From 4c7f8900f1d8a0e464e7092f132a7e93f7c20f2f Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 23 Feb 2008 07:06:55 +0100 Subject: [PATCH 0001/4982] x86: stackprotector & PARAVIRT fix on paravirt enabled 64-bit kernels the paravirt ops do function calls themselves - which is bad with the stackprotector - for example pda_init() loads 0 into %gs and then does MSR_GS_BASE write (which modifies gs.base) - but that MSR write is a function call on paravirt, which with stackprotector tries to read the stack canary from the PDA ... crashing the bootup. the solution was suggested by Arjan van de Ven: to exclude paravirt.c from stackprotector, too many lowlevel functionality is in it. It's not like we'll have paravirt functions with character arrays on their stack anyway... Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 5e618c3b472..8161e5a91ca 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -14,6 +14,7 @@ nostackp := $(call cc-option, -fno-stack-protector) CFLAGS_vsyscall_64.o := $(PROFILING) -g0 $(nostackp) CFLAGS_hpet.o := $(nostackp) CFLAGS_tsc_64.o := $(nostackp) +CFLAGS_paravirt.o := $(nostackp) obj-y := process_$(BITS).o signal_$(BITS).o entry_$(BITS).o obj-y += traps_$(BITS).o irq_$(BITS).o -- GitLab From e00320875d0cc5f8099a7227b2f25fbb3231268d Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 14 Feb 2008 08:48:23 +0100 Subject: [PATCH 0002/4982] x86: fix stackprotector canary updates during context switches fix a bug noticed and fixed by pageexec@freemail.hu. if built with -fstack-protector-all then we'll have canary checks built into the __switch_to() function. That does not work well with the canary-switching code there: while we already use the %rsp of the new task, we still call __switch_to() whith the previous task's canary value in the PDA, hence the __switch_to() ssp prologue instructions will store the previous canary. Then we update the PDA and upon return from __switch_to() the canary check triggers and we panic. so update the canary after we have called __switch_to(), where we are at the same stackframe level as the last stackframe of the next (and now freshly current) task. Note: this means that we call __switch_to() [and its sub-functions] still with the old canary, but that is not a problem, both the previous and the next task has a high-quality canary. The only (mostly academic) disadvantage is that the canary of one task may leak onto the stack of another task, increasing the risk of information leaks, were an attacker able to read the stack of specific tasks (but not that of others). To solve this we'll have to reorganize the way we switch tasks, and move the PDA setting into the switch_to() assembly code. That will happen in another patch. Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/process_64.c | 1 - include/asm-x86/pda.h | 2 -- include/asm-x86/system.h | 6 +++++- include/linux/sched.h | 3 +-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index e2319f39988..d8640388039 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -640,7 +640,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) write_pda(kernelstack, (unsigned long)task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET); #ifdef CONFIG_CC_STACKPROTECTOR - write_pda(stack_canary, next_p->stack_canary); /* * Build time only check to make sure the stack_canary is at * offset 40 in the pda; this is a gcc ABI requirement diff --git a/include/asm-x86/pda.h b/include/asm-x86/pda.h index 101fb9e1195..62b734986a4 100644 --- a/include/asm-x86/pda.h +++ b/include/asm-x86/pda.h @@ -16,11 +16,9 @@ struct x8664_pda { unsigned long oldrsp; /* 24 user rsp for system call */ int irqcount; /* 32 Irq nesting counter. Starts -1 */ unsigned int cpunumber; /* 36 Logical CPU number */ -#ifdef CONFIG_CC_STACKPROTECTOR unsigned long stack_canary; /* 40 stack canary value */ /* gcc-ABI: this canary MUST be at offset 40!!! */ -#endif char *irqstackptr; unsigned int __softirq_pending; unsigned int __nmi_count; /* number of NMI on this CPUs */ diff --git a/include/asm-x86/system.h b/include/asm-x86/system.h index a2f04cd79b2..172f5418509 100644 --- a/include/asm-x86/system.h +++ b/include/asm-x86/system.h @@ -92,6 +92,8 @@ do { \ ".globl thread_return\n" \ "thread_return:\n\t" \ "movq %%gs:%P[pda_pcurrent],%%rsi\n\t" \ + "movq %P[task_canary](%%rsi),%%r8\n\t" \ + "movq %%r8,%%gs:%P[pda_canary]\n\t" \ "movq %P[thread_info](%%rsi),%%r8\n\t" \ LOCK_PREFIX "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" \ "movq %%rax,%%rdi\n\t" \ @@ -103,7 +105,9 @@ do { \ [ti_flags] "i" (offsetof(struct thread_info, flags)), \ [tif_fork] "i" (TIF_FORK), \ [thread_info] "i" (offsetof(struct task_struct, stack)), \ - [pda_pcurrent] "i" (offsetof(struct x8664_pda, pcurrent)) \ + [task_canary] "i" (offsetof(struct task_struct, stack_canary)),\ + [pda_pcurrent] "i" (offsetof(struct x8664_pda, pcurrent)), \ + [pda_canary] "i" (offsetof(struct x8664_pda, stack_canary))\ : "memory", "cc" __EXTRA_CLOBBER) #endif diff --git a/include/linux/sched.h b/include/linux/sched.h index 5395a6176f4..d6a51515878 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1096,10 +1096,9 @@ struct task_struct { pid_t pid; pid_t tgid; -#ifdef CONFIG_CC_STACKPROTECTOR /* Canary value for the -fstack-protector gcc feature */ unsigned long stack_canary; -#endif + /* * pointers to (original) parent process, youngest child, younger sibling, * older sibling, respectively. (p->father can be replaced with -- GitLab From ce22bd92cba0958e052cb1ce0f89f1d3a02b60a7 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Mon, 12 May 2008 15:44:31 +0200 Subject: [PATCH 0003/4982] x86: setup stack canary for the idle threads The idle threads for non-boot CPUs are a bit special in how they are created; the result is that these don't have the stack canary set up properly in their PDA. Easiest fix is to just always set the PDA up correctly when entering the idle thread; this is a NOP for the boot cpu. Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/process_64.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index d8640388039..9e69e223023 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -146,6 +146,15 @@ static inline void play_dead(void) void cpu_idle(void) { current_thread_info()->status |= TS_POLLING; + +#ifdef CONFIG_CC_STACKPROTECTOR + /* + * If we're the non-boot CPU, nothing set the PDA stack + * canary up for us. This is as good a place as any for + * doing that. + */ + write_pda(stack_canary, current->stack_canary); +#endif /* endless idle loop with no priority at all */ while (1) { tick_nohz_stop_sched_tick(); -- GitLab From 7e09b2a02dae4616a5a26000169964b32f86cd35 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 14 Feb 2008 09:22:34 +0100 Subject: [PATCH 0004/4982] x86: fix canary of the boot CPU's idle task the boot CPU's idle task has a zero stackprotector canary value. this is a special task that is never forked, so the fork code does not randomize its canary. Do it when we hit cpu_idle(). Academic sidenote: this means that the early init code runs with a zero canary and hence the canary becomes predictable for this short, boot-only amount of time. Although attack vectors against early init code are very rare, it might make sense to move this initialization to an earlier point. (to one of the early init functions that never return - such as start_kernel()) Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/process_64.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 9e69e223023..d4c7ac7aa43 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -150,9 +150,13 @@ void cpu_idle(void) #ifdef CONFIG_CC_STACKPROTECTOR /* * If we're the non-boot CPU, nothing set the PDA stack - * canary up for us. This is as good a place as any for - * doing that. + * canary up for us - and if we are the boot CPU we have + * a 0 stack canary. This is a good place for updating + * it, as we wont ever return from this function (so the + * invalid canaries already on the stack wont ever + * trigger): */ + current->stack_canary = get_random_int(); write_pda(stack_canary, current->stack_canary); #endif /* endless idle loop with no priority at all */ -- GitLab From 517a92c4e19fcea815332d3155e9fb7723251274 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 14 Feb 2008 09:02:13 +0100 Subject: [PATCH 0005/4982] panic: print more informative messages on stackprotect failure pointed out by pageexec@freemail.hu: we just simply panic() when there's a stackprotector attack - giving the attacked person no information about what kernel code the attack went against. print out the attacked function. Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- kernel/panic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/panic.c b/kernel/panic.c index 425567f45b9..f236001cc4d 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -327,7 +327,8 @@ EXPORT_SYMBOL(warn_on_slowpath); */ void __stack_chk_fail(void) { - panic("stack-protector: Kernel stack is corrupted"); + panic("stack-protector: Kernel stack is corrupted in: %p\n", + __builtin_return_address(0)); } EXPORT_SYMBOL(__stack_chk_fail); #endif -- GitLab From 5cb273013e182a35e7db614d3e20a144cba71e53 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 14 Feb 2008 09:07:01 +0100 Subject: [PATCH 0006/4982] panic: print out stacktrace if DEBUG_BUGVERBOSE if CONFIG_DEBUG_BUGVERBOSE is set then the user most definitely wanted to see as much information about kernel crashes as possible - so give them at least a stack dump. this is particularly useful for stackprotector related panics, where the stacktrace can give us the exact location of the (attempted) attack. Pointed out by pageexec@freemail.hu in the stackprotector breakage threads. Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- kernel/panic.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/panic.c b/kernel/panic.c index f236001cc4d..17aad578a2f 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -80,6 +80,9 @@ NORET_TYPE void panic(const char * fmt, ...) vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); printk(KERN_EMERG "Kernel panic - not syncing: %s\n",buf); +#ifdef CONFIG_DEBUG_BUGVERBOSE + dump_stack(); +#endif bust_spinlocks(0); /* -- GitLab From 72370f2a5b227bd3817593a6b15ea3f53f51dfcb Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 13 Feb 2008 16:15:34 +0100 Subject: [PATCH 0007/4982] x86: if stackprotector is enabled, thn use stack-protector-all by default also enable the rodata and nx tests. Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/Kconfig | 3 ++- arch/x86/Kconfig.debug | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index dcbec34154c..83d8392c133 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1142,7 +1142,7 @@ config SECCOMP config CC_STACKPROTECTOR bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" - depends on X86_64 && EXPERIMENTAL && BROKEN + depends on X86_64 help This option turns on the -fstack-protector GCC feature. This feature puts, at the beginning of critical functions, a canary @@ -1159,6 +1159,7 @@ config CC_STACKPROTECTOR config CC_STACKPROTECTOR_ALL bool "Use stack-protector for all functions" depends on CC_STACKPROTECTOR + default y help Normally, GCC only inserts the canary value protection for functions that use large-ish on-stack buffers. By enabling diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index ac1e31ba479..b5c5b55d043 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -102,6 +102,7 @@ config DIRECT_GBPAGES config DEBUG_RODATA_TEST bool "Testcase for the DEBUG_RODATA feature" depends on DEBUG_RODATA + default y help This option enables a testcase for the DEBUG_RODATA feature as well as for the change_page_attr() infrastructure. -- GitLab From 9b5609fd773e6ac0b1d6d6e1bf68f32cca64e06b Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 14 Feb 2008 09:41:09 +0100 Subject: [PATCH 0008/4982] stackprotector: include files create for core kernel files to include. Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- include/asm-x86/stackprotector.h | 4 ++++ include/linux/stackprotector.h | 8 ++++++++ init/main.c | 1 + 3 files changed, 13 insertions(+) create mode 100644 include/asm-x86/stackprotector.h create mode 100644 include/linux/stackprotector.h diff --git a/include/asm-x86/stackprotector.h b/include/asm-x86/stackprotector.h new file mode 100644 index 00000000000..dcac7a6bdba --- /dev/null +++ b/include/asm-x86/stackprotector.h @@ -0,0 +1,4 @@ +#ifndef _ASM_STACKPROTECTOR_H +#define _ASM_STACKPROTECTOR_H 1 + +#endif diff --git a/include/linux/stackprotector.h b/include/linux/stackprotector.h new file mode 100644 index 00000000000..d3e8bbe602f --- /dev/null +++ b/include/linux/stackprotector.h @@ -0,0 +1,8 @@ +#ifndef _LINUX_STACKPROTECTOR_H +#define _LINUX_STACKPROTECTOR_H 1 + +#ifdef CONFIG_CC_STACKPROTECTOR +# include +#endif + +#endif diff --git a/init/main.c b/init/main.c index f7fb20021d4..a84322ca64a 100644 --- a/init/main.c +++ b/init/main.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include -- GitLab From 18aa8bb12dcb10adc3d7c9d69714d53667c0ab7f Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 14 Feb 2008 09:42:02 +0100 Subject: [PATCH 0009/4982] stackprotector: add boot_init_stack_canary() add the boot_init_stack_canary() and make the secondary idle threads use it. Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/process_64.c | 6 ++---- include/asm-x86/stackprotector.h | 20 ++++++++++++++++++++ include/linux/stackprotector.h | 4 ++++ 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index d4c7ac7aa43..5107cb214c7 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -147,7 +147,6 @@ void cpu_idle(void) { current_thread_info()->status |= TS_POLLING; -#ifdef CONFIG_CC_STACKPROTECTOR /* * If we're the non-boot CPU, nothing set the PDA stack * canary up for us - and if we are the boot CPU we have @@ -156,9 +155,8 @@ void cpu_idle(void) * invalid canaries already on the stack wont ever * trigger): */ - current->stack_canary = get_random_int(); - write_pda(stack_canary, current->stack_canary); -#endif + boot_init_stack_canary(); + /* endless idle loop with no priority at all */ while (1) { tick_nohz_stop_sched_tick(); diff --git a/include/asm-x86/stackprotector.h b/include/asm-x86/stackprotector.h index dcac7a6bdba..0f91f7a2688 100644 --- a/include/asm-x86/stackprotector.h +++ b/include/asm-x86/stackprotector.h @@ -1,4 +1,24 @@ #ifndef _ASM_STACKPROTECTOR_H #define _ASM_STACKPROTECTOR_H 1 +/* + * Initialize the stackprotector canary value. + * + * NOTE: this must only be called from functions that never return, + * and it must always be inlined. + */ +static __always_inline void boot_init_stack_canary(void) +{ + /* + * If we're the non-boot CPU, nothing set the PDA stack + * canary up for us - and if we are the boot CPU we have + * a 0 stack canary. This is a good place for updating + * it, as we wont ever return from this function (so the + * invalid canaries already on the stack wont ever + * trigger): + */ + current->stack_canary = get_random_int(); + write_pda(stack_canary, current->stack_canary); +} + #endif diff --git a/include/linux/stackprotector.h b/include/linux/stackprotector.h index d3e8bbe602f..422e71aafd0 100644 --- a/include/linux/stackprotector.h +++ b/include/linux/stackprotector.h @@ -3,6 +3,10 @@ #ifdef CONFIG_CC_STACKPROTECTOR # include +#else +static inline void boot_init_stack_canary(void) +{ +} #endif #endif -- GitLab From 420594296838fdc9a674470d710cda7d1487f9f4 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 14 Feb 2008 09:44:08 +0100 Subject: [PATCH 0010/4982] x86: fix the stackprotector canary of the boot CPU Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/process_64.c | 1 + include/linux/stackprotector.h | 4 ++++ init/main.c | 6 ++++++ 3 files changed, 11 insertions(+) diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 5107cb214c7..cce47f7fbf2 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -16,6 +16,7 @@ #include +#include #include #include #include diff --git a/include/linux/stackprotector.h b/include/linux/stackprotector.h index 422e71aafd0..6f3e54c704c 100644 --- a/include/linux/stackprotector.h +++ b/include/linux/stackprotector.h @@ -1,6 +1,10 @@ #ifndef _LINUX_STACKPROTECTOR_H #define _LINUX_STACKPROTECTOR_H 1 +#include +#include +#include + #ifdef CONFIG_CC_STACKPROTECTOR # include #else diff --git a/init/main.c b/init/main.c index a84322ca64a..b44e4eb0f5e 100644 --- a/init/main.c +++ b/init/main.c @@ -546,6 +546,12 @@ asmlinkage void __init start_kernel(void) unwind_init(); lockdep_init(); debug_objects_early_init(); + + /* + * Set up the the initial canary ASAP: + */ + boot_init_stack_canary(); + cgroup_init_early(); local_irq_disable(); -- GitLab From 960a672bd9f1ec06e8f197cf81a50fd07ea02e7f Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 14 Feb 2008 09:56:04 +0100 Subject: [PATCH 0011/4982] x86: stackprotector: mix TSC to the boot canary mix the TSC to the boot canary. Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- include/asm-x86/stackprotector.h | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/include/asm-x86/stackprotector.h b/include/asm-x86/stackprotector.h index 0f91f7a2688..3baf7ad89be 100644 --- a/include/asm-x86/stackprotector.h +++ b/include/asm-x86/stackprotector.h @@ -1,6 +1,8 @@ #ifndef _ASM_STACKPROTECTOR_H #define _ASM_STACKPROTECTOR_H 1 +#include + /* * Initialize the stackprotector canary value. * @@ -9,16 +11,28 @@ */ static __always_inline void boot_init_stack_canary(void) { + u64 canary; + u64 tsc; + /* * If we're the non-boot CPU, nothing set the PDA stack * canary up for us - and if we are the boot CPU we have * a 0 stack canary. This is a good place for updating * it, as we wont ever return from this function (so the * invalid canaries already on the stack wont ever - * trigger): + * trigger). + * + * We both use the random pool and the current TSC as a source + * of randomness. The TSC only matters for very early init, + * there it already has some randomness on most systems. Later + * on during the bootup the random pool has true entropy too. */ - current->stack_canary = get_random_int(); - write_pda(stack_canary, current->stack_canary); + get_random_bytes(&canary, sizeof(canary)); + tsc = __native_read_tsc(); + canary += tsc + (tsc << 32UL); + + current->stack_canary = canary; + write_pda(stack_canary, canary); } #endif -- GitLab From 113c5413cf9051cc50b88befdc42e3402bb92115 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 14 Feb 2008 10:36:03 +0100 Subject: [PATCH 0012/4982] x86: unify stackprotector features streamline the stackprotector features under a single option and make the stronger feature the one accessible. Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/Kconfig | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 83d8392c133..0cd1695c24f 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1140,13 +1140,17 @@ config SECCOMP If unsure, say Y. Only embedded should say N here. +config CC_STACKPROTECTOR_ALL + bool + config CC_STACKPROTECTOR bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" depends on X86_64 + select CC_STACKPROTECTOR_ALL help - This option turns on the -fstack-protector GCC feature. This - feature puts, at the beginning of critical functions, a canary - value on the stack just before the return address, and validates + This option turns on the -fstack-protector GCC feature. This + feature puts, at the beginning of functions, a canary value on + the stack just before the return address, and validates the value just before actually returning. Stack based buffer overflows (that need to overwrite this return address) now also overwrite the canary, which gets detected and the attack is then @@ -1154,16 +1158,8 @@ config CC_STACKPROTECTOR This feature requires gcc version 4.2 or above, or a distribution gcc with the feature backported. Older versions are automatically - detected and for those versions, this configuration option is ignored. - -config CC_STACKPROTECTOR_ALL - bool "Use stack-protector for all functions" - depends on CC_STACKPROTECTOR - default y - help - Normally, GCC only inserts the canary value protection for - functions that use large-ish on-stack buffers. By enabling - this option, GCC will be asked to do this for ALL functions. + detected and for those versions, this configuration option is + ignored. (and a warning is printed during bootup) source kernel/Kconfig.hz -- GitLab From 54371a43a66f4477889769b4fa00df936855dc8f Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Fri, 15 Feb 2008 15:33:12 -0800 Subject: [PATCH 0013/4982] x86: add CONFIG_CC_STACKPROTECTOR self-test This patch adds a simple self-test capability to the stackprotector feature. The test deliberately overflows a stack buffer and then checks if the canary trap function gets called. Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- kernel/panic.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/kernel/panic.c b/kernel/panic.c index 17aad578a2f..50cf9257b23 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -324,14 +324,82 @@ EXPORT_SYMBOL(warn_on_slowpath); #endif #ifdef CONFIG_CC_STACKPROTECTOR + +static unsigned long __stack_check_testing; +/* + * Self test function for the stack-protector feature. + * This test requires that the local variable absolutely has + * a stack slot, hence the barrier()s. + */ +static noinline void __stack_chk_test_func(void) +{ + unsigned long foo; + barrier(); + /* + * we need to make sure we're not about to clobber the return address, + * while real exploits do this, it's unhealthy on a running system. + * Besides, if we would, the test is already failed anyway so + * time to pull the emergency brake on it. + */ + if ((unsigned long)__builtin_return_address(0) == + *(((unsigned long *)&foo)+1)) { + printk(KERN_ERR "No -fstack-protector-stack-frame!\n"); + return; + } +#ifdef CONFIG_FRAME_POINTER + /* We also don't want to clobber the frame pointer */ + if ((unsigned long)__builtin_return_address(0) == + *(((unsigned long *)&foo)+2)) { + printk(KERN_ERR "No -fstack-protector-stack-frame!\n"); + return; + } +#endif + barrier(); + if (current->stack_canary == *(((unsigned long *)&foo)+1)) + *(((unsigned long *)&foo)+1) = 0; + else + printk(KERN_ERR "No -fstack-protector canary found\n"); + barrier(); +} + +static int __stack_chk_test(void) +{ + printk(KERN_INFO "Testing -fstack-protector-all feature\n"); + __stack_check_testing = (unsigned long)&__stack_chk_test_func; + __stack_chk_test_func(); + if (__stack_check_testing) { + printk(KERN_ERR "-fstack-protector-all test failed\n"); + WARN_ON(1); + } + return 0; +} /* * Called when gcc's -fstack-protector feature is used, and * gcc detects corruption of the on-stack canary value */ void __stack_chk_fail(void) { + if (__stack_check_testing == (unsigned long)&__stack_chk_test_func) { + long delta; + + delta = (unsigned long)__builtin_return_address(0) - + __stack_check_testing; + /* + * The test needs to happen inside the test function, so + * check if the return address is close to that function. + * The function is only 2 dozen bytes long, but keep a wide + * safety margin to avoid panic()s for normal users regardless + * of the quality of the compiler. + */ + if (delta >= 0 && delta <= 400) { + __stack_check_testing = 0; + return; + } + } panic("stack-protector: Kernel stack is corrupted in: %p\n", __builtin_return_address(0)); } EXPORT_SYMBOL(__stack_chk_fail); + +late_initcall(__stack_chk_test); #endif -- GitLab From b719ac56c0032bc1602914c6ea70b0f1581b08c7 Mon Sep 17 00:00:00 2001 From: Daniel Walker Date: Mon, 14 Apr 2008 10:03:50 -0700 Subject: [PATCH 0014/4982] panic.c: fix whitespace additions trivial: remove white space addition in stack protector Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- kernel/panic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/panic.c b/kernel/panic.c index 50cf9257b23..866be9b72e4 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -341,14 +341,14 @@ static noinline void __stack_chk_test_func(void) * Besides, if we would, the test is already failed anyway so * time to pull the emergency brake on it. */ - if ((unsigned long)__builtin_return_address(0) == + if ((unsigned long)__builtin_return_address(0) == *(((unsigned long *)&foo)+1)) { printk(KERN_ERR "No -fstack-protector-stack-frame!\n"); return; } #ifdef CONFIG_FRAME_POINTER /* We also don't want to clobber the frame pointer */ - if ((unsigned long)__builtin_return_address(0) == + if ((unsigned long)__builtin_return_address(0) == *(((unsigned long *)&foo)+2)) { printk(KERN_ERR "No -fstack-protector-stack-frame!\n"); return; -- GitLab From b40a4392a3c262e0d1b5379b4e142a8eefa63439 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Fri, 18 Apr 2008 06:16:45 -0700 Subject: [PATCH 0015/4982] stackprotector: turn not having the right gcc into a #warning If the user selects the stack-protector config option, but does not have a gcc that has the right bits enabled (for example because it isn't build with a glibc that supports TLS, as is common for cross-compilers, but also because it may be too old), then the runtime test fails right now. This patch adds a warning message for this scenario. This warning accomplishes two goals 1) the user is informed that the security option he selective isn't available 2) the user is suggested to turn of the CONFIG option that won't work for him, and would make the runtime test fail anyway. Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/Makefile | 2 +- kernel/panic.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 3cff3c894cf..c3e0eeeb1dd 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -73,7 +73,7 @@ else stackp := $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh stackp-$(CONFIG_CC_STACKPROTECTOR) := $(shell $(stackp) \ - "$(CC)" -fstack-protector ) + "$(CC)" "-fstack-protector -DGCC_HAS_SP" ) stackp-$(CONFIG_CC_STACKPROTECTOR_ALL) += $(shell $(stackp) \ "$(CC)" -fstack-protector-all ) diff --git a/kernel/panic.c b/kernel/panic.c index 866be9b72e4..6729e3f4ebc 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -325,6 +325,9 @@ EXPORT_SYMBOL(warn_on_slowpath); #ifdef CONFIG_CC_STACKPROTECTOR +#ifndef GCC_HAS_SP +#warning You have selected the CONFIG_CC_STACKPROTECTOR option, but the gcc used does not support this. +#endif static unsigned long __stack_check_testing; /* * Self test function for the stack-protector feature. -- GitLab From 7c9f8861e6c9c839f913e49b98c3854daca18f27 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Tue, 22 Apr 2008 16:38:23 -0500 Subject: [PATCH 0016/4982] stackprotector: use canary at end of stack to indicate overruns at oops time (Updated with a common max-stack-used checker that knows about the canary, as suggested by Joe Perches) Use a canary at the end of the stack to clearly indicate at oops time whether the stack has ever overflowed. This is a very simple implementation with a couple of drawbacks: 1) a thread may legitimately use exactly up to the last word on the stack -- but the chances of doing this and then oopsing later seem slim 2) it's possible that the stack usage isn't dense enough that the canary location could get skipped over -- but the worst that happens is that we don't flag the overrun -- though this happens fairly often in my testing :( With the code in place, an intentionally-bloated stack oops might do: BUG: unable to handle kernel paging request at ffff8103f84cc680 IP: [] update_curr+0x9a/0xa8 PGD 8063 PUD 0 Thread overran stack or stack corrupted Oops: 0000 [1] SMP CPU 0 ... ... unless the stack overrun is so bad that it corrupts some other thread. Signed-off-by: Eric Sandeen Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/mm/fault.c | 7 +++++++ include/linux/magic.h | 1 + include/linux/sched.h | 13 +++++++++++++ kernel/exit.c | 5 +---- kernel/fork.c | 5 +++++ kernel/sched.c | 7 +------ 6 files changed, 28 insertions(+), 10 deletions(-) diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index fd7e1798c75..1f524df68b9 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -581,6 +582,8 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) unsigned long address; int write, si_code; int fault; + unsigned long *stackend; + #ifdef CONFIG_X86_64 unsigned long flags; #endif @@ -850,6 +853,10 @@ no_context: show_fault_oops(regs, error_code, address); + stackend = end_of_stack(tsk); + if (*stackend != STACK_END_MAGIC) + printk(KERN_ALERT "Thread overran stack, or stack corrupted\n"); + tsk->thread.cr2 = address; tsk->thread.trap_no = 14; tsk->thread.error_code = error_code; diff --git a/include/linux/magic.h b/include/linux/magic.h index 1fa0c2ce4de..74e68e20116 100644 --- a/include/linux/magic.h +++ b/include/linux/magic.h @@ -42,4 +42,5 @@ #define FUTEXFS_SUPER_MAGIC 0xBAD1DEA #define INOTIFYFS_SUPER_MAGIC 0x2BAD1DEA +#define STACK_END_MAGIC 0x57AC6E9D #endif /* __LINUX_MAGIC_H__ */ diff --git a/include/linux/sched.h b/include/linux/sched.h index d6a51515878..c5181e77f30 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1969,6 +1969,19 @@ static inline unsigned long *end_of_stack(struct task_struct *p) extern void thread_info_cache_init(void); +#ifdef CONFIG_DEBUG_STACK_USAGE +static inline unsigned long stack_not_used(struct task_struct *p) +{ + unsigned long *n = end_of_stack(p); + + do { /* Skip over canary */ + n++; + } while (!*n); + + return (unsigned long)n - (unsigned long)end_of_stack(p); +} +#endif + /* set thread flags in other task's structures * - see asm/thread_info.h for TIF_xxxx flags available */ diff --git a/kernel/exit.c b/kernel/exit.c index 8f6185e69b6..fb8de6cbf2c 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -899,12 +899,9 @@ static void check_stack_usage(void) { static DEFINE_SPINLOCK(low_water_lock); static int lowest_to_date = THREAD_SIZE; - unsigned long *n = end_of_stack(current); unsigned long free; - while (*n == 0) - n++; - free = (unsigned long)n - (unsigned long)end_of_stack(current); + free = stack_not_used(current); if (free >= lowest_to_date) return; diff --git a/kernel/fork.c b/kernel/fork.c index 19908b26cf8..d428336e7aa 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -54,6 +54,7 @@ #include #include #include +#include #include #include @@ -186,6 +187,8 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) { struct task_struct *tsk; struct thread_info *ti; + unsigned long *stackend; + int err; prepare_to_copy(orig); @@ -211,6 +214,8 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) goto out; setup_thread_stack(tsk, orig); + stackend = end_of_stack(tsk); + *stackend = STACK_END_MAGIC; /* for overflow detection */ #ifdef CONFIG_CC_STACKPROTECTOR tsk->stack_canary = get_random_int(); diff --git a/kernel/sched.c b/kernel/sched.c index cfa222a9153..a964ed94509 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -5748,12 +5748,7 @@ void sched_show_task(struct task_struct *p) printk(KERN_CONT " %016lx ", thread_saved_pc(p)); #endif #ifdef CONFIG_DEBUG_STACK_USAGE - { - unsigned long *n = end_of_stack(p); - while (!*n) - n++; - free = (unsigned long)n - (unsigned long)end_of_stack(p); - } + free = stack_not_used(p); #endif printk(KERN_CONT "%5lu %5d %6d\n", free, task_pid_nr(p), task_pid_nr(p->real_parent)); -- GitLab From aa92db14270b79f0f91a9060b547a46f9e2639da Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Fri, 11 Jul 2008 05:09:55 -0700 Subject: [PATCH 0017/4982] stackprotector: better self-test check stackprotector functionality by manipulating the canary briefly during bootup. far more robust than trying to overflow the stack. (which is architecture dependent, etc.) Signed-off-by: Ingo Molnar --- kernel/panic.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/kernel/panic.c b/kernel/panic.c index 6729e3f4ebc..28153aec710 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -347,22 +347,18 @@ static noinline void __stack_chk_test_func(void) if ((unsigned long)__builtin_return_address(0) == *(((unsigned long *)&foo)+1)) { printk(KERN_ERR "No -fstack-protector-stack-frame!\n"); - return; } #ifdef CONFIG_FRAME_POINTER /* We also don't want to clobber the frame pointer */ if ((unsigned long)__builtin_return_address(0) == *(((unsigned long *)&foo)+2)) { printk(KERN_ERR "No -fstack-protector-stack-frame!\n"); - return; } #endif - barrier(); - if (current->stack_canary == *(((unsigned long *)&foo)+1)) - *(((unsigned long *)&foo)+1) = 0; - else + if (current->stack_canary != *(((unsigned long *)&foo)+1)) printk(KERN_ERR "No -fstack-protector canary found\n"); - barrier(); + + current->stack_canary = ~current->stack_canary; } static int __stack_chk_test(void) @@ -373,7 +369,8 @@ static int __stack_chk_test(void) if (__stack_check_testing) { printk(KERN_ERR "-fstack-protector-all test failed\n"); WARN_ON(1); - } + }; + current->stack_canary = ~current->stack_canary; return 0; } /* -- GitLab From af9ff7868f0f76d3364351b1641b9dfa99588e77 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sat, 12 Jul 2008 09:36:38 -0700 Subject: [PATCH 0018/4982] x86: simplify stackprotector self-check Clean up the code by removing no longer needed code; make sure the pda is updated and kept in sync Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar --- include/asm-x86/pda.h | 1 + kernel/panic.c | 29 +++++++---------------------- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/include/asm-x86/pda.h b/include/asm-x86/pda.h index 62b734986a4..a5ff5bb7629 100644 --- a/include/asm-x86/pda.h +++ b/include/asm-x86/pda.h @@ -131,4 +131,5 @@ do { \ #define PDA_STACKOFFSET (5*8) +#define refresh_stack_canary() write_pda(stack_canary, current->stack_canary) #endif diff --git a/kernel/panic.c b/kernel/panic.c index 28153aec710..87445a894c3 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -328,37 +328,21 @@ EXPORT_SYMBOL(warn_on_slowpath); #ifndef GCC_HAS_SP #warning You have selected the CONFIG_CC_STACKPROTECTOR option, but the gcc used does not support this. #endif + static unsigned long __stack_check_testing; + /* * Self test function for the stack-protector feature. * This test requires that the local variable absolutely has - * a stack slot, hence the barrier()s. + * a stack slot. */ static noinline void __stack_chk_test_func(void) { - unsigned long foo; - barrier(); - /* - * we need to make sure we're not about to clobber the return address, - * while real exploits do this, it's unhealthy on a running system. - * Besides, if we would, the test is already failed anyway so - * time to pull the emergency brake on it. - */ - if ((unsigned long)__builtin_return_address(0) == - *(((unsigned long *)&foo)+1)) { - printk(KERN_ERR "No -fstack-protector-stack-frame!\n"); - } -#ifdef CONFIG_FRAME_POINTER - /* We also don't want to clobber the frame pointer */ - if ((unsigned long)__builtin_return_address(0) == - *(((unsigned long *)&foo)+2)) { - printk(KERN_ERR "No -fstack-protector-stack-frame!\n"); - } -#endif - if (current->stack_canary != *(((unsigned long *)&foo)+1)) - printk(KERN_ERR "No -fstack-protector canary found\n"); + unsigned long dummy_buffer[64]; /* force gcc to use the canary */ current->stack_canary = ~current->stack_canary; + refresh_stack_canary(); + dummy_buffer[3] = 1; /* fool gcc into keeping the variable */ } static int __stack_chk_test(void) @@ -371,6 +355,7 @@ static int __stack_chk_test(void) WARN_ON(1); }; current->stack_canary = ~current->stack_canary; + refresh_stack_canary(); return 0; } /* -- GitLab From 4f962d4d65923d7b722192e729840cfb79af0a5a Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 13 Jul 2008 21:42:44 +0200 Subject: [PATCH 0019/4982] stackprotector: remove self-test turns out gcc generates such stackprotector-failure sequences in certain circumstances: movq -8(%rbp), %rax # D.16032, xorq %gs:40, %rax #, jne .L17 #, leave ret .L17: call __stack_chk_fail # .size __stack_chk_test_func, .-__stack_chk_test_func .section .init.text,"ax",@progbits .type panic_setup, @function panic_setup: pushq %rbp # note that there's no jump back to the failing context after the call to __stack_chk_fail - i.e. it has a ((noreturn)) attribute. Which is fair enough in the normal case but kills the self-test. (as we cannot reliably return in the self-test) Signed-off-by: Ingo Molnar --- kernel/panic.c | 47 ----------------------------------------------- 1 file changed, 47 deletions(-) diff --git a/kernel/panic.c b/kernel/panic.c index 87445a894c3..c35c9eca3eb 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -329,62 +329,15 @@ EXPORT_SYMBOL(warn_on_slowpath); #warning You have selected the CONFIG_CC_STACKPROTECTOR option, but the gcc used does not support this. #endif -static unsigned long __stack_check_testing; - -/* - * Self test function for the stack-protector feature. - * This test requires that the local variable absolutely has - * a stack slot. - */ -static noinline void __stack_chk_test_func(void) -{ - unsigned long dummy_buffer[64]; /* force gcc to use the canary */ - - current->stack_canary = ~current->stack_canary; - refresh_stack_canary(); - dummy_buffer[3] = 1; /* fool gcc into keeping the variable */ -} - -static int __stack_chk_test(void) -{ - printk(KERN_INFO "Testing -fstack-protector-all feature\n"); - __stack_check_testing = (unsigned long)&__stack_chk_test_func; - __stack_chk_test_func(); - if (__stack_check_testing) { - printk(KERN_ERR "-fstack-protector-all test failed\n"); - WARN_ON(1); - }; - current->stack_canary = ~current->stack_canary; - refresh_stack_canary(); - return 0; -} /* * Called when gcc's -fstack-protector feature is used, and * gcc detects corruption of the on-stack canary value */ void __stack_chk_fail(void) { - if (__stack_check_testing == (unsigned long)&__stack_chk_test_func) { - long delta; - - delta = (unsigned long)__builtin_return_address(0) - - __stack_check_testing; - /* - * The test needs to happen inside the test function, so - * check if the return address is close to that function. - * The function is only 2 dozen bytes long, but keep a wide - * safety margin to avoid panic()s for normal users regardless - * of the quality of the compiler. - */ - if (delta >= 0 && delta <= 400) { - __stack_check_testing = 0; - return; - } - } panic("stack-protector: Kernel stack is corrupted in: %p\n", __builtin_return_address(0)); } EXPORT_SYMBOL(__stack_chk_fail); -late_initcall(__stack_chk_test); #endif -- GitLab From 1df8130278c4543555fea697e5714fbac300b899 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 8 Dec 2008 15:58:50 +0000 Subject: [PATCH 0020/4982] [ARM] dma: remove dmach_t typedef Remove a pointless integer typedef. Signed-off-by: Russell King --- arch/arm/include/asm/dma.h | 32 ++++++------ arch/arm/include/asm/mach/dma.h | 12 ++--- arch/arm/kernel/dma-isa.c | 42 ++++++++-------- arch/arm/kernel/dma.c | 86 ++++++++++++++++----------------- arch/arm/mach-footbridge/dma.c | 6 +-- arch/arm/mach-rpc/dma.c | 20 ++++---- 6 files changed, 98 insertions(+), 100 deletions(-) diff --git a/arch/arm/include/asm/dma.h b/arch/arm/include/asm/dma.h index df5638f3643..c5557a650d1 100644 --- a/arch/arm/include/asm/dma.h +++ b/arch/arm/include/asm/dma.h @@ -19,8 +19,6 @@ #include #include -typedef unsigned int dmach_t; - #include /* @@ -52,44 +50,44 @@ static inline void release_dma_lock(unsigned long flags) /* Clear the 'DMA Pointer Flip Flop'. * Write 0 for LSB/MSB, 1 for MSB/LSB access. */ -#define clear_dma_ff(channel) +#define clear_dma_ff(chan) /* Set only the page register bits of the transfer address. * * NOTE: This is an architecture specific function, and should * be hidden from the drivers */ -extern void set_dma_page(dmach_t channel, char pagenr); +extern void set_dma_page(unsigned int chan, char pagenr); /* Request a DMA channel * * Some architectures may need to do allocate an interrupt */ -extern int request_dma(dmach_t channel, const char * device_id); +extern int request_dma(unsigned int chan, const char * device_id); /* Free a DMA channel * * Some architectures may need to do free an interrupt */ -extern void free_dma(dmach_t channel); +extern void free_dma(unsigned int chan); /* Enable DMA for this channel * * On some architectures, this may have other side effects like * enabling an interrupt and setting the DMA registers. */ -extern void enable_dma(dmach_t channel); +extern void enable_dma(unsigned int chan); /* Disable DMA for this channel * * On some architectures, this may have other side effects like * disabling an interrupt or whatever. */ -extern void disable_dma(dmach_t channel); +extern void disable_dma(unsigned int chan); /* Test whether the specified channel has an active DMA transfer */ -extern int dma_channel_active(dmach_t channel); +extern int dma_channel_active(unsigned int chan); /* Set the DMA scatter gather list for this channel * @@ -97,7 +95,7 @@ extern int dma_channel_active(dmach_t channel); * especially since some DMA architectures don't update the * DMA address immediately, but defer it to the enable_dma(). */ -extern void set_dma_sg(dmach_t channel, struct scatterlist *sg, int nr_sg); +extern void set_dma_sg(unsigned int chan, struct scatterlist *sg, int nr_sg); /* Set the DMA address for this channel * @@ -105,9 +103,9 @@ extern void set_dma_sg(dmach_t channel, struct scatterlist *sg, int nr_sg); * especially since some DMA architectures don't update the * DMA address immediately, but defer it to the enable_dma(). */ -extern void __set_dma_addr(dmach_t channel, void *addr); -#define set_dma_addr(channel, addr) \ - __set_dma_addr(channel, bus_to_virt(addr)) +extern void __set_dma_addr(unsigned int chan, void *addr); +#define set_dma_addr(chan, addr) \ + __set_dma_addr(chan, bus_to_virt(addr)) /* Set the DMA byte count for this channel * @@ -115,7 +113,7 @@ extern void __set_dma_addr(dmach_t channel, void *addr); * especially since some DMA architectures don't update the * DMA count immediately, but defer it to the enable_dma(). */ -extern void set_dma_count(dmach_t channel, unsigned long count); +extern void set_dma_count(unsigned int chan, unsigned long count); /* Set the transfer direction for this channel * @@ -124,11 +122,11 @@ extern void set_dma_count(dmach_t channel, unsigned long count); * DMA transfer direction immediately, but defer it to the * enable_dma(). */ -extern void set_dma_mode(dmach_t channel, dmamode_t mode); +extern void set_dma_mode(unsigned int chan, dmamode_t mode); /* Set the transfer speed for this channel */ -extern void set_dma_speed(dmach_t channel, int cycle_ns); +extern void set_dma_speed(unsigned int chan, int cycle_ns); /* Get DMA residue count. After a DMA transfer, this * should return zero. Reading this while a DMA transfer is @@ -136,7 +134,7 @@ extern void set_dma_speed(dmach_t channel, int cycle_ns); * If called before the channel has been used, it may return 1. * Otherwise, it returns the number of _bytes_ left to transfer. */ -extern int get_dma_residue(dmach_t channel); +extern int get_dma_residue(unsigned int chan); #ifndef NO_DMA #define NO_DMA 255 diff --git a/arch/arm/include/asm/mach/dma.h b/arch/arm/include/asm/mach/dma.h index fc7278ea714..281ae7e40a9 100644 --- a/arch/arm/include/asm/mach/dma.h +++ b/arch/arm/include/asm/mach/dma.h @@ -15,12 +15,12 @@ struct dma_struct; typedef struct dma_struct dma_t; struct dma_ops { - int (*request)(dmach_t, dma_t *); /* optional */ - void (*free)(dmach_t, dma_t *); /* optional */ - void (*enable)(dmach_t, dma_t *); /* mandatory */ - void (*disable)(dmach_t, dma_t *); /* mandatory */ - int (*residue)(dmach_t, dma_t *); /* optional */ - int (*setspeed)(dmach_t, dma_t *, int); /* optional */ + int (*request)(unsigned int, dma_t *); /* optional */ + void (*free)(unsigned int, dma_t *); /* optional */ + void (*enable)(unsigned int, dma_t *); /* mandatory */ + void (*disable)(unsigned int, dma_t *); /* mandatory */ + int (*residue)(unsigned int, dma_t *); /* optional */ + int (*setspeed)(unsigned int, dma_t *, int); /* optional */ char *type; }; diff --git a/arch/arm/kernel/dma-isa.c b/arch/arm/kernel/dma-isa.c index 4a3a50495c6..29eca48925d 100644 --- a/arch/arm/kernel/dma-isa.c +++ b/arch/arm/kernel/dma-isa.c @@ -49,25 +49,25 @@ static unsigned int isa_dma_port[8][7] = { { 0xd4, 0xd6, 0xd8, 0x48a, 0x08a, 0xcc, 0xce } }; -static int isa_get_dma_residue(dmach_t channel, dma_t *dma) +static int isa_get_dma_residue(unsigned int chan, dma_t *dma) { - unsigned int io_port = isa_dma_port[channel][ISA_DMA_COUNT]; + unsigned int io_port = isa_dma_port[chan][ISA_DMA_COUNT]; int count; count = 1 + inb(io_port); count |= inb(io_port) << 8; - return channel < 4 ? count : (count << 1); + return chan < 4 ? count : (count << 1); } -static void isa_enable_dma(dmach_t channel, dma_t *dma) +static void isa_enable_dma(unsigned int chan, dma_t *dma) { if (dma->invalid) { unsigned long address, length; unsigned int mode; enum dma_data_direction direction; - mode = channel & 3; + mode = chan & 3; switch (dma->dma_mode & DMA_MODE_MASK) { case DMA_MODE_READ: mode |= ISA_DMA_MODE_READ; @@ -105,34 +105,34 @@ static void isa_enable_dma(dmach_t channel, dma_t *dma) address = dma->buf.dma_address; length = dma->buf.length - 1; - outb(address >> 16, isa_dma_port[channel][ISA_DMA_PGLO]); - outb(address >> 24, isa_dma_port[channel][ISA_DMA_PGHI]); + outb(address >> 16, isa_dma_port[chan][ISA_DMA_PGLO]); + outb(address >> 24, isa_dma_port[chan][ISA_DMA_PGHI]); - if (channel >= 4) { + if (chan >= 4) { address >>= 1; length >>= 1; } - outb(0, isa_dma_port[channel][ISA_DMA_CLRFF]); + outb(0, isa_dma_port[chan][ISA_DMA_CLRFF]); - outb(address, isa_dma_port[channel][ISA_DMA_ADDR]); - outb(address >> 8, isa_dma_port[channel][ISA_DMA_ADDR]); + outb(address, isa_dma_port[chan][ISA_DMA_ADDR]); + outb(address >> 8, isa_dma_port[chan][ISA_DMA_ADDR]); - outb(length, isa_dma_port[channel][ISA_DMA_COUNT]); - outb(length >> 8, isa_dma_port[channel][ISA_DMA_COUNT]); + outb(length, isa_dma_port[chan][ISA_DMA_COUNT]); + outb(length >> 8, isa_dma_port[chan][ISA_DMA_COUNT]); if (dma->dma_mode & DMA_AUTOINIT) mode |= ISA_DMA_AUTOINIT; - outb(mode, isa_dma_port[channel][ISA_DMA_MODE]); + outb(mode, isa_dma_port[chan][ISA_DMA_MODE]); dma->invalid = 0; } - outb(channel & 3, isa_dma_port[channel][ISA_DMA_MASK]); + outb(chan & 3, isa_dma_port[chan][ISA_DMA_MASK]); } -static void isa_disable_dma(dmach_t channel, dma_t *dma) +static void isa_disable_dma(unsigned int chan, dma_t *dma) { - outb(channel | 4, isa_dma_port[channel][ISA_DMA_MASK]); + outb(chan | 4, isa_dma_port[chan][ISA_DMA_MASK]); } static struct dma_ops isa_dma_ops = { @@ -178,11 +178,11 @@ void __init isa_init_dma(dma_t *dma) outb(0xaa, 0x00); if (inb(0) == 0x55 && inb(0) == 0xaa) { - int channel, i; + int chan, i; - for (channel = 0; channel < 8; channel++) { - dma[channel].d_ops = &isa_dma_ops; - isa_disable_dma(channel, NULL); + for (chan = 0; chan < 8; chan++) { + dma[chan].d_ops = &isa_dma_ops; + isa_disable_dma(chan, NULL); } outb(0x40, 0x0b); diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c index d006085ed7e..c31bf00e5ba 100644 --- a/arch/arm/kernel/dma.c +++ b/arch/arm/kernel/dma.c @@ -30,12 +30,12 @@ static dma_t dma_chan[MAX_DMA_CHANNELS]; * * On certain platforms, we have to allocate an interrupt as well... */ -int request_dma(dmach_t channel, const char *device_id) +int request_dma(unsigned int chan, const char *device_id) { - dma_t *dma = dma_chan + channel; + dma_t *dma = dma_chan + chan; int ret; - if (channel >= MAX_DMA_CHANNELS || !dma->d_ops) + if (chan >= MAX_DMA_CHANNELS || !dma->d_ops) goto bad_dma; if (xchg(&dma->lock, 1) != 0) @@ -47,7 +47,7 @@ int request_dma(dmach_t channel, const char *device_id) ret = 0; if (dma->d_ops->request) - ret = dma->d_ops->request(channel, dma); + ret = dma->d_ops->request(chan, dma); if (ret) xchg(&dma->lock, 0); @@ -55,7 +55,7 @@ int request_dma(dmach_t channel, const char *device_id) return ret; bad_dma: - printk(KERN_ERR "dma: trying to allocate DMA%d\n", channel); + printk(KERN_ERR "dma: trying to allocate DMA%d\n", chan); return -EINVAL; busy: @@ -68,42 +68,42 @@ EXPORT_SYMBOL(request_dma); * * On certain platforms, we have to free interrupt as well... */ -void free_dma(dmach_t channel) +void free_dma(unsigned int chan) { - dma_t *dma = dma_chan + channel; + dma_t *dma = dma_chan + chan; - if (channel >= MAX_DMA_CHANNELS || !dma->d_ops) + if (chan >= MAX_DMA_CHANNELS || !dma->d_ops) goto bad_dma; if (dma->active) { - printk(KERN_ERR "dma%d: freeing active DMA\n", channel); - dma->d_ops->disable(channel, dma); + printk(KERN_ERR "dma%d: freeing active DMA\n", chan); + dma->d_ops->disable(chan, dma); dma->active = 0; } if (xchg(&dma->lock, 0) != 0) { if (dma->d_ops->free) - dma->d_ops->free(channel, dma); + dma->d_ops->free(chan, dma); return; } - printk(KERN_ERR "dma%d: trying to free free DMA\n", channel); + printk(KERN_ERR "dma%d: trying to free free DMA\n", chan); return; bad_dma: - printk(KERN_ERR "dma: trying to free DMA%d\n", channel); + printk(KERN_ERR "dma: trying to free DMA%d\n", chan); } EXPORT_SYMBOL(free_dma); /* Set DMA Scatter-Gather list */ -void set_dma_sg (dmach_t channel, struct scatterlist *sg, int nr_sg) +void set_dma_sg (unsigned int chan, struct scatterlist *sg, int nr_sg) { - dma_t *dma = dma_chan + channel; + dma_t *dma = dma_chan + chan; if (dma->active) printk(KERN_ERR "dma%d: altering DMA SG while " - "DMA active\n", channel); + "DMA active\n", chan); dma->sg = sg; dma->sgcount = nr_sg; @@ -115,13 +115,13 @@ EXPORT_SYMBOL(set_dma_sg); * * Copy address to the structure, and set the invalid bit */ -void __set_dma_addr (dmach_t channel, void *addr) +void __set_dma_addr (unsigned int chan, void *addr) { - dma_t *dma = dma_chan + channel; + dma_t *dma = dma_chan + chan; if (dma->active) printk(KERN_ERR "dma%d: altering DMA address while " - "DMA active\n", channel); + "DMA active\n", chan); dma->sg = NULL; dma->addr = addr; @@ -133,13 +133,13 @@ EXPORT_SYMBOL(__set_dma_addr); * * Copy address to the structure, and set the invalid bit */ -void set_dma_count (dmach_t channel, unsigned long count) +void set_dma_count (unsigned int chan, unsigned long count) { - dma_t *dma = dma_chan + channel; + dma_t *dma = dma_chan + chan; if (dma->active) printk(KERN_ERR "dma%d: altering DMA count while " - "DMA active\n", channel); + "DMA active\n", chan); dma->sg = NULL; dma->count = count; @@ -149,13 +149,13 @@ EXPORT_SYMBOL(set_dma_count); /* Set DMA direction mode */ -void set_dma_mode (dmach_t channel, dmamode_t mode) +void set_dma_mode (unsigned int chan, dmamode_t mode) { - dma_t *dma = dma_chan + channel; + dma_t *dma = dma_chan + chan; if (dma->active) printk(KERN_ERR "dma%d: altering DMA mode while " - "DMA active\n", channel); + "DMA active\n", chan); dma->dma_mode = mode; dma->invalid = 1; @@ -164,42 +164,42 @@ EXPORT_SYMBOL(set_dma_mode); /* Enable DMA channel */ -void enable_dma (dmach_t channel) +void enable_dma (unsigned int chan) { - dma_t *dma = dma_chan + channel; + dma_t *dma = dma_chan + chan; if (!dma->lock) goto free_dma; if (dma->active == 0) { dma->active = 1; - dma->d_ops->enable(channel, dma); + dma->d_ops->enable(chan, dma); } return; free_dma: - printk(KERN_ERR "dma%d: trying to enable free DMA\n", channel); + printk(KERN_ERR "dma%d: trying to enable free DMA\n", chan); BUG(); } EXPORT_SYMBOL(enable_dma); /* Disable DMA channel */ -void disable_dma (dmach_t channel) +void disable_dma (unsigned int chan) { - dma_t *dma = dma_chan + channel; + dma_t *dma = dma_chan + chan; if (!dma->lock) goto free_dma; if (dma->active == 1) { dma->active = 0; - dma->d_ops->disable(channel, dma); + dma->d_ops->disable(chan, dma); } return; free_dma: - printk(KERN_ERR "dma%d: trying to disable free DMA\n", channel); + printk(KERN_ERR "dma%d: trying to disable free DMA\n", chan); BUG(); } EXPORT_SYMBOL(disable_dma); @@ -207,36 +207,36 @@ EXPORT_SYMBOL(disable_dma); /* * Is the specified DMA channel active? */ -int dma_channel_active(dmach_t channel) +int dma_channel_active(unsigned int chan) { - return dma_chan[channel].active; + return dma_chan[chan].active; } EXPORT_SYMBOL(dma_channel_active); -void set_dma_page(dmach_t channel, char pagenr) +void set_dma_page(unsigned int chan, char pagenr) { - printk(KERN_ERR "dma%d: trying to set_dma_page\n", channel); + printk(KERN_ERR "dma%d: trying to set_dma_page\n", chan); } EXPORT_SYMBOL(set_dma_page); -void set_dma_speed(dmach_t channel, int cycle_ns) +void set_dma_speed(unsigned int chan, int cycle_ns) { - dma_t *dma = dma_chan + channel; + dma_t *dma = dma_chan + chan; int ret = 0; if (dma->d_ops->setspeed) - ret = dma->d_ops->setspeed(channel, dma, cycle_ns); + ret = dma->d_ops->setspeed(chan, dma, cycle_ns); dma->speed = ret; } EXPORT_SYMBOL(set_dma_speed); -int get_dma_residue(dmach_t channel) +int get_dma_residue(unsigned int chan) { - dma_t *dma = dma_chan + channel; + dma_t *dma = dma_chan + chan; int ret = 0; if (dma->d_ops->residue) - ret = dma->d_ops->residue(channel, dma); + ret = dma->d_ops->residue(chan, dma); return ret; } diff --git a/arch/arm/mach-footbridge/dma.c b/arch/arm/mach-footbridge/dma.c index b653e9cfa3f..e7b8a6adaf7 100644 --- a/arch/arm/mach-footbridge/dma.c +++ b/arch/arm/mach-footbridge/dma.c @@ -20,16 +20,16 @@ #include #if 0 -static int fb_dma_request(dmach_t channel, dma_t *dma) +static int fb_dma_request(unsigned int chan, dma_t *dma) { return -EINVAL; } -static void fb_dma_enable(dmach_t channel, dma_t *dma) +static void fb_dma_enable(unsigned int chan, dma_t *dma) { } -static void fb_dma_disable(dmach_t channel, dma_t *dma) +static void fb_dma_disable(unsigned int chan, dma_t *dma) { } diff --git a/arch/arm/mach-rpc/dma.c b/arch/arm/mach-rpc/dma.c index 7958a30f893..a86d3ed859a 100644 --- a/arch/arm/mach-rpc/dma.c +++ b/arch/arm/mach-rpc/dma.c @@ -125,18 +125,18 @@ static irqreturn_t iomd_dma_handle(int irq, void *dev_id) return IRQ_HANDLED; } -static int iomd_request_dma(dmach_t channel, dma_t *dma) +static int iomd_request_dma(unsigned int chan, dma_t *dma) { return request_irq(dma->dma_irq, iomd_dma_handle, IRQF_DISABLED, dma->device_id, dma); } -static void iomd_free_dma(dmach_t channel, dma_t *dma) +static void iomd_free_dma(unsigned int chan, dma_t *dma) { free_irq(dma->dma_irq, dma); } -static void iomd_enable_dma(dmach_t channel, dma_t *dma) +static void iomd_enable_dma(unsigned int chan, dma_t *dma) { unsigned long dma_base = dma->dma_base; unsigned int ctrl = TRANSFER_SIZE | DMA_CR_E; @@ -169,7 +169,7 @@ static void iomd_enable_dma(dmach_t channel, dma_t *dma) enable_irq(dma->dma_irq); } -static void iomd_disable_dma(dmach_t channel, dma_t *dma) +static void iomd_disable_dma(unsigned int chan, dma_t *dma) { unsigned long dma_base = dma->dma_base; unsigned long flags; @@ -181,7 +181,7 @@ static void iomd_disable_dma(dmach_t channel, dma_t *dma) local_irq_restore(flags); } -static int iomd_set_dma_speed(dmach_t channel, dma_t *dma, int cycle) +static int iomd_set_dma_speed(unsigned int chan, dma_t *dma, int cycle) { int tcr, speed; @@ -197,7 +197,7 @@ static int iomd_set_dma_speed(dmach_t channel, dma_t *dma, int cycle) tcr = iomd_readb(IOMD_DMATCR); speed &= 3; - switch (channel) { + switch (chan) { case DMA_0: tcr = (tcr & ~0x03) | speed; break; @@ -236,7 +236,7 @@ static struct fiq_handler fh = { .name = "floppydma" }; -static void floppy_enable_dma(dmach_t channel, dma_t *dma) +static void floppy_enable_dma(unsigned int chan, dma_t *dma) { void *fiqhandler_start; unsigned int fiqhandler_length; @@ -269,13 +269,13 @@ static void floppy_enable_dma(dmach_t channel, dma_t *dma) enable_fiq(dma->dma_irq); } -static void floppy_disable_dma(dmach_t channel, dma_t *dma) +static void floppy_disable_dma(unsigned int chan, dma_t *dma) { disable_fiq(dma->dma_irq); release_fiq(&fh); } -static int floppy_get_residue(dmach_t channel, dma_t *dma) +static int floppy_get_residue(unsigned int chan, dma_t *dma) { struct pt_regs regs; get_fiq_regs(®s); @@ -292,7 +292,7 @@ static struct dma_ops floppy_dma_ops = { /* * This is virtual DMA - we don't need anything here. */ -static void sound_enable_disable_dma(dmach_t channel, dma_t *dma) +static void sound_enable_disable_dma(unsigned int chan, dma_t *dma) { } -- GitLab From 3afb6e9c635f735c751148beddc195daec0e35ec Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 8 Dec 2008 16:08:48 +0000 Subject: [PATCH 0021/4982] [ARM] dma: factor out code looking up the DMA channel This is a preparitory patch to allow us to easily change the way we add and lookup DMA channel structures. Signed-off-by: Russell King --- arch/arm/kernel/dma.c | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c index c31bf00e5ba..0ffea3fc22d 100644 --- a/arch/arm/kernel/dma.c +++ b/arch/arm/kernel/dma.c @@ -25,6 +25,16 @@ EXPORT_SYMBOL(dma_spin_lock); static dma_t dma_chan[MAX_DMA_CHANNELS]; +static inline dma_t *dma_channel(unsigned int chan) +{ + dma_t *dma = dma_chan + chan; + + if (chan >= MAX_DMA_CHANNELS || !dma->d_ops) + return NULL; + + return dma; +} + /* * Request DMA channel * @@ -32,10 +42,10 @@ static dma_t dma_chan[MAX_DMA_CHANNELS]; */ int request_dma(unsigned int chan, const char *device_id) { - dma_t *dma = dma_chan + chan; + dma_t *dma = dma_channel(chan); int ret; - if (chan >= MAX_DMA_CHANNELS || !dma->d_ops) + if (!dma) goto bad_dma; if (xchg(&dma->lock, 1) != 0) @@ -70,9 +80,9 @@ EXPORT_SYMBOL(request_dma); */ void free_dma(unsigned int chan) { - dma_t *dma = dma_chan + chan; + dma_t *dma = dma_channel(chan); - if (chan >= MAX_DMA_CHANNELS || !dma->d_ops) + if (!dma) goto bad_dma; if (dma->active) { @@ -99,7 +109,7 @@ EXPORT_SYMBOL(free_dma); */ void set_dma_sg (unsigned int chan, struct scatterlist *sg, int nr_sg) { - dma_t *dma = dma_chan + chan; + dma_t *dma = dma_channel(chan); if (dma->active) printk(KERN_ERR "dma%d: altering DMA SG while " @@ -117,7 +127,7 @@ EXPORT_SYMBOL(set_dma_sg); */ void __set_dma_addr (unsigned int chan, void *addr) { - dma_t *dma = dma_chan + chan; + dma_t *dma = dma_channel(chan); if (dma->active) printk(KERN_ERR "dma%d: altering DMA address while " @@ -135,7 +145,7 @@ EXPORT_SYMBOL(__set_dma_addr); */ void set_dma_count (unsigned int chan, unsigned long count) { - dma_t *dma = dma_chan + chan; + dma_t *dma = dma_channel(chan); if (dma->active) printk(KERN_ERR "dma%d: altering DMA count while " @@ -151,7 +161,7 @@ EXPORT_SYMBOL(set_dma_count); */ void set_dma_mode (unsigned int chan, dmamode_t mode) { - dma_t *dma = dma_chan + chan; + dma_t *dma = dma_channel(chan); if (dma->active) printk(KERN_ERR "dma%d: altering DMA mode while " @@ -166,7 +176,7 @@ EXPORT_SYMBOL(set_dma_mode); */ void enable_dma (unsigned int chan) { - dma_t *dma = dma_chan + chan; + dma_t *dma = dma_channel(chan); if (!dma->lock) goto free_dma; @@ -187,7 +197,7 @@ EXPORT_SYMBOL(enable_dma); */ void disable_dma (unsigned int chan) { - dma_t *dma = dma_chan + chan; + dma_t *dma = dma_channel(chan); if (!dma->lock) goto free_dma; @@ -209,7 +219,8 @@ EXPORT_SYMBOL(disable_dma); */ int dma_channel_active(unsigned int chan) { - return dma_chan[chan].active; + dma_t *dma = dma_channel(chan); + return dma->active; } EXPORT_SYMBOL(dma_channel_active); @@ -221,7 +232,7 @@ EXPORT_SYMBOL(set_dma_page); void set_dma_speed(unsigned int chan, int cycle_ns) { - dma_t *dma = dma_chan + chan; + dma_t *dma = dma_channel(chan); int ret = 0; if (dma->d_ops->setspeed) @@ -232,7 +243,7 @@ EXPORT_SYMBOL(set_dma_speed); int get_dma_residue(unsigned int chan) { - dma_t *dma = dma_chan + chan; + dma_t *dma = dma_channel(chan); int ret = 0; if (dma->d_ops->residue) @@ -247,5 +258,4 @@ static int __init init_dma(void) arch_dma_init(dma_chan); return 0; } - core_initcall(init_dma); -- GitLab From 2f757f2ab7411cf0e2779012d8cda0cbf2f80d26 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 8 Dec 2008 16:33:30 +0000 Subject: [PATCH 0022/4982] [ARM] dma: rejig DMA initialization Rather than having the central DMA multiplexer call the architecture specific DMA initialization function, have each architecture DMA initialization function use core_initcall(), and register each DMA channel separately with the multiplexer. This removes the array of dma structures in the central multiplexer, replacing it with an array of pointers instead; this is more flexible since it allows the drivers to wrap the DMA structure (eventually allowing us to transition non-ISA DMA drivers away.) Signed-off-by: Russell King --- arch/arm/include/asm/mach/dma.h | 12 +++--- arch/arm/kernel/dma-isa.c | 18 +++++++-- arch/arm/kernel/dma.c | 25 ++++++------ arch/arm/mach-footbridge/dma.c | 6 ++- arch/arm/mach-rpc/dma.c | 68 ++++++++++++++++++++++----------- arch/arm/mach-shark/dma.c | 6 ++- 6 files changed, 88 insertions(+), 47 deletions(-) diff --git a/arch/arm/include/asm/mach/dma.h b/arch/arm/include/asm/mach/dma.h index 281ae7e40a9..38a3693f125 100644 --- a/arch/arm/include/asm/mach/dma.h +++ b/arch/arm/include/asm/mach/dma.h @@ -48,10 +48,12 @@ struct dma_struct { struct dma_ops *d_ops; }; -/* Prototype: void arch_dma_init(dma) - * Purpose : Initialise architecture specific DMA - * Params : dma - pointer to array of DMA structures +/* + * isa_dma_add - add an ISA-style DMA channel */ -extern void arch_dma_init(dma_t *dma); +extern int isa_dma_add(unsigned int, dma_t *dma); -extern void isa_init_dma(dma_t *dma); +/* + * Add the ISA DMA controller. Always takes channels 0-7. + */ +extern void isa_init_dma(void); diff --git a/arch/arm/kernel/dma-isa.c b/arch/arm/kernel/dma-isa.c index 29eca48925d..da02a7ff341 100644 --- a/arch/arm/kernel/dma-isa.c +++ b/arch/arm/kernel/dma-isa.c @@ -160,7 +160,12 @@ static struct resource dma_resources[] = { { .end = 0x048f } }; -void __init isa_init_dma(dma_t *dma) +static dma_t isa_dma[8]; + +/* + * ISA DMA always starts at channel 0 + */ +void __init isa_init_dma(void) { /* * Try to autodetect presence of an ISA DMA controller. @@ -178,10 +183,10 @@ void __init isa_init_dma(dma_t *dma) outb(0xaa, 0x00); if (inb(0) == 0x55 && inb(0) == 0xaa) { - int chan, i; + unsigned int chan, i; for (chan = 0; chan < 8; chan++) { - dma[chan].d_ops = &isa_dma_ops; + isa_dma[chan].d_ops = &isa_dma_ops; isa_disable_dma(chan, NULL); } @@ -217,5 +222,12 @@ void __init isa_init_dma(dma_t *dma) for (i = 0; i < ARRAY_SIZE(dma_resources); i++) request_resource(&ioport_resource, dma_resources + i); + + for (chan = 0; chan < 8; chan++) { + int ret = isa_dma_add(chan, &isa_dma[chan]); + if (ret) + printk(KERN_ERR "ISADMA%u: unable to register: %d\n", + chan, ret); + } } } diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c index 0ffea3fc22d..aab24f03ea1 100644 --- a/arch/arm/kernel/dma.c +++ b/arch/arm/kernel/dma.c @@ -23,16 +23,24 @@ DEFINE_SPINLOCK(dma_spin_lock); EXPORT_SYMBOL(dma_spin_lock); -static dma_t dma_chan[MAX_DMA_CHANNELS]; +static dma_t *dma_chan[MAX_DMA_CHANNELS]; static inline dma_t *dma_channel(unsigned int chan) { - dma_t *dma = dma_chan + chan; - - if (chan >= MAX_DMA_CHANNELS || !dma->d_ops) + if (chan >= MAX_DMA_CHANNELS) return NULL; - return dma; + return dma_chan[chan]; +} + +int __init isa_dma_add(unsigned int chan, dma_t *dma) +{ + if (!dma->d_ops) + return -EINVAL; + if (dma_chan[chan]) + return -EBUSY; + dma_chan[chan] = dma; + return 0; } /* @@ -252,10 +260,3 @@ int get_dma_residue(unsigned int chan) return ret; } EXPORT_SYMBOL(get_dma_residue); - -static int __init init_dma(void) -{ - arch_dma_init(dma_chan); - return 0; -} -core_initcall(init_dma); diff --git a/arch/arm/mach-footbridge/dma.c b/arch/arm/mach-footbridge/dma.c index e7b8a6adaf7..fdd94b182d7 100644 --- a/arch/arm/mach-footbridge/dma.c +++ b/arch/arm/mach-footbridge/dma.c @@ -41,7 +41,7 @@ static struct dma_ops fb_dma_ops = { }; #endif -void __init arch_dma_init(dma_t *dma) +static int __init fb_dma_init(void) { #if 0 dma[_DC21285_DMA(0)].d_ops = &fb_dma_ops; @@ -49,6 +49,8 @@ void __init arch_dma_init(dma_t *dma) #endif #ifdef CONFIG_ISA_DMA if (footbridge_cfn_mode()) - isa_init_dma(dma + _ISA_DMA(0)); + isa_init_dma(); #endif + return 0; } +core_initcall(fb_dma_init); diff --git a/arch/arm/mach-rpc/dma.c b/arch/arm/mach-rpc/dma.c index a86d3ed859a..efcf6718d1d 100644 --- a/arch/arm/mach-rpc/dma.c +++ b/arch/arm/mach-rpc/dma.c @@ -302,8 +302,22 @@ static struct dma_ops sound_dma_ops = { .disable = sound_enable_disable_dma, }; -void __init arch_dma_init(dma_t *dma) +static dma_t iomd_dma[6]; + +static dma_t floppy_dma = { + .dma_irq = FIQ_FLOPPYDATA, + .d_ops = &floppy_dma_ops, +}; + +static dma_t sound_dma = { + .d_ops = &sound_dma_ops, +}; + +static int __init rpc_dma_init(void) { + unsigned int i; + int ret; + iomd_writeb(0, IOMD_IO0CR); iomd_writeb(0, IOMD_IO1CR); iomd_writeb(0, IOMD_IO2CR); @@ -311,31 +325,39 @@ void __init arch_dma_init(dma_t *dma) iomd_writeb(0xa0, IOMD_DMATCR); - dma[DMA_0].dma_base = IOMD_IO0CURA; - dma[DMA_0].dma_irq = IRQ_DMA0; - dma[DMA_0].d_ops = &iomd_dma_ops; - dma[DMA_1].dma_base = IOMD_IO1CURA; - dma[DMA_1].dma_irq = IRQ_DMA1; - dma[DMA_1].d_ops = &iomd_dma_ops; - dma[DMA_2].dma_base = IOMD_IO2CURA; - dma[DMA_2].dma_irq = IRQ_DMA2; - dma[DMA_2].d_ops = &iomd_dma_ops; - dma[DMA_3].dma_base = IOMD_IO3CURA; - dma[DMA_3].dma_irq = IRQ_DMA3; - dma[DMA_3].d_ops = &iomd_dma_ops; - dma[DMA_S0].dma_base = IOMD_SD0CURA; - dma[DMA_S0].dma_irq = IRQ_DMAS0; - dma[DMA_S0].d_ops = &iomd_dma_ops; - dma[DMA_S1].dma_base = IOMD_SD1CURA; - dma[DMA_S1].dma_irq = IRQ_DMAS1; - dma[DMA_S1].d_ops = &iomd_dma_ops; - dma[DMA_VIRTUAL_FLOPPY].dma_irq = FIQ_FLOPPYDATA; - dma[DMA_VIRTUAL_FLOPPY].d_ops = &floppy_dma_ops; - dma[DMA_VIRTUAL_SOUND].d_ops = &sound_dma_ops; - /* * Setup DMA channels 2,3 to be for podules * and channels 0,1 for internal devices */ iomd_writeb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT); + + iomd_dma[DMA_0].dma_base = IOMD_IO0CURA; + iomd_dma[DMA_0].dma_irq = IRQ_DMA0; + iomd_dma[DMA_1].dma_base = IOMD_IO1CURA; + iomd_dma[DMA_1].dma_irq = IRQ_DMA1; + iomd_dma[DMA_2].dma_base = IOMD_IO2CURA; + iomd_dma[DMA_2].dma_irq = IRQ_DMA2; + iomd_dma[DMA_3].dma_base = IOMD_IO3CURA; + iomd_dma[DMA_3].dma_irq = IRQ_DMA3; + iomd_dma[DMA_S0].dma_base = IOMD_SD0CURA; + iomd_dma[DMA_S0].dma_irq = IRQ_DMAS0; + iomd_dma[DMA_S1].dma_base = IOMD_SD1CURA; + iomd_dma[DMA_S1].dma_irq = IRQ_DMAS1; + + for (i = DMA_0; i <= DMA_S1; i++) { + iomd_dma[i].d_ops = &iomd_dma_ops; + + ret = isa_dma_add(i, &iomd_dma[i]); + if (ret) + printk("IOMDDMA%u: unable to register: %d\n", i, ret); + } + + ret = isa_dma_add(DMA_VIRTUAL_FLOPPY, &floppy_dma); + if (ret) + printk("IOMDFLOPPY: unable to register: %d\n", ret); + ret = isa_dma_add(DMA_VIRTUAL_SOUND, &sound_dma); + if (ret) + printk("IOMDSOUND: unable to register: %d\n", ret); + return 0; } +core_initcall(rpc_dma_init); diff --git a/arch/arm/mach-shark/dma.c b/arch/arm/mach-shark/dma.c index 6774b8d5d13..10b5b8b3272 100644 --- a/arch/arm/mach-shark/dma.c +++ b/arch/arm/mach-shark/dma.c @@ -13,9 +13,11 @@ #include #include -void __init arch_dma_init(dma_t *dma) +static int __init shark_dma_init(void) { #ifdef CONFIG_ISA_DMA - isa_init_dma(dma); + isa_init_dma(); #endif + return 0; } +core_initcall(shark_dma_init); -- GitLab From ad9dd94c384f7ee37b798a9349b8c42da8fa99ab Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 8 Dec 2008 17:35:48 +0000 Subject: [PATCH 0023/4982] [ARM] dma: move RiscPC specific DMA data out of dma_struct Separate the RiscPC specific (IOMD and floppy FIQ) data out of the core DMA structure by making the IOMD and floppy DMA supersets. Signed-off-by: Russell King --- arch/arm/include/asm/mach/dma.h | 18 ++-- arch/arm/mach-rpc/dma.c | 146 +++++++++++++++++--------------- 2 files changed, 91 insertions(+), 73 deletions(-) diff --git a/arch/arm/include/asm/mach/dma.h b/arch/arm/include/asm/mach/dma.h index 38a3693f125..4326738ff36 100644 --- a/arch/arm/include/asm/mach/dma.h +++ b/arch/arm/include/asm/mach/dma.h @@ -40,14 +40,22 @@ struct dma_struct { unsigned int lock; /* Device is allocated */ const char *device_id; /* Device name */ - unsigned int dma_base; /* Controller base address */ - int dma_irq; /* Controller IRQ */ - struct scatterlist cur_sg; /* Current controller buffer */ - unsigned int state; - struct dma_ops *d_ops; }; +struct floppy_dma { + struct dma_struct dma; + unsigned int fiq; +}; + +struct iomd_dma { + struct dma_struct dma; + unsigned int state; + unsigned long base; /* Controller base address */ + int irq; /* Controller IRQ */ + struct scatterlist cur_sg; /* Current controller buffer */ +}; + /* * isa_dma_add - add an ISA-style DMA channel */ diff --git a/arch/arm/mach-rpc/dma.c b/arch/arm/mach-rpc/dma.c index efcf6718d1d..0163592b2af 100644 --- a/arch/arm/mach-rpc/dma.c +++ b/arch/arm/mach-rpc/dma.c @@ -44,15 +44,15 @@ typedef enum { #define CR (IOMD_IO0CR - IOMD_IO0CURA) #define ST (IOMD_IO0ST - IOMD_IO0CURA) -static void iomd_get_next_sg(struct scatterlist *sg, dma_t *dma) +static void iomd_get_next_sg(struct scatterlist *sg, struct iomd_dma *idma) { unsigned long end, offset, flags = 0; - if (dma->sg) { - sg->dma_address = dma->sg->dma_address; + if (idma->dma.sg) { + sg->dma_address = idma->dma.sg->dma_address; offset = sg->dma_address & ~PAGE_MASK; - end = offset + dma->sg->length; + end = offset + idma->dma.sg->length; if (end > PAGE_SIZE) end = PAGE_SIZE; @@ -62,15 +62,15 @@ static void iomd_get_next_sg(struct scatterlist *sg, dma_t *dma) sg->length = end - TRANSFER_SIZE; - dma->sg->length -= end - offset; - dma->sg->dma_address += end - offset; + idma->dma.sg->length -= end - offset; + idma->dma.sg->dma_address += end - offset; - if (dma->sg->length == 0) { - if (dma->sgcount > 1) { - dma->sg++; - dma->sgcount--; + if (idma->dma.sg->length == 0) { + if (idma->dma.sgcount > 1) { + idma->dma.sg++; + idma->dma.sgcount--; } else { - dma->sg = NULL; + idma->dma.sg = NULL; flags |= DMA_END_S; } } @@ -85,8 +85,8 @@ static void iomd_get_next_sg(struct scatterlist *sg, dma_t *dma) static irqreturn_t iomd_dma_handle(int irq, void *dev_id) { - dma_t *dma = (dma_t *)dev_id; - unsigned long base = dma->dma_base; + struct iomd_dma *idma = dev_id; + unsigned long base = idma->base; do { unsigned int status; @@ -95,31 +95,31 @@ static irqreturn_t iomd_dma_handle(int irq, void *dev_id) if (!(status & DMA_ST_INT)) return IRQ_HANDLED; - if ((dma->state ^ status) & DMA_ST_AB) - iomd_get_next_sg(&dma->cur_sg, dma); + if ((idma->state ^ status) & DMA_ST_AB) + iomd_get_next_sg(&idma->cur_sg, idma); switch (status & (DMA_ST_OFL | DMA_ST_AB)) { case DMA_ST_OFL: /* OIA */ case DMA_ST_AB: /* .IB */ - iomd_writel(dma->cur_sg.dma_address, base + CURA); - iomd_writel(dma->cur_sg.length, base + ENDA); - dma->state = DMA_ST_AB; + iomd_writel(idma->cur_sg.dma_address, base + CURA); + iomd_writel(idma->cur_sg.length, base + ENDA); + idma->state = DMA_ST_AB; break; case DMA_ST_OFL | DMA_ST_AB: /* OIB */ case 0: /* .IA */ - iomd_writel(dma->cur_sg.dma_address, base + CURB); - iomd_writel(dma->cur_sg.length, base + ENDB); - dma->state = 0; + iomd_writel(idma->cur_sg.dma_address, base + CURB); + iomd_writel(idma->cur_sg.length, base + ENDB); + idma->state = 0; break; } if (status & DMA_ST_OFL && - dma->cur_sg.length == (DMA_END_S|DMA_END_L)) + idma->cur_sg.length == (DMA_END_S|DMA_END_L)) break; } while (1); - dma->state = ~DMA_ST_AB; + idma->state = ~DMA_ST_AB; disable_irq(irq); return IRQ_HANDLED; @@ -127,56 +127,62 @@ static irqreturn_t iomd_dma_handle(int irq, void *dev_id) static int iomd_request_dma(unsigned int chan, dma_t *dma) { - return request_irq(dma->dma_irq, iomd_dma_handle, - IRQF_DISABLED, dma->device_id, dma); + struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma); + + return request_irq(idma->irq, iomd_dma_handle, + IRQF_DISABLED, idma->dma.device_id, idma); } static void iomd_free_dma(unsigned int chan, dma_t *dma) { - free_irq(dma->dma_irq, dma); + struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma); + + free_irq(idma->irq, idma); } static void iomd_enable_dma(unsigned int chan, dma_t *dma) { - unsigned long dma_base = dma->dma_base; + struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma); + unsigned long dma_base = idma->base; unsigned int ctrl = TRANSFER_SIZE | DMA_CR_E; - if (dma->invalid) { - dma->invalid = 0; + if (idma->dma.invalid) { + idma->dma.invalid = 0; /* * Cope with ISA-style drivers which expect cache * coherence. */ - if (!dma->sg) { - dma->sg = &dma->buf; - dma->sgcount = 1; - dma->buf.length = dma->count; - dma->buf.dma_address = dma_map_single(NULL, - dma->addr, dma->count, - dma->dma_mode == DMA_MODE_READ ? + if (!idma->dma.sg) { + idma->dma.sg = &idma->dma.buf; + idma->dma.sgcount = 1; + idma->dma.buf.length = idma->dma.count; + idma->dma.buf.dma_address = dma_map_single(NULL, + idma->dma.addr, idma->dma.count, + idma->dma.dma_mode == DMA_MODE_READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE); } iomd_writeb(DMA_CR_C, dma_base + CR); - dma->state = DMA_ST_AB; + idma->state = DMA_ST_AB; } - - if (dma->dma_mode == DMA_MODE_READ) + + if (idma->dma.dma_mode == DMA_MODE_READ) ctrl |= DMA_CR_D; iomd_writeb(ctrl, dma_base + CR); - enable_irq(dma->dma_irq); + enable_irq(idma->irq); } static void iomd_disable_dma(unsigned int chan, dma_t *dma) { - unsigned long dma_base = dma->dma_base; + struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma); + unsigned long dma_base = idma->base; unsigned long flags; local_irq_save(flags); - if (dma->state != ~DMA_ST_AB) - disable_irq(dma->dma_irq); + if (idma->state != ~DMA_ST_AB) + disable_irq(idma->irq); iomd_writeb(0, dma_base + CR); local_irq_restore(flags); } @@ -238,14 +244,15 @@ static struct fiq_handler fh = { static void floppy_enable_dma(unsigned int chan, dma_t *dma) { + struct floppy_dma *fdma = container_of(dma, struct floppy_dma, dma); void *fiqhandler_start; unsigned int fiqhandler_length; struct pt_regs regs; - if (dma->sg) + if (fdma->dma.sg) BUG(); - if (dma->dma_mode == DMA_MODE_READ) { + if (fdma->dma.dma_mode == DMA_MODE_READ) { extern unsigned char floppy_fiqin_start, floppy_fiqin_end; fiqhandler_start = &floppy_fiqin_start; fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start; @@ -255,8 +262,8 @@ static void floppy_enable_dma(unsigned int chan, dma_t *dma) fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start; } - regs.ARM_r9 = dma->count; - regs.ARM_r10 = (unsigned long)dma->addr; + regs.ARM_r9 = fdma->dma.count; + regs.ARM_r10 = (unsigned long)fdma->dma.addr; regs.ARM_fp = (unsigned long)FLOPPYDMA_BASE; if (claim_fiq(&fh)) { @@ -266,12 +273,13 @@ static void floppy_enable_dma(unsigned int chan, dma_t *dma) set_fiq_handler(fiqhandler_start, fiqhandler_length); set_fiq_regs(®s); - enable_fiq(dma->dma_irq); + enable_fiq(fdma->fiq); } static void floppy_disable_dma(unsigned int chan, dma_t *dma) { - disable_fiq(dma->dma_irq); + struct floppy_dma *fdma = container_of(dma, struct floppy_dma, dma); + disable_fiq(fdma->fiq); release_fiq(&fh); } @@ -302,11 +310,13 @@ static struct dma_ops sound_dma_ops = { .disable = sound_enable_disable_dma, }; -static dma_t iomd_dma[6]; +static struct iomd_dma iomd_dma[6]; -static dma_t floppy_dma = { - .dma_irq = FIQ_FLOPPYDATA, - .d_ops = &floppy_dma_ops, +static struct floppy_dma floppy_dma = { + .dma = { + .d_ops = &floppy_dma_ops, + }, + .fiq = FIQ_FLOPPYDATA, }; static dma_t sound_dma = { @@ -331,28 +341,28 @@ static int __init rpc_dma_init(void) */ iomd_writeb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT); - iomd_dma[DMA_0].dma_base = IOMD_IO0CURA; - iomd_dma[DMA_0].dma_irq = IRQ_DMA0; - iomd_dma[DMA_1].dma_base = IOMD_IO1CURA; - iomd_dma[DMA_1].dma_irq = IRQ_DMA1; - iomd_dma[DMA_2].dma_base = IOMD_IO2CURA; - iomd_dma[DMA_2].dma_irq = IRQ_DMA2; - iomd_dma[DMA_3].dma_base = IOMD_IO3CURA; - iomd_dma[DMA_3].dma_irq = IRQ_DMA3; - iomd_dma[DMA_S0].dma_base = IOMD_SD0CURA; - iomd_dma[DMA_S0].dma_irq = IRQ_DMAS0; - iomd_dma[DMA_S1].dma_base = IOMD_SD1CURA; - iomd_dma[DMA_S1].dma_irq = IRQ_DMAS1; + iomd_dma[DMA_0].base = IOMD_IO0CURA; + iomd_dma[DMA_0].irq = IRQ_DMA0; + iomd_dma[DMA_1].base = IOMD_IO1CURA; + iomd_dma[DMA_1].irq = IRQ_DMA1; + iomd_dma[DMA_2].base = IOMD_IO2CURA; + iomd_dma[DMA_2].irq = IRQ_DMA2; + iomd_dma[DMA_3].base = IOMD_IO3CURA; + iomd_dma[DMA_3].irq = IRQ_DMA3; + iomd_dma[DMA_S0].base = IOMD_SD0CURA; + iomd_dma[DMA_S0].irq = IRQ_DMAS0; + iomd_dma[DMA_S1].base = IOMD_SD1CURA; + iomd_dma[DMA_S1].irq = IRQ_DMAS1; for (i = DMA_0; i <= DMA_S1; i++) { - iomd_dma[i].d_ops = &iomd_dma_ops; + iomd_dma[i].dma.d_ops = &iomd_dma_ops; - ret = isa_dma_add(i, &iomd_dma[i]); + ret = isa_dma_add(i, &iomd_dma[i].dma); if (ret) printk("IOMDDMA%u: unable to register: %d\n", i, ret); } - ret = isa_dma_add(DMA_VIRTUAL_FLOPPY, &floppy_dma); + ret = isa_dma_add(DMA_VIRTUAL_FLOPPY, &floppy_dma.dma); if (ret) printk("IOMDFLOPPY: unable to register: %d\n", ret); ret = isa_dma_add(DMA_VIRTUAL_SOUND, &sound_dma); -- GitLab From 8c56afcbea22e472d3bfa8ddf06f23cd6bc56826 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 11 Dec 2008 14:50:39 +0000 Subject: [PATCH 0024/4982] [ARM] dma: constify dma controller name and dma ops Signed-off-by: Russell King --- arch/arm/include/asm/mach/dma.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/mach/dma.h b/arch/arm/include/asm/mach/dma.h index 4326738ff36..3122adae80b 100644 --- a/arch/arm/include/asm/mach/dma.h +++ b/arch/arm/include/asm/mach/dma.h @@ -21,7 +21,7 @@ struct dma_ops { void (*disable)(unsigned int, dma_t *); /* mandatory */ int (*residue)(unsigned int, dma_t *); /* optional */ int (*setspeed)(unsigned int, dma_t *, int); /* optional */ - char *type; + const char *type; }; struct dma_struct { @@ -40,7 +40,7 @@ struct dma_struct { unsigned int lock; /* Device is allocated */ const char *device_id; /* Device name */ - struct dma_ops *d_ops; + const struct dma_ops *d_ops; }; struct floppy_dma { -- GitLab From d667522fdf637ef1b425518afe11aedba80364b2 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 8 Dec 2008 17:50:25 +0000 Subject: [PATCH 0025/4982] [ARM] dma: ensure that the single entry sg is properly initialized Signed-off-by: Russell King --- arch/arm/kernel/dma.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c index aab24f03ea1..e7828fcd954 100644 --- a/arch/arm/kernel/dma.c +++ b/arch/arm/kernel/dma.c @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -37,6 +38,9 @@ int __init isa_dma_add(unsigned int chan, dma_t *dma) { if (!dma->d_ops) return -EINVAL; + + sg_init_table(&dma->buf, 1); + if (dma_chan[chan]) return -EBUSY; dma_chan[chan] = dma; -- GitLab From 9e28d7e8c5422a47db886c4104221ea165595de0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 8 Dec 2008 19:03:58 +0000 Subject: [PATCH 0026/4982] [ARM] dma: convert IOMD DMA to use sg_next() ... rather than incrementing the sg pointer. Signed-off-by: Russell King --- arch/arm/mach-rpc/dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-rpc/dma.c b/arch/arm/mach-rpc/dma.c index 0163592b2af..a5987bbed60 100644 --- a/arch/arm/mach-rpc/dma.c +++ b/arch/arm/mach-rpc/dma.c @@ -67,7 +67,7 @@ static void iomd_get_next_sg(struct scatterlist *sg, struct iomd_dma *idma) if (idma->dma.sg->length == 0) { if (idma->dma.sgcount > 1) { - idma->dma.sg++; + idma->dma.sg = sg_next(idma->dma.sg); idma->dma.sgcount--; } else { idma->dma.sg = NULL; -- GitLab From f6718653361e8f8a6aac9946822aa2090edf4f37 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 8 Dec 2008 19:25:28 +0000 Subject: [PATCH 0027/4982] [ARM] dma: pata_icside's contiguous sg array is now redundant Now that the IOMD DMA code walks the scatterlist using sg_next, converting the sg list into a contiguous list is no longer required. Signed-off-by: Russell King --- drivers/ata/pata_icside.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c index cf9e9848f8b..63121f45ba2 100644 --- a/drivers/ata/pata_icside.c +++ b/drivers/ata/pata_icside.c @@ -57,7 +57,6 @@ struct pata_icside_state { u8 disabled; unsigned int speed[ATA_MAX_DEVICES]; } port[2]; - struct scatterlist sg[PATA_ICSIDE_MAX_SG]; }; struct pata_icside_info { @@ -222,9 +221,7 @@ static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct pata_icside_state *state = ap->host->private_data; - struct scatterlist *sg, *rsg = state->sg; unsigned int write = qc->tf.flags & ATA_TFLAG_WRITE; - unsigned int si; /* * We are simplex; BUG if we try to fiddle with DMA @@ -232,21 +229,13 @@ static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc) */ BUG_ON(dma_channel_active(state->dma)); - /* - * Copy ATAs scattered sg list into a contiguous array of sg - */ - for_each_sg(qc->sg, sg, qc->n_elem, si) { - memcpy(rsg, sg, sizeof(*sg)); - rsg++; - } - /* * Route the DMA signals to the correct interface */ writeb(state->port[ap->port_no].port_sel, state->ioc_base); set_dma_speed(state->dma, state->port[ap->port_no].speed[qc->dev->devno]); - set_dma_sg(state->dma, state->sg, rsg - state->sg); + set_dma_sg(state->dma, qc->sg, qc->n_elem); set_dma_mode(state->dma, write ? DMA_MODE_WRITE : DMA_MODE_READ); /* issue r/w command */ -- GitLab From 5369bea7d7db1d95f63907f3470e23d32930be98 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 11 Dec 2008 16:37:06 +0000 Subject: [PATCH 0028/4982] [ARM] dma: Use sensible DMA parameters for Acorn drivers The hardware supports transfers up to a page boundary per buffer. Currently, we work around that in the DMA code by splitting each buffer up as we run through the scatterlist. Avoid this by telling the block layers about the hardware restriction. Eventually, this will allow us to phase out the splitting code, but not until the old IDE layer allows us to control the value it gives to blk_queue_segment_boundary(). Signed-off-by: Russell King --- arch/arm/mach-rpc/include/mach/isa-dma.h | 2 ++ drivers/ata/pata_icside.c | 6 ++---- drivers/scsi/arm/cumana_2.c | 3 ++- drivers/scsi/arm/eesox.c | 3 ++- drivers/scsi/arm/powertec.c | 3 ++- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-rpc/include/mach/isa-dma.h b/arch/arm/mach-rpc/include/mach/isa-dma.h index bad72054858..67bfc6719c3 100644 --- a/arch/arm/mach-rpc/include/mach/isa-dma.h +++ b/arch/arm/mach-rpc/include/mach/isa-dma.h @@ -23,5 +23,7 @@ #define DMA_FLOPPY DMA_VIRTUAL_FLOPPY +#define IOMD_DMA_BOUNDARY (PAGE_SIZE - 1) + #endif /* _ASM_ARCH_DMA_H */ diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c index 63121f45ba2..d7bc925c524 100644 --- a/drivers/ata/pata_icside.c +++ b/drivers/ata/pata_icside.c @@ -45,8 +45,6 @@ static const struct portinfo pata_icside_portinfo_v6_2 = { .stepping = 6, }; -#define PATA_ICSIDE_MAX_SG 128 - struct pata_icside_state { void __iomem *irq_port; void __iomem *ioc_base; @@ -295,8 +293,8 @@ static int icside_dma_init(struct pata_icside_info *info) static struct scsi_host_template pata_icside_sht = { ATA_BASE_SHT(DRV_NAME), - .sg_tablesize = PATA_ICSIDE_MAX_SG, - .dma_boundary = ~0, /* no dma boundaries */ + .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .dma_boundary = IOMD_DMA_BOUNDARY, }; static void pata_icside_postreset(struct ata_link *link, unsigned int *classes) diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c index 68a64123af8..8ee01b90733 100644 --- a/drivers/scsi/arm/cumana_2.c +++ b/drivers/scsi/arm/cumana_2.c @@ -390,7 +390,8 @@ static struct scsi_host_template cumanascsi2_template = { .eh_abort_handler = fas216_eh_abort, .can_queue = 1, .this_id = 7, - .sg_tablesize = SG_ALL, + .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .dma_boundary = IOMD_DMA_BOUNDARY, .cmd_per_lun = 1, .use_clustering = DISABLE_CLUSTERING, .proc_name = "cumanascsi2", diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c index bb2477b3fb0..d8435132f46 100644 --- a/drivers/scsi/arm/eesox.c +++ b/drivers/scsi/arm/eesox.c @@ -508,7 +508,8 @@ static struct scsi_host_template eesox_template = { .eh_abort_handler = fas216_eh_abort, .can_queue = 1, .this_id = 7, - .sg_tablesize = SG_ALL, + .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .dma_boundary = IOMD_DMA_BOUNDARY, .cmd_per_lun = 1, .use_clustering = DISABLE_CLUSTERING, .proc_name = "eesox", diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c index d9a546d1917..e2297b4c1b9 100644 --- a/drivers/scsi/arm/powertec.c +++ b/drivers/scsi/arm/powertec.c @@ -302,7 +302,8 @@ static struct scsi_host_template powertecscsi_template = { .can_queue = 8, .this_id = 7, - .sg_tablesize = SG_ALL, + .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .dma_boundary = IOMD_DMA_BOUNDARY, .cmd_per_lun = 2, .use_clustering = ENABLE_CLUSTERING, .proc_name = "powertec", -- GitLab From 1cc4fff0b360aeffeedb7d6db5089d88dd861700 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Mon, 22 Dec 2008 02:24:48 +0100 Subject: [PATCH 0029/4982] hrtimers: increase clock min delta threshold while interrupt hanging Impact: avoid timer IRQ hanging slow systems While using the function graph tracer on a virtualized system, the hrtimer_interrupt can hang the system on an infinite loop. This can be caused in several situations: - the hardware is very slow and HZ is set too high - something intrusive is slowing the system down (tracing under emulation) ... and the next clock events to program are always before the current time. This patch implements a reasonable compromise: if such a situation is detected, we share the CPUs time in 1/4 to process the hrtimer interrupts. This is enough to let the system running without serious starvation. It has been successfully tested under VirtualBox with 1000 HZ and 100 HZ with function graph tracer launched. On both cases, the clock events were increased until about 25 ms periodic ticks, which means 40 HZ. So we change a hard to debug hang into a warning message and a system that still manages to limp along. Signed-off-by: Frederic Weisbecker Signed-off-by: Ingo Molnar --- kernel/hrtimer.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index bda9cb92427..c2a69b89ac6 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -1171,6 +1171,29 @@ static void __run_hrtimer(struct hrtimer *timer) #ifdef CONFIG_HIGH_RES_TIMERS +static int force_clock_reprogram; + +/* + * After 5 iteration's attempts, we consider that hrtimer_interrupt() + * is hanging, which could happen with something that slows the interrupt + * such as the tracing. Then we force the clock reprogramming for each future + * hrtimer interrupts to avoid infinite loops and use the min_delta_ns + * threshold that we will overwrite. + * The next tick event will be scheduled to 3 times we currently spend on + * hrtimer_interrupt(). This gives a good compromise, the cpus will spend + * 1/4 of their time to process the hrtimer interrupts. This is enough to + * let it running without serious starvation. + */ + +static inline void +hrtimer_interrupt_hanging(struct clock_event_device *dev, + ktime_t try_time) +{ + force_clock_reprogram = 1; + dev->min_delta_ns = (unsigned long)try_time.tv64 * 3; + printk(KERN_WARNING "hrtimer: interrupt too slow, " + "forcing clock min delta to %lu ns\n", dev->min_delta_ns); +} /* * High resolution timer interrupt * Called with interrupts disabled @@ -1180,6 +1203,7 @@ void hrtimer_interrupt(struct clock_event_device *dev) struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); struct hrtimer_clock_base *base; ktime_t expires_next, now; + int nr_retries = 0; int i; BUG_ON(!cpu_base->hres_active); @@ -1187,6 +1211,10 @@ void hrtimer_interrupt(struct clock_event_device *dev) dev->next_event.tv64 = KTIME_MAX; retry: + /* 5 retries is enough to notice a hang */ + if (!(++nr_retries % 5)) + hrtimer_interrupt_hanging(dev, ktime_sub(ktime_get(), now)); + now = ktime_get(); expires_next.tv64 = KTIME_MAX; @@ -1239,7 +1267,7 @@ void hrtimer_interrupt(struct clock_event_device *dev) /* Reprogramming necessary ? */ if (expires_next.tv64 != KTIME_MAX) { - if (tick_program_event(expires_next, 0)) + if (tick_program_event(expires_next, force_clock_reprogram)) goto retry; } } -- GitLab From efdc64f0c792ea744bcc9203f35b908e66d42f41 Mon Sep 17 00:00:00 2001 From: Wang Chen Date: Mon, 29 Dec 2008 13:35:11 +0800 Subject: [PATCH 0030/4982] genirq: check chip->ack before calling Impact: fix theoretical NULL dereference The generic irq layer doesn't know whether irq_chip has ack routine on some architectures or not. Upon that, before calling chip->ack, we should check that it's not NULL. Signed-off-by: Wang Chen Signed-off-by: Ingo Molnar --- kernel/irq/chip.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 6eb3c7952b6..0ad02d76a0c 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -290,7 +290,8 @@ static inline void mask_ack_irq(struct irq_desc *desc, int irq) desc->chip->mask_ack(irq); else { desc->chip->mask(irq); - desc->chip->ack(irq); + if (desc->chip->ack) + desc->chip->ack(irq); } } @@ -475,7 +476,8 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc) kstat_incr_irqs_this_cpu(irq, desc); /* Start handling the irq */ - desc->chip->ack(irq); + if (desc->chip->ack) + desc->chip->ack(irq); desc = irq_remap_to_desc(irq, desc); /* Mark the IRQ currently in progress.*/ -- GitLab From 4d9842776a23e52ec4c60e0a79f5e1bbe91e463e Mon Sep 17 00:00:00 2001 From: Gregory Haskins Date: Mon, 29 Dec 2008 09:39:49 -0500 Subject: [PATCH 0031/4982] sched: cleanup inc/dec_rt_tasks Move some common definitions up to the function prologe to simplify the body logic. Signed-off-by: Gregory Haskins --- kernel/sched_rt.c | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 1bbd9901401..0a527723345 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -550,30 +550,28 @@ static void update_curr_rt(struct rq *rq) static inline void inc_rt_tasks(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) { - WARN_ON(!rt_prio(rt_se_prio(rt_se))); - rt_rq->rt_nr_running++; -#if defined CONFIG_SMP || defined CONFIG_RT_GROUP_SCHED - if (rt_se_prio(rt_se) < rt_rq->highest_prio) { + int prio = rt_se_prio(rt_se); #ifdef CONFIG_SMP - struct rq *rq = rq_of_rt_rq(rt_rq); + struct rq *rq = rq_of_rt_rq(rt_rq); #endif - rt_rq->highest_prio = rt_se_prio(rt_se); + WARN_ON(!rt_prio(prio)); + rt_rq->rt_nr_running++; +#if defined CONFIG_SMP || defined CONFIG_RT_GROUP_SCHED + if (prio < rt_rq->highest_prio) { + + rt_rq->highest_prio = prio; #ifdef CONFIG_SMP if (rq->online) - cpupri_set(&rq->rd->cpupri, rq->cpu, - rt_se_prio(rt_se)); + cpupri_set(&rq->rd->cpupri, rq->cpu, prio); #endif } #endif #ifdef CONFIG_SMP - if (rt_se->nr_cpus_allowed > 1) { - struct rq *rq = rq_of_rt_rq(rt_rq); - + if (rt_se->nr_cpus_allowed > 1) rq->rt.rt_nr_migratory++; - } - update_rt_migration(rq_of_rt_rq(rt_rq)); + update_rt_migration(rq); #endif #ifdef CONFIG_RT_GROUP_SCHED if (rt_se_boosted(rt_se)) @@ -590,6 +588,7 @@ static inline void dec_rt_tasks(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) { #ifdef CONFIG_SMP + struct rq *rq = rq_of_rt_rq(rt_rq); int highest_prio = rt_rq->highest_prio; #endif @@ -611,20 +610,13 @@ void dec_rt_tasks(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) rt_rq->highest_prio = MAX_RT_PRIO; #endif #ifdef CONFIG_SMP - if (rt_se->nr_cpus_allowed > 1) { - struct rq *rq = rq_of_rt_rq(rt_rq); + if (rt_se->nr_cpus_allowed > 1) rq->rt.rt_nr_migratory--; - } - if (rt_rq->highest_prio != highest_prio) { - struct rq *rq = rq_of_rt_rq(rt_rq); - - if (rq->online) - cpupri_set(&rq->rd->cpupri, rq->cpu, - rt_rq->highest_prio); - } + if (rq->online && rt_rq->highest_prio != highest_prio) + cpupri_set(&rq->rd->cpupri, rq->cpu, rt_rq->highest_prio); - update_rt_migration(rq_of_rt_rq(rt_rq)); + update_rt_migration(rq); #endif /* CONFIG_SMP */ #ifdef CONFIG_RT_GROUP_SCHED if (rt_se_boosted(rt_se)) -- GitLab From e864c499d9e57805ae1f9e7ea404dd223759cd53 Mon Sep 17 00:00:00 2001 From: Gregory Haskins Date: Mon, 29 Dec 2008 09:39:49 -0500 Subject: [PATCH 0032/4982] sched: track the next-highest priority on each runqueue We will use this later in the series to reduce the amount of rq-lock contention during a pull operation Signed-off-by: Gregory Haskins --- kernel/sched.c | 8 +++-- kernel/sched_rt.c | 81 +++++++++++++++++++++++++++++++++++------------ 2 files changed, 67 insertions(+), 22 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 756d981d91a..7729f9a45a8 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -463,7 +463,10 @@ struct rt_rq { struct rt_prio_array active; unsigned long rt_nr_running; #if defined CONFIG_SMP || defined CONFIG_RT_GROUP_SCHED - int highest_prio; /* highest queued rt task prio */ + struct { + int curr; /* highest queued rt task prio */ + int next; /* next highest */ + } highest_prio; #endif #ifdef CONFIG_SMP unsigned long rt_nr_migratory; @@ -8169,7 +8172,8 @@ static void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq) __set_bit(MAX_RT_PRIO, array->bitmap); #if defined CONFIG_SMP || defined CONFIG_RT_GROUP_SCHED - rt_rq->highest_prio = MAX_RT_PRIO; + rt_rq->highest_prio.curr = MAX_RT_PRIO; + rt_rq->highest_prio.next = MAX_RT_PRIO; #endif #ifdef CONFIG_SMP rt_rq->rt_nr_migratory = 0; diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 0a527723345..ad36d723223 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -108,7 +108,7 @@ static void sched_rt_rq_enqueue(struct rt_rq *rt_rq) if (rt_rq->rt_nr_running) { if (rt_se && !on_rt_rq(rt_se)) enqueue_rt_entity(rt_se); - if (rt_rq->highest_prio < curr->prio) + if (rt_rq->highest_prio.curr < curr->prio) resched_task(curr); } } @@ -473,7 +473,7 @@ static inline int rt_se_prio(struct sched_rt_entity *rt_se) struct rt_rq *rt_rq = group_rt_rq(rt_se); if (rt_rq) - return rt_rq->highest_prio; + return rt_rq->highest_prio.curr; #endif return rt_task_of(rt_se)->prio; @@ -547,6 +547,21 @@ static void update_curr_rt(struct rq *rq) } } +#if defined CONFIG_SMP || defined CONFIG_RT_GROUP_SCHED + +static struct task_struct *pick_next_highest_task_rt(struct rq *rq, int cpu); + +static inline int next_prio(struct rq *rq) +{ + struct task_struct *next = pick_next_highest_task_rt(rq, rq->cpu); + + if (next && rt_prio(next->prio)) + return next->prio; + else + return MAX_RT_PRIO; +} +#endif + static inline void inc_rt_tasks(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) { @@ -558,14 +573,32 @@ void inc_rt_tasks(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) WARN_ON(!rt_prio(prio)); rt_rq->rt_nr_running++; #if defined CONFIG_SMP || defined CONFIG_RT_GROUP_SCHED - if (prio < rt_rq->highest_prio) { + if (prio < rt_rq->highest_prio.curr) { - rt_rq->highest_prio = prio; + /* + * If the new task is higher in priority than anything on the + * run-queue, we have a new high that must be published to + * the world. We also know that the previous high becomes + * our next-highest. + */ + rt_rq->highest_prio.next = rt_rq->highest_prio.curr; + rt_rq->highest_prio.curr = prio; #ifdef CONFIG_SMP if (rq->online) cpupri_set(&rq->rd->cpupri, rq->cpu, prio); #endif - } + } else if (prio == rt_rq->highest_prio.curr) + /* + * If the next task is equal in priority to the highest on + * the run-queue, then we implicitly know that the next highest + * task cannot be any lower than current + */ + rt_rq->highest_prio.next = prio; + else if (prio < rt_rq->highest_prio.next) + /* + * Otherwise, we need to recompute next-highest + */ + rt_rq->highest_prio.next = next_prio(rq); #endif #ifdef CONFIG_SMP if (rt_se->nr_cpus_allowed > 1) @@ -589,7 +622,7 @@ void dec_rt_tasks(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) { #ifdef CONFIG_SMP struct rq *rq = rq_of_rt_rq(rt_rq); - int highest_prio = rt_rq->highest_prio; + int highest_prio = rt_rq->highest_prio.curr; #endif WARN_ON(!rt_prio(rt_se_prio(rt_se))); @@ -597,24 +630,32 @@ void dec_rt_tasks(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) rt_rq->rt_nr_running--; #if defined CONFIG_SMP || defined CONFIG_RT_GROUP_SCHED if (rt_rq->rt_nr_running) { - struct rt_prio_array *array; + int prio = rt_se_prio(rt_se); + + WARN_ON(prio < rt_rq->highest_prio.curr); - WARN_ON(rt_se_prio(rt_se) < rt_rq->highest_prio); - if (rt_se_prio(rt_se) == rt_rq->highest_prio) { - /* recalculate */ - array = &rt_rq->active; - rt_rq->highest_prio = + /* + * This may have been our highest or next-highest priority + * task and therefore we may have some recomputation to do + */ + if (prio == rt_rq->highest_prio.curr) { + struct rt_prio_array *array = &rt_rq->active; + + rt_rq->highest_prio.curr = sched_find_first_bit(array->bitmap); - } /* otherwise leave rq->highest prio alone */ + } + + if (prio <= rt_rq->highest_prio.next) + rt_rq->highest_prio.next = next_prio(rq); } else - rt_rq->highest_prio = MAX_RT_PRIO; + rt_rq->highest_prio.curr = MAX_RT_PRIO; #endif #ifdef CONFIG_SMP if (rt_se->nr_cpus_allowed > 1) rq->rt.rt_nr_migratory--; - if (rq->online && rt_rq->highest_prio != highest_prio) - cpupri_set(&rq->rd->cpupri, rq->cpu, rt_rq->highest_prio); + if (rq->online && rt_rq->highest_prio.curr != highest_prio) + cpupri_set(&rq->rd->cpupri, rq->cpu, rt_rq->highest_prio.curr); update_rt_migration(rq); #endif /* CONFIG_SMP */ @@ -1064,7 +1105,7 @@ static struct rq *find_lock_lowest_rq(struct task_struct *task, struct rq *rq) } /* If this rq is still suitable use it. */ - if (lowest_rq->rt.highest_prio > task->prio) + if (lowest_rq->rt.highest_prio.curr > task->prio) break; /* try again */ @@ -1252,7 +1293,7 @@ static int pull_rt_task(struct rq *this_rq) static void pre_schedule_rt(struct rq *rq, struct task_struct *prev) { /* Try to pull RT tasks here if we lower this rq's prio */ - if (unlikely(rt_task(prev)) && rq->rt.highest_prio > prev->prio) + if (unlikely(rt_task(prev)) && rq->rt.highest_prio.curr > prev->prio) pull_rt_task(rq); } @@ -1338,7 +1379,7 @@ static void rq_online_rt(struct rq *rq) __enable_runtime(rq); - cpupri_set(&rq->rd->cpupri, rq->cpu, rq->rt.highest_prio); + cpupri_set(&rq->rd->cpupri, rq->cpu, rq->rt.highest_prio.curr); } /* Assumes rq->lock is held */ @@ -1429,7 +1470,7 @@ static void prio_changed_rt(struct rq *rq, struct task_struct *p, * can release the rq lock and p could migrate. * Only reschedule if p is still on the same runqueue. */ - if (p->prio > rq->rt.highest_prio && rq->curr == p) + if (p->prio > rq->rt.highest_prio.curr && rq->curr == p) resched_task(p); #else /* For UP simply resched on drop of prio */ -- GitLab From a8728944efe23417e38bf22063f06d9d8ee21d59 Mon Sep 17 00:00:00 2001 From: Gregory Haskins Date: Mon, 29 Dec 2008 09:39:49 -0500 Subject: [PATCH 0033/4982] sched: use highest_prio.curr for pull threshold highest_prio.curr is actually a more accurate way to keep track of the pull_rt_task() threshold since it is always up to date, even if the "next" task migrates during double_lock. Therefore, stop looking at the "next" task object and simply use the highest_prio.curr. Signed-off-by: Gregory Haskins --- kernel/sched_rt.c | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index ad36d723223..f8fb3edadca 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -1207,14 +1207,12 @@ static void push_rt_tasks(struct rq *rq) static int pull_rt_task(struct rq *this_rq) { int this_cpu = this_rq->cpu, ret = 0, cpu; - struct task_struct *p, *next; + struct task_struct *p; struct rq *src_rq; if (likely(!rt_overloaded(this_rq))) return 0; - next = pick_next_task_rt(this_rq); - for_each_cpu(cpu, this_rq->rd->rto_mask) { if (this_cpu == cpu) continue; @@ -1223,17 +1221,9 @@ static int pull_rt_task(struct rq *this_rq) /* * We can potentially drop this_rq's lock in * double_lock_balance, and another CPU could - * steal our next task - hence we must cause - * the caller to recalculate the next task - * in that case: + * alter this_rq */ - if (double_lock_balance(this_rq, src_rq)) { - struct task_struct *old_next = next; - - next = pick_next_task_rt(this_rq); - if (next != old_next) - ret = 1; - } + double_lock_balance(this_rq, src_rq); /* * Are there still pullable RT tasks? @@ -1247,7 +1237,7 @@ static int pull_rt_task(struct rq *this_rq) * Do we have an RT task that preempts * the to-be-scheduled task? */ - if (p && (!next || (p->prio < next->prio))) { + if (p && (p->prio < this_rq->rt.highest_prio.curr)) { WARN_ON(p == src_rq->curr); WARN_ON(!p->se.on_rq); @@ -1257,12 +1247,9 @@ static int pull_rt_task(struct rq *this_rq) * This is just that p is wakeing up and hasn't * had a chance to schedule. We only pull * p if it is lower in priority than the - * current task on the run queue or - * this_rq next task is lower in prio than - * the current task on that rq. + * current task on the run queue */ - if (p->prio < src_rq->curr->prio || - (next && next->prio < src_rq->curr->prio)) + if (p->prio < src_rq->curr->prio) goto skip; ret = 1; @@ -1275,13 +1262,7 @@ static int pull_rt_task(struct rq *this_rq) * case there's an even higher prio task * in another runqueue. (low likelyhood * but possible) - * - * Update next so that we won't pick a task - * on another cpu with a priority lower (or equal) - * than the one we just picked. */ - next = p; - } skip: double_unlock_balance(this_rq, src_rq); -- GitLab From 74ab8e4f6412c0b2d730fe5de28dc21de8b92c01 Mon Sep 17 00:00:00 2001 From: Gregory Haskins Date: Mon, 29 Dec 2008 09:39:50 -0500 Subject: [PATCH 0034/4982] sched: use highest_prio.next to optimize pull operations We currently take the rq->lock for every cpu in an overload state during pull_rt_tasks(). However, we now have enough information via the highest_prio.[curr|next] fields to determine if there is any tasks of interest to warrant the overhead of the rq->lock, before we actually take it. So we use this information to reduce lock contention during the pull for the case where the source-rq doesnt have tasks that preempt the current task. Signed-off-by: Gregory Haskins --- kernel/sched_rt.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index f8fb3edadca..d047f288c41 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -1218,6 +1218,18 @@ static int pull_rt_task(struct rq *this_rq) continue; src_rq = cpu_rq(cpu); + + /* + * Don't bother taking the src_rq->lock if the next highest + * task is known to be lower-priority than our current task. + * This may look racy, but if this value is about to go + * logically higher, the src_rq will push this task away. + * And if its going logically lower, we do not care + */ + if (src_rq->rt.highest_prio.next >= + this_rq->rt.highest_prio.curr) + continue; + /* * We can potentially drop this_rq's lock in * double_lock_balance, and another CPU could -- GitLab From 777c2f389e463428fd7e2871051a84d7fe84b172 Mon Sep 17 00:00:00 2001 From: Gregory Haskins Date: Mon, 29 Dec 2008 09:39:50 -0500 Subject: [PATCH 0035/4982] sched: only try to push a task on wakeup if it is migratable There is no sense in wasting time trying to push a task away that cannot move anywhere else. We gain no benefit from trying to push other tasks at this point, so if the task being woken up is non migratable, just skip the whole operation. This reduces overhead in the wakeup path for certain tasks. Signed-off-by: Gregory Haskins --- kernel/sched_rt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index d047f288c41..8d33843cb2c 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -1314,7 +1314,8 @@ static void task_wake_up_rt(struct rq *rq, struct task_struct *p) { if (!task_running(rq, p) && !test_tsk_need_resched(rq->curr) && - rq->rt.overloaded) + rq->rt.overloaded && + p->rt.nr_cpus_allowed > 1) push_rt_tasks(rq); } -- GitLab From 7e96fa5875d4a9be18d74d3ca7b90518d05bc426 Mon Sep 17 00:00:00 2001 From: Gregory Haskins Date: Mon, 29 Dec 2008 09:39:50 -0500 Subject: [PATCH 0036/4982] sched: pull only one task during NEWIDLE balancing to limit critical section git-id c4acb2c0669c5c5c9b28e9d02a34b5c67edf7092 attempted to limit newidle critical section length by stopping after at least one task was moved. Further investigation has shown that there are other paths nested further inside the algorithm which still remain that allow long latencies to occur with newidle balancing. This patch applies the same technique inside balance_tasks() to limit the duration of this optional balancing operation. Signed-off-by: Gregory Haskins CC: Nick Piggin --- kernel/sched.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/kernel/sched.c b/kernel/sched.c index 7729f9a45a8..94d9a6c5ff9 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2984,6 +2984,16 @@ next: pulled++; rem_load_move -= p->se.load.weight; +#ifdef CONFIG_PREEMPT + /* + * NEWIDLE balancing is a source of latency, so preemptible kernels + * will stop after the first task is pulled to minimize the critical + * section. + */ + if (idle == CPU_NEWLY_IDLE) + goto out; +#endif + /* * We only want to steal up to the prescribed amount of weighted load. */ @@ -3030,9 +3040,15 @@ static int move_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest, sd, idle, all_pinned, &this_best_prio); class = class->next; +#ifdef CONFIG_PREEMPT + /* + * NEWIDLE balancing is a source of latency, so preemptible + * kernels will stop after the first task is pulled to minimize + * the critical section. + */ if (idle == CPU_NEWLY_IDLE && this_rq->nr_running) break; - +#endif } while (class && max_load_move > total_load_moved); return total_load_moved > 0; -- GitLab From 8f45e2b516201d1bf681e6026fa5276385def565 Mon Sep 17 00:00:00 2001 From: Gregory Haskins Date: Mon, 29 Dec 2008 09:39:51 -0500 Subject: [PATCH 0037/4982] sched: make double-lock-balance fair double_lock balance() currently favors logically lower cpus since they often do not have to release their own lock to acquire a second lock. The result is that logically higher cpus can get starved when there is a lot of pressure on the RQs. This can result in higher latencies on higher cpu-ids. This patch makes the algorithm more fair by forcing all paths to have to release both locks before acquiring them again. Since callsites to double_lock_balance already consider it a potential preemption/reschedule point, they have the proper logic to recheck for atomicity violations. Signed-off-by: Gregory Haskins --- kernel/sched.c | 51 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 94d9a6c5ff9..8fca364f359 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1608,21 +1608,42 @@ static inline void update_shares_locked(struct rq *rq, struct sched_domain *sd) #endif +#ifdef CONFIG_PREEMPT + /* - * double_lock_balance - lock the busiest runqueue, this_rq is locked already. + * fair double_lock_balance: Safely acquires both rq->locks in a fair + * way at the expense of forcing extra atomic operations in all + * invocations. This assures that the double_lock is acquired using the + * same underlying policy as the spinlock_t on this architecture, which + * reduces latency compared to the unfair variant below. However, it + * also adds more overhead and therefore may reduce throughput. */ -static int double_lock_balance(struct rq *this_rq, struct rq *busiest) +static inline int _double_lock_balance(struct rq *this_rq, struct rq *busiest) + __releases(this_rq->lock) + __acquires(busiest->lock) + __acquires(this_rq->lock) +{ + spin_unlock(&this_rq->lock); + double_rq_lock(this_rq, busiest); + + return 1; +} + +#else +/* + * Unfair double_lock_balance: Optimizes throughput at the expense of + * latency by eliminating extra atomic operations when the locks are + * already in proper order on entry. This favors lower cpu-ids and will + * grant the double lock to lower cpus over higher ids under contention, + * regardless of entry order into the function. + */ +static int _double_lock_balance(struct rq *this_rq, struct rq *busiest) __releases(this_rq->lock) __acquires(busiest->lock) __acquires(this_rq->lock) { int ret = 0; - if (unlikely(!irqs_disabled())) { - /* printk() doesn't work good under rq->lock */ - spin_unlock(&this_rq->lock); - BUG_ON(1); - } if (unlikely(!spin_trylock(&busiest->lock))) { if (busiest < this_rq) { spin_unlock(&this_rq->lock); @@ -1635,6 +1656,22 @@ static int double_lock_balance(struct rq *this_rq, struct rq *busiest) return ret; } +#endif /* CONFIG_PREEMPT */ + +/* + * double_lock_balance - lock the busiest runqueue, this_rq is locked already. + */ +static int double_lock_balance(struct rq *this_rq, struct rq *busiest) +{ + if (unlikely(!irqs_disabled())) { + /* printk() doesn't work good under rq->lock */ + spin_unlock(&this_rq->lock); + BUG_ON(1); + } + + return _double_lock_balance(this_rq, busiest); +} + static inline void double_unlock_balance(struct rq *this_rq, struct rq *busiest) __releases(busiest->lock) { -- GitLab From 967fc04671feea4dbf780c9e55a0bc8fcf68a14e Mon Sep 17 00:00:00 2001 From: Gregory Haskins Date: Mon, 29 Dec 2008 09:39:52 -0500 Subject: [PATCH 0038/4982] sched: add sched_class->needs_post_schedule() member We currently run class->post_schedule() outside of the rq->lock, which means that we need to test for the need to post_schedule outside of the lock to avoid a forced reacquistion. This is currently not a problem as we only look at rq->rt.overloaded. However, we want to enhance this going forward to look at more state to reduce the need to post_schedule to a bare minimum set. Therefore, we introduce a new member-func called needs_post_schedule() which tests for the post_schedule condtion without actually performing the work. Therefore it is safe to call this function before the rq->lock is released, because we are guaranteed not to drop the lock at an intermediate point (such as what post_schedule() may do). We will use this later in the series [ rostedt: removed paranoid BUG_ON ] Signed-off-by: Gregory Haskins --- include/linux/sched.h | 1 + kernel/sched.c | 8 +++++++- kernel/sched_rt.c | 24 ++++++++++++++---------- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index e5f928a079e..836a86c32a6 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1012,6 +1012,7 @@ struct sched_class { struct rq *busiest, struct sched_domain *sd, enum cpu_idle_type idle); void (*pre_schedule) (struct rq *this_rq, struct task_struct *task); + int (*needs_post_schedule) (struct rq *this_rq); void (*post_schedule) (struct rq *this_rq); void (*task_wake_up) (struct rq *this_rq, struct task_struct *task); diff --git a/kernel/sched.c b/kernel/sched.c index 8fca364f359..3acbad8991a 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2621,6 +2621,12 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev) { struct mm_struct *mm = rq->prev_mm; long prev_state; +#ifdef CONFIG_SMP + int post_schedule = 0; + + if (current->sched_class->needs_post_schedule) + post_schedule = current->sched_class->needs_post_schedule(rq); +#endif rq->prev_mm = NULL; @@ -2639,7 +2645,7 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev) finish_arch_switch(prev); finish_lock_switch(rq, prev); #ifdef CONFIG_SMP - if (current->sched_class->post_schedule) + if (post_schedule) current->sched_class->post_schedule(rq); #endif diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 8d33843cb2c..b0b6ea4ed67 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -1290,20 +1290,23 @@ static void pre_schedule_rt(struct rq *rq, struct task_struct *prev) pull_rt_task(rq); } +/* + * assumes rq->lock is held + */ +static int needs_post_schedule_rt(struct rq *rq) +{ + return rq->rt.overloaded ? 1 : 0; +} + static void post_schedule_rt(struct rq *rq) { /* - * If we have more than one rt_task queued, then - * see if we can push the other rt_tasks off to other CPUS. - * Note we may release the rq lock, and since - * the lock was owned by prev, we need to release it - * first via finish_lock_switch and then reaquire it here. + * This is only called if needs_post_schedule_rt() indicates that + * we need to push tasks away */ - if (unlikely(rq->rt.overloaded)) { - spin_lock_irq(&rq->lock); - push_rt_tasks(rq); - spin_unlock_irq(&rq->lock); - } + spin_lock_irq(&rq->lock); + push_rt_tasks(rq); + spin_unlock_irq(&rq->lock); } /* @@ -1557,6 +1560,7 @@ static const struct sched_class rt_sched_class = { .rq_online = rq_online_rt, .rq_offline = rq_offline_rt, .pre_schedule = pre_schedule_rt, + .needs_post_schedule = needs_post_schedule_rt, .post_schedule = post_schedule_rt, .task_wake_up = task_wake_up_rt, .switched_from = switched_from_rt, -- GitLab From 4075134e40804821f90866d7de56802e4dcecb1e Mon Sep 17 00:00:00 2001 From: Gregory Haskins Date: Mon, 29 Dec 2008 09:39:53 -0500 Subject: [PATCH 0039/4982] plist: fix PLIST_NODE_INIT to work with debug enabled It seems that PLIST_NODE_INIT breaks if used and DEBUG_PI_LIST is defined. Since there are no current users of PLIST_NODE_INIT, this has gone undetected. This patch fixes the build issue that enables the DEBUG_PI_LIST later in the series when we use it in init_task.h Signed-off-by: Gregory Haskins --- include/linux/plist.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/include/linux/plist.h b/include/linux/plist.h index 85de2f05587..45926d77d6a 100644 --- a/include/linux/plist.h +++ b/include/linux/plist.h @@ -96,6 +96,10 @@ struct plist_node { # define PLIST_HEAD_LOCK_INIT(_lock) #endif +#define _PLIST_HEAD_INIT(head) \ + .prio_list = LIST_HEAD_INIT((head).prio_list), \ + .node_list = LIST_HEAD_INIT((head).node_list) + /** * PLIST_HEAD_INIT - static struct plist_head initializer * @head: struct plist_head variable name @@ -103,8 +107,7 @@ struct plist_node { */ #define PLIST_HEAD_INIT(head, _lock) \ { \ - .prio_list = LIST_HEAD_INIT((head).prio_list), \ - .node_list = LIST_HEAD_INIT((head).node_list), \ + _PLIST_HEAD_INIT(head), \ PLIST_HEAD_LOCK_INIT(&(_lock)) \ } @@ -116,7 +119,7 @@ struct plist_node { #define PLIST_NODE_INIT(node, __prio) \ { \ .prio = (__prio), \ - .plist = PLIST_HEAD_INIT((node).plist, NULL), \ + .plist = { _PLIST_HEAD_INIT((node).plist) }, \ } /** -- GitLab From 917b627d4d981dc614519d7b34ea31a976b14e12 Mon Sep 17 00:00:00 2001 From: Gregory Haskins Date: Mon, 29 Dec 2008 09:39:53 -0500 Subject: [PATCH 0040/4982] sched: create "pushable_tasks" list to limit pushing to one attempt The RT scheduler employs a "push/pull" design to actively balance tasks within the system (on a per disjoint cpuset basis). When a task is awoken, it is immediately determined if there are any lower priority cpus which should be preempted. This is opposed to the way normal SCHED_OTHER tasks behave, which will wait for a periodic rebalancing operation to occur before spreading out load. When a particular RQ has more than 1 active RT task, it is said to be in an "overloaded" state. Once this occurs, the system enters the active balancing mode, where it will try to push the task away, or persuade a different cpu to pull it over. The system will stay in this state until the system falls back below the <= 1 queued RT task per RQ. However, the current implementation suffers from a limitation in the push logic. Once overloaded, all tasks (other than current) on the RQ are analyzed on every push operation, even if it was previously unpushable (due to affinity, etc). Whats more, the operation stops at the first task that is unpushable and will not look at items lower in the queue. This causes two problems: 1) We can have the same tasks analyzed over and over again during each push, which extends out the fast path in the scheduler for no gain. Consider a RQ that has dozens of tasks that are bound to a core. Each one of those tasks will be encountered and skipped for each push operation while they are queued. 2) There may be lower-priority tasks under the unpushable task that could have been successfully pushed, but will never be considered until either the unpushable task is cleared, or a pull operation succeeds. The net result is a potential latency source for mid priority tasks. This patch aims to rectify these two conditions by introducing a new priority sorted list: "pushable_tasks". A task is added to the list each time a task is activated or preempted. It is removed from the list any time it is deactivated, made current, or fails to push. This works because a task only needs to be attempted to push once. After an initial failure to push, the other cpus will eventually try to pull the task when the conditions are proper. This also solves the problem that we don't completely analyze all tasks due to encountering an unpushable tasks. Now every task will have a push attempted (when appropriate). This reduces latency both by shorting the critical section of the rq->lock for certain workloads, and by making sure the algorithm considers all eligible tasks in the system. [ rostedt: added a couple more BUG_ONs ] Signed-off-by: Gregory Haskins Acked-by: Steven Rostedt --- include/linux/init_task.h | 1 + include/linux/sched.h | 1 + kernel/sched.c | 4 ++ kernel/sched_rt.c | 119 ++++++++++++++++++++++++++++++++------ 4 files changed, 107 insertions(+), 18 deletions(-) diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 23fd8909b9e..6851225f44a 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -140,6 +140,7 @@ extern struct group_info init_groups; .nr_cpus_allowed = NR_CPUS, \ }, \ .tasks = LIST_HEAD_INIT(tsk.tasks), \ + .pushable_tasks = PLIST_NODE_INIT(tsk.pushable_tasks, MAX_PRIO), \ .ptraced = LIST_HEAD_INIT(tsk.ptraced), \ .ptrace_entry = LIST_HEAD_INIT(tsk.ptrace_entry), \ .real_parent = &tsk, \ diff --git a/include/linux/sched.h b/include/linux/sched.h index 836a86c32a6..440cabb2d43 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1179,6 +1179,7 @@ struct task_struct { #endif struct list_head tasks; + struct plist_node pushable_tasks; struct mm_struct *mm, *active_mm; diff --git a/kernel/sched.c b/kernel/sched.c index 3acbad8991a..24ab80c2876 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -471,6 +471,7 @@ struct rt_rq { #ifdef CONFIG_SMP unsigned long rt_nr_migratory; int overloaded; + struct plist_head pushable_tasks; #endif int rt_throttled; u64 rt_time; @@ -2481,6 +2482,8 @@ void sched_fork(struct task_struct *p, int clone_flags) /* Want to start with kernel preemption disabled. */ task_thread_info(p)->preempt_count = 1; #endif + plist_node_init(&p->pushable_tasks, MAX_PRIO); + put_cpu(); } @@ -8237,6 +8240,7 @@ static void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq) #ifdef CONFIG_SMP rt_rq->rt_nr_migratory = 0; rt_rq->overloaded = 0; + plist_head_init(&rq->rt.pushable_tasks, &rq->lock); #endif rt_rq->rt_time = 0; diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index b0b6ea4ed67..fe9da6084c8 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -49,6 +49,24 @@ static void update_rt_migration(struct rq *rq) rq->rt.overloaded = 0; } } + +static void enqueue_pushable_task(struct rq *rq, struct task_struct *p) +{ + plist_del(&p->pushable_tasks, &rq->rt.pushable_tasks); + plist_node_init(&p->pushable_tasks, p->prio); + plist_add(&p->pushable_tasks, &rq->rt.pushable_tasks); +} + +static void dequeue_pushable_task(struct rq *rq, struct task_struct *p) +{ + plist_del(&p->pushable_tasks, &rq->rt.pushable_tasks); +} + +#else + +#define enqueue_pushable_task(rq, p) do { } while (0) +#define dequeue_pushable_task(rq, p) do { } while (0) + #endif /* CONFIG_SMP */ static inline struct task_struct *rt_task_of(struct sched_rt_entity *rt_se) @@ -751,6 +769,9 @@ static void enqueue_task_rt(struct rq *rq, struct task_struct *p, int wakeup) enqueue_rt_entity(rt_se); + if (!task_current(rq, p) && p->rt.nr_cpus_allowed > 1) + enqueue_pushable_task(rq, p); + inc_cpu_load(rq, p->se.load.weight); } @@ -761,6 +782,8 @@ static void dequeue_task_rt(struct rq *rq, struct task_struct *p, int sleep) update_curr_rt(rq); dequeue_rt_entity(rt_se); + dequeue_pushable_task(rq, p); + dec_cpu_load(rq, p->se.load.weight); } @@ -911,7 +934,7 @@ static struct sched_rt_entity *pick_next_rt_entity(struct rq *rq, return next; } -static struct task_struct *pick_next_task_rt(struct rq *rq) +static struct task_struct *_pick_next_task_rt(struct rq *rq) { struct sched_rt_entity *rt_se; struct task_struct *p; @@ -933,6 +956,18 @@ static struct task_struct *pick_next_task_rt(struct rq *rq) p = rt_task_of(rt_se); p->se.exec_start = rq->clock; + + return p; +} + +static struct task_struct *pick_next_task_rt(struct rq *rq) +{ + struct task_struct *p = _pick_next_task_rt(rq); + + /* The running task is never eligible for pushing */ + if (p) + dequeue_pushable_task(rq, p); + return p; } @@ -940,6 +975,13 @@ static void put_prev_task_rt(struct rq *rq, struct task_struct *p) { update_curr_rt(rq); p->se.exec_start = 0; + + /* + * The previous task needs to be made eligible for pushing + * if it is still active + */ + if (p->se.on_rq && p->rt.nr_cpus_allowed > 1) + enqueue_pushable_task(rq, p); } #ifdef CONFIG_SMP @@ -1116,6 +1158,31 @@ static struct rq *find_lock_lowest_rq(struct task_struct *task, struct rq *rq) return lowest_rq; } +static inline int has_pushable_tasks(struct rq *rq) +{ + return !plist_head_empty(&rq->rt.pushable_tasks); +} + +static struct task_struct *pick_next_pushable_task(struct rq *rq) +{ + struct task_struct *p; + + if (!has_pushable_tasks(rq)) + return NULL; + + p = plist_first_entry(&rq->rt.pushable_tasks, + struct task_struct, pushable_tasks); + + BUG_ON(rq->cpu != task_cpu(p)); + BUG_ON(task_current(rq, p)); + BUG_ON(p->rt.nr_cpus_allowed <= 1); + + BUG_ON(!p->se.on_rq); + BUG_ON(!rt_task(p)); + + return p; +} + /* * If the current CPU has more than one RT task, see if the non * running task can migrate over to a CPU that is running a task @@ -1125,13 +1192,12 @@ static int push_rt_task(struct rq *rq) { struct task_struct *next_task; struct rq *lowest_rq; - int ret = 0; int paranoid = RT_MAX_TRIES; if (!rq->rt.overloaded) return 0; - next_task = pick_next_highest_task_rt(rq, -1); + next_task = pick_next_pushable_task(rq); if (!next_task) return 0; @@ -1163,12 +1229,19 @@ static int push_rt_task(struct rq *rq) * so it is possible that next_task has changed. * If it has, then try again. */ - task = pick_next_highest_task_rt(rq, -1); + task = pick_next_pushable_task(rq); if (unlikely(task != next_task) && task && paranoid--) { put_task_struct(next_task); next_task = task; goto retry; } + + /* + * Once we have failed to push this task, we will not + * try again, since the other cpus will pull from us + * when they are ready + */ + dequeue_pushable_task(rq, next_task); goto out; } @@ -1180,23 +1253,12 @@ static int push_rt_task(struct rq *rq) double_unlock_balance(rq, lowest_rq); - ret = 1; out: put_task_struct(next_task); - return ret; + return 1; } -/* - * TODO: Currently we just use the second highest prio task on - * the queue, and stop when it can't migrate (or there's - * no more RT tasks). There may be a case where a lower - * priority RT task has a different affinity than the - * higher RT task. In this case the lower RT task could - * possibly be able to migrate where as the higher priority - * RT task could not. We currently ignore this issue. - * Enhancements are welcome! - */ static void push_rt_tasks(struct rq *rq) { /* push_rt_task will return true if it moved an RT */ @@ -1295,7 +1357,7 @@ static void pre_schedule_rt(struct rq *rq, struct task_struct *prev) */ static int needs_post_schedule_rt(struct rq *rq) { - return rq->rt.overloaded ? 1 : 0; + return has_pushable_tasks(rq); } static void post_schedule_rt(struct rq *rq) @@ -1317,7 +1379,7 @@ static void task_wake_up_rt(struct rq *rq, struct task_struct *p) { if (!task_running(rq, p) && !test_tsk_need_resched(rq->curr) && - rq->rt.overloaded && + has_pushable_tasks(rq) && p->rt.nr_cpus_allowed > 1) push_rt_tasks(rq); } @@ -1354,6 +1416,24 @@ static void set_cpus_allowed_rt(struct task_struct *p, if (p->se.on_rq && (weight != p->rt.nr_cpus_allowed)) { struct rq *rq = task_rq(p); + if (!task_current(rq, p)) { + /* + * Make sure we dequeue this task from the pushable list + * before going further. It will either remain off of + * the list because we are no longer pushable, or it + * will be requeued. + */ + if (p->rt.nr_cpus_allowed > 1) + dequeue_pushable_task(rq, p); + + /* + * Requeue if our weight is changing and still > 1 + */ + if (weight > 1) + enqueue_pushable_task(rq, p); + + } + if ((p->rt.nr_cpus_allowed <= 1) && (weight > 1)) { rq->rt.rt_nr_migratory++; } else if ((p->rt.nr_cpus_allowed > 1) && (weight <= 1)) { @@ -1538,6 +1618,9 @@ static void set_curr_task_rt(struct rq *rq) struct task_struct *p = rq->curr; p->se.exec_start = rq->clock; + + /* The running task is never eligible for pushing */ + dequeue_pushable_task(rq, p); } static const struct sched_class rt_sched_class = { -- GitLab From 1563513d34ed4b12ef32bc2adde4a53ce05701a1 Mon Sep 17 00:00:00 2001 From: Gregory Haskins Date: Mon, 29 Dec 2008 09:39:53 -0500 Subject: [PATCH 0041/4982] RT: fix push_rt_task() to handle dequeue_pushable properly A panic was discovered by Chirag Jog where a BUG_ON sanity check in the new "pushable_task" logic would trigger a panic under certain circumstances: http://lkml.org/lkml/2008/9/25/189 Gilles Carry discovered that the root cause was attributed to the pushable_tasks list getting corrupted in the push_rt_task logic. This was the result of a dropped rq lock in double_lock_balance allowing a task in the process of being pushed to potentially migrate away, and thus corrupt the pushable_tasks() list. I traced back the problem as introduced by the pushable_tasks patch that went in recently. There is a "retry" path in push_rt_task() that actually had a compound conditional to decide whether to retry or exit. I missed the meaning behind the rationale for the virtual "if(!task) goto out;" portion of the compound statement and thus did not handle it properly. The new pushable_tasks logic actually creates three distinct conditions: 1) an untouched and unpushable task should be dequeued 2) a migrated task where more pushable tasks remain should be retried 3) a migrated task where no more pushable tasks exist should exit The original logic mushed (1) and (3) together, resulting in the system dequeuing a migrated task (against an unlocked foreign run-queue nonetheless). To fix this, we get rid of the notion of "paranoid" and we support the three unique conditions properly. The paranoid feature is no longer relevant with the new pushable logic (since pushable naturally limits the loop) anyway, so lets just remove it. Reported-By: Chirag Jog Found-by: Gilles Carry Signed-off-by: Gregory Haskins --- kernel/sched_rt.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index fe9da6084c8..64a8f0aa117 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -1192,7 +1192,6 @@ static int push_rt_task(struct rq *rq) { struct task_struct *next_task; struct rq *lowest_rq; - int paranoid = RT_MAX_TRIES; if (!rq->rt.overloaded) return 0; @@ -1226,23 +1225,34 @@ static int push_rt_task(struct rq *rq) struct task_struct *task; /* * find lock_lowest_rq releases rq->lock - * so it is possible that next_task has changed. - * If it has, then try again. + * so it is possible that next_task has migrated. + * + * We need to make sure that the task is still on the same + * run-queue and is also still the next task eligible for + * pushing. */ task = pick_next_pushable_task(rq); - if (unlikely(task != next_task) && task && paranoid--) { - put_task_struct(next_task); - next_task = task; - goto retry; + if (task_cpu(next_task) == rq->cpu && task == next_task) { + /* + * If we get here, the task hasnt moved at all, but + * it has failed to push. We will not try again, + * since the other cpus will pull from us when they + * are ready. + */ + dequeue_pushable_task(rq, next_task); + goto out; } + if (!task) + /* No more tasks, just exit */ + goto out; + /* - * Once we have failed to push this task, we will not - * try again, since the other cpus will pull from us - * when they are ready + * Something has shifted, try again. */ - dequeue_pushable_task(rq, next_task); - goto out; + put_task_struct(next_task); + next_task = task; + goto retry; } deactivate_task(rq, next_task, 0); -- GitLab From 5762ba1873b0bb9faa631aaa02f533c2b9837f82 Mon Sep 17 00:00:00 2001 From: Sebastien Dugue Date: Mon, 1 Dec 2008 14:09:07 +0100 Subject: [PATCH 0042/4982] hrtimers: allow the hot-unplugging of all cpus Impact: fix CPU hotplug hang on Power6 testbox On architectures that support offlining all cpus (at least powerpc/pseries), hot-unpluging the tick_do_timer_cpu can result in a system hang. This comes from the fact that if the cpu going down happens to be the cpu doing the tick, then as the tick_do_timer_cpu handover happens after the cpu is dead (via the CPU_DEAD notification), we're left without ticks, jiffies are frozen and any task relying on timers (msleep, ...) is stuck. That's particularly the case for the cpu looping in __cpu_die() waiting for the dying cpu to be dead. This patch addresses this by having the tick_do_timer_cpu handover happen earlier during the CPU_DYING notification. For this, a new clockevent notification type is introduced (CLOCK_EVT_NOTIFY_CPU_DYING) which is triggered in hrtimer_cpu_notify(). Signed-off-by: Sebastien Dugue Cc: Signed-off-by: Ingo Molnar --- include/linux/clockchips.h | 1 + kernel/hrtimer.c | 4 ++++ kernel/time/tick-common.c | 26 +++++++++++++++++++------- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h index ed3a5d473e5..c6de413c5dd 100644 --- a/include/linux/clockchips.h +++ b/include/linux/clockchips.h @@ -36,6 +36,7 @@ enum clock_event_nofitiers { CLOCK_EVT_NOTIFY_BROADCAST_EXIT, CLOCK_EVT_NOTIFY_SUSPEND, CLOCK_EVT_NOTIFY_RESUME, + CLOCK_EVT_NOTIFY_CPU_DYING, CLOCK_EVT_NOTIFY_CPU_DEAD, }; diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index c2a69b89ac6..61cb933395b 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -1609,6 +1609,10 @@ static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self, break; #ifdef CONFIG_HOTPLUG_CPU + case CPU_DYING: + case CPU_DYING_FROZEN: + clockevents_notify(CLOCK_EVT_NOTIFY_CPU_DYING, &scpu); + break; case CPU_DEAD: case CPU_DEAD_FROZEN: { diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index df12434b43c..457d281258e 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c @@ -273,6 +273,21 @@ out_bc: return ret; } +/* + * Transfer the do_timer job away from a dying cpu. + * + * Called with interrupts disabled. + */ +static void tick_handover_do_timer(int *cpup) +{ + if (*cpup == tick_do_timer_cpu) { + int cpu = first_cpu(cpu_online_map); + + tick_do_timer_cpu = (cpu != NR_CPUS) ? cpu : + TICK_DO_TIMER_NONE; + } +} + /* * Shutdown an event device on a given cpu: * @@ -297,13 +312,6 @@ static void tick_shutdown(unsigned int *cpup) clockevents_exchange_device(dev, NULL); td->evtdev = NULL; } - /* Transfer the do_timer job away from this cpu */ - if (*cpup == tick_do_timer_cpu) { - int cpu = first_cpu(cpu_online_map); - - tick_do_timer_cpu = (cpu != NR_CPUS) ? cpu : - TICK_DO_TIMER_NONE; - } spin_unlock_irqrestore(&tick_device_lock, flags); } @@ -357,6 +365,10 @@ static int tick_notify(struct notifier_block *nb, unsigned long reason, tick_broadcast_oneshot_control(reason); break; + case CLOCK_EVT_NOTIFY_CPU_DYING: + tick_handover_do_timer(dev); + break; + case CLOCK_EVT_NOTIFY_CPU_DEAD: tick_shutdown_broadcast_oneshot(dev); tick_shutdown_broadcast(dev); -- GitLab From bc6447b8e4fdb3306ee6381df9650a1a8aa57c5b Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 2 Jan 2009 12:18:53 +0000 Subject: [PATCH 0043/4982] [ARM] dma: make DMA_MODE_xxx reflect ISA DMA settings Signed-off-by: Russell King --- arch/arm/include/asm/dma.h | 13 ++++++++----- arch/arm/kernel/dma-isa.c | 13 +------------ 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/arch/arm/include/asm/dma.h b/arch/arm/include/asm/dma.h index c5557a650d1..59f59c6c79f 100644 --- a/arch/arm/include/asm/dma.h +++ b/arch/arm/include/asm/dma.h @@ -26,12 +26,15 @@ */ typedef unsigned int dmamode_t; -#define DMA_MODE_MASK 3 +/* + * The DMA modes reflect the settings for the ISA DMA controller + */ +#define DMA_MODE_MASK 0xcc -#define DMA_MODE_READ 0 -#define DMA_MODE_WRITE 1 -#define DMA_MODE_CASCADE 2 -#define DMA_AUTOINIT 4 +#define DMA_MODE_READ 0x44 +#define DMA_MODE_WRITE 0x48 +#define DMA_MODE_CASCADE 0xc0 +#define DMA_AUTOINIT 0x10 extern spinlock_t dma_spin_lock; diff --git a/arch/arm/kernel/dma-isa.c b/arch/arm/kernel/dma-isa.c index da02a7ff341..0e88e46fc73 100644 --- a/arch/arm/kernel/dma-isa.c +++ b/arch/arm/kernel/dma-isa.c @@ -24,11 +24,6 @@ #include #include -#define ISA_DMA_MODE_READ 0x44 -#define ISA_DMA_MODE_WRITE 0x48 -#define ISA_DMA_MODE_CASCADE 0xc0 -#define ISA_DMA_AUTOINIT 0x10 - #define ISA_DMA_MASK 0 #define ISA_DMA_MODE 1 #define ISA_DMA_CLRFF 2 @@ -67,20 +62,17 @@ static void isa_enable_dma(unsigned int chan, dma_t *dma) unsigned int mode; enum dma_data_direction direction; - mode = chan & 3; + mode = (chan & 3) | dma->dma_mode; switch (dma->dma_mode & DMA_MODE_MASK) { case DMA_MODE_READ: - mode |= ISA_DMA_MODE_READ; direction = DMA_FROM_DEVICE; break; case DMA_MODE_WRITE: - mode |= ISA_DMA_MODE_WRITE; direction = DMA_TO_DEVICE; break; case DMA_MODE_CASCADE: - mode |= ISA_DMA_MODE_CASCADE; direction = DMA_BIDIRECTIONAL; break; @@ -121,9 +113,6 @@ static void isa_enable_dma(unsigned int chan, dma_t *dma) outb(length, isa_dma_port[chan][ISA_DMA_COUNT]); outb(length >> 8, isa_dma_port[chan][ISA_DMA_COUNT]); - if (dma->dma_mode & DMA_AUTOINIT) - mode |= ISA_DMA_AUTOINIT; - outb(mode, isa_dma_port[chan][ISA_DMA_MODE]); dma->invalid = 0; } -- GitLab From 4e57ea9a2e8e807e20f64d5b53fbee2c7c9e87ae Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 2 Jan 2009 12:34:31 +0000 Subject: [PATCH 0044/4982] [ARM] dma: remove usage of dmamode_t from MXC platform support Signed-off-by: Russell King --- arch/arm/plat-mxc/dma-mx1-mx2.c | 6 +++--- arch/arm/plat-mxc/include/mach/dma-mx1-mx2.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/plat-mxc/dma-mx1-mx2.c b/arch/arm/plat-mxc/dma-mx1-mx2.c index 21427434444..92bc4f6bd01 100644 --- a/arch/arm/plat-mxc/dma-mx1-mx2.c +++ b/arch/arm/plat-mxc/dma-mx1-mx2.c @@ -114,7 +114,7 @@ struct imx_dma_channel { void (*err_handler) (int, void *, int errcode); void (*prog_handler) (int, void *, struct scatterlist *); void *data; - dmamode_t dma_mode; + unsigned int dma_mode; struct scatterlist *sg; unsigned int resbytes; int dma_num; @@ -193,7 +193,7 @@ static inline int imx_dma_sg_next(int channel, struct scatterlist *sg) int imx_dma_setup_single(int channel, dma_addr_t dma_address, unsigned int dma_length, unsigned int dev_addr, - dmamode_t dmamode) + unsigned int dmamode) { struct imx_dma_channel *imxdma = &imx_dma_channels[channel]; @@ -288,7 +288,7 @@ int imx_dma_setup_sg(int channel, struct scatterlist *sg, unsigned int sgcount, unsigned int dma_length, unsigned int dev_addr, - dmamode_t dmamode) + unsigned int dmamode) { struct imx_dma_channel *imxdma = &imx_dma_channels[channel]; diff --git a/arch/arm/plat-mxc/include/mach/dma-mx1-mx2.h b/arch/arm/plat-mxc/include/mach/dma-mx1-mx2.h index 6cc6f0c8cb2..c162920b13a 100644 --- a/arch/arm/plat-mxc/include/mach/dma-mx1-mx2.h +++ b/arch/arm/plat-mxc/include/mach/dma-mx1-mx2.h @@ -54,12 +54,12 @@ imx_dma_config_burstlen(int channel, unsigned int burstlen); int imx_dma_setup_single(int channel, dma_addr_t dma_address, unsigned int dma_length, unsigned int dev_addr, - dmamode_t dmamode); + unsigned int dmamode); int imx_dma_setup_sg(int channel, struct scatterlist *sg, unsigned int sgcount, unsigned int dma_length, - unsigned int dev_addr, dmamode_t dmamode); + unsigned int dev_addr, unsigned int dmamode); int imx_dma_setup_handlers(int channel, -- GitLab From f0ffc816250a8cc28e6824326e2d58333e058eca Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 2 Jan 2009 12:34:55 +0000 Subject: [PATCH 0045/4982] [ARM] dma: remove dmamode_t typedef Signed-off-by: Russell King --- arch/arm/include/asm/dma.h | 7 +------ arch/arm/include/asm/mach/dma.h | 2 +- arch/arm/kernel/dma.c | 2 +- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/arch/arm/include/asm/dma.h b/arch/arm/include/asm/dma.h index 59f59c6c79f..7edf3536df2 100644 --- a/arch/arm/include/asm/dma.h +++ b/arch/arm/include/asm/dma.h @@ -21,11 +21,6 @@ #include -/* - * DMA modes - */ -typedef unsigned int dmamode_t; - /* * The DMA modes reflect the settings for the ISA DMA controller */ @@ -125,7 +120,7 @@ extern void set_dma_count(unsigned int chan, unsigned long count); * DMA transfer direction immediately, but defer it to the * enable_dma(). */ -extern void set_dma_mode(unsigned int chan, dmamode_t mode); +extern void set_dma_mode(unsigned int chan, unsigned int mode); /* Set the transfer speed for this channel */ diff --git a/arch/arm/include/asm/mach/dma.h b/arch/arm/include/asm/mach/dma.h index 3122adae80b..5166145d8a3 100644 --- a/arch/arm/include/asm/mach/dma.h +++ b/arch/arm/include/asm/mach/dma.h @@ -34,7 +34,7 @@ struct dma_struct { unsigned int active:1; /* Transfer active */ unsigned int invalid:1; /* Address/Count changed */ - dmamode_t dma_mode; /* DMA mode */ + unsigned int dma_mode; /* DMA mode */ int speed; /* DMA speed */ unsigned int lock; /* Device is allocated */ diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c index e7828fcd954..7d5b9fb01e7 100644 --- a/arch/arm/kernel/dma.c +++ b/arch/arm/kernel/dma.c @@ -171,7 +171,7 @@ EXPORT_SYMBOL(set_dma_count); /* Set DMA direction mode */ -void set_dma_mode (unsigned int chan, dmamode_t mode) +void set_dma_mode (unsigned int chan, unsigned int mode) { dma_t *dma = dma_channel(chan); -- GitLab From bd8a71a7b0f50da9350d202d325c3926ffd6b189 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 3 Jan 2009 16:56:56 +0000 Subject: [PATCH 0046/4982] ALSA: Reduce boilerplate for new jack types Use a lookup table rather than explicit code to map input subsystem jack types into ASoC ones, implemented as suggested by Takashi Iwai. Signed-off-by: Mark Brown --- include/sound/jack.h | 3 +++ sound/core/jack.c | 44 ++++++++++++++++++++------------------------ 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/include/sound/jack.h b/include/sound/jack.h index 2e0315cdd0d..85266a2f5c6 100644 --- a/include/sound/jack.h +++ b/include/sound/jack.h @@ -30,6 +30,9 @@ struct input_dev; /** * Jack types which can be reported. These values are used as a * bitmask. + * + * Note that this must be kept in sync with the lookup table in + * sound/core/jack.c. */ enum snd_jack_types { SND_JACK_HEADPHONE = 0x0001, diff --git a/sound/core/jack.c b/sound/core/jack.c index dd4a12dc09a..b2da10c9916 100644 --- a/sound/core/jack.c +++ b/sound/core/jack.c @@ -23,6 +23,13 @@ #include #include +static int jack_types[] = { + SW_HEADPHONE_INSERT, + SW_MICROPHONE_INSERT, + SW_LINEOUT_INSERT, + SW_JACK_PHYSICAL_INSERT, +}; + static int snd_jack_dev_free(struct snd_device *device) { struct snd_jack *jack = device->device_data; @@ -79,6 +86,7 @@ int snd_jack_new(struct snd_card *card, const char *id, int type, { struct snd_jack *jack; int err; + int i; static struct snd_device_ops ops = { .dev_free = snd_jack_dev_free, .dev_register = snd_jack_dev_register, @@ -100,18 +108,10 @@ int snd_jack_new(struct snd_card *card, const char *id, int type, jack->type = type; - if (type & SND_JACK_HEADPHONE) - input_set_capability(jack->input_dev, EV_SW, - SW_HEADPHONE_INSERT); - if (type & SND_JACK_LINEOUT) - input_set_capability(jack->input_dev, EV_SW, - SW_LINEOUT_INSERT); - if (type & SND_JACK_MICROPHONE) - input_set_capability(jack->input_dev, EV_SW, - SW_MICROPHONE_INSERT); - if (type & SND_JACK_MECHANICAL) - input_set_capability(jack->input_dev, EV_SW, - SW_JACK_PHYSICAL_INSERT); + for (i = 0; i < ARRAY_SIZE(jack_types); i++) + if (type & (1 << i)) + input_set_capability(jack->input_dev, EV_SW, + jack_types[i]); err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops); if (err < 0) @@ -154,21 +154,17 @@ EXPORT_SYMBOL(snd_jack_set_parent); */ void snd_jack_report(struct snd_jack *jack, int status) { + int i; + if (!jack) return; - if (jack->type & SND_JACK_HEADPHONE) - input_report_switch(jack->input_dev, SW_HEADPHONE_INSERT, - status & SND_JACK_HEADPHONE); - if (jack->type & SND_JACK_LINEOUT) - input_report_switch(jack->input_dev, SW_LINEOUT_INSERT, - status & SND_JACK_LINEOUT); - if (jack->type & SND_JACK_MICROPHONE) - input_report_switch(jack->input_dev, SW_MICROPHONE_INSERT, - status & SND_JACK_MICROPHONE); - if (jack->type & SND_JACK_MECHANICAL) - input_report_switch(jack->input_dev, SW_JACK_PHYSICAL_INSERT, - status & SND_JACK_MECHANICAL); + for (i = 0; i < ARRAY_SIZE(jack_types); i++) { + int testbit = 1 << i; + if (jack->type & testbit) + input_report_switch(jack->input_dev, jack_types[i], + status & testbit); + } input_sync(jack->input_dev); } -- GitLab From bc22c17e12c130dc929218a95aa347e0f3fd05dc Mon Sep 17 00:00:00 2001 From: Alain Knaff Date: Sun, 4 Jan 2009 22:46:16 +0100 Subject: [PATCH 0047/4982] bzip2/lzma: library support for gzip, bzip2 and lzma decompression Impact: Replaces inflate.c with a wrapper around zlib_inflate; new library code This is the first part of the bzip2/lzma patch The bzip patch is based on an idea by Christian Ludwig, includes support for compressing the kernel with bzip2 or lzma rather than gzip. Both compressors give smaller sizes than gzip. Lzma's decompresses faster than bzip2. It also supports ramdisks and initramfs' compressed using these two compressors. The functionality has been successfully used for a couple of years by the udpcast project This version applies to "tip" kernel 2.6.28 This part contains: - changed inflate.c to accomodate rest of patch - implementation of bzip2 compression (not used at this stage yet) - implementation of lzma compression (not used at this stage yet) - Makefile routines to support bzip2 and lzma kernel compression Signed-off-by: Alain Knaff Signed-off-by: H. Peter Anvin --- include/linux/decompress/bunzip2.h | 10 + include/linux/decompress/generic.h | 30 ++ include/linux/decompress/inflate.h | 13 + include/linux/decompress/mm.h | 87 ++++ include/linux/decompress/unlzma.h | 12 + lib/decompress_bunzip2.c | 735 +++++++++++++++++++++++++++++ lib/decompress_inflate.c | 167 +++++++ lib/decompress_unlzma.c | 647 +++++++++++++++++++++++++ lib/zlib_inflate/inflate.h | 4 + lib/zlib_inflate/inftrees.h | 4 + scripts/Makefile.lib | 14 + scripts/bin_size | 10 + 12 files changed, 1733 insertions(+) create mode 100644 include/linux/decompress/bunzip2.h create mode 100644 include/linux/decompress/generic.h create mode 100644 include/linux/decompress/inflate.h create mode 100644 include/linux/decompress/mm.h create mode 100644 include/linux/decompress/unlzma.h create mode 100644 lib/decompress_bunzip2.c create mode 100644 lib/decompress_inflate.c create mode 100644 lib/decompress_unlzma.c create mode 100644 scripts/bin_size diff --git a/include/linux/decompress/bunzip2.h b/include/linux/decompress/bunzip2.h new file mode 100644 index 00000000000..115272137a9 --- /dev/null +++ b/include/linux/decompress/bunzip2.h @@ -0,0 +1,10 @@ +#ifndef DECOMPRESS_BUNZIP2_H +#define DECOMPRESS_BUNZIP2_H + +int bunzip2(unsigned char *inbuf, int len, + int(*fill)(void*, unsigned int), + int(*flush)(void*, unsigned int), + unsigned char *output, + int *pos, + void(*error)(char *x)); +#endif diff --git a/include/linux/decompress/generic.h b/include/linux/decompress/generic.h new file mode 100644 index 00000000000..f847f514f78 --- /dev/null +++ b/include/linux/decompress/generic.h @@ -0,0 +1,30 @@ +#ifndef DECOMPRESS_GENERIC_H +#define DECOMPRESS_GENERIC_H + +/* Minimal chunksize to be read. + *Bzip2 prefers at least 4096 + *Lzma prefers 0x10000 */ +#define COMPR_IOBUF_SIZE 4096 + +typedef int (*decompress_fn) (unsigned char *inbuf, int len, + int(*fill)(void*, unsigned int), + int(*writebb)(void*, unsigned int), + unsigned char *output, + int *posp, + void(*error)(char *x)); + +/* inbuf - input buffer + *len - len of pre-read data in inbuf + *fill - function to fill inbuf if empty + *writebb - function to write out outbug + *posp - if non-null, input position (number of bytes read) will be + * returned here + * + *If len != 0, the inbuf is initialized (with as much data), and fill + *should not be called + *If len = 0, the inbuf is allocated, but empty. Its size is IOBUF_SIZE + *fill should be called (repeatedly...) to read data, at most IOBUF_SIZE + */ + + +#endif diff --git a/include/linux/decompress/inflate.h b/include/linux/decompress/inflate.h new file mode 100644 index 00000000000..f9b06ccc3e5 --- /dev/null +++ b/include/linux/decompress/inflate.h @@ -0,0 +1,13 @@ +#ifndef INFLATE_H +#define INFLATE_H + +/* Other housekeeping constants */ +#define INBUFSIZ 4096 + +int gunzip(unsigned char *inbuf, int len, + int(*fill)(void*, unsigned int), + int(*flush)(void*, unsigned int), + unsigned char *output, + int *pos, + void(*error_fn)(char *x)); +#endif diff --git a/include/linux/decompress/mm.h b/include/linux/decompress/mm.h new file mode 100644 index 00000000000..12ff8c3f1d0 --- /dev/null +++ b/include/linux/decompress/mm.h @@ -0,0 +1,87 @@ +/* + * linux/compr_mm.h + * + * Memory management for pre-boot and ramdisk uncompressors + * + * Authors: Alain Knaff + * + */ + +#ifndef DECOMPR_MM_H +#define DECOMPR_MM_H + +#ifdef STATIC + +/* Code active when included from pre-boot environment: */ + +/* A trivial malloc implementation, adapted from + * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 + */ +static unsigned long malloc_ptr; +static int malloc_count; + +static void *malloc(int size) +{ + void *p; + + if (size < 0) + error("Malloc error"); + if (!malloc_ptr) + malloc_ptr = free_mem_ptr; + + malloc_ptr = (malloc_ptr + 3) & ~3; /* Align */ + + p = (void *)malloc_ptr; + malloc_ptr += size; + + if (free_mem_end_ptr && malloc_ptr >= free_mem_end_ptr) + error("Out of memory"); + + malloc_count++; + return p; +} + +static void free(void *where) +{ + malloc_count--; + if (!malloc_count) + malloc_ptr = free_mem_ptr; +} + +#define large_malloc(a) malloc(a) +#define large_free(a) free(a) + +#define set_error_fn(x) + +#define INIT + +#else /* STATIC */ + +/* Code active when compiled standalone for use when loading ramdisk: */ + +#include +#include +#include +#include + +/* Use defines rather than static inline in order to avoid spurious + * warnings when not needed (indeed large_malloc / large_free are not + * needed by inflate */ + +#define malloc(a) kmalloc(a, GFP_KERNEL) +#define free(a) kfree(a) + +#define large_malloc(a) vmalloc(a) +#define large_free(a) vfree(a) + +static void(*error)(char *m); +#define set_error_fn(x) error = x; + +#define INIT __init +#define STATIC + +#include + +#endif /* STATIC */ + +#endif /* DECOMPR_MM_H */ diff --git a/include/linux/decompress/unlzma.h b/include/linux/decompress/unlzma.h new file mode 100644 index 00000000000..7796538f1bf --- /dev/null +++ b/include/linux/decompress/unlzma.h @@ -0,0 +1,12 @@ +#ifndef DECOMPRESS_UNLZMA_H +#define DECOMPRESS_UNLZMA_H + +int unlzma(unsigned char *, int, + int(*fill)(void*, unsigned int), + int(*flush)(void*, unsigned int), + unsigned char *output, + int *posp, + void(*error)(char *x) + ); + +#endif diff --git a/lib/decompress_bunzip2.c b/lib/decompress_bunzip2.c new file mode 100644 index 00000000000..5d3ddb5fcfd --- /dev/null +++ b/lib/decompress_bunzip2.c @@ -0,0 +1,735 @@ +/* vi: set sw = 4 ts = 4: */ +/* Small bzip2 deflate implementation, by Rob Landley (rob@landley.net). + + Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), + which also acknowledges contributions by Mike Burrows, David Wheeler, + Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, + Robert Sedgewick, and Jon L. Bentley. + + This code is licensed under the LGPLv2: + LGPL (http://www.gnu.org/copyleft/lgpl.html +*/ + +/* + Size and speed optimizations by Manuel Novoa III (mjn3@codepoet.org). + + More efficient reading of Huffman codes, a streamlined read_bunzip() + function, and various other tweaks. In (limited) tests, approximately + 20% faster than bzcat on x86 and about 10% faster on arm. + + Note that about 2/3 of the time is spent in read_unzip() reversing + the Burrows-Wheeler transformation. Much of that time is delay + resulting from cache misses. + + I would ask that anyone benefiting from this work, especially those + using it in commercial products, consider making a donation to my local + non-profit hospice organization in the name of the woman I loved, who + passed away Feb. 12, 2003. + + In memory of Toni W. Hagan + + Hospice of Acadiana, Inc. + 2600 Johnston St., Suite 200 + Lafayette, LA 70503-3240 + + Phone (337) 232-1234 or 1-800-738-2226 + Fax (337) 232-1297 + + http://www.hospiceacadiana.com/ + + Manuel + */ + +/* + Made it fit for running in Linux Kernel by Alain Knaff (alain@knaff.lu) +*/ + + +#ifndef STATIC +#include +#endif /* !STATIC */ + +#include + +#ifndef INT_MAX +#define INT_MAX 0x7fffffff +#endif + +/* Constants for Huffman coding */ +#define MAX_GROUPS 6 +#define GROUP_SIZE 50 /* 64 would have been more efficient */ +#define MAX_HUFCODE_BITS 20 /* Longest Huffman code allowed */ +#define MAX_SYMBOLS 258 /* 256 literals + RUNA + RUNB */ +#define SYMBOL_RUNA 0 +#define SYMBOL_RUNB 1 + +/* Status return values */ +#define RETVAL_OK 0 +#define RETVAL_LAST_BLOCK (-1) +#define RETVAL_NOT_BZIP_DATA (-2) +#define RETVAL_UNEXPECTED_INPUT_EOF (-3) +#define RETVAL_UNEXPECTED_OUTPUT_EOF (-4) +#define RETVAL_DATA_ERROR (-5) +#define RETVAL_OUT_OF_MEMORY (-6) +#define RETVAL_OBSOLETE_INPUT (-7) + +/* Other housekeeping constants */ +#define BZIP2_IOBUF_SIZE 4096 + +/* This is what we know about each Huffman coding group */ +struct group_data { + /* We have an extra slot at the end of limit[] for a sentinal value. */ + int limit[MAX_HUFCODE_BITS+1]; + int base[MAX_HUFCODE_BITS]; + int permute[MAX_SYMBOLS]; + int minLen, maxLen; +}; + +/* Structure holding all the housekeeping data, including IO buffers and + memory that persists between calls to bunzip */ +struct bunzip_data { + /* State for interrupting output loop */ + int writeCopies, writePos, writeRunCountdown, writeCount, writeCurrent; + /* I/O tracking data (file handles, buffers, positions, etc.) */ + int (*fill)(void*, unsigned int); + int inbufCount, inbufPos /*, outbufPos*/; + unsigned char *inbuf /*,*outbuf*/; + unsigned int inbufBitCount, inbufBits; + /* The CRC values stored in the block header and calculated from the + data */ + unsigned int crc32Table[256], headerCRC, totalCRC, writeCRC; + /* Intermediate buffer and its size (in bytes) */ + unsigned int *dbuf, dbufSize; + /* These things are a bit too big to go on the stack */ + unsigned char selectors[32768]; /* nSelectors = 15 bits */ + struct group_data groups[MAX_GROUPS]; /* Huffman coding tables */ + int io_error; /* non-zero if we have IO error */ +}; + + +/* Return the next nnn bits of input. All reads from the compressed input + are done through this function. All reads are big endian */ +static unsigned int INIT get_bits(struct bunzip_data *bd, char bits_wanted) +{ + unsigned int bits = 0; + + /* If we need to get more data from the byte buffer, do so. + (Loop getting one byte at a time to enforce endianness and avoid + unaligned access.) */ + while (bd->inbufBitCount < bits_wanted) { + /* If we need to read more data from file into byte buffer, do + so */ + if (bd->inbufPos == bd->inbufCount) { + if (bd->io_error) + return 0; + bd->inbufCount = bd->fill(bd->inbuf, BZIP2_IOBUF_SIZE); + if (bd->inbufCount <= 0) { + bd->io_error = RETVAL_UNEXPECTED_INPUT_EOF; + return 0; + } + bd->inbufPos = 0; + } + /* Avoid 32-bit overflow (dump bit buffer to top of output) */ + if (bd->inbufBitCount >= 24) { + bits = bd->inbufBits&((1 << bd->inbufBitCount)-1); + bits_wanted -= bd->inbufBitCount; + bits <<= bits_wanted; + bd->inbufBitCount = 0; + } + /* Grab next 8 bits of input from buffer. */ + bd->inbufBits = (bd->inbufBits << 8)|bd->inbuf[bd->inbufPos++]; + bd->inbufBitCount += 8; + } + /* Calculate result */ + bd->inbufBitCount -= bits_wanted; + bits |= (bd->inbufBits >> bd->inbufBitCount)&((1 << bits_wanted)-1); + + return bits; +} + +/* Unpacks the next block and sets up for the inverse burrows-wheeler step. */ + +static int INIT get_next_block(struct bunzip_data *bd) +{ + struct group_data *hufGroup = NULL; + int *base = NULL; + int *limit = NULL; + int dbufCount, nextSym, dbufSize, groupCount, selector, + i, j, k, t, runPos, symCount, symTotal, nSelectors, + byteCount[256]; + unsigned char uc, symToByte[256], mtfSymbol[256], *selectors; + unsigned int *dbuf, origPtr; + + dbuf = bd->dbuf; + dbufSize = bd->dbufSize; + selectors = bd->selectors; + + /* Read in header signature and CRC, then validate signature. + (last block signature means CRC is for whole file, return now) */ + i = get_bits(bd, 24); + j = get_bits(bd, 24); + bd->headerCRC = get_bits(bd, 32); + if ((i == 0x177245) && (j == 0x385090)) + return RETVAL_LAST_BLOCK; + if ((i != 0x314159) || (j != 0x265359)) + return RETVAL_NOT_BZIP_DATA; + /* We can add support for blockRandomised if anybody complains. + There was some code for this in busybox 1.0.0-pre3, but nobody ever + noticed that it didn't actually work. */ + if (get_bits(bd, 1)) + return RETVAL_OBSOLETE_INPUT; + origPtr = get_bits(bd, 24); + if (origPtr > dbufSize) + return RETVAL_DATA_ERROR; + /* mapping table: if some byte values are never used (encoding things + like ascii text), the compression code removes the gaps to have fewer + symbols to deal with, and writes a sparse bitfield indicating which + values were present. We make a translation table to convert the + symbols back to the corresponding bytes. */ + t = get_bits(bd, 16); + symTotal = 0; + for (i = 0; i < 16; i++) { + if (t&(1 << (15-i))) { + k = get_bits(bd, 16); + for (j = 0; j < 16; j++) + if (k&(1 << (15-j))) + symToByte[symTotal++] = (16*i)+j; + } + } + /* How many different Huffman coding groups does this block use? */ + groupCount = get_bits(bd, 3); + if (groupCount < 2 || groupCount > MAX_GROUPS) + return RETVAL_DATA_ERROR; + /* nSelectors: Every GROUP_SIZE many symbols we select a new + Huffman coding group. Read in the group selector list, + which is stored as MTF encoded bit runs. (MTF = Move To + Front, as each value is used it's moved to the start of the + list.) */ + nSelectors = get_bits(bd, 15); + if (!nSelectors) + return RETVAL_DATA_ERROR; + for (i = 0; i < groupCount; i++) + mtfSymbol[i] = i; + for (i = 0; i < nSelectors; i++) { + /* Get next value */ + for (j = 0; get_bits(bd, 1); j++) + if (j >= groupCount) + return RETVAL_DATA_ERROR; + /* Decode MTF to get the next selector */ + uc = mtfSymbol[j]; + for (; j; j--) + mtfSymbol[j] = mtfSymbol[j-1]; + mtfSymbol[0] = selectors[i] = uc; + } + /* Read the Huffman coding tables for each group, which code + for symTotal literal symbols, plus two run symbols (RUNA, + RUNB) */ + symCount = symTotal+2; + for (j = 0; j < groupCount; j++) { + unsigned char length[MAX_SYMBOLS], temp[MAX_HUFCODE_BITS+1]; + int minLen, maxLen, pp; + /* Read Huffman code lengths for each symbol. They're + stored in a way similar to mtf; record a starting + value for the first symbol, and an offset from the + previous value for everys symbol after that. + (Subtracting 1 before the loop and then adding it + back at the end is an optimization that makes the + test inside the loop simpler: symbol length 0 + becomes negative, so an unsigned inequality catches + it.) */ + t = get_bits(bd, 5)-1; + for (i = 0; i < symCount; i++) { + for (;;) { + if (((unsigned)t) > (MAX_HUFCODE_BITS-1)) + return RETVAL_DATA_ERROR; + + /* If first bit is 0, stop. Else + second bit indicates whether to + increment or decrement the value. + Optimization: grab 2 bits and unget + the second if the first was 0. */ + + k = get_bits(bd, 2); + if (k < 2) { + bd->inbufBitCount++; + break; + } + /* Add one if second bit 1, else + * subtract 1. Avoids if/else */ + t += (((k+1)&2)-1); + } + /* Correct for the initial -1, to get the + * final symbol length */ + length[i] = t+1; + } + /* Find largest and smallest lengths in this group */ + minLen = maxLen = length[0]; + + for (i = 1; i < symCount; i++) { + if (length[i] > maxLen) + maxLen = length[i]; + else if (length[i] < minLen) + minLen = length[i]; + } + + /* Calculate permute[], base[], and limit[] tables from + * length[]. + * + * permute[] is the lookup table for converting + * Huffman coded symbols into decoded symbols. base[] + * is the amount to subtract from the value of a + * Huffman symbol of a given length when using + * permute[]. + * + * limit[] indicates the largest numerical value a + * symbol with a given number of bits can have. This + * is how the Huffman codes can vary in length: each + * code with a value > limit[length] needs another + * bit. + */ + hufGroup = bd->groups+j; + hufGroup->minLen = minLen; + hufGroup->maxLen = maxLen; + /* Note that minLen can't be smaller than 1, so we + adjust the base and limit array pointers so we're + not always wasting the first entry. We do this + again when using them (during symbol decoding).*/ + base = hufGroup->base-1; + limit = hufGroup->limit-1; + /* Calculate permute[]. Concurently, initialize + * temp[] and limit[]. */ + pp = 0; + for (i = minLen; i <= maxLen; i++) { + temp[i] = limit[i] = 0; + for (t = 0; t < symCount; t++) + if (length[t] == i) + hufGroup->permute[pp++] = t; + } + /* Count symbols coded for at each bit length */ + for (i = 0; i < symCount; i++) + temp[length[i]]++; + /* Calculate limit[] (the largest symbol-coding value + *at each bit length, which is (previous limit << + *1)+symbols at this level), and base[] (number of + *symbols to ignore at each bit length, which is limit + *minus the cumulative count of symbols coded for + *already). */ + pp = t = 0; + for (i = minLen; i < maxLen; i++) { + pp += temp[i]; + /* We read the largest possible symbol size + and then unget bits after determining how + many we need, and those extra bits could be + set to anything. (They're noise from + future symbols.) At each level we're + really only interested in the first few + bits, so here we set all the trailing + to-be-ignored bits to 1 so they don't + affect the value > limit[length] + comparison. */ + limit[i] = (pp << (maxLen - i)) - 1; + pp <<= 1; + base[i+1] = pp-(t += temp[i]); + } + limit[maxLen+1] = INT_MAX; /* Sentinal value for + * reading next sym. */ + limit[maxLen] = pp+temp[maxLen]-1; + base[minLen] = 0; + } + /* We've finished reading and digesting the block header. Now + read this block's Huffman coded symbols from the file and + undo the Huffman coding and run length encoding, saving the + result into dbuf[dbufCount++] = uc */ + + /* Initialize symbol occurrence counters and symbol Move To + * Front table */ + for (i = 0; i < 256; i++) { + byteCount[i] = 0; + mtfSymbol[i] = (unsigned char)i; + } + /* Loop through compressed symbols. */ + runPos = dbufCount = symCount = selector = 0; + for (;;) { + /* Determine which Huffman coding group to use. */ + if (!(symCount--)) { + symCount = GROUP_SIZE-1; + if (selector >= nSelectors) + return RETVAL_DATA_ERROR; + hufGroup = bd->groups+selectors[selector++]; + base = hufGroup->base-1; + limit = hufGroup->limit-1; + } + /* Read next Huffman-coded symbol. */ + /* Note: It is far cheaper to read maxLen bits and + back up than it is to read minLen bits and then an + additional bit at a time, testing as we go. + Because there is a trailing last block (with file + CRC), there is no danger of the overread causing an + unexpected EOF for a valid compressed file. As a + further optimization, we do the read inline + (falling back to a call to get_bits if the buffer + runs dry). The following (up to got_huff_bits:) is + equivalent to j = get_bits(bd, hufGroup->maxLen); + */ + while (bd->inbufBitCount < hufGroup->maxLen) { + if (bd->inbufPos == bd->inbufCount) { + j = get_bits(bd, hufGroup->maxLen); + goto got_huff_bits; + } + bd->inbufBits = + (bd->inbufBits << 8)|bd->inbuf[bd->inbufPos++]; + bd->inbufBitCount += 8; + }; + bd->inbufBitCount -= hufGroup->maxLen; + j = (bd->inbufBits >> bd->inbufBitCount)& + ((1 << hufGroup->maxLen)-1); +got_huff_bits: + /* Figure how how many bits are in next symbol and + * unget extras */ + i = hufGroup->minLen; + while (j > limit[i]) + ++i; + bd->inbufBitCount += (hufGroup->maxLen - i); + /* Huffman decode value to get nextSym (with bounds checking) */ + if ((i > hufGroup->maxLen) + || (((unsigned)(j = (j>>(hufGroup->maxLen-i))-base[i])) + >= MAX_SYMBOLS)) + return RETVAL_DATA_ERROR; + nextSym = hufGroup->permute[j]; + /* We have now decoded the symbol, which indicates + either a new literal byte, or a repeated run of the + most recent literal byte. First, check if nextSym + indicates a repeated run, and if so loop collecting + how many times to repeat the last literal. */ + if (((unsigned)nextSym) <= SYMBOL_RUNB) { /* RUNA or RUNB */ + /* If this is the start of a new run, zero out + * counter */ + if (!runPos) { + runPos = 1; + t = 0; + } + /* Neat trick that saves 1 symbol: instead of + or-ing 0 or 1 at each bit position, add 1 + or 2 instead. For example, 1011 is 1 << 0 + + 1 << 1 + 2 << 2. 1010 is 2 << 0 + 2 << 1 + + 1 << 2. You can make any bit pattern + that way using 1 less symbol than the basic + or 0/1 method (except all bits 0, which + would use no symbols, but a run of length 0 + doesn't mean anything in this context). + Thus space is saved. */ + t += (runPos << nextSym); + /* +runPos if RUNA; +2*runPos if RUNB */ + + runPos <<= 1; + continue; + } + /* When we hit the first non-run symbol after a run, + we now know how many times to repeat the last + literal, so append that many copies to our buffer + of decoded symbols (dbuf) now. (The last literal + used is the one at the head of the mtfSymbol + array.) */ + if (runPos) { + runPos = 0; + if (dbufCount+t >= dbufSize) + return RETVAL_DATA_ERROR; + + uc = symToByte[mtfSymbol[0]]; + byteCount[uc] += t; + while (t--) + dbuf[dbufCount++] = uc; + } + /* Is this the terminating symbol? */ + if (nextSym > symTotal) + break; + /* At this point, nextSym indicates a new literal + character. Subtract one to get the position in the + MTF array at which this literal is currently to be + found. (Note that the result can't be -1 or 0, + because 0 and 1 are RUNA and RUNB. But another + instance of the first symbol in the mtf array, + position 0, would have been handled as part of a + run above. Therefore 1 unused mtf position minus 2 + non-literal nextSym values equals -1.) */ + if (dbufCount >= dbufSize) + return RETVAL_DATA_ERROR; + i = nextSym - 1; + uc = mtfSymbol[i]; + /* Adjust the MTF array. Since we typically expect to + *move only a small number of symbols, and are bound + *by 256 in any case, using memmove here would + *typically be bigger and slower due to function call + *overhead and other assorted setup costs. */ + do { + mtfSymbol[i] = mtfSymbol[i-1]; + } while (--i); + mtfSymbol[0] = uc; + uc = symToByte[uc]; + /* We have our literal byte. Save it into dbuf. */ + byteCount[uc]++; + dbuf[dbufCount++] = (unsigned int)uc; + } + /* At this point, we've read all the Huffman-coded symbols + (and repeated runs) for this block from the input stream, + and decoded them into the intermediate buffer. There are + dbufCount many decoded bytes in dbuf[]. Now undo the + Burrows-Wheeler transform on dbuf. See + http://dogma.net/markn/articles/bwt/bwt.htm + */ + /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */ + j = 0; + for (i = 0; i < 256; i++) { + k = j+byteCount[i]; + byteCount[i] = j; + j = k; + } + /* Figure out what order dbuf would be in if we sorted it. */ + for (i = 0; i < dbufCount; i++) { + uc = (unsigned char)(dbuf[i] & 0xff); + dbuf[byteCount[uc]] |= (i << 8); + byteCount[uc]++; + } + /* Decode first byte by hand to initialize "previous" byte. + Note that it doesn't get output, and if the first three + characters are identical it doesn't qualify as a run (hence + writeRunCountdown = 5). */ + if (dbufCount) { + if (origPtr >= dbufCount) + return RETVAL_DATA_ERROR; + bd->writePos = dbuf[origPtr]; + bd->writeCurrent = (unsigned char)(bd->writePos&0xff); + bd->writePos >>= 8; + bd->writeRunCountdown = 5; + } + bd->writeCount = dbufCount; + + return RETVAL_OK; +} + +/* Undo burrows-wheeler transform on intermediate buffer to produce output. + If start_bunzip was initialized with out_fd =-1, then up to len bytes of + data are written to outbuf. Return value is number of bytes written or + error (all errors are negative numbers). If out_fd!=-1, outbuf and len + are ignored, data is written to out_fd and return is RETVAL_OK or error. +*/ + +static int INIT read_bunzip(struct bunzip_data *bd, char *outbuf, int len) +{ + const unsigned int *dbuf; + int pos, xcurrent, previous, gotcount; + + /* If last read was short due to end of file, return last block now */ + if (bd->writeCount < 0) + return bd->writeCount; + + gotcount = 0; + dbuf = bd->dbuf; + pos = bd->writePos; + xcurrent = bd->writeCurrent; + + /* We will always have pending decoded data to write into the output + buffer unless this is the very first call (in which case we haven't + Huffman-decoded a block into the intermediate buffer yet). */ + + if (bd->writeCopies) { + /* Inside the loop, writeCopies means extra copies (beyond 1) */ + --bd->writeCopies; + /* Loop outputting bytes */ + for (;;) { + /* If the output buffer is full, snapshot + * state and return */ + if (gotcount >= len) { + bd->writePos = pos; + bd->writeCurrent = xcurrent; + bd->writeCopies++; + return len; + } + /* Write next byte into output buffer, updating CRC */ + outbuf[gotcount++] = xcurrent; + bd->writeCRC = (((bd->writeCRC) << 8) + ^bd->crc32Table[((bd->writeCRC) >> 24) + ^xcurrent]); + /* Loop now if we're outputting multiple + * copies of this byte */ + if (bd->writeCopies) { + --bd->writeCopies; + continue; + } +decode_next_byte: + if (!bd->writeCount--) + break; + /* Follow sequence vector to undo + * Burrows-Wheeler transform */ + previous = xcurrent; + pos = dbuf[pos]; + xcurrent = pos&0xff; + pos >>= 8; + /* After 3 consecutive copies of the same + byte, the 4th is a repeat count. We count + down from 4 instead *of counting up because + testing for non-zero is faster */ + if (--bd->writeRunCountdown) { + if (xcurrent != previous) + bd->writeRunCountdown = 4; + } else { + /* We have a repeated run, this byte + * indicates the count */ + bd->writeCopies = xcurrent; + xcurrent = previous; + bd->writeRunCountdown = 5; + /* Sometimes there are just 3 bytes + * (run length 0) */ + if (!bd->writeCopies) + goto decode_next_byte; + /* Subtract the 1 copy we'd output + * anyway to get extras */ + --bd->writeCopies; + } + } + /* Decompression of this block completed successfully */ + bd->writeCRC = ~bd->writeCRC; + bd->totalCRC = ((bd->totalCRC << 1) | + (bd->totalCRC >> 31)) ^ bd->writeCRC; + /* If this block had a CRC error, force file level CRC error. */ + if (bd->writeCRC != bd->headerCRC) { + bd->totalCRC = bd->headerCRC+1; + return RETVAL_LAST_BLOCK; + } + } + + /* Refill the intermediate buffer by Huffman-decoding next + * block of input */ + /* (previous is just a convenient unused temp variable here) */ + previous = get_next_block(bd); + if (previous) { + bd->writeCount = previous; + return (previous != RETVAL_LAST_BLOCK) ? previous : gotcount; + } + bd->writeCRC = 0xffffffffUL; + pos = bd->writePos; + xcurrent = bd->writeCurrent; + goto decode_next_byte; +} + +static int INIT nofill(void *buf, unsigned int len) +{ + return -1; +} + +/* Allocate the structure, read file header. If in_fd ==-1, inbuf must contain + a complete bunzip file (len bytes long). If in_fd!=-1, inbuf and len are + ignored, and data is read from file handle into temporary buffer. */ +static int INIT start_bunzip(struct bunzip_data **bdp, void *inbuf, int len, + int (*fill)(void*, unsigned int)) +{ + struct bunzip_data *bd; + unsigned int i, j, c; + const unsigned int BZh0 = + (((unsigned int)'B') << 24)+(((unsigned int)'Z') << 16) + +(((unsigned int)'h') << 8)+(unsigned int)'0'; + + /* Figure out how much data to allocate */ + i = sizeof(struct bunzip_data); + + /* Allocate bunzip_data. Most fields initialize to zero. */ + bd = *bdp = malloc(i); + memset(bd, 0, sizeof(struct bunzip_data)); + /* Setup input buffer */ + bd->inbuf = inbuf; + bd->inbufCount = len; + if (fill != NULL) + bd->fill = fill; + else + bd->fill = nofill; + + /* Init the CRC32 table (big endian) */ + for (i = 0; i < 256; i++) { + c = i << 24; + for (j = 8; j; j--) + c = c&0x80000000 ? (c << 1)^0x04c11db7 : (c << 1); + bd->crc32Table[i] = c; + } + + /* Ensure that file starts with "BZh['1'-'9']." */ + i = get_bits(bd, 32); + if (((unsigned int)(i-BZh0-1)) >= 9) + return RETVAL_NOT_BZIP_DATA; + + /* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of + uncompressed data. Allocate intermediate buffer for block. */ + bd->dbufSize = 100000*(i-BZh0); + + bd->dbuf = large_malloc(bd->dbufSize * sizeof(int)); + return RETVAL_OK; +} + +/* Example usage: decompress src_fd to dst_fd. (Stops at end of bzip2 data, + not end of file.) */ +STATIC int INIT bunzip2(unsigned char *buf, int len, + int(*fill)(void*, unsigned int), + int(*flush)(void*, unsigned int), + unsigned char *outbuf, + int *pos, + void(*error_fn)(char *x)) +{ + struct bunzip_data *bd; + int i = -1; + unsigned char *inbuf; + + set_error_fn(error_fn); + if (flush) + outbuf = malloc(BZIP2_IOBUF_SIZE); + else + len -= 4; /* Uncompressed size hack active in pre-boot + environment */ + if (!outbuf) { + error("Could not allocate output bufer"); + return -1; + } + if (buf) + inbuf = buf; + else + inbuf = malloc(BZIP2_IOBUF_SIZE); + if (!inbuf) { + error("Could not allocate input bufer"); + goto exit_0; + } + i = start_bunzip(&bd, inbuf, len, fill); + if (!i) { + for (;;) { + i = read_bunzip(bd, outbuf, BZIP2_IOBUF_SIZE); + if (i <= 0) + break; + if (!flush) + outbuf += i; + else + if (i != flush(outbuf, i)) { + i = RETVAL_UNEXPECTED_OUTPUT_EOF; + break; + } + } + } + /* Check CRC and release memory */ + if (i == RETVAL_LAST_BLOCK) { + if (bd->headerCRC != bd->totalCRC) + error("Data integrity error when decompressing."); + else + i = RETVAL_OK; + } else if (i == RETVAL_UNEXPECTED_OUTPUT_EOF) { + error("Compressed file ends unexpectedly"); + } + if (bd->dbuf) + large_free(bd->dbuf); + if (pos) + *pos = bd->inbufPos; + free(bd); + if (!buf) + free(inbuf); +exit_0: + if (flush) + free(outbuf); + return i; +} + +#define decompress bunzip2 diff --git a/lib/decompress_inflate.c b/lib/decompress_inflate.c new file mode 100644 index 00000000000..163e66aea5f --- /dev/null +++ b/lib/decompress_inflate.c @@ -0,0 +1,167 @@ +#ifdef STATIC +/* Pre-boot environment: included */ + +/* prevent inclusion of _LINUX_KERNEL_H in pre-boot environment: lots + * errors about console_printk etc... on ARM */ +#define _LINUX_KERNEL_H + +#include "zlib_inflate/inftrees.c" +#include "zlib_inflate/inffast.c" +#include "zlib_inflate/inflate.c" + +#else /* STATIC */ +/* initramfs et al: linked */ + +#include + +#include "zlib_inflate/inftrees.h" +#include "zlib_inflate/inffast.h" +#include "zlib_inflate/inflate.h" + +#include "zlib_inflate/infutil.h" + +#endif /* STATIC */ + +#include + +#define INBUF_LEN (16*1024) + +/* Included from initramfs et al code */ +STATIC int INIT gunzip(unsigned char *buf, int len, + int(*fill)(void*, unsigned int), + int(*flush)(void*, unsigned int), + unsigned char *out_buf, + int *pos, + void(*error_fn)(char *x)) { + u8 *zbuf; + struct z_stream_s *strm; + int rc; + size_t out_len; + + set_error_fn(error_fn); + rc = -1; + if (flush) { + out_len = 0x8100; /* 32 K */ + out_buf = malloc(out_len); + } else { + out_len = 0x7fffffff; /* no limit */ + } + if (!out_buf) { + error("Out of memory while allocating output buffer"); + goto gunzip_nomem1; + } + + if (buf) + zbuf = buf; + else { + zbuf = malloc(INBUF_LEN); + len = 0; + } + if (!zbuf) { + error("Out of memory while allocating input buffer"); + goto gunzip_nomem2; + } + + strm = malloc(sizeof(*strm)); + if (strm == NULL) { + error("Out of memory while allocating z_stream"); + goto gunzip_nomem3; + } + + strm->workspace = malloc(flush ? zlib_inflate_workspacesize() : + sizeof(struct inflate_state)); + if (strm->workspace == NULL) { + error("Out of memory while allocating workspace"); + goto gunzip_nomem4; + } + + if (len == 0) + len = fill(zbuf, INBUF_LEN); + + /* verify the gzip header */ + if (len < 10 || + zbuf[0] != 0x1f || zbuf[1] != 0x8b || zbuf[2] != 0x08) { + if (pos) + *pos = 0; + error("Not a gzip file"); + goto gunzip_5; + } + + /* skip over gzip header (1f,8b,08... 10 bytes total + + * possible asciz filename) + */ + strm->next_in = zbuf + 10; + /* skip over asciz filename */ + if (zbuf[3] & 0x8) { + while (strm->next_in[0]) + strm->next_in++; + strm->next_in++; + } + strm->avail_in = len - 10; + + strm->next_out = out_buf; + strm->avail_out = out_len; + + rc = zlib_inflateInit2(strm, -MAX_WBITS); + + if (!flush) { + WS(strm)->inflate_state.wsize = 0; + WS(strm)->inflate_state.window = NULL; + } + + while (rc == Z_OK) { + if (strm->avail_in == 0) { + /* TODO: handle case where both pos and fill are set */ + len = fill(zbuf, INBUF_LEN); + if (len < 0) { + rc = -1; + error("read error"); + break; + } + strm->next_in = zbuf; + strm->avail_in = len; + } + rc = zlib_inflate(strm, 0); + + /* Write any data generated */ + if (flush && strm->next_out > out_buf) { + int l = strm->next_out - out_buf; + if (l != flush(out_buf, l)) { + rc = -1; + error("write error"); + break; + } + strm->next_out = out_buf; + strm->avail_out = out_len; + } + + /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */ + if (rc == Z_STREAM_END) { + rc = 0; + break; + } else if (rc != Z_OK) { + error("uncompression error"); + rc = -1; + } + } + + zlib_inflateEnd(strm); + if (pos) + /* add + 8 to skip over trailer */ + *pos = strm->next_in - zbuf+8; + +gunzip_5: + free(strm->workspace); +gunzip_nomem4: + free(strm); +gunzip_nomem3: + if (!buf) + free(zbuf); +gunzip_nomem2: + if (flush) + free(out_buf); +gunzip_nomem1: + return rc; /* returns Z_OK (0) if successful */ +} + +#define decompress gunzip diff --git a/lib/decompress_unlzma.c b/lib/decompress_unlzma.c new file mode 100644 index 00000000000..546f2f4c157 --- /dev/null +++ b/lib/decompress_unlzma.c @@ -0,0 +1,647 @@ +/* Lzma decompressor for Linux kernel. Shamelessly snarfed + *from busybox 1.1.1 + * + *Linux kernel adaptation + *Copyright (C) 2006 Alain < alain@knaff.lu > + * + *Based on small lzma deflate implementation/Small range coder + *implementation for lzma. + *Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org > + * + *Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/) + *Copyright (C) 1999-2005 Igor Pavlov + * + *Copyrights of the parts, see headers below. + * + * + *This program is free software; you can redistribute it and/or + *modify it under the terms of the GNU Lesser General Public + *License as published by the Free Software Foundation; either + *version 2.1 of the License, or (at your option) any later version. + * + *This program is distributed in the hope that it will be useful, + *but WITHOUT ANY WARRANTY; without even the implied warranty of + *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + *Lesser General Public License for more details. + * + *You should have received a copy of the GNU Lesser General Public + *License along with this library; if not, write to the Free Software + *Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef STATIC +#include +#endif /* STATIC */ + +#include + +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + +static long long INIT read_int(unsigned char *ptr, int size) +{ + int i; + long long ret = 0; + + for (i = 0; i < size; i++) + ret = (ret << 8) | ptr[size-i-1]; + return ret; +} + +#define ENDIAN_CONVERT(x) \ + x = (typeof(x))read_int((unsigned char *)&x, sizeof(x)) + + +/* Small range coder implementation for lzma. + *Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org > + * + *Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/) + *Copyright (c) 1999-2005 Igor Pavlov + */ + +#include + +#define LZMA_IOBUF_SIZE 0x10000 + +struct rc { + int (*fill)(void*, unsigned int); + uint8_t *ptr; + uint8_t *buffer; + uint8_t *buffer_end; + int buffer_size; + uint32_t code; + uint32_t range; + uint32_t bound; +}; + + +#define RC_TOP_BITS 24 +#define RC_MOVE_BITS 5 +#define RC_MODEL_TOTAL_BITS 11 + + +/* Called twice: once at startup and once in rc_normalize() */ +static void INIT rc_read(struct rc *rc) +{ + rc->buffer_size = rc->fill((char *)rc->buffer, LZMA_IOBUF_SIZE); + if (rc->buffer_size <= 0) + error("unexpected EOF"); + rc->ptr = rc->buffer; + rc->buffer_end = rc->buffer + rc->buffer_size; +} + +/* Called once */ +static inline void INIT rc_init(struct rc *rc, + int (*fill)(void*, unsigned int), + char *buffer, int buffer_size) +{ + rc->fill = fill; + rc->buffer = (uint8_t *)buffer; + rc->buffer_size = buffer_size; + rc->buffer_end = rc->buffer + rc->buffer_size; + rc->ptr = rc->buffer; + + rc->code = 0; + rc->range = 0xFFFFFFFF; +} + +static inline void INIT rc_init_code(struct rc *rc) +{ + int i; + + for (i = 0; i < 5; i++) { + if (rc->ptr >= rc->buffer_end) + rc_read(rc); + rc->code = (rc->code << 8) | *rc->ptr++; + } +} + + +/* Called once. TODO: bb_maybe_free() */ +static inline void INIT rc_free(struct rc *rc) +{ + free(rc->buffer); +} + +/* Called twice, but one callsite is in inline'd rc_is_bit_0_helper() */ +static void INIT rc_do_normalize(struct rc *rc) +{ + if (rc->ptr >= rc->buffer_end) + rc_read(rc); + rc->range <<= 8; + rc->code = (rc->code << 8) | *rc->ptr++; +} +static inline void INIT rc_normalize(struct rc *rc) +{ + if (rc->range < (1 << RC_TOP_BITS)) + rc_do_normalize(rc); +} + +/* Called 9 times */ +/* Why rc_is_bit_0_helper exists? + *Because we want to always expose (rc->code < rc->bound) to optimizer + */ +static inline uint32_t INIT rc_is_bit_0_helper(struct rc *rc, uint16_t *p) +{ + rc_normalize(rc); + rc->bound = *p * (rc->range >> RC_MODEL_TOTAL_BITS); + return rc->bound; +} +static inline int INIT rc_is_bit_0(struct rc *rc, uint16_t *p) +{ + uint32_t t = rc_is_bit_0_helper(rc, p); + return rc->code < t; +} + +/* Called ~10 times, but very small, thus inlined */ +static inline void INIT rc_update_bit_0(struct rc *rc, uint16_t *p) +{ + rc->range = rc->bound; + *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS; +} +static inline void rc_update_bit_1(struct rc *rc, uint16_t *p) +{ + rc->range -= rc->bound; + rc->code -= rc->bound; + *p -= *p >> RC_MOVE_BITS; +} + +/* Called 4 times in unlzma loop */ +static int INIT rc_get_bit(struct rc *rc, uint16_t *p, int *symbol) +{ + if (rc_is_bit_0(rc, p)) { + rc_update_bit_0(rc, p); + *symbol *= 2; + return 0; + } else { + rc_update_bit_1(rc, p); + *symbol = *symbol * 2 + 1; + return 1; + } +} + +/* Called once */ +static inline int INIT rc_direct_bit(struct rc *rc) +{ + rc_normalize(rc); + rc->range >>= 1; + if (rc->code >= rc->range) { + rc->code -= rc->range; + return 1; + } + return 0; +} + +/* Called twice */ +static inline void INIT +rc_bit_tree_decode(struct rc *rc, uint16_t *p, int num_levels, int *symbol) +{ + int i = num_levels; + + *symbol = 1; + while (i--) + rc_get_bit(rc, p + *symbol, symbol); + *symbol -= 1 << num_levels; +} + + +/* + * Small lzma deflate implementation. + * Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org > + * + * Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/) + * Copyright (C) 1999-2005 Igor Pavlov + */ + + +struct lzma_header { + uint8_t pos; + uint32_t dict_size; + uint64_t dst_size; +} __attribute__ ((packed)) ; + + +#define LZMA_BASE_SIZE 1846 +#define LZMA_LIT_SIZE 768 + +#define LZMA_NUM_POS_BITS_MAX 4 + +#define LZMA_LEN_NUM_LOW_BITS 3 +#define LZMA_LEN_NUM_MID_BITS 3 +#define LZMA_LEN_NUM_HIGH_BITS 8 + +#define LZMA_LEN_CHOICE 0 +#define LZMA_LEN_CHOICE_2 (LZMA_LEN_CHOICE + 1) +#define LZMA_LEN_LOW (LZMA_LEN_CHOICE_2 + 1) +#define LZMA_LEN_MID (LZMA_LEN_LOW \ + + (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_LOW_BITS))) +#define LZMA_LEN_HIGH (LZMA_LEN_MID \ + +(1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_MID_BITS))) +#define LZMA_NUM_LEN_PROBS (LZMA_LEN_HIGH + (1 << LZMA_LEN_NUM_HIGH_BITS)) + +#define LZMA_NUM_STATES 12 +#define LZMA_NUM_LIT_STATES 7 + +#define LZMA_START_POS_MODEL_INDEX 4 +#define LZMA_END_POS_MODEL_INDEX 14 +#define LZMA_NUM_FULL_DISTANCES (1 << (LZMA_END_POS_MODEL_INDEX >> 1)) + +#define LZMA_NUM_POS_SLOT_BITS 6 +#define LZMA_NUM_LEN_TO_POS_STATES 4 + +#define LZMA_NUM_ALIGN_BITS 4 + +#define LZMA_MATCH_MIN_LEN 2 + +#define LZMA_IS_MATCH 0 +#define LZMA_IS_REP (LZMA_IS_MATCH + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)) +#define LZMA_IS_REP_G0 (LZMA_IS_REP + LZMA_NUM_STATES) +#define LZMA_IS_REP_G1 (LZMA_IS_REP_G0 + LZMA_NUM_STATES) +#define LZMA_IS_REP_G2 (LZMA_IS_REP_G1 + LZMA_NUM_STATES) +#define LZMA_IS_REP_0_LONG (LZMA_IS_REP_G2 + LZMA_NUM_STATES) +#define LZMA_POS_SLOT (LZMA_IS_REP_0_LONG \ + + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)) +#define LZMA_SPEC_POS (LZMA_POS_SLOT \ + +(LZMA_NUM_LEN_TO_POS_STATES << LZMA_NUM_POS_SLOT_BITS)) +#define LZMA_ALIGN (LZMA_SPEC_POS \ + + LZMA_NUM_FULL_DISTANCES - LZMA_END_POS_MODEL_INDEX) +#define LZMA_LEN_CODER (LZMA_ALIGN + (1 << LZMA_NUM_ALIGN_BITS)) +#define LZMA_REP_LEN_CODER (LZMA_LEN_CODER + LZMA_NUM_LEN_PROBS) +#define LZMA_LITERAL (LZMA_REP_LEN_CODER + LZMA_NUM_LEN_PROBS) + + +struct writer { + uint8_t *buffer; + uint8_t previous_byte; + size_t buffer_pos; + int bufsize; + size_t global_pos; + int(*flush)(void*, unsigned int); + struct lzma_header *header; +}; + +struct cstate { + int state; + uint32_t rep0, rep1, rep2, rep3; +}; + +static inline size_t INIT get_pos(struct writer *wr) +{ + return + wr->global_pos + wr->buffer_pos; +} + +static inline uint8_t INIT peek_old_byte(struct writer *wr, + uint32_t offs) +{ + if (!wr->flush) { + int32_t pos; + while (offs > wr->header->dict_size) + offs -= wr->header->dict_size; + pos = wr->buffer_pos - offs; + return wr->buffer[pos]; + } else { + uint32_t pos = wr->buffer_pos - offs; + while (pos >= wr->header->dict_size) + pos += wr->header->dict_size; + return wr->buffer[pos]; + } + +} + +static inline void INIT write_byte(struct writer *wr, uint8_t byte) +{ + wr->buffer[wr->buffer_pos++] = wr->previous_byte = byte; + if (wr->flush && wr->buffer_pos == wr->header->dict_size) { + wr->buffer_pos = 0; + wr->global_pos += wr->header->dict_size; + wr->flush((char *)wr->buffer, wr->header->dict_size); + } +} + + +static inline void INIT copy_byte(struct writer *wr, uint32_t offs) +{ + write_byte(wr, peek_old_byte(wr, offs)); +} + +static inline void INIT copy_bytes(struct writer *wr, + uint32_t rep0, int len) +{ + do { + copy_byte(wr, rep0); + len--; + } while (len != 0 && wr->buffer_pos < wr->header->dst_size); +} + +static inline void INIT process_bit0(struct writer *wr, struct rc *rc, + struct cstate *cst, uint16_t *p, + int pos_state, uint16_t *prob, + int lc, uint32_t literal_pos_mask) { + int mi = 1; + rc_update_bit_0(rc, prob); + prob = (p + LZMA_LITERAL + + (LZMA_LIT_SIZE + * (((get_pos(wr) & literal_pos_mask) << lc) + + (wr->previous_byte >> (8 - lc)))) + ); + + if (cst->state >= LZMA_NUM_LIT_STATES) { + int match_byte = peek_old_byte(wr, cst->rep0); + do { + int bit; + uint16_t *prob_lit; + + match_byte <<= 1; + bit = match_byte & 0x100; + prob_lit = prob + 0x100 + bit + mi; + if (rc_get_bit(rc, prob_lit, &mi)) { + if (!bit) + break; + } else { + if (bit) + break; + } + } while (mi < 0x100); + } + while (mi < 0x100) { + uint16_t *prob_lit = prob + mi; + rc_get_bit(rc, prob_lit, &mi); + } + write_byte(wr, mi); + if (cst->state < 4) + cst->state = 0; + else if (cst->state < 10) + cst->state -= 3; + else + cst->state -= 6; +} + +static inline void INIT process_bit1(struct writer *wr, struct rc *rc, + struct cstate *cst, uint16_t *p, + int pos_state, uint16_t *prob) { + int offset; + uint16_t *prob_len; + int num_bits; + int len; + + rc_update_bit_1(rc, prob); + prob = p + LZMA_IS_REP + cst->state; + if (rc_is_bit_0(rc, prob)) { + rc_update_bit_0(rc, prob); + cst->rep3 = cst->rep2; + cst->rep2 = cst->rep1; + cst->rep1 = cst->rep0; + cst->state = cst->state < LZMA_NUM_LIT_STATES ? 0 : 3; + prob = p + LZMA_LEN_CODER; + } else { + rc_update_bit_1(rc, prob); + prob = p + LZMA_IS_REP_G0 + cst->state; + if (rc_is_bit_0(rc, prob)) { + rc_update_bit_0(rc, prob); + prob = (p + LZMA_IS_REP_0_LONG + + (cst->state << + LZMA_NUM_POS_BITS_MAX) + + pos_state); + if (rc_is_bit_0(rc, prob)) { + rc_update_bit_0(rc, prob); + + cst->state = cst->state < LZMA_NUM_LIT_STATES ? + 9 : 11; + copy_byte(wr, cst->rep0); + return; + } else { + rc_update_bit_1(rc, prob); + } + } else { + uint32_t distance; + + rc_update_bit_1(rc, prob); + prob = p + LZMA_IS_REP_G1 + cst->state; + if (rc_is_bit_0(rc, prob)) { + rc_update_bit_0(rc, prob); + distance = cst->rep1; + } else { + rc_update_bit_1(rc, prob); + prob = p + LZMA_IS_REP_G2 + cst->state; + if (rc_is_bit_0(rc, prob)) { + rc_update_bit_0(rc, prob); + distance = cst->rep2; + } else { + rc_update_bit_1(rc, prob); + distance = cst->rep3; + cst->rep3 = cst->rep2; + } + cst->rep2 = cst->rep1; + } + cst->rep1 = cst->rep0; + cst->rep0 = distance; + } + cst->state = cst->state < LZMA_NUM_LIT_STATES ? 8 : 11; + prob = p + LZMA_REP_LEN_CODER; + } + + prob_len = prob + LZMA_LEN_CHOICE; + if (rc_is_bit_0(rc, prob_len)) { + rc_update_bit_0(rc, prob_len); + prob_len = (prob + LZMA_LEN_LOW + + (pos_state << + LZMA_LEN_NUM_LOW_BITS)); + offset = 0; + num_bits = LZMA_LEN_NUM_LOW_BITS; + } else { + rc_update_bit_1(rc, prob_len); + prob_len = prob + LZMA_LEN_CHOICE_2; + if (rc_is_bit_0(rc, prob_len)) { + rc_update_bit_0(rc, prob_len); + prob_len = (prob + LZMA_LEN_MID + + (pos_state << + LZMA_LEN_NUM_MID_BITS)); + offset = 1 << LZMA_LEN_NUM_LOW_BITS; + num_bits = LZMA_LEN_NUM_MID_BITS; + } else { + rc_update_bit_1(rc, prob_len); + prob_len = prob + LZMA_LEN_HIGH; + offset = ((1 << LZMA_LEN_NUM_LOW_BITS) + + (1 << LZMA_LEN_NUM_MID_BITS)); + num_bits = LZMA_LEN_NUM_HIGH_BITS; + } + } + + rc_bit_tree_decode(rc, prob_len, num_bits, &len); + len += offset; + + if (cst->state < 4) { + int pos_slot; + + cst->state += LZMA_NUM_LIT_STATES; + prob = + p + LZMA_POS_SLOT + + ((len < + LZMA_NUM_LEN_TO_POS_STATES ? len : + LZMA_NUM_LEN_TO_POS_STATES - 1) + << LZMA_NUM_POS_SLOT_BITS); + rc_bit_tree_decode(rc, prob, + LZMA_NUM_POS_SLOT_BITS, + &pos_slot); + if (pos_slot >= LZMA_START_POS_MODEL_INDEX) { + int i, mi; + num_bits = (pos_slot >> 1) - 1; + cst->rep0 = 2 | (pos_slot & 1); + if (pos_slot < LZMA_END_POS_MODEL_INDEX) { + cst->rep0 <<= num_bits; + prob = p + LZMA_SPEC_POS + + cst->rep0 - pos_slot - 1; + } else { + num_bits -= LZMA_NUM_ALIGN_BITS; + while (num_bits--) + cst->rep0 = (cst->rep0 << 1) | + rc_direct_bit(rc); + prob = p + LZMA_ALIGN; + cst->rep0 <<= LZMA_NUM_ALIGN_BITS; + num_bits = LZMA_NUM_ALIGN_BITS; + } + i = 1; + mi = 1; + while (num_bits--) { + if (rc_get_bit(rc, prob + mi, &mi)) + cst->rep0 |= i; + i <<= 1; + } + } else + cst->rep0 = pos_slot; + if (++(cst->rep0) == 0) + return; + } + + len += LZMA_MATCH_MIN_LEN; + + copy_bytes(wr, cst->rep0, len); +} + + + +STATIC inline int INIT unlzma(unsigned char *buf, int in_len, + int(*fill)(void*, unsigned int), + int(*flush)(void*, unsigned int), + unsigned char *output, + int *posp, + void(*error_fn)(char *x) + ) +{ + struct lzma_header header; + int lc, pb, lp; + uint32_t pos_state_mask; + uint32_t literal_pos_mask; + uint16_t *p; + int num_probs; + struct rc rc; + int i, mi; + struct writer wr; + struct cstate cst; + unsigned char *inbuf; + int ret = -1; + + set_error_fn(error_fn); + if (!flush) + in_len -= 4; /* Uncompressed size hack active in pre-boot + environment */ + if (buf) + inbuf = buf; + else + inbuf = malloc(LZMA_IOBUF_SIZE); + if (!inbuf) { + error("Could not allocate input bufer"); + goto exit_0; + } + + cst.state = 0; + cst.rep0 = cst.rep1 = cst.rep2 = cst.rep3 = 1; + + wr.header = &header; + wr.flush = flush; + wr.global_pos = 0; + wr.previous_byte = 0; + wr.buffer_pos = 0; + + rc_init(&rc, fill, inbuf, in_len); + + for (i = 0; i < sizeof(header); i++) { + if (rc.ptr >= rc.buffer_end) + rc_read(&rc); + ((unsigned char *)&header)[i] = *rc.ptr++; + } + + if (header.pos >= (9 * 5 * 5)) + error("bad header"); + + mi = 0; + lc = header.pos; + while (lc >= 9) { + mi++; + lc -= 9; + } + pb = 0; + lp = mi; + while (lp >= 5) { + pb++; + lp -= 5; + } + pos_state_mask = (1 << pb) - 1; + literal_pos_mask = (1 << lp) - 1; + + ENDIAN_CONVERT(header.dict_size); + ENDIAN_CONVERT(header.dst_size); + + if (header.dict_size == 0) + header.dict_size = 1; + + if (output) + wr.buffer = output; + else { + wr.bufsize = MIN(header.dst_size, header.dict_size); + wr.buffer = large_malloc(wr.bufsize); + } + if (wr.buffer == NULL) + goto exit_1; + + num_probs = LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)); + p = (uint16_t *) large_malloc(num_probs * sizeof(*p)); + if (p == 0) + goto exit_2; + num_probs = LZMA_LITERAL + (LZMA_LIT_SIZE << (lc + lp)); + for (i = 0; i < num_probs; i++) + p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1; + + rc_init_code(&rc); + + while (get_pos(&wr) < header.dst_size) { + int pos_state = get_pos(&wr) & pos_state_mask; + uint16_t *prob = p + LZMA_IS_MATCH + + (cst.state << LZMA_NUM_POS_BITS_MAX) + pos_state; + if (rc_is_bit_0(&rc, prob)) + process_bit0(&wr, &rc, &cst, p, pos_state, prob, + lc, literal_pos_mask); + else { + process_bit1(&wr, &rc, &cst, p, pos_state, prob); + if (cst.rep0 == 0) + break; + } + } + + if (posp) + *posp = rc.ptr-rc.buffer; + if (wr.flush) + wr.flush(wr.buffer, wr.buffer_pos); + ret = 0; + large_free(p); +exit_2: + if (!output) + large_free(wr.buffer); +exit_1: + if (!buf) + free(inbuf); +exit_0: + return ret; +} + +#define decompress unlzma diff --git a/lib/zlib_inflate/inflate.h b/lib/zlib_inflate/inflate.h index df8a6c92052..3d17b3d1b21 100644 --- a/lib/zlib_inflate/inflate.h +++ b/lib/zlib_inflate/inflate.h @@ -1,3 +1,6 @@ +#ifndef INFLATE_H +#define INFLATE_H + /* inflate.h -- internal inflate state definition * Copyright (C) 1995-2004 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h @@ -105,3 +108,4 @@ struct inflate_state { unsigned short work[288]; /* work area for code table building */ code codes[ENOUGH]; /* space for code tables */ }; +#endif diff --git a/lib/zlib_inflate/inftrees.h b/lib/zlib_inflate/inftrees.h index 5f5219b1240..b70b4731ac7 100644 --- a/lib/zlib_inflate/inftrees.h +++ b/lib/zlib_inflate/inftrees.h @@ -1,3 +1,6 @@ +#ifndef INFTREES_H +#define INFTREES_H + /* inftrees.h -- header to use inftrees.c * Copyright (C) 1995-2005 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h @@ -53,3 +56,4 @@ typedef enum { extern int zlib_inflate_table (codetype type, unsigned short *lens, unsigned codes, code **table, unsigned *bits, unsigned short *work); +#endif diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index e06365775bd..70b4676e3b9 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -186,3 +186,17 @@ quiet_cmd_gzip = GZIP $@ cmd_gzip = gzip -f -9 < $< > $@ +# Bzip2 +# --------------------------------------------------------------------------- + +# Bzip2 does not include size in file... so we have to fake that +size_append=$(CONFIG_SHELL) $(srctree)/scripts/bin_size + +quiet_cmd_bzip2 = BZIP2 $@ +cmd_bzip2 = (bzip2 -9 < $< ; $(size_append) $<) > $@ || (rm -f $@ ; false) + +# Lzma +# --------------------------------------------------------------------------- + +quiet_cmd_lzma = LZMA $@ +cmd_lzma = (lzma -9 -c $< ; $(size_append) $<) >$@ || (rm -f $@ ; false) diff --git a/scripts/bin_size b/scripts/bin_size new file mode 100644 index 00000000000..43e1b360cee --- /dev/null +++ b/scripts/bin_size @@ -0,0 +1,10 @@ +#!/bin/sh + +if [ $# = 0 ] ; then + echo Usage: $0 file +fi + +size_dec=`stat -c "%s" $1` +size_hex_echo_string=`printf "%08x" $size_dec | + sed 's/\(..\)\(..\)\(..\)\(..\)/\\\\x\4\\\\x\3\\\\x\2\\\\x\1/g'` +/bin/echo -ne $size_hex_echo_string -- GitLab From 30d65dbfe3add7f010a075991dc0bfeaebb7d9e1 Mon Sep 17 00:00:00 2001 From: Alain Knaff Date: Sun, 4 Jan 2009 22:46:17 +0100 Subject: [PATCH 0048/4982] bzip2/lzma: config and initramfs support for bzip2/lzma decompression Impact: New code for initramfs decompression, new features This is the second part of the bzip2/lzma patch The bzip patch is based on an idea by Christian Ludwig, includes support for compressing the kernel with bzip2 or lzma rather than gzip. Both compressors give smaller sizes than gzip. Lzma's decompresses faster than bzip2. It also supports ramdisks and initramfs' compressed using these two compressors. The functionality has been successfully used for a couple of years by the udpcast project This version applies to "tip" kernel 2.6.28 This part contains: - support for new compressions (bzip2 and lzma) in initramfs and old-style ramdisk - config dialog for kernel compression (but new kernel compressions not yet supported) Signed-off-by: Alain Knaff Signed-off-by: H. Peter Anvin --- drivers/block/Kconfig | 25 ++++++ init/Kconfig | 50 ++++++++++++ init/do_mounts_rd.c | 182 +++++++++++++++--------------------------- init/initramfs.c | 123 ++++++++++------------------ lib/Makefile | 3 +- 5 files changed, 184 insertions(+), 199 deletions(-) diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 0344a8a8321..79559444242 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -358,6 +358,31 @@ config BLK_DEV_XIP will prevent RAM block device backing store memory from being allocated from highmem (only a problem for highmem systems). +config RD_BZIP2 + bool "Initial ramdisk compressed using bzip2" + default n + depends on BLK_DEV_INITRD=y + help + Support loading of a bzip2 encoded initial ramdisk or cpio buffer + If unsure, say N. + +config RD_LZMA + bool "Initial ramdisk compressed using lzma" + default n + depends on BLK_DEV_INITRD=y + help + Support loading of a lzma encoded initial ramdisk or cpio buffer + If unsure, say N. + +config RD_GZIP + bool "Initial ramdisk compressed using gzip" + default y + depends on BLK_DEV_INITRD=y + select ZLIB_INFLATE + help + Support loading of a gzip encoded initial ramdisk or cpio buffer. + If unsure, say Y. + config CDROM_PKTCDVD tristate "Packet writing on CD/DVD media" depends on !UML diff --git a/init/Kconfig b/init/Kconfig index f6281711166..df84625b137 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -101,6 +101,56 @@ config LOCALVERSION_AUTO which is done within the script "scripts/setlocalversion".) +choice + prompt "Kernel compression mode" + default KERNEL_GZIP + help + The linux kernel is a kind of self-extracting executable. + Several compression algorithms are available, which differ + in efficiency, compression and decompression speed. + Compression speed is only relevant when building a kernel. + Decompression speed is relevant at each boot. + + If you have any problems with bzip2 or lzma compressed + kernels, mail me (Alain Knaff) . (An older + version of this functionality (bzip2 only), for 2.4, was + supplied by Christian Ludwig) + + High compression options are mostly useful for users, who + are low on disk space (embedded systems), but for whom ram + size matters less. + + If in doubt, select 'gzip' + +config KERNEL_GZIP + bool "Gzip" + help + The old and tried gzip compression. Its compression ratio is + the poorest among the 3 choices; however its speed (both + compression and decompression) is the fastest. + +config KERNEL_BZIP2 + bool "Bzip2" + help + Its compression ratio and speed is intermediate. + Decompression speed is slowest among the 3. + The kernel size is about 10 per cent smaller with bzip2, + in comparison to gzip. + Bzip2 uses a large amount of memory. For modern kernels + you will need at least 8MB RAM or more for booting. + +config KERNEL_LZMA + bool "LZMA" + help + The most recent compression algorithm. + Its ratio is best, decompression speed is between the other + 2. Compression is slowest. + The kernel size is about 33 per cent smaller with lzma, + in comparison to gzip. + +endchoice + + config SWAP bool "Support for paging of anonymous memory (swap)" depends on MMU && BLOCK diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c index a7c748fa977..dcaeb1f90b3 100644 --- a/init/do_mounts_rd.c +++ b/init/do_mounts_rd.c @@ -10,6 +10,12 @@ #include "do_mounts.h" +#include + +#include +#include +#include + int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */ static int __init prompt_ramdisk(char *str) @@ -28,7 +34,7 @@ static int __init ramdisk_start_setup(char *str) } __setup("ramdisk_start=", ramdisk_start_setup); -static int __init crd_load(int in_fd, int out_fd); +static int __init crd_load(int in_fd, int out_fd, decompress_fn deco); /* * This routine tries to find a RAM disk image to load, and returns the @@ -44,7 +50,7 @@ static int __init crd_load(int in_fd, int out_fd); * gzip */ static int __init -identify_ramdisk_image(int fd, int start_block) +identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) { const int size = 512; struct minix_super_block *minixsb; @@ -70,6 +76,7 @@ identify_ramdisk_image(int fd, int start_block) sys_lseek(fd, start_block * BLOCK_SIZE, 0); sys_read(fd, buf, size); +#ifdef CONFIG_RD_GZIP /* * If it matches the gzip magic numbers, return 0 */ @@ -77,9 +84,39 @@ identify_ramdisk_image(int fd, int start_block) printk(KERN_NOTICE "RAMDISK: Compressed image found at block %d\n", start_block); + *decompressor = gunzip; + nblocks = 0; + goto done; + } +#endif + +#ifdef CONFIG_RD_BZIP2 + /* + * If it matches the bzip2 magic numbers, return -1 + */ + if (buf[0] == 0x42 && (buf[1] == 0x5a)) { + printk(KERN_NOTICE + "RAMDISK: Bzipped image found at block %d\n", + start_block); + *decompressor = bunzip2; + nblocks = 0; + goto done; + } +#endif + +#ifdef CONFIG_RD_LZMA + /* + * If it matches the lzma magic numbers, return -1 + */ + if (buf[0] == 0x5d && (buf[1] == 0x00)) { + printk(KERN_NOTICE + "RAMDISK: Lzma image found at block %d\n", + start_block); + *decompressor = unlzma; nblocks = 0; goto done; } +#endif /* romfs is at block zero too */ if (romfsb->word0 == ROMSB_WORD0 && @@ -143,6 +180,7 @@ int __init rd_load_image(char *from) int nblocks, i, disk; char *buf = NULL; unsigned short rotate = 0; + decompress_fn decompressor = NULL; #if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES) char rotator[4] = { '|' , '/' , '-' , '\\' }; #endif @@ -155,12 +193,12 @@ int __init rd_load_image(char *from) if (in_fd < 0) goto noclose_input; - nblocks = identify_ramdisk_image(in_fd, rd_image_start); + nblocks = identify_ramdisk_image(in_fd, rd_image_start, &decompressor); if (nblocks < 0) goto done; if (nblocks == 0) { - if (crd_load(in_fd, out_fd) == 0) + if (crd_load(in_fd, out_fd, decompressor) == 0) goto successful_load; goto done; } @@ -259,138 +297,48 @@ int __init rd_load_disk(int n) return rd_load_image("/dev/root"); } -/* - * gzip declarations - */ - -#define OF(args) args - -#ifndef memzero -#define memzero(s, n) memset ((s), 0, (n)) -#endif - -typedef unsigned char uch; -typedef unsigned short ush; -typedef unsigned long ulg; - -#define INBUFSIZ 4096 -#define WSIZE 0x8000 /* window size--must be a power of two, and */ - /* at least 32K for zip's deflate method */ - -static uch *inbuf; -static uch *window; - -static unsigned insize; /* valid bytes in inbuf */ -static unsigned inptr; /* index of next byte to be processed in inbuf */ -static unsigned outcnt; /* bytes in output buffer */ static int exit_code; -static int unzip_error; -static long bytes_out; +static int decompress_error; static int crd_infd, crd_outfd; -#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) - -/* Diagnostic functions (stubbed out) */ -#define Assert(cond,msg) -#define Trace(x) -#define Tracev(x) -#define Tracevv(x) -#define Tracec(c,x) -#define Tracecv(c,x) - -#define STATIC static -#define INIT __init - -static int __init fill_inbuf(void); -static void __init flush_window(void); -static void __init error(char *m); - -#define NO_INFLATE_MALLOC - -#include "../lib/inflate.c" - -/* =========================================================================== - * Fill the input buffer. This is called only when the buffer is empty - * and at least one byte is really needed. - * Returning -1 does not guarantee that gunzip() will ever return. - */ -static int __init fill_inbuf(void) +static int __init compr_fill(void *buf, unsigned int len) { - if (exit_code) return -1; - - insize = sys_read(crd_infd, inbuf, INBUFSIZ); - if (insize == 0) { - error("RAMDISK: ran out of compressed data"); - return -1; - } - - inptr = 1; - - return inbuf[0]; + int r = sys_read(crd_infd, buf, len); + if (r < 0) + printk(KERN_ERR "RAMDISK: error while reading compressed data"); + else if (r == 0) + printk(KERN_ERR "RAMDISK: EOF while reading compressed data"); + return r; } -/* =========================================================================== - * Write the output window window[0..outcnt-1] and update crc and bytes_out. - * (Used for the decompressed data only.) - */ -static void __init flush_window(void) +static int __init compr_flush(void *window, unsigned int outcnt) { - ulg c = crc; /* temporary variable */ - unsigned n, written; - uch *in, ch; - - written = sys_write(crd_outfd, window, outcnt); - if (written != outcnt && unzip_error == 0) { - printk(KERN_ERR "RAMDISK: incomplete write (%d != %d) %ld\n", - written, outcnt, bytes_out); - unzip_error = 1; - } - in = window; - for (n = 0; n < outcnt; n++) { - ch = *in++; - c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); - } - crc = c; - bytes_out += (ulg)outcnt; - outcnt = 0; + int written = sys_write(crd_outfd, window, outcnt); + if (written != outcnt) { + if (decompress_error == 0) + printk(KERN_ERR + "RAMDISK: incomplete write (%d != %d)\n", + written, outcnt); + decompress_error = 1; + return -1; + } + return outcnt; } static void __init error(char *x) { printk(KERN_ERR "%s\n", x); exit_code = 1; - unzip_error = 1; + decompress_error = 1; } -static int __init crd_load(int in_fd, int out_fd) +static int __init crd_load(int in_fd, int out_fd, decompress_fn deco) { int result; - - insize = 0; /* valid bytes in inbuf */ - inptr = 0; /* index of next byte to be processed in inbuf */ - outcnt = 0; /* bytes in output buffer */ - exit_code = 0; - bytes_out = 0; - crc = (ulg)0xffffffffL; /* shift register contents */ - crd_infd = in_fd; crd_outfd = out_fd; - inbuf = kmalloc(INBUFSIZ, GFP_KERNEL); - if (!inbuf) { - printk(KERN_ERR "RAMDISK: Couldn't allocate gzip buffer\n"); - return -1; - } - window = kmalloc(WSIZE, GFP_KERNEL); - if (!window) { - printk(KERN_ERR "RAMDISK: Couldn't allocate gzip window\n"); - kfree(inbuf); - return -1; - } - makecrc(); - result = gunzip(); - if (unzip_error) + result = deco(NULL, 0, compr_fill, compr_flush, NULL, NULL, error); + if (decompress_error) result = 1; - kfree(inbuf); - kfree(window); return result; } diff --git a/init/initramfs.c b/init/initramfs.c index 4f5ba75aaa7..40bd4fb9578 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -389,11 +389,14 @@ static int __init write_buffer(char *buf, unsigned len) return len - count; } -static void __init flush_buffer(char *buf, unsigned len) + +static int __init flush_buffer(void *bufv, unsigned len) { + char *buf = (char *) bufv; int written; + int origLen = len; if (message) - return; + return -1; while ((written = write_buffer(buf, len)) < len && !message) { char c = buf[written]; if (c == '0') { @@ -407,73 +410,14 @@ static void __init flush_buffer(char *buf, unsigned len) } else error("junk in compressed archive"); } + return origLen; } -/* - * gzip declarations - */ - -#define OF(args) args - -#ifndef memzero -#define memzero(s, n) memset ((s), 0, (n)) -#endif - -typedef unsigned char uch; -typedef unsigned short ush; -typedef unsigned long ulg; - -#define WSIZE 0x8000 /* window size--must be a power of two, and */ - /* at least 32K for zip's deflate method */ - -static uch *inbuf; -static uch *window; - -static unsigned insize; /* valid bytes in inbuf */ -static unsigned inptr; /* index of next byte to be processed in inbuf */ -static unsigned outcnt; /* bytes in output buffer */ -static long bytes_out; - -#define get_byte() (inptr < insize ? inbuf[inptr++] : -1) - -/* Diagnostic functions (stubbed out) */ -#define Assert(cond,msg) -#define Trace(x) -#define Tracev(x) -#define Tracevv(x) -#define Tracec(c,x) -#define Tracecv(c,x) - -#define STATIC static -#define INIT __init - -static void __init flush_window(void); -static void __init error(char *m); - -#define NO_INFLATE_MALLOC +static unsigned my_inptr; /* index of next byte to be processed in inbuf */ -#include "../lib/inflate.c" - -/* =========================================================================== - * Write the output window window[0..outcnt-1] and update crc and bytes_out. - * (Used for the decompressed data only.) - */ -static void __init flush_window(void) -{ - ulg c = crc; /* temporary variable */ - unsigned n; - uch *in, ch; - - flush_buffer(window, outcnt); - in = window; - for (n = 0; n < outcnt; n++) { - ch = *in++; - c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); - } - crc = c; - bytes_out += (ulg)outcnt; - outcnt = 0; -} +#include +#include +#include static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) { @@ -482,9 +426,10 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) header_buf = kmalloc(110, GFP_KERNEL); symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL); name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL); - window = kmalloc(WSIZE, GFP_KERNEL); - if (!window || !header_buf || !symlink_buf || !name_buf) + + if (!header_buf || !symlink_buf || !name_buf) panic("can't allocate buffers"); + state = Start; this_header = 0; message = NULL; @@ -504,22 +449,38 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) continue; } this_header = 0; - insize = len; - inbuf = buf; - inptr = 0; - outcnt = 0; /* bytes in output buffer */ - bytes_out = 0; - crc = (ulg)0xffffffffL; /* shift register contents */ - makecrc(); - gunzip(); + if (!gunzip(buf, len, NULL, flush_buffer, NULL, + &my_inptr, error) && + message == NULL) + goto ok; + +#ifdef CONFIG_RD_BZIP2 + message = NULL; /* Zero out message, or else cpio will + think an error has already occured */ + if (!bunzip2(buf, len, NULL, flush_buffer, NULL, + &my_inptr, error) && + message == NULL) { + goto ok; + } +#endif + +#ifdef CONFIG_RD_LZMA + message = NULL; /* Zero out message, or else cpio will + think an error has already occured */ + if (!unlzma(buf, len, NULL, flush_buffer, NULL, + &my_inptr, error) && + message == NULL) { + goto ok; + } +#endif +ok: if (state != Reset) - error("junk in gzipped archive"); - this_header = saved_offset + inptr; - buf += inptr; - len -= inptr; + error("junk in compressed archive"); + this_header = saved_offset + my_inptr; + buf += my_inptr; + len -= my_inptr; } dir_utime(); - kfree(window); kfree(name_buf); kfree(symlink_buf); kfree(header_buf); diff --git a/lib/Makefile b/lib/Makefile index 32b0e64ded2..e2a21d5a264 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -11,7 +11,8 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \ rbtree.o radix-tree.o dump_stack.o \ idr.o int_sqrt.o extable.o prio_tree.o \ sha1.o irq_regs.o reciprocal_div.o argv_split.o \ - proportions.o prio_heap.o ratelimit.o show_mem.o is_single_threaded.o + proportions.o prio_heap.o ratelimit.o show_mem.o is_single_threaded.o \ + decompress_inflate.o decompress_bunzip2.o decompress_unlzma.o lib-$(CONFIG_MMU) += ioremap.o lib-$(CONFIG_SMP) += cpumask.o -- GitLab From b172fd882d201cf8aa67cddd9c1a023421fd4956 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sun, 4 Jan 2009 14:42:52 -0800 Subject: [PATCH 0049/4982] bzip2/lzma: use a table to search for initramfs compression formats Impact: Code simplification Instead of open-coding testing for initramfs compression formats, use a table. Signed-off-by: H. Peter Anvin --- init/do_mounts_rd.c | 82 +++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 47 deletions(-) diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c index dcaeb1f90b3..9c9d7dbcf9c 100644 --- a/init/do_mounts_rd.c +++ b/init/do_mounts_rd.c @@ -43,13 +43,31 @@ static int __init crd_load(int in_fd, int out_fd, decompress_fn deco); * numbers could not be found. * * We currently check for the following magic numbers: - * minix - * ext2 + * minix + * ext2 * romfs * cramfs - * gzip + * gzip */ -static int __init +static const struct compress_format { + unsigned char magic[2]; + const char *name; + decompress_fn decompressor; +} compressed_formats[] = { +#ifdef CONFIG_RD_GZIP + { {037, 0213}, "gzip", gunzip }, + { {037, 0236}, "gzip", gunzip }, +#endif +#ifdef CONFIG_RD_BZIP2 + { {0x42, 0x5a}, "bzip2", bunzip2 }, +#endif +#ifdef CONFIG_RD_LZMA + { {0x5d, 0x00}, "lzma", unlzma }, +#endif + { {0, 0}, NULL, NULL } +}; + +static int __init identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) { const int size = 512; @@ -59,6 +77,7 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) struct cramfs_super *cramfsb; int nblocks = -1; unsigned char *buf; + const struct compress_format *cf; buf = kmalloc(size, GFP_KERNEL); if (!buf) @@ -71,52 +90,21 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) memset(buf, 0xe5, size); /* - * Read block 0 to test for gzipped kernel + * Read block 0 to test for compressed kernel */ sys_lseek(fd, start_block * BLOCK_SIZE, 0); sys_read(fd, buf, size); -#ifdef CONFIG_RD_GZIP - /* - * If it matches the gzip magic numbers, return 0 - */ - if (buf[0] == 037 && ((buf[1] == 0213) || (buf[1] == 0236))) { - printk(KERN_NOTICE - "RAMDISK: Compressed image found at block %d\n", - start_block); - *decompressor = gunzip; - nblocks = 0; - goto done; - } -#endif - -#ifdef CONFIG_RD_BZIP2 - /* - * If it matches the bzip2 magic numbers, return -1 - */ - if (buf[0] == 0x42 && (buf[1] == 0x5a)) { - printk(KERN_NOTICE - "RAMDISK: Bzipped image found at block %d\n", - start_block); - *decompressor = bunzip2; - nblocks = 0; - goto done; - } -#endif - -#ifdef CONFIG_RD_LZMA - /* - * If it matches the lzma magic numbers, return -1 - */ - if (buf[0] == 0x5d && (buf[1] == 0x00)) { - printk(KERN_NOTICE - "RAMDISK: Lzma image found at block %d\n", - start_block); - *decompressor = unlzma; - nblocks = 0; - goto done; + for (cf = compressed_formats; cf->decompressor; cf++) { + if (buf[0] == cf->magic[0] && buf[1] == cf->magic[1]) { + printk(KERN_NOTICE + "RAMDISK: %s image found at block %d\n", + cf->name, start_block); + *decompressor = cf->decompressor; + nblocks = 0; + goto done; + } } -#endif /* romfs is at block zero too */ if (romfsb->word0 == ROMSB_WORD0 && @@ -165,7 +153,7 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) printk(KERN_NOTICE "RAMDISK: Couldn't find valid RAM disk image starting at %d.\n", start_block); - + done: sys_lseek(fd, start_block * BLOCK_SIZE, 0); kfree(buf); @@ -224,7 +212,7 @@ int __init rd_load_image(char *from) nblocks, rd_blocks); goto done; } - + /* * OK, time to copy in the data */ -- GitLab From ae03c49964af5033534e518eebe439c3b90f43a7 Mon Sep 17 00:00:00 2001 From: Alain Knaff Date: Sun, 4 Jan 2009 22:46:17 +0100 Subject: [PATCH 0050/4982] bzip2/lzma: x86 kernel compression support Impact: Replaces x86 kernel decompressor with new code This is the third part of the bzip2/lzma patch The bzip patch is based on an idea by Christian Ludwig, includes support for compressing the kernel with bzip2 or lzma rather than gzip. Both compressors give smaller sizes than gzip. Lzma's decompresses faster than bzip2. It also supports ramdisks and initramfs' compressed using these two compressors. The functionality has been successfully used for a couple of years by the udpcast project This version applies to "tip" kernel 2.6.28 This part contains: - support for new bzip2 and lzma kernel compression for x86 Signed-off-by: Alain Knaff Signed-off-by: H. Peter Anvin --- arch/x86/boot/compressed/Makefile | 21 +++++- arch/x86/boot/compressed/misc.c | 118 ++++-------------------------- arch/x86/include/asm/boot.h | 12 ++- 3 files changed, 44 insertions(+), 107 deletions(-) diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 1771c804e02..3ca4c194b8e 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -4,7 +4,7 @@ # create a compressed vmlinux image from the original vmlinux # -targets := vmlinux vmlinux.bin vmlinux.bin.gz head_$(BITS).o misc.o piggy.o +targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma head_$(BITS).o misc.o piggy.o KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 KBUILD_CFLAGS += -fno-strict-aliasing -fPIC @@ -47,18 +47,35 @@ ifeq ($(CONFIG_X86_32),y) ifdef CONFIG_RELOCATABLE $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin.all FORCE $(call if_changed,gzip) +$(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin.all FORCE + $(call if_changed,bzip2) +$(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin.all FORCE + $(call if_changed,lzma) else $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE $(call if_changed,gzip) +$(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin FORCE + $(call if_changed,bzip2) +$(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE + $(call if_changed,lzma) endif LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T else + $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE $(call if_changed,gzip) +$(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin FORCE + $(call if_changed,bzip2) +$(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE + $(call if_changed,lzma) LDFLAGS_piggy.o := -r --format binary --oformat elf64-x86-64 -T endif -$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE +suffix_$(CONFIG_KERNEL_GZIP) = gz +suffix_$(CONFIG_KERNEL_BZIP2) = bz2 +suffix_$(CONFIG_KERNEL_LZMA) = lzma + +$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix_y) FORCE $(call if_changed,ld) diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index da062216948..e45be73684f 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -116,71 +116,13 @@ /* * gzip declarations */ - -#define OF(args) args #define STATIC static #undef memset #undef memcpy #define memzero(s, n) memset((s), 0, (n)) -typedef unsigned char uch; -typedef unsigned short ush; -typedef unsigned long ulg; - -/* - * Window size must be at least 32k, and a power of two. - * We don't actually have a window just a huge output buffer, - * so we report a 2G window size, as that should always be - * larger than our output buffer: - */ -#define WSIZE 0x80000000 - -/* Input buffer: */ -static unsigned char *inbuf; - -/* Sliding window buffer (and final output buffer): */ -static unsigned char *window; - -/* Valid bytes in inbuf: */ -static unsigned insize; - -/* Index of next byte to be processed in inbuf: */ -static unsigned inptr; - -/* Bytes in output buffer: */ -static unsigned outcnt; - -/* gzip flag byte */ -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ -#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gz file */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAM 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ -#define RESERVED 0xC0 /* bit 6, 7: reserved */ - -#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) - -/* Diagnostic functions */ -#ifdef DEBUG -# define Assert(cond, msg) do { if (!(cond)) error(msg); } while (0) -# define Trace(x) do { fprintf x; } while (0) -# define Tracev(x) do { if (verbose) fprintf x ; } while (0) -# define Tracevv(x) do { if (verbose > 1) fprintf x ; } while (0) -# define Tracec(c, x) do { if (verbose && (c)) fprintf x ; } while (0) -# define Tracecv(c, x) do { if (verbose > 1 && (c)) fprintf x ; } while (0) -#else -# define Assert(cond, msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c, x) -# define Tracecv(c, x) -#endif -static int fill_inbuf(void); -static void flush_window(void); static void error(char *m); /* @@ -189,13 +131,8 @@ static void error(char *m); static struct boot_params *real_mode; /* Pointer to real-mode data */ static int quiet; -extern unsigned char input_data[]; -extern int input_len; - -static long bytes_out; - static void *memset(void *s, int c, unsigned n); -static void *memcpy(void *dest, const void *src, unsigned n); +void *memcpy(void *dest, const void *src, unsigned n); static void __putstr(int, const char *); #define putstr(__x) __putstr(0, __x) @@ -213,7 +150,17 @@ static char *vidmem; static int vidport; static int lines, cols; -#include "../../../../lib/inflate.c" +#ifdef CONFIG_KERNEL_GZIP +#include "../../../../lib/decompress_inflate.c" +#endif + +#ifdef CONFIG_KERNEL_BZIP2 +#include "../../../../lib/decompress_bunzip2.c" +#endif + +#ifdef CONFIG_KERNEL_LZMA +#include "../../../../lib/decompress_unlzma.c" +#endif static void scroll(void) { @@ -282,7 +229,7 @@ static void *memset(void *s, int c, unsigned n) return s; } -static void *memcpy(void *dest, const void *src, unsigned n) +void *memcpy(void *dest, const void *src, unsigned n) { int i; const char *s = src; @@ -293,38 +240,6 @@ static void *memcpy(void *dest, const void *src, unsigned n) return dest; } -/* =========================================================================== - * Fill the input buffer. This is called only when the buffer is empty - * and at least one byte is really needed. - */ -static int fill_inbuf(void) -{ - error("ran out of input data"); - return 0; -} - -/* =========================================================================== - * Write the output window window[0..outcnt-1] and update crc and bytes_out. - * (Used for the decompressed data only.) - */ -static void flush_window(void) -{ - /* With my window equal to my output buffer - * I only need to compute the crc here. - */ - unsigned long c = crc; /* temporary variable */ - unsigned n; - unsigned char *in, ch; - - in = window; - for (n = 0; n < outcnt; n++) { - ch = *in++; - c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); - } - crc = c; - bytes_out += (unsigned long)outcnt; - outcnt = 0; -} static void error(char *x) { @@ -407,12 +322,8 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap, lines = real_mode->screen_info.orig_video_lines; cols = real_mode->screen_info.orig_video_cols; - window = output; /* Output buffer (Normally at 1M) */ free_mem_ptr = heap; /* Heap */ free_mem_end_ptr = heap + BOOT_HEAP_SIZE; - inbuf = input_data; /* Input buffer */ - insize = input_len; - inptr = 0; #ifdef CONFIG_X86_64 if ((unsigned long)output & (__KERNEL_ALIGN - 1)) @@ -430,10 +341,9 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap, #endif #endif - makecrc(); if (!quiet) putstr("\nDecompressing Linux... "); - gunzip(); + decompress(input_data, input_len, NULL, NULL, output, NULL, error); parse_elf(output); if (!quiet) putstr("done.\nBooting the kernel.\n"); diff --git a/arch/x86/include/asm/boot.h b/arch/x86/include/asm/boot.h index dd61616cb73..c0e8e68a31f 100644 --- a/arch/x86/include/asm/boot.h +++ b/arch/x86/include/asm/boot.h @@ -15,11 +15,21 @@ + (CONFIG_PHYSICAL_ALIGN - 1)) \ & ~(CONFIG_PHYSICAL_ALIGN - 1)) +#if (defined CONFIG_KERNEL_BZIP2) +#define BOOT_HEAP_SIZE 0x400000 +#else + #ifdef CONFIG_X86_64 #define BOOT_HEAP_SIZE 0x7000 -#define BOOT_STACK_SIZE 0x4000 #else #define BOOT_HEAP_SIZE 0x4000 +#endif + +#endif + +#ifdef CONFIG_X86_64 +#define BOOT_STACK_SIZE 0x4000 +#else #define BOOT_STACK_SIZE 0x1000 #endif -- GitLab From 0f5e2d2484ccd3062bb1f63083bafa37041bc868 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sun, 4 Jan 2009 15:10:40 -0800 Subject: [PATCH 0051/4982] bzip2/lzma: handle failures from bzip2 and lzma correctly Impact: Bug fix If bzip2 or lzma fails (for example, if they aren't installed on the system), we need to propagate the failure out to "make". However, they were masked by being followed by a semicolon. Signed-off-by: H. Peter Anvin --- scripts/Makefile.lib | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 70b4676e3b9..3b949a35447 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -193,10 +193,10 @@ cmd_gzip = gzip -f -9 < $< > $@ size_append=$(CONFIG_SHELL) $(srctree)/scripts/bin_size quiet_cmd_bzip2 = BZIP2 $@ -cmd_bzip2 = (bzip2 -9 < $< ; $(size_append) $<) > $@ || (rm -f $@ ; false) +cmd_bzip2 = (bzip2 -9 < $< && $(size_append) $<) > $@ || (rm -f $@ ; false) # Lzma # --------------------------------------------------------------------------- quiet_cmd_lzma = LZMA $@ -cmd_lzma = (lzma -9 -c $< ; $(size_append) $<) >$@ || (rm -f $@ ; false) +cmd_lzma = (lzma -9 -c $< && $(size_append) $<) >$@ || (rm -f $@ ; false) -- GitLab From 2e9f3bddcbc711bb14d86c6f068a779bf3710247 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sun, 4 Jan 2009 15:41:25 -0800 Subject: [PATCH 0052/4982] bzip2/lzma: make config machinery an arch configurable Impact: Bug fix (we should not show this menu on irrelevant architectures) Make the config machinery to drive the gzip/bzip2/lzma selection dependent on the architecture advertising HAVE_KERNEL_* so that we don't display this for architectures where it doesn't matter. Signed-off-by: H. Peter Anvin --- arch/x86/Kconfig | 3 +++ init/Kconfig | 52 +++++++++++++++++++++++++++++------------------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 862adb9bf0d..7b66c34d0aa 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -39,6 +39,9 @@ config X86 select HAVE_GENERIC_DMA_COHERENT if X86_32 select HAVE_EFFICIENT_UNALIGNED_ACCESS select USER_STACKTRACE_SUPPORT + select HAVE_KERNEL_GZIP + select HAVE_KERNEL_BZIP2 + select HAVE_KERNEL_LZMA config ARCH_DEFCONFIG string diff --git a/init/Kconfig b/init/Kconfig index df84625b137..f9633c03cb1 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -101,10 +101,20 @@ config LOCALVERSION_AUTO which is done within the script "scripts/setlocalversion".) +config HAVE_KERNEL_GZIP + bool + +config HAVE_KERNEL_BZIP2 + bool + +config HAVE_KERNEL_LZMA + bool + choice - prompt "Kernel compression mode" - default KERNEL_GZIP - help + prompt "Kernel compression mode" + default KERNEL_GZIP + depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA + help The linux kernel is a kind of self-extracting executable. Several compression algorithms are available, which differ in efficiency, compression and decompression speed. @@ -123,34 +133,34 @@ choice If in doubt, select 'gzip' config KERNEL_GZIP - bool "Gzip" - help - The old and tried gzip compression. Its compression ratio is - the poorest among the 3 choices; however its speed (both - compression and decompression) is the fastest. + bool "Gzip" + depends on HAVE_KERNEL_GZIP + help + The old and tried gzip compression. Its compression ratio is + the poorest among the 3 choices; however its speed (both + compression and decompression) is the fastest. config KERNEL_BZIP2 bool "Bzip2" + depends on HAVE_KERNEL_BZIP2 help Its compression ratio and speed is intermediate. - Decompression speed is slowest among the 3. - The kernel size is about 10 per cent smaller with bzip2, - in comparison to gzip. - Bzip2 uses a large amount of memory. For modern kernels - you will need at least 8MB RAM or more for booting. + Decompression speed is slowest among the three. The kernel + size is about 10% smaller with bzip2, in comparison to gzip. + Bzip2 uses a large amount of memory. For modern kernels you + will need at least 8MB RAM or more for booting. config KERNEL_LZMA - bool "LZMA" - help - The most recent compression algorithm. - Its ratio is best, decompression speed is between the other - 2. Compression is slowest. - The kernel size is about 33 per cent smaller with lzma, - in comparison to gzip. + bool "LZMA" + depends on HAVE_KERNEL_LZMA + help + The most recent compression algorithm. + Its ratio is best, decompression speed is between the other + two. Compression is slowest. The kernel size is about 33% + smaller with LZMA in comparison to gzip. endchoice - config SWAP bool "Support for paging of anonymous memory (swap)" depends on MMU && BLOCK -- GitLab From c8531ab343dec88ed8005e403b1b304c710b7494 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 5 Jan 2009 13:48:31 -0800 Subject: [PATCH 0053/4982] bzip2/lzma: proper Kconfig dependencies for the ramdisk options Impact: Partial resolution of build failure Make all the compression algorithms properly configurable, and make sure the ramdisk options pull in the proper compression algorithms, as they should. Signed-off-by: H. Peter Anvin --- drivers/block/Kconfig | 20 +++++++++++--------- lib/Kconfig | 13 +++++++++++++ lib/Makefile | 7 +++++-- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 79559444242..cc9fa69c1ce 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -358,10 +358,20 @@ config BLK_DEV_XIP will prevent RAM block device backing store memory from being allocated from highmem (only a problem for highmem systems). +config RD_GZIP + bool "Initial ramdisk compressed using gzip" + default y + depends on BLK_DEV_INITRD=y + select DECOMPRESS_GZIP + help + Support loading of a gzip encoded initial ramdisk or cpio buffer. + If unsure, say Y. + config RD_BZIP2 bool "Initial ramdisk compressed using bzip2" default n depends on BLK_DEV_INITRD=y + select DECOMPRESS_BZIP2 help Support loading of a bzip2 encoded initial ramdisk or cpio buffer If unsure, say N. @@ -370,19 +380,11 @@ config RD_LZMA bool "Initial ramdisk compressed using lzma" default n depends on BLK_DEV_INITRD=y + select DECOMPRESS_LZMA help Support loading of a lzma encoded initial ramdisk or cpio buffer If unsure, say N. -config RD_GZIP - bool "Initial ramdisk compressed using gzip" - default y - depends on BLK_DEV_INITRD=y - select ZLIB_INFLATE - help - Support loading of a gzip encoded initial ramdisk or cpio buffer. - If unsure, say Y. - config CDROM_PKTCDVD tristate "Packet writing on CD/DVD media" depends on !UML diff --git a/lib/Kconfig b/lib/Kconfig index 03c2c24b908..e37f061fd32 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -97,6 +97,19 @@ config LZO_COMPRESS config LZO_DECOMPRESS tristate +# +# These all provide a common interface (hence the apparent duplication with +# ZLIB_INFLATE; DECOMPRESS_GZIP is just a wrapper.) +# +config DECOMPRESS_GZIP + tristate + +config DECOMPRESS_BZIP2 + tristate + +config DECOMPRESS_LZMA + tristate + # # Generic allocator support is selected if needed # diff --git a/lib/Makefile b/lib/Makefile index e2a21d5a264..d9ac5a414fa 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -11,8 +11,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \ rbtree.o radix-tree.o dump_stack.o \ idr.o int_sqrt.o extable.o prio_tree.o \ sha1.o irq_regs.o reciprocal_div.o argv_split.o \ - proportions.o prio_heap.o ratelimit.o show_mem.o is_single_threaded.o \ - decompress_inflate.o decompress_bunzip2.o decompress_unlzma.o + proportions.o prio_heap.o ratelimit.o show_mem.o is_single_threaded.o lib-$(CONFIG_MMU) += ioremap.o lib-$(CONFIG_SMP) += cpumask.o @@ -66,6 +65,10 @@ obj-$(CONFIG_REED_SOLOMON) += reed_solomon/ obj-$(CONFIG_LZO_COMPRESS) += lzo/ obj-$(CONFIG_LZO_DECOMPRESS) += lzo/ +obj-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o +obj-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o +obj-$(CONFIG_DECOMPRESS_LZMA) += decompress_unlzma.o + obj-$(CONFIG_TEXTSEARCH) += textsearch.o obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o obj-$(CONFIG_TEXTSEARCH_BM) += ts_bm.o -- GitLab From 7856a16ea03ed9b17860d756ee6473c2e57882b2 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 7 Jan 2009 00:01:43 -0800 Subject: [PATCH 0054/4982] bzip2/lzma: DECOMPRESS_GZIP should select ZLIB_INFLATE Impact: Partial resolution of build failure DECOMPRESS_GZIP is just a common-interface wrapper around the zlib_inflate code; it thus need to select it. Signed-off-by: H. Peter Anvin --- lib/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Kconfig b/lib/Kconfig index e37f061fd32..daa481824d9 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -102,6 +102,7 @@ config LZO_DECOMPRESS # ZLIB_INFLATE; DECOMPRESS_GZIP is just a wrapper.) # config DECOMPRESS_GZIP + select ZLIB_INFLATE tristate config DECOMPRESS_BZIP2 -- GitLab From fb9a4ca9820fd4d7c4906bd393004662451e273e Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 7 Jan 2009 00:03:49 -0800 Subject: [PATCH 0055/4982] bzip2/lzma: move initrd/ramfs options out of BLK_DEV Impact: Partial resolution of build failure Move the initrd/initramfs configuration options from drivers/block/Kconfig to usr/Kconfig, since they do not and should not depend on CONFIG_BLK_DEV. This fixes builds when CONFIG_BLK_DEV=n. Signed-off-by: H. Peter Anvin --- drivers/block/Kconfig | 27 --------------------------- usr/Kconfig | 27 +++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index cc9fa69c1ce..0344a8a8321 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -358,33 +358,6 @@ config BLK_DEV_XIP will prevent RAM block device backing store memory from being allocated from highmem (only a problem for highmem systems). -config RD_GZIP - bool "Initial ramdisk compressed using gzip" - default y - depends on BLK_DEV_INITRD=y - select DECOMPRESS_GZIP - help - Support loading of a gzip encoded initial ramdisk or cpio buffer. - If unsure, say Y. - -config RD_BZIP2 - bool "Initial ramdisk compressed using bzip2" - default n - depends on BLK_DEV_INITRD=y - select DECOMPRESS_BZIP2 - help - Support loading of a bzip2 encoded initial ramdisk or cpio buffer - If unsure, say N. - -config RD_LZMA - bool "Initial ramdisk compressed using lzma" - default n - depends on BLK_DEV_INITRD=y - select DECOMPRESS_LZMA - help - Support loading of a lzma encoded initial ramdisk or cpio buffer - If unsure, say N. - config CDROM_PKTCDVD tristate "Packet writing on CD/DVD media" depends on !UML diff --git a/usr/Kconfig b/usr/Kconfig index 86cecb59dd0..a691a8f5898 100644 --- a/usr/Kconfig +++ b/usr/Kconfig @@ -44,3 +44,30 @@ config INITRAMFS_ROOT_GID owned by group root in the initial ramdisk image. If you are not sure, leave it set to "0". + +config RD_GZIP + bool "Initial ramdisk compressed using gzip" + default y + depends on BLK_DEV_INITRD=y + select DECOMPRESS_GZIP + help + Support loading of a gzip encoded initial ramdisk or cpio buffer. + If unsure, say Y. + +config RD_BZIP2 + bool "Initial ramdisk compressed using bzip2" + default n + depends on BLK_DEV_INITRD=y + select DECOMPRESS_BZIP2 + help + Support loading of a bzip2 encoded initial ramdisk or cpio buffer + If unsure, say N. + +config RD_LZMA + bool "Initial ramdisk compressed using lzma" + default n + depends on BLK_DEV_INITRD=y + select DECOMPRESS_LZMA + help + Support loading of a lzma encoded initial ramdisk or cpio buffer + If unsure, say N. -- GitLab From a26ee60f90daffe1de6be0d093af86e7279b3dfd Mon Sep 17 00:00:00 2001 From: Alain Knaff Date: Wed, 7 Jan 2009 00:10:27 -0800 Subject: [PATCH 0056/4982] bzip2/lzma: fix built-in initramfs vs CONFIG_RD_GZIP Impact: Resolves build failures in some configurations Makes it possible to disable CONFIG_RD_GZIP . In that case, the built-in initramfs will be compressed by whatever compressor is available (bzip2 or lzma) or left uncompressed if none is available. It also removes a couple of warnings which occur when no ramdisk compression at all is chosen. It also restores the select ZLIB_INFLATE in drivers/block/Kconfig which somehow came missing. This is needed to activate compilation of the stuff in zlib_deflate. Signed-off-by: Alain Knaff Signed-off-by: H. Peter Anvin --- init/initramfs.c | 7 +++++- scripts/gen_initramfs_list.sh | 17 +++++++++----- usr/Makefile | 42 +++++++++++++++++++++++++---------- usr/initramfs_data.S | 2 +- usr/initramfs_data.bz2.S | 29 ++++++++++++++++++++++++ usr/initramfs_data.gz.S | 29 ++++++++++++++++++++++++ usr/initramfs_data.lzma.S | 29 ++++++++++++++++++++++++ 7 files changed, 135 insertions(+), 20 deletions(-) create mode 100644 usr/initramfs_data.bz2.S create mode 100644 usr/initramfs_data.gz.S create mode 100644 usr/initramfs_data.lzma.S diff --git a/init/initramfs.c b/init/initramfs.c index 40bd4fb9578..a3ba91cdab8 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -389,7 +389,7 @@ static int __init write_buffer(char *buf, unsigned len) return len - count; } - +#if defined CONFIG_RD_GZIP || defined CONFIG_RD_BZIP2 || defined CONFIG_RD_LZMA static int __init flush_buffer(void *bufv, unsigned len) { char *buf = (char *) bufv; @@ -412,6 +412,7 @@ static int __init flush_buffer(void *bufv, unsigned len) } return origLen; } +#endif static unsigned my_inptr; /* index of next byte to be processed in inbuf */ @@ -449,10 +450,12 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) continue; } this_header = 0; +#ifdef CONFIG_RD_GZIP if (!gunzip(buf, len, NULL, flush_buffer, NULL, &my_inptr, error) && message == NULL) goto ok; +#endif #ifdef CONFIG_RD_BZIP2 message = NULL; /* Zero out message, or else cpio will @@ -473,7 +476,9 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) goto ok; } #endif +#if defined CONFIG_RD_GZIP || defined CONFIG_RD_BZIP2 || defined CONFIG_RD_LZMA ok: +#endif if (state != Reset) error("junk in compressed archive"); this_header = saved_offset + my_inptr; diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh index 5f3415f2873..41041e4923f 100644 --- a/scripts/gen_initramfs_list.sh +++ b/scripts/gen_initramfs_list.sh @@ -5,7 +5,7 @@ # Released under the terms of the GNU GPL # # Generate a cpio packed initramfs. It uses gen_init_cpio to generate -# the cpio archive, and gzip to pack it. +# the cpio archive, and then compresses it. # The script may also be used to generate the inputfile used for gen_init_cpio # This script assumes that gen_init_cpio is located in usr/ directory @@ -16,8 +16,8 @@ usage() { cat << EOF Usage: $0 [-o ] [-u ] [-g ] {-d | } ... - -o Create gzipped initramfs file named using - gen_init_cpio and gzip + -o Create compressed initramfs file named using + gen_init_cpio and compressor depending on the extension -u User ID to map to user ID 0 (root). is only meaningful if is a directory. "squash" forces all files to uid 0. @@ -225,6 +225,7 @@ cpio_list= output="/dev/stdout" output_file="" is_cpio_compressed= +compr="gzip -9 -f" arg="$1" case "$arg" in @@ -233,11 +234,15 @@ case "$arg" in echo "deps_initramfs := \\" shift ;; - "-o") # generate gzipped cpio image named $1 + "-o") # generate compressed cpio image named $1 shift output_file="$1" cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)" output=${cpio_list} + echo "$output_file" | grep -q "\.gz$" && compr="gzip -9 -f" + echo "$output_file" | grep -q "\.bz2$" && compr="bzip2 -9 -f" + echo "$output_file" | grep -q "\.lzma$" && compr="lzma -9 -f" + echo "$output_file" | grep -q "\.cpio$" && compr="cat" shift ;; esac @@ -274,7 +279,7 @@ while [ $# -gt 0 ]; do esac done -# If output_file is set we will generate cpio archive and gzip it +# If output_file is set we will generate cpio archive and compress it # we are carefull to delete tmp files if [ ! -z ${output_file} ]; then if [ -z ${cpio_file} ]; then @@ -287,7 +292,7 @@ if [ ! -z ${output_file} ]; then if [ "${is_cpio_compressed}" = "compressed" ]; then cat ${cpio_tfile} > ${output_file} else - cat ${cpio_tfile} | gzip -f -9 - > ${output_file} + cat ${cpio_tfile} | ${compr} - > ${output_file} fi [ -z ${cpio_file} ] && rm ${cpio_tfile} fi diff --git a/usr/Makefile b/usr/Makefile index 201f27f8cba..451cdff7dff 100644 --- a/usr/Makefile +++ b/usr/Makefile @@ -5,14 +5,32 @@ klibcdirs:; PHONY += klibcdirs +# Find out "preferred" ramdisk compressor. Order of preference is +# 1. bzip2 efficient, and likely to be present +# 2. gzip former default +# 3. lzma +# 4. none + +# None of the above +suffix_y = + +# Lzma, but no gzip nor bzip2 +suffix_$(CONFIG_RD_LZMA) = .lzma + +# Gzip, but no bzip2 +suffix_$(CONFIG_RD_GZIP) = .gz + +# Bzip2 +suffix_$(CONFIG_RD_BZIP2) = .bz2 + # Generate builtin.o based on initramfs_data.o -obj-$(CONFIG_BLK_DEV_INITRD) := initramfs_data.o +obj-$(CONFIG_BLK_DEV_INITRD) := initramfs_data$(suffix_y).o -# initramfs_data.o contains the initramfs_data.cpio.gz image. +# initramfs_data.o contains the compressed initramfs_data.cpio image. # The image is included using .incbin, a dependency which is not # tracked automatically. -$(obj)/initramfs_data.o: $(obj)/initramfs_data.cpio.gz FORCE +$(obj)/initramfs_data$(suffix_y).o: $(obj)/initramfs_data.cpio$(suffix_y) FORCE ##### # Generate the initramfs cpio archive @@ -25,28 +43,28 @@ ramfs-args := \ $(if $(CONFIG_INITRAMFS_ROOT_UID), -u $(CONFIG_INITRAMFS_ROOT_UID)) \ $(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID)) -# .initramfs_data.cpio.gz.d is used to identify all files included +# .initramfs_data.cpio.d is used to identify all files included # in initramfs and to detect if any files are added/removed. # Removed files are identified by directory timestamp being updated # The dependency list is generated by gen_initramfs.sh -l -ifneq ($(wildcard $(obj)/.initramfs_data.cpio.gz.d),) - include $(obj)/.initramfs_data.cpio.gz.d +ifneq ($(wildcard $(obj)/.initramfs_data.cpio.d),) + include $(obj)/.initramfs_data.cpio.d endif quiet_cmd_initfs = GEN $@ cmd_initfs = $(initramfs) -o $@ $(ramfs-args) $(ramfs-input) -targets := initramfs_data.cpio.gz +targets := initramfs_data.cpio.gz initramfs_data.cpio.bz2 initramfs_data.cpio.lzma initramfs_data.cpio # do not try to update files included in initramfs $(deps_initramfs): ; $(deps_initramfs): klibcdirs -# We rebuild initramfs_data.cpio.gz if: -# 1) Any included file is newer then initramfs_data.cpio.gz +# We rebuild initramfs_data.cpio if: +# 1) Any included file is newer then initramfs_data.cpio # 2) There are changes in which files are included (added or deleted) -# 3) If gen_init_cpio are newer than initramfs_data.cpio.gz +# 3) If gen_init_cpio are newer than initramfs_data.cpio # 4) arguments to gen_initramfs.sh changes -$(obj)/initramfs_data.cpio.gz: $(obj)/gen_init_cpio $(deps_initramfs) klibcdirs - $(Q)$(initramfs) -l $(ramfs-input) > $(obj)/.initramfs_data.cpio.gz.d +$(obj)/initramfs_data.cpio$(suffix_y): $(obj)/gen_init_cpio $(deps_initramfs) klibcdirs + $(Q)$(initramfs) -l $(ramfs-input) > $(obj)/.initramfs_data.cpio.d $(call if_changed,initfs) diff --git a/usr/initramfs_data.S b/usr/initramfs_data.S index c2e1ad424f4..7c6973d8d82 100644 --- a/usr/initramfs_data.S +++ b/usr/initramfs_data.S @@ -26,5 +26,5 @@ SECTIONS */ .section .init.ramfs,"a" -.incbin "usr/initramfs_data.cpio.gz" +.incbin "usr/initramfs_data.cpio" diff --git a/usr/initramfs_data.bz2.S b/usr/initramfs_data.bz2.S new file mode 100644 index 00000000000..bc54d090365 --- /dev/null +++ b/usr/initramfs_data.bz2.S @@ -0,0 +1,29 @@ +/* + initramfs_data includes the compressed binary that is the + filesystem used for early user space. + Note: Older versions of "as" (prior to binutils 2.11.90.0.23 + released on 2001-07-14) dit not support .incbin. + If you are forced to use older binutils than that then the + following trick can be applied to create the resulting binary: + + + ld -m elf_i386 --format binary --oformat elf32-i386 -r \ + -T initramfs_data.scr initramfs_data.cpio.gz -o initramfs_data.o + ld -m elf_i386 -r -o built-in.o initramfs_data.o + + initramfs_data.scr looks like this: +SECTIONS +{ + .init.ramfs : { *(.data) } +} + + The above example is for i386 - the parameters vary from architectures. + Eventually look up LDFLAGS_BLOB in an older version of the + arch/$(ARCH)/Makefile to see the flags used before .incbin was introduced. + + Using .incbin has the advantage over ld that the correct flags are set + in the ELF header, as required by certain architectures. +*/ + +.section .init.ramfs,"a" +.incbin "usr/initramfs_data.cpio.bz2" diff --git a/usr/initramfs_data.gz.S b/usr/initramfs_data.gz.S new file mode 100644 index 00000000000..890c8dd1d6b --- /dev/null +++ b/usr/initramfs_data.gz.S @@ -0,0 +1,29 @@ +/* + initramfs_data includes the compressed binary that is the + filesystem used for early user space. + Note: Older versions of "as" (prior to binutils 2.11.90.0.23 + released on 2001-07-14) dit not support .incbin. + If you are forced to use older binutils than that then the + following trick can be applied to create the resulting binary: + + + ld -m elf_i386 --format binary --oformat elf32-i386 -r \ + -T initramfs_data.scr initramfs_data.cpio.gz -o initramfs_data.o + ld -m elf_i386 -r -o built-in.o initramfs_data.o + + initramfs_data.scr looks like this: +SECTIONS +{ + .init.ramfs : { *(.data) } +} + + The above example is for i386 - the parameters vary from architectures. + Eventually look up LDFLAGS_BLOB in an older version of the + arch/$(ARCH)/Makefile to see the flags used before .incbin was introduced. + + Using .incbin has the advantage over ld that the correct flags are set + in the ELF header, as required by certain architectures. +*/ + +.section .init.ramfs,"a" +.incbin "usr/initramfs_data.cpio.gz" diff --git a/usr/initramfs_data.lzma.S b/usr/initramfs_data.lzma.S new file mode 100644 index 00000000000..e11469e4856 --- /dev/null +++ b/usr/initramfs_data.lzma.S @@ -0,0 +1,29 @@ +/* + initramfs_data includes the compressed binary that is the + filesystem used for early user space. + Note: Older versions of "as" (prior to binutils 2.11.90.0.23 + released on 2001-07-14) dit not support .incbin. + If you are forced to use older binutils than that then the + following trick can be applied to create the resulting binary: + + + ld -m elf_i386 --format binary --oformat elf32-i386 -r \ + -T initramfs_data.scr initramfs_data.cpio.gz -o initramfs_data.o + ld -m elf_i386 -r -o built-in.o initramfs_data.o + + initramfs_data.scr looks like this: +SECTIONS +{ + .init.ramfs : { *(.data) } +} + + The above example is for i386 - the parameters vary from architectures. + Eventually look up LDFLAGS_BLOB in an older version of the + arch/$(ARCH)/Makefile to see the flags used before .incbin was introduced. + + Using .incbin has the advantage over ld that the correct flags are set + in the ELF header, as required by certain architectures. +*/ + +.section .init.ramfs,"a" +.incbin "usr/initramfs_data.cpio.lzma" -- GitLab From c8334dc8fb6413b363df3e1419e287f5b25bce32 Mon Sep 17 00:00:00 2001 From: James Morris Date: Wed, 7 Jan 2009 20:06:18 +1100 Subject: [PATCH 0057/4982] maintainers: add security subsystem wiki Add url to the security subsystem wiki. Signed-off-by: James Morris --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index ceb32ee51f9..6bd7d47ab9d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3783,6 +3783,7 @@ M: jmorris@namei.org L: linux-kernel@vger.kernel.org L: linux-security-module@vger.kernel.org (suggested Cc:) T: git kernel.org:pub/scm/linux/kernel/git/jmorris/security-testing-2.6.git +W: http://security.wiki.kernel.org/ S: Supported SECURITY CONTACT -- GitLab From d506fc322ec2af04fc47be83d796a1c9e1a16022 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 Jan 2009 11:54:25 +0200 Subject: [PATCH 0058/4982] ALSA: Add support for video out to the jack reporting API Add support for reporting new jack types SND_JACK_VIDEOOUT and SND_JACK_AVOUT (a combination of LINEOUT and VIDEOOUT) to the jack reporting API. Also add the corresponding SW_VIDEOOUT_INSERT switch to the input system header. Signed-off-by: Jani Nikula Signed-off-by: Mark Brown --- include/linux/input.h | 1 + include/sound/jack.h | 2 ++ sound/core/jack.c | 1 + 3 files changed, 4 insertions(+) diff --git a/include/linux/input.h b/include/linux/input.h index 9a6355f74db..adc13322d1d 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -661,6 +661,7 @@ struct input_absinfo { #define SW_DOCK 0x05 /* set = plugged into dock */ #define SW_LINEOUT_INSERT 0x06 /* set = inserted */ #define SW_JACK_PHYSICAL_INSERT 0x07 /* set = mechanical switch set */ +#define SW_VIDEOOUT_INSERT 0x08 /* set = inserted */ #define SW_MAX 0x0f #define SW_CNT (SW_MAX+1) diff --git a/include/sound/jack.h b/include/sound/jack.h index 85266a2f5c6..6b013c6f6a0 100644 --- a/include/sound/jack.h +++ b/include/sound/jack.h @@ -40,6 +40,8 @@ enum snd_jack_types { SND_JACK_HEADSET = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE, SND_JACK_LINEOUT = 0x0004, SND_JACK_MECHANICAL = 0x0008, /* If detected separately */ + SND_JACK_VIDEOOUT = 0x0010, + SND_JACK_AVOUT = SND_JACK_LINEOUT | SND_JACK_VIDEOOUT, }; struct snd_jack { diff --git a/sound/core/jack.c b/sound/core/jack.c index b2da10c9916..43b10d6e522 100644 --- a/sound/core/jack.c +++ b/sound/core/jack.c @@ -28,6 +28,7 @@ static int jack_types[] = { SW_MICROPHONE_INSERT, SW_LINEOUT_INSERT, SW_JACK_PHYSICAL_INSERT, + SW_VIDEOOUT_INSERT, }; static int snd_jack_dev_free(struct snd_device *device) -- GitLab From 7760ec77ab2a9e48bdd0d13341446a8a51f0b9f1 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Wed, 7 Jan 2009 18:10:13 +0530 Subject: [PATCH 0059/4982] x86: smp.h remove obsolete function declaration Impact: cleanup Signed-off-by: Jaswinder Singh Rajput Signed-off-by: Ingo Molnar --- arch/x86/include/asm/smp.h | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index 830b9fcb642..83a4cc07431 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -22,7 +22,6 @@ extern cpumask_t cpu_callout_map; extern cpumask_t cpu_initialized; extern cpumask_t cpu_callin_map; -extern void (*mtrr_hook)(void); extern void zap_low_mappings(void); extern int __cpuinit get_local_pda(int cpu); -- GitLab From dacf7333571d770366bff74d10b56aa545434605 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Wed, 7 Jan 2009 17:26:35 +0530 Subject: [PATCH 0060/4982] x86: smp.h move zap_low_mappings declartion to tlbflush.h Impact: cleanup, moving NON-SMP stuff from smp.h Signed-off-by: Jaswinder Singh Rajput Signed-off-by: Ingo Molnar --- arch/x86/include/asm/smp.h | 2 -- arch/x86/include/asm/tlbflush.h | 2 ++ arch/x86/mm/init_32.c | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index 83a4cc07431..64c9e848f13 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -22,8 +22,6 @@ extern cpumask_t cpu_callout_map; extern cpumask_t cpu_initialized; extern cpumask_t cpu_callin_map; -extern void zap_low_mappings(void); - extern int __cpuinit get_local_pda(int cpu); extern int smp_num_siblings; diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index 0e7bbb54911..aed0b700b83 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -175,4 +175,6 @@ static inline void flush_tlb_kernel_range(unsigned long start, flush_tlb_all(); } +extern void zap_low_mappings(void); + #endif /* _ASM_X86_TLBFLUSH_H */ diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index f99a6c6c432..a9dd0b7ad61 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -49,7 +49,6 @@ #include #include #include -#include unsigned int __VMALLOC_RESERVE = 128 << 20; -- GitLab From 6e5385d44b2df05e50a8d07ba0e14d3e32685237 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Wed, 7 Jan 2009 18:11:35 +0530 Subject: [PATCH 0061/4982] x86: smp.h move prefill_possible_map declartion to cpu.h Impact: cleanup, moving NON-SMP stuff from smp.h Signed-off-by: Jaswinder Singh Rajput Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpu.h | 10 ++++++++++ arch/x86/include/asm/smp.h | 6 ------ arch/x86/kernel/setup.c | 2 +- arch/x86/kernel/smpboot.c | 1 - 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index bae482df603..29aa6d0752b 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h @@ -7,6 +7,16 @@ #include #include +#ifdef CONFIG_SMP + +extern void prefill_possible_map(void); + +#else /* CONFIG_SMP */ + +static inline void prefill_possible_map(void) {} + +#endif /* CONFIG_SMP */ + struct x86_cpu { struct cpu cpu; }; diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index 64c9e848f13..62bd3f68269 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -138,8 +138,6 @@ void play_dead_common(void); void native_send_call_func_ipi(const struct cpumask *mask); void native_send_call_func_single_ipi(int cpu); -extern void prefill_possible_map(void); - void smp_store_cpu_info(int id); #define cpu_physical_id(cpu) per_cpu(x86_cpu_to_apicid, cpu) @@ -148,10 +146,6 @@ static inline int num_booting_cpus(void) { return cpus_weight(cpu_callout_map); } -#else -static inline void prefill_possible_map(void) -{ -} #endif /* CONFIG_SMP */ extern unsigned disabled_cpus __cpuinitdata; diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index ae0d8042cf6..f41c4486c27 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -89,7 +89,7 @@ #include #include -#include +#include #include #include #include diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 07576bee03e..f8c885bed18 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -53,7 +53,6 @@ #include #include #include -#include #include #include #include -- GitLab From f472cdba849cc3d838f3788469316e8572463a8c Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Wed, 7 Jan 2009 21:34:25 +0530 Subject: [PATCH 0062/4982] x86: smp.h move stack_processor_id declartion to cpu.h Impact: cleanup Signed-off-by: Jaswinder Singh Rajput Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpu.h | 2 ++ arch/x86/include/asm/smp.h | 1 - arch/x86/kernel/cpu/common.c | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index 29aa6d0752b..f958e7e49c0 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h @@ -15,6 +15,8 @@ extern void prefill_possible_map(void); static inline void prefill_possible_map(void) {} +#define stack_smp_processor_id() 0 + #endif /* CONFIG_SMP */ struct x86_cpu { diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index 62bd3f68269..ed4af9a89cf 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -173,7 +173,6 @@ extern int safe_smp_processor_id(void); #else /* !CONFIG_X86_32_SMP && !CONFIG_X86_64_SMP */ #define cpu_physical_id(cpu) boot_cpu_physical_apicid #define safe_smp_processor_id() 0 -#define stack_smp_processor_id() 0 #endif #ifdef CONFIG_X86_LOCAL_APIC diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 3f95a40f718..f7619a2eaff 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -21,6 +21,7 @@ #include #include #include +#include #ifdef CONFIG_X86_LOCAL_APIC #include #include -- GitLab From 96b89dc6598a50e3aac8e2c6d826ae3795b7d030 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Wed, 7 Jan 2009 21:35:48 +0530 Subject: [PATCH 0063/4982] x86: smp.h move safe_smp_processor_id declartion to cpu.h Impact: cleanup Signed-off-by: Jaswinder Singh Rajput Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpu.h | 1 + arch/x86/include/asm/smp.h | 1 - arch/x86/kernel/crash.c | 2 +- arch/x86/kernel/reboot.c | 1 + arch/x86/mach-voyager/setup.c | 1 + 5 files changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index f958e7e49c0..4c16888ffa3 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h @@ -15,6 +15,7 @@ extern void prefill_possible_map(void); static inline void prefill_possible_map(void) {} +#define safe_smp_processor_id() 0 #define stack_smp_processor_id() 0 #endif /* CONFIG_SMP */ diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index ed4af9a89cf..c92b93594ab 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -172,7 +172,6 @@ extern int safe_smp_processor_id(void); #else /* !CONFIG_X86_32_SMP && !CONFIG_X86_64_SMP */ #define cpu_physical_id(cpu) boot_cpu_physical_apicid -#define safe_smp_processor_id() 0 #endif #ifdef CONFIG_X86_LOCAL_APIC diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c index c689d19e35a..11b93cabdf7 100644 --- a/arch/x86/kernel/crash.c +++ b/arch/x86/kernel/crash.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 2b46eb41643..f8536fee5c1 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -14,6 +14,7 @@ #include #include #include +#include #ifdef CONFIG_X86_32 # include diff --git a/arch/x86/mach-voyager/setup.c b/arch/x86/mach-voyager/setup.c index a580b9562e7..0ade62555ff 100644 --- a/arch/x86/mach-voyager/setup.c +++ b/arch/x86/mach-voyager/setup.c @@ -9,6 +9,7 @@ #include #include #include +#include void __init pre_intr_init_hook(void) { -- GitLab From af8968abf09fe5984bdd206e54e0eeb1dc1fa29c Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Wed, 7 Jan 2009 21:37:33 +0530 Subject: [PATCH 0064/4982] x86: smp.h move cpu_physical_id declartion to cpu.h Impact: cleanup Signed-off-by: Jaswinder Singh Rajput Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpu.h | 1 + arch/x86/include/asm/smp.h | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index 4c16888ffa3..89edafb9339 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h @@ -15,6 +15,7 @@ extern void prefill_possible_map(void); static inline void prefill_possible_map(void) {} +#define cpu_physical_id(cpu) boot_cpu_physical_apicid #define safe_smp_processor_id() 0 #define stack_smp_processor_id() 0 diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index c92b93594ab..c975b6f83c6 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -170,8 +170,6 @@ extern int safe_smp_processor_id(void); }) #define safe_smp_processor_id() smp_processor_id() -#else /* !CONFIG_X86_32_SMP && !CONFIG_X86_64_SMP */ -#define cpu_physical_id(cpu) boot_cpu_physical_apicid #endif #ifdef CONFIG_X86_LOCAL_APIC -- GitLab From 6d652ea1d056390a0c33db92b44ed219284b71af Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Wed, 7 Jan 2009 21:38:59 +0530 Subject: [PATCH 0065/4982] x86: smp.h move boot_cpu_id declartion to cpu.h Impact: cleanup Signed-off-by: Jaswinder Singh Rajput Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpu.h | 7 +++++++ arch/x86/include/asm/smp.h | 6 ------ arch/x86/kernel/io_apic.c | 1 + drivers/pci/intr_remapping.c | 1 + 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index 89edafb9339..f03b23e3286 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h @@ -31,4 +31,11 @@ extern void arch_unregister_cpu(int); #endif DECLARE_PER_CPU(int, cpu_state); + +#ifdef CONFIG_X86_HAS_BOOT_CPU_ID +extern unsigned char boot_cpu_id; +#else +#define boot_cpu_id 0 +#endif + #endif /* _ASM_X86_CPU_H */ diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index c975b6f83c6..74ad9ef6ae0 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -212,11 +212,5 @@ static inline int hard_smp_processor_id(void) #endif /* CONFIG_X86_LOCAL_APIC */ -#ifdef CONFIG_X86_HAS_BOOT_CPU_ID -extern unsigned char boot_cpu_id; -#else -#define boot_cpu_id 0 -#endif - #endif /* __ASSEMBLY__ */ #endif /* _ASM_X86_SMP_H */ diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 1c4a1302536..109c91db202 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index f78371b2252..5a57753ea9f 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "intr_remapping.h" -- GitLab From ca9c1aaec4187fc9922cfb6b283fffef89286943 Mon Sep 17 00:00:00 2001 From: Ian Molton Date: Tue, 6 Jan 2009 20:11:51 +0000 Subject: [PATCH 0066/4982] ASoC: dapm: Allow explictly named mixer controls This patch allows you to define the mixer paths as having the same name as the paths they represent. This is required to support codecs such as the wm9705 neatly without extra controls in the alsa mixer. Signed-off-by: Ian Molton --- Documentation/sound/alsa/soc/dapm.txt | 3 ++ include/sound/soc-dapm.h | 11 +++++++ sound/soc/soc-dapm.c | 47 ++++++++++++++++++++------- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/Documentation/sound/alsa/soc/dapm.txt b/Documentation/sound/alsa/soc/dapm.txt index 46f9684d0b2..9e6763264a2 100644 --- a/Documentation/sound/alsa/soc/dapm.txt +++ b/Documentation/sound/alsa/soc/dapm.txt @@ -116,6 +116,9 @@ SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0), SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls, ARRAY_SIZE(wm8731_output_mixer_controls)), +If you dont want the mixer elements prefixed with the name of the mixer widget, +you can use SND_SOC_DAPM_MIXER_NAMED_CTL instead. the parameters are the same +as for SND_SOC_DAPM_MIXER. 2.3 Platform/Machine domain Widgets ----------------------------------- diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 4af1083e328..cc99dd40493 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -76,6 +76,11 @@ wcontrols, wncontrols)\ { .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ .invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols} +#define SND_SOC_DAPM_MIXER_NAMED_CTL(wname, wreg, wshift, winvert, \ + wcontrols, wncontrols)\ +{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, .reg = wreg, \ + .shift = wshift, .invert = winvert, .kcontrols = wcontrols, \ + .num_kcontrols = wncontrols} #define SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) \ { .id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \ .invert = winvert, .kcontrols = NULL, .num_kcontrols = 0} @@ -101,6 +106,11 @@ { .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ .invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols, \ .event = wevent, .event_flags = wflags} +#define SND_SOC_DAPM_MIXER_NAMED_CTL_E(wname, wreg, wshift, winvert, \ + wcontrols, wncontrols, wevent, wflags) \ +{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ + .invert = winvert, .kcontrols = wcontrols, \ + .num_kcontrols = wncontrols, .event = wevent, .event_flags = wflags} #define SND_SOC_DAPM_MICBIAS_E(wname, wreg, wshift, winvert, wevent, wflags) \ { .id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \ .invert = winvert, .kcontrols = NULL, .num_kcontrols = 0, \ @@ -263,6 +273,7 @@ enum snd_soc_dapm_type { snd_soc_dapm_mux, /* selects 1 analog signal from many inputs */ snd_soc_dapm_value_mux, /* selects 1 analog signal from many inputs */ snd_soc_dapm_mixer, /* mixes several analog signals together */ + snd_soc_dapm_mixer_named_ctl, /* mixer with named controls */ snd_soc_dapm_pga, /* programmable gain/attenuation (volume) */ snd_soc_dapm_adc, /* analog to digital converter */ snd_soc_dapm_dac, /* digital to analog converter */ diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index ad0d801677c..6362c7641ce 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -54,14 +54,15 @@ static int dapm_up_seq[] = { snd_soc_dapm_pre, snd_soc_dapm_micbias, snd_soc_dapm_mic, snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_dac, - snd_soc_dapm_mixer, snd_soc_dapm_pga, snd_soc_dapm_adc, snd_soc_dapm_hp, - snd_soc_dapm_spk, snd_soc_dapm_post + snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_pga, + snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, snd_soc_dapm_post }; + static int dapm_down_seq[] = { snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, - snd_soc_dapm_pga, snd_soc_dapm_mixer, snd_soc_dapm_dac, snd_soc_dapm_mic, - snd_soc_dapm_micbias, snd_soc_dapm_mux, snd_soc_dapm_value_mux, - snd_soc_dapm_post + snd_soc_dapm_pga, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_mixer, + snd_soc_dapm_dac, snd_soc_dapm_mic, snd_soc_dapm_micbias, + snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_post }; static int dapm_status = 1; @@ -101,7 +102,8 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, { switch (w->id) { case snd_soc_dapm_switch: - case snd_soc_dapm_mixer: { + case snd_soc_dapm_mixer: + case snd_soc_dapm_mixer_named_ctl: { int val; struct soc_mixer_control *mc = (struct soc_mixer_control *) w->kcontrols[i].private_value; @@ -347,15 +349,33 @@ static int dapm_new_mixer(struct snd_soc_codec *codec, if (path->name != (char*)w->kcontrols[i].name) continue; - /* add dapm control with long name */ - name_len = 2 + strlen(w->name) - + strlen(w->kcontrols[i].name); + /* add dapm control with long name. + * for dapm_mixer this is the concatenation of the + * mixer and kcontrol name. + * for dapm_mixer_named_ctl this is simply the + * kcontrol name. + */ + name_len = strlen(w->kcontrols[i].name) + 1; + if (w->id == snd_soc_dapm_mixer) + name_len += 1 + strlen(w->name); + path->long_name = kmalloc(name_len, GFP_KERNEL); + if (path->long_name == NULL) return -ENOMEM; - snprintf(path->long_name, name_len, "%s %s", - w->name, w->kcontrols[i].name); + switch (w->id) { + case snd_soc_dapm_mixer: + default: + snprintf(path->long_name, name_len, "%s %s", + w->name, w->kcontrols[i].name); + break; + case snd_soc_dapm_mixer_named_ctl: + snprintf(path->long_name, name_len, "%s", + w->kcontrols[i].name); + break; + } + path->long_name[name_len - 1] = '\0'; path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, @@ -711,6 +731,7 @@ static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action) case snd_soc_dapm_adc: case snd_soc_dapm_pga: case snd_soc_dapm_mixer: + case snd_soc_dapm_mixer_named_ctl: if (w->name) { in = is_connected_input_ep(w); dapm_clear_walk(w->codec); @@ -822,6 +843,7 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, int found = 0; if (widget->id != snd_soc_dapm_mixer && + widget->id != snd_soc_dapm_mixer_named_ctl && widget->id != snd_soc_dapm_switch) return -ENODEV; @@ -875,6 +897,7 @@ static ssize_t dapm_widget_show(struct device *dev, case snd_soc_dapm_adc: case snd_soc_dapm_pga: case snd_soc_dapm_mixer: + case snd_soc_dapm_mixer_named_ctl: if (w->name) count += sprintf(buf + count, "%s: %s\n", w->name, w->power ? "On":"Off"); @@ -1058,6 +1081,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec, break; case snd_soc_dapm_switch: case snd_soc_dapm_mixer: + case snd_soc_dapm_mixer_named_ctl: ret = dapm_connect_mixer(codec, wsource, wsink, path, control); if (ret != 0) goto err; @@ -1135,6 +1159,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec) switch(w->id) { case snd_soc_dapm_switch: case snd_soc_dapm_mixer: + case snd_soc_dapm_mixer_named_ctl: dapm_new_mixer(codec, w); break; case snd_soc_dapm_mux: -- GitLab From 01d07820a0df6b6134c1bb75b1e84c9d0cdab3be Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Sun, 4 Jan 2009 03:11:05 +0900 Subject: [PATCH 0067/4982] sparseirq: make for_each_irq_desc() more robust Raja reported for_each_irq_desc() has possibility unsafeness: if anyone write folliwing code, for_each_irq_desc() doesn't work as intended: (right now this code does not exist at all) if (safe) for_each_irq_desc(irq, desc) { ... } else panic(); Reported-by: Raja R Harinath Signed-off-by: KOSAKI Motohiro Signed-off-by: Ingo Molnar --- include/linux/irqnr.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/linux/irqnr.h b/include/linux/irqnr.h index 86af92e9e84..52ebbb4b161 100644 --- a/include/linux/irqnr.h +++ b/include/linux/irqnr.h @@ -28,13 +28,17 @@ extern struct irq_desc *irq_to_desc(unsigned int irq); # define for_each_irq_desc(irq, desc) \ for (irq = 0, desc = irq_to_desc(irq); irq < nr_irqs; \ irq++, desc = irq_to_desc(irq)) \ - if (desc) + if (!desc) \ + ; \ + else # define for_each_irq_desc_reverse(irq, desc) \ for (irq = nr_irqs - 1, desc = irq_to_desc(irq); irq >= 0; \ irq--, desc = irq_to_desc(irq)) \ - if (desc) + if (!desc) \ + ; \ + else #endif /* CONFIG_GENERIC_HARDIRQS */ -- GitLab From 3195954da9cdb1cadb2059921c62e69d376c624f Mon Sep 17 00:00:00 2001 From: Andrea Borgia Date: Wed, 7 Jan 2009 22:58:50 +0100 Subject: [PATCH 0068/4982] ALSA: preliminary support for Toshiba SB-0500 The Toshiba Multimedia Center SB-0500 is a rebranded version of the Creative Technology SB Live! 24-bit External: it shares the same chipset and only has minor cosmetic differences. Remote controller works with alsa_usb module, basic audio is there and mixer controls are mostly untested. Signed-off-by: Andrea Borgia Signed-off-by: Takashi Iwai --- sound/usb/usbmixer.c | 15 ++++++++++----- sound/usb/usbmixer_maps.c | 5 +++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index 00397c8a765..bc8bd00047a 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c @@ -66,6 +66,7 @@ static const struct rc_config { { USB_ID(0x041e, 0x3000), 0, 1, 2, 1, 18, 0x0013 }, /* Extigy */ { USB_ID(0x041e, 0x3020), 2, 1, 6, 6, 18, 0x0013 }, /* Audigy 2 NX */ { USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */ + { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */ }; struct usb_mixer_interface { @@ -1706,7 +1707,8 @@ static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer, break; /* live24ext: 4 = line-in jack */ case 3: /* hp-out jack (may actuate Mute) */ - if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) + if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || + mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) snd_usb_mixer_notify_id(mixer, mixer->rc_cfg->mute_mixer_id); break; default: @@ -1956,8 +1958,9 @@ static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer) int i, err; for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) { - if (i > 1 && /* Live24ext has 2 LEDs only */ - mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) + if (i > 1 && /* Live24ext has 2 LEDs only */ + (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || + mixer->chip->usb_id == USB_ID(0x041e, 0x3048))) break; err = snd_ctl_add(mixer->chip->card, snd_ctl_new1(&snd_audigy2nx_controls[i], mixer)); @@ -1994,7 +1997,8 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry, snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname); if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020)) jacks = jacks_audigy2nx; - else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) + else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || + mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) jacks = jacks_live24ext; else return; @@ -2044,7 +2048,8 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, goto _error; if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) || - mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) { + mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || + mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) { struct snd_info_entry *entry; if ((err = snd_audigy2nx_controls_create(mixer)) < 0) diff --git a/sound/usb/usbmixer_maps.c b/sound/usb/usbmixer_maps.c index d755be0ad81..f41214f3ad6 100644 --- a/sound/usb/usbmixer_maps.c +++ b/sound/usb/usbmixer_maps.c @@ -284,6 +284,11 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { .id = USB_ID(0x041e, 0x3040), .map = live24ext_map, }, + { + .id = USB_ID(0x041e, 0x3048), + .map = audigy2nx_map, + .selector_map = audigy2nx_selectors, + }, { /* Hercules DJ Console (Windows Edition) */ .id = USB_ID(0x06f8, 0xb000), -- GitLab From 41401db698cbb5d1869776bf336881db267e7d19 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Thu, 8 Jan 2009 15:42:46 +0530 Subject: [PATCH 0069/4982] x86: rename intel_mp_floating to mpf_intel Impact: cleanup, solve 80 columns wrap problems intel_mp_floating should be renamed to mpf_intel. The reason: the 'f' in MPF already means 'floating' which means MP Floating pointer structure - no need to repeat that in the type name. Signed-off-by: Jaswinder Singh Rajput Signed-off-by: Ingo Molnar --- arch/x86/include/asm/mpspec_def.h | 3 ++- arch/x86/kernel/mpparse.c | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/arch/x86/include/asm/mpspec_def.h b/arch/x86/include/asm/mpspec_def.h index 59568bc4767..187dc920193 100644 --- a/arch/x86/include/asm/mpspec_def.h +++ b/arch/x86/include/asm/mpspec_def.h @@ -24,7 +24,8 @@ # endif #endif -struct intel_mp_floating { +/* Intel MP Floating Pointer Structure */ +struct mpf_intel { char mpf_signature[4]; /* "_MP_" */ unsigned int mpf_physptr; /* Configuration table address */ unsigned char mpf_length; /* Our length (paragraphs) */ diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index c0601c2848a..6cea941c4db 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -569,14 +569,14 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type) } } -static struct intel_mp_floating *mpf_found; +static struct mpf_intel *mpf_found; /* * Scan the memory blocks for an SMP configuration block. */ static void __init __get_smp_config(unsigned int early) { - struct intel_mp_floating *mpf = mpf_found; + struct mpf_intel *mpf = mpf_found; if (!mpf) return; @@ -687,14 +687,14 @@ static int __init smp_scan_config(unsigned long base, unsigned long length, unsigned reserve) { unsigned int *bp = phys_to_virt(base); - struct intel_mp_floating *mpf; + struct mpf_intel *mpf; apic_printk(APIC_VERBOSE, "Scan SMP from %p for %ld bytes.\n", bp, length); BUILD_BUG_ON(sizeof(*mpf) != 16); while (length > 0) { - mpf = (struct intel_mp_floating *)bp; + mpf = (struct mpf_intel *)bp; if ((*bp == SMP_MAGIC_IDENT) && (mpf->mpf_length == 1) && !mpf_checksum((unsigned char *)bp, 16) && @@ -1000,7 +1000,7 @@ static int __init update_mp_table(void) { char str[16]; char oem[10]; - struct intel_mp_floating *mpf; + struct mpf_intel *mpf; struct mpc_table *mpc, *mpc_new; if (!enable_update_mptable) @@ -1052,7 +1052,7 @@ static int __init update_mp_table(void) mpc = mpc_new; /* check if we can modify that */ if (mpc_new_phys - mpf->mpf_physptr) { - struct intel_mp_floating *mpf_new; + struct mpf_intel *mpf_new; /* steal 16 bytes from [0, 1k) */ printk(KERN_INFO "mpf new: %x\n", 0x400 - 16); mpf_new = phys_to_virt(0x400 - 16); -- GitLab From 1eb1b3b65dc3e3ffcc6a60e115c085c0c11c1077 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Thu, 8 Jan 2009 15:43:26 +0530 Subject: [PATCH 0070/4982] x86: rename all fields of mpf_intel mpf_X to X Impact: cleanup, solve 80 columns wrap problems It would be cleaner to rename all the mpf->mpf_X fields to mpf->X - that alone would give 4 characters per usage site. (we already know that it's an 'mpf' entity - no need to duplicate that in the field too) Signed-off-by: Jaswinder Singh Rajput Signed-off-by: Ingo Molnar --- arch/x86/include/asm/mpspec_def.h | 20 ++++++------- arch/x86/kernel/mpparse.c | 50 +++++++++++++++---------------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/arch/x86/include/asm/mpspec_def.h b/arch/x86/include/asm/mpspec_def.h index 187dc920193..4a7f96d7c18 100644 --- a/arch/x86/include/asm/mpspec_def.h +++ b/arch/x86/include/asm/mpspec_def.h @@ -26,16 +26,16 @@ /* Intel MP Floating Pointer Structure */ struct mpf_intel { - char mpf_signature[4]; /* "_MP_" */ - unsigned int mpf_physptr; /* Configuration table address */ - unsigned char mpf_length; /* Our length (paragraphs) */ - unsigned char mpf_specification;/* Specification version */ - unsigned char mpf_checksum; /* Checksum (makes sum 0) */ - unsigned char mpf_feature1; /* Standard or configuration ? */ - unsigned char mpf_feature2; /* Bit7 set for IMCR|PIC */ - unsigned char mpf_feature3; /* Unused (0) */ - unsigned char mpf_feature4; /* Unused (0) */ - unsigned char mpf_feature5; /* Unused (0) */ + char signature[4]; /* "_MP_" */ + unsigned int physptr; /* Configuration table address */ + unsigned char length; /* Our length (paragraphs) */ + unsigned char specification; /* Specification version */ + unsigned char checksum; /* Checksum (makes sum 0) */ + unsigned char feature1; /* Standard or configuration ? */ + unsigned char feature2; /* Bit7 set for IMCR|PIC */ + unsigned char feature3; /* Unused (0) */ + unsigned char feature4; /* Unused (0) */ + unsigned char feature5; /* Unused (0) */ }; #define MPC_SIGNATURE "PCMP" diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 6cea941c4db..8385d4e7e15 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -597,9 +597,9 @@ static void __init __get_smp_config(unsigned int early) } printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n", - mpf->mpf_specification); + mpf->specification); #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32) - if (mpf->mpf_feature2 & (1 << 7)) { + if (mpf->feature2 & (1 << 7)) { printk(KERN_INFO " IMCR and PIC compatibility mode.\n"); pic_mode = 1; } else { @@ -610,7 +610,7 @@ static void __init __get_smp_config(unsigned int early) /* * Now see if we need to read further. */ - if (mpf->mpf_feature1 != 0) { + if (mpf->feature1 != 0) { if (early) { /* * local APIC has default address @@ -620,16 +620,16 @@ static void __init __get_smp_config(unsigned int early) } printk(KERN_INFO "Default MP configuration #%d\n", - mpf->mpf_feature1); - construct_default_ISA_mptable(mpf->mpf_feature1); + mpf->feature1); + construct_default_ISA_mptable(mpf->feature1); - } else if (mpf->mpf_physptr) { + } else if (mpf->physptr) { /* * Read the physical hardware table. Anything here will * override the defaults. */ - if (!smp_read_mpc(phys_to_virt(mpf->mpf_physptr), early)) { + if (!smp_read_mpc(phys_to_virt(mpf->physptr), early)) { #ifdef CONFIG_X86_LOCAL_APIC smp_found_config = 0; #endif @@ -696,10 +696,10 @@ static int __init smp_scan_config(unsigned long base, unsigned long length, while (length > 0) { mpf = (struct mpf_intel *)bp; if ((*bp == SMP_MAGIC_IDENT) && - (mpf->mpf_length == 1) && + (mpf->length == 1) && !mpf_checksum((unsigned char *)bp, 16) && - ((mpf->mpf_specification == 1) - || (mpf->mpf_specification == 4))) { + ((mpf->specification == 1) + || (mpf->specification == 4))) { #ifdef CONFIG_X86_LOCAL_APIC smp_found_config = 1; #endif @@ -712,7 +712,7 @@ static int __init smp_scan_config(unsigned long base, unsigned long length, return 1; reserve_bootmem_generic(virt_to_phys(mpf), PAGE_SIZE, BOOTMEM_DEFAULT); - if (mpf->mpf_physptr) { + if (mpf->physptr) { unsigned long size = PAGE_SIZE; #ifdef CONFIG_X86_32 /* @@ -721,14 +721,14 @@ static int __init smp_scan_config(unsigned long base, unsigned long length, * the bottom is mapped now. * PC-9800's MPC table places on the very last * of physical memory; so that simply reserving - * PAGE_SIZE from mpg->mpf_physptr yields BUG() + * PAGE_SIZE from mpf->physptr yields BUG() * in reserve_bootmem. */ unsigned long end = max_low_pfn * PAGE_SIZE; - if (mpf->mpf_physptr + size > end) - size = end - mpf->mpf_physptr; + if (mpf->physptr + size > end) + size = end - mpf->physptr; #endif - reserve_bootmem_generic(mpf->mpf_physptr, size, + reserve_bootmem_generic(mpf->physptr, size, BOOTMEM_DEFAULT); } @@ -1013,19 +1013,19 @@ static int __init update_mp_table(void) /* * Now see if we need to go further. */ - if (mpf->mpf_feature1 != 0) + if (mpf->feature1 != 0) return 0; - if (!mpf->mpf_physptr) + if (!mpf->physptr) return 0; - mpc = phys_to_virt(mpf->mpf_physptr); + mpc = phys_to_virt(mpf->physptr); if (!smp_check_mpc(mpc, oem, str)) return 0; printk(KERN_INFO "mpf: %lx\n", virt_to_phys(mpf)); - printk(KERN_INFO "mpf_physptr: %x\n", mpf->mpf_physptr); + printk(KERN_INFO "physptr: %x\n", mpf->physptr); if (mpc_new_phys && mpc->length > mpc_new_length) { mpc_new_phys = 0; @@ -1046,23 +1046,23 @@ static int __init update_mp_table(void) } printk(KERN_INFO "use in-positon replacing\n"); } else { - mpf->mpf_physptr = mpc_new_phys; + mpf->physptr = mpc_new_phys; mpc_new = phys_to_virt(mpc_new_phys); memcpy(mpc_new, mpc, mpc->length); mpc = mpc_new; /* check if we can modify that */ - if (mpc_new_phys - mpf->mpf_physptr) { + if (mpc_new_phys - mpf->physptr) { struct mpf_intel *mpf_new; /* steal 16 bytes from [0, 1k) */ printk(KERN_INFO "mpf new: %x\n", 0x400 - 16); mpf_new = phys_to_virt(0x400 - 16); memcpy(mpf_new, mpf, 16); mpf = mpf_new; - mpf->mpf_physptr = mpc_new_phys; + mpf->physptr = mpc_new_phys; } - mpf->mpf_checksum = 0; - mpf->mpf_checksum -= mpf_checksum((unsigned char *)mpf, 16); - printk(KERN_INFO "mpf_physptr new: %x\n", mpf->mpf_physptr); + mpf->checksum = 0; + mpf->checksum -= mpf_checksum((unsigned char *)mpf, 16); + printk(KERN_INFO "physptr new: %x\n", mpf->physptr); } /* -- GitLab From 5619448fc55650cb76cbb825e16e4bb5d1390399 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 8 Jan 2009 15:09:12 -0800 Subject: [PATCH 0071/4982] bzip2/lzma: fix constant in decompress_inflate Impact: Cleanup Fix constant 0x8100 /* 32K */; according to Alain the value 0x8100 was left over test code to test misalignment, the correct value is indeed 0x8000 == 32K. Signed-off-by: H. Peter Anvin --- lib/decompress_inflate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/decompress_inflate.c b/lib/decompress_inflate.c index 163e66aea5f..d2e7c758d1c 100644 --- a/lib/decompress_inflate.c +++ b/lib/decompress_inflate.c @@ -41,7 +41,7 @@ STATIC int INIT gunzip(unsigned char *buf, int len, set_error_fn(error_fn); rc = -1; if (flush) { - out_len = 0x8100; /* 32 K */ + out_len = 0x8000; /* 32 K */ out_buf = malloc(out_len); } else { out_len = 0x7fffffff; /* no limit */ -- GitLab From 6c11b12ac6f101732d43b5682f5b3ae4dda4205f Mon Sep 17 00:00:00 2001 From: Alain Knaff Date: Thu, 8 Jan 2009 15:10:19 -0800 Subject: [PATCH 0072/4982] bzip2/lzma: fix decompress_inflate.c vs multi-block-with-embedded-filename Impact: Bug fix Fix gunzip uncompression, so that it also works with files with embedded filenames that are larger than one block. Signed-off-by: Alain Knaff Signed-off-by: H. Peter Anvin --- lib/decompress_inflate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/decompress_inflate.c b/lib/decompress_inflate.c index d2e7c758d1c..839a329b4fc 100644 --- a/lib/decompress_inflate.c +++ b/lib/decompress_inflate.c @@ -97,7 +97,7 @@ STATIC int INIT gunzip(unsigned char *buf, int len, strm->next_in++; strm->next_in++; } - strm->avail_in = len - 10; + strm->avail_in = len - (strm->next_in - zbuf); strm->next_out = out_buf; strm->avail_out = out_len; -- GitLab From 889c92d21db40be0b7d22a59395060237895bb85 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 8 Jan 2009 15:14:17 -0800 Subject: [PATCH 0073/4982] bzip2/lzma: centralize format detection Centralize the compression format detection to a common routine in the lib directory, and use it for both initramfs and initrd. Signed-off-by: H. Peter Anvin --- include/linux/decompress/generic.h | 3 ++ init/do_mounts_rd.c | 38 +++++------------------ init/initramfs.c | 39 +++++------------------ lib/Makefile | 9 +++--- lib/decompress.c | 50 ++++++++++++++++++++++++++++++ 5 files changed, 72 insertions(+), 67 deletions(-) create mode 100644 lib/decompress.c diff --git a/include/linux/decompress/generic.h b/include/linux/decompress/generic.h index f847f514f78..6dfb856327b 100644 --- a/include/linux/decompress/generic.h +++ b/include/linux/decompress/generic.h @@ -26,5 +26,8 @@ typedef int (*decompress_fn) (unsigned char *inbuf, int len, *fill should be called (repeatedly...) to read data, at most IOBUF_SIZE */ +/* Utility routine to detect the decompression method */ +decompress_fn decompress_method(const unsigned char *inbuf, int len, + const char **name); #endif diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c index 9c9d7dbcf9c..a06ed4f92e0 100644 --- a/init/do_mounts_rd.c +++ b/init/do_mounts_rd.c @@ -12,9 +12,6 @@ #include -#include -#include -#include int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */ @@ -49,24 +46,6 @@ static int __init crd_load(int in_fd, int out_fd, decompress_fn deco); * cramfs * gzip */ -static const struct compress_format { - unsigned char magic[2]; - const char *name; - decompress_fn decompressor; -} compressed_formats[] = { -#ifdef CONFIG_RD_GZIP - { {037, 0213}, "gzip", gunzip }, - { {037, 0236}, "gzip", gunzip }, -#endif -#ifdef CONFIG_RD_BZIP2 - { {0x42, 0x5a}, "bzip2", bunzip2 }, -#endif -#ifdef CONFIG_RD_LZMA - { {0x5d, 0x00}, "lzma", unlzma }, -#endif - { {0, 0}, NULL, NULL } -}; - static int __init identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) { @@ -77,7 +56,7 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) struct cramfs_super *cramfsb; int nblocks = -1; unsigned char *buf; - const struct compress_format *cf; + const char *compress_name; buf = kmalloc(size, GFP_KERNEL); if (!buf) @@ -95,15 +74,12 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) sys_lseek(fd, start_block * BLOCK_SIZE, 0); sys_read(fd, buf, size); - for (cf = compressed_formats; cf->decompressor; cf++) { - if (buf[0] == cf->magic[0] && buf[1] == cf->magic[1]) { - printk(KERN_NOTICE - "RAMDISK: %s image found at block %d\n", - cf->name, start_block); - *decompressor = cf->decompressor; - nblocks = 0; - goto done; - } + *decompressor = decompress_method(buf, size, &compress_name); + if (*decompressor) { + printk(KERN_NOTICE "RAMDISK: %s image found at block %d\n", + compress_name, start_block); + nblocks = 0; + goto done; } /* romfs is at block zero too */ diff --git a/init/initramfs.c b/init/initramfs.c index a3ba91cdab8..2f42984e558 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -416,13 +416,13 @@ static int __init flush_buffer(void *bufv, unsigned len) static unsigned my_inptr; /* index of next byte to be processed in inbuf */ -#include -#include -#include +#include static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) { int written; + decompress_fn decompress; + dry_run = check_only; header_buf = kmalloc(110, GFP_KERNEL); symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL); @@ -450,35 +450,10 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) continue; } this_header = 0; -#ifdef CONFIG_RD_GZIP - if (!gunzip(buf, len, NULL, flush_buffer, NULL, - &my_inptr, error) && - message == NULL) - goto ok; -#endif - -#ifdef CONFIG_RD_BZIP2 - message = NULL; /* Zero out message, or else cpio will - think an error has already occured */ - if (!bunzip2(buf, len, NULL, flush_buffer, NULL, - &my_inptr, error) && - message == NULL) { - goto ok; - } -#endif - -#ifdef CONFIG_RD_LZMA - message = NULL; /* Zero out message, or else cpio will - think an error has already occured */ - if (!unlzma(buf, len, NULL, flush_buffer, NULL, - &my_inptr, error) && - message == NULL) { - goto ok; - } -#endif -#if defined CONFIG_RD_GZIP || defined CONFIG_RD_BZIP2 || defined CONFIG_RD_LZMA -ok: -#endif + decompress = decompress_method(buf, len, NULL); + if (decompress) + decompress(buf, len, NULL, flush_buffer, NULL, + &my_inptr, error); if (state != Reset) error("junk in compressed archive"); this_header = saved_offset + my_inptr; diff --git a/lib/Makefile b/lib/Makefile index d9ac5a414fa..790de7c25d0 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -11,7 +11,8 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \ rbtree.o radix-tree.o dump_stack.o \ idr.o int_sqrt.o extable.o prio_tree.o \ sha1.o irq_regs.o reciprocal_div.o argv_split.o \ - proportions.o prio_heap.o ratelimit.o show_mem.o is_single_threaded.o + proportions.o prio_heap.o ratelimit.o show_mem.o \ + is_single_threaded.o decompress.o lib-$(CONFIG_MMU) += ioremap.o lib-$(CONFIG_SMP) += cpumask.o @@ -65,9 +66,9 @@ obj-$(CONFIG_REED_SOLOMON) += reed_solomon/ obj-$(CONFIG_LZO_COMPRESS) += lzo/ obj-$(CONFIG_LZO_DECOMPRESS) += lzo/ -obj-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o -obj-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o -obj-$(CONFIG_DECOMPRESS_LZMA) += decompress_unlzma.o +lib-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o +lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o +lib-$(CONFIG_DECOMPRESS_LZMA) += decompress_unlzma.o obj-$(CONFIG_TEXTSEARCH) += textsearch.o obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o diff --git a/lib/decompress.c b/lib/decompress.c new file mode 100644 index 00000000000..edac55cc782 --- /dev/null +++ b/lib/decompress.c @@ -0,0 +1,50 @@ +/* + * decompress.c + * + * Detect the decompression method based on magic number + */ + +#include + +#include +#include +#include + +#include +#include + +static const struct compress_format { + unsigned char magic[2]; + const char *name; + decompress_fn decompressor; +} compressed_formats[] = { +#ifdef CONFIG_DECOMPRESS_GZIP + { {037, 0213}, "gzip", gunzip }, + { {037, 0236}, "gzip", gunzip }, +#endif +#ifdef CONFIG_DECOMPRESS_BZIP2 + { {0x42, 0x5a}, "bzip2", bunzip2 }, +#endif +#ifdef CONFIG_DECOMPRESS_LZMA + { {0x5d, 0x00}, "lzma", unlzma }, +#endif + { {0, 0}, NULL, NULL } +}; + +decompress_fn decompress_method(const unsigned char *inbuf, int len, + const char **name) +{ + const struct compress_format *cf; + + if (len < 2) + return NULL; /* Need at least this much... */ + + for (cf = compressed_formats; cf->decompressor; cf++) { + if (!memcmp(inbuf, cf->magic, 2)) + break; + + } + if (name) + *name = cf->name; + return cf->decompressor; +} -- GitLab From 1649923dd52ce914be98bff0ae352344ef04f305 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 7 Jan 2009 18:25:13 +0000 Subject: [PATCH 0074/4982] ASoC: Constify pin names for DAPM pin status APIs Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 8 ++++---- sound/soc/soc-dapm.c | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index cc99dd40493..075244ef41e 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -260,10 +260,10 @@ int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev, int snd_soc_dapm_sys_add(struct device *dev); /* dapm audio pin control and status */ -int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin); -int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin); -int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin); -int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin); +int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin); +int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, const char *pin); +int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, const char *pin); +int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, const char *pin); int snd_soc_dapm_sync(struct snd_soc_codec *codec); /* dapm widget types */ diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 6362c7641ce..a35ce69d9d7 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -961,7 +961,7 @@ static void dapm_free_widgets(struct snd_soc_codec *codec) } static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec, - char *pin, int status) + const char *pin, int status) { struct snd_soc_dapm_widget *w; @@ -1643,7 +1643,7 @@ int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev, * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to * do any widget power switching. */ -int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin) +int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin) { return snd_soc_dapm_set_pin(codec, pin, 1); } @@ -1658,7 +1658,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin); * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to * do any widget power switching. */ -int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin) +int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, const char *pin) { return snd_soc_dapm_set_pin(codec, pin, 0); } @@ -1678,7 +1678,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin); * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to * do any widget power switching. */ -int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin) +int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, const char *pin) { return snd_soc_dapm_set_pin(codec, pin, 0); } @@ -1693,7 +1693,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin); * * Returns 1 for connected otherwise 0. */ -int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin) +int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, const char *pin) { struct snd_soc_dapm_widget *w; -- GitLab From 8a2cd6180f8fa00111843c2f4a4f4361995358e0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 7 Jan 2009 17:31:10 +0000 Subject: [PATCH 0075/4982] ASoC: Add jack reporting interface This patch adds a jack reporting interface to ASoC. This wraps the ALSA core jack detection functionality and provides integration with DAPM to automatically update the power state of pins based on the jack state. Since embedded platforms can have multiple detecton methods used for a single jack (eg, separate microphone and headphone detection) the report function allows specification of which bits are being updated on a given report. The expected usage is that machine drivers will create jack objects and then configure jack detection methods to update that jack. Signed-off-by: Mark Brown --- include/sound/soc.h | 32 ++++++++++ sound/soc/Kconfig | 1 + sound/soc/Makefile | 2 +- sound/soc/soc-jack.c | 138 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 sound/soc/soc-jack.c diff --git a/include/sound/soc.h b/include/sound/soc.h index 9b930d34211..9c3ef6a3e9f 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -154,6 +154,8 @@ enum snd_soc_bias_level { SND_SOC_BIAS_OFF, }; +struct snd_jack; +struct snd_soc_card; struct snd_soc_device; struct snd_soc_pcm_stream; struct snd_soc_ops; @@ -164,6 +166,8 @@ struct snd_soc_platform; struct snd_soc_codec; struct soc_enum; struct snd_soc_ac97_ops; +struct snd_soc_jack; +struct snd_soc_jack_pin; typedef int (*hw_write_t)(void *,const char* ,int); typedef int (*hw_read_t)(void *,char* ,int); @@ -184,6 +188,13 @@ int snd_soc_init_card(struct snd_soc_device *socdev); int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, const struct snd_pcm_hardware *hw); +/* Jack reporting */ +int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type, + struct snd_soc_jack *jack); +void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask); +int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, + struct snd_soc_jack_pin *pins); + /* codec IO */ #define snd_soc_read(codec, reg) codec->read(codec, reg) #define snd_soc_write(codec, reg, value) codec->write(codec, reg, value) @@ -239,6 +250,27 @@ int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol, int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); +/** + * struct snd_soc_jack_pin - Describes a pin to update based on jack detection + * + * @pin: name of the pin to update + * @mask: bits to check for in reported jack status + * @invert: if non-zero then pin is enabled when status is not reported + */ +struct snd_soc_jack_pin { + struct list_head list; + const char *pin; + int mask; + bool invert; +}; + +struct snd_soc_jack { + struct snd_jack *jack; + struct snd_soc_card *card; + struct list_head pins; + int status; +}; + /* SoC PCM stream information */ struct snd_soc_pcm_stream { char *stream_name; diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index ef025c66cc6..3d2bb6fc6dc 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -6,6 +6,7 @@ menuconfig SND_SOC tristate "ALSA for SoC audio support" select SND_PCM select AC97_BUS if SND_SOC_AC97_BUS + select SND_JACK if INPUT=y || INPUT=SND ---help--- If you want ASoC support, you should say Y here and also to the diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 86a9b1f5b0f..0237879fd41 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,4 +1,4 @@ -snd-soc-core-objs := soc-core.o soc-dapm.o +snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o obj-$(CONFIG_SND_SOC) += snd-soc-core.o obj-$(CONFIG_SND_SOC) += codecs/ diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c new file mode 100644 index 00000000000..8cc00c3cdf3 --- /dev/null +++ b/sound/soc/soc-jack.c @@ -0,0 +1,138 @@ +/* + * soc-jack.c -- ALSA SoC jack handling + * + * Copyright 2008 Wolfson Microelectronics PLC. + * + * Author: Mark Brown + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include + +/** + * snd_soc_jack_new - Create a new jack + * @card: ASoC card + * @id: an identifying string for this jack + * @type: a bitmask of enum snd_jack_type values that can be detected by + * this jack + * @jack: structure to use for the jack + * + * Creates a new jack object. + * + * Returns zero if successful, or a negative error code on failure. + * On success jack will be initialised. + */ +int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type, + struct snd_soc_jack *jack) +{ + jack->card = card; + INIT_LIST_HEAD(&jack->pins); + + return snd_jack_new(card->socdev->codec->card, id, type, &jack->jack); +} +EXPORT_SYMBOL_GPL(snd_soc_jack_new); + +/** + * snd_soc_jack_report - Report the current status for a jack + * + * @jack: the jack + * @status: a bitmask of enum snd_jack_type values that are currently detected. + * @mask: a bitmask of enum snd_jack_type values that being reported. + * + * If configured using snd_soc_jack_add_pins() then the associated + * DAPM pins will be enabled or disabled as appropriate and DAPM + * synchronised. + * + * Note: This function uses mutexes and should be called from a + * context which can sleep (such as a workqueue). + */ +void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) +{ + struct snd_soc_codec *codec = jack->card->socdev->codec; + struct snd_soc_jack_pin *pin; + int enable; + int oldstatus; + + if (!jack) { + WARN_ON_ONCE(!jack); + return; + } + + mutex_lock(&codec->mutex); + + oldstatus = jack->status; + + jack->status &= ~mask; + jack->status |= status; + + /* The DAPM sync is expensive enough to be worth skipping */ + if (jack->status == oldstatus) + goto out; + + list_for_each_entry(pin, &jack->pins, list) { + enable = pin->mask & status; + + if (pin->invert) + enable = !enable; + + if (enable) + snd_soc_dapm_enable_pin(codec, pin->pin); + else + snd_soc_dapm_disable_pin(codec, pin->pin); + } + + snd_soc_dapm_sync(codec); + + snd_jack_report(jack->jack, status); + +out: + mutex_unlock(&codec->mutex); +} +EXPORT_SYMBOL_GPL(snd_soc_jack_report); + +/** + * snd_soc_jack_add_pins - Associate DAPM pins with an ASoC jack + * + * @jack: ASoC jack + * @count: Number of pins + * @pins: Array of pins + * + * After this function has been called the DAPM pins specified in the + * pins array will have their status updated to reflect the current + * state of the jack whenever the jack status is updated. + */ +int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, + struct snd_soc_jack_pin *pins) +{ + int i; + + for (i = 0; i < count; i++) { + if (!pins[i].pin) { + printk(KERN_ERR "No name for pin %d\n", i); + return -EINVAL; + } + if (!pins[i].mask) { + printk(KERN_ERR "No mask for pin %d (%s)\n", i, + pins[i].pin); + return -EINVAL; + } + + INIT_LIST_HEAD(&pins[i].list); + list_add(&(pins[i].list), &jack->pins); + } + + /* Update to reflect the last reported status; canned jack + * implementations are likely to set their state before the + * card has an opportunity to associate pins. + */ + snd_soc_jack_report(jack, 0, 0); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_jack_add_pins); -- GitLab From a6ba2b2dabb583e7820e567fb309d771b50cb9ff Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 8 Jan 2009 15:16:16 +0000 Subject: [PATCH 0076/4982] ASoC: Implement WM8350 headphone jack detection Signed-off-by: Mark Brown --- include/linux/mfd/wm8350/audio.h | 1 + sound/soc/codecs/wm8350.c | 116 +++++++++++++++++++++++++++++++ sound/soc/codecs/wm8350.h | 8 +++ 3 files changed, 125 insertions(+) diff --git a/include/linux/mfd/wm8350/audio.h b/include/linux/mfd/wm8350/audio.h index af95a1d2f3a..d899dc0223b 100644 --- a/include/linux/mfd/wm8350/audio.h +++ b/include/linux/mfd/wm8350/audio.h @@ -490,6 +490,7 @@ /* * R231 (0xE7) - Jack Status */ +#define WM8350_JACK_L_LVL 0x0800 #define WM8350_JACK_R_LVL 0x0400 /* diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index e3989d406f5..47a9dabb523 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -51,10 +51,17 @@ struct wm8350_output { u16 mute; }; +struct wm8350_jack_data { + struct snd_soc_jack *jack; + int report; +}; + struct wm8350_data { struct snd_soc_codec codec; struct wm8350_output out1; struct wm8350_output out2; + struct wm8350_jack_data hpl; + struct wm8350_jack_data hpr; struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; }; @@ -1328,6 +1335,95 @@ static int wm8350_resume(struct platform_device *pdev) return 0; } +static void wm8350_hp_jack_handler(struct wm8350 *wm8350, int irq, void *data) +{ + struct wm8350_data *priv = data; + u16 reg; + int report; + int mask; + struct wm8350_jack_data *jack = NULL; + + switch (irq) { + case WM8350_IRQ_CODEC_JCK_DET_L: + jack = &priv->hpl; + mask = WM8350_JACK_L_LVL; + break; + + case WM8350_IRQ_CODEC_JCK_DET_R: + jack = &priv->hpr; + mask = WM8350_JACK_R_LVL; + break; + + default: + BUG(); + } + + if (!jack->jack) { + dev_warn(wm8350->dev, "Jack interrupt called with no jack\n"); + return; + } + + /* Debounce */ + msleep(200); + + reg = wm8350_reg_read(wm8350, WM8350_JACK_PIN_STATUS); + if (reg & mask) + report = jack->report; + else + report = 0; + + snd_soc_jack_report(jack->jack, report, jack->report); +} + +/** + * wm8350_hp_jack_detect - Enable headphone jack detection. + * + * @codec: WM8350 codec + * @which: left or right jack detect signal + * @jack: jack to report detection events on + * @report: value to report + * + * Enables the headphone jack detection of the WM8350. + */ +int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which, + struct snd_soc_jack *jack, int report) +{ + struct wm8350_data *priv = codec->private_data; + struct wm8350 *wm8350 = codec->control_data; + int irq; + int ena; + + switch (which) { + case WM8350_JDL: + priv->hpl.jack = jack; + priv->hpl.report = report; + irq = WM8350_IRQ_CODEC_JCK_DET_L; + ena = WM8350_JDL_ENA; + break; + + case WM8350_JDR: + priv->hpr.jack = jack; + priv->hpr.report = report; + irq = WM8350_IRQ_CODEC_JCK_DET_R; + ena = WM8350_JDR_ENA; + break; + + default: + return -EINVAL; + } + + wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); + wm8350_set_bits(wm8350, WM8350_JACK_DETECT, ena); + + /* Sync status */ + wm8350_hp_jack_handler(wm8350, irq, priv); + + wm8350_unmask_irq(wm8350, irq); + + return 0; +} +EXPORT_SYMBOL_GPL(wm8350_hp_jack_detect); + static struct snd_soc_codec *wm8350_codec; static int wm8350_probe(struct platform_device *pdev) @@ -1381,6 +1477,13 @@ static int wm8350_probe(struct platform_device *pdev) wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME, WM8350_OUT2_VU | WM8350_OUT2R_MUTE); + wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); + wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); + wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, + wm8350_hp_jack_handler, priv); + wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, + wm8350_hp_jack_handler, priv); + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) { dev_err(&pdev->dev, "failed to create pcms\n"); @@ -1411,8 +1514,21 @@ static int wm8350_remove(struct platform_device *pdev) struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct snd_soc_codec *codec = socdev->codec; struct wm8350 *wm8350 = codec->control_data; + struct wm8350_data *priv = codec->private_data; int ret; + wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, + WM8350_JDL_ENA | WM8350_JDR_ENA); + wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); + + wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); + wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); + wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); + wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); + + priv->hpl.jack = NULL; + priv->hpr.jack = NULL; + /* cancel any work waiting to be queued. */ ret = cancel_delayed_work(&codec->delayed_work); diff --git a/sound/soc/codecs/wm8350.h b/sound/soc/codecs/wm8350.h index cc2887aa6c3..d11bd9288cf 100644 --- a/sound/soc/codecs/wm8350.h +++ b/sound/soc/codecs/wm8350.h @@ -17,4 +17,12 @@ extern struct snd_soc_dai wm8350_dai; extern struct snd_soc_codec_device soc_codec_dev_wm8350; +enum wm8350_jack { + WM8350_JDL = 1, + WM8350_JDR = 2, +}; + +int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which, + struct snd_soc_jack *jack, int report); + #endif -- GitLab From 3e8e1952e3a3dd59b11233a532ca68e6471742d9 Mon Sep 17 00:00:00 2001 From: Ian Molton Date: Fri, 9 Jan 2009 00:23:21 +0000 Subject: [PATCH 0077/4982] ASoC: cleanup duplicated code. Many codec drivers were implementing cookie-cutter copies of the function that adds kcontrols to the codec. This patch moves this code to a common function snd_soc_add_controls() in soc-core.c and updates all drivers using copies of this function to use the new common version. [Edited to raise priority of error log message and document parameters. -- broonie] Signed-off-by: Ian Molton Signed-off-by: Mark Brown --- include/sound/soc.h | 2 ++ sound/soc/codecs/ad1980.c | 17 ++---------- sound/soc/codecs/ak4535.c | 18 ++---------- sound/soc/codecs/ssm2602.c | 18 ++---------- sound/soc/codecs/tlv320aic23.c | 21 ++------------ sound/soc/codecs/tlv320aic3x.c | 19 ++----------- sound/soc/codecs/twl4030.c | 19 ++----------- sound/soc/codecs/uda134x.c | 50 +++++++++++----------------------- sound/soc/codecs/uda1380.c | 18 ++---------- sound/soc/codecs/wm8350.c | 18 ++---------- sound/soc/codecs/wm8510.c | 19 ++----------- sound/soc/codecs/wm8580.c | 17 ++---------- sound/soc/codecs/wm8728.c | 18 ++---------- sound/soc/codecs/wm8731.c | 19 ++----------- sound/soc/codecs/wm8750.c | 18 ++---------- sound/soc/codecs/wm8753.c | 18 ++---------- sound/soc/codecs/wm8900.c | 19 ++----------- sound/soc/codecs/wm8903.c | 18 ++---------- sound/soc/codecs/wm8971.c | 18 ++---------- sound/soc/codecs/wm8990.c | 18 ++---------- sound/soc/codecs/wm9712.c | 18 ++---------- sound/soc/codecs/wm9713.c | 18 ++---------- sound/soc/soc-core.c | 31 +++++++++++++++++++++ 23 files changed, 89 insertions(+), 360 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 9c3ef6a3e9f..9d5a0362a05 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -214,6 +214,8 @@ void snd_soc_free_ac97_codec(struct snd_soc_codec *codec); */ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, void *data, char *long_name); +int snd_soc_add_controls(struct snd_soc_codec *codec, + const struct snd_kcontrol_new *controls, int num_controls); int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol, diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 73fdbb4d4a3..c3c5d0eee37 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c @@ -93,20 +93,6 @@ SOC_ENUM("Capture Source", ad1980_cap_src), SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0), }; -/* add non dapm controls */ -static int ad1980_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(ad1980_snd_ac97_controls); i++) { - err = snd_ctl_add(codec->card, snd_soc_cnew( - &ad1980_snd_ac97_controls[i], codec, NULL)); - if (err < 0) - return err; - } - return 0; -} - static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) { @@ -269,7 +255,8 @@ static int ad1980_soc_probe(struct platform_device *pdev) ext_status = ac97_read(codec, AC97_EXTENDED_STATUS); ac97_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800); - ad1980_add_controls(codec); + snd_soc_add_controls(codec, ad1980_snd_ac97_controls, + ARRAY_SIZE(ad1980_snd_ac97_controls)); ret = snd_soc_init_card(socdev); if (ret < 0) { printk(KERN_ERR "ad1980: failed to register card\n"); diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index 81300d8d42c..f17c363cb1d 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c @@ -155,21 +155,6 @@ static const struct snd_kcontrol_new ak4535_snd_controls[] = { SOC_SINGLE("Mic Sidetone Volume", AK4535_VOL, 4, 7, 0), }; -/* add non dapm controls */ -static int ak4535_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(ak4535_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&ak4535_snd_controls[i], codec, NULL)); - if (err < 0) - return err; - } - - return 0; -} - /* Mono 1 Mixer */ static const struct snd_kcontrol_new ak4535_mono1_mixer_controls[] = { SOC_DAPM_SINGLE("Mic Sidetone Switch", AK4535_SIG1, 4, 1, 0), @@ -510,7 +495,8 @@ static int ak4535_init(struct snd_soc_device *socdev) /* power on device */ ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - ak4535_add_controls(codec); + snd_soc_add_controls(codec, ak4535_snd_controls, + ARRAY_SIZE(ak4535_snd_controls)); ak4535_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index cac37361676..ec7fe3b7b0c 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -151,21 +151,6 @@ SOC_ENUM("Capture Source", ssm2602_enum[0]), SOC_ENUM("Playback De-emphasis", ssm2602_enum[1]), }; -/* add non dapm controls */ -static int ssm2602_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(ssm2602_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&ssm2602_snd_controls[i], codec, NULL)); - if (err < 0) - return err; - } - - return 0; -} - /* Output Mixer */ static const struct snd_kcontrol_new ssm2602_output_mixer_controls[] = { SOC_DAPM_SINGLE("Line Bypass Switch", SSM2602_APANA, 3, 1, 0), @@ -622,7 +607,8 @@ static int ssm2602_init(struct snd_soc_device *socdev) APANA_ENABLE_MIC_BOOST); ssm2602_write(codec, SSM2602_PWR, 0); - ssm2602_add_controls(codec); + snd_soc_add_controls(codec, ssm2602_snd_controls, + ARRAY_SIZE(ssm2602_snd_controls)); ssm2602_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index cfdea007c4c..a0e47c1dcd6 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -183,24 +183,6 @@ static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = { SOC_ENUM("Playback De-emphasis", tlv320aic23_deemph), }; -/* add non dapm controls */ -static int tlv320aic23_add_controls(struct snd_soc_codec *codec) -{ - - int err, i; - - for (i = 0; i < ARRAY_SIZE(tlv320aic23_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&tlv320aic23_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - - return 0; - -} - /* PGA Mixer controls for Line and Mic switch */ static const struct snd_kcontrol_new tlv320aic23_output_mixer_controls[] = { SOC_DAPM_SINGLE("Line Bypass Switch", TLV320AIC23_ANLG, 3, 1, 0), @@ -718,7 +700,8 @@ static int tlv320aic23_init(struct snd_soc_device *socdev) tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x1); - tlv320aic23_add_controls(codec); + snd_soc_add_controls(codec, tlv320aic23_snd_controls, + ARRAY_SIZE(tlv320aic23_snd_controls)); tlv320aic23_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index b47a749c5ea..36ab0198ca3 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -311,22 +311,6 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]), }; -/* add non dapm controls */ -static int aic3x_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(aic3x_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&aic3x_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - - return 0; -} - /* Left DAC Mux */ static const struct snd_kcontrol_new aic3x_left_dac_mux_controls = SOC_DAPM_ENUM("Route", aic3x_enum[LDAC_ENUM]); @@ -1224,7 +1208,8 @@ static int aic3x_init(struct snd_soc_device *socdev) aic3x_write(codec, AIC3X_GPIO1_REG, (setup->gpio_func[0] & 0xf) << 4); aic3x_write(codec, AIC3X_GPIO2_REG, (setup->gpio_func[1] & 0xf) << 4); - aic3x_add_controls(codec); + snd_soc_add_controls(codec, aic3x_snd_controls, + ARRAY_SIZE(aic3x_snd_controls)); aic3x_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index fd0f338374a..253063fd319 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -670,22 +670,6 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = { 0, 3, 5, 0, input_gain_tlv), }; -/* add non dapm controls */ -static int twl4030_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(twl4030_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&twl4030_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - - return 0; -} - static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { /* Left channel inputs */ SND_SOC_DAPM_INPUT("MAINMIC"), @@ -1233,7 +1217,8 @@ static int twl4030_init(struct snd_soc_device *socdev) /* power on device */ twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - twl4030_add_controls(codec); + snd_soc_add_controls(codec, twl4030_snd_controls, + ARRAY_SIZE(twl4030_snd_controls)); twl4030_add_widgets(codec); ret = snd_soc_init_card(socdev); diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index a2c5064a774..277825d155a 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c @@ -431,39 +431,6 @@ SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]), SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0), }; -static int uda134x_add_controls(struct snd_soc_codec *codec) -{ - int err, i, n; - const struct snd_kcontrol_new *ctrls; - struct uda134x_platform_data *pd = codec->control_data; - - switch (pd->model) { - case UDA134X_UDA1340: - case UDA134X_UDA1344: - n = ARRAY_SIZE(uda1340_snd_controls); - ctrls = uda1340_snd_controls; - break; - case UDA134X_UDA1341: - n = ARRAY_SIZE(uda1341_snd_controls); - ctrls = uda1341_snd_controls; - break; - default: - printk(KERN_ERR "%s unkown codec type: %d", - __func__, pd->model); - return -EINVAL; - } - - for (i = 0; i < n; i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&ctrls[i], - codec, NULL)); - if (err < 0) - return err; - } - - return 0; -} - struct snd_soc_dai uda134x_dai = { .name = "UDA134X", /* playback capabilities */ @@ -572,7 +539,22 @@ static int uda134x_soc_probe(struct platform_device *pdev) goto pcm_err; } - ret = uda134x_add_controls(codec); + switch (pd->model) { + case UDA134X_UDA1340: + case UDA134X_UDA1344: + ret = snd_soc_add_controls(codec, uda1340_snd_controls, + ARRAY_SIZE(uda1340_snd_controls)); + break; + case UDA134X_UDA1341: + ret = snd_soc_add_controls(codec, uda1341_snd_controls, + ARRAY_SIZE(uda1341_snd_controls)); + break; + default: + printk(KERN_ERR "%s unkown codec type: %d", + __func__, pd->model); + return -EINVAL; + } + if (ret < 0) { printk(KERN_ERR "UDA134X: failed to register controls\n"); goto pcm_err; diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index e6bf0844fbf..a957b4365b9 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -271,21 +271,6 @@ static const struct snd_kcontrol_new uda1380_snd_controls[] = { SOC_SINGLE("AGC Switch", UDA1380_AGC, 0, 1, 0), }; -/* add non dapm controls */ -static int uda1380_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(uda1380_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&uda1380_snd_controls[i], codec, NULL)); - if (err < 0) - return err; - } - - return 0; -} - /* Input mux */ static const struct snd_kcontrol_new uda1380_input_mux_control = SOC_DAPM_ENUM("Route", uda1380_input_sel_enum); @@ -675,7 +660,8 @@ static int uda1380_init(struct snd_soc_device *socdev, int dac_clk) } /* uda1380 init */ - uda1380_add_controls(codec); + snd_soc_add_controls(codec, uda1380_snd_controls, + ARRAY_SIZE(uda1380_snd_controls)); uda1380_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 47a9dabb523..2e0db29b499 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -782,21 +782,6 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Beep", NULL, "IN3R PGA"}, }; -static int wm8350_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8350_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8350_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - - return 0; -} - static int wm8350_add_widgets(struct snd_soc_codec *codec) { int ret; @@ -1490,7 +1475,8 @@ static int wm8350_probe(struct platform_device *pdev) return ret; } - wm8350_add_controls(codec); + snd_soc_add_controls(codec, wm8350_snd_controls, + ARRAY_SIZE(wm8350_snd_controls)); wm8350_add_widgets(codec); wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 40f8238df71..abe7cce8771 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -171,22 +171,6 @@ SOC_SINGLE("Capture Boost(+20dB)", WM8510_ADCBOOST, 8, 1, 0), SOC_SINGLE("Mono Playback Switch", WM8510_MONOMIX, 6, 1, 1), }; -/* add non dapm controls */ -static int wm8510_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8510_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8510_snd_controls[i], codec, - NULL)); - if (err < 0) - return err; - } - - return 0; -} - /* Speaker Output Mixer */ static const struct snd_kcontrol_new wm8510_speaker_mixer_controls[] = { SOC_DAPM_SINGLE("Line Bypass Switch", WM8510_SPKMIX, 1, 1, 0), @@ -656,7 +640,8 @@ static int wm8510_init(struct snd_soc_device *socdev) /* power on device */ codec->bias_level = SND_SOC_BIAS_OFF; wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - wm8510_add_controls(codec); + snd_soc_add_controls(codec, wm8510_snd_controls, + ARRAY_SIZE(wm8510_snd_controls)); wm8510_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index d004e584529..9b75a377453 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -330,20 +330,6 @@ SOC_DOUBLE("ADC Mute Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 0), SOC_SINGLE("ADC High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0), }; -/* Add non-DAPM controls */ -static int wm8580_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8580_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8580_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - return 0; -} static const struct snd_soc_dapm_widget wm8580_dapm_widgets[] = { SND_SOC_DAPM_DAC("DAC1", "Playback", WM8580_PWRDN1, 2, 1), SND_SOC_DAPM_DAC("DAC2", "Playback", WM8580_PWRDN1, 3, 1), @@ -866,7 +852,8 @@ static int wm8580_init(struct snd_soc_device *socdev) goto pcm_err; } - wm8580_add_controls(codec); + snd_soc_add_controls(codec, wm8580_snd_controls, + ARRAY_SIZE(wm8580_snd_controls)); wm8580_add_widgets(codec); ret = snd_soc_init_card(socdev); diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 80b11983e13..defa310bc7d 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -92,21 +92,6 @@ SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8728_DACLVOL, WM8728_DACRVOL, SOC_SINGLE("Deemphasis", WM8728_DACCTL, 1, 1, 0), }; -static int wm8728_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8728_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8728_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - - return 0; -} - /* * DAPM controls. */ @@ -330,7 +315,8 @@ static int wm8728_init(struct snd_soc_device *socdev) /* power on device */ wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - wm8728_add_controls(codec); + snd_soc_add_controls(codec, wm8728_snd_controls, + ARRAY_SIZE(wm8728_snd_controls)); wm8728_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index c444b9f2701..96d6e1aeaf4 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -129,22 +129,6 @@ SOC_SINGLE("Store DC Offset Switch", WM8731_APDIGI, 4, 1, 0), SOC_ENUM("Playback De-emphasis", wm8731_enum[1]), }; -/* add non dapm controls */ -static int wm8731_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8731_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8731_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - - return 0; -} - /* Output Mixer */ static const struct snd_kcontrol_new wm8731_output_mixer_controls[] = { SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0), @@ -543,7 +527,8 @@ static int wm8731_init(struct snd_soc_device *socdev) reg = wm8731_read_reg_cache(codec, WM8731_RINVOL); wm8731_write(codec, WM8731_RINVOL, reg & ~0x0100); - wm8731_add_controls(codec); + snd_soc_add_controls(codec, wm8731_snd_controls, + ARRAY_SIZE(wm8731_snd_controls)); wm8731_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 5997fa68e0d..1578569793a 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -231,21 +231,6 @@ SOC_SINGLE("Mono Playback Volume", WM8750_MOUTV, 0, 127, 0), }; -/* add non dapm controls */ -static int wm8750_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8750_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8750_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - return 0; -} - /* * DAPM Controls */ @@ -816,7 +801,8 @@ static int wm8750_init(struct snd_soc_device *socdev) reg = wm8750_read_reg_cache(codec, WM8750_RINVOL); wm8750_write(codec, WM8750_RINVOL, reg | 0x0100); - wm8750_add_controls(codec); + snd_soc_add_controls(codec, wm8750_snd_controls, + ARRAY_SIZE(wm8750_snd_controls)); wm8750_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 6c21b50c937..7283178e0eb 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -339,21 +339,6 @@ SOC_ENUM("ADC Data Select", wm8753_enum[27]), SOC_ENUM("ROUT2 Phase", wm8753_enum[28]), }; -/* add non dapm controls */ -static int wm8753_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8753_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8753_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - return 0; -} - /* * _DAPM_ Controls */ @@ -1603,7 +1588,8 @@ static int wm8753_init(struct snd_soc_device *socdev) reg = wm8753_read_reg_cache(codec, WM8753_RINVOL); wm8753_write(codec, WM8753_RINVOL, reg | 0x0100); - wm8753_add_controls(codec); + snd_soc_add_controls(codec, wm8753_snd_controls, + ARRAY_SIZE(wm8753_snd_controls)); wm8753_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 6767de10ded..1e08d4f065f 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -517,22 +517,6 @@ SOC_SINGLE("LINEOUT2 LP -12dB", WM8900_REG_LOUTMIXCTL1, }; -/* add non dapm controls */ -static int wm8900_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8900_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8900_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - - return 0; -} - static const struct snd_kcontrol_new wm8900_dapm_loutput2_control = SOC_DAPM_SINGLE("LINEOUT2L Switch", WM8900_REG_POWER3, 6, 1, 0); @@ -1439,7 +1423,8 @@ static int wm8900_probe(struct platform_device *pdev) goto pcm_err; } - wm8900_add_controls(codec); + snd_soc_add_controls(codec, wm8900_snd_controls, + ARRAY_SIZE(wm8900_snd_controls)); wm8900_add_widgets(codec); ret = snd_soc_init_card(socdev); diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index bde74546db4..6ff34b957dc 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -744,21 +744,6 @@ SOC_DOUBLE_R_TLV("Speaker Volume", 0, 63, 0, out_tlv), }; -static int wm8903_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8903_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8903_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - - return 0; -} - static const struct snd_kcontrol_new linput_mode_mux = SOC_DAPM_ENUM("Left Input Mode Mux", linput_mode_enum); @@ -1737,7 +1722,8 @@ static int wm8903_probe(struct platform_device *pdev) goto err; } - wm8903_add_controls(socdev->codec); + snd_soc_add_controls(socdev->codec, wm8903_snd_controls, + ARRAY_SIZE(wm8903_snd_controls)); wm8903_add_widgets(socdev->codec); ret = snd_soc_init_card(socdev); diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 88ead7f8dd9..c8bd9b06f33 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -195,21 +195,6 @@ static const struct snd_kcontrol_new wm8971_snd_controls[] = { SOC_DOUBLE_R("Mic Boost", WM8971_LADCIN, WM8971_RADCIN, 4, 3, 0), }; -/* add non-DAPM controls */ -static int wm8971_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8971_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8971_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - return 0; -} - /* * DAPM Controls */ @@ -745,7 +730,8 @@ static int wm8971_init(struct snd_soc_device *socdev) reg = wm8971_read_reg_cache(codec, WM8971_RINVOL); wm8971_write(codec, WM8971_RINVOL, reg | 0x0100); - wm8971_add_controls(codec); + snd_soc_add_controls(codec, wm8971_snd_controls, + ARRAY_SIZE(wm8971_snd_controls)); wm8971_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 5b5afc14447..6b2778632d5 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -417,21 +417,6 @@ SOC_SINGLE("RIN34 Mute Switch", WM8990_RIGHT_LINE_INPUT_3_4_VOLUME, }; -/* add non dapm controls */ -static int wm8990_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8990_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8990_snd_controls[i], codec, - NULL)); - if (err < 0) - return err; - } - return 0; -} - /* * _DAPM_ Controls */ @@ -1460,7 +1445,8 @@ static int wm8990_init(struct snd_soc_device *socdev) wm8990_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); wm8990_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); - wm8990_add_controls(codec); + snd_soc_add_controls(codec, wm8990_snd_controls, + ARRAY_SIZE(wm8990_snd_controls)); wm8990_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index af83d629078..1b0ace0f4dc 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -154,21 +154,6 @@ SOC_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1), SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0), }; -/* add non dapm controls */ -static int wm9712_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm9712_snd_ac97_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm9712_snd_ac97_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - return 0; -} - /* We have to create a fake left and right HP mixers because * the codec only has a single control that is shared by both channels. * This makes it impossible to determine the audio path. @@ -698,7 +683,8 @@ static int wm9712_soc_probe(struct platform_device *pdev) ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000); wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - wm9712_add_controls(codec); + snd_soc_add_controls(codec, wm9712_snd_ac97_controls, + ARRAY_SIZE(wm9712_snd_ac97_controls)); wm9712_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index f3ca8aaf013..a45622620db 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -190,21 +190,6 @@ SOC_SINGLE("3D Lower Cut-off Switch", AC97_REC_GAIN_MIC, 4, 1, 0), SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1), }; -/* add non dapm controls */ -static int wm9713_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm9713_snd_ac97_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm9713_snd_ac97_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - return 0; -} - /* We have to create a fake left and right HP mixers because * the codec only has a single control that is shared by both channels. * This makes it impossible to determine the audio path using the current @@ -1245,7 +1230,8 @@ static int wm9713_soc_probe(struct platform_device *pdev) reg = ac97_read(codec, AC97_CD) & 0x7fff; ac97_write(codec, AC97_CD, reg); - wm9713_add_controls(codec); + snd_soc_add_controls(codec, wm9713_snd_ac97_controls, + ARRAY_SIZE(wm9713_snd_ac97_controls)); wm9713_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 6cbe7e82f23..d3b97a7542e 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1494,6 +1494,37 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, } EXPORT_SYMBOL_GPL(snd_soc_cnew); +/** + * snd_soc_add_controls - add an array of controls to a codec. + * Convienience function to add a list of controls. Many codecs were + * duplicating this code. + * + * @codec: codec to add controls to + * @controls: array of controls to add + * @num_controls: number of elements in the array + * + * Return 0 for success, else error. + */ +int snd_soc_add_controls(struct snd_soc_codec *codec, + const struct snd_kcontrol_new *controls, int num_controls) +{ + struct snd_card *card = codec->card; + int err, i; + + for (i = 0; i < num_controls; i++) { + const struct snd_kcontrol_new *control = &controls[i]; + err = snd_ctl_add(card, snd_soc_cnew(control, codec, NULL)); + if (err < 0) { + dev_err(codec->dev, "%s: Failed to add %s\n", + codec->name, control->name); + return err; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_add_controls); + /** * snd_soc_info_enum_double - enumerated double mixer info callback * @kcontrol: mixer control -- GitLab From 736f93236ce786d1bcf09ad4dcb38a360d35ea1b Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 10 Jan 2009 12:06:19 +0100 Subject: [PATCH 0078/4982] bzip2/lzma: make flush_buffer() unconditional Impact: build fix flush_buffer() is used unconditionally: init/initramfs.c:456: error: 'flush_buffer' undeclared (first use in this function) init/initramfs.c:456: error: (Each undeclared identifier is reported only once init/initramfs.c:456: error: for each function it appears in.) So remove the decompressor #ifdefs from around it. Signed-off-by: Ingo Molnar --- init/initramfs.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/init/initramfs.c b/init/initramfs.c index f8241e832aa..76f4a012533 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -390,7 +390,6 @@ static int __init write_buffer(char *buf, unsigned len) return len - count; } -#if defined CONFIG_RD_GZIP || defined CONFIG_RD_BZIP2 || defined CONFIG_RD_LZMA static int __init flush_buffer(void *bufv, unsigned len) { char *buf = (char *) bufv; @@ -413,7 +412,6 @@ static int __init flush_buffer(void *bufv, unsigned len) } return origLen; } -#endif static unsigned my_inptr; /* index of next byte to be processed in inbuf */ -- GitLab From 068790334cececc3d2d945617ccc585477da2e38 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 10 Jan 2009 12:17:37 +0530 Subject: [PATCH 0079/4982] x86: smp.h move cpu_callin_mask and cpu_callin_map declartion to cpumask.h Impact: cleanup Signed-off-by: Jaswinder Singh Rajput Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpumask.h | 19 +++++++++++++++++++ arch/x86/include/asm/smp.h | 3 --- arch/x86/kernel/cpu/common.c | 1 + arch/x86/kernel/setup_percpu.c | 1 + arch/x86/kernel/smpboot.c | 1 + 5 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 arch/x86/include/asm/cpumask.h diff --git a/arch/x86/include/asm/cpumask.h b/arch/x86/include/asm/cpumask.h new file mode 100644 index 00000000000..308dddd5632 --- /dev/null +++ b/arch/x86/include/asm/cpumask.h @@ -0,0 +1,19 @@ +#ifndef _ASM_X86_CPUMASK_H +#define _ASM_X86_CPUMASK_H +#ifndef __ASSEMBLY__ +#include + +#ifdef CONFIG_X86_64 + +extern cpumask_var_t cpu_callin_mask; + +#else /* CONFIG_X86_32 */ + +extern cpumask_t cpu_callin_map; + +#define cpu_callin_mask ((struct cpumask *)&cpu_callin_map) + +#endif /* CONFIG_X86_32 */ + +#endif /* __ASSEMBLY__ */ +#endif /* _ASM_X86_CPUMASK_H */ diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index 1963e27673c..c35aa5c0dd1 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -20,19 +20,16 @@ #ifdef CONFIG_X86_64 -extern cpumask_var_t cpu_callin_mask; extern cpumask_var_t cpu_callout_mask; extern cpumask_var_t cpu_initialized_mask; extern cpumask_var_t cpu_sibling_setup_mask; #else /* CONFIG_X86_32 */ -extern cpumask_t cpu_callin_map; extern cpumask_t cpu_callout_map; extern cpumask_t cpu_initialized; extern cpumask_t cpu_sibling_setup_map; -#define cpu_callin_mask ((struct cpumask *)&cpu_callin_map) #define cpu_callout_mask ((struct cpumask *)&cpu_callout_map) #define cpu_initialized_mask ((struct cpumask *)&cpu_initialized) #define cpu_sibling_setup_mask ((struct cpumask *)&cpu_sibling_setup_map) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 14e543b6fd4..f0025846244 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -22,6 +22,7 @@ #include #include #include +#include #ifdef CONFIG_X86_LOCAL_APIC #include #include diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 55c46074eba..bf63de72b64 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -13,6 +13,7 @@ #include #include #include +#include #ifdef CONFIG_X86_LOCAL_APIC unsigned int num_processors; diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 6c2b8444b83..84ac1cf46d8 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include -- GitLab From fb8fd077fbf0de6662acfd240e8e6b25cf3202ca Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 10 Jan 2009 12:20:24 +0530 Subject: [PATCH 0080/4982] x86: smp.h move cpu_callout_mask and cpu_callout_map declartion to cpumask.h Impact: cleanup Signed-off-by: Jaswinder Singh Rajput Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpumask.h | 3 +++ arch/x86/include/asm/smp.h | 4 +--- arch/x86/kernel/smpboot.c | 1 - 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/cpumask.h b/arch/x86/include/asm/cpumask.h index 308dddd5632..9933fcad3c8 100644 --- a/arch/x86/include/asm/cpumask.h +++ b/arch/x86/include/asm/cpumask.h @@ -6,12 +6,15 @@ #ifdef CONFIG_X86_64 extern cpumask_var_t cpu_callin_mask; +extern cpumask_var_t cpu_callout_mask; #else /* CONFIG_X86_32 */ extern cpumask_t cpu_callin_map; +extern cpumask_t cpu_callout_map; #define cpu_callin_mask ((struct cpumask *)&cpu_callin_map) +#define cpu_callout_mask ((struct cpumask *)&cpu_callout_map) #endif /* CONFIG_X86_32 */ diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index c35aa5c0dd1..a3afec5cad0 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -17,20 +17,18 @@ #endif #include #include +#include #ifdef CONFIG_X86_64 -extern cpumask_var_t cpu_callout_mask; extern cpumask_var_t cpu_initialized_mask; extern cpumask_var_t cpu_sibling_setup_mask; #else /* CONFIG_X86_32 */ -extern cpumask_t cpu_callout_map; extern cpumask_t cpu_initialized; extern cpumask_t cpu_sibling_setup_map; -#define cpu_callout_mask ((struct cpumask *)&cpu_callout_map) #define cpu_initialized_mask ((struct cpumask *)&cpu_initialized) #define cpu_sibling_setup_mask ((struct cpumask *)&cpu_sibling_setup_map) diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 84ac1cf46d8..6c2b8444b83 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -55,7 +55,6 @@ #include #include #include -#include #include #include #include -- GitLab From 493f6ca54e1ea59732dd334e35c5fe2d8e440b06 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 10 Jan 2009 12:48:22 +0530 Subject: [PATCH 0081/4982] x86: smp.h move cpu_initialized_mask and cpu_initialized declartion to cpumask.h Impact: cleanup Signed-off-by: Jaswinder Singh Rajput Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpumask.h | 3 +++ arch/x86/include/asm/smp.h | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/cpumask.h b/arch/x86/include/asm/cpumask.h index 9933fcad3c8..d4cfd120b84 100644 --- a/arch/x86/include/asm/cpumask.h +++ b/arch/x86/include/asm/cpumask.h @@ -7,14 +7,17 @@ extern cpumask_var_t cpu_callin_mask; extern cpumask_var_t cpu_callout_mask; +extern cpumask_var_t cpu_initialized_mask; #else /* CONFIG_X86_32 */ extern cpumask_t cpu_callin_map; extern cpumask_t cpu_callout_map; +extern cpumask_t cpu_initialized; #define cpu_callin_mask ((struct cpumask *)&cpu_callin_map) #define cpu_callout_mask ((struct cpumask *)&cpu_callout_map) +#define cpu_initialized_mask ((struct cpumask *)&cpu_initialized) #endif /* CONFIG_X86_32 */ diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index a3afec5cad0..7d2a80319e8 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -21,15 +21,12 @@ #ifdef CONFIG_X86_64 -extern cpumask_var_t cpu_initialized_mask; extern cpumask_var_t cpu_sibling_setup_mask; #else /* CONFIG_X86_32 */ -extern cpumask_t cpu_initialized; extern cpumask_t cpu_sibling_setup_map; -#define cpu_initialized_mask ((struct cpumask *)&cpu_initialized) #define cpu_sibling_setup_mask ((struct cpumask *)&cpu_sibling_setup_map) #endif /* CONFIG_X86_32 */ -- GitLab From 52811d8c9beb67da6bc4b770de3c4134376788a1 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 10 Jan 2009 12:58:50 +0530 Subject: [PATCH 0082/4982] x86: smp.h move cpu_sibling_setup_mask and cpu_sibling_setup_map declartion to cpumask.h Impact: cleanup Signed-off-by: Jaswinder Singh Rajput Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpumask.h | 3 +++ arch/x86/include/asm/smp.h | 12 ------------ 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/arch/x86/include/asm/cpumask.h b/arch/x86/include/asm/cpumask.h index d4cfd120b84..26c6dad9047 100644 --- a/arch/x86/include/asm/cpumask.h +++ b/arch/x86/include/asm/cpumask.h @@ -8,16 +8,19 @@ extern cpumask_var_t cpu_callin_mask; extern cpumask_var_t cpu_callout_mask; extern cpumask_var_t cpu_initialized_mask; +extern cpumask_var_t cpu_sibling_setup_mask; #else /* CONFIG_X86_32 */ extern cpumask_t cpu_callin_map; extern cpumask_t cpu_callout_map; extern cpumask_t cpu_initialized; +extern cpumask_t cpu_sibling_setup_map; #define cpu_callin_mask ((struct cpumask *)&cpu_callin_map) #define cpu_callout_mask ((struct cpumask *)&cpu_callout_map) #define cpu_initialized_mask ((struct cpumask *)&cpu_initialized) +#define cpu_sibling_setup_mask ((struct cpumask *)&cpu_sibling_setup_map) #endif /* CONFIG_X86_32 */ diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index 7d2a80319e8..a8cea7b0943 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -19,18 +19,6 @@ #include #include -#ifdef CONFIG_X86_64 - -extern cpumask_var_t cpu_sibling_setup_mask; - -#else /* CONFIG_X86_32 */ - -extern cpumask_t cpu_sibling_setup_map; - -#define cpu_sibling_setup_mask ((struct cpumask *)&cpu_sibling_setup_map) - -#endif /* CONFIG_X86_32 */ - extern int __cpuinit get_local_pda(int cpu); extern int smp_num_siblings; -- GitLab From d7e51e66899f95dabc89b4d4c6674a6e50fa37fc Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Wed, 7 Jan 2009 15:03:13 -0800 Subject: [PATCH 0083/4982] sparseirq: make some func to be used with genirq Impact: clean up sparseirq fallout on random.c Ingo suggested to change some ifdef from SPARSE_IRQ to GENERIC_HARDIRQS so we could some #ifdef later if all arch support genirq Signed-off-by: Yinghai Lu Acked-by: Matt Mackall Signed-off-by: Ingo Molnar --- drivers/char/random.c | 2 +- drivers/pci/intr_remapping.c | 2 +- include/linux/irq.h | 6 ++---- include/linux/kernel_stat.h | 6 +++--- kernel/irq/handle.c | 7 ++++--- 5 files changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 7c13581ca9c..a778918c8f4 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -558,7 +558,7 @@ struct timer_rand_state { unsigned dont_count_entropy:1; }; -#ifndef CONFIG_SPARSE_IRQ +#ifndef CONFIG_GENERIC_HARDIRQS static struct timer_rand_state *irq_timer_state[NR_IRQS]; diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index f78371b2252..3d604132a04 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c @@ -20,7 +20,7 @@ struct irq_2_iommu { u8 irte_mask; }; -#ifdef CONFIG_SPARSE_IRQ +#ifdef CONFIG_GENERIC_HARDIRQS static struct irq_2_iommu *get_one_free_irq_2_iommu(int cpu) { struct irq_2_iommu *iommu; diff --git a/include/linux/irq.h b/include/linux/irq.h index f899b502f18..e9a878978c8 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -160,12 +160,10 @@ struct irq_2_iommu; */ struct irq_desc { unsigned int irq; -#ifdef CONFIG_SPARSE_IRQ struct timer_rand_state *timer_rand_state; unsigned int *kstat_irqs; -# ifdef CONFIG_INTR_REMAP +#ifdef CONFIG_INTR_REMAP struct irq_2_iommu *irq_2_iommu; -# endif #endif irq_flow_handler_t handle_irq; struct irq_chip *chip; @@ -202,13 +200,13 @@ extern void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc extern struct irq_desc irq_desc[NR_IRQS]; #else /* CONFIG_SPARSE_IRQ */ extern struct irq_desc *move_irq_desc(struct irq_desc *old_desc, int cpu); +#endif /* CONFIG_SPARSE_IRQ */ #define kstat_irqs_this_cpu(DESC) \ ((DESC)->kstat_irqs[smp_processor_id()]) #define kstat_incr_irqs_this_cpu(irqno, DESC) \ ((DESC)->kstat_irqs[smp_processor_id()]++) -#endif /* CONFIG_SPARSE_IRQ */ extern struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu); diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h index 570d2041311..a3431b164be 100644 --- a/include/linux/kernel_stat.h +++ b/include/linux/kernel_stat.h @@ -28,7 +28,7 @@ struct cpu_usage_stat { struct kernel_stat { struct cpu_usage_stat cpustat; -#ifndef CONFIG_SPARSE_IRQ +#ifndef CONFIG_GENERIC_HARDIRQS unsigned int irqs[NR_IRQS]; #endif }; @@ -41,7 +41,7 @@ DECLARE_PER_CPU(struct kernel_stat, kstat); extern unsigned long long nr_context_switches(void); -#ifndef CONFIG_SPARSE_IRQ +#ifndef CONFIG_GENERIC_HARDIRQS #define kstat_irqs_this_cpu(irq) \ (kstat_this_cpu.irqs[irq]) @@ -55,7 +55,7 @@ static inline void kstat_incr_irqs_this_cpu(unsigned int irq, #endif -#ifndef CONFIG_SPARSE_IRQ +#ifndef CONFIG_GENERIC_HARDIRQS static inline unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) { return kstat_cpu(cpu).irqs[irq]; diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index c20db0be917..48299a8a22f 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -213,6 +213,7 @@ struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { } }; +static unsigned int kstat_irqs_all[NR_IRQS][NR_CPUS]; int __init early_irq_init(void) { struct irq_desc *desc; @@ -222,8 +223,10 @@ int __init early_irq_init(void) desc = irq_desc; count = ARRAY_SIZE(irq_desc); - for (i = 0; i < count; i++) + for (i = 0; i < count; i++) { desc[i].irq = i; + desc[i].kstat_irqs = kstat_irqs_all[i]; + } return arch_early_irq_init(); } @@ -451,12 +454,10 @@ void early_init_irq_lock_class(void) } } -#ifdef CONFIG_SPARSE_IRQ unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) { struct irq_desc *desc = irq_to_desc(irq); return desc ? desc->kstat_irqs[cpu] : 0; } -#endif EXPORT_SYMBOL(kstat_irqs_cpu); -- GitLab From 7106a5ab89c50c6b5aadea0850b40323804a922d Mon Sep 17 00:00:00 2001 From: Benjamin LaHaise Date: Sat, 10 Jan 2009 23:00:22 -0500 Subject: [PATCH 0084/4982] x86-64: remove locked instruction from switch_to() Impact: micro-optimization The patch below removes an unnecessary locked instruction from switch_to(). TIF_FORK is only ever set in copy_thread() on initial process creation, and gets cleared during the first scheduling of the process. As such, it is safe to use an unlocked test for the flag within switch_to(). Signed-off-by: Benjamin LaHaise Signed-off-by: Ingo Molnar --- arch/x86/include/asm/system.h | 6 +++--- arch/x86/kernel/entry_64.S | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h index 8e626ea33a1..fa47b1e6a86 100644 --- a/arch/x86/include/asm/system.h +++ b/arch/x86/include/asm/system.h @@ -96,15 +96,15 @@ do { \ "thread_return:\n\t" \ "movq %%gs:%P[pda_pcurrent],%%rsi\n\t" \ "movq %P[thread_info](%%rsi),%%r8\n\t" \ - LOCK_PREFIX "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" \ "movq %%rax,%%rdi\n\t" \ - "jc ret_from_fork\n\t" \ + "testl %[_tif_fork],%P[ti_flags](%%r8)\n\t" \ + "jnz ret_from_fork\n\t" \ RESTORE_CONTEXT \ : "=a" (last) \ : [next] "S" (next), [prev] "D" (prev), \ [threadrsp] "i" (offsetof(struct task_struct, thread.sp)), \ [ti_flags] "i" (offsetof(struct thread_info, flags)), \ - [tif_fork] "i" (TIF_FORK), \ + [_tif_fork] "i" (_TIF_FORK), \ [thread_info] "i" (offsetof(struct task_struct, stack)), \ [pda_pcurrent] "i" (offsetof(struct x8664_pda, pcurrent)) \ : "memory", "cc" __EXTRA_CLOBBER) diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index e28c7a98779..38dd37458e4 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -408,6 +408,8 @@ END(save_paranoid) ENTRY(ret_from_fork) DEFAULT_FRAME + LOCK ; btr $TIF_FORK,TI_flags(%r8) + push kernel_eflags(%rip) CFI_ADJUST_CFA_OFFSET 8 popf # reset kernel eflags -- GitLab From 199f7978730a4bbd88038fd84212b30759579f1a Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Fri, 9 Jan 2009 23:10:52 +0100 Subject: [PATCH 0085/4982] ALSA: wss-lib: move AD1845 frequency setting into wss-lib This is required to allow the sscape driver to autodetect installed codec. Also, do not create a timer if detected codec has no hardware timer (e.g. AD1848). Signed-off-by: Krzysztof Helt Cc: Rene Herman Signed-off-by: Takashi Iwai --- sound/isa/sscape.c | 113 +++------------------------------------- sound/isa/wss/wss_lib.c | 40 ++++++++++++++ 2 files changed, 48 insertions(+), 105 deletions(-) diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 48a16d86583..bc449166d18 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -129,9 +129,6 @@ enum GA_REG { #define DMA_8BIT 0x80 -#define AD1845_FREQ_SEL_MSB 0x16 -#define AD1845_FREQ_SEL_LSB 0x17 - enum card_type { SSCAPE, SSCAPE_PNP, @@ -954,82 +951,6 @@ static int __devinit create_mpu401(struct snd_card *card, int devnum, unsigned l } -/* - * Override for the CS4231 playback format function. - * The AD1845 has much simpler format and rate selection. - */ -static void ad1845_playback_format(struct snd_wss *chip, - struct snd_pcm_hw_params *params, - unsigned char format) -{ - unsigned long flags; - unsigned rate = params_rate(params); - - /* - * The AD1845 can't handle sample frequencies - * outside of 4 kHZ to 50 kHZ - */ - if (rate > 50000) - rate = 50000; - else if (rate < 4000) - rate = 4000; - - spin_lock_irqsave(&chip->reg_lock, flags); - - /* - * Program the AD1845 correctly for the playback stream. - * Note that we do NOT need to toggle the MCE bit because - * the PLAYBACK_ENABLE bit of the Interface Configuration - * register is set. - * - * NOTE: We seem to need to write to the MSB before the LSB - * to get the correct sample frequency. - */ - snd_wss_out(chip, CS4231_PLAYBK_FORMAT, (format & 0xf0)); - snd_wss_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8)); - snd_wss_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate); - - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -/* - * Override for the CS4231 capture format function. - * The AD1845 has much simpler format and rate selection. - */ -static void ad1845_capture_format(struct snd_wss *chip, - struct snd_pcm_hw_params *params, - unsigned char format) -{ - unsigned long flags; - unsigned rate = params_rate(params); - - /* - * The AD1845 can't handle sample frequencies - * outside of 4 kHZ to 50 kHZ - */ - if (rate > 50000) - rate = 50000; - else if (rate < 4000) - rate = 4000; - - spin_lock_irqsave(&chip->reg_lock, flags); - - /* - * Program the AD1845 correctly for the playback stream. - * Note that we do NOT need to toggle the MCE bit because - * the CAPTURE_ENABLE bit of the Interface Configuration - * register is set. - * - * NOTE: We seem to need to write to the MSB before the LSB - * to get the correct sample frequency. - */ - snd_wss_out(chip, CS4231_REC_FORMAT, (format & 0xf0)); - snd_wss_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8)); - snd_wss_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate); - - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - /* * Create an AD1845 PCM subdevice on the SoundScape. The AD1845 * is very much like a CS4231, with a few extra bits. We will @@ -1055,11 +976,6 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, unsigned long flags; struct snd_pcm *pcm; -#define AD1845_FREQ_SEL_ENABLE 0x08 - -#define AD1845_PWR_DOWN_CTRL 0x1b -#define AD1845_CRYS_CLOCK_SEL 0x1d - /* * It turns out that the PLAYBACK_ENABLE bit is set * by the lowlevel driver ... @@ -1074,7 +990,6 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, */ if (sscape->type != SSCAPE_VIVO) { - int val; /* * The input clock frequency on the SoundScape must * be 14.31818 MHz, because we must set this register @@ -1082,22 +997,10 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, */ snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); - snd_wss_out(chip, AD1845_CRYS_CLOCK_SEL, 0x20); + snd_wss_out(chip, AD1845_CLOCK, 0x20); spin_unlock_irqrestore(&chip->reg_lock, flags); snd_wss_mce_down(chip); - /* - * More custom configuration: - * a) select "mode 2" and provide a current drive of 8mA - * b) enable frequency selection (for capture/playback) - */ - spin_lock_irqsave(&chip->reg_lock, flags); - snd_wss_out(chip, CS4231_MISC_INFO, - CS4231_MODE2 | 0x10); - val = snd_wss_in(chip, AD1845_PWR_DOWN_CTRL); - snd_wss_out(chip, AD1845_PWR_DOWN_CTRL, - val | AD1845_FREQ_SEL_ENABLE); - spin_unlock_irqrestore(&chip->reg_lock, flags); } err = snd_wss_pcm(chip, 0, &pcm); @@ -1113,11 +1016,13 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, "for AD1845 chip\n"); goto _error; } - err = snd_wss_timer(chip, 0, NULL); - if (err < 0) { - snd_printk(KERN_ERR "sscape: No timer device " - "for AD1845 chip\n"); - goto _error; + if (chip->hardware != WSS_HW_AD1848) { + err = snd_wss_timer(chip, 0, NULL); + if (err < 0) { + snd_printk(KERN_ERR "sscape: No timer device " + "for AD1845 chip\n"); + goto _error; + } } if (sscape->type != SSCAPE_VIVO) { @@ -1128,8 +1033,6 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, "MIDI mixer control\n"); goto _error; } - chip->set_playback_format = ad1845_playback_format; - chip->set_capture_format = ad1845_capture_format; } strcpy(card->driver, "SoundScape"); diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index 3d6c5f2838a..13299aebd07 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c @@ -646,6 +646,24 @@ static void snd_wss_playback_format(struct snd_wss *chip, full_calib = 0; } spin_unlock_irqrestore(&chip->reg_lock, flags); + } else if (chip->hardware == WSS_HW_AD1845) { + unsigned rate = params_rate(params); + + /* + * Program the AD1845 correctly for the playback stream. + * Note that we do NOT need to toggle the MCE bit because + * the PLAYBACK_ENABLE bit of the Interface Configuration + * register is set. + * + * NOTE: We seem to need to write to the MSB before the LSB + * to get the correct sample frequency. + */ + spin_lock_irqsave(&chip->reg_lock, flags); + snd_wss_out(chip, CS4231_PLAYBK_FORMAT, (pdfr & 0xf0)); + snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff); + snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff); + full_calib = 0; + spin_unlock_irqrestore(&chip->reg_lock, flags); } if (full_calib) { snd_wss_mce_up(chip); @@ -690,6 +708,24 @@ static void snd_wss_capture_format(struct snd_wss *chip, full_calib = 0; } spin_unlock_irqrestore(&chip->reg_lock, flags); + } else if (chip->hardware == WSS_HW_AD1845) { + unsigned rate = params_rate(params); + + /* + * Program the AD1845 correctly for the capture stream. + * Note that we do NOT need to toggle the MCE bit because + * the PLAYBACK_ENABLE bit of the Interface Configuration + * register is set. + * + * NOTE: We seem to need to write to the MSB before the LSB + * to get the correct sample frequency. + */ + spin_lock_irqsave(&chip->reg_lock, flags); + snd_wss_out(chip, CS4231_REC_FORMAT, (cdfr & 0xf0)); + snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff); + snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff); + full_calib = 0; + spin_unlock_irqrestore(&chip->reg_lock, flags); } if (full_calib) { snd_wss_mce_up(chip); @@ -1314,6 +1350,10 @@ static int snd_wss_probe(struct snd_wss *chip) chip->image[CS4231_ALT_FEATURE_2] = chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01; } + /* enable fine grained frequency selection */ + if (chip->hardware == WSS_HW_AD1845) + chip->image[AD1845_PWR_DOWN] = 8; + ptr = (unsigned char *) &chip->image; regnum = (chip->hardware & WSS_HW_AD1848_MASK) ? 16 : 32; snd_wss_mce_down(chip); -- GitLab From dee4102a9a5882b4f7d5cc165ba29e8cc63cf92e Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 11 Jan 2009 00:29:15 -0800 Subject: [PATCH 0086/4982] sparseirq: use kstat_irqs_cpu instead Impact: build fix Ingo Molnar wrote: > tip/arch/blackfin/kernel/irqchip.c: In function 'show_interrupts': > tip/arch/blackfin/kernel/irqchip.c:85: error: 'struct kernel_stat' has no member named 'irqs' > make[2]: *** [arch/blackfin/kernel/irqchip.o] Error 1 > make[2]: *** Waiting for unfinished jobs.... > So could move kstat_irqs array to irq_desc struct. (s390, m68k, sparc) are not touched yet, because they don't support genirq Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/blackfin/kernel/irqchip.c | 2 +- arch/frv/kernel/irq.c | 2 +- arch/h8300/kernel/irq.c | 4 ++-- arch/ia64/kernel/irq.c | 2 +- arch/m32r/kernel/irq.c | 2 +- arch/mips/kernel/irq.c | 2 +- arch/mn10300/kernel/irq.c | 2 +- arch/parisc/kernel/irq.c | 2 +- arch/powerpc/kernel/irq.c | 2 +- arch/powerpc/platforms/cell/interrupt.c | 2 +- arch/sh/kernel/irq.c | 2 +- arch/um/kernel/irq.c | 2 +- arch/xtensa/kernel/irq.c | 2 +- 13 files changed, 14 insertions(+), 14 deletions(-) diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c index ab8209cbbad..a4e12d1b379 100644 --- a/arch/blackfin/kernel/irqchip.c +++ b/arch/blackfin/kernel/irqchip.c @@ -82,7 +82,7 @@ int show_interrupts(struct seq_file *p, void *v) goto skip; seq_printf(p, "%3d: ", i); for_each_online_cpu(j) - seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); + seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); seq_printf(p, " %8s", irq_desc[i].chip->name); seq_printf(p, " %s", action->name); for (action = action->next; action; action = action->next) diff --git a/arch/frv/kernel/irq.c b/arch/frv/kernel/irq.c index 73abae767fd..af3e824b91b 100644 --- a/arch/frv/kernel/irq.c +++ b/arch/frv/kernel/irq.c @@ -74,7 +74,7 @@ int show_interrupts(struct seq_file *p, void *v) if (action) { seq_printf(p, "%3d: ", i); for_each_present_cpu(cpu) - seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]); + seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu)); seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-"); seq_printf(p, " %s", action->name); for (action = action->next; diff --git a/arch/h8300/kernel/irq.c b/arch/h8300/kernel/irq.c index ef4f0047067..74f8dd7b34d 100644 --- a/arch/h8300/kernel/irq.c +++ b/arch/h8300/kernel/irq.c @@ -183,7 +183,7 @@ asmlinkage void do_IRQ(int irq) #if defined(CONFIG_PROC_FS) int show_interrupts(struct seq_file *p, void *v) { - int i = *(loff_t *) v, j; + int i = *(loff_t *) v; struct irqaction * action; unsigned long flags; @@ -196,7 +196,7 @@ int show_interrupts(struct seq_file *p, void *v) if (!action) goto unlock; seq_printf(p, "%3d: ",i); - seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); + seq_printf(p, "%10u ", kstat_irqs(i)); seq_printf(p, " %14s", irq_desc[i].chip->name); seq_printf(p, "-%-8s", irq_desc[i].name); seq_printf(p, " %s", action->name); diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c index a58f64ca9f0..4f596613bff 100644 --- a/arch/ia64/kernel/irq.c +++ b/arch/ia64/kernel/irq.c @@ -80,7 +80,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_printf(p, "%10u ", kstat_irqs(i)); #else for_each_online_cpu(j) { - seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); + seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); } #endif seq_printf(p, " %14s", irq_desc[i].chip->name); diff --git a/arch/m32r/kernel/irq.c b/arch/m32r/kernel/irq.c index 2aeae467009..8dfd31e87c4 100644 --- a/arch/m32r/kernel/irq.c +++ b/arch/m32r/kernel/irq.c @@ -49,7 +49,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_printf(p, "%10u ", kstat_irqs(i)); #else for_each_online_cpu(j) - seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); + seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); #endif seq_printf(p, " %14s", irq_desc[i].chip->typename); seq_printf(p, " %s", action->name); diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c index 4b4007b3083..98f336dc3cd 100644 --- a/arch/mips/kernel/irq.c +++ b/arch/mips/kernel/irq.c @@ -108,7 +108,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_printf(p, "%10u ", kstat_irqs(i)); #else for_each_online_cpu(j) - seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); + seq_printf(p, "%10u ", kstat_cpu(i, j)); #endif seq_printf(p, " %14s", irq_desc[i].chip->name); seq_printf(p, " %s", action->name); diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c index 56c64ccc9c2..50fdb5c16e0 100644 --- a/arch/mn10300/kernel/irq.c +++ b/arch/mn10300/kernel/irq.c @@ -221,7 +221,7 @@ int show_interrupts(struct seq_file *p, void *v) if (action) { seq_printf(p, "%3d: ", i); for_each_present_cpu(cpu) - seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]); + seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu)); seq_printf(p, " %14s.%u", irq_desc[i].chip->name, (GxICR(i) & GxICR_LEVEL) >> GxICR_LEVEL_SHIFT); diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index ac2c822928c..704341b0b09 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -183,7 +183,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_printf(p, "%3d: ", i); #ifdef CONFIG_SMP for_each_online_cpu(j) - seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); + seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); #else seq_printf(p, "%10u ", kstat_irqs(i)); #endif diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 23b8b5e36f9..17efb7118db 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -190,7 +190,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_printf(p, "%3d: ", i); #ifdef CONFIG_SMP for_each_online_cpu(j) - seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); + seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); #else seq_printf(p, "%10u ", kstat_irqs(i)); #endif /* CONFIG_SMP */ diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 28c04dab263..1f0d774ad92 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -254,7 +254,7 @@ static void handle_iic_irq(unsigned int irq, struct irq_desc *desc) goto out_eoi; } - kstat_cpu(cpu).irqs[irq]++; + kstat_incr_irqs_this_cpu(irq, desc); /* Mark the IRQ currently in progress.*/ desc->status |= IRQ_INPROGRESS; diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index 64b7690c664..0080a1607aa 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -51,7 +51,7 @@ int show_interrupts(struct seq_file *p, void *v) goto unlock; seq_printf(p, "%3d: ",i); for_each_online_cpu(j) - seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); + seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); seq_printf(p, " %14s", irq_desc[i].chip->name); seq_printf(p, "-%-8s", irq_desc[i].name); seq_printf(p, " %s", action->name); diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index 3d7aad09b17..336b6156907 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c @@ -42,7 +42,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_printf(p, "%10u ", kstat_irqs(i)); #else for_each_online_cpu(j) - seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); + seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); #endif seq_printf(p, " %14s", irq_desc[i].chip->typename); seq_printf(p, " %s", action->name); diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c index 5fbcde59a92..f3b66fba5b8 100644 --- a/arch/xtensa/kernel/irq.c +++ b/arch/xtensa/kernel/irq.c @@ -99,7 +99,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_printf(p, "%10u ", kstat_irqs(i)); #else for_each_online_cpu(j) - seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); + seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); #endif seq_printf(p, " %14s", irq_desc[i].chip->typename); seq_printf(p, " %s", action->name); -- GitLab From d178a1eb5c034df1f74a2b67bf311afa5d6b8e95 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 11 Jan 2009 00:35:42 -0800 Subject: [PATCH 0087/4982] sparseirq: fix build with unknown irq_desc struct Ingo Molnar wrote: > > tip/kernel/fork.c: In function 'copy_signal': > tip/kernel/fork.c:825: warning: unused variable 'ret' > tip/drivers/char/random.c: In function 'get_timer_rand_state': > tip/drivers/char/random.c:584: error: dereferencing pointer to incomplete type > tip/drivers/char/random.c: In function 'set_timer_rand_state': > tip/drivers/char/random.c:594: error: dereferencing pointer to incomplete type > make[3]: *** [drivers/char/random.o] Error 1 irq_desc is defined in linux/irq.h, so include it in the genirq case. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- drivers/char/random.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/char/random.c b/drivers/char/random.c index a778918c8f4..7c43ae782b2 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -241,6 +241,10 @@ #include #include +#ifdef CONFIG_GENERIC_HARDIRQS +# include +#endif + #include #include #include -- GitLab From 7f7ace0cda64c99599c23785f8979a072e118058 Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Sat, 10 Jan 2009 21:58:08 -0800 Subject: [PATCH 0088/4982] cpumask: update irq_desc to use cpumask_var_t Impact: reduce memory usage, use new cpumask API. Replace the affinity and pending_masks with cpumask_var_t's. This adds to the significant size reduction done with the SPARSE_IRQS changes. The added functions (init_alloc_desc_masks & init_copy_desc_masks) are in the include file so they can be inlined (and optimized out for the !CONFIG_CPUMASKS_OFFSTACK case.) [Naming chosen to be consistent with the other init*irq functions, as well as the backwards arg declaration of "from, to" instead of the more common "to, from" standard.] Includes a slight change to the declaration of struct irq_desc to embed the pending_mask within ifdef(CONFIG_SMP) to be consistent with other references, and some small changes to Xen. Tested: sparse/non-sparse/cpumask_offstack/non-cpumask_offstack/nonuma/nosmp on x86_64 Signed-off-by: Mike Travis Cc: Chris Wright Cc: Jeremy Fitzhardinge Cc: KOSAKI Motohiro Cc: Venkatesh Pallipadi Cc: virtualization@lists.osdl.org Cc: xen-devel@lists.xensource.com Cc: Yinghai Lu --- arch/x86/kernel/io_apic.c | 20 +++++----- arch/x86/kernel/irq_32.c | 2 +- arch/x86/kernel/irq_64.c | 2 +- drivers/xen/events.c | 4 +- include/linux/irq.h | 81 +++++++++++++++++++++++++++++++++++++-- kernel/irq/chip.c | 5 ++- kernel/irq/handle.c | 26 +++++++------ kernel/irq/manage.c | 12 +++--- kernel/irq/migration.c | 12 +++--- kernel/irq/numa_migrate.c | 12 +++++- kernel/irq/proc.c | 4 +- 11 files changed, 135 insertions(+), 45 deletions(-) diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 1c4a1302536..1337eab60ec 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -356,7 +356,7 @@ set_extra_move_desc(struct irq_desc *desc, const struct cpumask *mask) if (!cfg->move_in_progress) { /* it means that domain is not changed */ - if (!cpumask_intersects(&desc->affinity, mask)) + if (!cpumask_intersects(desc->affinity, mask)) cfg->move_desc_pending = 1; } } @@ -579,9 +579,9 @@ set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask) if (assign_irq_vector(irq, cfg, mask)) return BAD_APICID; - cpumask_and(&desc->affinity, cfg->domain, mask); + cpumask_and(desc->affinity, cfg->domain, mask); set_extra_move_desc(desc, mask); - return cpu_mask_to_apicid_and(&desc->affinity, cpu_online_mask); + return cpu_mask_to_apicid_and(desc->affinity, cpu_online_mask); } static void @@ -2383,7 +2383,7 @@ migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask) if (cfg->move_in_progress) send_cleanup_vector(cfg); - cpumask_copy(&desc->affinity, mask); + cpumask_copy(desc->affinity, mask); } static int migrate_irq_remapped_level_desc(struct irq_desc *desc) @@ -2405,11 +2405,11 @@ static int migrate_irq_remapped_level_desc(struct irq_desc *desc) } /* everthing is clear. we have right of way */ - migrate_ioapic_irq_desc(desc, &desc->pending_mask); + migrate_ioapic_irq_desc(desc, desc->pending_mask); ret = 0; desc->status &= ~IRQ_MOVE_PENDING; - cpumask_clear(&desc->pending_mask); + cpumask_clear(desc->pending_mask); unmask: unmask_IO_APIC_irq_desc(desc); @@ -2434,7 +2434,7 @@ static void ir_irq_migration(struct work_struct *work) continue; } - desc->chip->set_affinity(irq, &desc->pending_mask); + desc->chip->set_affinity(irq, desc->pending_mask); spin_unlock_irqrestore(&desc->lock, flags); } } @@ -2448,7 +2448,7 @@ static void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc, { if (desc->status & IRQ_LEVEL) { desc->status |= IRQ_MOVE_PENDING; - cpumask_copy(&desc->pending_mask, mask); + cpumask_copy(desc->pending_mask, mask); migrate_irq_remapped_level_desc(desc); return; } @@ -2516,7 +2516,7 @@ static void irq_complete_move(struct irq_desc **descp) /* domain has not changed, but affinity did */ me = smp_processor_id(); - if (cpu_isset(me, desc->affinity)) { + if (cpumask_test_cpu(me, desc->affinity)) { *descp = desc = move_irq_desc(desc, me); /* get the new one */ cfg = desc->chip_data; @@ -4039,7 +4039,7 @@ void __init setup_ioapic_dest(void) */ if (desc->status & (IRQ_NO_BALANCING | IRQ_AFFINITY_SET)) - mask = &desc->affinity; + mask = desc->affinity; else mask = TARGET_CPUS; diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index 74b9ff7341e..e0f29be8ab0 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c @@ -248,7 +248,7 @@ void fixup_irqs(void) if (irq == 2) continue; - affinity = &desc->affinity; + affinity = desc->affinity; if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) { printk("Breaking affinity for irq %i\n", irq); affinity = cpu_all_mask; diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index 63c88e6ec02..0b21cb1ea11 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c @@ -100,7 +100,7 @@ void fixup_irqs(void) /* interrupt's are disabled at this point */ spin_lock(&desc->lock); - affinity = &desc->affinity; + affinity = desc->affinity; if (!irq_has_action(irq) || cpumask_equal(affinity, cpu_online_mask)) { spin_unlock(&desc->lock); diff --git a/drivers/xen/events.c b/drivers/xen/events.c index eb0dfdeaa94..e0767ff35d6 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -125,7 +125,7 @@ static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu) BUG_ON(irq == -1); #ifdef CONFIG_SMP - irq_to_desc(irq)->affinity = cpumask_of_cpu(cpu); + cpumask_copy(irq_to_desc(irq)->affinity, cpumask_of(cpu)); #endif __clear_bit(chn, cpu_evtchn_mask[cpu_evtchn[chn]]); @@ -142,7 +142,7 @@ static void init_evtchn_cpu_bindings(void) /* By default all event channels notify CPU#0. */ for_each_irq_desc(i, desc) { - desc->affinity = cpumask_of_cpu(0); + cpumask_copy(desc->affinity, cpumask_of(0)); } #endif diff --git a/include/linux/irq.h b/include/linux/irq.h index f899b502f18..fa27210f1df 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -182,11 +182,11 @@ struct irq_desc { unsigned int irqs_unhandled; spinlock_t lock; #ifdef CONFIG_SMP - cpumask_t affinity; + cpumask_var_t affinity; unsigned int cpu; -#endif #ifdef CONFIG_GENERIC_PENDING_IRQ - cpumask_t pending_mask; + cpumask_var_t pending_mask; +#endif #endif #ifdef CONFIG_PROC_FS struct proc_dir_entry *dir; @@ -422,4 +422,79 @@ extern int set_irq_msi(unsigned int irq, struct msi_desc *entry); #endif /* !CONFIG_S390 */ +#ifdef CONFIG_SMP +/** + * init_alloc_desc_masks - allocate cpumasks for irq_desc + * @desc: pointer to irq_desc struct + * @boot: true if need bootmem + * + * Allocates affinity and pending_mask cpumask if required. + * Returns true if successful (or not required). + * Side effect: affinity has all bits set, pending_mask has all bits clear. + */ +static inline bool init_alloc_desc_masks(struct irq_desc *desc, int node, + bool boot) +{ + if (boot) { + alloc_bootmem_cpumask_var(&desc->affinity); + cpumask_setall(desc->affinity); + +#ifdef CONFIG_GENERIC_PENDING_IRQ + alloc_bootmem_cpumask_var(&desc->pending_mask); + cpumask_clear(desc->pending_mask); +#endif + return true; + } + + if (!alloc_cpumask_var_node(&desc->affinity, GFP_ATOMIC, node)) + return false; + cpumask_setall(desc->affinity); + +#ifdef CONFIG_GENERIC_PENDING_IRQ + if (!alloc_cpumask_var_node(&desc->pending_mask, GFP_ATOMIC, node)) { + free_cpumask_var(desc->affinity); + return false; + } + cpumask_clear(desc->pending_mask); +#endif + return true; +} + +/** + * init_copy_desc_masks - copy cpumasks for irq_desc + * @old_desc: pointer to old irq_desc struct + * @new_desc: pointer to new irq_desc struct + * + * Insures affinity and pending_masks are copied to new irq_desc. + * If !CONFIG_CPUMASKS_OFFSTACK the cpumasks are embedded in the + * irq_desc struct so the copy is redundant. + */ + +static inline void init_copy_desc_masks(struct irq_desc *old_desc, + struct irq_desc *new_desc) +{ +#ifdef CONFIG_CPUMASKS_OFFSTACK + cpumask_copy(new_desc->affinity, old_desc->affinity); + +#ifdef CONFIG_GENERIC_PENDING_IRQ + cpumask_copy(new_desc->pending_mask, old_desc->pending_mask); +#endif +#endif +} + +#else /* !CONFIG_SMP */ + +static inline bool init_alloc_desc_masks(struct irq_desc *desc, int node, + bool boot) +{ + return true; +} + +static inline void init_copy_desc_masks(struct irq_desc *old_desc, + struct irq_desc *new_desc) +{ +} + +#endif /* CONFIG_SMP */ + #endif /* _LINUX_IRQ_H */ diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index f63c706d25e..c248eba98b4 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -46,7 +46,10 @@ void dynamic_irq_init(unsigned int irq) desc->irq_count = 0; desc->irqs_unhandled = 0; #ifdef CONFIG_SMP - cpumask_setall(&desc->affinity); + cpumask_setall(desc->affinity); +#ifdef CONFIG_GENERIC_PENDING_IRQ + cpumask_clear(desc->pending_mask); +#endif #endif spin_unlock_irqrestore(&desc->lock, flags); } diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index c20db0be917..b8fa1354f01 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -64,9 +64,6 @@ static struct irq_desc irq_desc_init = { .handle_irq = handle_bad_irq, .depth = 1, .lock = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock), -#ifdef CONFIG_SMP - .affinity = CPU_MASK_ALL -#endif }; void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr) @@ -88,6 +85,8 @@ void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr) static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu) { + int node = cpu_to_node(cpu); + memcpy(desc, &irq_desc_init, sizeof(struct irq_desc)); spin_lock_init(&desc->lock); @@ -101,6 +100,10 @@ static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu) printk(KERN_ERR "can not alloc kstat_irqs\n"); BUG_ON(1); } + if (!init_alloc_desc_masks(desc, node, false)) { + printk(KERN_ERR "can not alloc irq_desc cpumasks\n"); + BUG_ON(1); + } arch_init_chip_data(desc, cpu); } @@ -119,9 +122,6 @@ static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_sm .handle_irq = handle_bad_irq, .depth = 1, .lock = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock), -#ifdef CONFIG_SMP - .affinity = CPU_MASK_ALL -#endif } }; @@ -141,7 +141,7 @@ int __init early_irq_init(void) desc[i].irq = i; desc[i].kstat_irqs = kstat_irqs_legacy[i]; lockdep_set_class(&desc[i].lock, &irq_desc_lock_class); - + init_alloc_desc_masks(&desc[i], 0, true); irq_desc_ptrs[i] = desc + i; } @@ -188,6 +188,10 @@ struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu) printk(KERN_ERR "can not alloc irq_desc\n"); BUG_ON(1); } + if (!init_alloc_desc_masks(desc, node, false)) { + printk(KERN_ERR "can not alloc irq_desc cpumasks\n"); + BUG_ON(1); + } init_one_irq_desc(irq, desc, cpu); irq_desc_ptrs[irq] = desc; @@ -207,9 +211,6 @@ struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { .handle_irq = handle_bad_irq, .depth = 1, .lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock), -#ifdef CONFIG_SMP - .affinity = CPU_MASK_ALL -#endif } }; @@ -222,9 +223,10 @@ int __init early_irq_init(void) desc = irq_desc; count = ARRAY_SIZE(irq_desc); - for (i = 0; i < count; i++) + for (i = 0; i < count; i++) { desc[i].irq = i; - + init_alloc_desc_masks(&desc[i], 0, true); + } return arch_early_irq_init(); } diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index cd0cd8dcb34..b98739af455 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -98,14 +98,14 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask) #ifdef CONFIG_GENERIC_PENDING_IRQ if (desc->status & IRQ_MOVE_PCNTXT || desc->status & IRQ_DISABLED) { - cpumask_copy(&desc->affinity, cpumask); + cpumask_copy(desc->affinity, cpumask); desc->chip->set_affinity(irq, cpumask); } else { desc->status |= IRQ_MOVE_PENDING; - cpumask_copy(&desc->pending_mask, cpumask); + cpumask_copy(desc->pending_mask, cpumask); } #else - cpumask_copy(&desc->affinity, cpumask); + cpumask_copy(desc->affinity, cpumask); desc->chip->set_affinity(irq, cpumask); #endif desc->status |= IRQ_AFFINITY_SET; @@ -127,16 +127,16 @@ int do_irq_select_affinity(unsigned int irq, struct irq_desc *desc) * one of the targets is online. */ if (desc->status & (IRQ_AFFINITY_SET | IRQ_NO_BALANCING)) { - if (cpumask_any_and(&desc->affinity, cpu_online_mask) + if (cpumask_any_and(desc->affinity, cpu_online_mask) < nr_cpu_ids) goto set_affinity; else desc->status &= ~IRQ_AFFINITY_SET; } - cpumask_and(&desc->affinity, cpu_online_mask, irq_default_affinity); + cpumask_and(desc->affinity, cpu_online_mask, irq_default_affinity); set_affinity: - desc->chip->set_affinity(irq, &desc->affinity); + desc->chip->set_affinity(irq, desc->affinity); return 0; } diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c index bd72329e630..e05ad9be43b 100644 --- a/kernel/irq/migration.c +++ b/kernel/irq/migration.c @@ -18,7 +18,7 @@ void move_masked_irq(int irq) desc->status &= ~IRQ_MOVE_PENDING; - if (unlikely(cpumask_empty(&desc->pending_mask))) + if (unlikely(cpumask_empty(desc->pending_mask))) return; if (!desc->chip->set_affinity) @@ -38,13 +38,13 @@ void move_masked_irq(int irq) * For correct operation this depends on the caller * masking the irqs. */ - if (likely(cpumask_any_and(&desc->pending_mask, cpu_online_mask) + if (likely(cpumask_any_and(desc->pending_mask, cpu_online_mask) < nr_cpu_ids)) { - cpumask_and(&desc->affinity, - &desc->pending_mask, cpu_online_mask); - desc->chip->set_affinity(irq, &desc->affinity); + cpumask_and(desc->affinity, + desc->pending_mask, cpu_online_mask); + desc->chip->set_affinity(irq, desc->affinity); } - cpumask_clear(&desc->pending_mask); + cpumask_clear(desc->pending_mask); } void move_native_irq(int irq) diff --git a/kernel/irq/numa_migrate.c b/kernel/irq/numa_migrate.c index ecf765c6a77..f001a4ea641 100644 --- a/kernel/irq/numa_migrate.c +++ b/kernel/irq/numa_migrate.c @@ -46,6 +46,7 @@ static void init_copy_one_irq_desc(int irq, struct irq_desc *old_desc, desc->cpu = cpu; lockdep_set_class(&desc->lock, &irq_desc_lock_class); init_copy_kstat_irqs(old_desc, desc, cpu, nr_cpu_ids); + init_copy_desc_masks(old_desc, desc); arch_init_copy_chip_data(old_desc, desc, cpu); } @@ -76,11 +77,20 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc, node = cpu_to_node(cpu); desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node); if (!desc) { - printk(KERN_ERR "irq %d: can not get new irq_desc for migration.\n", irq); + printk(KERN_ERR "irq %d: can not get new irq_desc " + "for migration.\n", irq); /* still use old one */ desc = old_desc; goto out_unlock; } + if (!init_alloc_desc_masks(desc, node, false)) { + printk(KERN_ERR "irq %d: can not get new irq_desc cpumask " + "for migration.\n", irq); + /* still use old one */ + kfree(desc); + desc = old_desc; + goto out_unlock; + } init_copy_one_irq_desc(irq, old_desc, desc, cpu); irq_desc_ptrs[irq] = desc; diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index aae3f742bce..692363dd591 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c @@ -20,11 +20,11 @@ static struct proc_dir_entry *root_irq_dir; static int irq_affinity_proc_show(struct seq_file *m, void *v) { struct irq_desc *desc = irq_to_desc((long)m->private); - const struct cpumask *mask = &desc->affinity; + const struct cpumask *mask = desc->affinity; #ifdef CONFIG_GENERIC_PENDING_IRQ if (desc->status & IRQ_MOVE_PENDING) - mask = &desc->pending_mask; + mask = desc->pending_mask; #endif seq_cpumask(m, mask); seq_putc(m, '\n'); -- GitLab From fbd59a8d1f7cf325fdb6828659f1fb76631e87b3 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sat, 10 Jan 2009 21:58:08 -0800 Subject: [PATCH 0089/4982] cpumask: Use topology_core_cpumask()/topology_thread_cpumask() Impact: reduce stack usage, use new cpumask API. This actually uses topology_core_cpumask() and topology_thread_cpumask(), removing the only users of topology_core_siblings() and topology_thread_siblings() Signed-off-by: Rusty Russell Signed-off-by: Mike Travis Cc: linux-net-drivers@solarflare.com --- Documentation/cputopology.txt | 6 +++--- drivers/base/topology.c | 33 ++++++++++++++++----------------- drivers/net/sfc/efx.c | 4 ++-- include/linux/topology.h | 6 ++++++ 4 files changed, 27 insertions(+), 22 deletions(-) diff --git a/Documentation/cputopology.txt b/Documentation/cputopology.txt index 45932ec21ce..b41f3e58aef 100644 --- a/Documentation/cputopology.txt +++ b/Documentation/cputopology.txt @@ -18,11 +18,11 @@ For an architecture to support this feature, it must define some of these macros in include/asm-XXX/topology.h: #define topology_physical_package_id(cpu) #define topology_core_id(cpu) -#define topology_thread_siblings(cpu) -#define topology_core_siblings(cpu) +#define topology_thread_cpumask(cpu) +#define topology_core_cpumask(cpu) The type of **_id is int. -The type of siblings is cpumask_t. +The type of siblings is (const) struct cpumask *. To be consistent on all architectures, include/linux/topology.h provides default definitions for any of the above macros that are diff --git a/drivers/base/topology.c b/drivers/base/topology.c index a778fb52b11..bf6b13206d0 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c @@ -31,7 +31,10 @@ #include #include -#define define_one_ro(_name) \ +#define define_one_ro_named(_name, _func) \ +static SYSDEV_ATTR(_name, 0444, _func, NULL) + +#define define_one_ro(_name) \ static SYSDEV_ATTR(_name, 0444, show_##_name, NULL) #define define_id_show_func(name) \ @@ -42,8 +45,8 @@ static ssize_t show_##name(struct sys_device *dev, \ return sprintf(buf, "%d\n", topology_##name(cpu)); \ } -#if defined(topology_thread_siblings) || defined(topology_core_siblings) -static ssize_t show_cpumap(int type, cpumask_t *mask, char *buf) +#if defined(topology_thread_cpumask) || defined(topology_core_cpumask) +static ssize_t show_cpumap(int type, const struct cpumask *mask, char *buf) { ptrdiff_t len = PTR_ALIGN(buf + PAGE_SIZE - 1, PAGE_SIZE) - buf; int n = 0; @@ -65,7 +68,7 @@ static ssize_t show_##name(struct sys_device *dev, \ struct sysdev_attribute *attr, char *buf) \ { \ unsigned int cpu = dev->id; \ - return show_cpumap(0, &(topology_##name(cpu)), buf); \ + return show_cpumap(0, topology_##name(cpu), buf); \ } #define define_siblings_show_list(name) \ @@ -74,7 +77,7 @@ static ssize_t show_##name##_list(struct sys_device *dev, \ char *buf) \ { \ unsigned int cpu = dev->id; \ - return show_cpumap(1, &(topology_##name(cpu)), buf); \ + return show_cpumap(1, topology_##name(cpu), buf); \ } #else @@ -82,9 +85,7 @@ static ssize_t show_##name##_list(struct sys_device *dev, \ static ssize_t show_##name(struct sys_device *dev, \ struct sysdev_attribute *attr, char *buf) \ { \ - unsigned int cpu = dev->id; \ - cpumask_t mask = topology_##name(cpu); \ - return show_cpumap(0, &mask, buf); \ + return show_cpumap(0, topology_##name(dev->id), buf); \ } #define define_siblings_show_list(name) \ @@ -92,9 +93,7 @@ static ssize_t show_##name##_list(struct sys_device *dev, \ struct sysdev_attribute *attr, \ char *buf) \ { \ - unsigned int cpu = dev->id; \ - cpumask_t mask = topology_##name(cpu); \ - return show_cpumap(1, &mask, buf); \ + return show_cpumap(1, topology_##name(dev->id), buf); \ } #endif @@ -107,13 +106,13 @@ define_one_ro(physical_package_id); define_id_show_func(core_id); define_one_ro(core_id); -define_siblings_show_func(thread_siblings); -define_one_ro(thread_siblings); -define_one_ro(thread_siblings_list); +define_siblings_show_func(thread_cpumask); +define_one_ro_named(thread_siblings, show_thread_cpumask); +define_one_ro_named(thread_siblings_list, show_thread_cpumask_list); -define_siblings_show_func(core_siblings); -define_one_ro(core_siblings); -define_one_ro(core_siblings_list); +define_siblings_show_func(core_cpumask); +define_one_ro_named(core_siblings, show_core_cpumask); +define_one_ro_named(core_siblings_list, show_core_cpumask_list); static struct attribute *default_attrs[] = { &attr_physical_package_id.attr, diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 7673fd92eaf..f2e56ceee0e 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -863,8 +863,8 @@ static int efx_wanted_rx_queues(void) for_each_online_cpu(cpu) { if (!cpu_isset(cpu, core_mask)) { ++count; - cpus_or(core_mask, core_mask, - topology_core_siblings(cpu)); + cpumask_or(&core_mask, &core_mask, + topology_core_cpumask(cpu)); } } diff --git a/include/linux/topology.h b/include/linux/topology.h index e632d29f054..a16b9e06f2e 100644 --- a/include/linux/topology.h +++ b/include/linux/topology.h @@ -193,5 +193,11 @@ int arch_update_cpu_topology(void); #ifndef topology_core_siblings #define topology_core_siblings(cpu) cpumask_of_cpu(cpu) #endif +#ifndef topology_thread_cpumask +#define topology_thread_cpumask(cpu) cpumask_of(cpu) +#endif +#ifndef topology_core_cpumask +#define topology_core_cpumask(cpu) cpumask_of(cpu) +#endif #endif /* _LINUX_TOPOLOGY_H */ -- GitLab From f7df8ed164996cd2c6aca9674388be6ef78d8b37 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sat, 10 Jan 2009 21:58:09 -0800 Subject: [PATCH 0090/4982] cpumask: convert misc driver functions Impact: use new cpumask API. Convert misc driver functions to use struct cpumask. To Do: - Convert iucv_buffer_cpumask to cpumask_var_t. Signed-off-by: Rusty Russell Signed-off-by: Mike Travis Acked-by: Dean Nelson Cc: Robert Richter Cc: oprofile-list@lists.sf.net Cc: Jeremy Fitzhardinge Cc: Chris Wright Cc: virtualization@lists.osdl.org Cc: xen-devel@lists.xensource.com Cc: Ursula Braun Cc: linux390@de.ibm.com Cc: linux-s390@vger.kernel.org --- drivers/base/cpu.c | 2 +- drivers/misc/sgi-xp/xpc_main.c | 2 +- drivers/oprofile/buffer_sync.c | 22 ++++++++++++++++++---- drivers/oprofile/buffer_sync.h | 4 ++++ drivers/oprofile/oprof.c | 9 ++++++++- drivers/xen/manage.c | 2 +- 6 files changed, 33 insertions(+), 8 deletions(-) diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 719ee5c1c8d..5b257a57bc5 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -107,7 +107,7 @@ static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL); /* * Print cpu online, possible, present, and system maps */ -static ssize_t print_cpus_map(char *buf, cpumask_t *map) +static ssize_t print_cpus_map(char *buf, const struct cpumask *map) { int n = cpulist_scnprintf(buf, PAGE_SIZE-2, map); diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c index 89218f7cfaa..6576170de96 100644 --- a/drivers/misc/sgi-xp/xpc_main.c +++ b/drivers/misc/sgi-xp/xpc_main.c @@ -318,7 +318,7 @@ xpc_hb_checker(void *ignore) /* this thread was marked active by xpc_hb_init() */ - set_cpus_allowed_ptr(current, &cpumask_of_cpu(XPC_HB_CHECK_CPU)); + set_cpus_allowed_ptr(current, cpumask_of(XPC_HB_CHECK_CPU)); /* set our heartbeating to other partitions into motion */ xpc_hb_check_timeout = jiffies + (xpc_hb_check_interval * HZ); diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index 9da5a4b8113..c3ea5fa7d05 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -38,7 +38,7 @@ static LIST_HEAD(dying_tasks); static LIST_HEAD(dead_tasks); -static cpumask_t marked_cpus = CPU_MASK_NONE; +static cpumask_var_t marked_cpus; static DEFINE_SPINLOCK(task_mortuary); static void process_task_mortuary(void); @@ -456,10 +456,10 @@ static void mark_done(int cpu) { int i; - cpu_set(cpu, marked_cpus); + cpumask_set_cpu(cpu, marked_cpus); for_each_online_cpu(i) { - if (!cpu_isset(i, marked_cpus)) + if (!cpumask_test_cpu(i, marked_cpus)) return; } @@ -468,7 +468,7 @@ static void mark_done(int cpu) */ process_task_mortuary(); - cpus_clear(marked_cpus); + cpumask_clear(marked_cpus); } @@ -565,6 +565,20 @@ void sync_buffer(int cpu) mutex_unlock(&buffer_mutex); } +int __init buffer_sync_init(void) +{ + if (!alloc_cpumask_var(&marked_cpus, GFP_KERNEL)) + return -ENOMEM; + + cpumask_clear(marked_cpus); + return 0; +} + +void __exit buffer_sync_cleanup(void) +{ + free_cpumask_var(marked_cpus); +} + /* The function can be used to add a buffer worth of data directly to * the kernel buffer. The buffer is assumed to be a circular buffer. * Take the entries from index start and end at index end, wrapping diff --git a/drivers/oprofile/buffer_sync.h b/drivers/oprofile/buffer_sync.h index 3110732c183..0ebf5db6267 100644 --- a/drivers/oprofile/buffer_sync.h +++ b/drivers/oprofile/buffer_sync.h @@ -19,4 +19,8 @@ void sync_stop(void); /* sync the given CPU's buffer */ void sync_buffer(int cpu); +/* initialize/destroy the buffer system. */ +int buffer_sync_init(void); +void buffer_sync_cleanup(void); + #endif /* OPROFILE_BUFFER_SYNC_H */ diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c index 3cffce90f82..ced39f60229 100644 --- a/drivers/oprofile/oprof.c +++ b/drivers/oprofile/oprof.c @@ -183,6 +183,10 @@ static int __init oprofile_init(void) { int err; + err = buffer_sync_init(); + if (err) + return err; + err = oprofile_arch_init(&oprofile_ops); if (err < 0 || timer) { @@ -191,8 +195,10 @@ static int __init oprofile_init(void) } err = oprofilefs_register(); - if (err) + if (err) { oprofile_arch_exit(); + buffer_sync_cleanup(); + } return err; } @@ -202,6 +208,7 @@ static void __exit oprofile_exit(void) { oprofilefs_unregister(); oprofile_arch_exit(); + buffer_sync_cleanup(); } diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 9b91617b958..e7e83b65c18 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c @@ -100,7 +100,7 @@ static void do_suspend(void) /* XXX use normal device tree? */ xenbus_suspend(); - err = stop_machine(xen_suspend, &cancelled, &cpumask_of_cpu(0)); + err = stop_machine(xen_suspend, &cancelled, cpumask_of(0)); if (err) { printk(KERN_ERR "failed to start xen_suspend: %d\n", err); goto out; -- GitLab From 2f8975fbcf07103afab0bbaea5f5b1a9967ffb86 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sat, 10 Jan 2009 21:58:09 -0800 Subject: [PATCH 0091/4982] cpumask: convert drivers/net/sfc Impact: reduce stack usage, use new cpumask API. Remove a cpumask from the stack. Ben Hutchings indicated that printing a warning and returning 1 was acceptable for the corner case where allocation fails. Signed-off-by: Rusty Russell Signed-off-by: Mike Travis Cc: Ben Hutchings Cc: linux-net-drivers@solarflare.com --- drivers/net/sfc/efx.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index f2e56ceee0e..101c00a7bb7 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -854,20 +854,27 @@ static void efx_fini_io(struct efx_nic *efx) * interrupts across them. */ static int efx_wanted_rx_queues(void) { - cpumask_t core_mask; + cpumask_var_t core_mask; int count; int cpu; - cpus_clear(core_mask); + if (!alloc_cpumask_var(&core_mask, GFP_KERNEL)) { + printk(KERN_WARNING + "efx.c: allocation failure, irq balancing hobbled\n"); + return 1; + } + + cpumask_clear(core_mask); count = 0; for_each_online_cpu(cpu) { - if (!cpu_isset(cpu, core_mask)) { + if (!cpumask_test_cpu(cpu, core_mask)) { ++count; - cpumask_or(&core_mask, &core_mask, + cpumask_or(core_mask, core_mask, topology_core_cpumask(cpu)); } } + free_cpumask_var(core_mask); return count; } -- GitLab From 651f8118cf0a5724f23fe1de4a3d9d36b2e01c2e Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sat, 10 Jan 2009 21:58:09 -0800 Subject: [PATCH 0092/4982] cpumask: convert other misc kernel functions Impact: use new cpumask API. Convert other misc kernel functions to use struct cpumask. Signed-off-by: Rusty Russell Signed-off-by: Mike Travis --- lib/smp_processor_id.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c index 0f8fc22ed10..4689cb073da 100644 --- a/lib/smp_processor_id.c +++ b/lib/smp_processor_id.c @@ -22,7 +22,7 @@ notrace unsigned int debug_smp_processor_id(void) * Kernel threads bound to a single CPU can safely use * smp_processor_id(): */ - if (cpus_equal(current->cpus_allowed, cpumask_of_cpu(this_cpu))) + if (cpumask_equal(¤t->cpus_allowed, cpumask_of(this_cpu))) goto out; /* -- GitLab From 802bf931f2688ad125b73db597ce63cc842fb27a Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Sat, 10 Jan 2009 21:58:09 -0800 Subject: [PATCH 0093/4982] cpumask: fix bug in use cpumask_var_t in irq_desc Impact: fix bug where new irq_desc uses old cpumask pointers which are freed. As Yinghai pointed out, init_copy_one_irq_desc() copies the old desc to the new desc overwriting the cpumask pointers. Since the old_desc and the cpumask pointers are freed, then memory corruption will occur if these old pointers are used. Move the allocation of these pointers to after the copy. Signed-off-by: Mike Travis Cc: Yinghai Lu --- include/linux/irq.h | 9 +++++++-- kernel/irq/handle.c | 8 +------- kernel/irq/numa_migrate.c | 13 ++++++++----- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/include/linux/irq.h b/include/linux/irq.h index fa27210f1df..27a67536511 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -426,15 +426,18 @@ extern int set_irq_msi(unsigned int irq, struct msi_desc *entry); /** * init_alloc_desc_masks - allocate cpumasks for irq_desc * @desc: pointer to irq_desc struct + * @cpu: cpu which will be handling the cpumasks * @boot: true if need bootmem * * Allocates affinity and pending_mask cpumask if required. * Returns true if successful (or not required). * Side effect: affinity has all bits set, pending_mask has all bits clear. */ -static inline bool init_alloc_desc_masks(struct irq_desc *desc, int node, +static inline bool init_alloc_desc_masks(struct irq_desc *desc, int cpu, bool boot) { + int node; + if (boot) { alloc_bootmem_cpumask_var(&desc->affinity); cpumask_setall(desc->affinity); @@ -446,6 +449,8 @@ static inline bool init_alloc_desc_masks(struct irq_desc *desc, int node, return true; } + node = cpu_to_node(cpu); + if (!alloc_cpumask_var_node(&desc->affinity, GFP_ATOMIC, node)) return false; cpumask_setall(desc->affinity); @@ -484,7 +489,7 @@ static inline void init_copy_desc_masks(struct irq_desc *old_desc, #else /* !CONFIG_SMP */ -static inline bool init_alloc_desc_masks(struct irq_desc *desc, int node, +static inline bool init_alloc_desc_masks(struct irq_desc *desc, int cpu, bool boot) { return true; diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index b8fa1354f01..f01c0a30cb4 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -85,8 +85,6 @@ void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr) static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu) { - int node = cpu_to_node(cpu); - memcpy(desc, &irq_desc_init, sizeof(struct irq_desc)); spin_lock_init(&desc->lock); @@ -100,7 +98,7 @@ static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu) printk(KERN_ERR "can not alloc kstat_irqs\n"); BUG_ON(1); } - if (!init_alloc_desc_masks(desc, node, false)) { + if (!init_alloc_desc_masks(desc, cpu, false)) { printk(KERN_ERR "can not alloc irq_desc cpumasks\n"); BUG_ON(1); } @@ -188,10 +186,6 @@ struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu) printk(KERN_ERR "can not alloc irq_desc\n"); BUG_ON(1); } - if (!init_alloc_desc_masks(desc, node, false)) { - printk(KERN_ERR "can not alloc irq_desc cpumasks\n"); - BUG_ON(1); - } init_one_irq_desc(irq, desc, cpu); irq_desc_ptrs[irq] = desc; diff --git a/kernel/irq/numa_migrate.c b/kernel/irq/numa_migrate.c index f001a4ea641..666260e4c06 100644 --- a/kernel/irq/numa_migrate.c +++ b/kernel/irq/numa_migrate.c @@ -38,16 +38,22 @@ static void free_kstat_irqs(struct irq_desc *old_desc, struct irq_desc *desc) old_desc->kstat_irqs = NULL; } -static void init_copy_one_irq_desc(int irq, struct irq_desc *old_desc, +static bool init_copy_one_irq_desc(int irq, struct irq_desc *old_desc, struct irq_desc *desc, int cpu) { memcpy(desc, old_desc, sizeof(struct irq_desc)); + if (!init_alloc_desc_masks(desc, cpu, false)) { + printk(KERN_ERR "irq %d: can not get new irq_desc cpumask " + "for migration.\n", irq); + return false; + } spin_lock_init(&desc->lock); desc->cpu = cpu; lockdep_set_class(&desc->lock, &irq_desc_lock_class); init_copy_kstat_irqs(old_desc, desc, cpu, nr_cpu_ids); init_copy_desc_masks(old_desc, desc); arch_init_copy_chip_data(old_desc, desc, cpu); + return true; } static void free_one_irq_desc(struct irq_desc *old_desc, struct irq_desc *desc) @@ -83,15 +89,12 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc, desc = old_desc; goto out_unlock; } - if (!init_alloc_desc_masks(desc, node, false)) { - printk(KERN_ERR "irq %d: can not get new irq_desc cpumask " - "for migration.\n", irq); + if (!init_copy_one_irq_desc(irq, old_desc, desc, cpu)) { /* still use old one */ kfree(desc); desc = old_desc; goto out_unlock; } - init_copy_one_irq_desc(irq, old_desc, desc, cpu); irq_desc_ptrs[irq] = desc; -- GitLab From 4595f9620cda8a1e973588e743cf5f8436dd20c6 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sat, 10 Jan 2009 21:58:09 -0800 Subject: [PATCH 0094/4982] x86: change flush_tlb_others to take a const struct cpumask Impact: reduce stack usage, use new cpumask API. This is made a little more tricky by uv_flush_tlb_others which actually alters its argument, for an IPI to be sent to the remaining cpus in the mask. I solve this by allocating a cpumask_var_t for this case and falling back to IPI should this fail. To eliminate temporaries in the caller, all flush_tlb_others implementations now do the this-cpu-elimination step themselves. Note also the curious "cpus_or(f->flush_cpumask, cpumask, f->flush_cpumask)" which has been there since pre-git and yet f->flush_cpumask is always zero at this point. Signed-off-by: Rusty Russell Signed-off-by: Mike Travis --- arch/x86/include/asm/paravirt.h | 8 ++-- arch/x86/include/asm/tlbflush.h | 8 ++-- arch/x86/include/asm/uv/uv_bau.h | 3 +- arch/x86/kernel/tlb_32.c | 67 ++++++++++++++------------------ arch/x86/kernel/tlb_64.c | 61 ++++++++++++++++------------- arch/x86/kernel/tlb_uv.c | 16 ++++---- arch/x86/xen/enlighten.c | 31 ++++++--------- 7 files changed, 93 insertions(+), 101 deletions(-) diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index ba3e2ff6aed..c26c6bf4da0 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -244,7 +244,8 @@ struct pv_mmu_ops { void (*flush_tlb_user)(void); void (*flush_tlb_kernel)(void); void (*flush_tlb_single)(unsigned long addr); - void (*flush_tlb_others)(const cpumask_t *cpus, struct mm_struct *mm, + void (*flush_tlb_others)(const struct cpumask *cpus, + struct mm_struct *mm, unsigned long va); /* Hooks for allocating and freeing a pagetable top-level */ @@ -984,10 +985,11 @@ static inline void __flush_tlb_single(unsigned long addr) PVOP_VCALL1(pv_mmu_ops.flush_tlb_single, addr); } -static inline void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm, +static inline void flush_tlb_others(const struct cpumask *cpumask, + struct mm_struct *mm, unsigned long va) { - PVOP_VCALL3(pv_mmu_ops.flush_tlb_others, &cpumask, mm, va); + PVOP_VCALL3(pv_mmu_ops.flush_tlb_others, cpumask, mm, va); } static inline int paravirt_pgd_alloc(struct mm_struct *mm) diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index 0e7bbb54911..f4e1b550ce6 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -113,7 +113,7 @@ static inline void flush_tlb_range(struct vm_area_struct *vma, __flush_tlb(); } -static inline void native_flush_tlb_others(const cpumask_t *cpumask, +static inline void native_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm, unsigned long va) { @@ -142,8 +142,8 @@ static inline void flush_tlb_range(struct vm_area_struct *vma, flush_tlb_mm(vma->vm_mm); } -void native_flush_tlb_others(const cpumask_t *cpumask, struct mm_struct *mm, - unsigned long va); +void native_flush_tlb_others(const struct cpumask *cpumask, + struct mm_struct *mm, unsigned long va); #define TLBSTATE_OK 1 #define TLBSTATE_LAZY 2 @@ -166,7 +166,7 @@ static inline void reset_lazy_tlbstate(void) #endif /* SMP */ #ifndef CONFIG_PARAVIRT -#define flush_tlb_others(mask, mm, va) native_flush_tlb_others(&mask, mm, va) +#define flush_tlb_others(mask, mm, va) native_flush_tlb_others(mask, mm, va) #endif static inline void flush_tlb_kernel_range(unsigned long start, diff --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h index 50423c7b56b..74e6393bfdd 100644 --- a/arch/x86/include/asm/uv/uv_bau.h +++ b/arch/x86/include/asm/uv/uv_bau.h @@ -325,7 +325,8 @@ static inline void bau_cpubits_clear(struct bau_local_cpumask *dstp, int nbits) #define cpubit_isset(cpu, bau_local_cpumask) \ test_bit((cpu), (bau_local_cpumask).bits) -extern int uv_flush_tlb_others(cpumask_t *, struct mm_struct *, unsigned long); +extern int uv_flush_tlb_others(struct cpumask *, + struct mm_struct *, unsigned long); extern void uv_bau_message_intr1(void); extern void uv_bau_timeout_intr1(void); diff --git a/arch/x86/kernel/tlb_32.c b/arch/x86/kernel/tlb_32.c index ce505464224..ec53818f4e3 100644 --- a/arch/x86/kernel/tlb_32.c +++ b/arch/x86/kernel/tlb_32.c @@ -20,7 +20,7 @@ DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) * Optimizations Manfred Spraul */ -static cpumask_t flush_cpumask; +static cpumask_var_t flush_cpumask; static struct mm_struct *flush_mm; static unsigned long flush_va; static DEFINE_SPINLOCK(tlbstate_lock); @@ -92,7 +92,7 @@ void smp_invalidate_interrupt(struct pt_regs *regs) cpu = get_cpu(); - if (!cpu_isset(cpu, flush_cpumask)) + if (!cpumask_test_cpu(cpu, flush_cpumask)) goto out; /* * This was a BUG() but until someone can quote me the @@ -114,35 +114,22 @@ void smp_invalidate_interrupt(struct pt_regs *regs) } ack_APIC_irq(); smp_mb__before_clear_bit(); - cpu_clear(cpu, flush_cpumask); + cpumask_clear_cpu(cpu, flush_cpumask); smp_mb__after_clear_bit(); out: put_cpu_no_resched(); inc_irq_stat(irq_tlb_count); } -void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm, - unsigned long va) +void native_flush_tlb_others(const struct cpumask *cpumask, + struct mm_struct *mm, unsigned long va) { - cpumask_t cpumask = *cpumaskp; - /* - * A couple of (to be removed) sanity checks: - * - * - current CPU must not be in mask * - mask must exist :) */ - BUG_ON(cpus_empty(cpumask)); - BUG_ON(cpu_isset(smp_processor_id(), cpumask)); + BUG_ON(cpumask_empty(cpumask)); BUG_ON(!mm); -#ifdef CONFIG_HOTPLUG_CPU - /* If a CPU which we ran on has gone down, OK. */ - cpus_and(cpumask, cpumask, cpu_online_map); - if (unlikely(cpus_empty(cpumask))) - return; -#endif - /* * i'm not happy about this global shared spinlock in the * MM hot path, but we'll see how contended it is. @@ -150,9 +137,17 @@ void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm, */ spin_lock(&tlbstate_lock); + cpumask_andnot(flush_cpumask, cpumask, cpumask_of(smp_processor_id())); +#ifdef CONFIG_HOTPLUG_CPU + /* If a CPU which we ran on has gone down, OK. */ + cpumask_and(flush_cpumask, flush_cpumask, cpu_online_mask); + if (unlikely(cpumask_empty(flush_cpumask))) { + spin_unlock(&tlbstate_lock); + return; + } +#endif flush_mm = mm; flush_va = va; - cpus_or(flush_cpumask, cpumask, flush_cpumask); /* * Make the above memory operations globally visible before @@ -163,9 +158,9 @@ void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm, * We have to send the IPI only to * CPUs affected. */ - send_IPI_mask(&cpumask, INVALIDATE_TLB_VECTOR); + send_IPI_mask(flush_cpumask, INVALIDATE_TLB_VECTOR); - while (!cpus_empty(flush_cpumask)) + while (!cpumask_empty(flush_cpumask)) /* nothing. lockup detection does not belong here */ cpu_relax(); @@ -177,25 +172,19 @@ void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm, void flush_tlb_current_task(void) { struct mm_struct *mm = current->mm; - cpumask_t cpu_mask; preempt_disable(); - cpu_mask = mm->cpu_vm_mask; - cpu_clear(smp_processor_id(), cpu_mask); local_flush_tlb(); - if (!cpus_empty(cpu_mask)) - flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL); + if (cpumask_any_but(&mm->cpu_vm_mask, smp_processor_id()) < nr_cpu_ids) + flush_tlb_others(&mm->cpu_vm_mask, mm, TLB_FLUSH_ALL); preempt_enable(); } void flush_tlb_mm(struct mm_struct *mm) { - cpumask_t cpu_mask; preempt_disable(); - cpu_mask = mm->cpu_vm_mask; - cpu_clear(smp_processor_id(), cpu_mask); if (current->active_mm == mm) { if (current->mm) @@ -203,8 +192,8 @@ void flush_tlb_mm(struct mm_struct *mm) else leave_mm(smp_processor_id()); } - if (!cpus_empty(cpu_mask)) - flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL); + if (cpumask_any_but(&mm->cpu_vm_mask, smp_processor_id()) < nr_cpu_ids) + flush_tlb_others(&mm->cpu_vm_mask, mm, TLB_FLUSH_ALL); preempt_enable(); } @@ -212,11 +201,8 @@ void flush_tlb_mm(struct mm_struct *mm) void flush_tlb_page(struct vm_area_struct *vma, unsigned long va) { struct mm_struct *mm = vma->vm_mm; - cpumask_t cpu_mask; preempt_disable(); - cpu_mask = mm->cpu_vm_mask; - cpu_clear(smp_processor_id(), cpu_mask); if (current->active_mm == mm) { if (current->mm) @@ -225,9 +211,8 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long va) leave_mm(smp_processor_id()); } - if (!cpus_empty(cpu_mask)) - flush_tlb_others(cpu_mask, mm, va); - + if (cpumask_any_but(&mm->cpu_vm_mask, smp_processor_id()) < nr_cpu_ids) + flush_tlb_others(&mm->cpu_vm_mask, mm, va); preempt_enable(); } EXPORT_SYMBOL(flush_tlb_page); @@ -254,3 +239,9 @@ void reset_lazy_tlbstate(void) per_cpu(cpu_tlbstate, cpu).active_mm = &init_mm; } +static int init_flush_cpumask(void) +{ + alloc_cpumask_var(&flush_cpumask, GFP_KERNEL); + return 0; +} +early_initcall(init_flush_cpumask); diff --git a/arch/x86/kernel/tlb_64.c b/arch/x86/kernel/tlb_64.c index f8be6f1d2e4..38836aef51b 100644 --- a/arch/x86/kernel/tlb_64.c +++ b/arch/x86/kernel/tlb_64.c @@ -43,10 +43,10 @@ union smp_flush_state { struct { - cpumask_t flush_cpumask; struct mm_struct *flush_mm; unsigned long flush_va; spinlock_t tlbstate_lock; + DECLARE_BITMAP(flush_cpumask, NR_CPUS); }; char pad[SMP_CACHE_BYTES]; } ____cacheline_aligned; @@ -131,7 +131,7 @@ asmlinkage void smp_invalidate_interrupt(struct pt_regs *regs) sender = ~regs->orig_ax - INVALIDATE_TLB_VECTOR_START; f = &per_cpu(flush_state, sender); - if (!cpu_isset(cpu, f->flush_cpumask)) + if (!cpumask_test_cpu(cpu, to_cpumask(f->flush_cpumask))) goto out; /* * This was a BUG() but until someone can quote me the @@ -153,19 +153,15 @@ asmlinkage void smp_invalidate_interrupt(struct pt_regs *regs) } out: ack_APIC_irq(); - cpu_clear(cpu, f->flush_cpumask); + cpumask_clear_cpu(cpu, to_cpumask(f->flush_cpumask)); inc_irq_stat(irq_tlb_count); } -void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm, - unsigned long va) +static void flush_tlb_others_ipi(const struct cpumask *cpumask, + struct mm_struct *mm, unsigned long va) { int sender; union smp_flush_state *f; - cpumask_t cpumask = *cpumaskp; - - if (is_uv_system() && uv_flush_tlb_others(&cpumask, mm, va)) - return; /* Caller has disabled preemption */ sender = smp_processor_id() % NUM_INVALIDATE_TLB_VECTORS; @@ -180,7 +176,8 @@ void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm, f->flush_mm = mm; f->flush_va = va; - cpus_or(f->flush_cpumask, cpumask, f->flush_cpumask); + cpumask_andnot(to_cpumask(f->flush_cpumask), + cpumask, cpumask_of(smp_processor_id())); /* * Make the above memory operations globally visible before @@ -191,9 +188,9 @@ void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm, * We have to send the IPI only to * CPUs affected. */ - send_IPI_mask(&cpumask, INVALIDATE_TLB_VECTOR_START + sender); + send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR_START + sender); - while (!cpus_empty(f->flush_cpumask)) + while (!cpumask_empty(to_cpumask(f->flush_cpumask))) cpu_relax(); f->flush_mm = NULL; @@ -201,6 +198,24 @@ void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm, spin_unlock(&f->tlbstate_lock); } +void native_flush_tlb_others(const struct cpumask *cpumask, + struct mm_struct *mm, unsigned long va) +{ + if (is_uv_system()) { + cpumask_var_t after_uv_flush; + + if (alloc_cpumask_var(&after_uv_flush, GFP_ATOMIC)) { + cpumask_andnot(after_uv_flush, + cpumask, cpumask_of(smp_processor_id())); + if (!uv_flush_tlb_others(after_uv_flush, mm, va)) + flush_tlb_others_ipi(after_uv_flush, mm, va); + free_cpumask_var(after_uv_flush); + return; + } + } + flush_tlb_others_ipi(cpumask, mm, va); +} + static int __cpuinit init_smp_flush(void) { int i; @@ -215,25 +230,18 @@ core_initcall(init_smp_flush); void flush_tlb_current_task(void) { struct mm_struct *mm = current->mm; - cpumask_t cpu_mask; preempt_disable(); - cpu_mask = mm->cpu_vm_mask; - cpu_clear(smp_processor_id(), cpu_mask); local_flush_tlb(); - if (!cpus_empty(cpu_mask)) - flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL); + if (cpumask_any_but(&mm->cpu_vm_mask, smp_processor_id()) < nr_cpu_ids) + flush_tlb_others(&mm->cpu_vm_mask, mm, TLB_FLUSH_ALL); preempt_enable(); } void flush_tlb_mm(struct mm_struct *mm) { - cpumask_t cpu_mask; - preempt_disable(); - cpu_mask = mm->cpu_vm_mask; - cpu_clear(smp_processor_id(), cpu_mask); if (current->active_mm == mm) { if (current->mm) @@ -241,8 +249,8 @@ void flush_tlb_mm(struct mm_struct *mm) else leave_mm(smp_processor_id()); } - if (!cpus_empty(cpu_mask)) - flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL); + if (cpumask_any_but(&mm->cpu_vm_mask, smp_processor_id()) < nr_cpu_ids) + flush_tlb_others(&mm->cpu_vm_mask, mm, TLB_FLUSH_ALL); preempt_enable(); } @@ -250,11 +258,8 @@ void flush_tlb_mm(struct mm_struct *mm) void flush_tlb_page(struct vm_area_struct *vma, unsigned long va) { struct mm_struct *mm = vma->vm_mm; - cpumask_t cpu_mask; preempt_disable(); - cpu_mask = mm->cpu_vm_mask; - cpu_clear(smp_processor_id(), cpu_mask); if (current->active_mm == mm) { if (current->mm) @@ -263,8 +268,8 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long va) leave_mm(smp_processor_id()); } - if (!cpus_empty(cpu_mask)) - flush_tlb_others(cpu_mask, mm, va); + if (cpumask_any_but(&mm->cpu_vm_mask, smp_processor_id()) < nr_cpu_ids) + flush_tlb_others(&mm->cpu_vm_mask, mm, va); preempt_enable(); } diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c index f885023167e..690dcf1a27d 100644 --- a/arch/x86/kernel/tlb_uv.c +++ b/arch/x86/kernel/tlb_uv.c @@ -212,11 +212,11 @@ static int uv_wait_completion(struct bau_desc *bau_desc, * The cpumaskp mask contains the cpus the broadcast was sent to. * * Returns 1 if all remote flushing was done. The mask is zeroed. - * Returns 0 if some remote flushing remains to be done. The mask is left - * unchanged. + * Returns 0 if some remote flushing remains to be done. The mask will have + * some bits still set. */ int uv_flush_send_and_wait(int cpu, int this_blade, struct bau_desc *bau_desc, - cpumask_t *cpumaskp) + struct cpumask *cpumaskp) { int completion_status = 0; int right_shift; @@ -263,13 +263,13 @@ int uv_flush_send_and_wait(int cpu, int this_blade, struct bau_desc *bau_desc, * Success, so clear the remote cpu's from the mask so we don't * use the IPI method of shootdown on them. */ - for_each_cpu_mask(bit, *cpumaskp) { + for_each_cpu(bit, cpumaskp) { blade = uv_cpu_to_blade_id(bit); if (blade == this_blade) continue; - cpu_clear(bit, *cpumaskp); + cpumask_clear_cpu(bit, cpumaskp); } - if (!cpus_empty(*cpumaskp)) + if (!cpumask_empty(cpumaskp)) return 0; return 1; } @@ -296,7 +296,7 @@ int uv_flush_send_and_wait(int cpu, int this_blade, struct bau_desc *bau_desc, * Returns 1 if all remote flushing was done. * Returns 0 if some remote flushing remains to be done. */ -int uv_flush_tlb_others(cpumask_t *cpumaskp, struct mm_struct *mm, +int uv_flush_tlb_others(struct cpumask *cpumaskp, struct mm_struct *mm, unsigned long va) { int i; @@ -315,7 +315,7 @@ int uv_flush_tlb_others(cpumask_t *cpumaskp, struct mm_struct *mm, bau_nodes_clear(&bau_desc->distribution, UV_DISTRIBUTION_SIZE); i = 0; - for_each_cpu_mask(bit, *cpumaskp) { + for_each_cpu(bit, cpumaskp) { blade = uv_cpu_to_blade_id(bit); BUG_ON(blade > (UV_DISTRIBUTION_SIZE - 1)); if (blade == this_blade) { diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index bea215230b2..965539ec425 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -634,35 +634,27 @@ static void xen_flush_tlb_single(unsigned long addr) preempt_enable(); } -static void xen_flush_tlb_others(const cpumask_t *cpus, struct mm_struct *mm, - unsigned long va) +static void xen_flush_tlb_others(const struct cpumask *cpus, + struct mm_struct *mm, unsigned long va) { struct { struct mmuext_op op; - cpumask_t mask; + DECLARE_BITMAP(mask, NR_CPUS); } *args; - cpumask_t cpumask = *cpus; struct multicall_space mcs; - /* - * A couple of (to be removed) sanity checks: - * - * - current CPU must not be in mask - * - mask must exist :) - */ - BUG_ON(cpus_empty(cpumask)); - BUG_ON(cpu_isset(smp_processor_id(), cpumask)); + BUG_ON(cpumask_empty(cpus)); BUG_ON(!mm); - /* If a CPU which we ran on has gone down, OK. */ - cpus_and(cpumask, cpumask, cpu_online_map); - if (cpus_empty(cpumask)) - return; - mcs = xen_mc_entry(sizeof(*args)); args = mcs.args; - args->mask = cpumask; - args->op.arg2.vcpumask = &args->mask; + args->op.arg2.vcpumask = to_cpumask(args->mask); + + /* Remove us, and any offline CPUS. */ + cpumask_and(to_cpumask(args->mask), cpus, cpu_online_mask); + cpumask_clear_cpu(smp_processor_id(), to_cpumask(args->mask)); + if (unlikely(cpumask_empty(to_cpumask(args->mask)))) + goto issue; if (va == TLB_FLUSH_ALL) { args->op.cmd = MMUEXT_TLB_FLUSH_MULTI; @@ -673,6 +665,7 @@ static void xen_flush_tlb_others(const cpumask_t *cpus, struct mm_struct *mm, MULTI_mmuext_op(mcs.mc, &args->op, 1, NULL, DOMID_SELF); +issue: xen_mc_issue(PARAVIRT_LAZY_MMU); } -- GitLab From 0e21990ae7ee11af94f44f240b06e520cf1505d4 Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Sat, 10 Jan 2009 21:58:10 -0800 Subject: [PATCH 0095/4982] SGI UV cpumask: use static temp cpumask in flush_tlb Impact: Improve tlb flush performance for UV Calling alloc_cpumask_var a zillion times a second does affect performance. Replace with static cpumask. Note: when CONFIG_X86_UV is defined, this extra PER_CPU memory will be optimized out for non-UV configs as is_uv_system() will then return a constant 0. Signed-off-by: Mike Travis --- arch/x86/kernel/tlb_64.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/arch/x86/kernel/tlb_64.c b/arch/x86/kernel/tlb_64.c index 38836aef51b..7a3f9891302 100644 --- a/arch/x86/kernel/tlb_64.c +++ b/arch/x86/kernel/tlb_64.c @@ -202,16 +202,17 @@ void native_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm, unsigned long va) { if (is_uv_system()) { - cpumask_var_t after_uv_flush; - - if (alloc_cpumask_var(&after_uv_flush, GFP_ATOMIC)) { - cpumask_andnot(after_uv_flush, - cpumask, cpumask_of(smp_processor_id())); - if (!uv_flush_tlb_others(after_uv_flush, mm, va)) - flush_tlb_others_ipi(after_uv_flush, mm, va); - free_cpumask_var(after_uv_flush); - return; - } + /* FIXME: could be an percpu_alloc'd thing */ + static DEFINE_PER_CPU(cpumask_t, flush_tlb_mask); + struct cpumask *after_uv_flush = &get_cpu_var(flush_tlb_mask); + + cpumask_andnot(after_uv_flush, cpumask, + cpumask_of(smp_processor_id())); + if (!uv_flush_tlb_others(after_uv_flush, mm, va)) + flush_tlb_others_ipi(after_uv_flush, mm, va); + + put_cpu_var(flush_tlb_uv_cpumask); + return; } flush_tlb_others_ipi(cpumask, mm, va); } -- GitLab From a1c33bbeb7061f3ed39103c385844474eaa8f921 Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Sat, 10 Jan 2009 21:58:10 -0800 Subject: [PATCH 0096/4982] x86: cleanup remaining cpumask_t code in mce_amd_64.c Impact: Reduce memory usage, use new cpumask API. Use cpumask_var_t for 'cpus' cpumask in struct threshold_bank and update remaining old cpumask_t functions to new cpumask API. Signed-off-by: Mike Travis --- arch/x86/kernel/cpu/mcheck/mce_amd_64.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c index 8ae8c4ff094..4772e91e824 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c @@ -67,7 +67,7 @@ static struct threshold_block threshold_defaults = { struct threshold_bank { struct kobject *kobj; struct threshold_block *blocks; - cpumask_t cpus; + cpumask_var_t cpus; }; static DEFINE_PER_CPU(struct threshold_bank *, threshold_banks[NR_BANKS]); @@ -481,7 +481,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) #ifdef CONFIG_SMP if (cpu_data(cpu).cpu_core_id && shared_bank[bank]) { /* symlink */ - i = first_cpu(per_cpu(cpu_core_map, cpu)); + i = cpumask_first(&per_cpu(cpu_core_map, cpu)); /* first core not up yet */ if (cpu_data(i).cpu_core_id) @@ -501,7 +501,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) if (err) goto out; - b->cpus = per_cpu(cpu_core_map, cpu); + cpumask_copy(b->cpus, &per_cpu(cpu_core_map, cpu)); per_cpu(threshold_banks, cpu)[bank] = b; goto out; } @@ -512,15 +512,20 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) err = -ENOMEM; goto out; } + if (!alloc_cpumask_var(&b->cpus, GFP_KERNEL)) { + kfree(b); + err = -ENOMEM; + goto out; + } b->kobj = kobject_create_and_add(name, &per_cpu(device_mce, cpu).kobj); if (!b->kobj) goto out_free; #ifndef CONFIG_SMP - b->cpus = CPU_MASK_ALL; + cpumask_setall(b->cpus); #else - b->cpus = per_cpu(cpu_core_map, cpu); + cpumask_copy(b->cpus, &per_cpu(cpu_core_map, cpu)); #endif per_cpu(threshold_banks, cpu)[bank] = b; @@ -529,7 +534,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) if (err) goto out_free; - for_each_cpu_mask_nr(i, b->cpus) { + for_each_cpu(i, b->cpus) { if (i == cpu) continue; @@ -545,6 +550,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) out_free: per_cpu(threshold_banks, cpu)[bank] = NULL; + free_cpumask_var(b->cpus); kfree(b); out: return err; @@ -619,7 +625,7 @@ static void threshold_remove_bank(unsigned int cpu, int bank) #endif /* remove all sibling symlinks before unregistering */ - for_each_cpu_mask_nr(i, b->cpus) { + for_each_cpu(i, b->cpus) { if (i == cpu) continue; @@ -632,6 +638,7 @@ static void threshold_remove_bank(unsigned int cpu, int bank) free_out: kobject_del(b->kobj); kobject_put(b->kobj); + free_cpumask_var(b->cpus); kfree(b); per_cpu(threshold_banks, cpu)[bank] = NULL; } -- GitLab From f9b90566cd46e19f670a1e60a717ff243f060a8a Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Sat, 10 Jan 2009 21:58:10 -0800 Subject: [PATCH 0097/4982] x86: reduce stack usage in init_intel_cacheinfo Impact: reduce stack usage. init_intel_cacheinfo() does not use the cpumask so define a subset of struct _cpuid4_info (_cpuid4_info_regs) that can be used instead. Signed-off-by: Mike Travis --- arch/x86/kernel/cpu/intel_cacheinfo.c | 63 +++++++++++++++++++-------- 1 file changed, 44 insertions(+), 19 deletions(-) diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 48533d77be7..58527a9fc40 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -132,7 +132,16 @@ struct _cpuid4_info { union _cpuid4_leaf_ecx ecx; unsigned long size; unsigned long can_disable; - cpumask_t shared_cpu_map; /* future?: only cpus/node is needed */ + DECLARE_BITMAP(shared_cpu_map, NR_CPUS); +}; + +/* subset of above _cpuid4_info w/o shared_cpu_map */ +struct _cpuid4_info_regs { + union _cpuid4_leaf_eax eax; + union _cpuid4_leaf_ebx ebx; + union _cpuid4_leaf_ecx ecx; + unsigned long size; + unsigned long can_disable; }; #ifdef CONFIG_PCI @@ -263,7 +272,7 @@ amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax, } static void __cpuinit -amd_check_l3_disable(int index, struct _cpuid4_info *this_leaf) +amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) { if (index < 3) return; @@ -271,7 +280,8 @@ amd_check_l3_disable(int index, struct _cpuid4_info *this_leaf) } static int -__cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf) +__cpuinit cpuid4_cache_lookup_regs(int index, + struct _cpuid4_info_regs *this_leaf) { union _cpuid4_leaf_eax eax; union _cpuid4_leaf_ebx ebx; @@ -299,6 +309,15 @@ __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf) return 0; } +static int +__cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf) +{ + struct _cpuid4_info_regs *leaf_regs = + (struct _cpuid4_info_regs *)this_leaf; + + return cpuid4_cache_lookup_regs(index, leaf_regs); +} + static int __cpuinit find_num_cache_leaves(void) { unsigned int eax, ebx, ecx, edx; @@ -338,11 +357,10 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) * parameters cpuid leaf to find the cache details */ for (i = 0; i < num_cache_leaves; i++) { - struct _cpuid4_info this_leaf; - + struct _cpuid4_info_regs this_leaf; int retval; - retval = cpuid4_cache_lookup(i, &this_leaf); + retval = cpuid4_cache_lookup_regs(i, &this_leaf); if (retval >= 0) { switch(this_leaf.eax.split.level) { case 1: @@ -491,17 +509,20 @@ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing; if (num_threads_sharing == 1) - cpu_set(cpu, this_leaf->shared_cpu_map); + cpumask_set_cpu(cpu, to_cpumask(this_leaf->shared_cpu_map)); else { index_msb = get_count_order(num_threads_sharing); for_each_online_cpu(i) { if (cpu_data(i).apicid >> index_msb == c->apicid >> index_msb) { - cpu_set(i, this_leaf->shared_cpu_map); + cpumask_set_cpu(i, + to_cpumask(this_leaf->shared_cpu_map)); if (i != cpu && per_cpu(cpuid4_info, i)) { - sibling_leaf = CPUID4_INFO_IDX(i, index); - cpu_set(cpu, sibling_leaf->shared_cpu_map); + sibling_leaf = + CPUID4_INFO_IDX(i, index); + cpumask_set_cpu(cpu, to_cpumask( + sibling_leaf->shared_cpu_map)); } } } @@ -513,9 +534,10 @@ static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index) int sibling; this_leaf = CPUID4_INFO_IDX(cpu, index); - for_each_cpu_mask_nr(sibling, this_leaf->shared_cpu_map) { + for_each_cpu(sibling, to_cpumask(this_leaf->shared_cpu_map)) { sibling_leaf = CPUID4_INFO_IDX(sibling, index); - cpu_clear(cpu, sibling_leaf->shared_cpu_map); + cpumask_clear_cpu(cpu, + to_cpumask(sibling_leaf->shared_cpu_map)); } } #else @@ -620,8 +642,9 @@ static ssize_t show_shared_cpu_map_func(struct _cpuid4_info *this_leaf, int n = 0; if (len > 1) { - cpumask_t *mask = &this_leaf->shared_cpu_map; + const struct cpumask *mask; + mask = to_cpumask(this_leaf->shared_cpu_map); n = type? cpulist_scnprintf(buf, len-2, mask) : cpumask_scnprintf(buf, len-2, mask); @@ -684,7 +707,8 @@ static struct pci_dev *get_k8_northbridge(int node) static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf) { - int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map)); + const struct cpumask *mask = to_cpumask(this_leaf->shared_cpu_map); + int node = cpu_to_node(cpumask_first(mask)); struct pci_dev *dev = NULL; ssize_t ret = 0; int i; @@ -718,7 +742,8 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, const char *buf, size_t count) { - int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map)); + const struct cpumask *mask = to_cpumask(this_leaf->shared_cpu_map); + int node = cpu_to_node(cpumask_first(mask)); struct pci_dev *dev = NULL; unsigned int ret, index, val; @@ -863,7 +888,7 @@ err_out: return -ENOMEM; } -static cpumask_t cache_dev_map = CPU_MASK_NONE; +static DECLARE_BITMAP(cache_dev_map, NR_CPUS); /* Add/Remove cache interface for CPU device */ static int __cpuinit cache_add_dev(struct sys_device * sys_dev) @@ -903,7 +928,7 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev) } kobject_uevent(&(this_object->kobj), KOBJ_ADD); } - cpu_set(cpu, cache_dev_map); + cpumask_set_cpu(cpu, to_cpumask(cache_dev_map)); kobject_uevent(per_cpu(cache_kobject, cpu), KOBJ_ADD); return 0; @@ -916,9 +941,9 @@ static void __cpuinit cache_remove_dev(struct sys_device * sys_dev) if (per_cpu(cpuid4_info, cpu) == NULL) return; - if (!cpu_isset(cpu, cache_dev_map)) + if (!cpumask_test_cpu(cpu, to_cpumask(cache_dev_map))) return; - cpu_clear(cpu, cache_dev_map); + cpumask_clear_cpu(cpu, to_cpumask(cache_dev_map)); for (i = 0; i < num_cache_leaves; i++) kobject_put(&(INDEX_KOBJECT_PTR(cpu,i)->kobj)); -- GitLab From c90e785be2fd9dfaef1f030d0314e44052553736 Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Sat, 10 Jan 2009 21:58:10 -0800 Subject: [PATCH 0098/4982] cpumask: use cpumask_var_t in dcdbas.c Impact: reduce stack usage. Replace cpumask_t with cpumask_var_t in drivers/firmware/dcdbas.c. Signed-off-by: Mike Travis --- drivers/firmware/dcdbas.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c index 777fba48d2d..3009e0171e5 100644 --- a/drivers/firmware/dcdbas.c +++ b/drivers/firmware/dcdbas.c @@ -244,7 +244,7 @@ static ssize_t host_control_on_shutdown_store(struct device *dev, */ int dcdbas_smi_request(struct smi_cmd *smi_cmd) { - cpumask_t old_mask; + cpumask_var_t old_mask; int ret = 0; if (smi_cmd->magic != SMI_CMD_MAGIC) { @@ -254,8 +254,11 @@ int dcdbas_smi_request(struct smi_cmd *smi_cmd) } /* SMI requires CPU 0 */ - old_mask = current->cpus_allowed; - set_cpus_allowed_ptr(current, &cpumask_of_cpu(0)); + if (!alloc_cpumask_var(&old_mask, GFP_KERNEL)) + return -ENOMEM; + + cpumask_copy(old_mask, ¤t->cpus_allowed); + set_cpus_allowed_ptr(current, cpumask_of(0)); if (smp_processor_id() != 0) { dev_dbg(&dcdbas_pdev->dev, "%s: failed to get CPU 0\n", __func__); @@ -275,7 +278,8 @@ int dcdbas_smi_request(struct smi_cmd *smi_cmd) ); out: - set_cpus_allowed_ptr(current, &old_mask); + set_cpus_allowed_ptr(current, old_mask); + free_cpumask_var(old_mask); return ret; } -- GitLab From d38b223c86db3162dc85b5a1997ac8a210e1660b Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Sat, 10 Jan 2009 21:58:11 -0800 Subject: [PATCH 0099/4982] cpumask: reduce stack usage in find_lowest_rq Impact: reduce stack usage, cleanup Use a cpumask_var_t in find_lowest_rq() and clean up other old cpumask_t calls. Signed-off-by: Mike Travis --- kernel/sched_rt.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 954e1a81b79..da932f4c852 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -960,16 +960,17 @@ static struct task_struct *pick_next_highest_task_rt(struct rq *rq, int cpu) static DEFINE_PER_CPU(cpumask_var_t, local_cpu_mask); -static inline int pick_optimal_cpu(int this_cpu, cpumask_t *mask) +static inline int pick_optimal_cpu(int this_cpu, + const struct cpumask *mask) { int first; /* "this_cpu" is cheaper to preempt than a remote processor */ - if ((this_cpu != -1) && cpu_isset(this_cpu, *mask)) + if ((this_cpu != -1) && cpumask_test_cpu(this_cpu, mask)) return this_cpu; - first = first_cpu(*mask); - if (first != NR_CPUS) + first = cpumask_first(mask); + if (first < nr_cpu_ids) return first; return -1; @@ -981,6 +982,7 @@ static int find_lowest_rq(struct task_struct *task) struct cpumask *lowest_mask = __get_cpu_var(local_cpu_mask); int this_cpu = smp_processor_id(); int cpu = task_cpu(task); + cpumask_var_t domain_mask; if (task->rt.nr_cpus_allowed == 1) return -1; /* No other targets possible */ @@ -1013,19 +1015,25 @@ static int find_lowest_rq(struct task_struct *task) if (this_cpu == cpu) this_cpu = -1; /* Skip this_cpu opt if the same */ - for_each_domain(cpu, sd) { - if (sd->flags & SD_WAKE_AFFINE) { - cpumask_t domain_mask; - int best_cpu; + if (alloc_cpumask_var(&domain_mask, GFP_ATOMIC)) { + for_each_domain(cpu, sd) { + if (sd->flags & SD_WAKE_AFFINE) { + int best_cpu; - cpumask_and(&domain_mask, sched_domain_span(sd), - lowest_mask); + cpumask_and(domain_mask, + sched_domain_span(sd), + lowest_mask); - best_cpu = pick_optimal_cpu(this_cpu, - &domain_mask); - if (best_cpu != -1) - return best_cpu; + best_cpu = pick_optimal_cpu(this_cpu, + domain_mask); + + if (best_cpu != -1) { + free_cpumask_var(domain_mask); + return best_cpu; + } + } } + free_cpumask_var(domain_mask); } /* -- GitLab From c7a3589e7a1f8fdbd2536fe1bfa60b37f5121c69 Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Sat, 10 Jan 2009 21:58:11 -0800 Subject: [PATCH 0100/4982] Xen: reduce memory required for cpu_evtchn_mask Impact: reduce memory usage. Reduce this significant gain in the amount of memory used when NR_CPUS bumped from 128 to 4096 by allocating the array based on nr_cpu_ids: 65536 +2031616 2097152 +3100% cpu_evtchn_mask(.bss) Signed-off-by: Mike Travis Cc: Jeremy Fitzhardinge Cc: Chris Wright Cc: virtualization@lists.osdl.org Cc: xen-devel@lists.xensource.com --- drivers/xen/events.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index e0767ff35d6..ed7527b3745 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -75,7 +75,14 @@ enum { static int evtchn_to_irq[NR_EVENT_CHANNELS] = { [0 ... NR_EVENT_CHANNELS-1] = -1 }; -static unsigned long cpu_evtchn_mask[NR_CPUS][NR_EVENT_CHANNELS/BITS_PER_LONG]; +struct cpu_evtchn_s { + unsigned long bits[NR_EVENT_CHANNELS/BITS_PER_LONG]; +}; +static struct cpu_evtchn_s *cpu_evtchn_mask_p; +static inline unsigned long *cpu_evtchn_mask(int cpu) +{ + return cpu_evtchn_mask_p[cpu].bits; +} static u8 cpu_evtchn[NR_EVENT_CHANNELS]; /* Reference counts for bindings to IRQs. */ @@ -115,7 +122,7 @@ static inline unsigned long active_evtchns(unsigned int cpu, unsigned int idx) { return (sh->evtchn_pending[idx] & - cpu_evtchn_mask[cpu][idx] & + cpu_evtchn_mask(cpu)[idx] & ~sh->evtchn_mask[idx]); } @@ -128,8 +135,8 @@ static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu) cpumask_copy(irq_to_desc(irq)->affinity, cpumask_of(cpu)); #endif - __clear_bit(chn, cpu_evtchn_mask[cpu_evtchn[chn]]); - __set_bit(chn, cpu_evtchn_mask[cpu]); + __clear_bit(chn, cpu_evtchn_mask(cpu_evtchn[chn])); + __set_bit(chn, cpu_evtchn_mask(cpu)); cpu_evtchn[chn] = cpu; } @@ -147,7 +154,7 @@ static void init_evtchn_cpu_bindings(void) #endif memset(cpu_evtchn, 0, sizeof(cpu_evtchn)); - memset(cpu_evtchn_mask[0], ~0, sizeof(cpu_evtchn_mask[0])); + memset(cpu_evtchn_mask(0), ~0, sizeof(cpu_evtchn_mask(0))); } static inline unsigned int cpu_from_evtchn(unsigned int evtchn) @@ -822,6 +829,10 @@ static struct irq_chip xen_dynamic_chip __read_mostly = { void __init xen_init_IRQ(void) { int i; + size_t size = nr_cpu_ids * sizeof(struct cpu_evtchn_s); + + cpu_evtchn_mask_p = kmalloc(size, GFP_KERNEL); + BUG_ON(cpu_evtchn_mask == NULL); init_evtchn_cpu_bindings(); -- GitLab From 9594949b060efe86ecaa1a66839232a3b9800bc9 Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Sat, 10 Jan 2009 22:24:06 -0800 Subject: [PATCH 0101/4982] irq: change references from NR_IRQS to nr_irqs Impact: preparation, cleanup, add KERN_INFO printk Modify references from NR_IRQS to nr_irqs as the later will become variable-sized based on nr_cpu_ids when CONFIG_SPARSE_IRQS=y. Signed-off-by: Mike Travis --- arch/x86/kernel/io_apic.c | 2 +- kernel/irq/handle.c | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 1337eab60ec..ae80638012d 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -3183,7 +3183,7 @@ unsigned int create_irq_nr(unsigned int irq_want) irq = 0; spin_lock_irqsave(&vector_lock, flags); - for (new = irq_want; new < NR_IRQS; new++) { + for (new = irq_want; new < nr_irqs; new++) { if (platform_legacy_irq(new)) continue; diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index f01c0a30cb4..790c5fa7ea3 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -132,6 +132,8 @@ int __init early_irq_init(void) int legacy_count; int i; + printk(KERN_INFO "NR_IRQS:%d nr_irqs:%d\n", NR_IRQS, nr_irqs); + desc = irq_desc_legacy; legacy_count = ARRAY_SIZE(irq_desc_legacy); @@ -143,7 +145,7 @@ int __init early_irq_init(void) irq_desc_ptrs[i] = desc + i; } - for (i = legacy_count; i < NR_IRQS; i++) + for (i = legacy_count; i < nr_irqs; i++) irq_desc_ptrs[i] = NULL; return arch_early_irq_init(); @@ -151,7 +153,7 @@ int __init early_irq_init(void) struct irq_desc *irq_to_desc(unsigned int irq) { - return (irq < NR_IRQS) ? irq_desc_ptrs[irq] : NULL; + return (irq < nr_irqs) ? irq_desc_ptrs[irq] : NULL; } struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu) @@ -160,9 +162,9 @@ struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu) unsigned long flags; int node; - if (irq >= NR_IRQS) { - printk(KERN_WARNING "irq >= NR_IRQS in irq_to_desc_alloc: %d %d\n", - irq, NR_IRQS); + if (irq >= nr_irqs) { + printk(KERN_WARNING "irq >= nr_irqs in irq_to_desc_alloc: %d %d\n", + irq, nr_irqs); WARN_ON(1); return NULL; } @@ -214,6 +216,8 @@ int __init early_irq_init(void) int count; int i; + printk(KERN_INFO "NR_IRQS:%d\n", NR_IRQS); + desc = irq_desc; count = ARRAY_SIZE(irq_desc); -- GitLab From e2f4d06545ec1f29b0e838ee34cbf3500ea5b9a4 Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Sat, 10 Jan 2009 22:24:06 -0800 Subject: [PATCH 0102/4982] irq: use WARN() instead of WARN_ON(). Impact: cleanup WARN msg. Ingo requested: > While at it, could you please also convert this to a WARN() construct > instead? (in a separate commit) ... and it shall be done. ;-) Signed-off-by: Mike Travis --- kernel/irq/handle.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 790c5fa7ea3..fd1ef16252f 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -163,9 +163,8 @@ struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu) int node; if (irq >= nr_irqs) { - printk(KERN_WARNING "irq >= nr_irqs in irq_to_desc_alloc: %d %d\n", - irq, nr_irqs); - WARN_ON(1); + WARN(1, "irq (%d) >= nr_irqs (%d) in irq_to_desc_alloc\n", + irq, nr_irqs); return NULL; } -- GitLab From 0fa0ebbf15addc1be8f73325d809c8547a9de304 Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Sat, 10 Jan 2009 22:24:06 -0800 Subject: [PATCH 0103/4982] irq: allocate irq_desc_ptrs array based on nr_irqs Impact: allocate irq_desc_ptrs in preparation for making it variable-sized. This addresses this memory usage bump when NR_CPUS bumped from 128 to 4096: 34816 +229376 264192 +658% irq_desc_ptrs(.data.read_mostly) The patch is split into two parts, the first simply allocates the irq_desc_ptrs array. Then next will deal with making it variable. This is only when CONFIG_SPARSE_IRQS=y. Signed-off-by: Mike Travis --- kernel/irq/handle.c | 11 +++++++++-- kernel/irq/internals.h | 7 +++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index fd1ef16252f..d0b8f7e7279 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "internals.h" @@ -110,7 +111,7 @@ static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu) */ DEFINE_SPINLOCK(sparse_irq_lock); -struct irq_desc *irq_desc_ptrs[NR_IRQS] __read_mostly; +struct irq_desc **irq_desc_ptrs __read_mostly; static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_smp = { [0 ... NR_IRQS_LEGACY-1] = { @@ -137,6 +138,9 @@ int __init early_irq_init(void) desc = irq_desc_legacy; legacy_count = ARRAY_SIZE(irq_desc_legacy); + /* allocate irq_desc_ptrs array based on nr_irqs */ + irq_desc_ptrs = alloc_bootmem(nr_irqs * sizeof(void *)); + for (i = 0; i < legacy_count; i++) { desc[i].irq = i; desc[i].kstat_irqs = kstat_irqs_legacy[i]; @@ -153,7 +157,10 @@ int __init early_irq_init(void) struct irq_desc *irq_to_desc(unsigned int irq) { - return (irq < nr_irqs) ? irq_desc_ptrs[irq] : NULL; + if (irq_desc_ptrs && irq < nr_irqs) + return irq_desc_ptrs[irq]; + + return NULL; } struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu) diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index e6d0a43cc12..40416a81a0f 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h @@ -16,7 +16,14 @@ extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, extern struct lock_class_key irq_desc_lock_class; extern void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr); extern spinlock_t sparse_irq_lock; + +#ifdef CONFIG_SPARSE_IRQ +/* irq_desc_ptrs allocated at boot time */ +extern struct irq_desc **irq_desc_ptrs; +#else +/* irq_desc_ptrs is a fixed size array */ extern struct irq_desc *irq_desc_ptrs[NR_IRQS]; +#endif #ifdef CONFIG_PROC_FS extern void register_irq_proc(unsigned int irq, struct irq_desc *desc); -- GitLab From 9332fccdedf8e09448f3b69b624211ae879f6c45 Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Sat, 10 Jan 2009 22:24:07 -0800 Subject: [PATCH 0104/4982] irq: initialize nr_irqs based on nr_cpu_ids Impact: Reduce memory usage. This is the second half of the changes to make the irq_desc_ptrs be variable sized based on nr_cpu_ids. This is done by adding a new "max_nr_irqs" macro to irq_vectors.h (and a dummy in irqnr.h) to return a max NR_IRQS value based on NR_CPUS or nr_cpu_ids. This necessitated moving the define of MAX_IO_APICS to a separate file (asm/apicnum.h) so it could be included without the baggage of the other asm/apicdef.h declarations. Signed-off-by: Mike Travis --- arch/x86/include/asm/apicdef.h | 8 ++------ arch/x86/include/asm/apicnum.h | 12 ++++++++++++ arch/x86/include/asm/irq_vectors.h | 16 +++++++++++----- include/linux/irqnr.h | 7 +++++++ kernel/irq/handle.c | 3 +++ 5 files changed, 35 insertions(+), 11 deletions(-) create mode 100644 arch/x86/include/asm/apicnum.h diff --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h index 63134e31e8b..1a6454ef7f6 100644 --- a/arch/x86/include/asm/apicdef.h +++ b/arch/x86/include/asm/apicdef.h @@ -132,12 +132,8 @@ #define APIC_BASE_MSR 0x800 #define X2APIC_ENABLE (1UL << 10) -#ifdef CONFIG_X86_32 -# define MAX_IO_APICS 64 -#else -# define MAX_IO_APICS 128 -# define MAX_LOCAL_APIC 32768 -#endif +/* get MAX_IO_APICS */ +#include /* * All x86-64 systems are xAPIC compatible. diff --git a/arch/x86/include/asm/apicnum.h b/arch/x86/include/asm/apicnum.h new file mode 100644 index 00000000000..82f613c607c --- /dev/null +++ b/arch/x86/include/asm/apicnum.h @@ -0,0 +1,12 @@ +#ifndef _ASM_X86_APICNUM_H +#define _ASM_X86_APICNUM_H + +/* define MAX_IO_APICS */ +#ifdef CONFIG_X86_32 +# define MAX_IO_APICS 64 +#else +# define MAX_IO_APICS 128 +# define MAX_LOCAL_APIC 32768 +#endif + +#endif /* _ASM_X86_APICNUM_H */ diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index f7ff65032b9..602361ad0e7 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h @@ -105,6 +105,8 @@ #if defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_VOYAGER) +#include /* need MAX_IO_APICS */ + #ifndef CONFIG_SPARSE_IRQ # if NR_CPUS < MAX_IO_APICS # define NR_IRQS (NR_VECTORS + (32 * NR_CPUS)) @@ -112,11 +114,15 @@ # define NR_IRQS (NR_VECTORS + (32 * MAX_IO_APICS)) # endif #else -# if (8 * NR_CPUS) > (32 * MAX_IO_APICS) -# define NR_IRQS (NR_VECTORS + (8 * NR_CPUS)) -# else -# define NR_IRQS (NR_VECTORS + (32 * MAX_IO_APICS)) -# endif + +/* defined as a macro so nr_irqs = max_nr_irqs(nr_cpu_ids) can be used */ +# define max_nr_irqs(nr_cpus) \ + ((8 * nr_cpus) > (32 * MAX_IO_APICS) ? \ + (NR_VECTORS + (8 * NR_CPUS)) : \ + (NR_VECTORS + (32 * MAX_IO_APICS))) \ + +# define NR_IRQS max_nr_irqs(NR_CPUS) + #endif #elif defined(CONFIG_X86_VOYAGER) diff --git a/include/linux/irqnr.h b/include/linux/irqnr.h index 86af92e9e84..de66e4e1040 100644 --- a/include/linux/irqnr.h +++ b/include/linux/irqnr.h @@ -20,11 +20,18 @@ # define for_each_irq_desc_reverse(irq, desc) \ for (irq = nr_irqs - 1; irq >= 0; irq--) + #else /* CONFIG_GENERIC_HARDIRQS */ +#include /* need possible max_nr_irqs() */ + extern int nr_irqs; extern struct irq_desc *irq_to_desc(unsigned int irq); +# ifndef max_nr_irqs +# define max_nr_irqs(nr_cpus) NR_IRQS +# endif + # define for_each_irq_desc(irq, desc) \ for (irq = 0, desc = irq_to_desc(irq); irq < nr_irqs; \ irq++, desc = irq_to_desc(irq)) \ diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index d0b8f7e7279..ebba7a116f1 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -133,6 +133,9 @@ int __init early_irq_init(void) int legacy_count; int i; + /* initialize nr_irqs based on nr_cpu_ids */ + nr_irqs = max_nr_irqs(nr_cpu_ids); + printk(KERN_INFO "NR_IRQS:%d nr_irqs:%d\n", NR_IRQS, nr_irqs); desc = irq_desc_legacy; -- GitLab From 542d865bbed4ce1f050f586e53cf1cfadda93766 Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Sat, 10 Jan 2009 22:24:07 -0800 Subject: [PATCH 0105/4982] kstat: modify kstat_irqs_legacy to be variable sized Impact: reduce memory usage. Allocate kstat_irqs_legacy based on nr_cpu_ids to deal with this memory usage bump when NR_CPUS bumped from 128 to 4096: 8192 +253952 262144 +3100% kstat_irqs_legacy(.bss) This is only when CONFIG_SPARSE_IRQS=y. Signed-off-by: Mike Travis --- kernel/irq/handle.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index ebba7a116f1..b39f32ac8f8 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -124,8 +124,7 @@ static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_sm } }; -/* FIXME: use bootmem alloc ...*/ -static unsigned int kstat_irqs_legacy[NR_IRQS_LEGACY][NR_CPUS]; +static unsigned int *kstat_irqs_legacy; int __init early_irq_init(void) { @@ -144,9 +143,14 @@ int __init early_irq_init(void) /* allocate irq_desc_ptrs array based on nr_irqs */ irq_desc_ptrs = alloc_bootmem(nr_irqs * sizeof(void *)); + /* allocate based on nr_cpu_ids */ + /* FIXME: invert kstat_irgs, and it'd be a per_cpu_alloc'd thing */ + kstat_irqs_legacy = alloc_bootmem(NR_IRQS_LEGACY * nr_cpu_ids * + sizeof(int)); + for (i = 0; i < legacy_count; i++) { desc[i].irq = i; - desc[i].kstat_irqs = kstat_irqs_legacy[i]; + desc[i].kstat_irqs = kstat_irqs_legacy + i * nr_cpu_ids; lockdep_set_class(&desc[i].lock, &irq_desc_lock_class); init_alloc_desc_masks(&desc[i], 0, true); irq_desc_ptrs[i] = desc + i; -- GitLab From 92296c6d6e908c35fca287a21af27be814af9c75 Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Sun, 11 Jan 2009 09:22:58 -0800 Subject: [PATCH 0106/4982] cpumask, irq: non-x86 build failures Ingo Molnar wrote: > All non-x86 architectures fail to build: > > In file included from /home/mingo/tip/include/linux/random.h:11, > from /home/mingo/tip/include/linux/stackprotector.h:6, > from /home/mingo/tip/init/main.c:17: > /home/mingo/tip/include/linux/irqnr.h:26:63: error: asm/irq_vectors.h: No such file or directory Do not include asm/irq_vectors.h in generic code - it's not available on all architectures. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/apicdef.h | 8 ++++++-- include/linux/irqnr.h | 6 ------ kernel/irq/handle.c | 5 +++++ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h index 1a6454ef7f6..63134e31e8b 100644 --- a/arch/x86/include/asm/apicdef.h +++ b/arch/x86/include/asm/apicdef.h @@ -132,8 +132,12 @@ #define APIC_BASE_MSR 0x800 #define X2APIC_ENABLE (1UL << 10) -/* get MAX_IO_APICS */ -#include +#ifdef CONFIG_X86_32 +# define MAX_IO_APICS 64 +#else +# define MAX_IO_APICS 128 +# define MAX_LOCAL_APIC 32768 +#endif /* * All x86-64 systems are xAPIC compatible. diff --git a/include/linux/irqnr.h b/include/linux/irqnr.h index de66e4e1040..887477bc2ab 100644 --- a/include/linux/irqnr.h +++ b/include/linux/irqnr.h @@ -23,15 +23,9 @@ #else /* CONFIG_GENERIC_HARDIRQS */ -#include /* need possible max_nr_irqs() */ - extern int nr_irqs; extern struct irq_desc *irq_to_desc(unsigned int irq); -# ifndef max_nr_irqs -# define max_nr_irqs(nr_cpus) NR_IRQS -# endif - # define for_each_irq_desc(irq, desc) \ for (irq = 0, desc = irq_to_desc(irq); irq < nr_irqs; \ irq++, desc = irq_to_desc(irq)) \ diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index b39f32ac8f8..04d3e46031e 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -58,6 +58,11 @@ int nr_irqs = NR_IRQS; EXPORT_SYMBOL_GPL(nr_irqs); #ifdef CONFIG_SPARSE_IRQ + +#ifndef max_nr_irqs +#define max_nr_irqs(nr_cpus) NR_IRQS +#endif + static struct irq_desc irq_desc_init = { .irq = -1, .status = IRQ_DISABLED, -- GitLab From 28e08861b9afab4168b758fb7b95aa7a4da0f668 Mon Sep 17 00:00:00 2001 From: Christophe Saout Date: Sun, 11 Jan 2009 11:46:23 -0800 Subject: [PATCH 0107/4982] xen: fix too early kmalloc call Impact: fix bootup crash on xen guests SLAB is not yet up, with earlyprintk it is giving me an Oops in __kmalloc. Replace call to kmalloc() with alloc_bootmem(). Reported-by: Christophe Saout Signed-off-by: Mike Travis Signed-off-by: Ingo Molnar --- drivers/xen/events.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index ed7527b3745..3141e149d59 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -831,8 +832,8 @@ void __init xen_init_IRQ(void) int i; size_t size = nr_cpu_ids * sizeof(struct cpu_evtchn_s); - cpu_evtchn_mask_p = kmalloc(size, GFP_KERNEL); - BUG_ON(cpu_evtchn_mask == NULL); + cpu_evtchn_mask_p = alloc_bootmem(size); + BUG_ON(cpu_evtchn_mask_p == NULL); init_evtchn_cpu_bindings(); -- GitLab From dd3feda7748b4c2739de47daaaa387fb01926c15 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Mon, 12 Jan 2009 14:44:29 +0530 Subject: [PATCH 0108/4982] x86: microcode_intel.c fix style problems Impact: cleanup Fix: WARNING: Use #include instead of ERROR: trailing whitespace ERROR: "(foo*)" should be "(foo *)" total: 3 errors, 1 warnings Signed-off-by: Jaswinder Singh Rajput Signed-off-by: Ingo Molnar --- arch/x86/kernel/microcode_intel.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index b7f4c929e61..5e9f4fc5138 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c @@ -87,9 +87,9 @@ #include #include #include +#include #include -#include #include #include @@ -196,7 +196,7 @@ static inline int update_match_cpu(struct cpu_signature *csig, int sig, int pf) return (!sigmatch(sig, csig->sig, pf, csig->pf)) ? 0 : 1; } -static inline int +static inline int update_match_revision(struct microcode_header_intel *mc_header, int rev) { return (mc_header->rev <= rev) ? 0 : 1; @@ -442,8 +442,8 @@ static int request_microcode_fw(int cpu, struct device *device) return ret; } - ret = generic_load_microcode(cpu, (void*)firmware->data, firmware->size, - &get_ucode_fw); + ret = generic_load_microcode(cpu, (void *)firmware->data, + firmware->size, &get_ucode_fw); release_firmware(firmware); @@ -460,7 +460,7 @@ static int request_microcode_user(int cpu, const void __user *buf, size_t size) /* We should bind the task to the CPU */ BUG_ON(cpu != raw_smp_processor_id()); - return generic_load_microcode(cpu, (void*)buf, size, &get_ucode_user); + return generic_load_microcode(cpu, (void *)buf, size, &get_ucode_user); } static void microcode_fini_cpu(int cpu) -- GitLab From 448dd2fa3ec915ad4325868ef8bb9b9490d9f6a9 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Mon, 12 Jan 2009 14:45:14 +0530 Subject: [PATCH 0109/4982] x86: msr.c fix style problems Impact: cleanup Fix: WARNING: Use #include instead of total: 0 errors, 1 warnings Signed-off-by: Jaswinder Singh Rajput Signed-off-by: Ingo Molnar --- arch/x86/kernel/msr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index 726266695b2..3cf3413ec62 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c @@ -35,10 +35,10 @@ #include #include #include +#include #include #include -#include #include static struct class *msr_class; -- GitLab From e17029ad69c7b1518413c00f793d89bb77b8527b Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Mon, 12 Jan 2009 14:46:03 +0530 Subject: [PATCH 0110/4982] x86: module_32.c fix style problems Impact: cleanup Fix: ERROR: code indent should use tabs where possible ERROR: trailing whitespace ERROR: spaces required around that '=' (ctx:VxW) total: 3 errors, 0 warnings Signed-off-by: Jaswinder Singh Rajput Signed-off-by: Ingo Molnar --- arch/x86/kernel/module_32.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/module_32.c b/arch/x86/kernel/module_32.c index 3db0a5442eb..0edd819050e 100644 --- a/arch/x86/kernel/module_32.c +++ b/arch/x86/kernel/module_32.c @@ -42,7 +42,7 @@ void module_free(struct module *mod, void *module_region) { vfree(module_region); /* FIXME: If module_region == mod->init_region, trim exception - table entries. */ + table entries. */ } /* We don't need anything special. */ @@ -113,13 +113,13 @@ int module_finalize(const Elf_Ehdr *hdr, *para = NULL; char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; - for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { + for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { if (!strcmp(".text", secstrings + s->sh_name)) text = s; if (!strcmp(".altinstructions", secstrings + s->sh_name)) alt = s; if (!strcmp(".smp_locks", secstrings + s->sh_name)) - locks= s; + locks = s; if (!strcmp(".parainstructions", secstrings + s->sh_name)) para = s; } -- GitLab From 3b9dc9f2f123286aaade54c45fef6723d587c664 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Mon, 12 Jan 2009 14:46:48 +0530 Subject: [PATCH 0111/4982] x86: module_64.c fix style problems Impact: cleanup Fix: ERROR: trailing whitespace ERROR: code indent should use tabs where possible WARNING: %Ld/%Lu are not-standard C, use %lld/%llu WARNING: printk() should include KERN_ facility level ERROR: spaces required around that '=' (ctx:VxW) total: 13 errors, 2 warnings Signed-off-by: Jaswinder Singh Rajput Signed-off-by: Ingo Molnar --- arch/x86/kernel/module_64.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/x86/kernel/module_64.c b/arch/x86/kernel/module_64.c index 6ba87830d4b..c23880b90b5 100644 --- a/arch/x86/kernel/module_64.c +++ b/arch/x86/kernel/module_64.c @@ -30,14 +30,14 @@ #include #include -#define DEBUGP(fmt...) +#define DEBUGP(fmt...) #ifndef CONFIG_UML void module_free(struct module *mod, void *module_region) { vfree(module_region); /* FIXME: If module_region == mod->init_region, trim exception - table entries. */ + table entries. */ } void *module_alloc(unsigned long size) @@ -77,7 +77,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr; Elf64_Sym *sym; void *loc; - u64 val; + u64 val; DEBUGP("Applying relocate section %u to %u\n", relsec, sechdrs[relsec].sh_info); @@ -91,11 +91,11 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, sym = (Elf64_Sym *)sechdrs[symindex].sh_addr + ELF64_R_SYM(rel[i].r_info); - DEBUGP("type %d st_value %Lx r_addend %Lx loc %Lx\n", - (int)ELF64_R_TYPE(rel[i].r_info), - sym->st_value, rel[i].r_addend, (u64)loc); + DEBUGP("type %d st_value %Lx r_addend %Lx loc %Lx\n", + (int)ELF64_R_TYPE(rel[i].r_info), + sym->st_value, rel[i].r_addend, (u64)loc); - val = sym->st_value + rel[i].r_addend; + val = sym->st_value + rel[i].r_addend; switch (ELF64_R_TYPE(rel[i].r_info)) { case R_X86_64_NONE: @@ -113,16 +113,16 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, if ((s64)val != *(s32 *)loc) goto overflow; break; - case R_X86_64_PC32: + case R_X86_64_PC32: val -= (u64)loc; *(u32 *)loc = val; #if 0 if ((s64)val != *(s32 *)loc) - goto overflow; + goto overflow; #endif break; default: - printk(KERN_ERR "module %s: Unknown rela relocation: %Lu\n", + printk(KERN_ERR "module %s: Unknown rela relocation: %llu\n", me->name, ELF64_R_TYPE(rel[i].r_info)); return -ENOEXEC; } @@ -130,7 +130,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, return 0; overflow: - printk(KERN_ERR "overflow in relocation type %d val %Lx\n", + printk(KERN_ERR "overflow in relocation type %d val %Lx\n", (int)ELF64_R_TYPE(rel[i].r_info), val); printk(KERN_ERR "`%s' likely not compiled with -mcmodel=kernel\n", me->name); @@ -143,13 +143,13 @@ int apply_relocate(Elf_Shdr *sechdrs, unsigned int relsec, struct module *me) { - printk("non add relocation not supported\n"); + printk(KERN_ERR "non add relocation not supported\n"); return -ENOSYS; -} +} int module_finalize(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, - struct module *me) + const Elf_Shdr *sechdrs, + struct module *me) { const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL, *para = NULL; @@ -161,7 +161,7 @@ int module_finalize(const Elf_Ehdr *hdr, if (!strcmp(".altinstructions", secstrings + s->sh_name)) alt = s; if (!strcmp(".smp_locks", secstrings + s->sh_name)) - locks= s; + locks = s; if (!strcmp(".parainstructions", secstrings + s->sh_name)) para = s; } -- GitLab From 53fb1e63599438bd5f6fbb852023d80916d83983 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 28 Dec 2008 16:32:08 +0100 Subject: [PATCH 0112/4982] ALSA: Introduce snd_card_create() Introduced snd_card_create() function as a replacement of snd_card_new(). The new function returns a negative error code so that the probe callback can return the proper error code, while snd_card_new() can give only NULL check. The old snd_card_new() is still provided as an inline function but with __deprecated attribute. It'll be removed soon later. Signed-off-by: Takashi Iwai --- include/sound/core.h | 14 ++++++++++++- sound/core/init.c | 47 +++++++++++++++++++++++++++++--------------- 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/include/sound/core.h b/include/sound/core.h index f632484bc74..25420c3b551 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -296,8 +296,20 @@ int snd_card_locked(int card); extern int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int cmd); #endif +int snd_card_create(int idx, const char *id, + struct module *module, int extra_size, + struct snd_card **card_ret); + +static inline __deprecated struct snd_card *snd_card_new(int idx, const char *id, - struct module *module, int extra_size); + struct module *module, int extra_size) +{ + struct snd_card *card; + if (snd_card_create(idx, id, module, extra_size, &card) < 0) + return NULL; + return card; +} + int snd_card_disconnect(struct snd_card *card); int snd_card_free(struct snd_card *card); int snd_card_free_when_closed(struct snd_card *card); diff --git a/sound/core/init.c b/sound/core/init.c index 0d5520c415d..dc4b80c7f31 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -121,31 +121,44 @@ static inline int init_info_for_card(struct snd_card *card) #endif /** - * snd_card_new - create and initialize a soundcard structure + * snd_card_create - create and initialize a soundcard structure * @idx: card index (address) [0 ... (SNDRV_CARDS-1)] * @xid: card identification (ASCII string) * @module: top level module for locking * @extra_size: allocate this extra size after the main soundcard structure + * @card_ret: the pointer to store the created card instance * * Creates and initializes a soundcard structure. * - * Returns kmallocated snd_card structure. Creates the ALSA control interface - * (which is blocked until snd_card_register function is called). + * The function allocates snd_card instance via kzalloc with the given + * space for the driver to use freely. The allocated struct is stored + * in the given card_ret pointer. + * + * Returns zero if successful or a negative error code. */ -struct snd_card *snd_card_new(int idx, const char *xid, - struct module *module, int extra_size) +int snd_card_create(int idx, const char *xid, + struct module *module, int extra_size, + struct snd_card **card_ret) { struct snd_card *card; int err, idx2; + if (snd_BUG_ON(!card_ret)) + return -EINVAL; + *card_ret = NULL; + if (extra_size < 0) extra_size = 0; card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL); - if (card == NULL) - return NULL; + if (!card) + return -ENOMEM; if (xid) { - if (!snd_info_check_reserved_words(xid)) + if (!snd_info_check_reserved_words(xid)) { + snd_printk(KERN_ERR + "given id string '%s' is reserved.\n", xid); + err = -EBUSY; goto __error; + } strlcpy(card->id, xid, sizeof(card->id)); } err = 0; @@ -202,26 +215,28 @@ struct snd_card *snd_card_new(int idx, const char *xid, #endif /* the control interface cannot be accessed from the user space until */ /* snd_cards_bitmask and snd_cards are set with snd_card_register */ - if ((err = snd_ctl_create(card)) < 0) { - snd_printd("unable to register control minors\n"); + err = snd_ctl_create(card); + if (err < 0) { + snd_printk(KERN_ERR "unable to register control minors\n"); goto __error; } - if ((err = snd_info_card_create(card)) < 0) { - snd_printd("unable to create card info\n"); + err = snd_info_card_create(card); + if (err < 0) { + snd_printk(KERN_ERR "unable to create card info\n"); goto __error_ctl; } if (extra_size > 0) card->private_data = (char *)card + sizeof(struct snd_card); - return card; + *card_ret = card; + return 0; __error_ctl: snd_device_free_all(card, SNDRV_DEV_CMD_PRE); __error: kfree(card); - return NULL; + return err; } - -EXPORT_SYMBOL(snd_card_new); +EXPORT_SYMBOL(snd_card_create); /* return non-zero if a card is already locked */ int snd_card_locked(int card) -- GitLab From c95eadd2f1afd2ba643e85a8dfc9079a3f03ae47 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 28 Dec 2008 16:43:35 +0100 Subject: [PATCH 0113/4982] ALSA: Convert to snd_card_create() in sound/isa/* Convert from snd_card_new() to the new snd_card_create() function. Signed-off-by: Takashi Iwai --- sound/isa/ad1816a/ad1816a.c | 7 ++++--- sound/isa/ad1848/ad1848.c | 6 +++--- sound/isa/adlib.c | 6 +++--- sound/isa/als100.c | 7 ++++--- sound/isa/azt2320.c | 7 ++++--- sound/isa/cmi8330.c | 26 +++++++++++++------------ sound/isa/cs423x/cs4231.c | 6 +++--- sound/isa/cs423x/cs4236.c | 7 ++++--- sound/isa/dt019x.c | 7 ++++--- sound/isa/es1688/es1688.c | 6 +++--- sound/isa/es18xx.c | 7 +++++-- sound/isa/gus/gusclassic.c | 6 +++--- sound/isa/gus/gusextreme.c | 6 +++--- sound/isa/gus/gusmax.c | 8 ++++---- sound/isa/gus/interwave.c | 7 ++++--- sound/isa/opl3sa2.c | 31 ++++++++++++++++-------------- sound/isa/opti9xx/miro.c | 7 ++++--- sound/isa/opti9xx/opti92x-ad1848.c | 6 ++++-- sound/isa/sb/es968.c | 7 ++++--- sound/isa/sb/sb16.c | 9 ++++++--- sound/isa/sb/sb8.c | 8 ++++---- sound/isa/sc6000.c | 6 +++--- sound/isa/sgalaxy.c | 6 +++--- sound/isa/sscape.c | 16 +++++++-------- sound/isa/wavefront/wavefront.c | 7 ++++--- 25 files changed, 122 insertions(+), 100 deletions(-) diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c index 77524244a84..9660e598232 100644 --- a/sound/isa/ad1816a/ad1816a.c +++ b/sound/isa/ad1816a/ad1816a.c @@ -157,9 +157,10 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard struct snd_ad1816a *chip; struct snd_opl3 *opl3; - if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_ad1816a))) == NULL) - return -ENOMEM; + error = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_card_ad1816a), &card); + if (error < 0) + return error; acard = (struct snd_card_ad1816a *)card->private_data; if ((error = snd_card_ad1816a_pnp(dev, acard, pcard, pid))) { diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c index 223a6c03881..4beeb6f98e0 100644 --- a/sound/isa/ad1848/ad1848.c +++ b/sound/isa/ad1848/ad1848.c @@ -91,9 +91,9 @@ static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n) struct snd_pcm *pcm; int error; - card = snd_card_new(index[n], id[n], THIS_MODULE, 0); - if (!card) - return -EINVAL; + error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); + if (error < 0) + return error; error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], -1, thinkpad[n] ? WSS_HW_THINKPAD : WSS_HW_DETECT, diff --git a/sound/isa/adlib.c b/sound/isa/adlib.c index 374b7177e11..7465ae036e0 100644 --- a/sound/isa/adlib.c +++ b/sound/isa/adlib.c @@ -53,10 +53,10 @@ static int __devinit snd_adlib_probe(struct device *dev, unsigned int n) struct snd_opl3 *opl3; int error; - card = snd_card_new(index[n], id[n], THIS_MODULE, 0); - if (!card) { + error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); + if (error < 0) { dev_err(dev, "could not create card\n"); - return -EINVAL; + return error; } card->private_data = request_region(port[n], 4, CRD_NAME); diff --git a/sound/isa/als100.c b/sound/isa/als100.c index f1ce30f379c..5fd52e4d707 100644 --- a/sound/isa/als100.c +++ b/sound/isa/als100.c @@ -163,9 +163,10 @@ static int __devinit snd_card_als100_probe(int dev, struct snd_card_als100 *acard; struct snd_opl3 *opl3; - if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_als100))) == NULL) - return -ENOMEM; + error = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_card_als100), &card); + if (error < 0) + return error; acard = card->private_data; if ((error = snd_card_als100_pnp(dev, acard, pcard, pid))) { diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c index 3e74d1a3928..f7aa637b0d1 100644 --- a/sound/isa/azt2320.c +++ b/sound/isa/azt2320.c @@ -184,9 +184,10 @@ static int __devinit snd_card_azt2320_probe(int dev, struct snd_wss *chip; struct snd_opl3 *opl3; - if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_azt2320))) == NULL) - return -ENOMEM; + error = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_card_azt2320), &card); + if (error < 0) + return error; acard = (struct snd_card_azt2320 *)card->private_data; if ((error = snd_card_azt2320_pnp(dev, acard, pcard, pid))) { diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index e49aec700a5..24e60902f8c 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -467,20 +467,22 @@ static int snd_cmi8330_resume(struct snd_card *card) #define PFX "cmi8330: " -static struct snd_card *snd_cmi8330_card_new(int dev) +static int snd_cmi8330_card_new(int dev, struct snd_card **cardp) { struct snd_card *card; struct snd_cmi8330 *acard; + int err; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_cmi8330)); - if (card == NULL) { + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_cmi8330), &card); + if (err < 0) { snd_printk(KERN_ERR PFX "could not get a new card\n"); - return NULL; + return err; } acard = card->private_data; acard->card = card; - return card; + *cardp = card; + return 0; } static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) @@ -564,9 +566,9 @@ static int __devinit snd_cmi8330_isa_probe(struct device *pdev, struct snd_card *card; int err; - card = snd_cmi8330_card_new(dev); - if (! card) - return -ENOMEM; + err = snd_cmi8330_card_new(dev, &card); + if (err < 0) + return err; snd_card_set_dev(card, pdev); if ((err = snd_cmi8330_probe(card, dev)) < 0) { snd_card_free(card); @@ -628,9 +630,9 @@ static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard, if (dev >= SNDRV_CARDS) return -ENODEV; - card = snd_cmi8330_card_new(dev); - if (! card) - return -ENOMEM; + res = snd_cmi8330_card_new(dev, &card); + if (res < 0) + return res; if ((res = snd_cmi8330_pnp(dev, card->private_data, pcard, pid)) < 0) { snd_printk(KERN_ERR PFX "PnP detection failed\n"); snd_card_free(card); diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c index f019d449e2d..cb9153e75b8 100644 --- a/sound/isa/cs423x/cs4231.c +++ b/sound/isa/cs423x/cs4231.c @@ -95,9 +95,9 @@ static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n) struct snd_pcm *pcm; int error; - card = snd_card_new(index[n], id[n], THIS_MODULE, 0); - if (!card) - return -EINVAL; + error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); + if (error < 0) + return error; error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], dma2[n], WSS_HW_DETECT, 0, &chip); diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index 019c9401663..db830682804 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c @@ -385,10 +385,11 @@ static void snd_card_cs4236_free(struct snd_card *card) static struct snd_card *snd_cs423x_card_new(int dev) { struct snd_card *card; + int err; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_cs4236)); - if (card == NULL) + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_card_cs4236), &card); + if (err < 0) return NULL; card->private_free = snd_card_cs4236_free; return card; diff --git a/sound/isa/dt019x.c b/sound/isa/dt019x.c index a0242c3b613..80f5b1af9be 100644 --- a/sound/isa/dt019x.c +++ b/sound/isa/dt019x.c @@ -150,9 +150,10 @@ static int __devinit snd_card_dt019x_probe(int dev, struct pnp_card_link *pcard, struct snd_card_dt019x *acard; struct snd_opl3 *opl3; - if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_dt019x))) == NULL) - return -ENOMEM; + error = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_card_dt019x), &card); + if (error < 0) + return error; acard = card->private_data; snd_card_set_dev(card, &pcard->card->dev); diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c index b46377139cf..d746750410e 100644 --- a/sound/isa/es1688/es1688.c +++ b/sound/isa/es1688/es1688.c @@ -122,9 +122,9 @@ static int __devinit snd_es1688_probe(struct device *dev, unsigned int n) struct snd_pcm *pcm; int error; - card = snd_card_new(index[n], id[n], THIS_MODULE, 0); - if (!card) - return -EINVAL; + error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); + if (error < 0) + return error; error = snd_es1688_legacy_create(card, dev, n, &chip); if (error < 0) diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index 90498e4ca26..c24c6322fcc 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -2127,8 +2127,11 @@ static int __devinit snd_audiodrive_pnpc(int dev, struct snd_audiodrive *acard, static struct snd_card *snd_es18xx_card_new(int dev) { - return snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_audiodrive)); + struct snd_card *card; + if (snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_audiodrive), &card) < 0) + return NULL; + return card; } static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev) diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c index 426532a4d73..086b8f0e0f9 100644 --- a/sound/isa/gus/gusclassic.c +++ b/sound/isa/gus/gusclassic.c @@ -148,9 +148,9 @@ static int __devinit snd_gusclassic_probe(struct device *dev, unsigned int n) struct snd_gus_card *gus; int error; - card = snd_card_new(index[n], id[n], THIS_MODULE, 0); - if (!card) - return -EINVAL; + error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); + if (error < 0) + return error; if (pcm_channels[n] < 2) pcm_channels[n] = 2; diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c index 7ad4c3b41a8..180a8dea6bd 100644 --- a/sound/isa/gus/gusextreme.c +++ b/sound/isa/gus/gusextreme.c @@ -241,9 +241,9 @@ static int __devinit snd_gusextreme_probe(struct device *dev, unsigned int n) struct snd_opl3 *opl3; int error; - card = snd_card_new(index[n], id[n], THIS_MODULE, 0); - if (!card) - return -EINVAL; + error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); + if (error < 0) + return error; if (mpu_port[n] == SNDRV_AUTO_PORT) mpu_port[n] = 0; diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c index f94c1976e63..f26eac8d811 100644 --- a/sound/isa/gus/gusmax.c +++ b/sound/isa/gus/gusmax.c @@ -214,10 +214,10 @@ static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev) struct snd_wss *wss; struct snd_gusmax *maxcard; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_gusmax)); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_gusmax), &card); + if (err < 0) + return err; card->private_free = snd_gusmax_free; maxcard = (struct snd_gusmax *)card->private_data; maxcard->card = card; diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index 5faecfb602d..e040c763891 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c @@ -630,10 +630,11 @@ static struct snd_card *snd_interwave_card_new(int dev) { struct snd_card *card; struct snd_interwave *iwcard; + int err; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_interwave)); - if (card == NULL) + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_interwave), &card); + if (err < 0) return NULL; iwcard = card->private_data; iwcard->card = card; diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index 58c972b2af0..645491a5302 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c @@ -617,21 +617,24 @@ static void snd_opl3sa2_free(struct snd_card *card) release_and_free_resource(chip->res_port); } -static struct snd_card *snd_opl3sa2_card_new(int dev) +static int snd_opl3sa2_card_new(int dev, struct snd_card **cardp) { struct snd_card *card; struct snd_opl3sa2 *chip; + int err; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct snd_opl3sa2)); - if (card == NULL) - return NULL; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_opl3sa2), &card); + if (err < 0) + return err; strcpy(card->driver, "OPL3SA2"); strcpy(card->shortname, "Yamaha OPL3-SA2"); chip = card->private_data; spin_lock_init(&chip->reg_lock); chip->irq = -1; card->private_free = snd_opl3sa2_free; - return card; + *cardp = card; + return 0; } static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev) @@ -723,9 +726,9 @@ static int __devinit snd_opl3sa2_pnp_detect(struct pnp_dev *pdev, if (dev >= SNDRV_CARDS) return -ENODEV; - card = snd_opl3sa2_card_new(dev); - if (! card) - return -ENOMEM; + err = snd_opl3sa2_card_new(dev, &card); + if (err < 0) + return err; if ((err = snd_opl3sa2_pnp(dev, card->private_data, pdev)) < 0) { snd_card_free(card); return err; @@ -789,9 +792,9 @@ static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard, if (dev >= SNDRV_CARDS) return -ENODEV; - card = snd_opl3sa2_card_new(dev); - if (! card) - return -ENOMEM; + err = snd_opl3sa2_card_new(dev, &card); + if (err < 0) + return err; if ((err = snd_opl3sa2_pnp(dev, card->private_data, pdev)) < 0) { snd_card_free(card); return err; @@ -870,9 +873,9 @@ static int __devinit snd_opl3sa2_isa_probe(struct device *pdev, struct snd_card *card; int err; - card = snd_opl3sa2_card_new(dev); - if (! card) - return -ENOMEM; + err = snd_opl3sa2_card_new(dev, &card); + if (err < 0) + return err; snd_card_set_dev(card, pdev); if ((err = snd_opl3sa2_probe(card, dev)) < 0) { snd_card_free(card); diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index 440755cc001..02e30d7c6a9 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c @@ -1228,9 +1228,10 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n) struct snd_pcm *pcm; struct snd_rawmidi *rmidi; - if (!(card = snd_card_new(index, id, THIS_MODULE, - sizeof(struct snd_miro)))) - return -ENOMEM; + error = snd_card_create(index, id, THIS_MODULE, + sizeof(struct snd_miro), &card); + if (error < 0) + return error; card->private_free = snd_card_miro_free; miro = card->private_data; diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 19706b0d849..5750f38bb79 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -833,9 +833,11 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) static struct snd_card *snd_opti9xx_card_new(void) { struct snd_card *card; + int err; - card = snd_card_new(index, id, THIS_MODULE, sizeof(struct snd_opti9xx)); - if (! card) + err = snd_card_create(index, id, THIS_MODULE, + sizeof(struct snd_opti9xx), &card); + if (err < 0) return NULL; card->private_free = snd_card_opti9xx_free; return card; diff --git a/sound/isa/sb/es968.c b/sound/isa/sb/es968.c index c8c8e214c84..cafc3a7316a 100644 --- a/sound/isa/sb/es968.c +++ b/sound/isa/sb/es968.c @@ -108,9 +108,10 @@ static int __devinit snd_card_es968_probe(int dev, struct snd_card *card; struct snd_card_es968 *acard; - if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_es968))) == NULL) - return -ENOMEM; + error = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_card_es968), &card); + if (error < 0) + return error; acard = card->private_data; if ((error = snd_card_es968_pnp(dev, acard, pcard, pid))) { snd_card_free(card); diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index 2c201f78ce5..adf4fdd2c4a 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c @@ -326,9 +326,12 @@ static void snd_sb16_free(struct snd_card *card) static struct snd_card *snd_sb16_card_new(int dev) { - struct snd_card *card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_sb16)); - if (card == NULL) + struct snd_card *card; + int err; + + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_card_sb16), &card); + if (err < 0) return NULL; card->private_free = snd_sb16_free; return card; diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c index ea06877be4b..3cd57ee5466 100644 --- a/sound/isa/sb/sb8.c +++ b/sound/isa/sb/sb8.c @@ -103,10 +103,10 @@ static int __devinit snd_sb8_probe(struct device *pdev, unsigned int dev) struct snd_opl3 *opl3; int err; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_sb8)); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_sb8), &card); + if (err < 0) + return err; acard = card->private_data; card->private_free = snd_sb8_free; diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c index ca35924dc3b..7a1470376c6 100644 --- a/sound/isa/sc6000.c +++ b/sound/isa/sc6000.c @@ -489,9 +489,9 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) char __iomem *vmss_port; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (!card) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if (xirq == SNDRV_AUTO_IRQ) { xirq = snd_legacy_find_free_irq(possible_irqs); diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c index 2c7503bf127..6fe27b9d944 100644 --- a/sound/isa/sgalaxy.c +++ b/sound/isa/sgalaxy.c @@ -243,9 +243,9 @@ static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev) struct snd_card *card; struct snd_wss *chip; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; xirq = irq[dev]; if (xirq == SNDRV_AUTO_IRQ) { diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 48a16d86583..4025fb558c5 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -1357,10 +1357,10 @@ static int __devinit snd_sscape_probe(struct device *pdev, unsigned int dev) struct soundscape *sscape; int ret; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct soundscape)); - if (!card) - return -ENOMEM; + ret = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct soundscape), &card); + if (ret < 0) + return ret; sscape = get_card_soundscape(card); sscape->type = SSCAPE; @@ -1462,10 +1462,10 @@ static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard, * Create a new ALSA sound card entry, in anticipation * of detecting our hardware ... */ - card = snd_card_new(index[idx], id[idx], THIS_MODULE, - sizeof(struct soundscape)); - if (!card) - return -ENOMEM; + ret = snd_card_create(index[idx], id[idx], THIS_MODULE, + sizeof(struct soundscape), &card); + if (ret < 0) + return ret; sscape = get_card_soundscape(card); diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index 4c095bc7c72..82b8fb74690 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c @@ -342,10 +342,11 @@ static struct snd_card *snd_wavefront_card_new(int dev) { struct snd_card *card; snd_wavefront_card_t *acard; + int err; - card = snd_card_new (index[dev], id[dev], THIS_MODULE, - sizeof(snd_wavefront_card_t)); - if (card == NULL) + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(snd_wavefront_card_t), &card); + if (err < 0) return NULL; acard = card->private_data; -- GitLab From e58de7baf7de11f01a675cbbf6ecc8a2758b9ca5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 28 Dec 2008 16:44:30 +0100 Subject: [PATCH 0114/4982] ALSA: Convert to snd_card_create() in sound/pci/* Convert from snd_card_new() to the new snd_card_create() function in sound/pci/*. Signed-off-by: Takashi Iwai --- sound/pci/ad1889.c | 6 +++--- sound/pci/ali5451/ali5451.c | 6 +++--- sound/pci/als300.c | 6 +++--- sound/pci/als4000.c | 9 +++++---- sound/pci/atiixp.c | 6 +++--- sound/pci/atiixp_modem.c | 6 +++--- sound/pci/au88x0/au88x0.c | 6 +++--- sound/pci/aw2/aw2-alsa.c | 6 +++--- sound/pci/azt3328.c | 6 +++--- sound/pci/bt87x.c | 6 +++--- sound/pci/ca0106/ca0106_main.c | 6 +++--- sound/pci/cmipci.c | 6 +++--- sound/pci/cs4281.c | 6 +++--- sound/pci/cs46xx/cs46xx.c | 6 +++--- sound/pci/cs5530.c | 6 +++--- sound/pci/cs5535audio/cs5535audio.c | 6 +++--- sound/pci/echoaudio/echoaudio.c | 6 +++--- sound/pci/emu10k1/emu10k1.c | 6 +++--- sound/pci/emu10k1/emu10k1x.c | 6 +++--- sound/pci/ens1370.c | 6 +++--- sound/pci/es1938.c | 6 +++--- sound/pci/es1968.c | 6 +++--- sound/pci/fm801.c | 6 +++--- sound/pci/hda/hda_intel.c | 6 +++--- sound/pci/ice1712/ice1712.c | 6 +++--- sound/pci/ice1712/ice1724.c | 6 +++--- sound/pci/intel8x0.c | 6 +++--- sound/pci/intel8x0m.c | 6 +++--- sound/pci/korg1212/korg1212.c | 6 +++--- sound/pci/maestro3.c | 6 +++--- sound/pci/mixart/mixart.c | 6 +++--- sound/pci/nm256/nm256.c | 6 +++--- sound/pci/oxygen/oxygen_lib.c | 8 ++++---- sound/pci/pcxhr/pcxhr.c | 6 +++--- sound/pci/riptide/riptide.c | 6 +++--- sound/pci/rme32.c | 7 ++++--- sound/pci/rme96.c | 7 ++++--- sound/pci/rme9652/hdsp.c | 6 ++++-- sound/pci/rme9652/hdspm.c | 8 ++++---- sound/pci/rme9652/rme9652.c | 8 ++++---- sound/pci/sis7019.c | 5 ++--- sound/pci/sonicvibes.c | 6 +++--- sound/pci/trident/trident.c | 6 +++--- sound/pci/via82xx.c | 6 +++--- sound/pci/via82xx_modem.c | 6 +++--- sound/pci/vx222/vx222.c | 6 +++--- sound/pci/ymfpci/ymfpci.c | 6 +++--- 47 files changed, 148 insertions(+), 144 deletions(-) diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index a7f38e63303..d1f242bd0ac 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c @@ -995,10 +995,10 @@ snd_ad1889_probe(struct pci_dev *pci, } /* (2) */ - card = snd_card_new(index[devno], id[devno], THIS_MODULE, 0); + err = snd_card_create(index[devno], id[devno], THIS_MODULE, 0, &card); /* XXX REVISIT: we can probably allocate chip in this call */ - if (card == NULL) - return -ENOMEM; + if (err < 0) + return err; strcpy(card->driver, "AD1889"); strcpy(card->shortname, "Analog Devices AD1889"); diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 1a0fd65ec28..b36c551da56 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -2307,9 +2307,9 @@ static int __devinit snd_ali_probe(struct pci_dev *pci, snd_ali_printk("probe ...\n"); - card = snd_card_new(index, id, THIS_MODULE, 0); - if (!card) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; err = snd_ali_create(card, pci, pcm_channels, spdif, &codec); if (err < 0) diff --git a/sound/pci/als300.c b/sound/pci/als300.c index 8df6824b51c..f557c155db4 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c @@ -812,10 +812,10 @@ static int __devinit snd_als300_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (card == NULL) - return -ENOMEM; + if (err < 0) + return err; chip_type = pci_id->driver_data; diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index ba570053d4d..542a0c65a92 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c @@ -889,12 +889,13 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci, pci_write_config_word(pci, PCI_COMMAND, word | PCI_COMMAND_IO); pci_set_master(pci); - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(*acard) /* private_data: acard */); - if (card == NULL) { + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(*acard) /* private_data: acard */, + &card); + if (err < 0) { pci_release_regions(pci); pci_disable_device(pci); - return -ENOMEM; + return err; } acard = card->private_data; diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 226fe8237d3..9ce8548c03e 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -1645,9 +1645,9 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci, struct atiixp *chip; int err; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; strcpy(card->driver, spdif_aclink ? "ATIIXP" : "ATIIXP-SPDMA"); strcpy(card->shortname, "ATI IXP"); diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index 0e6e5cc1c50..c3136cccc55 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -1288,9 +1288,9 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci, struct atiixp_modem *chip; int err; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; strcpy(card->driver, "ATIIXP-MODEM"); strcpy(card->shortname, "ATI IXP Modem"); diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c index a36d4d1fd41..9ec122383ee 100644 --- a/sound/pci/au88x0/au88x0.c +++ b/sound/pci/au88x0/au88x0.c @@ -250,9 +250,9 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) return -ENOENT; } // (2) - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; // (3) if ((err = snd_vortex_create(card, pci, &chip)) < 0) { diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c index 3f00ddf450f..eefcbf648ee 100644 --- a/sound/pci/aw2/aw2-alsa.c +++ b/sound/pci/aw2/aw2-alsa.c @@ -368,9 +368,9 @@ static int __devinit snd_aw2_probe(struct pci_dev *pci, } /* (2) Create card instance */ - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; /* (3) Create main component */ err = snd_aw2_create(card, pci, &chip); diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 333007c523a..1df96e76c48 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -2216,9 +2216,9 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; strcpy(card->driver, "AZF3328"); strcpy(card->shortname, "Aztech AZF3328 (PCI168)"); diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 1aa1c040254..a299340519d 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -888,9 +888,9 @@ static int __devinit snd_bt87x_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (!card) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; err = snd_bt87x_create(card, pci, &chip); if (err < 0) diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 0e62205d408..b116456e770 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -1707,9 +1707,9 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; err = snd_ca0106_create(dev, card, pci, &chip); if (err < 0) diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 1a74ca62c31..c7899c32aba 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -3272,9 +3272,9 @@ static int __devinit snd_cmipci_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; switch (pci->device) { case PCI_DEVICE_ID_CMEDIA_CM8738: diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index 192e7842e18..b9b07f46463 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -1925,9 +1925,9 @@ static int __devinit snd_cs4281_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if ((err = snd_cs4281_create(card, pci, &chip, dual_codec[dev])) < 0) { snd_card_free(card); diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c index e876b3263e4..c9b3e3d48cb 100644 --- a/sound/pci/cs46xx/cs46xx.c +++ b/sound/pci/cs46xx/cs46xx.c @@ -88,9 +88,9 @@ static int __devinit snd_card_cs46xx_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if ((err = snd_cs46xx_create(card, pci, external_amp[dev], thinkpad[dev], &chip)) < 0) { diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c index 6dea5b5cc77..dc464321d0f 100644 --- a/sound/pci/cs5530.c +++ b/sound/pci/cs5530.c @@ -258,10 +258,10 @@ static int __devinit snd_cs5530_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (card == NULL) - return -ENOMEM; + if (err < 0) + return err; err = snd_cs5530_create(card, pci, &chip); if (err < 0) { diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index 826e6dec2e9..ac1d72e0a1e 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c @@ -353,9 +353,9 @@ static int __devinit snd_cs5535audio_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if ((err = snd_cs5535audio_create(card, pci, &cs5535au)) < 0) goto probefail_out; diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index 8dbc5c4ba42..9d015a76eb6 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c @@ -1997,9 +1997,9 @@ static int __devinit snd_echo_probe(struct pci_dev *pci, DE_INIT(("Echoaudio driver starting...\n")); i = 0; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; snd_card_set_dev(card, &pci->dev); diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 8354c1a8331..c7f3b994101 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c @@ -114,9 +114,9 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if (max_buffer_size[dev] < 32) max_buffer_size[dev] = 32; else if (max_buffer_size[dev] > 1024) diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index 5ff4dbb62da..31542adc6b7 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c @@ -1544,9 +1544,9 @@ static int __devinit snd_emu10k1x_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if ((err = snd_emu10k1x_create(card, pci, &chip)) < 0) { snd_card_free(card); diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 9bf95367c88..e00614cbcef 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -2409,9 +2409,9 @@ static int __devinit snd_audiopci_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if ((err = snd_ensoniq_create(card, pci, &ensoniq)) < 0) { snd_card_free(card); diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 4cd9a1faaec..34a78afc26d 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -1799,9 +1799,9 @@ static int __devinit snd_es1938_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; for (idx = 0; idx < 5; idx++) { if (pci_resource_start(pci, idx) == 0 || !(pci_resource_flags(pci, idx) & IORESOURCE_IO)) { diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index e9c3794bbcb..dc97e811614 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -2645,9 +2645,9 @@ static int __devinit snd_es1968_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (!card) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if (total_bufsize[dev] < 128) total_bufsize[dev] = 128; diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index c129f9e2072..60cdb9e0b68 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -1468,9 +1468,9 @@ static int __devinit snd_card_fm801_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if ((err = snd_fm801_create(card, pci, tea575x_tuner[dev], &chip)) < 0) { snd_card_free(card); return err; diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index f04de115ee1..ad5df2ae6f7 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2335,10 +2335,10 @@ static int __devinit azx_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (!card) { + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) { snd_printk(KERN_ERR SFX "Error creating card!\n"); - return -ENOMEM; + return err; } err = azx_create(card, pci, dev, pci_id->driver_data, &chip); diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 58d7cda03de..bab1c700f49 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -2648,9 +2648,9 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; strcpy(card->driver, "ICE1712"); strcpy(card->shortname, "ICEnsemble ICE1712"); diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index bb8d8c766b9..7ff36d3f0f4 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -2456,9 +2456,9 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; strcpy(card->driver, "ICE1724"); strcpy(card->shortname, "ICEnsemble ICE1724"); diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 19d3391e229..671ff65db02 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -3058,9 +3058,9 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci, int err; struct shortname_table *name; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; if (spdif_aclink < 0) spdif_aclink = check_default_spdif_aclink(pci); diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 93449e46456..33a843c1931 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -1269,9 +1269,9 @@ static int __devinit snd_intel8x0m_probe(struct pci_dev *pci, int err; struct shortname_table *name; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; strcpy(card->driver, "ICH-MODEM"); strcpy(card->shortname, "Intel ICH"); diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 5f8006b4275..8b79969034b 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -2443,9 +2443,9 @@ snd_korg1212_probe(struct pci_dev *pci, dev++; return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if ((err = snd_korg1212_create(card, pci, &korg1212)) < 0) { snd_card_free(card); diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 59bbaf8f3e5..70141548f25 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -2691,9 +2691,9 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; switch (pci->device) { case PCI_DEVICE_ID_ESS_ALLEGRO: diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index f23a73577c2..bfc19e36c4b 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -1365,12 +1365,12 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci, else idx = index[dev] + i; snprintf(tmpid, sizeof(tmpid), "%s-%d", id[dev] ? id[dev] : "MIXART", i); - card = snd_card_new(idx, tmpid, THIS_MODULE, 0); + err = snd_card_create(idx, tmpid, THIS_MODULE, 0, &card); - if (! card) { + if (err < 0) { snd_printk(KERN_ERR "cannot allocate the card %d\n", i); snd_mixart_free(mgr); - return -ENOMEM; + return err; } strcpy(card->driver, CARD_NAME); diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 50c9f8a0508..522a040855d 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -1668,9 +1668,9 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci, } } - card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; switch (pci->device) { case PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO: diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index 84f481d41ef..9c81e0b0511 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c @@ -459,10 +459,10 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, struct oxygen *chip; int err; - card = snd_card_new(index, id, model->owner, - sizeof *chip + model->model_data_size); - if (!card) - return -ENOMEM; + err = snd_card_create(index, id, model->owner, + sizeof(*chip) + model->model_data_size, &card); + if (err < 0) + return err; chip = card->private_data; chip->card = card; diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index 27cf2c28d11..7f95459c8b1 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c @@ -1510,12 +1510,12 @@ static int __devinit pcxhr_probe(struct pci_dev *pci, snprintf(tmpid, sizeof(tmpid), "%s-%d", id[dev] ? id[dev] : card_name, i); - card = snd_card_new(idx, tmpid, THIS_MODULE, 0); + err = snd_card_create(idx, tmpid, THIS_MODULE, 0, &card); - if (! card) { + if (err < 0) { snd_printk(KERN_ERR "cannot allocate the card %d\n", i); pcxhr_free(mgr); - return -ENOMEM; + return err; } strcpy(card->driver, DRIVER_NAME); diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index 3caacfb9d8e..6f1034417a0 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -2102,9 +2102,9 @@ snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if ((err = snd_riptide_create(card, pci, &chip)) < 0) { snd_card_free(card); return err; diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index e7ef3a1a25a..d7b966e7c4c 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -1941,9 +1941,10 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) return -ENOENT; } - if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct rme32))) == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct rme32), &card); + if (err < 0) + return err; card->private_free = snd_rme32_card_free; rme32 = (struct rme32 *) card->private_data; rme32->card = card; diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 3fdd488d097..55fb1c131f5 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -2348,9 +2348,10 @@ snd_rme96_probe(struct pci_dev *pci, dev++; return -ENOENT; } - if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct rme96))) == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct rme96), &card); + if (err < 0) + return err; card->private_free = snd_rme96_card_free; rme96 = (struct rme96 *)card->private_data; rme96->card = card; diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 44d0c15e2b7..05b3f795a16 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -5158,8 +5158,10 @@ static int __devinit snd_hdsp_probe(struct pci_dev *pci, return -ENOENT; } - if (!(card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct hdsp)))) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct hdsp), &card); + if (err < 0) + return err; hdsp = (struct hdsp *) card->private_data; card->private_free = snd_hdsp_card_free; diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 71231cf1b2b..d4b4e0d0fee 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -4503,10 +4503,10 @@ static int __devinit snd_hdspm_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], - THIS_MODULE, sizeof(struct hdspm)); - if (!card) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], + THIS_MODULE, sizeof(struct hdspm), &card); + if (err < 0) + return err; hdspm = card->private_data; card->private_free = snd_hdspm_card_free; diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 2570907134d..bc539abb210 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c @@ -2594,11 +2594,11 @@ static int __devinit snd_rme9652_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_rme9652)); + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_rme9652), &card); - if (!card) - return -ENOMEM; + if (err < 0) + return err; rme9652 = (struct snd_rme9652 *) card->private_data; card->private_free = snd_rme9652_card_free; diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index df2007e3be7..baf6d8e3dab 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c @@ -1387,9 +1387,8 @@ static int __devinit snd_sis7019_probe(struct pci_dev *pci, if (!enable) goto error_out; - rc = -ENOMEM; - card = snd_card_new(index, id, THIS_MODULE, sizeof(*sis)); - if (!card) + rc = snd_card_create(index, id, THIS_MODULE, sizeof(*sis), &card); + if (rc < 0) goto error_out; strcpy(card->driver, "SiS7019"); diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index cd408b86c83..c5601b0ad7c 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -1423,9 +1423,9 @@ static int __devinit snd_sonic_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; for (idx = 0; idx < 5; idx++) { if (pci_resource_start(pci, idx) == 0 || !(pci_resource_flags(pci, idx) & IORESOURCE_IO)) { diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index d94b16ffb38..21cef97d478 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c @@ -89,9 +89,9 @@ static int __devinit snd_trident_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if ((err = snd_trident_create(card, pci, pcm_channels[dev], diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 1aafe956ee2..d8705547dae 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -2433,9 +2433,9 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci, unsigned int i; int err; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; card_type = pci_id->driver_data; switch (card_type) { diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 5bd79d2a5a1..c086b762c15 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -1167,9 +1167,9 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci, unsigned int i; int err; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; card_type = pci_id->driver_data; switch (card_type) { diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index acc352f4a44..fc9136c3e0d 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c @@ -204,9 +204,9 @@ static int __devinit snd_vx222_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; switch ((int)pci_id->driver_data) { case VX_PCI_VX222_OLD: diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index 2631a554845..4af66661f9b 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c @@ -187,9 +187,9 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; switch (pci_id->device) { case 0x0004: str = "YMF724"; model = "DS-1"; break; -- GitLab From bd7dd77c2a05c530684eea2e3af16449ae9c5d52 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 28 Dec 2008 16:45:02 +0100 Subject: [PATCH 0115/4982] ALSA: Convert to snd_card_create() in other sound/* Convert from snd_card_new() to the new snd_card_create() function in other sound subdirectories. Signed-off-by: Takashi Iwai --- sound/aoa/core/alsa.c | 7 ++++--- sound/arm/aaci.c | 7 ++++--- sound/arm/pxa2xx-ac97.c | 7 +++---- sound/arm/sa11xx-uda1341.c | 7 ++++--- sound/drivers/dummy.c | 8 ++++---- sound/drivers/ml403-ac97cr.c | 6 +++--- sound/drivers/mpu401/mpu401.c | 6 +++--- sound/drivers/mtpav.c | 6 +++--- sound/drivers/mts64.c | 6 +++--- sound/drivers/pcsp/pcsp.c | 6 +++--- sound/drivers/portman2x4.c | 6 +++--- sound/drivers/serial-u16550.c | 6 +++--- sound/drivers/virmidi.c | 8 ++++---- sound/mips/au1x00.c | 7 ++++--- sound/mips/hal2.c | 6 +++--- sound/mips/sgio2audio.c | 6 +++--- sound/parisc/harmony.c | 6 +++--- sound/pcmcia/pdaudiocf/pdaudiocf.c | 8 ++++---- sound/pcmcia/vx/vxpocket.c | 8 ++++---- sound/ppc/powermac.c | 6 +++--- sound/ppc/snd_ps3.c | 6 ++---- sound/sh/aica.c | 8 ++++---- sound/soc/soc-core.c | 8 ++++---- sound/sparc/amd7930.c | 7 ++++--- sound/sparc/cs4231.c | 9 +++++---- sound/sparc/dbri.c | 8 ++++---- sound/spi/at73c213.c | 7 +++---- sound/usb/caiaq/caiaq-device.c | 7 ++++--- sound/usb/usbaudio.c | 6 +++--- sound/usb/usx2y/us122l.c | 8 +++++--- sound/usb/usx2y/usbusx2y.c | 7 +++++-- 31 files changed, 111 insertions(+), 103 deletions(-) diff --git a/sound/aoa/core/alsa.c b/sound/aoa/core/alsa.c index 61785046358..0fa3855b479 100644 --- a/sound/aoa/core/alsa.c +++ b/sound/aoa/core/alsa.c @@ -23,9 +23,10 @@ int aoa_alsa_init(char *name, struct module *mod, struct device *dev) /* cannot be EEXIST due to usage in aoa_fabric_register */ return -EBUSY; - alsa_card = snd_card_new(index, name, mod, sizeof(struct aoa_card)); - if (!alsa_card) - return -ENOMEM; + err = snd_card_create(index, name, mod, sizeof(struct aoa_card), + &alsa_card); + if (err < 0) + return err; aoa_card = alsa_card->private_data; aoa_card->alsa_card = alsa_card; alsa_card->dev = dev; diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index 89096e811a4..7d39aac9ec1 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c @@ -995,10 +995,11 @@ static struct aaci * __devinit aaci_init_card(struct amba_device *dev) { struct aaci *aaci; struct snd_card *card; + int err; - card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, - THIS_MODULE, sizeof(struct aaci)); - if (card == NULL) + err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, + THIS_MODULE, sizeof(struct aaci), &card); + if (err < 0) return NULL; card->private_free = aaci_free_card; diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index 85cf591d4e1..7ed100c80a5 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c @@ -173,10 +173,9 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev) struct snd_ac97_template ac97_template; int ret; - ret = -ENOMEM; - card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, - THIS_MODULE, 0); - if (!card) + ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, + THIS_MODULE, 0, &card); + if (ret < 0) goto err; card->dev = &dev->dev; diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c index 1dcd51d81d1..51d708c31e6 100644 --- a/sound/arm/sa11xx-uda1341.c +++ b/sound/arm/sa11xx-uda1341.c @@ -887,9 +887,10 @@ static int __devinit sa11xx_uda1341_probe(struct platform_device *devptr) struct sa11xx_uda1341 *chip; /* register the soundcard */ - card = snd_card_new(-1, id, THIS_MODULE, sizeof(struct sa11xx_uda1341)); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(-1, id, THIS_MODULE, + sizeof(struct sa11xx_uda1341), &card); + if (err < 0) + return err; chip = card->private_data; spin_lock_init(&chip->s[0].dma_lock); diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index 73be7e14a60..54239d2e099 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -588,10 +588,10 @@ static int __devinit snd_dummy_probe(struct platform_device *devptr) int idx, err; int dev = devptr->id; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_dummy)); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_dummy), &card); + if (err < 0) + return err; dummy = card->private_data; dummy->card = card; for (idx = 0; idx < MAX_PCM_DEVICES && idx < pcm_devs[dev]; idx++) { diff --git a/sound/drivers/ml403-ac97cr.c b/sound/drivers/ml403-ac97cr.c index 7783843ca9a..1950ffce2b5 100644 --- a/sound/drivers/ml403-ac97cr.c +++ b/sound/drivers/ml403-ac97cr.c @@ -1279,9 +1279,9 @@ static int __devinit snd_ml403_ac97cr_probe(struct platform_device *pfdev) if (!enable[dev]) return -ENOENT; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; err = snd_ml403_ac97cr_create(card, pfdev, &ml403_ac97cr); if (err < 0) { PDEBUG(INIT_FAILURE, "probe(): create failed!\n"); diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c index 5b996f3faba..149d05a8202 100644 --- a/sound/drivers/mpu401/mpu401.c +++ b/sound/drivers/mpu401/mpu401.c @@ -73,9 +73,9 @@ static int snd_mpu401_create(int dev, struct snd_card **rcard) snd_printk(KERN_ERR "the uart_enter option is obsolete; remove it\n"); *rcard = NULL; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; strcpy(card->driver, "MPU-401 UART"); strcpy(card->shortname, card->driver); sprintf(card->longname, "%s at %#lx, ", card->shortname, port[dev]); diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c index 5b89c0883d6..c3e9833dcfd 100644 --- a/sound/drivers/mtpav.c +++ b/sound/drivers/mtpav.c @@ -696,9 +696,9 @@ static int __devinit snd_mtpav_probe(struct platform_device *dev) int err; struct mtpav *mtp_card; - card = snd_card_new(index, id, THIS_MODULE, sizeof(*mtp_card)); - if (! card) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, sizeof(*mtp_card), &card); + if (err < 0) + return err; mtp_card = card->private_data; spin_lock_init(&mtp_card->spinlock); diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c index 87ba1ddc011..33d9db782e0 100644 --- a/sound/drivers/mts64.c +++ b/sound/drivers/mts64.c @@ -957,10 +957,10 @@ static int __devinit snd_mts64_probe(struct platform_device *pdev) if ((err = snd_mts64_probe_port(p)) < 0) return err; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) { + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) { snd_printd("Cannot create card\n"); - return -ENOMEM; + return err; } strcpy(card->driver, DRIVER_NAME); strcpy(card->shortname, "ESI " CARD_NAME); diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c index a4049eb94d3..aa2ae07a76d 100644 --- a/sound/drivers/pcsp/pcsp.c +++ b/sound/drivers/pcsp/pcsp.c @@ -98,9 +98,9 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev) hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); pcsp_chip.timer.function = pcsp_do_timer; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (!card) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; err = snd_pcsp_create(card); if (err < 0) { diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c index b1c047ec19a..60158e2e0ea 100644 --- a/sound/drivers/portman2x4.c +++ b/sound/drivers/portman2x4.c @@ -746,10 +746,10 @@ static int __devinit snd_portman_probe(struct platform_device *pdev) if ((err = snd_portman_probe_port(p)) < 0) return err; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) { + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) { snd_printd("Cannot create card\n"); - return -ENOMEM; + return err; } strcpy(card->driver, DRIVER_NAME); strcpy(card->shortname, CARD_NAME); diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index d8aab9da97c..891d081e482 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c @@ -936,9 +936,9 @@ static int __devinit snd_serial_probe(struct platform_device *devptr) return -ENODEV; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; strcpy(card->driver, "Serial"); strcpy(card->shortname, "Serial MIDI (UART16550A)"); diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c index f79e3614079..6f48711818f 100644 --- a/sound/drivers/virmidi.c +++ b/sound/drivers/virmidi.c @@ -90,10 +90,10 @@ static int __devinit snd_virmidi_probe(struct platform_device *devptr) int idx, err; int dev = devptr->id; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_virmidi)); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_card_virmidi), &card); + if (err < 0) + return err; vmidi = (struct snd_card_virmidi *)card->private_data; vmidi->card = card; diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c index 1881cec11e7..99e1391b2eb 100644 --- a/sound/mips/au1x00.c +++ b/sound/mips/au1x00.c @@ -636,9 +636,10 @@ au1000_init(void) struct snd_card *card; struct snd_au1000 *au1000; - card = snd_card_new(-1, "AC97", THIS_MODULE, sizeof(struct snd_au1000)); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(-1, "AC97", THIS_MODULE, + sizeof(struct snd_au1000), &card); + if (err < 0) + return err; card->private_free = snd_au1000_free; au1000 = card->private_data; diff --git a/sound/mips/hal2.c b/sound/mips/hal2.c index db495be0186..c52691c2fc4 100644 --- a/sound/mips/hal2.c +++ b/sound/mips/hal2.c @@ -878,9 +878,9 @@ static int __devinit hal2_probe(struct platform_device *pdev) struct snd_hal2 *chip; int err; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; err = hal2_create(card, &chip); if (err < 0) { diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c index 4c63504348d..66f3b48ceaf 100644 --- a/sound/mips/sgio2audio.c +++ b/sound/mips/sgio2audio.c @@ -936,9 +936,9 @@ static int __devinit snd_sgio2audio_probe(struct platform_device *pdev) struct snd_sgio2audio *chip; int err; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; err = snd_sgio2audio_create(card, &chip); if (err < 0) { diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c index 41f870f8a11..6055fd6d3b3 100644 --- a/sound/parisc/harmony.c +++ b/sound/parisc/harmony.c @@ -975,9 +975,9 @@ snd_harmony_probe(struct parisc_device *padev) struct snd_card *card; struct snd_harmony *h; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; err = snd_harmony_create(card, padev, &h); if (err < 0) diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index 819aaaac432..183f6615c68 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c @@ -91,7 +91,7 @@ static int snd_pdacf_dev_free(struct snd_device *device) */ static int snd_pdacf_probe(struct pcmcia_device *link) { - int i; + int i, err; struct snd_pdacf *pdacf; struct snd_card *card; static struct snd_device_ops ops = { @@ -112,10 +112,10 @@ static int snd_pdacf_probe(struct pcmcia_device *link) return -ENODEV; /* disabled explicitly */ /* ok, create a card instance */ - card = snd_card_new(index[i], id[i], THIS_MODULE, 0); - if (card == NULL) { + err = snd_card_create(index[i], id[i], THIS_MODULE, 0, &card); + if (err < 0) { snd_printk(KERN_ERR "pdacf: cannot create a card instance\n"); - return -ENOMEM; + return err; } pdacf = snd_pdacf_create(card); diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index 706602a4060..087ded8a8d7 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c @@ -292,7 +292,7 @@ static int vxpocket_probe(struct pcmcia_device *p_dev) { struct snd_card *card; struct snd_vxpocket *vxp; - int i; + int i, err; /* find an empty slot from the card list */ for (i = 0; i < SNDRV_CARDS; i++) { @@ -307,10 +307,10 @@ static int vxpocket_probe(struct pcmcia_device *p_dev) return -ENODEV; /* disabled explicitly */ /* ok, create a card instance */ - card = snd_card_new(index[i], id[i], THIS_MODULE, 0); - if (card == NULL) { + err = snd_card_create(index[i], id[i], THIS_MODULE, 0, &card); + if (err < 0) { snd_printk(KERN_ERR "vxpocket: cannot create a card instance\n"); - return -ENOMEM; + return err; } vxp = snd_vxpocket_new(card, ibl[i], p_dev); diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c index c936225771b..2e18ed0ea89 100644 --- a/sound/ppc/powermac.c +++ b/sound/ppc/powermac.c @@ -58,9 +58,9 @@ static int __init snd_pmac_probe(struct platform_device *devptr) char *name_ext; int err; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; if ((err = snd_pmac_new(card, &chip)) < 0) goto __error; diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c index 8f9e3859c37..ef2c3f41717 100644 --- a/sound/ppc/snd_ps3.c +++ b/sound/ppc/snd_ps3.c @@ -969,11 +969,9 @@ static int __init snd_ps3_driver_probe(struct ps3_system_bus_device *dev) } /* create card instance */ - the_card.card = snd_card_new(index, id, THIS_MODULE, 0); - if (!the_card.card) { - ret = -ENXIO; + ret = snd_card_create(index, id, THIS_MODULE, 0, &the_card.card); + if (ret < 0) goto clean_irq; - } strcpy(the_card.card->driver, "PS3"); strcpy(the_card.card->shortname, "PS3"); diff --git a/sound/sh/aica.c b/sound/sh/aica.c index 7c920f3e7fe..f551233c5a0 100644 --- a/sound/sh/aica.c +++ b/sound/sh/aica.c @@ -609,11 +609,11 @@ static int __devinit snd_aica_probe(struct platform_device *devptr) dreamcastcard = kmalloc(sizeof(struct snd_card_aica), GFP_KERNEL); if (unlikely(!dreamcastcard)) return -ENOMEM; - dreamcastcard->card = - snd_card_new(index, SND_AICA_DRIVER, THIS_MODULE, 0); - if (unlikely(!dreamcastcard->card)) { + err = snd_card_create(index, SND_AICA_DRIVER, THIS_MODULE, 0, + &dreamcastcard->card); + if (unlikely(err < 0)) { kfree(dreamcastcard); - return -ENODEV; + return err; } strcpy(dreamcastcard->card->driver, "snd_aica"); strcpy(dreamcastcard->card->shortname, SND_AICA_DRIVER); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 6cbe7e82f23..318dfdd54d7 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1311,17 +1311,17 @@ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid) { struct snd_soc_codec *codec = socdev->codec; struct snd_soc_card *card = socdev->card; - int ret = 0, i; + int ret, i; mutex_lock(&codec->mutex); /* register a sound card */ - codec->card = snd_card_new(idx, xid, codec->owner, 0); - if (!codec->card) { + ret = snd_card_create(idx, xid, codec->owner, 0, &codec->card); + if (ret < 0) { printk(KERN_ERR "asoc: can't create sound card for codec %s\n", codec->name); mutex_unlock(&codec->mutex); - return -ENODEV; + return ret; } codec->card->dev = socdev->dev; diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index f87933e4881..ba38912614b 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c @@ -1018,9 +1018,10 @@ static int __devinit amd7930_sbus_probe(struct of_device *op, const struct of_de return -ENOENT; } - card = snd_card_new(index[dev_num], id[dev_num], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev_num], id[dev_num], THIS_MODULE, 0, + &card); + if (err < 0) + return err; strcpy(card->driver, "AMD7930"); strcpy(card->shortname, "Sun AMD7930"); diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 41c38758747..7d93fa705cc 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -1563,6 +1563,7 @@ static int __init cs4231_attach_begin(struct snd_card **rcard) { struct snd_card *card; struct snd_cs4231 *chip; + int err; *rcard = NULL; @@ -1574,10 +1575,10 @@ static int __init cs4231_attach_begin(struct snd_card **rcard) return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_cs4231)); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_cs4231), &card); + if (err < 0) + return err; strcpy(card->driver, "CS4231"); strcpy(card->shortname, "Sun CS4231"); diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index 23ed6f04a71..af95ff1e126 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -2612,10 +2612,10 @@ static int __devinit dbri_probe(struct of_device *op, const struct of_device_id return -ENODEV; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_dbri)); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_dbri), &card); + if (err < 0) + return err; strcpy(card->driver, "DBRI"); strcpy(card->shortname, "Sun DBRI"); diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c index 09802e8a6fb..4c7b051f9d1 100644 --- a/sound/spi/at73c213.c +++ b/sound/spi/at73c213.c @@ -965,12 +965,11 @@ static int __devinit snd_at73c213_probe(struct spi_device *spi) return PTR_ERR(board->dac_clk); } - retval = -ENOMEM; - /* Allocate "card" using some unused identifiers. */ snprintf(id, sizeof id, "at73c213_%d", board->ssc_id); - card = snd_card_new(-1, id, THIS_MODULE, sizeof(struct snd_at73c213)); - if (!card) + retval = snd_card_create(-1, id, THIS_MODULE, + sizeof(struct snd_at73c213), &card); + if (retval < 0) goto out; chip = card->private_data; diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c index a62500e387a..63a2c1d5779 100644 --- a/sound/usb/caiaq/caiaq-device.c +++ b/sound/usb/caiaq/caiaq-device.c @@ -339,6 +339,7 @@ static void __devinit setup_card(struct snd_usb_caiaqdev *dev) static struct snd_card* create_card(struct usb_device* usb_dev) { int devnum; + int err; struct snd_card *card; struct snd_usb_caiaqdev *dev; @@ -349,9 +350,9 @@ static struct snd_card* create_card(struct usb_device* usb_dev) if (devnum >= SNDRV_CARDS) return NULL; - card = snd_card_new(index[devnum], id[devnum], THIS_MODULE, - sizeof(struct snd_usb_caiaqdev)); - if (!card) + err = snd_card_create(index[devnum], id[devnum], THIS_MODULE, + sizeof(struct snd_usb_caiaqdev), &card); + if (err < 0) return NULL; dev = caiaqdev(card); diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index c709b956322..eec32e1a302 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -3463,10 +3463,10 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, return -ENXIO; } - card = snd_card_new(index[idx], id[idx], THIS_MODULE, 0); - if (card == NULL) { + err = snd_card_create(index[idx], id[idx], THIS_MODULE, 0, &card); + if (err < 0) { snd_printk(KERN_ERR "cannot create card instance %d\n", idx); - return -ENOMEM; + return err; } chip = kzalloc(sizeof(*chip), GFP_KERNEL); diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c index 73e59f4403a..b21bb475c0f 100644 --- a/sound/usb/usx2y/us122l.c +++ b/sound/usb/usx2y/us122l.c @@ -482,14 +482,16 @@ static struct snd_card *usx2y_create_card(struct usb_device *device) { int dev; struct snd_card *card; + int err; + for (dev = 0; dev < SNDRV_CARDS; ++dev) if (enable[dev] && !snd_us122l_card_used[dev]) break; if (dev >= SNDRV_CARDS) return NULL; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct us122l)); - if (!card) + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct us122l), &card); + if (err < 0) return NULL; snd_us122l_card_used[US122L(card)->chip.index = dev] = 1; diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c index 11639bd72a5..b848a180638 100644 --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c @@ -337,13 +337,16 @@ static struct snd_card *usX2Y_create_card(struct usb_device *device) { int dev; struct snd_card * card; + int err; + for (dev = 0; dev < SNDRV_CARDS; ++dev) if (enable[dev] && !snd_usX2Y_card_used[dev]) break; if (dev >= SNDRV_CARDS) return NULL; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct usX2Ydev)); - if (!card) + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct usX2Ydev), &card); + if (err < 0) return NULL; snd_usX2Y_card_used[usX2Y(card)->chip.index = dev] = 1; card->private_free = snd_usX2Y_card_private_free; -- GitLab From d453379bc5d34d7f55b55931245de5ac1896fd8d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 28 Dec 2008 16:45:34 +0100 Subject: [PATCH 0116/4982] ALSA: Update description of snd_card_create() in documents Signed-off-by: Takashi Iwai --- .../alsa/DocBook/writing-an-alsa-driver.tmpl | 44 +++++++++++-------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index 87a7c07ab65..320384c1791 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -492,9 +492,9 @@ } /* (2) */ - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; /* (3) */ err = snd_mychip_create(card, pci, &chip); @@ -590,8 +590,9 @@ @@ -809,26 +810,28 @@ As mentioned above, to create a card instance, call - snd_card_new(). + snd_card_create(). - The function takes four arguments, the card-index number, the + The function takes five arguments, the card-index number, the id string, the module pointer (usually THIS_MODULE), - and the size of extra-data space. The last argument is used to + the size of extra-data space, and the pointer to return the + card instance. The extra_size argument is used to allocate card->private_data for the chip-specific data. Note that these data - are allocated by snd_card_new(). + are allocated by snd_card_create(). @@ -915,15 +918,16 @@
- 1. Allocating via <function>snd_card_new()</function>. + 1. Allocating via <function>snd_card_create()</function>. As mentioned above, you can pass the extra-data-length - to the 4th argument of snd_card_new(), i.e. + to the 4th argument of snd_card_create(), i.e. @@ -952,8 +956,8 @@ After allocating a card instance via - snd_card_new() (with - NULL on the 4th arg), call + snd_card_create() (with + 0 on the 4th arg), call kzalloc(). @@ -961,7 +965,7 @@ @@ -5750,8 +5754,9 @@ struct _snd_pcm_runtime { .... struct snd_card *card; struct mychip *chip; + int err; .... - card = snd_card_new(index[dev], id[dev], THIS_MODULE, NULL); + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); .... chip = kzalloc(sizeof(*chip), GFP_KERNEL); .... @@ -5763,7 +5768,7 @@ struct _snd_pcm_runtime { When you created the chip data with - snd_card_new(), it's anyway accessible + snd_card_create(), it's anyway accessible via private_data field. @@ -5775,9 +5780,10 @@ struct _snd_pcm_runtime { .... struct snd_card *card; struct mychip *chip; + int err; .... - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct mychip)); + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct mychip), &card); .... chip = card->private_data; .... -- GitLab From 3e7fb9f7ec00fd7cefd0d8e83df0cff86ce12515 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 28 Dec 2008 16:47:30 +0100 Subject: [PATCH 0117/4982] ALSA: Return proper error code at probe in sound/isa/* Some drivers in sound/isa/* don't handle the error code properly from snd_card_create(). This patch fixes these places. Signed-off-by: Takashi Iwai --- sound/isa/cs423x/cs4236.c | 25 +++++++++++++------------ sound/isa/es18xx.c | 27 ++++++++++++--------------- sound/isa/gus/interwave.c | 19 ++++++++++--------- sound/isa/opti9xx/opti92x-ad1848.c | 20 ++++++++++---------- sound/isa/sb/sb16.c | 19 ++++++++++--------- sound/isa/wavefront/wavefront.c | 19 ++++++++++--------- 6 files changed, 65 insertions(+), 64 deletions(-) diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index db830682804..f7845986f46 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c @@ -382,7 +382,7 @@ static void snd_card_cs4236_free(struct snd_card *card) release_and_free_resource(acard->res_sb_port); } -static struct snd_card *snd_cs423x_card_new(int dev) +static int snd_cs423x_card_new(int dev, struct snd_card **cardp) { struct snd_card *card; int err; @@ -390,9 +390,10 @@ static struct snd_card *snd_cs423x_card_new(int dev) err = snd_card_create(index[dev], id[dev], THIS_MODULE, sizeof(struct snd_card_cs4236), &card); if (err < 0) - return NULL; + return err; card->private_free = snd_card_cs4236_free; - return card; + *cardp = card; + return 0; } static int __devinit snd_cs423x_probe(struct snd_card *card, int dev) @@ -513,9 +514,9 @@ static int __devinit snd_cs423x_isa_probe(struct device *pdev, struct snd_card *card; int err; - card = snd_cs423x_card_new(dev); - if (! card) - return -ENOMEM; + err = snd_cs423x_card_new(dev, &card); + if (err < 0) + return err; snd_card_set_dev(card, pdev); if ((err = snd_cs423x_probe(card, dev)) < 0) { snd_card_free(card); @@ -595,9 +596,9 @@ static int __devinit snd_cs4232_pnpbios_detect(struct pnp_dev *pdev, if (dev >= SNDRV_CARDS) return -ENODEV; - card = snd_cs423x_card_new(dev); - if (! card) - return -ENOMEM; + err = snd_cs423x_card_new(dev, &card); + if (err < 0) + return err; if ((err = snd_card_cs4232_pnp(dev, card->private_data, pdev)) < 0) { printk(KERN_ERR "PnP BIOS detection failed for " IDENT "\n"); snd_card_free(card); @@ -657,9 +658,9 @@ static int __devinit snd_cs423x_pnpc_detect(struct pnp_card_link *pcard, if (dev >= SNDRV_CARDS) return -ENODEV; - card = snd_cs423x_card_new(dev); - if (! card) - return -ENOMEM; + res = snd_cs423x_card_new(dev, &card); + if (res < 0) + return res; if ((res = snd_card_cs423x_pnpc(dev, card->private_data, pcard, pid)) < 0) { printk(KERN_ERR "isapnp detection failed and probing for " IDENT " is not supported\n"); diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index c24c6322fcc..8cfbff73a83 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -2125,13 +2125,10 @@ static int __devinit snd_audiodrive_pnpc(int dev, struct snd_audiodrive *acard, #define is_isapnp_selected(dev) 0 #endif -static struct snd_card *snd_es18xx_card_new(int dev) +static int snd_es18xx_card_new(int dev, struct snd_card **cardp) { - struct snd_card *card; - if (snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_audiodrive), &card) < 0) - return NULL; - return card; + return snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_audiodrive), cardp); } static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev) @@ -2200,9 +2197,9 @@ static int __devinit snd_es18xx_isa_probe1(int dev, struct device *devptr) struct snd_card *card; int err; - card = snd_es18xx_card_new(dev); - if (! card) - return -ENOMEM; + err = snd_es18xx_card_new(dev, &card); + if (err < 0) + return err; snd_card_set_dev(card, devptr); if ((err = snd_audiodrive_probe(card, dev)) < 0) { snd_card_free(card); @@ -2306,9 +2303,9 @@ static int __devinit snd_audiodrive_pnp_detect(struct pnp_dev *pdev, if (dev >= SNDRV_CARDS) return -ENODEV; - card = snd_es18xx_card_new(dev); - if (! card) - return -ENOMEM; + err = snd_es18xx_card_new(dev, &card); + if (err < 0) + return err; if ((err = snd_audiodrive_pnp(dev, card->private_data, pdev)) < 0) { snd_card_free(card); return err; @@ -2365,9 +2362,9 @@ static int __devinit snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard, if (dev >= SNDRV_CARDS) return -ENODEV; - card = snd_es18xx_card_new(dev); - if (! card) - return -ENOMEM; + res = snd_es18xx_card_new(dev, &card); + if (res < 0) + return res; if ((res = snd_audiodrive_pnpc(dev, card->private_data, pcard, pid)) < 0) { snd_card_free(card); diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index e040c763891..50e429a120d 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c @@ -626,7 +626,7 @@ static void snd_interwave_free(struct snd_card *card) free_irq(iwcard->irq, (void *)iwcard); } -static struct snd_card *snd_interwave_card_new(int dev) +static int snd_interwave_card_new(int dev, struct snd_card **cardp) { struct snd_card *card; struct snd_interwave *iwcard; @@ -635,12 +635,13 @@ static struct snd_card *snd_interwave_card_new(int dev) err = snd_card_create(index[dev], id[dev], THIS_MODULE, sizeof(struct snd_interwave), &card); if (err < 0) - return NULL; + return err; iwcard = card->private_data; iwcard->card = card; iwcard->irq = -1; card->private_free = snd_interwave_free; - return card; + *cardp = card; + return 0; } static int __devinit snd_interwave_probe(struct snd_card *card, int dev) @@ -779,9 +780,9 @@ static int __devinit snd_interwave_isa_probe1(int dev, struct device *devptr) struct snd_card *card; int err; - card = snd_interwave_card_new(dev); - if (! card) - return -ENOMEM; + err = snd_interwave_card_new(dev, &card); + if (err < 0) + return err; snd_card_set_dev(card, devptr); if ((err = snd_interwave_probe(card, dev)) < 0) { @@ -877,9 +878,9 @@ static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard, if (dev >= SNDRV_CARDS) return -ENODEV; - card = snd_interwave_card_new(dev); - if (! card) - return -ENOMEM; + res = snd_interwave_card_new(dev, &card); + if (res < 0) + return res; if ((res = snd_interwave_pnp(dev, card->private_data, pcard, pid)) < 0) { snd_card_free(card); diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 5750f38bb79..87a4feb5010 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -830,17 +830,17 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) return snd_card_register(card); } -static struct snd_card *snd_opti9xx_card_new(void) +static int snd_opti9xx_card_new(struct snd_card **cardp) { struct snd_card *card; - int err; err = snd_card_create(index, id, THIS_MODULE, sizeof(struct snd_opti9xx), &card); if (err < 0) - return NULL; + return err; card->private_free = snd_card_opti9xx_free; - return card; + *cardp = card; + return 0; } static int __devinit snd_opti9xx_isa_match(struct device *devptr, @@ -905,9 +905,9 @@ static int __devinit snd_opti9xx_isa_probe(struct device *devptr, } #endif - card = snd_opti9xx_card_new(); - if (! card) - return -ENOMEM; + error = snd_opti9xx_card_new(&card); + if (error < 0) + return error; if ((error = snd_card_opti9xx_detect(card, card->private_data)) < 0) { snd_card_free(card); @@ -952,9 +952,9 @@ static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, return -EBUSY; if (! isapnp) return -ENODEV; - card = snd_opti9xx_card_new(); - if (! card) - return -ENOMEM; + error = snd_opti9xx_card_new(&card); + if (error < 0) + return error; chip = card->private_data; hw = snd_card_opti9xx_pnp(chip, pcard, pid); diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index adf4fdd2c4a..519c36346de 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c @@ -324,7 +324,7 @@ static void snd_sb16_free(struct snd_card *card) #define is_isapnp_selected(dev) 0 #endif -static struct snd_card *snd_sb16_card_new(int dev) +static int snd_sb16_card_new(int dev, struct snd_card **cardp) { struct snd_card *card; int err; @@ -332,9 +332,10 @@ static struct snd_card *snd_sb16_card_new(int dev) err = snd_card_create(index[dev], id[dev], THIS_MODULE, sizeof(struct snd_card_sb16), &card); if (err < 0) - return NULL; + return err; card->private_free = snd_sb16_free; - return card; + *cardp = card; + return 0; } static int __devinit snd_sb16_probe(struct snd_card *card, int dev) @@ -492,9 +493,9 @@ static int __devinit snd_sb16_isa_probe1(int dev, struct device *pdev) struct snd_card *card; int err; - card = snd_sb16_card_new(dev); - if (! card) - return -ENOMEM; + err = snd_sb16_card_new(dev, &card); + if (err < 0) + return err; acard = card->private_data; /* non-PnP FM port address is hardwired with base port address */ @@ -613,9 +614,9 @@ static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard, for ( ; dev < SNDRV_CARDS; dev++) { if (!enable[dev] || !isapnp[dev]) continue; - card = snd_sb16_card_new(dev); - if (! card) - return -ENOMEM; + res = snd_sb16_card_new(dev, &card); + if (res < 0) + return res; snd_card_set_dev(card, &pcard->card->dev); if ((res = snd_card_sb16_pnp(dev, card->private_data, pcard, pid)) < 0 || (res = snd_sb16_probe(card, dev)) < 0) { diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index 82b8fb74690..95898b2b7b5 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c @@ -338,7 +338,7 @@ snd_wavefront_free(struct snd_card *card) } } -static struct snd_card *snd_wavefront_card_new(int dev) +static int snd_wavefront_card_new(int dev, struct snd_card **cardp) { struct snd_card *card; snd_wavefront_card_t *acard; @@ -347,7 +347,7 @@ static struct snd_card *snd_wavefront_card_new(int dev) err = snd_card_create(index[dev], id[dev], THIS_MODULE, sizeof(snd_wavefront_card_t), &card); if (err < 0) - return NULL; + return err; acard = card->private_data; acard->wavefront.irq = -1; @@ -358,7 +358,8 @@ static struct snd_card *snd_wavefront_card_new(int dev) acard->wavefront.card = card; card->private_free = snd_wavefront_free; - return card; + *cardp = card; + return 0; } static int __devinit @@ -568,9 +569,9 @@ static int __devinit snd_wavefront_isa_probe(struct device *pdev, struct snd_card *card; int err; - card = snd_wavefront_card_new(dev); - if (! card) - return -ENOMEM; + err = snd_wavefront_card_new(dev, &card); + if (err < 0) + return err; snd_card_set_dev(card, pdev); if ((err = snd_wavefront_probe(card, dev)) < 0) { snd_card_free(card); @@ -617,9 +618,9 @@ static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard, if (dev >= SNDRV_CARDS) return -ENODEV; - card = snd_wavefront_card_new(dev); - if (! card) - return -ENOMEM; + res = snd_wavefront_card_new(dev, &card); + if (res < 0) + return res; if (snd_wavefront_pnp (dev, card->private_data, pcard, pid) < 0) { if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) { -- GitLab From 51721f70acaca5aa056b07c5cbe58e62662c068c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 28 Dec 2008 16:55:08 +0100 Subject: [PATCH 0118/4982] ALSA: Return proper error code at probe in sound/usb/* Some drivers in soudn/usb/* don't handle the error code properly from snd_card_create(). This patch fixes these places. Signed-off-by: Takashi Iwai --- sound/usb/caiaq/caiaq-device.c | 15 +++++----- sound/usb/usx2y/us122l.c | 51 +++++++++++++++++++++------------- sound/usb/usx2y/usbusx2y.c | 45 ++++++++++++++++++------------ 3 files changed, 67 insertions(+), 44 deletions(-) diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c index 63a2c1d5779..55a9075cb09 100644 --- a/sound/usb/caiaq/caiaq-device.c +++ b/sound/usb/caiaq/caiaq-device.c @@ -336,7 +336,7 @@ static void __devinit setup_card(struct snd_usb_caiaqdev *dev) log("Unable to set up control system (ret=%d)\n", ret); } -static struct snd_card* create_card(struct usb_device* usb_dev) +static int create_card(struct usb_device* usb_dev, struct snd_card **cardp) { int devnum; int err; @@ -348,12 +348,12 @@ static struct snd_card* create_card(struct usb_device* usb_dev) break; if (devnum >= SNDRV_CARDS) - return NULL; + return -ENODEV; err = snd_card_create(index[devnum], id[devnum], THIS_MODULE, sizeof(struct snd_usb_caiaqdev), &card); if (err < 0) - return NULL; + return err; dev = caiaqdev(card); dev->chip.dev = usb_dev; @@ -363,7 +363,8 @@ static struct snd_card* create_card(struct usb_device* usb_dev) spin_lock_init(&dev->spinlock); snd_card_set_dev(card, &usb_dev->dev); - return card; + *cardp = card; + return 0; } static int __devinit init_card(struct snd_usb_caiaqdev *dev) @@ -442,10 +443,10 @@ static int __devinit snd_probe(struct usb_interface *intf, struct snd_card *card; struct usb_device *device = interface_to_usbdev(intf); - card = create_card(device); + ret = create_card(device, &card); - if (!card) - return -ENOMEM; + if (ret < 0) + return ret; usb_set_intfdata(intf, card); ret = init_card(caiaqdev(card)); diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c index b21bb475c0f..98276aafefe 100644 --- a/sound/usb/usx2y/us122l.c +++ b/sound/usb/usx2y/us122l.c @@ -478,7 +478,7 @@ static bool us122l_create_card(struct snd_card *card) return true; } -static struct snd_card *usx2y_create_card(struct usb_device *device) +static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp) { int dev; struct snd_card *card; @@ -488,11 +488,11 @@ static struct snd_card *usx2y_create_card(struct usb_device *device) if (enable[dev] && !snd_us122l_card_used[dev]) break; if (dev >= SNDRV_CARDS) - return NULL; + return -ENODEV; err = snd_card_create(index[dev], id[dev], THIS_MODULE, sizeof(struct us122l), &card); if (err < 0) - return NULL; + return err; snd_us122l_card_used[US122L(card)->chip.index = dev] = 1; US122L(card)->chip.dev = device; @@ -511,46 +511,57 @@ static struct snd_card *usx2y_create_card(struct usb_device *device) US122L(card)->chip.dev->devnum ); snd_card_set_dev(card, &device->dev); - return card; + *cardp = card; + return 0; } -static void *us122l_usb_probe(struct usb_interface *intf, - const struct usb_device_id *device_id) +static int us122l_usb_probe(struct usb_interface *intf, + const struct usb_device_id *device_id, + struct snd_card **cardp) { struct usb_device *device = interface_to_usbdev(intf); - struct snd_card *card = usx2y_create_card(device); + struct snd_card *card; + int err; - if (!card) - return NULL; + err = usx2y_create_card(device, &card); + if (err < 0) + return err; - if (!us122l_create_card(card) || - snd_card_register(card) < 0) { + if (!us122l_create_card(card)) { snd_card_free(card); - return NULL; + return -EINVAL; + } + + err = snd_card_register(card); + if (err < 0) { + snd_card_free(card); + return err; } usb_get_dev(device); - return card; + *cardp = card; + return 0; } static int snd_us122l_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct snd_card *card; + int err; + snd_printdd(KERN_DEBUG"%p:%i\n", intf, intf->cur_altsetting->desc.bInterfaceNumber); if (intf->cur_altsetting->desc.bInterfaceNumber != 1) return 0; - card = us122l_usb_probe(usb_get_intf(intf), id); - - if (card) { - usb_set_intfdata(intf, card); - return 0; + err = us122l_usb_probe(usb_get_intf(intf), id, &card); + if (err < 0) { + usb_put_intf(intf); + return err; } - usb_put_intf(intf); - return -EIO; + usb_set_intfdata(intf, card); + return 0; } static void snd_us122l_disconnect(struct usb_interface *intf) diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c index b848a180638..af8b8495405 100644 --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c @@ -333,7 +333,7 @@ static struct usb_device_id snd_usX2Y_usb_id_table[] = { { /* terminator */ } }; -static struct snd_card *usX2Y_create_card(struct usb_device *device) +static int usX2Y_create_card(struct usb_device *device, struct snd_card **cardp) { int dev; struct snd_card * card; @@ -343,11 +343,11 @@ static struct snd_card *usX2Y_create_card(struct usb_device *device) if (enable[dev] && !snd_usX2Y_card_used[dev]) break; if (dev >= SNDRV_CARDS) - return NULL; + return -ENODEV; err = snd_card_create(index[dev], id[dev], THIS_MODULE, sizeof(struct usX2Ydev), &card); if (err < 0) - return NULL; + return err; snd_usX2Y_card_used[usX2Y(card)->chip.index = dev] = 1; card->private_free = snd_usX2Y_card_private_free; usX2Y(card)->chip.dev = device; @@ -365,26 +365,36 @@ static struct snd_card *usX2Y_create_card(struct usb_device *device) usX2Y(card)->chip.dev->bus->busnum, usX2Y(card)->chip.dev->devnum ); snd_card_set_dev(card, &device->dev); - return card; + *cardp = card; + return 0; } -static void *usX2Y_usb_probe(struct usb_device *device, struct usb_interface *intf, const struct usb_device_id *device_id) +static int usX2Y_usb_probe(struct usb_device *device, + struct usb_interface *intf, + const struct usb_device_id *device_id, + struct snd_card **cardp) { int err; struct snd_card * card; + + *cardp = NULL; if (le16_to_cpu(device->descriptor.idVendor) != 0x1604 || (le16_to_cpu(device->descriptor.idProduct) != USB_ID_US122 && le16_to_cpu(device->descriptor.idProduct) != USB_ID_US224 && - le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428) || - !(card = usX2Y_create_card(device))) - return NULL; + le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428)) + return -EINVAL; + + err = usX2Y_create_card(device, &card); + if (err < 0) + return err; if ((err = usX2Y_hwdep_new(card, device)) < 0 || (err = snd_card_register(card)) < 0) { snd_card_free(card); - return NULL; + return err; } - return card; + *cardp = card; + return 0; } /* @@ -392,13 +402,14 @@ static void *usX2Y_usb_probe(struct usb_device *device, struct usb_interface *in */ static int snd_usX2Y_probe(struct usb_interface *intf, const struct usb_device_id *id) { - void *chip; - chip = usX2Y_usb_probe(interface_to_usbdev(intf), intf, id); - if (chip) { - usb_set_intfdata(intf, chip); - return 0; - } else - return -EIO; + struct snd_card *card; + int err; + + err = usX2Y_usb_probe(interface_to_usbdev(intf), intf, id, &card); + if (err < 0) + return err; + dev_set_drvdata(&intf->dev, card); + return 0; } static void snd_usX2Y_disconnect(struct usb_interface *intf) -- GitLab From aa3d75d80de464cf23af1d068a5e22f1527b6957 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 28 Dec 2008 16:59:41 +0100 Subject: [PATCH 0119/4982] ALSA: pdaudiocf - Fix missing free in the error path Added the missing snd_card_free() in the error path of probe callback. Signed-off-by: Takashi Iwai --- sound/pcmcia/pdaudiocf/pdaudiocf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index 183f6615c68..ec51569fd50 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c @@ -119,8 +119,10 @@ static int snd_pdacf_probe(struct pcmcia_device *link) } pdacf = snd_pdacf_create(card); - if (! pdacf) + if (!pdacf) { + snd_card_free(card); return -EIO; + } if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, pdacf, &ops) < 0) { kfree(pdacf); -- GitLab From 2fa51107c9aa80ae95b4524198442cdea82d08a3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 28 Dec 2008 17:03:56 +0100 Subject: [PATCH 0120/4982] ALSA: Return proper error code at probe in sound/pcmcia/* Signed-off-by: Takashi Iwai --- sound/pcmcia/pdaudiocf/pdaudiocf.c | 7 ++++--- sound/pcmcia/vx/vxpocket.c | 24 ++++++++++++++---------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index ec51569fd50..7dea74b71cf 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c @@ -121,13 +121,14 @@ static int snd_pdacf_probe(struct pcmcia_device *link) pdacf = snd_pdacf_create(card); if (!pdacf) { snd_card_free(card); - return -EIO; + return -ENOMEM; } - if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, pdacf, &ops) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, pdacf, &ops); + if (err < 0) { kfree(pdacf); snd_card_free(card); - return -ENODEV; + return err; } snd_card_set_dev(card, &handle_to_dev(link)); diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index 087ded8a8d7..7445cc8a47d 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c @@ -130,23 +130,26 @@ static struct snd_vx_hardware vxp440_hw = { /* * create vxpocket instance */ -static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl, - struct pcmcia_device *link) +static int snd_vxpocket_new(struct snd_card *card, int ibl, + struct pcmcia_device *link, + struct snd_vxpocket **chip_ret) { struct vx_core *chip; struct snd_vxpocket *vxp; static struct snd_device_ops ops = { .dev_free = snd_vxpocket_dev_free, }; + int err; chip = snd_vx_create(card, &vxpocket_hw, &snd_vxpocket_ops, sizeof(struct snd_vxpocket) - sizeof(struct vx_core)); - if (! chip) - return NULL; + if (!chip) + return -ENOMEM; - if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { kfree(chip); - return NULL; + return err; } chip->ibl.size = ibl; @@ -169,7 +172,8 @@ static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl, link->conf.ConfigIndex = 1; link->conf.Present = PRESENT_OPTION; - return vxp; + *chip_ret = vxp; + return 0; } @@ -313,10 +317,10 @@ static int vxpocket_probe(struct pcmcia_device *p_dev) return err; } - vxp = snd_vxpocket_new(card, ibl[i], p_dev); - if (! vxp) { + err = snd_vxpocket_new(card, ibl[i], p_dev, &vxp); + if (err < 0) { snd_card_free(card); - return -ENODEV; + return err; } card->private_data = vxp; -- GitLab From 758021bfa9ea25c58e62d2f68512628b19502ce7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 12 Jan 2009 15:17:09 +0100 Subject: [PATCH 0121/4982] drivers/media: Convert to snd_card_create() Convert from snd_card_new() to the new snd_card_create() function. Signed-off-by: Takashi Iwai --- drivers/media/video/cx88/cx88-alsa.c | 7 ++++--- drivers/media/video/em28xx/em28xx-audio.c | 7 ++++--- drivers/media/video/saa7134/saa7134-alsa.c | 8 ++++---- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 66c755c116d..ce98d955231 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -803,9 +803,10 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci, return (-ENOENT); } - card = snd_card_new(index[devno], id[devno], THIS_MODULE, sizeof(snd_cx88_card_t)); - if (!card) - return (-ENOMEM); + err = snd_card_create(index[devno], id[devno], THIS_MODULE, + sizeof(snd_cx88_card_t), &card); + if (err < 0) + return err; card->private_free = snd_cx88_dev_free; diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index 94378ccb750..66579508e17 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -438,9 +438,10 @@ static int em28xx_audio_init(struct em28xx *dev) printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus " "Rechberger\n"); - card = snd_card_new(index[devnr], "Em28xx Audio", THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0, + &card); + if (err < 0) + return err; spin_lock_init(&adev->slock); err = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm); diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 26194a0ce92..482be1436e9 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -990,10 +990,10 @@ static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum) if (!enable[devnum]) return -ENODEV; - card = snd_card_new(index[devnum], id[devnum], THIS_MODULE, sizeof(snd_card_saa7134_t)); - - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[devnum], id[devnum], THIS_MODULE, + sizeof(snd_card_saa7134_t), &card); + if (err < 0) + return err; strcpy(card->driver, "SAA7134"); -- GitLab From 6ff1871617a3ea1eeaf88b42f652f9a311826bad Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 12 Jan 2009 15:18:28 +0100 Subject: [PATCH 0122/4982] drivers/staging: Convert to snd_card_create() for go7007 Convert from snd_card_new to the new snd_card_create() for go7007. Signed-off-by: Takashi Iwai --- drivers/staging/go7007/snd-go7007.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/staging/go7007/snd-go7007.c b/drivers/staging/go7007/snd-go7007.c index a7de401f61a..cd19be6c00e 100644 --- a/drivers/staging/go7007/snd-go7007.c +++ b/drivers/staging/go7007/snd-go7007.c @@ -248,10 +248,11 @@ int go7007_snd_init(struct go7007 *go) spin_lock_init(&gosnd->lock); gosnd->hw_ptr = gosnd->w_idx = gosnd->avail = 0; gosnd->capturing = 0; - gosnd->card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (gosnd->card == NULL) { + ret = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, + &gosnd->card); + if (ret < 0) { kfree(gosnd); - return -ENOMEM; + return ret; } ret = snd_device_new(gosnd->card, SNDRV_DEV_LOWLEVEL, go, &go7007_snd_device_ops); -- GitLab From 183c6e0fb4e39c860960de4abd7541bd260491bb Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 12 Jan 2009 15:19:08 +0100 Subject: [PATCH 0123/4982] drivers/usb/gadget: Convert to snd_card_create() Convert from snd_card_new() to the new snd_card_create() function for gmidi. Signed-off-by: Takashi Iwai --- drivers/usb/gadget/gmidi.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 60d3f9e9b51..14e09abbddf 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -1099,10 +1099,9 @@ static int gmidi_register_card(struct gmidi_device *dev) .dev_free = gmidi_snd_free, }; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (!card) { - ERROR(dev, "snd_card_new failed\n"); - err = -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) { + ERROR(dev, "snd_card_create failed\n"); goto fail; } dev->card = card; -- GitLab From 42bb8cc5e81028e217105299001070d57eb84ad7 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Fri, 9 Jan 2009 12:17:40 -0800 Subject: [PATCH 0124/4982] x86: hpet: allow force enable on ICH10 HPET Intel "Smackover" x58 BIOS don't have HPET enabled in the BIOS, so allow to force enable it at least. The register layout is the same as in other recent ICHs, so all the code can be reused. Using numerical PCI-ID because it's unlikely the PCI-ID will be used anywhere else. Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar --- arch/x86/kernel/quirks.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index 309949e9e1c..697d1b78cfb 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c @@ -172,7 +172,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_4, ich_force_enable_hpet); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_7, ich_force_enable_hpet); - +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x3a16, /* ICH10 */ + ich_force_enable_hpet); static struct pci_dev *cached_dev; -- GitLab From 0b0f0b1c2c87de299df6f92a8ffc0a73bd1bb960 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 11 Jan 2009 13:35:56 -0800 Subject: [PATCH 0125/4982] sparseirq: use kstat_irqs_cpu on non-x86 architectures too so we could move kstat_irqs array to irq_desc struct. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/alpha/kernel/irq.c | 2 +- arch/alpha/kernel/irq_alpha.c | 2 +- arch/arm/kernel/irq.c | 2 +- arch/arm/mach-ns9xxx/irq.c | 3 +-- arch/avr32/kernel/irq.c | 2 +- arch/cris/kernel/irq.c | 2 +- arch/mips/kernel/irq.c | 2 +- 7 files changed, 7 insertions(+), 8 deletions(-) diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c index 703731accda..430550bd1eb 100644 --- a/arch/alpha/kernel/irq.c +++ b/arch/alpha/kernel/irq.c @@ -90,7 +90,7 @@ show_interrupts(struct seq_file *p, void *v) seq_printf(p, "%10u ", kstat_irqs(irq)); #else for_each_online_cpu(j) - seq_printf(p, "%10u ", kstat_cpu(j).irqs[irq]); + seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); #endif seq_printf(p, " %14s", irq_desc[irq].chip->typename); seq_printf(p, " %c%s", diff --git a/arch/alpha/kernel/irq_alpha.c b/arch/alpha/kernel/irq_alpha.c index e16aeb6e79e..67c19f8a994 100644 --- a/arch/alpha/kernel/irq_alpha.c +++ b/arch/alpha/kernel/irq_alpha.c @@ -64,7 +64,7 @@ do_entInt(unsigned long type, unsigned long vector, smp_percpu_timer_interrupt(regs); cpu = smp_processor_id(); if (cpu != boot_cpuid) { - kstat_cpu(cpu).irqs[RTC_IRQ]++; + kstat_incr_irqs_this_cpu(RTC_IRQ, irq_to_desc(RTC_IRQ)); } else { handle_irq(RTC_IRQ); } diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 7141cee1fab..a285e4a636a 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -76,7 +76,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_printf(p, "%3d: ", i); for_each_present_cpu(cpu) - seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]); + seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu)); seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-"); seq_printf(p, " %s", action->name); for (action = action->next; action; action = action->next) diff --git a/arch/arm/mach-ns9xxx/irq.c b/arch/arm/mach-ns9xxx/irq.c index 22e0eb6e9ec..feb0e54a91d 100644 --- a/arch/arm/mach-ns9xxx/irq.c +++ b/arch/arm/mach-ns9xxx/irq.c @@ -63,7 +63,6 @@ static struct irq_chip ns9xxx_chip = { #else static void handle_prio_irq(unsigned int irq, struct irq_desc *desc) { - unsigned int cpu = smp_processor_id(); struct irqaction *action; irqreturn_t action_ret; @@ -72,7 +71,7 @@ static void handle_prio_irq(unsigned int irq, struct irq_desc *desc) BUG_ON(desc->status & IRQ_INPROGRESS); desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); - kstat_cpu(cpu).irqs[irq]++; + kstat_incr_irqs_this_cpu(irq, desc); action = desc->action; if (unlikely(!action || (desc->status & IRQ_DISABLED))) diff --git a/arch/avr32/kernel/irq.c b/arch/avr32/kernel/irq.c index a8e767d836a..9f572229d31 100644 --- a/arch/avr32/kernel/irq.c +++ b/arch/avr32/kernel/irq.c @@ -58,7 +58,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_printf(p, "%3d: ", i); for_each_online_cpu(cpu) - seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]); + seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu)); seq_printf(p, " %8s", irq_desc[i].chip->name ? : "-"); seq_printf(p, " %s", action->name); for (action = action->next; action; action = action->next) diff --git a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c index 2dfac8c7909..7f642fcffbf 100644 --- a/arch/cris/kernel/irq.c +++ b/arch/cris/kernel/irq.c @@ -66,7 +66,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_printf(p, "%10u ", kstat_irqs(i)); #else for_each_online_cpu(j) - seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); + seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); #endif seq_printf(p, " %14s", irq_desc[i].chip->typename); seq_printf(p, " %s", action->name); diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c index 98f336dc3cd..7b845ba9dff 100644 --- a/arch/mips/kernel/irq.c +++ b/arch/mips/kernel/irq.c @@ -108,7 +108,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_printf(p, "%10u ", kstat_irqs(i)); #else for_each_online_cpu(j) - seq_printf(p, "%10u ", kstat_cpu(i, j)); + seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); #endif seq_printf(p, " %14s", irq_desc[i].chip->name); seq_printf(p, " %s", action->name); -- GitLab From 23a22d57a8962479ca630c9542e62d6f86fdf927 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 12 Jan 2009 14:24:04 -0800 Subject: [PATCH 0126/4982] bzip2/lzma: comprehensible error messages for missing decompressor Instead of failing to identify a compressed image with a decompressor that we don't have compiled in, identify it and fail with a comprehensible panic message. Signed-off-by: H. Peter Anvin --- init/do_mounts_rd.c | 5 ++++- init/initramfs.c | 12 +++++++++++- lib/decompress.c | 16 ++++++++++------ 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c index a015e267fd1..91d0cfca507 100644 --- a/init/do_mounts_rd.c +++ b/init/do_mounts_rd.c @@ -79,9 +79,12 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) sys_read(fd, buf, size); *decompressor = decompress_method(buf, size, &compress_name); - if (*decompressor) { + if (compress_name) { printk(KERN_NOTICE "RAMDISK: %s image found at block %d\n", compress_name, start_block); + if (!*decompressor) + printk(KERN_CRIT "RAMDISK: %s decompressor not configured!\n", + compress_name); nblocks = 0; goto done; } diff --git a/init/initramfs.c b/init/initramfs.c index 76f4a012533..9a7290ec818 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -421,6 +421,8 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) { int written; decompress_fn decompress; + const char *compress_name; + static __initdata char msg_buf[64]; dry_run = check_only; header_buf = kmalloc(110, GFP_KERNEL); @@ -449,10 +451,18 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) continue; } this_header = 0; - decompress = decompress_method(buf, len, NULL); + decompress = decompress_method(buf, len, &compress_name); if (decompress) decompress(buf, len, NULL, flush_buffer, NULL, &my_inptr, error); + else if (compress_name) { + if (!message) { + snprintf(msg_buf, sizeof msg_buf, + "compression method %s not configured", + compress_name); + message = msg_buf; + } + } if (state != Reset) error("junk in compressed archive"); this_header = saved_offset + my_inptr; diff --git a/lib/decompress.c b/lib/decompress.c index edac55cc782..961f367320f 100644 --- a/lib/decompress.c +++ b/lib/decompress.c @@ -13,21 +13,25 @@ #include #include +#ifndef CONFIG_DECOMPRESS_GZIP +# define gunzip NULL +#endif +#ifndef CONFIG_DECOMPRESS_BZIP2 +# define bunzip2 NULL +#endif +#ifndef CONFIG_DECOMPRESS_LZMA +# define unlzma NULL +#endif + static const struct compress_format { unsigned char magic[2]; const char *name; decompress_fn decompressor; } compressed_formats[] = { -#ifdef CONFIG_DECOMPRESS_GZIP { {037, 0213}, "gzip", gunzip }, { {037, 0236}, "gzip", gunzip }, -#endif -#ifdef CONFIG_DECOMPRESS_BZIP2 { {0x42, 0x5a}, "bzip2", bunzip2 }, -#endif -#ifdef CONFIG_DECOMPRESS_LZMA { {0x5d, 0x00}, "lzma", unlzma }, -#endif { {0, 0}, NULL, NULL } }; -- GitLab From e65e49d0f3714f4a6a42f6f6a19926ba33fcda75 Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Mon, 12 Jan 2009 15:27:13 -0800 Subject: [PATCH 0127/4982] irq: update all arches for new irq_desc Impact: cleanup, update to new cpumask API Irq_desc.affinity and irq_desc.pending_mask are now cpumask_var_t's so access to them should be using the new cpumask API. Signed-off-by: Mike Travis --- arch/alpha/kernel/irq.c | 2 +- arch/arm/kernel/irq.c | 18 ++++++++++++------ arch/arm/oprofile/op_model_mpcore.c | 2 +- arch/blackfin/kernel/irqchip.c | 5 +++++ arch/ia64/kernel/iosapic.c | 2 +- arch/ia64/kernel/irq.c | 4 ++-- arch/ia64/kernel/msi_ia64.c | 4 ++-- arch/ia64/sn/kernel/msi_sn.c | 2 +- arch/mips/include/asm/irq.h | 2 +- arch/mips/kernel/irq-gic.c | 2 +- arch/mips/kernel/smtc.c | 2 +- arch/mips/mti-malta/malta-smtc.c | 5 +++-- arch/parisc/kernel/irq.c | 8 ++++---- arch/powerpc/kernel/irq.c | 2 +- arch/powerpc/platforms/pseries/xics.c | 5 +++-- arch/powerpc/sysdev/mpic.c | 3 ++- arch/sparc/kernel/irq_64.c | 5 +++-- 17 files changed, 44 insertions(+), 29 deletions(-) diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c index 703731accda..7bc7489223f 100644 --- a/arch/alpha/kernel/irq.c +++ b/arch/alpha/kernel/irq.c @@ -55,7 +55,7 @@ int irq_select_affinity(unsigned int irq) cpu = (cpu < (NR_CPUS-1) ? cpu + 1 : 0); last_cpu = cpu; - irq_desc[irq].affinity = cpumask_of_cpu(cpu); + cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu)); irq_desc[irq].chip->set_affinity(irq, cpumask_of(cpu)); return 0; } diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 7141cee1fab..4bb723eadad 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -104,6 +104,11 @@ static struct irq_desc bad_irq_desc = { .lock = SPIN_LOCK_UNLOCKED }; +#ifdef CONFIG_CPUMASK_OFFSTACK +/* We are not allocating bad_irq_desc.affinity or .pending_mask */ +#error "ARM architecture does not support CONFIG_CPUMASK_OFFSTACK." +#endif + /* * do_IRQ handles all hardware IRQ's. Decoded IRQs should not * come via this function. Instead, they should provide their @@ -161,7 +166,7 @@ void __init init_IRQ(void) irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_NOPROBE; #ifdef CONFIG_SMP - bad_irq_desc.affinity = CPU_MASK_ALL; + cpumask_setall(bad_irq_desc.affinity); bad_irq_desc.cpu = smp_processor_id(); #endif init_arch_irq(); @@ -191,15 +196,16 @@ void migrate_irqs(void) struct irq_desc *desc = irq_desc + i; if (desc->cpu == cpu) { - unsigned int newcpu = any_online_cpu(desc->affinity); - - if (newcpu == NR_CPUS) { + unsigned int newcpu = cpumask_any_and(desc->affinity, + cpu_online_mask); + if (newcpu >= nr_cpu_ids) { if (printk_ratelimit()) printk(KERN_INFO "IRQ%u no longer affine to CPU%u\n", i, cpu); - cpus_setall(desc->affinity); - newcpu = any_online_cpu(desc->affinity); + cpumask_setall(desc->affinity); + newcpu = cpumask_any_and(desc->affinity, + cpu_online_mask); } route_irq(desc, i, newcpu); diff --git a/arch/arm/oprofile/op_model_mpcore.c b/arch/arm/oprofile/op_model_mpcore.c index 6d6bd589924..853d42bb868 100644 --- a/arch/arm/oprofile/op_model_mpcore.c +++ b/arch/arm/oprofile/op_model_mpcore.c @@ -263,7 +263,7 @@ static void em_route_irq(int irq, unsigned int cpu) const struct cpumask *mask = cpumask_of(cpu); spin_lock_irq(&desc->lock); - desc->affinity = *mask; + cpumask_copy(desc->affinity, mask); desc->chip->set_affinity(irq, mask); spin_unlock_irq(&desc->lock); } diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c index ab8209cbbad..5780d6df154 100644 --- a/arch/blackfin/kernel/irqchip.c +++ b/arch/blackfin/kernel/irqchip.c @@ -69,6 +69,11 @@ static struct irq_desc bad_irq_desc = { #endif }; +#ifdef CONFIG_CPUMASK_OFFSTACK +/* We are not allocating a variable-sized bad_irq_desc.affinity */ +#error "Blackfin architecture does not support CONFIG_CPUMASK_OFFSTACK." +#endif + int show_interrupts(struct seq_file *p, void *v) { int i = *(loff_t *) v, j; diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index 5cfd3d91001..006ad366a45 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -880,7 +880,7 @@ iosapic_unregister_intr (unsigned int gsi) if (iosapic_intr_info[irq].count == 0) { #ifdef CONFIG_SMP /* Clear affinity */ - cpus_setall(idesc->affinity); + cpumask_setall(idesc->affinity); #endif /* Clear the interrupt information */ iosapic_intr_info[irq].dest = 0; diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c index a58f64ca9f0..226233a6fa1 100644 --- a/arch/ia64/kernel/irq.c +++ b/arch/ia64/kernel/irq.c @@ -103,7 +103,7 @@ static char irq_redir [NR_IRQS]; // = { [0 ... NR_IRQS-1] = 1 }; void set_irq_affinity_info (unsigned int irq, int hwid, int redir) { if (irq < NR_IRQS) { - cpumask_copy(&irq_desc[irq].affinity, + cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu_logical_id(hwid))); irq_redir[irq] = (char) (redir & 0xff); } @@ -148,7 +148,7 @@ static void migrate_irqs(void) if (desc->status == IRQ_PER_CPU) continue; - if (cpumask_any_and(&irq_desc[irq].affinity, cpu_online_mask) + if (cpumask_any_and(irq_desc[irq].affinity, cpu_online_mask) >= nr_cpu_ids) { /* * Save it for phase 2 processing diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c index 89033933903..dcb6b7c51ea 100644 --- a/arch/ia64/kernel/msi_ia64.c +++ b/arch/ia64/kernel/msi_ia64.c @@ -75,7 +75,7 @@ static void ia64_set_msi_irq_affinity(unsigned int irq, msg.data = data; write_msi_msg(irq, &msg); - irq_desc[irq].affinity = cpumask_of_cpu(cpu); + cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu)); } #endif /* CONFIG_SMP */ @@ -187,7 +187,7 @@ static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask) msg.address_lo |= MSI_ADDR_DESTID_CPU(cpu_physical_id(cpu)); dmar_msi_write(irq, &msg); - irq_desc[irq].affinity = *mask; + cpumask_copy(irq_desc[irq].affinity, mask); } #endif /* CONFIG_SMP */ diff --git a/arch/ia64/sn/kernel/msi_sn.c b/arch/ia64/sn/kernel/msi_sn.c index ca553b0429c..81e428943d7 100644 --- a/arch/ia64/sn/kernel/msi_sn.c +++ b/arch/ia64/sn/kernel/msi_sn.c @@ -205,7 +205,7 @@ static void sn_set_msi_irq_affinity(unsigned int irq, msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff); write_msi_msg(irq, &msg); - irq_desc[irq].affinity = *cpu_mask; + cpumask_copy(irq_desc[irq].affinity, cpu_mask); } #endif /* CONFIG_SMP */ diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h index abc62aa744a..3214ade02d1 100644 --- a/arch/mips/include/asm/irq.h +++ b/arch/mips/include/asm/irq.h @@ -66,7 +66,7 @@ extern void smtc_forward_irq(unsigned int irq); */ #define IRQ_AFFINITY_HOOK(irq) \ do { \ - if (!cpu_isset(smp_processor_id(), irq_desc[irq].affinity)) { \ + if (!cpumask_test_cpu(smp_processor_id(), irq_desc[irq].affinity)) {\ smtc_forward_irq(irq); \ irq_exit(); \ return; \ diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c index 494a49a317e..87deb8f6c45 100644 --- a/arch/mips/kernel/irq-gic.c +++ b/arch/mips/kernel/irq-gic.c @@ -187,7 +187,7 @@ static void gic_set_affinity(unsigned int irq, const struct cpumask *cpumask) set_bit(irq, pcpu_masks[first_cpu(tmp)].pcpu_mask); } - irq_desc[irq].affinity = *cpumask; + cpumask_copy(irq_desc[irq].affinity, cpumask); spin_unlock_irqrestore(&gic_lock, flags); } diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index b6cca01ff82..d2c1ab12425 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -686,7 +686,7 @@ void smtc_forward_irq(unsigned int irq) * and efficiency, we just pick the easiest one to find. */ - target = first_cpu(irq_desc[irq].affinity); + target = cpumask_first(irq_desc[irq].affinity); /* * We depend on the platform code to have correctly processed diff --git a/arch/mips/mti-malta/malta-smtc.c b/arch/mips/mti-malta/malta-smtc.c index aabd7274507..5ba31888fef 100644 --- a/arch/mips/mti-malta/malta-smtc.c +++ b/arch/mips/mti-malta/malta-smtc.c @@ -116,7 +116,7 @@ struct plat_smp_ops msmtc_smp_ops = { void plat_set_irq_affinity(unsigned int irq, const struct cpumask *affinity) { - cpumask_t tmask = *affinity; + cpumask_t tmask; int cpu = 0; void smtc_set_irq_affinity(unsigned int irq, cpumask_t aff); @@ -139,11 +139,12 @@ void plat_set_irq_affinity(unsigned int irq, const struct cpumask *affinity) * be made to forward to an offline "CPU". */ + cpumask_copy(&tmask, affinity); for_each_cpu(cpu, affinity) { if ((cpu_data[cpu].vpe_id != 0) || !cpu_online(cpu)) cpu_clear(cpu, tmask); } - irq_desc[irq].affinity = tmask; + cpumask_copy(irq_desc[irq].affinity, &tmask); if (cpus_empty(tmask)) /* diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index ac2c822928c..49482806863 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -120,7 +120,7 @@ int cpu_check_affinity(unsigned int irq, cpumask_t *dest) if (CHECK_IRQ_PER_CPU(irq)) { /* Bad linux design decision. The mask has already * been set; we must reset it */ - irq_desc[irq].affinity = CPU_MASK_ALL; + cpumask_setall(irq_desc[irq].affinity); return -EINVAL; } @@ -136,7 +136,7 @@ static void cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest) if (cpu_check_affinity(irq, dest)) return; - irq_desc[irq].affinity = *dest; + cpumask_copy(irq_desc[irq].affinity, dest); } #endif @@ -295,7 +295,7 @@ int txn_alloc_irq(unsigned int bits_wide) unsigned long txn_affinity_addr(unsigned int irq, int cpu) { #ifdef CONFIG_SMP - irq_desc[irq].affinity = cpumask_of_cpu(cpu); + cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu)); #endif return per_cpu(cpu_data, cpu).txn_addr; @@ -352,7 +352,7 @@ void do_cpu_irq_mask(struct pt_regs *regs) irq = eirr_to_irq(eirr_val); #ifdef CONFIG_SMP - dest = irq_desc[irq].affinity; + cpumask_copy(&dest, irq_desc[irq].affinity); if (CHECK_IRQ_PER_CPU(irq_desc[irq].status) && !cpu_isset(smp_processor_id(), dest)) { int cpu = first_cpu(dest); diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 23b8b5e36f9..ad1e5ac721d 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -231,7 +231,7 @@ void fixup_irqs(cpumask_t map) if (irq_desc[irq].status & IRQ_PER_CPU) continue; - cpus_and(mask, irq_desc[irq].affinity, map); + cpumask_and(&mask, irq_desc[irq].affinity, &map); if (any_online_cpu(mask) == NR_CPUS) { printk("Breaking affinity for irq %i\n", irq); mask = map; diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 84e058f1e1c..80b513449f4 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -153,9 +153,10 @@ static int get_irq_server(unsigned int virq, unsigned int strict_check) { int server; /* For the moment only implement delivery to all cpus or one cpu */ - cpumask_t cpumask = irq_desc[virq].affinity; + cpumask_t cpumask; cpumask_t tmp = CPU_MASK_NONE; + cpumask_copy(&cpumask, irq_desc[virq].affinity); if (!distribute_irqs) return default_server; @@ -869,7 +870,7 @@ void xics_migrate_irqs_away(void) virq, cpu); /* Reset affinity to all cpus */ - irq_desc[virq].affinity = CPU_MASK_ALL; + cpumask_setall(irq_desc[virq].affinity); desc->chip->set_affinity(virq, cpu_all_mask); unlock: spin_unlock_irqrestore(&desc->lock, flags); diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 3e0d89dcdba..0afd21f9a22 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -566,9 +566,10 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic) #ifdef CONFIG_SMP static int irq_choose_cpu(unsigned int virt_irq) { - cpumask_t mask = irq_desc[virt_irq].affinity; + cpumask_t mask; int cpuid; + cpumask_copy(&mask, irq_desc[virt_irq].affinity); if (cpus_equal(mask, CPU_MASK_ALL)) { static int irq_rover; static DEFINE_SPINLOCK(irq_rover_lock); diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c index cab8e028687..4ac5c651e00 100644 --- a/arch/sparc/kernel/irq_64.c +++ b/arch/sparc/kernel/irq_64.c @@ -247,9 +247,10 @@ struct irq_handler_data { #ifdef CONFIG_SMP static int irq_choose_cpu(unsigned int virt_irq) { - cpumask_t mask = irq_desc[virt_irq].affinity; + cpumask_t mask; int cpuid; + cpumask_copy(&mask, irq_desc[virt_irq].affinity); if (cpus_equal(mask, CPU_MASK_ALL)) { static int irq_rover; static DEFINE_SPINLOCK(irq_rover_lock); @@ -854,7 +855,7 @@ void fixup_irqs(void) !(irq_desc[irq].status & IRQ_PER_CPU)) { if (irq_desc[irq].chip->set_affinity) irq_desc[irq].chip->set_affinity(irq, - &irq_desc[irq].affinity); + irq_desc[irq].affinity); } spin_unlock_irqrestore(&irq_desc[irq].lock, flags); } -- GitLab From 4a046d1754ee6ebb6f399696805ed61ea0444d4c Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 12 Jan 2009 17:39:24 -0800 Subject: [PATCH 0128/4982] x86: arch_probe_nr_irqs Impact: save RAM with large NR_CPUS, get smaller nr_irqs Signed-off-by: Yinghai Lu Signed-off-by: Mike Travis --- arch/x86/include/asm/irq_vectors.h | 7 ++----- arch/x86/kernel/io_apic.c | 16 ++++++++++++++++ include/linux/interrupt.h | 1 + kernel/irq/handle.c | 9 ++------- kernel/softirq.c | 5 +++++ 5 files changed, 26 insertions(+), 12 deletions(-) diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index 602361ad0e7..a16a2ab2b42 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h @@ -115,14 +115,11 @@ # endif #else -/* defined as a macro so nr_irqs = max_nr_irqs(nr_cpu_ids) can be used */ -# define max_nr_irqs(nr_cpus) \ - ((8 * nr_cpus) > (32 * MAX_IO_APICS) ? \ +# define NR_IRQS \ + ((8 * NR_CPUS) > (32 * MAX_IO_APICS) ? \ (NR_VECTORS + (8 * NR_CPUS)) : \ (NR_VECTORS + (32 * MAX_IO_APICS))) \ -# define NR_IRQS max_nr_irqs(NR_CPUS) - #endif #elif defined(CONFIG_X86_VOYAGER) diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index ae80638012d..157986916cd 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -3850,6 +3850,22 @@ void __init probe_nr_irqs_gsi(void) nr_irqs_gsi = nr; } +#ifdef CONFIG_SPARSE_IRQ +int __init arch_probe_nr_irqs(void) +{ + int nr; + + nr = ((8 * nr_cpu_ids) > (32 * nr_ioapics) ? + (NR_VECTORS + (8 * nr_cpu_ids)) : + (NR_VECTORS + (32 * nr_ioapics))); + + if (nr < nr_irqs && nr > nr_irqs_gsi) + nr_irqs = nr; + + return 0; +} +#endif + /* -------------------------------------------------------------------------- ACPI-based IOAPIC Configuration -------------------------------------------------------------------------- */ diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 9127f6b51a3..472f11765f6 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -467,6 +467,7 @@ int show_interrupts(struct seq_file *p, void *v); struct irq_desc; extern int early_irq_init(void); +extern int arch_probe_nr_irqs(void); extern int arch_early_irq_init(void); extern int arch_init_chip_data(struct irq_desc *desc, int cpu); diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 04d3e46031e..375d68cd5bf 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -59,10 +59,6 @@ EXPORT_SYMBOL_GPL(nr_irqs); #ifdef CONFIG_SPARSE_IRQ -#ifndef max_nr_irqs -#define max_nr_irqs(nr_cpus) NR_IRQS -#endif - static struct irq_desc irq_desc_init = { .irq = -1, .status = IRQ_DISABLED, @@ -137,9 +133,8 @@ int __init early_irq_init(void) int legacy_count; int i; - /* initialize nr_irqs based on nr_cpu_ids */ - nr_irqs = max_nr_irqs(nr_cpu_ids); - + /* initialize nr_irqs based on nr_cpu_ids */ + arch_probe_nr_irqs(); printk(KERN_INFO "NR_IRQS:%d nr_irqs:%d\n", NR_IRQS, nr_irqs); desc = irq_desc_legacy; diff --git a/kernel/softirq.c b/kernel/softirq.c index bdbe9de9cd8..0365b4899a3 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -795,6 +795,11 @@ int __init __weak early_irq_init(void) return 0; } +int __init __weak arch_probe_nr_irqs(void) +{ + return 0; +} + int __init __weak arch_early_irq_init(void) { return 0; -- GitLab From 554b91edec1c588b889a7357ff201c0a450e31ff Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Mon, 12 Jan 2009 21:25:04 +0100 Subject: [PATCH 0129/4982] ALSA: sscape: fix incorrect timeout after microcode upload A comment states that one should wait up to 5 secs while a waiting loop waits only 5 system ticks. Signed-off-by: Krzysztof Helt Signed-off-by: Takashi Iwai --- sound/isa/sscape.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index bc449166d18..6a7f842b962 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -393,20 +393,20 @@ static int sscape_wait_dma_unsafe(unsigned io_base, enum GA_REG reg, unsigned ti */ static int obp_startup_ack(struct soundscape *s, unsigned timeout) { - while (timeout != 0) { + unsigned long end_time = jiffies + msecs_to_jiffies(timeout); + + do { unsigned long flags; unsigned char x; - schedule_timeout_uninterruptible(1); - spin_lock_irqsave(&s->lock, flags); x = inb(HOST_DATA_IO(s->io_base)); spin_unlock_irqrestore(&s->lock, flags); if ((x & 0xfe) == 0xfe) return 1; - --timeout; - } /* while */ + msleep(10); + } while (time_before(jiffies, end_time)); return 0; } @@ -420,20 +420,20 @@ static int obp_startup_ack(struct soundscape *s, unsigned timeout) */ static int host_startup_ack(struct soundscape *s, unsigned timeout) { - while (timeout != 0) { + unsigned long end_time = jiffies + msecs_to_jiffies(timeout); + + do { unsigned long flags; unsigned char x; - schedule_timeout_uninterruptible(1); - spin_lock_irqsave(&s->lock, flags); x = inb(HOST_DATA_IO(s->io_base)); spin_unlock_irqrestore(&s->lock, flags); if (x == 0xfe) return 1; - --timeout; - } /* while */ + msleep(10); + } while (time_before(jiffies, end_time)); return 0; } @@ -529,10 +529,10 @@ static int upload_dma_data(struct soundscape *s, * give it 5 seconds (max) ... */ ret = 0; - if (!obp_startup_ack(s, 5)) { + if (!obp_startup_ack(s, 5000)) { snd_printk(KERN_ERR "sscape: No response from on-board processor after upload\n"); ret = -EAGAIN; - } else if (!host_startup_ack(s, 5)) { + } else if (!host_startup_ack(s, 5000)) { snd_printk(KERN_ERR "sscape: SoundScape failed to initialise\n"); ret = -EAGAIN; } -- GitLab From dc61b66fc724f89d357c43e2319d2cb7bec1e517 Mon Sep 17 00:00:00 2001 From: Andrea Borgia Date: Mon, 12 Jan 2009 23:17:47 +0100 Subject: [PATCH 0130/4982] ALSA: rename "Device" to "Toshiba SB-0500" via quirks Signed-off-by: Andrea Borgia Signed-off-by: Takashi Iwai --- sound/usb/usbquirks.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index 92115755d98..d59323ecd57 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h @@ -39,6 +39,16 @@ .idProduct = prod, \ .bInterfaceClass = USB_CLASS_VENDOR_SPEC +/* Creative/Toshiba Multimedia Center SB-0500 */ +{ + USB_DEVICE(0x041e, 0x3048), + .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + .vendor_name = "Toshiba", + .product_name = "SB-0500", + .ifnum = QUIRK_NO_INTERFACE + } +}, + /* Creative/E-Mu devices */ { USB_DEVICE(0x041e, 0x3010), -- GitLab From a4a0acf8e17e3d08e28b721ceceb898fbc959ceb Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 13 Jan 2009 18:43:03 -0800 Subject: [PATCH 0131/4982] x86: fix broken flush_tlb_others_ipi() This commit broke flush_tlb_others_ipi() causing boot hangs on a 16 logical cpu system: > commit 4595f9620cda8a1e973588e743cf5f8436dd20c6 > Author: Rusty Russell > Date: Sat Jan 10 21:58:09 2009 -0800 > > x86: change flush_tlb_others to take a const struct cpumask This change resulted in sending the invalidate tlb vector to the sender itself causing the hang. flush_tlb_others_ipi() should exclude the sender itself from the destination list. Signed-off-by: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/tlb_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/tlb_64.c b/arch/x86/kernel/tlb_64.c index 7a3f9891302..54ee2ecb5e2 100644 --- a/arch/x86/kernel/tlb_64.c +++ b/arch/x86/kernel/tlb_64.c @@ -188,7 +188,7 @@ static void flush_tlb_others_ipi(const struct cpumask *cpumask, * We have to send the IPI only to * CPUs affected. */ - send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR_START + sender); + send_IPI_mask(f->flush_cpumask, INVALIDATE_TLB_VECTOR_START + sender); while (!cpumask_empty(to_cpumask(f->flush_cpumask))) cpu_relax(); -- GitLab From b1a0aac05f044e78a589bfd7a9e2334aa640eb45 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 14 Jan 2009 09:34:06 +0100 Subject: [PATCH 0132/4982] ALSA: opti9xx - Fix build breakage by snd_card_create() conversion Add a missing variable declaration. Signed-off-by: Takashi Iwai --- sound/isa/opti9xx/opti92x-ad1848.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 87a4feb5010..cd6e60a6a4e 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -833,6 +833,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) static int snd_opti9xx_card_new(struct snd_card **cardp) { struct snd_card *card; + int err; err = snd_card_create(index, id, THIS_MODULE, sizeof(struct snd_opti9xx), &card); -- GitLab From b5ba7e6d1e7e2ac808afd21be1e56dc34caf20e6 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Mon, 12 Jan 2009 17:46:17 +0530 Subject: [PATCH 0133/4982] x86: replacing mp_config_ioapic with mpc_ioapic Impact: cleanup, solve 80 columns wrap problems Signed-off-by: Jaswinder Singh Rajput Signed-off-by: Ingo Molnar --- arch/x86/include/asm/io_apic.h | 10 +----- arch/x86/kernel/acpi/boot.c | 28 ++++++++-------- arch/x86/kernel/io_apic.c | 60 ++++++++++++++++------------------ arch/x86/kernel/mpparse.c | 12 +++---- 4 files changed, 50 insertions(+), 60 deletions(-) diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index 7a1f44ac1f1..5a56ae9b505 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h @@ -120,14 +120,6 @@ extern int nr_ioapic_registers[MAX_IO_APICS]; #define MP_MAX_IOAPIC_PIN 127 -struct mp_config_ioapic { - unsigned long mp_apicaddr; - unsigned int mp_apicid; - unsigned char mp_type; - unsigned char mp_apicver; - unsigned char mp_flags; -}; - struct mp_config_intsrc { unsigned int mp_dstapic; unsigned char mp_type; @@ -139,7 +131,7 @@ struct mp_config_intsrc { }; /* I/O APIC entries */ -extern struct mp_config_ioapic mp_ioapics[MAX_IO_APICS]; +extern struct mpc_ioapic mp_ioapics[MAX_IO_APICS]; /* # of MP IRQ source entries */ extern int mp_irq_entries; diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index d37593c2f43..2b27019e64f 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -912,8 +912,8 @@ static u8 __init uniq_ioapic_id(u8 id) DECLARE_BITMAP(used, 256); bitmap_zero(used, 256); for (i = 0; i < nr_ioapics; i++) { - struct mp_config_ioapic *ia = &mp_ioapics[i]; - __set_bit(ia->mp_apicid, used); + struct mpc_ioapic *ia = &mp_ioapics[i]; + __set_bit(ia->apicid, used); } if (!test_bit(id, used)) return id; @@ -945,29 +945,29 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) idx = nr_ioapics; - mp_ioapics[idx].mp_type = MP_IOAPIC; - mp_ioapics[idx].mp_flags = MPC_APIC_USABLE; - mp_ioapics[idx].mp_apicaddr = address; + mp_ioapics[idx].type = MP_IOAPIC; + mp_ioapics[idx].flags = MPC_APIC_USABLE; + mp_ioapics[idx].apicaddr = address; set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); - mp_ioapics[idx].mp_apicid = uniq_ioapic_id(id); + mp_ioapics[idx].apicid = uniq_ioapic_id(id); #ifdef CONFIG_X86_32 - mp_ioapics[idx].mp_apicver = io_apic_get_version(idx); + mp_ioapics[idx].apicver = io_apic_get_version(idx); #else - mp_ioapics[idx].mp_apicver = 0; + mp_ioapics[idx].apicver = 0; #endif /* * Build basic GSI lookup table to facilitate gsi->io_apic lookups * and to prevent reprogramming of IOAPIC pins (PCI GSIs). */ - mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mp_apicid; + mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].apicid; mp_ioapic_routing[idx].gsi_base = gsi_base; mp_ioapic_routing[idx].gsi_end = gsi_base + io_apic_get_redir_entries(idx); - printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%lx, " - "GSI %d-%d\n", idx, mp_ioapics[idx].mp_apicid, - mp_ioapics[idx].mp_apicver, mp_ioapics[idx].mp_apicaddr, + printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, " + "GSI %d-%d\n", idx, mp_ioapics[idx].apicid, + mp_ioapics[idx].apicver, mp_ioapics[idx].apicaddr, mp_ioapic_routing[idx].gsi_base, mp_ioapic_routing[idx].gsi_end); nr_ioapics++; @@ -1026,7 +1026,7 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) mp_irq.mp_irqflag = (trigger << 2) | polarity; mp_irq.mp_srcbus = MP_ISA_BUS; mp_irq.mp_srcbusirq = bus_irq; /* IRQ */ - mp_irq.mp_dstapic = mp_ioapics[ioapic].mp_apicid; /* APIC ID */ + mp_irq.mp_dstapic = mp_ioapics[ioapic].apicid; /* APIC ID */ mp_irq.mp_dstirq = pin; /* INTIN# */ save_mp_irq(&mp_irq); @@ -1062,7 +1062,7 @@ void __init mp_config_acpi_legacy_irqs(void) ioapic = mp_find_ioapic(0); if (ioapic < 0) return; - dstapic = mp_ioapics[ioapic].mp_apicid; + dstapic = mp_ioapics[ioapic].apicid; /* * Use the default configuration for the IRQs 0-15. Unless diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 109c91db202..6c51ecdfbf4 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -83,7 +83,7 @@ static DEFINE_SPINLOCK(vector_lock); int nr_ioapic_registers[MAX_IO_APICS]; /* I/O APIC entries */ -struct mp_config_ioapic mp_ioapics[MAX_IO_APICS]; +struct mpc_ioapic mp_ioapics[MAX_IO_APICS]; int nr_ioapics; /* MP IRQ source entries */ @@ -387,7 +387,7 @@ struct io_apic { static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx) { return (void __iomem *) __fix_to_virt(FIX_IO_APIC_BASE_0 + idx) - + (mp_ioapics[idx].mp_apicaddr & ~PAGE_MASK); + + (mp_ioapics[idx].apicaddr & ~PAGE_MASK); } static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) @@ -946,7 +946,7 @@ static int find_irq_entry(int apic, int pin, int type) for (i = 0; i < mp_irq_entries; i++) if (mp_irqs[i].mp_irqtype == type && - (mp_irqs[i].mp_dstapic == mp_ioapics[apic].mp_apicid || + (mp_irqs[i].mp_dstapic == mp_ioapics[apic].apicid || mp_irqs[i].mp_dstapic == MP_APIC_ALL) && mp_irqs[i].mp_dstirq == pin) return i; @@ -988,7 +988,7 @@ static int __init find_isa_irq_apic(int irq, int type) if (i < mp_irq_entries) { int apic; for(apic = 0; apic < nr_ioapics; apic++) { - if (mp_ioapics[apic].mp_apicid == mp_irqs[i].mp_dstapic) + if (mp_ioapics[apic].apicid == mp_irqs[i].mp_dstapic) return apic; } } @@ -1016,7 +1016,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin) int lbus = mp_irqs[i].mp_srcbus; for (apic = 0; apic < nr_ioapics; apic++) - if (mp_ioapics[apic].mp_apicid == mp_irqs[i].mp_dstapic || + if (mp_ioapics[apic].apicid == mp_irqs[i].mp_dstapic || mp_irqs[i].mp_dstapic == MP_APIC_ALL) break; @@ -1567,14 +1567,14 @@ static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, struct irq_de apic_printk(APIC_VERBOSE,KERN_DEBUG "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> " "IRQ %d Mode:%i Active:%i)\n", - apic, mp_ioapics[apic].mp_apicid, pin, cfg->vector, + apic, mp_ioapics[apic].apicid, pin, cfg->vector, irq, trigger, polarity); - if (setup_ioapic_entry(mp_ioapics[apic].mp_apicid, irq, &entry, + if (setup_ioapic_entry(mp_ioapics[apic].apicid, irq, &entry, dest, trigger, polarity, cfg->vector)) { printk("Failed to setup ioapic entry for ioapic %d, pin %d\n", - mp_ioapics[apic].mp_apicid, pin); + mp_ioapics[apic].apicid, pin); __clear_irq_vector(irq, cfg); return; } @@ -1605,12 +1605,10 @@ static void __init setup_IO_APIC_irqs(void) notcon = 1; apic_printk(APIC_VERBOSE, KERN_DEBUG " %d-%d", - mp_ioapics[apic].mp_apicid, - pin); + mp_ioapics[apic].apicid, pin); } else apic_printk(APIC_VERBOSE, " %d-%d", - mp_ioapics[apic].mp_apicid, - pin); + mp_ioapics[apic].apicid, pin); continue; } if (notcon) { @@ -1700,7 +1698,7 @@ __apicdebuginit(void) print_IO_APIC(void) printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries); for (i = 0; i < nr_ioapics; i++) printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n", - mp_ioapics[i].mp_apicid, nr_ioapic_registers[i]); + mp_ioapics[i].apicid, nr_ioapic_registers[i]); /* * We are a bit conservative about what we expect. We have to @@ -1720,7 +1718,7 @@ __apicdebuginit(void) print_IO_APIC(void) spin_unlock_irqrestore(&ioapic_lock, flags); printk("\n"); - printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mp_apicid); + printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].apicid); printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw); printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.bits.ID); printk(KERN_DEBUG "....... : Delivery Type: %X\n", reg_00.bits.delivery_type); @@ -2122,14 +2120,14 @@ static void __init setup_ioapic_ids_from_mpc(void) reg_00.raw = io_apic_read(apic, 0); spin_unlock_irqrestore(&ioapic_lock, flags); - old_id = mp_ioapics[apic].mp_apicid; + old_id = mp_ioapics[apic].apicid; - if (mp_ioapics[apic].mp_apicid >= get_physical_broadcast()) { + if (mp_ioapics[apic].apicid >= get_physical_broadcast()) { printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n", - apic, mp_ioapics[apic].mp_apicid); + apic, mp_ioapics[apic].apicid); printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", reg_00.bits.ID); - mp_ioapics[apic].mp_apicid = reg_00.bits.ID; + mp_ioapics[apic].apicid = reg_00.bits.ID; } /* @@ -2138,9 +2136,9 @@ static void __init setup_ioapic_ids_from_mpc(void) * 'stuck on smp_invalidate_needed IPI wait' messages. */ if (check_apicid_used(phys_id_present_map, - mp_ioapics[apic].mp_apicid)) { + mp_ioapics[apic].apicid)) { printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n", - apic, mp_ioapics[apic].mp_apicid); + apic, mp_ioapics[apic].apicid); for (i = 0; i < get_physical_broadcast(); i++) if (!physid_isset(i, phys_id_present_map)) break; @@ -2149,13 +2147,13 @@ static void __init setup_ioapic_ids_from_mpc(void) printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", i); physid_set(i, phys_id_present_map); - mp_ioapics[apic].mp_apicid = i; + mp_ioapics[apic].apicid = i; } else { physid_mask_t tmp; - tmp = apicid_to_cpu_present(mp_ioapics[apic].mp_apicid); + tmp = apicid_to_cpu_present(mp_ioapics[apic].apicid); apic_printk(APIC_VERBOSE, "Setting %d in the " "phys_id_present_map\n", - mp_ioapics[apic].mp_apicid); + mp_ioapics[apic].apicid); physids_or(phys_id_present_map, phys_id_present_map, tmp); } @@ -2164,11 +2162,11 @@ static void __init setup_ioapic_ids_from_mpc(void) * We need to adjust the IRQ routing table * if the ID changed. */ - if (old_id != mp_ioapics[apic].mp_apicid) + if (old_id != mp_ioapics[apic].apicid) for (i = 0; i < mp_irq_entries; i++) if (mp_irqs[i].mp_dstapic == old_id) mp_irqs[i].mp_dstapic - = mp_ioapics[apic].mp_apicid; + = mp_ioapics[apic].apicid; /* * Read the right value from the MPC table and @@ -2176,9 +2174,9 @@ static void __init setup_ioapic_ids_from_mpc(void) */ apic_printk(APIC_VERBOSE, KERN_INFO "...changing IO-APIC physical APIC ID to %d ...", - mp_ioapics[apic].mp_apicid); + mp_ioapics[apic].apicid); - reg_00.bits.ID = mp_ioapics[apic].mp_apicid; + reg_00.bits.ID = mp_ioapics[apic].apicid; spin_lock_irqsave(&ioapic_lock, flags); io_apic_write(apic, 0, reg_00.raw); spin_unlock_irqrestore(&ioapic_lock, flags); @@ -2189,7 +2187,7 @@ static void __init setup_ioapic_ids_from_mpc(void) spin_lock_irqsave(&ioapic_lock, flags); reg_00.raw = io_apic_read(apic, 0); spin_unlock_irqrestore(&ioapic_lock, flags); - if (reg_00.bits.ID != mp_ioapics[apic].mp_apicid) + if (reg_00.bits.ID != mp_ioapics[apic].apicid) printk("could not set ID!\n"); else apic_printk(APIC_VERBOSE, " ok.\n"); @@ -3118,8 +3116,8 @@ static int ioapic_resume(struct sys_device *dev) spin_lock_irqsave(&ioapic_lock, flags); reg_00.raw = io_apic_read(dev->id, 0); - if (reg_00.bits.ID != mp_ioapics[dev->id].mp_apicid) { - reg_00.bits.ID = mp_ioapics[dev->id].mp_apicid; + if (reg_00.bits.ID != mp_ioapics[dev->id].apicid) { + reg_00.bits.ID = mp_ioapics[dev->id].apicid; io_apic_write(dev->id, 0, reg_00.raw); } spin_unlock_irqrestore(&ioapic_lock, flags); @@ -4101,7 +4099,7 @@ void __init ioapic_init_mappings(void) ioapic_res = ioapic_setup_resources(); for (i = 0; i < nr_ioapics; i++) { if (smp_found_config) { - ioapic_phys = mp_ioapics[i].mp_apicaddr; + ioapic_phys = mp_ioapics[i].apicaddr; #ifdef CONFIG_X86_32 if (!ioapic_phys) { printk(KERN_ERR diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 8385d4e7e15..a86a6553743 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -143,11 +143,11 @@ static void __init MP_ioapic_info(struct mpc_ioapic *m) if (bad_ioapic(m->apicaddr)) return; - mp_ioapics[nr_ioapics].mp_apicaddr = m->apicaddr; - mp_ioapics[nr_ioapics].mp_apicid = m->apicid; - mp_ioapics[nr_ioapics].mp_type = m->type; - mp_ioapics[nr_ioapics].mp_apicver = m->apicver; - mp_ioapics[nr_ioapics].mp_flags = m->flags; + mp_ioapics[nr_ioapics].apicaddr = m->apicaddr; + mp_ioapics[nr_ioapics].apicid = m->apicid; + mp_ioapics[nr_ioapics].type = m->type; + mp_ioapics[nr_ioapics].apicver = m->apicver; + mp_ioapics[nr_ioapics].flags = m->flags; nr_ioapics++; } @@ -416,7 +416,7 @@ static void __init construct_default_ioirq_mptable(int mpc_default_type) intsrc.type = MP_INTSRC; intsrc.irqflag = 0; /* conforming */ intsrc.srcbus = 0; - intsrc.dstapic = mp_ioapics[0].mp_apicid; + intsrc.dstapic = mp_ioapics[0].apicid; intsrc.irqtype = mp_INT; -- GitLab From c2c21745ecba23c74690a124bcd371f83bd71e45 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Mon, 12 Jan 2009 17:47:22 +0530 Subject: [PATCH 0134/4982] x86: replacing mp_config_intsrc with mpc_intsrc Impact: cleanup, solve 80 columns wrap problems Signed-off-by: Jaswinder Singh Rajput Signed-off-by: Ingo Molnar --- arch/x86/include/asm/io_apic.h | 16 +------- arch/x86/kernel/acpi/boot.c | 70 +++++++++++++++++----------------- arch/x86/kernel/io_apic.c | 64 +++++++++++++++---------------- arch/x86/kernel/mpparse.c | 68 ++++++++++++++++----------------- 4 files changed, 101 insertions(+), 117 deletions(-) diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index 5a56ae9b505..08ec793aa04 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h @@ -114,22 +114,8 @@ struct IR_IO_APIC_route_entry { extern int nr_ioapics; extern int nr_ioapic_registers[MAX_IO_APICS]; -/* - * MP-BIOS irq configuration table structures: - */ - #define MP_MAX_IOAPIC_PIN 127 -struct mp_config_intsrc { - unsigned int mp_dstapic; - unsigned char mp_type; - unsigned char mp_irqtype; - unsigned short mp_irqflag; - unsigned char mp_srcbus; - unsigned char mp_srcbusirq; - unsigned char mp_dstirq; -}; - /* I/O APIC entries */ extern struct mpc_ioapic mp_ioapics[MAX_IO_APICS]; @@ -137,7 +123,7 @@ extern struct mpc_ioapic mp_ioapics[MAX_IO_APICS]; extern int mp_irq_entries; /* MP IRQ source entries */ -extern struct mp_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; +extern struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES]; /* non-0 if default (table-less) MP configuration */ extern int mpc_default_type; diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 2b27019e64f..4cb5964f149 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -973,19 +973,19 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) nr_ioapics++; } -static void assign_to_mp_irq(struct mp_config_intsrc *m, - struct mp_config_intsrc *mp_irq) +static void assign_to_mp_irq(struct mpc_intsrc *m, + struct mpc_intsrc *mp_irq) { - memcpy(mp_irq, m, sizeof(struct mp_config_intsrc)); + memcpy(mp_irq, m, sizeof(struct mpc_intsrc)); } -static int mp_irq_cmp(struct mp_config_intsrc *mp_irq, - struct mp_config_intsrc *m) +static int mp_irq_cmp(struct mpc_intsrc *mp_irq, + struct mpc_intsrc *m) { - return memcmp(mp_irq, m, sizeof(struct mp_config_intsrc)); + return memcmp(mp_irq, m, sizeof(struct mpc_intsrc)); } -static void save_mp_irq(struct mp_config_intsrc *m) +static void save_mp_irq(struct mpc_intsrc *m) { int i; @@ -1003,7 +1003,7 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) { int ioapic; int pin; - struct mp_config_intsrc mp_irq; + struct mpc_intsrc mp_irq; /* * Convert 'gsi' to 'ioapic.pin'. @@ -1021,13 +1021,13 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) if ((bus_irq == 0) && (trigger == 3)) trigger = 1; - mp_irq.mp_type = MP_INTSRC; - mp_irq.mp_irqtype = mp_INT; - mp_irq.mp_irqflag = (trigger << 2) | polarity; - mp_irq.mp_srcbus = MP_ISA_BUS; - mp_irq.mp_srcbusirq = bus_irq; /* IRQ */ - mp_irq.mp_dstapic = mp_ioapics[ioapic].apicid; /* APIC ID */ - mp_irq.mp_dstirq = pin; /* INTIN# */ + mp_irq.type = MP_INTSRC; + mp_irq.irqtype = mp_INT; + mp_irq.irqflag = (trigger << 2) | polarity; + mp_irq.srcbus = MP_ISA_BUS; + mp_irq.srcbusirq = bus_irq; /* IRQ */ + mp_irq.dstapic = mp_ioapics[ioapic].apicid; /* APIC ID */ + mp_irq.dstirq = pin; /* INTIN# */ save_mp_irq(&mp_irq); } @@ -1037,7 +1037,7 @@ void __init mp_config_acpi_legacy_irqs(void) int i; int ioapic; unsigned int dstapic; - struct mp_config_intsrc mp_irq; + struct mpc_intsrc mp_irq; #if defined (CONFIG_MCA) || defined (CONFIG_EISA) /* @@ -1072,16 +1072,14 @@ void __init mp_config_acpi_legacy_irqs(void) int idx; for (idx = 0; idx < mp_irq_entries; idx++) { - struct mp_config_intsrc *irq = mp_irqs + idx; + struct mpc_intsrc *irq = mp_irqs + idx; /* Do we already have a mapping for this ISA IRQ? */ - if (irq->mp_srcbus == MP_ISA_BUS - && irq->mp_srcbusirq == i) + if (irq->srcbus == MP_ISA_BUS && irq->srcbusirq == i) break; /* Do we already have a mapping for this IOAPIC pin */ - if (irq->mp_dstapic == dstapic && - irq->mp_dstirq == i) + if (irq->dstapic == dstapic && irq->dstirq == i) break; } @@ -1090,13 +1088,13 @@ void __init mp_config_acpi_legacy_irqs(void) continue; /* IRQ already used */ } - mp_irq.mp_type = MP_INTSRC; - mp_irq.mp_irqflag = 0; /* Conforming */ - mp_irq.mp_srcbus = MP_ISA_BUS; - mp_irq.mp_dstapic = dstapic; - mp_irq.mp_irqtype = mp_INT; - mp_irq.mp_srcbusirq = i; /* Identity mapped */ - mp_irq.mp_dstirq = i; + mp_irq.type = MP_INTSRC; + mp_irq.irqflag = 0; /* Conforming */ + mp_irq.srcbus = MP_ISA_BUS; + mp_irq.dstapic = dstapic; + mp_irq.irqtype = mp_INT; + mp_irq.srcbusirq = i; /* Identity mapped */ + mp_irq.dstirq = i; save_mp_irq(&mp_irq); } @@ -1207,22 +1205,22 @@ int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin, u32 gsi, int triggering, int polarity) { #ifdef CONFIG_X86_MPPARSE - struct mp_config_intsrc mp_irq; + struct mpc_intsrc mp_irq; int ioapic; if (!acpi_ioapic) return 0; /* print the entry should happen on mptable identically */ - mp_irq.mp_type = MP_INTSRC; - mp_irq.mp_irqtype = mp_INT; - mp_irq.mp_irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) | + mp_irq.type = MP_INTSRC; + mp_irq.irqtype = mp_INT; + mp_irq.irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) | (polarity == ACPI_ACTIVE_HIGH ? 1 : 3); - mp_irq.mp_srcbus = number; - mp_irq.mp_srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3); + mp_irq.srcbus = number; + mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3); ioapic = mp_find_ioapic(gsi); - mp_irq.mp_dstapic = mp_ioapic_routing[ioapic].apic_id; - mp_irq.mp_dstirq = gsi - mp_ioapic_routing[ioapic].gsi_base; + mp_irq.dstapic = mp_ioapic_routing[ioapic].apic_id; + mp_irq.dstirq = gsi - mp_ioapic_routing[ioapic].gsi_base; save_mp_irq(&mp_irq); #endif diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 6c51ecdfbf4..79b8c0c72d3 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -87,7 +87,7 @@ struct mpc_ioapic mp_ioapics[MAX_IO_APICS]; int nr_ioapics; /* MP IRQ source entries */ -struct mp_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; +struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES]; /* # of MP IRQ source entries */ int mp_irq_entries; @@ -945,10 +945,10 @@ static int find_irq_entry(int apic, int pin, int type) int i; for (i = 0; i < mp_irq_entries; i++) - if (mp_irqs[i].mp_irqtype == type && - (mp_irqs[i].mp_dstapic == mp_ioapics[apic].apicid || - mp_irqs[i].mp_dstapic == MP_APIC_ALL) && - mp_irqs[i].mp_dstirq == pin) + if (mp_irqs[i].irqtype == type && + (mp_irqs[i].dstapic == mp_ioapics[apic].apicid || + mp_irqs[i].dstapic == MP_APIC_ALL) && + mp_irqs[i].dstirq == pin) return i; return -1; @@ -962,13 +962,13 @@ static int __init find_isa_irq_pin(int irq, int type) int i; for (i = 0; i < mp_irq_entries; i++) { - int lbus = mp_irqs[i].mp_srcbus; + int lbus = mp_irqs[i].srcbus; if (test_bit(lbus, mp_bus_not_pci) && - (mp_irqs[i].mp_irqtype == type) && - (mp_irqs[i].mp_srcbusirq == irq)) + (mp_irqs[i].irqtype == type) && + (mp_irqs[i].srcbusirq == irq)) - return mp_irqs[i].mp_dstirq; + return mp_irqs[i].dstirq; } return -1; } @@ -978,17 +978,17 @@ static int __init find_isa_irq_apic(int irq, int type) int i; for (i = 0; i < mp_irq_entries; i++) { - int lbus = mp_irqs[i].mp_srcbus; + int lbus = mp_irqs[i].srcbus; if (test_bit(lbus, mp_bus_not_pci) && - (mp_irqs[i].mp_irqtype == type) && - (mp_irqs[i].mp_srcbusirq == irq)) + (mp_irqs[i].irqtype == type) && + (mp_irqs[i].srcbusirq == irq)) break; } if (i < mp_irq_entries) { int apic; for(apic = 0; apic < nr_ioapics; apic++) { - if (mp_ioapics[apic].apicid == mp_irqs[i].mp_dstapic) + if (mp_ioapics[apic].apicid == mp_irqs[i].dstapic) return apic; } } @@ -1013,23 +1013,23 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin) return -1; } for (i = 0; i < mp_irq_entries; i++) { - int lbus = mp_irqs[i].mp_srcbus; + int lbus = mp_irqs[i].srcbus; for (apic = 0; apic < nr_ioapics; apic++) - if (mp_ioapics[apic].apicid == mp_irqs[i].mp_dstapic || - mp_irqs[i].mp_dstapic == MP_APIC_ALL) + if (mp_ioapics[apic].apicid == mp_irqs[i].dstapic || + mp_irqs[i].dstapic == MP_APIC_ALL) break; if (!test_bit(lbus, mp_bus_not_pci) && - !mp_irqs[i].mp_irqtype && + !mp_irqs[i].irqtype && (bus == lbus) && - (slot == ((mp_irqs[i].mp_srcbusirq >> 2) & 0x1f))) { - int irq = pin_2_irq(i,apic,mp_irqs[i].mp_dstirq); + (slot == ((mp_irqs[i].srcbusirq >> 2) & 0x1f))) { + int irq = pin_2_irq(i, apic, mp_irqs[i].dstirq); if (!(apic || IO_APIC_IRQ(irq))) continue; - if (pin == (mp_irqs[i].mp_srcbusirq & 3)) + if (pin == (mp_irqs[i].srcbusirq & 3)) return irq; /* * Use the first all-but-pin matching entry as a @@ -1072,7 +1072,7 @@ static int EISA_ELCR(unsigned int irq) * EISA conforming in the MP table, that means its trigger type must * be read in from the ELCR */ -#define default_EISA_trigger(idx) (EISA_ELCR(mp_irqs[idx].mp_srcbusirq)) +#define default_EISA_trigger(idx) (EISA_ELCR(mp_irqs[idx].srcbusirq)) #define default_EISA_polarity(idx) default_ISA_polarity(idx) /* PCI interrupts are always polarity one level triggered, @@ -1089,13 +1089,13 @@ static int EISA_ELCR(unsigned int irq) static int MPBIOS_polarity(int idx) { - int bus = mp_irqs[idx].mp_srcbus; + int bus = mp_irqs[idx].srcbus; int polarity; /* * Determine IRQ line polarity (high active or low active): */ - switch (mp_irqs[idx].mp_irqflag & 3) + switch (mp_irqs[idx].irqflag & 3) { case 0: /* conforms, ie. bus-type dependent polarity */ if (test_bit(bus, mp_bus_not_pci)) @@ -1131,13 +1131,13 @@ static int MPBIOS_polarity(int idx) static int MPBIOS_trigger(int idx) { - int bus = mp_irqs[idx].mp_srcbus; + int bus = mp_irqs[idx].srcbus; int trigger; /* * Determine IRQ trigger mode (edge or level sensitive): */ - switch ((mp_irqs[idx].mp_irqflag>>2) & 3) + switch ((mp_irqs[idx].irqflag>>2) & 3) { case 0: /* conforms, ie. bus-type dependent */ if (test_bit(bus, mp_bus_not_pci)) @@ -1215,16 +1215,16 @@ int (*ioapic_renumber_irq)(int ioapic, int irq); static int pin_2_irq(int idx, int apic, int pin) { int irq, i; - int bus = mp_irqs[idx].mp_srcbus; + int bus = mp_irqs[idx].srcbus; /* * Debugging check, we are in big trouble if this message pops up! */ - if (mp_irqs[idx].mp_dstirq != pin) + if (mp_irqs[idx].dstirq != pin) printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n"); if (test_bit(bus, mp_bus_not_pci)) { - irq = mp_irqs[idx].mp_srcbusirq; + irq = mp_irqs[idx].srcbusirq; } else { /* * PCI IRQs are mapped in order @@ -2164,8 +2164,8 @@ static void __init setup_ioapic_ids_from_mpc(void) */ if (old_id != mp_ioapics[apic].apicid) for (i = 0; i < mp_irq_entries; i++) - if (mp_irqs[i].mp_dstapic == old_id) - mp_irqs[i].mp_dstapic + if (mp_irqs[i].dstapic == old_id) + mp_irqs[i].dstapic = mp_ioapics[apic].apicid; /* @@ -3983,8 +3983,8 @@ int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity) return -1; for (i = 0; i < mp_irq_entries; i++) - if (mp_irqs[i].mp_irqtype == mp_INT && - mp_irqs[i].mp_srcbusirq == bus_irq) + if (mp_irqs[i].irqtype == mp_INT && + mp_irqs[i].srcbusirq == bus_irq) break; if (i >= mp_irq_entries) return -1; diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index a86a6553743..ad36377dc93 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -159,55 +159,55 @@ static void print_MP_intsrc_info(struct mpc_intsrc *m) m->srcbusirq, m->dstapic, m->dstirq); } -static void __init print_mp_irq_info(struct mp_config_intsrc *mp_irq) +static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq) { apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x," " IRQ %02x, APIC ID %x, APIC INT %02x\n", - mp_irq->mp_irqtype, mp_irq->mp_irqflag & 3, - (mp_irq->mp_irqflag >> 2) & 3, mp_irq->mp_srcbus, - mp_irq->mp_srcbusirq, mp_irq->mp_dstapic, mp_irq->mp_dstirq); + mp_irq->irqtype, mp_irq->irqflag & 3, + (mp_irq->irqflag >> 2) & 3, mp_irq->srcbus, + mp_irq->srcbusirq, mp_irq->dstapic, mp_irq->dstirq); } static void __init assign_to_mp_irq(struct mpc_intsrc *m, - struct mp_config_intsrc *mp_irq) + struct mpc_intsrc *mp_irq) { - mp_irq->mp_dstapic = m->dstapic; - mp_irq->mp_type = m->type; - mp_irq->mp_irqtype = m->irqtype; - mp_irq->mp_irqflag = m->irqflag; - mp_irq->mp_srcbus = m->srcbus; - mp_irq->mp_srcbusirq = m->srcbusirq; - mp_irq->mp_dstirq = m->dstirq; + mp_irq->dstapic = m->dstapic; + mp_irq->type = m->type; + mp_irq->irqtype = m->irqtype; + mp_irq->irqflag = m->irqflag; + mp_irq->srcbus = m->srcbus; + mp_irq->srcbusirq = m->srcbusirq; + mp_irq->dstirq = m->dstirq; } -static void __init assign_to_mpc_intsrc(struct mp_config_intsrc *mp_irq, +static void __init assign_to_mpc_intsrc(struct mpc_intsrc *mp_irq, struct mpc_intsrc *m) { - m->dstapic = mp_irq->mp_dstapic; - m->type = mp_irq->mp_type; - m->irqtype = mp_irq->mp_irqtype; - m->irqflag = mp_irq->mp_irqflag; - m->srcbus = mp_irq->mp_srcbus; - m->srcbusirq = mp_irq->mp_srcbusirq; - m->dstirq = mp_irq->mp_dstirq; + m->dstapic = mp_irq->dstapic; + m->type = mp_irq->type; + m->irqtype = mp_irq->irqtype; + m->irqflag = mp_irq->irqflag; + m->srcbus = mp_irq->srcbus; + m->srcbusirq = mp_irq->srcbusirq; + m->dstirq = mp_irq->dstirq; } -static int __init mp_irq_mpc_intsrc_cmp(struct mp_config_intsrc *mp_irq, +static int __init mp_irq_mpc_intsrc_cmp(struct mpc_intsrc *mp_irq, struct mpc_intsrc *m) { - if (mp_irq->mp_dstapic != m->dstapic) + if (mp_irq->dstapic != m->dstapic) return 1; - if (mp_irq->mp_type != m->type) + if (mp_irq->type != m->type) return 2; - if (mp_irq->mp_irqtype != m->irqtype) + if (mp_irq->irqtype != m->irqtype) return 3; - if (mp_irq->mp_irqflag != m->irqflag) + if (mp_irq->irqflag != m->irqflag) return 4; - if (mp_irq->mp_srcbus != m->srcbus) + if (mp_irq->srcbus != m->srcbus) return 5; - if (mp_irq->mp_srcbusirq != m->srcbusirq) + if (mp_irq->srcbusirq != m->srcbusirq) return 6; - if (mp_irq->mp_dstirq != m->dstirq) + if (mp_irq->dstirq != m->dstirq) return 7; return 0; @@ -808,15 +808,15 @@ static int __init get_MP_intsrc_index(struct mpc_intsrc *m) /* not legacy */ for (i = 0; i < mp_irq_entries; i++) { - if (mp_irqs[i].mp_irqtype != mp_INT) + if (mp_irqs[i].irqtype != mp_INT) continue; - if (mp_irqs[i].mp_irqflag != 0x0f) + if (mp_irqs[i].irqflag != 0x0f) continue; - if (mp_irqs[i].mp_srcbus != m->srcbus) + if (mp_irqs[i].srcbus != m->srcbus) continue; - if (mp_irqs[i].mp_srcbusirq != m->srcbusirq) + if (mp_irqs[i].srcbusirq != m->srcbusirq) continue; if (irq_used[i]) { /* already claimed */ @@ -921,10 +921,10 @@ static int __init replace_intsrc_all(struct mpc_table *mpc, if (irq_used[i]) continue; - if (mp_irqs[i].mp_irqtype != mp_INT) + if (mp_irqs[i].irqtype != mp_INT) continue; - if (mp_irqs[i].mp_irqflag != 0x0f) + if (mp_irqs[i].irqflag != 0x0f) continue; if (nr_m_spare > 0) { -- GitLab From 09b3ec7315a18d885127544204f1e389d41058d0 Mon Sep 17 00:00:00 2001 From: Frederik Deweerdt Date: Mon, 12 Jan 2009 22:35:42 +0100 Subject: [PATCH 0135/4982] x86, tlb flush_data: replace per_cpu with an array Impact: micro-optimization, memory reduction On x86_64 flush tlb data is stored in per_cpu variables. This is unnecessary because only the first NUM_INVALIDATE_TLB_VECTORS entries are accessed. This patch aims at making the code less confusing (there's nothing really "per_cpu") by using a plain array. It also would save some memory on most distros out there (Ubuntu x86_64 has NR_CPUS=64 by default). [ Ravikiran G Thirumalai also pointed out that the correct alignment is ____cacheline_internodealigned_in_smp, so that there's no bouncing on vsmp. ] Signed-off-by: Frederik Deweerdt Acked-by: Ravikiran Thirumalai Signed-off-by: Ingo Molnar --- arch/x86/kernel/tlb_64.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/tlb_64.c b/arch/x86/kernel/tlb_64.c index f8be6f1d2e4..8cfea5d1451 100644 --- a/arch/x86/kernel/tlb_64.c +++ b/arch/x86/kernel/tlb_64.c @@ -33,7 +33,7 @@ * To avoid global state use 8 different call vectors. * Each CPU uses a specific vector to trigger flushes on other * CPUs. Depending on the received vector the target CPUs look into - * the right per cpu variable for the flush data. + * the right array slot for the flush data. * * With more than 8 CPUs they are hashed to the 8 available * vectors. The limited global vector space forces us to this right now. @@ -48,13 +48,13 @@ union smp_flush_state { unsigned long flush_va; spinlock_t tlbstate_lock; }; - char pad[SMP_CACHE_BYTES]; -} ____cacheline_aligned; + char pad[CONFIG_X86_INTERNODE_CACHE_BYTES]; +} ____cacheline_internodealigned_in_smp; /* State is put into the per CPU data section, but padded to a full cache line because other CPUs can access it and we don't want false sharing in the per cpu data segment. */ -static DEFINE_PER_CPU(union smp_flush_state, flush_state); +static union smp_flush_state flush_state[NUM_INVALIDATE_TLB_VECTORS]; /* * We cannot call mmdrop() because we are in interrupt context, @@ -129,7 +129,7 @@ asmlinkage void smp_invalidate_interrupt(struct pt_regs *regs) * Use that to determine where the sender put the data. */ sender = ~regs->orig_ax - INVALIDATE_TLB_VECTOR_START; - f = &per_cpu(flush_state, sender); + f = &flush_state[sender]; if (!cpu_isset(cpu, f->flush_cpumask)) goto out; @@ -169,7 +169,7 @@ void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm, /* Caller has disabled preemption */ sender = smp_processor_id() % NUM_INVALIDATE_TLB_VECTORS; - f = &per_cpu(flush_state, sender); + f = &flush_state[sender]; /* * Could avoid this lock when @@ -205,8 +205,8 @@ static int __cpuinit init_smp_flush(void) { int i; - for_each_possible_cpu(i) - spin_lock_init(&per_cpu(flush_state, i).tlbstate_lock); + for (i = 0; i < ARRAY_SIZE(flush_state); i++) + spin_lock_init(&flush_state[i].tlbstate_lock); return 0; } -- GitLab From 0a2a18b721abc960fbcada406746877d22340a60 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 12 Jan 2009 23:37:16 +0100 Subject: [PATCH 0136/4982] x86: change the default cache size to 64 bytes Right now the generic cacheline size is 128 bytes - that is wasteful when structures are aligned, as all modern x86 CPUs have an (effective) cacheline sizes of 64 bytes. It was set to 128 bytes due to some cacheline aliasing problems on older P4 systems, but those are many years old and we dont optimize for them anymore. (They'll still get the 128 bytes cacheline size if the kernel is specifically built for Pentium 4) Signed-off-by: Ingo Molnar Acked-by: Arjan van de Ven --- arch/x86/Kconfig.cpu | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index 8078955845a..cdf4a962323 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -307,10 +307,10 @@ config X86_CMPXCHG config X86_L1_CACHE_SHIFT int - default "7" if MPENTIUM4 || X86_GENERIC || GENERIC_CPU || MPSC + default "7" if MPENTIUM4 || MPSC default "4" if X86_ELAN || M486 || M386 || MGEODEGX1 default "5" if MWINCHIP3D || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX - default "6" if MK7 || MK8 || MPENTIUMM || MCORE2 || MVIAC7 + default "6" if MK7 || MK8 || MPENTIUMM || MCORE2 || MVIAC7 || X86_GENERIC || GENERIC_CPU config X86_XADD def_bool y -- GitLab From b665967979d0e990f196e7c4ba88e17c9ed9b781 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 12 Jan 2009 11:54:27 -0800 Subject: [PATCH 0137/4982] x86: make 32bit MAX_HARDIRQS_PER_CPU to be NR_VECTORS Impact: clean up to be same as 64bit 32-bit is using per-cpu vector too, so don't use default NR_IRQS. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/include/asm/hardirq_32.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/include/asm/hardirq_32.h b/arch/x86/include/asm/hardirq_32.h index cf7954d1405..d4b5d731073 100644 --- a/arch/x86/include/asm/hardirq_32.h +++ b/arch/x86/include/asm/hardirq_32.h @@ -19,6 +19,9 @@ typedef struct { DECLARE_PER_CPU(irq_cpustat_t, irq_stat); +/* We can have at most NR_VECTORS irqs routed to a cpu at a time */ +#define MAX_HARDIRQS_PER_CPU NR_VECTORS + #define __ARCH_IRQ_STAT #define __IRQ_STAT(cpu, member) (per_cpu(irq_stat, cpu).member) -- GitLab From b07430ac37103218b5c1e542490a1b98e6deb3d6 Mon Sep 17 00:00:00 2001 From: Gregory Haskins Date: Wed, 14 Jan 2009 08:55:39 -0500 Subject: [PATCH 0138/4982] sched: de CPP-ify the scheduler code Signed-off-by: Gregory Haskins --- kernel/sched_rt.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 18c7b5b3158..4eda5f795f0 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -64,8 +64,10 @@ static void dequeue_pushable_task(struct rq *rq, struct task_struct *p) #else -#define enqueue_pushable_task(rq, p) do { } while (0) -#define dequeue_pushable_task(rq, p) do { } while (0) +static inline +void enqueue_pushable_task(struct rq *rq, struct task_struct *p) {} +static inline +void dequeue_pushable_task(struct rq *rq, struct task_struct *p) {} #endif /* CONFIG_SMP */ -- GitLab From 398a153b16b09a68739928d4502455db9725ac86 Mon Sep 17 00:00:00 2001 From: Gregory Haskins Date: Wed, 14 Jan 2009 09:10:04 -0500 Subject: [PATCH 0139/4982] sched: fix build error in kernel/sched_rt.c when RT_GROUP_SCHED && !SMP Ingo found a build error in the scheduler when RT_GROUP_SCHED was enabled, but SMP was not. This patch rearranges the code such that it is a little more streamlined and compiles under all permutations of SMP, UP and RT_GROUP_SCHED. It was boot tested on my 4-way x86_64 and it still passes preempt-test. Signed-off-by: Gregory Haskins --- kernel/sched.c | 4 + kernel/sched_rt.c | 264 +++++++++++++++++++++++++++++----------------- 2 files changed, 174 insertions(+), 94 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index dd1a1466c1e..2b703f1fac3 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -466,7 +466,9 @@ struct rt_rq { #if defined CONFIG_SMP || defined CONFIG_RT_GROUP_SCHED struct { int curr; /* highest queued rt task prio */ +#ifdef CONFIG_SMP int next; /* next highest */ +#endif } highest_prio; #endif #ifdef CONFIG_SMP @@ -8267,8 +8269,10 @@ static void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq) #if defined CONFIG_SMP || defined CONFIG_RT_GROUP_SCHED rt_rq->highest_prio.curr = MAX_RT_PRIO; +#ifdef CONFIG_SMP rt_rq->highest_prio.next = MAX_RT_PRIO; #endif +#endif #ifdef CONFIG_SMP rt_rq->rt_nr_migratory = 0; rt_rq->overloaded = 0; diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 4eda5f795f0..4230b15fe90 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -3,6 +3,40 @@ * policies) */ +static inline struct task_struct *rt_task_of(struct sched_rt_entity *rt_se) +{ + return container_of(rt_se, struct task_struct, rt); +} + +#ifdef CONFIG_RT_GROUP_SCHED + +static inline struct rq *rq_of_rt_rq(struct rt_rq *rt_rq) +{ + return rt_rq->rq; +} + +static inline struct rt_rq *rt_rq_of_se(struct sched_rt_entity *rt_se) +{ + return rt_se->rt_rq; +} + +#else /* CONFIG_RT_GROUP_SCHED */ + +static inline struct rq *rq_of_rt_rq(struct rt_rq *rt_rq) +{ + return container_of(rt_rq, struct rq, rt); +} + +static inline struct rt_rq *rt_rq_of_se(struct sched_rt_entity *rt_se) +{ + struct task_struct *p = rt_task_of(rt_se); + struct rq *rq = task_rq(p); + + return &rq->rt; +} + +#endif /* CONFIG_RT_GROUP_SCHED */ + #ifdef CONFIG_SMP static inline int rt_overloaded(struct rq *rq) @@ -37,19 +71,35 @@ static inline void rt_clear_overload(struct rq *rq) cpumask_clear_cpu(rq->cpu, rq->rd->rto_mask); } -static void update_rt_migration(struct rq *rq) +static void update_rt_migration(struct rt_rq *rt_rq) { - if (rq->rt.rt_nr_migratory && (rq->rt.rt_nr_running > 1)) { - if (!rq->rt.overloaded) { - rt_set_overload(rq); - rq->rt.overloaded = 1; + if (rt_rq->rt_nr_migratory && (rt_rq->rt_nr_running > 1)) { + if (!rt_rq->overloaded) { + rt_set_overload(rq_of_rt_rq(rt_rq)); + rt_rq->overloaded = 1; } - } else if (rq->rt.overloaded) { - rt_clear_overload(rq); - rq->rt.overloaded = 0; + } else if (rt_rq->overloaded) { + rt_clear_overload(rq_of_rt_rq(rt_rq)); + rt_rq->overloaded = 0; } } +static void inc_rt_migration(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) +{ + if (rt_se->nr_cpus_allowed > 1) + rt_rq->rt_nr_migratory++; + + update_rt_migration(rt_rq); +} + +static void dec_rt_migration(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) +{ + if (rt_se->nr_cpus_allowed > 1) + rt_rq->rt_nr_migratory--; + + update_rt_migration(rt_rq); +} + static void enqueue_pushable_task(struct rq *rq, struct task_struct *p) { plist_del(&p->pushable_tasks, &rq->rt.pushable_tasks); @@ -68,14 +118,13 @@ static inline void enqueue_pushable_task(struct rq *rq, struct task_struct *p) {} static inline void dequeue_pushable_task(struct rq *rq, struct task_struct *p) {} +static inline +void inc_rt_migration(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) {} +static inline +void dec_rt_migration(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) {} #endif /* CONFIG_SMP */ -static inline struct task_struct *rt_task_of(struct sched_rt_entity *rt_se) -{ - return container_of(rt_se, struct task_struct, rt); -} - static inline int on_rt_rq(struct sched_rt_entity *rt_se) { return !list_empty(&rt_se->run_list); @@ -99,16 +148,6 @@ static inline u64 sched_rt_period(struct rt_rq *rt_rq) #define for_each_leaf_rt_rq(rt_rq, rq) \ list_for_each_entry_rcu(rt_rq, &rq->leaf_rt_rq_list, leaf_rt_rq_list) -static inline struct rq *rq_of_rt_rq(struct rt_rq *rt_rq) -{ - return rt_rq->rq; -} - -static inline struct rt_rq *rt_rq_of_se(struct sched_rt_entity *rt_se) -{ - return rt_se->rt_rq; -} - #define for_each_sched_rt_entity(rt_se) \ for (; rt_se; rt_se = rt_se->parent) @@ -196,19 +235,6 @@ static inline u64 sched_rt_period(struct rt_rq *rt_rq) #define for_each_leaf_rt_rq(rt_rq, rq) \ for (rt_rq = &rq->rt; rt_rq; rt_rq = NULL) -static inline struct rq *rq_of_rt_rq(struct rt_rq *rt_rq) -{ - return container_of(rt_rq, struct rq, rt); -} - -static inline struct rt_rq *rt_rq_of_se(struct sched_rt_entity *rt_se) -{ - struct task_struct *p = rt_task_of(rt_se); - struct rq *rq = task_rq(p); - - return &rq->rt; -} - #define for_each_sched_rt_entity(rt_se) \ for (; rt_se; rt_se = NULL) @@ -567,7 +593,7 @@ static void update_curr_rt(struct rq *rq) } } -#if defined CONFIG_SMP || defined CONFIG_RT_GROUP_SCHED +#if defined CONFIG_SMP static struct task_struct *pick_next_highest_task_rt(struct rq *rq, int cpu); @@ -580,33 +606,24 @@ static inline int next_prio(struct rq *rq) else return MAX_RT_PRIO; } -#endif -static inline -void inc_rt_tasks(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) +static void +inc_rt_prio_smp(struct rt_rq *rt_rq, int prio, int prev_prio) { - int prio = rt_se_prio(rt_se); -#ifdef CONFIG_SMP struct rq *rq = rq_of_rt_rq(rt_rq); -#endif - WARN_ON(!rt_prio(prio)); - rt_rq->rt_nr_running++; -#if defined CONFIG_SMP || defined CONFIG_RT_GROUP_SCHED - if (prio < rt_rq->highest_prio.curr) { + if (prio < prev_prio) { /* * If the new task is higher in priority than anything on the - * run-queue, we have a new high that must be published to - * the world. We also know that the previous high becomes - * our next-highest. + * run-queue, we know that the previous high becomes our + * next-highest. */ - rt_rq->highest_prio.next = rt_rq->highest_prio.curr; - rt_rq->highest_prio.curr = prio; -#ifdef CONFIG_SMP + rt_rq->highest_prio.next = prev_prio; + if (rq->online) cpupri_set(&rq->rd->cpupri, rq->cpu, prio); -#endif + } else if (prio == rt_rq->highest_prio.curr) /* * If the next task is equal in priority to the highest on @@ -619,72 +636,131 @@ void inc_rt_tasks(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) * Otherwise, we need to recompute next-highest */ rt_rq->highest_prio.next = next_prio(rq); -#endif -#ifdef CONFIG_SMP - if (rt_se->nr_cpus_allowed > 1) - rq->rt.rt_nr_migratory++; +} - update_rt_migration(rq); -#endif -#ifdef CONFIG_RT_GROUP_SCHED - if (rt_se_boosted(rt_se)) - rt_rq->rt_nr_boosted++; +static void +dec_rt_prio_smp(struct rt_rq *rt_rq, int prio, int prev_prio) +{ + struct rq *rq = rq_of_rt_rq(rt_rq); - if (rt_rq->tg) - start_rt_bandwidth(&rt_rq->tg->rt_bandwidth); -#else - start_rt_bandwidth(&def_rt_bandwidth); -#endif + if (rt_rq->rt_nr_running && (prio <= rt_rq->highest_prio.next)) + rt_rq->highest_prio.next = next_prio(rq); + + if (rq->online && rt_rq->highest_prio.curr != prev_prio) + cpupri_set(&rq->rd->cpupri, rq->cpu, rt_rq->highest_prio.curr); } +#else /* CONFIG_SMP */ + static inline -void dec_rt_tasks(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) -{ -#ifdef CONFIG_SMP - struct rq *rq = rq_of_rt_rq(rt_rq); - int highest_prio = rt_rq->highest_prio.curr; -#endif +void inc_rt_prio_smp(struct rt_rq *rt_rq, int prio, int prev_prio) {} +static inline +void dec_rt_prio_smp(struct rt_rq *rt_rq, int prio, int prev_prio) {} + +#endif /* CONFIG_SMP */ - WARN_ON(!rt_prio(rt_se_prio(rt_se))); - WARN_ON(!rt_rq->rt_nr_running); - rt_rq->rt_nr_running--; #if defined CONFIG_SMP || defined CONFIG_RT_GROUP_SCHED +static void +inc_rt_prio(struct rt_rq *rt_rq, int prio) +{ + int prev_prio = rt_rq->highest_prio.curr; + + if (prio < prev_prio) + rt_rq->highest_prio.curr = prio; + + inc_rt_prio_smp(rt_rq, prio, prev_prio); +} + +static void +dec_rt_prio(struct rt_rq *rt_rq, int prio) +{ + int prev_prio = rt_rq->highest_prio.curr; + if (rt_rq->rt_nr_running) { - int prio = rt_se_prio(rt_se); - WARN_ON(prio < rt_rq->highest_prio.curr); + WARN_ON(prio < prev_prio); /* - * This may have been our highest or next-highest priority - * task and therefore we may have some recomputation to do + * This may have been our highest task, and therefore + * we may have some recomputation to do */ - if (prio == rt_rq->highest_prio.curr) { + if (prio == prev_prio) { struct rt_prio_array *array = &rt_rq->active; rt_rq->highest_prio.curr = sched_find_first_bit(array->bitmap); } - if (prio <= rt_rq->highest_prio.next) - rt_rq->highest_prio.next = next_prio(rq); } else rt_rq->highest_prio.curr = MAX_RT_PRIO; -#endif -#ifdef CONFIG_SMP - if (rt_se->nr_cpus_allowed > 1) - rq->rt.rt_nr_migratory--; - if (rq->online && rt_rq->highest_prio.curr != highest_prio) - cpupri_set(&rq->rd->cpupri, rq->cpu, rt_rq->highest_prio.curr); + dec_rt_prio_smp(rt_rq, prio, prev_prio); +} + +#else + +static inline void inc_rt_prio(struct rt_rq *rt_rq, int prio) {} +static inline void dec_rt_prio(struct rt_rq *rt_rq, int prio) {} + +#endif /* CONFIG_SMP || CONFIG_RT_GROUP_SCHED */ - update_rt_migration(rq); -#endif /* CONFIG_SMP */ #ifdef CONFIG_RT_GROUP_SCHED + +static void +inc_rt_group(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) +{ + if (rt_se_boosted(rt_se)) + rt_rq->rt_nr_boosted++; + + if (rt_rq->tg) + start_rt_bandwidth(&rt_rq->tg->rt_bandwidth); +} + +static void +dec_rt_group(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) +{ if (rt_se_boosted(rt_se)) rt_rq->rt_nr_boosted--; WARN_ON(!rt_rq->rt_nr_running && rt_rq->rt_nr_boosted); -#endif +} + +#else /* CONFIG_RT_GROUP_SCHED */ + +static void +inc_rt_group(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) +{ + start_rt_bandwidth(&def_rt_bandwidth); +} + +static inline +void dec_rt_group(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) {} + +#endif /* CONFIG_RT_GROUP_SCHED */ + +static inline +void inc_rt_tasks(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) +{ + int prio = rt_se_prio(rt_se); + + WARN_ON(!rt_prio(prio)); + rt_rq->rt_nr_running++; + + inc_rt_prio(rt_rq, prio); + inc_rt_migration(rt_se, rt_rq); + inc_rt_group(rt_se, rt_rq); +} + +static inline +void dec_rt_tasks(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) +{ + WARN_ON(!rt_prio(rt_se_prio(rt_se))); + WARN_ON(!rt_rq->rt_nr_running); + rt_rq->rt_nr_running--; + + dec_rt_prio(rt_rq, rt_se_prio(rt_se)); + dec_rt_migration(rt_se, rt_rq); + dec_rt_group(rt_se, rt_rq); } static void __enqueue_rt_entity(struct sched_rt_entity *rt_se) @@ -1453,7 +1529,7 @@ static void set_cpus_allowed_rt(struct task_struct *p, rq->rt.rt_nr_migratory--; } - update_rt_migration(rq); + update_rt_migration(&rq->rt); } cpumask_copy(&p->cpus_allowed, new_mask); -- GitLab From 6047a007d0f6b7395cd158f3bdda34ab39a48821 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Wed, 14 Jan 2009 12:22:25 +0200 Subject: [PATCH 0140/4982] SLUB: Use ->objsize from struct kmem_cache_cpu in slab_free() There's no reason to use ->objsize from struct kmem_cache in slab_free() for the SLAB_DEBUG_OBJECTS case. All it does is generate extra cache pressure as we try very hard not to touch struct kmem_cache in the fast-path. Signed-off-by: Pekka Enberg --- mm/slub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/slub.c b/mm/slub.c index 6392ae5cc6b..f21e25ad453 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1724,7 +1724,7 @@ static __always_inline void slab_free(struct kmem_cache *s, c = get_cpu_slab(s, smp_processor_id()); debug_check_no_locks_freed(object, c->objsize); if (!(s->flags & SLAB_DEBUG_OBJECTS)) - debug_check_no_obj_freed(object, s->objsize); + debug_check_no_obj_freed(object, c->objsize); if (likely(page == c->page && c->node >= 0)) { object[c->offset] = c->freelist; c->freelist = object; -- GitLab From 73310a169aebe257efdd35a763cce1c7658f40c9 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 14 Jan 2009 11:28:35 -0800 Subject: [PATCH 0141/4982] init: make initrd/initramfs decompression failure a KERN_EMERG event Impact: More consistent behaviour, avoid policy in the kernel Upgrade/downgrade initrd/initramfs decompression failure from inconsistently a panic or a KERN_ALERT message to a KERN_EMERG event. It is, however, possible do design a system which can recover from this (using the kernel builtin code and/or the internal initramfs), which means this is policy, not a technical necessity. A good way to handle this would be to have a panic-level=X option, to force a panic on a printk above a certain level. That is a separate patch, however. Signed-off-by: H. Peter Anvin --- init/do_mounts_rd.c | 3 ++- init/initramfs.c | 11 +++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c index 91d0cfca507..027a402708d 100644 --- a/init/do_mounts_rd.c +++ b/init/do_mounts_rd.c @@ -83,7 +83,8 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) printk(KERN_NOTICE "RAMDISK: %s image found at block %d\n", compress_name, start_block); if (!*decompressor) - printk(KERN_CRIT "RAMDISK: %s decompressor not configured!\n", + printk(KERN_EMERG + "RAMDISK: %s decompressor not configured!\n", compress_name); nblocks = 0; goto done; diff --git a/init/initramfs.c b/init/initramfs.c index 9a7290ec818..7dcde7ea660 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -528,7 +528,7 @@ static int __init populate_rootfs(void) char *err = unpack_to_rootfs(__initramfs_start, __initramfs_end - __initramfs_start, 0); if (err) - panic(err); + panic(err); /* Failed to decompress INTERNAL initramfs */ if (initrd_start) { #ifdef CONFIG_BLK_DEV_RAM int fd; @@ -554,9 +554,12 @@ static int __init populate_rootfs(void) printk(KERN_INFO "Unpacking initramfs..."); err = unpack_to_rootfs((char *)initrd_start, initrd_end - initrd_start, 0); - if (err) - panic(err); - printk(" done\n"); + if (err) { + printk(" failed!\n"); + printk(KERN_EMERG "%s\n", err); + } else { + printk(" done\n"); + } free_initrd(); #endif } -- GitLab From 444027031cd069ea7e48b016cb33bbf201c8a9f0 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Wed, 14 Jan 2009 23:37:47 +0300 Subject: [PATCH 0142/4982] x86: headers cleanup - prctl.h Impact: cleanup (internal kernel function exported) 'make headers_check' warn us about leaking of kernel private (mostly compile time vars) data to userspace in headers. Fix it. sys_arch_prctl is completely removed from header since frankly I don't even understand why we describe it here. It is described like __SYSCALL(__NR_arch_prctl, sys_arch_prctl) in unistd_64.h and implemented in process_64.c. User-mode linux involved? So this one in fact is suspicious. Signed-off-by: Cyrill Gorcunov Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/prctl.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/x86/include/asm/prctl.h b/arch/x86/include/asm/prctl.h index a8894647dd9..3ac5032fae0 100644 --- a/arch/x86/include/asm/prctl.h +++ b/arch/x86/include/asm/prctl.h @@ -6,8 +6,4 @@ #define ARCH_GET_FS 0x1003 #define ARCH_GET_GS 0x1004 -#ifdef CONFIG_X86_64 -extern long sys_arch_prctl(int, unsigned long); -#endif /* CONFIG_X86_64 */ - #endif /* _ASM_X86_PRCTL_H */ -- GitLab From a7c4e68615e20771f279c51a2bec8980675c78c7 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Wed, 14 Jan 2009 23:37:49 +0300 Subject: [PATCH 0143/4982] x86: headers cleanup - sigcontext32.h Impact: cleanup 'make headers_check' warn us about lack of linux/types.h here. Lets add it. Signed-off-by: Cyrill Gorcunov Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/sigcontext32.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/include/asm/sigcontext32.h b/arch/x86/include/asm/sigcontext32.h index 6126188cf3a..ad1478c4ae1 100644 --- a/arch/x86/include/asm/sigcontext32.h +++ b/arch/x86/include/asm/sigcontext32.h @@ -1,6 +1,8 @@ #ifndef _ASM_X86_SIGCONTEXT32_H #define _ASM_X86_SIGCONTEXT32_H +#include + /* signal context for 32bit programs. */ #define X86_FXSR_MAGIC 0x0000 -- GitLab From dbca1df48e89d8aa59254fdc10ef16c16e73d94e Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Wed, 14 Jan 2009 23:37:50 +0300 Subject: [PATCH 0144/4982] x86: headers cleanup - setup.h Impact: cleanup 'make headers_check' warn us about leaking of kernel private (mostly compile time vars) data to userspace in headers. Fix it. Guard this one by __KERNEL__. Signed-off-by: Cyrill Gorcunov Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/setup.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h index ebe858cdc8a..29d31c0d13d 100644 --- a/arch/x86/include/asm/setup.h +++ b/arch/x86/include/asm/setup.h @@ -1,6 +1,8 @@ #ifndef _ASM_X86_SETUP_H #define _ASM_X86_SETUP_H +#ifdef __KERNEL__ + #define COMMAND_LINE_SIZE 2048 #ifndef __ASSEMBLY__ @@ -8,10 +10,8 @@ /* Interrupt control for vSMPowered x86_64 systems */ void vsmp_init(void); - void setup_bios_corruption_check(void); - #ifdef CONFIG_X86_VISWS extern void visws_early_detect(void); extern int is_visws_box(void); @@ -43,7 +43,7 @@ struct x86_quirks { void (*mpc_oem_bus_info)(struct mpc_bus *m, char *name); void (*mpc_oem_pci_bus)(struct mpc_bus *m); void (*smp_read_mpc_oem)(struct mpc_oemtable *oemtable, - unsigned short oemsize); + unsigned short oemsize); int (*setup_ioapic_ids)(void); int (*update_genapic)(void); }; @@ -56,8 +56,6 @@ extern unsigned long saved_video_mode; #endif #endif /* __ASSEMBLY__ */ -#ifdef __KERNEL__ - #ifdef __i386__ #include -- GitLab From 95c4bff0308eb0819436b730a836846d3e784657 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Wed, 14 Jan 2009 23:37:46 +0300 Subject: [PATCH 0145/4982] x86: headers cleanup - boot.h Impact: cleanup 'make headers_check' warn us about leaking of kernel private (mostly compile time vars) data to userspace in headers. Fix it. Neither BOOT_HEAP_SIZE, BOOT_STACK_SIZE refs was found by searching thru net (ie in user-space area) so fence this all by __KERNEL__ guard. Signed-off-by: Cyrill Gorcunov Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/boot.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/boot.h b/arch/x86/include/asm/boot.h index c0e8e68a31f..6526cf08b0e 100644 --- a/arch/x86/include/asm/boot.h +++ b/arch/x86/include/asm/boot.h @@ -10,14 +10,16 @@ #define EXTENDED_VGA 0xfffe /* 80x50 mode */ #define ASK_VGA 0xfffd /* ask for it at bootup */ +#ifdef __KERNEL__ + /* Physical address where kernel should be loaded. */ #define LOAD_PHYSICAL_ADDR ((CONFIG_PHYSICAL_START \ + (CONFIG_PHYSICAL_ALIGN - 1)) \ & ~(CONFIG_PHYSICAL_ALIGN - 1)) -#if (defined CONFIG_KERNEL_BZIP2) +#ifdef CONFIG_KERNEL_BZIP2 #define BOOT_HEAP_SIZE 0x400000 -#else +#else /* !CONFIG_KERNEL_BZIP2 */ #ifdef CONFIG_X86_64 #define BOOT_HEAP_SIZE 0x7000 @@ -25,7 +27,7 @@ #define BOOT_HEAP_SIZE 0x4000 #endif -#endif +#endif /* !CONFIG_KERNEL_BZIP2 */ #ifdef CONFIG_X86_64 #define BOOT_STACK_SIZE 0x4000 @@ -33,4 +35,6 @@ #define BOOT_STACK_SIZE 0x1000 #endif +#endif /* __KERNEL__ */ + #endif /* _ASM_X86_BOOT_H */ -- GitLab From ee287587dafd77fd211e50637561224605c214b4 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 14 Jan 2009 16:07:38 -0800 Subject: [PATCH 0146/4982] bzip2/lzma: update boot protocol specification Impact: documentation Update the boot protocol specification to include the currently supported file formats and their magic numbers. Signed-off-by: H. Peter Anvin --- Documentation/x86/boot.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/x86/boot.txt b/Documentation/x86/boot.txt index fcdc62b3c3d..9ac70ffe2b7 100644 --- a/Documentation/x86/boot.txt +++ b/Documentation/x86/boot.txt @@ -542,7 +542,10 @@ Protocol: 2.08+ The payload may be compressed. The format of both the compressed and uncompressed data should be determined using the standard magic - numbers. Currently only gzip compressed ELF is used. + numbers. The currently supported compression formats are gzip + (magic numbers 1F 8B or 1F 9E), bzip2 (magic number 42 5A) and LZMA + (magic number 5D 00). The uncompressed payload is currently always ELF + (magic number 7F 45 4C 46). Field name: payload_length Type: read -- GitLab From d2287f5ebea9ff2487d614719775f0b03fce15f6 Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Wed, 14 Jan 2009 15:43:54 -0800 Subject: [PATCH 0147/4982] irq: update all arches for new irq_desc, fix Impact: fix build errors Since the SPARSE IRQS changes redefined how the kstat irqs are organized, arch's must use the new accessor function: kstat_incr_irqs_this_cpu(irq, DESC); If CONFIG_SPARSE_IRQS is set, then DESC is a pointer to the irq_desc which has a pointer to the kstat_irqs. If not, then the .irqs field of struct kernel_stat is used instead. Signed-off-by: Mike Travis Signed-off-by: Ingo Molnar --- arch/ia64/kernel/irq_ia64.c | 12 ++++++++---- arch/mips/kernel/smtc.c | 4 +++- arch/mips/sgi-ip22/ip22-int.c | 2 +- arch/mips/sgi-ip22/ip22-time.c | 2 +- arch/mips/sibyte/bcm1480/smp.c | 3 ++- arch/mips/sibyte/sb1250/smp.c | 3 ++- arch/mn10300/kernel/mn10300-watchdog.c | 3 ++- arch/sparc/kernel/time_64.c | 2 +- 8 files changed, 20 insertions(+), 11 deletions(-) diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index 28d3d483db9..927ad027820 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -493,11 +493,13 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) saved_tpr = ia64_getreg(_IA64_REG_CR_TPR); ia64_srlz_d(); while (vector != IA64_SPURIOUS_INT_VECTOR) { + struct irq_desc *desc = irq_to_desc(vector); + if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) { smp_local_flush_tlb(); - kstat_this_cpu.irqs[vector]++; + kstat_incr_irqs_this_cpu(vector, desc); } else if (unlikely(IS_RESCHEDULE(vector))) - kstat_this_cpu.irqs[vector]++; + kstat_incr_irqs_this_cpu(vector, desc); else { int irq = local_vector_to_irq(vector); @@ -551,11 +553,13 @@ void ia64_process_pending_intr(void) * Perform normal interrupt style processing */ while (vector != IA64_SPURIOUS_INT_VECTOR) { + struct irq_desc *desc = irq_to_desc(vector); + if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) { smp_local_flush_tlb(); - kstat_this_cpu.irqs[vector]++; + kstat_incr_irqs_this_cpu(vector, desc); } else if (unlikely(IS_RESCHEDULE(vector))) - kstat_this_cpu.irqs[vector]++; + kstat_incr_irqs_this_cpu(vector, desc); else { struct pt_regs *old_regs = set_irq_regs(NULL); int irq = local_vector_to_irq(vector); diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index d2c1ab12425..5f5af7d4c89 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -921,11 +921,13 @@ void ipi_decode(struct smtc_ipi *pipi) struct clock_event_device *cd; void *arg_copy = pipi->arg; int type_copy = pipi->type; + int irq = MIPS_CPU_IRQ_BASE + 1; + smtc_ipi_nq(&freeIPIq, pipi); switch (type_copy) { case SMTC_CLOCK_TICK: irq_enter(); - kstat_this_cpu.irqs[MIPS_CPU_IRQ_BASE + 1]++; + kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); cd = &per_cpu(mips_clockevent_device, cpu); cd->event_handler(cd); irq_exit(); diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c index f8b18af141a..0ecd5fe9486 100644 --- a/arch/mips/sgi-ip22/ip22-int.c +++ b/arch/mips/sgi-ip22/ip22-int.c @@ -155,7 +155,7 @@ static void indy_buserror_irq(void) int irq = SGI_BUSERR_IRQ; irq_enter(); - kstat_this_cpu.irqs[irq]++; + kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); ip22_be_interrupt(irq); irq_exit(); } diff --git a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c index 3dcb27ec0c5..c8f7d2328b2 100644 --- a/arch/mips/sgi-ip22/ip22-time.c +++ b/arch/mips/sgi-ip22/ip22-time.c @@ -122,7 +122,7 @@ void indy_8254timer_irq(void) char c; irq_enter(); - kstat_this_cpu.irqs[irq]++; + kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); printk(KERN_ALERT "Oops, got 8254 interrupt.\n"); ArcRead(0, &c, 1, &cnt); ArcEnterInteractiveMode(); diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c index dddfda8e829..314691648c9 100644 --- a/arch/mips/sibyte/bcm1480/smp.c +++ b/arch/mips/sibyte/bcm1480/smp.c @@ -178,9 +178,10 @@ struct plat_smp_ops bcm1480_smp_ops = { void bcm1480_mailbox_interrupt(void) { int cpu = smp_processor_id(); + int irq = K_BCM1480_INT_MBOX_0_0; unsigned int action; - kstat_this_cpu.irqs[K_BCM1480_INT_MBOX_0_0]++; + kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); /* Load the mailbox register to figure out what we're supposed to do */ action = (__raw_readq(mailbox_0_regs[cpu]) >> 48) & 0xffff; diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c index 5950a288a7d..cad14003b84 100644 --- a/arch/mips/sibyte/sb1250/smp.c +++ b/arch/mips/sibyte/sb1250/smp.c @@ -166,9 +166,10 @@ struct plat_smp_ops sb_smp_ops = { void sb1250_mailbox_interrupt(void) { int cpu = smp_processor_id(); + int irq = K_INT_MBOX_0; unsigned int action; - kstat_this_cpu.irqs[K_INT_MBOX_0]++; + kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); /* Load the mailbox register to figure out what we're supposed to do */ action = (____raw_readq(mailbox_regs[cpu]) >> 48) & 0xffff; diff --git a/arch/mn10300/kernel/mn10300-watchdog.c b/arch/mn10300/kernel/mn10300-watchdog.c index 10811e981d2..2e370d88a87 100644 --- a/arch/mn10300/kernel/mn10300-watchdog.c +++ b/arch/mn10300/kernel/mn10300-watchdog.c @@ -130,6 +130,7 @@ void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep) * the stack NMI-atomically, it's safe to use smp_processor_id(). */ int sum, cpu = smp_processor_id(); + int irq = NMIIRQ; u8 wdt, tmp; wdt = WDCTR & ~WDCTR_WDCNE; @@ -138,7 +139,7 @@ void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep) NMICR = NMICR_WDIF; nmi_count(cpu)++; - kstat_this_cpu.irqs[NMIIRQ]++; + kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); sum = irq_stat[cpu].__irq_count; if (last_irq_sums[cpu] == sum) { diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index 54405d36214..28b48f3eb25 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c @@ -727,7 +727,7 @@ void timer_interrupt(int irq, struct pt_regs *regs) irq_enter(); - kstat_this_cpu.irqs[0]++; + kstat_incr_irqs_this_cpu(0, irq_to_desc(0)); if (unlikely(!evt->event_handler)) { printk(KERN_WARNING -- GitLab From 831451ac4e44d3a20b581ce726ef1d1144373f7d Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 14 Jan 2009 12:39:18 +0100 Subject: [PATCH 0148/4982] sched: introduce avg_wakeup Introduce a new avg_wakeup statistic. avg_wakeup is a measure of how frequently a task wakes up other tasks, it represents the average time between wakeups, with a limit of avg_runtime for when it doesn't wake up anybody. Signed-off-by: Peter Zijlstra Signed-off-by: Mike Galbraith Signed-off-by: Ingo Molnar --- include/linux/sched.h | 3 +++ kernel/sched.c | 36 ++++++++++++++++++++++++++++++------ kernel/sched_debug.c | 1 + 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 4cae9b81a1f..daf4e07bc97 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1046,6 +1046,9 @@ struct sched_entity { u64 exec_max; u64 slice_max; + u64 start_runtime; + u64 avg_wakeup; + u64 nr_migrations; u64 nr_migrations_cold; u64 nr_failed_migrations_affine; diff --git a/kernel/sched.c b/kernel/sched.c index 8be2c13b50d..86f5a063f0b 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1705,6 +1705,9 @@ static void update_avg(u64 *avg, u64 sample) static void enqueue_task(struct rq *rq, struct task_struct *p, int wakeup) { + if (wakeup) + p->se.start_runtime = p->se.sum_exec_runtime; + sched_info_queued(p); p->sched_class->enqueue_task(rq, p, wakeup); p->se.on_rq = 1; @@ -1712,10 +1715,15 @@ static void enqueue_task(struct rq *rq, struct task_struct *p, int wakeup) static void dequeue_task(struct rq *rq, struct task_struct *p, int sleep) { - if (sleep && p->se.last_wakeup) { - update_avg(&p->se.avg_overlap, - p->se.sum_exec_runtime - p->se.last_wakeup); - p->se.last_wakeup = 0; + if (sleep) { + if (p->se.last_wakeup) { + update_avg(&p->se.avg_overlap, + p->se.sum_exec_runtime - p->se.last_wakeup); + p->se.last_wakeup = 0; + } else { + update_avg(&p->se.avg_wakeup, + sysctl_sched_wakeup_granularity); + } } sched_info_dequeued(p); @@ -2345,6 +2353,22 @@ out_activate: activate_task(rq, p, 1); success = 1; + /* + * Only attribute actual wakeups done by this task. + */ + if (!in_interrupt()) { + struct sched_entity *se = ¤t->se; + u64 sample = se->sum_exec_runtime; + + if (se->last_wakeup) + sample -= se->last_wakeup; + else + sample -= se->start_runtime; + update_avg(&se->avg_wakeup, sample); + + se->last_wakeup = se->sum_exec_runtime; + } + out_running: trace_sched_wakeup(rq, p, success); check_preempt_curr(rq, p, sync); @@ -2355,8 +2379,6 @@ out_running: p->sched_class->task_wake_up(rq, p); #endif out: - current->se.last_wakeup = current->se.sum_exec_runtime; - task_rq_unlock(rq, &flags); return success; @@ -2386,6 +2408,8 @@ static void __sched_fork(struct task_struct *p) p->se.prev_sum_exec_runtime = 0; p->se.last_wakeup = 0; p->se.avg_overlap = 0; + p->se.start_runtime = 0; + p->se.avg_wakeup = sysctl_sched_wakeup_granularity; #ifdef CONFIG_SCHEDSTATS p->se.wait_start = 0; diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c index 16eeba4e416..2b1260f0e80 100644 --- a/kernel/sched_debug.c +++ b/kernel/sched_debug.c @@ -397,6 +397,7 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m) PN(se.vruntime); PN(se.sum_exec_runtime); PN(se.avg_overlap); + PN(se.avg_wakeup); nr_switches = p->nvcsw + p->nivcsw; -- GitLab From e52fb7c097238d34f4d8e2a596f8a3f85b0c0565 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 14 Jan 2009 12:39:19 +0100 Subject: [PATCH 0149/4982] sched: prefer wakers Prefer tasks that wake other tasks to preempt quickly. This improves performance because more work is available sooner. The workload that prompted this patch was a kernel build over NFS4 (for some curious and not understood reason we had to revert commit: 18de9735300756e3ca9c361ef58409d8561dfe0d to make any progress at all) Without this patch a make -j8 bzImage (of x86-64 defconfig) would take 3m30-ish, with this patch we're down to 2m50-ish. psql-sysbench/mysql-sysbench show a slight improvement in peak performance as well, tbench and vmark seemed to not care. It is possible to improve upon the build time (to 2m20-ish) but that seriously destroys other benchmarks (just shows that there's more room for tinkering). Much thanks to Mike who put in a lot of effort to benchmark things and proved a worthy opponent with a competing patch. Signed-off-by: Peter Zijlstra Signed-off-by: Mike Galbraith Signed-off-by: Ingo Molnar --- kernel/sched_fair.c | 59 ++++++++++++++++++++++++++++++++++++----- kernel/sched_features.h | 3 ++- 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 8e1352c7555..bdf64346b4d 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -1295,16 +1295,63 @@ out: } #endif /* CONFIG_SMP */ -static unsigned long wakeup_gran(struct sched_entity *se) +/* + * Adaptive granularity + * + * se->avg_wakeup gives the average time a task runs until it does a wakeup, + * with the limit of wakeup_gran -- when it never does a wakeup. + * + * So the smaller avg_wakeup is the faster we want this task to preempt, + * but we don't want to treat the preemptee unfairly and therefore allow it + * to run for at least the amount of time we'd like to run. + * + * NOTE: we use 2*avg_wakeup to increase the probability of actually doing one + * + * NOTE: we use *nr_running to scale with load, this nicely matches the + * degrading latency on load. + */ +static unsigned long +adaptive_gran(struct sched_entity *curr, struct sched_entity *se) +{ + u64 this_run = curr->sum_exec_runtime - curr->prev_sum_exec_runtime; + u64 expected_wakeup = 2*se->avg_wakeup * cfs_rq_of(se)->nr_running; + u64 gran = 0; + + if (this_run < expected_wakeup) + gran = expected_wakeup - this_run; + + return min_t(s64, gran, sysctl_sched_wakeup_granularity); +} + +static unsigned long +wakeup_gran(struct sched_entity *curr, struct sched_entity *se) { unsigned long gran = sysctl_sched_wakeup_granularity; + if (cfs_rq_of(curr)->curr && sched_feat(ADAPTIVE_GRAN)) + gran = adaptive_gran(curr, se); + /* - * More easily preempt - nice tasks, while not making it harder for - * + nice tasks. + * Since its curr running now, convert the gran from real-time + * to virtual-time in his units. */ - if (!sched_feat(ASYM_GRAN) || se->load.weight > NICE_0_LOAD) - gran = calc_delta_fair(sysctl_sched_wakeup_granularity, se); + if (sched_feat(ASYM_GRAN)) { + /* + * By using 'se' instead of 'curr' we penalize light tasks, so + * they get preempted easier. That is, if 'se' < 'curr' then + * the resulting gran will be larger, therefore penalizing the + * lighter, if otoh 'se' > 'curr' then the resulting gran will + * be smaller, again penalizing the lighter task. + * + * This is especially important for buddies when the leftmost + * task is higher priority than the buddy. + */ + if (unlikely(se->load.weight != NICE_0_LOAD)) + gran = calc_delta_fair(gran, se); + } else { + if (unlikely(curr->load.weight != NICE_0_LOAD)) + gran = calc_delta_fair(gran, curr); + } return gran; } @@ -1331,7 +1378,7 @@ wakeup_preempt_entity(struct sched_entity *curr, struct sched_entity *se) if (vdiff <= 0) return -1; - gran = wakeup_gran(curr); + gran = wakeup_gran(curr, se); if (vdiff > gran) return 1; diff --git a/kernel/sched_features.h b/kernel/sched_features.h index da5d93b5d2c..76f61756e67 100644 --- a/kernel/sched_features.h +++ b/kernel/sched_features.h @@ -1,5 +1,6 @@ SCHED_FEAT(NEW_FAIR_SLEEPERS, 1) -SCHED_FEAT(NORMALIZED_SLEEPER, 1) +SCHED_FEAT(NORMALIZED_SLEEPER, 0) +SCHED_FEAT(ADAPTIVE_GRAN, 1) SCHED_FEAT(WAKEUP_PREEMPT, 1) SCHED_FEAT(START_DEBIT, 1) SCHED_FEAT(AFFINE_WAKEUPS, 1) -- GitLab From f11826385b63566d98c02d35f592232ee77cd791 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Wed, 14 Jan 2009 12:27:35 +0000 Subject: [PATCH 0150/4982] x86: fully honor "nolapic" Impact: widen the effect of the 'nolapic' boot parameter "nolapic" should not only suppress SMP and use of the LAPIC, but it also ought to have the effect of disabling all IO-APIC related activity as well as PCI MSI and HT-IRQs. Signed-off-by: Jan Beulich Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic.c | 7 ++++++- arch/x86/kernel/io_apic.c | 6 ++++++ arch/x86/kernel/smpboot.c | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 0f830e4f567..c3dd64fabcf 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -1126,6 +1126,11 @@ void __cpuinit setup_local_APIC(void) unsigned int value; int i, j; + if (disable_apic) { + disable_ioapic_setup(); + return; + } + #ifdef CONFIG_X86_32 /* Pound the ESR really hard over the head with a big hammer - mbligh */ if (lapic_is_integrated() && esr_disable) { @@ -1566,11 +1571,11 @@ int apic_version[MAX_APICS]; int __init APIC_init_uniprocessor(void) { -#ifdef CONFIG_X86_64 if (disable_apic) { pr_info("Apic disabled\n"); return -1; } +#ifdef CONFIG_X86_64 if (!cpu_has_apic) { disable_apic = 1; pr_info("Apic disabled by BIOS\n"); diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 1c4a1302536..40747e58f30 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -3258,6 +3258,9 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms int err; unsigned dest; + if (disable_apic) + return -ENXIO; + cfg = irq_cfg(irq); err = assign_irq_vector(irq, cfg, TARGET_CPUS); if (err) @@ -3726,6 +3729,9 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) struct irq_cfg *cfg; int err; + if (disable_apic) + return -ENXIO; + cfg = irq_cfg(irq); err = assign_irq_vector(irq, cfg, TARGET_CPUS); if (!err) { diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index bb1a3b1fc87..31f99ec2e0f 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1125,6 +1125,7 @@ static int __init smp_sanity_check(unsigned max_cpus) printk(KERN_ERR "... forcing use of dummy APIC emulation." "(tell your hw vendor)\n"); smpboot_clear_io_apic(); + disable_ioapic_setup(); return -1; } -- GitLab From a08c4743ed5b861c4fa3d75be00da7106c926296 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Wed, 14 Jan 2009 12:28:51 +0000 Subject: [PATCH 0151/4982] x86: avoid early crash in disable_local_APIC() E.g. when called due to an early panic. Signed-off-by: Jan Beulich Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index c3dd64fabcf..38d6aab2358 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -895,6 +895,10 @@ void disable_local_APIC(void) { unsigned int value; + /* APIC hasn't been mapped yet */ + if (!apic_phys) + return; + clear_local_APIC(); /* -- GitLab From 54da5b3d44238eeb7417bacf792fb416d473bf4d Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 15 Jan 2009 13:04:58 +0100 Subject: [PATCH 0152/4982] x86: fix broken flush_tlb_others_ipi(), fix Impact: cleanup Use the proper type. Signed-off-by: Ingo Molnar --- arch/x86/kernel/tlb_64.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/tlb_64.c b/arch/x86/kernel/tlb_64.c index 54ee2ecb5e2..7f4141d3b66 100644 --- a/arch/x86/kernel/tlb_64.c +++ b/arch/x86/kernel/tlb_64.c @@ -188,7 +188,8 @@ static void flush_tlb_others_ipi(const struct cpumask *cpumask, * We have to send the IPI only to * CPUs affected. */ - send_IPI_mask(f->flush_cpumask, INVALIDATE_TLB_VECTOR_START + sender); + send_IPI_mask(to_cpumask(f->flush_cpumask), + INVALIDATE_TLB_VECTOR_START + sender); while (!cpumask_empty(to_cpumask(f->flush_cpumask))) cpu_relax(); -- GitLab From e56d0cfe7790fd3218ae4f6aae1335547fea8763 Mon Sep 17 00:00:00 2001 From: Baodong Chen Date: Thu, 8 Jan 2009 19:24:29 +0800 Subject: [PATCH 0153/4982] Documentation/x86/boot.txt: modify fieldname Modify field names to the right ones: - start_sys was changed to start_sys_seg - iinitrd_addr_max was changed to ramdisk_max - pad2 was changed to pad2 and pad3 - readmode_swtch was changed to realmode_swtch Signed-off-by: Baodong Chen <[email]chenbdchenbd@gmail.com[email]> Acked-by: Jiri Kosina Signed-off-by: Ingo Molnar --- Documentation/x86/boot.txt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Documentation/x86/boot.txt b/Documentation/x86/boot.txt index 7b4596ac412..12299697b7c 100644 --- a/Documentation/x86/boot.txt +++ b/Documentation/x86/boot.txt @@ -158,7 +158,7 @@ Offset Proto Name Meaning 0202/4 2.00+ header Magic signature "HdrS" 0206/2 2.00+ version Boot protocol version supported 0208/4 2.00+ realmode_swtch Boot loader hook (see below) -020C/2 2.00+ start_sys The load-low segment (0x1000) (obsolete) +020C/2 2.00+ start_sys_seg The load-low segment (0x1000) (obsolete) 020E/2 2.00+ kernel_version Pointer to kernel version string 0210/1 2.00+ type_of_loader Boot loader identifier 0211/1 2.00+ loadflags Boot protocol option flags @@ -170,10 +170,11 @@ Offset Proto Name Meaning 0224/2 2.01+ heap_end_ptr Free memory after setup end 0226/2 N/A pad1 Unused 0228/4 2.02+ cmd_line_ptr 32-bit pointer to the kernel command line -022C/4 2.03+ initrd_addr_max Highest legal initrd address +022C/4 2.03+ ramdisk_max Highest legal initrd address 0230/4 2.05+ kernel_alignment Physical addr alignment required for kernel 0234/1 2.05+ relocatable_kernel Whether kernel is relocatable or not -0235/3 N/A pad2 Unused +0235/1 N/A pad2 Unused +0236/2 N/A pad3 Unused 0238/4 2.06+ cmdline_size Maximum size of the kernel command line 023C/4 2.07+ hardware_subarch Hardware subarchitecture 0240/8 2.07+ hardware_subarch_data Subarchitecture-specific data @@ -299,14 +300,14 @@ Protocol: 2.00+ e.g. 0x0204 for version 2.04, and 0x0a11 for a hypothetical version 10.17. -Field name: readmode_swtch +Field name: realmode_swtch Type: modify (optional) Offset/size: 0x208/4 Protocol: 2.00+ Boot loader hook (see ADVANCED BOOT LOADER HOOKS below.) -Field name: start_sys +Field name: start_sys_seg Type: read Offset/size: 0x20c/2 Protocol: 2.00+ @@ -468,7 +469,7 @@ Protocol: 2.02+ zero, the kernel will assume that your boot loader does not support the 2.02+ protocol. -Field name: initrd_addr_max +Field name: ramdisk_max Type: read Offset/size: 0x22c/4 Protocol: 2.03+ -- GitLab From 5cd7376200be7b8bab085557ff5876b04bd84191 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 15 Jan 2009 15:46:08 +0100 Subject: [PATCH 0154/4982] fix: crash: IP: __bitmap_intersects+0x48/0x73 -tip testing found this crash: > [ 35.258515] calling acpi_cpufreq_init+0x0/0x127 @ 1 > [ 35.264127] BUG: unable to handle kernel NULL pointer dereference at (null) > [ 35.267554] IP: [] __bitmap_intersects+0x48/0x73 > [ 35.267554] PGD 0 > [ 35.267554] Oops: 0000 [#1] SMP DEBUG_PAGEALLOC arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c is still broken: there's no allocation of the variable mask, so we pass in an uninitialized cmd.mask field to drv_read(), which then passes it to the scheduler which then crashes ... Switch it over to the much simpler constant-cpumask-pointers approach. Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index 6f11e029e8c..019276717a7 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -145,7 +145,7 @@ typedef union { struct drv_cmd { unsigned int type; - cpumask_var_t mask; + const struct cpumask *mask; drv_addr_union addr; u32 val; }; @@ -235,8 +235,7 @@ static u32 get_cur_val(const struct cpumask *mask) return 0; } - cpumask_copy(cmd.mask, mask); - + cmd.mask = mask; drv_read(&cmd); dprintk("get_cur_val = %u\n", cmd.val); @@ -403,9 +402,6 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy, return -ENODEV; } - if (unlikely(!alloc_cpumask_var(&cmd.mask, GFP_KERNEL))) - return -ENOMEM; - perf = data->acpi_data; result = cpufreq_frequency_table_target(policy, data->freq_table, @@ -450,9 +446,9 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy, /* cpufreq holds the hotplug lock, so we are safe from here on */ if (policy->shared_type != CPUFREQ_SHARED_TYPE_ANY) - cpumask_and(cmd.mask, cpu_online_mask, policy->cpus); + cmd.mask = policy->cpus; else - cpumask_copy(cmd.mask, cpumask_of(policy->cpu)); + cmd.mask = cpumask_of(policy->cpu); freqs.old = perf->states[perf->state].core_frequency * 1000; freqs.new = data->freq_table[next_state].frequency; @@ -479,7 +475,6 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy, perf->state = next_perf_state; out: - free_cpumask_var(cmd.mask); return result; } -- GitLab From 641b4879444c0edb276fedca5c2fcbd2e5c70044 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 15 Jan 2009 17:05:24 +0100 Subject: [PATCH 0155/4982] ALSA: usb-audio - Cache mixer values Cache mixer values in usb-audio driver to reduce too excessive accesses to the hardware. Signed-off-by: Takashi Iwai --- sound/usb/usbmixer.c | 122 +++++++++++++++++++++++++------------------ 1 file changed, 70 insertions(+), 52 deletions(-) diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index 00397c8a765..c07b3f8485e 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c @@ -110,6 +110,8 @@ struct mixer_build { const struct usbmix_selector_map *selector_map; }; +#define MAX_CHANNELS 10 /* max logical channels */ + struct usb_mixer_elem_info { struct usb_mixer_interface *mixer; struct usb_mixer_elem_info *next_id_elem; /* list of controls with same id */ @@ -120,6 +122,8 @@ struct usb_mixer_elem_info { int channels; int val_type; int min, max, res; + int cached; + int cache_val[MAX_CHANNELS]; u8 initialized; }; @@ -181,8 +185,6 @@ enum { USB_PROC_DCR_RELEASE = 6, }; -#define MAX_CHANNELS 10 /* max logical channels */ - /* * manual mapping of mixer names @@ -376,11 +378,35 @@ static int get_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int * } /* channel = 0: master, 1 = first channel */ -static inline int get_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int *value) +static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval, + int channel, int *value) { return get_ctl_value(cval, GET_CUR, (cval->control << 8) | channel, value); } +static int get_cur_mix_value(struct usb_mixer_elem_info *cval, + int channel, int index, int *value) +{ + int err; + + if (cval->cached & (1 << channel)) { + *value = cval->cache_val[index]; + return 0; + } + err = get_cur_mix_raw(cval, channel, value); + if (err < 0) { + if (!cval->mixer->ignore_ctl_error) + snd_printd(KERN_ERR "cannot get current value for " + "control %d ch %d: err = %d\n", + cval->control, channel, err); + return err; + } + cval->cached |= 1 << channel; + cval->cache_val[index] = *value; + return 0; +} + + /* * set a mixer value */ @@ -412,9 +438,17 @@ static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int v return set_ctl_value(cval, SET_CUR, validx, value); } -static inline int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int value) +static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, + int index, int value) { - return set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value); + int err; + err = set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, + value); + if (err < 0) + return err; + cval->cached |= 1 << channel; + cval->cache_val[index] = value; + return 0; } /* @@ -718,7 +752,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) if (cval->min + cval->res < cval->max) { int last_valid_res = cval->res; int saved, test, check; - get_cur_mix_value(cval, minchn, &saved); + get_cur_mix_raw(cval, minchn, &saved); for (;;) { test = saved; if (test < cval->max) @@ -726,8 +760,8 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) else test -= cval->res; if (test < cval->min || test > cval->max || - set_cur_mix_value(cval, minchn, test) || - get_cur_mix_value(cval, minchn, &check)) { + set_cur_mix_value(cval, minchn, 0, test) || + get_cur_mix_raw(cval, minchn, &check)) { cval->res = last_valid_res; break; } @@ -735,7 +769,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) break; cval->res *= 2; } - set_cur_mix_value(cval, minchn, saved); + set_cur_mix_value(cval, minchn, 0, saved); } cval->initialized = 1; @@ -775,35 +809,25 @@ static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e struct usb_mixer_elem_info *cval = kcontrol->private_data; int c, cnt, val, err; + ucontrol->value.integer.value[0] = cval->min; if (cval->cmask) { cnt = 0; for (c = 0; c < MAX_CHANNELS; c++) { - if (cval->cmask & (1 << c)) { - err = get_cur_mix_value(cval, c + 1, &val); - if (err < 0) { - if (cval->mixer->ignore_ctl_error) { - ucontrol->value.integer.value[0] = cval->min; - return 0; - } - snd_printd(KERN_ERR "cannot get current value for control %d ch %d: err = %d\n", cval->control, c + 1, err); - return err; - } - val = get_relative_value(cval, val); - ucontrol->value.integer.value[cnt] = val; - cnt++; - } + if (!(cval->cmask & (1 << c))) + continue; + err = get_cur_mix_value(cval, c + 1, cnt, &val); + if (err < 0) + return cval->mixer->ignore_ctl_error ? 0 : err; + val = get_relative_value(cval, val); + ucontrol->value.integer.value[cnt] = val; + cnt++; } + return 0; } else { /* master channel */ - err = get_cur_mix_value(cval, 0, &val); - if (err < 0) { - if (cval->mixer->ignore_ctl_error) { - ucontrol->value.integer.value[0] = cval->min; - return 0; - } - snd_printd(KERN_ERR "cannot get current value for control %d master ch: err = %d\n", cval->control, err); - return err; - } + err = get_cur_mix_value(cval, 0, 0, &val); + if (err < 0) + return cval->mixer->ignore_ctl_error ? 0 : err; val = get_relative_value(cval, val); ucontrol->value.integer.value[0] = val; } @@ -820,34 +844,28 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e if (cval->cmask) { cnt = 0; for (c = 0; c < MAX_CHANNELS; c++) { - if (cval->cmask & (1 << c)) { - err = get_cur_mix_value(cval, c + 1, &oval); - if (err < 0) { - if (cval->mixer->ignore_ctl_error) - return 0; - return err; - } - val = ucontrol->value.integer.value[cnt]; - val = get_abs_value(cval, val); - if (oval != val) { - set_cur_mix_value(cval, c + 1, val); - changed = 1; - } - get_cur_mix_value(cval, c + 1, &val); - cnt++; + if (!(cval->cmask & (1 << c))) + continue; + err = get_cur_mix_value(cval, c + 1, cnt, &oval); + if (err < 0) + return cval->mixer->ignore_ctl_error ? 0 : err; + val = ucontrol->value.integer.value[cnt]; + val = get_abs_value(cval, val); + if (oval != val) { + set_cur_mix_value(cval, c + 1, cnt, val); + changed = 1; } + cnt++; } } else { /* master channel */ - err = get_cur_mix_value(cval, 0, &oval); - if (err < 0 && cval->mixer->ignore_ctl_error) - return 0; + err = get_cur_mix_value(cval, 0, 0, &oval); if (err < 0) - return err; + return cval->mixer->ignore_ctl_error ? 0 : err; val = ucontrol->value.integer.value[0]; val = get_abs_value(cval, val); if (val != oval) { - set_cur_mix_value(cval, 0, val); + set_cur_mix_value(cval, 0, 0, val); changed = 1; } } -- GitLab From f2a082711905312dc7b6675e913fee0c4689f7ae Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Thu, 15 Jan 2009 09:19:32 -0800 Subject: [PATCH 0156/4982] x86: fix build warning when CONFIG_NUMA not defined. Impact: fix build warning The macro cpu_to_node did not reference it's argument, and instead simply returned a 0. This causes a "unused variable" warning if it's the only reference in a function (show_cache_disable). Replace it with the more correct inline function. Signed-off-by: Mike Travis --- arch/x86/include/asm/topology.h | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h index 4e2f2e0aab2..d0c68e29163 100644 --- a/arch/x86/include/asm/topology.h +++ b/arch/x86/include/asm/topology.h @@ -192,9 +192,20 @@ extern int __node_distance(int, int); #else /* !CONFIG_NUMA */ -#define numa_node_id() 0 -#define cpu_to_node(cpu) 0 -#define early_cpu_to_node(cpu) 0 +static inline int numa_node_id(void) +{ + return 0; +} + +static inline int cpu_to_node(int cpu) +{ + return 0; +} + +static inline int early_cpu_to_node(int cpu) +{ + return 0; +} static inline const cpumask_t *cpumask_of_node(int node) { -- GitLab From 45e513b689b8b0a01ec2b01cc21816e4780d7ea6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 15 Jan 2009 18:21:48 +0100 Subject: [PATCH 0157/4982] ALSA: snd-aoa: handle older machines This patch changes snd-aoa to handle some older machines that are currently handled by snd-powermac. snd-aoa has a number of advantages though, notably it can autoload better and is generally a more modern driver. By hardcoding the accepted device-ids (last hunk of the patch) I'm trying to avoid regressions because this driver will otherwise load automatically and not let snd-powermac load. People who are unhappy with snd-powermac and have a device-id property in the device tree are encouraged to read this patch and make a patch to amend this as appropriate. Signed-off-by: Johannes Berg Signed-off-by: Takashi Iwai --- sound/aoa/fabrics/layout.c | 74 ++++++++++++++++++++++++-------- sound/aoa/soundbus/i2sbus/core.c | 22 +++++++--- 2 files changed, 74 insertions(+), 22 deletions(-) diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c index ad60f5d10e8..d9b1d22a62c 100644 --- a/sound/aoa/fabrics/layout.c +++ b/sound/aoa/fabrics/layout.c @@ -1,16 +1,14 @@ /* - * Apple Onboard Audio driver -- layout fabric + * Apple Onboard Audio driver -- layout/machine id fabric * - * Copyright 2006 Johannes Berg + * Copyright 2006-2008 Johannes Berg * * GPL v2, can be found in COPYING. * * - * This fabric module looks for sound codecs - * based on the layout-id property in the device tree. - * + * This fabric module looks for sound codecs based on the + * layout-id or device-id property in the device tree. */ - #include #include #include @@ -63,7 +61,7 @@ struct codec_connect_info { #define LAYOUT_FLAG_COMBO_LINEOUT_SPDIF (1<<0) struct layout { - unsigned int layout_id; + unsigned int layout_id, device_id; struct codec_connect_info codecs[MAX_CODECS_PER_BUS]; int flags; @@ -111,6 +109,10 @@ MODULE_ALIAS("sound-layout-96"); MODULE_ALIAS("sound-layout-98"); MODULE_ALIAS("sound-layout-100"); +MODULE_ALIAS("aoa-device-id-14"); +MODULE_ALIAS("aoa-device-id-22"); +MODULE_ALIAS("aoa-device-id-35"); + /* onyx with all but microphone connected */ static struct codec_connection onyx_connections_nomic[] = { { @@ -518,6 +520,27 @@ static struct layout layouts[] = { .connections = onyx_connections_noheadphones, }, }, + /* PowerMac3,4 */ + { .device_id = 14, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_noline, + }, + }, + /* PowerMac3,6 */ + { .device_id = 22, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_all, + }, + }, + /* PowerBook5,2 */ + { .device_id = 35, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_all, + }, + }, {} }; @@ -526,7 +549,7 @@ static struct layout *find_layout_by_id(unsigned int id) struct layout *l; l = layouts; - while (l->layout_id) { + while (l->codecs[0].name) { if (l->layout_id == id) return l; l++; @@ -534,6 +557,19 @@ static struct layout *find_layout_by_id(unsigned int id) return NULL; } +static struct layout *find_layout_by_device(unsigned int id) +{ + struct layout *l; + + l = layouts; + while (l->codecs[0].name) { + if (l->device_id == id) + return l; + l++; + } + return NULL; +} + static void use_layout(struct layout *l) { int i; @@ -938,8 +974,8 @@ static struct aoa_fabric layout_fabric = { static int aoa_fabric_layout_probe(struct soundbus_dev *sdev) { struct device_node *sound = NULL; - const unsigned int *layout_id; - struct layout *layout; + const unsigned int *id; + struct layout *layout = NULL; struct layout_dev *ldev = NULL; int err; @@ -952,15 +988,18 @@ static int aoa_fabric_layout_probe(struct soundbus_dev *sdev) if (sound->type && strcasecmp(sound->type, "soundchip") == 0) break; } - if (!sound) return -ENODEV; + if (!sound) + return -ENODEV; - layout_id = of_get_property(sound, "layout-id", NULL); - if (!layout_id) - goto outnodev; - printk(KERN_INFO "snd-aoa-fabric-layout: found bus with layout %d\n", - *layout_id); + id = of_get_property(sound, "layout-id", NULL); + if (id) { + layout = find_layout_by_id(*id); + } else { + id = of_get_property(sound, "device-id", NULL); + if (id) + layout = find_layout_by_device(*id); + } - layout = find_layout_by_id(*layout_id); if (!layout) { printk(KERN_ERR "snd-aoa-fabric-layout: unknown layout\n"); goto outnodev; @@ -976,6 +1015,7 @@ static int aoa_fabric_layout_probe(struct soundbus_dev *sdev) ldev->layout = layout; ldev->gpio.node = sound->parent; switch (layout->layout_id) { + case 0: /* anything with device_id, not layout_id */ case 41: /* that unknown machine no one seems to have */ case 51: /* PowerBook5,4 */ case 58: /* Mac Mini */ diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c index be468edf3ec..418c84c99d6 100644 --- a/sound/aoa/soundbus/i2sbus/core.c +++ b/sound/aoa/soundbus/i2sbus/core.c @@ -1,7 +1,7 @@ /* * i2sbus driver * - * Copyright 2006 Johannes Berg + * Copyright 2006-2008 Johannes Berg * * GPL v2, can be found in COPYING. */ @@ -186,13 +186,25 @@ static int i2sbus_add_dev(struct macio_dev *macio, } } if (i == 1) { - const u32 *layout_id = - of_get_property(sound, "layout-id", NULL); - if (layout_id) { - layout = *layout_id; + const u32 *id = of_get_property(sound, "layout-id", NULL); + + if (id) { + layout = *id; snprintf(dev->sound.modalias, 32, "sound-layout-%d", layout); ok = 1; + } else { + id = of_get_property(sound, "device-id", NULL); + /* + * We probably cannot handle all device-id machines, + * so restrict to those we do handle for now. + */ + if (id && (*id == 22 || *id == 14 || *id == 35)) { + snprintf(dev->sound.modalias, 32, + "aoa-device-id-%d", *id); + ok = 1; + layout = -1; + } } } /* for the time being, until we can handle non-layout-id -- GitLab From 5f17e79cdf530b1a6090c65730e5656ac9c19eaa Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 15 Jan 2009 18:22:31 +0100 Subject: [PATCH 0158/4982] ALSA: snd-aoa: handle master-amp if present Some machines have a master amp GPIO that needs to be toggled to get sound output, in addition to speaker/headphone/line-out amps. This makes snd-aoa handle it, if present in the device tree, thus making snd-aoa be able to output sound on PowerMac3,6, which was previously handled by snd-powermac which also doesn't use the master amp GPIO. Signed-off-by: Johannes Berg Signed-off-by: Takashi Iwai --- sound/aoa/aoa-gpio.h | 2 ++ sound/aoa/core/gpio-feature.c | 17 ++++++++++++++++- sound/aoa/fabrics/layout.c | 7 +++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/sound/aoa/aoa-gpio.h b/sound/aoa/aoa-gpio.h index ee64f5de896..6065b0344e2 100644 --- a/sound/aoa/aoa-gpio.h +++ b/sound/aoa/aoa-gpio.h @@ -34,10 +34,12 @@ struct gpio_methods { void (*set_headphone)(struct gpio_runtime *rt, int on); void (*set_speakers)(struct gpio_runtime *rt, int on); void (*set_lineout)(struct gpio_runtime *rt, int on); + void (*set_master)(struct gpio_runtime *rt, int on); int (*get_headphone)(struct gpio_runtime *rt); int (*get_speakers)(struct gpio_runtime *rt); int (*get_lineout)(struct gpio_runtime *rt); + int (*get_master)(struct gpio_runtime *rt); void (*set_hw_reset)(struct gpio_runtime *rt, int on); diff --git a/sound/aoa/core/gpio-feature.c b/sound/aoa/core/gpio-feature.c index c93ad5dec66..de8e03afa97 100644 --- a/sound/aoa/core/gpio-feature.c +++ b/sound/aoa/core/gpio-feature.c @@ -14,7 +14,7 @@ #include #include "../aoa.h" -/* TODO: these are 20 global variables +/* TODO: these are lots of global variables * that aren't used on most machines... * Move them into a dynamically allocated * structure and use that. @@ -23,6 +23,7 @@ /* these are the GPIO numbers (register addresses as offsets into * the GPIO space) */ static int headphone_mute_gpio; +static int master_mute_gpio; static int amp_mute_gpio; static int lineout_mute_gpio; static int hw_reset_gpio; @@ -32,6 +33,7 @@ static int linein_detect_gpio; /* see the SWITCH_GPIO macro */ static int headphone_mute_gpio_activestate; +static int master_mute_gpio_activestate; static int amp_mute_gpio_activestate; static int lineout_mute_gpio_activestate; static int hw_reset_gpio_activestate; @@ -156,6 +158,7 @@ static int ftr_gpio_get_##name(struct gpio_runtime *rt) \ FTR_GPIO(headphone, 0); FTR_GPIO(amp, 1); FTR_GPIO(lineout, 2); +FTR_GPIO(master, 3); static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on) { @@ -172,6 +175,8 @@ static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on) hw_reset_gpio, v); } +static struct gpio_methods methods; + static void ftr_gpio_all_amps_off(struct gpio_runtime *rt) { int saved; @@ -181,6 +186,8 @@ static void ftr_gpio_all_amps_off(struct gpio_runtime *rt) ftr_gpio_set_headphone(rt, 0); ftr_gpio_set_amp(rt, 0); ftr_gpio_set_lineout(rt, 0); + if (methods.set_master) + ftr_gpio_set_master(rt, 0); rt->implementation_private = saved; } @@ -193,6 +200,8 @@ static void ftr_gpio_all_amps_restore(struct gpio_runtime *rt) ftr_gpio_set_headphone(rt, (s>>0)&1); ftr_gpio_set_amp(rt, (s>>1)&1); ftr_gpio_set_lineout(rt, (s>>2)&1); + if (methods.set_master) + ftr_gpio_set_master(rt, (s>>3)&1); } static void ftr_handle_notify(struct work_struct *work) @@ -231,6 +240,12 @@ static void ftr_gpio_init(struct gpio_runtime *rt) get_gpio("hw-reset", "audio-hw-reset", &hw_reset_gpio, &hw_reset_gpio_activestate); + if (get_gpio("master-mute", NULL, + &master_mute_gpio, + &master_mute_gpio_activestate)) { + methods.set_master = ftr_gpio_set_master; + methods.get_master = ftr_gpio_get_master; + } headphone_detect_node = get_gpio("headphone-detect", NULL, &headphone_detect_gpio, diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c index d9b1d22a62c..fbf5c933baa 100644 --- a/sound/aoa/fabrics/layout.c +++ b/sound/aoa/fabrics/layout.c @@ -600,6 +600,7 @@ struct layout_dev { struct snd_kcontrol *headphone_ctrl; struct snd_kcontrol *lineout_ctrl; struct snd_kcontrol *speaker_ctrl; + struct snd_kcontrol *master_ctrl; struct snd_kcontrol *headphone_detected_ctrl; struct snd_kcontrol *lineout_detected_ctrl; @@ -651,6 +652,7 @@ static struct snd_kcontrol_new n##_ctl = { \ AMP_CONTROL(headphone, "Headphone Switch"); AMP_CONTROL(speakers, "Speakers Switch"); AMP_CONTROL(lineout, "Line-Out Switch"); +AMP_CONTROL(master, "Master Switch"); static int detect_choice_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -891,6 +893,11 @@ static void layout_attached_codec(struct aoa_codec *codec) lineout = codec->gpio->methods->get_detect(codec->gpio, AOA_NOTIFY_LINE_OUT); + if (codec->gpio->methods->set_master) { + ctl = snd_ctl_new1(&master_ctl, codec->gpio); + ldev->master_ctrl = ctl; + aoa_snd_ctl_add(ctl); + } while (cc->connected) { if (cc->connected & CC_SPEAKERS) { if (headphones <= 0 && lineout <= 0) -- GitLab From c99dbbe9f8f6b3e9383e64710217e873431d1c31 Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Thu, 15 Jan 2009 12:09:44 -0800 Subject: [PATCH 0159/4982] sched: fix warning on ia64 Andrew Morton reported this warning on ia64: kernel/sched.c: In function `sd_init_NODE': kernel/sched.c:7449: warning: comparison of distinct pointer types lacks a cast Using the untyped min() function produces such warnings. Fix: type the constant 32 as unsigned int to match typeof(num_online_cpus). Reported-by: Andrew Morton Signed-off-by: Mike Travis Signed-off-by: Ingo Molnar --- arch/ia64/include/asm/topology.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ia64/include/asm/topology.h b/arch/ia64/include/asm/topology.h index 32f3af1641c..3193f4417e1 100644 --- a/arch/ia64/include/asm/topology.h +++ b/arch/ia64/include/asm/topology.h @@ -84,7 +84,7 @@ void build_cpu_to_node_map(void); .child = NULL, \ .groups = NULL, \ .min_interval = 8, \ - .max_interval = 8*(min(num_online_cpus(), 32)), \ + .max_interval = 8*(min(num_online_cpus(), 32U)), \ .busy_factor = 64, \ .imbalance_pct = 125, \ .cache_nice_tries = 2, \ -- GitLab From ac37373b6463d32955c6ac6b753d5e5b0946a791 Mon Sep 17 00:00:00 2001 From: Hugo Villeneuve Date: Thu, 15 Jan 2009 15:40:35 -0500 Subject: [PATCH 0160/4982] ASoC: DaVinci: Fix SFFSDR compilation error. Remove dependency on sffsdr_fpga_set_codec_fs() when the SFFSDR FPGA module is not selected. Signed-off-by: Hugo Villeneuve Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-sffsdr.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c index 4935d1bcbd8..50baef1fe5b 100644 --- a/sound/soc/davinci/davinci-sffsdr.c +++ b/sound/soc/davinci/davinci-sffsdr.c @@ -25,7 +25,9 @@ #include #include +#ifdef CONFIG_SFFSDR_FPGA #include +#endif #include #include @@ -43,6 +45,17 @@ static int sffsdr_hw_params(struct snd_pcm_substream *substream, int fs; int ret = 0; + /* Fsref can be 32000, 44100 or 48000. */ + fs = params_rate(params); + +#ifndef CONFIG_SFFSDR_FPGA + /* Without the FPGA module, the Fs is fixed at 44100 Hz */ + if (fs != 44100) { + pr_debug("warning: only 44.1 kHz is supported without SFFSDR FPGA module\n"); + return -EINVAL; + } +#endif + /* Set cpu DAI configuration: * CLKX and CLKR are the inputs for the Sample Rate Generator. * FSX and FSR are outputs, driven by the sample Rate Generator. */ @@ -53,12 +66,13 @@ static int sffsdr_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - /* Fsref can be 32000, 44100 or 48000. */ - fs = params_rate(params); - pr_debug("sffsdr_hw_params: rate = %d Hz\n", fs); +#ifndef CONFIG_SFFSDR_FPGA + return 0; +#else return sffsdr_fpga_set_codec_fs(fs); +#endif } static struct snd_soc_ops sffsdr_ops = { -- GitLab From 8d29b7b9f81d6b83d869ff054e6c189d6da73f1f Mon Sep 17 00:00:00 2001 From: Ben Nizette Date: Wed, 14 Jan 2009 09:32:19 +1100 Subject: [PATCH 0161/4982] avr32: Fix out-of-range rcalls in large kernels Replace handcoded rcall instructions with the call pseudo-instruction. For kernels too far over 1MB the rcall instruction can't reach and linking will fail. We already call the final linker with --relax which converts call pseudo-instructions to the right things anyway. This fixes arch/avr32/kernel/built-in.o: In function `syscall_exit_work': (.ex.text+0x198): relocation truncated to fit: R_AVR32_22H_PCREL against symbol `schedule' defined in .sched.text section in kernel/built-in.o arch/avr32/kernel/built-in.o: In function `fault_exit_work': (.ex.text+0x3b6): relocation truncated to fit: R_AVR32_22H_PCREL against symbol `schedule' defined in .sched.text section in kernel/built-in.o But I'm still left with arch/avr32/kernel/built-in.o:(.fixup+0x2): relocation truncated to fit: R_AVR32_22H_PCREL against `.text'+45a arch/avr32/kernel/built-in.o:(.fixup+0x8): relocation truncated to fit: R_AVR32_22H_PCREL against `.text'+8ea arch/avr32/kernel/built-in.o:(.fixup+0xe): relocation truncated to fit: R_AVR32_22H_PCREL against `.text'+abe arch/avr32/kernel/built-in.o:(.fixup+0x14): relocation truncated to fit: R_AVR32_22H_PCREL against `.text'+ac8 arch/avr32/kernel/built-in.o:(.fixup+0x1a): relocation truncated to fit: R_AVR32_22H_PCREL against `.text'+ad2 arch/avr32/kernel/built-in.o:(.fixup+0x20): relocation truncated to fit: R_AVR32_22H_PCREL against `.text'+adc arch/avr32/kernel/built-in.o:(.fixup+0x26): relocation truncated to fit: R_AVR32_22H_PCREL against `.text'+ae6 arch/avr32/kernel/built-in.o:(.fixup+0x2c): relocation truncated to fit: R_AVR32_22H_PCREL against `.text'+af0 arch/avr32/kernel/built-in.o:(.fixup+0x32): additional relocation overflows omitted from the output These are caused by a similar problem with 'rjmp' instructions. Unfortunately, there's no easy fix for these at the moment since we don't have a arbitrary-range 'jmp' instruction similar to 'call'. Signed-off-by: Ben Nizette Signed-off-by: Haavard Skinnemoen --- arch/avr32/kernel/entry-avr32b.S | 60 +++++++++++++++---------------- arch/avr32/kernel/syscall-stubs.S | 14 ++++---- arch/avr32/lib/strnlen_user.S | 2 +- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S index 33d49377b8b..009a80155d6 100644 --- a/arch/avr32/kernel/entry-avr32b.S +++ b/arch/avr32/kernel/entry-avr32b.S @@ -150,10 +150,10 @@ page_not_present: tlbmiss_restore sub sp, 4 stmts --sp, r0-lr - rcall save_full_context_ex + call save_full_context_ex mfsr r12, SYSREG_ECR mov r11, sp - rcall do_page_fault + call do_page_fault rjmp ret_from_exception .align 2 @@ -250,7 +250,7 @@ syscall_badsys: .global ret_from_fork ret_from_fork: - rcall schedule_tail + call schedule_tail /* check for syscall tracing */ get_thread_info r0 @@ -261,7 +261,7 @@ ret_from_fork: syscall_trace_enter: pushm r8-r12 - rcall syscall_trace + call syscall_trace popm r8-r12 rjmp syscall_trace_cont @@ -269,14 +269,14 @@ syscall_exit_work: bld r1, TIF_SYSCALL_TRACE brcc 1f unmask_interrupts - rcall syscall_trace + call syscall_trace mask_interrupts ld.w r1, r0[TI_flags] 1: bld r1, TIF_NEED_RESCHED brcc 2f unmask_interrupts - rcall schedule + call schedule mask_interrupts ld.w r1, r0[TI_flags] rjmp 1b @@ -287,7 +287,7 @@ syscall_exit_work: unmask_interrupts mov r12, sp mov r11, r0 - rcall do_notify_resume + call do_notify_resume mask_interrupts ld.w r1, r0[TI_flags] rjmp 1b @@ -394,7 +394,7 @@ handle_critical: mfsr r12, SYSREG_ECR mov r11, sp - rcall do_critical_exception + call do_critical_exception /* We should never get here... */ bad_return: @@ -407,18 +407,18 @@ bad_return: do_bus_error_write: sub sp, 4 stmts --sp, r0-lr - rcall save_full_context_ex + call save_full_context_ex mov r11, 1 rjmp 1f do_bus_error_read: sub sp, 4 stmts --sp, r0-lr - rcall save_full_context_ex + call save_full_context_ex mov r11, 0 1: mfsr r12, SYSREG_BEAR mov r10, sp - rcall do_bus_error + call do_bus_error rjmp ret_from_exception .align 1 @@ -433,7 +433,7 @@ do_nmi_ll: 1: pushm r8, r9 /* PC and SR */ mfsr r12, SYSREG_ECR mov r11, sp - rcall do_nmi + call do_nmi popm r8-r9 mtsr SYSREG_RAR_NMI, r8 tst r0, r0 @@ -457,29 +457,29 @@ do_nmi_ll: handle_address_fault: sub sp, 4 stmts --sp, r0-lr - rcall save_full_context_ex + call save_full_context_ex mfsr r12, SYSREG_ECR mov r11, sp - rcall do_address_exception + call do_address_exception rjmp ret_from_exception handle_protection_fault: sub sp, 4 stmts --sp, r0-lr - rcall save_full_context_ex + call save_full_context_ex mfsr r12, SYSREG_ECR mov r11, sp - rcall do_page_fault + call do_page_fault rjmp ret_from_exception .align 1 do_illegal_opcode_ll: sub sp, 4 stmts --sp, r0-lr - rcall save_full_context_ex + call save_full_context_ex mfsr r12, SYSREG_ECR mov r11, sp - rcall do_illegal_opcode + call do_illegal_opcode rjmp ret_from_exception do_dtlb_modified: @@ -513,11 +513,11 @@ do_dtlb_modified: do_fpe_ll: sub sp, 4 stmts --sp, r0-lr - rcall save_full_context_ex + call save_full_context_ex unmask_interrupts mov r12, 26 mov r11, sp - rcall do_fpe + call do_fpe rjmp ret_from_exception ret_from_exception: @@ -553,7 +553,7 @@ fault_resume_kernel: lddsp r4, sp[REG_SR] bld r4, SYSREG_GM_OFFSET brcs 1f - rcall preempt_schedule_irq + call preempt_schedule_irq 1: #endif @@ -582,7 +582,7 @@ fault_exit_work: bld r1, TIF_NEED_RESCHED brcc 1f unmask_interrupts - rcall schedule + call schedule mask_interrupts ld.w r1, r0[TI_flags] rjmp fault_exit_work @@ -593,7 +593,7 @@ fault_exit_work: unmask_interrupts mov r12, sp mov r11, r0 - rcall do_notify_resume + call do_notify_resume mask_interrupts ld.w r1, r0[TI_flags] rjmp fault_exit_work @@ -616,10 +616,10 @@ handle_debug: .Ldebug_fixup_cont: #ifdef CONFIG_TRACE_IRQFLAGS - rcall trace_hardirqs_off + call trace_hardirqs_off #endif mov r12, sp - rcall do_debug + call do_debug mov sp, r12 lddsp r2, sp[REG_SR] @@ -643,7 +643,7 @@ handle_debug: mtsr SYSREG_RSR_DBG, r11 mtsr SYSREG_RAR_DBG, r10 #ifdef CONFIG_TRACE_IRQFLAGS - rcall trace_hardirqs_on + call trace_hardirqs_on 1: #endif ldmts sp++, r0-lr @@ -676,7 +676,7 @@ debug_resume_kernel: #ifdef CONFIG_TRACE_IRQFLAGS bld r11, SYSREG_GM_OFFSET brcc 1f - rcall trace_hardirqs_on + call trace_hardirqs_on 1: #endif mfsr r2, SYSREG_SR @@ -747,7 +747,7 @@ irq_level\level: mov r11, sp mov r12, \level - rcall do_IRQ + call do_IRQ lddsp r4, sp[REG_SR] bfextu r4, r4, SYSREG_M0_OFFSET, 3 @@ -767,7 +767,7 @@ irq_level\level: 1: #ifdef CONFIG_TRACE_IRQFLAGS - rcall trace_hardirqs_on + call trace_hardirqs_on #endif popm r8-r9 mtsr rar_int\level, r8 @@ -807,7 +807,7 @@ irq_level\level: lddsp r4, sp[REG_SR] bld r4, SYSREG_GM_OFFSET brcs 1b - rcall preempt_schedule_irq + call preempt_schedule_irq #endif rjmp 1b .endm diff --git a/arch/avr32/kernel/syscall-stubs.S b/arch/avr32/kernel/syscall-stubs.S index 673178e235f..f7244cd02fb 100644 --- a/arch/avr32/kernel/syscall-stubs.S +++ b/arch/avr32/kernel/syscall-stubs.S @@ -61,7 +61,7 @@ __sys_execve: __sys_mmap2: pushm lr st.w --sp, ARG6 - rcall sys_mmap2 + call sys_mmap2 sub sp, -4 popm pc @@ -70,7 +70,7 @@ __sys_mmap2: __sys_sendto: pushm lr st.w --sp, ARG6 - rcall sys_sendto + call sys_sendto sub sp, -4 popm pc @@ -79,7 +79,7 @@ __sys_sendto: __sys_recvfrom: pushm lr st.w --sp, ARG6 - rcall sys_recvfrom + call sys_recvfrom sub sp, -4 popm pc @@ -88,7 +88,7 @@ __sys_recvfrom: __sys_pselect6: pushm lr st.w --sp, ARG6 - rcall sys_pselect6 + call sys_pselect6 sub sp, -4 popm pc @@ -97,7 +97,7 @@ __sys_pselect6: __sys_splice: pushm lr st.w --sp, ARG6 - rcall sys_splice + call sys_splice sub sp, -4 popm pc @@ -106,7 +106,7 @@ __sys_splice: __sys_epoll_pwait: pushm lr st.w --sp, ARG6 - rcall sys_epoll_pwait + call sys_epoll_pwait sub sp, -4 popm pc @@ -115,6 +115,6 @@ __sys_epoll_pwait: __sys_sync_file_range: pushm lr st.w --sp, ARG6 - rcall sys_sync_file_range + call sys_sync_file_range sub sp, -4 popm pc diff --git a/arch/avr32/lib/strnlen_user.S b/arch/avr32/lib/strnlen_user.S index 65ce11afa66..e46f4724962 100644 --- a/arch/avr32/lib/strnlen_user.S +++ b/arch/avr32/lib/strnlen_user.S @@ -48,7 +48,7 @@ adjust_length: lddpc lr, _task_size sub r11, lr, r12 mov r9, r11 - rcall __strnlen_user + call __strnlen_user cp.w r12, r9 brgt 1f popm pc -- GitLab From 61f3632fdcdcf547f6487f56b45976d7964756c4 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Wed, 14 Jan 2009 13:32:53 +0100 Subject: [PATCH 0162/4982] avr32: fix out-of-range rjmp instruction on large kernels Use .subsection to place fixups closer to their jump targets. This increases the maximum size of the kernel before we get link errors significantly. The problem here is that we don't have a "call"-ish pseudo-instruction to use instead of rjmp...we could add one, but that means we'll have to wait for a new toolchain release, wait until we're fairly sure most people are using it, etc... As an added bonus, it should decrease the RAM footprint slightly, though it might pollute the icache a bit more. Signed-off-by: Haavard Skinnemoen --- arch/avr32/include/asm/uaccess.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/avr32/include/asm/uaccess.h b/arch/avr32/include/asm/uaccess.h index ed092395215..245b2ee213c 100644 --- a/arch/avr32/include/asm/uaccess.h +++ b/arch/avr32/include/asm/uaccess.h @@ -230,10 +230,10 @@ extern int __put_user_bad(void); asm volatile( \ "1: ld." suffix " %1, %3 \n" \ "2: \n" \ - " .section .fixup, \"ax\" \n" \ + " .subsection 1 \n" \ "3: mov %0, %4 \n" \ " rjmp 2b \n" \ - " .previous \n" \ + " .subsection 0 \n" \ " .section __ex_table, \"a\" \n" \ " .long 1b, 3b \n" \ " .previous \n" \ @@ -295,10 +295,10 @@ extern int __put_user_bad(void); asm volatile( \ "1: st." suffix " %1, %3 \n" \ "2: \n" \ - " .section .fixup, \"ax\" \n" \ + " .subsection 1 \n" \ "3: mov %0, %4 \n" \ " rjmp 2b \n" \ - " .previous \n" \ + " .subsection 0 \n" \ " .section __ex_table, \"a\" \n" \ " .long 1b, 3b \n" \ " .previous \n" \ -- GitLab From 2165592b837e086f2b94835a2d81e6f3199c1319 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 16 Jan 2009 11:03:19 +0100 Subject: [PATCH 0163/4982] ALSA: snd-usb-caiaq: support for two more audio devices - Added support for two new audio devices from Native Instuments, 'Audio4DJ' and 'GuitarRig mobile' - Add missing statement about 'Session IO' in Kconfig help text - Version number bumped to 1.3.11 Signed-off-by: Daniel Mack Signed-off-by: Takashi Iwai --- sound/usb/Kconfig | 3 +++ sound/usb/caiaq/caiaq-audio.c | 5 +++-- sound/usb/caiaq/caiaq-control.c | 15 ++++++++++++--- sound/usb/caiaq/caiaq-device.c | 16 ++++++++++++++-- sound/usb/caiaq/caiaq-device.h | 2 ++ 5 files changed, 34 insertions(+), 7 deletions(-) diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index 4f0eac9bff1..523aec188cc 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig @@ -48,7 +48,10 @@ config SND_USB_CAIAQ * Native Instruments Kore Controller * Native Instruments Kore Controller 2 * Native Instruments Audio Kontrol 1 + * Native Instruments Audio 4 DJ * Native Instruments Audio 8 DJ + * Native Instruments Guitar Rig Session I/O + * Native Instruments Guitar Rig mobile To compile this driver as a module, choose M here: the module will be called snd-usb-caiaq. diff --git a/sound/usb/caiaq/caiaq-audio.c b/sound/usb/caiaq/caiaq-audio.c index b3a60332583..fc6d571eeac 100644 --- a/sound/usb/caiaq/caiaq-audio.c +++ b/sound/usb/caiaq/caiaq-audio.c @@ -638,9 +638,10 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev) case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_SESSIONIO): - dev->samplerates |= SNDRV_PCM_RATE_88200; + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_GUITARRIGMOBILE): dev->samplerates |= SNDRV_PCM_RATE_192000; - break; + /* fall thru */ + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): dev->samplerates |= SNDRV_PCM_RATE_88200; break; diff --git a/sound/usb/caiaq/caiaq-control.c b/sound/usb/caiaq/caiaq-control.c index ccd763dd716..6ac5489a0f2 100644 --- a/sound/usb/caiaq/caiaq-control.c +++ b/sound/usb/caiaq/caiaq-control.c @@ -39,14 +39,15 @@ static int control_info(struct snd_kcontrol *kcontrol, struct snd_usb_caiaqdev *dev = caiaqdev(chip->card); int pos = kcontrol->private_value; int is_intval = pos & CNT_INTVAL; + unsigned int id = dev->chip.usb_id; uinfo->count = 1; pos &= ~CNT_INTVAL; - if (dev->chip.usb_id == - USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ) + if (((id == USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ)) || + (id == USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ))) && (pos == 0)) { - /* current input mode of A8DJ */ + /* current input mode of A8DJ and A4DJ */ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->value.integer.min = 0; uinfo->value.integer.max = 2; @@ -247,6 +248,10 @@ static struct caiaq_controller a8dj_controller[] = { { "Software lock", 40 } }; +static struct caiaq_controller a4dj_controller[] = { + { "Current input mode", 0 | CNT_INTVAL } +}; + static int __devinit add_controls(struct caiaq_controller *c, int num, struct snd_usb_caiaqdev *dev) { @@ -295,6 +300,10 @@ int __devinit snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev) ret = add_controls(a8dj_controller, ARRAY_SIZE(a8dj_controller), dev); break; + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): + ret = add_controls(a4dj_controller, + ARRAY_SIZE(a4dj_controller), dev); + break; } return ret; diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c index 41c36b055f6..d09fc2a88cf 100644 --- a/sound/usb/caiaq/caiaq-device.c +++ b/sound/usb/caiaq/caiaq-device.c @@ -42,15 +42,17 @@ #endif MODULE_AUTHOR("Daniel Mack "); -MODULE_DESCRIPTION("caiaq USB audio, version 1.3.10"); +MODULE_DESCRIPTION("caiaq USB audio, version 1.3.11"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," "{Native Instruments, RigKontrol3}," "{Native Instruments, Kore Controller}," "{Native Instruments, Kore Controller 2}," "{Native Instruments, Audio Kontrol 1}," + "{Native Instruments, Audio 4 DJ}," "{Native Instruments, Audio 8 DJ}," - "{Native Instruments, Session I/O}}"); + "{Native Instruments, Session I/O}," + "{Native Instruments, GuitarRig mobile}"); static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */ @@ -116,6 +118,16 @@ static struct usb_device_id snd_usb_id_table[] = { .idVendor = USB_VID_NATIVEINSTRUMENTS, .idProduct = USB_PID_SESSIONIO }, + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = USB_VID_NATIVEINSTRUMENTS, + .idProduct = USB_PID_GUITARRIGMOBILE + }, + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = USB_VID_NATIVEINSTRUMENTS, + .idProduct = USB_PID_AUDIO4DJ + }, { /* terminator */ } }; diff --git a/sound/usb/caiaq/caiaq-device.h b/sound/usb/caiaq/caiaq-device.h index ab56e738c5f..0560c327d99 100644 --- a/sound/usb/caiaq/caiaq-device.h +++ b/sound/usb/caiaq/caiaq-device.h @@ -10,8 +10,10 @@ #define USB_PID_KORECONTROLLER 0x4711 #define USB_PID_KORECONTROLLER2 0x4712 #define USB_PID_AK1 0x0815 +#define USB_PID_AUDIO4DJ 0x0839 #define USB_PID_AUDIO8DJ 0x1978 #define USB_PID_SESSIONIO 0x1915 +#define USB_PID_GUITARRIGMOBILE 0x0d8d #define EP1_BUFSIZE 64 #define CAIAQ_USB_STR_LEN 0xff -- GitLab From 2d68259db26ad57fd9643f1c69b5181ec9836ca9 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 16 Jan 2009 17:14:38 +0900 Subject: [PATCH 0164/4982] clockevents: let set_mode() setup delta information Allow the set_mode() clockevent callback to decide and fill in delta details such as shift, mult, max_delta_ns and min_delta_ns. With this change the clockevent can be registered without delta details which allows us to keep the parent clock disabled until the clockevent gets setup using set_mode(). Letting set_mode() fill in or update delta details allows us to save power by disabling the parent clock while the clockevent is unused. This may however make the parent clock rate change, so next time the clockevent gets enabled we need let set_mode() to update the detla details accordingly. Doing it at registration time is not enough. Furthermore, the delta details seem unused in the case of periodic-only clockevent drivers, so this change also allows registration of such drivers without the delta details filled in. Signed-off-by: Magnus Damm Signed-off-by: Thomas Gleixner --- kernel/time/clockevents.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index ea2f48af83c..d13be216a79 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -68,6 +68,17 @@ void clockevents_set_mode(struct clock_event_device *dev, if (dev->mode != mode) { dev->set_mode(mode, dev); dev->mode = mode; + + /* + * A nsec2cyc multiplicator of 0 is invalid and we'd crash + * on it, so fix it up and emit a warning: + */ + if (mode == CLOCK_EVT_MODE_ONESHOT) { + if (unlikely(!dev->mult)) { + dev->mult = 1; + WARN_ON(1); + } + } } } @@ -168,15 +179,6 @@ void clockevents_register_device(struct clock_event_device *dev) BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED); BUG_ON(!dev->cpumask); - /* - * A nsec2cyc multiplicator of 0 is invalid and we'd crash - * on it, so fix it up and emit a warning: - */ - if (unlikely(!dev->mult)) { - dev->mult = 1; - WARN_ON(1); - } - spin_lock(&clockevents_lock); list_add(&dev->list, &clockevent_devices); -- GitLab From 34cb61359b503d7aff6447acb037a5efd6ce93b2 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 16 Jan 2009 13:36:06 +0100 Subject: [PATCH 0165/4982] sched: fix !CONFIG_SCHEDSTATS build failure Stephen Rothwell reported this linux-next build failure with !CONFIG_SCHEDSTATS: | In file included from kernel/sched.c:1703: | kernel/sched_fair.c: In function 'adaptive_gran': | kernel/sched_fair.c:1324: error: 'struct sched_entity' has no member named 'avg_wakeup' The start_runtime and avg_wakeup metrics are now not just for statistics, but also for scheduling - so they always need to be available. (Also move out the nr_migrations fields - for future perfcounters usage.) Reported-by: Stephen Rothwell Signed-off-by: Ingo Molnar --- include/linux/sched.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index daf4e07bc97..5d56b54350a 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1031,6 +1031,10 @@ struct sched_entity { u64 last_wakeup; u64 avg_overlap; + u64 start_runtime; + u64 avg_wakeup; + u64 nr_migrations; + #ifdef CONFIG_SCHEDSTATS u64 wait_start; u64 wait_max; @@ -1046,10 +1050,6 @@ struct sched_entity { u64 exec_max; u64 slice_max; - u64 start_runtime; - u64 avg_wakeup; - - u64 nr_migrations; u64 nr_migrations_cold; u64 nr_failed_migrations_affine; u64 nr_failed_migrations_running; -- GitLab From 7de6883faad71e3a253d55b9e1a47b89ebce0a31 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 13 Jan 2009 20:41:34 +0900 Subject: [PATCH 0166/4982] x86: fix pda_to_op() There's no instruction to move a 64bit immediate into memory location. Drop "i". Signed-off-by: Tejun Heo Signed-off-by: Ingo Molnar --- arch/x86/include/asm/pda.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h index 2fbfff88df3..cbd3f48a832 100644 --- a/arch/x86/include/asm/pda.h +++ b/arch/x86/include/asm/pda.h @@ -78,7 +78,7 @@ do { \ case 8: \ asm(op "q %1,%%gs:%c2": \ "+m" (_proxy_pda.field) : \ - "ri" ((T__)val), \ + "r" ((T__)val), \ "i"(pda_offset(field))); \ break; \ default: \ -- GitLab From f10fcd47120e80f66665567dbe17f5071c7aef52 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 13 Jan 2009 20:41:34 +0900 Subject: [PATCH 0167/4982] x86: make early_per_cpu() a lvalue and use it Make early_per_cpu() a lvalue as per_cpu() is and use it where applicable. Signed-off-by: Tejun Heo Signed-off-by: Ingo Molnar --- arch/x86/include/asm/percpu.h | 6 +++--- arch/x86/include/asm/topology.h | 5 +---- arch/x86/kernel/apic.c | 13 ++----------- 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index ece72053ba6..df644f3e53e 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h @@ -195,9 +195,9 @@ do { \ #define early_per_cpu_ptr(_name) (_name##_early_ptr) #define early_per_cpu_map(_name, _idx) (_name##_early_map[_idx]) #define early_per_cpu(_name, _cpu) \ - (early_per_cpu_ptr(_name) ? \ - early_per_cpu_ptr(_name)[_cpu] : \ - per_cpu(_name, _cpu)) + *(early_per_cpu_ptr(_name) ? \ + &early_per_cpu_ptr(_name)[_cpu] : \ + &per_cpu(_name, _cpu)) #else /* !CONFIG_SMP */ #define DEFINE_EARLY_PER_CPU(_type, _name, _initvalue) \ diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h index 4e2f2e0aab2..87ca3fd86e8 100644 --- a/arch/x86/include/asm/topology.h +++ b/arch/x86/include/asm/topology.h @@ -102,10 +102,7 @@ static inline int cpu_to_node(int cpu) /* Same function but used if called before per_cpu areas are setup */ static inline int early_cpu_to_node(int cpu) { - if (early_per_cpu_ptr(x86_cpu_to_node_map)) - return early_per_cpu_ptr(x86_cpu_to_node_map)[cpu]; - - return per_cpu(x86_cpu_to_node_map, cpu); + return early_per_cpu(x86_cpu_to_node_map, cpu); } /* Returns a pointer to the cpumask of CPUs on Node 'node'. */ diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 38d6aab2358..48578795583 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -1877,17 +1877,8 @@ void __cpuinit generic_processor_info(int apicid, int version) #endif #if defined(CONFIG_X86_SMP) || defined(CONFIG_X86_64) - /* are we being called early in kernel startup? */ - if (early_per_cpu_ptr(x86_cpu_to_apicid)) { - u16 *cpu_to_apicid = early_per_cpu_ptr(x86_cpu_to_apicid); - u16 *bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid); - - cpu_to_apicid[cpu] = apicid; - bios_cpu_apicid[cpu] = apicid; - } else { - per_cpu(x86_cpu_to_apicid, cpu) = apicid; - per_cpu(x86_bios_cpu_apicid, cpu) = apicid; - } + early_per_cpu(x86_cpu_to_apicid, cpu) = apicid; + early_per_cpu(x86_bios_cpu_apicid, cpu) = apicid; #endif set_cpu_possible(cpu, true); -- GitLab From c90aa894f0240084f2c6e42e2333b211d6cfe2b2 Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Tue, 13 Jan 2009 20:41:34 +0900 Subject: [PATCH 0168/4982] x86: cleanup early setup_percpu references [ Based on original patch from Christoph Lameter and Mike Travis. ] * Ruggedize some calls in setup_percpu.c to prevent mishaps in early calls, particularly for non-critical functions. * Cleanup DEBUG_PER_CPU_MAPS usages and some comments. Signed-off-by: Mike Travis Signed-off-by: Tejun Heo Signed-off-by: Ingo Molnar --- arch/x86/kernel/setup_percpu.c | 56 ++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index bf63de72b64..56c63ac62b1 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -15,6 +15,12 @@ #include #include +#ifdef CONFIG_DEBUG_PER_CPU_MAPS +# define DBG(x...) printk(KERN_DEBUG x) +#else +# define DBG(x...) +#endif + #ifdef CONFIG_X86_LOCAL_APIC unsigned int num_processors; unsigned disabled_cpus __cpuinitdata; @@ -27,31 +33,39 @@ unsigned int max_physical_apicid; physid_mask_t phys_cpu_present_map; #endif -/* map cpu index to physical APIC ID */ +/* + * Map cpu index to physical APIC ID + */ DEFINE_EARLY_PER_CPU(u16, x86_cpu_to_apicid, BAD_APICID); DEFINE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid, BAD_APICID); EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_apicid); EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid); #if defined(CONFIG_NUMA) && defined(CONFIG_X86_64) -#define X86_64_NUMA 1 +#define X86_64_NUMA 1 /* (used later) */ -/* map cpu index to node index */ +/* + * Map cpu index to node index + */ DEFINE_EARLY_PER_CPU(int, x86_cpu_to_node_map, NUMA_NO_NODE); EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_node_map); -/* which logical CPUs are on which nodes */ +/* + * Which logical CPUs are on which nodes + */ cpumask_t *node_to_cpumask_map; EXPORT_SYMBOL(node_to_cpumask_map); -/* setup node_to_cpumask_map */ +/* + * Setup node_to_cpumask_map + */ static void __init setup_node_to_cpumask_map(void); #else static inline void setup_node_to_cpumask_map(void) { } #endif -#if defined(CONFIG_HAVE_SETUP_PER_CPU_AREA) && defined(CONFIG_X86_SMP) +#ifdef CONFIG_HAVE_SETUP_PER_CPU_AREA /* * Copy data used in early init routines from the initial arrays to the * per cpu data areas. These arrays then become expendable and the @@ -200,6 +214,8 @@ void __init setup_per_cpu_areas(void) #endif per_cpu_offset(cpu) = ptr - __per_cpu_start; memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); + + DBG("PERCPU: cpu %4d %p\n", cpu, ptr); } /* Setup percpu data maps */ @@ -221,6 +237,7 @@ void __init setup_per_cpu_areas(void) * Requires node_possible_map to be valid. * * Note: node_to_cpumask() is not valid until after this is done. + * (Use CONFIG_DEBUG_PER_CPU_MAPS to check this.) */ static void __init setup_node_to_cpumask_map(void) { @@ -236,6 +253,7 @@ static void __init setup_node_to_cpumask_map(void) /* allocate the map */ map = alloc_bootmem_low(nr_node_ids * sizeof(cpumask_t)); + DBG("node_to_cpumask_map at %p for %d nodes\n", map, nr_node_ids); pr_debug("Node to cpumask map at %p for %d nodes\n", map, nr_node_ids); @@ -248,17 +266,23 @@ void __cpuinit numa_set_node(int cpu, int node) { int *cpu_to_node_map = early_per_cpu_ptr(x86_cpu_to_node_map); - if (cpu_pda(cpu) && node != NUMA_NO_NODE) - cpu_pda(cpu)->nodenumber = node; - - if (cpu_to_node_map) + /* early setting, no percpu area yet */ + if (cpu_to_node_map) { cpu_to_node_map[cpu] = node; + return; + } - else if (per_cpu_offset(cpu)) - per_cpu(x86_cpu_to_node_map, cpu) = node; +#ifdef CONFIG_DEBUG_PER_CPU_MAPS + if (cpu >= nr_cpu_ids || !per_cpu_offset(cpu)) { + printk(KERN_ERR "numa_set_node: invalid cpu# (%d)\n", cpu); + dump_stack(); + return; + } +#endif + per_cpu(x86_cpu_to_node_map, cpu) = node; - else - pr_debug("Setting node for non-present cpu %d\n", cpu); + if (node != NUMA_NO_NODE) + cpu_pda(cpu)->nodenumber = node; } void __cpuinit numa_clear_node(int cpu) @@ -275,7 +299,7 @@ void __cpuinit numa_add_cpu(int cpu) void __cpuinit numa_remove_cpu(int cpu) { - cpu_clear(cpu, node_to_cpumask_map[cpu_to_node(cpu)]); + cpu_clear(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); } #else /* CONFIG_DEBUG_PER_CPU_MAPS */ @@ -285,7 +309,7 @@ void __cpuinit numa_remove_cpu(int cpu) */ static void __cpuinit numa_set_cpumask(int cpu, int enable) { - int node = cpu_to_node(cpu); + int node = early_cpu_to_node(cpu); cpumask_t *mask; char buf[64]; -- GitLab From a698c823e15149941b0f0281527d0c0d1daf2639 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 13 Jan 2009 20:41:35 +0900 Subject: [PATCH 0169/4982] x86: make vmlinux_32.lds.S use PERCPU() macro Make vmlinux_32.lds.S use the generic PERCPU() macro instead of open coding it. This will ease future changes. Signed-off-by: Tejun Heo Signed-off-by: Ingo Molnar --- arch/x86/kernel/vmlinux_32.lds.S | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/arch/x86/kernel/vmlinux_32.lds.S b/arch/x86/kernel/vmlinux_32.lds.S index 82c67559dde..3eba7f7bac0 100644 --- a/arch/x86/kernel/vmlinux_32.lds.S +++ b/arch/x86/kernel/vmlinux_32.lds.S @@ -178,14 +178,7 @@ SECTIONS __initramfs_end = .; } #endif - . = ALIGN(PAGE_SIZE); - .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { - __per_cpu_start = .; - *(.data.percpu.page_aligned) - *(.data.percpu) - *(.data.percpu.shared_aligned) - __per_cpu_end = .; - } + PERCPU(PAGE_SIZE) . = ALIGN(PAGE_SIZE); /* freed after init ends here */ -- GitLab From 3e5d8f978435bb9ba4dfe3f4514e65e7885db1a9 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 13 Jan 2009 20:41:35 +0900 Subject: [PATCH 0170/4982] x86: make percpu symbols zerobased on SMP [ Based on original patch from Christoph Lameter and Mike Travis. ] This patch makes percpu symbols zerobased on x86_64 SMP by adding PERCPU_VADDR() to vmlinux.lds.h which helps setting explicit vaddr on the percpu output section and using it in vmlinux_64.lds.S. A new PHDR is added as existing ones cannot contain sections near address zero. PERCPU_VADDR() also adds a new symbol __per_cpu_load which always points to the vaddr of the loaded percpu data.init region. The following adjustments have been made to accomodate the address change. * code to locate percpu gdt_page in head_64.S is updated to add the load address to the gdt_page offset. * __per_cpu_load is used in places where access to the init data area is necessary. * pda->data_offset is initialized soon after C code is entered as zero value doesn't work anymore. This patch is mostly taken from Mike Travis' "x86_64: Base percpu variables at zero" patch. Signed-off-by: Tejun Heo Signed-off-by: Ingo Molnar --- arch/x86/kernel/head64.c | 2 ++ arch/x86/kernel/head_64.S | 24 ++++++++++++++- arch/x86/kernel/setup_percpu.c | 2 +- arch/x86/kernel/vmlinux_64.lds.S | 17 ++++++++++- include/asm-generic/sections.h | 2 +- include/asm-generic/vmlinux.lds.h | 51 +++++++++++++++++++++++++++---- 6 files changed, 88 insertions(+), 10 deletions(-) diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index b9a4d8c4b93..bc2900ca82c 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -44,6 +44,8 @@ void __init x86_64_init_pda(void) { _cpu_pda = __cpu_pda; cpu_pda(0) = &_boot_cpu_pda; + cpu_pda(0)->data_offset = + (unsigned long)(__per_cpu_load - __per_cpu_start); pda_init(0); } diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 0e275d49556..7ee0363871e 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -204,6 +204,23 @@ ENTRY(secondary_startup_64) pushq $0 popfq +#ifdef CONFIG_SMP + /* + * early_gdt_base should point to the gdt_page in static percpu init + * data area. Computing this requires two symbols - __per_cpu_load + * and per_cpu__gdt_page. As linker can't do no such relocation, do + * it by hand. As early_gdt_descr is manipulated by C code for + * secondary CPUs, this should be done only once for the boot CPU + * when early_gdt_descr_base contains zero. + */ + movq early_gdt_descr_base(%rip), %rax + testq %rax, %rax + jnz 1f + movq $__per_cpu_load, %rax + addq $per_cpu__gdt_page, %rax + movq %rax, early_gdt_descr_base(%rip) +1: +#endif /* * We must switch to a new descriptor in kernel space for the GDT * because soon the kernel won't have access anymore to the userspace @@ -401,7 +418,12 @@ NEXT_PAGE(level2_spare_pgt) .globl early_gdt_descr early_gdt_descr: .word GDT_ENTRIES*8-1 - .quad per_cpu__gdt_page +#ifdef CONFIG_SMP +early_gdt_descr_base: + .quad 0x0000000000000000 +#else + .quad per_cpu__gdt_page +#endif ENTRY(phys_base) /* This must match the first entry in level2_kernel_pgt */ diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 56c63ac62b1..44845842e72 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -213,7 +213,7 @@ void __init setup_per_cpu_areas(void) } #endif per_cpu_offset(cpu) = ptr - __per_cpu_start; - memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); + memcpy(ptr, __per_cpu_load, __per_cpu_end - __per_cpu_start); DBG("PERCPU: cpu %4d %p\n", cpu, ptr); } diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S index 1a614c0e6be..f50280db0df 100644 --- a/arch/x86/kernel/vmlinux_64.lds.S +++ b/arch/x86/kernel/vmlinux_64.lds.S @@ -19,6 +19,9 @@ PHDRS { data PT_LOAD FLAGS(7); /* RWE */ user PT_LOAD FLAGS(7); /* RWE */ data.init PT_LOAD FLAGS(7); /* RWE */ +#ifdef CONFIG_SMP + percpu PT_LOAD FLAGS(7); /* RWE */ +#endif note PT_NOTE FLAGS(0); /* ___ */ } SECTIONS @@ -208,14 +211,26 @@ SECTIONS __initramfs_end = .; #endif +#ifdef CONFIG_SMP + /* + * percpu offsets are zero-based on SMP. PERCPU_VADDR() changes the + * output PHDR, so the next output section - __data_nosave - should + * switch it back to data.init. + */ + . = ALIGN(PAGE_SIZE); + PERCPU_VADDR(0, :percpu) +#else PERCPU(PAGE_SIZE) +#endif . = ALIGN(PAGE_SIZE); __init_end = .; . = ALIGN(PAGE_SIZE); __nosave_begin = .; - .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.data.nosave) } + .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { + *(.data.nosave) + } :data.init /* switch back to data.init, see PERCPU_VADDR() above */ . = ALIGN(PAGE_SIZE); __nosave_end = .; diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h index 79a7ff925bf..4ce48e87853 100644 --- a/include/asm-generic/sections.h +++ b/include/asm-generic/sections.h @@ -9,7 +9,7 @@ extern char __bss_start[], __bss_stop[]; extern char __init_begin[], __init_end[]; extern char _sinittext[], _einittext[]; extern char _end[]; -extern char __per_cpu_start[], __per_cpu_end[]; +extern char __per_cpu_load[], __per_cpu_start[], __per_cpu_end[]; extern char __kprobes_text_start[], __kprobes_text_end[]; extern char __initdata_begin[], __initdata_end[]; extern char __start_rodata[], __end_rodata[]; diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index c61fab1dd2f..fc2f55f2dcd 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -430,12 +430,51 @@ *(.initcall7.init) \ *(.initcall7s.init) -#define PERCPU(align) \ - . = ALIGN(align); \ - VMLINUX_SYMBOL(__per_cpu_start) = .; \ - .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { \ +#define PERCPU_PROLOG(vaddr) \ + VMLINUX_SYMBOL(__per_cpu_load) = .; \ + .data.percpu vaddr : AT(__per_cpu_load - LOAD_OFFSET) { \ + VMLINUX_SYMBOL(__per_cpu_start) = .; + +#define PERCPU_EPILOG(phdr) \ + VMLINUX_SYMBOL(__per_cpu_end) = .; \ + } phdr \ + . = __per_cpu_load + SIZEOF(.data.percpu); + +/** + * PERCPU_VADDR - define output section for percpu area + * @vaddr: explicit base address (optional) + * @phdr: destination PHDR (optional) + * + * Macro which expands to output section for percpu area. If @vaddr + * is not blank, it specifies explicit base address and all percpu + * symbols will be offset from the given address. If blank, @vaddr + * always equals @laddr + LOAD_OFFSET. + * + * @phdr defines the output PHDR to use if not blank. Be warned that + * output PHDR is sticky. If @phdr is specified, the next output + * section in the linker script will go there too. @phdr should have + * a leading colon. + * + * This macro defines three symbols, __per_cpu_load, __per_cpu_start + * and __per_cpu_end. The first one is the vaddr of loaded percpu + * init data. __per_cpu_start equals @vaddr and __per_cpu_end is the + * end offset. + */ +#define PERCPU_VADDR(vaddr, phdr) \ + PERCPU_PROLOG(vaddr) \ *(.data.percpu.page_aligned) \ *(.data.percpu) \ *(.data.percpu.shared_aligned) \ - } \ - VMLINUX_SYMBOL(__per_cpu_end) = .; + PERCPU_EPILOG(phdr) + +/** + * PERCPU - define output section for percpu area, simple version + * @align: required alignment + * + * Align to @align and outputs output section for percpu area. This + * macro doesn't maniuplate @vaddr or @phdr and __per_cpu_load and + * __per_cpu_start will be identical. + */ +#define PERCPU(align) \ + . = ALIGN(align); \ + PERCPU_VADDR( , ) -- GitLab From f32ff5388d86518c0375ccdb330d3b459b9c405e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 13 Jan 2009 20:41:35 +0900 Subject: [PATCH 0171/4982] x86: load pointer to pda into %gs while brining up a CPU [ Based on original patch from Christoph Lameter and Mike Travis. ] CPU startup code in head_64.S loaded address of a zero page into %gs for temporary use till pda is loaded but address to the actual pda is available at the point. Load the real address directly instead. This will help unifying percpu and pda handling later on. This patch is mostly taken from Mike Travis' "x86_64: Fold pda into per cpu area" patch. Signed-off-by: Tejun Heo --- arch/x86/include/asm/trampoline.h | 1 + arch/x86/kernel/acpi/sleep.c | 1 + arch/x86/kernel/head64.c | 4 ++-- arch/x86/kernel/head_64.S | 15 ++++++++++----- arch/x86/kernel/smpboot.c | 1 + 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/arch/x86/include/asm/trampoline.h b/arch/x86/include/asm/trampoline.h index 780ba0ab94f..90f06c25221 100644 --- a/arch/x86/include/asm/trampoline.h +++ b/arch/x86/include/asm/trampoline.h @@ -13,6 +13,7 @@ extern unsigned char *trampoline_base; extern unsigned long init_rsp; extern unsigned long initial_code; +extern unsigned long initial_gs; #define TRAMPOLINE_SIZE roundup(trampoline_end - trampoline_data, PAGE_SIZE) #define TRAMPOLINE_BASE 0x6000 diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 707c1f6f95f..9ff67f8dc2c 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -101,6 +101,7 @@ int acpi_save_state_mem(void) stack_start.sp = temp_stack + sizeof(temp_stack); early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(smp_processor_id()); + initial_gs = (unsigned long)cpu_pda(smp_processor_id()); #endif initial_code = (unsigned long)wakeup_long64; saved_magic = 0x123456789abcdef0; diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index bc2900ca82c..76ffba2aa66 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -26,8 +26,8 @@ #include #include -/* boot cpu pda */ -static struct x8664_pda _boot_cpu_pda; +/* boot cpu pda, referenced by head_64.S to initialize %gs for boot CPU */ +struct x8664_pda _boot_cpu_pda; #ifdef CONFIG_SMP /* diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 7ee0363871e..2f0ab008988 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -243,12 +243,15 @@ ENTRY(secondary_startup_64) movl %eax,%fs movl %eax,%gs - /* - * Setup up a dummy PDA. this is just for some early bootup code - * that does in_interrupt() - */ + /* Set up %gs. + * + * %gs should point to the pda. For initial boot, make %gs point + * to the _boot_cpu_pda in data section. For a secondary CPU, + * initial_gs should be set to its pda address before the CPU runs + * this code. + */ movl $MSR_GS_BASE,%ecx - movq $empty_zero_page,%rax + movq initial_gs(%rip),%rax movq %rax,%rdx shrq $32,%rdx wrmsr @@ -274,6 +277,8 @@ ENTRY(secondary_startup_64) .align 8 ENTRY(initial_code) .quad x86_64_start_kernel + ENTRY(initial_gs) + .quad _boot_cpu_pda __FINITDATA ENTRY(stack_start) diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 1a712da1dfa..70d846628bb 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -854,6 +854,7 @@ do_rest: #else cpu_pda(cpu)->pcurrent = c_idle.idle; clear_tsk_thread_flag(c_idle.idle, TIF_FORK); + initial_gs = (unsigned long)cpu_pda(cpu); #endif early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu); initial_code = (unsigned long)start_secondary; -- GitLab From c8f3329a0ddd751241e96b4100df7eda14b2cbc6 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 13 Jan 2009 20:41:35 +0900 Subject: [PATCH 0172/4982] x86: use static _cpu_pda array _cpu_pda array first uses statically allocated storage in data.init and then switches to allocated bootmem to conserve space. However, after folding pda area into percpu area, _cpu_pda array will be removed completely. Drop the reallocation part to simplify the code for soon-to-follow changes. Signed-off-by: Tejun Heo Signed-off-by: Ingo Molnar --- arch/x86/include/asm/pda.h | 3 ++- arch/x86/kernel/cpu/common.c | 2 +- arch/x86/kernel/head64.c | 12 ------------ arch/x86/kernel/setup_percpu.c | 14 +++----------- 4 files changed, 6 insertions(+), 25 deletions(-) diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h index cbd3f48a832..2d5b49c3248 100644 --- a/arch/x86/include/asm/pda.h +++ b/arch/x86/include/asm/pda.h @@ -5,6 +5,7 @@ #include #include #include +#include #include /* Per processor datastructure. %gs points to it while the kernel runs */ @@ -39,7 +40,7 @@ struct x8664_pda { unsigned irq_spurious_count; } ____cacheline_aligned_in_smp; -extern struct x8664_pda **_cpu_pda; +extern struct x8664_pda *_cpu_pda[NR_CPUS]; extern void pda_init(int); #define cpu_pda(i) (_cpu_pda[i]) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index f0025846244..c116c599326 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -879,7 +879,7 @@ static __init int setup_disablecpuid(char *arg) __setup("clearcpuid=", setup_disablecpuid); #ifdef CONFIG_X86_64 -struct x8664_pda **_cpu_pda __read_mostly; +struct x8664_pda *_cpu_pda[NR_CPUS] __read_mostly; EXPORT_SYMBOL(_cpu_pda); struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table }; diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 76ffba2aa66..462d0beccb6 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -29,20 +29,8 @@ /* boot cpu pda, referenced by head_64.S to initialize %gs for boot CPU */ struct x8664_pda _boot_cpu_pda; -#ifdef CONFIG_SMP -/* - * We install an empty cpu_pda pointer table to indicate to early users - * (numa_set_node) that the cpu_pda pointer table for cpus other than - * the boot cpu is not yet setup. - */ -static struct x8664_pda *__cpu_pda[NR_CPUS] __initdata; -#else -static struct x8664_pda *__cpu_pda[NR_CPUS] __read_mostly; -#endif - void __init x86_64_init_pda(void) { - _cpu_pda = __cpu_pda; cpu_pda(0) = &_boot_cpu_pda; cpu_pda(0)->data_offset = (unsigned long)(__per_cpu_load - __per_cpu_start); diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 44845842e72..73ab01b297c 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -114,7 +114,6 @@ static inline void setup_cpu_pda_map(void) { } static void __init setup_cpu_pda_map(void) { char *pda; - struct x8664_pda **new_cpu_pda; unsigned long size; int cpu; @@ -122,28 +121,21 @@ static void __init setup_cpu_pda_map(void) /* allocate cpu_pda array and pointer table */ { - unsigned long tsize = nr_cpu_ids * sizeof(void *); unsigned long asize = size * (nr_cpu_ids - 1); - tsize = roundup(tsize, cache_line_size()); - new_cpu_pda = alloc_bootmem(tsize + asize); - pda = (char *)new_cpu_pda + tsize; + pda = alloc_bootmem(asize); } /* initialize pointer table to static pda's */ for_each_possible_cpu(cpu) { if (cpu == 0) { /* leave boot cpu pda in place */ - new_cpu_pda[0] = cpu_pda(0); continue; } - new_cpu_pda[cpu] = (struct x8664_pda *)pda; - new_cpu_pda[cpu]->in_bootmem = 1; + cpu_pda(cpu) = (struct x8664_pda *)pda; + cpu_pda(cpu)->in_bootmem = 1; pda += size; } - - /* point to new pointer table */ - _cpu_pda = new_cpu_pda; } #endif /* CONFIG_SMP && CONFIG_X86_64 */ -- GitLab From 1a51e3a0aed18767cf2762e95456ecfeb0bca5e6 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 13 Jan 2009 20:41:35 +0900 Subject: [PATCH 0173/4982] x86: fold pda into percpu area on SMP [ Based on original patch from Christoph Lameter and Mike Travis. ] Currently pdas and percpu areas are allocated separately. %gs points to local pda and percpu area can be reached using pda->data_offset. This patch folds pda into percpu area. Due to strange gcc requirement, pda needs to be at the beginning of the percpu area so that pda->stack_canary is at %gs:40. To achieve this, a new percpu output section macro - PERCPU_VADDR_PREALLOC() - is added and used to reserve pda sized chunk at the start of the percpu area. After this change, for boot cpu, %gs first points to pda in the data.init area and later during setup_per_cpu_areas() gets updated to point to the actual pda. This means that setup_per_cpu_areas() need to reload %gs for CPU0 while clearing pda area for other cpus as cpu0 already has modified it when control reaches setup_per_cpu_areas(). This patch also removes now unnecessary get_local_pda() and its call sites. A lot of this patch is taken from Mike Travis' "x86_64: Fold pda into per cpu area" patch. Signed-off-by: Tejun Heo Signed-off-by: Ingo Molnar --- arch/x86/include/asm/percpu.h | 8 +++ arch/x86/include/asm/smp.h | 2 - arch/x86/kernel/asm-offsets_64.c | 1 + arch/x86/kernel/cpu/common.c | 6 +- arch/x86/kernel/head64.c | 8 ++- arch/x86/kernel/head_64.S | 15 +++-- arch/x86/kernel/setup_percpu.c | 107 +++++++++++++----------------- arch/x86/kernel/smpboot.c | 60 +---------------- arch/x86/kernel/vmlinux_64.lds.S | 6 +- arch/x86/xen/smp.c | 10 --- include/asm-generic/vmlinux.lds.h | 25 ++++++- 11 files changed, 104 insertions(+), 144 deletions(-) diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index df644f3e53e..0ed77cf33f7 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h @@ -1,6 +1,14 @@ #ifndef _ASM_X86_PERCPU_H #define _ASM_X86_PERCPU_H +#ifndef __ASSEMBLY__ +#ifdef CONFIG_X86_64 +extern void load_pda_offset(int cpu); +#else +static inline void load_pda_offset(int cpu) { } +#endif +#endif + #ifdef CONFIG_X86_64 #include diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index a8cea7b0943..127415402ea 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -19,8 +19,6 @@ #include #include -extern int __cpuinit get_local_pda(int cpu); - extern int smp_num_siblings; extern unsigned int num_processors; diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index 1d41d3f1edb..f8d1b047ef4 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c @@ -56,6 +56,7 @@ int main(void) ENTRY(cpunumber); ENTRY(irqstackptr); ENTRY(data_offset); + DEFINE(pda_size, sizeof(struct x8664_pda)); BLANK(); #undef ENTRY #ifdef CONFIG_PARAVIRT diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index c116c599326..7041acdf557 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -893,10 +893,8 @@ void __cpuinit pda_init(int cpu) /* Setup up data that may be needed in __get_free_pages early */ loadsegment(fs, 0); loadsegment(gs, 0); - /* Memory clobbers used to order PDA accessed */ - mb(); - wrmsrl(MSR_GS_BASE, pda); - mb(); + + load_pda_offset(cpu); pda->cpunumber = cpu; pda->irqcount = -1; diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 462d0beccb6..1a311293f73 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -26,12 +26,18 @@ #include #include -/* boot cpu pda, referenced by head_64.S to initialize %gs for boot CPU */ +#ifndef CONFIG_SMP +/* boot cpu pda, referenced by head_64.S to initialize %gs on UP */ struct x8664_pda _boot_cpu_pda; +#endif void __init x86_64_init_pda(void) { +#ifdef CONFIG_SMP + cpu_pda(0) = (void *)__per_cpu_load; +#else cpu_pda(0) = &_boot_cpu_pda; +#endif cpu_pda(0)->data_offset = (unsigned long)(__per_cpu_load - __per_cpu_start); pda_init(0); diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 2f0ab008988..7a995d0e9f7 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -245,10 +245,13 @@ ENTRY(secondary_startup_64) /* Set up %gs. * - * %gs should point to the pda. For initial boot, make %gs point - * to the _boot_cpu_pda in data section. For a secondary CPU, - * initial_gs should be set to its pda address before the CPU runs - * this code. + * On SMP, %gs should point to the per-cpu area. For initial + * boot, make %gs point to the init data section. For a + * secondary CPU,initial_gs should be set to its pda address + * before the CPU runs this code. + * + * On UP, initial_gs points to _boot_cpu_pda and doesn't + * change. */ movl $MSR_GS_BASE,%ecx movq initial_gs(%rip),%rax @@ -278,7 +281,11 @@ ENTRY(secondary_startup_64) ENTRY(initial_code) .quad x86_64_start_kernel ENTRY(initial_gs) +#ifdef CONFIG_SMP + .quad __per_cpu_load +#else .quad _boot_cpu_pda +#endif __FINITDATA ENTRY(stack_start) diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 73ab01b297c..63d46280227 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #ifdef CONFIG_DEBUG_PER_CPU_MAPS @@ -65,6 +66,36 @@ static void __init setup_node_to_cpumask_map(void); static inline void setup_node_to_cpumask_map(void) { } #endif +#ifdef CONFIG_X86_64 +void __cpuinit load_pda_offset(int cpu) +{ + /* Memory clobbers used to order pda/percpu accesses */ + mb(); + wrmsrl(MSR_GS_BASE, cpu_pda(cpu)); + mb(); +} + +#endif /* CONFIG_SMP && CONFIG_X86_64 */ + +#ifdef CONFIG_X86_64 + +/* correctly size the local cpu masks */ +static void setup_cpu_local_masks(void) +{ + alloc_bootmem_cpumask_var(&cpu_initialized_mask); + alloc_bootmem_cpumask_var(&cpu_callin_mask); + alloc_bootmem_cpumask_var(&cpu_callout_mask); + alloc_bootmem_cpumask_var(&cpu_sibling_setup_mask); +} + +#else /* CONFIG_X86_32 */ + +static inline void setup_cpu_local_masks(void) +{ +} + +#endif /* CONFIG_X86_32 */ + #ifdef CONFIG_HAVE_SETUP_PER_CPU_AREA /* * Copy data used in early init routines from the initial arrays to the @@ -101,63 +132,7 @@ static void __init setup_per_cpu_maps(void) */ unsigned long __per_cpu_offset[NR_CPUS] __read_mostly; EXPORT_SYMBOL(__per_cpu_offset); -static inline void setup_cpu_pda_map(void) { } - -#elif !defined(CONFIG_SMP) -static inline void setup_cpu_pda_map(void) { } - -#else /* CONFIG_SMP && CONFIG_X86_64 */ - -/* - * Allocate cpu_pda pointer table and array via alloc_bootmem. - */ -static void __init setup_cpu_pda_map(void) -{ - char *pda; - unsigned long size; - int cpu; - - size = roundup(sizeof(struct x8664_pda), cache_line_size()); - - /* allocate cpu_pda array and pointer table */ - { - unsigned long asize = size * (nr_cpu_ids - 1); - - pda = alloc_bootmem(asize); - } - - /* initialize pointer table to static pda's */ - for_each_possible_cpu(cpu) { - if (cpu == 0) { - /* leave boot cpu pda in place */ - continue; - } - cpu_pda(cpu) = (struct x8664_pda *)pda; - cpu_pda(cpu)->in_bootmem = 1; - pda += size; - } -} - -#endif /* CONFIG_SMP && CONFIG_X86_64 */ - -#ifdef CONFIG_X86_64 - -/* correctly size the local cpu masks */ -static void setup_cpu_local_masks(void) -{ - alloc_bootmem_cpumask_var(&cpu_initialized_mask); - alloc_bootmem_cpumask_var(&cpu_callin_mask); - alloc_bootmem_cpumask_var(&cpu_callout_mask); - alloc_bootmem_cpumask_var(&cpu_sibling_setup_mask); -} - -#else /* CONFIG_X86_32 */ - -static inline void setup_cpu_local_masks(void) -{ -} - -#endif /* CONFIG_X86_32 */ +#endif /* * Great future plan: @@ -171,9 +146,6 @@ void __init setup_per_cpu_areas(void) int cpu; unsigned long align = 1; - /* Setup cpu_pda map */ - setup_cpu_pda_map(); - /* Copy section for each CPU (we discard the original) */ old_size = PERCPU_ENOUGH_ROOM; align = max_t(unsigned long, PAGE_SIZE, align); @@ -204,8 +176,21 @@ void __init setup_per_cpu_areas(void) cpu, node, __pa(ptr)); } #endif - per_cpu_offset(cpu) = ptr - __per_cpu_start; + memcpy(ptr, __per_cpu_load, __per_cpu_end - __per_cpu_start); +#ifdef CONFIG_X86_64 + cpu_pda(cpu) = (void *)ptr; + + /* + * CPU0 modified pda in the init data area, reload pda + * offset for CPU0 and clear the area for others. + */ + if (cpu == 0) + load_pda_offset(0); + else + memset(cpu_pda(cpu), 0, sizeof(*cpu_pda(cpu))); +#endif + per_cpu_offset(cpu) = ptr - __per_cpu_start; DBG("PERCPU: cpu %4d %p\n", cpu, ptr); } diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 70d846628bb..f2f77ca494d 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -744,52 +744,6 @@ static void __cpuinit do_fork_idle(struct work_struct *work) complete(&c_idle->done); } -#ifdef CONFIG_X86_64 - -/* __ref because it's safe to call free_bootmem when after_bootmem == 0. */ -static void __ref free_bootmem_pda(struct x8664_pda *oldpda) -{ - if (!after_bootmem) - free_bootmem((unsigned long)oldpda, sizeof(*oldpda)); -} - -/* - * Allocate node local memory for the AP pda. - * - * Must be called after the _cpu_pda pointer table is initialized. - */ -int __cpuinit get_local_pda(int cpu) -{ - struct x8664_pda *oldpda, *newpda; - unsigned long size = sizeof(struct x8664_pda); - int node = cpu_to_node(cpu); - - if (cpu_pda(cpu) && !cpu_pda(cpu)->in_bootmem) - return 0; - - oldpda = cpu_pda(cpu); - newpda = kmalloc_node(size, GFP_ATOMIC, node); - if (!newpda) { - printk(KERN_ERR "Could not allocate node local PDA " - "for CPU %d on node %d\n", cpu, node); - - if (oldpda) - return 0; /* have a usable pda */ - else - return -1; - } - - if (oldpda) { - memcpy(newpda, oldpda, size); - free_bootmem_pda(oldpda); - } - - newpda->in_bootmem = 0; - cpu_pda(cpu) = newpda; - return 0; -} -#endif /* CONFIG_X86_64 */ - static int __cpuinit do_boot_cpu(int apicid, int cpu) /* * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad @@ -807,16 +761,6 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu) }; INIT_WORK(&c_idle.work, do_fork_idle); -#ifdef CONFIG_X86_64 - /* Allocate node local memory for AP pdas */ - if (cpu > 0) { - boot_error = get_local_pda(cpu); - if (boot_error) - goto restore_state; - /* if can't get pda memory, can't start cpu */ - } -#endif - alternatives_smp_switch(1); c_idle.idle = get_idle_for_cpu(cpu); @@ -931,9 +875,7 @@ do_rest: inquire_remote_apic(apicid); } } -#ifdef CONFIG_X86_64 -restore_state: -#endif + if (boot_error) { /* Try to put things back the way they were before ... */ numa_remove_cpu(cpu); /* was set by numa_add_cpu */ diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S index f50280db0df..962f21f1d4d 100644 --- a/arch/x86/kernel/vmlinux_64.lds.S +++ b/arch/x86/kernel/vmlinux_64.lds.S @@ -5,6 +5,7 @@ #define LOAD_OFFSET __START_KERNEL_map #include +#include #include #undef i386 /* in case the preprocessor is a 32bit one */ @@ -215,10 +216,11 @@ SECTIONS /* * percpu offsets are zero-based on SMP. PERCPU_VADDR() changes the * output PHDR, so the next output section - __data_nosave - should - * switch it back to data.init. + * switch it back to data.init. Also, pda should be at the head of + * percpu area. Preallocate it. */ . = ALIGN(PAGE_SIZE); - PERCPU_VADDR(0, :percpu) + PERCPU_VADDR_PREALLOC(0, :percpu, pda_size) #else PERCPU(PAGE_SIZE) #endif diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index c44e2069c7c..83fa4236477 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -283,16 +283,6 @@ static int __cpuinit xen_cpu_up(unsigned int cpu) struct task_struct *idle = idle_task(cpu); int rc; -#ifdef CONFIG_X86_64 - /* Allocate node local memory for AP pdas */ - WARN_ON(cpu == 0); - if (cpu > 0) { - rc = get_local_pda(cpu); - if (rc) - return rc; - } -#endif - #ifdef CONFIG_X86_32 init_gdt(cpu); per_cpu(current_task, cpu) = idle; diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index fc2f55f2dcd..e53319cf29c 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -441,9 +441,10 @@ . = __per_cpu_load + SIZEOF(.data.percpu); /** - * PERCPU_VADDR - define output section for percpu area + * PERCPU_VADDR_PREALLOC - define output section for percpu area with prealloc * @vaddr: explicit base address (optional) * @phdr: destination PHDR (optional) + * @prealloc: the size of prealloc area * * Macro which expands to output section for percpu area. If @vaddr * is not blank, it specifies explicit base address and all percpu @@ -455,11 +456,33 @@ * section in the linker script will go there too. @phdr should have * a leading colon. * + * If @prealloc is non-zero, the specified number of bytes will be + * reserved at the start of percpu area. As the prealloc area is + * likely to break alignment, this macro puts areas in increasing + * alignment order. + * * This macro defines three symbols, __per_cpu_load, __per_cpu_start * and __per_cpu_end. The first one is the vaddr of loaded percpu * init data. __per_cpu_start equals @vaddr and __per_cpu_end is the * end offset. */ +#define PERCPU_VADDR_PREALLOC(vaddr, segment, prealloc) \ + PERCPU_PROLOG(vaddr) \ + . += prealloc; \ + *(.data.percpu) \ + *(.data.percpu.shared_aligned) \ + *(.data.percpu.page_aligned) \ + PERCPU_EPILOG(segment) + +/** + * PERCPU_VADDR - define output section for percpu area + * @vaddr: explicit base address (optional) + * @phdr: destination PHDR (optional) + * + * Macro which expands to output section for percpu area. Mostly + * identical to PERCPU_VADDR_PREALLOC(@vaddr, @phdr, 0) other than + * using slighly different layout. + */ #define PERCPU_VADDR(vaddr, phdr) \ PERCPU_PROLOG(vaddr) \ *(.data.percpu.page_aligned) \ -- GitLab From 9939ddaff52787b2a7c1adf1b2afc95421aa0884 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 13 Jan 2009 20:41:35 +0900 Subject: [PATCH 0174/4982] x86: merge 64 and 32 SMP percpu handling Now that pda is allocated as part of percpu, percpu doesn't need to be accessed through pda. Unify x86_64 SMP percpu access with x86_32 SMP one. Other than the segment register, operand size and the base of percpu symbols, they behave identical now. This patch replaces now unnecessary pda->data_offset with a dummy field which is necessary to keep stack_canary at its place. This patch also moves per_cpu_offset initialization out of init_gdt() into setup_per_cpu_areas(). Note that this change also necessitates explicit per_cpu_offset initializations in voyager_smp.c. With this change, x86_OP_percpu()'s are as efficient on x86_64 as on x86_32 and also x86_64 can use assembly PER_CPU macros. Signed-off-by: Tejun Heo Signed-off-by: Ingo Molnar --- arch/x86/include/asm/pda.h | 3 +- arch/x86/include/asm/percpu.h | 127 +++++++++------------------- arch/x86/kernel/asm-offsets_64.c | 1 - arch/x86/kernel/entry_64.S | 7 +- arch/x86/kernel/head64.c | 2 - arch/x86/kernel/setup_percpu.c | 15 ++-- arch/x86/kernel/smpcommon.c | 3 +- arch/x86/mach-voyager/voyager_smp.c | 2 + 8 files changed, 55 insertions(+), 105 deletions(-) diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h index 2d5b49c3248..e91558e3785 100644 --- a/arch/x86/include/asm/pda.h +++ b/arch/x86/include/asm/pda.h @@ -11,8 +11,7 @@ /* Per processor datastructure. %gs points to it while the kernel runs */ struct x8664_pda { struct task_struct *pcurrent; /* 0 Current process */ - unsigned long data_offset; /* 8 Per cpu data offset from linker - address */ + unsigned long dummy; unsigned long kernelstack; /* 16 top of kernel stack for current */ unsigned long oldrsp; /* 24 user rsp for system call */ int irqcount; /* 32 Irq nesting counter. Starts -1 */ diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index 0ed77cf33f7..556f84b9ea9 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h @@ -1,62 +1,13 @@ #ifndef _ASM_X86_PERCPU_H #define _ASM_X86_PERCPU_H -#ifndef __ASSEMBLY__ #ifdef CONFIG_X86_64 -extern void load_pda_offset(int cpu); +#define __percpu_seg gs +#define __percpu_mov_op movq #else -static inline void load_pda_offset(int cpu) { } -#endif -#endif - -#ifdef CONFIG_X86_64 -#include - -/* Same as asm-generic/percpu.h, except that we store the per cpu offset - in the PDA. Longer term the PDA and every per cpu variable - should be just put into a single section and referenced directly - from %gs */ - -#ifdef CONFIG_SMP -#include - -#define __per_cpu_offset(cpu) (cpu_pda(cpu)->data_offset) -#define __my_cpu_offset read_pda(data_offset) - -#define per_cpu_offset(x) (__per_cpu_offset(x)) - +#define __percpu_seg fs +#define __percpu_mov_op movl #endif -#include - -DECLARE_PER_CPU(struct x8664_pda, pda); - -/* - * These are supposed to be implemented as a single instruction which - * operates on the per-cpu data base segment. x86-64 doesn't have - * that yet, so this is a fairly inefficient workaround for the - * meantime. The single instruction is atomic with respect to - * preemption and interrupts, so we need to explicitly disable - * interrupts here to achieve the same effect. However, because it - * can be used from within interrupt-disable/enable, we can't actually - * disable interrupts; disabling preemption is enough. - */ -#define x86_read_percpu(var) \ - ({ \ - typeof(per_cpu_var(var)) __tmp; \ - preempt_disable(); \ - __tmp = __get_cpu_var(var); \ - preempt_enable(); \ - __tmp; \ - }) - -#define x86_write_percpu(var, val) \ - do { \ - preempt_disable(); \ - __get_cpu_var(var) = (val); \ - preempt_enable(); \ - } while(0) - -#else /* CONFIG_X86_64 */ #ifdef __ASSEMBLY__ @@ -73,42 +24,26 @@ DECLARE_PER_CPU(struct x8664_pda, pda); * PER_CPU(cpu_gdt_descr, %ebx) */ #ifdef CONFIG_SMP -#define PER_CPU(var, reg) \ - movl %fs:per_cpu__##this_cpu_off, reg; \ +#define PER_CPU(var, reg) \ + __percpu_mov_op %__percpu_seg:per_cpu__this_cpu_off, reg; \ lea per_cpu__##var(reg), reg -#define PER_CPU_VAR(var) %fs:per_cpu__##var +#define PER_CPU_VAR(var) %__percpu_seg:per_cpu__##var #else /* ! SMP */ -#define PER_CPU(var, reg) \ - movl $per_cpu__##var, reg +#define PER_CPU(var, reg) \ + __percpu_mov_op $per_cpu__##var, reg #define PER_CPU_VAR(var) per_cpu__##var #endif /* SMP */ #else /* ...!ASSEMBLY */ -/* - * PER_CPU finds an address of a per-cpu variable. - * - * Args: - * var - variable name - * cpu - 32bit register containing the current CPU number - * - * The resulting address is stored in the "cpu" argument. - * - * Example: - * PER_CPU(cpu_gdt_descr, %ebx) - */ -#ifdef CONFIG_SMP - -#define __my_cpu_offset x86_read_percpu(this_cpu_off) - -/* fs segment starts at (positive) offset == __per_cpu_offset[cpu] */ -#define __percpu_seg "%%fs:" +#include -#else /* !SMP */ - -#define __percpu_seg "" - -#endif /* SMP */ +#ifdef CONFIG_SMP +#define __percpu_seg_str "%%"__stringify(__percpu_seg)":" +#define __my_cpu_offset x86_read_percpu(this_cpu_off) +#else +#define __percpu_seg_str +#endif #include @@ -128,20 +63,25 @@ do { \ } \ switch (sizeof(var)) { \ case 1: \ - asm(op "b %1,"__percpu_seg"%0" \ + asm(op "b %1,"__percpu_seg_str"%0" \ : "+m" (var) \ : "ri" ((T__)val)); \ break; \ case 2: \ - asm(op "w %1,"__percpu_seg"%0" \ + asm(op "w %1,"__percpu_seg_str"%0" \ : "+m" (var) \ : "ri" ((T__)val)); \ break; \ case 4: \ - asm(op "l %1,"__percpu_seg"%0" \ + asm(op "l %1,"__percpu_seg_str"%0" \ : "+m" (var) \ : "ri" ((T__)val)); \ break; \ + case 8: \ + asm(op "q %1,"__percpu_seg_str"%0" \ + : "+m" (var) \ + : "r" ((T__)val)); \ + break; \ default: __bad_percpu_size(); \ } \ } while (0) @@ -151,17 +91,22 @@ do { \ typeof(var) ret__; \ switch (sizeof(var)) { \ case 1: \ - asm(op "b "__percpu_seg"%1,%0" \ + asm(op "b "__percpu_seg_str"%1,%0" \ : "=r" (ret__) \ : "m" (var)); \ break; \ case 2: \ - asm(op "w "__percpu_seg"%1,%0" \ + asm(op "w "__percpu_seg_str"%1,%0" \ : "=r" (ret__) \ : "m" (var)); \ break; \ case 4: \ - asm(op "l "__percpu_seg"%1,%0" \ + asm(op "l "__percpu_seg_str"%1,%0" \ + : "=r" (ret__) \ + : "m" (var)); \ + break; \ + case 8: \ + asm(op "q "__percpu_seg_str"%1,%0" \ : "=r" (ret__) \ : "m" (var)); \ break; \ @@ -175,8 +120,14 @@ do { \ #define x86_add_percpu(var, val) percpu_to_op("add", per_cpu__##var, val) #define x86_sub_percpu(var, val) percpu_to_op("sub", per_cpu__##var, val) #define x86_or_percpu(var, val) percpu_to_op("or", per_cpu__##var, val) + +#ifdef CONFIG_X86_64 +extern void load_pda_offset(int cpu); +#else +static inline void load_pda_offset(int cpu) { } +#endif + #endif /* !__ASSEMBLY__ */ -#endif /* !CONFIG_X86_64 */ #ifdef CONFIG_SMP diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index f8d1b047ef4..f4cc81bfbf8 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c @@ -55,7 +55,6 @@ int main(void) ENTRY(irqcount); ENTRY(cpunumber); ENTRY(irqstackptr); - ENTRY(data_offset); DEFINE(pda_size, sizeof(struct x8664_pda)); BLANK(); #undef ENTRY diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index e28c7a98779..4833f3a1965 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -52,6 +52,7 @@ #include #include #include +#include /* Avoid __ASSEMBLER__'ifying just for this. */ #include @@ -1072,10 +1073,10 @@ ENTRY(\sym) TRACE_IRQS_OFF movq %rsp,%rdi /* pt_regs pointer */ xorl %esi,%esi /* no error code */ - movq %gs:pda_data_offset, %rbp - subq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp) + PER_CPU(init_tss, %rbp) + subq $EXCEPTION_STKSZ, TSS_ist + (\ist - 1) * 8(%rbp) call \do_sym - addq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp) + addq $EXCEPTION_STKSZ, TSS_ist + (\ist - 1) * 8(%rbp) jmp paranoid_exit /* %ebx: no swapgs flag */ CFI_ENDPROC END(\sym) diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 1a311293f73..e99b661a97f 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -38,8 +38,6 @@ void __init x86_64_init_pda(void) #else cpu_pda(0) = &_boot_cpu_pda; #endif - cpu_pda(0)->data_offset = - (unsigned long)(__per_cpu_load - __per_cpu_start); pda_init(0); } diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 63d46280227..be1ff34db11 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -125,14 +125,14 @@ static void __init setup_per_cpu_maps(void) #endif } -#ifdef CONFIG_X86_32 -/* - * Great future not-so-futuristic plan: make i386 and x86_64 do it - * the same way - */ +#ifdef CONFIG_X86_64 +unsigned long __per_cpu_offset[NR_CPUS] __read_mostly = { + [0] = (unsigned long)__per_cpu_load, +}; +#else unsigned long __per_cpu_offset[NR_CPUS] __read_mostly; -EXPORT_SYMBOL(__per_cpu_offset); #endif +EXPORT_SYMBOL(__per_cpu_offset); /* * Great future plan: @@ -178,6 +178,7 @@ void __init setup_per_cpu_areas(void) #endif memcpy(ptr, __per_cpu_load, __per_cpu_end - __per_cpu_start); + per_cpu_offset(cpu) = ptr - __per_cpu_start; #ifdef CONFIG_X86_64 cpu_pda(cpu) = (void *)ptr; @@ -190,7 +191,7 @@ void __init setup_per_cpu_areas(void) else memset(cpu_pda(cpu), 0, sizeof(*cpu_pda(cpu))); #endif - per_cpu_offset(cpu) = ptr - __per_cpu_start; + per_cpu(this_cpu_off, cpu) = per_cpu_offset(cpu); DBG("PERCPU: cpu %4d %p\n", cpu, ptr); } diff --git a/arch/x86/kernel/smpcommon.c b/arch/x86/kernel/smpcommon.c index 397e309839d..84395fabc41 100644 --- a/arch/x86/kernel/smpcommon.c +++ b/arch/x86/kernel/smpcommon.c @@ -4,10 +4,10 @@ #include #include -#ifdef CONFIG_X86_32 DEFINE_PER_CPU(unsigned long, this_cpu_off); EXPORT_PER_CPU_SYMBOL(this_cpu_off); +#ifdef CONFIG_X86_32 /* * Initialize the CPU's GDT. This is either the boot CPU doing itself * (still using the master per-cpu area), or a CPU doing it for a @@ -24,7 +24,6 @@ __cpuinit void init_gdt(int cpu) write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_PERCPU, &gdt, DESCTYPE_S); - per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu]; per_cpu(cpu_number, cpu) = cpu; } #endif diff --git a/arch/x86/mach-voyager/voyager_smp.c b/arch/x86/mach-voyager/voyager_smp.c index 9840b7ec749..1a48368acb0 100644 --- a/arch/x86/mach-voyager/voyager_smp.c +++ b/arch/x86/mach-voyager/voyager_smp.c @@ -531,6 +531,7 @@ static void __init do_boot_cpu(__u8 cpu) stack_start.sp = (void *)idle->thread.sp; init_gdt(cpu); + per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu]; per_cpu(current_task, cpu) = idle; early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu); irq_ctx_init(cpu); @@ -1748,6 +1749,7 @@ static void __init voyager_smp_prepare_cpus(unsigned int max_cpus) static void __cpuinit voyager_smp_prepare_boot_cpu(void) { init_gdt(smp_processor_id()); + per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu]; switch_to_new_gdt(); cpu_set(smp_processor_id(), cpu_online_map); -- GitLab From b12d8db8fbfaed1e8222a15333a3645599636854 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 13 Jan 2009 20:41:35 +0900 Subject: [PATCH 0175/4982] x86: make pda a percpu variable [ Based on original patch from Christoph Lameter and Mike Travis. ] As pda is now allocated in percpu area, it can easily be made a proper percpu variable. Make it so by defining per cpu symbol from linker script and declaring it in C code for SMP and simply defining it for UP. This change cleans up code and brings SMP and UP closer a bit. Signed-off-by: Tejun Heo Signed-off-by: Ingo Molnar --- arch/x86/include/asm/pda.h | 5 +++-- arch/x86/kernel/cpu/common.c | 3 --- arch/x86/kernel/head64.c | 10 ---------- arch/x86/kernel/head_64.S | 5 +++-- arch/x86/kernel/setup_percpu.c | 16 ++++++++++++++-- arch/x86/kernel/vmlinux_64.lds.S | 4 +++- 6 files changed, 23 insertions(+), 20 deletions(-) diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h index e91558e3785..66ae1043393 100644 --- a/arch/x86/include/asm/pda.h +++ b/arch/x86/include/asm/pda.h @@ -7,6 +7,7 @@ #include #include #include +#include /* Per processor datastructure. %gs points to it while the kernel runs */ struct x8664_pda { @@ -39,10 +40,10 @@ struct x8664_pda { unsigned irq_spurious_count; } ____cacheline_aligned_in_smp; -extern struct x8664_pda *_cpu_pda[NR_CPUS]; +DECLARE_PER_CPU(struct x8664_pda, __pda); extern void pda_init(int); -#define cpu_pda(i) (_cpu_pda[i]) +#define cpu_pda(cpu) (&per_cpu(__pda, cpu)) /* * There is no fast way to get the base address of the PDA, all the accesses diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 7041acdf557..c49498d4083 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -879,9 +879,6 @@ static __init int setup_disablecpuid(char *arg) __setup("clearcpuid=", setup_disablecpuid); #ifdef CONFIG_X86_64 -struct x8664_pda *_cpu_pda[NR_CPUS] __read_mostly; -EXPORT_SYMBOL(_cpu_pda); - struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table }; static char boot_cpu_stack[IRQSTACKSIZE] __page_aligned_bss; diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index e99b661a97f..71b6f6ec96a 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -26,18 +26,8 @@ #include #include -#ifndef CONFIG_SMP -/* boot cpu pda, referenced by head_64.S to initialize %gs on UP */ -struct x8664_pda _boot_cpu_pda; -#endif - void __init x86_64_init_pda(void) { -#ifdef CONFIG_SMP - cpu_pda(0) = (void *)__per_cpu_load; -#else - cpu_pda(0) = &_boot_cpu_pda; -#endif pda_init(0); } diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 7a995d0e9f7..c8ace880661 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -19,6 +19,7 @@ #include #include #include +#include #ifdef CONFIG_PARAVIRT #include @@ -250,7 +251,7 @@ ENTRY(secondary_startup_64) * secondary CPU,initial_gs should be set to its pda address * before the CPU runs this code. * - * On UP, initial_gs points to _boot_cpu_pda and doesn't + * On UP, initial_gs points to PER_CPU_VAR(__pda) and doesn't * change. */ movl $MSR_GS_BASE,%ecx @@ -284,7 +285,7 @@ ENTRY(secondary_startup_64) #ifdef CONFIG_SMP .quad __per_cpu_load #else - .quad _boot_cpu_pda + .quad PER_CPU_VAR(__pda) #endif __FINITDATA diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index be1ff34db11..daeedf82c15 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -66,6 +66,16 @@ static void __init setup_node_to_cpumask_map(void); static inline void setup_node_to_cpumask_map(void) { } #endif +/* + * Define load_pda_offset() and per-cpu __pda for x86_64. + * load_pda_offset() is responsible for loading the offset of pda into + * %gs. + * + * On SMP, pda offset also duals as percpu base address and thus it + * should be at the start of per-cpu area. To achieve this, it's + * preallocated in vmlinux_64.lds.S directly instead of using + * DEFINE_PER_CPU(). + */ #ifdef CONFIG_X86_64 void __cpuinit load_pda_offset(int cpu) { @@ -74,6 +84,10 @@ void __cpuinit load_pda_offset(int cpu) wrmsrl(MSR_GS_BASE, cpu_pda(cpu)); mb(); } +#ifndef CONFIG_SMP +DEFINE_PER_CPU(struct x8664_pda, __pda); +EXPORT_PER_CPU_SYMBOL(__pda); +#endif #endif /* CONFIG_SMP && CONFIG_X86_64 */ @@ -180,8 +194,6 @@ void __init setup_per_cpu_areas(void) memcpy(ptr, __per_cpu_load, __per_cpu_end - __per_cpu_start); per_cpu_offset(cpu) = ptr - __per_cpu_start; #ifdef CONFIG_X86_64 - cpu_pda(cpu) = (void *)ptr; - /* * CPU0 modified pda in the init data area, reload pda * offset for CPU0 and clear the area for others. diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S index 962f21f1d4d..d2a0baa87d1 100644 --- a/arch/x86/kernel/vmlinux_64.lds.S +++ b/arch/x86/kernel/vmlinux_64.lds.S @@ -217,10 +217,12 @@ SECTIONS * percpu offsets are zero-based on SMP. PERCPU_VADDR() changes the * output PHDR, so the next output section - __data_nosave - should * switch it back to data.init. Also, pda should be at the head of - * percpu area. Preallocate it. + * percpu area. Preallocate it and define the percpu offset symbol + * so that it can be accessed as a percpu variable. */ . = ALIGN(PAGE_SIZE); PERCPU_VADDR_PREALLOC(0, :percpu, pda_size) + per_cpu____pda = __per_cpu_start; #else PERCPU(PAGE_SIZE) #endif -- GitLab From 49357d19e4fb31e28796eaff83499e7584c26878 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 13 Jan 2009 20:41:35 +0900 Subject: [PATCH 0176/4982] x86: convert pda ops to wrappers around x86 percpu accessors pda is now a percpu variable and there's no reason it can't use plain x86 percpu accessors. Add x86_test_and_clear_bit_percpu() and replace pda op implementations with wrappers around x86 percpu accessors. Signed-off-by: Tejun Heo Signed-off-by: Ingo Molnar --- arch/x86/include/asm/pda.h | 88 +++----------------------------- arch/x86/include/asm/percpu.h | 10 ++++ arch/x86/kernel/vmlinux_64.lds.S | 1 - arch/x86/kernel/x8664_ksyms_64.c | 2 - 4 files changed, 16 insertions(+), 85 deletions(-) diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h index 66ae1043393..e3d3a081d79 100644 --- a/arch/x86/include/asm/pda.h +++ b/arch/x86/include/asm/pda.h @@ -45,91 +45,15 @@ extern void pda_init(int); #define cpu_pda(cpu) (&per_cpu(__pda, cpu)) -/* - * There is no fast way to get the base address of the PDA, all the accesses - * have to mention %fs/%gs. So it needs to be done this Torvaldian way. - */ -extern void __bad_pda_field(void) __attribute__((noreturn)); - -/* - * proxy_pda doesn't actually exist, but tell gcc it is accessed for - * all PDA accesses so it gets read/write dependencies right. - */ -extern struct x8664_pda _proxy_pda; - -#define pda_offset(field) offsetof(struct x8664_pda, field) - -#define pda_to_op(op, field, val) \ -do { \ - typedef typeof(_proxy_pda.field) T__; \ - if (0) { T__ tmp__; tmp__ = (val); } /* type checking */ \ - switch (sizeof(_proxy_pda.field)) { \ - case 2: \ - asm(op "w %1,%%gs:%c2" : \ - "+m" (_proxy_pda.field) : \ - "ri" ((T__)val), \ - "i"(pda_offset(field))); \ - break; \ - case 4: \ - asm(op "l %1,%%gs:%c2" : \ - "+m" (_proxy_pda.field) : \ - "ri" ((T__)val), \ - "i" (pda_offset(field))); \ - break; \ - case 8: \ - asm(op "q %1,%%gs:%c2": \ - "+m" (_proxy_pda.field) : \ - "r" ((T__)val), \ - "i"(pda_offset(field))); \ - break; \ - default: \ - __bad_pda_field(); \ - } \ -} while (0) - -#define pda_from_op(op, field) \ -({ \ - typeof(_proxy_pda.field) ret__; \ - switch (sizeof(_proxy_pda.field)) { \ - case 2: \ - asm(op "w %%gs:%c1,%0" : \ - "=r" (ret__) : \ - "i" (pda_offset(field)), \ - "m" (_proxy_pda.field)); \ - break; \ - case 4: \ - asm(op "l %%gs:%c1,%0": \ - "=r" (ret__): \ - "i" (pda_offset(field)), \ - "m" (_proxy_pda.field)); \ - break; \ - case 8: \ - asm(op "q %%gs:%c1,%0": \ - "=r" (ret__) : \ - "i" (pda_offset(field)), \ - "m" (_proxy_pda.field)); \ - break; \ - default: \ - __bad_pda_field(); \ - } \ - ret__; \ -}) - -#define read_pda(field) pda_from_op("mov", field) -#define write_pda(field, val) pda_to_op("mov", field, val) -#define add_pda(field, val) pda_to_op("add", field, val) -#define sub_pda(field, val) pda_to_op("sub", field, val) -#define or_pda(field, val) pda_to_op("or", field, val) +#define read_pda(field) x86_read_percpu(__pda.field) +#define write_pda(field, val) x86_write_percpu(__pda.field, val) +#define add_pda(field, val) x86_add_percpu(__pda.field, val) +#define sub_pda(field, val) x86_sub_percpu(__pda.field, val) +#define or_pda(field, val) x86_or_percpu(__pda.field, val) /* This is not atomic against other CPUs -- CPU preemption needs to be off */ #define test_and_clear_bit_pda(bit, field) \ -({ \ - int old__; \ - asm volatile("btr %2,%%gs:%c3\n\tsbbl %0,%0" \ - : "=r" (old__), "+m" (_proxy_pda.field) \ - : "dIr" (bit), "i" (pda_offset(field)) : "memory");\ - old__; \ -}) + x86_test_and_clear_bit_percpu(bit, __pda.field) #endif diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index 556f84b9ea9..328b31a429d 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h @@ -121,6 +121,16 @@ do { \ #define x86_sub_percpu(var, val) percpu_to_op("sub", per_cpu__##var, val) #define x86_or_percpu(var, val) percpu_to_op("or", per_cpu__##var, val) +/* This is not atomic against other CPUs -- CPU preemption needs to be off */ +#define x86_test_and_clear_bit_percpu(bit, var) \ +({ \ + int old__; \ + asm volatile("btr %1,"__percpu_seg_str"%c2\n\tsbbl %0,%0" \ + : "=r" (old__) \ + : "dIr" (bit), "i" (&per_cpu__##var) : "memory"); \ + old__; \ +}) + #ifdef CONFIG_X86_64 extern void load_pda_offset(int cpu); #else diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S index d2a0baa87d1..a09abb8fb97 100644 --- a/arch/x86/kernel/vmlinux_64.lds.S +++ b/arch/x86/kernel/vmlinux_64.lds.S @@ -14,7 +14,6 @@ OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") OUTPUT_ARCH(i386:x86-64) ENTRY(phys_startup_64) jiffies_64 = jiffies; -_proxy_pda = 1; PHDRS { text PT_LOAD FLAGS(5); /* R_E */ data PT_LOAD FLAGS(7); /* RWE */ diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c index 695e426aa35..3909e3ba5ce 100644 --- a/arch/x86/kernel/x8664_ksyms_64.c +++ b/arch/x86/kernel/x8664_ksyms_64.c @@ -58,5 +58,3 @@ EXPORT_SYMBOL(__memcpy); EXPORT_SYMBOL(empty_zero_page); EXPORT_SYMBOL(init_level4_pgt); EXPORT_SYMBOL(load_gs_index); - -EXPORT_SYMBOL(_proxy_pda); -- GitLab From 004aa322f855a765741d9437a98dd8fe2e4f32a6 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 13 Jan 2009 20:41:35 +0900 Subject: [PATCH 0177/4982] x86: misc clean up after the percpu update Do the following cleanups: * kill x86_64_init_pda() which now is equivalent to pda_init() * use per_cpu_offset() instead of cpu_pda() when initializing initial_gs Signed-off-by: Tejun Heo Signed-off-by: Ingo Molnar --- arch/x86/include/asm/setup.h | 1 - arch/x86/kernel/acpi/sleep.c | 2 +- arch/x86/kernel/head64.c | 7 +------ arch/x86/kernel/smpboot.c | 2 +- arch/x86/xen/enlighten.c | 2 +- 5 files changed, 4 insertions(+), 10 deletions(-) diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h index ebe858cdc8a..536949749bc 100644 --- a/arch/x86/include/asm/setup.h +++ b/arch/x86/include/asm/setup.h @@ -100,7 +100,6 @@ extern unsigned long init_pg_tables_start; extern unsigned long init_pg_tables_end; #else -void __init x86_64_init_pda(void); void __init x86_64_start_kernel(char *real_mode); void __init x86_64_start_reservations(char *real_mode_data); diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 9ff67f8dc2c..4abff454c55 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -101,7 +101,7 @@ int acpi_save_state_mem(void) stack_start.sp = temp_stack + sizeof(temp_stack); early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(smp_processor_id()); - initial_gs = (unsigned long)cpu_pda(smp_processor_id()); + initial_gs = per_cpu_offset(smp_processor_id()); #endif initial_code = (unsigned long)wakeup_long64; saved_magic = 0x123456789abcdef0; diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 71b6f6ec96a..af67d3227ea 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -26,11 +26,6 @@ #include #include -void __init x86_64_init_pda(void) -{ - pda_init(0); -} - static void __init zap_identity_mappings(void) { pgd_t *pgd = pgd_offset_k(0UL); @@ -96,7 +91,7 @@ void __init x86_64_start_kernel(char * real_mode_data) if (console_loglevel == 10) early_printk("Kernel alive\n"); - x86_64_init_pda(); + pda_init(0); x86_64_start_reservations(real_mode_data); } diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index f2f77ca494d..2f0e0f1090f 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -798,7 +798,7 @@ do_rest: #else cpu_pda(cpu)->pcurrent = c_idle.idle; clear_tsk_thread_flag(c_idle.idle, TIF_FORK); - initial_gs = (unsigned long)cpu_pda(cpu); + initial_gs = per_cpu_offset(cpu); #endif early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu); initial_code = (unsigned long)start_secondary; diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 965539ec425..312414ef936 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1645,7 +1645,7 @@ asmlinkage void __init xen_start_kernel(void) #ifdef CONFIG_X86_64 /* Disable until direct per-cpu data access. */ have_vcpu_info_placement = 0; - x86_64_init_pda(); + pda_init(0); #endif xen_smp_init(); -- GitLab From 6dbde3530850d4d8bfc1b6bd4006d92786a2787f Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 15 Jan 2009 22:15:53 +0900 Subject: [PATCH 0178/4982] percpu: add optimized generic percpu accessors It is an optimization and a cleanup, and adds the following new generic percpu methods: percpu_read() percpu_write() percpu_add() percpu_sub() percpu_and() percpu_or() percpu_xor() and implements support for them on x86. (other architectures will fall back to a default implementation) The advantage is that for example to read a local percpu variable, instead of this sequence: return __get_cpu_var(var); ffffffff8102ca2b: 48 8b 14 fd 80 09 74 mov -0x7e8bf680(,%rdi,8),%rdx ffffffff8102ca32: 81 ffffffff8102ca33: 48 c7 c0 d8 59 00 00 mov $0x59d8,%rax ffffffff8102ca3a: 48 8b 04 10 mov (%rax,%rdx,1),%rax We can get a single instruction by using the optimized variants: return percpu_read(var); ffffffff8102ca3f: 65 48 8b 05 91 8f fd mov %gs:0x7efd8f91(%rip),%rax I also cleaned up the x86-specific APIs and made the x86 code use these new generic percpu primitives. tj: * fixed generic percpu_sub() definition as Roel Kluin pointed out * added percpu_and() for completeness's sake * made generic percpu ops atomic against preemption Signed-off-by: Ingo Molnar Signed-off-by: Tejun Heo --- arch/x86/include/asm/current.h | 2 +- arch/x86/include/asm/irq_regs_32.h | 4 +-- arch/x86/include/asm/mmu_context_32.h | 12 +++---- arch/x86/include/asm/pda.h | 10 +++--- arch/x86/include/asm/percpu.h | 24 +++++++------ arch/x86/include/asm/smp.h | 2 +- arch/x86/kernel/process_32.c | 2 +- arch/x86/kernel/tlb_32.c | 10 +++--- arch/x86/mach-voyager/voyager_smp.c | 4 +-- arch/x86/xen/enlighten.c | 14 ++++---- arch/x86/xen/irq.c | 8 ++--- arch/x86/xen/mmu.c | 2 +- arch/x86/xen/multicalls.h | 2 +- arch/x86/xen/smp.c | 2 +- include/asm-generic/percpu.h | 52 +++++++++++++++++++++++++++ 15 files changed, 102 insertions(+), 48 deletions(-) diff --git a/arch/x86/include/asm/current.h b/arch/x86/include/asm/current.h index 0930b4f8d67..0728480f5c5 100644 --- a/arch/x86/include/asm/current.h +++ b/arch/x86/include/asm/current.h @@ -10,7 +10,7 @@ struct task_struct; DECLARE_PER_CPU(struct task_struct *, current_task); static __always_inline struct task_struct *get_current(void) { - return x86_read_percpu(current_task); + return percpu_read(current_task); } #else /* X86_32 */ diff --git a/arch/x86/include/asm/irq_regs_32.h b/arch/x86/include/asm/irq_regs_32.h index 86afd747345..d7ed33ee94e 100644 --- a/arch/x86/include/asm/irq_regs_32.h +++ b/arch/x86/include/asm/irq_regs_32.h @@ -15,7 +15,7 @@ DECLARE_PER_CPU(struct pt_regs *, irq_regs); static inline struct pt_regs *get_irq_regs(void) { - return x86_read_percpu(irq_regs); + return percpu_read(irq_regs); } static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs) @@ -23,7 +23,7 @@ static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs) struct pt_regs *old_regs; old_regs = get_irq_regs(); - x86_write_percpu(irq_regs, new_regs); + percpu_write(irq_regs, new_regs); return old_regs; } diff --git a/arch/x86/include/asm/mmu_context_32.h b/arch/x86/include/asm/mmu_context_32.h index 7e98ce1d2c0..08b53454f83 100644 --- a/arch/x86/include/asm/mmu_context_32.h +++ b/arch/x86/include/asm/mmu_context_32.h @@ -4,8 +4,8 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) { #ifdef CONFIG_SMP - if (x86_read_percpu(cpu_tlbstate.state) == TLBSTATE_OK) - x86_write_percpu(cpu_tlbstate.state, TLBSTATE_LAZY); + if (percpu_read(cpu_tlbstate.state) == TLBSTATE_OK) + percpu_write(cpu_tlbstate.state, TLBSTATE_LAZY); #endif } @@ -19,8 +19,8 @@ static inline void switch_mm(struct mm_struct *prev, /* stop flush ipis for the previous mm */ cpu_clear(cpu, prev->cpu_vm_mask); #ifdef CONFIG_SMP - x86_write_percpu(cpu_tlbstate.state, TLBSTATE_OK); - x86_write_percpu(cpu_tlbstate.active_mm, next); + percpu_write(cpu_tlbstate.state, TLBSTATE_OK); + percpu_write(cpu_tlbstate.active_mm, next); #endif cpu_set(cpu, next->cpu_vm_mask); @@ -35,8 +35,8 @@ static inline void switch_mm(struct mm_struct *prev, } #ifdef CONFIG_SMP else { - x86_write_percpu(cpu_tlbstate.state, TLBSTATE_OK); - BUG_ON(x86_read_percpu(cpu_tlbstate.active_mm) != next); + percpu_write(cpu_tlbstate.state, TLBSTATE_OK); + BUG_ON(percpu_read(cpu_tlbstate.active_mm) != next); if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) { /* We were in lazy tlb mode and leave_mm disabled diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h index e3d3a081d79..47f274fe695 100644 --- a/arch/x86/include/asm/pda.h +++ b/arch/x86/include/asm/pda.h @@ -45,11 +45,11 @@ extern void pda_init(int); #define cpu_pda(cpu) (&per_cpu(__pda, cpu)) -#define read_pda(field) x86_read_percpu(__pda.field) -#define write_pda(field, val) x86_write_percpu(__pda.field, val) -#define add_pda(field, val) x86_add_percpu(__pda.field, val) -#define sub_pda(field, val) x86_sub_percpu(__pda.field, val) -#define or_pda(field, val) x86_or_percpu(__pda.field, val) +#define read_pda(field) percpu_read(__pda.field) +#define write_pda(field, val) percpu_write(__pda.field, val) +#define add_pda(field, val) percpu_add(__pda.field, val) +#define sub_pda(field, val) percpu_sub(__pda.field, val) +#define or_pda(field, val) percpu_or(__pda.field, val) /* This is not atomic against other CPUs -- CPU preemption needs to be off */ #define test_and_clear_bit_pda(bit, field) \ diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index 328b31a429d..03aa4b00a1c 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h @@ -40,16 +40,11 @@ #ifdef CONFIG_SMP #define __percpu_seg_str "%%"__stringify(__percpu_seg)":" -#define __my_cpu_offset x86_read_percpu(this_cpu_off) +#define __my_cpu_offset percpu_read(this_cpu_off) #else #define __percpu_seg_str #endif -#include - -/* We can use this directly for local CPU (faster). */ -DECLARE_PER_CPU(unsigned long, this_cpu_off); - /* For arch-specific code, we can use direct single-insn ops (they * don't give an lvalue though). */ extern void __bad_percpu_size(void); @@ -115,11 +110,13 @@ do { \ ret__; \ }) -#define x86_read_percpu(var) percpu_from_op("mov", per_cpu__##var) -#define x86_write_percpu(var, val) percpu_to_op("mov", per_cpu__##var, val) -#define x86_add_percpu(var, val) percpu_to_op("add", per_cpu__##var, val) -#define x86_sub_percpu(var, val) percpu_to_op("sub", per_cpu__##var, val) -#define x86_or_percpu(var, val) percpu_to_op("or", per_cpu__##var, val) +#define percpu_read(var) percpu_from_op("mov", per_cpu__##var) +#define percpu_write(var, val) percpu_to_op("mov", per_cpu__##var, val) +#define percpu_add(var, val) percpu_to_op("add", per_cpu__##var, val) +#define percpu_sub(var, val) percpu_to_op("sub", per_cpu__##var, val) +#define percpu_and(var, val) percpu_to_op("and", per_cpu__##var, val) +#define percpu_or(var, val) percpu_to_op("or", per_cpu__##var, val) +#define percpu_xor(var, val) percpu_to_op("xor", per_cpu__##var, val) /* This is not atomic against other CPUs -- CPU preemption needs to be off */ #define x86_test_and_clear_bit_percpu(bit, var) \ @@ -131,6 +128,11 @@ do { \ old__; \ }) +#include + +/* We can use this directly for local CPU (faster). */ +DECLARE_PER_CPU(unsigned long, this_cpu_off); + #ifdef CONFIG_X86_64 extern void load_pda_offset(int cpu); #else diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index 127415402ea..c7bbbbe65d3 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -160,7 +160,7 @@ extern unsigned disabled_cpus __cpuinitdata; * from the initial startup. We map APIC_BASE very early in page_setup(), * so this is correct in the x86 case. */ -#define raw_smp_processor_id() (x86_read_percpu(cpu_number)) +#define raw_smp_processor_id() (percpu_read(cpu_number)) extern int safe_smp_processor_id(void); #elif defined(CONFIG_X86_64_SMP) diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index a546f55c77b..77d546817d9 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -591,7 +591,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) if (prev->gs | next->gs) loadsegment(gs, next->gs); - x86_write_percpu(current_task, next_p); + percpu_write(current_task, next_p); return prev_p; } diff --git a/arch/x86/kernel/tlb_32.c b/arch/x86/kernel/tlb_32.c index ec53818f4e3..e65449d0f7d 100644 --- a/arch/x86/kernel/tlb_32.c +++ b/arch/x86/kernel/tlb_32.c @@ -34,8 +34,8 @@ static DEFINE_SPINLOCK(tlbstate_lock); */ void leave_mm(int cpu) { - BUG_ON(x86_read_percpu(cpu_tlbstate.state) == TLBSTATE_OK); - cpu_clear(cpu, x86_read_percpu(cpu_tlbstate.active_mm)->cpu_vm_mask); + BUG_ON(percpu_read(cpu_tlbstate.state) == TLBSTATE_OK); + cpu_clear(cpu, percpu_read(cpu_tlbstate.active_mm)->cpu_vm_mask); load_cr3(swapper_pg_dir); } EXPORT_SYMBOL_GPL(leave_mm); @@ -103,8 +103,8 @@ void smp_invalidate_interrupt(struct pt_regs *regs) * BUG(); */ - if (flush_mm == x86_read_percpu(cpu_tlbstate.active_mm)) { - if (x86_read_percpu(cpu_tlbstate.state) == TLBSTATE_OK) { + if (flush_mm == percpu_read(cpu_tlbstate.active_mm)) { + if (percpu_read(cpu_tlbstate.state) == TLBSTATE_OK) { if (flush_va == TLB_FLUSH_ALL) local_flush_tlb(); else @@ -222,7 +222,7 @@ static void do_flush_tlb_all(void *info) unsigned long cpu = smp_processor_id(); __flush_tlb_all(); - if (x86_read_percpu(cpu_tlbstate.state) == TLBSTATE_LAZY) + if (percpu_read(cpu_tlbstate.state) == TLBSTATE_LAZY) leave_mm(cpu); } diff --git a/arch/x86/mach-voyager/voyager_smp.c b/arch/x86/mach-voyager/voyager_smp.c index 1a48368acb0..96f15b09a4c 100644 --- a/arch/x86/mach-voyager/voyager_smp.c +++ b/arch/x86/mach-voyager/voyager_smp.c @@ -402,7 +402,7 @@ void __init find_smp_config(void) VOYAGER_SUS_IN_CONTROL_PORT); current_thread_info()->cpu = boot_cpu_id; - x86_write_percpu(cpu_number, boot_cpu_id); + percpu_write(cpu_number, boot_cpu_id); } /* @@ -1782,7 +1782,7 @@ static void __init voyager_smp_cpus_done(unsigned int max_cpus) void __init smp_setup_processor_id(void) { current_thread_info()->cpu = hard_smp_processor_id(); - x86_write_percpu(cpu_number, hard_smp_processor_id()); + percpu_write(cpu_number, hard_smp_processor_id()); } static void voyager_send_call_func(cpumask_t callmask) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 312414ef936..75b94139e1f 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -695,17 +695,17 @@ static void xen_write_cr0(unsigned long cr0) static void xen_write_cr2(unsigned long cr2) { - x86_read_percpu(xen_vcpu)->arch.cr2 = cr2; + percpu_read(xen_vcpu)->arch.cr2 = cr2; } static unsigned long xen_read_cr2(void) { - return x86_read_percpu(xen_vcpu)->arch.cr2; + return percpu_read(xen_vcpu)->arch.cr2; } static unsigned long xen_read_cr2_direct(void) { - return x86_read_percpu(xen_vcpu_info.arch.cr2); + return percpu_read(xen_vcpu_info.arch.cr2); } static void xen_write_cr4(unsigned long cr4) @@ -718,12 +718,12 @@ static void xen_write_cr4(unsigned long cr4) static unsigned long xen_read_cr3(void) { - return x86_read_percpu(xen_cr3); + return percpu_read(xen_cr3); } static void set_current_cr3(void *v) { - x86_write_percpu(xen_current_cr3, (unsigned long)v); + percpu_write(xen_current_cr3, (unsigned long)v); } static void __xen_write_cr3(bool kernel, unsigned long cr3) @@ -748,7 +748,7 @@ static void __xen_write_cr3(bool kernel, unsigned long cr3) MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); if (kernel) { - x86_write_percpu(xen_cr3, cr3); + percpu_write(xen_cr3, cr3); /* Update xen_current_cr3 once the batch has actually been submitted. */ @@ -764,7 +764,7 @@ static void xen_write_cr3(unsigned long cr3) /* Update while interrupts are disabled, so its atomic with respect to ipis */ - x86_write_percpu(xen_cr3, cr3); + percpu_write(xen_cr3, cr3); __xen_write_cr3(true, cr3); diff --git a/arch/x86/xen/irq.c b/arch/x86/xen/irq.c index bb042608c60..2e8271431e1 100644 --- a/arch/x86/xen/irq.c +++ b/arch/x86/xen/irq.c @@ -39,7 +39,7 @@ static unsigned long xen_save_fl(void) struct vcpu_info *vcpu; unsigned long flags; - vcpu = x86_read_percpu(xen_vcpu); + vcpu = percpu_read(xen_vcpu); /* flag has opposite sense of mask */ flags = !vcpu->evtchn_upcall_mask; @@ -62,7 +62,7 @@ static void xen_restore_fl(unsigned long flags) make sure we're don't switch CPUs between getting the vcpu pointer and updating the mask. */ preempt_disable(); - vcpu = x86_read_percpu(xen_vcpu); + vcpu = percpu_read(xen_vcpu); vcpu->evtchn_upcall_mask = flags; preempt_enable_no_resched(); @@ -83,7 +83,7 @@ static void xen_irq_disable(void) make sure we're don't switch CPUs between getting the vcpu pointer and updating the mask. */ preempt_disable(); - x86_read_percpu(xen_vcpu)->evtchn_upcall_mask = 1; + percpu_read(xen_vcpu)->evtchn_upcall_mask = 1; preempt_enable_no_resched(); } @@ -96,7 +96,7 @@ static void xen_irq_enable(void) the caller is confused and is trying to re-enable interrupts on an indeterminate processor. */ - vcpu = x86_read_percpu(xen_vcpu); + vcpu = percpu_read(xen_vcpu); vcpu->evtchn_upcall_mask = 0; /* Doesn't matter if we get preempted here, because any diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 503c240e26c..7bc7852cc5c 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1074,7 +1074,7 @@ static void drop_other_mm_ref(void *info) /* If this cpu still has a stale cr3 reference, then make sure it has been flushed. */ - if (x86_read_percpu(xen_current_cr3) == __pa(mm->pgd)) { + if (percpu_read(xen_current_cr3) == __pa(mm->pgd)) { load_cr3(swapper_pg_dir); arch_flush_lazy_cpu_mode(); } diff --git a/arch/x86/xen/multicalls.h b/arch/x86/xen/multicalls.h index 85893824161..e786fa7f261 100644 --- a/arch/x86/xen/multicalls.h +++ b/arch/x86/xen/multicalls.h @@ -39,7 +39,7 @@ static inline void xen_mc_issue(unsigned mode) xen_mc_flush(); /* restore flags saved in xen_mc_batch */ - local_irq_restore(x86_read_percpu(xen_mc_irq_flags)); + local_irq_restore(percpu_read(xen_mc_irq_flags)); } /* Set up a callback to be called when the current batch is flushed */ diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 83fa4236477..3bfd6dd0b47 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -78,7 +78,7 @@ static __cpuinit void cpu_bringup(void) xen_setup_cpu_clockevents(); cpu_set(cpu, cpu_online_map); - x86_write_percpu(cpu_state, CPU_ONLINE); + percpu_write(cpu_state, CPU_ONLINE); wmb(); /* We can take interrupts now: we're officially "up". */ diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h index b0e63c672eb..00f45ff081a 100644 --- a/include/asm-generic/percpu.h +++ b/include/asm-generic/percpu.h @@ -80,4 +80,56 @@ extern void setup_per_cpu_areas(void); #define DECLARE_PER_CPU(type, name) extern PER_CPU_ATTRIBUTES \ __typeof__(type) per_cpu_var(name) +/* + * Optional methods for optimized non-lvalue per-cpu variable access. + * + * @var can be a percpu variable or a field of it and its size should + * equal char, int or long. percpu_read() evaluates to a lvalue and + * all others to void. + * + * These operations are guaranteed to be atomic w.r.t. preemption. + * The generic versions use plain get/put_cpu_var(). Archs are + * encouraged to implement single-instruction alternatives which don't + * require preemption protection. + */ +#ifndef percpu_read +# define percpu_read(var) \ + ({ \ + typeof(per_cpu_var(var)) __tmp_var__; \ + __tmp_var__ = get_cpu_var(var); \ + put_cpu_var(var); \ + __tmp_var__; \ + }) +#endif + +#define __percpu_generic_to_op(var, val, op) \ +do { \ + get_cpu_var(var) op val; \ + put_cpu_var(var); \ +} while (0) + +#ifndef percpu_write +# define percpu_write(var, val) __percpu_generic_to_op(var, (val), =) +#endif + +#ifndef percpu_add +# define percpu_add(var, val) __percpu_generic_to_op(var, (val), +=) +#endif + +#ifndef percpu_sub +# define percpu_sub(var, val) __percpu_generic_to_op(var, (val), -=) +#endif + +#ifndef percpu_and +# define percpu_and(var, val) __percpu_generic_to_op(var, (val), &=) +#endif + +#ifndef percpu_or +# define percpu_or(var, val) __percpu_generic_to_op(var, (val), |=) +#endif + +#ifndef percpu_xor +# define percpu_xor(var, val) __percpu_generic_to_op(var, (val), ^=) +#endif + #endif /* _ASM_GENERIC_PERCPU_H_ */ -- GitLab From a338af2c648f5e07c582154745a6c60cd2d8bf12 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 16 Jan 2009 11:19:03 +0900 Subject: [PATCH 0179/4982] x86: fix build bug introduced during merge EXPORT_PER_CPU_SYMBOL() got misplaced during merge leading to build failure. Fix it. Signed-off-by: Tejun Heo --- arch/x86/kernel/setup_percpu.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index daeedf82c15..b5c35af2011 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -86,9 +86,8 @@ void __cpuinit load_pda_offset(int cpu) } #ifndef CONFIG_SMP DEFINE_PER_CPU(struct x8664_pda, __pda); -EXPORT_PER_CPU_SYMBOL(__pda); #endif - +EXPORT_PER_CPU_SYMBOL(__pda); #endif /* CONFIG_SMP && CONFIG_X86_64 */ #ifdef CONFIG_X86_64 -- GitLab From cd3adf52309867955d6e2175246b526442235805 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 16 Jan 2009 12:11:43 +0900 Subject: [PATCH 0180/4982] x86_64: initialize this_cpu_off to __per_cpu_load On x86_64, if get_per_cpu_var() is used before per cpu area is setup (if lockdep is turned on, it happens), it needs this_cpu_off to point to __per_cpu_load. Initialize accordingly. Signed-off-by: Tejun Heo --- arch/x86/kernel/smpcommon.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/x86/kernel/smpcommon.c b/arch/x86/kernel/smpcommon.c index 84395fabc41..7e157810062 100644 --- a/arch/x86/kernel/smpcommon.c +++ b/arch/x86/kernel/smpcommon.c @@ -3,8 +3,13 @@ */ #include #include +#include +#ifdef CONFIG_X86_64 +DEFINE_PER_CPU(unsigned long, this_cpu_off) = (unsigned long)__per_cpu_load; +#else DEFINE_PER_CPU(unsigned long, this_cpu_off); +#endif EXPORT_PER_CPU_SYMBOL(this_cpu_off); #ifdef CONFIG_X86_32 -- GitLab From ceacc2c1c85ac498ca4cf297bdfe5b4aaa9fd0e0 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 16 Jan 2009 14:46:40 +0100 Subject: [PATCH 0181/4982] sched: make plist a library facility Ingo Molnar wrote: > here's a new build failure with tip/sched/rt: > > LD .tmp_vmlinux1 > kernel/built-in.o: In function `set_curr_task_rt': > sched.c:(.text+0x3675): undefined reference to `plist_del' > kernel/built-in.o: In function `pick_next_task_rt': > sched.c:(.text+0x37ce): undefined reference to `plist_del' > kernel/built-in.o: In function `enqueue_pushable_task': > sched.c:(.text+0x381c): undefined reference to `plist_del' Eliminate the plist library kconfig and make it available unconditionally. Signed-off-by: Peter Zijlstra Signed-off-by: Ingo Molnar --- init/Kconfig | 1 - kernel/sched_rt.c | 21 +++++++++++++++------ lib/Kconfig | 6 ------ lib/Makefile | 4 ++-- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/init/Kconfig b/init/Kconfig index a724a149bf3..19b78aa010e 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -874,7 +874,6 @@ config SLABINFO config RT_MUTEXES boolean - select PLIST config BASE_SMALL int diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 4230b15fe90..48d1f6e8497 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -114,14 +114,23 @@ static void dequeue_pushable_task(struct rq *rq, struct task_struct *p) #else +static inline void enqueue_pushable_task(struct rq *rq, struct task_struct *p) +{ +} + +static inline void dequeue_pushable_task(struct rq *rq, struct task_struct *p) +{ +} + static inline -void enqueue_pushable_task(struct rq *rq, struct task_struct *p) {} -static inline -void dequeue_pushable_task(struct rq *rq, struct task_struct *p) {} -static inline -void inc_rt_migration(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) {} +void inc_rt_migration(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) +{ +} + static inline -void dec_rt_migration(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) {} +void dec_rt_migration(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) +{ +} #endif /* CONFIG_SMP */ diff --git a/lib/Kconfig b/lib/Kconfig index 03c2c24b908..fc8ea1ca59d 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -136,12 +136,6 @@ config TEXTSEARCH_BM config TEXTSEARCH_FSM tristate -# -# plist support is select#ed if needed -# -config PLIST - boolean - config HAS_IOMEM boolean depends on !NO_IOMEM diff --git a/lib/Makefile b/lib/Makefile index 32b0e64ded2..902d7385104 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -11,7 +11,8 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \ rbtree.o radix-tree.o dump_stack.o \ idr.o int_sqrt.o extable.o prio_tree.o \ sha1.o irq_regs.o reciprocal_div.o argv_split.o \ - proportions.o prio_heap.o ratelimit.o show_mem.o is_single_threaded.o + proportions.o prio_heap.o ratelimit.o show_mem.o \ + is_single_threaded.o plist.o lib-$(CONFIG_MMU) += ioremap.o lib-$(CONFIG_SMP) += cpumask.o @@ -40,7 +41,6 @@ lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o lib-$(CONFIG_GENERIC_FIND_LAST_BIT) += find_last_bit.o obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o -obj-$(CONFIG_PLIST) += plist.o obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o obj-$(CONFIG_DEBUG_LIST) += list_debug.o obj-$(CONFIG_DEBUG_OBJECTS) += debugobjects.o -- GitLab From 2aceefefc891e85d336c1d95d9d89fd785f5d44c Mon Sep 17 00:00:00 2001 From: Ian Molton Date: Fri, 16 Jan 2009 11:04:18 +0000 Subject: [PATCH 0182/4982] ASoC: Driver for the WM9705 AC97 codec. This driver adds support for the wm9705 ac97 codec. The driver supports audio input and output. Signed-off-by: Ian Molton Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 3 + sound/soc/codecs/wm9705.c | 410 ++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/wm9705.h | 14 ++ 4 files changed, 431 insertions(+) create mode 100644 sound/soc/codecs/wm9705.c create mode 100644 sound/soc/codecs/wm9705.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index d0e0d691ae5..cb5fcd605ac 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -34,6 +34,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_WM8903 if I2C select SND_SOC_WM8971 if I2C select SND_SOC_WM8990 if I2C + select SND_SOC_WM9705 if SND_SOC_AC97_BUS select SND_SOC_WM9712 if SND_SOC_AC97_BUS select SND_SOC_WM9713 if SND_SOC_AC97_BUS help @@ -144,6 +145,9 @@ config SND_SOC_WM8971 config SND_SOC_WM8990 tristate +config SND_SOC_WM9705 + tristate + config SND_SOC_WM9712 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index c4ddc9aa2bb..3664cdc300b 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -23,6 +23,7 @@ snd-soc-wm8900-objs := wm8900.o snd-soc-wm8903-objs := wm8903.o snd-soc-wm8971-objs := wm8971.o snd-soc-wm8990-objs := wm8990.o +snd-soc-wm9705-objs := wm9705.o snd-soc-wm9712-objs := wm9712.o snd-soc-wm9713-objs := wm9713.o @@ -51,5 +52,7 @@ obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o +obj-$(CONFIG_SND_SOC_WM8991) += snd-soc-wm8991.o +obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c new file mode 100644 index 00000000000..cb26b6a77ff --- /dev/null +++ b/sound/soc/codecs/wm9705.c @@ -0,0 +1,410 @@ +/* + * wm9705.c -- ALSA Soc WM9705 codec support + * + * Copyright 2008 Ian Molton + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; Version 2 of the License only. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * WM9705 register cache + */ +static const u16 wm9705_reg[] = { + 0x6150, 0x8000, 0x8000, 0x8000, /* 0x0 */ + 0x0000, 0x8000, 0x8008, 0x8008, /* 0x8 */ + 0x8808, 0x8808, 0x8808, 0x8808, /* 0x10 */ + 0x8808, 0x0000, 0x8000, 0x0000, /* 0x18 */ + 0x0000, 0x0000, 0x0000, 0x000f, /* 0x20 */ + 0x0605, 0x0000, 0xbb80, 0x0000, /* 0x28 */ + 0x0000, 0xbb80, 0x0000, 0x0000, /* 0x30 */ + 0x0000, 0x2000, 0x0000, 0x0000, /* 0x38 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 0x40 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 0x48 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 0x50 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 0x58 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 0x60 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 0x68 */ + 0x0000, 0x0808, 0x0000, 0x0006, /* 0x70 */ + 0x0000, 0x0000, 0x574d, 0x4c05, /* 0x78 */ +}; + +static const struct snd_kcontrol_new wm9705_snd_ac97_controls[] = { + SOC_DOUBLE("Master Playback Volume", AC97_MASTER, 8, 0, 31, 1), + SOC_SINGLE("Master Playback Switch", AC97_MASTER, 15, 1, 1), + SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1), + SOC_SINGLE("Headphone Playback Switch", AC97_HEADPHONE, 15, 1, 1), + SOC_DOUBLE("PCM Playback Volume", AC97_PCM, 8, 0, 31, 1), + SOC_SINGLE("PCM Playback Switch", AC97_PCM, 15, 1, 1), + SOC_SINGLE("Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1), + SOC_SINGLE("Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1), + SOC_SINGLE("PCBeep Playback Volume", AC97_PC_BEEP, 1, 15, 1), + SOC_SINGLE("Phone Playback Volume", AC97_PHONE, 0, 31, 1), + SOC_DOUBLE("Line Playback Volume", AC97_LINE, 8, 0, 31, 1), + SOC_DOUBLE("CD Playback Volume", AC97_CD, 8, 0, 31, 1), + SOC_SINGLE("Mic Playback Volume", AC97_MIC, 0, 31, 1), + SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 6, 1, 0), + SOC_DOUBLE("PCM Capture Volume", AC97_REC_GAIN, 8, 0, 15, 0), + SOC_SINGLE("PCM Capture Switch", AC97_REC_GAIN, 15, 1, 1), +}; + +static const char *wm9705_mic[] = {"Mic 1", "Mic 2"}; +static const char *wm9705_rec_sel[] = {"Mic", "CD", "NC", "NC", + "Line", "Stereo Mix", "Mono Mix", "Phone"}; + +static const struct soc_enum wm9705_enum_mic = + SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, wm9705_mic); +static const struct soc_enum wm9705_enum_rec_l = + SOC_ENUM_SINGLE(AC97_REC_SEL, 8, 8, wm9705_rec_sel); +static const struct soc_enum wm9705_enum_rec_r = + SOC_ENUM_SINGLE(AC97_REC_SEL, 0, 8, wm9705_rec_sel); + +/* Headphone Mixer */ +static const struct snd_kcontrol_new wm9705_hp_mixer_controls[] = { + SOC_DAPM_SINGLE("PCBeep Playback Switch", AC97_PC_BEEP, 15, 1, 1), + SOC_DAPM_SINGLE("CD Playback Switch", AC97_CD, 15, 1, 1), + SOC_DAPM_SINGLE("Mic Playback Switch", AC97_MIC, 15, 1, 1), + SOC_DAPM_SINGLE("Phone Playback Switch", AC97_PHONE, 15, 1, 1), + SOC_DAPM_SINGLE("Line Playback Switch", AC97_LINE, 15, 1, 1), +}; + +/* Mic source */ +static const struct snd_kcontrol_new wm9705_mic_src_controls = + SOC_DAPM_ENUM("Route", wm9705_enum_mic); + +/* Capture source */ +static const struct snd_kcontrol_new wm9705_capture_selectl_controls = + SOC_DAPM_ENUM("Route", wm9705_enum_rec_l); +static const struct snd_kcontrol_new wm9705_capture_selectr_controls = + SOC_DAPM_ENUM("Route", wm9705_enum_rec_r); + +/* DAPM widgets */ +static const struct snd_soc_dapm_widget wm9705_dapm_widgets[] = { + SND_SOC_DAPM_MUX("Mic Source", SND_SOC_NOPM, 0, 0, + &wm9705_mic_src_controls), + SND_SOC_DAPM_MUX("Left Capture Source", SND_SOC_NOPM, 0, 0, + &wm9705_capture_selectl_controls), + SND_SOC_DAPM_MUX("Right Capture Source", SND_SOC_NOPM, 0, 0, + &wm9705_capture_selectr_controls), + SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_MIXER_NAMED_CTL("HP Mixer", SND_SOC_NOPM, 0, 0, + &wm9705_hp_mixer_controls[0], + ARRAY_SIZE(wm9705_hp_mixer_controls)), + SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture", SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture", SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_PGA("Headphone PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("Speaker PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("Line PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("Line out PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("Mono PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("Phone PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("Mic PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("PCBEEP PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("CD PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("ADC PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_OUTPUT("HPOUTL"), + SND_SOC_DAPM_OUTPUT("HPOUTR"), + SND_SOC_DAPM_OUTPUT("LOUT"), + SND_SOC_DAPM_OUTPUT("ROUT"), + SND_SOC_DAPM_OUTPUT("MONOOUT"), + SND_SOC_DAPM_INPUT("PHONE"), + SND_SOC_DAPM_INPUT("LINEINL"), + SND_SOC_DAPM_INPUT("LINEINR"), + SND_SOC_DAPM_INPUT("CDINL"), + SND_SOC_DAPM_INPUT("CDINR"), + SND_SOC_DAPM_INPUT("PCBEEP"), + SND_SOC_DAPM_INPUT("MIC1"), + SND_SOC_DAPM_INPUT("MIC2"), +}; + +/* Audio map + * WM9705 has no switches to disable the route from the inputs to the HP mixer + * so in order to prevent active inputs from forcing the audio outputs to be + * constantly enabled, we use the mutes on those inputs to simulate such + * controls. + */ +static const struct snd_soc_dapm_route audio_map[] = { + /* HP mixer */ + {"HP Mixer", "PCBeep Playback Switch", "PCBEEP PGA"}, + {"HP Mixer", "CD Playback Switch", "CD PGA"}, + {"HP Mixer", "Mic Playback Switch", "Mic PGA"}, + {"HP Mixer", "Phone Playback Switch", "Phone PGA"}, + {"HP Mixer", "Line Playback Switch", "Line PGA"}, + {"HP Mixer", NULL, "Left DAC"}, + {"HP Mixer", NULL, "Right DAC"}, + + /* mono mixer */ + {"Mono Mixer", NULL, "HP Mixer"}, + + /* outputs */ + {"Headphone PGA", NULL, "HP Mixer"}, + {"HPOUTL", NULL, "Headphone PGA"}, + {"HPOUTR", NULL, "Headphone PGA"}, + {"Line out PGA", NULL, "HP Mixer"}, + {"LOUT", NULL, "Line out PGA"}, + {"ROUT", NULL, "Line out PGA"}, + {"Mono PGA", NULL, "Mono Mixer"}, + {"MONOOUT", NULL, "Mono PGA"}, + + /* inputs */ + {"CD PGA", NULL, "CDINL"}, + {"CD PGA", NULL, "CDINR"}, + {"Line PGA", NULL, "LINEINL"}, + {"Line PGA", NULL, "LINEINR"}, + {"Phone PGA", NULL, "PHONE"}, + {"Mic Source", "Mic 1", "MIC1"}, + {"Mic Source", "Mic 2", "MIC2"}, + {"Mic PGA", NULL, "Mic Source"}, + {"PCBEEP PGA", NULL, "PCBEEP"}, + + /* Left capture selector */ + {"Left Capture Source", "Mic", "Mic Source"}, + {"Left Capture Source", "CD", "CDINL"}, + {"Left Capture Source", "Line", "LINEINL"}, + {"Left Capture Source", "Stereo Mix", "HP Mixer"}, + {"Left Capture Source", "Mono Mix", "HP Mixer"}, + {"Left Capture Source", "Phone", "PHONE"}, + + /* Right capture source */ + {"Right Capture Source", "Mic", "Mic Source"}, + {"Right Capture Source", "CD", "CDINR"}, + {"Right Capture Source", "Line", "LINEINR"}, + {"Right Capture Source", "Stereo Mix", "HP Mixer"}, + {"Right Capture Source", "Mono Mix", "HP Mixer"}, + {"Right Capture Source", "Phone", "PHONE"}, + + {"ADC PGA", NULL, "Left Capture Source"}, + {"ADC PGA", NULL, "Right Capture Source"}, + + /* ADC's */ + {"Left ADC", NULL, "ADC PGA"}, + {"Right ADC", NULL, "ADC PGA"}, +}; + +static int wm9705_add_widgets(struct snd_soc_codec *codec) +{ + snd_soc_dapm_new_controls(codec, wm9705_dapm_widgets, + ARRAY_SIZE(wm9705_dapm_widgets)); + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); + snd_soc_dapm_new_widgets(codec); + + return 0; +} + +/* We use a register cache to enhance read performance. */ +static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) +{ + u16 *cache = codec->reg_cache; + + switch (reg) { + case AC97_RESET: + case AC97_VENDOR_ID1: + case AC97_VENDOR_ID2: + return soc_ac97_ops.read(codec->ac97, reg); + default: + reg = reg >> 1; + + if (reg >= (ARRAY_SIZE(wm9705_reg))) + return -EIO; + + return cache[reg]; + } +} + +static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int val) +{ + u16 *cache = codec->reg_cache; + + soc_ac97_ops.write(codec->ac97, reg, val); + reg = reg >> 1; + if (reg < (ARRAY_SIZE(wm9705_reg))) + cache[reg] = val; + + return 0; +} + +static int ac97_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_device *socdev = rtd->socdev; + struct snd_soc_codec *codec = socdev->codec; + int reg; + u16 vra; + + vra = ac97_read(codec, AC97_EXTENDED_STATUS); + ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + reg = AC97_PCM_FRONT_DAC_RATE; + else + reg = AC97_PCM_LR_ADC_RATE; + + return ac97_write(codec, reg, runtime->rate); +} + +#define WM9705_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | \ + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000) + +struct snd_soc_dai wm9705_dai[] = { + { + .name = "AC97 HiFi", + .ac97_control = 1, + .playback = { + .stream_name = "HiFi Playback", + .channels_min = 1, + .channels_max = 2, + .rates = WM9705_AC97_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { + .stream_name = "HiFi Capture", + .channels_min = 1, + .channels_max = 2, + .rates = WM9705_AC97_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .ops = { + .prepare = ac97_prepare, + }, + }, + { + .name = "AC97 Aux", + .playback = { + .stream_name = "Aux Playback", + .channels_min = 1, + .channels_max = 1, + .rates = WM9705_AC97_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + } +}; +EXPORT_SYMBOL_GPL(wm9705_dai); + +static int wm9705_reset(struct snd_soc_codec *codec) +{ + if (soc_ac97_ops.reset) { + soc_ac97_ops.reset(codec->ac97); + if (ac97_read(codec, 0) == wm9705_reg[0]) + return 0; /* Success */ + } + + return -EIO; +} + +static int wm9705_soc_probe(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec; + int ret = 0; + + printk(KERN_INFO "WM9705 SoC Audio Codec\n"); + + socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); + if (socdev->codec == NULL) + return -ENOMEM; + codec = socdev->codec; + mutex_init(&codec->mutex); + + codec->reg_cache = kmemdup(wm9705_reg, sizeof(wm9705_reg), GFP_KERNEL); + if (codec->reg_cache == NULL) { + ret = -ENOMEM; + goto cache_err; + } + codec->reg_cache_size = sizeof(wm9705_reg); + codec->reg_cache_step = 2; + + codec->name = "WM9705"; + codec->owner = THIS_MODULE; + codec->dai = wm9705_dai; + codec->num_dai = ARRAY_SIZE(wm9705_dai); + codec->write = ac97_write; + codec->read = ac97_read; + INIT_LIST_HEAD(&codec->dapm_widgets); + INIT_LIST_HEAD(&codec->dapm_paths); + + ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); + if (ret < 0) { + printk(KERN_ERR "wm9705: failed to register AC97 codec\n"); + goto codec_err; + } + + /* register pcms */ + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + if (ret < 0) + goto pcm_err; + + ret = wm9705_reset(codec); + if (ret) + goto reset_err; + + snd_soc_add_controls(codec, wm9705_snd_ac97_controls, + ARRAY_SIZE(wm9705_snd_ac97_controls)); + wm9705_add_widgets(codec); + + ret = snd_soc_init_card(socdev); + if (ret < 0) { + printk(KERN_ERR "wm9705: failed to register card\n"); + goto pcm_err; + } + + return 0; + +reset_err: + snd_soc_free_pcms(socdev); +pcm_err: + snd_soc_free_ac97_codec(codec); +codec_err: + kfree(codec->reg_cache); +cache_err: + kfree(socdev->codec); + socdev->codec = NULL; + return ret; +} + +static int wm9705_soc_remove(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->codec; + + if (codec == NULL) + return 0; + + snd_soc_dapm_free(socdev); + snd_soc_free_pcms(socdev); + snd_soc_free_ac97_codec(codec); + kfree(codec->reg_cache); + kfree(codec); + return 0; +} + +struct snd_soc_codec_device soc_codec_dev_wm9705 = { + .probe = wm9705_soc_probe, + .remove = wm9705_soc_remove, +}; +EXPORT_SYMBOL_GPL(soc_codec_dev_wm9705); + +MODULE_DESCRIPTION("ASoC WM9705 driver"); +MODULE_AUTHOR("Ian Molton"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/wm9705.h b/sound/soc/codecs/wm9705.h new file mode 100644 index 00000000000..d380f110f9e --- /dev/null +++ b/sound/soc/codecs/wm9705.h @@ -0,0 +1,14 @@ +/* + * wm9705.h -- WM9705 Soc Audio driver + */ + +#ifndef _WM9705_H +#define _WM9705_H + +#define WM9705_DAI_AC97_HIFI 0 +#define WM9705_DAI_AC97_AUX 1 + +extern struct snd_soc_dai wm9705_dai[2]; +extern struct snd_soc_codec_device soc_codec_dev_wm9705; + +#endif -- GitLab From a7e2e735dcf98717150d3c8eaa731de8038af05a Mon Sep 17 00:00:00 2001 From: Ian Molton Date: Thu, 8 Jan 2009 21:03:55 +0000 Subject: [PATCH 0183/4982] ASoC: machine driver for Toshiba e750 This patch adds support for the wm9705 ac97 codec as used in the Toshiba e750 PDA. It includes support for powering up / down the external headphone and speaker amplifiers on this machine. Signed-off-by: Ian Molton Signed-off-by: Mark Brown --- arch/arm/mach-pxa/e750.c | 5 + arch/arm/mach-pxa/include/mach/eseries-gpio.h | 5 + sound/soc/pxa/Kconfig | 9 + sound/soc/pxa/Makefile | 2 + sound/soc/pxa/e750_wm9705.c | 189 ++++++++++++++++++ 5 files changed, 210 insertions(+) create mode 100644 sound/soc/pxa/e750_wm9705.c diff --git a/arch/arm/mach-pxa/e750.c b/arch/arm/mach-pxa/e750.c index be1ab8edb97..665066fd280 100644 --- a/arch/arm/mach-pxa/e750.c +++ b/arch/arm/mach-pxa/e750.c @@ -133,6 +133,11 @@ static unsigned long e750_pin_config[] __initdata = { /* IrDA */ GPIO38_GPIO | MFP_LPM_DRIVE_HIGH, + /* Audio power control */ + GPIO4_GPIO, /* Headphone amp power */ + GPIO7_GPIO, /* Speaker amp power */ + GPIO37_GPIO, /* Headphone detect */ + /* PC Card */ GPIO8_GPIO, /* CD0 */ GPIO44_GPIO, /* CD1 */ diff --git a/arch/arm/mach-pxa/include/mach/eseries-gpio.h b/arch/arm/mach-pxa/include/mach/eseries-gpio.h index efbd2aa9ece..02b28e0ed73 100644 --- a/arch/arm/mach-pxa/include/mach/eseries-gpio.h +++ b/arch/arm/mach-pxa/include/mach/eseries-gpio.h @@ -45,6 +45,11 @@ /* e7xx IrDA power control */ #define GPIO_E7XX_IR_OFF 38 +/* e750 audio control GPIOs */ +#define GPIO_E750_HP_AMP_OFF 4 +#define GPIO_E750_SPK_AMP_OFF 7 +#define GPIO_E750_HP_DETECT 37 + /* ASIC related GPIOs */ #define GPIO_ESERIES_TMIO_IRQ 5 #define GPIO_ESERIES_TMIO_PCLR 19 diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index f82e1069947..b9b1a3f5d67 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -61,6 +61,15 @@ config SND_PXA2XX_SOC_TOSA Say Y if you want to add support for SoC audio on Sharp Zaurus SL-C6000x models (Tosa). +config SND_PXA2XX_SOC_E750 + tristate "SoC AC97 Audio support for e750" + depends on SND_PXA2XX_SOC && MACH_E750 + select SND_SOC_WM9705 + select SND_PXA2XX_SOC_AC97 + help + Say Y if you want to add support for SoC audio on the + toshiba e750 PDA + config SND_PXA2XX_SOC_E800 tristate "SoC AC97 Audio support for e800" depends on SND_PXA2XX_SOC && MACH_E800 diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile index 08a9f279772..c7d4cceeed9 100644 --- a/sound/soc/pxa/Makefile +++ b/sound/soc/pxa/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o snd-soc-corgi-objs := corgi.o snd-soc-poodle-objs := poodle.o snd-soc-tosa-objs := tosa.o +snd-soc-e750-objs := e750_wm9705.o snd-soc-e800-objs := e800_wm9712.o snd-soc-spitz-objs := spitz.o snd-soc-em-x270-objs := em-x270.o @@ -22,6 +23,7 @@ snd-soc-zylonite-objs := zylonite.o obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o obj-$(CONFIG_SND_PXA2XX_SOC_TOSA) += snd-soc-tosa.o +obj-$(CONFIG_SND_PXA2XX_SOC_E750) += snd-soc-e750.o obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c new file mode 100644 index 00000000000..20fbdcfa9f7 --- /dev/null +++ b/sound/soc/pxa/e750_wm9705.c @@ -0,0 +1,189 @@ +/* + * e750-wm9705.c -- SoC audio for e750 + * + * Copyright 2007 (c) Ian Molton + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; version 2 ONLY. + * + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "../codecs/wm9705.h" +#include "pxa2xx-pcm.h" +#include "pxa2xx-ac97.h" + +static int e750_spk_amp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + if (event & SND_SOC_DAPM_PRE_PMU) + gpio_set_value(GPIO_E750_SPK_AMP_OFF, 0); + else if (event & SND_SOC_DAPM_POST_PMD) + gpio_set_value(GPIO_E750_SPK_AMP_OFF, 1); + + return 0; +} + +static int e750_hp_amp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + if (event & SND_SOC_DAPM_PRE_PMU) + gpio_set_value(GPIO_E750_HP_AMP_OFF, 0); + else if (event & SND_SOC_DAPM_POST_PMD) + gpio_set_value(GPIO_E750_HP_AMP_OFF, 1); + + return 0; +} + +static const struct snd_soc_dapm_widget e750_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), + SND_SOC_DAPM_MIC("Mic (Internal)", NULL), + SND_SOC_DAPM_PGA_E("Headphone Amp", SND_SOC_NOPM, 0, 0, NULL, 0, + e750_hp_amp_event, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_PGA_E("Speaker Amp", SND_SOC_NOPM, 0, 0, NULL, 0, + e750_spk_amp_event, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_route audio_map[] = { + {"Headphone Amp", NULL, "HPOUTL"}, + {"Headphone Amp", NULL, "HPOUTR"}, + {"Headphone Jack", NULL, "Headphone Amp"}, + + {"Speaker Amp", NULL, "MONOOUT"}, + {"Speaker", NULL, "Speaker Amp"}, + + {"MIC1", NULL, "Mic (Internal)"}, +}; + +static int e750_ac97_init(struct snd_soc_codec *codec) +{ + snd_soc_dapm_nc_pin(codec, "LOUT"); + snd_soc_dapm_nc_pin(codec, "ROUT"); + snd_soc_dapm_nc_pin(codec, "PHONE"); + snd_soc_dapm_nc_pin(codec, "LINEINL"); + snd_soc_dapm_nc_pin(codec, "LINEINR"); + snd_soc_dapm_nc_pin(codec, "CDINL"); + snd_soc_dapm_nc_pin(codec, "CDINR"); + snd_soc_dapm_nc_pin(codec, "PCBEEP"); + snd_soc_dapm_nc_pin(codec, "MIC2"); + + snd_soc_dapm_new_controls(codec, e750_dapm_widgets, + ARRAY_SIZE(e750_dapm_widgets)); + + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); + + snd_soc_dapm_sync(codec); + + return 0; +} + +static struct snd_soc_dai_link e750_dai[] = { + { + .name = "AC97", + .stream_name = "AC97 HiFi", + .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], + .codec_dai = &wm9705_dai[WM9705_DAI_AC97_HIFI], + .init = e750_ac97_init, + /* use ops to check startup state */ + }, + { + .name = "AC97 Aux", + .stream_name = "AC97 Aux", + .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], + .codec_dai = &wm9705_dai[WM9705_DAI_AC97_AUX], + }, +}; + +static struct snd_soc_card e750 = { + .name = "Toshiba e750", + .platform = &pxa2xx_soc_platform, + .dai_link = e750_dai, + .num_links = ARRAY_SIZE(e750_dai), +}; + +static struct snd_soc_device e750_snd_devdata = { + .card = &e750, + .codec_dev = &soc_codec_dev_wm9705, +}; + +static struct platform_device *e750_snd_device; + +static int __init e750_init(void) +{ + int ret; + + if (!machine_is_e750()) + return -ENODEV; + + ret = gpio_request(GPIO_E750_HP_AMP_OFF, "Headphone amp"); + if (ret) + return ret; + + ret = gpio_request(GPIO_E750_SPK_AMP_OFF, "Speaker amp"); + if (ret) + goto free_hp_amp_gpio; + + ret = gpio_direction_output(GPIO_E750_HP_AMP_OFF, 1); + if (ret) + goto free_spk_amp_gpio; + + ret = gpio_direction_output(GPIO_E750_SPK_AMP_OFF, 1); + if (ret) + goto free_spk_amp_gpio; + + e750_snd_device = platform_device_alloc("soc-audio", -1); + if (!e750_snd_device) { + ret = -ENOMEM; + goto free_spk_amp_gpio; + } + + platform_set_drvdata(e750_snd_device, &e750_snd_devdata); + e750_snd_devdata.dev = &e750_snd_device->dev; + ret = platform_device_add(e750_snd_device); + + if (!ret) + return 0; + +/* Fail gracefully */ + platform_device_put(e750_snd_device); +free_spk_amp_gpio: + gpio_free(GPIO_E750_SPK_AMP_OFF); +free_hp_amp_gpio: + gpio_free(GPIO_E750_HP_AMP_OFF); + + return ret; +} + +static void __exit e750_exit(void) +{ + platform_device_unregister(e750_snd_device); + gpio_free(GPIO_E750_SPK_AMP_OFF); + gpio_free(GPIO_E750_HP_AMP_OFF); +} + +module_init(e750_init); +module_exit(e750_exit); + +/* Module information */ +MODULE_AUTHOR("Ian Molton "); +MODULE_DESCRIPTION("ALSA SoC driver for e750"); +MODULE_LICENSE("GPL v2"); -- GitLab From 0465c7aa6fbab89de820442aed449ceb8d9145a6 Mon Sep 17 00:00:00 2001 From: Ian Molton Date: Thu, 8 Jan 2009 21:16:05 +0000 Subject: [PATCH 0184/4982] ASoC: machine driver for Toshiba e800 This patch adds support for the wm9712 ac97 codec as used in the Toshiba e800 PDA. It includes support for powering up / down the external headphone and speaker amplifiers on this machine. Signed-off-by: Ian Molton Signed-off-by: Mark Brown --- arch/arm/mach-pxa/include/mach/eseries-gpio.h | 5 + sound/soc/pxa/e800_wm9712.c | 116 +++++++++++++++--- 2 files changed, 107 insertions(+), 14 deletions(-) diff --git a/arch/arm/mach-pxa/include/mach/eseries-gpio.h b/arch/arm/mach-pxa/include/mach/eseries-gpio.h index 02b28e0ed73..6d6e4d8fa4c 100644 --- a/arch/arm/mach-pxa/include/mach/eseries-gpio.h +++ b/arch/arm/mach-pxa/include/mach/eseries-gpio.h @@ -50,6 +50,11 @@ #define GPIO_E750_SPK_AMP_OFF 7 #define GPIO_E750_HP_DETECT 37 +/* e800 audio control GPIOs */ +#define GPIO_E800_HP_DETECT 81 +#define GPIO_E800_HP_AMP_OFF 82 +#define GPIO_E800_SPK_AMP_ON 83 + /* ASIC related GPIOs */ #define GPIO_ESERIES_TMIO_IRQ 5 #define GPIO_ESERIES_TMIO_PCLR 19 diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c index 2e3386dfa0f..78a1770b986 100644 --- a/sound/soc/pxa/e800_wm9712.c +++ b/sound/soc/pxa/e800_wm9712.c @@ -1,8 +1,6 @@ /* * e800-wm9712.c -- SoC audio for e800 * - * Based on tosa.c - * * Copyright 2007 (c) Ian Molton * * This program is free software; you can redistribute it and/or modify it @@ -13,31 +11,96 @@ #include #include -#include +#include #include #include #include #include -#include #include #include #include +#include + +#include #include "../codecs/wm9712.h" #include "pxa2xx-pcm.h" #include "pxa2xx-ac97.h" -static struct snd_soc_card e800; +static int e800_spk_amp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + if (event & SND_SOC_DAPM_PRE_PMU) + gpio_set_value(GPIO_E800_SPK_AMP_ON, 1); + else if (event & SND_SOC_DAPM_POST_PMD) + gpio_set_value(GPIO_E800_SPK_AMP_ON, 0); -static struct snd_soc_dai_link e800_dai[] = { + return 0; +} + +static int e800_hp_amp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) { - .name = "AC97 Aux", - .stream_name = "AC97 Aux", - .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], - .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], -}, + if (event & SND_SOC_DAPM_PRE_PMU) + gpio_set_value(GPIO_E800_HP_AMP_OFF, 0); + else if (event & SND_SOC_DAPM_POST_PMD) + gpio_set_value(GPIO_E800_HP_AMP_OFF, 1); + + return 0; +} + +static const struct snd_soc_dapm_widget e800_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Mic (Internal1)", NULL), + SND_SOC_DAPM_MIC("Mic (Internal2)", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), + SND_SOC_DAPM_PGA_E("Headphone Amp", SND_SOC_NOPM, 0, 0, NULL, 0, + e800_hp_amp_event, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_PGA_E("Speaker Amp", SND_SOC_NOPM, 0, 0, NULL, 0, + e800_spk_amp_event, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_route audio_map[] = { + {"Headphone Jack", NULL, "HPOUTL"}, + {"Headphone Jack", NULL, "HPOUTR"}, + {"Headphone Jack", NULL, "Headphone Amp"}, + + {"Speaker Amp", NULL, "MONOOUT"}, + {"Speaker", NULL, "Speaker Amp"}, + + {"MIC1", NULL, "Mic (Internal1)"}, + {"MIC2", NULL, "Mic (Internal2)"}, +}; + +static int e800_ac97_init(struct snd_soc_codec *codec) +{ + snd_soc_dapm_new_controls(codec, e800_dapm_widgets, + ARRAY_SIZE(e800_dapm_widgets)); + + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); + snd_soc_dapm_sync(codec); + + return 0; +} + +static struct snd_soc_dai_link e800_dai[] = { + { + .name = "AC97", + .stream_name = "AC97 HiFi", + .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], + .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], + .init = e800_ac97_init, + }, + { + .name = "AC97 Aux", + .stream_name = "AC97 Aux", + .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], + .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], + }, }; static struct snd_soc_card e800 = { @@ -61,6 +124,22 @@ static int __init e800_init(void) if (!machine_is_e800()) return -ENODEV; + ret = gpio_request(GPIO_E800_HP_AMP_OFF, "Headphone amp"); + if (ret) + return ret; + + ret = gpio_request(GPIO_E800_SPK_AMP_ON, "Speaker amp"); + if (ret) + goto free_hp_amp_gpio; + + ret = gpio_direction_output(GPIO_E800_HP_AMP_OFF, 1); + if (ret) + goto free_spk_amp_gpio; + + ret = gpio_direction_output(GPIO_E800_SPK_AMP_ON, 1); + if (ret) + goto free_spk_amp_gpio; + e800_snd_device = platform_device_alloc("soc-audio", -1); if (!e800_snd_device) return -ENOMEM; @@ -69,8 +148,15 @@ static int __init e800_init(void) e800_snd_devdata.dev = &e800_snd_device->dev; ret = platform_device_add(e800_snd_device); - if (ret) - platform_device_put(e800_snd_device); + if (!ret) + return 0; + +/* Fail gracefully */ + platform_device_put(e800_snd_device); +free_spk_amp_gpio: + gpio_free(GPIO_E800_SPK_AMP_ON); +free_hp_amp_gpio: + gpio_free(GPIO_E800_HP_AMP_OFF); return ret; } @@ -78,6 +164,8 @@ static int __init e800_init(void) static void __exit e800_exit(void) { platform_device_unregister(e800_snd_device); + gpio_free(GPIO_E800_SPK_AMP_ON); + gpio_free(GPIO_E800_HP_AMP_OFF); } module_init(e800_init); @@ -86,4 +174,4 @@ module_exit(e800_exit); /* Module information */ MODULE_AUTHOR("Ian Molton "); MODULE_DESCRIPTION("ALSA SoC driver for e800"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); -- GitLab From 74296a8ed6aa3c5bf672808ada690de7ba323ecc Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 16 Jan 2009 17:43:50 +0100 Subject: [PATCH 0185/4982] irq: provide debug_poll_all_shared_irqs() method under CONFIG_DEBUG_SHIRQ Provide a shared interrupt debug facility under CONFIG_DEBUG_SHIRQ: it uses the existing irqpoll facilities to iterate through all registered interrupt handlers and call those which can handle shared IRQ lines. This can be handy for suspend/resume debugging: if we call this function early during resume we can trigger crashes in those drivers which have incorrect assumptions about when exactly their ISRs will be called during suspend/resume. Signed-off-by: Ingo Molnar --- include/linux/interrupt.h | 6 ++++++ kernel/irq/spurious.c | 14 +++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 9127f6b51a3..468e3a25a4a 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -462,6 +462,12 @@ static inline void init_irq_proc(void) } #endif +#if defined(CONFIG_GENERIC_HARDIRQS) && defined(CONFIG_DEBUG_SHIRQ) +extern void debug_poll_all_shared_irqs(void); +#else +static inline void debug_poll_all_shared_irqs(void) { } +#endif + int show_interrupts(struct seq_file *p, void *v); struct irq_desc; diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index dd364c11e56..4d568294de3 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -104,7 +104,7 @@ static int misrouted_irq(int irq) return ok; } -static void poll_spurious_irqs(unsigned long dummy) +static void poll_all_shared_irqs(void) { struct irq_desc *desc; int i; @@ -123,11 +123,23 @@ static void poll_spurious_irqs(unsigned long dummy) try_one_irq(i, desc); } +} + +static void poll_spurious_irqs(unsigned long dummy) +{ + poll_all_shared_irqs(); mod_timer(&poll_spurious_irq_timer, jiffies + POLL_SPURIOUS_IRQ_INTERVAL); } +#ifdef CONFIG_DEBUG_SHIRQ +void debug_poll_all_shared_irqs(void) +{ + poll_all_shared_irqs(); +} +#endif + /* * If 99,900 of the previous 100,000 interrupts have not been handled * then assume that the IRQ is stuck in some manner. Drop a diagnostic -- GitLab From c42f69bb064333624dcc1452ed109441c3c9e7b4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 16 Jan 2009 16:31:03 +0000 Subject: [PATCH 0186/4982] ASoC: Ignore output frequency for WM9713 PLL The WM9713 driver does not support configuring the PLL output frequency so the output frequency parameter is irrelevant. Allow users to set it to zero by ignoring it. Signed-off-by: Mark Brown --- sound/soc/codecs/wm9713.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index a45622620db..e636d8a18ed 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -32,7 +32,6 @@ struct wm9713_priv { u32 pll_in; /* PLL input frequency */ - u32 pll_out; /* PLL output frequency */ }; static unsigned int ac97_read(struct snd_soc_codec *codec, @@ -723,13 +722,13 @@ static int wm9713_set_pll(struct snd_soc_codec *codec, struct _pll_div pll_div; /* turn PLL off ? */ - if (freq_in == 0 || freq_out == 0) { + if (freq_in == 0) { /* disable PLL power and select ext source */ reg = ac97_read(codec, AC97_HANDSET_RATE); ac97_write(codec, AC97_HANDSET_RATE, reg | 0x0080); reg = ac97_read(codec, AC97_EXTENDED_MID); ac97_write(codec, AC97_EXTENDED_MID, reg | 0x0200); - wm9713->pll_out = 0; + wm9713->pll_in = 0; return 0; } @@ -773,7 +772,6 @@ static int wm9713_set_pll(struct snd_soc_codec *codec, ac97_write(codec, AC97_EXTENDED_MID, reg & 0xfdff); reg = ac97_read(codec, AC97_HANDSET_RATE); ac97_write(codec, AC97_HANDSET_RATE, reg & 0xff7f); - wm9713->pll_out = freq_out; wm9713->pll_in = freq_in; /* wait 10ms AC97 link frames for the link to stabilise */ @@ -1149,8 +1147,8 @@ static int wm9713_soc_resume(struct platform_device *pdev) wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* do we need to re-start the PLL ? */ - if (wm9713->pll_out) - wm9713_set_pll(codec, 0, wm9713->pll_in, wm9713->pll_out); + if (wm9713->pll_in) + wm9713_set_pll(codec, 0, wm9713->pll_in, 0); /* only synchronise the codec if warm reset failed */ if (ret == 0) { -- GitLab From 68564a46976017496c2227660930d81240f82355 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 16 Jan 2009 15:31:15 -0800 Subject: [PATCH 0187/4982] work_on_cpu: don't try to get_online_cpus() in work_on_cpu. Impact: remove potential circular lock dependency with cpu hotplug lock This has caused more problems than it solved, with a pile of cpu hotplug locking issues. Followup patches will get_online_cpus() in callers that need it, but if they don't do it they're no worse than before when they were using set_cpus_allowed without locking. Signed-off-by: Rusty Russell Signed-off-by: Mike Travis --- kernel/workqueue.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 2f445833ae3..a35afdbc016 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -991,8 +991,8 @@ static void do_work_for_cpu(struct work_struct *w) * @fn: the function to run * @arg: the function arg * - * This will return -EINVAL in the cpu is not online, or the return value - * of @fn otherwise. + * This will return the value @fn returns. + * It is up to the caller to ensure that the cpu doesn't go offline. */ long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg) { @@ -1001,14 +1001,8 @@ long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg) INIT_WORK(&wfc.work, do_work_for_cpu); wfc.fn = fn; wfc.arg = arg; - get_online_cpus(); - if (unlikely(!cpu_online(cpu))) - wfc.ret = -EINVAL; - else { - schedule_work_on(cpu, &wfc.work); - flush_work(&wfc.work); - } - put_online_cpus(); + schedule_work_on(cpu, &wfc.work); + flush_work(&wfc.work); return wfc.ret; } -- GitLab From e1d9ec6246a2668a5d037f529877efb7cf176af8 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 16 Jan 2009 15:31:15 -0800 Subject: [PATCH 0188/4982] work_on_cpu: Use our own workqueue. Impact: remove potential clashes with generic kevent workqueue Annoyingly, some places we want to use work_on_cpu are already in workqueues. As per Ingo's suggestion, we create a different workqueue for work_on_cpu. Signed-off-by: Rusty Russell Signed-off-by: Mike Travis --- kernel/workqueue.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index a35afdbc016..1f0c509b40d 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -971,6 +971,8 @@ undo: } #ifdef CONFIG_SMP +static struct workqueue_struct *work_on_cpu_wq __read_mostly; + struct work_for_cpu { struct work_struct work; long (*fn)(void *); @@ -1001,7 +1003,7 @@ long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg) INIT_WORK(&wfc.work, do_work_for_cpu); wfc.fn = fn; wfc.arg = arg; - schedule_work_on(cpu, &wfc.work); + queue_work_on(cpu, work_on_cpu_wq, &wfc.work); flush_work(&wfc.work); return wfc.ret; @@ -1019,4 +1021,8 @@ void __init init_workqueues(void) hotcpu_notifier(workqueue_cpu_callback, 0); keventd_wq = create_workqueue("events"); BUG_ON(!keventd_wq); +#ifdef CONFIG_SMP + work_on_cpu_wq = create_workqueue("work_on_cpu"); + BUG_ON(!work_on_cpu_wq); +#endif } -- GitLab From 6eb714c63ed5bd663627f7dda8c4d5258f3b64ef Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Fri, 16 Jan 2009 15:31:15 -0800 Subject: [PATCH 0189/4982] cpufreq: use work_on_cpu in acpi-cpufreq.c for drv_read and drv_write Impact: use new work_on_cpu function to reduce stack usage Replace the saving of current->cpus_allowed and set_cpus_allowed_ptr() with a work_on_cpu function for drv_read() and drv_write(). Basically converts do_drv_{read,write} into "work_on_cpu" functions that are now called by drv_read and drv_write. Note: This patch basically reverts 50c668d6 which reverted 7503bfba, now that the work_on_cpu() function is more stable. Signed-off-by: Mike Travis Acked-by: Rusty Russell Tested-by: Dieter Ries Tested-by: Maciej Rutecki Cc: Dave Jones Cc: --- arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index 019276717a7..4b1c319d30c 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -150,8 +150,9 @@ struct drv_cmd { u32 val; }; -static void do_drv_read(struct drv_cmd *cmd) +static long do_drv_read(void *_cmd) { + struct drv_cmd *cmd = _cmd; u32 h; switch (cmd->type) { @@ -166,10 +167,12 @@ static void do_drv_read(struct drv_cmd *cmd) default: break; } + return 0; } -static void do_drv_write(struct drv_cmd *cmd) +static long do_drv_write(void *_cmd) { + struct drv_cmd *cmd = _cmd; u32 lo, hi; switch (cmd->type) { @@ -186,30 +189,23 @@ static void do_drv_write(struct drv_cmd *cmd) default: break; } + return 0; } static void drv_read(struct drv_cmd *cmd) { - cpumask_t saved_mask = current->cpus_allowed; cmd->val = 0; - set_cpus_allowed_ptr(current, cmd->mask); - do_drv_read(cmd); - set_cpus_allowed_ptr(current, &saved_mask); + work_on_cpu(cpumask_any(cmd->mask), do_drv_read, cmd); } static void drv_write(struct drv_cmd *cmd) { - cpumask_t saved_mask = current->cpus_allowed; unsigned int i; for_each_cpu(i, cmd->mask) { - set_cpus_allowed_ptr(current, cpumask_of(i)); - do_drv_write(cmd); + work_on_cpu(i, do_drv_write, cmd); } - - set_cpus_allowed_ptr(current, &saved_mask); - return; } static u32 get_cur_val(const struct cpumask *mask) @@ -367,7 +363,7 @@ static unsigned int get_cur_freq_on_cpu(unsigned int cpu) return freq; } -static unsigned int check_freqs(const cpumask_t *mask, unsigned int freq, +static unsigned int check_freqs(const struct cpumask *mask, unsigned int freq, struct acpi_cpufreq_data *data) { unsigned int cur_freq; -- GitLab From cef30b3a84e1c7cbd49987d83c5863c001445842 Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Fri, 16 Jan 2009 15:58:13 -0800 Subject: [PATCH 0190/4982] x86: put trigger in to detect mismatched apic versions. Fire off one message if two apic's discovered with different apic versions. Signed-off-by: Mike Travis --- arch/x86/kernel/apic.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 0f830e4f567..db0998641c5 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -1833,6 +1833,11 @@ void __cpuinit generic_processor_info(int apicid, int version) num_processors++; cpu = cpumask_next_zero(-1, cpu_present_mask); + if (version != apic_version[boot_cpu_physical_apicid]) + WARN_ONCE(1, + "ACPI: apic version mismatch, bootcpu: %x cpu %d: %x\n", + apic_version[boot_cpu_physical_apicid], cpu, version); + physid_set(apicid, phys_cpu_present_map); if (apicid == boot_cpu_physical_apicid) { /* -- GitLab From 145cd30bac885dffad9db9d487baad07b68a3d04 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 17 Jan 2009 14:42:50 +0900 Subject: [PATCH 0191/4982] linker script: add missing VMLINUX_SYMBOL The newly added PERCPU_*() macros define and use __per_cpu_load but VMLINUX_SYMBOL() was missing from usages causing build failures on archs where linker visible symbol is different from C symbols (e.g. blackfin). Signed-off-by: Tejun Heo --- include/asm-generic/vmlinux.lds.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index e53319cf29c..aa6b9b1b30b 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -432,13 +432,14 @@ #define PERCPU_PROLOG(vaddr) \ VMLINUX_SYMBOL(__per_cpu_load) = .; \ - .data.percpu vaddr : AT(__per_cpu_load - LOAD_OFFSET) { \ + .data.percpu vaddr : AT(VMLINUX_SYMBOL(__per_cpu_load) \ + - LOAD_OFFSET) { \ VMLINUX_SYMBOL(__per_cpu_start) = .; #define PERCPU_EPILOG(phdr) \ VMLINUX_SYMBOL(__per_cpu_end) = .; \ } phdr \ - . = __per_cpu_load + SIZEOF(.data.percpu); + . = VMLINUX_SYMBOL(__per_cpu_load) + SIZEOF(.data.percpu); /** * PERCPU_VADDR_PREALLOC - define output section for percpu area with prealloc -- GitLab From 74e7904559a10cbb9fbf9139c5c42fc87c0f62a4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 17 Jan 2009 15:26:32 +0900 Subject: [PATCH 0192/4982] linker script: add missing .data.percpu.page_aligned arm, arm/mach-integrator and powerpc were missing .data.percpu.page_aligned in their percpu output section definitions. Add it. Signed-off-by: Tejun Heo --- arch/arm/kernel/vmlinux.lds.S | 1 + arch/ia64/kernel/vmlinux.lds.S | 1 + arch/powerpc/kernel/vmlinux.lds.S | 1 + 3 files changed, 3 insertions(+) diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 00216071eaf..85598f7da40 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -65,6 +65,7 @@ SECTIONS #endif . = ALIGN(4096); __per_cpu_start = .; + *(.data.percpu.page_aligned) *(.data.percpu) *(.data.percpu.shared_aligned) __per_cpu_end = .; diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S index 10a7d47e851..f45e4e508ec 100644 --- a/arch/ia64/kernel/vmlinux.lds.S +++ b/arch/ia64/kernel/vmlinux.lds.S @@ -219,6 +219,7 @@ SECTIONS .data.percpu PERCPU_ADDR : AT(__phys_per_cpu_start - LOAD_OFFSET) { __per_cpu_start = .; + *(.data.percpu.page_aligned) *(.data.percpu) *(.data.percpu.shared_aligned) __per_cpu_end = .; diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 47bf15cd2c9..04e8ecea9b4 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -182,6 +182,7 @@ SECTIONS . = ALIGN(PAGE_SIZE); .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { __per_cpu_start = .; + *(.data.percpu.page_aligned) *(.data.percpu) *(.data.percpu.shared_aligned) __per_cpu_end = .; -- GitLab From 9ef344f89ac41116d4ab138b0941c784a3ab8cf4 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Fri, 16 Jan 2009 22:47:30 +0100 Subject: [PATCH 0193/4982] ALSA: wss-lib: remove "pops" before each played sound A WSS codec is autocalibrated each time before playing sound. Do only one calibration during codec initialization. Complete snd_wss_calibrate_mute to mute loopback volume as well. Signed-off-by: Krzysztof Helt Signed-off-by: Takashi Iwai --- sound/isa/wss/wss_lib.c | 41 +++++++++++++---------------------------- 1 file changed, 13 insertions(+), 28 deletions(-) diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index 13299aebd07..f0c0be5bb68 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c @@ -181,25 +181,6 @@ static void snd_wss_wait(struct snd_wss *chip) udelay(100); } -static void snd_wss_outm(struct snd_wss *chip, unsigned char reg, - unsigned char mask, unsigned char value) -{ - unsigned char tmp = (chip->image[reg] & mask) | value; - - snd_wss_wait(chip); -#ifdef CONFIG_SND_DEBUG - if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); -#endif - chip->image[reg] = tmp; - if (!chip->calibrate_mute) { - wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); - wmb(); - wss_outb(chip, CS4231P(REG), tmp); - mb(); - } -} - static void snd_wss_dout(struct snd_wss *chip, unsigned char reg, unsigned char value) { @@ -587,7 +568,15 @@ static void snd_wss_calibrate_mute(struct snd_wss *chip, int mute) chip->image[CS4231_RIGHT_INPUT]); snd_wss_dout(chip, CS4231_LOOPBACK, chip->image[CS4231_LOOPBACK]); + } else { + snd_wss_dout(chip, CS4231_LEFT_INPUT, + 0); + snd_wss_dout(chip, CS4231_RIGHT_INPUT, + 0); + snd_wss_dout(chip, CS4231_LOOPBACK, + 0xfd); } + snd_wss_dout(chip, CS4231_AUX1_LEFT_INPUT, mute | chip->image[CS4231_AUX1_LEFT_INPUT]); snd_wss_dout(chip, CS4231_AUX1_RIGHT_INPUT, @@ -630,7 +619,6 @@ static void snd_wss_playback_format(struct snd_wss *chip, int full_calib = 1; mutex_lock(&chip->mce_mutex); - snd_wss_calibrate_mute(chip, 1); if (chip->hardware == WSS_HW_CS4231A || (chip->hardware & WSS_HW_CS4232_MASK)) { spin_lock_irqsave(&chip->reg_lock, flags); @@ -681,7 +669,6 @@ static void snd_wss_playback_format(struct snd_wss *chip, udelay(100); /* this seems to help */ snd_wss_mce_down(chip); } - snd_wss_calibrate_mute(chip, 0); mutex_unlock(&chip->mce_mutex); } @@ -693,7 +680,6 @@ static void snd_wss_capture_format(struct snd_wss *chip, int full_calib = 1; mutex_lock(&chip->mce_mutex); - snd_wss_calibrate_mute(chip, 1); if (chip->hardware == WSS_HW_CS4231A || (chip->hardware & WSS_HW_CS4232_MASK)) { spin_lock_irqsave(&chip->reg_lock, flags); @@ -750,7 +736,6 @@ static void snd_wss_capture_format(struct snd_wss *chip, spin_unlock_irqrestore(&chip->reg_lock, flags); snd_wss_mce_down(chip); } - snd_wss_calibrate_mute(chip, 0); mutex_unlock(&chip->mce_mutex); } @@ -807,6 +792,7 @@ static void snd_wss_init(struct snd_wss *chip) { unsigned long flags; + snd_wss_calibrate_mute(chip, 1); snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE @@ -830,6 +816,8 @@ static void snd_wss_init(struct snd_wss *chip) snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); + chip->image[CS4231_IFACE_CTRL] &= ~CS4231_AUTOCALIB; + snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); snd_wss_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]); spin_unlock_irqrestore(&chip->reg_lock, flags); @@ -863,6 +851,7 @@ static void snd_wss_init(struct snd_wss *chip) chip->image[CS4231_REC_FORMAT]); spin_unlock_irqrestore(&chip->reg_lock, flags); snd_wss_mce_down(chip); + snd_wss_calibrate_mute(chip, 0); #ifdef SNDRV_DEBUG_MCE snd_printk("init: (5)\n"); @@ -921,8 +910,6 @@ static void snd_wss_close(struct snd_wss *chip, unsigned int mode) mutex_unlock(&chip->open_mutex); return; } - snd_wss_calibrate_mute(chip, 1); - /* disable IRQ */ spin_lock_irqsave(&chip->reg_lock, flags); if (!(chip->hardware & WSS_HW_AD1848_MASK)) @@ -955,8 +942,6 @@ static void snd_wss_close(struct snd_wss *chip, unsigned int mode) wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_calibrate_mute(chip, 0); - chip->mode = 0; mutex_unlock(&chip->open_mutex); } @@ -1149,7 +1134,7 @@ irqreturn_t snd_wss_interrupt(int irq, void *dev_id) if (chip->hardware & WSS_HW_AD1848_MASK) wss_outb(chip, CS4231P(STATUS), 0); else - snd_wss_outm(chip, CS4231_IRQ_STATUS, status, 0); + snd_wss_out(chip, CS4231_IRQ_STATUS, status); spin_unlock(&chip->reg_lock); return IRQ_HANDLED; } -- GitLab From 9c3da0991754d480328eeaa2b90cb231a1cea9b6 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Sat, 17 Jan 2009 17:11:57 -0800 Subject: [PATCH 0194/4982] IB: Remove __constant_{endian} uses The base versions handle constant folding just fine, use them directly. The replacements are OK in the include/ files as they are not exported to userspace so we don't need the __ prefixed versions. This patch does not affect code generation at all. Signed-off-by: Harvey Harrison Signed-off-by: Roland Dreier --- drivers/infiniband/core/cm.c | 15 ++- drivers/infiniband/core/cm_msgs.h | 22 ++--- drivers/infiniband/core/mad_rmpp.c | 2 +- drivers/infiniband/hw/cxgb3/iwch_qp.c | 4 +- drivers/infiniband/hw/ehca/ehca_sqp.c | 8 +- drivers/infiniband/hw/ipath/ipath_eeprom.c | 4 +- drivers/infiniband/hw/ipath/ipath_mad.c | 95 +++++++++---------- drivers/infiniband/hw/ipath/ipath_rc.c | 2 +- drivers/infiniband/hw/ipath/ipath_sdma.c | 4 +- drivers/infiniband/hw/ipath/ipath_uc.c | 2 +- drivers/infiniband/hw/ipath/ipath_ud.c | 4 +- drivers/infiniband/hw/ipath/ipath_user_sdma.c | 6 +- drivers/infiniband/hw/ipath/ipath_verbs.c | 2 +- drivers/infiniband/hw/ipath/ipath_verbs.h | 10 +- drivers/infiniband/hw/mlx4/qp.c | 22 ++--- include/rdma/ib_cm.h | 12 +-- include/rdma/ib_mad.h | 2 +- include/rdma/ib_smi.h | 34 +++---- 18 files changed, 124 insertions(+), 126 deletions(-) diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index f1e82a92e61..5130fc55b8e 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -927,8 +927,7 @@ int ib_cm_listen(struct ib_cm_id *cm_id, __be64 service_id, __be64 service_mask, unsigned long flags; int ret = 0; - service_mask = service_mask ? service_mask : - __constant_cpu_to_be64(~0ULL); + service_mask = service_mask ? service_mask : ~cpu_to_be64(0); service_id &= service_mask; if ((service_id & IB_SERVICE_ID_AGN_MASK) == IB_CM_ASSIGN_SERVICE_ID && (service_id != IB_CM_ASSIGN_SERVICE_ID)) @@ -954,7 +953,7 @@ int ib_cm_listen(struct ib_cm_id *cm_id, __be64 service_id, __be64 service_mask, spin_lock_irqsave(&cm.lock, flags); if (service_id == IB_CM_ASSIGN_SERVICE_ID) { cm_id->service_id = cpu_to_be64(cm.listen_service_id++); - cm_id->service_mask = __constant_cpu_to_be64(~0ULL); + cm_id->service_mask = ~cpu_to_be64(0); } else { cm_id->service_id = service_id; cm_id->service_mask = service_mask; @@ -1134,7 +1133,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id, goto error1; } cm_id->service_id = param->service_id; - cm_id->service_mask = __constant_cpu_to_be64(~0ULL); + cm_id->service_mask = ~cpu_to_be64(0); cm_id_priv->timeout_ms = cm_convert_to_ms( param->primary_path->packet_life_time) * 2 + cm_convert_to_ms( @@ -1545,7 +1544,7 @@ static int cm_req_handler(struct cm_work *work) cm_id_priv->id.cm_handler = listen_cm_id_priv->id.cm_handler; cm_id_priv->id.context = listen_cm_id_priv->id.context; cm_id_priv->id.service_id = req_msg->service_id; - cm_id_priv->id.service_mask = __constant_cpu_to_be64(~0ULL); + cm_id_priv->id.service_mask = ~cpu_to_be64(0); cm_process_routed_req(req_msg, work->mad_recv_wc->wc); cm_format_paths_from_req(req_msg, &work->path[0], &work->path[1]); @@ -2898,7 +2897,7 @@ int ib_send_cm_sidr_req(struct ib_cm_id *cm_id, goto out; cm_id->service_id = param->service_id; - cm_id->service_mask = __constant_cpu_to_be64(~0ULL); + cm_id->service_mask = ~cpu_to_be64(0); cm_id_priv->timeout_ms = param->timeout_ms; cm_id_priv->max_cm_retries = param->max_cm_retries; ret = cm_alloc_msg(cm_id_priv, &msg); @@ -2992,7 +2991,7 @@ static int cm_sidr_req_handler(struct cm_work *work) cm_id_priv->id.cm_handler = cur_cm_id_priv->id.cm_handler; cm_id_priv->id.context = cur_cm_id_priv->id.context; cm_id_priv->id.service_id = sidr_req_msg->service_id; - cm_id_priv->id.service_mask = __constant_cpu_to_be64(~0ULL); + cm_id_priv->id.service_mask = ~cpu_to_be64(0); cm_format_sidr_req_event(work, &cur_cm_id_priv->id); cm_process_work(cm_id_priv, work); @@ -3789,7 +3788,7 @@ static int __init ib_cm_init(void) rwlock_init(&cm.device_lock); spin_lock_init(&cm.lock); cm.listen_service_table = RB_ROOT; - cm.listen_service_id = __constant_be64_to_cpu(IB_CM_ASSIGN_SERVICE_ID); + cm.listen_service_id = be64_to_cpu(IB_CM_ASSIGN_SERVICE_ID); cm.remote_id_table = RB_ROOT; cm.remote_qp_table = RB_ROOT; cm.remote_sidr_table = RB_ROOT; diff --git a/drivers/infiniband/core/cm_msgs.h b/drivers/infiniband/core/cm_msgs.h index aec9c7af825..7e63c08f697 100644 --- a/drivers/infiniband/core/cm_msgs.h +++ b/drivers/infiniband/core/cm_msgs.h @@ -44,17 +44,17 @@ #define IB_CM_CLASS_VERSION 2 /* IB specification 1.2 */ -#define CM_REQ_ATTR_ID __constant_htons(0x0010) -#define CM_MRA_ATTR_ID __constant_htons(0x0011) -#define CM_REJ_ATTR_ID __constant_htons(0x0012) -#define CM_REP_ATTR_ID __constant_htons(0x0013) -#define CM_RTU_ATTR_ID __constant_htons(0x0014) -#define CM_DREQ_ATTR_ID __constant_htons(0x0015) -#define CM_DREP_ATTR_ID __constant_htons(0x0016) -#define CM_SIDR_REQ_ATTR_ID __constant_htons(0x0017) -#define CM_SIDR_REP_ATTR_ID __constant_htons(0x0018) -#define CM_LAP_ATTR_ID __constant_htons(0x0019) -#define CM_APR_ATTR_ID __constant_htons(0x001A) +#define CM_REQ_ATTR_ID cpu_to_be16(0x0010) +#define CM_MRA_ATTR_ID cpu_to_be16(0x0011) +#define CM_REJ_ATTR_ID cpu_to_be16(0x0012) +#define CM_REP_ATTR_ID cpu_to_be16(0x0013) +#define CM_RTU_ATTR_ID cpu_to_be16(0x0014) +#define CM_DREQ_ATTR_ID cpu_to_be16(0x0015) +#define CM_DREP_ATTR_ID cpu_to_be16(0x0016) +#define CM_SIDR_REQ_ATTR_ID cpu_to_be16(0x0017) +#define CM_SIDR_REP_ATTR_ID cpu_to_be16(0x0018) +#define CM_LAP_ATTR_ID cpu_to_be16(0x0019) +#define CM_APR_ATTR_ID cpu_to_be16(0x001A) enum cm_msg_sequence { CM_MSG_SEQUENCE_REQ, diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c index 3af2b84cd83..57a3c6f947b 100644 --- a/drivers/infiniband/core/mad_rmpp.c +++ b/drivers/infiniband/core/mad_rmpp.c @@ -735,7 +735,7 @@ process_rmpp_data(struct ib_mad_agent_private *agent, goto bad; } - if (rmpp_hdr->seg_num == __constant_htonl(1)) { + if (rmpp_hdr->seg_num == cpu_to_be32(1)) { if (!(ib_get_rmpp_flags(rmpp_hdr) & IB_MGMT_RMPP_FLAG_FIRST)) { rmpp_status = IB_MGMT_RMPP_STATUS_BAD_SEG; goto bad; diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c index 19661b2f040..48e2b0bcabd 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_qp.c +++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c @@ -99,8 +99,8 @@ static int build_rdma_write(union t3_wr *wqe, struct ib_send_wr *wr, if (wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) { plen = 4; wqe->write.sgl[0].stag = wr->ex.imm_data; - wqe->write.sgl[0].len = __constant_cpu_to_be32(0); - wqe->write.num_sgle = __constant_cpu_to_be32(0); + wqe->write.sgl[0].len = cpu_to_be32(0); + wqe->write.num_sgle = cpu_to_be32(0); *flit_cnt = 6; } else { plen = 0; diff --git a/drivers/infiniband/hw/ehca/ehca_sqp.c b/drivers/infiniband/hw/ehca/ehca_sqp.c index 44447aaa550..c568b28f4e2 100644 --- a/drivers/infiniband/hw/ehca/ehca_sqp.c +++ b/drivers/infiniband/hw/ehca/ehca_sqp.c @@ -46,11 +46,11 @@ #include "ehca_iverbs.h" #include "hcp_if.h" -#define IB_MAD_STATUS_REDIRECT __constant_htons(0x0002) -#define IB_MAD_STATUS_UNSUP_VERSION __constant_htons(0x0004) -#define IB_MAD_STATUS_UNSUP_METHOD __constant_htons(0x0008) +#define IB_MAD_STATUS_REDIRECT cpu_to_be16(0x0002) +#define IB_MAD_STATUS_UNSUP_VERSION cpu_to_be16(0x0004) +#define IB_MAD_STATUS_UNSUP_METHOD cpu_to_be16(0x0008) -#define IB_PMA_CLASS_PORT_INFO __constant_htons(0x0001) +#define IB_PMA_CLASS_PORT_INFO cpu_to_be16(0x0001) /** * ehca_define_sqp - Defines special queue pair 1 (GSI QP). When special queue diff --git a/drivers/infiniband/hw/ipath/ipath_eeprom.c b/drivers/infiniband/hw/ipath/ipath_eeprom.c index dc37277f1c8..fc7181985e8 100644 --- a/drivers/infiniband/hw/ipath/ipath_eeprom.c +++ b/drivers/infiniband/hw/ipath/ipath_eeprom.c @@ -772,8 +772,8 @@ void ipath_get_eeprom_info(struct ipath_devdata *dd) "0x%x, not 0x%x\n", csum, ifp->if_csum); goto done; } - if (*(__be64 *) ifp->if_guid == 0ULL || - *(__be64 *) ifp->if_guid == __constant_cpu_to_be64(-1LL)) { + if (*(__be64 *) ifp->if_guid == cpu_to_be64(0) || + *(__be64 *) ifp->if_guid == ~cpu_to_be64(0)) { ipath_dev_err(dd, "Invalid GUID %llx from flash; " "ignoring\n", *(unsigned long long *) ifp->if_guid); diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c index 17a12319747..16a702d4601 100644 --- a/drivers/infiniband/hw/ipath/ipath_mad.c +++ b/drivers/infiniband/hw/ipath/ipath_mad.c @@ -37,10 +37,10 @@ #include "ipath_verbs.h" #include "ipath_common.h" -#define IB_SMP_UNSUP_VERSION __constant_htons(0x0004) -#define IB_SMP_UNSUP_METHOD __constant_htons(0x0008) -#define IB_SMP_UNSUP_METH_ATTR __constant_htons(0x000C) -#define IB_SMP_INVALID_FIELD __constant_htons(0x001C) +#define IB_SMP_UNSUP_VERSION cpu_to_be16(0x0004) +#define IB_SMP_UNSUP_METHOD cpu_to_be16(0x0008) +#define IB_SMP_UNSUP_METH_ATTR cpu_to_be16(0x000C) +#define IB_SMP_INVALID_FIELD cpu_to_be16(0x001C) static int reply(struct ib_smp *smp) { @@ -789,12 +789,12 @@ static int recv_subn_set_pkeytable(struct ib_smp *smp, return recv_subn_get_pkeytable(smp, ibdev); } -#define IB_PMA_CLASS_PORT_INFO __constant_htons(0x0001) -#define IB_PMA_PORT_SAMPLES_CONTROL __constant_htons(0x0010) -#define IB_PMA_PORT_SAMPLES_RESULT __constant_htons(0x0011) -#define IB_PMA_PORT_COUNTERS __constant_htons(0x0012) -#define IB_PMA_PORT_COUNTERS_EXT __constant_htons(0x001D) -#define IB_PMA_PORT_SAMPLES_RESULT_EXT __constant_htons(0x001E) +#define IB_PMA_CLASS_PORT_INFO cpu_to_be16(0x0001) +#define IB_PMA_PORT_SAMPLES_CONTROL cpu_to_be16(0x0010) +#define IB_PMA_PORT_SAMPLES_RESULT cpu_to_be16(0x0011) +#define IB_PMA_PORT_COUNTERS cpu_to_be16(0x0012) +#define IB_PMA_PORT_COUNTERS_EXT cpu_to_be16(0x001D) +#define IB_PMA_PORT_SAMPLES_RESULT_EXT cpu_to_be16(0x001E) struct ib_perf { u8 base_version; @@ -884,19 +884,19 @@ struct ib_pma_portcounters { __be32 port_rcv_packets; } __attribute__ ((packed)); -#define IB_PMA_SEL_SYMBOL_ERROR __constant_htons(0x0001) -#define IB_PMA_SEL_LINK_ERROR_RECOVERY __constant_htons(0x0002) -#define IB_PMA_SEL_LINK_DOWNED __constant_htons(0x0004) -#define IB_PMA_SEL_PORT_RCV_ERRORS __constant_htons(0x0008) -#define IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS __constant_htons(0x0010) -#define IB_PMA_SEL_PORT_XMIT_DISCARDS __constant_htons(0x0040) -#define IB_PMA_SEL_LOCAL_LINK_INTEGRITY_ERRORS __constant_htons(0x0200) -#define IB_PMA_SEL_EXCESSIVE_BUFFER_OVERRUNS __constant_htons(0x0400) -#define IB_PMA_SEL_PORT_VL15_DROPPED __constant_htons(0x0800) -#define IB_PMA_SEL_PORT_XMIT_DATA __constant_htons(0x1000) -#define IB_PMA_SEL_PORT_RCV_DATA __constant_htons(0x2000) -#define IB_PMA_SEL_PORT_XMIT_PACKETS __constant_htons(0x4000) -#define IB_PMA_SEL_PORT_RCV_PACKETS __constant_htons(0x8000) +#define IB_PMA_SEL_SYMBOL_ERROR cpu_to_be16(0x0001) +#define IB_PMA_SEL_LINK_ERROR_RECOVERY cpu_to_be16(0x0002) +#define IB_PMA_SEL_LINK_DOWNED cpu_to_be16(0x0004) +#define IB_PMA_SEL_PORT_RCV_ERRORS cpu_to_be16(0x0008) +#define IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS cpu_to_be16(0x0010) +#define IB_PMA_SEL_PORT_XMIT_DISCARDS cpu_to_be16(0x0040) +#define IB_PMA_SEL_LOCAL_LINK_INTEGRITY_ERRORS cpu_to_be16(0x0200) +#define IB_PMA_SEL_EXCESSIVE_BUFFER_OVERRUNS cpu_to_be16(0x0400) +#define IB_PMA_SEL_PORT_VL15_DROPPED cpu_to_be16(0x0800) +#define IB_PMA_SEL_PORT_XMIT_DATA cpu_to_be16(0x1000) +#define IB_PMA_SEL_PORT_RCV_DATA cpu_to_be16(0x2000) +#define IB_PMA_SEL_PORT_XMIT_PACKETS cpu_to_be16(0x4000) +#define IB_PMA_SEL_PORT_RCV_PACKETS cpu_to_be16(0x8000) struct ib_pma_portcounters_ext { u8 reserved; @@ -913,14 +913,14 @@ struct ib_pma_portcounters_ext { __be64 port_multicast_rcv_packets; } __attribute__ ((packed)); -#define IB_PMA_SELX_PORT_XMIT_DATA __constant_htons(0x0001) -#define IB_PMA_SELX_PORT_RCV_DATA __constant_htons(0x0002) -#define IB_PMA_SELX_PORT_XMIT_PACKETS __constant_htons(0x0004) -#define IB_PMA_SELX_PORT_RCV_PACKETS __constant_htons(0x0008) -#define IB_PMA_SELX_PORT_UNI_XMIT_PACKETS __constant_htons(0x0010) -#define IB_PMA_SELX_PORT_UNI_RCV_PACKETS __constant_htons(0x0020) -#define IB_PMA_SELX_PORT_MULTI_XMIT_PACKETS __constant_htons(0x0040) -#define IB_PMA_SELX_PORT_MULTI_RCV_PACKETS __constant_htons(0x0080) +#define IB_PMA_SELX_PORT_XMIT_DATA cpu_to_be16(0x0001) +#define IB_PMA_SELX_PORT_RCV_DATA cpu_to_be16(0x0002) +#define IB_PMA_SELX_PORT_XMIT_PACKETS cpu_to_be16(0x0004) +#define IB_PMA_SELX_PORT_RCV_PACKETS cpu_to_be16(0x0008) +#define IB_PMA_SELX_PORT_UNI_XMIT_PACKETS cpu_to_be16(0x0010) +#define IB_PMA_SELX_PORT_UNI_RCV_PACKETS cpu_to_be16(0x0020) +#define IB_PMA_SELX_PORT_MULTI_XMIT_PACKETS cpu_to_be16(0x0040) +#define IB_PMA_SELX_PORT_MULTI_RCV_PACKETS cpu_to_be16(0x0080) static int recv_pma_get_classportinfo(struct ib_perf *pmp) { @@ -933,7 +933,7 @@ static int recv_pma_get_classportinfo(struct ib_perf *pmp) pmp->status |= IB_SMP_INVALID_FIELD; /* Indicate AllPortSelect is valid (only one port anyway) */ - p->cap_mask = __constant_cpu_to_be16(1 << 8); + p->cap_mask = cpu_to_be16(1 << 8); p->base_version = 1; p->class_version = 1; /* @@ -951,12 +951,11 @@ static int recv_pma_get_classportinfo(struct ib_perf *pmp) * We support 5 counters which only count the mandatory quantities. */ #define COUNTER_MASK(q, n) (q << ((9 - n) * 3)) -#define COUNTER_MASK0_9 \ - __constant_cpu_to_be32(COUNTER_MASK(1, 0) | \ - COUNTER_MASK(1, 1) | \ - COUNTER_MASK(1, 2) | \ - COUNTER_MASK(1, 3) | \ - COUNTER_MASK(1, 4)) +#define COUNTER_MASK0_9 cpu_to_be32(COUNTER_MASK(1, 0) | \ + COUNTER_MASK(1, 1) | \ + COUNTER_MASK(1, 2) | \ + COUNTER_MASK(1, 3) | \ + COUNTER_MASK(1, 4)) static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp, struct ib_device *ibdev, u8 port) @@ -1137,7 +1136,7 @@ static int recv_pma_get_portsamplesresult_ext(struct ib_perf *pmp, status = dev->pma_sample_status; p->sample_status = cpu_to_be16(status); /* 64 bits */ - p->extended_width = __constant_cpu_to_be32(0x80000000); + p->extended_width = cpu_to_be32(0x80000000); for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++) p->counter[i] = (status != IB_PMA_SAMPLE_STATUS_DONE) ? 0 : cpu_to_be64( @@ -1185,7 +1184,7 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp, pmp->status |= IB_SMP_INVALID_FIELD; if (cntrs.symbol_error_counter > 0xFFFFUL) - p->symbol_error_counter = __constant_cpu_to_be16(0xFFFF); + p->symbol_error_counter = cpu_to_be16(0xFFFF); else p->symbol_error_counter = cpu_to_be16((u16)cntrs.symbol_error_counter); @@ -1199,17 +1198,17 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp, else p->link_downed_counter = (u8)cntrs.link_downed_counter; if (cntrs.port_rcv_errors > 0xFFFFUL) - p->port_rcv_errors = __constant_cpu_to_be16(0xFFFF); + p->port_rcv_errors = cpu_to_be16(0xFFFF); else p->port_rcv_errors = cpu_to_be16((u16) cntrs.port_rcv_errors); if (cntrs.port_rcv_remphys_errors > 0xFFFFUL) - p->port_rcv_remphys_errors = __constant_cpu_to_be16(0xFFFF); + p->port_rcv_remphys_errors = cpu_to_be16(0xFFFF); else p->port_rcv_remphys_errors = cpu_to_be16((u16)cntrs.port_rcv_remphys_errors); if (cntrs.port_xmit_discards > 0xFFFFUL) - p->port_xmit_discards = __constant_cpu_to_be16(0xFFFF); + p->port_xmit_discards = cpu_to_be16(0xFFFF); else p->port_xmit_discards = cpu_to_be16((u16)cntrs.port_xmit_discards); @@ -1220,24 +1219,24 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp, p->lli_ebor_errors = (cntrs.local_link_integrity_errors << 4) | cntrs.excessive_buffer_overrun_errors; if (cntrs.vl15_dropped > 0xFFFFUL) - p->vl15_dropped = __constant_cpu_to_be16(0xFFFF); + p->vl15_dropped = cpu_to_be16(0xFFFF); else p->vl15_dropped = cpu_to_be16((u16)cntrs.vl15_dropped); if (cntrs.port_xmit_data > 0xFFFFFFFFUL) - p->port_xmit_data = __constant_cpu_to_be32(0xFFFFFFFF); + p->port_xmit_data = cpu_to_be32(0xFFFFFFFF); else p->port_xmit_data = cpu_to_be32((u32)cntrs.port_xmit_data); if (cntrs.port_rcv_data > 0xFFFFFFFFUL) - p->port_rcv_data = __constant_cpu_to_be32(0xFFFFFFFF); + p->port_rcv_data = cpu_to_be32(0xFFFFFFFF); else p->port_rcv_data = cpu_to_be32((u32)cntrs.port_rcv_data); if (cntrs.port_xmit_packets > 0xFFFFFFFFUL) - p->port_xmit_packets = __constant_cpu_to_be32(0xFFFFFFFF); + p->port_xmit_packets = cpu_to_be32(0xFFFFFFFF); else p->port_xmit_packets = cpu_to_be32((u32)cntrs.port_xmit_packets); if (cntrs.port_rcv_packets > 0xFFFFFFFFUL) - p->port_rcv_packets = __constant_cpu_to_be32(0xFFFFFFFF); + p->port_rcv_packets = cpu_to_be32(0xFFFFFFFF); else p->port_rcv_packets = cpu_to_be32((u32) cntrs.port_rcv_packets); diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c index 9170710b950..79b3dbc9717 100644 --- a/drivers/infiniband/hw/ipath/ipath_rc.c +++ b/drivers/infiniband/hw/ipath/ipath_rc.c @@ -1744,7 +1744,7 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, /* Signal completion event if the solicited bit is set. */ ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, (ohdr->bth[0] & - __constant_cpu_to_be32(1 << 23)) != 0); + cpu_to_be32(1 << 23)) != 0); break; case OP(RDMA_WRITE_FIRST): diff --git a/drivers/infiniband/hw/ipath/ipath_sdma.c b/drivers/infiniband/hw/ipath/ipath_sdma.c index 8e255adf5d9..4b069859085 100644 --- a/drivers/infiniband/hw/ipath/ipath_sdma.c +++ b/drivers/infiniband/hw/ipath/ipath_sdma.c @@ -781,10 +781,10 @@ retry: descqp = &dd->ipath_sdma_descq[dd->ipath_sdma_descq_cnt].qw[0]; descqp -= 2; /* SDmaLastDesc */ - descqp[0] |= __constant_cpu_to_le64(1ULL << 11); + descqp[0] |= cpu_to_le64(1ULL << 11); if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_INTREQ) { /* SDmaIntReq */ - descqp[0] |= __constant_cpu_to_le64(1ULL << 15); + descqp[0] |= cpu_to_le64(1ULL << 15); } /* Commit writes to memory and advance the tail on the chip */ diff --git a/drivers/infiniband/hw/ipath/ipath_uc.c b/drivers/infiniband/hw/ipath/ipath_uc.c index 82cc588b8bf..22e60998f1a 100644 --- a/drivers/infiniband/hw/ipath/ipath_uc.c +++ b/drivers/infiniband/hw/ipath/ipath_uc.c @@ -419,7 +419,7 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, /* Signal completion event if the solicited bit is set. */ ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, (ohdr->bth[0] & - __constant_cpu_to_be32(1 << 23)) != 0); + cpu_to_be32(1 << 23)) != 0); break; case OP(RDMA_WRITE_FIRST): diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c index 91c74cc797a..6076cb61bf6 100644 --- a/drivers/infiniband/hw/ipath/ipath_ud.c +++ b/drivers/infiniband/hw/ipath/ipath_ud.c @@ -370,7 +370,7 @@ int ipath_make_ud_req(struct ipath_qp *qp) */ ohdr->bth[1] = ah_attr->dlid >= IPATH_MULTICAST_LID_BASE && ah_attr->dlid != IPATH_PERMISSIVE_LID ? - __constant_cpu_to_be32(IPATH_MULTICAST_QPN) : + cpu_to_be32(IPATH_MULTICAST_QPN) : cpu_to_be32(wqe->wr.wr.ud.remote_qpn); ohdr->bth[2] = cpu_to_be32(qp->s_next_psn++ & IPATH_PSN_MASK); /* @@ -573,7 +573,7 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, /* Signal completion event if the solicited bit is set. */ ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, (ohdr->bth[0] & - __constant_cpu_to_be32(1 << 23)) != 0); + cpu_to_be32(1 << 23)) != 0); bail:; } diff --git a/drivers/infiniband/hw/ipath/ipath_user_sdma.c b/drivers/infiniband/hw/ipath/ipath_user_sdma.c index 82d9a0b5ca2..7bff4b9baa0 100644 --- a/drivers/infiniband/hw/ipath/ipath_user_sdma.c +++ b/drivers/infiniband/hw/ipath/ipath_user_sdma.c @@ -667,13 +667,13 @@ static inline __le64 ipath_sdma_make_desc0(struct ipath_devdata *dd, static inline __le64 ipath_sdma_make_first_desc0(__le64 descq) { - return descq | __constant_cpu_to_le64(1ULL << 12); + return descq | cpu_to_le64(1ULL << 12); } static inline __le64 ipath_sdma_make_last_desc0(__le64 descq) { /* last */ /* dma head */ - return descq | __constant_cpu_to_le64(1ULL << 11 | 1ULL << 13); + return descq | cpu_to_le64(1ULL << 11 | 1ULL << 13); } static inline __le64 ipath_sdma_make_desc1(u64 addr) @@ -763,7 +763,7 @@ static int ipath_user_sdma_push_pkts(struct ipath_devdata *dd, if (ofs >= IPATH_SMALLBUF_DWORDS) { for (i = 0; i < pkt->naddr; i++) { dd->ipath_sdma_descq[dtail].qw[0] |= - __constant_cpu_to_le64(1ULL << 14); + cpu_to_le64(1ULL << 14); if (++dtail == dd->ipath_sdma_descq_cnt) dtail = 0; } diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c index cdf0e6abd34..9289ab4b0ae 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.c +++ b/drivers/infiniband/hw/ipath/ipath_verbs.c @@ -1585,7 +1585,7 @@ static int ipath_query_port(struct ib_device *ibdev, u64 ibcstat; memset(props, 0, sizeof(*props)); - props->lid = lid ? lid : __constant_be16_to_cpu(IB_LID_PERMISSIVE); + props->lid = lid ? lid : be16_to_cpu(IB_LID_PERMISSIVE); props->lmc = dd->ipath_lmc; props->sm_lid = dev->sm_lid; props->sm_sl = dev->sm_sl; diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h index 11e3f613df9..ae6cff4abff 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.h +++ b/drivers/infiniband/hw/ipath/ipath_verbs.h @@ -86,11 +86,11 @@ #define IB_PMA_SAMPLE_STATUS_RUNNING 0x02 /* Mandatory IB performance counter select values. */ -#define IB_PMA_PORT_XMIT_DATA __constant_htons(0x0001) -#define IB_PMA_PORT_RCV_DATA __constant_htons(0x0002) -#define IB_PMA_PORT_XMIT_PKTS __constant_htons(0x0003) -#define IB_PMA_PORT_RCV_PKTS __constant_htons(0x0004) -#define IB_PMA_PORT_XMIT_WAIT __constant_htons(0x0005) +#define IB_PMA_PORT_XMIT_DATA cpu_to_be16(0x0001) +#define IB_PMA_PORT_RCV_DATA cpu_to_be16(0x0002) +#define IB_PMA_PORT_XMIT_PKTS cpu_to_be16(0x0003) +#define IB_PMA_PORT_RCV_PKTS cpu_to_be16(0x0004) +#define IB_PMA_PORT_XMIT_WAIT cpu_to_be16(0x0005) struct ib_reth { __be64 vaddr; diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index a91cb4c3fa5..f385a24d31d 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c @@ -71,17 +71,17 @@ enum { }; static const __be32 mlx4_ib_opcode[] = { - [IB_WR_SEND] = __constant_cpu_to_be32(MLX4_OPCODE_SEND), - [IB_WR_LSO] = __constant_cpu_to_be32(MLX4_OPCODE_LSO), - [IB_WR_SEND_WITH_IMM] = __constant_cpu_to_be32(MLX4_OPCODE_SEND_IMM), - [IB_WR_RDMA_WRITE] = __constant_cpu_to_be32(MLX4_OPCODE_RDMA_WRITE), - [IB_WR_RDMA_WRITE_WITH_IMM] = __constant_cpu_to_be32(MLX4_OPCODE_RDMA_WRITE_IMM), - [IB_WR_RDMA_READ] = __constant_cpu_to_be32(MLX4_OPCODE_RDMA_READ), - [IB_WR_ATOMIC_CMP_AND_SWP] = __constant_cpu_to_be32(MLX4_OPCODE_ATOMIC_CS), - [IB_WR_ATOMIC_FETCH_AND_ADD] = __constant_cpu_to_be32(MLX4_OPCODE_ATOMIC_FA), - [IB_WR_SEND_WITH_INV] = __constant_cpu_to_be32(MLX4_OPCODE_SEND_INVAL), - [IB_WR_LOCAL_INV] = __constant_cpu_to_be32(MLX4_OPCODE_LOCAL_INVAL), - [IB_WR_FAST_REG_MR] = __constant_cpu_to_be32(MLX4_OPCODE_FMR), + [IB_WR_SEND] = cpu_to_be32(MLX4_OPCODE_SEND), + [IB_WR_LSO] = cpu_to_be32(MLX4_OPCODE_LSO), + [IB_WR_SEND_WITH_IMM] = cpu_to_be32(MLX4_OPCODE_SEND_IMM), + [IB_WR_RDMA_WRITE] = cpu_to_be32(MLX4_OPCODE_RDMA_WRITE), + [IB_WR_RDMA_WRITE_WITH_IMM] = cpu_to_be32(MLX4_OPCODE_RDMA_WRITE_IMM), + [IB_WR_RDMA_READ] = cpu_to_be32(MLX4_OPCODE_RDMA_READ), + [IB_WR_ATOMIC_CMP_AND_SWP] = cpu_to_be32(MLX4_OPCODE_ATOMIC_CS), + [IB_WR_ATOMIC_FETCH_AND_ADD] = cpu_to_be32(MLX4_OPCODE_ATOMIC_FA), + [IB_WR_SEND_WITH_INV] = cpu_to_be32(MLX4_OPCODE_SEND_INVAL), + [IB_WR_LOCAL_INV] = cpu_to_be32(MLX4_OPCODE_LOCAL_INVAL), + [IB_WR_FAST_REG_MR] = cpu_to_be32(MLX4_OPCODE_FMR), }; static struct mlx4_ib_sqp *to_msqp(struct mlx4_ib_qp *mqp) diff --git a/include/rdma/ib_cm.h b/include/rdma/ib_cm.h index ec7c6d99ed3..93885830430 100644 --- a/include/rdma/ib_cm.h +++ b/include/rdma/ib_cm.h @@ -314,12 +314,12 @@ struct ib_cm_id *ib_create_cm_id(struct ib_device *device, */ void ib_destroy_cm_id(struct ib_cm_id *cm_id); -#define IB_SERVICE_ID_AGN_MASK __constant_cpu_to_be64(0xFF00000000000000ULL) -#define IB_CM_ASSIGN_SERVICE_ID __constant_cpu_to_be64(0x0200000000000000ULL) -#define IB_CMA_SERVICE_ID __constant_cpu_to_be64(0x0000000001000000ULL) -#define IB_CMA_SERVICE_ID_MASK __constant_cpu_to_be64(0xFFFFFFFFFF000000ULL) -#define IB_SDP_SERVICE_ID __constant_cpu_to_be64(0x0000000000010000ULL) -#define IB_SDP_SERVICE_ID_MASK __constant_cpu_to_be64(0xFFFFFFFFFFFF0000ULL) +#define IB_SERVICE_ID_AGN_MASK cpu_to_be64(0xFF00000000000000ULL) +#define IB_CM_ASSIGN_SERVICE_ID cpu_to_be64(0x0200000000000000ULL) +#define IB_CMA_SERVICE_ID cpu_to_be64(0x0000000001000000ULL) +#define IB_CMA_SERVICE_ID_MASK cpu_to_be64(0xFFFFFFFFFF000000ULL) +#define IB_SDP_SERVICE_ID cpu_to_be64(0x0000000000010000ULL) +#define IB_SDP_SERVICE_ID_MASK cpu_to_be64(0xFFFFFFFFFFFF0000ULL) struct ib_cm_compare_data { u8 data[IB_CM_COMPARE_SIZE]; diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h index 5f6c40fffcf..8cc71a130d1 100644 --- a/include/rdma/ib_mad.h +++ b/include/rdma/ib_mad.h @@ -107,7 +107,7 @@ #define IB_MGMT_RMPP_STATUS_ABORT_MAX 127 #define IB_QP0 0 -#define IB_QP1 __constant_htonl(1) +#define IB_QP1 cpu_to_be32(1) #define IB_QP1_QKEY 0x80010000 #define IB_QP_SET_QKEY 0x80000000 diff --git a/include/rdma/ib_smi.h b/include/rdma/ib_smi.h index aaca0878668..98b9086d769 100644 --- a/include/rdma/ib_smi.h +++ b/include/rdma/ib_smi.h @@ -63,25 +63,25 @@ struct ib_smp { u8 return_path[IB_SMP_MAX_PATH_HOPS]; } __attribute__ ((packed)); -#define IB_SMP_DIRECTION __constant_htons(0x8000) +#define IB_SMP_DIRECTION cpu_to_be16(0x8000) /* Subnet management attributes */ -#define IB_SMP_ATTR_NOTICE __constant_htons(0x0002) -#define IB_SMP_ATTR_NODE_DESC __constant_htons(0x0010) -#define IB_SMP_ATTR_NODE_INFO __constant_htons(0x0011) -#define IB_SMP_ATTR_SWITCH_INFO __constant_htons(0x0012) -#define IB_SMP_ATTR_GUID_INFO __constant_htons(0x0014) -#define IB_SMP_ATTR_PORT_INFO __constant_htons(0x0015) -#define IB_SMP_ATTR_PKEY_TABLE __constant_htons(0x0016) -#define IB_SMP_ATTR_SL_TO_VL_TABLE __constant_htons(0x0017) -#define IB_SMP_ATTR_VL_ARB_TABLE __constant_htons(0x0018) -#define IB_SMP_ATTR_LINEAR_FORWARD_TABLE __constant_htons(0x0019) -#define IB_SMP_ATTR_RANDOM_FORWARD_TABLE __constant_htons(0x001A) -#define IB_SMP_ATTR_MCAST_FORWARD_TABLE __constant_htons(0x001B) -#define IB_SMP_ATTR_SM_INFO __constant_htons(0x0020) -#define IB_SMP_ATTR_VENDOR_DIAG __constant_htons(0x0030) -#define IB_SMP_ATTR_LED_INFO __constant_htons(0x0031) -#define IB_SMP_ATTR_VENDOR_MASK __constant_htons(0xFF00) +#define IB_SMP_ATTR_NOTICE cpu_to_be16(0x0002) +#define IB_SMP_ATTR_NODE_DESC cpu_to_be16(0x0010) +#define IB_SMP_ATTR_NODE_INFO cpu_to_be16(0x0011) +#define IB_SMP_ATTR_SWITCH_INFO cpu_to_be16(0x0012) +#define IB_SMP_ATTR_GUID_INFO cpu_to_be16(0x0014) +#define IB_SMP_ATTR_PORT_INFO cpu_to_be16(0x0015) +#define IB_SMP_ATTR_PKEY_TABLE cpu_to_be16(0x0016) +#define IB_SMP_ATTR_SL_TO_VL_TABLE cpu_to_be16(0x0017) +#define IB_SMP_ATTR_VL_ARB_TABLE cpu_to_be16(0x0018) +#define IB_SMP_ATTR_LINEAR_FORWARD_TABLE cpu_to_be16(0x0019) +#define IB_SMP_ATTR_RANDOM_FORWARD_TABLE cpu_to_be16(0x001A) +#define IB_SMP_ATTR_MCAST_FORWARD_TABLE cpu_to_be16(0x001B) +#define IB_SMP_ATTR_SM_INFO cpu_to_be16(0x0020) +#define IB_SMP_ATTR_VENDOR_DIAG cpu_to_be16(0x0030) +#define IB_SMP_ATTR_LED_INFO cpu_to_be16(0x0031) +#define IB_SMP_ATTR_VENDOR_MASK cpu_to_be16(0xFF00) struct ib_port_info { __be64 mkey; -- GitLab From 1b437c8c73a36daa471dd54a63c426d72af5723d Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Mon, 19 Jan 2009 00:38:57 +0900 Subject: [PATCH 0195/4982] x86-64: Move irq stats from PDA to per-cpu and consolidate with 32-bit. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/hardirq_64.h | 24 +++++++++++++++++++----- arch/x86/include/asm/pda.h | 10 ---------- arch/x86/kernel/irq.c | 6 +----- arch/x86/kernel/irq_64.c | 3 +++ arch/x86/kernel/nmi.c | 10 +--------- arch/x86/xen/smp.c | 18 +++--------------- 6 files changed, 27 insertions(+), 44 deletions(-) diff --git a/arch/x86/include/asm/hardirq_64.h b/arch/x86/include/asm/hardirq_64.h index b5a6b5d5670..a65bab20f6c 100644 --- a/arch/x86/include/asm/hardirq_64.h +++ b/arch/x86/include/asm/hardirq_64.h @@ -3,22 +3,36 @@ #include #include -#include #include +typedef struct { + unsigned int __softirq_pending; + unsigned int __nmi_count; /* arch dependent */ + unsigned int apic_timer_irqs; /* arch dependent */ + unsigned int irq0_irqs; + unsigned int irq_resched_count; + unsigned int irq_call_count; + unsigned int irq_tlb_count; + unsigned int irq_thermal_count; + unsigned int irq_spurious_count; + unsigned int irq_threshold_count; +} ____cacheline_aligned irq_cpustat_t; + +DECLARE_PER_CPU(irq_cpustat_t, irq_stat); + /* We can have at most NR_VECTORS irqs routed to a cpu at a time */ #define MAX_HARDIRQS_PER_CPU NR_VECTORS #define __ARCH_IRQ_STAT 1 -#define inc_irq_stat(member) add_pda(member, 1) +#define inc_irq_stat(member) percpu_add(irq_stat.member, 1) -#define local_softirq_pending() read_pda(__softirq_pending) +#define local_softirq_pending() percpu_read(irq_stat.__softirq_pending) #define __ARCH_SET_SOFTIRQ_PENDING 1 -#define set_softirq_pending(x) write_pda(__softirq_pending, (x)) -#define or_softirq_pending(x) or_pda(__softirq_pending, (x)) +#define set_softirq_pending(x) percpu_write(irq_stat.__softirq_pending, (x)) +#define or_softirq_pending(x) percpu_or(irq_stat.__softirq_pending, (x)) extern void ack_bad_irq(unsigned int irq); diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h index 47f274fe695..69a40757e21 100644 --- a/arch/x86/include/asm/pda.h +++ b/arch/x86/include/asm/pda.h @@ -25,19 +25,9 @@ struct x8664_pda { char *irqstackptr; short nodenumber; /* number of current node (32k max) */ short in_bootmem; /* pda lives in bootmem */ - unsigned int __softirq_pending; - unsigned int __nmi_count; /* number of NMI on this CPUs */ short mmu_state; short isidle; struct mm_struct *active_mm; - unsigned apic_timer_irqs; - unsigned irq0_irqs; - unsigned irq_resched_count; - unsigned irq_call_count; - unsigned irq_tlb_count; - unsigned irq_thermal_count; - unsigned irq_threshold_count; - unsigned irq_spurious_count; } ____cacheline_aligned_in_smp; DECLARE_PER_CPU(struct x8664_pda, __pda); diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 3973e2df7f8..8b30d0c2512 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -36,11 +36,7 @@ void ack_bad_irq(unsigned int irq) #endif } -#ifdef CONFIG_X86_32 -# define irq_stats(x) (&per_cpu(irq_stat, x)) -#else -# define irq_stats(x) cpu_pda(x) -#endif +#define irq_stats(x) (&per_cpu(irq_stat, x)) /* * /proc/interrupts printing: */ diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index 0b21cb1ea11..1db05247b47 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c @@ -19,6 +19,9 @@ #include #include +DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); +EXPORT_PER_CPU_SYMBOL(irq_stat); + /* * Probabilistic stack overflow check: * diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c index 7228979f1e7..23b6d9e6e4f 100644 --- a/arch/x86/kernel/nmi.c +++ b/arch/x86/kernel/nmi.c @@ -61,11 +61,7 @@ static int endflag __initdata; static inline unsigned int get_nmi_count(int cpu) { -#ifdef CONFIG_X86_64 - return cpu_pda(cpu)->__nmi_count; -#else - return nmi_count(cpu); -#endif + return per_cpu(irq_stat, cpu).__nmi_count; } static inline int mce_in_progress(void) @@ -82,12 +78,8 @@ static inline int mce_in_progress(void) */ static inline unsigned int get_timer_irqs(int cpu) { -#ifdef CONFIG_X86_64 - return read_pda(apic_timer_irqs) + read_pda(irq0_irqs); -#else return per_cpu(irq_stat, cpu).apic_timer_irqs + per_cpu(irq_stat, cpu).irq0_irqs; -#endif } #ifdef CONFIG_SMP diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 3bfd6dd0b47..9ff3b0999cf 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -50,11 +50,7 @@ static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id); */ static irqreturn_t xen_reschedule_interrupt(int irq, void *dev_id) { -#ifdef CONFIG_X86_32 - __get_cpu_var(irq_stat).irq_resched_count++; -#else - add_pda(irq_resched_count, 1); -#endif + inc_irq_stat(irq_resched_count); return IRQ_HANDLED; } @@ -435,11 +431,7 @@ static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id) { irq_enter(); generic_smp_call_function_interrupt(); -#ifdef CONFIG_X86_32 - __get_cpu_var(irq_stat).irq_call_count++; -#else - add_pda(irq_call_count, 1); -#endif + inc_irq_stat(irq_call_count); irq_exit(); return IRQ_HANDLED; @@ -449,11 +441,7 @@ static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id) { irq_enter(); generic_smp_call_function_single_interrupt(); -#ifdef CONFIG_X86_32 - __get_cpu_var(irq_stat).irq_call_count++; -#else - add_pda(irq_call_count, 1); -#endif + inc_irq_stat(irq_call_count); irq_exit(); return IRQ_HANDLED; -- GitLab From 9eb912d1aa6b8106e06a73ea6702ec3dab0d6a1a Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Mon, 19 Jan 2009 00:38:57 +0900 Subject: [PATCH 0196/4982] x86-64: Move TLB state from PDA to per-cpu and consolidate with 32-bit. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/mmu_context_64.h | 16 +++++++--------- arch/x86/include/asm/pda.h | 2 -- arch/x86/include/asm/tlbflush.h | 7 ++----- arch/x86/kernel/cpu/common.c | 2 -- arch/x86/kernel/tlb_32.c | 12 ++---------- arch/x86/kernel/tlb_64.c | 13 ++++++++----- arch/x86/xen/mmu.c | 6 +----- 7 files changed, 20 insertions(+), 38 deletions(-) diff --git a/arch/x86/include/asm/mmu_context_64.h b/arch/x86/include/asm/mmu_context_64.h index 677d36e9540..c4572505ab3 100644 --- a/arch/x86/include/asm/mmu_context_64.h +++ b/arch/x86/include/asm/mmu_context_64.h @@ -1,13 +1,11 @@ #ifndef _ASM_X86_MMU_CONTEXT_64_H #define _ASM_X86_MMU_CONTEXT_64_H -#include - static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) { #ifdef CONFIG_SMP - if (read_pda(mmu_state) == TLBSTATE_OK) - write_pda(mmu_state, TLBSTATE_LAZY); + if (percpu_read(cpu_tlbstate.state) == TLBSTATE_OK) + percpu_write(cpu_tlbstate.state, TLBSTATE_LAZY); #endif } @@ -19,8 +17,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, /* stop flush ipis for the previous mm */ cpu_clear(cpu, prev->cpu_vm_mask); #ifdef CONFIG_SMP - write_pda(mmu_state, TLBSTATE_OK); - write_pda(active_mm, next); + percpu_write(cpu_tlbstate.state, TLBSTATE_OK); + percpu_write(cpu_tlbstate.active_mm, next); #endif cpu_set(cpu, next->cpu_vm_mask); load_cr3(next->pgd); @@ -30,9 +28,9 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, } #ifdef CONFIG_SMP else { - write_pda(mmu_state, TLBSTATE_OK); - if (read_pda(active_mm) != next) - BUG(); + percpu_write(cpu_tlbstate.state, TLBSTATE_OK); + BUG_ON(percpu_read(cpu_tlbstate.active_mm) != next); + if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) { /* We were in lazy tlb mode and leave_mm disabled * tlb flush IPI delivery. We must reload CR3 diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h index 69a40757e21..8ee835ed10e 100644 --- a/arch/x86/include/asm/pda.h +++ b/arch/x86/include/asm/pda.h @@ -25,9 +25,7 @@ struct x8664_pda { char *irqstackptr; short nodenumber; /* number of current node (32k max) */ short in_bootmem; /* pda lives in bootmem */ - short mmu_state; short isidle; - struct mm_struct *active_mm; } ____cacheline_aligned_in_smp; DECLARE_PER_CPU(struct x8664_pda, __pda); diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index 17feaa9c7e7..d3539f998f8 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -148,20 +148,17 @@ void native_flush_tlb_others(const struct cpumask *cpumask, #define TLBSTATE_OK 1 #define TLBSTATE_LAZY 2 -#ifdef CONFIG_X86_32 struct tlb_state { struct mm_struct *active_mm; int state; - char __cacheline_padding[L1_CACHE_BYTES-8]; }; DECLARE_PER_CPU(struct tlb_state, cpu_tlbstate); -void reset_lazy_tlbstate(void); -#else static inline void reset_lazy_tlbstate(void) { + percpu_write(cpu_tlbstate.state, 0); + percpu_write(cpu_tlbstate.active_mm, &init_mm); } -#endif #endif /* SMP */ diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index c49498d4083..3d0cc6f1711 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -897,8 +897,6 @@ void __cpuinit pda_init(int cpu) pda->irqcount = -1; pda->kernelstack = (unsigned long)stack_thread_info() - PDA_STACKOFFSET + THREAD_SIZE; - pda->active_mm = &init_mm; - pda->mmu_state = 0; if (cpu == 0) { /* others are initialized in smpboot.c */ diff --git a/arch/x86/kernel/tlb_32.c b/arch/x86/kernel/tlb_32.c index e65449d0f7d..abf0808d6fc 100644 --- a/arch/x86/kernel/tlb_32.c +++ b/arch/x86/kernel/tlb_32.c @@ -4,8 +4,8 @@ #include -DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) - ____cacheline_aligned = { &init_mm, 0, }; +DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) + = { &init_mm, 0, }; /* must come after the send_IPI functions above for inlining */ #include @@ -231,14 +231,6 @@ void flush_tlb_all(void) on_each_cpu(do_flush_tlb_all, NULL, 1); } -void reset_lazy_tlbstate(void) -{ - int cpu = raw_smp_processor_id(); - - per_cpu(cpu_tlbstate, cpu).state = 0; - per_cpu(cpu_tlbstate, cpu).active_mm = &init_mm; -} - static int init_flush_cpumask(void) { alloc_cpumask_var(&flush_cpumask, GFP_KERNEL); diff --git a/arch/x86/kernel/tlb_64.c b/arch/x86/kernel/tlb_64.c index 7f4141d3b66..e64a32c4882 100644 --- a/arch/x86/kernel/tlb_64.c +++ b/arch/x86/kernel/tlb_64.c @@ -18,6 +18,9 @@ #include #include +DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) + = { &init_mm, 0, }; + #include /* * Smarter SMP flushing macros. @@ -62,9 +65,9 @@ static DEFINE_PER_CPU(union smp_flush_state, flush_state); */ void leave_mm(int cpu) { - if (read_pda(mmu_state) == TLBSTATE_OK) + if (percpu_read(cpu_tlbstate.state) == TLBSTATE_OK) BUG(); - cpu_clear(cpu, read_pda(active_mm)->cpu_vm_mask); + cpu_clear(cpu, percpu_read(cpu_tlbstate.active_mm)->cpu_vm_mask); load_cr3(swapper_pg_dir); } EXPORT_SYMBOL_GPL(leave_mm); @@ -142,8 +145,8 @@ asmlinkage void smp_invalidate_interrupt(struct pt_regs *regs) * BUG(); */ - if (f->flush_mm == read_pda(active_mm)) { - if (read_pda(mmu_state) == TLBSTATE_OK) { + if (f->flush_mm == percpu_read(cpu_tlbstate.active_mm)) { + if (percpu_read(cpu_tlbstate.state) == TLBSTATE_OK) { if (f->flush_va == TLB_FLUSH_ALL) local_flush_tlb(); else @@ -281,7 +284,7 @@ static void do_flush_tlb_all(void *info) unsigned long cpu = smp_processor_id(); __flush_tlb_all(); - if (read_pda(mmu_state) == TLBSTATE_LAZY) + if (percpu_read(cpu_tlbstate.state) == TLBSTATE_LAZY) leave_mm(cpu); } diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 7bc7852cc5c..98cb9869eb2 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1063,11 +1063,7 @@ static void drop_other_mm_ref(void *info) struct mm_struct *mm = info; struct mm_struct *active_mm; -#ifdef CONFIG_X86_64 - active_mm = read_pda(active_mm); -#else - active_mm = __get_cpu_var(cpu_tlbstate).active_mm; -#endif + active_mm = percpu_read(cpu_tlbstate.active_mm); if (active_mm == mm) leave_mm(smp_processor_id()); -- GitLab From 26f80bd6a9ab17bc8a60b6092e7c0d05c5927ce5 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Mon, 19 Jan 2009 00:38:58 +0900 Subject: [PATCH 0197/4982] x86-64: Convert irqstacks to per-cpu Move the irqstackptr variable from the PDA to per-cpu. Make the stacks themselves per-cpu, removing some specific allocation code. Add a seperate flag (is_boot_cpu) to simplify the per-cpu boot adjustments. tj: * sprinkle some underbars around. * irq_stack_ptr is not used till traps_init(), no reason to initialize it early. On SMP, just leaving it NULL till proper initialization in setup_per_cpu_areas() works. Dropped is_boot_cpu and early irq_stack_ptr initialization. * do DECLARE/DEFINE_PER_CPU(char[IRQ_STACK_SIZE], irq_stack) instead of (char, irq_stack[IRQ_STACK_SIZE]). Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/page_64.h | 4 ++-- arch/x86/include/asm/pda.h | 1 - arch/x86/include/asm/processor.h | 3 +++ arch/x86/kernel/asm-offsets_64.c | 1 - arch/x86/kernel/cpu/common.c | 19 +++++++----------- arch/x86/kernel/dumpstack_64.c | 33 ++++++++++++++++---------------- arch/x86/kernel/entry_64.S | 6 +++--- arch/x86/kernel/setup_percpu.c | 4 +++- 8 files changed, 35 insertions(+), 36 deletions(-) diff --git a/arch/x86/include/asm/page_64.h b/arch/x86/include/asm/page_64.h index 5ebca29f44f..e27fdbe5f9e 100644 --- a/arch/x86/include/asm/page_64.h +++ b/arch/x86/include/asm/page_64.h @@ -13,8 +13,8 @@ #define DEBUG_STACK_ORDER (EXCEPTION_STACK_ORDER + 1) #define DEBUG_STKSZ (PAGE_SIZE << DEBUG_STACK_ORDER) -#define IRQSTACK_ORDER 2 -#define IRQSTACKSIZE (PAGE_SIZE << IRQSTACK_ORDER) +#define IRQ_STACK_ORDER 2 +#define IRQ_STACK_SIZE (PAGE_SIZE << IRQ_STACK_ORDER) #define STACKFAULT_STACK 1 #define DOUBLEFAULT_STACK 2 diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h index 8ee835ed10e..09965f7a216 100644 --- a/arch/x86/include/asm/pda.h +++ b/arch/x86/include/asm/pda.h @@ -22,7 +22,6 @@ struct x8664_pda { /* gcc-ABI: this canary MUST be at offset 40!!! */ #endif - char *irqstackptr; short nodenumber; /* number of current node (32k max) */ short in_bootmem; /* pda lives in bootmem */ short isidle; diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 091cd8855f2..f511246fa6c 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -378,6 +378,9 @@ union thread_xstate { #ifdef CONFIG_X86_64 DECLARE_PER_CPU(struct orig_ist, orig_ist); + +DECLARE_PER_CPU(char[IRQ_STACK_SIZE], irq_stack); +DECLARE_PER_CPU(char *, irq_stack_ptr); #endif extern void print_cpu_info(struct cpuinfo_x86 *); diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index f4cc81bfbf8..5b821fbdaf7 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c @@ -54,7 +54,6 @@ int main(void) ENTRY(pcurrent); ENTRY(irqcount); ENTRY(cpunumber); - ENTRY(irqstackptr); DEFINE(pda_size, sizeof(struct x8664_pda)); BLANK(); #undef ENTRY diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 3d0cc6f1711..496f0a01919 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -881,7 +881,13 @@ __setup("clearcpuid=", setup_disablecpuid); #ifdef CONFIG_X86_64 struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table }; -static char boot_cpu_stack[IRQSTACKSIZE] __page_aligned_bss; +DEFINE_PER_CPU_PAGE_ALIGNED(char[IRQ_STACK_SIZE], irq_stack); +#ifdef CONFIG_SMP +DEFINE_PER_CPU(char *, irq_stack_ptr); /* will be set during per cpu init */ +#else +DEFINE_PER_CPU(char *, irq_stack_ptr) = + per_cpu_var(irq_stack) + IRQ_STACK_SIZE - 64; +#endif void __cpuinit pda_init(int cpu) { @@ -901,18 +907,7 @@ void __cpuinit pda_init(int cpu) if (cpu == 0) { /* others are initialized in smpboot.c */ pda->pcurrent = &init_task; - pda->irqstackptr = boot_cpu_stack; - pda->irqstackptr += IRQSTACKSIZE - 64; } else { - if (!pda->irqstackptr) { - pda->irqstackptr = (char *) - __get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER); - if (!pda->irqstackptr) - panic("cannot allocate irqstack for cpu %d", - cpu); - pda->irqstackptr += IRQSTACKSIZE - 64; - } - if (pda->nodenumber == 0 && cpu_to_node(cpu) != NUMA_NO_NODE) pda->nodenumber = cpu_to_node(cpu); } diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index c302d070704..28e26a4315d 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c @@ -106,7 +106,8 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, const struct stacktrace_ops *ops, void *data) { const unsigned cpu = get_cpu(); - unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr; + unsigned long *irq_stack_end = + (unsigned long *)per_cpu(irq_stack_ptr, cpu); unsigned used = 0; struct thread_info *tinfo; int graph = 0; @@ -160,23 +161,23 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, stack = (unsigned long *) estack_end[-2]; continue; } - if (irqstack_end) { - unsigned long *irqstack; - irqstack = irqstack_end - - (IRQSTACKSIZE - 64) / sizeof(*irqstack); + if (irq_stack_end) { + unsigned long *irq_stack; + irq_stack = irq_stack_end - + (IRQ_STACK_SIZE - 64) / sizeof(*irq_stack); - if (stack >= irqstack && stack < irqstack_end) { + if (stack >= irq_stack && stack < irq_stack_end) { if (ops->stack(data, "IRQ") < 0) break; bp = print_context_stack(tinfo, stack, bp, - ops, data, irqstack_end, &graph); + ops, data, irq_stack_end, &graph); /* * We link to the next stack (which would be * the process stack normally) the last * pointer (index -1 to end) in the IRQ stack: */ - stack = (unsigned long *) (irqstack_end[-1]); - irqstack_end = NULL; + stack = (unsigned long *) (irq_stack_end[-1]); + irq_stack_end = NULL; ops->stack(data, "EOI"); continue; } @@ -199,10 +200,10 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, unsigned long *stack; int i; const int cpu = smp_processor_id(); - unsigned long *irqstack_end = - (unsigned long *) (cpu_pda(cpu)->irqstackptr); - unsigned long *irqstack = - (unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE); + unsigned long *irq_stack_end = + (unsigned long *)(per_cpu(irq_stack_ptr, cpu)); + unsigned long *irq_stack = + (unsigned long *)(per_cpu(irq_stack_ptr, cpu) - IRQ_STACK_SIZE); /* * debugging aid: "show_stack(NULL, NULL);" prints the @@ -218,9 +219,9 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, stack = sp; for (i = 0; i < kstack_depth_to_print; i++) { - if (stack >= irqstack && stack <= irqstack_end) { - if (stack == irqstack_end) { - stack = (unsigned long *) (irqstack_end[-1]); + if (stack >= irq_stack && stack <= irq_stack_end) { + if (stack == irq_stack_end) { + stack = (unsigned long *) (irq_stack_end[-1]); printk(" "); } } else { diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 4833f3a1965..d22677a6643 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -345,7 +345,7 @@ ENTRY(save_args) 1: incl %gs:pda_irqcount jne 2f popq_cfi %rax /* move return address... */ - mov %gs:pda_irqstackptr,%rsp + mov PER_CPU_VAR(irq_stack_ptr),%rsp EMPTY_FRAME 0 pushq_cfi %rax /* ... to the new stack */ /* @@ -1261,7 +1261,7 @@ ENTRY(call_softirq) mov %rsp,%rbp CFI_DEF_CFA_REGISTER rbp incl %gs:pda_irqcount - cmove %gs:pda_irqstackptr,%rsp + cmove PER_CPU_VAR(irq_stack_ptr),%rsp push %rbp # backlink for old unwinder call __do_softirq leaveq @@ -1300,7 +1300,7 @@ ENTRY(xen_do_hypervisor_callback) # do_hypervisor_callback(struct *pt_regs) 11: incl %gs:pda_irqcount movq %rsp,%rbp CFI_DEF_CFA_REGISTER rbp - cmovzq %gs:pda_irqstackptr,%rsp + cmovzq PER_CPU_VAR(irq_stack_ptr),%rsp pushq %rbp # backlink for old unwinder call xen_evtchn_do_upcall popq %rsp diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index b5c35af2011..8b53ef83c61 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -192,7 +192,10 @@ void __init setup_per_cpu_areas(void) memcpy(ptr, __per_cpu_load, __per_cpu_end - __per_cpu_start); per_cpu_offset(cpu) = ptr - __per_cpu_start; + per_cpu(this_cpu_off, cpu) = per_cpu_offset(cpu); #ifdef CONFIG_X86_64 + per_cpu(irq_stack_ptr, cpu) = + (char *)per_cpu(irq_stack, cpu) + IRQ_STACK_SIZE - 64; /* * CPU0 modified pda in the init data area, reload pda * offset for CPU0 and clear the area for others. @@ -202,7 +205,6 @@ void __init setup_per_cpu_areas(void) else memset(cpu_pda(cpu), 0, sizeof(*cpu_pda(cpu))); #endif - per_cpu(this_cpu_off, cpu) = per_cpu_offset(cpu); DBG("PERCPU: cpu %4d %p\n", cpu, ptr); } -- GitLab From 92d65b2371d86d40807e1dbfdccadc4d501edcde Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Mon, 19 Jan 2009 00:38:58 +0900 Subject: [PATCH 0198/4982] x86-64: Convert exception stacks to per-cpu Move the exception stacks to per-cpu, removing specific allocation code. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/kernel/cpu/common.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 496f0a01919..b6d7eec0be7 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -913,8 +913,9 @@ void __cpuinit pda_init(int cpu) } } -static char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + - DEBUG_STKSZ] __page_aligned_bss; +static DEFINE_PER_CPU_PAGE_ALIGNED(char, exception_stacks + [(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ]) + __aligned(PAGE_SIZE); extern asmlinkage void ignore_sysret(void); @@ -972,15 +973,12 @@ void __cpuinit cpu_init(void) struct tss_struct *t = &per_cpu(init_tss, cpu); struct orig_ist *orig_ist = &per_cpu(orig_ist, cpu); unsigned long v; - char *estacks = NULL; struct task_struct *me; int i; /* CPU 0 is initialised in head64.c */ if (cpu != 0) pda_init(cpu); - else - estacks = boot_exception_stacks; me = current; @@ -1014,18 +1012,13 @@ void __cpuinit cpu_init(void) * set up and load the per-CPU TSS */ if (!orig_ist->ist[0]) { - static const unsigned int order[N_EXCEPTION_STACKS] = { - [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER, - [DEBUG_STACK - 1] = DEBUG_STACK_ORDER + static const unsigned int sizes[N_EXCEPTION_STACKS] = { + [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STKSZ, + [DEBUG_STACK - 1] = DEBUG_STKSZ }; + char *estacks = per_cpu(exception_stacks, cpu); for (v = 0; v < N_EXCEPTION_STACKS; v++) { - if (cpu) { - estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]); - if (!estacks) - panic("Cannot allocate exception " - "stack %ld %d\n", v, cpu); - } - estacks += PAGE_SIZE << order[v]; + estacks += sizes[v]; orig_ist->ist[v] = t->x86_tss.ist[v] = (unsigned long)estacks; } -- GitLab From ea9279066de44053d0c20ea855bc9f4706652d84 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Mon, 19 Jan 2009 00:38:58 +0900 Subject: [PATCH 0199/4982] x86-64: Move cpu number from PDA to per-cpu and consolidate with 32-bit. tj: moved cpu_number definition out of CONFIG_HAVE_SETUP_PER_CPU_AREA for voyager. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/pda.h | 2 +- arch/x86/include/asm/smp.h | 4 +--- arch/x86/kernel/asm-offsets_64.c | 1 - arch/x86/kernel/cpu/common.c | 1 - arch/x86/kernel/process_32.c | 3 --- arch/x86/kernel/setup_percpu.c | 10 ++++++++++ arch/x86/kernel/smpcommon.c | 2 -- 7 files changed, 12 insertions(+), 11 deletions(-) diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h index 09965f7a216..668d5a5b6f7 100644 --- a/arch/x86/include/asm/pda.h +++ b/arch/x86/include/asm/pda.h @@ -16,7 +16,7 @@ struct x8664_pda { unsigned long kernelstack; /* 16 top of kernel stack for current */ unsigned long oldrsp; /* 24 user rsp for system call */ int irqcount; /* 32 Irq nesting counter. Starts -1 */ - unsigned int cpunumber; /* 36 Logical CPU number */ + unsigned int unused6; /* 36 was cpunumber */ #ifdef CONFIG_CC_STACKPROTECTOR unsigned long stack_canary; /* 40 stack canary value */ /* gcc-ABI: this canary MUST be at diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index c7bbbbe65d3..68636e767a9 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -25,9 +25,7 @@ extern unsigned int num_processors; DECLARE_PER_CPU(cpumask_t, cpu_sibling_map); DECLARE_PER_CPU(cpumask_t, cpu_core_map); DECLARE_PER_CPU(u16, cpu_llc_id); -#ifdef CONFIG_X86_32 DECLARE_PER_CPU(int, cpu_number); -#endif static inline struct cpumask *cpu_sibling_mask(int cpu) { @@ -164,7 +162,7 @@ extern unsigned disabled_cpus __cpuinitdata; extern int safe_smp_processor_id(void); #elif defined(CONFIG_X86_64_SMP) -#define raw_smp_processor_id() read_pda(cpunumber) +#define raw_smp_processor_id() (percpu_read(cpu_number)) #define stack_smp_processor_id() \ ({ \ diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index 5b821fbdaf7..cae6697c099 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c @@ -53,7 +53,6 @@ int main(void) ENTRY(oldrsp); ENTRY(pcurrent); ENTRY(irqcount); - ENTRY(cpunumber); DEFINE(pda_size, sizeof(struct x8664_pda)); BLANK(); #undef ENTRY diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index b6d7eec0be7..4221e920886 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -899,7 +899,6 @@ void __cpuinit pda_init(int cpu) load_pda_offset(cpu); - pda->cpunumber = cpu; pda->irqcount = -1; pda->kernelstack = (unsigned long)stack_thread_info() - PDA_STACKOFFSET + THREAD_SIZE; diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 77d546817d9..2c00a57ccb9 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -66,9 +66,6 @@ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task; EXPORT_PER_CPU_SYMBOL(current_task); -DEFINE_PER_CPU(int, cpu_number); -EXPORT_PER_CPU_SYMBOL(cpu_number); - /* * Return saved PC of a blocked thread. */ diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 8b53ef83c61..258497f93f4 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -22,6 +22,15 @@ # define DBG(x...) #endif +/* + * Could be inside CONFIG_HAVE_SETUP_PER_CPU_AREA with other stuff but + * voyager wants cpu_number too. + */ +#ifdef CONFIG_SMP +DEFINE_PER_CPU(int, cpu_number); +EXPORT_PER_CPU_SYMBOL(cpu_number); +#endif + #ifdef CONFIG_X86_LOCAL_APIC unsigned int num_processors; unsigned disabled_cpus __cpuinitdata; @@ -193,6 +202,7 @@ void __init setup_per_cpu_areas(void) memcpy(ptr, __per_cpu_load, __per_cpu_end - __per_cpu_start); per_cpu_offset(cpu) = ptr - __per_cpu_start; per_cpu(this_cpu_off, cpu) = per_cpu_offset(cpu); + per_cpu(cpu_number, cpu) = cpu; #ifdef CONFIG_X86_64 per_cpu(irq_stack_ptr, cpu) = (char *)per_cpu(irq_stack, cpu) + IRQ_STACK_SIZE - 64; diff --git a/arch/x86/kernel/smpcommon.c b/arch/x86/kernel/smpcommon.c index 7e157810062..add36b4e37c 100644 --- a/arch/x86/kernel/smpcommon.c +++ b/arch/x86/kernel/smpcommon.c @@ -28,7 +28,5 @@ __cpuinit void init_gdt(int cpu) write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_PERCPU, &gdt, DESCTYPE_S); - - per_cpu(cpu_number, cpu) = cpu; } #endif -- GitLab From c6f5e0acd5d12ee23f701f15889872e67b47caa6 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Mon, 19 Jan 2009 00:38:58 +0900 Subject: [PATCH 0200/4982] x86-64: Move current task from PDA to per-cpu and consolidate with 32-bit. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/current.h | 24 +++--------------------- arch/x86/include/asm/pda.h | 4 ++-- arch/x86/include/asm/system.h | 4 ++-- arch/x86/kernel/asm-offsets_64.c | 1 - arch/x86/kernel/cpu/common.c | 5 +---- arch/x86/kernel/dumpstack_64.c | 2 +- arch/x86/kernel/process_64.c | 5 ++++- arch/x86/kernel/smpboot.c | 3 +-- arch/x86/xen/smp.c | 3 +-- 9 files changed, 15 insertions(+), 36 deletions(-) diff --git a/arch/x86/include/asm/current.h b/arch/x86/include/asm/current.h index 0728480f5c5..c68c361697e 100644 --- a/arch/x86/include/asm/current.h +++ b/arch/x86/include/asm/current.h @@ -1,39 +1,21 @@ #ifndef _ASM_X86_CURRENT_H #define _ASM_X86_CURRENT_H -#ifdef CONFIG_X86_32 #include #include +#ifndef __ASSEMBLY__ struct task_struct; DECLARE_PER_CPU(struct task_struct *, current_task); -static __always_inline struct task_struct *get_current(void) -{ - return percpu_read(current_task); -} - -#else /* X86_32 */ - -#ifndef __ASSEMBLY__ -#include - -struct task_struct; static __always_inline struct task_struct *get_current(void) { - return read_pda(pcurrent); + return percpu_read(current_task); } -#else /* __ASSEMBLY__ */ - -#include -#define GET_CURRENT(reg) movq %gs:(pda_pcurrent),reg +#define current get_current() #endif /* __ASSEMBLY__ */ -#endif /* X86_32 */ - -#define current get_current() - #endif /* _ASM_X86_CURRENT_H */ diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h index 668d5a5b6f7..7209302d922 100644 --- a/arch/x86/include/asm/pda.h +++ b/arch/x86/include/asm/pda.h @@ -11,8 +11,8 @@ /* Per processor datastructure. %gs points to it while the kernel runs */ struct x8664_pda { - struct task_struct *pcurrent; /* 0 Current process */ - unsigned long dummy; + unsigned long unused1; + unsigned long unused2; unsigned long kernelstack; /* 16 top of kernel stack for current */ unsigned long oldrsp; /* 24 user rsp for system call */ int irqcount; /* 32 Irq nesting counter. Starts -1 */ diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h index 8e626ea33a1..4399aac680e 100644 --- a/arch/x86/include/asm/system.h +++ b/arch/x86/include/asm/system.h @@ -94,7 +94,7 @@ do { \ "call __switch_to\n\t" \ ".globl thread_return\n" \ "thread_return:\n\t" \ - "movq %%gs:%P[pda_pcurrent],%%rsi\n\t" \ + "movq "__percpu_seg_str"%P[current_task],%%rsi\n\t" \ "movq %P[thread_info](%%rsi),%%r8\n\t" \ LOCK_PREFIX "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" \ "movq %%rax,%%rdi\n\t" \ @@ -106,7 +106,7 @@ do { \ [ti_flags] "i" (offsetof(struct thread_info, flags)), \ [tif_fork] "i" (TIF_FORK), \ [thread_info] "i" (offsetof(struct task_struct, stack)), \ - [pda_pcurrent] "i" (offsetof(struct x8664_pda, pcurrent)) \ + [current_task] "m" (per_cpu_var(current_task)) \ : "memory", "cc" __EXTRA_CLOBBER) #endif diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index cae6697c099..4f7a210e1e5 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c @@ -51,7 +51,6 @@ int main(void) #define ENTRY(entry) DEFINE(pda_ ## entry, offsetof(struct x8664_pda, entry)) ENTRY(kernelstack); ENTRY(oldrsp); - ENTRY(pcurrent); ENTRY(irqcount); DEFINE(pda_size, sizeof(struct x8664_pda)); BLANK(); diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 4221e920886..b50e38d1688 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -903,10 +903,7 @@ void __cpuinit pda_init(int cpu) pda->kernelstack = (unsigned long)stack_thread_info() - PDA_STACKOFFSET + THREAD_SIZE; - if (cpu == 0) { - /* others are initialized in smpboot.c */ - pda->pcurrent = &init_task; - } else { + if (cpu != 0) { if (pda->nodenumber == 0 && cpu_to_node(cpu) != NUMA_NO_NODE) pda->nodenumber = cpu_to_node(cpu); } diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index 28e26a4315d..d35db5993fd 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c @@ -242,7 +242,7 @@ void show_registers(struct pt_regs *regs) int i; unsigned long sp; const int cpu = smp_processor_id(); - struct task_struct *cur = cpu_pda(cpu)->pcurrent; + struct task_struct *cur = current; sp = regs->sp; printk("CPU %d ", cpu); diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 416fb9282f4..e00c31a4b3c 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -57,6 +57,9 @@ asmlinkage extern void ret_from_fork(void); +DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task; +EXPORT_PER_CPU_SYMBOL(current_task); + unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED; static ATOMIC_NOTIFIER_HEAD(idle_notifier); @@ -615,7 +618,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) */ prev->usersp = read_pda(oldrsp); write_pda(oldrsp, next->usersp); - write_pda(pcurrent, next_p); + percpu_write(current_task, next_p); write_pda(kernelstack, (unsigned long)task_stack_page(next_p) + diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 2f0e0f1090f..5854be0fb80 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -790,13 +790,12 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu) set_idle_for_cpu(cpu, c_idle.idle); do_rest: -#ifdef CONFIG_X86_32 per_cpu(current_task, cpu) = c_idle.idle; +#ifdef CONFIG_X86_32 init_gdt(cpu); /* Stack for startup_32 can be just as for start_secondary onwards */ irq_ctx_init(cpu); #else - cpu_pda(cpu)->pcurrent = c_idle.idle; clear_tsk_thread_flag(c_idle.idle, TIF_FORK); initial_gs = per_cpu_offset(cpu); #endif diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 9ff3b0999cf..72c2eb9b64c 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -279,12 +279,11 @@ static int __cpuinit xen_cpu_up(unsigned int cpu) struct task_struct *idle = idle_task(cpu); int rc; + per_cpu(current_task, cpu) = idle; #ifdef CONFIG_X86_32 init_gdt(cpu); - per_cpu(current_task, cpu) = idle; irq_ctx_init(cpu); #else - cpu_pda(cpu)->pcurrent = idle; clear_tsk_thread_flag(idle, TIF_FORK); #endif xen_setup_timer(cpu); -- GitLab From 9af45651f1f7c89942e016a1a00a7ebddfa727f8 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Mon, 19 Jan 2009 00:38:58 +0900 Subject: [PATCH 0201/4982] x86-64: Move kernelstack from PDA to per-cpu. Also clean up PER_CPU_VAR usage in xen-asm_64.S tj: * remove now unused stack_thread_info() * s/kernelstack/kernel_stack/ * added FIXME comment in xen-asm_64.S Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/ia32/ia32entry.S | 8 ++++---- arch/x86/include/asm/pda.h | 4 +--- arch/x86/include/asm/thread_info.h | 20 ++++++++------------ arch/x86/kernel/asm-offsets_64.c | 1 - arch/x86/kernel/cpu/common.c | 6 ++++-- arch/x86/kernel/entry_64.S | 4 ++-- arch/x86/kernel/process_64.c | 4 ++-- arch/x86/kernel/smpboot.c | 3 +++ arch/x86/xen/xen-asm_64.S | 23 +++++++++++------------ 9 files changed, 35 insertions(+), 38 deletions(-) diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index 256b00b6189..9c79b247700 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -112,8 +112,8 @@ ENTRY(ia32_sysenter_target) CFI_DEF_CFA rsp,0 CFI_REGISTER rsp,rbp SWAPGS_UNSAFE_STACK - movq %gs:pda_kernelstack, %rsp - addq $(PDA_STACKOFFSET),%rsp + movq PER_CPU_VAR(kernel_stack), %rsp + addq $(KERNEL_STACK_OFFSET),%rsp /* * No need to follow this irqs on/off section: the syscall * disabled irqs, here we enable it straight after entry: @@ -273,13 +273,13 @@ ENDPROC(ia32_sysenter_target) ENTRY(ia32_cstar_target) CFI_STARTPROC32 simple CFI_SIGNAL_FRAME - CFI_DEF_CFA rsp,PDA_STACKOFFSET + CFI_DEF_CFA rsp,KERNEL_STACK_OFFSET CFI_REGISTER rip,rcx /*CFI_REGISTER rflags,r11*/ SWAPGS_UNSAFE_STACK movl %esp,%r8d CFI_REGISTER rsp,r8 - movq %gs:pda_kernelstack,%rsp + movq PER_CPU_VAR(kernel_stack),%rsp /* * No need to follow this irqs on/off section: the syscall * disabled irqs and here we enable it straight after entry: diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h index 7209302d922..4d28ffba6e1 100644 --- a/arch/x86/include/asm/pda.h +++ b/arch/x86/include/asm/pda.h @@ -13,7 +13,7 @@ struct x8664_pda { unsigned long unused1; unsigned long unused2; - unsigned long kernelstack; /* 16 top of kernel stack for current */ + unsigned long unused3; unsigned long oldrsp; /* 24 user rsp for system call */ int irqcount; /* 32 Irq nesting counter. Starts -1 */ unsigned int unused6; /* 36 was cpunumber */ @@ -44,6 +44,4 @@ extern void pda_init(int); #endif -#define PDA_STACKOFFSET (5*8) - #endif /* _ASM_X86_PDA_H */ diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index 98789647baa..b46f8ca007b 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h @@ -194,25 +194,21 @@ static inline struct thread_info *current_thread_info(void) #else /* X86_32 */ -#include +#include +#define KERNEL_STACK_OFFSET (5*8) /* * macros/functions for gaining access to the thread information structure * preempt_count needs to be 1 initially, until the scheduler is functional. */ #ifndef __ASSEMBLY__ -static inline struct thread_info *current_thread_info(void) -{ - struct thread_info *ti; - ti = (void *)(read_pda(kernelstack) + PDA_STACKOFFSET - THREAD_SIZE); - return ti; -} +DECLARE_PER_CPU(unsigned long, kernel_stack); -/* do not use in interrupt context */ -static inline struct thread_info *stack_thread_info(void) +static inline struct thread_info *current_thread_info(void) { struct thread_info *ti; - asm("andq %%rsp,%0; " : "=r" (ti) : "0" (~(THREAD_SIZE - 1))); + ti = (void *)(percpu_read(kernel_stack) + + KERNEL_STACK_OFFSET - THREAD_SIZE); return ti; } @@ -220,8 +216,8 @@ static inline struct thread_info *stack_thread_info(void) /* how to get the thread information struct from ASM */ #define GET_THREAD_INFO(reg) \ - movq %gs:pda_kernelstack,reg ; \ - subq $(THREAD_SIZE-PDA_STACKOFFSET),reg + movq PER_CPU_VAR(kernel_stack),reg ; \ + subq $(THREAD_SIZE-KERNEL_STACK_OFFSET),reg #endif diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index 4f7a210e1e5..cafff5f4a03 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c @@ -49,7 +49,6 @@ int main(void) BLANK(); #undef ENTRY #define ENTRY(entry) DEFINE(pda_ ## entry, offsetof(struct x8664_pda, entry)) - ENTRY(kernelstack); ENTRY(oldrsp); ENTRY(irqcount); DEFINE(pda_size, sizeof(struct x8664_pda)); diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index b50e38d1688..06b6290088f 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -889,6 +889,10 @@ DEFINE_PER_CPU(char *, irq_stack_ptr) = per_cpu_var(irq_stack) + IRQ_STACK_SIZE - 64; #endif +DEFINE_PER_CPU(unsigned long, kernel_stack) = + (unsigned long)&init_thread_union - KERNEL_STACK_OFFSET + THREAD_SIZE; +EXPORT_PER_CPU_SYMBOL(kernel_stack); + void __cpuinit pda_init(int cpu) { struct x8664_pda *pda = cpu_pda(cpu); @@ -900,8 +904,6 @@ void __cpuinit pda_init(int cpu) load_pda_offset(cpu); pda->irqcount = -1; - pda->kernelstack = (unsigned long)stack_thread_info() - - PDA_STACKOFFSET + THREAD_SIZE; if (cpu != 0) { if (pda->nodenumber == 0 && cpu_to_node(cpu) != NUMA_NO_NODE) diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index d22677a6643..0dd45859a7a 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -468,7 +468,7 @@ END(ret_from_fork) ENTRY(system_call) CFI_STARTPROC simple CFI_SIGNAL_FRAME - CFI_DEF_CFA rsp,PDA_STACKOFFSET + CFI_DEF_CFA rsp,KERNEL_STACK_OFFSET CFI_REGISTER rip,rcx /*CFI_REGISTER rflags,r11*/ SWAPGS_UNSAFE_STACK @@ -480,7 +480,7 @@ ENTRY(system_call) ENTRY(system_call_after_swapgs) movq %rsp,%gs:pda_oldrsp - movq %gs:pda_kernelstack,%rsp + movq PER_CPU_VAR(kernel_stack),%rsp /* * No need to follow this irqs off/on section - it's straight * and short: diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index e00c31a4b3c..6c5f5760210 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -620,9 +620,9 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) write_pda(oldrsp, next->usersp); percpu_write(current_task, next_p); - write_pda(kernelstack, + percpu_write(kernel_stack, (unsigned long)task_stack_page(next_p) + - THREAD_SIZE - PDA_STACKOFFSET); + THREAD_SIZE - KERNEL_STACK_OFFSET); #ifdef CONFIG_CC_STACKPROTECTOR write_pda(stack_canary, next_p->stack_canary); /* diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 5854be0fb80..869b98840fd 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -798,6 +798,9 @@ do_rest: #else clear_tsk_thread_flag(c_idle.idle, TIF_FORK); initial_gs = per_cpu_offset(cpu); + per_cpu(kernel_stack, cpu) = + (unsigned long)task_stack_page(c_idle.idle) - + KERNEL_STACK_OFFSET + THREAD_SIZE; #endif early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu); initial_code = (unsigned long)start_secondary; diff --git a/arch/x86/xen/xen-asm_64.S b/arch/x86/xen/xen-asm_64.S index 05794c566e8..5a23e899367 100644 --- a/arch/x86/xen/xen-asm_64.S +++ b/arch/x86/xen/xen-asm_64.S @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -28,12 +29,10 @@ #if 1 /* - x86-64 does not yet support direct access to percpu variables - via a segment override, so we just need to make sure this code - never gets used + FIXME: x86_64 now can support direct access to percpu variables + via a segment override. Update xen accordingly. */ #define BUG ud2a -#define PER_CPU_VAR(var, off) 0xdeadbeef #endif /* @@ -45,14 +44,14 @@ ENTRY(xen_irq_enable_direct) BUG /* Unmask events */ - movb $0, PER_CPU_VAR(xen_vcpu_info, XEN_vcpu_info_mask) + movb $0, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask /* Preempt here doesn't matter because that will deal with any pending interrupts. The pending check may end up being run on the wrong CPU, but that doesn't hurt. */ /* Test for pending */ - testb $0xff, PER_CPU_VAR(xen_vcpu_info, XEN_vcpu_info_pending) + testb $0xff, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_pending jz 1f 2: call check_events @@ -69,7 +68,7 @@ ENDPATCH(xen_irq_enable_direct) ENTRY(xen_irq_disable_direct) BUG - movb $1, PER_CPU_VAR(xen_vcpu_info, XEN_vcpu_info_mask) + movb $1, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask ENDPATCH(xen_irq_disable_direct) ret ENDPROC(xen_irq_disable_direct) @@ -87,7 +86,7 @@ ENDPATCH(xen_irq_disable_direct) ENTRY(xen_save_fl_direct) BUG - testb $0xff, PER_CPU_VAR(xen_vcpu_info, XEN_vcpu_info_mask) + testb $0xff, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask setz %ah addb %ah,%ah ENDPATCH(xen_save_fl_direct) @@ -107,13 +106,13 @@ ENTRY(xen_restore_fl_direct) BUG testb $X86_EFLAGS_IF>>8, %ah - setz PER_CPU_VAR(xen_vcpu_info, XEN_vcpu_info_mask) + setz PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask /* Preempt here doesn't matter because that will deal with any pending interrupts. The pending check may end up being run on the wrong CPU, but that doesn't hurt. */ /* check for unmasked and pending */ - cmpw $0x0001, PER_CPU_VAR(xen_vcpu_info, XEN_vcpu_info_pending) + cmpw $0x0001, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_pending jz 1f 2: call check_events 1: @@ -196,7 +195,7 @@ ENTRY(xen_sysret64) /* We're already on the usermode stack at this point, but still with the kernel gs, so we can easily switch back */ movq %rsp, %gs:pda_oldrsp - movq %gs:pda_kernelstack,%rsp + movq PER_CPU_VAR(kernel_stack),%rsp pushq $__USER_DS pushq %gs:pda_oldrsp @@ -213,7 +212,7 @@ ENTRY(xen_sysret32) /* We're already on the usermode stack at this point, but still with the kernel gs, so we can easily switch back */ movq %rsp, %gs:pda_oldrsp - movq %gs:pda_kernelstack, %rsp + movq PER_CPU_VAR(kernel_stack), %rsp pushq $__USER32_DS pushq %gs:pda_oldrsp -- GitLab From 3d1e42a7cf945e289d6ba26159aa0e2b0645401b Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Mon, 19 Jan 2009 00:38:58 +0900 Subject: [PATCH 0202/4982] x86-64: Move oldrsp from PDA to per-cpu. tj: * in asm-offsets_64.c, pda.h inclusion shouldn't be removed as pda is still referenced in the file * s/oldrsp/old_rsp/ Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/pda.h | 2 +- arch/x86/kernel/asm-offsets_64.c | 1 - arch/x86/kernel/entry_64.S | 10 +++++----- arch/x86/kernel/process_64.c | 8 +++++--- arch/x86/xen/xen-asm_64.S | 8 ++++---- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h index 4d28ffba6e1..ae23deb9955 100644 --- a/arch/x86/include/asm/pda.h +++ b/arch/x86/include/asm/pda.h @@ -14,7 +14,7 @@ struct x8664_pda { unsigned long unused1; unsigned long unused2; unsigned long unused3; - unsigned long oldrsp; /* 24 user rsp for system call */ + unsigned long unused4; int irqcount; /* 32 Irq nesting counter. Starts -1 */ unsigned int unused6; /* 36 was cpunumber */ #ifdef CONFIG_CC_STACKPROTECTOR diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index cafff5f4a03..afda6deb851 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c @@ -49,7 +49,6 @@ int main(void) BLANK(); #undef ENTRY #define ENTRY(entry) DEFINE(pda_ ## entry, offsetof(struct x8664_pda, entry)) - ENTRY(oldrsp); ENTRY(irqcount); DEFINE(pda_size, sizeof(struct x8664_pda)); BLANK(); diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 0dd45859a7a..7c27da407da 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -210,7 +210,7 @@ ENTRY(native_usergs_sysret64) /* %rsp:at FRAMEEND */ .macro FIXUP_TOP_OF_STACK tmp offset=0 - movq %gs:pda_oldrsp,\tmp + movq PER_CPU_VAR(old_rsp),\tmp movq \tmp,RSP+\offset(%rsp) movq $__USER_DS,SS+\offset(%rsp) movq $__USER_CS,CS+\offset(%rsp) @@ -221,7 +221,7 @@ ENTRY(native_usergs_sysret64) .macro RESTORE_TOP_OF_STACK tmp offset=0 movq RSP+\offset(%rsp),\tmp - movq \tmp,%gs:pda_oldrsp + movq \tmp,PER_CPU_VAR(old_rsp) movq EFLAGS+\offset(%rsp),\tmp movq \tmp,R11+\offset(%rsp) .endm @@ -479,7 +479,7 @@ ENTRY(system_call) */ ENTRY(system_call_after_swapgs) - movq %rsp,%gs:pda_oldrsp + movq %rsp,PER_CPU_VAR(old_rsp) movq PER_CPU_VAR(kernel_stack),%rsp /* * No need to follow this irqs off/on section - it's straight @@ -523,7 +523,7 @@ sysret_check: CFI_REGISTER rip,rcx RESTORE_ARGS 0,-ARG_SKIP,1 /*CFI_REGISTER rflags,r11*/ - movq %gs:pda_oldrsp, %rsp + movq PER_CPU_VAR(old_rsp), %rsp USERGS_SYSRET64 CFI_RESTORE_STATE @@ -833,7 +833,7 @@ common_interrupt: XCPT_FRAME addq $-0x80,(%rsp) /* Adjust vector to [-256,-1] range */ interrupt do_IRQ - /* 0(%rsp): oldrsp-ARGOFFSET */ + /* 0(%rsp): old_rsp-ARGOFFSET */ ret_from_intr: DISABLE_INTERRUPTS(CLBR_NONE) TRACE_IRQS_OFF diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 6c5f5760210..48012891892 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -60,6 +60,8 @@ asmlinkage extern void ret_from_fork(void); DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task; EXPORT_PER_CPU_SYMBOL(current_task); +DEFINE_PER_CPU(unsigned long, old_rsp); + unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED; static ATOMIC_NOTIFIER_HEAD(idle_notifier); @@ -395,7 +397,7 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) load_gs_index(0); regs->ip = new_ip; regs->sp = new_sp; - write_pda(oldrsp, new_sp); + percpu_write(old_rsp, new_sp); regs->cs = __USER_CS; regs->ss = __USER_DS; regs->flags = 0x200; @@ -616,8 +618,8 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) /* * Switch the PDA and FPU contexts. */ - prev->usersp = read_pda(oldrsp); - write_pda(oldrsp, next->usersp); + prev->usersp = percpu_read(old_rsp); + percpu_write(old_rsp, next->usersp); percpu_write(current_task, next_p); percpu_write(kernel_stack, diff --git a/arch/x86/xen/xen-asm_64.S b/arch/x86/xen/xen-asm_64.S index 5a23e899367..d6fc51f4ce8 100644 --- a/arch/x86/xen/xen-asm_64.S +++ b/arch/x86/xen/xen-asm_64.S @@ -194,11 +194,11 @@ RELOC(xen_sysexit, 1b+1) ENTRY(xen_sysret64) /* We're already on the usermode stack at this point, but still with the kernel gs, so we can easily switch back */ - movq %rsp, %gs:pda_oldrsp + movq %rsp, PER_CPU_VAR(old_rsp) movq PER_CPU_VAR(kernel_stack),%rsp pushq $__USER_DS - pushq %gs:pda_oldrsp + pushq PER_CPU_VAR(old_rsp) pushq %r11 pushq $__USER_CS pushq %rcx @@ -211,11 +211,11 @@ RELOC(xen_sysret64, 1b+1) ENTRY(xen_sysret32) /* We're already on the usermode stack at this point, but still with the kernel gs, so we can easily switch back */ - movq %rsp, %gs:pda_oldrsp + movq %rsp, PER_CPU_VAR(old_rsp) movq PER_CPU_VAR(kernel_stack), %rsp pushq $__USER32_DS - pushq %gs:pda_oldrsp + pushq PER_CPU_VAR(old_rsp) pushq %r11 pushq $__USER32_CS pushq %rcx -- GitLab From 5689553076c4a67b83426b076082c63085b7567a Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Mon, 19 Jan 2009 00:38:58 +0900 Subject: [PATCH 0203/4982] x86-64: Move irqcount from PDA to per-cpu. tj: s/irqcount/irq_count/ Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/pda.h | 2 +- arch/x86/kernel/asm-offsets_64.c | 1 - arch/x86/kernel/cpu/common.c | 4 ++-- arch/x86/kernel/entry_64.S | 14 +++++++------- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h index ae23deb9955..4527d70314d 100644 --- a/arch/x86/include/asm/pda.h +++ b/arch/x86/include/asm/pda.h @@ -15,7 +15,7 @@ struct x8664_pda { unsigned long unused2; unsigned long unused3; unsigned long unused4; - int irqcount; /* 32 Irq nesting counter. Starts -1 */ + int unused5; unsigned int unused6; /* 36 was cpunumber */ #ifdef CONFIG_CC_STACKPROTECTOR unsigned long stack_canary; /* 40 stack canary value */ diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index afda6deb851..64c834a39aa 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c @@ -49,7 +49,6 @@ int main(void) BLANK(); #undef ENTRY #define ENTRY(entry) DEFINE(pda_ ## entry, offsetof(struct x8664_pda, entry)) - ENTRY(irqcount); DEFINE(pda_size, sizeof(struct x8664_pda)); BLANK(); #undef ENTRY diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 06b6290088f..e2323ecce1d 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -893,6 +893,8 @@ DEFINE_PER_CPU(unsigned long, kernel_stack) = (unsigned long)&init_thread_union - KERNEL_STACK_OFFSET + THREAD_SIZE; EXPORT_PER_CPU_SYMBOL(kernel_stack); +DEFINE_PER_CPU(unsigned int, irq_count) = -1; + void __cpuinit pda_init(int cpu) { struct x8664_pda *pda = cpu_pda(cpu); @@ -903,8 +905,6 @@ void __cpuinit pda_init(int cpu) load_pda_offset(cpu); - pda->irqcount = -1; - if (cpu != 0) { if (pda->nodenumber == 0 && cpu_to_node(cpu) != NUMA_NO_NODE) pda->nodenumber = cpu_to_node(cpu); diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 7c27da407da..c52b6091916 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -337,12 +337,12 @@ ENTRY(save_args) je 1f SWAPGS /* - * irqcount is used to check if a CPU is already on an interrupt stack + * irq_count is used to check if a CPU is already on an interrupt stack * or not. While this is essentially redundant with preempt_count it is * a little cheaper to use a separate counter in the PDA (short of * moving irq_enter into assembly, which would be too much work) */ -1: incl %gs:pda_irqcount +1: incl PER_CPU_VAR(irq_count) jne 2f popq_cfi %rax /* move return address... */ mov PER_CPU_VAR(irq_stack_ptr),%rsp @@ -837,7 +837,7 @@ common_interrupt: ret_from_intr: DISABLE_INTERRUPTS(CLBR_NONE) TRACE_IRQS_OFF - decl %gs:pda_irqcount + decl PER_CPU_VAR(irq_count) leaveq CFI_DEF_CFA_REGISTER rsp CFI_ADJUST_CFA_OFFSET -8 @@ -1260,14 +1260,14 @@ ENTRY(call_softirq) CFI_REL_OFFSET rbp,0 mov %rsp,%rbp CFI_DEF_CFA_REGISTER rbp - incl %gs:pda_irqcount + incl PER_CPU_VAR(irq_count) cmove PER_CPU_VAR(irq_stack_ptr),%rsp push %rbp # backlink for old unwinder call __do_softirq leaveq CFI_DEF_CFA_REGISTER rsp CFI_ADJUST_CFA_OFFSET -8 - decl %gs:pda_irqcount + decl PER_CPU_VAR(irq_count) ret CFI_ENDPROC END(call_softirq) @@ -1297,7 +1297,7 @@ ENTRY(xen_do_hypervisor_callback) # do_hypervisor_callback(struct *pt_regs) movq %rdi, %rsp # we don't return, adjust the stack frame CFI_ENDPROC DEFAULT_FRAME -11: incl %gs:pda_irqcount +11: incl PER_CPU_VAR(irq_count) movq %rsp,%rbp CFI_DEF_CFA_REGISTER rbp cmovzq PER_CPU_VAR(irq_stack_ptr),%rsp @@ -1305,7 +1305,7 @@ ENTRY(xen_do_hypervisor_callback) # do_hypervisor_callback(struct *pt_regs) call xen_evtchn_do_upcall popq %rsp CFI_DEF_CFA_REGISTER rsp - decl %gs:pda_irqcount + decl PER_CPU_VAR(irq_count) jmp error_exit CFI_ENDPROC END(do_hypervisor_callback) -- GitLab From e7a22c1ebcc1caa8178df1819d05128bb5b45ab9 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Mon, 19 Jan 2009 00:38:59 +0900 Subject: [PATCH 0204/4982] x86-64: Move nodenumber from PDA to per-cpu. tj: * s/nodenumber/node_number/ * removed now unused pda variable from pda_init() Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/pda.h | 1 - arch/x86/include/asm/topology.h | 3 ++- arch/x86/kernel/cpu/common.c | 13 ++++++------- arch/x86/kernel/setup_percpu.c | 4 +++- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h index 4527d70314d..b30ef6bddc4 100644 --- a/arch/x86/include/asm/pda.h +++ b/arch/x86/include/asm/pda.h @@ -22,7 +22,6 @@ struct x8664_pda { /* gcc-ABI: this canary MUST be at offset 40!!! */ #endif - short nodenumber; /* number of current node (32k max) */ short in_bootmem; /* pda lives in bootmem */ short isidle; } ____cacheline_aligned_in_smp; diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h index 87ca3fd86e8..ffea1fe03a9 100644 --- a/arch/x86/include/asm/topology.h +++ b/arch/x86/include/asm/topology.h @@ -83,7 +83,8 @@ extern cpumask_t *node_to_cpumask_map; DECLARE_EARLY_PER_CPU(int, x86_cpu_to_node_map); /* Returns the number of the current Node. */ -#define numa_node_id() read_pda(nodenumber) +DECLARE_PER_CPU(int, node_number); +#define numa_node_id() percpu_read(node_number) #ifdef CONFIG_DEBUG_PER_CPU_MAPS extern int cpu_to_node(int cpu); diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index e2323ecce1d..7976a6a0f65 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -897,18 +897,11 @@ DEFINE_PER_CPU(unsigned int, irq_count) = -1; void __cpuinit pda_init(int cpu) { - struct x8664_pda *pda = cpu_pda(cpu); - /* Setup up data that may be needed in __get_free_pages early */ loadsegment(fs, 0); loadsegment(gs, 0); load_pda_offset(cpu); - - if (cpu != 0) { - if (pda->nodenumber == 0 && cpu_to_node(cpu) != NUMA_NO_NODE) - pda->nodenumber = cpu_to_node(cpu); - } } static DEFINE_PER_CPU_PAGE_ALIGNED(char, exception_stacks @@ -978,6 +971,12 @@ void __cpuinit cpu_init(void) if (cpu != 0) pda_init(cpu); +#ifdef CONFIG_NUMA + if (cpu != 0 && percpu_read(node_number) == 0 && + cpu_to_node(cpu) != NUMA_NO_NODE) + percpu_write(node_number, cpu_to_node(cpu)); +#endif + me = current; if (cpumask_test_and_set_cpu(cpu, cpu_initialized_mask)) diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 258497f93f4..efbafbbff58 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -53,6 +53,8 @@ EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid); #if defined(CONFIG_NUMA) && defined(CONFIG_X86_64) #define X86_64_NUMA 1 /* (used later) */ +DEFINE_PER_CPU(int, node_number) = 0; +EXPORT_PER_CPU_SYMBOL(node_number); /* * Map cpu index to node index @@ -283,7 +285,7 @@ void __cpuinit numa_set_node(int cpu, int node) per_cpu(x86_cpu_to_node_map, cpu) = node; if (node != NUMA_NO_NODE) - cpu_pda(cpu)->nodenumber = node; + per_cpu(node_number, cpu) = node; } void __cpuinit numa_clear_node(int cpu) -- GitLab From c2558e0eba66b49993e619da66c95a50a97830a3 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Mon, 19 Jan 2009 00:38:59 +0900 Subject: [PATCH 0205/4982] x86-64: Move isidle from PDA to per-cpu. tj: s/isidle/is_idle/ Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/pda.h | 1 - arch/x86/kernel/process_64.c | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h index b30ef6bddc4..c31ca048a90 100644 --- a/arch/x86/include/asm/pda.h +++ b/arch/x86/include/asm/pda.h @@ -23,7 +23,6 @@ struct x8664_pda { offset 40!!! */ #endif short in_bootmem; /* pda lives in bootmem */ - short isidle; } ____cacheline_aligned_in_smp; DECLARE_PER_CPU(struct x8664_pda, __pda); diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 48012891892..4523ff88a69 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -61,6 +61,7 @@ DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task; EXPORT_PER_CPU_SYMBOL(current_task); DEFINE_PER_CPU(unsigned long, old_rsp); +static DEFINE_PER_CPU(unsigned char, is_idle); unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED; @@ -80,13 +81,13 @@ EXPORT_SYMBOL_GPL(idle_notifier_unregister); void enter_idle(void) { - write_pda(isidle, 1); + percpu_write(is_idle, 1); atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL); } static void __exit_idle(void) { - if (test_and_clear_bit_pda(0, isidle) == 0) + if (x86_test_and_clear_bit_percpu(0, is_idle) == 0) return; atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL); } -- GitLab From 87b264065880fa696c121dad8498a60524e0f6de Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Mon, 19 Jan 2009 00:38:59 +0900 Subject: [PATCH 0206/4982] x86-64: Use absolute displacements for per-cpu accesses. Accessing memory through %gs should not use rip-relative addressing. Adding a P prefix for the argument tells gcc to not add (%rip) to the memory references. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/percpu.h | 26 +++++++++++++------------- arch/x86/include/asm/system.h | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index 03aa4b00a1c..165d5272ece 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h @@ -39,10 +39,10 @@ #include #ifdef CONFIG_SMP -#define __percpu_seg_str "%%"__stringify(__percpu_seg)":" +#define __percpu_arg(x) "%%"__stringify(__percpu_seg)":%P" #x #define __my_cpu_offset percpu_read(this_cpu_off) #else -#define __percpu_seg_str +#define __percpu_arg(x) "%" #x #endif /* For arch-specific code, we can use direct single-insn ops (they @@ -58,22 +58,22 @@ do { \ } \ switch (sizeof(var)) { \ case 1: \ - asm(op "b %1,"__percpu_seg_str"%0" \ + asm(op "b %1,"__percpu_arg(0) \ : "+m" (var) \ : "ri" ((T__)val)); \ break; \ case 2: \ - asm(op "w %1,"__percpu_seg_str"%0" \ + asm(op "w %1,"__percpu_arg(0) \ : "+m" (var) \ : "ri" ((T__)val)); \ break; \ case 4: \ - asm(op "l %1,"__percpu_seg_str"%0" \ + asm(op "l %1,"__percpu_arg(0) \ : "+m" (var) \ : "ri" ((T__)val)); \ break; \ case 8: \ - asm(op "q %1,"__percpu_seg_str"%0" \ + asm(op "q %1,"__percpu_arg(0) \ : "+m" (var) \ : "r" ((T__)val)); \ break; \ @@ -86,22 +86,22 @@ do { \ typeof(var) ret__; \ switch (sizeof(var)) { \ case 1: \ - asm(op "b "__percpu_seg_str"%1,%0" \ + asm(op "b "__percpu_arg(1)",%0" \ : "=r" (ret__) \ : "m" (var)); \ break; \ case 2: \ - asm(op "w "__percpu_seg_str"%1,%0" \ + asm(op "w "__percpu_arg(1)",%0" \ : "=r" (ret__) \ : "m" (var)); \ break; \ case 4: \ - asm(op "l "__percpu_seg_str"%1,%0" \ + asm(op "l "__percpu_arg(1)",%0" \ : "=r" (ret__) \ : "m" (var)); \ break; \ case 8: \ - asm(op "q "__percpu_seg_str"%1,%0" \ + asm(op "q "__percpu_arg(1)",%0" \ : "=r" (ret__) \ : "m" (var)); \ break; \ @@ -122,9 +122,9 @@ do { \ #define x86_test_and_clear_bit_percpu(bit, var) \ ({ \ int old__; \ - asm volatile("btr %1,"__percpu_seg_str"%c2\n\tsbbl %0,%0" \ - : "=r" (old__) \ - : "dIr" (bit), "i" (&per_cpu__##var) : "memory"); \ + asm volatile("btr %2,"__percpu_arg(1)"\n\tsbbl %0,%0" \ + : "=r" (old__), "+m" (per_cpu__##var) \ + : "dIr" (bit)); \ old__; \ }) diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h index 4399aac680e..d1dc27dba36 100644 --- a/arch/x86/include/asm/system.h +++ b/arch/x86/include/asm/system.h @@ -94,7 +94,7 @@ do { \ "call __switch_to\n\t" \ ".globl thread_return\n" \ "thread_return:\n\t" \ - "movq "__percpu_seg_str"%P[current_task],%%rsi\n\t" \ + "movq "__percpu_arg([current_task])",%%rsi\n\t" \ "movq %P[thread_info](%%rsi),%%r8\n\t" \ LOCK_PREFIX "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" \ "movq %%rax,%%rdi\n\t" \ -- GitLab From 8693290b9038f32b6b9bafd97b7e18465d62655b Mon Sep 17 00:00:00 2001 From: Andreas Bergmeier Date: Sun, 18 Jan 2009 18:48:03 +0100 Subject: [PATCH 0207/4982] ALSA: usb-audio - Quirk for Serato phono Ignore errors (wrong usb interface data) found when using the serato scratch live box with alsa Thus the alsa controls can be accessed (beware: they don't work though - but at least it's one ugly error message less) Signed-off-by: Andreas Bergmeier Signed-off-by: Takashi Iwai --- sound/usb/usbmixer_maps.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/sound/usb/usbmixer_maps.c b/sound/usb/usbmixer_maps.c index f41214f3ad6..3e5d66cf1f5 100644 --- a/sound/usb/usbmixer_maps.c +++ b/sound/usb/usbmixer_maps.c @@ -261,6 +261,22 @@ static struct usbmix_name_map aureon_51_2_map[] = { {} /* terminator */ }; +static struct usbmix_name_map scratch_live_map[] = { + /* 1: IT Line 1 (USB streaming) */ + /* 2: OT Line 1 (Speaker) */ + /* 3: IT Line 1 (Line connector) */ + { 4, "Line 1 In" }, /* FU */ + /* 5: OT Line 1 (USB streaming) */ + /* 6: IT Line 2 (USB streaming) */ + /* 7: OT Line 2 (Speaker) */ + /* 8: IT Line 2 (Line connector) */ + { 9, "Line 2 In" }, /* FU */ + /* 10: OT Line 2 (USB streaming) */ + /* 11: IT Mic (Line connector) */ + /* 12: OT Mic (USB streaming) */ + { 0 } /* terminator */ +}; + /* * Control map entries */ @@ -316,6 +332,11 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { .id = USB_ID(0x0ccd, 0x0028), .map = aureon_51_2_map, }, + { + .id = USB_ID(0x13e5, 0x0001), + .map = scratch_live_map, + .ignore_ctl_error = 1, + }, { 0 } /* terminator */ }; -- GitLab From 5662a2f8e7313f78d6b17ab383f3e4f04971c335 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 18 Jan 2009 19:37:21 +0100 Subject: [PATCH 0208/4982] x86, rdc321x: remove/move leftover files Impact: cleanup Move/remove leftover RDC321 files. Now that it's not a subarch anymore, arch/x86/mach-rdc321x and arch/x86/include/asm/mach-rdc321x/ are not needed. One include file was still in use: rdc321x_defs.h, move that to the generic x86 asm header directory. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/mach-rdc321x/gpio.h | 60 ------ .../asm/{mach-rdc321x => }/rdc321x_defs.h | 0 arch/x86/mach-rdc321x/Makefile | 5 - arch/x86/mach-rdc321x/gpio.c | 194 ------------------ arch/x86/mach-rdc321x/platform.c | 69 ------- drivers/watchdog/rdc321x_wdt.c | 2 +- 6 files changed, 1 insertion(+), 329 deletions(-) delete mode 100644 arch/x86/include/asm/mach-rdc321x/gpio.h rename arch/x86/include/asm/{mach-rdc321x => }/rdc321x_defs.h (100%) delete mode 100644 arch/x86/mach-rdc321x/Makefile delete mode 100644 arch/x86/mach-rdc321x/gpio.c delete mode 100644 arch/x86/mach-rdc321x/platform.c diff --git a/arch/x86/include/asm/mach-rdc321x/gpio.h b/arch/x86/include/asm/mach-rdc321x/gpio.h deleted file mode 100644 index c210ab5788b..00000000000 --- a/arch/x86/include/asm/mach-rdc321x/gpio.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef _ASM_X86_MACH_RDC321X_GPIO_H -#define _ASM_X86_MACH_RDC321X_GPIO_H - -#include - -extern int rdc_gpio_get_value(unsigned gpio); -extern void rdc_gpio_set_value(unsigned gpio, int value); -extern int rdc_gpio_direction_input(unsigned gpio); -extern int rdc_gpio_direction_output(unsigned gpio, int value); -extern int rdc_gpio_request(unsigned gpio, const char *label); -extern void rdc_gpio_free(unsigned gpio); -extern void __init rdc321x_gpio_setup(void); - -/* Wrappers for the arch-neutral GPIO API */ - -static inline int gpio_request(unsigned gpio, const char *label) -{ - return rdc_gpio_request(gpio, label); -} - -static inline void gpio_free(unsigned gpio) -{ - might_sleep(); - rdc_gpio_free(gpio); -} - -static inline int gpio_direction_input(unsigned gpio) -{ - return rdc_gpio_direction_input(gpio); -} - -static inline int gpio_direction_output(unsigned gpio, int value) -{ - return rdc_gpio_direction_output(gpio, value); -} - -static inline int gpio_get_value(unsigned gpio) -{ - return rdc_gpio_get_value(gpio); -} - -static inline void gpio_set_value(unsigned gpio, int value) -{ - rdc_gpio_set_value(gpio, value); -} - -static inline int gpio_to_irq(unsigned gpio) -{ - return gpio; -} - -static inline int irq_to_gpio(unsigned irq) -{ - return irq; -} - -/* For cansleep */ -#include - -#endif /* _ASM_X86_MACH_RDC321X_GPIO_H */ diff --git a/arch/x86/include/asm/mach-rdc321x/rdc321x_defs.h b/arch/x86/include/asm/rdc321x_defs.h similarity index 100% rename from arch/x86/include/asm/mach-rdc321x/rdc321x_defs.h rename to arch/x86/include/asm/rdc321x_defs.h diff --git a/arch/x86/mach-rdc321x/Makefile b/arch/x86/mach-rdc321x/Makefile deleted file mode 100644 index 8325b4ca431..00000000000 --- a/arch/x86/mach-rdc321x/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for the RDC321x specific parts of the kernel -# -obj-$(CONFIG_X86_RDC321X) := gpio.o platform.o - diff --git a/arch/x86/mach-rdc321x/gpio.c b/arch/x86/mach-rdc321x/gpio.c deleted file mode 100644 index 247f33d3a40..00000000000 --- a/arch/x86/mach-rdc321x/gpio.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * GPIO support for RDC SoC R3210/R8610 - * - * Copyright (C) 2007, Florian Fainelli - * Copyright (C) 2008, Volker Weiss - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - -#include -#include -#include -#include - -#include -#include - - -/* spin lock to protect our private copy of GPIO data register plus - the access to PCI conf registers. */ -static DEFINE_SPINLOCK(gpio_lock); - -/* copy of GPIO data registers */ -static u32 gpio_data_reg1; -static u32 gpio_data_reg2; - -static u32 gpio_request_data[2]; - - -static inline void rdc321x_conf_write(unsigned addr, u32 value) -{ - outl((1 << 31) | (7 << 11) | addr, RDC3210_CFGREG_ADDR); - outl(value, RDC3210_CFGREG_DATA); -} - -static inline void rdc321x_conf_or(unsigned addr, u32 value) -{ - outl((1 << 31) | (7 << 11) | addr, RDC3210_CFGREG_ADDR); - value |= inl(RDC3210_CFGREG_DATA); - outl(value, RDC3210_CFGREG_DATA); -} - -static inline u32 rdc321x_conf_read(unsigned addr) -{ - outl((1 << 31) | (7 << 11) | addr, RDC3210_CFGREG_ADDR); - - return inl(RDC3210_CFGREG_DATA); -} - -/* configure pin as GPIO */ -static void rdc321x_configure_gpio(unsigned gpio) -{ - unsigned long flags; - - spin_lock_irqsave(&gpio_lock, flags); - rdc321x_conf_or(gpio < 32 - ? RDC321X_GPIO_CTRL_REG1 : RDC321X_GPIO_CTRL_REG2, - 1 << (gpio & 0x1f)); - spin_unlock_irqrestore(&gpio_lock, flags); -} - -/* initially setup the 2 copies of the gpio data registers. - This function must be called by the platform setup code. */ -void __init rdc321x_gpio_setup() -{ - /* this might not be, what others (BIOS, bootloader, etc.) - wrote to these registers before, but it's a good guess. Still - better than just using 0xffffffff. */ - - gpio_data_reg1 = rdc321x_conf_read(RDC321X_GPIO_DATA_REG1); - gpio_data_reg2 = rdc321x_conf_read(RDC321X_GPIO_DATA_REG2); -} - -/* determine, if gpio number is valid */ -static inline int rdc321x_is_gpio(unsigned gpio) -{ - return gpio <= RDC321X_MAX_GPIO; -} - -/* request GPIO */ -int rdc_gpio_request(unsigned gpio, const char *label) -{ - unsigned long flags; - - if (!rdc321x_is_gpio(gpio)) - return -EINVAL; - - spin_lock_irqsave(&gpio_lock, flags); - if (gpio_request_data[(gpio & 0x20) ? 1 : 0] & (1 << (gpio & 0x1f))) - goto inuse; - gpio_request_data[(gpio & 0x20) ? 1 : 0] |= (1 << (gpio & 0x1f)); - spin_unlock_irqrestore(&gpio_lock, flags); - - return 0; -inuse: - spin_unlock_irqrestore(&gpio_lock, flags); - return -EINVAL; -} -EXPORT_SYMBOL(rdc_gpio_request); - -/* release previously-claimed GPIO */ -void rdc_gpio_free(unsigned gpio) -{ - unsigned long flags; - - if (!rdc321x_is_gpio(gpio)) - return; - - spin_lock_irqsave(&gpio_lock, flags); - gpio_request_data[(gpio & 0x20) ? 1 : 0] &= ~(1 << (gpio & 0x1f)); - spin_unlock_irqrestore(&gpio_lock, flags); -} -EXPORT_SYMBOL(rdc_gpio_free); - -/* read GPIO pin */ -int rdc_gpio_get_value(unsigned gpio) -{ - u32 reg; - unsigned long flags; - - spin_lock_irqsave(&gpio_lock, flags); - reg = rdc321x_conf_read(gpio < 32 - ? RDC321X_GPIO_DATA_REG1 : RDC321X_GPIO_DATA_REG2); - spin_unlock_irqrestore(&gpio_lock, flags); - - return (1 << (gpio & 0x1f)) & reg ? 1 : 0; -} -EXPORT_SYMBOL(rdc_gpio_get_value); - -/* set GPIO pin to value */ -void rdc_gpio_set_value(unsigned gpio, int value) -{ - unsigned long flags; - u32 reg; - - reg = 1 << (gpio & 0x1f); - if (gpio < 32) { - spin_lock_irqsave(&gpio_lock, flags); - if (value) - gpio_data_reg1 |= reg; - else - gpio_data_reg1 &= ~reg; - rdc321x_conf_write(RDC321X_GPIO_DATA_REG1, gpio_data_reg1); - spin_unlock_irqrestore(&gpio_lock, flags); - } else { - spin_lock_irqsave(&gpio_lock, flags); - if (value) - gpio_data_reg2 |= reg; - else - gpio_data_reg2 &= ~reg; - rdc321x_conf_write(RDC321X_GPIO_DATA_REG2, gpio_data_reg2); - spin_unlock_irqrestore(&gpio_lock, flags); - } -} -EXPORT_SYMBOL(rdc_gpio_set_value); - -/* configure GPIO pin as input */ -int rdc_gpio_direction_input(unsigned gpio) -{ - if (!rdc321x_is_gpio(gpio)) - return -EINVAL; - - rdc321x_configure_gpio(gpio); - - return 0; -} -EXPORT_SYMBOL(rdc_gpio_direction_input); - -/* configure GPIO pin as output and set value */ -int rdc_gpio_direction_output(unsigned gpio, int value) -{ - if (!rdc321x_is_gpio(gpio)) - return -EINVAL; - - gpio_set_value(gpio, value); - rdc321x_configure_gpio(gpio); - - return 0; -} -EXPORT_SYMBOL(rdc_gpio_direction_output); diff --git a/arch/x86/mach-rdc321x/platform.c b/arch/x86/mach-rdc321x/platform.c deleted file mode 100644 index 4f4e50c3ad3..00000000000 --- a/arch/x86/mach-rdc321x/platform.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Generic RDC321x platform devices - * - * Copyright (C) 2007 Florian Fainelli - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#include -#include -#include -#include -#include -#include - -#include - -/* LEDS */ -static struct gpio_led default_leds[] = { - { .name = "rdc:dmz", .gpio = 1, }, -}; - -static struct gpio_led_platform_data rdc321x_led_data = { - .num_leds = ARRAY_SIZE(default_leds), - .leds = default_leds, -}; - -static struct platform_device rdc321x_leds = { - .name = "leds-gpio", - .id = -1, - .dev = { - .platform_data = &rdc321x_led_data, - } -}; - -/* Watchdog */ -static struct platform_device rdc321x_wdt = { - .name = "rdc321x-wdt", - .id = -1, - .num_resources = 0, -}; - -static struct platform_device *rdc321x_devs[] = { - &rdc321x_leds, - &rdc321x_wdt -}; - -static int __init rdc_board_setup(void) -{ - rdc321x_gpio_setup(); - - return platform_add_devices(rdc321x_devs, ARRAY_SIZE(rdc321x_devs)); -} - -arch_initcall(rdc_board_setup); diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c index bf92802f2bb..36e221beedc 100644 --- a/drivers/watchdog/rdc321x_wdt.c +++ b/drivers/watchdog/rdc321x_wdt.c @@ -37,7 +37,7 @@ #include #include -#include +#include #define RDC_WDT_MASK 0x80000000 /* Mask */ #define RDC_WDT_EN 0x00800000 /* Enable bit */ -- GitLab From 0d90a7ec48c704025307b129413bc62451b20ab3 Mon Sep 17 00:00:00 2001 From: "David P. Quigley" Date: Fri, 16 Jan 2009 09:22:02 -0500 Subject: [PATCH 0209/4982] SELinux: Condense super block security structure flags and cleanup necessary code. The super block security structure currently has three fields for what are essentially flags. The flags field is used for mount options while two other char fields are used for initialization and proc flags. These latter two fields are essentially bit fields since the only used values are 0 and 1. These fields have been collapsed into the flags field and new bit masks have been added for them. The code is also fixed to work with these new flags. Signed-off-by: David P. Quigley Acked-by: Eric Paris Signed-off-by: James Morris --- security/selinux/hooks.c | 38 ++++++++++++++--------------- security/selinux/include/objsec.h | 2 -- security/selinux/include/security.h | 6 +++++ 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 00815973d41..473adc5f4f9 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -431,7 +431,7 @@ static int sb_finish_set_opts(struct super_block *sb) } } - sbsec->initialized = 1; + sbsec->flags |= SE_SBINITIALIZED; if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n", @@ -487,17 +487,13 @@ static int selinux_get_mnt_opts(const struct super_block *sb, security_init_mnt_opts(opts); - if (!sbsec->initialized) + if (!(sbsec->flags & SE_SBINITIALIZED)) return -EINVAL; if (!ss_initialized) return -EINVAL; - /* - * if we ever use sbsec flags for anything other than tracking mount - * settings this is going to need a mask - */ - tmp = sbsec->flags; + tmp = sbsec->flags & SE_MNTMASK; /* count the number of mount options for this sb */ for (i = 0; i < 8; i++) { if (tmp & 0x01) @@ -562,8 +558,10 @@ out_free: static int bad_option(struct superblock_security_struct *sbsec, char flag, u32 old_sid, u32 new_sid) { + char mnt_flags = sbsec->flags & SE_MNTMASK; + /* check if the old mount command had the same options */ - if (sbsec->initialized) + if (sbsec->flags & SE_SBINITIALIZED) if (!(sbsec->flags & flag) || (old_sid != new_sid)) return 1; @@ -571,8 +569,8 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag, /* check if we were passed the same options twice, * aka someone passed context=a,context=b */ - if (!sbsec->initialized) - if (sbsec->flags & flag) + if (!(sbsec->flags & SE_SBINITIALIZED)) + if (mnt_flags & flag) return 1; return 0; } @@ -626,7 +624,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, * this sb does not set any security options. (The first options * will be used for both mounts) */ - if (sbsec->initialized && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) + if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) && (num_opts == 0)) goto out; @@ -690,19 +688,19 @@ static int selinux_set_mnt_opts(struct super_block *sb, } } - if (sbsec->initialized) { + if (sbsec->flags & SE_SBINITIALIZED) { /* previously mounted with options, but not on this attempt? */ - if (sbsec->flags && !num_opts) + if ((sbsec->flags & SE_MNTMASK) && !num_opts) goto out_double_mount; rc = 0; goto out; } if (strcmp(sb->s_type->name, "proc") == 0) - sbsec->proc = 1; + sbsec->flags |= SE_SBPROC; /* Determine the labeling behavior to use for this filesystem type. */ - rc = security_fs_use(sbsec->proc ? "proc" : sb->s_type->name, &sbsec->behavior, &sbsec->sid); + rc = security_fs_use((sbsec->flags & SE_SBPROC) ? "proc" : sb->s_type->name, &sbsec->behavior, &sbsec->sid); if (rc) { printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n", __func__, sb->s_type->name, rc); @@ -806,10 +804,10 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb, } /* how can we clone if the old one wasn't set up?? */ - BUG_ON(!oldsbsec->initialized); + BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); /* if fs is reusing a sb, just let its options stand... */ - if (newsbsec->initialized) + if (newsbsec->flags & SE_SBINITIALIZED) return; mutex_lock(&newsbsec->lock); @@ -1209,7 +1207,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent goto out_unlock; sbsec = inode->i_sb->s_security; - if (!sbsec->initialized) { + if (!(sbsec->flags & SE_SBINITIALIZED)) { /* Defer initialization until selinux_complete_init, after the initial policy is loaded and the security server is ready to handle calls. */ @@ -1326,7 +1324,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent /* Default to the fs superblock SID. */ isec->sid = sbsec->sid; - if (sbsec->proc && !S_ISLNK(inode->i_mode)) { + if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) { struct proc_inode *proci = PROC_I(inode); if (proci->pde) { isec->sclass = inode_mode_to_security_class(inode->i_mode); @@ -2585,7 +2583,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, } /* Possibly defer initialization to selinux_complete_init. */ - if (sbsec->initialized) { + if (sbsec->flags & SE_SBINITIALIZED) { struct inode_security_struct *isec = inode->i_security; isec->sclass = inode_mode_to_security_class(inode->i_mode); isec->sid = newsid; diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 3cc45168f67..c4e062336ef 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -60,9 +60,7 @@ struct superblock_security_struct { u32 def_sid; /* default SID for labeling */ u32 mntpoint_sid; /* SECURITY_FS_USE_MNTPOINT context for files */ unsigned int behavior; /* labeling behavior */ - unsigned char initialized; /* initialization flag */ unsigned char flags; /* which mount options were specified */ - unsigned char proc; /* proc fs */ struct mutex lock; struct list_head isec_head; spinlock_t isec_lock; diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 72447370bc9..ff4e19ccd8f 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -37,10 +37,16 @@ #define POLICYDB_VERSION_MAX POLICYDB_VERSION_BOUNDARY #endif +/* Mask for just the mount related flags */ +#define SE_MNTMASK 0x0f +/* Super block security struct flags for mount options */ #define CONTEXT_MNT 0x01 #define FSCONTEXT_MNT 0x02 #define ROOTCONTEXT_MNT 0x04 #define DEFCONTEXT_MNT 0x08 +/* Non-mount related flags */ +#define SE_SBINITIALIZED 0x10 +#define SE_SBPROC 0x20 #define CONTEXT_STR "context=" #define FSCONTEXT_STR "fscontext=" -- GitLab From 11689d47f0957121920c9ec646eb5d838755853a Mon Sep 17 00:00:00 2001 From: "David P. Quigley" Date: Fri, 16 Jan 2009 09:22:03 -0500 Subject: [PATCH 0210/4982] SELinux: Add new security mount option to indicate security label support. There is no easy way to tell if a file system supports SELinux security labeling. Because of this a new flag is being added to the super block security structure to indicate that the particular super block supports labeling. This flag is set for file systems using the xattr, task, and transition labeling methods unless that behavior is overridden by context mounts. Signed-off-by: David P. Quigley Acked-by: Eric Paris Signed-off-by: James Morris --- security/selinux/hooks.c | 39 +++++++++++++++++++++++++---- security/selinux/include/security.h | 2 ++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 473adc5f4f9..1a9768a8b64 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -89,7 +89,7 @@ #define XATTR_SELINUX_SUFFIX "selinux" #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX -#define NUM_SEL_MNT_OPTS 4 +#define NUM_SEL_MNT_OPTS 5 extern unsigned int policydb_loaded_version; extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); @@ -353,6 +353,7 @@ enum { Opt_fscontext = 2, Opt_defcontext = 3, Opt_rootcontext = 4, + Opt_labelsupport = 5, }; static const match_table_t tokens = { @@ -360,6 +361,7 @@ static const match_table_t tokens = { {Opt_fscontext, FSCONTEXT_STR "%s"}, {Opt_defcontext, DEFCONTEXT_STR "%s"}, {Opt_rootcontext, ROOTCONTEXT_STR "%s"}, + {Opt_labelsupport, LABELSUPP_STR}, {Opt_error, NULL}, }; @@ -431,7 +433,7 @@ static int sb_finish_set_opts(struct super_block *sb) } } - sbsec->flags |= SE_SBINITIALIZED; + sbsec->flags |= (SE_SBINITIALIZED | SE_SBLABELSUPP); if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n", @@ -441,6 +443,12 @@ static int sb_finish_set_opts(struct super_block *sb) sb->s_id, sb->s_type->name, labeling_behaviors[sbsec->behavior-1]); + if (sbsec->behavior == SECURITY_FS_USE_GENFS || + sbsec->behavior == SECURITY_FS_USE_MNTPOINT || + sbsec->behavior == SECURITY_FS_USE_NONE || + sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) + sbsec->flags &= ~SE_SBLABELSUPP; + /* Initialize the root inode. */ rc = inode_doinit_with_dentry(root_inode, root); @@ -500,6 +508,9 @@ static int selinux_get_mnt_opts(const struct super_block *sb, opts->num_mnt_opts++; tmp >>= 1; } + /* Check if the Label support flag is set */ + if (sbsec->flags & SE_SBLABELSUPP) + opts->num_mnt_opts++; opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC); if (!opts->mnt_opts) { @@ -545,6 +556,10 @@ static int selinux_get_mnt_opts(const struct super_block *sb, opts->mnt_opts[i] = context; opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT; } + if (sbsec->flags & SE_SBLABELSUPP) { + opts->mnt_opts[i] = NULL; + opts->mnt_opts_flags[i++] = SE_SBLABELSUPP; + } BUG_ON(i != opts->num_mnt_opts); @@ -635,6 +650,9 @@ static int selinux_set_mnt_opts(struct super_block *sb, */ for (i = 0; i < num_opts; i++) { u32 sid; + + if (flags[i] == SE_SBLABELSUPP) + continue; rc = security_context_to_sid(mount_options[i], strlen(mount_options[i]), &sid); if (rc) { @@ -915,7 +933,8 @@ static int selinux_parse_opts_str(char *options, goto out_err; } break; - + case Opt_labelsupport: + break; default: rc = -EINVAL; printk(KERN_WARNING "SELinux: unknown mount option\n"); @@ -997,7 +1016,12 @@ static void selinux_write_opts(struct seq_file *m, char *prefix; for (i = 0; i < opts->num_mnt_opts; i++) { - char *has_comma = strchr(opts->mnt_opts[i], ','); + char *has_comma; + + if (opts->mnt_opts[i]) + has_comma = strchr(opts->mnt_opts[i], ','); + else + has_comma = NULL; switch (opts->mnt_opts_flags[i]) { case CONTEXT_MNT: @@ -1012,6 +1036,10 @@ static void selinux_write_opts(struct seq_file *m, case DEFCONTEXT_MNT: prefix = DEFCONTEXT_STR; break; + case SE_SBLABELSUPP: + seq_putc(m, ','); + seq_puts(m, LABELSUPP_STR); + continue; default: BUG(); }; @@ -2398,7 +2426,8 @@ static inline int selinux_option(char *option, int len) return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) || match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) || match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) || - match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len)); + match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) || + match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len)); } static inline void take_option(char **to, char *from, int *first, int len) diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index ff4e19ccd8f..e1d9db77998 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -47,11 +47,13 @@ /* Non-mount related flags */ #define SE_SBINITIALIZED 0x10 #define SE_SBPROC 0x20 +#define SE_SBLABELSUPP 0x40 #define CONTEXT_STR "context=" #define FSCONTEXT_STR "fscontext=" #define ROOTCONTEXT_STR "rootcontext=" #define DEFCONTEXT_STR "defcontext=" +#define LABELSUPP_STR "seclabel" struct netlbl_lsm_secattr; -- GitLab From cd89596f0ccfa3ccb8a81ce47782231cf7ea7296 Mon Sep 17 00:00:00 2001 From: "David P. Quigley" Date: Fri, 16 Jan 2009 09:22:04 -0500 Subject: [PATCH 0211/4982] SELinux: Unify context mount and genfs behavior Context mounts and genfs labeled file systems behave differently with respect to setting file system labels. This patch brings genfs labeled file systems in line with context mounts in that setxattr calls to them should return EOPNOTSUPP and fscreate calls will be ignored. Signed-off-by: David P. Quigley Acked-by: Eric Paris Signed-off-by: James Morris --- security/selinux/hooks.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 1a9768a8b64..3bb4942e39c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1613,7 +1613,7 @@ static int may_create(struct inode *dir, if (rc) return rc; - if (!newsid || sbsec->behavior == SECURITY_FS_USE_MNTPOINT) { + if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { rc = security_transition_sid(sid, dsec->sid, tclass, &newsid); if (rc) return rc; @@ -2597,7 +2597,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, sid = tsec->sid; newsid = tsec->create_sid; - if (!newsid || sbsec->behavior == SECURITY_FS_USE_MNTPOINT) { + if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { rc = security_transition_sid(sid, dsec->sid, inode_mode_to_security_class(inode->i_mode), &newsid); @@ -2619,7 +2619,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, isec->initialized = 1; } - if (!ss_initialized || sbsec->behavior == SECURITY_FS_USE_MNTPOINT) + if (!ss_initialized || !(sbsec->flags & SE_SBLABELSUPP)) return -EOPNOTSUPP; if (name) { @@ -2796,7 +2796,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, return selinux_inode_setotherxattr(dentry, name); sbsec = inode->i_sb->s_security; - if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT) + if (!(sbsec->flags & SE_SBLABELSUPP)) return -EOPNOTSUPP; if (!is_owner_or_cap(inode)) -- GitLab From 422e79a8b39d9ac73e410dc3cd099aecea82afd2 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Mon, 19 Jan 2009 17:06:42 +1100 Subject: [PATCH 0212/4982] x86: Remove never-called arch_setup_msi_irq() Since commit 75c46fa, "x64, x2apic/intr-remap: MSI and MSI-X support for interrupt remapping infrastructure", x86 has had an implementation of arch_setup_msi_irqs(). That implementation does not call arch_setup_msi_irq(), instead it calls setup_irq(). No other x86 code calls arch_setup_msi_irq(). That leaves only arch_setup_msi_irqs() in drivers/pci/msi.c, but that routine is overridden by the x86 version of arch_setup_msi_irqs(). So arch_setup_msi_irq() is dead code, remove it. Signed-off-by: Michael Ellerman Signed-off-by: H. Peter Anvin --- arch/x86/kernel/io_apic.c | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 79b8c0c72d3..157aafa4558 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -3462,40 +3462,6 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq) return 0; } -int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc) -{ - unsigned int irq; - int ret; - unsigned int irq_want; - - irq_want = nr_irqs_gsi; - irq = create_irq_nr(irq_want); - if (irq == 0) - return -1; - -#ifdef CONFIG_INTR_REMAP - if (!intr_remapping_enabled) - goto no_ir; - - ret = msi_alloc_irte(dev, irq, 1); - if (ret < 0) - goto error; -no_ir: -#endif - ret = setup_msi_irq(dev, msidesc, irq); - if (ret < 0) { - destroy_irq(irq); - return ret; - } - return 0; - -#ifdef CONFIG_INTR_REMAP -error: - destroy_irq(irq); - return ret; -#endif -} - int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) { unsigned int irq; -- GitLab From 6e9ed0cc4b963fde66ab47d9fb19147631e44555 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Am=C3=A9rico=20Wang?= Date: Mon, 19 Jan 2009 02:00:38 +0800 Subject: [PATCH 0213/4982] slob: clean up the code - Use NULL instead of plain 0; - Rename slob_page() to is_slob_page(); - Define slob_page() to convert void* to struct slob_page*; - Rename slob_new_page() to slob_new_pages(); - Define slob_free_pages() accordingly. Compile tests only. Signed-off-by: WANG Cong Signed-off-by: Matt Mackall Cc: Christoph Lameter Signed-off-by: Pekka Enberg --- mm/slob.c | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/mm/slob.c b/mm/slob.c index bf7e8fc3aed..c9cd31d27e6 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -126,9 +126,9 @@ static LIST_HEAD(free_slob_medium); static LIST_HEAD(free_slob_large); /* - * slob_page: True for all slob pages (false for bigblock pages) + * is_slob_page: True for all slob pages (false for bigblock pages) */ -static inline int slob_page(struct slob_page *sp) +static inline int is_slob_page(struct slob_page *sp) { return PageSlobPage((struct page *)sp); } @@ -143,6 +143,11 @@ static inline void clear_slob_page(struct slob_page *sp) __ClearPageSlobPage((struct page *)sp); } +static inline struct slob_page *slob_page(const void *addr) +{ + return (struct slob_page *)virt_to_page(addr); +} + /* * slob_page_free: true for pages on free_slob_pages list. */ @@ -230,7 +235,7 @@ static int slob_last(slob_t *s) return !((unsigned long)slob_next(s) & ~PAGE_MASK); } -static void *slob_new_page(gfp_t gfp, int order, int node) +static void *slob_new_pages(gfp_t gfp, int order, int node) { void *page; @@ -247,12 +252,17 @@ static void *slob_new_page(gfp_t gfp, int order, int node) return page_address(page); } +static void slob_free_pages(void *b, int order) +{ + free_pages((unsigned long)b, order); +} + /* * Allocate a slob block within a given slob_page sp. */ static void *slob_page_alloc(struct slob_page *sp, size_t size, int align) { - slob_t *prev, *cur, *aligned = 0; + slob_t *prev, *cur, *aligned = NULL; int delta = 0, units = SLOB_UNITS(size); for (prev = NULL, cur = sp->free; ; prev = cur, cur = slob_next(cur)) { @@ -349,10 +359,10 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) /* Not enough space: must allocate a new page */ if (!b) { - b = slob_new_page(gfp & ~__GFP_ZERO, 0, node); + b = slob_new_pages(gfp & ~__GFP_ZERO, 0, node); if (!b) - return 0; - sp = (struct slob_page *)virt_to_page(b); + return NULL; + sp = slob_page(b); set_slob_page(sp); spin_lock_irqsave(&slob_lock, flags); @@ -384,7 +394,7 @@ static void slob_free(void *block, int size) return; BUG_ON(!size); - sp = (struct slob_page *)virt_to_page(block); + sp = slob_page(block); units = SLOB_UNITS(size); spin_lock_irqsave(&slob_lock, flags); @@ -476,7 +486,7 @@ void *__kmalloc_node(size_t size, gfp_t gfp, int node) } else { void *ret; - ret = slob_new_page(gfp | __GFP_COMP, get_order(size), node); + ret = slob_new_pages(gfp | __GFP_COMP, get_order(size), node); if (ret) { struct page *page; page = virt_to_page(ret); @@ -494,8 +504,8 @@ void kfree(const void *block) if (unlikely(ZERO_OR_NULL_PTR(block))) return; - sp = (struct slob_page *)virt_to_page(block); - if (slob_page(sp)) { + sp = slob_page(block); + if (is_slob_page(sp)) { int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); unsigned int *m = (unsigned int *)(block - align); slob_free(m, *m + align); @@ -513,8 +523,8 @@ size_t ksize(const void *block) if (unlikely(block == ZERO_SIZE_PTR)) return 0; - sp = (struct slob_page *)virt_to_page(block); - if (slob_page(sp)) { + sp = slob_page(block); + if (is_slob_page(sp)) { int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); unsigned int *m = (unsigned int *)(block - align); return SLOB_UNITS(*m) * SLOB_UNIT; @@ -572,7 +582,7 @@ void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node) if (c->size < PAGE_SIZE) b = slob_alloc(c->size, flags, c->align, node); else - b = slob_new_page(flags, get_order(c->size), node); + b = slob_new_pages(flags, get_order(c->size), node); if (c->ctor) c->ctor(b); @@ -586,7 +596,7 @@ static void __kmem_cache_free(void *b, int size) if (size < PAGE_SIZE) slob_free(b, size); else - free_pages((unsigned long)b, get_order(size)); + slob_free_pages(b, get_order(size)); } static void kmem_rcu_free(struct rcu_head *head) -- GitLab From f3a374e55a60f7ca57335c24ef875731b6683147 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 19 Jan 2009 14:30:48 +0100 Subject: [PATCH 0214/4982] ALSA: ca0106 - Add quirk for GA-G1975X mobo Giga-byte GA-G1975X mobo has a CA0106 on-board chip. Reference: bnc#395807 https://bugzilla.novell.com/show_bug.cgi?id=395807 Signed-off-by: Takashi Iwai --- sound/pci/ca0106/ca0106_main.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 0e62205d408..3aac7e6489c 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -255,6 +255,14 @@ static struct snd_ca0106_details ca0106_chip_details[] = { .gpio_type = 2, .i2c_adc = 1, .spi_dac = 1 } , + /* Giga-byte GA-G1975X mobo + * Novell bnc#395807 + */ + /* FIXME: the GPIO and I2C setting aren't tested well */ + { .serial = 0x1458a006, + .name = "Giga-byte GA-G1975X", + .gpio_type = 1, + .i2c_adc = 1 }, /* Shuttle XPC SD31P which has an onboard Creative Labs * Sound Blaster Live! 24-bit EAX * high-definition 7.1 audio processor". -- GitLab From cade9f8a9cf1cd41f6f9e8850c6a0465a21248c3 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 19 Jan 2009 12:08:58 +0100 Subject: [PATCH 0215/4982] ALSA: Release v1.0.19 Signed-off-by: Jaroslav Kysela Signed-off-by: Takashi Iwai --- include/sound/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sound/version.h b/include/sound/version.h index 2b48237e23b..a7e74e23ad2 100644 --- a/include/sound/version.h +++ b/include/sound/version.h @@ -1,3 +1,3 @@ /* include/version.h */ -#define CONFIG_SND_VERSION "1.0.18a" +#define CONFIG_SND_VERSION "1.0.19" #define CONFIG_SND_DATE "" -- GitLab From 2c782f5981a022f7a238d550af5daa75c8acf382 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 16 Jan 2009 16:35:52 +0000 Subject: [PATCH 0216/4982] ASoC: Implement support for CLK_POUT as MCLK on Zylonite The Zylonite supports switching the MCLK for the WM9713 between the AC97CLK and CLK_POUT outputs of the PXA processor via switch SW15 on the board. This patch adds support for configuring the system to use CLK_POUT. Unfortunately it is not possible to read the state of SW15 from software so this feature is controlled by a module option 'clk_pout' which should be set to a non-zero value to enable the use of CLK_POUT. Signed-off-by: Mark Brown --- sound/soc/pxa/zylonite.c | 101 ++++++++++++++++++++++++++++++++------- 1 file changed, 84 insertions(+), 17 deletions(-) diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index f8e9ecd589d..8541b679f6e 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -26,6 +27,17 @@ #include "pxa2xx-ac97.h" #include "pxa-ssp.h" +/* + * There is a physical switch SW15 on the board which changes the MCLK + * for the WM9713 between the standard AC97 master clock and the + * output of the CLK_POUT signal from the PXA. + */ +static int clk_pout; +module_param(clk_pout, int, 0); +MODULE_PARM_DESC(clk_pout, "Use CLK_POUT as WM9713 MCLK (SW15 on board)."); + +static struct clk *pout; + static struct snd_soc_card zylonite; static const struct snd_soc_dapm_widget zylonite_dapm_widgets[] = { @@ -61,10 +73,8 @@ static const struct snd_soc_dapm_route audio_map[] = { static int zylonite_wm9713_init(struct snd_soc_codec *codec) { - /* Currently we only support use of the AC97 clock here. If - * CLK_POUT is selected by SW15 then the clock API will need - * to be used to request and enable it here. - */ + if (clk_pout) + snd_soc_dai_set_pll(&codec->dai[0], 0, clk_get_rate(pout), 0); snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets, ARRAY_SIZE(zylonite_dapm_widgets)); @@ -85,7 +95,6 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - unsigned int pll_out = 0; unsigned int acds = 0; unsigned int wm9713_div = 0; int ret = 0; @@ -93,16 +102,13 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, switch (params_rate(params)) { case 8000: wm9713_div = 12; - pll_out = 2048000; break; case 16000: wm9713_div = 6; - pll_out = 4096000; break; case 48000: default: wm9713_div = 2; - pll_out = 12288000; acds = 1; break; } @@ -123,10 +129,6 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, pll_out); - if (ret < 0) - return ret; - ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_AUDIO_DIV_ACDS, acds); if (ret < 0) return ret; @@ -135,11 +137,12 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - /* Note that if the PLL is in use the WM9713_PCMCLK_PLL_DIV needs - * to be set instead. - */ - ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV, - WM9713_PCMDIV(wm9713_div)); + if (clk_pout) + ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_PLL_DIV, + WM9713_PCMDIV(wm9713_div)); + else + ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV, + WM9713_PCMDIV(wm9713_div)); if (ret < 0) return ret; @@ -173,8 +176,72 @@ static struct snd_soc_dai_link zylonite_dai[] = { }, }; +static int zylonite_probe(struct platform_device *pdev) +{ + int ret; + + if (clk_pout) { + pout = clk_get(NULL, "CLK_POUT"); + if (IS_ERR(pout)) { + dev_err(&pdev->dev, "Unable to obtain CLK_POUT: %ld\n", + PTR_ERR(pout)); + return PTR_ERR(pout); + } + + ret = clk_enable(pout); + if (ret != 0) { + dev_err(&pdev->dev, "Unable to enable CLK_POUT: %d\n", + ret); + clk_put(pout); + return ret; + } + + dev_dbg(&pdev->dev, "MCLK enabled at %luHz\n", + clk_get_rate(pout)); + } + + return 0; +} + +static int zylonite_remove(struct platform_device *pdev) +{ + if (clk_pout) { + clk_disable(pout); + clk_put(pout); + } + + return 0; +} + +static int zylonite_suspend_post(struct platform_device *pdev, + pm_message_t state) +{ + if (clk_pout) + clk_disable(pout); + + return 0; +} + +static int zylonite_resume_pre(struct platform_device *pdev) +{ + int ret = 0; + + if (clk_pout) { + ret = clk_enable(pout); + if (ret != 0) + dev_err(&pdev->dev, "Unable to enable CLK_POUT: %d\n", + ret); + } + + return ret; +} + static struct snd_soc_card zylonite = { .name = "Zylonite", + .probe = &zylonite_probe, + .remove = &zylonite_remove, + .suspend_post = &zylonite_suspend_post, + .resume_pre = &zylonite_resume_pre, .platform = &pxa2xx_soc_platform, .dai_link = zylonite_dai, .num_links = ARRAY_SIZE(zylonite_dai), -- GitLab From 28796eaf806502b9bd86cbacf8edbc14c80c14b0 Mon Sep 17 00:00:00 2001 From: Ian Molton Date: Sat, 17 Jan 2009 15:11:06 +0000 Subject: [PATCH 0217/4982] ASoC: machine support for Toshiba e740 PDA This patch provides suupport for the wm9705 AC97 codec on the Toshiba e740. Note: The e740 has a hard headphone switch that turns the speaker off and is not software detectable or controlable. Also both headphone and speaker amps share a common output enable. Signed-off-by: Ian Molton Signed-off-by: Mark Brown --- arch/arm/mach-pxa/e740.c | 5 + arch/arm/mach-pxa/include/mach/eseries-gpio.h | 5 + sound/soc/pxa/Kconfig | 9 + sound/soc/pxa/Makefile | 2 + sound/soc/pxa/e740_wm9705.c | 213 ++++++++++++++++++ 5 files changed, 234 insertions(+) create mode 100644 sound/soc/pxa/e740_wm9705.c diff --git a/arch/arm/mach-pxa/e740.c b/arch/arm/mach-pxa/e740.c index 6d48e00f4f0..a6fff782e7a 100644 --- a/arch/arm/mach-pxa/e740.c +++ b/arch/arm/mach-pxa/e740.c @@ -135,6 +135,11 @@ static unsigned long e740_pin_config[] __initdata = { /* IrDA */ GPIO38_GPIO | MFP_LPM_DRIVE_HIGH, + /* Audio power control */ + GPIO16_GPIO, /* AC97 codec AVDD2 supply (analogue power) */ + GPIO40_GPIO, /* Mic amp power */ + GPIO41_GPIO, /* Headphone amp power */ + /* PC Card */ GPIO8_GPIO, /* CD0 */ GPIO44_GPIO, /* CD1 */ diff --git a/arch/arm/mach-pxa/include/mach/eseries-gpio.h b/arch/arm/mach-pxa/include/mach/eseries-gpio.h index 6d6e4d8fa4c..f3e5509820d 100644 --- a/arch/arm/mach-pxa/include/mach/eseries-gpio.h +++ b/arch/arm/mach-pxa/include/mach/eseries-gpio.h @@ -45,6 +45,11 @@ /* e7xx IrDA power control */ #define GPIO_E7XX_IR_OFF 38 +/* e740 audio control GPIOs */ +#define GPIO_E740_WM9705_nAVDD2 16 +#define GPIO_E740_MIC_ON 40 +#define GPIO_E740_AMP_ON 41 + /* e750 audio control GPIOs */ #define GPIO_E750_HP_AMP_OFF 4 #define GPIO_E750_SPK_AMP_OFF 7 diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index b9b1a3f5d67..958ac3fe15d 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -61,6 +61,15 @@ config SND_PXA2XX_SOC_TOSA Say Y if you want to add support for SoC audio on Sharp Zaurus SL-C6000x models (Tosa). +config SND_PXA2XX_SOC_E740 + tristate "SoC AC97 Audio support for e740" + depends on SND_PXA2XX_SOC && MACH_E740 + select SND_SOC_WM9705 + select SND_PXA2XX_SOC_AC97 + help + Say Y if you want to add support for SoC audio on the + toshiba e740 PDA + config SND_PXA2XX_SOC_E750 tristate "SoC AC97 Audio support for e750" depends on SND_PXA2XX_SOC && MACH_E750 diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile index c7d4cceeed9..97a51a8c936 100644 --- a/sound/soc/pxa/Makefile +++ b/sound/soc/pxa/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o snd-soc-corgi-objs := corgi.o snd-soc-poodle-objs := poodle.o snd-soc-tosa-objs := tosa.o +snd-soc-e740-objs := e740_wm9705.o snd-soc-e750-objs := e750_wm9705.o snd-soc-e800-objs := e800_wm9712.o snd-soc-spitz-objs := spitz.o @@ -23,6 +24,7 @@ snd-soc-zylonite-objs := zylonite.o obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o obj-$(CONFIG_SND_PXA2XX_SOC_TOSA) += snd-soc-tosa.o +obj-$(CONFIG_SND_PXA2XX_SOC_E740) += snd-soc-e740.o obj-$(CONFIG_SND_PXA2XX_SOC_E750) += snd-soc-e750.o obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c new file mode 100644 index 00000000000..ac361765173 --- /dev/null +++ b/sound/soc/pxa/e740_wm9705.c @@ -0,0 +1,213 @@ +/* + * e740-wm9705.c -- SoC audio for e740 + * + * Copyright 2007 (c) Ian Molton + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; version 2 ONLY. + * + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "../codecs/wm9705.h" +#include "pxa2xx-pcm.h" +#include "pxa2xx-ac97.h" + + +#define E740_AUDIO_OUT 1 +#define E740_AUDIO_IN 2 + +static int e740_audio_power; + +static void e740_sync_audio_power(int status) +{ + gpio_set_value(GPIO_E740_WM9705_nAVDD2, !status); + gpio_set_value(GPIO_E740_AMP_ON, (status & E740_AUDIO_OUT) ? 1 : 0); + gpio_set_value(GPIO_E740_MIC_ON, (status & E740_AUDIO_IN) ? 1 : 0); +} + +static int e740_mic_amp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + if (event & SND_SOC_DAPM_PRE_PMU) + e740_audio_power |= E740_AUDIO_IN; + else if (event & SND_SOC_DAPM_POST_PMD) + e740_audio_power &= ~E740_AUDIO_IN; + + e740_sync_audio_power(e740_audio_power); + + return 0; +} + +static int e740_output_amp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + if (event & SND_SOC_DAPM_PRE_PMU) + e740_audio_power |= E740_AUDIO_OUT; + else if (event & SND_SOC_DAPM_POST_PMD) + e740_audio_power &= ~E740_AUDIO_OUT; + + e740_sync_audio_power(e740_audio_power); + + return 0; +} + +static const struct snd_soc_dapm_widget e740_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), + SND_SOC_DAPM_MIC("Mic (Internal)", NULL), + SND_SOC_DAPM_PGA_E("Output Amp", SND_SOC_NOPM, 0, 0, NULL, 0, + e740_output_amp_event, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_PGA_E("Mic Amp", SND_SOC_NOPM, 0, 0, NULL, 0, + e740_mic_amp_event, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_route audio_map[] = { + {"Output Amp", NULL, "LOUT"}, + {"Output Amp", NULL, "ROUT"}, + {"Output Amp", NULL, "MONOOUT"}, + + {"Speaker", NULL, "Output Amp"}, + {"Headphone Jack", NULL, "Output Amp"}, + + {"MIC1", NULL, "Mic Amp"}, + {"Mic Amp", NULL, "Mic (Internal)"}, +}; + +static int e740_ac97_init(struct snd_soc_codec *codec) +{ + snd_soc_dapm_nc_pin(codec, "HPOUTL"); + snd_soc_dapm_nc_pin(codec, "HPOUTR"); + snd_soc_dapm_nc_pin(codec, "PHONE"); + snd_soc_dapm_nc_pin(codec, "LINEINL"); + snd_soc_dapm_nc_pin(codec, "LINEINR"); + snd_soc_dapm_nc_pin(codec, "CDINL"); + snd_soc_dapm_nc_pin(codec, "CDINR"); + snd_soc_dapm_nc_pin(codec, "PCBEEP"); + snd_soc_dapm_nc_pin(codec, "MIC2"); + + snd_soc_dapm_new_controls(codec, e740_dapm_widgets, + ARRAY_SIZE(e740_dapm_widgets)); + + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); + + snd_soc_dapm_sync(codec); + + return 0; +} + +static struct snd_soc_dai_link e740_dai[] = { + { + .name = "AC97", + .stream_name = "AC97 HiFi", + .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], + .codec_dai = &wm9705_dai[WM9705_DAI_AC97_HIFI], + .init = e740_ac97_init, + }, + { + .name = "AC97 Aux", + .stream_name = "AC97 Aux", + .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], + .codec_dai = &wm9705_dai[WM9705_DAI_AC97_AUX], + }, +}; + +static struct snd_soc_card e740 = { + .name = "Toshiba e740", + .platform = &pxa2xx_soc_platform, + .dai_link = e740_dai, + .num_links = ARRAY_SIZE(e740_dai), +}; + +static struct snd_soc_device e740_snd_devdata = { + .card = &e740, + .codec_dev = &soc_codec_dev_wm9705, +}; + +static struct platform_device *e740_snd_device; + +static int __init e740_init(void) +{ + int ret; + + if (!machine_is_e740()) + return -ENODEV; + + ret = gpio_request(GPIO_E740_MIC_ON, "Mic amp"); + if (ret) + return ret; + + ret = gpio_request(GPIO_E740_AMP_ON, "Output amp"); + if (ret) + goto free_mic_amp_gpio; + + ret = gpio_request(GPIO_E740_WM9705_nAVDD2, "Audio power"); + if (ret) + goto free_op_amp_gpio; + + /* Disable audio */ + ret = gpio_direction_output(GPIO_E740_MIC_ON, 0); + if (ret) + goto free_apwr_gpio; + ret = gpio_direction_output(GPIO_E740_AMP_ON, 0); + if (ret) + goto free_apwr_gpio; + ret = gpio_direction_output(GPIO_E740_WM9705_nAVDD2, 1); + if (ret) + goto free_apwr_gpio; + + e740_snd_device = platform_device_alloc("soc-audio", -1); + if (!e740_snd_device) { + ret = -ENOMEM; + goto free_apwr_gpio; + } + + platform_set_drvdata(e740_snd_device, &e740_snd_devdata); + e740_snd_devdata.dev = &e740_snd_device->dev; + ret = platform_device_add(e740_snd_device); + + if (!ret) + return 0; + +/* Fail gracefully */ + platform_device_put(e740_snd_device); +free_apwr_gpio: + gpio_free(GPIO_E740_WM9705_nAVDD2); +free_op_amp_gpio: + gpio_free(GPIO_E740_AMP_ON); +free_mic_amp_gpio: + gpio_free(GPIO_E740_MIC_ON); + + return ret; +} + +static void __exit e740_exit(void) +{ + platform_device_unregister(e740_snd_device); +} + +module_init(e740_init); +module_exit(e740_exit); + +/* Module information */ +MODULE_AUTHOR("Ian Molton "); +MODULE_DESCRIPTION("ALSA SoC driver for e740"); +MODULE_LICENSE("GPL v2"); -- GitLab From 91432e976ff1323e5dd6f52498969602953c6ee9 Mon Sep 17 00:00:00 2001 From: Ian Molton Date: Sat, 17 Jan 2009 17:44:23 +0000 Subject: [PATCH 0218/4982] ASoC: fixes to caching implementations This patch takes fixes a number of bugs in the caching code used by several ASoC codec drivers. Mostly off-by-one fixes. Signed-off-by: Ian Molton Signed-off-by: Mark Brown --- sound/soc/codecs/ac97.c | 2 -- sound/soc/codecs/ad1980.c | 4 ++-- sound/soc/codecs/twl4030.c | 3 +++ sound/soc/codecs/wm8580.c | 4 ++-- sound/soc/codecs/wm8728.c | 4 ++-- sound/soc/codecs/wm8753.c | 4 ++-- sound/soc/codecs/wm8990.c | 4 ++-- sound/soc/codecs/wm9712.c | 4 ++-- sound/soc/codecs/wm9713.c | 4 ++-- 9 files changed, 17 insertions(+), 16 deletions(-) diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index fb53e6511af..89d41277616 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c @@ -123,7 +123,6 @@ bus_err: snd_soc_free_pcms(socdev); err: - kfree(socdev->codec->reg_cache); kfree(socdev->codec); socdev->codec = NULL; return ret; @@ -138,7 +137,6 @@ static int ac97_soc_remove(struct platform_device *pdev) return 0; snd_soc_free_pcms(socdev); - kfree(socdev->codec->reg_cache); kfree(socdev->codec); return 0; diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index c3c5d0eee37..faf358758e1 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c @@ -109,7 +109,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, default: reg = reg >> 1; - if (reg >= (ARRAY_SIZE(ad1980_reg))) + if (reg >= ARRAY_SIZE(ad1980_reg)) return -EINVAL; return cache[reg]; @@ -123,7 +123,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, soc_ac97_ops.write(codec->ac97, reg, val); reg = reg >> 1; - if (reg < (ARRAY_SIZE(ad1980_reg))) + if (reg < ARRAY_SIZE(ad1980_reg)) cache[reg] = val; return 0; diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index ddc9f37d863..f530c1e6d9e 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -125,6 +125,9 @@ static inline unsigned int twl4030_read_reg_cache(struct snd_soc_codec *codec, { u8 *cache = codec->reg_cache; + if (reg >= TWL4030_CACHEREGNUM) + return -EIO; + return cache[reg]; } diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 9b75a377453..3faf0e70ce1 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -200,7 +200,7 @@ static inline unsigned int wm8580_read_reg_cache(struct snd_soc_codec *codec, unsigned int reg) { u16 *cache = codec->reg_cache; - BUG_ON(reg > ARRAY_SIZE(wm8580_reg)); + BUG_ON(reg >= ARRAY_SIZE(wm8580_reg)); return cache[reg]; } @@ -223,7 +223,7 @@ static int wm8580_write(struct snd_soc_codec *codec, unsigned int reg, { u8 data[2]; - BUG_ON(reg > ARRAY_SIZE(wm8580_reg)); + BUG_ON(reg >= ARRAY_SIZE(wm8580_reg)); /* Registers are 9 bits wide */ value &= 0x1ff; diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index defa310bc7d..f90dc52e975 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -47,7 +47,7 @@ static inline unsigned int wm8728_read_reg_cache(struct snd_soc_codec *codec, unsigned int reg) { u16 *cache = codec->reg_cache; - BUG_ON(reg > ARRAY_SIZE(wm8728_reg_defaults)); + BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults)); return cache[reg]; } @@ -55,7 +55,7 @@ static inline void wm8728_write_reg_cache(struct snd_soc_codec *codec, u16 reg, unsigned int value) { u16 *cache = codec->reg_cache; - BUG_ON(reg > ARRAY_SIZE(wm8728_reg_defaults)); + BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults)); cache[reg] = value; } diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 7283178e0eb..5a1c1fca120 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -97,7 +97,7 @@ static inline unsigned int wm8753_read_reg_cache(struct snd_soc_codec *codec, unsigned int reg) { u16 *cache = codec->reg_cache; - if (reg < 1 || reg > (ARRAY_SIZE(wm8753_reg) + 1)) + if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1)) return -1; return cache[reg - 1]; } @@ -109,7 +109,7 @@ static inline void wm8753_write_reg_cache(struct snd_soc_codec *codec, unsigned int reg, unsigned int value) { u16 *cache = codec->reg_cache; - if (reg < 1 || reg > 0x3f) + if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1)) return; cache[reg - 1] = value; } diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 6b2778632d5..f93c0955ed9 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -116,7 +116,7 @@ static inline unsigned int wm8990_read_reg_cache(struct snd_soc_codec *codec, unsigned int reg) { u16 *cache = codec->reg_cache; - BUG_ON(reg > (ARRAY_SIZE(wm8990_reg)) - 1); + BUG_ON(reg >= ARRAY_SIZE(wm8990_reg)); return cache[reg]; } @@ -129,7 +129,7 @@ static inline void wm8990_write_reg_cache(struct snd_soc_codec *codec, u16 *cache = codec->reg_cache; /* Reset register and reserved registers are uncached */ - if (reg == 0 || reg > ARRAY_SIZE(wm8990_reg) - 1) + if (reg == 0 || reg >= ARRAY_SIZE(wm8990_reg)) return; cache[reg] = value; diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 1b0ace0f4dc..4dc90d67530 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -452,7 +452,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, else { reg = reg >> 1; - if (reg > (ARRAY_SIZE(wm9712_reg))) + if (reg >= (ARRAY_SIZE(wm9712_reg))) return -EIO; return cache[reg]; @@ -466,7 +466,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, soc_ac97_ops.write(codec->ac97, reg, val); reg = reg >> 1; - if (reg <= (ARRAY_SIZE(wm9712_reg))) + if (reg < (ARRAY_SIZE(wm9712_reg))) cache[reg] = val; return 0; diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index e636d8a18ed..0e60e16973d 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -620,7 +620,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, else { reg = reg >> 1; - if (reg > (ARRAY_SIZE(wm9713_reg))) + if (reg >= (ARRAY_SIZE(wm9713_reg))) return -EIO; return cache[reg]; @@ -634,7 +634,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, if (reg < 0x7c) soc_ac97_ops.write(codec->ac97, reg, val); reg = reg >> 1; - if (reg <= (ARRAY_SIZE(wm9713_reg))) + if (reg < (ARRAY_SIZE(wm9713_reg))) cache[reg] = val; return 0; -- GitLab From b2a19d02396c92294abcddee5bd9bd49cc4e4d1c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 17 Jan 2009 19:14:26 +0000 Subject: [PATCH 0219/4982] ASoC: Staticise PCM operations tables The PCM operations tables are not exported directly but are instead included in the platform structure so should be declared static. Signed-off-by: Mark Brown --- sound/soc/atmel/atmel-pcm.c | 2 +- sound/soc/au1x/dbdma2.c | 2 +- sound/soc/blackfin/bf5xx-ac97-pcm.c | 2 +- sound/soc/blackfin/bf5xx-i2s-pcm.c | 2 +- sound/soc/davinci/davinci-pcm.c | 2 +- sound/soc/omap/omap-pcm.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c index 3dcdc4e3cfa..9ef6b96373f 100644 --- a/sound/soc/atmel/atmel-pcm.c +++ b/sound/soc/atmel/atmel-pcm.c @@ -347,7 +347,7 @@ static int atmel_pcm_mmap(struct snd_pcm_substream *substream, vma->vm_end - vma->vm_start, vma->vm_page_prot); } -struct snd_pcm_ops atmel_pcm_ops = { +static struct snd_pcm_ops atmel_pcm_ops = { .open = atmel_pcm_open, .close = atmel_pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c index bc8d654576c..30490a25914 100644 --- a/sound/soc/au1x/dbdma2.c +++ b/sound/soc/au1x/dbdma2.c @@ -305,7 +305,7 @@ static int au1xpsc_pcm_close(struct snd_pcm_substream *substream) return 0; } -struct snd_pcm_ops au1xpsc_pcm_ops = { +static struct snd_pcm_ops au1xpsc_pcm_ops = { .open = au1xpsc_pcm_open, .close = au1xpsc_pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c index 8067cfafa3a..8cfed1a5dcb 100644 --- a/sound/soc/blackfin/bf5xx-ac97-pcm.c +++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c @@ -297,7 +297,7 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, } #endif -struct snd_pcm_ops bf5xx_pcm_ac97_ops = { +static struct snd_pcm_ops bf5xx_pcm_ac97_ops = { .open = bf5xx_pcm_open, .ioctl = snd_pcm_lib_ioctl, .hw_params = bf5xx_pcm_hw_params, diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c index 53d290b3ea4..1318c4f627b 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.c +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c @@ -184,7 +184,7 @@ static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream, return 0 ; } -struct snd_pcm_ops bf5xx_pcm_i2s_ops = { +static struct snd_pcm_ops bf5xx_pcm_i2s_ops = { .open = bf5xx_pcm_open, .ioctl = snd_pcm_lib_ioctl, .hw_params = bf5xx_pcm_hw_params, diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index 366049d8578..7af3b5b3a53 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c @@ -286,7 +286,7 @@ static int davinci_pcm_mmap(struct snd_pcm_substream *substream, runtime->dma_bytes); } -struct snd_pcm_ops davinci_pcm_ops = { +static struct snd_pcm_ops davinci_pcm_ops = { .open = davinci_pcm_open, .close = davinci_pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index b0362dfd5b7..607a38c7ae4 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -264,7 +264,7 @@ static int omap_pcm_mmap(struct snd_pcm_substream *substream, runtime->dma_bytes); } -struct snd_pcm_ops omap_pcm_ops = { +static struct snd_pcm_ops omap_pcm_ops = { .open = omap_pcm_open, .close = omap_pcm_close, .ioctl = snd_pcm_lib_ioctl, -- GitLab From 5cdc5e9e69d4dc3a3630ae1fa666401b2a8dcde6 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 19 Jan 2009 20:49:37 +0100 Subject: [PATCH 0220/4982] x86: fully honor "nolapic", fix Impact: build fix Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 48578795583..9ca12af6c87 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -1131,7 +1131,9 @@ void __cpuinit setup_local_APIC(void) int i, j; if (disable_apic) { +#ifdef CONFIG_X86_IO_APIC disable_ioapic_setup(); +#endif return; } -- GitLab From c6e50f93db5bd0895ec7c7d1b6f3886c6e1f11b6 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 20 Jan 2009 12:29:19 +0900 Subject: [PATCH 0221/4982] x86: cleanup stack protector Impact: cleanup Make the following cleanups. * remove duplicate comment from boot_init_stack_canary() which fits better in the other place - cpu_idle(). * move stack_canary offset check from __switch_to() to boot_init_stack_canary(). Signed-off-by: Tejun Heo --- arch/x86/include/asm/pda.h | 2 -- arch/x86/include/asm/stackprotector.h | 13 ++++++------- arch/x86/kernel/process_64.c | 7 ------- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h index 5976cd803e9..4a8c9d382c9 100644 --- a/arch/x86/include/asm/pda.h +++ b/arch/x86/include/asm/pda.h @@ -40,6 +40,4 @@ extern void pda_init(int); #endif -#define refresh_stack_canary() write_pda(stack_canary, current->stack_canary) - #endif /* _ASM_X86_PDA_H */ diff --git a/arch/x86/include/asm/stackprotector.h b/arch/x86/include/asm/stackprotector.h index c7f0d10bae7..2383e5bb475 100644 --- a/arch/x86/include/asm/stackprotector.h +++ b/arch/x86/include/asm/stackprotector.h @@ -16,13 +16,12 @@ static __always_inline void boot_init_stack_canary(void) u64 tsc; /* - * If we're the non-boot CPU, nothing set the PDA stack - * canary up for us - and if we are the boot CPU we have - * a 0 stack canary. This is a good place for updating - * it, as we wont ever return from this function (so the - * invalid canaries already on the stack wont ever - * trigger). - * + * Build time only check to make sure the stack_canary is at + * offset 40 in the pda; this is a gcc ABI requirement + */ + BUILD_BUG_ON(offsetof(struct x8664_pda, stack_canary) != 40); + + /* * We both use the random pool and the current TSC as a source * of randomness. The TSC only matters for very early init, * there it already has some randomness on most systems. Later diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index aa89eabf09e..088bc9a0f82 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -638,13 +638,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) percpu_write(kernel_stack, (unsigned long)task_stack_page(next_p) + THREAD_SIZE - KERNEL_STACK_OFFSET); -#ifdef CONFIG_CC_STACKPROTECTOR - /* - * Build time only check to make sure the stack_canary is at - * offset 40 in the pda; this is a gcc ABI requirement - */ - BUILD_BUG_ON(offsetof(struct x8664_pda, stack_canary) != 40); -#endif /* * Now maybe reload the debug registers and handle I/O bitmaps -- GitLab From b4a8f7a262e79ecb0b39beb1449af524a78887f8 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 20 Jan 2009 12:29:19 +0900 Subject: [PATCH 0222/4982] x86: conditionalize stack canary handling in hot path Impact: no unnecessary stack canary swapping during context switch There's no point in moving stack_canary around during context switch if it's not enabled. Conditionalize it. Signed-off-by: Tejun Heo --- arch/x86/include/asm/system.h | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h index 8cadfe9b119..b77bd8bd3cc 100644 --- a/arch/x86/include/asm/system.h +++ b/arch/x86/include/asm/system.h @@ -86,17 +86,28 @@ do { \ , "rcx", "rbx", "rdx", "r8", "r9", "r10", "r11", \ "r12", "r13", "r14", "r15" +#ifdef CONFIG_CC_STACKPROTECTOR +#define __switch_canary \ + "movq %P[task_canary](%%rsi),%%r8\n\t" \ + "movq %%r8,%%gs:%P[pda_canary]\n\t" +#define __switch_canary_param \ + , [task_canary] "i" (offsetof(struct task_struct, stack_canary)) \ + , [pda_canary] "i" (offsetof(struct x8664_pda, stack_canary)) +#else /* CC_STACKPROTECTOR */ +#define __switch_canary +#define __switch_canary_param +#endif /* CC_STACKPROTECTOR */ + /* Save restore flags to clear handle leaking NT */ #define switch_to(prev, next, last) \ - asm volatile(SAVE_CONTEXT \ + asm volatile(SAVE_CONTEXT \ "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */ \ "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */ \ "call __switch_to\n\t" \ ".globl thread_return\n" \ "thread_return:\n\t" \ "movq "__percpu_arg([current_task])",%%rsi\n\t" \ - "movq %P[task_canary](%%rsi),%%r8\n\t" \ - "movq %%r8,%%gs:%P[pda_canary]\n\t" \ + __switch_canary \ "movq %P[thread_info](%%rsi),%%r8\n\t" \ LOCK_PREFIX "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" \ "movq %%rax,%%rdi\n\t" \ @@ -108,9 +119,8 @@ do { \ [ti_flags] "i" (offsetof(struct thread_info, flags)), \ [tif_fork] "i" (TIF_FORK), \ [thread_info] "i" (offsetof(struct task_struct, stack)), \ - [task_canary] "i" (offsetof(struct task_struct, stack_canary)),\ - [current_task] "m" (per_cpu_var(current_task)), \ - [pda_canary] "i" (offsetof(struct x8664_pda, stack_canary))\ + [current_task] "m" (per_cpu_var(current_task)) \ + __switch_canary_param \ : "memory", "cc" __EXTRA_CLOBBER) #endif -- GitLab From 8ce031972b40da58c268caba8c5ea3c0856d7131 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Mon, 19 Jan 2009 12:21:27 +0900 Subject: [PATCH 0223/4982] x86: remove pda_init() Impact: cleanup Copy the code to cpu_init() to satisfy the requirement that the cpu be reinitialized. Remove all other calls, since the segments are already initialized in head_64.S. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/pda.h | 1 - arch/x86/kernel/cpu/common.c | 15 +++------------ arch/x86/kernel/head64.c | 2 -- arch/x86/xen/enlighten.c | 1 - 4 files changed, 3 insertions(+), 16 deletions(-) diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h index 4a8c9d382c9..b473e952439 100644 --- a/arch/x86/include/asm/pda.h +++ b/arch/x86/include/asm/pda.h @@ -24,7 +24,6 @@ struct x8664_pda { } ____cacheline_aligned_in_smp; DECLARE_PER_CPU(struct x8664_pda, __pda); -extern void pda_init(int); #define cpu_pda(cpu) (&per_cpu(__pda, cpu)) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 7976a6a0f65..f83a4d6160f 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -895,15 +895,6 @@ EXPORT_PER_CPU_SYMBOL(kernel_stack); DEFINE_PER_CPU(unsigned int, irq_count) = -1; -void __cpuinit pda_init(int cpu) -{ - /* Setup up data that may be needed in __get_free_pages early */ - loadsegment(fs, 0); - loadsegment(gs, 0); - - load_pda_offset(cpu); -} - static DEFINE_PER_CPU_PAGE_ALIGNED(char, exception_stacks [(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ]) __aligned(PAGE_SIZE); @@ -967,9 +958,9 @@ void __cpuinit cpu_init(void) struct task_struct *me; int i; - /* CPU 0 is initialised in head64.c */ - if (cpu != 0) - pda_init(cpu); + loadsegment(fs, 0); + loadsegment(gs, 0); + load_pda_offset(cpu); #ifdef CONFIG_NUMA if (cpu != 0 && percpu_read(node_number) == 0 && diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index af67d3227ea..f5b27224769 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -91,8 +91,6 @@ void __init x86_64_start_kernel(char * real_mode_data) if (console_loglevel == 10) early_printk("Kernel alive\n"); - pda_init(0); - x86_64_start_reservations(real_mode_data); } diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 75b94139e1f..bef941f6145 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1645,7 +1645,6 @@ asmlinkage void __init xen_start_kernel(void) #ifdef CONFIG_X86_64 /* Disable until direct per-cpu data access. */ have_vcpu_info_placement = 0; - pda_init(0); #endif xen_smp_init(); -- GitLab From 0bd74fa8e29dcad98f7e8ffe01ec05fb3326abaf Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Mon, 19 Jan 2009 12:21:27 +0900 Subject: [PATCH 0224/4982] percpu: refactor percpu.h Impact: cleanup Refactor the DEFINE_PER_CPU_* macros and add .data.percpu.first section. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- include/asm-generic/vmlinux.lds.h | 1 + include/linux/percpu.h | 41 +++++++++++++++++-------------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index aa6b9b1b30b..32bbf50d305 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -486,6 +486,7 @@ */ #define PERCPU_VADDR(vaddr, phdr) \ PERCPU_PROLOG(vaddr) \ + *(.data.percpu.first) \ *(.data.percpu.page_aligned) \ *(.data.percpu) \ *(.data.percpu.shared_aligned) \ diff --git a/include/linux/percpu.h b/include/linux/percpu.h index 9f2a3751873..0e24202b5a4 100644 --- a/include/linux/percpu.h +++ b/include/linux/percpu.h @@ -9,34 +9,39 @@ #include #ifdef CONFIG_SMP -#define DEFINE_PER_CPU(type, name) \ - __attribute__((__section__(".data.percpu"))) \ - PER_CPU_ATTRIBUTES __typeof__(type) per_cpu__##name +#define PER_CPU_BASE_SECTION ".data.percpu" #ifdef MODULE -#define SHARED_ALIGNED_SECTION ".data.percpu" +#define PER_CPU_SHARED_ALIGNED_SECTION "" #else -#define SHARED_ALIGNED_SECTION ".data.percpu.shared_aligned" +#define PER_CPU_SHARED_ALIGNED_SECTION ".shared_aligned" #endif +#define PER_CPU_FIRST_SECTION ".first" -#define DEFINE_PER_CPU_SHARED_ALIGNED(type, name) \ - __attribute__((__section__(SHARED_ALIGNED_SECTION))) \ - PER_CPU_ATTRIBUTES __typeof__(type) per_cpu__##name \ - ____cacheline_aligned_in_smp +#else + +#define PER_CPU_BASE_SECTION ".data" +#define PER_CPU_SHARED_ALIGNED_SECTION "" +#define PER_CPU_FIRST_SECTION "" + +#endif -#define DEFINE_PER_CPU_PAGE_ALIGNED(type, name) \ - __attribute__((__section__(".data.percpu.page_aligned"))) \ +#define DEFINE_PER_CPU_SECTION(type, name, section) \ + __attribute__((__section__(PER_CPU_BASE_SECTION section))) \ PER_CPU_ATTRIBUTES __typeof__(type) per_cpu__##name -#else + #define DEFINE_PER_CPU(type, name) \ - PER_CPU_ATTRIBUTES __typeof__(type) per_cpu__##name + DEFINE_PER_CPU_SECTION(type, name, "") -#define DEFINE_PER_CPU_SHARED_ALIGNED(type, name) \ - DEFINE_PER_CPU(type, name) +#define DEFINE_PER_CPU_SHARED_ALIGNED(type, name) \ + DEFINE_PER_CPU_SECTION(type, name, PER_CPU_SHARED_ALIGNED_SECTION) \ + ____cacheline_aligned_in_smp -#define DEFINE_PER_CPU_PAGE_ALIGNED(type, name) \ - DEFINE_PER_CPU(type, name) -#endif +#define DEFINE_PER_CPU_PAGE_ALIGNED(type, name) \ + DEFINE_PER_CPU_SECTION(type, name, ".page_aligned") + +#define DEFINE_PER_CPU_FIRST(type, name) \ + DEFINE_PER_CPU_SECTION(type, name, PER_CPU_FIRST_SECTION) #define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(per_cpu__##var) #define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var) -- GitLab From 8c7e58e690ae60ab4215b025f433ed4af261e103 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Mon, 19 Jan 2009 12:21:28 +0900 Subject: [PATCH 0225/4982] x86: rework __per_cpu_load adjustments Impact: cleanup Use cpu_number to determine if the adjustment is necessary. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/kernel/head_64.S | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index c8ace880661..98ea26a2fca 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -207,19 +207,15 @@ ENTRY(secondary_startup_64) #ifdef CONFIG_SMP /* - * early_gdt_base should point to the gdt_page in static percpu init - * data area. Computing this requires two symbols - __per_cpu_load - * and per_cpu__gdt_page. As linker can't do no such relocation, do - * it by hand. As early_gdt_descr is manipulated by C code for - * secondary CPUs, this should be done only once for the boot CPU - * when early_gdt_descr_base contains zero. + * Fix up static pointers that need __per_cpu_load added. The assembler + * is unable to do this directly. This is only needed for the boot cpu. + * These values are set up with the correct base addresses by C code for + * secondary cpus. */ - movq early_gdt_descr_base(%rip), %rax - testq %rax, %rax - jnz 1f - movq $__per_cpu_load, %rax - addq $per_cpu__gdt_page, %rax - movq %rax, early_gdt_descr_base(%rip) + movq initial_gs(%rip), %rax + cmpl $0, per_cpu__cpu_number(%rax) + jne 1f + addq %rax, early_gdt_descr_base(%rip) 1: #endif /* @@ -431,12 +427,8 @@ NEXT_PAGE(level2_spare_pgt) .globl early_gdt_descr early_gdt_descr: .word GDT_ENTRIES*8-1 -#ifdef CONFIG_SMP early_gdt_descr_base: - .quad 0x0000000000000000 -#else .quad per_cpu__gdt_page -#endif ENTRY(phys_base) /* This must match the first entry in level2_kernel_pgt */ -- GitLab From 947e76cdc34c782fc947313d4331380686eebbad Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Mon, 19 Jan 2009 12:21:28 +0900 Subject: [PATCH 0226/4982] x86: move stack_canary into irq_stack Impact: x86_64 percpu area layout change, irq_stack now at the beginning Now that the PDA is empty except for the stack canary, it can be removed. The irqstack is moved to the start of the per-cpu section. If the stack protector is enabled, the canary overlaps the bottom 48 bytes of the irqstack. tj: * updated subject * dropped asm relocation of irq_stack_ptr * updated comments a bit * rebased on top of stack canary changes Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/pda.h | 3 --- arch/x86/include/asm/percpu.h | 6 ----- arch/x86/include/asm/processor.h | 23 +++++++++++++++++- arch/x86/include/asm/stackprotector.h | 6 ++--- arch/x86/include/asm/system.h | 4 ++-- arch/x86/kernel/asm-offsets_64.c | 4 ---- arch/x86/kernel/cpu/common.c | 7 +++--- arch/x86/kernel/head_64.S | 13 ++++------ arch/x86/kernel/setup_percpu.c | 34 ++++----------------------- arch/x86/kernel/vmlinux_64.lds.S | 8 +++++-- 10 files changed, 46 insertions(+), 62 deletions(-) diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h index b473e952439..ba46416634f 100644 --- a/arch/x86/include/asm/pda.h +++ b/arch/x86/include/asm/pda.h @@ -17,9 +17,6 @@ struct x8664_pda { unsigned long unused4; int unused5; unsigned int unused6; /* 36 was cpunumber */ - unsigned long stack_canary; /* 40 stack canary value */ - /* gcc-ABI: this canary MUST be at - offset 40!!! */ short in_bootmem; /* pda lives in bootmem */ } ____cacheline_aligned_in_smp; diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index 165d5272ece..ce980db5e59 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h @@ -133,12 +133,6 @@ do { \ /* We can use this directly for local CPU (faster). */ DECLARE_PER_CPU(unsigned long, this_cpu_off); -#ifdef CONFIG_X86_64 -extern void load_pda_offset(int cpu); -#else -static inline void load_pda_offset(int cpu) { } -#endif - #endif /* !__ASSEMBLY__ */ #ifdef CONFIG_SMP diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index f511246fa6c..48676b943b9 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -379,8 +379,29 @@ union thread_xstate { #ifdef CONFIG_X86_64 DECLARE_PER_CPU(struct orig_ist, orig_ist); -DECLARE_PER_CPU(char[IRQ_STACK_SIZE], irq_stack); +union irq_stack_union { + char irq_stack[IRQ_STACK_SIZE]; + /* + * GCC hardcodes the stack canary as %gs:40. Since the + * irq_stack is the object at %gs:0, we reserve the bottom + * 48 bytes of the irq stack for the canary. + */ + struct { + char gs_base[40]; + unsigned long stack_canary; + }; +}; + +DECLARE_PER_CPU(union irq_stack_union, irq_stack_union); DECLARE_PER_CPU(char *, irq_stack_ptr); + +static inline void load_gs_base(int cpu) +{ + /* Memory clobbers used to order pda/percpu accesses */ + mb(); + wrmsrl(MSR_GS_BASE, (unsigned long)per_cpu(irq_stack_union.gs_base, cpu)); + mb(); +} #endif extern void print_cpu_info(struct cpuinfo_x86 *); diff --git a/arch/x86/include/asm/stackprotector.h b/arch/x86/include/asm/stackprotector.h index 2383e5bb475..36a700acaf2 100644 --- a/arch/x86/include/asm/stackprotector.h +++ b/arch/x86/include/asm/stackprotector.h @@ -2,7 +2,7 @@ #define _ASM_STACKPROTECTOR_H 1 #include -#include +#include /* * Initialize the stackprotector canary value. @@ -19,7 +19,7 @@ static __always_inline void boot_init_stack_canary(void) * Build time only check to make sure the stack_canary is at * offset 40 in the pda; this is a gcc ABI requirement */ - BUILD_BUG_ON(offsetof(struct x8664_pda, stack_canary) != 40); + BUILD_BUG_ON(offsetof(union irq_stack_union, stack_canary) != 40); /* * We both use the random pool and the current TSC as a source @@ -32,7 +32,7 @@ static __always_inline void boot_init_stack_canary(void) canary += tsc + (tsc << 32UL); current->stack_canary = canary; - write_pda(stack_canary, canary); + percpu_write(irq_stack_union.stack_canary, canary); } #endif diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h index b77bd8bd3cc..52eb748a68a 100644 --- a/arch/x86/include/asm/system.h +++ b/arch/x86/include/asm/system.h @@ -89,10 +89,10 @@ do { \ #ifdef CONFIG_CC_STACKPROTECTOR #define __switch_canary \ "movq %P[task_canary](%%rsi),%%r8\n\t" \ - "movq %%r8,%%gs:%P[pda_canary]\n\t" + "movq %%r8,%%gs:%P[gs_canary]\n\t" #define __switch_canary_param \ , [task_canary] "i" (offsetof(struct task_struct, stack_canary)) \ - , [pda_canary] "i" (offsetof(struct x8664_pda, stack_canary)) + , [gs_canary] "i" (offsetof(union irq_stack_union, stack_canary)) #else /* CC_STACKPROTECTOR */ #define __switch_canary #define __switch_canary_param diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index 64c834a39aa..94f9c8b39d2 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c @@ -48,10 +48,6 @@ int main(void) #endif BLANK(); #undef ENTRY -#define ENTRY(entry) DEFINE(pda_ ## entry, offsetof(struct x8664_pda, entry)) - DEFINE(pda_size, sizeof(struct x8664_pda)); - BLANK(); -#undef ENTRY #ifdef CONFIG_PARAVIRT BLANK(); OFFSET(PARAVIRT_enabled, pv_info, paravirt_enabled); diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index f83a4d6160f..098934e72a1 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -881,12 +881,13 @@ __setup("clearcpuid=", setup_disablecpuid); #ifdef CONFIG_X86_64 struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table }; -DEFINE_PER_CPU_PAGE_ALIGNED(char[IRQ_STACK_SIZE], irq_stack); +DEFINE_PER_CPU_FIRST(union irq_stack_union, + irq_stack_union) __aligned(PAGE_SIZE); #ifdef CONFIG_SMP DEFINE_PER_CPU(char *, irq_stack_ptr); /* will be set during per cpu init */ #else DEFINE_PER_CPU(char *, irq_stack_ptr) = - per_cpu_var(irq_stack) + IRQ_STACK_SIZE - 64; + per_cpu_var(irq_stack_union.irq_stack) + IRQ_STACK_SIZE - 64; #endif DEFINE_PER_CPU(unsigned long, kernel_stack) = @@ -960,7 +961,7 @@ void __cpuinit cpu_init(void) loadsegment(fs, 0); loadsegment(gs, 0); - load_pda_offset(cpu); + load_gs_base(cpu); #ifdef CONFIG_NUMA if (cpu != 0 && percpu_read(node_number) == 0 && diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 98ea26a2fca..a0a2b5ca9b7 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -242,13 +242,10 @@ ENTRY(secondary_startup_64) /* Set up %gs. * - * On SMP, %gs should point to the per-cpu area. For initial - * boot, make %gs point to the init data section. For a - * secondary CPU,initial_gs should be set to its pda address - * before the CPU runs this code. - * - * On UP, initial_gs points to PER_CPU_VAR(__pda) and doesn't - * change. + * The base of %gs always points to the bottom of the irqstack + * union. If the stack protector canary is enabled, it is + * located at %gs:40. Note that, on SMP, the boot cpu uses + * init data section till per cpu areas are set up. */ movl $MSR_GS_BASE,%ecx movq initial_gs(%rip),%rax @@ -281,7 +278,7 @@ ENTRY(secondary_startup_64) #ifdef CONFIG_SMP .quad __per_cpu_load #else - .quad PER_CPU_VAR(__pda) + .quad PER_CPU_VAR(irq_stack_union) #endif __FINITDATA diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index efbafbbff58..90b8e154bb5 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -77,30 +77,6 @@ static void __init setup_node_to_cpumask_map(void); static inline void setup_node_to_cpumask_map(void) { } #endif -/* - * Define load_pda_offset() and per-cpu __pda for x86_64. - * load_pda_offset() is responsible for loading the offset of pda into - * %gs. - * - * On SMP, pda offset also duals as percpu base address and thus it - * should be at the start of per-cpu area. To achieve this, it's - * preallocated in vmlinux_64.lds.S directly instead of using - * DEFINE_PER_CPU(). - */ -#ifdef CONFIG_X86_64 -void __cpuinit load_pda_offset(int cpu) -{ - /* Memory clobbers used to order pda/percpu accesses */ - mb(); - wrmsrl(MSR_GS_BASE, cpu_pda(cpu)); - mb(); -} -#ifndef CONFIG_SMP -DEFINE_PER_CPU(struct x8664_pda, __pda); -#endif -EXPORT_PER_CPU_SYMBOL(__pda); -#endif /* CONFIG_SMP && CONFIG_X86_64 */ - #ifdef CONFIG_X86_64 /* correctly size the local cpu masks */ @@ -207,15 +183,13 @@ void __init setup_per_cpu_areas(void) per_cpu(cpu_number, cpu) = cpu; #ifdef CONFIG_X86_64 per_cpu(irq_stack_ptr, cpu) = - (char *)per_cpu(irq_stack, cpu) + IRQ_STACK_SIZE - 64; + per_cpu(irq_stack_union.irq_stack, cpu) + IRQ_STACK_SIZE - 64; /* - * CPU0 modified pda in the init data area, reload pda - * offset for CPU0 and clear the area for others. + * Up to this point, CPU0 has been using .data.init + * area. Reload %gs offset for CPU0. */ if (cpu == 0) - load_pda_offset(0); - else - memset(cpu_pda(cpu), 0, sizeof(*cpu_pda(cpu))); + load_gs_base(cpu); #endif DBG("PERCPU: cpu %4d %p\n", cpu, ptr); diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S index a09abb8fb97..c9740996430 100644 --- a/arch/x86/kernel/vmlinux_64.lds.S +++ b/arch/x86/kernel/vmlinux_64.lds.S @@ -220,8 +220,7 @@ SECTIONS * so that it can be accessed as a percpu variable. */ . = ALIGN(PAGE_SIZE); - PERCPU_VADDR_PREALLOC(0, :percpu, pda_size) - per_cpu____pda = __per_cpu_start; + PERCPU_VADDR(0, :percpu) #else PERCPU(PAGE_SIZE) #endif @@ -262,3 +261,8 @@ SECTIONS */ ASSERT((_end - _text <= KERNEL_IMAGE_SIZE), "kernel image bigger than KERNEL_IMAGE_SIZE") + +#ifdef CONFIG_SMP +ASSERT((per_cpu__irq_stack_union == 0), + "irq_stack_union is not at start of per-cpu area"); +#endif -- GitLab From 0d974d4592708f85044751817da4b7016e1b0602 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Sun, 18 Jan 2009 19:52:25 -0500 Subject: [PATCH 0227/4982] x86: remove pda.h Impact: cleanup Signed-off-by: Brian Gerst --- arch/x86/include/asm/pda.h | 39 ------------------------------- arch/x86/include/asm/pgtable_64.h | 1 - arch/x86/include/asm/smp.h | 1 - arch/x86/kernel/asm-offsets_64.c | 1 - arch/x86/kernel/cpu/common.c | 1 - arch/x86/kernel/process_64.c | 1 - arch/x86/kernel/traps.c | 1 - 7 files changed, 45 deletions(-) delete mode 100644 arch/x86/include/asm/pda.h diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h deleted file mode 100644 index ba46416634f..00000000000 --- a/arch/x86/include/asm/pda.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef _ASM_X86_PDA_H -#define _ASM_X86_PDA_H - -#ifndef __ASSEMBLY__ -#include -#include -#include -#include -#include -#include - -/* Per processor datastructure. %gs points to it while the kernel runs */ -struct x8664_pda { - unsigned long unused1; - unsigned long unused2; - unsigned long unused3; - unsigned long unused4; - int unused5; - unsigned int unused6; /* 36 was cpunumber */ - short in_bootmem; /* pda lives in bootmem */ -} ____cacheline_aligned_in_smp; - -DECLARE_PER_CPU(struct x8664_pda, __pda); - -#define cpu_pda(cpu) (&per_cpu(__pda, cpu)) - -#define read_pda(field) percpu_read(__pda.field) -#define write_pda(field, val) percpu_write(__pda.field, val) -#define add_pda(field, val) percpu_add(__pda.field, val) -#define sub_pda(field, val) percpu_sub(__pda.field, val) -#define or_pda(field, val) percpu_or(__pda.field, val) - -/* This is not atomic against other CPUs -- CPU preemption needs to be off */ -#define test_and_clear_bit_pda(bit, field) \ - x86_test_and_clear_bit_percpu(bit, __pda.field) - -#endif - -#endif /* _ASM_X86_PDA_H */ diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index ba09289acca..1df9637dfda 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -11,7 +11,6 @@ #include #include #include -#include extern pud_t level3_kernel_pgt[512]; extern pud_t level3_ident_pgt[512]; diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index 68636e767a9..45ef8a1b9d7 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -15,7 +15,6 @@ # include # endif #endif -#include #include #include diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index 94f9c8b39d2..8793ab33e2c 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 098934e72a1..3887fcf6e51 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -30,7 +30,6 @@ #include #endif -#include #include #include #include diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 088bc9a0f82..c422eebb0c5 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 98c2d055284..ed5aee5f3fc 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -59,7 +59,6 @@ #ifdef CONFIG_X86_64 #include #include -#include #else #include #include -- GitLab From 6b7c38d55587f43bcd2cbce3a98b1c0826982090 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 19 Jan 2009 12:21:28 +0900 Subject: [PATCH 0228/4982] linker script: kill PERCPU_VADDR_PREALLOC() Impact: cleanup With .data.percpu.first in place, PERCPU_VADDR_PREALLOC() is no longer necessary. Kill it. Signed-off-by: Tejun Heo --- include/asm-generic/vmlinux.lds.h | 45 ++++++------------------------- 1 file changed, 8 insertions(+), 37 deletions(-) diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 32bbf50d305..53e21f36a80 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -430,22 +430,10 @@ *(.initcall7.init) \ *(.initcall7s.init) -#define PERCPU_PROLOG(vaddr) \ - VMLINUX_SYMBOL(__per_cpu_load) = .; \ - .data.percpu vaddr : AT(VMLINUX_SYMBOL(__per_cpu_load) \ - - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__per_cpu_start) = .; - -#define PERCPU_EPILOG(phdr) \ - VMLINUX_SYMBOL(__per_cpu_end) = .; \ - } phdr \ - . = VMLINUX_SYMBOL(__per_cpu_load) + SIZEOF(.data.percpu); - /** - * PERCPU_VADDR_PREALLOC - define output section for percpu area with prealloc + * PERCPU_VADDR - define output section for percpu area * @vaddr: explicit base address (optional) * @phdr: destination PHDR (optional) - * @prealloc: the size of prealloc area * * Macro which expands to output section for percpu area. If @vaddr * is not blank, it specifies explicit base address and all percpu @@ -457,40 +445,23 @@ * section in the linker script will go there too. @phdr should have * a leading colon. * - * If @prealloc is non-zero, the specified number of bytes will be - * reserved at the start of percpu area. As the prealloc area is - * likely to break alignment, this macro puts areas in increasing - * alignment order. - * * This macro defines three symbols, __per_cpu_load, __per_cpu_start * and __per_cpu_end. The first one is the vaddr of loaded percpu * init data. __per_cpu_start equals @vaddr and __per_cpu_end is the * end offset. */ -#define PERCPU_VADDR_PREALLOC(vaddr, segment, prealloc) \ - PERCPU_PROLOG(vaddr) \ - . += prealloc; \ - *(.data.percpu) \ - *(.data.percpu.shared_aligned) \ - *(.data.percpu.page_aligned) \ - PERCPU_EPILOG(segment) - -/** - * PERCPU_VADDR - define output section for percpu area - * @vaddr: explicit base address (optional) - * @phdr: destination PHDR (optional) - * - * Macro which expands to output section for percpu area. Mostly - * identical to PERCPU_VADDR_PREALLOC(@vaddr, @phdr, 0) other than - * using slighly different layout. - */ #define PERCPU_VADDR(vaddr, phdr) \ - PERCPU_PROLOG(vaddr) \ + VMLINUX_SYMBOL(__per_cpu_load) = .; \ + .data.percpu vaddr : AT(VMLINUX_SYMBOL(__per_cpu_load) \ + - LOAD_OFFSET) { \ + VMLINUX_SYMBOL(__per_cpu_start) = .; \ *(.data.percpu.first) \ *(.data.percpu.page_aligned) \ *(.data.percpu) \ *(.data.percpu.shared_aligned) \ - PERCPU_EPILOG(phdr) + VMLINUX_SYMBOL(__per_cpu_end) = .; \ + } phdr \ + . = VMLINUX_SYMBOL(__per_cpu_load) + SIZEOF(.data.percpu); /** * PERCPU - define output section for percpu area, simple version -- GitLab From 5766b842b23c6b40935a5f3bd435b2bcdaff2143 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 20 Jan 2009 09:13:15 +0100 Subject: [PATCH 0229/4982] x86, cpumask: fix tlb flush race Impact: fix bootup crash The cpumask is now passed in as a reference to mm->cpu_vm_mask, not on the stack - hence it is not constant anymore during the TLB flush. That way it could race and some static sanity checks would trigger: [ 238.154287] ------------[ cut here ]------------ [ 238.156039] kernel BUG at arch/x86/kernel/tlb_32.c:130! [ 238.156039] invalid opcode: 0000 [#1] SMP [ 238.156039] last sysfs file: /sys/class/net/eth2/address [ 238.156039] Modules linked in: [ 238.156039] [ 238.156039] Pid: 6493, comm: ifup-eth Not tainted (2.6.29-rc2-tip #1) P4DC6 [ 238.156039] EIP: 0060:[] EFLAGS: 00010202 CPU: 2 [ 238.156039] EIP is at native_flush_tlb_others+0x35/0x158 [ 238.156039] EAX: c0ef972c EBX: f6143301 ECX: 00000000 EDX: 00000000 [ 238.156039] ESI: f61433a8 EDI: f6143200 EBP: f34f3e00 ESP: f34f3df0 [ 238.156039] DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 [ 238.156039] Process ifup-eth (pid: 6493, ti=f34f2000 task=f399ab00 task.ti=f34f2000) [ 238.156039] Stack: [ 238.156039] ffffffff f61433a8 ffffffff f6143200 f34f3e18 c0118e9c 00000000 f6143200 [ 238.156039] f61433a8 f5bec738 f34f3e28 c0119435 c2b5b830 f6143200 f34f3e34 c01c2dc3 [ 238.156039] bffd9000 f34f3e60 c01c3051 00000000 ffffffff f34f3e4c 00000000 00000071 [ 238.156039] Call Trace: [ 238.156039] [] ? flush_tlb_others+0x52/0x5b [ 238.156039] [] ? flush_tlb_mm+0x7f/0x8b [ 238.156039] [] ? tlb_finish_mmu+0x2d/0x55 [ 238.156039] [] ? exit_mmap+0x124/0x170 [ 238.156039] [] ? mmput+0x40/0xf5 [ 238.156039] [] ? flush_old_exec+0x640/0x94b [ 238.156039] [] ? fsnotify_access+0x37/0x39 [ 238.156039] [] ? kernel_read+0x39/0x4b [ 238.156039] [] ? load_elf_binary+0x4a1/0x11bb [ 238.156039] [] ? might_fault+0x51/0x9c [ 238.156039] [] ? paravirt_read_tsc+0x20/0x4f [ 238.156039] [] ? native_sched_clock+0x5d/0x60 [ 238.156039] [] ? search_binary_handler+0xab/0x2c4 [ 238.156039] [] ? load_elf_binary+0x0/0x11bb [ 238.156039] [] ? _raw_read_unlock+0x21/0x46 [ 238.156039] [] ? load_elf_binary+0x0/0x11bb [ 238.156039] [] ? search_binary_handler+0xb2/0x2c4 [ 238.156039] [] ? do_execve+0x21c/0x2ee [ 238.156039] [] ? sys_execve+0x51/0x8c [ 238.156039] [] ? sysenter_do_call+0x12/0x43 Fix it by not assuming that the cpumask is constant. Signed-off-by: Ingo Molnar --- arch/x86/kernel/tlb_32.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/tlb_32.c b/arch/x86/kernel/tlb_32.c index ec53818f4e3..d37bbfcb813 100644 --- a/arch/x86/kernel/tlb_32.c +++ b/arch/x86/kernel/tlb_32.c @@ -125,9 +125,8 @@ void native_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm, unsigned long va) { /* - * - mask must exist :) + * mm must exist :) */ - BUG_ON(cpumask_empty(cpumask)); BUG_ON(!mm); /* @@ -138,14 +137,18 @@ void native_flush_tlb_others(const struct cpumask *cpumask, spin_lock(&tlbstate_lock); cpumask_andnot(flush_cpumask, cpumask, cpumask_of(smp_processor_id())); -#ifdef CONFIG_HOTPLUG_CPU - /* If a CPU which we ran on has gone down, OK. */ cpumask_and(flush_cpumask, flush_cpumask, cpu_online_mask); + + /* + * If a task whose mm mask we are looking at has descheduled and + * has cleared its presence from the mask, or if a CPU which we ran + * on has gone down then there might be no flush work left: + */ if (unlikely(cpumask_empty(flush_cpumask))) { spin_unlock(&tlbstate_lock); return; } -#endif + flush_mm = mm; flush_va = va; -- GitLab From 92181f190b649f7ef2b79cbf5c00f26ccc66da2a Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Tue, 20 Jan 2009 04:24:26 +0100 Subject: [PATCH 0230/4982] x86: optimise x86's do_page_fault (C entry point for the page fault path) Impact: cleanup, restructure code to improve assembly gcc isn't _all_ that smart about spilling registers to stack or reusing stack slots, even with branch annotations. do_page_fault contained a lot of functionality, so split unlikely paths into their own functions, and mark them as noinline just to be sure. I consider this actually to be somewhat of a cleanup too: the main function now contains about half the number of lines so the normal path is easier to read, while the error cases are also nicely split away. Also, ensure the order of arguments to functions is always the same: regs, addr, error_code. This can reduce code size a tiny bit, and just looks neater too. And add a couple of branch annotations. Before: do_page_fault: subq $360, %rsp #, After: do_page_fault: subq $56, %rsp #, bloat-o-meter: add/remove: 8/0 grow/shrink: 0/1 up/down: 2222/-1680 (542) function old new delta __bad_area_nosemaphore - 506 +506 no_context - 474 +474 vmalloc_fault - 424 +424 spurious_fault - 358 +358 mm_fault_error - 272 +272 bad_area_access_error - 89 +89 bad_area - 89 +89 bad_area_nosemaphore - 10 +10 do_page_fault 2464 784 -1680 Yes, the total size increases by 542 bytes, due to the extra function calls. But these will very rarely be called (except for vmalloc_fault) in a normal workload. Importantly, do_page_fault is less than 1/3rd it's original size, and touches far less stack. Existing gotos and branch hints did move a lot of the infrequently used text out of the fastpath, but that's even further improved after this patch. Signed-off-by: Nick Piggin Acked-by: Linus Torvalds Signed-off-by: Ingo Molnar --- arch/x86/mm/fault.c | 438 ++++++++++++++++++++++++++------------------ 1 file changed, 256 insertions(+), 182 deletions(-) diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 90dfae511a4..033292dc9e2 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -91,8 +91,8 @@ static inline int notify_page_fault(struct pt_regs *regs) * * Opcode checker based on code by Richard Brunner */ -static int is_prefetch(struct pt_regs *regs, unsigned long addr, - unsigned long error_code) +static int is_prefetch(struct pt_regs *regs, unsigned long error_code, + unsigned long addr) { unsigned char *instr; int scan_more = 1; @@ -409,15 +409,15 @@ static void show_fault_oops(struct pt_regs *regs, unsigned long error_code, } #ifdef CONFIG_X86_64 -static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs, - unsigned long error_code) +static noinline void pgtable_bad(struct pt_regs *regs, + unsigned long error_code, unsigned long address) { unsigned long flags = oops_begin(); int sig = SIGKILL; - struct task_struct *tsk; + struct task_struct *tsk = current; printk(KERN_ALERT "%s: Corrupted page table at address %lx\n", - current->comm, address); + tsk->comm, address); dump_pagetable(address); tsk = current; tsk->thread.cr2 = address; @@ -429,6 +429,190 @@ static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs, } #endif +static noinline void no_context(struct pt_regs *regs, + unsigned long error_code, unsigned long address) +{ + struct task_struct *tsk = current; +#ifdef CONFIG_X86_64 + unsigned long flags; + int sig; +#endif + + /* Are we prepared to handle this kernel fault? */ + if (fixup_exception(regs)) + return; + + /* + * X86_32 + * Valid to do another page fault here, because if this fault + * had been triggered by is_prefetch fixup_exception would have + * handled it. + * + * X86_64 + * Hall of shame of CPU/BIOS bugs. + */ + if (is_prefetch(regs, error_code, address)) + return; + + if (is_errata93(regs, address)) + return; + + /* + * Oops. The kernel tried to access some bad page. We'll have to + * terminate things with extreme prejudice. + */ +#ifdef CONFIG_X86_32 + bust_spinlocks(1); +#else + flags = oops_begin(); +#endif + + show_fault_oops(regs, error_code, address); + + tsk->thread.cr2 = address; + tsk->thread.trap_no = 14; + tsk->thread.error_code = error_code; + +#ifdef CONFIG_X86_32 + die("Oops", regs, error_code); + bust_spinlocks(0); + do_exit(SIGKILL); +#else + sig = SIGKILL; + if (__die("Oops", regs, error_code)) + sig = 0; + /* Executive summary in case the body of the oops scrolled away */ + printk(KERN_EMERG "CR2: %016lx\n", address); + oops_end(flags, regs, sig); +#endif +} + +static void __bad_area_nosemaphore(struct pt_regs *regs, + unsigned long error_code, unsigned long address, + int si_code) +{ + struct task_struct *tsk = current; + + /* User mode accesses just cause a SIGSEGV */ + if (error_code & PF_USER) { + /* + * It's possible to have interrupts off here. + */ + local_irq_enable(); + + /* + * Valid to do another page fault here because this one came + * from user space. + */ + if (is_prefetch(regs, error_code, address)) + return; + + if (is_errata100(regs, address)) + return; + + if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) && + printk_ratelimit()) { + printk( + "%s%s[%d]: segfault at %lx ip %p sp %p error %lx", + task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, + tsk->comm, task_pid_nr(tsk), address, + (void *) regs->ip, (void *) regs->sp, error_code); + print_vma_addr(" in ", regs->ip); + printk("\n"); + } + + tsk->thread.cr2 = address; + /* Kernel addresses are always protection faults */ + tsk->thread.error_code = error_code | (address >= TASK_SIZE); + tsk->thread.trap_no = 14; + force_sig_info_fault(SIGSEGV, si_code, address, tsk); + return; + } + + if (is_f00f_bug(regs, address)) + return; + + no_context(regs, error_code, address); +} + +static noinline void bad_area_nosemaphore(struct pt_regs *regs, + unsigned long error_code, unsigned long address) +{ + __bad_area_nosemaphore(regs, error_code, address, SEGV_MAPERR); +} + +static void __bad_area(struct pt_regs *regs, + unsigned long error_code, unsigned long address, + int si_code) +{ + struct mm_struct *mm = current->mm; + + /* + * Something tried to access memory that isn't in our memory map.. + * Fix it, but check if it's kernel or user first.. + */ + up_read(&mm->mmap_sem); + + __bad_area_nosemaphore(regs, error_code, address, si_code); +} + +static noinline void bad_area(struct pt_regs *regs, + unsigned long error_code, unsigned long address) +{ + __bad_area(regs, error_code, address, SEGV_MAPERR); +} + +static noinline void bad_area_access_error(struct pt_regs *regs, + unsigned long error_code, unsigned long address) +{ + __bad_area(regs, error_code, address, SEGV_ACCERR); +} + +/* TODO: fixup for "mm-invoke-oom-killer-from-page-fault.patch" */ +static void out_of_memory(struct pt_regs *regs, + unsigned long error_code, unsigned long address) +{ + /* + * We ran out of memory, call the OOM killer, and return the userspace + * (which will retry the fault, or kill us if we got oom-killed). + */ + up_read(¤t->mm->mmap_sem); + pagefault_out_of_memory(); +} + +static void do_sigbus(struct pt_regs *regs, + unsigned long error_code, unsigned long address) +{ + struct task_struct *tsk = current; + struct mm_struct *mm = tsk->mm; + + up_read(&mm->mmap_sem); + + /* Kernel mode? Handle exceptions or die */ + if (!(error_code & PF_USER)) + no_context(regs, error_code, address); +#ifdef CONFIG_X86_32 + /* User space => ok to do another page fault */ + if (is_prefetch(regs, error_code, address)) + return; +#endif + tsk->thread.cr2 = address; + tsk->thread.error_code = error_code; + tsk->thread.trap_no = 14; + force_sig_info_fault(SIGBUS, BUS_ADRERR, address, tsk); +} + +static noinline void mm_fault_error(struct pt_regs *regs, + unsigned long error_code, unsigned long address, unsigned int fault) +{ + if (fault & VM_FAULT_OOM) + out_of_memory(regs, error_code, address); + else if (fault & VM_FAULT_SIGBUS) + do_sigbus(regs, error_code, address); + else + BUG(); +} + static int spurious_fault_check(unsigned long error_code, pte_t *pte) { if ((error_code & PF_WRITE) && !pte_write(*pte)) @@ -448,8 +632,8 @@ static int spurious_fault_check(unsigned long error_code, pte_t *pte) * There are no security implications to leaving a stale TLB when * increasing the permissions on a page. */ -static int spurious_fault(unsigned long address, - unsigned long error_code) +static noinline int spurious_fault(unsigned long error_code, + unsigned long address) { pgd_t *pgd; pud_t *pud; @@ -494,7 +678,7 @@ static int spurious_fault(unsigned long address, * * This assumes no large pages in there. */ -static int vmalloc_fault(unsigned long address) +static noinline int vmalloc_fault(unsigned long address) { #ifdef CONFIG_X86_32 unsigned long pgd_paddr; @@ -573,6 +757,25 @@ static int vmalloc_fault(unsigned long address) int show_unhandled_signals = 1; +static inline int access_error(unsigned long error_code, int write, + struct vm_area_struct *vma) +{ + if (write) { + /* write, present and write, not present */ + if (unlikely(!(vma->vm_flags & VM_WRITE))) + return 1; + } else if (unlikely(error_code & PF_PROT)) { + /* read, present */ + return 1; + } else { + /* read, not present */ + if (unlikely(!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))) + return 1; + } + + return 0; +} + /* * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate @@ -583,16 +786,12 @@ asmlinkage #endif void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) { + unsigned long address; struct task_struct *tsk; struct mm_struct *mm; struct vm_area_struct *vma; - unsigned long address; - int write, si_code; + int write; int fault; -#ifdef CONFIG_X86_64 - unsigned long flags; - int sig; -#endif tsk = current; mm = tsk->mm; @@ -601,9 +800,7 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) /* get the address */ address = read_cr2(); - si_code = SEGV_MAPERR; - - if (notify_page_fault(regs)) + if (unlikely(notify_page_fault(regs))) return; if (unlikely(kmmio_fault(regs, address))) return; @@ -631,17 +828,17 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) return; /* Can handle a stale RO->RW TLB */ - if (spurious_fault(address, error_code)) + if (spurious_fault(error_code, address)) return; /* * Don't take the mm semaphore here. If we fixup a prefetch * fault we could otherwise deadlock. */ - goto bad_area_nosemaphore; + bad_area_nosemaphore(regs, error_code, address); + return; } - /* * It's safe to allow irq's after cr2 has been saved and the * vmalloc fault has been handled. @@ -657,15 +854,17 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) #ifdef CONFIG_X86_64 if (unlikely(error_code & PF_RSVD)) - pgtable_bad(address, regs, error_code); + pgtable_bad(regs, error_code, address); #endif /* * If we're in an interrupt, have no user context or are running in an * atomic region then we must not take the fault. */ - if (unlikely(in_atomic() || !mm)) - goto bad_area_nosemaphore; + if (unlikely(in_atomic() || !mm)) { + bad_area_nosemaphore(regs, error_code, address); + return; + } /* * When running in the kernel we expect faults to occur only to @@ -683,20 +882,26 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) * source. If this is invalid we can skip the address space check, * thus avoiding the deadlock. */ - if (!down_read_trylock(&mm->mmap_sem)) { + if (unlikely(!down_read_trylock(&mm->mmap_sem))) { if ((error_code & PF_USER) == 0 && - !search_exception_tables(regs->ip)) - goto bad_area_nosemaphore; + !search_exception_tables(regs->ip)) { + bad_area_nosemaphore(regs, error_code, address); + return; + } down_read(&mm->mmap_sem); } vma = find_vma(mm, address); - if (!vma) - goto bad_area; - if (vma->vm_start <= address) + if (unlikely(!vma)) { + bad_area(regs, error_code, address); + return; + } + if (likely(vma->vm_start <= address)) goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; + if (unlikely(!(vma->vm_flags & VM_GROWSDOWN))) { + bad_area(regs, error_code, address); + return; + } if (error_code & PF_USER) { /* * Accessing the stack below %sp is always a bug. @@ -704,31 +909,25 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) * and pusha to work. ("enter $65535,$31" pushes * 32 pointers and then decrements %sp by 65535.) */ - if (address + 65536 + 32 * sizeof(unsigned long) < regs->sp) - goto bad_area; + if (unlikely(address + 65536 + 32 * sizeof(unsigned long) < regs->sp)) { + bad_area(regs, error_code, address); + return; + } } - if (expand_stack(vma, address)) - goto bad_area; -/* - * Ok, we have a good vm_area for this memory access, so - * we can handle it.. - */ + if (unlikely(expand_stack(vma, address))) { + bad_area(regs, error_code, address); + return; + } + + /* + * Ok, we have a good vm_area for this memory access, so + * we can handle it.. + */ good_area: - si_code = SEGV_ACCERR; - write = 0; - switch (error_code & (PF_PROT|PF_WRITE)) { - default: /* 3: write, present */ - /* fall through */ - case PF_WRITE: /* write, not present */ - if (!(vma->vm_flags & VM_WRITE)) - goto bad_area; - write++; - break; - case PF_PROT: /* read, present */ - goto bad_area; - case 0: /* read, not present */ - if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) - goto bad_area; + write = error_code & PF_WRITE; + if (unlikely(access_error(error_code, write, vma))) { + bad_area_access_error(regs, error_code, address); + return; } /* @@ -738,11 +937,8 @@ good_area: */ fault = handle_mm_fault(mm, vma, address, write); if (unlikely(fault & VM_FAULT_ERROR)) { - if (fault & VM_FAULT_OOM) - goto out_of_memory; - else if (fault & VM_FAULT_SIGBUS) - goto do_sigbus; - BUG(); + mm_fault_error(regs, error_code, address, fault); + return; } if (fault & VM_FAULT_MAJOR) tsk->maj_flt++; @@ -760,128 +956,6 @@ good_area: } #endif up_read(&mm->mmap_sem); - return; - -/* - * Something tried to access memory that isn't in our memory map.. - * Fix it, but check if it's kernel or user first.. - */ -bad_area: - up_read(&mm->mmap_sem); - -bad_area_nosemaphore: - /* User mode accesses just cause a SIGSEGV */ - if (error_code & PF_USER) { - /* - * It's possible to have interrupts off here. - */ - local_irq_enable(); - - /* - * Valid to do another page fault here because this one came - * from user space. - */ - if (is_prefetch(regs, address, error_code)) - return; - - if (is_errata100(regs, address)) - return; - - if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) && - printk_ratelimit()) { - printk( - "%s%s[%d]: segfault at %lx ip %p sp %p error %lx", - task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, - tsk->comm, task_pid_nr(tsk), address, - (void *) regs->ip, (void *) regs->sp, error_code); - print_vma_addr(" in ", regs->ip); - printk("\n"); - } - - tsk->thread.cr2 = address; - /* Kernel addresses are always protection faults */ - tsk->thread.error_code = error_code | (address >= TASK_SIZE); - tsk->thread.trap_no = 14; - force_sig_info_fault(SIGSEGV, si_code, address, tsk); - return; - } - - if (is_f00f_bug(regs, address)) - return; - -no_context: - /* Are we prepared to handle this kernel fault? */ - if (fixup_exception(regs)) - return; - - /* - * X86_32 - * Valid to do another page fault here, because if this fault - * had been triggered by is_prefetch fixup_exception would have - * handled it. - * - * X86_64 - * Hall of shame of CPU/BIOS bugs. - */ - if (is_prefetch(regs, address, error_code)) - return; - - if (is_errata93(regs, address)) - return; - -/* - * Oops. The kernel tried to access some bad page. We'll have to - * terminate things with extreme prejudice. - */ -#ifdef CONFIG_X86_32 - bust_spinlocks(1); -#else - flags = oops_begin(); -#endif - - show_fault_oops(regs, error_code, address); - - tsk->thread.cr2 = address; - tsk->thread.trap_no = 14; - tsk->thread.error_code = error_code; - -#ifdef CONFIG_X86_32 - die("Oops", regs, error_code); - bust_spinlocks(0); - do_exit(SIGKILL); -#else - sig = SIGKILL; - if (__die("Oops", regs, error_code)) - sig = 0; - /* Executive summary in case the body of the oops scrolled away */ - printk(KERN_EMERG "CR2: %016lx\n", address); - oops_end(flags, regs, sig); -#endif - -out_of_memory: - /* - * We ran out of memory, call the OOM killer, and return the userspace - * (which will retry the fault, or kill us if we got oom-killed). - */ - up_read(&mm->mmap_sem); - pagefault_out_of_memory(); - return; - -do_sigbus: - up_read(&mm->mmap_sem); - - /* Kernel mode? Handle exceptions or die */ - if (!(error_code & PF_USER)) - goto no_context; -#ifdef CONFIG_X86_32 - /* User space => ok to do another page fault */ - if (is_prefetch(regs, address, error_code)) - return; -#endif - tsk->thread.cr2 = address; - tsk->thread.error_code = error_code; - tsk->thread.trap_no = 14; - force_sig_info_fault(SIGBUS, BUS_ADRERR, address, tsk); } DEFINE_SPINLOCK(pgd_lock); -- GitLab From 29fdbec2dcb1ce364812778271056aa9516ff3ed Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 20 Jan 2009 13:07:55 +0100 Subject: [PATCH 0231/4982] ALSA: hda - Add extra volume offset to standard volume amp macros Added the volume offset to base for the standard volume controls to handle elements with too big volume scales like -96dB..0dB. For such elements, you can set the base volume to reduce the range. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 45 ++++++++++++++++++++++++++++++++------- sound/pci/hda/hda_local.h | 5 ++++- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index b7bba7dc7cf..0cf2424ada6 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1119,6 +1119,7 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, u16 nid = get_amp_nid(kcontrol); u8 chs = get_amp_channels(kcontrol); int dir = get_amp_direction(kcontrol); + unsigned int ofs = get_amp_offset(kcontrol); u32 caps; caps = query_amp_caps(codec, nid, dir); @@ -1130,6 +1131,8 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, kcontrol->id.name); return -EINVAL; } + if (ofs < caps) + caps -= ofs; uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = chs == 3 ? 2 : 1; uinfo->value.integer.min = 0; @@ -1138,6 +1141,32 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, } EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info); + +static inline unsigned int +read_amp_value(struct hda_codec *codec, hda_nid_t nid, + int ch, int dir, int idx, unsigned int ofs) +{ + unsigned int val; + val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx); + val &= HDA_AMP_VOLMASK; + if (val >= ofs) + val -= ofs; + else + val = 0; + return val; +} + +static inline int +update_amp_value(struct hda_codec *codec, hda_nid_t nid, + int ch, int dir, int idx, unsigned int ofs, + unsigned int val) +{ + if (val > 0) + val += ofs; + return snd_hda_codec_amp_update(codec, nid, ch, dir, idx, + HDA_AMP_VOLMASK, val); +} + int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1146,14 +1175,13 @@ int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, int chs = get_amp_channels(kcontrol); int dir = get_amp_direction(kcontrol); int idx = get_amp_index(kcontrol); + unsigned int ofs = get_amp_offset(kcontrol); long *valp = ucontrol->value.integer.value; if (chs & 1) - *valp++ = snd_hda_codec_amp_read(codec, nid, 0, dir, idx) - & HDA_AMP_VOLMASK; + *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs); if (chs & 2) - *valp = snd_hda_codec_amp_read(codec, nid, 1, dir, idx) - & HDA_AMP_VOLMASK; + *valp = read_amp_value(codec, nid, 1, dir, idx, ofs); return 0; } EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get); @@ -1166,18 +1194,17 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, int chs = get_amp_channels(kcontrol); int dir = get_amp_direction(kcontrol); int idx = get_amp_index(kcontrol); + unsigned int ofs = get_amp_offset(kcontrol); long *valp = ucontrol->value.integer.value; int change = 0; snd_hda_power_up(codec); if (chs & 1) { - change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, - 0x7f, *valp); + change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp); valp++; } if (chs & 2) - change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, - 0x7f, *valp); + change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp); snd_hda_power_down(codec); return change; } @@ -1189,6 +1216,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = get_amp_nid(kcontrol); int dir = get_amp_direction(kcontrol); + unsigned int ofs = get_amp_offset(kcontrol); u32 caps, val1, val2; if (size < 4 * sizeof(unsigned int)) @@ -1197,6 +1225,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT; val2 = (val2 + 1) * 25; val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); + val1 += ofs; val1 = ((int)val1) * ((int)val2); if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) return -EFAULT; diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 1dd8716c387..d53ce1f8541 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -26,8 +26,10 @@ /* * for mixer controls */ +#define HDA_COMPOSE_AMP_VAL_OFS(nid,chs,idx,dir,ofs) \ + ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19) | ((ofs)<<23)) #define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \ - ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19)) + HDA_COMPOSE_AMP_VAL_OFS(nid, chs, idx, dir, 0) /* mono volume with index (index=0,1,...) (channel=1,2) */ #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ @@ -456,6 +458,7 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec, #define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3) #define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1) #define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) +#define get_amp_offset(kc) (((kc)->private_value >> 23) & 0x3f) /* * CEA Short Audio Descriptor data -- GitLab From 7c7767ebe2fa847c91a0dd5551ca422aba359473 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 20 Jan 2009 15:28:38 +0100 Subject: [PATCH 0232/4982] ALSA: hda - Halve too large volume scales for STAC/IDT codecs STAC/IDT codecs have often too large volume scales such as -96dB, and exposing this as is results in too large scale in percentage representation. This patch adds the check of the volume scale and halves the volume range if it's too large automatically. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 41 +++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index a4d4afe6b4f..c2d4abee3b0 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -166,6 +166,7 @@ struct sigmatel_spec { unsigned int alt_switch: 1; unsigned int hp_detect: 1; unsigned int spdif_mute: 1; + unsigned int check_volume_offset:1; /* gpio lines */ unsigned int eapd_mask; @@ -202,6 +203,8 @@ struct sigmatel_spec { hda_nid_t hp_dacs[5]; hda_nid_t speaker_dacs[5]; + int volume_offset; + /* capture */ hda_nid_t *adc_nids; unsigned int num_adcs; @@ -1297,6 +1300,8 @@ static int stac92xx_build_controls(struct hda_codec *codec) unsigned int vmaster_tlv[4]; snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], HDA_OUTPUT, vmaster_tlv); + /* correct volume offset */ + vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset; err = snd_hda_add_vmaster(codec, "Master Playback Volume", vmaster_tlv, slave_vols); if (err < 0) @@ -2980,14 +2985,34 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec) } /* create volume control/switch for the given prefx type */ -static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_t nid, int chs) +static int create_controls(struct hda_codec *codec, const char *pfx, + hda_nid_t nid, int chs) { + struct sigmatel_spec *spec = codec->spec; char name[32]; int err; + if (!spec->check_volume_offset) { + unsigned int caps, step, nums, db_scale; + caps = query_amp_caps(codec, nid, HDA_OUTPUT); + step = (caps & AC_AMPCAP_STEP_SIZE) >> + AC_AMPCAP_STEP_SIZE_SHIFT; + step = (step + 1) * 25; /* in .01dB unit */ + nums = (caps & AC_AMPCAP_NUM_STEPS) >> + AC_AMPCAP_NUM_STEPS_SHIFT; + db_scale = nums * step; + /* if dB scale is over -64dB, and finer enough, + * let's reduce it to half + */ + if (db_scale > 6400 && nums >= 0x1f) + spec->volume_offset = nums / 2; + spec->check_volume_offset = 1; + } + sprintf(name, "%s Playback Volume", pfx); err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name, - HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); + HDA_COMPOSE_AMP_VAL_OFS(nid, chs, 0, HDA_OUTPUT, + spec->volume_offset)); if (err < 0) return err; sprintf(name, "%s Playback Switch", pfx); @@ -3053,10 +3078,10 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, nid = spec->multiout.dac_nids[i]; if (i == 2) { /* Center/LFE */ - err = create_controls(spec, "Center", nid, 1); + err = create_controls(codec, "Center", nid, 1); if (err < 0) return err; - err = create_controls(spec, "LFE", nid, 2); + err = create_controls(codec, "LFE", nid, 2); if (err < 0) return err; @@ -3084,7 +3109,7 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, break; } } - err = create_controls(spec, name, nid, 3); + err = create_controls(codec, name, nid, 3); if (err < 0) return err; } @@ -3139,7 +3164,7 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, nid = spec->hp_dacs[i]; if (!nid) continue; - err = create_controls(spec, pfxs[nums++], nid, 3); + err = create_controls(codec, pfxs[nums++], nid, 3); if (err < 0) return err; } @@ -3153,7 +3178,7 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, nid = spec->speaker_dacs[i]; if (!nid) continue; - err = create_controls(spec, pfxs[nums++], nid, 3); + err = create_controls(codec, pfxs[nums++], nid, 3); if (err < 0) return err; } @@ -3729,7 +3754,7 @@ static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec, } if (lfe_pin) { - err = create_controls(spec, "LFE", lfe_pin, 1); + err = create_controls(codec, "LFE", lfe_pin, 1); if (err < 0) return err; } -- GitLab From afb33f8c0d7dea8c48ae1c2e3af5b437aa8dd7bb Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Mon, 12 Jan 2009 12:53:45 +0100 Subject: [PATCH 0233/4982] x86: remove byte locks Impact: cleanup Remove byte locks implementation, which was introduced by Jeremy in 8efcbab6 ("paravirt: introduce a "lock-byte" spinlock implementation"), but turned out to be dead code that is not used by any in-kernel virtualization guest (Xen uses its own variant of spinlocks implementation and KVM is not planning to move to byte locks). Signed-off-by: Jiri Kosina Signed-off-by: Ingo Molnar --- arch/x86/include/asm/paravirt.h | 2 - arch/x86/include/asm/spinlock.h | 66 +--------------------------- arch/x86/kernel/paravirt-spinlocks.c | 10 ----- 3 files changed, 2 insertions(+), 76 deletions(-) diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index ba3e2ff6aed..32bc6c2c138 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -1389,8 +1389,6 @@ static inline void __set_fixmap(unsigned /* enum fixed_addresses */ idx, void _paravirt_nop(void); #define paravirt_nop ((void *)_paravirt_nop) -void paravirt_use_bytelocks(void); - #ifdef CONFIG_SMP static inline int __raw_spin_is_locked(struct raw_spinlock *lock) diff --git a/arch/x86/include/asm/spinlock.h b/arch/x86/include/asm/spinlock.h index d17c91981da..2bd6b111a41 100644 --- a/arch/x86/include/asm/spinlock.h +++ b/arch/x86/include/asm/spinlock.h @@ -172,70 +172,8 @@ static inline int __ticket_spin_is_contended(raw_spinlock_t *lock) return (((tmp >> TICKET_SHIFT) - tmp) & ((1 << TICKET_SHIFT) - 1)) > 1; } -#ifdef CONFIG_PARAVIRT -/* - * Define virtualization-friendly old-style lock byte lock, for use in - * pv_lock_ops if desired. - * - * This differs from the pre-2.6.24 spinlock by always using xchgb - * rather than decb to take the lock; this allows it to use a - * zero-initialized lock structure. It also maintains a 1-byte - * contention counter, so that we can implement - * __byte_spin_is_contended. - */ -struct __byte_spinlock { - s8 lock; - s8 spinners; -}; - -static inline int __byte_spin_is_locked(raw_spinlock_t *lock) -{ - struct __byte_spinlock *bl = (struct __byte_spinlock *)lock; - return bl->lock != 0; -} - -static inline int __byte_spin_is_contended(raw_spinlock_t *lock) -{ - struct __byte_spinlock *bl = (struct __byte_spinlock *)lock; - return bl->spinners != 0; -} - -static inline void __byte_spin_lock(raw_spinlock_t *lock) -{ - struct __byte_spinlock *bl = (struct __byte_spinlock *)lock; - s8 val = 1; - - asm("1: xchgb %1, %0\n" - " test %1,%1\n" - " jz 3f\n" - " " LOCK_PREFIX "incb %2\n" - "2: rep;nop\n" - " cmpb $1, %0\n" - " je 2b\n" - " " LOCK_PREFIX "decb %2\n" - " jmp 1b\n" - "3:" - : "+m" (bl->lock), "+q" (val), "+m" (bl->spinners): : "memory"); -} - -static inline int __byte_spin_trylock(raw_spinlock_t *lock) -{ - struct __byte_spinlock *bl = (struct __byte_spinlock *)lock; - u8 old = 1; - - asm("xchgb %1,%0" - : "+m" (bl->lock), "+q" (old) : : "memory"); +#ifndef CONFIG_PARAVIRT - return old == 0; -} - -static inline void __byte_spin_unlock(raw_spinlock_t *lock) -{ - struct __byte_spinlock *bl = (struct __byte_spinlock *)lock; - smp_wmb(); - bl->lock = 0; -} -#else /* !CONFIG_PARAVIRT */ static inline int __raw_spin_is_locked(raw_spinlock_t *lock) { return __ticket_spin_is_locked(lock); @@ -267,7 +205,7 @@ static __always_inline void __raw_spin_lock_flags(raw_spinlock_t *lock, __raw_spin_lock(lock); } -#endif /* CONFIG_PARAVIRT */ +#endif static inline void __raw_spin_unlock_wait(raw_spinlock_t *lock) { diff --git a/arch/x86/kernel/paravirt-spinlocks.c b/arch/x86/kernel/paravirt-spinlocks.c index 95777b0faa7..3a7c5a44082 100644 --- a/arch/x86/kernel/paravirt-spinlocks.c +++ b/arch/x86/kernel/paravirt-spinlocks.c @@ -26,13 +26,3 @@ struct pv_lock_ops pv_lock_ops = { }; EXPORT_SYMBOL(pv_lock_ops); -void __init paravirt_use_bytelocks(void) -{ -#ifdef CONFIG_SMP - pv_lock_ops.spin_is_locked = __byte_spin_is_locked; - pv_lock_ops.spin_is_contended = __byte_spin_is_contended; - pv_lock_ops.spin_lock = __byte_spin_lock; - pv_lock_ops.spin_trylock = __byte_spin_trylock; - pv_lock_ops.spin_unlock = __byte_spin_unlock; -#endif -} -- GitLab From 89ce9e87083216389d2ff5740cc60f835537d8d0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 20 Jan 2009 17:15:57 +0100 Subject: [PATCH 0234/4982] ALSA: hda - Add debug prints for digital I/O pin detections Add the debug prints for digital I/O pin detections in snd_hda_parse_pin_def_config() function. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index b7bba7dc7cf..c03de0bc399 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -3499,6 +3499,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, cfg->hp_pins[1], cfg->hp_pins[2], cfg->hp_pins[3], cfg->hp_pins[4]); snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin); + if (cfg->dig_out_pin) + snd_printd(" dig-out=0x%x\n", cfg->dig_out_pin); snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," " cd=0x%x, aux=0x%x\n", cfg->input_pins[AUTO_PIN_MIC], @@ -3507,6 +3509,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, cfg->input_pins[AUTO_PIN_FRONT_LINE], cfg->input_pins[AUTO_PIN_CD], cfg->input_pins[AUTO_PIN_AUX]); + if (cfg->dig_out_pin) + snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin); return 0; } -- GitLab From 1b52ae701fedf97f9984e73b6a1fe2444230871b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 20 Jan 2009 17:17:29 +0100 Subject: [PATCH 0235/4982] ALSA: hda - Detect non-SPDIF digital I/O Accept non-SPDIF digital I/O pins as the digital pins. These are usually corresponding to HDMI I/O. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index c03de0bc399..2d6f72ca014 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -3390,9 +3390,11 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, cfg->input_pins[AUTO_PIN_AUX] = nid; break; case AC_JACK_SPDIF_OUT: + case AC_JACK_DIG_OTHER_OUT: cfg->dig_out_pin = nid; break; case AC_JACK_SPDIF_IN: + case AC_JACK_DIG_OTHER_IN: cfg->dig_in_pin = nid; break; } -- GitLab From caa10b6e808a4d65eb0306f0006308244f2b8d79 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 20 Jan 2009 17:19:01 +0100 Subject: [PATCH 0236/4982] ALSA: hda - Improve auto-probing of STAC9872 codec Use the standard STAC/IDT auto-probing routine for non-static STAC9872 codec probing. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 58 ++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index a4d4afe6b4f..b6e797d1c21 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -5511,24 +5511,62 @@ static struct snd_pci_quirk stac9872_cfg_tbl[] = { {} }; +static struct snd_kcontrol_new stac9872_mixer[] = { + HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), + HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), + STAC_INPUT_SOURCE(1), + { } /* end */ +}; + +static hda_nid_t stac9872_pin_nids[] = { + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x11, 0x13, 0x14, +}; + +static hda_nid_t stac9872_adc_nids[] = { + 0x8 /*,0x6*/ +}; + +static hda_nid_t stac9872_mux_nids[] = { + 0x15 +}; + static int patch_stac9872(struct hda_codec *codec) { struct sigmatel_spec *spec; - int board_config; - board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS, - stac9872_models, - stac9872_cfg_tbl); - if (board_config < 0) - /* unknown config, let generic-parser do its job... */ - return snd_hda_parse_generic_codec(codec); - spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) return -ENOMEM; - codec->spec = spec; - switch (board_config) { + + spec->board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS, + stac9872_models, + stac9872_cfg_tbl); + if (spec->board_config < 0) { + int err; + + spec->num_pins = ARRAY_SIZE(stac9872_pin_nids); + spec->pin_nids = stac9872_pin_nids; + spec->multiout.dac_nids = spec->dac_nids; + spec->num_adcs = ARRAY_SIZE(stac9872_adc_nids); + spec->adc_nids = stac9872_adc_nids; + spec->num_muxes = ARRAY_SIZE(stac9872_mux_nids); + spec->mux_nids = stac9872_mux_nids; + spec->mixer = stac9872_mixer; + spec->init = vaio_init; + + err = stac92xx_parse_auto_config(codec, 0x10, 0x12); + if (err < 0) { + stac92xx_free(codec); + return -EINVAL; + } + spec->input_mux = &spec->private_imux; + codec->patch_ops = stac92xx_patch_ops; + return 0; + } + + switch (spec->board_config) { case CXD9872RD_VAIO: case STAC9872AK_VAIO: case STAC9872K_VAIO: -- GitLab From 41b5b01afb71226653282951965d5efa9d7b843d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 20 Jan 2009 18:21:23 +0100 Subject: [PATCH 0237/4982] ALSA: hda - Don't break the PCM creation loop Don't break the loop in snd_hda_codec_build_pcms() even if the item has no substreams. It's possible that it's an empty item and the next item containing the valid substreams (e.g. realtek codecs may create the analog and alt-analog but no digitl streams). Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 2d6f72ca014..0129e95672a 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -2613,7 +2613,7 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec) int dev; if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams) - return 0; /* no substreams assigned */ + continue; /* no substreams assigned */ if (!cpcm->pcm) { dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type); -- GitLab From 2297bd6e526ce1469279284ffda9140f8d60ea84 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 20 Jan 2009 18:24:13 +0100 Subject: [PATCH 0238/4982] ALSA: hda - Check HDMI jack types in the auto configuration Add dig_out_type and dig_in_type fields to autocfg struct. A proper HDA_PCM_TYPE_* value is assigned to these fields according to the pin-jack location type value. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 8 ++++++++ sound/pci/hda/hda_local.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 0129e95672a..dd419ce43d9 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -3392,10 +3392,18 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, case AC_JACK_SPDIF_OUT: case AC_JACK_DIG_OTHER_OUT: cfg->dig_out_pin = nid; + if (loc == AC_JACK_LOC_HDMI) + cfg->dig_out_type = HDA_PCM_TYPE_HDMI; + else + cfg->dig_out_type = HDA_PCM_TYPE_SPDIF; break; case AC_JACK_SPDIF_IN: case AC_JACK_DIG_OTHER_IN: cfg->dig_in_pin = nid; + if (loc == AC_JACK_LOC_HDMI) + cfg->dig_in_type = HDA_PCM_TYPE_HDMI; + else + cfg->dig_in_type = HDA_PCM_TYPE_SPDIF; break; } } diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 1dd8716c387..a4ecd77a451 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -355,6 +355,8 @@ struct auto_pin_cfg { hda_nid_t dig_out_pin; hda_nid_t dig_in_pin; hda_nid_t mono_out_pin; + int dig_out_type; /* HDA_PCM_TYPE_XXX */ + int dig_in_type; /* HDA_PCM_TYPE_XXX */ }; #define get_defcfg_connect(cfg) \ -- GitLab From 8c441982fdc00f77b7aa609061c6411f47bcceda Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 20 Jan 2009 18:30:20 +0100 Subject: [PATCH 0239/4982] ALSA: hda - Assign proper digital I/O type for STAC/IDT Assign the proper PCM digital I/O type (HDA_PCM_TYPE_*) for the digital I/O on STAC/IDT codecs. HDA_PCM_TYPE_HDMI is assigned for the HDMI I/O. A similar framework is implemented to patch_realtek.c, but it's not set up and still using only HDA_PCM_TYPE_SPDIF yet. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 6 +++++- sound/pci/hda/patch_sigmatel.c | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 5d249a547fb..4fdae06162e 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -269,6 +269,7 @@ struct alc_spec { * dig_out_nid and hp_nid are optional */ hda_nid_t alt_dac_nid; + int dig_out_type; /* capture */ unsigned int num_adc_nids; @@ -3087,7 +3088,10 @@ static int alc_build_pcms(struct hda_codec *codec) codec->num_pcms = 2; info = spec->pcm_rec + 1; info->name = spec->stream_name_digital; - info->pcm_type = HDA_PCM_TYPE_SPDIF; + if (spec->dig_out_type) + info->pcm_type = spec->dig_out_type; + else + info->pcm_type = HDA_PCM_TYPE_SPDIF; if (spec->multiout.dig_out_nid && spec->stream_digital_playback) { info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback); diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index b6e797d1c21..1dd448e85bc 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -2553,7 +2553,7 @@ static int stac92xx_build_pcms(struct hda_codec *codec) codec->num_pcms++; info++; info->name = "STAC92xx Digital"; - info->pcm_type = HDA_PCM_TYPE_SPDIF; + info->pcm_type = spec->autocfg.dig_out_type; if (spec->multiout.dig_out_nid) { info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback; info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; -- GitLab From e64f14f4e570d6ec5bc88abac92a3a27150756d7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 20 Jan 2009 18:32:55 +0100 Subject: [PATCH 0240/4982] ALSA: hda - Allow digital-only I/O on ALC262 codec Some laptops like VAIO have multiple codecs and uses ALC262 only for the SPIDF output without analog I/O. So far, the codec-parser assumes the presence of analog I/O and returned an error for such a case. This patch adds some hacks to allow the digital-only configuration for ALC262. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 43 +++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4fdae06162e..4cfa78c5439 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -306,6 +306,9 @@ struct alc_spec { unsigned int jack_present: 1; unsigned int master_sw: 1; + /* other flags */ + unsigned int no_analog :1; /* digital I/O only */ + /* for virtual master */ hda_nid_t vmaster_nid; #ifdef CONFIG_SND_HDA_POWER_SAVE @@ -2019,11 +2022,13 @@ static int alc_build_controls(struct hda_codec *codec) spec->multiout.dig_out_nid); if (err < 0) return err; - err = snd_hda_create_spdif_share_sw(codec, - &spec->multiout); - if (err < 0) - return err; - spec->multiout.share_spdif = 1; + if (!spec->no_analog) { + err = snd_hda_create_spdif_share_sw(codec, + &spec->multiout); + if (err < 0) + return err; + spec->multiout.share_spdif = 1; + } } if (spec->dig_in_nid) { err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); @@ -2032,7 +2037,8 @@ static int alc_build_controls(struct hda_codec *codec) } /* if we have no master control, let's create it */ - if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { + if (!spec->no_analog && + !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { unsigned int vmaster_tlv[4]; snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, HDA_OUTPUT, vmaster_tlv); @@ -2041,7 +2047,8 @@ static int alc_build_controls(struct hda_codec *codec) if (err < 0) return err; } - if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { + if (!spec->no_analog && + !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { err = snd_hda_add_vmaster(codec, "Master Playback Switch", NULL, alc_slave_sws); if (err < 0) @@ -3060,6 +3067,9 @@ static int alc_build_pcms(struct hda_codec *codec) codec->num_pcms = 1; codec->pcm_info = info; + if (spec->no_analog) + goto skip_analog; + info->name = spec->stream_name_analog; if (spec->stream_analog_playback) { if (snd_BUG_ON(!spec->multiout.dac_nids)) @@ -3083,6 +3093,7 @@ static int alc_build_pcms(struct hda_codec *codec) } } + skip_analog: /* SPDIF for stream index #1 */ if (spec->multiout.dig_out_nid || spec->dig_in_nid) { codec->num_pcms = 2; @@ -3106,6 +3117,9 @@ static int alc_build_pcms(struct hda_codec *codec) codec->spdif_status_reset = 1; } + if (spec->no_analog) + return 0; + /* If the use of more than one ADC is requested for the current * model, configure a second analog capture-only PCM. */ @@ -10468,8 +10482,14 @@ static int alc262_parse_auto_config(struct hda_codec *codec) alc262_ignore); if (err < 0) return err; - if (!spec->autocfg.line_outs) + if (!spec->autocfg.line_outs) { + if (spec->autocfg.dig_out_pin || spec->autocfg.dig_in_pin) { + spec->multiout.max_channels = 2; + spec->no_analog = 1; + goto dig_only; + } return 0; /* can't find valid BIOS pin config */ + } err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg); if (err < 0) return err; @@ -10479,8 +10499,11 @@ static int alc262_parse_auto_config(struct hda_codec *codec) spec->multiout.max_channels = spec->multiout.num_dacs * 2; - if (spec->autocfg.dig_out_pin) + dig_only: + if (spec->autocfg.dig_out_pin) { spec->multiout.dig_out_nid = ALC262_DIGOUT_NID; + spec->dig_out_type = spec->autocfg.dig_out_type; + } if (spec->autocfg.dig_in_pin) spec->dig_in_nid = ALC262_DIGIN_NID; @@ -10875,7 +10898,7 @@ static int patch_alc262(struct hda_codec *codec) spec->capsrc_nids = alc262_capsrc_nids; } } - if (!spec->cap_mixer) + if (!spec->cap_mixer && !spec->no_analog) set_capture_mixer(spec); spec->vmaster_nid = 0x0c; -- GitLab From 75d91f9bc6d36b8d0ceef1cb75a4ac2b5c8a51d0 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Mon, 19 Jan 2009 11:57:46 -0600 Subject: [PATCH 0241/4982] ASoC: Allow Freescale MPC8610 audio drivers to be compiled as modules Change the Kconfig and Makefile options for Freescale MPC8610 audio drivers so that they can be compiled as modules, and simplify the Kconfig choices so that only the platform is selected. Also fix the naming of the driver files to conform to ALSA standards. [Removed extraneous SND_SOC dependency -- broonie] Signed-off-by: Timur Tabi Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 16 ++++++++-------- sound/soc/fsl/Makefile | 7 +++++-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 95c12b26fe3..c7c78c39cfe 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -1,17 +1,17 @@ config SND_SOC_OF_SIMPLE tristate +# ASoC platform support for the Freescale MPC8610 SOC. This compiles drivers +# for the SSI and the Elo DMA controller. You will still need to select +# a platform driver and a codec driver. config SND_SOC_MPC8610 - bool "ALSA SoC support for the MPC8610 SOC" - depends on MPC8610_HPCD - default y if MPC8610 - help - Say Y if you want to add support for codecs attached to the SSI - device on an MPC8610. + tristate + depends on MPC8610 config SND_SOC_MPC8610_HPCD - bool "ALSA SoC support for the Freescale MPC8610 HPCD board" - depends on SND_SOC_MPC8610 + tristate "ALSA SoC support for the Freescale MPC8610 HPCD board" + depends on MPC8610_HPCD + select SND_SOC_MPC8610 select SND_SOC_CS4270 select SND_SOC_CS4270_VD33_ERRATA default y if MPC8610_HPCD diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 035da4afec3..f85134c8638 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -2,10 +2,13 @@ obj-$(CONFIG_SND_SOC_OF_SIMPLE) += soc-of-simple.o # MPC8610 HPCD Machine Support -obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += mpc8610_hpcd.o +snd-soc-mpc8610-hpcd-objs := mpc8610_hpcd.o +obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += snd-soc-mpc8610-hpcd.o # MPC8610 Platform Support -obj-$(CONFIG_SND_SOC_MPC8610) += fsl_ssi.o fsl_dma.o +snd-soc-fsl-ssi-objs := fsl_ssi.o +snd-soc-fsl-dma-objs := fsl_dma.o +obj-$(CONFIG_SND_SOC_MPC8610) += snd-soc-fsl-ssi.o snd-soc-fsl-dma.o obj-$(CONFIG_SND_SOC_MPC5200_I2S) += mpc5200_psc_i2s.o -- GitLab From 927b0aea93bb324d743e575659e10d6d76818e4b Mon Sep 17 00:00:00 2001 From: Ian Molton Date: Mon, 19 Jan 2009 17:23:11 +0000 Subject: [PATCH 0242/4982] ASoC: Fix WM9705 capture switch name This patch fixes the acpture switch name so that it better reflects its purpose. Signed-off-by: Ian Molton Signed-off-by: Mark Brown --- sound/soc/codecs/wm9705.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index cb26b6a77ff..5e1937ac0b5 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c @@ -57,8 +57,8 @@ static const struct snd_kcontrol_new wm9705_snd_ac97_controls[] = { SOC_DOUBLE("CD Playback Volume", AC97_CD, 8, 0, 31, 1), SOC_SINGLE("Mic Playback Volume", AC97_MIC, 0, 31, 1), SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 6, 1, 0), - SOC_DOUBLE("PCM Capture Volume", AC97_REC_GAIN, 8, 0, 15, 0), - SOC_SINGLE("PCM Capture Switch", AC97_REC_GAIN, 15, 1, 1), + SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 15, 0), + SOC_SINGLE("Capture Switch", AC97_REC_GAIN, 15, 1, 1), }; static const char *wm9705_mic[] = {"Mic 1", "Mic 2"}; -- GitLab From 1e137f929bb490ff615ea475ac3904d58b0cdd5e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 21 Jan 2009 07:41:22 +0100 Subject: [PATCH 0243/4982] ALSA: hda - Clean up old VAIO hack codes for STAC9872 Get rid of old VAIO static hack codes for STAC9872 and use the BIOS auto-parser for all models. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 238 +++------------------------------ 1 file changed, 21 insertions(+), 217 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 775f8581906..dbe8b1201ef 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -5351,172 +5351,12 @@ static int patch_stac9205(struct hda_codec *codec) * STAC9872 hack */ -/* static config for Sony VAIO FE550G and Sony VAIO AR */ -static hda_nid_t vaio_dacs[] = { 0x2 }; -#define VAIO_HP_DAC 0x5 -static hda_nid_t vaio_adcs[] = { 0x8 /*,0x6*/ }; -static hda_nid_t vaio_mux_nids[] = { 0x15 }; - -static struct hda_input_mux vaio_mux = { - .num_items = 3, - .items = { - /* { "HP", 0x0 }, */ - { "Mic Jack", 0x1 }, - { "Internal Mic", 0x2 }, - { "PCM", 0x3 }, - } -}; - -static struct hda_verb vaio_init[] = { - {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */ - {0x0a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | STAC_HP_EVENT}, - {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */ - {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */ - {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */ - {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */ - {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */ - {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */ - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */ - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */ - {} -}; - -static struct hda_verb vaio_ar_init[] = { - {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */ - {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */ - {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */ - {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */ -/* {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },*/ /* Optical Out */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */ +static struct hda_verb stac9872_core_init[] = { {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */ - {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */ - {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */ -/* {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},*/ /* Optical Out */ - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */ {} }; -static struct snd_kcontrol_new vaio_mixer[] = { - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x02, 0, HDA_OUTPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x02, 0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Speaker Playback Volume", 0x05, 0, HDA_OUTPUT), - HDA_CODEC_MUTE("Speaker Playback Switch", 0x05, 0, HDA_OUTPUT), - /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ - HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .count = 1, - .info = stac92xx_mux_enum_info, - .get = stac92xx_mux_enum_get, - .put = stac92xx_mux_enum_put, - }, - {} -}; - -static struct snd_kcontrol_new vaio_ar_mixer[] = { - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x02, 0, HDA_OUTPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x02, 0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Speaker Playback Volume", 0x05, 0, HDA_OUTPUT), - HDA_CODEC_MUTE("Speaker Playback Switch", 0x05, 0, HDA_OUTPUT), - /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ - HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), - /*HDA_CODEC_MUTE("Optical Out Switch", 0x10, 0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Optical Out Volume", 0x10, 0, HDA_OUTPUT),*/ - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .count = 1, - .info = stac92xx_mux_enum_info, - .get = stac92xx_mux_enum_get, - .put = stac92xx_mux_enum_put, - }, - {} -}; - -static struct hda_codec_ops stac9872_patch_ops = { - .build_controls = stac92xx_build_controls, - .build_pcms = stac92xx_build_pcms, - .init = stac92xx_init, - .free = stac92xx_free, -#ifdef SND_HDA_NEEDS_RESUME - .resume = stac92xx_resume, -#endif -}; - -static int stac9872_vaio_init(struct hda_codec *codec) -{ - int err; - - err = stac92xx_init(codec); - if (err < 0) - return err; - if (codec->patch_ops.unsol_event) - codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); - return 0; -} - -static void stac9872_vaio_hp_detect(struct hda_codec *codec, unsigned int res) -{ - if (get_pin_presence(codec, 0x0a)) { - stac92xx_reset_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN); - stac92xx_set_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN); - } else { - stac92xx_reset_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN); - stac92xx_set_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN); - } -} - -static void stac9872_vaio_unsol_event(struct hda_codec *codec, unsigned int res) -{ - switch (res >> 26) { - case STAC_HP_EVENT: - stac9872_vaio_hp_detect(codec, res); - break; - } -} - -static struct hda_codec_ops stac9872_vaio_patch_ops = { - .build_controls = stac92xx_build_controls, - .build_pcms = stac92xx_build_pcms, - .init = stac9872_vaio_init, - .free = stac92xx_free, - .unsol_event = stac9872_vaio_unsol_event, -#ifdef CONFIG_PM - .resume = stac92xx_resume, -#endif -}; - -enum { /* FE and SZ series. id=0x83847661 and subsys=0x104D0700 or 104D1000. */ - CXD9872RD_VAIO, - /* Unknown. id=0x83847662 and subsys=0x104D1200 or 104D1000. */ - STAC9872AK_VAIO, - /* Unknown. id=0x83847661 and subsys=0x104D1200. */ - STAC9872K_VAIO, - /* AR Series. id=0x83847664 and subsys=104D1300 */ - CXD9872AKD_VAIO, - STAC_9872_MODELS, -}; - -static const char *stac9872_models[STAC_9872_MODELS] = { - [CXD9872RD_VAIO] = "vaio", - [CXD9872AKD_VAIO] = "vaio-ar", -}; - -static struct snd_pci_quirk stac9872_cfg_tbl[] = { - SND_PCI_QUIRK(0x104d, 0x81e6, "Sony VAIO F/S", CXD9872RD_VAIO), - SND_PCI_QUIRK(0x104d, 0x81ef, "Sony VAIO F/S", CXD9872RD_VAIO), - SND_PCI_QUIRK(0x104d, 0x81fd, "Sony VAIO AR", CXD9872AKD_VAIO), - SND_PCI_QUIRK(0x104d, 0x8205, "Sony VAIO AR", CXD9872AKD_VAIO), - {} -}; - static struct snd_kcontrol_new stac9872_mixer[] = { HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), @@ -5540,72 +5380,36 @@ static hda_nid_t stac9872_mux_nids[] = { static int patch_stac9872(struct hda_codec *codec) { struct sigmatel_spec *spec; + int err; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) return -ENOMEM; codec->spec = spec; +#if 0 /* no model right now */ spec->board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS, stac9872_models, stac9872_cfg_tbl); - if (spec->board_config < 0) { - int err; - - spec->num_pins = ARRAY_SIZE(stac9872_pin_nids); - spec->pin_nids = stac9872_pin_nids; - spec->multiout.dac_nids = spec->dac_nids; - spec->num_adcs = ARRAY_SIZE(stac9872_adc_nids); - spec->adc_nids = stac9872_adc_nids; - spec->num_muxes = ARRAY_SIZE(stac9872_mux_nids); - spec->mux_nids = stac9872_mux_nids; - spec->mixer = stac9872_mixer; - spec->init = vaio_init; - - err = stac92xx_parse_auto_config(codec, 0x10, 0x12); - if (err < 0) { - stac92xx_free(codec); - return -EINVAL; - } - spec->input_mux = &spec->private_imux; - codec->patch_ops = stac92xx_patch_ops; - return 0; - } - - switch (spec->board_config) { - case CXD9872RD_VAIO: - case STAC9872AK_VAIO: - case STAC9872K_VAIO: - spec->mixer = vaio_mixer; - spec->init = vaio_init; - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = ARRAY_SIZE(vaio_dacs); - spec->multiout.dac_nids = vaio_dacs; - spec->multiout.hp_nid = VAIO_HP_DAC; - spec->num_adcs = ARRAY_SIZE(vaio_adcs); - spec->adc_nids = vaio_adcs; - spec->num_pwrs = 0; - spec->input_mux = &vaio_mux; - spec->mux_nids = vaio_mux_nids; - codec->patch_ops = stac9872_vaio_patch_ops; - break; - - case CXD9872AKD_VAIO: - spec->mixer = vaio_ar_mixer; - spec->init = vaio_ar_init; - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = ARRAY_SIZE(vaio_dacs); - spec->multiout.dac_nids = vaio_dacs; - spec->multiout.hp_nid = VAIO_HP_DAC; - spec->num_adcs = ARRAY_SIZE(vaio_adcs); - spec->num_pwrs = 0; - spec->adc_nids = vaio_adcs; - spec->input_mux = &vaio_mux; - spec->mux_nids = vaio_mux_nids; - codec->patch_ops = stac9872_patch_ops; - break; - } +#endif + spec->num_pins = ARRAY_SIZE(stac9872_pin_nids); + spec->pin_nids = stac9872_pin_nids; + spec->multiout.dac_nids = spec->dac_nids; + spec->num_adcs = ARRAY_SIZE(stac9872_adc_nids); + spec->adc_nids = stac9872_adc_nids; + spec->num_muxes = ARRAY_SIZE(stac9872_mux_nids); + spec->mux_nids = stac9872_mux_nids; + spec->mixer = stac9872_mixer; + spec->init = stac9872_core_init; + + err = stac92xx_parse_auto_config(codec, 0x10, 0x12); + if (err < 0) { + stac92xx_free(codec); + return -EINVAL; + } + spec->input_mux = &spec->private_imux; + codec->patch_ops = stac92xx_patch_ops; return 0; } -- GitLab From 08989930f91e4802b94e03eb54e5385bac112811 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 21 Jan 2009 07:43:23 +0100 Subject: [PATCH 0244/4982] ALSA: hda - Remove old models for STAC9872 from the document Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 64eb1100eec..75914bcdce7 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -352,5 +352,4 @@ STAC92HD83* STAC9872 ======== - vaio Setup for VAIO FE550G/SZ110 - vaio-ar Setup for VAIO AR + N/A -- GitLab From 0f6ff0f06cc126e8dfaa20c8c6da53537e352378 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 20 Nov 2008 00:58:38 +0100 Subject: [PATCH 0245/4982] [ARM] pxa: PalmT5 initial support Signed-off-by: Marek Vasut Signed-off-by: Eric Miao --- MAINTAINERS | 2 +- arch/arm/mach-pxa/Kconfig | 10 + arch/arm/mach-pxa/Makefile | 1 + arch/arm/mach-pxa/include/mach/palmt5.h | 84 ++++ arch/arm/mach-pxa/palmt5.c | 497 ++++++++++++++++++++++++ 5 files changed, 593 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-pxa/include/mach/palmt5.h create mode 100644 arch/arm/mach-pxa/palmt5.c diff --git a/MAINTAINERS b/MAINTAINERS index 3fe4dc2c256..a267659552c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -622,7 +622,7 @@ P: Dirk Opfer M: dirk@opfer-online.de S: Maintained -ARM/PALMTX SUPPORT +ARM/PALMTX,PALMT5 SUPPORT P: Marek Vasut M: marek.vasut@gmail.com W: http://hackndev.com diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 8eea7306f29..9223ba607a7 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -319,6 +319,16 @@ config ARCH_PXA_PALM bool "PXA based Palm PDAs" select HAVE_PWM +config MACH_PALMT5 + bool "Palm Tungsten|T5" + default y + depends on ARCH_PXA_PALM + select PXA27x + select IWMMXT + help + Say Y here if you intend to run this kernel on a Palm Tungsten|T5 + handheld computer. + config MACH_PALMTX bool "Palm T|X" default y diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 7b28bb561d6..0d0afe84ec5 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_MACH_E740) += e740.o obj-$(CONFIG_MACH_E750) += e750.o obj-$(CONFIG_MACH_E400) += e400.o obj-$(CONFIG_MACH_E800) += e800.o +obj-$(CONFIG_MACH_PALMT5) += palmt5.o obj-$(CONFIG_MACH_PALMTX) += palmtx.o obj-$(CONFIG_MACH_PALMZ72) += palmz72.o obj-$(CONFIG_ARCH_VIPER) += viper.o diff --git a/arch/arm/mach-pxa/include/mach/palmt5.h b/arch/arm/mach-pxa/include/mach/palmt5.h new file mode 100644 index 00000000000..94db2881f04 --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/palmt5.h @@ -0,0 +1,84 @@ +/* + * GPIOs and interrupts for Palm Tungsten|T5 Handheld Computer + * + * Authors: Ales Snuparek + * Marek Vasut + * Justin Kendrick + * RichardT5 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef _INCLUDE_PALMT5_H_ +#define _INCLUDE_PALMT5_H_ + +/** HERE ARE GPIOs **/ + +/* GPIOs */ +#define GPIO_NR_PALMT5_GPIO_RESET 1 + +#define GPIO_NR_PALMT5_POWER_DETECT 90 +#define GPIO_NR_PALMT5_HOTSYNC_BUTTON_N 10 +#define GPIO_NR_PALMT5_EARPHONE_DETECT 107 + +/* SD/MMC */ +#define GPIO_NR_PALMT5_SD_DETECT_N 14 +#define GPIO_NR_PALMT5_SD_POWER 114 +#define GPIO_NR_PALMT5_SD_READONLY 115 + +/* TOUCHSCREEN */ +#define GPIO_NR_PALMT5_WM9712_IRQ 27 + +/* IRDA - disable GPIO connected to SD pin of tranceiver (TFBS4710?) ? */ +#define GPIO_NR_PALMT5_IR_DISABLE 40 + +/* USB */ +#define GPIO_NR_PALMT5_USB_DETECT_N 15 +#define GPIO_NR_PALMT5_USB_POWER 95 +#define GPIO_NR_PALMT5_USB_PULLUP 93 + +/* LCD/BACKLIGHT */ +#define GPIO_NR_PALMT5_BL_POWER 84 +#define GPIO_NR_PALMT5_LCD_POWER 96 + +/* BLUETOOTH */ +#define GPIO_NR_PALMT5_BT_POWER 17 +#define GPIO_NR_PALMT5_BT_RESET 83 + +/* INTERRUPTS */ +#define IRQ_GPIO_PALMT5_SD_DETECT_N IRQ_GPIO(GPIO_NR_PALMT5_SD_DETECT_N) +#define IRQ_GPIO_PALMT5_WM9712_IRQ IRQ_GPIO(GPIO_NR_PALMT5_WM9712_IRQ) +#define IRQ_GPIO_PALMT5_USB_DETECT IRQ_GPIO(GPIO_NR_PALMT5_USB_DETECT) +#define IRQ_GPIO_PALMT5_GPIO_RESET IRQ_GPIO(GPIO_NR_PALMT5_GPIO_RESET) + +/** HERE ARE INIT VALUES **/ + +/* Various addresses */ +#define PALMT5_PHYS_RAM_START 0xa0000000 +#define PALMT5_PHYS_IO_START 0x40000000 + +/* TOUCHSCREEN */ +#define AC97_LINK_FRAME 21 + +/* BATTERY */ +#define PALMT5_BAT_MAX_VOLTAGE 4000 /* 4.00v current voltage */ +#define PALMT5_BAT_MIN_VOLTAGE 3550 /* 3.55v critical voltage */ +#define PALMT5_BAT_MAX_CURRENT 0 /* unknokn */ +#define PALMT5_BAT_MIN_CURRENT 0 /* unknown */ +#define PALMT5_BAT_MAX_CHARGE 1 /* unknown */ +#define PALMT5_BAT_MIN_CHARGE 1 /* unknown */ +#define PALMT5_MAX_LIFE_MINS 360 /* on-life in minutes */ + +#define PALMT5_BAT_MEASURE_DELAY (HZ * 1) + +/* BACKLIGHT */ +#define PALMT5_MAX_INTENSITY 0xFE +#define PALMT5_DEFAULT_INTENSITY 0x7E +#define PALMT5_LIMIT_MASK 0x7F +#define PALMT5_PRESCALER 0x3F +#define PALMT5_PERIOD_NS 3500 + +#endif diff --git a/arch/arm/mach-pxa/palmt5.c b/arch/arm/mach-pxa/palmt5.c new file mode 100644 index 00000000000..51b4a602551 --- /dev/null +++ b/arch/arm/mach-pxa/palmt5.c @@ -0,0 +1,497 @@ +/* + * Hardware definitions for Palm Tungsten|T5 + * + * Author: Marek Vasut + * + * Based on work of: + * Ales Snuparek + * Justin Kendrick + * RichardT5 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * (find more info at www.hackndev.com) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "generic.h" +#include "devices.h" + +/****************************************************************************** + * Pin configuration + ******************************************************************************/ +static unsigned long palmt5_pin_config[] __initdata = { + /* MMC */ + GPIO32_MMC_CLK, + GPIO92_MMC_DAT_0, + GPIO109_MMC_DAT_1, + GPIO110_MMC_DAT_2, + GPIO111_MMC_DAT_3, + GPIO112_MMC_CMD, + GPIO14_GPIO, /* SD detect */ + GPIO114_GPIO, /* SD power */ + GPIO115_GPIO, /* SD r/o switch */ + + /* AC97 */ + GPIO28_AC97_BITCLK, + GPIO29_AC97_SDATA_IN_0, + GPIO30_AC97_SDATA_OUT, + GPIO31_AC97_SYNC, + + /* IrDA */ + GPIO40_GPIO, /* ir disable */ + GPIO46_FICP_RXD, + GPIO47_FICP_TXD, + + /* USB */ + GPIO15_GPIO, /* usb detect */ + GPIO95_GPIO, /* usb power */ + + /* MATRIX KEYPAD */ + GPIO100_KP_MKIN_0, + GPIO101_KP_MKIN_1, + GPIO102_KP_MKIN_2, + GPIO97_KP_MKIN_3, + GPIO103_KP_MKOUT_0, + GPIO104_KP_MKOUT_1, + GPIO105_KP_MKOUT_2, + + /* LCD */ + GPIO58_LCD_LDD_0, + GPIO59_LCD_LDD_1, + GPIO60_LCD_LDD_2, + GPIO61_LCD_LDD_3, + GPIO62_LCD_LDD_4, + GPIO63_LCD_LDD_5, + GPIO64_LCD_LDD_6, + GPIO65_LCD_LDD_7, + GPIO66_LCD_LDD_8, + GPIO67_LCD_LDD_9, + GPIO68_LCD_LDD_10, + GPIO69_LCD_LDD_11, + GPIO70_LCD_LDD_12, + GPIO71_LCD_LDD_13, + GPIO72_LCD_LDD_14, + GPIO73_LCD_LDD_15, + GPIO74_LCD_FCLK, + GPIO75_LCD_LCLK, + GPIO76_LCD_PCLK, + GPIO77_LCD_BIAS, + + /* PWM */ + GPIO16_PWM0_OUT, + + /* MISC */ + GPIO10_GPIO, /* hotsync button */ + GPIO90_GPIO, /* power detect */ + GPIO107_GPIO, /* earphone detect */ +}; + +/****************************************************************************** + * SD/MMC card controller + ******************************************************************************/ +static int palmt5_mci_init(struct device *dev, irq_handler_t palmt5_detect_int, + void *data) +{ + int err = 0; + + /* Setup an interrupt for detecting card insert/remove events */ + err = gpio_request(GPIO_NR_PALMT5_SD_DETECT_N, "SD IRQ"); + if (err) + goto err; + err = gpio_direction_input(GPIO_NR_PALMT5_SD_DETECT_N); + if (err) + goto err2; + err = request_irq(gpio_to_irq(GPIO_NR_PALMT5_SD_DETECT_N), + palmt5_detect_int, IRQF_DISABLED | IRQF_SAMPLE_RANDOM | + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, + "SD/MMC card detect", data); + if (err) { + printk(KERN_ERR "%s: cannot request SD/MMC card detect IRQ\n", + __func__); + goto err2; + } + + err = gpio_request(GPIO_NR_PALMT5_SD_POWER, "SD_POWER"); + if (err) + goto err3; + err = gpio_direction_output(GPIO_NR_PALMT5_SD_POWER, 0); + if (err) + goto err4; + + err = gpio_request(GPIO_NR_PALMT5_SD_READONLY, "SD_READONLY"); + if (err) + goto err4; + err = gpio_direction_input(GPIO_NR_PALMT5_SD_READONLY); + if (err) + goto err5; + + printk(KERN_DEBUG "%s: irq registered\n", __func__); + + return 0; + +err5: + gpio_free(GPIO_NR_PALMT5_SD_READONLY); +err4: + gpio_free(GPIO_NR_PALMT5_SD_POWER); +err3: + free_irq(gpio_to_irq(GPIO_NR_PALMT5_SD_DETECT_N), data); +err2: + gpio_free(GPIO_NR_PALMT5_SD_DETECT_N); +err: + return err; +} + +static void palmt5_mci_exit(struct device *dev, void *data) +{ + gpio_free(GPIO_NR_PALMT5_SD_READONLY); + gpio_free(GPIO_NR_PALMT5_SD_POWER); + free_irq(IRQ_GPIO_PALMT5_SD_DETECT_N, data); + gpio_free(GPIO_NR_PALMT5_SD_DETECT_N); +} + +static void palmt5_mci_power(struct device *dev, unsigned int vdd) +{ + struct pxamci_platform_data *p_d = dev->platform_data; + gpio_set_value(GPIO_NR_PALMT5_SD_POWER, p_d->ocr_mask & (1 << vdd)); +} + +static int palmt5_mci_get_ro(struct device *dev) +{ + return gpio_get_value(GPIO_NR_PALMT5_SD_READONLY); +} + +static struct pxamci_platform_data palmt5_mci_platform_data = { + .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, + .setpower = palmt5_mci_power, + .get_ro = palmt5_mci_get_ro, + .init = palmt5_mci_init, + .exit = palmt5_mci_exit, +}; + +/****************************************************************************** + * GPIO keyboard + ******************************************************************************/ +static unsigned int palmt5_matrix_keys[] = { + KEY(0, 0, KEY_POWER), + KEY(0, 1, KEY_F1), + KEY(0, 2, KEY_ENTER), + + KEY(1, 0, KEY_F2), + KEY(1, 1, KEY_F3), + KEY(1, 2, KEY_F4), + + KEY(2, 0, KEY_UP), + KEY(2, 2, KEY_DOWN), + + KEY(3, 0, KEY_RIGHT), + KEY(3, 2, KEY_LEFT), +}; + +static struct pxa27x_keypad_platform_data palmt5_keypad_platform_data = { + .matrix_key_rows = 4, + .matrix_key_cols = 3, + .matrix_key_map = palmt5_matrix_keys, + .matrix_key_map_size = ARRAY_SIZE(palmt5_matrix_keys), + + .debounce_interval = 30, +}; + +/****************************************************************************** + * GPIO keys + ******************************************************************************/ +static struct gpio_keys_button palmt5_pxa_buttons[] = { + {KEY_F8, GPIO_NR_PALMT5_HOTSYNC_BUTTON_N, 1, "HotSync Button" }, +}; + +static struct gpio_keys_platform_data palmt5_pxa_keys_data = { + .buttons = palmt5_pxa_buttons, + .nbuttons = ARRAY_SIZE(palmt5_pxa_buttons), +}; + +static struct platform_device palmt5_pxa_keys = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &palmt5_pxa_keys_data, + }, +}; + +/****************************************************************************** + * Backlight + ******************************************************************************/ +static int palmt5_backlight_init(struct device *dev) +{ + int ret; + + ret = gpio_request(GPIO_NR_PALMT5_BL_POWER, "BL POWER"); + if (ret) + goto err; + ret = gpio_direction_output(GPIO_NR_PALMT5_BL_POWER, 0); + if (ret) + goto err2; + ret = gpio_request(GPIO_NR_PALMT5_LCD_POWER, "LCD POWER"); + if (ret) + goto err2; + ret = gpio_direction_output(GPIO_NR_PALMT5_LCD_POWER, 0); + if (ret) + goto err3; + + return 0; +err3: + gpio_free(GPIO_NR_PALMT5_LCD_POWER); +err2: + gpio_free(GPIO_NR_PALMT5_BL_POWER); +err: + return ret; +} + +static int palmt5_backlight_notify(int brightness) +{ + gpio_set_value(GPIO_NR_PALMT5_BL_POWER, brightness); + gpio_set_value(GPIO_NR_PALMT5_LCD_POWER, brightness); + return brightness; +} + +static void palmt5_backlight_exit(struct device *dev) +{ + gpio_free(GPIO_NR_PALMT5_BL_POWER); + gpio_free(GPIO_NR_PALMT5_LCD_POWER); +} + +static struct platform_pwm_backlight_data palmt5_backlight_data = { + .pwm_id = 0, + .max_brightness = PALMT5_MAX_INTENSITY, + .dft_brightness = PALMT5_MAX_INTENSITY, + .pwm_period_ns = PALMT5_PERIOD_NS, + .init = palmt5_backlight_init, + .notify = palmt5_backlight_notify, + .exit = palmt5_backlight_exit, +}; + +static struct platform_device palmt5_backlight = { + .name = "pwm-backlight", + .dev = { + .parent = &pxa27x_device_pwm0.dev, + .platform_data = &palmt5_backlight_data, + }, +}; + +/****************************************************************************** + * IrDA + ******************************************************************************/ +static int palmt5_irda_startup(struct device *dev) +{ + int err; + err = gpio_request(GPIO_NR_PALMT5_IR_DISABLE, "IR DISABLE"); + if (err) + goto err; + err = gpio_direction_output(GPIO_NR_PALMT5_IR_DISABLE, 1); + if (err) + gpio_free(GPIO_NR_PALMT5_IR_DISABLE); +err: + return err; +} + +static void palmt5_irda_shutdown(struct device *dev) +{ + gpio_free(GPIO_NR_PALMT5_IR_DISABLE); +} + +static void palmt5_irda_transceiver_mode(struct device *dev, int mode) +{ + gpio_set_value(GPIO_NR_PALMT5_IR_DISABLE, mode & IR_OFF); + pxa2xx_transceiver_mode(dev, mode); +} + +static struct pxaficp_platform_data palmt5_ficp_platform_data = { + .startup = palmt5_irda_startup, + .shutdown = palmt5_irda_shutdown, + .transceiver_cap = IR_SIRMODE | IR_FIRMODE | IR_OFF, + .transceiver_mode = palmt5_irda_transceiver_mode, +}; + +/****************************************************************************** + * UDC + ******************************************************************************/ +static struct pxa2xx_udc_mach_info palmt5_udc_info __initdata = { + .gpio_vbus = GPIO_NR_PALMT5_USB_DETECT_N, + .gpio_vbus_inverted = 1, + .gpio_pullup = GPIO_NR_PALMT5_USB_POWER, + .gpio_pullup_inverted = 0, +}; + +/****************************************************************************** + * Power supply + ******************************************************************************/ +static int power_supply_init(struct device *dev) +{ + int ret; + + ret = gpio_request(GPIO_NR_PALMT5_POWER_DETECT, "CABLE_STATE_AC"); + if (ret) + goto err1; + ret = gpio_direction_input(GPIO_NR_PALMT5_POWER_DETECT); + if (ret) + goto err2; + + return 0; +err2: + gpio_free(GPIO_NR_PALMT5_POWER_DETECT); +err1: + return ret; +} + +static int palmt5_is_ac_online(void) +{ + return gpio_get_value(GPIO_NR_PALMT5_POWER_DETECT); +} + +static void power_supply_exit(struct device *dev) +{ + gpio_free(GPIO_NR_PALMT5_POWER_DETECT); +} + +static char *palmt5_supplicants[] = { + "main-battery", +}; + +static struct pda_power_pdata power_supply_info = { + .init = power_supply_init, + .is_ac_online = palmt5_is_ac_online, + .exit = power_supply_exit, + .supplied_to = palmt5_supplicants, + .num_supplicants = ARRAY_SIZE(palmt5_supplicants), +}; + +static struct platform_device power_supply = { + .name = "pda-power", + .id = -1, + .dev = { + .platform_data = &power_supply_info, + }, +}; + +/****************************************************************************** + * WM97xx battery + ******************************************************************************/ +static struct wm97xx_batt_info wm97xx_batt_pdata = { + .batt_aux = WM97XX_AUX_ID3, + .temp_aux = WM97XX_AUX_ID2, + .charge_gpio = -1, + .max_voltage = PALMT5_BAT_MAX_VOLTAGE, + .min_voltage = PALMT5_BAT_MIN_VOLTAGE, + .batt_mult = 1000, + .batt_div = 414, + .temp_mult = 1, + .temp_div = 1, + .batt_tech = POWER_SUPPLY_TECHNOLOGY_LIPO, + .batt_name = "main-batt", +}; + +/****************************************************************************** + * aSoC audio + ******************************************************************************/ +static struct palm27x_asoc_info palm27x_asoc_pdata = { + .jack_gpio = GPIO_NR_PALMT5_EARPHONE_DETECT, +}; + +/****************************************************************************** + * Framebuffer + ******************************************************************************/ +static struct pxafb_mode_info palmt5_lcd_modes[] = { +{ + .pixclock = 57692, + .xres = 320, + .yres = 480, + .bpp = 16, + + .left_margin = 32, + .right_margin = 1, + .upper_margin = 7, + .lower_margin = 1, + + .hsync_len = 4, + .vsync_len = 1, +}, +}; + +static struct pxafb_mach_info palmt5_lcd_screen = { + .modes = palmt5_lcd_modes, + .num_modes = ARRAY_SIZE(palmt5_lcd_modes), + .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL, +}; + +/****************************************************************************** + * Machine init + ******************************************************************************/ +static struct platform_device *devices[] __initdata = { +#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) + &palmt5_pxa_keys, +#endif + &palmt5_backlight, + &power_supply, +}; + +/* setup udc GPIOs initial state */ +static void __init palmt5_udc_init(void) +{ + if (!gpio_request(GPIO_NR_PALMT5_USB_POWER, "UDC Vbus")) { + gpio_direction_output(GPIO_NR_PALMT5_USB_POWER, 1); + gpio_free(GPIO_NR_PALMT5_USB_POWER); + } +} + +static void __init palmt5_init(void) +{ + pxa2xx_mfp_config(ARRAY_AND_SIZE(palmt5_pin_config)); + + set_pxa_fb_info(&palmt5_lcd_screen); + pxa_set_mci_info(&palmt5_mci_platform_data); + palmt5_udc_init(); + pxa_set_udc_info(&palmt5_udc_info); + pxa_set_ac97_info(NULL); + pxa_set_ficp_info(&palmt5_ficp_platform_data); + pxa_set_keypad_info(&palmt5_keypad_platform_data); + wm97xx_bat_set_pdata(&wm97xx_batt_pdata); + palm27x_asoc_set_pdata(&palm27x_asoc_pdata); + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +MACHINE_START(PALMT5, "Palm Tungsten|T5") + .phys_io = PALMT5_PHYS_IO_START, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .boot_params = 0xa0000100, + .map_io = pxa_map_io, + .init_irq = pxa27x_init_irq, + .timer = &pxa_timer, + .init_machine = palmt5_init +MACHINE_END -- GitLab From a645072a608356990b2737a48ecc1bfb66981599 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 20 Nov 2008 22:50:46 +0100 Subject: [PATCH 0246/4982] [ARM] pxa: PalmLD initial support Signed-off-by: Marek Vasut Signed-off-by: Eric Miao --- MAINTAINERS | 2 +- arch/arm/mach-pxa/Kconfig | 10 + arch/arm/mach-pxa/Makefile | 1 + arch/arm/mach-pxa/include/mach/palmld.h | 109 +++++ arch/arm/mach-pxa/palmld.c | 566 ++++++++++++++++++++++++ 5 files changed, 687 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-pxa/include/mach/palmld.h create mode 100644 arch/arm/mach-pxa/palmld.c diff --git a/MAINTAINERS b/MAINTAINERS index a267659552c..1a142b8cc1b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -622,7 +622,7 @@ P: Dirk Opfer M: dirk@opfer-online.de S: Maintained -ARM/PALMTX,PALMT5 SUPPORT +ARM/PALMTX,PALMT5,PALMLD SUPPORT P: Marek Vasut M: marek.vasut@gmail.com W: http://hackndev.com diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 9223ba607a7..af5b5b463a2 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -349,6 +349,16 @@ config MACH_PALMZ72 Say Y here if you intend to run this kernel on Palm Zire 72 handheld computer. +config MACH_PALMLD + bool "Palm LifeDrive" + default y + depends on ARCH_PXA_PALM + select PXA27x + select IWMMXT + help + Say Y here if you intend to run this kernel on a Palm LifeDrive + handheld computer. + config MACH_PCM990_BASEBOARD bool "PHYTEC PCM-990 development board" select HAVE_PWM diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 0d0afe84ec5..146aba72fa2 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -55,6 +55,7 @@ obj-$(CONFIG_MACH_E400) += e400.o obj-$(CONFIG_MACH_E800) += e800.o obj-$(CONFIG_MACH_PALMT5) += palmt5.o obj-$(CONFIG_MACH_PALMTX) += palmtx.o +obj-$(CONFIG_MACH_PALMLD) += palmld.o obj-$(CONFIG_MACH_PALMZ72) += palmz72.o obj-$(CONFIG_ARCH_VIPER) += viper.o diff --git a/arch/arm/mach-pxa/include/mach/palmld.h b/arch/arm/mach-pxa/include/mach/palmld.h new file mode 100644 index 00000000000..7c295a48d78 --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/palmld.h @@ -0,0 +1,109 @@ +/* + * GPIOs and interrupts for Palm LifeDrive Handheld Computer + * + * Authors: Alex Osborne + * Marek Vasut + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef _INCLUDE_PALMLD_H_ +#define _INCLUDE_PALMLD_H_ + +/** HERE ARE GPIOs **/ + +/* GPIOs */ +#define GPIO_NR_PALMLD_GPIO_RESET 1 +#define GPIO_NR_PALMLD_POWER_DETECT 4 +#define GPIO_NR_PALMLD_HOTSYNC_BUTTON_N 10 +#define GPIO_NR_PALMLD_POWER_SWITCH 12 +#define GPIO_NR_PALMLD_EARPHONE_DETECT 13 +#define GPIO_NR_PALMLD_LOCK_SWITCH 15 + +/* SD/MMC */ +#define GPIO_NR_PALMLD_SD_DETECT_N 14 +#define GPIO_NR_PALMLD_SD_POWER 114 +#define GPIO_NR_PALMLD_SD_READONLY 116 + +/* TOUCHSCREEN */ +#define GPIO_NR_PALMLD_WM9712_IRQ 27 + +/* IRDA */ +#define GPIO_NR_PALMLD_IR_DISABLE 108 + +/* LCD/BACKLIGHT */ +#define GPIO_NR_PALMLD_BL_POWER 19 +#define GPIO_NR_PALMLD_LCD_POWER 96 + +/* LCD BORDER */ +#define GPIO_NR_PALMLD_BORDER_SWITCH 21 +#define GPIO_NR_PALMLD_BORDER_SELECT 22 + +/* BLUETOOTH */ +#define GPIO_NR_PALMLD_BT_POWER 17 +#define GPIO_NR_PALMLD_BT_RESET 83 + +/* PCMCIA (WiFi) */ +#define GPIO_NR_PALMLD_PCMCIA_READY 38 +#define GPIO_NR_PALMLD_PCMCIA_POWER 36 +#define GPIO_NR_PALMLD_PCMCIA_RESET 81 + +/* LEDs */ +#define GPIO_NR_PALMLD_LED_GREEN 52 +#define GPIO_NR_PALMLD_LED_AMBER 94 + +/* IDE */ +#define GPIO_NR_PALMLD_IDE_IRQ 95 +#define GPIO_NR_PALMLD_IDE_RESET 98 +#define GPIO_NR_PALMLD_IDE_PWEN 115 + +/* USB */ +#define GPIO_NR_PALMLD_USB_DETECT_N 3 +#define GPIO_NR_PALMLD_USB_READY 86 +#define GPIO_NR_PALMLD_USB_RESET 88 +#define GPIO_NR_PALMLD_USB_INT 106 +#define GPIO_NR_PALMLD_USB_POWER 118 +/* 20, 53 and 86 are usb related too */ + +/* INTERRUPTS */ +#define IRQ_GPIO_PALMLD_GPIO_RESET IRQ_GPIO(GPIO_NR_PALMLD_GPIO_RESET) +#define IRQ_GPIO_PALMLD_SD_DETECT_N IRQ_GPIO(GPIO_NR_PALMLD_SD_DETECT_N) +#define IRQ_GPIO_PALMLD_WM9712_IRQ IRQ_GPIO(GPIO_NR_PALMLD_WM9712_IRQ) +#define IRQ_GPIO_PALMLD_IDE_IRQ IRQ_GPIO(GPIO_NR_PALMLD_IDE_IRQ) + + +/** HERE ARE INIT VALUES **/ + +/* IO mappings */ +#define PALMLD_USB_PHYS PXA_CS2_PHYS +#define PALMLD_USB_VIRT 0xf0000000 +#define PALMLD_USB_SIZE 0x00100000 + +#define PALMLD_IDE_PHYS 0x20000000 +#define PALMLD_IDE_VIRT 0xf1000000 +#define PALMLD_IDE_SIZE 0x00100000 + +#define PALMLD_PHYS_IO_START 0x40000000 + +/* BATTERY */ +#define PALMLD_BAT_MAX_VOLTAGE 4000 /* 4.00V maximum voltage */ +#define PALMLD_BAT_MIN_VOLTAGE 3550 /* 3.55V critical voltage */ +#define PALMLD_BAT_MAX_CURRENT 0 /* unknokn */ +#define PALMLD_BAT_MIN_CURRENT 0 /* unknown */ +#define PALMLD_BAT_MAX_CHARGE 1 /* unknown */ +#define PALMLD_BAT_MIN_CHARGE 1 /* unknown */ +#define PALMLD_MAX_LIFE_MINS 240 /* on-life in minutes */ + +#define PALMLD_BAT_MEASURE_DELAY (HZ * 1) + +/* BACKLIGHT */ +#define PALMLD_MAX_INTENSITY 0xFE +#define PALMLD_DEFAULT_INTENSITY 0x7E +#define PALMLD_LIMIT_MASK 0x7F +#define PALMLD_PRESCALER 0x3F +#define PALMLD_PERIOD_NS 3500 + +#endif diff --git a/arch/arm/mach-pxa/palmld.c b/arch/arm/mach-pxa/palmld.c new file mode 100644 index 00000000000..55a2c40b6f2 --- /dev/null +++ b/arch/arm/mach-pxa/palmld.c @@ -0,0 +1,566 @@ +/* + * Hardware definitions for Palm LifeDrive + * + * Author: Marek Vasut + * + * Based on work of: + * Alex Osborne + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * (find more info at www.hackndev.com) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "generic.h" +#include "devices.h" + +/****************************************************************************** + * Pin configuration + ******************************************************************************/ +static unsigned long palmld_pin_config[] __initdata = { + /* MMC */ + GPIO32_MMC_CLK, + GPIO92_MMC_DAT_0, + GPIO109_MMC_DAT_1, + GPIO110_MMC_DAT_2, + GPIO111_MMC_DAT_3, + GPIO112_MMC_CMD, + GPIO14_GPIO, /* SD detect */ + GPIO114_GPIO, /* SD power */ + GPIO116_GPIO, /* SD r/o switch */ + + /* AC97 */ + GPIO28_AC97_BITCLK, + GPIO29_AC97_SDATA_IN_0, + GPIO30_AC97_SDATA_OUT, + GPIO31_AC97_SYNC, + + /* IrDA */ + GPIO108_GPIO, /* ir disable */ + GPIO46_FICP_RXD, + GPIO47_FICP_TXD, + + /* MATRIX KEYPAD */ + GPIO100_KP_MKIN_0, + GPIO101_KP_MKIN_1, + GPIO102_KP_MKIN_2, + GPIO97_KP_MKIN_3, + GPIO103_KP_MKOUT_0, + GPIO104_KP_MKOUT_1, + GPIO105_KP_MKOUT_2, + + /* LCD */ + GPIO58_LCD_LDD_0, + GPIO59_LCD_LDD_1, + GPIO60_LCD_LDD_2, + GPIO61_LCD_LDD_3, + GPIO62_LCD_LDD_4, + GPIO63_LCD_LDD_5, + GPIO64_LCD_LDD_6, + GPIO65_LCD_LDD_7, + GPIO66_LCD_LDD_8, + GPIO67_LCD_LDD_9, + GPIO68_LCD_LDD_10, + GPIO69_LCD_LDD_11, + GPIO70_LCD_LDD_12, + GPIO71_LCD_LDD_13, + GPIO72_LCD_LDD_14, + GPIO73_LCD_LDD_15, + GPIO74_LCD_FCLK, + GPIO75_LCD_LCLK, + GPIO76_LCD_PCLK, + GPIO77_LCD_BIAS, + + /* PWM */ + GPIO16_PWM0_OUT, + + /* GPIO KEYS */ + GPIO10_GPIO, /* hotsync button */ + GPIO12_GPIO, /* power switch */ + GPIO15_GPIO, /* lock switch */ + + /* LEDs */ + GPIO52_GPIO, /* green led */ + GPIO94_GPIO, /* orange led */ + + /* PCMCIA */ + GPIO48_nPOE, + GPIO49_nPWE, + GPIO50_nPIOR, + GPIO51_nPIOW, + GPIO85_nPCE_1, + GPIO54_nPCE_2, + GPIO79_PSKTSEL, + GPIO55_nPREG, + GPIO56_nPWAIT, + GPIO57_nIOIS16, + GPIO36_GPIO, /* wifi power */ + GPIO38_GPIO, /* wifi ready */ + GPIO81_GPIO, /* wifi reset */ + + /* HDD */ + GPIO95_GPIO, /* HDD irq */ + GPIO115_GPIO, /* HDD power */ + + /* MISC */ + GPIO13_GPIO, /* earphone detect */ +}; + +/****************************************************************************** + * SD/MMC card controller + ******************************************************************************/ +static int palmld_mci_init(struct device *dev, irq_handler_t palmld_detect_int, + void *data) +{ + int err = 0; + + /* Setup an interrupt for detecting card insert/remove events */ + err = gpio_request(GPIO_NR_PALMLD_SD_DETECT_N, "SD IRQ"); + if (err) + goto err; + err = gpio_direction_input(GPIO_NR_PALMLD_SD_DETECT_N); + if (err) + goto err2; + err = request_irq(gpio_to_irq(GPIO_NR_PALMLD_SD_DETECT_N), + palmld_detect_int, IRQF_DISABLED | IRQF_SAMPLE_RANDOM | + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, + "SD/MMC card detect", data); + if (err) { + printk(KERN_ERR "%s: cannot request SD/MMC card detect IRQ\n", + __func__); + goto err2; + } + + err = gpio_request(GPIO_NR_PALMLD_SD_POWER, "SD_POWER"); + if (err) + goto err3; + err = gpio_direction_output(GPIO_NR_PALMLD_SD_POWER, 0); + if (err) + goto err4; + + err = gpio_request(GPIO_NR_PALMLD_SD_READONLY, "SD_READONLY"); + if (err) + goto err4; + err = gpio_direction_input(GPIO_NR_PALMLD_SD_READONLY); + if (err) + goto err5; + + printk(KERN_DEBUG "%s: irq registered\n", __func__); + + return 0; + +err5: + gpio_free(GPIO_NR_PALMLD_SD_READONLY); +err4: + gpio_free(GPIO_NR_PALMLD_SD_POWER); +err3: + free_irq(gpio_to_irq(GPIO_NR_PALMLD_SD_DETECT_N), data); +err2: + gpio_free(GPIO_NR_PALMLD_SD_DETECT_N); +err: + return err; +} + +static void palmld_mci_exit(struct device *dev, void *data) +{ + gpio_free(GPIO_NR_PALMLD_SD_READONLY); + gpio_free(GPIO_NR_PALMLD_SD_POWER); + free_irq(gpio_to_irq(GPIO_NR_PALMLD_SD_DETECT_N), data); + gpio_free(GPIO_NR_PALMLD_SD_DETECT_N); +} + +static void palmld_mci_power(struct device *dev, unsigned int vdd) +{ + struct pxamci_platform_data *p_d = dev->platform_data; + gpio_set_value(GPIO_NR_PALMLD_SD_POWER, p_d->ocr_mask & (1 << vdd)); +} + +static int palmld_mci_get_ro(struct device *dev) +{ + return gpio_get_value(GPIO_NR_PALMLD_SD_READONLY); +} + +static struct pxamci_platform_data palmld_mci_platform_data = { + .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, + .setpower = palmld_mci_power, + .get_ro = palmld_mci_get_ro, + .init = palmld_mci_init, + .exit = palmld_mci_exit, +}; + +/****************************************************************************** + * GPIO keyboard + ******************************************************************************/ +static unsigned int palmld_matrix_keys[] = { + KEY(0, 1, KEY_F2), + KEY(0, 2, KEY_UP), + + KEY(1, 0, KEY_F3), + KEY(1, 1, KEY_F4), + KEY(1, 2, KEY_RIGHT), + + KEY(2, 0, KEY_F1), + KEY(2, 1, KEY_F5), + KEY(2, 2, KEY_DOWN), + + KEY(3, 0, KEY_F6), + KEY(3, 1, KEY_ENTER), + KEY(3, 2, KEY_LEFT), +}; + +static struct pxa27x_keypad_platform_data palmld_keypad_platform_data = { + .matrix_key_rows = 4, + .matrix_key_cols = 3, + .matrix_key_map = palmld_matrix_keys, + .matrix_key_map_size = ARRAY_SIZE(palmld_matrix_keys), + + .debounce_interval = 30, +}; + +/****************************************************************************** + * GPIO keys + ******************************************************************************/ +static struct gpio_keys_button palmld_pxa_buttons[] = { + {KEY_F8, GPIO_NR_PALMLD_HOTSYNC_BUTTON_N, 1, "HotSync Button" }, + {KEY_F9, GPIO_NR_PALMLD_LOCK_SWITCH, 0, "Lock Switch" }, + {KEY_POWER, GPIO_NR_PALMLD_POWER_SWITCH, 0, "Power Switch" }, +}; + +static struct gpio_keys_platform_data palmld_pxa_keys_data = { + .buttons = palmld_pxa_buttons, + .nbuttons = ARRAY_SIZE(palmld_pxa_buttons), +}; + +static struct platform_device palmld_pxa_keys = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &palmld_pxa_keys_data, + }, +}; + +/****************************************************************************** + * Backlight + ******************************************************************************/ +static int palmld_backlight_init(struct device *dev) +{ + int ret; + + ret = gpio_request(GPIO_NR_PALMLD_BL_POWER, "BL POWER"); + if (ret) + goto err; + ret = gpio_direction_output(GPIO_NR_PALMLD_BL_POWER, 0); + if (ret) + goto err2; + ret = gpio_request(GPIO_NR_PALMLD_LCD_POWER, "LCD POWER"); + if (ret) + goto err2; + ret = gpio_direction_output(GPIO_NR_PALMLD_LCD_POWER, 0); + if (ret) + goto err3; + + return 0; +err3: + gpio_free(GPIO_NR_PALMLD_LCD_POWER); +err2: + gpio_free(GPIO_NR_PALMLD_BL_POWER); +err: + return ret; +} + +static int palmld_backlight_notify(int brightness) +{ + gpio_set_value(GPIO_NR_PALMLD_BL_POWER, brightness); + gpio_set_value(GPIO_NR_PALMLD_LCD_POWER, brightness); + return brightness; +} + +static void palmld_backlight_exit(struct device *dev) +{ + gpio_free(GPIO_NR_PALMLD_BL_POWER); + gpio_free(GPIO_NR_PALMLD_LCD_POWER); +} + +static struct platform_pwm_backlight_data palmld_backlight_data = { + .pwm_id = 0, + .max_brightness = PALMLD_MAX_INTENSITY, + .dft_brightness = PALMLD_MAX_INTENSITY, + .pwm_period_ns = PALMLD_PERIOD_NS, + .init = palmld_backlight_init, + .notify = palmld_backlight_notify, + .exit = palmld_backlight_exit, +}; + +static struct platform_device palmld_backlight = { + .name = "pwm-backlight", + .dev = { + .parent = &pxa27x_device_pwm0.dev, + .platform_data = &palmld_backlight_data, + }, +}; + +/****************************************************************************** + * IrDA + ******************************************************************************/ +static int palmld_irda_startup(struct device *dev) +{ + int err; + err = gpio_request(GPIO_NR_PALMLD_IR_DISABLE, "IR DISABLE"); + if (err) + goto err; + err = gpio_direction_output(GPIO_NR_PALMLD_IR_DISABLE, 1); + if (err) + gpio_free(GPIO_NR_PALMLD_IR_DISABLE); +err: + return err; +} + +static void palmld_irda_shutdown(struct device *dev) +{ + gpio_free(GPIO_NR_PALMLD_IR_DISABLE); +} + +static void palmld_irda_transceiver_mode(struct device *dev, int mode) +{ + gpio_set_value(GPIO_NR_PALMLD_IR_DISABLE, mode & IR_OFF); + pxa2xx_transceiver_mode(dev, mode); +} + +static struct pxaficp_platform_data palmld_ficp_platform_data = { + .startup = palmld_irda_startup, + .shutdown = palmld_irda_shutdown, + .transceiver_cap = IR_SIRMODE | IR_FIRMODE | IR_OFF, + .transceiver_mode = palmld_irda_transceiver_mode, +}; + +/****************************************************************************** + * LEDs + ******************************************************************************/ +struct gpio_led gpio_leds[] = { +{ + .name = "palmld:green:led", + .default_trigger = "none", + .gpio = GPIO_NR_PALMLD_LED_GREEN, +}, { + .name = "palmld:amber:led", + .default_trigger = "none", + .gpio = GPIO_NR_PALMLD_LED_AMBER, +}, +}; + +static struct gpio_led_platform_data gpio_led_info = { + .leds = gpio_leds, + .num_leds = ARRAY_SIZE(gpio_leds), +}; + +static struct platform_device palmld_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &gpio_led_info, + } +}; + +/****************************************************************************** + * Power supply + ******************************************************************************/ +static int power_supply_init(struct device *dev) +{ + int ret; + + ret = gpio_request(GPIO_NR_PALMLD_POWER_DETECT, "CABLE_STATE_AC"); + if (ret) + goto err1; + ret = gpio_direction_input(GPIO_NR_PALMLD_POWER_DETECT); + if (ret) + goto err2; + + ret = gpio_request(GPIO_NR_PALMLD_USB_DETECT_N, "CABLE_STATE_USB"); + if (ret) + goto err2; + ret = gpio_direction_input(GPIO_NR_PALMLD_USB_DETECT_N); + if (ret) + goto err3; + + return 0; + +err3: + gpio_free(GPIO_NR_PALMLD_USB_DETECT_N); +err2: + gpio_free(GPIO_NR_PALMLD_POWER_DETECT); +err1: + return ret; +} + +static int palmld_is_ac_online(void) +{ + return gpio_get_value(GPIO_NR_PALMLD_POWER_DETECT); +} + +static int palmld_is_usb_online(void) +{ + return !gpio_get_value(GPIO_NR_PALMLD_USB_DETECT_N); +} + +static void power_supply_exit(struct device *dev) +{ + gpio_free(GPIO_NR_PALMLD_USB_DETECT_N); + gpio_free(GPIO_NR_PALMLD_POWER_DETECT); +} + +static char *palmld_supplicants[] = { + "main-battery", +}; + +static struct pda_power_pdata power_supply_info = { + .init = power_supply_init, + .is_ac_online = palmld_is_ac_online, + .is_usb_online = palmld_is_usb_online, + .exit = power_supply_exit, + .supplied_to = palmld_supplicants, + .num_supplicants = ARRAY_SIZE(palmld_supplicants), +}; + +static struct platform_device power_supply = { + .name = "pda-power", + .id = -1, + .dev = { + .platform_data = &power_supply_info, + }, +}; + +/****************************************************************************** + * WM97xx battery + ******************************************************************************/ +static struct wm97xx_batt_info wm97xx_batt_pdata = { + .batt_aux = WM97XX_AUX_ID3, + .temp_aux = WM97XX_AUX_ID2, + .charge_gpio = -1, + .max_voltage = PALMLD_BAT_MAX_VOLTAGE, + .min_voltage = PALMLD_BAT_MIN_VOLTAGE, + .batt_mult = 1000, + .batt_div = 414, + .temp_mult = 1, + .temp_div = 1, + .batt_tech = POWER_SUPPLY_TECHNOLOGY_LIPO, + .batt_name = "main-batt", +}; + +/****************************************************************************** + * aSoC audio + ******************************************************************************/ +static struct palm27x_asoc_info palm27x_asoc_pdata = { + .jack_gpio = GPIO_NR_PALMLD_EARPHONE_DETECT, +}; + +/****************************************************************************** + * Framebuffer + ******************************************************************************/ +static struct pxafb_mode_info palmld_lcd_modes[] = { +{ + .pixclock = 57692, + .xres = 320, + .yres = 480, + .bpp = 16, + + .left_margin = 32, + .right_margin = 1, + .upper_margin = 7, + .lower_margin = 1, + + .hsync_len = 4, + .vsync_len = 1, +}, +}; + +static struct pxafb_mach_info palmld_lcd_screen = { + .modes = palmld_lcd_modes, + .num_modes = ARRAY_SIZE(palmld_lcd_modes), + .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL, +}; + +/****************************************************************************** + * Machine init + ******************************************************************************/ +static struct platform_device *devices[] __initdata = { +#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) + &palmld_pxa_keys, +#endif + &palmld_backlight, + &palmld_leds, + &power_supply, +}; + +static struct map_desc palmld_io_desc[] __initdata = { +{ + .virtual = PALMLD_IDE_VIRT, + .pfn = __phys_to_pfn(PALMLD_IDE_PHYS), + .length = PALMLD_IDE_SIZE, + .type = MT_DEVICE +}, +{ + .virtual = PALMLD_USB_VIRT, + .pfn = __phys_to_pfn(PALMLD_USB_PHYS), + .length = PALMLD_USB_SIZE, + .type = MT_DEVICE +}, +}; + +static void __init palmld_map_io(void) +{ + pxa_map_io(); + iotable_init(palmld_io_desc, ARRAY_SIZE(palmld_io_desc)); +} + +static void __init palmld_init(void) +{ + pxa2xx_mfp_config(ARRAY_AND_SIZE(palmld_pin_config)); + + set_pxa_fb_info(&palmld_lcd_screen); + pxa_set_mci_info(&palmld_mci_platform_data); + pxa_set_ac97_info(NULL); + pxa_set_ficp_info(&palmld_ficp_platform_data); + pxa_set_keypad_info(&palmld_keypad_platform_data); + wm97xx_bat_set_pdata(&wm97xx_batt_pdata); + palm27x_asoc_set_pdata(&palm27x_asoc_pdata); + + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +MACHINE_START(PALMLD, "Palm LifeDrive") + .phys_io = PALMLD_PHYS_IO_START, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .boot_params = 0xa0000100, + .map_io = palmld_map_io, + .init_irq = pxa27x_init_irq, + .timer = &pxa_timer, + .init_machine = palmld_init +MACHINE_END -- GitLab From 28c88046d0974e50859d80c885f61d67cb083d02 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 3 Dec 2008 09:38:10 +0200 Subject: [PATCH 0247/4982] [ARM] pxa/em-x270: updates for 2.6.29 The patch includes the following updates to EM-X270: - Added DA9030 support - Added NOR flash support - Added QCI with mt9m112 sensor support - Updated LCD support Signed-off-by: Mike Rapoport Signed-off-by: Eric Miao --- arch/arm/mach-pxa/em-x270.c | 371 ++++++++++++++++++++++++++++++++++-- 1 file changed, 356 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c index f5ed8038ede..1aaae97de7d 100644 --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c @@ -16,9 +16,16 @@ #include #include #include +#include #include #include #include +#include +#include +#include +#include + +#include #include #include @@ -31,6 +38,9 @@ #include #include #include +#include +#include +#include #include "generic.h" @@ -44,6 +54,9 @@ #define GPIO11_NAND_CS (11) #define GPIO56_NAND_RB (56) +/* Miscelaneous GPIOs */ +#define GPIO93_CAM_RESET (93) + static unsigned long em_x270_pin_config[] = { /* AC'97 */ GPIO28_AC97_BITCLK, @@ -154,6 +167,7 @@ static unsigned long em_x270_pin_config[] = { /* power controls */ GPIO20_GPIO | MFP_LPM_DRIVE_LOW, /* GPRS_PWEN */ + GPIO93_GPIO | MFP_LPM_DRIVE_LOW, /* Camera reset */ GPIO115_GPIO | MFP_LPM_DRIVE_LOW, /* WLAN_PWEN */ /* NAND controls */ @@ -369,6 +383,61 @@ static void __init em_x270_init_nand(void) static inline void em_x270_init_nand(void) {} #endif +#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE) +static struct mtd_partition em_x270_nor_parts[] = { + { + .name = "Bootloader", + .offset = 0x00000000, + .size = 0x00050000, + .mask_flags = MTD_WRITEABLE /* force read-only */ + }, { + .name = "Environment", + .offset = 0x00050000, + .size = 0x00010000, + }, { + .name = "Reserved", + .offset = 0x00060000, + .size = 0x00050000, + .mask_flags = MTD_WRITEABLE /* force read-only */ + }, { + .name = "Splashscreen", + .offset = 0x000b0000, + .size = 0x00050000, + } +}; + +static struct physmap_flash_data em_x270_nor_data[] = { + [0] = { + .width = 2, + .parts = em_x270_nor_parts, + .nr_parts = ARRAY_SIZE(em_x270_nor_parts), + }, +}; + +static struct resource em_x270_nor_flash_resource = { + .start = PXA_CS0_PHYS, + .end = PXA_CS0_PHYS + SZ_1M - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device em_x270_physmap_flash = { + .name = "physmap-flash", + .id = 0, + .num_resources = 1, + .resource = &em_x270_nor_flash_resource, + .dev = { + .platform_data = &em_x270_nor_data, + }, +}; + +static void __init em_x270_init_nor(void) +{ + platform_device_register(&em_x270_physmap_flash); +} +#else +static inline void em_x270_init_nor(void) {} +#endif + /* PXA27x OHCI controller setup */ #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) static int em_x270_ohci_init(struct device *dev) @@ -442,27 +511,43 @@ static void __init em_x270_init_mmc(void) static inline void em_x270_init_mmc(void) {} #endif -/* LCD 480x640 */ +/* LCD */ #if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE) -static struct pxafb_mode_info em_x270_lcd_mode = { - .pixclock = 50000, - .bpp = 16, - .xres = 480, - .yres = 640, - .hsync_len = 8, - .vsync_len = 2, - .left_margin = 8, - .upper_margin = 0, - .right_margin = 24, - .lower_margin = 4, - .cmap_greyscale = 0, +static struct pxafb_mode_info em_x270_lcd_modes[] = { + [0] = { + .pixclock = 38250, + .bpp = 16, + .xres = 480, + .yres = 640, + .hsync_len = 8, + .vsync_len = 2, + .left_margin = 8, + .upper_margin = 2, + .right_margin = 24, + .lower_margin = 4, + .sync = 0, + }, + [1] = { + .pixclock = 153800, + .bpp = 16, + .xres = 240, + .yres = 320, + .hsync_len = 8, + .vsync_len = 2, + .left_margin = 8, + .upper_margin = 2, + .right_margin = 88, + .lower_margin = 2, + .sync = 0, + }, }; static struct pxafb_mach_info em_x270_lcd = { - .modes = &em_x270_lcd_mode, - .num_modes = 1, + .modes = em_x270_lcd_modes, + .num_modes = 2, .lcd_conn = LCD_COLOR_TFT_16BPP, }; + static void __init em_x270_init_lcd(void) { set_pxa_fb_info(&em_x270_lcd); @@ -471,6 +556,40 @@ static void __init em_x270_init_lcd(void) static inline void em_x270_init_lcd(void) {} #endif +#if defined(CONFIG_SPI_PXA2XX) || defined(CONFIG_SPI_PXA2XX_MODULE) +static struct pxa2xx_spi_master em_x270_spi_info = { + .num_chipselect = 1, +}; + +static struct pxa2xx_spi_chip em_x270_tdo24m_chip = { + .rx_threshold = 1, + .tx_threshold = 1, +}; + +static struct tdo24m_platform_data em_x270_tdo24m_pdata = { + .model = TDO35S, +}; + +static struct spi_board_info em_x270_spi_devices[] __initdata = { + { + .modalias = "tdo24m", + .max_speed_hz = 1000000, + .bus_num = 1, + .chip_select = 0, + .controller_data = &em_x270_tdo24m_chip, + .platform_data = &em_x270_tdo24m_pdata, + }, +}; + +static void __init em_x270_init_spi(void) +{ + pxa2xx_set_spi_info(1, &em_x270_spi_info); + spi_register_board_info(ARRAY_AND_SIZE(em_x270_spi_devices)); +} +#else +static inline void em_x270_init_spi(void) {} +#endif + #if defined(CONFIG_SND_PXA2XX_AC97) || defined(CONFIG_SND_PXA2XX_AC97_MODULE) static void __init em_x270_init_ac97(void) { @@ -535,19 +654,241 @@ static void __init em_x270_init_gpio_keys(void) static inline void em_x270_init_gpio_keys(void) {} #endif +/* Quick Capture Interface and sensor setup */ +#if defined(CONFIG_VIDEO_PXA27x) || defined(CONFIG_VIDEO_PXA27x_MODULE) +static struct regulator *em_x270_camera_ldo; + +static int em_x270_sensor_init(struct device *dev) +{ + int ret; + + ret = gpio_request(GPIO93_CAM_RESET, "camera reset"); + if (ret) + return ret; + + gpio_direction_output(GPIO93_CAM_RESET, 0); + + em_x270_camera_ldo = regulator_get(NULL, "vcc cam"); + if (em_x270_camera_ldo == NULL) { + gpio_free(GPIO93_CAM_RESET); + return -ENODEV; + } + + ret = regulator_enable(em_x270_camera_ldo); + if (ret) { + regulator_put(em_x270_camera_ldo); + gpio_free(GPIO93_CAM_RESET); + return ret; + } + + gpio_set_value(GPIO93_CAM_RESET, 1); + + return 0; +} + +struct pxacamera_platform_data em_x270_camera_platform_data = { + .init = em_x270_sensor_init, + .flags = PXA_CAMERA_MASTER | PXA_CAMERA_DATAWIDTH_8 | + PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN, + .mclk_10khz = 2600, +}; + +static int em_x270_sensor_power(struct device *dev, int on) +{ + int ret; + int is_on = regulator_is_enabled(em_x270_camera_ldo); + + if (on == is_on) + return 0; + + gpio_set_value(GPIO93_CAM_RESET, !on); + + if (on) + ret = regulator_enable(em_x270_camera_ldo); + else + ret = regulator_disable(em_x270_camera_ldo); + + if (ret) + return ret; + + gpio_set_value(GPIO93_CAM_RESET, on); + + return 0; +} + +static struct soc_camera_link iclink = { + .bus_id = 0, + .power = em_x270_sensor_power, +}; + +static struct i2c_board_info em_x270_i2c_cam_info[] = { + { + I2C_BOARD_INFO("mt9m111", 0x48), + .platform_data = &iclink, + }, +}; + +static struct i2c_pxa_platform_data em_x270_i2c_info = { + .fast_mode = 1, +}; + +static void __init em_x270_init_camera(void) +{ + pxa_set_i2c_info(&em_x270_i2c_info); + i2c_register_board_info(0, ARRAY_AND_SIZE(em_x270_i2c_cam_info)); + pxa_set_camera_info(&em_x270_camera_platform_data); +} +#else +static inline void em_x270_init_camera(void) {} +#endif + +/* DA9030 related initializations */ +static struct regulator_consumer_supply ldo3_consumers[] = { + { + .dev = NULL, + .supply = "vcc gps", + }, +}; + +static struct regulator_consumer_supply ldo5_consumers[] = { + { + .dev = NULL, + .supply = "vcc cam", + }, +}; + +static struct regulator_consumer_supply ldo12_consumers[] = { + { + .dev = NULL, + .supply = "vcc usb", + }, +}; + +static struct regulator_consumer_supply ldo19_consumers[] = { + { + .dev = NULL, + .supply = "vcc gprs", + }, +}; + +static struct regulator_init_data ldo3_data = { + .constraints = { + .min_uV = 3200000, + .max_uV = 3200000, + .state_mem = { + .enabled = 0, + }, + }, + .num_consumer_supplies = ARRAY_SIZE(ldo3_consumers), + .consumer_supplies = ldo3_consumers, +}; + +static struct regulator_init_data ldo5_data = { + .constraints = { + .min_uV = 3000000, + .max_uV = 3000000, + .state_mem = { + .enabled = 0, + }, + }, + .num_consumer_supplies = ARRAY_SIZE(ldo5_consumers), + .consumer_supplies = ldo5_consumers, +}; + +static struct regulator_init_data ldo12_data = { + .constraints = { + .min_uV = 3000000, + .max_uV = 3000000, + .state_mem = { + .enabled = 0, + }, + }, + .num_consumer_supplies = ARRAY_SIZE(ldo12_consumers), + .consumer_supplies = ldo12_consumers, +}; + +static struct regulator_init_data ldo19_data = { + .constraints = { + .min_uV = 3200000, + .max_uV = 3200000, + .state_mem = { + .enabled = 0, + }, + }, + .num_consumer_supplies = ARRAY_SIZE(ldo19_consumers), + .consumer_supplies = ldo19_consumers, +}; + +struct led_info em_x270_led_info = { + .name = "em-x270:orange", + .default_trigger = "battery-charging-or-full", +}; + +struct da903x_subdev_info em_x270_da9030_subdevs[] = { + { + .name = "da903x-regulator", + .id = DA9030_ID_LDO3, + .platform_data = &ldo3_data, + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO5, + .platform_data = &ldo5_data, + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO12, + .platform_data = &ldo12_data, + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO19, + .platform_data = &ldo19_data, + }, { + .name = "da903x-led", + .id = DA9030_ID_LED_PC, + .platform_data = &em_x270_led_info, + }, { + .name = "da903x-backlight", + .id = DA9030_ID_WLED, + } +}; + +static struct da903x_platform_data em_x270_da9030_info = { + .num_subdevs = ARRAY_SIZE(em_x270_da9030_subdevs), + .subdevs = em_x270_da9030_subdevs, +}; + +static struct i2c_board_info em_x270_i2c_pmic_info = { + I2C_BOARD_INFO("da9030", 0x49), + .irq = IRQ_GPIO(0), + .platform_data = &em_x270_da9030_info, +}; + +static struct i2c_pxa_platform_data em_x270_pwr_i2c_info = { + .use_pio = 1, +}; + +static void __init em_x270_init_da9030(void) +{ + pxa27x_set_i2c_power_info(&em_x270_pwr_i2c_info); + i2c_register_board_info(1, &em_x270_i2c_pmic_info, 1); +} + static void __init em_x270_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(em_x270_pin_config)); + em_x270_init_da9030(); em_x270_init_dm9000(); em_x270_init_rtc(); em_x270_init_nand(); + em_x270_init_nor(); em_x270_init_lcd(); em_x270_init_mmc(); em_x270_init_ohci(); em_x270_init_keypad(); em_x270_init_gpio_keys(); em_x270_init_ac97(); + em_x270_init_camera(); + em_x270_init_spi(); } MACHINE_START(EM_X270, "Compulab EM-X270") -- GitLab From efd0ef4e57ec9ae12d013ce91ccef32589e95080 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 3 Dec 2008 09:38:07 +0200 Subject: [PATCH 0248/4982] [ARM] pxa: update xm_x2xx_defconfig Update xm_x2xx_defconfig to allow use of EM-X270 updated features Signed-off-by: Mike Rapoport Signed-off-by: Eric Miao --- arch/arm/configs/xm_x2xx_defconfig | 378 ++++++++++++++++++++--------- 1 file changed, 262 insertions(+), 116 deletions(-) diff --git a/arch/arm/configs/xm_x2xx_defconfig b/arch/arm/configs/xm_x2xx_defconfig index f891364dece..07c3c93754b 100644 --- a/arch/arm/configs/xm_x2xx_defconfig +++ b/arch/arm/configs/xm_x2xx_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.27-rc8 -# Sun Oct 5 11:05:36 2008 +# Linux kernel version: 2.6.28-rc6 +# Wed Dec 3 09:26:16 2008 # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y @@ -22,7 +22,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_ARCH_SUPPORTS_AOUT=y CONFIG_ZONE_DMA=y CONFIG_ARCH_MTD_XIP=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y @@ -80,7 +79,9 @@ CONFIG_SIGNALFD=y CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y +CONFIG_AIO=y # CONFIG_VM_EVENT_COUNTERS is not set +CONFIG_PCI_QUIRKS=y # CONFIG_SLUB_DEBUG is not set # CONFIG_SLAB is not set CONFIG_SLUB=y @@ -89,15 +90,9 @@ CONFIG_SLUB=y # CONFIG_MARKERS is not set CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set -# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set -# CONFIG_HAVE_IOREMAP_PROT is not set CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y -# CONFIG_HAVE_ARCH_TRACEHOOK is not set -# CONFIG_HAVE_DMA_ATTRS is not set -# CONFIG_USE_GENERIC_SMP_HELPERS is not set CONFIG_HAVE_CLK=y -# CONFIG_PROC_PAGE_MONITOR is not set CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -129,6 +124,7 @@ CONFIG_DEFAULT_CFQ=y # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="cfq" CONFIG_CLASSIC_RCU=y +CONFIG_FREEZER=y # # System Type @@ -169,8 +165,7 @@ CONFIG_ARCH_PXA=y # CONFIG_ARCH_LH7A40X is not set # CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_MSM7X00A is not set -CONFIG_DMABOUNCE=y +# CONFIG_ARCH_MSM is not set # # Intel PXA2xx/PXA3xx Implementations @@ -232,6 +227,7 @@ CONFIG_ARM_THUMB=y # CONFIG_OUTER_CACHE is not set CONFIG_IWMMXT=y CONFIG_XSCALE_PMU=y +CONFIG_DMABOUNCE=y # # Bus support @@ -287,14 +283,14 @@ CONFIG_FLATMEM_MANUAL=y # CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4096 # CONFIG_RESOURCES_64BIT is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y CONFIG_ALIGNMENT_TRAP=y # @@ -327,6 +323,8 @@ CONFIG_FPE_NWFPE=y # Userspace binary formats # CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y # CONFIG_BINFMT_AOUT is not set # CONFIG_BINFMT_MISC is not set @@ -389,6 +387,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set # CONFIG_LLC2 is not set @@ -434,11 +433,10 @@ CONFIG_BT_HCIUSB_SCO=y # CONFIG_BT_HCIBTUART is not set # CONFIG_BT_HCIVHCI is not set # CONFIG_AF_RXRPC is not set - -# -# Wireless -# +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y # CONFIG_CFG80211 is not set +CONFIG_WIRELESS_OLD_REGULATORY=y CONFIG_WIRELESS_EXT=y CONFIG_WIRELESS_EXT_SYSFS=y # CONFIG_MAC80211 is not set @@ -522,7 +520,7 @@ CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_COMPLEX_MAPPINGS is not set CONFIG_MTD_PHYSMAP=y CONFIG_MTD_PHYSMAP_START=0x0 -CONFIG_MTD_PHYSMAP_LEN=0x400000 +CONFIG_MTD_PHYSMAP_LEN=0x0 CONFIG_MTD_PHYSMAP_BANKWIDTH=2 CONFIG_MTD_PXA2XX=y # CONFIG_MTD_ARM_INTEGRATOR is not set @@ -535,6 +533,8 @@ CONFIG_MTD_PXA2XX=y # Self-contained MTD device drivers # # CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set # CONFIG_MTD_SLRAM is not set # CONFIG_MTD_PHRAM is not set # CONFIG_MTD_MTDRAM is not set @@ -756,6 +756,7 @@ CONFIG_MII=y CONFIG_DM9000=y CONFIG_DM9000_DEBUGLEVEL=1 # CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL is not set +# CONFIG_ENC28J60 is not set # CONFIG_SMC911X is not set # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set @@ -763,6 +764,9 @@ CONFIG_DM9000_DEBUGLEVEL=1 # CONFIG_IBM_NEW_EMAC_RGMII is not set # CONFIG_IBM_NEW_EMAC_TAH is not set # CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set @@ -775,7 +779,7 @@ CONFIG_NET_PCI=y # CONFIG_NATSEMI is not set # CONFIG_NE2K_PCI is not set # CONFIG_8139CP is not set -CONFIG_8139TOO=y +CONFIG_8139TOO=m # CONFIG_8139TOO_PIO is not set # CONFIG_8139TOO_TUNE_TWISTER is not set # CONFIG_8139TOO_8129 is not set @@ -787,6 +791,7 @@ CONFIG_8139TOO=y # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set # CONFIG_SC92031 is not set +# CONFIG_ATL2 is not set # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set # CONFIG_TR is not set @@ -879,6 +884,7 @@ CONFIG_KEYBOARD_PXA27x=m # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TABLET is not set CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set # CONFIG_TOUCHSCREEN_FUJITSU is not set # CONFIG_TOUCHSCREEN_GUNZE is not set # CONFIG_TOUCHSCREEN_ELO is not set @@ -1022,12 +1028,31 @@ CONFIG_I2C_PXA=y # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_I2C_DEBUG_CHIP is not set -# CONFIG_SPI is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_BITBANG is not set +CONFIG_SPI_PXA2XX=m + +# +# SPI Protocol Masters +# +# CONFIG_SPI_AT25 is not set +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set CONFIG_ARCH_REQUIRE_GPIOLIB=y CONFIG_GPIOLIB=y # CONFIG_DEBUG_GPIO is not set # CONFIG_GPIO_SYSFS is not set +# +# Memory mapped GPIO expanders: +# + # # I2C GPIO expanders: # @@ -1043,17 +1068,19 @@ CONFIG_GPIOLIB=y # # SPI GPIO expanders: # +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set # CONFIG_THERMAL is not set # CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y # # Sonics Silicon Backplane # -CONFIG_SSB_POSSIBLE=y # CONFIG_SSB is not set # @@ -1069,6 +1096,9 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_T7L66XB is not set # CONFIG_MFD_TC6387XB is not set # CONFIG_MFD_TC6393XB is not set +CONFIG_PMIC_DA903X=y +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set # # Multimedia devices @@ -1077,13 +1107,113 @@ CONFIG_SSB_POSSIBLE=y # # Multimedia core support # -# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L2_COMMON=m +# CONFIG_VIDEO_ALLOW_V4L1 is not set +CONFIG_VIDEO_V4L1_COMPAT=y # CONFIG_DVB_CORE is not set -# CONFIG_VIDEO_MEDIA is not set +CONFIG_VIDEO_MEDIA=m # # Multimedia drivers # +# CONFIG_MEDIA_ATTACH is not set +CONFIG_MEDIA_TUNER=m +CONFIG_MEDIA_TUNER_CUSTOMIZE=y +# CONFIG_MEDIA_TUNER_SIMPLE is not set +# CONFIG_MEDIA_TUNER_TDA8290 is not set +# CONFIG_MEDIA_TUNER_TDA827X is not set +# CONFIG_MEDIA_TUNER_TDA18271 is not set +# CONFIG_MEDIA_TUNER_TDA9887 is not set +# CONFIG_MEDIA_TUNER_TEA5761 is not set +# CONFIG_MEDIA_TUNER_TEA5767 is not set +# CONFIG_MEDIA_TUNER_MT20XX is not set +# CONFIG_MEDIA_TUNER_MT2060 is not set +# CONFIG_MEDIA_TUNER_MT2266 is not set +# CONFIG_MEDIA_TUNER_MT2131 is not set +# CONFIG_MEDIA_TUNER_QT1010 is not set +# CONFIG_MEDIA_TUNER_XC2028 is not set +# CONFIG_MEDIA_TUNER_XC5000 is not set +# CONFIG_MEDIA_TUNER_MXL5005S is not set +# CONFIG_MEDIA_TUNER_MXL5007T is not set +CONFIG_VIDEO_V4L2=m +CONFIG_VIDEOBUF_GEN=m +CONFIG_VIDEOBUF_DMA_SG=m +CONFIG_VIDEO_CAPTURE_DRIVERS=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set + +# +# Encoders/decoders and other helper chips +# + +# +# Audio decoders +# +# CONFIG_VIDEO_TVAUDIO is not set +# CONFIG_VIDEO_TDA7432 is not set +# CONFIG_VIDEO_TDA9840 is not set +# CONFIG_VIDEO_TDA9875 is not set +# CONFIG_VIDEO_TEA6415C is not set +# CONFIG_VIDEO_TEA6420 is not set +# CONFIG_VIDEO_MSP3400 is not set +# CONFIG_VIDEO_CS5345 is not set +# CONFIG_VIDEO_CS53L32A is not set +# CONFIG_VIDEO_M52790 is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_WM8775 is not set +# CONFIG_VIDEO_WM8739 is not set +# CONFIG_VIDEO_VP27SMPX is not set + +# +# Video decoders +# +# CONFIG_VIDEO_OV7670 is not set +# CONFIG_VIDEO_TCM825X is not set +# CONFIG_VIDEO_SAA711X is not set +# CONFIG_VIDEO_SAA717X is not set +# CONFIG_VIDEO_TVP5150 is not set + +# +# Video and audio decoders +# +# CONFIG_VIDEO_CX25840 is not set + +# +# MPEG video encoders +# +# CONFIG_VIDEO_CX2341X is not set + +# +# Video encoders +# +# CONFIG_VIDEO_SAA7127 is not set + +# +# Video improvement chips +# +# CONFIG_VIDEO_UPD64031A is not set +# CONFIG_VIDEO_UPD64083 is not set +# CONFIG_VIDEO_VIVI is not set +# CONFIG_VIDEO_BT848 is not set +# CONFIG_VIDEO_SAA5246A is not set +# CONFIG_VIDEO_SAA5249 is not set +# CONFIG_VIDEO_SAA7134 is not set +# CONFIG_VIDEO_HEXIUM_ORION is not set +# CONFIG_VIDEO_HEXIUM_GEMINI is not set +# CONFIG_VIDEO_CX88 is not set +# CONFIG_VIDEO_IVTV is not set +# CONFIG_VIDEO_CAFE_CCIC is not set +CONFIG_SOC_CAMERA=m +# CONFIG_SOC_CAMERA_MT9M001 is not set +CONFIG_SOC_CAMERA_MT9M111=m +# CONFIG_SOC_CAMERA_MT9V022 is not set +# CONFIG_SOC_CAMERA_PLATFORM is not set +CONFIG_VIDEO_PXA27x=m +# CONFIG_VIDEO_SH_MOBILE_CEU is not set +# CONFIG_V4L_USB_DRIVERS is not set +# CONFIG_RADIO_ADAPTERS is not set # CONFIG_DAB is not set # @@ -1095,6 +1225,7 @@ CONFIG_SSB_POSSIBLE=y CONFIG_FB=y # CONFIG_FIRMWARE_EDID is not set # CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y @@ -1128,6 +1259,7 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_S3 is not set # CONFIG_FB_SAVAGE is not set # CONFIG_FB_SIS is not set +# CONFIG_FB_VIA is not set # CONFIG_FB_NEOMAGIC is not set # CONFIG_FB_KYRO is not set # CONFIG_FB_3DFX is not set @@ -1144,7 +1276,17 @@ CONFIG_FB_MBX=m # CONFIG_FB_W100 is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_FB_MB862XX is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=m +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_ILI9320 is not set +CONFIG_LCD_TDO24M=m +# CONFIG_LCD_VGG2432A4 is not set +# CONFIG_LCD_PLATFORM is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=m +# CONFIG_BACKLIGHT_CORGI is not set +CONFIG_BACKLIGHT_DA903X=m # # Display device support @@ -1167,6 +1309,7 @@ CONFIG_LOGO_LINUX_MONO=y CONFIG_LOGO_LINUX_VGA16=y CONFIG_LOGO_LINUX_CLUT224=y CONFIG_SOUND=m +CONFIG_SOUND_OSS_CORE=y CONFIG_SND=m CONFIG_SND_TIMER=m CONFIG_SND_PCM=m @@ -1182,82 +1325,23 @@ CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_DEBUG is not set CONFIG_SND_VMASTER=y CONFIG_SND_AC97_CODEC=m -CONFIG_SND_DRIVERS=y -# CONFIG_SND_DUMMY is not set -# CONFIG_SND_MTPAV is not set -# CONFIG_SND_SERIAL_U16550 is not set -# CONFIG_SND_MPU401 is not set -# CONFIG_SND_AC97_POWER_SAVE is not set -CONFIG_SND_PCI=y -# CONFIG_SND_AD1889 is not set -# CONFIG_SND_ALS300 is not set -# CONFIG_SND_ALI5451 is not set -# CONFIG_SND_ATIIXP is not set -# CONFIG_SND_ATIIXP_MODEM is not set -# CONFIG_SND_AU8810 is not set -# CONFIG_SND_AU8820 is not set -# CONFIG_SND_AU8830 is not set -# CONFIG_SND_AW2 is not set -# CONFIG_SND_AZT3328 is not set -# CONFIG_SND_BT87X is not set -# CONFIG_SND_CA0106 is not set -# CONFIG_SND_CMIPCI is not set -# CONFIG_SND_OXYGEN is not set -# CONFIG_SND_CS4281 is not set -# CONFIG_SND_CS46XX is not set -# CONFIG_SND_DARLA20 is not set -# CONFIG_SND_GINA20 is not set -# CONFIG_SND_LAYLA20 is not set -# CONFIG_SND_DARLA24 is not set -# CONFIG_SND_GINA24 is not set -# CONFIG_SND_LAYLA24 is not set -# CONFIG_SND_MONA is not set -# CONFIG_SND_MIA is not set -# CONFIG_SND_ECHO3G is not set -# CONFIG_SND_INDIGO is not set -# CONFIG_SND_INDIGOIO is not set -# CONFIG_SND_INDIGODJ is not set -# CONFIG_SND_EMU10K1 is not set -# CONFIG_SND_EMU10K1X is not set -# CONFIG_SND_ENS1370 is not set -# CONFIG_SND_ENS1371 is not set -# CONFIG_SND_ES1938 is not set -# CONFIG_SND_ES1968 is not set -# CONFIG_SND_FM801 is not set -# CONFIG_SND_HDA_INTEL is not set -# CONFIG_SND_HDSP is not set -# CONFIG_SND_HDSPM is not set -# CONFIG_SND_HIFIER is not set -# CONFIG_SND_ICE1712 is not set -# CONFIG_SND_ICE1724 is not set -# CONFIG_SND_INTEL8X0 is not set -# CONFIG_SND_INTEL8X0M is not set -# CONFIG_SND_KORG1212 is not set -# CONFIG_SND_MAESTRO3 is not set -# CONFIG_SND_MIXART is not set -# CONFIG_SND_NM256 is not set -# CONFIG_SND_PCXHR is not set -# CONFIG_SND_RIPTIDE is not set -# CONFIG_SND_RME32 is not set -# CONFIG_SND_RME96 is not set -# CONFIG_SND_RME9652 is not set -# CONFIG_SND_SONICVIBES is not set -# CONFIG_SND_TRIDENT is not set -# CONFIG_SND_VIA82XX is not set -# CONFIG_SND_VIA82XX_MODEM is not set -# CONFIG_SND_VIRTUOSO is not set -# CONFIG_SND_VX222 is not set -# CONFIG_SND_YMFPCI is not set +# CONFIG_SND_DRIVERS is not set +# CONFIG_SND_PCI is not set CONFIG_SND_ARM=y CONFIG_SND_PXA2XX_PCM=m +CONFIG_SND_PXA2XX_LIB=m +CONFIG_SND_PXA2XX_LIB_AC97=y CONFIG_SND_PXA2XX_AC97=m -CONFIG_SND_USB=y -# CONFIG_SND_USB_AUDIO is not set -# CONFIG_SND_USB_CAIAQ is not set -CONFIG_SND_PCMCIA=y -# CONFIG_SND_VXPOCKET is not set -# CONFIG_SND_PDAUDIOCF is not set -# CONFIG_SND_SOC is not set +# CONFIG_SND_SPI is not set +# CONFIG_SND_USB is not set +# CONFIG_SND_PCMCIA is not set +CONFIG_SND_SOC=m +CONFIG_SND_SOC_AC97_BUS=y +CONFIG_SND_PXA2XX_SOC=m +CONFIG_SND_PXA2XX_SOC_AC97=m +CONFIG_SND_PXA2XX_SOC_EM_X270=m +# CONFIG_SND_SOC_ALL_CODECS is not set +CONFIG_SND_SOC_WM9712=m # CONFIG_SOUND_PRIME is not set CONFIG_AC97_BUS=m CONFIG_HID_SUPPORT=y @@ -1269,9 +1353,36 @@ CONFIG_HID_DEBUG=y # USB Input Devices # CONFIG_USB_HID=y -# CONFIG_USB_HIDINPUT_POWERBOOK is not set -# CONFIG_HID_FF is not set +# CONFIG_HID_PID is not set # CONFIG_USB_HIDDEV is not set + +# +# Special HID drivers +# +CONFIG_HID_COMPAT=y +CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_BRIGHT=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DELL=y +CONFIG_HID_EZKEY=y +CONFIG_HID_GYRATION=y +CONFIG_HID_LOGITECH=y +# CONFIG_LOGITECH_FF is not set +# CONFIG_LOGIRUMBLEPAD2_FF is not set +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_PANTHERLORD=y +# CONFIG_PANTHERLORD_FF is not set +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SONY=y +CONFIG_HID_SUNPLUS=y +# CONFIG_THRUSTMASTER_FF is not set +# CONFIG_ZEROPLUS_FF is not set CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y @@ -1291,6 +1402,8 @@ CONFIG_USB_DEVICEFS=y # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set CONFIG_USB_MON=y +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set # # USB Host Controller Drivers @@ -1306,6 +1419,8 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_UHCI_HCD is not set # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_WHCI_HCD is not set +# CONFIG_USB_HWA_HCD is not set # CONFIG_USB_MUSB_HDRC is not set # @@ -1314,13 +1429,14 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set # CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; # # -# may also be needed; see USB_STORAGE Help for more information +# see USB_STORAGE Help for more information # CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set @@ -1355,6 +1471,7 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_EMI62 is not set # CONFIG_USB_EMI26 is not set # CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set @@ -1371,13 +1488,15 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set +# CONFIG_UWB is not set CONFIG_MMC=m # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_UNSAFE_RESUME is not set # -# MMC/SD Card Drivers +# MMC/SD/SDIO Card Drivers # CONFIG_MMC_BLOCK=m CONFIG_MMC_BLOCK_BOUNCE=y @@ -1385,11 +1504,12 @@ CONFIG_MMC_BLOCK_BOUNCE=y # CONFIG_MMC_TEST is not set # -# MMC/SD Host Controller Drivers +# MMC/SD/SDIO Host Controller Drivers # CONFIG_MMC_PXA=m # CONFIG_MMC_SDHCI is not set # CONFIG_MMC_TIFM_SD is not set +# CONFIG_MMC_SPI is not set # CONFIG_MMC_SDRICOH_CS is not set # CONFIG_MEMSTICK is not set # CONFIG_ACCESSIBILITY is not set @@ -1400,9 +1520,9 @@ CONFIG_LEDS_CLASS=y # LED drivers # # CONFIG_LEDS_PCA9532 is not set -# CONFIG_LEDS_GPIO is not set -CONFIG_LEDS_CM_X270=y +CONFIG_LEDS_GPIO=m # CONFIG_LEDS_PCA955X is not set +CONFIG_LEDS_DA903X=m # # LED Triggers @@ -1410,6 +1530,7 @@ CONFIG_LEDS_CM_X270=y CONFIG_LEDS_TRIGGERS=y # CONFIG_LEDS_TRIGGER_TIMER is not set CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set # CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set CONFIG_RTC_LIB=y CONFIG_RTC_CLASS=y @@ -1441,21 +1562,32 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_M41T80 is not set # CONFIG_RTC_DRV_S35390A is not set # CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set # # SPI RTC drivers # +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set # # Platform RTC drivers # # CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set # CONFIG_RTC_DRV_DS1511 is not set # CONFIG_RTC_DRV_DS1553 is not set # CONFIG_RTC_DRV_DS1742 is not set # CONFIG_RTC_DRV_STK17TA8 is not set # CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set # CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set CONFIG_RTC_DRV_V3020=y # @@ -1463,14 +1595,12 @@ CONFIG_RTC_DRV_V3020=y # CONFIG_RTC_DRV_SA1100=y # CONFIG_DMADEVICES is not set - -# -# Voltage and Current regulators -# -# CONFIG_REGULATOR is not set +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set # CONFIG_REGULATOR_FIXED_VOLTAGE is not set # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set # CONFIG_REGULATOR_BQ24022 is not set +CONFIG_REGULATOR_DA903X=m # CONFIG_UIO is not set # @@ -1483,12 +1613,13 @@ CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y # CONFIG_EXT3_FS_POSIX_ACL is not set # CONFIG_EXT3_FS_SECURITY is not set -# CONFIG_EXT4DEV_FS is not set +# CONFIG_EXT4_FS is not set CONFIG_JBD=y CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set # CONFIG_OCFS2_FS is not set CONFIG_DNOTIFY=y @@ -1520,6 +1651,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_PROC_FS=y CONFIG_PROC_SYSCTL=y +# CONFIG_PROC_PAGE_MONITOR is not set CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set @@ -1567,6 +1699,7 @@ CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y +# CONFIG_SUNRPC_REGISTER_V4 is not set # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set @@ -1681,16 +1814,24 @@ CONFIG_DEBUG_KERNEL=y CONFIG_FRAME_POINTER=y # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set CONFIG_SYSCTL_SYSCALL_CHECK=y -CONFIG_HAVE_FTRACE=y -CONFIG_HAVE_DYNAMIC_FTRACE=y -# CONFIG_FTRACE is not set +CONFIG_HAVE_FUNCTION_TRACER=y + +# +# Tracers +# +# CONFIG_FUNCTION_TRACER is not set # CONFIG_IRQSOFF_TRACER is not set # CONFIG_SCHED_TRACER is not set # CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set @@ -1705,12 +1846,14 @@ CONFIG_DEBUG_LL=y # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set # CONFIG_SECURITY_FILE_CAPABILITIES is not set CONFIG_CRYPTO=y # # Crypto core or helper # +# CONFIG_CRYPTO_FIPS is not set # CONFIG_CRYPTO_MANAGER is not set # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set @@ -1783,14 +1926,17 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_DEFLATE is not set # CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set # # Library routines # CONFIG_BITREVERSE=y -# CONFIG_GENERIC_FIND_FIRST_BIT is not set -# CONFIG_GENERIC_FIND_NEXT_BIT is not set CONFIG_CRC_CCITT=m # CONFIG_CRC16 is not set # CONFIG_CRC_T10DIF is not set -- GitLab From b25a386b9c68ed23c3b2656f44b523e61480218b Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Sat, 17 Jan 2009 18:01:04 +0100 Subject: [PATCH 0249/4982] [ARM] pxa/magician: Update defconfig This is the touched up result of make magician_defconfig in 2.6.29-rc2. - Enabled USB host and bluetooth: magician has a CSR BlueCore3 connected to the PXA27x OHCI internally. - Made I2C built-in. Signed-off-by: Philipp Zabel Signed-off-by: Eric Miao --- arch/arm/configs/magician_defconfig | 641 +++++++++++++++++++++------- 1 file changed, 475 insertions(+), 166 deletions(-) diff --git a/arch/arm/configs/magician_defconfig b/arch/arm/configs/magician_defconfig index 4d11678584d..7adb09806d4 100644 --- a/arch/arm/configs/magician_defconfig +++ b/arch/arm/configs/magician_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.24-rc6 -# Sun Dec 30 13:02:54 2007 +# Linux kernel version: 2.6.29-rc2 +# Sat Jan 17 17:47:17 2009 # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y @@ -12,6 +12,7 @@ CONFIG_MMU=y # CONFIG_NO_IOPORT is not set CONFIG_GENERIC_HARDIRQS=y CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y CONFIG_LOCKDEP_SUPPORT=y CONFIG_TRACE_IRQFLAGS_SUPPORT=y CONFIG_HARDIRQS_SW_RESEND=y @@ -21,8 +22,8 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_ZONE_DMA=y CONFIG_ARCH_MTD_XIP=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_VECTORS_BASE=0xffff0000 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" @@ -41,16 +42,15 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set -# CONFIG_USER_NS is not set -# CONFIG_PID_NS is not set # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=16 +# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set -# CONFIG_FAIR_GROUP_SCHED is not set -# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y @@ -65,31 +65,41 @@ CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y +CONFIG_AIO=y CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y CONFIG_BLOCK=y # CONFIG_LBD is not set # CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set # CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -104,7 +114,11 @@ CONFIG_IOSCHED_NOOP=y CONFIG_DEFAULT_NOOP=y CONFIG_DEFAULT_IOSCHED="noop" CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set # CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +CONFIG_FREEZER=y # # System Type @@ -114,9 +128,7 @@ CONFIG_CLASSIC_RCU=y # CONFIG_ARCH_REALVIEW is not set # CONFIG_ARCH_VERSATILE is not set # CONFIG_ARCH_AT91 is not set -# CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_EP93XX is not set # CONFIG_ARCH_FOOTBRIDGE is not set @@ -130,41 +142,57 @@ CONFIG_CLASSIC_RCU=y # CONFIG_ARCH_IXP2000 is not set # CONFIG_ARCH_IXP4XX is not set # CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set # CONFIG_ARCH_KS8695 is not set # CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set # CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set # CONFIG_ARCH_PNX4008 is not set CONFIG_ARCH_PXA=y # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set # CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set # CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_W90X900 is not set # # Intel PXA2xx/PXA3xx Implementations # +# CONFIG_ARCH_GUMSTIX is not set +# CONFIG_MACH_INTELMOTE2 is not set # CONFIG_ARCH_LUBBOCK is not set # CONFIG_MACH_LOGICPD_PXA270 is not set # CONFIG_MACH_MAINSTONE is not set +# CONFIG_MACH_MP900C is not set # CONFIG_ARCH_PXA_IDP is not set # CONFIG_PXA_SHARPSL is not set -# CONFIG_MACH_TRIZEPS4 is not set +# CONFIG_ARCH_VIPER is not set +# CONFIG_ARCH_PXA_ESERIES is not set +# CONFIG_TRIZEPS_PXA is not set +# CONFIG_MACH_H5000 is not set # CONFIG_MACH_EM_X270 is not set +# CONFIG_MACH_COLIBRI is not set # CONFIG_MACH_ZYLONITE is not set +# CONFIG_MACH_LITTLETON is not set +# CONFIG_MACH_TAVOREVB is not set +# CONFIG_MACH_SAAR is not set # CONFIG_MACH_ARMCORE is not set +# CONFIG_MACH_CM_X300 is not set CONFIG_MACH_MAGICIAN=y +# CONFIG_MACH_MIOA701 is not set +# CONFIG_MACH_PCM027 is not set +# CONFIG_ARCH_PXA_PALM is not set +# CONFIG_PXA_EZX is not set CONFIG_PXA27x=y - -# -# Boot options -# - -# -# Power management -# +# CONFIG_PXA_PWM is not set +CONFIG_PXA_HAVE_BOARD_IRQS=y # # Processor Type @@ -173,6 +201,7 @@ CONFIG_CPU_32=y CONFIG_CPU_XSCALE=y CONFIG_CPU_32v5=y CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_PABRT_NOIFAR=y CONFIG_CPU_CACHE_VIVT=y CONFIG_CPU_TLB_V4WBI=y CONFIG_CPU_CP15=y @@ -186,6 +215,7 @@ CONFIG_ARM_THUMB=y # CONFIG_OUTER_CACHE is not set CONFIG_IWMMXT=y CONFIG_XSCALE_PMU=y +CONFIG_COMMON_CLKDEV=y # # Bus support @@ -197,28 +227,33 @@ CONFIG_XSCALE_PMU=y # # Kernel Features # -# CONFIG_TICK_ONESHOT is not set -# CONFIG_NO_HZ is not set +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y # CONFIG_HIGH_RES_TIMERS is not set CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 CONFIG_PREEMPT=y CONFIG_HZ=100 CONFIG_AEABI=y CONFIG_OABI_COMPAT=y -# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y # CONFIG_DISCONTIGMEM_MANUAL is not set # CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4096 -# CONFIG_RESOURCES_64BIT is not set -CONFIG_ZONE_DMA_FLAG=1 -CONFIG_BOUNCE=y +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y CONFIG_ALIGNMENT_TRAP=y # @@ -229,9 +264,10 @@ CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_CMDLINE="keepinitrd" # CONFIG_XIP_KERNEL is not set CONFIG_KEXEC=y +CONFIG_ATAGS_PROC=y # -# CPU Frequency scaling +# CPU Power Management # CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_TABLE=y @@ -239,6 +275,7 @@ CONFIG_CPU_FREQ_TABLE=y CONFIG_CPU_FREQ_STAT=y # CONFIG_CPU_FREQ_STAT_DETAILS is not set CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set @@ -247,6 +284,7 @@ CONFIG_CPU_FREQ_GOV_PERFORMANCE=y # CONFIG_CPU_FREQ_GOV_USERSPACE is not set CONFIG_CPU_FREQ_GOV_ONDEMAND=y # CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +# CONFIG_CPU_IDLE is not set # # Floating point emulation @@ -263,6 +301,8 @@ CONFIG_FPE_NWFPE=y # Userspace binary formats # CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y # CONFIG_BINFMT_AOUT is not set # CONFIG_BINFMT_MISC is not set @@ -270,21 +310,18 @@ CONFIG_BINFMT_ELF=y # Power management options # CONFIG_PM=y -# CONFIG_PM_LEGACY is not set # CONFIG_PM_DEBUG is not set CONFIG_PM_SLEEP=y -CONFIG_SUSPEND_UP_POSSIBLE=y CONFIG_SUSPEND=y -CONFIG_APM_EMULATION=y - -# -# Networking -# +CONFIG_SUSPEND_FREEZER=y +# CONFIG_APM_EMULATION is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_NET=y # # Networking options # +CONFIG_COMPAT_NET_DEV_OPS=y CONFIG_PACKET=y CONFIG_PACKET_MMAP=y CONFIG_UNIX=y @@ -316,33 +353,15 @@ CONFIG_IP_PNP=y CONFIG_TCP_CONG_CUBIC=y CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_TCP_MD5SIG is not set -# CONFIG_IP_VS is not set # CONFIG_IPV6 is not set -# CONFIG_INET6_XFRM_TUNNEL is not set -# CONFIG_INET6_TUNNEL is not set # CONFIG_NETWORK_SECMARK is not set -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set - -# -# Core Netfilter Configuration -# -# CONFIG_NETFILTER_NETLINK is not set -# CONFIG_NF_CONNTRACK_ENABLED is not set -# CONFIG_NF_CONNTRACK is not set -# CONFIG_NETFILTER_XTABLES is not set - -# -# IP: Netfilter Configuration -# -# CONFIG_IP_NF_QUEUE is not set -# CONFIG_IP_NF_IPTABLES is not set -# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_NETFILTER is not set # CONFIG_IP_DCCP is not set # CONFIG_IP_SCTP is not set # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set # CONFIG_LLC2 is not set @@ -353,6 +372,7 @@ CONFIG_NETFILTER=y # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set # # Network testing @@ -390,20 +410,17 @@ CONFIG_IRTTY_SIR=m # Dongle support # # CONFIG_DONGLE is not set - -# -# Old SIR device drivers -# -# CONFIG_IRPORT_SIR is not set - -# -# Old Serial dongle support -# +# CONFIG_KINGSUN_DONGLE is not set +# CONFIG_KSDAZZLE_DONGLE is not set +# CONFIG_KS959_DONGLE is not set # # FIR device drivers # +# CONFIG_USB_IRDA is not set +# CONFIG_SIGMATEL_FIR is not set CONFIG_PXA_FICP=m +# CONFIG_MCS_FIR is not set CONFIG_BT=m CONFIG_BT_L2CAP=m CONFIG_BT_SCO=m @@ -417,17 +434,17 @@ CONFIG_BT_HIDP=m # # Bluetooth device drivers # +CONFIG_BT_HCIBTUSB=m +# CONFIG_BT_HCIBTSDIO is not set # CONFIG_BT_HCIUART is not set +# CONFIG_BT_HCIBCM203X is not set +# CONFIG_BT_HCIBPA10X is not set +# CONFIG_BT_HCIBFUSB is not set # CONFIG_BT_HCIVHCI is not set # CONFIG_AF_RXRPC is not set - -# -# Wireless -# -# CONFIG_CFG80211 is not set -# CONFIG_WIRELESS_EXT is not set -# CONFIG_MAC80211 is not set -# CONFIG_IEEE80211 is not set +# CONFIG_PHONET is not set +# CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set @@ -442,25 +459,28 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set # CONFIG_CONNECTOR is not set CONFIG_MTD=y -CONFIG_MTD_DEBUG=y -CONFIG_MTD_DEBUG_VERBOSE=0 +# CONFIG_MTD_DEBUG is not set # CONFIG_MTD_CONCAT is not set CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set # CONFIG_MTD_REDBOOT_PARTS is not set CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set # # User Modules And Translation Layers # -CONFIG_MTD_CHAR=m -CONFIG_MTD_BLKDEVS=m -CONFIG_MTD_BLOCK=m +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y # CONFIG_FTL is not set # CONFIG_NFTL is not set # CONFIG_INFTL is not set @@ -473,6 +493,7 @@ CONFIG_MTD_BLOCK=m # CONFIG_MTD_CFI=y # CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y # CONFIG_MTD_CFI_ADV_OPTIONS is not set CONFIG_MTD_MAP_BANK_WIDTH_1=y CONFIG_MTD_MAP_BANK_WIDTH_2=y @@ -487,6 +508,7 @@ CONFIG_MTD_CFI_I2=y CONFIG_MTD_CFI_INTELEXT=y # CONFIG_MTD_CFI_AMDSTD is not set # CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set # CONFIG_MTD_ABSENT is not set @@ -497,9 +519,7 @@ CONFIG_MTD_CFI_INTELEXT=y # # CONFIG_MTD_COMPLEX_MAPPINGS is not set CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_PHYSMAP_START=0x00000000 -CONFIG_MTD_PHYSMAP_LEN=0x04000000 -CONFIG_MTD_PHYSMAP_BANKWIDTH=4 +# CONFIG_MTD_PHYSMAP_COMPAT is not set # CONFIG_MTD_PXA2XX is not set # CONFIG_MTD_ARM_INTEGRATOR is not set # CONFIG_MTD_SHARP_SL is not set @@ -522,6 +542,12 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=4 # CONFIG_MTD_NAND is not set # CONFIG_MTD_ONENAND is not set +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_QINFO_PROBE is not set + # # UBI - Unsorted block images # @@ -531,10 +557,12 @@ CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_COW_COMMON is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set # CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y # CONFIG_IDE is not set # @@ -547,7 +575,6 @@ CONFIG_BLK_DEV=y # CONFIG_ATA is not set # CONFIG_MD is not set CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_MACVLAN is not set @@ -563,6 +590,20 @@ CONFIG_NETDEVICES=y # # CONFIG_WLAN_PRE80211 is not set # CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set # CONFIG_WAN is not set CONFIG_PPP=m # CONFIG_PPP_MULTILINK is not set @@ -612,7 +653,26 @@ CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TABLET is not set CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set CONFIG_INPUT_MISC=y +# CONFIG_INPUT_ATI_REMOTE is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set CONFIG_INPUT_UINPUT=m # @@ -625,9 +685,11 @@ CONFIG_INPUT_UINPUT=m # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y # CONFIG_VT_HW_CONSOLE_BINDING is not set +# CONFIG_DEVKMEM is not set # CONFIG_SERIAL_NONSTANDARD is not set # @@ -642,6 +704,7 @@ CONFIG_SERIAL_PXA=y # CONFIG_SERIAL_PXA_CONSOLE is not set CONFIG_SERIAL_CORE=y CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set # CONFIG_LEGACY_PTYS is not set # CONFIG_IPMI_HANDLER is not set # CONFIG_HW_RANDOM is not set @@ -649,37 +712,45 @@ CONFIG_UNIX98_PTYS=y # CONFIG_R3964 is not set # CONFIG_RAW_DRIVER is not set # CONFIG_TCG_TPM is not set -CONFIG_I2C=m +CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y CONFIG_I2C_CHARDEV=m +CONFIG_I2C_HELPER_AUTO=y # -# I2C Algorithms +# I2C Hardware Bus support # -# CONFIG_I2C_ALGOBIT is not set -# CONFIG_I2C_ALGOPCF is not set -# CONFIG_I2C_ALGOPCA is not set # -# I2C Hardware Bus support +# I2C system bus drivers (mostly embedded / system-on-chip) # # CONFIG_I2C_GPIO is not set -CONFIG_I2C_PXA=m -# CONFIG_I2C_PXA_SLAVE is not set # CONFIG_I2C_OCORES is not set -# CONFIG_I2C_PARPORT_LIGHT is not set +CONFIG_I2C_PXA=y +# CONFIG_I2C_PXA_SLAVE is not set # CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_STUB is not set # # Miscellaneous I2C Chip support # -# CONFIG_SENSORS_DS1337 is not set -# CONFIG_SENSORS_DS1374 is not set # CONFIG_DS1682 is not set +# CONFIG_AT24 is not set # CONFIG_SENSORS_EEPROM is not set # CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set # CONFIG_SENSORS_PCA9539 is not set # CONFIG_SENSORS_PCF8591 is not set # CONFIG_SENSORS_MAX6875 is not set @@ -688,19 +759,39 @@ CONFIG_I2C_PXA=m # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_SPI is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_GPIO_SYSFS is not set # -# SPI support +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: # -# CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set CONFIG_W1=y # # 1-wire Bus Masters # +# CONFIG_W1_MASTER_DS2490 is not set # CONFIG_W1_MASTER_DS2482 is not set CONFIG_W1_MASTER_DS1WM=y +# CONFIG_W1_MASTER_GPIO is not set # # 1-wire Slaves @@ -709,32 +800,56 @@ CONFIG_W1_MASTER_DS1WM=y # CONFIG_W1_SLAVE_SMEM is not set # CONFIG_W1_SLAVE_DS2433 is not set CONFIG_W1_SLAVE_DS2760=y +# CONFIG_W1_SLAVE_BQ27000 is not set CONFIG_POWER_SUPPLY=y # CONFIG_POWER_SUPPLY_DEBUG is not set CONFIG_PDA_POWER=y -# CONFIG_APM_POWER is not set CONFIG_BATTERY_DS2760=y +# CONFIG_BATTERY_BQ27x00 is not set # CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y # # Sonics Silicon Backplane # -CONFIG_SSB_POSSIBLE=y # CONFIG_SSB is not set # # Multifunction device drivers # +# CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set CONFIG_HTC_EGPIO=y CONFIG_HTC_PASIC3=y +# CONFIG_TPS65010 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set # # Multimedia devices # + +# +# Multimedia core support +# # CONFIG_VIDEO_DEV is not set # CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# # CONFIG_DAB is not set # @@ -745,6 +860,7 @@ CONFIG_HTC_PASIC3=y CONFIG_FB=y # CONFIG_FIRMWARE_EDID is not set # CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y @@ -752,8 +868,8 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_FILLRECT is not set # CONFIG_FB_SYS_COPYAREA is not set # CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set -CONFIG_FB_DEFERRED_IO=y # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -765,13 +881,20 @@ CONFIG_FB_DEFERRED_IO=y # # CONFIG_FB_S1D13XXX is not set CONFIG_FB_PXA=y +CONFIG_FB_PXA_OVERLAY=y +# CONFIG_FB_PXA_SMARTPANEL is not set # CONFIG_FB_PXA_PARAMETERS is not set # CONFIG_FB_MBX is not set +# CONFIG_FB_W100 is not set # CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_LCD_CLASS_DEVICE=y +# CONFIG_LCD_ILI9320 is not set +# CONFIG_LCD_PLATFORM is not set CONFIG_BACKLIGHT_CLASS_DEVICE=y -CONFIG_BACKLIGHT_CORGI=y +# CONFIG_BACKLIGHT_GENERIC is not set # # Display device support @@ -802,15 +925,8 @@ CONFIG_FONT_MINI_4x6=y # CONFIG_FONT_SUN12x22 is not set # CONFIG_FONT_10x18 is not set # CONFIG_LOGO is not set - -# -# Sound -# CONFIG_SOUND=y - -# -# Advanced Linux Sound Architecture -# +CONFIG_SOUND_OSS_CORE=y CONFIG_SND=m CONFIG_SND_TIMER=m CONFIG_SND_PCM=m @@ -824,53 +940,151 @@ CONFIG_SND_SUPPORT_OLD_API=y CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set - -# -# Generic devices -# +CONFIG_SND_DRIVERS=y # CONFIG_SND_DUMMY is not set # CONFIG_SND_MTPAV is not set # CONFIG_SND_SERIAL_U16550 is not set # CONFIG_SND_MPU401 is not set +# CONFIG_SND_ARM is not set +CONFIG_SND_PXA2XX_LIB=m +# CONFIG_SND_USB is not set +CONFIG_SND_SOC=m +CONFIG_SND_PXA2XX_SOC=m +CONFIG_SND_SOC_I2C_AND_SPI=m +# CONFIG_SND_SOC_ALL_CODECS is not set +# CONFIG_SOUND_PRIME is not set +# CONFIG_HID_SUPPORT is not set +CONFIG_HID=m +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set # -# ALSA ARM devices +# Miscellaneous USB options # -# CONFIG_SND_PXA2XX_AC97 is not set +# CONFIG_USB_DEVICEFS is not set +# CONFIG_USB_DEVICE_CLASS is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +CONFIG_USB_MON=m +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set # -# System on Chip audio support +# USB Host Controller Drivers # -CONFIG_SND_SOC=m -CONFIG_SND_PXA2XX_SOC=m +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +# CONFIG_USB_MUSB_HDRC is not set # -# SoC Audio support for SuperH +# USB Device Class drivers # +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set # -# Open Sound System +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; # -# CONFIG_SOUND_PRIME is not set -# CONFIG_HID_SUPPORT is not set -CONFIG_HID=m -# CONFIG_USB_SUPPORT is not set + +# +# see USB_STORAGE Help for more information +# +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set +# CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_USB_GPIO_VBUS is not set CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_UNSAFE_RESUME is not set # -# MMC/SD Card Drivers +# MMC/SD/SDIO Card Drivers # CONFIG_MMC_BLOCK=y CONFIG_MMC_BLOCK_BOUNCE=y CONFIG_SDIO_UART=m +# CONFIG_MMC_TEST is not set # -# MMC/SD Host Controller Drivers +# MMC/SD/SDIO Host Controller Drivers # CONFIG_MMC_PXA=y +# CONFIG_MMC_SDHCI is not set +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_PCA955X is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +# CONFIG_LEDS_TRIGGER_TIMER is not set +# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set CONFIG_RTC_LIB=y CONFIG_RTC_CLASS=y CONFIG_RTC_HCTOSYS=y @@ -899,6 +1113,9 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_PCF8563 is not set # CONFIG_RTC_DRV_PCF8583 is not set # CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set # # SPI RTC drivers @@ -908,17 +1125,26 @@ CONFIG_RTC_INTF_DEV=y # Platform RTC drivers # # CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set # CONFIG_RTC_DRV_DS1553 is not set -# CONFIG_RTC_DRV_STK17TA8 is not set # CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set # CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set # CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set # CONFIG_RTC_DRV_V3020 is not set # # on-CPU RTC drivers # CONFIG_RTC_DRV_SA1100=y +# CONFIG_RTC_DRV_PXA is not set +# CONFIG_DMADEVICES is not set +# CONFIG_REGULATOR is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set # # File systems @@ -927,19 +1153,18 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XATTR is not set # CONFIG_EXT2_FS_XIP is not set # CONFIG_EXT3_FS is not set -# CONFIG_EXT4DEV_FS is not set +# CONFIG_EXT4_FS is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set -# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_FUSE_FS is not set @@ -965,15 +1190,13 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_PROC_FS=y CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set # CONFIG_CONFIGFS_FS is not set - -# -# Miscellaneous filesystems -# +CONFIG_MISC_FILESYSTEMS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set @@ -997,9 +1220,13 @@ CONFIG_JFFS2_CMODE_PRIORITY=y # CONFIG_JFFS2_CMODE_SIZE is not set # CONFIG_JFFS2_CMODE_FAVOURLZO is not set # CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set CONFIG_NETWORK_FILESYSTEMS=y @@ -1007,14 +1234,13 @@ CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set # CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set -# CONFIG_NFSD is not set CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y -# CONFIG_SUNRPC_BIND34 is not set +# CONFIG_SUNRPC_REGISTER_V4 is not set # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set @@ -1076,6 +1302,7 @@ CONFIG_NLS_UTF8=y CONFIG_PRINTK_TIME=y CONFIG_ENABLE_WARN_DEPRECATED=y CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 # CONFIG_MAGIC_SYSRQ is not set # CONFIG_UNUSED_SYMBOLS is not set # CONFIG_DEBUG_FS is not set @@ -1083,15 +1310,18 @@ CONFIG_ENABLE_MUST_CHECK=y CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SHIRQ is not set CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 # CONFIG_SCHED_DEBUG is not set # CONFIG_SCHEDSTATS is not set CONFIG_TIMER_STATS=y +# CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_SLAB is not set -CONFIG_DEBUG_PREEMPT=y +# CONFIG_DEBUG_PREEMPT is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set -CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_LOCK_ALLOC is not set # CONFIG_PROVE_LOCKING is not set # CONFIG_LOCK_STAT is not set @@ -1100,17 +1330,41 @@ CONFIG_DEBUG_MUTEXES=y # CONFIG_DEBUG_KOBJECT is not set CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set -CONFIG_DEBUG_VM=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set CONFIG_FRAME_POINTER=y -CONFIG_FORCED_INLINING=y # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_HAVE_FUNCTION_TRACER=y + +# +# Tracers +# +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set CONFIG_DEBUG_USER=y CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_STACK_USAGE is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set @@ -1119,55 +1373,110 @@ CONFIG_DEBUG_LL=y # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set # CONFIG_SECURITY_FILE_CAPABILITIES is not set CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=m +CONFIG_CRYPTO_ALGAPI2=m +CONFIG_CRYPTO_AEAD2=m CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_BLKCIPHER2=m +CONFIG_CRYPTO_HASH=m +CONFIG_CRYPTO_HASH2=m +CONFIG_CRYPTO_RNG2=m CONFIG_CRYPTO_MANAGER=m +CONFIG_CRYPTO_MANAGER2=m +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=m +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# # CONFIG_CRYPTO_HMAC is not set # CONFIG_CRYPTO_XCBC is not set -# CONFIG_CRYPTO_NULL is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set # CONFIG_CRYPTO_MD4 is not set # CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=m # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA512 is not set -# CONFIG_CRYPTO_WP512 is not set # CONFIG_CRYPTO_TGR192 is not set -# CONFIG_CRYPTO_GF128MUL is not set -CONFIG_CRYPTO_ECB=m -# CONFIG_CRYPTO_CBC is not set -CONFIG_CRYPTO_PCBC=m -# CONFIG_CRYPTO_LRW is not set -# CONFIG_CRYPTO_XTS is not set -# CONFIG_CRYPTO_CRYPTD is not set -# CONFIG_CRYPTO_DES is not set -# CONFIG_CRYPTO_FCRYPT is not set -# CONFIG_CRYPTO_BLOWFISH is not set -# CONFIG_CRYPTO_TWOFISH is not set -# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# # CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set -# CONFIG_CRYPTO_TEA is not set -CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set # CONFIG_CRYPTO_KHAZAD is not set -# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_SALSA20 is not set # CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# # CONFIG_CRYPTO_DEFLATE is not set -# CONFIG_CRYPTO_MICHAEL_MIC is not set -# CONFIG_CRYPTO_CRC32C is not set -# CONFIG_CRYPTO_CAMELLIA is not set -# CONFIG_CRYPTO_TEST is not set -# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set # # Library routines # CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y CONFIG_CRC_CCITT=y # CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set # CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y # CONFIG_CRC7 is not set -- GitLab From 73921ea5b5ccfe0bbe4c1dfcd1a60fdadc7c7d1e Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Sat, 17 Jan 2009 18:45:40 +0100 Subject: [PATCH 0250/4982] [ARM] pxa/magician: Enable backlight Magician uses the generic PWM backlight driver, so select HAVE_PWM. Signed-off-by: Philipp Zabel Signed-off-by: Eric Miao --- arch/arm/configs/magician_defconfig | 4 +++- arch/arm/mach-pxa/Kconfig | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/configs/magician_defconfig b/arch/arm/configs/magician_defconfig index 7adb09806d4..dde50df09bc 100644 --- a/arch/arm/configs/magician_defconfig +++ b/arch/arm/configs/magician_defconfig @@ -4,6 +4,7 @@ # Sat Jan 17 17:47:17 2009 # CONFIG_ARM=y +CONFIG_HAVE_PWM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_TIME=y @@ -191,7 +192,7 @@ CONFIG_MACH_MAGICIAN=y # CONFIG_ARCH_PXA_PALM is not set # CONFIG_PXA_EZX is not set CONFIG_PXA27x=y -# CONFIG_PXA_PWM is not set +CONFIG_PXA_PWM=y CONFIG_PXA_HAVE_BOARD_IRQS=y # @@ -895,6 +896,7 @@ CONFIG_LCD_CLASS_DEVICE=y # CONFIG_LCD_PLATFORM is not set CONFIG_BACKLIGHT_CLASS_DEVICE=y # CONFIG_BACKLIGHT_GENERIC is not set +CONFIG_BACKLIGHT_PWM=y # # Display device support diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index af5b5b463a2..a2ed2aa731b 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -295,6 +295,7 @@ config MACH_MAGICIAN bool "Enable HTC Magician Support" select PXA27x select IWMMXT + select HAVE_PWM select PXA_HAVE_BOARD_IRQS config MACH_MIOA701 -- GitLab From 16c3ea43b8e7b3bf4332f5570263f409e4ca4557 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Sat, 17 Jan 2009 18:45:41 +0100 Subject: [PATCH 0251/4982] [ARM] pxa/magician: setup SSP1 pins for audio Signed-off-by: Philipp Zabel Signed-off-by: Eric Miao --- arch/arm/mach-pxa/magician.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c index 21b821e1a60..4416ee1dc5d 100644 --- a/arch/arm/mach-pxa/magician.c +++ b/arch/arm/mach-pxa/magician.c @@ -66,6 +66,11 @@ static unsigned long magician_pin_config[] __initdata = { GPIO31_I2S_SYNC, GPIO113_I2S_SYSCLK, + /* SSP 1 */ + GPIO23_SSP1_SCLK, + GPIO24_SSP1_SFRM, + GPIO25_SSP1_TXD, + /* SSP 2 */ GPIO19_SSP2_SCLK, GPIO14_SSP2_SFRM, -- GitLab From dee63169884a528000d6318b1c1c2d0b445953f9 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Sat, 17 Jan 2009 18:45:42 +0100 Subject: [PATCH 0252/4982] [ARM] pxa/magician: enable power I2C for max158xx Signed-off-by: Philipp Zabel Signed-off-by: Eric Miao --- arch/arm/mach-pxa/magician.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c index 4416ee1dc5d..f734d663547 100644 --- a/arch/arm/mach-pxa/magician.c +++ b/arch/arm/mach-pxa/magician.c @@ -748,6 +748,7 @@ static void __init magician_init(void) gpio_direction_output(GPIO83_MAGICIAN_nIR_EN, 1); pxa_set_ficp_info(&magician_ficp_info); } + pxa27x_set_i2c_power_info(NULL); pxa_set_i2c_info(NULL); pxa_set_mci_info(&magician_mci_info); pxa_set_ohci_info(&magician_ohci_info); -- GitLab From fcb78d1f615a46509bffd9347b7f36fab4db79df Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Sat, 17 Jan 2009 18:45:43 +0100 Subject: [PATCH 0253/4982] [ARM] pxa/magician: Use SZ_64M for physmap resource Improves readability over the custom #define. Signed-off-by: Philipp Zabel Signed-off-by: Eric Miao --- arch/arm/mach-pxa/magician.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c index f734d663547..b952508d5f9 100644 --- a/arch/arm/mach-pxa/magician.c +++ b/arch/arm/mach-pxa/magician.c @@ -693,11 +693,9 @@ static void magician_set_vpp(struct map_info *map, int vpp) gpio_set_value(EGPIO_MAGICIAN_FLASH_VPP, vpp); } -#define PXA_CS_SIZE 0x04000000 - static struct resource strataflash_resource = { .start = PXA_CS0_PHYS, - .end = PXA_CS0_PHYS + PXA_CS_SIZE - 1, + .end = PXA_CS0_PHYS + SZ_64M - 1, .flags = IORESOURCE_MEM, }; -- GitLab From 51c10bbc3d7d700acd25a004d58a51067983acb6 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Sat, 17 Jan 2009 18:45:44 +0100 Subject: [PATCH 0254/4982] [ARM] pxa/magician: use named initializers for gpio_keys setup Signed-off-by: Philipp Zabel Signed-off-by: Eric Miao --- arch/arm/mach-pxa/magician.c | 39 ++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c index b952508d5f9..b7aafe6823f 100644 --- a/arch/arm/mach-pxa/magician.c +++ b/arch/arm/mach-pxa/magician.c @@ -153,22 +153,31 @@ static struct pxaficp_platform_data magician_ficp_info = { * GPIO Keys */ +#define INIT_KEY(_code, _gpio, _desc) \ + { \ + .code = KEY_##_code, \ + .gpio = _gpio, \ + .desc = _desc, \ + .type = EV_KEY, \ + .wakeup = 1, \ + } + static struct gpio_keys_button magician_button_table[] = { - {KEY_POWER, GPIO0_MAGICIAN_KEY_POWER, 0, "Power button"}, - {KEY_ESC, GPIO37_MAGICIAN_KEY_HANGUP, 0, "Hangup button"}, - {KEY_F10, GPIO38_MAGICIAN_KEY_CONTACTS, 0, "Contacts button"}, - {KEY_CALENDAR, GPIO90_MAGICIAN_KEY_CALENDAR, 0, "Calendar button"}, - {KEY_CAMERA, GPIO91_MAGICIAN_KEY_CAMERA, 0, "Camera button"}, - {KEY_UP, GPIO93_MAGICIAN_KEY_UP, 0, "Up button"}, - {KEY_DOWN, GPIO94_MAGICIAN_KEY_DOWN, 0, "Down button"}, - {KEY_LEFT, GPIO95_MAGICIAN_KEY_LEFT, 0, "Left button"}, - {KEY_RIGHT, GPIO96_MAGICIAN_KEY_RIGHT, 0, "Right button"}, - {KEY_KPENTER, GPIO97_MAGICIAN_KEY_ENTER, 0, "Action button"}, - {KEY_RECORD, GPIO98_MAGICIAN_KEY_RECORD, 0, "Record button"}, - {KEY_VOLUMEUP, GPIO100_MAGICIAN_KEY_VOL_UP, 0, "Volume up"}, - {KEY_VOLUMEDOWN, GPIO101_MAGICIAN_KEY_VOL_DOWN, 0, "Volume down"}, - {KEY_PHONE, GPIO102_MAGICIAN_KEY_PHONE, 0, "Phone button"}, - {KEY_PLAY, GPIO99_MAGICIAN_HEADPHONE_IN, 0, "Headset button"}, + INIT_KEY(POWER, GPIO0_MAGICIAN_KEY_POWER, "Power button"), + INIT_KEY(ESC, GPIO37_MAGICIAN_KEY_HANGUP, "Hangup button"), + INIT_KEY(F10, GPIO38_MAGICIAN_KEY_CONTACTS, "Contacts button"), + INIT_KEY(CALENDAR, GPIO90_MAGICIAN_KEY_CALENDAR, "Calendar button"), + INIT_KEY(CAMERA, GPIO91_MAGICIAN_KEY_CAMERA, "Camera button"), + INIT_KEY(UP, GPIO93_MAGICIAN_KEY_UP, "Up button"), + INIT_KEY(DOWN, GPIO94_MAGICIAN_KEY_DOWN, "Down button"), + INIT_KEY(LEFT, GPIO95_MAGICIAN_KEY_LEFT, "Left button"), + INIT_KEY(RIGHT, GPIO96_MAGICIAN_KEY_RIGHT, "Right button"), + INIT_KEY(KPENTER, GPIO97_MAGICIAN_KEY_ENTER, "Action button"), + INIT_KEY(RECORD, GPIO98_MAGICIAN_KEY_RECORD, "Record button"), + INIT_KEY(VOLUMEUP, GPIO100_MAGICIAN_KEY_VOL_UP, "Volume up"), + INIT_KEY(VOLUMEDOWN, GPIO101_MAGICIAN_KEY_VOL_DOWN, "Volume down"), + INIT_KEY(PHONE, GPIO102_MAGICIAN_KEY_PHONE, "Phone button"), + INIT_KEY(PLAY, GPIO99_MAGICIAN_HEADPHONE_IN, "Headset button"), }; static struct gpio_keys_platform_data gpio_keys_data = { -- GitLab From 48972cc5101dee24243c1b53d409cc27880e7a29 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Wed, 21 Jan 2009 08:18:16 +0100 Subject: [PATCH 0255/4982] ALSA: cmi8330: add OPL3 support Add OPL3 handling to the driver and volume control for FM synthesis. Signed-off-by: Krzysztof Helt Signed-off-by: Takashi Iwai --- sound/isa/Kconfig | 1 + sound/isa/cmi8330.c | 30 ++++++++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index ce0aa044e27..be2d377ff90 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig @@ -94,6 +94,7 @@ config SND_CMI8330 tristate "C-Media CMI8330" select SND_WSS_LIB select SND_SB16_DSP + select SND_OPL3_LIB help Say Y here to include support for soundcards based on the C-Media CMI8330 chip. diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index e49aec700a5..dec6ea52cc4 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -79,6 +80,7 @@ static int sbdma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; static long wssport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; static int wssirq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; static int wssdma[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; +static long fmport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for CMI8330 soundcard."); @@ -107,6 +109,8 @@ MODULE_PARM_DESC(wssirq, "IRQ # for CMI8330 WSS driver."); module_param_array(wssdma, int, NULL, 0444); MODULE_PARM_DESC(wssdma, "DMA for CMI8330 WSS driver."); +module_param_array(fmport, long, NULL, 0444); +MODULE_PARM_DESC(fmport, "FM port # for CMI8330 driver."); #ifdef CONFIG_PNP static int isa_registered; static int pnp_registered; @@ -219,8 +223,10 @@ WSS_SINGLE("3D Control - Switch", 0, CMI8330_RMUX3D, 5, 1, 1), WSS_SINGLE("PC Speaker Playback Volume", 0, CMI8330_OUTPUTVOL, 3, 3, 0), -WSS_SINGLE("FM Playback Switch", 0, - CMI8330_RECMUX, 3, 1, 1), +WSS_DOUBLE("FM Playback Switch", 0, + CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), +WSS_DOUBLE("FM Playback Volume", 0, + CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", CAPTURE, SWITCH), 0, CMI8330_RMUX3D, 7, 1, 1), WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", PLAYBACK, SWITCH), 0, @@ -333,6 +339,7 @@ static int __devinit snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard, wssport[dev] = pnp_port_start(pdev, 0); wssdma[dev] = pnp_dma(pdev, 0); wssirq[dev] = pnp_irq(pdev, 0); + fmport[dev] = pnp_port_start(pdev, 1); /* allocate SB16 resources */ pdev = acard->play; @@ -487,6 +494,7 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) { struct snd_cmi8330 *acard; int i, err; + struct snd_opl3 *opl3; acard = card->private_data; err = snd_wss_create(card, wssport[dev] + 4, -1, @@ -530,6 +538,24 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) snd_printk(KERN_ERR PFX "failed to create pcms\n"); return err; } + if (fmport[dev] != SNDRV_AUTO_PORT) { + if (snd_opl3_create(card, + fmport[dev], fmport[dev] + 2, + OPL3_HW_AUTO, 0, &opl3) < 0) { + snd_printk(KERN_ERR PFX + "no OPL device at 0x%lx-0x%lx ?\n", + fmport[dev], fmport[dev] + 2); + } else { + err = snd_opl3_timer_new(opl3, 0, 1); + if (err < 0) + return err; + + err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); + if (err < 0) + return err; + } + } + strcpy(card->driver, "CMI8330/C3D"); strcpy(card->shortname, "C-Media CMI8330/C3D"); -- GitLab From c9864fd30a28aceef5293f28559c4a2f5a20d7d5 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Wed, 21 Jan 2009 08:19:27 +0100 Subject: [PATCH 0256/4982] ALSA: sscape: use common MPU401 macros Remove local macros which redefines the common ones. Signed-off-by: Krzysztof Helt Signed-off-by: Takashi Iwai --- sound/isa/sscape.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 6a7f842b962..681e2237acb 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -89,9 +89,6 @@ MODULE_DEVICE_TABLE(pnp_card, sscape_pnpids); #endif -#define MPU401_IO(i) ((i) + 0) -#define MIDI_DATA_IO(i) ((i) + 0) -#define MIDI_CTRL_IO(i) ((i) + 1) #define HOST_CTRL_IO(i) ((i) + 2) #define HOST_DATA_IO(i) ((i) + 3) #define ODIE_ADDR_IO(i) ((i) + 4) @@ -327,7 +324,7 @@ static int host_write_ctrl_unsafe(unsigned io_base, unsigned char data, */ static inline int verify_mpu401(const struct snd_mpu401 * mpu) { - return ((inb(MIDI_CTRL_IO(mpu->port)) & 0xc0) == 0x80); + return ((inb(MPU401C(mpu)) & 0xc0) == 0x80); } /* @@ -335,7 +332,7 @@ static inline int verify_mpu401(const struct snd_mpu401 * mpu) */ static inline void initialise_mpu401(const struct snd_mpu401 * mpu) { - outb(0, MIDI_DATA_IO(mpu->port)); + outb(0, MPU401D(mpu)); } /* @@ -1191,12 +1188,11 @@ static int __devinit create_sscape(int dev, struct snd_card *card) } #define MIDI_DEVNUM 0 if (sscape->type != SSCAPE_VIVO) { - err = create_mpu401(card, MIDI_DEVNUM, - MPU401_IO(xport), mpu_irq[dev]); + err = create_mpu401(card, MIDI_DEVNUM, xport, mpu_irq[dev]); if (err < 0) { printk(KERN_ERR "sscape: Failed to create " "MPU-401 device at 0x%x\n", - MPU401_IO(xport)); + xport); goto _release_dma; } -- GitLab From 67e68bde02fe783efc2ce2ca31bdb992f5235f8d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 21 Jan 2009 17:26:05 +0900 Subject: [PATCH 0257/4982] x86: update canary handling during switch Impact: cleanup In switch_to(), instead of taking offset to irq_stack_union.stack, make it a proper percpu access using __percpu_arg() and per_cpu_var(). Signed-off-by: Tejun Heo --- arch/x86/include/asm/system.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h index 52eb748a68a..2fcc70bc85f 100644 --- a/arch/x86/include/asm/system.h +++ b/arch/x86/include/asm/system.h @@ -89,13 +89,15 @@ do { \ #ifdef CONFIG_CC_STACKPROTECTOR #define __switch_canary \ "movq %P[task_canary](%%rsi),%%r8\n\t" \ - "movq %%r8,%%gs:%P[gs_canary]\n\t" -#define __switch_canary_param \ - , [task_canary] "i" (offsetof(struct task_struct, stack_canary)) \ - , [gs_canary] "i" (offsetof(union irq_stack_union, stack_canary)) + "movq %%r8,"__percpu_arg([gs_canary])"\n\t" +#define __switch_canary_oparam \ + , [gs_canary] "=m" (per_cpu_var(irq_stack_union.stack_canary)) +#define __switch_canary_iparam \ + , [task_canary] "i" (offsetof(struct task_struct, stack_canary)) #else /* CC_STACKPROTECTOR */ #define __switch_canary -#define __switch_canary_param +#define __switch_canary_oparam +#define __switch_canary_iparam #endif /* CC_STACKPROTECTOR */ /* Save restore flags to clear handle leaking NT */ @@ -114,13 +116,14 @@ do { \ "jc ret_from_fork\n\t" \ RESTORE_CONTEXT \ : "=a" (last) \ + __switch_canary_oparam \ : [next] "S" (next), [prev] "D" (prev), \ [threadrsp] "i" (offsetof(struct task_struct, thread.sp)), \ [ti_flags] "i" (offsetof(struct thread_info, flags)), \ [tif_fork] "i" (TIF_FORK), \ [thread_info] "i" (offsetof(struct task_struct, stack)), \ [current_task] "m" (per_cpu_var(current_task)) \ - __switch_canary_param \ + __switch_canary_iparam \ : "memory", "cc" __EXTRA_CLOBBER) #endif -- GitLab From 06deef892c7327992434917fb6592c233430803d Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Wed, 21 Jan 2009 17:26:05 +0900 Subject: [PATCH 0258/4982] x86: clean up gdt_page definition Impact: cleanup && more compact percpu area layout with future changes Move 64-bit GDT to page-aligned section and clean up comment formatting. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/kernel/cpu/common.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 3887fcf6e51..a8f0dedcb0c 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -63,23 +63,23 @@ cpumask_t cpu_sibling_setup_map; static struct cpu_dev *this_cpu __cpuinitdata; +DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { #ifdef CONFIG_X86_64 -/* We need valid kernel segments for data and code in long mode too - * IRET will check the segment types kkeil 2000/10/28 - * Also sysret mandates a special GDT layout - */ -/* The TLS descriptors are currently at a different place compared to i386. - Hopefully nobody expects them at a fixed place (Wine?) */ -DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = { + /* + * We need valid kernel segments for data and code in long mode too + * IRET will check the segment types kkeil 2000/10/28 + * Also sysret mandates a special GDT layout + * + * The TLS descriptors are currently at a different place compared to i386. + * Hopefully nobody expects them at a fixed place (Wine?) + */ [GDT_ENTRY_KERNEL32_CS] = { { { 0x0000ffff, 0x00cf9b00 } } }, [GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00af9b00 } } }, [GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9300 } } }, [GDT_ENTRY_DEFAULT_USER32_CS] = { { { 0x0000ffff, 0x00cffb00 } } }, [GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff300 } } }, [GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00affb00 } } }, -} }; #else -DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { [GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00cf9a00 } } }, [GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9200 } } }, [GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00cffa00 } } }, @@ -112,8 +112,8 @@ DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { [GDT_ENTRY_ESPFIX_SS] = { { { 0x00000000, 0x00c09200 } } }, [GDT_ENTRY_PERCPU] = { { { 0x00000000, 0x00000000 } } }, -} }; #endif +} }; EXPORT_PER_CPU_SYMBOL_GPL(gdt_page); #ifdef CONFIG_X86_32 -- GitLab From 299e26992a737804e13e74fdb97cdab470ed19ac Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Wed, 21 Jan 2009 17:26:05 +0900 Subject: [PATCH 0259/4982] x86: fix percpu_write with 64-bit constants Impact: slightly better code generation for percpu_to_op() The processor will sign-extend 32-bit immediate values in 64-bit operations. Use the 'e' constraint ("32-bit signed integer constant, or a symbolic reference known to fit that range") for 64-bit constants. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/percpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index ce980db5e59..0b64af4f13a 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h @@ -75,7 +75,7 @@ do { \ case 8: \ asm(op "q %1,"__percpu_arg(0) \ : "+m" (var) \ - : "r" ((T__)val)); \ + : "re" ((T__)val)); \ break; \ default: __bad_percpu_size(); \ } \ -- GitLab From 0dd76d736eeb3e0ef86c5b103b47ae0e15edebad Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Wed, 21 Jan 2009 17:26:05 +0900 Subject: [PATCH 0260/4982] x86: set %fs to __KERNEL_PERCPU unconditionally for x86_32 Impact: cleanup %fs is currently set to __KERNEL_DS at boot, and conditionally switched to __KERNEL_PERCPU for secondary cpus. Instead, initialize GDT_ENTRY_PERCPU to the same attributes as GDT_ENTRY_KERNEL_DS and set %fs to __KERNEL_PERCPU unconditionally. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/kernel/cpu/common.c | 2 +- arch/x86/kernel/head_32.S | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index a8f0dedcb0c..fbebbcec001 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -111,7 +111,7 @@ DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { [GDT_ENTRY_APMBIOS_BASE+2] = { { { 0x0000ffff, 0x00409200 } } }, [GDT_ENTRY_ESPFIX_SS] = { { { 0x00000000, 0x00c09200 } } }, - [GDT_ENTRY_PERCPU] = { { { 0x00000000, 0x00000000 } } }, + [GDT_ENTRY_PERCPU] = { { { 0x0000ffff, 0x00cf9200 } } }, #endif } }; EXPORT_PER_CPU_SYMBOL_GPL(gdt_page); diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index e835b4eea70..24c0e5cd71e 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -429,12 +429,14 @@ is386: movl $2,%ecx # set MP ljmp $(__KERNEL_CS),$1f 1: movl $(__KERNEL_DS),%eax # reload all the segment registers movl %eax,%ss # after changing gdt. - movl %eax,%fs # gets reset once there's real percpu movl $(__USER_DS),%eax # DS/ES contains default USER segment movl %eax,%ds movl %eax,%es + movl $(__KERNEL_PERCPU), %eax + movl %eax,%fs # set this cpu's percpu + xorl %eax,%eax # Clear GS and LDT movl %eax,%gs lldt %ax @@ -446,8 +448,6 @@ is386: movl $2,%ecx # set MP movb $1, ready cmpb $0,%cl # the first CPU calls start_kernel je 1f - movl $(__KERNEL_PERCPU), %eax - movl %eax,%fs # set this cpu's percpu movl (stack_start), %esp 1: #endif /* CONFIG_SMP */ -- GitLab From 6826c8ff07b5f95df0473a748a9831707079b940 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Wed, 21 Jan 2009 17:26:06 +0900 Subject: [PATCH 0261/4982] x86: merge mmu_context.h Impact: cleanup tj: * changed cpu to unsigned as was done on mmu_context_64.h as cpu id is officially unsigned int * added missing ';' to 32bit version of deactivate_mm() Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/mmu_context.h | 63 +++++++++++++++++++++++++-- arch/x86/include/asm/mmu_context_32.h | 55 ----------------------- arch/x86/include/asm/mmu_context_64.h | 52 ---------------------- 3 files changed, 59 insertions(+), 111 deletions(-) delete mode 100644 arch/x86/include/asm/mmu_context_32.h delete mode 100644 arch/x86/include/asm/mmu_context_64.h diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h index 8aeeb3fd73d..52948df9cd1 100644 --- a/arch/x86/include/asm/mmu_context.h +++ b/arch/x86/include/asm/mmu_context.h @@ -21,11 +21,54 @@ static inline void paravirt_activate_mm(struct mm_struct *prev, int init_new_context(struct task_struct *tsk, struct mm_struct *mm); void destroy_context(struct mm_struct *mm); -#ifdef CONFIG_X86_32 -# include "mmu_context_32.h" -#else -# include "mmu_context_64.h" + +static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) +{ +#ifdef CONFIG_SMP + if (percpu_read(cpu_tlbstate.state) == TLBSTATE_OK) + percpu_write(cpu_tlbstate.state, TLBSTATE_LAZY); +#endif +} + +static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, + struct task_struct *tsk) +{ + unsigned cpu = smp_processor_id(); + + if (likely(prev != next)) { + /* stop flush ipis for the previous mm */ + cpu_clear(cpu, prev->cpu_vm_mask); +#ifdef CONFIG_SMP + percpu_write(cpu_tlbstate.state, TLBSTATE_OK); + percpu_write(cpu_tlbstate.active_mm, next); #endif + cpu_set(cpu, next->cpu_vm_mask); + + /* Re-load page tables */ + load_cr3(next->pgd); + + /* + * load the LDT, if the LDT is different: + */ + if (unlikely(prev->context.ldt != next->context.ldt)) + load_LDT_nolock(&next->context); + } +#ifdef CONFIG_SMP + else { + percpu_write(cpu_tlbstate.state, TLBSTATE_OK); + BUG_ON(percpu_read(cpu_tlbstate.active_mm) != next); + + if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) { + /* We were in lazy tlb mode and leave_mm disabled + * tlb flush IPI delivery. We must reload CR3 + * to make sure to use no freed page tables. + */ + load_cr3(next->pgd); + load_LDT_nolock(&next->context); + } + } +#endif +} #define activate_mm(prev, next) \ do { \ @@ -33,5 +76,17 @@ do { \ switch_mm((prev), (next), NULL); \ } while (0); +#ifdef CONFIG_X86_32 +#define deactivate_mm(tsk, mm) \ +do { \ + loadsegment(gs, 0); \ +} while (0) +#else +#define deactivate_mm(tsk, mm) \ +do { \ + load_gs_index(0); \ + loadsegment(fs, 0); \ +} while (0) +#endif #endif /* _ASM_X86_MMU_CONTEXT_H */ diff --git a/arch/x86/include/asm/mmu_context_32.h b/arch/x86/include/asm/mmu_context_32.h deleted file mode 100644 index 08b53454f83..00000000000 --- a/arch/x86/include/asm/mmu_context_32.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef _ASM_X86_MMU_CONTEXT_32_H -#define _ASM_X86_MMU_CONTEXT_32_H - -static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) -{ -#ifdef CONFIG_SMP - if (percpu_read(cpu_tlbstate.state) == TLBSTATE_OK) - percpu_write(cpu_tlbstate.state, TLBSTATE_LAZY); -#endif -} - -static inline void switch_mm(struct mm_struct *prev, - struct mm_struct *next, - struct task_struct *tsk) -{ - int cpu = smp_processor_id(); - - if (likely(prev != next)) { - /* stop flush ipis for the previous mm */ - cpu_clear(cpu, prev->cpu_vm_mask); -#ifdef CONFIG_SMP - percpu_write(cpu_tlbstate.state, TLBSTATE_OK); - percpu_write(cpu_tlbstate.active_mm, next); -#endif - cpu_set(cpu, next->cpu_vm_mask); - - /* Re-load page tables */ - load_cr3(next->pgd); - - /* - * load the LDT, if the LDT is different: - */ - if (unlikely(prev->context.ldt != next->context.ldt)) - load_LDT_nolock(&next->context); - } -#ifdef CONFIG_SMP - else { - percpu_write(cpu_tlbstate.state, TLBSTATE_OK); - BUG_ON(percpu_read(cpu_tlbstate.active_mm) != next); - - if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) { - /* We were in lazy tlb mode and leave_mm disabled - * tlb flush IPI delivery. We must reload %cr3. - */ - load_cr3(next->pgd); - load_LDT_nolock(&next->context); - } - } -#endif -} - -#define deactivate_mm(tsk, mm) \ - asm("movl %0,%%gs": :"r" (0)); - -#endif /* _ASM_X86_MMU_CONTEXT_32_H */ diff --git a/arch/x86/include/asm/mmu_context_64.h b/arch/x86/include/asm/mmu_context_64.h deleted file mode 100644 index c4572505ab3..00000000000 --- a/arch/x86/include/asm/mmu_context_64.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _ASM_X86_MMU_CONTEXT_64_H -#define _ASM_X86_MMU_CONTEXT_64_H - -static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) -{ -#ifdef CONFIG_SMP - if (percpu_read(cpu_tlbstate.state) == TLBSTATE_OK) - percpu_write(cpu_tlbstate.state, TLBSTATE_LAZY); -#endif -} - -static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, - struct task_struct *tsk) -{ - unsigned cpu = smp_processor_id(); - if (likely(prev != next)) { - /* stop flush ipis for the previous mm */ - cpu_clear(cpu, prev->cpu_vm_mask); -#ifdef CONFIG_SMP - percpu_write(cpu_tlbstate.state, TLBSTATE_OK); - percpu_write(cpu_tlbstate.active_mm, next); -#endif - cpu_set(cpu, next->cpu_vm_mask); - load_cr3(next->pgd); - - if (unlikely(next->context.ldt != prev->context.ldt)) - load_LDT_nolock(&next->context); - } -#ifdef CONFIG_SMP - else { - percpu_write(cpu_tlbstate.state, TLBSTATE_OK); - BUG_ON(percpu_read(cpu_tlbstate.active_mm) != next); - - if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) { - /* We were in lazy tlb mode and leave_mm disabled - * tlb flush IPI delivery. We must reload CR3 - * to make sure to use no freed page tables. - */ - load_cr3(next->pgd); - load_LDT_nolock(&next->context); - } - } -#endif -} - -#define deactivate_mm(tsk, mm) \ -do { \ - load_gs_index(0); \ - asm volatile("movl %0,%%fs"::"r"(0)); \ -} while (0) - -#endif /* _ASM_X86_MMU_CONTEXT_64_H */ -- GitLab From d650a5148593b65a3c3f9a344f46b91b7dfe7713 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Wed, 21 Jan 2009 17:26:06 +0900 Subject: [PATCH 0262/4982] x86: merge irq_regs.h Impact: cleanup, better irq_regs code generation for x86_64 Make 64-bit use the same optimizations as 32-bit. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/irq_regs.h | 36 +++++++++++++++++++++++++----- arch/x86/include/asm/irq_regs_32.h | 31 ------------------------- arch/x86/include/asm/irq_regs_64.h | 1 - arch/x86/kernel/irq_64.c | 3 +++ 4 files changed, 34 insertions(+), 37 deletions(-) delete mode 100644 arch/x86/include/asm/irq_regs_32.h delete mode 100644 arch/x86/include/asm/irq_regs_64.h diff --git a/arch/x86/include/asm/irq_regs.h b/arch/x86/include/asm/irq_regs.h index 89c898ab298..77843225b7e 100644 --- a/arch/x86/include/asm/irq_regs.h +++ b/arch/x86/include/asm/irq_regs.h @@ -1,5 +1,31 @@ -#ifdef CONFIG_X86_32 -# include "irq_regs_32.h" -#else -# include "irq_regs_64.h" -#endif +/* + * Per-cpu current frame pointer - the location of the last exception frame on + * the stack, stored in the per-cpu area. + * + * Jeremy Fitzhardinge + */ +#ifndef _ASM_X86_IRQ_REGS_H +#define _ASM_X86_IRQ_REGS_H + +#include + +#define ARCH_HAS_OWN_IRQ_REGS + +DECLARE_PER_CPU(struct pt_regs *, irq_regs); + +static inline struct pt_regs *get_irq_regs(void) +{ + return percpu_read(irq_regs); +} + +static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs) +{ + struct pt_regs *old_regs; + + old_regs = get_irq_regs(); + percpu_write(irq_regs, new_regs); + + return old_regs; +} + +#endif /* _ASM_X86_IRQ_REGS_32_H */ diff --git a/arch/x86/include/asm/irq_regs_32.h b/arch/x86/include/asm/irq_regs_32.h deleted file mode 100644 index d7ed33ee94e..00000000000 --- a/arch/x86/include/asm/irq_regs_32.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Per-cpu current frame pointer - the location of the last exception frame on - * the stack, stored in the per-cpu area. - * - * Jeremy Fitzhardinge - */ -#ifndef _ASM_X86_IRQ_REGS_32_H -#define _ASM_X86_IRQ_REGS_32_H - -#include - -#define ARCH_HAS_OWN_IRQ_REGS - -DECLARE_PER_CPU(struct pt_regs *, irq_regs); - -static inline struct pt_regs *get_irq_regs(void) -{ - return percpu_read(irq_regs); -} - -static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs) -{ - struct pt_regs *old_regs; - - old_regs = get_irq_regs(); - percpu_write(irq_regs, new_regs); - - return old_regs; -} - -#endif /* _ASM_X86_IRQ_REGS_32_H */ diff --git a/arch/x86/include/asm/irq_regs_64.h b/arch/x86/include/asm/irq_regs_64.h deleted file mode 100644 index 3dd9c0b7027..00000000000 --- a/arch/x86/include/asm/irq_regs_64.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index 1db05247b47..0b254de8408 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c @@ -22,6 +22,9 @@ DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); EXPORT_PER_CPU_SYMBOL(irq_stat); +DEFINE_PER_CPU(struct pt_regs *, irq_regs); +EXPORT_PER_CPU_SYMBOL(irq_regs); + /* * Probabilistic stack overflow check: * -- GitLab From bdbcdd48883940bbd8d17eb01172d58a261a413a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 21 Jan 2009 17:26:06 +0900 Subject: [PATCH 0263/4982] x86: uv cleanup Impact: cleanup Make the following uv related cleanups. * collect visible uv related definitions and interfaces into uv/uv.h and use it. this cleans up the messy situation where on 64bit, uv is defined properly, on 32bit generic it's dummy and on the rest undefined. after this clean up, uv is defined on 64 and dummy on 32. * update uv_flush_tlb_others() such that it takes cpumask of to-be-flushed cpus as argument, instead of that minus self, and returns yet-to-be-flushed cpumask, instead of modifying the passed in parameter. this interface change will ease dummy implementation of uv_flush_tlb_others() and makes uv tlb flush related stuff defined in tlb_uv proper. Signed-off-by: Tejun Heo --- arch/x86/include/asm/genapic_32.h | 7 ---- arch/x86/include/asm/genapic_64.h | 6 --- arch/x86/include/asm/uv/uv.h | 33 +++++++++++++++ arch/x86/include/asm/uv/uv_bau.h | 2 - arch/x86/kernel/cpu/common.c | 1 + arch/x86/kernel/genx2apic_uv_x.c | 1 + arch/x86/kernel/smpboot.c | 1 + arch/x86/kernel/tlb_64.c | 18 ++++---- arch/x86/kernel/tlb_uv.c | 68 ++++++++++++++++++------------- 9 files changed, 83 insertions(+), 54 deletions(-) create mode 100644 arch/x86/include/asm/uv/uv.h diff --git a/arch/x86/include/asm/genapic_32.h b/arch/x86/include/asm/genapic_32.h index 2c05b737ee2..4334502d366 100644 --- a/arch/x86/include/asm/genapic_32.h +++ b/arch/x86/include/asm/genapic_32.h @@ -138,11 +138,4 @@ struct genapic { extern struct genapic *genapic; extern void es7000_update_genapic_to_cluster(void); -enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC}; -#define get_uv_system_type() UV_NONE -#define is_uv_system() 0 -#define uv_wakeup_secondary(a, b) 1 -#define uv_system_init() do {} while (0) - - #endif /* _ASM_X86_GENAPIC_32_H */ diff --git a/arch/x86/include/asm/genapic_64.h b/arch/x86/include/asm/genapic_64.h index adf32fb56aa..7bb092c5905 100644 --- a/arch/x86/include/asm/genapic_64.h +++ b/arch/x86/include/asm/genapic_64.h @@ -51,15 +51,9 @@ extern struct genapic apic_x2apic_phys; extern int acpi_madt_oem_check(char *, char *); extern void apic_send_IPI_self(int vector); -enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC}; -extern enum uv_system_type get_uv_system_type(void); -extern int is_uv_system(void); extern struct genapic apic_x2apic_uv_x; DECLARE_PER_CPU(int, x2apic_extra_bits); -extern void uv_cpu_init(void); -extern void uv_system_init(void); -extern int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip); extern void setup_apic_routing(void); diff --git a/arch/x86/include/asm/uv/uv.h b/arch/x86/include/asm/uv/uv.h new file mode 100644 index 00000000000..dce5fe35013 --- /dev/null +++ b/arch/x86/include/asm/uv/uv.h @@ -0,0 +1,33 @@ +#ifndef _ASM_X86_UV_UV_H +#define _ASM_X86_UV_UV_H + +enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC}; + +#ifdef CONFIG_X86_64 + +extern enum uv_system_type get_uv_system_type(void); +extern int is_uv_system(void); +extern void uv_cpu_init(void); +extern void uv_system_init(void); +extern int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip); +extern const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, + struct mm_struct *mm, + unsigned long va, + unsigned int cpu); + +#else /* X86_64 */ + +static inline enum uv_system_type get_uv_system_type(void) { return UV_NONE; } +static inline int is_uv_system(void) { return 0; } +static inline void uv_cpu_init(void) { } +static inline void uv_system_init(void) { } +static inline int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip) +{ return 1; } +static inline const struct cpumask * +uv_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm, + unsigned long va, unsigned int cpu) +{ return cpumask; } + +#endif /* X86_64 */ + +#endif /* _ASM_X86_UV_UV_H */ diff --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h index 74e6393bfdd..9b0e61bf7a8 100644 --- a/arch/x86/include/asm/uv/uv_bau.h +++ b/arch/x86/include/asm/uv/uv_bau.h @@ -325,8 +325,6 @@ static inline void bau_cpubits_clear(struct bau_local_cpumask *dstp, int nbits) #define cpubit_isset(cpu, bau_local_cpumask) \ test_bit((cpu), (bau_local_cpumask).bits) -extern int uv_flush_tlb_others(struct cpumask *, - struct mm_struct *, unsigned long); extern void uv_bau_message_intr1(void); extern void uv_bau_timeout_intr1(void); diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index fbebbcec001..99904f288d6 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -28,6 +28,7 @@ #include #include #include +#include #endif #include diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index b193e082f6c..bfe36249145 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 869b98840fd..def770b57b5 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -62,6 +62,7 @@ #include #include #include +#include #include #include diff --git a/arch/x86/kernel/tlb_64.c b/arch/x86/kernel/tlb_64.c index e64a32c4882..b8bed841ad6 100644 --- a/arch/x86/kernel/tlb_64.c +++ b/arch/x86/kernel/tlb_64.c @@ -15,8 +15,7 @@ #include #include #include -#include -#include +#include DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) = { &init_mm, 0, }; @@ -206,16 +205,13 @@ void native_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm, unsigned long va) { if (is_uv_system()) { - /* FIXME: could be an percpu_alloc'd thing */ - static DEFINE_PER_CPU(cpumask_t, flush_tlb_mask); - struct cpumask *after_uv_flush = &get_cpu_var(flush_tlb_mask); + unsigned int cpu; - cpumask_andnot(after_uv_flush, cpumask, - cpumask_of(smp_processor_id())); - if (!uv_flush_tlb_others(after_uv_flush, mm, va)) - flush_tlb_others_ipi(after_uv_flush, mm, va); - - put_cpu_var(flush_tlb_uv_cpumask); + cpu = get_cpu(); + cpumask = uv_flush_tlb_others(cpumask, mm, va, cpu); + if (cpumask) + flush_tlb_others_ipi(cpumask, mm, va); + put_cpu(); return; } flush_tlb_others_ipi(cpumask, mm, va); diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c index 690dcf1a27d..aae15dd7260 100644 --- a/arch/x86/kernel/tlb_uv.c +++ b/arch/x86/kernel/tlb_uv.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -209,14 +210,15 @@ static int uv_wait_completion(struct bau_desc *bau_desc, * * Send a broadcast and wait for a broadcast message to complete. * - * The cpumaskp mask contains the cpus the broadcast was sent to. + * The flush_mask contains the cpus the broadcast was sent to. * - * Returns 1 if all remote flushing was done. The mask is zeroed. - * Returns 0 if some remote flushing remains to be done. The mask will have - * some bits still set. + * Returns NULL if all remote flushing was done. The mask is zeroed. + * Returns @flush_mask if some remote flushing remains to be done. The + * mask will have some bits still set. */ -int uv_flush_send_and_wait(int cpu, int this_blade, struct bau_desc *bau_desc, - struct cpumask *cpumaskp) +const struct cpumask *uv_flush_send_and_wait(int cpu, int this_blade, + struct bau_desc *bau_desc, + struct cpumask *flush_mask) { int completion_status = 0; int right_shift; @@ -263,59 +265,69 @@ int uv_flush_send_and_wait(int cpu, int this_blade, struct bau_desc *bau_desc, * Success, so clear the remote cpu's from the mask so we don't * use the IPI method of shootdown on them. */ - for_each_cpu(bit, cpumaskp) { + for_each_cpu(bit, flush_mask) { blade = uv_cpu_to_blade_id(bit); if (blade == this_blade) continue; - cpumask_clear_cpu(bit, cpumaskp); + cpumask_clear_cpu(bit, flush_mask); } - if (!cpumask_empty(cpumaskp)) - return 0; - return 1; + if (!cpumask_empty(flush_mask)) + return flush_mask; + return NULL; } /** * uv_flush_tlb_others - globally purge translation cache of a virtual * address or all TLB's - * @cpumaskp: mask of all cpu's in which the address is to be removed + * @cpumask: mask of all cpu's in which the address is to be removed * @mm: mm_struct containing virtual address range * @va: virtual address to be removed (or TLB_FLUSH_ALL for all TLB's on cpu) + * @cpu: the current cpu * * This is the entry point for initiating any UV global TLB shootdown. * * Purges the translation caches of all specified processors of the given * virtual address, or purges all TLB's on specified processors. * - * The caller has derived the cpumaskp from the mm_struct and has subtracted - * the local cpu from the mask. This function is called only if there - * are bits set in the mask. (e.g. flush_tlb_page()) + * The caller has derived the cpumask from the mm_struct. This function + * is called only if there are bits set in the mask. (e.g. flush_tlb_page()) * - * The cpumaskp is converted into a nodemask of the nodes containing + * The cpumask is converted into a nodemask of the nodes containing * the cpus. * - * Returns 1 if all remote flushing was done. - * Returns 0 if some remote flushing remains to be done. + * Note that this function should be called with preemption disabled. + * + * Returns NULL if all remote flushing was done. + * Returns pointer to cpumask if some remote flushing remains to be + * done. The returned pointer is valid till preemption is re-enabled. */ -int uv_flush_tlb_others(struct cpumask *cpumaskp, struct mm_struct *mm, - unsigned long va) +const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, + struct mm_struct *mm, + unsigned long va, unsigned int cpu) { + static DEFINE_PER_CPU(cpumask_t, flush_tlb_mask); + struct cpumask *flush_mask = &__get_cpu_var(flush_tlb_mask); int i; int bit; int blade; - int cpu; + int uv_cpu; int this_blade; int locals = 0; struct bau_desc *bau_desc; - cpu = uv_blade_processor_id(); + WARN_ON(!in_atomic()); + + cpumask_andnot(flush_mask, cpumask, cpumask_of(cpu)); + + uv_cpu = uv_blade_processor_id(); this_blade = uv_numa_blade_id(); bau_desc = __get_cpu_var(bau_control).descriptor_base; - bau_desc += UV_ITEMS_PER_DESCRIPTOR * cpu; + bau_desc += UV_ITEMS_PER_DESCRIPTOR * uv_cpu; bau_nodes_clear(&bau_desc->distribution, UV_DISTRIBUTION_SIZE); i = 0; - for_each_cpu(bit, cpumaskp) { + for_each_cpu(bit, flush_mask) { blade = uv_cpu_to_blade_id(bit); BUG_ON(blade > (UV_DISTRIBUTION_SIZE - 1)); if (blade == this_blade) { @@ -330,17 +342,17 @@ int uv_flush_tlb_others(struct cpumask *cpumaskp, struct mm_struct *mm, * no off_node flushing; return status for local node */ if (locals) - return 0; + return flush_mask; else - return 1; + return NULL; } __get_cpu_var(ptcstats).requestor++; __get_cpu_var(ptcstats).ntargeted += i; bau_desc->payload.address = va; - bau_desc->payload.sending_cpu = smp_processor_id(); + bau_desc->payload.sending_cpu = cpu; - return uv_flush_send_and_wait(cpu, this_blade, bau_desc, cpumaskp); + return uv_flush_send_and_wait(uv_cpu, this_blade, bau_desc, flush_mask); } /* -- GitLab From 6dd01bedee6c3191643db303a1dc530bad56ec55 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 21 Jan 2009 17:26:06 +0900 Subject: [PATCH 0264/4982] x86: prepare for tlb merge Impact: clean up, ipi vector number reordering for x86_32 Make the following changes to prepare for tlb merge. * reorder x86_32 ip vectors * adjust tlb_32.c and tlb_64.c such that their logics coincide exactly - on spurious invalidate ipi, tlb_32 acks the irq - tlb_64 now has proper memory barriers around clearing flush_cpumask (no change in generated code) * unexport flush_tlb_page from tlb_32.c, there's no user * use unsigned int for cpu id * drop unnecessary includes from tlb_64.c Signed-off-by: Tejun Heo --- arch/x86/include/asm/irq_vectors.h | 33 +++++++++++++++--------------- arch/x86/kernel/tlb_32.c | 10 ++++----- arch/x86/kernel/tlb_64.c | 18 +++++++--------- 3 files changed, 28 insertions(+), 33 deletions(-) diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index a16a2ab2b42..4ee8f800504 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h @@ -49,31 +49,30 @@ * some of the following vectors are 'rare', they are merged * into a single vector (CALL_FUNCTION_VECTOR) to save vector space. * TLB, reschedule and local APIC vectors are performance-critical. - * - * Vectors 0xf0-0xfa are free (reserved for future Linux use). */ #ifdef CONFIG_X86_32 # define SPURIOUS_APIC_VECTOR 0xff # define ERROR_APIC_VECTOR 0xfe -# define INVALIDATE_TLB_VECTOR 0xfd -# define RESCHEDULE_VECTOR 0xfc -# define CALL_FUNCTION_VECTOR 0xfb -# define CALL_FUNCTION_SINGLE_VECTOR 0xfa -# define THERMAL_APIC_VECTOR 0xf0 +# define RESCHEDULE_VECTOR 0xfd +# define CALL_FUNCTION_VECTOR 0xfc +# define CALL_FUNCTION_SINGLE_VECTOR 0xfb +# define THERMAL_APIC_VECTOR 0xfa +/* 0xf1 - 0xf9 : free */ +# define INVALIDATE_TLB_VECTOR 0xf0 #else -#define SPURIOUS_APIC_VECTOR 0xff -#define ERROR_APIC_VECTOR 0xfe -#define RESCHEDULE_VECTOR 0xfd -#define CALL_FUNCTION_VECTOR 0xfc -#define CALL_FUNCTION_SINGLE_VECTOR 0xfb -#define THERMAL_APIC_VECTOR 0xfa -#define THRESHOLD_APIC_VECTOR 0xf9 -#define UV_BAU_MESSAGE 0xf8 -#define INVALIDATE_TLB_VECTOR_END 0xf7 -#define INVALIDATE_TLB_VECTOR_START 0xf0 /* f0-f7 used for TLB flush */ +# define SPURIOUS_APIC_VECTOR 0xff +# define ERROR_APIC_VECTOR 0xfe +# define RESCHEDULE_VECTOR 0xfd +# define CALL_FUNCTION_VECTOR 0xfc +# define CALL_FUNCTION_SINGLE_VECTOR 0xfb +# define THERMAL_APIC_VECTOR 0xfa +# define THRESHOLD_APIC_VECTOR 0xf9 +# define UV_BAU_MESSAGE 0xf8 +# define INVALIDATE_TLB_VECTOR_END 0xf7 +# define INVALIDATE_TLB_VECTOR_START 0xf0 /* f0-f7 used for TLB flush */ #define NUM_INVALIDATE_TLB_VECTORS 8 diff --git a/arch/x86/kernel/tlb_32.c b/arch/x86/kernel/tlb_32.c index abf0808d6fc..93fcb05c7d4 100644 --- a/arch/x86/kernel/tlb_32.c +++ b/arch/x86/kernel/tlb_32.c @@ -84,13 +84,15 @@ EXPORT_SYMBOL_GPL(leave_mm); * * 1) Flush the tlb entries if the cpu uses the mm that's being flushed. * 2) Leave the mm if we are in the lazy tlb mode. + * + * Interrupts are disabled. */ void smp_invalidate_interrupt(struct pt_regs *regs) { - unsigned long cpu; + unsigned int cpu; - cpu = get_cpu(); + cpu = smp_processor_id(); if (!cpumask_test_cpu(cpu, flush_cpumask)) goto out; @@ -112,12 +114,11 @@ void smp_invalidate_interrupt(struct pt_regs *regs) } else leave_mm(cpu); } +out: ack_APIC_irq(); smp_mb__before_clear_bit(); cpumask_clear_cpu(cpu, flush_cpumask); smp_mb__after_clear_bit(); -out: - put_cpu_no_resched(); inc_irq_stat(irq_tlb_count); } @@ -215,7 +216,6 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long va) flush_tlb_others(&mm->cpu_vm_mask, mm, va); preempt_enable(); } -EXPORT_SYMBOL(flush_tlb_page); static void do_flush_tlb_all(void *info) { diff --git a/arch/x86/kernel/tlb_64.c b/arch/x86/kernel/tlb_64.c index b8bed841ad6..19ac661422f 100644 --- a/arch/x86/kernel/tlb_64.c +++ b/arch/x86/kernel/tlb_64.c @@ -1,20 +1,14 @@ #include #include -#include #include #include -#include -#include #include +#include -#include -#include #include #include -#include -#include -#include +#include #include DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) @@ -121,8 +115,8 @@ EXPORT_SYMBOL_GPL(leave_mm); asmlinkage void smp_invalidate_interrupt(struct pt_regs *regs) { - int cpu; - int sender; + unsigned int cpu; + unsigned int sender; union smp_flush_state *f; cpu = smp_processor_id(); @@ -155,14 +149,16 @@ asmlinkage void smp_invalidate_interrupt(struct pt_regs *regs) } out: ack_APIC_irq(); + smp_mb__before_clear_bit(); cpumask_clear_cpu(cpu, to_cpumask(f->flush_cpumask)); + smp_mb__after_clear_bit(); inc_irq_stat(irq_tlb_count); } static void flush_tlb_others_ipi(const struct cpumask *cpumask, struct mm_struct *mm, unsigned long va) { - int sender; + unsigned int sender; union smp_flush_state *f; /* Caller has disabled preemption */ -- GitLab From 02cf94c370e0dc9bf408fe45eb86fe9ad58eaf7f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 21 Jan 2009 17:26:06 +0900 Subject: [PATCH 0265/4982] x86: make x86_32 use tlb_64.c Impact: less contention when issuing invalidate IPI, cleanup Make x86_32 use the same tlb code as 64bit. The 64bit code uses multiple IPI vectors for tlb shootdown to reduce contention. This patch makes x86_32 allocate the same 8 IPIs as x86_64 and share the code paths. Note that the usage of asmlinkage is inconsistent for x86_32 and 64 and calls for further cleanup. This has been noted with a FIXME comment in tlb_64.c. Signed-off-by: Tejun Heo --- arch/x86/include/asm/irq_vectors.h | 7 +- .../x86/include/asm/mach-default/entry_arch.h | 18 +- arch/x86/kernel/Makefile | 2 +- arch/x86/kernel/entry_32.S | 6 +- arch/x86/kernel/irqinit_32.c | 11 +- arch/x86/kernel/tlb_32.c | 239 ------------------ arch/x86/kernel/tlb_64.c | 12 +- 7 files changed, 47 insertions(+), 248 deletions(-) delete mode 100644 arch/x86/kernel/tlb_32.c diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index 4ee8f800504..9a83a10a5d5 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h @@ -58,8 +58,11 @@ # define CALL_FUNCTION_VECTOR 0xfc # define CALL_FUNCTION_SINGLE_VECTOR 0xfb # define THERMAL_APIC_VECTOR 0xfa -/* 0xf1 - 0xf9 : free */ -# define INVALIDATE_TLB_VECTOR 0xf0 +/* 0xf8 - 0xf9 : free */ +# define INVALIDATE_TLB_VECTOR_END 0xf7 +# define INVALIDATE_TLB_VECTOR_START 0xf0 /* f0-f7 used for TLB flush */ + +# define NUM_INVALIDATE_TLB_VECTORS 8 #else diff --git a/arch/x86/include/asm/mach-default/entry_arch.h b/arch/x86/include/asm/mach-default/entry_arch.h index 6b1add8e31d..6fa399ad1de 100644 --- a/arch/x86/include/asm/mach-default/entry_arch.h +++ b/arch/x86/include/asm/mach-default/entry_arch.h @@ -11,10 +11,26 @@ */ #ifdef CONFIG_X86_SMP BUILD_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR) -BUILD_INTERRUPT(invalidate_interrupt,INVALIDATE_TLB_VECTOR) BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR) BUILD_INTERRUPT(call_function_single_interrupt,CALL_FUNCTION_SINGLE_VECTOR) BUILD_INTERRUPT(irq_move_cleanup_interrupt,IRQ_MOVE_CLEANUP_VECTOR) + +BUILD_INTERRUPT3(invalidate_interrupt0,INVALIDATE_TLB_VECTOR_START+0, + smp_invalidate_interrupt) +BUILD_INTERRUPT3(invalidate_interrupt1,INVALIDATE_TLB_VECTOR_START+1, + smp_invalidate_interrupt) +BUILD_INTERRUPT3(invalidate_interrupt2,INVALIDATE_TLB_VECTOR_START+2, + smp_invalidate_interrupt) +BUILD_INTERRUPT3(invalidate_interrupt3,INVALIDATE_TLB_VECTOR_START+3, + smp_invalidate_interrupt) +BUILD_INTERRUPT3(invalidate_interrupt4,INVALIDATE_TLB_VECTOR_START+4, + smp_invalidate_interrupt) +BUILD_INTERRUPT3(invalidate_interrupt5,INVALIDATE_TLB_VECTOR_START+5, + smp_invalidate_interrupt) +BUILD_INTERRUPT3(invalidate_interrupt6,INVALIDATE_TLB_VECTOR_START+6, + smp_invalidate_interrupt) +BUILD_INTERRUPT3(invalidate_interrupt7,INVALIDATE_TLB_VECTOR_START+7, + smp_invalidate_interrupt) #endif /* diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index eb074530c7d..a62a15c2222 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -58,7 +58,7 @@ obj-$(CONFIG_PCI) += early-quirks.o apm-y := apm_32.o obj-$(CONFIG_APM) += apm.o obj-$(CONFIG_X86_SMP) += smp.o -obj-$(CONFIG_X86_SMP) += smpboot.o tsc_sync.o ipi.o tlb_$(BITS).o +obj-$(CONFIG_X86_SMP) += smpboot.o tsc_sync.o ipi.o tlb_64.o obj-$(CONFIG_X86_32_SMP) += smpcommon.o obj-$(CONFIG_X86_64_SMP) += tsc_sync.o smpcommon.o obj-$(CONFIG_X86_TRAMPOLINE) += trampoline_$(BITS).o diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 46469029e9d..a0b91aac72a 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S @@ -672,7 +672,7 @@ common_interrupt: ENDPROC(common_interrupt) CFI_ENDPROC -#define BUILD_INTERRUPT(name, nr) \ +#define BUILD_INTERRUPT3(name, nr, fn) \ ENTRY(name) \ RING0_INT_FRAME; \ pushl $~(nr); \ @@ -680,11 +680,13 @@ ENTRY(name) \ SAVE_ALL; \ TRACE_IRQS_OFF \ movl %esp,%eax; \ - call smp_##name; \ + call fn; \ jmp ret_from_intr; \ CFI_ENDPROC; \ ENDPROC(name) +#define BUILD_INTERRUPT(name, nr) BUILD_INTERRUPT3(name, nr, smp_##name) + /* The include is where all of the SMP etc. interrupts come from */ #include "entry_arch.h" diff --git a/arch/x86/kernel/irqinit_32.c b/arch/x86/kernel/irqinit_32.c index 1507ad4e674..bf629cadec1 100644 --- a/arch/x86/kernel/irqinit_32.c +++ b/arch/x86/kernel/irqinit_32.c @@ -149,8 +149,15 @@ void __init native_init_IRQ(void) */ alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt); - /* IPI for invalidation */ - alloc_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt); + /* IPIs for invalidation */ + alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+0, invalidate_interrupt0); + alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+1, invalidate_interrupt1); + alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+2, invalidate_interrupt2); + alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+3, invalidate_interrupt3); + alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+4, invalidate_interrupt4); + alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+5, invalidate_interrupt5); + alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+6, invalidate_interrupt6); + alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+7, invalidate_interrupt7); /* IPI for generic function call */ alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt); diff --git a/arch/x86/kernel/tlb_32.c b/arch/x86/kernel/tlb_32.c deleted file mode 100644 index 93fcb05c7d4..00000000000 --- a/arch/x86/kernel/tlb_32.c +++ /dev/null @@ -1,239 +0,0 @@ -#include -#include -#include - -#include - -DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) - = { &init_mm, 0, }; - -/* must come after the send_IPI functions above for inlining */ -#include - -/* - * Smarter SMP flushing macros. - * c/o Linus Torvalds. - * - * These mean you can really definitely utterly forget about - * writing to user space from interrupts. (Its not allowed anyway). - * - * Optimizations Manfred Spraul - */ - -static cpumask_var_t flush_cpumask; -static struct mm_struct *flush_mm; -static unsigned long flush_va; -static DEFINE_SPINLOCK(tlbstate_lock); - -/* - * We cannot call mmdrop() because we are in interrupt context, - * instead update mm->cpu_vm_mask. - * - * We need to reload %cr3 since the page tables may be going - * away from under us.. - */ -void leave_mm(int cpu) -{ - BUG_ON(percpu_read(cpu_tlbstate.state) == TLBSTATE_OK); - cpu_clear(cpu, percpu_read(cpu_tlbstate.active_mm)->cpu_vm_mask); - load_cr3(swapper_pg_dir); -} -EXPORT_SYMBOL_GPL(leave_mm); - -/* - * - * The flush IPI assumes that a thread switch happens in this order: - * [cpu0: the cpu that switches] - * 1) switch_mm() either 1a) or 1b) - * 1a) thread switch to a different mm - * 1a1) cpu_clear(cpu, old_mm->cpu_vm_mask); - * Stop ipi delivery for the old mm. This is not synchronized with - * the other cpus, but smp_invalidate_interrupt ignore flush ipis - * for the wrong mm, and in the worst case we perform a superfluous - * tlb flush. - * 1a2) set cpu_tlbstate to TLBSTATE_OK - * Now the smp_invalidate_interrupt won't call leave_mm if cpu0 - * was in lazy tlb mode. - * 1a3) update cpu_tlbstate[].active_mm - * Now cpu0 accepts tlb flushes for the new mm. - * 1a4) cpu_set(cpu, new_mm->cpu_vm_mask); - * Now the other cpus will send tlb flush ipis. - * 1a4) change cr3. - * 1b) thread switch without mm change - * cpu_tlbstate[].active_mm is correct, cpu0 already handles - * flush ipis. - * 1b1) set cpu_tlbstate to TLBSTATE_OK - * 1b2) test_and_set the cpu bit in cpu_vm_mask. - * Atomically set the bit [other cpus will start sending flush ipis], - * and test the bit. - * 1b3) if the bit was 0: leave_mm was called, flush the tlb. - * 2) switch %%esp, ie current - * - * The interrupt must handle 2 special cases: - * - cr3 is changed before %%esp, ie. it cannot use current->{active_,}mm. - * - the cpu performs speculative tlb reads, i.e. even if the cpu only - * runs in kernel space, the cpu could load tlb entries for user space - * pages. - * - * The good news is that cpu_tlbstate is local to each cpu, no - * write/read ordering problems. - */ - -/* - * TLB flush IPI: - * - * 1) Flush the tlb entries if the cpu uses the mm that's being flushed. - * 2) Leave the mm if we are in the lazy tlb mode. - * - * Interrupts are disabled. - */ - -void smp_invalidate_interrupt(struct pt_regs *regs) -{ - unsigned int cpu; - - cpu = smp_processor_id(); - - if (!cpumask_test_cpu(cpu, flush_cpumask)) - goto out; - /* - * This was a BUG() but until someone can quote me the - * line from the intel manual that guarantees an IPI to - * multiple CPUs is retried _only_ on the erroring CPUs - * its staying as a return - * - * BUG(); - */ - - if (flush_mm == percpu_read(cpu_tlbstate.active_mm)) { - if (percpu_read(cpu_tlbstate.state) == TLBSTATE_OK) { - if (flush_va == TLB_FLUSH_ALL) - local_flush_tlb(); - else - __flush_tlb_one(flush_va); - } else - leave_mm(cpu); - } -out: - ack_APIC_irq(); - smp_mb__before_clear_bit(); - cpumask_clear_cpu(cpu, flush_cpumask); - smp_mb__after_clear_bit(); - inc_irq_stat(irq_tlb_count); -} - -void native_flush_tlb_others(const struct cpumask *cpumask, - struct mm_struct *mm, unsigned long va) -{ - /* - * - mask must exist :) - */ - BUG_ON(cpumask_empty(cpumask)); - BUG_ON(!mm); - - /* - * i'm not happy about this global shared spinlock in the - * MM hot path, but we'll see how contended it is. - * AK: x86-64 has a faster method that could be ported. - */ - spin_lock(&tlbstate_lock); - - cpumask_andnot(flush_cpumask, cpumask, cpumask_of(smp_processor_id())); -#ifdef CONFIG_HOTPLUG_CPU - /* If a CPU which we ran on has gone down, OK. */ - cpumask_and(flush_cpumask, flush_cpumask, cpu_online_mask); - if (unlikely(cpumask_empty(flush_cpumask))) { - spin_unlock(&tlbstate_lock); - return; - } -#endif - flush_mm = mm; - flush_va = va; - - /* - * Make the above memory operations globally visible before - * sending the IPI. - */ - smp_mb(); - /* - * We have to send the IPI only to - * CPUs affected. - */ - send_IPI_mask(flush_cpumask, INVALIDATE_TLB_VECTOR); - - while (!cpumask_empty(flush_cpumask)) - /* nothing. lockup detection does not belong here */ - cpu_relax(); - - flush_mm = NULL; - flush_va = 0; - spin_unlock(&tlbstate_lock); -} - -void flush_tlb_current_task(void) -{ - struct mm_struct *mm = current->mm; - - preempt_disable(); - - local_flush_tlb(); - if (cpumask_any_but(&mm->cpu_vm_mask, smp_processor_id()) < nr_cpu_ids) - flush_tlb_others(&mm->cpu_vm_mask, mm, TLB_FLUSH_ALL); - preempt_enable(); -} - -void flush_tlb_mm(struct mm_struct *mm) -{ - - preempt_disable(); - - if (current->active_mm == mm) { - if (current->mm) - local_flush_tlb(); - else - leave_mm(smp_processor_id()); - } - if (cpumask_any_but(&mm->cpu_vm_mask, smp_processor_id()) < nr_cpu_ids) - flush_tlb_others(&mm->cpu_vm_mask, mm, TLB_FLUSH_ALL); - - preempt_enable(); -} - -void flush_tlb_page(struct vm_area_struct *vma, unsigned long va) -{ - struct mm_struct *mm = vma->vm_mm; - - preempt_disable(); - - if (current->active_mm == mm) { - if (current->mm) - __flush_tlb_one(va); - else - leave_mm(smp_processor_id()); - } - - if (cpumask_any_but(&mm->cpu_vm_mask, smp_processor_id()) < nr_cpu_ids) - flush_tlb_others(&mm->cpu_vm_mask, mm, va); - preempt_enable(); -} - -static void do_flush_tlb_all(void *info) -{ - unsigned long cpu = smp_processor_id(); - - __flush_tlb_all(); - if (percpu_read(cpu_tlbstate.state) == TLBSTATE_LAZY) - leave_mm(cpu); -} - -void flush_tlb_all(void) -{ - on_each_cpu(do_flush_tlb_all, NULL, 1); -} - -static int init_flush_cpumask(void) -{ - alloc_cpumask_var(&flush_cpumask, GFP_KERNEL); - return 0; -} -early_initcall(init_flush_cpumask); diff --git a/arch/x86/kernel/tlb_64.c b/arch/x86/kernel/tlb_64.c index 19ac661422f..b3ca1b94065 100644 --- a/arch/x86/kernel/tlb_64.c +++ b/arch/x86/kernel/tlb_64.c @@ -113,7 +113,17 @@ EXPORT_SYMBOL_GPL(leave_mm); * Interrupts are disabled. */ -asmlinkage void smp_invalidate_interrupt(struct pt_regs *regs) +/* + * FIXME: use of asmlinkage is not consistent. On x86_64 it's noop + * but still used for documentation purpose but the usage is slightly + * inconsistent. On x86_32, asmlinkage is regparm(0) but interrupt + * entry calls in with the first parameter in %eax. Maybe define + * intrlinkage? + */ +#ifdef CONFIG_X86_64 +asmlinkage +#endif +void smp_invalidate_interrupt(struct pt_regs *regs) { unsigned int cpu; unsigned int sender; -- GitLab From 16c2d3f895a3bc8d8e4c76c2646a6b750c181299 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 21 Jan 2009 17:26:06 +0900 Subject: [PATCH 0266/4982] x86: rename tlb_64.c to tlb.c Impact: file rename tlb_64.c is now the tlb code for both 32 and 64. Rename it to tlb.c. Signed-off-by: Tejun Heo --- arch/x86/kernel/Makefile | 2 +- arch/x86/kernel/{tlb_64.c => tlb.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename arch/x86/kernel/{tlb_64.c => tlb.c} (100%) diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index a62a15c2222..0626a88fbb4 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -58,7 +58,7 @@ obj-$(CONFIG_PCI) += early-quirks.o apm-y := apm_32.o obj-$(CONFIG_APM) += apm.o obj-$(CONFIG_X86_SMP) += smp.o -obj-$(CONFIG_X86_SMP) += smpboot.o tsc_sync.o ipi.o tlb_64.o +obj-$(CONFIG_X86_SMP) += smpboot.o tsc_sync.o ipi.o tlb.o obj-$(CONFIG_X86_32_SMP) += smpcommon.o obj-$(CONFIG_X86_64_SMP) += tsc_sync.o smpcommon.o obj-$(CONFIG_X86_TRAMPOLINE) += trampoline_$(BITS).o diff --git a/arch/x86/kernel/tlb_64.c b/arch/x86/kernel/tlb.c similarity index 100% rename from arch/x86/kernel/tlb_64.c rename to arch/x86/kernel/tlb.c -- GitLab From 55f4949f5765e7a29863b6d17a774601810732f5 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 21 Jan 2009 10:08:53 +0100 Subject: [PATCH 0267/4982] x86, mm: move tlb.c to arch/x86/mm/ Impact: cleanup Now that it's unified, move the (SMP) TLB flushing code from arch/x86/kernel/ to arch/x86/mm/, where it belongs logically. Signed-off-by: Ingo Molnar --- arch/x86/kernel/Makefile | 2 +- arch/x86/mm/Makefile | 2 ++ arch/x86/{kernel => mm}/tlb.c | 0 3 files changed, 3 insertions(+), 1 deletion(-) rename arch/x86/{kernel => mm}/tlb.c (100%) diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 0626a88fbb4..0b3272f58bd 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -58,7 +58,7 @@ obj-$(CONFIG_PCI) += early-quirks.o apm-y := apm_32.o obj-$(CONFIG_APM) += apm.o obj-$(CONFIG_X86_SMP) += smp.o -obj-$(CONFIG_X86_SMP) += smpboot.o tsc_sync.o ipi.o tlb.o +obj-$(CONFIG_X86_SMP) += smpboot.o tsc_sync.o ipi.o obj-$(CONFIG_X86_32_SMP) += smpcommon.o obj-$(CONFIG_X86_64_SMP) += tsc_sync.o smpcommon.o obj-$(CONFIG_X86_TRAMPOLINE) += trampoline_$(BITS).o diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile index d8cc96a2738..9f05157220f 100644 --- a/arch/x86/mm/Makefile +++ b/arch/x86/mm/Makefile @@ -1,6 +1,8 @@ obj-y := init_$(BITS).o fault.o ioremap.o extable.o pageattr.o mmap.o \ pat.o pgtable.o gup.o +obj-$(CONFIG_X86_SMP) += tlb.o + obj-$(CONFIG_X86_32) += pgtable_32.o iomap_32.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o diff --git a/arch/x86/kernel/tlb.c b/arch/x86/mm/tlb.c similarity index 100% rename from arch/x86/kernel/tlb.c rename to arch/x86/mm/tlb.c -- GitLab From 4ec71fa2d2c3f1040348f2604f4b8ccc833d1c2e Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 21 Jan 2009 10:24:27 +0100 Subject: [PATCH 0268/4982] x86: uv cleanup, build fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: arch/x86/mm/srat_64.c: In function ‘acpi_numa_processor_affinity_init’: arch/x86/mm/srat_64.c:141: error: implicit declaration of function ‘get_uv_system_type’ arch/x86/mm/srat_64.c:141: error: ‘UV_X2APIC’ undeclared (first use in this function) arch/x86/mm/srat_64.c:141: error: (Each undeclared identifier is reported only once arch/x86/mm/srat_64.c:141: error: for each function it appears in.) A couple of UV definitions were moved to asm/uv/uv.h, but srat_64.c did not include that header. Add it. Signed-off-by: Ingo Molnar --- arch/x86/mm/srat_64.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c index 09737c8af07..15df1baee10 100644 --- a/arch/x86/mm/srat_64.c +++ b/arch/x86/mm/srat_64.c @@ -21,6 +21,7 @@ #include #include #include +#include int acpi_numa __initdata; -- GitLab From ace6c6c840878342f698f0da6588dd5ded755369 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 21 Jan 2009 10:32:44 +0100 Subject: [PATCH 0269/4982] x86: make x86_32 use tlb_64.c, build fix, clean up X86_L1_CACHE_BYTES MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: arch/x86/mm/tlb.c:47: error: ‘CONFIG_X86_INTERNODE_CACHE_BYTES’ undeclared here (not in a function) The CONFIG_X86_INTERNODE_CACHE_BYTES symbol is only defined on 64-bit, because vsmp support is 64-bit only. Define it on 32-bit too - where it will always be equal to X86_L1_CACHE_BYTES. Also move the default of X86_L1_CACHE_BYTES (which is separate from the more commonly used L1_CACHE_SHIFT kconfig symbol) from 128 bytes to 64 bytes. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig.cpu | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index cdf4a962323..8eb50ba9161 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -292,15 +292,13 @@ config X86_CPU # Define implied options from the CPU selection here config X86_L1_CACHE_BYTES int - default "128" if GENERIC_CPU || MPSC - default "64" if MK8 || MCORE2 - depends on X86_64 + default "128" if MPSC + default "64" if GENERIC_CPU || MK8 || MCORE2 || X86_32 config X86_INTERNODE_CACHE_BYTES int default "4096" if X86_VSMP default X86_L1_CACHE_BYTES if !X86_VSMP - depends on X86_64 config X86_CMPXCHG def_bool X86_64 || (X86_32 && !M386) -- GitLab From 5b221278d61e3907a5e4104a844b63bc8bb3d43a Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 21 Jan 2009 11:30:07 +0100 Subject: [PATCH 0270/4982] x86: uv cleanup, build fix #2 Fix more build-failure fallout from the UV cleanup - the UV drivers were not updated to include . Signed-off-by: Ingo Molnar --- drivers/misc/sgi-gru/gru.h | 2 ++ drivers/misc/sgi-xp/xp.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/misc/sgi-gru/gru.h b/drivers/misc/sgi-gru/gru.h index f93f03a9e6e..1b5f579df15 100644 --- a/drivers/misc/sgi-gru/gru.h +++ b/drivers/misc/sgi-gru/gru.h @@ -19,6 +19,8 @@ #ifndef __GRU_H__ #define __GRU_H__ +#include + /* * GRU architectural definitions */ diff --git a/drivers/misc/sgi-xp/xp.h b/drivers/misc/sgi-xp/xp.h index 7b4cbd5e03e..069ad3a1c2a 100644 --- a/drivers/misc/sgi-xp/xp.h +++ b/drivers/misc/sgi-xp/xp.h @@ -15,6 +15,8 @@ #include +#include + #ifdef CONFIG_IA64 #include #include /* defines is_shub1() and is_shub2() */ -- GitLab From 4d5d783896fc8c37be88ee5837ca9b3c13fcd55b Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Mon, 19 Jan 2009 16:34:26 -0800 Subject: [PATCH 0271/4982] x86: uaccess: fix style problems Impact: cleanup Fix coding style problems in arch/x86/include/asm/uaccess.h. Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/include/asm/uaccess.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index 4340055b755..aeb3c1b074c 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -121,7 +121,7 @@ extern int __get_user_bad(void); #define __get_user_x(size, ret, x, ptr) \ asm volatile("call __get_user_" #size \ - : "=a" (ret),"=d" (x) \ + : "=a" (ret), "=d" (x) \ : "0" (ptr)) \ /* Careful: we have to cast the result to the type of the pointer @@ -181,7 +181,7 @@ extern int __get_user_bad(void); #define __put_user_x(size, x, ptr, __ret_pu) \ asm volatile("call __put_user_" #size : "=a" (__ret_pu) \ - :"0" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx") + : "0" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx") @@ -276,7 +276,7 @@ do { \ __put_user_asm(x, ptr, retval, "w", "w", "ir", errret); \ break; \ case 4: \ - __put_user_asm(x, ptr, retval, "l", "k", "ir", errret);\ + __put_user_asm(x, ptr, retval, "l", "k", "ir", errret); \ break; \ case 8: \ __put_user_u64((__typeof__(*ptr))(x), ptr, retval); \ -- GitLab From cc86c9e0dc1a41451240b948bb39d46bb2536ae8 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Mon, 19 Jan 2009 16:37:41 -0800 Subject: [PATCH 0272/4982] x86: uaccess: rename __put_user_u64() to __put_user_asm_u64() Impact: cleanup rename __put_user_u64() to __put_user_asm_u64() like __get_user_asm_u64(). Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/include/asm/uaccess.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index aeb3c1b074c..69d2757cca9 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -186,7 +186,7 @@ extern int __get_user_bad(void); #ifdef CONFIG_X86_32 -#define __put_user_u64(x, addr, err) \ +#define __put_user_asm_u64(x, addr, err) \ asm volatile("1: movl %%eax,0(%2)\n" \ "2: movl %%edx,4(%2)\n" \ "3:\n" \ @@ -203,7 +203,7 @@ extern int __get_user_bad(void); asm volatile("call __put_user_8" : "=a" (__ret_pu) \ : "A" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx") #else -#define __put_user_u64(x, ptr, retval) \ +#define __put_user_asm_u64(x, ptr, retval) \ __put_user_asm(x, ptr, retval, "q", "", "Zr", -EFAULT) #define __put_user_x8(x, ptr, __ret_pu) __put_user_x(8, x, ptr, __ret_pu) #endif @@ -279,7 +279,7 @@ do { \ __put_user_asm(x, ptr, retval, "l", "k", "ir", errret); \ break; \ case 8: \ - __put_user_u64((__typeof__(*ptr))(x), ptr, retval); \ + __put_user_asm_u64((__typeof__(*ptr))(x), ptr, retval); \ break; \ default: \ __put_user_bad(); \ -- GitLab From 03b486322e994dde49e67aedb391867b7cf28822 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Tue, 20 Jan 2009 04:36:04 +0100 Subject: [PATCH 0273/4982] x86: make UV support configurable Make X86 SGI Ultraviolet support configurable. Saves about 13K of text size on my modest config. text data bss dec hex filename 6770537 1158680 694356 8623573 8395d5 vmlinux 6757492 1157664 694228 8609384 835e68 vmlinux.nouv Signed-off-by: Nick Piggin Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 7 +++++++ arch/x86/include/asm/uv/uv.h | 6 +++--- arch/x86/kernel/Makefile | 5 +++-- arch/x86/kernel/efi.c | 2 ++ arch/x86/kernel/entry_64.S | 2 ++ arch/x86/kernel/genapic_64.c | 2 ++ arch/x86/kernel/io_apic.c | 2 +- drivers/misc/Kconfig | 4 ++-- 8 files changed, 22 insertions(+), 8 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ef27aed6ff7..5a29b792cb8 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -391,6 +391,13 @@ config X86_RDC321X as R-8610-(G). If you don't have one of these chips, you should say N here. +config X86_UV + bool "SGI Ultraviolet" + depends on X86_64 + help + This option is needed in order to support SGI Ultraviolet systems. + If you don't have one of these, you should say N here. + config SCHED_OMIT_FRAME_POINTER def_bool y prompt "Single-depth WCHAN output" diff --git a/arch/x86/include/asm/uv/uv.h b/arch/x86/include/asm/uv/uv.h index dce5fe35013..8ac1d7e312f 100644 --- a/arch/x86/include/asm/uv/uv.h +++ b/arch/x86/include/asm/uv/uv.h @@ -3,7 +3,7 @@ enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC}; -#ifdef CONFIG_X86_64 +#ifdef CONFIG_X86_UV extern enum uv_system_type get_uv_system_type(void); extern int is_uv_system(void); @@ -15,7 +15,7 @@ extern const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, unsigned long va, unsigned int cpu); -#else /* X86_64 */ +#else /* X86_UV */ static inline enum uv_system_type get_uv_system_type(void) { return UV_NONE; } static inline int is_uv_system(void) { return 0; } @@ -28,6 +28,6 @@ uv_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm, unsigned long va, unsigned int cpu) { return cpumask; } -#endif /* X86_64 */ +#endif /* X86_UV */ #endif /* _ASM_X86_UV_UV_H */ diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 0b3272f58bd..a99437c965c 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -115,10 +115,11 @@ obj-$(CONFIG_SWIOTLB) += pci-swiotlb_64.o # NB rename without _64 ### # 64 bit specific files ifeq ($(CONFIG_X86_64),y) - obj-y += genapic_64.o genapic_flat_64.o genx2apic_uv_x.o tlb_uv.o - obj-y += bios_uv.o uv_irq.o uv_sysfs.o + obj-y += genapic_64.o genapic_flat_64.o obj-y += genx2apic_cluster.o obj-y += genx2apic_phys.o + obj-$(CONFIG_X86_UV) += genx2apic_uv_x.o tlb_uv.o + obj-$(CONFIG_X86_UV) += bios_uv.o uv_irq.o uv_sysfs.o obj-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o obj-$(CONFIG_AUDIT) += audit_64.o diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c index 1119d247fe1..b205272ad39 100644 --- a/arch/x86/kernel/efi.c +++ b/arch/x86/kernel/efi.c @@ -366,10 +366,12 @@ void __init efi_init(void) SMBIOS_TABLE_GUID)) { efi.smbios = config_tables[i].table; printk(" SMBIOS=0x%lx ", config_tables[i].table); +#ifdef CONFIG_X86_UV } else if (!efi_guidcmp(config_tables[i].guid, UV_SYSTEM_TABLE_GUID)) { efi.uv_systab = config_tables[i].table; printk(" UVsystab=0x%lx ", config_tables[i].table); +#endif } else if (!efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID)) { efi.hcdp = config_tables[i].table; diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index c52b6091916..a52703864a1 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -982,8 +982,10 @@ apicinterrupt IRQ_MOVE_CLEANUP_VECTOR \ irq_move_cleanup_interrupt smp_irq_move_cleanup_interrupt #endif +#ifdef CONFIG_X86_UV apicinterrupt UV_BAU_MESSAGE \ uv_bau_message_intr1 uv_bau_message_interrupt +#endif apicinterrupt LOCAL_TIMER_VECTOR \ apic_timer_interrupt smp_apic_timer_interrupt diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c index 2bced78b0b8..e656c272115 100644 --- a/arch/x86/kernel/genapic_64.c +++ b/arch/x86/kernel/genapic_64.c @@ -32,7 +32,9 @@ extern struct genapic apic_x2apic_cluster; struct genapic __read_mostly *genapic = &apic_flat; static struct genapic *apic_probe[] __initdata = { +#ifdef CONFIG_X86_UV &apic_x2apic_uv_x, +#endif &apic_x2apic_phys, &apic_x2apic_cluster, &apic_physflat, diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index f7966039072..e4d36bd56b6 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -3765,7 +3765,7 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) } #endif /* CONFIG_HT_IRQ */ -#ifdef CONFIG_X86_64 +#ifdef CONFIG_X86_UV /* * Re-target the irq to the specified CPU and enable the specified MMR located * on the specified blade to allow the sending of MSIs to the specified CPU. diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 419c378bd24..abcb8459254 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -170,7 +170,7 @@ config ENCLOSURE_SERVICES config SGI_XP tristate "Support communication between SGI SSIs" depends on NET - depends on (IA64_GENERIC || IA64_SGI_SN2 || IA64_SGI_UV || X86_64) && SMP + depends on (IA64_GENERIC || IA64_SGI_SN2 || IA64_SGI_UV || X86_UV) && SMP select IA64_UNCACHED_ALLOCATOR if IA64_GENERIC || IA64_SGI_SN2 select GENERIC_ALLOCATOR if IA64_GENERIC || IA64_SGI_SN2 select SGI_GRU if (IA64_GENERIC || IA64_SGI_UV || X86_64) && SMP @@ -197,7 +197,7 @@ config HP_ILO config SGI_GRU tristate "SGI GRU driver" - depends on (X86_64 || IA64_SGI_UV || IA64_GENERIC) && SMP + depends on (X86_UV || IA64_SGI_UV || IA64_GENERIC) && SMP default n select MMU_NOTIFIER ---help--- -- GitLab From 80c509fdd74f3b158267374cc55156965c8bf930 Mon Sep 17 00:00:00 2001 From: Steve Sakoman Date: Tue, 20 Jan 2009 23:05:27 -0800 Subject: [PATCH 0274/4982] ASoC: Complete Beagleboard support Commit dc06102a0c8b5aa0dd7f9a40ce241e793c252a87 in the asoc tree did not include the necessary Kconfig and Makefile changes. This patch completes the support for Beagleboard Signed-off-by: Steve Sakoman Acked-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/omap/Kconfig | 10 ++++++++++ sound/soc/omap/Makefile | 2 ++ 2 files changed, 12 insertions(+) diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 4f7f0401458..ccd8973683d 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -55,3 +55,13 @@ config SND_OMAP_SOC_OMAP3_PANDORA select SND_SOC_TWL4030 help Say Y if you want to add support for SoC audio on the OMAP3 Pandora. + +config SND_OMAP_SOC_OMAP3_BEAGLE + tristate "SoC Audio support for OMAP3 Beagle" + depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_BEAGLE + select SND_OMAP_SOC_MCBSP + select SND_SOC_TWL4030 + help + Say Y if you want to add support for SoC audio on the Beagleboard. + + diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile index 76fedd96e36..0c9e4ac3766 100644 --- a/sound/soc/omap/Makefile +++ b/sound/soc/omap/Makefile @@ -12,6 +12,7 @@ snd-soc-overo-objs := overo.o snd-soc-omap2evm-objs := omap2evm.o snd-soc-sdp3430-objs := sdp3430.o snd-soc-omap3pandora-objs := omap3pandora.o +snd-soc-omap3beagle-objs := omap3beagle.o obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o @@ -19,3 +20,4 @@ obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o +obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o -- GitLab From aa9c293ae46d71f5add0761bce8db67b162e3f29 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Wed, 21 Jan 2009 15:08:03 +0100 Subject: [PATCH 0275/4982] ALSA: do not create OPL3 timers if there is no OPL3 irq wired Most cards have OPL3 FM synthetiser but they do not have OPL3 interrupt wired to a sound chip or CPU. Do not create OPL3 timers for such cards as the timers are useless witthout interrupt. This patch removes OPL3 timers for following alsa drivers: snd-ad1816a, snd-opti93x, snd-opti92x, snd-sc6000, snd-cmi8330. Signed-off-by: Krzysztof Helt Signed-off-by: Takashi Iwai --- sound/isa/ad1816a/ad1816a.c | 7 ++----- sound/isa/cmi8330.c | 4 ---- sound/isa/opti9xx/opti92x-ad1848.c | 10 ++-------- sound/isa/sc6000.c | 4 ---- 4 files changed, 4 insertions(+), 21 deletions(-) diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c index 77524244a84..3810833d3a8 100644 --- a/sound/isa/ad1816a/ad1816a.c +++ b/sound/isa/ad1816a/ad1816a.c @@ -207,11 +207,8 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard OPL3_HW_AUTO, 0, &opl3) < 0) { printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx.\n", fm_port[dev], fm_port[dev] + 2); } else { - if ((error = snd_opl3_timer_new(opl3, 1, 2)) < 0) { - snd_card_free(card); - return error; - } - if ((error = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { + error = snd_opl3_hwdep_new(opl3, 0, 1, NULL); + if (error < 0) { snd_card_free(card); return error; } diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index dec6ea52cc4..11543795741 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -546,10 +546,6 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) "no OPL device at 0x%lx-0x%lx ?\n", fmport[dev], fmport[dev] + 2); } else { - err = snd_opl3_timer_new(opl3, 0, 1); - if (err < 0) - return err; - err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); if (err < 0) return err; diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 19706b0d849..5deb7e69a02 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -815,14 +815,8 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) chip->fm_port, chip->fm_port + 4 - 1); } if (opl3) { -#ifdef CS4231 - const int t1dev = 1; -#else - const int t1dev = 0; -#endif - if ((error = snd_opl3_timer_new(opl3, t1dev, t1dev+1)) < 0) - return error; - if ((error = snd_opl3_hwdep_new(opl3, 0, 1, &synth)) < 0) + error = snd_opl3_hwdep_new(opl3, 0, 1, &synth); + if (error < 0) return error; } } diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c index ca35924dc3b..bbc53692e68 100644 --- a/sound/isa/sc6000.c +++ b/sound/isa/sc6000.c @@ -576,10 +576,6 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) snd_printk(KERN_ERR PFX "no OPL device at 0x%x-0x%x ?\n", 0x388, 0x388 + 2); } else { - err = snd_opl3_timer_new(opl3, 0, 1); - if (err < 0) - goto err_unmap2; - err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); if (err < 0) goto err_unmap2; -- GitLab From a17ac45a5da76f851faf0b6502f66c1205159469 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Wed, 21 Jan 2009 15:14:09 +0100 Subject: [PATCH 0276/4982] ALSA: ad1816a: enable hardware timer Enable hardware timer with 10 usec resolution. Signed-off-by: Krzysztof Helt Signed-off-by: Takashi Iwai --- include/sound/ad1816a.h | 2 ++ sound/isa/ad1816a/ad1816a.c | 7 +++++++ sound/isa/ad1816a/ad1816a_lib.c | 5 ----- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/include/sound/ad1816a.h b/include/sound/ad1816a.h index b3aa62ee3c8..d010858c33c 100644 --- a/include/sound/ad1816a.h +++ b/include/sound/ad1816a.h @@ -169,5 +169,7 @@ extern int snd_ad1816a_create(struct snd_card *card, unsigned long port, extern int snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_pcm **rpcm); extern int snd_ad1816a_mixer(struct snd_ad1816a *chip); +extern int snd_ad1816a_timer(struct snd_ad1816a *chip, int device, + struct snd_timer **rtimer); #endif /* __SOUND_AD1816A_H */ diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c index 3810833d3a8..15f60107a11 100644 --- a/sound/isa/ad1816a/ad1816a.c +++ b/sound/isa/ad1816a/ad1816a.c @@ -156,6 +156,7 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard struct snd_card_ad1816a *acard; struct snd_ad1816a *chip; struct snd_opl3 *opl3; + struct snd_timer *timer; if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct snd_card_ad1816a))) == NULL) @@ -194,6 +195,12 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard return error; } + error = snd_ad1816a_timer(chip, 0, &timer); + if (error < 0) { + snd_card_free(card); + return error; + } + if (mpu_port[dev] > 0) { if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, mpu_port[dev], 0, mpu_irq[dev], IRQF_DISABLED, diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c index 3bfca7c59ba..1c9e01ecac0 100644 --- a/sound/isa/ad1816a/ad1816a_lib.c +++ b/sound/isa/ad1816a/ad1816a_lib.c @@ -377,7 +377,6 @@ static struct snd_pcm_hardware snd_ad1816a_capture = { .fifo_size = 0, }; -#if 0 /* not used now */ static int snd_ad1816a_timer_close(struct snd_timer *timer) { struct snd_ad1816a *chip = snd_timer_chip(timer); @@ -442,8 +441,6 @@ static struct snd_timer_hardware snd_ad1816a_timer_table = { .start = snd_ad1816a_timer_start, .stop = snd_ad1816a_timer_stop, }; -#endif /* not used now */ - static int snd_ad1816a_playback_open(struct snd_pcm_substream *substream) { @@ -687,7 +684,6 @@ int __devinit snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_p return 0; } -#if 0 /* not used now */ int __devinit snd_ad1816a_timer(struct snd_ad1816a *chip, int device, struct snd_timer **rtimer) { struct snd_timer *timer; @@ -709,7 +705,6 @@ int __devinit snd_ad1816a_timer(struct snd_ad1816a *chip, int device, struct snd *rtimer = timer; return 0; } -#endif /* not used now */ /* * -- GitLab From fb746d0e1365b7472ccc4c3d5b0672b34a092d0b Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Wed, 21 Jan 2009 20:45:41 +0100 Subject: [PATCH 0277/4982] x86: optimise page fault entry, cleanup tsk is already assigned to current, drop the redundant second assignment. Signed-off-by: Johannes Weiner Signed-off-by: Ingo Molnar --- arch/x86/mm/fault.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 033292dc9e2..8f4b859a04b 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -419,7 +419,6 @@ static noinline void pgtable_bad(struct pt_regs *regs, printk(KERN_ALERT "%s: Corrupted page table at address %lx\n", tsk->comm, address); dump_pagetable(address); - tsk = current; tsk->thread.cr2 = address; tsk->thread.trap_no = 14; tsk->thread.error_code = error_code; -- GitLab From 410e9d8f9ce962923b52096d40781a569803c760 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:00:58 +0000 Subject: [PATCH 0278/4982] atm: br2684 internal stats Now that stats are in net_device, use them. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/atm/br2684.c | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/net/atm/br2684.c b/net/atm/br2684.c index ea9438fc685..993cbf6078c 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -83,7 +83,6 @@ struct br2684_dev { struct list_head br2684_devs; int number; struct list_head brvccs; /* one device <=> one vcc (before xmas) */ - struct net_device_stats stats; int mac_was_set; enum br2684_payload payload; }; @@ -148,9 +147,10 @@ static struct net_device *br2684_find_dev(const struct br2684_if_spec *s) * the way for multiple vcc's per itf. Returns true if we can send, * otherwise false */ -static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev, +static int br2684_xmit_vcc(struct sk_buff *skb, struct net_device *dev, struct br2684_vcc *brvcc) { + struct br2684_dev *brdev = BRPRIV(dev); struct atm_vcc *atmvcc; int minheadroom = (brvcc->encaps == e_llc) ? 10 : 2; @@ -211,8 +211,8 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev, } atomic_add(skb->truesize, &sk_atm(atmvcc)->sk_wmem_alloc); ATM_SKB(skb)->atm_options = atmvcc->atm_options; - brdev->stats.tx_packets++; - brdev->stats.tx_bytes += skb->len; + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; atmvcc->send(atmvcc, skb); return 1; } @@ -233,14 +233,14 @@ static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev) brvcc = pick_outgoing_vcc(skb, brdev); if (brvcc == NULL) { pr_debug("no vcc attached to dev %s\n", dev->name); - brdev->stats.tx_errors++; - brdev->stats.tx_carrier_errors++; + dev->stats.tx_errors++; + dev->stats.tx_carrier_errors++; /* netif_stop_queue(dev); */ dev_kfree_skb(skb); read_unlock(&devs_lock); return 0; } - if (!br2684_xmit_vcc(skb, brdev, brvcc)) { + if (!br2684_xmit_vcc(skb, dev, brvcc)) { /* * We should probably use netif_*_queue() here, but that * involves added complication. We need to walk before @@ -248,19 +248,13 @@ static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev) * * Don't free here! this pointer might be no longer valid! */ - brdev->stats.tx_errors++; - brdev->stats.tx_fifo_errors++; + dev->stats.tx_errors++; + dev->stats.tx_fifo_errors++; } read_unlock(&devs_lock); return 0; } -static struct net_device_stats *br2684_get_stats(struct net_device *dev) -{ - pr_debug("br2684_get_stats\n"); - return &BRPRIV(dev)->stats; -} - /* * We remember when the MAC gets set, so we don't override it later with * the ESI of the ATM card of the first VC @@ -430,17 +424,17 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) /* sigh, interface is down? */ if (unlikely(!(net_dev->flags & IFF_UP))) goto dropped; - brdev->stats.rx_packets++; - brdev->stats.rx_bytes += skb->len; + net_dev->stats.rx_packets++; + net_dev->stats.rx_bytes += skb->len; memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data)); netif_rx(skb); return; dropped: - brdev->stats.rx_dropped++; + net_dev->stats.rx_dropped++; goto free_skb; error: - brdev->stats.rx_errors++; + net_dev->stats.rx_errors++; free_skb: dev_kfree_skb(skb); return; @@ -531,8 +525,8 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) skb->next = skb->prev = NULL; br2684_push(atmvcc, skb); - BRPRIV(skb->dev)->stats.rx_bytes -= skb->len; - BRPRIV(skb->dev)->stats.rx_packets--; + skb->dev->stats.rx_bytes -= skb->len; + skb->dev->stats.rx_packets--; skb = next; } @@ -554,7 +548,6 @@ static void br2684_setup(struct net_device *netdev) my_eth_mac_addr = netdev->set_mac_address; netdev->set_mac_address = br2684_mac_addr; netdev->hard_start_xmit = br2684_start_xmit; - netdev->get_stats = br2684_get_stats; INIT_LIST_HEAD(&brdev->brvccs); } @@ -568,7 +561,6 @@ static void br2684_setup_routed(struct net_device *netdev) my_eth_mac_addr = netdev->set_mac_address; netdev->set_mac_address = br2684_mac_addr; netdev->hard_start_xmit = br2684_start_xmit; - netdev->get_stats = br2684_get_stats; netdev->addr_len = 0; netdev->mtu = 1500; netdev->type = ARPHRD_PPP; -- GitLab From 0ba25ff4c669e5395110ba6ab4958a97a9f96922 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:00:59 +0000 Subject: [PATCH 0279/4982] br2684: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/atm/br2684.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/net/atm/br2684.c b/net/atm/br2684.c index 993cbf6078c..334fcd4a4ea 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -259,10 +259,9 @@ static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev) * We remember when the MAC gets set, so we don't override it later with * the ESI of the ATM card of the first VC */ -static int (*my_eth_mac_addr) (struct net_device *, void *); static int br2684_mac_addr(struct net_device *dev, void *p) { - int err = my_eth_mac_addr(dev, p); + int err = eth_mac_addr(dev, p); if (!err) BRPRIV(dev)->mac_was_set = 1; return err; @@ -538,16 +537,20 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) return err; } +static const struct net_device_ops br2684_netdev_ops = { + .ndo_start_xmit = br2684_start_xmit, + .ndo_set_mac_address = br2684_mac_addr, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, +}; + static void br2684_setup(struct net_device *netdev) { struct br2684_dev *brdev = BRPRIV(netdev); ether_setup(netdev); - brdev->net_dev = netdev; - my_eth_mac_addr = netdev->set_mac_address; - netdev->set_mac_address = br2684_mac_addr; - netdev->hard_start_xmit = br2684_start_xmit; + netdev->netdev_ops = &br2684_netdev_ops; INIT_LIST_HEAD(&brdev->brvccs); } @@ -558,9 +561,8 @@ static void br2684_setup_routed(struct net_device *netdev) brdev->net_dev = netdev; netdev->hard_header_len = 0; - my_eth_mac_addr = netdev->set_mac_address; - netdev->set_mac_address = br2684_mac_addr; - netdev->hard_start_xmit = br2684_start_xmit; + + netdev->netdev_ops = &br2684_netdev_ops; netdev->addr_len = 0; netdev->mtu = 1500; netdev->type = ARPHRD_PPP; -- GitLab From 1a6afe8a733a3edaa1816c10ec2a7353ae0ff47b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:00 +0000 Subject: [PATCH 0280/4982] clip: convert to internal network_device_stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/net/atmclip.h | 1 - net/atm/clip.c | 30 ++++++++++++------------------ 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/include/net/atmclip.h b/include/net/atmclip.h index b5a51a7bb36..467c531b8a7 100644 --- a/include/net/atmclip.h +++ b/include/net/atmclip.h @@ -50,7 +50,6 @@ struct atmarp_entry { struct clip_priv { int number; /* for convenience ... */ spinlock_t xoff_lock; /* ensures that pop is atomic (SMP) */ - struct net_device_stats stats; struct net_device *next; /* next CLIP interface */ }; diff --git a/net/atm/clip.c b/net/atm/clip.c index 2d33a83be79..da42fd06b61 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c @@ -214,15 +214,15 @@ static void clip_push(struct atm_vcc *vcc, struct sk_buff *skb) skb->protocol = ((__be16 *) skb->data)[3]; skb_pull(skb, RFC1483LLC_LEN); if (skb->protocol == htons(ETH_P_ARP)) { - PRIV(skb->dev)->stats.rx_packets++; - PRIV(skb->dev)->stats.rx_bytes += skb->len; + skb->dev->stats.rx_packets++; + skb->dev->stats.rx_bytes += skb->len; clip_arp_rcv(skb); return; } } clip_vcc->last_use = jiffies; - PRIV(skb->dev)->stats.rx_packets++; - PRIV(skb->dev)->stats.rx_bytes += skb->len; + skb->dev->stats.rx_packets++; + skb->dev->stats.rx_bytes += skb->len; memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data)); netif_rx(skb); } @@ -372,7 +372,7 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev) if (!skb->dst) { printk(KERN_ERR "clip_start_xmit: skb->dst == NULL\n"); dev_kfree_skb(skb); - clip_priv->stats.tx_dropped++; + dev->stats.tx_dropped++; return 0; } if (!skb->dst->neighbour) { @@ -380,13 +380,13 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev) skb->dst->neighbour = clip_find_neighbour(skb->dst, 1); if (!skb->dst->neighbour) { dev_kfree_skb(skb); /* lost that one */ - clip_priv->stats.tx_dropped++; + dev->stats.tx_dropped++; return 0; } #endif printk(KERN_ERR "clip_start_xmit: NO NEIGHBOUR !\n"); dev_kfree_skb(skb); - clip_priv->stats.tx_dropped++; + dev->stats.tx_dropped++; return 0; } entry = NEIGH2ENTRY(skb->dst->neighbour); @@ -400,7 +400,7 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev) skb_queue_tail(&entry->neigh->arp_queue, skb); else { dev_kfree_skb(skb); - clip_priv->stats.tx_dropped++; + dev->stats.tx_dropped++; } return 0; } @@ -423,8 +423,8 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev) printk(KERN_WARNING "clip_start_xmit: XOFF->XOFF transition\n"); return 0; } - clip_priv->stats.tx_packets++; - clip_priv->stats.tx_bytes += skb->len; + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; vcc->send(vcc, skb); if (atm_may_send(vcc, 0)) { entry->vccs->xoff = 0; @@ -443,11 +443,6 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } -static struct net_device_stats *clip_get_stats(struct net_device *dev) -{ - return &PRIV(dev)->stats; -} - static int clip_mkip(struct atm_vcc *vcc, int timeout) { struct clip_vcc *clip_vcc; @@ -501,8 +496,8 @@ static int clip_mkip(struct atm_vcc *vcc, int timeout) skb_get(skb); clip_push(vcc, skb); - PRIV(skb->dev)->stats.rx_packets--; - PRIV(skb->dev)->stats.rx_bytes -= len; + skb->dev->stats.rx_packets--; + skb->dev->stats.rx_bytes -= len; kfree_skb(skb); } @@ -561,7 +556,6 @@ static void clip_setup(struct net_device *dev) { dev->hard_start_xmit = clip_start_xmit; /* sg_xmit ... */ - dev->get_stats = clip_get_stats; dev->type = ARPHRD_ATM; dev->hard_header_len = RFC1483LLC_LEN; dev->mtu = RFC1626_MTU; -- GitLab From 162619e59ab456aa689080726cb2ada24c1dfddd Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:01 +0000 Subject: [PATCH 0281/4982] lec: convert to internal network_device_stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/atm/lec.c | 44 +++++++++++++++++--------------------------- net/atm/lec.h | 1 - 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/net/atm/lec.c b/net/atm/lec.c index e5e301550e8..63ff8b9a85b 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -62,7 +62,6 @@ static unsigned char bridge_ula_lec[] = { 0x01, 0x80, 0xc2, 0x00, 0x00 }; static int lec_open(struct net_device *dev); static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev); static int lec_close(struct net_device *dev); -static struct net_device_stats *lec_get_stats(struct net_device *dev); static void lec_init(struct net_device *dev); static struct lec_arp_table *lec_arp_find(struct lec_priv *priv, const unsigned char *mac_addr); @@ -218,28 +217,28 @@ static unsigned char *get_tr_dst(unsigned char *packet, unsigned char *rdesc) static int lec_open(struct net_device *dev) { - struct lec_priv *priv = netdev_priv(dev); - netif_start_queue(dev); - memset(&priv->stats, 0, sizeof(struct net_device_stats)); + memset(&dev->stats, 0, sizeof(struct net_device_stats)); return 0; } -static __inline__ void -lec_send(struct atm_vcc *vcc, struct sk_buff *skb, struct lec_priv *priv) +static void +lec_send(struct atm_vcc *vcc, struct sk_buff *skb) { + struct net_device *dev = skb->dev; + ATM_SKB(skb)->vcc = vcc; ATM_SKB(skb)->atm_options = vcc->atm_options; atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc); if (vcc->send(vcc, skb) < 0) { - priv->stats.tx_dropped++; + dev->stats.tx_dropped++; return; } - priv->stats.tx_packets++; - priv->stats.tx_bytes += skb->len; + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; } static void lec_tx_timeout(struct net_device *dev) @@ -270,7 +269,7 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev) pr_debug("lec_start_xmit called\n"); if (!priv->lecd) { printk("%s:No lecd attached\n", dev->name); - priv->stats.tx_errors++; + dev->stats.tx_errors++; netif_stop_queue(dev); return -EUNATCH; } @@ -345,7 +344,7 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev) GFP_ATOMIC); dev_kfree_skb(skb); if (skb2 == NULL) { - priv->stats.tx_dropped++; + dev->stats.tx_dropped++; return 0; } skb = skb2; @@ -380,7 +379,7 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev) ("%s:lec_start_xmit: tx queue full or no arp entry, dropping, ", dev->name); pr_debug("MAC address %pM\n", lec_h->h_dest); - priv->stats.tx_dropped++; + dev->stats.tx_dropped++; dev_kfree_skb(skb); } goto out; @@ -392,10 +391,10 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev) while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) { pr_debug("lec.c: emptying tx queue, "); pr_debug("MAC address %pM\n", lec_h->h_dest); - lec_send(vcc, skb2, priv); + lec_send(vcc, skb2); } - lec_send(vcc, skb, priv); + lec_send(vcc, skb); if (!atm_may_send(vcc, 0)) { struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc); @@ -427,15 +426,6 @@ static int lec_close(struct net_device *dev) return 0; } -/* - * Get the current statistics. - * This may be called with the card open or closed. - */ -static struct net_device_stats *lec_get_stats(struct net_device *dev) -{ - return &((struct lec_priv *)netdev_priv(dev))->stats; -} - static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) { unsigned long flags; @@ -810,8 +800,8 @@ static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb) else #endif skb->protocol = eth_type_trans(skb, dev); - priv->stats.rx_packets++; - priv->stats.rx_bytes += skb->len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data)); netif_rx(skb); } @@ -1887,7 +1877,7 @@ restart: lec_arp_hold(entry); spin_unlock_irqrestore(&priv->lec_arp_lock, flags); while ((skb = skb_dequeue(&entry->tx_wait)) != NULL) - lec_send(vcc, skb, entry->priv); + lec_send(vcc, skb); entry->last_used = jiffies; entry->status = ESI_FORWARD_DIRECT; lec_arp_put(entry); @@ -2305,7 +2295,7 @@ restart: lec_arp_hold(entry); spin_unlock_irqrestore(&priv->lec_arp_lock, flags); while ((skb = skb_dequeue(&entry->tx_wait)) != NULL) - lec_send(vcc, skb, entry->priv); + lec_send(vcc, skb); entry->last_used = jiffies; entry->status = ESI_FORWARD_DIRECT; lec_arp_put(entry); diff --git a/net/atm/lec.h b/net/atm/lec.h index 0d376682c1a..9d14d196cc1 100644 --- a/net/atm/lec.h +++ b/net/atm/lec.h @@ -69,7 +69,6 @@ struct lane2_ops { #define LEC_ARP_TABLE_SIZE 16 struct lec_priv { - struct net_device_stats stats; unsigned short lecid; /* Lecid of this client */ struct hlist_head lec_arp_empty_ones; /* Used for storing VCC's that don't have a MAC address attached yet */ -- GitLab From 004b3225c016efc90cbfe43cdf69c6331462bc56 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:02 +0000 Subject: [PATCH 0282/4982] lec: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/atm/lec.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/net/atm/lec.c b/net/atm/lec.c index 63ff8b9a85b..c0cba9a037e 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -667,17 +667,19 @@ static void lec_set_multicast_list(struct net_device *dev) return; } +static const struct net_device_ops lec_netdev_ops = { + .ndo_open = lec_open, + .ndo_stop = lec_close, + .ndo_start_xmit = lec_start_xmit, + .ndo_change_mtu = lec_change_mtu, + .ndo_tx_timeout = lec_tx_timeout, + .ndo_set_multicast_list = lec_set_multicast_list, +}; + + static void lec_init(struct net_device *dev) { - dev->change_mtu = lec_change_mtu; - dev->open = lec_open; - dev->stop = lec_close; - dev->hard_start_xmit = lec_start_xmit; - dev->tx_timeout = lec_tx_timeout; - - dev->get_stats = lec_get_stats; - dev->set_multicast_list = lec_set_multicast_list; - dev->do_ioctl = NULL; + dev->netdev_ops = &lec_netdev_ops; printk("%s: Initialized!\n", dev->name); } -- GitLab From b51414b69148433a79af5dc93463a0489492a788 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:03 +0000 Subject: [PATCH 0283/4982] netrom: convert to internal net_device_stats Signed-off-by: Stephen Hemminger Acked-by: Ralf Baechle Signed-off-by: David S. Miller --- include/net/netrom.h | 4 ---- net/netrom/af_netrom.c | 2 +- net/netrom/nr_dev.c | 14 ++------------ 3 files changed, 3 insertions(+), 17 deletions(-) diff --git a/include/net/netrom.h b/include/net/netrom.h index f06852bba62..15696b1fd30 100644 --- a/include/net/netrom.h +++ b/include/net/netrom.h @@ -59,10 +59,6 @@ enum { #define NR_MAX_WINDOW_SIZE 127 /* Maximum Window Allowable - 127 */ #define NR_MAX_PACKET_SIZE 236 /* Maximum Packet Length - 236 */ -struct nr_private { - struct net_device_stats stats; -}; - struct nr_sock { struct sock sock; ax25_address user_addr, source_addr, dest_addr; diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index e9c05b8f4f4..cba7849de98 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -1432,7 +1432,7 @@ static int __init nr_proto_init(void) struct net_device *dev; sprintf(name, "nr%d", i); - dev = alloc_netdev(sizeof(struct nr_private), name, nr_setup); + dev = alloc_netdev(0, name, nr_setup); if (!dev) { printk(KERN_ERR "NET/ROM: nr_proto_init - unable to allocate device structure\n"); goto fail; diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c index 6caf459665f..5b9a31a6e68 100644 --- a/net/netrom/nr_dev.c +++ b/net/netrom/nr_dev.c @@ -42,7 +42,7 @@ int nr_rx_ip(struct sk_buff *skb, struct net_device *dev) { - struct net_device_stats *stats = netdev_priv(dev); + struct net_device_stats *stats = &dev->stats; if (!netif_running(dev)) { stats->rx_dropped++; @@ -171,8 +171,7 @@ static int nr_close(struct net_device *dev) static int nr_xmit(struct sk_buff *skb, struct net_device *dev) { - struct nr_private *nr = netdev_priv(dev); - struct net_device_stats *stats = &nr->stats; + struct net_device_stats *stats = &dev->stats; unsigned int len = skb->len; if (!nr_route_frame(skb, NULL)) { @@ -187,13 +186,6 @@ static int nr_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } -static struct net_device_stats *nr_get_stats(struct net_device *dev) -{ - struct nr_private *nr = netdev_priv(dev); - - return &nr->stats; -} - static const struct header_ops nr_header_ops = { .create = nr_header, .rebuild= nr_rebuild_header, @@ -215,6 +207,4 @@ void nr_setup(struct net_device *dev) /* New-style flags. */ dev->flags = IFF_NOARP; - - dev->get_stats = nr_get_stats; } -- GitLab From 0f6c5c8e79781974c0e660fd8bfc659b101b44fd Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:04 +0000 Subject: [PATCH 0284/4982] netrom: convert to net_device_ops Signed-off-by: Stephen Hemminger Acked-by: Ralf Baechle Signed-off-by: David S. Miller --- net/netrom/nr_dev.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c index 5b9a31a6e68..351372463fe 100644 --- a/net/netrom/nr_dev.c +++ b/net/netrom/nr_dev.c @@ -191,19 +191,21 @@ static const struct header_ops nr_header_ops = { .rebuild= nr_rebuild_header, }; +static const struct net_device_ops nr_netdev_ops = { + .ndo_open = nr_open, + .ndo_stop = nr_close, + .ndo_start_xmit = nr_xmit, + .ndo_set_mac_address = nr_set_mac_address, +}; void nr_setup(struct net_device *dev) { dev->mtu = NR_MAX_PACKET_SIZE; - dev->hard_start_xmit = nr_xmit; - dev->open = nr_open; - dev->stop = nr_close; - + dev->netdev_ops = &nr_netdev_ops; dev->header_ops = &nr_header_ops; dev->hard_header_len = NR_NETWORK_LEN + NR_TRANSPORT_LEN; dev->addr_len = AX25_ADDR_LEN; dev->type = ARPHRD_NETROM; - dev->set_mac_address = nr_set_mac_address; /* New-style flags. */ dev->flags = IFF_NOARP; -- GitLab From d289d120b46d9b6c68448b1d1c6d3edb94cdbde6 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:05 +0000 Subject: [PATCH 0285/4982] rose: convert to internal net_device_stats Signed-off-by: Stephen Hemminger Acked-by: Ralf Baechle Signed-off-by: David S. Miller --- net/rose/af_rose.c | 3 +-- net/rose/rose_dev.c | 10 ++-------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 01392649b46..65013962658 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -1587,8 +1587,7 @@ static int __init rose_proto_init(void) char name[IFNAMSIZ]; sprintf(name, "rose%d", i); - dev = alloc_netdev(sizeof(struct net_device_stats), - name, rose_setup); + dev = alloc_netdev(0, name, rose_setup); if (!dev) { printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate memory\n"); rc = -ENOMEM; diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c index 12cfcf09556..ddb56670718 100644 --- a/net/rose/rose_dev.c +++ b/net/rose/rose_dev.c @@ -57,7 +57,7 @@ static int rose_rebuild_header(struct sk_buff *skb) { #ifdef CONFIG_INET struct net_device *dev = skb->dev; - struct net_device_stats *stats = netdev_priv(dev); + struct net_device_stats *stats = &dev->stats; unsigned char *bp = (unsigned char *)skb->data; struct sk_buff *skbn; unsigned int len; @@ -133,7 +133,7 @@ static int rose_close(struct net_device *dev) static int rose_xmit(struct sk_buff *skb, struct net_device *dev) { - struct net_device_stats *stats = netdev_priv(dev); + struct net_device_stats *stats = &dev->stats; if (!netif_running(dev)) { printk(KERN_ERR "ROSE: rose_xmit - called when iface is down\n"); @@ -144,11 +144,6 @@ static int rose_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } -static struct net_device_stats *rose_get_stats(struct net_device *dev) -{ - return netdev_priv(dev); -} - static const struct header_ops rose_header_ops = { .create = rose_header, .rebuild= rose_rebuild_header, @@ -169,5 +164,4 @@ void rose_setup(struct net_device *dev) /* New-style flags. */ dev->flags = IFF_NOARP; - dev->get_stats = rose_get_stats; } -- GitLab From 3170c6568776a58e1eeec8ff949a65f5cf5d7ceb Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:06 +0000 Subject: [PATCH 0286/4982] rose: convert to network_device_ops Signed-off-by: Stephen Hemminger Acked-by: Ralf Baechle Signed-off-by: David S. Miller --- net/rose/rose_dev.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c index ddb56670718..7dcf2569613 100644 --- a/net/rose/rose_dev.c +++ b/net/rose/rose_dev.c @@ -149,18 +149,22 @@ static const struct header_ops rose_header_ops = { .rebuild= rose_rebuild_header, }; +static const struct net_device_ops rose_netdev_ops = { + .ndo_open = rose_open, + .ndo_stop = rose_close, + .ndo_start_xmit = rose_xmit, + .ndo_set_mac_address = rose_set_mac_address, +}; + void rose_setup(struct net_device *dev) { dev->mtu = ROSE_MAX_PACKET_SIZE - 2; - dev->hard_start_xmit = rose_xmit; - dev->open = rose_open; - dev->stop = rose_close; + dev->netdev_ops = &rose_netdev_ops; dev->header_ops = &rose_header_ops; dev->hard_header_len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN; dev->addr_len = ROSE_ADDR_LEN; dev->type = ARPHRD_ROSE; - dev->set_mac_address = rose_set_mac_address; /* New-style flags. */ dev->flags = IFF_NOARP; -- GitLab From 60961ce4d09db7c1ba49da3375123a18845ec864 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:07 +0000 Subject: [PATCH 0287/4982] appletalk: remove unneeded stubs With net_device_ops if set_mac_address is null, then error is -EOPNOTSUPPORTED. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/appletalk/dev.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/net/appletalk/dev.c b/net/appletalk/dev.c index d856a62ab50..72277d70c98 100644 --- a/net/appletalk/dev.c +++ b/net/appletalk/dev.c @@ -9,22 +9,20 @@ #include #include +#ifdef CONFIG_COMPAT_NET_DEV_OPS static int ltalk_change_mtu(struct net_device *dev, int mtu) { return -EINVAL; } - -static int ltalk_mac_addr(struct net_device *dev, void *addr) -{ - return -EINVAL; -} +#endif static void ltalk_setup(struct net_device *dev) { /* Fill in the fields of the device structure with localtalk-generic values. */ +#ifdef CONFIG_COMPAT_NET_DEV_OPS dev->change_mtu = ltalk_change_mtu; - dev->set_mac_address = ltalk_mac_addr; +#endif dev->type = ARPHRD_LOCALTLK; dev->hard_header_len = LTALK_HLEN; -- GitLab From 5803c5122acb31ebf5f76b1a9925e2c72c4436e1 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:08 +0000 Subject: [PATCH 0288/4982] arcnet: convert to internal stats Use pre-existing network_device_stats inside network_device rather than own private structure. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/arcnet/arc-rawmode.c | 2 +- drivers/net/arcnet/arcnet.c | 38 ++++++++------------------ drivers/net/arcnet/capmode.c | 2 +- drivers/net/arcnet/rfc1051.c | 12 ++++---- drivers/net/arcnet/rfc1201.c | 47 ++++++++++++++++---------------- include/linux/arcdevice.h | 2 -- 6 files changed, 42 insertions(+), 61 deletions(-) diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c index 3ff9affb1a9..da017cbb5f6 100644 --- a/drivers/net/arcnet/arc-rawmode.c +++ b/drivers/net/arcnet/arc-rawmode.c @@ -102,7 +102,7 @@ static void rx(struct net_device *dev, int bufnum, skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); if (skb == NULL) { BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n"); - lp->stats.rx_dropped++; + dev->stats.rx_dropped++; return; } skb_put(skb, length + ARC_HDR_SIZE); diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 6b53e5ed125..34b9a4d0da3 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -105,7 +105,6 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, const void *daddr, const void *saddr, unsigned len); static int arcnet_rebuild_header(struct sk_buff *skb); -static struct net_device_stats *arcnet_get_stats(struct net_device *dev); static int go_tx(struct net_device *dev); static int debug = ARCNET_DEBUG; @@ -347,7 +346,6 @@ static void arcdev_setup(struct net_device *dev) dev->stop = arcnet_close; dev->hard_start_xmit = arcnet_send_packet; dev->tx_timeout = arcnet_timeout; - dev->get_stats = arcnet_get_stats; } struct net_device *alloc_arcdev(char *name) @@ -583,8 +581,8 @@ static int arcnet_rebuild_header(struct sk_buff *skb) } else { BUGMSG(D_NORMAL, "I don't understand ethernet protocol %Xh addresses!\n", type); - lp->stats.tx_errors++; - lp->stats.tx_aborted_errors++; + dev->stats.tx_errors++; + dev->stats.tx_aborted_errors++; } /* if we couldn't resolve the address... give up. */ @@ -645,7 +643,7 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev) !proto->ack_tx) { /* done right away and we don't want to acknowledge the package later - forget about it now */ - lp->stats.tx_bytes += skb->len; + dev->stats.tx_bytes += skb->len; freeskb = 1; } else { /* do it the 'split' way */ @@ -709,7 +707,7 @@ static int go_tx(struct net_device *dev) /* start sending */ ACOMMAND(TXcmd | (lp->cur_tx << 3)); - lp->stats.tx_packets++; + dev->stats.tx_packets++; lp->lasttrans_dest = lp->lastload_dest; lp->lastload_dest = 0; lp->excnak_pending = 0; @@ -732,11 +730,11 @@ static void arcnet_timeout(struct net_device *dev) msg = " - missed IRQ?"; } else { msg = ""; - lp->stats.tx_aborted_errors++; + dev->stats.tx_aborted_errors++; lp->timed_out = 1; ACOMMAND(NOTXcmd | (lp->cur_tx << 3)); } - lp->stats.tx_errors++; + dev->stats.tx_errors++; /* make sure we didn't miss a TX or a EXC NAK IRQ */ AINTMASK(0); @@ -865,8 +863,8 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) "transmit was not acknowledged! " "(status=%Xh, dest=%02Xh)\n", status, lp->lasttrans_dest); - lp->stats.tx_errors++; - lp->stats.tx_carrier_errors++; + dev->stats.tx_errors++; + dev->stats.tx_carrier_errors++; } else { BUGMSG(D_DURING, "broadcast was not acknowledged; that's normal " @@ -905,7 +903,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) if (txbuf != -1) { if (lp->outgoing.proto->continue_tx(dev, txbuf)) { /* that was the last segment */ - lp->stats.tx_bytes += lp->outgoing.skb->len; + dev->stats.tx_bytes += lp->outgoing.skb->len; if(!lp->outgoing.proto->ack_tx) { dev_kfree_skb_irq(lp->outgoing.skb); @@ -930,7 +928,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) } if (status & lp->intmask & RECONflag) { ACOMMAND(CFLAGScmd | CONFIGclear); - lp->stats.tx_carrier_errors++; + dev->stats.tx_carrier_errors++; BUGMSG(D_RECON, "Network reconfiguration detected (status=%Xh)\n", status); @@ -1038,8 +1036,8 @@ static void arcnet_rx(struct net_device *dev, int bufnum) "(%d+4 bytes)\n", bufnum, pkt.hard.source, pkt.hard.dest, length); - lp->stats.rx_packets++; - lp->stats.rx_bytes += length + ARC_HDR_SIZE; + dev->stats.rx_packets++; + dev->stats.rx_bytes += length + ARC_HDR_SIZE; /* call the right receiver for the protocol */ if (arc_proto_map[soft->proto]->is_ip) { @@ -1067,18 +1065,6 @@ static void arcnet_rx(struct net_device *dev, int bufnum) } - -/* - * Get the current statistics. This may be called with the card open or - * closed. - */ -static struct net_device_stats *arcnet_get_stats(struct net_device *dev) -{ - struct arcnet_local *lp = netdev_priv(dev); - return &lp->stats; -} - - static void null_rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length) { diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index 30580bbe252..1613929ff30 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -119,7 +119,7 @@ static void rx(struct net_device *dev, int bufnum, skb = alloc_skb(length + ARC_HDR_SIZE + sizeof(int), GFP_ATOMIC); if (skb == NULL) { BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n"); - lp->stats.rx_dropped++; + dev->stats.rx_dropped++; return; } skb_put(skb, length + ARC_HDR_SIZE + sizeof(int)); diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c index 49d39a9cb69..06f8fa2f8f2 100644 --- a/drivers/net/arcnet/rfc1051.c +++ b/drivers/net/arcnet/rfc1051.c @@ -88,7 +88,6 @@ MODULE_LICENSE("GPL"); */ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev) { - struct arcnet_local *lp = netdev_priv(dev); struct archdr *pkt = (struct archdr *) skb->data; struct arc_rfc1051 *soft = &pkt->soft.rfc1051; int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE; @@ -112,8 +111,8 @@ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev) return htons(ETH_P_ARP); default: - lp->stats.rx_errors++; - lp->stats.rx_crc_errors++; + dev->stats.rx_errors++; + dev->stats.rx_crc_errors++; return 0; } @@ -140,7 +139,7 @@ static void rx(struct net_device *dev, int bufnum, skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); if (skb == NULL) { BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n"); - lp->stats.rx_dropped++; + dev->stats.rx_dropped++; return; } skb_put(skb, length + ARC_HDR_SIZE); @@ -168,7 +167,6 @@ static void rx(struct net_device *dev, int bufnum, static int build_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, uint8_t daddr) { - struct arcnet_local *lp = netdev_priv(dev); int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE; struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size); struct arc_rfc1051 *soft = &pkt->soft.rfc1051; @@ -184,8 +182,8 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, default: BUGMSG(D_NORMAL, "RFC1051: I don't understand protocol %d (%Xh)\n", type, type); - lp->stats.tx_errors++; - lp->stats.tx_aborted_errors++; + dev->stats.tx_errors++; + dev->stats.tx_aborted_errors++; return 0; } diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c index 2303d3a1f4b..745530651c4 100644 --- a/drivers/net/arcnet/rfc1201.c +++ b/drivers/net/arcnet/rfc1201.c @@ -92,7 +92,6 @@ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev) { struct archdr *pkt = (struct archdr *) skb->data; struct arc_rfc1201 *soft = &pkt->soft.rfc1201; - struct arcnet_local *lp = netdev_priv(dev); int hdr_size = ARC_HDR_SIZE + RFC1201_HDR_SIZE; /* Pull off the arcnet header. */ @@ -121,8 +120,8 @@ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev) case ARC_P_NOVELL_EC: return htons(ETH_P_802_3); default: - lp->stats.rx_errors++; - lp->stats.rx_crc_errors++; + dev->stats.rx_errors++; + dev->stats.rx_crc_errors++; return 0; } @@ -172,8 +171,8 @@ static void rx(struct net_device *dev, int bufnum, in->sequence, soft->split_flag, soft->sequence); lp->rfc1201.aborted_seq = soft->sequence; dev_kfree_skb_irq(in->skb); - lp->stats.rx_errors++; - lp->stats.rx_missed_errors++; + dev->stats.rx_errors++; + dev->stats.rx_missed_errors++; in->skb = NULL; } in->sequence = soft->sequence; @@ -181,7 +180,7 @@ static void rx(struct net_device *dev, int bufnum, skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); if (skb == NULL) { BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n"); - lp->stats.rx_dropped++; + dev->stats.rx_dropped++; return; } skb_put(skb, length + ARC_HDR_SIZE); @@ -213,7 +212,7 @@ static void rx(struct net_device *dev, int bufnum, BUGMSG(D_EXTRA, "ARP source address was 00h, set to %02Xh.\n", saddr); - lp->stats.rx_crc_errors++; + dev->stats.rx_crc_errors++; *cptr = saddr; } else { BUGMSG(D_DURING, "ARP source address (%Xh) is fine.\n", @@ -222,8 +221,8 @@ static void rx(struct net_device *dev, int bufnum, } else { BUGMSG(D_NORMAL, "funny-shaped ARP packet. (%Xh, %Xh)\n", arp->ar_hln, arp->ar_pln); - lp->stats.rx_errors++; - lp->stats.rx_crc_errors++; + dev->stats.rx_errors++; + dev->stats.rx_crc_errors++; } } BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); @@ -257,8 +256,8 @@ static void rx(struct net_device *dev, int bufnum, soft->split_flag); dev_kfree_skb_irq(in->skb); in->skb = NULL; - lp->stats.rx_errors++; - lp->stats.rx_missed_errors++; + dev->stats.rx_errors++; + dev->stats.rx_missed_errors++; in->lastpacket = in->numpackets = 0; } if (soft->split_flag & 1) { /* first packet in split */ @@ -269,8 +268,8 @@ static void rx(struct net_device *dev, int bufnum, "(splitflag=%d, seq=%d)\n", in->sequence, soft->split_flag, soft->sequence); - lp->stats.rx_errors++; - lp->stats.rx_missed_errors++; + dev->stats.rx_errors++; + dev->stats.rx_missed_errors++; dev_kfree_skb_irq(in->skb); } in->sequence = soft->sequence; @@ -281,8 +280,8 @@ static void rx(struct net_device *dev, int bufnum, BUGMSG(D_EXTRA, "incoming packet more than 16 segments; dropping. (splitflag=%d)\n", soft->split_flag); lp->rfc1201.aborted_seq = soft->sequence; - lp->stats.rx_errors++; - lp->stats.rx_length_errors++; + dev->stats.rx_errors++; + dev->stats.rx_length_errors++; return; } in->skb = skb = alloc_skb(508 * in->numpackets + ARC_HDR_SIZE, @@ -290,7 +289,7 @@ static void rx(struct net_device *dev, int bufnum, if (skb == NULL) { BUGMSG(D_NORMAL, "(split) memory squeeze, dropping packet.\n"); lp->rfc1201.aborted_seq = soft->sequence; - lp->stats.rx_dropped++; + dev->stats.rx_dropped++; return; } skb->dev = dev; @@ -314,8 +313,8 @@ static void rx(struct net_device *dev, int bufnum, "first! (splitflag=%d, seq=%d, aborted=%d)\n", soft->split_flag, soft->sequence, lp->rfc1201.aborted_seq); - lp->stats.rx_errors++; - lp->stats.rx_missed_errors++; + dev->stats.rx_errors++; + dev->stats.rx_missed_errors++; } return; } @@ -325,8 +324,8 @@ static void rx(struct net_device *dev, int bufnum, if (packetnum <= in->lastpacket - 1) { BUGMSG(D_EXTRA, "duplicate splitpacket ignored! (splitflag=%d)\n", soft->split_flag); - lp->stats.rx_errors++; - lp->stats.rx_frame_errors++; + dev->stats.rx_errors++; + dev->stats.rx_frame_errors++; return; } /* "bad" duplicate, kill reassembly */ @@ -336,8 +335,8 @@ static void rx(struct net_device *dev, int bufnum, lp->rfc1201.aborted_seq = soft->sequence; dev_kfree_skb_irq(in->skb); in->skb = NULL; - lp->stats.rx_errors++; - lp->stats.rx_missed_errors++; + dev->stats.rx_errors++; + dev->stats.rx_missed_errors++; in->lastpacket = in->numpackets = 0; return; } @@ -404,8 +403,8 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, default: BUGMSG(D_NORMAL, "RFC1201: I don't understand protocol %d (%Xh)\n", type, type); - lp->stats.tx_errors++; - lp->stats.tx_aborted_errors++; + dev->stats.tx_errors++; + dev->stats.tx_aborted_errors++; return 0; } diff --git a/include/linux/arcdevice.h b/include/linux/arcdevice.h index a1916078fd0..ef0d6b7df44 100644 --- a/include/linux/arcdevice.h +++ b/include/linux/arcdevice.h @@ -235,8 +235,6 @@ struct Outgoing { struct arcnet_local { - struct net_device_stats stats; - uint8_t config, /* current value of CONFIG register */ timeout, /* Extended timeout for COM20020 */ backplane, /* Backplane flag for COM20020 */ -- GitLab From bca5b8939f107e498b3fdc92b3a2d286a868d347 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:09 +0000 Subject: [PATCH 0289/4982] arcnet: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/arcnet/arcnet.c | 33 ++++++++++++++++----------------- include/linux/arcdevice.h | 7 ++++++- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 34b9a4d0da3..a80d4a30a46 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -95,12 +95,12 @@ EXPORT_SYMBOL(arcnet_unregister_proto); EXPORT_SYMBOL(arcnet_debug); EXPORT_SYMBOL(alloc_arcdev); EXPORT_SYMBOL(arcnet_interrupt); +EXPORT_SYMBOL(arcnet_open); +EXPORT_SYMBOL(arcnet_close); +EXPORT_SYMBOL(arcnet_send_packet); +EXPORT_SYMBOL(arcnet_timeout); /* Internal function prototypes */ -static int arcnet_open(struct net_device *dev); -static int arcnet_close(struct net_device *dev); -static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev); -static void arcnet_timeout(struct net_device *dev); static int arcnet_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, const void *daddr, const void *saddr, unsigned len); @@ -321,11 +321,18 @@ static const struct header_ops arcnet_header_ops = { .rebuild = arcnet_rebuild_header, }; +static const struct net_device_ops arcnet_netdev_ops = { + .ndo_open = arcnet_open, + .ndo_stop = arcnet_close, + .ndo_start_xmit = arcnet_send_packet, + .ndo_tx_timeout = arcnet_timeout, +}; /* Setup a struct device for ARCnet. */ static void arcdev_setup(struct net_device *dev) { dev->type = ARPHRD_ARCNET; + dev->netdev_ops = &arcnet_netdev_ops; dev->header_ops = &arcnet_header_ops; dev->hard_header_len = sizeof(struct archdr); dev->mtu = choose_mtu(); @@ -338,17 +345,9 @@ static void arcdev_setup(struct net_device *dev) /* New-style flags. */ dev->flags = IFF_BROADCAST; - /* - * Put in this stuff here, so we don't have to export the symbols to - * the chipset drivers. - */ - dev->open = arcnet_open; - dev->stop = arcnet_close; - dev->hard_start_xmit = arcnet_send_packet; - dev->tx_timeout = arcnet_timeout; } -struct net_device *alloc_arcdev(char *name) +struct net_device *alloc_arcdev(const char *name) { struct net_device *dev; @@ -370,7 +369,7 @@ struct net_device *alloc_arcdev(char *name) * that "should" only need to be set once at boot, so that there is * non-reboot way to recover if something goes wrong. */ -static int arcnet_open(struct net_device *dev) +int arcnet_open(struct net_device *dev) { struct arcnet_local *lp = netdev_priv(dev); int count, newmtu, error; @@ -470,7 +469,7 @@ static int arcnet_open(struct net_device *dev) /* The inverse routine to arcnet_open - shuts down the card. */ -static int arcnet_close(struct net_device *dev) +int arcnet_close(struct net_device *dev) { struct arcnet_local *lp = netdev_priv(dev); @@ -599,7 +598,7 @@ static int arcnet_rebuild_header(struct sk_buff *skb) /* Called by the kernel in order to transmit a packet. */ -static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev) +int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev) { struct arcnet_local *lp = netdev_priv(dev); struct archdr *pkt; @@ -718,7 +717,7 @@ static int go_tx(struct net_device *dev) /* Called by the kernel when transmit times out */ -static void arcnet_timeout(struct net_device *dev) +void arcnet_timeout(struct net_device *dev) { unsigned long flags; struct arcnet_local *lp = netdev_priv(dev); diff --git a/include/linux/arcdevice.h b/include/linux/arcdevice.h index ef0d6b7df44..cd4bcb6989c 100644 --- a/include/linux/arcdevice.h +++ b/include/linux/arcdevice.h @@ -333,7 +333,12 @@ void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc); void arcnet_unregister_proto(struct ArcProto *proto); irqreturn_t arcnet_interrupt(int irq, void *dev_id); -struct net_device *alloc_arcdev(char *name); +struct net_device *alloc_arcdev(const char *name); + +int arcnet_open(struct net_device *dev); +int arcnet_close(struct net_device *dev); +int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev); +void arcnet_timeout(struct net_device *dev); #endif /* __KERNEL__ */ #endif /* _LINUX_ARCDEVICE_H */ -- GitLab From a1799af4d7deefccdaa9d222a886fa1373dbb49a Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:10 +0000 Subject: [PATCH 0290/4982] com20020: convert to net_devic_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/arcnet/com20020-isa.c | 2 ++ drivers/net/arcnet/com20020-pci.c | 3 +++ drivers/net/arcnet/com20020.c | 10 ++++++++-- include/linux/com20020.h | 1 + 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c index ea53a940272..db08fc24047 100644 --- a/drivers/net/arcnet/com20020-isa.c +++ b/drivers/net/arcnet/com20020-isa.c @@ -151,6 +151,8 @@ static int __init com20020_init(void) if (node && node != 0xff) dev->dev_addr[0] = node; + dev->netdev_ops = &com20020_netdev_ops; + lp = netdev_priv(dev); lp->backplane = backplane; lp->clockp = clockp & 7; diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index 8b51f632581..dbf4de39754 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -72,6 +72,9 @@ static int __devinit com20020pci_probe(struct pci_dev *pdev, const struct pci_de dev = alloc_arcdev(device); if (!dev) return -ENOMEM; + + dev->netdev_ops = &com20020_netdev_ops; + lp = netdev_priv(dev); pci_set_drvdata(pdev, dev); diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index 103688358fb..bbe8f2ccdad 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -149,6 +149,14 @@ int com20020_check(struct net_device *dev) return 0; } +const struct net_device_ops com20020_netdev_ops = { + .ndo_open = arcnet_open, + .ndo_stop = arcnet_close, + .ndo_start_xmit = arcnet_send_packet, + .ndo_tx_timeout = arcnet_timeout, + .ndo_set_multicast_list = com20020_set_mc_list, +}; + /* Set up the struct net_device associated with this card. Called after * probing succeeds. */ @@ -170,8 +178,6 @@ int com20020_found(struct net_device *dev, int shared) lp->hw.copy_from_card = com20020_copy_from_card; lp->hw.close = com20020_close; - dev->set_multicast_list = com20020_set_mc_list; - if (!dev->dev_addr[0]) dev->dev_addr[0] = inb(ioaddr + BUS_ALIGN*8); /* FIXME: do this some other way! */ diff --git a/include/linux/com20020.h b/include/linux/com20020.h index ac6d9a43e08..350afa773f8 100644 --- a/include/linux/com20020.h +++ b/include/linux/com20020.h @@ -29,6 +29,7 @@ int com20020_check(struct net_device *dev); int com20020_found(struct net_device *dev, int shared); +const struct net_device_ops com20020_netdev_ops; /* The number of low I/O ports used by the card. */ #define ARCNET_TOTAL_SIZE 8 -- GitLab From 878f64856d152ea4bab7dc3c279d0ee117901e1c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:11 +0000 Subject: [PATCH 0291/4982] 3c501: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/3c501.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c index 3d1318a3e68..1c5344aa57c 100644 --- a/drivers/net/3c501.c +++ b/drivers/net/3c501.c @@ -197,6 +197,17 @@ out: return ERR_PTR(err); } +static const struct net_device_ops el_netdev_ops = { + .ndo_open = el_open, + .ndo_stop = el1_close, + .ndo_start_xmit = el_start_xmit, + .ndo_tx_timeout = el_timeout, + .ndo_set_multicast_list = set_multicast_list, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + /** * el1_probe1: * @dev: The device structure to use @@ -305,12 +316,8 @@ static int __init el1_probe1(struct net_device *dev, int ioaddr) * The EL1-specific entries in the device structure. */ - dev->open = &el_open; - dev->hard_start_xmit = &el_start_xmit; - dev->tx_timeout = &el_timeout; + dev->netdev_ops = &el_netdev_ops; dev->watchdog_timeo = HZ; - dev->stop = &el1_close; - dev->set_multicast_list = &set_multicast_list; dev->ethtool_ops = &netdev_ethtool_ops; return 0; } -- GitLab From e6c42b782684cd582599d5c177516ee27d50deb8 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:12 +0000 Subject: [PATCH 0292/4982] 3c505: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/3c505.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c index 6124605bef0..ea1ad8ce883 100644 --- a/drivers/net/3c505.c +++ b/drivers/net/3c505.c @@ -1348,6 +1348,17 @@ static int __init elp_autodetect(struct net_device *dev) return 0; /* Because of this, the layer above will return -ENODEV */ } +static const struct net_device_ops elp_netdev_ops = { + .ndo_open = elp_open, + .ndo_stop = elp_close, + .ndo_get_stats = elp_get_stats, + .ndo_start_xmit = elp_start_xmit, + .ndo_tx_timeout = elp_timeout, + .ndo_set_multicast_list = elp_set_mc_list, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; /****************************************************** * @@ -1552,13 +1563,8 @@ static int __init elplus_setup(struct net_device *dev) printk(KERN_ERR "%s: adapter configuration failed\n", dev->name); } - dev->open = elp_open; /* local */ - dev->stop = elp_close; /* local */ - dev->get_stats = elp_get_stats; /* local */ - dev->hard_start_xmit = elp_start_xmit; /* local */ - dev->tx_timeout = elp_timeout; /* local */ + dev->netdev_ops = &elp_netdev_ops; dev->watchdog_timeo = 10*HZ; - dev->set_multicast_list = elp_set_mc_list; /* local */ dev->ethtool_ops = &netdev_ethtool_ops; /* local */ dev->mem_start = dev->mem_end = 0; -- GitLab From 1722de5098cb5a680945cb68c57be5b2bf67b52d Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:13 +0000 Subject: [PATCH 0293/4982] 3c507: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/3c507.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c index 423e65d0ba7..fbbaf826def 100644 --- a/drivers/net/3c507.c +++ b/drivers/net/3c507.c @@ -352,6 +352,16 @@ out: return ERR_PTR(err); } +static const struct net_device_ops netdev_ops = { + .ndo_open = el16_open, + .ndo_stop = el16_close, + .ndo_start_xmit = el16_send_packet, + .ndo_tx_timeout = el16_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + static int __init el16_probe1(struct net_device *dev, int ioaddr) { static unsigned char init_ID_done, version_printed; @@ -449,10 +459,7 @@ static int __init el16_probe1(struct net_device *dev, int ioaddr) goto out1; } - dev->open = el16_open; - dev->stop = el16_close; - dev->hard_start_xmit = el16_send_packet; - dev->tx_timeout = el16_tx_timeout; + dev->netdev_ops = &netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; dev->ethtool_ops = &netdev_ethtool_ops; dev->flags &= ~IFF_MULTICAST; /* Multicast doesn't work */ -- GitLab From 3186ae8f3f5a30ecfed9faa76ce113830da39fbd Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:14 +0000 Subject: [PATCH 0294/4982] 3c509: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/3c509.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index 535c234286e..d58919c7032 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -537,6 +537,21 @@ static struct mca_driver el3_mca_driver = { static int mca_registered; #endif /* CONFIG_MCA */ +static const struct net_device_ops netdev_ops = { + .ndo_open = el3_open, + .ndo_stop = el3_close, + .ndo_start_xmit = el3_start_xmit, + .ndo_get_stats = el3_get_stats, + .ndo_set_multicast_list = set_multicast_list, + .ndo_tx_timeout = el3_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = el3_poll_controller, +#endif +}; + static int __devinit el3_common_init(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); @@ -553,16 +568,8 @@ static int __devinit el3_common_init(struct net_device *dev) } /* The EL3-specific entries in the device structure. */ - dev->open = &el3_open; - dev->hard_start_xmit = &el3_start_xmit; - dev->stop = &el3_close; - dev->get_stats = &el3_get_stats; - dev->set_multicast_list = &set_multicast_list; - dev->tx_timeout = el3_tx_timeout; + dev->netdev_ops = &netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = el3_poll_controller; -#endif SET_ETHTOOL_OPS(dev, ðtool_ops); err = register_netdev(dev); -- GitLab From f3701c2f0e2ede7ae265fcf627f01f2a795ac41b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:15 +0000 Subject: [PATCH 0295/4982] 3c515: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/3c515.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c index 39ac12233aa..167bf23066e 100644 --- a/drivers/net/3c515.c +++ b/drivers/net/3c515.c @@ -563,6 +563,20 @@ no_pnp: return NULL; } + +static const struct net_device_ops netdev_ops = { + .ndo_open = corkscrew_open, + .ndo_stop = corkscrew_close, + .ndo_start_xmit = corkscrew_start_xmit, + .ndo_tx_timeout = corkscrew_timeout, + .ndo_get_stats = corkscrew_get_stats, + .ndo_set_multicast_list = set_rx_mode, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + + static int corkscrew_setup(struct net_device *dev, int ioaddr, struct pnp_dev *idev, int card_number) { @@ -681,13 +695,8 @@ static int corkscrew_setup(struct net_device *dev, int ioaddr, vp->full_bus_master_rx = (vp->capabilities & 0x20) ? 1 : 0; /* The 3c51x-specific entries in the device structure. */ - dev->open = &corkscrew_open; - dev->hard_start_xmit = &corkscrew_start_xmit; - dev->tx_timeout = &corkscrew_timeout; + dev->netdev_ops = &netdev_ops; dev->watchdog_timeo = (400 * HZ) / 1000; - dev->stop = &corkscrew_close; - dev->get_stats = &corkscrew_get_stats; - dev->set_multicast_list = &set_rx_mode; dev->ethtool_ops = &netdev_ethtool_ops; return register_netdev(dev); -- GitLab From 90e64c6ad2a5dd3ecad1b59e466d42945fe22eb2 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:16 +0000 Subject: [PATCH 0296/4982] 3c523: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/3c523.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c index ff41e1ff560..8f734d74b51 100644 --- a/drivers/net/3c523.c +++ b/drivers/net/3c523.c @@ -403,6 +403,20 @@ static int elmc_getinfo(char *buf, int slot, void *d) return len; } /* elmc_getinfo() */ +static const struct net_device_ops netdev_ops = { + .ndo_open = elmc_open, + .ndo_stop = elmc_close, + .ndo_get_stats = elmc_get_stats, + .ndo_start_xmit = elmc_send_packet, + .ndo_tx_timeout = elmc_timeout, +#ifdef ELMC_MULTICAST + .ndo_set_multicast_list = set_multicast_list, +#endif + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + /*****************************************************************/ static int __init do_elmc_probe(struct net_device *dev) @@ -544,17 +558,8 @@ static int __init do_elmc_probe(struct net_device *dev) printk(KERN_INFO "%s: hardware address %pM\n", dev->name, dev->dev_addr); - dev->open = &elmc_open; - dev->stop = &elmc_close; - dev->get_stats = &elmc_get_stats; - dev->hard_start_xmit = &elmc_send_packet; - dev->tx_timeout = &elmc_timeout; + dev->netdev_ops = &netdev_ops; dev->watchdog_timeo = HZ; -#ifdef ELMC_MULTICAST - dev->set_multicast_list = &set_multicast_list; -#else - dev->set_multicast_list = NULL; -#endif dev->ethtool_ops = &netdev_ethtool_ops; /* note that we haven't actually requested the IRQ from the kernel. -- GitLab From 4394e6533da7f652a19e08009fff713f4168915e Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:17 +0000 Subject: [PATCH 0297/4982] 3c527: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/3c527.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c index 2df3af3b9b2..b61073c42bf 100644 --- a/drivers/net/3c527.c +++ b/drivers/net/3c527.c @@ -288,6 +288,18 @@ struct net_device *__init mc32_probe(int unit) return ERR_PTR(-ENODEV); } +static const struct net_device_ops netdev_ops = { + .ndo_open = mc32_open, + .ndo_stop = mc32_close, + .ndo_start_xmit = mc32_send_packet, + .ndo_get_stats = mc32_get_stats, + .ndo_set_multicast_list = mc32_set_multicast_list, + .ndo_tx_timeout = mc32_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + /** * mc32_probe1 - Check a given slot for a board and test the card * @dev: Device structure to fill in @@ -518,12 +530,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot) printk("%s: Firmware Rev %d. %d RX buffers, %d TX buffers. Base of 0x%08X.\n", dev->name, lp->exec_box->data[12], lp->rx_len, lp->tx_len, lp->base); - dev->open = mc32_open; - dev->stop = mc32_close; - dev->hard_start_xmit = mc32_send_packet; - dev->get_stats = mc32_get_stats; - dev->set_multicast_list = mc32_set_multicast_list; - dev->tx_timeout = mc32_timeout; + dev->netdev_ops = &netdev_ops; dev->watchdog_timeo = HZ*5; /* Board does all the work */ dev->ethtool_ops = &netdev_ethtool_ops; -- GitLab From 48b47a5e306c1c119ee81ccd24d487c2df656410 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:18 +0000 Subject: [PATCH 0298/4982] 3c59x: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/3c59x.c | 55 ++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index cdbbb6226fc..b2563d384cf 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -992,6 +992,42 @@ out: return rc; } +static const struct net_device_ops boomrang_netdev_ops = { + .ndo_open = vortex_open, + .ndo_stop = vortex_close, + .ndo_start_xmit = boomerang_start_xmit, + .ndo_tx_timeout = vortex_tx_timeout, + .ndo_get_stats = vortex_get_stats, +#ifdef CONFIG_PCI + .ndo_do_ioctl = vortex_ioctl, +#endif + .ndo_set_multicast_list = set_rx_mode, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = poll_vortex, +#endif +}; + +static const struct net_device_ops vortex_netdev_ops = { + .ndo_open = vortex_open, + .ndo_stop = vortex_close, + .ndo_start_xmit = vortex_start_xmit, + .ndo_tx_timeout = vortex_tx_timeout, + .ndo_get_stats = vortex_get_stats, +#ifdef CONFIG_PCI + .ndo_do_ioctl = vortex_ioctl, +#endif + .ndo_set_multicast_list = set_rx_mode, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = poll_vortex, +#endif +}; + /* * Start up the PCI/EISA device which is described by *gendev. * Return 0 on success. @@ -1366,18 +1402,16 @@ static int __devinit vortex_probe1(struct device *gendev, } /* The 3c59x-specific entries in the device structure. */ - dev->open = vortex_open; if (vp->full_bus_master_tx) { - dev->hard_start_xmit = boomerang_start_xmit; + dev->netdev_ops = &boomrang_netdev_ops; /* Actually, it still should work with iommu. */ if (card_idx < MAX_UNITS && ((hw_checksums[card_idx] == -1 && (vp->drv_flags & HAS_HWCKSM)) || hw_checksums[card_idx] == 1)) { dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; } - } else { - dev->hard_start_xmit = vortex_start_xmit; - } + } else + dev->netdev_ops = &vortex_netdev_ops; if (print_info) { printk(KERN_INFO "%s: scatter/gather %sabled. h/w checksums %sabled\n", @@ -1386,18 +1420,9 @@ static int __devinit vortex_probe1(struct device *gendev, (dev->features & NETIF_F_IP_CSUM) ? "en":"dis"); } - dev->stop = vortex_close; - dev->get_stats = vortex_get_stats; -#ifdef CONFIG_PCI - dev->do_ioctl = vortex_ioctl; -#endif dev->ethtool_ops = &vortex_ethtool_ops; - dev->set_multicast_list = set_rx_mode; - dev->tx_timeout = vortex_tx_timeout; dev->watchdog_timeo = (watchdog * HZ) / 1000; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = poll_vortex; -#endif + if (pdev) { vp->pm_state_valid = 1; pci_save_state(VORTEX_PCI(vp)); -- GitLab From 9fd3238e95046b61d518ddacaa767fa09f31b0d0 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:19 +0000 Subject: [PATCH 0299/4982] ibmtr: convert to internal network_device_stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/tokenring/ibmtr.c | 29 ++++++----------------------- include/linux/ibmtr.h | 2 +- 2 files changed, 7 insertions(+), 24 deletions(-) diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c index fa7bce6e0c6..f195d54ae42 100644 --- a/drivers/net/tokenring/ibmtr.c +++ b/drivers/net/tokenring/ibmtr.c @@ -200,7 +200,6 @@ static void tr_rx(struct net_device *dev); static void ibmtr_reset_timer(struct timer_list*tmr,struct net_device *dev); static void tok_rerun(unsigned long dev_addr); static void ibmtr_readlog(struct net_device *dev); -static struct net_device_stats *tok_get_stats(struct net_device *dev); static int ibmtr_change_mtu(struct net_device *dev, int mtu); static void find_turbo_adapters(int *iolist); @@ -825,7 +824,6 @@ static int __devinit trdev_init(struct net_device *dev) dev->open = tok_open; dev->stop = tok_close; dev->hard_start_xmit = tok_send_packet; - dev->get_stats = tok_get_stats; dev->set_multicast_list = tok_set_multicast_list; dev->change_mtu = ibmtr_change_mtu; @@ -1460,7 +1458,7 @@ static irqreturn_t tok_interrupt(int irq, void *dev_id) "%02X\n", (int)retcode, (int)readb(ti->ssb + 6)); else - ti->tr_stats.tx_packets++; + dev->stats.tx_packets++; break; case XMIT_XID_CMD: DPRINTK("xmit xid ret_code: %02X\n", @@ -1646,7 +1644,7 @@ static void tr_tx(struct net_device *dev) break; } writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); - ti->tr_stats.tx_bytes += ti->current_skb->len; + dev->stats.tx_bytes += ti->current_skb->len; dev_kfree_skb_irq(ti->current_skb); ti->current_skb = NULL; netif_wake_queue(dev); @@ -1722,7 +1720,7 @@ static void tr_rx(struct net_device *dev) if (readb(llc + offsetof(struct trllc, llc)) != UI_CMD) { SET_PAGE(ti->asb_page); writeb(DATA_LOST, ti->asb + RETCODE_OFST); - ti->tr_stats.rx_dropped++; + dev->stats.rx_dropped++; writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); return; } @@ -1757,7 +1755,7 @@ static void tr_rx(struct net_device *dev) if (!(skb = dev_alloc_skb(skb_size))) { DPRINTK("out of memory. frame dropped.\n"); - ti->tr_stats.rx_dropped++; + dev->stats.rx_dropped++; SET_PAGE(ti->asb_page); writeb(DATA_LOST, ti->asb + offsetof(struct asb_rec, ret_code)); writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); @@ -1813,8 +1811,8 @@ static void tr_rx(struct net_device *dev) writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); - ti->tr_stats.rx_bytes += skb->len; - ti->tr_stats.rx_packets++; + dev->stats.rx_bytes += skb->len; + dev->stats.rx_packets++; skb->protocol = tr_type_trans(skb, dev); if (IPv4_p) { @@ -1876,21 +1874,6 @@ static void ibmtr_readlog(struct net_device *dev) /*****************************************************************************/ -/* tok_get_stats(): Basically a scaffold routine which will return - the address of the tr_statistics structure associated with - this device -- the tr.... structure is an ethnet look-alike - so at least for this iteration may suffice. */ - -static struct net_device_stats *tok_get_stats(struct net_device *dev) -{ - - struct tok_info *toki; - toki = netdev_priv(dev); - return (struct net_device_stats *) &toki->tr_stats; -} - -/*****************************************************************************/ - static int ibmtr_change_mtu(struct net_device *dev, int mtu) { struct tok_info *ti = netdev_priv(dev); diff --git a/include/linux/ibmtr.h b/include/linux/ibmtr.h index 1c7a0dd5536..06695b74d40 100644 --- a/include/linux/ibmtr.h +++ b/include/linux/ibmtr.h @@ -207,7 +207,7 @@ struct tok_info { unsigned short exsap_station_id; unsigned short global_int_enable; struct sk_buff *current_skb; - struct net_device_stats tr_stats; + unsigned char auto_speedsave; open_state open_status, sap_status; enum {MANUAL, AUTOMATIC} open_mode; -- GitLab From c86d87402966dc3f1996d17ef6bc2b676b46bb60 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:20 +0000 Subject: [PATCH 0300/4982] ibmtr: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/tokenring/ibmtr.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c index f195d54ae42..9d896116cf7 100644 --- a/drivers/net/tokenring/ibmtr.c +++ b/drivers/net/tokenring/ibmtr.c @@ -815,17 +815,21 @@ static unsigned char __devinit get_sram_size(struct tok_info *adapt_info) /*****************************************************************************/ +static const struct net_device_ops trdev_netdev_ops = { + .ndo_open = tok_open, + .ndo_stop = tok_close, + .ndo_start_xmit = tok_send_packet, + .ndo_set_multicast_list = tok_set_multicast_list, + .ndo_change_mtu = ibmtr_change_mtu, +}; + static int __devinit trdev_init(struct net_device *dev) { struct tok_info *ti = netdev_priv(dev); SET_PAGE(ti->srb_page); ti->open_failure = NO ; - dev->open = tok_open; - dev->stop = tok_close; - dev->hard_start_xmit = tok_send_packet; - dev->set_multicast_list = tok_set_multicast_list; - dev->change_mtu = ibmtr_change_mtu; + dev->netdev_ops = &trdev_netdev_ops; return 0; } -- GitLab From 37423fff4f02fcf6867971dfd678e99a34efeab3 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:21 +0000 Subject: [PATCH 0301/4982] lanstreamer: convert to internal network stats Use internal network_device_stats to keep track of statistics. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/tokenring/lanstreamer.c | 19 +++++-------------- drivers/net/tokenring/lanstreamer.h | 1 - 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c index 239c75217b1..ecfa564489c 100644 --- a/drivers/net/tokenring/lanstreamer.c +++ b/drivers/net/tokenring/lanstreamer.c @@ -207,7 +207,6 @@ static int streamer_xmit(struct sk_buff *skb, struct net_device *dev); static int streamer_close(struct net_device *dev); static void streamer_set_rx_mode(struct net_device *dev); static irqreturn_t streamer_interrupt(int irq, void *dev_id); -static struct net_device_stats *streamer_get_stats(struct net_device *dev); static int streamer_set_mac_address(struct net_device *dev, void *addr); static void streamer_arb_cmd(struct net_device *dev); static int streamer_change_mtu(struct net_device *dev, int mtu); @@ -331,7 +330,6 @@ static int __devinit streamer_init_one(struct pci_dev *pdev, dev->do_ioctl = NULL; #endif dev->set_multicast_list = &streamer_set_rx_mode; - dev->get_stats = &streamer_get_stats; dev->set_mac_address = &streamer_set_mac_address; dev->irq = pdev->irq; dev->base_addr=pio_start; @@ -937,7 +935,7 @@ static void streamer_rx(struct net_device *dev) if (skb == NULL) { printk(KERN_WARNING "%s: Not enough memory to copy packet to upper layers. \n", dev->name); - streamer_priv->streamer_stats.rx_dropped++; + dev->stats.rx_dropped++; } else { /* we allocated an skb OK */ if (buffer_cnt == 1) { /* release the DMA mapping */ @@ -1009,8 +1007,8 @@ static void streamer_rx(struct net_device *dev) /* send up to the protocol */ netif_rx(skb); } - streamer_priv->streamer_stats.rx_packets++; - streamer_priv->streamer_stats.rx_bytes += length; + dev->stats.rx_packets++; + dev->stats.rx_bytes += length; } /* if skb == null */ } /* end received without errors */ @@ -1053,8 +1051,8 @@ static irqreturn_t streamer_interrupt(int irq, void *dev_id) while(streamer_priv->streamer_tx_ring[(streamer_priv->tx_ring_last_status + 1) & (STREAMER_TX_RING_SIZE - 1)].status) { streamer_priv->tx_ring_last_status = (streamer_priv->tx_ring_last_status + 1) & (STREAMER_TX_RING_SIZE - 1); streamer_priv->free_tx_ring_entries++; - streamer_priv->streamer_stats.tx_bytes += streamer_priv->tx_ring_skb[streamer_priv->tx_ring_last_status]->len; - streamer_priv->streamer_stats.tx_packets++; + dev->stats.tx_bytes += streamer_priv->tx_ring_skb[streamer_priv->tx_ring_last_status]->len; + dev->stats.tx_packets++; dev_kfree_skb_irq(streamer_priv->tx_ring_skb[streamer_priv->tx_ring_last_status]); streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_last_status].buffer = 0xdeadbeef; streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_last_status].status = 0; @@ -1484,13 +1482,6 @@ static void streamer_srb_bh(struct net_device *dev) } /* switch srb[0] */ } -static struct net_device_stats *streamer_get_stats(struct net_device *dev) -{ - struct streamer_private *streamer_priv; - streamer_priv = netdev_priv(dev); - return (struct net_device_stats *) &streamer_priv->streamer_stats; -} - static int streamer_set_mac_address(struct net_device *dev, void *addr) { struct sockaddr *saddr = addr; diff --git a/drivers/net/tokenring/lanstreamer.h b/drivers/net/tokenring/lanstreamer.h index 13ccee6449c..3c58d6a3fbc 100644 --- a/drivers/net/tokenring/lanstreamer.h +++ b/drivers/net/tokenring/lanstreamer.h @@ -299,7 +299,6 @@ struct streamer_private { int tx_ring_free, tx_ring_last_status, rx_ring_last_received, free_tx_ring_entries; - struct net_device_stats streamer_stats; __u16 streamer_lan_status; __u8 streamer_ring_speed; __u16 pkt_buf_sz; -- GitLab From be18827815bc62f64797da05bcba9ba69101524d Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:22 +0000 Subject: [PATCH 0302/4982] lanstreamer: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/tokenring/lanstreamer.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c index ecfa564489c..0b2b7925da2 100644 --- a/drivers/net/tokenring/lanstreamer.c +++ b/drivers/net/tokenring/lanstreamer.c @@ -221,6 +221,18 @@ struct streamer_private *dev_streamer=NULL; #endif #endif +static const struct net_device_ops streamer_netdev_ops = { + .ndo_open = streamer_open, + .ndo_stop = streamer_close, + .ndo_start_xmit = streamer_xmit, + .ndo_change_mtu = streamer_change_mtu, +#if STREAMER_IOCTL + .ndo_do_ioctl = streamer_ioctl, +#endif + .ndo_set_multicast_list = streamer_set_rx_mode, + .ndo_set_mac_address = streamer_set_mac_address, +}; + static int __devinit streamer_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -320,17 +332,7 @@ static int __devinit streamer_init_one(struct pci_dev *pdev, init_waitqueue_head(&streamer_priv->srb_wait); init_waitqueue_head(&streamer_priv->trb_wait); - dev->open = &streamer_open; - dev->hard_start_xmit = &streamer_xmit; - dev->change_mtu = &streamer_change_mtu; - dev->stop = &streamer_close; -#if STREAMER_IOCTL - dev->do_ioctl = &streamer_ioctl; -#else - dev->do_ioctl = NULL; -#endif - dev->set_multicast_list = &streamer_set_rx_mode; - dev->set_mac_address = &streamer_set_mac_address; + dev->netdev_ops = &streamer_netdev_ops; dev->irq = pdev->irq; dev->base_addr=pio_start; SET_NETDEV_DEV(dev, &pdev->dev); -- GitLab From dcc59a9789fee98782aa2f3215bbea071bd643b1 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:23 +0000 Subject: [PATCH 0303/4982] olympic: convert to internal network device stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/tokenring/olympic.c | 21 ++++++--------------- drivers/net/tokenring/olympic.h | 1 - 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c index ecb5c7c9691..71fed1e2022 100644 --- a/drivers/net/tokenring/olympic.c +++ b/drivers/net/tokenring/olympic.c @@ -187,7 +187,6 @@ static int olympic_close(struct net_device *dev); static void olympic_set_rx_mode(struct net_device *dev); static void olympic_freemem(struct net_device *dev) ; static irqreturn_t olympic_interrupt(int irq, void *dev_id); -static struct net_device_stats * olympic_get_stats(struct net_device *dev); static int olympic_set_mac_address(struct net_device *dev, void *addr) ; static void olympic_arb_cmd(struct net_device *dev); static int olympic_change_mtu(struct net_device *dev, int mtu); @@ -259,7 +258,6 @@ static int __devinit olympic_probe(struct pci_dev *pdev, const struct pci_device dev->stop=&olympic_close; dev->do_ioctl=NULL; dev->set_multicast_list=&olympic_set_rx_mode; - dev->get_stats=&olympic_get_stats ; dev->set_mac_address=&olympic_set_mac_address ; SET_NETDEV_DEV(dev, &pdev->dev); @@ -785,7 +783,7 @@ static void olympic_rx(struct net_device *dev) } olympic_priv->rx_ring_last_received += i ; olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1) ; - olympic_priv->olympic_stats.rx_errors++; + dev->stats.rx_errors++; } else { if (buffer_cnt == 1) { @@ -796,7 +794,7 @@ static void olympic_rx(struct net_device *dev) if (skb == NULL) { printk(KERN_WARNING "%s: Not enough memory to copy packet to upper layers. \n",dev->name) ; - olympic_priv->olympic_stats.rx_dropped++ ; + dev->stats.rx_dropped++; /* Update counters even though we don't transfer the frame */ olympic_priv->rx_ring_last_received += i ; olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1) ; @@ -862,8 +860,8 @@ static void olympic_rx(struct net_device *dev) skb->protocol = tr_type_trans(skb,dev); netif_rx(skb) ; } - olympic_priv->olympic_stats.rx_packets++ ; - olympic_priv->olympic_stats.rx_bytes += length ; + dev->stats.rx_packets++ ; + dev->stats.rx_bytes += length ; } /* if skb == null */ } /* If status & 0x3b */ @@ -971,8 +969,8 @@ static irqreturn_t olympic_interrupt(int irq, void *dev_id) olympic_priv->tx_ring_last_status++; olympic_priv->tx_ring_last_status &= (OLYMPIC_TX_RING_SIZE-1); olympic_priv->free_tx_ring_entries++; - olympic_priv->olympic_stats.tx_bytes += olympic_priv->tx_ring_skb[olympic_priv->tx_ring_last_status]->len; - olympic_priv->olympic_stats.tx_packets++ ; + dev->stats.tx_bytes += olympic_priv->tx_ring_skb[olympic_priv->tx_ring_last_status]->len; + dev->stats.tx_packets++ ; pci_unmap_single(olympic_priv->pdev, le32_to_cpu(olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_last_status].buffer), olympic_priv->tx_ring_skb[olympic_priv->tx_ring_last_status]->len,PCI_DMA_TODEVICE); @@ -1344,13 +1342,6 @@ static void olympic_srb_bh(struct net_device *dev) } -static struct net_device_stats * olympic_get_stats(struct net_device *dev) -{ - struct olympic_private *olympic_priv ; - olympic_priv=netdev_priv(dev); - return (struct net_device_stats *) &olympic_priv->olympic_stats; -} - static int olympic_set_mac_address (struct net_device *dev, void *addr) { struct sockaddr *saddr = addr ; diff --git a/drivers/net/tokenring/olympic.h b/drivers/net/tokenring/olympic.h index 10fbba08978..30631bae4c9 100644 --- a/drivers/net/tokenring/olympic.h +++ b/drivers/net/tokenring/olympic.h @@ -275,7 +275,6 @@ struct olympic_private { struct sk_buff *tx_ring_skb[OLYMPIC_TX_RING_SIZE], *rx_ring_skb[OLYMPIC_RX_RING_SIZE]; int tx_ring_free, tx_ring_last_status, rx_ring_last_received,rx_status_last_received, free_tx_ring_entries; - struct net_device_stats olympic_stats ; u16 olympic_lan_status ; u8 olympic_ring_speed ; u16 pkt_buf_sz ; -- GitLab From efda072393fb4213e43d92bdd20cf180a06a8eb0 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:24 +0000 Subject: [PATCH 0304/4982] olympic: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/tokenring/olympic.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c index 71fed1e2022..77dc9da4c0b 100644 --- a/drivers/net/tokenring/olympic.c +++ b/drivers/net/tokenring/olympic.c @@ -194,6 +194,15 @@ static void olympic_srb_bh(struct net_device *dev) ; static void olympic_asb_bh(struct net_device *dev) ; static int olympic_proc_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data) ; +static const struct net_device_ops olympic_netdev_ops = { + .ndo_open = olympic_open, + .ndo_stop = olympic_close, + .ndo_start_xmit = olympic_xmit, + .ndo_change_mtu = olympic_change_mtu, + .ndo_set_multicast_list = olympic_set_rx_mode, + .ndo_set_mac_address = olympic_set_mac_address, +}; + static int __devinit olympic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev ; @@ -252,13 +261,7 @@ static int __devinit olympic_probe(struct pci_dev *pdev, const struct pci_device goto op_free_iomap; } - dev->open=&olympic_open; - dev->hard_start_xmit=&olympic_xmit; - dev->change_mtu=&olympic_change_mtu; - dev->stop=&olympic_close; - dev->do_ioctl=NULL; - dev->set_multicast_list=&olympic_set_rx_mode; - dev->set_mac_address=&olympic_set_mac_address ; + dev->netdev_ops = &olympic_netdev_ops; SET_NETDEV_DEV(dev, &pdev->dev); pci_set_drvdata(pdev,dev) ; -- GitLab From f1608f859a3fba95a3b0ae70f2528b81c6928d77 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:25 +0000 Subject: [PATCH 0305/4982] tms380tr: convert to net_device_ops Conver this related group of drivers to new API Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/tokenring/abyss.c | 10 ++++++++-- drivers/net/tokenring/tms380tr.c | 21 ++++++++++++--------- drivers/net/tokenring/tms380tr.h | 1 + drivers/net/tokenring/tmspci.c | 4 ++-- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/drivers/net/tokenring/abyss.c b/drivers/net/tokenring/abyss.c index b566d6d79ec..b9db1b5a58a 100644 --- a/drivers/net/tokenring/abyss.c +++ b/drivers/net/tokenring/abyss.c @@ -92,6 +92,8 @@ static void abyss_sifwritew(struct net_device *dev, unsigned short val, unsigned outw(val, dev->base_addr + reg); } +static struct net_device_ops abyss_netdev_ops; + static int __devinit abyss_attach(struct pci_dev *pdev, const struct pci_device_id *ent) { static int versionprinted; @@ -157,8 +159,7 @@ static int __devinit abyss_attach(struct pci_dev *pdev, const struct pci_device_ memcpy(tp->ProductID, "Madge PCI 16/4 Mk2", PROD_ID_SIZE + 1); - dev->open = abyss_open; - dev->stop = abyss_close; + dev->netdev_ops = &abyss_netdev_ops; pci_set_drvdata(pdev, dev); SET_NETDEV_DEV(dev, &pdev->dev); @@ -450,6 +451,11 @@ static struct pci_driver abyss_driver = { static int __init abyss_init (void) { + abyss_netdev_ops = tms380tr_netdev_ops; + + abyss_netdev_ops.ndo_open = abyss_open; + abyss_netdev_ops.ndo_stop = abyss_close; + return pci_register_driver(&abyss_driver); } diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c index 5be34c2fd48..b11bb72dc7a 100644 --- a/drivers/net/tokenring/tms380tr.c +++ b/drivers/net/tokenring/tms380tr.c @@ -2330,6 +2330,17 @@ void tmsdev_term(struct net_device *dev) DMA_BIDIRECTIONAL); } +const struct net_device_ops tms380tr_netdev_ops = { + .ndo_open = tms380tr_open, + .ndo_stop = tms380tr_close, + .ndo_start_xmit = tms380tr_send_packet, + .ndo_tx_timeout = tms380tr_timeout, + .ndo_get_stats = tms380tr_get_stats, + .ndo_set_multicast_list = tms380tr_set_multicast_list, + .ndo_set_mac_address = tms380tr_set_mac_address, +}; +EXPORT_SYMBOL(tms380tr_netdev_ops); + int tmsdev_init(struct net_device *dev, struct device *pdev) { struct net_local *tms_local; @@ -2353,16 +2364,8 @@ int tmsdev_init(struct net_device *dev, struct device *pdev) return -ENOMEM; } - /* These can be overridden by the card driver if needed */ - dev->open = tms380tr_open; - dev->stop = tms380tr_close; - dev->do_ioctl = NULL; - dev->hard_start_xmit = tms380tr_send_packet; - dev->tx_timeout = tms380tr_timeout; + dev->netdev_ops = &tms380tr_netdev_ops; dev->watchdog_timeo = HZ; - dev->get_stats = tms380tr_get_stats; - dev->set_multicast_list = &tms380tr_set_multicast_list; - dev->set_mac_address = tms380tr_set_mac_address; return 0; } diff --git a/drivers/net/tokenring/tms380tr.h b/drivers/net/tokenring/tms380tr.h index 7af76d70884..60b30ee38dc 100644 --- a/drivers/net/tokenring/tms380tr.h +++ b/drivers/net/tokenring/tms380tr.h @@ -14,6 +14,7 @@ #include /* module prototypes */ +extern const struct net_device_ops tms380tr_netdev_ops; int tms380tr_open(struct net_device *dev); int tms380tr_close(struct net_device *dev); irqreturn_t tms380tr_interrupt(int irq, void *dev_id); diff --git a/drivers/net/tokenring/tmspci.c b/drivers/net/tokenring/tmspci.c index 5f601773c26..b397e8785d6 100644 --- a/drivers/net/tokenring/tmspci.c +++ b/drivers/net/tokenring/tmspci.c @@ -157,8 +157,8 @@ static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_devic tp->tmspriv = cardinfo; - dev->open = tms380tr_open; - dev->stop = tms380tr_close; + dev->netdev_ops = &tms380tr_netdev_ops; + pci_set_drvdata(pdev, dev); SET_NETDEV_DEV(dev, &pdev->dev); -- GitLab From 69d651692f16c5e883f6af3d0eb36bdac5438f9c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:26 +0000 Subject: [PATCH 0306/4982] 3c559: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/tokenring/3c359.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c index 43853e3b210..4a65fc2dd92 100644 --- a/drivers/net/tokenring/3c359.c +++ b/drivers/net/tokenring/3c359.c @@ -274,6 +274,15 @@ static void xl_ee_write(struct net_device *dev, int ee_addr, u16 ee_value) return ; } + +static const struct net_device_ops xl_netdev_ops = { + .ndo_open = xl_open, + .ndo_stop = xl_close, + .ndo_start_xmit = xl_xmit, + .ndo_change_mtu = xl_change_mtu, + .ndo_set_multicast_list = xl_set_rx_mode, + .ndo_set_mac_address = xl_set_mac_address, +}; static int __devinit xl_probe(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -337,13 +346,7 @@ static int __devinit xl_probe(struct pci_dev *pdev, return i ; } - dev->open=&xl_open; - dev->hard_start_xmit=&xl_xmit; - dev->change_mtu=&xl_change_mtu; - dev->stop=&xl_close; - dev->do_ioctl=NULL; - dev->set_multicast_list=&xl_set_rx_mode; - dev->set_mac_address=&xl_set_mac_address ; + dev->netdev_ops = &xl_netdev_ops; SET_NETDEV_DEV(dev, &pdev->dev); pci_set_drvdata(pdev,dev) ; -- GitLab From bc0443fc38f802c5b7a7489b4a31577f1fadd4e4 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:27 +0000 Subject: [PATCH 0307/4982] znet: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/znet.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/znet.c b/drivers/net/znet.c index f0b15c9347d..0a6992d8611 100644 --- a/drivers/net/znet.c +++ b/drivers/net/znet.c @@ -358,6 +358,17 @@ static void znet_set_multicast_list (struct net_device *dev) * multicast address configured isn't equal to IFF_ALLMULTI */ } +static const struct net_device_ops znet_netdev_ops = { + .ndo_open = znet_open, + .ndo_stop = znet_close, + .ndo_start_xmit = znet_send_packet, + .ndo_set_multicast_list = znet_set_multicast_list, + .ndo_tx_timeout = znet_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + /* The Z-Note probe is pretty easy. The NETIDBLK exists in the safe-to-probe BIOS area. We just scan for the signature, and pull the vital parameters out of the structure. */ @@ -440,11 +451,7 @@ static int __init znet_probe (void) znet->tx_end = znet->tx_start + znet->tx_buf_len; /* The ZNET-specific entries in the device structure. */ - dev->open = &znet_open; - dev->hard_start_xmit = &znet_send_packet; - dev->stop = &znet_close; - dev->set_multicast_list = &znet_set_multicast_list; - dev->tx_timeout = znet_tx_timeout; + dev->netdev_ops = &znet_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; err = register_netdev(dev); if (err) -- GitLab From b3672a7394d2db85bd8c0f445df485fc09a0cef7 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:28 +0000 Subject: [PATCH 0308/4982] 6pack: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/hamradio/6pack.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 2d4089894ec..3da9f394b4c 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -322,23 +322,25 @@ static const struct header_ops sp_header_ops = { .rebuild = sp_rebuild_header, }; +static const struct net_device_ops sp_netdev_ops = { + .ndo_open = sp_open_dev, + .ndo_stop = sp_close, + .ndo_start_xmit = sp_xmit, + .ndo_set_mac_address = sp_set_mac_address, +}; + static void sp_setup(struct net_device *dev) { /* Finish setting up the DEVICE info. */ - dev->mtu = SIXP_MTU; - dev->hard_start_xmit = sp_xmit; - dev->open = sp_open_dev; + dev->netdev_ops = &sp_netdev_ops; dev->destructor = free_netdev; - dev->stop = sp_close; - - dev->set_mac_address = sp_set_mac_address; + dev->mtu = SIXP_MTU; dev->hard_header_len = AX25_MAX_HEADER_LEN; dev->header_ops = &sp_header_ops; dev->addr_len = AX25_ADDR_LEN; dev->type = ARPHRD_AX25; dev->tx_queue_len = 10; - dev->tx_timeout = NULL; /* Only activated in AX.25 mode */ memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN); -- GitLab From cd94f08658e15972d6ca8b53501efa48841f1b5b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:29 +0000 Subject: [PATCH 0309/4982] baycom: convert to internal net_device_stats Signed-off-by: Stephen Hemminger Acked-by: Thomas Sailer Signed-off-by: David S. Miller --- drivers/net/hamradio/baycom_epp.c | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index 81a65e3a1c0..c6e4ec3ade6 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c @@ -203,7 +203,6 @@ struct baycom_state { unsigned char buf[TXBUFFER_SIZE]; } hdlctx; - struct net_device_stats stats; unsigned int ptt_keyed; struct sk_buff *skb; /* next transmit packet */ @@ -423,7 +422,7 @@ static void encode_hdlc(struct baycom_state *bc) bc->hdlctx.bufptr = bc->hdlctx.buf; bc->hdlctx.bufcnt = wp - bc->hdlctx.buf; dev_kfree_skb(skb); - bc->stats.tx_packets++; + bc->dev->stats.tx_packets++; } /* ---------------------------------------------------------------------- */ @@ -547,7 +546,7 @@ static void do_rxpacket(struct net_device *dev) pktlen = bc->hdlcrx.bufcnt-2+1; /* KISS kludge */ if (!(skb = dev_alloc_skb(pktlen))) { printk("%s: memory squeeze, dropping packet\n", dev->name); - bc->stats.rx_dropped++; + dev->stats.rx_dropped++; return; } cp = skb_put(skb, pktlen); @@ -555,7 +554,7 @@ static void do_rxpacket(struct net_device *dev) memcpy(cp, bc->hdlcrx.buf, pktlen - 1); skb->protocol = ax25_type_trans(skb, dev); netif_rx(skb); - bc->stats.rx_packets++; + dev->stats.rx_packets++; } static int receive(struct net_device *dev, int cnt) @@ -802,19 +801,6 @@ static int baycom_set_mac_address(struct net_device *dev, void *addr) /* --------------------------------------------------------------------- */ -static struct net_device_stats *baycom_get_stats(struct net_device *dev) -{ - struct baycom_state *bc = netdev_priv(dev); - - /* - * Get the current statistics. This may be called with the - * card open or closed. - */ - return &bc->stats; -} - -/* --------------------------------------------------------------------- */ - static void epp_wakeup(void *handle) { struct net_device *dev = (struct net_device *)handle; @@ -1065,10 +1051,10 @@ static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) hi.data.cs.ptt = !!(bc->stat & EPP_PTTBIT); hi.data.cs.dcd = !(bc->stat & EPP_DCDBIT); hi.data.cs.ptt_keyed = bc->ptt_keyed; - hi.data.cs.tx_packets = bc->stats.tx_packets; - hi.data.cs.tx_errors = bc->stats.tx_errors; - hi.data.cs.rx_packets = bc->stats.rx_packets; - hi.data.cs.rx_errors = bc->stats.rx_errors; + hi.data.cs.tx_packets = dev->stats.tx_packets; + hi.data.cs.tx_errors = dev->stats.tx_errors; + hi.data.cs.rx_packets = dev->stats.rx_packets; + hi.data.cs.rx_errors = dev->stats.rx_errors; break; case HDLCDRVCTL_OLDGETSTAT: @@ -1147,7 +1133,6 @@ static void baycom_probe(struct net_device *dev) dev->stop = epp_close; dev->do_ioctl = baycom_ioctl; dev->hard_start_xmit = baycom_send_packet; - dev->get_stats = baycom_get_stats; /* Fill in the fields of the device structure */ bc->skb = NULL; -- GitLab From 9772a252b5b2ffbcf163cc07a443a444bf500040 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:30 +0000 Subject: [PATCH 0310/4982] baycom: convert to net_device_ops Signed-off-by: Stephen Hemminger Acked-by: Thomas Sailer Signed-off-by: David S. Miller --- drivers/net/hamradio/baycom_epp.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index c6e4ec3ade6..bb78c11559c 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c @@ -1102,6 +1102,14 @@ static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /* --------------------------------------------------------------------- */ +static const struct net_device_ops baycom_netdev_ops = { + .ndo_open = epp_open, + .ndo_stop = epp_close, + .ndo_do_ioctl = baycom_ioctl, + .ndo_start_xmit = baycom_send_packet, + .ndo_set_mac_address = baycom_set_mac_address, +}; + /* * Check for a network adaptor of this type, and return '0' if one exists. * If dev->base_addr == 0, probe all likely locations. @@ -1129,16 +1137,12 @@ static void baycom_probe(struct net_device *dev) /* * initialize the device struct */ - dev->open = epp_open; - dev->stop = epp_close; - dev->do_ioctl = baycom_ioctl; - dev->hard_start_xmit = baycom_send_packet; /* Fill in the fields of the device structure */ bc->skb = NULL; + dev->netdev_ops = &baycom_netdev_ops; dev->header_ops = &ax25_header_ops; - dev->set_mac_address = baycom_set_mac_address; dev->type = ARPHRD_AX25; /* AF_AX25 device */ dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN; -- GitLab From f57505fd7ce559bacf5cde26a79ea355fa3bc1ce Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:31 +0000 Subject: [PATCH 0311/4982] bpqether: convert to internal net_device_stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/hamradio/bpqether.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index 46f8f3390e7..b662b67125b 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c @@ -110,7 +110,6 @@ struct bpqdev { struct list_head bpq_list; /* list of bpq devices chain */ struct net_device *ethdev; /* link to ethernet device */ struct net_device *axdev; /* bpq device (bpq#) */ - struct net_device_stats stats; /* some statistics */ char dest_addr[6]; /* ether destination address */ char acpt_addr[6]; /* accept ether frames from this address only */ }; @@ -222,8 +221,8 @@ static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty skb_pull(skb, 2); /* Remove the length bytes */ skb_trim(skb, len); /* Set the length of the data */ - bpq->stats.rx_packets++; - bpq->stats.rx_bytes += len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += len; ptr = skb_push(skb, 1); *ptr = 0; @@ -292,7 +291,7 @@ static int bpq_xmit(struct sk_buff *skb, struct net_device *dev) bpq = netdev_priv(dev); if ((dev = bpq_get_ether_dev(dev)) == NULL) { - bpq->stats.tx_dropped++; + dev->stats.tx_dropped++; kfree_skb(skb); return -ENODEV; } @@ -300,24 +299,14 @@ static int bpq_xmit(struct sk_buff *skb, struct net_device *dev) skb->protocol = ax25_type_trans(skb, dev); skb_reset_network_header(skb); dev_hard_header(skb, dev, ETH_P_BPQ, bpq->dest_addr, NULL, 0); - bpq->stats.tx_packets++; - bpq->stats.tx_bytes+=skb->len; + dev->stats.tx_packets++; + dev->stats.tx_bytes+=skb->len; dev_queue_xmit(skb); netif_wake_queue(dev); return 0; } -/* - * Statistics - */ -static struct net_device_stats *bpq_get_stats(struct net_device *dev) -{ - struct bpqdev *bpq = netdev_priv(dev); - - return &bpq->stats; -} - /* * Set AX.25 callsign */ -- GitLab From 283767e70501a02e676c99964e5a3f09ec993469 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:32 +0000 Subject: [PATCH 0312/4982] bpqether: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/hamradio/bpqether.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index b662b67125b..4bf0f19ecfa 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c @@ -466,16 +466,17 @@ static const struct file_operations bpq_info_fops = { /* ------------------------------------------------------------------------ */ +static const struct net_device_ops bpq_netdev_ops = { + .ndo_open = bpq_open, + .ndo_stop = bpq_close, + .ndo_start_xmit = bpq_xmit, + .ndo_set_mac_address = bpq_set_mac_address, + .ndo_do_ioctl = bpq_ioctl, +}; static void bpq_setup(struct net_device *dev) { - - dev->hard_start_xmit = bpq_xmit; - dev->open = bpq_open; - dev->stop = bpq_close; - dev->set_mac_address = bpq_set_mac_address; - dev->get_stats = bpq_get_stats; - dev->do_ioctl = bpq_ioctl; + dev->netdev_ops = &bpq_netdev_ops; dev->destructor = free_netdev; memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN); -- GitLab From 13c0582d91ab63087a30addcfe42874541ca2689 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:33 +0000 Subject: [PATCH 0313/4982] dmascc: convert to internal network device stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/hamradio/dmascc.c | 41 ++++++++++++++--------------------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c index e67103396ed..b0817ea56bb 100644 --- a/drivers/net/hamradio/dmascc.c +++ b/drivers/net/hamradio/dmascc.c @@ -195,7 +195,7 @@ struct scc_priv { int chip; struct net_device *dev; struct scc_info *info; - struct net_device_stats stats; + int channel; int card_base, scc_cmd, scc_data; int tmr_cnt, tmr_ctrl, tmr_mode; @@ -239,7 +239,6 @@ static int scc_open(struct net_device *dev); static int scc_close(struct net_device *dev); static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); static int scc_send_packet(struct sk_buff *skb, struct net_device *dev); -static struct net_device_stats *scc_get_stats(struct net_device *dev); static int scc_set_mac_address(struct net_device *dev, void *sa); static inline void tx_on(struct scc_priv *priv); @@ -961,14 +960,6 @@ static int scc_send_packet(struct sk_buff *skb, struct net_device *dev) } -static struct net_device_stats *scc_get_stats(struct net_device *dev) -{ - struct scc_priv *priv = dev->ml_priv; - - return &priv->stats; -} - - static int scc_set_mac_address(struct net_device *dev, void *sa) { memcpy(dev->dev_addr, ((struct sockaddr *) sa)->sa_data, @@ -1216,17 +1207,17 @@ static void special_condition(struct scc_priv *priv, int rc) } if (priv->rx_over) { /* We had an overrun */ - priv->stats.rx_errors++; + priv->dev->stats.rx_errors++; if (priv->rx_over == 2) - priv->stats.rx_length_errors++; + priv->dev->stats.rx_length_errors++; else - priv->stats.rx_fifo_errors++; + priv->dev->stats.rx_fifo_errors++; priv->rx_over = 0; } else if (rc & CRC_ERR) { /* Count invalid CRC only if packet length >= minimum */ if (cb >= 15) { - priv->stats.rx_errors++; - priv->stats.rx_crc_errors++; + priv->dev->stats.rx_errors++; + priv->dev->stats.rx_crc_errors++; } } else { if (cb >= 15) { @@ -1239,8 +1230,8 @@ static void special_condition(struct scc_priv *priv, int rc) priv->rx_count++; schedule_work(&priv->rx_work); } else { - priv->stats.rx_errors++; - priv->stats.rx_over_errors++; + priv->dev->stats.rx_errors++; + priv->dev->stats.rx_over_errors++; } } } @@ -1275,7 +1266,7 @@ static void rx_bh(struct work_struct *ugli_api) skb = dev_alloc_skb(cb + 1); if (skb == NULL) { /* Drop packet */ - priv->stats.rx_dropped++; + priv->dev->stats.rx_dropped++; } else { /* Fill buffer */ data = skb_put(skb, cb + 1); @@ -1283,8 +1274,8 @@ static void rx_bh(struct work_struct *ugli_api) memcpy(&data[1], priv->rx_buf[i], cb); skb->protocol = ax25_type_trans(skb, priv->dev); netif_rx(skb); - priv->stats.rx_packets++; - priv->stats.rx_bytes += cb; + priv->dev->stats.rx_packets++; + priv->dev->stats.rx_bytes += cb; } spin_lock_irqsave(&priv->ring_lock, flags); /* Move tail */ @@ -1351,15 +1342,15 @@ static void es_isr(struct scc_priv *priv) write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN); if (res) { /* Update packet statistics */ - priv->stats.tx_errors++; - priv->stats.tx_fifo_errors++; + priv->dev->stats.tx_errors++; + priv->dev->stats.tx_fifo_errors++; /* Other underrun interrupts may already be waiting */ write_scc(priv, R0, RES_EXT_INT); write_scc(priv, R0, RES_EXT_INT); } else { /* Update packet statistics */ - priv->stats.tx_packets++; - priv->stats.tx_bytes += priv->tx_len[i]; + priv->dev->stats.tx_packets++; + priv->dev->stats.tx_bytes += priv->tx_len[i]; /* Remove frame from FIFO */ priv->tx_tail = (i + 1) % NUM_TX_BUF; priv->tx_count--; @@ -1425,7 +1416,7 @@ static void tm_isr(struct scc_priv *priv) write_scc(priv, R15, DCDIE); priv->rr0 = read_scc(priv, R0); if (priv->rr0 & DCD) { - priv->stats.collisions++; + priv->dev->stats.collisions++; rx_on(priv); priv->state = RX_ON; } else { -- GitLab From 52db625079e8f231a3e53e89871bd5adb66e8464 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:34 +0000 Subject: [PATCH 0314/4982] dmascc: convert to network_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/hamradio/dmascc.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c index b0817ea56bb..881bf818bb4 100644 --- a/drivers/net/hamradio/dmascc.c +++ b/drivers/net/hamradio/dmascc.c @@ -440,6 +440,13 @@ static void __init dev_setup(struct net_device *dev) memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN); } +static const struct net_device_ops scc_netdev_ops = { + .ndo_open = scc_open, + .ndo_stop = scc_close, + .ndo_start_xmit = scc_send_packet, + .ndo_do_ioctl = scc_ioctl, +}; + static int __init setup_adapter(int card_base, int type, int n) { int i, irq, chip; @@ -575,11 +582,7 @@ static int __init setup_adapter(int card_base, int type, int n) sprintf(dev->name, "dmascc%i", 2 * n + i); dev->base_addr = card_base; dev->irq = irq; - dev->open = scc_open; - dev->stop = scc_close; - dev->do_ioctl = scc_ioctl; - dev->hard_start_xmit = scc_send_packet; - dev->get_stats = scc_get_stats; + dev->netdev_ops = &scc_netdev_ops; dev->header_ops = &ax25_header_ops; dev->set_mac_address = scc_set_mac_address; } -- GitLab From 5a7616af604caf0d436a1ed0d4298bb25cd77d67 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:35 +0000 Subject: [PATCH 0315/4982] hdlcdrv: convert to internal net_device_stats Signed-off-by: Stephen Hemminger Acked-by: Thomas Sailer Signed-off-by: David S. Miller --- drivers/net/hamradio/hdlcdrv.c | 27 +++++++-------------------- include/linux/hdlcdrv.h | 1 - 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c index 8eba61a1d4a..1215a49c38f 100644 --- a/drivers/net/hamradio/hdlcdrv.c +++ b/drivers/net/hamradio/hdlcdrv.c @@ -154,7 +154,7 @@ static void hdlc_rx_flag(struct net_device *dev, struct hdlcdrv_state *s) pkt_len = s->hdlcrx.len - 2 + 1; /* KISS kludge */ if (!(skb = dev_alloc_skb(pkt_len))) { printk("%s: memory squeeze, dropping packet\n", dev->name); - s->stats.rx_dropped++; + dev->stats.rx_dropped++; return; } cp = skb_put(skb, pkt_len); @@ -162,7 +162,7 @@ static void hdlc_rx_flag(struct net_device *dev, struct hdlcdrv_state *s) memcpy(cp, s->hdlcrx.buffer, pkt_len - 1); skb->protocol = ax25_type_trans(skb, dev); netif_rx(skb); - s->stats.rx_packets++; + dev->stats.rx_packets++; } void hdlcdrv_receiver(struct net_device *dev, struct hdlcdrv_state *s) @@ -326,7 +326,7 @@ void hdlcdrv_transmitter(struct net_device *dev, struct hdlcdrv_state *s) s->hdlctx.len = pkt_len+2; /* the appended CRC */ s->hdlctx.tx_state = 2; s->hdlctx.bitstream = 0; - s->stats.tx_packets++; + dev->stats.tx_packets++; break; case 2: if (!s->hdlctx.len) { @@ -426,19 +426,6 @@ static int hdlcdrv_set_mac_address(struct net_device *dev, void *addr) return 0; } -/* --------------------------------------------------------------------- */ - -static struct net_device_stats *hdlcdrv_get_stats(struct net_device *dev) -{ - struct hdlcdrv_state *sm = netdev_priv(dev); - - /* - * Get the current statistics. This may be called with the - * card open or closed. - */ - return &sm->stats; -} - /* --------------------------------------------------------------------- */ /* * Open/initialize the board. This is called (in the current kernel) @@ -568,10 +555,10 @@ static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) bi.data.cs.ptt = hdlcdrv_ptt(s); bi.data.cs.dcd = s->hdlcrx.dcd; bi.data.cs.ptt_keyed = s->ptt_keyed; - bi.data.cs.tx_packets = s->stats.tx_packets; - bi.data.cs.tx_errors = s->stats.tx_errors; - bi.data.cs.rx_packets = s->stats.rx_packets; - bi.data.cs.rx_errors = s->stats.rx_errors; + bi.data.cs.tx_packets = dev->stats.tx_packets; + bi.data.cs.tx_errors = dev->stats.tx_errors; + bi.data.cs.rx_packets = dev->stats.rx_packets; + bi.data.cs.rx_errors = dev->stats.rx_errors; break; case HDLCDRVCTL_OLDGETSTAT: diff --git a/include/linux/hdlcdrv.h b/include/linux/hdlcdrv.h index bf6302f6b5f..0821bac62b8 100644 --- a/include/linux/hdlcdrv.h +++ b/include/linux/hdlcdrv.h @@ -241,7 +241,6 @@ struct hdlcdrv_state { struct hdlcdrv_bitbuffer bitbuf_hdlc; #endif /* HDLCDRV_DEBUG */ - struct net_device_stats stats; int ptt_keyed; /* queued skb for transmission */ -- GitLab From 2d8b223d81a385a746befc7facf93680f4185533 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:36 +0000 Subject: [PATCH 0316/4982] hdlcdrv: convert to net_device_ops Signed-off-by: Stephen Hemminger Acked-by: Thomas Sailer Signed-off-by: David S. Miller --- drivers/net/hamradio/hdlcdrv.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c index 1215a49c38f..61de56e45ee 100644 --- a/drivers/net/hamradio/hdlcdrv.c +++ b/drivers/net/hamradio/hdlcdrv.c @@ -617,6 +617,14 @@ static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /* --------------------------------------------------------------------- */ +static const struct net_device_ops hdlcdrv_netdev = { + .ndo_open = hdlcdrv_open, + .ndo_stop = hdlcdrv_close, + .ndo_start_xmit = hdlcdrv_send_packet, + .ndo_do_ioctl = hdlcdrv_ioctl, + .ndo_set_mac_address = hdlcdrv_set_mac_address, +}; + /* * Initialize fields in hdlcdrv */ @@ -656,21 +664,13 @@ static void hdlcdrv_setup(struct net_device *dev) s->bitbuf_hdlc.shreg = 0x80; #endif /* HDLCDRV_DEBUG */ - /* - * initialize the device struct - */ - dev->open = hdlcdrv_open; - dev->stop = hdlcdrv_close; - dev->do_ioctl = hdlcdrv_ioctl; - dev->hard_start_xmit = hdlcdrv_send_packet; - dev->get_stats = hdlcdrv_get_stats; /* Fill in the fields of the device structure */ s->skb = NULL; + dev->netdev_ops = &hdlcdrv_netdev; dev->header_ops = &ax25_header_ops; - dev->set_mac_address = hdlcdrv_set_mac_address; dev->type = ARPHRD_AX25; /* AF_AX25 device */ dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN; -- GitLab From 3c94acb7ee343e49075c8f3c72c1920633fc230c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:37 +0000 Subject: [PATCH 0317/4982] yam: convert to internal net_device_stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/hamradio/yam.c | 42 ++++++++------------------------------ 1 file changed, 9 insertions(+), 33 deletions(-) diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c index 5407f7486c9..be280871e9a 100644 --- a/drivers/net/hamradio/yam.c +++ b/drivers/net/hamradio/yam.c @@ -115,10 +115,6 @@ struct yam_port { struct net_device *dev; - /* Stats section */ - - struct net_device_stats stats; - int nb_rxint; int nb_mdint; @@ -507,7 +503,7 @@ static inline void yam_rx_flag(struct net_device *dev, struct yam_port *yp) } else { if (!(skb = dev_alloc_skb(pkt_len))) { printk(KERN_WARNING "%s: memory squeeze, dropping packet\n", dev->name); - ++yp->stats.rx_dropped; + ++dev->stats.rx_dropped; } else { unsigned char *cp; cp = skb_put(skb, pkt_len); @@ -515,7 +511,7 @@ static inline void yam_rx_flag(struct net_device *dev, struct yam_port *yp) memcpy(cp, yp->rx_buf, pkt_len - 1); skb->protocol = ax25_type_trans(skb, dev); netif_rx(skb); - ++yp->stats.rx_packets; + ++dev->stats.rx_packets; } } } @@ -677,7 +673,7 @@ static void yam_tx_byte(struct net_device *dev, struct yam_port *yp) yp->tx_count = 1; yp->tx_state = TX_HEAD; } - ++yp->stats.tx_packets; + ++dev->stats.tx_packets; break; case TX_TAIL: if (--yp->tx_count <= 0) { @@ -716,7 +712,7 @@ static irqreturn_t yam_interrupt(int irq, void *dev_id) handled = 1; if (lsr & LSR_OE) - ++yp->stats.rx_fifo_errors; + ++dev->stats.rx_fifo_errors; yp->dcd = (msr & RX_DCD) ? 1 : 0; @@ -778,11 +774,11 @@ static int yam_seq_show(struct seq_file *seq, void *v) seq_printf(seq, " TxTail %u\n", yp->txtail); seq_printf(seq, " SlotTime %u\n", yp->slot); seq_printf(seq, " Persist %u\n", yp->pers); - seq_printf(seq, " TxFrames %lu\n", yp->stats.tx_packets); - seq_printf(seq, " RxFrames %lu\n", yp->stats.rx_packets); + seq_printf(seq, " TxFrames %lu\n", dev->stats.tx_packets); + seq_printf(seq, " RxFrames %lu\n", dev->stats.rx_packets); seq_printf(seq, " TxInt %u\n", yp->nb_mdint); seq_printf(seq, " RxInt %u\n", yp->nb_rxint); - seq_printf(seq, " RxOver %lu\n", yp->stats.rx_fifo_errors); + seq_printf(seq, " RxOver %lu\n", dev->stats.rx_fifo_errors); seq_printf(seq, "\n"); return 0; } @@ -810,26 +806,6 @@ static const struct file_operations yam_info_fops = { #endif -/* --------------------------------------------------------------------- */ - -static struct net_device_stats *yam_get_stats(struct net_device *dev) -{ - struct yam_port *yp; - - if (!dev) - return NULL; - - yp = netdev_priv(dev); - if (yp->magic != YAM_MAGIC) - return NULL; - - /* - * Get the current statistics. This may be called with the - * card open or closed. - */ - return &yp->stats; -} - /* --------------------------------------------------------------------- */ static int yam_open(struct net_device *dev) @@ -878,9 +854,9 @@ static int yam_open(struct net_device *dev) /* Reset overruns for all ports - FPGA programming makes overruns */ for (i = 0; i < NR_PORTS; i++) { struct net_device *dev = yam_devs[i]; - struct yam_port *yp = netdev_priv(dev); + inb(LSR(dev->base_addr)); - yp->stats.rx_fifo_errors = 0; + dev->stats.rx_fifo_errors = 0; } printk(KERN_INFO "%s at iobase 0x%lx irq %u uart %s\n", dev->name, dev->base_addr, dev->irq, -- GitLab From 3f75f7482f7687b8ffe9e0ddad560797a9f9ad6e Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:38 +0000 Subject: [PATCH 0318/4982] yam: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/hamradio/yam.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c index be280871e9a..e2b0a19203a 100644 --- a/drivers/net/hamradio/yam.c +++ b/drivers/net/hamradio/yam.c @@ -1044,6 +1044,14 @@ static int yam_set_mac_address(struct net_device *dev, void *addr) /* --------------------------------------------------------------------- */ +static const struct net_device_ops yam_netdev_ops = { + .ndo_open = yam_open, + .ndo_stop = yam_close, + .ndo_start_xmit = yam_send_packet, + .ndo_do_ioctl = yam_ioctl, + .ndo_set_mac_address = yam_set_mac_address, +}; + static void yam_setup(struct net_device *dev) { struct yam_port *yp = netdev_priv(dev); @@ -1064,18 +1072,11 @@ static void yam_setup(struct net_device *dev) dev->base_addr = yp->iobase; dev->irq = yp->irq; - dev->open = yam_open; - dev->stop = yam_close; - dev->do_ioctl = yam_ioctl; - dev->hard_start_xmit = yam_send_packet; - dev->get_stats = yam_get_stats; - skb_queue_head_init(&yp->send_queue); + dev->netdev_ops = &yam_netdev_ops; dev->header_ops = &ax25_header_ops; - dev->set_mac_address = yam_set_mac_address; - dev->type = ARPHRD_AX25; dev->hard_header_len = AX25_MAX_HEADER_LEN; dev->mtu = AX25_MTU; -- GitLab From ff908cf83498010e832819cf50a23e16c43b1373 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:39 +0000 Subject: [PATCH 0319/4982] scc: convert to internal net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/hamradio/scc.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c index c011af7088e..49f9d2491d4 100644 --- a/drivers/net/hamradio/scc.c +++ b/drivers/net/hamradio/scc.c @@ -1542,23 +1542,24 @@ static int scc_net_alloc(const char *name, struct scc_channel *scc) /* * Network driver methods * */ /* ******************************************************************** */ +static const struct net_device_ops scc_netdev_ops = { + .ndo_open = scc_net_open, + .ndo_stop = scc_net_close, + .ndo_start_xmit = scc_net_tx, + .ndo_set_mac_address = scc_net_set_mac_address, + .ndo_get_stats = scc_net_get_stats, + .ndo_do_ioctl = scc_net_ioctl, +}; + /* ----> Initialize device <----- */ static void scc_net_setup(struct net_device *dev) { dev->tx_queue_len = 16; /* should be enough... */ - dev->open = scc_net_open; - dev->stop = scc_net_close; - - dev->hard_start_xmit = scc_net_tx; + dev->netdev_ops = &scc_netdev_ops; dev->header_ops = &ax25_header_ops; - dev->set_mac_address = scc_net_set_mac_address; - dev->get_stats = scc_net_get_stats; - dev->do_ioctl = scc_net_ioctl; - dev->tx_timeout = NULL; - memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN); memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN); -- GitLab From ddbe9a686805c36a0e68451ebb8cb51b21d0c718 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:40 +0000 Subject: [PATCH 0320/4982] mkiss: convert to internal network device stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/hamradio/mkiss.c | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index bbdb311b842..6fc0e698bcb 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -59,8 +59,6 @@ struct mkiss { unsigned char *xhead; /* pointer to next byte to XMIT */ int xleft; /* bytes left in XMIT queue */ - struct net_device_stats stats; - /* Detailed SLIP statistics. */ int mtu; /* Our mtu (to spot changes!) */ int buffsize; /* Max buffers sizes */ @@ -253,7 +251,7 @@ static void ax_bump(struct mkiss *ax) if (ax->rbuff[0] > 0x0f) { if (ax->rbuff[0] & 0x80) { if (check_crc_16(ax->rbuff, ax->rcount) < 0) { - ax->stats.rx_errors++; + ax->dev->stats.rx_errors++; spin_unlock_bh(&ax->buflock); return; @@ -268,7 +266,7 @@ static void ax_bump(struct mkiss *ax) *ax->rbuff &= ~0x80; } else if (ax->rbuff[0] & 0x20) { if (check_crc_flex(ax->rbuff, ax->rcount) < 0) { - ax->stats.rx_errors++; + ax->dev->stats.rx_errors++; spin_unlock_bh(&ax->buflock); return; } @@ -295,7 +293,7 @@ static void ax_bump(struct mkiss *ax) if ((skb = dev_alloc_skb(count)) == NULL) { printk(KERN_ERR "mkiss: %s: memory squeeze, dropping packet.\n", ax->dev->name); - ax->stats.rx_dropped++; + ax->dev->stats.rx_dropped++; spin_unlock_bh(&ax->buflock); return; } @@ -303,8 +301,8 @@ static void ax_bump(struct mkiss *ax) memcpy(skb_put(skb,count), ax->rbuff, count); skb->protocol = ax25_type_trans(skb, ax->dev); netif_rx(skb); - ax->stats.rx_packets++; - ax->stats.rx_bytes += count; + ax->dev->stats.rx_packets++; + ax->dev->stats.rx_bytes += count; spin_unlock_bh(&ax->buflock); } @@ -344,7 +342,7 @@ static void kiss_unesc(struct mkiss *ax, unsigned char s) return; } - ax->stats.rx_over_errors++; + ax->dev->stats.rx_over_errors++; set_bit(AXF_ERROR, &ax->flags); } spin_unlock_bh(&ax->buflock); @@ -406,7 +404,7 @@ static void ax_changedmtu(struct mkiss *ax) memcpy(ax->xbuff, ax->xhead, ax->xleft); } else { ax->xleft = 0; - ax->stats.tx_dropped++; + dev->stats.tx_dropped++; } } @@ -417,7 +415,7 @@ static void ax_changedmtu(struct mkiss *ax) memcpy(ax->rbuff, orbuff, ax->rcount); } else { ax->rcount = 0; - ax->stats.rx_over_errors++; + dev->stats.rx_over_errors++; set_bit(AXF_ERROR, &ax->flags); } } @@ -444,7 +442,7 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len) if (len > ax->mtu) { /* Sigh, shouldn't occur BUT ... */ len = ax->mtu; printk(KERN_ERR "mkiss: %s: truncating oversized transmit packet!\n", ax->dev->name); - ax->stats.tx_dropped++; + dev->stats.tx_dropped++; netif_start_queue(dev); return; } @@ -518,8 +516,8 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len) set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags); actual = ax->tty->ops->write(ax->tty, ax->xbuff, count); - ax->stats.tx_packets++; - ax->stats.tx_bytes += actual; + dev->stats.tx_packets++; + dev->stats.tx_bytes += actual; ax->dev->trans_start = jiffies; ax->xleft = count - actual; @@ -664,13 +662,6 @@ static int ax_close(struct net_device *dev) return 0; } -static struct net_device_stats *ax_get_stats(struct net_device *dev) -{ - struct mkiss *ax = netdev_priv(dev); - - return &ax->stats; -} - static const struct header_ops ax_header_ops = { .create = ax_header, .rebuild = ax_rebuild_header, @@ -683,7 +674,6 @@ static void ax_setup(struct net_device *dev) dev->hard_start_xmit = ax_xmit; dev->open = ax_open_dev; dev->stop = ax_close; - dev->get_stats = ax_get_stats; dev->set_mac_address = ax_set_mac_address; dev->hard_header_len = 0; dev->addr_len = 0; @@ -929,7 +919,7 @@ static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp, while (count--) { if (fp != NULL && *fp++) { if (!test_and_set_bit(AXF_ERROR, &ax->flags)) - ax->stats.rx_errors++; + ax->dev->stats.rx_errors++; cp++; continue; } -- GitLab From 6095e08126790592699d8aeef4d31b263a4176a4 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:41 +0000 Subject: [PATCH 0321/4982] dmascc: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/hamradio/mkiss.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index 6fc0e698bcb..ed5b37d4333 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -667,19 +667,23 @@ static const struct header_ops ax_header_ops = { .rebuild = ax_rebuild_header, }; +static const struct net_device_ops ax_netdev_ops = { + .ndo_open = ax_open_dev, + .ndo_stop = ax_close, + .ndo_start_xmit = ax_xmit, + .ndo_set_mac_address = ax_set_mac_address, +}; + static void ax_setup(struct net_device *dev) { /* Finish setting up the DEVICE info. */ dev->mtu = AX_MTU; - dev->hard_start_xmit = ax_xmit; - dev->open = ax_open_dev; - dev->stop = ax_close; - dev->set_mac_address = ax_set_mac_address; dev->hard_header_len = 0; dev->addr_len = 0; dev->type = ARPHRD_AX25; dev->tx_queue_len = 10; dev->header_ops = &ax_header_ops; + dev->netdev_ops = &ax_netdev_ops; memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN); -- GitLab From ba270ede101ad7439de7d4e92b71eece26db5c26 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 13:01:42 +0000 Subject: [PATCH 0322/4982] dmascc: convert to internal net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/82596.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/82596.c b/drivers/net/82596.c index b273596368e..cca94b9c08a 100644 --- a/drivers/net/82596.c +++ b/drivers/net/82596.c @@ -1122,6 +1122,17 @@ static void print_eth(unsigned char *add, char *str) static int io = 0x300; static int irq = 10; +static const struct net_device_ops i596_netdev_ops = { + .ndo_open = i596_open, + .ndo_stop = i596_close, + .ndo_start_xmit = i596_start_xmit, + .ndo_set_multicast_list = set_multicast_list, + .ndo_tx_timeout = i596_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + struct net_device * __init i82596_probe(int unit) { struct net_device *dev; @@ -1232,11 +1243,7 @@ found: DEB(DEB_PROBE,printk(KERN_INFO "%s", version)); /* The 82596-specific entries in the device structure. */ - dev->open = i596_open; - dev->stop = i596_close; - dev->hard_start_xmit = i596_start_xmit; - dev->set_multicast_list = set_multicast_list; - dev->tx_timeout = i596_tx_timeout; + dev->netdev_ops = &i596_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; dev->ml_priv = (void *)(dev->mem_start); -- GitLab From 0e0b46d80f8768c465c14994aba91ee714b0d7b7 Mon Sep 17 00:00:00 2001 From: Frank Blaschka Date: Fri, 9 Jan 2009 03:43:56 +0000 Subject: [PATCH 0323/4982] lcs: convert to net_device_ops lcs convert to net_device_ops. Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/lcs.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index acca6678cb2..bca08eff4a7 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -2097,6 +2097,20 @@ lcs_register_netdev(struct ccwgroup_device *ccwgdev) /** * lcs_new_device will be called by setting the group device online. */ +static const struct net_device_ops lcs_netdev_ops = { + .ndo_open = lcs_open_device, + .ndo_stop = lcs_stop_device, + .ndo_get_stats = lcs_getstats, + .ndo_start_xmit = lcs_start_xmit, +}; + +static const struct net_device_ops lcs_mc_netdev_ops = { + .ndo_open = lcs_open_device, + .ndo_stop = lcs_stop_device, + .ndo_get_stats = lcs_getstats, + .ndo_start_xmit = lcs_start_xmit, + .ndo_set_multicast_list = lcs_set_multicast_list, +}; static int lcs_new_device(struct ccwgroup_device *ccwgdev) @@ -2164,14 +2178,11 @@ lcs_new_device(struct ccwgroup_device *ccwgdev) goto out; card->dev = dev; card->dev->ml_priv = card; - card->dev->open = lcs_open_device; - card->dev->stop = lcs_stop_device; - card->dev->hard_start_xmit = lcs_start_xmit; - card->dev->get_stats = lcs_getstats; + card->dev->netdev_ops = &lcs_netdev_ops; memcpy(card->dev->dev_addr, card->mac, LCS_MAC_LENGTH); #ifdef CONFIG_IP_MULTICAST if (!lcs_check_multicast_support(card)) - card->dev->set_multicast_list = lcs_set_multicast_list; + card->dev->netdev_ops = &lcs_mc_netdev_ops; #endif netdev_out: lcs_set_allowed_threads(card,0xffffffff); -- GitLab From 69b3aa609cab34928931b86632316d065ba17ba3 Mon Sep 17 00:00:00 2001 From: Frank Blaschka Date: Fri, 9 Jan 2009 03:43:57 +0000 Subject: [PATCH 0324/4982] ctcm: convert to net_device_ops ctcm convert to net_device_ops. Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/ctcm_main.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index 2678573bece..8f2a888d0a0 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -1099,12 +1099,24 @@ static void ctcm_free_netdevice(struct net_device *dev) struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv); +static const struct net_device_ops ctcm_netdev_ops = { + .ndo_open = ctcm_open, + .ndo_stop = ctcm_close, + .ndo_get_stats = ctcm_stats, + .ndo_change_mtu = ctcm_change_mtu, + .ndo_start_xmit = ctcm_tx, +}; + +static const struct net_device_ops ctcm_mpc_netdev_ops = { + .ndo_open = ctcm_open, + .ndo_stop = ctcm_close, + .ndo_get_stats = ctcm_stats, + .ndo_change_mtu = ctcm_change_mtu, + .ndo_start_xmit = ctcmpc_tx, +}; + void static ctcm_dev_setup(struct net_device *dev) { - dev->open = ctcm_open; - dev->stop = ctcm_close; - dev->get_stats = ctcm_stats; - dev->change_mtu = ctcm_change_mtu; dev->type = ARPHRD_SLIP; dev->tx_queue_len = 100; dev->flags = IFF_POINTOPOINT | IFF_NOARP; @@ -1157,12 +1169,12 @@ static struct net_device *ctcm_init_netdevice(struct ctcm_priv *priv) dev->mtu = MPC_BUFSIZE_DEFAULT - TH_HEADER_LENGTH - PDU_HEADER_LENGTH; - dev->hard_start_xmit = ctcmpc_tx; + dev->netdev_ops = &ctcm_mpc_netdev_ops; dev->hard_header_len = TH_HEADER_LENGTH + PDU_HEADER_LENGTH; priv->buffer_size = MPC_BUFSIZE_DEFAULT; } else { dev->mtu = CTCM_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2; - dev->hard_start_xmit = ctcm_tx; + dev->netdev_ops = &ctcm_netdev_ops; dev->hard_header_len = LL_HEADER_LENGTH + 2; } -- GitLab From 4edd73b5cf466ab2c9d406fd6768cb3203abfbe5 Mon Sep 17 00:00:00 2001 From: Frank Blaschka Date: Fri, 9 Jan 2009 03:43:58 +0000 Subject: [PATCH 0325/4982] netiucv: convert to net_device_ops netiucv convert to net_device_ops. Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/netiucv.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 930e2fc2a01..1ba4509435f 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -1876,20 +1876,24 @@ static void netiucv_free_netdevice(struct net_device *dev) /** * Initialize a net device. (Called from kernel in alloc_netdev()) */ +static const struct net_device_ops netiucv_netdev_ops = { + .ndo_open = netiucv_open, + .ndo_stop = netiucv_close, + .ndo_get_stats = netiucv_stats, + .ndo_start_xmit = netiucv_tx, + .ndo_change_mtu = netiucv_change_mtu, +}; + static void netiucv_setup_netdevice(struct net_device *dev) { dev->mtu = NETIUCV_MTU_DEFAULT; - dev->hard_start_xmit = netiucv_tx; - dev->open = netiucv_open; - dev->stop = netiucv_close; - dev->get_stats = netiucv_stats; - dev->change_mtu = netiucv_change_mtu; dev->destructor = netiucv_free_netdevice; dev->hard_header_len = NETIUCV_HDRLEN; dev->addr_len = 0; dev->type = ARPHRD_SLIP; dev->tx_queue_len = NETIUCV_QUEUELEN_DEFAULT; dev->flags = IFF_POINTOPOINT | IFF_NOARP; + dev->netdev_ops = &netiucv_netdev_ops; } /** -- GitLab From 2171dc1815fcc5cc08d227155d65bb268070f6a5 Mon Sep 17 00:00:00 2001 From: Frank Blaschka Date: Fri, 9 Jan 2009 03:43:59 +0000 Subject: [PATCH 0326/4982] claw: convert to net_device_ops claw convert to net_device_ops. Signed-off-by: Frank Blaschka --- drivers/s390/net/claw.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index f5e618562c5..3cb387f45b6 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -2816,22 +2816,26 @@ claw_free_netdevice(struct net_device * dev, int free_dev) * Initialize everything of the net device except the name and the * channel structs. */ +static const struct net_device_ops claw_netdev_ops = { + .ndo_open = claw_open, + .ndo_stop = claw_release, + .ndo_get_stats = claw_stats, + .ndo_start_xmit = claw_tx, + .ndo_change_mtu = claw_change_mtu, +}; + static void claw_init_netdevice(struct net_device * dev) { CLAW_DBF_TEXT(2, setup, "init_dev"); CLAW_DBF_TEXT_(2, setup, "%s", dev->name); dev->mtu = CLAW_DEFAULT_MTU_SIZE; - dev->hard_start_xmit = claw_tx; - dev->open = claw_open; - dev->stop = claw_release; - dev->get_stats = claw_stats; - dev->change_mtu = claw_change_mtu; dev->hard_header_len = 0; dev->addr_len = 0; dev->type = ARPHRD_SLIP; dev->tx_queue_len = 1300; dev->flags = IFF_POINTOPOINT | IFF_NOARP; + dev->netdev_ops = &claw_netdev_ops; CLAW_DBF_TEXT(2, setup, "initok"); return; } -- GitLab From a962dc2520d85c278768f5f6028f300152fca7fa Mon Sep 17 00:00:00 2001 From: Inaky Perez-Gonzalez Date: Fri, 9 Jan 2009 16:43:49 +0000 Subject: [PATCH 0327/4982] wimax/i2400m: convert to net_device_ops Signed-off-by: Inaky Perez-Gonzalez Signed-off-by: David S. Miller --- drivers/net/wimax/i2400m/netdev.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c index 63fe708e8a3..57159e4bbfe 100644 --- a/drivers/net/wimax/i2400m/netdev.c +++ b/drivers/net/wimax/i2400m/netdev.c @@ -493,6 +493,14 @@ error_skb_realloc: i2400m, buf, buf_len); } +static const struct net_device_ops i2400m_netdev_ops = { + .ndo_open = i2400m_open, + .ndo_stop = i2400m_stop, + .ndo_start_xmit = i2400m_hard_start_xmit, + .ndo_tx_timeout = i2400m_tx_timeout, + .ndo_change_mtu = i2400m_change_mtu, +}; + /** * i2400m_netdev_setup - Setup setup @net_dev's i2400m private data @@ -513,11 +521,7 @@ void i2400m_netdev_setup(struct net_device *net_dev) & (~IFF_BROADCAST /* i2400m is P2P */ & ~IFF_MULTICAST); net_dev->watchdog_timeo = I2400M_TX_TIMEOUT; - net_dev->open = i2400m_open; - net_dev->stop = i2400m_stop; - net_dev->hard_start_xmit = i2400m_hard_start_xmit; - net_dev->change_mtu = i2400m_change_mtu; - net_dev->tx_timeout = i2400m_tx_timeout; + net_dev->netdev_ops = &i2400m_netdev_ops; d_fnend(3, NULL, "(net_dev %p) = void\n", net_dev); } EXPORT_SYMBOL_GPL(i2400m_netdev_setup); -- GitLab From 7cdc15f5f9db71e9c92422918ab9f8df0d31f81f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Ha=C5=82asa?= Date: Thu, 8 Jan 2009 19:46:54 +0100 Subject: [PATCH 0328/4982] WAN: Generic HDLC now uses IFF_WAN_HDLC private flag. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Krzysztof HaÅ‚asa Signed-off-by: David S. Miller --- drivers/net/wan/hdlc.c | 3 ++- include/linux/if.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c index 1f2a140c9f7..d83cd7884e0 100644 --- a/drivers/net/wan/hdlc.c +++ b/drivers/net/wan/hdlc.c @@ -106,7 +106,7 @@ static int hdlc_device_event(struct notifier_block *this, unsigned long event, if (dev_net(dev) != &init_net) return NOTIFY_DONE; - if (dev->get_stats != hdlc_get_stats) + if (!(dev->priv_flags & IFF_WAN_HDLC)) return NOTIFY_DONE; /* not an HDLC device */ if (event != NETDEV_CHANGE) @@ -235,6 +235,7 @@ static void hdlc_setup_dev(struct net_device *dev) */ dev->get_stats = hdlc_get_stats; dev->flags = IFF_POINTOPOINT | IFF_NOARP; + dev->priv_flags = IFF_WAN_HDLC; dev->mtu = HDLC_MAX_MTU; dev->type = ARPHRD_RAWHDLC; dev->hard_header_len = 16; diff --git a/include/linux/if.h b/include/linux/if.h index 2a6e29620a9..1108f3e099e 100644 --- a/include/linux/if.h +++ b/include/linux/if.h @@ -66,6 +66,7 @@ #define IFF_SLAVE_NEEDARP 0x40 /* need ARPs for validation */ #define IFF_ISATAP 0x80 /* ISATAP interface (RFC4214) */ #define IFF_MASTER_ARPMON 0x100 /* bonding master, ARP mon in use */ +#define IFF_WAN_HDLC 0x200 /* WAN HDLC device */ #define IF_GET_IFACE 0x0001 /* for querying only */ #define IF_GET_PROTO 0x0002 -- GitLab From dff3fde7be8f08c78914fca3d25e1cffe7625faa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Ha=C5=82asa?= Date: Thu, 8 Jan 2009 19:55:57 +0100 Subject: [PATCH 0329/4982] WAN: Allow hw HDLC drivers to override dev->get_stats. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the internal get_stats() by default. Fixes LMC and wanXL drivers. Signed-off-by: Krzysztof HaÅ‚asa Signed-off-by: David S. Miller --- drivers/net/wan/hdlc.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c index d83cd7884e0..dbc179887f8 100644 --- a/drivers/net/wan/hdlc.c +++ b/drivers/net/wan/hdlc.c @@ -52,15 +52,6 @@ static int hdlc_change_mtu(struct net_device *dev, int new_mtu) return 0; } - - -static struct net_device_stats *hdlc_get_stats(struct net_device *dev) -{ - return &dev->stats; -} - - - static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *p, struct net_device *orig_dev) { @@ -102,7 +93,7 @@ static int hdlc_device_event(struct notifier_block *this, unsigned long event, hdlc_device *hdlc; unsigned long flags; int on; - + if (dev_net(dev) != &init_net) return NOTIFY_DONE; @@ -233,7 +224,6 @@ static void hdlc_setup_dev(struct net_device *dev) /* Re-init all variables changed by HDLC protocol drivers, * including ether_setup() called from hdlc_raw_eth.c. */ - dev->get_stats = hdlc_get_stats; dev->flags = IFF_POINTOPOINT | IFF_NOARP; dev->priv_flags = IFF_WAN_HDLC; dev->mtu = HDLC_MAX_MTU; -- GitLab From 991990a12de42281f81b4e3a6471586d2d0caf6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Ha=C5=82asa?= Date: Thu, 8 Jan 2009 22:52:11 +0100 Subject: [PATCH 0330/4982] WAN: Convert generic HDLC drivers to netdev_ops. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also remove unneeded last_rx update from Synclink drivers. Synclink part mostly by Stephen Hemminger. Signed-off-by: Krzysztof HaÅ‚asa Signed-off-by: David S. Miller --- drivers/char/pcmcia/synclink_cs.c | 18 +++++++++++------- drivers/char/synclink.c | 18 +++++++++++------- drivers/char/synclink_gt.c | 18 +++++++++++------- drivers/char/synclinkmp.c | 18 +++++++++++------- drivers/net/wan/c101.c | 12 ++++++++---- drivers/net/wan/cosa.c | 14 ++++++++++---- drivers/net/wan/dscc4.c | 18 +++++++++++------- drivers/net/wan/farsync.c | 18 ++++++++++++------ drivers/net/wan/hdlc.c | 14 +++++++++++--- drivers/net/wan/hdlc_cisco.c | 1 - drivers/net/wan/hdlc_fr.c | 28 +++++++++------------------- drivers/net/wan/hdlc_ppp.c | 2 -- drivers/net/wan/hdlc_raw.c | 3 --- drivers/net/wan/hdlc_raw_eth.c | 8 ++------ drivers/net/wan/hdlc_x25.c | 2 +- drivers/net/wan/hostess_sv11.c | 12 +++++++++--- drivers/net/wan/ixp4xx_hss.c | 12 +++++++++--- drivers/net/wan/lmc/lmc_main.c | 19 +++++++++++-------- drivers/net/wan/lmc/lmc_proto.c | 17 +---------------- drivers/net/wan/n2.c | 12 ++++++++---- drivers/net/wan/pc300too.c | 12 ++++++++---- drivers/net/wan/pci200syn.c | 12 ++++++++---- drivers/net/wan/sealevel.c | 12 +++++++++--- drivers/net/wan/wanxl.c | 14 ++++++++++---- include/linux/hdlc.h | 5 +++++ 25 files changed, 186 insertions(+), 133 deletions(-) diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index dc073e167ab..5608a1e5a3b 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -4311,10 +4311,17 @@ static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size) dev->stats.rx_bytes += size; netif_rx(skb); - - dev->last_rx = jiffies; } +static const struct net_device_ops hdlcdev_ops = { + .ndo_open = hdlcdev_open, + .ndo_stop = hdlcdev_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = hdlcdev_ioctl, + .ndo_tx_timeout = hdlcdev_tx_timeout, +}; + /** * called by device driver when adding device instance * do generic HDLC initialization @@ -4341,11 +4348,8 @@ static int hdlcdev_init(MGSLPC_INFO *info) dev->irq = info->irq_level; /* network layer callbacks and settings */ - dev->do_ioctl = hdlcdev_ioctl; - dev->open = hdlcdev_open; - dev->stop = hdlcdev_close; - dev->tx_timeout = hdlcdev_tx_timeout; - dev->watchdog_timeo = 10*HZ; + dev->netdev_ops = &hdlcdev_ops; + dev->watchdog_timeo = 10 * HZ; dev->tx_queue_len = 50; /* generic HDLC layer callbacks and settings */ diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index b8063d4cad3..0057a8f58cb 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -8007,10 +8007,17 @@ static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size) dev->stats.rx_bytes += size; netif_rx(skb); - - dev->last_rx = jiffies; } +static const struct net_device_ops hdlcdev_ops = { + .ndo_open = hdlcdev_open, + .ndo_stop = hdlcdev_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = hdlcdev_ioctl, + .ndo_tx_timeout = hdlcdev_tx_timeout, +}; + /** * called by device driver when adding device instance * do generic HDLC initialization @@ -8038,11 +8045,8 @@ static int hdlcdev_init(struct mgsl_struct *info) dev->dma = info->dma_level; /* network layer callbacks and settings */ - dev->do_ioctl = hdlcdev_ioctl; - dev->open = hdlcdev_open; - dev->stop = hdlcdev_close; - dev->tx_timeout = hdlcdev_tx_timeout; - dev->watchdog_timeo = 10*HZ; + dev->netdev_ops = &hdlcdev_ops; + dev->watchdog_timeo = 10 * HZ; dev->tx_queue_len = 50; /* generic HDLC layer callbacks and settings */ diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index f329f459817..efb3dc928a4 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -1763,10 +1763,17 @@ static void hdlcdev_rx(struct slgt_info *info, char *buf, int size) dev->stats.rx_bytes += size; netif_rx(skb); - - dev->last_rx = jiffies; } +static const struct net_device_ops hdlcdev_ops = { + .ndo_open = hdlcdev_open, + .ndo_stop = hdlcdev_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = hdlcdev_ioctl, + .ndo_tx_timeout = hdlcdev_tx_timeout, +}; + /** * called by device driver when adding device instance * do generic HDLC initialization @@ -1794,11 +1801,8 @@ static int hdlcdev_init(struct slgt_info *info) dev->irq = info->irq_level; /* network layer callbacks and settings */ - dev->do_ioctl = hdlcdev_ioctl; - dev->open = hdlcdev_open; - dev->stop = hdlcdev_close; - dev->tx_timeout = hdlcdev_tx_timeout; - dev->watchdog_timeo = 10*HZ; + dev->netdev_ops = &hdlcdev_ops; + dev->watchdog_timeo = 10 * HZ; dev->tx_queue_len = 50; /* generic HDLC layer callbacks and settings */ diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 7b0c5b2dd26..8eb6c89a980 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -1907,10 +1907,17 @@ static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size) dev->stats.rx_bytes += size; netif_rx(skb); - - dev->last_rx = jiffies; } +static const struct net_device_ops hdlcdev_ops = { + .ndo_open = hdlcdev_open, + .ndo_stop = hdlcdev_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = hdlcdev_ioctl, + .ndo_tx_timeout = hdlcdev_tx_timeout, +}; + /** * called by device driver when adding device instance * do generic HDLC initialization @@ -1938,11 +1945,8 @@ static int hdlcdev_init(SLMP_INFO *info) dev->irq = info->irq_level; /* network layer callbacks and settings */ - dev->do_ioctl = hdlcdev_ioctl; - dev->open = hdlcdev_open; - dev->stop = hdlcdev_close; - dev->tx_timeout = hdlcdev_tx_timeout; - dev->watchdog_timeo = 10*HZ; + dev->netdev_ops = &hdlcdev_ops; + dev->watchdog_timeo = 10 * HZ; dev->tx_queue_len = 50; /* generic HDLC layer callbacks and settings */ diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c index b46897996f7..9693b0fd323 100644 --- a/drivers/net/wan/c101.c +++ b/drivers/net/wan/c101.c @@ -296,7 +296,13 @@ static void c101_destroy_card(card_t *card) kfree(card); } - +static const struct net_device_ops c101_ops = { + .ndo_open = c101_open, + .ndo_stop = c101_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = c101_ioctl, +}; static int __init c101_run(unsigned long irq, unsigned long winbase) { @@ -367,9 +373,7 @@ static int __init c101_run(unsigned long irq, unsigned long winbase) dev->mem_start = winbase; dev->mem_end = winbase + C101_MAPPED_RAM_SIZE - 1; dev->tx_queue_len = 50; - dev->do_ioctl = c101_ioctl; - dev->open = c101_open; - dev->stop = c101_close; + dev->netdev_ops = &c101_ops; hdlc->attach = sca_attach; hdlc->xmit = sca_xmit; card->settings.clock_type = CLOCK_EXT; diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index d80b72e22de..0d7ba117ef6 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c @@ -427,6 +427,15 @@ static void __exit cosa_exit(void) } module_exit(cosa_exit); +static const struct net_device_ops cosa_ops = { + .ndo_open = cosa_net_open, + .ndo_stop = cosa_net_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = cosa_net_ioctl, + .ndo_tx_timeout = cosa_net_timeout, +}; + static int cosa_probe(int base, int irq, int dma) { struct cosa_data *cosa = cosa_cards+nr_cards; @@ -575,10 +584,7 @@ static int cosa_probe(int base, int irq, int dma) } dev_to_hdlc(chan->netdev)->attach = cosa_net_attach; dev_to_hdlc(chan->netdev)->xmit = cosa_net_tx; - chan->netdev->open = cosa_net_open; - chan->netdev->stop = cosa_net_close; - chan->netdev->do_ioctl = cosa_net_ioctl; - chan->netdev->tx_timeout = cosa_net_timeout; + chan->netdev->netdev_ops = &cosa_ops; chan->netdev->watchdog_timeo = TX_TIMEOUT; chan->netdev->base_addr = chan->cosa->datareg; chan->netdev->irq = chan->cosa->irq; diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index 888025db2f0..8face5db8f3 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -883,6 +883,15 @@ static inline int dscc4_set_quartz(struct dscc4_dev_priv *dpriv, int hz) return ret; } +static const struct net_device_ops dscc4_ops = { + .ndo_open = dscc4_open, + .ndo_stop = dscc4_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = dscc4_ioctl, + .ndo_tx_timeout = dscc4_tx_timeout, +}; + static int dscc4_found1(struct pci_dev *pdev, void __iomem *ioaddr) { struct dscc4_pci_priv *ppriv; @@ -916,13 +925,8 @@ static int dscc4_found1(struct pci_dev *pdev, void __iomem *ioaddr) hdlc_device *hdlc = dev_to_hdlc(d); d->base_addr = (unsigned long)ioaddr; - d->init = NULL; d->irq = pdev->irq; - d->open = dscc4_open; - d->stop = dscc4_close; - d->set_multicast_list = NULL; - d->do_ioctl = dscc4_ioctl; - d->tx_timeout = dscc4_tx_timeout; + d->netdev_ops = &dscc4_ops; d->watchdog_timeo = TX_TIMEOUT; SET_NETDEV_DEV(d, &pdev->dev); @@ -1048,7 +1052,7 @@ static int dscc4_open(struct net_device *dev) struct dscc4_pci_priv *ppriv; int ret = -EAGAIN; - if ((dscc4_loopback_check(dpriv) < 0) || !dev->hard_start_xmit) + if ((dscc4_loopback_check(dpriv) < 0)) goto err; if ((ret = hdlc_open(dev))) diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c index 48a2c9d2895..00945f7c1e9 100644 --- a/drivers/net/wan/farsync.c +++ b/drivers/net/wan/farsync.c @@ -2424,6 +2424,15 @@ fst_init_card(struct fst_card_info *card) type_strings[card->type], card->irq, card->nports); } +static const struct net_device_ops fst_ops = { + .ndo_open = fst_open, + .ndo_stop = fst_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = fst_ioctl, + .ndo_tx_timeout = fst_tx_timeout, +}; + /* * Initialise card when detected. * Returns 0 to indicate success, or errno otherwise. @@ -2565,12 +2574,9 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->base_addr = card->pci_conf; dev->irq = card->irq; - dev->tx_queue_len = FST_TX_QUEUE_LEN; - dev->open = fst_open; - dev->stop = fst_close; - dev->do_ioctl = fst_ioctl; - dev->watchdog_timeo = FST_TX_TIMEOUT; - dev->tx_timeout = fst_tx_timeout; + dev->netdev_ops = &fst_ops; + dev->tx_queue_len = FST_TX_QUEUE_LEN; + dev->watchdog_timeo = FST_TX_TIMEOUT; hdlc->attach = fst_attach; hdlc->xmit = fst_start_xmit; } diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c index dbc179887f8..43da8bd7297 100644 --- a/drivers/net/wan/hdlc.c +++ b/drivers/net/wan/hdlc.c @@ -44,7 +44,7 @@ static const char* version = "HDLC support module revision 1.22"; static struct hdlc_proto *first_proto; -static int hdlc_change_mtu(struct net_device *dev, int new_mtu) +int hdlc_change_mtu(struct net_device *dev, int new_mtu) { if ((new_mtu < 68) || (new_mtu > HDLC_MAX_MTU)) return -EINVAL; @@ -66,7 +66,15 @@ static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev, return hdlc->proto->netif_rx(skb); } +int hdlc_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); + if (hdlc->proto->xmit) + return hdlc->proto->xmit(skb, dev); + + return hdlc->xmit(skb, dev); /* call hardware driver directly */ +} static inline void hdlc_proto_start(struct net_device *dev) { @@ -231,8 +239,6 @@ static void hdlc_setup_dev(struct net_device *dev) dev->hard_header_len = 16; dev->addr_len = 0; dev->header_ops = &hdlc_null_ops; - - dev->change_mtu = hdlc_change_mtu; } static void hdlc_setup(struct net_device *dev) @@ -330,6 +336,8 @@ MODULE_AUTHOR("Krzysztof Halasa "); MODULE_DESCRIPTION("HDLC support module"); MODULE_LICENSE("GPL v2"); +EXPORT_SYMBOL(hdlc_change_mtu); +EXPORT_SYMBOL(hdlc_start_xmit); EXPORT_SYMBOL(hdlc_open); EXPORT_SYMBOL(hdlc_close); EXPORT_SYMBOL(hdlc_ioctl); diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c index 44e64b15dbd..af3fd4fead8 100644 --- a/drivers/net/wan/hdlc_cisco.c +++ b/drivers/net/wan/hdlc_cisco.c @@ -382,7 +382,6 @@ static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr) memcpy(&state(hdlc)->settings, &new_settings, size); spin_lock_init(&state(hdlc)->lock); - dev->hard_start_xmit = hdlc->xmit; dev->header_ops = &cisco_header_ops; dev->type = ARPHRD_CISCO; netif_dormant_on(dev); diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index f1ddd7c3459..70e57cebc95 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c @@ -444,18 +444,6 @@ static int pvc_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } - - -static int pvc_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > HDLC_MAX_MTU)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - - - static inline void fr_log_dlci_active(pvc_device *pvc) { printk(KERN_INFO "%s: DLCI %d [%s%s%s]%s %s\n", @@ -1068,6 +1056,14 @@ static void pvc_setup(struct net_device *dev) dev->addr_len = 2; } +static const struct net_device_ops pvc_ops = { + .ndo_open = pvc_open, + .ndo_stop = pvc_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = pvc_xmit, + .ndo_do_ioctl = pvc_ioctl, +}; + static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type) { hdlc_device *hdlc = dev_to_hdlc(frad); @@ -1104,11 +1100,7 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type) *(__be16*)dev->dev_addr = htons(dlci); dlci_to_q922(dev->broadcast, dlci); } - dev->hard_start_xmit = pvc_xmit; - dev->open = pvc_open; - dev->stop = pvc_close; - dev->do_ioctl = pvc_ioctl; - dev->change_mtu = pvc_change_mtu; + dev->netdev_ops = &pvc_ops; dev->mtu = HDLC_MAX_MTU; dev->tx_queue_len = 0; dev->ml_priv = pvc; @@ -1260,8 +1252,6 @@ static int fr_ioctl(struct net_device *dev, struct ifreq *ifr) state(hdlc)->dce_pvc_count = 0; } memcpy(&state(hdlc)->settings, &new_settings, size); - - dev->hard_start_xmit = hdlc->xmit; dev->type = ARPHRD_FRAD; return 0; diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c index 57fe714c1c7..7b8a5eae201 100644 --- a/drivers/net/wan/hdlc_ppp.c +++ b/drivers/net/wan/hdlc_ppp.c @@ -558,7 +558,6 @@ out: return NET_RX_DROP; } - static void ppp_timer(unsigned long arg) { struct proto *proto = (struct proto *)arg; @@ -679,7 +678,6 @@ static int ppp_ioctl(struct net_device *dev, struct ifreq *ifr) ppp->keepalive_interval = 10; ppp->keepalive_timeout = 60; - dev->hard_start_xmit = hdlc->xmit; dev->hard_header_len = sizeof(struct hdlc_header); dev->header_ops = &ppp_header_ops; dev->type = ARPHRD_PPP; diff --git a/drivers/net/wan/hdlc_raw.c b/drivers/net/wan/hdlc_raw.c index 8612311748f..6e92c64ebd0 100644 --- a/drivers/net/wan/hdlc_raw.c +++ b/drivers/net/wan/hdlc_raw.c @@ -30,8 +30,6 @@ static __be16 raw_type_trans(struct sk_buff *skb, struct net_device *dev) return __constant_htons(ETH_P_IP); } - - static struct hdlc_proto proto = { .type_trans = raw_type_trans, .ioctl = raw_ioctl, @@ -86,7 +84,6 @@ static int raw_ioctl(struct net_device *dev, struct ifreq *ifr) if (result) return result; memcpy(hdlc->state, &new_settings, size); - dev->hard_start_xmit = hdlc->xmit; dev->type = ARPHRD_RAWHDLC; netif_dormant_off(dev); return 0; diff --git a/drivers/net/wan/hdlc_raw_eth.c b/drivers/net/wan/hdlc_raw_eth.c index a13fc320752..49e68f5ca5f 100644 --- a/drivers/net/wan/hdlc_raw_eth.c +++ b/drivers/net/wan/hdlc_raw_eth.c @@ -45,6 +45,7 @@ static int eth_tx(struct sk_buff *skb, struct net_device *dev) static struct hdlc_proto proto = { .type_trans = eth_type_trans, + .xmit = eth_tx, .ioctl = raw_eth_ioctl, .module = THIS_MODULE, }; @@ -56,9 +57,7 @@ static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr) const size_t size = sizeof(raw_hdlc_proto); raw_hdlc_proto new_settings; hdlc_device *hdlc = dev_to_hdlc(dev); - int result; - int (*old_ch_mtu)(struct net_device *, int); - int old_qlen; + int result, old_qlen; switch (ifr->ifr_settings.type) { case IF_GET_PROTO: @@ -99,11 +98,8 @@ static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr) if (result) return result; memcpy(hdlc->state, &new_settings, size); - dev->hard_start_xmit = eth_tx; - old_ch_mtu = dev->change_mtu; old_qlen = dev->tx_queue_len; ether_setup(dev); - dev->change_mtu = old_ch_mtu; dev->tx_queue_len = old_qlen; random_ether_addr(dev->dev_addr); netif_dormant_off(dev); diff --git a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c index cbcbf6f0414..b1dc29ed158 100644 --- a/drivers/net/wan/hdlc_x25.c +++ b/drivers/net/wan/hdlc_x25.c @@ -184,6 +184,7 @@ static struct hdlc_proto proto = { .close = x25_close, .ioctl = x25_ioctl, .netif_rx = x25_rx, + .xmit = x25_xmit, .module = THIS_MODULE, }; @@ -213,7 +214,6 @@ static int x25_ioctl(struct net_device *dev, struct ifreq *ifr) if ((result = attach_hdlc_protocol(dev, &proto, 0))) return result; - dev->hard_start_xmit = x25_xmit; dev->type = ARPHRD_X25; netif_dormant_off(dev); return 0; diff --git a/drivers/net/wan/hostess_sv11.c b/drivers/net/wan/hostess_sv11.c index af54f0cf1b3..567d4f5062d 100644 --- a/drivers/net/wan/hostess_sv11.c +++ b/drivers/net/wan/hostess_sv11.c @@ -173,6 +173,14 @@ static int hostess_attach(struct net_device *dev, unsigned short encoding, * Description block for a Comtrol Hostess SV11 card */ +static const struct net_device_ops hostess_ops = { + .ndo_open = hostess_open, + .ndo_stop = hostess_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = hostess_ioctl, +}; + static struct z8530_dev *sv11_init(int iobase, int irq) { struct z8530_dev *sv; @@ -267,9 +275,7 @@ static struct z8530_dev *sv11_init(int iobase, int irq) dev_to_hdlc(netdev)->attach = hostess_attach; dev_to_hdlc(netdev)->xmit = hostess_queue_xmit; - netdev->open = hostess_open; - netdev->stop = hostess_close; - netdev->do_ioctl = hostess_ioctl; + netdev->netdev_ops = &hostess_ops; netdev->base_addr = iobase; netdev->irq = irq; diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index 0dbd85b0162..7e8bbba2cc1 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -1230,6 +1230,14 @@ static int hss_hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) * initialization ****************************************************************************/ +static const struct net_device_ops hss_hdlc_ops = { + .ndo_open = hss_hdlc_open, + .ndo_stop = hss_hdlc_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = hss_hdlc_ioctl, +}; + static int __devinit hss_init_one(struct platform_device *pdev) { struct port *port; @@ -1254,9 +1262,7 @@ static int __devinit hss_init_one(struct platform_device *pdev) hdlc = dev_to_hdlc(dev); hdlc->attach = hss_hdlc_attach; hdlc->xmit = hss_hdlc_xmit; - dev->open = hss_hdlc_open; - dev->stop = hss_hdlc_close; - dev->do_ioctl = hss_hdlc_ioctl; + dev->netdev_ops = &hss_hdlc_ops; dev->tx_queue_len = 100; port->clock_type = CLOCK_EXT; port->clock_rate = 2048000; diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index feac3b99f8f..45b1822c962 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -806,6 +806,16 @@ static int lmc_attach(struct net_device *dev, unsigned short encoding, return -EINVAL; } +static const struct net_device_ops lmc_ops = { + .ndo_open = lmc_open, + .ndo_stop = lmc_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = lmc_ioctl, + .ndo_tx_timeout = lmc_driver_timeout, + .ndo_get_stats = lmc_get_stats, +}; + static int __devinit lmc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -849,11 +859,7 @@ static int __devinit lmc_init_one(struct pci_dev *pdev, dev->type = ARPHRD_HDLC; dev_to_hdlc(dev)->xmit = lmc_start_xmit; dev_to_hdlc(dev)->attach = lmc_attach; - dev->open = lmc_open; - dev->stop = lmc_close; - dev->get_stats = lmc_get_stats; - dev->do_ioctl = lmc_ioctl; - dev->tx_timeout = lmc_driver_timeout; + dev->netdev_ops = &lmc_ops; dev->watchdog_timeo = HZ; /* 1 second */ dev->tx_queue_len = 100; sc->lmc_device = dev; @@ -1059,9 +1065,6 @@ static int lmc_open(struct net_device *dev) if ((err = lmc_proto_open(sc)) != 0) return err; - dev->do_ioctl = lmc_ioctl; - - netif_start_queue(dev); sc->extra_stats.tx_tbusy0++; diff --git a/drivers/net/wan/lmc/lmc_proto.c b/drivers/net/wan/lmc/lmc_proto.c index 94b4c208b01..044a48175c4 100644 --- a/drivers/net/wan/lmc/lmc_proto.c +++ b/drivers/net/wan/lmc/lmc_proto.c @@ -51,30 +51,15 @@ void lmc_proto_attach(lmc_softc_t *sc) /*FOLD00*/ { lmc_trace(sc->lmc_device, "lmc_proto_attach in"); - switch(sc->if_type){ - case LMC_PPP: - { - struct net_device *dev = sc->lmc_device; - dev->do_ioctl = lmc_ioctl; - } - break; - case LMC_NET: - { + if (sc->if_type == LMC_NET) { struct net_device *dev = sc->lmc_device; /* * They set a few basics because they don't use HDLC */ dev->flags |= IFF_POINTOPOINT; - dev->hard_header_len = 0; dev->addr_len = 0; } - case LMC_RAW: /* Setup the task queue, maybe we should notify someone? */ - { - } - default: - break; - } lmc_trace(sc->lmc_device, "lmc_proto_attach out"); } diff --git a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c index 697715ae80f..83da596e205 100644 --- a/drivers/net/wan/n2.c +++ b/drivers/net/wan/n2.c @@ -324,7 +324,13 @@ static void n2_destroy_card(card_t *card) kfree(card); } - +static const struct net_device_ops n2_ops = { + .ndo_open = n2_open, + .ndo_stop = n2_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = n2_ioctl, +}; static int __init n2_run(unsigned long io, unsigned long irq, unsigned long winbase, long valid0, long valid1) @@ -460,9 +466,7 @@ static int __init n2_run(unsigned long io, unsigned long irq, dev->mem_start = winbase; dev->mem_end = winbase + USE_WINDOWSIZE - 1; dev->tx_queue_len = 50; - dev->do_ioctl = n2_ioctl; - dev->open = n2_open; - dev->stop = n2_close; + dev->netdev_ops = &n2_ops; hdlc->attach = sca_attach; hdlc->xmit = sca_xmit; port->settings.clock_type = CLOCK_EXT; diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c index f247e5d9002..60ece54bdd9 100644 --- a/drivers/net/wan/pc300too.c +++ b/drivers/net/wan/pc300too.c @@ -287,7 +287,13 @@ static void pc300_pci_remove_one(struct pci_dev *pdev) kfree(card); } - +static const struct net_device_ops pc300_ops = { + .ndo_open = pc300_open, + .ndo_stop = pc300_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = pc300_ioctl, +}; static int __devinit pc300_pci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -448,9 +454,7 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev, dev->mem_start = ramphys; dev->mem_end = ramphys + ramsize - 1; dev->tx_queue_len = 50; - dev->do_ioctl = pc300_ioctl; - dev->open = pc300_open; - dev->stop = pc300_close; + dev->netdev_ops = &pc300_ops; hdlc->attach = sca_attach; hdlc->xmit = sca_xmit; port->settings.clock_type = CLOCK_EXT; diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c index 1104d3a692f..e035d8c57e1 100644 --- a/drivers/net/wan/pci200syn.c +++ b/drivers/net/wan/pci200syn.c @@ -265,7 +265,13 @@ static void pci200_pci_remove_one(struct pci_dev *pdev) kfree(card); } - +static const struct net_device_ops pci200_ops = { + .ndo_open = pci200_open, + .ndo_stop = pci200_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = pci200_ioctl, +}; static int __devinit pci200_pci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -395,9 +401,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev, dev->mem_start = ramphys; dev->mem_end = ramphys + ramsize - 1; dev->tx_queue_len = 50; - dev->do_ioctl = pci200_ioctl; - dev->open = pci200_open; - dev->stop = pci200_close; + dev->netdev_ops = &pci200_ops; hdlc->attach = sca_attach; hdlc->xmit = sca_xmit; port->settings.clock_type = CLOCK_EXT; diff --git a/drivers/net/wan/sealevel.c b/drivers/net/wan/sealevel.c index 0941a26f6e3..23b26902745 100644 --- a/drivers/net/wan/sealevel.c +++ b/drivers/net/wan/sealevel.c @@ -169,6 +169,14 @@ static int sealevel_attach(struct net_device *dev, unsigned short encoding, return -EINVAL; } +static const struct net_device_ops sealevel_ops = { + .ndo_open = sealevel_open, + .ndo_stop = sealevel_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = sealevel_ioctl, +}; + static int slvl_setup(struct slvl_device *sv, int iobase, int irq) { struct net_device *dev = alloc_hdlcdev(sv); @@ -177,9 +185,7 @@ static int slvl_setup(struct slvl_device *sv, int iobase, int irq) dev_to_hdlc(dev)->attach = sealevel_attach; dev_to_hdlc(dev)->xmit = sealevel_queue_xmit; - dev->open = sealevel_open; - dev->stop = sealevel_close; - dev->do_ioctl = sealevel_ioctl; + dev->netdev_ops = &sealevel_ops; dev->base_addr = iobase; dev->irq = irq; diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index 4bffb67ebca..887acb0dc80 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c @@ -547,6 +547,15 @@ static void wanxl_pci_remove_one(struct pci_dev *pdev) #include "wanxlfw.inc" +static const struct net_device_ops wanxl_ops = { + .ndo_open = wanxl_open, + .ndo_stop = wanxl_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = wanxl_ioctl, + .ndo_get_stats = wanxl_get_stats, +}; + static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -777,12 +786,9 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, hdlc = dev_to_hdlc(dev); spin_lock_init(&port->lock); dev->tx_queue_len = 50; - dev->do_ioctl = wanxl_ioctl; - dev->open = wanxl_open; - dev->stop = wanxl_close; + dev->netdev_ops = &wanxl_ops; hdlc->attach = wanxl_attach; hdlc->xmit = wanxl_xmit; - dev->get_stats = wanxl_get_stats; port->card = card; port->node = i; get_status(port)->clocking = CLOCK_EXT; diff --git a/include/linux/hdlc.h b/include/linux/hdlc.h index fd47a151665..6a6e701f163 100644 --- a/include/linux/hdlc.h +++ b/include/linux/hdlc.h @@ -38,6 +38,7 @@ struct hdlc_proto { int (*ioctl)(struct net_device *dev, struct ifreq *ifr); __be16 (*type_trans)(struct sk_buff *skb, struct net_device *dev); int (*netif_rx)(struct sk_buff *skb); + int (*xmit)(struct sk_buff *skb, struct net_device *dev); struct module *module; struct hdlc_proto *next; /* next protocol in the list */ }; @@ -102,6 +103,10 @@ static __inline__ void debug_frame(const struct sk_buff *skb) int hdlc_open(struct net_device *dev); /* Must be called by hardware driver when HDLC device is being closed */ void hdlc_close(struct net_device *dev); +/* May be used by hardware driver */ +int hdlc_change_mtu(struct net_device *dev, int new_mtu); +/* Must be pointed to by hw driver's dev->netdev_ops->ndo_start_xmit */ +int hdlc_start_xmit(struct sk_buff *skb, struct net_device *dev); int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto, size_t size); -- GitLab From 4101dec9ca64d40f0d673f0a40ba46ba2c60e117 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 14 Jan 2009 13:52:18 -0800 Subject: [PATCH 0331/4982] net: constify VFTs Signed-off-by: Jan Engelhardt Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 2 +- drivers/net/hamradio/bpqether.c | 2 +- drivers/net/hamradio/scc.c | 2 +- drivers/net/hamradio/yam.c | 2 +- drivers/net/pppoe.c | 2 +- drivers/net/pppol2tp.c | 4 ++-- drivers/net/wireless/ath5k/debug.c | 2 +- drivers/net/wireless/libertas/debugfs.c | 14 +++++++------- drivers/net/wireless/strip.c | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 9fb388388fb..21bce2c0fde 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3369,7 +3369,7 @@ static int bond_info_seq_show(struct seq_file *seq, void *v) return 0; } -static struct seq_operations bond_info_seq_ops = { +static const struct seq_operations bond_info_seq_ops = { .start = bond_info_seq_start, .next = bond_info_seq_next, .stop = bond_info_seq_stop, diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index 4bf0f19ecfa..1f65d1edf13 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c @@ -443,7 +443,7 @@ static int bpq_seq_show(struct seq_file *seq, void *v) return 0; } -static struct seq_operations bpq_seqops = { +static const struct seq_operations bpq_seqops = { .start = bpq_seq_start, .next = bpq_seq_next, .stop = bpq_seq_stop, diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c index 49f9d2491d4..2acb18f0697 100644 --- a/drivers/net/hamradio/scc.c +++ b/drivers/net/hamradio/scc.c @@ -2074,7 +2074,7 @@ static int scc_net_seq_show(struct seq_file *seq, void *v) return 0; } -static struct seq_operations scc_net_seq_ops = { +static const struct seq_operations scc_net_seq_ops = { .start = scc_net_seq_start, .next = scc_net_seq_next, .stop = scc_net_seq_stop, diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c index e2b0a19203a..82a8be7613d 100644 --- a/drivers/net/hamradio/yam.c +++ b/drivers/net/hamradio/yam.c @@ -783,7 +783,7 @@ static int yam_seq_show(struct seq_file *seq, void *v) return 0; } -static struct seq_operations yam_seqops = { +static const struct seq_operations yam_seqops = { .start = yam_seq_start, .next = yam_seq_next, .stop = yam_seq_stop, diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index c22b30533a1..5efc3d172c8 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -1030,7 +1030,7 @@ static void pppoe_seq_stop(struct seq_file *seq, void *v) read_unlock_bh(&pppoe_hash_lock); } -static struct seq_operations pppoe_seq_ops = { +static const struct seq_operations pppoe_seq_ops = { .start = pppoe_seq_start, .next = pppoe_seq_next, .stop = pppoe_seq_stop, diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index f1a946785c6..635dd5fbe62 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c @@ -2517,7 +2517,7 @@ out: return 0; } -static struct seq_operations pppol2tp_seq_ops = { +static const struct seq_operations pppol2tp_seq_ops = { .start = pppol2tp_seq_start, .next = pppol2tp_seq_next, .stop = pppol2tp_seq_stop, @@ -2565,7 +2565,7 @@ static int pppol2tp_proc_release(struct inode *inode, struct file *file) return seq_release(inode, file); } -static struct file_operations pppol2tp_proc_fops = { +static const struct file_operations pppol2tp_proc_fops = { .owner = THIS_MODULE, .open = pppol2tp_proc_open, .read = seq_read, diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c index ccaeb5c219d..d281b6e3862 100644 --- a/drivers/net/wireless/ath5k/debug.c +++ b/drivers/net/wireless/ath5k/debug.c @@ -165,7 +165,7 @@ static int reg_show(struct seq_file *seq, void *p) return 0; } -static struct seq_operations register_seq_ops = { +static const struct seq_operations register_seq_ops = { .start = reg_start, .next = reg_next, .stop = reg_stop, diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index ec4efd7ff3c..50e28a0cdfe 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -629,7 +629,7 @@ static ssize_t lbs_rdrf_write(struct file *file, res = -EFAULT; goto out_unlock; } - priv->rf_offset = simple_strtoul((char *)buf, NULL, 16); + priv->rf_offset = simple_strtoul(buf, NULL, 16); res = count; out_unlock: free_page(addr); @@ -680,12 +680,12 @@ out_unlock: } struct lbs_debugfs_files { - char *name; + const char *name; int perm; struct file_operations fops; }; -static struct lbs_debugfs_files debugfs_files[] = { +static const struct lbs_debugfs_files debugfs_files[] = { { "info", 0444, FOPS(lbs_dev_info, write_file_dummy), }, { "getscantable", 0444, FOPS(lbs_getscantable, write_file_dummy), }, @@ -693,7 +693,7 @@ static struct lbs_debugfs_files debugfs_files[] = { lbs_sleepparams_write), }, }; -static struct lbs_debugfs_files debugfs_events_files[] = { +static const struct lbs_debugfs_files debugfs_events_files[] = { {"low_rssi", 0644, FOPS(lbs_lowrssi_read, lbs_lowrssi_write), }, {"low_snr", 0644, FOPS(lbs_lowsnr_read, @@ -708,7 +708,7 @@ static struct lbs_debugfs_files debugfs_events_files[] = { lbs_highsnr_write), }, }; -static struct lbs_debugfs_files debugfs_regs_files[] = { +static const struct lbs_debugfs_files debugfs_regs_files[] = { {"rdmac", 0644, FOPS(lbs_rdmac_read, lbs_rdmac_write), }, {"wrmac", 0600, FOPS(NULL, lbs_wrmac_write), }, {"rdbbp", 0644, FOPS(lbs_rdbbp_read, lbs_rdbbp_write), }, @@ -735,7 +735,7 @@ void lbs_debugfs_remove(void) void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev) { int i; - struct lbs_debugfs_files *files; + const struct lbs_debugfs_files *files; if (!lbs_dir) goto exit; @@ -938,7 +938,7 @@ static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf, return (ssize_t)cnt; } -static struct file_operations lbs_debug_fops = { +static const struct file_operations lbs_debug_fops = { .owner = THIS_MODULE, .open = open_file_generic, .write = lbs_debugfs_write, diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c index 7015f248055..d6bf8d2ef8e 100644 --- a/drivers/net/wireless/strip.c +++ b/drivers/net/wireless/strip.c @@ -1125,7 +1125,7 @@ static int strip_seq_show(struct seq_file *seq, void *v) } -static struct seq_operations strip_seq_ops = { +static const struct seq_operations strip_seq_ops = { .start = strip_seq_start, .next = strip_seq_next, .stop = strip_seq_stop, -- GitLab From eb5c8bc1442a03755ae75d99b59ccea6bbf25a34 Mon Sep 17 00:00:00 2001 From: Cesar Eduardo Barros Date: Wed, 14 Jan 2009 20:33:07 -0800 Subject: [PATCH 0332/4982] sc92031: more useful banner in kernel log The banner currently printed when loading the module is mostly useless. Replace it with a more informative one, printed after probing the device. Output format copied from 8139cp/8139too. Signed-off-by: Cesar Eduardo Barros Signed-off-by: David S. Miller --- drivers/net/sc92031.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index 8b75bef4a84..12ce341061a 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c @@ -1423,6 +1423,7 @@ static int __devinit sc92031_probe(struct pci_dev *pdev, struct net_device *dev; struct sc92031_priv *priv; u32 mac0, mac1; + unsigned long base_addr; err = pci_enable_device(pdev); if (unlikely(err < 0)) @@ -1497,6 +1498,14 @@ static int __devinit sc92031_probe(struct pci_dev *pdev, if (err < 0) goto out_register_netdev; +#if SC92031_USE_BAR == 0 + base_addr = dev->mem_start; +#elif SC92031_USE_BAR == 1 + base_addr = dev->base_addr; +#endif + printk(KERN_INFO "%s: SC92031 at 0x%lx, %pM, IRQ %d\n", dev->name, + base_addr, dev->dev_addr, dev->irq); + return 0; out_register_netdev: @@ -1603,7 +1612,6 @@ static struct pci_driver sc92031_pci_driver = { static int __init sc92031_init(void) { - printk(KERN_INFO SC92031_DESCRIPTION " " SC92031_VERSION "\n"); return pci_register_driver(&sc92031_pci_driver); } -- GitLab From 3230d2b00e6dacffabe3fd013f033606bcf08795 Mon Sep 17 00:00:00 2001 From: Cesar Eduardo Barros Date: Wed, 14 Jan 2009 20:33:27 -0800 Subject: [PATCH 0333/4982] sc92031: remove meaningless version string The version string makes no sense anymore, since this driver is only maintained within the kernel. Signed-off-by: Cesar Eduardo Barros Signed-off-by: David S. Miller --- drivers/net/sc92031.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index 12ce341061a..619d79813e7 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c @@ -37,7 +37,6 @@ #define SC92031_NAME "sc92031" #define SC92031_DESCRIPTION "Silan SC92031 PCI Fast Ethernet Adapter driver" -#define SC92031_VERSION "2.0c" /* BAR 0 is MMIO, BAR 1 is PIO */ #ifndef SC92031_USE_BAR @@ -1264,7 +1263,6 @@ static void sc92031_ethtool_get_drvinfo(struct net_device *dev, struct pci_dev *pdev = priv->pdev; strcpy(drvinfo->driver, SC92031_NAME); - strcpy(drvinfo->version, SC92031_VERSION); strcpy(drvinfo->bus_info, pci_name(pdev)); } @@ -1626,4 +1624,3 @@ module_exit(sc92031_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Cesar Eduardo Barros "); MODULE_DESCRIPTION(SC92031_DESCRIPTION); -MODULE_VERSION(SC92031_VERSION); -- GitLab From f08d7c36ccde73ea098dfda8ab63540978e9beb5 Mon Sep 17 00:00:00 2001 From: Cesar Eduardo Barros Date: Wed, 14 Jan 2009 20:33:44 -0800 Subject: [PATCH 0334/4982] sc92031: inline SC92031_DESCRIPTION SC92031_DESCRIPTION is only used in one place. Signed-off-by: Cesar Eduardo Barros Signed-off-by: David S. Miller --- drivers/net/sc92031.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index 619d79813e7..d24acdcdb15 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c @@ -36,7 +36,6 @@ #define PCI_DEVICE_ID_SILAN_8139D 0x8139 #define SC92031_NAME "sc92031" -#define SC92031_DESCRIPTION "Silan SC92031 PCI Fast Ethernet Adapter driver" /* BAR 0 is MMIO, BAR 1 is PIO */ #ifndef SC92031_USE_BAR @@ -1623,4 +1622,4 @@ module_exit(sc92031_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Cesar Eduardo Barros "); -MODULE_DESCRIPTION(SC92031_DESCRIPTION); +MODULE_DESCRIPTION("Silan SC92031 PCI Fast Ethernet Adapter driver"); -- GitLab From 5ec99fdf8e1a6ee90fce22c2fce94871ab44e8ba Mon Sep 17 00:00:00 2001 From: Cesar Eduardo Barros Date: Wed, 14 Jan 2009 20:34:04 -0800 Subject: [PATCH 0335/4982] sc92031: use device id directly instead of made-up name Instead of making up a name for the device ids, put them directly in the device id table. Also move the vendor id to pci_ids.h. Signed-off-by: Cesar Eduardo Barros Signed-off-by: David S. Miller --- drivers/net/sc92031.c | 8 ++------ include/linux/pci_ids.h | 2 ++ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index d24acdcdb15..00dfddbf2f9 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c @@ -31,10 +31,6 @@ #include -#define PCI_VENDOR_ID_SILAN 0x1904 -#define PCI_DEVICE_ID_SILAN_SC92031 0x2031 -#define PCI_DEVICE_ID_SILAN_8139D 0x8139 - #define SC92031_NAME "sc92031" /* BAR 0 is MMIO, BAR 1 is PIO */ @@ -1592,8 +1588,8 @@ out: } static struct pci_device_id sc92031_pci_device_id_table[] __devinitdata = { - { PCI_DEVICE(PCI_VENDOR_ID_SILAN, PCI_DEVICE_ID_SILAN_SC92031) }, - { PCI_DEVICE(PCI_VENDOR_ID_SILAN, PCI_DEVICE_ID_SILAN_8139D) }, + { PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x2031) }, + { PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x8139) }, { 0, } }; MODULE_DEVICE_TABLE(pci, sc92031_pci_device_id_table); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index d56ad9c21c0..302423afa13 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2209,6 +2209,8 @@ #define PCI_VENDOR_ID_TOPSPIN 0x1867 +#define PCI_VENDOR_ID_SILAN 0x1904 + #define PCI_VENDOR_ID_TDI 0x192E #define PCI_DEVICE_ID_TDI_EHCI 0x0101 -- GitLab From 627af770c63acddc2402dd19fec70df5c3ad8ab7 Mon Sep 17 00:00:00 2001 From: Cesar Eduardo Barros Date: Wed, 14 Jan 2009 20:34:24 -0800 Subject: [PATCH 0336/4982] sc92031: add a link to the datasheet Signed-off-by: Cesar Eduardo Barros Signed-off-by: David S. Miller --- drivers/net/sc92031.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index 00dfddbf2f9..c13cbf099b8 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c @@ -13,6 +13,9 @@ * Both are almost identical and seem to be based on pci-skeleton.c * * Rewritten for 2.6 by Cesar Eduardo Barros + * + * A datasheet for this chip can be found at + * http://www.silan.com.cn/english/products/pdf/SC92031AY.pdf */ /* Note about set_mac_address: I don't know how to change the hardware -- GitLab From 288379f050284087578b77e04f040b57db3db3f8 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 19 Jan 2009 16:43:59 -0800 Subject: [PATCH 0337/4982] net: Remove redundant NAPI functions Following the removal of the unused struct net_device * parameter from the NAPI functions named *netif_rx_* in commit 908a7a1, they are exactly equivalent to the corresponding *napi_* functions and are therefore redundant. Signed-off-by: Ben Hutchings Acked-by: Neil Horman Signed-off-by: David S. Miller --- drivers/infiniband/hw/nes/nes_hw.c | 2 +- drivers/infiniband/hw/nes/nes_nic.c | 2 +- drivers/infiniband/ulp/ipoib/ipoib_ib.c | 6 +-- drivers/net/8139cp.c | 6 +-- drivers/net/8139too.c | 6 +-- drivers/net/amd8111e.c | 6 +-- drivers/net/arm/ep93xx_eth.c | 8 ++-- drivers/net/arm/ixp4xx_eth.c | 12 +++--- drivers/net/atl1e/atl1e_main.c | 6 +-- drivers/net/b44.c | 6 +-- drivers/net/bnx2.c | 12 +++--- drivers/net/bnx2x_main.c | 6 +-- drivers/net/cassini.c | 8 ++-- drivers/net/chelsio/sge.c | 4 +- drivers/net/cpmac.c | 10 ++--- drivers/net/e100.c | 6 +-- drivers/net/e1000/e1000_main.c | 10 ++--- drivers/net/e1000e/netdev.c | 14 +++---- drivers/net/ehea/ehea_main.c | 8 ++-- drivers/net/enic/enic_main.c | 12 +++--- drivers/net/epic100.c | 6 +-- drivers/net/forcedeth.c | 10 ++--- drivers/net/fs_enet/fs_enet-main.c | 4 +- drivers/net/gianfar.c | 6 +-- drivers/net/ibmveth.c | 8 ++-- drivers/net/igb/igb_main.c | 12 +++--- drivers/net/ixgb/ixgb_main.c | 6 +-- drivers/net/ixgbe/ixgbe_main.c | 12 +++--- drivers/net/ixp2000/ixpdev.c | 4 +- drivers/net/jme.h | 6 +-- drivers/net/korina.c | 4 +- drivers/net/macb.c | 10 ++--- drivers/net/mlx4/en_rx.c | 4 +- drivers/net/myri10ge/myri10ge.c | 6 +-- drivers/net/natsemi.c | 6 +-- drivers/net/netxen/netxen_nic_main.c | 2 +- drivers/net/niu.c | 6 +-- drivers/net/pasemi_mac.c | 6 +-- drivers/net/pcnet32.c | 6 +-- drivers/net/qla3xxx.c | 6 +-- drivers/net/qlge/qlge_main.c | 6 +-- drivers/net/r6040.c | 4 +- drivers/net/r8169.c | 6 +-- drivers/net/s2io.c | 8 ++-- drivers/net/sb1250-mac.c | 6 +-- drivers/net/sfc/efx.c | 4 +- drivers/net/sfc/efx.h | 2 +- drivers/net/skge.c | 6 +-- drivers/net/smsc911x.c | 8 ++-- drivers/net/smsc9420.c | 4 +- drivers/net/spider_net.c | 12 +++--- drivers/net/starfire.c | 6 +-- drivers/net/sungem.c | 6 +-- drivers/net/tc35815.c | 6 +-- drivers/net/tehuti.c | 6 +-- drivers/net/tg3.c | 14 +++---- drivers/net/tsi108_eth.c | 8 ++-- drivers/net/tulip/interrupt.c | 10 ++--- drivers/net/typhoon.c | 6 +-- drivers/net/ucc_geth.c | 6 +-- drivers/net/via-rhine.c | 4 +- drivers/net/virtio_net.c | 12 +++--- drivers/net/wan/hd64572.c | 4 +- drivers/net/wan/ixp4xx_hss.c | 12 +++--- drivers/net/xen-netfront.c | 8 ++-- include/linux/netdevice.h | 50 ------------------------- 66 files changed, 227 insertions(+), 277 deletions(-) diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 5d139db1b77..53df9de2342 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c @@ -2541,7 +2541,7 @@ static void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic { struct nes_vnic *nesvnic = container_of(cq, struct nes_vnic, nic_cq); - netif_rx_schedule(&nesvnic->napi); + napi_schedule(&nesvnic->napi); } diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index 57a47cf7e51..f5484ad1279 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -111,7 +111,7 @@ static int nes_netdev_poll(struct napi_struct *napi, int budget) nes_nic_ce_handler(nesdev, nescq); if (nescq->cqes_pending == 0) { - netif_rx_complete(napi); + napi_complete(napi); /* clear out completed cqes and arm */ nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT | nescq->cq_number | (nescq->cqe_allocs_pending << 16)); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index a1925810be3..da608273983 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -446,11 +446,11 @@ poll_more: if (dev->features & NETIF_F_LRO) lro_flush_all(&priv->lro.lro_mgr); - netif_rx_complete(napi); + napi_complete(napi); if (unlikely(ib_req_notify_cq(priv->recv_cq, IB_CQ_NEXT_COMP | IB_CQ_REPORT_MISSED_EVENTS)) && - netif_rx_reschedule(napi)) + napi_reschedule(napi)) goto poll_more; } @@ -462,7 +462,7 @@ void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr) struct net_device *dev = dev_ptr; struct ipoib_dev_priv *priv = netdev_priv(dev); - netif_rx_schedule(&priv->napi); + napi_schedule(&priv->napi); } static void drain_tx_cq(struct net_device *dev) diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 4e19ae3ce6b..35517b06ec3 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -604,7 +604,7 @@ rx_next: spin_lock_irqsave(&cp->lock, flags); cpw16_f(IntrMask, cp_intr_mask); - __netif_rx_complete(napi); + __napi_complete(napi); spin_unlock_irqrestore(&cp->lock, flags); } @@ -641,9 +641,9 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance) } if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr)) - if (netif_rx_schedule_prep(&cp->napi)) { + if (napi_schedule_prep(&cp->napi)) { cpw16_f(IntrMask, cp_norx_intr_mask); - __netif_rx_schedule(&cp->napi); + __napi_schedule(&cp->napi); } if (status & (TxOK | TxErr | TxEmpty | SWInt)) diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index a5b24202d56..5341da604e8 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -2128,7 +2128,7 @@ static int rtl8139_poll(struct napi_struct *napi, int budget) */ spin_lock_irqsave(&tp->lock, flags); RTL_W16_F(IntrMask, rtl8139_intr_mask); - __netif_rx_complete(napi); + __napi_complete(napi); spin_unlock_irqrestore(&tp->lock, flags); } spin_unlock(&tp->rx_lock); @@ -2178,9 +2178,9 @@ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) /* Receive packets are processed by poll routine. If not running start it now. */ if (status & RxAckBits){ - if (netif_rx_schedule_prep(&tp->napi)) { + if (napi_schedule_prep(&tp->napi)) { RTL_W16_F (IntrMask, rtl8139_norx_intr_mask); - __netif_rx_schedule(&tp->napi); + __napi_schedule(&tp->napi); } } diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index 7709992bb6b..cb9c95d3ed0 100644 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -831,7 +831,7 @@ static int amd8111e_rx_poll(struct napi_struct *napi, int budget) if (rx_pkt_limit > 0) { /* Receive descriptor is empty now */ spin_lock_irqsave(&lp->lock, flags); - __netif_rx_complete(napi); + __napi_complete(napi); writel(VAL0|RINTEN0, mmio + INTEN0); writel(VAL2 | RDMD0, mmio + CMD0); spin_unlock_irqrestore(&lp->lock, flags); @@ -1170,11 +1170,11 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id) /* Check if Receive Interrupt has occurred. */ if (intr0 & RINT0) { - if (netif_rx_schedule_prep(&lp->napi)) { + if (napi_schedule_prep(&lp->napi)) { /* Disable receive interupts */ writel(RINTEN0, mmio + INTEN0); /* Schedule a polling routine */ - __netif_rx_schedule(&lp->napi); + __napi_schedule(&lp->napi); } else if (intren0 & RINTEN0) { printk("************Driver bug! \ interrupt while in poll\n"); diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index 3ec20cc18b0..cc7708775da 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -298,7 +298,7 @@ poll_some_more: int more = 0; spin_lock_irq(&ep->rx_lock); - __netif_rx_complete(napi); + __napi_complete(napi); wrl(ep, REG_INTEN, REG_INTEN_TX | REG_INTEN_RX); if (ep93xx_have_more_rx(ep)) { wrl(ep, REG_INTEN, REG_INTEN_TX); @@ -307,7 +307,7 @@ poll_some_more: } spin_unlock_irq(&ep->rx_lock); - if (more && netif_rx_reschedule(napi)) + if (more && napi_reschedule(napi)) goto poll_some_more; } @@ -415,9 +415,9 @@ static irqreturn_t ep93xx_irq(int irq, void *dev_id) if (status & REG_INTSTS_RX) { spin_lock(&ep->rx_lock); - if (likely(netif_rx_schedule_prep(&ep->napi))) { + if (likely(napi_schedule_prep(&ep->napi))) { wrl(ep, REG_INTEN, REG_INTEN_TX); - __netif_rx_schedule(&ep->napi); + __napi_schedule(&ep->napi); } spin_unlock(&ep->rx_lock); } diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index 5fce1d5c1a1..5fe17d5eaa5 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -473,7 +473,7 @@ static void eth_rx_irq(void *pdev) printk(KERN_DEBUG "%s: eth_rx_irq\n", dev->name); #endif qmgr_disable_irq(port->plat->rxq); - netif_rx_schedule(&port->napi); + napi_schedule(&port->napi); } static int eth_poll(struct napi_struct *napi, int budget) @@ -498,16 +498,16 @@ static int eth_poll(struct napi_struct *napi, int budget) if ((n = queue_get_desc(rxq, port, 0)) < 0) { #if DEBUG_RX - printk(KERN_DEBUG "%s: eth_poll netif_rx_complete\n", + printk(KERN_DEBUG "%s: eth_poll napi_complete\n", dev->name); #endif - netif_rx_complete(napi); + napi_complete(napi); qmgr_enable_irq(rxq); if (!qmgr_stat_empty(rxq) && - netif_rx_reschedule(napi)) { + napi_reschedule(napi)) { #if DEBUG_RX printk(KERN_DEBUG "%s: eth_poll" - " netif_rx_reschedule successed\n", + " napi_reschedule successed\n", dev->name); #endif qmgr_disable_irq(rxq); @@ -1036,7 +1036,7 @@ static int eth_open(struct net_device *dev) } ports_open++; /* we may already have RX data, enables IRQ */ - netif_rx_schedule(&port->napi); + napi_schedule(&port->napi); return 0; } diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c index bb9094d4cbc..c758884728a 100644 --- a/drivers/net/atl1e/atl1e_main.c +++ b/drivers/net/atl1e/atl1e_main.c @@ -1326,9 +1326,9 @@ static irqreturn_t atl1e_intr(int irq, void *data) AT_WRITE_REG(hw, REG_IMR, IMR_NORMAL_MASK & ~ISR_RX_EVENT); AT_WRITE_FLUSH(hw); - if (likely(netif_rx_schedule_prep( + if (likely(napi_schedule_prep( &adapter->napi))) - __netif_rx_schedule(&adapter->napi); + __napi_schedule(&adapter->napi); } } while (--max_ints > 0); /* re-enable Interrupt*/ @@ -1514,7 +1514,7 @@ static int atl1e_clean(struct napi_struct *napi, int budget) /* If no Tx and not enough Rx work done, exit the polling mode */ if (work_done < budget) { quit_polling: - netif_rx_complete(napi); + napi_complete(napi); imr_data = AT_READ_REG(&adapter->hw, REG_IMR); AT_WRITE_REG(&adapter->hw, REG_IMR, imr_data | ISR_RX_EVENT); /* test debug */ diff --git a/drivers/net/b44.c b/drivers/net/b44.c index c38512ebcea..92aaaa1ee9f 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -874,7 +874,7 @@ static int b44_poll(struct napi_struct *napi, int budget) } if (work_done < budget) { - netif_rx_complete(napi); + napi_complete(napi); b44_enable_ints(bp); } @@ -906,13 +906,13 @@ static irqreturn_t b44_interrupt(int irq, void *dev_id) goto irq_ack; } - if (netif_rx_schedule_prep(&bp->napi)) { + if (napi_schedule_prep(&bp->napi)) { /* NOTE: These writes are posted by the readback of * the ISTAT register below. */ bp->istat = istat; __b44_disable_ints(bp); - __netif_rx_schedule(&bp->napi); + __napi_schedule(&bp->napi); } else { printk(KERN_ERR PFX "%s: Error, poll already scheduled\n", dev->name); diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index d4a3dac21dc..e817802b248 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -3053,7 +3053,7 @@ bnx2_msi(int irq, void *dev_instance) if (unlikely(atomic_read(&bp->intr_sem) != 0)) return IRQ_HANDLED; - netif_rx_schedule(&bnapi->napi); + napi_schedule(&bnapi->napi); return IRQ_HANDLED; } @@ -3070,7 +3070,7 @@ bnx2_msi_1shot(int irq, void *dev_instance) if (unlikely(atomic_read(&bp->intr_sem) != 0)) return IRQ_HANDLED; - netif_rx_schedule(&bnapi->napi); + napi_schedule(&bnapi->napi); return IRQ_HANDLED; } @@ -3106,9 +3106,9 @@ bnx2_interrupt(int irq, void *dev_instance) if (unlikely(atomic_read(&bp->intr_sem) != 0)) return IRQ_HANDLED; - if (netif_rx_schedule_prep(&bnapi->napi)) { + if (napi_schedule_prep(&bnapi->napi)) { bnapi->last_status_idx = sblk->status_idx; - __netif_rx_schedule(&bnapi->napi); + __napi_schedule(&bnapi->napi); } return IRQ_HANDLED; @@ -3218,7 +3218,7 @@ static int bnx2_poll_msix(struct napi_struct *napi, int budget) rmb(); if (likely(!bnx2_has_fast_work(bnapi))) { - netif_rx_complete(napi); + napi_complete(napi); REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num | BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | bnapi->last_status_idx); @@ -3251,7 +3251,7 @@ static int bnx2_poll(struct napi_struct *napi, int budget) rmb(); if (likely(!bnx2_has_work(bnapi))) { - netif_rx_complete(napi); + napi_complete(napi); if (likely(bp->flags & BNX2_FLAG_USING_MSI_OR_MSIX)) { REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 074374ff93f..21764bfc048 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -1647,7 +1647,7 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie) prefetch(&fp->status_blk->c_status_block.status_block_index); prefetch(&fp->status_blk->u_status_block.status_block_index); - netif_rx_schedule(&bnx2x_fp(bp, index, napi)); + napi_schedule(&bnx2x_fp(bp, index, napi)); return IRQ_HANDLED; } @@ -1686,7 +1686,7 @@ static irqreturn_t bnx2x_interrupt(int irq, void *dev_instance) prefetch(&fp->status_blk->c_status_block.status_block_index); prefetch(&fp->status_blk->u_status_block.status_block_index); - netif_rx_schedule(&bnx2x_fp(bp, 0, napi)); + napi_schedule(&bnx2x_fp(bp, 0, napi)); status &= ~mask; } @@ -9339,7 +9339,7 @@ static int bnx2x_poll(struct napi_struct *napi, int budget) #ifdef BNX2X_STOP_ON_ERROR poll_panic: #endif - netif_rx_complete(napi); + napi_complete(napi); bnx2x_ack_sb(bp, FP_SB_ID(fp), USTORM_ID, le16_to_cpu(fp->fp_u_idx), IGU_INT_NOP, 1); diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 840b3d1a22f..bb46be27533 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -2506,7 +2506,7 @@ static irqreturn_t cas_interruptN(int irq, void *dev_id) if (status & INTR_RX_DONE_ALT) { /* handle rx separately */ #ifdef USE_NAPI cas_mask_intr(cp); - netif_rx_schedule(&cp->napi); + napi_schedule(&cp->napi); #else cas_rx_ringN(cp, ring, 0); #endif @@ -2557,7 +2557,7 @@ static irqreturn_t cas_interrupt1(int irq, void *dev_id) if (status & INTR_RX_DONE_ALT) { /* handle rx separately */ #ifdef USE_NAPI cas_mask_intr(cp); - netif_rx_schedule(&cp->napi); + napi_schedule(&cp->napi); #else cas_rx_ringN(cp, 1, 0); #endif @@ -2613,7 +2613,7 @@ static irqreturn_t cas_interrupt(int irq, void *dev_id) if (status & INTR_RX_DONE) { #ifdef USE_NAPI cas_mask_intr(cp); - netif_rx_schedule(&cp->napi); + napi_schedule(&cp->napi); #else cas_rx_ringN(cp, 0, 0); #endif @@ -2691,7 +2691,7 @@ rx_comp: #endif spin_unlock_irqrestore(&cp->lock, flags); if (enable_intr) { - netif_rx_complete(napi); + napi_complete(napi); cas_unmask_intr(cp); } return credits; diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index d984b799576..840da83fb3c 100644 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c @@ -1612,7 +1612,7 @@ int t1_poll(struct napi_struct *napi, int budget) int work_done = process_responses(adapter, budget); if (likely(work_done < budget)) { - netif_rx_complete(napi); + napi_complete(napi); writel(adapter->sge->respQ.cidx, adapter->regs + A_SG_SLEEPING); } @@ -1630,7 +1630,7 @@ irqreturn_t t1_interrupt(int irq, void *data) if (napi_schedule_prep(&adapter->napi)) { if (process_pure_responses(adapter)) - __netif_rx_schedule(&adapter->napi); + __napi_schedule(&adapter->napi); else { /* no data, no NAPI needed */ writel(sge->respQ.cidx, adapter->regs + A_SG_SLEEPING); diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index f66548751c3..4dad04e91f6 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -428,7 +428,7 @@ static int cpmac_poll(struct napi_struct *napi, int budget) printk(KERN_WARNING "%s: rx: polling, but no queue\n", priv->dev->name); spin_unlock(&priv->rx_lock); - netif_rx_complete(napi); + napi_complete(napi); return 0; } @@ -514,7 +514,7 @@ static int cpmac_poll(struct napi_struct *napi, int budget) if (processed == 0) { /* we ran out of packets to read, * revert to interrupt-driven mode */ - netif_rx_complete(napi); + napi_complete(napi); cpmac_write(priv->regs, CPMAC_RX_INT_ENABLE, 1); return 0; } @@ -536,7 +536,7 @@ fatal_error: } spin_unlock(&priv->rx_lock); - netif_rx_complete(napi); + napi_complete(napi); netif_tx_stop_all_queues(priv->dev); napi_disable(&priv->napi); @@ -802,9 +802,9 @@ static irqreturn_t cpmac_irq(int irq, void *dev_id) if (status & MAC_INT_RX) { queue = (status >> 8) & 7; - if (netif_rx_schedule_prep(&priv->napi)) { + if (napi_schedule_prep(&priv->napi)) { cpmac_write(priv->regs, CPMAC_RX_INT_CLEAR, 1 << queue); - __netif_rx_schedule(&priv->napi); + __napi_schedule(&priv->napi); } } diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 86bb876fb12..861d2eeaa43 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1944,9 +1944,9 @@ static irqreturn_t e100_intr(int irq, void *dev_id) if (stat_ack & stat_ack_rnr) nic->ru_running = RU_SUSPENDED; - if (likely(netif_rx_schedule_prep(&nic->napi))) { + if (likely(napi_schedule_prep(&nic->napi))) { e100_disable_irq(nic); - __netif_rx_schedule(&nic->napi); + __napi_schedule(&nic->napi); } return IRQ_HANDLED; @@ -1962,7 +1962,7 @@ static int e100_poll(struct napi_struct *napi, int budget) /* If budget not fully consumed, exit the polling mode */ if (work_done < budget) { - netif_rx_complete(napi); + napi_complete(napi); e100_enable_irq(nic); } diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 26474c92193..ffe466e0afb 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3687,12 +3687,12 @@ static irqreturn_t e1000_intr_msi(int irq, void *data) mod_timer(&adapter->watchdog_timer, jiffies + 1); } - if (likely(netif_rx_schedule_prep(&adapter->napi))) { + if (likely(napi_schedule_prep(&adapter->napi))) { adapter->total_tx_bytes = 0; adapter->total_tx_packets = 0; adapter->total_rx_bytes = 0; adapter->total_rx_packets = 0; - __netif_rx_schedule(&adapter->napi); + __napi_schedule(&adapter->napi); } else e1000_irq_enable(adapter); @@ -3747,12 +3747,12 @@ static irqreturn_t e1000_intr(int irq, void *data) ew32(IMC, ~0); E1000_WRITE_FLUSH(); } - if (likely(netif_rx_schedule_prep(&adapter->napi))) { + if (likely(napi_schedule_prep(&adapter->napi))) { adapter->total_tx_bytes = 0; adapter->total_tx_packets = 0; adapter->total_rx_bytes = 0; adapter->total_rx_packets = 0; - __netif_rx_schedule(&adapter->napi); + __napi_schedule(&adapter->napi); } else /* this really should not happen! if it does it is basically a * bug, but not a hard error, so enable ints and continue */ @@ -3793,7 +3793,7 @@ static int e1000_clean(struct napi_struct *napi, int budget) if (work_done < budget) { if (likely(adapter->itr_setting & 3)) e1000_set_itr(adapter); - netif_rx_complete(napi); + napi_complete(napi); e1000_irq_enable(adapter); } diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 91817d0afca..ff5b66adfc4 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -1179,12 +1179,12 @@ static irqreturn_t e1000_intr_msi(int irq, void *data) mod_timer(&adapter->watchdog_timer, jiffies + 1); } - if (netif_rx_schedule_prep(&adapter->napi)) { + if (napi_schedule_prep(&adapter->napi)) { adapter->total_tx_bytes = 0; adapter->total_tx_packets = 0; adapter->total_rx_bytes = 0; adapter->total_rx_packets = 0; - __netif_rx_schedule(&adapter->napi); + __napi_schedule(&adapter->napi); } return IRQ_HANDLED; @@ -1246,12 +1246,12 @@ static irqreturn_t e1000_intr(int irq, void *data) mod_timer(&adapter->watchdog_timer, jiffies + 1); } - if (netif_rx_schedule_prep(&adapter->napi)) { + if (napi_schedule_prep(&adapter->napi)) { adapter->total_tx_bytes = 0; adapter->total_tx_packets = 0; adapter->total_rx_bytes = 0; adapter->total_rx_packets = 0; - __netif_rx_schedule(&adapter->napi); + __napi_schedule(&adapter->napi); } return IRQ_HANDLED; @@ -1320,10 +1320,10 @@ static irqreturn_t e1000_intr_msix_rx(int irq, void *data) adapter->rx_ring->set_itr = 0; } - if (netif_rx_schedule_prep(&adapter->napi)) { + if (napi_schedule_prep(&adapter->napi)) { adapter->total_rx_bytes = 0; adapter->total_rx_packets = 0; - __netif_rx_schedule(&adapter->napi); + __napi_schedule(&adapter->napi); } return IRQ_HANDLED; } @@ -2028,7 +2028,7 @@ clean_rx: if (work_done < budget) { if (adapter->itr_setting & 3) e1000_set_itr(adapter); - netif_rx_complete(napi); + napi_complete(napi); if (adapter->msix_entries) ew32(IMS, adapter->rx_ring->ims_val); else diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index dfe92264e82..8dc2047da5c 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -830,7 +830,7 @@ static int ehea_poll(struct napi_struct *napi, int budget) while ((rx != budget) || force_irq) { pr->poll_counter = 0; force_irq = 0; - netif_rx_complete(napi); + napi_complete(napi); ehea_reset_cq_ep(pr->recv_cq); ehea_reset_cq_ep(pr->send_cq); ehea_reset_cq_n1(pr->recv_cq); @@ -841,7 +841,7 @@ static int ehea_poll(struct napi_struct *napi, int budget) if (!cqe && !cqe_skb) return rx; - if (!netif_rx_reschedule(napi)) + if (!napi_reschedule(napi)) return rx; cqe_skb = ehea_proc_cqes(pr, EHEA_POLL_MAX_CQES); @@ -859,7 +859,7 @@ static void ehea_netpoll(struct net_device *dev) int i; for (i = 0; i < port->num_def_qps; i++) - netif_rx_schedule(&port->port_res[i].napi); + napi_schedule(&port->port_res[i].napi); } #endif @@ -867,7 +867,7 @@ static irqreturn_t ehea_recv_irq_handler(int irq, void *param) { struct ehea_port_res *pr = param; - netif_rx_schedule(&pr->napi); + napi_schedule(&pr->napi); return IRQ_HANDLED; } diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 7d60551d538..4617956821c 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -411,8 +411,8 @@ static irqreturn_t enic_isr_legacy(int irq, void *data) } if (ENIC_TEST_INTR(pba, ENIC_INTX_WQ_RQ)) { - if (netif_rx_schedule_prep(&enic->napi)) - __netif_rx_schedule(&enic->napi); + if (napi_schedule_prep(&enic->napi)) + __napi_schedule(&enic->napi); } else { vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]); } @@ -440,7 +440,7 @@ static irqreturn_t enic_isr_msi(int irq, void *data) * writes). */ - netif_rx_schedule(&enic->napi); + napi_schedule(&enic->napi); return IRQ_HANDLED; } @@ -450,7 +450,7 @@ static irqreturn_t enic_isr_msix_rq(int irq, void *data) struct enic *enic = data; /* schedule NAPI polling for RQ cleanup */ - netif_rx_schedule(&enic->napi); + napi_schedule(&enic->napi); return IRQ_HANDLED; } @@ -1068,7 +1068,7 @@ static int enic_poll(struct napi_struct *napi, int budget) if (netdev->features & NETIF_F_LRO) lro_flush_all(&enic->lro_mgr); - netif_rx_complete(napi); + napi_complete(napi); vnic_intr_unmask(&enic->intr[ENIC_MSIX_RQ]); } @@ -1112,7 +1112,7 @@ static int enic_poll_msix(struct napi_struct *napi, int budget) if (netdev->features & NETIF_F_LRO) lro_flush_all(&enic->lro_mgr); - netif_rx_complete(napi); + napi_complete(napi); vnic_intr_unmask(&enic->intr[ENIC_MSIX_RQ]); } diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index a539bc3163c..b60e27dfcfa 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -1114,9 +1114,9 @@ static irqreturn_t epic_interrupt(int irq, void *dev_instance) if ((status & EpicNapiEvent) && !ep->reschedule_in_poll) { spin_lock(&ep->napi_lock); - if (netif_rx_schedule_prep(&ep->napi)) { + if (napi_schedule_prep(&ep->napi)) { epic_napi_irq_off(dev, ep); - __netif_rx_schedule(&ep->napi); + __napi_schedule(&ep->napi); } else ep->reschedule_in_poll++; spin_unlock(&ep->napi_lock); @@ -1293,7 +1293,7 @@ rx_action: more = ep->reschedule_in_poll; if (!more) { - __netif_rx_complete(napi); + __napi_complete(napi); outl(EpicNapiEvent, ioaddr + INTSTAT); epic_napi_irq_on(dev, ep); } else diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 5b910cf6374..875509d7d86 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -1760,7 +1760,7 @@ static void nv_do_rx_refill(unsigned long data) struct fe_priv *np = netdev_priv(dev); /* Just reschedule NAPI rx processing */ - netif_rx_schedule(&np->napi); + napi_schedule(&np->napi); } #else static void nv_do_rx_refill(unsigned long data) @@ -3406,7 +3406,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data) #ifdef CONFIG_FORCEDETH_NAPI if (events & NVREG_IRQ_RX_ALL) { spin_lock(&np->lock); - netif_rx_schedule(&np->napi); + napi_schedule(&np->napi); /* Disable furthur receive irq's */ np->irqmask &= ~NVREG_IRQ_RX_ALL; @@ -3523,7 +3523,7 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) #ifdef CONFIG_FORCEDETH_NAPI if (events & NVREG_IRQ_RX_ALL) { spin_lock(&np->lock); - netif_rx_schedule(&np->napi); + napi_schedule(&np->napi); /* Disable furthur receive irq's */ np->irqmask &= ~NVREG_IRQ_RX_ALL; @@ -3680,7 +3680,7 @@ static int nv_napi_poll(struct napi_struct *napi, int budget) /* re-enable receive interrupts */ spin_lock_irqsave(&np->lock, flags); - __netif_rx_complete(napi); + __napi_complete(napi); np->irqmask |= NVREG_IRQ_RX_ALL; if (np->msi_flags & NV_MSI_X_ENABLED) @@ -3706,7 +3706,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data) writel(NVREG_IRQ_RX_ALL, base + NvRegMSIXIrqStatus); if (events) { - netif_rx_schedule(&np->napi); + napi_schedule(&np->napi); /* disable receive interrupts on the nic */ writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); pci_push(base); diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index ce900e54d8d..b037ce9857b 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -209,7 +209,7 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget) if (received < budget) { /* done */ - netif_rx_complete(napi); + napi_complete(napi); (*fep->ops->napi_enable_rx)(dev); } return received; @@ -478,7 +478,7 @@ fs_enet_interrupt(int irq, void *dev_id) /* NOTE: it is possible for FCCs in NAPI mode */ /* to submit a spurious interrupt while in poll */ if (napi_ok) - __netif_rx_schedule(&fep->napi); + __napi_schedule(&fep->napi); } } diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index ea530673236..2e76699f810 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -1627,9 +1627,9 @@ static void gfar_schedule_cleanup(struct net_device *dev) spin_lock_irqsave(&priv->txlock, flags); spin_lock(&priv->rxlock); - if (netif_rx_schedule_prep(&priv->napi)) { + if (napi_schedule_prep(&priv->napi)) { gfar_write(&priv->regs->imask, IMASK_RTX_DISABLED); - __netif_rx_schedule(&priv->napi); + __napi_schedule(&priv->napi); } spin_unlock(&priv->rxlock); @@ -1886,7 +1886,7 @@ static int gfar_poll(struct napi_struct *napi, int budget) return budget; if (rx_cleaned < budget) { - netif_rx_complete(napi); + napi_complete(napi); /* Clear the halt bit in RSTAT */ gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT); diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index dfa6348ac1d..5c6315df86b 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -1028,10 +1028,10 @@ static int ibmveth_poll(struct napi_struct *napi, int budget) ibmveth_assert(lpar_rc == H_SUCCESS); - netif_rx_complete(napi); + napi_complete(napi); if (ibmveth_rxq_pending_buffer(adapter) && - netif_rx_reschedule(napi)) { + napi_reschedule(napi)) { lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE); goto restart_poll; @@ -1047,11 +1047,11 @@ static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance) struct ibmveth_adapter *adapter = netdev_priv(netdev); unsigned long lpar_rc; - if (netif_rx_schedule_prep(&adapter->napi)) { + if (napi_schedule_prep(&adapter->napi)) { lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE); ibmveth_assert(lpar_rc == H_SUCCESS); - __netif_rx_schedule(&adapter->napi); + __napi_schedule(&adapter->napi); } return IRQ_HANDLED; } diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index b82b0fb2056..3806bb9d8bf 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3386,8 +3386,8 @@ static irqreturn_t igb_msix_rx(int irq, void *data) igb_write_itr(rx_ring); - if (netif_rx_schedule_prep(&rx_ring->napi)) - __netif_rx_schedule(&rx_ring->napi); + if (napi_schedule_prep(&rx_ring->napi)) + __napi_schedule(&rx_ring->napi); #ifdef CONFIG_IGB_DCA if (rx_ring->adapter->flags & IGB_FLAG_DCA_ENABLED) @@ -3539,7 +3539,7 @@ static irqreturn_t igb_intr_msi(int irq, void *data) mod_timer(&adapter->watchdog_timer, jiffies + 1); } - netif_rx_schedule(&adapter->rx_ring[0].napi); + napi_schedule(&adapter->rx_ring[0].napi); return IRQ_HANDLED; } @@ -3577,7 +3577,7 @@ static irqreturn_t igb_intr(int irq, void *data) mod_timer(&adapter->watchdog_timer, jiffies + 1); } - netif_rx_schedule(&adapter->rx_ring[0].napi); + napi_schedule(&adapter->rx_ring[0].napi); return IRQ_HANDLED; } @@ -3612,7 +3612,7 @@ static int igb_poll(struct napi_struct *napi, int budget) !netif_running(netdev)) { if (adapter->itr_setting & 3) igb_set_itr(adapter); - netif_rx_complete(napi); + napi_complete(napi); if (!test_bit(__IGB_DOWN, &adapter->state)) igb_irq_enable(adapter); return 0; @@ -3638,7 +3638,7 @@ static int igb_clean_rx_ring_msix(struct napi_struct *napi, int budget) /* If not enough Rx work done, exit the polling mode */ if ((work_done == 0) || !netif_running(netdev)) { - netif_rx_complete(napi); + napi_complete(napi); if (adapter->itr_setting & 3) { if (adapter->num_rx_queues == 1) diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index eee28d39568..e2ef16b2970 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -1721,14 +1721,14 @@ ixgb_intr(int irq, void *data) if (!test_bit(__IXGB_DOWN, &adapter->flags)) mod_timer(&adapter->watchdog_timer, jiffies); - if (netif_rx_schedule_prep(&adapter->napi)) { + if (napi_schedule_prep(&adapter->napi)) { /* Disable interrupts and register for poll. The flush of the posted write is intentionally left out. */ IXGB_WRITE_REG(&adapter->hw, IMC, ~0); - __netif_rx_schedule(&adapter->napi); + __napi_schedule(&adapter->napi); } return IRQ_HANDLED; } @@ -1749,7 +1749,7 @@ ixgb_clean(struct napi_struct *napi, int budget) /* If budget not fully consumed, exit the polling mode */ if (work_done < budget) { - netif_rx_complete(napi); + napi_complete(napi); if (!test_bit(__IXGB_DOWN, &adapter->flags)) ixgb_irq_enable(adapter); } diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index d2f4d5f508b..7489094bbbc 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1015,7 +1015,7 @@ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data) rx_ring = &(adapter->rx_ring[r_idx]); /* disable interrupts on this vector only */ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rx_ring->v_idx); - netif_rx_schedule(&q_vector->napi); + napi_schedule(&q_vector->napi); return IRQ_HANDLED; } @@ -1056,7 +1056,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget) /* If all Rx work done, exit the polling mode */ if (work_done < budget) { - netif_rx_complete(napi); + napi_complete(napi); if (adapter->itr_setting & 3) ixgbe_set_itr_msix(q_vector); if (!test_bit(__IXGBE_DOWN, &adapter->state)) @@ -1105,7 +1105,7 @@ static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget) rx_ring = &(adapter->rx_ring[r_idx]); /* If all Rx work done, exit the polling mode */ if (work_done < budget) { - netif_rx_complete(napi); + napi_complete(napi); if (adapter->itr_setting & 3) ixgbe_set_itr_msix(q_vector); if (!test_bit(__IXGBE_DOWN, &adapter->state)) @@ -1381,13 +1381,13 @@ static irqreturn_t ixgbe_intr(int irq, void *data) ixgbe_check_fan_failure(adapter, eicr); - if (netif_rx_schedule_prep(&adapter->q_vector[0].napi)) { + if (napi_schedule_prep(&adapter->q_vector[0].napi)) { adapter->tx_ring[0].total_packets = 0; adapter->tx_ring[0].total_bytes = 0; adapter->rx_ring[0].total_packets = 0; adapter->rx_ring[0].total_bytes = 0; /* would disable interrupts here but EIAM disabled it */ - __netif_rx_schedule(&adapter->q_vector[0].napi); + __napi_schedule(&adapter->q_vector[0].napi); } return IRQ_HANDLED; @@ -2317,7 +2317,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget) /* If budget not fully consumed, exit the polling mode */ if (work_done < budget) { - netif_rx_complete(napi); + napi_complete(napi); if (adapter->itr_setting & 3) ixgbe_set_itr(adapter); if (!test_bit(__IXGBE_DOWN, &adapter->state)) diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c index 01474572056..d3bf2f017cc 100644 --- a/drivers/net/ixp2000/ixpdev.c +++ b/drivers/net/ixp2000/ixpdev.c @@ -141,7 +141,7 @@ static int ixpdev_poll(struct napi_struct *napi, int budget) break; } while (ixp2000_reg_read(IXP2000_IRQ_THD_RAW_STATUS_A_0) & 0x00ff); - netif_rx_complete(napi); + napi_complete(napi); ixp2000_reg_write(IXP2000_IRQ_THD_ENABLE_SET_A_0, 0x00ff); return rx; @@ -204,7 +204,7 @@ static irqreturn_t ixpdev_interrupt(int irq, void *dev_id) ixp2000_reg_wrb(IXP2000_IRQ_THD_ENABLE_CLEAR_A_0, 0x00ff); if (likely(napi_schedule_prep(&ip->napi))) { - __netif_rx_schedule(&ip->napi); + __napi_schedule(&ip->napi); } else { printk(KERN_CRIT "ixp2000: irq while polling!!\n"); } diff --git a/drivers/net/jme.h b/drivers/net/jme.h index 5154411b5e6..e321c678b11 100644 --- a/drivers/net/jme.h +++ b/drivers/net/jme.h @@ -398,15 +398,15 @@ struct jme_ring { #define JME_NAPI_WEIGHT(w) int w #define JME_NAPI_WEIGHT_VAL(w) w #define JME_NAPI_WEIGHT_SET(w, r) -#define JME_RX_COMPLETE(dev, napis) netif_rx_complete(napis) +#define JME_RX_COMPLETE(dev, napis) napi_complete(napis) #define JME_NAPI_ENABLE(priv) napi_enable(&priv->napi); #define JME_NAPI_DISABLE(priv) \ if (!napi_disable_pending(&priv->napi)) \ napi_disable(&priv->napi); #define JME_RX_SCHEDULE_PREP(priv) \ - netif_rx_schedule_prep(&priv->napi) + napi_schedule_prep(&priv->napi) #define JME_RX_SCHEDULE(priv) \ - __netif_rx_schedule(&priv->napi); + __napi_schedule(&priv->napi); /* * Jmac Adapter Private data diff --git a/drivers/net/korina.c b/drivers/net/korina.c index 75010cac76a..38d6649a29c 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c @@ -334,7 +334,7 @@ static irqreturn_t korina_rx_dma_interrupt(int irq, void *dev_id) DMA_STAT_HALT | DMA_STAT_ERR), &lp->rx_dma_regs->dmasm); - netif_rx_schedule(&lp->napi); + napi_schedule(&lp->napi); if (dmas & DMA_STAT_ERR) printk(KERN_ERR DRV_NAME "%s: DMA error\n", dev->name); @@ -468,7 +468,7 @@ static int korina_poll(struct napi_struct *napi, int budget) work_done = korina_rx(dev, budget); if (work_done < budget) { - netif_rx_complete(napi); + napi_complete(napi); writel(readl(&lp->rx_dma_regs->dmasm) & ~(DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR), diff --git a/drivers/net/macb.c b/drivers/net/macb.c index f6c4936e2fa..dc33d51213d 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -527,7 +527,7 @@ static int macb_poll(struct napi_struct *napi, int budget) * this function was called last time, and no packets * have been received since. */ - netif_rx_complete(napi); + napi_complete(napi); goto out; } @@ -538,13 +538,13 @@ static int macb_poll(struct napi_struct *napi, int budget) dev_warn(&bp->pdev->dev, "No RX buffers complete, status = %02lx\n", (unsigned long)status); - netif_rx_complete(napi); + napi_complete(napi); goto out; } work_done = macb_rx(bp, budget); if (work_done < budget) - netif_rx_complete(napi); + napi_complete(napi); /* * We've done what we can to clean the buffers. Make sure we @@ -579,7 +579,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) } if (status & MACB_RX_INT_FLAGS) { - if (netif_rx_schedule_prep(&bp->napi)) { + if (napi_schedule_prep(&bp->napi)) { /* * There's no point taking any more interrupts * until we have processed the buffers @@ -587,7 +587,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) macb_writel(bp, IDR, MACB_RX_INT_FLAGS); dev_dbg(&bp->pdev->dev, "scheduling RX softirq\n"); - __netif_rx_schedule(&bp->napi); + __napi_schedule(&bp->napi); } } diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c index c61b0bdca1a..ac55ebd2f14 100644 --- a/drivers/net/mlx4/en_rx.c +++ b/drivers/net/mlx4/en_rx.c @@ -814,7 +814,7 @@ void mlx4_en_rx_irq(struct mlx4_cq *mcq) struct mlx4_en_priv *priv = netdev_priv(cq->dev); if (priv->port_up) - netif_rx_schedule(&cq->napi); + napi_schedule(&cq->napi); else mlx4_en_arm_cq(priv, cq); } @@ -834,7 +834,7 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget) INC_PERF_COUNTER(priv->pstats.napi_quota); else { /* Done for now */ - netif_rx_complete(napi); + napi_complete(napi); mlx4_en_arm_cq(priv, cq); } return done; diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index e9c1296b267..2dacb8852dc 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -1514,7 +1514,7 @@ static int myri10ge_poll(struct napi_struct *napi, int budget) work_done = myri10ge_clean_rx_done(ss, budget); if (work_done < budget) { - netif_rx_complete(napi); + napi_complete(napi); put_be32(htonl(3), ss->irq_claim); } return work_done; @@ -1532,7 +1532,7 @@ static irqreturn_t myri10ge_intr(int irq, void *arg) /* an interrupt on a non-zero receive-only slice is implicitly * valid since MSI-X irqs are not shared */ if ((mgp->dev->real_num_tx_queues == 1) && (ss != mgp->ss)) { - netif_rx_schedule(&ss->napi); + napi_schedule(&ss->napi); return (IRQ_HANDLED); } @@ -1543,7 +1543,7 @@ static irqreturn_t myri10ge_intr(int irq, void *arg) /* low bit indicates receives are present, so schedule * napi poll handler */ if (stats->valid & 1) - netif_rx_schedule(&ss->napi); + napi_schedule(&ss->napi); if (!mgp->msi_enabled && !mgp->msix_enabled) { put_be32(0, mgp->irq_deassert); diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index c5dec54251b..c23a58624a3 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -2198,10 +2198,10 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) prefetch(&np->rx_skbuff[np->cur_rx % RX_RING_SIZE]); - if (netif_rx_schedule_prep(&np->napi)) { + if (napi_schedule_prep(&np->napi)) { /* Disable interrupts and register for poll */ natsemi_irq_disable(dev); - __netif_rx_schedule(&np->napi); + __napi_schedule(&np->napi); } else printk(KERN_WARNING "%s: Ignoring interrupt, status %#08x, mask %#08x.\n", @@ -2253,7 +2253,7 @@ static int natsemi_poll(struct napi_struct *napi, int budget) np->intr_status = readl(ioaddr + IntrStatus); } while (np->intr_status); - netif_rx_complete(napi); + napi_complete(napi); /* Reenable interrupts providing nothing is trying to shut * the chip down. */ diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index d854f07ef4d..1139e637f5d 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -1631,7 +1631,7 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget) } if ((work_done < budget) && tx_complete) { - netif_rx_complete(&adapter->napi); + napi_complete(&adapter->napi); netxen_nic_enable_int(adapter); } diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 0c0b752315c..4a5a089fa30 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -3669,7 +3669,7 @@ static int niu_poll(struct napi_struct *napi, int budget) work_done = niu_poll_core(np, lp, budget); if (work_done < budget) { - netif_rx_complete(napi); + napi_complete(napi); niu_ldg_rearm(np, lp, 1); } return work_done; @@ -4088,12 +4088,12 @@ static void __niu_fastpath_interrupt(struct niu *np, int ldg, u64 v0) static void niu_schedule_napi(struct niu *np, struct niu_ldg *lp, u64 v0, u64 v1, u64 v2) { - if (likely(netif_rx_schedule_prep(&lp->napi))) { + if (likely(napi_schedule_prep(&lp->napi))) { lp->v0 = v0; lp->v1 = v1; lp->v2 = v2; __niu_fastpath_interrupt(np, lp->ldg_num, v0); - __netif_rx_schedule(&lp->napi); + __napi_schedule(&lp->napi); } } diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c index d0349e7d73e..5eeb5a87b73 100644 --- a/drivers/net/pasemi_mac.c +++ b/drivers/net/pasemi_mac.c @@ -970,7 +970,7 @@ static irqreturn_t pasemi_mac_rx_intr(int irq, void *data) if (*chan->status & PAS_STATUS_ERROR) reg |= PAS_IOB_DMA_RXCH_RESET_DINTC; - netif_rx_schedule(&mac->napi); + napi_schedule(&mac->napi); write_iob_reg(PAS_IOB_DMA_RXCH_RESET(chan->chno), reg); @@ -1010,7 +1010,7 @@ static irqreturn_t pasemi_mac_tx_intr(int irq, void *data) mod_timer(&txring->clean_timer, jiffies + (TX_CLEAN_INTERVAL)*2); - netif_rx_schedule(&mac->napi); + napi_schedule(&mac->napi); if (reg) write_iob_reg(PAS_IOB_DMA_TXCH_RESET(chan->chno), reg); @@ -1639,7 +1639,7 @@ static int pasemi_mac_poll(struct napi_struct *napi, int budget) pkts = pasemi_mac_clean_rx(rx_ring(mac), budget); if (pkts < budget) { /* all done, no more packets present */ - netif_rx_complete(napi); + napi_complete(napi); pasemi_mac_restart_rx_intr(mac); pasemi_mac_restart_tx_intr(mac); diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 665a4286da3..80124fac65f 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -1397,7 +1397,7 @@ static int pcnet32_poll(struct napi_struct *napi, int budget) if (work_done < budget) { spin_lock_irqsave(&lp->lock, flags); - __netif_rx_complete(napi); + __napi_complete(napi); /* clear interrupt masks */ val = lp->a.read_csr(ioaddr, CSR3); @@ -2592,14 +2592,14 @@ pcnet32_interrupt(int irq, void *dev_id) dev->name, csr0); /* unlike for the lance, there is no restart needed */ } - if (netif_rx_schedule_prep(&lp->napi)) { + if (napi_schedule_prep(&lp->napi)) { u16 val; /* set interrupt masks */ val = lp->a.read_csr(ioaddr, CSR3); val |= 0x5f00; lp->a.write_csr(ioaddr, CSR3, val); mmiowb(); - __netif_rx_schedule(&lp->napi); + __napi_schedule(&lp->napi); break; } csr0 = lp->a.read_csr(ioaddr, CSR0); diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index 189ec29ac7a..8b2823c8dcc 100644 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -2292,7 +2292,7 @@ static int ql_poll(struct napi_struct *napi, int budget) if (tx_cleaned + rx_cleaned != budget) { spin_lock_irqsave(&qdev->hw_lock, hw_flags); - __netif_rx_complete(napi); + __napi_complete(napi); ql_update_small_bufq_prod_index(qdev); ql_update_lrg_bufq_prod_index(qdev); writel(qdev->rsp_consumer_index, @@ -2351,8 +2351,8 @@ static irqreturn_t ql3xxx_isr(int irq, void *dev_id) spin_unlock(&qdev->adapter_lock); } else if (value & ISP_IMR_DISABLE_CMPL_INT) { ql_disable_interrupts(qdev); - if (likely(netif_rx_schedule_prep(&qdev->napi))) { - __netif_rx_schedule(&qdev->napi); + if (likely(napi_schedule_prep(&qdev->napi))) { + __napi_schedule(&qdev->napi); } } else { return IRQ_NONE; diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 45421c8b601..16eb9dd8528 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -1642,7 +1642,7 @@ static int ql_napi_poll_msix(struct napi_struct *napi, int budget) rx_ring->cq_id); if (work_done < budget) { - __netif_rx_complete(napi); + __napi_complete(napi); ql_enable_completion_interrupt(qdev, rx_ring->irq); } return work_done; @@ -1727,7 +1727,7 @@ static irqreturn_t qlge_msix_tx_isr(int irq, void *dev_id) static irqreturn_t qlge_msix_rx_isr(int irq, void *dev_id) { struct rx_ring *rx_ring = dev_id; - netif_rx_schedule(&rx_ring->napi); + napi_schedule(&rx_ring->napi); return IRQ_HANDLED; } @@ -1813,7 +1813,7 @@ static irqreturn_t qlge_isr(int irq, void *dev_id) &rx_ring->rx_work, 0); else - netif_rx_schedule(&rx_ring->napi); + napi_schedule(&rx_ring->napi); work_done++; } } diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 72fd9e97c19..cc0f886b0c2 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -677,7 +677,7 @@ static int r6040_poll(struct napi_struct *napi, int budget) work_done = r6040_rx(dev, budget); if (work_done < budget) { - netif_rx_complete(napi); + napi_complete(napi); /* Enable RX interrupt */ iowrite16(ioread16(ioaddr + MIER) | RX_INTS, ioaddr + MIER); } @@ -714,7 +714,7 @@ static irqreturn_t r6040_interrupt(int irq, void *dev_id) /* Mask off RX interrupt */ misr &= ~RX_INTS; - netif_rx_schedule(&lp->napi); + napi_schedule(&lp->napi); } /* TX interrupt request */ diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 2c73ca606b3..1c4a980253f 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -3581,8 +3581,8 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); tp->intr_mask = ~tp->napi_event; - if (likely(netif_rx_schedule_prep(&tp->napi))) - __netif_rx_schedule(&tp->napi); + if (likely(napi_schedule_prep(&tp->napi))) + __napi_schedule(&tp->napi); else if (netif_msg_intr(tp)) { printk(KERN_INFO "%s: interrupt %04x in poll\n", dev->name, status); @@ -3603,7 +3603,7 @@ static int rtl8169_poll(struct napi_struct *napi, int budget) rtl8169_tx_interrupt(dev, tp, ioaddr); if (work_done < budget) { - netif_rx_complete(napi); + napi_complete(napi); tp->intr_mask = 0xffff; /* * 20040426: the barrier is not strictly required but the diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index f5c57c059bc..2a96a10fd0c 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -2852,7 +2852,7 @@ static int s2io_poll_msix(struct napi_struct *napi, int budget) s2io_chk_rx_buffers(nic, ring); if (pkts_processed < budget_org) { - netif_rx_complete(napi); + napi_complete(napi); /*Re Enable MSI-Rx Vector*/ addr = (u8 __iomem *)&bar0->xmsi_mask_reg; addr += 7 - ring->ring_no; @@ -2889,7 +2889,7 @@ static int s2io_poll_inta(struct napi_struct *napi, int budget) break; } if (pkts_processed < budget_org) { - netif_rx_complete(napi); + napi_complete(napi); /* Re enable the Rx interrupts for the ring */ writeq(0, &bar0->rx_traffic_mask); readl(&bar0->rx_traffic_mask); @@ -4342,7 +4342,7 @@ static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id) val8 = (ring->ring_no == 0) ? 0x7f : 0xff; writeb(val8, addr); val8 = readb(addr); - netif_rx_schedule(&ring->napi); + napi_schedule(&ring->napi); } else { rx_intr_handler(ring, 0); s2io_chk_rx_buffers(sp, ring); @@ -4789,7 +4789,7 @@ static irqreturn_t s2io_isr(int irq, void *dev_id) if (config->napi) { if (reason & GEN_INTR_RXTRAFFIC) { - netif_rx_schedule(&sp->napi); + napi_schedule(&sp->napi); writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_mask); writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int); readl(&bar0->rx_traffic_int); diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index 31e38fae017..3e11c1d6d79 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -2039,9 +2039,9 @@ static irqreturn_t sbmac_intr(int irq,void *dev_instance) sbdma_tx_process(sc,&(sc->sbm_txdma), 0); if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) { - if (netif_rx_schedule_prep(&sc->napi)) { + if (napi_schedule_prep(&sc->napi)) { __raw_writeq(0, sc->sbm_imr); - __netif_rx_schedule(&sc->napi); + __napi_schedule(&sc->napi); /* Depend on the exit from poll to reenable intr */ } else { @@ -2667,7 +2667,7 @@ static int sbmac_poll(struct napi_struct *napi, int budget) sbdma_tx_process(sc, &(sc->sbm_txdma), 1); if (work_done < budget) { - netif_rx_complete(napi); + napi_complete(napi); #ifdef CONFIG_SBMAC_COALESCE __raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) | diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 7673fd92eaf..77aca5d67b5 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -225,11 +225,11 @@ static int efx_poll(struct napi_struct *napi, int budget) if (rx_packets < budget) { /* There is no race here; although napi_disable() will - * only wait for netif_rx_complete(), this isn't a problem + * only wait for napi_complete(), this isn't a problem * since efx_channel_processed() will have no effect if * interrupts have already been disabled. */ - netif_rx_complete(napi); + napi_complete(napi); efx_channel_processed(channel); } diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h index 0dd7a532c78..fb1ac0e63c0 100644 --- a/drivers/net/sfc/efx.h +++ b/drivers/net/sfc/efx.h @@ -77,7 +77,7 @@ static inline void efx_schedule_channel(struct efx_channel *channel) channel->channel, raw_smp_processor_id()); channel->work_pending = true; - netif_rx_schedule(&channel->napi_str); + napi_schedule(&channel->napi_str); } #endif /* EFX_EFX_H */ diff --git a/drivers/net/skge.c b/drivers/net/skge.c index c9dbb06f8c9..952d37ffee5 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -3214,7 +3214,7 @@ static int skge_poll(struct napi_struct *napi, int to_do) unsigned long flags; spin_lock_irqsave(&hw->hw_lock, flags); - __netif_rx_complete(napi); + __napi_complete(napi); hw->intr_mask |= napimask[skge->port]; skge_write32(hw, B0_IMSK, hw->intr_mask); skge_read32(hw, B0_IMSK); @@ -3377,7 +3377,7 @@ static irqreturn_t skge_intr(int irq, void *dev_id) if (status & (IS_XA1_F|IS_R1_F)) { struct skge_port *skge = netdev_priv(hw->dev[0]); hw->intr_mask &= ~(IS_XA1_F|IS_R1_F); - netif_rx_schedule(&skge->napi); + napi_schedule(&skge->napi); } if (status & IS_PA_TO_TX1) @@ -3397,7 +3397,7 @@ static irqreturn_t skge_intr(int irq, void *dev_id) if (status & (IS_XA2_F|IS_R2_F)) { hw->intr_mask &= ~(IS_XA2_F|IS_R2_F); - netif_rx_schedule(&skge->napi); + napi_schedule(&skge->napi); } if (status & IS_PA_TO_RX2) { diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index f513bdf1c88..d271ae39c6f 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -984,7 +984,7 @@ static int smsc911x_poll(struct napi_struct *napi, int budget) /* We processed all packets available. Tell NAPI it can * stop polling then re-enable rx interrupts */ smsc911x_reg_write(pdata, INT_STS, INT_STS_RSFL_); - netif_rx_complete(napi); + napi_complete(napi); temp = smsc911x_reg_read(pdata, INT_EN); temp |= INT_EN_RSFL_EN_; smsc911x_reg_write(pdata, INT_EN, temp); @@ -1485,16 +1485,16 @@ static irqreturn_t smsc911x_irqhandler(int irq, void *dev_id) } if (likely(intsts & inten & INT_STS_RSFL_)) { - if (likely(netif_rx_schedule_prep(&pdata->napi))) { + if (likely(napi_schedule_prep(&pdata->napi))) { /* Disable Rx interrupts */ temp = smsc911x_reg_read(pdata, INT_EN); temp &= (~INT_EN_RSFL_EN_); smsc911x_reg_write(pdata, INT_EN, temp); /* Schedule a NAPI poll */ - __netif_rx_schedule(&pdata->napi); + __napi_schedule(&pdata->napi); } else { SMSC_WARNING(RX_ERR, - "netif_rx_schedule_prep failed"); + "napi_schedule_prep failed"); } serviced = IRQ_HANDLED; } diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c index c14a4c6452c..79f4c228b03 100644 --- a/drivers/net/smsc9420.c +++ b/drivers/net/smsc9420.c @@ -666,7 +666,7 @@ static irqreturn_t smsc9420_isr(int irq, void *dev_id) smsc9420_pci_flush_write(pd); ints_to_clear |= (DMAC_STS_RX_ | DMAC_STS_NIS_); - netif_rx_schedule(&pd->napi); + napi_schedule(&pd->napi); } if (ints_to_clear) @@ -889,7 +889,7 @@ static int smsc9420_rx_poll(struct napi_struct *napi, int budget) smsc9420_pci_flush_write(pd); if (work_done < budget) { - netif_rx_complete(&pd->napi); + napi_complete(&pd->napi); /* re-enable RX DMA interrupts */ dma_intr_ena = smsc9420_reg_read(pd, DMAC_INTR_ENA); diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 88d2c67788d..7f6b4a4052e 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -1301,7 +1301,7 @@ static int spider_net_poll(struct napi_struct *napi, int budget) /* if all packets are in the stack, enable interrupts and return 0 */ /* if not, return 1 */ if (packets_done < budget) { - netif_rx_complete(napi); + napi_complete(napi); spider_net_rx_irq_on(card); card->ignore_rx_ramfull = 0; } @@ -1528,7 +1528,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg, spider_net_refill_rx_chain(card); spider_net_enable_rxdmac(card); card->num_rx_ints ++; - netif_rx_schedule(&card->napi); + napi_schedule(&card->napi); } show_error = 0; break; @@ -1548,7 +1548,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg, spider_net_refill_rx_chain(card); spider_net_enable_rxdmac(card); card->num_rx_ints ++; - netif_rx_schedule(&card->napi); + napi_schedule(&card->napi); show_error = 0; break; @@ -1562,7 +1562,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg, spider_net_refill_rx_chain(card); spider_net_enable_rxdmac(card); card->num_rx_ints ++; - netif_rx_schedule(&card->napi); + napi_schedule(&card->napi); show_error = 0; break; @@ -1656,11 +1656,11 @@ spider_net_interrupt(int irq, void *ptr) if (status_reg & SPIDER_NET_RXINT ) { spider_net_rx_irq_off(card); - netif_rx_schedule(&card->napi); + napi_schedule(&card->napi); card->num_rx_ints ++; } if (status_reg & SPIDER_NET_TXINT) - netif_rx_schedule(&card->napi); + napi_schedule(&card->napi); if (status_reg & SPIDER_NET_LINKINT) spider_net_link_reset(netdev); diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index da3a76b18ef..98fe79515ba 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -1342,8 +1342,8 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) if (intr_status & (IntrRxDone | IntrRxEmpty)) { u32 enable; - if (likely(netif_rx_schedule_prep(&np->napi))) { - __netif_rx_schedule(&np->napi); + if (likely(napi_schedule_prep(&np->napi))) { + __napi_schedule(&np->napi); enable = readl(ioaddr + IntrEnable); enable &= ~(IntrRxDone | IntrRxEmpty); writel(enable, ioaddr + IntrEnable); @@ -1587,7 +1587,7 @@ static int netdev_poll(struct napi_struct *napi, int budget) intr_status = readl(ioaddr + IntrStatus); } while (intr_status & (IntrRxDone | IntrRxEmpty)); - netif_rx_complete(napi); + napi_complete(napi); intr_status = readl(ioaddr + IntrEnable); intr_status |= IntrRxDone | IntrRxEmpty; writel(intr_status, ioaddr + IntrEnable); diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 86c765d83de..4942059109f 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -921,7 +921,7 @@ static int gem_poll(struct napi_struct *napi, int budget) gp->status = readl(gp->regs + GREG_STAT); } while (gp->status & GREG_STAT_NAPI); - __netif_rx_complete(napi); + __napi_complete(napi); gem_enable_ints(gp); spin_unlock_irqrestore(&gp->lock, flags); @@ -944,7 +944,7 @@ static irqreturn_t gem_interrupt(int irq, void *dev_id) spin_lock_irqsave(&gp->lock, flags); - if (netif_rx_schedule_prep(&gp->napi)) { + if (napi_schedule_prep(&gp->napi)) { u32 gem_status = readl(gp->regs + GREG_STAT); if (gem_status == 0) { @@ -954,7 +954,7 @@ static irqreturn_t gem_interrupt(int irq, void *dev_id) } gp->status = gem_status; gem_disable_ints(gp); - __netif_rx_schedule(&gp->napi); + __napi_schedule(&gp->napi); } spin_unlock_irqrestore(&gp->lock, flags); diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index bcd0e60cbda..f42c67e93bf 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -1609,8 +1609,8 @@ static irqreturn_t tc35815_interrupt(int irq, void *dev_id) if (!(dmactl & DMA_IntMask)) { /* disable interrupts */ tc_writel(dmactl | DMA_IntMask, &tr->DMA_Ctl); - if (netif_rx_schedule_prep(&lp->napi)) - __netif_rx_schedule(&lp->napi); + if (napi_schedule_prep(&lp->napi)) + __napi_schedule(&lp->napi); else { printk(KERN_ERR "%s: interrupt taken in poll\n", dev->name); @@ -1919,7 +1919,7 @@ static int tc35815_poll(struct napi_struct *napi, int budget) spin_unlock(&lp->lock); if (received < budget) { - netif_rx_complete(napi); + napi_complete(napi); /* enable interrupts */ tc_writel(tc_readl(&tr->DMA_Ctl) & ~DMA_IntMask, &tr->DMA_Ctl); } diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index a7a4dc4d631..be9f38f8f0b 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c @@ -265,8 +265,8 @@ static irqreturn_t bdx_isr_napi(int irq, void *dev) bdx_isr_extra(priv, isr); if (isr & (IR_RX_DESC_0 | IR_TX_FREE_0)) { - if (likely(netif_rx_schedule_prep(&priv->napi))) { - __netif_rx_schedule(&priv->napi); + if (likely(napi_schedule_prep(&priv->napi))) { + __napi_schedule(&priv->napi); RET(IRQ_HANDLED); } else { /* NOTE: we get here if intr has slipped into window @@ -302,7 +302,7 @@ static int bdx_poll(struct napi_struct *napi, int budget) * device lock and allow waiting tasks (eg rmmod) to advance) */ priv->napi_stop = 0; - netif_rx_complete(napi); + napi_complete(napi); bdx_enable_interrupts(priv); } return work_done; diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 8b3f8468538..5fa65acb68e 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -4460,7 +4460,7 @@ static int tg3_poll(struct napi_struct *napi, int budget) sblk->status &= ~SD_STATUS_UPDATED; if (likely(!tg3_has_work(tp))) { - netif_rx_complete(napi); + napi_complete(napi); tg3_restart_ints(tp); break; } @@ -4470,7 +4470,7 @@ static int tg3_poll(struct napi_struct *napi, int budget) tx_recovery: /* work_done is guaranteed to be less than budget. */ - netif_rx_complete(napi); + napi_complete(napi); schedule_work(&tp->reset_task); return work_done; } @@ -4519,7 +4519,7 @@ static irqreturn_t tg3_msi_1shot(int irq, void *dev_id) prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); if (likely(!tg3_irq_sync(tp))) - netif_rx_schedule(&tp->napi); + napi_schedule(&tp->napi); return IRQ_HANDLED; } @@ -4544,7 +4544,7 @@ static irqreturn_t tg3_msi(int irq, void *dev_id) */ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); if (likely(!tg3_irq_sync(tp))) - netif_rx_schedule(&tp->napi); + napi_schedule(&tp->napi); return IRQ_RETVAL(1); } @@ -4586,7 +4586,7 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id) sblk->status &= ~SD_STATUS_UPDATED; if (likely(tg3_has_work(tp))) { prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); - netif_rx_schedule(&tp->napi); + napi_schedule(&tp->napi); } else { /* No work, shared interrupt perhaps? re-enable * interrupts, and flush that PCI write @@ -4632,7 +4632,7 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id) tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); if (tg3_irq_sync(tp)) goto out; - if (netif_rx_schedule_prep(&tp->napi)) { + if (napi_schedule_prep(&tp->napi)) { prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); /* Update last_tag to mark that this status has been * seen. Because interrupt may be shared, we may be @@ -4640,7 +4640,7 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id) * if tg3_poll() is not scheduled. */ tp->last_tag = sblk->status_tag; - __netif_rx_schedule(&tp->napi); + __napi_schedule(&tp->napi); } out: return IRQ_RETVAL(handled); diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c index 75461dbd487..1138782e561 100644 --- a/drivers/net/tsi108_eth.c +++ b/drivers/net/tsi108_eth.c @@ -888,7 +888,7 @@ static int tsi108_poll(struct napi_struct *napi, int budget) if (num_received < budget) { data->rxpending = 0; - netif_rx_complete(napi); + napi_complete(napi); TSI_WRITE(TSI108_EC_INTMASK, TSI_READ(TSI108_EC_INTMASK) @@ -915,11 +915,11 @@ static void tsi108_rx_int(struct net_device *dev) * * This can happen if this code races with tsi108_poll(), which masks * the interrupts after tsi108_irq_one() read the mask, but before - * netif_rx_schedule is called. It could also happen due to calls + * napi_schedule is called. It could also happen due to calls * from tsi108_check_rxring(). */ - if (netif_rx_schedule_prep(&data->napi)) { + if (napi_schedule_prep(&data->napi)) { /* Mask, rather than ack, the receive interrupts. The ack * will happen in tsi108_poll(). */ @@ -930,7 +930,7 @@ static void tsi108_rx_int(struct net_device *dev) | TSI108_INT_RXTHRESH | TSI108_INT_RXOVERRUN | TSI108_INT_RXERROR | TSI108_INT_RXWAIT); - __netif_rx_schedule(&data->napi); + __napi_schedule(&data->napi); } else { if (!netif_running(dev)) { /* This can happen if an interrupt occurs while the diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c index 6c3428a37c0..9f946d42108 100644 --- a/drivers/net/tulip/interrupt.c +++ b/drivers/net/tulip/interrupt.c @@ -103,7 +103,7 @@ void oom_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct tulip_private *tp = netdev_priv(dev); - netif_rx_schedule(&tp->napi); + napi_schedule(&tp->napi); } int tulip_poll(struct napi_struct *napi, int budget) @@ -300,7 +300,7 @@ int tulip_poll(struct napi_struct *napi, int budget) /* Remove us from polling list and enable RX intr. */ - netif_rx_complete(napi); + napi_complete(napi); iowrite32(tulip_tbl[tp->chip_id].valid_intrs, tp->base_addr+CSR7); /* The last op happens after poll completion. Which means the following: @@ -333,10 +333,10 @@ int tulip_poll(struct napi_struct *napi, int budget) /* Think: timer_pending() was an explicit signature of bug. * Timer can be pending now but fired and completed - * before we did netif_rx_complete(). See? We would lose it. */ + * before we did napi_complete(). See? We would lose it. */ /* remove ourselves from the polling list */ - netif_rx_complete(napi); + napi_complete(napi); return work_done; } @@ -519,7 +519,7 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance) rxd++; /* Mask RX intrs and add the device to poll list. */ iowrite32(tulip_tbl[tp->chip_id].valid_intrs&~RxPollInt, ioaddr + CSR7); - netif_rx_schedule(&tp->napi); + napi_schedule(&tp->napi); if (!(csr5&~(AbnormalIntr|NormalIntr|RxPollInt|TPLnkPass))) break; diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 3af9a9516cc..dcff5ade6d0 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -1783,7 +1783,7 @@ typhoon_poll(struct napi_struct *napi, int budget) } if (work_done < budget) { - netif_rx_complete(napi); + napi_complete(napi); iowrite32(TYPHOON_INTR_NONE, tp->ioaddr + TYPHOON_REG_INTR_MASK); typhoon_post_pci_writes(tp->ioaddr); @@ -1806,10 +1806,10 @@ typhoon_interrupt(int irq, void *dev_instance) iowrite32(intr_status, ioaddr + TYPHOON_REG_INTR_STATUS); - if (netif_rx_schedule_prep(&tp->napi)) { + if (napi_schedule_prep(&tp->napi)) { iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK); typhoon_post_pci_writes(ioaddr); - __netif_rx_schedule(&tp->napi); + __napi_schedule(&tp->napi); } else { printk(KERN_ERR "%s: Error, poll already scheduled\n", dev->name); diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 11441225bf4..6def6f826a5 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -3251,7 +3251,7 @@ static int ucc_geth_poll(struct napi_struct *napi, int budget) howmany += ucc_geth_rx(ugeth, i, budget - howmany); if (howmany < budget) { - netif_rx_complete(napi); + napi_complete(napi); setbits32(ugeth->uccf->p_uccm, UCCE_RX_EVENTS); } @@ -3282,10 +3282,10 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info) /* check for receive events that require processing */ if (ucce & UCCE_RX_EVENTS) { - if (netif_rx_schedule_prep(&ugeth->napi)) { + if (napi_schedule_prep(&ugeth->napi)) { uccm &= ~UCCE_RX_EVENTS; out_be32(uccf->p_uccm, uccm); - __netif_rx_schedule(&ugeth->napi); + __napi_schedule(&ugeth->napi); } } diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index 3b8e6325427..4671436ecf0 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -589,7 +589,7 @@ static int rhine_napipoll(struct napi_struct *napi, int budget) work_done = rhine_rx(dev, budget); if (work_done < budget) { - netif_rx_complete(napi); + napi_complete(napi); iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow | IntrRxDropped | IntrRxNoBuf | IntrTxAborted | @@ -1319,7 +1319,7 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance) IntrPCIErr | IntrStatsMax | IntrLinkChange, ioaddr + IntrEnable); - netif_rx_schedule(&rp->napi); + napi_schedule(&rp->napi); } if (intr_status & (IntrTxErrSummary | IntrTxDone)) { diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 43f6523c40b..30ae6d9a12a 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -374,9 +374,9 @@ static void skb_recv_done(struct virtqueue *rvq) { struct virtnet_info *vi = rvq->vdev->priv; /* Schedule NAPI, Suppress further interrupts if successful. */ - if (netif_rx_schedule_prep(&vi->napi)) { + if (napi_schedule_prep(&vi->napi)) { rvq->vq_ops->disable_cb(rvq); - __netif_rx_schedule(&vi->napi); + __napi_schedule(&vi->napi); } } @@ -402,11 +402,11 @@ again: /* Out of packets? */ if (received < budget) { - netif_rx_complete(napi); + napi_complete(napi); if (unlikely(!vi->rvq->vq_ops->enable_cb(vi->rvq)) && napi_schedule_prep(napi)) { vi->rvq->vq_ops->disable_cb(vi->rvq); - __netif_rx_schedule(napi); + __napi_schedule(napi); goto again; } } @@ -580,9 +580,9 @@ static int virtnet_open(struct net_device *dev) * won't get another interrupt, so process any outstanding packets * now. virtnet_poll wants re-enable the queue, so we disable here. * We synchronize against interrupts via NAPI_STATE_SCHED */ - if (netif_rx_schedule_prep(&vi->napi)) { + if (napi_schedule_prep(&vi->napi)) { vi->rvq->vq_ops->disable_cb(vi->rvq); - __netif_rx_schedule(&vi->napi); + __napi_schedule(&vi->napi); } return 0; } diff --git a/drivers/net/wan/hd64572.c b/drivers/net/wan/hd64572.c index 08b3536944f..497b003d723 100644 --- a/drivers/net/wan/hd64572.c +++ b/drivers/net/wan/hd64572.c @@ -341,7 +341,7 @@ static int sca_poll(struct napi_struct *napi, int budget) received = sca_rx_done(port, budget); if (received < budget) { - netif_rx_complete(napi); + napi_complete(napi); enable_intr(port); } @@ -359,7 +359,7 @@ static irqreturn_t sca_intr(int irq, void *dev_id) if (port && (isr0 & (i ? 0x08002200 : 0x00080022))) { handled = 1; disable_intr(port); - netif_rx_schedule(&port->napi); + napi_schedule(&port->napi); } } diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index 7e8bbba2cc1..3bf7d3f447d 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -622,7 +622,7 @@ static void hss_hdlc_rx_irq(void *pdev) printk(KERN_DEBUG "%s: hss_hdlc_rx_irq\n", dev->name); #endif qmgr_disable_irq(queue_ids[port->id].rx); - netif_rx_schedule(&port->napi); + napi_schedule(&port->napi); } static int hss_hdlc_poll(struct napi_struct *napi, int budget) @@ -649,15 +649,15 @@ static int hss_hdlc_poll(struct napi_struct *napi, int budget) if ((n = queue_get_desc(rxq, port, 0)) < 0) { #if DEBUG_RX printk(KERN_DEBUG "%s: hss_hdlc_poll" - " netif_rx_complete\n", dev->name); + " napi_complete\n", dev->name); #endif - netif_rx_complete(napi); + napi_complete(napi); qmgr_enable_irq(rxq); if (!qmgr_stat_empty(rxq) && - netif_rx_reschedule(napi)) { + napi_reschedule(napi)) { #if DEBUG_RX printk(KERN_DEBUG "%s: hss_hdlc_poll" - " netif_rx_reschedule succeeded\n", + " napi_reschedule succeeded\n", dev->name); #endif qmgr_disable_irq(rxq); @@ -1069,7 +1069,7 @@ static int hss_hdlc_open(struct net_device *dev) hss_start_hdlc(port); /* we may already have RX data, enables IRQ */ - netif_rx_schedule(&port->napi); + napi_schedule(&port->napi); return 0; err_unlock: diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index cd6184ee08e..9f102a6535c 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -196,7 +196,7 @@ static void rx_refill_timeout(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct netfront_info *np = netdev_priv(dev); - netif_rx_schedule(&np->napi); + napi_schedule(&np->napi); } static int netfront_tx_slot_available(struct netfront_info *np) @@ -328,7 +328,7 @@ static int xennet_open(struct net_device *dev) xennet_alloc_rx_buffers(dev); np->rx.sring->rsp_event = np->rx.rsp_cons + 1; if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx)) - netif_rx_schedule(&np->napi); + napi_schedule(&np->napi); } spin_unlock_bh(&np->rx_lock); @@ -979,7 +979,7 @@ err: RING_FINAL_CHECK_FOR_RESPONSES(&np->rx, more_to_do); if (!more_to_do) - __netif_rx_complete(napi); + __napi_complete(napi); local_irq_restore(flags); } @@ -1317,7 +1317,7 @@ static irqreturn_t xennet_interrupt(int irq, void *dev_id) xennet_tx_buf_gc(dev); /* Under tx_lock: protects access to rx shared-ring indexes. */ if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx)) - netif_rx_schedule(&np->napi); + napi_schedule(&np->napi); } spin_unlock_irqrestore(&np->tx_lock, flags); diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index ec54785d34f..dd8a35b3e8b 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1574,56 +1574,6 @@ static inline u32 netif_msg_init(int debug_value, int default_msg_enable_bits) return (1 << debug_value) - 1; } -/* Test if receive needs to be scheduled but only if up */ -static inline int netif_rx_schedule_prep(struct napi_struct *napi) -{ - return napi_schedule_prep(napi); -} - -/* Add interface to tail of rx poll list. This assumes that _prep has - * already been called and returned 1. - */ -static inline void __netif_rx_schedule(struct napi_struct *napi) -{ - __napi_schedule(napi); -} - -/* Try to reschedule poll. Called by irq handler. */ - -static inline void netif_rx_schedule(struct napi_struct *napi) -{ - if (netif_rx_schedule_prep(napi)) - __netif_rx_schedule(napi); -} - -/* Try to reschedule poll. Called by dev->poll() after netif_rx_complete(). */ -static inline int netif_rx_reschedule(struct napi_struct *napi) -{ - if (napi_schedule_prep(napi)) { - __netif_rx_schedule(napi); - return 1; - } - return 0; -} - -/* same as netif_rx_complete, except that local_irq_save(flags) - * has already been issued - */ -static inline void __netif_rx_complete(struct napi_struct *napi) -{ - __napi_complete(napi); -} - -/* Remove interface from poll list: it must be in the poll list - * on current cpu. This primitive is called by dev->poll(), when - * it completes the work. The device cannot be out of poll list at this - * moment, it is BUG(). - */ -static inline void netif_rx_complete(struct napi_struct *napi) -{ - napi_complete(napi); -} - static inline void __netif_tx_lock(struct netdev_queue *txq, int cpu) { spin_lock(&txq->_xmit_lock); -- GitLab From c405b828161286729b6a5a729159114dca122923 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 14 Jan 2009 20:37:59 -0800 Subject: [PATCH 0338/4982] e1000e: Invoke VLAN GRO handler Now that VLAN has GRO support as well, we can call its GRO handler as well. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- drivers/net/e1000e/netdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index ff5b66adfc4..2ffd7523a91 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -99,8 +99,8 @@ static void e1000_receive_skb(struct e1000_adapter *adapter, skb->protocol = eth_type_trans(skb, netdev); if (adapter->vlgrp && (status & E1000_RXD_STAT_VP)) - vlan_hwaccel_receive_skb(skb, adapter->vlgrp, - le16_to_cpu(vlan)); + vlan_gro_receive(&adapter->napi, adapter->vlgrp, + le16_to_cpu(vlan), skb); else napi_gro_receive(&adapter->napi, skb); } -- GitLab From 5cda9364f1fbc330f0d82f534505a8e375d0a66c Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Sun, 18 Jan 2009 21:29:40 -0800 Subject: [PATCH 0339/4982] cxgb3: ease msi-x settings conditions The driver currently drops to line interrupt mode if it did not get all the msi-x vectors it requested. Allow msi-x settings when a minimal amount of vectors is provided. Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/adapter.h | 1 + drivers/net/cxgb3/cxgb3_main.c | 23 +++++++++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h index a89d8cc5120..5fb7c6851eb 100644 --- a/drivers/net/cxgb3/adapter.h +++ b/drivers/net/cxgb3/adapter.h @@ -230,6 +230,7 @@ struct adapter { unsigned int slow_intr_mask; unsigned long irq_stats[IRQ_NUM_STATS]; + int msix_nvectors; struct { unsigned short vec; char desc[22]; diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 0089746b8d0..52131bd4cc7 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -338,7 +338,7 @@ static void free_irq_resources(struct adapter *adapter) free_irq(adapter->msix_info[0].vec, adapter); for_each_port(adapter, i) - n += adap2pinfo(adapter, i)->nqsets; + n += adap2pinfo(adapter, i)->nqsets; for (i = 0; i < n; ++i) free_irq(adapter->msix_info[i + 1].vec, @@ -2752,7 +2752,7 @@ static void set_nqsets(struct adapter *adap) int i, j = 0; int num_cpus = num_online_cpus(); int hwports = adap->params.nports; - int nqsets = SGE_QSETS; + int nqsets = adap->msix_nvectors - 1; if (adap->params.rev > 0 && adap->flags & USING_MSIX) { if (hwports == 2 && @@ -2781,18 +2781,25 @@ static void set_nqsets(struct adapter *adap) static int __devinit cxgb_enable_msix(struct adapter *adap) { struct msix_entry entries[SGE_QSETS + 1]; + int vectors; int i, err; - for (i = 0; i < ARRAY_SIZE(entries); ++i) + vectors = ARRAY_SIZE(entries); + for (i = 0; i < vectors; ++i) entries[i].entry = i; - err = pci_enable_msix(adap->pdev, entries, ARRAY_SIZE(entries)); + while ((err = pci_enable_msix(adap->pdev, entries, vectors)) > 0) + vectors = err; + + if (!err && vectors < (adap->params.nports + 1)) + err = -1; + if (!err) { - for (i = 0; i < ARRAY_SIZE(entries); ++i) + for (i = 0; i < vectors; ++i) adap->msix_info[i].vec = entries[i].vector; - } else if (err > 0) - dev_info(&adap->pdev->dev, - "only %d MSI-X vectors left, not using MSI-X\n", err); + adap->msix_nvectors = vectors; + } + return err; } -- GitLab From f90f92eed74251034f251e3cdf4fa5c4c1f09df0 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Fri, 16 Jan 2009 23:36:30 +0000 Subject: [PATCH 0340/4982] dccp: Initialisation framework for feature negotiation This initialises feature negotiation from two tables, which are in turn are initialised from sysctls. As a novel feature, specifics of the implementation (e.g. that short seqnos and ECN are not yet available) are advertised for robustness. Signed-off-by: Gerrit Renker Acked-by: Ian McDonald Signed-off-by: David S. Miller --- include/linux/dccp.h | 19 ------------- net/dccp/feat.c | 65 ++++++++++++++++++++++++++++++++++++++------ net/dccp/feat.h | 2 +- 3 files changed, 57 insertions(+), 29 deletions(-) diff --git a/include/linux/dccp.h b/include/linux/dccp.h index 61734e27abb..990e97fa1f0 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -369,28 +369,9 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb) * Will be used to pass the state from dccp_request_sock to dccp_sock. * * @dccpms_sequence_window - Sequence Window Feature (section 7.5.2) - * @dccpms_pending - List of features being negotiated - * @dccpms_conf - */ struct dccp_minisock { __u64 dccpms_sequence_window; - struct list_head dccpms_pending; - struct list_head dccpms_conf; -}; - -struct dccp_opt_conf { - __u8 *dccpoc_val; - __u8 dccpoc_len; -}; - -struct dccp_opt_pend { - struct list_head dccpop_node; - __u8 dccpop_type; - __u8 dccpop_feat; - __u8 *dccpop_val; - __u8 dccpop_len; - int dccpop_conf; - struct dccp_opt_conf *dccpop_sc; }; extern void dccp_minisock_init(struct dccp_minisock *dmsk); diff --git a/net/dccp/feat.c b/net/dccp/feat.c index 4152308958a..67ffac9905f 100644 --- a/net/dccp/feat.c +++ b/net/dccp/feat.c @@ -1115,23 +1115,70 @@ int dccp_feat_parse_options(struct sock *sk, struct dccp_request_sock *dreq, return 0; /* ignore FN options in all other states */ } +/** + * dccp_feat_init - Seed feature negotiation with host-specific defaults + * This initialises global defaults, depending on the value of the sysctls. + * These can later be overridden by registering changes via setsockopt calls. + * The last link in the chain is finalise_settings, to make sure that between + * here and the start of actual feature negotiation no inconsistencies enter. + * + * All features not appearing below use either defaults or are otherwise + * later adjusted through dccp_feat_finalise_settings(). + */ int dccp_feat_init(struct sock *sk) { - struct dccp_sock *dp = dccp_sk(sk); - struct dccp_minisock *dmsk = dccp_msk(sk); + struct list_head *fn = &dccp_sk(sk)->dccps_featneg; + u8 on = 1, off = 0; int rc; + struct { + u8 *val; + u8 len; + } tx, rx; + + /* Non-negotiable (NN) features */ + rc = __feat_register_nn(fn, DCCPF_SEQUENCE_WINDOW, 0, + sysctl_dccp_feat_sequence_window); + if (rc) + return rc; + + /* Server-priority (SP) features */ + + /* Advertise that short seqnos are not supported (7.6.1) */ + rc = __feat_register_sp(fn, DCCPF_SHORT_SEQNOS, true, true, &off, 1); + if (rc) + return rc; - INIT_LIST_HEAD(&dmsk->dccpms_pending); /* XXX no longer used */ - INIT_LIST_HEAD(&dmsk->dccpms_conf); /* XXX no longer used */ + /* RFC 4340 12.1: "If a DCCP is not ECN capable, ..." */ + rc = __feat_register_sp(fn, DCCPF_ECN_INCAPABLE, true, true, &on, 1); + if (rc) + return rc; + + /* + * We advertise the available list of CCIDs and reorder according to + * preferences, to avoid failure resulting from negotiating different + * singleton values (which always leads to failure). + * These settings can still (later) be overridden via sockopts. + */ + if (ccid_get_builtin_ccids(&tx.val, &tx.len) || + ccid_get_builtin_ccids(&rx.val, &rx.len)) + return -ENOBUFS; - /* Ack ratio */ - rc = __feat_register_nn(&dp->dccps_featneg, DCCPF_ACK_RATIO, 0, - dp->dccps_l_ack_ratio); + if (!dccp_feat_prefer(sysctl_dccp_feat_tx_ccid, tx.val, tx.len) || + !dccp_feat_prefer(sysctl_dccp_feat_rx_ccid, rx.val, rx.len)) + goto free_ccid_lists; + + rc = __feat_register_sp(fn, DCCPF_CCID, true, false, tx.val, tx.len); + if (rc) + goto free_ccid_lists; + + rc = __feat_register_sp(fn, DCCPF_CCID, false, false, rx.val, rx.len); + +free_ccid_lists: + kfree(tx.val); + kfree(rx.val); return rc; } -EXPORT_SYMBOL_GPL(dccp_feat_init); - int dccp_feat_activate_values(struct sock *sk, struct list_head *fn_list) { struct dccp_sock *dp = dccp_sk(sk); diff --git a/net/dccp/feat.h b/net/dccp/feat.h index 9b46e2a7866..5e7b8481cd0 100644 --- a/net/dccp/feat.h +++ b/net/dccp/feat.h @@ -113,13 +113,13 @@ static inline void dccp_feat_debug(const u8 type, const u8 feat, const u8 val) #define dccp_feat_debug(type, feat, val) #endif /* CONFIG_IP_DCCP_DEBUG */ +extern int dccp_feat_init(struct sock *sk); extern int dccp_feat_register_sp(struct sock *sk, u8 feat, u8 is_local, u8 const *list, u8 len); extern int dccp_feat_register_nn(struct sock *sk, u8 feat, u64 val); extern int dccp_feat_parse_options(struct sock *, struct dccp_request_sock *, u8 mand, u8 opt, u8 feat, u8 *val, u8 len); extern int dccp_feat_clone_list(struct list_head const *, struct list_head *); -extern int dccp_feat_init(struct sock *sk); /* * Encoding variable-length options and their maximum length. -- GitLab From 792b48780e8b6435d017cef4b5c304876a48653e Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Fri, 16 Jan 2009 23:36:31 +0000 Subject: [PATCH 0341/4982] dccp: Implement both feature-local and feature-remote Sequence Window feature This adds full support for local/remote Sequence Window feature, from which the * sequence-number-validity (W) and * acknowledgment-number-validity (W') windows derive as specified in RFC 4340, 7.5.3. Specifically, the following is contained in this patch: * integrated new socket fields into dccp_sk; * updated the update_gsr/gss routines with regard to these fields; * updated handler code: the Sequence Window feature is located at the TX side, so the local feature is meant if the handler-rx flag is false; * the initialisation of `rcv_wnd' in reqsk is removed, since - rcv_wnd is not used by the code anywhere; - sequence number checks are not done in the LISTEN state (cf. 7.5.3); - dccp_check_req checks the Ack number validity more rigorously; * the `struct dccp_minisock' became empty and is now removed. Signed-off-by: Gerrit Renker Acked-by: Ian McDonald Signed-off-by: David S. Miller --- Documentation/networking/dccp.txt | 3 ++- include/linux/dccp.h | 24 ++++-------------------- net/dccp/dccp.h | 16 +++++++--------- net/dccp/feat.c | 13 +++++++++++-- net/dccp/minisocks.c | 11 ----------- net/dccp/proto.c | 2 -- 6 files changed, 24 insertions(+), 45 deletions(-) diff --git a/Documentation/networking/dccp.txt b/Documentation/networking/dccp.txt index 7a3bb1abb83..b132e4a3cf0 100644 --- a/Documentation/networking/dccp.txt +++ b/Documentation/networking/dccp.txt @@ -141,7 +141,8 @@ rx_ccid = 2 Default CCID for the receiver-sender half-connection; see tx_ccid. seq_window = 100 - The initial sequence window (sec. 7.5.2). + The initial sequence window (sec. 7.5.2) of the sender. This influences + the local ackno validity and the remote seqno validity windows (7.5.1). tx_qlen = 5 The size of the transmit buffer in packets. A value of 0 corresponds diff --git a/include/linux/dccp.h b/include/linux/dccp.h index 990e97fa1f0..7a0502ab383 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -363,19 +363,6 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb) /* FIXME: for now we're default to 1 but it should really be 0 */ #define DCCPF_INITIAL_SEND_NDP_COUNT 1 -/** - * struct dccp_minisock - Minimal DCCP connection representation - * - * Will be used to pass the state from dccp_request_sock to dccp_sock. - * - * @dccpms_sequence_window - Sequence Window Feature (section 7.5.2) - */ -struct dccp_minisock { - __u64 dccpms_sequence_window; -}; - -extern void dccp_minisock_init(struct dccp_minisock *dmsk); - /** * struct dccp_request_sock - represent DCCP-specific connection request * @dreq_inet_rsk: structure inherited from @@ -464,13 +451,14 @@ struct dccp_ackvec; * @dccps_timestamp_time - time of receiving latest @dccps_timestamp_echo * @dccps_l_ack_ratio - feature-local Ack Ratio * @dccps_r_ack_ratio - feature-remote Ack Ratio + * @dccps_l_seq_win - local Sequence Window (influences ack number validity) + * @dccps_r_seq_win - remote Sequence Window (influences seq number validity) * @dccps_pcslen - sender partial checksum coverage (via sockopt) * @dccps_pcrlen - receiver partial checksum coverage (via sockopt) * @dccps_send_ndp_count - local Send NDP Count feature (7.7.2) * @dccps_ndp_count - number of Non Data Packets since last data packet * @dccps_mss_cache - current value of MSS (path MTU minus header sizes) * @dccps_rate_last - timestamp for rate-limiting DCCP-Sync (RFC 4340, 7.5.4) - * @dccps_minisock - associated minisock (accessed via dccp_msk) * @dccps_featneg - tracks feature-negotiation state (mostly during handshake) * @dccps_hc_rx_ackvec - rx half connection ack vector * @dccps_hc_rx_ccid - CCID used for the receiver (or receiving half-connection) @@ -504,12 +492,13 @@ struct dccp_sock { __u32 dccps_timestamp_time; __u16 dccps_l_ack_ratio; __u16 dccps_r_ack_ratio; + __u64 dccps_l_seq_win:48; + __u64 dccps_r_seq_win:48; __u8 dccps_pcslen:4; __u8 dccps_pcrlen:4; __u8 dccps_send_ndp_count:1; __u64 dccps_ndp_count:48; unsigned long dccps_rate_last; - struct dccp_minisock dccps_minisock; struct list_head dccps_featneg; struct dccp_ackvec *dccps_hc_rx_ackvec; struct ccid *dccps_hc_rx_ccid; @@ -527,11 +516,6 @@ static inline struct dccp_sock *dccp_sk(const struct sock *sk) return (struct dccp_sock *)sk; } -static inline struct dccp_minisock *dccp_msk(const struct sock *sk) -{ - return (struct dccp_minisock *)&dccp_sk(sk)->dccps_minisock; -} - static inline const char *dccp_role(const struct sock *sk) { switch (dccp_sk(sk)->dccps_role) { diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index f2230fc168e..04ae91898a6 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -409,23 +409,21 @@ static inline void dccp_hdr_set_ack(struct dccp_hdr_ack_bits *dhack, static inline void dccp_update_gsr(struct sock *sk, u64 seq) { struct dccp_sock *dp = dccp_sk(sk); - const struct dccp_minisock *dmsk = dccp_msk(sk); dp->dccps_gsr = seq; - dccp_set_seqno(&dp->dccps_swl, - dp->dccps_gsr + 1 - (dmsk->dccpms_sequence_window / 4)); - dccp_set_seqno(&dp->dccps_swh, - dp->dccps_gsr + (3 * dmsk->dccpms_sequence_window) / 4); + /* Sequence validity window depends on remote Sequence Window (7.5.1) */ + dp->dccps_swl = SUB48(ADD48(dp->dccps_gsr, 1), dp->dccps_r_seq_win / 4); + dp->dccps_swh = ADD48(dp->dccps_gsr, (3 * dp->dccps_r_seq_win) / 4); } static inline void dccp_update_gss(struct sock *sk, u64 seq) { struct dccp_sock *dp = dccp_sk(sk); - dp->dccps_awh = dp->dccps_gss = seq; - dccp_set_seqno(&dp->dccps_awl, - (dp->dccps_gss - - dccp_msk(sk)->dccpms_sequence_window + 1)); + dp->dccps_gss = seq; + /* Ack validity window depends on local Sequence Window value (7.5.1) */ + dp->dccps_awl = SUB48(ADD48(dp->dccps_gss, 1), dp->dccps_l_seq_win); + dp->dccps_awh = dp->dccps_gss; } static inline int dccp_ack_pending(const struct sock *sk) diff --git a/net/dccp/feat.c b/net/dccp/feat.c index 67ffac9905f..7303f79705d 100644 --- a/net/dccp/feat.c +++ b/net/dccp/feat.c @@ -51,8 +51,17 @@ static int dccp_hdlr_ccid(struct sock *sk, u64 ccid, bool rx) static int dccp_hdlr_seq_win(struct sock *sk, u64 seq_win, bool rx) { - if (!rx) - dccp_msk(sk)->dccpms_sequence_window = seq_win; + struct dccp_sock *dp = dccp_sk(sk); + + if (rx) { + dp->dccps_r_seq_win = seq_win; + /* propagate changes to update SWL/SWH */ + dccp_update_gsr(sk, dp->dccps_gsr); + } else { + dp->dccps_l_seq_win = seq_win; + /* propagate changes to update AWL */ + dccp_update_gss(sk, dp->dccps_gss); + } return 0; } diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 6821ae33dd3..5ca49cec95f 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -42,11 +42,6 @@ struct inet_timewait_death_row dccp_death_row = { EXPORT_SYMBOL_GPL(dccp_death_row); -void dccp_minisock_init(struct dccp_minisock *dmsk) -{ - dmsk->dccpms_sequence_window = sysctl_dccp_feat_sequence_window; -} - void dccp_time_wait(struct sock *sk, int state, int timeo) { struct inet_timewait_sock *tw = NULL; @@ -110,7 +105,6 @@ struct sock *dccp_create_openreq_child(struct sock *sk, struct dccp_request_sock *dreq = dccp_rsk(req); struct inet_connection_sock *newicsk = inet_csk(newsk); struct dccp_sock *newdp = dccp_sk(newsk); - struct dccp_minisock *newdmsk = dccp_msk(newsk); newdp->dccps_role = DCCP_ROLE_SERVER; newdp->dccps_hc_rx_ackvec = NULL; @@ -128,10 +122,6 @@ struct sock *dccp_create_openreq_child(struct sock *sk, * Initialize S.GAR := S.ISS * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookies */ - - /* See dccp_v4_conn_request */ - newdmsk->dccpms_sequence_window = req->rcv_wnd; - newdp->dccps_gar = newdp->dccps_iss = dreq->dreq_iss; dccp_update_gss(newsk, dreq->dreq_iss); @@ -290,7 +280,6 @@ int dccp_reqsk_init(struct request_sock *req, inet_rsk(req)->rmt_port = dccp_hdr(skb)->dccph_sport; inet_rsk(req)->loc_port = dccp_hdr(skb)->dccph_dport; inet_rsk(req)->acked = 0; - req->rcv_wnd = sysctl_dccp_feat_sequence_window; dreq->dreq_timestamp_echo = 0; /* inherit feature negotiation options from listening socket */ diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 945b4d5d23b..314a1b5c033 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -174,8 +174,6 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) struct dccp_sock *dp = dccp_sk(sk); struct inet_connection_sock *icsk = inet_csk(sk); - dccp_minisock_init(&dp->dccps_minisock); - icsk->icsk_rto = DCCP_TIMEOUT_INIT; icsk->icsk_syn_retries = sysctl_dccp_request_retries; sk->sk_state = DCCP_CLOSED; -- GitLab From 883ca833e5fb814fb03426c9d35e5489ce43e8da Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Fri, 16 Jan 2009 23:36:32 +0000 Subject: [PATCH 0342/4982] dccp: Initialisation and type-checking of feature sysctls This patch takes care of initialising and type-checking sysctls related to feature negotiation. Type checking is important since some of the sysctls now directly impact the feature-negotiation process. The sysctls are initialised with the known default values for each feature. For the type-checking the value constraints from RFC 4340 are used: * Sequence Window uses the specified Wmin=32, the maximum is ulong (4 bytes), tested and confirmed that it works up to 4294967295 - for Gbps speed; * Ack Ratio is between 0 .. 0xffff (2-byte unsigned integer); * CCIDs are between 0 .. 255; * request_retries, retries1, retries2 also between 0..255 for good measure; * tx_qlen is checked to be non-negative; * sync_ratelimit remains as before. Notes: ------ 1. Die s@sysctl_dccp_feat@sysctl_dccp@g since the sysctls are now in feat.c. 2. As pointed out by Arnaldo, the pattern of type-checking repeats itself in other places, sometimes with exactly the same kind of definitions (e.g. "static int zero;"). It may be a good idea (kernel janitors?) to consolidate type checking. For the sake of keeping the changeset small and in order not to affect other subsystems, I have not strived to generalise here. Signed-off-by: Gerrit Renker Acked-by: Ian McDonald Signed-off-by: David S. Miller --- include/linux/dccp.h | 8 -------- net/dccp/dccp.h | 3 --- net/dccp/feat.c | 11 ++++++++--- net/dccp/feat.h | 8 ++++++++ net/dccp/options.c | 4 ---- net/dccp/sysctl.c | 43 ++++++++++++++++++++++++++++++------------- 6 files changed, 46 insertions(+), 31 deletions(-) diff --git a/include/linux/dccp.h b/include/linux/dccp.h index 7a0502ab383..7434a8353e2 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -355,14 +355,6 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb) return __dccp_hdr_len(dccp_hdr(skb)); } - -/* initial values for each feature */ -#define DCCPF_INITIAL_SEQUENCE_WINDOW 100 -#define DCCPF_INITIAL_ACK_RATIO 2 -#define DCCPF_INITIAL_CCID DCCPC_CCID2 -/* FIXME: for now we're default to 1 but it should really be 0 */ -#define DCCPF_INITIAL_SEND_NDP_COUNT 1 - /** * struct dccp_request_sock - represent DCCP-specific connection request * @dreq_inet_rsk: structure inherited from diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 04ae91898a6..44a5bc6f678 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -95,9 +95,6 @@ extern void dccp_time_wait(struct sock *sk, int state, int timeo); extern int sysctl_dccp_request_retries; extern int sysctl_dccp_retries1; extern int sysctl_dccp_retries2; -extern int sysctl_dccp_feat_sequence_window; -extern int sysctl_dccp_feat_rx_ccid; -extern int sysctl_dccp_feat_tx_ccid; extern int sysctl_dccp_tx_qlen; extern int sysctl_dccp_sync_ratelimit; diff --git a/net/dccp/feat.c b/net/dccp/feat.c index 7303f79705d..12006e9b247 100644 --- a/net/dccp/feat.c +++ b/net/dccp/feat.c @@ -25,6 +25,11 @@ #include "ccid.h" #include "feat.h" +/* feature-specific sysctls - initialised to the defaults from RFC 4340, 6.4 */ +unsigned long sysctl_dccp_sequence_window __read_mostly = 100; +int sysctl_dccp_rx_ccid __read_mostly = 2, + sysctl_dccp_tx_ccid __read_mostly = 2; + /* * Feature activation handlers. * @@ -1146,7 +1151,7 @@ int dccp_feat_init(struct sock *sk) /* Non-negotiable (NN) features */ rc = __feat_register_nn(fn, DCCPF_SEQUENCE_WINDOW, 0, - sysctl_dccp_feat_sequence_window); + sysctl_dccp_sequence_window); if (rc) return rc; @@ -1172,8 +1177,8 @@ int dccp_feat_init(struct sock *sk) ccid_get_builtin_ccids(&rx.val, &rx.len)) return -ENOBUFS; - if (!dccp_feat_prefer(sysctl_dccp_feat_tx_ccid, tx.val, tx.len) || - !dccp_feat_prefer(sysctl_dccp_feat_rx_ccid, rx.val, rx.len)) + if (!dccp_feat_prefer(sysctl_dccp_tx_ccid, tx.val, tx.len) || + !dccp_feat_prefer(sysctl_dccp_rx_ccid, rx.val, rx.len)) goto free_ccid_lists; rc = __feat_register_sp(fn, DCCPF_CCID, true, false, tx.val, tx.len); diff --git a/net/dccp/feat.h b/net/dccp/feat.h index 5e7b8481cd0..40aa7a10bd5 100644 --- a/net/dccp/feat.h +++ b/net/dccp/feat.h @@ -100,6 +100,13 @@ struct ccid_dependency { u8 val; }; +/* + * Sysctls to seed defaults for feature negotiation + */ +extern unsigned long sysctl_dccp_sequence_window; +extern int sysctl_dccp_rx_ccid; +extern int sysctl_dccp_tx_ccid; + #ifdef CONFIG_IP_DCCP_DEBUG extern const char *dccp_feat_typename(const u8 type); extern const char *dccp_feat_name(const u8 feat); @@ -114,6 +121,7 @@ static inline void dccp_feat_debug(const u8 type, const u8 feat, const u8 val) #endif /* CONFIG_IP_DCCP_DEBUG */ extern int dccp_feat_init(struct sock *sk); +extern void dccp_feat_initialise_sysctls(void); extern int dccp_feat_register_sp(struct sock *sk, u8 feat, u8 is_local, u8 const *list, u8 len); extern int dccp_feat_register_nn(struct sock *sk, u8 feat, u64 val); diff --git a/net/dccp/options.c b/net/dccp/options.c index 7b1165c21f5..3e2726c7182 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -23,10 +23,6 @@ #include "dccp.h" #include "feat.h" -int sysctl_dccp_feat_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW; -int sysctl_dccp_feat_rx_ccid = DCCPF_INITIAL_CCID; -int sysctl_dccp_feat_tx_ccid = DCCPF_INITIAL_CCID; - u64 dccp_decode_value_var(const u8 *bf, const u8 len) { u64 value = 0; diff --git a/net/dccp/sysctl.c b/net/dccp/sysctl.c index 018e210875e..a5a1856234e 100644 --- a/net/dccp/sysctl.c +++ b/net/dccp/sysctl.c @@ -18,55 +18,72 @@ #error This file should not be compiled without CONFIG_SYSCTL defined #endif +/* Boundary values */ +static int zero = 0, + u8_max = 0xFF; +static unsigned long seqw_min = 32; + static struct ctl_table dccp_default_table[] = { { .procname = "seq_window", - .data = &sysctl_dccp_feat_sequence_window, - .maxlen = sizeof(sysctl_dccp_feat_sequence_window), + .data = &sysctl_dccp_sequence_window, + .maxlen = sizeof(sysctl_dccp_sequence_window), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = proc_doulongvec_minmax, + .extra1 = &seqw_min, /* RFC 4340, 7.5.2 */ }, { .procname = "rx_ccid", - .data = &sysctl_dccp_feat_rx_ccid, - .maxlen = sizeof(sysctl_dccp_feat_rx_ccid), + .data = &sysctl_dccp_rx_ccid, + .maxlen = sizeof(sysctl_dccp_rx_ccid), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, + .extra2 = &u8_max, /* RFC 4340, 10. */ }, { .procname = "tx_ccid", - .data = &sysctl_dccp_feat_tx_ccid, - .maxlen = sizeof(sysctl_dccp_feat_tx_ccid), + .data = &sysctl_dccp_tx_ccid, + .maxlen = sizeof(sysctl_dccp_tx_ccid), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, + .extra2 = &u8_max, /* RFC 4340, 10. */ }, { .procname = "request_retries", .data = &sysctl_dccp_request_retries, .maxlen = sizeof(sysctl_dccp_request_retries), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, + .extra2 = &u8_max, }, { .procname = "retries1", .data = &sysctl_dccp_retries1, .maxlen = sizeof(sysctl_dccp_retries1), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, + .extra2 = &u8_max, }, { .procname = "retries2", .data = &sysctl_dccp_retries2, .maxlen = sizeof(sysctl_dccp_retries2), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, + .extra2 = &u8_max, }, { .procname = "tx_qlen", .data = &sysctl_dccp_tx_qlen, .maxlen = sizeof(sysctl_dccp_tx_qlen), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, }, { .procname = "sync_ratelimit", -- GitLab From f3f3abb62ccb1a1c77bcce855c04e12356e6ac95 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Fri, 16 Jan 2009 23:36:33 +0000 Subject: [PATCH 0343/4982] dccp: Debugging functions for feature negotiation Since all feature-negotiation processing now takes place in feat.c, functions for producing verbose debugging output are concentrated there. New functions to print out values, entry records, and options are provided, and also a macro is defined to not always have the function name in the output line. Thanks a lot to Wei Yongjun and Giuseppe Galeota for help and discussion with an earlier revision of this patch. Signed-off-by: Gerrit Renker Acked-by: Ian McDonald Signed-off-by: David S. Miller --- net/dccp/dccp.h | 2 + net/dccp/feat.c | 149 ++++++++++++++++++++++++++++++++------------- net/dccp/feat.h | 13 ---- net/dccp/options.c | 4 -- 4 files changed, 109 insertions(+), 59 deletions(-) diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 44a5bc6f678..08a569ff02d 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -42,9 +42,11 @@ extern int dccp_debug; #define dccp_pr_debug(format, a...) DCCP_PR_DEBUG(dccp_debug, format, ##a) #define dccp_pr_debug_cat(format, a...) DCCP_PRINTK(dccp_debug, format, ##a) +#define dccp_debug(fmt, a...) dccp_pr_debug_cat(KERN_DEBUG fmt, ##a) #else #define dccp_pr_debug(format, a...) #define dccp_pr_debug_cat(format, a...) +#define dccp_debug(format, a...) #endif extern struct inet_hashinfo dccp_hashinfo; diff --git a/net/dccp/feat.c b/net/dccp/feat.c index 12006e9b247..b04160a2eea 100644 --- a/net/dccp/feat.c +++ b/net/dccp/feat.c @@ -208,6 +208,100 @@ static int dccp_feat_default_value(u8 feat_num) return idx < 0 ? 0 : dccp_feat_table[idx].default_value; } +/* + * Debugging and verbose-printing section + */ +static const char *dccp_feat_fname(const u8 feat) +{ + static const char *feature_names[] = { + [DCCPF_RESERVED] = "Reserved", + [DCCPF_CCID] = "CCID", + [DCCPF_SHORT_SEQNOS] = "Allow Short Seqnos", + [DCCPF_SEQUENCE_WINDOW] = "Sequence Window", + [DCCPF_ECN_INCAPABLE] = "ECN Incapable", + [DCCPF_ACK_RATIO] = "Ack Ratio", + [DCCPF_SEND_ACK_VECTOR] = "Send ACK Vector", + [DCCPF_SEND_NDP_COUNT] = "Send NDP Count", + [DCCPF_MIN_CSUM_COVER] = "Min. Csum Coverage", + [DCCPF_DATA_CHECKSUM] = "Send Data Checksum", + }; + if (feat > DCCPF_DATA_CHECKSUM && feat < DCCPF_MIN_CCID_SPECIFIC) + return feature_names[DCCPF_RESERVED]; + + if (feat == DCCPF_SEND_LEV_RATE) + return "Send Loss Event Rate"; + if (feat >= DCCPF_MIN_CCID_SPECIFIC) + return "CCID-specific"; + + return feature_names[feat]; +} + +static const char *dccp_feat_sname[] = { "DEFAULT", "INITIALISING", "CHANGING", + "UNSTABLE", "STABLE" }; + +#ifdef CONFIG_IP_DCCP_DEBUG +static const char *dccp_feat_oname(const u8 opt) +{ + switch (opt) { + case DCCPO_CHANGE_L: return "Change_L"; + case DCCPO_CONFIRM_L: return "Confirm_L"; + case DCCPO_CHANGE_R: return "Change_R"; + case DCCPO_CONFIRM_R: return "Confirm_R"; + } + return NULL; +} + +static void dccp_feat_printval(u8 feat_num, dccp_feat_val const *val) +{ + u8 i, type = dccp_feat_type(feat_num); + + if (val == NULL || (type == FEAT_SP && val->sp.vec == NULL)) + dccp_pr_debug_cat("(NULL)"); + else if (type == FEAT_SP) + for (i = 0; i < val->sp.len; i++) + dccp_pr_debug_cat("%s%u", i ? " " : "", val->sp.vec[i]); + else if (type == FEAT_NN) + dccp_pr_debug_cat("%llu", (unsigned long long)val->nn); + else + dccp_pr_debug_cat("unknown type %u", type); +} + +static void dccp_feat_printvals(u8 feat_num, u8 *list, u8 len) +{ + u8 type = dccp_feat_type(feat_num); + dccp_feat_val fval = { .sp.vec = list, .sp.len = len }; + + if (type == FEAT_NN) + fval.nn = dccp_decode_value_var(list, len); + dccp_feat_printval(feat_num, &fval); +} + +static void dccp_feat_print_entry(struct dccp_feat_entry const *entry) +{ + dccp_debug(" * %s %s = ", entry->is_local ? "local" : "remote", + dccp_feat_fname(entry->feat_num)); + dccp_feat_printval(entry->feat_num, &entry->val); + dccp_pr_debug_cat(", state=%s %s\n", dccp_feat_sname[entry->state], + entry->needs_confirm ? "(Confirm pending)" : ""); +} + +#define dccp_feat_print_opt(opt, feat, val, len, mandatory) do { \ + dccp_pr_debug("%s(%s, ", dccp_feat_oname(opt), dccp_feat_fname(feat));\ + dccp_feat_printvals(feat, val, len); \ + dccp_pr_debug_cat(") %s\n", mandatory ? "!" : ""); } while (0) + +#define dccp_feat_print_fnlist(fn_list) { \ + const struct dccp_feat_entry *___entry; \ + \ + dccp_pr_debug("List Dump:\n"); \ + list_for_each_entry(___entry, fn_list, node) \ + dccp_feat_print_entry(___entry); \ +} +#else /* ! CONFIG_IP_DCCP_DEBUG */ +#define dccp_feat_print_opt(opt, feat, val, len, mandatory) +#define dccp_feat_print_fnlist(fn_list) +#endif + static int __dccp_feat_activate(struct sock *sk, const int idx, const bool is_local, dccp_feat_val const *fval) { @@ -240,6 +334,10 @@ static int __dccp_feat_activate(struct sock *sk, const int idx, /* Location is RX if this is a local-RX or remote-TX feature */ rx = (is_local == (dccp_feat_table[idx].rxtx == FEAT_AT_RX)); + dccp_debug(" -> activating %s %s, %sval=%llu\n", rx ? "RX" : "TX", + dccp_feat_fname(dccp_feat_table[idx].feat_num), + fval ? "" : "default ", (unsigned long long)val); + return dccp_feat_table[idx].activation_hdlr(sk, val, rx); } @@ -544,6 +642,7 @@ int dccp_feat_insert_opts(struct dccp_sock *dp, struct dccp_request_sock *dreq, return -1; } } + dccp_feat_print_opt(opt, pos->feat_num, ptr, len, 0); if (dccp_insert_fn_opt(skb, opt, pos->feat_num, ptr, len, rpt)) return -1; @@ -797,6 +896,7 @@ int dccp_feat_finalise_settings(struct dccp_sock *dp) while (i--) if (ccids[i] > 0 && dccp_feat_propagate_ccid(fn, ccids[i], i)) return -1; + dccp_feat_print_fnlist(fn); return 0; } @@ -915,6 +1015,8 @@ static u8 dccp_feat_change_recv(struct list_head *fn, u8 is_mandatory, u8 opt, if (len == 0 || type == FEAT_UNKNOWN) /* 6.1 and 6.6.8 */ goto unknown_feature_or_value; + dccp_feat_print_opt(opt, feat, val, len, is_mandatory); + /* * Negotiation of NN features: Change R is invalid, so there is no * simultaneous negotiation; hence we do not look up in the list. @@ -1020,6 +1122,8 @@ static u8 dccp_feat_confirm_recv(struct list_head *fn, u8 is_mandatory, u8 opt, const bool local = (opt == DCCPO_CONFIRM_R); struct dccp_feat_entry *entry = dccp_feat_list_lookup(fn, feat, local); + dccp_feat_print_opt(opt, feat, val, len, is_mandatory); + if (entry == NULL) { /* nothing queued: ignore or handle error */ if (is_mandatory && type == FEAT_UNKNOWN) return DCCP_RESET_CODE_MANDATORY_ERROR; @@ -1217,9 +1321,10 @@ int dccp_feat_activate_values(struct sock *sk, struct list_head *fn_list) goto activation_failed; } if (cur->state != FEAT_STABLE) { - DCCP_CRIT("Negotiation of %s %u failed in state %u", + DCCP_CRIT("Negotiation of %s %s failed in state %s", cur->is_local ? "local" : "remote", - cur->feat_num, cur->state); + dccp_feat_fname(cur->feat_num), + dccp_feat_sname[cur->state]); goto activation_failed; } fvals[idx][cur->is_local] = &cur->val; @@ -1260,43 +1365,3 @@ activation_failed: dp->dccps_hc_rx_ackvec = NULL; return -1; } - -#ifdef CONFIG_IP_DCCP_DEBUG -const char *dccp_feat_typename(const u8 type) -{ - switch(type) { - case DCCPO_CHANGE_L: return("ChangeL"); - case DCCPO_CONFIRM_L: return("ConfirmL"); - case DCCPO_CHANGE_R: return("ChangeR"); - case DCCPO_CONFIRM_R: return("ConfirmR"); - /* the following case must not appear in feature negotation */ - default: dccp_pr_debug("unknown type %d [BUG!]\n", type); - } - return NULL; -} - -const char *dccp_feat_name(const u8 feat) -{ - static const char *feature_names[] = { - [DCCPF_RESERVED] = "Reserved", - [DCCPF_CCID] = "CCID", - [DCCPF_SHORT_SEQNOS] = "Allow Short Seqnos", - [DCCPF_SEQUENCE_WINDOW] = "Sequence Window", - [DCCPF_ECN_INCAPABLE] = "ECN Incapable", - [DCCPF_ACK_RATIO] = "Ack Ratio", - [DCCPF_SEND_ACK_VECTOR] = "Send ACK Vector", - [DCCPF_SEND_NDP_COUNT] = "Send NDP Count", - [DCCPF_MIN_CSUM_COVER] = "Min. Csum Coverage", - [DCCPF_DATA_CHECKSUM] = "Send Data Checksum", - }; - if (feat > DCCPF_DATA_CHECKSUM && feat < DCCPF_MIN_CCID_SPECIFIC) - return feature_names[DCCPF_RESERVED]; - - if (feat == DCCPF_SEND_LEV_RATE) - return "Send Loss Event Rate"; - if (feat >= DCCPF_MIN_CCID_SPECIFIC) - return "CCID-specific"; - - return feature_names[feat]; -} -#endif /* CONFIG_IP_DCCP_DEBUG */ diff --git a/net/dccp/feat.h b/net/dccp/feat.h index 40aa7a10bd5..f96721619de 100644 --- a/net/dccp/feat.h +++ b/net/dccp/feat.h @@ -107,19 +107,6 @@ extern unsigned long sysctl_dccp_sequence_window; extern int sysctl_dccp_rx_ccid; extern int sysctl_dccp_tx_ccid; -#ifdef CONFIG_IP_DCCP_DEBUG -extern const char *dccp_feat_typename(const u8 type); -extern const char *dccp_feat_name(const u8 feat); - -static inline void dccp_feat_debug(const u8 type, const u8 feat, const u8 val) -{ - dccp_pr_debug("%s(%s (%d), %d)\n", dccp_feat_typename(type), - dccp_feat_name(feat), feat, val); -} -#else -#define dccp_feat_debug(type, feat, val) -#endif /* CONFIG_IP_DCCP_DEBUG */ - extern int dccp_feat_init(struct sock *sk); extern void dccp_feat_initialise_sysctls(void); extern int dccp_feat_register_sp(struct sock *sk, u8 feat, u8 is_local, diff --git a/net/dccp/options.c b/net/dccp/options.c index 3e2726c7182..1b08cae9c65 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -498,10 +498,6 @@ int dccp_insert_fn_opt(struct sk_buff *skb, u8 type, u8 feat, *to++ = *val; if (len) memcpy(to, val, len); - - dccp_pr_debug("%s(%s (%d), ...), length %d\n", - dccp_feat_typename(type), - dccp_feat_name(feat), feat, len); return 0; } -- GitLab From 78b6f4ce58d1c85190003840912cc9097cbb8146 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 18 Jan 2009 21:49:45 -0800 Subject: [PATCH 0344/4982] ixgbe: Replace LRO with GRO This patch makes ixgbe invoke the GRO hooks instead of LRO. As GRO has a compatible external interface to LRO this is a very straightforward replacement. As GRO uses the napi structure to track the held packets, I've modified the code paths involved to pass that along. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- drivers/net/Kconfig | 1 - drivers/net/ixgbe/ixgbe.h | 9 ---- drivers/net/ixgbe/ixgbe_ethtool.c | 11 ----- drivers/net/ixgbe/ixgbe_main.c | 81 +++++-------------------------- 4 files changed, 13 insertions(+), 89 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 9fe8cb7d43a..eccb89770f5 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2444,7 +2444,6 @@ config ENIC config IXGBE tristate "Intel(R) 10GbE PCI Express adapters support" depends on PCI && INET - select INET_LRO ---help--- This driver supports Intel(R) 10GbE PCI Express family of adapters. For more information on how to identify your adapter, go diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index e112008f39c..6ac361a4b8a 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -31,7 +31,6 @@ #include #include #include -#include #include #include "ixgbe_type.h" @@ -88,9 +87,6 @@ #define IXGBE_TX_FLAGS_VLAN_PRIO_MASK 0x0000e000 #define IXGBE_TX_FLAGS_VLAN_SHIFT 16 -#define IXGBE_MAX_LRO_DESCRIPTORS 8 -#define IXGBE_MAX_LRO_AGGREGATE 32 - /* wrapper around a pointer to a socket buffer, * so a DMA handle can be stored along with the buffer */ struct ixgbe_tx_buffer { @@ -142,8 +138,6 @@ struct ixgbe_ring { /* cpu for tx queue */ int cpu; #endif - struct net_lro_mgr lro_mgr; - bool lro_used; struct ixgbe_queue_stats stats; u16 v_idx; /* maps directly to the index for this ring in the hardware * vector array, can also be used for finding the bit in EICR @@ -301,9 +295,6 @@ struct ixgbe_adapter { unsigned long state; u64 tx_busy; - u64 lro_aggregated; - u64 lro_flushed; - u64 lro_no_desc; unsigned int tx_ring_count; unsigned int rx_ring_count; diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 67f87a79154..4f6b5dfc78a 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -89,8 +89,6 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = { {"rx_header_split", IXGBE_STAT(rx_hdr_split)}, {"alloc_rx_page_failed", IXGBE_STAT(alloc_rx_page_failed)}, {"alloc_rx_buff_failed", IXGBE_STAT(alloc_rx_buff_failed)}, - {"lro_aggregated", IXGBE_STAT(lro_aggregated)}, - {"lro_flushed", IXGBE_STAT(lro_flushed)}, }; #define IXGBE_QUEUE_STATS_LEN \ @@ -808,15 +806,6 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev, int stat_count = sizeof(struct ixgbe_queue_stats) / sizeof(u64); int j, k; int i; - u64 aggregated = 0, flushed = 0, no_desc = 0; - for (i = 0; i < adapter->num_rx_queues; i++) { - aggregated += adapter->rx_ring[i].lro_mgr.stats.aggregated; - flushed += adapter->rx_ring[i].lro_mgr.stats.flushed; - no_desc += adapter->rx_ring[i].lro_mgr.stats.no_desc; - } - adapter->lro_aggregated = aggregated; - adapter->lro_flushed = flushed; - adapter->lro_no_desc = no_desc; ixgbe_update_stats(adapter); for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) { diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 7489094bbbc..f7b592eff68 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -403,23 +403,20 @@ static int __ixgbe_notify_dca(struct device *dev, void *data) * @rx_ring: rx descriptor ring (for a specific queue) to setup * @rx_desc: rx descriptor **/ -static void ixgbe_receive_skb(struct ixgbe_adapter *adapter, +static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector, struct sk_buff *skb, u8 status, - struct ixgbe_ring *ring, union ixgbe_adv_rx_desc *rx_desc) { + struct ixgbe_adapter *adapter = q_vector->adapter; + struct napi_struct *napi = &q_vector->napi; bool is_vlan = (status & IXGBE_RXD_STAT_VP); u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan); - if (adapter->netdev->features & NETIF_F_LRO && - skb->ip_summed == CHECKSUM_UNNECESSARY) { + if (skb->ip_summed == CHECKSUM_UNNECESSARY) { if (adapter->vlgrp && is_vlan && (tag != 0)) - lro_vlan_hwaccel_receive_skb(&ring->lro_mgr, skb, - adapter->vlgrp, tag, - rx_desc); + vlan_gro_receive(napi, adapter->vlgrp, tag, skb); else - lro_receive_skb(&ring->lro_mgr, skb, rx_desc); - ring->lro_used = true; + napi_gro_receive(napi, skb); } else { if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) { if (adapter->vlgrp && is_vlan && (tag != 0)) @@ -574,10 +571,11 @@ static inline u16 ixgbe_get_pkt_info(union ixgbe_adv_rx_desc *rx_desc) return rx_desc->wb.lower.lo_dword.hs_rss.pkt_info; } -static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter, +static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, struct ixgbe_ring *rx_ring, int *work_done, int work_to_do) { + struct ixgbe_adapter *adapter = q_vector->adapter; struct pci_dev *pdev = adapter->pdev; union ixgbe_adv_rx_desc *rx_desc, *next_rxd; struct ixgbe_rx_buffer *rx_buffer_info, *next_buffer; @@ -678,7 +676,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter, total_rx_packets++; skb->protocol = eth_type_trans(skb, adapter->netdev); - ixgbe_receive_skb(adapter, skb, staterr, rx_ring, rx_desc); + ixgbe_receive_skb(q_vector, skb, staterr, rx_desc); next_desc: rx_desc->wb.upper.status_error = 0; @@ -696,11 +694,6 @@ next_desc: staterr = le32_to_cpu(rx_desc->wb.upper.status_error); } - if (rx_ring->lro_used) { - lro_flush_all(&rx_ring->lro_mgr); - rx_ring->lro_used = false; - } - rx_ring->next_to_clean = i; cleaned_count = IXGBE_DESC_UNUSED(rx_ring); @@ -1052,7 +1045,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget) ixgbe_update_rx_dca(adapter, rx_ring); #endif - ixgbe_clean_rx_irq(adapter, rx_ring, &work_done, budget); + ixgbe_clean_rx_irq(q_vector, rx_ring, &work_done, budget); /* If all Rx work done, exit the polling mode */ if (work_done < budget) { @@ -1095,7 +1088,7 @@ static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget) if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) ixgbe_update_rx_dca(adapter, rx_ring); #endif - ixgbe_clean_rx_irq(adapter, rx_ring, &work_done, budget); + ixgbe_clean_rx_irq(q_vector, rx_ring, &work_done, budget); enable_mask |= rx_ring->v_idx; r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, r_idx + 1); @@ -1568,33 +1561,6 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, int index) IXGBE_WRITE_REG(&adapter->hw, IXGBE_SRRCTL(index), srrctl); } -/** - * ixgbe_get_skb_hdr - helper function for LRO header processing - * @skb: pointer to sk_buff to be added to LRO packet - * @iphdr: pointer to ip header structure - * @tcph: pointer to tcp header structure - * @hdr_flags: pointer to header flags - * @priv: private data - **/ -static int ixgbe_get_skb_hdr(struct sk_buff *skb, void **iphdr, void **tcph, - u64 *hdr_flags, void *priv) -{ - union ixgbe_adv_rx_desc *rx_desc = priv; - - /* Verify that this is a valid IPv4 TCP packet */ - if (!((ixgbe_get_pkt_info(rx_desc) & IXGBE_RXDADV_PKTTYPE_IPV4) && - (ixgbe_get_pkt_info(rx_desc) & IXGBE_RXDADV_PKTTYPE_TCP))) - return -1; - - /* Set network headers */ - skb_reset_network_header(skb); - skb_set_transport_header(skb, ip_hdrlen(skb)); - *iphdr = ip_hdr(skb); - *tcph = tcp_hdr(skb); - *hdr_flags = LRO_IPV4 | LRO_TCP; - return 0; -} - #define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \ (((S) & (PAGE_SIZE - 1)) ? 1 : 0)) @@ -1666,16 +1632,6 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) adapter->rx_ring[i].head = IXGBE_RDH(j); adapter->rx_ring[i].tail = IXGBE_RDT(j); adapter->rx_ring[i].rx_buf_len = rx_buf_len; - /* Intitial LRO Settings */ - adapter->rx_ring[i].lro_mgr.max_aggr = IXGBE_MAX_LRO_AGGREGATE; - adapter->rx_ring[i].lro_mgr.max_desc = IXGBE_MAX_LRO_DESCRIPTORS; - adapter->rx_ring[i].lro_mgr.get_skb_header = ixgbe_get_skb_hdr; - adapter->rx_ring[i].lro_mgr.features = LRO_F_EXTRACT_VLAN_ID; - if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) - adapter->rx_ring[i].lro_mgr.features |= LRO_F_NAPI; - adapter->rx_ring[i].lro_mgr.dev = adapter->netdev; - adapter->rx_ring[i].lro_mgr.ip_summed = CHECKSUM_UNNECESSARY; - adapter->rx_ring[i].lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY; ixgbe_configure_srrctl(adapter, j); } @@ -2310,7 +2266,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget) #endif tx_cleaned = ixgbe_clean_tx_irq(adapter, adapter->tx_ring); - ixgbe_clean_rx_irq(adapter, adapter->rx_ring, &work_done, budget); + ixgbe_clean_rx_irq(q_vector, adapter->rx_ring, &work_done, budget); if (tx_cleaned) work_done = budget; @@ -2926,12 +2882,6 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter, struct pci_dev *pdev = adapter->pdev; int size; - size = sizeof(struct net_lro_desc) * IXGBE_MAX_LRO_DESCRIPTORS; - rx_ring->lro_mgr.lro_arr = vmalloc(size); - if (!rx_ring->lro_mgr.lro_arr) - return -ENOMEM; - memset(rx_ring->lro_mgr.lro_arr, 0, size); - size = sizeof(struct ixgbe_rx_buffer) * rx_ring->count; rx_ring->rx_buffer_info = vmalloc(size); if (!rx_ring->rx_buffer_info) { @@ -2960,8 +2910,6 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter, return 0; alloc_failed: - vfree(rx_ring->lro_mgr.lro_arr); - rx_ring->lro_mgr.lro_arr = NULL; return -ENOMEM; } @@ -3039,9 +2987,6 @@ void ixgbe_free_rx_resources(struct ixgbe_adapter *adapter, { struct pci_dev *pdev = adapter->pdev; - vfree(rx_ring->lro_mgr.lro_arr); - rx_ring->lro_mgr.lro_arr = NULL; - ixgbe_clean_rx_ring(adapter, rx_ring); vfree(rx_ring->rx_buffer_info); @@ -4141,7 +4086,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, netdev->features |= NETIF_F_IPV6_CSUM; netdev->features |= NETIF_F_TSO; netdev->features |= NETIF_F_TSO6; - netdev->features |= NETIF_F_LRO; + netdev->features |= NETIF_F_GRO; netdev->vlan_features |= NETIF_F_TSO; netdev->vlan_features |= NETIF_F_TSO6; -- GitLab From da3bc07171dff957906cbe2ad5abb443eccf57c4 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 18 Jan 2009 21:50:16 -0800 Subject: [PATCH 0345/4982] sfc: Replace LRO with GRO This patch makes sfc invoke the GRO hooks instead of LRO. As GRO has a compatible external interface to LRO this is a very straightforward replacement. Everything should appear identical to the user except that the offload is now controlled by the GRO ethtool option instead of LRO. I've kept the lro module parameter as is since that's for compatibility only. I have eliminated efx_rx_mk_skb as the GRO layer can take care of all packets regardless of whether GRO is enabled or not. So the only case where we don't call GRO is if the packet checksum is absent. This is to keep the behaviour changes of the patch to a minimum. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- drivers/net/sfc/Kconfig | 1 - drivers/net/sfc/efx.c | 11 +- drivers/net/sfc/net_driver.h | 9 -- drivers/net/sfc/rx.c | 207 +++-------------------------------- drivers/net/sfc/rx.h | 3 - drivers/net/sfc/sfe4001.c | 1 + drivers/net/sfc/tenxpress.c | 1 + 7 files changed, 19 insertions(+), 214 deletions(-) diff --git a/drivers/net/sfc/Kconfig b/drivers/net/sfc/Kconfig index c535408ad6b..12a82966b57 100644 --- a/drivers/net/sfc/Kconfig +++ b/drivers/net/sfc/Kconfig @@ -2,7 +2,6 @@ config SFC tristate "Solarflare Solarstorm SFC4000 support" depends on PCI && INET select MII - select INET_LRO select CRC32 select I2C select I2C_ALGOBIT diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 77aca5d67b5..3ee2a4548cb 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -182,7 +182,6 @@ static int efx_process_channel(struct efx_channel *channel, int rx_quota) channel->rx_pkt = NULL; } - efx_flush_lro(channel); efx_rx_strategy(channel); efx_fast_push_rx_descriptors(&efx->rx_queue[channel->channel]); @@ -1269,18 +1268,11 @@ static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd) static int efx_init_napi(struct efx_nic *efx) { struct efx_channel *channel; - int rc; efx_for_each_channel(channel, efx) { channel->napi_dev = efx->net_dev; - rc = efx_lro_init(&channel->lro_mgr, efx); - if (rc) - goto err; } return 0; - err: - efx_fini_napi(efx); - return rc; } static void efx_fini_napi(struct efx_nic *efx) @@ -1288,7 +1280,6 @@ static void efx_fini_napi(struct efx_nic *efx) struct efx_channel *channel; efx_for_each_channel(channel, efx) { - efx_lro_fini(&channel->lro_mgr); channel->napi_dev = NULL; } } @@ -2097,7 +2088,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev, net_dev->features |= (NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_TSO); if (lro) - net_dev->features |= NETIF_F_LRO; + net_dev->features |= NETIF_F_GRO; /* Mask for features that also apply to VLAN devices */ net_dev->vlan_features |= (NETIF_F_ALL_CSUM | NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_TSO); diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 5f255f75754..8643505788c 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -25,15 +25,11 @@ #include #include #include -#include #include #include "enum.h" #include "bitfield.h" -#define EFX_MAX_LRO_DESCRIPTORS 8 -#define EFX_MAX_LRO_AGGR MAX_SKB_FRAGS - /************************************************************************** * * Build definitions @@ -340,13 +336,10 @@ enum efx_rx_alloc_method { * @eventq_read_ptr: Event queue read pointer * @last_eventq_read_ptr: Last event queue read pointer value. * @eventq_magic: Event queue magic value for driver-generated test events - * @lro_mgr: LRO state * @rx_alloc_level: Watermark based heuristic counter for pushing descriptors * and diagnostic counters * @rx_alloc_push_pages: RX allocation method currently in use for pushing * descriptors - * @rx_alloc_pop_pages: RX allocation method currently in use for popping - * descriptors * @n_rx_tobe_disc: Count of RX_TOBE_DISC errors * @n_rx_ip_frag_err: Count of RX IP fragment errors * @n_rx_ip_hdr_chksum_err: Count of RX IP header checksum errors @@ -371,10 +364,8 @@ struct efx_channel { unsigned int last_eventq_read_ptr; unsigned int eventq_magic; - struct net_lro_mgr lro_mgr; int rx_alloc_level; int rx_alloc_push_pages; - int rx_alloc_pop_pages; unsigned n_rx_tobe_disc; unsigned n_rx_ip_frag_err; diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c index b8ba4bbad88..a0345b38097 100644 --- a/drivers/net/sfc/rx.c +++ b/drivers/net/sfc/rx.c @@ -99,109 +99,6 @@ static inline unsigned int efx_rx_buf_size(struct efx_nic *efx) } -/************************************************************************** - * - * Linux generic LRO handling - * - ************************************************************************** - */ - -static int efx_lro_get_skb_hdr(struct sk_buff *skb, void **ip_hdr, - void **tcpudp_hdr, u64 *hdr_flags, void *priv) -{ - struct efx_channel *channel = priv; - struct iphdr *iph; - struct tcphdr *th; - - iph = (struct iphdr *)skb->data; - if (skb->protocol != htons(ETH_P_IP) || iph->protocol != IPPROTO_TCP) - goto fail; - - th = (struct tcphdr *)(skb->data + iph->ihl * 4); - - *tcpudp_hdr = th; - *ip_hdr = iph; - *hdr_flags = LRO_IPV4 | LRO_TCP; - - channel->rx_alloc_level += RX_ALLOC_FACTOR_LRO; - return 0; -fail: - channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB; - return -1; -} - -static int efx_get_frag_hdr(struct skb_frag_struct *frag, void **mac_hdr, - void **ip_hdr, void **tcpudp_hdr, u64 *hdr_flags, - void *priv) -{ - struct efx_channel *channel = priv; - struct ethhdr *eh; - struct iphdr *iph; - - /* We support EtherII and VLAN encapsulated IPv4 */ - eh = page_address(frag->page) + frag->page_offset; - *mac_hdr = eh; - - if (eh->h_proto == htons(ETH_P_IP)) { - iph = (struct iphdr *)(eh + 1); - } else { - struct vlan_ethhdr *veh = (struct vlan_ethhdr *)eh; - if (veh->h_vlan_encapsulated_proto != htons(ETH_P_IP)) - goto fail; - - iph = (struct iphdr *)(veh + 1); - } - *ip_hdr = iph; - - /* We can only do LRO over TCP */ - if (iph->protocol != IPPROTO_TCP) - goto fail; - - *hdr_flags = LRO_IPV4 | LRO_TCP; - *tcpudp_hdr = (struct tcphdr *)((u8 *) iph + iph->ihl * 4); - - channel->rx_alloc_level += RX_ALLOC_FACTOR_LRO; - return 0; - fail: - channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB; - return -1; -} - -int efx_lro_init(struct net_lro_mgr *lro_mgr, struct efx_nic *efx) -{ - size_t s = sizeof(struct net_lro_desc) * EFX_MAX_LRO_DESCRIPTORS; - struct net_lro_desc *lro_arr; - - /* Allocate the LRO descriptors structure */ - lro_arr = kzalloc(s, GFP_KERNEL); - if (lro_arr == NULL) - return -ENOMEM; - - lro_mgr->lro_arr = lro_arr; - lro_mgr->max_desc = EFX_MAX_LRO_DESCRIPTORS; - lro_mgr->max_aggr = EFX_MAX_LRO_AGGR; - lro_mgr->frag_align_pad = EFX_PAGE_SKB_ALIGN; - - lro_mgr->get_skb_header = efx_lro_get_skb_hdr; - lro_mgr->get_frag_header = efx_get_frag_hdr; - lro_mgr->dev = efx->net_dev; - - lro_mgr->features = LRO_F_NAPI; - - /* We can pass packets up with the checksum intact */ - lro_mgr->ip_summed = CHECKSUM_UNNECESSARY; - - lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY; - - return 0; -} - -void efx_lro_fini(struct net_lro_mgr *lro_mgr) -{ - kfree(lro_mgr->lro_arr); - lro_mgr->lro_arr = NULL; -} - /** * efx_init_rx_buffer_skb - create new RX buffer using skb-based allocation * @@ -549,77 +446,31 @@ static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue, static void efx_rx_packet_lro(struct efx_channel *channel, struct efx_rx_buffer *rx_buf) { - struct net_lro_mgr *lro_mgr = &channel->lro_mgr; - void *priv = channel; + struct napi_struct *napi = &channel->napi_str; /* Pass the skb/page into the LRO engine */ if (rx_buf->page) { - struct skb_frag_struct frags; + struct napi_gro_fraginfo info; - frags.page = rx_buf->page; - frags.page_offset = efx_rx_buf_offset(rx_buf); - frags.size = rx_buf->len; + info.frags[0].page = rx_buf->page; + info.frags[0].page_offset = efx_rx_buf_offset(rx_buf); + info.frags[0].size = rx_buf->len; + info.nr_frags = 1; + info.ip_summed = CHECKSUM_UNNECESSARY; + info.len = rx_buf->len; - lro_receive_frags(lro_mgr, &frags, rx_buf->len, - rx_buf->len, priv, 0); + napi_gro_frags(napi, &info); EFX_BUG_ON_PARANOID(rx_buf->skb); rx_buf->page = NULL; } else { EFX_BUG_ON_PARANOID(!rx_buf->skb); - lro_receive_skb(lro_mgr, rx_buf->skb, priv); + napi_gro_receive(napi, rx_buf->skb); rx_buf->skb = NULL; } } -/* Allocate and construct an SKB around a struct page.*/ -static struct sk_buff *efx_rx_mk_skb(struct efx_rx_buffer *rx_buf, - struct efx_nic *efx, - int hdr_len) -{ - struct sk_buff *skb; - - /* Allocate an SKB to store the headers */ - skb = netdev_alloc_skb(efx->net_dev, hdr_len + EFX_PAGE_SKB_ALIGN); - if (unlikely(skb == NULL)) { - EFX_ERR_RL(efx, "RX out of memory for skb\n"); - return NULL; - } - - EFX_BUG_ON_PARANOID(skb_shinfo(skb)->nr_frags); - EFX_BUG_ON_PARANOID(rx_buf->len < hdr_len); - - skb->ip_summed = CHECKSUM_UNNECESSARY; - skb_reserve(skb, EFX_PAGE_SKB_ALIGN); - - skb->len = rx_buf->len; - skb->truesize = rx_buf->len + sizeof(struct sk_buff); - memcpy(skb->data, rx_buf->data, hdr_len); - skb->tail += hdr_len; - - /* Append the remaining page onto the frag list */ - if (unlikely(rx_buf->len > hdr_len)) { - struct skb_frag_struct *frag = skb_shinfo(skb)->frags; - frag->page = rx_buf->page; - frag->page_offset = efx_rx_buf_offset(rx_buf) + hdr_len; - frag->size = skb->len - hdr_len; - skb_shinfo(skb)->nr_frags = 1; - skb->data_len = frag->size; - } else { - __free_pages(rx_buf->page, efx->rx_buffer_order); - skb->data_len = 0; - } - - /* Ownership has transferred from the rx_buf to skb */ - rx_buf->page = NULL; - - /* Move past the ethernet header */ - skb->protocol = eth_type_trans(skb, efx->net_dev); - - return skb; -} - void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index, unsigned int len, bool checksummed, bool discard) { @@ -687,7 +538,6 @@ void __efx_rx_packet(struct efx_channel *channel, { struct efx_nic *efx = channel->efx; struct sk_buff *skb; - bool lro = !!(efx->net_dev->features & NETIF_F_LRO); /* If we're in loopback test, then pass the packet directly to the * loopback layer, and free the rx_buf here @@ -709,41 +559,21 @@ void __efx_rx_packet(struct efx_channel *channel, efx->net_dev); } - /* Both our generic-LRO and SFC-SSR support skb and page based - * allocation, but neither support switching from one to the - * other on the fly. If we spot that the allocation mode has - * changed, then flush the LRO state. - */ - if (unlikely(channel->rx_alloc_pop_pages != (rx_buf->page != NULL))) { - efx_flush_lro(channel); - channel->rx_alloc_pop_pages = (rx_buf->page != NULL); - } - if (likely(checksummed && lro)) { + if (likely(checksummed || rx_buf->page)) { efx_rx_packet_lro(channel, rx_buf); goto done; } - /* Form an skb if required */ - if (rx_buf->page) { - int hdr_len = min(rx_buf->len, EFX_SKB_HEADERS); - skb = efx_rx_mk_skb(rx_buf, efx, hdr_len); - if (unlikely(skb == NULL)) { - efx_free_rx_buffer(efx, rx_buf); - goto done; - } - } else { - /* We now own the SKB */ - skb = rx_buf->skb; - rx_buf->skb = NULL; - } + /* We now own the SKB */ + skb = rx_buf->skb; + rx_buf->skb = NULL; EFX_BUG_ON_PARANOID(rx_buf->page); EFX_BUG_ON_PARANOID(rx_buf->skb); EFX_BUG_ON_PARANOID(!skb); /* Set the SKB flags */ - if (unlikely(!checksummed || !efx->rx_checksum_enabled)) - skb->ip_summed = CHECKSUM_NONE; + skb->ip_summed = CHECKSUM_NONE; /* Pass the packet up */ netif_receive_skb(skb); @@ -760,7 +590,7 @@ void efx_rx_strategy(struct efx_channel *channel) enum efx_rx_alloc_method method = rx_alloc_method; /* Only makes sense to use page based allocation if LRO is enabled */ - if (!(channel->efx->net_dev->features & NETIF_F_LRO)) { + if (!(channel->efx->net_dev->features & NETIF_F_GRO)) { method = RX_ALLOC_METHOD_SKB; } else if (method == RX_ALLOC_METHOD_AUTO) { /* Constrain the rx_alloc_level */ @@ -865,11 +695,6 @@ void efx_remove_rx_queue(struct efx_rx_queue *rx_queue) rx_queue->buffer = NULL; } -void efx_flush_lro(struct efx_channel *channel) -{ - lro_flush_all(&channel->lro_mgr); -} - module_param(rx_alloc_method, int, 0644); MODULE_PARM_DESC(rx_alloc_method, "Allocation method used for RX buffers"); diff --git a/drivers/net/sfc/rx.h b/drivers/net/sfc/rx.h index 0e88a9ddc1c..42ee7555a80 100644 --- a/drivers/net/sfc/rx.h +++ b/drivers/net/sfc/rx.h @@ -17,9 +17,6 @@ void efx_remove_rx_queue(struct efx_rx_queue *rx_queue); void efx_init_rx_queue(struct efx_rx_queue *rx_queue); void efx_fini_rx_queue(struct efx_rx_queue *rx_queue); -int efx_lro_init(struct net_lro_mgr *lro_mgr, struct efx_nic *efx); -void efx_lro_fini(struct net_lro_mgr *lro_mgr); -void efx_flush_lro(struct efx_channel *channel); void efx_rx_strategy(struct efx_channel *channel); void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue); void efx_rx_work(struct work_struct *data); diff --git a/drivers/net/sfc/sfe4001.c b/drivers/net/sfc/sfe4001.c index 16b80acb999..d21d014bf0c 100644 --- a/drivers/net/sfc/sfe4001.c +++ b/drivers/net/sfc/sfe4001.c @@ -24,6 +24,7 @@ */ #include +#include #include "net_driver.h" #include "efx.h" #include "phy.h" diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index 9ecb77da954..f1365097b4f 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c @@ -8,6 +8,7 @@ */ #include +#include #include #include "efx.h" #include "mdio_10g.h" -- GitLab From 649aa95d75cbadb9f440c1b8d04c666461de326f Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Sun, 18 Jan 2009 22:03:01 -0800 Subject: [PATCH 0346/4982] typhoon: replace users of __constant_{endian} The base versions handle constant folding just fine, use them directly. Signed-off-by: Harvey Harrison Acked-by: David Dillow Signed-off-by: David S. Miller --- drivers/net/typhoon.c | 2 +- drivers/net/typhoon.h | 234 +++++++++++++++++++++--------------------- 2 files changed, 118 insertions(+), 118 deletions(-) diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index dcff5ade6d0..a8e5651f316 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -1944,7 +1944,7 @@ typhoon_start_runtime(struct typhoon *tp) goto error_out; INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_VLAN_TYPE_WRITE); - xp_cmd.parm1 = __constant_cpu_to_le16(ETH_P_8021Q); + xp_cmd.parm1 = cpu_to_le16(ETH_P_8021Q); err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL); if(err < 0) goto error_out; diff --git a/drivers/net/typhoon.h b/drivers/net/typhoon.h index dd7022ca735..673fd512591 100644 --- a/drivers/net/typhoon.h +++ b/drivers/net/typhoon.h @@ -174,18 +174,18 @@ struct tx_desc { u64 tx_addr; /* opaque for hardware, for TX_DESC */ }; __le32 processFlags; -#define TYPHOON_TX_PF_NO_CRC __constant_cpu_to_le32(0x00000001) -#define TYPHOON_TX_PF_IP_CHKSUM __constant_cpu_to_le32(0x00000002) -#define TYPHOON_TX_PF_TCP_CHKSUM __constant_cpu_to_le32(0x00000004) -#define TYPHOON_TX_PF_TCP_SEGMENT __constant_cpu_to_le32(0x00000008) -#define TYPHOON_TX_PF_INSERT_VLAN __constant_cpu_to_le32(0x00000010) -#define TYPHOON_TX_PF_IPSEC __constant_cpu_to_le32(0x00000020) -#define TYPHOON_TX_PF_VLAN_PRIORITY __constant_cpu_to_le32(0x00000040) -#define TYPHOON_TX_PF_UDP_CHKSUM __constant_cpu_to_le32(0x00000080) -#define TYPHOON_TX_PF_PAD_FRAME __constant_cpu_to_le32(0x00000100) -#define TYPHOON_TX_PF_RESERVED __constant_cpu_to_le32(0x00000e00) -#define TYPHOON_TX_PF_VLAN_MASK __constant_cpu_to_le32(0x0ffff000) -#define TYPHOON_TX_PF_INTERNAL __constant_cpu_to_le32(0xf0000000) +#define TYPHOON_TX_PF_NO_CRC cpu_to_le32(0x00000001) +#define TYPHOON_TX_PF_IP_CHKSUM cpu_to_le32(0x00000002) +#define TYPHOON_TX_PF_TCP_CHKSUM cpu_to_le32(0x00000004) +#define TYPHOON_TX_PF_TCP_SEGMENT cpu_to_le32(0x00000008) +#define TYPHOON_TX_PF_INSERT_VLAN cpu_to_le32(0x00000010) +#define TYPHOON_TX_PF_IPSEC cpu_to_le32(0x00000020) +#define TYPHOON_TX_PF_VLAN_PRIORITY cpu_to_le32(0x00000040) +#define TYPHOON_TX_PF_UDP_CHKSUM cpu_to_le32(0x00000080) +#define TYPHOON_TX_PF_PAD_FRAME cpu_to_le32(0x00000100) +#define TYPHOON_TX_PF_RESERVED cpu_to_le32(0x00000e00) +#define TYPHOON_TX_PF_VLAN_MASK cpu_to_le32(0x0ffff000) +#define TYPHOON_TX_PF_INTERNAL cpu_to_le32(0xf0000000) #define TYPHOON_TX_PF_VLAN_TAG_SHIFT 12 } __attribute__ ((packed)); @@ -203,8 +203,8 @@ struct tcpopt_desc { u8 flags; u8 numDesc; __le16 mss_flags; -#define TYPHOON_TSO_FIRST __constant_cpu_to_le16(0x1000) -#define TYPHOON_TSO_LAST __constant_cpu_to_le16(0x2000) +#define TYPHOON_TSO_FIRST cpu_to_le16(0x1000) +#define TYPHOON_TSO_LAST cpu_to_le16(0x2000) __le32 respAddrLo; __le32 bytesTx; __le32 status; @@ -222,8 +222,8 @@ struct ipsec_desc { u8 flags; u8 numDesc; __le16 ipsecFlags; -#define TYPHOON_IPSEC_GEN_IV __constant_cpu_to_le16(0x0000) -#define TYPHOON_IPSEC_USE_IV __constant_cpu_to_le16(0x0001) +#define TYPHOON_IPSEC_GEN_IV cpu_to_le16(0x0000) +#define TYPHOON_IPSEC_USE_IV cpu_to_le16(0x0001) __le32 sa1; __le32 sa2; __le32 reserved; @@ -248,41 +248,41 @@ struct rx_desc { u32 addr; /* opaque, comes from virtAddr */ u32 addrHi; /* opaque, comes from virtAddrHi */ __le32 rxStatus; -#define TYPHOON_RX_ERR_INTERNAL __constant_cpu_to_le32(0x00000000) -#define TYPHOON_RX_ERR_FIFO_UNDERRUN __constant_cpu_to_le32(0x00000001) -#define TYPHOON_RX_ERR_BAD_SSD __constant_cpu_to_le32(0x00000002) -#define TYPHOON_RX_ERR_RUNT __constant_cpu_to_le32(0x00000003) -#define TYPHOON_RX_ERR_CRC __constant_cpu_to_le32(0x00000004) -#define TYPHOON_RX_ERR_OVERSIZE __constant_cpu_to_le32(0x00000005) -#define TYPHOON_RX_ERR_ALIGN __constant_cpu_to_le32(0x00000006) -#define TYPHOON_RX_ERR_DRIBBLE __constant_cpu_to_le32(0x00000007) -#define TYPHOON_RX_PROTO_MASK __constant_cpu_to_le32(0x00000003) -#define TYPHOON_RX_PROTO_UNKNOWN __constant_cpu_to_le32(0x00000000) -#define TYPHOON_RX_PROTO_IP __constant_cpu_to_le32(0x00000001) -#define TYPHOON_RX_PROTO_IPX __constant_cpu_to_le32(0x00000002) -#define TYPHOON_RX_VLAN __constant_cpu_to_le32(0x00000004) -#define TYPHOON_RX_IP_FRAG __constant_cpu_to_le32(0x00000008) -#define TYPHOON_RX_IPSEC __constant_cpu_to_le32(0x00000010) -#define TYPHOON_RX_IP_CHK_FAIL __constant_cpu_to_le32(0x00000020) -#define TYPHOON_RX_TCP_CHK_FAIL __constant_cpu_to_le32(0x00000040) -#define TYPHOON_RX_UDP_CHK_FAIL __constant_cpu_to_le32(0x00000080) -#define TYPHOON_RX_IP_CHK_GOOD __constant_cpu_to_le32(0x00000100) -#define TYPHOON_RX_TCP_CHK_GOOD __constant_cpu_to_le32(0x00000200) -#define TYPHOON_RX_UDP_CHK_GOOD __constant_cpu_to_le32(0x00000400) +#define TYPHOON_RX_ERR_INTERNAL cpu_to_le32(0x00000000) +#define TYPHOON_RX_ERR_FIFO_UNDERRUN cpu_to_le32(0x00000001) +#define TYPHOON_RX_ERR_BAD_SSD cpu_to_le32(0x00000002) +#define TYPHOON_RX_ERR_RUNT cpu_to_le32(0x00000003) +#define TYPHOON_RX_ERR_CRC cpu_to_le32(0x00000004) +#define TYPHOON_RX_ERR_OVERSIZE cpu_to_le32(0x00000005) +#define TYPHOON_RX_ERR_ALIGN cpu_to_le32(0x00000006) +#define TYPHOON_RX_ERR_DRIBBLE cpu_to_le32(0x00000007) +#define TYPHOON_RX_PROTO_MASK cpu_to_le32(0x00000003) +#define TYPHOON_RX_PROTO_UNKNOWN cpu_to_le32(0x00000000) +#define TYPHOON_RX_PROTO_IP cpu_to_le32(0x00000001) +#define TYPHOON_RX_PROTO_IPX cpu_to_le32(0x00000002) +#define TYPHOON_RX_VLAN cpu_to_le32(0x00000004) +#define TYPHOON_RX_IP_FRAG cpu_to_le32(0x00000008) +#define TYPHOON_RX_IPSEC cpu_to_le32(0x00000010) +#define TYPHOON_RX_IP_CHK_FAIL cpu_to_le32(0x00000020) +#define TYPHOON_RX_TCP_CHK_FAIL cpu_to_le32(0x00000040) +#define TYPHOON_RX_UDP_CHK_FAIL cpu_to_le32(0x00000080) +#define TYPHOON_RX_IP_CHK_GOOD cpu_to_le32(0x00000100) +#define TYPHOON_RX_TCP_CHK_GOOD cpu_to_le32(0x00000200) +#define TYPHOON_RX_UDP_CHK_GOOD cpu_to_le32(0x00000400) __le16 filterResults; -#define TYPHOON_RX_FILTER_MASK __constant_cpu_to_le16(0x7fff) -#define TYPHOON_RX_FILTERED __constant_cpu_to_le16(0x8000) +#define TYPHOON_RX_FILTER_MASK cpu_to_le16(0x7fff) +#define TYPHOON_RX_FILTERED cpu_to_le16(0x8000) __le16 ipsecResults; -#define TYPHOON_RX_OUTER_AH_GOOD __constant_cpu_to_le16(0x0001) -#define TYPHOON_RX_OUTER_ESP_GOOD __constant_cpu_to_le16(0x0002) -#define TYPHOON_RX_INNER_AH_GOOD __constant_cpu_to_le16(0x0004) -#define TYPHOON_RX_INNER_ESP_GOOD __constant_cpu_to_le16(0x0008) -#define TYPHOON_RX_OUTER_AH_FAIL __constant_cpu_to_le16(0x0010) -#define TYPHOON_RX_OUTER_ESP_FAIL __constant_cpu_to_le16(0x0020) -#define TYPHOON_RX_INNER_AH_FAIL __constant_cpu_to_le16(0x0040) -#define TYPHOON_RX_INNER_ESP_FAIL __constant_cpu_to_le16(0x0080) -#define TYPHOON_RX_UNKNOWN_SA __constant_cpu_to_le16(0x0100) -#define TYPHOON_RX_ESP_FORMAT_ERR __constant_cpu_to_le16(0x0200) +#define TYPHOON_RX_OUTER_AH_GOOD cpu_to_le16(0x0001) +#define TYPHOON_RX_OUTER_ESP_GOOD cpu_to_le16(0x0002) +#define TYPHOON_RX_INNER_AH_GOOD cpu_to_le16(0x0004) +#define TYPHOON_RX_INNER_ESP_GOOD cpu_to_le16(0x0008) +#define TYPHOON_RX_OUTER_AH_FAIL cpu_to_le16(0x0010) +#define TYPHOON_RX_OUTER_ESP_FAIL cpu_to_le16(0x0020) +#define TYPHOON_RX_INNER_AH_FAIL cpu_to_le16(0x0040) +#define TYPHOON_RX_INNER_ESP_FAIL cpu_to_le16(0x0080) +#define TYPHOON_RX_UNKNOWN_SA cpu_to_le16(0x0100) +#define TYPHOON_RX_ESP_FORMAT_ERR cpu_to_le16(0x0200) __be32 vlanTag; } __attribute__ ((packed)); @@ -318,31 +318,31 @@ struct cmd_desc { u8 flags; u8 numDesc; __le16 cmd; -#define TYPHOON_CMD_TX_ENABLE __constant_cpu_to_le16(0x0001) -#define TYPHOON_CMD_TX_DISABLE __constant_cpu_to_le16(0x0002) -#define TYPHOON_CMD_RX_ENABLE __constant_cpu_to_le16(0x0003) -#define TYPHOON_CMD_RX_DISABLE __constant_cpu_to_le16(0x0004) -#define TYPHOON_CMD_SET_RX_FILTER __constant_cpu_to_le16(0x0005) -#define TYPHOON_CMD_READ_STATS __constant_cpu_to_le16(0x0007) -#define TYPHOON_CMD_XCVR_SELECT __constant_cpu_to_le16(0x0013) -#define TYPHOON_CMD_SET_MAX_PKT_SIZE __constant_cpu_to_le16(0x001a) -#define TYPHOON_CMD_READ_MEDIA_STATUS __constant_cpu_to_le16(0x001b) -#define TYPHOON_CMD_GOTO_SLEEP __constant_cpu_to_le16(0x0023) -#define TYPHOON_CMD_SET_MULTICAST_HASH __constant_cpu_to_le16(0x0025) -#define TYPHOON_CMD_SET_MAC_ADDRESS __constant_cpu_to_le16(0x0026) -#define TYPHOON_CMD_READ_MAC_ADDRESS __constant_cpu_to_le16(0x0027) -#define TYPHOON_CMD_VLAN_TYPE_WRITE __constant_cpu_to_le16(0x002b) -#define TYPHOON_CMD_CREATE_SA __constant_cpu_to_le16(0x0034) -#define TYPHOON_CMD_DELETE_SA __constant_cpu_to_le16(0x0035) -#define TYPHOON_CMD_READ_VERSIONS __constant_cpu_to_le16(0x0043) -#define TYPHOON_CMD_IRQ_COALESCE_CTRL __constant_cpu_to_le16(0x0045) -#define TYPHOON_CMD_ENABLE_WAKE_EVENTS __constant_cpu_to_le16(0x0049) -#define TYPHOON_CMD_SET_OFFLOAD_TASKS __constant_cpu_to_le16(0x004f) -#define TYPHOON_CMD_HELLO_RESP __constant_cpu_to_le16(0x0057) -#define TYPHOON_CMD_HALT __constant_cpu_to_le16(0x005d) -#define TYPHOON_CMD_READ_IPSEC_INFO __constant_cpu_to_le16(0x005e) -#define TYPHOON_CMD_GET_IPSEC_ENABLE __constant_cpu_to_le16(0x0067) -#define TYPHOON_CMD_GET_CMD_LVL __constant_cpu_to_le16(0x0069) +#define TYPHOON_CMD_TX_ENABLE cpu_to_le16(0x0001) +#define TYPHOON_CMD_TX_DISABLE cpu_to_le16(0x0002) +#define TYPHOON_CMD_RX_ENABLE cpu_to_le16(0x0003) +#define TYPHOON_CMD_RX_DISABLE cpu_to_le16(0x0004) +#define TYPHOON_CMD_SET_RX_FILTER cpu_to_le16(0x0005) +#define TYPHOON_CMD_READ_STATS cpu_to_le16(0x0007) +#define TYPHOON_CMD_XCVR_SELECT cpu_to_le16(0x0013) +#define TYPHOON_CMD_SET_MAX_PKT_SIZE cpu_to_le16(0x001a) +#define TYPHOON_CMD_READ_MEDIA_STATUS cpu_to_le16(0x001b) +#define TYPHOON_CMD_GOTO_SLEEP cpu_to_le16(0x0023) +#define TYPHOON_CMD_SET_MULTICAST_HASH cpu_to_le16(0x0025) +#define TYPHOON_CMD_SET_MAC_ADDRESS cpu_to_le16(0x0026) +#define TYPHOON_CMD_READ_MAC_ADDRESS cpu_to_le16(0x0027) +#define TYPHOON_CMD_VLAN_TYPE_WRITE cpu_to_le16(0x002b) +#define TYPHOON_CMD_CREATE_SA cpu_to_le16(0x0034) +#define TYPHOON_CMD_DELETE_SA cpu_to_le16(0x0035) +#define TYPHOON_CMD_READ_VERSIONS cpu_to_le16(0x0043) +#define TYPHOON_CMD_IRQ_COALESCE_CTRL cpu_to_le16(0x0045) +#define TYPHOON_CMD_ENABLE_WAKE_EVENTS cpu_to_le16(0x0049) +#define TYPHOON_CMD_SET_OFFLOAD_TASKS cpu_to_le16(0x004f) +#define TYPHOON_CMD_HELLO_RESP cpu_to_le16(0x0057) +#define TYPHOON_CMD_HALT cpu_to_le16(0x005d) +#define TYPHOON_CMD_READ_IPSEC_INFO cpu_to_le16(0x005e) +#define TYPHOON_CMD_GET_IPSEC_ENABLE cpu_to_le16(0x0067) +#define TYPHOON_CMD_GET_CMD_LVL cpu_to_le16(0x0069) u16 seqNo; __le16 parm1; __le32 parm2; @@ -380,11 +380,11 @@ struct resp_desc { /* TYPHOON_CMD_SET_RX_FILTER filter bits (cmd.parm1) */ -#define TYPHOON_RX_FILTER_DIRECTED __constant_cpu_to_le16(0x0001) -#define TYPHOON_RX_FILTER_ALL_MCAST __constant_cpu_to_le16(0x0002) -#define TYPHOON_RX_FILTER_BROADCAST __constant_cpu_to_le16(0x0004) -#define TYPHOON_RX_FILTER_PROMISCOUS __constant_cpu_to_le16(0x0008) -#define TYPHOON_RX_FILTER_MCAST_HASH __constant_cpu_to_le16(0x0010) +#define TYPHOON_RX_FILTER_DIRECTED cpu_to_le16(0x0001) +#define TYPHOON_RX_FILTER_ALL_MCAST cpu_to_le16(0x0002) +#define TYPHOON_RX_FILTER_BROADCAST cpu_to_le16(0x0004) +#define TYPHOON_RX_FILTER_PROMISCOUS cpu_to_le16(0x0008) +#define TYPHOON_RX_FILTER_MCAST_HASH cpu_to_le16(0x0010) /* TYPHOON_CMD_READ_STATS response format */ @@ -416,40 +416,40 @@ struct stats_resp { __le32 rxOverflow; __le32 rxFiltered; __le32 linkStatus; -#define TYPHOON_LINK_STAT_MASK __constant_cpu_to_le32(0x00000001) -#define TYPHOON_LINK_GOOD __constant_cpu_to_le32(0x00000001) -#define TYPHOON_LINK_BAD __constant_cpu_to_le32(0x00000000) -#define TYPHOON_LINK_SPEED_MASK __constant_cpu_to_le32(0x00000002) -#define TYPHOON_LINK_100MBPS __constant_cpu_to_le32(0x00000002) -#define TYPHOON_LINK_10MBPS __constant_cpu_to_le32(0x00000000) -#define TYPHOON_LINK_DUPLEX_MASK __constant_cpu_to_le32(0x00000004) -#define TYPHOON_LINK_FULL_DUPLEX __constant_cpu_to_le32(0x00000004) -#define TYPHOON_LINK_HALF_DUPLEX __constant_cpu_to_le32(0x00000000) +#define TYPHOON_LINK_STAT_MASK cpu_to_le32(0x00000001) +#define TYPHOON_LINK_GOOD cpu_to_le32(0x00000001) +#define TYPHOON_LINK_BAD cpu_to_le32(0x00000000) +#define TYPHOON_LINK_SPEED_MASK cpu_to_le32(0x00000002) +#define TYPHOON_LINK_100MBPS cpu_to_le32(0x00000002) +#define TYPHOON_LINK_10MBPS cpu_to_le32(0x00000000) +#define TYPHOON_LINK_DUPLEX_MASK cpu_to_le32(0x00000004) +#define TYPHOON_LINK_FULL_DUPLEX cpu_to_le32(0x00000004) +#define TYPHOON_LINK_HALF_DUPLEX cpu_to_le32(0x00000000) __le32 unused2; __le32 unused3; } __attribute__ ((packed)); /* TYPHOON_CMD_XCVR_SELECT xcvr values (resp.parm1) */ -#define TYPHOON_XCVR_10HALF __constant_cpu_to_le16(0x0000) -#define TYPHOON_XCVR_10FULL __constant_cpu_to_le16(0x0001) -#define TYPHOON_XCVR_100HALF __constant_cpu_to_le16(0x0002) -#define TYPHOON_XCVR_100FULL __constant_cpu_to_le16(0x0003) -#define TYPHOON_XCVR_AUTONEG __constant_cpu_to_le16(0x0004) +#define TYPHOON_XCVR_10HALF cpu_to_le16(0x0000) +#define TYPHOON_XCVR_10FULL cpu_to_le16(0x0001) +#define TYPHOON_XCVR_100HALF cpu_to_le16(0x0002) +#define TYPHOON_XCVR_100FULL cpu_to_le16(0x0003) +#define TYPHOON_XCVR_AUTONEG cpu_to_le16(0x0004) /* TYPHOON_CMD_READ_MEDIA_STATUS (resp.parm1) */ -#define TYPHOON_MEDIA_STAT_CRC_STRIP_DISABLE __constant_cpu_to_le16(0x0004) -#define TYPHOON_MEDIA_STAT_COLLISION_DETECT __constant_cpu_to_le16(0x0010) -#define TYPHOON_MEDIA_STAT_CARRIER_SENSE __constant_cpu_to_le16(0x0020) -#define TYPHOON_MEDIA_STAT_POLARITY_REV __constant_cpu_to_le16(0x0400) -#define TYPHOON_MEDIA_STAT_NO_LINK __constant_cpu_to_le16(0x0800) +#define TYPHOON_MEDIA_STAT_CRC_STRIP_DISABLE cpu_to_le16(0x0004) +#define TYPHOON_MEDIA_STAT_COLLISION_DETECT cpu_to_le16(0x0010) +#define TYPHOON_MEDIA_STAT_CARRIER_SENSE cpu_to_le16(0x0020) +#define TYPHOON_MEDIA_STAT_POLARITY_REV cpu_to_le16(0x0400) +#define TYPHOON_MEDIA_STAT_NO_LINK cpu_to_le16(0x0800) /* TYPHOON_CMD_SET_MULTICAST_HASH enable values (cmd.parm1) */ -#define TYPHOON_MCAST_HASH_DISABLE __constant_cpu_to_le16(0x0000) -#define TYPHOON_MCAST_HASH_ENABLE __constant_cpu_to_le16(0x0001) -#define TYPHOON_MCAST_HASH_SET __constant_cpu_to_le16(0x0002) +#define TYPHOON_MCAST_HASH_DISABLE cpu_to_le16(0x0000) +#define TYPHOON_MCAST_HASH_ENABLE cpu_to_le16(0x0001) +#define TYPHOON_MCAST_HASH_SET cpu_to_le16(0x0002) /* TYPHOON_CMD_CREATE_SA descriptor and settings */ @@ -459,9 +459,9 @@ struct sa_descriptor { u16 cmd; u16 seqNo; u16 mode; -#define TYPHOON_SA_MODE_NULL __constant_cpu_to_le16(0x0000) -#define TYPHOON_SA_MODE_AH __constant_cpu_to_le16(0x0001) -#define TYPHOON_SA_MODE_ESP __constant_cpu_to_le16(0x0002) +#define TYPHOON_SA_MODE_NULL cpu_to_le16(0x0000) +#define TYPHOON_SA_MODE_AH cpu_to_le16(0x0001) +#define TYPHOON_SA_MODE_ESP cpu_to_le16(0x0002) u8 hashFlags; #define TYPHOON_SA_HASH_ENABLE 0x01 #define TYPHOON_SA_HASH_SHA1 0x02 @@ -493,22 +493,22 @@ struct sa_descriptor { /* TYPHOON_CMD_SET_OFFLOAD_TASKS bits (cmd.parm2 (Tx) & cmd.parm3 (Rx)) * This is all for IPv4. */ -#define TYPHOON_OFFLOAD_TCP_CHKSUM __constant_cpu_to_le32(0x00000002) -#define TYPHOON_OFFLOAD_UDP_CHKSUM __constant_cpu_to_le32(0x00000004) -#define TYPHOON_OFFLOAD_IP_CHKSUM __constant_cpu_to_le32(0x00000008) -#define TYPHOON_OFFLOAD_IPSEC __constant_cpu_to_le32(0x00000010) -#define TYPHOON_OFFLOAD_BCAST_THROTTLE __constant_cpu_to_le32(0x00000020) -#define TYPHOON_OFFLOAD_DHCP_PREVENT __constant_cpu_to_le32(0x00000040) -#define TYPHOON_OFFLOAD_VLAN __constant_cpu_to_le32(0x00000080) -#define TYPHOON_OFFLOAD_FILTERING __constant_cpu_to_le32(0x00000100) -#define TYPHOON_OFFLOAD_TCP_SEGMENT __constant_cpu_to_le32(0x00000200) +#define TYPHOON_OFFLOAD_TCP_CHKSUM cpu_to_le32(0x00000002) +#define TYPHOON_OFFLOAD_UDP_CHKSUM cpu_to_le32(0x00000004) +#define TYPHOON_OFFLOAD_IP_CHKSUM cpu_to_le32(0x00000008) +#define TYPHOON_OFFLOAD_IPSEC cpu_to_le32(0x00000010) +#define TYPHOON_OFFLOAD_BCAST_THROTTLE cpu_to_le32(0x00000020) +#define TYPHOON_OFFLOAD_DHCP_PREVENT cpu_to_le32(0x00000040) +#define TYPHOON_OFFLOAD_VLAN cpu_to_le32(0x00000080) +#define TYPHOON_OFFLOAD_FILTERING cpu_to_le32(0x00000100) +#define TYPHOON_OFFLOAD_TCP_SEGMENT cpu_to_le32(0x00000200) /* TYPHOON_CMD_ENABLE_WAKE_EVENTS bits (cmd.parm1) */ -#define TYPHOON_WAKE_MAGIC_PKT __constant_cpu_to_le16(0x01) -#define TYPHOON_WAKE_LINK_EVENT __constant_cpu_to_le16(0x02) -#define TYPHOON_WAKE_ICMP_ECHO __constant_cpu_to_le16(0x04) -#define TYPHOON_WAKE_ARP __constant_cpu_to_le16(0x08) +#define TYPHOON_WAKE_MAGIC_PKT cpu_to_le16(0x01) +#define TYPHOON_WAKE_LINK_EVENT cpu_to_le16(0x02) +#define TYPHOON_WAKE_ICMP_ECHO cpu_to_le16(0x04) +#define TYPHOON_WAKE_ARP cpu_to_le16(0x08) /* These are used to load the firmware image on the NIC */ -- GitLab From 5c0999b72b34541a3734a9138c43d5c024a42d47 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 19 Jan 2009 15:20:57 -0800 Subject: [PATCH 0347/4982] igb: Replace LRO with GRO This patch makes igb invoke the GRO hooks instead of LRO. As GRO has a compatible external interface to LRO this is a very straightforward replacement. Three things of note: 1) I've kept the LRO Kconfig option until we decide to enable GRO across the board at which point it can also be killed. 2) The poll_controller stuff is broken in igb as it tries to do the same work as the normal poll routine. Since poll_controller can be called in the middle of a poll, this can't be good. I noticed this because poll_controller can invoke the GRO hooks without flushing held GRO packets. However, this should be harmless (assuming the poll_controller bug above doesn't kill you first :) since the next ->poll will clear the backlog. The only time when we'll have a problem is if we're already executing the GRO code on the same ring, but that's no worse than what happens now. 3) I kept the ip_summed check before calling GRO so that we're on par with previous behaviour. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- drivers/net/Kconfig | 1 - drivers/net/igb/igb.h | 16 ------- drivers/net/igb/igb_ethtool.c | 17 ------- drivers/net/igb/igb_main.c | 90 +++-------------------------------- 4 files changed, 6 insertions(+), 118 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index eccb89770f5..805682586c8 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2022,7 +2022,6 @@ config IGB config IGB_LRO bool "Use software LRO" depends on IGB && INET - select INET_LRO ---help--- Say Y here if you want to use large receive offload. diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 5a27825cc48..7d8c8873915 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -36,12 +36,6 @@ struct igb_adapter; -#ifdef CONFIG_IGB_LRO -#include -#define MAX_LRO_AGGR 32 -#define MAX_LRO_DESCRIPTORS 8 -#endif - /* Interrupt defines */ #define IGB_MIN_DYN_ITR 3000 #define IGB_MAX_DYN_ITR 96000 @@ -176,10 +170,6 @@ struct igb_ring { struct napi_struct napi; int set_itr; struct igb_ring *buddy; -#ifdef CONFIG_IGB_LRO - struct net_lro_mgr lro_mgr; - bool lro_used; -#endif }; }; @@ -288,12 +278,6 @@ struct igb_adapter { int need_ioport; struct igb_ring *multi_tx_table[IGB_MAX_TX_QUEUES]; -#ifdef CONFIG_IGB_LRO - unsigned int lro_max_aggr; - unsigned int lro_aggregated; - unsigned int lro_flushed; - unsigned int lro_no_desc; -#endif unsigned int tx_ring_count; unsigned int rx_ring_count; }; diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 3c831f1472a..4606e63fc6f 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -93,11 +93,6 @@ static const struct igb_stats igb_gstrings_stats[] = { { "tx_smbus", IGB_STAT(stats.mgptc) }, { "rx_smbus", IGB_STAT(stats.mgprc) }, { "dropped_smbus", IGB_STAT(stats.mgpdc) }, -#ifdef CONFIG_IGB_LRO - { "lro_aggregated", IGB_STAT(lro_aggregated) }, - { "lro_flushed", IGB_STAT(lro_flushed) }, - { "lro_no_desc", IGB_STAT(lro_no_desc) }, -#endif }; #define IGB_QUEUE_STATS_LEN \ @@ -1921,18 +1916,6 @@ static void igb_get_ethtool_stats(struct net_device *netdev, int stat_count = sizeof(struct igb_queue_stats) / sizeof(u64); int j; int i; -#ifdef CONFIG_IGB_LRO - int aggregated = 0, flushed = 0, no_desc = 0; - - for (i = 0; i < adapter->num_rx_queues; i++) { - aggregated += adapter->rx_ring[i].lro_mgr.stats.aggregated; - flushed += adapter->rx_ring[i].lro_mgr.stats.flushed; - no_desc += adapter->rx_ring[i].lro_mgr.stats.no_desc; - } - adapter->lro_aggregated = aggregated; - adapter->lro_flushed = flushed; - adapter->lro_no_desc = no_desc; -#endif igb_update_stats(adapter); for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) { diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 3806bb9d8bf..dbe03c2b49c 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -115,9 +115,6 @@ static bool igb_clean_tx_irq(struct igb_ring *); static int igb_poll(struct napi_struct *, int); static bool igb_clean_rx_irq_adv(struct igb_ring *, int *, int); static void igb_alloc_rx_buffers_adv(struct igb_ring *, int); -#ifdef CONFIG_IGB_LRO -static int igb_get_skb_hdr(struct sk_buff *skb, void **, void **, u64 *, void *); -#endif static int igb_ioctl(struct net_device *, struct ifreq *, int cmd); static void igb_tx_timeout(struct net_device *); static void igb_reset_task(struct work_struct *); @@ -1189,7 +1186,7 @@ static int __devinit igb_probe(struct pci_dev *pdev, netdev->features |= NETIF_F_TSO6; #ifdef CONFIG_IGB_LRO - netdev->features |= NETIF_F_LRO; + netdev->features |= NETIF_F_GRO; #endif netdev->vlan_features |= NETIF_F_TSO; @@ -1739,14 +1736,6 @@ int igb_setup_rx_resources(struct igb_adapter *adapter, struct pci_dev *pdev = adapter->pdev; int size, desc_len; -#ifdef CONFIG_IGB_LRO - size = sizeof(struct net_lro_desc) * MAX_LRO_DESCRIPTORS; - rx_ring->lro_mgr.lro_arr = vmalloc(size); - if (!rx_ring->lro_mgr.lro_arr) - goto err; - memset(rx_ring->lro_mgr.lro_arr, 0, size); -#endif - size = sizeof(struct igb_buffer) * rx_ring->count; rx_ring->buffer_info = vmalloc(size); if (!rx_ring->buffer_info) @@ -1773,10 +1762,6 @@ int igb_setup_rx_resources(struct igb_adapter *adapter, return 0; err: -#ifdef CONFIG_IGB_LRO - vfree(rx_ring->lro_mgr.lro_arr); - rx_ring->lro_mgr.lro_arr = NULL; -#endif vfree(rx_ring->buffer_info); dev_err(&adapter->pdev->dev, "Unable to allocate memory for " "the receive descriptor ring\n"); @@ -1930,16 +1915,6 @@ static void igb_configure_rx(struct igb_adapter *adapter) rxdctl |= IGB_RX_HTHRESH << 8; rxdctl |= IGB_RX_WTHRESH << 16; wr32(E1000_RXDCTL(j), rxdctl); -#ifdef CONFIG_IGB_LRO - /* Intitial LRO Settings */ - ring->lro_mgr.max_aggr = MAX_LRO_AGGR; - ring->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS; - ring->lro_mgr.get_skb_header = igb_get_skb_hdr; - ring->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID; - ring->lro_mgr.dev = adapter->netdev; - ring->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY; - ring->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY; -#endif } if (adapter->num_rx_queues > 1) { @@ -2128,11 +2103,6 @@ void igb_free_rx_resources(struct igb_ring *rx_ring) vfree(rx_ring->buffer_info); rx_ring->buffer_info = NULL; -#ifdef CONFIG_IGB_LRO - vfree(rx_ring->lro_mgr.lro_arr); - rx_ring->lro_mgr.lro_arr = NULL; -#endif - pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma); rx_ring->desc = NULL; @@ -3768,39 +3738,6 @@ static bool igb_clean_tx_irq(struct igb_ring *tx_ring) return (count < tx_ring->count); } -#ifdef CONFIG_IGB_LRO - /** - * igb_get_skb_hdr - helper function for LRO header processing - * @skb: pointer to sk_buff to be added to LRO packet - * @iphdr: pointer to ip header structure - * @tcph: pointer to tcp header structure - * @hdr_flags: pointer to header flags - * @priv: pointer to the receive descriptor for the current sk_buff - **/ -static int igb_get_skb_hdr(struct sk_buff *skb, void **iphdr, void **tcph, - u64 *hdr_flags, void *priv) -{ - union e1000_adv_rx_desc *rx_desc = priv; - u16 pkt_type = rx_desc->wb.lower.lo_dword.pkt_info & - (E1000_RXDADV_PKTTYPE_IPV4 | E1000_RXDADV_PKTTYPE_TCP); - - /* Verify that this is a valid IPv4 TCP packet */ - if (pkt_type != (E1000_RXDADV_PKTTYPE_IPV4 | - E1000_RXDADV_PKTTYPE_TCP)) - return -1; - - /* Set network headers */ - skb_reset_network_header(skb); - skb_set_transport_header(skb, ip_hdrlen(skb)); - *iphdr = ip_hdr(skb); - *tcph = tcp_hdr(skb); - *hdr_flags = LRO_IPV4 | LRO_TCP; - - return 0; - -} -#endif /* CONFIG_IGB_LRO */ - /** * igb_receive_skb - helper function to handle rx indications * @ring: pointer to receive ring receving this packet @@ -3815,28 +3752,20 @@ static void igb_receive_skb(struct igb_ring *ring, u8 status, struct igb_adapter * adapter = ring->adapter; bool vlan_extracted = (adapter->vlgrp && (status & E1000_RXD_STAT_VP)); -#ifdef CONFIG_IGB_LRO - if (adapter->netdev->features & NETIF_F_LRO && - skb->ip_summed == CHECKSUM_UNNECESSARY) { + if (skb->ip_summed == CHECKSUM_UNNECESSARY) { if (vlan_extracted) - lro_vlan_hwaccel_receive_skb(&ring->lro_mgr, skb, - adapter->vlgrp, - le16_to_cpu(rx_desc->wb.upper.vlan), - rx_desc); + vlan_gro_receive(&ring->napi, adapter->vlgrp, + le16_to_cpu(rx_desc->wb.upper.vlan), + skb); else - lro_receive_skb(&ring->lro_mgr,skb, rx_desc); - ring->lro_used = 1; + napi_gro_receive(&ring->napi, skb); } else { -#endif if (vlan_extracted) vlan_hwaccel_receive_skb(skb, adapter->vlgrp, le16_to_cpu(rx_desc->wb.upper.vlan)); else - netif_receive_skb(skb); -#ifdef CONFIG_IGB_LRO } -#endif } @@ -3991,13 +3920,6 @@ next_desc: rx_ring->next_to_clean = i; cleaned_count = IGB_DESC_UNUSED(rx_ring); -#ifdef CONFIG_IGB_LRO - if (rx_ring->lro_used) { - lro_flush_all(&rx_ring->lro_mgr); - rx_ring->lro_used = 0; - } -#endif - if (cleaned_count) igb_alloc_rx_buffers_adv(rx_ring, cleaned_count); -- GitLab From a9d8f9110d7e953c2f2b521087a4179677843c2a Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Mon, 19 Jan 2009 16:46:02 -0800 Subject: [PATCH 0348/4982] inet: Allowing more than 64k connections and heavily optimize bind(0) time. With simple extension to the binding mechanism, which allows to bind more than 64k sockets (or smaller amount, depending on sysctl parameters), we have to traverse the whole bind hash table to find out empty bucket. And while it is not a problem for example for 32k connections, bind() completion time grows exponentially (since after each successful binding we have to traverse one bucket more to find empty one) even if we start each time from random offset inside the hash table. So, when hash table is full, and we want to add another socket, we have to traverse the whole table no matter what, so effectivelly this will be the worst case performance and it will be constant. Attached picture shows bind() time depending on number of already bound sockets. Green area corresponds to the usual binding to zero port process, which turns on kernel port selection as described above. Red area is the bind process, when number of reuse-bound sockets is not limited by 64k (or sysctl parameters). The same exponential growth (hidden by the green area) before number of ports reaches sysctl limit. At this time bind hash table has exactly one reuse-enbaled socket in a bucket, but it is possible that they have different addresses. Actually kernel selects the first port to try randomly, so at the beginning bind will take roughly constant time, but with time number of port to check after random start will increase. And that will have exponential growth, but because of above random selection, not every next port selection will necessary take longer time than previous. So we have to consider the area below in the graph (if you could zoom it, you could find, that there are many different times placed there), so area can hide another. Blue area corresponds to the port selection optimization. This is rather simple design approach: hashtable now maintains (unprecise and racely updated) number of currently bound sockets, and when number of such sockets becomes greater than predefined value (I use maximum port range defined by sysctls), we stop traversing the whole bind hash table and just stop at first matching bucket after random start. Above limit roughly corresponds to the case, when bind hash table is full and we turned on mechanism of allowing to bind more reuse-enabled sockets, so it does not change behaviour of other sockets. Signed-off-by: Evgeniy Polyakov Tested-by: Denys Fedoryschenko Signed-off-by: David S. Miller --- include/net/inet_hashtables.h | 3 ++- net/ipv4/inet_connection_sock.c | 41 +++++++++++++++++++++++++++------ net/ipv4/inet_hashtables.c | 11 ++++++++- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index f44bb5c77a7..cdc08c19063 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h @@ -82,6 +82,7 @@ struct inet_bind_bucket { #endif unsigned short port; signed short fastreuse; + int num_owners; struct hlist_node node; struct hlist_head owners; }; @@ -133,7 +134,7 @@ struct inet_hashinfo { struct inet_bind_hashbucket *bhash; unsigned int bhash_size; - /* Note : 4 bytes padding on 64 bit arches */ + int bsockets; struct kmem_cache *bind_bucket_cachep; diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index f26ab38680d..df8e72f0747 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -93,24 +93,40 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum) struct inet_bind_hashbucket *head; struct hlist_node *node; struct inet_bind_bucket *tb; - int ret; + int ret, attempts = 5; struct net *net = sock_net(sk); + int smallest_size = -1, smallest_rover; local_bh_disable(); if (!snum) { int remaining, rover, low, high; +again: inet_get_local_port_range(&low, &high); remaining = (high - low) + 1; - rover = net_random() % remaining + low; + smallest_rover = rover = net_random() % remaining + low; + smallest_size = -1; do { head = &hashinfo->bhash[inet_bhashfn(net, rover, hashinfo->bhash_size)]; spin_lock(&head->lock); inet_bind_bucket_for_each(tb, node, &head->chain) - if (ib_net(tb) == net && tb->port == rover) + if (ib_net(tb) == net && tb->port == rover) { + if (tb->fastreuse > 0 && + sk->sk_reuse && + sk->sk_state != TCP_LISTEN && + (tb->num_owners < smallest_size || smallest_size == -1)) { + smallest_size = tb->num_owners; + smallest_rover = rover; + if (hashinfo->bsockets > (high - low) + 1) { + spin_unlock(&head->lock); + snum = smallest_rover; + goto have_snum; + } + } goto next; + } break; next: spin_unlock(&head->lock); @@ -125,14 +141,19 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum) * the top level, not from the 'break;' statement. */ ret = 1; - if (remaining <= 0) + if (remaining <= 0) { + if (smallest_size != -1) { + snum = smallest_rover; + goto have_snum; + } goto fail; - + } /* OK, here is the one we will use. HEAD is * non-NULL and we hold it's mutex. */ snum = rover; } else { +have_snum: head = &hashinfo->bhash[inet_bhashfn(net, snum, hashinfo->bhash_size)]; spin_lock(&head->lock); @@ -145,12 +166,18 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum) tb_found: if (!hlist_empty(&tb->owners)) { if (tb->fastreuse > 0 && - sk->sk_reuse && sk->sk_state != TCP_LISTEN) { + sk->sk_reuse && sk->sk_state != TCP_LISTEN && + smallest_size == -1) { goto success; } else { ret = 1; - if (inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb)) + if (inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb)) { + if (sk->sk_reuse && sk->sk_state != TCP_LISTEN && --attempts >= 0) { + spin_unlock(&head->lock); + goto again; + } goto fail_unlock; + } } } tb_not_found: diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 6a1045da48d..d7b6178bf48 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -38,6 +38,7 @@ struct inet_bind_bucket *inet_bind_bucket_create(struct kmem_cache *cachep, write_pnet(&tb->ib_net, hold_net(net)); tb->port = snum; tb->fastreuse = 0; + tb->num_owners = 0; INIT_HLIST_HEAD(&tb->owners); hlist_add_head(&tb->node, &head->chain); } @@ -59,8 +60,13 @@ void inet_bind_bucket_destroy(struct kmem_cache *cachep, struct inet_bind_bucket void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb, const unsigned short snum) { + struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; + + hashinfo->bsockets++; + inet_sk(sk)->num = snum; sk_add_bind_node(sk, &tb->owners); + tb->num_owners++; inet_csk(sk)->icsk_bind_hash = tb; } @@ -75,9 +81,12 @@ static void __inet_put_port(struct sock *sk) struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash]; struct inet_bind_bucket *tb; + hashinfo->bsockets--; + spin_lock(&head->lock); tb = inet_csk(sk)->icsk_bind_hash; __sk_del_bind_node(sk); + tb->num_owners--; inet_csk(sk)->icsk_bind_hash = NULL; inet_sk(sk)->num = 0; inet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb); @@ -444,9 +453,9 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row, */ inet_bind_bucket_for_each(tb, node, &head->chain) { if (ib_net(tb) == net && tb->port == port) { - WARN_ON(hlist_empty(&tb->owners)); if (tb->fastreuse >= 0) goto next_port; + WARN_ON(hlist_empty(&tb->owners)); if (!check_established(death_row, sk, port, &tw)) goto ok; -- GitLab From 3d16543d3235fefca351c10b30c1cca6536f2569 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Mon, 19 Jan 2009 16:56:50 -0800 Subject: [PATCH 0349/4982] tg3: remove extra casting Signed-off-by: Francois Romieu Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 5fa65acb68e..5b3d60568d5 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -860,7 +860,7 @@ static int tg3_bmcr_reset(struct tg3 *tp) static int tg3_mdio_read(struct mii_bus *bp, int mii_id, int reg) { - struct tg3 *tp = (struct tg3 *)bp->priv; + struct tg3 *tp = bp->priv; u32 val; if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_PAUSED) @@ -874,7 +874,7 @@ static int tg3_mdio_read(struct mii_bus *bp, int mii_id, int reg) static int tg3_mdio_write(struct mii_bus *bp, int mii_id, int reg, u16 val) { - struct tg3 *tp = (struct tg3 *)bp->priv; + struct tg3 *tp = bp->priv; if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_PAUSED) return -EAGAIN; -- GitLab From 5384e8361a9bb7fca054b47c1dde7ac0e929407f Mon Sep 17 00:00:00 2001 From: Masakazu Mokuno Date: Thu, 15 Jan 2009 22:47:29 +0000 Subject: [PATCH 0350/4982] PS3: gelic: convert the ethernet part to net_device_ops Convert the gelic driver to net_device_ops Signed-off-by: Masakazu Mokuno Signed-off-by: David S. Miller --- drivers/net/ps3_gelic_net.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c index 4b564eda5bd..06649d0c209 100644 --- a/drivers/net/ps3_gelic_net.c +++ b/drivers/net/ps3_gelic_net.c @@ -1403,6 +1403,19 @@ void gelic_net_tx_timeout(struct net_device *netdev) atomic_dec(&card->tx_timeout_task_counter); } +static const struct net_device_ops gelic_netdevice_ops = { + .ndo_open = gelic_net_open, + .ndo_stop = gelic_net_stop, + .ndo_start_xmit = gelic_net_xmit, + .ndo_set_multicast_list = gelic_net_set_multi, + .ndo_change_mtu = gelic_net_change_mtu, + .ndo_tx_timeout = gelic_net_tx_timeout, + .ndo_validate_addr = eth_validate_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = gelic_net_poll_controller, +#endif +}; + /** * gelic_ether_setup_netdev_ops - initialization of net_device operations * @netdev: net_device structure @@ -1412,21 +1425,12 @@ void gelic_net_tx_timeout(struct net_device *netdev) static void gelic_ether_setup_netdev_ops(struct net_device *netdev, struct napi_struct *napi) { - netdev->open = &gelic_net_open; - netdev->stop = &gelic_net_stop; - netdev->hard_start_xmit = &gelic_net_xmit; - netdev->set_multicast_list = &gelic_net_set_multi; - netdev->change_mtu = &gelic_net_change_mtu; - /* tx watchdog */ - netdev->tx_timeout = &gelic_net_tx_timeout; netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT; /* NAPI */ netif_napi_add(netdev, napi, gelic_net_poll, GELIC_NET_NAPI_WEIGHT); netdev->ethtool_ops = &gelic_ether_ethtool_ops; -#ifdef CONFIG_NET_POLL_CONTROLLER - netdev->poll_controller = gelic_net_poll_controller; -#endif + netdev->netdev_ops = &gelic_netdevice_ops; } /** -- GitLab From 31e2b7bd21035cb3d7cd567dfdf4f82817c4f6fb Mon Sep 17 00:00:00 2001 From: Masakazu Mokuno Date: Thu, 15 Jan 2009 22:52:55 +0000 Subject: [PATCH 0351/4982] PS3: gelic: wireless: convert the wireless part to net_device_ops Convert the gelic wireless driver to net_device_ops Signed-off-by: Masakazu Mokuno Signed-off-by: David S. Miller --- drivers/net/ps3_gelic_wireless.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c index ec231424668..708ae067c33 100644 --- a/drivers/net/ps3_gelic_wireless.c +++ b/drivers/net/ps3_gelic_wireless.c @@ -2697,6 +2697,19 @@ static int gelic_wl_stop(struct net_device *netdev) /* -- */ +static const struct net_device_ops gelic_wl_netdevice_ops = { + .ndo_open = gelic_wl_open, + .ndo_stop = gelic_wl_stop, + .ndo_start_xmit = gelic_net_xmit, + .ndo_set_multicast_list = gelic_net_set_multi, + .ndo_change_mtu = gelic_net_change_mtu, + .ndo_tx_timeout = gelic_net_tx_timeout, + .ndo_validate_addr = eth_validate_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = gelic_net_poll_controller, +#endif +}; + static struct ethtool_ops gelic_wl_ethtool_ops = { .get_drvinfo = gelic_net_get_drvinfo, .get_link = gelic_wl_get_link, @@ -2711,21 +2724,12 @@ static void gelic_wl_setup_netdev_ops(struct net_device *netdev) struct gelic_wl_info *wl; wl = port_wl(netdev_priv(netdev)); BUG_ON(!wl); - netdev->open = &gelic_wl_open; - netdev->stop = &gelic_wl_stop; - netdev->hard_start_xmit = &gelic_net_xmit; - netdev->set_multicast_list = &gelic_net_set_multi; - netdev->change_mtu = &gelic_net_change_mtu; - netdev->wireless_data = &wl->wireless_data; - netdev->wireless_handlers = &gelic_wl_wext_handler_def; - /* tx watchdog */ - netdev->tx_timeout = &gelic_net_tx_timeout; netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT; netdev->ethtool_ops = &gelic_wl_ethtool_ops; -#ifdef CONFIG_NET_POLL_CONTROLLER - netdev->poll_controller = gelic_net_poll_controller; -#endif + netdev->netdev_ops = &gelic_wl_netdevice_ops; + netdev->wireless_data = &wl->wireless_data; + netdev->wireless_handlers = &gelic_wl_wext_handler_def; } /* -- GitLab From 357fe2c6d2b12482abd1c3f24a086a2f507f03fc Mon Sep 17 00:00:00 2001 From: Vernon Sauder Date: Fri, 16 Jan 2009 13:23:19 +0000 Subject: [PATCH 0352/4982] smc91x: enable ethtool EEPROM interface Signed-off-by: Vernon Sauder Acked-by: Nicolas Pitre Signed-off-by: David S. Miller --- drivers/net/smc91x.c | 116 ++++++++++++++++++++++++++++++++++++++++++- drivers/net/smc91x.h | 10 ++++ 2 files changed, 124 insertions(+), 2 deletions(-) diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index b215a8d85e6..508e8da2f65 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -1643,6 +1643,117 @@ static void smc_ethtool_setmsglevel(struct net_device *dev, u32 level) lp->msg_enable = level; } +static int smc_write_eeprom_word(struct net_device *dev, u16 addr, u16 word) +{ + u16 ctl; + struct smc_local *lp = netdev_priv(dev); + void __iomem *ioaddr = lp->base; + + spin_lock_irq(&lp->lock); + /* load word into GP register */ + SMC_SELECT_BANK(lp, 1); + SMC_SET_GP(lp, word); + /* set the address to put the data in EEPROM */ + SMC_SELECT_BANK(lp, 2); + SMC_SET_PTR(lp, addr); + /* tell it to write */ + SMC_SELECT_BANK(lp, 1); + ctl = SMC_GET_CTL(lp); + SMC_SET_CTL(lp, ctl | (CTL_EEPROM_SELECT | CTL_STORE)); + /* wait for it to finish */ + do { + udelay(1); + } while (SMC_GET_CTL(lp) & CTL_STORE); + /* clean up */ + SMC_SET_CTL(lp, ctl); + SMC_SELECT_BANK(lp, 2); + spin_unlock_irq(&lp->lock); + return 0; +} + +static int smc_read_eeprom_word(struct net_device *dev, u16 addr, u16 *word) +{ + u16 ctl; + struct smc_local *lp = netdev_priv(dev); + void __iomem *ioaddr = lp->base; + + spin_lock_irq(&lp->lock); + /* set the EEPROM address to get the data from */ + SMC_SELECT_BANK(lp, 2); + SMC_SET_PTR(lp, addr | PTR_READ); + /* tell it to load */ + SMC_SELECT_BANK(lp, 1); + SMC_SET_GP(lp, 0xffff); /* init to known */ + ctl = SMC_GET_CTL(lp); + SMC_SET_CTL(lp, ctl | (CTL_EEPROM_SELECT | CTL_RELOAD)); + /* wait for it to finish */ + do { + udelay(1); + } while (SMC_GET_CTL(lp) & CTL_RELOAD); + /* read word from GP register */ + *word = SMC_GET_GP(lp); + /* clean up */ + SMC_SET_CTL(lp, ctl); + SMC_SELECT_BANK(lp, 2); + spin_unlock_irq(&lp->lock); + return 0; +} + +static int smc_ethtool_geteeprom_len(struct net_device *dev) +{ + return 0x23 * 2; +} + +static int smc_ethtool_geteeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *data) +{ + int i; + int imax; + + DBG(1, "Reading %d bytes at %d(0x%x)\n", + eeprom->len, eeprom->offset, eeprom->offset); + imax = smc_ethtool_geteeprom_len(dev); + for (i = 0; i < eeprom->len; i += 2) { + int ret; + u16 wbuf; + int offset = i + eeprom->offset; + if (offset > imax) + break; + ret = smc_read_eeprom_word(dev, offset >> 1, &wbuf); + if (ret != 0) + return ret; + DBG(2, "Read 0x%x from 0x%x\n", wbuf, offset >> 1); + data[i] = (wbuf >> 8) & 0xff; + data[i+1] = wbuf & 0xff; + } + return 0; +} + +static int smc_ethtool_seteeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *data) +{ + int i; + int imax; + + DBG(1, "Writing %d bytes to %d(0x%x)\n", + eeprom->len, eeprom->offset, eeprom->offset); + imax = smc_ethtool_geteeprom_len(dev); + for (i = 0; i < eeprom->len; i += 2) { + int ret; + u16 wbuf; + int offset = i + eeprom->offset; + if (offset > imax) + break; + wbuf = (data[i] << 8) | data[i + 1]; + DBG(2, "Writing 0x%x to 0x%x\n", wbuf, offset >> 1); + ret = smc_write_eeprom_word(dev, offset >> 1, wbuf); + if (ret != 0) + return ret; + } + return 0; +} + + static const struct ethtool_ops smc_ethtool_ops = { .get_settings = smc_ethtool_getsettings, .set_settings = smc_ethtool_setsettings, @@ -1652,8 +1763,9 @@ static const struct ethtool_ops smc_ethtool_ops = { .set_msglevel = smc_ethtool_setmsglevel, .nway_reset = smc_ethtool_nwayreset, .get_link = ethtool_op_get_link, -// .get_eeprom = smc_ethtool_geteeprom, -// .set_eeprom = smc_ethtool_seteeprom, + .get_eeprom_len = smc_ethtool_geteeprom_len, + .get_eeprom = smc_ethtool_geteeprom, + .set_eeprom = smc_ethtool_seteeprom, }; /* diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index c4ccd121bc9..ed9ae43523a 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -1141,6 +1141,16 @@ static const char * chip_ids[ 16 ] = { #define SMC_GET_MII(lp) SMC_inw(ioaddr, MII_REG(lp)) +#define SMC_GET_GP(lp) SMC_inw(ioaddr, GP_REG(lp)) + +#define SMC_SET_GP(lp, x) \ + do { \ + if (SMC_MUST_ALIGN_WRITE(lp)) \ + SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 8, 1)); \ + else \ + SMC_outw(x, ioaddr, GP_REG(lp)); \ + } while (0) + #define SMC_SET_MII(lp, x) SMC_outw(x, ioaddr, MII_REG(lp)) #define SMC_GET_MIR(lp) SMC_inw(ioaddr, MIR_REG(lp)) -- GitLab From 9f4d26d0f3016cf8813977d624751b94465fa317 Mon Sep 17 00:00:00 2001 From: Mark McLoughlin Date: Mon, 19 Jan 2009 17:09:49 -0800 Subject: [PATCH 0353/4982] virtio_net: add link status handling Allow the host to inform us that the link is down by adding a VIRTIO_NET_F_STATUS which indicates that device status is available in virtio_net config. This is currently useful for simulating link down conditions (e.g. using proposed qemu 'set_link' monitor command) but would also be needed if we were to support device assignment via virtio. Signed-off-by: Mark McLoughlin Signed-off-by: Rusty Russell (added future masking) Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 43 +++++++++++++++++++++++++++++++++++++- include/linux/virtio_net.h | 5 +++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 30ae6d9a12a..9b33d6ebf54 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -42,6 +42,7 @@ struct virtnet_info struct virtqueue *rvq, *svq; struct net_device *dev; struct napi_struct napi; + unsigned int status; /* The skb we couldn't send because buffers were full. */ struct sk_buff *last_xmit_skb; @@ -611,6 +612,7 @@ static struct ethtool_ops virtnet_ethtool_ops = { .set_tx_csum = virtnet_set_tx_csum, .set_sg = ethtool_op_set_sg, .set_tso = ethtool_op_set_tso, + .get_link = ethtool_op_get_link, }; #define MIN_MTU 68 @@ -636,6 +638,41 @@ static const struct net_device_ops virtnet_netdev = { #endif }; +static void virtnet_update_status(struct virtnet_info *vi) +{ + u16 v; + + if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) + return; + + vi->vdev->config->get(vi->vdev, + offsetof(struct virtio_net_config, status), + &v, sizeof(v)); + + /* Ignore unknown (future) status bits */ + v &= VIRTIO_NET_S_LINK_UP; + + if (vi->status == v) + return; + + vi->status = v; + + if (vi->status & VIRTIO_NET_S_LINK_UP) { + netif_carrier_on(vi->dev); + netif_wake_queue(vi->dev); + } else { + netif_carrier_off(vi->dev); + netif_stop_queue(vi->dev); + } +} + +static void virtnet_config_changed(struct virtio_device *vdev) +{ + struct virtnet_info *vi = vdev->priv; + + virtnet_update_status(vi); +} + static int virtnet_probe(struct virtio_device *vdev) { int err; @@ -738,6 +775,9 @@ static int virtnet_probe(struct virtio_device *vdev) goto unregister; } + vi->status = VIRTIO_NET_S_LINK_UP; + virtnet_update_status(vi); + pr_debug("virtnet: registered device %s\n", dev->name); return 0; @@ -793,7 +833,7 @@ static unsigned int features[] = { VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6, VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */ - VIRTIO_NET_F_MRG_RXBUF, + VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_F_NOTIFY_ON_EMPTY, }; @@ -805,6 +845,7 @@ static struct virtio_driver virtio_net = { .id_table = id_table, .probe = virtnet_probe, .remove = __devexit_p(virtnet_remove), + .config_changed = virtnet_config_changed, }; static int __init init(void) diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index 5cdd0aa8bde..f76bd4a753e 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -21,11 +21,16 @@ #define VIRTIO_NET_F_HOST_ECN 13 /* Host can handle TSO[6] w/ ECN in. */ #define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */ #define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */ +#define VIRTIO_NET_F_STATUS 16 /* virtio_net_config.status available */ + +#define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ struct virtio_net_config { /* The config defining mac address (if VIRTIO_NET_F_MAC) */ __u8 mac[6]; + /* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */ + __u16 status; } __attribute__((packed)); /* This is the first element of the scatter-gather list. If you don't -- GitLab From 57a574993d94671b495cdbe8aeb78b745abfe14f Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Mon, 19 Jan 2009 17:14:21 -0800 Subject: [PATCH 0354/4982] phylib: unsigneds go unnoticed both pdata->mdc and pdata->mdio are unsigned. Notice a negative return value. Signed-off-by: Roel Kluin Signed-off-by: David S. Miller --- drivers/net/phy/mdio-gpio.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index a439ebeb431..3f460c56492 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c @@ -200,16 +200,21 @@ static int __devinit mdio_ofgpio_probe(struct of_device *ofdev, { struct device_node *np = NULL; struct mdio_gpio_platform_data *pdata; + int ret; pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; - pdata->mdc = of_get_gpio(ofdev->node, 0); - pdata->mdio = of_get_gpio(ofdev->node, 1); - - if (pdata->mdc < 0 || pdata->mdio < 0) + ret = of_get_gpio(ofdev->node, 0); + if (ret < 0) goto out_free; + pdata->mdc = ret; + + ret = of_get_gpio(ofdev->node, 1); + if (ret < 0) + goto out_free; + pdata->mdio = ret; while ((np = of_get_next_child(ofdev->node, np))) if (!strcmp(np->type, "ethernet-phy")) -- GitLab From 749c10f931923451a4c59b4435d182aa9ae27a4f Mon Sep 17 00:00:00 2001 From: Timo Teras Date: Mon, 19 Jan 2009 17:22:12 -0800 Subject: [PATCH 0355/4982] gre: strict physical device binding Check the device on receive path and allow otherwise identical devices as long as the physical device differs. This is useful for NBMA tunnels, where you want to use different gre IP for each public IP available via different physical devices. Signed-off-by: Timo Teras Signed-off-by: David S. Miller --- net/ipv4/ip_gre.c | 128 +++++++++++++++++++++++++++++++--------------- 1 file changed, 88 insertions(+), 40 deletions(-) diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 0101521f366..4a43739c903 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -164,67 +164,113 @@ static DEFINE_RWLOCK(ipgre_lock); /* Given src, dst and key, find appropriate for input tunnel. */ -static struct ip_tunnel * ipgre_tunnel_lookup(struct net *net, +static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev, __be32 remote, __be32 local, __be32 key, __be16 gre_proto) { + struct net *net = dev_net(dev); + int link = dev->ifindex; unsigned h0 = HASH(remote); unsigned h1 = HASH(key); - struct ip_tunnel *t; - struct ip_tunnel *t2 = NULL; + struct ip_tunnel *t, *sel[4] = { NULL, NULL, NULL, NULL }; struct ipgre_net *ign = net_generic(net, ipgre_net_id); int dev_type = (gre_proto == htons(ETH_P_TEB)) ? ARPHRD_ETHER : ARPHRD_IPGRE; + int idx; for (t = ign->tunnels_r_l[h0^h1]; t; t = t->next) { - if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) { - if (t->parms.i_key == key && t->dev->flags & IFF_UP) { - if (t->dev->type == dev_type) - return t; - if (t->dev->type == ARPHRD_IPGRE && !t2) - t2 = t; - } - } + if (local != t->parms.iph.saddr || + remote != t->parms.iph.daddr || + key != t->parms.i_key || + !(t->dev->flags & IFF_UP)) + continue; + + if (t->dev->type != ARPHRD_IPGRE && + t->dev->type != dev_type) + continue; + + idx = 0; + if (t->parms.link != link) + idx |= 1; + if (t->dev->type != dev_type) + idx |= 2; + if (idx == 0) + return t; + if (sel[idx] == NULL) + sel[idx] = t; } for (t = ign->tunnels_r[h0^h1]; t; t = t->next) { - if (remote == t->parms.iph.daddr) { - if (t->parms.i_key == key && t->dev->flags & IFF_UP) { - if (t->dev->type == dev_type) - return t; - if (t->dev->type == ARPHRD_IPGRE && !t2) - t2 = t; - } - } + if (remote != t->parms.iph.daddr || + key != t->parms.i_key || + !(t->dev->flags & IFF_UP)) + continue; + + if (t->dev->type != ARPHRD_IPGRE && + t->dev->type != dev_type) + continue; + + idx = 0; + if (t->parms.link != link) + idx |= 1; + if (t->dev->type != dev_type) + idx |= 2; + if (idx == 0) + return t; + if (sel[idx] == NULL) + sel[idx] = t; } for (t = ign->tunnels_l[h1]; t; t = t->next) { - if (local == t->parms.iph.saddr || - (local == t->parms.iph.daddr && - ipv4_is_multicast(local))) { - if (t->parms.i_key == key && t->dev->flags & IFF_UP) { - if (t->dev->type == dev_type) - return t; - if (t->dev->type == ARPHRD_IPGRE && !t2) - t2 = t; - } - } + if ((local != t->parms.iph.saddr && + (local != t->parms.iph.daddr || + !ipv4_is_multicast(local))) || + key != t->parms.i_key || + !(t->dev->flags & IFF_UP)) + continue; + + if (t->dev->type != ARPHRD_IPGRE && + t->dev->type != dev_type) + continue; + + idx = 0; + if (t->parms.link != link) + idx |= 1; + if (t->dev->type != dev_type) + idx |= 2; + if (idx == 0) + return t; + if (sel[idx] == NULL) + sel[idx] = t; } for (t = ign->tunnels_wc[h1]; t; t = t->next) { - if (t->parms.i_key == key && t->dev->flags & IFF_UP) { - if (t->dev->type == dev_type) - return t; - if (t->dev->type == ARPHRD_IPGRE && !t2) - t2 = t; - } + if (t->parms.i_key != key || + !(t->dev->flags & IFF_UP)) + continue; + + if (t->dev->type != ARPHRD_IPGRE && + t->dev->type != dev_type) + continue; + + idx = 0; + if (t->parms.link != link) + idx |= 1; + if (t->dev->type != dev_type) + idx |= 2; + if (idx == 0) + return t; + if (sel[idx] == NULL) + sel[idx] = t; } - if (t2) - return t2; + for (idx = 1; idx < ARRAY_SIZE(sel); idx++) + if (sel[idx] != NULL) + return sel[idx]; - if (ign->fb_tunnel_dev->flags&IFF_UP) + if (ign->fb_tunnel_dev->flags & IFF_UP) return netdev_priv(ign->fb_tunnel_dev); + return NULL; } @@ -284,6 +330,7 @@ static struct ip_tunnel *ipgre_tunnel_find(struct net *net, __be32 remote = parms->iph.daddr; __be32 local = parms->iph.saddr; __be32 key = parms->i_key; + int link = parms->link; struct ip_tunnel *t, **tp; struct ipgre_net *ign = net_generic(net, ipgre_net_id); @@ -291,6 +338,7 @@ static struct ip_tunnel *ipgre_tunnel_find(struct net *net, if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr && key == t->parms.i_key && + link == t->parms.link && type == t->dev->type) break; @@ -421,7 +469,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info) } read_lock(&ipgre_lock); - t = ipgre_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr, + t = ipgre_tunnel_lookup(skb->dev, iph->daddr, iph->saddr, flags & GRE_KEY ? *(((__be32 *)p) + (grehlen / 4) - 1) : 0, p[1]); @@ -518,7 +566,7 @@ static int ipgre_rcv(struct sk_buff *skb) gre_proto = *(__be16 *)(h + 2); read_lock(&ipgre_lock); - if ((tunnel = ipgre_tunnel_lookup(dev_net(skb->dev), + if ((tunnel = ipgre_tunnel_lookup(skb->dev, iph->saddr, iph->daddr, key, gre_proto))) { struct net_device_stats *stats = &tunnel->dev->stats; -- GitLab From 7be2df451fa916f93e37763a58d33483feb0909f Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 21 Jan 2009 14:39:13 -0800 Subject: [PATCH 0356/4982] cxgb3: Replace LRO with GRO This patch makes cxgb3 invoke the GRO hooks instead of LRO. As GRO has a compatible external interface to LRO this is a very straightforward replacement. I've kept the ioctl controls for per-queue LRO switches. However, we should not encourage anyone to use these. Because of that, I've also kept the skb construction code in cxgb3. Hopefully we can phase out those per-queue switches and then kill this too. Signed-off-by: Herbert Xu Acked-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/Kconfig | 1 - drivers/net/cxgb3/adapter.h | 13 +--- drivers/net/cxgb3/cxgb3_main.c | 42 ++--------- drivers/net/cxgb3/sge.c | 119 +++++-------------------------- drivers/scsi/cxgb3i/cxgb3i_ddp.h | 2 + 5 files changed, 24 insertions(+), 153 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 805682586c8..c4776a2adf0 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2407,7 +2407,6 @@ config CHELSIO_T3 tristate "Chelsio Communications T3 10Gb Ethernet support" depends on CHELSIO_T3_DEPENDS select FW_LOADER - select INET_LRO help This driver supports Chelsio T3-based gigabit and 10Gb Ethernet adapters. diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h index 5fb7c6851eb..fbe15699584 100644 --- a/drivers/net/cxgb3/adapter.h +++ b/drivers/net/cxgb3/adapter.h @@ -42,7 +42,6 @@ #include #include #include -#include #include "t3cdev.h" #include @@ -178,15 +177,11 @@ enum { /* per port SGE statistics */ SGE_PSTAT_TX_CSUM, /* # of TX checksum offloads */ SGE_PSTAT_VLANEX, /* # of VLAN tag extractions */ SGE_PSTAT_VLANINS, /* # of VLAN tag insertions */ - SGE_PSTAT_LRO_AGGR, /* # of page chunks added to LRO sessions */ - SGE_PSTAT_LRO_FLUSHED, /* # of flushed LRO sessions */ - SGE_PSTAT_LRO_NO_DESC, /* # of overflown LRO sessions */ SGE_PSTAT_MAX /* must be last */ }; -#define T3_MAX_LRO_SES 8 -#define T3_MAX_LRO_MAX_PKTS 64 +struct napi_gro_fraginfo; struct sge_qset { /* an SGE queue set */ struct adapter *adap; @@ -194,12 +189,8 @@ struct sge_qset { /* an SGE queue set */ struct sge_rspq rspq; struct sge_fl fl[SGE_RXQ_PER_SET]; struct sge_txq txq[SGE_TXQ_PER_SET]; - struct net_lro_mgr lro_mgr; - struct net_lro_desc lro_desc[T3_MAX_LRO_SES]; - struct skb_frag_struct *lro_frag_tbl; - int lro_nfrags; + struct napi_gro_fraginfo lro_frag_tbl; int lro_enabled; - int lro_frag_len; void *lro_va; struct net_device *netdev; struct netdev_queue *tx_q; /* associated netdev TX queue */ diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 52131bd4cc7..7381f378b4e 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -508,19 +508,9 @@ static void set_qset_lro(struct net_device *dev, int qset_idx, int val) { struct port_info *pi = netdev_priv(dev); struct adapter *adapter = pi->adapter; - int i, lro_on = 1; adapter->params.sge.qset[qset_idx].lro = !!val; adapter->sge.qs[qset_idx].lro_enabled = !!val; - - /* let ethtool report LRO on only if all queues are LRO enabled */ - for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; ++i) - lro_on &= adapter->params.sge.qset[i].lro; - - if (lro_on) - dev->features |= NETIF_F_LRO; - else - dev->features &= ~NETIF_F_LRO; } /** @@ -1433,9 +1423,9 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats, *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_VLANINS); *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_TX_CSUM); *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_RX_CSUM_GOOD); - *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_LRO_AGGR); - *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_LRO_FLUSHED); - *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_LRO_NO_DESC); + *data++ = 0; + *data++ = 0; + *data++ = 0; *data++ = s->rx_cong_drops; *data++ = s->num_toggled; @@ -1826,28 +1816,6 @@ static void get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) memset(&wol->sopass, 0, sizeof(wol->sopass)); } -static int cxgb3_set_flags(struct net_device *dev, u32 data) -{ - struct port_info *pi = netdev_priv(dev); - int i; - - if (data & ETH_FLAG_LRO) { - if (!(pi->rx_offload & T3_RX_CSUM)) - return -EINVAL; - - pi->rx_offload |= T3_LRO; - for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; i++) - set_qset_lro(dev, i, 1); - - } else { - pi->rx_offload &= ~T3_LRO; - for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; i++) - set_qset_lro(dev, i, 0); - } - - return 0; -} - static const struct ethtool_ops cxgb_ethtool_ops = { .get_settings = get_settings, .set_settings = set_settings, @@ -1877,8 +1845,6 @@ static const struct ethtool_ops cxgb_ethtool_ops = { .get_regs = get_regs, .get_wol = get_wol, .set_tso = ethtool_op_set_tso, - .get_flags = ethtool_op_get_flags, - .set_flags = cxgb3_set_flags, }; static int in_range(int val, int lo, int hi) @@ -2967,7 +2933,7 @@ static int __devinit init_one(struct pci_dev *pdev, netdev->mem_end = mmio_start + mmio_len - 1; netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO; netdev->features |= NETIF_F_LLTX; - netdev->features |= NETIF_F_LRO; + netdev->features |= NETIF_F_GRO; if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 379a1324db4..8299fb538f2 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -585,8 +585,7 @@ static void t3_reset_qset(struct sge_qset *q) memset(q->txq, 0, sizeof(struct sge_txq) * SGE_TXQ_PER_SET); q->txq_stopped = 0; q->tx_reclaim_timer.function = NULL; /* for t3_stop_sge_timers() */ - kfree(q->lro_frag_tbl); - q->lro_nfrags = q->lro_frag_len = 0; + q->lro_frag_tbl.nr_frags = q->lro_frag_tbl.len = 0; } @@ -1945,10 +1944,8 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq, qs->port_stats[SGE_PSTAT_VLANEX]++; if (likely(grp)) if (lro) - lro_vlan_hwaccel_receive_skb(&qs->lro_mgr, skb, - grp, - ntohs(p->vlan), - p); + vlan_gro_receive(&qs->napi, grp, + ntohs(p->vlan), skb); else { if (unlikely(pi->iscsi_ipv4addr && is_arp(skb))) { @@ -1965,7 +1962,7 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq, dev_kfree_skb_any(skb); } else if (rq->polling) { if (lro) - lro_receive_skb(&qs->lro_mgr, skb, p); + napi_gro_receive(&qs->napi, skb); else { if (unlikely(pi->iscsi_ipv4addr && is_arp(skb))) cxgb3_arp_process(adap, skb); @@ -1980,59 +1977,6 @@ static inline int is_eth_tcp(u32 rss) return G_HASHTYPE(ntohl(rss)) == RSS_HASH_4_TUPLE; } -/** - * lro_frame_ok - check if an ingress packet is eligible for LRO - * @p: the CPL header of the packet - * - * Returns true if a received packet is eligible for LRO. - * The following conditions must be true: - * - packet is TCP/IP Ethernet II (checked elsewhere) - * - not an IP fragment - * - no IP options - * - TCP/IP checksums are correct - * - the packet is for this host - */ -static inline int lro_frame_ok(const struct cpl_rx_pkt *p) -{ - const struct ethhdr *eh = (struct ethhdr *)(p + 1); - const struct iphdr *ih = (struct iphdr *)(eh + 1); - - return (*((u8 *)p + 1) & 0x90) == 0x10 && p->csum == htons(0xffff) && - eh->h_proto == htons(ETH_P_IP) && ih->ihl == (sizeof(*ih) >> 2); -} - -static int t3_get_lro_header(void **eh, void **iph, void **tcph, - u64 *hdr_flags, void *priv) -{ - const struct cpl_rx_pkt *cpl = priv; - - if (!lro_frame_ok(cpl)) - return -1; - - *eh = (struct ethhdr *)(cpl + 1); - *iph = (struct iphdr *)((struct ethhdr *)*eh + 1); - *tcph = (struct tcphdr *)((struct iphdr *)*iph + 1); - - *hdr_flags = LRO_IPV4 | LRO_TCP; - return 0; -} - -static int t3_get_skb_header(struct sk_buff *skb, - void **iph, void **tcph, u64 *hdr_flags, - void *priv) -{ - void *eh; - - return t3_get_lro_header(&eh, iph, tcph, hdr_flags, priv); -} - -static int t3_get_frag_header(struct skb_frag_struct *frag, void **eh, - void **iph, void **tcph, u64 *hdr_flags, - void *priv) -{ - return t3_get_lro_header(eh, iph, tcph, hdr_flags, priv); -} - /** * lro_add_page - add a page chunk to an LRO session * @adap: the adapter @@ -2049,8 +1993,9 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs, { struct rx_sw_desc *sd = &fl->sdesc[fl->cidx]; struct cpl_rx_pkt *cpl; - struct skb_frag_struct *rx_frag = qs->lro_frag_tbl; - int nr_frags = qs->lro_nfrags, frag_len = qs->lro_frag_len; + struct skb_frag_struct *rx_frag = qs->lro_frag_tbl.frags; + int nr_frags = qs->lro_frag_tbl.nr_frags; + int frag_len = qs->lro_frag_tbl.len; int offset = 0; if (!nr_frags) { @@ -2069,13 +2014,13 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs, rx_frag->page_offset = sd->pg_chunk.offset + offset; rx_frag->size = len; frag_len += len; - qs->lro_nfrags++; - qs->lro_frag_len = frag_len; + qs->lro_frag_tbl.nr_frags++; + qs->lro_frag_tbl.len = frag_len; if (!complete) return; - qs->lro_nfrags = qs->lro_frag_len = 0; + qs->lro_frag_tbl.ip_summed = CHECKSUM_UNNECESSARY; cpl = qs->lro_va; if (unlikely(cpl->vlan_valid)) { @@ -2084,36 +2029,15 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs, struct vlan_group *grp = pi->vlan_grp; if (likely(grp != NULL)) { - lro_vlan_hwaccel_receive_frags(&qs->lro_mgr, - qs->lro_frag_tbl, - frag_len, frag_len, - grp, ntohs(cpl->vlan), - cpl, 0); - return; + vlan_gro_frags(&qs->napi, grp, ntohs(cpl->vlan), + &qs->lro_frag_tbl); + goto out; } } - lro_receive_frags(&qs->lro_mgr, qs->lro_frag_tbl, - frag_len, frag_len, cpl, 0); -} + napi_gro_frags(&qs->napi, &qs->lro_frag_tbl); -/** - * init_lro_mgr - initialize a LRO manager object - * @lro_mgr: the LRO manager object - */ -static void init_lro_mgr(struct sge_qset *qs, struct net_lro_mgr *lro_mgr) -{ - lro_mgr->dev = qs->netdev; - lro_mgr->features = LRO_F_NAPI; - lro_mgr->frag_align_pad = NET_IP_ALIGN; - lro_mgr->ip_summed = CHECKSUM_UNNECESSARY; - lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY; - lro_mgr->max_desc = T3_MAX_LRO_SES; - lro_mgr->lro_arr = qs->lro_desc; - lro_mgr->get_frag_header = t3_get_frag_header; - lro_mgr->get_skb_header = t3_get_skb_header; - lro_mgr->max_aggr = T3_MAX_LRO_MAX_PKTS; - if (lro_mgr->max_aggr > MAX_SKB_FRAGS) - lro_mgr->max_aggr = MAX_SKB_FRAGS; +out: + qs->lro_frag_tbl.nr_frags = qs->lro_frag_tbl.len = 0; } /** @@ -2357,10 +2281,6 @@ next_fl: } deliver_partial_bundle(&adap->tdev, q, offload_skbs, ngathered); - lro_flush_all(&qs->lro_mgr); - qs->port_stats[SGE_PSTAT_LRO_AGGR] = qs->lro_mgr.stats.aggregated; - qs->port_stats[SGE_PSTAT_LRO_FLUSHED] = qs->lro_mgr.stats.flushed; - qs->port_stats[SGE_PSTAT_LRO_NO_DESC] = qs->lro_mgr.stats.no_desc; if (sleeping) check_ring_db(adap, qs, sleeping); @@ -2907,7 +2827,6 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, { int i, avail, ret = -ENOMEM; struct sge_qset *q = &adapter->sge.qs[id]; - struct net_lro_mgr *lro_mgr = &q->lro_mgr; init_qset_cntxt(q, id); setup_timer(&q->tx_reclaim_timer, sge_timer_cb, (unsigned long)q); @@ -2987,10 +2906,6 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, q->fl[0].order = FL0_PG_ORDER; q->fl[1].order = FL1_PG_ORDER; - q->lro_frag_tbl = kcalloc(MAX_FRAME_SIZE / FL1_PG_CHUNK_SIZE + 1, - sizeof(struct skb_frag_struct), - GFP_KERNEL); - q->lro_nfrags = q->lro_frag_len = 0; spin_lock_irq(&adapter->sge.reg_lock); /* FL threshold comparison uses < */ @@ -3042,8 +2957,6 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, q->tx_q = netdevq; t3_update_qset_coalesce(q, p); - init_lro_mgr(q, lro_mgr); - avail = refill_fl(adapter, &q->fl[0], q->fl[0].size, GFP_KERNEL | __GFP_COMP); if (!avail) { diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.h b/drivers/scsi/cxgb3i/cxgb3i_ddp.h index 5c7c4d95c49..f675807cc48 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_ddp.h +++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.h @@ -13,6 +13,8 @@ #ifndef __CXGB3I_ULP2_DDP_H__ #define __CXGB3I_ULP2_DDP_H__ +#include + /** * struct cxgb3i_tag_format - cxgb3i ulp tag format for an iscsi entity * -- GitLab From 52d07b1f5039f51101a589856d9058e9cc8ce5dc Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Mon, 19 Jan 2009 17:27:06 -0800 Subject: [PATCH 0357/4982] bnx2: annotate bp->phy_lock functions It looks like the locking is OK as the locks were being taken before the various phy setup functions, add the annotations as they release and reacquire the phy_lock. Signed-off-by: Harvey Harrison Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index e817802b248..fe575b9a9b7 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -1497,6 +1497,8 @@ static int bnx2_fw_sync(struct bnx2 *, u32, int, int); static int bnx2_setup_remote_phy(struct bnx2 *bp, u8 port) +__releases(&bp->phy_lock) +__acquires(&bp->phy_lock) { u32 speed_arg = 0, pause_adv; @@ -1554,6 +1556,8 @@ bnx2_setup_remote_phy(struct bnx2 *bp, u8 port) static int bnx2_setup_serdes_phy(struct bnx2 *bp, u8 port) +__releases(&bp->phy_lock) +__acquires(&bp->phy_lock) { u32 adv, bmcr; u32 new_adv = 0; @@ -1866,6 +1870,8 @@ bnx2_set_remote_link(struct bnx2 *bp) static int bnx2_setup_copper_phy(struct bnx2 *bp) +__releases(&bp->phy_lock) +__acquires(&bp->phy_lock) { u32 bmcr; u32 new_bmcr; @@ -1963,6 +1969,8 @@ bnx2_setup_copper_phy(struct bnx2 *bp) static int bnx2_setup_phy(struct bnx2 *bp, u8 port) +__releases(&bp->phy_lock) +__acquires(&bp->phy_lock) { if (bp->loopback == MAC_LOOPBACK) return 0; @@ -2176,6 +2184,8 @@ bnx2_init_copper_phy(struct bnx2 *bp, int reset_phy) static int bnx2_init_phy(struct bnx2 *bp, int reset_phy) +__releases(&bp->phy_lock) +__acquires(&bp->phy_lock) { u32 val; int rc = 0; -- GitLab From 5851765cca21e973a7f4850fbaf1ef55e0cb1965 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 21 Jan 2009 14:42:07 -0800 Subject: [PATCH 0358/4982] igb: igb should not flag lltx Igb has flags enabling lltx but this is a holdover from the earlier e1000 driver which the igb driver was based off of. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index dbe03c2b49c..e11043d90db 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1197,7 +1197,6 @@ static int __devinit igb_probe(struct pci_dev *pdev, if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; - netdev->features |= NETIF_F_LLTX; adapter->en_mng_pt = igb_enable_mng_pass_thru(&adapter->hw); /* before reading the NVM, reset the controller to put the device in a -- GitLab From 921aa7491201b238589ab9f94184b18a1ed00e12 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 21 Jan 2009 14:42:28 -0800 Subject: [PATCH 0359/4982] igb: make certain to power on optics for 82576 fiber nics It appears that a step was missed in the initialization of 82576 fiber nics that resulted in it not powering on the optics. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_82575.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index f5e2e7235fc..9b367ba8e26 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -1103,6 +1103,13 @@ static s32 igb_setup_fiber_serdes_link_82575(struct e1000_hw *hw) E1000_CTRL_SWDPIN1; wr32(E1000_CTRL, reg); + /* Power on phy for 82576 fiber adapters */ + if (hw->mac.type == e1000_82576) { + reg = rd32(E1000_CTRL_EXT); + reg &= ~E1000_CTRL_EXT_SDP7_DATA; + wr32(E1000_CTRL_EXT, reg); + } + /* Set switch control to serdes energy detect */ reg = rd32(E1000_CONNSW); reg |= E1000_CONNSW_ENRGSRC; -- GitLab From 8017943e6b177f117e4be71f09a38e2c9fd56193 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 21 Jan 2009 14:42:47 -0800 Subject: [PATCH 0360/4982] e1000: drop lltx, remove unnecessary lock LLTX is deprecated, don't use it. This completes the removal of LLTX from the Intel Network drivers. Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000.h | 2 -- drivers/net/e1000/e1000_main.c | 29 +++-------------------------- 2 files changed, 3 insertions(+), 28 deletions(-) diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index f5581de0475..e9a416f4016 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -182,7 +182,6 @@ struct e1000_tx_ring { /* array of buffer information structs */ struct e1000_buffer *buffer_info; - spinlock_t tx_lock; u16 tdh; u16 tdt; bool last_tx_tso; @@ -238,7 +237,6 @@ struct e1000_adapter { u16 link_speed; u16 link_duplex; spinlock_t stats_lock; - spinlock_t tx_queue_lock; unsigned int total_tx_bytes; unsigned int total_tx_packets; unsigned int total_rx_bytes; diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index ffe466e0afb..7ec1a0c5a0c 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -31,7 +31,7 @@ char e1000_driver_name[] = "e1000"; static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; -#define DRV_VERSION "7.3.20-k3-NAPI" +#define DRV_VERSION "7.3.21-k2-NAPI" const char e1000_driver_version[] = DRV_VERSION; static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation."; @@ -1048,8 +1048,6 @@ static int __devinit e1000_probe(struct pci_dev *pdev, if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; - netdev->features |= NETIF_F_LLTX; - netdev->vlan_features |= NETIF_F_TSO; netdev->vlan_features |= NETIF_F_TSO6; netdev->vlan_features |= NETIF_F_HW_CSUM; @@ -1368,8 +1366,6 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter) return -ENOMEM; } - spin_lock_init(&adapter->tx_queue_lock); - /* Explicitly disable IRQ since the NIC can be in any state. */ e1000_irq_disable(adapter); @@ -1624,7 +1620,6 @@ setup_tx_desc_die: txdr->next_to_use = 0; txdr->next_to_clean = 0; - spin_lock_init(&txdr->tx_lock); return 0; } @@ -3185,7 +3180,6 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) unsigned int max_txd_pwr = E1000_MAX_TXD_PWR; unsigned int tx_flags = 0; unsigned int len = skb->len - skb->data_len; - unsigned long flags; unsigned int nr_frags; unsigned int mss; int count = 0; @@ -3290,22 +3284,15 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) (hw->mac_type == e1000_82573)) e1000_transfer_dhcp_info(adapter, skb); - if (!spin_trylock_irqsave(&tx_ring->tx_lock, flags)) - /* Collision - tell upper layer to requeue */ - return NETDEV_TX_LOCKED; - /* need: count + 2 desc gap to keep tail from touching * head, otherwise try next time */ - if (unlikely(e1000_maybe_stop_tx(netdev, tx_ring, count + 2))) { - spin_unlock_irqrestore(&tx_ring->tx_lock, flags); + if (unlikely(e1000_maybe_stop_tx(netdev, tx_ring, count + 2))) return NETDEV_TX_BUSY; - } if (unlikely(hw->mac_type == e1000_82547)) { if (unlikely(e1000_82547_fifo_workaround(adapter, skb))) { netif_stop_queue(netdev); mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1); - spin_unlock_irqrestore(&tx_ring->tx_lock, flags); return NETDEV_TX_BUSY; } } @@ -3320,7 +3307,6 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) tso = e1000_tso(adapter, tx_ring, skb); if (tso < 0) { dev_kfree_skb_any(skb); - spin_unlock_irqrestore(&tx_ring->tx_lock, flags); return NETDEV_TX_OK; } @@ -3345,7 +3331,6 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) /* Make sure there is space in the ring for the next send. */ e1000_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2); - spin_unlock_irqrestore(&tx_ring->tx_lock, flags); return NETDEV_TX_OK; } @@ -3773,15 +3758,7 @@ static int e1000_clean(struct napi_struct *napi, int budget) adapter = netdev_priv(poll_dev); - /* e1000_clean is called per-cpu. This lock protects - * tx_ring[0] from being cleaned by multiple cpus - * simultaneously. A failure obtaining the lock means - * tx_ring[0] is currently being cleaned anyway. */ - if (spin_trylock(&adapter->tx_queue_lock)) { - tx_cleaned = e1000_clean_tx_irq(adapter, - &adapter->tx_ring[0]); - spin_unlock(&adapter->tx_queue_lock); - } + tx_cleaned = e1000_clean_tx_irq(adapter, &adapter->tx_ring[0]); adapter->clean_rx(adapter, &adapter->rx_ring[0], &work_done, budget); -- GitLab From 086c1b2c52f03d128d1a6db47f8736c56e915043 Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Wed, 21 Jan 2009 14:43:59 -0800 Subject: [PATCH 0361/4982] ehea: Use net_device_ops structure Adapt to lately introduced net_device_ops structure. Signed-off-by: Thomas Klein Signed-off-by: David S. Miller --- drivers/net/ehea/ehea.h | 2 +- drivers/net/ehea/ehea_main.c | 33 +++++++++++++++++++-------------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 6271b9411cc..f7e2ccfd3e8 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -40,7 +40,7 @@ #include #define DRV_NAME "ehea" -#define DRV_VERSION "EHEA_0096" +#define DRV_VERSION "EHEA_0097" /* eHEA capability flags */ #define DLPAR_PORT_ADD_REM 1 diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 8dc2047da5c..d0c2c4569f2 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -3069,6 +3069,22 @@ static void ehea_unregister_port(struct ehea_port *port) of_device_unregister(&port->ofdev); } +static const struct net_device_ops ehea_netdev_ops = { + .ndo_open = ehea_open, + .ndo_stop = ehea_stop, + .ndo_start_xmit = ehea_start_xmit, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = ehea_netpoll, +#endif + .ndo_get_stats = ehea_get_stats, + .ndo_set_mac_address = ehea_set_mac_addr, + .ndo_set_multicast_list = ehea_set_multicast_list, + .ndo_change_mtu = ehea_change_mtu, + .ndo_vlan_rx_register = ehea_vlan_rx_register, + .ndo_vlan_rx_add_vid = ehea_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = ehea_vlan_rx_kill_vid +}; + struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter, u32 logical_port_id, struct device_node *dn) @@ -3121,19 +3137,9 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter, /* initialize net_device structure */ memcpy(dev->dev_addr, &port->mac_addr, ETH_ALEN); - dev->open = ehea_open; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = ehea_netpoll; -#endif - dev->stop = ehea_stop; - dev->hard_start_xmit = ehea_start_xmit; - dev->get_stats = ehea_get_stats; - dev->set_multicast_list = ehea_set_multicast_list; - dev->set_mac_address = ehea_set_mac_addr; - dev->change_mtu = ehea_change_mtu; - dev->vlan_rx_register = ehea_vlan_rx_register; - dev->vlan_rx_add_vid = ehea_vlan_rx_add_vid; - dev->vlan_rx_kill_vid = ehea_vlan_rx_kill_vid; + dev->netdev_ops = &ehea_netdev_ops; + ehea_set_ethtool_ops(dev); + dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER @@ -3142,7 +3148,6 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter, dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT; INIT_WORK(&port->reset_task, ehea_reset_port); - ehea_set_ethtool_ops(dev); ret = register_netdev(dev); if (ret) { -- GitLab From 3faf2693bd6800c2521799f6a9ae174d9f080ed2 Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Wed, 21 Jan 2009 14:45:33 -0800 Subject: [PATCH 0362/4982] ehea: Fix mem allocations which require page alignment PAGE_SIZE allocations via slab are not guaranteed to be page-aligned. Fixed all memory allocations where page alignment is required by firmware. Signed-off-by: Thomas Klein Signed-off-by: David S. Miller --- drivers/net/ehea/ehea_main.c | 56 ++++++++++++++++++------------------ drivers/net/ehea/ehea_qmr.c | 4 +-- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index d0c2c4569f2..dfcdd7f21c7 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -308,7 +308,7 @@ static struct net_device_stats *ehea_get_stats(struct net_device *dev) memset(stats, 0, sizeof(*stats)); - cb2 = kzalloc(PAGE_SIZE, GFP_ATOMIC); + cb2 = (void *)get_zeroed_page(GFP_ATOMIC); if (!cb2) { ehea_error("no mem for cb2"); goto out; @@ -341,7 +341,7 @@ static struct net_device_stats *ehea_get_stats(struct net_device *dev) stats->rx_packets = rx_packets; out_herr: - kfree(cb2); + free_page((unsigned long)cb2); out: return stats; } @@ -915,7 +915,7 @@ int ehea_sense_port_attr(struct ehea_port *port) struct hcp_ehea_port_cb0 *cb0; /* may be called via ehea_neq_tasklet() */ - cb0 = kzalloc(PAGE_SIZE, GFP_ATOMIC); + cb0 = (void *)get_zeroed_page(GFP_ATOMIC); if (!cb0) { ehea_error("no mem for cb0"); ret = -ENOMEM; @@ -996,7 +996,7 @@ int ehea_sense_port_attr(struct ehea_port *port) out_free: if (ret || netif_msg_probe(port)) ehea_dump(cb0, sizeof(*cb0), "ehea_sense_port_attr"); - kfree(cb0); + free_page((unsigned long)cb0); out: return ret; } @@ -1007,7 +1007,7 @@ int ehea_set_portspeed(struct ehea_port *port, u32 port_speed) u64 hret; int ret = 0; - cb4 = kzalloc(PAGE_SIZE, GFP_KERNEL); + cb4 = (void *)get_zeroed_page(GFP_KERNEL); if (!cb4) { ehea_error("no mem for cb4"); ret = -ENOMEM; @@ -1075,7 +1075,7 @@ int ehea_set_portspeed(struct ehea_port *port, u32 port_speed) if (!prop_carrier_state || (port->phy_link == EHEA_PHY_LINK_UP)) netif_carrier_on(port->netdev); - kfree(cb4); + free_page((unsigned long)cb4); out: return ret; } @@ -1302,7 +1302,7 @@ static int ehea_configure_port(struct ehea_port *port) struct hcp_ehea_port_cb0 *cb0; ret = -ENOMEM; - cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL); + cb0 = (void *)get_zeroed_page(GFP_KERNEL); if (!cb0) goto out; @@ -1338,7 +1338,7 @@ static int ehea_configure_port(struct ehea_port *port) ret = 0; out_free: - kfree(cb0); + free_page((unsigned long)cb0); out: return ret; } @@ -1748,7 +1748,7 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa) goto out; } - cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL); + cb0 = (void *)get_zeroed_page(GFP_KERNEL); if (!cb0) { ehea_error("no mem for cb0"); ret = -ENOMEM; @@ -1793,7 +1793,7 @@ out_upregs: ehea_update_bcmc_registrations(); spin_unlock(&ehea_bcmc_regs.lock); out_free: - kfree(cb0); + free_page((unsigned long)cb0); out: return ret; } @@ -1817,7 +1817,7 @@ static void ehea_promiscuous(struct net_device *dev, int enable) if ((enable && port->promisc) || (!enable && !port->promisc)) return; - cb7 = kzalloc(PAGE_SIZE, GFP_ATOMIC); + cb7 = (void *)get_zeroed_page(GFP_ATOMIC); if (!cb7) { ehea_error("no mem for cb7"); goto out; @@ -1836,7 +1836,7 @@ static void ehea_promiscuous(struct net_device *dev, int enable) port->promisc = enable; out: - kfree(cb7); + free_page((unsigned long)cb7); return; } @@ -2217,7 +2217,7 @@ static void ehea_vlan_rx_register(struct net_device *dev, port->vgrp = grp; - cb1 = kzalloc(PAGE_SIZE, GFP_KERNEL); + cb1 = (void *)get_zeroed_page(GFP_KERNEL); if (!cb1) { ehea_error("no mem for cb1"); goto out; @@ -2228,7 +2228,7 @@ static void ehea_vlan_rx_register(struct net_device *dev, if (hret != H_SUCCESS) ehea_error("modify_ehea_port failed"); - kfree(cb1); + free_page((unsigned long)cb1); out: return; } @@ -2241,7 +2241,7 @@ static void ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) int index; u64 hret; - cb1 = kzalloc(PAGE_SIZE, GFP_KERNEL); + cb1 = (void *)get_zeroed_page(GFP_KERNEL); if (!cb1) { ehea_error("no mem for cb1"); goto out; @@ -2262,7 +2262,7 @@ static void ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) if (hret != H_SUCCESS) ehea_error("modify_ehea_port failed"); out: - kfree(cb1); + free_page((unsigned long)cb1); return; } @@ -2276,7 +2276,7 @@ static void ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) vlan_group_set_device(port->vgrp, vid, NULL); - cb1 = kzalloc(PAGE_SIZE, GFP_KERNEL); + cb1 = (void *)get_zeroed_page(GFP_KERNEL); if (!cb1) { ehea_error("no mem for cb1"); goto out; @@ -2297,7 +2297,7 @@ static void ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) if (hret != H_SUCCESS) ehea_error("modify_ehea_port failed"); out: - kfree(cb1); + free_page((unsigned long)cb1); return; } @@ -2309,7 +2309,7 @@ int ehea_activate_qp(struct ehea_adapter *adapter, struct ehea_qp *qp) u64 dummy64 = 0; struct hcp_modify_qp_cb0 *cb0; - cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL); + cb0 = (void *)get_zeroed_page(GFP_KERNEL); if (!cb0) { ret = -ENOMEM; goto out; @@ -2372,7 +2372,7 @@ int ehea_activate_qp(struct ehea_adapter *adapter, struct ehea_qp *qp) ret = 0; out: - kfree(cb0); + free_page((unsigned long)cb0); return ret; } @@ -2664,7 +2664,7 @@ int ehea_stop_qps(struct net_device *dev) u64 dummy64 = 0; u16 dummy16 = 0; - cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL); + cb0 = (void *)get_zeroed_page(GFP_KERNEL); if (!cb0) { ret = -ENOMEM; goto out; @@ -2716,7 +2716,7 @@ int ehea_stop_qps(struct net_device *dev) ret = 0; out: - kfree(cb0); + free_page((unsigned long)cb0); return ret; } @@ -2766,7 +2766,7 @@ int ehea_restart_qps(struct net_device *dev) u64 dummy64 = 0; u16 dummy16 = 0; - cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL); + cb0 = (void *)get_zeroed_page(GFP_KERNEL); if (!cb0) { ret = -ENOMEM; goto out; @@ -2819,7 +2819,7 @@ int ehea_restart_qps(struct net_device *dev) ehea_refill_rq3(pr, 0); } out: - kfree(cb0); + free_page((unsigned long)cb0); return ret; } @@ -2950,7 +2950,7 @@ int ehea_sense_adapter_attr(struct ehea_adapter *adapter) u64 hret; int ret; - cb = kzalloc(PAGE_SIZE, GFP_KERNEL); + cb = (void *)get_zeroed_page(GFP_KERNEL); if (!cb) { ret = -ENOMEM; goto out; @@ -2967,7 +2967,7 @@ int ehea_sense_adapter_attr(struct ehea_adapter *adapter) ret = 0; out_herr: - kfree(cb); + free_page((unsigned long)cb); out: return ret; } @@ -2981,7 +2981,7 @@ int ehea_get_jumboframe_status(struct ehea_port *port, int *jumbo) *jumbo = 0; /* (Try to) enable *jumbo frames */ - cb4 = kzalloc(PAGE_SIZE, GFP_KERNEL); + cb4 = (void *)get_zeroed_page(GFP_KERNEL); if (!cb4) { ehea_error("no mem for cb4"); ret = -ENOMEM; @@ -3009,7 +3009,7 @@ int ehea_get_jumboframe_status(struct ehea_port *port, int *jumbo) } else ret = -EINVAL; - kfree(cb4); + free_page((unsigned long)cb4); } out: return ret; diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c index 49d766ebbcf..3747457f5e6 100644 --- a/drivers/net/ehea/ehea_qmr.c +++ b/drivers/net/ehea/ehea_qmr.c @@ -1005,7 +1005,7 @@ void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle) unsigned long ret; u64 *rblock; - rblock = kzalloc(PAGE_SIZE, GFP_KERNEL); + rblock = (void *)get_zeroed_page(GFP_KERNEL); if (!rblock) { ehea_error("Cannot allocate rblock memory."); return; @@ -1022,5 +1022,5 @@ void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle) else ehea_error("Error data could not be fetched: %llX", res_handle); - kfree(rblock); + free_page((unsigned long)rblock); } -- GitLab From e2878806227d223467f84f900ef4c6733ee166df Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Wed, 21 Jan 2009 14:45:57 -0800 Subject: [PATCH 0363/4982] ehea: Improve driver behaviour in low mem conditions Reworked receive queue fill policies to make the driver more tolerant in low memory conditions. Signed-off-by: Thomas Klein Signed-off-by: David S. Miller --- drivers/net/ehea/ehea_main.c | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index dfcdd7f21c7..19fccca74ce 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -370,8 +370,6 @@ static void ehea_refill_rq1(struct ehea_port_res *pr, int index, int nr_of_wqes) EHEA_L_PKT_SIZE); if (!skb_arr_rq1[index]) { pr->rq1_skba.os_skbs = fill_wqes - i; - ehea_error("%s: no mem for skb/%d wqes filled", - dev->name, i); break; } } @@ -387,26 +385,19 @@ static void ehea_refill_rq1(struct ehea_port_res *pr, int index, int nr_of_wqes) ehea_update_rq1a(pr->qp, adder); } -static int ehea_init_fill_rq1(struct ehea_port_res *pr, int nr_rq1a) +static void ehea_init_fill_rq1(struct ehea_port_res *pr, int nr_rq1a) { - int ret = 0; struct sk_buff **skb_arr_rq1 = pr->rq1_skba.arr; struct net_device *dev = pr->port->netdev; int i; for (i = 0; i < pr->rq1_skba.len; i++) { skb_arr_rq1[i] = netdev_alloc_skb(dev, EHEA_L_PKT_SIZE); - if (!skb_arr_rq1[i]) { - ehea_error("%s: no mem for skb/%d wqes filled", - dev->name, i); - ret = -ENOMEM; - goto out; - } + if (!skb_arr_rq1[i]) + break; } /* Ring doorbell */ ehea_update_rq1a(pr->qp, nr_rq1a); -out: - return ret; } static int ehea_refill_rq_def(struct ehea_port_res *pr, @@ -435,10 +426,12 @@ static int ehea_refill_rq_def(struct ehea_port_res *pr, u64 tmp_addr; struct sk_buff *skb = netdev_alloc_skb(dev, packet_size); if (!skb) { - ehea_error("%s: no mem for skb/%d wqes filled", - pr->port->netdev->name, i); q_skba->os_skbs = fill_wqes - i; - ret = -ENOMEM; + if (q_skba->os_skbs == q_skba->len - 2) { + ehea_info("%s: rq%i ran dry - no mem for skb", + pr->port->netdev->name, rq_nr); + ret = -ENOMEM; + } break; } skb_reserve(skb, NET_IP_ALIGN); @@ -1201,11 +1194,11 @@ static int ehea_fill_port_res(struct ehea_port_res *pr) int ret; struct ehea_qp_init_attr *init_attr = &pr->qp->init_attr; - ret = ehea_init_fill_rq1(pr, init_attr->act_nr_rwqes_rq1 - - init_attr->act_nr_rwqes_rq2 - - init_attr->act_nr_rwqes_rq3 - 1); + ehea_init_fill_rq1(pr, init_attr->act_nr_rwqes_rq1 + - init_attr->act_nr_rwqes_rq2 + - init_attr->act_nr_rwqes_rq3 - 1); - ret |= ehea_refill_rq2(pr, init_attr->act_nr_rwqes_rq2 - 1); + ret = ehea_refill_rq2(pr, init_attr->act_nr_rwqes_rq2 - 1); ret |= ehea_refill_rq3(pr, init_attr->act_nr_rwqes_rq3 - 1); -- GitLab From 6aba915881918a429d656e874f7fec2efd37ad96 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Wed, 21 Jan 2009 15:54:15 -0800 Subject: [PATCH 0364/4982] net: pppoe - code cleanup and helpers - Introduce PPPOE_HASH_MASK. - Remove redundant declaration of pppoe_chan_ops. - Introduce stage_session helper. - Tabs, space, long-line-split cleanup. Signed-off-by: Cyrill Gorcunov Signed-off-by: David S. Miller --- drivers/net/pppoe.c | 167 +++++++++++++++++++++++--------------------- 1 file changed, 86 insertions(+), 81 deletions(-) diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 5efc3d172c8..c2ceea4f46b 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -84,32 +84,43 @@ #include #define PPPOE_HASH_BITS 4 -#define PPPOE_HASH_SIZE (1<sid == b->sid && - (memcmp(a->remote, b->remote, ETH_ALEN) == 0)); + return a->sid == b->sid && + (memcmp(a->remote, b->remote, ETH_ALEN) == 0); } static inline int cmp_addr(struct pppoe_addr *a, __be16 sid, char *addr) { - return (a->sid == sid && - (memcmp(a->remote,addr,ETH_ALEN) == 0)); + return a->sid == sid && + (memcmp(a->remote, addr, ETH_ALEN) == 0); } -#if 8%PPPOE_HASH_BITS +#if 8 % PPPOE_HASH_BITS #error 8 must be a multiple of PPPOE_HASH_BITS #endif @@ -118,17 +129,14 @@ static int hash_item(__be16 sid, unsigned char *addr) unsigned char hash = 0; unsigned int i; - for (i = 0 ; i < ETH_ALEN ; i++) { + for (i = 0; i < ETH_ALEN; i++) hash ^= addr[i]; - } - for (i = 0 ; i < sizeof(sid_t)*8 ; i += 8 ){ - hash ^= (__force __u32)sid>>i; - } - for (i = 8 ; (i>>=1) >= PPPOE_HASH_BITS ; ) { - hash ^= hash>>i; - } + for (i = 0; i < sizeof(sid_t) * 8; i += 8) + hash ^= (__force __u32)sid >> i; + for (i = 8; (i >>= 1) >= PPPOE_HASH_BITS;) + hash ^= hash >> i; - return hash & ( PPPOE_HASH_SIZE - 1 ); + return hash & PPPOE_HASH_MASK; } /* zeroed because its in .bss */ @@ -146,10 +154,15 @@ static struct pppox_sock *__get_item(__be16 sid, unsigned char *addr, int ifinde ret = item_hash_table[hash]; - while (ret && !(cmp_addr(&ret->pppoe_pa, sid, addr) && ret->pppoe_ifindex == ifindex)) + while (ret) { + if (cmp_addr(&ret->pppoe_pa, sid, addr) && + ret->pppoe_ifindex == ifindex) + return ret; + ret = ret->next; + } - return ret; + return NULL; } static int __set_item(struct pppox_sock *po) @@ -159,7 +172,8 @@ static int __set_item(struct pppox_sock *po) ret = item_hash_table[hash]; while (ret) { - if (cmp_2_addr(&ret->pppoe_pa, &po->pppoe_pa) && ret->pppoe_ifindex == po->pppoe_ifindex) + if (cmp_2_addr(&ret->pppoe_pa, &po->pppoe_pa) && + ret->pppoe_ifindex == po->pppoe_ifindex) return -EALREADY; ret = ret->next; @@ -180,7 +194,8 @@ static struct pppox_sock *__delete_item(__be16 sid, char *addr, int ifindex) src = &item_hash_table[hash]; while (ret) { - if (cmp_addr(&ret->pppoe_pa, sid, addr) && ret->pppoe_ifindex == ifindex) { + if (cmp_addr(&ret->pppoe_pa, sid, addr) && + ret->pppoe_ifindex == ifindex) { *src = ret->next; break; } @@ -217,7 +232,7 @@ static inline struct pppox_sock *get_item_by_addr(struct sockaddr_pppox *sp) int ifindex; dev = dev_get_by_name(&init_net, sp->sa_addr.pppoe.dev); - if(!dev) + if (!dev) return NULL; ifindex = dev->ifindex; dev_put(dev); @@ -329,7 +344,6 @@ static struct notifier_block pppoe_notifier = { .notifier_call = pppoe_device_event, }; - /************************************************************************ * * Do the real work of receiving a PPPoE Session frame. @@ -383,7 +397,8 @@ static int pppoe_rcv(struct sk_buff *skb, struct pppox_sock *po; int len; - if (!(skb = skb_share_check(skb, GFP_ATOMIC))) + skb = skb_share_check(skb, GFP_ATOMIC); + if (!skb) goto out; if (dev_net(dev) != &init_net) @@ -432,7 +447,8 @@ static int pppoe_disc_rcv(struct sk_buff *skb, if (dev_net(dev) != &init_net) goto abort; - if (!(skb = skb_share_check(skb, GFP_ATOMIC))) + skb = skb_share_check(skb, GFP_ATOMIC); + if (!skb) goto out; if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr))) @@ -493,12 +509,11 @@ static struct proto pppoe_sk_proto = { **********************************************************************/ static int pppoe_create(struct net *net, struct socket *sock) { - int error = -ENOMEM; struct sock *sk; sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppoe_sk_proto); if (!sk) - goto out; + return -ENOMEM; sock_init_data(sock, sk); @@ -511,8 +526,7 @@ static int pppoe_create(struct net *net, struct socket *sock) sk->sk_family = PF_PPPOX; sk->sk_protocol = PX_PROTO_OE; - error = 0; -out: return error; + return 0; } static int pppoe_release(struct socket *sock) @@ -524,7 +538,7 @@ static int pppoe_release(struct socket *sock) return 0; lock_sock(sk); - if (sock_flag(sk, SOCK_DEAD)){ + if (sock_flag(sk, SOCK_DEAD)) { release_sock(sk); return -EBADF; } @@ -542,7 +556,7 @@ static int pppoe_release(struct socket *sock) write_lock_bh(&pppoe_hash_lock); po = pppox_sk(sk); - if (po->pppoe_pa.sid) { + if (stage_session(po->pppoe_pa.sid)) { __delete_item(po->pppoe_pa.sid, po->pppoe_pa.remote, po->pppoe_ifindex); } @@ -564,7 +578,6 @@ static int pppoe_release(struct socket *sock) return 0; } - static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, int sockaddr_len, int flags) { @@ -582,32 +595,31 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, /* Check for already bound sockets */ error = -EBUSY; - if ((sk->sk_state & PPPOX_CONNECTED) && sp->sa_addr.pppoe.sid) + if ((sk->sk_state & PPPOX_CONNECTED) && + stage_session(sp->sa_addr.pppoe.sid)) goto end; /* Check for already disconnected sockets, on attempts to disconnect */ error = -EALREADY; - if ((sk->sk_state & PPPOX_DEAD) && !sp->sa_addr.pppoe.sid ) + if ((sk->sk_state & PPPOX_DEAD) && + !stage_session(sp->sa_addr.pppoe.sid)) goto end; error = 0; - if (po->pppoe_pa.sid) { - pppox_unbind_sock(sk); - /* Delete the old binding */ - delete_item(po->pppoe_pa.sid,po->pppoe_pa.remote,po->pppoe_ifindex); - - if(po->pppoe_dev) + /* Delete the old binding */ + if (stage_session(po->pppoe_pa.sid)) { + pppox_unbind_sock(sk); + delete_item(po->pppoe_pa.sid, po->pppoe_pa.remote, po->pppoe_ifindex); + if (po->pppoe_dev) dev_put(po->pppoe_dev); - memset(sk_pppox(po) + 1, 0, sizeof(struct pppox_sock) - sizeof(struct sock)); - sk->sk_state = PPPOX_NONE; } - /* Don't re-bind if sid==0 */ - if (sp->sa_addr.pppoe.sid != 0) { + /* Re-bind in session stage only */ + if (stage_session(sp->sa_addr.pppoe.sid)) { dev = dev_get_by_name(&init_net, sp->sa_addr.pppoe.dev); error = -ENODEV; @@ -618,7 +630,7 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, po->pppoe_ifindex = dev->ifindex; write_lock_bh(&pppoe_hash_lock); - if (!(dev->flags & IFF_UP)){ + if (!(dev->flags & IFF_UP)) { write_unlock_bh(&pppoe_hash_lock); goto err_put; } @@ -648,7 +660,7 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, po->num = sp->sa_addr.pppoe.sid; - end: +end: release_sock(sk); return error; err_put: @@ -659,7 +671,6 @@ err_put: goto end; } - static int pppoe_getname(struct socket *sock, struct sockaddr *uaddr, int *usockaddr_len, int peer) { @@ -678,7 +689,6 @@ static int pppoe_getname(struct socket *sock, struct sockaddr *uaddr, return 0; } - static int pppoe_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { @@ -709,7 +719,7 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, break; err = -EFAULT; - if (get_user(val,(int __user *) arg)) + if (get_user(val, (int __user *)arg)) break; if (val < (po->pppoe_dev->mtu @@ -722,7 +732,7 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, case PPPIOCSFLAGS: err = -EFAULT; - if (get_user(val, (int __user *) arg)) + if (get_user(val, (int __user *)arg)) break; err = 0; break; @@ -749,7 +759,7 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, err = -EINVAL; if (po->pppoe_relay.sa_family != AF_PPPOX || - po->pppoe_relay.sa_protocol!= PX_PROTO_OE) + po->pppoe_relay.sa_protocol != PX_PROTO_OE) break; /* Check that the socket referenced by the address @@ -781,7 +791,6 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, return err; } - static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len) { @@ -808,7 +817,7 @@ static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock, dev = po->pppoe_dev; error = -EMSGSIZE; - if (total_len > (dev->mtu + dev->hard_header_len)) + if (total_len > (dev->mtu + dev->hard_header_len)) goto end; @@ -853,7 +862,6 @@ end: return error; } - /************************************************************************ * * xmit function for internal use. @@ -903,7 +911,6 @@ abort: return 1; } - /************************************************************************ * * xmit function called by generic PPP driver @@ -916,7 +923,6 @@ static int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb) return __pppoe_xmit(sk, skb); } - static struct ppp_channel_ops pppoe_chan_ops = { .start_xmit = pppoe_xmit, }; @@ -976,9 +982,9 @@ out: static __inline__ struct pppox_sock *pppoe_get_idx(loff_t pos) { struct pppox_sock *po; - int i = 0; + int i; - for (; i < PPPOE_HASH_SIZE; i++) { + for (i = 0; i < PPPOE_HASH_SIZE; i++) { po = item_hash_table[i]; while (po) { if (!pos--) @@ -1064,32 +1070,31 @@ static inline int pppoe_proc_init(void) { return 0; } #endif /* CONFIG_PROC_FS */ static const struct proto_ops pppoe_ops = { - .family = AF_PPPOX, - .owner = THIS_MODULE, - .release = pppoe_release, - .bind = sock_no_bind, - .connect = pppoe_connect, - .socketpair = sock_no_socketpair, - .accept = sock_no_accept, - .getname = pppoe_getname, - .poll = datagram_poll, - .listen = sock_no_listen, - .shutdown = sock_no_shutdown, - .setsockopt = sock_no_setsockopt, - .getsockopt = sock_no_getsockopt, - .sendmsg = pppoe_sendmsg, - .recvmsg = pppoe_recvmsg, - .mmap = sock_no_mmap, - .ioctl = pppox_ioctl, + .family = AF_PPPOX, + .owner = THIS_MODULE, + .release = pppoe_release, + .bind = sock_no_bind, + .connect = pppoe_connect, + .socketpair = sock_no_socketpair, + .accept = sock_no_accept, + .getname = pppoe_getname, + .poll = datagram_poll, + .listen = sock_no_listen, + .shutdown = sock_no_shutdown, + .setsockopt = sock_no_setsockopt, + .getsockopt = sock_no_getsockopt, + .sendmsg = pppoe_sendmsg, + .recvmsg = pppoe_recvmsg, + .mmap = sock_no_mmap, + .ioctl = pppox_ioctl, }; static struct pppox_proto pppoe_proto = { - .create = pppoe_create, - .ioctl = pppoe_ioctl, - .owner = THIS_MODULE, + .create = pppoe_create, + .ioctl = pppoe_ioctl, + .owner = THIS_MODULE, }; - static int __init pppoe_init(void) { int err = proto_register(&pppoe_sk_proto, 0); @@ -1097,7 +1102,7 @@ static int __init pppoe_init(void) if (err) goto out; - err = register_pppox_proto(PX_PROTO_OE, &pppoe_proto); + err = register_pppox_proto(PX_PROTO_OE, &pppoe_proto); if (err) goto out_unregister_pppoe_proto; -- GitLab From a6bcf1c1d38e0672db35e0d9f2504ac04ddf3ed5 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Wed, 21 Jan 2009 15:54:54 -0800 Subject: [PATCH 0365/4982] net: pppoe - introduce net-namespace functionality - each net-namespace for pppoe module is having own hash table and appropriate locks wich are allocated at time of namespace intialization. It requires about 140 bytes of memory for every new namespace but such approach allow us to escape from hash chains growing and additional lock contends (especially in SMP environment). - pppox code allows to create per-namespace sockets for PX_PROTO_OE protocol only (since at this moment support for pppol2tp net-namespace is not implemented yet). Signed-off-by: Cyrill Gorcunov Signed-off-by: David S. Miller --- drivers/net/pppoe.c | 377 ++++++++++++++++++++++++++++---------------- drivers/net/pppox.c | 7 +- 2 files changed, 248 insertions(+), 136 deletions(-) diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index c2ceea4f46b..fb3056334aa 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -78,7 +78,9 @@ #include #include +#include #include +#include #include #include @@ -93,7 +95,24 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb); static const struct proto_ops pppoe_ops; static struct ppp_channel_ops pppoe_chan_ops; -static DEFINE_RWLOCK(pppoe_hash_lock); + +/* per-net private data for this module */ +static unsigned int pppoe_net_id; +struct pppoe_net { + /* + * we could use _single_ hash table for all + * nets by injecting net id into the hash but + * it would increase hash chains and add + * a few additional math comparations messy + * as well, moreover in case of SMP less locking + * controversy here + */ + struct pppox_sock *hash_table[PPPOE_HASH_SIZE]; + rwlock_t hash_lock; +}; + +/* to eliminate a race btw pppoe_flush_dev and pppoe_release */ +static DEFINE_SPINLOCK(flush_lock); /* * PPPoE could be in the following stages: @@ -108,16 +127,21 @@ static inline bool stage_session(__be16 sid) return sid != 0; } +static inline struct pppoe_net *pppoe_pernet(struct net *net) +{ + BUG_ON(!net); + + return net_generic(net, pppoe_net_id); +} + static inline int cmp_2_addr(struct pppoe_addr *a, struct pppoe_addr *b) { - return a->sid == b->sid && - (memcmp(a->remote, b->remote, ETH_ALEN) == 0); + return a->sid == b->sid && !memcmp(a->remote, b->remote, ETH_ALEN); } static inline int cmp_addr(struct pppoe_addr *a, __be16 sid, char *addr) { - return a->sid == sid && - (memcmp(a->remote, addr, ETH_ALEN) == 0); + return a->sid == sid && !memcmp(a->remote, addr, ETH_ALEN); } #if 8 % PPPOE_HASH_BITS @@ -139,21 +163,18 @@ static int hash_item(__be16 sid, unsigned char *addr) return hash & PPPOE_HASH_MASK; } -/* zeroed because its in .bss */ -static struct pppox_sock *item_hash_table[PPPOE_HASH_SIZE]; - /********************************************************************** * * Set/get/delete/rehash items (internal versions) * **********************************************************************/ -static struct pppox_sock *__get_item(__be16 sid, unsigned char *addr, int ifindex) +static struct pppox_sock *__get_item(struct pppoe_net *pn, __be16 sid, + unsigned char *addr, int ifindex) { int hash = hash_item(sid, addr); struct pppox_sock *ret; - ret = item_hash_table[hash]; - + ret = pn->hash_table[hash]; while (ret) { if (cmp_addr(&ret->pppoe_pa, sid, addr) && ret->pppoe_ifindex == ifindex) @@ -165,12 +186,12 @@ static struct pppox_sock *__get_item(__be16 sid, unsigned char *addr, int ifinde return NULL; } -static int __set_item(struct pppox_sock *po) +static int __set_item(struct pppoe_net *pn, struct pppox_sock *po) { int hash = hash_item(po->pppoe_pa.sid, po->pppoe_pa.remote); struct pppox_sock *ret; - ret = item_hash_table[hash]; + ret = pn->hash_table[hash]; while (ret) { if (cmp_2_addr(&ret->pppoe_pa, &po->pppoe_pa) && ret->pppoe_ifindex == po->pppoe_ifindex) @@ -179,19 +200,20 @@ static int __set_item(struct pppox_sock *po) ret = ret->next; } - po->next = item_hash_table[hash]; - item_hash_table[hash] = po; + po->next = pn->hash_table[hash]; + pn->hash_table[hash] = po; return 0; } -static struct pppox_sock *__delete_item(__be16 sid, char *addr, int ifindex) +static struct pppox_sock *__delete_item(struct pppoe_net *pn, __be16 sid, + char *addr, int ifindex) { int hash = hash_item(sid, addr); struct pppox_sock *ret, **src; - ret = item_hash_table[hash]; - src = &item_hash_table[hash]; + ret = pn->hash_table[hash]; + src = &pn->hash_table[hash]; while (ret) { if (cmp_addr(&ret->pppoe_pa, sid, addr) && @@ -212,46 +234,54 @@ static struct pppox_sock *__delete_item(__be16 sid, char *addr, int ifindex) * Set/get/delete/rehash items * **********************************************************************/ -static inline struct pppox_sock *get_item(__be16 sid, - unsigned char *addr, int ifindex) +static inline struct pppox_sock *get_item(struct pppoe_net *pn, __be16 sid, + unsigned char *addr, int ifindex) { struct pppox_sock *po; - read_lock_bh(&pppoe_hash_lock); - po = __get_item(sid, addr, ifindex); + read_lock_bh(&pn->hash_lock); + po = __get_item(pn, sid, addr, ifindex); if (po) sock_hold(sk_pppox(po)); - read_unlock_bh(&pppoe_hash_lock); + read_unlock_bh(&pn->hash_lock); return po; } -static inline struct pppox_sock *get_item_by_addr(struct sockaddr_pppox *sp) +static inline struct pppox_sock *get_item_by_addr(struct net *net, + struct sockaddr_pppox *sp) { struct net_device *dev; + struct pppoe_net *pn; + struct pppox_sock *pppox_sock; + int ifindex; - dev = dev_get_by_name(&init_net, sp->sa_addr.pppoe.dev); + dev = dev_get_by_name(net, sp->sa_addr.pppoe.dev); if (!dev) return NULL; + ifindex = dev->ifindex; + pn = net_generic(net, pppoe_net_id); + pppox_sock = get_item(pn, sp->sa_addr.pppoe.sid, + sp->sa_addr.pppoe.remote, ifindex); dev_put(dev); - return get_item(sp->sa_addr.pppoe.sid, sp->sa_addr.pppoe.remote, ifindex); + + return pppox_sock; } -static inline struct pppox_sock *delete_item(__be16 sid, char *addr, int ifindex) +static inline struct pppox_sock *delete_item(struct pppoe_net *pn, __be16 sid, + char *addr, int ifindex) { struct pppox_sock *ret; - write_lock_bh(&pppoe_hash_lock); - ret = __delete_item(sid, addr, ifindex); - write_unlock_bh(&pppoe_hash_lock); + write_lock_bh(&pn->hash_lock); + ret = __delete_item(pn, sid, addr, ifindex); + write_unlock_bh(&pn->hash_lock); return ret; } - - /*************************************************************************** * * Handler for device events. @@ -261,25 +291,33 @@ static inline struct pppox_sock *delete_item(__be16 sid, char *addr, int ifindex static void pppoe_flush_dev(struct net_device *dev) { - int hash; + struct pppoe_net *pn; + int i; + BUG_ON(dev == NULL); - write_lock_bh(&pppoe_hash_lock); - for (hash = 0; hash < PPPOE_HASH_SIZE; hash++) { - struct pppox_sock *po = item_hash_table[hash]; + pn = pppoe_pernet(dev_net(dev)); + if (!pn) /* already freed */ + return; + + write_lock_bh(&pn->hash_lock); + for (i = 0; i < PPPOE_HASH_SIZE; i++) { + struct pppox_sock *po = pn->hash_table[i]; while (po != NULL) { - struct sock *sk = sk_pppox(po); + struct sock *sk; if (po->pppoe_dev != dev) { po = po->next; continue; } + sk = sk_pppox(po); + spin_lock(&flush_lock); po->pppoe_dev = NULL; + spin_unlock(&flush_lock); dev_put(dev); - /* We always grab the socket lock, followed by the - * pppoe_hash_lock, in that order. Since we should + * hash_lock, in that order. Since we should * hold the sock lock while doing any unbinding, * we need to release the lock we're holding. * Hold a reference to the sock so it doesn't disappear @@ -288,7 +326,7 @@ static void pppoe_flush_dev(struct net_device *dev) sock_hold(sk); - write_unlock_bh(&pppoe_hash_lock); + write_unlock_bh(&pn->hash_lock); lock_sock(sk); if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) { @@ -304,20 +342,17 @@ static void pppoe_flush_dev(struct net_device *dev) * While the lock was dropped the chain contents may * have changed. */ - write_lock_bh(&pppoe_hash_lock); - po = item_hash_table[hash]; + write_lock_bh(&pn->hash_lock); + po = pn->hash_table[i]; } } - write_unlock_bh(&pppoe_hash_lock); + write_unlock_bh(&pn->hash_lock); } static int pppoe_device_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = (struct net_device *) ptr; - - if (dev_net(dev) != &init_net) - return NOTIFY_DONE; + struct net_device *dev = (struct net_device *)ptr; /* Only look at sockets that are using this specific device. */ switch (event) { @@ -339,7 +374,6 @@ static int pppoe_device_event(struct notifier_block *this, return NOTIFY_DONE; } - static struct notifier_block pppoe_notifier = { .notifier_call = pppoe_device_event, }; @@ -357,8 +391,8 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb) if (sk->sk_state & PPPOX_BOUND) { ppp_input(&po->chan, skb); } else if (sk->sk_state & PPPOX_RELAY) { - relay_po = get_item_by_addr(&po->pppoe_relay); - + relay_po = get_item_by_addr(dev_net(po->pppoe_dev), + &po->pppoe_relay); if (relay_po == NULL) goto abort_kfree; @@ -387,23 +421,18 @@ abort_kfree: * Receive wrapper called in BH context. * ***********************************************************************/ -static int pppoe_rcv(struct sk_buff *skb, - struct net_device *dev, - struct packet_type *pt, - struct net_device *orig_dev) - +static int pppoe_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt, struct net_device *orig_dev) { struct pppoe_hdr *ph; struct pppox_sock *po; + struct pppoe_net *pn; int len; skb = skb_share_check(skb, GFP_ATOMIC); if (!skb) goto out; - if (dev_net(dev) != &init_net) - goto drop; - if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr))) goto drop; @@ -417,7 +446,8 @@ static int pppoe_rcv(struct sk_buff *skb, if (pskb_trim_rcsum(skb, len)) goto drop; - po = get_item(ph->sid, eth_hdr(skb)->h_source, dev->ifindex); + pn = pppoe_pernet(dev_net(dev)); + po = get_item(pn, ph->sid, eth_hdr(skb)->h_source, dev->ifindex); if (!po) goto drop; @@ -435,17 +465,13 @@ out: * This is solely for detection of PADT frames * ***********************************************************************/ -static int pppoe_disc_rcv(struct sk_buff *skb, - struct net_device *dev, - struct packet_type *pt, - struct net_device *orig_dev) +static int pppoe_disc_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt, struct net_device *orig_dev) { struct pppoe_hdr *ph; struct pppox_sock *po; - - if (dev_net(dev) != &init_net) - goto abort; + struct pppoe_net *pn; skb = skb_share_check(skb, GFP_ATOMIC); if (!skb) @@ -458,7 +484,8 @@ static int pppoe_disc_rcv(struct sk_buff *skb, if (ph->code != PADT_CODE) goto abort; - po = get_item(ph->sid, eth_hdr(skb)->h_source, dev->ifindex); + pn = pppoe_pernet(dev_net(dev)); + po = get_item(pn, ph->sid, eth_hdr(skb)->h_source, dev->ifindex); if (po) { struct sock *sk = sk_pppox(po); @@ -517,14 +544,14 @@ static int pppoe_create(struct net *net, struct socket *sock) sock_init_data(sock, sk); - sock->state = SS_UNCONNECTED; - sock->ops = &pppoe_ops; + sock->state = SS_UNCONNECTED; + sock->ops = &pppoe_ops; - sk->sk_backlog_rcv = pppoe_rcv_core; - sk->sk_state = PPPOX_NONE; - sk->sk_type = SOCK_STREAM; - sk->sk_family = PF_PPPOX; - sk->sk_protocol = PX_PROTO_OE; + sk->sk_backlog_rcv = pppoe_rcv_core; + sk->sk_state = PPPOX_NONE; + sk->sk_type = SOCK_STREAM; + sk->sk_family = PF_PPPOX; + sk->sk_protocol = PX_PROTO_OE; return 0; } @@ -533,6 +560,7 @@ static int pppoe_release(struct socket *sock) { struct sock *sk = sock->sk; struct pppox_sock *po; + struct pppoe_net *pn; if (!sk) return 0; @@ -548,26 +576,39 @@ static int pppoe_release(struct socket *sock) /* Signal the death of the socket. */ sk->sk_state = PPPOX_DEAD; + /* + * pppoe_flush_dev could lead to a race with + * this routine so we use flush_lock to eliminate + * such a case (we only need per-net specific data) + */ + spin_lock(&flush_lock); + po = pppox_sk(sk); + if (!po->pppoe_dev) { + spin_unlock(&flush_lock); + goto out; + } + pn = pppoe_pernet(dev_net(po->pppoe_dev)); + spin_unlock(&flush_lock); - /* Write lock on hash lock protects the entire "po" struct from - * concurrent updates via pppoe_flush_dev. The "po" struct should - * be considered part of the hash table contents, thus protected - * by the hash table lock */ - write_lock_bh(&pppoe_hash_lock); + /* + * protect "po" from concurrent updates + * on pppoe_flush_dev + */ + write_lock_bh(&pn->hash_lock); po = pppox_sk(sk); - if (stage_session(po->pppoe_pa.sid)) { - __delete_item(po->pppoe_pa.sid, - po->pppoe_pa.remote, po->pppoe_ifindex); - } + if (stage_session(po->pppoe_pa.sid)) + __delete_item(pn, po->pppoe_pa.sid, po->pppoe_pa.remote, + po->pppoe_ifindex); if (po->pppoe_dev) { dev_put(po->pppoe_dev); po->pppoe_dev = NULL; } - write_unlock_bh(&pppoe_hash_lock); + write_unlock_bh(&pn->hash_lock); +out: sock_orphan(sk); sock->sk = NULL; @@ -582,9 +623,10 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, int sockaddr_len, int flags) { struct sock *sk = sock->sk; - struct net_device *dev; - struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr; + struct sockaddr_pppox *sp = (struct sockaddr_pppox *)uservaddr; struct pppox_sock *po = pppox_sk(sk); + struct net_device *dev; + struct pppoe_net *pn; int error; lock_sock(sk); @@ -610,9 +652,12 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, /* Delete the old binding */ if (stage_session(po->pppoe_pa.sid)) { pppox_unbind_sock(sk); - delete_item(po->pppoe_pa.sid, po->pppoe_pa.remote, po->pppoe_ifindex); - if (po->pppoe_dev) + if (po->pppoe_dev) { + pn = pppoe_pernet(dev_net(po->pppoe_dev)); + delete_item(pn, po->pppoe_pa.sid, + po->pppoe_pa.remote, po->pppoe_ifindex); dev_put(po->pppoe_dev); + } memset(sk_pppox(po) + 1, 0, sizeof(struct pppox_sock) - sizeof(struct sock)); sk->sk_state = PPPOX_NONE; @@ -620,18 +665,17 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, /* Re-bind in session stage only */ if (stage_session(sp->sa_addr.pppoe.sid)) { - dev = dev_get_by_name(&init_net, sp->sa_addr.pppoe.dev); - error = -ENODEV; + dev = dev_get_by_name(sock_net(sk), sp->sa_addr.pppoe.dev); if (!dev) goto end; po->pppoe_dev = dev; po->pppoe_ifindex = dev->ifindex; - - write_lock_bh(&pppoe_hash_lock); + pn = pppoe_pernet(dev_net(dev)); + write_lock_bh(&pn->hash_lock); if (!(dev->flags & IFF_UP)) { - write_unlock_bh(&pppoe_hash_lock); + write_unlock_bh(&pn->hash_lock); goto err_put; } @@ -639,8 +683,8 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, &sp->sa_addr.pppoe, sizeof(struct pppoe_addr)); - error = __set_item(po); - write_unlock_bh(&pppoe_hash_lock); + error = __set_item(pn, po); + write_unlock_bh(&pn->hash_lock); if (error < 0) goto err_put; @@ -700,7 +744,6 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, switch (cmd) { case PPPIOCGMRU: err = -ENXIO; - if (!(sk->sk_state & PPPOX_CONNECTED)) break; @@ -708,7 +751,7 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, if (put_user(po->pppoe_dev->mtu - sizeof(struct pppoe_hdr) - PPP_HDRLEN, - (int __user *) arg)) + (int __user *)arg)) break; err = 0; break; @@ -764,8 +807,7 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, /* Check that the socket referenced by the address actually exists. */ - relay_po = get_item_by_addr(&po->pppoe_relay); - + relay_po = get_item_by_addr(sock_net(sk), &po->pppoe_relay); if (!relay_po) break; @@ -837,11 +879,10 @@ static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock, skb->priority = sk->sk_priority; skb->protocol = __constant_htons(ETH_P_PPP_SES); - ph = (struct pppoe_hdr *) skb_put(skb, total_len + sizeof(struct pppoe_hdr)); - start = (char *) &ph->tag[0]; + ph = (struct pppoe_hdr *)skb_put(skb, total_len + sizeof(struct pppoe_hdr)); + start = (char *)&ph->tag[0]; error = memcpy_fromiovec(start, m->msg_iov, total_len); - if (error < 0) { kfree_skb(skb); goto end; @@ -919,7 +960,7 @@ abort: ***********************************************************************/ static int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb) { - struct sock *sk = (struct sock *) chan->private; + struct sock *sk = (struct sock *)chan->private; return __pppoe_xmit(sk, skb); } @@ -941,7 +982,6 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock, skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &error); - if (error < 0) goto end; @@ -964,6 +1004,7 @@ static int pppoe_seq_show(struct seq_file *seq, void *v) { struct pppox_sock *po; char *dev_name; + DECLARE_MAC_BUF(mac); if (v == SEQ_START_TOKEN) { seq_puts(seq, "Id Address Device\n"); @@ -974,44 +1015,47 @@ static int pppoe_seq_show(struct seq_file *seq, void *v) dev_name = po->pppoe_pa.dev; seq_printf(seq, "%08X %pM %8s\n", - po->pppoe_pa.sid, po->pppoe_pa.remote, dev_name); + po->pppoe_pa.sid, po->pppoe_pa.remote, dev_name); out: return 0; } -static __inline__ struct pppox_sock *pppoe_get_idx(loff_t pos) +static inline struct pppox_sock *pppoe_get_idx(struct pppoe_net *pn, loff_t pos) { struct pppox_sock *po; int i; for (i = 0; i < PPPOE_HASH_SIZE; i++) { - po = item_hash_table[i]; + po = pn->hash_table[i]; while (po) { if (!pos--) goto out; po = po->next; } } + out: return po; } static void *pppoe_seq_start(struct seq_file *seq, loff_t *pos) - __acquires(pppoe_hash_lock) + __acquires(pn->hash_lock) { + struct pppoe_net *pn = pppoe_pernet(seq->private); loff_t l = *pos; - read_lock_bh(&pppoe_hash_lock); - return l ? pppoe_get_idx(--l) : SEQ_START_TOKEN; + read_lock_bh(&pn->hash_lock); + return l ? pppoe_get_idx(pn, --l) : SEQ_START_TOKEN; } static void *pppoe_seq_next(struct seq_file *seq, void *v, loff_t *pos) { + struct pppoe_net *pn = pppoe_pernet(seq->private); struct pppox_sock *po; ++*pos; if (v == SEQ_START_TOKEN) { - po = pppoe_get_idx(0); + po = pppoe_get_idx(pn, 0); goto out; } po = v; @@ -1021,19 +1065,21 @@ static void *pppoe_seq_next(struct seq_file *seq, void *v, loff_t *pos) int hash = hash_item(po->pppoe_pa.sid, po->pppoe_pa.remote); while (++hash < PPPOE_HASH_SIZE) { - po = item_hash_table[hash]; + po = pn->hash_table[hash]; if (po) break; } } + out: return po; } static void pppoe_seq_stop(struct seq_file *seq, void *v) - __releases(pppoe_hash_lock) + __releases(pn->hash_lock) { - read_unlock_bh(&pppoe_hash_lock); + struct pppoe_net *pn = pppoe_pernet(seq->private); + read_unlock_bh(&pn->hash_lock); } static const struct seq_operations pppoe_seq_ops = { @@ -1045,7 +1091,30 @@ static const struct seq_operations pppoe_seq_ops = { static int pppoe_seq_open(struct inode *inode, struct file *file) { - return seq_open(file, &pppoe_seq_ops); + struct seq_file *m; + struct net *net; + int err; + + err = seq_open(file, &pppoe_seq_ops); + if (err) + return err; + + m = file->private_data; + net = maybe_get_net(PDE_NET(PDE(inode))); + BUG_ON(!net); + m->private = net; + + return err; +} + +static int pppoe_seq_release(struct inode *inode, struct file *file) +{ + struct seq_file *m; + + m = file->private_data; + put_net((struct net*)m->private); + + return seq_release(inode, file); } static const struct file_operations pppoe_seq_fops = { @@ -1053,20 +1122,9 @@ static const struct file_operations pppoe_seq_fops = { .open = pppoe_seq_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = pppoe_seq_release, }; -static int __init pppoe_proc_init(void) -{ - struct proc_dir_entry *p; - - p = proc_net_fops_create(&init_net, "pppoe", S_IRUGO, &pppoe_seq_fops); - if (!p) - return -ENOMEM; - return 0; -} -#else /* CONFIG_PROC_FS */ -static inline int pppoe_proc_init(void) { return 0; } #endif /* CONFIG_PROC_FS */ static const struct proto_ops pppoe_ops = { @@ -1095,10 +1153,61 @@ static struct pppox_proto pppoe_proto = { .owner = THIS_MODULE, }; +static __net_init int pppoe_init_net(struct net *net) +{ + struct pppoe_net *pn; + struct proc_dir_entry *pde; + int err; + + pn = kzalloc(sizeof(*pn), GFP_KERNEL); + if (!pn) + return -ENOMEM; + + rwlock_init(&pn->hash_lock); + + err = net_assign_generic(net, pppoe_net_id, pn); + if (err) + goto out; + + pde = proc_net_fops_create(net, "pppoe", S_IRUGO, &pppoe_seq_fops); +#ifdef CONFIG_PROC_FS + if (!pde) { + err = -ENOMEM; + goto out; + } +#endif + + return 0; + +out: + kfree(pn); + return err; +} + +static __net_exit void pppoe_exit_net(struct net *net) +{ + struct pppoe_net *pn; + + proc_net_remove(net, "pppoe"); + pn = net_generic(net, pppoe_net_id); + /* + * if someone has cached our net then + * further net_generic call will return NULL + */ + net_assign_generic(net, pppoe_net_id, NULL); + kfree(pn); +} + +static __net_initdata struct pernet_operations pppoe_net_ops = { + .init = pppoe_init_net, + .exit = pppoe_exit_net, +}; + static int __init pppoe_init(void) { - int err = proto_register(&pppoe_sk_proto, 0); + int err; + err = proto_register(&pppoe_sk_proto, 0); if (err) goto out; @@ -1106,20 +1215,22 @@ static int __init pppoe_init(void) if (err) goto out_unregister_pppoe_proto; - err = pppoe_proc_init(); + err = register_pernet_gen_device(&pppoe_net_id, &pppoe_net_ops); if (err) goto out_unregister_pppox_proto; dev_add_pack(&pppoes_ptype); dev_add_pack(&pppoed_ptype); register_netdevice_notifier(&pppoe_notifier); -out: - return err; + + return 0; + out_unregister_pppox_proto: unregister_pppox_proto(PX_PROTO_OE); out_unregister_pppoe_proto: proto_unregister(&pppoe_sk_proto); - goto out; +out: + return err; } static void __exit pppoe_exit(void) @@ -1128,7 +1239,7 @@ static void __exit pppoe_exit(void) dev_remove_pack(&pppoes_ptype); dev_remove_pack(&pppoed_ptype); unregister_netdevice_notifier(&pppoe_notifier); - remove_proc_entry("pppoe", init_net.proc_net); + unregister_pernet_gen_device(pppoe_net_id, &pppoe_net_ops); proto_unregister(&pppoe_sk_proto); } diff --git a/drivers/net/pppox.c b/drivers/net/pppox.c index 03aecc97fb4..ee9d3cf81be 100644 --- a/drivers/net/pppox.c +++ b/drivers/net/pppox.c @@ -108,12 +108,13 @@ static int pppox_create(struct net *net, struct socket *sock, int protocol) { int rc = -EPROTOTYPE; - if (net != &init_net) - return -EAFNOSUPPORT; - if (protocol < 0 || protocol > PX_MAX_PROTO) goto out; + /* we support net-namespaces for PPPoE only (yet) */ + if (protocol != PX_PROTO_OE && net != &init_net) + return -EAFNOSUPPORT; + rc = -EPROTONOSUPPORT; if (!pppox_protos[protocol]) request_module("pppox-proto-%d", protocol); -- GitLab From 4e9fb8016a351b5b9da7fea32bcfdbc9d836e421 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Wed, 21 Jan 2009 15:55:15 -0800 Subject: [PATCH 0366/4982] net: pppol2tp - introduce net-namespace functionality - Each tunnel and appropriate lock are inside own namespace now. - pppox code allows to create per-namespace sockets for both PX_PROTO_OE and PX_PROTO_OL2TP protocols. Actually since now pppox_create support net-namespaces new PPPo... protocols (if they ever will be) should support net-namespace too otherwise explicit check for &init_net would be needed. Signed-off-by: Cyrill Gorcunov Signed-off-by: James Chapman Signed-off-by: David S. Miller --- drivers/net/pppol2tp.c | 160 ++++++++++++++++++++++++++++++----------- drivers/net/pppox.c | 4 -- 2 files changed, 117 insertions(+), 47 deletions(-) diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index 635dd5fbe62..f3f9cb1f77c 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c @@ -90,7 +90,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -204,6 +206,7 @@ struct pppol2tp_tunnel struct sock *sock; /* Parent socket */ struct list_head list; /* Keep a list of all open * prepared sockets */ + struct net *pppol2tp_net; /* the net we belong to */ atomic_t ref_count; }; @@ -227,8 +230,20 @@ static atomic_t pppol2tp_tunnel_count; static atomic_t pppol2tp_session_count; static struct ppp_channel_ops pppol2tp_chan_ops = { pppol2tp_xmit , NULL }; static struct proto_ops pppol2tp_ops; -static LIST_HEAD(pppol2tp_tunnel_list); -static DEFINE_RWLOCK(pppol2tp_tunnel_list_lock); + +/* per-net private data for this module */ +static unsigned int pppol2tp_net_id; +struct pppol2tp_net { + struct list_head pppol2tp_tunnel_list; + rwlock_t pppol2tp_tunnel_list_lock; +}; + +static inline struct pppol2tp_net *pppol2tp_pernet(struct net *net) +{ + BUG_ON(!net); + + return net_generic(net, pppol2tp_net_id); +} /* Helpers to obtain tunnel/session contexts from sockets. */ @@ -321,18 +336,19 @@ pppol2tp_session_find(struct pppol2tp_tunnel *tunnel, u16 session_id) /* Lookup a tunnel by id */ -static struct pppol2tp_tunnel *pppol2tp_tunnel_find(u16 tunnel_id) +static struct pppol2tp_tunnel *pppol2tp_tunnel_find(struct net *net, u16 tunnel_id) { - struct pppol2tp_tunnel *tunnel = NULL; + struct pppol2tp_tunnel *tunnel; + struct pppol2tp_net *pn = pppol2tp_pernet(net); - read_lock_bh(&pppol2tp_tunnel_list_lock); - list_for_each_entry(tunnel, &pppol2tp_tunnel_list, list) { + read_lock_bh(&pn->pppol2tp_tunnel_list_lock); + list_for_each_entry(tunnel, &pn->pppol2tp_tunnel_list, list) { if (tunnel->stats.tunnel_id == tunnel_id) { - read_unlock_bh(&pppol2tp_tunnel_list_lock); + read_unlock_bh(&pn->pppol2tp_tunnel_list_lock); return tunnel; } } - read_unlock_bh(&pppol2tp_tunnel_list_lock); + read_unlock_bh(&pn->pppol2tp_tunnel_list_lock); return NULL; } @@ -1287,10 +1303,12 @@ again: */ static void pppol2tp_tunnel_free(struct pppol2tp_tunnel *tunnel) { + struct pppol2tp_net *pn = pppol2tp_pernet(tunnel->pppol2tp_net); + /* Remove from socket list */ - write_lock_bh(&pppol2tp_tunnel_list_lock); + write_lock_bh(&pn->pppol2tp_tunnel_list_lock); list_del_init(&tunnel->list); - write_unlock_bh(&pppol2tp_tunnel_list_lock); + write_unlock_bh(&pn->pppol2tp_tunnel_list_lock); atomic_dec(&pppol2tp_tunnel_count); kfree(tunnel); @@ -1444,13 +1462,14 @@ error: /* Internal function to prepare a tunnel (UDP) socket to have PPPoX * sockets attached to it. */ -static struct sock *pppol2tp_prepare_tunnel_socket(int fd, u16 tunnel_id, - int *error) +static struct sock *pppol2tp_prepare_tunnel_socket(struct net *net, + int fd, u16 tunnel_id, int *error) { int err; struct socket *sock = NULL; struct sock *sk; struct pppol2tp_tunnel *tunnel; + struct pppol2tp_net *pn; struct sock *ret = NULL; /* Get the tunnel UDP socket from the fd, which was opened by @@ -1524,11 +1543,15 @@ static struct sock *pppol2tp_prepare_tunnel_socket(int fd, u16 tunnel_id, /* Misc init */ rwlock_init(&tunnel->hlist_lock); + /* The net we belong to */ + tunnel->pppol2tp_net = net; + pn = pppol2tp_pernet(net); + /* Add tunnel to our list */ INIT_LIST_HEAD(&tunnel->list); - write_lock_bh(&pppol2tp_tunnel_list_lock); - list_add(&tunnel->list, &pppol2tp_tunnel_list); - write_unlock_bh(&pppol2tp_tunnel_list_lock); + write_lock_bh(&pn->pppol2tp_tunnel_list_lock); + list_add(&tunnel->list, &pn->pppol2tp_tunnel_list); + write_unlock_bh(&pn->pppol2tp_tunnel_list_lock); atomic_inc(&pppol2tp_tunnel_count); /* Bump the reference count. The tunnel context is deleted @@ -1629,7 +1652,8 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, * tunnel id. */ if ((sp->pppol2tp.s_session == 0) && (sp->pppol2tp.d_session == 0)) { - tunnel_sock = pppol2tp_prepare_tunnel_socket(sp->pppol2tp.fd, + tunnel_sock = pppol2tp_prepare_tunnel_socket(sock_net(sk), + sp->pppol2tp.fd, sp->pppol2tp.s_tunnel, &error); if (tunnel_sock == NULL) @@ -1637,7 +1661,7 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, tunnel = tunnel_sock->sk_user_data; } else { - tunnel = pppol2tp_tunnel_find(sp->pppol2tp.s_tunnel); + tunnel = pppol2tp_tunnel_find(sock_net(sk), sp->pppol2tp.s_tunnel); /* Error if we can't find the tunnel */ error = -ENOENT; @@ -2347,8 +2371,9 @@ end: #include struct pppol2tp_seq_data { - struct pppol2tp_tunnel *tunnel; /* current tunnel */ - struct pppol2tp_session *session; /* NULL means get first session in tunnel */ + struct net *seq_net; /* net of inode */ + struct pppol2tp_tunnel *tunnel; /* current tunnel */ + struct pppol2tp_session *session; /* NULL means get first session in tunnel */ }; static struct pppol2tp_session *next_session(struct pppol2tp_tunnel *tunnel, struct pppol2tp_session *curr) @@ -2384,17 +2409,18 @@ out: return session; } -static struct pppol2tp_tunnel *next_tunnel(struct pppol2tp_tunnel *curr) +static struct pppol2tp_tunnel *next_tunnel(struct pppol2tp_net *pn, + struct pppol2tp_tunnel *curr) { struct pppol2tp_tunnel *tunnel = NULL; - read_lock_bh(&pppol2tp_tunnel_list_lock); - if (list_is_last(&curr->list, &pppol2tp_tunnel_list)) { + read_lock_bh(&pn->pppol2tp_tunnel_list_lock); + if (list_is_last(&curr->list, &pn->pppol2tp_tunnel_list)) { goto out; } tunnel = list_entry(curr->list.next, struct pppol2tp_tunnel, list); out: - read_unlock_bh(&pppol2tp_tunnel_list_lock); + read_unlock_bh(&pn->pppol2tp_tunnel_list_lock); return tunnel; } @@ -2402,6 +2428,7 @@ out: static void *pppol2tp_seq_start(struct seq_file *m, loff_t *offs) { struct pppol2tp_seq_data *pd = SEQ_START_TOKEN; + struct pppol2tp_net *pn; loff_t pos = *offs; if (!pos) @@ -2409,14 +2436,15 @@ static void *pppol2tp_seq_start(struct seq_file *m, loff_t *offs) BUG_ON(m->private == NULL); pd = m->private; + pn = pppol2tp_pernet(pd->seq_net); if (pd->tunnel == NULL) { - if (!list_empty(&pppol2tp_tunnel_list)) - pd->tunnel = list_entry(pppol2tp_tunnel_list.next, struct pppol2tp_tunnel, list); + if (!list_empty(&pn->pppol2tp_tunnel_list)) + pd->tunnel = list_entry(pn->pppol2tp_tunnel_list.next, struct pppol2tp_tunnel, list); } else { pd->session = next_session(pd->tunnel, pd->session); if (pd->session == NULL) { - pd->tunnel = next_tunnel(pd->tunnel); + pd->tunnel = next_tunnel(pn, pd->tunnel); } } @@ -2532,6 +2560,7 @@ static int pppol2tp_proc_open(struct inode *inode, struct file *file) { struct seq_file *m; struct pppol2tp_seq_data *pd; + struct net *net; int ret = 0; ret = seq_open(file, &pppol2tp_seq_ops); @@ -2542,12 +2571,15 @@ static int pppol2tp_proc_open(struct inode *inode, struct file *file) /* Allocate and fill our proc_data for access later */ ret = -ENOMEM; - m->private = kzalloc(sizeof(struct pppol2tp_seq_data), GFP_KERNEL); + m->private = kzalloc(sizeof(*pd), GFP_KERNEL); if (m->private == NULL) goto out; pd = m->private; - ret = 0; + net = maybe_get_net(PDE_NET(PDE(inode))); + BUG_ON(!net); + pd->seq_net = net; + return 0; out: return ret; @@ -2558,6 +2590,9 @@ out: static int pppol2tp_proc_release(struct inode *inode, struct file *file) { struct seq_file *m = (struct seq_file *)file->private_data; + struct pppol2tp_seq_data *pd = m->private; + + put_net(pd->seq_net); kfree(m->private); m->private = NULL; @@ -2573,8 +2608,6 @@ static const struct file_operations pppol2tp_proc_fops = { .release = pppol2tp_proc_release, }; -static struct proc_dir_entry *pppol2tp_proc; - #endif /* CONFIG_PROC_FS */ /***************************************************************************** @@ -2606,6 +2639,57 @@ static struct pppox_proto pppol2tp_proto = { .ioctl = pppol2tp_ioctl }; +static __net_init int pppol2tp_init_net(struct net *net) +{ + struct pppol2tp_net *pn; + struct proc_dir_entry *pde; + int err; + + pn = kzalloc(sizeof(*pn), GFP_KERNEL); + if (!pn) + return -ENOMEM; + + INIT_LIST_HEAD(&pn->pppol2tp_tunnel_list); + rwlock_init(&pn->pppol2tp_tunnel_list_lock); + + err = net_assign_generic(net, pppol2tp_net_id, pn); + if (err) + goto out; + + pde = proc_net_fops_create(net, "pppol2tp", S_IRUGO, &pppol2tp_proc_fops); +#ifdef CONFIG_PROC_FS + if (!pde) { + err = -ENOMEM; + goto out; + } +#endif + + return 0; + +out: + kfree(pn); + return err; +} + +static __net_exit void pppol2tp_exit_net(struct net *net) +{ + struct pppoe_net *pn; + + proc_net_remove(net, "pppol2tp"); + pn = net_generic(net, pppol2tp_net_id); + /* + * if someone has cached our net then + * further net_generic call will return NULL + */ + net_assign_generic(net, pppol2tp_net_id, NULL); + kfree(pn); +} + +static __net_initdata struct pernet_operations pppol2tp_net_ops = { + .init = pppol2tp_init_net, + .exit = pppol2tp_exit_net, +}; + static int __init pppol2tp_init(void) { int err; @@ -2617,23 +2701,17 @@ static int __init pppol2tp_init(void) if (err) goto out_unregister_pppol2tp_proto; -#ifdef CONFIG_PROC_FS - pppol2tp_proc = proc_net_fops_create(&init_net, "pppol2tp", 0, - &pppol2tp_proc_fops); - if (!pppol2tp_proc) { - err = -ENOMEM; + err = register_pernet_gen_device(&pppol2tp_net_id, &pppol2tp_net_ops); + if (err) goto out_unregister_pppox_proto; - } -#endif /* CONFIG_PROC_FS */ + printk(KERN_INFO "PPPoL2TP kernel driver, %s\n", PPPOL2TP_DRV_VERSION); out: return err; -#ifdef CONFIG_PROC_FS out_unregister_pppox_proto: unregister_pppox_proto(PX_PROTO_OL2TP); -#endif out_unregister_pppol2tp_proto: proto_unregister(&pppol2tp_sk_proto); goto out; @@ -2642,10 +2720,6 @@ out_unregister_pppol2tp_proto: static void __exit pppol2tp_exit(void) { unregister_pppox_proto(PX_PROTO_OL2TP); - -#ifdef CONFIG_PROC_FS - remove_proc_entry("pppol2tp", init_net.proc_net); -#endif proto_unregister(&pppol2tp_sk_proto); } diff --git a/drivers/net/pppox.c b/drivers/net/pppox.c index ee9d3cf81be..4f6d33fbc67 100644 --- a/drivers/net/pppox.c +++ b/drivers/net/pppox.c @@ -111,10 +111,6 @@ static int pppox_create(struct net *net, struct socket *sock, int protocol) if (protocol < 0 || protocol > PX_MAX_PROTO) goto out; - /* we support net-namespaces for PPPoE only (yet) */ - if (protocol != PX_PROTO_OE && net != &init_net) - return -EAFNOSUPPORT; - rc = -EPROTONOSUPPORT; if (!pppox_protos[protocol]) request_module("pppox-proto-%d", protocol); -- GitLab From 273ec51dd7ceaa76e038875d85061ec856d8905e Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Wed, 21 Jan 2009 15:55:35 -0800 Subject: [PATCH 0367/4982] net: ppp_generic - introduce net-namespace functionality v2 - Each namespace contains ppp channels and units separately with appropriate locks Signed-off-by: Cyrill Gorcunov Signed-off-by: David S. Miller --- drivers/net/ppp_generic.c | 275 ++++++++++++++++++++++++++---------- include/linux/ppp_channel.h | 4 + 2 files changed, 202 insertions(+), 77 deletions(-) diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 7b2728b8f1b..4405a76ed3d 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -49,6 +49,10 @@ #include #include +#include +#include +#include + #define PPP_VERSION "2.4.2" /* @@ -131,6 +135,7 @@ struct ppp { struct sock_filter *active_filter;/* filter for pkts to reset idle */ unsigned pass_len, active_len; #endif /* CONFIG_PPP_FILTER */ + struct net *ppp_net; /* the net we belong to */ }; /* @@ -155,6 +160,7 @@ struct channel { struct rw_semaphore chan_sem; /* protects `chan' during chan ioctl */ spinlock_t downl; /* protects `chan', file.xq dequeue */ struct ppp *ppp; /* ppp unit we're connected to */ + struct net *chan_net; /* the net channel belongs to */ struct list_head clist; /* link in list of channels per unit */ rwlock_t upl; /* protects `ppp' */ #ifdef CONFIG_PPP_MULTILINK @@ -173,26 +179,35 @@ struct channel { * channel.downl. */ -/* - * all_ppp_mutex protects the all_ppp_units mapping. - * It also ensures that finding a ppp unit in the all_ppp_units map - * and updating its file.refcnt field is atomic. - */ -static DEFINE_MUTEX(all_ppp_mutex); static atomic_t ppp_unit_count = ATOMIC_INIT(0); -static DEFINE_IDR(ppp_units_idr); - -/* - * all_channels_lock protects all_channels and last_channel_index, - * and the atomicity of find a channel and updating its file.refcnt - * field. - */ -static DEFINE_SPINLOCK(all_channels_lock); -static LIST_HEAD(all_channels); -static LIST_HEAD(new_channels); -static int last_channel_index; static atomic_t channel_count = ATOMIC_INIT(0); +/* per-net private data for this module */ +static unsigned int ppp_net_id; +struct ppp_net { + /* units to ppp mapping */ + struct idr units_idr; + + /* + * all_ppp_mutex protects the units_idr mapping. + * It also ensures that finding a ppp unit in the units_idr + * map and updating its file.refcnt field is atomic. + */ + struct mutex all_ppp_mutex; + + /* channels */ + struct list_head all_channels; + struct list_head new_channels; + int last_channel_index; + + /* + * all_channels_lock protects all_channels and + * last_channel_index, and the atomicity of find + * a channel and updating its file.refcnt field. + */ + spinlock_t all_channels_lock; +}; + /* Get the PPP protocol number from a skb */ #define PPP_PROTO(skb) (((skb)->data[0] << 8) + (skb)->data[1]) @@ -216,8 +231,8 @@ static atomic_t channel_count = ATOMIC_INIT(0); #define seq_after(a, b) ((s32)((a) - (b)) > 0) /* Prototypes. */ -static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file, - unsigned int cmd, unsigned long arg); +static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf, + struct file *file, unsigned int cmd, unsigned long arg); static void ppp_xmit_process(struct ppp *ppp); static void ppp_send_frame(struct ppp *ppp, struct sk_buff *skb); static void ppp_push(struct ppp *ppp); @@ -240,12 +255,12 @@ static void ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound); static void ppp_ccp_closed(struct ppp *ppp); static struct compressor *find_compressor(int type); static void ppp_get_stats(struct ppp *ppp, struct ppp_stats *st); -static struct ppp *ppp_create_interface(int unit, int *retp); +static struct ppp *ppp_create_interface(struct net *net, int unit, int *retp); static void init_ppp_file(struct ppp_file *pf, int kind); static void ppp_shutdown_interface(struct ppp *ppp); static void ppp_destroy_interface(struct ppp *ppp); -static struct ppp *ppp_find_unit(int unit); -static struct channel *ppp_find_channel(int unit); +static struct ppp *ppp_find_unit(struct ppp_net *pn, int unit); +static struct channel *ppp_find_channel(struct ppp_net *pn, int unit); static int ppp_connect_channel(struct channel *pch, int unit); static int ppp_disconnect_channel(struct channel *pch); static void ppp_destroy_channel(struct channel *pch); @@ -256,6 +271,14 @@ static void *unit_find(struct idr *p, int n); static struct class *ppp_class; +/* per net-namespace data */ +static inline struct ppp_net *ppp_pernet(struct net *net) +{ + BUG_ON(!net); + + return net_generic(net, ppp_net_id); +} + /* Translates a PPP protocol number to a NP index (NP == network protocol) */ static inline int proto_to_npindex(int proto) { @@ -544,7 +567,8 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int __user *p = argp; if (!pf) - return ppp_unattached_ioctl(pf, file, cmd, arg); + return ppp_unattached_ioctl(current->nsproxy->net_ns, + pf, file, cmd, arg); if (cmd == PPPIOCDETACH) { /* @@ -763,12 +787,13 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return err; } -static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file, - unsigned int cmd, unsigned long arg) +static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf, + struct file *file, unsigned int cmd, unsigned long arg) { int unit, err = -EFAULT; struct ppp *ppp; struct channel *chan; + struct ppp_net *pn; int __user *p = (int __user *)arg; lock_kernel(); @@ -777,7 +802,7 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file, /* Create a new ppp unit */ if (get_user(unit, p)) break; - ppp = ppp_create_interface(unit, &err); + ppp = ppp_create_interface(net, unit, &err); if (!ppp) break; file->private_data = &ppp->file; @@ -792,29 +817,31 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file, /* Attach to an existing ppp unit */ if (get_user(unit, p)) break; - mutex_lock(&all_ppp_mutex); err = -ENXIO; - ppp = ppp_find_unit(unit); + pn = ppp_pernet(net); + mutex_lock(&pn->all_ppp_mutex); + ppp = ppp_find_unit(pn, unit); if (ppp) { atomic_inc(&ppp->file.refcnt); file->private_data = &ppp->file; err = 0; } - mutex_unlock(&all_ppp_mutex); + mutex_unlock(&pn->all_ppp_mutex); break; case PPPIOCATTCHAN: if (get_user(unit, p)) break; - spin_lock_bh(&all_channels_lock); err = -ENXIO; - chan = ppp_find_channel(unit); + pn = ppp_pernet(net); + spin_lock_bh(&pn->all_channels_lock); + chan = ppp_find_channel(pn, unit); if (chan) { atomic_inc(&chan->file.refcnt); file->private_data = &chan->file; err = 0; } - spin_unlock_bh(&all_channels_lock); + spin_unlock_bh(&pn->all_channels_lock); break; default: @@ -834,6 +861,51 @@ static const struct file_operations ppp_device_fops = { .release = ppp_release }; +static __net_init int ppp_init_net(struct net *net) +{ + struct ppp_net *pn; + int err; + + pn = kzalloc(sizeof(*pn), GFP_KERNEL); + if (!pn) + return -ENOMEM; + + idr_init(&pn->units_idr); + mutex_init(&pn->all_ppp_mutex); + + INIT_LIST_HEAD(&pn->all_channels); + INIT_LIST_HEAD(&pn->new_channels); + + spin_lock_init(&pn->all_channels_lock); + + err = net_assign_generic(net, ppp_net_id, pn); + if (err) { + kfree(pn); + return err; + } + + return 0; +} + +static __net_exit void ppp_exit_net(struct net *net) +{ + struct ppp_net *pn; + + pn = net_generic(net, ppp_net_id); + idr_destroy(&pn->units_idr); + /* + * if someone has cached our net then + * further net_generic call will return NULL + */ + net_assign_generic(net, ppp_net_id, NULL); + kfree(pn); +} + +static __net_initdata struct pernet_operations ppp_net_ops = { + .init = ppp_init_net, + .exit = ppp_exit_net, +}; + #define PPP_MAJOR 108 /* Called at boot time if ppp is compiled into the kernel, @@ -843,25 +915,36 @@ static int __init ppp_init(void) int err; printk(KERN_INFO "PPP generic driver version " PPP_VERSION "\n"); - err = register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops); - if (!err) { - ppp_class = class_create(THIS_MODULE, "ppp"); - if (IS_ERR(ppp_class)) { - err = PTR_ERR(ppp_class); - goto out_chrdev; - } - device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL, - "ppp"); + + err = register_pernet_gen_device(&ppp_net_id, &ppp_net_ops); + if (err) { + printk(KERN_ERR "failed to register PPP pernet device (%d)\n", err); + goto out; } -out: - if (err) + err = register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops); + if (err) { printk(KERN_ERR "failed to register PPP device (%d)\n", err); - return err; + goto out_net; + } + + ppp_class = class_create(THIS_MODULE, "ppp"); + if (IS_ERR(ppp_class)) { + err = PTR_ERR(ppp_class); + goto out_chrdev; + } + + /* not a big deal if we fail here :-) */ + device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL, "ppp"); + + return 0; out_chrdev: unregister_chrdev(PPP_MAJOR, "ppp"); - goto out; +out_net: + unregister_pernet_gen_device(ppp_net_id, &ppp_net_ops); +out: + return err; } /* @@ -969,6 +1052,7 @@ static void ppp_setup(struct net_device *dev) dev->tx_queue_len = 3; dev->type = ARPHRD_PPP; dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; + dev->features |= NETIF_F_NETNS_LOCAL; } /* @@ -1986,19 +2070,27 @@ ppp_mp_reconstruct(struct ppp *ppp) * Channel interface. */ -/* - * Create a new, unattached ppp channel. - */ -int -ppp_register_channel(struct ppp_channel *chan) +/* Create a new, unattached ppp channel. */ +int ppp_register_channel(struct ppp_channel *chan) +{ + return ppp_register_net_channel(current->nsproxy->net_ns, chan); +} + +/* Create a new, unattached ppp channel for specified net. */ +int ppp_register_net_channel(struct net *net, struct ppp_channel *chan) { struct channel *pch; + struct ppp_net *pn; pch = kzalloc(sizeof(struct channel), GFP_KERNEL); if (!pch) return -ENOMEM; + + pn = ppp_pernet(net); + pch->ppp = NULL; pch->chan = chan; + pch->chan_net = net; chan->ppp = pch; init_ppp_file(&pch->file, CHANNEL); pch->file.hdrlen = chan->hdrlen; @@ -2008,11 +2100,13 @@ ppp_register_channel(struct ppp_channel *chan) init_rwsem(&pch->chan_sem); spin_lock_init(&pch->downl); rwlock_init(&pch->upl); - spin_lock_bh(&all_channels_lock); - pch->file.index = ++last_channel_index; - list_add(&pch->list, &new_channels); + + spin_lock_bh(&pn->all_channels_lock); + pch->file.index = ++pn->last_channel_index; + list_add(&pch->list, &pn->new_channels); atomic_inc(&channel_count); - spin_unlock_bh(&all_channels_lock); + spin_unlock_bh(&pn->all_channels_lock); + return 0; } @@ -2053,9 +2147,11 @@ void ppp_unregister_channel(struct ppp_channel *chan) { struct channel *pch = chan->ppp; + struct ppp_net *pn; if (!pch) return; /* should never happen */ + chan->ppp = NULL; /* @@ -2068,9 +2164,12 @@ ppp_unregister_channel(struct ppp_channel *chan) spin_unlock_bh(&pch->downl); up_write(&pch->chan_sem); ppp_disconnect_channel(pch); - spin_lock_bh(&all_channels_lock); + + pn = ppp_pernet(pch->chan_net); + spin_lock_bh(&pn->all_channels_lock); list_del(&pch->list); - spin_unlock_bh(&all_channels_lock); + spin_unlock_bh(&pn->all_channels_lock); + pch->file.dead = 1; wake_up_interruptible(&pch->file.rwait); if (atomic_dec_and_test(&pch->file.refcnt)) @@ -2395,9 +2494,10 @@ ppp_get_stats(struct ppp *ppp, struct ppp_stats *st) * unit == -1 means allocate a new number. */ static struct ppp * -ppp_create_interface(int unit, int *retp) +ppp_create_interface(struct net *net, int unit, int *retp) { struct ppp *ppp; + struct ppp_net *pn; struct net_device *dev = NULL; int ret = -ENOMEM; int i; @@ -2406,6 +2506,8 @@ ppp_create_interface(int unit, int *retp) if (!dev) goto out1; + pn = ppp_pernet(net); + ppp = netdev_priv(dev); ppp->dev = dev; ppp->mru = PPP_MRU; @@ -2421,17 +2523,23 @@ ppp_create_interface(int unit, int *retp) skb_queue_head_init(&ppp->mrq); #endif /* CONFIG_PPP_MULTILINK */ + /* + * drum roll: don't forget to set + * the net device is belong to + */ + dev_net_set(dev, net); + ret = -EEXIST; - mutex_lock(&all_ppp_mutex); + mutex_lock(&pn->all_ppp_mutex); if (unit < 0) { - unit = unit_get(&ppp_units_idr, ppp); + unit = unit_get(&pn->units_idr, ppp); if (unit < 0) { *retp = unit; goto out2; } } else { - if (unit_find(&ppp_units_idr, unit)) + if (unit_find(&pn->units_idr, unit)) goto out2; /* unit already exists */ /* * if caller need a specified unit number @@ -2442,7 +2550,7 @@ ppp_create_interface(int unit, int *retp) * fair but at least pppd will ask us to allocate * new unit in this case so user is happy :) */ - unit = unit_set(&ppp_units_idr, ppp, unit); + unit = unit_set(&pn->units_idr, ppp, unit); if (unit < 0) goto out2; } @@ -2453,20 +2561,22 @@ ppp_create_interface(int unit, int *retp) ret = register_netdev(dev); if (ret != 0) { - unit_put(&ppp_units_idr, unit); + unit_put(&pn->units_idr, unit); printk(KERN_ERR "PPP: couldn't register device %s (%d)\n", dev->name, ret); goto out2; } + ppp->ppp_net = net; + atomic_inc(&ppp_unit_count); - mutex_unlock(&all_ppp_mutex); + mutex_unlock(&pn->all_ppp_mutex); *retp = 0; return ppp; out2: - mutex_unlock(&all_ppp_mutex); + mutex_unlock(&pn->all_ppp_mutex); free_netdev(dev); out1: *retp = ret; @@ -2492,7 +2602,11 @@ init_ppp_file(struct ppp_file *pf, int kind) */ static void ppp_shutdown_interface(struct ppp *ppp) { - mutex_lock(&all_ppp_mutex); + struct ppp_net *pn; + + pn = ppp_pernet(ppp->ppp_net); + mutex_lock(&pn->all_ppp_mutex); + /* This will call dev_close() for us. */ ppp_lock(ppp); if (!ppp->closing) { @@ -2502,11 +2616,12 @@ static void ppp_shutdown_interface(struct ppp *ppp) } else ppp_unlock(ppp); - unit_put(&ppp_units_idr, ppp->file.index); + unit_put(&pn->units_idr, ppp->file.index); ppp->file.dead = 1; ppp->owner = NULL; wake_up_interruptible(&ppp->file.rwait); - mutex_unlock(&all_ppp_mutex); + + mutex_unlock(&pn->all_ppp_mutex); } /* @@ -2554,9 +2669,9 @@ static void ppp_destroy_interface(struct ppp *ppp) * The caller should have locked the all_ppp_mutex. */ static struct ppp * -ppp_find_unit(int unit) +ppp_find_unit(struct ppp_net *pn, int unit) { - return unit_find(&ppp_units_idr, unit); + return unit_find(&pn->units_idr, unit); } /* @@ -2568,20 +2683,22 @@ ppp_find_unit(int unit) * when we have a lot of channels in use. */ static struct channel * -ppp_find_channel(int unit) +ppp_find_channel(struct ppp_net *pn, int unit) { struct channel *pch; - list_for_each_entry(pch, &new_channels, list) { + list_for_each_entry(pch, &pn->new_channels, list) { if (pch->file.index == unit) { - list_move(&pch->list, &all_channels); + list_move(&pch->list, &pn->all_channels); return pch; } } - list_for_each_entry(pch, &all_channels, list) { + + list_for_each_entry(pch, &pn->all_channels, list) { if (pch->file.index == unit) return pch; } + return NULL; } @@ -2592,11 +2709,14 @@ static int ppp_connect_channel(struct channel *pch, int unit) { struct ppp *ppp; + struct ppp_net *pn; int ret = -ENXIO; int hdrlen; - mutex_lock(&all_ppp_mutex); - ppp = ppp_find_unit(unit); + pn = ppp_pernet(pch->chan_net); + + mutex_lock(&pn->all_ppp_mutex); + ppp = ppp_find_unit(pn, unit); if (!ppp) goto out; write_lock_bh(&pch->upl); @@ -2620,7 +2740,7 @@ ppp_connect_channel(struct channel *pch, int unit) outl: write_unlock_bh(&pch->upl); out: - mutex_unlock(&all_ppp_mutex); + mutex_unlock(&pn->all_ppp_mutex); return ret; } @@ -2677,7 +2797,7 @@ static void __exit ppp_cleanup(void) unregister_chrdev(PPP_MAJOR, "ppp"); device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0)); class_destroy(ppp_class); - idr_destroy(&ppp_units_idr); + unregister_pernet_gen_device(ppp_net_id, &ppp_net_ops); } /* @@ -2743,6 +2863,7 @@ static void *unit_find(struct idr *p, int n) module_init(ppp_init); module_exit(ppp_cleanup); +EXPORT_SYMBOL(ppp_register_net_channel); EXPORT_SYMBOL(ppp_register_channel); EXPORT_SYMBOL(ppp_unregister_channel); EXPORT_SYMBOL(ppp_channel_index); diff --git a/include/linux/ppp_channel.h b/include/linux/ppp_channel.h index a942892d6df..9d64bdf1477 100644 --- a/include/linux/ppp_channel.h +++ b/include/linux/ppp_channel.h @@ -22,6 +22,7 @@ #include #include #include +#include struct ppp_channel; @@ -56,6 +57,9 @@ extern void ppp_input(struct ppp_channel *, struct sk_buff *); that we may have missed a packet. */ extern void ppp_input_error(struct ppp_channel *, int code); +/* Attach a channel to a given PPP unit in specified net. */ +extern int ppp_register_net_channel(struct net *, struct ppp_channel *); + /* Attach a channel to a given PPP unit. */ extern int ppp_register_channel(struct ppp_channel *); -- GitLab From f5882c30508c1e3c4fbbdaa9ca08d0922c5fb071 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Wed, 21 Jan 2009 15:55:40 -0800 Subject: [PATCH 0368/4982] net: pppoe,pppol2tp - register channels with explicit net In PPPo[E|L2TP] we could explicitly point which net namespace we're going to use for channels - make it so. Signed-off-by: Cyrill Gorcunov Signed-off-by: James Chapman Signed-off-by: David S. Miller --- drivers/net/pppoe.c | 2 +- drivers/net/pppol2tp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index fb3056334aa..39f3e21647e 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -695,7 +695,7 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, po->chan.private = sk; po->chan.ops = &pppoe_chan_ops; - error = ppp_register_channel(&po->chan); + error = ppp_register_net_channel(dev_net(dev), &po->chan); if (error) goto err_put; diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index f3f9cb1f77c..056e22a784b 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c @@ -1749,7 +1749,7 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, po->chan.ops = &pppol2tp_chan_ops; po->chan.mtu = session->mtu; - error = ppp_register_channel(&po->chan); + error = ppp_register_net_channel(sock_net(sk), &po->chan); if (error) goto end_put_tun; -- GitLab From 74a3e5a71c9b54c63bff978e9cafbcef67600f0b Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 20 Jan 2009 10:56:20 +0000 Subject: [PATCH 0369/4982] tun: Remove unnecessary tun_get_by_name Currently the tun driver keeps a private list of tun devices for what appears to be a small gain in performance when reconnecting a file descriptor to an existing tun or tap device. So simplify the code by removing it. Signed-off-by: Eric W. Biederman Signed-off-by: David S. Miller --- drivers/net/tun.c | 74 ++++++++++++----------------------------------- 1 file changed, 19 insertions(+), 55 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index d7b81e4fdd5..17923a50853 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -88,7 +88,6 @@ struct tap_filter { }; struct tun_struct { - struct list_head list; unsigned int flags; int attached; uid_t owner; @@ -213,11 +212,6 @@ static int check_filter(struct tap_filter *filter, const struct sk_buff *skb) /* Network device part of the driver */ -static int tun_net_id; -struct tun_net { - struct list_head dev_list; -}; - static const struct ethtool_ops tun_ethtool_ops; /* Net device open. */ @@ -697,30 +691,22 @@ static void tun_setup(struct net_device *dev) dev->features |= NETIF_F_NETNS_LOCAL; } -static struct tun_struct *tun_get_by_name(struct tun_net *tn, const char *name) -{ - struct tun_struct *tun; - - ASSERT_RTNL(); - list_for_each_entry(tun, &tn->dev_list, list) { - if (!strncmp(tun->dev->name, name, IFNAMSIZ)) - return tun; - } - - return NULL; -} - static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) { - struct tun_net *tn; struct tun_struct *tun; struct net_device *dev; const struct cred *cred = current_cred(); int err; - tn = net_generic(net, tun_net_id); - tun = tun_get_by_name(tn, ifr->ifr_name); - if (tun) { + dev = __dev_get_by_name(net, ifr->ifr_name); + if (dev) { + if ((ifr->ifr_flags & IFF_TUN) && dev->netdev_ops == &tun_netdev_ops) + tun = netdev_priv(dev); + else if ((ifr->ifr_flags & IFF_TAP) && dev->netdev_ops == &tap_netdev_ops) + tun = netdev_priv(dev); + else + return -EINVAL; + if (tun->attached) return -EBUSY; @@ -733,8 +719,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) return -EPERM; } } - else if (__dev_get_by_name(net, ifr->ifr_name)) - return -EINVAL; else { char *name; unsigned long flags = 0; @@ -782,8 +766,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) err = register_netdevice(tun->dev); if (err < 0) goto err_free_dev; - - list_add(&tun->list, &tn->dev_list); } DBG(KERN_INFO "%s: tun_set_iff\n", tun->dev->name); @@ -1095,10 +1077,8 @@ static int tun_chr_close(struct inode *inode, struct file *file) /* Drop read queue */ skb_queue_purge(&tun->readq); - if (!(tun->flags & TUN_PERSIST)) { - list_del(&tun->list); + if (!(tun->flags & TUN_PERSIST)) unregister_netdevice(tun->dev); - } rtnl_unlock(); @@ -1212,37 +1192,21 @@ static const struct ethtool_ops tun_ethtool_ops = { static int tun_init_net(struct net *net) { - struct tun_net *tn; - - tn = kmalloc(sizeof(*tn), GFP_KERNEL); - if (tn == NULL) - return -ENOMEM; - - INIT_LIST_HEAD(&tn->dev_list); - - if (net_assign_generic(net, tun_net_id, tn)) { - kfree(tn); - return -ENOMEM; - } - return 0; } static void tun_exit_net(struct net *net) { - struct tun_net *tn; - struct tun_struct *tun, *nxt; - - tn = net_generic(net, tun_net_id); + struct net_device *dev, *next; rtnl_lock(); - list_for_each_entry_safe(tun, nxt, &tn->dev_list, list) { - DBG(KERN_INFO "%s cleaned up\n", tun->dev->name); - unregister_netdevice(tun->dev); + for_each_netdev_safe(net, dev, next) { + if (dev->ethtool_ops != &tun_ethtool_ops) + continue; + DBG(KERN_INFO "%s cleaned up\n", dev->name); + unregister_netdevice(dev); } rtnl_unlock(); - - kfree(tn); } static struct pernet_operations tun_net_ops = { @@ -1257,7 +1221,7 @@ static int __init tun_init(void) printk(KERN_INFO "tun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION); printk(KERN_INFO "tun: %s\n", DRV_COPYRIGHT); - ret = register_pernet_gen_device(&tun_net_id, &tun_net_ops); + ret = register_pernet_device(&tun_net_ops); if (ret) { printk(KERN_ERR "tun: Can't register pernet ops\n"); goto err_pernet; @@ -1271,7 +1235,7 @@ static int __init tun_init(void) return 0; err_misc: - unregister_pernet_gen_device(tun_net_id, &tun_net_ops); + unregister_pernet_device(&tun_net_ops); err_pernet: return ret; } @@ -1279,7 +1243,7 @@ err_pernet: static void tun_cleanup(void) { misc_deregister(&tun_miscdev); - unregister_pernet_gen_device(tun_net_id, &tun_net_ops); + unregister_pernet_device(&tun_net_ops); } module_init(tun_init); -- GitLab From a7385ba21102a90f902055f9f185ca02bf62fa43 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 20 Jan 2009 10:57:48 +0000 Subject: [PATCH 0370/4982] tun: Fix races in tun_set_iff It is possible for two different tasks with access to the same file descriptor to call tun_set_iff on it at the same time and race to attach to a tap device. Prevent this by placing all of the logic to attach to a file descriptor in one function and testing the file descriptor to be certain it is not already attached to another tun device. Signed-off-by: Eric W. Biederman Signed-off-by: David S. Miller --- drivers/net/tun.c | 48 +++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 17923a50853..20ef14dc560 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -106,6 +106,31 @@ struct tun_struct { #endif }; +static int tun_attach(struct tun_struct *tun, struct file *file) +{ + const struct cred *cred = current_cred(); + + ASSERT_RTNL(); + + if (file->private_data) + return -EINVAL; + + if (tun->attached) + return -EBUSY; + + /* Check permissions */ + if (((tun->owner != -1 && cred->euid != tun->owner) || + (tun->group != -1 && cred->egid != tun->group)) && + !capable(CAP_NET_ADMIN)) + return -EPERM; + + file->private_data = tun; + tun->attached = 1; + get_net(dev_net(tun->dev)); + + return 0; +} + /* TAP filterting */ static void addr_hash_set(u32 *mask, const u8 *addr) { @@ -695,7 +720,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) { struct tun_struct *tun; struct net_device *dev; - const struct cred *cred = current_cred(); int err; dev = __dev_get_by_name(net, ifr->ifr_name); @@ -707,17 +731,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) else return -EINVAL; - if (tun->attached) - return -EBUSY; - - /* Check permissions */ - if (((tun->owner != -1 && - cred->euid != tun->owner) || - (tun->group != -1 && - cred->egid != tun->group)) && - !capable(CAP_NET_ADMIN)) { - return -EPERM; - } + err = tun_attach(tun, file); + if (err < 0) + return err; } else { char *name; @@ -766,6 +782,10 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) err = register_netdevice(tun->dev); if (err < 0) goto err_free_dev; + + err = tun_attach(tun, file); + if (err < 0) + goto err_free_dev; } DBG(KERN_INFO "%s: tun_set_iff\n", tun->dev->name); @@ -785,10 +805,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) else tun->flags &= ~TUN_VNET_HDR; - file->private_data = tun; - tun->attached = 1; - get_net(dev_net(tun->dev)); - /* Make sure persistent devices do not get stuck in * xoff state. */ -- GitLab From eac9e902658dab1e097b8ef064e9e3d16c152cc9 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 20 Jan 2009 10:59:05 +0000 Subject: [PATCH 0371/4982] tun: Use POLLERR not EBADF in tun_chr_poll EBADF is meaningless in the context of a poll mask so use POLLERR instead. Signed-off-by: Eric W. Biederman Signed-off-by: David S. Miller --- drivers/net/tun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 20ef14dc560..8743de9d257 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -382,7 +382,7 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait) unsigned int mask = POLLOUT | POLLWRNORM; if (!tun) - return -EBADFD; + return POLLERR; DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name); -- GitLab From 631ab46b79559d6fed784fd7883c0cda4d8cfcfa Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 20 Jan 2009 11:00:40 +0000 Subject: [PATCH 0372/4982] tun: Introduce tun_file Currently the tun code suffers from only having a single word of data that exists for the entire life of the tun file descriptor. This results in peculiar holding of references to the network namespace as well as races between free_netdevice and tun_chr_close. Fix this by introducing tun_file which will hold the per file state. For the moment it still holds just a single word so the differences are all logic changes with no changes in semantics. Signed-off-by: Eric W. Biederman Signed-off-by: David S. Miller --- drivers/net/tun.c | 156 ++++++++++++++++++++++++++++++---------------- 1 file changed, 104 insertions(+), 52 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 8743de9d257..d3a665d2f7b 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -87,9 +87,13 @@ struct tap_filter { unsigned char addr[FLT_EXACT_COUNT][ETH_ALEN]; }; +struct tun_file { + struct tun_struct *tun; +}; + struct tun_struct { + struct tun_file *tfile; unsigned int flags; - int attached; uid_t owner; gid_t group; @@ -108,14 +112,15 @@ struct tun_struct { static int tun_attach(struct tun_struct *tun, struct file *file) { + struct tun_file *tfile = file->private_data; const struct cred *cred = current_cred(); ASSERT_RTNL(); - if (file->private_data) + if (tfile->tun) return -EINVAL; - if (tun->attached) + if (tun->tfile) return -EBUSY; /* Check permissions */ @@ -124,13 +129,41 @@ static int tun_attach(struct tun_struct *tun, struct file *file) !capable(CAP_NET_ADMIN)) return -EPERM; - file->private_data = tun; - tun->attached = 1; + tfile->tun = tun; + tun->tfile = tfile; get_net(dev_net(tun->dev)); return 0; } +static void __tun_detach(struct tun_struct *tun) +{ + struct tun_file *tfile = tun->tfile; + + /* Detach from net device */ + tfile->tun = NULL; + tun->tfile = NULL; + put_net(dev_net(tun->dev)); + + /* Drop read queue */ + skb_queue_purge(&tun->readq); +} + +static struct tun_struct *__tun_get(struct tun_file *tfile) +{ + return tfile->tun; +} + +static struct tun_struct *tun_get(struct file *file) +{ + return __tun_get(file->private_data); +} + +static void tun_put(struct tun_struct *tun) +{ + /* Noop for now */ +} + /* TAP filterting */ static void addr_hash_set(u32 *mask, const u8 *addr) { @@ -261,7 +294,7 @@ static int tun_net_xmit(struct sk_buff *skb, struct net_device *dev) DBG(KERN_INFO "%s: tun_net_xmit %d\n", tun->dev->name, skb->len); /* Drop packet if interface is not attached */ - if (!tun->attached) + if (!tun->tfile) goto drop; /* Drop if the filter does not like it. @@ -378,7 +411,7 @@ static void tun_net_init(struct net_device *dev) /* Poll */ static unsigned int tun_chr_poll(struct file *file, poll_table * wait) { - struct tun_struct *tun = file->private_data; + struct tun_struct *tun = tun_get(file); unsigned int mask = POLLOUT | POLLWRNORM; if (!tun) @@ -391,6 +424,7 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait) if (!skb_queue_empty(&tun->readq)) mask |= POLLIN | POLLRDNORM; + tun_put(tun); return mask; } @@ -575,14 +609,18 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv, static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv, unsigned long count, loff_t pos) { - struct tun_struct *tun = iocb->ki_filp->private_data; + struct tun_struct *tun = tun_get(iocb->ki_filp); + ssize_t result; if (!tun) return -EBADFD; DBG(KERN_INFO "%s: tun_chr_write %ld\n", tun->dev->name, count); - return tun_get_user(tun, (struct iovec *) iv, iov_length(iv, count)); + result = tun_get_user(tun, (struct iovec *) iv, iov_length(iv, count)); + + tun_put(tun); + return result; } /* Put packet to the user space buffer */ @@ -655,7 +693,7 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, unsigned long count, loff_t pos) { struct file *file = iocb->ki_filp; - struct tun_struct *tun = file->private_data; + struct tun_struct *tun = tun_get(file); DECLARE_WAITQUEUE(wait, current); struct sk_buff *skb; ssize_t len, ret = 0; @@ -666,8 +704,10 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, DBG(KERN_INFO "%s: tun_chr_read\n", tun->dev->name); len = iov_length(iv, count); - if (len < 0) - return -EINVAL; + if (len < 0) { + ret = -EINVAL; + goto out; + } add_wait_queue(&tun->read_wait, &wait); while (len) { @@ -698,6 +738,8 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, current->state = TASK_RUNNING; remove_wait_queue(&tun->read_wait, &wait); +out: + tun_put(tun); return ret; } @@ -822,7 +864,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr) { - struct tun_struct *tun = file->private_data; + struct tun_struct *tun = tun_get(file); if (!tun) return -EBADFD; @@ -847,6 +889,7 @@ static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr) if (tun->flags & TUN_VNET_HDR) ifr->ifr_flags |= IFF_VNET_HDR; + tun_put(tun); return 0; } @@ -893,7 +936,7 @@ static int set_offload(struct net_device *dev, unsigned long arg) static int tun_chr_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - struct tun_struct *tun = file->private_data; + struct tun_struct *tun; void __user* argp = (void __user*)arg; struct ifreq ifr; int ret; @@ -902,6 +945,16 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, if (copy_from_user(&ifr, argp, sizeof ifr)) return -EFAULT; + if (cmd == TUNGETFEATURES) { + /* Currently this just means: "what IFF flags are valid?". + * This is needed because we never checked for invalid flags on + * TUNSETIFF. */ + return put_user(IFF_TUN | IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE | + IFF_VNET_HDR, + (unsigned int __user*)argp); + } + + tun = tun_get(file); if (cmd == TUNSETIFF && !tun) { int err; @@ -919,28 +972,21 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, return 0; } - if (cmd == TUNGETFEATURES) { - /* Currently this just means: "what IFF flags are valid?". - * This is needed because we never checked for invalid flags on - * TUNSETIFF. */ - return put_user(IFF_TUN | IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE | - IFF_VNET_HDR, - (unsigned int __user*)argp); - } if (!tun) return -EBADFD; DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->dev->name, cmd); + ret = 0; switch (cmd) { case TUNGETIFF: ret = tun_get_iff(current->nsproxy->net_ns, file, &ifr); if (ret) - return ret; + break; if (copy_to_user(argp, &ifr, sizeof(ifr))) - return -EFAULT; + ret = -EFAULT; break; case TUNSETNOCSUM: @@ -992,7 +1038,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, ret = 0; } rtnl_unlock(); - return ret; + break; #ifdef TUN_DEBUG case TUNSETDEBUG: @@ -1003,24 +1049,25 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, rtnl_lock(); ret = set_offload(tun->dev, arg); rtnl_unlock(); - return ret; + break; case TUNSETTXFILTER: /* Can be set only for TAPs */ + ret = -EINVAL; if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV) - return -EINVAL; + break; rtnl_lock(); ret = update_filter(&tun->txflt, (void __user *)arg); rtnl_unlock(); - return ret; + break; case SIOCGIFHWADDR: /* Get hw addres */ memcpy(ifr.ifr_hwaddr.sa_data, tun->dev->dev_addr, ETH_ALEN); ifr.ifr_hwaddr.sa_family = tun->dev->type; if (copy_to_user(argp, &ifr, sizeof ifr)) - return -EFAULT; - return 0; + ret = -EFAULT; + break; case SIOCSIFHWADDR: /* Set hw address */ @@ -1030,18 +1077,19 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, rtnl_lock(); ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr); rtnl_unlock(); - return ret; - + break; default: - return -EINVAL; + ret = -EINVAL; + break; }; - return 0; + tun_put(tun); + return ret; } static int tun_chr_fasync(int fd, struct file *file, int on) { - struct tun_struct *tun = file->private_data; + struct tun_struct *tun = tun_get(file); int ret; if (!tun) @@ -1063,40 +1111,44 @@ static int tun_chr_fasync(int fd, struct file *file, int on) ret = 0; out: unlock_kernel(); + tun_put(tun); return ret; } static int tun_chr_open(struct inode *inode, struct file * file) { + struct tun_file *tfile; cycle_kernel_lock(); DBG1(KERN_INFO "tunX: tun_chr_open\n"); - file->private_data = NULL; + + tfile = kmalloc(sizeof(*tfile), GFP_KERNEL); + if (!tfile) + return -ENOMEM; + tfile->tun = NULL; + file->private_data = tfile; return 0; } static int tun_chr_close(struct inode *inode, struct file *file) { - struct tun_struct *tun = file->private_data; - - if (!tun) - return 0; + struct tun_file *tfile = file->private_data; + struct tun_struct *tun = __tun_get(tfile); - DBG(KERN_INFO "%s: tun_chr_close\n", tun->dev->name); - rtnl_lock(); + if (tun) { + DBG(KERN_INFO "%s: tun_chr_close\n", tun->dev->name); - /* Detach from net device */ - file->private_data = NULL; - tun->attached = 0; - put_net(dev_net(tun->dev)); + rtnl_lock(); + __tun_detach(tun); - /* Drop read queue */ - skb_queue_purge(&tun->readq); + /* If desireable, unregister the netdevice. */ + if (!(tun->flags & TUN_PERSIST)) + unregister_netdevice(tun->dev); - if (!(tun->flags & TUN_PERSIST)) - unregister_netdevice(tun->dev); + rtnl_unlock(); + } - rtnl_unlock(); + kfree(tfile); return 0; } @@ -1177,7 +1229,7 @@ static void tun_set_msglevel(struct net_device *dev, u32 value) static u32 tun_get_link(struct net_device *dev) { struct tun_struct *tun = netdev_priv(dev); - return tun->attached; + return !!tun->tfile; } static u32 tun_get_rx_csum(struct net_device *dev) -- GitLab From 36b50bab53207daf34be63ca62fb8b0b08dc6e6b Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 20 Jan 2009 11:01:48 +0000 Subject: [PATCH 0373/4982] tun: Grab the netns in open. Grabbing namespaces in open, and putting them in close always seems to be the cleanest approach with the fewest surprises. So now that we have tun_file so we have somepleace to put the network namespace, let's grab the network namespace on file open and put on file close. Signed-off-by: Eric W. Biederman Signed-off-by: David S. Miller --- drivers/net/tun.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index d3a665d2f7b..dfbf5865977 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -89,6 +89,7 @@ struct tap_filter { struct tun_file { struct tun_struct *tun; + struct net *net; }; struct tun_struct { @@ -131,7 +132,6 @@ static int tun_attach(struct tun_struct *tun, struct file *file) tfile->tun = tun; tun->tfile = tfile; - get_net(dev_net(tun->dev)); return 0; } @@ -143,7 +143,6 @@ static void __tun_detach(struct tun_struct *tun) /* Detach from net device */ tfile->tun = NULL; tun->tfile = NULL; - put_net(dev_net(tun->dev)); /* Drop read queue */ skb_queue_purge(&tun->readq); @@ -936,6 +935,7 @@ static int set_offload(struct net_device *dev, unsigned long arg) static int tun_chr_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + struct tun_file *tfile = file->private_data; struct tun_struct *tun; void __user* argp = (void __user*)arg; struct ifreq ifr; @@ -954,14 +954,14 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, (unsigned int __user*)argp); } - tun = tun_get(file); + tun = __tun_get(tfile); if (cmd == TUNSETIFF && !tun) { int err; ifr.ifr_name[IFNAMSIZ-1] = '\0'; rtnl_lock(); - err = tun_set_iff(current->nsproxy->net_ns, file, &ifr); + err = tun_set_iff(tfile->net, file, &ifr); rtnl_unlock(); if (err) @@ -1125,6 +1125,7 @@ static int tun_chr_open(struct inode *inode, struct file * file) if (!tfile) return -ENOMEM; tfile->tun = NULL; + tfile->net = get_net(current->nsproxy->net_ns); file->private_data = tfile; return 0; } @@ -1148,6 +1149,7 @@ static int tun_chr_close(struct inode *inode, struct file *file) rtnl_unlock(); } + put_net(tfile->net); kfree(tfile); return 0; -- GitLab From 38231b7a8d1b74c920822640d1ce8eb8046377fb Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 20 Jan 2009 11:02:28 +0000 Subject: [PATCH 0374/4982] tun: Make tun_net_xmit atomic wrt tun_attach && tun_detach Currently this small race allows for a packet to be received when we detach from an tun device and still be enqueued. Not especially important but not what the code is trying to do. Signed-off-by: Eric W. Biederman Signed-off-by: David S. Miller --- drivers/net/tun.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index dfbf5865977..fa93160bf52 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -115,25 +115,33 @@ static int tun_attach(struct tun_struct *tun, struct file *file) { struct tun_file *tfile = file->private_data; const struct cred *cred = current_cred(); + int err; ASSERT_RTNL(); - if (tfile->tun) - return -EINVAL; - - if (tun->tfile) - return -EBUSY; - /* Check permissions */ if (((tun->owner != -1 && cred->euid != tun->owner) || (tun->group != -1 && cred->egid != tun->group)) && !capable(CAP_NET_ADMIN)) return -EPERM; + netif_tx_lock_bh(tun->dev); + + err = -EINVAL; + if (tfile->tun) + goto out; + + err = -EBUSY; + if (tun->tfile) + goto out; + + err = 0; tfile->tun = tun; tun->tfile = tfile; - return 0; +out: + netif_tx_unlock_bh(tun->dev); + return err; } static void __tun_detach(struct tun_struct *tun) @@ -141,8 +149,10 @@ static void __tun_detach(struct tun_struct *tun) struct tun_file *tfile = tun->tfile; /* Detach from net device */ + netif_tx_lock_bh(tun->dev); tfile->tun = NULL; tun->tfile = NULL; + netif_tx_unlock_bh(tun->dev); /* Drop read queue */ skb_queue_purge(&tun->readq); -- GitLab From b2430de37ef0bc0799ffba7b5219d38ca417eb76 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 20 Jan 2009 11:03:21 +0000 Subject: [PATCH 0375/4982] tun: Move read_wait into tun_file The poll interface requires that the waitqueue exist while the struct file is open. In the rare case when a tun device disappears before the tun file closes we fail to provide this property, so move read_wait. This is safe now that tun_net_xmit is atomic with tun_detach. Signed-off-by: Eric W. Biederman Signed-off-by: David S. Miller --- drivers/net/tun.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index fa93160bf52..030d9858bb6 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -90,6 +90,7 @@ struct tap_filter { struct tun_file { struct tun_struct *tun; struct net *net; + wait_queue_head_t read_wait; }; struct tun_struct { @@ -98,7 +99,6 @@ struct tun_struct { uid_t owner; gid_t group; - wait_queue_head_t read_wait; struct sk_buff_head readq; struct net_device *dev; @@ -335,7 +335,7 @@ static int tun_net_xmit(struct sk_buff *skb, struct net_device *dev) /* Notify and wake up reader process */ if (tun->flags & TUN_FASYNC) kill_fasync(&tun->fasync, SIGIO, POLL_IN); - wake_up_interruptible(&tun->read_wait); + wake_up_interruptible(&tun->tfile->read_wait); return 0; drop: @@ -420,7 +420,8 @@ static void tun_net_init(struct net_device *dev) /* Poll */ static unsigned int tun_chr_poll(struct file *file, poll_table * wait) { - struct tun_struct *tun = tun_get(file); + struct tun_file *tfile = file->private_data; + struct tun_struct *tun = __tun_get(tfile); unsigned int mask = POLLOUT | POLLWRNORM; if (!tun) @@ -428,7 +429,7 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait) DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name); - poll_wait(file, &tun->read_wait, wait); + poll_wait(file, &tfile->read_wait, wait); if (!skb_queue_empty(&tun->readq)) mask |= POLLIN | POLLRDNORM; @@ -702,7 +703,8 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, unsigned long count, loff_t pos) { struct file *file = iocb->ki_filp; - struct tun_struct *tun = tun_get(file); + struct tun_file *tfile = file->private_data; + struct tun_struct *tun = __tun_get(tfile); DECLARE_WAITQUEUE(wait, current); struct sk_buff *skb; ssize_t len, ret = 0; @@ -718,7 +720,7 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, goto out; } - add_wait_queue(&tun->read_wait, &wait); + add_wait_queue(&tfile->read_wait, &wait); while (len) { current->state = TASK_INTERRUPTIBLE; @@ -745,7 +747,7 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, } current->state = TASK_RUNNING; - remove_wait_queue(&tun->read_wait, &wait); + remove_wait_queue(&tfile->read_wait, &wait); out: tun_put(tun); @@ -757,7 +759,6 @@ static void tun_setup(struct net_device *dev) struct tun_struct *tun = netdev_priv(dev); skb_queue_head_init(&tun->readq); - init_waitqueue_head(&tun->read_wait); tun->owner = -1; tun->group = -1; @@ -1136,6 +1137,7 @@ static int tun_chr_open(struct inode *inode, struct file * file) return -ENOMEM; tfile->tun = NULL; tfile->net = get_net(current->nsproxy->net_ns); + init_waitqueue_head(&tfile->read_wait); file->private_data = tfile; return 0; } -- GitLab From c70f182940f988448f3c12a209d18b1edc276e33 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 20 Jan 2009 11:07:17 +0000 Subject: [PATCH 0376/4982] tun: Fix races between tun_net_close and free_netdev. The tun code does not cope gracefully if the network device goes away before the tun file descriptor is closed. It looks like we can trigger this with rmmod, and moving tun devices between network namespaces will allow this to be triggered when network namespaces exit. To fix this I introduce an intermediate data structure tun_file which holds a count of users and a pointer to the struct tun_struct. tun_get increments that reference count if it is greater than 0. tun_put decrements that reference count and detaches from the network device if the count is 0. While we have a file attached to the network device I hold a reference to the network device keeping it from going away completely. When a network device is unregistered I decrement the count of the attached tun_file and if that was the last user I detach the tun_file, and all processes on read_wait are woken up to ensure they do not sleep indefinitely. As some of those sleeps happen with the count on the tun device elevated waking up the read waiters ensures that tun_file will be detached in a timely manner. Signed-off-by: Eric W. Biederman Signed-off-by: David S. Miller --- drivers/net/tun.c | 50 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 030d9858bb6..51dba6192ba 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -88,6 +88,7 @@ struct tap_filter { }; struct tun_file { + atomic_t count; struct tun_struct *tun; struct net *net; wait_queue_head_t read_wait; @@ -138,6 +139,8 @@ static int tun_attach(struct tun_struct *tun, struct file *file) err = 0; tfile->tun = tun; tun->tfile = tfile; + dev_hold(tun->dev); + atomic_inc(&tfile->count); out: netif_tx_unlock_bh(tun->dev); @@ -156,11 +159,26 @@ static void __tun_detach(struct tun_struct *tun) /* Drop read queue */ skb_queue_purge(&tun->readq); + + /* Drop the extra count on the net device */ + dev_put(tun->dev); +} + +static void tun_detach(struct tun_struct *tun) +{ + rtnl_lock(); + __tun_detach(tun); + rtnl_unlock(); } static struct tun_struct *__tun_get(struct tun_file *tfile) { - return tfile->tun; + struct tun_struct *tun = NULL; + + if (atomic_inc_not_zero(&tfile->count)) + tun = tfile->tun; + + return tun; } static struct tun_struct *tun_get(struct file *file) @@ -170,7 +188,10 @@ static struct tun_struct *tun_get(struct file *file) static void tun_put(struct tun_struct *tun) { - /* Noop for now */ + struct tun_file *tfile = tun->tfile; + + if (atomic_dec_and_test(&tfile->count)) + tun_detach(tfile->tun); } /* TAP filterting */ @@ -281,6 +302,21 @@ static int check_filter(struct tap_filter *filter, const struct sk_buff *skb) static const struct ethtool_ops tun_ethtool_ops; +/* Net device detach from fd. */ +static void tun_net_uninit(struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + struct tun_file *tfile = tun->tfile; + + /* Inform the methods they need to stop using the dev. + */ + if (tfile) { + wake_up_all(&tfile->read_wait); + if (atomic_dec_and_test(&tfile->count)) + __tun_detach(tun); + } +} + /* Net device open. */ static int tun_net_open(struct net_device *dev) { @@ -367,6 +403,7 @@ tun_net_change_mtu(struct net_device *dev, int new_mtu) } static const struct net_device_ops tun_netdev_ops = { + .ndo_uninit = tun_net_uninit, .ndo_open = tun_net_open, .ndo_stop = tun_net_close, .ndo_start_xmit = tun_net_xmit, @@ -374,6 +411,7 @@ static const struct net_device_ops tun_netdev_ops = { }; static const struct net_device_ops tap_netdev_ops = { + .ndo_uninit = tun_net_uninit, .ndo_open = tun_net_open, .ndo_stop = tun_net_close, .ndo_start_xmit = tun_net_xmit, @@ -434,6 +472,9 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait) if (!skb_queue_empty(&tun->readq)) mask |= POLLIN | POLLRDNORM; + if (tun->dev->reg_state != NETREG_REGISTERED) + mask = POLLERR; + tun_put(tun); return mask; } @@ -734,6 +775,10 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, ret = -ERESTARTSYS; break; } + if (tun->dev->reg_state != NETREG_REGISTERED) { + ret = -EIO; + break; + } /* Nothing to read, let's sleep */ schedule(); @@ -1135,6 +1180,7 @@ static int tun_chr_open(struct inode *inode, struct file * file) tfile = kmalloc(sizeof(*tfile), GFP_KERNEL); if (!tfile) return -ENOMEM; + atomic_set(&tfile->count, 0); tfile->tun = NULL; tfile->net = get_net(current->nsproxy->net_ns); init_waitqueue_head(&tfile->read_wait); -- GitLab From aec191aa2a04b082238156dc9690fff8ce95dd6b Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 20 Jan 2009 11:08:46 +0000 Subject: [PATCH 0377/4982] tun: There is no longer any need to deny changing network namespaces With the awkward case between free_netdev and dev_chr_close fixed there is no longer any need to limit tun and tap devices to the network namespace they were created in. So remove the NETIF_F_NETNS_LOCAL flag on the network device. Signed-off-by: Eric W. Biederman Signed-off-by: David S. Miller --- drivers/net/tun.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 51dba6192ba..97b050015f5 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -810,7 +810,6 @@ static void tun_setup(struct net_device *dev) dev->ethtool_ops = &tun_ethtool_ops; dev->destructor = free_netdev; - dev->features |= NETIF_F_NETNS_LOCAL; } static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) -- GitLab From f019a7a594d951f085eb3878c3d825556d447efe Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 21 Jan 2009 16:02:16 -0800 Subject: [PATCH 0378/4982] tun: Implement ip link del tunXXX This greatly simplifies testing to verify I have fixed the problems with a tun device disappearing when the tun file descriptor is still held open. Further it allows removal network namespace operations for the tun driver. Reducing the network namespace handling in the driver to the minimum. i.e. When we are creating a tun device. Signed-off-by: Eric W. Biederman Signed-off-by: David S. Miller --- drivers/net/tun.c | 56 +++++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 97b050015f5..e9bcbdfe015 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -63,6 +63,7 @@ #include #include #include +#include #include #include @@ -812,6 +813,22 @@ static void tun_setup(struct net_device *dev) dev->destructor = free_netdev; } +/* Trivial set of netlink ops to allow deleting tun or tap + * device with netlink. + */ +static int tun_validate(struct nlattr *tb[], struct nlattr *data[]) +{ + return -EINVAL; +} + +static struct rtnl_link_ops tun_link_ops __read_mostly = { + .kind = DRV_NAME, + .priv_size = sizeof(struct tun_struct), + .setup = tun_setup, + .validate = tun_validate, +}; + + static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) { struct tun_struct *tun; @@ -861,6 +878,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) return -ENOMEM; dev_net_set(dev, net); + dev->rtnl_link_ops = &tun_link_ops; tun = netdev_priv(dev); tun->dev = dev; @@ -1317,29 +1335,6 @@ static const struct ethtool_ops tun_ethtool_ops = { .set_rx_csum = tun_set_rx_csum }; -static int tun_init_net(struct net *net) -{ - return 0; -} - -static void tun_exit_net(struct net *net) -{ - struct net_device *dev, *next; - - rtnl_lock(); - for_each_netdev_safe(net, dev, next) { - if (dev->ethtool_ops != &tun_ethtool_ops) - continue; - DBG(KERN_INFO "%s cleaned up\n", dev->name); - unregister_netdevice(dev); - } - rtnl_unlock(); -} - -static struct pernet_operations tun_net_ops = { - .init = tun_init_net, - .exit = tun_exit_net, -}; static int __init tun_init(void) { @@ -1348,10 +1343,10 @@ static int __init tun_init(void) printk(KERN_INFO "tun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION); printk(KERN_INFO "tun: %s\n", DRV_COPYRIGHT); - ret = register_pernet_device(&tun_net_ops); + ret = rtnl_link_register(&tun_link_ops); if (ret) { - printk(KERN_ERR "tun: Can't register pernet ops\n"); - goto err_pernet; + printk(KERN_ERR "tun: Can't register link_ops\n"); + goto err_linkops; } ret = misc_register(&tun_miscdev); @@ -1359,18 +1354,17 @@ static int __init tun_init(void) printk(KERN_ERR "tun: Can't register misc device %d\n", TUN_MINOR); goto err_misc; } - return 0; - + return 0; err_misc: - unregister_pernet_device(&tun_net_ops); -err_pernet: + rtnl_link_unregister(&tun_link_ops); +err_linkops: return ret; } static void tun_cleanup(void) { misc_deregister(&tun_miscdev); - unregister_pernet_device(&tun_net_ops); + rtnl_link_unregister(&tun_link_ops); } module_init(tun_init); -- GitLab From 623d3f0c619f3576dae69709ca8aa93ac76d8c63 Mon Sep 17 00:00:00 2001 From: David Miller Date: Wed, 21 Jan 2009 17:24:51 -0800 Subject: [PATCH 0379/4982] sparc64: Fix build by including linux/irq.h into time_64.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changeset d7e51e66899f95dabc89b4d4c6674a6e50fa37fc ("sparseirq: make some func to be used with genirq") broke the build on sparc64: arch/sparc/kernel/time_64.c: In function ‘timer_interrupt’: arch/sparc/kernel/time_64.c:732: error: implicit declaration of function ‘kstat_incr_irqs_this_cpu’ make[1]: *** [arch/sparc/kernel/time_64.o] Error 1 Signed-off-by: David S. Miller Signed-off-by: Ingo Molnar --- arch/sparc/kernel/time_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index 54405d36214..a55279939b6 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c @@ -36,10 +36,10 @@ #include #include #include +#include #include #include -#include #include #include #include -- GitLab From e81838d2555e77c893f720c25bfb0c0e5782ef57 Mon Sep 17 00:00:00 2001 From: David Miller Date: Wed, 21 Jan 2009 17:15:53 -0800 Subject: [PATCH 0380/4982] sparc64: Fix build by using kstat_irqs_cpu() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changeset d7e51e66899f95dabc89b4d4c6674a6e50fa37fc ("sparseirq: make some func to be used with genirq") broke the build on sparc64: arch/sparc/kernel/irq_64.c: In function ‘show_interrupts’: arch/sparc/kernel/irq_64.c:188: error: ‘struct kernel_stat’ has no member named ‘irqs’ make[1]: *** [arch/sparc/kernel/irq_64.o] Error 1 Fix by using the kstat_irqs_cpu() interface. Signed-off-by: David S. Miller Signed-off-by: Ingo Molnar --- arch/sparc/kernel/irq_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c index cab8e028687..2e98bef5078 100644 --- a/arch/sparc/kernel/irq_64.c +++ b/arch/sparc/kernel/irq_64.c @@ -185,7 +185,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_printf(p, "%10u ", kstat_irqs(i)); #else for_each_online_cpu(j) - seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); + seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); #endif seq_printf(p, " %9s", irq_desc[i].chip->typename); seq_printf(p, " %s", action->name); -- GitLab From d52a61c04c6c0814ca270a088feedb126436598e Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 22 Jan 2009 00:38:56 -0800 Subject: [PATCH 0381/4982] irq: clean up irq stat methods David Miller suggested, related to a kstat_irqs related build breakage: > Either linux/kernel_stat.h provides the kstat_incr_irqs_this_cpu > interface or linux/irq.h does, not both. So move them to kernel_stat.h. Signed-off-by: Ingo Molnar --- include/linux/irq.h | 6 ------ include/linux/kernel_stat.h | 9 ++++++--- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/include/linux/irq.h b/include/linux/irq.h index e9a878978c8..48901e9a33b 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -202,12 +202,6 @@ extern struct irq_desc irq_desc[NR_IRQS]; extern struct irq_desc *move_irq_desc(struct irq_desc *old_desc, int cpu); #endif /* CONFIG_SPARSE_IRQ */ -#define kstat_irqs_this_cpu(DESC) \ - ((DESC)->kstat_irqs[smp_processor_id()]) -#define kstat_incr_irqs_this_cpu(irqno, DESC) \ - ((DESC)->kstat_irqs[smp_processor_id()]++) - - extern struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu); static inline struct irq_desc * diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h index a3431b164be..0c8b89f28a9 100644 --- a/include/linux/kernel_stat.h +++ b/include/linux/kernel_stat.h @@ -52,16 +52,19 @@ static inline void kstat_incr_irqs_this_cpu(unsigned int irq, { kstat_this_cpu.irqs[irq]++; } -#endif - -#ifndef CONFIG_GENERIC_HARDIRQS static inline unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) { return kstat_cpu(cpu).irqs[irq]; } #else +#include extern unsigned int kstat_irqs_cpu(unsigned int irq, int cpu); +#define kstat_irqs_this_cpu(DESC) \ + ((DESC)->kstat_irqs[smp_processor_id()]) +#define kstat_incr_irqs_this_cpu(irqno, DESC) \ + ((DESC)->kstat_irqs[smp_processor_id()]++) + #endif /* -- GitLab From d639bab8da86d330493487e8c0fea8ca31f53427 Mon Sep 17 00:00:00 2001 From: "venkatesh.pallipadi@intel.com" Date: Fri, 9 Jan 2009 16:13:13 -0800 Subject: [PATCH 0382/4982] x86 PAT: ioremap_wc should take resource_size_t parameter Impact: fix/extend ioremap_wc() beyond 4GB aperture on 32-bit ioremap_wc() was taking in unsigned long parameter, where as it should take 64-bit resource_size_t parameter like other ioremap variants. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/include/asm/io.h | 2 +- arch/x86/mm/ioremap.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index 05cfed4485f..bdbb4b96160 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h @@ -91,7 +91,7 @@ extern void unxlate_dev_mem_ptr(unsigned long phys, void *addr); extern int ioremap_change_attr(unsigned long vaddr, unsigned long size, unsigned long prot_val); -extern void __iomem *ioremap_wc(unsigned long offset, unsigned long size); +extern void __iomem *ioremap_wc(resource_size_t offset, unsigned long size); /* * early_ioremap() and early_iounmap() are for temporary early boot-time diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index bd85d42819e..2ddb1e79a19 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -367,7 +367,7 @@ EXPORT_SYMBOL(ioremap_nocache); * * Must be freed with iounmap. */ -void __iomem *ioremap_wc(unsigned long phys_addr, unsigned long size) +void __iomem *ioremap_wc(resource_size_t phys_addr, unsigned long size) { if (pat_enabled) return __ioremap_caller(phys_addr, size, _PAGE_CACHE_WC, -- GitLab From 8ce8419829998c91b33200894a0db5e1441d6952 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 22 Jan 2009 16:59:20 +0100 Subject: [PATCH 0383/4982] ALSA: hda - Avoid to set the pin control again if already set Check the present pin control bit and avoid the write if it's already set in patch_sigmatel.c. This will reduce the number of verb execs at jack plugging. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 0fa6c593d1d..11634a4478e 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -4126,7 +4126,9 @@ static void stac92xx_free(struct hda_codec *codec) static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, unsigned int flag) { - unsigned int pin_ctl = snd_hda_codec_read(codec, nid, + unsigned int old_ctl, pin_ctl; + + pin_ctl = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); if (pin_ctl & AC_PINCTL_IN_EN) { @@ -4140,14 +4142,17 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, return; } + old_ctl = pin_ctl; /* if setting pin direction bits, clear the current direction bits first */ if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)) pin_ctl &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); - snd_hda_codec_write_cache(codec, nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - pin_ctl | flag); + pin_ctl |= flag; + if (old_ctl != pin_ctl) + snd_hda_codec_write_cache(codec, nid, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, + pin_ctl); } static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, @@ -4155,9 +4160,10 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, { unsigned int pin_ctl = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); - snd_hda_codec_write_cache(codec, nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - pin_ctl & ~flag); + if (pin_ctl & flag) + snd_hda_codec_write_cache(codec, nid, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, + pin_ctl & ~flag); } static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid) -- GitLab From d9a4268ee92ba1a2355c892a3add1fa66856b510 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 22 Jan 2009 17:40:18 +0100 Subject: [PATCH 0384/4982] ALSA: hda - Add quirk for Gateway %1616 laptop Gateway T1616 laptop needs EAPD always on while the current STAC9205 code turns off per HP plug. Added a new model "eapd" to keep it on. Reference: Novell bnc#467597 https://bugzilla.novell.com/show_bug.cgi?id=467597 Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 1 + sound/pci/hda/patch_sigmatel.c | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 75914bcdce7..ef6b22e2541 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -285,6 +285,7 @@ STAC9205/9254 dell-m42 Dell (unknown) dell-m43 Dell Precision dell-m44 Dell Inspiron + eapd Keep EAPD on (e.g. Gateway T1616) STAC9220/9221 ============= diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 3f85731055c..ed2fa431b03 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -66,6 +66,7 @@ enum { STAC_9205_DELL_M42, STAC_9205_DELL_M43, STAC_9205_DELL_M44, + STAC_9205_EAPD, STAC_9205_MODELS }; @@ -2240,6 +2241,7 @@ static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = { [STAC_9205_DELL_M42] = dell_9205_m42_pin_configs, [STAC_9205_DELL_M43] = dell_9205_m43_pin_configs, [STAC_9205_DELL_M44] = dell_9205_m44_pin_configs, + [STAC_9205_EAPD] = NULL, }; static const char *stac9205_models[STAC_9205_MODELS] = { @@ -2247,12 +2249,14 @@ static const char *stac9205_models[STAC_9205_MODELS] = { [STAC_9205_DELL_M42] = "dell-m42", [STAC_9205_DELL_M43] = "dell-m43", [STAC_9205_DELL_M44] = "dell-m44", + [STAC_9205_EAPD] = "eapd", }; static struct snd_pci_quirk stac9205_cfg_tbl[] = { /* SigmaTel reference board */ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_9205_REF), + /* Dell */ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1, "unknown Dell", STAC_9205_DELL_M42), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2, @@ -2283,6 +2287,8 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = { "Dell Inspiron", STAC_9205_DELL_M44), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228, "Dell Vostro 1500", STAC_9205_DELL_M42), + /* Gateway */ + SND_PCI_QUIRK(0x107b, 0x0565, "Gateway T1616", STAC_9205_EAPD), {} /* terminator */ }; @@ -5320,7 +5326,9 @@ static int patch_stac9205(struct hda_codec *codec) spec->aloopback_mask = 0x40; spec->aloopback_shift = 0; - spec->eapd_switch = 1; + /* Turn on/off EAPD per HP plugging */ + if (spec->board_config != STAC_9205_EAPD) + spec->eapd_switch = 1; spec->multiout.dac_nids = spec->dac_nids; switch (spec->board_config){ -- GitLab From 4fe1d58bf56f69de68868630d222322a6b45bb55 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 22 Jan 2009 13:49:44 -0800 Subject: [PATCH 0385/4982] sctp/ipv6.c: use ipv6_addr_copy Signed-off-by: Joe Perches Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/ipv6.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index ceaa4aa066e..78622756669 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -97,8 +97,7 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev, if (addr) { addr->a.v6.sin6_family = AF_INET6; addr->a.v6.sin6_port = 0; - memcpy(&addr->a.v6.sin6_addr, &ifa->addr, - sizeof(struct in6_addr)); + ipv6_addr_copy(&addr->a.v6.sin6_addr, &ifa->addr); addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex; addr->valid = 1; spin_lock_bh(&sctp_local_addr_lock); -- GitLab From e35fac80ed0bb878f652cc0f70ca268656d275f7 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Thu, 22 Jan 2009 13:52:26 -0800 Subject: [PATCH 0386/4982] net: pppoe - get rid of DECLARE_MAC_BUF While was playing with PPP namespaces I occasionally brought back DECLARE_MAC_BUF which is not needed (we have %pM here). Fix it. Signed-off-by: Cyrill Gorcunov Signed-off-by: David S. Miller --- drivers/net/pppoe.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 39f3e21647e..798b8cf5f9a 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -1004,7 +1004,6 @@ static int pppoe_seq_show(struct seq_file *seq, void *v) { struct pppox_sock *po; char *dev_name; - DECLARE_MAC_BUF(mac); if (v == SEQ_START_TOKEN) { seq_puts(seq, "Id Address Device\n"); -- GitLab From 70a269e6c9c9b38b1a37dce068c59e9a912f8578 Mon Sep 17 00:00:00 2001 From: Benjamin Thery Date: Thu, 22 Jan 2009 04:56:15 +0000 Subject: [PATCH 0387/4982] netns: ipmr: allocate mroute_socket per-namespace. Preliminary work to make IPv4 multicast routing netns-aware. Make IPv4 multicast routing mroute_socket per-namespace, moves it into struct netns_ipv4. At the moment, mroute_socket is only referenced in init_net. Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 4 ++++ net/ipv4/ipmr.c | 28 +++++++++++++--------------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 977f482d97a..4f00722c747 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -54,5 +54,9 @@ struct netns_ipv4 { struct timer_list rt_secret_timer; atomic_t rt_genid; + +#ifdef CONFIG_IP_MROUTE + struct sock *mroute_sk; +#endif }; #endif diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 14666449dc1..ac324b702e8 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -67,9 +67,6 @@ #define CONFIG_IP_PIMSM 1 #endif -static struct sock *mroute_socket; - - /* Big lock, protecting vif table, mrt cache and mroute socket state. Note that the changes are semaphored via rtnl_lock. */ @@ -658,7 +655,7 @@ static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert) skb->transport_header = skb->network_header; } - if (mroute_socket == NULL) { + if (init_net.ipv4.mroute_sk == NULL) { kfree_skb(skb); return -EINVAL; } @@ -666,7 +663,8 @@ static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert) /* * Deliver to mrouted */ - if ((ret = sock_queue_rcv_skb(mroute_socket, skb))<0) { + ret = sock_queue_rcv_skb(init_net.ipv4.mroute_sk, skb); + if (ret < 0) { if (net_ratelimit()) printk(KERN_WARNING "mroute: pending queue full, dropping entries.\n"); kfree_skb(skb); @@ -896,11 +894,11 @@ static void mroute_clean_tables(struct sock *sk) static void mrtsock_destruct(struct sock *sk) { rtnl_lock(); - if (sk == mroute_socket) { + if (sk == init_net.ipv4.mroute_sk) { IPV4_DEVCONF_ALL(sock_net(sk), MC_FORWARDING)--; write_lock_bh(&mrt_lock); - mroute_socket = NULL; + init_net.ipv4.mroute_sk = NULL; write_unlock_bh(&mrt_lock); mroute_clean_tables(sk); @@ -922,7 +920,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int struct mfcctl mfc; if (optname != MRT_INIT) { - if (sk != mroute_socket && !capable(CAP_NET_ADMIN)) + if (sk != init_net.ipv4.mroute_sk && !capable(CAP_NET_ADMIN)) return -EACCES; } @@ -935,7 +933,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int return -ENOPROTOOPT; rtnl_lock(); - if (mroute_socket) { + if (init_net.ipv4.mroute_sk) { rtnl_unlock(); return -EADDRINUSE; } @@ -943,7 +941,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int ret = ip_ra_control(sk, 1, mrtsock_destruct); if (ret == 0) { write_lock_bh(&mrt_lock); - mroute_socket = sk; + init_net.ipv4.mroute_sk = sk; write_unlock_bh(&mrt_lock); IPV4_DEVCONF_ALL(sock_net(sk), MC_FORWARDING)++; @@ -951,7 +949,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int rtnl_unlock(); return ret; case MRT_DONE: - if (sk != mroute_socket) + if (sk != init_net.ipv4.mroute_sk) return -EACCES; return ip_ra_control(sk, 0, NULL); case MRT_ADD_VIF: @@ -964,7 +962,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int return -ENFILE; rtnl_lock(); if (optname == MRT_ADD_VIF) { - ret = vif_add(&vif, sk==mroute_socket); + ret = vif_add(&vif, sk == init_net.ipv4.mroute_sk); } else { ret = vif_delete(vif.vifc_vifi, 0); } @@ -985,7 +983,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int if (optname == MRT_DEL_MFC) ret = ipmr_mfc_delete(&mfc); else - ret = ipmr_mfc_add(&mfc, sk==mroute_socket); + ret = ipmr_mfc_add(&mfc, sk == init_net.ipv4.mroute_sk); rtnl_unlock(); return ret; /* @@ -1425,9 +1423,9 @@ int ip_mr_input(struct sk_buff *skb) that we can forward NO IGMP messages. */ read_lock(&mrt_lock); - if (mroute_socket) { + if (init_net.ipv4.mroute_sk) { nf_reset(skb); - raw_rcv(mroute_socket, skb); + raw_rcv(init_net.ipv4.mroute_sk, skb); read_unlock(&mrt_lock); return 0; } -- GitLab From cf958ae377ee2545ae70cf48d38e7eb4308c27ea Mon Sep 17 00:00:00 2001 From: Benjamin Thery Date: Thu, 22 Jan 2009 04:56:16 +0000 Subject: [PATCH 0388/4982] netns: ipmr: dynamically allocate vif_table Preliminary work to make IPv6 multicast routing netns-aware. Dynamically allocate interface table vif_table and move it to struct netns_ipv4, and update MIF_EXISTS() macro. At the moment, vif_table is only referenced in init_net. Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 2 + net/ipv4/ipmr.c | 109 ++++++++++++++++++++++++--------------- 2 files changed, 70 insertions(+), 41 deletions(-) diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 4f00722c747..edbcccbbc31 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -57,6 +57,8 @@ struct netns_ipv4 { #ifdef CONFIG_IP_MROUTE struct sock *mroute_sk; + struct vif_device *vif_table; + int maxvif; #endif }; #endif diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index ac324b702e8..75a5f79cc22 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -77,10 +77,7 @@ static DEFINE_RWLOCK(mrt_lock); * Multicast router control variables */ -static struct vif_device vif_table[MAXVIFS]; /* Devices */ -static int maxvif; - -#define VIF_EXISTS(idx) (vif_table[idx].dev != NULL) +#define VIF_EXISTS(_net, _idx) ((_net)->ipv4.vif_table[_idx].dev != NULL) static int mroute_do_assert; /* Set in PIM assert */ static int mroute_do_pim; @@ -286,10 +283,10 @@ static int vif_delete(int vifi, int notify) struct net_device *dev; struct in_device *in_dev; - if (vifi < 0 || vifi >= maxvif) + if (vifi < 0 || vifi >= init_net.ipv4.maxvif) return -EADDRNOTAVAIL; - v = &vif_table[vifi]; + v = &init_net.ipv4.vif_table[vifi]; write_lock_bh(&mrt_lock); dev = v->dev; @@ -305,13 +302,13 @@ static int vif_delete(int vifi, int notify) reg_vif_num = -1; #endif - if (vifi+1 == maxvif) { + if (vifi+1 == init_net.ipv4.maxvif) { int tmp; for (tmp=vifi-1; tmp>=0; tmp--) { - if (VIF_EXISTS(tmp)) + if (VIF_EXISTS(&init_net, tmp)) break; } - maxvif = tmp+1; + init_net.ipv4.maxvif = tmp+1; } write_unlock_bh(&mrt_lock); @@ -411,8 +408,9 @@ static void ipmr_update_thresholds(struct mfc_cache *cache, unsigned char *ttls) cache->mfc_un.res.maxvif = 0; memset(cache->mfc_un.res.ttls, 255, MAXVIFS); - for (vifi=0; vifimfc_un.res.ttls[vifi] = ttls[vifi]; if (cache->mfc_un.res.minvif > vifi) cache->mfc_un.res.minvif = vifi; @@ -425,13 +423,13 @@ static void ipmr_update_thresholds(struct mfc_cache *cache, unsigned char *ttls) static int vif_add(struct vifctl *vifc, int mrtsock) { int vifi = vifc->vifc_vifi; - struct vif_device *v = &vif_table[vifi]; + struct vif_device *v = &init_net.ipv4.vif_table[vifi]; struct net_device *dev; struct in_device *in_dev; int err; /* Is vif busy ? */ - if (VIF_EXISTS(vifi)) + if (VIF_EXISTS(&init_net, vifi)) return -EADDRINUSE; switch (vifc->vifc_flags) { @@ -509,8 +507,8 @@ static int vif_add(struct vifctl *vifc, int mrtsock) if (v->flags&VIFF_REGISTER) reg_vif_num = vifi; #endif - if (vifi+1 > maxvif) - maxvif = vifi+1; + if (vifi+1 > init_net.ipv4.maxvif) + init_net.ipv4.maxvif = vifi+1; write_unlock_bh(&mrt_lock); return 0; } @@ -849,8 +847,8 @@ static void mroute_clean_tables(struct sock *sk) /* * Shut down all active vif entries */ - for (i=0; i= maxvif) + if (vr.vifi >= init_net.ipv4.maxvif) return -EINVAL; read_lock(&mrt_lock); - vif=&vif_table[vr.vifi]; - if (VIF_EXISTS(vr.vifi)) { + vif = &init_net.ipv4.vif_table[vr.vifi]; + if (VIF_EXISTS(&init_net, vr.vifi)) { vr.icount = vif->pkt_in; vr.ocount = vif->pkt_out; vr.ibytes = vif->bytes_in; @@ -1140,8 +1138,8 @@ static int ipmr_device_event(struct notifier_block *this, unsigned long event, v if (event != NETDEV_UNREGISTER) return NOTIFY_DONE; - v=&vif_table[0]; - for (ct=0; ctdev == dev) vif_delete(ct, 1); } @@ -1204,7 +1202,7 @@ static inline int ipmr_forward_finish(struct sk_buff *skb) static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) { const struct iphdr *iph = ip_hdr(skb); - struct vif_device *vif = &vif_table[vifi]; + struct vif_device *vif = &init_net.ipv4.vif_table[vifi]; struct net_device *dev; struct rtable *rt; int encap = 0; @@ -1305,8 +1303,8 @@ out_free: static int ipmr_find_vif(struct net_device *dev) { int ct; - for (ct=maxvif-1; ct>=0; ct--) { - if (vif_table[ct].dev == dev) + for (ct = init_net.ipv4.maxvif-1; ct >= 0; ct--) { + if (init_net.ipv4.vif_table[ct].dev == dev) break; } return ct; @@ -1326,7 +1324,7 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local /* * Wrong interface: drop packet and (maybe) send PIM assert. */ - if (vif_table[vif].dev != skb->dev) { + if (init_net.ipv4.vif_table[vif].dev != skb->dev) { int true_vifi; if (skb->rtable->fl.iif == 0) { @@ -1362,8 +1360,8 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local goto dont_forward; } - vif_table[vif].pkt_in++; - vif_table[vif].bytes_in += skb->len; + init_net.ipv4.vif_table[vif].pkt_in++; + init_net.ipv4.vif_table[vif].bytes_in += skb->len; /* * Forward the frame @@ -1500,7 +1498,7 @@ static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen) read_lock(&mrt_lock); if (reg_vif_num >= 0) - reg_dev = vif_table[reg_vif_num].dev; + reg_dev = init_net.ipv4.vif_table[reg_vif_num].dev; if (reg_dev) dev_hold(reg_dev); read_unlock(&mrt_lock); @@ -1581,7 +1579,7 @@ ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm) { int ct; struct rtnexthop *nhp; - struct net_device *dev = vif_table[c->mfc_parent].dev; + struct net_device *dev = init_net.ipv4.vif_table[c->mfc_parent].dev; u8 *b = skb_tail_pointer(skb); struct rtattr *mp_head; @@ -1597,7 +1595,7 @@ ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm) nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp))); nhp->rtnh_flags = 0; nhp->rtnh_hops = c->mfc_un.res.ttls[ct]; - nhp->rtnh_ifindex = vif_table[ct].dev->ifindex; + nhp->rtnh_ifindex = init_net.ipv4.vif_table[ct].dev->ifindex; nhp->rtnh_len = sizeof(*nhp); } } @@ -1672,11 +1670,11 @@ struct ipmr_vif_iter { static struct vif_device *ipmr_vif_seq_idx(struct ipmr_vif_iter *iter, loff_t pos) { - for (iter->ct = 0; iter->ct < maxvif; ++iter->ct) { - if (!VIF_EXISTS(iter->ct)) + for (iter->ct = 0; iter->ct < init_net.ipv4.maxvif; ++iter->ct) { + if (!VIF_EXISTS(&init_net, iter->ct)) continue; if (pos-- == 0) - return &vif_table[iter->ct]; + return &init_net.ipv4.vif_table[iter->ct]; } return NULL; } @@ -1697,10 +1695,10 @@ static void *ipmr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos) if (v == SEQ_START_TOKEN) return ipmr_vif_seq_idx(iter, 0); - while (++iter->ct < maxvif) { - if (!VIF_EXISTS(iter->ct)) + while (++iter->ct < init_net.ipv4.maxvif) { + if (!VIF_EXISTS(&init_net, iter->ct)) continue; - return &vif_table[iter->ct]; + return &init_net.ipv4.vif_table[iter->ct]; } return NULL; } @@ -1722,7 +1720,7 @@ static int ipmr_vif_seq_show(struct seq_file *seq, void *v) seq_printf(seq, "%2Zd %-10s %8ld %7ld %8ld %7ld %05X %08X %08X\n", - vif - vif_table, + vif - init_net.ipv4.vif_table, name, vif->bytes_in, vif->pkt_in, vif->bytes_out, vif->pkt_out, vif->flags, vif->local, vif->remote); @@ -1864,9 +1862,9 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) mfc->mfc_un.res.wrong_if); for (n = mfc->mfc_un.res.minvif; n < mfc->mfc_un.res.maxvif; n++ ) { - if (VIF_EXISTS(n) - && mfc->mfc_un.res.ttls[n] < 255) - seq_printf(seq, + if (VIF_EXISTS(&init_net, n) && + mfc->mfc_un.res.ttls[n] < 255) + seq_printf(seq, " %2d:%-3d", n, mfc->mfc_un.res.ttls[n]); } @@ -1913,6 +1911,29 @@ static struct net_protocol pim_protocol = { /* * Setup for IP multicast routing */ +static int __net_init ipmr_net_init(struct net *net) +{ + int err = 0; + + net->ipv4.vif_table = kcalloc(MAXVIFS, sizeof(struct vif_device), + GFP_KERNEL); + if (!net->ipv4.vif_table) { + err = -ENOMEM; + goto fail; + } +fail: + return err; +} + +static void __net_exit ipmr_net_exit(struct net *net) +{ + kfree(net->ipv4.vif_table); +} + +static struct pernet_operations ipmr_net_ops = { + .init = ipmr_net_init, + .exit = ipmr_net_exit, +}; int __init ip_mr_init(void) { @@ -1925,6 +1946,10 @@ int __init ip_mr_init(void) if (!mrt_cachep) return -ENOMEM; + err = register_pernet_subsys(&ipmr_net_ops); + if (err) + goto reg_pernet_fail; + setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0); err = register_netdevice_notifier(&ip_mr_notifier); if (err) @@ -1945,6 +1970,8 @@ proc_vif_fail: #endif reg_notif_fail: del_timer(&ipmr_expire_timer); + unregister_pernet_subsys(&ipmr_net_ops); +reg_pernet_fail: kmem_cache_destroy(mrt_cachep); return err; } -- GitLab From 5c0a66f5f3c9c59e2c341400048e2cff768e67a9 Mon Sep 17 00:00:00 2001 From: Benjamin Thery Date: Thu, 22 Jan 2009 04:56:17 +0000 Subject: [PATCH 0389/4982] netns: ipmr: store netns in struct mfc_cache This patch stores into struct mfc_cache the network namespace each mfc_cache belongs to. The new member is mfc_net. mfc_net is assigned at cache allocation and doesn't change during the rest of the cache entry life. A new net parameter is added to ipmr_cache_alloc/ipmr_cache_alloc_unres. This will help to retrieve the current netns around the IPv4 multicast routing code. At the moment, all mfc_cache are allocated in init_net. Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- include/linux/mroute.h | 15 +++++++++++++++ net/ipv4/ipmr.c | 26 +++++++++++++++++--------- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/include/linux/mroute.h b/include/linux/mroute.h index 8a455694d68..beaf3aae8aa 100644 --- a/include/linux/mroute.h +++ b/include/linux/mroute.h @@ -193,6 +193,9 @@ struct vif_device struct mfc_cache { struct mfc_cache *next; /* Next entry on cache line */ +#ifdef CONFIG_NET_NS + struct net *mfc_net; +#endif __be32 mfc_mcastgrp; /* Group the entry belongs to */ __be32 mfc_origin; /* Source of packet */ vifi_t mfc_parent; /* Source interface */ @@ -215,6 +218,18 @@ struct mfc_cache } mfc_un; }; +static inline +struct net *mfc_net(const struct mfc_cache *mfc) +{ + return read_pnet(&mfc->mfc_net); +} + +static inline +void mfc_net_set(struct mfc_cache *mfc, struct net *net) +{ + write_pnet(&mfc->mfc_net, hold_net(net)); +} + #define MFC_STATIC 1 #define MFC_NOTIFY 2 diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 75a5f79cc22..8428a0fb5c1 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -327,6 +327,12 @@ static int vif_delete(int vifi, int notify) return 0; } +static inline void ipmr_cache_free(struct mfc_cache *c) +{ + release_net(mfc_net(c)); + kmem_cache_free(mrt_cachep, c); +} + /* Destroy an unresolved cache entry, killing queued skbs and reporting error to netlink readers. */ @@ -353,7 +359,7 @@ static void ipmr_destroy_unres(struct mfc_cache *c) kfree_skb(skb); } - kmem_cache_free(mrt_cachep, c); + ipmr_cache_free(c); } @@ -528,22 +534,24 @@ static struct mfc_cache *ipmr_cache_find(__be32 origin, __be32 mcastgrp) /* * Allocate a multicast cache entry */ -static struct mfc_cache *ipmr_cache_alloc(void) +static struct mfc_cache *ipmr_cache_alloc(struct net *net) { struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL); if (c == NULL) return NULL; c->mfc_un.res.minvif = MAXVIFS; + mfc_net_set(c, net); return c; } -static struct mfc_cache *ipmr_cache_alloc_unres(void) +static struct mfc_cache *ipmr_cache_alloc_unres(struct net *net) { struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC); if (c == NULL) return NULL; skb_queue_head_init(&c->mfc_un.unres.unresolved); c->mfc_un.unres.expires = jiffies + 10*HZ; + mfc_net_set(c, net); return c; } @@ -695,7 +703,7 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) */ if (atomic_read(&cache_resolve_queue_len) >= 10 || - (c=ipmr_cache_alloc_unres())==NULL) { + (c = ipmr_cache_alloc_unres(&init_net)) == NULL) { spin_unlock_bh(&mfc_unres_lock); kfree_skb(skb); @@ -718,7 +726,7 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) */ spin_unlock_bh(&mfc_unres_lock); - kmem_cache_free(mrt_cachep, c); + ipmr_cache_free(c); kfree_skb(skb); return err; } @@ -763,7 +771,7 @@ static int ipmr_mfc_delete(struct mfcctl *mfc) *cp = c->next; write_unlock_bh(&mrt_lock); - kmem_cache_free(mrt_cachep, c); + ipmr_cache_free(c); return 0; } } @@ -796,7 +804,7 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) if (!ipv4_is_multicast(mfc->mfcc_mcastgrp.s_addr)) return -EINVAL; - c = ipmr_cache_alloc(); + c = ipmr_cache_alloc(&init_net); if (c == NULL) return -ENOMEM; @@ -831,7 +839,7 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) if (uc) { ipmr_cache_resolve(uc, c); - kmem_cache_free(mrt_cachep, uc); + ipmr_cache_free(uc); } return 0; } @@ -868,7 +876,7 @@ static void mroute_clean_tables(struct sock *sk) *cp = c->next; write_unlock_bh(&mrt_lock); - kmem_cache_free(mrt_cachep, c); + ipmr_cache_free(c); } } -- GitLab From 2bb8b26c3ea8bde1943dc5cd4dda2dc9f48fb281 Mon Sep 17 00:00:00 2001 From: Benjamin Thery Date: Thu, 22 Jan 2009 04:56:18 +0000 Subject: [PATCH 0390/4982] netns: ipmr: dynamically allocate mfc_cache_array Preliminary work to make IPv4 multicast routing netns-aware. Dynamically allocate IPv4 multicast forwarding cache, mfc_cache_array, and move it to struct netns_ipv4. At the moment, mfc_cache_array is only referenced in init_net. Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 1 + net/ipv4/ipmr.c | 41 +++++++++++++++++++++++++++------------- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index edbcccbbc31..0b4285ac29d 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -57,6 +57,7 @@ struct netns_ipv4 { #ifdef CONFIG_IP_MROUTE struct sock *mroute_sk; + struct mfc_cache **mfc_cache_array; struct vif_device *vif_table; int maxvif; #endif diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 8428a0fb5c1..35b868dd3bf 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -82,8 +82,6 @@ static DEFINE_RWLOCK(mrt_lock); static int mroute_do_assert; /* Set in PIM assert */ static int mroute_do_pim; -static struct mfc_cache *mfc_cache_array[MFC_LINES]; /* Forwarding cache */ - static struct mfc_cache *mfc_unres_queue; /* Queue of unresolved entries */ static atomic_t cache_resolve_queue_len; /* Size of unresolved */ @@ -524,7 +522,7 @@ static struct mfc_cache *ipmr_cache_find(__be32 origin, __be32 mcastgrp) int line = MFC_HASH(mcastgrp, origin); struct mfc_cache *c; - for (c=mfc_cache_array[line]; c; c = c->next) { + for (c = init_net.ipv4.mfc_cache_array[line]; c; c = c->next) { if (c->mfc_origin==origin && c->mfc_mcastgrp==mcastgrp) break; } @@ -764,7 +762,8 @@ static int ipmr_mfc_delete(struct mfcctl *mfc) line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr); - for (cp=&mfc_cache_array[line]; (c=*cp) != NULL; cp = &c->next) { + for (cp = &init_net.ipv4.mfc_cache_array[line]; + (c = *cp) != NULL; cp = &c->next) { if (c->mfc_origin == mfc->mfcc_origin.s_addr && c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) { write_lock_bh(&mrt_lock); @@ -785,7 +784,8 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr); - for (cp=&mfc_cache_array[line]; (c=*cp) != NULL; cp = &c->next) { + for (cp = &init_net.ipv4.mfc_cache_array[line]; + (c = *cp) != NULL; cp = &c->next) { if (c->mfc_origin == mfc->mfcc_origin.s_addr && c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) break; @@ -816,8 +816,8 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) c->mfc_flags |= MFC_STATIC; write_lock_bh(&mrt_lock); - c->next = mfc_cache_array[line]; - mfc_cache_array[line] = c; + c->next = init_net.ipv4.mfc_cache_array[line]; + init_net.ipv4.mfc_cache_array[line] = c; write_unlock_bh(&mrt_lock); /* @@ -866,7 +866,7 @@ static void mroute_clean_tables(struct sock *sk) for (i=0; imfc_flags&MFC_STATIC) { cp = &c->next; @@ -1767,10 +1767,11 @@ static struct mfc_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos) { struct mfc_cache *mfc; - it->cache = mfc_cache_array; + it->cache = init_net.ipv4.mfc_cache_array; read_lock(&mrt_lock); for (it->ct = 0; it->ct < MFC_LINES; it->ct++) - for (mfc = mfc_cache_array[it->ct]; mfc; mfc = mfc->next) + for (mfc = init_net.ipv4.mfc_cache_array[it->ct]; + mfc; mfc = mfc->next) if (pos-- == 0) return mfc; read_unlock(&mrt_lock); @@ -1812,10 +1813,10 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) if (it->cache == &mfc_unres_queue) goto end_of_list; - BUG_ON(it->cache != mfc_cache_array); + BUG_ON(it->cache != init_net.ipv4.mfc_cache_array); while (++it->ct < MFC_LINES) { - mfc = mfc_cache_array[it->ct]; + mfc = init_net.ipv4.mfc_cache_array[it->ct]; if (mfc) return mfc; } @@ -1843,7 +1844,7 @@ static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v) if (it->cache == &mfc_unres_queue) spin_unlock_bh(&mfc_unres_lock); - else if (it->cache == mfc_cache_array) + else if (it->cache == init_net.ipv4.mfc_cache_array) read_unlock(&mrt_lock); } @@ -1929,12 +1930,26 @@ static int __net_init ipmr_net_init(struct net *net) err = -ENOMEM; goto fail; } + + /* Forwarding cache */ + net->ipv4.mfc_cache_array = kcalloc(MFC_LINES, + sizeof(struct mfc_cache *), + GFP_KERNEL); + if (!net->ipv4.mfc_cache_array) { + err = -ENOMEM; + goto fail_mfc_cache; + } + return 0; + +fail_mfc_cache: + kfree(net->ipv4.vif_table); fail: return err; } static void __net_exit ipmr_net_exit(struct net *net) { + kfree(net->ipv4.mfc_cache_array); kfree(net->ipv4.vif_table); } -- GitLab From 1e8fb3b6a4ac6c5e486298d88289038456957545 Mon Sep 17 00:00:00 2001 From: Benjamin Thery Date: Thu, 22 Jan 2009 04:56:19 +0000 Subject: [PATCH 0391/4982] netns: ipmr: declare counter cache_resolve_queue_len per-namespace Preliminary work to make IPv4 multicast routing netns-aware. Declare variable cache_resolve_queue_len per-namespace: move it into struct netns_ipv4. This variable counts the number of unresolved cache entries queued in the list mfc_unres_queue. This list is kept global to all netns as the number of entries per namespace is limited to 10 (hardcoded in routine ipmr_cache_unresolved). Entries belonging to different namespaces in mfc_unres_queue will be identified by matching the mfc_net member introduced previously in struct mfc_cache. Keeping this list global to all netns, also allows us to keep a single timer (ipmr_expire_timer) to handle their expiration. In some places cache_resolve_queue_len value was tested for arming or deleting the timer. These tests were equivalent to testing mfc_unres_queue value instead and are replaced in this patch. At the moment, cache_resolve_queue_len is only referenced in init_net. Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 1 + net/ipv4/ipmr.c | 39 +++++++++++++++++++++------------------ 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 0b4285ac29d..90b7cd20aa6 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -60,6 +60,7 @@ struct netns_ipv4 { struct mfc_cache **mfc_cache_array; struct vif_device *vif_table; int maxvif; + atomic_t cache_resolve_queue_len; #endif }; #endif diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 35b868dd3bf..feafd14eb7b 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -83,7 +83,6 @@ static int mroute_do_assert; /* Set in PIM assert */ static int mroute_do_pim; static struct mfc_cache *mfc_unres_queue; /* Queue of unresolved entries */ -static atomic_t cache_resolve_queue_len; /* Size of unresolved */ /* Special spinlock for queue of unresolved entries */ static DEFINE_SPINLOCK(mfc_unres_lock); @@ -340,7 +339,7 @@ static void ipmr_destroy_unres(struct mfc_cache *c) struct sk_buff *skb; struct nlmsgerr *e; - atomic_dec(&cache_resolve_queue_len); + atomic_dec(&init_net.ipv4.cache_resolve_queue_len); while ((skb = skb_dequeue(&c->mfc_un.unres.unresolved))) { if (ip_hdr(skb)->version == 0) { @@ -374,7 +373,7 @@ static void ipmr_expire_process(unsigned long dummy) return; } - if (atomic_read(&cache_resolve_queue_len) == 0) + if (mfc_unres_queue == NULL) goto out; now = jiffies; @@ -395,7 +394,7 @@ static void ipmr_expire_process(unsigned long dummy) ipmr_destroy_unres(c); } - if (atomic_read(&cache_resolve_queue_len)) + if (mfc_unres_queue != NULL) mod_timer(&ipmr_expire_timer, jiffies + expires); out: @@ -690,7 +689,8 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) spin_lock_bh(&mfc_unres_lock); for (c=mfc_unres_queue; c; c=c->next) { - if (c->mfc_mcastgrp == iph->daddr && + if (net_eq(mfc_net(c), &init_net) && + c->mfc_mcastgrp == iph->daddr && c->mfc_origin == iph->saddr) break; } @@ -700,7 +700,7 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) * Create a new entry if allowable */ - if (atomic_read(&cache_resolve_queue_len) >= 10 || + if (atomic_read(&init_net.ipv4.cache_resolve_queue_len) >= 10 || (c = ipmr_cache_alloc_unres(&init_net)) == NULL) { spin_unlock_bh(&mfc_unres_lock); @@ -729,7 +729,7 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) return err; } - atomic_inc(&cache_resolve_queue_len); + atomic_inc(&init_net.ipv4.cache_resolve_queue_len); c->next = mfc_unres_queue; mfc_unres_queue = c; @@ -827,14 +827,16 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) spin_lock_bh(&mfc_unres_lock); for (cp = &mfc_unres_queue; (uc=*cp) != NULL; cp = &uc->next) { - if (uc->mfc_origin == c->mfc_origin && + if (net_eq(mfc_net(uc), &init_net) && + uc->mfc_origin == c->mfc_origin && uc->mfc_mcastgrp == c->mfc_mcastgrp) { *cp = uc->next; - if (atomic_dec_and_test(&cache_resolve_queue_len)) - del_timer(&ipmr_expire_timer); + atomic_dec(&init_net.ipv4.cache_resolve_queue_len); break; } } + if (mfc_unres_queue == NULL) + del_timer(&ipmr_expire_timer); spin_unlock_bh(&mfc_unres_lock); if (uc) { @@ -880,18 +882,19 @@ static void mroute_clean_tables(struct sock *sk) } } - if (atomic_read(&cache_resolve_queue_len) != 0) { - struct mfc_cache *c; + if (atomic_read(&init_net.ipv4.cache_resolve_queue_len) != 0) { + struct mfc_cache *c, **cp; spin_lock_bh(&mfc_unres_lock); - while (mfc_unres_queue != NULL) { - c = mfc_unres_queue; - mfc_unres_queue = c->next; - spin_unlock_bh(&mfc_unres_lock); + cp = &mfc_unres_queue; + while ((c = *cp) != NULL) { + if (!net_eq(mfc_net(c), &init_net)) { + cp = &c->next; + continue; + } + *cp = c->next; ipmr_destroy_unres(c); - - spin_lock_bh(&mfc_unres_lock); } spin_unlock_bh(&mfc_unres_lock); } -- GitLab From 6f9374a9342e896c68df7cf7c0b039ab5cca994c Mon Sep 17 00:00:00 2001 From: Benjamin Thery Date: Thu, 22 Jan 2009 04:56:20 +0000 Subject: [PATCH 0392/4982] netns: ipmr: declare mroute_do_assert and mroute_do_pim per-namespace Preliminary work to make IPv4 multicast routing netns-aware. Declare IPv multicast routing variables 'mroute_do_assert' and 'mroute_do_pim' per-namespace in struct netns_ipv4. At the moment, these variables are only referenced in init_net. Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 2 ++ net/ipv4/ipmr.c | 24 +++++++++++------------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 90b7cd20aa6..8451722782b 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -61,6 +61,8 @@ struct netns_ipv4 { struct vif_device *vif_table; int maxvif; atomic_t cache_resolve_queue_len; + int mroute_do_assert; + int mroute_do_pim; #endif }; #endif diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index feafd14eb7b..d6a28acc068 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -79,9 +79,6 @@ static DEFINE_RWLOCK(mrt_lock); #define VIF_EXISTS(_net, _idx) ((_net)->ipv4.vif_table[_idx].dev != NULL) -static int mroute_do_assert; /* Set in PIM assert */ -static int mroute_do_pim; - static struct mfc_cache *mfc_unres_queue; /* Queue of unresolved entries */ /* Special spinlock for queue of unresolved entries */ @@ -1003,7 +1000,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int int v; if (get_user(v,(int __user *)optval)) return -EFAULT; - mroute_do_assert=(v)?1:0; + init_net.ipv4.mroute_do_assert = (v) ? 1 : 0; return 0; } #ifdef CONFIG_IP_PIMSM @@ -1017,11 +1014,11 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int rtnl_lock(); ret = 0; - if (v != mroute_do_pim) { - mroute_do_pim = v; - mroute_do_assert = v; + if (v != init_net.ipv4.mroute_do_pim) { + init_net.ipv4.mroute_do_pim = v; + init_net.ipv4.mroute_do_assert = v; #ifdef CONFIG_IP_PIMSM_V2 - if (mroute_do_pim) + if (init_net.ipv4.mroute_do_pim) ret = inet_add_protocol(&pim_protocol, IPPROTO_PIM); else @@ -1073,10 +1070,10 @@ int ip_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, int val = 0x0305; #ifdef CONFIG_IP_PIMSM else if (optname == MRT_PIM) - val = mroute_do_pim; + val = init_net.ipv4.mroute_do_pim; #endif else - val = mroute_do_assert; + val = init_net.ipv4.mroute_do_assert; if (copy_to_user(optval, &val, olr)) return -EFAULT; return 0; @@ -1356,13 +1353,14 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local cache->mfc_un.res.wrong_if++; true_vifi = ipmr_find_vif(skb->dev); - if (true_vifi >= 0 && mroute_do_assert && + if (true_vifi >= 0 && init_net.ipv4.mroute_do_assert && /* pimsm uses asserts, when switching from RPT to SPT, so that we cannot check that packet arrived on an oif. It is bad, but otherwise we would need to move pretty large chunk of pimd to kernel. Ough... --ANK */ - (mroute_do_pim || cache->mfc_un.res.ttls[true_vifi] < 255) && + (init_net.ipv4.mroute_do_pim || + cache->mfc_un.res.ttls[true_vifi] < 255) && time_after(jiffies, cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) { cache->mfc_un.res.last_assert = jiffies; @@ -1550,7 +1548,7 @@ int pim_rcv_v1(struct sk_buff * skb) pim = igmp_hdr(skb); - if (!mroute_do_pim || + if (!init_net.ipv4.mroute_do_pim || pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER) goto drop; -- GitLab From 6c5143dbcfe50ac722965dc7d096abbeeec8bb33 Mon Sep 17 00:00:00 2001 From: Benjamin Thery Date: Thu, 22 Jan 2009 04:56:21 +0000 Subject: [PATCH 0393/4982] netns: ipmr: declare reg_vif_num per-namespace Preliminary work to make IPv4 multicast routing netns-aware. Declare variable 'reg_vif_num' per-namespace, move into struct netns_ipv4. At the moment, this variable is only referenced in init_net. Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 3 +++ net/ipv4/ipmr.c | 22 ++++++++++++---------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 8451722782b..2eb3814d625 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -63,6 +63,9 @@ struct netns_ipv4 { atomic_t cache_resolve_queue_len; int mroute_do_assert; int mroute_do_pim; +#if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2) + int mroute_reg_vif_num; +#endif #endif }; #endif diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index d6a28acc068..346e67b50d6 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -197,14 +197,12 @@ failure: #ifdef CONFIG_IP_PIMSM -static int reg_vif_num = -1; - static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) { read_lock(&mrt_lock); dev->stats.tx_bytes += skb->len; dev->stats.tx_packets++; - ipmr_cache_report(skb, reg_vif_num, IGMPMSG_WHOLEPKT); + ipmr_cache_report(skb, init_net.ipv4.mroute_reg_vif_num, IGMPMSG_WHOLEPKT); read_unlock(&mrt_lock); kfree_skb(skb); return 0; @@ -292,8 +290,8 @@ static int vif_delete(int vifi, int notify) } #ifdef CONFIG_IP_PIMSM - if (vifi == reg_vif_num) - reg_vif_num = -1; + if (vifi == init_net.ipv4.mroute_reg_vif_num) + init_net.ipv4.mroute_reg_vif_num = -1; #endif if (vifi+1 == init_net.ipv4.maxvif) { @@ -439,7 +437,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock) * Special Purpose VIF in PIM * All the packets will be sent to the daemon */ - if (reg_vif_num >= 0) + if (init_net.ipv4.mroute_reg_vif_num >= 0) return -EADDRINUSE; dev = ipmr_reg_vif(); if (!dev) @@ -505,7 +503,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock) v->dev = dev; #ifdef CONFIG_IP_PIMSM if (v->flags&VIFF_REGISTER) - reg_vif_num = vifi; + init_net.ipv4.mroute_reg_vif_num = vifi; #endif if (vifi+1 > init_net.ipv4.maxvif) init_net.ipv4.maxvif = vifi+1; @@ -623,7 +621,7 @@ static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert) memcpy(msg, skb_network_header(pkt), sizeof(struct iphdr)); msg->im_msgtype = IGMPMSG_WHOLEPKT; msg->im_mbz = 0; - msg->im_vif = reg_vif_num; + msg->im_vif = init_net.ipv4.mroute_reg_vif_num; ip_hdr(skb)->ihl = sizeof(struct iphdr) >> 2; ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(pkt)->tot_len) + sizeof(struct iphdr)); @@ -1506,8 +1504,8 @@ static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen) return 1; read_lock(&mrt_lock); - if (reg_vif_num >= 0) - reg_dev = init_net.ipv4.vif_table[reg_vif_num].dev; + if (init_net.ipv4.mroute_reg_vif_num >= 0) + reg_dev = init_net.ipv4.vif_table[init_net.ipv4.mroute_reg_vif_num].dev; if (reg_dev) dev_hold(reg_dev); read_unlock(&mrt_lock); @@ -1940,6 +1938,10 @@ static int __net_init ipmr_net_init(struct net *net) err = -ENOMEM; goto fail_mfc_cache; } + +#ifdef CONFIG_IP_PIMSM + net->ipv4.mroute_reg_vif_num = -1; +#endif return 0; fail_mfc_cache: -- GitLab From f6bb451476be53d456e73bcfd82356afd680bbb0 Mon Sep 17 00:00:00 2001 From: Benjamin Thery Date: Thu, 22 Jan 2009 04:56:22 +0000 Subject: [PATCH 0394/4982] netns: ipmr: declare ipmr /proc/net entries per-namespace Declare IPv4 multicast forwarding /proc/net entries per-namespace: /proc/net/ip_mr_vif /proc/net/ip_mr_cache Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- net/ipv4/ipmr.c | 101 +++++++++++++++++++++++++++++------------------- 1 file changed, 62 insertions(+), 39 deletions(-) diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 346e67b50d6..a4fd97f1920 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1671,17 +1671,19 @@ int ipmr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait) * The /proc interfaces to multicast routing /proc/ip_mr_cache /proc/ip_mr_vif */ struct ipmr_vif_iter { + struct seq_net_private p; int ct; }; -static struct vif_device *ipmr_vif_seq_idx(struct ipmr_vif_iter *iter, +static struct vif_device *ipmr_vif_seq_idx(struct net *net, + struct ipmr_vif_iter *iter, loff_t pos) { - for (iter->ct = 0; iter->ct < init_net.ipv4.maxvif; ++iter->ct) { - if (!VIF_EXISTS(&init_net, iter->ct)) + for (iter->ct = 0; iter->ct < net->ipv4.maxvif; ++iter->ct) { + if (!VIF_EXISTS(net, iter->ct)) continue; if (pos-- == 0) - return &init_net.ipv4.vif_table[iter->ct]; + return &net->ipv4.vif_table[iter->ct]; } return NULL; } @@ -1689,23 +1691,26 @@ static struct vif_device *ipmr_vif_seq_idx(struct ipmr_vif_iter *iter, static void *ipmr_vif_seq_start(struct seq_file *seq, loff_t *pos) __acquires(mrt_lock) { + struct net *net = seq_file_net(seq); + read_lock(&mrt_lock); - return *pos ? ipmr_vif_seq_idx(seq->private, *pos - 1) + return *pos ? ipmr_vif_seq_idx(net, seq->private, *pos - 1) : SEQ_START_TOKEN; } static void *ipmr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct ipmr_vif_iter *iter = seq->private; + struct net *net = seq_file_net(seq); ++*pos; if (v == SEQ_START_TOKEN) - return ipmr_vif_seq_idx(iter, 0); + return ipmr_vif_seq_idx(net, iter, 0); - while (++iter->ct < init_net.ipv4.maxvif) { - if (!VIF_EXISTS(&init_net, iter->ct)) + while (++iter->ct < net->ipv4.maxvif) { + if (!VIF_EXISTS(net, iter->ct)) continue; - return &init_net.ipv4.vif_table[iter->ct]; + return &net->ipv4.vif_table[iter->ct]; } return NULL; } @@ -1718,6 +1723,8 @@ static void ipmr_vif_seq_stop(struct seq_file *seq, void *v) static int ipmr_vif_seq_show(struct seq_file *seq, void *v) { + struct net *net = seq_file_net(seq); + if (v == SEQ_START_TOKEN) { seq_puts(seq, "Interface BytesIn PktsIn BytesOut PktsOut Flags Local Remote\n"); @@ -1727,7 +1734,7 @@ static int ipmr_vif_seq_show(struct seq_file *seq, void *v) seq_printf(seq, "%2Zd %-10s %8ld %7ld %8ld %7ld %05X %08X %08X\n", - vif - init_net.ipv4.vif_table, + vif - net->ipv4.vif_table, name, vif->bytes_in, vif->pkt_in, vif->bytes_out, vif->pkt_out, vif->flags, vif->local, vif->remote); @@ -1744,8 +1751,8 @@ static const struct seq_operations ipmr_vif_seq_ops = { static int ipmr_vif_open(struct inode *inode, struct file *file) { - return seq_open_private(file, &ipmr_vif_seq_ops, - sizeof(struct ipmr_vif_iter)); + return seq_open_net(inode, file, &ipmr_vif_seq_ops, + sizeof(struct ipmr_vif_iter)); } static const struct file_operations ipmr_vif_fops = { @@ -1753,23 +1760,25 @@ static const struct file_operations ipmr_vif_fops = { .open = ipmr_vif_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release_private, + .release = seq_release_net, }; struct ipmr_mfc_iter { + struct seq_net_private p; struct mfc_cache **cache; int ct; }; -static struct mfc_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos) +static struct mfc_cache *ipmr_mfc_seq_idx(struct net *net, + struct ipmr_mfc_iter *it, loff_t pos) { struct mfc_cache *mfc; - it->cache = init_net.ipv4.mfc_cache_array; + it->cache = net->ipv4.mfc_cache_array; read_lock(&mrt_lock); for (it->ct = 0; it->ct < MFC_LINES; it->ct++) - for (mfc = init_net.ipv4.mfc_cache_array[it->ct]; + for (mfc = net->ipv4.mfc_cache_array[it->ct]; mfc; mfc = mfc->next) if (pos-- == 0) return mfc; @@ -1778,7 +1787,8 @@ static struct mfc_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos) it->cache = &mfc_unres_queue; spin_lock_bh(&mfc_unres_lock); for (mfc = mfc_unres_queue; mfc; mfc = mfc->next) - if (pos-- == 0) + if (net_eq(mfc_net(mfc), net) && + pos-- == 0) return mfc; spin_unlock_bh(&mfc_unres_lock); @@ -1790,9 +1800,11 @@ static struct mfc_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos) static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos) { struct ipmr_mfc_iter *it = seq->private; + struct net *net = seq_file_net(seq); + it->cache = NULL; it->ct = 0; - return *pos ? ipmr_mfc_seq_idx(seq->private, *pos - 1) + return *pos ? ipmr_mfc_seq_idx(net, seq->private, *pos - 1) : SEQ_START_TOKEN; } @@ -1800,11 +1812,12 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct mfc_cache *mfc = v; struct ipmr_mfc_iter *it = seq->private; + struct net *net = seq_file_net(seq); ++*pos; if (v == SEQ_START_TOKEN) - return ipmr_mfc_seq_idx(seq->private, 0); + return ipmr_mfc_seq_idx(net, seq->private, 0); if (mfc->next) return mfc->next; @@ -1812,10 +1825,10 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) if (it->cache == &mfc_unres_queue) goto end_of_list; - BUG_ON(it->cache != init_net.ipv4.mfc_cache_array); + BUG_ON(it->cache != net->ipv4.mfc_cache_array); while (++it->ct < MFC_LINES) { - mfc = init_net.ipv4.mfc_cache_array[it->ct]; + mfc = net->ipv4.mfc_cache_array[it->ct]; if (mfc) return mfc; } @@ -1827,6 +1840,8 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) spin_lock_bh(&mfc_unres_lock); mfc = mfc_unres_queue; + while (mfc && !net_eq(mfc_net(mfc), net)) + mfc = mfc->next; if (mfc) return mfc; @@ -1840,16 +1855,18 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v) { struct ipmr_mfc_iter *it = seq->private; + struct net *net = seq_file_net(seq); if (it->cache == &mfc_unres_queue) spin_unlock_bh(&mfc_unres_lock); - else if (it->cache == init_net.ipv4.mfc_cache_array) + else if (it->cache == net->ipv4.mfc_cache_array) read_unlock(&mrt_lock); } static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) { int n; + struct net *net = seq_file_net(seq); if (v == SEQ_START_TOKEN) { seq_puts(seq, @@ -1870,7 +1887,7 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) mfc->mfc_un.res.wrong_if); for (n = mfc->mfc_un.res.minvif; n < mfc->mfc_un.res.maxvif; n++ ) { - if (VIF_EXISTS(&init_net, n) && + if (VIF_EXISTS(net, n) && mfc->mfc_un.res.ttls[n] < 255) seq_printf(seq, " %2d:%-3d", @@ -1896,8 +1913,8 @@ static const struct seq_operations ipmr_mfc_seq_ops = { static int ipmr_mfc_open(struct inode *inode, struct file *file) { - return seq_open_private(file, &ipmr_mfc_seq_ops, - sizeof(struct ipmr_mfc_iter)); + return seq_open_net(inode, file, &ipmr_mfc_seq_ops, + sizeof(struct ipmr_mfc_iter)); } static const struct file_operations ipmr_mfc_fops = { @@ -1905,7 +1922,7 @@ static const struct file_operations ipmr_mfc_fops = { .open = ipmr_mfc_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release_private, + .release = seq_release_net, }; #endif @@ -1942,8 +1959,22 @@ static int __net_init ipmr_net_init(struct net *net) #ifdef CONFIG_IP_PIMSM net->ipv4.mroute_reg_vif_num = -1; #endif + +#ifdef CONFIG_PROC_FS + err = -ENOMEM; + if (!proc_net_fops_create(net, "ip_mr_vif", 0, &ipmr_vif_fops)) + goto proc_vif_fail; + if (!proc_net_fops_create(net, "ip_mr_cache", 0, &ipmr_mfc_fops)) + goto proc_cache_fail; +#endif return 0; +#ifdef CONFIG_PROC_FS +proc_cache_fail: + proc_net_remove(net, "ip_mr_vif"); +proc_vif_fail: + kfree(net->ipv4.mfc_cache_array); +#endif fail_mfc_cache: kfree(net->ipv4.vif_table); fail: @@ -1952,6 +1983,10 @@ fail: static void __net_exit ipmr_net_exit(struct net *net) { +#ifdef CONFIG_PROC_FS + proc_net_remove(net, "ip_mr_cache"); + proc_net_remove(net, "ip_mr_vif"); +#endif kfree(net->ipv4.mfc_cache_array); kfree(net->ipv4.vif_table); } @@ -1980,20 +2015,8 @@ int __init ip_mr_init(void) err = register_netdevice_notifier(&ip_mr_notifier); if (err) goto reg_notif_fail; -#ifdef CONFIG_PROC_FS - err = -ENOMEM; - if (!proc_net_fops_create(&init_net, "ip_mr_vif", 0, &ipmr_vif_fops)) - goto proc_vif_fail; - if (!proc_net_fops_create(&init_net, "ip_mr_cache", 0, &ipmr_mfc_fops)) - goto proc_cache_fail; -#endif return 0; -#ifdef CONFIG_PROC_FS -proc_cache_fail: - proc_net_remove(&init_net, "ip_mr_vif"); -proc_vif_fail: - unregister_netdevice_notifier(&ip_mr_notifier); -#endif + reg_notif_fail: del_timer(&ipmr_expire_timer); unregister_pernet_subsys(&ipmr_net_ops); -- GitLab From 4feb88e5c694bfe414cbc3ce0e383f7f7038f90b Mon Sep 17 00:00:00 2001 From: Benjamin Thery Date: Thu, 22 Jan 2009 04:56:23 +0000 Subject: [PATCH 0395/4982] netns: ipmr: enable namespace support in ipv4 multicast routing code This last patch makes the appropriate changes to use and propagate the network namespace where needed in IPv4 multicast routing code. This consists mainly in replacing all the remaining init_net occurences with current netns pointer retrieved from sockets, net devices or mfc_caches depending on the routines' contexts. Some routines receive a new 'struct net' parameter to propagate the current netns: * vif_add/vif_delete * ipmr_new_tunnel * mroute_clean_tables * ipmr_cache_find * ipmr_cache_report * ipmr_cache_unresolved * ipmr_mfc_add/ipmr_mfc_delete * ipmr_get_route * rt_fill_info (in route.c) Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- include/linux/mroute.h | 3 +- net/ipv4/ipmr.c | 243 +++++++++++++++++++++++------------------ net/ipv4/route.c | 11 +- 3 files changed, 143 insertions(+), 114 deletions(-) diff --git a/include/linux/mroute.h b/include/linux/mroute.h index beaf3aae8aa..0d45b4e8d36 100644 --- a/include/linux/mroute.h +++ b/include/linux/mroute.h @@ -256,7 +256,8 @@ void mfc_net_set(struct mfc_cache *mfc, struct net *net) #ifdef __KERNEL__ struct rtmsg; -extern int ipmr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait); +extern int ipmr_get_route(struct net *net, struct sk_buff *skb, + struct rtmsg *rtm, int nowait); #endif #endif diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index a4fd97f1920..21a6dc710f2 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -95,7 +95,8 @@ static DEFINE_SPINLOCK(mfc_unres_lock); static struct kmem_cache *mrt_cachep __read_mostly; static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local); -static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert); +static int ipmr_cache_report(struct net *net, + struct sk_buff *pkt, vifi_t vifi, int assert); static int ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm); #ifdef CONFIG_IP_PIMSM_V2 @@ -108,9 +109,11 @@ static struct timer_list ipmr_expire_timer; static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v) { + struct net *net = dev_net(dev); + dev_close(dev); - dev = __dev_get_by_name(&init_net, "tunl0"); + dev = __dev_get_by_name(net, "tunl0"); if (dev) { const struct net_device_ops *ops = dev->netdev_ops; struct ifreq ifr; @@ -136,11 +139,11 @@ static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v) } static -struct net_device *ipmr_new_tunnel(struct vifctl *v) +struct net_device *ipmr_new_tunnel(struct net *net, struct vifctl *v) { struct net_device *dev; - dev = __dev_get_by_name(&init_net, "tunl0"); + dev = __dev_get_by_name(net, "tunl0"); if (dev) { const struct net_device_ops *ops = dev->netdev_ops; @@ -169,7 +172,8 @@ struct net_device *ipmr_new_tunnel(struct vifctl *v) dev = NULL; - if (err == 0 && (dev = __dev_get_by_name(&init_net, p.name)) != NULL) { + if (err == 0 && + (dev = __dev_get_by_name(net, p.name)) != NULL) { dev->flags |= IFF_MULTICAST; in_dev = __in_dev_get_rtnl(dev); @@ -199,10 +203,13 @@ failure: static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) { + struct net *net = dev_net(dev); + read_lock(&mrt_lock); dev->stats.tx_bytes += skb->len; dev->stats.tx_packets++; - ipmr_cache_report(skb, init_net.ipv4.mroute_reg_vif_num, IGMPMSG_WHOLEPKT); + ipmr_cache_report(net, skb, net->ipv4.mroute_reg_vif_num, + IGMPMSG_WHOLEPKT); read_unlock(&mrt_lock); kfree_skb(skb); return 0; @@ -269,16 +276,16 @@ failure: * @notify: Set to 1, if the caller is a notifier_call */ -static int vif_delete(int vifi, int notify) +static int vif_delete(struct net *net, int vifi, int notify) { struct vif_device *v; struct net_device *dev; struct in_device *in_dev; - if (vifi < 0 || vifi >= init_net.ipv4.maxvif) + if (vifi < 0 || vifi >= net->ipv4.maxvif) return -EADDRNOTAVAIL; - v = &init_net.ipv4.vif_table[vifi]; + v = &net->ipv4.vif_table[vifi]; write_lock_bh(&mrt_lock); dev = v->dev; @@ -290,17 +297,17 @@ static int vif_delete(int vifi, int notify) } #ifdef CONFIG_IP_PIMSM - if (vifi == init_net.ipv4.mroute_reg_vif_num) - init_net.ipv4.mroute_reg_vif_num = -1; + if (vifi == net->ipv4.mroute_reg_vif_num) + net->ipv4.mroute_reg_vif_num = -1; #endif - if (vifi+1 == init_net.ipv4.maxvif) { + if (vifi+1 == net->ipv4.maxvif) { int tmp; for (tmp=vifi-1; tmp>=0; tmp--) { - if (VIF_EXISTS(&init_net, tmp)) + if (VIF_EXISTS(net, tmp)) break; } - init_net.ipv4.maxvif = tmp+1; + net->ipv4.maxvif = tmp+1; } write_unlock_bh(&mrt_lock); @@ -333,8 +340,9 @@ static void ipmr_destroy_unres(struct mfc_cache *c) { struct sk_buff *skb; struct nlmsgerr *e; + struct net *net = mfc_net(c); - atomic_dec(&init_net.ipv4.cache_resolve_queue_len); + atomic_dec(&net->ipv4.cache_resolve_queue_len); while ((skb = skb_dequeue(&c->mfc_un.unres.unresolved))) { if (ip_hdr(skb)->version == 0) { @@ -346,7 +354,7 @@ static void ipmr_destroy_unres(struct mfc_cache *c) e->error = -ETIMEDOUT; memset(&e->msg, 0, sizeof(e->msg)); - rtnl_unicast(skb, &init_net, NETLINK_CB(skb).pid); + rtnl_unicast(skb, net, NETLINK_CB(skb).pid); } else kfree_skb(skb); } @@ -401,13 +409,14 @@ out: static void ipmr_update_thresholds(struct mfc_cache *cache, unsigned char *ttls) { int vifi; + struct net *net = mfc_net(cache); cache->mfc_un.res.minvif = MAXVIFS; cache->mfc_un.res.maxvif = 0; memset(cache->mfc_un.res.ttls, 255, MAXVIFS); - for (vifi = 0; vifi < init_net.ipv4.maxvif; vifi++) { - if (VIF_EXISTS(&init_net, vifi) && + for (vifi = 0; vifi < net->ipv4.maxvif; vifi++) { + if (VIF_EXISTS(net, vifi) && ttls[vifi] && ttls[vifi] < 255) { cache->mfc_un.res.ttls[vifi] = ttls[vifi]; if (cache->mfc_un.res.minvif > vifi) @@ -418,16 +427,16 @@ static void ipmr_update_thresholds(struct mfc_cache *cache, unsigned char *ttls) } } -static int vif_add(struct vifctl *vifc, int mrtsock) +static int vif_add(struct net *net, struct vifctl *vifc, int mrtsock) { int vifi = vifc->vifc_vifi; - struct vif_device *v = &init_net.ipv4.vif_table[vifi]; + struct vif_device *v = &net->ipv4.vif_table[vifi]; struct net_device *dev; struct in_device *in_dev; int err; /* Is vif busy ? */ - if (VIF_EXISTS(&init_net, vifi)) + if (VIF_EXISTS(net, vifi)) return -EADDRINUSE; switch (vifc->vifc_flags) { @@ -437,7 +446,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock) * Special Purpose VIF in PIM * All the packets will be sent to the daemon */ - if (init_net.ipv4.mroute_reg_vif_num >= 0) + if (net->ipv4.mroute_reg_vif_num >= 0) return -EADDRINUSE; dev = ipmr_reg_vif(); if (!dev) @@ -451,7 +460,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock) break; #endif case VIFF_TUNNEL: - dev = ipmr_new_tunnel(vifc); + dev = ipmr_new_tunnel(net, vifc); if (!dev) return -ENOBUFS; err = dev_set_allmulti(dev, 1); @@ -462,7 +471,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock) } break; case 0: - dev = ip_dev_find(&init_net, vifc->vifc_lcl_addr.s_addr); + dev = ip_dev_find(net, vifc->vifc_lcl_addr.s_addr); if (!dev) return -EADDRNOTAVAIL; err = dev_set_allmulti(dev, 1); @@ -503,20 +512,22 @@ static int vif_add(struct vifctl *vifc, int mrtsock) v->dev = dev; #ifdef CONFIG_IP_PIMSM if (v->flags&VIFF_REGISTER) - init_net.ipv4.mroute_reg_vif_num = vifi; + net->ipv4.mroute_reg_vif_num = vifi; #endif - if (vifi+1 > init_net.ipv4.maxvif) - init_net.ipv4.maxvif = vifi+1; + if (vifi+1 > net->ipv4.maxvif) + net->ipv4.maxvif = vifi+1; write_unlock_bh(&mrt_lock); return 0; } -static struct mfc_cache *ipmr_cache_find(__be32 origin, __be32 mcastgrp) +static struct mfc_cache *ipmr_cache_find(struct net *net, + __be32 origin, + __be32 mcastgrp) { int line = MFC_HASH(mcastgrp, origin); struct mfc_cache *c; - for (c = init_net.ipv4.mfc_cache_array[line]; c; c = c->next) { + for (c = net->ipv4.mfc_cache_array[line]; c; c = c->next) { if (c->mfc_origin==origin && c->mfc_mcastgrp==mcastgrp) break; } @@ -576,7 +587,7 @@ static void ipmr_cache_resolve(struct mfc_cache *uc, struct mfc_cache *c) memset(&e->msg, 0, sizeof(e->msg)); } - rtnl_unicast(skb, &init_net, NETLINK_CB(skb).pid); + rtnl_unicast(skb, mfc_net(c), NETLINK_CB(skb).pid); } else ip_mr_forward(skb, c, 0); } @@ -589,7 +600,8 @@ static void ipmr_cache_resolve(struct mfc_cache *uc, struct mfc_cache *c) * Called under mrt_lock. */ -static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert) +static int ipmr_cache_report(struct net *net, + struct sk_buff *pkt, vifi_t vifi, int assert) { struct sk_buff *skb; const int ihl = ip_hdrlen(pkt); @@ -621,7 +633,7 @@ static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert) memcpy(msg, skb_network_header(pkt), sizeof(struct iphdr)); msg->im_msgtype = IGMPMSG_WHOLEPKT; msg->im_mbz = 0; - msg->im_vif = init_net.ipv4.mroute_reg_vif_num; + msg->im_vif = net->ipv4.mroute_reg_vif_num; ip_hdr(skb)->ihl = sizeof(struct iphdr) >> 2; ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(pkt)->tot_len) + sizeof(struct iphdr)); @@ -653,7 +665,7 @@ static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert) skb->transport_header = skb->network_header; } - if (init_net.ipv4.mroute_sk == NULL) { + if (net->ipv4.mroute_sk == NULL) { kfree_skb(skb); return -EINVAL; } @@ -661,7 +673,7 @@ static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert) /* * Deliver to mrouted */ - ret = sock_queue_rcv_skb(init_net.ipv4.mroute_sk, skb); + ret = sock_queue_rcv_skb(net->ipv4.mroute_sk, skb); if (ret < 0) { if (net_ratelimit()) printk(KERN_WARNING "mroute: pending queue full, dropping entries.\n"); @@ -676,7 +688,7 @@ static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert) */ static int -ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) +ipmr_cache_unresolved(struct net *net, vifi_t vifi, struct sk_buff *skb) { int err; struct mfc_cache *c; @@ -684,7 +696,7 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) spin_lock_bh(&mfc_unres_lock); for (c=mfc_unres_queue; c; c=c->next) { - if (net_eq(mfc_net(c), &init_net) && + if (net_eq(mfc_net(c), net) && c->mfc_mcastgrp == iph->daddr && c->mfc_origin == iph->saddr) break; @@ -695,8 +707,8 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) * Create a new entry if allowable */ - if (atomic_read(&init_net.ipv4.cache_resolve_queue_len) >= 10 || - (c = ipmr_cache_alloc_unres(&init_net)) == NULL) { + if (atomic_read(&net->ipv4.cache_resolve_queue_len) >= 10 || + (c = ipmr_cache_alloc_unres(net)) == NULL) { spin_unlock_bh(&mfc_unres_lock); kfree_skb(skb); @@ -713,7 +725,8 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) /* * Reflect first query at mrouted. */ - if ((err = ipmr_cache_report(skb, vifi, IGMPMSG_NOCACHE))<0) { + err = ipmr_cache_report(net, skb, vifi, IGMPMSG_NOCACHE); + if (err < 0) { /* If the report failed throw the cache entry out - Brad Parker */ @@ -724,7 +737,7 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) return err; } - atomic_inc(&init_net.ipv4.cache_resolve_queue_len); + atomic_inc(&net->ipv4.cache_resolve_queue_len); c->next = mfc_unres_queue; mfc_unres_queue = c; @@ -750,14 +763,14 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) * MFC cache manipulation by user space mroute daemon */ -static int ipmr_mfc_delete(struct mfcctl *mfc) +static int ipmr_mfc_delete(struct net *net, struct mfcctl *mfc) { int line; struct mfc_cache *c, **cp; line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr); - for (cp = &init_net.ipv4.mfc_cache_array[line]; + for (cp = &net->ipv4.mfc_cache_array[line]; (c = *cp) != NULL; cp = &c->next) { if (c->mfc_origin == mfc->mfcc_origin.s_addr && c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) { @@ -772,14 +785,14 @@ static int ipmr_mfc_delete(struct mfcctl *mfc) return -ENOENT; } -static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) +static int ipmr_mfc_add(struct net *net, struct mfcctl *mfc, int mrtsock) { int line; struct mfc_cache *uc, *c, **cp; line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr); - for (cp = &init_net.ipv4.mfc_cache_array[line]; + for (cp = &net->ipv4.mfc_cache_array[line]; (c = *cp) != NULL; cp = &c->next) { if (c->mfc_origin == mfc->mfcc_origin.s_addr && c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) @@ -799,7 +812,7 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) if (!ipv4_is_multicast(mfc->mfcc_mcastgrp.s_addr)) return -EINVAL; - c = ipmr_cache_alloc(&init_net); + c = ipmr_cache_alloc(net); if (c == NULL) return -ENOMEM; @@ -811,8 +824,8 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) c->mfc_flags |= MFC_STATIC; write_lock_bh(&mrt_lock); - c->next = init_net.ipv4.mfc_cache_array[line]; - init_net.ipv4.mfc_cache_array[line] = c; + c->next = net->ipv4.mfc_cache_array[line]; + net->ipv4.mfc_cache_array[line] = c; write_unlock_bh(&mrt_lock); /* @@ -822,11 +835,11 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) spin_lock_bh(&mfc_unres_lock); for (cp = &mfc_unres_queue; (uc=*cp) != NULL; cp = &uc->next) { - if (net_eq(mfc_net(uc), &init_net) && + if (net_eq(mfc_net(uc), net) && uc->mfc_origin == c->mfc_origin && uc->mfc_mcastgrp == c->mfc_mcastgrp) { *cp = uc->next; - atomic_dec(&init_net.ipv4.cache_resolve_queue_len); + atomic_dec(&net->ipv4.cache_resolve_queue_len); break; } } @@ -845,16 +858,16 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) * Close the multicast socket, and clear the vif tables etc */ -static void mroute_clean_tables(struct sock *sk) +static void mroute_clean_tables(struct net *net) { int i; /* * Shut down all active vif entries */ - for (i = 0; i < init_net.ipv4.maxvif; i++) { - if (!(init_net.ipv4.vif_table[i].flags&VIFF_STATIC)) - vif_delete(i, 0); + for (i = 0; i < net->ipv4.maxvif; i++) { + if (!(net->ipv4.vif_table[i].flags&VIFF_STATIC)) + vif_delete(net, i, 0); } /* @@ -863,7 +876,7 @@ static void mroute_clean_tables(struct sock *sk) for (i=0; iipv4.mfc_cache_array[i]; while ((c = *cp) != NULL) { if (c->mfc_flags&MFC_STATIC) { cp = &c->next; @@ -877,13 +890,13 @@ static void mroute_clean_tables(struct sock *sk) } } - if (atomic_read(&init_net.ipv4.cache_resolve_queue_len) != 0) { + if (atomic_read(&net->ipv4.cache_resolve_queue_len) != 0) { struct mfc_cache *c, **cp; spin_lock_bh(&mfc_unres_lock); cp = &mfc_unres_queue; while ((c = *cp) != NULL) { - if (!net_eq(mfc_net(c), &init_net)) { + if (!net_eq(mfc_net(c), net)) { cp = &c->next; continue; } @@ -897,15 +910,17 @@ static void mroute_clean_tables(struct sock *sk) static void mrtsock_destruct(struct sock *sk) { + struct net *net = sock_net(sk); + rtnl_lock(); - if (sk == init_net.ipv4.mroute_sk) { - IPV4_DEVCONF_ALL(sock_net(sk), MC_FORWARDING)--; + if (sk == net->ipv4.mroute_sk) { + IPV4_DEVCONF_ALL(net, MC_FORWARDING)--; write_lock_bh(&mrt_lock); - init_net.ipv4.mroute_sk = NULL; + net->ipv4.mroute_sk = NULL; write_unlock_bh(&mrt_lock); - mroute_clean_tables(sk); + mroute_clean_tables(net); } rtnl_unlock(); } @@ -922,9 +937,10 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int int ret; struct vifctl vif; struct mfcctl mfc; + struct net *net = sock_net(sk); if (optname != MRT_INIT) { - if (sk != init_net.ipv4.mroute_sk && !capable(CAP_NET_ADMIN)) + if (sk != net->ipv4.mroute_sk && !capable(CAP_NET_ADMIN)) return -EACCES; } @@ -937,7 +953,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int return -ENOPROTOOPT; rtnl_lock(); - if (init_net.ipv4.mroute_sk) { + if (net->ipv4.mroute_sk) { rtnl_unlock(); return -EADDRINUSE; } @@ -945,15 +961,15 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int ret = ip_ra_control(sk, 1, mrtsock_destruct); if (ret == 0) { write_lock_bh(&mrt_lock); - init_net.ipv4.mroute_sk = sk; + net->ipv4.mroute_sk = sk; write_unlock_bh(&mrt_lock); - IPV4_DEVCONF_ALL(sock_net(sk), MC_FORWARDING)++; + IPV4_DEVCONF_ALL(net, MC_FORWARDING)++; } rtnl_unlock(); return ret; case MRT_DONE: - if (sk != init_net.ipv4.mroute_sk) + if (sk != net->ipv4.mroute_sk) return -EACCES; return ip_ra_control(sk, 0, NULL); case MRT_ADD_VIF: @@ -966,9 +982,9 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int return -ENFILE; rtnl_lock(); if (optname == MRT_ADD_VIF) { - ret = vif_add(&vif, sk == init_net.ipv4.mroute_sk); + ret = vif_add(net, &vif, sk == net->ipv4.mroute_sk); } else { - ret = vif_delete(vif.vifc_vifi, 0); + ret = vif_delete(net, vif.vifc_vifi, 0); } rtnl_unlock(); return ret; @@ -985,9 +1001,9 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int return -EFAULT; rtnl_lock(); if (optname == MRT_DEL_MFC) - ret = ipmr_mfc_delete(&mfc); + ret = ipmr_mfc_delete(net, &mfc); else - ret = ipmr_mfc_add(&mfc, sk == init_net.ipv4.mroute_sk); + ret = ipmr_mfc_add(net, &mfc, sk == net->ipv4.mroute_sk); rtnl_unlock(); return ret; /* @@ -998,7 +1014,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int int v; if (get_user(v,(int __user *)optval)) return -EFAULT; - init_net.ipv4.mroute_do_assert = (v) ? 1 : 0; + net->ipv4.mroute_do_assert = (v) ? 1 : 0; return 0; } #ifdef CONFIG_IP_PIMSM @@ -1012,11 +1028,11 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int rtnl_lock(); ret = 0; - if (v != init_net.ipv4.mroute_do_pim) { - init_net.ipv4.mroute_do_pim = v; - init_net.ipv4.mroute_do_assert = v; + if (v != net->ipv4.mroute_do_pim) { + net->ipv4.mroute_do_pim = v; + net->ipv4.mroute_do_assert = v; #ifdef CONFIG_IP_PIMSM_V2 - if (init_net.ipv4.mroute_do_pim) + if (net->ipv4.mroute_do_pim) ret = inet_add_protocol(&pim_protocol, IPPROTO_PIM); else @@ -1047,6 +1063,7 @@ int ip_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, int { int olr; int val; + struct net *net = sock_net(sk); if (optname != MRT_VERSION && #ifdef CONFIG_IP_PIMSM @@ -1068,10 +1085,10 @@ int ip_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, int val = 0x0305; #ifdef CONFIG_IP_PIMSM else if (optname == MRT_PIM) - val = init_net.ipv4.mroute_do_pim; + val = net->ipv4.mroute_do_pim; #endif else - val = init_net.ipv4.mroute_do_assert; + val = net->ipv4.mroute_do_assert; if (copy_to_user(optval, &val, olr)) return -EFAULT; return 0; @@ -1087,16 +1104,17 @@ int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg) struct sioc_vif_req vr; struct vif_device *vif; struct mfc_cache *c; + struct net *net = sock_net(sk); switch (cmd) { case SIOCGETVIFCNT: if (copy_from_user(&vr, arg, sizeof(vr))) return -EFAULT; - if (vr.vifi >= init_net.ipv4.maxvif) + if (vr.vifi >= net->ipv4.maxvif) return -EINVAL; read_lock(&mrt_lock); - vif = &init_net.ipv4.vif_table[vr.vifi]; - if (VIF_EXISTS(&init_net, vr.vifi)) { + vif = &net->ipv4.vif_table[vr.vifi]; + if (VIF_EXISTS(net, vr.vifi)) { vr.icount = vif->pkt_in; vr.ocount = vif->pkt_out; vr.ibytes = vif->bytes_in; @@ -1114,7 +1132,7 @@ int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg) return -EFAULT; read_lock(&mrt_lock); - c = ipmr_cache_find(sr.src.s_addr, sr.grp.s_addr); + c = ipmr_cache_find(net, sr.src.s_addr, sr.grp.s_addr); if (c) { sr.pktcnt = c->mfc_un.res.pkt; sr.bytecnt = c->mfc_un.res.bytes; @@ -1136,18 +1154,19 @@ int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg) static int ipmr_device_event(struct notifier_block *this, unsigned long event, void *ptr) { struct net_device *dev = ptr; + struct net *net = dev_net(dev); struct vif_device *v; int ct; - if (!net_eq(dev_net(dev), &init_net)) + if (!net_eq(dev_net(dev), net)) return NOTIFY_DONE; if (event != NETDEV_UNREGISTER) return NOTIFY_DONE; - v = &init_net.ipv4.vif_table[0]; - for (ct = 0; ct < init_net.ipv4.maxvif; ct++, v++) { + v = &net->ipv4.vif_table[0]; + for (ct = 0; ct < net->ipv4.maxvif; ct++, v++) { if (v->dev == dev) - vif_delete(ct, 1); + vif_delete(net, ct, 1); } return NOTIFY_DONE; } @@ -1207,8 +1226,9 @@ static inline int ipmr_forward_finish(struct sk_buff *skb) static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) { + struct net *net = mfc_net(c); const struct iphdr *iph = ip_hdr(skb); - struct vif_device *vif = &init_net.ipv4.vif_table[vifi]; + struct vif_device *vif = &net->ipv4.vif_table[vifi]; struct net_device *dev; struct rtable *rt; int encap = 0; @@ -1222,7 +1242,7 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) vif->bytes_out += skb->len; vif->dev->stats.tx_bytes += skb->len; vif->dev->stats.tx_packets++; - ipmr_cache_report(skb, vifi, IGMPMSG_WHOLEPKT); + ipmr_cache_report(net, skb, vifi, IGMPMSG_WHOLEPKT); kfree_skb(skb); return; } @@ -1235,7 +1255,7 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) .saddr = vif->local, .tos = RT_TOS(iph->tos) } }, .proto = IPPROTO_IPIP }; - if (ip_route_output_key(&init_net, &rt, &fl)) + if (ip_route_output_key(net, &rt, &fl)) goto out_free; encap = sizeof(struct iphdr); } else { @@ -1244,7 +1264,7 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) { .daddr = iph->daddr, .tos = RT_TOS(iph->tos) } }, .proto = IPPROTO_IPIP }; - if (ip_route_output_key(&init_net, &rt, &fl)) + if (ip_route_output_key(net, &rt, &fl)) goto out_free; } @@ -1308,9 +1328,10 @@ out_free: static int ipmr_find_vif(struct net_device *dev) { + struct net *net = dev_net(dev); int ct; - for (ct = init_net.ipv4.maxvif-1; ct >= 0; ct--) { - if (init_net.ipv4.vif_table[ct].dev == dev) + for (ct = net->ipv4.maxvif-1; ct >= 0; ct--) { + if (net->ipv4.vif_table[ct].dev == dev) break; } return ct; @@ -1322,6 +1343,7 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local { int psend = -1; int vif, ct; + struct net *net = mfc_net(cache); vif = cache->mfc_parent; cache->mfc_un.res.pkt++; @@ -1330,7 +1352,7 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local /* * Wrong interface: drop packet and (maybe) send PIM assert. */ - if (init_net.ipv4.vif_table[vif].dev != skb->dev) { + if (net->ipv4.vif_table[vif].dev != skb->dev) { int true_vifi; if (skb->rtable->fl.iif == 0) { @@ -1351,24 +1373,24 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local cache->mfc_un.res.wrong_if++; true_vifi = ipmr_find_vif(skb->dev); - if (true_vifi >= 0 && init_net.ipv4.mroute_do_assert && + if (true_vifi >= 0 && net->ipv4.mroute_do_assert && /* pimsm uses asserts, when switching from RPT to SPT, so that we cannot check that packet arrived on an oif. It is bad, but otherwise we would need to move pretty large chunk of pimd to kernel. Ough... --ANK */ - (init_net.ipv4.mroute_do_pim || + (net->ipv4.mroute_do_pim || cache->mfc_un.res.ttls[true_vifi] < 255) && time_after(jiffies, cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) { cache->mfc_un.res.last_assert = jiffies; - ipmr_cache_report(skb, true_vifi, IGMPMSG_WRONGVIF); + ipmr_cache_report(net, skb, true_vifi, IGMPMSG_WRONGVIF); } goto dont_forward; } - init_net.ipv4.vif_table[vif].pkt_in++; - init_net.ipv4.vif_table[vif].bytes_in += skb->len; + net->ipv4.vif_table[vif].pkt_in++; + net->ipv4.vif_table[vif].bytes_in += skb->len; /* * Forward the frame @@ -1408,6 +1430,7 @@ dont_forward: int ip_mr_input(struct sk_buff *skb) { struct mfc_cache *cache; + struct net *net = dev_net(skb->dev); int local = skb->rtable->rt_flags&RTCF_LOCAL; /* Packet is looped back after forward, it should not be @@ -1428,9 +1451,9 @@ int ip_mr_input(struct sk_buff *skb) that we can forward NO IGMP messages. */ read_lock(&mrt_lock); - if (init_net.ipv4.mroute_sk) { + if (net->ipv4.mroute_sk) { nf_reset(skb); - raw_rcv(init_net.ipv4.mroute_sk, skb); + raw_rcv(net->ipv4.mroute_sk, skb); read_unlock(&mrt_lock); return 0; } @@ -1439,7 +1462,7 @@ int ip_mr_input(struct sk_buff *skb) } read_lock(&mrt_lock); - cache = ipmr_cache_find(ip_hdr(skb)->saddr, ip_hdr(skb)->daddr); + cache = ipmr_cache_find(net, ip_hdr(skb)->saddr, ip_hdr(skb)->daddr); /* * No usable cache entry @@ -1459,7 +1482,7 @@ int ip_mr_input(struct sk_buff *skb) vif = ipmr_find_vif(skb->dev); if (vif >= 0) { - int err = ipmr_cache_unresolved(vif, skb); + int err = ipmr_cache_unresolved(net, vif, skb); read_unlock(&mrt_lock); return err; @@ -1490,6 +1513,7 @@ static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen) { struct net_device *reg_dev = NULL; struct iphdr *encap; + struct net *net = dev_net(skb->dev); encap = (struct iphdr *)(skb_transport_header(skb) + pimlen); /* @@ -1504,8 +1528,8 @@ static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen) return 1; read_lock(&mrt_lock); - if (init_net.ipv4.mroute_reg_vif_num >= 0) - reg_dev = init_net.ipv4.vif_table[init_net.ipv4.mroute_reg_vif_num].dev; + if (net->ipv4.mroute_reg_vif_num >= 0) + reg_dev = net->ipv4.vif_table[net->ipv4.mroute_reg_vif_num].dev; if (reg_dev) dev_hold(reg_dev); read_unlock(&mrt_lock); @@ -1540,13 +1564,14 @@ static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen) int pim_rcv_v1(struct sk_buff * skb) { struct igmphdr *pim; + struct net *net = dev_net(skb->dev); if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(struct iphdr))) goto drop; pim = igmp_hdr(skb); - if (!init_net.ipv4.mroute_do_pim || + if (!net->ipv4.mroute_do_pim || pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER) goto drop; @@ -1586,7 +1611,8 @@ ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm) { int ct; struct rtnexthop *nhp; - struct net_device *dev = init_net.ipv4.vif_table[c->mfc_parent].dev; + struct net *net = mfc_net(c); + struct net_device *dev = net->ipv4.vif_table[c->mfc_parent].dev; u8 *b = skb_tail_pointer(skb); struct rtattr *mp_head; @@ -1602,7 +1628,7 @@ ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm) nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp))); nhp->rtnh_flags = 0; nhp->rtnh_hops = c->mfc_un.res.ttls[ct]; - nhp->rtnh_ifindex = init_net.ipv4.vif_table[ct].dev->ifindex; + nhp->rtnh_ifindex = net->ipv4.vif_table[ct].dev->ifindex; nhp->rtnh_len = sizeof(*nhp); } } @@ -1616,14 +1642,15 @@ rtattr_failure: return -EMSGSIZE; } -int ipmr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait) +int ipmr_get_route(struct net *net, + struct sk_buff *skb, struct rtmsg *rtm, int nowait) { int err; struct mfc_cache *cache; struct rtable *rt = skb->rtable; read_lock(&mrt_lock); - cache = ipmr_cache_find(rt->rt_src, rt->rt_dst); + cache = ipmr_cache_find(net, rt->rt_src, rt->rt_dst); if (cache == NULL) { struct sk_buff *skb2; @@ -1654,7 +1681,7 @@ int ipmr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait) iph->saddr = rt->rt_src; iph->daddr = rt->rt_dst; iph->version = 0; - err = ipmr_cache_unresolved(vif, skb2); + err = ipmr_cache_unresolved(net, vif, skb2); read_unlock(&mrt_lock); return err; } diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 97f71153584..6a9e204c802 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2779,7 +2779,8 @@ int ip_route_output_key(struct net *net, struct rtable **rp, struct flowi *flp) return ip_route_output_flow(net, rp, flp, NULL, 0); } -static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, +static int rt_fill_info(struct net *net, + struct sk_buff *skb, u32 pid, u32 seq, int event, int nowait, unsigned int flags) { struct rtable *rt = skb->rtable; @@ -2844,8 +2845,8 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, __be32 dst = rt->rt_dst; if (ipv4_is_multicast(dst) && !ipv4_is_local_multicast(dst) && - IPV4_DEVCONF_ALL(&init_net, MC_FORWARDING)) { - int err = ipmr_get_route(skb, r, nowait); + IPV4_DEVCONF_ALL(net, MC_FORWARDING)) { + int err = ipmr_get_route(net, skb, r, nowait); if (err <= 0) { if (!nowait) { if (err == 0) @@ -2950,7 +2951,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void if (rtm->rtm_flags & RTM_F_NOTIFY) rt->rt_flags |= RTCF_NOTIFY; - err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, + err = rt_fill_info(net, skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, RTM_NEWROUTE, 0, 0); if (err <= 0) goto errout_free; @@ -2988,7 +2989,7 @@ int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb) if (rt_is_expired(rt)) continue; skb->dst = dst_clone(&rt->u.dst); - if (rt_fill_info(skb, NETLINK_CB(cb->skb).pid, + if (rt_fill_info(net, skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, RTM_NEWROUTE, 1, NLM_F_MULTI) <= 0) { dst_release(xchg(&skb->dst, NULL)); -- GitLab From 5ef3041e4a7cd817bc5ebbb0e5e956a2bdd32c38 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 22 Jan 2009 14:06:25 -0800 Subject: [PATCH 0396/4982] au1000: reorder functions This patch reorders functions so that we do longer need forward declarations. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/au1000_eth.c | 1139 +++++++++++++++++++------------------- 1 file changed, 559 insertions(+), 580 deletions(-) diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index 9c875bb3f76..6d76ccb8e29 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -81,24 +81,6 @@ MODULE_AUTHOR(DRV_AUTHOR); MODULE_DESCRIPTION(DRV_DESC); MODULE_LICENSE("GPL"); -// prototypes -static void hard_stop(struct net_device *); -static void enable_rx_tx(struct net_device *dev); -static struct net_device * au1000_probe(int port_num); -static int au1000_init(struct net_device *); -static int au1000_open(struct net_device *); -static int au1000_close(struct net_device *); -static int au1000_tx(struct sk_buff *, struct net_device *); -static int au1000_rx(struct net_device *); -static irqreturn_t au1000_interrupt(int, void *); -static void au1000_tx_timeout(struct net_device *); -static void set_rx_mode(struct net_device *); -static int au1000_ioctl(struct net_device *, struct ifreq *, int); -static int au1000_mdio_read(struct net_device *, int, int); -static void au1000_mdio_write(struct net_device *, int, int, u16); -static void au1000_adjust_link(struct net_device *); -static void enable_mac(struct net_device *, int); - /* * Theory of operation * @@ -188,6 +170,26 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES]; # error MAC0-associated PHY attached 2nd MACs MII bus not supported yet #endif +static void enable_mac(struct net_device *dev, int force_reset) +{ + unsigned long flags; + struct au1000_private *aup = netdev_priv(dev); + + spin_lock_irqsave(&aup->lock, flags); + + if(force_reset || (!aup->mac_enabled)) { + *aup->enable = MAC_EN_CLOCK_ENABLE; + au_sync_delay(2); + *aup->enable = (MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2 + | MAC_EN_CLOCK_ENABLE); + au_sync_delay(2); + + aup->mac_enabled = 1; + } + + spin_unlock_irqrestore(&aup->lock, flags); +} + /* * MII operations */ @@ -281,6 +283,107 @@ static int au1000_mdiobus_reset(struct mii_bus *bus) return 0; } +static void hard_stop(struct net_device *dev) +{ + struct au1000_private *aup = netdev_priv(dev); + + if (au1000_debug > 4) + printk(KERN_INFO "%s: hard stop\n", dev->name); + + aup->mac->control &= ~(MAC_RX_ENABLE | MAC_TX_ENABLE); + au_sync_delay(10); +} + +static void enable_rx_tx(struct net_device *dev) +{ + struct au1000_private *aup = netdev_priv(dev); + + if (au1000_debug > 4) + printk(KERN_INFO "%s: enable_rx_tx\n", dev->name); + + aup->mac->control |= (MAC_RX_ENABLE | MAC_TX_ENABLE); + au_sync_delay(10); +} + +static void +au1000_adjust_link(struct net_device *dev) +{ + struct au1000_private *aup = netdev_priv(dev); + struct phy_device *phydev = aup->phy_dev; + unsigned long flags; + + int status_change = 0; + + BUG_ON(!aup->phy_dev); + + spin_lock_irqsave(&aup->lock, flags); + + if (phydev->link && (aup->old_speed != phydev->speed)) { + // speed changed + + switch(phydev->speed) { + case SPEED_10: + case SPEED_100: + break; + default: + printk(KERN_WARNING + "%s: Speed (%d) is not 10/100 ???\n", + dev->name, phydev->speed); + break; + } + + aup->old_speed = phydev->speed; + + status_change = 1; + } + + if (phydev->link && (aup->old_duplex != phydev->duplex)) { + // duplex mode changed + + /* switching duplex mode requires to disable rx and tx! */ + hard_stop(dev); + + if (DUPLEX_FULL == phydev->duplex) + aup->mac->control = ((aup->mac->control + | MAC_FULL_DUPLEX) + & ~MAC_DISABLE_RX_OWN); + else + aup->mac->control = ((aup->mac->control + & ~MAC_FULL_DUPLEX) + | MAC_DISABLE_RX_OWN); + au_sync_delay(1); + + enable_rx_tx(dev); + aup->old_duplex = phydev->duplex; + + status_change = 1; + } + + if(phydev->link != aup->old_link) { + // link state changed + + if (!phydev->link) { + /* link went down */ + aup->old_speed = 0; + aup->old_duplex = -1; + } + + aup->old_link = phydev->link; + status_change = 1; + } + + spin_unlock_irqrestore(&aup->lock, flags); + + if (status_change) { + if (phydev->link) + printk(KERN_INFO "%s: link up (%d/%s)\n", + dev->name, phydev->speed, + DUPLEX_FULL == phydev->duplex ? "Full" : "Half"); + else + printk(KERN_INFO "%s: link down\n", dev->name); + } +} + static int mii_probe (struct net_device *dev) { struct au1000_private *const aup = netdev_priv(dev); @@ -412,48 +515,6 @@ void ReleaseDB(struct au1000_private *aup, db_dest_t *pDB) aup->pDBfree = pDB; } -static void enable_rx_tx(struct net_device *dev) -{ - struct au1000_private *aup = netdev_priv(dev); - - if (au1000_debug > 4) - printk(KERN_INFO "%s: enable_rx_tx\n", dev->name); - - aup->mac->control |= (MAC_RX_ENABLE | MAC_TX_ENABLE); - au_sync_delay(10); -} - -static void hard_stop(struct net_device *dev) -{ - struct au1000_private *aup = netdev_priv(dev); - - if (au1000_debug > 4) - printk(KERN_INFO "%s: hard stop\n", dev->name); - - aup->mac->control &= ~(MAC_RX_ENABLE | MAC_TX_ENABLE); - au_sync_delay(10); -} - -static void enable_mac(struct net_device *dev, int force_reset) -{ - unsigned long flags; - struct au1000_private *aup = netdev_priv(dev); - - spin_lock_irqsave(&aup->lock, flags); - - if(force_reset || (!aup->mac_enabled)) { - *aup->enable = MAC_EN_CLOCK_ENABLE; - au_sync_delay(2); - *aup->enable = (MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2 - | MAC_EN_CLOCK_ENABLE); - au_sync_delay(2); - - aup->mac_enabled = 1; - } - - spin_unlock_irqrestore(&aup->lock, flags); -} - static void reset_mac_unlocked(struct net_device *dev) { struct au1000_private *const aup = netdev_priv(dev); @@ -541,30 +602,6 @@ static struct { static int num_ifs; -/* - * Setup the base address and interrupt of the Au1xxx ethernet macs - * based on cpu type and whether the interface is enabled in sys_pinfunc - * register. The last interface is enabled if SYS_PF_NI2 (bit 4) is 0. - */ -static int __init au1000_init_module(void) -{ - int ni = (int)((au_readl(SYS_PINFUNC) & (u32)(SYS_PF_NI2)) >> 4); - struct net_device *dev; - int i, found_one = 0; - - num_ifs = NUM_ETH_INTERFACES - ni; - - for(i = 0; i < num_ifs; i++) { - dev = au1000_probe(i); - iflist[i].dev = dev; - if (dev) - found_one++; - } - if (!found_one) - return -ENODEV; - return 0; -} - /* * ethtool operations */ @@ -611,336 +648,230 @@ static const struct ethtool_ops au1000_ethtool_ops = { .get_link = ethtool_op_get_link, }; -static struct net_device * au1000_probe(int port_num) + +/* + * Initialize the interface. + * + * When the device powers up, the clocks are disabled and the + * mac is in reset state. When the interface is closed, we + * do the same -- reset the device and disable the clocks to + * conserve power. Thus, whenever au1000_init() is called, + * the device should already be in reset state. + */ +static int au1000_init(struct net_device *dev) { - static unsigned version_printed = 0; - struct au1000_private *aup = NULL; - struct net_device *dev = NULL; - db_dest_t *pDB, *pDBfree; - char ethaddr[6]; - int irq, i, err; - u32 base, macen; + struct au1000_private *aup = netdev_priv(dev); + unsigned long flags; + int i; + u32 control; - if (port_num >= NUM_ETH_INTERFACES) - return NULL; + if (au1000_debug > 4) + printk("%s: au1000_init\n", dev->name); - base = CPHYSADDR(iflist[port_num].base_addr ); - macen = CPHYSADDR(iflist[port_num].macen_addr); - irq = iflist[port_num].irq; + /* bring the device out of reset */ + enable_mac(dev, 1); - if (!request_mem_region( base, MAC_IOSIZE, "Au1x00 ENET") || - !request_mem_region(macen, 4, "Au1x00 ENET")) - return NULL; + spin_lock_irqsave(&aup->lock, flags); - if (version_printed++ == 0) - printk("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR); + aup->mac->control = 0; + aup->tx_head = (aup->tx_dma_ring[0]->buff_stat & 0xC) >> 2; + aup->tx_tail = aup->tx_head; + aup->rx_head = (aup->rx_dma_ring[0]->buff_stat & 0xC) >> 2; - dev = alloc_etherdev(sizeof(struct au1000_private)); - if (!dev) { - printk(KERN_ERR "%s: alloc_etherdev failed\n", DRV_NAME); - return NULL; + aup->mac->mac_addr_high = dev->dev_addr[5]<<8 | dev->dev_addr[4]; + aup->mac->mac_addr_low = dev->dev_addr[3]<<24 | dev->dev_addr[2]<<16 | + dev->dev_addr[1]<<8 | dev->dev_addr[0]; + + for (i = 0; i < NUM_RX_DMA; i++) { + aup->rx_dma_ring[i]->buff_stat |= RX_DMA_ENABLE; } + au_sync(); - if ((err = register_netdev(dev)) != 0) { - printk(KERN_ERR "%s: Cannot register net device, error %d\n", - DRV_NAME, err); - free_netdev(dev); - return NULL; + control = MAC_RX_ENABLE | MAC_TX_ENABLE; +#ifndef CONFIG_CPU_LITTLE_ENDIAN + control |= MAC_BIG_ENDIAN; +#endif + if (aup->phy_dev) { + if (aup->phy_dev->link && (DUPLEX_FULL == aup->phy_dev->duplex)) + control |= MAC_FULL_DUPLEX; + else + control |= MAC_DISABLE_RX_OWN; + } else { /* PHY-less op, assume full-duplex */ + control |= MAC_FULL_DUPLEX; } - printk("%s: Au1xx0 Ethernet found at 0x%x, irq %d\n", - dev->name, base, irq); - - aup = netdev_priv(dev); - - spin_lock_init(&aup->lock); - - /* Allocate the data buffers */ - /* Snooping works fine with eth on all au1xxx */ - aup->vaddr = (u32)dma_alloc_noncoherent(NULL, MAX_BUF_SIZE * - (NUM_TX_BUFFS + NUM_RX_BUFFS), - &aup->dma_addr, 0); - if (!aup->vaddr) { - free_netdev(dev); - release_mem_region( base, MAC_IOSIZE); - release_mem_region(macen, 4); - return NULL; - } - - /* aup->mac is the base address of the MAC's registers */ - aup->mac = (volatile mac_reg_t *)iflist[port_num].base_addr; - - /* Setup some variables for quick register address access */ - aup->enable = (volatile u32 *)iflist[port_num].macen_addr; - aup->mac_id = port_num; - au_macs[port_num] = aup; - - if (port_num == 0) { - if (prom_get_ethernet_addr(ethaddr) == 0) - memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr)); - else { - printk(KERN_INFO "%s: No MAC address found\n", - dev->name); - /* Use the hard coded MAC addresses */ - } - - setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR); - } else if (port_num == 1) - setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR); - - /* - * Assign to the Ethernet ports two consecutive MAC addresses - * to match those that are printed on their stickers - */ - memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr)); - dev->dev_addr[5] += port_num; - - *aup->enable = 0; - aup->mac_enabled = 0; - - aup->mii_bus = mdiobus_alloc(); - if (aup->mii_bus == NULL) - goto err_out; - - aup->mii_bus->priv = dev; - aup->mii_bus->read = au1000_mdiobus_read; - aup->mii_bus->write = au1000_mdiobus_write; - aup->mii_bus->reset = au1000_mdiobus_reset; - aup->mii_bus->name = "au1000_eth_mii"; - snprintf(aup->mii_bus->id, MII_BUS_ID_SIZE, "%x", aup->mac_id); - aup->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); - for(i = 0; i < PHY_MAX_ADDR; ++i) - aup->mii_bus->irq[i] = PHY_POLL; - - /* if known, set corresponding PHY IRQs */ -#if defined(AU1XXX_PHY_STATIC_CONFIG) -# if defined(AU1XXX_PHY0_IRQ) - if (AU1XXX_PHY0_BUSID == aup->mac_id) - aup->mii_bus->irq[AU1XXX_PHY0_ADDR] = AU1XXX_PHY0_IRQ; -# endif -# if defined(AU1XXX_PHY1_IRQ) - if (AU1XXX_PHY1_BUSID == aup->mac_id) - aup->mii_bus->irq[AU1XXX_PHY1_ADDR] = AU1XXX_PHY1_IRQ; -# endif -#endif - mdiobus_register(aup->mii_bus); - - if (mii_probe(dev) != 0) { - goto err_out; - } - - pDBfree = NULL; - /* setup the data buffer descriptors and attach a buffer to each one */ - pDB = aup->db; - for (i = 0; i < (NUM_TX_BUFFS+NUM_RX_BUFFS); i++) { - pDB->pnext = pDBfree; - pDBfree = pDB; - pDB->vaddr = (u32 *)((unsigned)aup->vaddr + MAX_BUF_SIZE*i); - pDB->dma_addr = (dma_addr_t)virt_to_bus(pDB->vaddr); - pDB++; - } - aup->pDBfree = pDBfree; - - for (i = 0; i < NUM_RX_DMA; i++) { - pDB = GetFreeDB(aup); - if (!pDB) { - goto err_out; - } - aup->rx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr; - aup->rx_db_inuse[i] = pDB; - } - for (i = 0; i < NUM_TX_DMA; i++) { - pDB = GetFreeDB(aup); - if (!pDB) { - goto err_out; - } - aup->tx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr; - aup->tx_dma_ring[i]->len = 0; - aup->tx_db_inuse[i] = pDB; - } + aup->mac->control = control; + aup->mac->vlan1_tag = 0x8100; /* activate vlan support */ + au_sync(); - dev->base_addr = base; - dev->irq = irq; - dev->open = au1000_open; - dev->hard_start_xmit = au1000_tx; - dev->stop = au1000_close; - dev->set_multicast_list = &set_rx_mode; - dev->do_ioctl = &au1000_ioctl; - SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops); - dev->tx_timeout = au1000_tx_timeout; - dev->watchdog_timeo = ETH_TX_TIMEOUT; + spin_unlock_irqrestore(&aup->lock, flags); + return 0; +} - /* - * The boot code uses the ethernet controller, so reset it to start - * fresh. au1000_init() expects that the device is in reset state. - */ - reset_mac(dev); +static inline void update_rx_stats(struct net_device *dev, u32 status) +{ + struct au1000_private *aup = netdev_priv(dev); + struct net_device_stats *ps = &dev->stats; - return dev; + ps->rx_packets++; + if (status & RX_MCAST_FRAME) + ps->multicast++; -err_out: - if (aup->mii_bus != NULL) { - mdiobus_unregister(aup->mii_bus); - mdiobus_free(aup->mii_bus); + if (status & RX_ERROR) { + ps->rx_errors++; + if (status & RX_MISSED_FRAME) + ps->rx_missed_errors++; + if (status & (RX_OVERLEN | RX_OVERLEN | RX_LEN_ERROR)) + ps->rx_length_errors++; + if (status & RX_CRC_ERROR) + ps->rx_crc_errors++; + if (status & RX_COLL) + ps->collisions++; } + else + ps->rx_bytes += status & RX_FRAME_LEN_MASK; - /* here we should have a valid dev plus aup-> register addresses - * so we can reset the mac properly.*/ - reset_mac(dev); - - for (i = 0; i < NUM_RX_DMA; i++) { - if (aup->rx_db_inuse[i]) - ReleaseDB(aup, aup->rx_db_inuse[i]); - } - for (i = 0; i < NUM_TX_DMA; i++) { - if (aup->tx_db_inuse[i]) - ReleaseDB(aup, aup->tx_db_inuse[i]); - } - dma_free_noncoherent(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS), - (void *)aup->vaddr, aup->dma_addr); - unregister_netdev(dev); - free_netdev(dev); - release_mem_region( base, MAC_IOSIZE); - release_mem_region(macen, 4); - return NULL; } /* - * Initialize the interface. - * - * When the device powers up, the clocks are disabled and the - * mac is in reset state. When the interface is closed, we - * do the same -- reset the device and disable the clocks to - * conserve power. Thus, whenever au1000_init() is called, - * the device should already be in reset state. + * Au1000 receive routine. */ -static int au1000_init(struct net_device *dev) +static int au1000_rx(struct net_device *dev) { struct au1000_private *aup = netdev_priv(dev); - unsigned long flags; - int i; - u32 control; - - if (au1000_debug > 4) - printk("%s: au1000_init\n", dev->name); - - /* bring the device out of reset */ - enable_mac(dev, 1); - - spin_lock_irqsave(&aup->lock, flags); + struct sk_buff *skb; + volatile rx_dma_t *prxd; + u32 buff_stat, status; + db_dest_t *pDB; + u32 frmlen; - aup->mac->control = 0; - aup->tx_head = (aup->tx_dma_ring[0]->buff_stat & 0xC) >> 2; - aup->tx_tail = aup->tx_head; - aup->rx_head = (aup->rx_dma_ring[0]->buff_stat & 0xC) >> 2; + if (au1000_debug > 5) + printk("%s: au1000_rx head %d\n", dev->name, aup->rx_head); - aup->mac->mac_addr_high = dev->dev_addr[5]<<8 | dev->dev_addr[4]; - aup->mac->mac_addr_low = dev->dev_addr[3]<<24 | dev->dev_addr[2]<<16 | - dev->dev_addr[1]<<8 | dev->dev_addr[0]; + prxd = aup->rx_dma_ring[aup->rx_head]; + buff_stat = prxd->buff_stat; + while (buff_stat & RX_T_DONE) { + status = prxd->status; + pDB = aup->rx_db_inuse[aup->rx_head]; + update_rx_stats(dev, status); + if (!(status & RX_ERROR)) { - for (i = 0; i < NUM_RX_DMA; i++) { - aup->rx_dma_ring[i]->buff_stat |= RX_DMA_ENABLE; - } - au_sync(); + /* good frame */ + frmlen = (status & RX_FRAME_LEN_MASK); + frmlen -= 4; /* Remove FCS */ + skb = dev_alloc_skb(frmlen + 2); + if (skb == NULL) { + printk(KERN_ERR + "%s: Memory squeeze, dropping packet.\n", + dev->name); + dev->stats.rx_dropped++; + continue; + } + skb_reserve(skb, 2); /* 16 byte IP header align */ + skb_copy_to_linear_data(skb, + (unsigned char *)pDB->vaddr, frmlen); + skb_put(skb, frmlen); + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); /* pass the packet to upper layers */ + } + else { + if (au1000_debug > 4) { + if (status & RX_MISSED_FRAME) + printk("rx miss\n"); + if (status & RX_WDOG_TIMER) + printk("rx wdog\n"); + if (status & RX_RUNT) + printk("rx runt\n"); + if (status & RX_OVERLEN) + printk("rx overlen\n"); + if (status & RX_COLL) + printk("rx coll\n"); + if (status & RX_MII_ERROR) + printk("rx mii error\n"); + if (status & RX_CRC_ERROR) + printk("rx crc error\n"); + if (status & RX_LEN_ERROR) + printk("rx len error\n"); + if (status & RX_U_CNTRL_FRAME) + printk("rx u control frame\n"); + if (status & RX_MISSED_FRAME) + printk("rx miss\n"); + } + } + prxd->buff_stat = (u32)(pDB->dma_addr | RX_DMA_ENABLE); + aup->rx_head = (aup->rx_head + 1) & (NUM_RX_DMA - 1); + au_sync(); - control = MAC_RX_ENABLE | MAC_TX_ENABLE; -#ifndef CONFIG_CPU_LITTLE_ENDIAN - control |= MAC_BIG_ENDIAN; -#endif - if (aup->phy_dev) { - if (aup->phy_dev->link && (DUPLEX_FULL == aup->phy_dev->duplex)) - control |= MAC_FULL_DUPLEX; - else - control |= MAC_DISABLE_RX_OWN; - } else { /* PHY-less op, assume full-duplex */ - control |= MAC_FULL_DUPLEX; + /* next descriptor */ + prxd = aup->rx_dma_ring[aup->rx_head]; + buff_stat = prxd->buff_stat; } - - aup->mac->control = control; - aup->mac->vlan1_tag = 0x8100; /* activate vlan support */ - au_sync(); - - spin_unlock_irqrestore(&aup->lock, flags); return 0; } -static void -au1000_adjust_link(struct net_device *dev) +static void update_tx_stats(struct net_device *dev, u32 status) { struct au1000_private *aup = netdev_priv(dev); - struct phy_device *phydev = aup->phy_dev; - unsigned long flags; - - int status_change = 0; - - BUG_ON(!aup->phy_dev); - - spin_lock_irqsave(&aup->lock, flags); - - if (phydev->link && (aup->old_speed != phydev->speed)) { - // speed changed + struct net_device_stats *ps = &dev->stats; - switch(phydev->speed) { - case SPEED_10: - case SPEED_100: - break; - default: - printk(KERN_WARNING - "%s: Speed (%d) is not 10/100 ???\n", - dev->name, phydev->speed); - break; + if (status & TX_FRAME_ABORTED) { + if (!aup->phy_dev || (DUPLEX_FULL == aup->phy_dev->duplex)) { + if (status & (TX_JAB_TIMEOUT | TX_UNDERRUN)) { + /* any other tx errors are only valid + * in half duplex mode */ + ps->tx_errors++; + ps->tx_aborted_errors++; + } } + else { + ps->tx_errors++; + ps->tx_aborted_errors++; + if (status & (TX_NO_CARRIER | TX_LOSS_CARRIER)) + ps->tx_carrier_errors++; + } + } +} - aup->old_speed = phydev->speed; - - status_change = 1; - } - - if (phydev->link && (aup->old_duplex != phydev->duplex)) { - // duplex mode changed - - /* switching duplex mode requires to disable rx and tx! */ - hard_stop(dev); - - if (DUPLEX_FULL == phydev->duplex) - aup->mac->control = ((aup->mac->control - | MAC_FULL_DUPLEX) - & ~MAC_DISABLE_RX_OWN); - else - aup->mac->control = ((aup->mac->control - & ~MAC_FULL_DUPLEX) - | MAC_DISABLE_RX_OWN); - au_sync_delay(1); - - enable_rx_tx(dev); - aup->old_duplex = phydev->duplex; +/* + * Called from the interrupt service routine to acknowledge + * the TX DONE bits. This is a must if the irq is setup as + * edge triggered. + */ +static void au1000_tx_ack(struct net_device *dev) +{ + struct au1000_private *aup = netdev_priv(dev); + volatile tx_dma_t *ptxd; - status_change = 1; - } + ptxd = aup->tx_dma_ring[aup->tx_tail]; - if(phydev->link != aup->old_link) { - // link state changed + while (ptxd->buff_stat & TX_T_DONE) { + update_tx_stats(dev, ptxd->status); + ptxd->buff_stat &= ~TX_T_DONE; + ptxd->len = 0; + au_sync(); - if (!phydev->link) { - /* link went down */ - aup->old_speed = 0; - aup->old_duplex = -1; - } + aup->tx_tail = (aup->tx_tail + 1) & (NUM_TX_DMA - 1); + ptxd = aup->tx_dma_ring[aup->tx_tail]; - aup->old_link = phydev->link; - status_change = 1; + if (aup->tx_full) { + aup->tx_full = 0; + netif_wake_queue(dev); + } } +} - spin_unlock_irqrestore(&aup->lock, flags); +/* + * Au1000 interrupt service routine. + */ +static irqreturn_t au1000_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; - if (status_change) { - if (phydev->link) - printk(KERN_INFO "%s: link up (%d/%s)\n", - dev->name, phydev->speed, - DUPLEX_FULL == phydev->duplex ? "Full" : "Half"); - else - printk(KERN_INFO "%s: link down\n", dev->name); - } + /* Handle RX interrupts first to minimize chance of overrun */ + + au1000_rx(dev); + au1000_tx_ack(dev); + return IRQ_RETVAL(1); } static int au1000_open(struct net_device *dev) @@ -1003,88 +934,6 @@ static int au1000_close(struct net_device *dev) return 0; } -static void __exit au1000_cleanup_module(void) -{ - int i, j; - struct net_device *dev; - struct au1000_private *aup; - - for (i = 0; i < num_ifs; i++) { - dev = iflist[i].dev; - if (dev) { - aup = netdev_priv(dev); - unregister_netdev(dev); - mdiobus_unregister(aup->mii_bus); - mdiobus_free(aup->mii_bus); - for (j = 0; j < NUM_RX_DMA; j++) - if (aup->rx_db_inuse[j]) - ReleaseDB(aup, aup->rx_db_inuse[j]); - for (j = 0; j < NUM_TX_DMA; j++) - if (aup->tx_db_inuse[j]) - ReleaseDB(aup, aup->tx_db_inuse[j]); - dma_free_noncoherent(NULL, MAX_BUF_SIZE * - (NUM_TX_BUFFS + NUM_RX_BUFFS), - (void *)aup->vaddr, aup->dma_addr); - release_mem_region(dev->base_addr, MAC_IOSIZE); - release_mem_region(CPHYSADDR(iflist[i].macen_addr), 4); - free_netdev(dev); - } - } -} - -static void update_tx_stats(struct net_device *dev, u32 status) -{ - struct au1000_private *aup = netdev_priv(dev); - struct net_device_stats *ps = &dev->stats; - - if (status & TX_FRAME_ABORTED) { - if (!aup->phy_dev || (DUPLEX_FULL == aup->phy_dev->duplex)) { - if (status & (TX_JAB_TIMEOUT | TX_UNDERRUN)) { - /* any other tx errors are only valid - * in half duplex mode */ - ps->tx_errors++; - ps->tx_aborted_errors++; - } - } - else { - ps->tx_errors++; - ps->tx_aborted_errors++; - if (status & (TX_NO_CARRIER | TX_LOSS_CARRIER)) - ps->tx_carrier_errors++; - } - } -} - - -/* - * Called from the interrupt service routine to acknowledge - * the TX DONE bits. This is a must if the irq is setup as - * edge triggered. - */ -static void au1000_tx_ack(struct net_device *dev) -{ - struct au1000_private *aup = netdev_priv(dev); - volatile tx_dma_t *ptxd; - - ptxd = aup->tx_dma_ring[aup->tx_tail]; - - while (ptxd->buff_stat & TX_T_DONE) { - update_tx_stats(dev, ptxd->status); - ptxd->buff_stat &= ~TX_T_DONE; - ptxd->len = 0; - au_sync(); - - aup->tx_tail = (aup->tx_tail + 1) & (NUM_TX_DMA - 1); - ptxd = aup->tx_dma_ring[aup->tx_tail]; - - if (aup->tx_full) { - aup->tx_full = 0; - netif_wake_queue(dev); - } - } -} - - /* * Au1000 transmit routine. */ @@ -1129,136 +978,19 @@ static int au1000_tx(struct sk_buff *skb, struct net_device *dev) ptxd->len = ETH_ZLEN; } else - ptxd->len = skb->len; - - ps->tx_packets++; - ps->tx_bytes += ptxd->len; - - ptxd->buff_stat = pDB->dma_addr | TX_DMA_ENABLE; - au_sync(); - dev_kfree_skb(skb); - aup->tx_head = (aup->tx_head + 1) & (NUM_TX_DMA - 1); - dev->trans_start = jiffies; - return 0; -} - -static inline void update_rx_stats(struct net_device *dev, u32 status) -{ - struct au1000_private *aup = netdev_priv(dev); - struct net_device_stats *ps = &dev->stats; - - ps->rx_packets++; - if (status & RX_MCAST_FRAME) - ps->multicast++; - - if (status & RX_ERROR) { - ps->rx_errors++; - if (status & RX_MISSED_FRAME) - ps->rx_missed_errors++; - if (status & (RX_OVERLEN | RX_OVERLEN | RX_LEN_ERROR)) - ps->rx_length_errors++; - if (status & RX_CRC_ERROR) - ps->rx_crc_errors++; - if (status & RX_COLL) - ps->collisions++; - } - else - ps->rx_bytes += status & RX_FRAME_LEN_MASK; - -} - -/* - * Au1000 receive routine. - */ -static int au1000_rx(struct net_device *dev) -{ - struct au1000_private *aup = netdev_priv(dev); - struct sk_buff *skb; - volatile rx_dma_t *prxd; - u32 buff_stat, status; - db_dest_t *pDB; - u32 frmlen; - - if (au1000_debug > 5) - printk("%s: au1000_rx head %d\n", dev->name, aup->rx_head); - - prxd = aup->rx_dma_ring[aup->rx_head]; - buff_stat = prxd->buff_stat; - while (buff_stat & RX_T_DONE) { - status = prxd->status; - pDB = aup->rx_db_inuse[aup->rx_head]; - update_rx_stats(dev, status); - if (!(status & RX_ERROR)) { - - /* good frame */ - frmlen = (status & RX_FRAME_LEN_MASK); - frmlen -= 4; /* Remove FCS */ - skb = dev_alloc_skb(frmlen + 2); - if (skb == NULL) { - printk(KERN_ERR - "%s: Memory squeeze, dropping packet.\n", - dev->name); - dev->stats.rx_dropped++; - continue; - } - skb_reserve(skb, 2); /* 16 byte IP header align */ - skb_copy_to_linear_data(skb, - (unsigned char *)pDB->vaddr, frmlen); - skb_put(skb, frmlen); - skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); /* pass the packet to upper layers */ - } - else { - if (au1000_debug > 4) { - if (status & RX_MISSED_FRAME) - printk("rx miss\n"); - if (status & RX_WDOG_TIMER) - printk("rx wdog\n"); - if (status & RX_RUNT) - printk("rx runt\n"); - if (status & RX_OVERLEN) - printk("rx overlen\n"); - if (status & RX_COLL) - printk("rx coll\n"); - if (status & RX_MII_ERROR) - printk("rx mii error\n"); - if (status & RX_CRC_ERROR) - printk("rx crc error\n"); - if (status & RX_LEN_ERROR) - printk("rx len error\n"); - if (status & RX_U_CNTRL_FRAME) - printk("rx u control frame\n"); - if (status & RX_MISSED_FRAME) - printk("rx miss\n"); - } - } - prxd->buff_stat = (u32)(pDB->dma_addr | RX_DMA_ENABLE); - aup->rx_head = (aup->rx_head + 1) & (NUM_RX_DMA - 1); - au_sync(); - - /* next descriptor */ - prxd = aup->rx_dma_ring[aup->rx_head]; - buff_stat = prxd->buff_stat; - } - return 0; -} - - -/* - * Au1000 interrupt service routine. - */ -static irqreturn_t au1000_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; + ptxd->len = skb->len; - /* Handle RX interrupts first to minimize chance of overrun */ + ps->tx_packets++; + ps->tx_bytes += ptxd->len; - au1000_rx(dev); - au1000_tx_ack(dev); - return IRQ_RETVAL(1); + ptxd->buff_stat = pDB->dma_addr | TX_DMA_ENABLE; + au_sync(); + dev_kfree_skb(skb); + aup->tx_head = (aup->tx_head + 1) & (NUM_TX_DMA - 1); + dev->trans_start = jiffies; + return 0; } - /* * The Tx ring has been full longer than the watchdog timeout * value. The transmitter must be hung? @@ -1315,5 +1047,252 @@ static int au1000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return phy_mii_ioctl(aup->phy_dev, if_mii(rq), cmd); } +static struct net_device * au1000_probe(int port_num) +{ + static unsigned version_printed = 0; + struct au1000_private *aup = NULL; + struct net_device *dev = NULL; + db_dest_t *pDB, *pDBfree; + char ethaddr[6]; + int irq, i, err; + u32 base, macen; + + if (port_num >= NUM_ETH_INTERFACES) + return NULL; + + base = CPHYSADDR(iflist[port_num].base_addr ); + macen = CPHYSADDR(iflist[port_num].macen_addr); + irq = iflist[port_num].irq; + + if (!request_mem_region( base, MAC_IOSIZE, "Au1x00 ENET") || + !request_mem_region(macen, 4, "Au1x00 ENET")) + return NULL; + + if (version_printed++ == 0) + printk("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR); + + dev = alloc_etherdev(sizeof(struct au1000_private)); + if (!dev) { + printk(KERN_ERR "%s: alloc_etherdev failed\n", DRV_NAME); + return NULL; + } + + if ((err = register_netdev(dev)) != 0) { + printk(KERN_ERR "%s: Cannot register net device, error %d\n", + DRV_NAME, err); + free_netdev(dev); + return NULL; + } + + printk("%s: Au1xx0 Ethernet found at 0x%x, irq %d\n", + dev->name, base, irq); + + aup = netdev_priv(dev); + + spin_lock_init(&aup->lock); + + /* Allocate the data buffers */ + /* Snooping works fine with eth on all au1xxx */ + aup->vaddr = (u32)dma_alloc_noncoherent(NULL, MAX_BUF_SIZE * + (NUM_TX_BUFFS + NUM_RX_BUFFS), + &aup->dma_addr, 0); + if (!aup->vaddr) { + free_netdev(dev); + release_mem_region( base, MAC_IOSIZE); + release_mem_region(macen, 4); + return NULL; + } + + /* aup->mac is the base address of the MAC's registers */ + aup->mac = (volatile mac_reg_t *)iflist[port_num].base_addr; + + /* Setup some variables for quick register address access */ + aup->enable = (volatile u32 *)iflist[port_num].macen_addr; + aup->mac_id = port_num; + au_macs[port_num] = aup; + + if (port_num == 0) { + if (prom_get_ethernet_addr(ethaddr) == 0) + memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr)); + else { + printk(KERN_INFO "%s: No MAC address found\n", + dev->name); + /* Use the hard coded MAC addresses */ + } + + setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR); + } else if (port_num == 1) + setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR); + + /* + * Assign to the Ethernet ports two consecutive MAC addresses + * to match those that are printed on their stickers + */ + memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr)); + dev->dev_addr[5] += port_num; + + *aup->enable = 0; + aup->mac_enabled = 0; + + aup->mii_bus = mdiobus_alloc(); + if (aup->mii_bus == NULL) + goto err_out; + + aup->mii_bus->priv = dev; + aup->mii_bus->read = au1000_mdiobus_read; + aup->mii_bus->write = au1000_mdiobus_write; + aup->mii_bus->reset = au1000_mdiobus_reset; + aup->mii_bus->name = "au1000_eth_mii"; + snprintf(aup->mii_bus->id, MII_BUS_ID_SIZE, "%x", aup->mac_id); + aup->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); + for(i = 0; i < PHY_MAX_ADDR; ++i) + aup->mii_bus->irq[i] = PHY_POLL; + + /* if known, set corresponding PHY IRQs */ +#if defined(AU1XXX_PHY_STATIC_CONFIG) +# if defined(AU1XXX_PHY0_IRQ) + if (AU1XXX_PHY0_BUSID == aup->mac_id) + aup->mii_bus->irq[AU1XXX_PHY0_ADDR] = AU1XXX_PHY0_IRQ; +# endif +# if defined(AU1XXX_PHY1_IRQ) + if (AU1XXX_PHY1_BUSID == aup->mac_id) + aup->mii_bus->irq[AU1XXX_PHY1_ADDR] = AU1XXX_PHY1_IRQ; +# endif +#endif + mdiobus_register(aup->mii_bus); + + if (mii_probe(dev) != 0) { + goto err_out; + } + + pDBfree = NULL; + /* setup the data buffer descriptors and attach a buffer to each one */ + pDB = aup->db; + for (i = 0; i < (NUM_TX_BUFFS+NUM_RX_BUFFS); i++) { + pDB->pnext = pDBfree; + pDBfree = pDB; + pDB->vaddr = (u32 *)((unsigned)aup->vaddr + MAX_BUF_SIZE*i); + pDB->dma_addr = (dma_addr_t)virt_to_bus(pDB->vaddr); + pDB++; + } + aup->pDBfree = pDBfree; + + for (i = 0; i < NUM_RX_DMA; i++) { + pDB = GetFreeDB(aup); + if (!pDB) { + goto err_out; + } + aup->rx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr; + aup->rx_db_inuse[i] = pDB; + } + for (i = 0; i < NUM_TX_DMA; i++) { + pDB = GetFreeDB(aup); + if (!pDB) { + goto err_out; + } + aup->tx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr; + aup->tx_dma_ring[i]->len = 0; + aup->tx_db_inuse[i] = pDB; + } + + dev->base_addr = base; + dev->irq = irq; + dev->open = au1000_open; + dev->hard_start_xmit = au1000_tx; + dev->stop = au1000_close; + dev->set_multicast_list = &set_rx_mode; + dev->do_ioctl = &au1000_ioctl; + SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops); + dev->tx_timeout = au1000_tx_timeout; + dev->watchdog_timeo = ETH_TX_TIMEOUT; + + /* + * The boot code uses the ethernet controller, so reset it to start + * fresh. au1000_init() expects that the device is in reset state. + */ + reset_mac(dev); + + return dev; + +err_out: + if (aup->mii_bus != NULL) { + mdiobus_unregister(aup->mii_bus); + mdiobus_free(aup->mii_bus); + } + + /* here we should have a valid dev plus aup-> register addresses + * so we can reset the mac properly.*/ + reset_mac(dev); + + for (i = 0; i < NUM_RX_DMA; i++) { + if (aup->rx_db_inuse[i]) + ReleaseDB(aup, aup->rx_db_inuse[i]); + } + for (i = 0; i < NUM_TX_DMA; i++) { + if (aup->tx_db_inuse[i]) + ReleaseDB(aup, aup->tx_db_inuse[i]); + } + dma_free_noncoherent(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS), + (void *)aup->vaddr, aup->dma_addr); + unregister_netdev(dev); + free_netdev(dev); + release_mem_region( base, MAC_IOSIZE); + release_mem_region(macen, 4); + return NULL; +} + +/* + * Setup the base address and interrupt of the Au1xxx ethernet macs + * based on cpu type and whether the interface is enabled in sys_pinfunc + * register. The last interface is enabled if SYS_PF_NI2 (bit 4) is 0. + */ +static int __init au1000_init_module(void) +{ + int ni = (int)((au_readl(SYS_PINFUNC) & (u32)(SYS_PF_NI2)) >> 4); + struct net_device *dev; + int i, found_one = 0; + + num_ifs = NUM_ETH_INTERFACES - ni; + + for(i = 0; i < num_ifs; i++) { + dev = au1000_probe(i); + iflist[i].dev = dev; + if (dev) + found_one++; + } + if (!found_one) + return -ENODEV; + return 0; +} + +static void __exit au1000_cleanup_module(void) +{ + int i, j; + struct net_device *dev; + struct au1000_private *aup; + + for (i = 0; i < num_ifs; i++) { + dev = iflist[i].dev; + if (dev) { + aup = netdev_priv(dev); + unregister_netdev(dev); + mdiobus_unregister(aup->mii_bus); + mdiobus_free(aup->mii_bus); + for (j = 0; j < NUM_RX_DMA; j++) + if (aup->rx_db_inuse[j]) + ReleaseDB(aup, aup->rx_db_inuse[j]); + for (j = 0; j < NUM_TX_DMA; j++) + if (aup->tx_db_inuse[j]) + ReleaseDB(aup, aup->tx_db_inuse[j]); + dma_free_noncoherent(NULL, MAX_BUF_SIZE * + (NUM_TX_BUFFS + NUM_RX_BUFFS), + (void *)aup->vaddr, aup->dma_addr); + release_mem_region(dev->base_addr, MAC_IOSIZE); + release_mem_region(CPHYSADDR(iflist[i].macen_addr), 4); + free_netdev(dev); + } + } +} + module_init(au1000_init_module); module_exit(au1000_cleanup_module); -- GitLab From ab897d2013128f470240a541b31cf5e636984e71 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 22 Jan 2009 14:24:16 -0800 Subject: [PATCH 0397/4982] x86/pvops: remove pte_flags pvop pte_flags() was introduced as a new pvop in order to extract just the flags portion of a pte, which is a potentially cheaper operation than extracting the page number as well. It turns out this operation is not needed, because simply using a mask to extract the flags from a pte is sufficient for all current users. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/include/asm/page.h | 3 +-- arch/x86/include/asm/paravirt.h | 18 ------------------ arch/x86/kernel/paravirt.c | 1 - arch/x86/xen/enlighten.c | 1 - 4 files changed, 1 insertion(+), 22 deletions(-) diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h index e9873a2e869..6b9810859da 100644 --- a/arch/x86/include/asm/page.h +++ b/arch/x86/include/asm/page.h @@ -147,7 +147,7 @@ static inline pteval_t native_pte_val(pte_t pte) return pte.pte; } -static inline pteval_t native_pte_flags(pte_t pte) +static inline pteval_t pte_flags(pte_t pte) { return native_pte_val(pte) & PTE_FLAGS_MASK; } @@ -173,7 +173,6 @@ static inline pteval_t native_pte_flags(pte_t pte) #endif #define pte_val(x) native_pte_val(x) -#define pte_flags(x) native_pte_flags(x) #define __pte(x) native_make_pte(x) #endif /* CONFIG_PARAVIRT */ diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index ba3e2ff6aed..e25c410f3d8 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -279,7 +279,6 @@ struct pv_mmu_ops { pte_t *ptep, pte_t pte); pteval_t (*pte_val)(pte_t); - pteval_t (*pte_flags)(pte_t); pte_t (*make_pte)(pteval_t pte); pgdval_t (*pgd_val)(pgd_t); @@ -1084,23 +1083,6 @@ static inline pteval_t pte_val(pte_t pte) return ret; } -static inline pteval_t pte_flags(pte_t pte) -{ - pteval_t ret; - - if (sizeof(pteval_t) > sizeof(long)) - ret = PVOP_CALL2(pteval_t, pv_mmu_ops.pte_flags, - pte.pte, (u64)pte.pte >> 32); - else - ret = PVOP_CALL1(pteval_t, pv_mmu_ops.pte_flags, - pte.pte); - -#ifdef CONFIG_PARAVIRT_DEBUG - BUG_ON(ret & PTE_PFN_MASK); -#endif - return ret; -} - static inline pgd_t __pgd(pgdval_t val) { pgdval_t ret; diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index e4c8fb60887..202514be592 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -435,7 +435,6 @@ struct pv_mmu_ops pv_mmu_ops = { #endif /* PAGETABLE_LEVELS >= 3 */ .pte_val = native_pte_val, - .pte_flags = native_pte_flags, .pgd_val = native_pgd_val, .make_pte = native_make_pte, diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index bea215230b2..6f1bb71aa13 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1314,7 +1314,6 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = { .ptep_modify_prot_commit = __ptep_modify_prot_commit, .pte_val = xen_pte_val, - .pte_flags = native_pte_flags, .pgd_val = xen_pgd_val, .make_pte = xen_make_pte, -- GitLab From 6522869c34664dd5f05a0a327e93915b1281c90d Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 22 Jan 2009 14:24:22 -0800 Subject: [PATCH 0398/4982] x86: add pte_set_flags/clear_flags for pte flag manipulation It's not necessary to deconstruct and reconstruct a pte every time its flags are being updated. Introduce pte_set_flags and pte_clear_flags to set and clear flags in a pte. This allows the flag manipulation code to be inlined, and avoids calls via paravirt-ops. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/include/asm/pgtable.h | 38 +++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 06bbcbd66e9..6ceaef08486 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -240,64 +240,78 @@ static inline int pmd_large(pmd_t pte) (_PAGE_PSE | _PAGE_PRESENT); } +static inline pte_t pte_set_flags(pte_t pte, pteval_t set) +{ + pteval_t v = native_pte_val(pte); + + return native_make_pte(v | set); +} + +static inline pte_t pte_clear_flags(pte_t pte, pteval_t clear) +{ + pteval_t v = native_pte_val(pte); + + return native_make_pte(v & ~clear); +} + static inline pte_t pte_mkclean(pte_t pte) { - return __pte(pte_val(pte) & ~_PAGE_DIRTY); + return pte_clear_flags(pte, _PAGE_DIRTY); } static inline pte_t pte_mkold(pte_t pte) { - return __pte(pte_val(pte) & ~_PAGE_ACCESSED); + return pte_clear_flags(pte, _PAGE_ACCESSED); } static inline pte_t pte_wrprotect(pte_t pte) { - return __pte(pte_val(pte) & ~_PAGE_RW); + return pte_clear_flags(pte, _PAGE_RW); } static inline pte_t pte_mkexec(pte_t pte) { - return __pte(pte_val(pte) & ~_PAGE_NX); + return pte_clear_flags(pte, _PAGE_NX); } static inline pte_t pte_mkdirty(pte_t pte) { - return __pte(pte_val(pte) | _PAGE_DIRTY); + return pte_set_flags(pte, _PAGE_DIRTY); } static inline pte_t pte_mkyoung(pte_t pte) { - return __pte(pte_val(pte) | _PAGE_ACCESSED); + return pte_set_flags(pte, _PAGE_ACCESSED); } static inline pte_t pte_mkwrite(pte_t pte) { - return __pte(pte_val(pte) | _PAGE_RW); + return pte_set_flags(pte, _PAGE_RW); } static inline pte_t pte_mkhuge(pte_t pte) { - return __pte(pte_val(pte) | _PAGE_PSE); + return pte_set_flags(pte, _PAGE_PSE); } static inline pte_t pte_clrhuge(pte_t pte) { - return __pte(pte_val(pte) & ~_PAGE_PSE); + return pte_clear_flags(pte, _PAGE_PSE); } static inline pte_t pte_mkglobal(pte_t pte) { - return __pte(pte_val(pte) | _PAGE_GLOBAL); + return pte_set_flags(pte, _PAGE_GLOBAL); } static inline pte_t pte_clrglobal(pte_t pte) { - return __pte(pte_val(pte) & ~_PAGE_GLOBAL); + return pte_clear_flags(pte, _PAGE_GLOBAL); } static inline pte_t pte_mkspecial(pte_t pte) { - return __pte(pte_val(pte) | _PAGE_SPECIAL); + return pte_set_flags(pte, _PAGE_SPECIAL); } extern pteval_t __supported_pte_mask; -- GitLab From 03d2989df9c1c7df5b33c7a87e0790465461836a Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Fri, 23 Jan 2009 11:03:28 +0900 Subject: [PATCH 0399/4982] x86: remove idle_timestamp from 32bit irq_cpustat_t Impact: bogus irq_cpustat field removed idle_timestamp is left over from the removed irqbalance code. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/hardirq_32.h | 1 - arch/x86/kernel/process_32.c | 1 - 2 files changed, 2 deletions(-) diff --git a/arch/x86/include/asm/hardirq_32.h b/arch/x86/include/asm/hardirq_32.h index d4b5d731073..a70ed050fde 100644 --- a/arch/x86/include/asm/hardirq_32.h +++ b/arch/x86/include/asm/hardirq_32.h @@ -6,7 +6,6 @@ typedef struct { unsigned int __softirq_pending; - unsigned long idle_timestamp; unsigned int __nmi_count; /* arch dependent */ unsigned int apic_timer_irqs; /* arch dependent */ unsigned int irq0_irqs; diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 2c00a57ccb9..1a1ae8edc40 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -108,7 +108,6 @@ void cpu_idle(void) play_dead(); local_irq_disable(); - __get_cpu_var(irq_stat).idle_timestamp = jiffies; /* Don't trace irqs off for idle */ stop_critical_timings(); pm_idle(); -- GitLab From 3819cd489ec5d18a4cbd2f05acdc516473caa105 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Fri, 23 Jan 2009 11:03:29 +0900 Subject: [PATCH 0400/4982] x86: remove include of apic.h from hardirq_64.h Impact: cleanup APIC definitions aren't needed here. Remove the include and fix up the fallout. tj: added include to mce_intel_64.c. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/hardirq_64.h | 1 - arch/x86/kernel/cpu/mcheck/mce_intel_64.c | 1 + arch/x86/kernel/efi_64.c | 1 + arch/x86/kernel/irq_64.c | 1 + 4 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/hardirq_64.h b/arch/x86/include/asm/hardirq_64.h index a65bab20f6c..873c3c7bffc 100644 --- a/arch/x86/include/asm/hardirq_64.h +++ b/arch/x86/include/asm/hardirq_64.h @@ -3,7 +3,6 @@ #include #include -#include typedef struct { unsigned int __softirq_pending; diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c index 4b48f251fd3..5e8c79e748a 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/x86/kernel/efi_64.c b/arch/x86/kernel/efi_64.c index 652c5287215..a4ee29127fd 100644 --- a/arch/x86/kernel/efi_64.c +++ b/arch/x86/kernel/efi_64.c @@ -36,6 +36,7 @@ #include #include #include +#include static pgd_t save_pgd __initdata; static unsigned long efi_flags __initdata; diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index 0b254de8408..018963aa6ee 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c @@ -18,6 +18,7 @@ #include #include #include +#include DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); EXPORT_PER_CPU_SYMBOL(irq_stat); -- GitLab From 658a9a2c34914e8114eea9c4d85d4ecd3ee33b98 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Fri, 23 Jan 2009 11:03:31 +0900 Subject: [PATCH 0401/4982] x86: sync hardirq_{32,64}.h Impact: better code generation and removal of unused field for 32bit In general, use the 64-bit version. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/hardirq_32.h | 14 ++++++++++---- arch/x86/include/asm/hardirq_64.h | 10 +++++----- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/arch/x86/include/asm/hardirq_32.h b/arch/x86/include/asm/hardirq_32.h index a70ed050fde..e5a332c28c9 100644 --- a/arch/x86/include/asm/hardirq_32.h +++ b/arch/x86/include/asm/hardirq_32.h @@ -14,6 +14,7 @@ typedef struct { unsigned int irq_tlb_count; unsigned int irq_thermal_count; unsigned int irq_spurious_count; + unsigned int irq_threshold_count; } ____cacheline_aligned irq_cpustat_t; DECLARE_PER_CPU(irq_cpustat_t, irq_stat); @@ -22,11 +23,16 @@ DECLARE_PER_CPU(irq_cpustat_t, irq_stat); #define MAX_HARDIRQS_PER_CPU NR_VECTORS #define __ARCH_IRQ_STAT -#define __IRQ_STAT(cpu, member) (per_cpu(irq_stat, cpu).member) -#define inc_irq_stat(member) (__get_cpu_var(irq_stat).member++) +#define inc_irq_stat(member) percpu_add(irq_stat.member, 1) -void ack_bad_irq(unsigned int irq); -#include +#define local_softirq_pending() percpu_read(irq_stat.__softirq_pending) + +#define __ARCH_SET_SOFTIRQ_PENDING + +#define set_softirq_pending(x) percpu_write(irq_stat.__softirq_pending, (x)) +#define or_softirq_pending(x) percpu_or(irq_stat.__softirq_pending, (x)) + +extern void ack_bad_irq(unsigned int irq); #endif /* _ASM_X86_HARDIRQ_32_H */ diff --git a/arch/x86/include/asm/hardirq_64.h b/arch/x86/include/asm/hardirq_64.h index 873c3c7bffc..392e7d61457 100644 --- a/arch/x86/include/asm/hardirq_64.h +++ b/arch/x86/include/asm/hardirq_64.h @@ -22,16 +22,16 @@ DECLARE_PER_CPU(irq_cpustat_t, irq_stat); /* We can have at most NR_VECTORS irqs routed to a cpu at a time */ #define MAX_HARDIRQS_PER_CPU NR_VECTORS -#define __ARCH_IRQ_STAT 1 +#define __ARCH_IRQ_STAT #define inc_irq_stat(member) percpu_add(irq_stat.member, 1) -#define local_softirq_pending() percpu_read(irq_stat.__softirq_pending) +#define local_softirq_pending() percpu_read(irq_stat.__softirq_pending) -#define __ARCH_SET_SOFTIRQ_PENDING 1 +#define __ARCH_SET_SOFTIRQ_PENDING -#define set_softirq_pending(x) percpu_write(irq_stat.__softirq_pending, (x)) -#define or_softirq_pending(x) percpu_or(irq_stat.__softirq_pending, (x)) +#define set_softirq_pending(x) percpu_write(irq_stat.__softirq_pending, (x)) +#define or_softirq_pending(x) percpu_or(irq_stat.__softirq_pending, (x)) extern void ack_bad_irq(unsigned int irq); -- GitLab From 22da7b3df3a2e26a87a8581575dbf26e465a6ac7 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Fri, 23 Jan 2009 11:03:31 +0900 Subject: [PATCH 0402/4982] x86: merge hardirq_{32,64}.h into hardirq.h Impact: cleanup Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/hardirq.h | 43 +++++++++++++++++++++++++++---- arch/x86/include/asm/hardirq_32.h | 38 --------------------------- arch/x86/include/asm/hardirq_64.h | 38 --------------------------- 3 files changed, 38 insertions(+), 81 deletions(-) delete mode 100644 arch/x86/include/asm/hardirq_32.h delete mode 100644 arch/x86/include/asm/hardirq_64.h diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h index 000787df66e..f4a95f20f8e 100644 --- a/arch/x86/include/asm/hardirq.h +++ b/arch/x86/include/asm/hardirq.h @@ -1,11 +1,44 @@ -#ifdef CONFIG_X86_32 -# include "hardirq_32.h" -#else -# include "hardirq_64.h" -#endif +#ifndef _ASM_X86_HARDIRQ_H +#define _ASM_X86_HARDIRQ_H + +#include +#include + +typedef struct { + unsigned int __softirq_pending; + unsigned int __nmi_count; /* arch dependent */ + unsigned int apic_timer_irqs; /* arch dependent */ + unsigned int irq0_irqs; + unsigned int irq_resched_count; + unsigned int irq_call_count; + unsigned int irq_tlb_count; + unsigned int irq_thermal_count; + unsigned int irq_spurious_count; + unsigned int irq_threshold_count; +} ____cacheline_aligned irq_cpustat_t; + +DECLARE_PER_CPU(irq_cpustat_t, irq_stat); + +/* We can have at most NR_VECTORS irqs routed to a cpu at a time */ +#define MAX_HARDIRQS_PER_CPU NR_VECTORS + +#define __ARCH_IRQ_STAT + +#define inc_irq_stat(member) percpu_add(irq_stat.member, 1) + +#define local_softirq_pending() percpu_read(irq_stat.__softirq_pending) + +#define __ARCH_SET_SOFTIRQ_PENDING + +#define set_softirq_pending(x) percpu_write(irq_stat.__softirq_pending, (x)) +#define or_softirq_pending(x) percpu_or(irq_stat.__softirq_pending, (x)) + +extern void ack_bad_irq(unsigned int irq); extern u64 arch_irq_stat_cpu(unsigned int cpu); #define arch_irq_stat_cpu arch_irq_stat_cpu extern u64 arch_irq_stat(void); #define arch_irq_stat arch_irq_stat + +#endif /* _ASM_X86_HARDIRQ_H */ diff --git a/arch/x86/include/asm/hardirq_32.h b/arch/x86/include/asm/hardirq_32.h deleted file mode 100644 index e5a332c28c9..00000000000 --- a/arch/x86/include/asm/hardirq_32.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef _ASM_X86_HARDIRQ_32_H -#define _ASM_X86_HARDIRQ_32_H - -#include -#include - -typedef struct { - unsigned int __softirq_pending; - unsigned int __nmi_count; /* arch dependent */ - unsigned int apic_timer_irqs; /* arch dependent */ - unsigned int irq0_irqs; - unsigned int irq_resched_count; - unsigned int irq_call_count; - unsigned int irq_tlb_count; - unsigned int irq_thermal_count; - unsigned int irq_spurious_count; - unsigned int irq_threshold_count; -} ____cacheline_aligned irq_cpustat_t; - -DECLARE_PER_CPU(irq_cpustat_t, irq_stat); - -/* We can have at most NR_VECTORS irqs routed to a cpu at a time */ -#define MAX_HARDIRQS_PER_CPU NR_VECTORS - -#define __ARCH_IRQ_STAT - -#define inc_irq_stat(member) percpu_add(irq_stat.member, 1) - -#define local_softirq_pending() percpu_read(irq_stat.__softirq_pending) - -#define __ARCH_SET_SOFTIRQ_PENDING - -#define set_softirq_pending(x) percpu_write(irq_stat.__softirq_pending, (x)) -#define or_softirq_pending(x) percpu_or(irq_stat.__softirq_pending, (x)) - -extern void ack_bad_irq(unsigned int irq); - -#endif /* _ASM_X86_HARDIRQ_32_H */ diff --git a/arch/x86/include/asm/hardirq_64.h b/arch/x86/include/asm/hardirq_64.h deleted file mode 100644 index 392e7d61457..00000000000 --- a/arch/x86/include/asm/hardirq_64.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef _ASM_X86_HARDIRQ_64_H -#define _ASM_X86_HARDIRQ_64_H - -#include -#include - -typedef struct { - unsigned int __softirq_pending; - unsigned int __nmi_count; /* arch dependent */ - unsigned int apic_timer_irqs; /* arch dependent */ - unsigned int irq0_irqs; - unsigned int irq_resched_count; - unsigned int irq_call_count; - unsigned int irq_tlb_count; - unsigned int irq_thermal_count; - unsigned int irq_spurious_count; - unsigned int irq_threshold_count; -} ____cacheline_aligned irq_cpustat_t; - -DECLARE_PER_CPU(irq_cpustat_t, irq_stat); - -/* We can have at most NR_VECTORS irqs routed to a cpu at a time */ -#define MAX_HARDIRQS_PER_CPU NR_VECTORS - -#define __ARCH_IRQ_STAT - -#define inc_irq_stat(member) percpu_add(irq_stat.member, 1) - -#define local_softirq_pending() percpu_read(irq_stat.__softirq_pending) - -#define __ARCH_SET_SOFTIRQ_PENDING - -#define set_softirq_pending(x) percpu_write(irq_stat.__softirq_pending, (x)) -#define or_softirq_pending(x) percpu_or(irq_stat.__softirq_pending, (x)) - -extern void ack_bad_irq(unsigned int irq); - -#endif /* _ASM_X86_HARDIRQ_64_H */ -- GitLab From 2de3a5f7956eb81447feea3aec68193ddd8534bb Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Fri, 23 Jan 2009 11:03:32 +0900 Subject: [PATCH 0403/4982] x86: make irq_cpustat_t fields conditional Impact: shrink size of irq_cpustat_t when possible Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/hardirq.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h index f4a95f20f8e..176f058e715 100644 --- a/arch/x86/include/asm/hardirq.h +++ b/arch/x86/include/asm/hardirq.h @@ -7,14 +7,22 @@ typedef struct { unsigned int __softirq_pending; unsigned int __nmi_count; /* arch dependent */ - unsigned int apic_timer_irqs; /* arch dependent */ unsigned int irq0_irqs; +#ifdef CONFIG_X86_LOCAL_APIC + unsigned int apic_timer_irqs; /* arch dependent */ + unsigned int irq_spurious_count; +#endif +#ifdef CONFIG_SMP unsigned int irq_resched_count; unsigned int irq_call_count; unsigned int irq_tlb_count; +#endif +#ifdef CONFIG_X86_MCE unsigned int irq_thermal_count; - unsigned int irq_spurious_count; +# ifdef CONFIG_X86_64 unsigned int irq_threshold_count; +# endif +#endif } ____cacheline_aligned irq_cpustat_t; DECLARE_PER_CPU(irq_cpustat_t, irq_stat); -- GitLab From fd8757aed16470e088ecdad96ffd30f86c34424d Mon Sep 17 00:00:00 2001 From: Matthew Ranostay Date: Wed, 21 Jan 2009 17:45:12 -0500 Subject: [PATCH 0404/4982] Add PCI DFI vendor ID Add a define for DFI PCI vendor id. Signed-off-by: Matthew Ranostay Signed-off-by: Takashi Iwai --- include/linux/pci_ids.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index d543365518a..6b339766b7a 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2106,6 +2106,8 @@ #define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c #define PCI_DEVICE_ID_MELLANOX_SINAI 0x6274 +#define PCI_VENDOR_ID_DFI 0x15bd + #define PCI_VENDOR_ID_QUICKNET 0x15e2 #define PCI_DEVICE_ID_QUICKNET_XJ 0x0500 -- GitLab From 577aa2c195045599275b54356969ae19f34e7a66 Mon Sep 17 00:00:00 2001 From: Matthew Ranostay Date: Thu, 22 Jan 2009 22:55:44 -0500 Subject: [PATCH 0405/4982] ALSA: hda: add reference board SND_PCI_QUIRK Add another LanParty reference board SND_PCI_QUIRK to quirk lists of all codec families. Signed-off-by: Matthew Ranostay Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 212d8c09a67..3fbe22053b3 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1517,6 +1517,8 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = { /* SigmaTel reference board */ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_REF), + SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, + "DFI LanParty", STAC_REF), /* Dell laptops have BIOS problem */ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a8, "unknown Dell", STAC_9200_DELL_D21), @@ -1666,6 +1668,7 @@ static struct snd_pci_quirk stac925x_codec_id_cfg_tbl[] = { static struct snd_pci_quirk stac925x_cfg_tbl[] = { /* SigmaTel reference board */ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_REF), + SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, "DFI LanParty", STAC_REF), SND_PCI_QUIRK(0x8384, 0x7632, "Stac9202 Reference Board", STAC_REF), /* Default table for unknown ID */ @@ -1709,6 +1712,8 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { /* SigmaTel reference board */ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_92HD73XX_REF), + SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, + "DFI LanParty", STAC_92HD73XX_REF), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254, "Dell Studio 1535", STAC_DELL_M6_DMIC), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255, @@ -1753,6 +1758,8 @@ static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { /* SigmaTel reference board */ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_92HD83XXX_REF), + SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, + "DFI LanParty", STAC_92HD83XXX_REF), {} /* terminator */ }; @@ -1802,6 +1809,8 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { /* SigmaTel reference board */ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_92HD71BXX_REF), + SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, + "DFI LanParty", STAC_92HD71BXX_REF), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f2, "HP dv5", STAC_HP_M4), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f4, @@ -1992,6 +2001,8 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = { /* SigmaTel reference board */ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_D945_REF), + SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, + "DFI LanParty", STAC_D945_REF), /* Intel 945G based systems */ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0101, "Intel D945G", STAC_D945GTP3), @@ -2148,6 +2159,8 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = { /* SigmaTel reference board */ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_D965_REF), + SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, + "DFI LanParty", STAC_D965_REF), /* Intel 946 based systems */ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x3d01, "Intel D946", STAC_D965_3ST), SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xa301, "Intel D946", STAC_D965_3ST), @@ -2259,6 +2272,8 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = { /* SigmaTel reference board */ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_9205_REF), + SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, + "DFI LanParty", STAC_9205_REF), /* Dell */ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1, "unknown Dell", STAC_9205_DELL_M42), -- GitLab From 92af3e95e4896452ab33b1841c3e9a9d50658064 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Mon, 19 Jan 2009 14:17:08 +0000 Subject: [PATCH 0406/4982] e1000e: drop lltx, remove unnecessary lock LLTX is deprecated and complicated, don't use it. It was observed by Don Ash that e1000e was acquiring this lock in the NAPI cleanup path. This is obviously a bug, as this is a leftover from when e1000 supported multiple tx queues and fake netdevs. another user reported this to us and tested routing with the 2.6.27 kernel and this patch and reported a 3.5 % improvement in packets forwarded in a multi-port test on 82571 parts. Signed-off-by: Jesse Brandeburg Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/e1000.h | 2 -- drivers/net/e1000e/netdev.c | 34 +++------------------------------- 2 files changed, 3 insertions(+), 33 deletions(-) diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index 37bcb190eef..28bf9a51346 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -195,8 +195,6 @@ struct e1000_adapter { u16 link_duplex; u16 eeprom_vers; - spinlock_t tx_queue_lock; /* prevent concurrent tail updates */ - /* track device up/down/testing state */ unsigned long state; diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 2ffd7523a91..e04b392c9a5 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -47,7 +47,7 @@ #include "e1000.h" -#define DRV_VERSION "0.3.3.3-k6" +#define DRV_VERSION "0.3.3.4-k2" char e1000e_driver_name[] = "e1000e"; const char e1000e_driver_version[] = DRV_VERSION; @@ -1698,7 +1698,6 @@ int e1000e_setup_tx_resources(struct e1000_adapter *adapter) tx_ring->next_to_use = 0; tx_ring->next_to_clean = 0; - spin_lock_init(&adapter->tx_queue_lock); return 0; err: @@ -2007,16 +2006,7 @@ static int e1000_clean(struct napi_struct *napi, int budget) !(adapter->rx_ring->ims_val & adapter->tx_ring->ims_val)) goto clean_rx; - /* - * e1000_clean is called per-cpu. This lock protects - * tx_ring from being cleaned by multiple cpus - * simultaneously. A failure obtaining the lock means - * tx_ring is currently being cleaned anyway. - */ - if (spin_trylock(&adapter->tx_queue_lock)) { - tx_cleaned = e1000_clean_tx_irq(adapter); - spin_unlock(&adapter->tx_queue_lock); - } + tx_cleaned = e1000_clean_tx_irq(adapter); clean_rx: adapter->clean_rx(adapter, &work_done, budget); @@ -2922,8 +2912,6 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter) if (e1000_alloc_queues(adapter)) return -ENOMEM; - spin_lock_init(&adapter->tx_queue_lock); - /* Explicitly disable IRQ since the NIC can be in any state. */ e1000_irq_disable(adapter); @@ -4069,7 +4057,6 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) unsigned int max_txd_pwr = E1000_MAX_TXD_PWR; unsigned int tx_flags = 0; unsigned int len = skb->len - skb->data_len; - unsigned long irq_flags; unsigned int nr_frags; unsigned int mss; int count = 0; @@ -4138,18 +4125,12 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if (adapter->hw.mac.tx_pkt_filtering) e1000_transfer_dhcp_info(adapter, skb); - if (!spin_trylock_irqsave(&adapter->tx_queue_lock, irq_flags)) - /* Collision - tell upper layer to requeue */ - return NETDEV_TX_LOCKED; - /* * need: count + 2 desc gap to keep tail from touching * head, otherwise try next time */ - if (e1000_maybe_stop_tx(netdev, count + 2)) { - spin_unlock_irqrestore(&adapter->tx_queue_lock, irq_flags); + if (e1000_maybe_stop_tx(netdev, count + 2)) return NETDEV_TX_BUSY; - } if (adapter->vlgrp && vlan_tx_tag_present(skb)) { tx_flags |= E1000_TX_FLAGS_VLAN; @@ -4161,7 +4142,6 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) tso = e1000_tso(adapter, skb); if (tso < 0) { dev_kfree_skb_any(skb); - spin_unlock_irqrestore(&adapter->tx_queue_lock, irq_flags); return NETDEV_TX_OK; } @@ -4182,7 +4162,6 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if (count < 0) { /* handle pci_map_single() error in e1000_tx_map */ dev_kfree_skb_any(skb); - spin_unlock_irqrestore(&adapter->tx_queue_lock, irq_flags); return NETDEV_TX_OK; } @@ -4193,7 +4172,6 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) /* Make sure there is space in the ring for the next send. */ e1000_maybe_stop_tx(netdev, MAX_SKB_FRAGS + 2); - spin_unlock_irqrestore(&adapter->tx_queue_lock, irq_flags); return NETDEV_TX_OK; } @@ -4922,12 +4900,6 @@ static int __devinit e1000_probe(struct pci_dev *pdev, if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; - /* - * We should not be using LLTX anymore, but we are still Tx faster with - * it. - */ - netdev->features |= NETIF_F_LLTX; - if (e1000e_enable_mng_pass_thru(&adapter->hw)) adapter->flags |= FLAG_MNG_PT_ENABLED; -- GitLab From 8056d47e77a0f7e3c99c114deab4859d31496075 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 23 Jan 2009 09:09:43 +0100 Subject: [PATCH 0407/4982] ALSA: hda - Add model=ref for Intel board with STAC9221 An intel board (8086:0204) works only with model=ref. Reference: Novell bug #406529 https://bugzilla.novell.com/show_bug.cgi?id=406529 Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 3fbe22053b3..4ee9f7fc772 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -2056,6 +2056,9 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = { "Intel D945P", STAC_D945GTP3), SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0707, "Intel D945P", STAC_D945GTP5), + /* other intel */ + SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0204, + "Intel D945", STAC_D945_REF), /* other systems */ /* Apple Intel Mac (Mac Mini, MacBook, MacBook Pro...) */ SND_PCI_QUIRK(0x8384, 0x7680, -- GitLab From 99d0000f710f3432182761f65f9658f1cf0bf455 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 23 Jan 2009 11:09:15 +0100 Subject: [PATCH 0408/4982] x86, xen: fix hardirq.h merge fallout Impact: build fix This build error: arch/x86/xen/suspend.c:22: error: implicit declaration of function 'fix_to_virt' arch/x86/xen/suspend.c:22: error: 'FIX_PARAVIRT_BOOTMAP' undeclared (first use in this function) arch/x86/xen/suspend.c:22: error: (Each undeclared identifier is reported only once arch/x86/xen/suspend.c:22: error: for each function it appears in.) triggers because the hardirq.h unification removed an implicit fixmap.h include - on which arch/x86/xen/suspend.c depended. Add the fixmap.h include explicitly. Signed-off-by: Ingo Molnar --- arch/x86/xen/suspend.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c index 212ffe012b7..95be7b43472 100644 --- a/arch/x86/xen/suspend.c +++ b/arch/x86/xen/suspend.c @@ -6,6 +6,7 @@ #include #include +#include #include "xen-ops.h" #include "mmu.h" -- GitLab From e3c75964666a27cec46d2cccf2d9806336becd48 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 23 Jan 2009 11:57:22 +0100 Subject: [PATCH 0409/4982] ALSA: hda - Create "Input Source" control dynamically for STAC/IDT Instead of fixed kcontrol_new element, build "Input Source" controls dynamically. If the number of input-source items is 0 or 1, we don't need to create such a control. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 78 +++++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 25 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index b3c3a02a422..80a4c288b31 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -958,16 +958,6 @@ static struct hda_verb stac9205_core_init[] = { .private_value = HDA_COMPOSE_AMP_VAL(nid, chs, idx, dir) \ } -#define STAC_INPUT_SOURCE(cnt) \ - { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = "Input Source", \ - .count = cnt, \ - .info = stac92xx_mux_enum_info, \ - .get = stac92xx_mux_enum_get, \ - .put = stac92xx_mux_enum_put, \ - } - #define STAC_ANALOG_LOOPBACK(verb_read, verb_write, cnt) \ { \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ @@ -982,7 +972,6 @@ static struct hda_verb stac9205_core_init[] = { static struct snd_kcontrol_new stac9200_mixer[] = { HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), - STAC_INPUT_SOURCE(1), HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), { } /* end */ @@ -1098,7 +1087,6 @@ static struct snd_kcontrol_new stac92hd83xxx_mixer[] = { }; static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = { - STAC_INPUT_SOURCE(2), STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2), HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT), @@ -1127,7 +1115,6 @@ static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = { }; static struct snd_kcontrol_new stac92hd71bxx_mixer[] = { - STAC_INPUT_SOURCE(2), STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2), HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT), @@ -1141,14 +1128,12 @@ static struct snd_kcontrol_new stac92hd71bxx_mixer[] = { static struct snd_kcontrol_new stac925x_mixer[] = { HDA_CODEC_VOLUME("Master Playback Volume", 0x0e, 0, HDA_OUTPUT), HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT), - STAC_INPUT_SOURCE(1), HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT), HDA_CODEC_MUTE("Capture Switch", 0x14, 0, HDA_OUTPUT), { } /* end */ }; static struct snd_kcontrol_new stac9205_mixer[] = { - STAC_INPUT_SOURCE(2), STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0, 1), HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1b, 0x0, HDA_INPUT), @@ -1161,7 +1146,6 @@ static struct snd_kcontrol_new stac9205_mixer[] = { /* This needs to be generated dynamically based on sequence */ static struct snd_kcontrol_new stac922x_mixer[] = { - STAC_INPUT_SOURCE(2), HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_INPUT), HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_INPUT), @@ -1172,7 +1156,6 @@ static struct snd_kcontrol_new stac922x_mixer[] = { static struct snd_kcontrol_new stac927x_mixer[] = { - STAC_INPUT_SOURCE(3), STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB, 1), HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x18, 0x0, HDA_INPUT), @@ -2777,22 +2760,37 @@ static struct snd_kcontrol_new stac92xx_control_templates[] = { }; /* add dynamic controls */ -static int stac92xx_add_control_temp(struct sigmatel_spec *spec, - struct snd_kcontrol_new *ktemp, - int idx, const char *name, - unsigned long val) +static struct snd_kcontrol_new * +stac_control_new(struct sigmatel_spec *spec, + struct snd_kcontrol_new *ktemp, + const char *name) { struct snd_kcontrol_new *knew; snd_array_init(&spec->kctls, sizeof(*knew), 32); knew = snd_array_new(&spec->kctls); if (!knew) - return -ENOMEM; + return NULL; *knew = *ktemp; - knew->index = idx; knew->name = kstrdup(name, GFP_KERNEL); - if (!knew->name) + if (!knew->name) { + /* roolback */ + memset(knew, 0, sizeof(*knew)); + spec->kctls.alloced--; + return NULL; + } + return knew; +} + +static int stac92xx_add_control_temp(struct sigmatel_spec *spec, + struct snd_kcontrol_new *ktemp, + int idx, const char *name, + unsigned long val) +{ + struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name); + if (!knew) return -ENOMEM; + knew->index = idx; knew->private_value = val; return 0; } @@ -2814,6 +2812,29 @@ static inline int stac92xx_add_control(struct sigmatel_spec *spec, int type, return stac92xx_add_control_idx(spec, type, 0, name, val); } +static struct snd_kcontrol_new stac_input_src_temp = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Input Source", + .info = stac92xx_mux_enum_info, + .get = stac92xx_mux_enum_get, + .put = stac92xx_mux_enum_put, +}; + +static int stac92xx_add_input_source(struct sigmatel_spec *spec) +{ + struct snd_kcontrol_new *knew; + struct hda_input_mux *imux = &spec->private_imux; + + if (!spec->num_adcs || imux->num_items <= 1) + return 0; /* no need for input source control */ + knew = stac_control_new(spec, &stac_input_src_temp, + stac_input_src_temp.name); + if (!knew) + return -ENOMEM; + knew->count = spec->num_adcs; + return 0; +} + /* check whether the line-input can be used as line-out */ static hda_nid_t check_line_out_switch(struct hda_codec *codec) { @@ -3699,6 +3720,10 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out return err; } + err = stac92xx_add_input_source(spec); + if (err < 0) + return err; + spec->multiout.max_channels = spec->multiout.num_dacs * 2; if (spec->multiout.max_channels > 2) spec->surr_switch = 1; @@ -3812,6 +3837,10 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) return err; } + err = stac92xx_add_input_source(spec); + if (err < 0) + return err; + if (spec->autocfg.dig_out_pin) spec->multiout.dig_out_nid = 0x05; if (spec->autocfg.dig_in_pin) @@ -5426,7 +5455,6 @@ static struct hda_verb stac9872_core_init[] = { static struct snd_kcontrol_new stac9872_mixer[] = { HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), - STAC_INPUT_SOURCE(1), { } /* end */ }; -- GitLab From ff637d38ea6b9c54f708a2b9edabc1b0c73c6d0a Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Thu, 22 Jan 2009 18:23:39 -0600 Subject: [PATCH 0410/4982] ASoC: remove stand-alone mode support from CS4270 codec driver The CS4270 supports stand-alone mode, where the codec is not connect to the I2C or SPI buses. Instead, input voltages configure the codec at power-on. The CS4270 ASoC device driver has partial support for this mode, but the code was never tested, and partial support doesn't help anyone. It also made the rest of the code more complicated than necessary. [Removed redundant CS4270 dependency on I2C -- broonie] Signed-off-by: Timur Tabi Signed-off-by: Mark Brown --- sound/soc/codecs/cs4270.c | 92 ++++++++++++--------------------------- sound/soc/fsl/Kconfig | 3 +- 2 files changed, 29 insertions(+), 66 deletions(-) diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index f1aa0c34421..2e4ce04925e 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -12,11 +12,7 @@ * * Current features/limitations: * - * 1) Software mode is supported. Stand-alone mode is automatically - * selected if I2C is disabled or if a CS4270 is not found on the I2C - * bus. However, stand-alone mode is only partially implemented because - * there is no mechanism yet for this driver and the machine driver to - * communicate the values of the M0, M1, MCLK1, and MCLK2 pins. + * 1) Software mode is supported. Stand-alone mode is not supported. * 2) Only I2C is supported, not SPI * 3) Only Master mode is supported, not Slave. * 4) The machine driver's 'startup' function must call @@ -33,14 +29,6 @@ #include #include -#include "cs4270.h" - -/* If I2C is defined, then we support software mode. However, if we're - not compiled as module but I2C is, then we can't use I2C calls. */ -#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) -#define USE_I2C -#endif - /* Private data for the CS4270 */ struct cs4270_private { unsigned int mclk; /* Input frequency of the MCLK pin */ @@ -60,8 +48,6 @@ struct cs4270_private { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE) -#ifdef USE_I2C - /* CS4270 registers addresses */ #define CS4270_CHIPID 0x01 /* Chip ID */ #define CS4270_PWRCTL 0x02 /* Power Control */ @@ -271,17 +257,6 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai, return ret; } -/* - * A list of addresses on which this CS4270 could use. I2C addresses are - * 7 bits. For the CS4270, the upper four bits are always 1001, and the - * lower three bits are determined via the AD2, AD1, and AD0 pins - * (respectively). - */ -static const unsigned short normal_i2c[] = { - 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, I2C_CLIENT_END -}; -I2C_CLIENT_INSMOD; - /* * Pre-fill the CS4270 register cache. * @@ -476,7 +451,6 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, } #ifdef CONFIG_SND_SOC_CS4270_HWMUTE - /* * Set the CS4270 external mute * @@ -501,32 +475,16 @@ static int cs4270_mute(struct snd_soc_dai *dai, int mute) return snd_soc_write(codec, CS4270_MUTE, reg6); } - +#else +#define cs4270_mute NULL #endif -static int cs4270_i2c_probe(struct i2c_client *, const struct i2c_device_id *); - /* A list of non-DAPM controls that the CS4270 supports */ static const struct snd_kcontrol_new cs4270_snd_controls[] = { SOC_DOUBLE_R("Master Playback Volume", CS4270_VOLA, CS4270_VOLB, 0, 0xFF, 1) }; -static const struct i2c_device_id cs4270_id[] = { - {"cs4270", 0}, - {} -}; -MODULE_DEVICE_TABLE(i2c, cs4270_id); - -static struct i2c_driver cs4270_i2c_driver = { - .driver = { - .name = "CS4270 I2C", - .owner = THIS_MODULE, - }, - .id_table = cs4270_id, - .probe = cs4270_i2c_probe, -}; - /* * Global variable to store socdev for i2c probe function. * @@ -633,7 +591,20 @@ error: return ret; } -#endif /* USE_I2C*/ +static const struct i2c_device_id cs4270_id[] = { + {"cs4270", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, cs4270_id); + +static struct i2c_driver cs4270_i2c_driver = { + .driver = { + .name = "cs4270", + .owner = THIS_MODULE, + }, + .id_table = cs4270_id, + .probe = cs4270_i2c_probe, +}; struct snd_soc_dai cs4270_dai = { .name = "CS4270", @@ -698,7 +669,6 @@ static int cs4270_probe(struct platform_device *pdev) goto error_free_codec; } -#ifdef USE_I2C cs4270_socdev = socdev; ret = i2c_add_driver(&cs4270_i2c_driver); @@ -708,20 +678,16 @@ static int cs4270_probe(struct platform_device *pdev) } /* Did we find a CS4270 on the I2C bus? */ - if (codec->control_data) { - /* Initialize codec ops */ - cs4270_dai.ops.hw_params = cs4270_hw_params; - cs4270_dai.ops.set_sysclk = cs4270_set_dai_sysclk; - cs4270_dai.ops.set_fmt = cs4270_set_dai_fmt; -#ifdef CONFIG_SND_SOC_CS4270_HWMUTE - cs4270_dai.ops.digital_mute = cs4270_mute; -#endif - } else - printk(KERN_INFO "cs4270: no I2C device found, " - "using stand-alone mode\n"); -#else - printk(KERN_INFO "cs4270: I2C disabled, using stand-alone mode\n"); -#endif + if (!codec->control_data) { + printk(KERN_ERR "cs4270: failed to attach driver"); + goto error_del_driver; + } + + /* Initialize codec ops */ + cs4270_dai.ops.hw_params = cs4270_hw_params; + cs4270_dai.ops.set_sysclk = cs4270_set_dai_sysclk; + cs4270_dai.ops.set_fmt = cs4270_set_dai_fmt; + cs4270_dai.ops.digital_mute = cs4270_mute; ret = snd_soc_init_card(socdev); if (ret < 0) { @@ -732,11 +698,9 @@ static int cs4270_probe(struct platform_device *pdev) return 0; error_del_driver: -#ifdef USE_I2C i2c_del_driver(&cs4270_i2c_driver); error_free_pcms: -#endif snd_soc_free_pcms(socdev); error_free_codec: @@ -752,9 +716,7 @@ static int cs4270_remove(struct platform_device *pdev) snd_soc_free_pcms(socdev); -#ifdef USE_I2C i2c_del_driver(&cs4270_i2c_driver); -#endif kfree(socdev->codec); socdev->codec = NULL; diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index c7c78c39cfe..9fc90828337 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -10,7 +10,8 @@ config SND_SOC_MPC8610 config SND_SOC_MPC8610_HPCD tristate "ALSA SoC support for the Freescale MPC8610 HPCD board" - depends on MPC8610_HPCD + # I2C is necessary for the CS4270 driver + depends on MPC8610_HPCD && I2C select SND_SOC_MPC8610 select SND_SOC_CS4270 select SND_SOC_CS4270_VD33_ERRATA -- GitLab From c91cf25ebfbf3a5b336cbaa46646d37dd3d33127 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 23 Jan 2009 11:23:32 +0000 Subject: [PATCH 0411/4982] ASoC: Fix merge with PXA tree Fix a merge issue caused by context overlap. Reported-by: Stephen Rothwell Signed-off-by: Mark Brown --- sound/soc/pxa/e800_wm9712.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c index 78a1770b986..bc019cdce42 100644 --- a/sound/soc/pxa/e800_wm9712.c +++ b/sound/soc/pxa/e800_wm9712.c @@ -18,13 +18,10 @@ #include #include -#include -#include +#include #include #include -#include - #include "../codecs/wm9712.h" #include "pxa2xx-pcm.h" #include "pxa2xx-ac97.h" -- GitLab From 6d6e17de4f64131e9c976fd524d73aaec268178f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 23 Jan 2009 12:33:54 +0100 Subject: [PATCH 0412/4982] ALSA: hda - Fix initial verbs for mic-boosts on AD1981HD The mic boosts (NID 0x08 and 0x18) are input-amps, not output-amps. Fix the initial verbs for them. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_analog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 2e7371ec2e2..9a902c2f05a 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -1407,8 +1407,8 @@ static struct hda_verb ad1981_init_verbs[] = { {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, /* Mic boost: 0dB */ - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* Record selector: Front mic */ {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, -- GitLab From 19a2d3e9b99ffa264adf1138bd8d8aef8909dca9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 23 Jan 2009 12:35:25 +0100 Subject: [PATCH 0413/4982] ALSA: hda - Remove invalid amp initializations for AD1988* codecs The ADC widgets on AD1988* codecs have no amp controls. Remove invalid initialization verbs. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_analog.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 9a902c2f05a..52bc85dd6f5 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -2288,10 +2288,6 @@ static struct hda_verb ad1988_capture_init_verbs[] = { {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, - /* ADCs; muted */ - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, { } }; @@ -2399,10 +2395,6 @@ static struct hda_verb ad1988_3stack_init_verbs[] = { {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, - /* ADCs; muted */ - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Analog Mix output amp */ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ { } @@ -2474,10 +2466,6 @@ static struct hda_verb ad1988_laptop_init_verbs[] = { {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, - /* ADCs; muted */ - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Analog Mix output amp */ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ { } -- GitLab From 60e388e89c9e258a51a0995ddd9e18fdebcdbe12 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 23 Jan 2009 12:37:09 +0100 Subject: [PATCH 0414/4982] ALSA: hda - Fix invalid verbs for mic-boosts on AD1884* The mic-boosts (0x14 and 0x15) on AD1884* codecs are input-amps, not output-amps. Fix the invalid initialization verbs. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_analog.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 52bc85dd6f5..a7298d28a0d 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -3183,10 +3183,10 @@ static struct hda_verb ad1884_init_verbs[] = { {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, /* Port-B (front mic) pin */ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* Port-C (rear mic) pin */ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* Analog mixer; mute as default */ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, @@ -3601,10 +3601,10 @@ static struct hda_verb ad1884a_init_verbs[] = { {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Port-B (front mic) pin */ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* Port-C (rear line-in) pin */ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* Port-E (rear mic) pin */ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, -- GitLab From f6fca2e93c9ad3c704f02aaabe4359a8af16fbbb Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 23 Jan 2009 11:40:26 +0000 Subject: [PATCH 0415/4982] ASoC: Remove unneeded e7x0 inclusion of pxa-regs.h and hardware.h pxa-regs.h and hardware.h are not intended for use directly in driver code and references to them have been removed in other code - remove them from the newly added e740 and e750 machine drivers. Signed-off-by: Mark Brown --- sound/soc/pxa/e740_wm9705.c | 2 -- sound/soc/pxa/e750_wm9705.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c index ac361765173..7cd2f89d7b1 100644 --- a/sound/soc/pxa/e740_wm9705.c +++ b/sound/soc/pxa/e740_wm9705.c @@ -18,8 +18,6 @@ #include #include -#include -#include #include #include diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c index 20fbdcfa9f7..8dceccc5e05 100644 --- a/sound/soc/pxa/e750_wm9705.c +++ b/sound/soc/pxa/e750_wm9705.c @@ -18,8 +18,6 @@ #include #include -#include -#include #include #include -- GitLab From a435869cacbb581920df23411416bed533748bf1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 23 Jan 2009 11:49:45 +0000 Subject: [PATCH 0416/4982] ASoC: Configure SSP port PLL for Zylonite Signed-off-by: Mark Brown --- sound/soc/pxa/zylonite.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index 8541b679f6e..ec2fb764b24 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c @@ -95,6 +95,7 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + unsigned int pll_out = 0; unsigned int acds = 0; unsigned int wm9713_div = 0; int ret = 0; @@ -102,13 +103,16 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, switch (params_rate(params)) { case 8000: wm9713_div = 12; + pll_out = 2048000; break; case 16000: wm9713_div = 6; + pll_out = 4096000; break; case 48000: default: wm9713_div = 2; + pll_out = 12288000; acds = 1; break; } @@ -129,6 +133,10 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; + ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, pll_out); + if (ret < 0) + return ret; + ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_AUDIO_DIV_ACDS, acds); if (ret < 0) return ret; -- GitLab From 4cfb91c6d764b18e81bfb6e6779e07bcecbb197c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 23 Jan 2009 12:53:09 +0100 Subject: [PATCH 0417/4982] ALSA: hda - Fix invalid amp init for ALC268 codec Fix some invalid AMP initializations for ALC268 codecs. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4cfa78c5439..863ab957204 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -11279,19 +11279,13 @@ static void alc267_quanta_il1_unsol_event(struct hda_codec *codec, static struct hda_verb alc268_base_init_verbs[] = { /* Unmute DAC0-1 and set vol = 0 */ {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, /* * Set up output mixers (0x0c - 0x0e) */ /* set vol=0 to output mixers */ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00}, {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, @@ -11310,9 +11304,7 @@ static struct hda_verb alc268_base_init_verbs[] = { {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* set PCBEEP vol = 0, mute connections */ {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, @@ -11334,10 +11326,8 @@ static struct hda_verb alc268_base_init_verbs[] = { */ static struct hda_verb alc268_volume_init_verbs[] = { /* set output DAC */ - {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, + {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, @@ -11345,16 +11335,12 @@ static struct hda_verb alc268_volume_init_verbs[] = { {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* set PCBEEP vol = 0, mute connections */ {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, -- GitLab From 70040c07402ef5a3fad2133daffb7ee61b0d4641 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 23 Jan 2009 14:18:11 +0100 Subject: [PATCH 0418/4982] ALSA: hda - Fix wrong initial verb for AD1984 thinkpad model The docking mic-boost (0x25) has no mute bit. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_analog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index a7298d28a0d..e934e2c187d 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -3337,7 +3337,7 @@ static struct hda_verb ad1984_thinkpad_init_verbs[] = { {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* docking mic boost */ - {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* Analog mixer - docking mic; mute as default */ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* enable EAPD bit */ -- GitLab From 55aef4508598d59c2baea7e2a3e6dfed415bbfc0 Mon Sep 17 00:00:00 2001 From: Markus Bollinger Date: Fri, 23 Jan 2009 14:45:41 +0100 Subject: [PATCH 0419/4982] ALSA: pcxhr - add support for gpio ports and minor bug fix - add support for gpio ports (2 GPI, 2 GPO) of pcxhr stereo cards - minor bugfixes : allow setting clock to internal by the mixer even if there is no stream (but monitoring) Signed-off-by: Markus Bollinger Signed-off-by: Takashi Iwai --- sound/pci/pcxhr/pcxhr.c | 41 +++++++++++++++++++++++++++++++++++ sound/pci/pcxhr/pcxhr.h | 5 +++-- sound/pci/pcxhr/pcxhr_mix22.c | 40 ++++++++++++++++++++++++++++++---- sound/pci/pcxhr/pcxhr_mix22.h | 3 +++ sound/pci/pcxhr/pcxhr_mixer.c | 8 +++++-- 5 files changed, 89 insertions(+), 8 deletions(-) diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index 27cf2c28d11..ca89106f8c5 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c @@ -1334,6 +1334,40 @@ static void pcxhr_proc_sync(struct snd_info_entry *entry, snd_iprintf(buffer, "\n"); } +static void pcxhr_proc_gpio_read(struct snd_info_entry *entry, + struct snd_info_buffer *buffer) +{ + struct snd_pcxhr *chip = entry->private_data; + struct pcxhr_mgr *mgr = chip->mgr; + /* commands available when embedded DSP is running */ + if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) { + /* gpio ports on stereo boards only available */ + int value = 0; + hr222_read_gpio(mgr, 1, &value); /* GPI */ + snd_iprintf(buffer, "GPI: 0x%x\n", value); + hr222_read_gpio(mgr, 0, &value); /* GP0 */ + snd_iprintf(buffer, "GPO: 0x%x\n", value); + } else + snd_iprintf(buffer, "no firmware loaded\n"); + snd_iprintf(buffer, "\n"); +} +static void pcxhr_proc_gpo_write(struct snd_info_entry *entry, + struct snd_info_buffer *buffer) +{ + struct snd_pcxhr *chip = entry->private_data; + struct pcxhr_mgr *mgr = chip->mgr; + char line[64]; + int value; + /* commands available when embedded DSP is running */ + if (!(mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX))) + return; + while (!snd_info_get_line(buffer, line, sizeof(line))) { + if (sscanf(line, "GPO: 0x%x", &value) != 1) + continue; + hr222_write_gpo(mgr, value); /* GP0 */ + } +} + static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip) { struct snd_info_entry *entry; @@ -1342,6 +1376,13 @@ static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip) snd_info_set_text_ops(entry, chip, pcxhr_proc_info); if (! snd_card_proc_new(chip->card, "sync", &entry)) snd_info_set_text_ops(entry, chip, pcxhr_proc_sync); + /* gpio available on stereo sound cards only */ + if (chip->mgr->is_hr_stereo && + !snd_card_proc_new(chip->card, "gpio", &entry)) { + snd_info_set_text_ops(entry, chip, pcxhr_proc_gpio_read); + entry->c.text.write = pcxhr_proc_gpo_write; + entry->mode |= S_IWUSR; + } } /* end of proc interface */ diff --git a/sound/pci/pcxhr/pcxhr.h b/sound/pci/pcxhr/pcxhr.h index 84131a916c9..ac9c3b3bb4e 100644 --- a/sound/pci/pcxhr/pcxhr.h +++ b/sound/pci/pcxhr/pcxhr.h @@ -27,8 +27,8 @@ #include #include -#define PCXHR_DRIVER_VERSION 0x000905 /* 0.9.5 */ -#define PCXHR_DRIVER_VERSION_STRING "0.9.5" /* 0.9.5 */ +#define PCXHR_DRIVER_VERSION 0x000906 /* 0.9.6 */ +#define PCXHR_DRIVER_VERSION_STRING "0.9.6" /* 0.9.6 */ #define PCXHR_MAX_CARDS 6 @@ -124,6 +124,7 @@ struct pcxhr_mgr { unsigned char xlx_cfg; /* copy of PCXHR_XLX_CFG register */ unsigned char xlx_selmic; /* copy of PCXHR_XLX_SELMIC register */ + unsigned char dsp_reset; /* copy of PCXHR_DSP_RESET register */ }; diff --git a/sound/pci/pcxhr/pcxhr_mix22.c b/sound/pci/pcxhr/pcxhr_mix22.c index ff019126b67..1cb82c0a9cb 100644 --- a/sound/pci/pcxhr/pcxhr_mix22.c +++ b/sound/pci/pcxhr/pcxhr_mix22.c @@ -53,6 +53,8 @@ #define PCXHR_DSP_RESET_DSP 0x01 #define PCXHR_DSP_RESET_MUTE 0x02 #define PCXHR_DSP_RESET_CODEC 0x08 +#define PCXHR_DSP_RESET_GPO_OFFSET 5 +#define PCXHR_DSP_RESET_GPO_MASK 0x60 /* values for PCHR_XLX_CFG register */ #define PCXHR_CFG_SYNCDSP_MASK 0x80 @@ -81,6 +83,8 @@ /* values for PCHR_XLX_STATUS register - READ */ #define PCXHR_STAT_SRC_LOCK 0x01 #define PCXHR_STAT_LEVEL_IN 0x02 +#define PCXHR_STAT_GPI_OFFSET 2 +#define PCXHR_STAT_GPI_MASK 0x0C #define PCXHR_STAT_MIC_CAPS 0x10 /* values for PCHR_XLX_STATUS register - WRITE */ #define PCXHR_STAT_FREQ_SYNC_MASK 0x01 @@ -291,10 +295,11 @@ int hr222_sub_init(struct pcxhr_mgr *mgr) PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, PCXHR_DSP_RESET_DSP); msleep(5); - PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, - PCXHR_DSP_RESET_DSP | - PCXHR_DSP_RESET_MUTE | - PCXHR_DSP_RESET_CODEC); + mgr->dsp_reset = PCXHR_DSP_RESET_DSP | + PCXHR_DSP_RESET_MUTE | + PCXHR_DSP_RESET_CODEC; + PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, mgr->dsp_reset); + /* hr222_write_gpo(mgr, 0); does the same */ msleep(5); /* config AKM */ @@ -496,6 +501,33 @@ int hr222_get_external_clock(struct pcxhr_mgr *mgr, } +int hr222_read_gpio(struct pcxhr_mgr *mgr, int is_gpi, int *value) +{ + if (is_gpi) { + unsigned char reg = PCXHR_INPB(mgr, PCXHR_XLX_STATUS); + *value = (int)(reg & PCXHR_STAT_GPI_MASK) >> + PCXHR_STAT_GPI_OFFSET; + } else { + *value = (int)(mgr->dsp_reset & PCXHR_DSP_RESET_GPO_MASK) >> + PCXHR_DSP_RESET_GPO_OFFSET; + } + return 0; +} + + +int hr222_write_gpo(struct pcxhr_mgr *mgr, int value) +{ + unsigned char reg = mgr->dsp_reset & ~PCXHR_DSP_RESET_GPO_MASK; + + reg |= (unsigned char)(value << PCXHR_DSP_RESET_GPO_OFFSET) & + PCXHR_DSP_RESET_GPO_MASK; + + PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, reg); + mgr->dsp_reset = reg; + return 0; +} + + int hr222_update_analog_audio_level(struct snd_pcxhr *chip, int is_capture, int channel) { diff --git a/sound/pci/pcxhr/pcxhr_mix22.h b/sound/pci/pcxhr/pcxhr_mix22.h index 6b318b2f010..5a37a0007e8 100644 --- a/sound/pci/pcxhr/pcxhr_mix22.h +++ b/sound/pci/pcxhr/pcxhr_mix22.h @@ -32,6 +32,9 @@ int hr222_get_external_clock(struct pcxhr_mgr *mgr, enum pcxhr_clock_type clock_type, int *sample_rate); +int hr222_read_gpio(struct pcxhr_mgr *mgr, int is_gpi, int *value); +int hr222_write_gpo(struct pcxhr_mgr *mgr, int value); + #define HR222_LINE_PLAYBACK_LEVEL_MIN 0 /* -25.5 dB */ #define HR222_LINE_PLAYBACK_ZERO_LEVEL 51 /* 0.0 dB */ #define HR222_LINE_PLAYBACK_LEVEL_MAX 99 /* +24.0 dB */ diff --git a/sound/pci/pcxhr/pcxhr_mixer.c b/sound/pci/pcxhr/pcxhr_mixer.c index 2436e374586..fec04934462 100644 --- a/sound/pci/pcxhr/pcxhr_mixer.c +++ b/sound/pci/pcxhr/pcxhr_mixer.c @@ -789,11 +789,15 @@ static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol, if (mgr->use_clock_type != ucontrol->value.enumerated.item[0]) { mutex_lock(&mgr->setup_mutex); mgr->use_clock_type = ucontrol->value.enumerated.item[0]; - if (mgr->use_clock_type) + rate = 0; + if (mgr->use_clock_type != PCXHR_CLOCK_TYPE_INTERNAL) { pcxhr_get_external_clock(mgr, mgr->use_clock_type, &rate); - else + } else { rate = mgr->sample_rate; + if (!rate) + rate = 48000; + } if (rate) { pcxhr_set_clock(mgr, rate); if (mgr->sample_rate) -- GitLab From ef963dcf6879e500e6559b4327f6cbdc4439198e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 23 Jan 2009 14:53:58 +0000 Subject: [PATCH 0420/4982] ASoC: Fix spurious codec driver dependencies Kbuild ignores dependency from things that are themselves selected so ASoC machine drivers need to ensure that the control bus is being built. This also avoids issues where multiple buses are supported by a given codec. Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 4 ---- sound/soc/omap/Kconfig | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index cb5fcd605ac..656f180b2c1 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -91,7 +91,6 @@ config SND_SOC_SSM2602 config SND_SOC_TLV320AIC23 tristate - depends on I2C config SND_SOC_TLV320AIC26 tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE @@ -99,15 +98,12 @@ config SND_SOC_TLV320AIC26 config SND_SOC_TLV320AIC3X tristate - depends on I2C config SND_SOC_TWL4030 tristate - depends on TWL4030_CORE config SND_SOC_UDA134X tristate - select SND_SOC_L3 config SND_SOC_UDA1380 tristate diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index ccd8973683d..675732e724d 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -8,7 +8,7 @@ config SND_OMAP_SOC_MCBSP config SND_OMAP_SOC_N810 tristate "SoC Audio support for Nokia N810" - depends on SND_OMAP_SOC && MACH_NOKIA_N810 + depends on SND_OMAP_SOC && MACH_NOKIA_N810 && I2C select SND_OMAP_SOC_MCBSP select OMAP_MUX select SND_SOC_TLV320AIC3X @@ -17,7 +17,7 @@ config SND_OMAP_SOC_N810 config SND_OMAP_SOC_OSK5912 tristate "SoC Audio support for omap osk5912" - depends on SND_OMAP_SOC && MACH_OMAP_OSK + depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C select SND_OMAP_SOC_MCBSP select SND_SOC_TLV320AIC23 help -- GitLab From 01e097d6c409a6eb64758dce9fcde0c70073fe36 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 23 Jan 2009 15:07:45 +0000 Subject: [PATCH 0421/4982] ASoC: Include header file in cs4270 and wm9705 Ensures that the DAI and socdev exported by the codec match up with their exported prototype. Signed-off-by: Mark Brown --- sound/soc/codecs/cs4270.c | 2 ++ sound/soc/codecs/wm9705.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 2e4ce04925e..e2130d7b1e4 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -29,6 +29,8 @@ #include #include +#include "cs4270.h" + /* Private data for the CS4270 */ struct cs4270_private { unsigned int mclk; /* Input frequency of the MCLK pin */ diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index 5e1937ac0b5..d5c81bb3dec 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c @@ -20,6 +20,8 @@ #include #include +#include "wm9705.h" + /* * WM9705 register cache */ -- GitLab From 070504ade7a95a0f4395673717f3bb7d41793ca8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 23 Jan 2009 15:34:54 +0000 Subject: [PATCH 0422/4982] ASoC: Fix L3 bus handling in Kconfig It has no external dependencies but needs to be selected for L3 based codecs to work. Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 1 + sound/soc/s3c24xx/Kconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 656f180b2c1..a195303603e 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -10,6 +10,7 @@ config SND_SOC_I2C_AND_SPI config SND_SOC_ALL_CODECS tristate "Build all ASoC CODEC drivers" + select SND_SOC_L3 select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS select SND_SOC_AD1980 if SND_SOC_AC97_BUS select SND_SOC_AD73311 if I2C diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig index fcd03acf10f..e05a71084c3 100644 --- a/sound/soc/s3c24xx/Kconfig +++ b/sound/soc/s3c24xx/Kconfig @@ -48,4 +48,5 @@ config SND_S3C24XX_SOC_S3C24XX_UDA134X tristate "SoC I2S Audio support UDA134X wired to a S3C24XX" depends on SND_S3C24XX_SOC select SND_S3C24XX_SOC_I2S + select SND_SOC_L3 select SND_SOC_UDA134X -- GitLab From 0db4d0705260dd4bddf1e5a5441c58bdf08bdc9f Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Fri, 23 Jan 2009 16:31:19 -0600 Subject: [PATCH 0423/4982] ASoC: improve I2C initialization code in CS4270 driver Further improvements in the I2C initialization sequence of the CS4270 driver. All ASoC initialization is now done in the I2C probe function. Signed-off-by: Timur Tabi Signed-off-by: Mark Brown --- sound/soc/codecs/cs4270.c | 252 +++++++++++++++++--------------------- 1 file changed, 113 insertions(+), 139 deletions(-) diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index e2130d7b1e4..2aa12fdbd2c 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -31,12 +31,6 @@ #include "cs4270.h" -/* Private data for the CS4270 */ -struct cs4270_private { - unsigned int mclk; /* Input frequency of the MCLK pin */ - unsigned int mode; /* The mode (I2S or left-justified) */ -}; - /* * The codec isn't really big-endian or little-endian, since the I2S * interface requires data to be sent serially with the MSbit first. @@ -109,6 +103,14 @@ struct cs4270_private { #define CS4270_MUTE_DAC_A 0x01 #define CS4270_MUTE_DAC_B 0x02 +/* Private data for the CS4270 */ +struct cs4270_private { + struct snd_soc_codec codec; + u8 reg_cache[CS4270_NUMREGS]; + unsigned int mclk; /* Input frequency of the MCLK pin */ + unsigned int mode; /* The mode (I2S or left-justified) */ +}; + /* * Clock Ratio Selection for Master Mode with I2C enabled * @@ -504,6 +506,31 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = { */ static struct snd_soc_device *cs4270_socdev; +struct snd_soc_dai cs4270_dai = { + .name = "cs4270", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = 0, + .formats = CS4270_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = 0, + .formats = CS4270_FORMATS, + }, + .ops = { + .hw_params = cs4270_hw_params, + .set_sysclk = cs4270_set_dai_sysclk, + .set_fmt = cs4270_set_dai_fmt, + .digital_mute = cs4270_mute, + }, +}; +EXPORT_SYMBOL_GPL(cs4270_dai); + /* * Initialize the I2C interface of the CS4270 * @@ -517,47 +544,52 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, const struct i2c_device_id *id) { struct snd_soc_device *socdev = cs4270_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec; + struct cs4270_private *cs4270; int i; int ret = 0; - /* Probing all possible addresses has one drawback: if there are - multiple CS4270s on the bus, then you cannot specify which - socdev is matched with which CS4270. For now, we just reject - this I2C device if the socdev already has one attached. */ - if (codec->control_data) - return -ENODEV; - - /* Note: codec_dai->codec is NULL here */ - - codec->reg_cache = kzalloc(CS4270_NUMREGS, GFP_KERNEL); - if (!codec->reg_cache) { - printk(KERN_ERR "cs4270: could not allocate register cache\n"); - ret = -ENOMEM; - goto error; - } - /* Verify that we have a CS4270 */ ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); if (ret < 0) { printk(KERN_ERR "cs4270: failed to read I2C\n"); - goto error; + return ret; } /* The top four bits of the chip ID should be 1100. */ if ((ret & 0xF0) != 0xC0) { - /* The device at this address is not a CS4270 codec */ - ret = -ENODEV; - goto error; + printk(KERN_ERR "cs4270: device at addr %X is not a CS4270\n", + i2c_client->addr); + return -ENODEV; } printk(KERN_INFO "cs4270: found device at I2C address %X\n", i2c_client->addr); printk(KERN_INFO "cs4270: hardware revision %X\n", ret & 0xF); + /* Allocate enough space for the snd_soc_codec structure + and our private data together. */ + cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL); + if (!cs4270) { + printk(KERN_ERR "cs4270: Could not allocate codec structure\n"); + return -ENOMEM; + } + codec = &cs4270->codec; + socdev->codec = codec; + + mutex_init(&codec->mutex); + INIT_LIST_HEAD(&codec->dapm_widgets); + INIT_LIST_HEAD(&codec->dapm_paths); + + codec->name = "CS4270"; + codec->owner = THIS_MODULE; + codec->dai = &cs4270_dai; + codec->num_dai = 1; + codec->private_data = cs4270; codec->control_data = i2c_client; codec->read = cs4270_read_reg_cache; codec->write = cs4270_i2c_write; + codec->reg_cache = cs4270->reg_cache; codec->reg_cache_size = CS4270_NUMREGS; /* The I2C interface is set up, so pre-fill our register cache */ @@ -565,35 +597,72 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, ret = cs4270_fill_cache(codec); if (ret < 0) { printk(KERN_ERR "cs4270: failed to fill register cache\n"); - goto error; + goto error_free_codec; + } + + /* Register PCMs */ + + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + if (ret < 0) { + printk(KERN_ERR "cs4270: failed to create PCMs\n"); + goto error_free_codec; } /* Add the non-DAPM controls */ for (i = 0; i < ARRAY_SIZE(cs4270_snd_controls); i++) { - struct snd_kcontrol *kctrl = - snd_soc_cnew(&cs4270_snd_controls[i], codec, NULL); + struct snd_kcontrol *kctrl; + + kctrl = snd_soc_cnew(&cs4270_snd_controls[i], codec, NULL); + if (!kctrl) { + printk(KERN_ERR "cs4270: error creating control '%s'\n", + cs4270_snd_controls[i].name); + ret = -ENOMEM; + goto error_free_pcms; + } ret = snd_ctl_add(codec->card, kctrl); - if (ret < 0) - goto error; + if (ret < 0) { + printk(KERN_ERR "cs4270: error adding control '%s'\n", + cs4270_snd_controls[i].name); + goto error_free_pcms; + } } - i2c_set_clientdata(i2c_client, codec); + /* Initialize the SOC device */ + + ret = snd_soc_init_card(socdev); + if (ret < 0) { + printk(KERN_ERR "cs4270: failed to register card\n"); + goto error_free_pcms;; + } + + i2c_set_clientdata(i2c_client, socdev); return 0; -error: - codec->control_data = NULL; +error_free_pcms: + snd_soc_free_pcms(socdev); - kfree(codec->reg_cache); - codec->reg_cache = NULL; - codec->reg_cache_size = 0; +error_free_codec: + kfree(cs4270); return ret; } -static const struct i2c_device_id cs4270_id[] = { +static int cs4270_i2c_remove(struct i2c_client *i2c_client) +{ + struct snd_soc_device *socdev = i2c_get_clientdata(i2c_client); + struct snd_soc_codec *codec = socdev->codec; + struct cs4270_private *cs4270 = codec->private_data; + + snd_soc_free_pcms(socdev); + kfree(cs4270); + + return 0; +} + +static struct i2c_device_id cs4270_id[] = { {"cs4270", 0}, {} }; @@ -606,27 +675,9 @@ static struct i2c_driver cs4270_i2c_driver = { }, .id_table = cs4270_id, .probe = cs4270_i2c_probe, + .remove = cs4270_i2c_remove, }; -struct snd_soc_dai cs4270_dai = { - .name = "CS4270", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = 0, - .formats = CS4270_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = 0, - .formats = CS4270_FORMATS, - }, -}; -EXPORT_SYMBOL_GPL(cs4270_dai); - /* * ASoC probe function * @@ -635,94 +686,15 @@ EXPORT_SYMBOL_GPL(cs4270_dai); */ static int cs4270_probe(struct platform_device *pdev) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - printk(KERN_INFO "CS4270 ALSA SoC Codec\n"); - - /* Allocate enough space for the snd_soc_codec structure - and our private data together. */ - codec = kzalloc(ALIGN(sizeof(struct snd_soc_codec), 4) + - sizeof(struct cs4270_private), GFP_KERNEL); - if (!codec) { - printk(KERN_ERR "cs4270: Could not allocate codec structure\n"); - return -ENOMEM; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->name = "CS4270"; - codec->owner = THIS_MODULE; - codec->dai = &cs4270_dai; - codec->num_dai = 1; - codec->private_data = (void *) codec + - ALIGN(sizeof(struct snd_soc_codec), 4); - - socdev->codec = codec; - - /* Register PCMs */ - - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - printk(KERN_ERR "cs4270: failed to create PCMs\n"); - goto error_free_codec; - } - - cs4270_socdev = socdev; - - ret = i2c_add_driver(&cs4270_i2c_driver); - if (ret) { - printk(KERN_ERR "cs4270: failed to attach driver"); - goto error_free_pcms; - } - - /* Did we find a CS4270 on the I2C bus? */ - if (!codec->control_data) { - printk(KERN_ERR "cs4270: failed to attach driver"); - goto error_del_driver; - } + cs4270_socdev = platform_get_drvdata(pdev);; - /* Initialize codec ops */ - cs4270_dai.ops.hw_params = cs4270_hw_params; - cs4270_dai.ops.set_sysclk = cs4270_set_dai_sysclk; - cs4270_dai.ops.set_fmt = cs4270_set_dai_fmt; - cs4270_dai.ops.digital_mute = cs4270_mute; - - ret = snd_soc_init_card(socdev); - if (ret < 0) { - printk(KERN_ERR "cs4270: failed to register card\n"); - goto error_del_driver; - } - - return 0; - -error_del_driver: - i2c_del_driver(&cs4270_i2c_driver); - -error_free_pcms: - snd_soc_free_pcms(socdev); - -error_free_codec: - kfree(socdev->codec); - socdev->codec = NULL; - - return ret; + return i2c_add_driver(&cs4270_i2c_driver); } static int cs4270_remove(struct platform_device *pdev) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - i2c_del_driver(&cs4270_i2c_driver); - kfree(socdev->codec); - socdev->codec = NULL; - return 0; } @@ -740,6 +712,8 @@ EXPORT_SYMBOL_GPL(soc_codec_device_cs4270); static int __init cs4270_init(void) { + printk(KERN_INFO "Cirrus Logic CS4270 ALSA SoC Codec Driver\n"); + return snd_soc_register_dai(&cs4270_dai); } module_init(cs4270_init); -- GitLab From fe40c0af3cff3ea461cf25bddb979abc7279d4df Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Fri, 23 Jan 2009 15:49:41 -0800 Subject: [PATCH 0424/4982] x86: uaccess: introduce try and catch framework Impact: introduce new uaccess exception handling framework Introduce {get|put}_user_try and {get|put}_user_catch as new uaccess exception handling framework. {get|put}_user_try begins exception block and {get|put}_user_catch(err) ends the block and gets err if an exception occured in {get|put}_user_ex() in the block. The exception is stored thread_info->uaccess_err. The example usage of this framework is below; int func() { int err = 0; get_user_try { get_user_ex(...); get_user_ex(...); : } get_user_catch(err); return err; } Note: get_user_ex() is not clear the value when an exception occurs, it's different from the behavior of __get_user(), but I think it doesn't matter. Signed-off-by: Hiroshi Shimamoto Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/thread_info.h | 1 + arch/x86/include/asm/uaccess.h | 103 +++++++++++++++++++++++++++++ arch/x86/mm/extable.c | 6 ++ 3 files changed, 110 insertions(+) diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index 98789647baa..3f90aeb456b 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h @@ -40,6 +40,7 @@ struct thread_info { */ __u8 supervisor_stack[0]; #endif + int uaccess_err; }; #define INIT_THREAD_INFO(tsk) \ diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index 69d2757cca9..0ec6de4bcb0 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -199,12 +199,22 @@ extern int __get_user_bad(void); : "=r" (err) \ : "A" (x), "r" (addr), "i" (-EFAULT), "0" (err)) +#define __put_user_asm_ex_u64(x, addr) \ + asm volatile("1: movl %%eax,0(%1)\n" \ + "2: movl %%edx,4(%1)\n" \ + "3:\n" \ + _ASM_EXTABLE(1b, 2b - 1b) \ + _ASM_EXTABLE(2b, 3b - 2b) \ + : : "A" (x), "r" (addr)) + #define __put_user_x8(x, ptr, __ret_pu) \ asm volatile("call __put_user_8" : "=a" (__ret_pu) \ : "A" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx") #else #define __put_user_asm_u64(x, ptr, retval) \ __put_user_asm(x, ptr, retval, "q", "", "Zr", -EFAULT) +#define __put_user_asm_ex_u64(x, addr) \ + __put_user_asm_ex(x, addr, "q", "", "Zr") #define __put_user_x8(x, ptr, __ret_pu) __put_user_x(8, x, ptr, __ret_pu) #endif @@ -286,6 +296,27 @@ do { \ } \ } while (0) +#define __put_user_size_ex(x, ptr, size) \ +do { \ + __chk_user_ptr(ptr); \ + switch (size) { \ + case 1: \ + __put_user_asm_ex(x, ptr, "b", "b", "iq"); \ + break; \ + case 2: \ + __put_user_asm_ex(x, ptr, "w", "w", "ir"); \ + break; \ + case 4: \ + __put_user_asm_ex(x, ptr, "l", "k", "ir"); \ + break; \ + case 8: \ + __put_user_asm_ex_u64((__typeof__(*ptr))(x), ptr); \ + break; \ + default: \ + __put_user_bad(); \ + } \ +} while (0) + #else #define __put_user_size(x, ptr, size, retval, errret) \ @@ -311,9 +342,12 @@ do { \ #ifdef CONFIG_X86_32 #define __get_user_asm_u64(x, ptr, retval, errret) (x) = __get_user_bad() +#define __get_user_asm_ex_u64(x, ptr) (x) = __get_user_bad() #else #define __get_user_asm_u64(x, ptr, retval, errret) \ __get_user_asm(x, ptr, retval, "q", "", "=r", errret) +#define __get_user_asm_ex_u64(x, ptr) \ + __get_user_asm_ex(x, ptr, "q", "", "=r") #endif #define __get_user_size(x, ptr, size, retval, errret) \ @@ -350,6 +384,33 @@ do { \ : "=r" (err), ltype(x) \ : "m" (__m(addr)), "i" (errret), "0" (err)) +#define __get_user_size_ex(x, ptr, size) \ +do { \ + __chk_user_ptr(ptr); \ + switch (size) { \ + case 1: \ + __get_user_asm_ex(x, ptr, "b", "b", "=q"); \ + break; \ + case 2: \ + __get_user_asm_ex(x, ptr, "w", "w", "=r"); \ + break; \ + case 4: \ + __get_user_asm_ex(x, ptr, "l", "k", "=r"); \ + break; \ + case 8: \ + __get_user_asm_ex_u64(x, ptr); \ + break; \ + default: \ + (x) = __get_user_bad(); \ + } \ +} while (0) + +#define __get_user_asm_ex(x, addr, itype, rtype, ltype) \ + asm volatile("1: mov"itype" %1,%"rtype"0\n" \ + "2:\n" \ + _ASM_EXTABLE(1b, 2b - 1b) \ + : ltype(x) : "m" (__m(addr))) + #define __put_user_nocheck(x, ptr, size) \ ({ \ int __pu_err; \ @@ -385,6 +446,26 @@ struct __large_struct { unsigned long buf[100]; }; _ASM_EXTABLE(1b, 3b) \ : "=r"(err) \ : ltype(x), "m" (__m(addr)), "i" (errret), "0" (err)) + +#define __put_user_asm_ex(x, addr, itype, rtype, ltype) \ + asm volatile("1: mov"itype" %"rtype"0,%1\n" \ + "2:\n" \ + _ASM_EXTABLE(1b, 2b - 1b) \ + : : ltype(x), "m" (__m(addr))) + +/* + * uaccess_try and catch + */ +#define uaccess_try do { \ + int prev_err = current_thread_info()->uaccess_err; \ + current_thread_info()->uaccess_err = 0; \ + barrier(); + +#define uaccess_catch(err) \ + (err) |= current_thread_info()->uaccess_err; \ + current_thread_info()->uaccess_err = prev_err; \ +} while (0) + /** * __get_user: - Get a simple variable from user space, with less checking. * @x: Variable to store result. @@ -408,6 +489,7 @@ struct __large_struct { unsigned long buf[100]; }; #define __get_user(x, ptr) \ __get_user_nocheck((x), (ptr), sizeof(*(ptr))) + /** * __put_user: - Write a simple value into user space, with less checking. * @x: Value to copy to user space. @@ -434,6 +516,27 @@ struct __large_struct { unsigned long buf[100]; }; #define __get_user_unaligned __get_user #define __put_user_unaligned __put_user +/* + * {get|put}_user_try and catch + * + * get_user_try { + * get_user_ex(...); + * } get_user_catch(err) + */ +#define get_user_try uaccess_try +#define get_user_catch(err) uaccess_catch(err) +#define put_user_try uaccess_try +#define put_user_catch(err) uaccess_catch(err) + +#define get_user_ex(x, ptr) do { \ + unsigned long __gue_val; \ + __get_user_size_ex((__gue_val), (ptr), (sizeof(*(ptr)))); \ + (x) = (__force __typeof__(*(ptr)))__gue_val; \ +} while (0) + +#define put_user_ex(x, ptr) \ + __put_user_size_ex((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) + /* * movsl can be slow when source and dest are not both 8-byte aligned */ diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c index 7e8db53528a..61b41ca3b5a 100644 --- a/arch/x86/mm/extable.c +++ b/arch/x86/mm/extable.c @@ -23,6 +23,12 @@ int fixup_exception(struct pt_regs *regs) fixup = search_exception_tables(regs->ip); if (fixup) { + /* If fixup is less than 16, it means uaccess error */ + if (fixup->fixup < 16) { + current_thread_info()->uaccess_err = -EFAULT; + regs->ip += fixup->fixup; + return 1; + } regs->ip = fixup->fixup; return 1; } -- GitLab From 98e3d45edad207b4358948d6e2cac4e482c3bb5d Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Fri, 23 Jan 2009 15:50:10 -0800 Subject: [PATCH 0425/4982] x86: signal: use {get|put}_user_try and catch Impact: use new framework Use {get|put}_user_try, catch, and _ex in arch/x86/kernel/signal.c. Note: this patch contains "WARNING: line over 80 characters", because when introducing new block I insert an indent to avoid mistakes by edit. Signed-off-by: Hiroshi Shimamoto Signed-off-by: H. Peter Anvin --- arch/x86/kernel/signal.c | 291 +++++++++++++++++++++------------------ 1 file changed, 154 insertions(+), 137 deletions(-) diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 89bb7668041..cf34eb37fbe 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -51,24 +51,24 @@ #endif #define COPY(x) { \ - err |= __get_user(regs->x, &sc->x); \ + get_user_ex(regs->x, &sc->x); \ } #define COPY_SEG(seg) { \ unsigned short tmp; \ - err |= __get_user(tmp, &sc->seg); \ + get_user_ex(tmp, &sc->seg); \ regs->seg = tmp; \ } #define COPY_SEG_CPL3(seg) { \ unsigned short tmp; \ - err |= __get_user(tmp, &sc->seg); \ + get_user_ex(tmp, &sc->seg); \ regs->seg = tmp | 3; \ } #define GET_SEG(seg) { \ unsigned short tmp; \ - err |= __get_user(tmp, &sc->seg); \ + get_user_ex(tmp, &sc->seg); \ loadsegment(seg, tmp); \ } @@ -83,45 +83,49 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, /* Always make any pending restarted system calls return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; + get_user_try { + #ifdef CONFIG_X86_32 - GET_SEG(gs); - COPY_SEG(fs); - COPY_SEG(es); - COPY_SEG(ds); + GET_SEG(gs); + COPY_SEG(fs); + COPY_SEG(es); + COPY_SEG(ds); #endif /* CONFIG_X86_32 */ - COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); - COPY(dx); COPY(cx); COPY(ip); + COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); + COPY(dx); COPY(cx); COPY(ip); #ifdef CONFIG_X86_64 - COPY(r8); - COPY(r9); - COPY(r10); - COPY(r11); - COPY(r12); - COPY(r13); - COPY(r14); - COPY(r15); + COPY(r8); + COPY(r9); + COPY(r10); + COPY(r11); + COPY(r12); + COPY(r13); + COPY(r14); + COPY(r15); #endif /* CONFIG_X86_64 */ #ifdef CONFIG_X86_32 - COPY_SEG_CPL3(cs); - COPY_SEG_CPL3(ss); + COPY_SEG_CPL3(cs); + COPY_SEG_CPL3(ss); #else /* !CONFIG_X86_32 */ - /* Kernel saves and restores only the CS segment register on signals, - * which is the bare minimum needed to allow mixed 32/64-bit code. - * App's signal handler can save/restore other segments if needed. */ - COPY_SEG_CPL3(cs); + /* Kernel saves and restores only the CS segment register on signals, + * which is the bare minimum needed to allow mixed 32/64-bit code. + * App's signal handler can save/restore other segments if needed. */ + COPY_SEG_CPL3(cs); #endif /* CONFIG_X86_32 */ - err |= __get_user(tmpflags, &sc->flags); - regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); - regs->orig_ax = -1; /* disable syscall checks */ + get_user_ex(tmpflags, &sc->flags); + regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); + regs->orig_ax = -1; /* disable syscall checks */ + + get_user_ex(buf, &sc->fpstate); + err |= restore_i387_xstate(buf); - err |= __get_user(buf, &sc->fpstate); - err |= restore_i387_xstate(buf); + get_user_ex(*pax, &sc->ax); + } get_user_catch(err); - err |= __get_user(*pax, &sc->ax); return err; } @@ -131,57 +135,60 @@ setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate, { int err = 0; + put_user_try { + #ifdef CONFIG_X86_32 - { - unsigned int tmp; + { + unsigned int tmp; - savesegment(gs, tmp); - err |= __put_user(tmp, (unsigned int __user *)&sc->gs); - } - err |= __put_user(regs->fs, (unsigned int __user *)&sc->fs); - err |= __put_user(regs->es, (unsigned int __user *)&sc->es); - err |= __put_user(regs->ds, (unsigned int __user *)&sc->ds); + savesegment(gs, tmp); + put_user_ex(tmp, (unsigned int __user *)&sc->gs); + } + put_user_ex(regs->fs, (unsigned int __user *)&sc->fs); + put_user_ex(regs->es, (unsigned int __user *)&sc->es); + put_user_ex(regs->ds, (unsigned int __user *)&sc->ds); #endif /* CONFIG_X86_32 */ - err |= __put_user(regs->di, &sc->di); - err |= __put_user(regs->si, &sc->si); - err |= __put_user(regs->bp, &sc->bp); - err |= __put_user(regs->sp, &sc->sp); - err |= __put_user(regs->bx, &sc->bx); - err |= __put_user(regs->dx, &sc->dx); - err |= __put_user(regs->cx, &sc->cx); - err |= __put_user(regs->ax, &sc->ax); + put_user_ex(regs->di, &sc->di); + put_user_ex(regs->si, &sc->si); + put_user_ex(regs->bp, &sc->bp); + put_user_ex(regs->sp, &sc->sp); + put_user_ex(regs->bx, &sc->bx); + put_user_ex(regs->dx, &sc->dx); + put_user_ex(regs->cx, &sc->cx); + put_user_ex(regs->ax, &sc->ax); #ifdef CONFIG_X86_64 - err |= __put_user(regs->r8, &sc->r8); - err |= __put_user(regs->r9, &sc->r9); - err |= __put_user(regs->r10, &sc->r10); - err |= __put_user(regs->r11, &sc->r11); - err |= __put_user(regs->r12, &sc->r12); - err |= __put_user(regs->r13, &sc->r13); - err |= __put_user(regs->r14, &sc->r14); - err |= __put_user(regs->r15, &sc->r15); + put_user_ex(regs->r8, &sc->r8); + put_user_ex(regs->r9, &sc->r9); + put_user_ex(regs->r10, &sc->r10); + put_user_ex(regs->r11, &sc->r11); + put_user_ex(regs->r12, &sc->r12); + put_user_ex(regs->r13, &sc->r13); + put_user_ex(regs->r14, &sc->r14); + put_user_ex(regs->r15, &sc->r15); #endif /* CONFIG_X86_64 */ - err |= __put_user(current->thread.trap_no, &sc->trapno); - err |= __put_user(current->thread.error_code, &sc->err); - err |= __put_user(regs->ip, &sc->ip); + put_user_ex(current->thread.trap_no, &sc->trapno); + put_user_ex(current->thread.error_code, &sc->err); + put_user_ex(regs->ip, &sc->ip); #ifdef CONFIG_X86_32 - err |= __put_user(regs->cs, (unsigned int __user *)&sc->cs); - err |= __put_user(regs->flags, &sc->flags); - err |= __put_user(regs->sp, &sc->sp_at_signal); - err |= __put_user(regs->ss, (unsigned int __user *)&sc->ss); + put_user_ex(regs->cs, (unsigned int __user *)&sc->cs); + put_user_ex(regs->flags, &sc->flags); + put_user_ex(regs->sp, &sc->sp_at_signal); + put_user_ex(regs->ss, (unsigned int __user *)&sc->ss); #else /* !CONFIG_X86_32 */ - err |= __put_user(regs->flags, &sc->flags); - err |= __put_user(regs->cs, &sc->cs); - err |= __put_user(0, &sc->gs); - err |= __put_user(0, &sc->fs); + put_user_ex(regs->flags, &sc->flags); + put_user_ex(regs->cs, &sc->cs); + put_user_ex(0, &sc->gs); + put_user_ex(0, &sc->fs); #endif /* CONFIG_X86_32 */ - err |= __put_user(fpstate, &sc->fpstate); + put_user_ex(fpstate, &sc->fpstate); - /* non-iBCS2 extensions.. */ - err |= __put_user(mask, &sc->oldmask); - err |= __put_user(current->thread.cr2, &sc->cr2); + /* non-iBCS2 extensions.. */ + put_user_ex(mask, &sc->oldmask); + put_user_ex(current->thread.cr2, &sc->cr2); + } put_user_catch(err); return err; } @@ -336,43 +343,41 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return -EFAULT; - err |= __put_user(sig, &frame->sig); - err |= __put_user(&frame->info, &frame->pinfo); - err |= __put_user(&frame->uc, &frame->puc); - err |= copy_siginfo_to_user(&frame->info, info); - if (err) - return -EFAULT; - - /* Create the ucontext. */ - if (cpu_has_xsave) - err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags); - else - err |= __put_user(0, &frame->uc.uc_flags); - err |= __put_user(0, &frame->uc.uc_link); - err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); - err |= __put_user(sas_ss_flags(regs->sp), - &frame->uc.uc_stack.ss_flags); - err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); - err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, - regs, set->sig[0]); - err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); - if (err) - return -EFAULT; + put_user_try { + put_user_ex(sig, &frame->sig); + put_user_ex(&frame->info, &frame->pinfo); + put_user_ex(&frame->uc, &frame->puc); + err |= copy_siginfo_to_user(&frame->info, info); - /* Set up to return from userspace. */ - restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); - if (ka->sa.sa_flags & SA_RESTORER) - restorer = ka->sa.sa_restorer; - err |= __put_user(restorer, &frame->pretcode); + /* Create the ucontext. */ + if (cpu_has_xsave) + put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags); + else + put_user_ex(0, &frame->uc.uc_flags); + put_user_ex(0, &frame->uc.uc_link); + put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); + put_user_ex(sas_ss_flags(regs->sp), + &frame->uc.uc_stack.ss_flags); + put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, + regs, set->sig[0]); + err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + + /* Set up to return from userspace. */ + restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); + if (ka->sa.sa_flags & SA_RESTORER) + restorer = ka->sa.sa_restorer; + put_user_ex(restorer, &frame->pretcode); - /* - * This is movl $__NR_rt_sigreturn, %ax ; int $0x80 - * - * WE DO NOT USE IT ANY MORE! It's only left here for historical - * reasons and because gdb uses it as a signature to notice - * signal handler stack frames. - */ - err |= __put_user(*((u64 *)&rt_retcode), (u64 *)frame->retcode); + /* + * This is movl $__NR_rt_sigreturn, %ax ; int $0x80 + * + * WE DO NOT USE IT ANY MORE! It's only left here for historical + * reasons and because gdb uses it as a signature to notice + * signal handler stack frames. + */ + put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode); + } put_user_catch(err); if (err) return -EFAULT; @@ -436,28 +441,30 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return -EFAULT; } - /* Create the ucontext. */ - if (cpu_has_xsave) - err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags); - else - err |= __put_user(0, &frame->uc.uc_flags); - err |= __put_user(0, &frame->uc.uc_link); - err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); - err |= __put_user(sas_ss_flags(regs->sp), - &frame->uc.uc_stack.ss_flags); - err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); - err |= setup_sigcontext(&frame->uc.uc_mcontext, fp, regs, set->sig[0]); - err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); - - /* Set up to return from userspace. If provided, use a stub - already in userspace. */ - /* x86-64 should always use SA_RESTORER. */ - if (ka->sa.sa_flags & SA_RESTORER) { - err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); - } else { - /* could use a vstub here */ - return -EFAULT; - } + put_user_try { + /* Create the ucontext. */ + if (cpu_has_xsave) + put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags); + else + put_user_ex(0, &frame->uc.uc_flags); + put_user_ex(0, &frame->uc.uc_link); + put_user_ex(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); + put_user_ex(sas_ss_flags(regs->sp), + &frame->uc.uc_stack.ss_flags); + put_user_ex(me->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= setup_sigcontext(&frame->uc.uc_mcontext, fp, regs, set->sig[0]); + err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ + /* x86-64 should always use SA_RESTORER. */ + if (ka->sa.sa_flags & SA_RESTORER) { + put_user_ex(ka->sa.sa_restorer, &frame->pretcode); + } else { + /* could use a vstub here */ + err |= -EFAULT; + } + } put_user_catch(err); if (err) return -EFAULT; @@ -509,31 +516,41 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, struct old_sigaction __user *oact) { struct k_sigaction new_ka, old_ka; - int ret; + int ret = 0; if (act) { old_sigset_t mask; - if (!access_ok(VERIFY_READ, act, sizeof(*act)) || - __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) + if (!access_ok(VERIFY_READ, act, sizeof(*act))) return -EFAULT; - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); + get_user_try { + get_user_ex(new_ka.sa.sa_handler, &act->sa_handler); + get_user_ex(new_ka.sa.sa_flags, &act->sa_flags); + get_user_ex(mask, &act->sa_mask); + get_user_ex(new_ka.sa.sa_restorer, &act->sa_restorer); + } get_user_catch(ret); + + if (ret) + return -EFAULT; siginitset(&new_ka.sa.sa_mask, mask); } ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { - if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) + if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact))) return -EFAULT; - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); + put_user_try { + put_user_ex(old_ka.sa.sa_handler, &oact->sa_handler); + put_user_ex(old_ka.sa.sa_flags, &oact->sa_flags); + put_user_ex(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); + put_user_ex(old_ka.sa.sa_restorer, &oact->sa_restorer); + } put_user_catch(ret); + + if (ret) + return -EFAULT; } return ret; -- GitLab From 3b4b75700a245d0d48fc52a4d2f67d3155812aba Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Fri, 23 Jan 2009 15:50:38 -0800 Subject: [PATCH 0426/4982] x86: ia32_signal: use {get|put}_user_try and catch Impact: use new framework Use {get|put}_user_try, catch, and _ex in arch/x86/ia32/ia32_signal.c. Note: this patch contains "WARNING: line over 80 characters", because when introducing new block I insert an indent to avoid mistakes by edit. Signed-off-by: Hiroshi Shimamoto Signed-off-by: H. Peter Anvin --- arch/x86/ia32/ia32_signal.c | 365 +++++++++++++++++++----------------- 1 file changed, 195 insertions(+), 170 deletions(-) diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 9dabd00e980..dd77ac0cac4 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -46,78 +46,83 @@ void signal_fault(struct pt_regs *regs, void __user *frame, char *where); int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) { - int err; + int err = 0; if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t))) return -EFAULT; - /* If you change siginfo_t structure, please make sure that - this code is fixed accordingly. - It should never copy any pad contained in the structure - to avoid security leaks, but must copy the generic - 3 ints plus the relevant union member. */ - err = __put_user(from->si_signo, &to->si_signo); - err |= __put_user(from->si_errno, &to->si_errno); - err |= __put_user((short)from->si_code, &to->si_code); - - if (from->si_code < 0) { - err |= __put_user(from->si_pid, &to->si_pid); - err |= __put_user(from->si_uid, &to->si_uid); - err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr); - } else { - /* - * First 32bits of unions are always present: - * si_pid === si_band === si_tid === si_addr(LS half) - */ - err |= __put_user(from->_sifields._pad[0], - &to->_sifields._pad[0]); - switch (from->si_code >> 16) { - case __SI_FAULT >> 16: - break; - case __SI_CHLD >> 16: - err |= __put_user(from->si_utime, &to->si_utime); - err |= __put_user(from->si_stime, &to->si_stime); - err |= __put_user(from->si_status, &to->si_status); - /* FALL THROUGH */ - default: - case __SI_KILL >> 16: - err |= __put_user(from->si_uid, &to->si_uid); - break; - case __SI_POLL >> 16: - err |= __put_user(from->si_fd, &to->si_fd); - break; - case __SI_TIMER >> 16: - err |= __put_user(from->si_overrun, &to->si_overrun); - err |= __put_user(ptr_to_compat(from->si_ptr), - &to->si_ptr); - break; - /* This is not generated by the kernel as of now. */ - case __SI_RT >> 16: - case __SI_MESGQ >> 16: - err |= __put_user(from->si_uid, &to->si_uid); - err |= __put_user(from->si_int, &to->si_int); - break; + put_user_try { + /* If you change siginfo_t structure, please make sure that + this code is fixed accordingly. + It should never copy any pad contained in the structure + to avoid security leaks, but must copy the generic + 3 ints plus the relevant union member. */ + put_user_ex(from->si_signo, &to->si_signo); + put_user_ex(from->si_errno, &to->si_errno); + put_user_ex((short)from->si_code, &to->si_code); + + if (from->si_code < 0) { + put_user_ex(from->si_pid, &to->si_pid); + put_user_ex(from->si_uid, &to->si_uid); + put_user_ex(ptr_to_compat(from->si_ptr), &to->si_ptr); + } else { + /* + * First 32bits of unions are always present: + * si_pid === si_band === si_tid === si_addr(LS half) + */ + put_user_ex(from->_sifields._pad[0], + &to->_sifields._pad[0]); + switch (from->si_code >> 16) { + case __SI_FAULT >> 16: + break; + case __SI_CHLD >> 16: + put_user_ex(from->si_utime, &to->si_utime); + put_user_ex(from->si_stime, &to->si_stime); + put_user_ex(from->si_status, &to->si_status); + /* FALL THROUGH */ + default: + case __SI_KILL >> 16: + put_user_ex(from->si_uid, &to->si_uid); + break; + case __SI_POLL >> 16: + put_user_ex(from->si_fd, &to->si_fd); + break; + case __SI_TIMER >> 16: + put_user_ex(from->si_overrun, &to->si_overrun); + put_user_ex(ptr_to_compat(from->si_ptr), + &to->si_ptr); + break; + /* This is not generated by the kernel as of now. */ + case __SI_RT >> 16: + case __SI_MESGQ >> 16: + put_user_ex(from->si_uid, &to->si_uid); + put_user_ex(from->si_int, &to->si_int); + break; + } } - } + } put_user_catch(err); + return err; } int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) { - int err; + int err = 0; u32 ptr32; if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t))) return -EFAULT; - err = __get_user(to->si_signo, &from->si_signo); - err |= __get_user(to->si_errno, &from->si_errno); - err |= __get_user(to->si_code, &from->si_code); + get_user_try { + get_user_ex(to->si_signo, &from->si_signo); + get_user_ex(to->si_errno, &from->si_errno); + get_user_ex(to->si_code, &from->si_code); - err |= __get_user(to->si_pid, &from->si_pid); - err |= __get_user(to->si_uid, &from->si_uid); - err |= __get_user(ptr32, &from->si_ptr); - to->si_ptr = compat_ptr(ptr32); + get_user_ex(to->si_pid, &from->si_pid); + get_user_ex(to->si_uid, &from->si_uid); + get_user_ex(ptr32, &from->si_ptr); + to->si_ptr = compat_ptr(ptr32); + } get_user_catch(err); return err; } @@ -142,17 +147,23 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr, struct pt_regs *regs) { stack_t uss, uoss; - int ret; + int ret, err = 0; mm_segment_t seg; if (uss_ptr) { u32 ptr; memset(&uss, 0, sizeof(stack_t)); - if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t)) || - __get_user(ptr, &uss_ptr->ss_sp) || - __get_user(uss.ss_flags, &uss_ptr->ss_flags) || - __get_user(uss.ss_size, &uss_ptr->ss_size)) + if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t))) + return -EFAULT; + + get_user_try { + get_user_ex(ptr, &uss_ptr->ss_sp); + get_user_ex(uss.ss_flags, &uss_ptr->ss_flags); + get_user_ex(uss.ss_size, &uss_ptr->ss_size); + } get_user_catch(err); + + if (err) return -EFAULT; uss.ss_sp = compat_ptr(ptr); } @@ -161,10 +172,16 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr, ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->sp); set_fs(seg); if (ret >= 0 && uoss_ptr) { - if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)) || - __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) || - __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) || - __put_user(uoss.ss_size, &uoss_ptr->ss_size)) + if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t))) + return -EFAULT; + + put_user_try { + put_user_ex(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp); + put_user_ex(uoss.ss_flags, &uoss_ptr->ss_flags); + put_user_ex(uoss.ss_size, &uoss_ptr->ss_size); + } put_user_catch(err); + + if (err) ret = -EFAULT; } return ret; @@ -174,18 +191,18 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr, * Do a signal return; undo the signal stack. */ #define COPY(x) { \ - err |= __get_user(regs->x, &sc->x); \ + get_user_ex(regs->x, &sc->x); \ } #define COPY_SEG_CPL3(seg) { \ unsigned short tmp; \ - err |= __get_user(tmp, &sc->seg); \ + get_user_ex(tmp, &sc->seg); \ regs->seg = tmp | 3; \ } #define RELOAD_SEG(seg) { \ unsigned int cur, pre; \ - err |= __get_user(pre, &sc->seg); \ + get_user_ex(pre, &sc->seg); \ savesegment(seg, cur); \ pre |= 3; \ if (pre != cur) \ @@ -209,39 +226,42 @@ static int ia32_restore_sigcontext(struct pt_regs *regs, sc, sc->err, sc->ip, sc->cs, sc->flags); #endif - /* - * Reload fs and gs if they have changed in the signal - * handler. This does not handle long fs/gs base changes in - * the handler, but does not clobber them at least in the - * normal case. - */ - err |= __get_user(gs, &sc->gs); - gs |= 3; - savesegment(gs, oldgs); - if (gs != oldgs) - load_gs_index(gs); - - RELOAD_SEG(fs); - RELOAD_SEG(ds); - RELOAD_SEG(es); - - COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); - COPY(dx); COPY(cx); COPY(ip); - /* Don't touch extended registers */ - - COPY_SEG_CPL3(cs); - COPY_SEG_CPL3(ss); - - err |= __get_user(tmpflags, &sc->flags); - regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); - /* disable syscall checks */ - regs->orig_ax = -1; - - err |= __get_user(tmp, &sc->fpstate); - buf = compat_ptr(tmp); - err |= restore_i387_xstate_ia32(buf); - - err |= __get_user(*pax, &sc->ax); + get_user_try { + /* + * Reload fs and gs if they have changed in the signal + * handler. This does not handle long fs/gs base changes in + * the handler, but does not clobber them at least in the + * normal case. + */ + get_user_ex(gs, &sc->gs); + gs |= 3; + savesegment(gs, oldgs); + if (gs != oldgs) + load_gs_index(gs); + + RELOAD_SEG(fs); + RELOAD_SEG(ds); + RELOAD_SEG(es); + + COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); + COPY(dx); COPY(cx); COPY(ip); + /* Don't touch extended registers */ + + COPY_SEG_CPL3(cs); + COPY_SEG_CPL3(ss); + + get_user_ex(tmpflags, &sc->flags); + regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); + /* disable syscall checks */ + regs->orig_ax = -1; + + get_user_ex(tmp, &sc->fpstate); + buf = compat_ptr(tmp); + err |= restore_i387_xstate_ia32(buf); + + get_user_ex(*pax, &sc->ax); + } get_user_catch(err); + return err; } @@ -319,36 +339,38 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, { int tmp, err = 0; - savesegment(gs, tmp); - err |= __put_user(tmp, (unsigned int __user *)&sc->gs); - savesegment(fs, tmp); - err |= __put_user(tmp, (unsigned int __user *)&sc->fs); - savesegment(ds, tmp); - err |= __put_user(tmp, (unsigned int __user *)&sc->ds); - savesegment(es, tmp); - err |= __put_user(tmp, (unsigned int __user *)&sc->es); - - err |= __put_user(regs->di, &sc->di); - err |= __put_user(regs->si, &sc->si); - err |= __put_user(regs->bp, &sc->bp); - err |= __put_user(regs->sp, &sc->sp); - err |= __put_user(regs->bx, &sc->bx); - err |= __put_user(regs->dx, &sc->dx); - err |= __put_user(regs->cx, &sc->cx); - err |= __put_user(regs->ax, &sc->ax); - err |= __put_user(current->thread.trap_no, &sc->trapno); - err |= __put_user(current->thread.error_code, &sc->err); - err |= __put_user(regs->ip, &sc->ip); - err |= __put_user(regs->cs, (unsigned int __user *)&sc->cs); - err |= __put_user(regs->flags, &sc->flags); - err |= __put_user(regs->sp, &sc->sp_at_signal); - err |= __put_user(regs->ss, (unsigned int __user *)&sc->ss); - - err |= __put_user(ptr_to_compat(fpstate), &sc->fpstate); - - /* non-iBCS2 extensions.. */ - err |= __put_user(mask, &sc->oldmask); - err |= __put_user(current->thread.cr2, &sc->cr2); + put_user_try { + savesegment(gs, tmp); + put_user_ex(tmp, (unsigned int __user *)&sc->gs); + savesegment(fs, tmp); + put_user_ex(tmp, (unsigned int __user *)&sc->fs); + savesegment(ds, tmp); + put_user_ex(tmp, (unsigned int __user *)&sc->ds); + savesegment(es, tmp); + put_user_ex(tmp, (unsigned int __user *)&sc->es); + + put_user_ex(regs->di, &sc->di); + put_user_ex(regs->si, &sc->si); + put_user_ex(regs->bp, &sc->bp); + put_user_ex(regs->sp, &sc->sp); + put_user_ex(regs->bx, &sc->bx); + put_user_ex(regs->dx, &sc->dx); + put_user_ex(regs->cx, &sc->cx); + put_user_ex(regs->ax, &sc->ax); + put_user_ex(current->thread.trap_no, &sc->trapno); + put_user_ex(current->thread.error_code, &sc->err); + put_user_ex(regs->ip, &sc->ip); + put_user_ex(regs->cs, (unsigned int __user *)&sc->cs); + put_user_ex(regs->flags, &sc->flags); + put_user_ex(regs->sp, &sc->sp_at_signal); + put_user_ex(regs->ss, (unsigned int __user *)&sc->ss); + + put_user_ex(ptr_to_compat(fpstate), &sc->fpstate); + + /* non-iBCS2 extensions.. */ + put_user_ex(mask, &sc->oldmask); + put_user_ex(current->thread.cr2, &sc->cr2); + } put_user_catch(err); return err; } @@ -437,13 +459,17 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, else restorer = &frame->retcode; } - err |= __put_user(ptr_to_compat(restorer), &frame->pretcode); - /* - * These are actually not used anymore, but left because some - * gdb versions depend on them as a marker. - */ - err |= __put_user(*((u64 *)&code), (u64 *)frame->retcode); + put_user_try { + put_user_ex(ptr_to_compat(restorer), &frame->pretcode); + + /* + * These are actually not used anymore, but left because some + * gdb versions depend on them as a marker. + */ + put_user_ex(*((u64 *)&code), (u64 *)frame->retcode); + } put_user_catch(err); + if (err) return -EFAULT; @@ -496,41 +522,40 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return -EFAULT; - err |= __put_user(sig, &frame->sig); - err |= __put_user(ptr_to_compat(&frame->info), &frame->pinfo); - err |= __put_user(ptr_to_compat(&frame->uc), &frame->puc); - err |= copy_siginfo_to_user32(&frame->info, info); - if (err) - return -EFAULT; + put_user_try { + put_user_ex(sig, &frame->sig); + put_user_ex(ptr_to_compat(&frame->info), &frame->pinfo); + put_user_ex(ptr_to_compat(&frame->uc), &frame->puc); + err |= copy_siginfo_to_user32(&frame->info, info); - /* Create the ucontext. */ - if (cpu_has_xsave) - err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags); - else - err |= __put_user(0, &frame->uc.uc_flags); - err |= __put_user(0, &frame->uc.uc_link); - err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); - err |= __put_user(sas_ss_flags(regs->sp), - &frame->uc.uc_stack.ss_flags); - err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); - err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate, - regs, set->sig[0]); - err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); - if (err) - return -EFAULT; + /* Create the ucontext. */ + if (cpu_has_xsave) + put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags); + else + put_user_ex(0, &frame->uc.uc_flags); + put_user_ex(0, &frame->uc.uc_link); + put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); + put_user_ex(sas_ss_flags(regs->sp), + &frame->uc.uc_stack.ss_flags); + put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate, + regs, set->sig[0]); + err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + + if (ka->sa.sa_flags & SA_RESTORER) + restorer = ka->sa.sa_restorer; + else + restorer = VDSO32_SYMBOL(current->mm->context.vdso, + rt_sigreturn); + put_user_ex(ptr_to_compat(restorer), &frame->pretcode); + + /* + * Not actually used anymore, but left because some gdb + * versions need it. + */ + put_user_ex(*((u64 *)&code), (u64 *)frame->retcode); + } put_user_catch(err); - if (ka->sa.sa_flags & SA_RESTORER) - restorer = ka->sa.sa_restorer; - else - restorer = VDSO32_SYMBOL(current->mm->context.vdso, - rt_sigreturn); - err |= __put_user(ptr_to_compat(restorer), &frame->pretcode); - - /* - * Not actually used anymore, but left because some gdb - * versions need it. - */ - err |= __put_user(*((u64 *)&code), (u64 *)frame->retcode); if (err) return -EFAULT; -- GitLab From b1882e68d17a93b523dce09c3a181319aace2f0e Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 23 Jan 2009 17:18:52 -0800 Subject: [PATCH 0427/4982] x86: clean up stray space in Impact: Whitespace cleanup only Clean up a stray space character in arch/x86/include/asm/processor.h. Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/processor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 091cd8855f2..ac8fab3b868 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -73,7 +73,7 @@ struct cpuinfo_x86 { char pad0; #else /* Number of 4K pages in DTLB/ITLB combined(in pages): */ - int x86_tlbsize; + int x86_tlbsize; __u8 x86_virt_bits; __u8 x86_phys_bits; #endif -- GitLab From 75a048119e76540d73132cfc8e0fa0c0a8bb6c83 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 22 Jan 2009 16:17:05 -0800 Subject: [PATCH 0428/4982] x86: handle PAT more like other CPU features Impact: Cleanup When PAT was originally introduced, it was handled specially for a few reasons: - PAT bugs are hard to track down, so we wanted to maintain a whitelist of CPUs. - The i386 and x86-64 CPUID code was not yet unified. Both of these are now obsolete, so handle PAT like any other features, including ordinary feature blacklisting due to known bugs. Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/pat.h | 4 --- arch/x86/kernel/cpu/addon_cpuid_features.c | 34 ---------------------- arch/x86/kernel/cpu/common.c | 2 -- arch/x86/kernel/cpu/intel.c | 12 ++++++++ arch/x86/mm/pat.c | 31 +++++++++++++------- 5 files changed, 32 insertions(+), 51 deletions(-) diff --git a/arch/x86/include/asm/pat.h b/arch/x86/include/asm/pat.h index b8493b3b989..9709fdff661 100644 --- a/arch/x86/include/asm/pat.h +++ b/arch/x86/include/asm/pat.h @@ -5,10 +5,8 @@ #ifdef CONFIG_X86_PAT extern int pat_enabled; -extern void validate_pat_support(struct cpuinfo_x86 *c); #else static const int pat_enabled; -static inline void validate_pat_support(struct cpuinfo_x86 *c) { } #endif extern void pat_init(void); @@ -17,6 +15,4 @@ extern int reserve_memtype(u64 start, u64 end, unsigned long req_type, unsigned long *ret_type); extern int free_memtype(u64 start, u64 end); -extern void pat_disable(char *reason); - #endif /* _ASM_X86_PAT_H */ diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c index 2cf23634b6d..4e581fdc0a5 100644 --- a/arch/x86/kernel/cpu/addon_cpuid_features.c +++ b/arch/x86/kernel/cpu/addon_cpuid_features.c @@ -143,37 +143,3 @@ void __cpuinit detect_extended_topology(struct cpuinfo_x86 *c) return; #endif } - -#ifdef CONFIG_X86_PAT -void __cpuinit validate_pat_support(struct cpuinfo_x86 *c) -{ - if (!cpu_has_pat) - pat_disable("PAT not supported by CPU."); - - switch (c->x86_vendor) { - case X86_VENDOR_INTEL: - /* - * There is a known erratum on Pentium III and Core Solo - * and Core Duo CPUs. - * " Page with PAT set to WC while associated MTRR is UC - * may consolidate to UC " - * Because of this erratum, it is better to stick with - * setting WC in MTRR rather than using PAT on these CPUs. - * - * Enable PAT WC only on P4, Core 2 or later CPUs. - */ - if (c->x86 > 0x6 || (c->x86 == 6 && c->x86_model >= 15)) - return; - - pat_disable("PAT WC disabled due to known CPU erratum."); - return; - - case X86_VENDOR_AMD: - case X86_VENDOR_CENTAUR: - case X86_VENDOR_TRANSMETA: - return; - } - - pat_disable("PAT disabled. Not yet verified on this CPU type."); -} -#endif diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 83492b1f93b..0f8656361e0 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -570,8 +570,6 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c) if (this_cpu->c_early_init) this_cpu->c_early_init(c); - validate_pat_support(c); - #ifdef CONFIG_SMP c->cpu_index = boot_cpu_id; #endif diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 8ea6929e974..20ce03acf04 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -50,6 +50,18 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC); } + /* + * There is a known erratum on Pentium III and Core Solo + * and Core Duo CPUs. + * " Page with PAT set to WC while associated MTRR is UC + * may consolidate to UC " + * Because of this erratum, it is better to stick with + * setting WC in MTRR rather than using PAT on these CPUs. + * + * Enable PAT WC only on P4, Core 2 or later CPUs. + */ + if (c->x86 == 6 && c->x86_model < 15) + clear_cpu_cap(c, X86_FEATURE_PAT); } #ifdef CONFIG_X86_32 diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index 8b08fb95527..430cb44dd3f 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -30,7 +30,7 @@ #ifdef CONFIG_X86_PAT int __read_mostly pat_enabled = 1; -void __cpuinit pat_disable(char *reason) +void __cpuinit pat_disable(const char *reason) { pat_enabled = 0; printk(KERN_INFO "%s\n", reason); @@ -42,6 +42,11 @@ static int __init nopat(char *str) return 0; } early_param("nopat", nopat); +#else +static inline void pat_disable(const char *reason) +{ + (void)reason; +} #endif @@ -78,16 +83,20 @@ void pat_init(void) if (!pat_enabled) return; - /* Paranoia check. */ - if (!cpu_has_pat && boot_pat_state) { - /* - * If this happens we are on a secondary CPU, but - * switched to PAT on the boot CPU. We have no way to - * undo PAT. - */ - printk(KERN_ERR "PAT enabled, " - "but not supported by secondary CPU\n"); - BUG(); + if (!cpu_has_pat) { + if (!boot_pat_state) { + pat_disable("PAT not supported by CPU."); + return; + } else { + /* + * If this happens we are on a secondary CPU, but + * switched to PAT on the boot CPU. We have no way to + * undo PAT. + */ + printk(KERN_ERR "PAT enabled, " + "but not supported by secondary CPU\n"); + BUG(); + } } /* Set PWT to Write-Combining. All other bits stay the same */ -- GitLab From b38b0665905538e76e26f2a4c686179abb1f69f6 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 23 Jan 2009 17:20:50 -0800 Subject: [PATCH 0429/4982] x86: filter CPU features dependent on unavailable CPUID levels Impact: Fixes potential crashes on misconfigured systems. Some CPU features require specific CPUID levels to be available in order to function, as they contain information about the operation of a specific feature. However, some BIOSes and virtualization software provide the ability to mask CPUID levels in order to support legacy operating systems. We try to enable such CPUID levels when we know how to do it, but for the remaining cases, filter out such CPU features when there is no way for us to support them. Do this in one place, in the CPUID code, with a table-driven approach. Signed-off-by: H. Peter Anvin --- arch/x86/kernel/cpu/common.c | 47 ++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 0f8656361e0..21f086b4c1a 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -212,6 +212,49 @@ static inline void squash_the_stupid_serial_number(struct cpuinfo_x86 *c) } #endif +/* + * Some CPU features depend on higher CPUID levels, which may not always + * be available due to CPUID level capping or broken virtualization + * software. Add those features to this table to auto-disable them. + */ +struct cpuid_dependent_feature { + u32 feature; + u32 level; +}; +static const struct cpuid_dependent_feature __cpuinitconst +cpuid_dependent_features[] = { + { X86_FEATURE_MWAIT, 0x00000005 }, + { X86_FEATURE_DCA, 0x00000009 }, + { X86_FEATURE_XSAVE, 0x0000000d }, + { 0, 0 } +}; + +static void __cpuinit filter_cpuid_features(struct cpuinfo_x86 *c, bool warn) +{ + const struct cpuid_dependent_feature *df; + for (df = cpuid_dependent_features; df->feature; df++) { + /* + * Note: cpuid_level is set to -1 if unavailable, but + * extended_extended_level is set to 0 if unavailable + * and the legitimate extended levels are all negative + * when signed; hence the weird messing around with + * signs here... + */ + if (cpu_has(c, df->feature) && + ((s32)df->feature < 0 ? + (u32)df->feature > (u32)c->extended_cpuid_level : + (s32)df->feature > (s32)c->cpuid_level)) { + clear_cpu_cap(c, df->feature); + if (warn) + printk(KERN_WARNING + "CPU: CPU feature %s disabled " + "due to lack of CPUID level 0x%x\n", + x86_cap_flags[df->feature], + df->level); + } + } +} + /* * Naming convention should be: [()] * This table only is used unless init_() below doesn't set it; @@ -573,6 +616,7 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c) #ifdef CONFIG_SMP c->cpu_index = boot_cpu_id; #endif + filter_cpuid_features(c, false); } void __init early_cpu_init(void) @@ -706,6 +750,9 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) * we do "generic changes." */ + /* Filter out anything that depends on CPUID levels we don't have */ + filter_cpuid_features(c, true); + /* If the model name is still unset, do table lookup. */ if (!c->x86_model_id[0]) { char *p; -- GitLab From 0db155de988031f925096a7df1bf9633790a2c18 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 23 Jan 2009 22:28:48 -0800 Subject: [PATCH 0430/4982] com20020: Fix allyesconfig build failure. Reported by Stephen Rothwell. Due to missing 'extern' in the com20020_netdev_ops declaration, each file that includes linux/com20020.h gets another copy defined in it's resulting object file. Signed-off-by: David S. Miller --- include/linux/com20020.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/com20020.h b/include/linux/com20020.h index 350afa773f8..5dcfb944b6c 100644 --- a/include/linux/com20020.h +++ b/include/linux/com20020.h @@ -29,7 +29,7 @@ int com20020_check(struct net_device *dev); int com20020_found(struct net_device *dev, int shared); -const struct net_device_ops com20020_netdev_ops; +extern const struct net_device_ops com20020_netdev_ops; /* The number of low I/O ports used by the card. */ #define ARCNET_TOTAL_SIZE 8 -- GitLab From 6626bff24578753808c8b5bd4f1619e14e980f0f Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sun, 25 Jan 2009 11:31:36 +0100 Subject: [PATCH 0431/4982] hrtimer: prevent negative expiry value after clock_was_set() Impact: prevent false positive WARN_ON() in clockevents_program_event() clock_was_set() changes the base->offset of CLOCK_REALTIME and enforces the reprogramming of the clockevent device to expire timers which are based on CLOCK_REALTIME. If the clock change is large enough then the subtraction of the timer expiry value and base->offset can become negative which triggers the warning in clockevents_program_event(). Check the subtraction result and set a negative value to 0. Signed-off-by: Thomas Gleixner --- kernel/hrtimer.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 2c40ee8f44b..d71cef25954 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -501,6 +501,13 @@ static void hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base) continue; timer = rb_entry(base->first, struct hrtimer, node); expires = ktime_sub(hrtimer_get_expires(timer), base->offset); + /* + * clock_was_set() has changed base->offset so the + * result might be negative. Fix it up to prevent a + * false positive in clockevents_program_event() + */ + if (expires.tv64 < 0) + expires.tv64 = 0; if (expires.tv64 < cpu_base->expires_next.tv64) cpu_base->expires_next = expires; } -- GitLab From 01a1ac472f3cd3e24a5f70597346773115ef4586 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Sun, 25 Jan 2009 17:53:58 -0800 Subject: [PATCH 0432/4982] smsc95xx: remove unused completion struct Oliver Neukum spotted the useless complete() in our async callback. On closer inspection, the entire completion struct is unused. This patch removes it. Signed-off-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/usb/smsc95xx.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 5574abe29c7..26fabefdfd3 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -55,7 +55,6 @@ struct smsc95xx_priv { struct usb_context { struct usb_ctrlrequest req; - struct completion notify; struct usbnet *dev; }; @@ -316,8 +315,6 @@ static void smsc95xx_async_cmd_callback(struct urb *urb, struct pt_regs *regs) if (status < 0) devwarn(dev, "async callback failed with %d", status); - complete(&usb_context->notify); - kfree(usb_context); usb_free_urb(urb); } @@ -348,7 +345,6 @@ static int smsc95xx_write_reg_async(struct usbnet *dev, u16 index, u32 *data) usb_context->req.wValue = 00; usb_context->req.wIndex = cpu_to_le16(index); usb_context->req.wLength = cpu_to_le16(size); - init_completion(&usb_context->notify); usb_fill_control_urb(urb, dev->udev, usb_sndctrlpipe(dev->udev, 0), (void *)&usb_context->req, data, size, -- GitLab From 150a7fcc5ccf6ffe4a2280f5a447d104ec77912d Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Sun, 25 Jan 2009 17:54:46 -0800 Subject: [PATCH 0433/4982] smsc95xx: fix function prototype of async callback smsc95xx_async_cmd_callback doesn't currently match usb_complete_t, so there's a cast to force the square peg into the round hole. This patch fixes this properly. Signed-off-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/usb/smsc95xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 26fabefdfd3..5b0b9647382 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -306,7 +306,7 @@ static int smsc95xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length, return 0; } -static void smsc95xx_async_cmd_callback(struct urb *urb, struct pt_regs *regs) +static void smsc95xx_async_cmd_callback(struct urb *urb) { struct usb_context *usb_context = urb->context; struct usbnet *dev = usb_context->dev; @@ -348,7 +348,7 @@ static int smsc95xx_write_reg_async(struct usbnet *dev, u16 index, u32 *data) usb_fill_control_urb(urb, dev->udev, usb_sndctrlpipe(dev->udev, 0), (void *)&usb_context->req, data, size, - (usb_complete_t)smsc95xx_async_cmd_callback, + smsc95xx_async_cmd_callback, (void *)usb_context); status = usb_submit_urb(urb, GFP_ATOMIC); -- GitLab From 4811fcb79cee80c683237cfd15ca214e1d78c548 Mon Sep 17 00:00:00 2001 From: Andy Richter Date: Tue, 20 Jan 2009 06:14:33 +0000 Subject: [PATCH 0434/4982] kmsg: convert claw printk messages claw printks are converted to dev_xxx and pr_xxx macros. Signed-off-by: Andy Richter Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- drivers/s390/net/claw.c | 431 ++++++++++++++++++++++------------------ 1 file changed, 233 insertions(+), 198 deletions(-) diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index 3cb387f45b6..6669adf355b 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -60,6 +60,9 @@ * 1.25 Added Packing support * 1.5 */ + +#define KMSG_COMPONENT "claw" + #include #include #include @@ -94,7 +97,7 @@ CLAW uses the s390dbf file system see claw_trace and claw_setup */ - +static char version[] __initdata = "CLAW driver"; static char debug_buffer[255]; /** * Debug Facility Stuff @@ -206,20 +209,30 @@ static struct net_device_stats *claw_stats(struct net_device *dev); static int pages_to_order_of_mag(int num_of_pages); static struct sk_buff *claw_pack_skb(struct claw_privbk *privptr); /* sysfs Functions */ -static ssize_t claw_hname_show(struct device *dev, struct device_attribute *attr, char *buf); -static ssize_t claw_hname_write(struct device *dev, struct device_attribute *attr, +static ssize_t claw_hname_show(struct device *dev, + struct device_attribute *attr, char *buf); +static ssize_t claw_hname_write(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); -static ssize_t claw_adname_show(struct device *dev, struct device_attribute *attr, char *buf); -static ssize_t claw_adname_write(struct device *dev, struct device_attribute *attr, +static ssize_t claw_adname_show(struct device *dev, + struct device_attribute *attr, char *buf); +static ssize_t claw_adname_write(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); -static ssize_t claw_apname_show(struct device *dev, struct device_attribute *attr, char *buf); -static ssize_t claw_apname_write(struct device *dev, struct device_attribute *attr, +static ssize_t claw_apname_show(struct device *dev, + struct device_attribute *attr, char *buf); +static ssize_t claw_apname_write(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); -static ssize_t claw_wbuff_show(struct device *dev, struct device_attribute *attr, char *buf); -static ssize_t claw_wbuff_write(struct device *dev, struct device_attribute *attr, +static ssize_t claw_wbuff_show(struct device *dev, + struct device_attribute *attr, char *buf); +static ssize_t claw_wbuff_write(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); -static ssize_t claw_rbuff_show(struct device *dev, struct device_attribute *attr, char *buf); -static ssize_t claw_rbuff_write(struct device *dev, struct device_attribute *attr, +static ssize_t claw_rbuff_show(struct device *dev, + struct device_attribute *attr, char *buf); +static ssize_t claw_rbuff_write(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); static int claw_add_files(struct device *dev); static void claw_remove_files(struct device *dev); @@ -298,8 +311,8 @@ claw_probe(struct ccwgroup_device *cgdev) if (rc) { probe_error(cgdev); put_device(&cgdev->dev); - printk(KERN_WARNING "add_files failed %s %s Exit Line %d \n", - dev_name(&cgdev->cdev[0]->dev), __func__, __LINE__); + dev_err(&cgdev->dev, "Creating the /proc files for a new" + " CLAW device failed\n"); CLAW_DBF_TEXT_(2, setup, "probex%d", rc); return rc; } @@ -496,7 +509,8 @@ claw_open(struct net_device *dev) ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) || (((privptr->channel[READ].flag | privptr->channel[WRITE].flag) & CLAW_TIMER) != 0x00)) { - printk(KERN_INFO "%s: remote side is not ready\n", dev->name); + dev_info(&privptr->channel[READ].cdev->dev, + "%s: remote side is not ready\n", dev->name); CLAW_DBF_TEXT(2, trace, "notrdy"); for ( i = 0; i < 2; i++) { @@ -582,10 +596,9 @@ claw_irq_handler(struct ccw_device *cdev, CLAW_DBF_TEXT(4, trace, "clawirq"); /* Bypass all 'unsolicited interrupts' */ if (!cdev->dev.driver_data) { - printk(KERN_WARNING "claw: unsolicited interrupt for device:" - "%s received c-%02x d-%02x\n", - dev_name(&cdev->dev), irb->scsw.cmd.cstat, - irb->scsw.cmd.dstat); + dev_warn(&cdev->dev, "An uninitialized CLAW device received an" + " IRQ, c-%02x d-%02x\n", + irb->scsw.cmd.cstat, irb->scsw.cmd.dstat); CLAW_DBF_TEXT(2, trace, "badirq"); return; } @@ -597,8 +610,7 @@ claw_irq_handler(struct ccw_device *cdev, else if (privptr->channel[WRITE].cdev == cdev) p_ch = &privptr->channel[WRITE]; else { - printk(KERN_WARNING "claw: Can't determine channel for " - "interrupt, device %s\n", dev_name(&cdev->dev)); + dev_warn(&cdev->dev, "The device is not a CLAW device\n"); CLAW_DBF_TEXT(2, trace, "badchan"); return; } @@ -612,7 +624,8 @@ claw_irq_handler(struct ccw_device *cdev, /* Check for good subchannel return code, otherwise info message */ if (irb->scsw.cmd.cstat && !(irb->scsw.cmd.cstat & SCHN_STAT_PCI)) { - printk(KERN_INFO "%s: subchannel check for device: %04x -" + dev_info(&cdev->dev, + "%s: subchannel check for device: %04x -" " Sch Stat %02x Dev Stat %02x CPA - %04x\n", dev->name, p_ch->devno, irb->scsw.cmd.cstat, irb->scsw.cmd.dstat, @@ -651,7 +664,7 @@ claw_irq_handler(struct ccw_device *cdev, wake_up(&p_ch->wait); /* wake claw_open (READ)*/ } else if (p_ch->flag == CLAW_WRITE) { p_ch->claw_state = CLAW_START_WRITE; - /* send SYSTEM_VALIDATE */ + /* send SYSTEM_VALIDATE */ claw_strt_read(dev, LOCK_NO); claw_send_control(dev, SYSTEM_VALIDATE_REQUEST, @@ -659,10 +672,9 @@ claw_irq_handler(struct ccw_device *cdev, p_env->host_name, p_env->adapter_name); } else { - printk(KERN_WARNING "claw: unsolicited " - "interrupt for device:" - "%s received c-%02x d-%02x\n", - dev_name(&cdev->dev), + dev_warn(&cdev->dev, "The CLAW device received" + " an unexpected IRQ, " + "c-%02x d-%02x\n", irb->scsw.cmd.cstat, irb->scsw.cmd.dstat); return; @@ -677,8 +689,8 @@ claw_irq_handler(struct ccw_device *cdev, (p_ch->irb->ecw[0] & 0x40) == 0x40 || (p_ch->irb->ecw[0]) == 0) { privptr->stats.rx_errors++; - printk(KERN_INFO "%s: Restart is " - "required after remote " + dev_info(&cdev->dev, + "%s: Restart is required after remote " "side recovers \n", dev->name); } @@ -713,11 +725,13 @@ claw_irq_handler(struct ccw_device *cdev, return; case CLAW_START_WRITE: if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) { - printk(KERN_INFO "%s: Unit Check Occured in " + dev_info(&cdev->dev, + "%s: Unit Check Occured in " "write channel\n", dev->name); clear_bit(0, (void *)&p_ch->IO_active); if (p_ch->irb->ecw[0] & 0x80) { - printk(KERN_INFO "%s: Resetting Event " + dev_info(&cdev->dev, + "%s: Resetting Event " "occurred:\n", dev->name); init_timer(&p_ch->timer); p_ch->timer.function = @@ -725,7 +739,8 @@ claw_irq_handler(struct ccw_device *cdev, p_ch->timer.data = (unsigned long)p_ch; p_ch->timer.expires = jiffies + 10*HZ; add_timer(&p_ch->timer); - printk(KERN_INFO "%s: write connection " + dev_info(&cdev->dev, + "%s: write connection " "restarting\n", dev->name); } CLAW_DBF_TEXT(4, trace, "rstrtwrt"); @@ -733,9 +748,10 @@ claw_irq_handler(struct ccw_device *cdev, } if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_EXCEP) { clear_bit(0, (void *)&p_ch->IO_active); - printk(KERN_INFO "%s: Unit Exception " - "Occured in write channel\n", - dev->name); + dev_info(&cdev->dev, + "%s: Unit Exception " + "occurred in write channel\n", + dev->name); } if (!((p_ch->irb->scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS) || (p_ch->irb->scsw.cmd.stctl == SCSW_STCTL_STATUS_PEND) || @@ -757,8 +773,9 @@ claw_irq_handler(struct ccw_device *cdev, CLAW_DBF_TEXT(4, trace, "StWtExit"); return; default: - printk(KERN_WARNING "%s: wrong selection code - irq " - "state=%d\n", dev->name, p_ch->claw_state); + dev_warn(&cdev->dev, + "The CLAW device for %s received an unexpected IRQ\n", + dev->name); CLAW_DBF_TEXT(2, trace, "badIRQ"); return; } @@ -910,8 +927,10 @@ claw_release(struct net_device *dev) if (((privptr->channel[READ].last_dstat | privptr->channel[WRITE].last_dstat) & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) { - printk(KERN_WARNING "%s: channel problems during close - " - "read: %02x - write: %02x\n", + dev_warn(&privptr->channel[READ].cdev->dev, + "Deactivating %s completed with incorrect" + " subchannel status " + "(read %02x, write %02x)\n", dev->name, privptr->channel[READ].last_dstat, privptr->channel[WRITE].last_dstat); @@ -1076,8 +1095,8 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first, } if ( privptr-> p_read_active_first ==NULL ) { - privptr-> p_read_active_first= p_first; /* set new first */ - privptr-> p_read_active_last = p_last; /* set new last */ + privptr->p_read_active_first = p_first; /* set new first */ + privptr->p_read_active_last = p_last; /* set new last */ } else { @@ -1113,7 +1132,7 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first, privptr->p_read_active_last->r_TIC_2.cda= (__u32)__pa(&p_first->read); } - /* chain in new set of blocks */ + /* chain in new set of blocks */ privptr->p_read_active_last->next = p_first; privptr->p_read_active_last=p_last; } /* end of if ( privptr-> p_read_active_first ==NULL) */ @@ -1135,21 +1154,18 @@ ccw_check_return_code(struct ccw_device *cdev, int return_code) case -EBUSY: /* BUSY is a transient state no action needed */ break; case -ENODEV: - printk(KERN_EMERG "%s: Missing device called " - "for IO ENODEV\n", dev_name(&cdev->dev)); - break; - case -EIO: - printk(KERN_EMERG "%s: Status pending... EIO \n", - dev_name(&cdev->dev)); + dev_err(&cdev->dev, "The remote channel adapter is not" + " available\n"); break; case -EINVAL: - printk(KERN_EMERG "%s: Invalid Dev State EINVAL \n", - dev_name(&cdev->dev)); + dev_err(&cdev->dev, + "The status of the remote channel adapter" + " is not valid\n"); break; default: - printk(KERN_EMERG "%s: Unknown error in " - "Do_IO %d\n", dev_name(&cdev->dev), - return_code); + dev_err(&cdev->dev, "The common device layer" + " returned error code %d\n", + return_code); } } CLAW_DBF_TEXT(4, trace, "ccwret"); @@ -1163,40 +1179,41 @@ static void ccw_check_unit_check(struct chbk * p_ch, unsigned char sense ) { struct net_device *ndev = p_ch->ndev; + struct device *dev = &p_ch->cdev->dev; CLAW_DBF_TEXT(4, trace, "unitchek"); - printk(KERN_INFO "%s: Unit Check with sense byte:0x%04x\n", - ndev->name, sense); + dev_warn(dev, "The communication peer of %s disconnected\n", + ndev->name); if (sense & 0x40) { if (sense & 0x01) { - printk(KERN_WARNING "%s: Interface disconnect or " - "Selective reset " - "occurred (remote side)\n", ndev->name); - } - else { - printk(KERN_WARNING "%s: System reset occured" - " (remote side)\n", ndev->name); + dev_warn(dev, "The remote channel adapter for" + " %s has been reset\n", + ndev->name); } } else if (sense & 0x20) { if (sense & 0x04) { - printk(KERN_WARNING "%s: Data-streaming " - "timeout)\n", ndev->name); + dev_warn(dev, "A data streaming timeout occurred" + " for %s\n", + ndev->name); } else { - printk(KERN_WARNING "%s: Data-transfer parity" - " error\n", ndev->name); + dev_warn(dev, "A data transfer parity error occurred" + " for %s\n", + ndev->name); } } else if (sense & 0x10) { if (sense & 0x20) { - printk(KERN_WARNING "%s: Hardware malfunction " - "(remote side)\n", ndev->name); + dev_warn(dev, "The remote channel adapter for %s" + " is faulty\n", + ndev->name); } else { - printk(KERN_WARNING "%s: read-data parity error " - "(remote side)\n", ndev->name); + dev_warn(dev, "A read data parity error occurred" + " for %s\n", + ndev->name); } } @@ -1375,7 +1392,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid) */ if (p_first_ccw!=NULL) { - /* setup ending ccw sequence for this segment */ + /* setup ending ccw sequence for this segment */ pEnd=privptr->p_end_ccw; if (pEnd->write1) { pEnd->write1=0x00; /* second end ccw is now active */ @@ -1697,10 +1714,11 @@ init_ccw_bk(struct net_device *dev) p_buf-> w_TIC_1.flags = 0; p_buf-> w_TIC_1.count = 0; - if (((unsigned long)p_buff+privptr->p_env->write_size) >= + if (((unsigned long)p_buff + + privptr->p_env->write_size) >= ((unsigned long)(p_buff+2* - (privptr->p_env->write_size) -1) & PAGE_MASK)) { - p_buff= p_buff+privptr->p_env->write_size; + (privptr->p_env->write_size) - 1) & PAGE_MASK)) { + p_buff = p_buff+privptr->p_env->write_size; } } } @@ -1840,15 +1858,16 @@ init_ccw_bk(struct net_device *dev) p_buf->header.opcode=0xff; p_buf->header.flag=CLAW_PENDING; - if (((unsigned long)p_buff+privptr->p_env->read_size) >= - ((unsigned long)(p_buff+2*(privptr->p_env->read_size) -1) - & PAGE_MASK) ) { + if (((unsigned long)p_buff+privptr->p_env->read_size) >= + ((unsigned long)(p_buff+2*(privptr->p_env->read_size) + -1) + & PAGE_MASK)) { p_buff= p_buff+privptr->p_env->read_size; } else { p_buff= (void *)((unsigned long) - (p_buff+2*(privptr->p_env->read_size) -1) + (p_buff+2*(privptr->p_env->read_size)-1) & PAGE_MASK) ; } } /* for read_buffers */ @@ -1856,24 +1875,28 @@ init_ccw_bk(struct net_device *dev) else { /* read Size >= PAGE_SIZE */ for (i=0 ; i< privptr->p_env->read_buffers ; i++) { p_buff = (void *)__get_free_pages(__GFP_DMA, - (int)pages_to_order_of_mag(privptr->p_buff_pages_perread) ); + (int)pages_to_order_of_mag( + privptr->p_buff_pages_perread)); if (p_buff==NULL) { free_pages((unsigned long)privptr->p_buff_ccw, - (int)pages_to_order_of_mag(privptr->p_buff_ccw_num)); + (int)pages_to_order_of_mag(privptr-> + p_buff_ccw_num)); /* free the write pages */ p_buf=privptr->p_buff_write; while (p_buf!=NULL) { - free_pages((unsigned long)p_buf->p_buffer, - (int)pages_to_order_of_mag( - privptr->p_buff_pages_perwrite )); + free_pages( + (unsigned long)p_buf->p_buffer, + (int)pages_to_order_of_mag( + privptr->p_buff_pages_perwrite)); p_buf=p_buf->next; } /* free any read pages already alloc */ p_buf=privptr->p_buff_read; while (p_buf!=NULL) { - free_pages((unsigned long)p_buf->p_buffer, - (int)pages_to_order_of_mag( - privptr->p_buff_pages_perread )); + free_pages( + (unsigned long)p_buf->p_buffer, + (int)pages_to_order_of_mag( + privptr->p_buff_pages_perread)); p_buf=p_buf->next; } privptr->p_buff_ccw=NULL; @@ -2003,7 +2026,7 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw) tdev = &privptr->channel[READ].cdev->dev; memcpy( &temp_host_name, p_env->host_name, 8); memcpy( &temp_ws_name, p_env->adapter_name , 8); - printk(KERN_INFO "%s: CLAW device %.8s: " + dev_info(tdev, "%s: CLAW device %.8s: " "Received Control Packet\n", dev->name, temp_ws_name); if (privptr->release_pend==1) { @@ -2022,32 +2045,30 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw) if (p_ctlbk->version != CLAW_VERSION_ID) { claw_snd_sys_validate_rsp(dev, p_ctlbk, CLAW_RC_WRONG_VERSION); - printk("%s: %d is wrong version id. " - "Expected %d\n", - dev->name, p_ctlbk->version, - CLAW_VERSION_ID); + dev_warn(tdev, "The communication peer of %s" + " uses an incorrect API version %d\n", + dev->name, p_ctlbk->version); } p_sysval = (struct sysval *)&(p_ctlbk->data); - printk("%s: Recv Sys Validate Request: " - "Vers=%d,link_id=%d,Corr=%d,WS name=%." - "8s,Host name=%.8s\n", - dev->name, p_ctlbk->version, - p_ctlbk->linkid, - p_ctlbk->correlator, - p_sysval->WS_name, - p_sysval->host_name); + dev_info(tdev, "%s: Recv Sys Validate Request: " + "Vers=%d,link_id=%d,Corr=%d,WS name=%.8s," + "Host name=%.8s\n", + dev->name, p_ctlbk->version, + p_ctlbk->linkid, + p_ctlbk->correlator, + p_sysval->WS_name, + p_sysval->host_name); if (memcmp(temp_host_name, p_sysval->host_name, 8)) { claw_snd_sys_validate_rsp(dev, p_ctlbk, CLAW_RC_NAME_MISMATCH); CLAW_DBF_TEXT(2, setup, "HSTBAD"); CLAW_DBF_TEXT_(2, setup, "%s", p_sysval->host_name); CLAW_DBF_TEXT_(2, setup, "%s", temp_host_name); - printk(KERN_INFO "%s: Host name mismatch\n", - dev->name); - printk(KERN_INFO "%s: Received :%s: " - "expected :%s: \n", - dev->name, + dev_warn(tdev, + "Host name %s for %s does not match the" + " remote adapter name %s\n", p_sysval->host_name, + dev->name, temp_host_name); } if (memcmp(temp_ws_name, p_sysval->WS_name, 8)) { @@ -2056,35 +2077,38 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw) CLAW_DBF_TEXT(2, setup, "WSNBAD"); CLAW_DBF_TEXT_(2, setup, "%s", p_sysval->WS_name); CLAW_DBF_TEXT_(2, setup, "%s", temp_ws_name); - printk(KERN_INFO "%s: WS name mismatch\n", - dev->name); - printk(KERN_INFO "%s: Received :%s: " - "expected :%s: \n", - dev->name, - p_sysval->WS_name, - temp_ws_name); + dev_warn(tdev, "Adapter name %s for %s does not match" + " the remote host name %s\n", + p_sysval->WS_name, + dev->name, + temp_ws_name); } if ((p_sysval->write_frame_size < p_env->write_size) && (p_env->packing == 0)) { claw_snd_sys_validate_rsp(dev, p_ctlbk, CLAW_RC_HOST_RCV_TOO_SMALL); - printk(KERN_INFO "%s: host write size is too " - "small\n", dev->name); + dev_warn(tdev, + "The local write buffer is smaller than the" + " remote read buffer\n"); CLAW_DBF_TEXT(2, setup, "wrtszbad"); } if ((p_sysval->read_frame_size < p_env->read_size) && (p_env->packing == 0)) { claw_snd_sys_validate_rsp(dev, p_ctlbk, CLAW_RC_HOST_RCV_TOO_SMALL); - printk(KERN_INFO "%s: host read size is too " - "small\n", dev->name); + dev_warn(tdev, + "The local read buffer is smaller than the" + " remote write buffer\n"); CLAW_DBF_TEXT(2, setup, "rdsizbad"); } claw_snd_sys_validate_rsp(dev, p_ctlbk, 0); - printk(KERN_INFO "%s: CLAW device %.8s: System validate " - "completed.\n", dev->name, temp_ws_name); - printk("%s: sys Validate Rsize:%d Wsize:%d\n", dev->name, - p_sysval->read_frame_size, p_sysval->write_frame_size); + dev_info(tdev, + "CLAW device %.8s: System validate" + " completed.\n", temp_ws_name); + dev_info(tdev, + "%s: sys Validate Rsize:%d Wsize:%d\n", + dev->name, p_sysval->read_frame_size, + p_sysval->write_frame_size); privptr->system_validate_comp = 1; if (strncmp(p_env->api_type, WS_APPL_NAME_PACKED, 6) == 0) p_env->packing = PACKING_ASK; @@ -2092,8 +2116,10 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw) break; case SYSTEM_VALIDATE_RESPONSE: p_sysval = (struct sysval *)&(p_ctlbk->data); - printk("%s: Recv Sys Validate Resp: Vers=%d,Corr=%d,RC=%d," - "WS name=%.8s,Host name=%.8s\n", + dev_info(tdev, + "Settings for %s validated (version=%d, " + "remote device=%d, rc=%d, adapter name=%.8s, " + "host name=%.8s)\n", dev->name, p_ctlbk->version, p_ctlbk->correlator, @@ -2102,41 +2128,39 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw) p_sysval->host_name); switch (p_ctlbk->rc) { case 0: - printk(KERN_INFO "%s: CLAW device " - "%.8s: System validate " - "completed.\n", - dev->name, temp_ws_name); + dev_info(tdev, "%s: CLAW device " + "%.8s: System validate completed.\n", + dev->name, temp_ws_name); if (privptr->system_validate_comp == 0) claw_strt_conn_req(dev); privptr->system_validate_comp = 1; break; case CLAW_RC_NAME_MISMATCH: - printk(KERN_INFO "%s: Sys Validate " - "Resp : Host, WS name is " - "mismatch\n", - dev->name); + dev_warn(tdev, "Validating %s failed because of" + " a host or adapter name mismatch\n", + dev->name); break; case CLAW_RC_WRONG_VERSION: - printk(KERN_INFO "%s: Sys Validate " - "Resp : Wrong version\n", + dev_warn(tdev, "Validating %s failed because of a" + " version conflict\n", dev->name); break; case CLAW_RC_HOST_RCV_TOO_SMALL: - printk(KERN_INFO "%s: Sys Validate " - "Resp : bad frame size\n", + dev_warn(tdev, "Validating %s failed because of a" + " frame size conflict\n", dev->name); break; default: - printk(KERN_INFO "%s: Sys Validate " - "error code=%d \n", - dev->name, p_ctlbk->rc); + dev_warn(tdev, "The communication peer of %s rejected" + " the connection\n", + dev->name); break; } break; case CONNECTION_REQUEST: p_connect = (struct conncmd *)&(p_ctlbk->data); - printk(KERN_INFO "%s: Recv Conn Req: Vers=%d,link_id=%d," + dev_info(tdev, "%s: Recv Conn Req: Vers=%d,link_id=%d," "Corr=%d,HOST appl=%.8s,WS appl=%.8s\n", dev->name, p_ctlbk->version, @@ -2146,21 +2170,21 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw) p_connect->WS_name); if (privptr->active_link_ID != 0) { claw_snd_disc(dev, p_ctlbk); - printk(KERN_INFO "%s: Conn Req error : " - "already logical link is active \n", + dev_info(tdev, "%s rejected a connection request" + " because it is already active\n", dev->name); } if (p_ctlbk->linkid != 1) { claw_snd_disc(dev, p_ctlbk); - printk(KERN_INFO "%s: Conn Req error : " - "req logical link id is not 1\n", + dev_info(tdev, "%s rejected a request to open multiple" + " connections\n", dev->name); } rc = find_link(dev, p_connect->host_name, p_connect->WS_name); if (rc != 0) { claw_snd_disc(dev, p_ctlbk); - printk(KERN_INFO "%s: Conn Resp error: " - "req appl name does not match\n", + dev_info(tdev, "%s rejected a connection request" + " because of a type mismatch\n", dev->name); } claw_send_control(dev, @@ -2172,7 +2196,7 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw) p_env->packing = PACK_SEND; claw_snd_conn_req(dev, 0); } - printk(KERN_INFO "%s: CLAW device %.8s: Connection " + dev_info(tdev, "%s: CLAW device %.8s: Connection " "completed link_id=%d.\n", dev->name, temp_ws_name, p_ctlbk->linkid); @@ -2182,7 +2206,7 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw) break; case CONNECTION_RESPONSE: p_connect = (struct conncmd *)&(p_ctlbk->data); - printk(KERN_INFO "%s: Revc Conn Resp: Vers=%d,link_id=%d," + dev_info(tdev, "%s: Recv Conn Resp: Vers=%d,link_id=%d," "Corr=%d,RC=%d,Host appl=%.8s, WS appl=%.8s\n", dev->name, p_ctlbk->version, @@ -2193,16 +2217,18 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw) p_connect->WS_name); if (p_ctlbk->rc != 0) { - printk(KERN_INFO "%s: Conn Resp error: rc=%d \n", - dev->name, p_ctlbk->rc); + dev_warn(tdev, "The communication peer of %s rejected" + " a connection request\n", + dev->name); return 1; } rc = find_link(dev, p_connect->host_name, p_connect->WS_name); if (rc != 0) { claw_snd_disc(dev, p_ctlbk); - printk(KERN_INFO "%s: Conn Resp error: " - "req appl name does not match\n", + dev_warn(tdev, "The communication peer of %s" + " rejected a connection " + "request because of a type mismatch\n", dev->name); } /* should be until CONNECTION_CONFIRM */ @@ -2210,7 +2236,8 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw) break; case CONNECTION_CONFIRM: p_connect = (struct conncmd *)&(p_ctlbk->data); - printk(KERN_INFO "%s: Recv Conn Confirm:Vers=%d,link_id=%d," + dev_info(tdev, + "%s: Recv Conn Confirm:Vers=%d,link_id=%d," "Corr=%d,Host appl=%.8s,WS appl=%.8s\n", dev->name, p_ctlbk->version, @@ -2221,21 +2248,21 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw) if (p_ctlbk->linkid == -(privptr->active_link_ID)) { privptr->active_link_ID = p_ctlbk->linkid; if (p_env->packing > PACKING_ASK) { - printk(KERN_INFO "%s: Confirmed Now packing\n", - dev->name); + dev_info(tdev, + "%s: Confirmed Now packing\n", dev->name); p_env->packing = DO_PACKED; } p_ch = &privptr->channel[WRITE]; wake_up(&p_ch->wait); } else { - printk(KERN_INFO "%s: Conn confirm: " - "unexpected linkid=%d \n", + dev_warn(tdev, "Activating %s failed because of" + " an incorrect link ID=%d\n", dev->name, p_ctlbk->linkid); claw_snd_disc(dev, p_ctlbk); } break; case DISCONNECT: - printk(KERN_INFO "%s: Disconnect: " + dev_info(tdev, "%s: Disconnect: " "Vers=%d,link_id=%d,Corr=%d\n", dev->name, p_ctlbk->version, p_ctlbk->linkid, p_ctlbk->correlator); @@ -2247,12 +2274,13 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw) privptr->active_link_ID = 0; break; case CLAW_ERROR: - printk(KERN_INFO "%s: CLAW ERROR detected\n", + dev_warn(tdev, "The communication peer of %s failed\n", dev->name); break; default: - printk(KERN_INFO "%s: Unexpected command code=%d \n", - dev->name, p_ctlbk->command); + dev_warn(tdev, "The communication peer of %s sent" + " an unknown command code\n", + dev->name); break; } @@ -2294,12 +2322,14 @@ claw_send_control(struct net_device *dev, __u8 type, __u8 link, memcpy(&p_sysval->host_name, local_name, 8); memcpy(&p_sysval->WS_name, remote_name, 8); if (privptr->p_env->packing > 0) { - p_sysval->read_frame_size=DEF_PACK_BUFSIZE; - p_sysval->write_frame_size=DEF_PACK_BUFSIZE; + p_sysval->read_frame_size = DEF_PACK_BUFSIZE; + p_sysval->write_frame_size = DEF_PACK_BUFSIZE; } else { /* how big is the biggest group of packets */ - p_sysval->read_frame_size=privptr->p_env->read_size; - p_sysval->write_frame_size=privptr->p_env->write_size; + p_sysval->read_frame_size = + privptr->p_env->read_size; + p_sysval->write_frame_size = + privptr->p_env->write_size; } memset(&p_sysval->reserved, 0x00, 4); break; @@ -2511,8 +2541,10 @@ unpack_read(struct net_device *dev ) mtc_this_frm=1; if (p_this_ccw->header.length!= privptr->p_env->read_size ) { - printk(KERN_INFO " %s: Invalid frame detected " - "length is %02x\n" , + dev_warn(p_dev, + "The communication peer of %s" + " sent a faulty" + " frame of length %02x\n", dev->name, p_this_ccw->header.length); } } @@ -2544,7 +2576,7 @@ unpack_next: goto NextFrame; p_packd = p_this_ccw->p_buffer+pack_off; p_packh = (struct clawph *) p_packd; - if ((p_packh->len == 0) || /* all done with this frame? */ + if ((p_packh->len == 0) || /* done with this frame? */ (p_packh->flag != 0)) goto NextFrame; bytes_to_mov = p_packh->len; @@ -2594,9 +2626,9 @@ unpack_next: netif_rx(skb); } else { + dev_info(p_dev, "Allocating a buffer for" + " incoming data failed\n"); privptr->stats.rx_dropped++; - printk(KERN_WARNING "%s: %s() low on memory\n", - dev->name,__func__); } privptr->mtc_offset=0; privptr->mtc_logical_link=-1; @@ -2720,8 +2752,8 @@ claw_strt_out_IO( struct net_device *dev ) if (test_and_set_bit(0, (void *)&p_ch->IO_active) == 0) { parm = (unsigned long) p_ch; CLAW_DBF_TEXT(2, trace, "StWrtIO"); - rc = ccw_device_start (p_ch->cdev,&p_first_ccw->write, parm, - 0xff, 0); + rc = ccw_device_start(p_ch->cdev, &p_first_ccw->write, parm, + 0xff, 0); if (rc != 0) { ccw_check_return_code(p_ch->cdev, rc); } @@ -2884,8 +2916,8 @@ claw_new_device(struct ccwgroup_device *cgdev) int ret; struct ccw_dev_id dev_id; - printk(KERN_INFO "claw: add for %s\n", - dev_name(&cgdev->cdev[READ]->dev)); + dev_info(&cgdev->dev, "add for %s\n", + dev_name(&cgdev->cdev[READ]->dev)); CLAW_DBF_TEXT(2, setup, "new_dev"); privptr = cgdev->dev.driver_data; cgdev->cdev[READ]->dev.driver_data = privptr; @@ -2901,29 +2933,28 @@ claw_new_device(struct ccwgroup_device *cgdev) if (ret == 0) ret = add_channel(cgdev->cdev[1],1,privptr); if (ret != 0) { - printk(KERN_WARNING - "add channel failed with ret = %d\n", ret); + dev_warn(&cgdev->dev, "Creating a CLAW group device" + " failed with error code %d\n", ret); goto out; } ret = ccw_device_set_online(cgdev->cdev[READ]); if (ret != 0) { - printk(KERN_WARNING - "claw: ccw_device_set_online %s READ failed " - "with ret = %d\n", dev_name(&cgdev->cdev[READ]->dev), - ret); + dev_warn(&cgdev->dev, + "Setting the read subchannel online" + " failed with error code %d\n", ret); goto out; } ret = ccw_device_set_online(cgdev->cdev[WRITE]); if (ret != 0) { - printk(KERN_WARNING - "claw: ccw_device_set_online %s WRITE failed " - "with ret = %d\n", dev_name(&cgdev->cdev[WRITE]->dev), - ret); + dev_warn(&cgdev->dev, + "Setting the write subchannel online " + "failed with error code %d\n", ret); goto out; } dev = alloc_netdev(0,"claw%d",claw_init_netdevice); if (!dev) { - printk(KERN_WARNING "%s:alloc_netdev failed\n",__func__); + dev_warn(&cgdev->dev, + "Activating the CLAW device failed\n"); goto out; } dev->ml_priv = privptr; @@ -2951,13 +2982,13 @@ claw_new_device(struct ccwgroup_device *cgdev) privptr->channel[WRITE].ndev = dev; privptr->p_env->ndev = dev; - printk(KERN_INFO "%s:readsize=%d writesize=%d " + dev_info(&cgdev->dev, "%s:readsize=%d writesize=%d " "readbuffer=%d writebuffer=%d read=0x%04x write=0x%04x\n", dev->name, p_env->read_size, p_env->write_size, p_env->read_buffers, p_env->write_buffers, p_env->devno[READ], p_env->devno[WRITE]); - printk(KERN_INFO "%s:host_name:%.8s, adapter_name " + dev_info(&cgdev->dev, "%s:host_name:%.8s, adapter_name " ":%.8s api_type: %.8s\n", dev->name, p_env->host_name, p_env->adapter_name , p_env->api_type); @@ -3001,8 +3032,8 @@ claw_shutdown_device(struct ccwgroup_device *cgdev) ndev = priv->channel[READ].ndev; if (ndev) { /* Close the device */ - printk(KERN_INFO - "%s: shuting down \n",ndev->name); + dev_info(&cgdev->dev, "%s: shutting down \n", + ndev->name); if (ndev->flags & IFF_RUNNING) ret = claw_release(ndev); ndev->flags &=~IFF_RUNNING; @@ -3027,8 +3058,7 @@ claw_remove_device(struct ccwgroup_device *cgdev) CLAW_DBF_TEXT_(2, setup, "%s", dev_name(&cgdev->dev)); priv = cgdev->dev.driver_data; BUG_ON(!priv); - printk(KERN_INFO "claw: %s() called %s will be removed.\n", - __func__, dev_name(&cgdev->cdev[0]->dev)); + dev_info(&cgdev->dev, " will be removed.\n"); if (cgdev->state == CCWGROUP_ONLINE) claw_shutdown_device(cgdev); claw_remove_files(&cgdev->dev); @@ -3067,7 +3097,8 @@ claw_hname_show(struct device *dev, struct device_attribute *attr, char *buf) } static ssize_t -claw_hname_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +claw_hname_write(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct claw_privbk *priv; struct claw_env * p_env; @@ -3104,7 +3135,8 @@ claw_adname_show(struct device *dev, struct device_attribute *attr, char *buf) } static ssize_t -claw_adname_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +claw_adname_write(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct claw_privbk *priv; struct claw_env * p_env; @@ -3142,7 +3174,8 @@ claw_apname_show(struct device *dev, struct device_attribute *attr, char *buf) } static ssize_t -claw_apname_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +claw_apname_write(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct claw_privbk *priv; struct claw_env * p_env; @@ -3189,7 +3222,8 @@ claw_wbuff_show(struct device *dev, struct device_attribute *attr, char *buf) } static ssize_t -claw_wbuff_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +claw_wbuff_write(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct claw_privbk *priv; struct claw_env * p_env; @@ -3230,7 +3264,8 @@ claw_rbuff_show(struct device *dev, struct device_attribute *attr, char *buf) } static ssize_t -claw_rbuff_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +claw_rbuff_write(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct claw_privbk *priv; struct claw_env *p_env; @@ -3293,7 +3328,7 @@ claw_cleanup(void) { unregister_cu3088_discipline(&claw_group_driver); claw_unregister_debug_facility(); - printk(KERN_INFO "claw: Driver unloaded\n"); + pr_info("Driver unloaded\n"); } @@ -3307,12 +3342,12 @@ static int __init claw_init(void) { int ret = 0; - printk(KERN_INFO "claw: starting driver\n"); + pr_info("Loading %s\n", version); ret = claw_register_debug_facility(); if (ret) { - printk(KERN_WARNING "claw: %s() debug_register failed %d\n", - __func__,ret); + pr_err("Registering with the S/390 debug feature" + " failed with error code %d\n", ret); return ret; } CLAW_DBF_TEXT(2, setup, "init_mod"); @@ -3320,8 +3355,8 @@ claw_init(void) if (ret) { CLAW_DBF_TEXT(2, setup, "init_bad"); claw_unregister_debug_facility(); - printk(KERN_WARNING "claw; %s() cu3088 register failed %d\n", - __func__,ret); + pr_err("Registering with the cu3088 device driver failed " + "with error code %d\n", ret); } return ret; } -- GitLab From dd0a251c8e087bca05e8f9a3657078591ae6e12b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 25 Jan 2009 21:17:25 -0800 Subject: [PATCH 0435/4982] com0020: Add missing symbol export for com20020_netdev_ops. Thanks to Stephen Rothwell. Signed-off-by: David S. Miller --- drivers/net/arcnet/com20020.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index bbe8f2ccdad..651275a5f3d 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -348,6 +348,7 @@ static void com20020_set_mc_list(struct net_device *dev) defined(CONFIG_ARCNET_COM20020_CS_MODULE) EXPORT_SYMBOL(com20020_check); EXPORT_SYMBOL(com20020_found); +EXPORT_SYMBOL(com20020_netdev_ops); #endif MODULE_LICENSE("GPL"); -- GitLab From 2d4d57db692ea790e185656516e6ebe8791f1788 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Sun, 25 Jan 2009 12:50:13 -0800 Subject: [PATCH 0436/4982] x86: micro-optimize __raw_read_trylock() The current version of __raw_read_trylock starts with decrementing the lock and read its new value as a separate operation after that. That makes 3 dereferences (read, write (after sub), read) whereas a single atomic_dec_return does only two pointers dereferences (read, write). Signed-off-by: Frederic Weisbecker Signed-off-by: Ingo Molnar --- arch/x86/include/asm/spinlock.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/x86/include/asm/spinlock.h b/arch/x86/include/asm/spinlock.h index d17c91981da..4d3dcc51cac 100644 --- a/arch/x86/include/asm/spinlock.h +++ b/arch/x86/include/asm/spinlock.h @@ -329,8 +329,7 @@ static inline int __raw_read_trylock(raw_rwlock_t *lock) { atomic_t *count = (atomic_t *)lock; - atomic_dec(count); - if (atomic_read(count) >= 0) + if (atomic_dec_return(count) >= 0) return 1; atomic_inc(count); return 0; -- GitLab From 34707bcd0452aba644396767bc9fb61585bdab4f Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 26 Jan 2009 14:18:05 +0100 Subject: [PATCH 0437/4982] x86, debug: remove early_printk() #ifdefs from head_32.S Impact: cleanup Remove such constructs: #ifdef CONFIG_EARLY_PRINTK call early_printk #else call printk #endif Not only are they ugly, they are also pointless: a call to printk() maps to early_printk during early bootup anyway, if CONFIG_EARLY_PRINTK is enabled. Signed-off-by: Ingo Molnar --- arch/x86/kernel/head_32.S | 8 -------- 1 file changed, 8 deletions(-) diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index e835b4eea70..9f141071160 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -548,11 +548,7 @@ early_fault: pushl %eax pushl %edx /* trapno */ pushl $fault_msg -#ifdef CONFIG_EARLY_PRINTK - call early_printk -#else call printk -#endif #endif call dump_stack hlt_loop: @@ -580,11 +576,7 @@ ignore_int: pushl 32(%esp) pushl 40(%esp) pushl $int_msg -#ifdef CONFIG_EARLY_PRINTK - call early_printk -#else call printk -#endif addl $(5*4),%esp popl %ds popl %es -- GitLab From d5e397cb49b53381e4c99a064ca733c665646de8 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 26 Jan 2009 06:09:00 +0100 Subject: [PATCH 0438/4982] x86: improve early fault/irq printout Impact: add a stack dump to early IRQs/faults Signed-off-by: Ingo Molnar --- arch/x86/kernel/head_32.S | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index 9f141071160..84d05a4d7fc 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -577,6 +577,9 @@ ignore_int: pushl 40(%esp) pushl $int_msg call printk + + call dump_stack + addl $(5*4),%esp popl %ds popl %es @@ -652,7 +655,7 @@ early_recursion_flag: .long 0 int_msg: - .asciz "Unknown interrupt or fault at EIP %p %p %p\n" + .asciz "Unknown interrupt or fault at: %p %p %p\n" fault_msg: /* fault info: */ -- GitLab From 5a611268b69f05262936dd177205acbce4471358 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Mon, 26 Jan 2009 08:44:05 -0500 Subject: [PATCH 0439/4982] generic, x86: fix __per_cpu_load relocation This patch fixes this linker error: WARNING: Absolute relocations present Offset Info Type Sym.Value Sym.Name c0a4e07d 00e78001 R_386_32 c0ab0000 __per_cpu_load Now, __per_cpu_load is a section-relative symbol: c0aa4000 D __per_cpu_load c0aa4000 A __per_cpu_load_abs Signed-off-by: Brian Gerst Signed-off-by: Ingo Molnar --- include/asm-generic/vmlinux.lds.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 53e21f36a80..f3180a85c66 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -451,17 +451,18 @@ * end offset. */ #define PERCPU_VADDR(vaddr, phdr) \ - VMLINUX_SYMBOL(__per_cpu_load) = .; \ - .data.percpu vaddr : AT(VMLINUX_SYMBOL(__per_cpu_load) \ + VMLINUX_SYMBOL(__per_cpu_load_abs) = .; \ + .data.percpu vaddr : AT(VMLINUX_SYMBOL(__per_cpu_load_abs) \ - LOAD_OFFSET) { \ VMLINUX_SYMBOL(__per_cpu_start) = .; \ + VMLINUX_SYMBOL(__per_cpu_load) = LOADADDR(.data.percpu) + LOAD_OFFSET;\ *(.data.percpu.first) \ *(.data.percpu.page_aligned) \ *(.data.percpu) \ *(.data.percpu.shared_aligned) \ VMLINUX_SYMBOL(__per_cpu_end) = .; \ } phdr \ - . = VMLINUX_SYMBOL(__per_cpu_load) + SIZEOF(.data.percpu); + . = VMLINUX_SYMBOL(__per_cpu_load_abs) + SIZEOF(.data.percpu); /** * PERCPU - define output section for percpu area, simple version -- GitLab From ca8d33fc9fafe373362d35107f01fba1e73fb966 Mon Sep 17 00:00:00 2001 From: Matthew Ranostay Date: Mon, 26 Jan 2009 09:33:52 -0500 Subject: [PATCH 0440/4982] ALSA: hda: 92hd71xxx disable unmute support for codecs that don't have input amps Some revisions of the 92hd71xxx codec families don't have input amps on ports 0xa, 0xd and 0xf, so probe the widget caps on port 0xa and check for support, if found run snd_hda_sequence_write_cache() on the stac92hd71xxx_unmute_core_init verb list. Signed-off-by: Matthew Ranostay Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 80a4c288b31..03b26426611 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -858,26 +858,25 @@ static struct hda_verb stac92hd83xxx_core_init[] = { static struct hda_verb stac92hd71bxx_core_init[] = { /* set master volume and direct control */ { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, - /* unmute right and left channels for nodes 0x0a, 0xd, 0x0f */ - { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {} }; -#define HD_DISABLE_PORTF 2 +#define HD_DISABLE_PORTF 1 static struct hda_verb stac92hd71bxx_analog_core_init[] = { /* start of config #1 */ /* connect port 0f to audio mixer */ { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2}, - /* unmute right and left channels for node 0x0f */ - { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* start of config #2 */ /* set master volume and direct control */ { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, - /* unmute right and left channels for nodes 0x0a, 0xd */ + {} +}; + +static struct hda_verb stac92hd71bxx_unmute_core_init[] = { + /* unmute right and left channels for nodes 0x0f, 0xa, 0x0d */ + { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {} @@ -4942,6 +4941,7 @@ static struct hda_input_mux stac92hd71bxx_dmux = { static int patch_stac92hd71bxx(struct hda_codec *codec) { struct sigmatel_spec *spec; + struct hda_verb *unmute_init = stac92hd71bxx_unmute_core_init; int err = 0; spec = kzalloc(sizeof(*spec), GFP_KERNEL); @@ -5015,6 +5015,7 @@ again: /* disable VSW */ spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF]; + unmute_init++; stac_change_pin_config(codec, 0xf, 0x40f000f0); break; case 0x111d7603: /* 6 Port with Analog Mixer */ @@ -5031,6 +5032,9 @@ again: codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; } + if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP) + snd_hda_sequence_write_cache(codec, unmute_init); + spec->aloopback_mask = 0x50; spec->aloopback_shift = 0; -- GitLab From b7eb4a06e9980973755b7e95a6d97fb8decbf8fd Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 26 Jan 2009 08:08:34 +0100 Subject: [PATCH 0441/4982] sound: usb-audio: use normal number of frames for no-data URBs When sending a silence URB (before playback has started, or when it is paused), use the number of frames that would be normally sent instead of a single frame so that the rate at which completion interrupts arrive is consistent. Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/usb/usbaudio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index c709b956322..417d557ed64 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -525,7 +525,7 @@ static int snd_usb_audio_next_packet_size(struct snd_usb_substream *subs) /* * Prepare urb for streaming before playback starts or when paused. * - * We don't have any data, so we send a frame of silence. + * We don't have any data, so we send silence. */ static int prepare_nodata_playback_urb(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime, @@ -537,13 +537,13 @@ static int prepare_nodata_playback_urb(struct snd_usb_substream *subs, offs = 0; urb->dev = ctx->subs->dev; - urb->number_of_packets = subs->packs_per_ms; - for (i = 0; i < subs->packs_per_ms; ++i) { + for (i = 0; i < ctx->packets; ++i) { counts = snd_usb_audio_next_packet_size(subs); urb->iso_frame_desc[i].offset = offs * stride; urb->iso_frame_desc[i].length = counts * stride; offs += counts; } + urb->number_of_packets = ctx->packets; urb->transfer_buffer_length = offs * stride; memset(urb->transfer_buffer, subs->cur_audiofmt->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0, -- GitLab From 4d788e040b72d2a46ea3ba726b7fa0b65de06c88 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 26 Jan 2009 08:09:28 +0100 Subject: [PATCH 0442/4982] sound: usb-audio: limit playback queue length Once our URBs contain enough packets, queueing more URBs does not give us any additional underrun protection (as we use double-buffering) but just increases latency unnecessarily. Therefore, we try to limit the queue length to some reasonable value. Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/usb/usbaudio.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 417d557ed64..f3d4de23fed 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -108,6 +108,7 @@ MODULE_PARM_DESC(ignore_ctl_error, #define MAX_URBS 8 #define SYNC_URBS 4 /* always four urbs for sync */ #define MIN_PACKS_URB 1 /* minimum 1 packet per urb */ +#define MAX_QUEUE 24 /* try not to exceed this queue length, in ms */ struct audioformat { struct list_head list; @@ -1079,7 +1080,7 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri /* decide how many packets to be used */ if (is_playback) { - unsigned int minsize; + unsigned int minsize, maxpacks; /* determine how small a packet can be */ minsize = (subs->freqn >> (16 - subs->datainterval)) * (frame_bits >> 3); @@ -1094,6 +1095,12 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri /* we need at least two URBs for queueing */ if (total_packs < 2 * MIN_PACKS_URB * packs_per_ms) total_packs = 2 * MIN_PACKS_URB * packs_per_ms; + else { + /* and we don't want too long a queue either */ + maxpacks = max((unsigned int)MAX_QUEUE, urb_packs * 2); + if (total_packs > maxpacks * packs_per_ms) + total_packs = maxpacks * packs_per_ms; + } } else { total_packs = MAX_URBS * urb_packs; } -- GitLab From 160389c8d21c8139a93191c2e5ca2273f311ed4e Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 26 Jan 2009 08:10:19 +0100 Subject: [PATCH 0443/4982] sound: usb-audio: make URB sizes more equal Distribute the packets evenly among the URBs, instead of making all URBs except the last one to have the maximum size. This makes the timing of pointer updates more regular and removes some special cases from the code. Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/usb/usbaudio.c | 29 +++++------------------------ 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index f3d4de23fed..44485b29f67 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -1035,9 +1035,9 @@ static void release_substream_urbs(struct snd_usb_substream *subs, int force) static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int period_bytes, unsigned int rate, unsigned int frame_bits) { - unsigned int maxsize, n, i; + unsigned int maxsize, i; int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK; - unsigned int npacks[MAX_URBS], urb_packs, total_packs, packs_per_ms; + unsigned int urb_packs, total_packs, packs_per_ms; /* calculate the frequency in 16.16 format */ if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) @@ -1109,31 +1109,11 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri /* too much... */ subs->nurbs = MAX_URBS; total_packs = MAX_URBS * urb_packs; - } - n = total_packs; - for (i = 0; i < subs->nurbs; i++) { - npacks[i] = n > urb_packs ? urb_packs : n; - n -= urb_packs; - } - if (subs->nurbs <= 1) { + } else if (subs->nurbs < 2) { /* too little - we need at least two packets * to ensure contiguous playback/capture */ subs->nurbs = 2; - npacks[0] = (total_packs + 1) / 2; - npacks[1] = total_packs - npacks[0]; - } else if (npacks[subs->nurbs-1] < MIN_PACKS_URB * packs_per_ms) { - /* the last packet is too small.. */ - if (subs->nurbs > 2) { - /* merge to the first one */ - npacks[0] += npacks[subs->nurbs - 1]; - subs->nurbs--; - } else { - /* divide to two */ - subs->nurbs = 2; - npacks[0] = (total_packs + 1) / 2; - npacks[1] = total_packs - npacks[0]; - } } /* allocate and initialize data urbs */ @@ -1141,7 +1121,8 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri struct snd_urb_ctx *u = &subs->dataurb[i]; u->index = i; u->subs = subs; - u->packets = npacks[i]; + u->packets = (i + 1) * total_packs / subs->nurbs + - i * total_packs / subs->nurbs; u->buffer_size = maxsize * u->packets; if (subs->fmt_type == USB_FORMAT_TYPE_II) u->packets++; /* for transfer delimiter */ -- GitLab From b76811af7606b36cb0703f04449c301b9634dcbc Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 27 Jan 2009 10:18:51 +1100 Subject: [PATCH 0444/4982] solos: Fix length header in FPGA transfers The length field shouldn't ever include the size of the header itself. This fixes the problem that some people were seeing with 1500-byte packets. Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 72fc0f799a6..f0309546c35 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -356,7 +356,7 @@ static int popen(struct atm_vcc *vcc) } header = (void *)skb_put(skb, sizeof(*header)); - header->size = cpu_to_le16(sizeof(*header)); + header->size = cpu_to_le16(0); header->vpi = cpu_to_le16(vcc->vpi); header->vci = cpu_to_le16(vcc->vci); header->type = cpu_to_le16(PKT_POPEN); @@ -389,7 +389,7 @@ static void pclose(struct atm_vcc *vcc) } header = (void *)skb_put(skb, sizeof(*header)); - header->size = cpu_to_le16(sizeof(*header)); + header->size = cpu_to_le16(0); header->vpi = cpu_to_le16(vcc->vpi); header->vci = cpu_to_le16(vcc->vci); header->type = cpu_to_le16(PKT_PCLOSE); @@ -507,6 +507,7 @@ static int psend(struct atm_vcc *vcc, struct sk_buff *skb) struct solos_card *card = vcc->dev->dev_data; struct sk_buff *skb2 = NULL; struct pkt_hdr *header; + int pktlen; //dev_dbg(&card->dev->dev, "psend called.\n"); //dev_dbg(&card->dev->dev, "dev,vpi,vci = %d,%d,%d\n",SOLOS_CHAN(vcc->dev),vcc->vpi,vcc->vci); @@ -524,7 +525,8 @@ static int psend(struct atm_vcc *vcc, struct sk_buff *skb) return 0; } - if (skb->len > (BUF_SIZE - sizeof(*header))) { + pktlen = skb->len; + if (pktlen > (BUF_SIZE - sizeof(*header))) { dev_warn(&card->dev->dev, "Length of PDU is too large. Dropping PDU.\n"); solos_pop(vcc, skb); return 0; @@ -546,7 +548,8 @@ static int psend(struct atm_vcc *vcc, struct sk_buff *skb) header = (void *)skb_push(skb, sizeof(*header)); - header->size = cpu_to_le16(skb->len); + /* This does _not_ include the size of the header */ + header->size = cpu_to_le16(pktlen); header->vpi = cpu_to_le16(vcc->vpi); header->vci = cpu_to_le16(vcc->vci); header->type = cpu_to_le16(PKT_DATA); -- GitLab From 4306cad6fe02e2946183ab29e510f94190b8fff3 Mon Sep 17 00:00:00 2001 From: Simon Farnsworth Date: Mon, 19 Jan 2009 21:19:29 +0000 Subject: [PATCH 0445/4982] solos: Slight debugging improvements Print a message if pskb_expand_head fails. Make atmdebug writable by root, so that you can turn printing of data sent to and received from the card on and off at runtime - useful for tracking corruption. Signed-off-by: Simon Farnsworth Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index f0309546c35..3daa3a37431 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -91,7 +91,7 @@ MODULE_LICENSE("GPL"); MODULE_PARM_DESC(debug, "Enable Loopback"); MODULE_PARM_DESC(atmdebug, "Print ATM data"); module_param(debug, int, 0444); -module_param(atmdebug, int, 0444); +module_param(atmdebug, int, 0644); static int opens; @@ -541,6 +541,7 @@ static int psend(struct atm_vcc *vcc, struct sk_buff *skb) ret = pskb_expand_head(skb, expand_by, 0, GFP_ATOMIC); if (ret) { + dev_warn(&card->dev->dev, "pskb_expand_head failed.\n"); solos_pop(vcc, skb); return ret; } -- GitLab From 7c4015bdffed7c961b6df46c6326cc65962e6594 Mon Sep 17 00:00:00 2001 From: Simon Farnsworth Date: Wed, 21 Jan 2009 20:45:49 +0000 Subject: [PATCH 0446/4982] solos: FPGA and firmware update support. This is just a straight pull in of changes, syncing us up to 0.07 from openadsl.sf.net Signed-off-by: Nathan Williams Signed-off-by: Simon Farnsworth Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 171 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 169 insertions(+), 2 deletions(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 3daa3a37431..2b472c898c8 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -9,6 +9,7 @@ * * Authors: Nathan Williams * David Woodhouse + * Treker Chen * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -36,8 +37,9 @@ #include #include #include +#include -#define VERSION "0.04" +#define VERSION "0.07" #define PTAG "solos-pci" #define CONFIG_RAM_SIZE 128 @@ -45,16 +47,27 @@ #define IRQ_EN_ADDR 0x78 #define FPGA_VER 0x74 #define IRQ_CLEAR 0x70 -#define BUG_FLAG 0x6C +#define WRITE_FLASH 0x6C +#define PORTS 0x68 +#define FLASH_BLOCK 0x64 +#define FLASH_BUSY 0x60 +#define FPGA_MODE 0x5C +#define FLASH_MODE 0x58 #define DATA_RAM_SIZE 32768 #define BUF_SIZE 4096 +#define FPGA_PAGE 528 /* FPGA flash page size*/ +#define SOLOS_PAGE 512 /* Solos flash page size*/ +#define FPGA_BLOCK (FPGA_PAGE * 8) /* FPGA flash block size*/ +#define SOLOS_BLOCK (SOLOS_PAGE * 8) /* Solos flash block size*/ #define RX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2) #define TX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2 + BUF_SIZE) static int debug = 0; static int atmdebug = 0; +static int firmware_upgrade = 0; +static int fpga_upgrade = 0; struct pkt_hdr { __le16 size; @@ -80,6 +93,7 @@ struct solos_card { spinlock_t cli_queue_lock; struct sk_buff_head tx_queue[4]; struct sk_buff_head cli_queue[4]; + int flash_chip; }; #define SOLOS_CHAN(atmdev) ((int)(unsigned long)(atmdev)->phy_data) @@ -90,11 +104,19 @@ MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); MODULE_PARM_DESC(debug, "Enable Loopback"); MODULE_PARM_DESC(atmdebug, "Print ATM data"); +MODULE_PARM_DESC(firmware_upgrade, "Initiate Solos firmware upgrade"); +MODULE_PARM_DESC(fpga_upgrade, "Initiate FPGA upgrade"); module_param(debug, int, 0444); module_param(atmdebug, int, 0644); +module_param(firmware_upgrade, int, 0444); +module_param(fpga_upgrade, int, 0444); static int opens; +static struct firmware *fw; +static int flash_offset; +void flash_upgrade(struct solos_card *); +void flash_write(struct solos_card *); static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb, struct atm_vcc *vcc); static int fpga_tx(struct solos_card *); @@ -180,6 +202,131 @@ static ssize_t console_store(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(console, 0644, console_show, console_store); +void flash_upgrade(struct solos_card *card){ + uint32_t data32 = 0; + int blocksize = 0; + int numblocks = 0; + dev_info(&card->dev->dev, "Flash upgrade started\n"); + if (card->flash_chip == 0) { + if (request_firmware((const struct firmware **)&fw, + "solos-FPGA.bin",&card->dev->dev)) + { + dev_info(&card->dev->dev, + "Failed to find firmware\n"); + return; + } + blocksize = FPGA_BLOCK; + } else { + if (request_firmware((const struct firmware **)&fw, + "solos-Firmware.bin",&card->dev->dev)) + { + dev_info(&card->dev->dev, + "Failed to find firmware\n"); + return; + } + blocksize = SOLOS_BLOCK; + } + numblocks = fw->size/blocksize; + dev_info(&card->dev->dev, "Firmware size: %d\n", fw->size); + dev_info(&card->dev->dev, "Number of blocks: %d\n", numblocks); + + + dev_info(&card->dev->dev, "Changing FPGA to Update mode\n"); + iowrite32(1, card->config_regs + FPGA_MODE); + data32 = ioread32(card->config_regs + FPGA_MODE); + /*Set mode to Chip Erase*/ + if (card->flash_chip == 0) { + dev_info(&card->dev->dev, + "Set FPGA Flash mode to FPGA Chip Erase\n"); + } else { + dev_info(&card->dev->dev, + "Set FPGA Flash mode to Solos Chip Erase\n"); + } + iowrite32((card->flash_chip * 2), card->config_regs + FLASH_MODE); + flash_offset = 0; + iowrite32(1, card->config_regs + WRITE_FLASH); + return; +} + +void flash_write(struct solos_card *card){ + int block; + int block_num; + int blocksize; + int i; + uint32_t data32 = 0; + + /*Clear write flag*/ + iowrite32(0, card->config_regs + WRITE_FLASH); + /*Set mode to Block Write*/ + /*dev_info(&card->dev->dev, "Set FPGA Flash mode to Block Write\n");*/ + iowrite32(((card->flash_chip * 2) + 1), card->config_regs + FLASH_MODE); + + /*When finished programming flash, release firmware and exit*/ + if (fw->size - flash_offset == 0) { + //release_firmware(fw); /* This crashes for some reason */ + iowrite32(0, card->config_regs + WRITE_FLASH); + iowrite32(0, card->config_regs + FPGA_MODE); + iowrite32(0, card->config_regs + FLASH_MODE); + dev_info(&card->dev->dev, "Returning FPGA to Data mode\n"); + return; + } + if (card->flash_chip == 0) { + blocksize = FPGA_BLOCK; + } else { + blocksize = SOLOS_BLOCK; + } + + /*Calculate block size*/ + if ((fw->size - flash_offset) > blocksize) { + block = blocksize; + } else { + block = fw->size - flash_offset; + } + block_num = flash_offset / blocksize; + //dev_info(&card->dev->dev, "block %d/%d\n",block_num + 1,(fw->size/512/8)); + + /*Copy block into RAM*/ + for(i=0;idev->dev, "i: %d\n", i); + data32=0x00000000; + } + + switch(i%4){ + case 0: + data32 |= 0x0000FF00 & + (*(fw->data + i + flash_offset) << 8); + break; + case 1: + data32 |= 0x000000FF & *(fw->data + i + flash_offset); + break; + case 2: + data32 |= 0xFF000000 & + (*(fw->data + i + flash_offset) << 24); + break; + case 3: + data32 |= 0x00FF0000 & + (*(fw->data + i + flash_offset) << 16); + break; + } + + if (i%4 == 3) { + iowrite32(data32, RX_BUF(card, 3) + i - 3); + } + } + i--; + if (i%4 != 3) { + iowrite32(data32, RX_BUF(card, 3) + i - (i%4)); + } + + /*Specify block number and then trigger flash write*/ + iowrite32(block_num, card->config_regs + FLASH_BLOCK); + iowrite32(1, card->config_regs + WRITE_FLASH); +// iowrite32(0, card->config_regs + WRITE_FLASH); + flash_offset += block; + return; +} + static irqreturn_t solos_irq(int irq, void *dev_id) { struct solos_card *card = dev_id; @@ -207,6 +354,17 @@ void solos_bh(unsigned long card_arg) uint32_t card_flags; uint32_t tx_mask; uint32_t rx_done = 0; + uint32_t data32; + + data32 = ioread32(card->config_regs + FPGA_MODE); + if (data32 != 0) { + data32 = ioread32(card->config_regs + FLASH_BUSY); + if (data32 == 0) { + flash_write(card); + } + return; + } + card_flags = ioread32(card->config_regs + FLAGS_ADDR); @@ -680,6 +838,15 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) // Enable IRQs iowrite32(1, card->config_regs + IRQ_EN_ADDR); + if(firmware_upgrade != 0){ + card->flash_chip = 1; + flash_upgrade(card); + } else { + if(fpga_upgrade != 0){ + card->flash_chip = 0; + flash_upgrade(card); + } + } return 0; out_unmap_both: -- GitLab From fa755b9f2b03df1e0fa6d01b8949bbc778705973 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 27 Jan 2009 14:16:12 +1100 Subject: [PATCH 0447/4982] solos: Clean up firmware loading code We no longer try to load firmware while the ATM is up and running. However, this means that we _do_ make init_module() wait for it, and it takes a long time for now (since we're using ultra-conservative code in the FPGA for that too). The inner loop which uses swahb32p() was by Simon Farnsworth. Simon has patches which migrate us to request_firmware_nowait(), for which we'll actually need to take down the ATM devices, do the upgrade, then reregister them. Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 209 ++++++++++++++-------------------------- 1 file changed, 73 insertions(+), 136 deletions(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 2b472c898c8..89bdf733af9 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -93,7 +93,7 @@ struct solos_card { spinlock_t cli_queue_lock; struct sk_buff_head tx_queue[4]; struct sk_buff_head cli_queue[4]; - int flash_chip; + wait_queue_head_t fw_wq; }; #define SOLOS_CHAN(atmdev) ((int)(unsigned long)(atmdev)->phy_data) @@ -112,11 +112,7 @@ module_param(firmware_upgrade, int, 0444); module_param(fpga_upgrade, int, 0444); static int opens; -static struct firmware *fw; -static int flash_offset; -void flash_upgrade(struct solos_card *); -void flash_write(struct solos_card *); static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb, struct atm_vcc *vcc); static int fpga_tx(struct solos_card *); @@ -202,129 +198,73 @@ static ssize_t console_store(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(console, 0644, console_show, console_store); -void flash_upgrade(struct solos_card *card){ +static int flash_upgrade(struct solos_card *card, int chip) +{ + const struct firmware *fw; + const char *fw_name; uint32_t data32 = 0; int blocksize = 0; int numblocks = 0; - dev_info(&card->dev->dev, "Flash upgrade started\n"); - if (card->flash_chip == 0) { - if (request_firmware((const struct firmware **)&fw, - "solos-FPGA.bin",&card->dev->dev)) - { - dev_info(&card->dev->dev, - "Failed to find firmware\n"); - return; - } + int offset; + + if (chip == 0) { + fw_name = "solos-FPGA.bin"; blocksize = FPGA_BLOCK; } else { - if (request_firmware((const struct firmware **)&fw, - "solos-Firmware.bin",&card->dev->dev)) - { - dev_info(&card->dev->dev, - "Failed to find firmware\n"); - return; - } + fw_name = "solos-Firmware.bin"; blocksize = SOLOS_BLOCK; } - numblocks = fw->size/blocksize; - dev_info(&card->dev->dev, "Firmware size: %d\n", fw->size); + + if (request_firmware(&fw, fw_name, &card->dev->dev)) + return -ENOENT; + + dev_info(&card->dev->dev, "Flash upgrade starting\n"); + + numblocks = fw->size / blocksize; + dev_info(&card->dev->dev, "Firmware size: %zd\n", fw->size); dev_info(&card->dev->dev, "Number of blocks: %d\n", numblocks); - dev_info(&card->dev->dev, "Changing FPGA to Update mode\n"); iowrite32(1, card->config_regs + FPGA_MODE); data32 = ioread32(card->config_regs + FPGA_MODE); - /*Set mode to Chip Erase*/ - if (card->flash_chip == 0) { - dev_info(&card->dev->dev, - "Set FPGA Flash mode to FPGA Chip Erase\n"); - } else { - dev_info(&card->dev->dev, - "Set FPGA Flash mode to Solos Chip Erase\n"); - } - iowrite32((card->flash_chip * 2), card->config_regs + FLASH_MODE); - flash_offset = 0; - iowrite32(1, card->config_regs + WRITE_FLASH); - return; -} -void flash_write(struct solos_card *card){ - int block; - int block_num; - int blocksize; - int i; - uint32_t data32 = 0; + /* Set mode to Chip Erase */ + dev_info(&card->dev->dev, "Set FPGA Flash mode to %s Chip Erase\n", + chip?"Solos":"FPGA"); + iowrite32((chip * 2), card->config_regs + FLASH_MODE); - /*Clear write flag*/ - iowrite32(0, card->config_regs + WRITE_FLASH); - /*Set mode to Block Write*/ - /*dev_info(&card->dev->dev, "Set FPGA Flash mode to Block Write\n");*/ - iowrite32(((card->flash_chip * 2) + 1), card->config_regs + FLASH_MODE); - /*When finished programming flash, release firmware and exit*/ - if (fw->size - flash_offset == 0) { - //release_firmware(fw); /* This crashes for some reason */ + iowrite32(1, card->config_regs + WRITE_FLASH); + wait_event(card->fw_wq, !ioread32(card->config_regs + FLASH_BUSY)); + + for (offset = 0; offset < fw->size; offset += blocksize) { + int i; + + /* Clear write flag */ iowrite32(0, card->config_regs + WRITE_FLASH); - iowrite32(0, card->config_regs + FPGA_MODE); - iowrite32(0, card->config_regs + FLASH_MODE); - dev_info(&card->dev->dev, "Returning FPGA to Data mode\n"); - return; - } - if (card->flash_chip == 0) { - blocksize = FPGA_BLOCK; - } else { - blocksize = SOLOS_BLOCK; - } - - /*Calculate block size*/ - if ((fw->size - flash_offset) > blocksize) { - block = blocksize; - } else { - block = fw->size - flash_offset; - } - block_num = flash_offset / blocksize; - //dev_info(&card->dev->dev, "block %d/%d\n",block_num + 1,(fw->size/512/8)); - - /*Copy block into RAM*/ - for(i=0;idev->dev, "i: %d\n", i); - data32=0x00000000; - } - - switch(i%4){ - case 0: - data32 |= 0x0000FF00 & - (*(fw->data + i + flash_offset) << 8); - break; - case 1: - data32 |= 0x000000FF & *(fw->data + i + flash_offset); - break; - case 2: - data32 |= 0xFF000000 & - (*(fw->data + i + flash_offset) << 24); - break; - case 3: - data32 |= 0x00FF0000 & - (*(fw->data + i + flash_offset) << 16); - break; - } - if (i%4 == 3) { - iowrite32(data32, RX_BUF(card, 3) + i - 3); + /* Set mode to Block Write */ + /* dev_info(&card->dev->dev, "Set FPGA Flash mode to Block Write\n"); */ + iowrite32(((chip * 2) + 1), card->config_regs + FLASH_MODE); + + /* Copy block to buffer, swapping each 16 bits */ + for(i = 0; i < blocksize; i += 4) { + uint32_t word = swahb32p((uint32_t *)(fw->data + offset + i)); + iowrite32(word, RX_BUF(card, 3) + i); } - } - i--; - if (i%4 != 3) { - iowrite32(data32, RX_BUF(card, 3) + i - (i%4)); + + /* Specify block number and then trigger flash write */ + iowrite32(offset / blocksize, card->config_regs + FLASH_BLOCK); + iowrite32(1, card->config_regs + WRITE_FLASH); + wait_event(card->fw_wq, !ioread32(card->config_regs + FLASH_BUSY)); } - /*Specify block number and then trigger flash write*/ - iowrite32(block_num, card->config_regs + FLASH_BLOCK); - iowrite32(1, card->config_regs + WRITE_FLASH); -// iowrite32(0, card->config_regs + WRITE_FLASH); - flash_offset += block; - return; + release_firmware(fw); + iowrite32(0, card->config_regs + WRITE_FLASH); + iowrite32(0, card->config_regs + FPGA_MODE); + iowrite32(0, card->config_regs + FLASH_MODE); + dev_info(&card->dev->dev, "Returning FPGA to Data mode\n"); + return 0; } static irqreturn_t solos_irq(int irq, void *dev_id) @@ -337,10 +277,10 @@ static irqreturn_t solos_irq(int irq, void *dev_id) //Disable IRQs from FPGA iowrite32(0, card->config_regs + IRQ_EN_ADDR); - /* If we only do it when the device is open, we lose console - messages */ - if (1 || opens) + if (card->atmdev[0]) tasklet_schedule(&card->tlet); + else + wake_up(&card->fw_wq); //Enable IRQs from FPGA iowrite32(1, card->config_regs + IRQ_EN_ADDR); @@ -354,17 +294,6 @@ void solos_bh(unsigned long card_arg) uint32_t card_flags; uint32_t tx_mask; uint32_t rx_done = 0; - uint32_t data32; - - data32 = ioread32(card->config_regs + FPGA_MODE); - if (data32 != 0) { - data32 = ioread32(card->config_regs + FLASH_BUSY); - if (data32 == 0) { - flash_write(card); - } - return; - } - card_flags = ioread32(card->config_regs + FLAGS_ADDR); @@ -749,6 +678,7 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) return -ENOMEM; card->dev = dev; + init_waitqueue_head(&card->fw_wq); err = pci_enable_device(dev); if (err) { @@ -794,15 +724,13 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) card->nr_ports = 2; /* FIXME: Detect daughterboard */ - err = atm_init(card); - if (err) - goto out_unmap_both; - pci_set_drvdata(dev, card); + tasklet_init(&card->tlet, solos_bh, (unsigned long)card); spin_lock_init(&card->tx_lock); spin_lock_init(&card->tx_queue_lock); spin_lock_init(&card->cli_queue_lock); + /* // Set Loopback mode data32 = 0x00010000; @@ -832,24 +760,33 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) //dev_dbg(&card->dev->dev, "Requesting IRQ: %d\n",dev->irq); err = request_irq(dev->irq, solos_irq, IRQF_DISABLED|IRQF_SHARED, "solos-pci", card); - if (err) + if (err) { dev_dbg(&card->dev->dev, "Failed to request interrupt IRQ: %d\n", dev->irq); + goto out_unmap_both; + } // Enable IRQs iowrite32(1, card->config_regs + IRQ_EN_ADDR); - if(firmware_upgrade != 0){ - card->flash_chip = 1; - flash_upgrade(card); - } else { - if(fpga_upgrade != 0){ - card->flash_chip = 0; - flash_upgrade(card); - } - } + if (fpga_upgrade) + flash_upgrade(card, 0); + + if (firmware_upgrade) + flash_upgrade(card, 1); + + err = atm_init(card); + if (err) + goto out_free_irq; + return 0; + out_free_irq: + iowrite32(0, card->config_regs + IRQ_EN_ADDR); + free_irq(dev->irq, card); + tasklet_kill(&card->tlet); + out_unmap_both: + pci_set_drvdata(dev, NULL); pci_iounmap(dev, card->config_regs); out_unmap_config: pci_iounmap(dev, card->buffers); -- GitLab From 316bea79369334d11f8a6e22317a928d94c50ae5 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 27 Jan 2009 14:25:16 +1100 Subject: [PATCH 0448/4982] solos: Kill global 'opens' count. Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 89bdf733af9..5179dbf9bd1 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -111,8 +111,6 @@ module_param(atmdebug, int, 0644); module_param(firmware_upgrade, int, 0444); module_param(fpga_upgrade, int, 0444); -static int opens; - static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb, struct atm_vcc *vcc); static int fpga_tx(struct solos_card *); @@ -455,10 +453,6 @@ static int popen(struct atm_vcc *vcc) set_bit(ATM_VF_READY, &vcc->flags); list_vccs(0); - if (!opens) - iowrite32(1, card->config_regs + IRQ_EN_ADDR); - - opens++; //count open PVCs return 0; } @@ -484,8 +478,6 @@ static void pclose(struct atm_vcc *vcc) fpga_queue(card, SOLOS_CHAN(vcc->dev), skb, NULL); // dev_dbg(&card->dev->dev, "Close for vpi %d and vci %d on interface %d\n", vcc->vpi, vcc->vci, SOLOS_CHAN(vcc->dev)); - if (!--opens) - iowrite32(0, card->config_regs + IRQ_EN_ADDR); clear_bit(ATM_VF_ADDR, &vcc->flags); clear_bit(ATM_VF_READY, &vcc->flags); @@ -800,8 +792,6 @@ static int atm_init(struct solos_card *card) { int i; - opens = 0; - for (i = 0; i < card->nr_ports; i++) { skb_queue_head_init(&card->tx_queue[i]); skb_queue_head_init(&card->cli_queue[i]); -- GitLab From 0d77e7f04d5da160307f4f5c030a171e004f602b Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Tue, 27 Jan 2009 12:56:47 +0900 Subject: [PATCH 0449/4982] x86: merge setup_per_cpu_maps() into setup_per_cpu_areas() Impact: minor optimization Eliminates the need for two loops over possible cpus. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/kernel/setup_percpu.c | 48 ++++++++++++++-------------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 90b8e154bb5..d0b1476490a 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -97,33 +97,6 @@ static inline void setup_cpu_local_masks(void) #endif /* CONFIG_X86_32 */ #ifdef CONFIG_HAVE_SETUP_PER_CPU_AREA -/* - * Copy data used in early init routines from the initial arrays to the - * per cpu data areas. These arrays then become expendable and the - * *_early_ptr's are zeroed indicating that the static arrays are gone. - */ -static void __init setup_per_cpu_maps(void) -{ - int cpu; - - for_each_possible_cpu(cpu) { - per_cpu(x86_cpu_to_apicid, cpu) = - early_per_cpu_map(x86_cpu_to_apicid, cpu); - per_cpu(x86_bios_cpu_apicid, cpu) = - early_per_cpu_map(x86_bios_cpu_apicid, cpu); -#ifdef X86_64_NUMA - per_cpu(x86_cpu_to_node_map, cpu) = - early_per_cpu_map(x86_cpu_to_node_map, cpu); -#endif - } - - /* indicate the early static arrays will soon be gone */ - early_per_cpu_ptr(x86_cpu_to_apicid) = NULL; - early_per_cpu_ptr(x86_bios_cpu_apicid) = NULL; -#ifdef X86_64_NUMA - early_per_cpu_ptr(x86_cpu_to_node_map) = NULL; -#endif -} #ifdef CONFIG_X86_64 unsigned long __per_cpu_offset[NR_CPUS] __read_mostly = { @@ -181,6 +154,19 @@ void __init setup_per_cpu_areas(void) per_cpu_offset(cpu) = ptr - __per_cpu_start; per_cpu(this_cpu_off, cpu) = per_cpu_offset(cpu); per_cpu(cpu_number, cpu) = cpu; + /* + * Copy data used in early init routines from the initial arrays to the + * per cpu data areas. These arrays then become expendable and the + * *_early_ptr's are zeroed indicating that the static arrays are gone. + */ + per_cpu(x86_cpu_to_apicid, cpu) = + early_per_cpu_map(x86_cpu_to_apicid, cpu); + per_cpu(x86_bios_cpu_apicid, cpu) = + early_per_cpu_map(x86_bios_cpu_apicid, cpu); +#ifdef X86_64_NUMA + per_cpu(x86_cpu_to_node_map, cpu) = + early_per_cpu_map(x86_cpu_to_node_map, cpu); +#endif #ifdef CONFIG_X86_64 per_cpu(irq_stack_ptr, cpu) = per_cpu(irq_stack_union.irq_stack, cpu) + IRQ_STACK_SIZE - 64; @@ -195,8 +181,12 @@ void __init setup_per_cpu_areas(void) DBG("PERCPU: cpu %4d %p\n", cpu, ptr); } - /* Setup percpu data maps */ - setup_per_cpu_maps(); + /* indicate the early static arrays will soon be gone */ + early_per_cpu_ptr(x86_cpu_to_apicid) = NULL; + early_per_cpu_ptr(x86_bios_cpu_apicid) = NULL; +#ifdef X86_64_NUMA + early_per_cpu_ptr(x86_cpu_to_node_map) = NULL; +#endif /* Setup node to cpumask map */ setup_node_to_cpumask_map(); -- GitLab From 6470aff619fbb9dff8dfe8afa5033084cd55ca20 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Tue, 27 Jan 2009 12:56:47 +0900 Subject: [PATCH 0450/4982] x86: move 64-bit NUMA code Impact: Code movement, no functional change. Move the 64-bit NUMA code from setup_percpu.c to numa_64.c Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/topology.h | 6 + arch/x86/kernel/setup_percpu.c | 237 +------------------------------- arch/x86/mm/numa_64.c | 217 +++++++++++++++++++++++++++++ 3 files changed, 228 insertions(+), 232 deletions(-) diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h index 10022ed3a4b..77cfb2cfb38 100644 --- a/arch/x86/include/asm/topology.h +++ b/arch/x86/include/asm/topology.h @@ -74,6 +74,8 @@ static inline const struct cpumask *cpumask_of_node(int node) return &node_to_cpumask_map[node]; } +static inline void setup_node_to_cpumask_map(void) { } + #else /* CONFIG_X86_64 */ /* Mappings between node number and cpus on that node. */ @@ -120,6 +122,8 @@ static inline cpumask_t node_to_cpumask(int node) #endif /* !CONFIG_DEBUG_PER_CPU_MAPS */ +extern void setup_node_to_cpumask_map(void); + /* * Replace default node_to_cpumask_ptr with optimized version * Deprecated: use "const struct cpumask *mask = cpumask_of_node(node)" @@ -218,6 +222,8 @@ static inline int node_to_first_cpu(int node) return first_cpu(cpu_online_map); } +static inline void setup_node_to_cpumask_map(void) { } + /* * Replace default node_to_cpumask_ptr with optimized version * Deprecated: use "const struct cpumask *mask = cpumask_of_node(node)" diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index d0b1476490a..cb6d622520b 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -51,32 +51,6 @@ DEFINE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid, BAD_APICID); EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_apicid); EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid); -#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64) -#define X86_64_NUMA 1 /* (used later) */ -DEFINE_PER_CPU(int, node_number) = 0; -EXPORT_PER_CPU_SYMBOL(node_number); - -/* - * Map cpu index to node index - */ -DEFINE_EARLY_PER_CPU(int, x86_cpu_to_node_map, NUMA_NO_NODE); -EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_node_map); - -/* - * Which logical CPUs are on which nodes - */ -cpumask_t *node_to_cpumask_map; -EXPORT_SYMBOL(node_to_cpumask_map); - -/* - * Setup node_to_cpumask_map - */ -static void __init setup_node_to_cpumask_map(void); - -#else -static inline void setup_node_to_cpumask_map(void) { } -#endif - #ifdef CONFIG_X86_64 /* correctly size the local cpu masks */ @@ -163,13 +137,13 @@ void __init setup_per_cpu_areas(void) early_per_cpu_map(x86_cpu_to_apicid, cpu); per_cpu(x86_bios_cpu_apicid, cpu) = early_per_cpu_map(x86_bios_cpu_apicid, cpu); -#ifdef X86_64_NUMA - per_cpu(x86_cpu_to_node_map, cpu) = - early_per_cpu_map(x86_cpu_to_node_map, cpu); -#endif #ifdef CONFIG_X86_64 per_cpu(irq_stack_ptr, cpu) = per_cpu(irq_stack_union.irq_stack, cpu) + IRQ_STACK_SIZE - 64; +#ifdef CONFIG_NUMA + per_cpu(x86_cpu_to_node_map, cpu) = + early_per_cpu_map(x86_cpu_to_node_map, cpu); +#endif /* * Up to this point, CPU0 has been using .data.init * area. Reload %gs offset for CPU0. @@ -184,7 +158,7 @@ void __init setup_per_cpu_areas(void) /* indicate the early static arrays will soon be gone */ early_per_cpu_ptr(x86_cpu_to_apicid) = NULL; early_per_cpu_ptr(x86_bios_cpu_apicid) = NULL; -#ifdef X86_64_NUMA +#if defined(CONFIG_X86_64) && defined(CONFIG_NUMA) early_per_cpu_ptr(x86_cpu_to_node_map) = NULL; #endif @@ -197,204 +171,3 @@ void __init setup_per_cpu_areas(void) #endif -#ifdef X86_64_NUMA - -/* - * Allocate node_to_cpumask_map based on number of available nodes - * Requires node_possible_map to be valid. - * - * Note: node_to_cpumask() is not valid until after this is done. - * (Use CONFIG_DEBUG_PER_CPU_MAPS to check this.) - */ -static void __init setup_node_to_cpumask_map(void) -{ - unsigned int node, num = 0; - cpumask_t *map; - - /* setup nr_node_ids if not done yet */ - if (nr_node_ids == MAX_NUMNODES) { - for_each_node_mask(node, node_possible_map) - num = node; - nr_node_ids = num + 1; - } - - /* allocate the map */ - map = alloc_bootmem_low(nr_node_ids * sizeof(cpumask_t)); - DBG("node_to_cpumask_map at %p for %d nodes\n", map, nr_node_ids); - - pr_debug("Node to cpumask map at %p for %d nodes\n", - map, nr_node_ids); - - /* node_to_cpumask() will now work */ - node_to_cpumask_map = map; -} - -void __cpuinit numa_set_node(int cpu, int node) -{ - int *cpu_to_node_map = early_per_cpu_ptr(x86_cpu_to_node_map); - - /* early setting, no percpu area yet */ - if (cpu_to_node_map) { - cpu_to_node_map[cpu] = node; - return; - } - -#ifdef CONFIG_DEBUG_PER_CPU_MAPS - if (cpu >= nr_cpu_ids || !per_cpu_offset(cpu)) { - printk(KERN_ERR "numa_set_node: invalid cpu# (%d)\n", cpu); - dump_stack(); - return; - } -#endif - per_cpu(x86_cpu_to_node_map, cpu) = node; - - if (node != NUMA_NO_NODE) - per_cpu(node_number, cpu) = node; -} - -void __cpuinit numa_clear_node(int cpu) -{ - numa_set_node(cpu, NUMA_NO_NODE); -} - -#ifndef CONFIG_DEBUG_PER_CPU_MAPS - -void __cpuinit numa_add_cpu(int cpu) -{ - cpu_set(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); -} - -void __cpuinit numa_remove_cpu(int cpu) -{ - cpu_clear(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); -} - -#else /* CONFIG_DEBUG_PER_CPU_MAPS */ - -/* - * --------- debug versions of the numa functions --------- - */ -static void __cpuinit numa_set_cpumask(int cpu, int enable) -{ - int node = early_cpu_to_node(cpu); - cpumask_t *mask; - char buf[64]; - - if (node_to_cpumask_map == NULL) { - printk(KERN_ERR "node_to_cpumask_map NULL\n"); - dump_stack(); - return; - } - - mask = &node_to_cpumask_map[node]; - if (enable) - cpu_set(cpu, *mask); - else - cpu_clear(cpu, *mask); - - cpulist_scnprintf(buf, sizeof(buf), mask); - printk(KERN_DEBUG "%s cpu %d node %d: mask now %s\n", - enable ? "numa_add_cpu" : "numa_remove_cpu", cpu, node, buf); -} - -void __cpuinit numa_add_cpu(int cpu) -{ - numa_set_cpumask(cpu, 1); -} - -void __cpuinit numa_remove_cpu(int cpu) -{ - numa_set_cpumask(cpu, 0); -} - -int cpu_to_node(int cpu) -{ - if (early_per_cpu_ptr(x86_cpu_to_node_map)) { - printk(KERN_WARNING - "cpu_to_node(%d): usage too early!\n", cpu); - dump_stack(); - return early_per_cpu_ptr(x86_cpu_to_node_map)[cpu]; - } - return per_cpu(x86_cpu_to_node_map, cpu); -} -EXPORT_SYMBOL(cpu_to_node); - -/* - * Same function as cpu_to_node() but used if called before the - * per_cpu areas are setup. - */ -int early_cpu_to_node(int cpu) -{ - if (early_per_cpu_ptr(x86_cpu_to_node_map)) - return early_per_cpu_ptr(x86_cpu_to_node_map)[cpu]; - - if (!per_cpu_offset(cpu)) { - printk(KERN_WARNING - "early_cpu_to_node(%d): no per_cpu area!\n", cpu); - dump_stack(); - return NUMA_NO_NODE; - } - return per_cpu(x86_cpu_to_node_map, cpu); -} - - -/* empty cpumask */ -static const cpumask_t cpu_mask_none; - -/* - * Returns a pointer to the bitmask of CPUs on Node 'node'. - */ -const cpumask_t *cpumask_of_node(int node) -{ - if (node_to_cpumask_map == NULL) { - printk(KERN_WARNING - "cpumask_of_node(%d): no node_to_cpumask_map!\n", - node); - dump_stack(); - return (const cpumask_t *)&cpu_online_map; - } - if (node >= nr_node_ids) { - printk(KERN_WARNING - "cpumask_of_node(%d): node > nr_node_ids(%d)\n", - node, nr_node_ids); - dump_stack(); - return &cpu_mask_none; - } - return &node_to_cpumask_map[node]; -} -EXPORT_SYMBOL(cpumask_of_node); - -/* - * Returns a bitmask of CPUs on Node 'node'. - * - * Side note: this function creates the returned cpumask on the stack - * so with a high NR_CPUS count, excessive stack space is used. The - * node_to_cpumask_ptr function should be used whenever possible. - */ -cpumask_t node_to_cpumask(int node) -{ - if (node_to_cpumask_map == NULL) { - printk(KERN_WARNING - "node_to_cpumask(%d): no node_to_cpumask_map!\n", node); - dump_stack(); - return cpu_online_map; - } - if (node >= nr_node_ids) { - printk(KERN_WARNING - "node_to_cpumask(%d): node > nr_node_ids(%d)\n", - node, nr_node_ids); - dump_stack(); - return cpu_mask_none; - } - return node_to_cpumask_map[node]; -} -EXPORT_SYMBOL(node_to_cpumask); - -/* - * --------- end of debug versions of the numa functions --------- - */ - -#endif /* CONFIG_DEBUG_PER_CPU_MAPS */ - -#endif /* X86_64_NUMA */ - diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c index 71a14f89f89..08d140fbc31 100644 --- a/arch/x86/mm/numa_64.c +++ b/arch/x86/mm/numa_64.c @@ -20,6 +20,12 @@ #include #include +#ifdef CONFIG_DEBUG_PER_CPU_MAPS +# define DBG(x...) printk(KERN_DEBUG x) +#else +# define DBG(x...) +#endif + struct pglist_data *node_data[MAX_NUMNODES] __read_mostly; EXPORT_SYMBOL(node_data); @@ -33,6 +39,21 @@ int numa_off __initdata; static unsigned long __initdata nodemap_addr; static unsigned long __initdata nodemap_size; +DEFINE_PER_CPU(int, node_number) = 0; +EXPORT_PER_CPU_SYMBOL(node_number); + +/* + * Map cpu index to node index + */ +DEFINE_EARLY_PER_CPU(int, x86_cpu_to_node_map, NUMA_NO_NODE); +EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_node_map); + +/* + * Which logical CPUs are on which nodes + */ +cpumask_t *node_to_cpumask_map; +EXPORT_SYMBOL(node_to_cpumask_map); + /* * Given a shift value, try to populate memnodemap[] * Returns : @@ -640,3 +661,199 @@ void __init init_cpu_to_node(void) #endif +/* + * Allocate node_to_cpumask_map based on number of available nodes + * Requires node_possible_map to be valid. + * + * Note: node_to_cpumask() is not valid until after this is done. + * (Use CONFIG_DEBUG_PER_CPU_MAPS to check this.) + */ +void __init setup_node_to_cpumask_map(void) +{ + unsigned int node, num = 0; + cpumask_t *map; + + /* setup nr_node_ids if not done yet */ + if (nr_node_ids == MAX_NUMNODES) { + for_each_node_mask(node, node_possible_map) + num = node; + nr_node_ids = num + 1; + } + + /* allocate the map */ + map = alloc_bootmem_low(nr_node_ids * sizeof(cpumask_t)); + DBG("node_to_cpumask_map at %p for %d nodes\n", map, nr_node_ids); + + pr_debug("Node to cpumask map at %p for %d nodes\n", + map, nr_node_ids); + + /* node_to_cpumask() will now work */ + node_to_cpumask_map = map; +} + +void __cpuinit numa_set_node(int cpu, int node) +{ + int *cpu_to_node_map = early_per_cpu_ptr(x86_cpu_to_node_map); + + /* early setting, no percpu area yet */ + if (cpu_to_node_map) { + cpu_to_node_map[cpu] = node; + return; + } + +#ifdef CONFIG_DEBUG_PER_CPU_MAPS + if (cpu >= nr_cpu_ids || !per_cpu_offset(cpu)) { + printk(KERN_ERR "numa_set_node: invalid cpu# (%d)\n", cpu); + dump_stack(); + return; + } +#endif + per_cpu(x86_cpu_to_node_map, cpu) = node; + + if (node != NUMA_NO_NODE) + per_cpu(node_number, cpu) = node; +} + +void __cpuinit numa_clear_node(int cpu) +{ + numa_set_node(cpu, NUMA_NO_NODE); +} + +#ifndef CONFIG_DEBUG_PER_CPU_MAPS + +void __cpuinit numa_add_cpu(int cpu) +{ + cpu_set(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); +} + +void __cpuinit numa_remove_cpu(int cpu) +{ + cpu_clear(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); +} + +#else /* CONFIG_DEBUG_PER_CPU_MAPS */ + +/* + * --------- debug versions of the numa functions --------- + */ +static void __cpuinit numa_set_cpumask(int cpu, int enable) +{ + int node = early_cpu_to_node(cpu); + cpumask_t *mask; + char buf[64]; + + if (node_to_cpumask_map == NULL) { + printk(KERN_ERR "node_to_cpumask_map NULL\n"); + dump_stack(); + return; + } + + mask = &node_to_cpumask_map[node]; + if (enable) + cpu_set(cpu, *mask); + else + cpu_clear(cpu, *mask); + + cpulist_scnprintf(buf, sizeof(buf), mask); + printk(KERN_DEBUG "%s cpu %d node %d: mask now %s\n", + enable ? "numa_add_cpu" : "numa_remove_cpu", cpu, node, buf); +} + +void __cpuinit numa_add_cpu(int cpu) +{ + numa_set_cpumask(cpu, 1); +} + +void __cpuinit numa_remove_cpu(int cpu) +{ + numa_set_cpumask(cpu, 0); +} + +int cpu_to_node(int cpu) +{ + if (early_per_cpu_ptr(x86_cpu_to_node_map)) { + printk(KERN_WARNING + "cpu_to_node(%d): usage too early!\n", cpu); + dump_stack(); + return early_per_cpu_ptr(x86_cpu_to_node_map)[cpu]; + } + return per_cpu(x86_cpu_to_node_map, cpu); +} +EXPORT_SYMBOL(cpu_to_node); + +/* + * Same function as cpu_to_node() but used if called before the + * per_cpu areas are setup. + */ +int early_cpu_to_node(int cpu) +{ + if (early_per_cpu_ptr(x86_cpu_to_node_map)) + return early_per_cpu_ptr(x86_cpu_to_node_map)[cpu]; + + if (!per_cpu_offset(cpu)) { + printk(KERN_WARNING + "early_cpu_to_node(%d): no per_cpu area!\n", cpu); + dump_stack(); + return NUMA_NO_NODE; + } + return per_cpu(x86_cpu_to_node_map, cpu); +} + + +/* empty cpumask */ +static const cpumask_t cpu_mask_none; + +/* + * Returns a pointer to the bitmask of CPUs on Node 'node'. + */ +const cpumask_t *cpumask_of_node(int node) +{ + if (node_to_cpumask_map == NULL) { + printk(KERN_WARNING + "cpumask_of_node(%d): no node_to_cpumask_map!\n", + node); + dump_stack(); + return (const cpumask_t *)&cpu_online_map; + } + if (node >= nr_node_ids) { + printk(KERN_WARNING + "cpumask_of_node(%d): node > nr_node_ids(%d)\n", + node, nr_node_ids); + dump_stack(); + return &cpu_mask_none; + } + return &node_to_cpumask_map[node]; +} +EXPORT_SYMBOL(cpumask_of_node); + +/* + * Returns a bitmask of CPUs on Node 'node'. + * + * Side note: this function creates the returned cpumask on the stack + * so with a high NR_CPUS count, excessive stack space is used. The + * node_to_cpumask_ptr function should be used whenever possible. + */ +cpumask_t node_to_cpumask(int node) +{ + if (node_to_cpumask_map == NULL) { + printk(KERN_WARNING + "node_to_cpumask(%d): no node_to_cpumask_map!\n", node); + dump_stack(); + return cpu_online_map; + } + if (node >= nr_node_ids) { + printk(KERN_WARNING + "node_to_cpumask(%d): node > nr_node_ids(%d)\n", + node, nr_node_ids); + dump_stack(); + return cpu_mask_none; + } + return node_to_cpumask_map[node]; +} +EXPORT_SYMBOL(node_to_cpumask); + +/* + * --------- end of debug versions of the numa functions --------- + */ + +#endif /* CONFIG_DEBUG_PER_CPU_MAPS */ -- GitLab From 2f2f52bad72f5e1ca5d1b9ad00a7b57a8cbd9159 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Tue, 27 Jan 2009 12:56:47 +0900 Subject: [PATCH 0451/4982] x86: move setup_cpu_local_masks() Impact: Code movement, no functional change. Move setup_cpu_local_masks() to kernel/cpu/common.c, where the masks are defined. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/cpumask.h | 4 ++++ arch/x86/kernel/cpu/common.c | 9 +++++++++ arch/x86/kernel/setup_percpu.c | 19 ------------------- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/arch/x86/include/asm/cpumask.h b/arch/x86/include/asm/cpumask.h index 26c6dad9047..a7f3c75f8ad 100644 --- a/arch/x86/include/asm/cpumask.h +++ b/arch/x86/include/asm/cpumask.h @@ -10,6 +10,8 @@ extern cpumask_var_t cpu_callout_mask; extern cpumask_var_t cpu_initialized_mask; extern cpumask_var_t cpu_sibling_setup_mask; +extern void setup_cpu_local_masks(void); + #else /* CONFIG_X86_32 */ extern cpumask_t cpu_callin_map; @@ -22,6 +24,8 @@ extern cpumask_t cpu_sibling_setup_map; #define cpu_initialized_mask ((struct cpumask *)&cpu_initialized) #define cpu_sibling_setup_mask ((struct cpumask *)&cpu_sibling_setup_map) +static inline void setup_cpu_local_masks(void) { } + #endif /* CONFIG_X86_32 */ #endif /* __ASSEMBLY__ */ diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 99904f288d6..67e30c8a282 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -52,6 +52,15 @@ cpumask_var_t cpu_initialized_mask; /* representing cpus for which sibling maps can be computed */ cpumask_var_t cpu_sibling_setup_mask; +/* correctly size the local cpu masks */ +void setup_cpu_local_masks(void) +{ + alloc_bootmem_cpumask_var(&cpu_initialized_mask); + alloc_bootmem_cpumask_var(&cpu_callin_mask); + alloc_bootmem_cpumask_var(&cpu_callout_mask); + alloc_bootmem_cpumask_var(&cpu_sibling_setup_mask); +} + #else /* CONFIG_X86_32 */ cpumask_t cpu_callin_map; diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index cb6d622520b..7bebdba8eb8 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -51,25 +51,6 @@ DEFINE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid, BAD_APICID); EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_apicid); EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid); -#ifdef CONFIG_X86_64 - -/* correctly size the local cpu masks */ -static void setup_cpu_local_masks(void) -{ - alloc_bootmem_cpumask_var(&cpu_initialized_mask); - alloc_bootmem_cpumask_var(&cpu_callin_mask); - alloc_bootmem_cpumask_var(&cpu_callout_mask); - alloc_bootmem_cpumask_var(&cpu_sibling_setup_mask); -} - -#else /* CONFIG_X86_32 */ - -static inline void setup_cpu_local_masks(void) -{ -} - -#endif /* CONFIG_X86_32 */ - #ifdef CONFIG_HAVE_SETUP_PER_CPU_AREA #ifdef CONFIG_X86_64 -- GitLab From 74631a248dc2c2129a96f6b8b706ed54bb5c3d3c Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Tue, 27 Jan 2009 12:56:47 +0900 Subject: [PATCH 0452/4982] x86: always page-align per-cpu area start and size Impact: cleanup The way the code is written, align is always PAGE_SIZE. Simplify the code by removing the align variable. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/kernel/setup_percpu.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 7bebdba8eb8..5d4a4964a8b 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -69,15 +69,12 @@ EXPORT_SYMBOL(__per_cpu_offset); */ void __init setup_per_cpu_areas(void) { - ssize_t size, old_size; + ssize_t size; char *ptr; int cpu; - unsigned long align = 1; /* Copy section for each CPU (we discard the original) */ - old_size = PERCPU_ENOUGH_ROOM; - align = max_t(unsigned long, PAGE_SIZE, align); - size = roundup(old_size, align); + size = roundup(PERCPU_ENOUGH_ROOM, PAGE_SIZE); pr_info("NR_CPUS:%d nr_cpumask_bits:%d nr_cpu_ids:%d nr_node_ids:%d\n", NR_CPUS, nr_cpumask_bits, nr_cpu_ids, nr_node_ids); @@ -86,20 +83,17 @@ void __init setup_per_cpu_areas(void) for_each_possible_cpu(cpu) { #ifndef CONFIG_NEED_MULTIPLE_NODES - ptr = __alloc_bootmem(size, align, - __pa(MAX_DMA_ADDRESS)); + ptr = alloc_bootmem_pages(size); #else int node = early_cpu_to_node(cpu); if (!node_online(node) || !NODE_DATA(node)) { - ptr = __alloc_bootmem(size, align, - __pa(MAX_DMA_ADDRESS)); + ptr = alloc_bootmem_pages(size); pr_info("cpu %d has no node %d or node-local memory\n", cpu, node); pr_debug("per cpu data for cpu%d at %016lx\n", cpu, __pa(ptr)); } else { - ptr = __alloc_bootmem_node(NODE_DATA(node), size, align, - __pa(MAX_DMA_ADDRESS)); + ptr = alloc_bootmem_pages_node(NODE_DATA(node), size); pr_debug("per cpu data for cpu%d on node%d at %016lx\n", cpu, node, __pa(ptr)); } -- GitLab From ec70de8b04bf37213982a5e8f303bc38679f3f8e Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Tue, 27 Jan 2009 12:56:47 +0900 Subject: [PATCH 0453/4982] x86: move apic variables to apic.c Impact: Code movement Move the variable definitions to apic.c. Ifdef the copying of the two early per-cpu variables, since Voyager doesn't use them. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/kernel/apic.c | 18 ++++++++++++++++++ arch/x86/kernel/setup_percpu.c | 22 ++-------------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 1df341a528a..c6f15647eba 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -60,6 +60,24 @@ # error SPURIOUS_APIC_VECTOR definition error #endif +unsigned int num_processors; +unsigned disabled_cpus __cpuinitdata; +/* Processor that is doing the boot up */ +unsigned int boot_cpu_physical_apicid = -1U; +EXPORT_SYMBOL(boot_cpu_physical_apicid); +unsigned int max_physical_apicid; + +/* Bitmask of physically existing CPUs */ +physid_mask_t phys_cpu_present_map; + +/* + * Map cpu index to physical APIC ID + */ +DEFINE_EARLY_PER_CPU(u16, x86_cpu_to_apicid, BAD_APICID); +DEFINE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid, BAD_APICID); +EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_apicid); +EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid); + #ifdef CONFIG_X86_32 /* * Knob to control our willingness to enable the local APIC. diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 5d4a4964a8b..d367996693e 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -31,26 +31,6 @@ DEFINE_PER_CPU(int, cpu_number); EXPORT_PER_CPU_SYMBOL(cpu_number); #endif -#ifdef CONFIG_X86_LOCAL_APIC -unsigned int num_processors; -unsigned disabled_cpus __cpuinitdata; -/* Processor that is doing the boot up */ -unsigned int boot_cpu_physical_apicid = -1U; -EXPORT_SYMBOL(boot_cpu_physical_apicid); -unsigned int max_physical_apicid; - -/* Bitmask of physically existing CPUs */ -physid_mask_t phys_cpu_present_map; -#endif - -/* - * Map cpu index to physical APIC ID - */ -DEFINE_EARLY_PER_CPU(u16, x86_cpu_to_apicid, BAD_APICID); -DEFINE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid, BAD_APICID); -EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_apicid); -EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid); - #ifdef CONFIG_HAVE_SETUP_PER_CPU_AREA #ifdef CONFIG_X86_64 @@ -108,10 +88,12 @@ void __init setup_per_cpu_areas(void) * per cpu data areas. These arrays then become expendable and the * *_early_ptr's are zeroed indicating that the static arrays are gone. */ +#ifdef CONFIG_X86_LOCAL_APIC per_cpu(x86_cpu_to_apicid, cpu) = early_per_cpu_map(x86_cpu_to_apicid, cpu); per_cpu(x86_bios_cpu_apicid, cpu) = early_per_cpu_map(x86_bios_cpu_apicid, cpu); +#endif #ifdef CONFIG_X86_64 per_cpu(irq_stack_ptr, cpu) = per_cpu(irq_stack_union.irq_stack, cpu) + IRQ_STACK_SIZE - 64; -- GitLab From 996db817e3d1529d711e55b938d72ae4060b39fd Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Tue, 27 Jan 2009 12:56:47 +0900 Subject: [PATCH 0454/4982] x86: only compile setup_percpu.o on SMP Impact: Minor build optimization Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/kernel/Makefile | 3 ++- arch/x86/kernel/setup_percpu.c | 6 ------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index a99437c965c..73de055c29c 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -28,7 +28,7 @@ CFLAGS_paravirt.o := $(nostackp) obj-y := process_$(BITS).o signal.o entry_$(BITS).o obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o obj-y += time_$(BITS).o ioport.o ldt.o dumpstack.o -obj-y += setup.o i8259.o irqinit_$(BITS).o setup_percpu.o +obj-y += setup.o i8259.o irqinit_$(BITS).o obj-$(CONFIG_X86_VISWS) += visws_quirks.o obj-$(CONFIG_X86_32) += probe_roms_32.o obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o @@ -59,6 +59,7 @@ apm-y := apm_32.o obj-$(CONFIG_APM) += apm.o obj-$(CONFIG_X86_SMP) += smp.o obj-$(CONFIG_X86_SMP) += smpboot.o tsc_sync.o ipi.o +obj-$(CONFIG_SMP) += setup_percpu.o obj-$(CONFIG_X86_32_SMP) += smpcommon.o obj-$(CONFIG_X86_64_SMP) += tsc_sync.o smpcommon.o obj-$(CONFIG_X86_TRAMPOLINE) += trampoline_$(BITS).o diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index d367996693e..f30ff691c34 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -22,14 +22,8 @@ # define DBG(x...) #endif -/* - * Could be inside CONFIG_HAVE_SETUP_PER_CPU_AREA with other stuff but - * voyager wants cpu_number too. - */ -#ifdef CONFIG_SMP DEFINE_PER_CPU(int, cpu_number); EXPORT_PER_CPU_SYMBOL(cpu_number); -#endif #ifdef CONFIG_HAVE_SETUP_PER_CPU_AREA -- GitLab From 1688401a0fddba8991aa5c0943b8ae9583998d60 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Tue, 27 Jan 2009 12:56:48 +0900 Subject: [PATCH 0455/4982] x86: move this_cpu_offset Impact: Small cleanup Define BOOT_PERCPU_OFFSET and use it for this_cpu_offset and __per_cpu_offset initializers. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/kernel/setup_percpu.c | 15 ++++++++++----- arch/x86/kernel/smpcommon.c | 7 ------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index f30ff691c34..36c2e81dfc3 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -25,15 +25,20 @@ DEFINE_PER_CPU(int, cpu_number); EXPORT_PER_CPU_SYMBOL(cpu_number); +#ifdef CONFIG_X86_64 +#define BOOT_PERCPU_OFFSET ((unsigned long)__per_cpu_load) +#else +#define BOOT_PERCPU_OFFSET 0 +#endif + +DEFINE_PER_CPU(unsigned long, this_cpu_off) = BOOT_PERCPU_OFFSET; +EXPORT_PER_CPU_SYMBOL(this_cpu_off); + #ifdef CONFIG_HAVE_SETUP_PER_CPU_AREA -#ifdef CONFIG_X86_64 unsigned long __per_cpu_offset[NR_CPUS] __read_mostly = { - [0] = (unsigned long)__per_cpu_load, + [0] = BOOT_PERCPU_OFFSET, }; -#else -unsigned long __per_cpu_offset[NR_CPUS] __read_mostly; -#endif EXPORT_SYMBOL(__per_cpu_offset); /* diff --git a/arch/x86/kernel/smpcommon.c b/arch/x86/kernel/smpcommon.c index add36b4e37c..5ec29a1a846 100644 --- a/arch/x86/kernel/smpcommon.c +++ b/arch/x86/kernel/smpcommon.c @@ -5,13 +5,6 @@ #include #include -#ifdef CONFIG_X86_64 -DEFINE_PER_CPU(unsigned long, this_cpu_off) = (unsigned long)__per_cpu_load; -#else -DEFINE_PER_CPU(unsigned long, this_cpu_off); -#endif -EXPORT_PER_CPU_SYMBOL(this_cpu_off); - #ifdef CONFIG_X86_32 /* * Initialize the CPU's GDT. This is either the boot CPU doing itself -- GitLab From 34019be1cd2941128b5de6d7c0fbdb51f967d268 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Tue, 27 Jan 2009 12:56:48 +0900 Subject: [PATCH 0456/4982] x86: don't assume boot cpu is #0 Impact: minor cleanup Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/kernel/setup_percpu.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 36c2e81dfc3..be77f1a1231 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -15,6 +15,7 @@ #include #include #include +#include #ifdef CONFIG_DEBUG_PER_CPU_MAPS # define DBG(x...) printk(KERN_DEBUG x) @@ -37,7 +38,7 @@ EXPORT_PER_CPU_SYMBOL(this_cpu_off); #ifdef CONFIG_HAVE_SETUP_PER_CPU_AREA unsigned long __per_cpu_offset[NR_CPUS] __read_mostly = { - [0] = BOOT_PERCPU_OFFSET, + [0 ... NR_CPUS-1] = BOOT_PERCPU_OFFSET, }; EXPORT_SYMBOL(__per_cpu_offset); @@ -101,10 +102,10 @@ void __init setup_per_cpu_areas(void) early_per_cpu_map(x86_cpu_to_node_map, cpu); #endif /* - * Up to this point, CPU0 has been using .data.init - * area. Reload %gs offset for CPU0. + * Up to this point, the boot CPU has been using .data.init + * area. Reload %gs offset for the boot CPU. */ - if (cpu == 0) + if (cpu == boot_cpu_id) load_gs_base(cpu); #endif -- GitLab From 89c9c4c58ee86e6e8802597271f23679e0c46647 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Tue, 27 Jan 2009 12:56:48 +0900 Subject: [PATCH 0457/4982] x86: make Voyager use x86 per-cpu setup. Impact: standardize all x86 platforms on same setup code With the preceding changes, Voyager can use the same per-cpu setup code as all the other x86 platforms. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/Kconfig | 2 +- arch/x86/kernel/setup_percpu.c | 5 ----- arch/x86/mach-voyager/voyager_smp.c | 3 --- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 5a29b792cb8..d6218e6c982 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -133,7 +133,7 @@ config ARCH_HAS_CACHE_LINE_SIZE def_bool y config HAVE_SETUP_PER_CPU_AREA - def_bool X86_64_SMP || (X86_SMP && !X86_VOYAGER) + def_bool y config HAVE_CPUMASK_OF_CPU_MAP def_bool X86_64_SMP diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index be77f1a1231..599dc1cc1da 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -35,8 +35,6 @@ EXPORT_PER_CPU_SYMBOL(cpu_number); DEFINE_PER_CPU(unsigned long, this_cpu_off) = BOOT_PERCPU_OFFSET; EXPORT_PER_CPU_SYMBOL(this_cpu_off); -#ifdef CONFIG_HAVE_SETUP_PER_CPU_AREA - unsigned long __per_cpu_offset[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BOOT_PERCPU_OFFSET, }; @@ -125,6 +123,3 @@ void __init setup_per_cpu_areas(void) /* Setup cpu initialized, callin, callout masks */ setup_cpu_local_masks(); } - -#endif - diff --git a/arch/x86/mach-voyager/voyager_smp.c b/arch/x86/mach-voyager/voyager_smp.c index 96f15b09a4c..dd82f2052f3 100644 --- a/arch/x86/mach-voyager/voyager_smp.c +++ b/arch/x86/mach-voyager/voyager_smp.c @@ -531,7 +531,6 @@ static void __init do_boot_cpu(__u8 cpu) stack_start.sp = (void *)idle->thread.sp; init_gdt(cpu); - per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu]; per_cpu(current_task, cpu) = idle; early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu); irq_ctx_init(cpu); @@ -1749,7 +1748,6 @@ static void __init voyager_smp_prepare_cpus(unsigned int max_cpus) static void __cpuinit voyager_smp_prepare_boot_cpu(void) { init_gdt(smp_processor_id()); - per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu]; switch_to_new_gdt(); cpu_set(smp_processor_id(), cpu_online_map); @@ -1782,7 +1780,6 @@ static void __init voyager_smp_cpus_done(unsigned int max_cpus) void __init smp_setup_processor_id(void) { current_thread_info()->cpu = hard_smp_processor_id(); - percpu_write(cpu_number, hard_smp_processor_id()); } static void voyager_send_call_func(cpumask_t callmask) -- GitLab From b2d2f4312b117a6cc647c8521e2643a88771f757 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Tue, 27 Jan 2009 12:56:48 +0900 Subject: [PATCH 0458/4982] x86: initialize per-cpu GDT segment in per-cpu setup Impact: cleanup Rename init_gdt() to setup_percpu_segment(), and move it to setup_percpu.c. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/processor.h | 1 - arch/x86/kernel/Makefile | 3 +-- arch/x86/kernel/setup_percpu.c | 14 ++++++++++++++ arch/x86/kernel/smpboot.c | 4 ---- arch/x86/kernel/smpcommon.c | 25 ------------------------- arch/x86/mach-voyager/voyager_smp.c | 2 -- arch/x86/xen/smp.c | 1 - 7 files changed, 15 insertions(+), 35 deletions(-) delete mode 100644 arch/x86/kernel/smpcommon.c diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 48676b943b9..32c30b02b51 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -778,7 +778,6 @@ extern struct desc_ptr early_gdt_descr; extern void cpu_set_gdt(int); extern void switch_to_new_gdt(void); extern void cpu_init(void); -extern void init_gdt(int cpu); static inline unsigned long get_debugctlmsr(void) { diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 73de055c29c..37fa30bada1 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -60,8 +60,7 @@ obj-$(CONFIG_APM) += apm.o obj-$(CONFIG_X86_SMP) += smp.o obj-$(CONFIG_X86_SMP) += smpboot.o tsc_sync.o ipi.o obj-$(CONFIG_SMP) += setup_percpu.o -obj-$(CONFIG_X86_32_SMP) += smpcommon.o -obj-$(CONFIG_X86_64_SMP) += tsc_sync.o smpcommon.o +obj-$(CONFIG_X86_64_SMP) += tsc_sync.o obj-$(CONFIG_X86_TRAMPOLINE) += trampoline_$(BITS).o obj-$(CONFIG_X86_MPPARSE) += mpparse.o obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 599dc1cc1da..bcca3a7b374 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -40,6 +40,19 @@ unsigned long __per_cpu_offset[NR_CPUS] __read_mostly = { }; EXPORT_SYMBOL(__per_cpu_offset); +static inline void setup_percpu_segment(int cpu) +{ +#ifdef CONFIG_X86_32 + struct desc_struct gdt; + + pack_descriptor(&gdt, per_cpu_offset(cpu), 0xFFFFF, + 0x2 | DESCTYPE_S, 0x8); + gdt.s = 1; + write_gdt_entry(get_cpu_gdt_table(cpu), + GDT_ENTRY_PERCPU, &gdt, DESCTYPE_S); +#endif +} + /* * Great future plan: * Declare PDA itself and support (irqstack,tss,pgd) as per cpu data. @@ -81,6 +94,7 @@ void __init setup_per_cpu_areas(void) per_cpu_offset(cpu) = ptr - __per_cpu_start; per_cpu(this_cpu_off, cpu) = per_cpu_offset(cpu); per_cpu(cpu_number, cpu) = cpu; + setup_percpu_segment(cpu); /* * Copy data used in early init routines from the initial arrays to the * per cpu data areas. These arrays then become expendable and the diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index def770b57b5..f9dbcff4354 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -793,7 +793,6 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu) do_rest: per_cpu(current_task, cpu) = c_idle.idle; #ifdef CONFIG_X86_32 - init_gdt(cpu); /* Stack for startup_32 can be just as for start_secondary onwards */ irq_ctx_init(cpu); #else @@ -1186,9 +1185,6 @@ out: void __init native_smp_prepare_boot_cpu(void) { int me = smp_processor_id(); -#ifdef CONFIG_X86_32 - init_gdt(me); -#endif switch_to_new_gdt(); /* already set me in cpu_online_mask in boot_cpu_init() */ cpumask_set_cpu(me, cpu_callout_mask); diff --git a/arch/x86/kernel/smpcommon.c b/arch/x86/kernel/smpcommon.c deleted file mode 100644 index 5ec29a1a846..00000000000 --- a/arch/x86/kernel/smpcommon.c +++ /dev/null @@ -1,25 +0,0 @@ -/* - * SMP stuff which is common to all sub-architectures. - */ -#include -#include -#include - -#ifdef CONFIG_X86_32 -/* - * Initialize the CPU's GDT. This is either the boot CPU doing itself - * (still using the master per-cpu area), or a CPU doing it for a - * secondary which will soon come up. - */ -__cpuinit void init_gdt(int cpu) -{ - struct desc_struct gdt; - - pack_descriptor(&gdt, __per_cpu_offset[cpu], 0xFFFFF, - 0x2 | DESCTYPE_S, 0x8); - gdt.s = 1; - - write_gdt_entry(get_cpu_gdt_table(cpu), - GDT_ENTRY_PERCPU, &gdt, DESCTYPE_S); -} -#endif diff --git a/arch/x86/mach-voyager/voyager_smp.c b/arch/x86/mach-voyager/voyager_smp.c index dd82f2052f3..331cd6d5648 100644 --- a/arch/x86/mach-voyager/voyager_smp.c +++ b/arch/x86/mach-voyager/voyager_smp.c @@ -530,7 +530,6 @@ static void __init do_boot_cpu(__u8 cpu) /* init_tasks (in sched.c) is indexed logically */ stack_start.sp = (void *)idle->thread.sp; - init_gdt(cpu); per_cpu(current_task, cpu) = idle; early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu); irq_ctx_init(cpu); @@ -1747,7 +1746,6 @@ static void __init voyager_smp_prepare_cpus(unsigned int max_cpus) static void __cpuinit voyager_smp_prepare_boot_cpu(void) { - init_gdt(smp_processor_id()); switch_to_new_gdt(); cpu_set(smp_processor_id(), cpu_online_map); diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 72c2eb9b64c..7735e3dd359 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -281,7 +281,6 @@ static int __cpuinit xen_cpu_up(unsigned int cpu) per_cpu(current_task, cpu) = idle; #ifdef CONFIG_X86_32 - init_gdt(cpu); irq_ctx_init(cpu); #else clear_tsk_thread_flag(idle, TIF_FORK); -- GitLab From 1825b8edc2034c012ae48f797d74efd1bd9d4f72 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Tue, 27 Jan 2009 12:56:48 +0900 Subject: [PATCH 0459/4982] x86: remove extra barriers from load_gs_base() Impact: optimization mb() generates an mfence instruction, which is not needed here. Only a compiler barrier is needed, and that is handled by the memory clobber in the wrmsrl function. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/processor.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 32c30b02b51..794234eba31 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -397,10 +397,7 @@ DECLARE_PER_CPU(char *, irq_stack_ptr); static inline void load_gs_base(int cpu) { - /* Memory clobbers used to order pda/percpu accesses */ - mb(); wrmsrl(MSR_GS_BASE, (unsigned long)per_cpu(irq_stack_union.gs_base, cpu)); - mb(); } #endif -- GitLab From 2697fbd5faf19c84c17441b1752bdcbdcfd1248c Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Tue, 27 Jan 2009 12:56:48 +0900 Subject: [PATCH 0460/4982] x86: load new GDT after setting up boot cpu per-cpu area Impact: sync 32 and 64-bit code Merge load_gs_base() into switch_to_new_gdt(). Load the GDT and per-cpu state for the boot cpu when its new area is set up. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/processor.h | 5 ----- arch/x86/kernel/cpu/common.c | 15 +++++++++------ arch/x86/kernel/setup_percpu.c | 6 +++--- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 794234eba31..befa20b4a68 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -394,11 +394,6 @@ union irq_stack_union { DECLARE_PER_CPU(union irq_stack_union, irq_stack_union); DECLARE_PER_CPU(char *, irq_stack_ptr); - -static inline void load_gs_base(int cpu) -{ - wrmsrl(MSR_GS_BASE, (unsigned long)per_cpu(irq_stack_union.gs_base, cpu)); -} #endif extern void print_cpu_info(struct cpuinfo_x86 *); diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 67e30c8a282..0c766b80d91 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -258,12 +258,17 @@ __u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata; void switch_to_new_gdt(void) { struct desc_ptr gdt_descr; + int cpu = smp_processor_id(); - gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id()); + gdt_descr.address = (long)get_cpu_gdt_table(cpu); gdt_descr.size = GDT_SIZE - 1; load_gdt(&gdt_descr); + /* Reload the per-cpu base */ #ifdef CONFIG_X86_32 - asm("mov %0, %%fs" : : "r" (__KERNEL_PERCPU) : "memory"); + loadsegment(fs, __KERNEL_PERCPU); +#else + loadsegment(gs, 0); + wrmsrl(MSR_GS_BASE, (unsigned long)per_cpu(irq_stack_union.gs_base, cpu)); #endif } @@ -968,10 +973,6 @@ void __cpuinit cpu_init(void) struct task_struct *me; int i; - loadsegment(fs, 0); - loadsegment(gs, 0); - load_gs_base(cpu); - #ifdef CONFIG_NUMA if (cpu != 0 && percpu_read(node_number) == 0 && cpu_to_node(cpu) != NUMA_NO_NODE) @@ -993,6 +994,8 @@ void __cpuinit cpu_init(void) */ switch_to_new_gdt(); + loadsegment(fs, 0); + load_idt((const struct desc_ptr *)&idt_descr); memset(me->thread.tls_array, 0, GDT_ENTRY_TLS_ENTRIES * 8); diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index bcca3a7b374..4caa78d7cb1 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -112,14 +112,14 @@ void __init setup_per_cpu_areas(void) #ifdef CONFIG_NUMA per_cpu(x86_cpu_to_node_map, cpu) = early_per_cpu_map(x86_cpu_to_node_map, cpu); +#endif #endif /* * Up to this point, the boot CPU has been using .data.init - * area. Reload %gs offset for the boot CPU. + * area. Reload any changed state for the boot CPU. */ if (cpu == boot_cpu_id) - load_gs_base(cpu); -#endif + switch_to_new_gdt(); DBG("PERCPU: cpu %4d %p\n", cpu, ptr); } -- GitLab From afcf12422ec8236dc8b9238fef7a475876eea8da Mon Sep 17 00:00:00 2001 From: Timo Teras Date: Mon, 26 Jan 2009 20:56:10 -0800 Subject: [PATCH 0461/4982] gre: optimize hash lookup Instead of keeping candidate tunnel device from all categories, keep only one candidate with best score. This optimizes stack usage and speeds up exit code. Signed-off-by: Timo Teras Signed-off-by: David S. Miller --- net/ipv4/ip_gre.c | 69 +++++++++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 4a43739c903..07a188afb3a 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -172,11 +172,11 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev, int link = dev->ifindex; unsigned h0 = HASH(remote); unsigned h1 = HASH(key); - struct ip_tunnel *t, *sel[4] = { NULL, NULL, NULL, NULL }; + struct ip_tunnel *t, *cand = NULL; struct ipgre_net *ign = net_generic(net, ipgre_net_id); int dev_type = (gre_proto == htons(ETH_P_TEB)) ? ARPHRD_ETHER : ARPHRD_IPGRE; - int idx; + int score, cand_score = 4; for (t = ign->tunnels_r_l[h0^h1]; t; t = t->next) { if (local != t->parms.iph.saddr || @@ -189,15 +189,18 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev, t->dev->type != dev_type) continue; - idx = 0; + score = 0; if (t->parms.link != link) - idx |= 1; + score |= 1; if (t->dev->type != dev_type) - idx |= 2; - if (idx == 0) + score |= 2; + if (score == 0) return t; - if (sel[idx] == NULL) - sel[idx] = t; + + if (score < cand_score) { + cand = t; + cand_score = score; + } } for (t = ign->tunnels_r[h0^h1]; t; t = t->next) { @@ -210,15 +213,18 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev, t->dev->type != dev_type) continue; - idx = 0; + score = 0; if (t->parms.link != link) - idx |= 1; + score |= 1; if (t->dev->type != dev_type) - idx |= 2; - if (idx == 0) + score |= 2; + if (score == 0) return t; - if (sel[idx] == NULL) - sel[idx] = t; + + if (score < cand_score) { + cand = t; + cand_score = score; + } } for (t = ign->tunnels_l[h1]; t; t = t->next) { @@ -233,15 +239,18 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev, t->dev->type != dev_type) continue; - idx = 0; + score = 0; if (t->parms.link != link) - idx |= 1; + score |= 1; if (t->dev->type != dev_type) - idx |= 2; - if (idx == 0) + score |= 2; + if (score == 0) return t; - if (sel[idx] == NULL) - sel[idx] = t; + + if (score < cand_score) { + cand = t; + cand_score = score; + } } for (t = ign->tunnels_wc[h1]; t; t = t->next) { @@ -253,20 +262,22 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev, t->dev->type != dev_type) continue; - idx = 0; + score = 0; if (t->parms.link != link) - idx |= 1; + score |= 1; if (t->dev->type != dev_type) - idx |= 2; - if (idx == 0) + score |= 2; + if (score == 0) return t; - if (sel[idx] == NULL) - sel[idx] = t; + + if (score < cand_score) { + cand = t; + cand_score = score; + } } - for (idx = 1; idx < ARRAY_SIZE(sel); idx++) - if (sel[idx] != NULL) - return sel[idx]; + if (cand != NULL) + return cand; if (ign->fb_tunnel_dev->flags & IFF_UP) return netdev_priv(ign->fb_tunnel_dev); -- GitLab From 5b9c3cdd55ba57a25ae586373aaff723d8150085 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Mon, 26 Jan 2009 20:57:17 -0800 Subject: [PATCH 0462/4982] ixgbe: fix slow load times on 82598 nics Load times for NICs that use i2c to communicate with the phy were taking ~4.5 sec per port. This fix first checks to see if the link is already up before calling get_link_capabilities, since if it is we don't need query the phy for link state. Signed-off-by: Don Skidmore Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index f7b592eff68..18d4353afa6 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3901,16 +3901,27 @@ static void ixgbe_netpoll(struct net_device *netdev) **/ static int ixgbe_link_config(struct ixgbe_hw *hw) { - u32 autoneg = IXGBE_LINK_SPEED_10GB_FULL; + u32 autoneg; + bool link_up = false; + u32 ret = IXGBE_ERR_LINK_SETUP; - /* must always autoneg for both 1G and 10G link */ - hw->mac.autoneg = true; + if (hw->mac.ops.check_link) + ret = hw->mac.ops.check_link(hw, &autoneg, &link_up, false); - if ((hw->mac.type == ixgbe_mac_82598EB) && - (hw->phy.media_type == ixgbe_media_type_copper)) - autoneg = IXGBE_LINK_SPEED_82598_AUTONEG; + if (ret || !link_up) + goto link_cfg_out; - return hw->mac.ops.setup_link_speed(hw, autoneg, true, true); + if (hw->mac.ops.get_link_capabilities) + ret = hw->mac.ops.get_link_capabilities(hw, &autoneg, + &hw->mac.autoneg); + if (ret) + goto link_cfg_out; + + if (hw->mac.ops.setup_link_speed) + ret = hw->mac.ops.setup_link_speed(hw, autoneg, true, true); + +link_cfg_out: + return ret; } static const struct net_device_ops ixgbe_netdev_ops = { -- GitLab From 1e336d0fc99f159ed636ffb9128bc84e09ccc279 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Mon, 26 Jan 2009 20:57:51 -0800 Subject: [PATCH 0463/4982] ixgbe: add support KX/KX4 device And support for the KX/KX4 mezzanine card. Device id 0x10B6. Signed-off-by: Don Skidmore Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_82598.c | 9 +++++++++ drivers/net/ixgbe/ixgbe_ethtool.c | 12 ++++++++++++ drivers/net/ixgbe/ixgbe_main.c | 2 ++ drivers/net/ixgbe/ixgbe_type.h | 1 + 4 files changed, 24 insertions(+) diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index ad5699d9ab0..6c7ddb96ed0 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -213,6 +213,10 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw) /* Media type for I82598 is based on device ID */ switch (hw->device_id) { + case IXGBE_DEV_ID_82598: + /* Default device ID is mezzanine card KX/KX4 */ + media_type = ixgbe_media_type_backplane; + break; case IXGBE_DEV_ID_82598AF_DUAL_PORT: case IXGBE_DEV_ID_82598AF_SINGLE_PORT: case IXGBE_DEV_ID_82598EB_CX4: @@ -1002,6 +1006,11 @@ static s32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw) s32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; switch (hw->device_id) { + case IXGBE_DEV_ID_82598: + /* Default device ID is mezzanine card KX/KX4 */ + physical_layer = (IXGBE_PHYSICAL_LAYER_10GBASE_KX4 | + IXGBE_PHYSICAL_LAYER_1000BASE_KX); + break; case IXGBE_DEV_ID_82598EB_CX4: case IXGBE_DEV_ID_82598_CX4_DUAL_PORT: physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4; diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 4f6b5dfc78a..444200fa31e 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -130,6 +130,18 @@ static int ixgbe_get_settings(struct net_device *netdev, ecmd->advertising |= ADVERTISED_1000baseT_Full; ecmd->port = PORT_TP; + } else if (hw->phy.media_type == ixgbe_media_type_backplane) { + /* Set as FIBRE until SERDES defined in kernel */ + switch (hw->device_id) { + case IXGBE_DEV_ID_82598: + ecmd->supported |= (SUPPORTED_1000baseT_Full | + SUPPORTED_FIBRE); + ecmd->advertising = (ADVERTISED_10000baseT_Full | + ADVERTISED_1000baseT_Full | + ADVERTISED_FIBRE); + ecmd->port = PORT_FIBRE; + break; + } } else { ecmd->supported |= SUPPORTED_FIBRE; ecmd->advertising = (ADVERTISED_10000baseT_Full | diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 18d4353afa6..43980dc45e3 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -64,6 +64,8 @@ static const struct ixgbe_info *ixgbe_info_tbl[] = { * Class, Class Mask, private data (not used) } */ static struct pci_device_id ixgbe_pci_tbl[] = { + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598), + board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_DUAL_PORT), board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_SINGLE_PORT), diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index f011c57c920..e43f0c7c341 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -34,6 +34,7 @@ #define IXGBE_INTEL_VENDOR_ID 0x8086 /* Device IDs */ +#define IXGBE_DEV_ID_82598 0x10B6 #define IXGBE_DEV_ID_82598AF_DUAL_PORT 0x10C6 #define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7 #define IXGBE_DEV_ID_82598EB_SFP_LOM 0x10DB -- GitLab From 5075138d67ac66adab777163907d92d1a955ff50 Mon Sep 17 00:00:00 2001 From: "remi.denis-courmont@nokia" Date: Fri, 23 Jan 2009 03:00:25 +0000 Subject: [PATCH 0464/4982] Phonet: move to Networking options like other protocol stacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- net/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/Kconfig b/net/Kconfig index cdb8fdef6c4..a12bae0e3fe 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -185,6 +185,7 @@ source "net/x25/Kconfig" source "net/lapb/Kconfig" source "net/econet/Kconfig" source "net/wanrouter/Kconfig" +source "net/phonet/Kconfig" source "net/sched/Kconfig" source "net/dcb/Kconfig" @@ -229,7 +230,6 @@ source "net/can/Kconfig" source "net/irda/Kconfig" source "net/bluetooth/Kconfig" source "net/rxrpc/Kconfig" -source "net/phonet/Kconfig" config FIB_RULES bool -- GitLab From 4b8f704bea70a2c8719e47f53197678a87a0c62f Mon Sep 17 00:00:00 2001 From: "remi.denis-courmont@nokia" Date: Fri, 23 Jan 2009 03:00:26 +0000 Subject: [PATCH 0465/4982] Phonet: check destination before delivering packets locally MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- net/phonet/af_phonet.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index 13cb323f8c3..c7c39d92ee5 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c @@ -275,8 +275,6 @@ static inline int can_respond(struct sk_buff *skb) return 0; ph = pn_hdr(skb); - if (phonet_address_get(skb->dev, ph->pn_rdev) != ph->pn_rdev) - return 0; /* we are not the destination */ if (ph->pn_res == PN_PREFIX && !pskb_may_pull(skb, 5)) return 0; if (ph->pn_res == PN_COMMGR) /* indications */ @@ -344,8 +342,8 @@ static int phonet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pkttype, struct net_device *orig_dev) { + struct net *net = dev_net(dev); struct phonethdr *ph; - struct sock *sk; struct sockaddr_pn sa; u16 len; @@ -364,21 +362,21 @@ static int phonet_rcv(struct sk_buff *skb, struct net_device *dev, skb_reset_transport_header(skb); pn_skb_get_dst_sockaddr(skb, &sa); - if (pn_sockaddr_get_addr(&sa) == 0) - goto out; /* currently, we cannot be device 0 */ - sk = pn_find_sock_by_sa(dev_net(dev), &sa); - if (sk == NULL) { + /* check if we are the destination */ + if (phonet_address_lookup(net, pn_sockaddr_get_addr(&sa)) == 0) { + /* Phonet packet input */ + struct sock *sk = pn_find_sock_by_sa(net, &sa); + + if (sk) + return sk_receive_skb(sk, skb, 0); + if (can_respond(skb)) { send_obj_unreachable(skb); send_reset_indications(skb); } - goto out; } - /* Push data to the socket (or other sockets connected to it). */ - return sk_receive_skb(sk, skb, 0); - out: kfree_skb(skb); return NET_RX_DROP; -- GitLab From 76e02cf6945e6faa9f6b546dc0513512197c5966 Mon Sep 17 00:00:00 2001 From: "remi.denis-courmont@nokia" Date: Fri, 23 Jan 2009 03:00:27 +0000 Subject: [PATCH 0466/4982] Phonet: allow phonet_device_init() to fail, put it to __init section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- include/net/phonet/phonet.h | 1 - include/net/phonet/pn_dev.h | 3 ++- net/phonet/af_phonet.c | 9 ++++++--- net/phonet/pn_dev.c | 4 +++- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/net/phonet/phonet.h b/include/net/phonet/phonet.h index 057b0a8a288..d43f71b5ec0 100644 --- a/include/net/phonet/phonet.h +++ b/include/net/phonet/phonet.h @@ -105,7 +105,6 @@ void phonet_proto_unregister(int protocol, struct phonet_protocol *pp); int phonet_sysctl_init(void); void phonet_sysctl_exit(void); -void phonet_netlink_register(void); int isi_register(void); void isi_unregister(void); diff --git a/include/net/phonet/pn_dev.h b/include/net/phonet/pn_dev.h index aa1c59a1d33..59ae628b111 100644 --- a/include/net/phonet/pn_dev.h +++ b/include/net/phonet/pn_dev.h @@ -36,8 +36,9 @@ struct phonet_device { DECLARE_BITMAP(addrs, 64); }; -void phonet_device_init(void); +int phonet_device_init(void); void phonet_device_exit(void); +void phonet_netlink_register(void); struct net_device *phonet_device_get(struct net *net); int phonet_address_add(struct net_device *dev, u8 addr); diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index c7c39d92ee5..95bc49ddb8b 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c @@ -426,16 +426,18 @@ static int __init phonet_init(void) { int err; + err = phonet_device_init(); + if (err) + return err; + err = sock_register(&phonet_proto_family); if (err) { printk(KERN_ALERT "phonet protocol family initialization failed\n"); - return err; + goto err_sock; } - phonet_device_init(); dev_add_pack(&phonet_packet_type); - phonet_netlink_register(); phonet_sysctl_init(); err = isi_register(); @@ -447,6 +449,7 @@ err: phonet_sysctl_exit(); sock_unregister(PF_PHONET); dev_remove_pack(&phonet_packet_type); +err_sock: phonet_device_exit(); return err; } diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index 5491bf5e354..af49db01d63 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c @@ -188,9 +188,11 @@ static struct notifier_block phonet_device_notifier = { }; /* Initialize Phonet devices list */ -void phonet_device_init(void) +int __init phonet_device_init(void) { register_netdevice_notifier(&phonet_device_notifier); + phonet_netlink_register(); + return 0; } void phonet_device_exit(void) -- GitLab From 660f706d931d4795d341805e083a8091af74fa88 Mon Sep 17 00:00:00 2001 From: "remi.denis-courmont@nokia" Date: Fri, 23 Jan 2009 03:00:28 +0000 Subject: [PATCH 0467/4982] Phonet: handle rtnetlink registration failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- include/net/phonet/pn_dev.h | 2 +- net/phonet/pn_dev.c | 8 ++++++-- net/phonet/pn_netlink.c | 13 +++++++++---- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/include/net/phonet/pn_dev.h b/include/net/phonet/pn_dev.h index 59ae628b111..4ba2aedaa50 100644 --- a/include/net/phonet/pn_dev.h +++ b/include/net/phonet/pn_dev.h @@ -38,7 +38,7 @@ struct phonet_device { int phonet_device_init(void); void phonet_device_exit(void); -void phonet_netlink_register(void); +int phonet_netlink_register(void); struct net_device *phonet_device_get(struct net *net); int phonet_address_add(struct net_device *dev, u8 addr); diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index af49db01d63..fd418107652 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c @@ -190,9 +190,13 @@ static struct notifier_block phonet_device_notifier = { /* Initialize Phonet devices list */ int __init phonet_device_init(void) { + int err; + register_netdevice_notifier(&phonet_device_notifier); - phonet_netlink_register(); - return 0; + err = phonet_netlink_register(); + if (err) + phonet_device_exit(); + return err; } void phonet_device_exit(void) diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c index 242fe8f8c32..918a4f07f24 100644 --- a/net/phonet/pn_netlink.c +++ b/net/phonet/pn_netlink.c @@ -160,9 +160,14 @@ out: return skb->len; } -void __init phonet_netlink_register(void) +int __init phonet_netlink_register(void) { - rtnl_register(PF_PHONET, RTM_NEWADDR, addr_doit, NULL); - rtnl_register(PF_PHONET, RTM_DELADDR, addr_doit, NULL); - rtnl_register(PF_PHONET, RTM_GETADDR, NULL, getaddr_dumpit); + int err = __rtnl_register(PF_PHONET, RTM_NEWADDR, addr_doit, NULL); + if (err) + return err; + + /* Further __rtnl_register() cannot fail */ + __rtnl_register(PF_PHONET, RTM_DELADDR, addr_doit, NULL); + __rtnl_register(PF_PHONET, RTM_GETADDR, NULL, getaddr_dumpit); + return 0; } -- GitLab From 6530e0fee1834fab51720769ac422186de2b3120 Mon Sep 17 00:00:00 2001 From: "remi.denis-courmont@nokia" Date: Fri, 23 Jan 2009 03:00:29 +0000 Subject: [PATCH 0468/4982] Phonet: remove useless locking in device cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Incoming packets and sockets are already gone. The netdevice notifier is unregistered under the RTNL lock There remains a race with the rtnetlink handlers unregistration, but it is a generic RTNL issue that was already present before this change. Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- net/phonet/pn_dev.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index fd418107652..3e24c0522ee 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c @@ -204,13 +204,8 @@ void phonet_device_exit(void) struct phonet_device *pnd, *n; rtnl_unregister_all(PF_PHONET); - rtnl_lock(); - spin_lock_bh(&pndevs.lock); + unregister_netdevice_notifier(&phonet_device_notifier); list_for_each_entry_safe(pnd, n, &pndevs.list, list) __phonet_device_free(pnd); - - spin_unlock_bh(&pndevs.lock); - rtnl_unlock(); - unregister_netdevice_notifier(&phonet_device_notifier); } -- GitLab From 9a3b7a42bb2919a6282a96a5f4abe0f9be36c4b3 Mon Sep 17 00:00:00 2001 From: "remi.denis-courmont@nokia" Date: Fri, 23 Jan 2009 03:00:30 +0000 Subject: [PATCH 0469/4982] Phonet: use per-namespace devices list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- include/net/phonet/pn_dev.h | 2 +- net/phonet/pn_dev.c | 108 +++++++++++++++++++++++++----------- net/phonet/pn_netlink.c | 11 ++-- 3 files changed, 81 insertions(+), 40 deletions(-) diff --git a/include/net/phonet/pn_dev.h b/include/net/phonet/pn_dev.h index 4ba2aedaa50..5054dc5ea2c 100644 --- a/include/net/phonet/pn_dev.h +++ b/include/net/phonet/pn_dev.h @@ -28,7 +28,7 @@ struct phonet_device_list { spinlock_t lock; }; -extern struct phonet_device_list pndevs; +struct phonet_device_list *phonet_device_list(struct net *net); struct phonet_device { struct list_head list; diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index 3e24c0522ee..80a322d7790 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c @@ -28,32 +28,41 @@ #include #include #include +#include #include -/* when accessing, remember to lock with spin_lock(&pndevs.lock); */ -struct phonet_device_list pndevs = { - .list = LIST_HEAD_INIT(pndevs.list), - .lock = __SPIN_LOCK_UNLOCKED(pndevs.lock), +struct phonet_net { + struct phonet_device_list pndevs; }; +int phonet_net_id; + +struct phonet_device_list *phonet_device_list(struct net *net) +{ + struct phonet_net *pnn = net_generic(net, phonet_net_id); + return &pnn->pndevs; +} + /* Allocate new Phonet device. */ static struct phonet_device *__phonet_device_alloc(struct net_device *dev) { + struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev)); struct phonet_device *pnd = kmalloc(sizeof(*pnd), GFP_ATOMIC); if (pnd == NULL) return NULL; pnd->netdev = dev; bitmap_zero(pnd->addrs, 64); - list_add(&pnd->list, &pndevs.list); + list_add(&pnd->list, &pndevs->list); return pnd; } static struct phonet_device *__phonet_get(struct net_device *dev) { + struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev)); struct phonet_device *pnd; - list_for_each_entry(pnd, &pndevs.list, list) { + list_for_each_entry(pnd, &pndevs->list, list) { if (pnd->netdev == dev) return pnd; } @@ -68,32 +77,33 @@ static void __phonet_device_free(struct phonet_device *pnd) struct net_device *phonet_device_get(struct net *net) { + struct phonet_device_list *pndevs = phonet_device_list(net); struct phonet_device *pnd; struct net_device *dev; - spin_lock_bh(&pndevs.lock); - list_for_each_entry(pnd, &pndevs.list, list) { + spin_lock_bh(&pndevs->lock); + list_for_each_entry(pnd, &pndevs->list, list) { dev = pnd->netdev; BUG_ON(!dev); - if (net_eq(dev_net(dev), net) && - (dev->reg_state == NETREG_REGISTERED) && + if ((dev->reg_state == NETREG_REGISTERED) && ((pnd->netdev->flags & IFF_UP)) == IFF_UP) break; dev = NULL; } if (dev) dev_hold(dev); - spin_unlock_bh(&pndevs.lock); + spin_unlock_bh(&pndevs->lock); return dev; } int phonet_address_add(struct net_device *dev, u8 addr) { + struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev)); struct phonet_device *pnd; int err = 0; - spin_lock_bh(&pndevs.lock); + spin_lock_bh(&pndevs->lock); /* Find or create Phonet-specific device data */ pnd = __phonet_get(dev); if (pnd == NULL) @@ -102,31 +112,33 @@ int phonet_address_add(struct net_device *dev, u8 addr) err = -ENOMEM; else if (test_and_set_bit(addr >> 2, pnd->addrs)) err = -EEXIST; - spin_unlock_bh(&pndevs.lock); + spin_unlock_bh(&pndevs->lock); return err; } int phonet_address_del(struct net_device *dev, u8 addr) { + struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev)); struct phonet_device *pnd; int err = 0; - spin_lock_bh(&pndevs.lock); + spin_lock_bh(&pndevs->lock); pnd = __phonet_get(dev); if (!pnd || !test_and_clear_bit(addr >> 2, pnd->addrs)) err = -EADDRNOTAVAIL; else if (bitmap_empty(pnd->addrs, 64)) __phonet_device_free(pnd); - spin_unlock_bh(&pndevs.lock); + spin_unlock_bh(&pndevs->lock); return err; } /* Gets a source address toward a destination, through a interface. */ u8 phonet_address_get(struct net_device *dev, u8 addr) { + struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev)); struct phonet_device *pnd; - spin_lock_bh(&pndevs.lock); + spin_lock_bh(&pndevs->lock); pnd = __phonet_get(dev); if (pnd) { BUG_ON(bitmap_empty(pnd->addrs, 64)); @@ -136,30 +148,31 @@ u8 phonet_address_get(struct net_device *dev, u8 addr) addr = find_first_bit(pnd->addrs, 64) << 2; } else addr = PN_NO_ADDR; - spin_unlock_bh(&pndevs.lock); + spin_unlock_bh(&pndevs->lock); return addr; } int phonet_address_lookup(struct net *net, u8 addr) { + struct phonet_device_list *pndevs = phonet_device_list(net); struct phonet_device *pnd; + int err = -EADDRNOTAVAIL; - spin_lock_bh(&pndevs.lock); - list_for_each_entry(pnd, &pndevs.list, list) { - if (!net_eq(dev_net(pnd->netdev), net)) - continue; + spin_lock_bh(&pndevs->lock); + list_for_each_entry(pnd, &pndevs->list, list) { /* Don't allow unregistering devices! */ if ((pnd->netdev->reg_state != NETREG_REGISTERED) || ((pnd->netdev->flags & IFF_UP)) != IFF_UP) continue; if (test_bit(addr >> 2, pnd->addrs)) { - spin_unlock_bh(&pndevs.lock); - return 0; + err = 0; + goto found; } } - spin_unlock_bh(&pndevs.lock); - return -EADDRNOTAVAIL; +found: + spin_unlock_bh(&pndevs->lock); + return err; } /* notify Phonet of device events */ @@ -169,14 +182,16 @@ static int phonet_device_notify(struct notifier_block *me, unsigned long what, struct net_device *dev = arg; if (what == NETDEV_UNREGISTER) { + struct phonet_device_list *pndevs; struct phonet_device *pnd; /* Destroy phonet-specific device data */ - spin_lock_bh(&pndevs.lock); + pndevs = phonet_device_list(dev_net(dev)); + spin_lock_bh(&pndevs->lock); pnd = __phonet_get(dev); if (pnd) __phonet_device_free(pnd); - spin_unlock_bh(&pndevs.lock); + spin_unlock_bh(&pndevs->lock); } return 0; @@ -187,10 +202,41 @@ static struct notifier_block phonet_device_notifier = { .priority = 0, }; +/* Per-namespace Phonet devices handling */ +static int phonet_init_net(struct net *net) +{ + struct phonet_net *pnn = kmalloc(sizeof(*pnn), GFP_KERNEL); + if (!pnn) + return -ENOMEM; + + INIT_LIST_HEAD(&pnn->pndevs.list); + spin_lock_init(&pnn->pndevs.lock); + net_assign_generic(net, phonet_net_id, pnn); + return 0; +} + +static void phonet_exit_net(struct net *net) +{ + struct phonet_net *pnn = net_generic(net, phonet_net_id); + struct phonet_device *pnd, *n; + + list_for_each_entry_safe(pnd, n, &pnn->pndevs.list, list) + __phonet_device_free(pnd); + + kfree(pnn); +} + +static struct pernet_operations phonet_net_ops = { + .init = phonet_init_net, + .exit = phonet_exit_net, +}; + /* Initialize Phonet devices list */ int __init phonet_device_init(void) { - int err; + int err = register_pernet_gen_device(&phonet_net_id, &phonet_net_ops); + if (err) + return err; register_netdevice_notifier(&phonet_device_notifier); err = phonet_netlink_register(); @@ -201,11 +247,7 @@ int __init phonet_device_init(void) void phonet_device_exit(void) { - struct phonet_device *pnd, *n; - rtnl_unregister_all(PF_PHONET); unregister_netdevice_notifier(&phonet_device_notifier); - - list_for_each_entry_safe(pnd, n, &pndevs.list, list) - __phonet_device_free(pnd); + unregister_pernet_gen_device(phonet_net_id, &phonet_net_ops); } diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c index 918a4f07f24..1ceea1f9241 100644 --- a/net/phonet/pn_netlink.c +++ b/net/phonet/pn_netlink.c @@ -123,17 +123,16 @@ nla_put_failure: static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb) { - struct net *net = sock_net(skb->sk); + struct phonet_device_list *pndevs; struct phonet_device *pnd; int dev_idx = 0, dev_start_idx = cb->args[0]; int addr_idx = 0, addr_start_idx = cb->args[1]; - spin_lock_bh(&pndevs.lock); - list_for_each_entry(pnd, &pndevs.list, list) { + pndevs = phonet_device_list(sock_net(skb->sk)); + spin_lock_bh(&pndevs->lock); + list_for_each_entry(pnd, &pndevs->list, list) { u8 addr; - if (!net_eq(dev_net(pnd->netdev), net)) - continue; if (dev_idx > dev_start_idx) addr_start_idx = 0; if (dev_idx++ < dev_start_idx) @@ -153,7 +152,7 @@ static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb) } out: - spin_unlock_bh(&pndevs.lock); + spin_unlock_bh(&pndevs->lock); cb->args[0] = dev_idx; cb->args[1] = addr_idx; -- GitLab From cbec6605cf0fd5080f03eb787c95c1ecd660421f Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 26 Jan 2009 21:10:08 -0800 Subject: [PATCH 0470/4982] pppol2tp: stop using proc internals PDE_NET usage in driver code is a sign and, indeed, switching to seq_open_net/seq_release_net saves code and fixes bogus things, like user triggerabble BUG_ON(!net) after maybe_get_net, and NULLifying ->private. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- drivers/net/pppol2tp.c | 48 +++++------------------------------------- 1 file changed, 5 insertions(+), 43 deletions(-) diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index 056e22a784b..15f4a43a689 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c @@ -2371,7 +2371,7 @@ end: #include struct pppol2tp_seq_data { - struct net *seq_net; /* net of inode */ + struct seq_net_private p; struct pppol2tp_tunnel *tunnel; /* current tunnel */ struct pppol2tp_session *session; /* NULL means get first session in tunnel */ }; @@ -2436,7 +2436,7 @@ static void *pppol2tp_seq_start(struct seq_file *m, loff_t *offs) BUG_ON(m->private == NULL); pd = m->private; - pn = pppol2tp_pernet(pd->seq_net); + pn = pppol2tp_pernet(seq_file_net(m)); if (pd->tunnel == NULL) { if (!list_empty(&pn->pppol2tp_tunnel_list)) @@ -2558,46 +2558,8 @@ static const struct seq_operations pppol2tp_seq_ops = { */ static int pppol2tp_proc_open(struct inode *inode, struct file *file) { - struct seq_file *m; - struct pppol2tp_seq_data *pd; - struct net *net; - int ret = 0; - - ret = seq_open(file, &pppol2tp_seq_ops); - if (ret < 0) - goto out; - - m = file->private_data; - - /* Allocate and fill our proc_data for access later */ - ret = -ENOMEM; - m->private = kzalloc(sizeof(*pd), GFP_KERNEL); - if (m->private == NULL) - goto out; - - pd = m->private; - net = maybe_get_net(PDE_NET(PDE(inode))); - BUG_ON(!net); - pd->seq_net = net; - return 0; - -out: - return ret; -} - -/* Called when /proc file access completes. - */ -static int pppol2tp_proc_release(struct inode *inode, struct file *file) -{ - struct seq_file *m = (struct seq_file *)file->private_data; - struct pppol2tp_seq_data *pd = m->private; - - put_net(pd->seq_net); - - kfree(m->private); - m->private = NULL; - - return seq_release(inode, file); + return seq_open_net(inode, file, &pppol2tp_seq_ops, + sizeof(struct pppol2tp_seq_data)); } static const struct file_operations pppol2tp_proc_fops = { @@ -2605,7 +2567,7 @@ static const struct file_operations pppol2tp_proc_fops = { .open = pppol2tp_proc_open, .read = seq_read, .llseek = seq_lseek, - .release = pppol2tp_proc_release, + .release = seq_release_net, }; #endif /* CONFIG_PROC_FS */ -- GitLab From 3617aa485c7394e20fdaf356b1b78516fcaaa0d1 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 26 Jan 2009 21:11:02 -0800 Subject: [PATCH 0471/4982] net: pppoe - stop using proc internals Alexey Dobriyan pointed that using PDE_NET outside the proc code is plain bogus (thanks Alexey!). Fix it. Signed-off-by: Cyrill Gorcunov Signed-off-by: David S. Miller --- drivers/net/pppoe.c | 34 ++++++---------------------------- 1 file changed, 6 insertions(+), 28 deletions(-) diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 798b8cf5f9a..074803a78fc 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -1040,7 +1040,7 @@ out: static void *pppoe_seq_start(struct seq_file *seq, loff_t *pos) __acquires(pn->hash_lock) { - struct pppoe_net *pn = pppoe_pernet(seq->private); + struct pppoe_net *pn = pppoe_pernet(seq_file_net(seq)); loff_t l = *pos; read_lock_bh(&pn->hash_lock); @@ -1049,7 +1049,7 @@ static void *pppoe_seq_start(struct seq_file *seq, loff_t *pos) static void *pppoe_seq_next(struct seq_file *seq, void *v, loff_t *pos) { - struct pppoe_net *pn = pppoe_pernet(seq->private); + struct pppoe_net *pn = pppoe_pernet(seq_file_net(seq)); struct pppox_sock *po; ++*pos; @@ -1077,7 +1077,7 @@ out: static void pppoe_seq_stop(struct seq_file *seq, void *v) __releases(pn->hash_lock) { - struct pppoe_net *pn = pppoe_pernet(seq->private); + struct pppoe_net *pn = pppoe_pernet(seq_file_net(seq)); read_unlock_bh(&pn->hash_lock); } @@ -1090,30 +1090,8 @@ static const struct seq_operations pppoe_seq_ops = { static int pppoe_seq_open(struct inode *inode, struct file *file) { - struct seq_file *m; - struct net *net; - int err; - - err = seq_open(file, &pppoe_seq_ops); - if (err) - return err; - - m = file->private_data; - net = maybe_get_net(PDE_NET(PDE(inode))); - BUG_ON(!net); - m->private = net; - - return err; -} - -static int pppoe_seq_release(struct inode *inode, struct file *file) -{ - struct seq_file *m; - - m = file->private_data; - put_net((struct net*)m->private); - - return seq_release(inode, file); + return seq_open_net(inode, file, &pppoe_seq_ops, + sizeof(struct seq_net_private)); } static const struct file_operations pppoe_seq_fops = { @@ -1121,7 +1099,7 @@ static const struct file_operations pppoe_seq_fops = { .open = pppoe_seq_open, .read = seq_read, .llseek = seq_lseek, - .release = pppoe_seq_release, + .release = seq_release_net, }; #endif /* CONFIG_PROC_FS */ -- GitLab From db1d7bf70f42124f73675fca62fe32f3ab1111b4 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Mon, 26 Jan 2009 21:12:58 -0800 Subject: [PATCH 0472/4982] net: struct device - replace bus_id with dev_name(), dev_set_name() Signed-off-by: Kay Sievers Acked-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- drivers/net/arm/ks8695net.c | 2 +- drivers/net/au1000_eth.c | 8 ++++---- drivers/net/bfin_mac.c | 12 ++++++------ drivers/net/bmac.c | 2 +- drivers/net/cpmac.c | 2 +- drivers/net/declance.c | 6 +++--- drivers/net/depca.c | 6 +++--- drivers/net/ehea/ehea_main.c | 2 +- drivers/net/jazzsonic.c | 6 ++++-- drivers/net/macb.c | 10 +++++----- drivers/net/macsonic.c | 15 ++++++++------- drivers/net/mv643xx_eth.c | 2 +- drivers/net/sb1250-mac.c | 10 +++++----- drivers/net/smc911x.c | 2 +- drivers/net/smc91x.c | 2 +- drivers/net/smsc911x.c | 7 ++++--- drivers/net/smsc9420.c | 4 ++-- drivers/net/tc35815.c | 4 ++-- drivers/net/xtsonic.c | 2 +- 19 files changed, 54 insertions(+), 50 deletions(-) diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c index 1cf2f949c0b..b39210cf4fb 100644 --- a/drivers/net/arm/ks8695net.c +++ b/drivers/net/arm/ks8695net.c @@ -1059,7 +1059,7 @@ ks8695_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info) { strlcpy(info->driver, MODULENAME, sizeof(info->driver)); strlcpy(info->version, MODULEVERSION, sizeof(info->version)); - strlcpy(info->bus_info, ndev->dev.parent->bus_id, + strlcpy(info->bus_info, dev_name(ndev->dev.parent), sizeof(info->bus_info)); } diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index 6d76ccb8e29..4274e4ac963 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -458,8 +458,8 @@ static int mii_probe (struct net_device *dev) /* now we are supposed to have a proper phydev, to attach to... */ BUG_ON(phydev->attached_dev); - phydev = phy_connect(dev, phydev->dev.bus_id, &au1000_adjust_link, 0, - PHY_INTERFACE_MODE_MII); + phydev = phy_connect(dev, dev_name(&phydev->dev), &au1000_adjust_link, + 0, PHY_INTERFACE_MODE_MII); if (IS_ERR(phydev)) { printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); @@ -484,8 +484,8 @@ static int mii_probe (struct net_device *dev) aup->phy_dev = phydev; printk(KERN_INFO "%s: attached PHY driver [%s] " - "(mii_bus:phy_addr=%s, irq=%d)\n", - dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq); + "(mii_bus:phy_addr=%s, irq=%d)\n", dev->name, + phydev->drv->name, dev_name(&phydev->dev), phydev->irq); return 0; } diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 78e31aa861e..9afe8092dfc 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -415,11 +415,11 @@ static int mii_probe(struct net_device *dev) } #if defined(CONFIG_BFIN_MAC_RMII) - phydev = phy_connect(dev, phydev->dev.bus_id, &bfin_mac_adjust_link, 0, - PHY_INTERFACE_MODE_RMII); + phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link, + 0, PHY_INTERFACE_MODE_RMII); #else - phydev = phy_connect(dev, phydev->dev.bus_id, &bfin_mac_adjust_link, 0, - PHY_INTERFACE_MODE_MII); + phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link, + 0, PHY_INTERFACE_MODE_MII); #endif if (IS_ERR(phydev)) { @@ -447,7 +447,7 @@ static int mii_probe(struct net_device *dev) printk(KERN_INFO "%s: attached PHY driver [%s] " "(mii_bus:phy_addr=%s, irq=%d, mdc_clk=%dHz(mdc_div=%d)" "@sclk=%dMHz)\n", - DRV_NAME, phydev->drv->name, phydev->dev.bus_id, phydev->irq, + DRV_NAME, phydev->drv->name, dev_name(&phydev->dev), phydev->irq, MDC_CLK, mdc_div, sclk/1000000); return 0; @@ -488,7 +488,7 @@ static void bfin_mac_ethtool_getdrvinfo(struct net_device *dev, strcpy(info->driver, DRV_NAME); strcpy(info->version, DRV_VERSION); strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, dev->dev.bus_id); + strcpy(info->bus_info, dev_name(&dev->dev)); } static struct ethtool_ops bfin_mac_ethtool_ops = { diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index 8a546a33d58..1ab58375d06 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c @@ -1240,7 +1240,7 @@ static void bmac_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *inf { struct bmac_data *bp = netdev_priv(dev); strcpy(info->driver, "bmac"); - strcpy(info->bus_info, bp->mdev->ofdev.dev.bus_id); + strcpy(info->bus_info, dev_name(&bp->mdev->ofdev.dev)); } static const struct ethtool_ops bmac_ethtool_ops = { diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index 4dad04e91f6..3f476c7c073 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -1161,7 +1161,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev) priv->msg_enable = netif_msg_init(debug_level, 0xff); memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr)); - priv->phy = phy_connect(dev, cpmac_mii->phy_map[phy_id]->dev.bus_id, + priv->phy = phy_connect(dev, dev_name(&cpmac_mii->phy_map[phy_id]->dev), &cpmac_adjust_link, 0, PHY_INTERFACE_MODE_MII); if (IS_ERR(priv->phy)) { if (netif_msg_drv(priv)) diff --git a/drivers/net/declance.c b/drivers/net/declance.c index 7ce3053530f..861c867fca8 100644 --- a/drivers/net/declance.c +++ b/drivers/net/declance.c @@ -1027,7 +1027,7 @@ static int __init dec_lance_probe(struct device *bdev, const int type) printk(version); if (bdev) - snprintf(name, sizeof(name), "%s", bdev->bus_id); + snprintf(name, sizeof(name), "%s", dev_name(bdev)); else { i = 0; dev = root_lance_dev; @@ -1105,10 +1105,10 @@ static int __init dec_lance_probe(struct device *bdev, const int type) start = to_tc_dev(bdev)->resource.start; len = to_tc_dev(bdev)->resource.end - start + 1; - if (!request_mem_region(start, len, bdev->bus_id)) { + if (!request_mem_region(start, len, dev_name(bdev))) { printk(KERN_ERR "%s: Unable to reserve MMIO resource\n", - bdev->bus_id); + dev_name(bdev)); ret = -EBUSY; goto err_out_dev; } diff --git a/drivers/net/depca.c b/drivers/net/depca.c index e4cef491dc7..55625dbbae5 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -606,8 +606,8 @@ static int __init depca_hw_init (struct net_device *dev, struct device *device) if (!mem_start || lp->adapter < DEPCA || lp->adapter >=unknown) return -ENXIO; - printk ("%s: %s at 0x%04lx", - device->bus_id, depca_signature[lp->adapter], ioaddr); + printk("%s: %s at 0x%04lx", + dev_name(device), depca_signature[lp->adapter], ioaddr); switch (lp->depca_bus) { #ifdef CONFIG_MCA @@ -669,7 +669,7 @@ static int __init depca_hw_init (struct net_device *dev, struct device *device) spin_lock_init(&lp->lock); sprintf(lp->adapter_name, "%s (%s)", - depca_signature[lp->adapter], device->bus_id); + depca_signature[lp->adapter], dev_name(device)); status = -EBUSY; /* Initialisation Block */ diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 19fccca74ce..489fdb90f76 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -3033,7 +3033,7 @@ static struct device *ehea_register_port(struct ehea_port *port, port->ofdev.dev.parent = &port->adapter->ofdev->dev; port->ofdev.dev.bus = &ibmebus_bus_type; - sprintf(port->ofdev.dev.bus_id, "port%d", port_name_cnt++); + dev_set_name(&port->ofdev.dev, "port%d", port_name_cnt++); port->ofdev.dev.release = logical_port_release; ret = of_device_register(&port->ofdev); diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c index 334ff9e12cd..14248cfc3df 100644 --- a/drivers/net/jazzsonic.c +++ b/drivers/net/jazzsonic.c @@ -131,7 +131,8 @@ static int __init sonic_probe1(struct net_device *dev) if (sonic_debug && version_printed++ == 0) printk(version); - printk(KERN_INFO "%s: Sonic ethernet found at 0x%08lx, ", lp->device->bus_id, dev->base_addr); + printk(KERN_INFO "%s: Sonic ethernet found at 0x%08lx, ", + dev_name(lp->device), dev->base_addr); /* * Put the sonic into software reset, then @@ -156,7 +157,8 @@ static int __init sonic_probe1(struct net_device *dev) if ((lp->descriptors = dma_alloc_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode), &lp->descriptors_laddr, GFP_KERNEL)) == NULL) { - printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", lp->device->bus_id); + printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", + dev_name(lp->device)); goto out; } diff --git a/drivers/net/macb.c b/drivers/net/macb.c index dc33d51213d..872c1bdf42b 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -211,10 +211,10 @@ static int macb_mii_probe(struct net_device *dev) /* attach the mac to the phy */ if (pdata && pdata->is_rmii) { - phydev = phy_connect(dev, phydev->dev.bus_id, + phydev = phy_connect(dev, dev_name(&phydev->dev), &macb_handle_link_change, 0, PHY_INTERFACE_MODE_RMII); } else { - phydev = phy_connect(dev, phydev->dev.bus_id, + phydev = phy_connect(dev, dev_name(&phydev->dev), &macb_handle_link_change, 0, PHY_INTERFACE_MODE_MII); } @@ -1077,7 +1077,7 @@ static void macb_get_drvinfo(struct net_device *dev, strcpy(info->driver, bp->pdev->dev.driver->name); strcpy(info->version, "$Revision: 1.14 $"); - strcpy(info->bus_info, bp->pdev->dev.bus_id); + strcpy(info->bus_info, dev_name(&bp->pdev->dev)); } static struct ethtool_ops macb_ethtool_ops = { @@ -1234,8 +1234,8 @@ static int __init macb_probe(struct platform_device *pdev) phydev = bp->phy_dev; printk(KERN_INFO "%s: attached PHY driver [%s] " - "(mii_bus:phy_addr=%s, irq=%d)\n", - dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq); + "(mii_bus:phy_addr=%s, irq=%d)\n", dev->name, + phydev->drv->name, dev_name(&phydev->dev), phydev->irq); return 0; diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c index 205bb05c25d..527166e35d5 100644 --- a/drivers/net/macsonic.c +++ b/drivers/net/macsonic.c @@ -176,7 +176,8 @@ static int __init macsonic_init(struct net_device *dev) if ((lp->descriptors = dma_alloc_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode), &lp->descriptors_laddr, GFP_KERNEL)) == NULL) { - printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", lp->device->bus_id); + printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", + dev_name(lp->device)); return -ENOMEM; } @@ -337,7 +338,7 @@ static int __init mac_onboard_sonic_probe(struct net_device *dev) sonic_version_printed = 1; } printk(KERN_INFO "%s: onboard / comm-slot SONIC at 0x%08lx\n", - lp->device->bus_id, dev->base_addr); + dev_name(lp->device), dev->base_addr); /* The PowerBook's SONIC is 16 bit always. */ if (macintosh_config->ident == MAC_MODEL_PB520) { @@ -370,10 +371,10 @@ static int __init mac_onboard_sonic_probe(struct net_device *dev) } printk(KERN_INFO "%s: revision 0x%04x, using %d bit DMA and register offset %d\n", - lp->device->bus_id, sr, lp->dma_bitmode?32:16, lp->reg_offset); + dev_name(lp->device), sr, lp->dma_bitmode?32:16, lp->reg_offset); #if 0 /* This is sometimes useful to find out how MacOS configured the card. */ - printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", lp->device->bus_id, + printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", dev_name(lp->device), SONIC_READ(SONIC_DCR) & 0xffff, SONIC_READ(SONIC_DCR2) & 0xffff); #endif @@ -525,12 +526,12 @@ static int __init mac_nubus_sonic_probe(struct net_device *dev) sonic_version_printed = 1; } printk(KERN_INFO "%s: %s in slot %X\n", - lp->device->bus_id, ndev->board->name, ndev->board->slot); + dev_name(lp->device), ndev->board->name, ndev->board->slot); printk(KERN_INFO "%s: revision 0x%04x, using %d bit DMA and register offset %d\n", - lp->device->bus_id, SONIC_READ(SONIC_SR), dma_bitmode?32:16, reg_offset); + dev_name(lp->device), SONIC_READ(SONIC_SR), dma_bitmode?32:16, reg_offset); #if 0 /* This is sometimes useful to find out how MacOS configured the card. */ - printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", lp->device->bus_id, + printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", dev_name(lp->device), SONIC_READ(SONIC_DCR) & 0xffff, SONIC_READ(SONIC_DCR2) & 0xffff); #endif diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 5f31bbb614a..8fab31f631a 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -2589,7 +2589,7 @@ static void phy_init(struct mv643xx_eth_private *mp, int speed, int duplex) phy_reset(mp); - phy_attach(mp->dev, phy->dev.bus_id, 0, PHY_INTERFACE_MODE_GMII); + phy_attach(mp->dev, dev_name(&phy->dev), 0, PHY_INTERFACE_MODE_GMII); if (speed == 0) { phy->autoneg = AUTONEG_ENABLE; diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index 3e11c1d6d79..88dd2e09832 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -2478,7 +2478,7 @@ static int sbmac_mii_probe(struct net_device *dev) return -ENXIO; } - phy_dev = phy_connect(dev, phy_dev->dev.bus_id, &sbmac_mii_poll, 0, + phy_dev = phy_connect(dev, dev_name(&phy_dev->dev), &sbmac_mii_poll, 0, PHY_INTERFACE_MODE_GMII); if (IS_ERR(phy_dev)) { printk(KERN_ERR "%s: could not attach to PHY\n", dev->name); @@ -2500,7 +2500,7 @@ static int sbmac_mii_probe(struct net_device *dev) pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", dev->name, phy_dev->drv->name, - phy_dev->dev.bus_id, phy_dev->irq); + dev_name(&phy_dev->dev), phy_dev->irq); sc->phy_dev = phy_dev; @@ -2697,7 +2697,7 @@ static int __init sbmac_probe(struct platform_device *pldev) sbm_base = ioremap_nocache(res->start, res->end - res->start + 1); if (!sbm_base) { printk(KERN_ERR "%s: unable to map device registers\n", - pldev->dev.bus_id); + dev_name(&pldev->dev)); err = -ENOMEM; goto out_out; } @@ -2708,7 +2708,7 @@ static int __init sbmac_probe(struct platform_device *pldev) * If we find a zero, skip this MAC. */ sbmac_orig_hwaddr = __raw_readq(sbm_base + R_MAC_ETHERNET_ADDR); - pr_debug("%s: %sconfiguring MAC at 0x%08Lx\n", pldev->dev.bus_id, + pr_debug("%s: %sconfiguring MAC at 0x%08Lx\n", dev_name(&pldev->dev), sbmac_orig_hwaddr ? "" : "not ", (long long)res->start); if (sbmac_orig_hwaddr == 0) { err = 0; @@ -2721,7 +2721,7 @@ static int __init sbmac_probe(struct platform_device *pldev) dev = alloc_etherdev(sizeof(struct sbmac_softc)); if (!dev) { printk(KERN_ERR "%s: unable to allocate etherdev\n", - pldev->dev.bus_id); + dev_name(&pldev->dev)); err = -ENOMEM; goto out_unmap; } diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index bf3aa2a1eff..211213c6ab5 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -1545,7 +1545,7 @@ smc911x_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { strncpy(info->driver, CARDNAME, sizeof(info->driver)); strncpy(info->version, version, sizeof(info->version)); - strncpy(info->bus_info, dev->dev.parent->bus_id, sizeof(info->bus_info)); + strncpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info)); } static int smc911x_ethtool_nwayreset(struct net_device *dev) diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index 508e8da2f65..d1484060395 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -1614,7 +1614,7 @@ smc_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { strncpy(info->driver, CARDNAME, sizeof(info->driver)); strncpy(info->version, version, sizeof(info->version)); - strncpy(info->bus_info, dev->dev.parent->bus_id, sizeof(info->bus_info)); + strncpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info)); } static int smc_ethtool_nwayreset(struct net_device *dev) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index d271ae39c6f..a4a76f19451 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -769,7 +769,7 @@ static int smsc911x_mii_probe(struct net_device *dev) return -ENODEV; } - phydev = phy_connect(dev, phydev->dev.bus_id, + phydev = phy_connect(dev, dev_name(&phydev->dev), &smsc911x_phy_adjust_link, 0, pdata->config.phy_interface); if (IS_ERR(phydev)) { @@ -778,7 +778,8 @@ static int smsc911x_mii_probe(struct net_device *dev) } pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", - dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq); + dev->name, phydev->drv->name, + dev_name(&phydev->dev), phydev->irq); /* mask with MAC supported features */ phydev->supported &= (PHY_BASIC_FEATURES | SUPPORTED_Pause | @@ -1545,7 +1546,7 @@ static void smsc911x_ethtool_getdrvinfo(struct net_device *dev, { strlcpy(info->driver, SMSC_CHIPNAME, sizeof(info->driver)); strlcpy(info->version, SMSC_DRV_VERSION, sizeof(info->version)); - strlcpy(info->bus_info, dev->dev.parent->bus_id, + strlcpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info)); } diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c index 79f4c228b03..ce4e2e864bc 100644 --- a/drivers/net/smsc9420.c +++ b/drivers/net/smsc9420.c @@ -1156,7 +1156,7 @@ static int smsc9420_mii_probe(struct net_device *dev) smsc_info(PROBE, "PHY addr %d, phy_id 0x%08X", phydev->addr, phydev->phy_id); - phydev = phy_connect(dev, phydev->dev.bus_id, + phydev = phy_connect(dev, dev_name(&phydev->dev), &smsc9420_phy_adjust_link, 0, PHY_INTERFACE_MODE_MII); if (IS_ERR(phydev)) { @@ -1165,7 +1165,7 @@ static int smsc9420_mii_probe(struct net_device *dev) } pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", - dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq); + dev->name, phydev->drv->name, dev_name(&phydev->dev), phydev->irq); /* mask with MAC supported features */ phydev->supported &= (PHY_BASIC_FEATURES | SUPPORTED_Pause | diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index f42c67e93bf..b52a1c088f3 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -725,7 +725,7 @@ static int tc_mii_probe(struct net_device *dev) } /* attach the mac to the phy */ - phydev = phy_connect(dev, phydev->dev.bus_id, + phydev = phy_connect(dev, dev_name(&phydev->dev), &tc_handle_link_change, 0, lp->chiptype == TC35815_TX4939 ? PHY_INTERFACE_MODE_RMII : PHY_INTERFACE_MODE_MII); @@ -735,7 +735,7 @@ static int tc_mii_probe(struct net_device *dev) } printk(KERN_INFO "%s: attached PHY driver [%s] " "(mii_bus:phy_addr=%s, id=%x)\n", - dev->name, phydev->drv->name, phydev->dev.bus_id, + dev->name, phydev->drv->name, dev_name(&phydev->dev), phydev->phy_id); /* mask with MAC supported features */ diff --git a/drivers/net/xtsonic.c b/drivers/net/xtsonic.c index 03a3f34e903..a12a7211c98 100644 --- a/drivers/net/xtsonic.c +++ b/drivers/net/xtsonic.c @@ -183,7 +183,7 @@ static int __init sonic_probe1(struct net_device *dev) if (lp->descriptors == NULL) { printk(KERN_ERR "%s: couldn't alloc DMA memory for " - " descriptors.\n", lp->device->bus_id); + " descriptors.\n", dev_name(lp->device)); goto out; } -- GitLab From 01e2ffac7dbc0700c972eb38619870034a0b3418 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 27 Jan 2009 16:20:04 +1100 Subject: [PATCH 0473/4982] solos: Handle attribute show/store in kernel more sanely There are still a _lot_ of attributes, but for at least the basic ones we want to be able to get/set them from the kernel. Especially the ones we want to inform the ATM core about (link state, speed). Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 187 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 5179dbf9bd1..d9262a428dd 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -38,6 +38,8 @@ #include #include #include +#include +#include #define VERSION "0.07" #define PTAG "solos-pci" @@ -91,11 +93,23 @@ struct solos_card { spinlock_t tx_lock; spinlock_t tx_queue_lock; spinlock_t cli_queue_lock; + spinlock_t param_queue_lock; + struct list_head param_queue; struct sk_buff_head tx_queue[4]; struct sk_buff_head cli_queue[4]; + wait_queue_head_t param_wq; wait_queue_head_t fw_wq; }; + +struct solos_param { + struct list_head list; + pid_t pid; + int port; + struct sk_buff *response; + wait_queue_head_t wq; +}; + #define SOLOS_CHAN(atmdev) ((int)(unsigned long)(atmdev)->phy_data) MODULE_AUTHOR("Traverse Technologies "); @@ -131,6 +145,168 @@ static inline void solos_pop(struct atm_vcc *vcc, struct sk_buff *skb) dev_kfree_skb_any(skb); } +static ssize_t solos_param_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct atm_dev *atmdev = container_of(dev, struct atm_dev, class_dev); + struct solos_card *card = atmdev->dev_data; + struct solos_param prm; + struct sk_buff *skb; + struct pkt_hdr *header; + int buflen; + + buflen = strlen(attr->attr.name) + 10; + + skb = alloc_skb(buflen, GFP_KERNEL); + if (!skb) { + dev_warn(&card->dev->dev, "Failed to allocate sk_buff in solos_param_show()\n"); + return -ENOMEM; + } + + header = (void *)skb_put(skb, sizeof(*header)); + + buflen = snprintf((void *)&header[1], buflen - 1, + "L%05d\n%s\n", current->pid, attr->attr.name); + skb_put(skb, buflen); + + header->size = cpu_to_le16(buflen); + header->vpi = cpu_to_le16(0); + header->vci = cpu_to_le16(0); + header->type = cpu_to_le16(PKT_COMMAND); + + prm.pid = current->pid; + prm.response = NULL; + prm.port = SOLOS_CHAN(atmdev); + + spin_lock_irq(&card->param_queue_lock); + list_add(&prm.list, &card->param_queue); + spin_unlock_irq(&card->param_queue_lock); + + fpga_queue(card, prm.port, skb, NULL); + + wait_event_timeout(card->param_wq, prm.response, 5 * HZ); + + spin_lock_irq(&card->param_queue_lock); + list_del(&prm.list); + spin_unlock_irq(&card->param_queue_lock); + + if (!prm.response) + return -EIO; + + buflen = prm.response->len; + memcpy(buf, prm.response->data, buflen); + kfree_skb(prm.response); + + return buflen; +} + +static ssize_t solos_param_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct atm_dev *atmdev = container_of(dev, struct atm_dev, class_dev); + struct solos_card *card = atmdev->dev_data; + struct solos_param prm; + struct sk_buff *skb; + struct pkt_hdr *header; + int buflen; + ssize_t ret; + + buflen = strlen(attr->attr.name) + 11 + count; + + skb = alloc_skb(buflen, GFP_KERNEL); + if (!skb) { + dev_warn(&card->dev->dev, "Failed to allocate sk_buff in solos_param_store()\n"); + return -ENOMEM; + } + + header = (void *)skb_put(skb, sizeof(*header)); + + buflen = snprintf((void *)&header[1], buflen - 1, + "L%05d\n%s\n%s\n", current->pid, attr->attr.name, buf); + + skb_put(skb, buflen); + header->size = cpu_to_le16(buflen); + header->vpi = cpu_to_le16(0); + header->vci = cpu_to_le16(0); + header->type = cpu_to_le16(PKT_COMMAND); + + prm.pid = current->pid; + prm.response = NULL; + prm.port = SOLOS_CHAN(atmdev); + + spin_lock_irq(&card->param_queue_lock); + list_add(&prm.list, &card->param_queue); + spin_unlock_irq(&card->param_queue_lock); + + fpga_queue(card, prm.port, skb, NULL); + + wait_event_timeout(card->param_wq, prm.response, 5 * HZ); + + spin_lock_irq(&card->param_queue_lock); + list_del(&prm.list); + spin_unlock_irq(&card->param_queue_lock); + + skb = prm.response; + + if (!skb) + return -EIO; + + buflen = skb->len; + + /* Sometimes it has a newline, sometimes it doesn't. */ + if (skb->data[buflen - 1] == '\n') + buflen--; + + if (buflen == 2 && !strncmp(skb->data, "OK", 2)) + ret = count; + else if (buflen == 5 && !strncmp(skb->data, "ERROR", 5)) + ret = -EIO; + else { + /* We know we have enough space allocated for this; we allocated + it ourselves */ + skb->data[buflen] = 0; + + dev_warn(&card->dev->dev, "Unexpected parameter response: '%s'\n", + skb->data); + ret = -EIO; + } + kfree_skb(skb); + + return ret; +} + +static int process_command(struct solos_card *card, int port, struct sk_buff *skb) +{ + struct solos_param *prm; + unsigned long flags; + int cmdpid; + int found = 0; + + if (skb->len < 7) + return 0; + + if (skb->data[0] != 'L' || !isdigit(skb->data[1]) || + !isdigit(skb->data[2]) || !isdigit(skb->data[3]) || + !isdigit(skb->data[4]) || !isdigit(skb->data[5]) || + skb->data[6] != '\n') + return 0; + + cmdpid = simple_strtol(&skb->data[1], NULL, 10); + + spin_lock_irqsave(&card->param_queue_lock, flags); + list_for_each_entry(prm, &card->param_queue, list) { + if (prm->port == port && prm->pid == cmdpid) { + prm->response = skb; + skb_pull(skb, 7); + wake_up(&card->param_wq); + found = 1; + break; + } + } + spin_unlock_irqrestore(&card->param_queue_lock, flags); + return found; +} + static ssize_t console_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -195,6 +371,8 @@ static ssize_t console_store(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR(console, 0644, console_show, console_store); +static DEVICE_ATTR(OperationalMode, 0444, solos_param_show, NULL); +static DEVICE_ATTR(AutoStart, 0644, solos_param_show, solos_param_store); static int flash_upgrade(struct solos_card *card, int chip) { @@ -351,6 +529,8 @@ void solos_bh(unsigned long card_arg) case PKT_COMMAND: default: /* FIXME: Not really, surely? */ + if (process_command(card, port, skb)) + break; spin_lock(&card->cli_queue_lock); if (skb_queue_len(&card->cli_queue[port]) > 10) { if (net_ratelimit()) @@ -671,6 +851,7 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) card->dev = dev; init_waitqueue_head(&card->fw_wq); + init_waitqueue_head(&card->param_wq); err = pci_enable_device(dev); if (err) { @@ -722,6 +903,8 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) spin_lock_init(&card->tx_lock); spin_lock_init(&card->tx_queue_lock); spin_lock_init(&card->cli_queue_lock); + spin_lock_init(&card->param_queue_lock); + INIT_LIST_HEAD(&card->param_queue); /* // Set Loopback mode @@ -804,6 +987,10 @@ static int atm_init(struct solos_card *card) } if (device_create_file(&card->atmdev[i]->class_dev, &dev_attr_console)) dev_err(&card->dev->dev, "Could not register console for ATM device %d\n", i); + if (device_create_file(&card->atmdev[i]->class_dev, &dev_attr_OperationalMode)) + dev_err(&card->dev->dev, "Could not register opmode attr for ATM device %d\n", i); + if (device_create_file(&card->atmdev[i]->class_dev, &dev_attr_AutoStart)) + dev_err(&card->dev->dev, "Could not register autostart attr for ATM device %d\n", i); dev_info(&card->dev->dev, "Registered ATM device %d\n", card->atmdev[i]->number); -- GitLab From 22f25138c345ec46a13744c93c093ff822cd98d1 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 27 Jan 2009 14:21:37 +0900 Subject: [PATCH 0474/4982] x86: fix build breakage on voyage Impact: build fix x86_cpu_to_apicid and x86_bios_cpu_apicid aren't defined for voyage. Earlier patch forgot to conditionalize early percpu clearing. Fix it. Signed-off-by: James Bottomley Signed-off-by: Tejun Heo --- arch/x86/kernel/setup_percpu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 4caa78d7cb1..c7458ead22d 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -125,8 +125,10 @@ void __init setup_per_cpu_areas(void) } /* indicate the early static arrays will soon be gone */ +#ifdef CONFIG_X86_LOCAL_APIC early_per_cpu_ptr(x86_cpu_to_apicid) = NULL; early_per_cpu_ptr(x86_bios_cpu_apicid) = NULL; +#endif #if defined(CONFIG_X86_64) && defined(CONFIG_NUMA) early_per_cpu_ptr(x86_cpu_to_node_map) = NULL; #endif -- GitLab From cf3997f507624757f149fcc42b76fb03c151fb65 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 27 Jan 2009 14:25:05 +0900 Subject: [PATCH 0475/4982] x86: clean up indentation in setup_per_cpu_areas() Impact: cosmetic cleanup Signed-off-by: Tejun Heo --- arch/x86/kernel/setup_percpu.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index c7458ead22d..0d1e7ac439f 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -96,22 +96,25 @@ void __init setup_per_cpu_areas(void) per_cpu(cpu_number, cpu) = cpu; setup_percpu_segment(cpu); /* - * Copy data used in early init routines from the initial arrays to the - * per cpu data areas. These arrays then become expendable and the - * *_early_ptr's are zeroed indicating that the static arrays are gone. + * Copy data used in early init routines from the + * initial arrays to the per cpu data areas. These + * arrays then become expendable and the *_early_ptr's + * are zeroed indicating that the static arrays are + * gone. */ #ifdef CONFIG_X86_LOCAL_APIC per_cpu(x86_cpu_to_apicid, cpu) = - early_per_cpu_map(x86_cpu_to_apicid, cpu); + early_per_cpu_map(x86_cpu_to_apicid, cpu); per_cpu(x86_bios_cpu_apicid, cpu) = - early_per_cpu_map(x86_bios_cpu_apicid, cpu); + early_per_cpu_map(x86_bios_cpu_apicid, cpu); #endif #ifdef CONFIG_X86_64 per_cpu(irq_stack_ptr, cpu) = - per_cpu(irq_stack_union.irq_stack, cpu) + IRQ_STACK_SIZE - 64; + per_cpu(irq_stack_union.irq_stack, cpu) + + IRQ_STACK_SIZE - 64; #ifdef CONFIG_NUMA per_cpu(x86_cpu_to_node_map, cpu) = - early_per_cpu_map(x86_cpu_to_node_map, cpu); + early_per_cpu_map(x86_cpu_to_node_map, cpu); #endif #endif /* -- GitLab From a528079e01aa9cf6cddc852d5ab5cf4908974745 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 26 Jan 2009 21:32:25 -0800 Subject: [PATCH 0476/4982] smc91x: struct net_device_ops Convert the smc91x driver to use struct net_device_ops. Signed-off-by: Magnus Damm Signed-off-by: David S. Miller --- drivers/net/smc91x.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index d1484060395..fdcbaf8dfa7 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -1768,6 +1768,19 @@ static const struct ethtool_ops smc_ethtool_ops = { .set_eeprom = smc_ethtool_seteeprom, }; +static const struct net_device_ops smc_netdev_ops = { + .ndo_open = smc_open, + .ndo_stop = smc_close, + .ndo_start_xmit = smc_hard_start_xmit, + .ndo_tx_timeout = smc_timeout, + .ndo_set_multicast_list = smc_set_multicast_list, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = smc_poll_controller, +#endif +}; + /* * smc_findirq * @@ -1977,16 +1990,9 @@ static int __devinit smc_probe(struct net_device *dev, void __iomem *ioaddr, /* Fill in the fields of the device structure with ethernet values. */ ether_setup(dev); - dev->open = smc_open; - dev->stop = smc_close; - dev->hard_start_xmit = smc_hard_start_xmit; - dev->tx_timeout = smc_timeout; dev->watchdog_timeo = msecs_to_jiffies(watchdog); - dev->set_multicast_list = smc_set_multicast_list; + dev->netdev_ops = &smc_netdev_ops; dev->ethtool_ops = &smc_ethtool_ops; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = smc_poll_controller; -#endif tasklet_init(&lp->tx_task, smc_hardware_send_pkt, (unsigned long)dev); INIT_WORK(&lp->phy_configure, smc_phy_configure); -- GitLab From 1373c0fdbc5b477f5597a3ca9f2c782f15b56886 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Mon, 26 Jan 2009 21:33:16 -0800 Subject: [PATCH 0477/4982] smsc911x: leave RX_STOP interrupt permanently enabled smsc911x_set_multicast_list currently performs the only non-atomic read-modify-write of INT_EN. This patch permanently enables the RXSTOP_INT interrupt, and changes the ISR to only conditionally run the multicast filter workaround code. Signed-off-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/smsc911x.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index a4a76f19451..aaf0b4314ce 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1247,7 +1247,7 @@ static int smsc911x_open(struct net_device *dev) napi_enable(&pdata->napi); temp = smsc911x_reg_read(pdata, INT_EN); - temp |= (INT_EN_TDFA_EN_ | INT_EN_RSFL_EN_); + temp |= (INT_EN_TDFA_EN_ | INT_EN_RSFL_EN_ | INT_EN_RXSTOP_INT_EN_); smsc911x_reg_write(pdata, INT_EN, temp); spin_lock_irq(&pdata->mac_lock); @@ -1419,11 +1419,6 @@ static void smsc911x_set_multicast_list(struct net_device *dev) /* Request the hardware to stop, then perform the * update when we get an RX_STOP interrupt */ - smsc911x_reg_write(pdata, INT_STS, INT_STS_RXSTOP_INT_); - temp = smsc911x_reg_read(pdata, INT_EN); - temp |= INT_EN_RXSTOP_INT_EN_; - smsc911x_reg_write(pdata, INT_EN, temp); - temp = smsc911x_mac_read(pdata, MAC_CR); temp &= ~(MAC_CR_RXEN_); smsc911x_mac_write(pdata, MAC_CR, temp); @@ -1462,11 +1457,9 @@ static irqreturn_t smsc911x_irqhandler(int irq, void *dev_id) /* Called when there is a multicast update scheduled and * it is now safe to complete the update */ SMSC_TRACE(INTR, "RX Stop interrupt"); - temp = smsc911x_reg_read(pdata, INT_EN); - temp &= (~INT_EN_RXSTOP_INT_EN_); - smsc911x_reg_write(pdata, INT_EN, temp); smsc911x_reg_write(pdata, INT_STS, INT_STS_RXSTOP_INT_); - smsc911x_rx_multicast_update_workaround(pdata); + if (pdata->multicast_update_pending) + smsc911x_rx_multicast_update_workaround(pdata); serviced = IRQ_HANDLED; } -- GitLab From 18801be7f805b891876a6676ec7fac2e1acdec13 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 25 Dec 2008 18:17:09 +0900 Subject: [PATCH 0478/4982] sh: make gpio_get/set_value() O(1) This patch modifies the table based SuperH gpio implementation to make use of direct table lookups. With this change the functions gpio_get_value() and gpio_set_value() are O(1). Tested on Migo-R using bitbanging mmc. Performance is improved from 11 KBytes/s to 26 Kbytes/s. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/include/asm/gpio.h | 7 +++++- arch/sh/kernel/gpio.c | 48 +++++++++++++++++++++++++++++--------- 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/arch/sh/include/asm/gpio.h b/arch/sh/include/asm/gpio.h index 90673658eb1..942fefa61c7 100644 --- a/arch/sh/include/asm/gpio.h +++ b/arch/sh/include/asm/gpio.h @@ -20,7 +20,7 @@ #endif typedef unsigned short pinmux_enum_t; -typedef unsigned char pinmux_flag_t; +typedef unsigned short pinmux_flag_t; #define PINMUX_TYPE_NONE 0 #define PINMUX_TYPE_FUNCTION 1 @@ -34,6 +34,11 @@ typedef unsigned char pinmux_flag_t; #define PINMUX_FLAG_WANT_PULLUP (1 << 3) #define PINMUX_FLAG_WANT_PULLDOWN (1 << 4) +#define PINMUX_FLAG_DBIT_SHIFT 5 +#define PINMUX_FLAG_DBIT (0x1f << PINMUX_FLAG_DBIT_SHIFT) +#define PINMUX_FLAG_DREG_SHIFT 10 +#define PINMUX_FLAG_DREG (0x3f << PINMUX_FLAG_DREG_SHIFT) + struct pinmux_gpio { pinmux_enum_t enum_id; pinmux_flag_t flags; diff --git a/arch/sh/kernel/gpio.c b/arch/sh/kernel/gpio.c index d3716536103..fe92ba151b8 100644 --- a/arch/sh/kernel/gpio.c +++ b/arch/sh/kernel/gpio.c @@ -95,14 +95,13 @@ static int read_write_reg(unsigned long reg, unsigned long reg_width, return 0; } -static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio, - struct pinmux_data_reg **drp, int *bitp) +static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio) { - pinmux_enum_t enum_id = gpioc->gpios[gpio].enum_id; + struct pinmux_gpio *gpiop = &gpioc->gpios[gpio]; struct pinmux_data_reg *data_reg; int k, n; - if (!enum_in_range(enum_id, &gpioc->data)) + if (!enum_in_range(gpiop->enum_id, &gpioc->data)) return -1; k = 0; @@ -113,19 +112,38 @@ static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio, break; for (n = 0; n < data_reg->reg_width; n++) { - if (data_reg->enum_ids[n] == enum_id) { - *drp = data_reg; - *bitp = n; + if (data_reg->enum_ids[n] == gpiop->enum_id) { + gpiop->flags &= ~PINMUX_FLAG_DREG; + gpiop->flags |= (k << PINMUX_FLAG_DREG_SHIFT); + gpiop->flags &= ~PINMUX_FLAG_DBIT; + gpiop->flags |= (n << PINMUX_FLAG_DBIT_SHIFT); return 0; - } } k++; } + BUG(); + return -1; } +static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio, + struct pinmux_data_reg **drp, int *bitp) +{ + struct pinmux_gpio *gpiop = &gpioc->gpios[gpio]; + int k, n; + + if (!enum_in_range(gpiop->enum_id, &gpioc->data)) + return -1; + + k = (gpiop->flags & PINMUX_FLAG_DREG) >> PINMUX_FLAG_DREG_SHIFT; + n = (gpiop->flags & PINMUX_FLAG_DBIT) >> PINMUX_FLAG_DBIT_SHIFT; + *drp = gpioc->data_regs + k; + *bitp = n; + return 0; +} + static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id, struct pinmux_cfg_reg **crp, int *indexp, unsigned long **cntp) @@ -341,7 +359,8 @@ int __gpio_request(unsigned gpio) BUG(); } - gpioc->gpios[gpio].flags = pinmux_type; + gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE; + gpioc->gpios[gpio].flags |= pinmux_type; ret = 0; err_unlock: @@ -364,7 +383,8 @@ void gpio_free(unsigned gpio) pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE; pinmux_config_gpio(gpioc, gpio, pinmux_type, GPIO_CFG_FREE); - gpioc->gpios[gpio].flags = PINMUX_TYPE_NONE; + gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE; + gpioc->gpios[gpio].flags |= PINMUX_TYPE_NONE; spin_unlock_irqrestore(&gpio_lock, flags); } @@ -401,7 +421,8 @@ static int pinmux_direction(struct pinmux_info *gpioc, GPIO_CFG_REQ) != 0) BUG(); - gpioc->gpios[gpio].flags = new_pinmux_type; + gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE; + gpioc->gpios[gpio].flags |= new_pinmux_type; ret = 0; err_out: @@ -494,9 +515,14 @@ EXPORT_SYMBOL(gpio_set_value); int register_pinmux(struct pinmux_info *pip) { + int k; + registered_gpio = pip; pr_info("pinmux: %s handling gpio %d -> %d\n", pip->name, pip->first_gpio, pip->last_gpio); + for (k = pip->first_gpio; k <= pip->last_gpio; k++) + setup_data_reg(pip, k); + return 0; } -- GitLab From 0fc64cc0a27288e77ee8e12648d59632649371fc Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 25 Dec 2008 18:17:18 +0900 Subject: [PATCH 0479/4982] sh: lockless gpio_get_value() This patch separates the register read and write functions to allow lockless gpio_get_value(). Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/gpio.c | 126 +++++++++++++++++++++--------------------- 1 file changed, 63 insertions(+), 63 deletions(-) diff --git a/arch/sh/kernel/gpio.c b/arch/sh/kernel/gpio.c index fe92ba151b8..f8397a09491 100644 --- a/arch/sh/kernel/gpio.c +++ b/arch/sh/kernel/gpio.c @@ -46,9 +46,8 @@ static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r) return 1; } -static int read_write_reg(unsigned long reg, unsigned long reg_width, - unsigned long field_width, unsigned long in_pos, - unsigned long value, int do_write) +static int gpio_read_reg(unsigned long reg, unsigned long reg_width, + unsigned long field_width, unsigned long in_pos) { unsigned long data, mask, pos; @@ -57,10 +56,9 @@ static int read_write_reg(unsigned long reg, unsigned long reg_width, pos = reg_width - ((in_pos + 1) * field_width); #ifdef DEBUG - pr_info("%s, addr = %lx, value = %ld, pos = %ld, " + pr_info("read_reg: addr = %lx, pos = %ld, " "r_width = %ld, f_width = %ld\n", - do_write ? "write" : "read", reg, value, pos, - reg_width, field_width); + reg, pos, reg_width, field_width); #endif switch (reg_width) { @@ -75,24 +73,38 @@ static int read_write_reg(unsigned long reg, unsigned long reg_width, break; } - if (!do_write) - return (data >> pos) & mask; + return (data >> pos) & mask; +} + +static void gpio_write_reg(unsigned long reg, unsigned long reg_width, + unsigned long field_width, unsigned long in_pos, + unsigned long value) +{ + unsigned long mask, pos; + + mask = (1 << field_width) - 1; + pos = reg_width - ((in_pos + 1) * field_width); - data &= ~(mask << pos); - data |= value << pos; +#ifdef DEBUG + pr_info("write_reg addr = %lx, value = %ld, pos = %ld, " + "r_width = %ld, f_width = %ld\n", + reg, value, pos, reg_width, field_width); +#endif + + mask = ~(mask << pos); + value = value << pos; switch (reg_width) { case 8: - ctrl_outb(data, reg); + ctrl_outb((ctrl_inb(reg) & mask) | value, reg); break; case 16: - ctrl_outw(data, reg); + ctrl_outw((ctrl_inw(reg) & mask) | value, reg); break; case 32: - ctrl_outl(data, reg); + ctrl_outl((ctrl_inl(reg) & mask) | value, reg); break; } - return 0; } static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio) @@ -205,9 +217,9 @@ static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio, return -1; } -static int write_config_reg(struct pinmux_info *gpioc, - struct pinmux_cfg_reg *crp, - int index) +static void write_config_reg(struct pinmux_info *gpioc, + struct pinmux_cfg_reg *crp, + int index) { unsigned long ncomb, pos, value; @@ -215,8 +227,7 @@ static int write_config_reg(struct pinmux_info *gpioc, pos = index / ncomb; value = index % ncomb; - return read_write_reg(crp->reg, crp->reg_width, - crp->field_width, pos, value, 1); + gpio_write_reg(crp->reg, crp->reg_width, crp->field_width, pos, value); } static int check_config_reg(struct pinmux_info *gpioc, @@ -229,8 +240,8 @@ static int check_config_reg(struct pinmux_info *gpioc, pos = index / ncomb; value = index % ncomb; - if (read_write_reg(crp->reg, crp->reg_width, - crp->field_width, pos, 0, 0) == value) + if (gpio_read_reg(crp->reg, crp->reg_width, + crp->field_width, pos) == value) return 0; return -1; @@ -238,8 +249,8 @@ static int check_config_reg(struct pinmux_info *gpioc, enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE }; -int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio, - int pinmux_type, int cfg_mode) +static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio, + int pinmux_type, int cfg_mode) { struct pinmux_cfg_reg *cr = NULL; pinmux_enum_t enum_id; @@ -305,8 +316,7 @@ int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio, break; case GPIO_CFG_REQ: - if (write_config_reg(gpioc, cr, index) != 0) - goto out_err; + write_config_reg(gpioc, cr, index); *cntp = *cntp + 1; break; @@ -393,9 +403,12 @@ EXPORT_SYMBOL(gpio_free); static int pinmux_direction(struct pinmux_info *gpioc, unsigned gpio, int new_pinmux_type) { - int ret, pinmux_type; + int pinmux_type; + int ret = -EINVAL; + + if (!gpioc) + goto err_out; - ret = -EINVAL; pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE; switch (pinmux_type) { @@ -433,68 +446,59 @@ int gpio_direction_input(unsigned gpio) { struct pinmux_info *gpioc = gpio_controller(gpio); unsigned long flags; - int ret = -EINVAL; - - if (!gpioc) - goto err_out; + int ret; spin_lock_irqsave(&gpio_lock, flags); ret = pinmux_direction(gpioc, gpio, PINMUX_TYPE_INPUT); spin_unlock_irqrestore(&gpio_lock, flags); - err_out: + return ret; } EXPORT_SYMBOL(gpio_direction_input); -static int __gpio_get_set_value(struct pinmux_info *gpioc, - unsigned gpio, int value, - int do_write) +static void __gpio_set_value(struct pinmux_info *gpioc, + unsigned gpio, int value) { struct pinmux_data_reg *dr = NULL; int bit = 0; - if (get_data_reg(gpioc, gpio, &dr, &bit) != 0) + if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0) BUG(); else - value = read_write_reg(dr->reg, dr->reg_width, - 1, bit, !!value, do_write); - - return value; + gpio_write_reg(dr->reg, dr->reg_width, 1, bit, !!value); } int gpio_direction_output(unsigned gpio, int value) { struct pinmux_info *gpioc = gpio_controller(gpio); unsigned long flags; - int ret = -EINVAL; - - if (!gpioc) - goto err_out; + int ret; spin_lock_irqsave(&gpio_lock, flags); - __gpio_get_set_value(gpioc, gpio, value, 1); + __gpio_set_value(gpioc, gpio, value); ret = pinmux_direction(gpioc, gpio, PINMUX_TYPE_OUTPUT); spin_unlock_irqrestore(&gpio_lock, flags); - err_out: + return ret; } EXPORT_SYMBOL(gpio_direction_output); -int gpio_get_value(unsigned gpio) +static int __gpio_get_value(struct pinmux_info *gpioc, unsigned gpio) { - struct pinmux_info *gpioc = gpio_controller(gpio); - unsigned long flags; - int value = 0; + struct pinmux_data_reg *dr = NULL; + int bit = 0; - if (!gpioc) + if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0) { BUG(); - else { - spin_lock_irqsave(&gpio_lock, flags); - value = __gpio_get_set_value(gpioc, gpio, 0, 0); - spin_unlock_irqrestore(&gpio_lock, flags); + return 0; } - return value; + return gpio_read_reg(dr->reg, dr->reg_width, 1, bit); +} + +int gpio_get_value(unsigned gpio) +{ + return __gpio_get_value(gpio_controller(gpio), gpio); } EXPORT_SYMBOL(gpio_get_value); @@ -503,13 +507,9 @@ void gpio_set_value(unsigned gpio, int value) struct pinmux_info *gpioc = gpio_controller(gpio); unsigned long flags; - if (!gpioc) - BUG(); - else { - spin_lock_irqsave(&gpio_lock, flags); - __gpio_get_set_value(gpioc, gpio, value, 1); - spin_unlock_irqrestore(&gpio_lock, flags); - } + spin_lock_irqsave(&gpio_lock, flags); + __gpio_set_value(gpioc, gpio, value); + spin_unlock_irqrestore(&gpio_lock, flags); } EXPORT_SYMBOL(gpio_set_value); -- GitLab From 3292094e88ce6b76714dad8ec4b43d7c5c12ada2 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 25 Dec 2008 18:17:26 +0900 Subject: [PATCH 0480/4982] sh: lockless gpio_set_value() This patch optimizes the gpio data register handling for gpio_set_value(). Instead of using the good old spinlock-plus-read-modify-write strategy we now use a shadow register and atomic operations. This improves the bitbanging mmc performance on Migo-R from 26 Kbytes/s to 40 Kbytes/s. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/include/asm/gpio.h | 2 +- arch/sh/kernel/gpio.c | 106 ++++++++++++++++++++++++++++--------- 2 files changed, 82 insertions(+), 26 deletions(-) diff --git a/arch/sh/include/asm/gpio.h b/arch/sh/include/asm/gpio.h index 942fefa61c7..46a6d7914df 100644 --- a/arch/sh/include/asm/gpio.h +++ b/arch/sh/include/asm/gpio.h @@ -59,7 +59,7 @@ struct pinmux_cfg_reg { .enum_ids = (pinmux_enum_t [(r_width / f_width) * (1 << f_width)]) \ struct pinmux_data_reg { - unsigned long reg, reg_width; + unsigned long reg, reg_width, reg_shadow; pinmux_enum_t *enum_ids; }; diff --git a/arch/sh/kernel/gpio.c b/arch/sh/kernel/gpio.c index f8397a09491..28013567372 100644 --- a/arch/sh/kernel/gpio.c +++ b/arch/sh/kernel/gpio.c @@ -46,6 +46,62 @@ static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r) return 1; } +static unsigned long gpio_read_raw_reg(unsigned long reg, + unsigned long reg_width) +{ + switch (reg_width) { + case 8: + return ctrl_inb(reg); + case 16: + return ctrl_inw(reg); + case 32: + return ctrl_inl(reg); + } + + BUG(); + return 0; +} + +static void gpio_write_raw_reg(unsigned long reg, + unsigned long reg_width, + unsigned long data) +{ + switch (reg_width) { + case 8: + ctrl_outb(data, reg); + return; + case 16: + ctrl_outw(data, reg); + return; + case 32: + ctrl_outl(data, reg); + return; + } + + BUG(); +} + +static void gpio_write_bit(struct pinmux_data_reg *dr, + unsigned long in_pos, unsigned long value) +{ + unsigned long pos; + + pos = dr->reg_width - (in_pos + 1); + +#ifdef DEBUG + pr_info("write_bit addr = %lx, value = %ld, pos = %ld, " + "r_width = %ld\n", + dr->reg, !!value, pos, dr->reg_width); +#endif + + if (value) + set_bit(pos, &dr->reg_shadow); + else + clear_bit(pos, &dr->reg_shadow); + + gpio_write_raw_reg(dr->reg, dr->reg_width, dr->reg_shadow); +} + static int gpio_read_reg(unsigned long reg, unsigned long reg_width, unsigned long field_width, unsigned long in_pos) { @@ -61,18 +117,7 @@ static int gpio_read_reg(unsigned long reg, unsigned long reg_width, reg, pos, reg_width, field_width); #endif - switch (reg_width) { - case 8: - data = ctrl_inb(reg); - break; - case 16: - data = ctrl_inw(reg); - break; - case 32: - data = ctrl_inl(reg); - break; - } - + data = gpio_read_raw_reg(reg, reg_width); return (data >> pos) & mask; } @@ -140,6 +185,26 @@ static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio) return -1; } +static void setup_data_regs(struct pinmux_info *gpioc) +{ + struct pinmux_data_reg *drp; + int k; + + for (k = gpioc->first_gpio; k <= gpioc->last_gpio; k++) + setup_data_reg(gpioc, k); + + k = 0; + while (1) { + drp = gpioc->data_regs + k; + + if (!drp->reg_width) + break; + + drp->reg_shadow = gpio_read_raw_reg(drp->reg, drp->reg_width); + k++; + } +} + static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio, struct pinmux_data_reg **drp, int *bitp) { @@ -465,7 +530,7 @@ static void __gpio_set_value(struct pinmux_info *gpioc, if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0) BUG(); else - gpio_write_reg(dr->reg, dr->reg_width, 1, bit, !!value); + gpio_write_bit(dr, bit, value); } int gpio_direction_output(unsigned gpio, int value) @@ -474,8 +539,8 @@ int gpio_direction_output(unsigned gpio, int value) unsigned long flags; int ret; - spin_lock_irqsave(&gpio_lock, flags); __gpio_set_value(gpioc, gpio, value); + spin_lock_irqsave(&gpio_lock, flags); ret = pinmux_direction(gpioc, gpio, PINMUX_TYPE_OUTPUT); spin_unlock_irqrestore(&gpio_lock, flags); @@ -504,25 +569,16 @@ EXPORT_SYMBOL(gpio_get_value); void gpio_set_value(unsigned gpio, int value) { - struct pinmux_info *gpioc = gpio_controller(gpio); - unsigned long flags; - - spin_lock_irqsave(&gpio_lock, flags); - __gpio_set_value(gpioc, gpio, value); - spin_unlock_irqrestore(&gpio_lock, flags); + __gpio_set_value(gpio_controller(gpio), gpio, value); } EXPORT_SYMBOL(gpio_set_value); int register_pinmux(struct pinmux_info *pip) { - int k; - registered_gpio = pip; + setup_data_regs(pip); pr_info("pinmux: %s handling gpio %d -> %d\n", pip->name, pip->first_gpio, pip->last_gpio); - for (k = pip->first_gpio; k <= pip->last_gpio; k++) - setup_data_reg(pip, k); - return 0; } -- GitLab From 69edbba0021a48fe034849501513930f6175cb5d Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 25 Dec 2008 18:17:34 +0900 Subject: [PATCH 0481/4982] sh: use gpiolib This patch updates the SuperH gpio code to make use of gpiolib. The gpiolib callbacks get() and set() are lockless, but we use our own spinlock for the other operations to make sure hardware register bitfield accesses stay atomic. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 7 +++ arch/sh/boards/Kconfig | 4 +- arch/sh/include/asm/gpio.h | 61 ++++++++++++--------- arch/sh/kernel/Makefile_32 | 2 +- arch/sh/kernel/Makefile_64 | 2 +- arch/sh/kernel/gpio.c | 106 ++++++++++++++++++------------------- drivers/serial/sh-sci.h | 2 +- 7 files changed, 100 insertions(+), 84 deletions(-) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index ebabe518e72..3a2be227894 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -126,6 +126,13 @@ config ARCH_HAS_ILOG2_U64 config ARCH_NO_VIRT_TO_BUS def_bool y +config ARCH_WANT_OPTIONAL_GPIOLIB + def_bool y + depends on !ARCH_REQUIRE_GPIOLIB + +config ARCH_REQUIRE_GPIOLIB + def_bool n + config IO_TRAPPED bool diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig index 861914747e4..802d5c475a7 100644 --- a/arch/sh/boards/Kconfig +++ b/arch/sh/boards/Kconfig @@ -165,7 +165,7 @@ config SH_SH7785LCR_29BIT_PHYSMAPS config SH_MIGOR bool "Migo-R" depends on CPU_SUBTYPE_SH7722 - select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB help Select Migo-R if configuring for the SH7722 Migo-R platform by Renesas System Solutions Asia Pte. Ltd. @@ -173,7 +173,7 @@ config SH_MIGOR config SH_AP325RXA bool "AP-325RXA" depends on CPU_SUBTYPE_SH7723 - select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB help Renesas "AP-325RXA" support. Compatible with ALGO SYSTEM CO.,LTD. "AP-320A" diff --git a/arch/sh/include/asm/gpio.h b/arch/sh/include/asm/gpio.h index 46a6d7914df..61f93da2c62 100644 --- a/arch/sh/include/asm/gpio.h +++ b/arch/sh/include/asm/gpio.h @@ -19,6 +19,40 @@ #include #endif +#define ARCH_NR_GPIOS 512 +#include + +#ifdef CONFIG_GPIOLIB + +static inline int gpio_get_value(unsigned gpio) +{ + return __gpio_get_value(gpio); +} + +static inline void gpio_set_value(unsigned gpio, int value) +{ + __gpio_set_value(gpio, value); +} + +static inline int gpio_cansleep(unsigned gpio) +{ + return __gpio_cansleep(gpio); +} + +static inline int gpio_to_irq(unsigned gpio) +{ + WARN_ON(1); + return -ENOSYS; +} + +static inline int irq_to_gpio(unsigned int irq) +{ + WARN_ON(1); + return -EINVAL; +} + +#endif /* CONFIG_GPIOLIB */ + typedef unsigned short pinmux_enum_t; typedef unsigned short pinmux_flag_t; @@ -94,34 +128,9 @@ struct pinmux_info { unsigned int gpio_data_size; unsigned long *gpio_in_use; + struct gpio_chip chip; }; int register_pinmux(struct pinmux_info *pip); -int __gpio_request(unsigned gpio); -static inline int gpio_request(unsigned gpio, const char *label) -{ - return __gpio_request(gpio); -} -void gpio_free(unsigned gpio); -int gpio_direction_input(unsigned gpio); -int gpio_direction_output(unsigned gpio, int value); -int gpio_get_value(unsigned gpio); -void gpio_set_value(unsigned gpio, int value); - -/* IRQ modes are unspported */ -static inline int gpio_to_irq(unsigned gpio) -{ - WARN_ON(1); - return -EINVAL; -} - -static inline int irq_to_gpio(unsigned irq) -{ - WARN_ON(1); - return -EINVAL; -} - -#include - #endif /* __ASM_SH_GPIO_H */ diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32 index 2e1b86e16ab..7e7d22b5b4c 100644 --- a/arch/sh/kernel/Makefile_32 +++ b/arch/sh/kernel/Makefile_32 @@ -27,7 +27,7 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_IO_TRAPPED) += io_trapped.o obj-$(CONFIG_KPROBES) += kprobes.o -obj-$(CONFIG_GENERIC_GPIO) += gpio.o +obj-$(CONFIG_ARCH_REQUIRE_GPIOLIB) += gpio.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o obj-$(CONFIG_DUMP_CODE) += disassemble.o diff --git a/arch/sh/kernel/Makefile_64 b/arch/sh/kernel/Makefile_64 index fe425d7f687..cbcbbb6c049 100644 --- a/arch/sh/kernel/Makefile_64 +++ b/arch/sh/kernel/Makefile_64 @@ -15,6 +15,6 @@ obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_IO_TRAPPED) += io_trapped.o -obj-$(CONFIG_GENERIC_GPIO) += gpio.o +obj-$(CONFIG_ARCH_REQUIRE_GPIOLIB) += gpio.o EXTRA_CFLAGS += -Werror diff --git a/arch/sh/kernel/gpio.c b/arch/sh/kernel/gpio.c index 28013567372..d22e5af699f 100644 --- a/arch/sh/kernel/gpio.c +++ b/arch/sh/kernel/gpio.c @@ -19,22 +19,6 @@ #include #include -static struct pinmux_info *registered_gpio; - -static struct pinmux_info *gpio_controller(unsigned gpio) -{ - if (!registered_gpio) - return NULL; - - if (gpio < registered_gpio->first_gpio) - return NULL; - - if (gpio > registered_gpio->last_gpio) - return NULL; - - return registered_gpio; -} - static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r) { if (enum_id < r->begin) @@ -398,9 +382,14 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio, static DEFINE_SPINLOCK(gpio_lock); -int __gpio_request(unsigned gpio) +static struct pinmux_info *chip_to_pinmux(struct gpio_chip *chip) { - struct pinmux_info *gpioc = gpio_controller(gpio); + return container_of(chip, struct pinmux_info, chip); +} + +static int sh_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + struct pinmux_info *gpioc = chip_to_pinmux(chip); struct pinmux_data_reg *dummy; unsigned long flags; int i, ret, pinmux_type; @@ -412,30 +401,30 @@ int __gpio_request(unsigned gpio) spin_lock_irqsave(&gpio_lock, flags); - if ((gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE) != PINMUX_TYPE_NONE) + if ((gpioc->gpios[offset].flags & PINMUX_FLAG_TYPE) != PINMUX_TYPE_NONE) goto err_unlock; /* setup pin function here if no data is associated with pin */ - if (get_data_reg(gpioc, gpio, &dummy, &i) != 0) + if (get_data_reg(gpioc, offset, &dummy, &i) != 0) pinmux_type = PINMUX_TYPE_FUNCTION; else pinmux_type = PINMUX_TYPE_GPIO; if (pinmux_type == PINMUX_TYPE_FUNCTION) { - if (pinmux_config_gpio(gpioc, gpio, + if (pinmux_config_gpio(gpioc, offset, pinmux_type, GPIO_CFG_DRYRUN) != 0) goto err_unlock; - if (pinmux_config_gpio(gpioc, gpio, + if (pinmux_config_gpio(gpioc, offset, pinmux_type, GPIO_CFG_REQ) != 0) BUG(); } - gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE; - gpioc->gpios[gpio].flags |= pinmux_type; + gpioc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE; + gpioc->gpios[offset].flags |= pinmux_type; ret = 0; err_unlock: @@ -443,11 +432,10 @@ int __gpio_request(unsigned gpio) err_out: return ret; } -EXPORT_SYMBOL(__gpio_request); -void gpio_free(unsigned gpio) +static void sh_gpio_free(struct gpio_chip *chip, unsigned offset) { - struct pinmux_info *gpioc = gpio_controller(gpio); + struct pinmux_info *gpioc = chip_to_pinmux(chip); unsigned long flags; int pinmux_type; @@ -456,14 +444,13 @@ void gpio_free(unsigned gpio) spin_lock_irqsave(&gpio_lock, flags); - pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE; - pinmux_config_gpio(gpioc, gpio, pinmux_type, GPIO_CFG_FREE); - gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE; - gpioc->gpios[gpio].flags |= PINMUX_TYPE_NONE; + pinmux_type = gpioc->gpios[offset].flags & PINMUX_FLAG_TYPE; + pinmux_config_gpio(gpioc, offset, pinmux_type, GPIO_CFG_FREE); + gpioc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE; + gpioc->gpios[offset].flags |= PINMUX_TYPE_NONE; spin_unlock_irqrestore(&gpio_lock, flags); } -EXPORT_SYMBOL(gpio_free); static int pinmux_direction(struct pinmux_info *gpioc, unsigned gpio, int new_pinmux_type) @@ -507,21 +494,20 @@ static int pinmux_direction(struct pinmux_info *gpioc, return ret; } -int gpio_direction_input(unsigned gpio) +static int sh_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { - struct pinmux_info *gpioc = gpio_controller(gpio); + struct pinmux_info *gpioc = chip_to_pinmux(chip); unsigned long flags; int ret; spin_lock_irqsave(&gpio_lock, flags); - ret = pinmux_direction(gpioc, gpio, PINMUX_TYPE_INPUT); + ret = pinmux_direction(gpioc, offset, PINMUX_TYPE_INPUT); spin_unlock_irqrestore(&gpio_lock, flags); return ret; } -EXPORT_SYMBOL(gpio_direction_input); -static void __gpio_set_value(struct pinmux_info *gpioc, +static void sh_gpio_set_value(struct pinmux_info *gpioc, unsigned gpio, int value) { struct pinmux_data_reg *dr = NULL; @@ -533,22 +519,22 @@ static void __gpio_set_value(struct pinmux_info *gpioc, gpio_write_bit(dr, bit, value); } -int gpio_direction_output(unsigned gpio, int value) +static int sh_gpio_direction_output(struct gpio_chip *chip, unsigned offset, + int value) { - struct pinmux_info *gpioc = gpio_controller(gpio); + struct pinmux_info *gpioc = chip_to_pinmux(chip); unsigned long flags; int ret; - __gpio_set_value(gpioc, gpio, value); + sh_gpio_set_value(gpioc, offset, value); spin_lock_irqsave(&gpio_lock, flags); - ret = pinmux_direction(gpioc, gpio, PINMUX_TYPE_OUTPUT); + ret = pinmux_direction(gpioc, offset, PINMUX_TYPE_OUTPUT); spin_unlock_irqrestore(&gpio_lock, flags); return ret; } -EXPORT_SYMBOL(gpio_direction_output); -static int __gpio_get_value(struct pinmux_info *gpioc, unsigned gpio) +static int sh_gpio_get_value(struct pinmux_info *gpioc, unsigned gpio) { struct pinmux_data_reg *dr = NULL; int bit = 0; @@ -561,24 +547,38 @@ static int __gpio_get_value(struct pinmux_info *gpioc, unsigned gpio) return gpio_read_reg(dr->reg, dr->reg_width, 1, bit); } -int gpio_get_value(unsigned gpio) +static int sh_gpio_get(struct gpio_chip *chip, unsigned offset) { - return __gpio_get_value(gpio_controller(gpio), gpio); + return sh_gpio_get_value(chip_to_pinmux(chip), offset); } -EXPORT_SYMBOL(gpio_get_value); -void gpio_set_value(unsigned gpio, int value) +static void sh_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - __gpio_set_value(gpio_controller(gpio), gpio, value); + sh_gpio_set_value(chip_to_pinmux(chip), offset, value); } -EXPORT_SYMBOL(gpio_set_value); int register_pinmux(struct pinmux_info *pip) { - registered_gpio = pip; - setup_data_regs(pip); - pr_info("pinmux: %s handling gpio %d -> %d\n", + struct gpio_chip *chip = &pip->chip; + + pr_info("sh pinmux: %s handling gpio %d -> %d\n", pip->name, pip->first_gpio, pip->last_gpio); - return 0; + setup_data_regs(pip); + + chip->request = sh_gpio_request; + chip->free = sh_gpio_free; + chip->direction_input = sh_gpio_direction_input; + chip->get = sh_gpio_get; + chip->direction_output = sh_gpio_direction_output; + chip->set = sh_gpio_set; + + WARN_ON(pip->first_gpio != 0); /* needs testing */ + + chip->label = pip->name; + chip->owner = THIS_MODULE; + chip->base = pip->first_gpio; + chip->ngpio = (pip->last_gpio - pip->first_gpio) + 1; + + return gpiochip_add(chip); } diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index 3599828b976..6a7cd498023 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -1,6 +1,6 @@ #include #include -#include +#include #if defined(CONFIG_H83007) || defined(CONFIG_H83068) #include -- GitLab From 57e97cb8bedd06e8a2e562454423d58aab5827ce Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 6 Jan 2009 12:47:12 +0900 Subject: [PATCH 0482/4982] sh: Fix up GENERIC_GPIO build for ARCH_WANT_OPTIONAL_GPIO cases. CPUs define pinmux tables through the optional interface, while boards that require demux of their own require it explicitly. Roll the Makefile rules back to depend on GENERIC_GPIO, which covers both cases. Fixes a link error with an undefined reference to register_pinmux() on optional platforms. Signed-off-by: Paul Mundt --- arch/sh/kernel/Makefile_32 | 2 +- arch/sh/kernel/Makefile_64 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32 index 7e7d22b5b4c..2e1b86e16ab 100644 --- a/arch/sh/kernel/Makefile_32 +++ b/arch/sh/kernel/Makefile_32 @@ -27,7 +27,7 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_IO_TRAPPED) += io_trapped.o obj-$(CONFIG_KPROBES) += kprobes.o -obj-$(CONFIG_ARCH_REQUIRE_GPIOLIB) += gpio.o +obj-$(CONFIG_GENERIC_GPIO) += gpio.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o obj-$(CONFIG_DUMP_CODE) += disassemble.o diff --git a/arch/sh/kernel/Makefile_64 b/arch/sh/kernel/Makefile_64 index cbcbbb6c049..fe425d7f687 100644 --- a/arch/sh/kernel/Makefile_64 +++ b/arch/sh/kernel/Makefile_64 @@ -15,6 +15,6 @@ obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_IO_TRAPPED) += io_trapped.o -obj-$(CONFIG_ARCH_REQUIRE_GPIOLIB) += gpio.o +obj-$(CONFIG_GENERIC_GPIO) += gpio.o EXTRA_CFLAGS += -Werror -- GitLab From ae5e6d05a606e05e054f816bd01e02f69d38d283 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 7 Jan 2009 17:16:25 +0900 Subject: [PATCH 0483/4982] sh: mach-highlander and mach-rsk require gpiolib. Fix up the build for mach-highlander and mach-rsk. These operated on the assumption that GENERIC_GPIO support with an optional GPIOLIB was possible. This used to be true, but has not been the case since commit-id d56cc8bc661ac1ceded8d45ba2d53bb134fee17d ("sh: use gpiolib"), where the GENERIC_GPIO implementation was rewritten to use GPIOLIB directly. Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 7 ------- arch/sh/boards/Kconfig | 2 +- arch/sh/boards/mach-highlander/Kconfig | 2 +- arch/sh/boards/mach-rsk/Kconfig | 2 +- 4 files changed, 3 insertions(+), 10 deletions(-) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 3a2be227894..ebabe518e72 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -126,13 +126,6 @@ config ARCH_HAS_ILOG2_U64 config ARCH_NO_VIRT_TO_BUS def_bool y -config ARCH_WANT_OPTIONAL_GPIOLIB - def_bool y - depends on !ARCH_REQUIRE_GPIOLIB - -config ARCH_REQUIRE_GPIOLIB - def_bool n - config IO_TRAPPED bool diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig index 802d5c475a7..c9da37088d2 100644 --- a/arch/sh/boards/Kconfig +++ b/arch/sh/boards/Kconfig @@ -240,7 +240,7 @@ config SH_X3PROTO config SH_MAGIC_PANEL_R2 bool "Magic Panel R2" depends on CPU_SUBTYPE_SH7720 - select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB help Select Magic Panel R2 if configuring for Magic Panel R2. diff --git a/arch/sh/boards/mach-highlander/Kconfig b/arch/sh/boards/mach-highlander/Kconfig index 08057f62687..def49cc0a7b 100644 --- a/arch/sh/boards/mach-highlander/Kconfig +++ b/arch/sh/boards/mach-highlander/Kconfig @@ -18,7 +18,7 @@ config SH_R7780MP config SH_R7785RP bool "R7785RP board support" depends on CPU_SUBTYPE_SH7785 - select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB endchoice diff --git a/arch/sh/boards/mach-rsk/Kconfig b/arch/sh/boards/mach-rsk/Kconfig index bff095dffc0..aeff3b04220 100644 --- a/arch/sh/boards/mach-rsk/Kconfig +++ b/arch/sh/boards/mach-rsk/Kconfig @@ -10,7 +10,7 @@ config SH_RSK7201 config SH_RSK7203 bool "RSK7203" - select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB depends on CPU_SUBTYPE_SH7203 endchoice -- GitLab From d057f0a4efe441842adb2d263e50173b7e0e7e38 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 27 Jan 2009 16:52:07 +1100 Subject: [PATCH 0484/4982] solos: Add initial list of parameters I don't much like the trick with multiple inclusions of solos-attrlist.c but don't really see a saner way to do it without repeating the list. Signed-off-by: David Woodhouse --- drivers/atm/solos-attrlist.c | 70 ++++++++++++++++++++++++++++++++++++ drivers/atm/solos-pci.c | 30 ++++++++++++---- 2 files changed, 94 insertions(+), 6 deletions(-) create mode 100644 drivers/atm/solos-attrlist.c diff --git a/drivers/atm/solos-attrlist.c b/drivers/atm/solos-attrlist.c new file mode 100644 index 00000000000..efa2808dd94 --- /dev/null +++ b/drivers/atm/solos-attrlist.c @@ -0,0 +1,70 @@ +SOLOS_ATTR_RO(DriverVersion) +SOLOS_ATTR_RO(APIVersion) +SOLOS_ATTR_RO(FirmwareVersion) +// SOLOS_ATTR_RO(DspVersion) +// SOLOS_ATTR_RO(CommonHandshake) +SOLOS_ATTR_RO(Connected) +SOLOS_ATTR_RO(OperationalMode) +SOLOS_ATTR_RO(State) +SOLOS_ATTR_RO(Watchdog) +SOLOS_ATTR_RO(OperationProgress) +SOLOS_ATTR_RO(LastFailed) +SOLOS_ATTR_RO(TxBitRate) +SOLOS_ATTR_RO(RxBitRate) +// SOLOS_ATTR_RO(DeltACTATPds) +// SOLOS_ATTR_RO(DeltACTATPus) +SOLOS_ATTR_RO(TxATTNDR) +SOLOS_ATTR_RO(RxATTNDR) +SOLOS_ATTR_RO(AnnexType) +SOLOS_ATTR_RO(GeneralFailure) +SOLOS_ATTR_RO(InterleaveDpDn) +SOLOS_ATTR_RO(InterleaveDpUp) +SOLOS_ATTR_RO(RSCorrectedErrorsDn) +SOLOS_ATTR_RO(RSUnCorrectedErrorsDn) +SOLOS_ATTR_RO(RSCorrectedErrorsUp) +SOLOS_ATTR_RO(RSUnCorrectedErrorsUp) +SOLOS_ATTR_RO(InterleaveRDn) +SOLOS_ATTR_RO(InterleaveRUp) +SOLOS_ATTR_RO(ShowtimeStart) +SOLOS_ATTR_RO(ATURVendor) +SOLOS_ATTR_RO(ATUCCountry) +SOLOS_ATTR_RO(ATURANSIRev) +SOLOS_ATTR_RO(ATURANSISTD) +SOLOS_ATTR_RO(ATUCANSIRev) +SOLOS_ATTR_RO(ATUCANSIId) +SOLOS_ATTR_RO(ATUCANSISTD) +SOLOS_ATTR_RO(DataBoost) +SOLOS_ATTR_RO(LocalITUCountryCode) +SOLOS_ATTR_RO(LocalSEF) +SOLOS_ATTR_RO(LocalEndLOS) +SOLOS_ATTR_RO(LocalSNRMargin) +SOLOS_ATTR_RO(LocalLineAttn) +SOLOS_ATTR_RO(RawAttn) +SOLOS_ATTR_RO(LocalTxPower) +SOLOS_ATTR_RO(RemoteTxPower) +SOLOS_ATTR_RO(RemoteSEF) +SOLOS_ATTR_RO(RemoteLOS) +SOLOS_ATTR_RO(RemoteLineAttn) +SOLOS_ATTR_RO(RemoteSNRMargin) +SOLOS_ATTR_RO(LineUpCount) +SOLOS_ATTR_RO(SRACnt) +SOLOS_ATTR_RO(SRACntUp) +SOLOS_ATTR_RO(ProfileStatus) +SOLOS_ATTR_RW(Action) +SOLOS_ATTR_RW(ActivateLine) +SOLOS_ATTR_RO(LineStatus) +SOLOS_ATTR_RW(HostControl) +SOLOS_ATTR_RW(AutoStart) +SOLOS_ATTR_RW(Failsafe) +SOLOS_ATTR_RW(ShowtimeLed) +SOLOS_ATTR_RW(Retrain) +SOLOS_ATTR_RW(Defaults) +SOLOS_ATTR_RW(LineMode) +SOLOS_ATTR_RW(Profile) +SOLOS_ATTR_RW(DetectNoise) +SOLOS_ATTR_RO(SupportedAnnexes) +SOLOS_ATTR_RO(Status) +SOLOS_ATTR_RO(TotalStart) +SOLOS_ATTR_RO(RecentShowtimeStart) +SOLOS_ATTR_RO(TotalRxBlocks) +SOLOS_ATTR_RO(TotalTxBlocks) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index d9262a428dd..b0c4676296b 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -371,8 +371,28 @@ static ssize_t console_store(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR(console, 0644, console_show, console_store); -static DEVICE_ATTR(OperationalMode, 0444, solos_param_show, NULL); -static DEVICE_ATTR(AutoStart, 0644, solos_param_show, solos_param_store); + + +#define SOLOS_ATTR_RO(x) static DEVICE_ATTR(x, 0444, solos_param_show, NULL); +#define SOLOS_ATTR_RW(x) static DEVICE_ATTR(x, 0644, solos_param_show, solos_param_store); + +#include "solos-attrlist.c" + +#undef SOLOS_ATTR_RO +#undef SOLOS_ATTR_RW + +#define SOLOS_ATTR_RO(x) &dev_attr_##x.attr, +#define SOLOS_ATTR_RW(x) &dev_attr_##x.attr, + +static struct attribute *solos_attrs[] = { +#include "solos-attrlist.c" + NULL +}; + +static struct attribute_group solos_attr_group = { + .attrs = solos_attrs, + .name = "parameters", +}; static int flash_upgrade(struct solos_card *card, int chip) { @@ -987,10 +1007,8 @@ static int atm_init(struct solos_card *card) } if (device_create_file(&card->atmdev[i]->class_dev, &dev_attr_console)) dev_err(&card->dev->dev, "Could not register console for ATM device %d\n", i); - if (device_create_file(&card->atmdev[i]->class_dev, &dev_attr_OperationalMode)) - dev_err(&card->dev->dev, "Could not register opmode attr for ATM device %d\n", i); - if (device_create_file(&card->atmdev[i]->class_dev, &dev_attr_AutoStart)) - dev_err(&card->dev->dev, "Could not register autostart attr for ATM device %d\n", i); + if (sysfs_create_group(&card->atmdev[i]->class_dev.kobj, &solos_attr_group)) + dev_err(&card->dev->dev, "Could not register parameter group for ATM device %d\n", i); dev_info(&card->dev->dev, "Registered ATM device %d\n", card->atmdev[i]->number); -- GitLab From cb0bc205959bf8c60acae9c71f3da0597e756f8e Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Mon, 26 Jan 2009 22:21:59 -0800 Subject: [PATCH 0485/4982] cxgb3: Notify fatal errors Set up a notification mechanism to inform upper layer modules (iWARP, iSCSI) of a chip reset due to an EEH event or a fatal error. Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/cxgb3_main.c | 13 +++++++++---- drivers/net/cxgb3/cxgb3_offload.c | 12 ++++++++++++ drivers/net/cxgb3/cxgb3_offload.h | 7 +++++++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 7381f378b4e..f2c7cc3e263 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -2542,6 +2542,12 @@ static int t3_adapter_error(struct adapter *adapter, int reset) { int i, ret = 0; + if (is_offload(adapter) && + test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)) { + cxgb3_err_notify(&adapter->tdev, OFFLOAD_STATUS_DOWN, 0); + offload_close(&adapter->tdev); + } + /* Stop all ports */ for_each_port(adapter, i) { struct net_device *netdev = adapter->port[i]; @@ -2550,10 +2556,6 @@ static int t3_adapter_error(struct adapter *adapter, int reset) cxgb_close(netdev); } - if (is_offload(adapter) && - test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)) - offload_close(&adapter->tdev); - /* Stop SGE timers */ t3_stop_sge_timers(adapter); @@ -2605,6 +2607,9 @@ static void t3_resume_ports(struct adapter *adapter) } } } + + if (is_offload(adapter) && !ofld_disable) + cxgb3_err_notify(&adapter->tdev, OFFLOAD_STATUS_UP, 0); } /* diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c index 2d7f69aff1d..620d80be6aa 100644 --- a/drivers/net/cxgb3/cxgb3_offload.c +++ b/drivers/net/cxgb3/cxgb3_offload.c @@ -153,6 +153,18 @@ void cxgb3_remove_clients(struct t3cdev *tdev) mutex_unlock(&cxgb3_db_lock); } +void cxgb3_err_notify(struct t3cdev *tdev, u32 status, u32 error) +{ + struct cxgb3_client *client; + + mutex_lock(&cxgb3_db_lock); + list_for_each_entry(client, &client_list, client_list) { + if (client->err_handler) + client->err_handler(tdev, status, error); + } + mutex_unlock(&cxgb3_db_lock); +} + static struct net_device *get_iff_from_mac(struct adapter *adapter, const unsigned char *mac, unsigned int vlan) diff --git a/drivers/net/cxgb3/cxgb3_offload.h b/drivers/net/cxgb3/cxgb3_offload.h index d514e5019df..a8e8e5fcdf8 100644 --- a/drivers/net/cxgb3/cxgb3_offload.h +++ b/drivers/net/cxgb3/cxgb3_offload.h @@ -64,10 +64,16 @@ void cxgb3_register_client(struct cxgb3_client *client); void cxgb3_unregister_client(struct cxgb3_client *client); void cxgb3_add_clients(struct t3cdev *tdev); void cxgb3_remove_clients(struct t3cdev *tdev); +void cxgb3_err_notify(struct t3cdev *tdev, u32 status, u32 error); typedef int (*cxgb3_cpl_handler_func)(struct t3cdev *dev, struct sk_buff *skb, void *ctx); +enum { + OFFLOAD_STATUS_UP, + OFFLOAD_STATUS_DOWN +}; + struct cxgb3_client { char *name; void (*add) (struct t3cdev *); @@ -76,6 +82,7 @@ struct cxgb3_client { int (*redirect)(void *ctx, struct dst_entry *old, struct dst_entry *new, struct l2t_entry *l2t); struct list_head client_list; + void (*err_handler)(struct t3cdev *tdev, u32 status, u32 error); }; /* -- GitLab From a73efd0a8552927ebe5dff84936f7fdac4f7e314 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Mon, 26 Jan 2009 22:22:19 -0800 Subject: [PATCH 0486/4982] iw_cxgb3: handle chip reset notifications Freeze activity when notified that the underlying chip is getting reset on a EEH event or fatal error. Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/infiniband/hw/cxgb3/cxio_hal.c | 3 +++ drivers/infiniband/hw/cxgb3/cxio_hal.h | 2 ++ drivers/infiniband/hw/cxgb3/iwch.c | 15 ++++++++++++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c index 4dcf08b3fd8..11efd3528ce 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_hal.c +++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c @@ -701,6 +701,9 @@ static int __cxio_tpt_op(struct cxio_rdev *rdev_p, u32 reset_tpt_entry, u32 stag_idx; u32 wptr; + if (rdev_p->flags) + return -EIO; + stag_state = stag_state > 0; stag_idx = (*stag) >> 8; diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.h b/drivers/infiniband/hw/cxgb3/cxio_hal.h index 656fe47bc84..9ed65b05517 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_hal.h +++ b/drivers/infiniband/hw/cxgb3/cxio_hal.h @@ -108,6 +108,8 @@ struct cxio_rdev { struct gen_pool *pbl_pool; struct gen_pool *rqt_pool; struct list_head entry; + u32 flags; +#define CXIO_ERROR_FATAL 1 }; static inline int cxio_num_stags(struct cxio_rdev *rdev_p) diff --git a/drivers/infiniband/hw/cxgb3/iwch.c b/drivers/infiniband/hw/cxgb3/iwch.c index 4489c89d671..37a4fc264a0 100644 --- a/drivers/infiniband/hw/cxgb3/iwch.c +++ b/drivers/infiniband/hw/cxgb3/iwch.c @@ -51,13 +51,15 @@ cxgb3_cpl_handler_func t3c_handlers[NUM_CPL_CMDS]; static void open_rnic_dev(struct t3cdev *); static void close_rnic_dev(struct t3cdev *); +static void iwch_err_handler(struct t3cdev *, u32, u32); struct cxgb3_client t3c_client = { .name = "iw_cxgb3", .add = open_rnic_dev, .remove = close_rnic_dev, .handlers = t3c_handlers, - .redirect = iwch_ep_redirect + .redirect = iwch_ep_redirect, + .err_handler = iwch_err_handler }; static LIST_HEAD(dev_list); @@ -160,6 +162,17 @@ static void close_rnic_dev(struct t3cdev *tdev) mutex_unlock(&dev_mutex); } +static void iwch_err_handler(struct t3cdev *tdev, u32 status, u32 error) +{ + struct cxio_rdev *rdev = tdev->ulp; + + if (status == OFFLOAD_STATUS_DOWN) + rdev->flags = CXIO_ERROR_FATAL; + + return; + +} + static int __init iwch_init_module(void) { int err; -- GitLab From 87ebb18627930ce005beba227ca267b5b5372e06 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 27 Jan 2009 20:02:30 +1100 Subject: [PATCH 0487/4982] solos: Handle new line status change packets, hook up to ATM layer info Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 93 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index b0c4676296b..4c87dfb0156 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -82,6 +82,7 @@ struct pkt_hdr { #define PKT_COMMAND 1 #define PKT_POPEN 3 #define PKT_PCLOSE 4 +#define PKT_STATUS 5 struct solos_card { void __iomem *config_regs; @@ -275,6 +276,72 @@ static ssize_t solos_param_store(struct device *dev, struct device_attribute *at return ret; } +static char *next_string(struct sk_buff *skb) +{ + int i = 0; + char *this = skb->data; + + while (i < skb->len) { + if (this[i] == '\n') { + this[i] = 0; + skb_pull(skb, i); + return this; + } + } + return NULL; +} + +/* + * Status packet has fields separated by \n, starting with a version number + * for the information therein. Fields are.... + * + * packet version + * TxBitRate (version >= 1) + * RxBitRate (version >= 1) + * State (version >= 1) + */ +static int process_status(struct solos_card *card, int port, struct sk_buff *skb) +{ + char *str, *end; + int ver, rate_up, rate_down, state; + + if (!card->atmdev[port]) + return -ENODEV; + + str = next_string(skb); + if (!str) + return -EIO; + + ver = simple_strtol(str, NULL, 10); + if (ver < 1) { + dev_warn(&card->dev->dev, "Unexpected status interrupt version %d\n", + ver); + return -EIO; + } + + str = next_string(skb); + rate_up = simple_strtol(str, &end, 10); + if (*end) + return -EIO; + + str = next_string(skb); + rate_down = simple_strtol(str, &end, 10); + if (*end) + return -EIO; + + str = next_string(skb); + if (!strcmp(str, "Showtime")) + state = ATM_PHY_SIG_FOUND; + else state = ATM_PHY_SIG_LOST; + + card->atmdev[port]->link_rate = rate_down; + card->atmdev[port]->signal = state; + + dev_info(&card->dev->dev, "ATM state: '%s', %d/%d kb/s up/down.\n", + str, rate_up/1000, rate_down/1000); + return 0; +} + static int process_command(struct solos_card *card, int port, struct sk_buff *skb) { struct solos_param *prm; @@ -512,7 +579,7 @@ void solos_bh(unsigned long card_arg) size = le16_to_cpu(header.size); - skb = alloc_skb(size, GFP_ATOMIC); + skb = alloc_skb(size + 1, GFP_ATOMIC); if (!skb) { if (net_ratelimit()) dev_warn(&card->dev->dev, "Failed to allocate sk_buff for RX\n"); @@ -547,6 +614,11 @@ void solos_bh(unsigned long card_arg) atomic_inc(&vcc->stats->rx); break; + case PKT_STATUS: + process_status(card, port, skb); + dev_kfree_skb(skb); + break; + case PKT_COMMAND: default: /* FIXME: Not really, surely? */ if (process_command(card, port, skb)) @@ -996,6 +1068,9 @@ static int atm_init(struct solos_card *card) int i; for (i = 0; i < card->nr_ports; i++) { + struct sk_buff *skb; + struct pkt_hdr *header; + skb_queue_head_init(&card->tx_queue[i]); skb_queue_head_init(&card->cli_queue[i]); @@ -1016,6 +1091,22 @@ static int atm_init(struct solos_card *card) card->atmdev[i]->ci_range.vci_bits = 16; card->atmdev[i]->dev_data = card; card->atmdev[i]->phy_data = (void *)(unsigned long)i; + card->atmdev[i]->signal = ATM_PHY_SIG_UNKNOWN; + + skb = alloc_skb(sizeof(*header), GFP_ATOMIC); + if (!skb) { + dev_warn(&card->dev->dev, "Failed to allocate sk_buff in atm_init()\n"); + continue; + } + + header = (void *)skb_put(skb, sizeof(*header)); + + header->size = cpu_to_le16(0); + header->vpi = cpu_to_le16(0); + header->vci = cpu_to_le16(0); + header->type = cpu_to_le16(PKT_STATUS); + + fpga_queue(card, i, skb, NULL); } return 0; } -- GitLab From 6627a653bceb3a54e55e5cdc478ec5b8d5c9cc44 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 23 Jan 2009 22:55:23 +0000 Subject: [PATCH 0488/4982] ASoC: Push the codec runtime storage into the card structure This is a further stage on the road to refactoring away the ASoC platform device. Signed-off-by: Mark Brown --- include/sound/soc.h | 3 ++- sound/soc/codecs/ac97.c | 20 +++++++++--------- sound/soc/codecs/ad1980.c | 12 +++++------ sound/soc/codecs/ad73311.c | 8 ++++---- sound/soc/codecs/ak4535.c | 14 ++++++------- sound/soc/codecs/cs4270.c | 6 +++--- sound/soc/codecs/pcm3008.c | 12 +++++------ sound/soc/codecs/ssm2602.c | 20 +++++++++--------- sound/soc/codecs/tlv320aic23.c | 18 ++++++++--------- sound/soc/codecs/tlv320aic26.c | 4 ++-- sound/soc/codecs/tlv320aic3x.c | 14 ++++++------- sound/soc/codecs/twl4030.c | 12 +++++------ sound/soc/codecs/uda134x.c | 18 ++++++++--------- sound/soc/codecs/uda1380.c | 18 ++++++++--------- sound/soc/codecs/wm8350.c | 10 ++++----- sound/soc/codecs/wm8510.c | 16 +++++++-------- sound/soc/codecs/wm8580.c | 10 ++++----- sound/soc/codecs/wm8728.c | 16 +++++++-------- sound/soc/codecs/wm8731.c | 20 +++++++++--------- sound/soc/codecs/wm8750.c | 16 +++++++-------- sound/soc/codecs/wm8753.c | 18 ++++++++--------- sound/soc/codecs/wm8900.c | 8 ++++---- sound/soc/codecs/wm8903.c | 18 ++++++++--------- sound/soc/codecs/wm8971.c | 14 ++++++------- sound/soc/codecs/wm8990.c | 14 ++++++------- sound/soc/codecs/wm9705.c | 15 +++++++------- sound/soc/codecs/wm9712.c | 21 ++++++++++--------- sound/soc/codecs/wm9713.c | 17 ++++++++-------- sound/soc/soc-core.c | 37 ++++++++++++++++------------------ sound/soc/soc-dapm.c | 6 +++--- sound/soc/soc-jack.c | 4 ++-- 31 files changed, 220 insertions(+), 219 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 7039343e8a7..0e773526416 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -418,6 +418,8 @@ struct snd_soc_card { struct snd_soc_device *socdev; + struct snd_soc_codec *codec; + struct snd_soc_platform *platform; struct delayed_work delayed_work; struct work_struct deferred_resume_work; @@ -427,7 +429,6 @@ struct snd_soc_card { struct snd_soc_device { struct device *dev; struct snd_soc_card *card; - struct snd_soc_codec *codec; struct snd_soc_codec_device *codec_dev; void *codec_data; }; diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index 89d41277616..11f84b6e5cb 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c @@ -30,7 +30,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; @@ -84,10 +84,10 @@ static int ac97_soc_probe(struct platform_device *pdev) printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION); - socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (!socdev->codec) + socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); + if (!socdev->card->codec) return -ENOMEM; - codec = socdev->codec; + codec = socdev->card->codec; mutex_init(&codec->mutex); codec->name = "AC97"; @@ -123,21 +123,21 @@ bus_err: snd_soc_free_pcms(socdev); err: - kfree(socdev->codec); - socdev->codec = NULL; + kfree(socdev->card->codec); + socdev->card->codec = NULL; return ret; } static int ac97_soc_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (!codec) return 0; snd_soc_free_pcms(socdev); - kfree(socdev->codec); + kfree(socdev->card->codec); return 0; } @@ -147,7 +147,7 @@ static int ac97_soc_suspend(struct platform_device *pdev, pm_message_t msg) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - snd_ac97_suspend(socdev->codec->ac97); + snd_ac97_suspend(socdev->card->codec->ac97); return 0; } @@ -156,7 +156,7 @@ static int ac97_soc_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - snd_ac97_resume(socdev->codec->ac97); + snd_ac97_resume(socdev->card->codec->ac97); return 0; } diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index faf358758e1..ddb3b08ac23 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c @@ -186,10 +186,10 @@ static int ad1980_soc_probe(struct platform_device *pdev) printk(KERN_INFO "AD1980 SoC Audio Codec\n"); - socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (socdev->codec == NULL) + socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); + if (socdev->card->codec == NULL) return -ENOMEM; - codec = socdev->codec; + codec = socdev->card->codec; mutex_init(&codec->mutex); codec->reg_cache = @@ -275,15 +275,15 @@ codec_err: kfree(codec->reg_cache); cache_err: - kfree(socdev->codec); - socdev->codec = NULL; + kfree(socdev->card->codec); + socdev->card->codec = NULL; return ret; } static int ad1980_soc_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec == NULL) return 0; diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c index b09289a1e55..e61dac5e7b8 100644 --- a/sound/soc/codecs/ad73311.c +++ b/sound/soc/codecs/ad73311.c @@ -53,7 +53,7 @@ static int ad73311_soc_probe(struct platform_device *pdev) codec->owner = THIS_MODULE; codec->dai = &ad73311_dai; codec->num_dai = 1; - socdev->codec = codec; + socdev->card->codec = codec; INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -75,15 +75,15 @@ static int ad73311_soc_probe(struct platform_device *pdev) register_err: snd_soc_free_pcms(socdev); pcm_err: - kfree(socdev->codec); - socdev->codec = NULL; + kfree(socdev->card->codec); + socdev->card->codec = NULL; return ret; } static int ad73311_soc_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec == NULL) return 0; diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index f17c363cb1d..d56e6bb1fed 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c @@ -329,7 +329,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct ak4535_priv *ak4535 = codec->private_data; u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5); int rate = params_rate(params), fs = 256; @@ -447,7 +447,7 @@ EXPORT_SYMBOL_GPL(ak4535_dai); static int ak4535_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; @@ -456,7 +456,7 @@ static int ak4535_suspend(struct platform_device *pdev, pm_message_t state) static int ak4535_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; ak4535_sync(codec); ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); ak4535_set_bias_level(codec, codec->suspend_bias_level); @@ -469,7 +469,7 @@ static int ak4535_resume(struct platform_device *pdev) */ static int ak4535_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret = 0; codec->name = "AK4535"; @@ -523,7 +523,7 @@ static int ak4535_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = ak4535_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -622,7 +622,7 @@ static int ak4535_probe(struct platform_device *pdev) } codec->private_data = ak4535; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -649,7 +649,7 @@ static int ak4535_probe(struct platform_device *pdev) static int ak4535_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 2aa12fdbd2c..21253b48289 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -350,7 +350,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct cs4270_private *cs4270 = codec->private_data; int ret; unsigned int i; @@ -575,7 +575,7 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, return -ENOMEM; } codec = &cs4270->codec; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); @@ -653,7 +653,7 @@ error_free_codec: static int cs4270_i2c_remove(struct i2c_client *i2c_client) { struct snd_soc_device *socdev = i2c_get_clientdata(i2c_client); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct cs4270_private *cs4270 = codec->private_data; snd_soc_free_pcms(socdev); diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c index 9a3e67e5319..5cda9e6b5a7 100644 --- a/sound/soc/codecs/pcm3008.c +++ b/sound/soc/codecs/pcm3008.c @@ -67,11 +67,11 @@ static int pcm3008_soc_probe(struct platform_device *pdev) printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION); - socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (!socdev->codec) + socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); + if (!socdev->card->codec) return -ENOMEM; - codec = socdev->codec; + codec = socdev->card->codec; mutex_init(&codec->mutex); codec->name = "PCM3008"; @@ -139,7 +139,7 @@ gpio_err: card_err: snd_soc_free_pcms(socdev); pcm_err: - kfree(socdev->codec); + kfree(socdev->card->codec); return ret; } @@ -147,7 +147,7 @@ pcm_err: static int pcm3008_soc_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct pcm3008_setup_data *setup = socdev->codec_data; if (!codec) @@ -155,7 +155,7 @@ static int pcm3008_soc_remove(struct platform_device *pdev) pcm3008_gpio_free(setup); snd_soc_free_pcms(socdev); - kfree(socdev->codec); + kfree(socdev->card->codec); return 0; } diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index ec7fe3b7b0c..58e225dadc7 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -276,7 +276,7 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream, u16 srate; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct ssm2602_priv *ssm2602 = codec->private_data; struct i2c_client *i2c = codec->control_data; u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3; @@ -321,7 +321,7 @@ static int ssm2602_startup(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct ssm2602_priv *ssm2602 = codec->private_data; struct i2c_client *i2c = codec->control_data; struct snd_pcm_runtime *master_runtime; @@ -358,7 +358,7 @@ static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; /* set active */ ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC); @@ -370,7 +370,7 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct ssm2602_priv *ssm2602 = codec->private_data; /* deactivate */ if (!codec->active) @@ -535,7 +535,7 @@ EXPORT_SYMBOL_GPL(ssm2602_dai); static int ssm2602_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; @@ -544,7 +544,7 @@ static int ssm2602_suspend(struct platform_device *pdev, pm_message_t state) static int ssm2602_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -566,7 +566,7 @@ static int ssm2602_resume(struct platform_device *pdev) */ static int ssm2602_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int reg, ret = 0; codec->name = "SSM2602"; @@ -639,7 +639,7 @@ static int ssm2602_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = ssm2602_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -733,7 +733,7 @@ static int ssm2602_probe(struct platform_device *pdev) } codec->private_data = ssm2602; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -754,7 +754,7 @@ static int ssm2602_probe(struct platform_device *pdev) static int ssm2602_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index a0e47c1dcd6..8b20c360adf 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -405,7 +405,7 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u16 iface_reg; int ret; struct aic23 *aic23 = container_of(codec, struct aic23, codec); @@ -453,7 +453,7 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; /* set active */ tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001); @@ -466,7 +466,7 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct aic23 *aic23 = container_of(codec, struct aic23, codec); /* deactivate */ @@ -609,7 +609,7 @@ static int tlv320aic23_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0); tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); @@ -620,7 +620,7 @@ static int tlv320aic23_suspend(struct platform_device *pdev, static int tlv320aic23_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int i; u16 reg; @@ -642,7 +642,7 @@ static int tlv320aic23_resume(struct platform_device *pdev) */ static int tlv320aic23_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret = 0; u16 reg; @@ -729,7 +729,7 @@ static int tlv320aic23_codec_probe(struct i2c_client *i2c, const struct i2c_device_id *i2c_id) { struct snd_soc_device *socdev = tlv320aic23_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -787,7 +787,7 @@ static int tlv320aic23_probe(struct platform_device *pdev) if (aic23 == NULL) return -ENOMEM; codec = &aic23->codec; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -806,7 +806,7 @@ static int tlv320aic23_probe(struct platform_device *pdev) static int tlv320aic23_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct aic23 *aic23 = container_of(codec, struct aic23, codec); if (codec->control_data) diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index 29f2f1a017f..229e464cf71 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c @@ -130,7 +130,7 @@ static int aic26_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct aic26 *aic26 = codec->private_data; int fsref, divisor, wlen, pval, jval, dval, qval; u16 reg; @@ -338,7 +338,7 @@ static int aic26_probe(struct platform_device *pdev) return -ENODEV; } codec = &aic26->codec; - socdev->codec = codec; + socdev->card->codec = codec; dev_dbg(&pdev->dev, "Registering PCMs, dev=%p, socdev->dev=%p\n", &pdev->dev, socdev->dev); diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 36ab0198ca3..ba64b0c617e 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -727,7 +727,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct aic3x_priv *aic3x = codec->private_data; int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0; u8 data, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1; @@ -1079,7 +1079,7 @@ EXPORT_SYMBOL_GPL(aic3x_dai); static int aic3x_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); @@ -1089,7 +1089,7 @@ static int aic3x_suspend(struct platform_device *pdev, pm_message_t state) static int aic3x_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u8 *cache = codec->reg_cache; @@ -1112,7 +1112,7 @@ static int aic3x_resume(struct platform_device *pdev) */ static int aic3x_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct aic3x_setup_data *setup = socdev->codec_data; int reg, ret = 0; @@ -1243,7 +1243,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = aic3x_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -1348,7 +1348,7 @@ static int aic3x_probe(struct platform_device *pdev) } codec->private_data = aic3x; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -1374,7 +1374,7 @@ static int aic3x_probe(struct platform_device *pdev) static int aic3x_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; /* power down chip */ if (codec->control_data) diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index f530c1e6d9e..796f34cac85 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -981,7 +981,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u8 mode, old_mode, format, old_format; @@ -1166,7 +1166,7 @@ EXPORT_SYMBOL_GPL(twl4030_dai); static int twl4030_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); @@ -1176,7 +1176,7 @@ static int twl4030_suspend(struct platform_device *pdev, pm_message_t state) static int twl4030_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); twl4030_set_bias_level(codec, codec->suspend_bias_level); @@ -1190,7 +1190,7 @@ static int twl4030_resume(struct platform_device *pdev) static int twl4030_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret = 0; printk(KERN_INFO "TWL4030 Audio Codec init \n"); @@ -1251,7 +1251,7 @@ static int twl4030_probe(struct platform_device *pdev) if (codec == NULL) return -ENOMEM; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -1265,7 +1265,7 @@ static int twl4030_probe(struct platform_device *pdev) static int twl4030_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; printk(KERN_INFO "TWL4030 Audio Codec remove\n"); snd_soc_free_pcms(socdev); diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index 277825d155a..661599295ca 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c @@ -173,7 +173,7 @@ static int uda134x_startup(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct uda134x_priv *uda134x = codec->private_data; struct snd_pcm_runtime *master_runtime; @@ -206,7 +206,7 @@ static void uda134x_shutdown(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct uda134x_priv *uda134x = codec->private_data; if (uda134x->master_substream == substream) @@ -221,7 +221,7 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct uda134x_priv *uda134x = codec->private_data; u8 hw_params; @@ -492,11 +492,11 @@ static int uda134x_soc_probe(struct platform_device *pdev) return -EINVAL; } - socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (socdev->codec == NULL) + socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); + if (socdev->card->codec == NULL) return ret; - codec = socdev->codec; + codec = socdev->card->codec; uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL); if (uda134x == NULL) @@ -584,7 +584,7 @@ priv_err: static int uda134x_soc_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); @@ -604,7 +604,7 @@ static int uda134x_soc_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); @@ -614,7 +614,7 @@ static int uda134x_soc_suspend(struct platform_device *pdev, static int uda134x_soc_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE); uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index a957b4365b9..98e4a6560f0 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -397,7 +397,7 @@ static int uda1380_pcm_prepare(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int reg, reg_start, reg_end, clk; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { @@ -430,7 +430,7 @@ static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); /* set WSPLL power and divider if running from this clock */ @@ -469,7 +469,7 @@ static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); /* shut down WSPLL power if running from this clock */ @@ -591,7 +591,7 @@ EXPORT_SYMBOL_GPL(uda1380_dai); static int uda1380_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; @@ -600,7 +600,7 @@ static int uda1380_suspend(struct platform_device *pdev, pm_message_t state) static int uda1380_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -622,7 +622,7 @@ static int uda1380_resume(struct platform_device *pdev) */ static int uda1380_init(struct snd_soc_device *socdev, int dac_clk) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret = 0; codec->name = "UDA1380"; @@ -688,7 +688,7 @@ static int uda1380_i2c_probe(struct i2c_client *i2c, { struct snd_soc_device *socdev = uda1380_socdev; struct uda1380_setup_data *setup = socdev->codec_data; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -779,7 +779,7 @@ static int uda1380_probe(struct platform_device *pdev) if (codec == NULL) return -ENOMEM; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -803,7 +803,7 @@ static int uda1380_probe(struct platform_device *pdev) static int uda1380_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 2e0db29b499..75d3438ccb8 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -1301,7 +1301,7 @@ static int wm8350_set_bias_level(struct snd_soc_codec *codec, static int wm8350_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; @@ -1310,7 +1310,7 @@ static int wm8350_suspend(struct platform_device *pdev, pm_message_t state) static int wm8350_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -1423,8 +1423,8 @@ static int wm8350_probe(struct platform_device *pdev) BUG_ON(!wm8350_codec); - socdev->codec = wm8350_codec; - codec = socdev->codec; + socdev->card->codec = wm8350_codec; + codec = socdev->card->codec; wm8350 = codec->control_data; priv = codec->private_data; @@ -1498,7 +1498,7 @@ card_err: static int wm8350_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm8350 *wm8350 = codec->control_data; struct wm8350_data *priv = codec->private_data; int ret; diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index abe7cce8771..f01078cfbd7 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -452,7 +452,7 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u16 iface = wm8510_read_reg_cache(codec, WM8510_IFACE) & 0x19f; u16 adn = wm8510_read_reg_cache(codec, WM8510_ADD) & 0x1f1; @@ -581,7 +581,7 @@ EXPORT_SYMBOL_GPL(wm8510_dai); static int wm8510_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; @@ -590,7 +590,7 @@ static int wm8510_suspend(struct platform_device *pdev, pm_message_t state) static int wm8510_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -612,7 +612,7 @@ static int wm8510_resume(struct platform_device *pdev) */ static int wm8510_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret = 0; codec->name = "WM8510"; @@ -670,7 +670,7 @@ static int wm8510_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = wm8510_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -751,7 +751,7 @@ err_driver: static int __devinit wm8510_spi_probe(struct spi_device *spi) { struct snd_soc_device *socdev = wm8510_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; codec->control_data = spi; @@ -817,7 +817,7 @@ static int wm8510_probe(struct platform_device *pdev) if (codec == NULL) return -ENOMEM; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -847,7 +847,7 @@ static int wm8510_probe(struct platform_device *pdev) static int wm8510_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 3faf0e70ce1..d3c51ba5e6f 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -539,7 +539,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u16 paifb = wm8580_read(codec, WM8580_PAIF3 + dai->id); paifb &= ~WM8580_AIF_LENGTH_MASK; @@ -816,7 +816,7 @@ EXPORT_SYMBOL_GPL(wm8580_dai); */ static int wm8580_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret = 0; codec->name = "WM8580"; @@ -888,7 +888,7 @@ static int wm8580_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = wm8580_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -986,7 +986,7 @@ static int wm8580_probe(struct platform_device *pdev) } codec->private_data = wm8580; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -1007,7 +1007,7 @@ static int wm8580_probe(struct platform_device *pdev) static int wm8580_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index f90dc52e975..f8363b30889 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -137,7 +137,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u16 dac = wm8728_read_reg_cache(codec, WM8728_DACCTL); dac &= ~0x18; @@ -264,7 +264,7 @@ EXPORT_SYMBOL_GPL(wm8728_dai); static int wm8728_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); @@ -274,7 +274,7 @@ static int wm8728_suspend(struct platform_device *pdev, pm_message_t state) static int wm8728_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; wm8728_set_bias_level(codec, codec->suspend_bias_level); @@ -287,7 +287,7 @@ static int wm8728_resume(struct platform_device *pdev) */ static int wm8728_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret = 0; codec->name = "WM8728"; @@ -349,7 +349,7 @@ static int wm8728_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = wm8728_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -430,7 +430,7 @@ err_driver: static int __devinit wm8728_spi_probe(struct spi_device *spi) { struct snd_soc_device *socdev = wm8728_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; codec->control_data = spi; @@ -494,7 +494,7 @@ static int wm8728_probe(struct platform_device *pdev) if (codec == NULL) return -ENOMEM; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -527,7 +527,7 @@ static int wm8728_probe(struct platform_device *pdev) static int wm8728_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 96d6e1aeaf4..0150fe53a65 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -253,7 +253,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm8731_priv *wm8731 = codec->private_data; u16 iface = wm8731_read_reg_cache(codec, WM8731_IFACE) & 0xfff3; int i = get_coeff(wm8731->sysclk, params_rate(params)); @@ -283,7 +283,7 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; /* set active */ wm8731_write(codec, WM8731_ACTIVE, 0x0001); @@ -296,7 +296,7 @@ static void wm8731_shutdown(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; /* deactivate */ if (!codec->active) { @@ -458,7 +458,7 @@ EXPORT_SYMBOL_GPL(wm8731_dai); static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; wm8731_write(codec, WM8731_ACTIVE, 0x0); wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); @@ -468,7 +468,7 @@ static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) static int wm8731_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -490,7 +490,7 @@ static int wm8731_resume(struct platform_device *pdev) */ static int wm8731_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int reg, ret = 0; codec->name = "WM8731"; @@ -561,7 +561,7 @@ static int wm8731_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = wm8731_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -642,7 +642,7 @@ err_driver: static int __devinit wm8731_spi_probe(struct spi_device *spi) { struct snd_soc_device *socdev = wm8731_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; codec->control_data = spi; @@ -716,7 +716,7 @@ static int wm8731_probe(struct platform_device *pdev) } codec->private_data = wm8731; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -750,7 +750,7 @@ static int wm8731_probe(struct platform_device *pdev) static int wm8731_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 1578569793a..96afb86addc 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -604,7 +604,7 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm8750_priv *wm8750 = codec->private_data; u16 iface = wm8750_read_reg_cache(codec, WM8750_IFACE) & 0x1f3; u16 srate = wm8750_read_reg_cache(codec, WM8750_SRATE) & 0x1c0; @@ -712,7 +712,7 @@ static void wm8750_work(struct work_struct *work) static int wm8750_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; @@ -721,7 +721,7 @@ static int wm8750_suspend(struct platform_device *pdev, pm_message_t state) static int wm8750_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -754,7 +754,7 @@ static int wm8750_resume(struct platform_device *pdev) */ static int wm8750_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int reg, ret = 0; codec->name = "WM8750"; @@ -836,7 +836,7 @@ static int wm8750_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = wm8750_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -917,7 +917,7 @@ err_driver: static int __devinit wm8750_spi_probe(struct spi_device *spi) { struct snd_soc_device *socdev = wm8750_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; codec->control_data = spi; @@ -989,7 +989,7 @@ static int wm8750_probe(struct platform_device *pdev) } codec->private_data = wm8750; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -1043,7 +1043,7 @@ static int run_delayed_work(struct delayed_work *dwork) static int wm8750_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 5a1c1fca120..502766dce86 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -912,7 +912,7 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm8753_priv *wm8753 = codec->private_data; u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3; u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f; @@ -1146,7 +1146,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm8753_priv *wm8753 = codec->private_data; u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0; u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3; @@ -1483,7 +1483,7 @@ static void wm8753_work(struct work_struct *work) static int wm8753_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; /* we only need to suspend if we are a valid card */ if (!codec->card) @@ -1496,7 +1496,7 @@ static int wm8753_suspend(struct platform_device *pdev, pm_message_t state) static int wm8753_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -1533,7 +1533,7 @@ static int wm8753_resume(struct platform_device *pdev) */ static int wm8753_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int reg, ret = 0; codec->name = "WM8753"; @@ -1624,7 +1624,7 @@ static int wm8753_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = wm8753_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -1705,7 +1705,7 @@ err_driver: static int __devinit wm8753_spi_probe(struct spi_device *spi) { struct snd_soc_device *socdev = wm8753_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; codec->control_data = spi; @@ -1780,7 +1780,7 @@ static int wm8753_probe(struct platform_device *pdev) } codec->private_data = wm8753; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -1832,7 +1832,7 @@ static int run_delayed_work(struct delayed_work *dwork) static int wm8753_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 1e08d4f065f..85c0f1bc676 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -720,7 +720,7 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u16 reg; reg = wm8900_read(codec, WM8900_REG_AUDIO1) & ~0x60; @@ -1210,7 +1210,7 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec, static int wm8900_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm8900_priv *wm8900 = codec->private_data; int fll_out = wm8900->fll_out; int fll_in = wm8900->fll_in; @@ -1234,7 +1234,7 @@ static int wm8900_suspend(struct platform_device *pdev, pm_message_t state) static int wm8900_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm8900_priv *wm8900 = codec->private_data; u16 *cache; int i, ret; @@ -1414,7 +1414,7 @@ static int wm8900_probe(struct platform_device *pdev) } codec = wm8900_codec; - socdev->codec = codec; + socdev->card->codec = codec; /* Register pcms */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 6ff34b957dc..d36b2b1edf1 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -1261,7 +1261,7 @@ static int wm8903_startup(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm8903_priv *wm8903 = codec->private_data; struct i2c_client *i2c = codec->control_data; struct snd_pcm_runtime *master_runtime; @@ -1303,7 +1303,7 @@ static void wm8903_shutdown(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm8903_priv *wm8903 = codec->private_data; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -1323,7 +1323,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm8903_priv *wm8903 = codec->private_data; struct i2c_client *i2c = codec->control_data; int fs = params_rate(params); @@ -1527,7 +1527,7 @@ EXPORT_SYMBOL_GPL(wm8903_dai); static int wm8903_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); @@ -1537,7 +1537,7 @@ static int wm8903_suspend(struct platform_device *pdev, pm_message_t state) static int wm8903_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct i2c_client *i2c = codec->control_data; int i; u16 *reg_cache = codec->reg_cache; @@ -1713,7 +1713,7 @@ static int wm8903_probe(struct platform_device *pdev) goto err; } - socdev->codec = wm8903_codec; + socdev->card->codec = wm8903_codec; /* register pcms */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); @@ -1722,9 +1722,9 @@ static int wm8903_probe(struct platform_device *pdev) goto err; } - snd_soc_add_controls(socdev->codec, wm8903_snd_controls, + snd_soc_add_controls(socdev->card->codec, wm8903_snd_controls, ARRAY_SIZE(wm8903_snd_controls)); - wm8903_add_widgets(socdev->codec); + wm8903_add_widgets(socdev->card->codec); ret = snd_soc_init_card(socdev); if (ret < 0) { @@ -1745,7 +1745,7 @@ err: static int wm8903_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index c8bd9b06f33..24d4c905a01 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -531,7 +531,7 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm8971_priv *wm8971 = codec->private_data; u16 iface = wm8971_read_reg_cache(codec, WM8971_IFACE) & 0x1f3; u16 srate = wm8971_read_reg_cache(codec, WM8971_SRATE) & 0x1c0; @@ -637,7 +637,7 @@ static void wm8971_work(struct work_struct *work) static int wm8971_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; @@ -646,7 +646,7 @@ static int wm8971_suspend(struct platform_device *pdev, pm_message_t state) static int wm8971_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -677,7 +677,7 @@ static int wm8971_resume(struct platform_device *pdev) static int wm8971_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int reg, ret = 0; codec->name = "WM8971"; @@ -758,7 +758,7 @@ static int wm8971_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = wm8971_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -859,7 +859,7 @@ static int wm8971_probe(struct platform_device *pdev) } codec->private_data = wm8971; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -894,7 +894,7 @@ static int wm8971_probe(struct platform_device *pdev) static int wm8971_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index f93c0955ed9..6af1d399b31 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -1162,7 +1162,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u16 audio1 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_1); audio1 &= ~WM8990_AIF_WL_MASK; @@ -1361,7 +1361,7 @@ EXPORT_SYMBOL_GPL(wm8990_dai); static int wm8990_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; /* we only need to suspend if we are a valid card */ if (!codec->card) @@ -1374,7 +1374,7 @@ static int wm8990_suspend(struct platform_device *pdev, pm_message_t state) static int wm8990_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -1402,7 +1402,7 @@ static int wm8990_resume(struct platform_device *pdev) */ static int wm8990_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u16 reg; int ret = 0; @@ -1480,7 +1480,7 @@ static int wm8990_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = wm8990_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -1579,7 +1579,7 @@ static int wm8990_probe(struct platform_device *pdev) } codec->private_data = wm8990; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -1605,7 +1605,7 @@ static int wm8990_probe(struct platform_device *pdev) static int wm8990_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index d5c81bb3dec..2e9e06b2daa 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c @@ -249,7 +249,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int reg; u16 vra; @@ -323,10 +323,11 @@ static int wm9705_soc_probe(struct platform_device *pdev) printk(KERN_INFO "WM9705 SoC Audio Codec\n"); - socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (socdev->codec == NULL) + socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), + GFP_KERNEL); + if (socdev->card->codec == NULL) return -ENOMEM; - codec = socdev->codec; + codec = socdev->card->codec; mutex_init(&codec->mutex); codec->reg_cache = kmemdup(wm9705_reg, sizeof(wm9705_reg), GFP_KERNEL); @@ -380,15 +381,15 @@ pcm_err: codec_err: kfree(codec->reg_cache); cache_err: - kfree(socdev->codec); - socdev->codec = NULL; + kfree(socdev->card->codec); + socdev->card->codec = NULL; return ret; } static int wm9705_soc_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec == NULL) return 0; diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 4dc90d67530..b3a8be77676 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -478,7 +478,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int reg; u16 vra; @@ -499,7 +499,7 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u16 vra, xsle; vra = ac97_read(codec, AC97_EXTENDED_STATUS); @@ -592,7 +592,7 @@ static int wm9712_soc_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; wm9712_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; @@ -601,7 +601,7 @@ static int wm9712_soc_suspend(struct platform_device *pdev, static int wm9712_soc_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int i, ret; u16 *cache = codec->reg_cache; @@ -637,10 +637,11 @@ static int wm9712_soc_probe(struct platform_device *pdev) printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION); - socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (socdev->codec == NULL) + socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), + GFP_KERNEL); + if (socdev->card->codec == NULL) return -ENOMEM; - codec = socdev->codec; + codec = socdev->card->codec; mutex_init(&codec->mutex); codec->reg_cache = kmemdup(wm9712_reg, sizeof(wm9712_reg), GFP_KERNEL); @@ -704,15 +705,15 @@ codec_err: kfree(codec->reg_cache); cache_err: - kfree(socdev->codec); - socdev->codec = NULL; + kfree(socdev->card->codec); + socdev->card->codec = NULL; return ret; } static int wm9712_soc_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec == NULL) return 0; diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 0e60e16973d..54db9c52498 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -1115,7 +1115,7 @@ static int wm9713_soc_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u16 reg; /* Disable everything except touchpanel - that will be handled @@ -1133,7 +1133,7 @@ static int wm9713_soc_suspend(struct platform_device *pdev, static int wm9713_soc_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm9713_priv *wm9713 = codec->private_data; int i, ret; u16 *cache = codec->reg_cache; @@ -1174,10 +1174,11 @@ static int wm9713_soc_probe(struct platform_device *pdev) printk(KERN_INFO "WM9713/WM9714 SoC Audio Codec %s\n", WM9713_VERSION); - socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (socdev->codec == NULL) + socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), + GFP_KERNEL); + if (socdev->card->codec == NULL) return -ENOMEM; - codec = socdev->codec; + codec = socdev->card->codec; mutex_init(&codec->mutex); codec->reg_cache = kmemdup(wm9713_reg, sizeof(wm9713_reg), GFP_KERNEL); @@ -1249,15 +1250,15 @@ priv_err: kfree(codec->reg_cache); cache_err: - kfree(socdev->codec); - socdev->codec = NULL; + kfree(socdev->card->codec); + socdev->card->codec = NULL; return ret; } static int wm9713_soc_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec == NULL) return 0; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 8313d52a6e8..f18c7a3e36d 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -234,7 +234,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) cpu_dai->capture.active = codec_dai->capture.active = 1; cpu_dai->active = codec_dai->active = 1; cpu_dai->runtime = runtime; - socdev->codec->active++; + card->codec->active++; mutex_unlock(&pcm_mutex); return 0; @@ -264,7 +264,7 @@ static void close_delayed_work(struct work_struct *work) struct snd_soc_card *card = container_of(work, struct snd_soc_card, delayed_work.work); struct snd_soc_device *socdev = card->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = card->codec; struct snd_soc_dai *codec_dai; int i; @@ -319,7 +319,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream) struct snd_soc_platform *platform = card->platform; struct snd_soc_dai *cpu_dai = machine->cpu_dai; struct snd_soc_dai *codec_dai = machine->codec_dai; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = card->codec; mutex_lock(&pcm_mutex); @@ -387,7 +387,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) struct snd_soc_platform *platform = card->platform; struct snd_soc_dai *cpu_dai = machine->cpu_dai; struct snd_soc_dai *codec_dai = machine->codec_dai; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = card->codec; int ret = 0; mutex_lock(&pcm_mutex); @@ -553,7 +553,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) struct snd_soc_platform *platform = card->platform; struct snd_soc_dai *cpu_dai = machine->cpu_dai; struct snd_soc_dai *codec_dai = machine->codec_dai; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = card->codec; mutex_lock(&pcm_mutex); @@ -629,7 +629,7 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state) struct snd_soc_card *card = socdev->card; struct snd_soc_platform *platform = card->platform; struct snd_soc_codec_device *codec_dev = socdev->codec_dev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = card->codec; int i; /* Due to the resume being scheduled into a workqueue we could @@ -705,7 +705,7 @@ static void soc_resume_deferred(struct work_struct *work) struct snd_soc_device *socdev = card->socdev; struct snd_soc_platform *platform = card->platform; struct snd_soc_codec_device *codec_dev = socdev->codec_dev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = card->codec; struct platform_device *pdev = to_platform_device(socdev->dev); int i; @@ -982,8 +982,8 @@ static struct platform_driver soc_driver = { static int soc_new_pcm(struct snd_soc_device *socdev, struct snd_soc_dai_link *dai_link, int num) { - struct snd_soc_codec *codec = socdev->codec; struct snd_soc_card *card = socdev->card; + struct snd_soc_codec *codec = card->codec; struct snd_soc_platform *platform = card->platform; struct snd_soc_dai *codec_dai = dai_link->codec_dai; struct snd_soc_dai *cpu_dai = dai_link->cpu_dai; @@ -998,7 +998,7 @@ static int soc_new_pcm(struct snd_soc_device *socdev, rtd->dai = dai_link; rtd->socdev = socdev; - codec_dai->codec = socdev->codec; + codec_dai->codec = card->codec; /* check client and interface hw capabilities */ sprintf(new_name, "%s %s-%d", dai_link->stream_name, codec_dai->name, @@ -1048,9 +1048,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev, } /* codec register dump */ -static ssize_t soc_codec_reg_show(struct snd_soc_device *devdata, char *buf) +static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) { - struct snd_soc_codec *codec = devdata->codec; int i, step = 1, count = 0; if (!codec->reg_cache_size) @@ -1090,7 +1089,7 @@ static ssize_t codec_reg_show(struct device *dev, struct device_attribute *attr, char *buf) { struct snd_soc_device *devdata = dev_get_drvdata(dev); - return soc_codec_reg_show(devdata, buf); + return soc_codec_reg_show(devdata->card->codec, buf); } static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); @@ -1107,12 +1106,10 @@ static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf, { ssize_t ret; struct snd_soc_codec *codec = file->private_data; - struct device *card_dev = codec->card->dev; - struct snd_soc_device *devdata = card_dev->driver_data; char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; - ret = soc_codec_reg_show(devdata, buf); + ret = soc_codec_reg_show(codec, buf); if (ret >= 0) ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); kfree(buf); @@ -1309,8 +1306,8 @@ EXPORT_SYMBOL_GPL(snd_soc_test_bits); */ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid) { - struct snd_soc_codec *codec = socdev->codec; struct snd_soc_card *card = socdev->card; + struct snd_soc_codec *codec = card->codec; int ret = 0, i; mutex_lock(&codec->mutex); @@ -1355,8 +1352,8 @@ EXPORT_SYMBOL_GPL(snd_soc_new_pcms); */ int snd_soc_init_card(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; struct snd_soc_card *card = socdev->card; + struct snd_soc_codec *codec = card->codec; int ret = 0, i, ac97 = 0, err = 0; for (i = 0; i < card->num_links; i++) { @@ -1404,7 +1401,7 @@ int snd_soc_init_card(struct snd_soc_device *socdev) if (err < 0) printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); - soc_init_codec_debugfs(socdev->codec); + soc_init_codec_debugfs(codec); mutex_unlock(&codec->mutex); out: @@ -1421,14 +1418,14 @@ EXPORT_SYMBOL_GPL(snd_soc_init_card); */ void snd_soc_free_pcms(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; #ifdef CONFIG_SND_SOC_AC97_BUS struct snd_soc_dai *codec_dai; int i; #endif mutex_lock(&codec->mutex); - soc_cleanup_codec_debugfs(socdev->codec); + soc_cleanup_codec_debugfs(codec); #ifdef CONFIG_SND_SOC_AC97_BUS for (i = 0; i < codec->num_dai; i++) { codec_dai = &codec->dai[i]; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 54b4564b82b..f4a8753c84c 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -817,7 +817,7 @@ static ssize_t dapm_widget_show(struct device *dev, struct device_attribute *attr, char *buf) { struct snd_soc_device *devdata = dev_get_drvdata(dev); - struct snd_soc_codec *codec = devdata->codec; + struct snd_soc_codec *codec = devdata->card->codec; struct snd_soc_dapm_widget *w; int count = 0; char *state = "not set"; @@ -1552,8 +1552,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event); int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev, enum snd_soc_bias_level level) { - struct snd_soc_codec *codec = socdev->codec; struct snd_soc_card *card = socdev->card; + struct snd_soc_codec *codec = socdev->card->codec; int ret = 0; if (card->set_bias_level) @@ -1645,7 +1645,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status); */ void snd_soc_dapm_free(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; snd_soc_dapm_sys_remove(socdev->dev); dapm_free_widgets(codec); diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index 8cc00c3cdf3..ab64a30bedd 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c @@ -34,7 +34,7 @@ int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type, jack->card = card; INIT_LIST_HEAD(&jack->pins); - return snd_jack_new(card->socdev->codec->card, id, type, &jack->jack); + return snd_jack_new(card->codec->card, id, type, &jack->jack); } EXPORT_SYMBOL_GPL(snd_soc_jack_new); @@ -54,7 +54,7 @@ EXPORT_SYMBOL_GPL(snd_soc_jack_new); */ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) { - struct snd_soc_codec *codec = jack->card->socdev->codec; + struct snd_soc_codec *codec = jack->card->codec; struct snd_soc_jack_pin *pin; int enable; int oldstatus; -- GitLab From b9d710b3c530ed91e8683933fe94c7605d175bf5 Mon Sep 17 00:00:00 2001 From: Andreas Bergmeier Date: Sat, 24 Jan 2009 12:15:14 +0100 Subject: [PATCH 0489/4982] ALSA: usbaudio - use printf format instead of hardcoding it Rather use printf format instead of hardcoding prefix like 0x. A next step would be to predefine certain formats. Signed-off-by: Andreas Bergmeier Signed-off-by: Takashi Iwai --- sound/usb/usbaudio.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 44485b29f67..4636926d12d 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -1280,14 +1280,14 @@ static int init_usb_sample_rate(struct usb_device *dev, int iface, if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) { - snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep 0x%x\n", + snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n", dev->devnum, iface, fmt->altsetting, rate, ep); return err; } if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN, SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) { - snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep 0x%x\n", + snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n", dev->devnum, iface, fmt->altsetting, ep); return 0; /* some devices don't support reading */ } @@ -1456,7 +1456,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, channels = params_channels(hw_params); fmt = find_format(subs, format, rate, channels); if (!fmt) { - snd_printd(KERN_DEBUG "cannot set format: format = 0x%x, rate = %d, channels = %d\n", + snd_printd(KERN_DEBUG "cannot set format: format = %#x, rate = %d, channels = %d\n", format, rate, channels); return -EINVAL; } @@ -2148,7 +2148,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s fp = list_entry(p, struct audioformat, list); snd_iprintf(buffer, " Interface %d\n", fp->iface); snd_iprintf(buffer, " Altset %d\n", fp->altsetting); - snd_iprintf(buffer, " Format: 0x%x\n", fp->format); + snd_iprintf(buffer, " Format: %#x\n", fp->format); snd_iprintf(buffer, " Channels: %d\n", fp->channels); snd_iprintf(buffer, " Endpoint: %d %s (%s)\n", fp->endpoint & USB_ENDPOINT_NUMBER_MASK, @@ -2168,7 +2168,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s snd_iprintf(buffer, "\n"); } // snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize); - // snd_iprintf(buffer, " EP Attribute = 0x%x\n", fp->attributes); + // snd_iprintf(buffer, " EP Attribute = %#x\n", fp->attributes); } } @@ -2607,7 +2607,7 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, struct audioformat fp->format = SNDRV_PCM_FORMAT_MPEG; break; default: - snd_printd(KERN_INFO "%d:%u:%d : unknown format tag 0x%x is detected. processed as MPEG.\n", + snd_printd(KERN_INFO "%d:%u:%d : unknown format tag %#x is detected. processed as MPEG.\n", chip->dev->devnum, fp->iface, fp->altsetting, format); fp->format = SNDRV_PCM_FORMAT_MPEG; break; @@ -2805,7 +2805,7 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) continue; } - snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint 0x%x\n", dev->devnum, iface_no, altno, fp->endpoint); + snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint); err = add_audio_endpoint(chip, stream, fp); if (err < 0) { kfree(fp->rate_table); -- GitLab From 3fc93030e5a792fdd0da3321487f5cbfd1143c2b Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 27 Jan 2009 11:29:39 +0200 Subject: [PATCH 0490/4982] ASoC: TWL4030: Syncronize the reg_cache for ANAMICL after the offset cancelation The offset cancelation bit in ANAMICL register is self cleanig. Make sure that the reg_cache holds the same value as the HW register. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/codecs/twl4030.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 796f34cac85..24419afd319 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -913,6 +913,9 @@ static void twl4030_power_up(struct snd_soc_codec *codec) ((byte & TWL4030_CNCL_OFFSET_START) == TWL4030_CNCL_OFFSET_START)); + /* Make sure that the reg_cache has the same value as the HW */ + twl4030_write_reg_cache(codec, TWL4030_REG_ANAMICL, byte); + /* anti-pop when changing analog gain */ regmisc1 = twl4030_read_reg_cache(codec, TWL4030_REG_MISC_SET_1); twl4030_write(codec, TWL4030_REG_MISC_SET_1, -- GitLab From db04e2c58a65364218b89f1372b4b3b78d206423 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 27 Jan 2009 11:29:40 +0200 Subject: [PATCH 0491/4982] ASoC: TWL4030: Code clean up for codec power up and down Merge the codec up and down functions to a simple one. Codec is powered down by default (reg_cache change). Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/codecs/twl4030.c | 43 +++++++++++++++----------------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 24419afd319..af7b433d4f5 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -42,7 +42,7 @@ */ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = { 0x00, /* this register not used */ - 0x93, /* REG_CODEC_MODE (0x1) */ + 0x91, /* REG_CODEC_MODE (0x1) */ 0xc3, /* REG_OPTION (0x2) */ 0x00, /* REG_UNKNOWN (0x3) */ 0x00, /* REG_MICBIAS_CTL (0x4) */ @@ -154,26 +154,17 @@ static int twl4030_write(struct snd_soc_codec *codec, return twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg); } -static void twl4030_clear_codecpdz(struct snd_soc_codec *codec) +static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) { u8 mode; mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE); - twl4030_write(codec, TWL4030_REG_CODEC_MODE, - mode & ~TWL4030_CODECPDZ); + if (enable) + mode |= TWL4030_CODECPDZ; + else + mode &= ~TWL4030_CODECPDZ; - /* REVISIT: this delay is present in TI sample drivers */ - /* but there seems to be no TRM requirement for it */ - udelay(10); -} - -static void twl4030_set_codecpdz(struct snd_soc_codec *codec) -{ - u8 mode; - - mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE); - twl4030_write(codec, TWL4030_REG_CODEC_MODE, - mode | TWL4030_CODECPDZ); + twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode); /* REVISIT: this delay is present in TI sample drivers */ /* but there seems to be no TRM requirement for it */ @@ -185,7 +176,7 @@ static void twl4030_init_chip(struct snd_soc_codec *codec) int i; /* clear CODECPDZ prior to setting register defaults */ - twl4030_clear_codecpdz(codec); + twl4030_codec_enable(codec, 0); /* set all audio section registers to reasonable defaults */ for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++) @@ -895,7 +886,7 @@ static void twl4030_power_up(struct snd_soc_codec *codec) int i = 0; /* set CODECPDZ to turn on codec */ - twl4030_set_codecpdz(codec); + twl4030_codec_enable(codec, 1); /* initiate offset cancellation */ anamicl = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL); @@ -922,8 +913,8 @@ static void twl4030_power_up(struct snd_soc_codec *codec) regmisc1 | TWL4030_SMOOTH_ANAVOL_EN); /* toggle CODECPDZ as per TRM */ - twl4030_clear_codecpdz(codec); - twl4030_set_codecpdz(codec); + twl4030_codec_enable(codec, 0); + twl4030_codec_enable(codec, 1); /* program anti-pop with bias ramp delay */ popn = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); @@ -952,7 +943,7 @@ static void twl4030_power_down(struct snd_soc_codec *codec) twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn); /* power down */ - twl4030_clear_codecpdz(codec); + twl4030_codec_enable(codec, 0); } static int twl4030_set_bias_level(struct snd_soc_codec *codec, @@ -1030,7 +1021,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream, if (mode != old_mode) { /* change rate and set CODECPDZ */ twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode); - twl4030_set_codecpdz(codec); + twl4030_codec_enable(codec, 1); } /* sample size */ @@ -1053,13 +1044,13 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream, if (format != old_format) { /* clear CODECPDZ before changing format (codec requirement) */ - twl4030_clear_codecpdz(codec); + twl4030_codec_enable(codec, 0); /* change format */ twl4030_write(codec, TWL4030_REG_AUDIO_IF, format); /* set CODECPDZ afterwards */ - twl4030_set_codecpdz(codec); + twl4030_codec_enable(codec, 1); } return 0; } @@ -1129,13 +1120,13 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai, if (format != old_format) { /* clear CODECPDZ before changing format (codec requirement) */ - twl4030_clear_codecpdz(codec); + twl4030_codec_enable(codec, 0); /* change format */ twl4030_write(codec, TWL4030_REG_AUDIO_IF, format); /* set CODECPDZ afterwards */ - twl4030_set_codecpdz(codec); + twl4030_codec_enable(codec, 1); } return 0; -- GitLab From aad749e51a66d473f5cef4a050e3e36795261be3 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 27 Jan 2009 11:29:41 +0200 Subject: [PATCH 0492/4982] ASoC: TWL4030: Enable Headset Left anti-pop/bias ramp only if the Headset Left is in use The Headset Left anti-pop and bias ramp does not need to be enabled, if the headset is not in use. Move the code to DAPM event handler for HeadsetL. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/codecs/twl4030.c | 71 ++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 26 deletions(-) diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index af7b433d4f5..900486ef633 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -414,6 +414,47 @@ static int handsfree_event(struct snd_soc_dapm_widget *w, return 0; } +static int headsetl_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + unsigned char hs_gain, hs_pop; + + /* Save the current volume */ + hs_gain = twl4030_read_reg_cache(w->codec, TWL4030_REG_HS_GAIN_SET); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + /* Do the anti-pop/bias ramp enable according to the TRM */ + hs_pop = TWL4030_RAMP_DELAY_645MS; + twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); + hs_pop |= TWL4030_VMID_EN; + twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); + /* Is this needed? Can we just use whatever gain here? */ + twl4030_write(w->codec, TWL4030_REG_HS_GAIN_SET, + (hs_gain & (~0x0f)) | 0x0a); + hs_pop |= TWL4030_RAMP_EN; + twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); + + /* Restore the original volume */ + twl4030_write(w->codec, TWL4030_REG_HS_GAIN_SET, hs_gain); + break; + case SND_SOC_DAPM_POST_PMD: + /* Do the anti-pop/bias ramp disable according to the TRM */ + hs_pop = twl4030_read_reg_cache(w->codec, + TWL4030_REG_HS_POPN_SET); + hs_pop &= ~TWL4030_RAMP_EN; + twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); + /* Bypass the reg_cache to mute the headset */ + twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + hs_gain & (~0x0f), + TWL4030_REG_HS_GAIN_SET); + hs_pop &= ~TWL4030_VMID_EN; + twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); + break; + } + return 0; +} + /* * Some of the gain controls in TWL (mostly those which are associated with * the outputs) are implemented in an interesting way: @@ -720,8 +761,9 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { SND_SOC_DAPM_VALUE_MUX("PredriveR Mux", SND_SOC_NOPM, 0, 0, &twl4030_dapm_predriver_control), /* HeadsetL/R */ - SND_SOC_DAPM_MUX("HeadsetL Mux", SND_SOC_NOPM, 0, 0, - &twl4030_dapm_hsol_control), + SND_SOC_DAPM_MUX_E("HeadsetL Mux", SND_SOC_NOPM, 0, 0, + &twl4030_dapm_hsol_control, headsetl_event, + SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MUX("HeadsetR Mux", SND_SOC_NOPM, 0, 0, &twl4030_dapm_hsor_control), /* CarkitL/R */ @@ -882,7 +924,7 @@ static int twl4030_add_widgets(struct snd_soc_codec *codec) static void twl4030_power_up(struct snd_soc_codec *codec) { - u8 anamicl, regmisc1, byte, popn; + u8 anamicl, regmisc1, byte; int i = 0; /* set CODECPDZ to turn on codec */ @@ -915,33 +957,10 @@ static void twl4030_power_up(struct snd_soc_codec *codec) /* toggle CODECPDZ as per TRM */ twl4030_codec_enable(codec, 0); twl4030_codec_enable(codec, 1); - - /* program anti-pop with bias ramp delay */ - popn = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); - popn &= TWL4030_RAMP_DELAY; - popn |= TWL4030_RAMP_DELAY_645MS; - twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn); - popn |= TWL4030_VMID_EN; - twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn); - - /* enable anti-pop ramp */ - popn |= TWL4030_RAMP_EN; - twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn); } static void twl4030_power_down(struct snd_soc_codec *codec) { - u8 popn; - - /* disable anti-pop ramp */ - popn = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); - popn &= ~TWL4030_RAMP_EN; - twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn); - - /* disable bias out */ - popn &= ~TWL4030_VMID_EN; - twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn); - /* power down */ twl4030_codec_enable(codec, 0); } -- GitLab From fb2a2f84908460c18c3894963990518b224dd9ff Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 27 Jan 2009 11:29:42 +0200 Subject: [PATCH 0493/4982] ASoC: TWL4030: Physical ADC and amplifier power switch change Change the power switches for the physical ADC and for the amplifiers for the analog capture path to map more closely the actual path inside of the codec. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/codecs/twl4030.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 900486ef633..8fe059e3e9a 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -802,16 +802,16 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD| SND_SOC_DAPM_POST_REG), - /* Analog input muxes with power switch for the physical ADCL/R */ + /* Analog input muxes with switch for the capture amplifiers */ SND_SOC_DAPM_VALUE_MUX("Analog Left Capture Route", - TWL4030_REG_AVADC_CTL, 3, 0, &twl4030_dapm_analoglmic_control), + TWL4030_REG_ANAMICL, 4, 0, &twl4030_dapm_analoglmic_control), SND_SOC_DAPM_VALUE_MUX("Analog Right Capture Route", - TWL4030_REG_AVADC_CTL, 1, 0, &twl4030_dapm_analogrmic_control), + TWL4030_REG_ANAMICR, 4, 0, &twl4030_dapm_analogrmic_control), - SND_SOC_DAPM_PGA("Analog Left Amplifier", - TWL4030_REG_ANAMICL, 4, 0, NULL, 0), - SND_SOC_DAPM_PGA("Analog Right Amplifier", - TWL4030_REG_ANAMICR, 4, 0, NULL, 0), + SND_SOC_DAPM_PGA("ADC Physical Left", + TWL4030_REG_AVADC_CTL, 3, 0, NULL, 0), + SND_SOC_DAPM_PGA("ADC Physical Right", + TWL4030_REG_AVADC_CTL, 1, 0, NULL, 0), SND_SOC_DAPM_PGA("Digimic0 Enable", TWL4030_REG_ADCMICSEL, 1, 0, NULL, 0), @@ -885,23 +885,23 @@ static const struct snd_soc_dapm_route intercon[] = { {"Analog Right Capture Route", "Sub mic", "SUBMIC"}, {"Analog Right Capture Route", "AUXR", "AUXR"}, - {"Analog Left Amplifier", NULL, "Analog Left Capture Route"}, - {"Analog Right Amplifier", NULL, "Analog Right Capture Route"}, + {"ADC Physical Left", NULL, "Analog Left Capture Route"}, + {"ADC Physical Right", NULL, "Analog Right Capture Route"}, {"Digimic0 Enable", NULL, "DIGIMIC0"}, {"Digimic1 Enable", NULL, "DIGIMIC1"}, /* TX1 Left capture path */ - {"TX1 Capture Route", "Analog", "Analog Left Amplifier"}, + {"TX1 Capture Route", "Analog", "ADC Physical Left"}, {"TX1 Capture Route", "Digimic0", "Digimic0 Enable"}, /* TX1 Right capture path */ - {"TX1 Capture Route", "Analog", "Analog Right Amplifier"}, + {"TX1 Capture Route", "Analog", "ADC Physical Right"}, {"TX1 Capture Route", "Digimic0", "Digimic0 Enable"}, /* TX2 Left capture path */ - {"TX2 Capture Route", "Analog", "Analog Left Amplifier"}, + {"TX2 Capture Route", "Analog", "ADC Physical Left"}, {"TX2 Capture Route", "Digimic1", "Digimic1 Enable"}, /* TX2 Right capture path */ - {"TX2 Capture Route", "Analog", "Analog Right Amplifier"}, + {"TX2 Capture Route", "Analog", "ADC Physical Right"}, {"TX2 Capture Route", "Digimic1", "Digimic1 Enable"}, {"ADC Virtual Left1", NULL, "TX1 Capture Route"}, -- GitLab From 006f367e38fb45e2f161c0f500c74449ae63e866 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 27 Jan 2009 11:29:43 +0200 Subject: [PATCH 0494/4982] ASoC: TWL4030: Move the twl4030_power_up and _power_down function Move the twl4030_power_up and twl4030_power_down function earlier to facilitate the analog bypass implementation. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/codecs/twl4030.c | 85 +++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 43 deletions(-) diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 8fe059e3e9a..f985bef40a3 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -184,6 +184,48 @@ static void twl4030_init_chip(struct snd_soc_codec *codec) } +static void twl4030_power_up(struct snd_soc_codec *codec) +{ + u8 anamicl, regmisc1, byte; + int i = 0; + + /* set CODECPDZ to turn on codec */ + twl4030_codec_enable(codec, 1); + + /* initiate offset cancellation */ + anamicl = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL); + twl4030_write(codec, TWL4030_REG_ANAMICL, + anamicl | TWL4030_CNCL_OFFSET_START); + + /* wait for offset cancellation to complete */ + do { + /* this takes a little while, so don't slam i2c */ + udelay(2000); + twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, + TWL4030_REG_ANAMICL); + } while ((i++ < 100) && + ((byte & TWL4030_CNCL_OFFSET_START) == + TWL4030_CNCL_OFFSET_START)); + + /* Make sure that the reg_cache has the same value as the HW */ + twl4030_write_reg_cache(codec, TWL4030_REG_ANAMICL, byte); + + /* anti-pop when changing analog gain */ + regmisc1 = twl4030_read_reg_cache(codec, TWL4030_REG_MISC_SET_1); + twl4030_write(codec, TWL4030_REG_MISC_SET_1, + regmisc1 | TWL4030_SMOOTH_ANAVOL_EN); + + /* toggle CODECPDZ as per TRM */ + twl4030_codec_enable(codec, 0); + twl4030_codec_enable(codec, 1); +} + +static void twl4030_power_down(struct snd_soc_codec *codec) +{ + /* power down */ + twl4030_codec_enable(codec, 0); +} + /* Earpiece */ static const char *twl4030_earpiece_texts[] = {"Off", "DACL1", "DACL2", "DACR1"}; @@ -922,49 +964,6 @@ static int twl4030_add_widgets(struct snd_soc_codec *codec) return 0; } -static void twl4030_power_up(struct snd_soc_codec *codec) -{ - u8 anamicl, regmisc1, byte; - int i = 0; - - /* set CODECPDZ to turn on codec */ - twl4030_codec_enable(codec, 1); - - /* initiate offset cancellation */ - anamicl = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL); - twl4030_write(codec, TWL4030_REG_ANAMICL, - anamicl | TWL4030_CNCL_OFFSET_START); - - - /* wait for offset cancellation to complete */ - do { - /* this takes a little while, so don't slam i2c */ - udelay(2000); - twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, - TWL4030_REG_ANAMICL); - } while ((i++ < 100) && - ((byte & TWL4030_CNCL_OFFSET_START) == - TWL4030_CNCL_OFFSET_START)); - - /* Make sure that the reg_cache has the same value as the HW */ - twl4030_write_reg_cache(codec, TWL4030_REG_ANAMICL, byte); - - /* anti-pop when changing analog gain */ - regmisc1 = twl4030_read_reg_cache(codec, TWL4030_REG_MISC_SET_1); - twl4030_write(codec, TWL4030_REG_MISC_SET_1, - regmisc1 | TWL4030_SMOOTH_ANAVOL_EN); - - /* toggle CODECPDZ as per TRM */ - twl4030_codec_enable(codec, 0); - twl4030_codec_enable(codec, 1); -} - -static void twl4030_power_down(struct snd_soc_codec *codec) -{ - /* power down */ - twl4030_codec_enable(codec, 0); -} - static int twl4030_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { -- GitLab From 1e615df654ef00a6354f32be08a8fb6a395b2ef1 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 27 Jan 2009 21:47:47 +1100 Subject: [PATCH 0495/4982] solos: Kill existing connections on link down event Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 4c87dfb0156..c289b6251c1 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -132,6 +132,7 @@ static int fpga_tx(struct solos_card *); static irqreturn_t solos_irq(int irq, void *dev_id); static struct atm_vcc* find_vcc(struct atm_dev *dev, short vpi, int vci); static int list_vccs(int vci); +static void release_vccs(struct atm_dev *dev); static int atm_init(struct solos_card *); static void atm_remove(struct solos_card *); static int send_command(struct solos_card *card, int dev, const char *buf, size_t size); @@ -332,7 +333,10 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb str = next_string(skb); if (!strcmp(str, "Showtime")) state = ATM_PHY_SIG_FOUND; - else state = ATM_PHY_SIG_LOST; + else { + state = ATM_PHY_SIG_LOST; + release_vccs(card->atmdev[port]); + } card->atmdev[port]->link_rate = rate_down; card->atmdev[port]->signal = state; @@ -683,7 +687,7 @@ static int list_vccs(int vci) vcc->vci); } } else { - for(i=0; i<32; i++){ + for(i = 0; i < VCC_HTABLE_SIZE; i++){ head = &vcc_hash[i]; sk_for_each(s, node, head) { num_found ++; @@ -699,6 +703,28 @@ static int list_vccs(int vci) return num_found; } +static void release_vccs(struct atm_dev *dev) +{ + int i; + + write_lock_irq(&vcc_sklist_lock); + for (i = 0; i < VCC_HTABLE_SIZE; i++) { + struct hlist_head *head = &vcc_hash[i]; + struct hlist_node *node, *tmp; + struct sock *s; + struct atm_vcc *vcc; + + sk_for_each_safe(s, node, tmp, head) { + vcc = atm_sk(s); + if (vcc->dev == dev) { + vcc_release_async(vcc, -EPIPE); + sk_del_node_init(s); + } + } + } + write_unlock_irq(&vcc_sklist_lock); +} + static int popen(struct atm_vcc *vcc) { -- GitLab From b28a4b9a38b9d75caceb4f554bfdbb7a413b2ad0 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 27 Jan 2009 21:50:36 +1100 Subject: [PATCH 0496/4982] solos: Reject non-AAL5 connections.... for now Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index c289b6251c1..b500f00e184 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -732,6 +732,12 @@ static int popen(struct atm_vcc *vcc) struct sk_buff *skb; struct pkt_hdr *header; + if (vcc->qos.aal != ATM_AAL5) { + dev_warn(&card->dev->dev, "Unsupported ATM type %d\n", + vcc->qos.aal); + return -EINVAL; + } + skb = alloc_skb(sizeof(*header), GFP_ATOMIC); if (!skb && net_ratelimit()) { dev_warn(&card->dev->dev, "Failed to allocate sk_buff in popen()\n"); -- GitLab From 042cbaf88ab48e11afb725541e3c2cbf5b483680 Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Tue, 27 Jan 2009 21:45:57 +0100 Subject: [PATCH 0497/4982] x86 setup: fix asm constraints in vesa_store_edid Impact: fix potential miscompile (currently believed non-manifest) As the comment explains, the VBE DDC call can clobber any register. Tell the compiler about that fact. Signed-off-by: Andreas Schwab Signed-off-by: H. Peter Anvin --- arch/x86/boot/video-vesa.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/x86/boot/video-vesa.c b/arch/x86/boot/video-vesa.c index 75115849af3..4a58c8ce3f6 100644 --- a/arch/x86/boot/video-vesa.c +++ b/arch/x86/boot/video-vesa.c @@ -269,9 +269,8 @@ void vesa_store_edid(void) we genuinely have to assume all registers are destroyed here. */ asm("pushw %%es; movw %2,%%es; "INT10"; popw %%es" - : "+a" (ax), "+b" (bx) - : "c" (cx), "D" (di) - : "esi"); + : "+a" (ax), "+b" (bx), "+c" (cx), "+D" (di) + : : "esi", "edx"); if (ax != 0x004f) return; /* No EDID */ @@ -285,9 +284,9 @@ void vesa_store_edid(void) dx = 0; /* EDID block number */ di =(size_t) &boot_params.edid_info; /* (ES:)Pointer to block */ asm(INT10 - : "+a" (ax), "+b" (bx), "+d" (dx), "=m" (boot_params.edid_info) - : "c" (cx), "D" (di) - : "esi"); + : "+a" (ax), "+b" (bx), "+d" (dx), "=m" (boot_params.edid_info), + "+c" (cx), "+D" (di) + : : "esi"); #endif /* CONFIG_FIRMWARE_EDID */ } -- GitLab From 8f6d86dc4178957d9814b1784848012a927a3898 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 27 Jan 2009 21:41:34 +0100 Subject: [PATCH 0498/4982] x86: cpu_init(): remove ugly #ifdef construct around debug register clear Impact: Cleanup While I was looking through the new and improved bootstrap code - great work that, thanks! I found the below a slight improvement. Remove unnecessary ugly #ifdef construct around debug register clear. Signed-off-by: Peter Zijlstra Signed-off-by: H. Peter Anvin --- arch/x86/kernel/cpu/common.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index f0025846244..3f272d42d09 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1071,22 +1071,19 @@ void __cpuinit cpu_init(void) */ if (kgdb_connected && arch_kgdb_ops.correct_hw_break) arch_kgdb_ops.correct_hw_break(); - else { + else #endif - /* - * Clear all 6 debug registers: - */ - - set_debugreg(0UL, 0); - set_debugreg(0UL, 1); - set_debugreg(0UL, 2); - set_debugreg(0UL, 3); - set_debugreg(0UL, 6); - set_debugreg(0UL, 7); -#ifdef CONFIG_KGDB - /* If the kgdb is connected no debug regs should be altered. */ + { + /* + * Clear all 6 debug registers: + */ + set_debugreg(0UL, 0); + set_debugreg(0UL, 1); + set_debugreg(0UL, 2); + set_debugreg(0UL, 3); + set_debugreg(0UL, 6); + set_debugreg(0UL, 7); } -#endif fpu_init(); -- GitLab From af7806560c972b5b8c79e9704d7816813343cbc1 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 28 Jan 2009 10:22:57 +1100 Subject: [PATCH 0499/4982] solos: Add SNR and Attn to status packet, fix oops on load Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index b500f00e184..297869965fc 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -303,8 +303,8 @@ static char *next_string(struct sk_buff *skb) */ static int process_status(struct solos_card *card, int port, struct sk_buff *skb) { - char *str, *end; - int ver, rate_up, rate_down, state; + char *str, *end, *state_str; + int ver, rate_up, rate_down, state, snr, attn; if (!card->atmdev[port]) return -ENODEV; @@ -330,19 +330,35 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb if (*end) return -EIO; - str = next_string(skb); - if (!strcmp(str, "Showtime")) + state_str = next_string(skb); + if (!strcmp(state_str, "Showtime")) state = ATM_PHY_SIG_FOUND; else { state = ATM_PHY_SIG_LOST; release_vccs(card->atmdev[port]); } + str = next_string(skb); + snr = simple_strtol(str, &end, 10); + if (*end) + return -EIO; + + str = next_string(skb); + attn = simple_strtol(str, &end, 10); + if (*end) + return -EIO; + + if (state == ATM_PHY_SIG_LOST && !rate_up && !rate_down) + dev_info(&card->dev->dev, "Port %d ATM state: %s\n", + port, state_str); + else + dev_info(&card->dev->dev, "Port %d ATM state: %s (%d/%d kb/s, SNR %ddB, Attn %ddB)\n", + port, state_str, rate_up/1000, rate_down/1000, + snr, attn); + card->atmdev[port]->link_rate = rate_down; card->atmdev[port]->signal = state; - dev_info(&card->dev->dev, "ATM state: '%s', %d/%d kb/s up/down.\n", - str, rate_up/1000, rate_down/1000); return 0; } @@ -851,7 +867,7 @@ static int fpga_tx(struct solos_card *card) dev_vdbg(&card->dev->dev, "TX Flags are %X\n", tx_pending); for (port = 0; port < card->nr_ports; port++) { - if (!(tx_pending & (1 << port))) { + if (card->atmdev[port] && !(tx_pending & (1 << port))) { spin_lock(&card->tx_queue_lock); skb = skb_dequeue(&card->tx_queue[port]); -- GitLab From 3456b22111be920e15e6999b15d2f402a48e775d Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 28 Jan 2009 10:39:23 +1100 Subject: [PATCH 0500/4982] solos: Fix under-allocation of skb size for get/set parameters Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 297869965fc..2dca5ffc806 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -159,7 +159,7 @@ static ssize_t solos_param_show(struct device *dev, struct device_attribute *att buflen = strlen(attr->attr.name) + 10; - skb = alloc_skb(buflen, GFP_KERNEL); + skb = alloc_skb(sizeof(*header) + buflen, GFP_KERNEL); if (!skb) { dev_warn(&card->dev->dev, "Failed to allocate sk_buff in solos_param_show()\n"); return -ENOMEM; @@ -215,7 +215,7 @@ static ssize_t solos_param_store(struct device *dev, struct device_attribute *at buflen = strlen(attr->attr.name) + 11 + count; - skb = alloc_skb(buflen, GFP_KERNEL); + skb = alloc_skb(sizeof(*header) + buflen, GFP_KERNEL); if (!skb) { dev_warn(&card->dev->dev, "Failed to allocate sk_buff in solos_param_store()\n"); return -ENOMEM; -- GitLab From d5a9e24afb4ab38110ebb777588ea0bd0eacbd0a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 27 Jan 2009 16:22:11 -0800 Subject: [PATCH 0501/4982] net: Allow RX queue selection to seed TX queue hashing. The idea is that drivers which implement multiqueue RX pre-seed the SKB by recording the RX queue selected by the hardware. If such a seed is found on TX, we'll use that to select the outgoing TX queue. This helps get more consistent load balancing on router and firewall loads. Signed-off-by: David S. Miller --- include/linux/skbuff.h | 15 +++++++++++++++ net/core/dev.c | 8 ++++++++ 2 files changed, 23 insertions(+) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index cf2cb50f77d..a2c2378a9c5 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1904,6 +1904,21 @@ static inline void skb_copy_queue_mapping(struct sk_buff *to, const struct sk_bu to->queue_mapping = from->queue_mapping; } +static inline void skb_record_rx_queue(struct sk_buff *skb, u16 rx_queue) +{ + skb->queue_mapping = rx_queue + 1; +} + +static inline u16 skb_get_rx_queue(struct sk_buff *skb) +{ + return skb->queue_mapping - 1; +} + +static inline bool skb_rx_queue_recorded(struct sk_buff *skb) +{ + return (skb->queue_mapping != 0); +} + #ifdef CONFIG_XFRM static inline struct sec_path *skb_sec_path(struct sk_buff *skb) { diff --git a/net/core/dev.c b/net/core/dev.c index 5379b0c1190..b21ad0b47aa 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1722,6 +1722,13 @@ static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb) simple_tx_hashrnd_initialized = 1; } + if (skb_rx_queue_recorded(skb)) { + u32 val = skb_get_rx_queue(skb); + + hash = jhash_1word(val, simple_tx_hashrnd); + goto out; + } + switch (skb->protocol) { case htons(ETH_P_IP): if (!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET))) @@ -1759,6 +1766,7 @@ static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb) hash = jhash_3words(addr1, addr2, ports, simple_tx_hashrnd); +out: return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32); } -- GitLab From 0c8dfc830aadd978e461dad66c33741b71c6a0be Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 27 Jan 2009 16:22:32 -0800 Subject: [PATCH 0502/4982] net: Add skb_record_rx_queue() calls to multiqueue capable drivers. Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 2 ++ drivers/net/bnx2x_main.c | 1 + drivers/net/cxgb3/sge.c | 1 + drivers/net/igb/igb_main.c | 1 + drivers/net/ixgbe/ixgbe_main.c | 1 + drivers/net/mlx4/en_rx.c | 1 + drivers/net/myri10ge/myri10ge.c | 1 + drivers/net/niu.c | 1 + drivers/net/qlge/qlge_main.c | 1 + drivers/net/s2io.c | 1 + drivers/net/sfc/rx.c | 2 ++ 11 files changed, 13 insertions(+) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index fe575b9a9b7..49e0e51a9df 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -3007,6 +3007,8 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) skb->ip_summed = CHECKSUM_UNNECESSARY; } + skb_record_rx_queue(skb, bnapi - &bp->bnx2_napi[0]); + #ifdef BCM_VLAN if (hw_vlan) vlan_hwaccel_receive_skb(skb, bp->vlgrp, vtag); diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 71f81c79d63..88da14c141f 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -1325,6 +1325,7 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp, skb->protocol = eth_type_trans(skb, bp->dev); skb->ip_summed = CHECKSUM_UNNECESSARY; + skb_record_rx_queue(skb, queue); { struct iphdr *iph; diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 8299fb538f2..272a0168f3e 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -1937,6 +1937,7 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq, skb->ip_summed = CHECKSUM_UNNECESSARY; } else skb->ip_summed = CHECKSUM_NONE; + skb_record_rx_queue(skb, qs - &adap->sge.qs[0]); if (unlikely(p->vlan_valid)) { struct vlan_group *grp = pi->vlan_grp; diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index e11043d90db..bd166803671 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3751,6 +3751,7 @@ static void igb_receive_skb(struct igb_ring *ring, u8 status, struct igb_adapter * adapter = ring->adapter; bool vlan_extracted = (adapter->vlgrp && (status & E1000_RXD_STAT_VP)); + skb_record_rx_queue(skb, ring->queue_index); if (skb->ip_summed == CHECKSUM_UNNECESSARY) { if (vlan_extracted) vlan_gro_receive(&ring->napi, adapter->vlgrp, diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 43980dc45e3..fe4a4d17c4b 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -414,6 +414,7 @@ static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector, bool is_vlan = (status & IXGBE_RXD_STAT_VP); u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan); + skb_record_rx_queue(skb, q_vector - &adapter->q_vector[0]); if (skb->ip_summed == CHECKSUM_UNNECESSARY) { if (adapter->vlgrp && is_vlan && (tag != 0)) vlan_gro_receive(napi, adapter->vlgrp, tag, skb); diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c index ac55ebd2f14..a4130e76499 100644 --- a/drivers/net/mlx4/en_rx.c +++ b/drivers/net/mlx4/en_rx.c @@ -768,6 +768,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud skb->ip_summed = ip_summed; skb->protocol = eth_type_trans(skb, dev); + skb_record_rx_queue(skb, cq->ring); /* Push it up the stack */ if (priv->vlgrp && (be32_to_cpu(cqe->vlan_my_qpn) & diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 2dacb8852dc..aea9fdaa3cd 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -1324,6 +1324,7 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, struct myri10ge_rx_buf *rx, skb_shinfo(skb)->nr_frags = 0; } skb->protocol = eth_type_trans(skb, dev); + skb_record_rx_queue(skb, ss - &mgp->ss[0]); if (mgp->csum_flag) { if ((skb->protocol == htons(ETH_P_IP)) || diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 4a5a089fa30..2346ca6bf5b 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -3390,6 +3390,7 @@ static int niu_process_rx_pkt(struct niu *np, struct rx_ring_info *rp) rp->rx_bytes += skb->len; skb->protocol = eth_type_trans(skb, np->dev); + skb_record_rx_queue(skb, rp->rx_channel); netif_receive_skb(skb); return num_rcr; diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 16eb9dd8528..4ab6e72ea95 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -1436,6 +1436,7 @@ static void ql_process_mac_rx_intr(struct ql_adapter *qdev, qdev->stats.rx_packets++; qdev->stats.rx_bytes += skb->len; skb->protocol = eth_type_trans(skb, ndev); + skb_record_rx_queue(skb, rx_ring - &qdev->rx_ring[0]); if (qdev->vlgrp && (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V)) { QPRINTK(qdev, RX_STATUS, DEBUG, "Passing a VLAN packet upstream.\n"); diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 2a96a10fd0c..e0a353f4ec9 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -7542,6 +7542,7 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) sp->mac_control.stats_info->sw_stat.mem_freed += skb->truesize; send_up: + skb_record_rx_queue(skb, ring_no); queue_rx_frame(skb, RXD_GET_VLAN_TAG(rxdp->Control_2)); aggregate: sp->mac_control.rings[ring_no].rx_bufs_left -= 1; diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c index a0345b38097..66d7fe3db3e 100644 --- a/drivers/net/sfc/rx.c +++ b/drivers/net/sfc/rx.c @@ -575,6 +575,8 @@ void __efx_rx_packet(struct efx_channel *channel, /* Set the SKB flags */ skb->ip_summed = CHECKSUM_NONE; + skb_record_rx_queue(skb, channel->channel); + /* Pass the packet up */ netif_receive_skb(skb); -- GitLab From f7105d63940899ece79bda024f668e6c761cfebf Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 27 Jan 2009 16:27:48 -0800 Subject: [PATCH 0503/4982] net: If SKB has attached socket, use socket's hash for TX queue selection. Signed-off-by: David S. Miller --- net/core/dev.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/core/dev.c b/net/core/dev.c index b21ad0b47aa..cb8caa93cac 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1729,6 +1729,13 @@ static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb) goto out; } + if (skb->sk && skb->sk->sk_hash) { + u32 val = skb->sk->sk_hash; + + hash = jhash_1word(val, simple_tx_hashrnd); + goto out; + } + switch (skb->protocol) { case htons(ETH_P_IP): if (!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET))) -- GitLab From 7019298a2a5058c4e324494d6c8d0598214c28f4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 27 Jan 2009 16:34:47 -0800 Subject: [PATCH 0504/4982] net: Get rid of by-hand TX queue hashing. We now only TX hash on pre-computed SKB properties. The thinking is: 1) High performance routing and firewalling setups will have a multiqueue capable card used for receive, and therefore would have RX queue recordings made into the SKB which can be used for the TX side hash. 2) Locally generated packets will have an attached socket and thus a valid sk->sk_hash to make use of. Signed-off-by: David S. Miller --- net/core/dev.c | 73 ++++++++++---------------------------------------- 1 file changed, 14 insertions(+), 59 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index cb8caa93cac..e61b95c11fc 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1708,72 +1708,27 @@ out_kfree_skb: return 0; } -static u32 simple_tx_hashrnd; -static int simple_tx_hashrnd_initialized = 0; +static u32 skb_tx_hashrnd; +static int skb_tx_hashrnd_initialized = 0; -static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb) +static u16 skb_tx_hash(struct net_device *dev, struct sk_buff *skb) { - u32 addr1, addr2, ports; - u32 hash, ihl; - u8 ip_proto = 0; + u32 hash; - if (unlikely(!simple_tx_hashrnd_initialized)) { - get_random_bytes(&simple_tx_hashrnd, 4); - simple_tx_hashrnd_initialized = 1; + if (unlikely(!skb_tx_hashrnd_initialized)) { + get_random_bytes(&skb_tx_hashrnd, 4); + skb_tx_hashrnd_initialized = 1; } if (skb_rx_queue_recorded(skb)) { - u32 val = skb_get_rx_queue(skb); - - hash = jhash_1word(val, simple_tx_hashrnd); - goto out; - } - - if (skb->sk && skb->sk->sk_hash) { - u32 val = skb->sk->sk_hash; - - hash = jhash_1word(val, simple_tx_hashrnd); - goto out; - } - - switch (skb->protocol) { - case htons(ETH_P_IP): - if (!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET))) - ip_proto = ip_hdr(skb)->protocol; - addr1 = ip_hdr(skb)->saddr; - addr2 = ip_hdr(skb)->daddr; - ihl = ip_hdr(skb)->ihl; - break; - case htons(ETH_P_IPV6): - ip_proto = ipv6_hdr(skb)->nexthdr; - addr1 = ipv6_hdr(skb)->saddr.s6_addr32[3]; - addr2 = ipv6_hdr(skb)->daddr.s6_addr32[3]; - ihl = (40 >> 2); - break; - default: - return 0; - } - - - switch (ip_proto) { - case IPPROTO_TCP: - case IPPROTO_UDP: - case IPPROTO_DCCP: - case IPPROTO_ESP: - case IPPROTO_AH: - case IPPROTO_SCTP: - case IPPROTO_UDPLITE: - ports = *((u32 *) (skb_network_header(skb) + (ihl * 4))); - break; - - default: - ports = 0; - break; - } + hash = skb_get_rx_queue(skb); + } else if (skb->sk && skb->sk->sk_hash) { + hash = skb->sk->sk_hash; + } else + hash = skb->protocol; - hash = jhash_3words(addr1, addr2, ports, simple_tx_hashrnd); + hash = jhash_1word(hash, skb_tx_hashrnd); -out: return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32); } @@ -1786,7 +1741,7 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev, if (ops->ndo_select_queue) queue_index = ops->ndo_select_queue(dev, skb); else if (dev->real_num_tx_queues > 1) - queue_index = simple_tx_hash(dev, skb); + queue_index = skb_tx_hash(dev, skb); skb_set_queue_mapping(skb, queue_index); return netdev_get_tx_queue(dev, queue_index); -- GitLab From c0fe30265a1fe3a69e0ce0d08b49de1dda9c1190 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 28 Jan 2009 14:34:34 +1100 Subject: [PATCH 0505/4982] solos: Remove parameter group from sysfs on ATM dev deregister Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 2dca5ffc806..b7d4af3df2a 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -1166,6 +1166,8 @@ static void atm_remove(struct solos_card *card) for (i = 0; i < card->nr_ports; i++) { if (card->atmdev[i]) { dev_info(&card->dev->dev, "Unregistering ATM device %d\n", card->atmdev[i]->number); + + sysfs_remove_group(&card->atmdev[i]->class_dev.kobj, &solos_attr_group); atm_dev_deregister(card->atmdev[i]); } } -- GitLab From 909372317e67bdbbfced5dab3ade3437e3f2b254 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 28 Jan 2009 16:46:56 +1100 Subject: [PATCH 0506/4982] solos: First attempt at DMA support Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 118 ++++++++++++++++++++++++++++++---------- 1 file changed, 90 insertions(+), 28 deletions(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index b7d4af3df2a..63c9ad03aec 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -55,6 +55,8 @@ #define FLASH_BUSY 0x60 #define FPGA_MODE 0x5C #define FLASH_MODE 0x58 +#define TX_DMA_ADDR(port) (0x40 + (4 * (port))) +#define RX_DMA_ADDR(port) (0x30 + (4 * (port))) #define DATA_RAM_SIZE 32768 #define BUF_SIZE 4096 @@ -78,6 +80,14 @@ struct pkt_hdr { __le16 type; }; +struct solos_skb_cb { + struct atm_vcc *vcc; + uint32_t dma_addr; +}; + + +#define SKB_CB(skb) ((struct solos_skb_cb *)skb->cb) + #define PKT_DATA 0 #define PKT_COMMAND 1 #define PKT_POPEN 3 @@ -98,8 +108,11 @@ struct solos_card { struct list_head param_queue; struct sk_buff_head tx_queue[4]; struct sk_buff_head cli_queue[4]; + struct sk_buff *tx_skb[4]; + struct sk_buff *rx_skb[4]; wait_queue_head_t param_wq; wait_queue_head_t fw_wq; + int using_dma; }; @@ -588,44 +601,64 @@ void solos_bh(unsigned long card_arg) for (port = 0; port < card->nr_ports; port++) { if (card_flags & (0x10 << port)) { - struct pkt_hdr header; + struct pkt_hdr _hdr, *header; struct sk_buff *skb; struct atm_vcc *vcc; int size; - rx_done |= 0x10 << port; + if (card->using_dma) { + skb = card->rx_skb[port]; + pci_unmap_single(card->dev, SKB_CB(skb)->dma_addr, skb->len, + PCI_DMA_FROMDEVICE); + + card->rx_skb[port] = alloc_skb(2048, GFP_ATOMIC); + if (card->rx_skb[port]) { + SKB_CB(card->rx_skb[port])->dma_addr = + pci_map_single(card->dev, skb->data, skb->len, + PCI_DMA_FROMDEVICE); + iowrite32(SKB_CB(card->rx_skb[port])->dma_addr, + card->config_regs + RX_DMA_ADDR(port)); + } + header = (void *)skb->data; + size = le16_to_cpu(header->size); + skb_put(skb, size + sizeof(*header)); + skb_pull(skb, sizeof(*header)); + } else { + header = &_hdr; - memcpy_fromio(&header, RX_BUF(card, port), sizeof(header)); + rx_done |= 0x10 << port; - size = le16_to_cpu(header.size); + memcpy_fromio(header, RX_BUF(card, port), sizeof(*header)); - skb = alloc_skb(size + 1, GFP_ATOMIC); - if (!skb) { - if (net_ratelimit()) - dev_warn(&card->dev->dev, "Failed to allocate sk_buff for RX\n"); - continue; - } + size = le16_to_cpu(header->size); - memcpy_fromio(skb_put(skb, size), - RX_BUF(card, port) + sizeof(header), - size); + skb = alloc_skb(size + 1, GFP_ATOMIC); + if (!skb) { + if (net_ratelimit()) + dev_warn(&card->dev->dev, "Failed to allocate sk_buff for RX\n"); + continue; + } + memcpy_fromio(skb_put(skb, size), + RX_BUF(card, port) + sizeof(*header), + size); + } if (atmdebug) { dev_info(&card->dev->dev, "Received: device %d\n", port); dev_info(&card->dev->dev, "size: %d VPI: %d VCI: %d\n", - size, le16_to_cpu(header.vpi), - le16_to_cpu(header.vci)); + size, le16_to_cpu(header->vpi), + le16_to_cpu(header->vci)); print_buffer(skb); } - switch (le16_to_cpu(header.type)) { + switch (le16_to_cpu(header->type)) { case PKT_DATA: - vcc = find_vcc(card->atmdev[port], le16_to_cpu(header.vpi), - le16_to_cpu(header.vci)); + vcc = find_vcc(card->atmdev[port], le16_to_cpu(header->vpi), + le16_to_cpu(header->vci)); if (!vcc) { if (net_ratelimit()) dev_warn(&card->dev->dev, "Received packet for unknown VCI.VPI %d.%d on port %d\n", - le16_to_cpu(header.vci), le16_to_cpu(header.vpi), + le16_to_cpu(header->vci), le16_to_cpu(header->vpi), port); continue; } @@ -839,7 +872,7 @@ static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb, { int old_len; - *(void **)skb->cb = vcc; + SKB_CB(skb)->vcc = vcc; spin_lock(&card->tx_queue_lock); old_len = skb_queue_len(&card->tx_queue[port]); @@ -881,17 +914,37 @@ static int fpga_tx(struct solos_card *card) port); print_buffer(skb); } - memcpy_toio(TX_BUF(card, port), skb->data, skb->len); + if (card->using_dma) { + if (card->tx_skb[port]) { + struct sk_buff *oldskb = card->tx_skb[port]; - vcc = *(void **)skb->cb; + pci_unmap_single(card->dev, SKB_CB(oldskb)->dma_addr, + oldskb->len, PCI_DMA_TODEVICE); - if (vcc) { - atomic_inc(&vcc->stats->tx); - solos_pop(vcc, skb); - } else - dev_kfree_skb_irq(skb); + vcc = SKB_CB(oldskb)->vcc; - tx_started |= 1 << port; //Set TX full flag + if (vcc) { + atomic_inc(&vcc->stats->tx); + solos_pop(vcc, oldskb); + } else + dev_kfree_skb_irq(oldskb); + } + + SKB_CB(skb)->dma_addr = pci_map_single(card->dev, skb->data, + skb->len, PCI_DMA_TODEVICE); + iowrite32(SKB_CB(skb)->dma_addr, card->config_regs + TX_DMA_ADDR(port)); + } else { + memcpy_toio(TX_BUF(card, port), skb->data, skb->len); + tx_started |= 1 << port; //Set TX full flag + + vcc = SKB_CB(skb)->vcc; + + if (vcc) { + atomic_inc(&vcc->stats->tx); + solos_pop(vcc, skb); + } else + dev_kfree_skb_irq(skb); + } } } if (tx_started) @@ -999,6 +1052,12 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) goto out; } + err = pci_set_dma_mask(dev, DMA_32BIT_MASK); + if (err) { + dev_warn(&dev->dev, "Failed to set 32-bit DMA mask\n"); + goto out; + } + err = pci_request_regions(dev, "solos"); if (err) { dev_warn(&dev->dev, "Failed to request regions\n"); @@ -1035,6 +1094,9 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) dev_info(&dev->dev, "Solos FPGA Version %d.%02d svn-%d\n", major_ver, minor_ver, fpga_ver); + if (fpga_ver > 27) + card->using_dma = 1; + card->nr_ports = 2; /* FIXME: Detect daughterboard */ pci_set_drvdata(dev, card); -- GitLab From f6c6383502751ceb6f2f3579ad22578ca44f91f5 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Sat, 24 Jan 2009 13:35:28 +0100 Subject: [PATCH 0507/4982] ALSA: Turtle Beach Multisound Classic/Pinnacle driver This is driver for Turtle Beach Multisound cards: Classic, Fiji and Pinnacle. Tested pcm playback and recording and MIDI playback on Multisound Pinnacle. Signed-off-by: Krzysztof Helt Signed-off-by: Takashi Iwai --- sound/isa/Kconfig | 31 + sound/isa/msnd/Makefile | 9 + sound/isa/msnd/msnd.c | 702 +++++++++++++++ sound/isa/msnd/msnd.h | 308 +++++++ sound/isa/msnd/msnd_classic.c | 3 + sound/isa/msnd/msnd_classic.h | 129 +++ sound/isa/msnd/msnd_midi.c | 180 ++++ sound/isa/msnd/msnd_pinnacle.c | 1235 ++++++++++++++++++++++++++ sound/isa/msnd/msnd_pinnacle.h | 181 ++++ sound/isa/msnd/msnd_pinnacle_mixer.c | 343 +++++++ 10 files changed, 3121 insertions(+) create mode 100644 sound/isa/msnd/Makefile create mode 100644 sound/isa/msnd/msnd.c create mode 100644 sound/isa/msnd/msnd.h create mode 100644 sound/isa/msnd/msnd_classic.c create mode 100644 sound/isa/msnd/msnd_classic.h create mode 100644 sound/isa/msnd/msnd_midi.c create mode 100644 sound/isa/msnd/msnd_pinnacle.c create mode 100644 sound/isa/msnd/msnd_pinnacle.h create mode 100644 sound/isa/msnd/msnd_pinnacle_mixer.c diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index ce0aa044e27..a74725950b0 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig @@ -411,5 +411,36 @@ config SND_WAVEFRONT_FIRMWARE_IN_KERNEL you need to install the firmware files from the alsa-firmware package. +config SND_MSND_PINNACLE + tristate "Turtle Beach MultiSound Pinnacle/Fiji driver" + depends on X86 && EXPERIMENTAL + select FW_LOADER + select SND_MPU401_UART + select SND_PCM + help + Say Y to include support for Turtle Beach MultiSound Pinnacle/ + Fiji soundcards. + + To compile this driver as a module, choose M here: the module + will be called snd-msnd-pinnacle. + +config SND_MSND_CLASSIC + tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey" + depends on X86 && EXPERIMENTAL + select FW_LOADER + select SND_MPU401_UART + select SND_PCM + help + Say M here if you have a Turtle Beach MultiSound Classic, Tahiti or + Monterey (not for the Pinnacle or Fiji). + + See for important information + about this driver. Note that it has been discontinued, but the + Voyetra Turtle Beach knowledge base entry for it is still available + at . + + To compile this driver as a module, choose M here: the module + will be called snd-msnd-classic. + endif # SND_ISA diff --git a/sound/isa/msnd/Makefile b/sound/isa/msnd/Makefile new file mode 100644 index 00000000000..2171c0aa2f6 --- /dev/null +++ b/sound/isa/msnd/Makefile @@ -0,0 +1,9 @@ + +snd-msnd-lib-objs := msnd.o msnd_midi.o msnd_pinnacle_mixer.o +snd-msnd-pinnacle-objs := msnd_pinnacle.o +snd-msnd-classic-objs := msnd_classic.o + +# Toplevel Module Dependency +obj-$(CONFIG_SND_MSND_PINNACLE) += snd-msnd-pinnacle.o snd-msnd-lib.o +obj-$(CONFIG_SND_MSND_CLASSIC) += snd-msnd-classic.o snd-msnd-lib.o + diff --git a/sound/isa/msnd/msnd.c b/sound/isa/msnd/msnd.c new file mode 100644 index 00000000000..264e08212c6 --- /dev/null +++ b/sound/isa/msnd/msnd.c @@ -0,0 +1,702 @@ +/********************************************************************* + * + * 2002/06/30 Karsten Wiese: + * removed kernel-version dependencies. + * ripped from linux kernel 2.4.18 (OSS Implementation) by me. + * In the OSS Version, this file is compiled to a separate MODULE, + * that is used by the pinnacle and the classic driver. + * since there is no classic driver for alsa yet (i dont have a classic + * & writing one blindfold is difficult) this file's object is statically + * linked into the pinnacle-driver-module for now. look for the string + * "uncomment this to make this a module again" + * to do guess what. + * + * the following is a copy of the 2.4.18 OSS FREE file-heading comment: + * + * msnd.c - Driver Base + * + * Turtle Beach MultiSound Sound Card Driver for Linux + * + * Copyright (C) 1998 Andrew Veliath + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + ********************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "msnd.h" + +#define LOGNAME "msnd" + + +void snd_msnd_init_queue(void *base, int start, int size) +{ + writew(PCTODSP_BASED(start), base + JQS_wStart); + writew(PCTODSP_OFFSET(size) - 1, base + JQS_wSize); + writew(0, base + JQS_wHead); + writew(0, base + JQS_wTail); +} +EXPORT_SYMBOL(snd_msnd_init_queue); + +static int snd_msnd_wait_TXDE(struct snd_msnd *dev) +{ + unsigned int io = dev->io; + int timeout = 1000; + + while (timeout-- > 0) + if (inb(io + HP_ISR) & HPISR_TXDE) + return 0; + + return -EIO; +} + +static int snd_msnd_wait_HC0(struct snd_msnd *dev) +{ + unsigned int io = dev->io; + int timeout = 1000; + + while (timeout-- > 0) + if (!(inb(io + HP_CVR) & HPCVR_HC)) + return 0; + + return -EIO; +} + +int snd_msnd_send_dsp_cmd(struct snd_msnd *dev, u8 cmd) +{ + unsigned long flags; + + spin_lock_irqsave(&dev->lock, flags); + if (snd_msnd_wait_HC0(dev) == 0) { + outb(cmd, dev->io + HP_CVR); + spin_unlock_irqrestore(&dev->lock, flags); + return 0; + } + spin_unlock_irqrestore(&dev->lock, flags); + + snd_printd(KERN_ERR LOGNAME ": Send DSP command timeout\n"); + + return -EIO; +} +EXPORT_SYMBOL(snd_msnd_send_dsp_cmd); + +int snd_msnd_send_word(struct snd_msnd *dev, unsigned char high, + unsigned char mid, unsigned char low) +{ + unsigned int io = dev->io; + + if (snd_msnd_wait_TXDE(dev) == 0) { + outb(high, io + HP_TXH); + outb(mid, io + HP_TXM); + outb(low, io + HP_TXL); + return 0; + } + + snd_printd(KERN_ERR LOGNAME ": Send host word timeout\n"); + + return -EIO; +} +EXPORT_SYMBOL(snd_msnd_send_word); + +int snd_msnd_upload_host(struct snd_msnd *dev, const u8 *bin, int len) +{ + int i; + + if (len % 3 != 0) { + snd_printk(KERN_ERR LOGNAME + ": Upload host data not multiple of 3!\n"); + return -EINVAL; + } + + for (i = 0; i < len; i += 3) + if (snd_msnd_send_word(dev, bin[i], bin[i + 1], bin[i + 2])) + return -EIO; + + inb(dev->io + HP_RXL); + inb(dev->io + HP_CVR); + + return 0; +} +EXPORT_SYMBOL(snd_msnd_upload_host); + +int snd_msnd_enable_irq(struct snd_msnd *dev) +{ + unsigned long flags; + + if (dev->irq_ref++) + return 0; + + snd_printdd(LOGNAME ": Enabling IRQ\n"); + + spin_lock_irqsave(&dev->lock, flags); + if (snd_msnd_wait_TXDE(dev) == 0) { + outb(inb(dev->io + HP_ICR) | HPICR_TREQ, dev->io + HP_ICR); + if (dev->type == msndClassic) + outb(dev->irqid, dev->io + HP_IRQM); + + outb(inb(dev->io + HP_ICR) & ~HPICR_TREQ, dev->io + HP_ICR); + outb(inb(dev->io + HP_ICR) | HPICR_RREQ, dev->io + HP_ICR); + enable_irq(dev->irq); + snd_msnd_init_queue(dev->DSPQ, dev->dspq_data_buff, + dev->dspq_buff_size); + spin_unlock_irqrestore(&dev->lock, flags); + return 0; + } + spin_unlock_irqrestore(&dev->lock, flags); + + snd_printd(KERN_ERR LOGNAME ": Enable IRQ failed\n"); + + return -EIO; +} +EXPORT_SYMBOL(snd_msnd_enable_irq); + +int snd_msnd_disable_irq(struct snd_msnd *dev) +{ + unsigned long flags; + + if (--dev->irq_ref > 0) + return 0; + + if (dev->irq_ref < 0) + snd_printd(KERN_WARNING LOGNAME ": IRQ ref count is %d\n", + dev->irq_ref); + + snd_printdd(LOGNAME ": Disabling IRQ\n"); + + spin_lock_irqsave(&dev->lock, flags); + if (snd_msnd_wait_TXDE(dev) == 0) { + outb(inb(dev->io + HP_ICR) & ~HPICR_RREQ, dev->io + HP_ICR); + if (dev->type == msndClassic) + outb(HPIRQ_NONE, dev->io + HP_IRQM); + disable_irq(dev->irq); + spin_unlock_irqrestore(&dev->lock, flags); + return 0; + } + spin_unlock_irqrestore(&dev->lock, flags); + + snd_printd(KERN_ERR LOGNAME ": Disable IRQ failed\n"); + + return -EIO; +} +EXPORT_SYMBOL(snd_msnd_disable_irq); + +static inline long get_play_delay_jiffies(struct snd_msnd *chip, long size) +{ + long tmp = (size * HZ * chip->play_sample_size) / 8; + return tmp / (chip->play_sample_rate * chip->play_channels); +} + +static void snd_msnd_dsp_write_flush(struct snd_msnd *chip) +{ + if (!(chip->mode & FMODE_WRITE) || !test_bit(F_WRITING, &chip->flags)) + return; + set_bit(F_WRITEFLUSH, &chip->flags); +/* interruptible_sleep_on_timeout( + &chip->writeflush, + get_play_delay_jiffies(&chip, chip->DAPF.len));*/ + clear_bit(F_WRITEFLUSH, &chip->flags); + if (!signal_pending(current)) + schedule_timeout_interruptible( + get_play_delay_jiffies(chip, chip->play_period_bytes)); + clear_bit(F_WRITING, &chip->flags); +} + +void snd_msnd_dsp_halt(struct snd_msnd *chip, struct file *file) +{ + if ((file ? file->f_mode : chip->mode) & FMODE_READ) { + clear_bit(F_READING, &chip->flags); + snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP); + snd_msnd_disable_irq(chip); + if (file) { + snd_printd(KERN_INFO LOGNAME + ": Stopping read for %p\n", file); + chip->mode &= ~FMODE_READ; + } + clear_bit(F_AUDIO_READ_INUSE, &chip->flags); + } + if ((file ? file->f_mode : chip->mode) & FMODE_WRITE) { + if (test_bit(F_WRITING, &chip->flags)) { + snd_msnd_dsp_write_flush(chip); + snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP); + } + snd_msnd_disable_irq(chip); + if (file) { + snd_printd(KERN_INFO + LOGNAME ": Stopping write for %p\n", file); + chip->mode &= ~FMODE_WRITE; + } + clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags); + } +} +EXPORT_SYMBOL(snd_msnd_dsp_halt); + + +int snd_msnd_DARQ(struct snd_msnd *chip, int bank) +{ + int /*size, n,*/ timeout = 3; + u16 wTmp; + /* void *DAQD; */ + + /* Increment the tail and check for queue wrap */ + wTmp = readw(chip->DARQ + JQS_wTail) + PCTODSP_OFFSET(DAQDS__size); + if (wTmp > readw(chip->DARQ + JQS_wSize)) + wTmp = 0; + while (wTmp == readw(chip->DARQ + JQS_wHead) && timeout--) + udelay(1); + + if (chip->capturePeriods == 2) { + void *pDAQ = chip->mappedbase + DARQ_DATA_BUFF + + bank * DAQDS__size + DAQDS_wStart; + unsigned short offset = 0x3000 + chip->capturePeriodBytes; + + if (readw(pDAQ) != PCTODSP_BASED(0x3000)) + offset = 0x3000; + writew(PCTODSP_BASED(offset), pDAQ); + } + + writew(wTmp, chip->DARQ + JQS_wTail); + +#if 0 + /* Get our digital audio queue struct */ + DAQD = bank * DAQDS__size + chip->mappedbase + DARQ_DATA_BUFF; + + /* Get length of data */ + size = readw(DAQD + DAQDS_wSize); + + /* Read data from the head (unprotected bank 1 access okay + since this is only called inside an interrupt) */ + outb(HPBLKSEL_1, chip->io + HP_BLKS); + n = msnd_fifo_write(&chip->DARF, + (char *)(chip->base + bank * DAR_BUFF_SIZE), + size, 0); + if (n <= 0) { + outb(HPBLKSEL_0, chip->io + HP_BLKS); + return n; + } + outb(HPBLKSEL_0, chip->io + HP_BLKS); +#endif + + return 1; +} +EXPORT_SYMBOL(snd_msnd_DARQ); + +int snd_msnd_DAPQ(struct snd_msnd *chip, int start) +{ + u16 DAPQ_tail; + int protect = start, nbanks = 0; + void *DAQD; + static int play_banks_submitted; + /* unsigned long flags; + spin_lock_irqsave(&chip->lock, flags); not necessary */ + + DAPQ_tail = readw(chip->DAPQ + JQS_wTail); + while (DAPQ_tail != readw(chip->DAPQ + JQS_wHead) || start) { + int bank_num = DAPQ_tail / PCTODSP_OFFSET(DAQDS__size); + + if (start) { + start = 0; + play_banks_submitted = 0; + } + + /* Get our digital audio queue struct */ + DAQD = bank_num * DAQDS__size + chip->mappedbase + + DAPQ_DATA_BUFF; + + /* Write size of this bank */ + writew(chip->play_period_bytes, DAQD + DAQDS_wSize); + if (play_banks_submitted < 3) + ++play_banks_submitted; + else if (chip->playPeriods == 2) { + unsigned short offset = chip->play_period_bytes; + + if (readw(DAQD + DAQDS_wStart) != PCTODSP_BASED(0x0)) + offset = 0; + + writew(PCTODSP_BASED(offset), DAQD + DAQDS_wStart); + } + ++nbanks; + + /* Then advance the tail */ + /* + if (protect) + snd_printd(KERN_INFO "B %X %lX\n", + bank_num, xtime.tv_usec); + */ + + DAPQ_tail = (++bank_num % 3) * PCTODSP_OFFSET(DAQDS__size); + writew(DAPQ_tail, chip->DAPQ + JQS_wTail); + /* Tell the DSP to play the bank */ + snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_START); + if (protect) + if (2 == bank_num) + break; + } + /* + if (protect) + snd_printd(KERN_INFO "%lX\n", xtime.tv_usec); + */ + /* spin_unlock_irqrestore(&chip->lock, flags); not necessary */ + return nbanks; +} +EXPORT_SYMBOL(snd_msnd_DAPQ); + +static void snd_msnd_play_reset_queue(struct snd_msnd *chip, + unsigned int pcm_periods, + unsigned int pcm_count) +{ + int n; + void *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF; + + chip->last_playbank = -1; + chip->playLimit = pcm_count * (pcm_periods - 1); + chip->playPeriods = pcm_periods; + writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wHead); + writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wTail); + + chip->play_period_bytes = pcm_count; + + for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) { + writew(PCTODSP_BASED((u32)(pcm_count * n)), + pDAQ + DAQDS_wStart); + writew(0, pDAQ + DAQDS_wSize); + writew(1, pDAQ + DAQDS_wFormat); + writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize); + writew(chip->play_channels, pDAQ + DAQDS_wChannels); + writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate); + writew(HIMT_PLAY_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg); + writew(n, pDAQ + DAQDS_wFlags); + } +} + +static void snd_msnd_capture_reset_queue(struct snd_msnd *chip, + unsigned int pcm_periods, + unsigned int pcm_count) +{ + int n; + void *pDAQ; + /* unsigned long flags; */ + + /* snd_msnd_init_queue(chip->DARQ, DARQ_DATA_BUFF, DARQ_BUFF_SIZE); */ + + chip->last_recbank = 2; + chip->captureLimit = pcm_count * (pcm_periods - 1); + chip->capturePeriods = pcm_periods; + writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DARQ + JQS_wHead); + writew(PCTODSP_OFFSET(chip->last_recbank * DAQDS__size), + chip->DARQ + JQS_wTail); + +#if 0 /* Critical section: bank 1 access. this is how the OSS driver does it:*/ + spin_lock_irqsave(&chip->lock, flags); + outb(HPBLKSEL_1, chip->io + HP_BLKS); + memset_io(chip->mappedbase, 0, DAR_BUFF_SIZE * 3); + outb(HPBLKSEL_0, chip->io + HP_BLKS); + spin_unlock_irqrestore(&chip->lock, flags); +#endif + + chip->capturePeriodBytes = pcm_count; + snd_printdd("snd_msnd_capture_reset_queue() %i\n", pcm_count); + + pDAQ = chip->mappedbase + DARQ_DATA_BUFF; + + for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) { + u32 tmp = pcm_count * n; + + writew(PCTODSP_BASED(tmp + 0x3000), pDAQ + DAQDS_wStart); + writew(pcm_count, pDAQ + DAQDS_wSize); + writew(1, pDAQ + DAQDS_wFormat); + writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize); + writew(chip->capture_channels, pDAQ + DAQDS_wChannels); + writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate); + writew(HIMT_RECORD_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg); + writew(n, pDAQ + DAQDS_wFlags); + } +} + +static struct snd_pcm_hardware snd_msnd_playback = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP_VALID, + .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, + .rates = SNDRV_PCM_RATE_8000_48000, + .rate_min = 8000, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 2, + .buffer_bytes_max = 0x3000, + .period_bytes_min = 0x40, + .period_bytes_max = 0x1800, + .periods_min = 2, + .periods_max = 3, + .fifo_size = 0, +}; + +static struct snd_pcm_hardware snd_msnd_capture = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP_VALID, + .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, + .rates = SNDRV_PCM_RATE_8000_48000, + .rate_min = 8000, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 2, + .buffer_bytes_max = 0x3000, + .period_bytes_min = 0x40, + .period_bytes_max = 0x1800, + .periods_min = 2, + .periods_max = 3, + .fifo_size = 0, +}; + + +static int snd_msnd_playback_open(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_msnd *chip = snd_pcm_substream_chip(substream); + + set_bit(F_AUDIO_WRITE_INUSE, &chip->flags); + clear_bit(F_WRITING, &chip->flags); + snd_msnd_enable_irq(chip); + + runtime->dma_area = chip->mappedbase; + runtime->dma_bytes = 0x3000; + + chip->playback_substream = substream; + runtime->hw = snd_msnd_playback; + return 0; +} + +static int snd_msnd_playback_close(struct snd_pcm_substream *substream) +{ + struct snd_msnd *chip = snd_pcm_substream_chip(substream); + + snd_msnd_disable_irq(chip); + clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags); + return 0; +} + + +static int snd_msnd_playback_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + int i; + struct snd_msnd *chip = snd_pcm_substream_chip(substream); + void *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF; + + chip->play_sample_size = snd_pcm_format_width(params_format(params)); + chip->play_channels = params_channels(params); + chip->play_sample_rate = params_rate(params); + + for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) { + writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize); + writew(chip->play_channels, pDAQ + DAQDS_wChannels); + writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate); + } + /* dont do this here: + * snd_msnd_calibrate_adc(chip->play_sample_rate); + */ + + return 0; +} + +static int snd_msnd_playback_prepare(struct snd_pcm_substream *substream) +{ + struct snd_msnd *chip = snd_pcm_substream_chip(substream); + unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream); + unsigned int pcm_count = snd_pcm_lib_period_bytes(substream); + unsigned int pcm_periods = pcm_size / pcm_count; + + snd_msnd_play_reset_queue(chip, pcm_periods, pcm_count); + chip->playDMAPos = 0; + return 0; +} + +static int snd_msnd_playback_trigger(struct snd_pcm_substream *substream, + int cmd) +{ + struct snd_msnd *chip = snd_pcm_substream_chip(substream); + int result = 0; + + if (cmd == SNDRV_PCM_TRIGGER_START) { + snd_printdd("snd_msnd_playback_trigger(START)\n"); + chip->banksPlayed = 0; + set_bit(F_WRITING, &chip->flags); + snd_msnd_DAPQ(chip, 1); + } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { + snd_printdd("snd_msnd_playback_trigger(STop)\n"); + /* interrupt diagnostic, comment this out later */ + clear_bit(F_WRITING, &chip->flags); + snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP); + } else { + snd_printd(KERN_ERR "snd_msnd_playback_trigger(?????)\n"); + result = -EINVAL; + } + + snd_printdd("snd_msnd_playback_trigger() ENDE\n"); + return result; +} + +static snd_pcm_uframes_t +snd_msnd_playback_pointer(struct snd_pcm_substream *substream) +{ + struct snd_msnd *chip = snd_pcm_substream_chip(substream); + + return bytes_to_frames(substream->runtime, chip->playDMAPos); +} + + +static struct snd_pcm_ops snd_msnd_playback_ops = { + .open = snd_msnd_playback_open, + .close = snd_msnd_playback_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = snd_msnd_playback_hw_params, + .prepare = snd_msnd_playback_prepare, + .trigger = snd_msnd_playback_trigger, + .pointer = snd_msnd_playback_pointer, +}; + +static int snd_msnd_capture_open(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_msnd *chip = snd_pcm_substream_chip(substream); + + set_bit(F_AUDIO_READ_INUSE, &chip->flags); + snd_msnd_enable_irq(chip); + runtime->dma_area = chip->mappedbase + 0x3000; + runtime->dma_bytes = 0x3000; + memset(runtime->dma_area, 0, runtime->dma_bytes); + chip->capture_substream = substream; + runtime->hw = snd_msnd_capture; + return 0; +} + +static int snd_msnd_capture_close(struct snd_pcm_substream *substream) +{ + struct snd_msnd *chip = snd_pcm_substream_chip(substream); + + snd_msnd_disable_irq(chip); + clear_bit(F_AUDIO_READ_INUSE, &chip->flags); + return 0; +} + +static int snd_msnd_capture_prepare(struct snd_pcm_substream *substream) +{ + struct snd_msnd *chip = snd_pcm_substream_chip(substream); + unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream); + unsigned int pcm_count = snd_pcm_lib_period_bytes(substream); + unsigned int pcm_periods = pcm_size / pcm_count; + + snd_msnd_capture_reset_queue(chip, pcm_periods, pcm_count); + chip->captureDMAPos = 0; + return 0; +} + +static int snd_msnd_capture_trigger(struct snd_pcm_substream *substream, + int cmd) +{ + struct snd_msnd *chip = snd_pcm_substream_chip(substream); + + if (cmd == SNDRV_PCM_TRIGGER_START) { + chip->last_recbank = -1; + set_bit(F_READING, &chip->flags); + if (snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_START) == 0) + return 0; + + clear_bit(F_READING, &chip->flags); + } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { + clear_bit(F_READING, &chip->flags); + snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP); + return 0; + } + return -EINVAL; +} + + +static snd_pcm_uframes_t +snd_msnd_capture_pointer(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_msnd *chip = snd_pcm_substream_chip(substream); + + return bytes_to_frames(runtime, chip->captureDMAPos); +} + + +static int snd_msnd_capture_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + int i; + struct snd_msnd *chip = snd_pcm_substream_chip(substream); + void *pDAQ = chip->mappedbase + DARQ_DATA_BUFF; + + chip->capture_sample_size = snd_pcm_format_width(params_format(params)); + chip->capture_channels = params_channels(params); + chip->capture_sample_rate = params_rate(params); + + for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) { + writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize); + writew(chip->capture_channels, pDAQ + DAQDS_wChannels); + writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate); + } + return 0; +} + + +static struct snd_pcm_ops snd_msnd_capture_ops = { + .open = snd_msnd_capture_open, + .close = snd_msnd_capture_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = snd_msnd_capture_hw_params, + .prepare = snd_msnd_capture_prepare, + .trigger = snd_msnd_capture_trigger, + .pointer = snd_msnd_capture_pointer, +}; + + +int snd_msnd_pcm(struct snd_card *card, int device, + struct snd_pcm **rpcm) +{ + struct snd_msnd *chip = card->private_data; + struct snd_pcm *pcm; + int err; + + err = snd_pcm_new(card, "MSNDPINNACLE", device, 1, 1, &pcm); + if (err < 0) + return err; + + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_msnd_playback_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_msnd_capture_ops); + + pcm->private_data = chip; + strcpy(pcm->name, "Hurricane"); + + + if (rpcm) + *rpcm = pcm; + return 0; +} +EXPORT_SYMBOL(snd_msnd_pcm); + diff --git a/sound/isa/msnd/msnd.h b/sound/isa/msnd/msnd.h new file mode 100644 index 00000000000..3773e242b58 --- /dev/null +++ b/sound/isa/msnd/msnd.h @@ -0,0 +1,308 @@ +/********************************************************************* + * + * msnd.h + * + * Turtle Beach MultiSound Sound Card Driver for Linux + * + * Some parts of this header file were derived from the Turtle Beach + * MultiSound Driver Development Kit. + * + * Copyright (C) 1998 Andrew Veliath + * Copyright (C) 1993 Turtle Beach Systems, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + ********************************************************************/ +#ifndef __MSND_H +#define __MSND_H + +#define DEFSAMPLERATE 44100 +#define DEFSAMPLESIZE SNDRV_PCM_FORMAT_S16 +#define DEFCHANNELS 1 + +#define SRAM_BANK_SIZE 0x8000 +#define SRAM_CNTL_START 0x7F00 +#define SMA_STRUCT_START 0x7F40 + +#define DSP_BASE_ADDR 0x4000 +#define DSP_BANK_BASE 0x4000 + +#define AGND 0x01 +#define SIGNAL 0x02 + +#define EXT_DSP_BIT_DCAL 0x0001 +#define EXT_DSP_BIT_MIDI_CON 0x0002 + +#define BUFFSIZE 0x8000 +#define HOSTQ_SIZE 0x40 + +#define DAP_BUFF_SIZE 0x2400 + +#define DAPQ_STRUCT_SIZE 0x10 +#define DARQ_STRUCT_SIZE 0x10 +#define DAPQ_BUFF_SIZE (3 * 0x10) +#define DARQ_BUFF_SIZE (3 * 0x10) +#define MODQ_BUFF_SIZE 0x400 + +#define DAPQ_DATA_BUFF 0x6C00 +#define DARQ_DATA_BUFF 0x6C30 +#define MODQ_DATA_BUFF 0x6C60 +#define MIDQ_DATA_BUFF 0x7060 + +#define DAPQ_OFFSET SRAM_CNTL_START +#define DARQ_OFFSET (SRAM_CNTL_START + 0x08) +#define MODQ_OFFSET (SRAM_CNTL_START + 0x10) +#define MIDQ_OFFSET (SRAM_CNTL_START + 0x18) +#define DSPQ_OFFSET (SRAM_CNTL_START + 0x20) + +#define HP_ICR 0x00 +#define HP_CVR 0x01 +#define HP_ISR 0x02 +#define HP_IVR 0x03 +#define HP_NU 0x04 +#define HP_INFO 0x04 +#define HP_TXH 0x05 +#define HP_RXH 0x05 +#define HP_TXM 0x06 +#define HP_RXM 0x06 +#define HP_TXL 0x07 +#define HP_RXL 0x07 + +#define HP_ICR_DEF 0x00 +#define HP_CVR_DEF 0x12 +#define HP_ISR_DEF 0x06 +#define HP_IVR_DEF 0x0f +#define HP_NU_DEF 0x00 + +#define HP_IRQM 0x09 + +#define HPR_BLRC 0x08 +#define HPR_SPR1 0x09 +#define HPR_SPR2 0x0A +#define HPR_TCL0 0x0B +#define HPR_TCL1 0x0C +#define HPR_TCL2 0x0D +#define HPR_TCL3 0x0E +#define HPR_TCL4 0x0F + +#define HPICR_INIT 0x80 +#define HPICR_HM1 0x40 +#define HPICR_HM0 0x20 +#define HPICR_HF1 0x10 +#define HPICR_HF0 0x08 +#define HPICR_TREQ 0x02 +#define HPICR_RREQ 0x01 + +#define HPCVR_HC 0x80 + +#define HPISR_HREQ 0x80 +#define HPISR_DMA 0x40 +#define HPISR_HF3 0x10 +#define HPISR_HF2 0x08 +#define HPISR_TRDY 0x04 +#define HPISR_TXDE 0x02 +#define HPISR_RXDF 0x01 + +#define HPIO_290 0 +#define HPIO_260 1 +#define HPIO_250 2 +#define HPIO_240 3 +#define HPIO_230 4 +#define HPIO_220 5 +#define HPIO_210 6 +#define HPIO_3E0 7 + +#define HPMEM_NONE 0 +#define HPMEM_B000 1 +#define HPMEM_C800 2 +#define HPMEM_D000 3 +#define HPMEM_D400 4 +#define HPMEM_D800 5 +#define HPMEM_E000 6 +#define HPMEM_E800 7 + +#define HPIRQ_NONE 0 +#define HPIRQ_5 1 +#define HPIRQ_7 2 +#define HPIRQ_9 3 +#define HPIRQ_10 4 +#define HPIRQ_11 5 +#define HPIRQ_12 6 +#define HPIRQ_15 7 + +#define HIMT_PLAY_DONE 0x00 +#define HIMT_RECORD_DONE 0x01 +#define HIMT_MIDI_EOS 0x02 +#define HIMT_MIDI_OUT 0x03 + +#define HIMT_MIDI_IN_UCHAR 0x0E +#define HIMT_DSP 0x0F + +#define HDEX_BASE 0x92 +#define HDEX_PLAY_START (0 + HDEX_BASE) +#define HDEX_PLAY_STOP (1 + HDEX_BASE) +#define HDEX_PLAY_PAUSE (2 + HDEX_BASE) +#define HDEX_PLAY_RESUME (3 + HDEX_BASE) +#define HDEX_RECORD_START (4 + HDEX_BASE) +#define HDEX_RECORD_STOP (5 + HDEX_BASE) +#define HDEX_MIDI_IN_START (6 + HDEX_BASE) +#define HDEX_MIDI_IN_STOP (7 + HDEX_BASE) +#define HDEX_MIDI_OUT_START (8 + HDEX_BASE) +#define HDEX_MIDI_OUT_STOP (9 + HDEX_BASE) +#define HDEX_AUX_REQ (10 + HDEX_BASE) + +#define HDEXAR_CLEAR_PEAKS 1 +#define HDEXAR_IN_SET_POTS 2 +#define HDEXAR_AUX_SET_POTS 3 +#define HDEXAR_CAL_A_TO_D 4 +#define HDEXAR_RD_EXT_DSP_BITS 5 + +/* Pinnacle only HDEXAR defs */ +#define HDEXAR_SET_ANA_IN 0 +#define HDEXAR_SET_SYNTH_IN 4 +#define HDEXAR_READ_DAT_IN 5 +#define HDEXAR_MIC_SET_POTS 6 +#define HDEXAR_SET_DAT_IN 7 + +#define HDEXAR_SET_SYNTH_48 8 +#define HDEXAR_SET_SYNTH_44 9 + +#define HIWORD(l) ((u16)((((u32)(l)) >> 16) & 0xFFFF)) +#define LOWORD(l) ((u16)(u32)(l)) +#define HIBYTE(w) ((u8)(((u16)(w) >> 8) & 0xFF)) +#define LOBYTE(w) ((u8)(w)) +#define MAKELONG(low, hi) ((long)(((u16)(low))|(((u32)((u16)(hi)))<<16))) +#define MAKEWORD(low, hi) ((u16)(((u8)(low))|(((u16)((u8)(hi)))<<8))) + +#define PCTODSP_OFFSET(w) (u16)((w)/2) +#define PCTODSP_BASED(w) (u16)(((w)/2) + DSP_BASE_ADDR) +#define DSPTOPC_BASED(w) (((w) - DSP_BASE_ADDR) * 2) + +#ifdef SLOWIO +# undef outb +# undef inb +# define outb outb_p +# define inb inb_p +#endif + +/* JobQueueStruct */ +#define JQS_wStart 0x00 +#define JQS_wSize 0x02 +#define JQS_wHead 0x04 +#define JQS_wTail 0x06 +#define JQS__size 0x08 + +/* DAQueueDataStruct */ +#define DAQDS_wStart 0x00 +#define DAQDS_wSize 0x02 +#define DAQDS_wFormat 0x04 +#define DAQDS_wSampleSize 0x06 +#define DAQDS_wChannels 0x08 +#define DAQDS_wSampleRate 0x0A +#define DAQDS_wIntMsg 0x0C +#define DAQDS_wFlags 0x0E +#define DAQDS__size 0x10 + +#include + +struct snd_msnd { + void __iomem *mappedbase; + int play_period_bytes; + int playLimit; + int playPeriods; + int playDMAPos; + int banksPlayed; + int captureDMAPos; + int capturePeriodBytes; + int captureLimit; + int capturePeriods; + struct snd_card *card; + void *msndmidi_mpu; + struct snd_rawmidi *rmidi; + + /* Hardware resources */ + long io; + int memid, irqid; + int irq, irq_ref; + unsigned long base; + + /* Motorola 56k DSP SMA */ + void __iomem *SMA; + void __iomem *DAPQ; + void __iomem *DARQ; + void __iomem *MODQ; + void __iomem *MIDQ; + void __iomem *DSPQ; + int dspq_data_buff, dspq_buff_size; + + /* State variables */ + enum { msndClassic, msndPinnacle } type; + mode_t mode; + unsigned long flags; +#define F_RESETTING 0 +#define F_HAVEDIGITAL 1 +#define F_AUDIO_WRITE_INUSE 2 +#define F_WRITING 3 +#define F_WRITEBLOCK 4 +#define F_WRITEFLUSH 5 +#define F_AUDIO_READ_INUSE 6 +#define F_READING 7 +#define F_READBLOCK 8 +#define F_EXT_MIDI_INUSE 9 +#define F_HDR_MIDI_INUSE 10 +#define F_DISABLE_WRITE_NDELAY 11 + spinlock_t lock; + spinlock_t mixer_lock; + int nresets; + unsigned recsrc; +#define LEVEL_ENTRIES 32 + int left_levels[LEVEL_ENTRIES]; + int right_levels[LEVEL_ENTRIES]; + int calibrate_signal; + int play_sample_size, play_sample_rate, play_channels; + int play_ndelay; + int capture_sample_size, capture_sample_rate, capture_channels; + int capture_ndelay; + u8 bCurrentMidiPatch; + + int last_playbank, last_recbank; + struct snd_pcm_substream *playback_substream; + struct snd_pcm_substream *capture_substream; + +}; + +void snd_msnd_init_queue(void *base, int start, int size); + +int snd_msnd_send_dsp_cmd(struct snd_msnd *chip, u8 cmd); +int snd_msnd_send_word(struct snd_msnd *chip, + unsigned char high, + unsigned char mid, + unsigned char low); +int snd_msnd_upload_host(struct snd_msnd *chip, + const u8 *bin, int len); +int snd_msnd_enable_irq(struct snd_msnd *chip); +int snd_msnd_disable_irq(struct snd_msnd *chip); +void snd_msnd_dsp_halt(struct snd_msnd *chip, struct file *file); +int snd_msnd_DAPQ(struct snd_msnd *chip, int start); +int snd_msnd_DARQ(struct snd_msnd *chip, int start); +int snd_msnd_pcm(struct snd_card *card, int device, struct snd_pcm **rpcm); + +int snd_msndmidi_new(struct snd_card *card, int device); +void snd_msndmidi_input_read(void *mpu); + +void snd_msndmix_setup(struct snd_msnd *chip); +int __devinit snd_msndmix_new(struct snd_card *card); +int snd_msndmix_force_recsrc(struct snd_msnd *chip, int recsrc); +#endif /* __MSND_H */ diff --git a/sound/isa/msnd/msnd_classic.c b/sound/isa/msnd/msnd_classic.c new file mode 100644 index 00000000000..3b23a096fa4 --- /dev/null +++ b/sound/isa/msnd/msnd_classic.c @@ -0,0 +1,3 @@ +/* The work is in msnd_pinnacle.c, just define MSND_CLASSIC before it. */ +#define MSND_CLASSIC +#include "msnd_pinnacle.c" diff --git a/sound/isa/msnd/msnd_classic.h b/sound/isa/msnd/msnd_classic.h new file mode 100644 index 00000000000..f18d5fa5baf --- /dev/null +++ b/sound/isa/msnd/msnd_classic.h @@ -0,0 +1,129 @@ +/********************************************************************* + * + * msnd_classic.h + * + * Turtle Beach MultiSound Sound Card Driver for Linux + * + * Some parts of this header file were derived from the Turtle Beach + * MultiSound Driver Development Kit. + * + * Copyright (C) 1998 Andrew Veliath + * Copyright (C) 1993 Turtle Beach Systems, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + ********************************************************************/ +#ifndef __MSND_CLASSIC_H +#define __MSND_CLASSIC_H + +#define DSP_NUMIO 0x10 + +#define HP_MEMM 0x08 + +#define HP_BITM 0x0E +#define HP_WAIT 0x0D +#define HP_DSPR 0x0A +#define HP_PROR 0x0B +#define HP_BLKS 0x0C + +#define HPPRORESET_OFF 0 +#define HPPRORESET_ON 1 + +#define HPDSPRESET_OFF 0 +#define HPDSPRESET_ON 1 + +#define HPBLKSEL_0 0 +#define HPBLKSEL_1 1 + +#define HPWAITSTATE_0 0 +#define HPWAITSTATE_1 1 + +#define HPBITMODE_16 0 +#define HPBITMODE_8 1 + +#define HIDSP_INT_PLAY_UNDER 0x00 +#define HIDSP_INT_RECORD_OVER 0x01 +#define HIDSP_INPUT_CLIPPING 0x02 +#define HIDSP_MIDI_IN_OVER 0x10 +#define HIDSP_MIDI_OVERRUN_ERR 0x13 + +#define TIME_PRO_RESET_DONE 0x028A +#define TIME_PRO_SYSEX 0x0040 +#define TIME_PRO_RESET 0x0032 + +#define DAR_BUFF_SIZE 0x2000 + +#define MIDQ_BUFF_SIZE 0x200 +#define DSPQ_BUFF_SIZE 0x40 + +#define DSPQ_DATA_BUFF 0x7260 + +#define MOP_SYNTH 0x10 +#define MOP_EXTOUT 0x32 +#define MOP_EXTTHRU 0x02 +#define MOP_OUTMASK 0x01 + +#define MIP_EXTIN 0x01 +#define MIP_SYNTH 0x00 +#define MIP_INMASK 0x32 + +/* Classic SMA Common Data */ +#define SMA_wCurrPlayBytes 0x0000 +#define SMA_wCurrRecordBytes 0x0002 +#define SMA_wCurrPlayVolLeft 0x0004 +#define SMA_wCurrPlayVolRight 0x0006 +#define SMA_wCurrInVolLeft 0x0008 +#define SMA_wCurrInVolRight 0x000a +#define SMA_wUser_3 0x000c +#define SMA_wUser_4 0x000e +#define SMA_dwUser_5 0x0010 +#define SMA_dwUser_6 0x0014 +#define SMA_wUser_7 0x0018 +#define SMA_wReserved_A 0x001a +#define SMA_wReserved_B 0x001c +#define SMA_wReserved_C 0x001e +#define SMA_wReserved_D 0x0020 +#define SMA_wReserved_E 0x0022 +#define SMA_wReserved_F 0x0024 +#define SMA_wReserved_G 0x0026 +#define SMA_wReserved_H 0x0028 +#define SMA_wCurrDSPStatusFlags 0x002a +#define SMA_wCurrHostStatusFlags 0x002c +#define SMA_wCurrInputTagBits 0x002e +#define SMA_wCurrLeftPeak 0x0030 +#define SMA_wCurrRightPeak 0x0032 +#define SMA_wExtDSPbits 0x0034 +#define SMA_bExtHostbits 0x0036 +#define SMA_bBoardLevel 0x0037 +#define SMA_bInPotPosRight 0x0038 +#define SMA_bInPotPosLeft 0x0039 +#define SMA_bAuxPotPosRight 0x003a +#define SMA_bAuxPotPosLeft 0x003b +#define SMA_wCurrMastVolLeft 0x003c +#define SMA_wCurrMastVolRight 0x003e +#define SMA_bUser_12 0x0040 +#define SMA_bUser_13 0x0041 +#define SMA_wUser_14 0x0042 +#define SMA_wUser_15 0x0044 +#define SMA_wCalFreqAtoD 0x0046 +#define SMA_wUser_16 0x0048 +#define SMA_wUser_17 0x004a +#define SMA__size 0x004c + +#define INITCODEFILE "turtlebeach/msndinit.bin" +#define PERMCODEFILE "turtlebeach/msndperm.bin" +#define LONGNAME "MultiSound (Classic/Monterey/Tahiti)" + +#endif /* __MSND_CLASSIC_H */ diff --git a/sound/isa/msnd/msnd_midi.c b/sound/isa/msnd/msnd_midi.c new file mode 100644 index 00000000000..cb9aa4c4edd --- /dev/null +++ b/sound/isa/msnd/msnd_midi.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) by Jaroslav Kysela + * Copyright (c) 2009 by Krzysztof Helt + * Routines for control of MPU-401 in UART mode + * + * MPU-401 supports UART mode which is not capable generate transmit + * interrupts thus output is done via polling. Also, if irq < 0, then + * input is done also via polling. Do not expect good performance. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include +#include + +#include "msnd.h" + +#define MSNDMIDI_MODE_BIT_INPUT 0 +#define MSNDMIDI_MODE_BIT_OUTPUT 1 +#define MSNDMIDI_MODE_BIT_INPUT_TRIGGER 2 +#define MSNDMIDI_MODE_BIT_OUTPUT_TRIGGER 3 + +struct snd_msndmidi { + struct snd_msnd *dev; + + unsigned long mode; /* MSNDMIDI_MODE_XXXX */ + + struct snd_rawmidi_substream *substream_input; + + spinlock_t input_lock; +}; + +/* + * input/output open/close - protected by open_mutex in rawmidi.c + */ +static int snd_msndmidi_input_open(struct snd_rawmidi_substream *substream) +{ + struct snd_msndmidi *mpu; + + snd_printdd("snd_msndmidi_input_open()\n"); + + mpu = substream->rmidi->private_data; + + mpu->substream_input = substream; + + snd_msnd_enable_irq(mpu->dev); + + snd_msnd_send_dsp_cmd(mpu->dev, HDEX_MIDI_IN_START); + set_bit(MSNDMIDI_MODE_BIT_INPUT, &mpu->mode); + return 0; +} + +static int snd_msndmidi_input_close(struct snd_rawmidi_substream *substream) +{ + struct snd_msndmidi *mpu; + + mpu = substream->rmidi->private_data; + snd_msnd_send_dsp_cmd(mpu->dev, HDEX_MIDI_IN_STOP); + clear_bit(MSNDMIDI_MODE_BIT_INPUT, &mpu->mode); + mpu->substream_input = NULL; + snd_msnd_disable_irq(mpu->dev); + return 0; +} + +static void snd_msndmidi_input_drop(struct snd_msndmidi *mpu) +{ + u16 tail; + + tail = readw(mpu->dev->MIDQ + JQS_wTail); + writew(tail, mpu->dev->MIDQ + JQS_wHead); +} + +/* + * trigger input + */ +static void snd_msndmidi_input_trigger(struct snd_rawmidi_substream *substream, + int up) +{ + unsigned long flags; + struct snd_msndmidi *mpu; + + snd_printdd("snd_msndmidi_input_trigger(, %i)\n", up); + + mpu = substream->rmidi->private_data; + spin_lock_irqsave(&mpu->input_lock, flags); + if (up) { + if (!test_and_set_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, + &mpu->mode)) + snd_msndmidi_input_drop(mpu); + } else { + clear_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, &mpu->mode); + } + spin_unlock_irqrestore(&mpu->input_lock, flags); + if (up) + snd_msndmidi_input_read(mpu); +} + +void snd_msndmidi_input_read(void *mpuv) +{ + unsigned long flags; + struct snd_msndmidi *mpu = mpuv; + void *pwMIDQData = mpu->dev->mappedbase + MIDQ_DATA_BUFF; + + spin_lock_irqsave(&mpu->input_lock, flags); + while (readw(mpu->dev->MIDQ + JQS_wTail) != + readw(mpu->dev->MIDQ + JQS_wHead)) { + u16 wTmp, val; + val = readw(pwMIDQData + 2 * readw(mpu->dev->MIDQ + JQS_wHead)); + + if (test_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, + &mpu->mode)) + snd_rawmidi_receive(mpu->substream_input, + (unsigned char *)&val, 1); + + wTmp = readw(mpu->dev->MIDQ + JQS_wHead) + 1; + if (wTmp > readw(mpu->dev->MIDQ + JQS_wSize)) + writew(0, mpu->dev->MIDQ + JQS_wHead); + else + writew(wTmp, mpu->dev->MIDQ + JQS_wHead); + } + spin_unlock_irqrestore(&mpu->input_lock, flags); +} +EXPORT_SYMBOL(snd_msndmidi_input_read); + +static struct snd_rawmidi_ops snd_msndmidi_input = { + .open = snd_msndmidi_input_open, + .close = snd_msndmidi_input_close, + .trigger = snd_msndmidi_input_trigger, +}; + +static void snd_msndmidi_free(struct snd_rawmidi *rmidi) +{ + struct snd_msndmidi *mpu = rmidi->private_data; + kfree(mpu); +} + +int snd_msndmidi_new(struct snd_card *card, int device) +{ + struct snd_msnd *chip = card->private_data; + struct snd_msndmidi *mpu; + struct snd_rawmidi *rmidi; + int err; + + err = snd_rawmidi_new(card, "MSND-MIDI", device, 1, 1, &rmidi); + if (err < 0) + return err; + mpu = kcalloc(1, sizeof(*mpu), GFP_KERNEL); + if (mpu == NULL) { + snd_device_free(card, rmidi); + return -ENOMEM; + } + mpu->dev = chip; + chip->msndmidi_mpu = mpu; + rmidi->private_data = mpu; + rmidi->private_free = snd_msndmidi_free; + spin_lock_init(&mpu->input_lock); + strcpy(rmidi->name, "MSND MIDI"); + snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, + &snd_msndmidi_input); + rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; + return 0; +} diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c new file mode 100644 index 00000000000..70559223e8f --- /dev/null +++ b/sound/isa/msnd/msnd_pinnacle.c @@ -0,0 +1,1235 @@ +/********************************************************************* + * + * Linux multisound pinnacle/fiji driver for ALSA. + * + * 2002/06/30 Karsten Wiese: + * for now this is only used to build a pinnacle / fiji driver. + * the OSS parent of this code is designed to also support + * the multisound classic via the file msnd_classic.c. + * to make it easier for some brave heart to implemt classic + * support in alsa, i left all the MSND_CLASSIC tokens in this file. + * but for now this untested & undone. + * + * + * ripped from linux kernel 2.4.18 by Karsten Wiese. + * + * the following is a copy of the 2.4.18 OSS FREE file-heading comment: + * + * Turtle Beach MultiSound Sound Card Driver for Linux + * msnd_pinnacle.c / msnd_classic.c + * + * -- If MSND_CLASSIC is defined: + * + * -> driver for Turtle Beach Classic/Monterey/Tahiti + * + * -- Else + * + * -> driver for Turtle Beach Pinnacle/Fiji + * + * 12-3-2000 Modified IO port validation Steve Sycamore + * + * Copyright (C) 1998 Andrew Veliath + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + ********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef MSND_CLASSIC +# ifndef __alpha__ +# define SLOWIO +# endif +#endif +#include "msnd.h" +#ifdef MSND_CLASSIC +# include "msnd_classic.h" +# define LOGNAME "msnd_classic" +#else +# include "msnd_pinnacle.h" +# define LOGNAME "snd_msnd_pinnacle" +#endif + +static void __devinit set_default_audio_parameters(struct snd_msnd *chip) +{ + chip->play_sample_size = DEFSAMPLESIZE; + chip->play_sample_rate = DEFSAMPLERATE; + chip->play_channels = DEFCHANNELS; + chip->capture_sample_size = DEFSAMPLESIZE; + chip->capture_sample_rate = DEFSAMPLERATE; + chip->capture_channels = DEFCHANNELS; +} + +static void snd_msnd_eval_dsp_msg(struct snd_msnd *chip, u16 wMessage) +{ + switch (HIBYTE(wMessage)) { + case HIMT_PLAY_DONE: { + if (chip->banksPlayed < 3) + snd_printdd("%08X: HIMT_PLAY_DONE: %i\n", + (unsigned)jiffies, LOBYTE(wMessage)); + + if (chip->last_playbank == LOBYTE(wMessage)) { + snd_printdd("chip.last_playbank == LOBYTE(wMessage)\n"); + break; + } + chip->banksPlayed++; + + if (test_bit(F_WRITING, &chip->flags)) + snd_msnd_DAPQ(chip, 0); + + chip->last_playbank = LOBYTE(wMessage); + chip->playDMAPos += chip->play_period_bytes; + if (chip->playDMAPos > chip->playLimit) + chip->playDMAPos = 0; + snd_pcm_period_elapsed(chip->playback_substream); + + break; + } + case HIMT_RECORD_DONE: + if (chip->last_recbank == LOBYTE(wMessage)) + break; + chip->last_recbank = LOBYTE(wMessage); + chip->captureDMAPos += chip->capturePeriodBytes; + if (chip->captureDMAPos > (chip->captureLimit)) + chip->captureDMAPos = 0; + + if (test_bit(F_READING, &chip->flags)) + snd_msnd_DARQ(chip, chip->last_recbank); + + snd_pcm_period_elapsed(chip->capture_substream); + break; + + case HIMT_DSP: + switch (LOBYTE(wMessage)) { +#ifndef MSND_CLASSIC + case HIDSP_PLAY_UNDER: +#endif + case HIDSP_INT_PLAY_UNDER: + snd_printd(KERN_WARNING LOGNAME ": Play underflow %i\n", + chip->banksPlayed); + if (chip->banksPlayed > 2) + clear_bit(F_WRITING, &chip->flags); + break; + + case HIDSP_INT_RECORD_OVER: + snd_printd(KERN_WARNING LOGNAME ": Record overflow\n"); + clear_bit(F_READING, &chip->flags); + break; + + default: + snd_printd(KERN_WARNING LOGNAME + ": DSP message %d 0x%02x\n", + LOBYTE(wMessage), LOBYTE(wMessage)); + break; + } + break; + + case HIMT_MIDI_IN_UCHAR: + if (chip->msndmidi_mpu) + snd_msndmidi_input_read(chip->msndmidi_mpu); + break; + + default: + snd_printd(KERN_WARNING LOGNAME ": HIMT message %d 0x%02x\n", + HIBYTE(wMessage), HIBYTE(wMessage)); + break; + } +} + +static irqreturn_t snd_msnd_interrupt(int irq, void *dev_id) +{ + struct snd_msnd *chip = dev_id; + void *pwDSPQData = chip->mappedbase + DSPQ_DATA_BUFF; + + /* Send ack to DSP */ + /* inb(chip->io + HP_RXL); */ + + /* Evaluate queued DSP messages */ + while (readw(chip->DSPQ + JQS_wTail) != readw(chip->DSPQ + JQS_wHead)) { + u16 wTmp; + + snd_msnd_eval_dsp_msg(chip, + readw(pwDSPQData + 2 * readw(chip->DSPQ + JQS_wHead))); + + wTmp = readw(chip->DSPQ + JQS_wHead) + 1; + if (wTmp > readw(chip->DSPQ + JQS_wSize)) + writew(0, chip->DSPQ + JQS_wHead); + else + writew(wTmp, chip->DSPQ + JQS_wHead); + } + /* Send ack to DSP */ + inb(chip->io + HP_RXL); + return IRQ_HANDLED; +} + + +static int snd_msnd_reset_dsp(long io, unsigned char *info) +{ + int timeout = 100; + + outb(HPDSPRESET_ON, io + HP_DSPR); + msleep(1); +#ifndef MSND_CLASSIC + if (info) + *info = inb(io + HP_INFO); +#endif + outb(HPDSPRESET_OFF, io + HP_DSPR); + msleep(1); + while (timeout-- > 0) { + if (inb(io + HP_CVR) == HP_CVR_DEF) + return 0; + msleep(1); + } + snd_printk(KERN_ERR LOGNAME ": Cannot reset DSP\n"); + + return -EIO; +} + +static int __devinit snd_msnd_probe(struct snd_card *card) +{ + struct snd_msnd *chip = card->private_data; + unsigned char info; +#ifndef MSND_CLASSIC + char *xv, *rev = NULL; + char *pin = "TB Pinnacle", *fiji = "TB Fiji"; + char *pinfiji = "TB Pinnacle/Fiji"; +#endif + + if (!request_region(chip->io, DSP_NUMIO, "probing")) { + snd_printk(KERN_ERR LOGNAME ": I/O port conflict\n"); + return -ENODEV; + } + + if (snd_msnd_reset_dsp(chip->io, &info) < 0) { + release_region(chip->io, DSP_NUMIO); + return -ENODEV; + } + +#ifdef MSND_CLASSIC + strcpy(card->shortname, "Classic/Tahiti/Monterey"); + strcpy(card->longname, "Turtle Beach Multisound"); + printk(KERN_INFO LOGNAME ": %s, " + "I/O 0x%lx-0x%lx, IRQ %d, memory mapped to 0x%lX-0x%lX\n", + card->shortname, + chip->io, chip->io + DSP_NUMIO - 1, + chip->irq, + chip->base, chip->base + 0x7fff); +#else + switch (info >> 4) { + case 0xf: + xv = "<= 1.15"; + break; + case 0x1: + xv = "1.18/1.2"; + break; + case 0x2: + xv = "1.3"; + break; + case 0x3: + xv = "1.4"; + break; + default: + xv = "unknown"; + break; + } + + switch (info & 0x7) { + case 0x0: + rev = "I"; + strcpy(card->shortname, pin); + break; + case 0x1: + rev = "F"; + strcpy(card->shortname, pin); + break; + case 0x2: + rev = "G"; + strcpy(card->shortname, pin); + break; + case 0x3: + rev = "H"; + strcpy(card->shortname, pin); + break; + case 0x4: + rev = "E"; + strcpy(card->shortname, fiji); + break; + case 0x5: + rev = "C"; + strcpy(card->shortname, fiji); + break; + case 0x6: + rev = "D"; + strcpy(card->shortname, fiji); + break; + case 0x7: + rev = "A-B (Fiji) or A-E (Pinnacle)"; + strcpy(card->shortname, pinfiji); + break; + } + strcpy(card->longname, "Turtle Beach Multisound Pinnacle"); + printk(KERN_INFO LOGNAME ": %s revision %s, Xilinx version %s, " + "I/O 0x%lx-0x%lx, IRQ %d, memory mapped to 0x%lX-0x%lX\n", + card->shortname, + rev, xv, + chip->io, chip->io + DSP_NUMIO - 1, + chip->irq, + chip->base, chip->base + 0x7fff); +#endif + + release_region(chip->io, DSP_NUMIO); + return 0; +} + +static int snd_msnd_init_sma(struct snd_msnd *chip) +{ + static int initted; + u16 mastVolLeft, mastVolRight; + unsigned long flags; + +#ifdef MSND_CLASSIC + outb(chip->memid, chip->io + HP_MEMM); +#endif + outb(HPBLKSEL_0, chip->io + HP_BLKS); + /* Motorola 56k shared memory base */ + chip->SMA = chip->mappedbase + SMA_STRUCT_START; + + if (initted) { + mastVolLeft = readw(chip->SMA + SMA_wCurrMastVolLeft); + mastVolRight = readw(chip->SMA + SMA_wCurrMastVolRight); + } else + mastVolLeft = mastVolRight = 0; + memset_io(chip->mappedbase, 0, 0x8000); + + /* Critical section: bank 1 access */ + spin_lock_irqsave(&chip->lock, flags); + outb(HPBLKSEL_1, chip->io + HP_BLKS); + memset_io(chip->mappedbase, 0, 0x8000); + outb(HPBLKSEL_0, chip->io + HP_BLKS); + spin_unlock_irqrestore(&chip->lock, flags); + + /* Digital audio play queue */ + chip->DAPQ = chip->mappedbase + DAPQ_OFFSET; + snd_msnd_init_queue(chip->DAPQ, DAPQ_DATA_BUFF, DAPQ_BUFF_SIZE); + + /* Digital audio record queue */ + chip->DARQ = chip->mappedbase + DARQ_OFFSET; + snd_msnd_init_queue(chip->DARQ, DARQ_DATA_BUFF, DARQ_BUFF_SIZE); + + /* MIDI out queue */ + chip->MODQ = chip->mappedbase + MODQ_OFFSET; + snd_msnd_init_queue(chip->MODQ, MODQ_DATA_BUFF, MODQ_BUFF_SIZE); + + /* MIDI in queue */ + chip->MIDQ = chip->mappedbase + MIDQ_OFFSET; + snd_msnd_init_queue(chip->MIDQ, MIDQ_DATA_BUFF, MIDQ_BUFF_SIZE); + + /* DSP -> host message queue */ + chip->DSPQ = chip->mappedbase + DSPQ_OFFSET; + snd_msnd_init_queue(chip->DSPQ, DSPQ_DATA_BUFF, DSPQ_BUFF_SIZE); + + /* Setup some DSP values */ +#ifndef MSND_CLASSIC + writew(1, chip->SMA + SMA_wCurrPlayFormat); + writew(chip->play_sample_size, chip->SMA + SMA_wCurrPlaySampleSize); + writew(chip->play_channels, chip->SMA + SMA_wCurrPlayChannels); + writew(chip->play_sample_rate, chip->SMA + SMA_wCurrPlaySampleRate); +#endif + writew(chip->play_sample_rate, chip->SMA + SMA_wCalFreqAtoD); + writew(mastVolLeft, chip->SMA + SMA_wCurrMastVolLeft); + writew(mastVolRight, chip->SMA + SMA_wCurrMastVolRight); +#ifndef MSND_CLASSIC + writel(0x00010000, chip->SMA + SMA_dwCurrPlayPitch); + writel(0x00000001, chip->SMA + SMA_dwCurrPlayRate); +#endif + writew(0x303, chip->SMA + SMA_wCurrInputTagBits); + + initted = 1; + + return 0; +} + + +static int upload_dsp_code(struct snd_card *card) +{ + struct snd_msnd *chip = card->private_data; + const struct firmware *init_fw = NULL, *perm_fw = NULL; + int err; + + outb(HPBLKSEL_0, chip->io + HP_BLKS); + + err = request_firmware(&init_fw, INITCODEFILE, card->dev); + if (err < 0) { + printk(KERN_ERR LOGNAME ": Error loading " INITCODEFILE); + goto cleanup1; + } + err = request_firmware(&perm_fw, PERMCODEFILE, card->dev); + if (err < 0) { + printk(KERN_ERR LOGNAME ": Error loading " PERMCODEFILE); + goto cleanup; + } + + memcpy_toio(chip->mappedbase, perm_fw->data, perm_fw->size); + if (snd_msnd_upload_host(chip, init_fw->data, init_fw->size) < 0) { + printk(KERN_WARNING LOGNAME ": Error uploading to DSP\n"); + err = -ENODEV; + goto cleanup; + } + printk(KERN_INFO LOGNAME ": DSP firmware uploaded\n"); + err = 0; + +cleanup: + release_firmware(perm_fw); +cleanup1: + release_firmware(init_fw); + return err; +} + +#ifdef MSND_CLASSIC +static void reset_proteus(struct snd_msnd *chip) +{ + outb(HPPRORESET_ON, chip->io + HP_PROR); + msleep(TIME_PRO_RESET); + outb(HPPRORESET_OFF, chip->io + HP_PROR); + msleep(TIME_PRO_RESET_DONE); +} +#endif + +static int snd_msnd_initialize(struct snd_card *card) +{ + struct snd_msnd *chip = card->private_data; + int err, timeout; + +#ifdef MSND_CLASSIC + outb(HPWAITSTATE_0, chip->io + HP_WAIT); + outb(HPBITMODE_16, chip->io + HP_BITM); + + reset_proteus(chip); +#endif + err = snd_msnd_init_sma(chip); + if (err < 0) { + printk(KERN_WARNING LOGNAME ": Cannot initialize SMA\n"); + return err; + } + + err = snd_msnd_reset_dsp(chip->io, NULL); + if (err < 0) + return err; + + err = upload_dsp_code(card); + if (err < 0) { + printk(KERN_WARNING LOGNAME ": Cannot upload DSP code\n"); + return err; + } + + timeout = 200; + + while (readw(chip->mappedbase)) { + msleep(1); + if (!timeout--) { + snd_printd(KERN_ERR LOGNAME ": DSP reset timeout\n"); + return -EIO; + } + } + + snd_msndmix_setup(chip); + return 0; +} + +static int snd_msnd_dsp_full_reset(struct snd_card *card) +{ + struct snd_msnd *chip = card->private_data; + int rv; + + if (test_bit(F_RESETTING, &chip->flags) || ++chip->nresets > 10) + return 0; + + set_bit(F_RESETTING, &chip->flags); + snd_msnd_dsp_halt(chip, NULL); /* Unconditionally halt */ + + rv = snd_msnd_initialize(card); + if (rv) + printk(KERN_WARNING LOGNAME ": DSP reset failed\n"); + snd_msndmix_force_recsrc(chip, 0); + clear_bit(F_RESETTING, &chip->flags); + return rv; +} + +static int snd_msnd_dev_free(struct snd_device *device) +{ + snd_printdd("snd_msnd_chip_free()\n"); + return 0; +} + +static int snd_msnd_send_dsp_cmd_chk(struct snd_msnd *chip, u8 cmd) +{ + if (snd_msnd_send_dsp_cmd(chip, cmd) == 0) + return 0; + snd_msnd_dsp_full_reset(chip->card); + return snd_msnd_send_dsp_cmd(chip, cmd); +} + +static int __devinit snd_msnd_calibrate_adc(struct snd_msnd *chip, u16 srate) +{ + snd_printdd("snd_msnd_calibrate_adc(%i)\n", srate); + writew(srate, chip->SMA + SMA_wCalFreqAtoD); + if (chip->calibrate_signal == 0) + writew(readw(chip->SMA + SMA_wCurrHostStatusFlags) + | 0x0001, chip->SMA + SMA_wCurrHostStatusFlags); + else + writew(readw(chip->SMA + SMA_wCurrHostStatusFlags) + & ~0x0001, chip->SMA + SMA_wCurrHostStatusFlags); + if (snd_msnd_send_word(chip, 0, 0, HDEXAR_CAL_A_TO_D) == 0 && + snd_msnd_send_dsp_cmd_chk(chip, HDEX_AUX_REQ) == 0) { + schedule_timeout_interruptible(msecs_to_jiffies(333)); + return 0; + } + printk(KERN_WARNING LOGNAME ": ADC calibration failed\n"); + return -EIO; +} + +/* + * ALSA callback function, called when attempting to open the MIDI device. + */ +static int snd_msnd_mpu401_open(struct snd_mpu401 *mpu) +{ + snd_msnd_enable_irq(mpu->private_data); + snd_msnd_send_dsp_cmd(mpu->private_data, HDEX_MIDI_IN_START); + return 0; +} + +static void snd_msnd_mpu401_close(struct snd_mpu401 *mpu) +{ + snd_msnd_send_dsp_cmd(mpu->private_data, HDEX_MIDI_IN_STOP); + snd_msnd_disable_irq(mpu->private_data); +} + +static long mpu_io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; +static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; + +static int __devinit snd_msnd_attach(struct snd_card *card) +{ + struct snd_msnd *chip = card->private_data; + int err; + static struct snd_device_ops ops = { + .dev_free = snd_msnd_dev_free, + }; + + err = request_irq(chip->irq, snd_msnd_interrupt, 0, card->shortname, + chip); + if (err < 0) { + printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", chip->irq); + return err; + } + request_region(chip->io, DSP_NUMIO, card->shortname); + + if (!request_mem_region(chip->base, BUFFSIZE, card->shortname)) { + printk(KERN_ERR LOGNAME + ": unable to grab memory region 0x%lx-0x%lx\n", + chip->base, chip->base + BUFFSIZE - 1); + release_region(chip->io, DSP_NUMIO); + free_irq(chip->irq, chip); + return -EBUSY; + } + chip->mappedbase = ioremap_nocache(chip->base, 0x8000); + if (!chip->mappedbase) { + printk(KERN_ERR LOGNAME + ": unable to map memory region 0x%lx-0x%lx\n", + chip->base, chip->base + BUFFSIZE - 1); + err = -EIO; + goto err_release_region; + } + + err = snd_msnd_dsp_full_reset(card); + if (err < 0) + goto err_release_region; + + /* Register device */ + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) + goto err_release_region; + + err = snd_msnd_pcm(card, 0, NULL); + if (err < 0) { + printk(KERN_ERR LOGNAME ": error creating new PCM device\n"); + goto err_release_region; + } + + err = snd_msndmix_new(card); + if (err < 0) { + printk(KERN_ERR LOGNAME ": error creating new Mixer device\n"); + goto err_release_region; + } + + + if (mpu_io[0] != SNDRV_AUTO_PORT) { + struct snd_mpu401 *mpu; + + err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, + mpu_io[0], + MPU401_MODE_INPUT | + MPU401_MODE_OUTPUT, + mpu_irq[0], IRQF_DISABLED, + &chip->rmidi); + if (err < 0) { + printk(KERN_ERR LOGNAME + ": error creating new Midi device\n"); + goto err_release_region; + } + mpu = chip->rmidi->private_data; + + mpu->open_input = snd_msnd_mpu401_open; + mpu->close_input = snd_msnd_mpu401_close; + mpu->private_data = chip; + } + + disable_irq(chip->irq); + snd_msnd_calibrate_adc(chip, chip->play_sample_rate); + snd_msndmix_force_recsrc(chip, 0); + + err = snd_card_register(card); + if (err < 0) + goto err_release_region; + + return 0; + +err_release_region: + if (chip->mappedbase) + iounmap(chip->mappedbase); + release_mem_region(chip->base, BUFFSIZE); + release_region(chip->io, DSP_NUMIO); + free_irq(chip->irq, chip); + return err; +} + + +static void __devexit snd_msnd_unload(struct snd_card *card) +{ + struct snd_msnd *chip = card->private_data; + + iounmap(chip->mappedbase); + release_mem_region(chip->base, BUFFSIZE); + release_region(chip->io, DSP_NUMIO); + free_irq(chip->irq, chip); + snd_card_free(card); +} + +#ifndef MSND_CLASSIC + +/* Pinnacle/Fiji Logical Device Configuration */ + +static int __devinit snd_msnd_write_cfg(int cfg, int reg, int value) +{ + outb(reg, cfg); + outb(value, cfg + 1); + if (value != inb(cfg + 1)) { + printk(KERN_ERR LOGNAME ": snd_msnd_write_cfg: I/O error\n"); + return -EIO; + } + return 0; +} + +static int __devinit snd_msnd_write_cfg_io0(int cfg, int num, u16 io) +{ + if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) + return -EIO; + if (snd_msnd_write_cfg(cfg, IREG_IO0_BASEHI, HIBYTE(io))) + return -EIO; + if (snd_msnd_write_cfg(cfg, IREG_IO0_BASELO, LOBYTE(io))) + return -EIO; + return 0; +} + +static int __devinit snd_msnd_write_cfg_io1(int cfg, int num, u16 io) +{ + if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) + return -EIO; + if (snd_msnd_write_cfg(cfg, IREG_IO1_BASEHI, HIBYTE(io))) + return -EIO; + if (snd_msnd_write_cfg(cfg, IREG_IO1_BASELO, LOBYTE(io))) + return -EIO; + return 0; +} + +static int __devinit snd_msnd_write_cfg_irq(int cfg, int num, u16 irq) +{ + if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) + return -EIO; + if (snd_msnd_write_cfg(cfg, IREG_IRQ_NUMBER, LOBYTE(irq))) + return -EIO; + if (snd_msnd_write_cfg(cfg, IREG_IRQ_TYPE, IRQTYPE_EDGE)) + return -EIO; + return 0; +} + +static int __devinit snd_msnd_write_cfg_mem(int cfg, int num, int mem) +{ + u16 wmem; + + mem >>= 8; + wmem = (u16)(mem & 0xfff); + if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) + return -EIO; + if (snd_msnd_write_cfg(cfg, IREG_MEMBASEHI, HIBYTE(wmem))) + return -EIO; + if (snd_msnd_write_cfg(cfg, IREG_MEMBASELO, LOBYTE(wmem))) + return -EIO; + if (wmem && snd_msnd_write_cfg(cfg, IREG_MEMCONTROL, + MEMTYPE_HIADDR | MEMTYPE_16BIT)) + return -EIO; + return 0; +} + +static int __devinit snd_msnd_activate_logical(int cfg, int num) +{ + if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) + return -EIO; + if (snd_msnd_write_cfg(cfg, IREG_ACTIVATE, LD_ACTIVATE)) + return -EIO; + return 0; +} + +static int __devinit snd_msnd_write_cfg_logical(int cfg, int num, u16 io0, + u16 io1, u16 irq, int mem) +{ + if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) + return -EIO; + if (snd_msnd_write_cfg_io0(cfg, num, io0)) + return -EIO; + if (snd_msnd_write_cfg_io1(cfg, num, io1)) + return -EIO; + if (snd_msnd_write_cfg_irq(cfg, num, irq)) + return -EIO; + if (snd_msnd_write_cfg_mem(cfg, num, mem)) + return -EIO; + if (snd_msnd_activate_logical(cfg, num)) + return -EIO; + return 0; +} + +static int __devinit snd_msnd_pinnacle_cfg_reset(int cfg) +{ + int i; + + /* Reset devices if told to */ + printk(KERN_INFO LOGNAME ": Resetting all devices\n"); + for (i = 0; i < 4; ++i) + if (snd_msnd_write_cfg_logical(cfg, i, 0, 0, 0, 0)) + return -EIO; + + return 0; +} +#endif + +static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ +static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ + +module_param_array(index, int, NULL, S_IRUGO); +MODULE_PARM_DESC(index, "Index value for msnd_pinnacle soundcard."); +module_param_array(id, charp, NULL, S_IRUGO); +MODULE_PARM_DESC(id, "ID string for msnd_pinnacle soundcard."); + +static long io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; +static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; +static long mem[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; + +static long cfg[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; + +#ifndef MSND_CLASSIC +/* Extra Peripheral Configuration (Default: Disable) */ +static long ide_io0[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; +static long ide_io1[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; +static int ide_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; + +static long joystick_io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; +/* If we have the digital daugherboard... */ +static int digital[SNDRV_CARDS]; + +/* Extra Peripheral Configuration */ +static int reset[SNDRV_CARDS]; +#endif + +static int write_ndelay[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 1 }; + +static int calibrate_signal; + +#ifdef CONFIG_PNP +static int isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; +module_param_array(isapnp, bool, NULL, 0444); +MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard."); +#endif + +MODULE_AUTHOR("Karsten Wiese "); +MODULE_DESCRIPTION("Turtle Beach " LONGNAME " Linux Driver"); +MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(INITCODEFILE); +MODULE_FIRMWARE(PERMCODEFILE); + +module_param_array(io, long, NULL, S_IRUGO); +MODULE_PARM_DESC(io, "IO port #"); +module_param_array(irq, int, NULL, S_IRUGO); +module_param_array(mem, long, NULL, S_IRUGO); +module_param_array(write_ndelay, int, NULL, S_IRUGO); +module_param(calibrate_signal, int, S_IRUGO); +#ifndef MSND_CLASSIC +module_param_array(digital, int, NULL, S_IRUGO); +module_param_array(cfg, long, NULL, S_IRUGO); +module_param_array(reset, int, 0, S_IRUGO); +module_param_array(mpu_io, long, NULL, S_IRUGO); +module_param_array(mpu_irq, int, NULL, S_IRUGO); +module_param_array(ide_io0, long, NULL, S_IRUGO); +module_param_array(ide_io1, long, NULL, S_IRUGO); +module_param_array(ide_irq, int, NULL, S_IRUGO); +module_param_array(joystick_io, long, NULL, S_IRUGO); +#endif + + +static int __devinit snd_msnd_isa_match(struct device *pdev, unsigned int i) +{ + if (io[i] == SNDRV_AUTO_PORT) + return 0; + + if (irq[i] == SNDRV_AUTO_PORT || mem[i] == SNDRV_AUTO_PORT) { + printk(KERN_WARNING LOGNAME ": io, irq and mem must be set\n"); + return 0; + } + +#ifdef MSND_CLASSIC + if (!(io[i] == 0x290 || + io[i] == 0x260 || + io[i] == 0x250 || + io[i] == 0x240 || + io[i] == 0x230 || + io[i] == 0x220 || + io[i] == 0x210 || + io[i] == 0x3e0)) { + printk(KERN_ERR LOGNAME ": \"io\" - DSP I/O base must be set " + " to 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x290, " + "or 0x3E0\n"); + return 0; + } +#else + if (io[i] < 0x100 || io[i] > 0x3e0 || (io[i] % 0x10) != 0) { + printk(KERN_ERR LOGNAME + ": \"io\" - DSP I/O base must within the range 0x100 " + "to 0x3E0 and must be evenly divisible by 0x10\n"); + return 0; + } +#endif /* MSND_CLASSIC */ + + if (!(irq[i] == 5 || + irq[i] == 7 || + irq[i] == 9 || + irq[i] == 10 || + irq[i] == 11 || + irq[i] == 12)) { + printk(KERN_ERR LOGNAME + ": \"irq\" - must be set to 5, 7, 9, 10, 11 or 12\n"); + return 0; + } + + if (!(mem[i] == 0xb0000 || + mem[i] == 0xc8000 || + mem[i] == 0xd0000 || + mem[i] == 0xd8000 || + mem[i] == 0xe0000 || + mem[i] == 0xe8000)) { + printk(KERN_ERR LOGNAME ": \"mem\" - must be set to " + "0xb0000, 0xc8000, 0xd0000, 0xd8000, 0xe0000 or " + "0xe8000\n"); + return 0; + } + +#ifndef MSND_CLASSIC + if (cfg[i] == SNDRV_AUTO_PORT) { + printk(KERN_INFO LOGNAME ": Assuming PnP mode\n"); + } else if (cfg[i] != 0x250 && cfg[i] != 0x260 && cfg[i] != 0x270) { + printk(KERN_INFO LOGNAME + ": Config port must be 0x250, 0x260 or 0x270 " + "(or unspecified for PnP mode)\n"); + return 0; + } +#endif /* MSND_CLASSIC */ + + return 1; +} + +static int __devinit snd_msnd_isa_probe(struct device *pdev, unsigned int idx) +{ + int err; + struct snd_card *card; + struct snd_msnd *chip; + + if (isapnp[idx] || cfg[idx] == SNDRV_AUTO_PORT) { + printk(KERN_INFO LOGNAME ": Assuming PnP mode\n"); + return -ENODEV; + } + + err = snd_card_create(index[idx], id[idx], THIS_MODULE, + sizeof(struct snd_msnd), &card); + if (err < 0) + return err; + + snd_card_set_dev(card, pdev); + chip = card->private_data; + chip->card = card; + +#ifdef MSND_CLASSIC + switch (irq[idx]) { + case 5: + chip->irqid = HPIRQ_5; break; + case 7: + chip->irqid = HPIRQ_7; break; + case 9: + chip->irqid = HPIRQ_9; break; + case 10: + chip->irqid = HPIRQ_10; break; + case 11: + chip->irqid = HPIRQ_11; break; + case 12: + chip->irqid = HPIRQ_12; break; + } + + switch (mem[idx]) { + case 0xb0000: + chip->memid = HPMEM_B000; break; + case 0xc8000: + chip->memid = HPMEM_C800; break; + case 0xd0000: + chip->memid = HPMEM_D000; break; + case 0xd8000: + chip->memid = HPMEM_D800; break; + case 0xe0000: + chip->memid = HPMEM_E000; break; + case 0xe8000: + chip->memid = HPMEM_E800; break; + } +#else + printk(KERN_INFO LOGNAME ": Non-PnP mode: configuring at port 0x%lx\n", + cfg[idx]); + + if (!request_region(cfg[idx], 2, "Pinnacle/Fiji Config")) { + printk(KERN_ERR LOGNAME ": Config port 0x%lx conflict\n", + cfg[idx]); + snd_card_free(card); + return -EIO; + } + if (reset[idx]) + if (snd_msnd_pinnacle_cfg_reset(cfg[idx])) { + err = -EIO; + goto cfg_error; + } + + /* DSP */ + err = snd_msnd_write_cfg_logical(cfg[idx], 0, + io[idx], 0, + irq[idx], mem[idx]); + + if (err) + goto cfg_error; + + /* The following are Pinnacle specific */ + + /* MPU */ + if (mpu_io[idx] != SNDRV_AUTO_PORT + && mpu_irq[idx] != SNDRV_AUTO_IRQ) { + printk(KERN_INFO LOGNAME + ": Configuring MPU to I/O 0x%lx IRQ %d\n", + mpu_io[idx], mpu_irq[idx]); + err = snd_msnd_write_cfg_logical(cfg[idx], 1, + mpu_io[idx], 0, + mpu_irq[idx], 0); + + if (err) + goto cfg_error; + } + + /* IDE */ + if (ide_io0[idx] != SNDRV_AUTO_PORT + && ide_io1[idx] != SNDRV_AUTO_PORT + && ide_irq[idx] != SNDRV_AUTO_IRQ) { + printk(KERN_INFO LOGNAME + ": Configuring IDE to I/O 0x%lx, 0x%lx IRQ %d\n", + ide_io0[idx], ide_io1[idx], ide_irq[idx]); + err = snd_msnd_write_cfg_logical(cfg[idx], 2, + ide_io0[idx], ide_io1[idx], + ide_irq[idx], 0); + + if (err) + goto cfg_error; + } + + /* Joystick */ + if (joystick_io[idx] != SNDRV_AUTO_PORT) { + printk(KERN_INFO LOGNAME + ": Configuring joystick to I/O 0x%lx\n", + joystick_io[idx]); + err = snd_msnd_write_cfg_logical(cfg[idx], 3, + joystick_io[idx], 0, + 0, 0); + + if (err) + goto cfg_error; + } + release_region(cfg[idx], 2); + +#endif /* MSND_CLASSIC */ + + set_default_audio_parameters(chip); +#ifdef MSND_CLASSIC + chip->type = msndClassic; +#else + chip->type = msndPinnacle; +#endif + chip->io = io[idx]; + chip->irq = irq[idx]; + chip->base = mem[idx]; + + chip->calibrate_signal = calibrate_signal ? 1 : 0; + chip->recsrc = 0; + chip->dspq_data_buff = DSPQ_DATA_BUFF; + chip->dspq_buff_size = DSPQ_BUFF_SIZE; + if (write_ndelay[idx]) + clear_bit(F_DISABLE_WRITE_NDELAY, &chip->flags); + else + set_bit(F_DISABLE_WRITE_NDELAY, &chip->flags); +#ifndef MSND_CLASSIC + if (digital[idx]) + set_bit(F_HAVEDIGITAL, &chip->flags); +#endif + spin_lock_init(&chip->lock); + err = snd_msnd_probe(card); + if (err < 0) { + printk(KERN_ERR LOGNAME ": Probe failed\n"); + snd_card_free(card); + return err; + } + + err = snd_msnd_attach(card); + if (err < 0) { + printk(KERN_ERR LOGNAME ": Attach failed\n"); + snd_card_free(card); + return err; + } + dev_set_drvdata(pdev, card); + + return 0; + +#ifndef MSND_CLASSIC +cfg_error: + release_region(cfg[idx], 2); + snd_card_free(card); + return err; +#endif +} + +static int __devexit snd_msnd_isa_remove(struct device *pdev, unsigned int dev) +{ + snd_msnd_unload(dev_get_drvdata(pdev)); + dev_set_drvdata(pdev, NULL); + return 0; +} + +#define DEV_NAME "msnd-pinnacle" + +static struct isa_driver snd_msnd_driver = { + .match = snd_msnd_isa_match, + .probe = snd_msnd_isa_probe, + .remove = __devexit_p(snd_msnd_isa_remove), + /* FIXME: suspend, resume */ + .driver = { + .name = DEV_NAME + }, +}; + +#ifdef CONFIG_PNP +static int __devinit snd_msnd_pnp_detect(struct pnp_card_link *pcard, + const struct pnp_card_device_id *pid) +{ + static int idx; + struct pnp_dev *pnp_dev; + struct pnp_dev *mpu_dev; + struct snd_card *card; + struct snd_msnd *chip; + int ret; + + for ( ; idx < SNDRV_CARDS; idx++) { + if (isapnp[idx]) + break; + } + if (idx >= SNDRV_CARDS) + return -ENODEV; + + /* + * Check that we still have room for another sound card ... + */ + pnp_dev = pnp_request_card_device(pcard, pid->devs[0].id, NULL); + if (!pnp_dev) + return -ENODEV; + + mpu_dev = pnp_request_card_device(pcard, pid->devs[1].id, NULL); + if (!mpu_dev) + return -ENODEV; + + if (!pnp_is_active(pnp_dev) && pnp_activate_dev(pnp_dev) < 0) { + printk(KERN_INFO "msnd_pinnacle: device is inactive\n"); + return -EBUSY; + } + + if (!pnp_is_active(mpu_dev) && pnp_activate_dev(mpu_dev) < 0) { + printk(KERN_INFO "msnd_pinnacle: MPU device is inactive\n"); + return -EBUSY; + } + + /* + * Create a new ALSA sound card entry, in anticipation + * of detecting our hardware ... + */ + ret = snd_card_create(index[idx], id[idx], THIS_MODULE, + sizeof(struct snd_msnd), &card); + if (ret < 0) + return ret; + + chip = card->private_data; + chip->card = card; + snd_card_set_dev(card, &pcard->card->dev); + + /* + * Read the correct parameters off the ISA PnP bus ... + */ + io[idx] = pnp_port_start(pnp_dev, 0); + irq[idx] = pnp_irq(pnp_dev, 0); + mem[idx] = pnp_mem_start(pnp_dev, 0); + mpu_io[idx] = pnp_port_start(mpu_dev, 0); + mpu_irq[idx] = pnp_irq(mpu_dev, 0); + + set_default_audio_parameters(chip); +#ifdef MSND_CLASSIC + chip->type = msndClassic; +#else + chip->type = msndPinnacle; +#endif + chip->io = io[idx]; + chip->irq = irq[idx]; + chip->base = mem[idx]; + + chip->calibrate_signal = calibrate_signal ? 1 : 0; + chip->recsrc = 0; + chip->dspq_data_buff = DSPQ_DATA_BUFF; + chip->dspq_buff_size = DSPQ_BUFF_SIZE; + if (write_ndelay[idx]) + clear_bit(F_DISABLE_WRITE_NDELAY, &chip->flags); + else + set_bit(F_DISABLE_WRITE_NDELAY, &chip->flags); +#ifndef MSND_CLASSIC + if (digital[idx]) + set_bit(F_HAVEDIGITAL, &chip->flags); +#endif + spin_lock_init(&chip->lock); + ret = snd_msnd_probe(card); + if (ret < 0) { + printk(KERN_ERR LOGNAME ": Probe failed\n"); + goto _release_card; + } + + ret = snd_msnd_attach(card); + if (ret < 0) { + printk(KERN_ERR LOGNAME ": Attach failed\n"); + goto _release_card; + } + + pnp_set_card_drvdata(pcard, card); + ++idx; + return 0; + +_release_card: + snd_card_free(card); + return ret; +} + +static void __devexit snd_msnd_pnp_remove(struct pnp_card_link *pcard) +{ + snd_msnd_unload(pnp_get_card_drvdata(pcard)); + pnp_set_card_drvdata(pcard, NULL); +} + +static int isa_registered; +static int pnp_registered; + +static struct pnp_card_device_id msnd_pnpids[] = { + /* Pinnacle PnP */ + { .id = "BVJ0440", .devs = { { "TBS0000" }, { "TBS0001" } } }, + { .id = "" } /* end */ +}; + +MODULE_DEVICE_TABLE(pnp_card, msnd_pnpids); + +static struct pnp_card_driver msnd_pnpc_driver = { + .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, + .name = "msnd_pinnacle", + .id_table = msnd_pnpids, + .probe = snd_msnd_pnp_detect, + .remove = __devexit_p(snd_msnd_pnp_remove), +}; +#endif /* CONFIG_PNP */ + +static int __init snd_msnd_init(void) +{ + int err; + + err = isa_register_driver(&snd_msnd_driver, SNDRV_CARDS); +#ifdef CONFIG_PNP + if (!err) + isa_registered = 1; + + err = pnp_register_card_driver(&msnd_pnpc_driver); + if (!err) + pnp_registered = 1; + + if (isa_registered) + err = 0; +#endif + return err; +} + +static void __exit snd_msnd_exit(void) +{ +#ifdef CONFIG_PNP + if (pnp_registered) + pnp_unregister_card_driver(&msnd_pnpc_driver); + if (isa_registered) +#endif + isa_unregister_driver(&snd_msnd_driver); +} + +module_init(snd_msnd_init); +module_exit(snd_msnd_exit); + diff --git a/sound/isa/msnd/msnd_pinnacle.h b/sound/isa/msnd/msnd_pinnacle.h new file mode 100644 index 00000000000..48318d1ee34 --- /dev/null +++ b/sound/isa/msnd/msnd_pinnacle.h @@ -0,0 +1,181 @@ +/********************************************************************* + * + * msnd_pinnacle.h + * + * Turtle Beach MultiSound Sound Card Driver for Linux + * + * Some parts of this header file were derived from the Turtle Beach + * MultiSound Driver Development Kit. + * + * Copyright (C) 1998 Andrew Veliath + * Copyright (C) 1993 Turtle Beach Systems, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + ********************************************************************/ +#ifndef __MSND_PINNACLE_H +#define __MSND_PINNACLE_H + +#define DSP_NUMIO 0x08 + +#define IREG_LOGDEVICE 0x07 +#define IREG_ACTIVATE 0x30 +#define LD_ACTIVATE 0x01 +#define LD_DISACTIVATE 0x00 +#define IREG_EECONTROL 0x3F +#define IREG_MEMBASEHI 0x40 +#define IREG_MEMBASELO 0x41 +#define IREG_MEMCONTROL 0x42 +#define IREG_MEMRANGEHI 0x43 +#define IREG_MEMRANGELO 0x44 +#define MEMTYPE_8BIT 0x00 +#define MEMTYPE_16BIT 0x02 +#define MEMTYPE_RANGE 0x00 +#define MEMTYPE_HIADDR 0x01 +#define IREG_IO0_BASEHI 0x60 +#define IREG_IO0_BASELO 0x61 +#define IREG_IO1_BASEHI 0x62 +#define IREG_IO1_BASELO 0x63 +#define IREG_IRQ_NUMBER 0x70 +#define IREG_IRQ_TYPE 0x71 +#define IRQTYPE_HIGH 0x02 +#define IRQTYPE_LOW 0x00 +#define IRQTYPE_LEVEL 0x01 +#define IRQTYPE_EDGE 0x00 + +#define HP_DSPR 0x04 +#define HP_BLKS 0x04 + +#define HPDSPRESET_OFF 2 +#define HPDSPRESET_ON 0 + +#define HPBLKSEL_0 2 +#define HPBLKSEL_1 3 + +#define HIMT_DAT_OFF 0x03 + +#define HIDSP_PLAY_UNDER 0x00 +#define HIDSP_INT_PLAY_UNDER 0x01 +#define HIDSP_SSI_TX_UNDER 0x02 +#define HIDSP_RECQ_OVERFLOW 0x08 +#define HIDSP_INT_RECORD_OVER 0x09 +#define HIDSP_SSI_RX_OVERFLOW 0x0a + +#define HIDSP_MIDI_IN_OVER 0x10 + +#define HIDSP_MIDI_FRAME_ERR 0x11 +#define HIDSP_MIDI_PARITY_ERR 0x12 +#define HIDSP_MIDI_OVERRUN_ERR 0x13 + +#define HIDSP_INPUT_CLIPPING 0x20 +#define HIDSP_MIX_CLIPPING 0x30 +#define HIDSP_DAT_IN_OFF 0x21 + +#define TIME_PRO_RESET_DONE 0x028A +#define TIME_PRO_SYSEX 0x001E +#define TIME_PRO_RESET 0x0032 + +#define DAR_BUFF_SIZE 0x1000 + +#define MIDQ_BUFF_SIZE 0x800 +#define DSPQ_BUFF_SIZE 0x5A0 + +#define DSPQ_DATA_BUFF 0x7860 + +#define MOP_WAVEHDR 0 +#define MOP_EXTOUT 1 +#define MOP_HWINIT 0xfe +#define MOP_NONE 0xff +#define MOP_MAX 1 + +#define MIP_EXTIN 0 +#define MIP_WAVEHDR 1 +#define MIP_HWINIT 0xfe +#define MIP_MAX 1 + +/* Pinnacle/Fiji SMA Common Data */ +#define SMA_wCurrPlayBytes 0x0000 +#define SMA_wCurrRecordBytes 0x0002 +#define SMA_wCurrPlayVolLeft 0x0004 +#define SMA_wCurrPlayVolRight 0x0006 +#define SMA_wCurrInVolLeft 0x0008 +#define SMA_wCurrInVolRight 0x000a +#define SMA_wCurrMHdrVolLeft 0x000c +#define SMA_wCurrMHdrVolRight 0x000e +#define SMA_dwCurrPlayPitch 0x0010 +#define SMA_dwCurrPlayRate 0x0014 +#define SMA_wCurrMIDIIOPatch 0x0018 +#define SMA_wCurrPlayFormat 0x001a +#define SMA_wCurrPlaySampleSize 0x001c +#define SMA_wCurrPlayChannels 0x001e +#define SMA_wCurrPlaySampleRate 0x0020 +#define SMA_wCurrRecordFormat 0x0022 +#define SMA_wCurrRecordSampleSize 0x0024 +#define SMA_wCurrRecordChannels 0x0026 +#define SMA_wCurrRecordSampleRate 0x0028 +#define SMA_wCurrDSPStatusFlags 0x002a +#define SMA_wCurrHostStatusFlags 0x002c +#define SMA_wCurrInputTagBits 0x002e +#define SMA_wCurrLeftPeak 0x0030 +#define SMA_wCurrRightPeak 0x0032 +#define SMA_bMicPotPosLeft 0x0034 +#define SMA_bMicPotPosRight 0x0035 +#define SMA_bMicPotMaxLeft 0x0036 +#define SMA_bMicPotMaxRight 0x0037 +#define SMA_bInPotPosLeft 0x0038 +#define SMA_bInPotPosRight 0x0039 +#define SMA_bAuxPotPosLeft 0x003a +#define SMA_bAuxPotPosRight 0x003b +#define SMA_bInPotMaxLeft 0x003c +#define SMA_bInPotMaxRight 0x003d +#define SMA_bAuxPotMaxLeft 0x003e +#define SMA_bAuxPotMaxRight 0x003f +#define SMA_bInPotMaxMethod 0x0040 +#define SMA_bAuxPotMaxMethod 0x0041 +#define SMA_wCurrMastVolLeft 0x0042 +#define SMA_wCurrMastVolRight 0x0044 +#define SMA_wCalFreqAtoD 0x0046 +#define SMA_wCurrAuxVolLeft 0x0048 +#define SMA_wCurrAuxVolRight 0x004a +#define SMA_wCurrPlay1VolLeft 0x004c +#define SMA_wCurrPlay1VolRight 0x004e +#define SMA_wCurrPlay2VolLeft 0x0050 +#define SMA_wCurrPlay2VolRight 0x0052 +#define SMA_wCurrPlay3VolLeft 0x0054 +#define SMA_wCurrPlay3VolRight 0x0056 +#define SMA_wCurrPlay4VolLeft 0x0058 +#define SMA_wCurrPlay4VolRight 0x005a +#define SMA_wCurrPlay1PeakLeft 0x005c +#define SMA_wCurrPlay1PeakRight 0x005e +#define SMA_wCurrPlay2PeakLeft 0x0060 +#define SMA_wCurrPlay2PeakRight 0x0062 +#define SMA_wCurrPlay3PeakLeft 0x0064 +#define SMA_wCurrPlay3PeakRight 0x0066 +#define SMA_wCurrPlay4PeakLeft 0x0068 +#define SMA_wCurrPlay4PeakRight 0x006a +#define SMA_wCurrPlayPeakLeft 0x006c +#define SMA_wCurrPlayPeakRight 0x006e +#define SMA_wCurrDATSR 0x0070 +#define SMA_wCurrDATRXCHNL 0x0072 +#define SMA_wCurrDATTXCHNL 0x0074 +#define SMA_wCurrDATRXRate 0x0076 +#define SMA_dwDSPPlayCount 0x0078 +#define SMA__size 0x007c + +#define INITCODEFILE "turtlebeach/pndspini.bin" +#define PERMCODEFILE "turtlebeach/pndsperm.bin" +#define LONGNAME "MultiSound (Pinnacle/Fiji)" + +#endif /* __MSND_PINNACLE_H */ diff --git a/sound/isa/msnd/msnd_pinnacle_mixer.c b/sound/isa/msnd/msnd_pinnacle_mixer.c new file mode 100644 index 00000000000..494058a1a50 --- /dev/null +++ b/sound/isa/msnd/msnd_pinnacle_mixer.c @@ -0,0 +1,343 @@ +/*************************************************************************** + msnd_pinnacle_mixer.c - description + ------------------- + begin : Fre Jun 7 2002 + copyright : (C) 2002 by karsten wiese + email : annabellesgarden@yahoo.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include + +#include +#include +#include "msnd.h" +#include "msnd_pinnacle.h" + + +#define MSND_MIXER_VOLUME 0 +#define MSND_MIXER_PCM 1 +#define MSND_MIXER_AUX 2 /* Input source 1 (aux1) */ +#define MSND_MIXER_IMIX 3 /* Recording monitor */ +#define MSND_MIXER_SYNTH 4 +#define MSND_MIXER_SPEAKER 5 +#define MSND_MIXER_LINE 6 +#define MSND_MIXER_MIC 7 +#define MSND_MIXER_RECLEV 11 /* Recording level */ +#define MSND_MIXER_IGAIN 12 /* Input gain */ +#define MSND_MIXER_OGAIN 13 /* Output gain */ +#define MSND_MIXER_DIGITAL 17 /* Digital (input) 1 */ + +/* Device mask bits */ + +#define MSND_MASK_VOLUME (1 << MSND_MIXER_VOLUME) +#define MSND_MASK_SYNTH (1 << MSND_MIXER_SYNTH) +#define MSND_MASK_PCM (1 << MSND_MIXER_PCM) +#define MSND_MASK_SPEAKER (1 << MSND_MIXER_SPEAKER) +#define MSND_MASK_LINE (1 << MSND_MIXER_LINE) +#define MSND_MASK_MIC (1 << MSND_MIXER_MIC) +#define MSND_MASK_IMIX (1 << MSND_MIXER_IMIX) +#define MSND_MASK_RECLEV (1 << MSND_MIXER_RECLEV) +#define MSND_MASK_IGAIN (1 << MSND_MIXER_IGAIN) +#define MSND_MASK_OGAIN (1 << MSND_MIXER_OGAIN) +#define MSND_MASK_AUX (1 << MSND_MIXER_AUX) +#define MSND_MASK_DIGITAL (1 << MSND_MIXER_DIGITAL) + +static int snd_msndmix_info_mux(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + static char *texts[3] = { + "Analog", "MASS", "SPDIF", + }; + struct snd_msnd *chip = snd_kcontrol_chip(kcontrol); + unsigned items = test_bit(F_HAVEDIGITAL, &chip->flags) ? 3 : 2; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + uinfo->value.enumerated.items = items; + if (uinfo->value.enumerated.item >= items) + uinfo->value.enumerated.item = items - 1; + strcpy(uinfo->value.enumerated.name, + texts[uinfo->value.enumerated.item]); + return 0; +} + +static int snd_msndmix_get_mux(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_msnd *chip = snd_kcontrol_chip(kcontrol); + /* MSND_MASK_IMIX is the default */ + ucontrol->value.enumerated.item[0] = 0; + + if (chip->recsrc & MSND_MASK_SYNTH) { + ucontrol->value.enumerated.item[0] = 1; + } else if ((chip->recsrc & MSND_MASK_DIGITAL) && + test_bit(F_HAVEDIGITAL, &chip->flags)) { + ucontrol->value.enumerated.item[0] = 2; + } + + + return 0; +} + +static int snd_msndmix_set_mux(struct snd_msnd *chip, int val) +{ + unsigned newrecsrc; + int change; + unsigned char msndbyte; + + switch (val) { + case 0: + newrecsrc = MSND_MASK_IMIX; + msndbyte = HDEXAR_SET_ANA_IN; + break; + case 1: + newrecsrc = MSND_MASK_SYNTH; + msndbyte = HDEXAR_SET_SYNTH_IN; + break; + case 2: + newrecsrc = MSND_MASK_DIGITAL; + msndbyte = HDEXAR_SET_DAT_IN; + break; + default: + return -EINVAL; + } + change = newrecsrc != chip->recsrc; + if (change) { + change = 0; + if (!snd_msnd_send_word(chip, 0, 0, msndbyte)) + if (!snd_msnd_send_dsp_cmd(chip, HDEX_AUX_REQ)) { + chip->recsrc = newrecsrc; + change = 1; + } + } + return change; +} + +static int snd_msndmix_put_mux(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_msnd *msnd = snd_kcontrol_chip(kcontrol); + return snd_msndmix_set_mux(msnd, ucontrol->value.enumerated.item[0]); +} + + +static int snd_msndmix_volume_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 2; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 100; + return 0; +} + +static int snd_msndmix_volume_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_msnd *msnd = snd_kcontrol_chip(kcontrol); + int addr = kcontrol->private_value; + unsigned long flags; + + spin_lock_irqsave(&msnd->mixer_lock, flags); + ucontrol->value.integer.value[0] = msnd->left_levels[addr] * 100; + ucontrol->value.integer.value[0] /= 0xFFFF; + ucontrol->value.integer.value[1] = msnd->right_levels[addr] * 100; + ucontrol->value.integer.value[1] /= 0xFFFF; + spin_unlock_irqrestore(&msnd->mixer_lock, flags); + return 0; +} + +#define update_volm(a, b) \ + do { \ + writew((dev->left_levels[a] >> 1) * \ + readw(dev->SMA + SMA_wCurrMastVolLeft) / 0xffff, \ + dev->SMA + SMA_##b##Left); \ + writew((dev->right_levels[a] >> 1) * \ + readw(dev->SMA + SMA_wCurrMastVolRight) / 0xffff, \ + dev->SMA + SMA_##b##Right); \ + } while (0); + +#define update_potm(d, s, ar) \ + do { \ + writeb((dev->left_levels[d] >> 8) * \ + readw(dev->SMA + SMA_wCurrMastVolLeft) / 0xffff, \ + dev->SMA + SMA_##s##Left); \ + writeb((dev->right_levels[d] >> 8) * \ + readw(dev->SMA + SMA_wCurrMastVolRight) / 0xffff, \ + dev->SMA + SMA_##s##Right); \ + if (snd_msnd_send_word(dev, 0, 0, ar) == 0) \ + snd_msnd_send_dsp_cmd(dev, HDEX_AUX_REQ); \ + } while (0); + +#define update_pot(d, s, ar) \ + do { \ + writeb(dev->left_levels[d] >> 8, \ + dev->SMA + SMA_##s##Left); \ + writeb(dev->right_levels[d] >> 8, \ + dev->SMA + SMA_##s##Right); \ + if (snd_msnd_send_word(dev, 0, 0, ar) == 0) \ + snd_msnd_send_dsp_cmd(dev, HDEX_AUX_REQ); \ + } while (0); + + +static int snd_msndmix_set(struct snd_msnd *dev, int d, int left, int right) +{ + int bLeft, bRight; + int wLeft, wRight; + int updatemaster = 0; + + if (d >= LEVEL_ENTRIES) + return -EINVAL; + + bLeft = left * 0xff / 100; + wLeft = left * 0xffff / 100; + + bRight = right * 0xff / 100; + wRight = right * 0xffff / 100; + + dev->left_levels[d] = wLeft; + dev->right_levels[d] = wRight; + + switch (d) { + /* master volume unscaled controls */ + case MSND_MIXER_LINE: /* line pot control */ + /* scaled by IMIX in digital mix */ + writeb(bLeft, dev->SMA + SMA_bInPotPosLeft); + writeb(bRight, dev->SMA + SMA_bInPotPosRight); + if (snd_msnd_send_word(dev, 0, 0, HDEXAR_IN_SET_POTS) == 0) + snd_msnd_send_dsp_cmd(dev, HDEX_AUX_REQ); + break; + case MSND_MIXER_MIC: /* mic pot control */ + if (dev->type == msndClassic) + return -EINVAL; + /* scaled by IMIX in digital mix */ + writeb(bLeft, dev->SMA + SMA_bMicPotPosLeft); + writeb(bRight, dev->SMA + SMA_bMicPotPosRight); + if (snd_msnd_send_word(dev, 0, 0, HDEXAR_MIC_SET_POTS) == 0) + snd_msnd_send_dsp_cmd(dev, HDEX_AUX_REQ); + break; + case MSND_MIXER_VOLUME: /* master volume */ + writew(wLeft, dev->SMA + SMA_wCurrMastVolLeft); + writew(wRight, dev->SMA + SMA_wCurrMastVolRight); + /* fall through */ + + case MSND_MIXER_AUX: /* aux pot control */ + /* scaled by master volume */ + /* fall through */ + + /* digital controls */ + case MSND_MIXER_SYNTH: /* synth vol (dsp mix) */ + case MSND_MIXER_PCM: /* pcm vol (dsp mix) */ + case MSND_MIXER_IMIX: /* input monitor (dsp mix) */ + /* scaled by master volume */ + updatemaster = 1; + break; + + default: + return -EINVAL; + } + + if (updatemaster) { + /* update master volume scaled controls */ + update_volm(MSND_MIXER_PCM, wCurrPlayVol); + update_volm(MSND_MIXER_IMIX, wCurrInVol); + if (dev->type == msndPinnacle) + update_volm(MSND_MIXER_SYNTH, wCurrMHdrVol); + update_potm(MSND_MIXER_AUX, bAuxPotPos, HDEXAR_AUX_SET_POTS); + } + + return 0; +} + +static int snd_msndmix_volume_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_msnd *msnd = snd_kcontrol_chip(kcontrol); + int change, addr = kcontrol->private_value; + int left, right; + unsigned long flags; + + left = ucontrol->value.integer.value[0] % 101; + right = ucontrol->value.integer.value[1] % 101; + spin_lock_irqsave(&msnd->mixer_lock, flags); + change = msnd->left_levels[addr] != left + || msnd->right_levels[addr] != right; + snd_msndmix_set(msnd, addr, left, right); + spin_unlock_irqrestore(&msnd->mixer_lock, flags); + return change; +} + + +#define DUMMY_VOLUME(xname, xindex, addr) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ + .info = snd_msndmix_volume_info, \ + .get = snd_msndmix_volume_get, .put = snd_msndmix_volume_put, \ + .private_value = addr } + + +static struct snd_kcontrol_new snd_msnd_controls[] = { +DUMMY_VOLUME("Master Volume", 0, MSND_MIXER_VOLUME), +DUMMY_VOLUME("PCM Volume", 0, MSND_MIXER_PCM), +DUMMY_VOLUME("Aux Volume", 0, MSND_MIXER_AUX), +DUMMY_VOLUME("Line Volume", 0, MSND_MIXER_LINE), +DUMMY_VOLUME("Mic Volume", 0, MSND_MIXER_MIC), +DUMMY_VOLUME("Monitor", 0, MSND_MIXER_IMIX), +{ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Capture Source", + .info = snd_msndmix_info_mux, + .get = snd_msndmix_get_mux, + .put = snd_msndmix_put_mux, +} +}; + + +int __devinit snd_msndmix_new(struct snd_card *card) +{ + struct snd_msnd *chip = card->private_data; + unsigned int idx; + int err; + + if (snd_BUG_ON(!chip)) + return -EINVAL; + spin_lock_init(&chip->mixer_lock); + strcpy(card->mixername, "MSND Pinnacle Mixer"); + + for (idx = 0; idx < ARRAY_SIZE(snd_msnd_controls); idx++) + err = snd_ctl_add(card, + snd_ctl_new1(snd_msnd_controls + idx, chip)); + if (err < 0) + return err; + + return 0; +} +EXPORT_SYMBOL(snd_msndmix_new); + +void snd_msndmix_setup(struct snd_msnd *dev) +{ + update_pot(MSND_MIXER_LINE, bInPotPos, HDEXAR_IN_SET_POTS); + update_potm(MSND_MIXER_AUX, bAuxPotPos, HDEXAR_AUX_SET_POTS); + update_volm(MSND_MIXER_PCM, wCurrPlayVol); + update_volm(MSND_MIXER_IMIX, wCurrInVol); + if (dev->type == msndPinnacle) { + update_pot(MSND_MIXER_MIC, bMicPotPos, HDEXAR_MIC_SET_POTS); + update_volm(MSND_MIXER_SYNTH, wCurrMHdrVol); + } +} +EXPORT_SYMBOL(snd_msndmix_setup); + +int snd_msndmix_force_recsrc(struct snd_msnd *dev, int recsrc) +{ + dev->recsrc = -1; + return snd_msndmix_set_mux(dev, recsrc); +} +EXPORT_SYMBOL(snd_msndmix_force_recsrc); -- GitLab From c96330b083ce88b9fea428df99b4631f1b6410ef Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 28 Jan 2009 08:23:03 +0100 Subject: [PATCH 0508/4982] ALSA: Add description of new snd-msnd-* drivers Signed-off-by: Takashi Iwai --- .../sound/alsa/ALSA-Configuration.txt | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 841a9365d5f..ba7b14a13ab 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -1185,6 +1185,54 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. This module supports multiple devices and PnP. + Module snd-msnd-classic + ----------------------- + + Module for Turtle Beach MultiSound Classic, Tahiti or Monterey + soundcards. + + io - Port # for msnd-classic card + irq - IRQ # for msnd-classic card + mem - Memory address (0xb0000, 0xc8000, 0xd0000, 0xd8000, + 0xe0000 or 0xe8000) + write_ndelay - enable write ndelay (default = 1) + calibrate_signal - calibrate signal (default = 0) + isapnp - ISA PnP detection - 0 = disable, 1 = enable (default) + digital - Digital daughterboard present (default = 0) + cfg - Config port (0x250, 0x260 or 0x270) default = PnP + reset - Reset all devices + mpu_io - MPU401 I/O port + mpu_irq - MPU401 irq# + ide_io0 - IDE port #0 + ide_io1 - IDE port #1 + ide_irq - IDE irq# + joystick_io - Joystick I/O port + + The driver requires firmware files "turtlebeach/msndinit.bin" and + "turtlebeach/msndperm.bin" in the proper firmware directory. + + See Documentation/sound/oss/MultiSound for important information + about this driver. Note that it has been discontinued, but the + Voyetra Turtle Beach knowledge base entry for it is still available + at + http://www.turtlebeach.com/site/kb_ftp/790.asp + + Module snd-msnd-pinnacle + ------------------------ + + Module for Turtle Beach MultiSound Pinnacle/Fiji soundcards. + + io - Port # for pinnacle/fiji card + irq - IRQ # for pinnalce/fiji card + mem - Memory address (0xb0000, 0xc8000, 0xd0000, 0xd8000, + 0xe0000 or 0xe8000) + write_ndelay - enable write ndelay (default = 1) + calibrate_signal - calibrate signal (default = 0) + isapnp - ISA PnP detection - 0 = disable, 1 = enable (default) + + The driver requires firmware files "turtlebeach/pndspini.bin" and + "turtlebeach/pndsperm.bin" in the proper firmware directory. + Module snd-mtpav ---------------- -- GitLab From a5f7c47391ca15c3e2f8e2aa46fb089408541bcd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 28 Jan 2009 09:02:52 +0100 Subject: [PATCH 0509/4982] ALSA: enable build of snd-msnd-* drivers Added the missing msnd directory to Makefile. Signed-off-by: Takashi Iwai --- sound/isa/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/isa/Makefile b/sound/isa/Makefile index 63af13d901a..b906b9a1a81 100644 --- a/sound/isa/Makefile +++ b/sound/isa/Makefile @@ -26,5 +26,5 @@ obj-$(CONFIG_SND_SC6000) += snd-sc6000.o obj-$(CONFIG_SND_SGALAXY) += snd-sgalaxy.o obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o -obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ gus/ opti9xx/ \ +obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ gus/ msnd/ opti9xx/ \ sb/ wavefront/ wss/ -- GitLab From e3e9c5e7096f6379ca8fa78413b2055fa29f4530 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Wed, 28 Jan 2009 12:40:42 -0200 Subject: [PATCH 0510/4982] ALSA: Don't cold reset AC97 codecs in some ICH chipsets Check in a quirk list if it should do cold reset when AC97 power saving is enabled. Some devices do not resume properly when cold reset, although power saving works OK. Signed-off-by: Thadeu Lima de Souza Cascardo Signed-off-by: Takashi Iwai --- sound/pci/intel8x0.c | 68 +++++++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 16 deletions(-) diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 19d3391e229..b37bd268301 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -2287,23 +2287,23 @@ static void do_ali_reset(struct intel8x0 *chip) iputdword(chip, ICHREG(ALI_INTERRUPTSR), 0x00000000); } -static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) -{ - unsigned long end_time; - unsigned int cnt, status, nstatus; - - /* put logic to right state */ - /* first clear status bits */ - status = ICH_RCS | ICH_MCINT | ICH_POINT | ICH_PIINT; - if (chip->device_type == DEVICE_NFORCE) - status |= ICH_NVSPINT; - cnt = igetdword(chip, ICHREG(GLOB_STA)); - iputdword(chip, ICHREG(GLOB_STA), cnt & status); +#ifdef CONFIG_SND_AC97_POWER_SAVE +static struct snd_pci_quirk ich_chip_reset_mode[] = { + SND_PCI_QUIRK(0x1014, 0x051f, "Thinkpad R32", 1), + { } /* end */ +}; +static int snd_intel8x0_ich_chip_cold_reset(struct intel8x0 *chip) +{ + unsigned int cnt; /* ACLink on, 2 channels */ + + if (snd_pci_quirk_lookup(chip->pci, ich_chip_reset_mode)) + return -EIO; + cnt = igetdword(chip, ICHREG(GLOB_CNT)); cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK); -#ifdef CONFIG_SND_AC97_POWER_SAVE + /* do cold reset - the full ac97 powerdown may leave the controller * in a warm state but actually it cannot communicate with the codec. */ @@ -2312,22 +2312,58 @@ static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) udelay(10); iputdword(chip, ICHREG(GLOB_CNT), cnt | ICH_AC97COLD); msleep(1); + return 0; +} +#define snd_intel8x0_ich_chip_can_cold_reset(chip) \ + (!snd_pci_quirk_lookup(chip->pci, ich_chip_reset_mode)) #else +#define snd_intel8x0_ich_chip_cold_reset(x) do { } while (0) +#define snd_intel8x0_ich_chip_can_cold_reset(chip) (0) +#endif + +static int snd_intel8x0_ich_chip_reset(struct intel8x0 *chip) +{ + unsigned long end_time; + unsigned int cnt; + /* ACLink on, 2 channels */ + cnt = igetdword(chip, ICHREG(GLOB_CNT)); + cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK); /* finish cold or do warm reset */ cnt |= (cnt & ICH_AC97COLD) == 0 ? ICH_AC97COLD : ICH_AC97WARM; iputdword(chip, ICHREG(GLOB_CNT), cnt); end_time = (jiffies + (HZ / 4)) + 1; do { if ((igetdword(chip, ICHREG(GLOB_CNT)) & ICH_AC97WARM) == 0) - goto __ok; + return 0; schedule_timeout_uninterruptible(1); } while (time_after_eq(end_time, jiffies)); snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n", igetdword(chip, ICHREG(GLOB_CNT))); return -EIO; +} + +static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) +{ + unsigned long end_time; + unsigned int status, nstatus; + unsigned int cnt; + int err; + + /* put logic to right state */ + /* first clear status bits */ + status = ICH_RCS | ICH_MCINT | ICH_POINT | ICH_PIINT; + if (chip->device_type == DEVICE_NFORCE) + status |= ICH_NVSPINT; + cnt = igetdword(chip, ICHREG(GLOB_STA)); + iputdword(chip, ICHREG(GLOB_STA), cnt & status); + + if (snd_intel8x0_ich_chip_can_cold_reset(chip)) + err = snd_intel8x0_ich_chip_cold_reset(chip); + else + err = snd_intel8x0_ich_chip_reset(chip); + if (err < 0) + return err; - __ok: -#endif if (probing) { /* wait for any codec ready status. * Once it becomes ready it should remain ready -- GitLab From e167280070cccd2e0cde94f73ded0a4b08bf6412 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 28 Jan 2009 16:05:16 +0100 Subject: [PATCH 0511/4982] ALSA: intel8x0 - Fix build with CONFIG_SND_AC97_POWERSAVE=n Signed-off-by: Takashi Iwai --- sound/pci/intel8x0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index b37bd268301..b13ef1e2a4a 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -2317,7 +2317,7 @@ static int snd_intel8x0_ich_chip_cold_reset(struct intel8x0 *chip) #define snd_intel8x0_ich_chip_can_cold_reset(chip) \ (!snd_pci_quirk_lookup(chip->pci, ich_chip_reset_mode)) #else -#define snd_intel8x0_ich_chip_cold_reset(x) do { } while (0) +#define snd_intel8x0_ich_chip_cold_reset(chip) 0 #define snd_intel8x0_ich_chip_can_cold_reset(chip) (0) #endif -- GitLab From 61b9b9b109217b2bfb128c3ca24d8f8c839a425f Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Wed, 28 Jan 2009 09:16:33 -0200 Subject: [PATCH 0512/4982] ALSA: hda - Consider additional capture source/selector in ALC889 Currently code for capture source support in ALC889 only considers capture mixers. This change adds additional support for ADC+selector present in ALC889, taking into account also the presence of an additional DMIC connection item in the selector. Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 105 +++++++++++++++++++++++++--------- 1 file changed, 77 insertions(+), 28 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 863ab957204..d81cb5eb8c5 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -238,6 +238,13 @@ enum { ALC883_MODEL_LAST, }; +/* styles of capture selection */ +enum { + CAPT_MUX = 0, /* only mux based */ + CAPT_MIX, /* only mixer based */ + CAPT_1MUX_MIX, /* first mux and other mixers */ +}; + /* for GPIO Poll */ #define GPIO_MASK 0x03 @@ -276,7 +283,7 @@ struct alc_spec { hda_nid_t *adc_nids; hda_nid_t *capsrc_nids; hda_nid_t dig_in_nid; /* digital-in NID; optional */ - unsigned char is_mix_capture; /* matrix-style capture (non-mux) */ + int capture_style; /* capture style (CAPT_*) */ /* capture source */ unsigned int num_mux_defs; @@ -294,7 +301,7 @@ struct alc_spec { /* dynamic controls, init_verbs and input_mux */ struct auto_pin_cfg autocfg; struct snd_array kctls; - struct hda_input_mux private_imux; + struct hda_input_mux private_imux[3]; hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; /* hooks */ @@ -396,7 +403,8 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; imux = &spec->input_mux[mux_idx]; - if (spec->is_mix_capture) { + if (spec->capture_style && + !(spec->capture_style == CAPT_1MUX_MIX && !adc_idx)) { /* Matrix-mixer style (e.g. ALC882) */ unsigned int *cur_val = &spec->cur_mux[adc_idx]; unsigned int i, idx; @@ -4130,7 +4138,7 @@ static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) { - struct hda_input_mux *imux = &spec->private_imux; + struct hda_input_mux *imux = &spec->private_imux[0]; int i, err, idx; for (i = 0; i < AUTO_PIN_LAST; i++) { @@ -4279,7 +4287,7 @@ static int alc880_parse_auto_config(struct hda_codec *codec) add_verb(spec, alc880_volume_init_verbs); spec->num_mux_defs = 1; - spec->input_mux = &spec->private_imux; + spec->input_mux = &spec->private_imux[0]; store_pin_configs(codec); return 1; @@ -5487,7 +5495,7 @@ static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec, static int alc260_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) { - struct hda_input_mux *imux = &spec->private_imux; + struct hda_input_mux *imux = &spec->private_imux[0]; int i, err, idx; for (i = 0; i < AUTO_PIN_LAST; i++) { @@ -5647,7 +5655,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec) add_verb(spec, alc260_volume_init_verbs); spec->num_mux_defs = 1; - spec->input_mux = &spec->private_imux; + spec->input_mux = &spec->private_imux[0]; store_pin_configs(codec); return 1; @@ -7087,7 +7095,7 @@ static int patch_alc882(struct hda_codec *codec) spec->stream_digital_playback = &alc882_pcm_digital_playback; spec->stream_digital_capture = &alc882_pcm_digital_capture; - spec->is_mix_capture = 1; /* matrix-style capture */ + spec->capture_style = CAPT_MIX; /* matrix-style capture */ if (!spec->adc_nids && spec->input_mux) { /* check whether NID 0x07 is valid */ unsigned int wcap = get_wcaps(codec, 0x07); @@ -7155,10 +7163,14 @@ static hda_nid_t alc883_adc_nids_rev[2] = { 0x09, 0x08 }; +#define alc889_adc_nids alc880_adc_nids + static hda_nid_t alc883_capsrc_nids[2] = { 0x23, 0x22 }; static hda_nid_t alc883_capsrc_nids_rev[2] = { 0x22, 0x23 }; +#define alc889_capsrc_nids alc882_capsrc_nids + /* input MUX */ /* FIXME: should be a matrix-type input source selection */ @@ -8977,6 +8989,8 @@ static int alc883_parse_auto_config(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; int err = alc880_parse_auto_config(codec); + struct auto_pin_cfg *cfg = &spec->autocfg; + int i; if (err < 0) return err; @@ -8990,6 +9004,26 @@ static int alc883_parse_auto_config(struct hda_codec *codec) /* hack - override the init verbs */ spec->init_verbs[0] = alc883_auto_init_verbs; + /* setup input_mux for ALC889 */ + if (codec->vendor_id == 0x10ec0889) { + /* digital-mic input pin is excluded in alc880_auto_create..() + * because it's under 0x18 + */ + if (cfg->input_pins[AUTO_PIN_MIC] == 0x12 || + cfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) { + struct hda_input_mux *imux = &spec->private_imux[0]; + for (i = 1; i < 3; i++) + memcpy(&spec->private_imux[i], + &spec->private_imux[0], + sizeof(spec->private_imux[0])); + imux->items[imux->num_items].label = "Int DMic"; + imux->items[imux->num_items].index = 0x0b; + imux->num_items++; + spec->num_mux_defs = 3; + spec->input_mux = spec->private_imux; + } + } + return 1; /* config found */ } @@ -9053,14 +9087,36 @@ static int patch_alc883(struct hda_codec *codec) spec->stream_name_analog = "ALC888 Analog"; spec->stream_name_digital = "ALC888 Digital"; } + if (!spec->num_adc_nids) { + spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); + spec->adc_nids = alc883_adc_nids; + } + if (!spec->capsrc_nids) + spec->capsrc_nids = alc883_capsrc_nids; + spec->capture_style = CAPT_MIX; /* matrix-style capture */ break; case 0x10ec0889: spec->stream_name_analog = "ALC889 Analog"; spec->stream_name_digital = "ALC889 Digital"; + if (!spec->num_adc_nids) { + spec->num_adc_nids = ARRAY_SIZE(alc889_adc_nids); + spec->adc_nids = alc889_adc_nids; + } + if (!spec->capsrc_nids) + spec->capsrc_nids = alc889_capsrc_nids; + spec->capture_style = CAPT_1MUX_MIX; /* 1mux/Nmix-style + capture */ break; default: spec->stream_name_analog = "ALC883 Analog"; spec->stream_name_digital = "ALC883 Digital"; + if (!spec->num_adc_nids) { + spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); + spec->adc_nids = alc883_adc_nids; + } + if (!spec->capsrc_nids) + spec->capsrc_nids = alc883_capsrc_nids; + spec->capture_style = CAPT_MIX; /* matrix-style capture */ break; } @@ -9071,13 +9127,6 @@ static int patch_alc883(struct hda_codec *codec) spec->stream_digital_playback = &alc883_pcm_digital_playback; spec->stream_digital_capture = &alc883_pcm_digital_capture; - if (!spec->num_adc_nids) { - spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); - spec->adc_nids = alc883_adc_nids; - } - if (!spec->capsrc_nids) - spec->capsrc_nids = alc883_capsrc_nids; - spec->is_mix_capture = 1; /* matrix-style capture */ if (!spec->cap_mixer) set_capture_mixer(spec); @@ -10512,7 +10561,7 @@ static int alc262_parse_auto_config(struct hda_codec *codec) add_verb(spec, alc262_volume_init_verbs); spec->num_mux_defs = 1; - spec->input_mux = &spec->private_imux; + spec->input_mux = &spec->private_imux[0]; err = alc_auto_add_mic_boost(codec); if (err < 0) @@ -10881,7 +10930,7 @@ static int patch_alc262(struct hda_codec *codec) spec->stream_digital_playback = &alc262_pcm_digital_playback; spec->stream_digital_capture = &alc262_pcm_digital_capture; - spec->is_mix_capture = 1; + spec->capture_style = CAPT_MIX; if (!spec->adc_nids && spec->input_mux) { /* check whether NID 0x07 is valid */ unsigned int wcap = get_wcaps(codec, 0x07); @@ -11539,7 +11588,7 @@ static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec, static int alc268_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) { - struct hda_input_mux *imux = &spec->private_imux; + struct hda_input_mux *imux = &spec->private_imux[0]; int i, idx1; for (i = 0; i < AUTO_PIN_LAST; i++) { @@ -11657,7 +11706,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec) add_verb(spec, alc268_volume_init_verbs); spec->num_mux_defs = 1; - spec->input_mux = &spec->private_imux; + spec->input_mux = &spec->private_imux[0]; err = alc_auto_add_mic_boost(codec); if (err < 0) @@ -12511,7 +12560,7 @@ static int alc269_auto_create_analog_input_ctls(struct alc_spec *spec, */ if (cfg->input_pins[AUTO_PIN_MIC] == 0x12 || cfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) { - struct hda_input_mux *imux = &spec->private_imux; + struct hda_input_mux *imux = &spec->private_imux[0]; imux->items[imux->num_items].label = "Int Mic"; imux->items[imux->num_items].index = 0x05; imux->num_items++; @@ -12567,7 +12616,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) add_verb(spec, alc269_init_verbs); spec->num_mux_defs = 1; - spec->input_mux = &spec->private_imux; + spec->input_mux = &spec->private_imux[0]; /* set default input source */ snd_hda_codec_write_cache(codec, alc269_capsrc_nids[0], 0, AC_VERB_SET_CONNECT_SEL, @@ -13483,7 +13532,7 @@ static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin) static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) { - struct hda_input_mux *imux = &spec->private_imux; + struct hda_input_mux *imux = &spec->private_imux[0]; int i, err, idx, idx1; for (i = 0; i < AUTO_PIN_LAST; i++) { @@ -13620,7 +13669,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec) add_verb(spec, alc861_auto_init_verbs); spec->num_mux_defs = 1; - spec->input_mux = &spec->private_imux; + spec->input_mux = &spec->private_imux[0]; spec->adc_nids = alc861_adc_nids; spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids); @@ -14724,7 +14773,7 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) add_verb(spec, alc861vd_volume_init_verbs); spec->num_mux_defs = 1; - spec->input_mux = &spec->private_imux; + spec->input_mux = &spec->private_imux[0]; err = alc_auto_add_mic_boost(codec); if (err < 0) @@ -14803,7 +14852,7 @@ static int patch_alc861vd(struct hda_codec *codec) spec->adc_nids = alc861vd_adc_nids; spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids); spec->capsrc_nids = alc861vd_capsrc_nids; - spec->is_mix_capture = 1; + spec->capture_style = CAPT_MIX; set_capture_mixer(spec); @@ -16397,7 +16446,7 @@ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, static int alc662_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) { - struct hda_input_mux *imux = &spec->private_imux; + struct hda_input_mux *imux = &spec->private_imux[0]; int i, err, idx; for (i = 0; i < AUTO_PIN_LAST; i++) { @@ -16528,7 +16577,7 @@ static int alc662_parse_auto_config(struct hda_codec *codec) add_mixer(spec, spec->kctls.list); spec->num_mux_defs = 1; - spec->input_mux = &spec->private_imux; + spec->input_mux = &spec->private_imux[0]; add_verb(spec, alc662_auto_init_verbs); if (codec->vendor_id == 0x10ec0663) @@ -16613,7 +16662,7 @@ static int patch_alc662(struct hda_codec *codec) spec->adc_nids = alc662_adc_nids; spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids); spec->capsrc_nids = alc662_capsrc_nids; - spec->is_mix_capture = 1; + spec->capture_style = CAPT_MIX; if (!spec->cap_mixer) set_capture_mixer(spec); -- GitLab From 305a47b17c6efcc0e7b67b0bd41e2c12b7af758b Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Fri, 16 Jan 2009 16:21:12 +0000 Subject: [PATCH 0513/4982] dlm: Change rwlock which is only used in write mode to a spinlock The ls_dirtbl[].lock was an rwlock, but since it was only used in write mode a spinlock will suffice. Signed-off-by: Steven Whitehouse Signed-off-by: David Teigland --- fs/dlm/dir.c | 18 +++++++++--------- fs/dlm/dlm_internal.h | 2 +- fs/dlm/lockspace.c | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/fs/dlm/dir.c b/fs/dlm/dir.c index 92969f879a1..858fba14aaa 100644 --- a/fs/dlm/dir.c +++ b/fs/dlm/dir.c @@ -156,7 +156,7 @@ void dlm_dir_remove_entry(struct dlm_ls *ls, int nodeid, char *name, int namelen bucket = dir_hash(ls, name, namelen); - write_lock(&ls->ls_dirtbl[bucket].lock); + spin_lock(&ls->ls_dirtbl[bucket].lock); de = search_bucket(ls, name, namelen, bucket); @@ -173,7 +173,7 @@ void dlm_dir_remove_entry(struct dlm_ls *ls, int nodeid, char *name, int namelen list_del(&de->list); kfree(de); out: - write_unlock(&ls->ls_dirtbl[bucket].lock); + spin_unlock(&ls->ls_dirtbl[bucket].lock); } void dlm_dir_clear(struct dlm_ls *ls) @@ -185,14 +185,14 @@ void dlm_dir_clear(struct dlm_ls *ls) DLM_ASSERT(list_empty(&ls->ls_recover_list), ); for (i = 0; i < ls->ls_dirtbl_size; i++) { - write_lock(&ls->ls_dirtbl[i].lock); + spin_lock(&ls->ls_dirtbl[i].lock); head = &ls->ls_dirtbl[i].list; while (!list_empty(head)) { de = list_entry(head->next, struct dlm_direntry, list); list_del(&de->list); put_free_de(ls, de); } - write_unlock(&ls->ls_dirtbl[i].lock); + spin_unlock(&ls->ls_dirtbl[i].lock); } } @@ -307,17 +307,17 @@ static int get_entry(struct dlm_ls *ls, int nodeid, char *name, bucket = dir_hash(ls, name, namelen); - write_lock(&ls->ls_dirtbl[bucket].lock); + spin_lock(&ls->ls_dirtbl[bucket].lock); de = search_bucket(ls, name, namelen, bucket); if (de) { *r_nodeid = de->master_nodeid; - write_unlock(&ls->ls_dirtbl[bucket].lock); + spin_unlock(&ls->ls_dirtbl[bucket].lock); if (*r_nodeid == nodeid) return -EEXIST; return 0; } - write_unlock(&ls->ls_dirtbl[bucket].lock); + spin_unlock(&ls->ls_dirtbl[bucket].lock); if (namelen > DLM_RESNAME_MAXLEN) return -EINVAL; @@ -330,7 +330,7 @@ static int get_entry(struct dlm_ls *ls, int nodeid, char *name, de->length = namelen; memcpy(de->name, name, namelen); - write_lock(&ls->ls_dirtbl[bucket].lock); + spin_lock(&ls->ls_dirtbl[bucket].lock); tmp = search_bucket(ls, name, namelen, bucket); if (tmp) { kfree(de); @@ -339,7 +339,7 @@ static int get_entry(struct dlm_ls *ls, int nodeid, char *name, list_add_tail(&de->list, &ls->ls_dirtbl[bucket].list); } *r_nodeid = de->master_nodeid; - write_unlock(&ls->ls_dirtbl[bucket].lock); + spin_unlock(&ls->ls_dirtbl[bucket].lock); return 0; } diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index 076e86f38bc..d01ca0a711d 100644 --- a/fs/dlm/dlm_internal.h +++ b/fs/dlm/dlm_internal.h @@ -99,7 +99,7 @@ struct dlm_direntry { struct dlm_dirtable { struct list_head list; - rwlock_t lock; + spinlock_t lock; }; struct dlm_rsbtable { diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index aa32e5f0249..cd8e2df3c29 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c @@ -487,7 +487,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace, goto out_lkbfree; for (i = 0; i < size; i++) { INIT_LIST_HEAD(&ls->ls_dirtbl[i].list); - rwlock_init(&ls->ls_dirtbl[i].lock); + spin_lock_init(&ls->ls_dirtbl[i].lock); } INIT_LIST_HEAD(&ls->ls_waiters); -- GitLab From 44ad532b3277f0cae55bfe0625d3140cf73af450 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 22 Jan 2009 13:24:49 -0800 Subject: [PATCH 0514/4982] dlm: use ipv6_addr_copy Signed-off-by: Joe Perches Signed-off-by: David Teigland --- fs/dlm/lowcomms.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 103a5ebd137..bf09262b8b0 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c @@ -53,6 +53,7 @@ #include #include #include +#include #include "dlm_internal.h" #include "lowcomms.h" @@ -250,8 +251,7 @@ static int nodeid_to_addr(int nodeid, struct sockaddr *retaddr) } else { struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &addr; struct sockaddr_in6 *ret6 = (struct sockaddr_in6 *) retaddr; - memcpy(&ret6->sin6_addr, &in6->sin6_addr, - sizeof(in6->sin6_addr)); + ipv6_addr_copy(&ret6->sin6_addr, &in6->sin6_addr); } return 0; -- GitLab From 2cf12c0bf261e19d9641d7b8aa220e2651a03289 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 22 Jan 2009 13:26:47 -0800 Subject: [PATCH 0515/4982] dlm: comment typo fixes Signed-off-by: Joe Perches Signed-off-by: David Teigland --- fs/dlm/lowcomms.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index bf09262b8b0..982314c472c 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c @@ -21,7 +21,7 @@ * * Cluster nodes are referred to by their nodeids. nodeids are * simply 32 bit numbers to the locking module - if they need to - * be expanded for the cluster infrastructure then that is it's + * be expanded for the cluster infrastructure then that is its * responsibility. It is this layer's * responsibility to resolve these into IP address or * whatever it needs for inter-node communication. @@ -36,9 +36,9 @@ * of high load. Also, this way, the sending thread can collect together * messages bound for one node and send them in one block. * - * lowcomms will choose to use wither TCP or SCTP as its transport layer + * lowcomms will choose to use either TCP or SCTP as its transport layer * depending on the configuration variable 'protocol'. This should be set - * to 0 (default) for TCP or 1 for SCTP. It shouldbe configured using a + * to 0 (default) for TCP or 1 for SCTP. It should be configured using a * cluster-wide mechanism as it must be the same on all nodes of the cluster * for the DLM to function. * -- GitLab From 6e7a59944a2971c4fb400bfbecb2f68570086b05 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 23:07:42 +0100 Subject: [PATCH 0516/4982] x86, genapic: refactor genapic_64.h Impact: pre unification cleanup Make genapic_64.h similar to genapic_32.h: reorder fields, unify types and bring in new entries. No existing functionality is affected. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/genapic_64.h | 68 +++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 9 deletions(-) diff --git a/arch/x86/include/asm/genapic_64.h b/arch/x86/include/asm/genapic_64.h index 7bb092c5905..0a5f7122d9f 100644 --- a/arch/x86/include/asm/genapic_64.h +++ b/arch/x86/include/asm/genapic_64.h @@ -16,13 +16,62 @@ struct genapic { char *name; + + int (*probe)(void); int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id); + int (*apic_id_registered)(void); + u32 int_delivery_mode; u32 int_dest_mode; - int (*apic_id_registered)(void); + const struct cpumask *(*target_cpus)(void); + + int ESR_DISABLE; + + int apic_destination_logical; + unsigned long (*check_apicid_used)(physid_mask_t bitmap, int apicid); + unsigned long (*check_apicid_present)(int apicid); + + int no_balance_irq; + int no_ioapic_check; + void (*vector_allocation_domain)(int cpu, struct cpumask *retmask); void (*init_apic_ldr)(void); + + physid_mask_t (*ioapic_phys_id_map)(physid_mask_t map); + + void (*setup_apic_routing)(void); + int (*multi_timer_check)(int apic, int irq); + int (*apicid_to_node)(int logical_apicid); + int (*cpu_to_logical_apicid)(int cpu); + int (*cpu_present_to_apicid)(int mps_cpu); + physid_mask_t (*apicid_to_cpu_present)(int phys_apicid); + void (*setup_portio_remap)(void); + int (*check_phys_apicid_present)(int boot_cpu_physical_apicid); + void (*enable_apic_mode)(void); +#ifdef CONFIG_X86_32 + u32 (*phys_pkg_id)(u32 cpuid_apic, int index_msb); +#else + unsigned int (*phys_pkg_id)(int index_msb); +#endif + + /* + * When one of the next two hooks returns 1 the genapic + * is switched to this. Essentially they are additional + * probe functions: + */ + int (*mps_oem_check)(struct mpc_table *mpc, char *oem, + char *productid); + + unsigned int (*get_apic_id)(unsigned long x); + unsigned long (*set_apic_id)(unsigned int id); + unsigned long apic_id_mask; + + unsigned int (*cpu_mask_to_apicid)(const struct cpumask *cpumask); + unsigned int (*cpu_mask_to_apicid_and)(const struct cpumask *cpumask, + const struct cpumask *andmask); + +#ifdef CONFIG_SMP /* ipi */ void (*send_IPI_mask)(const struct cpumask *mask, int vector); void (*send_IPI_mask_allbutself)(const struct cpumask *mask, @@ -30,16 +79,17 @@ struct genapic { void (*send_IPI_allbutself)(int vector); void (*send_IPI_all)(int vector); void (*send_IPI_self)(int vector); - /* */ - unsigned int (*cpu_mask_to_apicid)(const struct cpumask *cpumask); - unsigned int (*cpu_mask_to_apicid_and)(const struct cpumask *cpumask, - const struct cpumask *andmask); - unsigned int (*phys_pkg_id)(int index_msb); - unsigned int (*get_apic_id)(unsigned long x); - unsigned long (*set_apic_id)(unsigned int id); - unsigned long apic_id_mask; +#endif /* wakeup_secondary_cpu */ int (*wakeup_cpu)(int apicid, unsigned long start_eip); + + int trampoline_phys_low; + int trampoline_phys_high; + void (*wait_for_init_deassert)(atomic_t *deassert); + void (*smp_callin_clear_local_apic)(void); + void (*store_NMI_vector)(unsigned short *high, unsigned short *low); + void (*restore_NMI_vector)(unsigned short *high, unsigned short *low); + void (*inquire_remote_apic)(int apicid); }; extern struct genapic *genapic; -- GitLab From 943d0f74d47724d0e33083674c16a834f080af2c Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 23:07:42 +0100 Subject: [PATCH 0517/4982] x86, genapic: refactor genapic_32.h Impact: pre unification cleanup Make genapic_32.h similar to genapic_64.h: reorder fields, unify types and bring in new entries. No existing functionality is affected. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/genapic_32.h | 37 ++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/arch/x86/include/asm/genapic_32.h b/arch/x86/include/asm/genapic_32.h index 4334502d366..5808b7daf0a 100644 --- a/arch/x86/include/asm/genapic_32.h +++ b/arch/x86/include/asm/genapic_32.h @@ -21,19 +21,28 @@ struct mpc_cpu; struct genapic { char *name; - int (*probe)(void); + int (*probe)(void); + int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id); int (*apic_id_registered)(void); + + u32 int_delivery_mode; + u32 int_dest_mode; + const struct cpumask *(*target_cpus)(void); - int int_delivery_mode; - int int_dest_mode; + int ESR_DISABLE; + int apic_destination_logical; unsigned long (*check_apicid_used)(physid_mask_t bitmap, int apicid); unsigned long (*check_apicid_present)(int apicid); + int no_balance_irq; int no_ioapic_check; + + void (*vector_allocation_domain)(int cpu, struct cpumask *retmask); void (*init_apic_ldr)(void); + physid_mask_t (*ioapic_phys_id_map)(physid_mask_t map); void (*setup_apic_routing)(void); @@ -45,22 +54,27 @@ struct genapic { void (*setup_portio_remap)(void); int (*check_phys_apicid_present)(int boot_cpu_physical_apicid); void (*enable_apic_mode)(void); +#ifdef CONFIG_X86_32 u32 (*phys_pkg_id)(u32 cpuid_apic, int index_msb); +#else + unsigned int (*phys_pkg_id)(int index_msb); +#endif - /* mpparse */ - /* When one of the next two hooks returns 1 the genapic - is switched to this. Essentially they are additional probe - functions. */ + /* + * When one of the next two hooks returns 1 the genapic + * is switched to this. Essentially they are additional + * probe functions: + */ int (*mps_oem_check)(struct mpc_table *mpc, char *oem, char *productid); - int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id); - unsigned (*get_apic_id)(unsigned long x); + unsigned int (*get_apic_id)(unsigned long x); + unsigned long (*set_apic_id)(unsigned int id); unsigned long apic_id_mask; + unsigned int (*cpu_mask_to_apicid)(const struct cpumask *cpumask); unsigned int (*cpu_mask_to_apicid_and)(const struct cpumask *cpumask, const struct cpumask *andmask); - void (*vector_allocation_domain)(int cpu, struct cpumask *retmask); #ifdef CONFIG_SMP /* ipi */ @@ -69,8 +83,11 @@ struct genapic { int vector); void (*send_IPI_allbutself)(int vector); void (*send_IPI_all)(int vector); + void (*send_IPI_self)(int vector); #endif + /* wakeup_secondary_cpu */ int (*wakeup_cpu)(int apicid, unsigned long start_eip); + int trampoline_phys_low; int trampoline_phys_high; void (*wait_for_init_deassert)(atomic_t *deassert); -- GitLab From ef7471b13f3ef81074af1972b97355df9df3cdf3 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 23:12:02 +0100 Subject: [PATCH 0518/4982] x86, genapic: unify struct genapic Move over the (now identical) struct genapic definitions from genapic_32/64.h to genapic.h. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/genapic.h | 96 +++++++++++++++++++++++++++++++ arch/x86/include/asm/genapic_32.h | 93 ------------------------------ arch/x86/include/asm/genapic_64.h | 91 ----------------------------- 3 files changed, 96 insertions(+), 184 deletions(-) diff --git a/arch/x86/include/asm/genapic.h b/arch/x86/include/asm/genapic.h index d48bee663a6..3dea66a328e 100644 --- a/arch/x86/include/asm/genapic.h +++ b/arch/x86/include/asm/genapic.h @@ -1,5 +1,101 @@ +#ifndef _ASM_X86_GENAPIC_H +#define _ASM_X86_GENAPIC_H + +#include + +/* + * Copyright 2004 James Cleverdon, IBM. + * Subject to the GNU Public License, v.2 + * + * Generic APIC sub-arch data struct. + * + * Hacked for x86-64 by James Cleverdon from i386 architecture code by + * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and + * James Cleverdon. + */ + +struct genapic { + char *name; + + int (*probe)(void); + int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id); + int (*apic_id_registered)(void); + + u32 int_delivery_mode; + u32 int_dest_mode; + + const struct cpumask *(*target_cpus)(void); + + int ESR_DISABLE; + + int apic_destination_logical; + unsigned long (*check_apicid_used)(physid_mask_t bitmap, int apicid); + unsigned long (*check_apicid_present)(int apicid); + + int no_balance_irq; + int no_ioapic_check; + + void (*vector_allocation_domain)(int cpu, struct cpumask *retmask); + void (*init_apic_ldr)(void); + + physid_mask_t (*ioapic_phys_id_map)(physid_mask_t map); + + void (*setup_apic_routing)(void); + int (*multi_timer_check)(int apic, int irq); + int (*apicid_to_node)(int logical_apicid); + int (*cpu_to_logical_apicid)(int cpu); + int (*cpu_present_to_apicid)(int mps_cpu); + physid_mask_t (*apicid_to_cpu_present)(int phys_apicid); + void (*setup_portio_remap)(void); + int (*check_phys_apicid_present)(int boot_cpu_physical_apicid); + void (*enable_apic_mode)(void); +#ifdef CONFIG_X86_32 + u32 (*phys_pkg_id)(u32 cpuid_apic, int index_msb); +#else + unsigned int (*phys_pkg_id)(int index_msb); +#endif + + /* + * When one of the next two hooks returns 1 the genapic + * is switched to this. Essentially they are additional + * probe functions: + */ + int (*mps_oem_check)(struct mpc_table *mpc, char *oem, + char *productid); + + unsigned int (*get_apic_id)(unsigned long x); + unsigned long (*set_apic_id)(unsigned int id); + unsigned long apic_id_mask; + + unsigned int (*cpu_mask_to_apicid)(const struct cpumask *cpumask); + unsigned int (*cpu_mask_to_apicid_and)(const struct cpumask *cpumask, + const struct cpumask *andmask); + +#ifdef CONFIG_SMP + /* ipi */ + void (*send_IPI_mask)(const struct cpumask *mask, int vector); + void (*send_IPI_mask_allbutself)(const struct cpumask *mask, + int vector); + void (*send_IPI_allbutself)(int vector); + void (*send_IPI_all)(int vector); + void (*send_IPI_self)(int vector); +#endif + /* wakeup_secondary_cpu */ + int (*wakeup_cpu)(int apicid, unsigned long start_eip); + + int trampoline_phys_low; + int trampoline_phys_high; + void (*wait_for_init_deassert)(atomic_t *deassert); + void (*smp_callin_clear_local_apic)(void); + void (*store_NMI_vector)(unsigned short *high, unsigned short *low); + void (*restore_NMI_vector)(unsigned short *high, unsigned short *low); + void (*inquire_remote_apic)(int apicid); +}; + #ifdef CONFIG_X86_32 # include "genapic_32.h" #else # include "genapic_64.h" #endif + +#endif /* _ASM_X86_GENAPIC_64_H */ diff --git a/arch/x86/include/asm/genapic_32.h b/arch/x86/include/asm/genapic_32.h index 5808b7daf0a..a56785ed12a 100644 --- a/arch/x86/include/asm/genapic_32.h +++ b/arch/x86/include/asm/genapic_32.h @@ -4,99 +4,6 @@ #include #include -/* - * Generic APIC driver interface. - * - * An straight forward mapping of the APIC related parts of the - * x86 subarchitecture interface to a dynamic object. - * - * This is used by the "generic" x86 subarchitecture. - * - * Copyright 2003 Andi Kleen, SuSE Labs. - */ - -struct mpc_bus; -struct mpc_table; -struct mpc_cpu; - -struct genapic { - char *name; - - int (*probe)(void); - int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id); - int (*apic_id_registered)(void); - - u32 int_delivery_mode; - u32 int_dest_mode; - - const struct cpumask *(*target_cpus)(void); - - int ESR_DISABLE; - - int apic_destination_logical; - unsigned long (*check_apicid_used)(physid_mask_t bitmap, int apicid); - unsigned long (*check_apicid_present)(int apicid); - - int no_balance_irq; - int no_ioapic_check; - - void (*vector_allocation_domain)(int cpu, struct cpumask *retmask); - void (*init_apic_ldr)(void); - - physid_mask_t (*ioapic_phys_id_map)(physid_mask_t map); - - void (*setup_apic_routing)(void); - int (*multi_timer_check)(int apic, int irq); - int (*apicid_to_node)(int logical_apicid); - int (*cpu_to_logical_apicid)(int cpu); - int (*cpu_present_to_apicid)(int mps_cpu); - physid_mask_t (*apicid_to_cpu_present)(int phys_apicid); - void (*setup_portio_remap)(void); - int (*check_phys_apicid_present)(int boot_cpu_physical_apicid); - void (*enable_apic_mode)(void); -#ifdef CONFIG_X86_32 - u32 (*phys_pkg_id)(u32 cpuid_apic, int index_msb); -#else - unsigned int (*phys_pkg_id)(int index_msb); -#endif - - /* - * When one of the next two hooks returns 1 the genapic - * is switched to this. Essentially they are additional - * probe functions: - */ - int (*mps_oem_check)(struct mpc_table *mpc, char *oem, - char *productid); - - unsigned int (*get_apic_id)(unsigned long x); - unsigned long (*set_apic_id)(unsigned int id); - unsigned long apic_id_mask; - - unsigned int (*cpu_mask_to_apicid)(const struct cpumask *cpumask); - unsigned int (*cpu_mask_to_apicid_and)(const struct cpumask *cpumask, - const struct cpumask *andmask); - -#ifdef CONFIG_SMP - /* ipi */ - void (*send_IPI_mask)(const struct cpumask *mask, int vector); - void (*send_IPI_mask_allbutself)(const struct cpumask *mask, - int vector); - void (*send_IPI_allbutself)(int vector); - void (*send_IPI_all)(int vector); - void (*send_IPI_self)(int vector); -#endif - /* wakeup_secondary_cpu */ - int (*wakeup_cpu)(int apicid, unsigned long start_eip); - - int trampoline_phys_low; - int trampoline_phys_high; - void (*wait_for_init_deassert)(atomic_t *deassert); - void (*smp_callin_clear_local_apic)(void); - void (*store_NMI_vector)(unsigned short *high, unsigned short *low); - void (*restore_NMI_vector)(unsigned short *high, unsigned short *low); - void (*inquire_remote_apic)(int apicid); -}; - #define APICFUNC(x) .x = x, /* More functions could be probably marked IPIFUNC and save some space diff --git a/arch/x86/include/asm/genapic_64.h b/arch/x86/include/asm/genapic_64.h index 0a5f7122d9f..c70ca0d50eb 100644 --- a/arch/x86/include/asm/genapic_64.h +++ b/arch/x86/include/asm/genapic_64.h @@ -1,97 +1,6 @@ #ifndef _ASM_X86_GENAPIC_64_H #define _ASM_X86_GENAPIC_64_H -#include - -/* - * Copyright 2004 James Cleverdon, IBM. - * Subject to the GNU Public License, v.2 - * - * Generic APIC sub-arch data struct. - * - * Hacked for x86-64 by James Cleverdon from i386 architecture code by - * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and - * James Cleverdon. - */ - -struct genapic { - char *name; - - int (*probe)(void); - int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id); - int (*apic_id_registered)(void); - - u32 int_delivery_mode; - u32 int_dest_mode; - - const struct cpumask *(*target_cpus)(void); - - int ESR_DISABLE; - - int apic_destination_logical; - unsigned long (*check_apicid_used)(physid_mask_t bitmap, int apicid); - unsigned long (*check_apicid_present)(int apicid); - - int no_balance_irq; - int no_ioapic_check; - - void (*vector_allocation_domain)(int cpu, struct cpumask *retmask); - void (*init_apic_ldr)(void); - - physid_mask_t (*ioapic_phys_id_map)(physid_mask_t map); - - void (*setup_apic_routing)(void); - int (*multi_timer_check)(int apic, int irq); - int (*apicid_to_node)(int logical_apicid); - int (*cpu_to_logical_apicid)(int cpu); - int (*cpu_present_to_apicid)(int mps_cpu); - physid_mask_t (*apicid_to_cpu_present)(int phys_apicid); - void (*setup_portio_remap)(void); - int (*check_phys_apicid_present)(int boot_cpu_physical_apicid); - void (*enable_apic_mode)(void); -#ifdef CONFIG_X86_32 - u32 (*phys_pkg_id)(u32 cpuid_apic, int index_msb); -#else - unsigned int (*phys_pkg_id)(int index_msb); -#endif - - /* - * When one of the next two hooks returns 1 the genapic - * is switched to this. Essentially they are additional - * probe functions: - */ - int (*mps_oem_check)(struct mpc_table *mpc, char *oem, - char *productid); - - unsigned int (*get_apic_id)(unsigned long x); - unsigned long (*set_apic_id)(unsigned int id); - unsigned long apic_id_mask; - - unsigned int (*cpu_mask_to_apicid)(const struct cpumask *cpumask); - unsigned int (*cpu_mask_to_apicid_and)(const struct cpumask *cpumask, - const struct cpumask *andmask); - -#ifdef CONFIG_SMP - /* ipi */ - void (*send_IPI_mask)(const struct cpumask *mask, int vector); - void (*send_IPI_mask_allbutself)(const struct cpumask *mask, - int vector); - void (*send_IPI_allbutself)(int vector); - void (*send_IPI_all)(int vector); - void (*send_IPI_self)(int vector); -#endif - /* wakeup_secondary_cpu */ - int (*wakeup_cpu)(int apicid, unsigned long start_eip); - - int trampoline_phys_low; - int trampoline_phys_high; - void (*wait_for_init_deassert)(atomic_t *deassert); - void (*smp_callin_clear_local_apic)(void); - void (*store_NMI_vector)(unsigned short *high, unsigned short *low); - void (*restore_NMI_vector)(unsigned short *high, unsigned short *low); - void (*inquire_remote_apic)(int apicid); -}; - extern struct genapic *genapic; extern struct genapic apic_flat; -- GitLab From ced733ec0bfe9a8a5140a7aefdfe802598e4b8c0 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 23:15:06 +0100 Subject: [PATCH 0519/4982] x86, genapic: finish unification Unify remaining bits of genapic_32/64.h. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/genapic.h | 80 ++++++++++++++++++++++++++++++- arch/x86/include/asm/genapic_32.h | 65 ------------------------- arch/x86/include/asm/genapic_64.h | 19 -------- 3 files changed, 78 insertions(+), 86 deletions(-) delete mode 100644 arch/x86/include/asm/genapic_32.h delete mode 100644 arch/x86/include/asm/genapic_64.h diff --git a/arch/x86/include/asm/genapic.h b/arch/x86/include/asm/genapic.h index 3dea66a328e..7df1b48fa35 100644 --- a/arch/x86/include/asm/genapic.h +++ b/arch/x86/include/asm/genapic.h @@ -93,9 +93,85 @@ struct genapic { }; #ifdef CONFIG_X86_32 -# include "genapic_32.h" + +#include +#include + +#define APICFUNC(x) .x = x, + +/* More functions could be probably marked IPIFUNC and save some space + in UP GENERICARCH kernels, but I don't have the nerve right now + to untangle this mess. -AK */ +#ifdef CONFIG_SMP +#define IPIFUNC(x) APICFUNC(x) #else -# include "genapic_64.h" +#define IPIFUNC(x) #endif +#define APIC_INIT(aname, aprobe) \ +{ \ + .name = aname, \ + .probe = aprobe, \ + .int_delivery_mode = INT_DELIVERY_MODE, \ + .int_dest_mode = INT_DEST_MODE, \ + .no_balance_irq = NO_BALANCE_IRQ, \ + .ESR_DISABLE = esr_disable, \ + .apic_destination_logical = APIC_DEST_LOGICAL, \ + APICFUNC(apic_id_registered) \ + APICFUNC(target_cpus) \ + APICFUNC(check_apicid_used) \ + APICFUNC(check_apicid_present) \ + APICFUNC(init_apic_ldr) \ + APICFUNC(ioapic_phys_id_map) \ + APICFUNC(setup_apic_routing) \ + APICFUNC(multi_timer_check) \ + APICFUNC(apicid_to_node) \ + APICFUNC(cpu_to_logical_apicid) \ + APICFUNC(cpu_present_to_apicid) \ + APICFUNC(apicid_to_cpu_present) \ + APICFUNC(setup_portio_remap) \ + APICFUNC(check_phys_apicid_present) \ + APICFUNC(mps_oem_check) \ + APICFUNC(get_apic_id) \ + .apic_id_mask = APIC_ID_MASK, \ + APICFUNC(cpu_mask_to_apicid) \ + APICFUNC(cpu_mask_to_apicid_and) \ + APICFUNC(vector_allocation_domain) \ + APICFUNC(acpi_madt_oem_check) \ + IPIFUNC(send_IPI_mask) \ + IPIFUNC(send_IPI_allbutself) \ + IPIFUNC(send_IPI_all) \ + APICFUNC(enable_apic_mode) \ + APICFUNC(phys_pkg_id) \ + .trampoline_phys_low = TRAMPOLINE_PHYS_LOW, \ + .trampoline_phys_high = TRAMPOLINE_PHYS_HIGH, \ + APICFUNC(wait_for_init_deassert) \ + APICFUNC(smp_callin_clear_local_apic) \ + APICFUNC(store_NMI_vector) \ + APICFUNC(restore_NMI_vector) \ + APICFUNC(inquire_remote_apic) \ +} + +extern struct genapic *genapic; +extern void es7000_update_genapic_to_cluster(void); + +#else /* CONFIG_X86_64: */ + +extern struct genapic *genapic; + +extern struct genapic apic_flat; +extern struct genapic apic_physflat; +extern struct genapic apic_x2apic_cluster; +extern struct genapic apic_x2apic_phys; +extern int acpi_madt_oem_check(char *, char *); + +extern void apic_send_IPI_self(int vector); + +extern struct genapic apic_x2apic_uv_x; +DECLARE_PER_CPU(int, x2apic_extra_bits); + +extern void setup_apic_routing(void); + +#endif /* CONFIG_X86_64 */ + #endif /* _ASM_X86_GENAPIC_64_H */ diff --git a/arch/x86/include/asm/genapic_32.h b/arch/x86/include/asm/genapic_32.h deleted file mode 100644 index a56785ed12a..00000000000 --- a/arch/x86/include/asm/genapic_32.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef _ASM_X86_GENAPIC_32_H -#define _ASM_X86_GENAPIC_32_H - -#include -#include - -#define APICFUNC(x) .x = x, - -/* More functions could be probably marked IPIFUNC and save some space - in UP GENERICARCH kernels, but I don't have the nerve right now - to untangle this mess. -AK */ -#ifdef CONFIG_SMP -#define IPIFUNC(x) APICFUNC(x) -#else -#define IPIFUNC(x) -#endif - -#define APIC_INIT(aname, aprobe) \ -{ \ - .name = aname, \ - .probe = aprobe, \ - .int_delivery_mode = INT_DELIVERY_MODE, \ - .int_dest_mode = INT_DEST_MODE, \ - .no_balance_irq = NO_BALANCE_IRQ, \ - .ESR_DISABLE = esr_disable, \ - .apic_destination_logical = APIC_DEST_LOGICAL, \ - APICFUNC(apic_id_registered) \ - APICFUNC(target_cpus) \ - APICFUNC(check_apicid_used) \ - APICFUNC(check_apicid_present) \ - APICFUNC(init_apic_ldr) \ - APICFUNC(ioapic_phys_id_map) \ - APICFUNC(setup_apic_routing) \ - APICFUNC(multi_timer_check) \ - APICFUNC(apicid_to_node) \ - APICFUNC(cpu_to_logical_apicid) \ - APICFUNC(cpu_present_to_apicid) \ - APICFUNC(apicid_to_cpu_present) \ - APICFUNC(setup_portio_remap) \ - APICFUNC(check_phys_apicid_present) \ - APICFUNC(mps_oem_check) \ - APICFUNC(get_apic_id) \ - .apic_id_mask = APIC_ID_MASK, \ - APICFUNC(cpu_mask_to_apicid) \ - APICFUNC(cpu_mask_to_apicid_and) \ - APICFUNC(vector_allocation_domain) \ - APICFUNC(acpi_madt_oem_check) \ - IPIFUNC(send_IPI_mask) \ - IPIFUNC(send_IPI_allbutself) \ - IPIFUNC(send_IPI_all) \ - APICFUNC(enable_apic_mode) \ - APICFUNC(phys_pkg_id) \ - .trampoline_phys_low = TRAMPOLINE_PHYS_LOW, \ - .trampoline_phys_high = TRAMPOLINE_PHYS_HIGH, \ - APICFUNC(wait_for_init_deassert) \ - APICFUNC(smp_callin_clear_local_apic) \ - APICFUNC(store_NMI_vector) \ - APICFUNC(restore_NMI_vector) \ - APICFUNC(inquire_remote_apic) \ -} - -extern struct genapic *genapic; -extern void es7000_update_genapic_to_cluster(void); - -#endif /* _ASM_X86_GENAPIC_32_H */ diff --git a/arch/x86/include/asm/genapic_64.h b/arch/x86/include/asm/genapic_64.h deleted file mode 100644 index c70ca0d50eb..00000000000 --- a/arch/x86/include/asm/genapic_64.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _ASM_X86_GENAPIC_64_H -#define _ASM_X86_GENAPIC_64_H - -extern struct genapic *genapic; - -extern struct genapic apic_flat; -extern struct genapic apic_physflat; -extern struct genapic apic_x2apic_cluster; -extern struct genapic apic_x2apic_phys; -extern int acpi_madt_oem_check(char *, char *); - -extern void apic_send_IPI_self(int vector); - -extern struct genapic apic_x2apic_uv_x; -DECLARE_PER_CPU(int, x2apic_extra_bits); - -extern void setup_apic_routing(void); - -#endif /* _ASM_X86_GENAPIC_64_H */ -- GitLab From 505deeb1a228e5b0bf6ac5d0d78f4a4253a9efe9 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 23:23:22 +0100 Subject: [PATCH 0520/4982] x86, genapic: cleanups Unify genapic.h some more. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/genapic.h | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/arch/x86/include/asm/genapic.h b/arch/x86/include/asm/genapic.h index 7df1b48fa35..19a5193e965 100644 --- a/arch/x86/include/asm/genapic.h +++ b/arch/x86/include/asm/genapic.h @@ -3,6 +3,9 @@ #include +#include +#include + /* * Copyright 2004 James Cleverdon, IBM. * Subject to the GNU Public License, v.2 @@ -13,7 +16,6 @@ * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and * James Cleverdon. */ - struct genapic { char *name; @@ -85,6 +87,7 @@ struct genapic { int trampoline_phys_low; int trampoline_phys_high; + void (*wait_for_init_deassert)(atomic_t *deassert); void (*smp_callin_clear_local_apic)(void); void (*store_NMI_vector)(unsigned short *high, unsigned short *low); @@ -92,10 +95,9 @@ struct genapic { void (*inquire_remote_apic)(int apicid); }; -#ifdef CONFIG_X86_32 +extern struct genapic *genapic; -#include -#include +#ifdef CONFIG_X86_32 #define APICFUNC(x) .x = x, @@ -143,8 +145,8 @@ struct genapic { IPIFUNC(send_IPI_all) \ APICFUNC(enable_apic_mode) \ APICFUNC(phys_pkg_id) \ - .trampoline_phys_low = TRAMPOLINE_PHYS_LOW, \ - .trampoline_phys_high = TRAMPOLINE_PHYS_HIGH, \ + .trampoline_phys_low = TRAMPOLINE_PHYS_LOW, \ + .trampoline_phys_high = TRAMPOLINE_PHYS_HIGH, \ APICFUNC(wait_for_init_deassert) \ APICFUNC(smp_callin_clear_local_apic) \ APICFUNC(store_NMI_vector) \ @@ -152,13 +154,10 @@ struct genapic { APICFUNC(inquire_remote_apic) \ } -extern struct genapic *genapic; extern void es7000_update_genapic_to_cluster(void); #else /* CONFIG_X86_64: */ -extern struct genapic *genapic; - extern struct genapic apic_flat; extern struct genapic apic_physflat; extern struct genapic apic_x2apic_cluster; -- GitLab From 6781d948cc05b02df915650f2eb49550a1631df9 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 23:54:23 +0100 Subject: [PATCH 0521/4982] x86, genapic: provide IPI callbacks unconditionally 64-bit x86 uses the IPI callbacks even on UP - so provide them generally. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/genapic.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/x86/include/asm/genapic.h b/arch/x86/include/asm/genapic.h index 19a5193e965..c27efde0523 100644 --- a/arch/x86/include/asm/genapic.h +++ b/arch/x86/include/asm/genapic.h @@ -73,7 +73,6 @@ struct genapic { unsigned int (*cpu_mask_to_apicid_and)(const struct cpumask *cpumask, const struct cpumask *andmask); -#ifdef CONFIG_SMP /* ipi */ void (*send_IPI_mask)(const struct cpumask *mask, int vector); void (*send_IPI_mask_allbutself)(const struct cpumask *mask, @@ -81,7 +80,7 @@ struct genapic { void (*send_IPI_allbutself)(int vector); void (*send_IPI_all)(int vector); void (*send_IPI_self)(int vector); -#endif + /* wakeup_secondary_cpu */ int (*wakeup_cpu)(int apicid, unsigned long start_eip); -- GitLab From c8d46cf06dc2e3a8f57a350eb9f9b19fd7f2ffe5 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 00:14:11 +0100 Subject: [PATCH 0522/4982] x86: rename 'genapic' to 'apic' Rename genapic-> to apic-> references because in a future chagne we'll open-code all the indirect calls (instead of obscuring them via macros), so we want this reference to be as short as possible. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/genapic.h | 2 +- arch/x86/include/asm/mach-default/mach_apic.h | 22 ++--- .../include/asm/mach-default/mach_apicdef.h | 6 +- arch/x86/include/asm/mach-default/mach_ipi.h | 8 +- arch/x86/include/asm/mach-generic/mach_apic.h | 50 ++++++------ .../include/asm/mach-generic/mach_apicdef.h | 4 +- arch/x86/include/asm/mach-generic/mach_ipi.h | 6 +- .../include/asm/mach-generic/mach_wakecpu.h | 14 ++-- arch/x86/kernel/es7000_32.c | 6 +- arch/x86/kernel/genapic_64.c | 16 ++-- arch/x86/kernel/io_apic.c | 80 +++++++++---------- arch/x86/kernel/numaq_32.c | 2 +- arch/x86/kernel/setup.c | 2 +- arch/x86/mach-generic/es7000.c | 12 +-- arch/x86/mach-generic/probe.c | 24 +++--- 15 files changed, 127 insertions(+), 127 deletions(-) diff --git a/arch/x86/include/asm/genapic.h b/arch/x86/include/asm/genapic.h index c27efde0523..3970da3245c 100644 --- a/arch/x86/include/asm/genapic.h +++ b/arch/x86/include/asm/genapic.h @@ -94,7 +94,7 @@ struct genapic { void (*inquire_remote_apic)(int apicid); }; -extern struct genapic *genapic; +extern struct genapic *apic; #ifdef CONFIG_X86_32 diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index cc09cbbee27..2448b927b64 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -22,18 +22,18 @@ static inline const struct cpumask *target_cpus(void) #ifdef CONFIG_X86_64 #include -#define INT_DELIVERY_MODE (genapic->int_delivery_mode) -#define INT_DEST_MODE (genapic->int_dest_mode) -#define TARGET_CPUS (genapic->target_cpus()) -#define apic_id_registered (genapic->apic_id_registered) -#define init_apic_ldr (genapic->init_apic_ldr) -#define cpu_mask_to_apicid (genapic->cpu_mask_to_apicid) -#define cpu_mask_to_apicid_and (genapic->cpu_mask_to_apicid_and) -#define phys_pkg_id (genapic->phys_pkg_id) -#define vector_allocation_domain (genapic->vector_allocation_domain) +#define INT_DELIVERY_MODE (apic->int_delivery_mode) +#define INT_DEST_MODE (apic->int_dest_mode) +#define TARGET_CPUS (apic->target_cpus()) +#define apic_id_registered (apic->apic_id_registered) +#define init_apic_ldr (apic->init_apic_ldr) +#define cpu_mask_to_apicid (apic->cpu_mask_to_apicid) +#define cpu_mask_to_apicid_and (apic->cpu_mask_to_apicid_and) +#define phys_pkg_id (apic->phys_pkg_id) +#define vector_allocation_domain (apic->vector_allocation_domain) #define read_apic_id() (GET_APIC_ID(apic_read(APIC_ID))) -#define send_IPI_self (genapic->send_IPI_self) -#define wakeup_secondary_cpu (genapic->wakeup_cpu) +#define send_IPI_self (apic->send_IPI_self) +#define wakeup_secondary_cpu (apic->wakeup_cpu) extern void setup_apic_routing(void); #else #define INT_DELIVERY_MODE dest_LowestPrio diff --git a/arch/x86/include/asm/mach-default/mach_apicdef.h b/arch/x86/include/asm/mach-default/mach_apicdef.h index 53179936d6c..b4dcc0971c7 100644 --- a/arch/x86/include/asm/mach-default/mach_apicdef.h +++ b/arch/x86/include/asm/mach-default/mach_apicdef.h @@ -4,9 +4,9 @@ #include #ifdef CONFIG_X86_64 -#define APIC_ID_MASK (genapic->apic_id_mask) -#define GET_APIC_ID(x) (genapic->get_apic_id(x)) -#define SET_APIC_ID(x) (genapic->set_apic_id(x)) +#define APIC_ID_MASK (apic->apic_id_mask) +#define GET_APIC_ID(x) (apic->get_apic_id(x)) +#define SET_APIC_ID(x) (apic->set_apic_id(x)) #else #define APIC_ID_MASK (0xF<<24) static inline unsigned get_apic_id(unsigned long x) diff --git a/arch/x86/include/asm/mach-default/mach_ipi.h b/arch/x86/include/asm/mach-default/mach_ipi.h index 191312d155d..089399643df 100644 --- a/arch/x86/include/asm/mach-default/mach_ipi.h +++ b/arch/x86/include/asm/mach-default/mach_ipi.h @@ -12,8 +12,8 @@ extern int no_broadcast; #ifdef CONFIG_X86_64 #include -#define send_IPI_mask (genapic->send_IPI_mask) -#define send_IPI_mask_allbutself (genapic->send_IPI_mask_allbutself) +#define send_IPI_mask (apic->send_IPI_mask) +#define send_IPI_mask_allbutself (apic->send_IPI_mask_allbutself) #else static inline void send_IPI_mask(const struct cpumask *mask, int vector) { @@ -39,8 +39,8 @@ static inline void __local_send_IPI_all(int vector) } #ifdef CONFIG_X86_64 -#define send_IPI_allbutself (genapic->send_IPI_allbutself) -#define send_IPI_all (genapic->send_IPI_all) +#define send_IPI_allbutself (apic->send_IPI_allbutself) +#define send_IPI_all (apic->send_IPI_all) #else static inline void send_IPI_allbutself(int vector) { diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index 48553e958ad..59972d94ff1 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -3,32 +3,32 @@ #include -#define esr_disable (genapic->ESR_DISABLE) -#define NO_BALANCE_IRQ (genapic->no_balance_irq) -#define INT_DELIVERY_MODE (genapic->int_delivery_mode) -#define INT_DEST_MODE (genapic->int_dest_mode) +#define esr_disable (apic->ESR_DISABLE) +#define NO_BALANCE_IRQ (apic->no_balance_irq) +#define INT_DELIVERY_MODE (apic->int_delivery_mode) +#define INT_DEST_MODE (apic->int_dest_mode) #undef APIC_DEST_LOGICAL -#define APIC_DEST_LOGICAL (genapic->apic_destination_logical) -#define TARGET_CPUS (genapic->target_cpus()) -#define apic_id_registered (genapic->apic_id_registered) -#define init_apic_ldr (genapic->init_apic_ldr) -#define ioapic_phys_id_map (genapic->ioapic_phys_id_map) -#define setup_apic_routing (genapic->setup_apic_routing) -#define multi_timer_check (genapic->multi_timer_check) -#define apicid_to_node (genapic->apicid_to_node) -#define cpu_to_logical_apicid (genapic->cpu_to_logical_apicid) -#define cpu_present_to_apicid (genapic->cpu_present_to_apicid) -#define apicid_to_cpu_present (genapic->apicid_to_cpu_present) -#define setup_portio_remap (genapic->setup_portio_remap) -#define check_apicid_present (genapic->check_apicid_present) -#define check_phys_apicid_present (genapic->check_phys_apicid_present) -#define check_apicid_used (genapic->check_apicid_used) -#define cpu_mask_to_apicid (genapic->cpu_mask_to_apicid) -#define cpu_mask_to_apicid_and (genapic->cpu_mask_to_apicid_and) -#define vector_allocation_domain (genapic->vector_allocation_domain) -#define enable_apic_mode (genapic->enable_apic_mode) -#define phys_pkg_id (genapic->phys_pkg_id) -#define wakeup_secondary_cpu (genapic->wakeup_cpu) +#define APIC_DEST_LOGICAL (apic->apic_destination_logical) +#define TARGET_CPUS (apic->target_cpus()) +#define apic_id_registered (apic->apic_id_registered) +#define init_apic_ldr (apic->init_apic_ldr) +#define ioapic_phys_id_map (apic->ioapic_phys_id_map) +#define setup_apic_routing (apic->setup_apic_routing) +#define multi_timer_check (apic->multi_timer_check) +#define apicid_to_node (apic->apicid_to_node) +#define cpu_to_logical_apicid (apic->cpu_to_logical_apicid) +#define cpu_present_to_apicid (apic->cpu_present_to_apicid) +#define apicid_to_cpu_present (apic->apicid_to_cpu_present) +#define setup_portio_remap (apic->setup_portio_remap) +#define check_apicid_present (apic->check_apicid_present) +#define check_phys_apicid_present (apic->check_phys_apicid_present) +#define check_apicid_used (apic->check_apicid_used) +#define cpu_mask_to_apicid (apic->cpu_mask_to_apicid) +#define cpu_mask_to_apicid_and (apic->cpu_mask_to_apicid_and) +#define vector_allocation_domain (apic->vector_allocation_domain) +#define enable_apic_mode (apic->enable_apic_mode) +#define phys_pkg_id (apic->phys_pkg_id) +#define wakeup_secondary_cpu (apic->wakeup_cpu) extern void generic_bigsmp_probe(void); diff --git a/arch/x86/include/asm/mach-generic/mach_apicdef.h b/arch/x86/include/asm/mach-generic/mach_apicdef.h index 68041f3802f..acc9adddb34 100644 --- a/arch/x86/include/asm/mach-generic/mach_apicdef.h +++ b/arch/x86/include/asm/mach-generic/mach_apicdef.h @@ -4,8 +4,8 @@ #ifndef APIC_DEFINITION #include -#define GET_APIC_ID (genapic->get_apic_id) -#define APIC_ID_MASK (genapic->apic_id_mask) +#define GET_APIC_ID (apic->get_apic_id) +#define APIC_ID_MASK (apic->apic_id_mask) #endif #endif /* _ASM_X86_MACH_GENERIC_MACH_APICDEF_H */ diff --git a/arch/x86/include/asm/mach-generic/mach_ipi.h b/arch/x86/include/asm/mach-generic/mach_ipi.h index ffd637e3c3d..75e54bd6cbd 100644 --- a/arch/x86/include/asm/mach-generic/mach_ipi.h +++ b/arch/x86/include/asm/mach-generic/mach_ipi.h @@ -3,8 +3,8 @@ #include -#define send_IPI_mask (genapic->send_IPI_mask) -#define send_IPI_allbutself (genapic->send_IPI_allbutself) -#define send_IPI_all (genapic->send_IPI_all) +#define send_IPI_mask (apic->send_IPI_mask) +#define send_IPI_allbutself (apic->send_IPI_allbutself) +#define send_IPI_all (apic->send_IPI_all) #endif /* _ASM_X86_MACH_GENERIC_MACH_IPI_H */ diff --git a/arch/x86/include/asm/mach-generic/mach_wakecpu.h b/arch/x86/include/asm/mach-generic/mach_wakecpu.h index 1ab16b168c8..22006bbee61 100644 --- a/arch/x86/include/asm/mach-generic/mach_wakecpu.h +++ b/arch/x86/include/asm/mach-generic/mach_wakecpu.h @@ -1,12 +1,12 @@ #ifndef _ASM_X86_MACH_GENERIC_MACH_WAKECPU_H #define _ASM_X86_MACH_GENERIC_MACH_WAKECPU_H -#define TRAMPOLINE_PHYS_LOW (genapic->trampoline_phys_low) -#define TRAMPOLINE_PHYS_HIGH (genapic->trampoline_phys_high) -#define wait_for_init_deassert (genapic->wait_for_init_deassert) -#define smp_callin_clear_local_apic (genapic->smp_callin_clear_local_apic) -#define store_NMI_vector (genapic->store_NMI_vector) -#define restore_NMI_vector (genapic->restore_NMI_vector) -#define inquire_remote_apic (genapic->inquire_remote_apic) +#define TRAMPOLINE_PHYS_LOW (apic->trampoline_phys_low) +#define TRAMPOLINE_PHYS_HIGH (apic->trampoline_phys_high) +#define wait_for_init_deassert (apic->wait_for_init_deassert) +#define smp_callin_clear_local_apic (apic->smp_callin_clear_local_apic) +#define store_NMI_vector (apic->store_NMI_vector) +#define restore_NMI_vector (apic->restore_NMI_vector) +#define inquire_remote_apic (apic->inquire_remote_apic) #endif /* _ASM_X86_MACH_GENERIC_MACH_APIC_H */ diff --git a/arch/x86/kernel/es7000_32.c b/arch/x86/kernel/es7000_32.c index 53699c931ad..20a2a43c2a9 100644 --- a/arch/x86/kernel/es7000_32.c +++ b/arch/x86/kernel/es7000_32.c @@ -188,14 +188,14 @@ static void noop_wait_for_deassert(atomic_t *deassert_not_used) static int __init es7000_update_genapic(void) { - genapic->wakeup_cpu = wakeup_secondary_cpu_via_mip; + apic->wakeup_cpu = wakeup_secondary_cpu_via_mip; /* MPENTIUMIII */ if (boot_cpu_data.x86 == 6 && (boot_cpu_data.x86_model >= 7 || boot_cpu_data.x86_model <= 11)) { es7000_update_genapic_to_cluster(); - genapic->wait_for_init_deassert = noop_wait_for_deassert; - genapic->wakeup_cpu = wakeup_secondary_cpu_via_mip; + apic->wait_for_init_deassert = noop_wait_for_deassert; + apic->wakeup_cpu = wakeup_secondary_cpu_via_mip; } return 0; diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c index e656c272115..2b986389a24 100644 --- a/arch/x86/kernel/genapic_64.c +++ b/arch/x86/kernel/genapic_64.c @@ -29,7 +29,7 @@ extern struct genapic apic_x2xpic_uv_x; extern struct genapic apic_x2apic_phys; extern struct genapic apic_x2apic_cluster; -struct genapic __read_mostly *genapic = &apic_flat; +struct genapic __read_mostly *apic = &apic_flat; static struct genapic *apic_probe[] __initdata = { #ifdef CONFIG_X86_UV @@ -46,15 +46,15 @@ static struct genapic *apic_probe[] __initdata = { */ void __init setup_apic_routing(void) { - if (genapic == &apic_x2apic_phys || genapic == &apic_x2apic_cluster) { + if (apic == &apic_x2apic_phys || apic == &apic_x2apic_cluster) { if (!intr_remapping_enabled) - genapic = &apic_flat; + apic = &apic_flat; } - if (genapic == &apic_flat) { + if (apic == &apic_flat) { if (max_physical_apicid >= 8) - genapic = &apic_physflat; - printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name); + apic = &apic_physflat; + printk(KERN_INFO "Setting APIC routing to %s\n", apic->name); } if (x86_quirks->update_genapic) @@ -74,9 +74,9 @@ int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) for (i = 0; apic_probe[i]; ++i) { if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) { - genapic = apic_probe[i]; + apic = apic_probe[i]; printk(KERN_INFO "Setting APIC routing to %s.\n", - genapic->name); + apic->name); return 1; } } diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index bfb7d734062..7283234229f 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -1486,7 +1486,7 @@ static void ioapic_register_intr(int irq, struct irq_desc *desc, unsigned long t handle_edge_irq, "edge"); } -static int setup_ioapic_entry(int apic, int irq, +static int setup_ioapic_entry(int apic_id, int irq, struct IO_APIC_route_entry *entry, unsigned int destination, int trigger, int polarity, int vector) @@ -1498,18 +1498,18 @@ static int setup_ioapic_entry(int apic, int irq, #ifdef CONFIG_INTR_REMAP if (intr_remapping_enabled) { - struct intel_iommu *iommu = map_ioapic_to_ir(apic); + struct intel_iommu *iommu = map_ioapic_to_ir(apic_id); struct irte irte; struct IR_IO_APIC_route_entry *ir_entry = (struct IR_IO_APIC_route_entry *) entry; int index; if (!iommu) - panic("No mapping iommu for ioapic %d\n", apic); + panic("No mapping iommu for ioapic %d\n", apic_id); index = alloc_irte(iommu, irq, 1); if (index < 0) - panic("Failed to allocate IRTE for ioapic %d\n", apic); + panic("Failed to allocate IRTE for ioapic %d\n", apic_id); memset(&irte, 0, sizeof(irte)); @@ -1547,7 +1547,7 @@ static int setup_ioapic_entry(int apic, int irq, return 0; } -static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, struct irq_desc *desc, +static void setup_IO_APIC_irq(int apic_id, int pin, unsigned int irq, struct irq_desc *desc, int trigger, int polarity) { struct irq_cfg *cfg; @@ -1567,14 +1567,14 @@ static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, struct irq_de apic_printk(APIC_VERBOSE,KERN_DEBUG "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> " "IRQ %d Mode:%i Active:%i)\n", - apic, mp_ioapics[apic].apicid, pin, cfg->vector, + apic_id, mp_ioapics[apic_id].apicid, pin, cfg->vector, irq, trigger, polarity); - if (setup_ioapic_entry(mp_ioapics[apic].apicid, irq, &entry, + if (setup_ioapic_entry(mp_ioapics[apic_id].apicid, irq, &entry, dest, trigger, polarity, cfg->vector)) { printk("Failed to setup ioapic entry for ioapic %d, pin %d\n", - mp_ioapics[apic].apicid, pin); + mp_ioapics[apic_id].apicid, pin); __clear_irq_vector(irq, cfg); return; } @@ -1583,12 +1583,12 @@ static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, struct irq_de if (irq < NR_IRQS_LEGACY) disable_8259A_irq(irq); - ioapic_write_entry(apic, pin, entry); + ioapic_write_entry(apic_id, pin, entry); } static void __init setup_IO_APIC_irqs(void) { - int apic, pin, idx, irq; + int apic_id, pin, idx, irq; int notcon = 0; struct irq_desc *desc; struct irq_cfg *cfg; @@ -1596,19 +1596,19 @@ static void __init setup_IO_APIC_irqs(void) apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); - for (apic = 0; apic < nr_ioapics; apic++) { - for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { + for (apic_id = 0; apic_id < nr_ioapics; apic_id++) { + for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) { - idx = find_irq_entry(apic, pin, mp_INT); + idx = find_irq_entry(apic_id, pin, mp_INT); if (idx == -1) { if (!notcon) { notcon = 1; apic_printk(APIC_VERBOSE, KERN_DEBUG " %d-%d", - mp_ioapics[apic].apicid, pin); + mp_ioapics[apic_id].apicid, pin); } else apic_printk(APIC_VERBOSE, " %d-%d", - mp_ioapics[apic].apicid, pin); + mp_ioapics[apic_id].apicid, pin); continue; } if (notcon) { @@ -1617,9 +1617,9 @@ static void __init setup_IO_APIC_irqs(void) notcon = 0; } - irq = pin_2_irq(idx, apic, pin); + irq = pin_2_irq(idx, apic_id, pin); #ifdef CONFIG_X86_32 - if (multi_timer_check(apic, irq)) + if (multi_timer_check(apic_id, irq)) continue; #endif desc = irq_to_desc_alloc_cpu(irq, cpu); @@ -1628,9 +1628,9 @@ static void __init setup_IO_APIC_irqs(void) continue; } cfg = desc->chip_data; - add_pin_to_irq_cpu(cfg, cpu, apic, pin); + add_pin_to_irq_cpu(cfg, cpu, apic_id, pin); - setup_IO_APIC_irq(apic, pin, irq, desc, + setup_IO_APIC_irq(apic_id, pin, irq, desc, irq_trigger(idx), irq_polarity(idx)); } } @@ -1643,7 +1643,7 @@ static void __init setup_IO_APIC_irqs(void) /* * Set up the timer pin, possibly with the 8259A-master behind. */ -static void __init setup_timer_IRQ0_pin(unsigned int apic, unsigned int pin, +static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin, int vector) { struct IO_APIC_route_entry entry; @@ -1676,7 +1676,7 @@ static void __init setup_timer_IRQ0_pin(unsigned int apic, unsigned int pin, /* * Add it to the IO-APIC irq-routing table: */ - ioapic_write_entry(apic, pin, entry); + ioapic_write_entry(apic_id, pin, entry); } @@ -2089,7 +2089,7 @@ static void __init setup_ioapic_ids_from_mpc(void) { union IO_APIC_reg_00 reg_00; physid_mask_t phys_id_present_map; - int apic; + int apic_id; int i; unsigned char old_id; unsigned long flags; @@ -2113,21 +2113,21 @@ static void __init setup_ioapic_ids_from_mpc(void) /* * Set the IOAPIC ID to the value stored in the MPC table. */ - for (apic = 0; apic < nr_ioapics; apic++) { + for (apic_id = 0; apic_id < nr_ioapics; apic_id++) { /* Read the register 0 value */ spin_lock_irqsave(&ioapic_lock, flags); - reg_00.raw = io_apic_read(apic, 0); + reg_00.raw = io_apic_read(apic_id, 0); spin_unlock_irqrestore(&ioapic_lock, flags); - old_id = mp_ioapics[apic].apicid; + old_id = mp_ioapics[apic_id].apicid; - if (mp_ioapics[apic].apicid >= get_physical_broadcast()) { + if (mp_ioapics[apic_id].apicid >= get_physical_broadcast()) { printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n", - apic, mp_ioapics[apic].apicid); + apic_id, mp_ioapics[apic_id].apicid); printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", reg_00.bits.ID); - mp_ioapics[apic].apicid = reg_00.bits.ID; + mp_ioapics[apic_id].apicid = reg_00.bits.ID; } /* @@ -2136,9 +2136,9 @@ static void __init setup_ioapic_ids_from_mpc(void) * 'stuck on smp_invalidate_needed IPI wait' messages. */ if (check_apicid_used(phys_id_present_map, - mp_ioapics[apic].apicid)) { + mp_ioapics[apic_id].apicid)) { printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n", - apic, mp_ioapics[apic].apicid); + apic_id, mp_ioapics[apic_id].apicid); for (i = 0; i < get_physical_broadcast(); i++) if (!physid_isset(i, phys_id_present_map)) break; @@ -2147,13 +2147,13 @@ static void __init setup_ioapic_ids_from_mpc(void) printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", i); physid_set(i, phys_id_present_map); - mp_ioapics[apic].apicid = i; + mp_ioapics[apic_id].apicid = i; } else { physid_mask_t tmp; - tmp = apicid_to_cpu_present(mp_ioapics[apic].apicid); + tmp = apicid_to_cpu_present(mp_ioapics[apic_id].apicid); apic_printk(APIC_VERBOSE, "Setting %d in the " "phys_id_present_map\n", - mp_ioapics[apic].apicid); + mp_ioapics[apic_id].apicid); physids_or(phys_id_present_map, phys_id_present_map, tmp); } @@ -2162,11 +2162,11 @@ static void __init setup_ioapic_ids_from_mpc(void) * We need to adjust the IRQ routing table * if the ID changed. */ - if (old_id != mp_ioapics[apic].apicid) + if (old_id != mp_ioapics[apic_id].apicid) for (i = 0; i < mp_irq_entries; i++) if (mp_irqs[i].dstapic == old_id) mp_irqs[i].dstapic - = mp_ioapics[apic].apicid; + = mp_ioapics[apic_id].apicid; /* * Read the right value from the MPC table and @@ -2174,20 +2174,20 @@ static void __init setup_ioapic_ids_from_mpc(void) */ apic_printk(APIC_VERBOSE, KERN_INFO "...changing IO-APIC physical APIC ID to %d ...", - mp_ioapics[apic].apicid); + mp_ioapics[apic_id].apicid); - reg_00.bits.ID = mp_ioapics[apic].apicid; + reg_00.bits.ID = mp_ioapics[apic_id].apicid; spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(apic, 0, reg_00.raw); + io_apic_write(apic_id, 0, reg_00.raw); spin_unlock_irqrestore(&ioapic_lock, flags); /* * Sanity check */ spin_lock_irqsave(&ioapic_lock, flags); - reg_00.raw = io_apic_read(apic, 0); + reg_00.raw = io_apic_read(apic_id, 0); spin_unlock_irqrestore(&ioapic_lock, flags); - if (reg_00.bits.ID != mp_ioapics[apic].apicid) + if (reg_00.bits.ID != mp_ioapics[apic_id].apicid) printk("could not set ID!\n"); else apic_printk(APIC_VERBOSE, " ok.\n"); diff --git a/arch/x86/kernel/numaq_32.c b/arch/x86/kernel/numaq_32.c index f2191d4f271..3928280278f 100644 --- a/arch/x86/kernel/numaq_32.c +++ b/arch/x86/kernel/numaq_32.c @@ -236,7 +236,7 @@ static int __init numaq_setup_ioapic_ids(void) static int __init numaq_update_genapic(void) { - genapic->wakeup_cpu = wakeup_secondary_cpu_via_nmi; + apic->wakeup_cpu = wakeup_secondary_cpu_via_nmi; return 0; } diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index f41c4486c27..a58e9f5e603 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -590,7 +590,7 @@ static int __init default_update_genapic(void) { #ifdef CONFIG_X86_SMP # if defined(CONFIG_X86_GENERICARCH) || defined(CONFIG_X86_64) - genapic->wakeup_cpu = wakeup_secondary_cpu_via_init; + apic->wakeup_cpu = wakeup_secondary_cpu_via_init; # endif #endif diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index c2ded144802..2f4f4a6e39b 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -20,14 +20,14 @@ void __init es7000_update_genapic_to_cluster(void) { - genapic->target_cpus = target_cpus_cluster; - genapic->int_delivery_mode = INT_DELIVERY_MODE_CLUSTER; - genapic->int_dest_mode = INT_DEST_MODE_CLUSTER; - genapic->no_balance_irq = NO_BALANCE_IRQ_CLUSTER; + apic->target_cpus = target_cpus_cluster; + apic->int_delivery_mode = INT_DELIVERY_MODE_CLUSTER; + apic->int_dest_mode = INT_DEST_MODE_CLUSTER; + apic->no_balance_irq = NO_BALANCE_IRQ_CLUSTER; - genapic->init_apic_ldr = init_apic_ldr_cluster; + apic->init_apic_ldr = init_apic_ldr_cluster; - genapic->cpu_mask_to_apicid = cpu_mask_to_apicid_cluster; + apic->cpu_mask_to_apicid = cpu_mask_to_apicid_cluster; } static int probe_es7000(void) diff --git a/arch/x86/mach-generic/probe.c b/arch/x86/mach-generic/probe.c index 15a38daef1a..82bf0f520fb 100644 --- a/arch/x86/mach-generic/probe.c +++ b/arch/x86/mach-generic/probe.c @@ -23,7 +23,7 @@ extern struct genapic apic_bigsmp; extern struct genapic apic_es7000; extern struct genapic apic_default; -struct genapic *genapic = &apic_default; +struct genapic *apic = &apic_default; static struct genapic *apic_probe[] __initdata = { #ifdef CONFIG_X86_NUMAQ @@ -52,7 +52,7 @@ static int __init parse_apic(char *arg) for (i = 0; apic_probe[i]; i++) { if (!strcmp(apic_probe[i]->name, arg)) { - genapic = apic_probe[i]; + apic = apic_probe[i]; cmdline_apic = 1; return 0; } @@ -76,13 +76,13 @@ void __init generic_bigsmp_probe(void) * - we find more than 8 CPUs in acpi LAPIC listing with xAPIC support */ - if (!cmdline_apic && genapic == &apic_default) { + if (!cmdline_apic && apic == &apic_default) { if (apic_bigsmp.probe()) { - genapic = &apic_bigsmp; + apic = &apic_bigsmp; if (x86_quirks->update_genapic) x86_quirks->update_genapic(); printk(KERN_INFO "Overriding APIC driver with %s\n", - genapic->name); + apic->name); } } #endif @@ -94,7 +94,7 @@ void __init generic_apic_probe(void) int i; for (i = 0; apic_probe[i]; i++) { if (apic_probe[i]->probe()) { - genapic = apic_probe[i]; + apic = apic_probe[i]; break; } } @@ -105,7 +105,7 @@ void __init generic_apic_probe(void) if (x86_quirks->update_genapic) x86_quirks->update_genapic(); } - printk(KERN_INFO "Using APIC driver %s\n", genapic->name); + printk(KERN_INFO "Using APIC driver %s\n", apic->name); } /* These functions can switch the APIC even after the initial ->probe() */ @@ -116,11 +116,11 @@ int __init mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) for (i = 0; apic_probe[i]; ++i) { if (apic_probe[i]->mps_oem_check(mpc, oem, productid)) { if (!cmdline_apic) { - genapic = apic_probe[i]; + apic = apic_probe[i]; if (x86_quirks->update_genapic) x86_quirks->update_genapic(); printk(KERN_INFO "Switched to APIC driver `%s'.\n", - genapic->name); + apic->name); } return 1; } @@ -134,11 +134,11 @@ int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) for (i = 0; apic_probe[i]; ++i) { if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) { if (!cmdline_apic) { - genapic = apic_probe[i]; + apic = apic_probe[i]; if (x86_quirks->update_genapic) x86_quirks->update_genapic(); printk(KERN_INFO "Switched to APIC driver `%s'.\n", - genapic->name); + apic->name); } return 1; } @@ -148,5 +148,5 @@ int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) int hard_smp_processor_id(void) { - return genapic->get_apic_id(*(unsigned long *)(APIC_BASE+APIC_ID)); + return apic->get_apic_id(*(unsigned long *)(APIC_BASE+APIC_ID)); } -- GitLab From f2f05ee8b8d346d4edee766384a5fedafdd4f9f8 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 02:37:01 +0100 Subject: [PATCH 0523/4982] x86: clean up genapic_flat - reorder fields so that they appear in struct genapic field ordering - add zero-initialized fields too so that it's apparent which functionality is default / missing. Signed-off-by: Ingo Molnar --- arch/x86/kernel/genapic_flat_64.c | 73 +++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 19 deletions(-) diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index 34185488e4f..f1bfdd3608a 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -175,25 +175,60 @@ static unsigned int phys_pkg_id(int index_msb) } struct genapic apic_flat = { - .name = "flat", - .acpi_madt_oem_check = flat_acpi_madt_oem_check, - .int_delivery_mode = dest_LowestPrio, - .int_dest_mode = (APIC_DEST_LOGICAL != 0), - .target_cpus = flat_target_cpus, - .vector_allocation_domain = flat_vector_allocation_domain, - .apic_id_registered = flat_apic_id_registered, - .init_apic_ldr = flat_init_apic_ldr, - .send_IPI_all = flat_send_IPI_all, - .send_IPI_allbutself = flat_send_IPI_allbutself, - .send_IPI_mask = flat_send_IPI_mask, - .send_IPI_mask_allbutself = flat_send_IPI_mask_allbutself, - .send_IPI_self = apic_send_IPI_self, - .cpu_mask_to_apicid = flat_cpu_mask_to_apicid, - .cpu_mask_to_apicid_and = flat_cpu_mask_to_apicid_and, - .phys_pkg_id = phys_pkg_id, - .get_apic_id = get_apic_id, - .set_apic_id = set_apic_id, - .apic_id_mask = (0xFFu<<24), + .name = "flat", + .probe = NULL, + .acpi_madt_oem_check = flat_acpi_madt_oem_check, + .apic_id_registered = flat_apic_id_registered, + + .int_delivery_mode = dest_LowestPrio, + .int_dest_mode = (APIC_DEST_LOGICAL != 0), + + .target_cpus = flat_target_cpus, + .ESR_DISABLE = 0, + .apic_destination_logical = 0, + .check_apicid_used = NULL, + .check_apicid_present = NULL, + + .no_balance_irq = 0, + .no_ioapic_check = 0, + + .vector_allocation_domain = flat_vector_allocation_domain, + .init_apic_ldr = flat_init_apic_ldr, + + .ioapic_phys_id_map = NULL, + .setup_apic_routing = NULL, + .multi_timer_check = NULL, + .apicid_to_node = NULL, + .cpu_to_logical_apicid = NULL, + .cpu_present_to_apicid = NULL, + .apicid_to_cpu_present = NULL, + .setup_portio_remap = NULL, + .check_phys_apicid_present = NULL, + .enable_apic_mode = NULL, + .phys_pkg_id = phys_pkg_id, + .mps_oem_check = NULL, + + .get_apic_id = get_apic_id, + .set_apic_id = set_apic_id, + .apic_id_mask = 0xFFu << 24, + + .cpu_mask_to_apicid = flat_cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = flat_cpu_mask_to_apicid_and, + + .send_IPI_mask = flat_send_IPI_mask, + .send_IPI_mask_allbutself = flat_send_IPI_mask_allbutself, + .send_IPI_allbutself = flat_send_IPI_allbutself, + .send_IPI_all = flat_send_IPI_all, + .send_IPI_self = apic_send_IPI_self, + + .wakeup_cpu = NULL, + .trampoline_phys_low = 0, + .trampoline_phys_high = 0, + .wait_for_init_deassert = NULL, + .smp_callin_clear_local_apic = NULL, + .store_NMI_vector = NULL, + .restore_NMI_vector = NULL, + .inquire_remote_apic = NULL, }; /* -- GitLab From 4c3e51e05a7eefead4033b187394458ff8626497 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 02:37:01 +0100 Subject: [PATCH 0524/4982] x86: clean up genapic_phys_flat - reorder fields so that they appear in struct genapic field ordering - add zero-initialized fields too so that it's apparent which functionality is default / missing. Signed-off-by: Ingo Molnar --- arch/x86/kernel/genapic_flat_64.c | 75 +++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 19 deletions(-) diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index f1bfdd3608a..e9233374cef 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -320,23 +320,60 @@ physflat_cpu_mask_to_apicid_and(const struct cpumask *cpumask, } struct genapic apic_physflat = { - .name = "physical flat", - .acpi_madt_oem_check = physflat_acpi_madt_oem_check, - .int_delivery_mode = dest_Fixed, - .int_dest_mode = (APIC_DEST_PHYSICAL != 0), - .target_cpus = physflat_target_cpus, - .vector_allocation_domain = physflat_vector_allocation_domain, - .apic_id_registered = flat_apic_id_registered, - .init_apic_ldr = flat_init_apic_ldr,/*not needed, but shouldn't hurt*/ - .send_IPI_all = physflat_send_IPI_all, - .send_IPI_allbutself = physflat_send_IPI_allbutself, - .send_IPI_mask = physflat_send_IPI_mask, - .send_IPI_mask_allbutself = physflat_send_IPI_mask_allbutself, - .send_IPI_self = apic_send_IPI_self, - .cpu_mask_to_apicid = physflat_cpu_mask_to_apicid, - .cpu_mask_to_apicid_and = physflat_cpu_mask_to_apicid_and, - .phys_pkg_id = phys_pkg_id, - .get_apic_id = get_apic_id, - .set_apic_id = set_apic_id, - .apic_id_mask = (0xFFu<<24), + + .name = "physical flat", + .probe = NULL, + .acpi_madt_oem_check = physflat_acpi_madt_oem_check, + .apic_id_registered = flat_apic_id_registered, + + .int_delivery_mode = dest_Fixed, + .int_dest_mode = (APIC_DEST_PHYSICAL != 0), + + .target_cpus = physflat_target_cpus, + .ESR_DISABLE = 0, + .apic_destination_logical = 0, + .check_apicid_used = NULL, + .check_apicid_present = NULL, + + .no_balance_irq = 0, + .no_ioapic_check = 0, + + .vector_allocation_domain = physflat_vector_allocation_domain, + /* not needed, but shouldn't hurt: */ + .init_apic_ldr = flat_init_apic_ldr, + + .ioapic_phys_id_map = NULL, + .setup_apic_routing = NULL, + .multi_timer_check = NULL, + .apicid_to_node = NULL, + .cpu_to_logical_apicid = NULL, + .cpu_present_to_apicid = NULL, + .apicid_to_cpu_present = NULL, + .setup_portio_remap = NULL, + .check_phys_apicid_present = NULL, + .enable_apic_mode = NULL, + .phys_pkg_id = phys_pkg_id, + .mps_oem_check = NULL, + + .get_apic_id = get_apic_id, + .set_apic_id = set_apic_id, + .apic_id_mask = 0xFFu<<24, + + .cpu_mask_to_apicid = physflat_cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = physflat_cpu_mask_to_apicid_and, + + .send_IPI_mask = physflat_send_IPI_mask, + .send_IPI_mask_allbutself = physflat_send_IPI_mask_allbutself, + .send_IPI_allbutself = physflat_send_IPI_allbutself, + .send_IPI_all = physflat_send_IPI_all, + .send_IPI_self = apic_send_IPI_self, + + .wakeup_cpu = NULL, + .trampoline_phys_low = 0, + .trampoline_phys_high = 0, + .wait_for_init_deassert = NULL, + .smp_callin_clear_local_apic = NULL, + .store_NMI_vector = NULL, + .restore_NMI_vector = NULL, + .inquire_remote_apic = NULL, }; -- GitLab From c7967329911013a05920ef12832935c541bb8c9a Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 02:37:01 +0100 Subject: [PATCH 0525/4982] x86: clean up apic_x2apic_uv_x - reorder fields so that they appear in struct genapic field ordering - add zero-initialized fields too so that it's apparent which functionality is default / missing. Signed-off-by: Ingo Molnar --- arch/x86/kernel/genx2apic_uv_x.c | 74 ++++++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index bfe36249145..94f606f204a 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -237,25 +237,61 @@ static void uv_send_IPI_self(int vector) } struct genapic apic_x2apic_uv_x = { - .name = "UV large system", - .acpi_madt_oem_check = uv_acpi_madt_oem_check, - .int_delivery_mode = dest_Fixed, - .int_dest_mode = (APIC_DEST_PHYSICAL != 0), - .target_cpus = uv_target_cpus, - .vector_allocation_domain = uv_vector_allocation_domain, - .apic_id_registered = uv_apic_id_registered, - .init_apic_ldr = uv_init_apic_ldr, - .send_IPI_all = uv_send_IPI_all, - .send_IPI_allbutself = uv_send_IPI_allbutself, - .send_IPI_mask = uv_send_IPI_mask, - .send_IPI_mask_allbutself = uv_send_IPI_mask_allbutself, - .send_IPI_self = uv_send_IPI_self, - .cpu_mask_to_apicid = uv_cpu_mask_to_apicid, - .cpu_mask_to_apicid_and = uv_cpu_mask_to_apicid_and, - .phys_pkg_id = phys_pkg_id, - .get_apic_id = get_apic_id, - .set_apic_id = set_apic_id, - .apic_id_mask = (0xFFFFFFFFu), + + .name = "UV large system", + .probe = NULL, + .acpi_madt_oem_check = uv_acpi_madt_oem_check, + .apic_id_registered = uv_apic_id_registered, + + .int_delivery_mode = dest_Fixed, + .int_dest_mode = (APIC_DEST_PHYSICAL != 0), + + .target_cpus = uv_target_cpus, + .ESR_DISABLE = 0, + .apic_destination_logical = 0, + .check_apicid_used = NULL, + .check_apicid_present = NULL, + + .no_balance_irq = 0, + .no_ioapic_check = 0, + + .vector_allocation_domain = uv_vector_allocation_domain, + .init_apic_ldr = uv_init_apic_ldr, + + .ioapic_phys_id_map = NULL, + .setup_apic_routing = NULL, + .multi_timer_check = NULL, + .apicid_to_node = NULL, + .cpu_to_logical_apicid = NULL, + .cpu_present_to_apicid = NULL, + .apicid_to_cpu_present = NULL, + .setup_portio_remap = NULL, + .check_phys_apicid_present = NULL, + .enable_apic_mode = NULL, + .phys_pkg_id = phys_pkg_id, + .mps_oem_check = NULL, + + .get_apic_id = get_apic_id, + .set_apic_id = set_apic_id, + .apic_id_mask = 0xFFFFFFFFu, + + .cpu_mask_to_apicid = uv_cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = uv_cpu_mask_to_apicid_and, + + .send_IPI_mask = uv_send_IPI_mask, + .send_IPI_mask_allbutself = uv_send_IPI_mask_allbutself, + .send_IPI_allbutself = uv_send_IPI_allbutself, + .send_IPI_all = uv_send_IPI_all, + .send_IPI_self = uv_send_IPI_self, + + .wakeup_cpu = NULL, + .trampoline_phys_low = 0, + .trampoline_phys_high = 0, + .wait_for_init_deassert = NULL, + .smp_callin_clear_local_apic = NULL, + .store_NMI_vector = NULL, + .restore_NMI_vector = NULL, + .inquire_remote_apic = NULL, }; static __cpuinit void set_x2apic_extra_bits(int pnode) -- GitLab From 05c155c235c757329ec89ad591516538ed8352c0 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 02:37:01 +0100 Subject: [PATCH 0526/4982] x86: clean up apic_x2apic_phys - reorder fields so that they appear in struct genapic field ordering - add zero-initialized fields too so that it's apparent which functionality is default / missing. Signed-off-by: Ingo Molnar --- arch/x86/kernel/genx2apic_phys.c | 74 ++++++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c index 21bcc0e098b..c98361fb7ee 100644 --- a/arch/x86/kernel/genx2apic_phys.c +++ b/arch/x86/kernel/genx2apic_phys.c @@ -172,23 +172,59 @@ static void init_x2apic_ldr(void) } struct genapic apic_x2apic_phys = { - .name = "physical x2apic", - .acpi_madt_oem_check = x2apic_acpi_madt_oem_check, - .int_delivery_mode = dest_Fixed, - .int_dest_mode = (APIC_DEST_PHYSICAL != 0), - .target_cpus = x2apic_target_cpus, - .vector_allocation_domain = x2apic_vector_allocation_domain, - .apic_id_registered = x2apic_apic_id_registered, - .init_apic_ldr = init_x2apic_ldr, - .send_IPI_all = x2apic_send_IPI_all, - .send_IPI_allbutself = x2apic_send_IPI_allbutself, - .send_IPI_mask = x2apic_send_IPI_mask, - .send_IPI_mask_allbutself = x2apic_send_IPI_mask_allbutself, - .send_IPI_self = x2apic_send_IPI_self, - .cpu_mask_to_apicid = x2apic_cpu_mask_to_apicid, - .cpu_mask_to_apicid_and = x2apic_cpu_mask_to_apicid_and, - .phys_pkg_id = phys_pkg_id, - .get_apic_id = get_apic_id, - .set_apic_id = set_apic_id, - .apic_id_mask = (0xFFFFFFFFu), + + .name = "physical x2apic", + .probe = NULL, + .acpi_madt_oem_check = x2apic_acpi_madt_oem_check, + .apic_id_registered = x2apic_apic_id_registered, + + .int_delivery_mode = dest_Fixed, + .int_dest_mode = (APIC_DEST_PHYSICAL != 0), + + .target_cpus = x2apic_target_cpus, + .ESR_DISABLE = 0, + .apic_destination_logical = 0, + .check_apicid_used = NULL, + .check_apicid_present = NULL, + + .no_balance_irq = 0, + .no_ioapic_check = 0, + + .vector_allocation_domain = x2apic_vector_allocation_domain, + .init_apic_ldr = init_x2apic_ldr, + + .ioapic_phys_id_map = NULL, + .setup_apic_routing = NULL, + .multi_timer_check = NULL, + .apicid_to_node = NULL, + .cpu_to_logical_apicid = NULL, + .cpu_present_to_apicid = NULL, + .apicid_to_cpu_present = NULL, + .setup_portio_remap = NULL, + .check_phys_apicid_present = NULL, + .enable_apic_mode = NULL, + .phys_pkg_id = phys_pkg_id, + .mps_oem_check = NULL, + + .get_apic_id = get_apic_id, + .set_apic_id = set_apic_id, + .apic_id_mask = 0xFFFFFFFFu, + + .cpu_mask_to_apicid = x2apic_cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = x2apic_cpu_mask_to_apicid_and, + + .send_IPI_mask = x2apic_send_IPI_mask, + .send_IPI_mask_allbutself = x2apic_send_IPI_mask_allbutself, + .send_IPI_allbutself = x2apic_send_IPI_allbutself, + .send_IPI_all = x2apic_send_IPI_all, + .send_IPI_self = x2apic_send_IPI_self, + + .wakeup_cpu = NULL, + .trampoline_phys_low = 0, + .trampoline_phys_high = 0, + .wait_for_init_deassert = NULL, + .smp_callin_clear_local_apic = NULL, + .store_NMI_vector = NULL, + .restore_NMI_vector = NULL, + .inquire_remote_apic = NULL, }; -- GitLab From 504a3c3ad45d200a6ac8be5aa019c8fa05e26dc8 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 02:37:01 +0100 Subject: [PATCH 0527/4982] x86: clean up apic_x2apic_cluster - reorder fields so that they appear in struct genapic field ordering - add zero-initialized fields too so that it's apparent which functionality is default / missing. Signed-off-by: Ingo Molnar --- arch/x86/kernel/genx2apic_cluster.c | 74 +++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c index 6ce497cc372..fc855e503ac 100644 --- a/arch/x86/kernel/genx2apic_cluster.c +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -176,23 +176,59 @@ static void init_x2apic_ldr(void) } struct genapic apic_x2apic_cluster = { - .name = "cluster x2apic", - .acpi_madt_oem_check = x2apic_acpi_madt_oem_check, - .int_delivery_mode = dest_LowestPrio, - .int_dest_mode = (APIC_DEST_LOGICAL != 0), - .target_cpus = x2apic_target_cpus, - .vector_allocation_domain = x2apic_vector_allocation_domain, - .apic_id_registered = x2apic_apic_id_registered, - .init_apic_ldr = init_x2apic_ldr, - .send_IPI_all = x2apic_send_IPI_all, - .send_IPI_allbutself = x2apic_send_IPI_allbutself, - .send_IPI_mask = x2apic_send_IPI_mask, - .send_IPI_mask_allbutself = x2apic_send_IPI_mask_allbutself, - .send_IPI_self = x2apic_send_IPI_self, - .cpu_mask_to_apicid = x2apic_cpu_mask_to_apicid, - .cpu_mask_to_apicid_and = x2apic_cpu_mask_to_apicid_and, - .phys_pkg_id = phys_pkg_id, - .get_apic_id = get_apic_id, - .set_apic_id = set_apic_id, - .apic_id_mask = (0xFFFFFFFFu), + + .name = "cluster x2apic", + .probe = NULL, + .acpi_madt_oem_check = x2apic_acpi_madt_oem_check, + .apic_id_registered = x2apic_apic_id_registered, + + .int_delivery_mode = dest_LowestPrio, + .int_dest_mode = (APIC_DEST_LOGICAL != 0), + + .target_cpus = x2apic_target_cpus, + .ESR_DISABLE = 0, + .apic_destination_logical = 0, + .check_apicid_used = NULL, + .check_apicid_present = NULL, + + .no_balance_irq = 0, + .no_ioapic_check = 0, + + .vector_allocation_domain = x2apic_vector_allocation_domain, + .init_apic_ldr = init_x2apic_ldr, + + .ioapic_phys_id_map = NULL, + .setup_apic_routing = NULL, + .multi_timer_check = NULL, + .apicid_to_node = NULL, + .cpu_to_logical_apicid = NULL, + .cpu_present_to_apicid = NULL, + .apicid_to_cpu_present = NULL, + .setup_portio_remap = NULL, + .check_phys_apicid_present = NULL, + .enable_apic_mode = NULL, + .phys_pkg_id = phys_pkg_id, + .mps_oem_check = NULL, + + .get_apic_id = get_apic_id, + .set_apic_id = set_apic_id, + .apic_id_mask = 0xFFFFFFFFu, + + .cpu_mask_to_apicid = x2apic_cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = x2apic_cpu_mask_to_apicid_and, + + .send_IPI_mask = x2apic_send_IPI_mask, + .send_IPI_mask_allbutself = x2apic_send_IPI_mask_allbutself, + .send_IPI_allbutself = x2apic_send_IPI_allbutself, + .send_IPI_all = x2apic_send_IPI_all, + .send_IPI_self = x2apic_send_IPI_self, + + .wakeup_cpu = NULL, + .trampoline_phys_low = 0, + .trampoline_phys_high = 0, + .wait_for_init_deassert = NULL, + .smp_callin_clear_local_apic = NULL, + .store_NMI_vector = NULL, + .restore_NMI_vector = NULL, + .inquire_remote_apic = NULL, }; -- GitLab From 0a7e8c64142b2ae5aacdc509ed112b8e362ac8a4 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 03:32:03 +0100 Subject: [PATCH 0528/4982] x86, genapic: cleanup 32-bit apic_default template Clean up the APIC driver template: - order fields properly - use the macro names explicitly (so that they can be renamed later) - fill in NULL entries as well Signed-off-by: Ingo Molnar --- arch/x86/mach-generic/default.c | 58 ++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index e63a4a76d8c..d5fec764fb4 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -24,4 +24,60 @@ static int probe_default(void) return 1; } -struct genapic apic_default = APIC_INIT("default", probe_default); +struct genapic apic_default = { + + .name = "default", + .probe = probe_default, + .acpi_madt_oem_check = acpi_madt_oem_check, + .apic_id_registered = apic_id_registered, + + .int_delivery_mode = INT_DELIVERY_MODE, + .int_dest_mode = INT_DEST_MODE, + + .target_cpus = target_cpus, + .ESR_DISABLE = esr_disable, + .apic_destination_logical = APIC_DEST_LOGICAL, + .check_apicid_used = check_apicid_used, + .check_apicid_present = check_apicid_present, + + .no_balance_irq = NO_BALANCE_IRQ, + .no_ioapic_check = 0, + + .vector_allocation_domain = vector_allocation_domain, + .init_apic_ldr = init_apic_ldr, + + .ioapic_phys_id_map = ioapic_phys_id_map, + .setup_apic_routing = setup_apic_routing, + .multi_timer_check = multi_timer_check, + .apicid_to_node = apicid_to_node, + .cpu_to_logical_apicid = cpu_to_logical_apicid, + .cpu_present_to_apicid = cpu_present_to_apicid, + .apicid_to_cpu_present = apicid_to_cpu_present, + .setup_portio_remap = setup_portio_remap, + .check_phys_apicid_present = check_phys_apicid_present, + .enable_apic_mode = enable_apic_mode, + .phys_pkg_id = phys_pkg_id, + .mps_oem_check = mps_oem_check, + + .get_apic_id = get_apic_id, + .set_apic_id = NULL, + .apic_id_mask = APIC_ID_MASK, + + .cpu_mask_to_apicid = cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = cpu_mask_to_apicid_and, + + .send_IPI_mask = send_IPI_mask, + .send_IPI_mask_allbutself = NULL, + .send_IPI_allbutself = send_IPI_allbutself, + .send_IPI_all = send_IPI_all, + .send_IPI_self = NULL, + + .wakeup_cpu = NULL, + .trampoline_phys_low = TRAMPOLINE_PHYS_LOW, + .trampoline_phys_high = TRAMPOLINE_PHYS_HIGH, + .wait_for_init_deassert = wait_for_init_deassert, + .smp_callin_clear_local_apic = smp_callin_clear_local_apic, + .store_NMI_vector = store_NMI_vector, + .restore_NMI_vector = restore_NMI_vector, + .inquire_remote_apic = inquire_remote_apic, +}; -- GitLab From d26b6d6660d704ffa59f22ad57c9103e3fba289f Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 03:32:03 +0100 Subject: [PATCH 0529/4982] x86, genapic: cleanup 32-bit apic_bigsmp template Clean up the APIC driver template: - order fields properly - use the macro names explicitly (so that they can be renamed later) - fill in NULL entries as well Signed-off-by: Ingo Molnar --- arch/x86/mach-generic/bigsmp.c | 58 +++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index bc4c7840b2a..13e82bc4dae 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -57,4 +57,60 @@ static int probe_bigsmp(void) return dmi_bigsmp; } -struct genapic apic_bigsmp = APIC_INIT("bigsmp", probe_bigsmp); +struct genapic apic_bigsmp = { + + .name = "bigsmp", + .probe = probe_bigsmp, + .acpi_madt_oem_check = acpi_madt_oem_check, + .apic_id_registered = apic_id_registered, + + .int_delivery_mode = INT_DELIVERY_MODE, + .int_dest_mode = INT_DEST_MODE, + + .target_cpus = target_cpus, + .ESR_DISABLE = esr_disable, + .apic_destination_logical = APIC_DEST_LOGICAL, + .check_apicid_used = check_apicid_used, + .check_apicid_present = check_apicid_present, + + .no_balance_irq = NO_BALANCE_IRQ, + .no_ioapic_check = 0, + + .vector_allocation_domain = vector_allocation_domain, + .init_apic_ldr = init_apic_ldr, + + .ioapic_phys_id_map = ioapic_phys_id_map, + .setup_apic_routing = setup_apic_routing, + .multi_timer_check = multi_timer_check, + .apicid_to_node = apicid_to_node, + .cpu_to_logical_apicid = cpu_to_logical_apicid, + .cpu_present_to_apicid = cpu_present_to_apicid, + .apicid_to_cpu_present = apicid_to_cpu_present, + .setup_portio_remap = setup_portio_remap, + .check_phys_apicid_present = check_phys_apicid_present, + .enable_apic_mode = enable_apic_mode, + .phys_pkg_id = phys_pkg_id, + .mps_oem_check = mps_oem_check, + + .get_apic_id = get_apic_id, + .set_apic_id = NULL, + .apic_id_mask = APIC_ID_MASK, + + .cpu_mask_to_apicid = cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = cpu_mask_to_apicid_and, + + .send_IPI_mask = send_IPI_mask, + .send_IPI_mask_allbutself = NULL, + .send_IPI_allbutself = send_IPI_allbutself, + .send_IPI_all = send_IPI_all, + .send_IPI_self = NULL, + + .wakeup_cpu = NULL, + .trampoline_phys_low = TRAMPOLINE_PHYS_LOW, + .trampoline_phys_high = TRAMPOLINE_PHYS_HIGH, + .wait_for_init_deassert = wait_for_init_deassert, + .smp_callin_clear_local_apic = smp_callin_clear_local_apic, + .store_NMI_vector = store_NMI_vector, + .restore_NMI_vector = restore_NMI_vector, + .inquire_remote_apic = inquire_remote_apic, +}; -- GitLab From fea3437adf778cfe69b7f8cff0afb8060d84b647 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 03:32:03 +0100 Subject: [PATCH 0530/4982] x86, genapic: cleanup 32-bit apic_numaq template Clean up the APIC driver template: - order fields properly - use the macro names explicitly (so that they can be renamed later) - fill in NULL entries as well Signed-off-by: Ingo Molnar --- arch/x86/mach-generic/numaq.c | 58 ++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 3679e225564..fa486ca49c0 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -50,4 +50,60 @@ static void vector_allocation_domain(int cpu, cpumask_t *retmask) *retmask = (cpumask_t){ { [0] = APIC_ALL_CPUS, } }; } -struct genapic apic_numaq = APIC_INIT("NUMAQ", probe_numaq); +struct genapic apic_numaq = { + + .name = "NUMAQ", + .probe = probe_numaq, + .acpi_madt_oem_check = acpi_madt_oem_check, + .apic_id_registered = apic_id_registered, + + .int_delivery_mode = INT_DELIVERY_MODE, + .int_dest_mode = INT_DEST_MODE, + + .target_cpus = target_cpus, + .ESR_DISABLE = esr_disable, + .apic_destination_logical = APIC_DEST_LOGICAL, + .check_apicid_used = check_apicid_used, + .check_apicid_present = check_apicid_present, + + .no_balance_irq = NO_BALANCE_IRQ, + .no_ioapic_check = 0, + + .vector_allocation_domain = vector_allocation_domain, + .init_apic_ldr = init_apic_ldr, + + .ioapic_phys_id_map = ioapic_phys_id_map, + .setup_apic_routing = setup_apic_routing, + .multi_timer_check = multi_timer_check, + .apicid_to_node = apicid_to_node, + .cpu_to_logical_apicid = cpu_to_logical_apicid, + .cpu_present_to_apicid = cpu_present_to_apicid, + .apicid_to_cpu_present = apicid_to_cpu_present, + .setup_portio_remap = setup_portio_remap, + .check_phys_apicid_present = check_phys_apicid_present, + .enable_apic_mode = enable_apic_mode, + .phys_pkg_id = phys_pkg_id, + .mps_oem_check = mps_oem_check, + + .get_apic_id = get_apic_id, + .set_apic_id = NULL, + .apic_id_mask = APIC_ID_MASK, + + .cpu_mask_to_apicid = cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = cpu_mask_to_apicid_and, + + .send_IPI_mask = send_IPI_mask, + .send_IPI_mask_allbutself = NULL, + .send_IPI_allbutself = send_IPI_allbutself, + .send_IPI_all = send_IPI_all, + .send_IPI_self = NULL, + + .wakeup_cpu = NULL, + .trampoline_phys_low = TRAMPOLINE_PHYS_LOW, + .trampoline_phys_high = TRAMPOLINE_PHYS_HIGH, + .wait_for_init_deassert = wait_for_init_deassert, + .smp_callin_clear_local_apic = smp_callin_clear_local_apic, + .store_NMI_vector = store_NMI_vector, + .restore_NMI_vector = restore_NMI_vector, + .inquire_remote_apic = inquire_remote_apic, +}; -- GitLab From fed53ebf3c4e233e085c453a27ae287ccbf149fb Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 03:32:03 +0100 Subject: [PATCH 0531/4982] x86, genapic: cleanup 32-bit apic_es7000 template Clean up the APIC driver template: - order fields properly - use the macro names explicitly (so that they can be renamed later) - fill in NULL entries as well Signed-off-by: Ingo Molnar --- arch/x86/mach-generic/es7000.c | 58 +++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 2f4f4a6e39b..4a404ea5f92 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -100,4 +100,60 @@ static void vector_allocation_domain(int cpu, cpumask_t *retmask) *retmask = (cpumask_t){ { [0] = APIC_ALL_CPUS, } }; } -struct genapic __initdata_refok apic_es7000 = APIC_INIT("es7000", probe_es7000); +struct genapic apic_es7000 = { + + .name = "es7000", + .probe = probe_es7000, + .acpi_madt_oem_check = acpi_madt_oem_check, + .apic_id_registered = apic_id_registered, + + .int_delivery_mode = INT_DELIVERY_MODE, + .int_dest_mode = INT_DEST_MODE, + + .target_cpus = target_cpus, + .ESR_DISABLE = esr_disable, + .apic_destination_logical = APIC_DEST_LOGICAL, + .check_apicid_used = check_apicid_used, + .check_apicid_present = check_apicid_present, + + .no_balance_irq = NO_BALANCE_IRQ, + .no_ioapic_check = 0, + + .vector_allocation_domain = vector_allocation_domain, + .init_apic_ldr = init_apic_ldr, + + .ioapic_phys_id_map = ioapic_phys_id_map, + .setup_apic_routing = setup_apic_routing, + .multi_timer_check = multi_timer_check, + .apicid_to_node = apicid_to_node, + .cpu_to_logical_apicid = cpu_to_logical_apicid, + .cpu_present_to_apicid = cpu_present_to_apicid, + .apicid_to_cpu_present = apicid_to_cpu_present, + .setup_portio_remap = setup_portio_remap, + .check_phys_apicid_present = check_phys_apicid_present, + .enable_apic_mode = enable_apic_mode, + .phys_pkg_id = phys_pkg_id, + .mps_oem_check = mps_oem_check, + + .get_apic_id = get_apic_id, + .set_apic_id = NULL, + .apic_id_mask = APIC_ID_MASK, + + .cpu_mask_to_apicid = cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = cpu_mask_to_apicid_and, + + .send_IPI_mask = send_IPI_mask, + .send_IPI_mask_allbutself = NULL, + .send_IPI_allbutself = send_IPI_allbutself, + .send_IPI_all = send_IPI_all, + .send_IPI_self = NULL, + + .wakeup_cpu = NULL, + .trampoline_phys_low = TRAMPOLINE_PHYS_LOW, + .trampoline_phys_high = TRAMPOLINE_PHYS_HIGH, + .wait_for_init_deassert = wait_for_init_deassert, + .smp_callin_clear_local_apic = smp_callin_clear_local_apic, + .store_NMI_vector = store_NMI_vector, + .restore_NMI_vector = restore_NMI_vector, + .inquire_remote_apic = inquire_remote_apic, +}; -- GitLab From 491a50c4fbcf6cc39a702a16a2dfaf42f0eb8058 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 03:32:03 +0100 Subject: [PATCH 0532/4982] x86, genapic: cleanup 32-bit apic_summit template Clean up the APIC driver template: - order fields properly - use the macro names explicitly (so that they can be renamed later) - fill in NULL entries as well Signed-off-by: Ingo Molnar --- arch/x86/mach-generic/summit.c | 58 +++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 2821ffc188b..479c1d40977 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -37,4 +37,60 @@ static void vector_allocation_domain(int cpu, cpumask_t *retmask) *retmask = (cpumask_t){ { [0] = APIC_ALL_CPUS, } }; } -struct genapic apic_summit = APIC_INIT("summit", probe_summit); +struct genapic apic_summit = { + + .name = "summit", + .probe = probe_summit, + .acpi_madt_oem_check = acpi_madt_oem_check, + .apic_id_registered = apic_id_registered, + + .int_delivery_mode = INT_DELIVERY_MODE, + .int_dest_mode = INT_DEST_MODE, + + .target_cpus = target_cpus, + .ESR_DISABLE = esr_disable, + .apic_destination_logical = APIC_DEST_LOGICAL, + .check_apicid_used = check_apicid_used, + .check_apicid_present = check_apicid_present, + + .no_balance_irq = NO_BALANCE_IRQ, + .no_ioapic_check = 0, + + .vector_allocation_domain = vector_allocation_domain, + .init_apic_ldr = init_apic_ldr, + + .ioapic_phys_id_map = ioapic_phys_id_map, + .setup_apic_routing = setup_apic_routing, + .multi_timer_check = multi_timer_check, + .apicid_to_node = apicid_to_node, + .cpu_to_logical_apicid = cpu_to_logical_apicid, + .cpu_present_to_apicid = cpu_present_to_apicid, + .apicid_to_cpu_present = apicid_to_cpu_present, + .setup_portio_remap = setup_portio_remap, + .check_phys_apicid_present = check_phys_apicid_present, + .enable_apic_mode = enable_apic_mode, + .phys_pkg_id = phys_pkg_id, + .mps_oem_check = mps_oem_check, + + .get_apic_id = get_apic_id, + .set_apic_id = NULL, + .apic_id_mask = APIC_ID_MASK, + + .cpu_mask_to_apicid = cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = cpu_mask_to_apicid_and, + + .send_IPI_mask = send_IPI_mask, + .send_IPI_mask_allbutself = NULL, + .send_IPI_allbutself = send_IPI_allbutself, + .send_IPI_all = send_IPI_all, + .send_IPI_self = NULL, + + .wakeup_cpu = NULL, + .trampoline_phys_low = TRAMPOLINE_PHYS_LOW, + .trampoline_phys_high = TRAMPOLINE_PHYS_HIGH, + .wait_for_init_deassert = wait_for_init_deassert, + .smp_callin_clear_local_apic = smp_callin_clear_local_apic, + .store_NMI_vector = store_NMI_vector, + .restore_NMI_vector = restore_NMI_vector, + .inquire_remote_apic = inquire_remote_apic, +}; -- GitLab From 9a6801da55e4a4492e8f666ac272efe8186682c8 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 03:18:13 +0100 Subject: [PATCH 0533/4982] x86: remove APIC_INIT / APICFUNC / IPIFUNC The APIC_INIT() / APICFUNC / IPIFUNC macros were ugly and obfuscated the true identity of various APIC driver methods. Now that they are not used anymore, remove them. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/genapic.h | 63 ++-------------------------------- 1 file changed, 2 insertions(+), 61 deletions(-) diff --git a/arch/x86/include/asm/genapic.h b/arch/x86/include/asm/genapic.h index 3970da3245c..26c5e824a71 100644 --- a/arch/x86/include/asm/genapic.h +++ b/arch/x86/include/asm/genapic.h @@ -97,66 +97,8 @@ struct genapic { extern struct genapic *apic; #ifdef CONFIG_X86_32 - -#define APICFUNC(x) .x = x, - -/* More functions could be probably marked IPIFUNC and save some space - in UP GENERICARCH kernels, but I don't have the nerve right now - to untangle this mess. -AK */ -#ifdef CONFIG_SMP -#define IPIFUNC(x) APICFUNC(x) -#else -#define IPIFUNC(x) -#endif - -#define APIC_INIT(aname, aprobe) \ -{ \ - .name = aname, \ - .probe = aprobe, \ - .int_delivery_mode = INT_DELIVERY_MODE, \ - .int_dest_mode = INT_DEST_MODE, \ - .no_balance_irq = NO_BALANCE_IRQ, \ - .ESR_DISABLE = esr_disable, \ - .apic_destination_logical = APIC_DEST_LOGICAL, \ - APICFUNC(apic_id_registered) \ - APICFUNC(target_cpus) \ - APICFUNC(check_apicid_used) \ - APICFUNC(check_apicid_present) \ - APICFUNC(init_apic_ldr) \ - APICFUNC(ioapic_phys_id_map) \ - APICFUNC(setup_apic_routing) \ - APICFUNC(multi_timer_check) \ - APICFUNC(apicid_to_node) \ - APICFUNC(cpu_to_logical_apicid) \ - APICFUNC(cpu_present_to_apicid) \ - APICFUNC(apicid_to_cpu_present) \ - APICFUNC(setup_portio_remap) \ - APICFUNC(check_phys_apicid_present) \ - APICFUNC(mps_oem_check) \ - APICFUNC(get_apic_id) \ - .apic_id_mask = APIC_ID_MASK, \ - APICFUNC(cpu_mask_to_apicid) \ - APICFUNC(cpu_mask_to_apicid_and) \ - APICFUNC(vector_allocation_domain) \ - APICFUNC(acpi_madt_oem_check) \ - IPIFUNC(send_IPI_mask) \ - IPIFUNC(send_IPI_allbutself) \ - IPIFUNC(send_IPI_all) \ - APICFUNC(enable_apic_mode) \ - APICFUNC(phys_pkg_id) \ - .trampoline_phys_low = TRAMPOLINE_PHYS_LOW, \ - .trampoline_phys_high = TRAMPOLINE_PHYS_HIGH, \ - APICFUNC(wait_for_init_deassert) \ - APICFUNC(smp_callin_clear_local_apic) \ - APICFUNC(store_NMI_vector) \ - APICFUNC(restore_NMI_vector) \ - APICFUNC(inquire_remote_apic) \ -} - extern void es7000_update_genapic_to_cluster(void); - -#else /* CONFIG_X86_64: */ - +#else extern struct genapic apic_flat; extern struct genapic apic_physflat; extern struct genapic apic_x2apic_cluster; @@ -169,7 +111,6 @@ extern struct genapic apic_x2apic_uv_x; DECLARE_PER_CPU(int, x2apic_extra_bits); extern void setup_apic_routing(void); - -#endif /* CONFIG_X86_64 */ +#endif #endif /* _ASM_X86_GENAPIC_64_H */ -- GitLab From 306db03b0d71bf9c94155c0c4771a79fc70b4b27 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 03:43:47 +0100 Subject: [PATCH 0534/4982] x86: clean up apic->acpi_madt_oem_check methods Impact: refactor code x86 subarchitectures each defined a "acpi_madt_oem_check()" method, which could be an inline function, or an extern, or a static function, and which was also the name of a genapic field. Untangle this namespace spaghetti by setting ->acpi_madt_oem_check() to NULL on those subarchitectures that have no detection quirks, and rename the other ones (summit, es7000) that do. Also change default_acpi_madt_oem_check() to handle NULL entries, and clean its control flow up as well. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/es7000/mpparse.h | 2 +- arch/x86/include/asm/genapic.h | 2 +- .../include/asm/mach-default/mach_mpparse.h | 2 +- .../include/asm/mach-generic/mach_mpparse.h | 2 +- arch/x86/include/asm/summit/mpparse.h | 2 +- arch/x86/kernel/acpi/boot.c | 3 ++- arch/x86/kernel/genapic_64.c | 2 +- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 6 ++--- arch/x86/mach-generic/numaq.c | 8 +------ arch/x86/mach-generic/probe.c | 24 +++++++++++-------- arch/x86/mach-generic/summit.c | 2 +- 13 files changed, 29 insertions(+), 30 deletions(-) diff --git a/arch/x86/include/asm/es7000/mpparse.h b/arch/x86/include/asm/es7000/mpparse.h index c1629b090ec..30692c4ae85 100644 --- a/arch/x86/include/asm/es7000/mpparse.h +++ b/arch/x86/include/asm/es7000/mpparse.h @@ -9,7 +9,7 @@ extern void unmap_unisys_acpi_oem_table(unsigned long oem_addr); extern void setup_unisys(void); #ifndef CONFIG_X86_GENERICARCH -extern int acpi_madt_oem_check(char *oem_id, char *oem_table_id); +extern int default_acpi_madt_oem_check(char *oem_id, char *oem_table_id); extern int mps_oem_check(struct mpc_table *mpc, char *oem, char *productid); #endif diff --git a/arch/x86/include/asm/genapic.h b/arch/x86/include/asm/genapic.h index 26c5e824a71..108abdf6953 100644 --- a/arch/x86/include/asm/genapic.h +++ b/arch/x86/include/asm/genapic.h @@ -103,7 +103,7 @@ extern struct genapic apic_flat; extern struct genapic apic_physflat; extern struct genapic apic_x2apic_cluster; extern struct genapic apic_x2apic_phys; -extern int acpi_madt_oem_check(char *, char *); +extern int default_acpi_madt_oem_check(char *, char *); extern void apic_send_IPI_self(int vector); diff --git a/arch/x86/include/asm/mach-default/mach_mpparse.h b/arch/x86/include/asm/mach-default/mach_mpparse.h index c70a263d68c..8fa01770ba6 100644 --- a/arch/x86/include/asm/mach-default/mach_mpparse.h +++ b/arch/x86/include/asm/mach-default/mach_mpparse.h @@ -8,7 +8,7 @@ mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) } /* Hook from generic ACPI tables.c */ -static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) +static inline int default_acpi_madt_oem_check(char *oem_id, char *oem_table_id) { return 0; } diff --git a/arch/x86/include/asm/mach-generic/mach_mpparse.h b/arch/x86/include/asm/mach-generic/mach_mpparse.h index 9444ab8dca9..f497d96c76b 100644 --- a/arch/x86/include/asm/mach-generic/mach_mpparse.h +++ b/arch/x86/include/asm/mach-generic/mach_mpparse.h @@ -4,6 +4,6 @@ extern int mps_oem_check(struct mpc_table *, char *, char *); -extern int acpi_madt_oem_check(char *, char *); +extern int default_acpi_madt_oem_check(char *, char *); #endif /* _ASM_X86_MACH_GENERIC_MACH_MPPARSE_H */ diff --git a/arch/x86/include/asm/summit/mpparse.h b/arch/x86/include/asm/summit/mpparse.h index 380e86c0236..555ed8238e9 100644 --- a/arch/x86/include/asm/summit/mpparse.h +++ b/arch/x86/include/asm/summit/mpparse.h @@ -27,7 +27,7 @@ static inline int mps_oem_check(struct mpc_table *mpc, char *oem, } /* Hook from generic ACPI tables.c */ -static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) +static inline int summit_acpi_madt_oem_check(char *oem_id, char *oem_table_id) { if (!strncmp(oem_id, "IBM", 3) && (!strncmp(oem_table_id, "SERVIGIL", 8) diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 4cb5964f149..314fe0dddef 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -239,7 +239,8 @@ static int __init acpi_parse_madt(struct acpi_table_header *table) madt->address); } - acpi_madt_oem_check(madt->header.oem_id, madt->header.oem_table_id); + default_acpi_madt_oem_check(madt->header.oem_id, + madt->header.oem_table_id); return 0; } diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c index 2b986389a24..060945b8eec 100644 --- a/arch/x86/kernel/genapic_64.c +++ b/arch/x86/kernel/genapic_64.c @@ -68,7 +68,7 @@ void apic_send_IPI_self(int vector) __send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL); } -int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) +int __init default_acpi_madt_oem_check(char *oem_id, char *oem_table_id) { int i; diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 13e82bc4dae..22c3608b80d 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -61,7 +61,7 @@ struct genapic apic_bigsmp = { .name = "bigsmp", .probe = probe_bigsmp, - .acpi_madt_oem_check = acpi_madt_oem_check, + .acpi_madt_oem_check = NULL, .apic_id_registered = apic_id_registered, .int_delivery_mode = INT_DELIVERY_MODE, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index d5fec764fb4..cfec3494a96 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -28,7 +28,7 @@ struct genapic apic_default = { .name = "default", .probe = probe_default, - .acpi_madt_oem_check = acpi_madt_oem_check, + .acpi_madt_oem_check = NULL, .apic_id_registered = apic_id_registered, .int_delivery_mode = INT_DELIVERY_MODE, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 4a404ea5f92..23fe6f1c969 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -57,7 +57,7 @@ mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) #ifdef CONFIG_ACPI /* Hook from generic ACPI tables.c */ -static int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) +static int __init es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id) { unsigned long oem_addr = 0; int check_dsdt; @@ -81,7 +81,7 @@ static int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) return ret; } #else -static int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) +static int __init es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id) { return 0; } @@ -104,7 +104,7 @@ struct genapic apic_es7000 = { .name = "es7000", .probe = probe_es7000, - .acpi_madt_oem_check = acpi_madt_oem_check, + .acpi_madt_oem_check = es7000_acpi_madt_oem_check, .apic_id_registered = apic_id_registered, .int_delivery_mode = INT_DELIVERY_MODE, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index fa486ca49c0..9691b4e1654 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -31,12 +31,6 @@ static int probe_numaq(void) return found_numaq; } -/* Hook from generic ACPI tables.c */ -static int acpi_madt_oem_check(char *oem_id, char *oem_table_id) -{ - return 0; -} - static void vector_allocation_domain(int cpu, cpumask_t *retmask) { /* Careful. Some cpus do not strictly honor the set of cpus @@ -54,7 +48,7 @@ struct genapic apic_numaq = { .name = "NUMAQ", .probe = probe_numaq, - .acpi_madt_oem_check = acpi_madt_oem_check, + .acpi_madt_oem_check = NULL, .apic_id_registered = apic_id_registered, .int_delivery_mode = INT_DELIVERY_MODE, diff --git a/arch/x86/mach-generic/probe.c b/arch/x86/mach-generic/probe.c index 82bf0f520fb..a21e2b1a701 100644 --- a/arch/x86/mach-generic/probe.c +++ b/arch/x86/mach-generic/probe.c @@ -128,20 +128,24 @@ int __init mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) return 0; } -int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) +int __init default_acpi_madt_oem_check(char *oem_id, char *oem_table_id) { int i; + for (i = 0; apic_probe[i]; ++i) { - if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) { - if (!cmdline_apic) { - apic = apic_probe[i]; - if (x86_quirks->update_genapic) - x86_quirks->update_genapic(); - printk(KERN_INFO "Switched to APIC driver `%s'.\n", - apic->name); - } - return 1; + if (!apic_probe[i]->acpi_madt_oem_check) + continue; + if (!apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) + continue; + + if (!cmdline_apic) { + apic = apic_probe[i]; + if (x86_quirks->update_genapic) + x86_quirks->update_genapic(); + printk(KERN_INFO "Switched to APIC driver `%s'.\n", + apic->name); } + return 1; } return 0; } diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 479c1d40977..0eea9fbb2a5 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -41,7 +41,7 @@ struct genapic apic_summit = { .name = "summit", .probe = probe_summit, - .acpi_madt_oem_check = acpi_madt_oem_check, + .acpi_madt_oem_check = summit_acpi_madt_oem_check, .apic_id_registered = apic_id_registered, .int_delivery_mode = INT_DELIVERY_MODE, -- GitLab From 7ed248daa56156f2fd7175f90b62fc6397b0c7b7 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 03:43:47 +0100 Subject: [PATCH 0535/4982] x86: clean up apic->apic_id_registered() methods Impact: cleanup x86 subarchitectures each defined a "apic_id_registered()" method, which could be an inline function depending on which subarch we build for, and which was also the name of a genapic field. Untangle this namespace spaghetti by giving each of the instances a separate name. Also remove wrapper macro obfuscation. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 4 ++-- arch/x86/include/asm/es7000/apic.h | 4 ++-- arch/x86/include/asm/mach-default/mach_apic.h | 3 +-- arch/x86/include/asm/mach-generic/mach_apic.h | 1 - arch/x86/include/asm/numaq/apic.h | 2 +- arch/x86/include/asm/summit/apic.h | 2 +- arch/x86/kernel/apic.c | 2 +- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 2 +- arch/x86/mach-generic/numaq.c | 2 +- arch/x86/mach-generic/summit.c | 2 +- 12 files changed, 13 insertions(+), 15 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index d8dd9f53791..42c56df3ff3 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h @@ -4,9 +4,9 @@ #define xapic_phys_to_log_apicid(cpu) (per_cpu(x86_bios_cpu_apicid, cpu)) #define esr_disable (1) -static inline int apic_id_registered(void) +static inline int bigsmp_apic_id_registered(void) { - return (1); + return 1; } static inline const cpumask_t *target_cpus(void) diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index c58b9cc7446..a1819b510de 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -6,9 +6,9 @@ #define xapic_phys_to_log_apicid(cpu) per_cpu(x86_bios_cpu_apicid, cpu) #define esr_disable (1) -static inline int apic_id_registered(void) +static inline int es7000_apic_id_registered(void) { - return (1); + return 1; } static inline const cpumask_t *target_cpus_cluster(void) diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index 2448b927b64..6a454fa0b43 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -25,7 +25,6 @@ static inline const struct cpumask *target_cpus(void) #define INT_DELIVERY_MODE (apic->int_delivery_mode) #define INT_DEST_MODE (apic->int_dest_mode) #define TARGET_CPUS (apic->target_cpus()) -#define apic_id_registered (apic->apic_id_registered) #define init_apic_ldr (apic->init_apic_ldr) #define cpu_mask_to_apicid (apic->cpu_mask_to_apicid) #define cpu_mask_to_apicid_and (apic->cpu_mask_to_apicid_and) @@ -57,7 +56,7 @@ static inline void init_apic_ldr(void) apic_write(APIC_LDR, val); } -static inline int apic_id_registered(void) +static inline int default_apic_id_registered(void) { return physid_isset(read_apic_id(), phys_cpu_present_map); } diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index 59972d94ff1..cc6e9d70f06 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -10,7 +10,6 @@ #undef APIC_DEST_LOGICAL #define APIC_DEST_LOGICAL (apic->apic_destination_logical) #define TARGET_CPUS (apic->target_cpus()) -#define apic_id_registered (apic->apic_id_registered) #define init_apic_ldr (apic->init_apic_ldr) #define ioapic_phys_id_map (apic->ioapic_phys_id_map) #define setup_apic_routing (apic->setup_apic_routing) diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h index bf37bc49bd8..59b62b19d02 100644 --- a/arch/x86/include/asm/numaq/apic.h +++ b/arch/x86/include/asm/numaq/apic.h @@ -28,7 +28,7 @@ static inline unsigned long check_apicid_present(int bit) } #define apicid_cluster(apicid) (apicid & 0xF0) -static inline int apic_id_registered(void) +static inline int numaq_apic_id_registered(void) { return 1; } diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index 93d2c8667cf..a36ef6e4b1f 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h @@ -74,7 +74,7 @@ static inline int multi_timer_check(int apic, int irq) return 0; } -static inline int apic_id_registered(void) +static inline int summit_apic_id_registered(void) { return 1; } diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index c6f15647eba..b6740de18fb 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -1171,7 +1171,7 @@ void __cpuinit setup_local_APIC(void) * Double-check whether this APIC is really registered. * This is meaningless in clustered apic mode, so we skip it. */ - if (!apic_id_registered()) + if (!apic->apic_id_registered()) BUG(); /* diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 22c3608b80d..17abf5c6242 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -62,7 +62,7 @@ struct genapic apic_bigsmp = { .name = "bigsmp", .probe = probe_bigsmp, .acpi_madt_oem_check = NULL, - .apic_id_registered = apic_id_registered, + .apic_id_registered = bigsmp_apic_id_registered, .int_delivery_mode = INT_DELIVERY_MODE, .int_dest_mode = INT_DEST_MODE, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index cfec3494a96..1f30559e9d8 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -29,7 +29,7 @@ struct genapic apic_default = { .name = "default", .probe = probe_default, .acpi_madt_oem_check = NULL, - .apic_id_registered = apic_id_registered, + .apic_id_registered = default_apic_id_registered, .int_delivery_mode = INT_DELIVERY_MODE, .int_dest_mode = INT_DEST_MODE, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 23fe6f1c969..d68ca0bce67 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -105,7 +105,7 @@ struct genapic apic_es7000 = { .name = "es7000", .probe = probe_es7000, .acpi_madt_oem_check = es7000_acpi_madt_oem_check, - .apic_id_registered = apic_id_registered, + .apic_id_registered = es7000_apic_id_registered, .int_delivery_mode = INT_DELIVERY_MODE, .int_dest_mode = INT_DEST_MODE, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 9691b4e1654..b22a79b15b1 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -49,7 +49,7 @@ struct genapic apic_numaq = { .name = "NUMAQ", .probe = probe_numaq, .acpi_madt_oem_check = NULL, - .apic_id_registered = apic_id_registered, + .apic_id_registered = numaq_apic_id_registered, .int_delivery_mode = INT_DELIVERY_MODE, .int_dest_mode = INT_DEST_MODE, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 0eea9fbb2a5..744fa1b86ef 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -42,7 +42,7 @@ struct genapic apic_summit = { .name = "summit", .probe = probe_summit, .acpi_madt_oem_check = summit_acpi_madt_oem_check, - .apic_id_registered = apic_id_registered, + .apic_id_registered = summit_apic_id_registered, .int_delivery_mode = INT_DELIVERY_MODE, .int_dest_mode = INT_DEST_MODE, -- GitLab From f8987a1093cc7a896137e264c24e04d4048e9f95 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 04:02:31 +0100 Subject: [PATCH 0536/4982] x86, genapic: rename int_delivery_mode, et. al. int_delivery_mode is supposed to mean 'interrupt delivery mode', but it's quite a misnomer as 'int' we usually think of as an integer type ... The standard naming for such attributes is 'irq' - so rename the following fields and macros: int_delivery_mode => irq_delivery_mode INT_DELIVERY_MODE => IRQ_DELIVERY_MODE int_dest_mode => irq_dest_mode INT_DEST_MODE => IRQ_DEST_MODE Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 4 +-- arch/x86/include/asm/es7000/apic.h | 4 +-- arch/x86/include/asm/genapic.h | 4 +-- arch/x86/include/asm/mach-default/mach_apic.h | 8 ++--- arch/x86/include/asm/mach-generic/mach_apic.h | 4 +-- arch/x86/include/asm/numaq/apic.h | 4 +-- arch/x86/include/asm/summit/apic.h | 4 +-- arch/x86/kernel/genapic_flat_64.c | 8 ++--- arch/x86/kernel/genx2apic_cluster.c | 4 +-- arch/x86/kernel/genx2apic_phys.c | 4 +-- arch/x86/kernel/genx2apic_uv_x.c | 4 +-- arch/x86/kernel/io_apic.c | 30 +++++++++---------- arch/x86/mach-generic/bigsmp.c | 4 +-- arch/x86/mach-generic/default.c | 4 +-- arch/x86/mach-generic/es7000.c | 8 ++--- arch/x86/mach-generic/numaq.c | 4 +-- arch/x86/mach-generic/summit.c | 4 +-- 17 files changed, 53 insertions(+), 53 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index 42c56df3ff3..8ff8bba8833 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h @@ -21,8 +21,8 @@ static inline const cpumask_t *target_cpus(void) #undef APIC_DEST_LOGICAL #define APIC_DEST_LOGICAL 0 #define APIC_DFR_VALUE (APIC_DFR_FLAT) -#define INT_DELIVERY_MODE (dest_Fixed) -#define INT_DEST_MODE (0) /* phys delivery to target proc */ +#define IRQ_DELIVERY_MODE (dest_Fixed) +#define IRQ_DEST_MODE (0) /* phys delivery to target proc */ #define NO_BALANCE_IRQ (0) static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index a1819b510de..830e8731cc0 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -27,8 +27,8 @@ static inline const cpumask_t *target_cpus(void) #define NO_BALANCE_IRQ_CLUSTER (1) #define APIC_DFR_VALUE (APIC_DFR_FLAT) -#define INT_DELIVERY_MODE (dest_Fixed) -#define INT_DEST_MODE (0) /* phys delivery to target procs */ +#define IRQ_DELIVERY_MODE (dest_Fixed) +#define IRQ_DEST_MODE (0) /* phys delivery to target procs */ #define NO_BALANCE_IRQ (0) #undef APIC_DEST_LOGICAL #define APIC_DEST_LOGICAL 0x0 diff --git a/arch/x86/include/asm/genapic.h b/arch/x86/include/asm/genapic.h index 108abdf6953..e998e3df5d2 100644 --- a/arch/x86/include/asm/genapic.h +++ b/arch/x86/include/asm/genapic.h @@ -23,8 +23,8 @@ struct genapic { int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id); int (*apic_id_registered)(void); - u32 int_delivery_mode; - u32 int_dest_mode; + u32 irq_delivery_mode; + u32 irq_dest_mode; const struct cpumask *(*target_cpus)(void); diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index 6a454fa0b43..b5364793262 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -22,8 +22,8 @@ static inline const struct cpumask *target_cpus(void) #ifdef CONFIG_X86_64 #include -#define INT_DELIVERY_MODE (apic->int_delivery_mode) -#define INT_DEST_MODE (apic->int_dest_mode) +#define IRQ_DELIVERY_MODE (apic->irq_delivery_mode) +#define IRQ_DEST_MODE (apic->irq_dest_mode) #define TARGET_CPUS (apic->target_cpus()) #define init_apic_ldr (apic->init_apic_ldr) #define cpu_mask_to_apicid (apic->cpu_mask_to_apicid) @@ -35,8 +35,8 @@ static inline const struct cpumask *target_cpus(void) #define wakeup_secondary_cpu (apic->wakeup_cpu) extern void setup_apic_routing(void); #else -#define INT_DELIVERY_MODE dest_LowestPrio -#define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */ +#define IRQ_DELIVERY_MODE dest_LowestPrio +#define IRQ_DEST_MODE 1 /* logical delivery broadcast to all procs */ #define TARGET_CPUS (target_cpus()) #define wakeup_secondary_cpu wakeup_secondary_cpu_via_init /* diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index cc6e9d70f06..03492f2219e 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -5,8 +5,8 @@ #define esr_disable (apic->ESR_DISABLE) #define NO_BALANCE_IRQ (apic->no_balance_irq) -#define INT_DELIVERY_MODE (apic->int_delivery_mode) -#define INT_DEST_MODE (apic->int_dest_mode) +#define IRQ_DELIVERY_MODE (apic->irq_delivery_mode) +#define IRQ_DEST_MODE (apic->irq_dest_mode) #undef APIC_DEST_LOGICAL #define APIC_DEST_LOGICAL (apic->apic_destination_logical) #define TARGET_CPUS (apic->target_cpus()) diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h index 59b62b19d02..d885e35df18 100644 --- a/arch/x86/include/asm/numaq/apic.h +++ b/arch/x86/include/asm/numaq/apic.h @@ -15,8 +15,8 @@ static inline const cpumask_t *target_cpus(void) #define NO_BALANCE_IRQ (1) #define esr_disable (1) -#define INT_DELIVERY_MODE dest_LowestPrio -#define INT_DEST_MODE 0 /* physical delivery on LOCAL quad */ +#define IRQ_DELIVERY_MODE dest_LowestPrio +#define IRQ_DEST_MODE 0 /* physical delivery on LOCAL quad */ static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) { diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index a36ef6e4b1f..0b7d0d14e56 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h @@ -24,8 +24,8 @@ static inline const cpumask_t *target_cpus(void) return &cpumask_of_cpu(0); } -#define INT_DELIVERY_MODE (dest_LowestPrio) -#define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */ +#define IRQ_DELIVERY_MODE (dest_LowestPrio) +#define IRQ_DEST_MODE 1 /* logical delivery broadcast to all procs */ static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) { diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index e9233374cef..0a263d6bb5e 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -180,8 +180,8 @@ struct genapic apic_flat = { .acpi_madt_oem_check = flat_acpi_madt_oem_check, .apic_id_registered = flat_apic_id_registered, - .int_delivery_mode = dest_LowestPrio, - .int_dest_mode = (APIC_DEST_LOGICAL != 0), + .irq_delivery_mode = dest_LowestPrio, + .irq_dest_mode = (APIC_DEST_LOGICAL != 0), .target_cpus = flat_target_cpus, .ESR_DISABLE = 0, @@ -326,8 +326,8 @@ struct genapic apic_physflat = { .acpi_madt_oem_check = physflat_acpi_madt_oem_check, .apic_id_registered = flat_apic_id_registered, - .int_delivery_mode = dest_Fixed, - .int_dest_mode = (APIC_DEST_PHYSICAL != 0), + .irq_delivery_mode = dest_Fixed, + .irq_dest_mode = (APIC_DEST_PHYSICAL != 0), .target_cpus = physflat_target_cpus, .ESR_DISABLE = 0, diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c index fc855e503ac..e9ff7dc9a0f 100644 --- a/arch/x86/kernel/genx2apic_cluster.c +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -182,8 +182,8 @@ struct genapic apic_x2apic_cluster = { .acpi_madt_oem_check = x2apic_acpi_madt_oem_check, .apic_id_registered = x2apic_apic_id_registered, - .int_delivery_mode = dest_LowestPrio, - .int_dest_mode = (APIC_DEST_LOGICAL != 0), + .irq_delivery_mode = dest_LowestPrio, + .irq_dest_mode = (APIC_DEST_LOGICAL != 0), .target_cpus = x2apic_target_cpus, .ESR_DISABLE = 0, diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c index c98361fb7ee..8141b5a88f6 100644 --- a/arch/x86/kernel/genx2apic_phys.c +++ b/arch/x86/kernel/genx2apic_phys.c @@ -178,8 +178,8 @@ struct genapic apic_x2apic_phys = { .acpi_madt_oem_check = x2apic_acpi_madt_oem_check, .apic_id_registered = x2apic_apic_id_registered, - .int_delivery_mode = dest_Fixed, - .int_dest_mode = (APIC_DEST_PHYSICAL != 0), + .irq_delivery_mode = dest_Fixed, + .irq_dest_mode = (APIC_DEST_PHYSICAL != 0), .target_cpus = x2apic_target_cpus, .ESR_DISABLE = 0, diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index 94f606f204a..6a73cad0d3e 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -243,8 +243,8 @@ struct genapic apic_x2apic_uv_x = { .acpi_madt_oem_check = uv_acpi_madt_oem_check, .apic_id_registered = uv_apic_id_registered, - .int_delivery_mode = dest_Fixed, - .int_dest_mode = (APIC_DEST_PHYSICAL != 0), + .irq_delivery_mode = dest_Fixed, + .irq_dest_mode = (APIC_DEST_PHYSICAL != 0), .target_cpus = uv_target_cpus, .ESR_DISABLE = 0, diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 7283234229f..5f967b9c9af 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -1514,9 +1514,9 @@ static int setup_ioapic_entry(int apic_id, int irq, memset(&irte, 0, sizeof(irte)); irte.present = 1; - irte.dst_mode = INT_DEST_MODE; + irte.dst_mode = IRQ_DEST_MODE; irte.trigger_mode = trigger; - irte.dlvry_mode = INT_DELIVERY_MODE; + irte.dlvry_mode = IRQ_DELIVERY_MODE; irte.vector = vector; irte.dest_id = IRTE_DEST(destination); @@ -1529,8 +1529,8 @@ static int setup_ioapic_entry(int apic_id, int irq, } else #endif { - entry->delivery_mode = INT_DELIVERY_MODE; - entry->dest_mode = INT_DEST_MODE; + entry->delivery_mode = IRQ_DELIVERY_MODE; + entry->dest_mode = IRQ_DEST_MODE; entry->dest = destination; } @@ -1659,10 +1659,10 @@ static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin, * We use logical delivery to get the timer IRQ * to the first CPU. */ - entry.dest_mode = INT_DEST_MODE; + entry.dest_mode = IRQ_DEST_MODE; entry.mask = 1; /* mask IRQ now */ entry.dest = cpu_mask_to_apicid(TARGET_CPUS); - entry.delivery_mode = INT_DELIVERY_MODE; + entry.delivery_mode = IRQ_DELIVERY_MODE; entry.polarity = 0; entry.trigger = 0; entry.vector = vector; @@ -3279,9 +3279,9 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms memset (&irte, 0, sizeof(irte)); irte.present = 1; - irte.dst_mode = INT_DEST_MODE; + irte.dst_mode = IRQ_DEST_MODE; irte.trigger_mode = 0; /* edge */ - irte.dlvry_mode = INT_DELIVERY_MODE; + irte.dlvry_mode = IRQ_DELIVERY_MODE; irte.vector = cfg->vector; irte.dest_id = IRTE_DEST(dest); @@ -3299,10 +3299,10 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms msg->address_hi = MSI_ADDR_BASE_HI; msg->address_lo = MSI_ADDR_BASE_LO | - ((INT_DEST_MODE == 0) ? + ((IRQ_DEST_MODE == 0) ? MSI_ADDR_DEST_MODE_PHYSICAL: MSI_ADDR_DEST_MODE_LOGICAL) | - ((INT_DELIVERY_MODE != dest_LowestPrio) ? + ((IRQ_DELIVERY_MODE != dest_LowestPrio) ? MSI_ADDR_REDIRECTION_CPU: MSI_ADDR_REDIRECTION_LOWPRI) | MSI_ADDR_DEST_ID(dest); @@ -3310,7 +3310,7 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms msg->data = MSI_DATA_TRIGGER_EDGE | MSI_DATA_LEVEL_ASSERT | - ((INT_DELIVERY_MODE != dest_LowestPrio) ? + ((IRQ_DELIVERY_MODE != dest_LowestPrio) ? MSI_DATA_DELIVERY_FIXED: MSI_DATA_DELIVERY_LOWPRI) | MSI_DATA_VECTOR(cfg->vector); @@ -3711,11 +3711,11 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) HT_IRQ_LOW_BASE | HT_IRQ_LOW_DEST_ID(dest) | HT_IRQ_LOW_VECTOR(cfg->vector) | - ((INT_DEST_MODE == 0) ? + ((IRQ_DEST_MODE == 0) ? HT_IRQ_LOW_DM_PHYSICAL : HT_IRQ_LOW_DM_LOGICAL) | HT_IRQ_LOW_RQEOI_EDGE | - ((INT_DELIVERY_MODE != dest_LowestPrio) ? + ((IRQ_DELIVERY_MODE != dest_LowestPrio) ? HT_IRQ_LOW_MT_FIXED : HT_IRQ_LOW_MT_ARBITRATED) | HT_IRQ_LOW_IRQ_MASKED; @@ -3763,8 +3763,8 @@ int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade, BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long)); entry->vector = cfg->vector; - entry->delivery_mode = INT_DELIVERY_MODE; - entry->dest_mode = INT_DEST_MODE; + entry->delivery_mode = IRQ_DELIVERY_MODE; + entry->dest_mode = IRQ_DEST_MODE; entry->polarity = 0; entry->trigger = 0; entry->mask = 0; diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 17abf5c6242..c15c1aa2dc7 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -64,8 +64,8 @@ struct genapic apic_bigsmp = { .acpi_madt_oem_check = NULL, .apic_id_registered = bigsmp_apic_id_registered, - .int_delivery_mode = INT_DELIVERY_MODE, - .int_dest_mode = INT_DEST_MODE, + .irq_delivery_mode = IRQ_DELIVERY_MODE, + .irq_dest_mode = IRQ_DEST_MODE, .target_cpus = target_cpus, .ESR_DISABLE = esr_disable, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index 1f30559e9d8..d32b175eff8 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -31,8 +31,8 @@ struct genapic apic_default = { .acpi_madt_oem_check = NULL, .apic_id_registered = default_apic_id_registered, - .int_delivery_mode = INT_DELIVERY_MODE, - .int_dest_mode = INT_DEST_MODE, + .irq_delivery_mode = IRQ_DELIVERY_MODE, + .irq_dest_mode = IRQ_DEST_MODE, .target_cpus = target_cpus, .ESR_DISABLE = esr_disable, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index d68ca0bce67..06653892953 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -21,8 +21,8 @@ void __init es7000_update_genapic_to_cluster(void) { apic->target_cpus = target_cpus_cluster; - apic->int_delivery_mode = INT_DELIVERY_MODE_CLUSTER; - apic->int_dest_mode = INT_DEST_MODE_CLUSTER; + apic->irq_delivery_mode = INT_DELIVERY_MODE_CLUSTER; + apic->irq_dest_mode = INT_DEST_MODE_CLUSTER; apic->no_balance_irq = NO_BALANCE_IRQ_CLUSTER; apic->init_apic_ldr = init_apic_ldr_cluster; @@ -107,8 +107,8 @@ struct genapic apic_es7000 = { .acpi_madt_oem_check = es7000_acpi_madt_oem_check, .apic_id_registered = es7000_apic_id_registered, - .int_delivery_mode = INT_DELIVERY_MODE, - .int_dest_mode = INT_DEST_MODE, + .irq_delivery_mode = IRQ_DELIVERY_MODE, + .irq_dest_mode = IRQ_DEST_MODE, .target_cpus = target_cpus, .ESR_DISABLE = esr_disable, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index b22a79b15b1..401957142fd 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -51,8 +51,8 @@ struct genapic apic_numaq = { .acpi_madt_oem_check = NULL, .apic_id_registered = numaq_apic_id_registered, - .int_delivery_mode = INT_DELIVERY_MODE, - .int_dest_mode = INT_DEST_MODE, + .irq_delivery_mode = IRQ_DELIVERY_MODE, + .irq_dest_mode = IRQ_DEST_MODE, .target_cpus = target_cpus, .ESR_DISABLE = esr_disable, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 744fa1b86ef..946da7aa762 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -44,8 +44,8 @@ struct genapic apic_summit = { .acpi_madt_oem_check = summit_acpi_madt_oem_check, .apic_id_registered = summit_apic_id_registered, - .int_delivery_mode = INT_DELIVERY_MODE, - .int_dest_mode = INT_DEST_MODE, + .irq_delivery_mode = IRQ_DELIVERY_MODE, + .irq_dest_mode = IRQ_DEST_MODE, .target_cpus = target_cpus, .ESR_DISABLE = esr_disable, -- GitLab From 9b5bc8dc12421a4b17047061f473d85c1797d543 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 04:09:58 +0100 Subject: [PATCH 0537/4982] x86, apic: remove IRQ_DEST_MODE / IRQ_DELIVERY_MODE Remove the wrapper macros IRQ_DEST_MODE and IRQ_DELIVERY_MODE. The typical 32-bit and the 64-bit build all dereference via the genapic, so it's pointless to hide that indirection via these ugly macros. Furthermore, it also obscures subarchitecture details. So replace it with apic->irq_dest_mode / etc. accesses. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 4 +-- arch/x86/include/asm/es7000/apic.h | 4 +-- arch/x86/include/asm/mach-default/mach_apic.h | 5 ++-- arch/x86/include/asm/mach-generic/mach_apic.h | 2 -- arch/x86/include/asm/numaq/apic.h | 4 +-- arch/x86/include/asm/summit/apic.h | 4 +-- arch/x86/kernel/io_apic.c | 30 +++++++++---------- arch/x86/mach-generic/bigsmp.c | 4 +-- arch/x86/mach-generic/default.c | 4 +-- arch/x86/mach-generic/es7000.c | 4 +-- arch/x86/mach-generic/numaq.c | 4 +-- arch/x86/mach-generic/summit.c | 4 +-- 12 files changed, 35 insertions(+), 38 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index 8ff8bba8833..293551b0e61 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h @@ -21,8 +21,8 @@ static inline const cpumask_t *target_cpus(void) #undef APIC_DEST_LOGICAL #define APIC_DEST_LOGICAL 0 #define APIC_DFR_VALUE (APIC_DFR_FLAT) -#define IRQ_DELIVERY_MODE (dest_Fixed) -#define IRQ_DEST_MODE (0) /* phys delivery to target proc */ +#define BIGSMP_IRQ_DELIVERY_MODE (dest_Fixed) +#define BIGSMP_IRQ_DEST_MODE (0) /* phys delivery to target proc */ #define NO_BALANCE_IRQ (0) static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index 830e8731cc0..690016683f2 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -27,8 +27,8 @@ static inline const cpumask_t *target_cpus(void) #define NO_BALANCE_IRQ_CLUSTER (1) #define APIC_DFR_VALUE (APIC_DFR_FLAT) -#define IRQ_DELIVERY_MODE (dest_Fixed) -#define IRQ_DEST_MODE (0) /* phys delivery to target procs */ +#define ES7000_IRQ_DELIVERY_MODE (dest_Fixed) +#define ES7000_IRQ_DEST_MODE (0) /* phys delivery to target procs */ #define NO_BALANCE_IRQ (0) #undef APIC_DEST_LOGICAL #define APIC_DEST_LOGICAL 0x0 diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index b5364793262..eafbf4f2038 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -22,7 +22,6 @@ static inline const struct cpumask *target_cpus(void) #ifdef CONFIG_X86_64 #include -#define IRQ_DELIVERY_MODE (apic->irq_delivery_mode) #define IRQ_DEST_MODE (apic->irq_dest_mode) #define TARGET_CPUS (apic->target_cpus()) #define init_apic_ldr (apic->init_apic_ldr) @@ -35,8 +34,8 @@ static inline const struct cpumask *target_cpus(void) #define wakeup_secondary_cpu (apic->wakeup_cpu) extern void setup_apic_routing(void); #else -#define IRQ_DELIVERY_MODE dest_LowestPrio -#define IRQ_DEST_MODE 1 /* logical delivery broadcast to all procs */ +#define DEFAULT_IRQ_DELIVERY_MODE dest_LowestPrio +#define DEFAULT_IRQ_DEST_MODE 1 /* logical delivery broadcast to all procs */ #define TARGET_CPUS (target_cpus()) #define wakeup_secondary_cpu wakeup_secondary_cpu_via_init /* diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index 03492f2219e..387a5d00c43 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -5,8 +5,6 @@ #define esr_disable (apic->ESR_DISABLE) #define NO_BALANCE_IRQ (apic->no_balance_irq) -#define IRQ_DELIVERY_MODE (apic->irq_delivery_mode) -#define IRQ_DEST_MODE (apic->irq_dest_mode) #undef APIC_DEST_LOGICAL #define APIC_DEST_LOGICAL (apic->apic_destination_logical) #define TARGET_CPUS (apic->target_cpus()) diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h index d885e35df18..7746035c591 100644 --- a/arch/x86/include/asm/numaq/apic.h +++ b/arch/x86/include/asm/numaq/apic.h @@ -15,8 +15,8 @@ static inline const cpumask_t *target_cpus(void) #define NO_BALANCE_IRQ (1) #define esr_disable (1) -#define IRQ_DELIVERY_MODE dest_LowestPrio -#define IRQ_DEST_MODE 0 /* physical delivery on LOCAL quad */ +#define NUMAQ_IRQ_DELIVERY_MODE dest_LowestPrio +#define NUMAQ_IRQ_DEST_MODE 0 /* physical delivery on LOCAL quad */ static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) { diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index 0b7d0d14e56..ea2abe9b597 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h @@ -24,8 +24,8 @@ static inline const cpumask_t *target_cpus(void) return &cpumask_of_cpu(0); } -#define IRQ_DELIVERY_MODE (dest_LowestPrio) -#define IRQ_DEST_MODE 1 /* logical delivery broadcast to all procs */ +#define SUMMIT_IRQ_DELIVERY_MODE (dest_LowestPrio) +#define SUMMIT_IRQ_DEST_MODE 1 /* logical delivery broadcast to all procs */ static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) { diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 5f967b9c9af..301b6571d70 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -1514,9 +1514,9 @@ static int setup_ioapic_entry(int apic_id, int irq, memset(&irte, 0, sizeof(irte)); irte.present = 1; - irte.dst_mode = IRQ_DEST_MODE; + irte.dst_mode = apic->irq_dest_mode; irte.trigger_mode = trigger; - irte.dlvry_mode = IRQ_DELIVERY_MODE; + irte.dlvry_mode = apic->irq_delivery_mode; irte.vector = vector; irte.dest_id = IRTE_DEST(destination); @@ -1529,8 +1529,8 @@ static int setup_ioapic_entry(int apic_id, int irq, } else #endif { - entry->delivery_mode = IRQ_DELIVERY_MODE; - entry->dest_mode = IRQ_DEST_MODE; + entry->delivery_mode = apic->irq_delivery_mode; + entry->dest_mode = apic->irq_dest_mode; entry->dest = destination; } @@ -1659,10 +1659,10 @@ static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin, * We use logical delivery to get the timer IRQ * to the first CPU. */ - entry.dest_mode = IRQ_DEST_MODE; + entry.dest_mode = apic->irq_dest_mode; entry.mask = 1; /* mask IRQ now */ entry.dest = cpu_mask_to_apicid(TARGET_CPUS); - entry.delivery_mode = IRQ_DELIVERY_MODE; + entry.delivery_mode = apic->irq_delivery_mode; entry.polarity = 0; entry.trigger = 0; entry.vector = vector; @@ -3279,9 +3279,9 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms memset (&irte, 0, sizeof(irte)); irte.present = 1; - irte.dst_mode = IRQ_DEST_MODE; + irte.dst_mode = apic->irq_dest_mode; irte.trigger_mode = 0; /* edge */ - irte.dlvry_mode = IRQ_DELIVERY_MODE; + irte.dlvry_mode = apic->irq_delivery_mode; irte.vector = cfg->vector; irte.dest_id = IRTE_DEST(dest); @@ -3299,10 +3299,10 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms msg->address_hi = MSI_ADDR_BASE_HI; msg->address_lo = MSI_ADDR_BASE_LO | - ((IRQ_DEST_MODE == 0) ? + ((apic->irq_dest_mode == 0) ? MSI_ADDR_DEST_MODE_PHYSICAL: MSI_ADDR_DEST_MODE_LOGICAL) | - ((IRQ_DELIVERY_MODE != dest_LowestPrio) ? + ((apic->irq_delivery_mode != dest_LowestPrio) ? MSI_ADDR_REDIRECTION_CPU: MSI_ADDR_REDIRECTION_LOWPRI) | MSI_ADDR_DEST_ID(dest); @@ -3310,7 +3310,7 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms msg->data = MSI_DATA_TRIGGER_EDGE | MSI_DATA_LEVEL_ASSERT | - ((IRQ_DELIVERY_MODE != dest_LowestPrio) ? + ((apic->irq_delivery_mode != dest_LowestPrio) ? MSI_DATA_DELIVERY_FIXED: MSI_DATA_DELIVERY_LOWPRI) | MSI_DATA_VECTOR(cfg->vector); @@ -3711,11 +3711,11 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) HT_IRQ_LOW_BASE | HT_IRQ_LOW_DEST_ID(dest) | HT_IRQ_LOW_VECTOR(cfg->vector) | - ((IRQ_DEST_MODE == 0) ? + ((apic->irq_dest_mode == 0) ? HT_IRQ_LOW_DM_PHYSICAL : HT_IRQ_LOW_DM_LOGICAL) | HT_IRQ_LOW_RQEOI_EDGE | - ((IRQ_DELIVERY_MODE != dest_LowestPrio) ? + ((apic->irq_delivery_mode != dest_LowestPrio) ? HT_IRQ_LOW_MT_FIXED : HT_IRQ_LOW_MT_ARBITRATED) | HT_IRQ_LOW_IRQ_MASKED; @@ -3763,8 +3763,8 @@ int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade, BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long)); entry->vector = cfg->vector; - entry->delivery_mode = IRQ_DELIVERY_MODE; - entry->dest_mode = IRQ_DEST_MODE; + entry->delivery_mode = apic->irq_delivery_mode; + entry->dest_mode = apic->irq_dest_mode; entry->polarity = 0; entry->trigger = 0; entry->mask = 0; diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index c15c1aa2dc7..e8c1ceca7c9 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -64,8 +64,8 @@ struct genapic apic_bigsmp = { .acpi_madt_oem_check = NULL, .apic_id_registered = bigsmp_apic_id_registered, - .irq_delivery_mode = IRQ_DELIVERY_MODE, - .irq_dest_mode = IRQ_DEST_MODE, + .irq_delivery_mode = BIGSMP_IRQ_DELIVERY_MODE, + .irq_dest_mode = BIGSMP_IRQ_DEST_MODE, .target_cpus = target_cpus, .ESR_DISABLE = esr_disable, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index d32b175eff8..0482106f0e1 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -31,8 +31,8 @@ struct genapic apic_default = { .acpi_madt_oem_check = NULL, .apic_id_registered = default_apic_id_registered, - .irq_delivery_mode = IRQ_DELIVERY_MODE, - .irq_dest_mode = IRQ_DEST_MODE, + .irq_delivery_mode = DEFAULT_IRQ_DELIVERY_MODE, + .irq_dest_mode = DEFAULT_IRQ_DEST_MODE, .target_cpus = target_cpus, .ESR_DISABLE = esr_disable, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 06653892953..5d97408919b 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -107,8 +107,8 @@ struct genapic apic_es7000 = { .acpi_madt_oem_check = es7000_acpi_madt_oem_check, .apic_id_registered = es7000_apic_id_registered, - .irq_delivery_mode = IRQ_DELIVERY_MODE, - .irq_dest_mode = IRQ_DEST_MODE, + .irq_delivery_mode = ES7000_IRQ_DELIVERY_MODE, + .irq_dest_mode = ES7000_IRQ_DEST_MODE, .target_cpus = target_cpus, .ESR_DISABLE = esr_disable, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 401957142fd..77ac66935fd 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -51,8 +51,8 @@ struct genapic apic_numaq = { .acpi_madt_oem_check = NULL, .apic_id_registered = numaq_apic_id_registered, - .irq_delivery_mode = IRQ_DELIVERY_MODE, - .irq_dest_mode = IRQ_DEST_MODE, + .irq_delivery_mode = NUMAQ_IRQ_DELIVERY_MODE, + .irq_dest_mode = NUMAQ_IRQ_DEST_MODE, .target_cpus = target_cpus, .ESR_DISABLE = esr_disable, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 946da7aa762..7b3f43caf2a 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -44,8 +44,8 @@ struct genapic apic_summit = { .acpi_madt_oem_check = summit_acpi_madt_oem_check, .apic_id_registered = summit_apic_id_registered, - .irq_delivery_mode = IRQ_DELIVERY_MODE, - .irq_dest_mode = IRQ_DEST_MODE, + .irq_delivery_mode = SUMMIT_IRQ_DELIVERY_MODE, + .irq_dest_mode = SUMMIT_IRQ_DEST_MODE, .target_cpus = target_cpus, .ESR_DISABLE = esr_disable, -- GitLab From dcafa4a8c95ce063cbae0a5e61632bc3c4924e66 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 04:16:01 +0100 Subject: [PATCH 0538/4982] x86, apic: remove DEFAULT_IRQ_DELIVERY_MODE and DEFAULT_IRQ_DEST_MODE Impact: cleanup They were only used in a single place and obscured the apic_default template. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/mach-default/mach_apic.h | 2 -- arch/x86/mach-generic/default.c | 5 +++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index eafbf4f2038..f3b2cd42388 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -34,8 +34,6 @@ static inline const struct cpumask *target_cpus(void) #define wakeup_secondary_cpu (apic->wakeup_cpu) extern void setup_apic_routing(void); #else -#define DEFAULT_IRQ_DELIVERY_MODE dest_LowestPrio -#define DEFAULT_IRQ_DEST_MODE 1 /* logical delivery broadcast to all procs */ #define TARGET_CPUS (target_cpus()) #define wakeup_secondary_cpu wakeup_secondary_cpu_via_init /* diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index 0482106f0e1..fe97b0114a0 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -31,8 +31,9 @@ struct genapic apic_default = { .acpi_madt_oem_check = NULL, .apic_id_registered = default_apic_id_registered, - .irq_delivery_mode = DEFAULT_IRQ_DELIVERY_MODE, - .irq_dest_mode = DEFAULT_IRQ_DEST_MODE, + .irq_delivery_mode = dest_LowestPrio, + /* logical delivery broadcast to all CPUs: */ + .irq_dest_mode = 1, .target_cpus = target_cpus, .ESR_DISABLE = esr_disable, -- GitLab From 82daea6b0890f739be1ad4ab1c1b922b1555582e Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 04:16:01 +0100 Subject: [PATCH 0539/4982] x86, apic: remove SUMMIT_IRQ_DELIVERY_MODE and SUMMIT_IRQ_DEST_MODE Impact: cleanup They were only used in a single place and obscured the apic_summit template. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/summit/apic.h | 3 --- arch/x86/mach-generic/summit.c | 5 +++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index ea2abe9b597..427d0889f6f 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h @@ -24,9 +24,6 @@ static inline const cpumask_t *target_cpus(void) return &cpumask_of_cpu(0); } -#define SUMMIT_IRQ_DELIVERY_MODE (dest_LowestPrio) -#define SUMMIT_IRQ_DEST_MODE 1 /* logical delivery broadcast to all procs */ - static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) { return 0; diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 7b3f43caf2a..1b9164b92b0 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -44,8 +44,9 @@ struct genapic apic_summit = { .acpi_madt_oem_check = summit_acpi_madt_oem_check, .apic_id_registered = summit_apic_id_registered, - .irq_delivery_mode = SUMMIT_IRQ_DELIVERY_MODE, - .irq_dest_mode = SUMMIT_IRQ_DEST_MODE, + .irq_delivery_mode = dest_LowestPrio, + /* logical delivery broadcast to all CPUs: */ + .irq_dest_mode = 1, .target_cpus = target_cpus, .ESR_DISABLE = esr_disable, -- GitLab From 1b1bcb3ff4e4934d949574cec90679219ace5412 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 04:16:01 +0100 Subject: [PATCH 0540/4982] x86, apic: remove NUMAQ_IRQ_DELIVERY_MODE and NUMAQ_IRQ_DEST_MODE Impact: cleanup They were only used in a single place and obscured the apic_numaq template. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/numaq/apic.h | 3 --- arch/x86/mach-generic/numaq.c | 5 +++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h index 7746035c591..a9d846769a0 100644 --- a/arch/x86/include/asm/numaq/apic.h +++ b/arch/x86/include/asm/numaq/apic.h @@ -15,9 +15,6 @@ static inline const cpumask_t *target_cpus(void) #define NO_BALANCE_IRQ (1) #define esr_disable (1) -#define NUMAQ_IRQ_DELIVERY_MODE dest_LowestPrio -#define NUMAQ_IRQ_DEST_MODE 0 /* physical delivery on LOCAL quad */ - static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) { return physid_isset(apicid, bitmap); diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 77ac66935fd..6daddb6949d 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -51,8 +51,9 @@ struct genapic apic_numaq = { .acpi_madt_oem_check = NULL, .apic_id_registered = numaq_apic_id_registered, - .irq_delivery_mode = NUMAQ_IRQ_DELIVERY_MODE, - .irq_dest_mode = NUMAQ_IRQ_DEST_MODE, + .irq_delivery_mode = dest_LowestPrio, + /* physical delivery on LOCAL quad: */ + .irq_dest_mode = 0, .target_cpus = target_cpus, .ESR_DISABLE = esr_disable, -- GitLab From d8a3539e64f8e27b0ab5bb7e7ba3b8f34b739224 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 04:16:01 +0100 Subject: [PATCH 0541/4982] x86, apic: remove BIGSMP_IRQ_DELIVERY_MODE and BIGSMP_IRQ_DEST_MODE Impact: cleanup They were only used in a single place and obscured the apic_bigsmp driver template. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 2 -- arch/x86/mach-generic/bigsmp.c | 5 +++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index 293551b0e61..dca2d5b01da 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h @@ -21,8 +21,6 @@ static inline const cpumask_t *target_cpus(void) #undef APIC_DEST_LOGICAL #define APIC_DEST_LOGICAL 0 #define APIC_DFR_VALUE (APIC_DFR_FLAT) -#define BIGSMP_IRQ_DELIVERY_MODE (dest_Fixed) -#define BIGSMP_IRQ_DEST_MODE (0) /* phys delivery to target proc */ #define NO_BALANCE_IRQ (0) static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index e8c1ceca7c9..06be776067a 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -64,8 +64,9 @@ struct genapic apic_bigsmp = { .acpi_madt_oem_check = NULL, .apic_id_registered = bigsmp_apic_id_registered, - .irq_delivery_mode = BIGSMP_IRQ_DELIVERY_MODE, - .irq_dest_mode = BIGSMP_IRQ_DEST_MODE, + .irq_delivery_mode = dest_Fixed, + /* phys delivery to target CPU: */ + .irq_dest_mode = 0, .target_cpus = target_cpus, .ESR_DISABLE = esr_disable, -- GitLab From 38bd77a6c35168b03b65f7438cdcc1257d550924 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 04:16:01 +0100 Subject: [PATCH 0542/4982] x86, apic: remove ES7000_IRQ_DELIVERY_MODE and ES7000_IRQ_DEST_MODE Impact: cleanup They were only used in a single place and obscured the apic_es7000 driver template. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/es7000/apic.h | 2 -- arch/x86/mach-generic/es7000.c | 5 +++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index 690016683f2..342416b3fad 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -27,8 +27,6 @@ static inline const cpumask_t *target_cpus(void) #define NO_BALANCE_IRQ_CLUSTER (1) #define APIC_DFR_VALUE (APIC_DFR_FLAT) -#define ES7000_IRQ_DELIVERY_MODE (dest_Fixed) -#define ES7000_IRQ_DEST_MODE (0) /* phys delivery to target procs */ #define NO_BALANCE_IRQ (0) #undef APIC_DEST_LOGICAL #define APIC_DEST_LOGICAL 0x0 diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 5d97408919b..269a97aef43 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -107,8 +107,9 @@ struct genapic apic_es7000 = { .acpi_madt_oem_check = es7000_acpi_madt_oem_check, .apic_id_registered = es7000_apic_id_registered, - .irq_delivery_mode = ES7000_IRQ_DELIVERY_MODE, - .irq_dest_mode = ES7000_IRQ_DEST_MODE, + .irq_delivery_mode = dest_Fixed, + /* phys delivery to target CPUs: */ + .irq_dest_mode = 0, .target_cpus = target_cpus, .ESR_DISABLE = esr_disable, -- GitLab From 7fe732862d9697cc1863286fbcace9a67f231b4c Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 04:24:16 +0100 Subject: [PATCH 0543/4982] x86, apic: remove IRQ_DEST_MODE Remove leftover definition. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/mach-default/mach_apic.h | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index f3b2cd42388..ce3bc4845b9 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -22,7 +22,6 @@ static inline const struct cpumask *target_cpus(void) #ifdef CONFIG_X86_64 #include -#define IRQ_DEST_MODE (apic->irq_dest_mode) #define TARGET_CPUS (apic->target_cpus()) #define init_apic_ldr (apic->init_apic_ldr) #define cpu_mask_to_apicid (apic->cpu_mask_to_apicid) -- GitLab From 0a9cc20b9c18372ba5a9fea990f5812f3ee01e32 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 04:30:40 +0100 Subject: [PATCH 0544/4982] x86, apic: clean up target_cpus methods Impact: cleanup Clean up all the target_cpus() namespace overlap that exists between bigsmp, es7000, mach-default, numaq and summit - by separating the different functions into different names. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 2 +- arch/x86/include/asm/es7000/apic.h | 4 ++-- arch/x86/include/asm/mach-default/mach_apic.h | 4 ++-- arch/x86/include/asm/numaq/apic.h | 2 +- arch/x86/include/asm/summit/apic.h | 2 +- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 2 +- arch/x86/mach-generic/numaq.c | 2 +- arch/x86/mach-generic/summit.c | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index dca2d5b01da..d6aeca3c5a8 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h @@ -9,7 +9,7 @@ static inline int bigsmp_apic_id_registered(void) return 1; } -static inline const cpumask_t *target_cpus(void) +static inline const cpumask_t *bigsmp_target_cpus(void) { #ifdef CONFIG_SMP return &cpu_online_map; diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index 342416b3fad..7e5c31a4f8d 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -16,7 +16,7 @@ static inline const cpumask_t *target_cpus_cluster(void) return &CPU_MASK_ALL; } -static inline const cpumask_t *target_cpus(void) +static inline const cpumask_t *es7000_target_cpus(void) { return &cpumask_of_cpu(smp_processor_id()); } @@ -83,7 +83,7 @@ static inline void setup_apic_routing(void) printk("Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n", (apic_version[apic] == 0x14) ? "Physical Cluster" : "Logical Cluster", - nr_ioapics, cpus_addr(*target_cpus())[0]); + nr_ioapics, cpus_addr(*es7000_target_cpus())[0]); } static inline int multi_timer_check(int apic, int irq) diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index ce3bc4845b9..af1607ddd2a 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -8,7 +8,7 @@ #define APIC_DFR_VALUE (APIC_DFR_FLAT) -static inline const struct cpumask *target_cpus(void) +static inline const struct cpumask *default_target_cpus(void) { #ifdef CONFIG_SMP return cpu_online_mask; @@ -33,7 +33,7 @@ static inline const struct cpumask *target_cpus(void) #define wakeup_secondary_cpu (apic->wakeup_cpu) extern void setup_apic_routing(void); #else -#define TARGET_CPUS (target_cpus()) +#define TARGET_CPUS (default_target_cpus()) #define wakeup_secondary_cpu wakeup_secondary_cpu_via_init /* * Set up the logical destination ID. diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h index a9d846769a0..1111ff9e41d 100644 --- a/arch/x86/include/asm/numaq/apic.h +++ b/arch/x86/include/asm/numaq/apic.h @@ -7,7 +7,7 @@ #define APIC_DFR_VALUE (APIC_DFR_CLUSTER) -static inline const cpumask_t *target_cpus(void) +static inline const cpumask_t *numaq_target_cpus(void) { return &CPU_MASK_ALL; } diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index 427d0889f6f..7c1f9151429 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h @@ -15,7 +15,7 @@ #define APIC_DFR_VALUE (APIC_DFR_CLUSTER) -static inline const cpumask_t *target_cpus(void) +static inline const cpumask_t *summit_target_cpus(void) { /* CPU_MASK_ALL (0xff) has undefined behaviour with * dest_LowestPrio mode logical clustered apic interrupt routing diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 06be776067a..d3cead2d2fc 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -68,7 +68,7 @@ struct genapic apic_bigsmp = { /* phys delivery to target CPU: */ .irq_dest_mode = 0, - .target_cpus = target_cpus, + .target_cpus = bigsmp_target_cpus, .ESR_DISABLE = esr_disable, .apic_destination_logical = APIC_DEST_LOGICAL, .check_apicid_used = check_apicid_used, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index fe97b0114a0..a483e22273e 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -35,7 +35,7 @@ struct genapic apic_default = { /* logical delivery broadcast to all CPUs: */ .irq_dest_mode = 1, - .target_cpus = target_cpus, + .target_cpus = default_target_cpus, .ESR_DISABLE = esr_disable, .apic_destination_logical = APIC_DEST_LOGICAL, .check_apicid_used = check_apicid_used, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 269a97aef43..e31f0c35470 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -111,7 +111,7 @@ struct genapic apic_es7000 = { /* phys delivery to target CPUs: */ .irq_dest_mode = 0, - .target_cpus = target_cpus, + .target_cpus = es7000_target_cpus, .ESR_DISABLE = esr_disable, .apic_destination_logical = APIC_DEST_LOGICAL, .check_apicid_used = check_apicid_used, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 6daddb6949d..4b84b5970fb 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -55,7 +55,7 @@ struct genapic apic_numaq = { /* physical delivery on LOCAL quad: */ .irq_dest_mode = 0, - .target_cpus = target_cpus, + .target_cpus = numaq_target_cpus, .ESR_DISABLE = esr_disable, .apic_destination_logical = APIC_DEST_LOGICAL, .check_apicid_used = check_apicid_used, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 1b9164b92b0..e6b956a0848 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -48,7 +48,7 @@ struct genapic apic_summit = { /* logical delivery broadcast to all CPUs: */ .irq_dest_mode = 1, - .target_cpus = target_cpus, + .target_cpus = summit_target_cpus, .ESR_DISABLE = esr_disable, .apic_destination_logical = APIC_DEST_LOGICAL, .check_apicid_used = check_apicid_used, -- GitLab From fe402e1f2b67a63f1e53ab2a316fc20f7ca4ec91 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 04:32:51 +0100 Subject: [PATCH 0545/4982] x86, apic: clean up / remove TARGET_CPUS Impact: cleanup use apic->target_cpus() directly instead of the TARGET_CPUS wrapper. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/es7000/apic.h | 4 ++-- arch/x86/include/asm/mach-default/mach_apic.h | 2 -- arch/x86/include/asm/mach-generic/mach_apic.h | 1 - arch/x86/include/asm/summit/apic.h | 2 +- arch/x86/kernel/io_apic.c | 22 +++++++++---------- 5 files changed, 14 insertions(+), 17 deletions(-) diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index 7e5c31a4f8d..53adda099c9 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -161,7 +161,7 @@ cpu_mask_to_apicid_cluster(const struct cpumask *cpumask) return 0xFF; /* * The cpus in the mask must all be on the apic cluster. If are not - * on the same apicid cluster return default value of TARGET_CPUS. + * on the same apicid cluster return default value of target_cpus(): */ cpu = cpumask_first(cpumask); apicid = cpu_to_logical_apicid(cpu); @@ -194,7 +194,7 @@ static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask) return cpu_to_logical_apicid(0); /* * The cpus in the mask must all be on the apic cluster. If are not - * on the same apicid cluster return default value of TARGET_CPUS. + * on the same apicid cluster return default value of target_cpus(): */ cpu = first_cpu(*cpumask); apicid = cpu_to_logical_apicid(cpu); diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index af1607ddd2a..77a97247587 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -22,7 +22,6 @@ static inline const struct cpumask *default_target_cpus(void) #ifdef CONFIG_X86_64 #include -#define TARGET_CPUS (apic->target_cpus()) #define init_apic_ldr (apic->init_apic_ldr) #define cpu_mask_to_apicid (apic->cpu_mask_to_apicid) #define cpu_mask_to_apicid_and (apic->cpu_mask_to_apicid_and) @@ -33,7 +32,6 @@ static inline const struct cpumask *default_target_cpus(void) #define wakeup_secondary_cpu (apic->wakeup_cpu) extern void setup_apic_routing(void); #else -#define TARGET_CPUS (default_target_cpus()) #define wakeup_secondary_cpu wakeup_secondary_cpu_via_init /* * Set up the logical destination ID. diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index 387a5d00c43..da2d7780cb5 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -7,7 +7,6 @@ #define NO_BALANCE_IRQ (apic->no_balance_irq) #undef APIC_DEST_LOGICAL #define APIC_DEST_LOGICAL (apic->apic_destination_logical) -#define TARGET_CPUS (apic->target_cpus()) #define init_apic_ldr (apic->init_apic_ldr) #define ioapic_phys_id_map (apic->ioapic_phys_id_map) #define setup_apic_routing (apic->setup_apic_routing) diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index 7c1f9151429..cf5036f1ce6 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h @@ -148,7 +148,7 @@ static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask) return (int) 0xFF; /* * The cpus in the mask must all be on the apic cluster. If are not - * on the same apicid cluster return default value of TARGET_CPUS. + * on the same apicid cluster return default value of target_cpus(): */ cpu = first_cpu(*cpumask); apicid = cpu_to_logical_apicid(cpu); diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 301b6571d70..7503285e180 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -1559,10 +1559,10 @@ static void setup_IO_APIC_irq(int apic_id, int pin, unsigned int irq, struct irq cfg = desc->chip_data; - if (assign_irq_vector(irq, cfg, TARGET_CPUS)) + if (assign_irq_vector(irq, cfg, apic->target_cpus())) return; - dest = cpu_mask_to_apicid_and(cfg->domain, TARGET_CPUS); + dest = cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus()); apic_printk(APIC_VERBOSE,KERN_DEBUG "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> " @@ -1661,7 +1661,7 @@ static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin, */ entry.dest_mode = apic->irq_dest_mode; entry.mask = 1; /* mask IRQ now */ - entry.dest = cpu_mask_to_apicid(TARGET_CPUS); + entry.dest = cpu_mask_to_apicid(apic->target_cpus()); entry.delivery_mode = apic->irq_delivery_mode; entry.polarity = 0; entry.trigger = 0; @@ -2877,7 +2877,7 @@ static inline void __init check_timer(void) * get/set the timer IRQ vector: */ disable_8259A_irq(0); - assign_irq_vector(0, cfg, TARGET_CPUS); + assign_irq_vector(0, cfg, apic->target_cpus()); /* * As IRQ0 is to be enabled in the 8259A, the virtual @@ -3195,7 +3195,7 @@ unsigned int create_irq_nr(unsigned int irq_want) if (cfg_new->vector != 0) continue; - if (__assign_irq_vector(new, cfg_new, TARGET_CPUS) == 0) + if (__assign_irq_vector(new, cfg_new, apic->target_cpus()) == 0) irq = new; break; } @@ -3261,11 +3261,11 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms return -ENXIO; cfg = irq_cfg(irq); - err = assign_irq_vector(irq, cfg, TARGET_CPUS); + err = assign_irq_vector(irq, cfg, apic->target_cpus()); if (err) return err; - dest = cpu_mask_to_apicid_and(cfg->domain, TARGET_CPUS); + dest = cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus()); #ifdef CONFIG_INTR_REMAP if (irq_remapped(irq)) { @@ -3698,12 +3698,12 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) return -ENXIO; cfg = irq_cfg(irq); - err = assign_irq_vector(irq, cfg, TARGET_CPUS); + err = assign_irq_vector(irq, cfg, apic->target_cpus()); if (!err) { struct ht_irq_msg msg; unsigned dest; - dest = cpu_mask_to_apicid_and(cfg->domain, TARGET_CPUS); + dest = cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus()); msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest); @@ -3987,7 +3987,7 @@ int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity) /* * This function currently is only a helper for the i386 smp boot process where * we need to reprogram the ioredtbls to cater for the cpus which have come online - * so mask in all cases should simply be TARGET_CPUS + * so mask in all cases should simply be apic->target_cpus() */ #ifdef CONFIG_SMP void __init setup_ioapic_dest(void) @@ -4028,7 +4028,7 @@ void __init setup_ioapic_dest(void) (IRQ_NO_BALANCING | IRQ_AFFINITY_SET)) mask = desc->affinity; else - mask = TARGET_CPUS; + mask = apic->target_cpus(); #ifdef CONFIG_INTR_REMAP if (intr_remapping_enabled) -- GitLab From f6f52baf2613dd319e9ba3f3319bf1f1c442e4b3 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 05:01:41 +0100 Subject: [PATCH 0546/4982] x86: clean up esr_disable() methods Impact: cleanup Most subarchitectures want to disable the APIC ESR (Error Status Register), because they generally have hardware hacks that wrap standard CPUs into a bigger system and hence the APIC bus is quite non-standard and weirdnesses (lockups) have been seen with ESR reporting. Remove the esr_disable macros and put the desired flag into each subarchitecture's genapic template directly. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 1 - arch/x86/include/asm/es7000/apic.h | 1 - arch/x86/include/asm/mach-default/mach_apic.h | 1 - arch/x86/include/asm/mach-generic/mach_apic.h | 1 - arch/x86/include/asm/numaq/apic.h | 1 - arch/x86/include/asm/summit/apic.h | 1 - arch/x86/kernel/apic.c | 4 ++-- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 2 +- arch/x86/mach-generic/numaq.c | 2 +- arch/x86/mach-generic/summit.c | 2 +- 12 files changed, 7 insertions(+), 13 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index d6aeca3c5a8..b550cb11102 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h @@ -2,7 +2,6 @@ #define __ASM_MACH_APIC_H #define xapic_phys_to_log_apicid(cpu) (per_cpu(x86_bios_cpu_apicid, cpu)) -#define esr_disable (1) static inline int bigsmp_apic_id_registered(void) { diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index 53adda099c9..aa11c768bed 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -4,7 +4,6 @@ #include #define xapic_phys_to_log_apicid(cpu) per_cpu(x86_bios_cpu_apicid, cpu) -#define esr_disable (1) static inline int es7000_apic_id_registered(void) { diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index 77a97247587..5f8d17fdc96 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -18,7 +18,6 @@ static inline const struct cpumask *default_target_cpus(void) } #define NO_BALANCE_IRQ (0) -#define esr_disable (0) #ifdef CONFIG_X86_64 #include diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index da2d7780cb5..63fe985219f 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -3,7 +3,6 @@ #include -#define esr_disable (apic->ESR_DISABLE) #define NO_BALANCE_IRQ (apic->no_balance_irq) #undef APIC_DEST_LOGICAL #define APIC_DEST_LOGICAL (apic->apic_destination_logical) diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h index 1111ff9e41d..8ecb3b45c6c 100644 --- a/arch/x86/include/asm/numaq/apic.h +++ b/arch/x86/include/asm/numaq/apic.h @@ -13,7 +13,6 @@ static inline const cpumask_t *numaq_target_cpus(void) } #define NO_BALANCE_IRQ (1) -#define esr_disable (1) static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) { diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index cf5036f1ce6..84679e687ad 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h @@ -4,7 +4,6 @@ #include #include -#define esr_disable (1) #define NO_BALANCE_IRQ (0) /* In clustered mode, the high nibble of APIC ID is a cluster number. diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index b6740de18fb..69d8c30d571 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -1107,7 +1107,7 @@ static void __cpuinit lapic_setup_esr(void) return; } - if (esr_disable) { + if (apic->ESR_DISABLE) { /* * Something untraceable is creating bad interrupts on * secondary quads ... for the moment, just leave the @@ -1157,7 +1157,7 @@ void __cpuinit setup_local_APIC(void) #ifdef CONFIG_X86_32 /* Pound the ESR really hard over the head with a big hammer - mbligh */ - if (lapic_is_integrated() && esr_disable) { + if (lapic_is_integrated() && apic->ESR_DISABLE) { apic_write(APIC_ESR, 0); apic_write(APIC_ESR, 0); apic_write(APIC_ESR, 0); diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index d3cead2d2fc..f0bb72674f7 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -69,7 +69,7 @@ struct genapic apic_bigsmp = { .irq_dest_mode = 0, .target_cpus = bigsmp_target_cpus, - .ESR_DISABLE = esr_disable, + .ESR_DISABLE = 1, .apic_destination_logical = APIC_DEST_LOGICAL, .check_apicid_used = check_apicid_used, .check_apicid_present = check_apicid_present, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index a483e22273e..c30141a9aca 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -36,7 +36,7 @@ struct genapic apic_default = { .irq_dest_mode = 1, .target_cpus = default_target_cpus, - .ESR_DISABLE = esr_disable, + .ESR_DISABLE = 0, .apic_destination_logical = APIC_DEST_LOGICAL, .check_apicid_used = check_apicid_used, .check_apicid_present = check_apicid_present, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index e31f0c35470..e8aa8fd4f49 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -112,7 +112,7 @@ struct genapic apic_es7000 = { .irq_dest_mode = 0, .target_cpus = es7000_target_cpus, - .ESR_DISABLE = esr_disable, + .ESR_DISABLE = 1, .apic_destination_logical = APIC_DEST_LOGICAL, .check_apicid_used = check_apicid_used, .check_apicid_present = check_apicid_present, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 4b84b5970fb..860edc8bd90 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -56,7 +56,7 @@ struct genapic apic_numaq = { .irq_dest_mode = 0, .target_cpus = numaq_target_cpus, - .ESR_DISABLE = esr_disable, + .ESR_DISABLE = 1, .apic_destination_logical = APIC_DEST_LOGICAL, .check_apicid_used = check_apicid_used, .check_apicid_present = check_apicid_present, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index e6b956a0848..cd5ef115a4e 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -49,7 +49,7 @@ struct genapic apic_summit = { .irq_dest_mode = 1, .target_cpus = summit_target_cpus, - .ESR_DISABLE = esr_disable, + .ESR_DISABLE = 1, .apic_destination_logical = APIC_DEST_LOGICAL, .check_apicid_used = check_apicid_used, .check_apicid_present = check_apicid_present, -- GitLab From 08125d3edab90644724652eedec3e219e3e0f2e7 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 05:08:44 +0100 Subject: [PATCH 0547/4982] x86: rename ->ESR_DISABLE to ->disable_esr the ->ESR_DISABLE shouting variant was used to enable the esr_disable macro wrappers. Those ugly macros are removed now so we can rename ->ESR_DISABLE to ->disable_esr Signed-off-by: Ingo Molnar --- arch/x86/include/asm/genapic.h | 2 +- arch/x86/kernel/apic.c | 4 ++-- arch/x86/kernel/genapic_flat_64.c | 4 ++-- arch/x86/kernel/genx2apic_cluster.c | 2 +- arch/x86/kernel/genx2apic_phys.c | 2 +- arch/x86/kernel/genx2apic_uv_x.c | 2 +- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 2 +- arch/x86/mach-generic/numaq.c | 2 +- arch/x86/mach-generic/summit.c | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/arch/x86/include/asm/genapic.h b/arch/x86/include/asm/genapic.h index e998e3df5d2..7aee4a4c524 100644 --- a/arch/x86/include/asm/genapic.h +++ b/arch/x86/include/asm/genapic.h @@ -28,7 +28,7 @@ struct genapic { const struct cpumask *(*target_cpus)(void); - int ESR_DISABLE; + int disable_esr; int apic_destination_logical; unsigned long (*check_apicid_used)(physid_mask_t bitmap, int apicid); diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 69d8c30d571..3853ed76c88 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -1107,7 +1107,7 @@ static void __cpuinit lapic_setup_esr(void) return; } - if (apic->ESR_DISABLE) { + if (apic->disable_esr) { /* * Something untraceable is creating bad interrupts on * secondary quads ... for the moment, just leave the @@ -1157,7 +1157,7 @@ void __cpuinit setup_local_APIC(void) #ifdef CONFIG_X86_32 /* Pound the ESR really hard over the head with a big hammer - mbligh */ - if (lapic_is_integrated() && apic->ESR_DISABLE) { + if (lapic_is_integrated() && apic->disable_esr) { apic_write(APIC_ESR, 0); apic_write(APIC_ESR, 0); apic_write(APIC_ESR, 0); diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index 0a263d6bb5e..d437a60cc58 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -184,7 +184,7 @@ struct genapic apic_flat = { .irq_dest_mode = (APIC_DEST_LOGICAL != 0), .target_cpus = flat_target_cpus, - .ESR_DISABLE = 0, + .disable_esr = 0, .apic_destination_logical = 0, .check_apicid_used = NULL, .check_apicid_present = NULL, @@ -330,7 +330,7 @@ struct genapic apic_physflat = { .irq_dest_mode = (APIC_DEST_PHYSICAL != 0), .target_cpus = physflat_target_cpus, - .ESR_DISABLE = 0, + .disable_esr = 0, .apic_destination_logical = 0, .check_apicid_used = NULL, .check_apicid_present = NULL, diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c index e9ff7dc9a0f..c1cffae4a4c 100644 --- a/arch/x86/kernel/genx2apic_cluster.c +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -186,7 +186,7 @@ struct genapic apic_x2apic_cluster = { .irq_dest_mode = (APIC_DEST_LOGICAL != 0), .target_cpus = x2apic_target_cpus, - .ESR_DISABLE = 0, + .disable_esr = 0, .apic_destination_logical = 0, .check_apicid_used = NULL, .check_apicid_present = NULL, diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c index 8141b5a88f6..c59602be035 100644 --- a/arch/x86/kernel/genx2apic_phys.c +++ b/arch/x86/kernel/genx2apic_phys.c @@ -182,7 +182,7 @@ struct genapic apic_x2apic_phys = { .irq_dest_mode = (APIC_DEST_PHYSICAL != 0), .target_cpus = x2apic_target_cpus, - .ESR_DISABLE = 0, + .disable_esr = 0, .apic_destination_logical = 0, .check_apicid_used = NULL, .check_apicid_present = NULL, diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index 6a73cad0d3e..525b4e480a7 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -247,7 +247,7 @@ struct genapic apic_x2apic_uv_x = { .irq_dest_mode = (APIC_DEST_PHYSICAL != 0), .target_cpus = uv_target_cpus, - .ESR_DISABLE = 0, + .disable_esr = 0, .apic_destination_logical = 0, .check_apicid_used = NULL, .check_apicid_present = NULL, diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index f0bb72674f7..fe9bf252c06 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -69,7 +69,7 @@ struct genapic apic_bigsmp = { .irq_dest_mode = 0, .target_cpus = bigsmp_target_cpus, - .ESR_DISABLE = 1, + .disable_esr = 1, .apic_destination_logical = APIC_DEST_LOGICAL, .check_apicid_used = check_apicid_used, .check_apicid_present = check_apicid_present, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index c30141a9aca..d3fe8017e94 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -36,7 +36,7 @@ struct genapic apic_default = { .irq_dest_mode = 1, .target_cpus = default_target_cpus, - .ESR_DISABLE = 0, + .disable_esr = 0, .apic_destination_logical = APIC_DEST_LOGICAL, .check_apicid_used = check_apicid_used, .check_apicid_present = check_apicid_present, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index e8aa8fd4f49..b4f8abfb714 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -112,7 +112,7 @@ struct genapic apic_es7000 = { .irq_dest_mode = 0, .target_cpus = es7000_target_cpus, - .ESR_DISABLE = 1, + .disable_esr = 1, .apic_destination_logical = APIC_DEST_LOGICAL, .check_apicid_used = check_apicid_used, .check_apicid_present = check_apicid_present, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 860edc8bd90..f3b7840d227 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -56,7 +56,7 @@ struct genapic apic_numaq = { .irq_dest_mode = 0, .target_cpus = numaq_target_cpus, - .ESR_DISABLE = 1, + .disable_esr = 1, .apic_destination_logical = APIC_DEST_LOGICAL, .check_apicid_used = check_apicid_used, .check_apicid_present = check_apicid_present, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index cd5ef115a4e..95e075b61bd 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -49,7 +49,7 @@ struct genapic apic_summit = { .irq_dest_mode = 1, .target_cpus = summit_target_cpus, - .ESR_DISABLE = 1, + .disable_esr = 1, .apic_destination_logical = APIC_DEST_LOGICAL, .check_apicid_used = check_apicid_used, .check_apicid_present = check_apicid_present, -- GitLab From 0b06e734bff7554c31eac4aad2fc9be4adb7c1c1 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 05:13:04 +0100 Subject: [PATCH 0548/4982] x86: clean up the APIC_DEST_LOGICAL logic Impact: cleanup The bigsmp and es7000 subarchitectures un-defined APIC_DEST_LOGICAL in a rather nasty way by re-defining it to zero. That is infinitely fragile and makes it very hard to see what to code really does in a given context. The very same constant has different meanings and values - depending on which subarch is enabled. Untangle this mess by never undefining the constant, but instead propagating the right values into the genapic driver templates. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 2 -- arch/x86/include/asm/es7000/apic.h | 2 -- arch/x86/include/asm/mach-generic/mach_apic.h | 2 -- arch/x86/kernel/genapic_flat_64.c | 12 ++++++------ arch/x86/kernel/genx2apic_cluster.c | 10 +++++----- arch/x86/kernel/genx2apic_phys.c | 2 +- arch/x86/kernel/genx2apic_uv_x.c | 4 ++-- arch/x86/kernel/io_apic.c | 2 +- arch/x86/kernel/ipi.c | 2 +- arch/x86/kernel/smpboot.c | 2 +- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/es7000.c | 2 +- 12 files changed, 19 insertions(+), 25 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index b550cb11102..7e6e33a6db0 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h @@ -17,8 +17,6 @@ static inline const cpumask_t *bigsmp_target_cpus(void) #endif } -#undef APIC_DEST_LOGICAL -#define APIC_DEST_LOGICAL 0 #define APIC_DFR_VALUE (APIC_DFR_FLAT) #define NO_BALANCE_IRQ (0) diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index aa11c768bed..0d770fce4b2 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -27,8 +27,6 @@ static inline const cpumask_t *es7000_target_cpus(void) #define APIC_DFR_VALUE (APIC_DFR_FLAT) #define NO_BALANCE_IRQ (0) -#undef APIC_DEST_LOGICAL -#define APIC_DEST_LOGICAL 0x0 static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) { diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index 63fe985219f..00d5fe6e676 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -4,8 +4,6 @@ #include #define NO_BALANCE_IRQ (apic->no_balance_irq) -#undef APIC_DEST_LOGICAL -#define APIC_DEST_LOGICAL (apic->apic_destination_logical) #define init_apic_ldr (apic->init_apic_ldr) #define ioapic_phys_id_map (apic->ioapic_phys_id_map) #define setup_apic_routing (apic->setup_apic_routing) diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index d437a60cc58..fd242c6b3ba 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -74,7 +74,7 @@ static inline void _flat_send_IPI_mask(unsigned long mask, int vector) unsigned long flags; local_irq_save(flags); - __send_IPI_dest_field(mask, vector, APIC_DEST_LOGICAL); + __send_IPI_dest_field(mask, vector, apic->apic_destination_logical); local_irq_restore(flags); } @@ -114,7 +114,7 @@ static void flat_send_IPI_allbutself(int vector) _flat_send_IPI_mask(mask, vector); } } else if (num_online_cpus() > 1) { - __send_IPI_shortcut(APIC_DEST_ALLBUT, vector,APIC_DEST_LOGICAL); + __send_IPI_shortcut(APIC_DEST_ALLBUT, vector, apic->apic_destination_logical); } } @@ -123,7 +123,7 @@ static void flat_send_IPI_all(int vector) if (vector == NMI_VECTOR) flat_send_IPI_mask(cpu_online_mask, vector); else - __send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL); + __send_IPI_shortcut(APIC_DEST_ALLINC, vector, apic->apic_destination_logical); } static unsigned int get_apic_id(unsigned long x) @@ -181,11 +181,11 @@ struct genapic apic_flat = { .apic_id_registered = flat_apic_id_registered, .irq_delivery_mode = dest_LowestPrio, - .irq_dest_mode = (APIC_DEST_LOGICAL != 0), + .irq_dest_mode = 1, /* logical */ .target_cpus = flat_target_cpus, .disable_esr = 0, - .apic_destination_logical = 0, + .apic_destination_logical = APIC_DEST_LOGICAL, .check_apicid_used = NULL, .check_apicid_present = NULL, @@ -327,7 +327,7 @@ struct genapic apic_physflat = { .apic_id_registered = flat_apic_id_registered, .irq_delivery_mode = dest_Fixed, - .irq_dest_mode = (APIC_DEST_PHYSICAL != 0), + .irq_dest_mode = 0, /* physical */ .target_cpus = physflat_target_cpus, .disable_esr = 0, diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c index c1cffae4a4c..a76e75ecc20 100644 --- a/arch/x86/kernel/genx2apic_cluster.c +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -64,7 +64,7 @@ static void x2apic_send_IPI_mask(const struct cpumask *mask, int vector) for_each_cpu(query_cpu, mask) __x2apic_send_IPI_dest( per_cpu(x86_cpu_to_logical_apicid, query_cpu), - vector, APIC_DEST_LOGICAL); + vector, apic->apic_destination_logical); local_irq_restore(flags); } @@ -80,7 +80,7 @@ static void x2apic_send_IPI_mask_allbutself(const struct cpumask *mask, if (query_cpu != this_cpu) __x2apic_send_IPI_dest( per_cpu(x86_cpu_to_logical_apicid, query_cpu), - vector, APIC_DEST_LOGICAL); + vector, apic->apic_destination_logical); local_irq_restore(flags); } @@ -95,7 +95,7 @@ static void x2apic_send_IPI_allbutself(int vector) if (query_cpu != this_cpu) __x2apic_send_IPI_dest( per_cpu(x86_cpu_to_logical_apicid, query_cpu), - vector, APIC_DEST_LOGICAL); + vector, apic->apic_destination_logical); local_irq_restore(flags); } @@ -183,11 +183,11 @@ struct genapic apic_x2apic_cluster = { .apic_id_registered = x2apic_apic_id_registered, .irq_delivery_mode = dest_LowestPrio, - .irq_dest_mode = (APIC_DEST_LOGICAL != 0), + .irq_dest_mode = 1, /* logical */ .target_cpus = x2apic_target_cpus, .disable_esr = 0, - .apic_destination_logical = 0, + .apic_destination_logical = APIC_DEST_LOGICAL, .check_apicid_used = NULL, .check_apicid_present = NULL, diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c index c59602be035..9b6d68deb14 100644 --- a/arch/x86/kernel/genx2apic_phys.c +++ b/arch/x86/kernel/genx2apic_phys.c @@ -179,7 +179,7 @@ struct genapic apic_x2apic_phys = { .apic_id_registered = x2apic_apic_id_registered, .irq_delivery_mode = dest_Fixed, - .irq_dest_mode = (APIC_DEST_PHYSICAL != 0), + .irq_dest_mode = 0, /* physical */ .target_cpus = x2apic_target_cpus, .disable_esr = 0, diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index 525b4e480a7..0a756800c11 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -244,11 +244,11 @@ struct genapic apic_x2apic_uv_x = { .apic_id_registered = uv_apic_id_registered, .irq_delivery_mode = dest_Fixed, - .irq_dest_mode = (APIC_DEST_PHYSICAL != 0), + .irq_dest_mode = 1, /* logical */ .target_cpus = uv_target_cpus, .disable_esr = 0, - .apic_destination_logical = 0, + .apic_destination_logical = APIC_DEST_LOGICAL, .check_apicid_used = NULL, .check_apicid_present = NULL, diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 7503285e180..17526d7a8ab 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -806,7 +806,7 @@ void send_IPI_self(int vector) * Wait for idle. */ apic_wait_icr_idle(); - cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL; + cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | apic->apic_destination_logical; /* * Send the IPI. The write to APIC_ICR fires this off. */ diff --git a/arch/x86/kernel/ipi.c b/arch/x86/kernel/ipi.c index 285bbf8831f..400b7bd48f6 100644 --- a/arch/x86/kernel/ipi.c +++ b/arch/x86/kernel/ipi.c @@ -30,7 +30,7 @@ static inline int __prepare_ICR(unsigned int shortcut, int vector) { - unsigned int icr = shortcut | APIC_DEST_LOGICAL; + unsigned int icr = shortcut | apic->apic_destination_logical; switch (vector) { default: diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index f9dbcff4354..f0a173718d9 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -583,7 +583,7 @@ wakeup_secondary_cpu_via_nmi(int logical_apicid, unsigned long start_eip) /* Target chip */ /* Boot on the stack */ /* Kick the second */ - apic_icr_write(APIC_DM_NMI | APIC_DEST_LOGICAL, logical_apicid); + apic_icr_write(APIC_DM_NMI | apic->apic_destination_logical, logical_apicid); pr_debug("Waiting for send to finish...\n"); send_status = safe_apic_wait_icr_idle(); diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index fe9bf252c06..13ee7dc9b95 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -70,7 +70,7 @@ struct genapic apic_bigsmp = { .target_cpus = bigsmp_target_cpus, .disable_esr = 1, - .apic_destination_logical = APIC_DEST_LOGICAL, + .apic_destination_logical = 0, .check_apicid_used = check_apicid_used, .check_apicid_present = check_apicid_present, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index b4f8abfb714..61b5da213ce 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -113,7 +113,7 @@ struct genapic apic_es7000 = { .target_cpus = es7000_target_cpus, .disable_esr = 1, - .apic_destination_logical = APIC_DEST_LOGICAL, + .apic_destination_logical = 0, .check_apicid_used = check_apicid_used, .check_apicid_present = check_apicid_present, -- GitLab From bdb1a9b62fc182d4da3143e346f7a0925d243352 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 05:29:25 +0100 Subject: [PATCH 0549/4982] x86, apic: rename genapic::apic_destination_logical to genapic::dest_logical This field name was unreasonably long - shorten it. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/genapic.h | 2 +- arch/x86/kernel/genapic_flat_64.c | 10 +++++----- arch/x86/kernel/genx2apic_cluster.c | 8 ++++---- arch/x86/kernel/genx2apic_phys.c | 2 +- arch/x86/kernel/genx2apic_uv_x.c | 2 +- arch/x86/kernel/io_apic.c | 2 +- arch/x86/kernel/ipi.c | 2 +- arch/x86/kernel/smpboot.c | 2 +- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 2 +- arch/x86/mach-generic/numaq.c | 2 +- arch/x86/mach-generic/summit.c | 2 +- 13 files changed, 20 insertions(+), 20 deletions(-) diff --git a/arch/x86/include/asm/genapic.h b/arch/x86/include/asm/genapic.h index 7aee4a4c524..f9d1ec018fd 100644 --- a/arch/x86/include/asm/genapic.h +++ b/arch/x86/include/asm/genapic.h @@ -30,7 +30,7 @@ struct genapic { int disable_esr; - int apic_destination_logical; + int dest_logical; unsigned long (*check_apicid_used)(physid_mask_t bitmap, int apicid); unsigned long (*check_apicid_present)(int apicid); diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index fd242c6b3ba..d22cbdaee20 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -74,7 +74,7 @@ static inline void _flat_send_IPI_mask(unsigned long mask, int vector) unsigned long flags; local_irq_save(flags); - __send_IPI_dest_field(mask, vector, apic->apic_destination_logical); + __send_IPI_dest_field(mask, vector, apic->dest_logical); local_irq_restore(flags); } @@ -114,7 +114,7 @@ static void flat_send_IPI_allbutself(int vector) _flat_send_IPI_mask(mask, vector); } } else if (num_online_cpus() > 1) { - __send_IPI_shortcut(APIC_DEST_ALLBUT, vector, apic->apic_destination_logical); + __send_IPI_shortcut(APIC_DEST_ALLBUT, vector, apic->dest_logical); } } @@ -123,7 +123,7 @@ static void flat_send_IPI_all(int vector) if (vector == NMI_VECTOR) flat_send_IPI_mask(cpu_online_mask, vector); else - __send_IPI_shortcut(APIC_DEST_ALLINC, vector, apic->apic_destination_logical); + __send_IPI_shortcut(APIC_DEST_ALLINC, vector, apic->dest_logical); } static unsigned int get_apic_id(unsigned long x) @@ -185,7 +185,7 @@ struct genapic apic_flat = { .target_cpus = flat_target_cpus, .disable_esr = 0, - .apic_destination_logical = APIC_DEST_LOGICAL, + .dest_logical = APIC_DEST_LOGICAL, .check_apicid_used = NULL, .check_apicid_present = NULL, @@ -331,7 +331,7 @@ struct genapic apic_physflat = { .target_cpus = physflat_target_cpus, .disable_esr = 0, - .apic_destination_logical = 0, + .dest_logical = 0, .check_apicid_used = NULL, .check_apicid_present = NULL, diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c index a76e75ecc20..b91a48eae52 100644 --- a/arch/x86/kernel/genx2apic_cluster.c +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -64,7 +64,7 @@ static void x2apic_send_IPI_mask(const struct cpumask *mask, int vector) for_each_cpu(query_cpu, mask) __x2apic_send_IPI_dest( per_cpu(x86_cpu_to_logical_apicid, query_cpu), - vector, apic->apic_destination_logical); + vector, apic->dest_logical); local_irq_restore(flags); } @@ -80,7 +80,7 @@ static void x2apic_send_IPI_mask_allbutself(const struct cpumask *mask, if (query_cpu != this_cpu) __x2apic_send_IPI_dest( per_cpu(x86_cpu_to_logical_apicid, query_cpu), - vector, apic->apic_destination_logical); + vector, apic->dest_logical); local_irq_restore(flags); } @@ -95,7 +95,7 @@ static void x2apic_send_IPI_allbutself(int vector) if (query_cpu != this_cpu) __x2apic_send_IPI_dest( per_cpu(x86_cpu_to_logical_apicid, query_cpu), - vector, apic->apic_destination_logical); + vector, apic->dest_logical); local_irq_restore(flags); } @@ -187,7 +187,7 @@ struct genapic apic_x2apic_cluster = { .target_cpus = x2apic_target_cpus, .disable_esr = 0, - .apic_destination_logical = APIC_DEST_LOGICAL, + .dest_logical = APIC_DEST_LOGICAL, .check_apicid_used = NULL, .check_apicid_present = NULL, diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c index 9b6d68deb14..f070e86af0f 100644 --- a/arch/x86/kernel/genx2apic_phys.c +++ b/arch/x86/kernel/genx2apic_phys.c @@ -183,7 +183,7 @@ struct genapic apic_x2apic_phys = { .target_cpus = x2apic_target_cpus, .disable_esr = 0, - .apic_destination_logical = 0, + .dest_logical = 0, .check_apicid_used = NULL, .check_apicid_present = NULL, diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index 0a756800c11..c8a89158679 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -248,7 +248,7 @@ struct genapic apic_x2apic_uv_x = { .target_cpus = uv_target_cpus, .disable_esr = 0, - .apic_destination_logical = APIC_DEST_LOGICAL, + .dest_logical = APIC_DEST_LOGICAL, .check_apicid_used = NULL, .check_apicid_present = NULL, diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 17526d7a8ab..7f8b32b2089 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -806,7 +806,7 @@ void send_IPI_self(int vector) * Wait for idle. */ apic_wait_icr_idle(); - cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | apic->apic_destination_logical; + cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | apic->dest_logical; /* * Send the IPI. The write to APIC_ICR fires this off. */ diff --git a/arch/x86/kernel/ipi.c b/arch/x86/kernel/ipi.c index 400b7bd48f6..e2e4895ca69 100644 --- a/arch/x86/kernel/ipi.c +++ b/arch/x86/kernel/ipi.c @@ -30,7 +30,7 @@ static inline int __prepare_ICR(unsigned int shortcut, int vector) { - unsigned int icr = shortcut | apic->apic_destination_logical; + unsigned int icr = shortcut | apic->dest_logical; switch (vector) { default: diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index f0a173718d9..45c096f605f 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -583,7 +583,7 @@ wakeup_secondary_cpu_via_nmi(int logical_apicid, unsigned long start_eip) /* Target chip */ /* Boot on the stack */ /* Kick the second */ - apic_icr_write(APIC_DM_NMI | apic->apic_destination_logical, logical_apicid); + apic_icr_write(APIC_DM_NMI | apic->dest_logical, logical_apicid); pr_debug("Waiting for send to finish...\n"); send_status = safe_apic_wait_icr_idle(); diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 13ee7dc9b95..7c52840f205 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -70,7 +70,7 @@ struct genapic apic_bigsmp = { .target_cpus = bigsmp_target_cpus, .disable_esr = 1, - .apic_destination_logical = 0, + .dest_logical = 0, .check_apicid_used = check_apicid_used, .check_apicid_present = check_apicid_present, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index d3fe8017e94..53fa1ad8318 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -37,7 +37,7 @@ struct genapic apic_default = { .target_cpus = default_target_cpus, .disable_esr = 0, - .apic_destination_logical = APIC_DEST_LOGICAL, + .dest_logical = APIC_DEST_LOGICAL, .check_apicid_used = check_apicid_used, .check_apicid_present = check_apicid_present, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 61b5da213ce..50fed0225cd 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -113,7 +113,7 @@ struct genapic apic_es7000 = { .target_cpus = es7000_target_cpus, .disable_esr = 1, - .apic_destination_logical = 0, + .dest_logical = 0, .check_apicid_used = check_apicid_used, .check_apicid_present = check_apicid_present, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index f3b7840d227..1fb1b1a4aa0 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -57,7 +57,7 @@ struct genapic apic_numaq = { .target_cpus = numaq_target_cpus, .disable_esr = 1, - .apic_destination_logical = APIC_DEST_LOGICAL, + .dest_logical = APIC_DEST_LOGICAL, .check_apicid_used = check_apicid_used, .check_apicid_present = check_apicid_present, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 95e075b61bd..5c27d4d824e 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -50,7 +50,7 @@ struct genapic apic_summit = { .target_cpus = summit_target_cpus, .disable_esr = 1, - .apic_destination_logical = APIC_DEST_LOGICAL, + .dest_logical = APIC_DEST_LOGICAL, .check_apicid_used = check_apicid_used, .check_apicid_present = check_apicid_present, -- GitLab From d1d7cae8fd54a301a0de531b48451649933ffdcf Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 05:41:42 +0100 Subject: [PATCH 0550/4982] x86, apic: clean up check_apicid*() callbacks Clean up these methods - to make it clearer which function is used in which case. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 9 +++++---- arch/x86/include/asm/es7000/apic.h | 5 +++-- arch/x86/include/asm/mach-default/mach_apic.h | 4 ++-- arch/x86/include/asm/mach-generic/mach_apic.h | 2 -- arch/x86/include/asm/numaq/apic.h | 5 +++-- arch/x86/include/asm/summit/apic.h | 5 +++-- arch/x86/kernel/io_apic.c | 6 +++--- arch/x86/mach-generic/bigsmp.c | 4 ++-- arch/x86/mach-generic/default.c | 4 ++-- arch/x86/mach-generic/es7000.c | 4 ++-- arch/x86/mach-generic/numaq.c | 4 ++-- arch/x86/mach-generic/summit.c | 4 ++-- 12 files changed, 29 insertions(+), 27 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index 7e6e33a6db0..bd52d4d86f0 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h @@ -20,14 +20,15 @@ static inline const cpumask_t *bigsmp_target_cpus(void) #define APIC_DFR_VALUE (APIC_DFR_FLAT) #define NO_BALANCE_IRQ (0) -static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) +static inline unsigned long +bigsmp_check_apicid_used(physid_mask_t bitmap, int apicid) { - return (0); + return 0; } -static inline unsigned long check_apicid_present(int bit) +static inline unsigned long bigsmp_check_apicid_present(int bit) { - return (1); + return 1; } static inline unsigned long calculate_ldr(int cpu) diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index 0d770fce4b2..cd888daa193 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -28,11 +28,12 @@ static inline const cpumask_t *es7000_target_cpus(void) #define APIC_DFR_VALUE (APIC_DFR_FLAT) #define NO_BALANCE_IRQ (0) -static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) +static inline unsigned long +es7000_check_apicid_used(physid_mask_t bitmap, int apicid) { return 0; } -static inline unsigned long check_apicid_present(int bit) +static inline unsigned long es7000_check_apicid_present(int bit) { return physid_isset(bit, phys_cpu_present_map); } diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index 5f8d17fdc96..064bc11a991 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -105,12 +105,12 @@ static inline void vector_allocation_domain(int cpu, struct cpumask *retmask) } #endif -static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) +static inline unsigned long default_check_apicid_used(physid_mask_t bitmap, int apicid) { return physid_isset(apicid, bitmap); } -static inline unsigned long check_apicid_present(int bit) +static inline unsigned long default_check_apicid_present(int bit) { return physid_isset(bit, phys_cpu_present_map); } diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index 00d5fe6e676..e035f88dfcd 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -13,9 +13,7 @@ #define cpu_present_to_apicid (apic->cpu_present_to_apicid) #define apicid_to_cpu_present (apic->apicid_to_cpu_present) #define setup_portio_remap (apic->setup_portio_remap) -#define check_apicid_present (apic->check_apicid_present) #define check_phys_apicid_present (apic->check_phys_apicid_present) -#define check_apicid_used (apic->check_apicid_used) #define cpu_mask_to_apicid (apic->cpu_mask_to_apicid) #define cpu_mask_to_apicid_and (apic->cpu_mask_to_apicid_and) #define vector_allocation_domain (apic->vector_allocation_domain) diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h index 8ecb3b45c6c..571fdaeafaa 100644 --- a/arch/x86/include/asm/numaq/apic.h +++ b/arch/x86/include/asm/numaq/apic.h @@ -14,11 +14,12 @@ static inline const cpumask_t *numaq_target_cpus(void) #define NO_BALANCE_IRQ (1) -static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) +static inline unsigned long +numaq_check_apicid_used(physid_mask_t bitmap, int apicid) { return physid_isset(apicid, bitmap); } -static inline unsigned long check_apicid_present(int bit) +static inline unsigned long numaq_check_apicid_present(int bit) { return physid_isset(bit, phys_cpu_present_map); } diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index 84679e687ad..482038b244b 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h @@ -23,13 +23,14 @@ static inline const cpumask_t *summit_target_cpus(void) return &cpumask_of_cpu(0); } -static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) +static inline unsigned long +summit_check_apicid_used(physid_mask_t bitmap, int apicid) { return 0; } /* we don't use the phys_cpu_present_map to indicate apicid presence */ -static inline unsigned long check_apicid_present(int bit) +static inline unsigned long summit_check_apicid_present(int bit) { return 1; } diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 7f8b32b2089..733ecf17272 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -2135,7 +2135,7 @@ static void __init setup_ioapic_ids_from_mpc(void) * system must have a unique ID or we get lots of nice * 'stuck on smp_invalidate_needed IPI wait' messages. */ - if (check_apicid_used(phys_id_present_map, + if (apic->check_apicid_used(phys_id_present_map, mp_ioapics[apic_id].apicid)) { printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n", apic_id, mp_ioapics[apic_id].apicid); @@ -3878,10 +3878,10 @@ int __init io_apic_get_unique_id(int ioapic, int apic_id) * Every APIC in a system must have a unique ID or we get lots of nice * 'stuck on smp_invalidate_needed IPI wait' messages. */ - if (check_apicid_used(apic_id_map, apic_id)) { + if (apic->check_apicid_used(apic_id_map, apic_id)) { for (i = 0; i < get_physical_broadcast(); i++) { - if (!check_apicid_used(apic_id_map, i)) + if (!apic->check_apicid_used(apic_id_map, i)) break; } diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 7c52840f205..aa8443f6c0f 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -71,8 +71,8 @@ struct genapic apic_bigsmp = { .target_cpus = bigsmp_target_cpus, .disable_esr = 1, .dest_logical = 0, - .check_apicid_used = check_apicid_used, - .check_apicid_present = check_apicid_present, + .check_apicid_used = bigsmp_check_apicid_used, + .check_apicid_present = bigsmp_check_apicid_present, .no_balance_irq = NO_BALANCE_IRQ, .no_ioapic_check = 0, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index 53fa1ad8318..47f6b5b06ba 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -38,8 +38,8 @@ struct genapic apic_default = { .target_cpus = default_target_cpus, .disable_esr = 0, .dest_logical = APIC_DEST_LOGICAL, - .check_apicid_used = check_apicid_used, - .check_apicid_present = check_apicid_present, + .check_apicid_used = default_check_apicid_used, + .check_apicid_present = default_check_apicid_present, .no_balance_irq = NO_BALANCE_IRQ, .no_ioapic_check = 0, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 50fed0225cd..5633f3296e1 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -114,8 +114,8 @@ struct genapic apic_es7000 = { .target_cpus = es7000_target_cpus, .disable_esr = 1, .dest_logical = 0, - .check_apicid_used = check_apicid_used, - .check_apicid_present = check_apicid_present, + .check_apicid_used = es7000_check_apicid_used, + .check_apicid_present = es7000_check_apicid_present, .no_balance_irq = NO_BALANCE_IRQ, .no_ioapic_check = 0, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 1fb1b1a4aa0..d85206d8e4a 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -58,8 +58,8 @@ struct genapic apic_numaq = { .target_cpus = numaq_target_cpus, .disable_esr = 1, .dest_logical = APIC_DEST_LOGICAL, - .check_apicid_used = check_apicid_used, - .check_apicid_present = check_apicid_present, + .check_apicid_used = numaq_check_apicid_used, + .check_apicid_present = numaq_check_apicid_present, .no_balance_irq = NO_BALANCE_IRQ, .no_ioapic_check = 0, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 5c27d4d824e..f54cf73d3ed 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -51,8 +51,8 @@ struct genapic apic_summit = { .target_cpus = summit_target_cpus, .disable_esr = 1, .dest_logical = APIC_DEST_LOGICAL, - .check_apicid_used = check_apicid_used, - .check_apicid_present = check_apicid_present, + .check_apicid_used = summit_check_apicid_used, + .check_apicid_present = summit_check_apicid_present, .no_balance_irq = NO_BALANCE_IRQ, .no_ioapic_check = 0, -- GitLab From 2e867b17cc02e1799f18126af0ddd7b63dd8f6f4 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 05:57:56 +0100 Subject: [PATCH 0551/4982] x86, apic: remove no_balance_irq and no_ioapic_check flags These flags are completely unused. (the in-kernel IRQ balancer has been removed from the upstream kernel.) Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 1 - arch/x86/include/asm/es7000/apic.h | 2 -- arch/x86/include/asm/genapic.h | 3 --- arch/x86/include/asm/mach-default/mach_apic.h | 2 -- arch/x86/include/asm/mach-generic/mach_apic.h | 1 - arch/x86/include/asm/numaq/apic.h | 2 -- arch/x86/include/asm/summit/apic.h | 2 -- arch/x86/kernel/genapic_flat_64.c | 6 ------ arch/x86/kernel/genx2apic_cluster.c | 3 --- arch/x86/kernel/genx2apic_phys.c | 3 --- arch/x86/kernel/genx2apic_uv_x.c | 3 --- arch/x86/mach-generic/bigsmp.c | 3 --- arch/x86/mach-generic/default.c | 3 --- arch/x86/mach-generic/es7000.c | 4 ---- arch/x86/mach-generic/numaq.c | 3 --- arch/x86/mach-generic/summit.c | 3 --- 16 files changed, 44 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index bd52d4d86f0..916451252b3 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h @@ -18,7 +18,6 @@ static inline const cpumask_t *bigsmp_target_cpus(void) } #define APIC_DFR_VALUE (APIC_DFR_FLAT) -#define NO_BALANCE_IRQ (0) static inline unsigned long bigsmp_check_apicid_used(physid_mask_t bitmap, int apicid) diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index cd888daa193..847008a7702 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -23,10 +23,8 @@ static inline const cpumask_t *es7000_target_cpus(void) #define APIC_DFR_VALUE_CLUSTER (APIC_DFR_CLUSTER) #define INT_DELIVERY_MODE_CLUSTER (dest_LowestPrio) #define INT_DEST_MODE_CLUSTER (1) /* logical delivery broadcast to all procs */ -#define NO_BALANCE_IRQ_CLUSTER (1) #define APIC_DFR_VALUE (APIC_DFR_FLAT) -#define NO_BALANCE_IRQ (0) static inline unsigned long es7000_check_apicid_used(physid_mask_t bitmap, int apicid) diff --git a/arch/x86/include/asm/genapic.h b/arch/x86/include/asm/genapic.h index f9d1ec018fd..661898c2229 100644 --- a/arch/x86/include/asm/genapic.h +++ b/arch/x86/include/asm/genapic.h @@ -34,9 +34,6 @@ struct genapic { unsigned long (*check_apicid_used)(physid_mask_t bitmap, int apicid); unsigned long (*check_apicid_present)(int apicid); - int no_balance_irq; - int no_ioapic_check; - void (*vector_allocation_domain)(int cpu, struct cpumask *retmask); void (*init_apic_ldr)(void); diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index 064bc11a991..8adccf8ee47 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -17,8 +17,6 @@ static inline const struct cpumask *default_target_cpus(void) #endif } -#define NO_BALANCE_IRQ (0) - #ifdef CONFIG_X86_64 #include #define init_apic_ldr (apic->init_apic_ldr) diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index e035f88dfcd..4cb9e2b99e3 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -3,7 +3,6 @@ #include -#define NO_BALANCE_IRQ (apic->no_balance_irq) #define init_apic_ldr (apic->init_apic_ldr) #define ioapic_phys_id_map (apic->ioapic_phys_id_map) #define setup_apic_routing (apic->setup_apic_routing) diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h index 571fdaeafaa..defee3496ad 100644 --- a/arch/x86/include/asm/numaq/apic.h +++ b/arch/x86/include/asm/numaq/apic.h @@ -12,8 +12,6 @@ static inline const cpumask_t *numaq_target_cpus(void) return &CPU_MASK_ALL; } -#define NO_BALANCE_IRQ (1) - static inline unsigned long numaq_check_apicid_used(physid_mask_t bitmap, int apicid) { diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index 482038b244b..51df002ecf4 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h @@ -4,8 +4,6 @@ #include #include -#define NO_BALANCE_IRQ (0) - /* In clustered mode, the high nibble of APIC ID is a cluster number. * The low nibble is a 4-bit bitmap. */ #define XAPIC_DEST_CPUS_SHIFT 4 diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index d22cbdaee20..9446f372a16 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -189,9 +189,6 @@ struct genapic apic_flat = { .check_apicid_used = NULL, .check_apicid_present = NULL, - .no_balance_irq = 0, - .no_ioapic_check = 0, - .vector_allocation_domain = flat_vector_allocation_domain, .init_apic_ldr = flat_init_apic_ldr, @@ -335,9 +332,6 @@ struct genapic apic_physflat = { .check_apicid_used = NULL, .check_apicid_present = NULL, - .no_balance_irq = 0, - .no_ioapic_check = 0, - .vector_allocation_domain = physflat_vector_allocation_domain, /* not needed, but shouldn't hurt: */ .init_apic_ldr = flat_init_apic_ldr, diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c index b91a48eae52..2eeca6e744a 100644 --- a/arch/x86/kernel/genx2apic_cluster.c +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -191,9 +191,6 @@ struct genapic apic_x2apic_cluster = { .check_apicid_used = NULL, .check_apicid_present = NULL, - .no_balance_irq = 0, - .no_ioapic_check = 0, - .vector_allocation_domain = x2apic_vector_allocation_domain, .init_apic_ldr = init_x2apic_ldr, diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c index f070e86af0f..be0ee3e56ef 100644 --- a/arch/x86/kernel/genx2apic_phys.c +++ b/arch/x86/kernel/genx2apic_phys.c @@ -187,9 +187,6 @@ struct genapic apic_x2apic_phys = { .check_apicid_used = NULL, .check_apicid_present = NULL, - .no_balance_irq = 0, - .no_ioapic_check = 0, - .vector_allocation_domain = x2apic_vector_allocation_domain, .init_apic_ldr = init_x2apic_ldr, diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index c8a89158679..68b423f3da9 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -252,9 +252,6 @@ struct genapic apic_x2apic_uv_x = { .check_apicid_used = NULL, .check_apicid_present = NULL, - .no_balance_irq = 0, - .no_ioapic_check = 0, - .vector_allocation_domain = uv_vector_allocation_domain, .init_apic_ldr = uv_init_apic_ldr, diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index aa8443f6c0f..6da251aa9f4 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -74,9 +74,6 @@ struct genapic apic_bigsmp = { .check_apicid_used = bigsmp_check_apicid_used, .check_apicid_present = bigsmp_check_apicid_present, - .no_balance_irq = NO_BALANCE_IRQ, - .no_ioapic_check = 0, - .vector_allocation_domain = vector_allocation_domain, .init_apic_ldr = init_apic_ldr, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index 47f6b5b06ba..e89e8c9dd68 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -41,9 +41,6 @@ struct genapic apic_default = { .check_apicid_used = default_check_apicid_used, .check_apicid_present = default_check_apicid_present, - .no_balance_irq = NO_BALANCE_IRQ, - .no_ioapic_check = 0, - .vector_allocation_domain = vector_allocation_domain, .init_apic_ldr = init_apic_ldr, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 5633f3296e1..8e9eeecf7e2 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -23,7 +23,6 @@ void __init es7000_update_genapic_to_cluster(void) apic->target_cpus = target_cpus_cluster; apic->irq_delivery_mode = INT_DELIVERY_MODE_CLUSTER; apic->irq_dest_mode = INT_DEST_MODE_CLUSTER; - apic->no_balance_irq = NO_BALANCE_IRQ_CLUSTER; apic->init_apic_ldr = init_apic_ldr_cluster; @@ -117,9 +116,6 @@ struct genapic apic_es7000 = { .check_apicid_used = es7000_check_apicid_used, .check_apicid_present = es7000_check_apicid_present, - .no_balance_irq = NO_BALANCE_IRQ, - .no_ioapic_check = 0, - .vector_allocation_domain = vector_allocation_domain, .init_apic_ldr = init_apic_ldr, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index d85206d8e4a..f909189fee3 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -61,9 +61,6 @@ struct genapic apic_numaq = { .check_apicid_used = numaq_check_apicid_used, .check_apicid_present = numaq_check_apicid_present, - .no_balance_irq = NO_BALANCE_IRQ, - .no_ioapic_check = 0, - .vector_allocation_domain = vector_allocation_domain, .init_apic_ldr = init_apic_ldr, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index f54cf73d3ed..99a9bea8d14 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -54,9 +54,6 @@ struct genapic apic_summit = { .check_apicid_used = summit_check_apicid_used, .check_apicid_present = summit_check_apicid_present, - .no_balance_irq = NO_BALANCE_IRQ, - .no_ioapic_check = 0, - .vector_allocation_domain = vector_allocation_domain, .init_apic_ldr = init_apic_ldr, -- GitLab From e2d40b1878bd13ca1028ddd299c48e4821ac3535 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 06:50:47 +0100 Subject: [PATCH 0552/4982] x86, apic: clean up ->vector_allocation_domain() - separate the namespace - remove macros - move the default vector-allocation-domain to mach-generic - fix whitespace damage Signed-off-by: Ingo Molnar --- arch/x86/include/asm/mach-default/mach_apic.h | 13 ------------- arch/x86/include/asm/mach-generic/mach_apic.h | 1 - arch/x86/kernel/io_apic.c | 2 +- arch/x86/mach-generic/bigsmp.c | 4 ++-- arch/x86/mach-generic/default.c | 16 +++++++++++++++- arch/x86/mach-generic/es7000.c | 4 ++-- arch/x86/mach-generic/numaq.c | 4 ++-- arch/x86/mach-generic/summit.c | 4 ++-- 8 files changed, 24 insertions(+), 24 deletions(-) diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index 8adccf8ee47..9c56542644c 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -23,7 +23,6 @@ static inline const struct cpumask *default_target_cpus(void) #define cpu_mask_to_apicid (apic->cpu_mask_to_apicid) #define cpu_mask_to_apicid_and (apic->cpu_mask_to_apicid_and) #define phys_pkg_id (apic->phys_pkg_id) -#define vector_allocation_domain (apic->vector_allocation_domain) #define read_apic_id() (GET_APIC_ID(apic_read(APIC_ID))) #define send_IPI_self (apic->send_IPI_self) #define wakeup_secondary_cpu (apic->wakeup_cpu) @@ -89,18 +88,6 @@ static inline int apicid_to_node(int logical_apicid) #endif } -static inline void vector_allocation_domain(int cpu, struct cpumask *retmask) -{ - /* Careful. Some cpus do not strictly honor the set of cpus - * specified in the interrupt destination when using lowest - * priority interrupt delivery mode. - * - * In particular there was a hyperthreading cpu observed to - * deliver interrupts to the wrong hyperthread when only one - * hyperthread was specified in the interrupt desitination. - */ - *retmask = (cpumask_t) { { [0] = APIC_ALL_CPUS } }; -} #endif static inline unsigned long default_check_apicid_used(physid_mask_t bitmap, int apicid) diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index 4cb9e2b99e3..e94881af962 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -15,7 +15,6 @@ #define check_phys_apicid_present (apic->check_phys_apicid_present) #define cpu_mask_to_apicid (apic->cpu_mask_to_apicid) #define cpu_mask_to_apicid_and (apic->cpu_mask_to_apicid_and) -#define vector_allocation_domain (apic->vector_allocation_domain) #define enable_apic_mode (apic->enable_apic_mode) #define phys_pkg_id (apic->phys_pkg_id) #define wakeup_secondary_cpu (apic->wakeup_cpu) diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 733ecf17272..49899e06624 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -1316,7 +1316,7 @@ __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask) int new_cpu; int vector, offset; - vector_allocation_domain(cpu, tmp_mask); + apic->vector_allocation_domain(cpu, tmp_mask); vector = current_vector; offset = current_offset; diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 6da251aa9f4..391cc99cd21 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -42,7 +42,7 @@ static const struct dmi_system_id bigsmp_dmi_table[] = { { } }; -static void vector_allocation_domain(int cpu, cpumask_t *retmask) +static void bigsmp_vector_allocation_domain(int cpu, cpumask_t *retmask) { cpus_clear(*retmask); cpu_set(cpu, *retmask); @@ -74,7 +74,7 @@ struct genapic apic_bigsmp = { .check_apicid_used = bigsmp_check_apicid_used, .check_apicid_present = bigsmp_check_apicid_present, - .vector_allocation_domain = vector_allocation_domain, + .vector_allocation_domain = bigsmp_vector_allocation_domain, .init_apic_ldr = init_apic_ldr, .ioapic_phys_id_map = ioapic_phys_id_map, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index e89e8c9dd68..6adc3c69a3c 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -18,6 +18,20 @@ #include #include +static void default_vector_allocation_domain(int cpu, struct cpumask *retmask) +{ + /* + * Careful. Some cpus do not strictly honor the set of cpus + * specified in the interrupt destination when using lowest + * priority interrupt delivery mode. + * + * In particular there was a hyperthreading cpu observed to + * deliver interrupts to the wrong hyperthread when only one + * hyperthread was specified in the interrupt desitination. + */ + *retmask = (cpumask_t) { { [0] = APIC_ALL_CPUS } }; +} + /* should be called last. */ static int probe_default(void) { @@ -41,7 +55,7 @@ struct genapic apic_default = { .check_apicid_used = default_check_apicid_used, .check_apicid_present = default_check_apicid_present, - .vector_allocation_domain = vector_allocation_domain, + .vector_allocation_domain = default_vector_allocation_domain, .init_apic_ldr = init_apic_ldr, .ioapic_phys_id_map = ioapic_phys_id_map, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 8e9eeecf7e2..bc1f21cd6a4 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -86,7 +86,7 @@ static int __init es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id) } #endif -static void vector_allocation_domain(int cpu, cpumask_t *retmask) +static void es7000_vector_allocation_domain(int cpu, cpumask_t *retmask) { /* Careful. Some cpus do not strictly honor the set of cpus * specified in the interrupt destination when using lowest @@ -116,7 +116,7 @@ struct genapic apic_es7000 = { .check_apicid_used = es7000_check_apicid_used, .check_apicid_present = es7000_check_apicid_present, - .vector_allocation_domain = vector_allocation_domain, + .vector_allocation_domain = es7000_vector_allocation_domain, .init_apic_ldr = init_apic_ldr, .ioapic_phys_id_map = ioapic_phys_id_map, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index f909189fee3..712882f48c4 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -31,7 +31,7 @@ static int probe_numaq(void) return found_numaq; } -static void vector_allocation_domain(int cpu, cpumask_t *retmask) +static void numaq_vector_allocation_domain(int cpu, cpumask_t *retmask) { /* Careful. Some cpus do not strictly honor the set of cpus * specified in the interrupt destination when using lowest @@ -61,7 +61,7 @@ struct genapic apic_numaq = { .check_apicid_used = numaq_check_apicid_used, .check_apicid_present = numaq_check_apicid_present, - .vector_allocation_domain = vector_allocation_domain, + .vector_allocation_domain = numaq_vector_allocation_domain, .init_apic_ldr = init_apic_ldr, .ioapic_phys_id_map = ioapic_phys_id_map, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 99a9bea8d14..1834887b94a 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -24,7 +24,7 @@ static int probe_summit(void) return 0; } -static void vector_allocation_domain(int cpu, cpumask_t *retmask) +static void summit_vector_allocation_domain(int cpu, cpumask_t *retmask) { /* Careful. Some cpus do not strictly honor the set of cpus * specified in the interrupt destination when using lowest @@ -54,7 +54,7 @@ struct genapic apic_summit = { .check_apicid_used = summit_check_apicid_used, .check_apicid_present = summit_check_apicid_present, - .vector_allocation_domain = vector_allocation_domain, + .vector_allocation_domain = summit_vector_allocation_domain, .init_apic_ldr = init_apic_ldr, .ioapic_phys_id_map = ioapic_phys_id_map, -- GitLab From a5c4329622a3437adef4b2a4288d127957743c97 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 06:50:47 +0100 Subject: [PATCH 0553/4982] x86, apic: clean up ->init_apic_ldr() - separate the namespace - remove macros Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 2 +- arch/x86/include/asm/es7000/apic.h | 4 ++-- arch/x86/include/asm/mach-default/mach_apic.h | 3 +-- arch/x86/include/asm/mach-generic/mach_apic.h | 1 - arch/x86/include/asm/numaq/apic.h | 2 +- arch/x86/include/asm/summit/apic.h | 2 +- arch/x86/kernel/apic.c | 2 +- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 4 ++-- arch/x86/mach-generic/numaq.c | 2 +- arch/x86/mach-generic/summit.c | 2 +- 12 files changed, 13 insertions(+), 15 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index 916451252b3..81941308299 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h @@ -46,7 +46,7 @@ static inline unsigned long calculate_ldr(int cpu) * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel * document number 292116). So here it goes... */ -static inline void init_apic_ldr(void) +static inline void bigsmp_init_apic_ldr(void) { unsigned long val; int cpu = smp_processor_id(); diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index 847008a7702..06f5757bf7a 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -52,7 +52,7 @@ static inline unsigned long calculate_ldr(int cpu) * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel * document number 292116). So here it goes... */ -static inline void init_apic_ldr_cluster(void) +static inline void es7000_init_apic_ldr_cluster(void) { unsigned long val; int cpu = smp_processor_id(); @@ -62,7 +62,7 @@ static inline void init_apic_ldr_cluster(void) apic_write(APIC_LDR, val); } -static inline void init_apic_ldr(void) +static inline void es7000_init_apic_ldr(void) { unsigned long val; int cpu = smp_processor_id(); diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index 9c56542644c..23e0a2da3a9 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -19,7 +19,6 @@ static inline const struct cpumask *default_target_cpus(void) #ifdef CONFIG_X86_64 #include -#define init_apic_ldr (apic->init_apic_ldr) #define cpu_mask_to_apicid (apic->cpu_mask_to_apicid) #define cpu_mask_to_apicid_and (apic->cpu_mask_to_apicid_and) #define phys_pkg_id (apic->phys_pkg_id) @@ -36,7 +35,7 @@ extern void setup_apic_routing(void); * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel * document number 292116). So here it goes... */ -static inline void init_apic_ldr(void) +static inline void default_init_apic_ldr(void) { unsigned long val; diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index e94881af962..8e51f416394 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -3,7 +3,6 @@ #include -#define init_apic_ldr (apic->init_apic_ldr) #define ioapic_phys_id_map (apic->ioapic_phys_id_map) #define setup_apic_routing (apic->setup_apic_routing) #define multi_timer_check (apic->multi_timer_check) diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h index defee3496ad..802297489a3 100644 --- a/arch/x86/include/asm/numaq/apic.h +++ b/arch/x86/include/asm/numaq/apic.h @@ -28,7 +28,7 @@ static inline int numaq_apic_id_registered(void) return 1; } -static inline void init_apic_ldr(void) +static inline void numaq_init_apic_ldr(void) { /* Already done in NUMA-Q firmware */ } diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index 51df002ecf4..9108c89fe88 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h @@ -37,7 +37,7 @@ static inline unsigned long summit_check_apicid_present(int bit) extern u8 cpu_2_logical_apicid[]; -static inline void init_apic_ldr(void) +static inline void summit_init_apic_ldr(void) { unsigned long val, id; int count = 0; diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 3853ed76c88..b7077936ac0 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -1179,7 +1179,7 @@ void __cpuinit setup_local_APIC(void) * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel * document number 292116). So here it goes... */ - init_apic_ldr(); + apic->init_apic_ldr(); /* * Set Task Priority to 'accept all'. We never change this diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 391cc99cd21..7b7fc471a3f 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -75,7 +75,7 @@ struct genapic apic_bigsmp = { .check_apicid_present = bigsmp_check_apicid_present, .vector_allocation_domain = bigsmp_vector_allocation_domain, - .init_apic_ldr = init_apic_ldr, + .init_apic_ldr = bigsmp_init_apic_ldr, .ioapic_phys_id_map = ioapic_phys_id_map, .setup_apic_routing = setup_apic_routing, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index 6adc3c69a3c..633e8482af2 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -56,7 +56,7 @@ struct genapic apic_default = { .check_apicid_present = default_check_apicid_present, .vector_allocation_domain = default_vector_allocation_domain, - .init_apic_ldr = init_apic_ldr, + .init_apic_ldr = default_init_apic_ldr, .ioapic_phys_id_map = ioapic_phys_id_map, .setup_apic_routing = setup_apic_routing, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index bc1f21cd6a4..b70833e3597 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -24,7 +24,7 @@ void __init es7000_update_genapic_to_cluster(void) apic->irq_delivery_mode = INT_DELIVERY_MODE_CLUSTER; apic->irq_dest_mode = INT_DEST_MODE_CLUSTER; - apic->init_apic_ldr = init_apic_ldr_cluster; + apic->init_apic_ldr = es7000_init_apic_ldr_cluster; apic->cpu_mask_to_apicid = cpu_mask_to_apicid_cluster; } @@ -117,7 +117,7 @@ struct genapic apic_es7000 = { .check_apicid_present = es7000_check_apicid_present, .vector_allocation_domain = es7000_vector_allocation_domain, - .init_apic_ldr = init_apic_ldr, + .init_apic_ldr = es7000_init_apic_ldr, .ioapic_phys_id_map = ioapic_phys_id_map, .setup_apic_routing = setup_apic_routing, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 712882f48c4..a06fda57928 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -62,7 +62,7 @@ struct genapic apic_numaq = { .check_apicid_present = numaq_check_apicid_present, .vector_allocation_domain = numaq_vector_allocation_domain, - .init_apic_ldr = init_apic_ldr, + .init_apic_ldr = numaq_init_apic_ldr, .ioapic_phys_id_map = ioapic_phys_id_map, .setup_apic_routing = setup_apic_routing, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 1834887b94a..36c552fa427 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -55,7 +55,7 @@ struct genapic apic_summit = { .check_apicid_present = summit_check_apicid_present, .vector_allocation_domain = summit_vector_allocation_domain, - .init_apic_ldr = init_apic_ldr, + .init_apic_ldr = summit_init_apic_ldr, .ioapic_phys_id_map = ioapic_phys_id_map, .setup_apic_routing = setup_apic_routing, -- GitLab From d190cb87c4503014353f2310c4bfa2268fa7111d Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 06:50:47 +0100 Subject: [PATCH 0554/4982] x86, apic: clean up ->ioapic_phys_id_map() - separate the namespace - remove macros Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 2 +- arch/x86/include/asm/es7000/apic.h | 2 +- arch/x86/include/asm/mach-default/mach_apic.h | 2 +- arch/x86/include/asm/mach-generic/mach_apic.h | 1 - arch/x86/include/asm/numaq/apic.h | 2 +- arch/x86/include/asm/summit/apic.h | 3 ++- arch/x86/kernel/io_apic.c | 4 ++-- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 2 +- arch/x86/mach-generic/numaq.c | 2 +- arch/x86/mach-generic/summit.c | 2 +- 12 files changed, 13 insertions(+), 13 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index 81941308299..05116d5487d 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h @@ -94,7 +94,7 @@ static inline int cpu_to_logical_apicid(int cpu) return cpu_physical_id(cpu); } -static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map) +static inline physid_mask_t bigsmp_ioapic_phys_id_map(physid_mask_t phys_map) { /* For clustered we don't have a good way to do this yet - hack */ return physids_promote(0xFFL); diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index 06f5757bf7a..db3e652f0f7 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -125,7 +125,7 @@ static inline int cpu_to_logical_apicid(int cpu) #endif } -static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map) +static inline physid_mask_t es7000_ioapic_phys_id_map(physid_mask_t phys_map) { /* For clustered we don't have a good way to do this yet - hack */ return physids_promote(0xff); diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index 23e0a2da3a9..7abdaae06f2 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -99,7 +99,7 @@ static inline unsigned long default_check_apicid_present(int bit) return physid_isset(bit, phys_cpu_present_map); } -static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map) +static inline physid_mask_t default_ioapic_phys_id_map(physid_mask_t phys_map) { return phys_map; } diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index 8e51f416394..c1c96e6bb18 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -3,7 +3,6 @@ #include -#define ioapic_phys_id_map (apic->ioapic_phys_id_map) #define setup_apic_routing (apic->setup_apic_routing) #define multi_timer_check (apic->multi_timer_check) #define apicid_to_node (apic->apicid_to_node) diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h index 802297489a3..dc7499b9262 100644 --- a/arch/x86/include/asm/numaq/apic.h +++ b/arch/x86/include/asm/numaq/apic.h @@ -48,7 +48,7 @@ static inline int multi_timer_check(int apic, int irq) return apic != 0 && irq == 0; } -static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map) +static inline physid_mask_t numaq_ioapic_phys_id_map(physid_mask_t phys_map) { /* We don't have a good way to do this yet - hack */ return physids_promote(0xFUL); diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index 9108c89fe88..4dafb58f930 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h @@ -109,7 +109,8 @@ static inline int cpu_present_to_apicid(int mps_cpu) return BAD_APICID; } -static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_id_map) +static inline physid_mask_t + summit_ioapic_phys_id_map(physid_mask_t phys_id_map) { /* For clustered we don't have a good way to do this yet - hack */ return physids_promote(0x0F); diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 49899e06624..db79ad9a764 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -2108,7 +2108,7 @@ static void __init setup_ioapic_ids_from_mpc(void) * This is broken; anything with a real cpu count has to * circumvent this idiocy regardless. */ - phys_id_present_map = ioapic_phys_id_map(phys_cpu_present_map); + phys_id_present_map = apic->ioapic_phys_id_map(phys_cpu_present_map); /* * Set the IOAPIC ID to the value stored in the MPC table. @@ -3862,7 +3862,7 @@ int __init io_apic_get_unique_id(int ioapic, int apic_id) */ if (physids_empty(apic_id_map)) - apic_id_map = ioapic_phys_id_map(phys_cpu_present_map); + apic_id_map = apic->ioapic_phys_id_map(phys_cpu_present_map); spin_lock_irqsave(&ioapic_lock, flags); reg_00.raw = io_apic_read(ioapic, 0); diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 7b7fc471a3f..f2a3418d0cc 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -77,7 +77,7 @@ struct genapic apic_bigsmp = { .vector_allocation_domain = bigsmp_vector_allocation_domain, .init_apic_ldr = bigsmp_init_apic_ldr, - .ioapic_phys_id_map = ioapic_phys_id_map, + .ioapic_phys_id_map = bigsmp_ioapic_phys_id_map, .setup_apic_routing = setup_apic_routing, .multi_timer_check = multi_timer_check, .apicid_to_node = apicid_to_node, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index 633e8482af2..c403f3d9300 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -58,7 +58,7 @@ struct genapic apic_default = { .vector_allocation_domain = default_vector_allocation_domain, .init_apic_ldr = default_init_apic_ldr, - .ioapic_phys_id_map = ioapic_phys_id_map, + .ioapic_phys_id_map = default_ioapic_phys_id_map, .setup_apic_routing = setup_apic_routing, .multi_timer_check = multi_timer_check, .apicid_to_node = apicid_to_node, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index b70833e3597..ce09baf0872 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -119,7 +119,7 @@ struct genapic apic_es7000 = { .vector_allocation_domain = es7000_vector_allocation_domain, .init_apic_ldr = es7000_init_apic_ldr, - .ioapic_phys_id_map = ioapic_phys_id_map, + .ioapic_phys_id_map = es7000_ioapic_phys_id_map, .setup_apic_routing = setup_apic_routing, .multi_timer_check = multi_timer_check, .apicid_to_node = apicid_to_node, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index a06fda57928..5d98f18a0bd 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -64,7 +64,7 @@ struct genapic apic_numaq = { .vector_allocation_domain = numaq_vector_allocation_domain, .init_apic_ldr = numaq_init_apic_ldr, - .ioapic_phys_id_map = ioapic_phys_id_map, + .ioapic_phys_id_map = numaq_ioapic_phys_id_map, .setup_apic_routing = setup_apic_routing, .multi_timer_check = multi_timer_check, .apicid_to_node = apicid_to_node, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 36c552fa427..6abdd53a01c 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -57,7 +57,7 @@ struct genapic apic_summit = { .vector_allocation_domain = summit_vector_allocation_domain, .init_apic_ldr = summit_init_apic_ldr, - .ioapic_phys_id_map = ioapic_phys_id_map, + .ioapic_phys_id_map = summit_ioapic_phys_id_map, .setup_apic_routing = setup_apic_routing, .multi_timer_check = multi_timer_check, .apicid_to_node = apicid_to_node, -- GitLab From 72ce016583916fb7ffcbaa6a3e1f8f731b79a865 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 06:50:47 +0100 Subject: [PATCH 0555/4982] x86, apic: clean up ->setup_apic_routing() - separate the namespace - remove macros - remove namespace clash on 64-bit Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 2 +- arch/x86/include/asm/es7000/apic.h | 2 +- arch/x86/include/asm/genapic.h | 2 +- arch/x86/include/asm/mach-default/mach_apic.h | 4 ++-- arch/x86/include/asm/mach-generic/mach_apic.h | 1 - arch/x86/include/asm/numaq/apic.h | 2 +- arch/x86/include/asm/summit/apic.h | 2 +- arch/x86/kernel/acpi/boot.c | 5 ++--- arch/x86/kernel/apic.c | 2 +- arch/x86/kernel/genapic_64.c | 2 +- arch/x86/kernel/mpparse.c | 6 +++--- arch/x86/kernel/smpboot.c | 2 +- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 2 +- arch/x86/mach-generic/numaq.c | 2 +- arch/x86/mach-generic/summit.c | 2 +- 17 files changed, 20 insertions(+), 22 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index 05116d5487d..321ea47b5dd 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h @@ -56,7 +56,7 @@ static inline void bigsmp_init_apic_ldr(void) apic_write(APIC_LDR, val); } -static inline void setup_apic_routing(void) +static inline void bigsmp_setup_apic_routing(void) { printk("Enabling APIC mode: %s. Using %d I/O APICs\n", "Physflat", nr_ioapics); diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index db3e652f0f7..f1183000a94 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -73,7 +73,7 @@ static inline void es7000_init_apic_ldr(void) } extern int apic_version [MAX_APICS]; -static inline void setup_apic_routing(void) +static inline void es7000_setup_apic_routing(void) { int apic = per_cpu(x86_bios_cpu_apicid, smp_processor_id()); printk("Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n", diff --git a/arch/x86/include/asm/genapic.h b/arch/x86/include/asm/genapic.h index 661898c2229..38b1202316f 100644 --- a/arch/x86/include/asm/genapic.h +++ b/arch/x86/include/asm/genapic.h @@ -107,7 +107,7 @@ extern void apic_send_IPI_self(int vector); extern struct genapic apic_x2apic_uv_x; DECLARE_PER_CPU(int, x2apic_extra_bits); -extern void setup_apic_routing(void); +extern void default_setup_apic_routing(void); #endif #endif /* _ASM_X86_GENAPIC_64_H */ diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index 7abdaae06f2..d4467746304 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -25,7 +25,7 @@ static inline const struct cpumask *default_target_cpus(void) #define read_apic_id() (GET_APIC_ID(apic_read(APIC_ID))) #define send_IPI_self (apic->send_IPI_self) #define wakeup_secondary_cpu (apic->wakeup_cpu) -extern void setup_apic_routing(void); +extern void default_setup_apic_routing(void); #else #define wakeup_secondary_cpu wakeup_secondary_cpu_via_init /* @@ -70,7 +70,7 @@ static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) return cpuid_apic >> index_msb; } -static inline void setup_apic_routing(void) +static inline void default_setup_apic_routing(void) { #ifdef CONFIG_X86_IO_APIC printk("Enabling APIC mode: %s. Using %d I/O APICs\n", diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index c1c96e6bb18..ddf369248ab 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -3,7 +3,6 @@ #include -#define setup_apic_routing (apic->setup_apic_routing) #define multi_timer_check (apic->multi_timer_check) #define apicid_to_node (apic->apicid_to_node) #define cpu_to_logical_apicid (apic->cpu_to_logical_apicid) diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h index dc7499b9262..2feb7e72e9e 100644 --- a/arch/x86/include/asm/numaq/apic.h +++ b/arch/x86/include/asm/numaq/apic.h @@ -33,7 +33,7 @@ static inline void numaq_init_apic_ldr(void) /* Already done in NUMA-Q firmware */ } -static inline void setup_apic_routing(void) +static inline void numaq_setup_apic_routing(void) { printk("Enabling APIC mode: %s. Using %d I/O APICs\n", "NUMA-Q", nr_ioapics); diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index 4dafb58f930..7ec2696bc9a 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h @@ -74,7 +74,7 @@ static inline int summit_apic_id_registered(void) return 1; } -static inline void setup_apic_routing(void) +static inline void summit_setup_apic_routing(void) { printk("Enabling APIC mode: Summit. Using %d I/O APICs\n", nr_ioapics); diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 314fe0dddef..539163161a4 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -1360,9 +1360,8 @@ static void __init acpi_process_madt(void) acpi_ioapic = 1; smp_found_config = 1; -#ifdef CONFIG_X86_32 - setup_apic_routing(); -#endif + if (apic->setup_apic_routing) + apic->setup_apic_routing(); } } if (error == -EINVAL) { diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index b7077936ac0..fcbcc03cd4b 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -1625,7 +1625,7 @@ int __init APIC_init_uniprocessor(void) enable_IR_x2apic(); #endif #ifdef CONFIG_X86_64 - setup_apic_routing(); + default_setup_apic_routing(); #endif verify_local_APIC(); diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c index 060945b8eec..d57d2138f07 100644 --- a/arch/x86/kernel/genapic_64.c +++ b/arch/x86/kernel/genapic_64.c @@ -44,7 +44,7 @@ static struct genapic *apic_probe[] __initdata = { /* * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode. */ -void __init setup_apic_routing(void) +void __init default_setup_apic_routing(void) { if (apic == &apic_x2apic_phys || apic == &apic_x2apic_cluster) { if (!intr_remapping_enabled) diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index fa6bb263892..c8a534a16d9 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -390,9 +390,9 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) generic_bigsmp_probe(); #endif -#ifdef CONFIG_X86_32 - setup_apic_routing(); -#endif + if (apic->setup_apic_routing) + apic->setup_apic_routing(); + if (!num_processors) printk(KERN_ERR "MPTABLE: no processors registered!\n"); return num_processors; diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 45c096f605f..3791b4ae567 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1128,7 +1128,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) #ifdef CONFIG_X86_64 enable_IR_x2apic(); - setup_apic_routing(); + default_setup_apic_routing(); #endif if (smp_sanity_check(max_cpus) < 0) { diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index f2a3418d0cc..ad3837a59bd 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -78,7 +78,7 @@ struct genapic apic_bigsmp = { .init_apic_ldr = bigsmp_init_apic_ldr, .ioapic_phys_id_map = bigsmp_ioapic_phys_id_map, - .setup_apic_routing = setup_apic_routing, + .setup_apic_routing = bigsmp_setup_apic_routing, .multi_timer_check = multi_timer_check, .apicid_to_node = apicid_to_node, .cpu_to_logical_apicid = cpu_to_logical_apicid, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index c403f3d9300..67f287fc12d 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -59,7 +59,7 @@ struct genapic apic_default = { .init_apic_ldr = default_init_apic_ldr, .ioapic_phys_id_map = default_ioapic_phys_id_map, - .setup_apic_routing = setup_apic_routing, + .setup_apic_routing = default_setup_apic_routing, .multi_timer_check = multi_timer_check, .apicid_to_node = apicid_to_node, .cpu_to_logical_apicid = cpu_to_logical_apicid, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index ce09baf0872..f6117293946 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -120,7 +120,7 @@ struct genapic apic_es7000 = { .init_apic_ldr = es7000_init_apic_ldr, .ioapic_phys_id_map = es7000_ioapic_phys_id_map, - .setup_apic_routing = setup_apic_routing, + .setup_apic_routing = es7000_setup_apic_routing, .multi_timer_check = multi_timer_check, .apicid_to_node = apicid_to_node, .cpu_to_logical_apicid = cpu_to_logical_apicid, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 5d98f18a0bd..8c137f41348 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -65,7 +65,7 @@ struct genapic apic_numaq = { .init_apic_ldr = numaq_init_apic_ldr, .ioapic_phys_id_map = numaq_ioapic_phys_id_map, - .setup_apic_routing = setup_apic_routing, + .setup_apic_routing = numaq_setup_apic_routing, .multi_timer_check = multi_timer_check, .apicid_to_node = apicid_to_node, .cpu_to_logical_apicid = cpu_to_logical_apicid, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 6abdd53a01c..0698566dc7b 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -58,7 +58,7 @@ struct genapic apic_summit = { .init_apic_ldr = summit_init_apic_ldr, .ioapic_phys_id_map = summit_ioapic_phys_id_map, - .setup_apic_routing = setup_apic_routing, + .setup_apic_routing = summit_setup_apic_routing, .multi_timer_check = multi_timer_check, .apicid_to_node = apicid_to_node, .cpu_to_logical_apicid = cpu_to_logical_apicid, -- GitLab From 33a201fac698a93d9d1ffa77030ba2ff38d1a3d1 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 07:17:26 +0100 Subject: [PATCH 0556/4982] x86, apic: streamline the ->multi_timer_check() quirk only NUMAQ uses this quirk: to prevent the timer IRQ from being added on secondary nodes. All other genapic templates can have a NULL ->multi_timer_check() callback. Also, extend the generic code to treat a NULL pointer accordingly. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 5 ----- arch/x86/include/asm/es7000/apic.h | 5 ----- arch/x86/include/asm/mach-default/mach_apic.h | 5 ----- arch/x86/include/asm/mach-generic/mach_apic.h | 1 - arch/x86/include/asm/numaq/apic.h | 2 +- arch/x86/include/asm/summit/apic.h | 5 ----- arch/x86/kernel/io_apic.c | 11 ++++++++--- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 2 +- arch/x86/mach-generic/numaq.c | 2 +- arch/x86/mach-generic/summit.c | 2 +- 12 files changed, 14 insertions(+), 30 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index 321ea47b5dd..df59298086c 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h @@ -62,11 +62,6 @@ static inline void bigsmp_setup_apic_routing(void) "Physflat", nr_ioapics); } -static inline int multi_timer_check(int apic, int irq) -{ - return (0); -} - static inline int apicid_to_node(int logical_apicid) { return apicid_2_node[hard_smp_processor_id()]; diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index f1183000a94..632e4cd3f4f 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -82,11 +82,6 @@ static inline void es7000_setup_apic_routing(void) nr_ioapics, cpus_addr(*es7000_target_cpus())[0]); } -static inline int multi_timer_check(int apic, int irq) -{ - return 0; -} - static inline int apicid_to_node(int logical_apicid) { return 0; diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index d4467746304..f418d470cf4 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -104,11 +104,6 @@ static inline physid_mask_t default_ioapic_phys_id_map(physid_mask_t phys_map) return phys_map; } -static inline int multi_timer_check(int apic, int irq) -{ - return 0; -} - /* Mapping from cpu number to logical apicid */ static inline int cpu_to_logical_apicid(int cpu) { diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index ddf369248ab..bdea0a759e8 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -3,7 +3,6 @@ #include -#define multi_timer_check (apic->multi_timer_check) #define apicid_to_node (apic->apicid_to_node) #define cpu_to_logical_apicid (apic->cpu_to_logical_apicid) #define cpu_present_to_apicid (apic->cpu_present_to_apicid) diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h index 2feb7e72e9e..22bdf3d4c0e 100644 --- a/arch/x86/include/asm/numaq/apic.h +++ b/arch/x86/include/asm/numaq/apic.h @@ -43,7 +43,7 @@ static inline void numaq_setup_apic_routing(void) * Skip adding the timer int on secondary nodes, which causes * a small but painful rift in the time-space continuum. */ -static inline int multi_timer_check(int apic, int irq) +static inline int numaq_multi_timer_check(int apic, int irq) { return apic != 0 && irq == 0; } diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index 7ec2696bc9a..acb7bd1de84 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h @@ -64,11 +64,6 @@ static inline void summit_init_apic_ldr(void) apic_write(APIC_LDR, val); } -static inline int multi_timer_check(int apic, int irq) -{ - return 0; -} - static inline int summit_apic_id_registered(void) { return 1; diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index db79ad9a764..282ea112f3c 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -1618,10 +1618,15 @@ static void __init setup_IO_APIC_irqs(void) } irq = pin_2_irq(idx, apic_id, pin); -#ifdef CONFIG_X86_32 - if (multi_timer_check(apic_id, irq)) + + /* + * Skip the timer IRQ if there's a quirk handler + * installed and if it returns 1: + */ + if (apic->multi_timer_check && + apic->multi_timer_check(apic_id, irq)) continue; -#endif + desc = irq_to_desc_alloc_cpu(irq, cpu); if (!desc) { printk(KERN_INFO "can not get irq_desc for %d\n", irq); diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index ad3837a59bd..d0749569cdf 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -79,7 +79,7 @@ struct genapic apic_bigsmp = { .ioapic_phys_id_map = bigsmp_ioapic_phys_id_map, .setup_apic_routing = bigsmp_setup_apic_routing, - .multi_timer_check = multi_timer_check, + .multi_timer_check = NULL, .apicid_to_node = apicid_to_node, .cpu_to_logical_apicid = cpu_to_logical_apicid, .cpu_present_to_apicid = cpu_present_to_apicid, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index 67f287fc12d..6a21aa7c0c6 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -60,7 +60,7 @@ struct genapic apic_default = { .ioapic_phys_id_map = default_ioapic_phys_id_map, .setup_apic_routing = default_setup_apic_routing, - .multi_timer_check = multi_timer_check, + .multi_timer_check = NULL, .apicid_to_node = apicid_to_node, .cpu_to_logical_apicid = cpu_to_logical_apicid, .cpu_present_to_apicid = cpu_present_to_apicid, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index f6117293946..0be59a51df2 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -121,7 +121,7 @@ struct genapic apic_es7000 = { .ioapic_phys_id_map = es7000_ioapic_phys_id_map, .setup_apic_routing = es7000_setup_apic_routing, - .multi_timer_check = multi_timer_check, + .multi_timer_check = NULL, .apicid_to_node = apicid_to_node, .cpu_to_logical_apicid = cpu_to_logical_apicid, .cpu_present_to_apicid = cpu_present_to_apicid, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 8c137f41348..da4ed653506 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -66,7 +66,7 @@ struct genapic apic_numaq = { .ioapic_phys_id_map = numaq_ioapic_phys_id_map, .setup_apic_routing = numaq_setup_apic_routing, - .multi_timer_check = multi_timer_check, + .multi_timer_check = numaq_multi_timer_check, .apicid_to_node = apicid_to_node, .cpu_to_logical_apicid = cpu_to_logical_apicid, .cpu_present_to_apicid = cpu_present_to_apicid, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 0698566dc7b..b618a186f1e 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -59,7 +59,7 @@ struct genapic apic_summit = { .ioapic_phys_id_map = summit_ioapic_phys_id_map, .setup_apic_routing = summit_setup_apic_routing, - .multi_timer_check = multi_timer_check, + .multi_timer_check = NULL, .apicid_to_node = apicid_to_node, .cpu_to_logical_apicid = cpu_to_logical_apicid, .cpu_present_to_apicid = cpu_present_to_apicid, -- GitLab From 3f57a318c36e1f24070a18df8c4971ca08d33142 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 06:50:47 +0100 Subject: [PATCH 0557/4982] x86, apic: clean up ->apicid_to_node() - separate the namespace - remove macros Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 2 +- arch/x86/include/asm/es7000/apic.h | 2 +- arch/x86/include/asm/mach-default/mach_apic.h | 2 +- arch/x86/include/asm/mach-generic/mach_apic.h | 1 - arch/x86/include/asm/numaq/apic.h | 4 ++-- arch/x86/include/asm/summit/apic.h | 2 +- arch/x86/kernel/smpboot.c | 2 +- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 2 +- arch/x86/mach-generic/numaq.c | 2 +- arch/x86/mach-generic/summit.c | 2 +- 12 files changed, 12 insertions(+), 13 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index df59298086c..77f0b734875 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h @@ -62,7 +62,7 @@ static inline void bigsmp_setup_apic_routing(void) "Physflat", nr_ioapics); } -static inline int apicid_to_node(int logical_apicid) +static inline int bigsmp_apicid_to_node(int logical_apicid) { return apicid_2_node[hard_smp_processor_id()]; } diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index 632e4cd3f4f..bcdf31400df 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -82,7 +82,7 @@ static inline void es7000_setup_apic_routing(void) nr_ioapics, cpus_addr(*es7000_target_cpus())[0]); } -static inline int apicid_to_node(int logical_apicid) +static inline int es7000_apicid_to_node(int logical_apicid) { return 0; } diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index f418d470cf4..2f78209d972 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -78,7 +78,7 @@ static inline void default_setup_apic_routing(void) #endif } -static inline int apicid_to_node(int logical_apicid) +static inline int default_apicid_to_node(int logical_apicid) { #ifdef CONFIG_SMP return apicid_2_node[hard_smp_processor_id()]; diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index bdea0a759e8..b585a8e5f81 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -3,7 +3,6 @@ #include -#define apicid_to_node (apic->apicid_to_node) #define cpu_to_logical_apicid (apic->cpu_to_logical_apicid) #define cpu_present_to_apicid (apic->cpu_present_to_apicid) #define apicid_to_cpu_present (apic->apicid_to_cpu_present) diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h index 22bdf3d4c0e..a0e3b437118 100644 --- a/arch/x86/include/asm/numaq/apic.h +++ b/arch/x86/include/asm/numaq/apic.h @@ -76,14 +76,14 @@ static inline int cpu_present_to_apicid(int mps_cpu) return BAD_APICID; } -static inline int apicid_to_node(int logical_apicid) +static inline int numaq_apicid_to_node(int logical_apicid) { return logical_apicid >> 4; } static inline physid_mask_t apicid_to_cpu_present(int logical_apicid) { - int node = apicid_to_node(logical_apicid); + int node = numaq_apicid_to_node(logical_apicid); int cpu = __ffs(logical_apicid & 0xf); return physid_mask_of_physid(cpu + 4*node); diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index acb7bd1de84..cfff2760e60 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h @@ -75,7 +75,7 @@ static inline void summit_setup_apic_routing(void) nr_ioapics); } -static inline int apicid_to_node(int logical_apicid) +static inline int summit_apicid_to_node(int logical_apicid) { #ifdef CONFIG_SMP return apicid_2_node[hard_smp_processor_id()]; diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 3791b4ae567..1dd4cecd4bc 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -163,7 +163,7 @@ static void map_cpu_to_logical_apicid(void) { int cpu = smp_processor_id(); int apicid = logical_smp_processor_id(); - int node = apicid_to_node(apicid); + int node = apic->apicid_to_node(apicid); if (!node_online(node)) node = first_online_node; diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index d0749569cdf..2f4121499e5 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -80,7 +80,7 @@ struct genapic apic_bigsmp = { .ioapic_phys_id_map = bigsmp_ioapic_phys_id_map, .setup_apic_routing = bigsmp_setup_apic_routing, .multi_timer_check = NULL, - .apicid_to_node = apicid_to_node, + .apicid_to_node = bigsmp_apicid_to_node, .cpu_to_logical_apicid = cpu_to_logical_apicid, .cpu_present_to_apicid = cpu_present_to_apicid, .apicid_to_cpu_present = apicid_to_cpu_present, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index 6a21aa7c0c6..d391c2dc819 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -61,7 +61,7 @@ struct genapic apic_default = { .ioapic_phys_id_map = default_ioapic_phys_id_map, .setup_apic_routing = default_setup_apic_routing, .multi_timer_check = NULL, - .apicid_to_node = apicid_to_node, + .apicid_to_node = default_apicid_to_node, .cpu_to_logical_apicid = cpu_to_logical_apicid, .cpu_present_to_apicid = cpu_present_to_apicid, .apicid_to_cpu_present = apicid_to_cpu_present, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 0be59a51df2..933f2a38599 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -122,7 +122,7 @@ struct genapic apic_es7000 = { .ioapic_phys_id_map = es7000_ioapic_phys_id_map, .setup_apic_routing = es7000_setup_apic_routing, .multi_timer_check = NULL, - .apicid_to_node = apicid_to_node, + .apicid_to_node = es7000_apicid_to_node, .cpu_to_logical_apicid = cpu_to_logical_apicid, .cpu_present_to_apicid = cpu_present_to_apicid, .apicid_to_cpu_present = apicid_to_cpu_present, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index da4ed653506..38344fb9979 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -67,7 +67,7 @@ struct genapic apic_numaq = { .ioapic_phys_id_map = numaq_ioapic_phys_id_map, .setup_apic_routing = numaq_setup_apic_routing, .multi_timer_check = numaq_multi_timer_check, - .apicid_to_node = apicid_to_node, + .apicid_to_node = numaq_apicid_to_node, .cpu_to_logical_apicid = cpu_to_logical_apicid, .cpu_present_to_apicid = cpu_present_to_apicid, .apicid_to_cpu_present = apicid_to_cpu_present, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index b618a186f1e..6150604deaa 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -60,7 +60,7 @@ struct genapic apic_summit = { .ioapic_phys_id_map = summit_ioapic_phys_id_map, .setup_apic_routing = summit_setup_apic_routing, .multi_timer_check = NULL, - .apicid_to_node = apicid_to_node, + .apicid_to_node = summit_apicid_to_node, .cpu_to_logical_apicid = cpu_to_logical_apicid, .cpu_present_to_apicid = cpu_present_to_apicid, .apicid_to_cpu_present = apicid_to_cpu_present, -- GitLab From 5257c5111ca21c8e857b65a79ab986b313e1c362 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 06:50:47 +0100 Subject: [PATCH 0558/4982] x86, apic: clean up ->cpu_to_logical_apicid() - separate the namespace - remove macros Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 6 +++--- arch/x86/include/asm/es7000/apic.h | 16 ++++++++-------- arch/x86/include/asm/mach-default/mach_apic.h | 2 +- arch/x86/include/asm/mach-generic/mach_apic.h | 1 - arch/x86/include/asm/numaq/apic.h | 3 ++- arch/x86/include/asm/summit/apic.h | 8 ++++---- arch/x86/kernel/ipi.c | 4 ++-- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 2 +- arch/x86/mach-generic/numaq.c | 2 +- arch/x86/mach-generic/summit.c | 2 +- 12 files changed, 25 insertions(+), 25 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index 77f0b734875..d0d894ff7d3 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h @@ -82,7 +82,7 @@ static inline physid_mask_t apicid_to_cpu_present(int phys_apicid) extern u8 cpu_2_logical_apicid[]; /* Mapping from cpu number to logical apicid */ -static inline int cpu_to_logical_apicid(int cpu) +static inline int bigsmp_cpu_to_logical_apicid(int cpu) { if (cpu >= nr_cpu_ids) return BAD_APICID; @@ -115,7 +115,7 @@ static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask) int apicid; cpu = first_cpu(*cpumask); - apicid = cpu_to_logical_apicid(cpu); + apicid = bigsmp_cpu_to_logical_apicid(cpu); return apicid; } @@ -132,7 +132,7 @@ static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *cpumask, if (cpumask_test_cpu(cpu, cpu_online_mask)) break; if (cpu < nr_cpu_ids) - return cpu_to_logical_apicid(cpu); + return bigsmp_cpu_to_logical_apicid(cpu); return BAD_APICID; } diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index bcdf31400df..e0cd07e74f9 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -109,7 +109,7 @@ static inline physid_mask_t apicid_to_cpu_present(int phys_apicid) extern u8 cpu_2_logical_apicid[]; /* Mapping from cpu number to logical apicid */ -static inline int cpu_to_logical_apicid(int cpu) +static inline int es7000_cpu_to_logical_apicid(int cpu) { #ifdef CONFIG_SMP if (cpu >= nr_cpu_ids) @@ -155,10 +155,10 @@ cpu_mask_to_apicid_cluster(const struct cpumask *cpumask) * on the same apicid cluster return default value of target_cpus(): */ cpu = cpumask_first(cpumask); - apicid = cpu_to_logical_apicid(cpu); + apicid = es7000_cpu_to_logical_apicid(cpu); while (cpus_found < num_bits_set) { if (cpumask_test_cpu(cpu, cpumask)) { - int new_apicid = cpu_to_logical_apicid(cpu); + int new_apicid = es7000_cpu_to_logical_apicid(cpu); if (apicid_cluster(apicid) != apicid_cluster(new_apicid)){ printk ("%s: Not a valid mask!\n", __func__); @@ -182,20 +182,20 @@ static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask) num_bits_set = cpus_weight(*cpumask); /* Return id to all */ if (num_bits_set == nr_cpu_ids) - return cpu_to_logical_apicid(0); + return es7000_cpu_to_logical_apicid(0); /* * The cpus in the mask must all be on the apic cluster. If are not * on the same apicid cluster return default value of target_cpus(): */ cpu = first_cpu(*cpumask); - apicid = cpu_to_logical_apicid(cpu); + apicid = es7000_cpu_to_logical_apicid(cpu); while (cpus_found < num_bits_set) { if (cpu_isset(cpu, *cpumask)) { - int new_apicid = cpu_to_logical_apicid(cpu); + int new_apicid = es7000_cpu_to_logical_apicid(cpu); if (apicid_cluster(apicid) != apicid_cluster(new_apicid)){ printk ("%s: Not a valid mask!\n", __func__); - return cpu_to_logical_apicid(0); + return es7000_cpu_to_logical_apicid(0); } apicid = new_apicid; cpus_found++; @@ -209,7 +209,7 @@ static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask) static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *inmask, const struct cpumask *andmask) { - int apicid = cpu_to_logical_apicid(0); + int apicid = es7000_cpu_to_logical_apicid(0); cpumask_var_t cpumask; if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC)) diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index 2f78209d972..eae3e4b6ed0 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -105,7 +105,7 @@ static inline physid_mask_t default_ioapic_phys_id_map(physid_mask_t phys_map) } /* Mapping from cpu number to logical apicid */ -static inline int cpu_to_logical_apicid(int cpu) +static inline int default_cpu_to_logical_apicid(int cpu) { return 1 << cpu; } diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index b585a8e5f81..2ea913e8e0d 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -3,7 +3,6 @@ #include -#define cpu_to_logical_apicid (apic->cpu_to_logical_apicid) #define cpu_present_to_apicid (apic->cpu_present_to_apicid) #define apicid_to_cpu_present (apic->apicid_to_cpu_present) #define setup_portio_remap (apic->setup_portio_remap) diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h index a0e3b437118..6989abd3485 100644 --- a/arch/x86/include/asm/numaq/apic.h +++ b/arch/x86/include/asm/numaq/apic.h @@ -56,7 +56,8 @@ static inline physid_mask_t numaq_ioapic_phys_id_map(physid_mask_t phys_map) /* Mapping from cpu number to logical apicid */ extern u8 cpu_2_logical_apicid[]; -static inline int cpu_to_logical_apicid(int cpu) + +static inline int numaq_cpu_to_logical_apicid(int cpu) { if (cpu >= nr_cpu_ids) return BAD_APICID; diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index cfff2760e60..d564d7ee3f6 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h @@ -85,7 +85,7 @@ static inline int summit_apicid_to_node(int logical_apicid) } /* Mapping from cpu number to logical apicid */ -static inline int cpu_to_logical_apicid(int cpu) +static inline int summit_cpu_to_logical_apicid(int cpu) { #ifdef CONFIG_SMP if (cpu >= nr_cpu_ids) @@ -145,10 +145,10 @@ static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask) * on the same apicid cluster return default value of target_cpus(): */ cpu = first_cpu(*cpumask); - apicid = cpu_to_logical_apicid(cpu); + apicid = summit_cpu_to_logical_apicid(cpu); while (cpus_found < num_bits_set) { if (cpu_isset(cpu, *cpumask)) { - int new_apicid = cpu_to_logical_apicid(cpu); + int new_apicid = summit_cpu_to_logical_apicid(cpu); if (apicid_cluster(apicid) != apicid_cluster(new_apicid)){ printk ("%s: Not a valid mask!\n", __func__); @@ -165,7 +165,7 @@ static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask) static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *inmask, const struct cpumask *andmask) { - int apicid = cpu_to_logical_apicid(0); + int apicid = summit_cpu_to_logical_apicid(0); cpumask_var_t cpumask; if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC)) diff --git a/arch/x86/kernel/ipi.c b/arch/x86/kernel/ipi.c index e2e4895ca69..367c5e684fa 100644 --- a/arch/x86/kernel/ipi.c +++ b/arch/x86/kernel/ipi.c @@ -140,7 +140,7 @@ void send_IPI_mask_sequence(const struct cpumask *mask, int vector) local_irq_save(flags); for_each_cpu(query_cpu, mask) - __send_IPI_dest_field(cpu_to_logical_apicid(query_cpu), vector); + __send_IPI_dest_field(apic->cpu_to_logical_apicid(query_cpu), vector); local_irq_restore(flags); } @@ -155,7 +155,7 @@ void send_IPI_mask_allbutself(const struct cpumask *mask, int vector) local_irq_save(flags); for_each_cpu(query_cpu, mask) if (query_cpu != this_cpu) - __send_IPI_dest_field(cpu_to_logical_apicid(query_cpu), + __send_IPI_dest_field(apic->cpu_to_logical_apicid(query_cpu), vector); local_irq_restore(flags); } diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 2f4121499e5..cd6f02ba88e 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -81,7 +81,7 @@ struct genapic apic_bigsmp = { .setup_apic_routing = bigsmp_setup_apic_routing, .multi_timer_check = NULL, .apicid_to_node = bigsmp_apicid_to_node, - .cpu_to_logical_apicid = cpu_to_logical_apicid, + .cpu_to_logical_apicid = bigsmp_cpu_to_logical_apicid, .cpu_present_to_apicid = cpu_present_to_apicid, .apicid_to_cpu_present = apicid_to_cpu_present, .setup_portio_remap = setup_portio_remap, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index d391c2dc819..ef9b936c41a 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -62,7 +62,7 @@ struct genapic apic_default = { .setup_apic_routing = default_setup_apic_routing, .multi_timer_check = NULL, .apicid_to_node = default_apicid_to_node, - .cpu_to_logical_apicid = cpu_to_logical_apicid, + .cpu_to_logical_apicid = default_cpu_to_logical_apicid, .cpu_present_to_apicid = cpu_present_to_apicid, .apicid_to_cpu_present = apicid_to_cpu_present, .setup_portio_remap = setup_portio_remap, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 933f2a38599..74bf2b6b751 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -123,7 +123,7 @@ struct genapic apic_es7000 = { .setup_apic_routing = es7000_setup_apic_routing, .multi_timer_check = NULL, .apicid_to_node = es7000_apicid_to_node, - .cpu_to_logical_apicid = cpu_to_logical_apicid, + .cpu_to_logical_apicid = es7000_cpu_to_logical_apicid, .cpu_present_to_apicid = cpu_present_to_apicid, .apicid_to_cpu_present = apicid_to_cpu_present, .setup_portio_remap = setup_portio_remap, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 38344fb9979..461f5beedb2 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -68,7 +68,7 @@ struct genapic apic_numaq = { .setup_apic_routing = numaq_setup_apic_routing, .multi_timer_check = numaq_multi_timer_check, .apicid_to_node = numaq_apicid_to_node, - .cpu_to_logical_apicid = cpu_to_logical_apicid, + .cpu_to_logical_apicid = numaq_cpu_to_logical_apicid, .cpu_present_to_apicid = cpu_present_to_apicid, .apicid_to_cpu_present = apicid_to_cpu_present, .setup_portio_remap = setup_portio_remap, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 6150604deaa..d99be2d4efc 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -61,7 +61,7 @@ struct genapic apic_summit = { .setup_apic_routing = summit_setup_apic_routing, .multi_timer_check = NULL, .apicid_to_node = summit_apicid_to_node, - .cpu_to_logical_apicid = cpu_to_logical_apicid, + .cpu_to_logical_apicid = summit_cpu_to_logical_apicid, .cpu_present_to_apicid = cpu_present_to_apicid, .apicid_to_cpu_present = apicid_to_cpu_present, .setup_portio_remap = setup_portio_remap, -- GitLab From a21769a4461801454930a06bc18bd8249cd9e993 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 06:50:47 +0100 Subject: [PATCH 0559/4982] x86, apic: clean up ->cpu_present_to_apicid() - separate the namespace - remove macros Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 2 +- arch/x86/include/asm/es7000/apic.h | 2 +- arch/x86/include/asm/genapic.h | 2 ++ arch/x86/include/asm/mach-default/mach_apic.h | 11 ++++++++++- arch/x86/include/asm/mach-generic/mach_apic.h | 1 - arch/x86/include/asm/numaq/apic.h | 2 +- arch/x86/include/asm/summit/apic.h | 2 +- arch/x86/kernel/genapic_flat_64.c | 4 ++-- arch/x86/kernel/genx2apic_cluster.c | 2 +- arch/x86/kernel/genx2apic_phys.c | 2 +- arch/x86/kernel/genx2apic_uv_x.c | 2 +- arch/x86/kernel/smpboot.c | 9 ++++++++- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 2 +- arch/x86/mach-generic/numaq.c | 2 +- arch/x86/mach-generic/summit.c | 2 +- 17 files changed, 34 insertions(+), 17 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index d0d894ff7d3..eea5e9788dd 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h @@ -67,7 +67,7 @@ static inline int bigsmp_apicid_to_node(int logical_apicid) return apicid_2_node[hard_smp_processor_id()]; } -static inline int cpu_present_to_apicid(int mps_cpu) +static inline int bigsmp_cpu_present_to_apicid(int mps_cpu) { if (mps_cpu < nr_cpu_ids) return (int) per_cpu(x86_bios_cpu_apicid, mps_cpu); diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index e0cd07e74f9..7cdde3d9c5f 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -88,7 +88,7 @@ static inline int es7000_apicid_to_node(int logical_apicid) } -static inline int cpu_present_to_apicid(int mps_cpu) +static inline int es7000_cpu_present_to_apicid(int mps_cpu) { if (!mps_cpu) return boot_cpu_physical_apicid; diff --git a/arch/x86/include/asm/genapic.h b/arch/x86/include/asm/genapic.h index 38b1202316f..2cb14d51e45 100644 --- a/arch/x86/include/asm/genapic.h +++ b/arch/x86/include/asm/genapic.h @@ -108,6 +108,8 @@ extern struct genapic apic_x2apic_uv_x; DECLARE_PER_CPU(int, x2apic_extra_bits); extern void default_setup_apic_routing(void); + +extern int default_cpu_present_to_apicid(int mps_cpu); #endif #endif /* _ASM_X86_GENAPIC_64_H */ diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index eae3e4b6ed0..15d5627a9d6 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -110,7 +110,7 @@ static inline int default_cpu_to_logical_apicid(int cpu) return 1 << cpu; } -static inline int cpu_present_to_apicid(int mps_cpu) +static inline int __default_cpu_present_to_apicid(int mps_cpu) { if (mps_cpu < nr_cpu_ids && cpu_present(mps_cpu)) return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu); @@ -118,6 +118,15 @@ static inline int cpu_present_to_apicid(int mps_cpu) return BAD_APICID; } +#ifdef CONFIG_X86_32 +static inline int default_cpu_present_to_apicid(int mps_cpu) +{ + return __default_cpu_present_to_apicid(mps_cpu); +} +#else +extern int default_cpu_present_to_apicid(int mps_cpu); +#endif + static inline physid_mask_t apicid_to_cpu_present(int phys_apicid) { return physid_mask_of_physid(phys_apicid); diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index 2ea913e8e0d..332fe93ab41 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -3,7 +3,6 @@ #include -#define cpu_present_to_apicid (apic->cpu_present_to_apicid) #define apicid_to_cpu_present (apic->apicid_to_cpu_present) #define setup_portio_remap (apic->setup_portio_remap) #define check_phys_apicid_present (apic->check_phys_apicid_present) diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h index 6989abd3485..f482b063447 100644 --- a/arch/x86/include/asm/numaq/apic.h +++ b/arch/x86/include/asm/numaq/apic.h @@ -69,7 +69,7 @@ static inline int numaq_cpu_to_logical_apicid(int cpu) * cpu to APIC ID relation to properly interact with the intelligent * mode of the cluster controller. */ -static inline int cpu_present_to_apicid(int mps_cpu) +static inline int numaq_cpu_present_to_apicid(int mps_cpu) { if (mps_cpu < 60) return ((mps_cpu >> 2) << 4) | (1 << (mps_cpu & 0x3)); diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index d564d7ee3f6..fc127369188 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h @@ -96,7 +96,7 @@ static inline int summit_cpu_to_logical_apicid(int cpu) #endif } -static inline int cpu_present_to_apicid(int mps_cpu) +static inline int summit_cpu_present_to_apicid(int mps_cpu) { if (mps_cpu < nr_cpu_ids) return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu); diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index 9446f372a16..f4a2c1c0a1a 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -197,7 +197,7 @@ struct genapic apic_flat = { .multi_timer_check = NULL, .apicid_to_node = NULL, .cpu_to_logical_apicid = NULL, - .cpu_present_to_apicid = NULL, + .cpu_present_to_apicid = default_cpu_present_to_apicid, .apicid_to_cpu_present = NULL, .setup_portio_remap = NULL, .check_phys_apicid_present = NULL, @@ -341,7 +341,7 @@ struct genapic apic_physflat = { .multi_timer_check = NULL, .apicid_to_node = NULL, .cpu_to_logical_apicid = NULL, - .cpu_present_to_apicid = NULL, + .cpu_present_to_apicid = default_cpu_present_to_apicid, .apicid_to_cpu_present = NULL, .setup_portio_remap = NULL, .check_phys_apicid_present = NULL, diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c index 2eeca6e744a..710d612a964 100644 --- a/arch/x86/kernel/genx2apic_cluster.c +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -199,7 +199,7 @@ struct genapic apic_x2apic_cluster = { .multi_timer_check = NULL, .apicid_to_node = NULL, .cpu_to_logical_apicid = NULL, - .cpu_present_to_apicid = NULL, + .cpu_present_to_apicid = default_cpu_present_to_apicid, .apicid_to_cpu_present = NULL, .setup_portio_remap = NULL, .check_phys_apicid_present = NULL, diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c index be0ee3e56ef..49a449178c3 100644 --- a/arch/x86/kernel/genx2apic_phys.c +++ b/arch/x86/kernel/genx2apic_phys.c @@ -195,7 +195,7 @@ struct genapic apic_x2apic_phys = { .multi_timer_check = NULL, .apicid_to_node = NULL, .cpu_to_logical_apicid = NULL, - .cpu_present_to_apicid = NULL, + .cpu_present_to_apicid = default_cpu_present_to_apicid, .apicid_to_cpu_present = NULL, .setup_portio_remap = NULL, .check_phys_apicid_present = NULL, diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index 68b423f3da9..a08a6359186 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -260,7 +260,7 @@ struct genapic apic_x2apic_uv_x = { .multi_timer_check = NULL, .apicid_to_node = NULL, .cpu_to_logical_apicid = NULL, - .cpu_present_to_apicid = NULL, + .cpu_present_to_apicid = default_cpu_present_to_apicid, .apicid_to_cpu_present = NULL, .setup_portio_remap = NULL, .check_phys_apicid_present = NULL, diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 1dd4cecd4bc..812bf39de35 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -903,9 +903,16 @@ do_rest: return boot_error; } +#ifdef CONFIG_X86_64 +int default_cpu_present_to_apicid(int mps_cpu) +{ + return __default_cpu_present_to_apicid(mps_cpu); +} +#endif + int __cpuinit native_cpu_up(unsigned int cpu) { - int apicid = cpu_present_to_apicid(cpu); + int apicid = apic->cpu_present_to_apicid(cpu); unsigned long flags; int err; diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index cd6f02ba88e..1eaf18c801d 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -82,7 +82,7 @@ struct genapic apic_bigsmp = { .multi_timer_check = NULL, .apicid_to_node = bigsmp_apicid_to_node, .cpu_to_logical_apicid = bigsmp_cpu_to_logical_apicid, - .cpu_present_to_apicid = cpu_present_to_apicid, + .cpu_present_to_apicid = bigsmp_cpu_present_to_apicid, .apicid_to_cpu_present = apicid_to_cpu_present, .setup_portio_remap = setup_portio_remap, .check_phys_apicid_present = check_phys_apicid_present, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index ef9b936c41a..2903657f420 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -63,7 +63,7 @@ struct genapic apic_default = { .multi_timer_check = NULL, .apicid_to_node = default_apicid_to_node, .cpu_to_logical_apicid = default_cpu_to_logical_apicid, - .cpu_present_to_apicid = cpu_present_to_apicid, + .cpu_present_to_apicid = default_cpu_present_to_apicid, .apicid_to_cpu_present = apicid_to_cpu_present, .setup_portio_remap = setup_portio_remap, .check_phys_apicid_present = check_phys_apicid_present, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 74bf2b6b751..5a3a8ab4f8a 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -124,7 +124,7 @@ struct genapic apic_es7000 = { .multi_timer_check = NULL, .apicid_to_node = es7000_apicid_to_node, .cpu_to_logical_apicid = es7000_cpu_to_logical_apicid, - .cpu_present_to_apicid = cpu_present_to_apicid, + .cpu_present_to_apicid = es7000_cpu_present_to_apicid, .apicid_to_cpu_present = apicid_to_cpu_present, .setup_portio_remap = setup_portio_remap, .check_phys_apicid_present = check_phys_apicid_present, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 461f5beedb2..d928cae211c 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -69,7 +69,7 @@ struct genapic apic_numaq = { .multi_timer_check = numaq_multi_timer_check, .apicid_to_node = numaq_apicid_to_node, .cpu_to_logical_apicid = numaq_cpu_to_logical_apicid, - .cpu_present_to_apicid = cpu_present_to_apicid, + .cpu_present_to_apicid = numaq_cpu_present_to_apicid, .apicid_to_cpu_present = apicid_to_cpu_present, .setup_portio_remap = setup_portio_remap, .check_phys_apicid_present = check_phys_apicid_present, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index d99be2d4efc..e6bb34ee580 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -62,7 +62,7 @@ struct genapic apic_summit = { .multi_timer_check = NULL, .apicid_to_node = summit_apicid_to_node, .cpu_to_logical_apicid = summit_cpu_to_logical_apicid, - .cpu_present_to_apicid = cpu_present_to_apicid, + .cpu_present_to_apicid = summit_cpu_present_to_apicid, .apicid_to_cpu_present = apicid_to_cpu_present, .setup_portio_remap = setup_portio_remap, .check_phys_apicid_present = check_phys_apicid_present, -- GitLab From 8058714a41afc4c983acb274b1adf7bd3cfe7f6e Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 06:50:47 +0100 Subject: [PATCH 0560/4982] x86, apic: clean up ->apicid_to_cpu_present() - separate the namespace - remove macros Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 2 +- arch/x86/include/asm/es7000/apic.h | 2 +- arch/x86/include/asm/mach-default/mach_apic.h | 2 +- arch/x86/include/asm/mach-generic/mach_apic.h | 1 - arch/x86/include/asm/numaq/apic.h | 2 +- arch/x86/include/asm/summit/apic.h | 4 ++-- arch/x86/kernel/io_apic.c | 4 ++-- arch/x86/kernel/visws_quirks.c | 2 +- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 2 +- arch/x86/mach-generic/numaq.c | 2 +- arch/x86/mach-generic/summit.c | 2 +- 13 files changed, 14 insertions(+), 15 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index eea5e9788dd..080457450b2 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h @@ -75,7 +75,7 @@ static inline int bigsmp_cpu_present_to_apicid(int mps_cpu) return BAD_APICID; } -static inline physid_mask_t apicid_to_cpu_present(int phys_apicid) +static inline physid_mask_t bigsmp_apicid_to_cpu_present(int phys_apicid) { return physid_mask_of_physid(phys_apicid); } diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index 7cdde3d9c5f..a09e1133ced 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -98,7 +98,7 @@ static inline int es7000_cpu_present_to_apicid(int mps_cpu) return BAD_APICID; } -static inline physid_mask_t apicid_to_cpu_present(int phys_apicid) +static inline physid_mask_t es7000_apicid_to_cpu_present(int phys_apicid) { static int id = 0; physid_mask_t mask; diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index 15d5627a9d6..22683e5b82b 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -127,7 +127,7 @@ static inline int default_cpu_present_to_apicid(int mps_cpu) extern int default_cpu_present_to_apicid(int mps_cpu); #endif -static inline physid_mask_t apicid_to_cpu_present(int phys_apicid) +static inline physid_mask_t default_apicid_to_cpu_present(int phys_apicid) { return physid_mask_of_physid(phys_apicid); } diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index 332fe93ab41..997618f2eb5 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -3,7 +3,6 @@ #include -#define apicid_to_cpu_present (apic->apicid_to_cpu_present) #define setup_portio_remap (apic->setup_portio_remap) #define check_phys_apicid_present (apic->check_phys_apicid_present) #define cpu_mask_to_apicid (apic->cpu_mask_to_apicid) diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h index f482b063447..8ac000f9928 100644 --- a/arch/x86/include/asm/numaq/apic.h +++ b/arch/x86/include/asm/numaq/apic.h @@ -82,7 +82,7 @@ static inline int numaq_apicid_to_node(int logical_apicid) return logical_apicid >> 4; } -static inline physid_mask_t apicid_to_cpu_present(int logical_apicid) +static inline physid_mask_t numaq_apicid_to_cpu_present(int logical_apicid) { int node = numaq_apicid_to_node(logical_apicid); int cpu = __ffs(logical_apicid & 0xf); diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index fc127369188..79c1a45f886 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h @@ -105,13 +105,13 @@ static inline int summit_cpu_present_to_apicid(int mps_cpu) } static inline physid_mask_t - summit_ioapic_phys_id_map(physid_mask_t phys_id_map) +summit_ioapic_phys_id_map(physid_mask_t phys_id_map) { /* For clustered we don't have a good way to do this yet - hack */ return physids_promote(0x0F); } -static inline physid_mask_t apicid_to_cpu_present(int apicid) +static inline physid_mask_t summit_apicid_to_cpu_present(int apicid) { return physid_mask_of_physid(0); } diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 282ea112f3c..3d85d3d810b 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -2155,7 +2155,7 @@ static void __init setup_ioapic_ids_from_mpc(void) mp_ioapics[apic_id].apicid = i; } else { physid_mask_t tmp; - tmp = apicid_to_cpu_present(mp_ioapics[apic_id].apicid); + tmp = apic->apicid_to_cpu_present(mp_ioapics[apic_id].apicid); apic_printk(APIC_VERBOSE, "Setting %d in the " "phys_id_present_map\n", mp_ioapics[apic_id].apicid); @@ -3899,7 +3899,7 @@ int __init io_apic_get_unique_id(int ioapic, int apic_id) apic_id = i; } - tmp = apicid_to_cpu_present(apic_id); + tmp = apic->apicid_to_cpu_present(apic_id); physids_or(apic_id_map, apic_id_map, tmp); if (reg_00.bits.ID != apic_id) { diff --git a/arch/x86/kernel/visws_quirks.c b/arch/x86/kernel/visws_quirks.c index d801d06af06..2ed5bdf15c9 100644 --- a/arch/x86/kernel/visws_quirks.c +++ b/arch/x86/kernel/visws_quirks.c @@ -200,7 +200,7 @@ static void __init MP_processor_info(struct mpc_cpu *m) return; } - apic_cpus = apicid_to_cpu_present(m->apicid); + apic_cpus = apic->apicid_to_cpu_present(m->apicid); physids_or(phys_cpu_present_map, phys_cpu_present_map, apic_cpus); /* * Validate version diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 1eaf18c801d..61396523074 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -83,7 +83,7 @@ struct genapic apic_bigsmp = { .apicid_to_node = bigsmp_apicid_to_node, .cpu_to_logical_apicid = bigsmp_cpu_to_logical_apicid, .cpu_present_to_apicid = bigsmp_cpu_present_to_apicid, - .apicid_to_cpu_present = apicid_to_cpu_present, + .apicid_to_cpu_present = bigsmp_apicid_to_cpu_present, .setup_portio_remap = setup_portio_remap, .check_phys_apicid_present = check_phys_apicid_present, .enable_apic_mode = enable_apic_mode, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index 2903657f420..8fc704a3db7 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -64,7 +64,7 @@ struct genapic apic_default = { .apicid_to_node = default_apicid_to_node, .cpu_to_logical_apicid = default_cpu_to_logical_apicid, .cpu_present_to_apicid = default_cpu_present_to_apicid, - .apicid_to_cpu_present = apicid_to_cpu_present, + .apicid_to_cpu_present = default_apicid_to_cpu_present, .setup_portio_remap = setup_portio_remap, .check_phys_apicid_present = check_phys_apicid_present, .enable_apic_mode = enable_apic_mode, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 5a3a8ab4f8a..1e0e1627455 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -125,7 +125,7 @@ struct genapic apic_es7000 = { .apicid_to_node = es7000_apicid_to_node, .cpu_to_logical_apicid = es7000_cpu_to_logical_apicid, .cpu_present_to_apicid = es7000_cpu_present_to_apicid, - .apicid_to_cpu_present = apicid_to_cpu_present, + .apicid_to_cpu_present = es7000_apicid_to_cpu_present, .setup_portio_remap = setup_portio_remap, .check_phys_apicid_present = check_phys_apicid_present, .enable_apic_mode = enable_apic_mode, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index d928cae211c..839b86b765a 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -70,7 +70,7 @@ struct genapic apic_numaq = { .apicid_to_node = numaq_apicid_to_node, .cpu_to_logical_apicid = numaq_cpu_to_logical_apicid, .cpu_present_to_apicid = numaq_cpu_present_to_apicid, - .apicid_to_cpu_present = apicid_to_cpu_present, + .apicid_to_cpu_present = numaq_apicid_to_cpu_present, .setup_portio_remap = setup_portio_remap, .check_phys_apicid_present = check_phys_apicid_present, .enable_apic_mode = enable_apic_mode, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index e6bb34ee580..b6e37607a52 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -63,7 +63,7 @@ struct genapic apic_summit = { .apicid_to_node = summit_apicid_to_node, .cpu_to_logical_apicid = summit_cpu_to_logical_apicid, .cpu_present_to_apicid = summit_cpu_present_to_apicid, - .apicid_to_cpu_present = apicid_to_cpu_present, + .apicid_to_cpu_present = summit_apicid_to_cpu_present, .setup_portio_remap = setup_portio_remap, .check_phys_apicid_present = check_phys_apicid_present, .enable_apic_mode = enable_apic_mode, -- GitLab From d83093b50416f4ca59d3a84b2ddc217748214d64 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 12:43:18 +0100 Subject: [PATCH 0561/4982] x86: refactor ->setup_portio_remap() subarch methods Only NUMAQ has a real ->setup_portio_remap() method, the other subarchitectures define it but keep it empty. So mark the vector as NULL, extend the generic code to handle NULL -setup_portio_remap() entries and remove all the empty handlers. Also move the NUMAQ method from the header file into the apic driver .c file. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 2 +- arch/x86/include/asm/es7000/apic.h | 4 ---- arch/x86/include/asm/mach-default/mach_apic.h | 4 ---- arch/x86/include/asm/mach-generic/mach_apic.h | 1 - arch/x86/include/asm/numaq/apic.h | 13 ------------- arch/x86/include/asm/summit/apic.h | 2 +- arch/x86/kernel/smpboot.c | 3 ++- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 2 +- arch/x86/mach-generic/numaq.c | 15 ++++++++++++++- arch/x86/mach-generic/summit.c | 2 +- 12 files changed, 22 insertions(+), 30 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index 080457450b2..2fa70032e3b 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h @@ -95,7 +95,7 @@ static inline physid_mask_t bigsmp_ioapic_phys_id_map(physid_mask_t phys_map) return physids_promote(0xFFL); } -static inline void setup_portio_remap(void) +static inline void bigsmp_setup_portio_remap(void) { } diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index a09e1133ced..c5b0eb51e53 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -127,10 +127,6 @@ static inline physid_mask_t es7000_ioapic_phys_id_map(physid_mask_t phys_map) } -static inline void setup_portio_remap(void) -{ -} - extern unsigned int boot_cpu_physical_apicid; static inline int check_phys_apicid_present(int cpu_physical_apicid) { diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index 22683e5b82b..54c20e19e28 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -132,10 +132,6 @@ static inline physid_mask_t default_apicid_to_cpu_present(int phys_apicid) return physid_mask_of_physid(phys_apicid); } -static inline void setup_portio_remap(void) -{ -} - static inline int check_phys_apicid_present(int boot_cpu_physical_apicid) { return physid_isset(boot_cpu_physical_apicid, phys_cpu_present_map); diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index 997618f2eb5..393a97c5685 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -3,7 +3,6 @@ #include -#define setup_portio_remap (apic->setup_portio_remap) #define check_phys_apicid_present (apic->check_phys_apicid_present) #define cpu_mask_to_apicid (apic->cpu_mask_to_apicid) #define cpu_mask_to_apicid_and (apic->cpu_mask_to_apicid_and) diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h index 8ac000f9928..6b626519cd7 100644 --- a/arch/x86/include/asm/numaq/apic.h +++ b/arch/x86/include/asm/numaq/apic.h @@ -92,19 +92,6 @@ static inline physid_mask_t numaq_apicid_to_cpu_present(int logical_apicid) extern void *xquad_portio; -static inline void setup_portio_remap(void) -{ - int num_quads = num_online_nodes(); - - if (num_quads <= 1) - return; - - printk("Remapping cross-quad port I/O for %d quads\n", num_quads); - xquad_portio = ioremap(XQUAD_PORTIO_BASE, num_quads*XQUAD_PORTIO_QUAD); - printk("xquad_portio vaddr 0x%08lx, len %08lx\n", - (u_long) xquad_portio, (u_long) num_quads*XQUAD_PORTIO_QUAD); -} - static inline int check_phys_apicid_present(int boot_cpu_physical_apicid) { return (1); diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index 79c1a45f886..131343b0b75 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h @@ -116,7 +116,7 @@ static inline physid_mask_t summit_apicid_to_cpu_present(int apicid) return physid_mask_of_physid(0); } -static inline void setup_portio_remap(void) +static inline void summit_setup_portio_remap(void) { } diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 812bf39de35..0e7d26c01f9 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1170,7 +1170,8 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) map_cpu_to_logical_apicid(); - setup_portio_remap(); + if (apic->setup_portio_remap) + apic->setup_portio_remap(); smpboot_setup_io_apic(); /* diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 61396523074..424740554a3 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -84,7 +84,7 @@ struct genapic apic_bigsmp = { .cpu_to_logical_apicid = bigsmp_cpu_to_logical_apicid, .cpu_present_to_apicid = bigsmp_cpu_present_to_apicid, .apicid_to_cpu_present = bigsmp_apicid_to_cpu_present, - .setup_portio_remap = setup_portio_remap, + .setup_portio_remap = NULL, .check_phys_apicid_present = check_phys_apicid_present, .enable_apic_mode = enable_apic_mode, .phys_pkg_id = phys_pkg_id, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index 8fc704a3db7..b48a58daf71 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -65,7 +65,7 @@ struct genapic apic_default = { .cpu_to_logical_apicid = default_cpu_to_logical_apicid, .cpu_present_to_apicid = default_cpu_present_to_apicid, .apicid_to_cpu_present = default_apicid_to_cpu_present, - .setup_portio_remap = setup_portio_remap, + .setup_portio_remap = NULL, .check_phys_apicid_present = check_phys_apicid_present, .enable_apic_mode = enable_apic_mode, .phys_pkg_id = phys_pkg_id, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 1e0e1627455..449eca5b604 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -126,7 +126,7 @@ struct genapic apic_es7000 = { .cpu_to_logical_apicid = es7000_cpu_to_logical_apicid, .cpu_present_to_apicid = es7000_cpu_present_to_apicid, .apicid_to_cpu_present = es7000_apicid_to_cpu_present, - .setup_portio_remap = setup_portio_remap, + .setup_portio_remap = NULL, .check_phys_apicid_present = check_phys_apicid_present, .enable_apic_mode = enable_apic_mode, .phys_pkg_id = phys_pkg_id, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 839b86b765a..e60361b0bf1 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -44,6 +44,19 @@ static void numaq_vector_allocation_domain(int cpu, cpumask_t *retmask) *retmask = (cpumask_t){ { [0] = APIC_ALL_CPUS, } }; } +static void numaq_setup_portio_remap(void) +{ + int num_quads = num_online_nodes(); + + if (num_quads <= 1) + return; + + printk("Remapping cross-quad port I/O for %d quads\n", num_quads); + xquad_portio = ioremap(XQUAD_PORTIO_BASE, num_quads*XQUAD_PORTIO_QUAD); + printk("xquad_portio vaddr 0x%08lx, len %08lx\n", + (u_long) xquad_portio, (u_long) num_quads*XQUAD_PORTIO_QUAD); +} + struct genapic apic_numaq = { .name = "NUMAQ", @@ -71,7 +84,7 @@ struct genapic apic_numaq = { .cpu_to_logical_apicid = numaq_cpu_to_logical_apicid, .cpu_present_to_apicid = numaq_cpu_present_to_apicid, .apicid_to_cpu_present = numaq_apicid_to_cpu_present, - .setup_portio_remap = setup_portio_remap, + .setup_portio_remap = numaq_setup_portio_remap, .check_phys_apicid_present = check_phys_apicid_present, .enable_apic_mode = enable_apic_mode, .phys_pkg_id = phys_pkg_id, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index b6e37607a52..ffcf7ca2e8c 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -64,7 +64,7 @@ struct genapic apic_summit = { .cpu_to_logical_apicid = summit_cpu_to_logical_apicid, .cpu_present_to_apicid = summit_cpu_present_to_apicid, .apicid_to_cpu_present = summit_apicid_to_cpu_present, - .setup_portio_remap = setup_portio_remap, + .setup_portio_remap = NULL, .check_phys_apicid_present = check_phys_apicid_present, .enable_apic_mode = enable_apic_mode, .phys_pkg_id = phys_pkg_id, -- GitLab From a27a621001f4c3e57caf47feff4b014577fd01c6 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 12:43:18 +0100 Subject: [PATCH 0562/4982] x86: refactor ->check_phys_apicid_present() subarch methods - spread out the namespace to per driver methods - extend it to 64-bit as well so that we can use apic->check_phys_apicid_present() unconditionally Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 6 +++--- arch/x86/include/asm/es7000/apic.h | 4 ++-- arch/x86/include/asm/genapic.h | 1 + arch/x86/include/asm/mach-default/mach_apic.h | 18 +++++++++++++----- arch/x86/include/asm/mach-generic/mach_apic.h | 1 - arch/x86/include/asm/numaq/apic.h | 4 ++-- arch/x86/include/asm/summit/apic.h | 2 +- arch/x86/kernel/genapic_flat_64.c | 4 ++-- arch/x86/kernel/genx2apic_cluster.c | 2 +- arch/x86/kernel/genx2apic_phys.c | 2 +- arch/x86/kernel/genx2apic_uv_x.c | 2 +- arch/x86/kernel/smpboot.c | 7 ++++++- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 2 +- arch/x86/mach-generic/numaq.c | 2 +- arch/x86/mach-generic/summit.c | 2 +- 17 files changed, 38 insertions(+), 25 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index 2fa70032e3b..5ba4118fcdf 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h @@ -99,13 +99,13 @@ static inline void bigsmp_setup_portio_remap(void) { } -static inline void enable_apic_mode(void) +static inline int bigsmp_check_phys_apicid_present(int boot_cpu_physical_apicid) { + return 1; } -static inline int check_phys_apicid_present(int boot_cpu_physical_apicid) +static inline void enable_apic_mode(void) { - return (1); } /* As we are using single CPU as destination, pick only one CPU here */ diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index c5b0eb51e53..717c27f8da6 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -126,9 +126,9 @@ static inline physid_mask_t es7000_ioapic_phys_id_map(physid_mask_t phys_map) return physids_promote(0xff); } - extern unsigned int boot_cpu_physical_apicid; -static inline int check_phys_apicid_present(int cpu_physical_apicid) + +static inline int es7000_check_phys_apicid_present(int cpu_physical_apicid) { boot_cpu_physical_apicid = read_apic_id(); return (1); diff --git a/arch/x86/include/asm/genapic.h b/arch/x86/include/asm/genapic.h index 2cb14d51e45..f292fd02eba 100644 --- a/arch/x86/include/asm/genapic.h +++ b/arch/x86/include/asm/genapic.h @@ -110,6 +110,7 @@ DECLARE_PER_CPU(int, x2apic_extra_bits); extern void default_setup_apic_routing(void); extern int default_cpu_present_to_apicid(int mps_cpu); +extern int default_check_phys_apicid_present(int boot_cpu_physical_apicid); #endif #endif /* _ASM_X86_GENAPIC_64_H */ diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index 54c20e19e28..0a824d3a223 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -118,13 +118,26 @@ static inline int __default_cpu_present_to_apicid(int mps_cpu) return BAD_APICID; } +static inline int +__default_check_phys_apicid_present(int boot_cpu_physical_apicid) +{ + return physid_isset(boot_cpu_physical_apicid, phys_cpu_present_map); +} + #ifdef CONFIG_X86_32 static inline int default_cpu_present_to_apicid(int mps_cpu) { return __default_cpu_present_to_apicid(mps_cpu); } + +static inline int +default_check_phys_apicid_present(int boot_cpu_physical_apicid) +{ + return __default_check_phys_apicid_present(boot_cpu_physical_apicid); +} #else extern int default_cpu_present_to_apicid(int mps_cpu); +extern int default_check_phys_apicid_present(int boot_cpu_physical_apicid); #endif static inline physid_mask_t default_apicid_to_cpu_present(int phys_apicid) @@ -132,11 +145,6 @@ static inline physid_mask_t default_apicid_to_cpu_present(int phys_apicid) return physid_mask_of_physid(phys_apicid); } -static inline int check_phys_apicid_present(int boot_cpu_physical_apicid) -{ - return physid_isset(boot_cpu_physical_apicid, phys_cpu_present_map); -} - static inline void enable_apic_mode(void) { } diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index 393a97c5685..efd762d951a 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -3,7 +3,6 @@ #include -#define check_phys_apicid_present (apic->check_phys_apicid_present) #define cpu_mask_to_apicid (apic->cpu_mask_to_apicid) #define cpu_mask_to_apicid_and (apic->cpu_mask_to_apicid_and) #define enable_apic_mode (apic->enable_apic_mode) diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h index 6b626519cd7..3be735e2ab9 100644 --- a/arch/x86/include/asm/numaq/apic.h +++ b/arch/x86/include/asm/numaq/apic.h @@ -92,9 +92,9 @@ static inline physid_mask_t numaq_apicid_to_cpu_present(int logical_apicid) extern void *xquad_portio; -static inline int check_phys_apicid_present(int boot_cpu_physical_apicid) +static inline int numaq_check_phys_apicid_present(int boot_cpu_physical_apicid) { - return (1); + return 1; } static inline void enable_apic_mode(void) diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index 131343b0b75..fe578f6df78 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h @@ -120,7 +120,7 @@ static inline void summit_setup_portio_remap(void) { } -static inline int check_phys_apicid_present(int boot_cpu_physical_apicid) +static inline int summit_check_phys_apicid_present(int boot_cpu_physical_apicid) { return 1; } diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index f4a2c1c0a1a..78adf71f7e5 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -200,7 +200,7 @@ struct genapic apic_flat = { .cpu_present_to_apicid = default_cpu_present_to_apicid, .apicid_to_cpu_present = NULL, .setup_portio_remap = NULL, - .check_phys_apicid_present = NULL, + .check_phys_apicid_present = default_check_phys_apicid_present, .enable_apic_mode = NULL, .phys_pkg_id = phys_pkg_id, .mps_oem_check = NULL, @@ -344,7 +344,7 @@ struct genapic apic_physflat = { .cpu_present_to_apicid = default_cpu_present_to_apicid, .apicid_to_cpu_present = NULL, .setup_portio_remap = NULL, - .check_phys_apicid_present = NULL, + .check_phys_apicid_present = default_check_phys_apicid_present, .enable_apic_mode = NULL, .phys_pkg_id = phys_pkg_id, .mps_oem_check = NULL, diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c index 710d612a964..7062e24b18f 100644 --- a/arch/x86/kernel/genx2apic_cluster.c +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -202,7 +202,7 @@ struct genapic apic_x2apic_cluster = { .cpu_present_to_apicid = default_cpu_present_to_apicid, .apicid_to_cpu_present = NULL, .setup_portio_remap = NULL, - .check_phys_apicid_present = NULL, + .check_phys_apicid_present = default_check_phys_apicid_present, .enable_apic_mode = NULL, .phys_pkg_id = phys_pkg_id, .mps_oem_check = NULL, diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c index 49a449178c3..7177a1110f0 100644 --- a/arch/x86/kernel/genx2apic_phys.c +++ b/arch/x86/kernel/genx2apic_phys.c @@ -198,7 +198,7 @@ struct genapic apic_x2apic_phys = { .cpu_present_to_apicid = default_cpu_present_to_apicid, .apicid_to_cpu_present = NULL, .setup_portio_remap = NULL, - .check_phys_apicid_present = NULL, + .check_phys_apicid_present = default_check_phys_apicid_present, .enable_apic_mode = NULL, .phys_pkg_id = phys_pkg_id, .mps_oem_check = NULL, diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index a08a6359186..debd721f0b4 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -263,7 +263,7 @@ struct genapic apic_x2apic_uv_x = { .cpu_present_to_apicid = default_cpu_present_to_apicid, .apicid_to_cpu_present = NULL, .setup_portio_remap = NULL, - .check_phys_apicid_present = NULL, + .check_phys_apicid_present = default_check_phys_apicid_present, .enable_apic_mode = NULL, .phys_pkg_id = phys_pkg_id, .mps_oem_check = NULL, diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 0e7d26c01f9..ab83be2f8e0 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -908,6 +908,11 @@ int default_cpu_present_to_apicid(int mps_cpu) { return __default_cpu_present_to_apicid(mps_cpu); } + +int default_check_phys_apicid_present(int boot_cpu_physical_apicid) +{ + return __default_check_phys_apicid_present(boot_cpu_physical_apicid); +} #endif int __cpuinit native_cpu_up(unsigned int cpu) @@ -1058,7 +1063,7 @@ static int __init smp_sanity_check(unsigned max_cpus) * Should not be necessary because the MP table should list the boot * CPU too, but we do it for the sake of robustness anyway. */ - if (!check_phys_apicid_present(boot_cpu_physical_apicid)) { + if (!apic->check_phys_apicid_present(boot_cpu_physical_apicid)) { printk(KERN_NOTICE "weird, boot CPU (#%d) not listed by the BIOS.\n", boot_cpu_physical_apicid); diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 424740554a3..82743d16c23 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -85,7 +85,7 @@ struct genapic apic_bigsmp = { .cpu_present_to_apicid = bigsmp_cpu_present_to_apicid, .apicid_to_cpu_present = bigsmp_apicid_to_cpu_present, .setup_portio_remap = NULL, - .check_phys_apicid_present = check_phys_apicid_present, + .check_phys_apicid_present = bigsmp_check_phys_apicid_present, .enable_apic_mode = enable_apic_mode, .phys_pkg_id = phys_pkg_id, .mps_oem_check = mps_oem_check, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index b48a58daf71..d0374c69ad0 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -66,7 +66,7 @@ struct genapic apic_default = { .cpu_present_to_apicid = default_cpu_present_to_apicid, .apicid_to_cpu_present = default_apicid_to_cpu_present, .setup_portio_remap = NULL, - .check_phys_apicid_present = check_phys_apicid_present, + .check_phys_apicid_present = default_check_phys_apicid_present, .enable_apic_mode = enable_apic_mode, .phys_pkg_id = phys_pkg_id, .mps_oem_check = mps_oem_check, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 449eca5b604..52b3eb5e645 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -127,7 +127,7 @@ struct genapic apic_es7000 = { .cpu_present_to_apicid = es7000_cpu_present_to_apicid, .apicid_to_cpu_present = es7000_apicid_to_cpu_present, .setup_portio_remap = NULL, - .check_phys_apicid_present = check_phys_apicid_present, + .check_phys_apicid_present = es7000_check_phys_apicid_present, .enable_apic_mode = enable_apic_mode, .phys_pkg_id = phys_pkg_id, .mps_oem_check = mps_oem_check, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index e60361b0bf1..7ec2ca43ca2 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -85,7 +85,7 @@ struct genapic apic_numaq = { .cpu_present_to_apicid = numaq_cpu_present_to_apicid, .apicid_to_cpu_present = numaq_apicid_to_cpu_present, .setup_portio_remap = numaq_setup_portio_remap, - .check_phys_apicid_present = check_phys_apicid_present, + .check_phys_apicid_present = numaq_check_phys_apicid_present, .enable_apic_mode = enable_apic_mode, .phys_pkg_id = phys_pkg_id, .mps_oem_check = mps_oem_check, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index ffcf7ca2e8c..acf12de8916 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -65,7 +65,7 @@ struct genapic apic_summit = { .cpu_present_to_apicid = summit_cpu_present_to_apicid, .apicid_to_cpu_present = summit_apicid_to_cpu_present, .setup_portio_remap = NULL, - .check_phys_apicid_present = check_phys_apicid_present, + .check_phys_apicid_present = summit_check_phys_apicid_present, .enable_apic_mode = enable_apic_mode, .phys_pkg_id = phys_pkg_id, .mps_oem_check = mps_oem_check, -- GitLab From 4904033302c745342e3b3a611881cdee57fbe06a Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 12:43:18 +0100 Subject: [PATCH 0563/4982] x86: refactor ->enable_apic_mode() subarch methods Only ES7000 has a real ->enable_apic_mode() method, the other subarchitectures define it but keep it empty. So mark the vector as NULL, extend the generic code to handle NULL -setup_portio_remap() entries and remove all the empty handlers. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 4 ---- arch/x86/include/asm/mach-default/mach_apic.h | 3 --- arch/x86/include/asm/mach-generic/mach_apic.h | 1 - arch/x86/include/asm/numaq/apic.h | 4 ---- arch/x86/include/asm/summit/apic.h | 4 ---- arch/x86/kernel/apic.c | 3 ++- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 6 +++--- arch/x86/mach-generic/numaq.c | 2 +- arch/x86/mach-generic/summit.c | 2 +- 11 files changed, 9 insertions(+), 24 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index 5ba4118fcdf..f49d440862f 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h @@ -104,10 +104,6 @@ static inline int bigsmp_check_phys_apicid_present(int boot_cpu_physical_apicid) return 1; } -static inline void enable_apic_mode(void) -{ -} - /* As we are using single CPU as destination, pick only one CPU here */ static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask) { diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index 0a824d3a223..3647c92d45e 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -145,8 +145,5 @@ static inline physid_mask_t default_apicid_to_cpu_present(int phys_apicid) return physid_mask_of_physid(phys_apicid); } -static inline void enable_apic_mode(void) -{ -} #endif /* CONFIG_X86_LOCAL_APIC */ #endif /* _ASM_X86_MACH_DEFAULT_MACH_APIC_H */ diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index efd762d951a..6fed521585c 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -5,7 +5,6 @@ #define cpu_mask_to_apicid (apic->cpu_mask_to_apicid) #define cpu_mask_to_apicid_and (apic->cpu_mask_to_apicid_and) -#define enable_apic_mode (apic->enable_apic_mode) #define phys_pkg_id (apic->phys_pkg_id) #define wakeup_secondary_cpu (apic->wakeup_cpu) diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h index 3be735e2ab9..dc93c30972e 100644 --- a/arch/x86/include/asm/numaq/apic.h +++ b/arch/x86/include/asm/numaq/apic.h @@ -97,10 +97,6 @@ static inline int numaq_check_phys_apicid_present(int boot_cpu_physical_apicid) return 1; } -static inline void enable_apic_mode(void) -{ -} - /* * We use physical apicids here, not logical, so just return the default * physical broadcast to stop people from breaking us diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index fe578f6df78..526d19e7944 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h @@ -125,10 +125,6 @@ static inline int summit_check_phys_apicid_present(int boot_cpu_physical_apicid) return 1; } -static inline void enable_apic_mode(void) -{ -} - static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask) { int num_bits_set; diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index fcbcc03cd4b..9d6374da478 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -1763,7 +1763,8 @@ void __init connect_bsp_APIC(void) outb(0x01, 0x23); } #endif - enable_apic_mode(); + if (apic->enable_apic_mode) + apic->enable_apic_mode(); } /** diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 82743d16c23..e151b472456 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -86,7 +86,7 @@ struct genapic apic_bigsmp = { .apicid_to_cpu_present = bigsmp_apicid_to_cpu_present, .setup_portio_remap = NULL, .check_phys_apicid_present = bigsmp_check_phys_apicid_present, - .enable_apic_mode = enable_apic_mode, + .enable_apic_mode = NULL, .phys_pkg_id = phys_pkg_id, .mps_oem_check = mps_oem_check, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index d0374c69ad0..ac6be195b97 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -67,7 +67,7 @@ struct genapic apic_default = { .apicid_to_cpu_present = default_apicid_to_cpu_present, .setup_portio_remap = NULL, .check_phys_apicid_present = default_check_phys_apicid_present, - .enable_apic_mode = enable_apic_mode, + .enable_apic_mode = NULL, .phys_pkg_id = phys_pkg_id, .mps_oem_check = mps_oem_check, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 52b3eb5e645..9acb71120ef 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -36,10 +36,10 @@ static int probe_es7000(void) } extern void es7000_sw_apic(void); -static void __init enable_apic_mode(void) + +static void __init es7000_enable_apic_mode(void) { es7000_sw_apic(); - return; } static __init int @@ -128,7 +128,7 @@ struct genapic apic_es7000 = { .apicid_to_cpu_present = es7000_apicid_to_cpu_present, .setup_portio_remap = NULL, .check_phys_apicid_present = es7000_check_phys_apicid_present, - .enable_apic_mode = enable_apic_mode, + .enable_apic_mode = es7000_enable_apic_mode, .phys_pkg_id = phys_pkg_id, .mps_oem_check = mps_oem_check, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 7ec2ca43ca2..8d3358de3fe 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -86,7 +86,7 @@ struct genapic apic_numaq = { .apicid_to_cpu_present = numaq_apicid_to_cpu_present, .setup_portio_remap = numaq_setup_portio_remap, .check_phys_apicid_present = numaq_check_phys_apicid_present, - .enable_apic_mode = enable_apic_mode, + .enable_apic_mode = NULL, .phys_pkg_id = phys_pkg_id, .mps_oem_check = mps_oem_check, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index acf12de8916..cb83bcbb2de 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -66,7 +66,7 @@ struct genapic apic_summit = { .apicid_to_cpu_present = summit_apicid_to_cpu_present, .setup_portio_remap = NULL, .check_phys_apicid_present = summit_check_phys_apicid_present, - .enable_apic_mode = enable_apic_mode, + .enable_apic_mode = NULL, .phys_pkg_id = phys_pkg_id, .mps_oem_check = mps_oem_check, -- GitLab From b0b20e5a3a6615ae750804523aeedd32911bb9d6 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 13:15:06 +0100 Subject: [PATCH 0564/4982] x86, es7000: clean up es7000_enable_apic_mode() - eliminate the needless es7000_enable_apic_mode() complication which was not apparent prior the namespace cleanups - clean up the control flow in es7000_enable_apic_mode() - other cleanups Signed-off-by: Ingo Molnar --- arch/x86/include/asm/es7000/apic.h | 2 ++ arch/x86/kernel/es7000_32.c | 27 ++++++++++++++------------- arch/x86/mach-generic/es7000.c | 7 ------- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index 717c27f8da6..038c4f0e480 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -36,6 +36,8 @@ static inline unsigned long es7000_check_apicid_present(int bit) return physid_isset(bit, phys_cpu_present_map); } +extern void es7000_enable_apic_mode(void); + #define apicid_cluster(apicid) (apicid & 0xF0) static inline unsigned long calculate_ldr(int cpu) diff --git a/arch/x86/kernel/es7000_32.c b/arch/x86/kernel/es7000_32.c index 20a2a43c2a9..e73fe18488a 100644 --- a/arch/x86/kernel/es7000_32.c +++ b/arch/x86/kernel/es7000_32.c @@ -359,20 +359,21 @@ es7000_mip_write(struct mip_reg *mip_reg) return status; } -void __init -es7000_sw_apic(void) +void __init es7000_enable_apic_mode(void) { - if (es7000_plat) { - int mip_status; - struct mip_reg es7000_mip_reg; - - printk("ES7000: Enabling APIC mode.\n"); - memset(&es7000_mip_reg, 0, sizeof(struct mip_reg)); - es7000_mip_reg.off_0 = MIP_SW_APIC; - es7000_mip_reg.off_38 = (MIP_VALID); - while ((mip_status = es7000_mip_write(&es7000_mip_reg)) != 0) - printk("es7000_sw_apic: command failed, status = %x\n", - mip_status); + struct mip_reg es7000_mip_reg; + int mip_status; + + if (!es7000_plat) return; + + printk("ES7000: Enabling APIC mode.\n"); + memset(&es7000_mip_reg, 0, sizeof(struct mip_reg)); + es7000_mip_reg.off_0 = MIP_SW_APIC; + es7000_mip_reg.off_38 = MIP_VALID; + + while ((mip_status = es7000_mip_write(&es7000_mip_reg)) != 0) { + printk("es7000_enable_apic_mode: command failed, status = %x\n", + mip_status); } } diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 9acb71120ef..1185964b7a3 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -35,13 +35,6 @@ static int probe_es7000(void) return 0; } -extern void es7000_sw_apic(void); - -static void __init es7000_enable_apic_mode(void) -{ - es7000_sw_apic(); -} - static __init int mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) { -- GitLab From d4c9a9f3d416cfa1f5ffbe09d864d069467fe693 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 13:31:22 +0100 Subject: [PATCH 0565/4982] x86, apic: unify phys_pkg_id() - unify the call signature of 64-bit to that of 32-bit - clean up the types all around - clean up namespace contamination Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 2 +- arch/x86/include/asm/es7000/apic.h | 2 +- arch/x86/include/asm/genapic.h | 6 +----- arch/x86/include/asm/mach-default/mach_apic.h | 2 +- arch/x86/include/asm/numaq/apic.h | 2 +- arch/x86/include/asm/summit/apic.h | 5 +++-- arch/x86/kernel/cpu/addon_cpuid_features.c | 10 +--------- arch/x86/kernel/cpu/common.c | 11 +---------- arch/x86/kernel/genapic_flat_64.c | 6 +++--- arch/x86/kernel/genx2apic_cluster.c | 4 ++-- arch/x86/kernel/genx2apic_phys.c | 4 ++-- arch/x86/kernel/genx2apic_uv_x.c | 4 ++-- 12 files changed, 19 insertions(+), 39 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index f49d440862f..b7cba5b5635 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h @@ -133,7 +133,7 @@ static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *cpumask, return BAD_APICID; } -static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) +static inline int phys_pkg_id(int cpuid_apic, int index_msb) { return cpuid_apic >> index_msb; } diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index 038c4f0e480..d2c6c202e8b 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -221,7 +221,7 @@ static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *inmask, return apicid; } -static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) +static inline int phys_pkg_id(int cpuid_apic, int index_msb) { return cpuid_apic >> index_msb; } diff --git a/arch/x86/include/asm/genapic.h b/arch/x86/include/asm/genapic.h index f292fd02eba..14b19de8cd0 100644 --- a/arch/x86/include/asm/genapic.h +++ b/arch/x86/include/asm/genapic.h @@ -48,11 +48,7 @@ struct genapic { void (*setup_portio_remap)(void); int (*check_phys_apicid_present)(int boot_cpu_physical_apicid); void (*enable_apic_mode)(void); -#ifdef CONFIG_X86_32 - u32 (*phys_pkg_id)(u32 cpuid_apic, int index_msb); -#else - unsigned int (*phys_pkg_id)(int index_msb); -#endif + int (*phys_pkg_id)(int cpuid_apic, int index_msb); /* * When one of the next two hooks returns 1 the genapic diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index 3647c92d45e..55797a35150 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -65,7 +65,7 @@ static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *cpumask, return (unsigned int)(mask1 & mask2 & mask3); } -static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) +static inline int phys_pkg_id(int cpuid_apic, int index_msb) { return cpuid_apic >> index_msb; } diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h index dc93c30972e..bc2c8a425c0 100644 --- a/arch/x86/include/asm/numaq/apic.h +++ b/arch/x86/include/asm/numaq/apic.h @@ -113,7 +113,7 @@ static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *cpumask, } /* No NUMA-Q box has a HT CPU, but it can't hurt to use the default code. */ -static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) +static inline int phys_pkg_id(int cpuid_apic, int index_msb) { return cpuid_apic >> index_msb; } diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index 526d19e7944..64cd441ae00 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h @@ -175,13 +175,14 @@ static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *inmask, return apicid; } -/* cpuid returns the value latched in the HW at reset, not the APIC ID +/* + * cpuid returns the value latched in the HW at reset, not the APIC ID * register's value. For any box whose BIOS changes APIC IDs, like * clustered APIC systems, we must use hard_smp_processor_id. * * See Intel's IA-32 SW Dev's Manual Vol2 under CPUID. */ -static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) +static inline int phys_pkg_id(int cpuid_apic, int index_msb) { return hard_smp_processor_id() >> index_msb; } diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c index 4e581fdc0a5..84f8e4a5aef 100644 --- a/arch/x86/kernel/cpu/addon_cpuid_features.c +++ b/arch/x86/kernel/cpu/addon_cpuid_features.c @@ -116,7 +116,6 @@ void __cpuinit detect_extended_topology(struct cpuinfo_x86 *c) core_select_mask = (~(-1 << core_plus_mask_width)) >> ht_mask_width; -#ifdef CONFIG_X86_32 c->cpu_core_id = phys_pkg_id(c->initial_apicid, ht_mask_width) & core_select_mask; c->phys_proc_id = phys_pkg_id(c->initial_apicid, core_plus_mask_width); @@ -124,14 +123,7 @@ void __cpuinit detect_extended_topology(struct cpuinfo_x86 *c) * Reinit the apicid, now that we have extended initial_apicid. */ c->apicid = phys_pkg_id(c->initial_apicid, 0); -#else - c->cpu_core_id = phys_pkg_id(ht_mask_width) & core_select_mask; - c->phys_proc_id = phys_pkg_id(core_plus_mask_width); - /* - * Reinit the apicid, now that we have extended initial_apicid. - */ - c->apicid = phys_pkg_id(0); -#endif + c->x86_max_cores = (core_level_siblings / smp_num_siblings); diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 275e2cb43b9..93c491c4fe7 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -442,11 +442,7 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) } index_msb = get_count_order(smp_num_siblings); -#ifdef CONFIG_X86_64 - c->phys_proc_id = phys_pkg_id(index_msb); -#else c->phys_proc_id = phys_pkg_id(c->initial_apicid, index_msb); -#endif smp_num_siblings = smp_num_siblings / c->x86_max_cores; @@ -454,13 +450,8 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) core_bits = get_count_order(c->x86_max_cores); -#ifdef CONFIG_X86_64 - c->cpu_core_id = phys_pkg_id(index_msb) & - ((1 << core_bits) - 1); -#else c->cpu_core_id = phys_pkg_id(c->initial_apicid, index_msb) & ((1 << core_bits) - 1); -#endif } out: @@ -742,7 +733,7 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) this_cpu->c_identify(c); #ifdef CONFIG_X86_64 - c->apicid = phys_pkg_id(0); + c->apicid = phys_pkg_id(c->initial_apicid, 0); #endif /* diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index 78adf71f7e5..cc9e07b9609 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -169,7 +169,7 @@ static unsigned int flat_cpu_mask_to_apicid_and(const struct cpumask *cpumask, return mask1 & mask2; } -static unsigned int phys_pkg_id(int index_msb) +static int flat_phys_pkg_id(int initial_apic_id, int index_msb) { return hard_smp_processor_id() >> index_msb; } @@ -202,7 +202,7 @@ struct genapic apic_flat = { .setup_portio_remap = NULL, .check_phys_apicid_present = default_check_phys_apicid_present, .enable_apic_mode = NULL, - .phys_pkg_id = phys_pkg_id, + .phys_pkg_id = flat_phys_pkg_id, .mps_oem_check = NULL, .get_apic_id = get_apic_id, @@ -346,7 +346,7 @@ struct genapic apic_physflat = { .setup_portio_remap = NULL, .check_phys_apicid_present = default_check_phys_apicid_present, .enable_apic_mode = NULL, - .phys_pkg_id = phys_pkg_id, + .phys_pkg_id = flat_phys_pkg_id, .mps_oem_check = NULL, .get_apic_id = get_apic_id, diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c index 7062e24b18f..18b6f14376e 100644 --- a/arch/x86/kernel/genx2apic_cluster.c +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -157,7 +157,7 @@ static unsigned long set_apic_id(unsigned int id) return x; } -static unsigned int phys_pkg_id(int index_msb) +static int x2apic_cluster_phys_pkg_id(int initial_apicid, int index_msb) { return current_cpu_data.initial_apicid >> index_msb; } @@ -204,7 +204,7 @@ struct genapic apic_x2apic_cluster = { .setup_portio_remap = NULL, .check_phys_apicid_present = default_check_phys_apicid_present, .enable_apic_mode = NULL, - .phys_pkg_id = phys_pkg_id, + .phys_pkg_id = x2apic_cluster_phys_pkg_id, .mps_oem_check = NULL, .get_apic_id = get_apic_id, diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c index 7177a1110f0..2cb6f49e4c5 100644 --- a/arch/x86/kernel/genx2apic_phys.c +++ b/arch/x86/kernel/genx2apic_phys.c @@ -156,7 +156,7 @@ static unsigned long set_apic_id(unsigned int id) return x; } -static unsigned int phys_pkg_id(int index_msb) +static int x2apic_phys_pkg_id(int initial_apicid, int index_msb) { return current_cpu_data.initial_apicid >> index_msb; } @@ -200,7 +200,7 @@ struct genapic apic_x2apic_phys = { .setup_portio_remap = NULL, .check_phys_apicid_present = default_check_phys_apicid_present, .enable_apic_mode = NULL, - .phys_pkg_id = phys_pkg_id, + .phys_pkg_id = x2apic_phys_pkg_id, .mps_oem_check = NULL, .get_apic_id = get_apic_id, diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index debd721f0b4..67e7658775e 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -226,7 +226,7 @@ static unsigned int uv_read_apic_id(void) return get_apic_id(apic_read(APIC_ID)); } -static unsigned int phys_pkg_id(int index_msb) +static int uv_phys_pkg_id(int initial_apicid, int index_msb) { return uv_read_apic_id() >> index_msb; } @@ -265,7 +265,7 @@ struct genapic apic_x2apic_uv_x = { .setup_portio_remap = NULL, .check_phys_apicid_present = default_check_phys_apicid_present, .enable_apic_mode = NULL, - .phys_pkg_id = phys_pkg_id, + .phys_pkg_id = uv_phys_pkg_id, .mps_oem_check = NULL, .get_apic_id = get_apic_id, -- GitLab From cb8cc442dc7e07cb5438b357843ab4095ad73933 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 13:24:54 +0100 Subject: [PATCH 0566/4982] x86, apic: refactor ->phys_pkg_id() Refactor the ->phys_pkg_id() methods: - namespace separation - macro wrapper removal - open-coded calls to the methods in the generic code Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 2 +- arch/x86/include/asm/es7000/apic.h | 2 +- arch/x86/include/asm/mach-default/mach_apic.h | 3 +-- arch/x86/include/asm/mach-generic/mach_apic.h | 1 - arch/x86/include/asm/numaq/apic.h | 2 +- arch/x86/include/asm/summit/apic.h | 2 +- arch/x86/kernel/cpu/addon_cpuid_features.c | 6 +++--- arch/x86/kernel/cpu/common.c | 8 ++++---- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 2 +- arch/x86/mach-generic/numaq.c | 2 +- arch/x86/mach-generic/summit.c | 2 +- 13 files changed, 17 insertions(+), 19 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index b7cba5b5635..1230f5d7a38 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h @@ -133,7 +133,7 @@ static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *cpumask, return BAD_APICID; } -static inline int phys_pkg_id(int cpuid_apic, int index_msb) +static inline int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb) { return cpuid_apic >> index_msb; } diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index d2c6c202e8b..f183dfb4de4 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -221,7 +221,7 @@ static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *inmask, return apicid; } -static inline int phys_pkg_id(int cpuid_apic, int index_msb) +static inline int es7000_phys_pkg_id(int cpuid_apic, int index_msb) { return cpuid_apic >> index_msb; } diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index 55797a35150..d0605281a6b 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -21,7 +21,6 @@ static inline const struct cpumask *default_target_cpus(void) #include #define cpu_mask_to_apicid (apic->cpu_mask_to_apicid) #define cpu_mask_to_apicid_and (apic->cpu_mask_to_apicid_and) -#define phys_pkg_id (apic->phys_pkg_id) #define read_apic_id() (GET_APIC_ID(apic_read(APIC_ID))) #define send_IPI_self (apic->send_IPI_self) #define wakeup_secondary_cpu (apic->wakeup_cpu) @@ -65,7 +64,7 @@ static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *cpumask, return (unsigned int)(mask1 & mask2 & mask3); } -static inline int phys_pkg_id(int cpuid_apic, int index_msb) +static inline int default_phys_pkg_id(int cpuid_apic, int index_msb) { return cpuid_apic >> index_msb; } diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index 6fed521585c..1eeb5b61e48 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -5,7 +5,6 @@ #define cpu_mask_to_apicid (apic->cpu_mask_to_apicid) #define cpu_mask_to_apicid_and (apic->cpu_mask_to_apicid_and) -#define phys_pkg_id (apic->phys_pkg_id) #define wakeup_secondary_cpu (apic->wakeup_cpu) extern void generic_bigsmp_probe(void); diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h index bc2c8a425c0..765c4d5124c 100644 --- a/arch/x86/include/asm/numaq/apic.h +++ b/arch/x86/include/asm/numaq/apic.h @@ -113,7 +113,7 @@ static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *cpumask, } /* No NUMA-Q box has a HT CPU, but it can't hurt to use the default code. */ -static inline int phys_pkg_id(int cpuid_apic, int index_msb) +static inline int numaq_phys_pkg_id(int cpuid_apic, int index_msb) { return cpuid_apic >> index_msb; } diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index 64cd441ae00..fa6b3b45290 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h @@ -182,7 +182,7 @@ static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *inmask, * * See Intel's IA-32 SW Dev's Manual Vol2 under CPUID. */ -static inline int phys_pkg_id(int cpuid_apic, int index_msb) +static inline int summit_phys_pkg_id(int cpuid_apic, int index_msb) { return hard_smp_processor_id() >> index_msb; } diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c index 84f8e4a5aef..e8bb892c09f 100644 --- a/arch/x86/kernel/cpu/addon_cpuid_features.c +++ b/arch/x86/kernel/cpu/addon_cpuid_features.c @@ -116,13 +116,13 @@ void __cpuinit detect_extended_topology(struct cpuinfo_x86 *c) core_select_mask = (~(-1 << core_plus_mask_width)) >> ht_mask_width; - c->cpu_core_id = phys_pkg_id(c->initial_apicid, ht_mask_width) + c->cpu_core_id = apic->phys_pkg_id(c->initial_apicid, ht_mask_width) & core_select_mask; - c->phys_proc_id = phys_pkg_id(c->initial_apicid, core_plus_mask_width); + c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid, core_plus_mask_width); /* * Reinit the apicid, now that we have extended initial_apicid. */ - c->apicid = phys_pkg_id(c->initial_apicid, 0); + c->apicid = apic->phys_pkg_id(c->initial_apicid, 0); c->x86_max_cores = (core_level_siblings / smp_num_siblings); diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 93c491c4fe7..055b9c3a660 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -442,7 +442,7 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) } index_msb = get_count_order(smp_num_siblings); - c->phys_proc_id = phys_pkg_id(c->initial_apicid, index_msb); + c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid, index_msb); smp_num_siblings = smp_num_siblings / c->x86_max_cores; @@ -450,7 +450,7 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) core_bits = get_count_order(c->x86_max_cores); - c->cpu_core_id = phys_pkg_id(c->initial_apicid, index_msb) & + c->cpu_core_id = apic->phys_pkg_id(c->initial_apicid, index_msb) & ((1 << core_bits) - 1); } @@ -686,7 +686,7 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c) c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xFF; #ifdef CONFIG_X86_32 # ifdef CONFIG_X86_HT - c->apicid = phys_pkg_id(c->initial_apicid, 0); + c->apicid = apic->phys_pkg_id(c->initial_apicid, 0); # else c->apicid = c->initial_apicid; # endif @@ -733,7 +733,7 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) this_cpu->c_identify(c); #ifdef CONFIG_X86_64 - c->apicid = phys_pkg_id(c->initial_apicid, 0); + c->apicid = apic->phys_pkg_id(c->initial_apicid, 0); #endif /* diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index e151b472456..d04b38954df 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -87,7 +87,7 @@ struct genapic apic_bigsmp = { .setup_portio_remap = NULL, .check_phys_apicid_present = bigsmp_check_phys_apicid_present, .enable_apic_mode = NULL, - .phys_pkg_id = phys_pkg_id, + .phys_pkg_id = bigsmp_phys_pkg_id, .mps_oem_check = mps_oem_check, .get_apic_id = get_apic_id, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index ac6be195b97..5c9266f756e 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -68,7 +68,7 @@ struct genapic apic_default = { .setup_portio_remap = NULL, .check_phys_apicid_present = default_check_phys_apicid_present, .enable_apic_mode = NULL, - .phys_pkg_id = phys_pkg_id, + .phys_pkg_id = default_phys_pkg_id, .mps_oem_check = mps_oem_check, .get_apic_id = get_apic_id, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 1185964b7a3..52787e34c9c 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -122,7 +122,7 @@ struct genapic apic_es7000 = { .setup_portio_remap = NULL, .check_phys_apicid_present = es7000_check_phys_apicid_present, .enable_apic_mode = es7000_enable_apic_mode, - .phys_pkg_id = phys_pkg_id, + .phys_pkg_id = es7000_phys_pkg_id, .mps_oem_check = mps_oem_check, .get_apic_id = get_apic_id, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 8d3358de3fe..6a1134e6d72 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -87,7 +87,7 @@ struct genapic apic_numaq = { .setup_portio_remap = numaq_setup_portio_remap, .check_phys_apicid_present = numaq_check_phys_apicid_present, .enable_apic_mode = NULL, - .phys_pkg_id = phys_pkg_id, + .phys_pkg_id = numaq_phys_pkg_id, .mps_oem_check = mps_oem_check, .get_apic_id = get_apic_id, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index cb83bcbb2de..2d6843a61d9 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -67,7 +67,7 @@ struct genapic apic_summit = { .setup_portio_remap = NULL, .check_phys_apicid_present = summit_check_phys_apicid_present, .enable_apic_mode = NULL, - .phys_pkg_id = phys_pkg_id, + .phys_pkg_id = summit_phys_pkg_id, .mps_oem_check = mps_oem_check, .get_apic_id = get_apic_id, -- GitLab From 5f836405ef632ba82f4a5261ff2be4198e53b51b Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 13:47:42 +0100 Subject: [PATCH 0567/4982] x86, smp: clean up mps_oem_check() Impact: cleanup - allow NULL ->mps_oem_check() entries - clean up the code flow Signed-off-by: Ingo Molnar --- arch/x86/include/asm/genapic.h | 3 +-- arch/x86/mach-generic/probe.c | 22 +++++++++++++--------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/arch/x86/include/asm/genapic.h b/arch/x86/include/asm/genapic.h index 14b19de8cd0..8bb1c73c55b 100644 --- a/arch/x86/include/asm/genapic.h +++ b/arch/x86/include/asm/genapic.h @@ -55,8 +55,7 @@ struct genapic { * is switched to this. Essentially they are additional * probe functions: */ - int (*mps_oem_check)(struct mpc_table *mpc, char *oem, - char *productid); + int (*mps_oem_check)(struct mpc_table *mpc, char *oem, char *productid); unsigned int (*get_apic_id)(unsigned long x); unsigned long (*set_apic_id)(unsigned int id); diff --git a/arch/x86/mach-generic/probe.c b/arch/x86/mach-generic/probe.c index a21e2b1a701..799a70f4d90 100644 --- a/arch/x86/mach-generic/probe.c +++ b/arch/x86/mach-generic/probe.c @@ -113,17 +113,21 @@ void __init generic_apic_probe(void) int __init mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) { int i; + for (i = 0; apic_probe[i]; ++i) { - if (apic_probe[i]->mps_oem_check(mpc, oem, productid)) { - if (!cmdline_apic) { - apic = apic_probe[i]; - if (x86_quirks->update_genapic) - x86_quirks->update_genapic(); - printk(KERN_INFO "Switched to APIC driver `%s'.\n", - apic->name); - } - return 1; + if (!apic_probe[i]->mps_oem_check) + continue; + if (!apic_probe[i]->mps_oem_check(mpc, oem, productid)) + continue; + + if (!cmdline_apic) { + apic = apic_probe[i]; + if (x86_quirks->update_genapic) + x86_quirks->update_genapic(); + printk(KERN_INFO "Switched to APIC driver `%s'.\n", + apic->name); } + return 1; } return 0; } -- GitLab From 1322a2e2db87c938d8381f8501af9a4d0eab8bc7 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 13:54:56 +0100 Subject: [PATCH 0568/4982] x86, mpparse: call the generic quirk handlers early Call all the registered MPS quirk handlers early. These methods scan low RAM typically for specific signatures so are safe to be called early. Signed-off-by: Ingo Molnar --- arch/x86/kernel/mpparse.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index c8a534a16d9..f6fb1928439 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -292,16 +292,7 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) return 0; #ifdef CONFIG_X86_32 - /* - * need to make sure summit and es7000's mps_oem_check is safe to be - * called early via genericarch 's mps_oem_check - */ - if (early) { -#ifdef CONFIG_X86_NUMAQ - numaq_mps_oem_check(mpc, oem, str); -#endif - } else - mps_oem_check(mpc, oem, str); + mps_oem_check(mpc, oem, str); #endif /* save the local APIC address, it might be non-default */ if (!acpi_lapic) -- GitLab From 9c7642470ecf03d8b4946a2addc8fe631b8426dd Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 13:44:32 +0100 Subject: [PATCH 0569/4982] x86: consolidate the ->mps_oem_check() code - spread out the mps_oem_check() namespace on a per APIC driver basis Signed-off-by: Ingo Molnar --- arch/x86/include/asm/es7000/mpparse.h | 6 ------ arch/x86/include/asm/mach-default/mach_mpparse.h | 2 +- arch/x86/include/asm/mach-generic/mach_mpparse.h | 3 +-- arch/x86/include/asm/summit/mpparse.h | 4 ++-- arch/x86/kernel/mpparse.c | 2 +- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 5 +++-- arch/x86/mach-generic/numaq.c | 4 ++-- arch/x86/mach-generic/probe.c | 3 ++- arch/x86/mach-generic/summit.c | 2 +- 11 files changed, 15 insertions(+), 20 deletions(-) diff --git a/arch/x86/include/asm/es7000/mpparse.h b/arch/x86/include/asm/es7000/mpparse.h index 30692c4ae85..662eb1e574d 100644 --- a/arch/x86/include/asm/es7000/mpparse.h +++ b/arch/x86/include/asm/es7000/mpparse.h @@ -8,13 +8,7 @@ extern int find_unisys_acpi_oem_table(unsigned long *oem_addr); extern void unmap_unisys_acpi_oem_table(unsigned long oem_addr); extern void setup_unisys(void); -#ifndef CONFIG_X86_GENERICARCH -extern int default_acpi_madt_oem_check(char *oem_id, char *oem_table_id); -extern int mps_oem_check(struct mpc_table *mpc, char *oem, char *productid); -#endif - #ifdef CONFIG_ACPI - static inline int es7000_check_dsdt(void) { struct acpi_table_header header; diff --git a/arch/x86/include/asm/mach-default/mach_mpparse.h b/arch/x86/include/asm/mach-default/mach_mpparse.h index 8fa01770ba6..af0da140df9 100644 --- a/arch/x86/include/asm/mach-default/mach_mpparse.h +++ b/arch/x86/include/asm/mach-default/mach_mpparse.h @@ -2,7 +2,7 @@ #define _ASM_X86_MACH_DEFAULT_MACH_MPPARSE_H static inline int -mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) +generic_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) { return 0; } diff --git a/arch/x86/include/asm/mach-generic/mach_mpparse.h b/arch/x86/include/asm/mach-generic/mach_mpparse.h index f497d96c76b..22bfb56f8fb 100644 --- a/arch/x86/include/asm/mach-generic/mach_mpparse.h +++ b/arch/x86/include/asm/mach-generic/mach_mpparse.h @@ -1,8 +1,7 @@ #ifndef _ASM_X86_MACH_GENERIC_MACH_MPPARSE_H #define _ASM_X86_MACH_GENERIC_MACH_MPPARSE_H - -extern int mps_oem_check(struct mpc_table *, char *, char *); +extern int generic_mps_oem_check(struct mpc_table *, char *, char *); extern int default_acpi_madt_oem_check(char *, char *); diff --git a/arch/x86/include/asm/summit/mpparse.h b/arch/x86/include/asm/summit/mpparse.h index 555ed8238e9..4bbcce39acb 100644 --- a/arch/x86/include/asm/summit/mpparse.h +++ b/arch/x86/include/asm/summit/mpparse.h @@ -11,8 +11,8 @@ extern void setup_summit(void); #define setup_summit() {} #endif -static inline int mps_oem_check(struct mpc_table *mpc, char *oem, - char *productid) +static inline int +summit_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) { if (!strncmp(oem, "IBM ENSW", 8) && (!strncmp(productid, "VIGIL SMP", 9) diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index f6fb1928439..b12fa5ce6f5 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -292,7 +292,7 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) return 0; #ifdef CONFIG_X86_32 - mps_oem_check(mpc, oem, str); + generic_mps_oem_check(mpc, oem, str); #endif /* save the local APIC address, it might be non-default */ if (!acpi_lapic) diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index d04b38954df..6bf6aafeb2c 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -88,7 +88,7 @@ struct genapic apic_bigsmp = { .check_phys_apicid_present = bigsmp_check_phys_apicid_present, .enable_apic_mode = NULL, .phys_pkg_id = bigsmp_phys_pkg_id, - .mps_oem_check = mps_oem_check, + .mps_oem_check = NULL, .get_apic_id = get_apic_id, .set_apic_id = NULL, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index 5c9266f756e..e5f85cd75b4 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -69,7 +69,7 @@ struct genapic apic_default = { .check_phys_apicid_present = default_check_phys_apicid_present, .enable_apic_mode = NULL, .phys_pkg_id = default_phys_pkg_id, - .mps_oem_check = mps_oem_check, + .mps_oem_check = NULL, .get_apic_id = get_apic_id, .set_apic_id = NULL, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 52787e34c9c..f861163cd39 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -36,11 +36,12 @@ static int probe_es7000(void) } static __init int -mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) +es7000_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) { if (mpc->oemptr) { struct mpc_oemtable *oem_table = (struct mpc_oemtable *)mpc->oemptr; + if (!strncmp(oem, "UNISYS", 6)) return parse_unisys_oem((char *)oem_table); } @@ -123,7 +124,7 @@ struct genapic apic_es7000 = { .check_phys_apicid_present = es7000_check_phys_apicid_present, .enable_apic_mode = es7000_enable_apic_mode, .phys_pkg_id = es7000_phys_pkg_id, - .mps_oem_check = mps_oem_check, + .mps_oem_check = es7000_mps_oem_check, .get_apic_id = get_apic_id, .set_apic_id = NULL, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 6a1134e6d72..517882c9c15 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -19,7 +19,7 @@ #include #include -static int mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) +static int __numaq_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) { numaq_mps_oem_check(mpc, oem, productid); return found_numaq; @@ -88,7 +88,7 @@ struct genapic apic_numaq = { .check_phys_apicid_present = numaq_check_phys_apicid_present, .enable_apic_mode = NULL, .phys_pkg_id = numaq_phys_pkg_id, - .mps_oem_check = mps_oem_check, + .mps_oem_check = __numaq_mps_oem_check, .get_apic_id = get_apic_id, .set_apic_id = NULL, diff --git a/arch/x86/mach-generic/probe.c b/arch/x86/mach-generic/probe.c index 799a70f4d90..ab68c6e5c48 100644 --- a/arch/x86/mach-generic/probe.c +++ b/arch/x86/mach-generic/probe.c @@ -110,7 +110,8 @@ void __init generic_apic_probe(void) /* These functions can switch the APIC even after the initial ->probe() */ -int __init mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) +int __init +generic_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) { int i; diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 2d6843a61d9..719e944ff30 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -68,7 +68,7 @@ struct genapic apic_summit = { .check_phys_apicid_present = summit_check_phys_apicid_present, .enable_apic_mode = NULL, .phys_pkg_id = summit_phys_pkg_id, - .mps_oem_check = mps_oem_check, + .mps_oem_check = summit_mps_oem_check, .get_apic_id = get_apic_id, .set_apic_id = NULL, -- GitLab From ca6c8ed4646f8ccaa4f7db618bf69b8b8fb49767 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 14:08:38 +0100 Subject: [PATCH 0570/4982] x86, apic: refactor ->get_apic_id() & GET_APIC_ID() - spread out the namespace on a per driver basis - get rid of macro wrappers - small cleanups Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apicdef.h | 6 ++---- arch/x86/include/asm/es7000/apicdef.h | 6 ++---- arch/x86/include/asm/mach-default/mach_apic.h | 2 +- arch/x86/include/asm/mach-default/mach_apicdef.h | 10 +++++----- arch/x86/include/asm/mach-generic/mach_apicdef.h | 1 - arch/x86/include/asm/numaq/apicdef.h | 7 ++----- arch/x86/include/asm/smp.h | 2 +- arch/x86/include/asm/summit/apicdef.h | 6 ++---- arch/x86/kernel/genapic_flat_64.c | 9 +++++---- arch/x86/kernel/genx2apic_cluster.c | 4 ++-- arch/x86/kernel/genx2apic_phys.c | 4 ++-- arch/x86/kernel/genx2apic_uv_x.c | 6 +++--- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 2 +- arch/x86/mach-generic/numaq.c | 2 +- arch/x86/mach-generic/summit.c | 2 +- 17 files changed, 32 insertions(+), 41 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apicdef.h b/arch/x86/include/asm/bigsmp/apicdef.h index 392c3f5ef2f..ed25dd6503b 100644 --- a/arch/x86/include/asm/bigsmp/apicdef.h +++ b/arch/x86/include/asm/bigsmp/apicdef.h @@ -3,11 +3,9 @@ #define APIC_ID_MASK (0xFF<<24) -static inline unsigned get_apic_id(unsigned long x) +static inline unsigned bigsmp_get_apic_id(unsigned long x) { - return (((x)>>24)&0xFF); + return (x >> 24) & 0xFF; } -#define GET_APIC_ID(x) get_apic_id(x) - #endif diff --git a/arch/x86/include/asm/es7000/apicdef.h b/arch/x86/include/asm/es7000/apicdef.h index 8b234a3cb85..e23791762a1 100644 --- a/arch/x86/include/asm/es7000/apicdef.h +++ b/arch/x86/include/asm/es7000/apicdef.h @@ -3,11 +3,9 @@ #define APIC_ID_MASK (0xFF<<24) -static inline unsigned get_apic_id(unsigned long x) +static inline unsigned int es7000_get_apic_id(unsigned long x) { - return (((x)>>24)&0xFF); + return (x >> 24) & 0xFF; } -#define GET_APIC_ID(x) get_apic_id(x) - #endif diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index d0605281a6b..8719208f273 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -21,7 +21,7 @@ static inline const struct cpumask *default_target_cpus(void) #include #define cpu_mask_to_apicid (apic->cpu_mask_to_apicid) #define cpu_mask_to_apicid_and (apic->cpu_mask_to_apicid_and) -#define read_apic_id() (GET_APIC_ID(apic_read(APIC_ID))) +#define read_apic_id() (apic->get_apic_id(apic_read(APIC_ID))) #define send_IPI_self (apic->send_IPI_self) #define wakeup_secondary_cpu (apic->wakeup_cpu) extern void default_setup_apic_routing(void); diff --git a/arch/x86/include/asm/mach-default/mach_apicdef.h b/arch/x86/include/asm/mach-default/mach_apicdef.h index b4dcc0971c7..e84d437ba2b 100644 --- a/arch/x86/include/asm/mach-default/mach_apicdef.h +++ b/arch/x86/include/asm/mach-default/mach_apicdef.h @@ -5,20 +5,20 @@ #ifdef CONFIG_X86_64 #define APIC_ID_MASK (apic->apic_id_mask) -#define GET_APIC_ID(x) (apic->get_apic_id(x)) #define SET_APIC_ID(x) (apic->set_apic_id(x)) #else #define APIC_ID_MASK (0xF<<24) -static inline unsigned get_apic_id(unsigned long x) + +static inline unsigned default_get_apic_id(unsigned long x) { unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR)); + if (APIC_XAPIC(ver)) - return (((x)>>24)&0xFF); + return (x >> 24) & 0xFF; else - return (((x)>>24)&0xF); + return (x >> 24) & 0x0F; } -#define GET_APIC_ID(x) get_apic_id(x) #endif #endif /* _ASM_X86_MACH_DEFAULT_MACH_APICDEF_H */ diff --git a/arch/x86/include/asm/mach-generic/mach_apicdef.h b/arch/x86/include/asm/mach-generic/mach_apicdef.h index acc9adddb34..645520bcd2c 100644 --- a/arch/x86/include/asm/mach-generic/mach_apicdef.h +++ b/arch/x86/include/asm/mach-generic/mach_apicdef.h @@ -4,7 +4,6 @@ #ifndef APIC_DEFINITION #include -#define GET_APIC_ID (apic->get_apic_id) #define APIC_ID_MASK (apic->apic_id_mask) #endif diff --git a/arch/x86/include/asm/numaq/apicdef.h b/arch/x86/include/asm/numaq/apicdef.h index e012a46cc22..29f5e3d34e5 100644 --- a/arch/x86/include/asm/numaq/apicdef.h +++ b/arch/x86/include/asm/numaq/apicdef.h @@ -1,14 +1,11 @@ #ifndef __ASM_NUMAQ_APICDEF_H #define __ASM_NUMAQ_APICDEF_H - #define APIC_ID_MASK (0xF<<24) -static inline unsigned get_apic_id(unsigned long x) +static inline unsigned int numaq_get_apic_id(unsigned long x) { - return (((x)>>24)&0x0F); + return (x >> 24) & 0x0F; } -#define GET_APIC_ID(x) get_apic_id(x) - #endif diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index 45ef8a1b9d7..c63d480802a 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -189,7 +189,7 @@ static inline unsigned int read_apic_id(void) reg = *(u32 *)(APIC_BASE + APIC_ID); - return GET_APIC_ID(reg); + return apic->get_apic_id(reg); } #endif diff --git a/arch/x86/include/asm/summit/apicdef.h b/arch/x86/include/asm/summit/apicdef.h index f3fbca1f61c..4286528af7c 100644 --- a/arch/x86/include/asm/summit/apicdef.h +++ b/arch/x86/include/asm/summit/apicdef.h @@ -3,11 +3,9 @@ #define APIC_ID_MASK (0xFF<<24) -static inline unsigned get_apic_id(unsigned long x) +static inline unsigned summit_get_apic_id(unsigned long x) { - return (x>>24)&0xFF; + return (x >> 24) & 0xFF; } -#define GET_APIC_ID(x) get_apic_id(x) - #endif diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index cc9e07b9609..ab47091dac2 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -126,11 +126,12 @@ static void flat_send_IPI_all(int vector) __send_IPI_shortcut(APIC_DEST_ALLINC, vector, apic->dest_logical); } -static unsigned int get_apic_id(unsigned long x) +static unsigned int flat_get_apic_id(unsigned long x) { unsigned int id; id = (((x)>>24) & 0xFFu); + return id; } @@ -146,7 +147,7 @@ static unsigned int read_xapic_id(void) { unsigned int id; - id = get_apic_id(apic_read(APIC_ID)); + id = flat_get_apic_id(apic_read(APIC_ID)); return id; } @@ -205,7 +206,7 @@ struct genapic apic_flat = { .phys_pkg_id = flat_phys_pkg_id, .mps_oem_check = NULL, - .get_apic_id = get_apic_id, + .get_apic_id = flat_get_apic_id, .set_apic_id = set_apic_id, .apic_id_mask = 0xFFu << 24, @@ -349,7 +350,7 @@ struct genapic apic_physflat = { .phys_pkg_id = flat_phys_pkg_id, .mps_oem_check = NULL, - .get_apic_id = get_apic_id, + .get_apic_id = flat_get_apic_id, .set_apic_id = set_apic_id, .apic_id_mask = 0xFFu<<24, diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c index 18b6f14376e..c7557e05184 100644 --- a/arch/x86/kernel/genx2apic_cluster.c +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -141,7 +141,7 @@ static unsigned int x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, return BAD_APICID; } -static unsigned int get_apic_id(unsigned long x) +static unsigned int x2apic_cluster_phys_get_apic_id(unsigned long x) { unsigned int id; @@ -207,7 +207,7 @@ struct genapic apic_x2apic_cluster = { .phys_pkg_id = x2apic_cluster_phys_pkg_id, .mps_oem_check = NULL, - .get_apic_id = get_apic_id, + .get_apic_id = x2apic_cluster_phys_get_apic_id, .set_apic_id = set_apic_id, .apic_id_mask = 0xFFFFFFFFu, diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c index 2cb6f49e4c5..80cba49cfd8 100644 --- a/arch/x86/kernel/genx2apic_phys.c +++ b/arch/x86/kernel/genx2apic_phys.c @@ -140,7 +140,7 @@ static unsigned int x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, return BAD_APICID; } -static unsigned int get_apic_id(unsigned long x) +static unsigned int x2apic_phys_get_apic_id(unsigned long x) { unsigned int id; @@ -203,7 +203,7 @@ struct genapic apic_x2apic_phys = { .phys_pkg_id = x2apic_phys_pkg_id, .mps_oem_check = NULL, - .get_apic_id = get_apic_id, + .get_apic_id = x2apic_phys_get_apic_id, .set_apic_id = set_apic_id, .apic_id_mask = 0xFFFFFFFFu, diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index 67e7658775e..50310b96adc 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -201,7 +201,7 @@ static unsigned int uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask, return BAD_APICID; } -static unsigned int get_apic_id(unsigned long x) +static unsigned int x2apic_get_apic_id(unsigned long x) { unsigned int id; @@ -223,7 +223,7 @@ static unsigned long set_apic_id(unsigned int id) static unsigned int uv_read_apic_id(void) { - return get_apic_id(apic_read(APIC_ID)); + return x2apic_get_apic_id(apic_read(APIC_ID)); } static int uv_phys_pkg_id(int initial_apicid, int index_msb) @@ -268,7 +268,7 @@ struct genapic apic_x2apic_uv_x = { .phys_pkg_id = uv_phys_pkg_id, .mps_oem_check = NULL, - .get_apic_id = get_apic_id, + .get_apic_id = x2apic_get_apic_id, .set_apic_id = set_apic_id, .apic_id_mask = 0xFFFFFFFFu, diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 6bf6aafeb2c..9eca977227c 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -90,7 +90,7 @@ struct genapic apic_bigsmp = { .phys_pkg_id = bigsmp_phys_pkg_id, .mps_oem_check = NULL, - .get_apic_id = get_apic_id, + .get_apic_id = bigsmp_get_apic_id, .set_apic_id = NULL, .apic_id_mask = APIC_ID_MASK, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index e5f85cd75b4..d51a3f0335a 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -71,7 +71,7 @@ struct genapic apic_default = { .phys_pkg_id = default_phys_pkg_id, .mps_oem_check = NULL, - .get_apic_id = get_apic_id, + .get_apic_id = default_get_apic_id, .set_apic_id = NULL, .apic_id_mask = APIC_ID_MASK, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index f861163cd39..1944675db62 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -126,7 +126,7 @@ struct genapic apic_es7000 = { .phys_pkg_id = es7000_phys_pkg_id, .mps_oem_check = es7000_mps_oem_check, - .get_apic_id = get_apic_id, + .get_apic_id = es7000_get_apic_id, .set_apic_id = NULL, .apic_id_mask = APIC_ID_MASK, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 517882c9c15..fcbba84c090 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -90,7 +90,7 @@ struct genapic apic_numaq = { .phys_pkg_id = numaq_phys_pkg_id, .mps_oem_check = __numaq_mps_oem_check, - .get_apic_id = get_apic_id, + .get_apic_id = numaq_get_apic_id, .set_apic_id = NULL, .apic_id_mask = APIC_ID_MASK, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 719e944ff30..5650eaf9061 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -70,7 +70,7 @@ struct genapic apic_summit = { .phys_pkg_id = summit_phys_pkg_id, .mps_oem_check = summit_mps_oem_check, - .get_apic_id = get_apic_id, + .get_apic_id = summit_get_apic_id, .set_apic_id = NULL, .apic_id_mask = APIC_ID_MASK, -- GitLab From 5b8127277bc4cdca78eda5ee900a314642822ace Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 14:59:17 +0100 Subject: [PATCH 0571/4982] x86, apic: refactor ->apic_id_mask & APIC_ID_MASK - spread out the namespace on a per driver basis - get rid of wrapper macros Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apicdef.h | 2 +- arch/x86/include/asm/es7000/apicdef.h | 2 +- arch/x86/include/asm/mach-default/mach_apicdef.h | 3 +-- arch/x86/include/asm/mach-generic/mach_apicdef.h | 2 -- arch/x86/include/asm/numaq/apicdef.h | 2 +- arch/x86/include/asm/summit/apicdef.h | 2 +- arch/x86/kernel/apic.c | 4 ++-- arch/x86/kernel/genapic_flat_64.c | 2 +- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 2 +- arch/x86/mach-generic/numaq.c | 2 +- arch/x86/mach-generic/summit.c | 2 +- 13 files changed, 13 insertions(+), 16 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apicdef.h b/arch/x86/include/asm/bigsmp/apicdef.h index ed25dd6503b..6e587818c7e 100644 --- a/arch/x86/include/asm/bigsmp/apicdef.h +++ b/arch/x86/include/asm/bigsmp/apicdef.h @@ -1,7 +1,7 @@ #ifndef __ASM_MACH_APICDEF_H #define __ASM_MACH_APICDEF_H -#define APIC_ID_MASK (0xFF<<24) +#define BIGSMP_APIC_ID_MASK (0xFF<<24) static inline unsigned bigsmp_get_apic_id(unsigned long x) { diff --git a/arch/x86/include/asm/es7000/apicdef.h b/arch/x86/include/asm/es7000/apicdef.h index e23791762a1..476da0c7f5c 100644 --- a/arch/x86/include/asm/es7000/apicdef.h +++ b/arch/x86/include/asm/es7000/apicdef.h @@ -1,7 +1,7 @@ #ifndef __ASM_ES7000_APICDEF_H #define __ASM_ES7000_APICDEF_H -#define APIC_ID_MASK (0xFF<<24) +#define ES7000_APIC_ID_MASK (0xFF<<24) static inline unsigned int es7000_get_apic_id(unsigned long x) { diff --git a/arch/x86/include/asm/mach-default/mach_apicdef.h b/arch/x86/include/asm/mach-default/mach_apicdef.h index e84d437ba2b..8318d121ea6 100644 --- a/arch/x86/include/asm/mach-default/mach_apicdef.h +++ b/arch/x86/include/asm/mach-default/mach_apicdef.h @@ -4,10 +4,9 @@ #include #ifdef CONFIG_X86_64 -#define APIC_ID_MASK (apic->apic_id_mask) #define SET_APIC_ID(x) (apic->set_apic_id(x)) #else -#define APIC_ID_MASK (0xF<<24) +#define DEFAULT_APIC_ID_MASK (0x0F<<24) static inline unsigned default_get_apic_id(unsigned long x) { diff --git a/arch/x86/include/asm/mach-generic/mach_apicdef.h b/arch/x86/include/asm/mach-generic/mach_apicdef.h index 645520bcd2c..61caa65b13f 100644 --- a/arch/x86/include/asm/mach-generic/mach_apicdef.h +++ b/arch/x86/include/asm/mach-generic/mach_apicdef.h @@ -3,8 +3,6 @@ #ifndef APIC_DEFINITION #include - -#define APIC_ID_MASK (apic->apic_id_mask) #endif #endif /* _ASM_X86_MACH_GENERIC_MACH_APICDEF_H */ diff --git a/arch/x86/include/asm/numaq/apicdef.h b/arch/x86/include/asm/numaq/apicdef.h index 29f5e3d34e5..6f2cc5df0b1 100644 --- a/arch/x86/include/asm/numaq/apicdef.h +++ b/arch/x86/include/asm/numaq/apicdef.h @@ -1,7 +1,7 @@ #ifndef __ASM_NUMAQ_APICDEF_H #define __ASM_NUMAQ_APICDEF_H -#define APIC_ID_MASK (0xF<<24) +#define NUMAQ_APIC_ID_MASK (0xF<<24) static inline unsigned int numaq_get_apic_id(unsigned long x) { diff --git a/arch/x86/include/asm/summit/apicdef.h b/arch/x86/include/asm/summit/apicdef.h index 4286528af7c..0373f0c7b5d 100644 --- a/arch/x86/include/asm/summit/apicdef.h +++ b/arch/x86/include/asm/summit/apicdef.h @@ -1,7 +1,7 @@ #ifndef __ASM_SUMMIT_APICDEF_H #define __ASM_SUMMIT_APICDEF_H -#define APIC_ID_MASK (0xFF<<24) +#define SUMMIT_APIC_ID_MASK (0xFF<<24) static inline unsigned summit_get_apic_id(unsigned long x) { diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 9d6374da478..5f7f3a9a47a 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -1009,11 +1009,11 @@ int __init verify_local_APIC(void) */ reg0 = apic_read(APIC_ID); apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0); - apic_write(APIC_ID, reg0 ^ APIC_ID_MASK); + apic_write(APIC_ID, reg0 ^ apic->apic_id_mask); reg1 = apic_read(APIC_ID); apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg1); apic_write(APIC_ID, reg0); - if (reg1 != (reg0 ^ APIC_ID_MASK)) + if (reg1 != (reg0 ^ apic->apic_id_mask)) return 0; /* diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index ab47091dac2..78baa55cd0e 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -352,7 +352,7 @@ struct genapic apic_physflat = { .get_apic_id = flat_get_apic_id, .set_apic_id = set_apic_id, - .apic_id_mask = 0xFFu<<24, + .apic_id_mask = 0xFFu << 24, .cpu_mask_to_apicid = physflat_cpu_mask_to_apicid, .cpu_mask_to_apicid_and = physflat_cpu_mask_to_apicid_and, diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 9eca977227c..1f4ad4f7702 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -92,7 +92,7 @@ struct genapic apic_bigsmp = { .get_apic_id = bigsmp_get_apic_id, .set_apic_id = NULL, - .apic_id_mask = APIC_ID_MASK, + .apic_id_mask = BIGSMP_APIC_ID_MASK, .cpu_mask_to_apicid = cpu_mask_to_apicid, .cpu_mask_to_apicid_and = cpu_mask_to_apicid_and, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index d51a3f0335a..239af25615b 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -73,7 +73,7 @@ struct genapic apic_default = { .get_apic_id = default_get_apic_id, .set_apic_id = NULL, - .apic_id_mask = APIC_ID_MASK, + .apic_id_mask = DEFAULT_APIC_ID_MASK, .cpu_mask_to_apicid = cpu_mask_to_apicid, .cpu_mask_to_apicid_and = cpu_mask_to_apicid_and, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 1944675db62..21fb33eea91 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -128,7 +128,7 @@ struct genapic apic_es7000 = { .get_apic_id = es7000_get_apic_id, .set_apic_id = NULL, - .apic_id_mask = APIC_ID_MASK, + .apic_id_mask = ES7000_APIC_ID_MASK, .cpu_mask_to_apicid = cpu_mask_to_apicid, .cpu_mask_to_apicid_and = cpu_mask_to_apicid_and, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index fcbba84c090..27d2d1f2d6f 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -92,7 +92,7 @@ struct genapic apic_numaq = { .get_apic_id = numaq_get_apic_id, .set_apic_id = NULL, - .apic_id_mask = APIC_ID_MASK, + .apic_id_mask = NUMAQ_APIC_ID_MASK, .cpu_mask_to_apicid = cpu_mask_to_apicid, .cpu_mask_to_apicid_and = cpu_mask_to_apicid_and, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 5650eaf9061..f24cba1b29d 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -72,7 +72,7 @@ struct genapic apic_summit = { .get_apic_id = summit_get_apic_id, .set_apic_id = NULL, - .apic_id_mask = APIC_ID_MASK, + .apic_id_mask = SUMMIT_APIC_ID_MASK, .cpu_mask_to_apicid = cpu_mask_to_apicid, .cpu_mask_to_apicid_and = cpu_mask_to_apicid_and, -- GitLab From 94af18755266edf46803564414d74f9621aaded8 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 15:08:53 +0100 Subject: [PATCH 0572/4982] x86, apic: get rid of *_APIC_ID_MASK definitions Impact: cleanup Remove the *_APIC_ID_MASK subarch definitions and move them straight to the genapic driver initialization code. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apicdef.h | 2 -- arch/x86/include/asm/es7000/apicdef.h | 2 -- arch/x86/include/asm/mach-default/mach_apicdef.h | 1 - arch/x86/include/asm/numaq/apicdef.h | 2 -- arch/x86/include/asm/summit/apicdef.h | 2 -- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 2 +- arch/x86/mach-generic/numaq.c | 2 +- arch/x86/mach-generic/summit.c | 2 +- 10 files changed, 5 insertions(+), 14 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apicdef.h b/arch/x86/include/asm/bigsmp/apicdef.h index 6e587818c7e..e58dee84757 100644 --- a/arch/x86/include/asm/bigsmp/apicdef.h +++ b/arch/x86/include/asm/bigsmp/apicdef.h @@ -1,8 +1,6 @@ #ifndef __ASM_MACH_APICDEF_H #define __ASM_MACH_APICDEF_H -#define BIGSMP_APIC_ID_MASK (0xFF<<24) - static inline unsigned bigsmp_get_apic_id(unsigned long x) { return (x >> 24) & 0xFF; diff --git a/arch/x86/include/asm/es7000/apicdef.h b/arch/x86/include/asm/es7000/apicdef.h index 476da0c7f5c..c74881a7b3d 100644 --- a/arch/x86/include/asm/es7000/apicdef.h +++ b/arch/x86/include/asm/es7000/apicdef.h @@ -1,8 +1,6 @@ #ifndef __ASM_ES7000_APICDEF_H #define __ASM_ES7000_APICDEF_H -#define ES7000_APIC_ID_MASK (0xFF<<24) - static inline unsigned int es7000_get_apic_id(unsigned long x) { return (x >> 24) & 0xFF; diff --git a/arch/x86/include/asm/mach-default/mach_apicdef.h b/arch/x86/include/asm/mach-default/mach_apicdef.h index 8318d121ea6..5141085962d 100644 --- a/arch/x86/include/asm/mach-default/mach_apicdef.h +++ b/arch/x86/include/asm/mach-default/mach_apicdef.h @@ -6,7 +6,6 @@ #ifdef CONFIG_X86_64 #define SET_APIC_ID(x) (apic->set_apic_id(x)) #else -#define DEFAULT_APIC_ID_MASK (0x0F<<24) static inline unsigned default_get_apic_id(unsigned long x) { diff --git a/arch/x86/include/asm/numaq/apicdef.h b/arch/x86/include/asm/numaq/apicdef.h index 6f2cc5df0b1..cd927d5bd50 100644 --- a/arch/x86/include/asm/numaq/apicdef.h +++ b/arch/x86/include/asm/numaq/apicdef.h @@ -1,8 +1,6 @@ #ifndef __ASM_NUMAQ_APICDEF_H #define __ASM_NUMAQ_APICDEF_H -#define NUMAQ_APIC_ID_MASK (0xF<<24) - static inline unsigned int numaq_get_apic_id(unsigned long x) { return (x >> 24) & 0x0F; diff --git a/arch/x86/include/asm/summit/apicdef.h b/arch/x86/include/asm/summit/apicdef.h index 0373f0c7b5d..c24b0df2dec 100644 --- a/arch/x86/include/asm/summit/apicdef.h +++ b/arch/x86/include/asm/summit/apicdef.h @@ -1,8 +1,6 @@ #ifndef __ASM_SUMMIT_APICDEF_H #define __ASM_SUMMIT_APICDEF_H -#define SUMMIT_APIC_ID_MASK (0xFF<<24) - static inline unsigned summit_get_apic_id(unsigned long x) { return (x >> 24) & 0xFF; diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 1f4ad4f7702..ee52c59aa3a 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -92,7 +92,7 @@ struct genapic apic_bigsmp = { .get_apic_id = bigsmp_get_apic_id, .set_apic_id = NULL, - .apic_id_mask = BIGSMP_APIC_ID_MASK, + .apic_id_mask = 0xFF << 24, .cpu_mask_to_apicid = cpu_mask_to_apicid, .cpu_mask_to_apicid_and = cpu_mask_to_apicid_and, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index 239af25615b..e4ed7e6d626 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -73,7 +73,7 @@ struct genapic apic_default = { .get_apic_id = default_get_apic_id, .set_apic_id = NULL, - .apic_id_mask = DEFAULT_APIC_ID_MASK, + .apic_id_mask = 0x0F << 24, .cpu_mask_to_apicid = cpu_mask_to_apicid, .cpu_mask_to_apicid_and = cpu_mask_to_apicid_and, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 21fb33eea91..3d046dec0c9 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -128,7 +128,7 @@ struct genapic apic_es7000 = { .get_apic_id = es7000_get_apic_id, .set_apic_id = NULL, - .apic_id_mask = ES7000_APIC_ID_MASK, + .apic_id_mask = 0xFF << 24, .cpu_mask_to_apicid = cpu_mask_to_apicid, .cpu_mask_to_apicid_and = cpu_mask_to_apicid_and, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 27d2d1f2d6f..a7bf1aa02e1 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -92,7 +92,7 @@ struct genapic apic_numaq = { .get_apic_id = numaq_get_apic_id, .set_apic_id = NULL, - .apic_id_mask = NUMAQ_APIC_ID_MASK, + .apic_id_mask = 0x0F << 24, .cpu_mask_to_apicid = cpu_mask_to_apicid, .cpu_mask_to_apicid_and = cpu_mask_to_apicid_and, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index f24cba1b29d..a0ae6b91048 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -72,7 +72,7 @@ struct genapic apic_summit = { .get_apic_id = summit_get_apic_id, .set_apic_id = NULL, - .apic_id_mask = SUMMIT_APIC_ID_MASK, + .apic_id_mask = 0xFF << 24, .cpu_mask_to_apicid = cpu_mask_to_apicid, .cpu_mask_to_apicid_and = cpu_mask_to_apicid_and, -- GitLab From debccb3e77be52cfc26c5a99e123c114c5c72aeb Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 15:20:18 +0100 Subject: [PATCH 0573/4982] x86, apic: refactor ->cpu_mask_to_apicid*() - spread out the namespace on a per driver basis - clean up the functions - get rid of macros Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 17 +++++------ arch/x86/include/asm/es7000/apic.h | 29 ++++++++++++------- arch/x86/include/asm/mach-default/mach_apic.h | 10 +++---- arch/x86/include/asm/mach-generic/mach_apic.h | 2 -- arch/x86/include/asm/numaq/apic.h | 11 +++---- arch/x86/include/asm/summit/apic.h | 21 +++++++++----- arch/x86/kernel/genapic_flat_64.c | 4 ++- arch/x86/kernel/genx2apic_cluster.c | 15 ++++++---- arch/x86/kernel/genx2apic_phys.c | 15 ++++++---- arch/x86/kernel/genx2apic_uv_x.c | 14 +++++---- arch/x86/kernel/io_apic.c | 21 ++++++++------ arch/x86/mach-generic/bigsmp.c | 4 +-- arch/x86/mach-generic/default.c | 4 +-- arch/x86/mach-generic/es7000.c | 6 ++-- arch/x86/mach-generic/numaq.c | 4 +-- arch/x86/mach-generic/summit.c | 4 +-- 16 files changed, 101 insertions(+), 80 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index 1230f5d7a38..ee29d66cd30 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h @@ -105,18 +105,14 @@ static inline int bigsmp_check_phys_apicid_present(int boot_cpu_physical_apicid) } /* As we are using single CPU as destination, pick only one CPU here */ -static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask) +static inline unsigned int bigsmp_cpu_mask_to_apicid(const cpumask_t *cpumask) { - int cpu; - int apicid; - - cpu = first_cpu(*cpumask); - apicid = bigsmp_cpu_to_logical_apicid(cpu); - return apicid; + return bigsmp_cpu_to_logical_apicid(first_cpu(*cpumask)); } -static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *cpumask, - const struct cpumask *andmask) +static inline unsigned int +bigsmp_cpu_mask_to_apicid_and(const struct cpumask *cpumask, + const struct cpumask *andmask) { int cpu; @@ -124,9 +120,10 @@ static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *cpumask, * We're using fixed IRQ delivery, can only return one phys APIC ID. * May as well be the first. */ - for_each_cpu_and(cpu, cpumask, andmask) + for_each_cpu_and(cpu, cpumask, andmask) { if (cpumask_test_cpu(cpu, cpu_online_mask)) break; + } if (cpu < nr_cpu_ids) return bigsmp_cpu_to_logical_apicid(cpu); diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index f183dfb4de4..b89b45db735 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h @@ -137,12 +137,12 @@ static inline int es7000_check_phys_apicid_present(int cpu_physical_apicid) } static inline unsigned int -cpu_mask_to_apicid_cluster(const struct cpumask *cpumask) +es7000_cpu_mask_to_apicid_cluster(const struct cpumask *cpumask) { - int num_bits_set; int cpus_found = 0; - int cpu; + int num_bits_set; int apicid; + int cpu; num_bits_set = cpumask_weight(cpumask); /* Return id to all */ @@ -154,12 +154,15 @@ cpu_mask_to_apicid_cluster(const struct cpumask *cpumask) */ cpu = cpumask_first(cpumask); apicid = es7000_cpu_to_logical_apicid(cpu); + while (cpus_found < num_bits_set) { if (cpumask_test_cpu(cpu, cpumask)) { int new_apicid = es7000_cpu_to_logical_apicid(cpu); + if (apicid_cluster(apicid) != - apicid_cluster(new_apicid)){ + apicid_cluster(new_apicid)) { printk ("%s: Not a valid mask!\n", __func__); + return 0xFF; } apicid = new_apicid; @@ -170,12 +173,12 @@ cpu_mask_to_apicid_cluster(const struct cpumask *cpumask) return apicid; } -static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask) +static inline unsigned int es7000_cpu_mask_to_apicid(const cpumask_t *cpumask) { - int num_bits_set; int cpus_found = 0; - int cpu; + int num_bits_set; int apicid; + int cpu; num_bits_set = cpus_weight(*cpumask); /* Return id to all */ @@ -190,9 +193,11 @@ static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask) while (cpus_found < num_bits_set) { if (cpu_isset(cpu, *cpumask)) { int new_apicid = es7000_cpu_to_logical_apicid(cpu); + if (apicid_cluster(apicid) != - apicid_cluster(new_apicid)){ + apicid_cluster(new_apicid)) { printk ("%s: Not a valid mask!\n", __func__); + return es7000_cpu_to_logical_apicid(0); } apicid = new_apicid; @@ -204,8 +209,9 @@ static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask) } -static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *inmask, - const struct cpumask *andmask) +static inline unsigned int +es7000_cpu_mask_to_apicid_and(const struct cpumask *inmask, + const struct cpumask *andmask) { int apicid = es7000_cpu_to_logical_apicid(0); cpumask_var_t cpumask; @@ -215,9 +221,10 @@ static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *inmask, cpumask_and(cpumask, inmask, andmask); cpumask_and(cpumask, cpumask, cpu_online_mask); - apicid = cpu_mask_to_apicid(cpumask); + apicid = es7000_cpu_mask_to_apicid(cpumask); free_cpumask_var(cpumask); + return apicid; } diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index 8719208f273..8972f843414 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -19,8 +19,6 @@ static inline const struct cpumask *default_target_cpus(void) #ifdef CONFIG_X86_64 #include -#define cpu_mask_to_apicid (apic->cpu_mask_to_apicid) -#define cpu_mask_to_apicid_and (apic->cpu_mask_to_apicid_and) #define read_apic_id() (apic->get_apic_id(apic_read(APIC_ID))) #define send_IPI_self (apic->send_IPI_self) #define wakeup_secondary_cpu (apic->wakeup_cpu) @@ -49,13 +47,15 @@ static inline int default_apic_id_registered(void) return physid_isset(read_apic_id(), phys_cpu_present_map); } -static inline unsigned int cpu_mask_to_apicid(const struct cpumask *cpumask) +static inline unsigned int +default_cpu_mask_to_apicid(const struct cpumask *cpumask) { return cpumask_bits(cpumask)[0]; } -static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *cpumask, - const struct cpumask *andmask) +static inline unsigned int +default_cpu_mask_to_apicid_and(const struct cpumask *cpumask, + const struct cpumask *andmask) { unsigned long mask1 = cpumask_bits(cpumask)[0]; unsigned long mask2 = cpumask_bits(andmask)[0]; diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index 1eeb5b61e48..ca460e45991 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -3,8 +3,6 @@ #include -#define cpu_mask_to_apicid (apic->cpu_mask_to_apicid) -#define cpu_mask_to_apicid_and (apic->cpu_mask_to_apicid_and) #define wakeup_secondary_cpu (apic->wakeup_cpu) extern void generic_bigsmp_probe(void); diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h index 765c4d5124c..ce95e79f723 100644 --- a/arch/x86/include/asm/numaq/apic.h +++ b/arch/x86/include/asm/numaq/apic.h @@ -101,15 +101,16 @@ static inline int numaq_check_phys_apicid_present(int boot_cpu_physical_apicid) * We use physical apicids here, not logical, so just return the default * physical broadcast to stop people from breaking us */ -static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask) +static inline unsigned int numaq_cpu_mask_to_apicid(const cpumask_t *cpumask) { - return (int) 0xF; + return 0x0F; } -static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *cpumask, - const struct cpumask *andmask) +static inline unsigned int +numaq_cpu_mask_to_apicid_and(const struct cpumask *cpumask, + const struct cpumask *andmask) { - return (int) 0xF; + return 0x0F; } /* No NUMA-Q box has a HT CPU, but it can't hurt to use the default code. */ diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index fa6b3b45290..15b8dbd19e1 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h @@ -125,29 +125,32 @@ static inline int summit_check_phys_apicid_present(int boot_cpu_physical_apicid) return 1; } -static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask) +static inline unsigned int summit_cpu_mask_to_apicid(const cpumask_t *cpumask) { - int num_bits_set; int cpus_found = 0; - int cpu; + int num_bits_set; int apicid; + int cpu; num_bits_set = cpus_weight(*cpumask); /* Return id to all */ if (num_bits_set >= nr_cpu_ids) - return (int) 0xFF; + return 0xFF; /* * The cpus in the mask must all be on the apic cluster. If are not * on the same apicid cluster return default value of target_cpus(): */ cpu = first_cpu(*cpumask); apicid = summit_cpu_to_logical_apicid(cpu); + while (cpus_found < num_bits_set) { if (cpu_isset(cpu, *cpumask)) { int new_apicid = summit_cpu_to_logical_apicid(cpu); + if (apicid_cluster(apicid) != - apicid_cluster(new_apicid)){ + apicid_cluster(new_apicid)) { printk ("%s: Not a valid mask!\n", __func__); + return 0xFF; } apicid = apicid | new_apicid; @@ -158,8 +161,9 @@ static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask) return apicid; } -static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *inmask, - const struct cpumask *andmask) +static inline unsigned int +summit_cpu_mask_to_apicid_and(const struct cpumask *inmask, + const struct cpumask *andmask) { int apicid = summit_cpu_to_logical_apicid(0); cpumask_var_t cpumask; @@ -169,9 +173,10 @@ static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *inmask, cpumask_and(cpumask, inmask, andmask); cpumask_and(cpumask, cpumask, cpu_online_mask); - apicid = cpu_mask_to_apicid(cpumask); + apicid = summit_cpu_mask_to_apicid(cpumask); free_cpumask_var(cpumask); + return apicid; } diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index 78baa55cd0e..b941b112caf 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -309,11 +309,13 @@ physflat_cpu_mask_to_apicid_and(const struct cpumask *cpumask, * We're using fixed IRQ delivery, can only return one phys APIC ID. * May as well be the first. */ - for_each_cpu_and(cpu, cpumask, andmask) + for_each_cpu_and(cpu, cpumask, andmask) { if (cpumask_test_cpu(cpu, cpu_online_mask)) break; + } if (cpu < nr_cpu_ids) return per_cpu(x86_cpu_to_apicid, cpu); + return BAD_APICID; } diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c index c7557e05184..62f9fccf01d 100644 --- a/arch/x86/kernel/genx2apic_cluster.c +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -111,21 +111,21 @@ static int x2apic_apic_id_registered(void) static unsigned int x2apic_cpu_mask_to_apicid(const struct cpumask *cpumask) { - int cpu; - /* * We're using fixed IRQ delivery, can only return one logical APIC ID. * May as well be the first. */ - cpu = cpumask_first(cpumask); + int cpu = cpumask_first(cpumask); + if ((unsigned)cpu < nr_cpu_ids) return per_cpu(x86_cpu_to_logical_apicid, cpu); else return BAD_APICID; } -static unsigned int x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, - const struct cpumask *andmask) +static unsigned int +x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, + const struct cpumask *andmask) { int cpu; @@ -133,11 +133,14 @@ static unsigned int x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, * We're using fixed IRQ delivery, can only return one logical APIC ID. * May as well be the first. */ - for_each_cpu_and(cpu, cpumask, andmask) + for_each_cpu_and(cpu, cpumask, andmask) { if (cpumask_test_cpu(cpu, cpu_online_mask)) break; + } + if (cpu < nr_cpu_ids) return per_cpu(x86_cpu_to_logical_apicid, cpu); + return BAD_APICID; } diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c index 80cba49cfd8..3da1675b260 100644 --- a/arch/x86/kernel/genx2apic_phys.c +++ b/arch/x86/kernel/genx2apic_phys.c @@ -110,21 +110,21 @@ static int x2apic_apic_id_registered(void) static unsigned int x2apic_cpu_mask_to_apicid(const struct cpumask *cpumask) { - int cpu; - /* * We're using fixed IRQ delivery, can only return one phys APIC ID. * May as well be the first. */ - cpu = cpumask_first(cpumask); + int cpu = cpumask_first(cpumask); + if ((unsigned)cpu < nr_cpu_ids) return per_cpu(x86_cpu_to_apicid, cpu); else return BAD_APICID; } -static unsigned int x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, - const struct cpumask *andmask) +static unsigned int +x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, + const struct cpumask *andmask) { int cpu; @@ -132,11 +132,14 @@ static unsigned int x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, * We're using fixed IRQ delivery, can only return one phys APIC ID. * May as well be the first. */ - for_each_cpu_and(cpu, cpumask, andmask) + for_each_cpu_and(cpu, cpumask, andmask) { if (cpumask_test_cpu(cpu, cpu_online_mask)) break; + } + if (cpu < nr_cpu_ids) return per_cpu(x86_cpu_to_apicid, cpu); + return BAD_APICID; } diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index 50310b96adc..f957878c21e 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -171,21 +171,21 @@ static void uv_init_apic_ldr(void) static unsigned int uv_cpu_mask_to_apicid(const struct cpumask *cpumask) { - int cpu; - /* * We're using fixed IRQ delivery, can only return one phys APIC ID. * May as well be the first. */ - cpu = cpumask_first(cpumask); + int cpu = cpumask_first(cpumask); + if ((unsigned)cpu < nr_cpu_ids) return per_cpu(x86_cpu_to_apicid, cpu); else return BAD_APICID; } -static unsigned int uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask, - const struct cpumask *andmask) +static unsigned int +uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask, + const struct cpumask *andmask) { int cpu; @@ -193,11 +193,13 @@ static unsigned int uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask, * We're using fixed IRQ delivery, can only return one phys APIC ID. * May as well be the first. */ - for_each_cpu_and(cpu, cpumask, andmask) + for_each_cpu_and(cpu, cpumask, andmask) { if (cpumask_test_cpu(cpu, cpu_online_mask)) break; + } if (cpu < nr_cpu_ids) return per_cpu(x86_cpu_to_apicid, cpu); + return BAD_APICID; } diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 3d85d3d810b..01a2505d727 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -563,8 +563,9 @@ static int assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask); /* - * Either sets desc->affinity to a valid value, and returns cpu_mask_to_apicid - * of that, or returns BAD_APICID and leaves desc->affinity untouched. + * Either sets desc->affinity to a valid value, and returns + * ->cpu_mask_to_apicid of that, or returns BAD_APICID and + * leaves desc->affinity untouched. */ static unsigned int set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask) @@ -582,7 +583,8 @@ set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask) cpumask_and(desc->affinity, cfg->domain, mask); set_extra_move_desc(desc, mask); - return cpu_mask_to_apicid_and(desc->affinity, cpu_online_mask); + + return apic->cpu_mask_to_apicid_and(desc->affinity, cpu_online_mask); } static void @@ -1562,7 +1564,7 @@ static void setup_IO_APIC_irq(int apic_id, int pin, unsigned int irq, struct irq if (assign_irq_vector(irq, cfg, apic->target_cpus())) return; - dest = cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus()); + dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus()); apic_printk(APIC_VERBOSE,KERN_DEBUG "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> " @@ -1666,7 +1668,7 @@ static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin, */ entry.dest_mode = apic->irq_dest_mode; entry.mask = 1; /* mask IRQ now */ - entry.dest = cpu_mask_to_apicid(apic->target_cpus()); + entry.dest = apic->cpu_mask_to_apicid(apic->target_cpus()); entry.delivery_mode = apic->irq_delivery_mode; entry.polarity = 0; entry.trigger = 0; @@ -2367,7 +2369,7 @@ migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask) set_extra_move_desc(desc, mask); - dest = cpu_mask_to_apicid_and(cfg->domain, mask); + dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask); modify_ioapic_rte = desc->status & IRQ_LEVEL; if (modify_ioapic_rte) { @@ -3270,7 +3272,7 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms if (err) return err; - dest = cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus()); + dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus()); #ifdef CONFIG_INTR_REMAP if (irq_remapped(irq)) { @@ -3708,7 +3710,8 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) struct ht_irq_msg msg; unsigned dest; - dest = cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus()); + dest = apic->cpu_mask_to_apicid_and(cfg->domain, + apic->target_cpus()); msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest); @@ -3773,7 +3776,7 @@ int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade, entry->polarity = 0; entry->trigger = 0; entry->mask = 0; - entry->dest = cpu_mask_to_apicid(eligible_cpu); + entry->dest = apic->cpu_mask_to_apicid(eligible_cpu); mmr_pnode = uv_blade_to_pnode(mmr_blade); uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value); diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index ee52c59aa3a..22c2c7b8e4a 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -94,8 +94,8 @@ struct genapic apic_bigsmp = { .set_apic_id = NULL, .apic_id_mask = 0xFF << 24, - .cpu_mask_to_apicid = cpu_mask_to_apicid, - .cpu_mask_to_apicid_and = cpu_mask_to_apicid_and, + .cpu_mask_to_apicid = bigsmp_cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = bigsmp_cpu_mask_to_apicid_and, .send_IPI_mask = send_IPI_mask, .send_IPI_mask_allbutself = NULL, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index e4ed7e6d626..477ebec1674 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -75,8 +75,8 @@ struct genapic apic_default = { .set_apic_id = NULL, .apic_id_mask = 0x0F << 24, - .cpu_mask_to_apicid = cpu_mask_to_apicid, - .cpu_mask_to_apicid_and = cpu_mask_to_apicid_and, + .cpu_mask_to_apicid = default_cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, .send_IPI_mask = send_IPI_mask, .send_IPI_mask_allbutself = NULL, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 3d046dec0c9..d758cf65d73 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -26,7 +26,7 @@ void __init es7000_update_genapic_to_cluster(void) apic->init_apic_ldr = es7000_init_apic_ldr_cluster; - apic->cpu_mask_to_apicid = cpu_mask_to_apicid_cluster; + apic->cpu_mask_to_apicid = es7000_cpu_mask_to_apicid_cluster; } static int probe_es7000(void) @@ -130,8 +130,8 @@ struct genapic apic_es7000 = { .set_apic_id = NULL, .apic_id_mask = 0xFF << 24, - .cpu_mask_to_apicid = cpu_mask_to_apicid, - .cpu_mask_to_apicid_and = cpu_mask_to_apicid_and, + .cpu_mask_to_apicid = es7000_cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = es7000_cpu_mask_to_apicid_and, .send_IPI_mask = send_IPI_mask, .send_IPI_mask_allbutself = NULL, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index a7bf1aa02e1..eb7d56a521d 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -94,8 +94,8 @@ struct genapic apic_numaq = { .set_apic_id = NULL, .apic_id_mask = 0x0F << 24, - .cpu_mask_to_apicid = cpu_mask_to_apicid, - .cpu_mask_to_apicid_and = cpu_mask_to_apicid_and, + .cpu_mask_to_apicid = numaq_cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = numaq_cpu_mask_to_apicid_and, .send_IPI_mask = send_IPI_mask, .send_IPI_mask_allbutself = NULL, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index a0ae6b91048..8c293055bdf 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -74,8 +74,8 @@ struct genapic apic_summit = { .set_apic_id = NULL, .apic_id_mask = 0xFF << 24, - .cpu_mask_to_apicid = cpu_mask_to_apicid, - .cpu_mask_to_apicid_and = cpu_mask_to_apicid_and, + .cpu_mask_to_apicid = summit_cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = summit_cpu_mask_to_apicid_and, .send_IPI_mask = send_IPI_mask, .send_IPI_mask_allbutself = NULL, -- GitLab From dac5f4121df3c39fdb2ea57acd669a0ae19e46f8 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 15:42:24 +0100 Subject: [PATCH 0574/4982] x86, apic: untangle the send_IPI_*() jungle Our send_IPI_*() methods and definitions are a twisted mess: the same symbol is defined to different things depending on .config details, in a non-transparent way. - spread out the quirks into separately named per apic driver methods - prefix the standard PC methods with default_ - get rid of wrapper macro obfuscation - clean up various details Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/ipi.h | 16 ++++---- arch/x86/include/asm/es7000/ipi.h | 16 ++++---- arch/x86/include/asm/hw_irq.h | 4 +- arch/x86/include/asm/ipi.h | 38 +++++++++--------- arch/x86/include/asm/mach-default/mach_apic.h | 1 - arch/x86/include/asm/mach-default/mach_ipi.h | 40 ++++++++----------- arch/x86/include/asm/mach-generic/mach_ipi.h | 4 -- arch/x86/include/asm/numaq/ipi.h | 16 ++++---- arch/x86/include/asm/summit/ipi.h | 16 ++++---- arch/x86/kernel/apic.c | 2 +- arch/x86/kernel/genapic_64.c | 2 +- arch/x86/kernel/genapic_flat_64.c | 24 ++++++----- arch/x86/kernel/genx2apic_cluster.c | 38 ++++++++++-------- arch/x86/kernel/genx2apic_phys.c | 36 +++++++---------- arch/x86/kernel/genx2apic_uv_x.c | 21 +++++----- arch/x86/kernel/io_apic.c | 10 ++--- arch/x86/kernel/ipi.c | 28 +++++++------ arch/x86/kernel/kgdb.c | 2 +- arch/x86/kernel/reboot.c | 2 +- arch/x86/kernel/smp.c | 10 ++--- arch/x86/mach-generic/bigsmp.c | 6 +-- arch/x86/mach-generic/default.c | 6 +-- arch/x86/mach-generic/es7000.c | 6 +-- arch/x86/mach-generic/numaq.c | 6 +-- arch/x86/mach-generic/summit.c | 6 +-- arch/x86/mm/tlb.c | 2 +- 26 files changed, 178 insertions(+), 180 deletions(-) diff --git a/arch/x86/include/asm/bigsmp/ipi.h b/arch/x86/include/asm/bigsmp/ipi.h index 27fcd01b3ae..a91db69cda6 100644 --- a/arch/x86/include/asm/bigsmp/ipi.h +++ b/arch/x86/include/asm/bigsmp/ipi.h @@ -1,22 +1,22 @@ #ifndef __ASM_MACH_IPI_H #define __ASM_MACH_IPI_H -void send_IPI_mask_sequence(const struct cpumask *mask, int vector); -void send_IPI_mask_allbutself(const struct cpumask *mask, int vector); +void default_send_IPI_mask_sequence(const struct cpumask *mask, int vector); +void default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector); -static inline void send_IPI_mask(const struct cpumask *mask, int vector) +static inline void default_send_IPI_mask(const struct cpumask *mask, int vector) { - send_IPI_mask_sequence(mask, vector); + default_send_IPI_mask_sequence(mask, vector); } -static inline void send_IPI_allbutself(int vector) +static inline void bigsmp_send_IPI_allbutself(int vector) { - send_IPI_mask_allbutself(cpu_online_mask, vector); + default_send_IPI_mask_allbutself(cpu_online_mask, vector); } -static inline void send_IPI_all(int vector) +static inline void bigsmp_send_IPI_all(int vector) { - send_IPI_mask(cpu_online_mask, vector); + default_send_IPI_mask(cpu_online_mask, vector); } #endif /* __ASM_MACH_IPI_H */ diff --git a/arch/x86/include/asm/es7000/ipi.h b/arch/x86/include/asm/es7000/ipi.h index 7e8ed24d4b8..81e77c812ba 100644 --- a/arch/x86/include/asm/es7000/ipi.h +++ b/arch/x86/include/asm/es7000/ipi.h @@ -1,22 +1,22 @@ #ifndef __ASM_ES7000_IPI_H #define __ASM_ES7000_IPI_H -void send_IPI_mask_sequence(const struct cpumask *mask, int vector); -void send_IPI_mask_allbutself(const struct cpumask *mask, int vector); +void default_send_IPI_mask_sequence(const struct cpumask *mask, int vector); +void default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector); -static inline void send_IPI_mask(const struct cpumask *mask, int vector) +static inline void es7000_send_IPI_mask(const struct cpumask *mask, int vector) { - send_IPI_mask_sequence(mask, vector); + default_send_IPI_mask_sequence(mask, vector); } -static inline void send_IPI_allbutself(int vector) +static inline void es7000_send_IPI_allbutself(int vector) { - send_IPI_mask_allbutself(cpu_online_mask, vector); + default_send_IPI_mask_allbutself(cpu_online_mask, vector); } -static inline void send_IPI_all(int vector) +static inline void es7000_send_IPI_all(int vector) { - send_IPI_mask(cpu_online_mask, vector); + es7000_send_IPI_mask(cpu_online_mask, vector); } #endif /* __ASM_ES7000_IPI_H */ diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index 8de644b6b95..bfa921fad13 100644 --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h @@ -73,9 +73,9 @@ extern void enable_IO_APIC(void); /* IPI functions */ #ifdef CONFIG_X86_32 -extern void send_IPI_self(int vector); +extern void default_send_IPI_self(int vector); #endif -extern void send_IPI(int dest, int vector); +extern void default_send_IPI(int dest, int vector); /* Statistics */ extern atomic_t irq_err_count; diff --git a/arch/x86/include/asm/ipi.h b/arch/x86/include/asm/ipi.h index c745a306f7d..a8d717f2c7e 100644 --- a/arch/x86/include/asm/ipi.h +++ b/arch/x86/include/asm/ipi.h @@ -55,8 +55,9 @@ static inline void __xapic_wait_icr_idle(void) cpu_relax(); } -static inline void __send_IPI_shortcut(unsigned int shortcut, int vector, - unsigned int dest) +static inline void +__default_send_IPI_shortcut(unsigned int shortcut, + int vector, unsigned int dest) { /* * Subtle. In the case of the 'never do double writes' workaround @@ -87,8 +88,8 @@ static inline void __send_IPI_shortcut(unsigned int shortcut, int vector, * This is used to send an IPI with no shorthand notation (the destination is * specified in bits 56 to 63 of the ICR). */ -static inline void __send_IPI_dest_field(unsigned int mask, int vector, - unsigned int dest) +static inline void + __default_send_IPI_dest_field(unsigned int mask, int vector, unsigned int dest) { unsigned long cfg; @@ -117,11 +118,11 @@ static inline void __send_IPI_dest_field(unsigned int mask, int vector, native_apic_mem_write(APIC_ICR, cfg); } -static inline void send_IPI_mask_sequence(const struct cpumask *mask, - int vector) +static inline void +default_send_IPI_mask_sequence(const struct cpumask *mask, int vector) { - unsigned long flags; unsigned long query_cpu; + unsigned long flags; /* * Hack. The clustered APIC addressing mode doesn't allow us to send @@ -130,27 +131,28 @@ static inline void send_IPI_mask_sequence(const struct cpumask *mask, */ local_irq_save(flags); for_each_cpu(query_cpu, mask) { - __send_IPI_dest_field(per_cpu(x86_cpu_to_apicid, query_cpu), - vector, APIC_DEST_PHYSICAL); + __default_send_IPI_dest_field(per_cpu(x86_cpu_to_apicid, + query_cpu), vector, APIC_DEST_PHYSICAL); } local_irq_restore(flags); } -static inline void send_IPI_mask_allbutself(const struct cpumask *mask, - int vector) +static inline void +default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector) { - unsigned long flags; - unsigned int query_cpu; unsigned int this_cpu = smp_processor_id(); + unsigned int query_cpu; + unsigned long flags; /* See Hack comment above */ local_irq_save(flags); - for_each_cpu(query_cpu, mask) - if (query_cpu != this_cpu) - __send_IPI_dest_field( - per_cpu(x86_cpu_to_apicid, query_cpu), - vector, APIC_DEST_PHYSICAL); + for_each_cpu(query_cpu, mask) { + if (query_cpu == this_cpu) + continue; + __default_send_IPI_dest_field(per_cpu(x86_cpu_to_apicid, + query_cpu), vector, APIC_DEST_PHYSICAL); + } local_irq_restore(flags); } diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index 8972f843414..2e4104cf348 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -20,7 +20,6 @@ static inline const struct cpumask *default_target_cpus(void) #ifdef CONFIG_X86_64 #include #define read_apic_id() (apic->get_apic_id(apic_read(APIC_ID))) -#define send_IPI_self (apic->send_IPI_self) #define wakeup_secondary_cpu (apic->wakeup_cpu) extern void default_setup_apic_routing(void); #else diff --git a/arch/x86/include/asm/mach-default/mach_ipi.h b/arch/x86/include/asm/mach-default/mach_ipi.h index 089399643df..85dec630c69 100644 --- a/arch/x86/include/asm/mach-default/mach_ipi.h +++ b/arch/x86/include/asm/mach-default/mach_ipi.h @@ -4,45 +4,40 @@ /* Avoid include hell */ #define NMI_VECTOR 0x02 -void send_IPI_mask_bitmask(const struct cpumask *mask, int vector); -void send_IPI_mask_allbutself(const struct cpumask *mask, int vector); -void __send_IPI_shortcut(unsigned int shortcut, int vector); +void default_send_IPI_mask_bitmask(const struct cpumask *mask, int vector); +void default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector); +void __default_send_IPI_shortcut(unsigned int shortcut, int vector); extern int no_broadcast; #ifdef CONFIG_X86_64 #include -#define send_IPI_mask (apic->send_IPI_mask) -#define send_IPI_mask_allbutself (apic->send_IPI_mask_allbutself) #else -static inline void send_IPI_mask(const struct cpumask *mask, int vector) +static inline void default_send_IPI_mask(const struct cpumask *mask, int vector) { - send_IPI_mask_bitmask(mask, vector); + default_send_IPI_mask_bitmask(mask, vector); } -void send_IPI_mask_allbutself(const struct cpumask *mask, int vector); +void default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector); #endif -static inline void __local_send_IPI_allbutself(int vector) +static inline void __default_local_send_IPI_allbutself(int vector) { if (no_broadcast || vector == NMI_VECTOR) - send_IPI_mask_allbutself(cpu_online_mask, vector); + apic->send_IPI_mask_allbutself(cpu_online_mask, vector); else - __send_IPI_shortcut(APIC_DEST_ALLBUT, vector); + __default_send_IPI_shortcut(APIC_DEST_ALLBUT, vector); } -static inline void __local_send_IPI_all(int vector) +static inline void __default_local_send_IPI_all(int vector) { if (no_broadcast || vector == NMI_VECTOR) - send_IPI_mask(cpu_online_mask, vector); + apic->send_IPI_mask(cpu_online_mask, vector); else - __send_IPI_shortcut(APIC_DEST_ALLINC, vector); + __default_send_IPI_shortcut(APIC_DEST_ALLINC, vector); } -#ifdef CONFIG_X86_64 -#define send_IPI_allbutself (apic->send_IPI_allbutself) -#define send_IPI_all (apic->send_IPI_all) -#else -static inline void send_IPI_allbutself(int vector) +#ifdef CONFIG_X86_32 +static inline void default_send_IPI_allbutself(int vector) { /* * if there are no other CPUs in the system then we get an APIC send @@ -51,13 +46,12 @@ static inline void send_IPI_allbutself(int vector) if (!(num_online_cpus() > 1)) return; - __local_send_IPI_allbutself(vector); - return; + __default_local_send_IPI_allbutself(vector); } -static inline void send_IPI_all(int vector) +static inline void default_send_IPI_all(int vector) { - __local_send_IPI_all(vector); + __default_local_send_IPI_all(vector); } #endif diff --git a/arch/x86/include/asm/mach-generic/mach_ipi.h b/arch/x86/include/asm/mach-generic/mach_ipi.h index 75e54bd6cbd..5691c09645c 100644 --- a/arch/x86/include/asm/mach-generic/mach_ipi.h +++ b/arch/x86/include/asm/mach-generic/mach_ipi.h @@ -3,8 +3,4 @@ #include -#define send_IPI_mask (apic->send_IPI_mask) -#define send_IPI_allbutself (apic->send_IPI_allbutself) -#define send_IPI_all (apic->send_IPI_all) - #endif /* _ASM_X86_MACH_GENERIC_MACH_IPI_H */ diff --git a/arch/x86/include/asm/numaq/ipi.h b/arch/x86/include/asm/numaq/ipi.h index a8374c65277..5dbc4b4cd5e 100644 --- a/arch/x86/include/asm/numaq/ipi.h +++ b/arch/x86/include/asm/numaq/ipi.h @@ -1,22 +1,22 @@ #ifndef __ASM_NUMAQ_IPI_H #define __ASM_NUMAQ_IPI_H -void send_IPI_mask_sequence(const struct cpumask *mask, int vector); -void send_IPI_mask_allbutself(const struct cpumask *mask, int vector); +void default_send_IPI_mask_sequence(const struct cpumask *mask, int vector); +void default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector); -static inline void send_IPI_mask(const struct cpumask *mask, int vector) +static inline void numaq_send_IPI_mask(const struct cpumask *mask, int vector) { - send_IPI_mask_sequence(mask, vector); + default_send_IPI_mask_sequence(mask, vector); } -static inline void send_IPI_allbutself(int vector) +static inline void numaq_send_IPI_allbutself(int vector) { - send_IPI_mask_allbutself(cpu_online_mask, vector); + default_send_IPI_mask_allbutself(cpu_online_mask, vector); } -static inline void send_IPI_all(int vector) +static inline void numaq_send_IPI_all(int vector) { - send_IPI_mask(cpu_online_mask, vector); + numaq_send_IPI_mask(cpu_online_mask, vector); } #endif /* __ASM_NUMAQ_IPI_H */ diff --git a/arch/x86/include/asm/summit/ipi.h b/arch/x86/include/asm/summit/ipi.h index a8a2c24f50c..f87a43fe0ae 100644 --- a/arch/x86/include/asm/summit/ipi.h +++ b/arch/x86/include/asm/summit/ipi.h @@ -1,26 +1,26 @@ #ifndef __ASM_SUMMIT_IPI_H #define __ASM_SUMMIT_IPI_H -void send_IPI_mask_sequence(const cpumask_t *mask, int vector); -void send_IPI_mask_allbutself(const cpumask_t *mask, int vector); +void default_send_IPI_mask_sequence(const cpumask_t *mask, int vector); +void default_send_IPI_mask_allbutself(const cpumask_t *mask, int vector); -static inline void send_IPI_mask(const cpumask_t *mask, int vector) +static inline void summit_send_IPI_mask(const cpumask_t *mask, int vector) { - send_IPI_mask_sequence(mask, vector); + default_send_IPI_mask_sequence(mask, vector); } -static inline void send_IPI_allbutself(int vector) +static inline void summit_send_IPI_allbutself(int vector) { cpumask_t mask = cpu_online_map; cpu_clear(smp_processor_id(), mask); if (!cpus_empty(mask)) - send_IPI_mask(&mask, vector); + summit_send_IPI_mask(&mask, vector); } -static inline void send_IPI_all(int vector) +static inline void summit_send_IPI_all(int vector) { - send_IPI_mask(&cpu_online_map, vector); + summit_send_IPI_mask(&cpu_online_map, vector); } #endif /* __ASM_SUMMIT_IPI_H */ diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 5f7f3a9a47a..84b8e7c57ab 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -475,7 +475,7 @@ static void lapic_timer_setup(enum clock_event_mode mode, static void lapic_timer_broadcast(const struct cpumask *mask) { #ifdef CONFIG_SMP - send_IPI_mask(mask, LOCAL_TIMER_VECTOR); + apic->send_IPI_mask(mask, LOCAL_TIMER_VECTOR); #endif } diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c index d57d2138f07..820dea5d0eb 100644 --- a/arch/x86/kernel/genapic_64.c +++ b/arch/x86/kernel/genapic_64.c @@ -65,7 +65,7 @@ void __init default_setup_apic_routing(void) void apic_send_IPI_self(int vector) { - __send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL); + __default_send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL); } int __init default_acpi_madt_oem_check(char *oem_id, char *oem_table_id) diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index b941b112caf..7c648ccea51 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -74,7 +74,7 @@ static inline void _flat_send_IPI_mask(unsigned long mask, int vector) unsigned long flags; local_irq_save(flags); - __send_IPI_dest_field(mask, vector, apic->dest_logical); + __default_send_IPI_dest_field(mask, vector, apic->dest_logical); local_irq_restore(flags); } @@ -85,14 +85,15 @@ static void flat_send_IPI_mask(const struct cpumask *cpumask, int vector) _flat_send_IPI_mask(mask, vector); } -static void flat_send_IPI_mask_allbutself(const struct cpumask *cpumask, - int vector) +static void + flat_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector) { unsigned long mask = cpumask_bits(cpumask)[0]; int cpu = smp_processor_id(); if (cpu < BITS_PER_LONG) clear_bit(cpu, &mask); + _flat_send_IPI_mask(mask, vector); } @@ -114,16 +115,19 @@ static void flat_send_IPI_allbutself(int vector) _flat_send_IPI_mask(mask, vector); } } else if (num_online_cpus() > 1) { - __send_IPI_shortcut(APIC_DEST_ALLBUT, vector, apic->dest_logical); + __default_send_IPI_shortcut(APIC_DEST_ALLBUT, + vector, apic->dest_logical); } } static void flat_send_IPI_all(int vector) { - if (vector == NMI_VECTOR) + if (vector == NMI_VECTOR) { flat_send_IPI_mask(cpu_online_mask, vector); - else - __send_IPI_shortcut(APIC_DEST_ALLINC, vector, apic->dest_logical); + } else { + __default_send_IPI_shortcut(APIC_DEST_ALLINC, + vector, apic->dest_logical); + } } static unsigned int flat_get_apic_id(unsigned long x) @@ -265,18 +269,18 @@ static void physflat_vector_allocation_domain(int cpu, struct cpumask *retmask) static void physflat_send_IPI_mask(const struct cpumask *cpumask, int vector) { - send_IPI_mask_sequence(cpumask, vector); + default_send_IPI_mask_sequence(cpumask, vector); } static void physflat_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector) { - send_IPI_mask_allbutself(cpumask, vector); + default_send_IPI_mask_allbutself(cpumask, vector); } static void physflat_send_IPI_allbutself(int vector) { - send_IPI_mask_allbutself(cpu_online_mask, vector); + default_send_IPI_mask_allbutself(cpu_online_mask, vector); } static void physflat_send_IPI_all(int vector) diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c index 62f9fccf01d..2d97726a973 100644 --- a/arch/x86/kernel/genx2apic_cluster.c +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -36,8 +36,8 @@ static void x2apic_vector_allocation_domain(int cpu, struct cpumask *retmask) cpumask_set_cpu(cpu, retmask); } -static void __x2apic_send_IPI_dest(unsigned int apicid, int vector, - unsigned int dest) +static void + __x2apic_send_IPI_dest(unsigned int apicid, int vector, unsigned int dest) { unsigned long cfg; @@ -57,45 +57,50 @@ static void __x2apic_send_IPI_dest(unsigned int apicid, int vector, */ static void x2apic_send_IPI_mask(const struct cpumask *mask, int vector) { - unsigned long flags; unsigned long query_cpu; + unsigned long flags; local_irq_save(flags); - for_each_cpu(query_cpu, mask) + for_each_cpu(query_cpu, mask) { __x2apic_send_IPI_dest( per_cpu(x86_cpu_to_logical_apicid, query_cpu), vector, apic->dest_logical); + } local_irq_restore(flags); } -static void x2apic_send_IPI_mask_allbutself(const struct cpumask *mask, - int vector) +static void + x2apic_send_IPI_mask_allbutself(const struct cpumask *mask, int vector) { - unsigned long flags; - unsigned long query_cpu; unsigned long this_cpu = smp_processor_id(); + unsigned long query_cpu; + unsigned long flags; local_irq_save(flags); - for_each_cpu(query_cpu, mask) - if (query_cpu != this_cpu) - __x2apic_send_IPI_dest( + for_each_cpu(query_cpu, mask) { + if (query_cpu == this_cpu) + continue; + __x2apic_send_IPI_dest( per_cpu(x86_cpu_to_logical_apicid, query_cpu), vector, apic->dest_logical); + } local_irq_restore(flags); } static void x2apic_send_IPI_allbutself(int vector) { - unsigned long flags; - unsigned long query_cpu; unsigned long this_cpu = smp_processor_id(); + unsigned long query_cpu; + unsigned long flags; local_irq_save(flags); - for_each_online_cpu(query_cpu) - if (query_cpu != this_cpu) - __x2apic_send_IPI_dest( + for_each_online_cpu(query_cpu) { + if (query_cpu == this_cpu) + continue; + __x2apic_send_IPI_dest( per_cpu(x86_cpu_to_logical_apicid, query_cpu), vector, apic->dest_logical); + } local_irq_restore(flags); } @@ -175,7 +180,6 @@ static void init_x2apic_ldr(void) int cpu = smp_processor_id(); per_cpu(x86_cpu_to_logical_apicid, cpu) = apic_read(APIC_LDR); - return; } struct genapic apic_x2apic_cluster = { diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c index 3da1675b260..74777c27669 100644 --- a/arch/x86/kernel/genx2apic_phys.c +++ b/arch/x86/kernel/genx2apic_phys.c @@ -55,8 +55,8 @@ static void __x2apic_send_IPI_dest(unsigned int apicid, int vector, static void x2apic_send_IPI_mask(const struct cpumask *mask, int vector) { - unsigned long flags; unsigned long query_cpu; + unsigned long flags; local_irq_save(flags); for_each_cpu(query_cpu, mask) { @@ -66,12 +66,12 @@ static void x2apic_send_IPI_mask(const struct cpumask *mask, int vector) local_irq_restore(flags); } -static void x2apic_send_IPI_mask_allbutself(const struct cpumask *mask, - int vector) +static void + x2apic_send_IPI_mask_allbutself(const struct cpumask *mask, int vector) { - unsigned long flags; - unsigned long query_cpu; unsigned long this_cpu = smp_processor_id(); + unsigned long query_cpu; + unsigned long flags; local_irq_save(flags); for_each_cpu(query_cpu, mask) { @@ -85,16 +85,17 @@ static void x2apic_send_IPI_mask_allbutself(const struct cpumask *mask, static void x2apic_send_IPI_allbutself(int vector) { - unsigned long flags; - unsigned long query_cpu; unsigned long this_cpu = smp_processor_id(); + unsigned long query_cpu; + unsigned long flags; local_irq_save(flags); - for_each_online_cpu(query_cpu) - if (query_cpu != this_cpu) - __x2apic_send_IPI_dest( - per_cpu(x86_cpu_to_apicid, query_cpu), - vector, APIC_DEST_PHYSICAL); + for_each_online_cpu(query_cpu) { + if (query_cpu == this_cpu) + continue; + __x2apic_send_IPI_dest(per_cpu(x86_cpu_to_apicid, query_cpu), + vector, APIC_DEST_PHYSICAL); + } local_irq_restore(flags); } @@ -145,18 +146,12 @@ x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, static unsigned int x2apic_phys_get_apic_id(unsigned long x) { - unsigned int id; - - id = x; - return id; + return x; } static unsigned long set_apic_id(unsigned int id) { - unsigned long x; - - x = id; - return x; + return id; } static int x2apic_phys_pkg_id(int initial_apicid, int index_msb) @@ -171,7 +166,6 @@ static void x2apic_send_IPI_self(int vector) static void init_x2apic_ldr(void) { - return; } struct genapic apic_x2apic_phys = { diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index f957878c21e..24b9f42db9b 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -118,12 +118,13 @@ static void uv_send_IPI_one(int cpu, int vector) int pnode; apicid = per_cpu(x86_cpu_to_apicid, cpu); - lapicid = apicid & 0x3f; /* ZZZ macro needed */ + lapicid = apicid & 0x3f; /* ZZZ macro needed */ pnode = uv_apicid_to_pnode(apicid); - val = - (1UL << UVH_IPI_INT_SEND_SHFT) | (lapicid << - UVH_IPI_INT_APIC_ID_SHFT) | - (vector << UVH_IPI_INT_VECTOR_SHFT); + + val = ( 1UL << UVH_IPI_INT_SEND_SHFT ) | + ( lapicid << UVH_IPI_INT_APIC_ID_SHFT ) | + ( vector << UVH_IPI_INT_VECTOR_SHFT ); + uv_write_global_mmr64(pnode, UVH_IPI_INT, val); } @@ -137,22 +138,24 @@ static void uv_send_IPI_mask(const struct cpumask *mask, int vector) static void uv_send_IPI_mask_allbutself(const struct cpumask *mask, int vector) { - unsigned int cpu; unsigned int this_cpu = smp_processor_id(); + unsigned int cpu; - for_each_cpu(cpu, mask) + for_each_cpu(cpu, mask) { if (cpu != this_cpu) uv_send_IPI_one(cpu, vector); + } } static void uv_send_IPI_allbutself(int vector) { - unsigned int cpu; unsigned int this_cpu = smp_processor_id(); + unsigned int cpu; - for_each_online_cpu(cpu) + for_each_online_cpu(cpu) { if (cpu != this_cpu) uv_send_IPI_one(cpu, vector); + } } static void uv_send_IPI_all(int vector) diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 01a2505d727..e90970ce21a 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -514,11 +514,11 @@ static void send_cleanup_vector(struct irq_cfg *cfg) for_each_cpu_and(i, cfg->old_domain, cpu_online_mask) cfg->move_cleanup_count++; for_each_cpu_and(i, cfg->old_domain, cpu_online_mask) - send_IPI_mask(cpumask_of(i), IRQ_MOVE_CLEANUP_VECTOR); + apic->send_IPI_mask(cpumask_of(i), IRQ_MOVE_CLEANUP_VECTOR); } else { cpumask_and(cleanup_mask, cfg->old_domain, cpu_online_mask); cfg->move_cleanup_count = cpumask_weight(cleanup_mask); - send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR); + apic->send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR); free_cpumask_var(cleanup_mask); } cfg->move_in_progress = 0; @@ -800,7 +800,7 @@ static void clear_IO_APIC (void) } #if !defined(CONFIG_SMP) && defined(CONFIG_X86_32) -void send_IPI_self(int vector) +void default_send_IPI_self(int vector) { unsigned int cfg; @@ -2297,7 +2297,7 @@ static int ioapic_retrigger_irq(unsigned int irq) unsigned long flags; spin_lock_irqsave(&vector_lock, flags); - send_IPI_mask(cpumask_of(cpumask_first(cfg->domain)), cfg->vector); + apic->send_IPI_mask(cpumask_of(cpumask_first(cfg->domain)), cfg->vector); spin_unlock_irqrestore(&vector_lock, flags); return 1; @@ -2305,7 +2305,7 @@ static int ioapic_retrigger_irq(unsigned int irq) #else static int ioapic_retrigger_irq(unsigned int irq) { - send_IPI_self(irq_cfg(irq)->vector); + apic->send_IPI_self(irq_cfg(irq)->vector); return 1; } diff --git a/arch/x86/kernel/ipi.c b/arch/x86/kernel/ipi.c index 367c5e684fa..e16c41b2e4e 100644 --- a/arch/x86/kernel/ipi.c +++ b/arch/x86/kernel/ipi.c @@ -48,7 +48,7 @@ static inline int __prepare_ICR2(unsigned int mask) return SET_APIC_DEST_FIELD(mask); } -void __send_IPI_shortcut(unsigned int shortcut, int vector) +void __default_send_IPI_shortcut(unsigned int shortcut, int vector) { /* * Subtle. In the case of the 'never do double writes' workaround @@ -75,16 +75,16 @@ void __send_IPI_shortcut(unsigned int shortcut, int vector) apic_write(APIC_ICR, cfg); } -void send_IPI_self(int vector) +void default_send_IPI_self(int vector) { - __send_IPI_shortcut(APIC_DEST_SELF, vector); + __default_send_IPI_shortcut(APIC_DEST_SELF, vector); } /* * This is used to send an IPI with no shorthand notation (the destination is * specified in bits 56 to 63 of the ICR). */ -static inline void __send_IPI_dest_field(unsigned long mask, int vector) +static inline void __default_send_IPI_dest_field(unsigned long mask, int vector) { unsigned long cfg; @@ -116,18 +116,18 @@ static inline void __send_IPI_dest_field(unsigned long mask, int vector) /* * This is only used on smaller machines. */ -void send_IPI_mask_bitmask(const struct cpumask *cpumask, int vector) +void default_send_IPI_mask_bitmask(const struct cpumask *cpumask, int vector) { unsigned long mask = cpumask_bits(cpumask)[0]; unsigned long flags; local_irq_save(flags); WARN_ON(mask & ~cpumask_bits(cpu_online_mask)[0]); - __send_IPI_dest_field(mask, vector); + __default_send_IPI_dest_field(mask, vector); local_irq_restore(flags); } -void send_IPI_mask_sequence(const struct cpumask *mask, int vector) +void default_send_IPI_mask_sequence(const struct cpumask *mask, int vector) { unsigned long flags; unsigned int query_cpu; @@ -140,11 +140,11 @@ void send_IPI_mask_sequence(const struct cpumask *mask, int vector) local_irq_save(flags); for_each_cpu(query_cpu, mask) - __send_IPI_dest_field(apic->cpu_to_logical_apicid(query_cpu), vector); + __default_send_IPI_dest_field(apic->cpu_to_logical_apicid(query_cpu), vector); local_irq_restore(flags); } -void send_IPI_mask_allbutself(const struct cpumask *mask, int vector) +void default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector) { unsigned long flags; unsigned int query_cpu; @@ -153,10 +153,12 @@ void send_IPI_mask_allbutself(const struct cpumask *mask, int vector) /* See Hack comment above */ local_irq_save(flags); - for_each_cpu(query_cpu, mask) - if (query_cpu != this_cpu) - __send_IPI_dest_field(apic->cpu_to_logical_apicid(query_cpu), - vector); + for_each_cpu(query_cpu, mask) { + if (query_cpu == this_cpu) + continue; + __default_send_IPI_dest_field( + apic->cpu_to_logical_apicid(query_cpu), vector); + } local_irq_restore(flags); } diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index 10435a120d2..b62a3811e01 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c @@ -347,7 +347,7 @@ void kgdb_post_primary_code(struct pt_regs *regs, int e_vector, int err_code) */ void kgdb_roundup_cpus(unsigned long flags) { - send_IPI_allbutself(APIC_DM_NMI); + apic->send_IPI_allbutself(APIC_DM_NMI); } #endif diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index f8536fee5c1..38dace28d62 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -651,7 +651,7 @@ static int crash_nmi_callback(struct notifier_block *self, static void smp_send_nmi_allbutself(void) { - send_IPI_allbutself(NMI_VECTOR); + apic->send_IPI_allbutself(NMI_VECTOR); } static struct notifier_block crash_nmi_nb = { diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index e6faa3316bd..c48ba6cc32a 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c @@ -118,12 +118,12 @@ static void native_smp_send_reschedule(int cpu) WARN_ON(1); return; } - send_IPI_mask(cpumask_of(cpu), RESCHEDULE_VECTOR); + apic->send_IPI_mask(cpumask_of(cpu), RESCHEDULE_VECTOR); } void native_send_call_func_single_ipi(int cpu) { - send_IPI_mask(cpumask_of(cpu), CALL_FUNCTION_SINGLE_VECTOR); + apic->send_IPI_mask(cpumask_of(cpu), CALL_FUNCTION_SINGLE_VECTOR); } void native_send_call_func_ipi(const struct cpumask *mask) @@ -131,7 +131,7 @@ void native_send_call_func_ipi(const struct cpumask *mask) cpumask_var_t allbutself; if (!alloc_cpumask_var(&allbutself, GFP_ATOMIC)) { - send_IPI_mask(mask, CALL_FUNCTION_VECTOR); + apic->send_IPI_mask(mask, CALL_FUNCTION_VECTOR); return; } @@ -140,9 +140,9 @@ void native_send_call_func_ipi(const struct cpumask *mask) if (cpumask_equal(mask, allbutself) && cpumask_equal(cpu_online_mask, cpu_callout_mask)) - send_IPI_allbutself(CALL_FUNCTION_VECTOR); + apic->send_IPI_allbutself(CALL_FUNCTION_VECTOR); else - send_IPI_mask(mask, CALL_FUNCTION_VECTOR); + apic->send_IPI_mask(mask, CALL_FUNCTION_VECTOR); free_cpumask_var(allbutself); } diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 22c2c7b8e4a..4782b554788 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -97,10 +97,10 @@ struct genapic apic_bigsmp = { .cpu_mask_to_apicid = bigsmp_cpu_mask_to_apicid, .cpu_mask_to_apicid_and = bigsmp_cpu_mask_to_apicid_and, - .send_IPI_mask = send_IPI_mask, + .send_IPI_mask = default_send_IPI_mask, .send_IPI_mask_allbutself = NULL, - .send_IPI_allbutself = send_IPI_allbutself, - .send_IPI_all = send_IPI_all, + .send_IPI_allbutself = bigsmp_send_IPI_allbutself, + .send_IPI_all = bigsmp_send_IPI_all, .send_IPI_self = NULL, .wakeup_cpu = NULL, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index 477ebec1674..bf4670db25f 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -78,10 +78,10 @@ struct genapic apic_default = { .cpu_mask_to_apicid = default_cpu_mask_to_apicid, .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, - .send_IPI_mask = send_IPI_mask, + .send_IPI_mask = default_send_IPI_mask, .send_IPI_mask_allbutself = NULL, - .send_IPI_allbutself = send_IPI_allbutself, - .send_IPI_all = send_IPI_all, + .send_IPI_allbutself = default_send_IPI_allbutself, + .send_IPI_all = default_send_IPI_all, .send_IPI_self = NULL, .wakeup_cpu = NULL, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index d758cf65d73..d36642e6d90 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -133,10 +133,10 @@ struct genapic apic_es7000 = { .cpu_mask_to_apicid = es7000_cpu_mask_to_apicid, .cpu_mask_to_apicid_and = es7000_cpu_mask_to_apicid_and, - .send_IPI_mask = send_IPI_mask, + .send_IPI_mask = es7000_send_IPI_mask, .send_IPI_mask_allbutself = NULL, - .send_IPI_allbutself = send_IPI_allbutself, - .send_IPI_all = send_IPI_all, + .send_IPI_allbutself = es7000_send_IPI_allbutself, + .send_IPI_all = es7000_send_IPI_all, .send_IPI_self = NULL, .wakeup_cpu = NULL, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index eb7d56a521d..135b1832ad8 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -97,10 +97,10 @@ struct genapic apic_numaq = { .cpu_mask_to_apicid = numaq_cpu_mask_to_apicid, .cpu_mask_to_apicid_and = numaq_cpu_mask_to_apicid_and, - .send_IPI_mask = send_IPI_mask, + .send_IPI_mask = numaq_send_IPI_mask, .send_IPI_mask_allbutself = NULL, - .send_IPI_allbutself = send_IPI_allbutself, - .send_IPI_all = send_IPI_all, + .send_IPI_allbutself = numaq_send_IPI_allbutself, + .send_IPI_all = numaq_send_IPI_all, .send_IPI_self = NULL, .wakeup_cpu = NULL, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 8c293055bdf..77196a4a9d2 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -77,10 +77,10 @@ struct genapic apic_summit = { .cpu_mask_to_apicid = summit_cpu_mask_to_apicid, .cpu_mask_to_apicid_and = summit_cpu_mask_to_apicid_and, - .send_IPI_mask = send_IPI_mask, + .send_IPI_mask = summit_send_IPI_mask, .send_IPI_mask_allbutself = NULL, - .send_IPI_allbutself = send_IPI_allbutself, - .send_IPI_all = send_IPI_all, + .send_IPI_allbutself = summit_send_IPI_allbutself, + .send_IPI_all = summit_send_IPI_all, .send_IPI_self = NULL, .wakeup_cpu = NULL, diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 72a6d4ebe34..6348e114692 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -196,7 +196,7 @@ static void flush_tlb_others_ipi(const struct cpumask *cpumask, * We have to send the IPI only to * CPUs affected. */ - send_IPI_mask(to_cpumask(f->flush_cpumask), + apic->send_IPI_mask(to_cpumask(f->flush_cpumask), INVALIDATE_TLB_VECTOR_START + sender); while (!cpumask_empty(to_cpumask(f->flush_cpumask))) -- GitLab From 6f177c01db6b865181fbc6c948381b290ee09718 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 16:09:23 +0100 Subject: [PATCH 0575/4982] x86, smp: clean up ->trampoline_phys_low/high handling - spread out the namespace on a per apic driver basis - remove wrapper macros Signed-off-by: Ingo Molnar --- arch/x86/include/asm/es7000/wakecpu.h | 4 ++-- arch/x86/include/asm/mach-default/mach_wakecpu.h | 4 ++-- arch/x86/include/asm/mach-default/smpboot_hooks.h | 6 +++--- arch/x86/include/asm/mach-generic/mach_wakecpu.h | 2 -- arch/x86/include/asm/numaq/wakecpu.h | 12 ++++++------ arch/x86/mach-generic/bigsmp.c | 4 ++-- arch/x86/mach-generic/default.c | 4 ++-- arch/x86/mach-generic/es7000.c | 4 ++-- arch/x86/mach-generic/numaq.c | 4 ++-- arch/x86/mach-generic/summit.c | 4 ++-- 10 files changed, 23 insertions(+), 25 deletions(-) diff --git a/arch/x86/include/asm/es7000/wakecpu.h b/arch/x86/include/asm/es7000/wakecpu.h index 78f0daaee43..4c01be6ff80 100644 --- a/arch/x86/include/asm/es7000/wakecpu.h +++ b/arch/x86/include/asm/es7000/wakecpu.h @@ -1,8 +1,8 @@ #ifndef __ASM_ES7000_WAKECPU_H #define __ASM_ES7000_WAKECPU_H -#define TRAMPOLINE_PHYS_LOW 0x467 -#define TRAMPOLINE_PHYS_HIGH 0x469 +#define ES7000_TRAMPOLINE_PHYS_LOW 0x467 +#define ES7000_TRAMPOLINE_PHYS_HIGH 0x469 static inline void wait_for_init_deassert(atomic_t *deassert) { diff --git a/arch/x86/include/asm/mach-default/mach_wakecpu.h b/arch/x86/include/asm/mach-default/mach_wakecpu.h index 89897a6a65b..0a8d7860e44 100644 --- a/arch/x86/include/asm/mach-default/mach_wakecpu.h +++ b/arch/x86/include/asm/mach-default/mach_wakecpu.h @@ -1,8 +1,8 @@ #ifndef _ASM_X86_MACH_DEFAULT_MACH_WAKECPU_H #define _ASM_X86_MACH_DEFAULT_MACH_WAKECPU_H -#define TRAMPOLINE_PHYS_LOW (0x467) -#define TRAMPOLINE_PHYS_HIGH (0x469) +#define DEFAULT_TRAMPOLINE_PHYS_LOW (0x467) +#define DEFAULT_TRAMPOLINE_PHYS_HIGH (0x469) static inline void wait_for_init_deassert(atomic_t *deassert) { diff --git a/arch/x86/include/asm/mach-default/smpboot_hooks.h b/arch/x86/include/asm/mach-default/smpboot_hooks.h index 23bf52103b8..1def6011490 100644 --- a/arch/x86/include/asm/mach-default/smpboot_hooks.h +++ b/arch/x86/include/asm/mach-default/smpboot_hooks.h @@ -13,10 +13,10 @@ static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip) CMOS_WRITE(0xa, 0xf); local_flush_tlb(); pr_debug("1.\n"); - *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_HIGH)) = + *((volatile unsigned short *)phys_to_virt(apic->trampoline_phys_high)) = start_eip >> 4; pr_debug("2.\n"); - *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = + *((volatile unsigned short *)phys_to_virt(apic->trampoline_phys_low)) = start_eip & 0xf; pr_debug("3.\n"); } @@ -34,7 +34,7 @@ static inline void smpboot_restore_warm_reset_vector(void) */ CMOS_WRITE(0, 0xf); - *((volatile long *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = 0; + *((volatile long *)phys_to_virt(apic->trampoline_phys_low)) = 0; } static inline void __init smpboot_setup_io_apic(void) diff --git a/arch/x86/include/asm/mach-generic/mach_wakecpu.h b/arch/x86/include/asm/mach-generic/mach_wakecpu.h index 22006bbee61..2031377a954 100644 --- a/arch/x86/include/asm/mach-generic/mach_wakecpu.h +++ b/arch/x86/include/asm/mach-generic/mach_wakecpu.h @@ -1,8 +1,6 @@ #ifndef _ASM_X86_MACH_GENERIC_MACH_WAKECPU_H #define _ASM_X86_MACH_GENERIC_MACH_WAKECPU_H -#define TRAMPOLINE_PHYS_LOW (apic->trampoline_phys_low) -#define TRAMPOLINE_PHYS_HIGH (apic->trampoline_phys_high) #define wait_for_init_deassert (apic->wait_for_init_deassert) #define smp_callin_clear_local_apic (apic->smp_callin_clear_local_apic) #define store_NMI_vector (apic->store_NMI_vector) diff --git a/arch/x86/include/asm/numaq/wakecpu.h b/arch/x86/include/asm/numaq/wakecpu.h index 6f499df8edd..8b6c16d8558 100644 --- a/arch/x86/include/asm/numaq/wakecpu.h +++ b/arch/x86/include/asm/numaq/wakecpu.h @@ -3,8 +3,8 @@ /* This file copes with machines that wakeup secondary CPUs by NMIs */ -#define TRAMPOLINE_PHYS_LOW (0x8) -#define TRAMPOLINE_PHYS_HIGH (0xa) +#define NUMAQ_TRAMPOLINE_PHYS_LOW (0x8) +#define NUMAQ_TRAMPOLINE_PHYS_HIGH (0xa) /* We don't do anything here because we use NMI's to boot instead */ static inline void wait_for_init_deassert(atomic_t *deassert) @@ -24,17 +24,17 @@ static inline void store_NMI_vector(unsigned short *high, unsigned short *low) { printk("Storing NMI vector\n"); *high = - *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_HIGH)); + *((volatile unsigned short *)phys_to_virt(NUMAQ_TRAMPOLINE_PHYS_HIGH)); *low = - *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_LOW)); + *((volatile unsigned short *)phys_to_virt(NUMAQ_TRAMPOLINE_PHYS_LOW)); } static inline void restore_NMI_vector(unsigned short *high, unsigned short *low) { printk("Restoring NMI vector\n"); - *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_HIGH)) = + *((volatile unsigned short *)phys_to_virt(NUMAQ_TRAMPOLINE_PHYS_HIGH)) = *high; - *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = + *((volatile unsigned short *)phys_to_virt(NUMAQ_TRAMPOLINE_PHYS_LOW)) = *low; } diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 4782b554788..a317fbe07fd 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -104,8 +104,8 @@ struct genapic apic_bigsmp = { .send_IPI_self = NULL, .wakeup_cpu = NULL, - .trampoline_phys_low = TRAMPOLINE_PHYS_LOW, - .trampoline_phys_high = TRAMPOLINE_PHYS_HIGH, + .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, + .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, .wait_for_init_deassert = wait_for_init_deassert, .smp_callin_clear_local_apic = smp_callin_clear_local_apic, .store_NMI_vector = store_NMI_vector, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index bf4670db25f..17d8f9c2218 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -85,8 +85,8 @@ struct genapic apic_default = { .send_IPI_self = NULL, .wakeup_cpu = NULL, - .trampoline_phys_low = TRAMPOLINE_PHYS_LOW, - .trampoline_phys_high = TRAMPOLINE_PHYS_HIGH, + .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, + .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, .wait_for_init_deassert = wait_for_init_deassert, .smp_callin_clear_local_apic = smp_callin_clear_local_apic, .store_NMI_vector = store_NMI_vector, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index d36642e6d90..871e85445e2 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -140,8 +140,8 @@ struct genapic apic_es7000 = { .send_IPI_self = NULL, .wakeup_cpu = NULL, - .trampoline_phys_low = TRAMPOLINE_PHYS_LOW, - .trampoline_phys_high = TRAMPOLINE_PHYS_HIGH, + .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, + .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, .wait_for_init_deassert = wait_for_init_deassert, .smp_callin_clear_local_apic = smp_callin_clear_local_apic, .store_NMI_vector = store_NMI_vector, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 135b1832ad8..0b496ab5450 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -104,8 +104,8 @@ struct genapic apic_numaq = { .send_IPI_self = NULL, .wakeup_cpu = NULL, - .trampoline_phys_low = TRAMPOLINE_PHYS_LOW, - .trampoline_phys_high = TRAMPOLINE_PHYS_HIGH, + .trampoline_phys_low = NUMAQ_TRAMPOLINE_PHYS_LOW, + .trampoline_phys_high = NUMAQ_TRAMPOLINE_PHYS_HIGH, .wait_for_init_deassert = wait_for_init_deassert, .smp_callin_clear_local_apic = smp_callin_clear_local_apic, .store_NMI_vector = store_NMI_vector, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 77196a4a9d2..c4799cd3459 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -84,8 +84,8 @@ struct genapic apic_summit = { .send_IPI_self = NULL, .wakeup_cpu = NULL, - .trampoline_phys_low = TRAMPOLINE_PHYS_LOW, - .trampoline_phys_high = TRAMPOLINE_PHYS_HIGH, + .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, + .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, .wait_for_init_deassert = wait_for_init_deassert, .smp_callin_clear_local_apic = smp_callin_clear_local_apic, .store_NMI_vector = store_NMI_vector, -- GitLab From abfa584c8df8b691cf18f51c7d4af27e5b32be4a Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 16:15:16 +0100 Subject: [PATCH 0576/4982] x86: set ->trampoline_phys_low/high on 64-bit too 64-bit x86 has zero for ->trampoline_phys_low/high, but the smpboot code can use these values - so it's better to set them up to their correct values. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/genapic.h | 6 ++++++ arch/x86/include/asm/mach-default/mach_wakecpu.h | 3 --- arch/x86/kernel/genapic_flat_64.c | 8 ++++---- arch/x86/kernel/genx2apic_cluster.c | 4 ++-- arch/x86/kernel/genx2apic_phys.c | 4 ++-- arch/x86/kernel/genx2apic_uv_x.c | 4 ++-- 6 files changed, 16 insertions(+), 13 deletions(-) diff --git a/arch/x86/include/asm/genapic.h b/arch/x86/include/asm/genapic.h index 8bb1c73c55b..90e83a769a1 100644 --- a/arch/x86/include/asm/genapic.h +++ b/arch/x86/include/asm/genapic.h @@ -88,6 +88,12 @@ struct genapic { extern struct genapic *apic; +/* + * Warm reset vector default position: + */ +#define DEFAULT_TRAMPOLINE_PHYS_LOW 0x467 +#define DEFAULT_TRAMPOLINE_PHYS_HIGH 0x469 + #ifdef CONFIG_X86_32 extern void es7000_update_genapic_to_cluster(void); #else diff --git a/arch/x86/include/asm/mach-default/mach_wakecpu.h b/arch/x86/include/asm/mach-default/mach_wakecpu.h index 0a8d7860e44..a327a675e47 100644 --- a/arch/x86/include/asm/mach-default/mach_wakecpu.h +++ b/arch/x86/include/asm/mach-default/mach_wakecpu.h @@ -1,9 +1,6 @@ #ifndef _ASM_X86_MACH_DEFAULT_MACH_WAKECPU_H #define _ASM_X86_MACH_DEFAULT_MACH_WAKECPU_H -#define DEFAULT_TRAMPOLINE_PHYS_LOW (0x467) -#define DEFAULT_TRAMPOLINE_PHYS_HIGH (0x469) - static inline void wait_for_init_deassert(atomic_t *deassert) { while (!atomic_read(deassert)) diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index 7c648ccea51..3a28d6a8c49 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -224,8 +224,8 @@ struct genapic apic_flat = { .send_IPI_self = apic_send_IPI_self, .wakeup_cpu = NULL, - .trampoline_phys_low = 0, - .trampoline_phys_high = 0, + .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, + .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, .wait_for_init_deassert = NULL, .smp_callin_clear_local_apic = NULL, .store_NMI_vector = NULL, @@ -370,8 +370,8 @@ struct genapic apic_physflat = { .send_IPI_self = apic_send_IPI_self, .wakeup_cpu = NULL, - .trampoline_phys_low = 0, - .trampoline_phys_high = 0, + .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, + .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, .wait_for_init_deassert = NULL, .smp_callin_clear_local_apic = NULL, .store_NMI_vector = NULL, diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c index 2d97726a973..abc5ee329f2 100644 --- a/arch/x86/kernel/genx2apic_cluster.c +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -228,8 +228,8 @@ struct genapic apic_x2apic_cluster = { .send_IPI_self = x2apic_send_IPI_self, .wakeup_cpu = NULL, - .trampoline_phys_low = 0, - .trampoline_phys_high = 0, + .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, + .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, .wait_for_init_deassert = NULL, .smp_callin_clear_local_apic = NULL, .store_NMI_vector = NULL, diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c index 74777c27669..dc815ef22d8 100644 --- a/arch/x86/kernel/genx2apic_phys.c +++ b/arch/x86/kernel/genx2apic_phys.c @@ -214,8 +214,8 @@ struct genapic apic_x2apic_phys = { .send_IPI_self = x2apic_send_IPI_self, .wakeup_cpu = NULL, - .trampoline_phys_low = 0, - .trampoline_phys_high = 0, + .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, + .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, .wait_for_init_deassert = NULL, .smp_callin_clear_local_apic = NULL, .store_NMI_vector = NULL, diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index 24b9f42db9b..b5908735ca5 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -287,8 +287,8 @@ struct genapic apic_x2apic_uv_x = { .send_IPI_self = uv_send_IPI_self, .wakeup_cpu = NULL, - .trampoline_phys_low = 0, - .trampoline_phys_high = 0, + .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, + .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, .wait_for_init_deassert = NULL, .smp_callin_clear_local_apic = NULL, .store_NMI_vector = NULL, -- GitLab From a965936643e28af8152d9e960b966baa1a5588a2 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 16:21:32 +0100 Subject: [PATCH 0577/4982] x86, smp: refactor ->wait_for_init_deassert() - spread out the namespace on a per APIC driver basis - handle a NULL ->wait_for_init_deassert() as a 'dont wait' default method - remove NUMAQ and Summit handlers Signed-off-by: Ingo Molnar --- arch/x86/include/asm/es7000/wakecpu.h | 2 +- arch/x86/include/asm/mach-default/mach_wakecpu.h | 2 +- arch/x86/include/asm/mach-generic/mach_wakecpu.h | 1 - arch/x86/include/asm/numaq/wakecpu.h | 5 ----- arch/x86/kernel/es7000_32.c | 6 +----- arch/x86/kernel/smpboot.c | 3 ++- arch/x86/mach-generic/bigsmp.c | 4 +++- arch/x86/mach-generic/default.c | 4 +++- arch/x86/mach-generic/es7000.c | 4 +++- arch/x86/mach-generic/numaq.c | 5 ++++- arch/x86/mach-generic/summit.c | 4 +++- 11 files changed, 21 insertions(+), 19 deletions(-) diff --git a/arch/x86/include/asm/es7000/wakecpu.h b/arch/x86/include/asm/es7000/wakecpu.h index 4c01be6ff80..5c4d05f46d2 100644 --- a/arch/x86/include/asm/es7000/wakecpu.h +++ b/arch/x86/include/asm/es7000/wakecpu.h @@ -4,7 +4,7 @@ #define ES7000_TRAMPOLINE_PHYS_LOW 0x467 #define ES7000_TRAMPOLINE_PHYS_HIGH 0x469 -static inline void wait_for_init_deassert(atomic_t *deassert) +static inline void es7000_wait_for_init_deassert(atomic_t *deassert) { #ifndef CONFIG_ES7000_CLUSTERED_APIC while (!atomic_read(deassert)) diff --git a/arch/x86/include/asm/mach-default/mach_wakecpu.h b/arch/x86/include/asm/mach-default/mach_wakecpu.h index a327a675e47..1d34c69a758 100644 --- a/arch/x86/include/asm/mach-default/mach_wakecpu.h +++ b/arch/x86/include/asm/mach-default/mach_wakecpu.h @@ -1,7 +1,7 @@ #ifndef _ASM_X86_MACH_DEFAULT_MACH_WAKECPU_H #define _ASM_X86_MACH_DEFAULT_MACH_WAKECPU_H -static inline void wait_for_init_deassert(atomic_t *deassert) +static inline void default_wait_for_init_deassert(atomic_t *deassert) { while (!atomic_read(deassert)) cpu_relax(); diff --git a/arch/x86/include/asm/mach-generic/mach_wakecpu.h b/arch/x86/include/asm/mach-generic/mach_wakecpu.h index 2031377a954..58e54122f73 100644 --- a/arch/x86/include/asm/mach-generic/mach_wakecpu.h +++ b/arch/x86/include/asm/mach-generic/mach_wakecpu.h @@ -1,7 +1,6 @@ #ifndef _ASM_X86_MACH_GENERIC_MACH_WAKECPU_H #define _ASM_X86_MACH_GENERIC_MACH_WAKECPU_H -#define wait_for_init_deassert (apic->wait_for_init_deassert) #define smp_callin_clear_local_apic (apic->smp_callin_clear_local_apic) #define store_NMI_vector (apic->store_NMI_vector) #define restore_NMI_vector (apic->restore_NMI_vector) diff --git a/arch/x86/include/asm/numaq/wakecpu.h b/arch/x86/include/asm/numaq/wakecpu.h index 8b6c16d8558..884b95cf584 100644 --- a/arch/x86/include/asm/numaq/wakecpu.h +++ b/arch/x86/include/asm/numaq/wakecpu.h @@ -6,11 +6,6 @@ #define NUMAQ_TRAMPOLINE_PHYS_LOW (0x8) #define NUMAQ_TRAMPOLINE_PHYS_HIGH (0xa) -/* We don't do anything here because we use NMI's to boot instead */ -static inline void wait_for_init_deassert(atomic_t *deassert) -{ -} - /* * Because we use NMIs rather than the INIT-STARTUP sequence to * bootstrap the CPUs, the APIC may be in a weird state. Kick it. diff --git a/arch/x86/kernel/es7000_32.c b/arch/x86/kernel/es7000_32.c index e73fe18488a..d7f433ee602 100644 --- a/arch/x86/kernel/es7000_32.c +++ b/arch/x86/kernel/es7000_32.c @@ -182,10 +182,6 @@ static int wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip) return 0; } -static void noop_wait_for_deassert(atomic_t *deassert_not_used) -{ -} - static int __init es7000_update_genapic(void) { apic->wakeup_cpu = wakeup_secondary_cpu_via_mip; @@ -194,7 +190,7 @@ static int __init es7000_update_genapic(void) if (boot_cpu_data.x86 == 6 && (boot_cpu_data.x86_model >= 7 || boot_cpu_data.x86_model <= 11)) { es7000_update_genapic_to_cluster(); - apic->wait_for_init_deassert = noop_wait_for_deassert; + apic->wait_for_init_deassert = NULL; apic->wakeup_cpu = wakeup_secondary_cpu_via_mip; } diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index ab83be2f8e0..558af378a61 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -196,7 +196,8 @@ static void __cpuinit smp_callin(void) * our local APIC. We have to wait for the IPI or we'll * lock up on an APIC access. */ - wait_for_init_deassert(&init_deasserted); + if (apic->wait_for_init_deassert) + apic->wait_for_init_deassert(&init_deasserted); /* * (This works even if the APIC is not enabled.) diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index a317fbe07fd..40910bfd1b4 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -106,7 +106,9 @@ struct genapic apic_bigsmp = { .wakeup_cpu = NULL, .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, - .wait_for_init_deassert = wait_for_init_deassert, + + .wait_for_init_deassert = default_wait_for_init_deassert, + .smp_callin_clear_local_apic = smp_callin_clear_local_apic, .store_NMI_vector = store_NMI_vector, .restore_NMI_vector = restore_NMI_vector, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index 17d8f9c2218..c2464843df9 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -87,7 +87,9 @@ struct genapic apic_default = { .wakeup_cpu = NULL, .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, - .wait_for_init_deassert = wait_for_init_deassert, + + .wait_for_init_deassert = default_wait_for_init_deassert, + .smp_callin_clear_local_apic = smp_callin_clear_local_apic, .store_NMI_vector = store_NMI_vector, .restore_NMI_vector = restore_NMI_vector, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 871e85445e2..4cb3984834e 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -142,7 +142,9 @@ struct genapic apic_es7000 = { .wakeup_cpu = NULL, .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, - .wait_for_init_deassert = wait_for_init_deassert, + + .wait_for_init_deassert = default_wait_for_init_deassert, + .smp_callin_clear_local_apic = smp_callin_clear_local_apic, .store_NMI_vector = store_NMI_vector, .restore_NMI_vector = restore_NMI_vector, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 0b496ab5450..fb03867e7c0 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -106,7 +106,10 @@ struct genapic apic_numaq = { .wakeup_cpu = NULL, .trampoline_phys_low = NUMAQ_TRAMPOLINE_PHYS_LOW, .trampoline_phys_high = NUMAQ_TRAMPOLINE_PHYS_HIGH, - .wait_for_init_deassert = wait_for_init_deassert, + + /* We don't do anything here because we use NMI's to boot instead */ + .wait_for_init_deassert = NULL, + .smp_callin_clear_local_apic = smp_callin_clear_local_apic, .store_NMI_vector = store_NMI_vector, .restore_NMI_vector = restore_NMI_vector, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index c4799cd3459..fdca78b96b6 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -86,7 +86,9 @@ struct genapic apic_summit = { .wakeup_cpu = NULL, .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, - .wait_for_init_deassert = wait_for_init_deassert, + + .wait_for_init_deassert = default_wait_for_init_deassert, + .smp_callin_clear_local_apic = smp_callin_clear_local_apic, .store_NMI_vector = store_NMI_vector, .restore_NMI_vector = restore_NMI_vector, -- GitLab From 333344d94300500e401cffb4eea10a5ab6e5a41d Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 16:31:52 +0100 Subject: [PATCH 0578/4982] x86, smp: refactor ->smp_callin_clear_local_apic() methods Only NUMAQ does something substantial here, because it initializes via NMIs (not via INIT as standard SMP startup) - so it needs to reset the APIC. - extend the generic code to handle NULL methods - clear out dummy methods and replace them with NULL - clean up: remove wrapper macros, etc. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/es7000/wakecpu.h | 5 ----- arch/x86/include/asm/mach-default/mach_wakecpu.h | 5 ----- arch/x86/include/asm/mach-generic/mach_wakecpu.h | 1 - arch/x86/include/asm/numaq/wakecpu.h | 4 ++-- arch/x86/kernel/smpboot.c | 3 ++- arch/x86/mach-generic/bigsmp.c | 3 ++- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 4 +++- arch/x86/mach-generic/numaq.c | 2 +- arch/x86/mach-generic/summit.c | 3 ++- 10 files changed, 13 insertions(+), 19 deletions(-) diff --git a/arch/x86/include/asm/es7000/wakecpu.h b/arch/x86/include/asm/es7000/wakecpu.h index 5c4d05f46d2..e8e03962633 100644 --- a/arch/x86/include/asm/es7000/wakecpu.h +++ b/arch/x86/include/asm/es7000/wakecpu.h @@ -13,11 +13,6 @@ static inline void es7000_wait_for_init_deassert(atomic_t *deassert) return; } -/* Nothing to do for most platforms, since cleared by the INIT cycle */ -static inline void smp_callin_clear_local_apic(void) -{ -} - static inline void store_NMI_vector(unsigned short *high, unsigned short *low) { } diff --git a/arch/x86/include/asm/mach-default/mach_wakecpu.h b/arch/x86/include/asm/mach-default/mach_wakecpu.h index 1d34c69a758..d059807cd7e 100644 --- a/arch/x86/include/asm/mach-default/mach_wakecpu.h +++ b/arch/x86/include/asm/mach-default/mach_wakecpu.h @@ -8,11 +8,6 @@ static inline void default_wait_for_init_deassert(atomic_t *deassert) return; } -/* Nothing to do for most platforms, since cleared by the INIT cycle */ -static inline void smp_callin_clear_local_apic(void) -{ -} - static inline void store_NMI_vector(unsigned short *high, unsigned short *low) { } diff --git a/arch/x86/include/asm/mach-generic/mach_wakecpu.h b/arch/x86/include/asm/mach-generic/mach_wakecpu.h index 58e54122f73..30515a154d8 100644 --- a/arch/x86/include/asm/mach-generic/mach_wakecpu.h +++ b/arch/x86/include/asm/mach-generic/mach_wakecpu.h @@ -1,7 +1,6 @@ #ifndef _ASM_X86_MACH_GENERIC_MACH_WAKECPU_H #define _ASM_X86_MACH_GENERIC_MACH_WAKECPU_H -#define smp_callin_clear_local_apic (apic->smp_callin_clear_local_apic) #define store_NMI_vector (apic->store_NMI_vector) #define restore_NMI_vector (apic->restore_NMI_vector) #define inquire_remote_apic (apic->inquire_remote_apic) diff --git a/arch/x86/include/asm/numaq/wakecpu.h b/arch/x86/include/asm/numaq/wakecpu.h index 884b95cf584..61d0a7d9613 100644 --- a/arch/x86/include/asm/numaq/wakecpu.h +++ b/arch/x86/include/asm/numaq/wakecpu.h @@ -8,9 +8,9 @@ /* * Because we use NMIs rather than the INIT-STARTUP sequence to - * bootstrap the CPUs, the APIC may be in a weird state. Kick it. + * bootstrap the CPUs, the APIC may be in a weird state. Kick it: */ -static inline void smp_callin_clear_local_apic(void) +static inline void numaq_smp_callin_clear_local_apic(void) { clear_local_APIC(); } diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 558af378a61..10873a46b29 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -244,7 +244,8 @@ static void __cpuinit smp_callin(void) */ pr_debug("CALLIN, before setup_local_APIC().\n"); - smp_callin_clear_local_apic(); + if (apic->smp_callin_clear_local_apic) + apic->smp_callin_clear_local_apic(); setup_local_APIC(); end_local_APIC_setup(); map_cpu_to_logical_apicid(); diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 40910bfd1b4..bd069e7b521 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -109,7 +109,8 @@ struct genapic apic_bigsmp = { .wait_for_init_deassert = default_wait_for_init_deassert, - .smp_callin_clear_local_apic = smp_callin_clear_local_apic, + .smp_callin_clear_local_apic = NULL, + .store_NMI_vector = store_NMI_vector, .restore_NMI_vector = restore_NMI_vector, .inquire_remote_apic = inquire_remote_apic, diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index c2464843df9..a25e6eff048 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -90,7 +90,7 @@ struct genapic apic_default = { .wait_for_init_deassert = default_wait_for_init_deassert, - .smp_callin_clear_local_apic = smp_callin_clear_local_apic, + .smp_callin_clear_local_apic = NULL, .store_NMI_vector = store_NMI_vector, .restore_NMI_vector = restore_NMI_vector, .inquire_remote_apic = inquire_remote_apic, diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 4cb3984834e..ab41b543914 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -145,7 +145,9 @@ struct genapic apic_es7000 = { .wait_for_init_deassert = default_wait_for_init_deassert, - .smp_callin_clear_local_apic = smp_callin_clear_local_apic, + /* Nothing to do for most platforms, since cleared by the INIT cycle: */ + .smp_callin_clear_local_apic = NULL, + .store_NMI_vector = store_NMI_vector, .restore_NMI_vector = restore_NMI_vector, .inquire_remote_apic = inquire_remote_apic, diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index fb03867e7c0..4d3924f8cd0 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -110,7 +110,7 @@ struct genapic apic_numaq = { /* We don't do anything here because we use NMI's to boot instead */ .wait_for_init_deassert = NULL, - .smp_callin_clear_local_apic = smp_callin_clear_local_apic, + .smp_callin_clear_local_apic = numaq_smp_callin_clear_local_apic, .store_NMI_vector = store_NMI_vector, .restore_NMI_vector = restore_NMI_vector, .inquire_remote_apic = inquire_remote_apic, diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index fdca78b96b6..2595baa7997 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -89,7 +89,8 @@ struct genapic apic_summit = { .wait_for_init_deassert = default_wait_for_init_deassert, - .smp_callin_clear_local_apic = smp_callin_clear_local_apic, + .smp_callin_clear_local_apic = NULL, + .store_NMI_vector = store_NMI_vector, .restore_NMI_vector = restore_NMI_vector, .inquire_remote_apic = inquire_remote_apic, -- GitLab From 7bd06ec63a1204ca44b9f1dc487b8632016162d1 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 16:31:52 +0100 Subject: [PATCH 0579/4982] x86, smp: refactor ->store/restore_NMI_vector() methods Only NUMAQ does something substantial here, because it initializes via NMIs (not via INIT as standard SMP startup) - so it needs to store and restore the NMI vector. - extend the generic code to handle NULL methods - clear out dummy methods and replace them with NULL - clean up: remove wrapper macros, etc. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/es7000/wakecpu.h | 8 -------- arch/x86/include/asm/mach-default/mach_wakecpu.h | 8 -------- arch/x86/include/asm/mach-generic/mach_wakecpu.h | 2 -- arch/x86/include/asm/numaq/wakecpu.h | 6 ++++-- arch/x86/kernel/smpboot.c | 3 ++- arch/x86/mach-generic/bigsmp.c | 5 ++--- arch/x86/mach-generic/default.c | 4 ++-- arch/x86/mach-generic/es7000.c | 5 ++--- arch/x86/mach-generic/numaq.c | 4 ++-- arch/x86/mach-generic/summit.c | 5 ++--- 10 files changed, 16 insertions(+), 34 deletions(-) diff --git a/arch/x86/include/asm/es7000/wakecpu.h b/arch/x86/include/asm/es7000/wakecpu.h index e8e03962633..71a3a412d0e 100644 --- a/arch/x86/include/asm/es7000/wakecpu.h +++ b/arch/x86/include/asm/es7000/wakecpu.h @@ -13,14 +13,6 @@ static inline void es7000_wait_for_init_deassert(atomic_t *deassert) return; } -static inline void store_NMI_vector(unsigned short *high, unsigned short *low) -{ -} - -static inline void restore_NMI_vector(unsigned short *high, unsigned short *low) -{ -} - extern void __inquire_remote_apic(int apicid); static inline void inquire_remote_apic(int apicid) diff --git a/arch/x86/include/asm/mach-default/mach_wakecpu.h b/arch/x86/include/asm/mach-default/mach_wakecpu.h index d059807cd7e..656bb5e52bc 100644 --- a/arch/x86/include/asm/mach-default/mach_wakecpu.h +++ b/arch/x86/include/asm/mach-default/mach_wakecpu.h @@ -8,14 +8,6 @@ static inline void default_wait_for_init_deassert(atomic_t *deassert) return; } -static inline void store_NMI_vector(unsigned short *high, unsigned short *low) -{ -} - -static inline void restore_NMI_vector(unsigned short *high, unsigned short *low) -{ -} - #ifdef CONFIG_SMP extern void __inquire_remote_apic(int apicid); #else /* CONFIG_SMP */ diff --git a/arch/x86/include/asm/mach-generic/mach_wakecpu.h b/arch/x86/include/asm/mach-generic/mach_wakecpu.h index 30515a154d8..93207dfe8f5 100644 --- a/arch/x86/include/asm/mach-generic/mach_wakecpu.h +++ b/arch/x86/include/asm/mach-generic/mach_wakecpu.h @@ -1,8 +1,6 @@ #ifndef _ASM_X86_MACH_GENERIC_MACH_WAKECPU_H #define _ASM_X86_MACH_GENERIC_MACH_WAKECPU_H -#define store_NMI_vector (apic->store_NMI_vector) -#define restore_NMI_vector (apic->restore_NMI_vector) #define inquire_remote_apic (apic->inquire_remote_apic) #endif /* _ASM_X86_MACH_GENERIC_MACH_APIC_H */ diff --git a/arch/x86/include/asm/numaq/wakecpu.h b/arch/x86/include/asm/numaq/wakecpu.h index 61d0a7d9613..123201712a9 100644 --- a/arch/x86/include/asm/numaq/wakecpu.h +++ b/arch/x86/include/asm/numaq/wakecpu.h @@ -15,7 +15,8 @@ static inline void numaq_smp_callin_clear_local_apic(void) clear_local_APIC(); } -static inline void store_NMI_vector(unsigned short *high, unsigned short *low) +static inline void +numaq_store_NMI_vector(unsigned short *high, unsigned short *low) { printk("Storing NMI vector\n"); *high = @@ -24,7 +25,8 @@ static inline void store_NMI_vector(unsigned short *high, unsigned short *low) *((volatile unsigned short *)phys_to_virt(NUMAQ_TRAMPOLINE_PHYS_LOW)); } -static inline void restore_NMI_vector(unsigned short *high, unsigned short *low) +static inline void +numaq_restore_NMI_vector(unsigned short *high, unsigned short *low) { printk("Restoring NMI vector\n"); *((volatile unsigned short *)phys_to_virt(NUMAQ_TRAMPOLINE_PHYS_HIGH)) = diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 10873a46b29..1492024592f 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -826,7 +826,8 @@ do_rest: pr_debug("Setting warm reset code and vector.\n"); - store_NMI_vector(&nmi_high, &nmi_low); + if (apic->store_NMI_vector) + apic->store_NMI_vector(&nmi_high, &nmi_low); smpboot_setup_warm_reset_vector(start_ip); /* diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index bd069e7b521..ecdb230d0f2 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -110,8 +110,7 @@ struct genapic apic_bigsmp = { .wait_for_init_deassert = default_wait_for_init_deassert, .smp_callin_clear_local_apic = NULL, - - .store_NMI_vector = store_NMI_vector, - .restore_NMI_vector = restore_NMI_vector, + .store_NMI_vector = NULL, + .restore_NMI_vector = NULL, .inquire_remote_apic = inquire_remote_apic, }; diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index a25e6eff048..950925615a9 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -91,7 +91,7 @@ struct genapic apic_default = { .wait_for_init_deassert = default_wait_for_init_deassert, .smp_callin_clear_local_apic = NULL, - .store_NMI_vector = store_NMI_vector, - .restore_NMI_vector = restore_NMI_vector, + .store_NMI_vector = NULL, + .restore_NMI_vector = NULL, .inquire_remote_apic = inquire_remote_apic, }; diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index ab41b543914..13190709138 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -147,8 +147,7 @@ struct genapic apic_es7000 = { /* Nothing to do for most platforms, since cleared by the INIT cycle: */ .smp_callin_clear_local_apic = NULL, - - .store_NMI_vector = store_NMI_vector, - .restore_NMI_vector = restore_NMI_vector, + .store_NMI_vector = NULL, + .restore_NMI_vector = NULL, .inquire_remote_apic = inquire_remote_apic, }; diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 4d3924f8cd0..d7f7fcf21c3 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -111,7 +111,7 @@ struct genapic apic_numaq = { .wait_for_init_deassert = NULL, .smp_callin_clear_local_apic = numaq_smp_callin_clear_local_apic, - .store_NMI_vector = store_NMI_vector, - .restore_NMI_vector = restore_NMI_vector, + .store_NMI_vector = numaq_store_NMI_vector, + .restore_NMI_vector = numaq_restore_NMI_vector, .inquire_remote_apic = inquire_remote_apic, }; diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 2595baa7997..46fca79f831 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -90,8 +90,7 @@ struct genapic apic_summit = { .wait_for_init_deassert = default_wait_for_init_deassert, .smp_callin_clear_local_apic = NULL, - - .store_NMI_vector = store_NMI_vector, - .restore_NMI_vector = restore_NMI_vector, + .store_NMI_vector = NULL, + .restore_NMI_vector = NULL, .inquire_remote_apic = inquire_remote_apic, }; -- GitLab From 3d5f597e938c425554cb7668fd3c9d6a536a984a Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 16:43:47 +0100 Subject: [PATCH 0580/4982] x86, smp: remove ->restore_NMI_vector() Nothing actually restores the NMI vector - so remove this logic altogether. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/genapic.h | 1 - arch/x86/include/asm/numaq/wakecpu.h | 10 ---------- arch/x86/kernel/genapic_flat_64.c | 2 -- arch/x86/kernel/genx2apic_cluster.c | 1 - arch/x86/kernel/genx2apic_phys.c | 1 - arch/x86/kernel/genx2apic_uv_x.c | 1 - arch/x86/mach-generic/bigsmp.c | 1 - arch/x86/mach-generic/default.c | 1 - arch/x86/mach-generic/es7000.c | 1 - arch/x86/mach-generic/numaq.c | 1 - arch/x86/mach-generic/summit.c | 1 - 11 files changed, 21 deletions(-) diff --git a/arch/x86/include/asm/genapic.h b/arch/x86/include/asm/genapic.h index 90e83a769a1..e5f9c5696fb 100644 --- a/arch/x86/include/asm/genapic.h +++ b/arch/x86/include/asm/genapic.h @@ -82,7 +82,6 @@ struct genapic { void (*wait_for_init_deassert)(atomic_t *deassert); void (*smp_callin_clear_local_apic)(void); void (*store_NMI_vector)(unsigned short *high, unsigned short *low); - void (*restore_NMI_vector)(unsigned short *high, unsigned short *low); void (*inquire_remote_apic)(int apicid); }; diff --git a/arch/x86/include/asm/numaq/wakecpu.h b/arch/x86/include/asm/numaq/wakecpu.h index 123201712a9..920dcfefa83 100644 --- a/arch/x86/include/asm/numaq/wakecpu.h +++ b/arch/x86/include/asm/numaq/wakecpu.h @@ -25,16 +25,6 @@ numaq_store_NMI_vector(unsigned short *high, unsigned short *low) *((volatile unsigned short *)phys_to_virt(NUMAQ_TRAMPOLINE_PHYS_LOW)); } -static inline void -numaq_restore_NMI_vector(unsigned short *high, unsigned short *low) -{ - printk("Restoring NMI vector\n"); - *((volatile unsigned short *)phys_to_virt(NUMAQ_TRAMPOLINE_PHYS_HIGH)) = - *high; - *((volatile unsigned short *)phys_to_virt(NUMAQ_TRAMPOLINE_PHYS_LOW)) = - *low; -} - static inline void inquire_remote_apic(int apicid) { } diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index 3a28d6a8c49..e9237f59928 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -229,7 +229,6 @@ struct genapic apic_flat = { .wait_for_init_deassert = NULL, .smp_callin_clear_local_apic = NULL, .store_NMI_vector = NULL, - .restore_NMI_vector = NULL, .inquire_remote_apic = NULL, }; @@ -375,6 +374,5 @@ struct genapic apic_physflat = { .wait_for_init_deassert = NULL, .smp_callin_clear_local_apic = NULL, .store_NMI_vector = NULL, - .restore_NMI_vector = NULL, .inquire_remote_apic = NULL, }; diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c index abc5ee329f2..7c87156b641 100644 --- a/arch/x86/kernel/genx2apic_cluster.c +++ b/arch/x86/kernel/genx2apic_cluster.c @@ -233,6 +233,5 @@ struct genapic apic_x2apic_cluster = { .wait_for_init_deassert = NULL, .smp_callin_clear_local_apic = NULL, .store_NMI_vector = NULL, - .restore_NMI_vector = NULL, .inquire_remote_apic = NULL, }; diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c index dc815ef22d8..5cbae8aa040 100644 --- a/arch/x86/kernel/genx2apic_phys.c +++ b/arch/x86/kernel/genx2apic_phys.c @@ -219,6 +219,5 @@ struct genapic apic_x2apic_phys = { .wait_for_init_deassert = NULL, .smp_callin_clear_local_apic = NULL, .store_NMI_vector = NULL, - .restore_NMI_vector = NULL, .inquire_remote_apic = NULL, }; diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index b5908735ca5..6adb5e6f4d9 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c @@ -292,7 +292,6 @@ struct genapic apic_x2apic_uv_x = { .wait_for_init_deassert = NULL, .smp_callin_clear_local_apic = NULL, .store_NMI_vector = NULL, - .restore_NMI_vector = NULL, .inquire_remote_apic = NULL, }; diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index ecdb230d0f2..d9377af88cb 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -111,6 +111,5 @@ struct genapic apic_bigsmp = { .smp_callin_clear_local_apic = NULL, .store_NMI_vector = NULL, - .restore_NMI_vector = NULL, .inquire_remote_apic = inquire_remote_apic, }; diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index 950925615a9..b004257035c 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -92,6 +92,5 @@ struct genapic apic_default = { .smp_callin_clear_local_apic = NULL, .store_NMI_vector = NULL, - .restore_NMI_vector = NULL, .inquire_remote_apic = inquire_remote_apic, }; diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 13190709138..62673a8002f 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -148,6 +148,5 @@ struct genapic apic_es7000 = { /* Nothing to do for most platforms, since cleared by the INIT cycle: */ .smp_callin_clear_local_apic = NULL, .store_NMI_vector = NULL, - .restore_NMI_vector = NULL, .inquire_remote_apic = inquire_remote_apic, }; diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index d7f7fcf21c3..2c3341564d1 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -112,6 +112,5 @@ struct genapic apic_numaq = { .smp_callin_clear_local_apic = numaq_smp_callin_clear_local_apic, .store_NMI_vector = numaq_store_NMI_vector, - .restore_NMI_vector = numaq_restore_NMI_vector, .inquire_remote_apic = inquire_remote_apic, }; diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 46fca79f831..c2471a9fa8f 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -91,6 +91,5 @@ struct genapic apic_summit = { .smp_callin_clear_local_apic = NULL, .store_NMI_vector = NULL, - .restore_NMI_vector = NULL, .inquire_remote_apic = inquire_remote_apic, }; -- GitLab From 25dc004903a38f0b6f6626dbbab058c8709c5398 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 16:31:52 +0100 Subject: [PATCH 0581/4982] x86, smp: refactor ->inquire_remote_apic() methods Nothing exciting - a few subarches dont want APIC remote reads to be performed - the others are content with the default method. - extend the generic code to handle NULL methods - clear out dummy methods and replace them with NULL - clean up: remove wrapper macros, etc. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/es7000/wakecpu.h | 8 -------- arch/x86/include/asm/mach-default/mach_wakecpu.h | 2 +- arch/x86/include/asm/mach-generic/mach_wakecpu.h | 2 -- arch/x86/include/asm/numaq/wakecpu.h | 4 ---- arch/x86/kernel/smpboot.c | 4 ++-- arch/x86/mach-generic/bigsmp.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/es7000.c | 2 +- arch/x86/mach-generic/numaq.c | 2 +- arch/x86/mach-generic/summit.c | 2 +- 10 files changed, 8 insertions(+), 22 deletions(-) diff --git a/arch/x86/include/asm/es7000/wakecpu.h b/arch/x86/include/asm/es7000/wakecpu.h index 71a3a412d0e..99c72be1840 100644 --- a/arch/x86/include/asm/es7000/wakecpu.h +++ b/arch/x86/include/asm/es7000/wakecpu.h @@ -13,12 +13,4 @@ static inline void es7000_wait_for_init_deassert(atomic_t *deassert) return; } -extern void __inquire_remote_apic(int apicid); - -static inline void inquire_remote_apic(int apicid) -{ - if (apic_verbosity >= APIC_DEBUG) - __inquire_remote_apic(apicid); -} - #endif /* __ASM_MACH_WAKECPU_H */ diff --git a/arch/x86/include/asm/mach-default/mach_wakecpu.h b/arch/x86/include/asm/mach-default/mach_wakecpu.h index 656bb5e52bc..b1cde560e4c 100644 --- a/arch/x86/include/asm/mach-default/mach_wakecpu.h +++ b/arch/x86/include/asm/mach-default/mach_wakecpu.h @@ -16,7 +16,7 @@ static inline void __inquire_remote_apic(int apicid) } #endif /* CONFIG_SMP */ -static inline void inquire_remote_apic(int apicid) +static inline void default_inquire_remote_apic(int apicid) { if (apic_verbosity >= APIC_DEBUG) __inquire_remote_apic(apicid); diff --git a/arch/x86/include/asm/mach-generic/mach_wakecpu.h b/arch/x86/include/asm/mach-generic/mach_wakecpu.h index 93207dfe8f5..0b884c03a3f 100644 --- a/arch/x86/include/asm/mach-generic/mach_wakecpu.h +++ b/arch/x86/include/asm/mach-generic/mach_wakecpu.h @@ -1,6 +1,4 @@ #ifndef _ASM_X86_MACH_GENERIC_MACH_WAKECPU_H #define _ASM_X86_MACH_GENERIC_MACH_WAKECPU_H -#define inquire_remote_apic (apic->inquire_remote_apic) - #endif /* _ASM_X86_MACH_GENERIC_MACH_APIC_H */ diff --git a/arch/x86/include/asm/numaq/wakecpu.h b/arch/x86/include/asm/numaq/wakecpu.h index 920dcfefa83..afe81439c7d 100644 --- a/arch/x86/include/asm/numaq/wakecpu.h +++ b/arch/x86/include/asm/numaq/wakecpu.h @@ -25,8 +25,4 @@ numaq_store_NMI_vector(unsigned short *high, unsigned short *low) *((volatile unsigned short *)phys_to_virt(NUMAQ_TRAMPOLINE_PHYS_LOW)); } -static inline void inquire_remote_apic(int apicid) -{ -} - #endif /* __ASM_NUMAQ_WAKECPU_H */ diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 1492024592f..170adc5b6cb 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -876,8 +876,8 @@ do_rest: else /* trampoline code not run */ printk(KERN_ERR "Not responding.\n"); - if (get_uv_system_type() != UV_NON_UNIQUE_APIC) - inquire_remote_apic(apicid); + if (apic->inquire_remote_apic) + apic->inquire_remote_apic(apicid); } } diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index d9377af88cb..4d8b2d442ba 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -111,5 +111,5 @@ struct genapic apic_bigsmp = { .smp_callin_clear_local_apic = NULL, .store_NMI_vector = NULL, - .inquire_remote_apic = inquire_remote_apic, + .inquire_remote_apic = default_inquire_remote_apic, }; diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index b004257035c..c12dd2300a5 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -92,5 +92,5 @@ struct genapic apic_default = { .smp_callin_clear_local_apic = NULL, .store_NMI_vector = NULL, - .inquire_remote_apic = inquire_remote_apic, + .inquire_remote_apic = default_inquire_remote_apic, }; diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 62673a8002f..be090b2037c 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -148,5 +148,5 @@ struct genapic apic_es7000 = { /* Nothing to do for most platforms, since cleared by the INIT cycle: */ .smp_callin_clear_local_apic = NULL, .store_NMI_vector = NULL, - .inquire_remote_apic = inquire_remote_apic, + .inquire_remote_apic = default_inquire_remote_apic, }; diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index 2c3341564d1..ddb50fba286 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -112,5 +112,5 @@ struct genapic apic_numaq = { .smp_callin_clear_local_apic = numaq_smp_callin_clear_local_apic, .store_NMI_vector = numaq_store_NMI_vector, - .inquire_remote_apic = inquire_remote_apic, + .inquire_remote_apic = NULL, }; diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index c2471a9fa8f..d5db3045437 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -91,5 +91,5 @@ struct genapic apic_summit = { .smp_callin_clear_local_apic = NULL, .store_NMI_vector = NULL, - .inquire_remote_apic = inquire_remote_apic, + .inquire_remote_apic = default_inquire_remote_apic, }; -- GitLab From 018e047f3a98bd8d9e9d78b19bc38415f0c34dd7 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 17:09:58 +0100 Subject: [PATCH 0582/4982] x86, ES7000: consolidate the APIC code Consolidate all the ES7000 APIC code into arch/x86/mach-generic/es7000.c. With this ES7000 ceases to rely on any subarchitecture include files. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/es7000/apic.h | 236 ------------------- arch/x86/include/asm/es7000/apicdef.h | 9 - arch/x86/include/asm/es7000/ipi.h | 22 -- arch/x86/include/asm/es7000/mpparse.h | 23 -- arch/x86/include/asm/es7000/wakecpu.h | 16 -- arch/x86/mach-generic/es7000.c | 314 ++++++++++++++++++++++++-- 6 files changed, 295 insertions(+), 325 deletions(-) delete mode 100644 arch/x86/include/asm/es7000/apic.h delete mode 100644 arch/x86/include/asm/es7000/apicdef.h delete mode 100644 arch/x86/include/asm/es7000/ipi.h delete mode 100644 arch/x86/include/asm/es7000/mpparse.h delete mode 100644 arch/x86/include/asm/es7000/wakecpu.h diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h deleted file mode 100644 index b89b45db735..00000000000 --- a/arch/x86/include/asm/es7000/apic.h +++ /dev/null @@ -1,236 +0,0 @@ -#ifndef __ASM_ES7000_APIC_H -#define __ASM_ES7000_APIC_H - -#include - -#define xapic_phys_to_log_apicid(cpu) per_cpu(x86_bios_cpu_apicid, cpu) - -static inline int es7000_apic_id_registered(void) -{ - return 1; -} - -static inline const cpumask_t *target_cpus_cluster(void) -{ - return &CPU_MASK_ALL; -} - -static inline const cpumask_t *es7000_target_cpus(void) -{ - return &cpumask_of_cpu(smp_processor_id()); -} - -#define APIC_DFR_VALUE_CLUSTER (APIC_DFR_CLUSTER) -#define INT_DELIVERY_MODE_CLUSTER (dest_LowestPrio) -#define INT_DEST_MODE_CLUSTER (1) /* logical delivery broadcast to all procs */ - -#define APIC_DFR_VALUE (APIC_DFR_FLAT) - -static inline unsigned long -es7000_check_apicid_used(physid_mask_t bitmap, int apicid) -{ - return 0; -} -static inline unsigned long es7000_check_apicid_present(int bit) -{ - return physid_isset(bit, phys_cpu_present_map); -} - -extern void es7000_enable_apic_mode(void); - -#define apicid_cluster(apicid) (apicid & 0xF0) - -static inline unsigned long calculate_ldr(int cpu) -{ - unsigned long id; - id = xapic_phys_to_log_apicid(cpu); - return (SET_APIC_LOGICAL_ID(id)); -} - -/* - * Set up the logical destination ID. - * - * Intel recommends to set DFR, LdR and TPR before enabling - * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel - * document number 292116). So here it goes... - */ -static inline void es7000_init_apic_ldr_cluster(void) -{ - unsigned long val; - int cpu = smp_processor_id(); - - apic_write(APIC_DFR, APIC_DFR_VALUE_CLUSTER); - val = calculate_ldr(cpu); - apic_write(APIC_LDR, val); -} - -static inline void es7000_init_apic_ldr(void) -{ - unsigned long val; - int cpu = smp_processor_id(); - - apic_write(APIC_DFR, APIC_DFR_VALUE); - val = calculate_ldr(cpu); - apic_write(APIC_LDR, val); -} - -extern int apic_version [MAX_APICS]; -static inline void es7000_setup_apic_routing(void) -{ - int apic = per_cpu(x86_bios_cpu_apicid, smp_processor_id()); - printk("Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n", - (apic_version[apic] == 0x14) ? - "Physical Cluster" : "Logical Cluster", - nr_ioapics, cpus_addr(*es7000_target_cpus())[0]); -} - -static inline int es7000_apicid_to_node(int logical_apicid) -{ - return 0; -} - - -static inline int es7000_cpu_present_to_apicid(int mps_cpu) -{ - if (!mps_cpu) - return boot_cpu_physical_apicid; - else if (mps_cpu < nr_cpu_ids) - return (int) per_cpu(x86_bios_cpu_apicid, mps_cpu); - else - return BAD_APICID; -} - -static inline physid_mask_t es7000_apicid_to_cpu_present(int phys_apicid) -{ - static int id = 0; - physid_mask_t mask; - mask = physid_mask_of_physid(id); - ++id; - return mask; -} - -extern u8 cpu_2_logical_apicid[]; -/* Mapping from cpu number to logical apicid */ -static inline int es7000_cpu_to_logical_apicid(int cpu) -{ -#ifdef CONFIG_SMP - if (cpu >= nr_cpu_ids) - return BAD_APICID; - return (int)cpu_2_logical_apicid[cpu]; -#else - return logical_smp_processor_id(); -#endif -} - -static inline physid_mask_t es7000_ioapic_phys_id_map(physid_mask_t phys_map) -{ - /* For clustered we don't have a good way to do this yet - hack */ - return physids_promote(0xff); -} - -extern unsigned int boot_cpu_physical_apicid; - -static inline int es7000_check_phys_apicid_present(int cpu_physical_apicid) -{ - boot_cpu_physical_apicid = read_apic_id(); - return (1); -} - -static inline unsigned int -es7000_cpu_mask_to_apicid_cluster(const struct cpumask *cpumask) -{ - int cpus_found = 0; - int num_bits_set; - int apicid; - int cpu; - - num_bits_set = cpumask_weight(cpumask); - /* Return id to all */ - if (num_bits_set == nr_cpu_ids) - return 0xFF; - /* - * The cpus in the mask must all be on the apic cluster. If are not - * on the same apicid cluster return default value of target_cpus(): - */ - cpu = cpumask_first(cpumask); - apicid = es7000_cpu_to_logical_apicid(cpu); - - while (cpus_found < num_bits_set) { - if (cpumask_test_cpu(cpu, cpumask)) { - int new_apicid = es7000_cpu_to_logical_apicid(cpu); - - if (apicid_cluster(apicid) != - apicid_cluster(new_apicid)) { - printk ("%s: Not a valid mask!\n", __func__); - - return 0xFF; - } - apicid = new_apicid; - cpus_found++; - } - cpu++; - } - return apicid; -} - -static inline unsigned int es7000_cpu_mask_to_apicid(const cpumask_t *cpumask) -{ - int cpus_found = 0; - int num_bits_set; - int apicid; - int cpu; - - num_bits_set = cpus_weight(*cpumask); - /* Return id to all */ - if (num_bits_set == nr_cpu_ids) - return es7000_cpu_to_logical_apicid(0); - /* - * The cpus in the mask must all be on the apic cluster. If are not - * on the same apicid cluster return default value of target_cpus(): - */ - cpu = first_cpu(*cpumask); - apicid = es7000_cpu_to_logical_apicid(cpu); - while (cpus_found < num_bits_set) { - if (cpu_isset(cpu, *cpumask)) { - int new_apicid = es7000_cpu_to_logical_apicid(cpu); - - if (apicid_cluster(apicid) != - apicid_cluster(new_apicid)) { - printk ("%s: Not a valid mask!\n", __func__); - - return es7000_cpu_to_logical_apicid(0); - } - apicid = new_apicid; - cpus_found++; - } - cpu++; - } - return apicid; -} - - -static inline unsigned int -es7000_cpu_mask_to_apicid_and(const struct cpumask *inmask, - const struct cpumask *andmask) -{ - int apicid = es7000_cpu_to_logical_apicid(0); - cpumask_var_t cpumask; - - if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC)) - return apicid; - - cpumask_and(cpumask, inmask, andmask); - cpumask_and(cpumask, cpumask, cpu_online_mask); - apicid = es7000_cpu_mask_to_apicid(cpumask); - - free_cpumask_var(cpumask); - - return apicid; -} - -static inline int es7000_phys_pkg_id(int cpuid_apic, int index_msb) -{ - return cpuid_apic >> index_msb; -} - -#endif /* __ASM_ES7000_APIC_H */ diff --git a/arch/x86/include/asm/es7000/apicdef.h b/arch/x86/include/asm/es7000/apicdef.h deleted file mode 100644 index c74881a7b3d..00000000000 --- a/arch/x86/include/asm/es7000/apicdef.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __ASM_ES7000_APICDEF_H -#define __ASM_ES7000_APICDEF_H - -static inline unsigned int es7000_get_apic_id(unsigned long x) -{ - return (x >> 24) & 0xFF; -} - -#endif diff --git a/arch/x86/include/asm/es7000/ipi.h b/arch/x86/include/asm/es7000/ipi.h deleted file mode 100644 index 81e77c812ba..00000000000 --- a/arch/x86/include/asm/es7000/ipi.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef __ASM_ES7000_IPI_H -#define __ASM_ES7000_IPI_H - -void default_send_IPI_mask_sequence(const struct cpumask *mask, int vector); -void default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector); - -static inline void es7000_send_IPI_mask(const struct cpumask *mask, int vector) -{ - default_send_IPI_mask_sequence(mask, vector); -} - -static inline void es7000_send_IPI_allbutself(int vector) -{ - default_send_IPI_mask_allbutself(cpu_online_mask, vector); -} - -static inline void es7000_send_IPI_all(int vector) -{ - es7000_send_IPI_mask(cpu_online_mask, vector); -} - -#endif /* __ASM_ES7000_IPI_H */ diff --git a/arch/x86/include/asm/es7000/mpparse.h b/arch/x86/include/asm/es7000/mpparse.h deleted file mode 100644 index 662eb1e574d..00000000000 --- a/arch/x86/include/asm/es7000/mpparse.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef __ASM_ES7000_MPPARSE_H -#define __ASM_ES7000_MPPARSE_H - -#include - -extern int parse_unisys_oem (char *oemptr); -extern int find_unisys_acpi_oem_table(unsigned long *oem_addr); -extern void unmap_unisys_acpi_oem_table(unsigned long oem_addr); -extern void setup_unisys(void); - -#ifdef CONFIG_ACPI -static inline int es7000_check_dsdt(void) -{ - struct acpi_table_header header; - - if (ACPI_SUCCESS(acpi_get_table_header(ACPI_SIG_DSDT, 0, &header)) && - !strncmp(header.oem_id, "UNISYS", 6)) - return 1; - return 0; -} -#endif - -#endif /* __ASM_MACH_MPPARSE_H */ diff --git a/arch/x86/include/asm/es7000/wakecpu.h b/arch/x86/include/asm/es7000/wakecpu.h deleted file mode 100644 index 99c72be1840..00000000000 --- a/arch/x86/include/asm/es7000/wakecpu.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __ASM_ES7000_WAKECPU_H -#define __ASM_ES7000_WAKECPU_H - -#define ES7000_TRAMPOLINE_PHYS_LOW 0x467 -#define ES7000_TRAMPOLINE_PHYS_HIGH 0x469 - -static inline void es7000_wait_for_init_deassert(atomic_t *deassert) -{ -#ifndef CONFIG_ES7000_CLUSTERED_APIC - while (!atomic_read(deassert)) - cpu_relax(); -#endif - return; -} - -#endif /* __ASM_MACH_WAKECPU_H */ diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index be090b2037c..8b6113ec380 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -11,13 +11,300 @@ #include #include #include -#include +#include #include -#include -#include -#include +#include #include +#define APIC_DFR_VALUE_CLUSTER (APIC_DFR_CLUSTER) +#define INT_DELIVERY_MODE_CLUSTER (dest_LowestPrio) +#define INT_DEST_MODE_CLUSTER (1) /* logical delivery broadcast to all procs */ + +#define APIC_DFR_VALUE (APIC_DFR_FLAT) + +extern void es7000_enable_apic_mode(void); +extern int apic_version [MAX_APICS]; +extern u8 cpu_2_logical_apicid[]; +extern unsigned int boot_cpu_physical_apicid; + +extern int parse_unisys_oem (char *oemptr); +extern int find_unisys_acpi_oem_table(unsigned long *oem_addr); +extern void unmap_unisys_acpi_oem_table(unsigned long oem_addr); +extern void setup_unisys(void); + +#define apicid_cluster(apicid) (apicid & 0xF0) +#define xapic_phys_to_log_apicid(cpu) per_cpu(x86_bios_cpu_apicid, cpu) + +static void es7000_vector_allocation_domain(int cpu, cpumask_t *retmask) +{ + /* Careful. Some cpus do not strictly honor the set of cpus + * specified in the interrupt destination when using lowest + * priority interrupt delivery mode. + * + * In particular there was a hyperthreading cpu observed to + * deliver interrupts to the wrong hyperthread when only one + * hyperthread was specified in the interrupt desitination. + */ + *retmask = (cpumask_t){ { [0] = APIC_ALL_CPUS, } }; +} + + +static void es7000_wait_for_init_deassert(atomic_t *deassert) +{ +#ifndef CONFIG_ES7000_CLUSTERED_APIC + while (!atomic_read(deassert)) + cpu_relax(); +#endif + return; +} + +static unsigned int es7000_get_apic_id(unsigned long x) +{ + return (x >> 24) & 0xFF; +} + +#ifdef CONFIG_ACPI +static int es7000_check_dsdt(void) +{ + struct acpi_table_header header; + + if (ACPI_SUCCESS(acpi_get_table_header(ACPI_SIG_DSDT, 0, &header)) && + !strncmp(header.oem_id, "UNISYS", 6)) + return 1; + return 0; +} +#endif + +static void es7000_send_IPI_mask(const struct cpumask *mask, int vector) +{ + default_send_IPI_mask_sequence(mask, vector); +} + +static void es7000_send_IPI_allbutself(int vector) +{ + default_send_IPI_mask_allbutself(cpu_online_mask, vector); +} + +static void es7000_send_IPI_all(int vector) +{ + es7000_send_IPI_mask(cpu_online_mask, vector); +} + +static int es7000_apic_id_registered(void) +{ + return 1; +} + +static const cpumask_t *target_cpus_cluster(void) +{ + return &CPU_MASK_ALL; +} + +static const cpumask_t *es7000_target_cpus(void) +{ + return &cpumask_of_cpu(smp_processor_id()); +} + +static unsigned long +es7000_check_apicid_used(physid_mask_t bitmap, int apicid) +{ + return 0; +} +static unsigned long es7000_check_apicid_present(int bit) +{ + return physid_isset(bit, phys_cpu_present_map); +} + +static unsigned long calculate_ldr(int cpu) +{ + unsigned long id = xapic_phys_to_log_apicid(cpu); + + return (SET_APIC_LOGICAL_ID(id)); +} + +/* + * Set up the logical destination ID. + * + * Intel recommends to set DFR, LdR and TPR before enabling + * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel + * document number 292116). So here it goes... + */ +static void es7000_init_apic_ldr_cluster(void) +{ + unsigned long val; + int cpu = smp_processor_id(); + + apic_write(APIC_DFR, APIC_DFR_VALUE_CLUSTER); + val = calculate_ldr(cpu); + apic_write(APIC_LDR, val); +} + +static void es7000_init_apic_ldr(void) +{ + unsigned long val; + int cpu = smp_processor_id(); + + apic_write(APIC_DFR, APIC_DFR_VALUE); + val = calculate_ldr(cpu); + apic_write(APIC_LDR, val); +} + +static void es7000_setup_apic_routing(void) +{ + int apic = per_cpu(x86_bios_cpu_apicid, smp_processor_id()); + printk("Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n", + (apic_version[apic] == 0x14) ? + "Physical Cluster" : "Logical Cluster", + nr_ioapics, cpus_addr(*es7000_target_cpus())[0]); +} + +static int es7000_apicid_to_node(int logical_apicid) +{ + return 0; +} + + +static int es7000_cpu_present_to_apicid(int mps_cpu) +{ + if (!mps_cpu) + return boot_cpu_physical_apicid; + else if (mps_cpu < nr_cpu_ids) + return (int) per_cpu(x86_bios_cpu_apicid, mps_cpu); + else + return BAD_APICID; +} + +static physid_mask_t es7000_apicid_to_cpu_present(int phys_apicid) +{ + static int id = 0; + physid_mask_t mask; + + mask = physid_mask_of_physid(id); + ++id; + + return mask; +} + +/* Mapping from cpu number to logical apicid */ +static int es7000_cpu_to_logical_apicid(int cpu) +{ +#ifdef CONFIG_SMP + if (cpu >= nr_cpu_ids) + return BAD_APICID; + return (int)cpu_2_logical_apicid[cpu]; +#else + return logical_smp_processor_id(); +#endif +} + +static physid_mask_t es7000_ioapic_phys_id_map(physid_mask_t phys_map) +{ + /* For clustered we don't have a good way to do this yet - hack */ + return physids_promote(0xff); +} + +static int es7000_check_phys_apicid_present(int cpu_physical_apicid) +{ + boot_cpu_physical_apicid = read_apic_id(); + return (1); +} + +static unsigned int +es7000_cpu_mask_to_apicid_cluster(const struct cpumask *cpumask) +{ + int cpus_found = 0; + int num_bits_set; + int apicid; + int cpu; + + num_bits_set = cpumask_weight(cpumask); + /* Return id to all */ + if (num_bits_set == nr_cpu_ids) + return 0xFF; + /* + * The cpus in the mask must all be on the apic cluster. If are not + * on the same apicid cluster return default value of target_cpus(): + */ + cpu = cpumask_first(cpumask); + apicid = es7000_cpu_to_logical_apicid(cpu); + + while (cpus_found < num_bits_set) { + if (cpumask_test_cpu(cpu, cpumask)) { + int new_apicid = es7000_cpu_to_logical_apicid(cpu); + + if (apicid_cluster(apicid) != + apicid_cluster(new_apicid)) { + printk ("%s: Not a valid mask!\n", __func__); + + return 0xFF; + } + apicid = new_apicid; + cpus_found++; + } + cpu++; + } + return apicid; +} + +static unsigned int es7000_cpu_mask_to_apicid(const cpumask_t *cpumask) +{ + int cpus_found = 0; + int num_bits_set; + int apicid; + int cpu; + + num_bits_set = cpus_weight(*cpumask); + /* Return id to all */ + if (num_bits_set == nr_cpu_ids) + return es7000_cpu_to_logical_apicid(0); + /* + * The cpus in the mask must all be on the apic cluster. If are not + * on the same apicid cluster return default value of target_cpus(): + */ + cpu = first_cpu(*cpumask); + apicid = es7000_cpu_to_logical_apicid(cpu); + while (cpus_found < num_bits_set) { + if (cpu_isset(cpu, *cpumask)) { + int new_apicid = es7000_cpu_to_logical_apicid(cpu); + + if (apicid_cluster(apicid) != + apicid_cluster(new_apicid)) { + printk ("%s: Not a valid mask!\n", __func__); + + return es7000_cpu_to_logical_apicid(0); + } + apicid = new_apicid; + cpus_found++; + } + cpu++; + } + return apicid; +} + +static unsigned int +es7000_cpu_mask_to_apicid_and(const struct cpumask *inmask, + const struct cpumask *andmask) +{ + int apicid = es7000_cpu_to_logical_apicid(0); + cpumask_var_t cpumask; + + if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC)) + return apicid; + + cpumask_and(cpumask, inmask, andmask); + cpumask_and(cpumask, cpumask, cpu_online_mask); + apicid = es7000_cpu_mask_to_apicid(cpumask); + + free_cpumask_var(cpumask); + + return apicid; +} + +static int es7000_phys_pkg_id(int cpuid_apic, int index_msb) +{ + return cpuid_apic >> index_msb; +} + void __init es7000_update_genapic_to_cluster(void) { apic->target_cpus = target_cpus_cluster; @@ -80,18 +367,6 @@ static int __init es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id) } #endif -static void es7000_vector_allocation_domain(int cpu, cpumask_t *retmask) -{ - /* Careful. Some cpus do not strictly honor the set of cpus - * specified in the interrupt destination when using lowest - * priority interrupt delivery mode. - * - * In particular there was a hyperthreading cpu observed to - * deliver interrupts to the wrong hyperthread when only one - * hyperthread was specified in the interrupt desitination. - */ - *retmask = (cpumask_t){ { [0] = APIC_ALL_CPUS, } }; -} struct genapic apic_es7000 = { @@ -140,10 +415,11 @@ struct genapic apic_es7000 = { .send_IPI_self = NULL, .wakeup_cpu = NULL, - .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, - .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, - .wait_for_init_deassert = default_wait_for_init_deassert, + .trampoline_phys_low = 0x467, + .trampoline_phys_high = 0x469, + + .wait_for_init_deassert = es7000_wait_for_init_deassert, /* Nothing to do for most platforms, since cleared by the INIT cycle: */ .smp_callin_clear_local_apic = NULL, -- GitLab From 0939e4fd351c58d08d25650797749f18904461af Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 17:16:25 +0100 Subject: [PATCH 0583/4982] x86, smp: eliminate asm/mach-default/mach_wakecpu.h Spread mach_wakecpu.h's definitions into apic.h and genapic.h and remove mach_wakecpu.h. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/apic.h | 15 +++++++++++ arch/x86/include/asm/genapic.h | 7 ++++++ .../include/asm/mach-default/mach_wakecpu.h | 25 ------------------- arch/x86/kernel/smpboot.c | 1 - arch/x86/mach-generic/bigsmp.c | 1 - arch/x86/mach-generic/default.c | 1 - arch/x86/mach-generic/es7000.c | 1 - arch/x86/mach-generic/summit.c | 1 - 8 files changed, 22 insertions(+), 30 deletions(-) delete mode 100644 arch/x86/include/asm/mach-default/mach_wakecpu.h diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index ab1d51a8855..e8f030440bc 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -41,6 +41,21 @@ extern unsigned int apic_verbosity; extern int local_apic_timer_c2_ok; extern int disable_apic; + +#ifdef CONFIG_SMP +extern void __inquire_remote_apic(int apicid); +#else /* CONFIG_SMP */ +static inline void __inquire_remote_apic(int apicid) +{ +} +#endif /* CONFIG_SMP */ + +static inline void default_inquire_remote_apic(int apicid) +{ + if (apic_verbosity >= APIC_DEBUG) + __inquire_remote_apic(apicid); +} + /* * Basic functions accessing APICs. */ diff --git a/arch/x86/include/asm/genapic.h b/arch/x86/include/asm/genapic.h index e5f9c5696fb..1772dad01b1 100644 --- a/arch/x86/include/asm/genapic.h +++ b/arch/x86/include/asm/genapic.h @@ -113,4 +113,11 @@ extern int default_cpu_present_to_apicid(int mps_cpu); extern int default_check_phys_apicid_present(int boot_cpu_physical_apicid); #endif +static inline void default_wait_for_init_deassert(atomic_t *deassert) +{ + while (!atomic_read(deassert)) + cpu_relax(); + return; +} + #endif /* _ASM_X86_GENAPIC_64_H */ diff --git a/arch/x86/include/asm/mach-default/mach_wakecpu.h b/arch/x86/include/asm/mach-default/mach_wakecpu.h deleted file mode 100644 index b1cde560e4c..00000000000 --- a/arch/x86/include/asm/mach-default/mach_wakecpu.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _ASM_X86_MACH_DEFAULT_MACH_WAKECPU_H -#define _ASM_X86_MACH_DEFAULT_MACH_WAKECPU_H - -static inline void default_wait_for_init_deassert(atomic_t *deassert) -{ - while (!atomic_read(deassert)) - cpu_relax(); - return; -} - -#ifdef CONFIG_SMP -extern void __inquire_remote_apic(int apicid); -#else /* CONFIG_SMP */ -static inline void __inquire_remote_apic(int apicid) -{ -} -#endif /* CONFIG_SMP */ - -static inline void default_inquire_remote_apic(int apicid) -{ - if (apic_verbosity >= APIC_DEBUG) - __inquire_remote_apic(apicid); -} - -#endif /* _ASM_X86_MACH_DEFAULT_MACH_WAKECPU_H */ diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 170adc5b6cb..1fdc1a7e7b5 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -66,7 +66,6 @@ #include #include -#include #include #ifdef CONFIG_X86_32 diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 4d8b2d442ba..6fcccfb5918 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -17,7 +17,6 @@ #include #include #include -#include static int dmi_bigsmp; /* can be set by dmi scanners */ diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index c12dd2300a5..e3c5114fd91 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -16,7 +16,6 @@ #include #include #include -#include static void default_vector_allocation_domain(int cpu, struct cpumask *retmask) { diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 8b6113ec380..bb11166b7c3 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c @@ -14,7 +14,6 @@ #include #include #include -#include #define APIC_DFR_VALUE_CLUSTER (APIC_DFR_CLUSTER) #define INT_DELIVERY_MODE_CLUSTER (dest_LowestPrio) diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index d5db3045437..673a64f8b46 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c @@ -16,7 +16,6 @@ #include #include #include -#include static int probe_summit(void) { -- GitLab From fb5b33c9f62ca9222c11841d61ddb7dc1a6552e9 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 17:29:27 +0100 Subject: [PATCH 0584/4982] x86: eliminate asm/mach-*/mach_mpparse.h Move the definition to mpparse.h. Signed-off-by: Ingo Molnar --- .../x86/include/asm/mach-default/mach_mpparse.h | 17 ----------------- .../x86/include/asm/mach-generic/mach_mpparse.h | 8 -------- arch/x86/include/asm/mpspec.h | 4 ++++ arch/x86/kernel/acpi/boot.c | 1 - arch/x86/kernel/es7000_32.c | 1 - arch/x86/kernel/mpparse.c | 1 - arch/x86/mach-generic/bigsmp.c | 1 - arch/x86/mach-generic/default.c | 1 - 8 files changed, 4 insertions(+), 30 deletions(-) delete mode 100644 arch/x86/include/asm/mach-default/mach_mpparse.h delete mode 100644 arch/x86/include/asm/mach-generic/mach_mpparse.h diff --git a/arch/x86/include/asm/mach-default/mach_mpparse.h b/arch/x86/include/asm/mach-default/mach_mpparse.h deleted file mode 100644 index af0da140df9..00000000000 --- a/arch/x86/include/asm/mach-default/mach_mpparse.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _ASM_X86_MACH_DEFAULT_MACH_MPPARSE_H -#define _ASM_X86_MACH_DEFAULT_MACH_MPPARSE_H - -static inline int -generic_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) -{ - return 0; -} - -/* Hook from generic ACPI tables.c */ -static inline int default_acpi_madt_oem_check(char *oem_id, char *oem_table_id) -{ - return 0; -} - - -#endif /* _ASM_X86_MACH_DEFAULT_MACH_MPPARSE_H */ diff --git a/arch/x86/include/asm/mach-generic/mach_mpparse.h b/arch/x86/include/asm/mach-generic/mach_mpparse.h deleted file mode 100644 index 22bfb56f8fb..00000000000 --- a/arch/x86/include/asm/mach-generic/mach_mpparse.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _ASM_X86_MACH_GENERIC_MACH_MPPARSE_H -#define _ASM_X86_MACH_GENERIC_MACH_MPPARSE_H - -extern int generic_mps_oem_check(struct mpc_table *, char *, char *); - -extern int default_acpi_madt_oem_check(char *, char *); - -#endif /* _ASM_X86_MACH_GENERIC_MACH_MPPARSE_H */ diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h index 62d14ce3cd0..432e9cbc607 100644 --- a/arch/x86/include/asm/mpspec.h +++ b/arch/x86/include/asm/mpspec.h @@ -142,4 +142,8 @@ static inline void physid_set_mask_of_physid(int physid, physid_mask_t *map) extern physid_mask_t phys_cpu_present_map; +extern int generic_mps_oem_check(struct mpc_table *, char *, char *); + +extern int default_acpi_madt_oem_check(char *, char *); + #endif /* _ASM_X86_MPSPEC_H */ diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 539163161a4..7b02a1cedca 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -63,7 +63,6 @@ EXPORT_SYMBOL(acpi_disabled); #ifdef CONFIG_X86_LOCAL_APIC #include -#include #endif /* CONFIG_X86_LOCAL_APIC */ #endif /* X86 */ diff --git a/arch/x86/kernel/es7000_32.c b/arch/x86/kernel/es7000_32.c index d7f433ee602..8faea13c8fa 100644 --- a/arch/x86/kernel/es7000_32.c +++ b/arch/x86/kernel/es7000_32.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index b12fa5ce6f5..c6930162b3b 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -32,7 +32,6 @@ #include #ifdef CONFIG_X86_32 #include -#include #endif /* diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 6fcccfb5918..626f45ca4e7 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c @@ -16,7 +16,6 @@ #include #include #include -#include static int dmi_bigsmp; /* can be set by dmi scanners */ diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index e3c5114fd91..6485e57e29b 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -15,7 +15,6 @@ #include #include #include -#include static void default_vector_allocation_domain(int cpu, struct cpumask *retmask) { -- GitLab From b2af018ff26f1a2a026f548f7f0e552589905689 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 17:36:56 +0100 Subject: [PATCH 0585/4982] x86: remove mach_mpspec.h Move its definitions into mpspec.h. Signed-off-by: Ingo Molnar --- .../include/asm/mach-default/mach_mpspec.h | 12 --------- .../include/asm/mach-generic/mach_mpspec.h | 12 --------- arch/x86/include/asm/mpspec.h | 25 ++++++++++++++----- 3 files changed, 19 insertions(+), 30 deletions(-) delete mode 100644 arch/x86/include/asm/mach-default/mach_mpspec.h delete mode 100644 arch/x86/include/asm/mach-generic/mach_mpspec.h diff --git a/arch/x86/include/asm/mach-default/mach_mpspec.h b/arch/x86/include/asm/mach-default/mach_mpspec.h deleted file mode 100644 index e85ede686be..00000000000 --- a/arch/x86/include/asm/mach-default/mach_mpspec.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _ASM_X86_MACH_DEFAULT_MACH_MPSPEC_H -#define _ASM_X86_MACH_DEFAULT_MACH_MPSPEC_H - -#define MAX_IRQ_SOURCES 256 - -#if CONFIG_BASE_SMALL == 0 -#define MAX_MP_BUSSES 256 -#else -#define MAX_MP_BUSSES 32 -#endif - -#endif /* _ASM_X86_MACH_DEFAULT_MACH_MPSPEC_H */ diff --git a/arch/x86/include/asm/mach-generic/mach_mpspec.h b/arch/x86/include/asm/mach-generic/mach_mpspec.h deleted file mode 100644 index 3bc40722657..00000000000 --- a/arch/x86/include/asm/mach-generic/mach_mpspec.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _ASM_X86_MACH_GENERIC_MACH_MPSPEC_H -#define _ASM_X86_MACH_GENERIC_MACH_MPSPEC_H - -#define MAX_IRQ_SOURCES 256 - -/* Summit or generic (i.e. installer) kernels need lots of bus entries. */ -/* Maximum 256 PCI busses, plus 1 ISA bus in each of 4 cabinets. */ -#define MAX_MP_BUSSES 260 - -extern void numaq_mps_oem_check(struct mpc_table *, char *, char *); - -#endif /* _ASM_X86_MACH_GENERIC_MACH_MPSPEC_H */ diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h index 432e9cbc607..03fb0d39654 100644 --- a/arch/x86/include/asm/mpspec.h +++ b/arch/x86/include/asm/mpspec.h @@ -9,7 +9,18 @@ extern int apic_version[MAX_APICS]; extern int pic_mode; #ifdef CONFIG_X86_32 -#include + +/* + * Summit or generic (i.e. installer) kernels need lots of bus entries. + * Maximum 256 PCI busses, plus 1 ISA bus in each of 4 cabinets. + */ +#if CONFIG_BASE_SMALL == 0 +# define MAX_MP_BUSSES 260 +#else +# define MAX_MP_BUSSES 32 +#endif + +#define MAX_IRQ_SOURCES 256 extern unsigned int def_to_bigsmp; extern u8 apicid_2_node[]; @@ -20,15 +31,15 @@ extern int mp_bus_id_to_local[MAX_MP_BUSSES]; extern int quad_local_to_mp_bus_id [NR_CPUS/4][4]; #endif -#define MAX_APICID 256 +#define MAX_APICID 256 -#else +#else /* CONFIG_X86_64: */ -#define MAX_MP_BUSSES 256 +#define MAX_MP_BUSSES 256 /* Each PCI slot may be a combo card with its own bus. 4 IRQ pins per slot. */ -#define MAX_IRQ_SOURCES (MAX_MP_BUSSES * 4) +#define MAX_IRQ_SOURCES (MAX_MP_BUSSES * 4) -#endif +#endif /* CONFIG_X86_64 */ extern void early_find_smp_config(void); extern void early_get_smp_config(void); @@ -146,4 +157,6 @@ extern int generic_mps_oem_check(struct mpc_table *, char *, char *); extern int default_acpi_madt_oem_check(char *, char *); +extern void numaq_mps_oem_check(struct mpc_table *, char *, char *); + #endif /* _ASM_X86_MPSPEC_H */ -- GitLab From 1f75ed0c1311a50ed393bcac258de65680d360e5 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 17:36:56 +0100 Subject: [PATCH 0586/4982] x86: remove mach_apicdef.h Move its definitions into apic.h. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/apic.h | 16 ++++++++++++++ arch/x86/include/asm/mach-default/mach_apic.h | 1 - .../include/asm/mach-default/mach_apicdef.h | 22 ------------------- .../include/asm/mach-generic/mach_apicdef.h | 8 ------- arch/x86/include/asm/smp.h | 4 ++-- arch/x86/kernel/apic.c | 1 - arch/x86/kernel/genapic_flat_64.c | 1 - arch/x86/kernel/io_apic.c | 1 - arch/x86/kernel/mpparse.c | 3 --- arch/x86/mach-generic/default.c | 1 - 10 files changed, 18 insertions(+), 40 deletions(-) delete mode 100644 arch/x86/include/asm/mach-default/mach_apicdef.h delete mode 100644 arch/x86/include/asm/mach-generic/mach_apicdef.h diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index e8f030440bc..3a3202074c6 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -211,4 +211,20 @@ static inline void disable_local_APIC(void) { } #endif /* !CONFIG_X86_LOCAL_APIC */ +#ifdef CONFIG_X86_64 +#define SET_APIC_ID(x) (apic->set_apic_id(x)) +#else + +static inline unsigned default_get_apic_id(unsigned long x) +{ + unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR)); + + if (APIC_XAPIC(ver)) + return (x >> 24) & 0xFF; + else + return (x >> 24) & 0x0F; +} + +#endif + #endif /* _ASM_X86_APIC_H */ diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index 2e4104cf348..b60b767d5be 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -3,7 +3,6 @@ #ifdef CONFIG_X86_LOCAL_APIC -#include #include #define APIC_DFR_VALUE (APIC_DFR_FLAT) diff --git a/arch/x86/include/asm/mach-default/mach_apicdef.h b/arch/x86/include/asm/mach-default/mach_apicdef.h deleted file mode 100644 index 5141085962d..00000000000 --- a/arch/x86/include/asm/mach-default/mach_apicdef.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _ASM_X86_MACH_DEFAULT_MACH_APICDEF_H -#define _ASM_X86_MACH_DEFAULT_MACH_APICDEF_H - -#include - -#ifdef CONFIG_X86_64 -#define SET_APIC_ID(x) (apic->set_apic_id(x)) -#else - -static inline unsigned default_get_apic_id(unsigned long x) -{ - unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR)); - - if (APIC_XAPIC(ver)) - return (x >> 24) & 0xFF; - else - return (x >> 24) & 0x0F; -} - -#endif - -#endif /* _ASM_X86_MACH_DEFAULT_MACH_APICDEF_H */ diff --git a/arch/x86/include/asm/mach-generic/mach_apicdef.h b/arch/x86/include/asm/mach-generic/mach_apicdef.h deleted file mode 100644 index 61caa65b13f..00000000000 --- a/arch/x86/include/asm/mach-generic/mach_apicdef.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _ASM_X86_MACH_GENERIC_MACH_APICDEF_H -#define _ASM_X86_MACH_GENERIC_MACH_APICDEF_H - -#ifndef APIC_DEFINITION -#include -#endif - -#endif /* _ASM_X86_MACH_GENERIC_MACH_APICDEF_H */ diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index c63d480802a..d4ac4de4bce 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -173,6 +173,8 @@ extern int safe_smp_processor_id(void); #endif +#include + #ifdef CONFIG_X86_LOCAL_APIC #ifndef CONFIG_X86_64 @@ -182,7 +184,6 @@ static inline int logical_smp_processor_id(void) return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR)); } -#include static inline unsigned int read_apic_id(void) { unsigned int reg; @@ -197,7 +198,6 @@ static inline unsigned int read_apic_id(void) # if defined(APIC_DEFINITION) || defined(CONFIG_X86_64) extern int hard_smp_processor_id(void); # else -#include static inline int hard_smp_processor_id(void) { /* we don't want to mark this access volatile - bad code generation */ diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 84b8e7c57ab..e6220809ca1 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -50,7 +50,6 @@ #include #include -#include #include /* diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index e9237f59928..19bffb3f732 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -19,7 +19,6 @@ #include #include #include -#include #ifdef CONFIG_ACPI #include diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index e90970ce21a..abae81989c2 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -64,7 +64,6 @@ #include #include -#include #define __apicdebuginit(type) static type __init diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index c6930162b3b..a1452a53d14 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -30,9 +30,6 @@ #include #include -#ifdef CONFIG_X86_32 -#include -#endif /* * Checksum an MP configuration block. diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index 6485e57e29b..07817b2a787 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include -- GitLab From 328386d7ab600aa0993a1226f5817ac30a735724 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 17:50:18 +0100 Subject: [PATCH 0587/4982] x86, smp: refactor ->wake_cpu - remove macro wrappers Signed-off-by: Ingo Molnar --- arch/x86/include/asm/mach-default/mach_apic.h | 2 -- arch/x86/include/asm/mach-generic/mach_apic.h | 2 -- arch/x86/kernel/setup.c | 5 ++--- arch/x86/kernel/smpboot.c | 4 ++-- 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h index b60b767d5be..bae053cdcde 100644 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ b/arch/x86/include/asm/mach-default/mach_apic.h @@ -19,10 +19,8 @@ static inline const struct cpumask *default_target_cpus(void) #ifdef CONFIG_X86_64 #include #define read_apic_id() (apic->get_apic_id(apic_read(APIC_ID))) -#define wakeup_secondary_cpu (apic->wakeup_cpu) extern void default_setup_apic_routing(void); #else -#define wakeup_secondary_cpu wakeup_secondary_cpu_via_init /* * Set up the logical destination ID. * diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h index ca460e45991..96f217f819e 100644 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ b/arch/x86/include/asm/mach-generic/mach_apic.h @@ -3,8 +3,6 @@ #include -#define wakeup_secondary_cpu (apic->wakeup_cpu) - extern void generic_bigsmp_probe(void); #endif /* _ASM_X86_MACH_GENERIC_MACH_APIC_H */ diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index a58e9f5e603..6b27f6dc7bf 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -589,9 +589,8 @@ early_param("elfcorehdr", setup_elfcorehdr); static int __init default_update_genapic(void) { #ifdef CONFIG_X86_SMP -# if defined(CONFIG_X86_GENERICARCH) || defined(CONFIG_X86_64) - apic->wakeup_cpu = wakeup_secondary_cpu_via_init; -# endif + if (!apic->wakeup_cpu) + apic->wakeup_cpu = wakeup_secondary_cpu_via_init; #endif return 0; diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 1fdc1a7e7b5..3fed177f345 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -750,7 +750,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu) /* * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad * (ie clustered apic addressing mode), this is a LOGICAL apic ID. - * Returns zero if CPU booted OK, else error code from wakeup_secondary_cpu. + * Returns zero if CPU booted OK, else error code from ->wakeup_cpu. */ { unsigned long boot_error = 0; @@ -841,7 +841,7 @@ do_rest: /* * Starting actual IPI sequence... */ - boot_error = wakeup_secondary_cpu(apicid, start_ip); + boot_error = apic->wakeup_cpu(apicid, start_ip); if (!boot_error) { /* -- GitLab From 5a44632f77a9c867621f7bf80c233eac75fea672 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 18:47:24 +0100 Subject: [PATCH 0588/4982] x86, numaq: consolidate code Move all the NUMAQ subarch definitions into numaq.c. With this it ceases to depend on build-time subarch features. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/numaq/apic.h | 122 ------------------- arch/x86/include/asm/numaq/apicdef.h | 9 -- arch/x86/include/asm/numaq/ipi.h | 22 ---- arch/x86/include/asm/numaq/mpparse.h | 6 - arch/x86/include/asm/numaq/wakecpu.h | 28 ----- arch/x86/mach-generic/numaq.c | 171 ++++++++++++++++++++++++++- arch/x86/pci/numaq_32.c | 2 +- 7 files changed, 167 insertions(+), 193 deletions(-) delete mode 100644 arch/x86/include/asm/numaq/apic.h delete mode 100644 arch/x86/include/asm/numaq/apicdef.h delete mode 100644 arch/x86/include/asm/numaq/ipi.h delete mode 100644 arch/x86/include/asm/numaq/mpparse.h delete mode 100644 arch/x86/include/asm/numaq/wakecpu.h diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h deleted file mode 100644 index ce95e79f723..00000000000 --- a/arch/x86/include/asm/numaq/apic.h +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef __ASM_NUMAQ_APIC_H -#define __ASM_NUMAQ_APIC_H - -#include -#include -#include - -#define APIC_DFR_VALUE (APIC_DFR_CLUSTER) - -static inline const cpumask_t *numaq_target_cpus(void) -{ - return &CPU_MASK_ALL; -} - -static inline unsigned long -numaq_check_apicid_used(physid_mask_t bitmap, int apicid) -{ - return physid_isset(apicid, bitmap); -} -static inline unsigned long numaq_check_apicid_present(int bit) -{ - return physid_isset(bit, phys_cpu_present_map); -} -#define apicid_cluster(apicid) (apicid & 0xF0) - -static inline int numaq_apic_id_registered(void) -{ - return 1; -} - -static inline void numaq_init_apic_ldr(void) -{ - /* Already done in NUMA-Q firmware */ -} - -static inline void numaq_setup_apic_routing(void) -{ - printk("Enabling APIC mode: %s. Using %d I/O APICs\n", - "NUMA-Q", nr_ioapics); -} - -/* - * Skip adding the timer int on secondary nodes, which causes - * a small but painful rift in the time-space continuum. - */ -static inline int numaq_multi_timer_check(int apic, int irq) -{ - return apic != 0 && irq == 0; -} - -static inline physid_mask_t numaq_ioapic_phys_id_map(physid_mask_t phys_map) -{ - /* We don't have a good way to do this yet - hack */ - return physids_promote(0xFUL); -} - -/* Mapping from cpu number to logical apicid */ -extern u8 cpu_2_logical_apicid[]; - -static inline int numaq_cpu_to_logical_apicid(int cpu) -{ - if (cpu >= nr_cpu_ids) - return BAD_APICID; - return (int)cpu_2_logical_apicid[cpu]; -} - -/* - * Supporting over 60 cpus on NUMA-Q requires a locality-dependent - * cpu to APIC ID relation to properly interact with the intelligent - * mode of the cluster controller. - */ -static inline int numaq_cpu_present_to_apicid(int mps_cpu) -{ - if (mps_cpu < 60) - return ((mps_cpu >> 2) << 4) | (1 << (mps_cpu & 0x3)); - else - return BAD_APICID; -} - -static inline int numaq_apicid_to_node(int logical_apicid) -{ - return logical_apicid >> 4; -} - -static inline physid_mask_t numaq_apicid_to_cpu_present(int logical_apicid) -{ - int node = numaq_apicid_to_node(logical_apicid); - int cpu = __ffs(logical_apicid & 0xf); - - return physid_mask_of_physid(cpu + 4*node); -} - -extern void *xquad_portio; - -static inline int numaq_check_phys_apicid_present(int boot_cpu_physical_apicid) -{ - return 1; -} - -/* - * We use physical apicids here, not logical, so just return the default - * physical broadcast to stop people from breaking us - */ -static inline unsigned int numaq_cpu_mask_to_apicid(const cpumask_t *cpumask) -{ - return 0x0F; -} - -static inline unsigned int -numaq_cpu_mask_to_apicid_and(const struct cpumask *cpumask, - const struct cpumask *andmask) -{ - return 0x0F; -} - -/* No NUMA-Q box has a HT CPU, but it can't hurt to use the default code. */ -static inline int numaq_phys_pkg_id(int cpuid_apic, int index_msb) -{ - return cpuid_apic >> index_msb; -} - -#endif /* __ASM_NUMAQ_APIC_H */ diff --git a/arch/x86/include/asm/numaq/apicdef.h b/arch/x86/include/asm/numaq/apicdef.h deleted file mode 100644 index cd927d5bd50..00000000000 --- a/arch/x86/include/asm/numaq/apicdef.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __ASM_NUMAQ_APICDEF_H -#define __ASM_NUMAQ_APICDEF_H - -static inline unsigned int numaq_get_apic_id(unsigned long x) -{ - return (x >> 24) & 0x0F; -} - -#endif diff --git a/arch/x86/include/asm/numaq/ipi.h b/arch/x86/include/asm/numaq/ipi.h deleted file mode 100644 index 5dbc4b4cd5e..00000000000 --- a/arch/x86/include/asm/numaq/ipi.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef __ASM_NUMAQ_IPI_H -#define __ASM_NUMAQ_IPI_H - -void default_send_IPI_mask_sequence(const struct cpumask *mask, int vector); -void default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector); - -static inline void numaq_send_IPI_mask(const struct cpumask *mask, int vector) -{ - default_send_IPI_mask_sequence(mask, vector); -} - -static inline void numaq_send_IPI_allbutself(int vector) -{ - default_send_IPI_mask_allbutself(cpu_online_mask, vector); -} - -static inline void numaq_send_IPI_all(int vector) -{ - numaq_send_IPI_mask(cpu_online_mask, vector); -} - -#endif /* __ASM_NUMAQ_IPI_H */ diff --git a/arch/x86/include/asm/numaq/mpparse.h b/arch/x86/include/asm/numaq/mpparse.h deleted file mode 100644 index a2eeefcd1cc..00000000000 --- a/arch/x86/include/asm/numaq/mpparse.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_NUMAQ_MPPARSE_H -#define __ASM_NUMAQ_MPPARSE_H - -extern void numaq_mps_oem_check(struct mpc_table *, char *, char *); - -#endif /* __ASM_NUMAQ_MPPARSE_H */ diff --git a/arch/x86/include/asm/numaq/wakecpu.h b/arch/x86/include/asm/numaq/wakecpu.h deleted file mode 100644 index afe81439c7d..00000000000 --- a/arch/x86/include/asm/numaq/wakecpu.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __ASM_NUMAQ_WAKECPU_H -#define __ASM_NUMAQ_WAKECPU_H - -/* This file copes with machines that wakeup secondary CPUs by NMIs */ - -#define NUMAQ_TRAMPOLINE_PHYS_LOW (0x8) -#define NUMAQ_TRAMPOLINE_PHYS_HIGH (0xa) - -/* - * Because we use NMIs rather than the INIT-STARTUP sequence to - * bootstrap the CPUs, the APIC may be in a weird state. Kick it: - */ -static inline void numaq_smp_callin_clear_local_apic(void) -{ - clear_local_APIC(); -} - -static inline void -numaq_store_NMI_vector(unsigned short *high, unsigned short *low) -{ - printk("Storing NMI vector\n"); - *high = - *((volatile unsigned short *)phys_to_virt(NUMAQ_TRAMPOLINE_PHYS_HIGH)); - *low = - *((volatile unsigned short *)phys_to_virt(NUMAQ_TRAMPOLINE_PHYS_LOW)); -} - -#endif /* __ASM_NUMAQ_WAKECPU_H */ diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c index ddb50fba286..c221cfb2c2d 100644 --- a/arch/x86/mach-generic/numaq.c +++ b/arch/x86/mach-generic/numaq.c @@ -11,14 +11,175 @@ #include #include #include -#include +#include #include -#include -#include -#include -#include #include +#include +#include +#include +#define NUMAQ_APIC_DFR_VALUE (APIC_DFR_CLUSTER) + +static inline unsigned int numaq_get_apic_id(unsigned long x) +{ + return (x >> 24) & 0x0F; +} + +void default_send_IPI_mask_sequence(const struct cpumask *mask, int vector); +void default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector); + +static inline void numaq_send_IPI_mask(const struct cpumask *mask, int vector) +{ + default_send_IPI_mask_sequence(mask, vector); +} + +static inline void numaq_send_IPI_allbutself(int vector) +{ + default_send_IPI_mask_allbutself(cpu_online_mask, vector); +} + +static inline void numaq_send_IPI_all(int vector) +{ + numaq_send_IPI_mask(cpu_online_mask, vector); +} + +extern void numaq_mps_oem_check(struct mpc_table *, char *, char *); + +#define NUMAQ_TRAMPOLINE_PHYS_LOW (0x8) +#define NUMAQ_TRAMPOLINE_PHYS_HIGH (0xa) + +/* + * Because we use NMIs rather than the INIT-STARTUP sequence to + * bootstrap the CPUs, the APIC may be in a weird state. Kick it: + */ +static inline void numaq_smp_callin_clear_local_apic(void) +{ + clear_local_APIC(); +} + +static inline void +numaq_store_NMI_vector(unsigned short *high, unsigned short *low) +{ + printk("Storing NMI vector\n"); + *high = + *((volatile unsigned short *)phys_to_virt(NUMAQ_TRAMPOLINE_PHYS_HIGH)); + *low = + *((volatile unsigned short *)phys_to_virt(NUMAQ_TRAMPOLINE_PHYS_LOW)); +} + +static inline const cpumask_t *numaq_target_cpus(void) +{ + return &CPU_MASK_ALL; +} + +static inline unsigned long +numaq_check_apicid_used(physid_mask_t bitmap, int apicid) +{ + return physid_isset(apicid, bitmap); +} + +static inline unsigned long numaq_check_apicid_present(int bit) +{ + return physid_isset(bit, phys_cpu_present_map); +} + +#define apicid_cluster(apicid) (apicid & 0xF0) + +static inline int numaq_apic_id_registered(void) +{ + return 1; +} + +static inline void numaq_init_apic_ldr(void) +{ + /* Already done in NUMA-Q firmware */ +} + +static inline void numaq_setup_apic_routing(void) +{ + printk("Enabling APIC mode: %s. Using %d I/O APICs\n", + "NUMA-Q", nr_ioapics); +} + +/* + * Skip adding the timer int on secondary nodes, which causes + * a small but painful rift in the time-space continuum. + */ +static inline int numaq_multi_timer_check(int apic, int irq) +{ + return apic != 0 && irq == 0; +} + +static inline physid_mask_t numaq_ioapic_phys_id_map(physid_mask_t phys_map) +{ + /* We don't have a good way to do this yet - hack */ + return physids_promote(0xFUL); +} + +/* Mapping from cpu number to logical apicid */ +extern u8 cpu_2_logical_apicid[]; + +static inline int numaq_cpu_to_logical_apicid(int cpu) +{ + if (cpu >= nr_cpu_ids) + return BAD_APICID; + return (int)cpu_2_logical_apicid[cpu]; +} + +/* + * Supporting over 60 cpus on NUMA-Q requires a locality-dependent + * cpu to APIC ID relation to properly interact with the intelligent + * mode of the cluster controller. + */ +static inline int numaq_cpu_present_to_apicid(int mps_cpu) +{ + if (mps_cpu < 60) + return ((mps_cpu >> 2) << 4) | (1 << (mps_cpu & 0x3)); + else + return BAD_APICID; +} + +static inline int numaq_apicid_to_node(int logical_apicid) +{ + return logical_apicid >> 4; +} + +static inline physid_mask_t numaq_apicid_to_cpu_present(int logical_apicid) +{ + int node = numaq_apicid_to_node(logical_apicid); + int cpu = __ffs(logical_apicid & 0xf); + + return physid_mask_of_physid(cpu + 4*node); +} + +extern void *xquad_portio; + +static inline int numaq_check_phys_apicid_present(int boot_cpu_physical_apicid) +{ + return 1; +} + +/* + * We use physical apicids here, not logical, so just return the default + * physical broadcast to stop people from breaking us + */ +static inline unsigned int numaq_cpu_mask_to_apicid(const cpumask_t *cpumask) +{ + return 0x0F; +} + +static inline unsigned int +numaq_cpu_mask_to_apicid_and(const struct cpumask *cpumask, + const struct cpumask *andmask) +{ + return 0x0F; +} + +/* No NUMA-Q box has a HT CPU, but it can't hurt to use the default code. */ +static inline int numaq_phys_pkg_id(int cpuid_apic, int index_msb) +{ + return cpuid_apic >> index_msb; +} static int __numaq_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) { numaq_mps_oem_check(mpc, oem, productid); diff --git a/arch/x86/pci/numaq_32.c b/arch/x86/pci/numaq_32.c index 2089354968a..1b2d773612e 100644 --- a/arch/x86/pci/numaq_32.c +++ b/arch/x86/pci/numaq_32.c @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include -- GitLab From b11b867f78910192fc54bd0d09148cf768c7aaad Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 18:49:31 +0100 Subject: [PATCH 0589/4982] x86, summit: consolidate code Consolidate all the Summit code into a single file: arch/x86/kernel/summit_32.c. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/summit/apic.h | 195 ------------ arch/x86/include/asm/summit/apicdef.h | 9 - arch/x86/include/asm/summit/ipi.h | 26 -- arch/x86/include/asm/summit/mpparse.h | 109 ------- arch/x86/kernel/summit_32.c | 417 +++++++++++++++++++++++++- arch/x86/mach-generic/Makefile | 1 - arch/x86/mach-generic/summit.c | 94 ------ 7 files changed, 416 insertions(+), 435 deletions(-) delete mode 100644 arch/x86/include/asm/summit/apic.h delete mode 100644 arch/x86/include/asm/summit/apicdef.h delete mode 100644 arch/x86/include/asm/summit/ipi.h delete mode 100644 arch/x86/include/asm/summit/mpparse.h delete mode 100644 arch/x86/mach-generic/summit.c diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h deleted file mode 100644 index 15b8dbd19e1..00000000000 --- a/arch/x86/include/asm/summit/apic.h +++ /dev/null @@ -1,195 +0,0 @@ -#ifndef __ASM_SUMMIT_APIC_H -#define __ASM_SUMMIT_APIC_H - -#include -#include - -/* In clustered mode, the high nibble of APIC ID is a cluster number. - * The low nibble is a 4-bit bitmap. */ -#define XAPIC_DEST_CPUS_SHIFT 4 -#define XAPIC_DEST_CPUS_MASK ((1u << XAPIC_DEST_CPUS_SHIFT) - 1) -#define XAPIC_DEST_CLUSTER_MASK (XAPIC_DEST_CPUS_MASK << XAPIC_DEST_CPUS_SHIFT) - -#define APIC_DFR_VALUE (APIC_DFR_CLUSTER) - -static inline const cpumask_t *summit_target_cpus(void) -{ - /* CPU_MASK_ALL (0xff) has undefined behaviour with - * dest_LowestPrio mode logical clustered apic interrupt routing - * Just start on cpu 0. IRQ balancing will spread load - */ - return &cpumask_of_cpu(0); -} - -static inline unsigned long -summit_check_apicid_used(physid_mask_t bitmap, int apicid) -{ - return 0; -} - -/* we don't use the phys_cpu_present_map to indicate apicid presence */ -static inline unsigned long summit_check_apicid_present(int bit) -{ - return 1; -} - -#define apicid_cluster(apicid) ((apicid) & XAPIC_DEST_CLUSTER_MASK) - -extern u8 cpu_2_logical_apicid[]; - -static inline void summit_init_apic_ldr(void) -{ - unsigned long val, id; - int count = 0; - u8 my_id = (u8)hard_smp_processor_id(); - u8 my_cluster = (u8)apicid_cluster(my_id); -#ifdef CONFIG_SMP - u8 lid; - int i; - - /* Create logical APIC IDs by counting CPUs already in cluster. */ - for (count = 0, i = nr_cpu_ids; --i >= 0; ) { - lid = cpu_2_logical_apicid[i]; - if (lid != BAD_APICID && apicid_cluster(lid) == my_cluster) - ++count; - } -#endif - /* We only have a 4 wide bitmap in cluster mode. If a deranged - * BIOS puts 5 CPUs in one APIC cluster, we're hosed. */ - BUG_ON(count >= XAPIC_DEST_CPUS_SHIFT); - id = my_cluster | (1UL << count); - apic_write(APIC_DFR, APIC_DFR_VALUE); - val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; - val |= SET_APIC_LOGICAL_ID(id); - apic_write(APIC_LDR, val); -} - -static inline int summit_apic_id_registered(void) -{ - return 1; -} - -static inline void summit_setup_apic_routing(void) -{ - printk("Enabling APIC mode: Summit. Using %d I/O APICs\n", - nr_ioapics); -} - -static inline int summit_apicid_to_node(int logical_apicid) -{ -#ifdef CONFIG_SMP - return apicid_2_node[hard_smp_processor_id()]; -#else - return 0; -#endif -} - -/* Mapping from cpu number to logical apicid */ -static inline int summit_cpu_to_logical_apicid(int cpu) -{ -#ifdef CONFIG_SMP - if (cpu >= nr_cpu_ids) - return BAD_APICID; - return (int)cpu_2_logical_apicid[cpu]; -#else - return logical_smp_processor_id(); -#endif -} - -static inline int summit_cpu_present_to_apicid(int mps_cpu) -{ - if (mps_cpu < nr_cpu_ids) - return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu); - else - return BAD_APICID; -} - -static inline physid_mask_t -summit_ioapic_phys_id_map(physid_mask_t phys_id_map) -{ - /* For clustered we don't have a good way to do this yet - hack */ - return physids_promote(0x0F); -} - -static inline physid_mask_t summit_apicid_to_cpu_present(int apicid) -{ - return physid_mask_of_physid(0); -} - -static inline void summit_setup_portio_remap(void) -{ -} - -static inline int summit_check_phys_apicid_present(int boot_cpu_physical_apicid) -{ - return 1; -} - -static inline unsigned int summit_cpu_mask_to_apicid(const cpumask_t *cpumask) -{ - int cpus_found = 0; - int num_bits_set; - int apicid; - int cpu; - - num_bits_set = cpus_weight(*cpumask); - /* Return id to all */ - if (num_bits_set >= nr_cpu_ids) - return 0xFF; - /* - * The cpus in the mask must all be on the apic cluster. If are not - * on the same apicid cluster return default value of target_cpus(): - */ - cpu = first_cpu(*cpumask); - apicid = summit_cpu_to_logical_apicid(cpu); - - while (cpus_found < num_bits_set) { - if (cpu_isset(cpu, *cpumask)) { - int new_apicid = summit_cpu_to_logical_apicid(cpu); - - if (apicid_cluster(apicid) != - apicid_cluster(new_apicid)) { - printk ("%s: Not a valid mask!\n", __func__); - - return 0xFF; - } - apicid = apicid | new_apicid; - cpus_found++; - } - cpu++; - } - return apicid; -} - -static inline unsigned int -summit_cpu_mask_to_apicid_and(const struct cpumask *inmask, - const struct cpumask *andmask) -{ - int apicid = summit_cpu_to_logical_apicid(0); - cpumask_var_t cpumask; - - if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC)) - return apicid; - - cpumask_and(cpumask, inmask, andmask); - cpumask_and(cpumask, cpumask, cpu_online_mask); - apicid = summit_cpu_mask_to_apicid(cpumask); - - free_cpumask_var(cpumask); - - return apicid; -} - -/* - * cpuid returns the value latched in the HW at reset, not the APIC ID - * register's value. For any box whose BIOS changes APIC IDs, like - * clustered APIC systems, we must use hard_smp_processor_id. - * - * See Intel's IA-32 SW Dev's Manual Vol2 under CPUID. - */ -static inline int summit_phys_pkg_id(int cpuid_apic, int index_msb) -{ - return hard_smp_processor_id() >> index_msb; -} - -#endif /* __ASM_SUMMIT_APIC_H */ diff --git a/arch/x86/include/asm/summit/apicdef.h b/arch/x86/include/asm/summit/apicdef.h deleted file mode 100644 index c24b0df2dec..00000000000 --- a/arch/x86/include/asm/summit/apicdef.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __ASM_SUMMIT_APICDEF_H -#define __ASM_SUMMIT_APICDEF_H - -static inline unsigned summit_get_apic_id(unsigned long x) -{ - return (x >> 24) & 0xFF; -} - -#endif diff --git a/arch/x86/include/asm/summit/ipi.h b/arch/x86/include/asm/summit/ipi.h deleted file mode 100644 index f87a43fe0ae..00000000000 --- a/arch/x86/include/asm/summit/ipi.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef __ASM_SUMMIT_IPI_H -#define __ASM_SUMMIT_IPI_H - -void default_send_IPI_mask_sequence(const cpumask_t *mask, int vector); -void default_send_IPI_mask_allbutself(const cpumask_t *mask, int vector); - -static inline void summit_send_IPI_mask(const cpumask_t *mask, int vector) -{ - default_send_IPI_mask_sequence(mask, vector); -} - -static inline void summit_send_IPI_allbutself(int vector) -{ - cpumask_t mask = cpu_online_map; - cpu_clear(smp_processor_id(), mask); - - if (!cpus_empty(mask)) - summit_send_IPI_mask(&mask, vector); -} - -static inline void summit_send_IPI_all(int vector) -{ - summit_send_IPI_mask(&cpu_online_map, vector); -} - -#endif /* __ASM_SUMMIT_IPI_H */ diff --git a/arch/x86/include/asm/summit/mpparse.h b/arch/x86/include/asm/summit/mpparse.h deleted file mode 100644 index 4bbcce39acb..00000000000 --- a/arch/x86/include/asm/summit/mpparse.h +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef __ASM_SUMMIT_MPPARSE_H -#define __ASM_SUMMIT_MPPARSE_H - -#include - -extern int use_cyclone; - -#ifdef CONFIG_X86_SUMMIT_NUMA -extern void setup_summit(void); -#else -#define setup_summit() {} -#endif - -static inline int -summit_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) -{ - if (!strncmp(oem, "IBM ENSW", 8) && - (!strncmp(productid, "VIGIL SMP", 9) - || !strncmp(productid, "EXA", 3) - || !strncmp(productid, "RUTHLESS SMP", 12))){ - mark_tsc_unstable("Summit based system"); - use_cyclone = 1; /*enable cyclone-timer*/ - setup_summit(); - return 1; - } - return 0; -} - -/* Hook from generic ACPI tables.c */ -static inline int summit_acpi_madt_oem_check(char *oem_id, char *oem_table_id) -{ - if (!strncmp(oem_id, "IBM", 3) && - (!strncmp(oem_table_id, "SERVIGIL", 8) - || !strncmp(oem_table_id, "EXA", 3))){ - mark_tsc_unstable("Summit based system"); - use_cyclone = 1; /*enable cyclone-timer*/ - setup_summit(); - return 1; - } - return 0; -} - -struct rio_table_hdr { - unsigned char version; /* Version number of this data structure */ - /* Version 3 adds chassis_num & WP_index */ - unsigned char num_scal_dev; /* # of Scalability devices (Twisters for Vigil) */ - unsigned char num_rio_dev; /* # of RIO I/O devices (Cyclones and Winnipegs) */ -} __attribute__((packed)); - -struct scal_detail { - unsigned char node_id; /* Scalability Node ID */ - unsigned long CBAR; /* Address of 1MB register space */ - unsigned char port0node; /* Node ID port connected to: 0xFF=None */ - unsigned char port0port; /* Port num port connected to: 0,1,2, or 0xFF=None */ - unsigned char port1node; /* Node ID port connected to: 0xFF = None */ - unsigned char port1port; /* Port num port connected to: 0,1,2, or 0xFF=None */ - unsigned char port2node; /* Node ID port connected to: 0xFF = None */ - unsigned char port2port; /* Port num port connected to: 0,1,2, or 0xFF=None */ - unsigned char chassis_num; /* 1 based Chassis number (1 = boot node) */ -} __attribute__((packed)); - -struct rio_detail { - unsigned char node_id; /* RIO Node ID */ - unsigned long BBAR; /* Address of 1MB register space */ - unsigned char type; /* Type of device */ - unsigned char owner_id; /* For WPEG: Node ID of Cyclone that owns this WPEG*/ - /* For CYC: Node ID of Twister that owns this CYC */ - unsigned char port0node; /* Node ID port connected to: 0xFF=None */ - unsigned char port0port; /* Port num port connected to: 0,1,2, or 0xFF=None */ - unsigned char port1node; /* Node ID port connected to: 0xFF=None */ - unsigned char port1port; /* Port num port connected to: 0,1,2, or 0xFF=None */ - unsigned char first_slot; /* For WPEG: Lowest slot number below this WPEG */ - /* For CYC: 0 */ - unsigned char status; /* For WPEG: Bit 0 = 1 : the XAPIC is used */ - /* = 0 : the XAPIC is not used, ie:*/ - /* ints fwded to another XAPIC */ - /* Bits1:7 Reserved */ - /* For CYC: Bits0:7 Reserved */ - unsigned char WP_index; /* For WPEG: WPEG instance index - lower ones have */ - /* lower slot numbers/PCI bus numbers */ - /* For CYC: No meaning */ - unsigned char chassis_num; /* 1 based Chassis number */ - /* For LookOut WPEGs this field indicates the */ - /* Expansion Chassis #, enumerated from Boot */ - /* Node WPEG external port, then Boot Node CYC */ - /* external port, then Next Vigil chassis WPEG */ - /* external port, etc. */ - /* Shared Lookouts have only 1 chassis number (the */ - /* first one assigned) */ -} __attribute__((packed)); - - -typedef enum { - CompatTwister = 0, /* Compatibility Twister */ - AltTwister = 1, /* Alternate Twister of internal 8-way */ - CompatCyclone = 2, /* Compatibility Cyclone */ - AltCyclone = 3, /* Alternate Cyclone of internal 8-way */ - CompatWPEG = 4, /* Compatibility WPEG */ - AltWPEG = 5, /* Second Planar WPEG */ - LookOutAWPEG = 6, /* LookOut WPEG */ - LookOutBWPEG = 7, /* LookOut WPEG */ -} node_type; - -static inline int is_WPEG(struct rio_detail *rio){ - return (rio->type == CompatWPEG || rio->type == AltWPEG || - rio->type == LookOutAWPEG || rio->type == LookOutBWPEG); -} - -#endif /* __ASM_SUMMIT_MPPARSE_H */ diff --git a/arch/x86/kernel/summit_32.c b/arch/x86/kernel/summit_32.c index 7b987852e87..3b60dd5e57f 100644 --- a/arch/x86/kernel/summit_32.c +++ b/arch/x86/kernel/summit_32.c @@ -30,7 +30,364 @@ #include #include #include -#include + +/* + * APIC driver for the IBM "Summit" chipset. + */ +#define APIC_DEFINITION 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static inline unsigned summit_get_apic_id(unsigned long x) +{ + return (x >> 24) & 0xFF; +} + +void default_send_IPI_mask_sequence(const cpumask_t *mask, int vector); +void default_send_IPI_mask_allbutself(const cpumask_t *mask, int vector); + +static inline void summit_send_IPI_mask(const cpumask_t *mask, int vector) +{ + default_send_IPI_mask_sequence(mask, vector); +} + +static inline void summit_send_IPI_allbutself(int vector) +{ + cpumask_t mask = cpu_online_map; + cpu_clear(smp_processor_id(), mask); + + if (!cpus_empty(mask)) + summit_send_IPI_mask(&mask, vector); +} + +static inline void summit_send_IPI_all(int vector) +{ + summit_send_IPI_mask(&cpu_online_map, vector); +} + +#include + +extern int use_cyclone; + +#ifdef CONFIG_X86_SUMMIT_NUMA +extern void setup_summit(void); +#else +#define setup_summit() {} +#endif + +static inline int +summit_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) +{ + if (!strncmp(oem, "IBM ENSW", 8) && + (!strncmp(productid, "VIGIL SMP", 9) + || !strncmp(productid, "EXA", 3) + || !strncmp(productid, "RUTHLESS SMP", 12))){ + mark_tsc_unstable("Summit based system"); + use_cyclone = 1; /*enable cyclone-timer*/ + setup_summit(); + return 1; + } + return 0; +} + +/* Hook from generic ACPI tables.c */ +static inline int summit_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + if (!strncmp(oem_id, "IBM", 3) && + (!strncmp(oem_table_id, "SERVIGIL", 8) + || !strncmp(oem_table_id, "EXA", 3))){ + mark_tsc_unstable("Summit based system"); + use_cyclone = 1; /*enable cyclone-timer*/ + setup_summit(); + return 1; + } + return 0; +} + +struct rio_table_hdr { + unsigned char version; /* Version number of this data structure */ + /* Version 3 adds chassis_num & WP_index */ + unsigned char num_scal_dev; /* # of Scalability devices (Twisters for Vigil) */ + unsigned char num_rio_dev; /* # of RIO I/O devices (Cyclones and Winnipegs) */ +} __attribute__((packed)); + +struct scal_detail { + unsigned char node_id; /* Scalability Node ID */ + unsigned long CBAR; /* Address of 1MB register space */ + unsigned char port0node; /* Node ID port connected to: 0xFF=None */ + unsigned char port0port; /* Port num port connected to: 0,1,2, or 0xFF=None */ + unsigned char port1node; /* Node ID port connected to: 0xFF = None */ + unsigned char port1port; /* Port num port connected to: 0,1,2, or 0xFF=None */ + unsigned char port2node; /* Node ID port connected to: 0xFF = None */ + unsigned char port2port; /* Port num port connected to: 0,1,2, or 0xFF=None */ + unsigned char chassis_num; /* 1 based Chassis number (1 = boot node) */ +} __attribute__((packed)); + +struct rio_detail { + unsigned char node_id; /* RIO Node ID */ + unsigned long BBAR; /* Address of 1MB register space */ + unsigned char type; /* Type of device */ + unsigned char owner_id; /* For WPEG: Node ID of Cyclone that owns this WPEG*/ + /* For CYC: Node ID of Twister that owns this CYC */ + unsigned char port0node; /* Node ID port connected to: 0xFF=None */ + unsigned char port0port; /* Port num port connected to: 0,1,2, or 0xFF=None */ + unsigned char port1node; /* Node ID port connected to: 0xFF=None */ + unsigned char port1port; /* Port num port connected to: 0,1,2, or 0xFF=None */ + unsigned char first_slot; /* For WPEG: Lowest slot number below this WPEG */ + /* For CYC: 0 */ + unsigned char status; /* For WPEG: Bit 0 = 1 : the XAPIC is used */ + /* = 0 : the XAPIC is not used, ie:*/ + /* ints fwded to another XAPIC */ + /* Bits1:7 Reserved */ + /* For CYC: Bits0:7 Reserved */ + unsigned char WP_index; /* For WPEG: WPEG instance index - lower ones have */ + /* lower slot numbers/PCI bus numbers */ + /* For CYC: No meaning */ + unsigned char chassis_num; /* 1 based Chassis number */ + /* For LookOut WPEGs this field indicates the */ + /* Expansion Chassis #, enumerated from Boot */ + /* Node WPEG external port, then Boot Node CYC */ + /* external port, then Next Vigil chassis WPEG */ + /* external port, etc. */ + /* Shared Lookouts have only 1 chassis number (the */ + /* first one assigned) */ +} __attribute__((packed)); + + +typedef enum { + CompatTwister = 0, /* Compatibility Twister */ + AltTwister = 1, /* Alternate Twister of internal 8-way */ + CompatCyclone = 2, /* Compatibility Cyclone */ + AltCyclone = 3, /* Alternate Cyclone of internal 8-way */ + CompatWPEG = 4, /* Compatibility WPEG */ + AltWPEG = 5, /* Second Planar WPEG */ + LookOutAWPEG = 6, /* LookOut WPEG */ + LookOutBWPEG = 7, /* LookOut WPEG */ +} node_type; + +static inline int is_WPEG(struct rio_detail *rio){ + return (rio->type == CompatWPEG || rio->type == AltWPEG || + rio->type == LookOutAWPEG || rio->type == LookOutBWPEG); +} + + +/* In clustered mode, the high nibble of APIC ID is a cluster number. + * The low nibble is a 4-bit bitmap. */ +#define XAPIC_DEST_CPUS_SHIFT 4 +#define XAPIC_DEST_CPUS_MASK ((1u << XAPIC_DEST_CPUS_SHIFT) - 1) +#define XAPIC_DEST_CLUSTER_MASK (XAPIC_DEST_CPUS_MASK << XAPIC_DEST_CPUS_SHIFT) + +#define SUMMIT_APIC_DFR_VALUE (APIC_DFR_CLUSTER) + +static inline const cpumask_t *summit_target_cpus(void) +{ + /* CPU_MASK_ALL (0xff) has undefined behaviour with + * dest_LowestPrio mode logical clustered apic interrupt routing + * Just start on cpu 0. IRQ balancing will spread load + */ + return &cpumask_of_cpu(0); +} + +static inline unsigned long +summit_check_apicid_used(physid_mask_t bitmap, int apicid) +{ + return 0; +} + +/* we don't use the phys_cpu_present_map to indicate apicid presence */ +static inline unsigned long summit_check_apicid_present(int bit) +{ + return 1; +} + +#define apicid_cluster(apicid) ((apicid) & XAPIC_DEST_CLUSTER_MASK) + +extern u8 cpu_2_logical_apicid[]; + +static inline void summit_init_apic_ldr(void) +{ + unsigned long val, id; + int count = 0; + u8 my_id = (u8)hard_smp_processor_id(); + u8 my_cluster = (u8)apicid_cluster(my_id); +#ifdef CONFIG_SMP + u8 lid; + int i; + + /* Create logical APIC IDs by counting CPUs already in cluster. */ + for (count = 0, i = nr_cpu_ids; --i >= 0; ) { + lid = cpu_2_logical_apicid[i]; + if (lid != BAD_APICID && apicid_cluster(lid) == my_cluster) + ++count; + } +#endif + /* We only have a 4 wide bitmap in cluster mode. If a deranged + * BIOS puts 5 CPUs in one APIC cluster, we're hosed. */ + BUG_ON(count >= XAPIC_DEST_CPUS_SHIFT); + id = my_cluster | (1UL << count); + apic_write(APIC_DFR, SUMMIT_APIC_DFR_VALUE); + val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; + val |= SET_APIC_LOGICAL_ID(id); + apic_write(APIC_LDR, val); +} + +static inline int summit_apic_id_registered(void) +{ + return 1; +} + +static inline void summit_setup_apic_routing(void) +{ + printk("Enabling APIC mode: Summit. Using %d I/O APICs\n", + nr_ioapics); +} + +static inline int summit_apicid_to_node(int logical_apicid) +{ +#ifdef CONFIG_SMP + return apicid_2_node[hard_smp_processor_id()]; +#else + return 0; +#endif +} + +/* Mapping from cpu number to logical apicid */ +static inline int summit_cpu_to_logical_apicid(int cpu) +{ +#ifdef CONFIG_SMP + if (cpu >= nr_cpu_ids) + return BAD_APICID; + return (int)cpu_2_logical_apicid[cpu]; +#else + return logical_smp_processor_id(); +#endif +} + +static inline int summit_cpu_present_to_apicid(int mps_cpu) +{ + if (mps_cpu < nr_cpu_ids) + return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu); + else + return BAD_APICID; +} + +static inline physid_mask_t +summit_ioapic_phys_id_map(physid_mask_t phys_id_map) +{ + /* For clustered we don't have a good way to do this yet - hack */ + return physids_promote(0x0F); +} + +static inline physid_mask_t summit_apicid_to_cpu_present(int apicid) +{ + return physid_mask_of_physid(0); +} + +static inline void summit_setup_portio_remap(void) +{ +} + +static inline int summit_check_phys_apicid_present(int boot_cpu_physical_apicid) +{ + return 1; +} + +static inline unsigned int summit_cpu_mask_to_apicid(const cpumask_t *cpumask) +{ + int cpus_found = 0; + int num_bits_set; + int apicid; + int cpu; + + num_bits_set = cpus_weight(*cpumask); + /* Return id to all */ + if (num_bits_set >= nr_cpu_ids) + return 0xFF; + /* + * The cpus in the mask must all be on the apic cluster. If are not + * on the same apicid cluster return default value of target_cpus(): + */ + cpu = first_cpu(*cpumask); + apicid = summit_cpu_to_logical_apicid(cpu); + + while (cpus_found < num_bits_set) { + if (cpu_isset(cpu, *cpumask)) { + int new_apicid = summit_cpu_to_logical_apicid(cpu); + + if (apicid_cluster(apicid) != + apicid_cluster(new_apicid)) { + printk ("%s: Not a valid mask!\n", __func__); + + return 0xFF; + } + apicid = apicid | new_apicid; + cpus_found++; + } + cpu++; + } + return apicid; +} + +static inline unsigned int +summit_cpu_mask_to_apicid_and(const struct cpumask *inmask, + const struct cpumask *andmask) +{ + int apicid = summit_cpu_to_logical_apicid(0); + cpumask_var_t cpumask; + + if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC)) + return apicid; + + cpumask_and(cpumask, inmask, andmask); + cpumask_and(cpumask, cpumask, cpu_online_mask); + apicid = summit_cpu_mask_to_apicid(cpumask); + + free_cpumask_var(cpumask); + + return apicid; +} + +/* + * cpuid returns the value latched in the HW at reset, not the APIC ID + * register's value. For any box whose BIOS changes APIC IDs, like + * clustered APIC systems, we must use hard_smp_processor_id. + * + * See Intel's IA-32 SW Dev's Manual Vol2 under CPUID. + */ +static inline int summit_phys_pkg_id(int cpuid_apic, int index_msb) +{ + return hard_smp_processor_id() >> index_msb; +} + +static int probe_summit(void) +{ + /* probed later in mptable/ACPI hooks */ + return 0; +} + +static void summit_vector_allocation_domain(int cpu, cpumask_t *retmask) +{ + /* Careful. Some cpus do not strictly honor the set of cpus + * specified in the interrupt destination when using lowest + * priority interrupt delivery mode. + * + * In particular there was a hyperthreading cpu observed to + * deliver interrupts to the wrong hyperthread when only one + * hyperthread was specified in the interrupt desitination. + */ + *retmask = (cpumask_t){ { [0] = APIC_ALL_CPUS, } }; +} static struct rio_table_hdr *rio_table_hdr __initdata; static struct scal_detail *scal_devs[MAX_NUMNODES] __initdata; @@ -186,3 +543,61 @@ void __init setup_summit(void) next_wpeg = 0; } while (next_wpeg != 0); } + + +struct genapic apic_summit = { + + .name = "summit", + .probe = probe_summit, + .acpi_madt_oem_check = summit_acpi_madt_oem_check, + .apic_id_registered = summit_apic_id_registered, + + .irq_delivery_mode = dest_LowestPrio, + /* logical delivery broadcast to all CPUs: */ + .irq_dest_mode = 1, + + .target_cpus = summit_target_cpus, + .disable_esr = 1, + .dest_logical = APIC_DEST_LOGICAL, + .check_apicid_used = summit_check_apicid_used, + .check_apicid_present = summit_check_apicid_present, + + .vector_allocation_domain = summit_vector_allocation_domain, + .init_apic_ldr = summit_init_apic_ldr, + + .ioapic_phys_id_map = summit_ioapic_phys_id_map, + .setup_apic_routing = summit_setup_apic_routing, + .multi_timer_check = NULL, + .apicid_to_node = summit_apicid_to_node, + .cpu_to_logical_apicid = summit_cpu_to_logical_apicid, + .cpu_present_to_apicid = summit_cpu_present_to_apicid, + .apicid_to_cpu_present = summit_apicid_to_cpu_present, + .setup_portio_remap = NULL, + .check_phys_apicid_present = summit_check_phys_apicid_present, + .enable_apic_mode = NULL, + .phys_pkg_id = summit_phys_pkg_id, + .mps_oem_check = summit_mps_oem_check, + + .get_apic_id = summit_get_apic_id, + .set_apic_id = NULL, + .apic_id_mask = 0xFF << 24, + + .cpu_mask_to_apicid = summit_cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = summit_cpu_mask_to_apicid_and, + + .send_IPI_mask = summit_send_IPI_mask, + .send_IPI_mask_allbutself = NULL, + .send_IPI_allbutself = summit_send_IPI_allbutself, + .send_IPI_all = summit_send_IPI_all, + .send_IPI_self = NULL, + + .wakeup_cpu = NULL, + .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, + .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, + + .wait_for_init_deassert = default_wait_for_init_deassert, + + .smp_callin_clear_local_apic = NULL, + .store_NMI_vector = NULL, + .inquire_remote_apic = default_inquire_remote_apic, +}; diff --git a/arch/x86/mach-generic/Makefile b/arch/x86/mach-generic/Makefile index 6730f4e7c74..78ab5735cb8 100644 --- a/arch/x86/mach-generic/Makefile +++ b/arch/x86/mach-generic/Makefile @@ -6,6 +6,5 @@ EXTRA_CFLAGS := -Iarch/x86/kernel obj-y := probe.o default.o obj-$(CONFIG_X86_NUMAQ) += numaq.o -obj-$(CONFIG_X86_SUMMIT) += summit.o obj-$(CONFIG_X86_BIGSMP) += bigsmp.o obj-$(CONFIG_X86_ES7000) += es7000.o diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c deleted file mode 100644 index 673a64f8b46..00000000000 --- a/arch/x86/mach-generic/summit.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * APIC driver for the IBM "Summit" chipset. - */ -#define APIC_DEFINITION 1 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int probe_summit(void) -{ - /* probed later in mptable/ACPI hooks */ - return 0; -} - -static void summit_vector_allocation_domain(int cpu, cpumask_t *retmask) -{ - /* Careful. Some cpus do not strictly honor the set of cpus - * specified in the interrupt destination when using lowest - * priority interrupt delivery mode. - * - * In particular there was a hyperthreading cpu observed to - * deliver interrupts to the wrong hyperthread when only one - * hyperthread was specified in the interrupt desitination. - */ - *retmask = (cpumask_t){ { [0] = APIC_ALL_CPUS, } }; -} - -struct genapic apic_summit = { - - .name = "summit", - .probe = probe_summit, - .acpi_madt_oem_check = summit_acpi_madt_oem_check, - .apic_id_registered = summit_apic_id_registered, - - .irq_delivery_mode = dest_LowestPrio, - /* logical delivery broadcast to all CPUs: */ - .irq_dest_mode = 1, - - .target_cpus = summit_target_cpus, - .disable_esr = 1, - .dest_logical = APIC_DEST_LOGICAL, - .check_apicid_used = summit_check_apicid_used, - .check_apicid_present = summit_check_apicid_present, - - .vector_allocation_domain = summit_vector_allocation_domain, - .init_apic_ldr = summit_init_apic_ldr, - - .ioapic_phys_id_map = summit_ioapic_phys_id_map, - .setup_apic_routing = summit_setup_apic_routing, - .multi_timer_check = NULL, - .apicid_to_node = summit_apicid_to_node, - .cpu_to_logical_apicid = summit_cpu_to_logical_apicid, - .cpu_present_to_apicid = summit_cpu_present_to_apicid, - .apicid_to_cpu_present = summit_apicid_to_cpu_present, - .setup_portio_remap = NULL, - .check_phys_apicid_present = summit_check_phys_apicid_present, - .enable_apic_mode = NULL, - .phys_pkg_id = summit_phys_pkg_id, - .mps_oem_check = summit_mps_oem_check, - - .get_apic_id = summit_get_apic_id, - .set_apic_id = NULL, - .apic_id_mask = 0xFF << 24, - - .cpu_mask_to_apicid = summit_cpu_mask_to_apicid, - .cpu_mask_to_apicid_and = summit_cpu_mask_to_apicid_and, - - .send_IPI_mask = summit_send_IPI_mask, - .send_IPI_mask_allbutself = NULL, - .send_IPI_allbutself = summit_send_IPI_allbutself, - .send_IPI_all = summit_send_IPI_all, - .send_IPI_self = NULL, - - .wakeup_cpu = NULL, - .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, - .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, - - .wait_for_init_deassert = default_wait_for_init_deassert, - - .smp_callin_clear_local_apic = NULL, - .store_NMI_vector = NULL, - .inquire_remote_apic = default_inquire_remote_apic, -}; -- GitLab From f0f6f346a1edaec23b990c25f53478669e56fa70 Mon Sep 17 00:00:00 2001 From: Moni Shoua Date: Wed, 28 Jan 2009 14:54:35 -0800 Subject: [PATCH 0590/4982] IB/mlx4: Fix dispatch of IB_EVENT_LID_CHANGE event When snooping a PortInfo MAD, its client_reregister bit is checked. If the bit is ON then a CLIENT_REREGISTER event is dispatched, otherwise a LID_CHANGE event is dispatched. This way of decision ignores the cases where the MAD changes the LID along with an instruction to reregister (so a necessary LID_CHANGE event won't be dispatched) or the MAD is neither of these (and an unnecessary LID_CHANGE event will be dispatched). This causes problems at least with IPoIB, which will do a "light" flush on reregister, rather than the "heavy" flush required due to a LID change. Fix this by dispatching a CLIENT_REREGISTER event if the client_reregister bit is set, but also compare the LID in the MAD to the current LID. If and only if they are not identical then a LID_CHANGE event is dispatched. Signed-off-by: Moni Shoua Signed-off-by: Jack Morgenstein Signed-off-by: Yossi Etigin Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mlx4/mad.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index 606f1e2ef28..19e68ab6616 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c @@ -147,7 +147,8 @@ static void update_sm_ah(struct mlx4_ib_dev *dev, u8 port_num, u16 lid, u8 sl) * Snoop SM MADs for port info and P_Key table sets, so we can * synthesize LID change and P_Key change events. */ -static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad) +static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad, + u16 prev_lid) { struct ib_event event; @@ -157,6 +158,7 @@ static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad) if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PORT_INFO) { struct ib_port_info *pinfo = (struct ib_port_info *) ((struct ib_smp *) mad)->data; + u16 lid = be16_to_cpu(pinfo->lid); update_sm_ah(to_mdev(ibdev), port_num, be16_to_cpu(pinfo->sm_lid), @@ -165,12 +167,15 @@ static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad) event.device = ibdev; event.element.port_num = port_num; - if (pinfo->clientrereg_resv_subnetto & 0x80) + if (pinfo->clientrereg_resv_subnetto & 0x80) { event.event = IB_EVENT_CLIENT_REREGISTER; - else - event.event = IB_EVENT_LID_CHANGE; + ib_dispatch_event(&event); + } - ib_dispatch_event(&event); + if (prev_lid != lid) { + event.event = IB_EVENT_LID_CHANGE; + ib_dispatch_event(&event); + } } if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PKEY_TABLE) { @@ -228,8 +233,9 @@ int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, struct ib_wc *in_wc, struct ib_grh *in_grh, struct ib_mad *in_mad, struct ib_mad *out_mad) { - u16 slid; + u16 slid, prev_lid = 0; int err; + struct ib_port_attr pattr; slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE); @@ -263,6 +269,13 @@ int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, } else return IB_MAD_RESULT_SUCCESS; + if ((in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED || + in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) && + in_mad->mad_hdr.method == IB_MGMT_METHOD_SET && + in_mad->mad_hdr.attr_id == IB_SMP_ATTR_PORT_INFO && + !ib_query_port(ibdev, port_num, &pattr)) + prev_lid = pattr.lid; + err = mlx4_MAD_IFC(to_mdev(ibdev), mad_flags & IB_MAD_IGNORE_MKEY, mad_flags & IB_MAD_IGNORE_BKEY, @@ -271,7 +284,7 @@ int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, return IB_MAD_RESULT_FAILURE; if (!out_mad->mad_hdr.status) { - smp_snoop(ibdev, port_num, in_mad); + smp_snoop(ibdev, port_num, in_mad, prev_lid); node_desc_override(ibdev, out_mad); } -- GitLab From 270b8b85134c299799dddec624ceeb5671330131 Mon Sep 17 00:00:00 2001 From: Moni Shoua Date: Wed, 28 Jan 2009 15:15:56 -0800 Subject: [PATCH 0591/4982] IB/mthca: Fix dispatch of IB_EVENT_LID_CHANGE event When snooping a PortInfo MAD, its client_reregister bit is checked. If the bit is ON then a CLIENT_REREGISTER event is dispatched, otherwise a LID_CHANGE event is dispatched. This way of decision ignores the cases where the MAD changes the LID along with an instruction to reregister (so a necessary LID_CHANGE event won't be dispatched) or the MAD is neither of these (and an unnecessary LID_CHANGE event will be dispatched). This causes problems at least with IPoIB, which will do a "light" flush on reregister, rather than the "heavy" flush required due to a LID change. Fix this by dispatching a CLIENT_REREGISTER event if the client_reregister bit is set, but also compare the LID in the MAD to the current LID. If and only if they are not identical then a LID_CHANGE event is dispatched. Signed-off-by: Moni Shoua Signed-off-by: Jack Morgenstein Signed-off-by: Yossi Etigin Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_mad.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c index 640449582ab..5648659ff0b 100644 --- a/drivers/infiniband/hw/mthca/mthca_mad.c +++ b/drivers/infiniband/hw/mthca/mthca_mad.c @@ -104,7 +104,8 @@ static void update_sm_ah(struct mthca_dev *dev, */ static void smp_snoop(struct ib_device *ibdev, u8 port_num, - struct ib_mad *mad) + struct ib_mad *mad, + u16 prev_lid) { struct ib_event event; @@ -114,6 +115,7 @@ static void smp_snoop(struct ib_device *ibdev, if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PORT_INFO) { struct ib_port_info *pinfo = (struct ib_port_info *) ((struct ib_smp *) mad)->data; + u16 lid = be16_to_cpu(pinfo->lid); mthca_update_rate(to_mdev(ibdev), port_num); update_sm_ah(to_mdev(ibdev), port_num, @@ -123,12 +125,15 @@ static void smp_snoop(struct ib_device *ibdev, event.device = ibdev; event.element.port_num = port_num; - if (pinfo->clientrereg_resv_subnetto & 0x80) + if (pinfo->clientrereg_resv_subnetto & 0x80) { event.event = IB_EVENT_CLIENT_REREGISTER; - else - event.event = IB_EVENT_LID_CHANGE; + ib_dispatch_event(&event); + } - ib_dispatch_event(&event); + if (prev_lid != lid) { + event.event = IB_EVENT_LID_CHANGE; + ib_dispatch_event(&event); + } } if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PKEY_TABLE) { @@ -196,6 +201,8 @@ int mthca_process_mad(struct ib_device *ibdev, int err; u8 status; u16 slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE); + u16 prev_lid = 0; + struct ib_port_attr pattr; /* Forward locally generated traps to the SM */ if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP && @@ -233,6 +240,12 @@ int mthca_process_mad(struct ib_device *ibdev, return IB_MAD_RESULT_SUCCESS; } else return IB_MAD_RESULT_SUCCESS; + if ((in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED || + in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) && + in_mad->mad_hdr.method == IB_MGMT_METHOD_SET && + in_mad->mad_hdr.attr_id == IB_SMP_ATTR_PORT_INFO && + !ib_query_port(ibdev, port_num, &pattr)) + prev_lid = pattr.lid; err = mthca_MAD_IFC(to_mdev(ibdev), mad_flags & IB_MAD_IGNORE_MKEY, @@ -252,7 +265,7 @@ int mthca_process_mad(struct ib_device *ibdev, } if (!out_mad->mad_hdr.status) { - smp_snoop(ibdev, port_num, in_mad); + smp_snoop(ibdev, port_num, in_mad, prev_lid); node_desc_override(ibdev, out_mad); } -- GitLab From eaf83e39355a0a8933a003fa3b27b37d19901d64 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 29 Jan 2009 10:51:11 +1100 Subject: [PATCH 0592/4982] solos: Tidy up DMA handling a little. Still untested Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 95 +++++++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 42 deletions(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 63c9ad03aec..acba08df5eb 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -68,6 +68,8 @@ #define RX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2) #define TX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2 + BUF_SIZE) +#define RX_DMA_SIZE 2048 + static int debug = 0; static int atmdebug = 0; static int firmware_upgrade = 0; @@ -608,17 +610,11 @@ void solos_bh(unsigned long card_arg) if (card->using_dma) { skb = card->rx_skb[port]; - pci_unmap_single(card->dev, SKB_CB(skb)->dma_addr, skb->len, - PCI_DMA_FROMDEVICE); - - card->rx_skb[port] = alloc_skb(2048, GFP_ATOMIC); - if (card->rx_skb[port]) { - SKB_CB(card->rx_skb[port])->dma_addr = - pci_map_single(card->dev, skb->data, skb->len, - PCI_DMA_FROMDEVICE); - iowrite32(SKB_CB(card->rx_skb[port])->dma_addr, - card->config_regs + RX_DMA_ADDR(port)); - } + card->rx_skb[port] = NULL; + + pci_unmap_single(card->dev, SKB_CB(skb)->dma_addr, + RX_DMA_SIZE, PCI_DMA_FROMDEVICE); + header = (void *)skb->data; size = le16_to_cpu(header->size); skb_put(skb, size + sizeof(*header)); @@ -669,7 +665,7 @@ void solos_bh(unsigned long card_arg) case PKT_STATUS: process_status(card, port, skb); - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); break; case PKT_COMMAND: @@ -681,12 +677,32 @@ void solos_bh(unsigned long card_arg) if (net_ratelimit()) dev_warn(&card->dev->dev, "Dropping console response on port %d\n", port); + dev_kfree_skb_any(skb); } else skb_queue_tail(&card->cli_queue[port], skb); spin_unlock(&card->cli_queue_lock); break; } } + /* Allocate RX skbs for any ports which need them */ + if (card->using_dma && card->atmdev[port] && + !card->rx_skb[port]) { + struct sk_buff *skb = alloc_skb(RX_DMA_SIZE, GFP_ATOMIC); + if (skb) { + SKB_CB(skb)->dma_addr = + pci_map_single(card->dev, skb->data, + RX_DMA_SIZE, PCI_DMA_FROMDEVICE); + iowrite32(SKB_CB(skb)->dma_addr, + card->config_regs + RX_DMA_ADDR(port)); + card->rx_skb[port] = skb; + } else { + if (net_ratelimit()) + dev_warn(&card->dev->dev, "Failed to allocate RX skb"); + + /* We'll have to try again later */ + tasklet_schedule(&card->tlet); + } + } } if (rx_done) iowrite32(rx_done, card->config_regs + FLAGS_ADDR); @@ -901,50 +917,45 @@ static int fpga_tx(struct solos_card *card) for (port = 0; port < card->nr_ports; port++) { if (card->atmdev[port] && !(tx_pending & (1 << port))) { + struct sk_buff *oldskb = card->tx_skb[port]; + if (oldskb) + pci_unmap_single(card->dev, SKB_CB(oldskb)->dma_addr, + oldskb->len, PCI_DMA_TODEVICE); + spin_lock(&card->tx_queue_lock); skb = skb_dequeue(&card->tx_queue[port]); spin_unlock(&card->tx_queue_lock); - if (!skb) + if (skb && !card->using_dma) { + memcpy_toio(TX_BUF(card, port), skb->data, skb->len); + tx_started |= 1 << port; //Set TX full flag + oldskb = skb; /* We're done with this skb already */ + } else if (skb && card->using_dma) { + SKB_CB(skb)->dma_addr = pci_map_single(card->dev, skb->data, + skb->len, PCI_DMA_TODEVICE); + iowrite32(SKB_CB(skb)->dma_addr, + card->config_regs + TX_DMA_ADDR(port)); + } + + if (!oldskb) continue; + /* Clean up and free oldskb now it's gone */ if (atmdebug) { dev_info(&card->dev->dev, "Transmitted: port %d\n", port); - print_buffer(skb); + print_buffer(oldskb); } - if (card->using_dma) { - if (card->tx_skb[port]) { - struct sk_buff *oldskb = card->tx_skb[port]; - - pci_unmap_single(card->dev, SKB_CB(oldskb)->dma_addr, - oldskb->len, PCI_DMA_TODEVICE); - - vcc = SKB_CB(oldskb)->vcc; - - if (vcc) { - atomic_inc(&vcc->stats->tx); - solos_pop(vcc, oldskb); - } else - dev_kfree_skb_irq(oldskb); - } - SKB_CB(skb)->dma_addr = pci_map_single(card->dev, skb->data, - skb->len, PCI_DMA_TODEVICE); - iowrite32(SKB_CB(skb)->dma_addr, card->config_regs + TX_DMA_ADDR(port)); - } else { - memcpy_toio(TX_BUF(card, port), skb->data, skb->len); - tx_started |= 1 << port; //Set TX full flag + vcc = SKB_CB(oldskb)->vcc; - vcc = SKB_CB(skb)->vcc; + if (vcc) { + atomic_inc(&vcc->stats->tx); + solos_pop(vcc, oldskb); + } else + dev_kfree_skb_irq(oldskb); - if (vcc) { - atomic_inc(&vcc->stats->tx); - solos_pop(vcc, skb); - } else - dev_kfree_skb_irq(skb); - } } } if (tx_started) -- GitLab From f69e417033af84316c3ed7cafabd388b3ae85952 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 29 Jan 2009 11:10:58 +1100 Subject: [PATCH 0593/4982] solos: Tidy up tx_mask handling for ports which need TX Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index acba08df5eb..bf59c407fec 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -100,6 +100,7 @@ struct solos_card { void __iomem *config_regs; void __iomem *buffers; int nr_ports; + int tx_mask; struct pci_dev *dev; struct atm_dev *atmdev[4]; struct tasklet_struct tlet; @@ -590,15 +591,13 @@ void solos_bh(unsigned long card_arg) struct solos_card *card = (void *)card_arg; int port; uint32_t card_flags; - uint32_t tx_mask; uint32_t rx_done = 0; card_flags = ioread32(card->config_regs + FLAGS_ADDR); /* The TX bits are set if the channel is busy; clear if not. We want to invoke fpga_tx() unless _all_ the bits for active channels are set */ - tx_mask = (1 << card->nr_ports) - 1; - if ((card_flags & tx_mask) != tx_mask) + if ((card_flags & card->tx_mask) != card->tx_mask) fpga_tx(card); for (port = 0; port < card->nr_ports; port++) { @@ -887,15 +886,20 @@ static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb, struct atm_vcc *vcc) { int old_len; + unsigned long flags; SKB_CB(skb)->vcc = vcc; - spin_lock(&card->tx_queue_lock); + spin_lock_irqsave(&card->tx_queue_lock, flags); old_len = skb_queue_len(&card->tx_queue[port]); skb_queue_tail(&card->tx_queue[port], skb); - spin_unlock(&card->tx_queue_lock); + if (!old_len) { + card->tx_mask |= (1 << port); + } + spin_unlock_irqrestore(&card->tx_queue_lock, flags); - /* If TX might need to be started, do so */ + /* Theoretically we could just schedule the tasklet here, but + that introduces latency we don't want -- it's noticeable */ if (!old_len) fpga_tx(card); } @@ -911,7 +915,7 @@ static int fpga_tx(struct solos_card *card) spin_lock_irqsave(&card->tx_lock, flags); - tx_pending = ioread32(card->config_regs + FLAGS_ADDR); + tx_pending = ioread32(card->config_regs + FLAGS_ADDR) & card->tx_mask; dev_vdbg(&card->dev->dev, "TX Flags are %X\n", tx_pending); @@ -925,6 +929,8 @@ static int fpga_tx(struct solos_card *card) spin_lock(&card->tx_queue_lock); skb = skb_dequeue(&card->tx_queue[port]); + if (!skb) + card->tx_mask &= ~(1 << port); spin_unlock(&card->tx_queue_lock); if (skb && !card->using_dma) { -- GitLab From cd2169fbfb39e6fc2fb9055ed2eedaa68f53c734 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 29 Jan 2009 11:12:58 +1100 Subject: [PATCH 0594/4982] solos: Remove unused loopback debug stuff Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index bf59c407fec..2ef81575378 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -70,7 +70,6 @@ #define RX_DMA_SIZE 2048 -static int debug = 0; static int atmdebug = 0; static int firmware_upgrade = 0; static int fpga_upgrade = 0; @@ -133,11 +132,9 @@ MODULE_AUTHOR("Traverse Technologies "); MODULE_DESCRIPTION("Solos PCI driver"); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); -MODULE_PARM_DESC(debug, "Enable Loopback"); MODULE_PARM_DESC(atmdebug, "Print ATM data"); MODULE_PARM_DESC(firmware_upgrade, "Initiate Solos firmware upgrade"); MODULE_PARM_DESC(fpga_upgrade, "Initiate FPGA upgrade"); -module_param(debug, int, 0444); module_param(atmdebug, int, 0644); module_param(firmware_upgrade, int, 0444); module_param(fpga_upgrade, int, 0444); @@ -974,26 +971,12 @@ static int fpga_tx(struct solos_card *card) static int psend(struct atm_vcc *vcc, struct sk_buff *skb) { struct solos_card *card = vcc->dev->dev_data; - struct sk_buff *skb2 = NULL; struct pkt_hdr *header; int pktlen; //dev_dbg(&card->dev->dev, "psend called.\n"); //dev_dbg(&card->dev->dev, "dev,vpi,vci = %d,%d,%d\n",SOLOS_CHAN(vcc->dev),vcc->vpi,vcc->vci); - if (debug) { - skb2 = atm_alloc_charge(vcc, skb->len, GFP_ATOMIC); - if (skb2) { - memcpy(skb2->data, skb->data, skb->len); - skb_put(skb2, skb->len); - vcc->push(vcc, skb2); - atomic_inc(&vcc->stats->rx); - } - atomic_inc(&vcc->stats->tx); - solos_pop(vcc, skb); - return 0; - } - pktlen = skb->len; if (pktlen > (BUF_SIZE - sizeof(*header))) { dev_warn(&card->dev->dev, "Length of PDU is too large. Dropping PDU.\n"); @@ -1052,9 +1035,6 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) uint32_t data32; struct solos_card *card; - if (debug) - return 0; - card = kzalloc(sizeof(*card), GFP_KERNEL); if (!card) return -ENOMEM; @@ -1256,9 +1236,6 @@ static void fpga_remove(struct pci_dev *dev) { struct solos_card *card = pci_get_drvdata(dev); - if (debug) - return; - atm_remove(card); dev_vdbg(&dev->dev, "Freeing IRQ\n"); -- GitLab From fcd82664cb421b043f97ad194a7eda3592e0349e Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 29 Jan 2009 11:29:12 +1100 Subject: [PATCH 0595/4982] solos: Remove IRQF_DISABLED, don't frob IRQ enable on the FPGA in solos_irq() Neither of these are necessary. Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 2ef81575378..f2736dd3eb0 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -570,16 +570,12 @@ static irqreturn_t solos_irq(int irq, void *dev_id) //ACK IRQ iowrite32(0, card->config_regs + IRQ_CLEAR); - //Disable IRQs from FPGA - iowrite32(0, card->config_regs + IRQ_EN_ADDR); if (card->atmdev[0]) tasklet_schedule(&card->tlet); else wake_up(&card->fw_wq); - //Enable IRQs from FPGA - iowrite32(1, card->config_regs + IRQ_EN_ADDR); return IRQ_RETVAL(handled); } @@ -1132,7 +1128,7 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) } */ //dev_dbg(&card->dev->dev, "Requesting IRQ: %d\n",dev->irq); - err = request_irq(dev->irq, solos_irq, IRQF_DISABLED|IRQF_SHARED, + err = request_irq(dev->irq, solos_irq, IRQF_SHARED, "solos-pci", card); if (err) { dev_dbg(&card->dev->dev, "Failed to request interrupt IRQ: %d\n", dev->irq); -- GitLab From a0641cc49a1d1436b3591a9aa4be8159f84b662c Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 29 Jan 2009 11:31:28 +1100 Subject: [PATCH 0596/4982] solos: Remove superfluous wait_queue_head_t from struct solos_param Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index f2736dd3eb0..8121f8556ea 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -123,7 +123,6 @@ struct solos_param { pid_t pid; int port; struct sk_buff *response; - wait_queue_head_t wq; }; #define SOLOS_CHAN(atmdev) ((int)(unsigned long)(atmdev)->phy_data) -- GitLab From c6428e52facd03dfac971a44abca4bc058104fec Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 29 Jan 2009 12:17:09 +1100 Subject: [PATCH 0597/4982] solos: Fix various bugs in status packet handling Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 49 +++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 8121f8556ea..5e228a3f750 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -293,13 +293,15 @@ static char *next_string(struct sk_buff *skb) { int i = 0; char *this = skb->data; - - while (i < skb->len) { + + for (i = 0; i < skb->len; i++) { if (this[i] == '\n') { this[i] = 0; - skb_pull(skb, i); + skb_pull(skb, i + 1); return this; } + if (!isprint(this[i])) + return NULL; } return NULL; } @@ -316,7 +318,7 @@ static char *next_string(struct sk_buff *skb) static int process_status(struct solos_card *card, int port, struct sk_buff *skb) { char *str, *end, *state_str; - int ver, rate_up, rate_down, state, snr, attn; + int ver, rate_up, rate_down, state; if (!card->atmdev[port]) return -ENODEV; @@ -333,16 +335,22 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb } str = next_string(skb); + if (!str) + return -EIO; rate_up = simple_strtol(str, &end, 10); if (*end) return -EIO; str = next_string(skb); + if (!str) + return -EIO; rate_down = simple_strtol(str, &end, 10); if (*end) return -EIO; state_str = next_string(skb); + if (!state_str) + return -EIO; if (!strcmp(state_str, "Showtime")) state = ATM_PHY_SIG_FOUND; else { @@ -350,25 +358,24 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb release_vccs(card->atmdev[port]); } - str = next_string(skb); - snr = simple_strtol(str, &end, 10); - if (*end) - return -EIO; - - str = next_string(skb); - attn = simple_strtol(str, &end, 10); - if (*end) - return -EIO; - - if (state == ATM_PHY_SIG_LOST && !rate_up && !rate_down) + if (state == ATM_PHY_SIG_LOST) { dev_info(&card->dev->dev, "Port %d ATM state: %s\n", port, state_str); - else - dev_info(&card->dev->dev, "Port %d ATM state: %s (%d/%d kb/s, SNR %ddB, Attn %ddB)\n", - port, state_str, rate_up/1000, rate_down/1000, - snr, attn); - - card->atmdev[port]->link_rate = rate_down; + } else { + char *snr, *attn; + + snr = next_string(skb); + if (!str) + return -EIO; + attn = next_string(skb); + if (!attn) + return -EIO; + + dev_info(&card->dev->dev, "Port %d: %s (%d/%d kb/s%s%s%s%s)\n", + port, state_str, rate_down/1000, rate_up/1000, + snr[0]?", SNR ":"", snr, attn[0]?", Attn ":"", attn); + } + card->atmdev[port]->link_rate = rate_down / 424; card->atmdev[port]->signal = state; return 0; -- GitLab From 42990701f938b9318e46102d9919ceb28e5b0e6d Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Tue, 20 Jan 2009 21:14:37 +0000 Subject: [PATCH 0598/4982] sh: Relax inline assembly constraints When dereferencing the memory address contained in a register and modifying the value at that memory address, the register should not be listed in the inline asm outputs. The value at the memory address is an output (which is taken care of with the "memory" clobber), not the register. Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- arch/sh/include/asm/bitops-llsc.h | 72 +++++++++++++++--------------- arch/sh/include/asm/cmpxchg-llsc.h | 38 ++++++++-------- 2 files changed, 55 insertions(+), 55 deletions(-) diff --git a/arch/sh/include/asm/bitops-llsc.h b/arch/sh/include/asm/bitops-llsc.h index 1d2fc0b010a..d8328be0619 100644 --- a/arch/sh/include/asm/bitops-llsc.h +++ b/arch/sh/include/asm/bitops-llsc.h @@ -1,7 +1,7 @@ #ifndef __ASM_SH_BITOPS_LLSC_H #define __ASM_SH_BITOPS_LLSC_H -static inline void set_bit(int nr, volatile void * addr) +static inline void set_bit(int nr, volatile void *addr) { int mask; volatile unsigned int *a = addr; @@ -13,16 +13,16 @@ static inline void set_bit(int nr, volatile void * addr) __asm__ __volatile__ ( "1: \n\t" "movli.l @%1, %0 ! set_bit \n\t" - "or %3, %0 \n\t" + "or %2, %0 \n\t" "movco.l %0, @%1 \n\t" "bf 1b \n\t" - : "=&z" (tmp), "=r" (a) - : "1" (a), "r" (mask) + : "=&z" (tmp) + : "r" (a), "r" (mask) : "t", "memory" ); } -static inline void clear_bit(int nr, volatile void * addr) +static inline void clear_bit(int nr, volatile void *addr) { int mask; volatile unsigned int *a = addr; @@ -34,16 +34,16 @@ static inline void clear_bit(int nr, volatile void * addr) __asm__ __volatile__ ( "1: \n\t" "movli.l @%1, %0 ! clear_bit \n\t" - "and %3, %0 \n\t" + "and %2, %0 \n\t" "movco.l %0, @%1 \n\t" "bf 1b \n\t" - : "=&z" (tmp), "=r" (a) - : "1" (a), "r" (~mask) + : "=&z" (tmp) + : "r" (a), "r" (~mask) : "t", "memory" ); } -static inline void change_bit(int nr, volatile void * addr) +static inline void change_bit(int nr, volatile void *addr) { int mask; volatile unsigned int *a = addr; @@ -55,16 +55,16 @@ static inline void change_bit(int nr, volatile void * addr) __asm__ __volatile__ ( "1: \n\t" "movli.l @%1, %0 ! change_bit \n\t" - "xor %3, %0 \n\t" + "xor %2, %0 \n\t" "movco.l %0, @%1 \n\t" "bf 1b \n\t" - : "=&z" (tmp), "=r" (a) - : "1" (a), "r" (mask) + : "=&z" (tmp) + : "r" (a), "r" (mask) : "t", "memory" ); } -static inline int test_and_set_bit(int nr, volatile void * addr) +static inline int test_and_set_bit(int nr, volatile void *addr) { int mask, retval; volatile unsigned int *a = addr; @@ -75,21 +75,21 @@ static inline int test_and_set_bit(int nr, volatile void * addr) __asm__ __volatile__ ( "1: \n\t" - "movli.l @%1, %0 ! test_and_set_bit \n\t" - "mov %0, %2 \n\t" - "or %4, %0 \n\t" - "movco.l %0, @%1 \n\t" + "movli.l @%2, %0 ! test_and_set_bit \n\t" + "mov %0, %1 \n\t" + "or %3, %0 \n\t" + "movco.l %0, @%2 \n\t" "bf 1b \n\t" - "and %4, %2 \n\t" - : "=&z" (tmp), "=r" (a), "=&r" (retval) - : "1" (a), "r" (mask) + "and %3, %1 \n\t" + : "=&z" (tmp), "=&r" (retval) + : "r" (a), "r" (mask) : "t", "memory" ); return retval != 0; } -static inline int test_and_clear_bit(int nr, volatile void * addr) +static inline int test_and_clear_bit(int nr, volatile void *addr) { int mask, retval; volatile unsigned int *a = addr; @@ -100,22 +100,22 @@ static inline int test_and_clear_bit(int nr, volatile void * addr) __asm__ __volatile__ ( "1: \n\t" - "movli.l @%1, %0 ! test_and_clear_bit \n\t" - "mov %0, %2 \n\t" - "and %5, %0 \n\t" - "movco.l %0, @%1 \n\t" + "movli.l @%2, %0 ! test_and_clear_bit \n\t" + "mov %0, %1 \n\t" + "and %4, %0 \n\t" + "movco.l %0, @%2 \n\t" "bf 1b \n\t" - "and %4, %2 \n\t" + "and %3, %1 \n\t" "synco \n\t" - : "=&z" (tmp), "=r" (a), "=&r" (retval) - : "1" (a), "r" (mask), "r" (~mask) + : "=&z" (tmp), "=&r" (retval) + : "r" (a), "r" (mask), "r" (~mask) : "t", "memory" ); return retval != 0; } -static inline int test_and_change_bit(int nr, volatile void * addr) +static inline int test_and_change_bit(int nr, volatile void *addr) { int mask, retval; volatile unsigned int *a = addr; @@ -126,15 +126,15 @@ static inline int test_and_change_bit(int nr, volatile void * addr) __asm__ __volatile__ ( "1: \n\t" - "movli.l @%1, %0 ! test_and_change_bit \n\t" - "mov %0, %2 \n\t" - "xor %4, %0 \n\t" - "movco.l %0, @%1 \n\t" + "movli.l @%2, %0 ! test_and_change_bit \n\t" + "mov %0, %1 \n\t" + "xor %3, %0 \n\t" + "movco.l %0, @%2 \n\t" "bf 1b \n\t" - "and %4, %2 \n\t" + "and %3, %1 \n\t" "synco \n\t" - : "=&z" (tmp), "=r" (a), "=&r" (retval) - : "1" (a), "r" (mask) + : "=&z" (tmp), "=&r" (retval) + : "r" (a), "r" (mask) : "t", "memory" ); diff --git a/arch/sh/include/asm/cmpxchg-llsc.h b/arch/sh/include/asm/cmpxchg-llsc.h index aee3bf28658..0fac3da536c 100644 --- a/arch/sh/include/asm/cmpxchg-llsc.h +++ b/arch/sh/include/asm/cmpxchg-llsc.h @@ -8,14 +8,14 @@ static inline unsigned long xchg_u32(volatile u32 *m, unsigned long val) __asm__ __volatile__ ( "1: \n\t" - "movli.l @%1, %0 ! xchg_u32 \n\t" - "mov %0, %2 \n\t" - "mov %4, %0 \n\t" - "movco.l %0, @%1 \n\t" + "movli.l @%2, %0 ! xchg_u32 \n\t" + "mov %0, %1 \n\t" + "mov %3, %0 \n\t" + "movco.l %0, @%2 \n\t" "bf 1b \n\t" "synco \n\t" - : "=&z"(tmp), "=r" (m), "=&r" (retval) - : "1" (m), "r" (val) + : "=&z"(tmp), "=&r" (retval) + : "r" (m), "r" (val) : "t", "memory" ); @@ -29,14 +29,14 @@ static inline unsigned long xchg_u8(volatile u8 *m, unsigned long val) __asm__ __volatile__ ( "1: \n\t" - "movli.l @%1, %0 ! xchg_u8 \n\t" - "mov %0, %2 \n\t" - "mov %4, %0 \n\t" - "movco.l %0, @%1 \n\t" + "movli.l @%2, %0 ! xchg_u8 \n\t" + "mov %0, %1 \n\t" + "mov %3, %0 \n\t" + "movco.l %0, @%2 \n\t" "bf 1b \n\t" "synco \n\t" - : "=&z"(tmp), "=r" (m), "=&r" (retval) - : "1" (m), "r" (val & 0xff) + : "=&z"(tmp), "=&r" (retval) + : "r" (m), "r" (val & 0xff) : "t", "memory" ); @@ -51,17 +51,17 @@ __cmpxchg_u32(volatile int *m, unsigned long old, unsigned long new) __asm__ __volatile__ ( "1: \n\t" - "movli.l @%1, %0 ! __cmpxchg_u32 \n\t" - "mov %0, %2 \n\t" - "cmp/eq %2, %4 \n\t" + "movli.l @%2, %0 ! __cmpxchg_u32 \n\t" + "mov %0, %1 \n\t" + "cmp/eq %1, %3 \n\t" "bf 2f \n\t" - "mov %5, %0 \n\t" + "mov %3, %0 \n\t" "2: \n\t" - "movco.l %0, @%1 \n\t" + "movco.l %0, @%2 \n\t" "bf 1b \n\t" "synco \n\t" - : "=&z" (tmp), "=r" (m), "=&r" (retval) - : "1" (m), "r" (old), "r" (new) + : "=&z" (tmp), "=&r" (retval) + : "r" (m), "r" (old), "r" (new) : "t", "memory" ); -- GitLab From 84fdf6cda30df72994baa2496da86787fb44cbb4 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Tue, 20 Jan 2009 21:14:38 +0000 Subject: [PATCH 0599/4982] sh: Use the atomic_t "counter" member Now that atomic_t is a generic opaque type for all architectures, it is unwise to use intimate knowledge of its internals when manipulating it. Instead of relying on the "counter" member being at offset 0 from the beginning of an atomic_t, explicitly reference the member. This guards us from any changes to the layout of the beginning of the atomic_t type. Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- arch/sh/include/asm/atomic-irq.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/sh/include/asm/atomic-irq.h b/arch/sh/include/asm/atomic-irq.h index 74f7943cff6..a0b348068ca 100644 --- a/arch/sh/include/asm/atomic-irq.h +++ b/arch/sh/include/asm/atomic-irq.h @@ -11,7 +11,7 @@ static inline void atomic_add(int i, atomic_t *v) unsigned long flags; local_irq_save(flags); - *(long *)v += i; + v->counter += i; local_irq_restore(flags); } @@ -20,7 +20,7 @@ static inline void atomic_sub(int i, atomic_t *v) unsigned long flags; local_irq_save(flags); - *(long *)v -= i; + v->counter -= i; local_irq_restore(flags); } @@ -29,9 +29,9 @@ static inline int atomic_add_return(int i, atomic_t *v) unsigned long temp, flags; local_irq_save(flags); - temp = *(long *)v; + temp = v->counter; temp += i; - *(long *)v = temp; + v->counter = temp; local_irq_restore(flags); return temp; @@ -42,9 +42,9 @@ static inline int atomic_sub_return(int i, atomic_t *v) unsigned long temp, flags; local_irq_save(flags); - temp = *(long *)v; + temp = v->counter; temp -= i; - *(long *)v = temp; + v->counter = temp; local_irq_restore(flags); return temp; @@ -55,7 +55,7 @@ static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) unsigned long flags; local_irq_save(flags); - *(long *)v &= ~mask; + v->counter &= ~mask; local_irq_restore(flags); } @@ -64,7 +64,7 @@ static inline void atomic_set_mask(unsigned int mask, atomic_t *v) unsigned long flags; local_irq_save(flags); - *(long *)v |= mask; + v->counter |= mask; local_irq_restore(flags); } -- GitLab From 35c2221ba1093af77cc2164d5785a88f08a9fc57 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 29 Jan 2009 14:08:27 +1100 Subject: [PATCH 0600/4982] solos: Clean up handling of card->tx_mask a little Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 53 ++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 5e228a3f750..e7691b3328f 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -140,7 +140,7 @@ module_param(fpga_upgrade, int, 0444); static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb, struct atm_vcc *vcc); -static int fpga_tx(struct solos_card *); +static uint32_t fpga_tx(struct solos_card *); static irqreturn_t solos_irq(int irq, void *dev_id); static struct atm_vcc* find_vcc(struct atm_dev *dev, short vpi, int vci); static int list_vccs(int vci); @@ -438,8 +438,6 @@ static int send_command(struct solos_card *card, int dev, const char *buf, size_ struct sk_buff *skb; struct pkt_hdr *header; -// dev_dbg(&card->dev->dev, "size: %d\n", size); - if (size > (BUF_SIZE - sizeof(*header))) { dev_dbg(&card->dev->dev, "Command is too big. Dropping request\n"); return 0; @@ -574,9 +572,9 @@ static irqreturn_t solos_irq(int irq, void *dev_id) struct solos_card *card = dev_id; int handled = 1; - //ACK IRQ iowrite32(0, card->config_regs + IRQ_CLEAR); + /* If we're up and running, just kick the tasklet to process TX/RX */ if (card->atmdev[0]) tasklet_schedule(&card->tlet); else @@ -588,16 +586,16 @@ static irqreturn_t solos_irq(int irq, void *dev_id) void solos_bh(unsigned long card_arg) { struct solos_card *card = (void *)card_arg; - int port; uint32_t card_flags; uint32_t rx_done = 0; + int port; - card_flags = ioread32(card->config_regs + FLAGS_ADDR); - - /* The TX bits are set if the channel is busy; clear if not. We want to - invoke fpga_tx() unless _all_ the bits for active channels are set */ - if ((card_flags & card->tx_mask) != card->tx_mask) - fpga_tx(card); + /* + * Since fpga_tx() is going to need to read the flags under its lock, + * it can return them to us so that we don't have to hit PCI MMIO + * again for the same information + */ + card_flags = fpga_tx(card); for (port = 0; port < card->nr_ports; port++) { if (card_flags & (0x10 << port)) { @@ -892,9 +890,8 @@ static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb, spin_lock_irqsave(&card->tx_queue_lock, flags); old_len = skb_queue_len(&card->tx_queue[port]); skb_queue_tail(&card->tx_queue[port], skb); - if (!old_len) { + if (!old_len) card->tx_mask |= (1 << port); - } spin_unlock_irqrestore(&card->tx_queue_lock, flags); /* Theoretically we could just schedule the tasklet here, but @@ -903,9 +900,9 @@ static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb, fpga_tx(card); } -static int fpga_tx(struct solos_card *card) +static uint32_t fpga_tx(struct solos_card *card) { - uint32_t tx_pending; + uint32_t tx_pending, card_flags; uint32_t tx_started = 0; struct sk_buff *skb; struct atm_vcc *vcc; @@ -913,19 +910,24 @@ static int fpga_tx(struct solos_card *card) unsigned long flags; spin_lock_irqsave(&card->tx_lock, flags); - - tx_pending = ioread32(card->config_regs + FLAGS_ADDR) & card->tx_mask; - - dev_vdbg(&card->dev->dev, "TX Flags are %X\n", tx_pending); - - for (port = 0; port < card->nr_ports; port++) { - if (card->atmdev[port] && !(tx_pending & (1 << port))) { + + card_flags = ioread32(card->config_regs + FLAGS_ADDR); + /* + * The queue lock is required for _writing_ to tx_mask, but we're + * OK to read it here without locking. The only potential update + * that we could race with is in fpga_queue() where it sets a bit + * for a new port... but it's going to call this function again if + * it's doing that, anyway. + */ + tx_pending = card->tx_mask & ~card_flags; + + for (port = 0; tx_pending; tx_pending >>= 1, port++) { + if (tx_pending & 1) { struct sk_buff *oldskb = card->tx_skb[port]; - if (oldskb) pci_unmap_single(card->dev, SKB_CB(oldskb)->dma_addr, oldskb->len, PCI_DMA_TODEVICE); - + spin_lock(&card->tx_queue_lock); skb = skb_dequeue(&card->tx_queue[port]); if (!skb) @@ -966,8 +968,9 @@ static int fpga_tx(struct solos_card *card) if (tx_started) iowrite32(tx_started, card->config_regs + FLAGS_ADDR); + out: spin_unlock_irqrestore(&card->tx_lock, flags); - return 0; + return card_flags; } static int psend(struct atm_vcc *vcc, struct sk_buff *skb) -- GitLab From bdc54625b650bfeeb8225a2a5103a3685423e43c Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 29 Jan 2009 14:37:20 +1100 Subject: [PATCH 0601/4982] solos: Remove debugging, commented-out test code Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 52 +++-------------------------------------- 1 file changed, 3 insertions(+), 49 deletions(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index e7691b3328f..21c73b17d5f 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -813,8 +813,7 @@ static int popen(struct atm_vcc *vcc) fpga_queue(card, SOLOS_CHAN(vcc->dev), skb, NULL); -// dev_dbg(&card->dev->dev, "Open for vpi %d and vci %d on interface %d\n", vcc->vpi, vcc->vci, SOLOS_CHAN(vcc->dev)); - set_bit(ATM_VF_ADDR, &vcc->flags); // accept the vpi / vci + set_bit(ATM_VF_ADDR, &vcc->flags); set_bit(ATM_VF_READY, &vcc->flags); list_vccs(0); @@ -842,8 +841,6 @@ static void pclose(struct atm_vcc *vcc) fpga_queue(card, SOLOS_CHAN(vcc->dev), skb, NULL); -// dev_dbg(&card->dev->dev, "Close for vpi %d and vci %d on interface %d\n", vcc->vpi, vcc->vci, SOLOS_CHAN(vcc->dev)); - clear_bit(ATM_VF_ADDR, &vcc->flags); clear_bit(ATM_VF_READY, &vcc->flags); @@ -936,7 +933,7 @@ static uint32_t fpga_tx(struct solos_card *card) if (skb && !card->using_dma) { memcpy_toio(TX_BUF(card, port), skb->data, skb->len); - tx_started |= 1 << port; //Set TX full flag + tx_started |= 1 << port; oldskb = skb; /* We're done with this skb already */ } else if (skb && card->using_dma) { SKB_CB(skb)->dma_addr = pci_map_single(card->dev, skb->data, @@ -965,10 +962,10 @@ static uint32_t fpga_tx(struct solos_card *card) } } + /* For non-DMA TX, write the 'TX start' bit for all four ports simultaneously */ if (tx_started) iowrite32(tx_started, card->config_regs + FLAGS_ADDR); - out: spin_unlock_irqrestore(&card->tx_lock, flags); return card_flags; } @@ -979,9 +976,6 @@ static int psend(struct atm_vcc *vcc, struct sk_buff *skb) struct pkt_hdr *header; int pktlen; - //dev_dbg(&card->dev->dev, "psend called.\n"); - //dev_dbg(&card->dev->dev, "dev,vpi,vci = %d,%d,%d\n",SOLOS_CHAN(vcc->dev),vcc->vpi,vcc->vci); - pktlen = skb->len; if (pktlen > (BUF_SIZE - sizeof(*header))) { dev_warn(&card->dev->dev, "Length of PDU is too large. Dropping PDU.\n"); @@ -1077,11 +1071,6 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) goto out_unmap_config; } -// for(i=0;i<64 ;i+=4){ -// data32=ioread32(card->buffers + i); -// dev_dbg(&card->dev->dev, "%08lX\n",(unsigned long)data32); -// } - //Fill Config Mem with zeros for(i = 0; i < 128; i += 4) iowrite32(0, card->config_regs + i); @@ -1110,33 +1099,6 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) spin_lock_init(&card->param_queue_lock); INIT_LIST_HEAD(&card->param_queue); -/* - // Set Loopback mode - data32 = 0x00010000; - iowrite32(data32,card->config_regs + FLAGS_ADDR); -*/ -/* - // Fill Buffers with zeros - for (i = 0; i < BUF_SIZE * 8; i += 4) - iowrite32(0, card->buffers + i); -*/ -/* - for(i = 0; i < (BUF_SIZE * 1); i += 4) - iowrite32(0x12345678, card->buffers + i + (0*BUF_SIZE)); - for(i = 0; i < (BUF_SIZE * 1); i += 4) - iowrite32(0xabcdef98, card->buffers + i + (1*BUF_SIZE)); - - // Read Config Memory - printk(KERN_DEBUG "Reading Config MEM\n"); - i = 0; - for(i = 0; i < 16; i++) { - data32=ioread32(card->buffers + i*(BUF_SIZE/2)); - printk(KERN_ALERT "Addr: %lX Data: %08lX\n", - (unsigned long)(addr_start + i*(BUF_SIZE/2)), - (unsigned long)data32); - } -*/ - //dev_dbg(&card->dev->dev, "Requesting IRQ: %d\n",dev->irq); err = request_irq(dev->irq, solos_irq, IRQF_SHARED, "solos-pci", card); if (err) { @@ -1144,7 +1106,6 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) goto out_unmap_both; } - // Enable IRQs iowrite32(1, card->config_regs + IRQ_EN_ADDR); if (fpga_upgrade) @@ -1243,25 +1204,18 @@ static void fpga_remove(struct pci_dev *dev) atm_remove(card); - dev_vdbg(&dev->dev, "Freeing IRQ\n"); - // Disable IRQs from FPGA iowrite32(0, card->config_regs + IRQ_EN_ADDR); free_irq(dev->irq, card); tasklet_kill(&card->tlet); - // iowrite32(0x01,pciregs); - dev_vdbg(&dev->dev, "Unmapping PCI resource\n"); pci_iounmap(dev, card->buffers); pci_iounmap(dev, card->config_regs); - dev_vdbg(&dev->dev, "Releasing PCI Region\n"); pci_release_regions(dev); pci_disable_device(dev); pci_set_drvdata(dev, NULL); kfree(card); -// dev_dbg(&card->dev->dev, "fpga_remove\n"); - return; } static struct pci_device_id fpga_pci_tbl[] __devinitdata = { -- GitLab From a448720ca3248e8a7a426336885549d6e923fd8e Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 28 Jan 2009 15:42:23 -0800 Subject: [PATCH 0602/4982] x86: unify asm/io.h: IO_SPACE_LIMIT Impact: Cleanup (trivial unification) Move common define IO_SPACE_LIMIT from to . Signed-off-by: Jeremy Fitzhardinge Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/io.h | 1 + arch/x86/include/asm/io_32.h | 2 -- arch/x86/include/asm/io_64.h | 2 -- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index 05cfed4485f..975207c08b3 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h @@ -106,5 +106,6 @@ extern void __iomem *early_memremap(unsigned long offset, unsigned long size); extern void early_iounmap(void __iomem *addr, unsigned long size); extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys); +#define IO_SPACE_LIMIT 0xffff #endif /* _ASM_X86_IO_H */ diff --git a/arch/x86/include/asm/io_32.h b/arch/x86/include/asm/io_32.h index d8e242e1b39..e08d8ed05a1 100644 --- a/arch/x86/include/asm/io_32.h +++ b/arch/x86/include/asm/io_32.h @@ -37,8 +37,6 @@ * - Arnaldo Carvalho de Melo */ -#define IO_SPACE_LIMIT 0xffff - #define XQUAD_PORTIO_BASE 0xfe400000 #define XQUAD_PORTIO_QUAD 0x40000 /* 256k per quad. */ diff --git a/arch/x86/include/asm/io_64.h b/arch/x86/include/asm/io_64.h index 563c16270ba..1131d8ea2c6 100644 --- a/arch/x86/include/asm/io_64.h +++ b/arch/x86/include/asm/io_64.h @@ -136,8 +136,6 @@ __OUTS(b) __OUTS(w) __OUTS(l) -#define IO_SPACE_LIMIT 0xffff - #if defined(__KERNEL__) && defined(__x86_64__) #include -- GitLab From dc66ff6220f0a6c938df41add526d645852d9a75 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Thu, 22 Jan 2009 15:16:14 +0000 Subject: [PATCH 0603/4982] SH: fix start_thread and user_stack_pointer macros Fix macros start_thread and user_stack_pointer. When these macros aren't called with a variable named regs as second argument, this will result in a build failure. Signed-off-by: Roel Kluin Signed-off-by: Paul Mundt --- arch/sh/include/asm/kprobes.h | 2 +- arch/sh/include/asm/processor_32.h | 12 ++++++------ arch/sh/include/asm/processor_64.h | 14 +++++++------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h index 6078d8e551d..613644a758e 100644 --- a/arch/sh/include/asm/kprobes.h +++ b/arch/sh/include/asm/kprobes.h @@ -16,7 +16,7 @@ typedef u16 kprobe_opcode_t; ? (MAX_STACK_SIZE) \ : (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR))) -#define regs_return_value(regs) ((regs)->regs[0]) +#define regs_return_value(_regs) ((_regs)->regs[0]) #define flush_insn_slot(p) do { } while (0) #define kretprobe_blacklist_size 0 diff --git a/arch/sh/include/asm/processor_32.h b/arch/sh/include/asm/processor_32.h index d79063c5eb9..dcaed24c71f 100644 --- a/arch/sh/include/asm/processor_32.h +++ b/arch/sh/include/asm/processor_32.h @@ -108,12 +108,12 @@ extern int ubc_usercnt; /* * Do necessary setup to start up a newly executed thread. */ -#define start_thread(regs, new_pc, new_sp) \ +#define start_thread(_regs, new_pc, new_sp) \ set_fs(USER_DS); \ - regs->pr = 0; \ - regs->sr = SR_FD; /* User mode. */ \ - regs->pc = new_pc; \ - regs->regs[15] = new_sp + _regs->pr = 0; \ + _regs->sr = SR_FD; /* User mode. */ \ + _regs->pc = new_pc; \ + _regs->regs[15] = new_sp /* Forward declaration, a strange C thing */ struct task_struct; @@ -189,7 +189,7 @@ extern unsigned long get_wchan(struct task_struct *p); #define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc) #define KSTK_ESP(tsk) (task_pt_regs(tsk)->regs[15]) -#define user_stack_pointer(regs) ((regs)->regs[15]) +#define user_stack_pointer(_regs) ((_regs)->regs[15]) #if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH3) || \ defined(CONFIG_CPU_SH4) diff --git a/arch/sh/include/asm/processor_64.h b/arch/sh/include/asm/processor_64.h index 803177fcf08..5727d31b0cc 100644 --- a/arch/sh/include/asm/processor_64.h +++ b/arch/sh/include/asm/processor_64.h @@ -145,13 +145,13 @@ struct thread_struct { */ #define SR_USER (SR_MMU | SR_FD) -#define start_thread(regs, new_pc, new_sp) \ +#define start_thread(_regs, new_pc, new_sp) \ set_fs(USER_DS); \ - regs->sr = SR_USER; /* User mode. */ \ - regs->pc = new_pc - 4; /* Compensate syscall exit */ \ - regs->pc |= 1; /* Set SHmedia ! */ \ - regs->regs[18] = 0; \ - regs->regs[15] = new_sp + _regs->sr = SR_USER; /* User mode. */ \ + _regs->pc = new_pc - 4; /* Compensate syscall exit */ \ + _regs->pc |= 1; /* Set SHmedia ! */ \ + _regs->regs[18] = 0; \ + _regs->regs[15] = new_sp /* Forward declaration, a strange C thing */ struct task_struct; @@ -226,7 +226,7 @@ extern unsigned long get_wchan(struct task_struct *p); #define KSTK_EIP(tsk) ((tsk)->thread.pc) #define KSTK_ESP(tsk) ((tsk)->thread.sp) -#define user_stack_pointer(regs) ((regs)->regs[15]) +#define user_stack_pointer(_regs) ((_regs)->regs[15]) #endif /* __ASSEMBLY__ */ #endif /* __ASM_SH_PROCESSOR_64_H */ -- GitLab From 328cc6dfaadad614449eca1c75559e64c5054fea Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Wed, 28 Jan 2009 15:39:22 -0200 Subject: [PATCH 0604/4982] ALSA: AC97: Print AC97 flags in proc file to make debug it easier While debugging some code paths in AC97 codec patches and its suspend and resume functions, getting to know the flags has proved useful to follow those code paths. Signed-off-by: Thadeu Lima de Souza Cascardo Signed-off-by: Takashi Iwai --- sound/pci/ac97/ac97_proc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c index 060ea59d5f0..73b17d526c8 100644 --- a/sound/pci/ac97/ac97_proc.c +++ b/sound/pci/ac97/ac97_proc.c @@ -125,6 +125,8 @@ static void snd_ac97_proc_read_main(struct snd_ac97 *ac97, struct snd_info_buffe snd_iprintf(buffer, "PCI Subsys Device: 0x%04x\n\n", ac97->subsystem_device); + snd_iprintf(buffer, "Flags: %x\n", ac97->flags); + if ((ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23) { val = snd_ac97_read(ac97, AC97_INT_PAGING); snd_ac97_update_bits(ac97, AC97_INT_PAGING, -- GitLab From b833b5ec0411adc2255053a0e0ec536d97e5784e Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Wed, 28 Jan 2009 18:20:06 -0200 Subject: [PATCH 0605/4982] ALSA: AC97: Fix function name type in comment s/updat/update/ Signed-off-by: Thadeu Lima de Souza Cascardo Signed-off-by: Takashi Iwai --- sound/pci/ac97/ac97_codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index e2b843b4f9d..27551e963e5 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -383,7 +383,7 @@ int snd_ac97_update_bits(struct snd_ac97 *ac97, unsigned short reg, unsigned sho EXPORT_SYMBOL(snd_ac97_update_bits); -/* no lock version - see snd_ac97_updat_bits() */ +/* no lock version - see snd_ac97_update_bits() */ int snd_ac97_update_bits_nolock(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value) { -- GitLab From 955c0778723501cc16fec40501cd54b7e72d3e74 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 22 Jan 2009 09:55:31 +0000 Subject: [PATCH 0606/4982] sh: rework clocksource and sched_clock Rework and simplify the sched_clock and clocksource code. Instead of registering the clocksource in a shared file we move it into the tmu driver. Also, add code to handle sched_clock in the case of no clocksource. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/include/asm/timer.h | 4 +-- arch/sh/kernel/time_32.c | 59 +++++-------------------------- arch/sh/kernel/timers/timer-tmu.c | 10 ++++-- 3 files changed, 19 insertions(+), 54 deletions(-) diff --git a/arch/sh/include/asm/timer.h b/arch/sh/include/asm/timer.h index a7ca3a195bb..4c3b66e30af 100644 --- a/arch/sh/include/asm/timer.h +++ b/arch/sh/include/asm/timer.h @@ -9,7 +9,6 @@ struct sys_timer_ops { int (*init)(void); int (*start)(void); int (*stop)(void); - cycle_t (*read)(void); #ifndef CONFIG_GENERIC_TIME unsigned long (*get_offset)(void); #endif @@ -39,6 +38,7 @@ struct sys_timer *get_sys_timer(void); /* arch/sh/kernel/time.c */ void handle_timer_tick(void); -extern unsigned long sh_hpt_frequency; + +extern struct clocksource clocksource_sh; #endif /* __ASM_SH_TIMER_H */ diff --git a/arch/sh/kernel/time_32.c b/arch/sh/kernel/time_32.c index 8457f83242c..ca22eef669a 100644 --- a/arch/sh/kernel/time_32.c +++ b/arch/sh/kernel/time_32.c @@ -41,14 +41,6 @@ static int null_rtc_set_time(const time_t secs) return 0; } -/* - * Null high precision timer functions for systems lacking one. - */ -static cycle_t null_hpt_read(void) -{ - return 0; -} - void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time; int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time; @@ -200,42 +192,21 @@ device_initcall(timer_init_sysfs); void (*board_time_init)(void); -/* - * Shamelessly based on the MIPS and Sparc64 work. - */ -static unsigned long timer_ticks_per_nsec_quotient __read_mostly; -unsigned long sh_hpt_frequency = 0; - -#define NSEC_PER_CYC_SHIFT 10 - -static struct clocksource clocksource_sh = { +struct clocksource clocksource_sh = { .name = "SuperH", - .rating = 200, - .mask = CLOCKSOURCE_MASK(32), - .read = null_hpt_read, - .shift = 16, - .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -static void __init init_sh_clocksource(void) -{ - if (!sh_hpt_frequency || clocksource_sh.read == null_hpt_read) - return; - - clocksource_sh.mult = clocksource_hz2mult(sh_hpt_frequency, - clocksource_sh.shift); - - timer_ticks_per_nsec_quotient = - clocksource_hz2mult(sh_hpt_frequency, NSEC_PER_CYC_SHIFT); - - clocksource_register(&clocksource_sh); -} - #ifdef CONFIG_GENERIC_TIME unsigned long long sched_clock(void) { - unsigned long long ticks = clocksource_sh.read(); - return (ticks * timer_ticks_per_nsec_quotient) >> NSEC_PER_CYC_SHIFT; + unsigned long long cycles; + + /* jiffies based sched_clock if no clocksource is installed */ + if (!clocksource_sh.rating) + return (unsigned long long)jiffies * (NSEC_PER_SEC / HZ); + + cycles = clocksource_sh.read(); + return cyc2ns(&clocksource_sh, cycles); } #endif @@ -260,16 +231,4 @@ void __init time_init(void) */ sys_timer = get_sys_timer(); printk(KERN_INFO "Using %s for system timer\n", sys_timer->name); - - - if (sys_timer->ops->read) - clocksource_sh.read = sys_timer->ops->read; - - init_sh_clocksource(); - - if (sh_hpt_frequency) - printk("Using %lu.%03lu MHz high precision timer.\n", - ((sh_hpt_frequency + 500) / 1000) / 1000, - ((sh_hpt_frequency + 500) / 1000) % 1000); - } diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c index 0db3f951033..33a24fcf0a1 100644 --- a/arch/sh/kernel/timers/timer-tmu.c +++ b/arch/sh/kernel/timers/timer-tmu.c @@ -254,7 +254,14 @@ static int tmu_timer_init(void) _tmu_start(TMU1); - sh_hpt_frequency = clk_get_rate(&tmu1_clk); + clocksource_sh.rating = 200; + clocksource_sh.mask = CLOCKSOURCE_MASK(32); + clocksource_sh.read = tmu_timer_read; + clocksource_sh.shift = 10; + clocksource_sh.mult = clocksource_hz2mult(clk_get_rate(&tmu1_clk), + clocksource_sh.shift); + clocksource_sh.flags = CLOCK_SOURCE_IS_CONTINUOUS; + clocksource_register(&clocksource_sh); tmu0_clockevent.mult = div_sc(frequency, NSEC_PER_SEC, tmu0_clockevent.shift); @@ -274,7 +281,6 @@ static struct sys_timer_ops tmu_timer_ops = { .init = tmu_timer_init, .start = tmu_timer_start, .stop = tmu_timer_stop, - .read = tmu_timer_read, }; struct sys_timer tmu_timer = { -- GitLab From 70f0800133b2a6d694c10908b8673a5327b3bfd6 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 22 Jan 2009 09:55:40 +0000 Subject: [PATCH 0607/4982] sh: tmu disable support Add TMU disable support so we can use other clockevents. Also, setup the clockevent rating. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/timers/timer-tmu.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c index 33a24fcf0a1..2b62f9cff22 100644 --- a/arch/sh/kernel/timers/timer-tmu.c +++ b/arch/sh/kernel/timers/timer-tmu.c @@ -146,7 +146,14 @@ static irqreturn_t tmu_timer_interrupt(int irq, void *dummy) _tmu_clear_status(TMU0); _tmu_set_irq(TMU0,tmu0_clockevent.mode != CLOCK_EVT_MODE_ONESHOT); - evt->event_handler(evt); + switch (tmu0_clockevent.mode) { + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_PERIODIC: + evt->event_handler(evt); + break; + default: + break; + } return IRQ_HANDLED; } @@ -271,6 +278,7 @@ static int tmu_timer_init(void) clockevent_delta2ns(1, &tmu0_clockevent); tmu0_clockevent.cpumask = cpumask_of(0); + tmu0_clockevent.rating = 100; clockevents_register_device(&tmu0_clockevent); -- GitLab From 07821d3310996746a2cf1e9c705ffe64223d1112 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 22 Jan 2009 09:55:49 +0000 Subject: [PATCH 0608/4982] sh: fix no sys_timer case Handle the case with a sys_timer set to NULL. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/time_32.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/sh/kernel/time_32.c b/arch/sh/kernel/time_32.c index ca22eef669a..766554ba2a5 100644 --- a/arch/sh/kernel/time_32.c +++ b/arch/sh/kernel/time_32.c @@ -181,7 +181,12 @@ static struct sysdev_class timer_sysclass = { static int __init timer_init_sysfs(void) { - int ret = sysdev_class_register(&timer_sysclass); + int ret; + + if (!sys_timer) + return 0; + + ret = sysdev_class_register(&timer_sysclass); if (ret != 0) return ret; @@ -230,5 +235,8 @@ void __init time_init(void) * initialized for us. */ sys_timer = get_sys_timer(); + if (unlikely(!sys_timer)) + panic("System timer missing.\n"); + printk(KERN_INFO "Using %s for system timer\n", sys_timer->name); } -- GitLab From 3fb1b6ad0679ad671bd496712b2a088550ee86b2 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 22 Jan 2009 09:55:59 +0000 Subject: [PATCH 0609/4982] sh: CMT clockevent platform driver SuperH CMT clockevent driver. Both 16-bit and 32-bit CMT versions are supported, but only 32-bit is tested. This driver contains support for both clockevents and clocksources, but no unregistration is supported at this point. Works fine as clock source and/or event in periodic or oneshot mode. Tested on sh7722 and sh7723, but should work with any cpu/architecture. This version is lacking clocksource and early platform driver support for now - this to minimize the amount of dependencies. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 8 + drivers/clocksource/Makefile | 1 + drivers/clocksource/sh_cmt.c | 615 +++++++++++++++++++++++++++++++++++ include/linux/sh_cmt.h | 13 + 4 files changed, 637 insertions(+) create mode 100644 drivers/clocksource/sh_cmt.c create mode 100644 include/linux/sh_cmt.h diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index ebabe518e72..5407e1295e5 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -397,6 +397,14 @@ source "arch/sh/boards/Kconfig" menu "Timer and clock configuration" +config SH_TIMER_CMT + def_bool n + prompt "CMT support" + select GENERIC_TIME + select GENERIC_CLOCKEVENTS + help + This enables build of the CMT system timer driver. + config SH_TMU def_bool y prompt "TMU timer support" diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 1525882190f..1efb2879a94 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o obj-$(CONFIG_X86_CYCLONE_TIMER) += cyclone.o obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o +obj-$(CONFIG_SH_TIMER_CMT) += sh_cmt.o diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c new file mode 100644 index 00000000000..7783b42f691 --- /dev/null +++ b/drivers/clocksource/sh_cmt.c @@ -0,0 +1,615 @@ +/* + * SuperH Timer Support - CMT + * + * Copyright (C) 2008 Magnus Damm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct sh_cmt_priv { + void __iomem *mapbase; + struct clk *clk; + unsigned long width; /* 16 or 32 bit version of hardware block */ + unsigned long overflow_bit; + unsigned long clear_bits; + struct irqaction irqaction; + struct platform_device *pdev; + + unsigned long flags; + unsigned long match_value; + unsigned long next_match_value; + unsigned long max_match_value; + unsigned long rate; + spinlock_t lock; + struct clock_event_device ced; + unsigned long total_cycles; +}; + +static DEFINE_SPINLOCK(sh_cmt_lock); + +#define CMSTR -1 /* shared register */ +#define CMCSR 0 /* channel register */ +#define CMCNT 1 /* channel register */ +#define CMCOR 2 /* channel register */ + +static inline unsigned long sh_cmt_read(struct sh_cmt_priv *p, int reg_nr) +{ + struct sh_cmt_config *cfg = p->pdev->dev.platform_data; + void __iomem *base = p->mapbase; + unsigned long offs; + + if (reg_nr == CMSTR) { + offs = 0; + base -= cfg->channel_offset; + } else + offs = reg_nr; + + if (p->width == 16) + offs <<= 1; + else { + offs <<= 2; + if ((reg_nr == CMCNT) || (reg_nr == CMCOR)) + return ioread32(base + offs); + } + + return ioread16(base + offs); +} + +static inline void sh_cmt_write(struct sh_cmt_priv *p, int reg_nr, + unsigned long value) +{ + struct sh_cmt_config *cfg = p->pdev->dev.platform_data; + void __iomem *base = p->mapbase; + unsigned long offs; + + if (reg_nr == CMSTR) { + offs = 0; + base -= cfg->channel_offset; + } else + offs = reg_nr; + + if (p->width == 16) + offs <<= 1; + else { + offs <<= 2; + if ((reg_nr == CMCNT) || (reg_nr == CMCOR)) { + iowrite32(value, base + offs); + return; + } + } + + iowrite16(value, base + offs); +} + +static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p, + int *has_wrapped) +{ + unsigned long v1, v2, v3; + + /* Make sure the timer value is stable. Stolen from acpi_pm.c */ + do { + v1 = sh_cmt_read(p, CMCNT); + v2 = sh_cmt_read(p, CMCNT); + v3 = sh_cmt_read(p, CMCNT); + } while (unlikely((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1) + || (v3 > v1 && v3 < v2))); + + *has_wrapped = sh_cmt_read(p, CMCSR) & p->overflow_bit; + return v2; +} + + +static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) +{ + struct sh_cmt_config *cfg = p->pdev->dev.platform_data; + unsigned long flags, value; + + /* start stop register shared by multiple timer channels */ + spin_lock_irqsave(&sh_cmt_lock, flags); + value = sh_cmt_read(p, CMSTR); + + if (start) + value |= 1 << cfg->timer_bit; + else + value &= ~(1 << cfg->timer_bit); + + sh_cmt_write(p, CMSTR, value); + spin_unlock_irqrestore(&sh_cmt_lock, flags); +} + +static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) +{ + struct sh_cmt_config *cfg = p->pdev->dev.platform_data; + int ret; + + /* enable clock */ + ret = clk_enable(p->clk); + if (ret) { + pr_err("sh_cmt: cannot enable clock \"%s\"\n", cfg->clk); + return ret; + } + *rate = clk_get_rate(p->clk) / 8; + + /* make sure channel is disabled */ + sh_cmt_start_stop_ch(p, 0); + + /* configure channel, periodic mode and maximum timeout */ + if (p->width == 16) + sh_cmt_write(p, CMCSR, 0); + else + sh_cmt_write(p, CMCSR, 0x01a4); + + sh_cmt_write(p, CMCOR, 0xffffffff); + sh_cmt_write(p, CMCNT, 0); + + /* enable channel */ + sh_cmt_start_stop_ch(p, 1); + return 0; +} + +static void sh_cmt_disable(struct sh_cmt_priv *p) +{ + /* disable channel */ + sh_cmt_start_stop_ch(p, 0); + + /* stop clock */ + clk_disable(p->clk); +} + +/* private flags */ +#define FLAG_CLOCKEVENT (1 << 0) +#define FLAG_CLOCKSOURCE (1 << 1) +#define FLAG_REPROGRAM (1 << 2) +#define FLAG_SKIPEVENT (1 << 3) +#define FLAG_IRQCONTEXT (1 << 4) + +static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p, + int absolute) +{ + unsigned long new_match; + unsigned long value = p->next_match_value; + unsigned long delay = 0; + unsigned long now = 0; + int has_wrapped; + + now = sh_cmt_get_counter(p, &has_wrapped); + p->flags |= FLAG_REPROGRAM; /* force reprogram */ + + if (has_wrapped) { + /* we're competing with the interrupt handler. + * -> let the interrupt handler reprogram the timer. + * -> interrupt number two handles the event. + */ + p->flags |= FLAG_SKIPEVENT; + return; + } + + if (absolute) + now = 0; + + do { + /* reprogram the timer hardware, + * but don't save the new match value yet. + */ + new_match = now + value + delay; + if (new_match > p->max_match_value) + new_match = p->max_match_value; + + sh_cmt_write(p, CMCOR, new_match); + + now = sh_cmt_get_counter(p, &has_wrapped); + if (has_wrapped && (new_match > p->match_value)) { + /* we are changing to a greater match value, + * so this wrap must be caused by the counter + * matching the old value. + * -> first interrupt reprograms the timer. + * -> interrupt number two handles the event. + */ + p->flags |= FLAG_SKIPEVENT; + break; + } + + if (has_wrapped) { + /* we are changing to a smaller match value, + * so the wrap must be caused by the counter + * matching the new value. + * -> save programmed match value. + * -> let isr handle the event. + */ + p->match_value = new_match; + break; + } + + /* be safe: verify hardware settings */ + if (now < new_match) { + /* timer value is below match value, all good. + * this makes sure we won't miss any match events. + * -> save programmed match value. + * -> let isr handle the event. + */ + p->match_value = new_match; + break; + } + + /* the counter has reached a value greater + * than our new match value. and since the + * has_wrapped flag isn't set we must have + * programmed a too close event. + * -> increase delay and retry. + */ + if (delay) + delay <<= 1; + else + delay = 1; + + if (!delay) + pr_warning("sh_cmt: too long delay\n"); + + } while (delay); +} + +static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta) +{ + unsigned long flags; + + if (delta > p->max_match_value) + pr_warning("sh_cmt: delta out of range\n"); + + spin_lock_irqsave(&p->lock, flags); + p->next_match_value = delta; + sh_cmt_clock_event_program_verify(p, 0); + spin_unlock_irqrestore(&p->lock, flags); +} + +static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id) +{ + struct sh_cmt_priv *p = dev_id; + + /* clear flags */ + sh_cmt_write(p, CMCSR, sh_cmt_read(p, CMCSR) & p->clear_bits); + + /* update clock source counter to begin with if enabled + * the wrap flag should be cleared by the timer specific + * isr before we end up here. + */ + if (p->flags & FLAG_CLOCKSOURCE) + p->total_cycles += p->match_value; + + if (!(p->flags & FLAG_REPROGRAM)) + p->next_match_value = p->max_match_value; + + p->flags |= FLAG_IRQCONTEXT; + + if (p->flags & FLAG_CLOCKEVENT) { + if (!(p->flags & FLAG_SKIPEVENT)) { + if (p->ced.mode == CLOCK_EVT_MODE_ONESHOT) { + p->next_match_value = p->max_match_value; + p->flags |= FLAG_REPROGRAM; + } + + p->ced.event_handler(&p->ced); + } + } + + p->flags &= ~FLAG_SKIPEVENT; + + if (p->flags & FLAG_REPROGRAM) { + p->flags &= ~FLAG_REPROGRAM; + sh_cmt_clock_event_program_verify(p, 1); + + if (p->flags & FLAG_CLOCKEVENT) + if ((p->ced.mode == CLOCK_EVT_MODE_SHUTDOWN) + || (p->match_value == p->next_match_value)) + p->flags &= ~FLAG_REPROGRAM; + } + + p->flags &= ~FLAG_IRQCONTEXT; + + return IRQ_HANDLED; +} + +static int sh_cmt_start(struct sh_cmt_priv *p, unsigned long flag) +{ + int ret = 0; + unsigned long flags; + + spin_lock_irqsave(&p->lock, flags); + + if (!(p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE))) + ret = sh_cmt_enable(p, &p->rate); + + if (ret) + goto out; + p->flags |= flag; + + /* setup timeout if no clockevent */ + if ((flag == FLAG_CLOCKSOURCE) && (!(p->flags & FLAG_CLOCKEVENT))) + sh_cmt_set_next(p, p->max_match_value); + out: + spin_unlock_irqrestore(&p->lock, flags); + + return ret; +} + +static void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag) +{ + unsigned long flags; + unsigned long f; + + spin_lock_irqsave(&p->lock, flags); + + f = p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE); + p->flags &= ~flag; + + if (f && !(p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE))) + sh_cmt_disable(p); + + /* adjust the timeout to maximum if only clocksource left */ + if ((flag == FLAG_CLOCKEVENT) && (p->flags & FLAG_CLOCKSOURCE)) + sh_cmt_set_next(p, p->max_match_value); + + spin_unlock_irqrestore(&p->lock, flags); +} + +static struct sh_cmt_priv *ced_to_sh_cmt(struct clock_event_device *ced) +{ + return container_of(ced, struct sh_cmt_priv, ced); +} + +static void sh_cmt_clock_event_start(struct sh_cmt_priv *p, int periodic) +{ + struct clock_event_device *ced = &p->ced; + + sh_cmt_start(p, FLAG_CLOCKEVENT); + + /* TODO: calculate good shift from rate and counter bit width */ + + ced->shift = 32; + ced->mult = div_sc(p->rate, NSEC_PER_SEC, ced->shift); + ced->max_delta_ns = clockevent_delta2ns(p->max_match_value, ced); + ced->min_delta_ns = clockevent_delta2ns(0x1f, ced); + + if (periodic) + sh_cmt_set_next(p, (p->rate + HZ/2) / HZ); + else + sh_cmt_set_next(p, p->max_match_value); +} + +static void sh_cmt_clock_event_mode(enum clock_event_mode mode, + struct clock_event_device *ced) +{ + struct sh_cmt_priv *p = ced_to_sh_cmt(ced); + + /* deal with old setting first */ + switch (ced->mode) { + case CLOCK_EVT_MODE_PERIODIC: + case CLOCK_EVT_MODE_ONESHOT: + sh_cmt_stop(p, FLAG_CLOCKEVENT); + break; + default: + break; + } + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + pr_info("sh_cmt: %s used for periodic clock events\n", + ced->name); + sh_cmt_clock_event_start(p, 1); + break; + case CLOCK_EVT_MODE_ONESHOT: + pr_info("sh_cmt: %s used for oneshot clock events\n", + ced->name); + sh_cmt_clock_event_start(p, 0); + break; + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_UNUSED: + sh_cmt_stop(p, FLAG_CLOCKEVENT); + break; + default: + break; + } +} + +static int sh_cmt_clock_event_next(unsigned long delta, + struct clock_event_device *ced) +{ + struct sh_cmt_priv *p = ced_to_sh_cmt(ced); + + BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT); + if (likely(p->flags & FLAG_IRQCONTEXT)) + p->next_match_value = delta; + else + sh_cmt_set_next(p, delta); + + return 0; +} + +static void sh_cmt_register_clockevent(struct sh_cmt_priv *p, + char *name, unsigned long rating) +{ + struct clock_event_device *ced = &p->ced; + + memset(ced, 0, sizeof(*ced)); + + ced->name = name; + ced->features = CLOCK_EVT_FEAT_PERIODIC; + ced->features |= CLOCK_EVT_FEAT_ONESHOT; + ced->rating = rating; + ced->cpumask = cpumask_of(0); + ced->set_next_event = sh_cmt_clock_event_next; + ced->set_mode = sh_cmt_clock_event_mode; + + pr_info("sh_cmt: %s used for clock events\n", ced->name); + ced->mult = 1; /* work around misplaced WARN_ON() in clockevents.c */ + clockevents_register_device(ced); +} + +int sh_cmt_register(struct sh_cmt_priv *p, char *name, + unsigned long clockevent_rating, + unsigned long clocksource_rating) +{ + if (p->width == (sizeof(p->max_match_value) * 8)) + p->max_match_value = ~0; + else + p->max_match_value = (1 << p->width) - 1; + + p->match_value = p->max_match_value; + spin_lock_init(&p->lock); + + if (clockevent_rating) + sh_cmt_register_clockevent(p, name, clockevent_rating); + + return 0; +} + +static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) +{ + struct sh_cmt_config *cfg = pdev->dev.platform_data; + struct resource *res; + int irq, ret; + ret = -ENXIO; + + memset(p, 0, sizeof(*p)); + p->pdev = pdev; + + if (!cfg) { + dev_err(&p->pdev->dev, "missing platform data\n"); + goto err0; + } + + platform_set_drvdata(pdev, p); + + res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&p->pdev->dev, "failed to get I/O memory\n"); + goto err0; + } + + irq = platform_get_irq(p->pdev, 0); + if (irq < 0) { + dev_err(&p->pdev->dev, "failed to get irq\n"); + goto err0; + } + + /* map memory, let mapbase point to our channel */ + p->mapbase = ioremap_nocache(res->start, resource_size(res)); + if (p->mapbase == NULL) { + pr_err("sh_cmt: failed to remap I/O memory\n"); + goto err0; + } + + /* request irq using setup_irq() (too early for request_irq()) */ + p->irqaction.name = cfg->name; + p->irqaction.handler = sh_cmt_interrupt; + p->irqaction.dev_id = p; + p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL; + p->irqaction.mask = CPU_MASK_NONE; + ret = setup_irq(irq, &p->irqaction); + if (ret) { + pr_err("sh_cmt: failed to request irq %d\n", irq); + goto err1; + } + + /* get hold of clock */ + p->clk = clk_get(&p->pdev->dev, cfg->clk); + if (IS_ERR(p->clk)) { + pr_err("sh_cmt: cannot get clock \"%s\"\n", cfg->clk); + ret = PTR_ERR(p->clk); + goto err2; + } + + if (resource_size(res) == 6) { + p->width = 16; + p->overflow_bit = 0x80; + p->clear_bits = ~0xc0; + } else { + p->width = 32; + p->overflow_bit = 0x8000; + p->clear_bits = ~0xc000; + } + + return sh_cmt_register(p, cfg->name, + cfg->clockevent_rating, + cfg->clocksource_rating); + err2: + free_irq(irq, p); + err1: + iounmap(p->mapbase); + err0: + return ret; +} + +static int __devinit sh_cmt_probe(struct platform_device *pdev) +{ + struct sh_cmt_priv *p = platform_get_drvdata(pdev); + int ret; + + p = kmalloc(sizeof(*p), GFP_KERNEL); + if (p == NULL) { + dev_err(&pdev->dev, "failed to allocate driver data\n"); + return -ENOMEM; + } + + ret = sh_cmt_setup(p, pdev); + if (ret) { + kfree(p); + + platform_set_drvdata(pdev, NULL); + } + return ret; +} + +static int __devexit sh_cmt_remove(struct platform_device *pdev) +{ + return -EBUSY; /* cannot unregister clockevent and clocksource */ +} + +static struct platform_driver sh_cmt_device_driver = { + .probe = sh_cmt_probe, + .remove = __devexit_p(sh_cmt_remove), + .driver = { + .name = "sh_cmt", + } +}; + +static int __init sh_cmt_init(void) +{ + return platform_driver_register(&sh_cmt_device_driver); +} + +static void __exit sh_cmt_exit(void) +{ + platform_driver_unregister(&sh_cmt_device_driver); +} + +module_init(sh_cmt_init); +module_exit(sh_cmt_exit); + +MODULE_AUTHOR("Magnus Damm"); +MODULE_DESCRIPTION("SuperH CMT Timer Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/sh_cmt.h b/include/linux/sh_cmt.h new file mode 100644 index 00000000000..68cacde5954 --- /dev/null +++ b/include/linux/sh_cmt.h @@ -0,0 +1,13 @@ +#ifndef __SH_CMT_H__ +#define __SH_CMT_H__ + +struct sh_cmt_config { + char *name; + unsigned long channel_offset; + int timer_bit; + char *clk; + unsigned long clockevent_rating; + unsigned long clocksource_rating; +}; + +#endif /* __SH_CMT_H__ */ -- GitLab From 424f59d04d7450555ef2bf1eb4a5e2cd2ecf08cd Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 22 Jan 2009 09:56:09 +0000 Subject: [PATCH 0610/4982] sh: CMT platform data for sh7723/sh7722/sh7366/sh7343 CMT platform data for SuperH Mobile sh7723/sh7722/sh7343/sh7366. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/setup-sh7343.c | 34 ++++++++++++++++++++++++++ arch/sh/kernel/cpu/sh4a/setup-sh7366.c | 34 ++++++++++++++++++++++++++ arch/sh/kernel/cpu/sh4a/setup-sh7722.c | 34 ++++++++++++++++++++++++++ arch/sh/kernel/cpu/sh4a/setup-sh7723.c | 34 ++++++++++++++++++++++++++ 4 files changed, 136 insertions(+) diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c index 4ff4dc64520..c1549382c87 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c @@ -12,6 +12,7 @@ #include #include #include +#include #include static struct resource iic0_resources[] = { @@ -140,6 +141,38 @@ static struct platform_device jpu_device = { .num_resources = ARRAY_SIZE(jpu_resources), }; +static struct sh_cmt_config cmt_platform_data = { + .name = "CMT", + .channel_offset = 0x60, + .timer_bit = 5, + .clk = "cmt0", + .clockevent_rating = 125, + .clocksource_rating = 200, +}; + +static struct resource cmt_resources[] = { + [0] = { + .name = "CMT", + .start = 0x044a0060, + .end = 0x044a006b, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 104, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device cmt_device = { + .name = "sh_cmt", + .id = 0, + .dev = { + .platform_data = &cmt_platform_data, + }, + .resource = cmt_resources, + .num_resources = ARRAY_SIZE(cmt_resources), +}; + static struct plat_sci_port sci_platform_data[] = { { .mapbase = 0xffe00000, @@ -175,6 +208,7 @@ static struct platform_device sci_device = { }; static struct platform_device *sh7343_devices[] __initdata = { + &cmt_device, &iic0_device, &iic1_device, &sci_device, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c index 839ae97a7fd..93ecf8ed5c6 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c @@ -14,6 +14,7 @@ #include #include #include +#include #include static struct resource iic_resources[] = { @@ -147,6 +148,38 @@ static struct platform_device veu1_device = { .num_resources = ARRAY_SIZE(veu1_resources), }; +static struct sh_cmt_config cmt_platform_data = { + .name = "CMT", + .channel_offset = 0x60, + .timer_bit = 5, + .clk = "cmt0", + .clockevent_rating = 125, + .clocksource_rating = 200, +}; + +static struct resource cmt_resources[] = { + [0] = { + .name = "CMT", + .start = 0x044a0060, + .end = 0x044a006b, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 104, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device cmt_device = { + .name = "sh_cmt", + .id = 0, + .dev = { + .platform_data = &cmt_platform_data, + }, + .resource = cmt_resources, + .num_resources = ARRAY_SIZE(cmt_resources), +}; + static struct plat_sci_port sci_platform_data[] = { { .mapbase = 0xffe00000, @@ -167,6 +200,7 @@ static struct platform_device sci_device = { }; static struct platform_device *sh7366_devices[] __initdata = { + &cmt_device, &iic_device, &sci_device, &usb_host_device, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c index 5146afc156e..0e5d204bc79 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -176,6 +177,38 @@ static struct platform_device jpu_device = { .num_resources = ARRAY_SIZE(jpu_resources), }; +static struct sh_cmt_config cmt_platform_data = { + .name = "CMT", + .channel_offset = 0x60, + .timer_bit = 5, + .clk = "cmt0", + .clockevent_rating = 125, + .clocksource_rating = 200, +}; + +static struct resource cmt_resources[] = { + [0] = { + .name = "CMT", + .start = 0x044a0060, + .end = 0x044a006b, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 104, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device cmt_device = { + .name = "sh_cmt", + .id = 0, + .dev = { + .platform_data = &cmt_platform_data, + }, + .resource = cmt_resources, + .num_resources = ARRAY_SIZE(cmt_resources), +}; + static struct plat_sci_port sci_platform_data[] = { { .mapbase = 0xffe00000, @@ -209,6 +242,7 @@ static struct platform_device sci_device = { }; static struct platform_device *sh7722_devices[] __initdata = { + &cmt_device, &rtc_device, &usbf_device, &iic_device, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c index 849770d780a..5338dacbcfb 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -100,6 +101,38 @@ static struct platform_device veu1_device = { .num_resources = ARRAY_SIZE(veu1_resources), }; +static struct sh_cmt_config cmt_platform_data = { + .name = "CMT", + .channel_offset = 0x60, + .timer_bit = 5, + .clk = "cmt0", + .clockevent_rating = 125, + .clocksource_rating = 200, +}; + +static struct resource cmt_resources[] = { + [0] = { + .name = "CMT", + .start = 0x044a0060, + .end = 0x044a006b, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 104, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device cmt_device = { + .name = "sh_cmt", + .id = 0, + .dev = { + .platform_data = &cmt_platform_data, + }, + .resource = cmt_resources, + .num_resources = ARRAY_SIZE(cmt_resources), +}; + static struct plat_sci_port sci_platform_data[] = { { .mapbase = 0xffe00000, @@ -221,6 +254,7 @@ static struct platform_device iic_device = { }; static struct platform_device *sh7723_devices[] __initdata = { + &cmt_device, &sci_device, &rtc_device, &iic_device, -- GitLab From f5ad881b425616741bf8696f70b2749abe54a936 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 29 Jan 2009 18:08:58 +0900 Subject: [PATCH 0611/4982] sh: Use SYS_SUPPORTS_CMT for managing CMT timer dependencies. Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 5407e1295e5..5784bcec1a1 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -107,6 +107,9 @@ config SYS_SUPPORTS_NUMA config SYS_SUPPORTS_PCI bool +config SYS_SUPPORTS_CMT + bool + config STACKTRACE_SUPPORT def_bool y @@ -188,6 +191,7 @@ choice config CPU_SUBTYPE_SH7619 bool "Support SH7619 processor" select CPU_SH2 + select SYS_SUPPORTS_CMT # SH-2A Processor Support @@ -200,15 +204,18 @@ config CPU_SUBTYPE_SH7203 bool "Support SH7203 processor" select CPU_SH2A select CPU_HAS_FPU + select SYS_SUPPORTS_CMT config CPU_SUBTYPE_SH7206 bool "Support SH7206 processor" select CPU_SH2A + select SYS_SUPPORTS_CMT config CPU_SUBTYPE_SH7263 bool "Support SH7263 processor" select CPU_SH2A select CPU_HAS_FPU + select SYS_SUPPORTS_CMT config CPU_SUBTYPE_MXG bool "Support MX-G processor" @@ -324,6 +331,7 @@ config CPU_SUBTYPE_SH7723 select CPU_SH4A select CPU_SHX2 select ARCH_SPARSEMEM_ENABLE + select SYS_SUPPORTS_CMT help Select SH7723 if you have an SH-MobileR2 CPU. @@ -362,6 +370,7 @@ config CPU_SUBTYPE_SHX3 config CPU_SUBTYPE_SH7343 bool "Support SH7343 processor" select CPU_SH4AL_DSP + select SYS_SUPPORTS_CMT config CPU_SUBTYPE_SH7722 bool "Support SH7722 processor" @@ -369,6 +378,7 @@ config CPU_SUBTYPE_SH7722 select CPU_SHX2 select ARCH_SPARSEMEM_ENABLE select SYS_SUPPORTS_NUMA + select SYS_SUPPORTS_CMT config CPU_SUBTYPE_SH7366 bool "Support SH7366 processor" @@ -376,6 +386,7 @@ config CPU_SUBTYPE_SH7366 select CPU_SHX2 select ARCH_SPARSEMEM_ENABLE select SYS_SUPPORTS_NUMA + select SYS_SUPPORTS_CMT # SH-5 Processor Support @@ -397,34 +408,36 @@ source "arch/sh/boards/Kconfig" menu "Timer and clock configuration" -config SH_TIMER_CMT - def_bool n - prompt "CMT support" - select GENERIC_TIME - select GENERIC_CLOCKEVENTS - help - This enables build of the CMT system timer driver. - config SH_TMU - def_bool y - prompt "TMU timer support" + bool "TMU timer support" depends on CPU_SH3 || CPU_SH4 + default y select GENERIC_TIME select GENERIC_CLOCKEVENTS help This enables the use of the TMU as the system timer. config SH_CMT - def_bool y - prompt "CMT timer support" - depends on CPU_SH2 && !CPU_SUBTYPE_MXG + bool "CMT timer support" + depends on SYS_SUPPORTS_CMT + default y help This enables the use of the CMT as the system timer. +# +# Support for the new-style CMT driver. This will replace SH_CMT +# once its other dependencies are merged. +# +config SH_TIMER_CMT + bool "CMT clockevents driver" + depends on SYS_SUPPORTS_CMT && !SH_CMT + select GENERIC_TIME + select GENERIC_CLOCKEVENTS + config SH_MTU2 - def_bool n - prompt "MTU2 timer support" + bool "MTU2 timer support" depends on CPU_SH2A + default y help This enables the use of the MTU2 as the system timer. -- GitLab From d63f3a5857906851b9c1a39e3871a97f4acc1005 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 29 Jan 2009 18:10:13 +0900 Subject: [PATCH 0612/4982] sh: Fix up MTU2 support for SH7203. Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 3 ++- arch/sh/kernel/timers/timer-mtu2.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 5784bcec1a1..c6faad734e5 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -447,7 +447,8 @@ config SH_TIMER_IRQ CPU_SUBTYPE_SH7763 default "86" if CPU_SUBTYPE_SH7619 default "140" if CPU_SUBTYPE_SH7206 - default "142" if CPU_SUBTYPE_SH7203 + default "142" if CPU_SUBTYPE_SH7203 && SH_CMT + default "153" if CPU_SUBTYPE_SH7203 && SH_MTU2 default "238" if CPU_SUBTYPE_MXG default "16" diff --git a/arch/sh/kernel/timers/timer-mtu2.c b/arch/sh/kernel/timers/timer-mtu2.c index c3d237e1d56..9a77ae86b40 100644 --- a/arch/sh/kernel/timers/timer-mtu2.c +++ b/arch/sh/kernel/timers/timer-mtu2.c @@ -35,7 +35,8 @@ #define MTU2_TSR_1 0xfffe4385 #define MTU2_TCNT_1 0xfffe4386 /* 16-bit counter */ -#if defined(CONFIG_CPU_SUBTYPE_SH7201) +#if defined(CONFIG_CPU_SUBTYPE_SH7201) || \ + defined(CONFIG_CPU_SUBTYPE_SH7203) #define MTU2_TGRA_1 0xfffe4388 #else #define MTU2_TGRA_1 0xfffe438a -- GitLab From c161e40f45d32b48f8facbee17720e708607002f Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 29 Jan 2009 18:11:25 +0900 Subject: [PATCH 0613/4982] sh: Don't enable GENERIC_TIME for the CMT clockevent driver yet. GENERIC_TIME still depends on the clocksource bits being there, which is presently not supported. This allows the CMT clockevent driver to be used alongside alternate system timers that do not yet provide a clocksource of their own (MTU2 and so on in the case of SH-2A). Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 1 - arch/sh/kernel/time_32.c | 2 -- 2 files changed, 3 deletions(-) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index c6faad734e5..50c992444e5 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -431,7 +431,6 @@ config SH_CMT config SH_TIMER_CMT bool "CMT clockevents driver" depends on SYS_SUPPORTS_CMT && !SH_CMT - select GENERIC_TIME select GENERIC_CLOCKEVENTS config SH_MTU2 diff --git a/arch/sh/kernel/time_32.c b/arch/sh/kernel/time_32.c index 766554ba2a5..c34e1e0f9b0 100644 --- a/arch/sh/kernel/time_32.c +++ b/arch/sh/kernel/time_32.c @@ -104,7 +104,6 @@ int do_settimeofday(struct timespec *tv) EXPORT_SYMBOL(do_settimeofday); #endif /* !CONFIG_GENERIC_TIME */ -#ifndef CONFIG_GENERIC_CLOCKEVENTS /* last time the RTC clock got updated */ static long last_rtc_update; @@ -148,7 +147,6 @@ void handle_timer_tick(void) update_process_times(user_mode(get_irq_regs())); #endif } -#endif /* !CONFIG_GENERIC_CLOCKEVENTS */ #ifdef CONFIG_PM int timer_suspend(struct sys_device *dev, pm_message_t state) -- GitLab From 56305757f0b64b7d5dd02fd54c6dfc0989868f31 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Thu, 29 Jan 2009 11:44:24 +0100 Subject: [PATCH 0614/4982] ALSA: sscape: update Kconfig description about SoundScape cards The SoundScape driver handles more cards then described. Signed-off-by: Takashi Iwai --- sound/isa/Kconfig | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index ce0aa044e27..542c1ead14b 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig @@ -377,14 +377,17 @@ config SND_SGALAXY will be called snd-sgalaxy. config SND_SSCAPE - tristate "Ensoniq SoundScape PnP driver" + tristate "Ensoniq SoundScape driver" select SND_HWDEP select SND_MPU401_UART select SND_WSS_LIB help - Say Y here to include support for Ensoniq SoundScape PnP + Say Y here to include support for Ensoniq SoundScape soundcards. + The PCM audio is supported on SoundScape Classic, Elite, PnP + and VIVO cards. The MIDI support is very experimental. + To compile this driver as a module, choose M here: the module will be called snd-sscape. -- GitLab From 0a898e6e500ec8ab98000896fe243c4c0e91c72a Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Thu, 29 Jan 2009 11:46:45 +0100 Subject: [PATCH 0615/4982] ALSA: gus: update debug messages Convert some of them to snd_printdd() and update arguments to make them compilable. Signed-off-by: Takashi Iwai --- sound/isa/gus/gus_dma.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/sound/isa/gus/gus_dma.c b/sound/isa/gus/gus_dma.c index f45f6116c77..cf8cd3c26a5 100644 --- a/sound/isa/gus/gus_dma.c +++ b/sound/isa/gus/gus_dma.c @@ -45,7 +45,8 @@ static void snd_gf1_dma_program(struct snd_gus_card * gus, unsigned char dma_cmd; unsigned int address_high; - // snd_printk("dma_transfer: addr=0x%x, buf=0x%lx, count=0x%x\n", addr, (long) buf, count); + snd_printdd("dma_transfer: addr=0x%x, buf=0x%lx, count=0x%x\n", + addr, buf_addr, count); if (gus->gf1.dma1 > 3) { if (gus->gf1.enh_mode) { @@ -142,7 +143,9 @@ static void snd_gf1_dma_interrupt(struct snd_gus_card * gus) snd_gf1_dma_program(gus, block->addr, block->buf_addr, block->count, (unsigned short) block->cmd); kfree(block); #if 0 - printk("program dma (IRQ) - addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", addr, (long) buffer, count, cmd); + snd_printd(KERN_DEBUG "program dma (IRQ) - " + "addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", + block->addr, block->buf_addr, block->count, block->cmd); #endif } @@ -203,13 +206,16 @@ int snd_gf1_dma_transfer_block(struct snd_gus_card * gus, } *block = *__block; block->next = NULL; -#if 0 - printk("addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", block->addr, (long) block->buffer, block->count, block->cmd); -#endif -#if 0 - printk("gus->gf1.dma_data_pcm_last = 0x%lx\n", (long)gus->gf1.dma_data_pcm_last); - printk("gus->gf1.dma_data_pcm = 0x%lx\n", (long)gus->gf1.dma_data_pcm); -#endif + + snd_printdd("addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", + block->addr, (long) block->buffer, block->count, + block->cmd); + + snd_printdd("gus->gf1.dma_data_pcm_last = 0x%lx\n", + (long)gus->gf1.dma_data_pcm_last); + snd_printdd("gus->gf1.dma_data_pcm = 0x%lx\n", + (long)gus->gf1.dma_data_pcm); + spin_lock_irqsave(&gus->dma_lock, flags); if (synth) { if (gus->gf1.dma_data_synth_last) { -- GitLab From c97dff84e0d9a4e0b7048e033d33511e3897c859 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Thu, 29 Jan 2009 11:48:14 +0100 Subject: [PATCH 0616/4982] ALSA: cmi8330: add MPU-401 support Add MPU-401 port support for the chip. Also, update some error messages and description. Signed-off-by: Takashi Iwai --- sound/isa/Kconfig | 1 + sound/isa/cmi8330.c | 42 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index be2d377ff90..5915dc41c0e 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig @@ -95,6 +95,7 @@ config SND_CMI8330 select SND_WSS_LIB select SND_SB16_DSP select SND_OPL3_LIB + select SND_MPU401_UART help Say Y here to include support for soundcards based on the C-Media CMI8330 chip. diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index 11543795741..9ca8122f7ba 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -31,11 +31,11 @@ * To quickly load the module, * * modprobe -a snd-cmi8330 sbport=0x220 sbirq=5 sbdma8=1 - * sbdma16=5 wssport=0x530 wssirq=11 wssdma=0 + * sbdma16=5 wssport=0x530 wssirq=11 wssdma=0 fmport=0x388 * * This card has two mixers and two PCM devices. I've cheesed it such * that recording and playback can be done through the same device. - * The driver "magically" routes the capturing to the AD1848 codec, + * The driver "magically" routes the capturing to the CMI8330 codec, * and playback to the SB16 codec. This allows for full-duplex mode * to some extent. * The utilities in alsa-utils are aware of both devices, so passing @@ -52,6 +52,7 @@ #include #include #include +#include #include #include @@ -81,6 +82,8 @@ static long wssport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; static int wssirq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; static int wssdma[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; static long fmport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; +static long mpuport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; +static int mpuirq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for CMI8330 soundcard."); @@ -111,6 +114,10 @@ MODULE_PARM_DESC(wssdma, "DMA for CMI8330 WSS driver."); module_param_array(fmport, long, NULL, 0444); MODULE_PARM_DESC(fmport, "FM port # for CMI8330 driver."); +module_param_array(mpuport, long, NULL, 0444); +MODULE_PARM_DESC(mpuport, "MPU-401 port # for CMI8330 driver."); +module_param_array(mpuirq, int, NULL, 0444); +MODULE_PARM_DESC(mpuirq, "IRQ # for CMI8330 MPU-401 port."); #ifdef CONFIG_PNP static int isa_registered; static int pnp_registered; @@ -153,6 +160,7 @@ struct snd_cmi8330 { #ifdef CONFIG_PNP struct pnp_dev *cap; struct pnp_dev *play; + struct pnp_dev *mpu; #endif struct snd_card *card; struct snd_wss *wss; @@ -169,7 +177,7 @@ struct snd_cmi8330 { #ifdef CONFIG_PNP static struct pnp_card_device_id snd_cmi8330_pnpids[] = { - { .id = "CMI0001", .devs = { { "@@@0001" }, { "@X@0001" } } }, + { .id = "CMI0001", .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } } }, { .id = "" } }; @@ -329,11 +337,15 @@ static int __devinit snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard, if (acard->play == NULL) return -EBUSY; + acard->mpu = pnp_request_card_device(card, id->devs[2].id, NULL); + if (acard->play == NULL) + return -EBUSY; + pdev = acard->cap; err = pnp_activate_dev(pdev); if (err < 0) { - snd_printk(KERN_ERR "CMI8330/C3D (AD1848) PnP configure failure\n"); + snd_printk(KERN_ERR "CMI8330/C3D PnP configure failure\n"); return -EBUSY; } wssport[dev] = pnp_port_start(pdev, 0); @@ -354,6 +366,17 @@ static int __devinit snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard, sbdma16[dev] = pnp_dma(pdev, 1); sbirq[dev] = pnp_irq(pdev, 0); + /* allocate MPU-401 resources */ + pdev = acard->mpu; + + err = pnp_activate_dev(pdev); + if (err < 0) { + snd_printk(KERN_ERR + "CMI8330/C3D (MPU-401) PnP configure failure\n"); + return -EBUSY; + } + mpuport[dev] = pnp_port_start(pdev, 0); + mpuirq[dev] = pnp_irq(pdev, 0); return 0; } #endif @@ -502,11 +525,11 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) wssdma[dev], -1, WSS_HW_DETECT, 0, &acard->wss); if (err < 0) { - snd_printk(KERN_ERR PFX "(AD1848) device busy??\n"); + snd_printk(KERN_ERR PFX "(CMI8330) device busy??\n"); return err; } if (acard->wss->hardware != WSS_HW_CMI8330) { - snd_printk(KERN_ERR PFX "(AD1848) not found during probe\n"); + snd_printk(KERN_ERR PFX "(CMI8330) not found during probe\n"); return -ENODEV; } @@ -552,6 +575,13 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) } } + if (mpuport[dev] != SNDRV_AUTO_PORT) { + if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, + mpuport[dev], 0, mpuirq[dev], + IRQF_DISABLED, NULL) < 0) + printk(KERN_ERR PFX "no MPU-401 device at 0x%lx.\n", + mpuport[dev]); + } strcpy(card->driver, "CMI8330/C3D"); strcpy(card->shortname, "C-Media CMI8330/C3D"); -- GitLab From 9e128fddcc589db4e7d9e8328f656ae4a21a2808 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 29 Jan 2009 11:49:10 +0100 Subject: [PATCH 0617/4982] ALSA: Add missing description of snd-cmi8330 module parameters Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 841a9365d5f..7134a8f7044 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -346,6 +346,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. sbirq - IRQ # for CMI8330 chip (SB16) sbdma8 - 8bit DMA # for CMI8330 chip (SB16) sbdma16 - 16bit DMA # for CMI8330 chip (SB16) + fmport - (optional) OPL3 I/O port + mpuport - (optional) MPU401 I/O port + mpuirq - (optional) MPU401 irq # This module supports multiple cards and autoprobe. -- GitLab From 7c20dcc545d78946e40e8fab99637fe815b1d211 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 29 Jan 2009 11:29:22 +0100 Subject: [PATCH 0618/4982] x86, summit: consolidate code, fix Build fix for !NUMA Summit. Signed-off-by: Ingo Molnar --- arch/x86/kernel/Makefile | 2 +- arch/x86/kernel/summit_32.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 37fa30bada1..a382ca6f6a1 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -73,7 +73,7 @@ obj-$(CONFIG_KEXEC) += relocate_kernel_$(BITS).o crash.o obj-$(CONFIG_CRASH_DUMP) += crash_dump_$(BITS).o obj-$(CONFIG_X86_NUMAQ) += numaq_32.o obj-$(CONFIG_X86_ES7000) += es7000_32.o -obj-$(CONFIG_X86_SUMMIT_NUMA) += summit_32.o +obj-$(CONFIG_X86_SUMMIT) += summit_32.o obj-y += vsmp_64.o obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_MODULES) += module_$(BITS).o diff --git a/arch/x86/kernel/summit_32.c b/arch/x86/kernel/summit_32.c index 3b60dd5e57f..84ff9ebbcc9 100644 --- a/arch/x86/kernel/summit_32.c +++ b/arch/x86/kernel/summit_32.c @@ -389,6 +389,7 @@ static void summit_vector_allocation_domain(int cpu, cpumask_t *retmask) *retmask = (cpumask_t){ { [0] = APIC_ALL_CPUS, } }; } +#ifdef CONFIG_X86_SUMMIT_NUMA static struct rio_table_hdr *rio_table_hdr __initdata; static struct scal_detail *scal_devs[MAX_NUMNODES] __initdata; static struct rio_detail *rio_devs[MAX_NUMNODES*4] __initdata; @@ -543,7 +544,7 @@ void __init setup_summit(void) next_wpeg = 0; } while (next_wpeg != 0); } - +#endif struct genapic apic_summit = { -- GitLab From 1dcdd3d15ecea0c22a09d4d001a39d425fceff2c Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 17:55:37 +0100 Subject: [PATCH 0619/4982] x86: remove mach_apic.h Spread mach_apic.h definitions into genapic.h. (with some knock-on effects on smp.h and apic.h.) Signed-off-by: Ingo Molnar --- arch/x86/include/asm/apic.h | 2 +- arch/x86/include/asm/genapic.h | 139 +++++++++++++++++ arch/x86/include/asm/mach-default/mach_apic.h | 144 ------------------ arch/x86/include/asm/mach-generic/mach_apic.h | 8 - arch/x86/include/asm/smp.h | 19 --- arch/x86/kernel/acpi/boot.c | 14 +- arch/x86/kernel/apic.c | 22 ++- arch/x86/kernel/cpu/addon_cpuid_features.c | 2 +- arch/x86/kernel/cpu/amd.c | 2 +- arch/x86/kernel/cpu/common.c | 2 +- arch/x86/kernel/cpu/intel.c | 2 +- arch/x86/kernel/io_apic.c | 2 +- arch/x86/kernel/ipi.c | 2 +- arch/x86/kernel/irq_32.c | 2 +- arch/x86/kernel/mpparse.c | 3 +- arch/x86/kernel/setup.c | 2 +- arch/x86/kernel/smp.c | 2 +- arch/x86/kernel/smpboot.c | 2 +- arch/x86/kernel/tlb_uv.c | 2 +- arch/x86/kernel/visws_quirks.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mach-generic/probe.c | 5 - 22 files changed, 175 insertions(+), 207 deletions(-) delete mode 100644 arch/x86/include/asm/mach-default/mach_apic.h delete mode 100644 arch/x86/include/asm/mach-generic/mach_apic.h diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 3a3202074c6..6a77068e261 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -215,7 +215,7 @@ static inline void disable_local_APIC(void) { } #define SET_APIC_ID(x) (apic->set_apic_id(x)) #else -static inline unsigned default_get_apic_id(unsigned long x) +static inline unsigned default_get_apic_id(unsigned long x) { unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR)); diff --git a/arch/x86/include/asm/genapic.h b/arch/x86/include/asm/genapic.h index 1772dad01b1..ce3655a4948 100644 --- a/arch/x86/include/asm/genapic.h +++ b/arch/x86/include/asm/genapic.h @@ -120,4 +120,143 @@ static inline void default_wait_for_init_deassert(atomic_t *deassert) return; } +extern void generic_bigsmp_probe(void); + + +#ifdef CONFIG_X86_LOCAL_APIC + +#include + +#define APIC_DFR_VALUE (APIC_DFR_FLAT) + +static inline const struct cpumask *default_target_cpus(void) +{ +#ifdef CONFIG_SMP + return cpu_online_mask; +#else + return cpumask_of(0); +#endif +} + +DECLARE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid); + + +static inline unsigned int read_apic_id(void) +{ + unsigned int reg; + + reg = *(u32 *)(APIC_BASE + APIC_ID); + + return apic->get_apic_id(reg); +} + +#ifdef CONFIG_X86_64 +extern void default_setup_apic_routing(void); +#else + +/* + * Set up the logical destination ID. + * + * Intel recommends to set DFR, LDR and TPR before enabling + * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel + * document number 292116). So here it goes... + */ +extern void default_init_apic_ldr(void); + +static inline int default_apic_id_registered(void) +{ + return physid_isset(read_apic_id(), phys_cpu_present_map); +} + +static inline unsigned int +default_cpu_mask_to_apicid(const struct cpumask *cpumask) +{ + return cpumask_bits(cpumask)[0]; +} + +static inline unsigned int +default_cpu_mask_to_apicid_and(const struct cpumask *cpumask, + const struct cpumask *andmask) +{ + unsigned long mask1 = cpumask_bits(cpumask)[0]; + unsigned long mask2 = cpumask_bits(andmask)[0]; + unsigned long mask3 = cpumask_bits(cpu_online_mask)[0]; + + return (unsigned int)(mask1 & mask2 & mask3); +} + +static inline int default_phys_pkg_id(int cpuid_apic, int index_msb) +{ + return cpuid_apic >> index_msb; +} + +static inline void default_setup_apic_routing(void) +{ +#ifdef CONFIG_X86_IO_APIC + printk("Enabling APIC mode: %s. Using %d I/O APICs\n", + "Flat", nr_ioapics); +#endif +} + +extern int default_apicid_to_node(int logical_apicid); + +#endif + +static inline unsigned long default_check_apicid_used(physid_mask_t bitmap, int apicid) +{ + return physid_isset(apicid, bitmap); +} + +static inline unsigned long default_check_apicid_present(int bit) +{ + return physid_isset(bit, phys_cpu_present_map); +} + +static inline physid_mask_t default_ioapic_phys_id_map(physid_mask_t phys_map) +{ + return phys_map; +} + +/* Mapping from cpu number to logical apicid */ +static inline int default_cpu_to_logical_apicid(int cpu) +{ + return 1 << cpu; +} + +static inline int __default_cpu_present_to_apicid(int mps_cpu) +{ + if (mps_cpu < nr_cpu_ids && cpu_present(mps_cpu)) + return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu); + else + return BAD_APICID; +} + +static inline int +__default_check_phys_apicid_present(int boot_cpu_physical_apicid) +{ + return physid_isset(boot_cpu_physical_apicid, phys_cpu_present_map); +} + +#ifdef CONFIG_X86_32 +static inline int default_cpu_present_to_apicid(int mps_cpu) +{ + return __default_cpu_present_to_apicid(mps_cpu); +} + +static inline int +default_check_phys_apicid_present(int boot_cpu_physical_apicid) +{ + return __default_check_phys_apicid_present(boot_cpu_physical_apicid); +} +#else +extern int default_cpu_present_to_apicid(int mps_cpu); +extern int default_check_phys_apicid_present(int boot_cpu_physical_apicid); +#endif + +static inline physid_mask_t default_apicid_to_cpu_present(int phys_apicid) +{ + return physid_mask_of_physid(phys_apicid); +} + +#endif /* CONFIG_X86_LOCAL_APIC */ #endif /* _ASM_X86_GENAPIC_64_H */ diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h deleted file mode 100644 index bae053cdcde..00000000000 --- a/arch/x86/include/asm/mach-default/mach_apic.h +++ /dev/null @@ -1,144 +0,0 @@ -#ifndef _ASM_X86_MACH_DEFAULT_MACH_APIC_H -#define _ASM_X86_MACH_DEFAULT_MACH_APIC_H - -#ifdef CONFIG_X86_LOCAL_APIC - -#include - -#define APIC_DFR_VALUE (APIC_DFR_FLAT) - -static inline const struct cpumask *default_target_cpus(void) -{ -#ifdef CONFIG_SMP - return cpu_online_mask; -#else - return cpumask_of(0); -#endif -} - -#ifdef CONFIG_X86_64 -#include -#define read_apic_id() (apic->get_apic_id(apic_read(APIC_ID))) -extern void default_setup_apic_routing(void); -#else -/* - * Set up the logical destination ID. - * - * Intel recommends to set DFR, LDR and TPR before enabling - * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel - * document number 292116). So here it goes... - */ -static inline void default_init_apic_ldr(void) -{ - unsigned long val; - - apic_write(APIC_DFR, APIC_DFR_VALUE); - val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; - val |= SET_APIC_LOGICAL_ID(1UL << smp_processor_id()); - apic_write(APIC_LDR, val); -} - -static inline int default_apic_id_registered(void) -{ - return physid_isset(read_apic_id(), phys_cpu_present_map); -} - -static inline unsigned int -default_cpu_mask_to_apicid(const struct cpumask *cpumask) -{ - return cpumask_bits(cpumask)[0]; -} - -static inline unsigned int -default_cpu_mask_to_apicid_and(const struct cpumask *cpumask, - const struct cpumask *andmask) -{ - unsigned long mask1 = cpumask_bits(cpumask)[0]; - unsigned long mask2 = cpumask_bits(andmask)[0]; - unsigned long mask3 = cpumask_bits(cpu_online_mask)[0]; - - return (unsigned int)(mask1 & mask2 & mask3); -} - -static inline int default_phys_pkg_id(int cpuid_apic, int index_msb) -{ - return cpuid_apic >> index_msb; -} - -static inline void default_setup_apic_routing(void) -{ -#ifdef CONFIG_X86_IO_APIC - printk("Enabling APIC mode: %s. Using %d I/O APICs\n", - "Flat", nr_ioapics); -#endif -} - -static inline int default_apicid_to_node(int logical_apicid) -{ -#ifdef CONFIG_SMP - return apicid_2_node[hard_smp_processor_id()]; -#else - return 0; -#endif -} - -#endif - -static inline unsigned long default_check_apicid_used(physid_mask_t bitmap, int apicid) -{ - return physid_isset(apicid, bitmap); -} - -static inline unsigned long default_check_apicid_present(int bit) -{ - return physid_isset(bit, phys_cpu_present_map); -} - -static inline physid_mask_t default_ioapic_phys_id_map(physid_mask_t phys_map) -{ - return phys_map; -} - -/* Mapping from cpu number to logical apicid */ -static inline int default_cpu_to_logical_apicid(int cpu) -{ - return 1 << cpu; -} - -static inline int __default_cpu_present_to_apicid(int mps_cpu) -{ - if (mps_cpu < nr_cpu_ids && cpu_present(mps_cpu)) - return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu); - else - return BAD_APICID; -} - -static inline int -__default_check_phys_apicid_present(int boot_cpu_physical_apicid) -{ - return physid_isset(boot_cpu_physical_apicid, phys_cpu_present_map); -} - -#ifdef CONFIG_X86_32 -static inline int default_cpu_present_to_apicid(int mps_cpu) -{ - return __default_cpu_present_to_apicid(mps_cpu); -} - -static inline int -default_check_phys_apicid_present(int boot_cpu_physical_apicid) -{ - return __default_check_phys_apicid_present(boot_cpu_physical_apicid); -} -#else -extern int default_cpu_present_to_apicid(int mps_cpu); -extern int default_check_phys_apicid_present(int boot_cpu_physical_apicid); -#endif - -static inline physid_mask_t default_apicid_to_cpu_present(int phys_apicid) -{ - return physid_mask_of_physid(phys_apicid); -} - -#endif /* CONFIG_X86_LOCAL_APIC */ -#endif /* _ASM_X86_MACH_DEFAULT_MACH_APIC_H */ diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h deleted file mode 100644 index 96f217f819e..00000000000 --- a/arch/x86/include/asm/mach-generic/mach_apic.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _ASM_X86_MACH_GENERIC_MACH_APIC_H -#define _ASM_X86_MACH_GENERIC_MACH_APIC_H - -#include - -extern void generic_bigsmp_probe(void); - -#endif /* _ASM_X86_MACH_GENERIC_MACH_APIC_H */ diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index d4ac4de4bce..47d0e21f2b9 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -173,8 +173,6 @@ extern int safe_smp_processor_id(void); #endif -#include - #ifdef CONFIG_X86_LOCAL_APIC #ifndef CONFIG_X86_64 @@ -184,26 +182,9 @@ static inline int logical_smp_processor_id(void) return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR)); } -static inline unsigned int read_apic_id(void) -{ - unsigned int reg; - - reg = *(u32 *)(APIC_BASE + APIC_ID); - - return apic->get_apic_id(reg); -} #endif - -# if defined(APIC_DEFINITION) || defined(CONFIG_X86_64) extern int hard_smp_processor_id(void); -# else -static inline int hard_smp_processor_id(void) -{ - /* we don't want to mark this access volatile - bad code generation */ - return read_apic_id(); -} -# endif /* APIC_DEFINITION */ #else /* CONFIG_X86_LOCAL_APIC */ diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 7b02a1cedca..cb8b52785e3 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -42,10 +42,6 @@ #include #include -#ifdef CONFIG_X86_LOCAL_APIC -# include -#endif - static int __initdata acpi_force = 0; u32 acpi_rsdt_forced; #ifdef CONFIG_ACPI @@ -56,15 +52,7 @@ int acpi_disabled = 1; EXPORT_SYMBOL(acpi_disabled); #ifdef CONFIG_X86_64 - -#include - -#else /* X86 */ - -#ifdef CONFIG_X86_LOCAL_APIC -#include -#endif /* CONFIG_X86_LOCAL_APIC */ - +# include #endif /* X86 */ #define BAD_MADT_ENTRY(entry, end) ( \ diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index e6220809ca1..41a0ba34d6b 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -49,7 +49,6 @@ #include #include -#include #include /* @@ -1910,11 +1909,30 @@ void __cpuinit generic_processor_info(int apicid, int version) set_cpu_present(cpu, true); } -#ifdef CONFIG_X86_64 int hard_smp_processor_id(void) { return read_apic_id(); } + +void default_init_apic_ldr(void) +{ + unsigned long val; + + apic_write(APIC_DFR, APIC_DFR_VALUE); + val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; + val |= SET_APIC_LOGICAL_ID(1UL << smp_processor_id()); + apic_write(APIC_LDR, val); +} + +#ifdef CONFIG_X86_32 +int default_apicid_to_node(int logical_apicid) +{ +#ifdef CONFIG_SMP + return apicid_2_node[hard_smp_processor_id()]; +#else + return 0; +#endif +} #endif /* diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c index e8bb892c09f..4a48bb40974 100644 --- a/arch/x86/kernel/cpu/addon_cpuid_features.c +++ b/arch/x86/kernel/cpu/addon_cpuid_features.c @@ -7,7 +7,7 @@ #include #include -#include +#include struct cpuid_bit { u16 feature; diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 7c878f6aa91..ff4d7b9e32e 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -12,7 +12,7 @@ # include #endif -#include +#include #include "cpu.h" diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 055b9c3a660..c4bdc7f0020 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -26,7 +26,7 @@ #ifdef CONFIG_X86_LOCAL_APIC #include #include -#include +#include #include #include #endif diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 5deefae9064..1cef0aa5e5d 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -24,7 +24,7 @@ #ifdef CONFIG_X86_LOCAL_APIC #include #include -#include +#include #endif static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index abae81989c2..e0744ea6d0f 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -63,7 +63,7 @@ #include #include -#include +#include #define __apicdebuginit(type) static type __init diff --git a/arch/x86/kernel/ipi.c b/arch/x86/kernel/ipi.c index e16c41b2e4e..50076d92fbc 100644 --- a/arch/x86/kernel/ipi.c +++ b/arch/x86/kernel/ipi.c @@ -19,7 +19,7 @@ #include #ifdef CONFIG_X86_32 -#include +#include #include /* diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index e0f29be8ab0..d802c844991 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c @@ -231,7 +231,7 @@ unsigned int do_IRQ(struct pt_regs *regs) } #ifdef CONFIG_HOTPLUG_CPU -#include +#include /* A cpu has been removed from cpu_online_mask. Reset irq affinities. */ void fixup_irqs(void) diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index a1452a53d14..94fe71029c3 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -29,8 +29,7 @@ #include #include -#include - +#include /* * Checksum an MP configuration block. */ diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 6b27f6dc7bf..92e42939fb0 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -97,7 +97,7 @@ #include #include -#include +#include #include #include diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index c48ba6cc32a..892e7c389be 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include /* * Some notes on x86 processor bugs affecting SMP operation: * diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 3fed177f345..489fde9d947 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -65,7 +65,7 @@ #include #include -#include +#include #include #ifdef CONFIG_X86_32 diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c index 89fce1b6d01..755ede02b13 100644 --- a/arch/x86/kernel/tlb_uv.c +++ b/arch/x86/kernel/tlb_uv.c @@ -20,7 +20,7 @@ #include #include -#include +#include static struct bau_control **uv_bau_table_bases __read_mostly; static int uv_bau_retry_limit __read_mostly; diff --git a/arch/x86/kernel/visws_quirks.c b/arch/x86/kernel/visws_quirks.c index 2ed5bdf15c9..3bd7f47a91b 100644 --- a/arch/x86/kernel/visws_quirks.c +++ b/arch/x86/kernel/visws_quirks.c @@ -34,7 +34,7 @@ #include -#include "mach_apic.h" +#include #include diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index 07817b2a787..7d5123e474e 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include static void default_vector_allocation_domain(int cpu, struct cpumask *retmask) diff --git a/arch/x86/mach-generic/probe.c b/arch/x86/mach-generic/probe.c index ab68c6e5c48..c03c7222132 100644 --- a/arch/x86/mach-generic/probe.c +++ b/arch/x86/mach-generic/probe.c @@ -154,8 +154,3 @@ int __init default_acpi_madt_oem_check(char *oem_id, char *oem_table_id) } return 0; } - -int hard_smp_processor_id(void) -{ - return apic->get_apic_id(*(unsigned long *)(APIC_BASE+APIC_ID)); -} -- GitLab From 83d7aeabe4cf20e59b5d7fd56a75cfd0e0b6b880 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Wed, 28 Jan 2009 17:52:57 -0800 Subject: [PATCH 0620/4982] x86: remove mach_apic.h, fix Use apic_read() instead of open-coded mmio. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/genapic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/genapic.h b/arch/x86/include/asm/genapic.h index ce3655a4948..ccfcd19d5b7 100644 --- a/arch/x86/include/asm/genapic.h +++ b/arch/x86/include/asm/genapic.h @@ -145,7 +145,7 @@ static inline unsigned int read_apic_id(void) { unsigned int reg; - reg = *(u32 *)(APIC_BASE + APIC_ID); + reg = apic_read(APIC_ID); return apic->get_apic_id(reg); } -- GitLab From 2e096df8edefad78155bb406a5a86c182b17786e Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 19:01:05 +0100 Subject: [PATCH 0621/4982] x86, ES7000: Consolidate code Move all ES7000 code into arch/x86/kernel/es7000_32.c. With this it ceases to rely on any build-time subarch features. Signed-off-by: Ingo Molnar --- arch/x86/kernel/es7000_32.c | 428 +++++++++++++++++++++++++++++++++ arch/x86/mach-generic/Makefile | 1 - arch/x86/mach-generic/es7000.c | 427 -------------------------------- 3 files changed, 428 insertions(+), 428 deletions(-) delete mode 100644 arch/x86/mach-generic/es7000.c diff --git a/arch/x86/kernel/es7000_32.c b/arch/x86/kernel/es7000_32.c index 8faea13c8fa..078364ccfa0 100644 --- a/arch/x86/kernel/es7000_32.c +++ b/arch/x86/kernel/es7000_32.c @@ -372,3 +372,431 @@ void __init es7000_enable_apic_mode(void) mip_status); } } + +/* + * APIC driver for the Unisys ES7000 chipset. + */ +#define APIC_DEFINITION 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define APIC_DFR_VALUE_CLUSTER (APIC_DFR_CLUSTER) +#define INT_DELIVERY_MODE_CLUSTER (dest_LowestPrio) +#define INT_DEST_MODE_CLUSTER (1) /* logical delivery broadcast to all procs */ + +#define APIC_DFR_VALUE (APIC_DFR_FLAT) + +extern void es7000_enable_apic_mode(void); +extern int apic_version [MAX_APICS]; +extern u8 cpu_2_logical_apicid[]; +extern unsigned int boot_cpu_physical_apicid; + +extern int parse_unisys_oem (char *oemptr); +extern int find_unisys_acpi_oem_table(unsigned long *oem_addr); +extern void unmap_unisys_acpi_oem_table(unsigned long oem_addr); +extern void setup_unisys(void); + +#define apicid_cluster(apicid) (apicid & 0xF0) +#define xapic_phys_to_log_apicid(cpu) per_cpu(x86_bios_cpu_apicid, cpu) + +static void es7000_vector_allocation_domain(int cpu, cpumask_t *retmask) +{ + /* Careful. Some cpus do not strictly honor the set of cpus + * specified in the interrupt destination when using lowest + * priority interrupt delivery mode. + * + * In particular there was a hyperthreading cpu observed to + * deliver interrupts to the wrong hyperthread when only one + * hyperthread was specified in the interrupt desitination. + */ + *retmask = (cpumask_t){ { [0] = APIC_ALL_CPUS, } }; +} + + +static void es7000_wait_for_init_deassert(atomic_t *deassert) +{ +#ifndef CONFIG_ES7000_CLUSTERED_APIC + while (!atomic_read(deassert)) + cpu_relax(); +#endif + return; +} + +static unsigned int es7000_get_apic_id(unsigned long x) +{ + return (x >> 24) & 0xFF; +} + +#ifdef CONFIG_ACPI +static int es7000_check_dsdt(void) +{ + struct acpi_table_header header; + + if (ACPI_SUCCESS(acpi_get_table_header(ACPI_SIG_DSDT, 0, &header)) && + !strncmp(header.oem_id, "UNISYS", 6)) + return 1; + return 0; +} +#endif + +static void es7000_send_IPI_mask(const struct cpumask *mask, int vector) +{ + default_send_IPI_mask_sequence(mask, vector); +} + +static void es7000_send_IPI_allbutself(int vector) +{ + default_send_IPI_mask_allbutself(cpu_online_mask, vector); +} + +static void es7000_send_IPI_all(int vector) +{ + es7000_send_IPI_mask(cpu_online_mask, vector); +} + +static int es7000_apic_id_registered(void) +{ + return 1; +} + +static const cpumask_t *target_cpus_cluster(void) +{ + return &CPU_MASK_ALL; +} + +static const cpumask_t *es7000_target_cpus(void) +{ + return &cpumask_of_cpu(smp_processor_id()); +} + +static unsigned long +es7000_check_apicid_used(physid_mask_t bitmap, int apicid) +{ + return 0; +} +static unsigned long es7000_check_apicid_present(int bit) +{ + return physid_isset(bit, phys_cpu_present_map); +} + +static unsigned long calculate_ldr(int cpu) +{ + unsigned long id = xapic_phys_to_log_apicid(cpu); + + return (SET_APIC_LOGICAL_ID(id)); +} + +/* + * Set up the logical destination ID. + * + * Intel recommends to set DFR, LdR and TPR before enabling + * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel + * document number 292116). So here it goes... + */ +static void es7000_init_apic_ldr_cluster(void) +{ + unsigned long val; + int cpu = smp_processor_id(); + + apic_write(APIC_DFR, APIC_DFR_VALUE_CLUSTER); + val = calculate_ldr(cpu); + apic_write(APIC_LDR, val); +} + +static void es7000_init_apic_ldr(void) +{ + unsigned long val; + int cpu = smp_processor_id(); + + apic_write(APIC_DFR, APIC_DFR_VALUE); + val = calculate_ldr(cpu); + apic_write(APIC_LDR, val); +} + +static void es7000_setup_apic_routing(void) +{ + int apic = per_cpu(x86_bios_cpu_apicid, smp_processor_id()); + printk("Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n", + (apic_version[apic] == 0x14) ? + "Physical Cluster" : "Logical Cluster", + nr_ioapics, cpus_addr(*es7000_target_cpus())[0]); +} + +static int es7000_apicid_to_node(int logical_apicid) +{ + return 0; +} + + +static int es7000_cpu_present_to_apicid(int mps_cpu) +{ + if (!mps_cpu) + return boot_cpu_physical_apicid; + else if (mps_cpu < nr_cpu_ids) + return (int) per_cpu(x86_bios_cpu_apicid, mps_cpu); + else + return BAD_APICID; +} + +static physid_mask_t es7000_apicid_to_cpu_present(int phys_apicid) +{ + static int id = 0; + physid_mask_t mask; + + mask = physid_mask_of_physid(id); + ++id; + + return mask; +} + +/* Mapping from cpu number to logical apicid */ +static int es7000_cpu_to_logical_apicid(int cpu) +{ +#ifdef CONFIG_SMP + if (cpu >= nr_cpu_ids) + return BAD_APICID; + return (int)cpu_2_logical_apicid[cpu]; +#else + return logical_smp_processor_id(); +#endif +} + +static physid_mask_t es7000_ioapic_phys_id_map(physid_mask_t phys_map) +{ + /* For clustered we don't have a good way to do this yet - hack */ + return physids_promote(0xff); +} + +static int es7000_check_phys_apicid_present(int cpu_physical_apicid) +{ + boot_cpu_physical_apicid = read_apic_id(); + return (1); +} + +static unsigned int +es7000_cpu_mask_to_apicid_cluster(const struct cpumask *cpumask) +{ + int cpus_found = 0; + int num_bits_set; + int apicid; + int cpu; + + num_bits_set = cpumask_weight(cpumask); + /* Return id to all */ + if (num_bits_set == nr_cpu_ids) + return 0xFF; + /* + * The cpus in the mask must all be on the apic cluster. If are not + * on the same apicid cluster return default value of target_cpus(): + */ + cpu = cpumask_first(cpumask); + apicid = es7000_cpu_to_logical_apicid(cpu); + + while (cpus_found < num_bits_set) { + if (cpumask_test_cpu(cpu, cpumask)) { + int new_apicid = es7000_cpu_to_logical_apicid(cpu); + + if (apicid_cluster(apicid) != + apicid_cluster(new_apicid)) { + printk ("%s: Not a valid mask!\n", __func__); + + return 0xFF; + } + apicid = new_apicid; + cpus_found++; + } + cpu++; + } + return apicid; +} + +static unsigned int es7000_cpu_mask_to_apicid(const cpumask_t *cpumask) +{ + int cpus_found = 0; + int num_bits_set; + int apicid; + int cpu; + + num_bits_set = cpus_weight(*cpumask); + /* Return id to all */ + if (num_bits_set == nr_cpu_ids) + return es7000_cpu_to_logical_apicid(0); + /* + * The cpus in the mask must all be on the apic cluster. If are not + * on the same apicid cluster return default value of target_cpus(): + */ + cpu = first_cpu(*cpumask); + apicid = es7000_cpu_to_logical_apicid(cpu); + while (cpus_found < num_bits_set) { + if (cpu_isset(cpu, *cpumask)) { + int new_apicid = es7000_cpu_to_logical_apicid(cpu); + + if (apicid_cluster(apicid) != + apicid_cluster(new_apicid)) { + printk ("%s: Not a valid mask!\n", __func__); + + return es7000_cpu_to_logical_apicid(0); + } + apicid = new_apicid; + cpus_found++; + } + cpu++; + } + return apicid; +} + +static unsigned int +es7000_cpu_mask_to_apicid_and(const struct cpumask *inmask, + const struct cpumask *andmask) +{ + int apicid = es7000_cpu_to_logical_apicid(0); + cpumask_var_t cpumask; + + if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC)) + return apicid; + + cpumask_and(cpumask, inmask, andmask); + cpumask_and(cpumask, cpumask, cpu_online_mask); + apicid = es7000_cpu_mask_to_apicid(cpumask); + + free_cpumask_var(cpumask); + + return apicid; +} + +static int es7000_phys_pkg_id(int cpuid_apic, int index_msb) +{ + return cpuid_apic >> index_msb; +} + +void __init es7000_update_genapic_to_cluster(void) +{ + apic->target_cpus = target_cpus_cluster; + apic->irq_delivery_mode = INT_DELIVERY_MODE_CLUSTER; + apic->irq_dest_mode = INT_DEST_MODE_CLUSTER; + + apic->init_apic_ldr = es7000_init_apic_ldr_cluster; + + apic->cpu_mask_to_apicid = es7000_cpu_mask_to_apicid_cluster; +} + +static int probe_es7000(void) +{ + /* probed later in mptable/ACPI hooks */ + return 0; +} + +static __init int +es7000_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) +{ + if (mpc->oemptr) { + struct mpc_oemtable *oem_table = + (struct mpc_oemtable *)mpc->oemptr; + + if (!strncmp(oem, "UNISYS", 6)) + return parse_unisys_oem((char *)oem_table); + } + return 0; +} + +#ifdef CONFIG_ACPI +/* Hook from generic ACPI tables.c */ +static int __init es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + unsigned long oem_addr = 0; + int check_dsdt; + int ret = 0; + + /* check dsdt at first to avoid clear fix_map for oem_addr */ + check_dsdt = es7000_check_dsdt(); + + if (!find_unisys_acpi_oem_table(&oem_addr)) { + if (check_dsdt) + ret = parse_unisys_oem((char *)oem_addr); + else { + setup_unisys(); + ret = 1; + } + /* + * we need to unmap it + */ + unmap_unisys_acpi_oem_table(oem_addr); + } + return ret; +} +#else +static int __init es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + return 0; +} +#endif + + +struct genapic apic_es7000 = { + + .name = "es7000", + .probe = probe_es7000, + .acpi_madt_oem_check = es7000_acpi_madt_oem_check, + .apic_id_registered = es7000_apic_id_registered, + + .irq_delivery_mode = dest_Fixed, + /* phys delivery to target CPUs: */ + .irq_dest_mode = 0, + + .target_cpus = es7000_target_cpus, + .disable_esr = 1, + .dest_logical = 0, + .check_apicid_used = es7000_check_apicid_used, + .check_apicid_present = es7000_check_apicid_present, + + .vector_allocation_domain = es7000_vector_allocation_domain, + .init_apic_ldr = es7000_init_apic_ldr, + + .ioapic_phys_id_map = es7000_ioapic_phys_id_map, + .setup_apic_routing = es7000_setup_apic_routing, + .multi_timer_check = NULL, + .apicid_to_node = es7000_apicid_to_node, + .cpu_to_logical_apicid = es7000_cpu_to_logical_apicid, + .cpu_present_to_apicid = es7000_cpu_present_to_apicid, + .apicid_to_cpu_present = es7000_apicid_to_cpu_present, + .setup_portio_remap = NULL, + .check_phys_apicid_present = es7000_check_phys_apicid_present, + .enable_apic_mode = es7000_enable_apic_mode, + .phys_pkg_id = es7000_phys_pkg_id, + .mps_oem_check = es7000_mps_oem_check, + + .get_apic_id = es7000_get_apic_id, + .set_apic_id = NULL, + .apic_id_mask = 0xFF << 24, + + .cpu_mask_to_apicid = es7000_cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = es7000_cpu_mask_to_apicid_and, + + .send_IPI_mask = es7000_send_IPI_mask, + .send_IPI_mask_allbutself = NULL, + .send_IPI_allbutself = es7000_send_IPI_allbutself, + .send_IPI_all = es7000_send_IPI_all, + .send_IPI_self = NULL, + + .wakeup_cpu = NULL, + + .trampoline_phys_low = 0x467, + .trampoline_phys_high = 0x469, + + .wait_for_init_deassert = es7000_wait_for_init_deassert, + + /* Nothing to do for most platforms, since cleared by the INIT cycle: */ + .smp_callin_clear_local_apic = NULL, + .store_NMI_vector = NULL, + .inquire_remote_apic = default_inquire_remote_apic, +}; diff --git a/arch/x86/mach-generic/Makefile b/arch/x86/mach-generic/Makefile index 78ab5735cb8..05e47acfd66 100644 --- a/arch/x86/mach-generic/Makefile +++ b/arch/x86/mach-generic/Makefile @@ -7,4 +7,3 @@ EXTRA_CFLAGS := -Iarch/x86/kernel obj-y := probe.o default.o obj-$(CONFIG_X86_NUMAQ) += numaq.o obj-$(CONFIG_X86_BIGSMP) += bigsmp.o -obj-$(CONFIG_X86_ES7000) += es7000.o diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c deleted file mode 100644 index bb11166b7c3..00000000000 --- a/arch/x86/mach-generic/es7000.c +++ /dev/null @@ -1,427 +0,0 @@ -/* - * APIC driver for the Unisys ES7000 chipset. - */ -#define APIC_DEFINITION 1 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define APIC_DFR_VALUE_CLUSTER (APIC_DFR_CLUSTER) -#define INT_DELIVERY_MODE_CLUSTER (dest_LowestPrio) -#define INT_DEST_MODE_CLUSTER (1) /* logical delivery broadcast to all procs */ - -#define APIC_DFR_VALUE (APIC_DFR_FLAT) - -extern void es7000_enable_apic_mode(void); -extern int apic_version [MAX_APICS]; -extern u8 cpu_2_logical_apicid[]; -extern unsigned int boot_cpu_physical_apicid; - -extern int parse_unisys_oem (char *oemptr); -extern int find_unisys_acpi_oem_table(unsigned long *oem_addr); -extern void unmap_unisys_acpi_oem_table(unsigned long oem_addr); -extern void setup_unisys(void); - -#define apicid_cluster(apicid) (apicid & 0xF0) -#define xapic_phys_to_log_apicid(cpu) per_cpu(x86_bios_cpu_apicid, cpu) - -static void es7000_vector_allocation_domain(int cpu, cpumask_t *retmask) -{ - /* Careful. Some cpus do not strictly honor the set of cpus - * specified in the interrupt destination when using lowest - * priority interrupt delivery mode. - * - * In particular there was a hyperthreading cpu observed to - * deliver interrupts to the wrong hyperthread when only one - * hyperthread was specified in the interrupt desitination. - */ - *retmask = (cpumask_t){ { [0] = APIC_ALL_CPUS, } }; -} - - -static void es7000_wait_for_init_deassert(atomic_t *deassert) -{ -#ifndef CONFIG_ES7000_CLUSTERED_APIC - while (!atomic_read(deassert)) - cpu_relax(); -#endif - return; -} - -static unsigned int es7000_get_apic_id(unsigned long x) -{ - return (x >> 24) & 0xFF; -} - -#ifdef CONFIG_ACPI -static int es7000_check_dsdt(void) -{ - struct acpi_table_header header; - - if (ACPI_SUCCESS(acpi_get_table_header(ACPI_SIG_DSDT, 0, &header)) && - !strncmp(header.oem_id, "UNISYS", 6)) - return 1; - return 0; -} -#endif - -static void es7000_send_IPI_mask(const struct cpumask *mask, int vector) -{ - default_send_IPI_mask_sequence(mask, vector); -} - -static void es7000_send_IPI_allbutself(int vector) -{ - default_send_IPI_mask_allbutself(cpu_online_mask, vector); -} - -static void es7000_send_IPI_all(int vector) -{ - es7000_send_IPI_mask(cpu_online_mask, vector); -} - -static int es7000_apic_id_registered(void) -{ - return 1; -} - -static const cpumask_t *target_cpus_cluster(void) -{ - return &CPU_MASK_ALL; -} - -static const cpumask_t *es7000_target_cpus(void) -{ - return &cpumask_of_cpu(smp_processor_id()); -} - -static unsigned long -es7000_check_apicid_used(physid_mask_t bitmap, int apicid) -{ - return 0; -} -static unsigned long es7000_check_apicid_present(int bit) -{ - return physid_isset(bit, phys_cpu_present_map); -} - -static unsigned long calculate_ldr(int cpu) -{ - unsigned long id = xapic_phys_to_log_apicid(cpu); - - return (SET_APIC_LOGICAL_ID(id)); -} - -/* - * Set up the logical destination ID. - * - * Intel recommends to set DFR, LdR and TPR before enabling - * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel - * document number 292116). So here it goes... - */ -static void es7000_init_apic_ldr_cluster(void) -{ - unsigned long val; - int cpu = smp_processor_id(); - - apic_write(APIC_DFR, APIC_DFR_VALUE_CLUSTER); - val = calculate_ldr(cpu); - apic_write(APIC_LDR, val); -} - -static void es7000_init_apic_ldr(void) -{ - unsigned long val; - int cpu = smp_processor_id(); - - apic_write(APIC_DFR, APIC_DFR_VALUE); - val = calculate_ldr(cpu); - apic_write(APIC_LDR, val); -} - -static void es7000_setup_apic_routing(void) -{ - int apic = per_cpu(x86_bios_cpu_apicid, smp_processor_id()); - printk("Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n", - (apic_version[apic] == 0x14) ? - "Physical Cluster" : "Logical Cluster", - nr_ioapics, cpus_addr(*es7000_target_cpus())[0]); -} - -static int es7000_apicid_to_node(int logical_apicid) -{ - return 0; -} - - -static int es7000_cpu_present_to_apicid(int mps_cpu) -{ - if (!mps_cpu) - return boot_cpu_physical_apicid; - else if (mps_cpu < nr_cpu_ids) - return (int) per_cpu(x86_bios_cpu_apicid, mps_cpu); - else - return BAD_APICID; -} - -static physid_mask_t es7000_apicid_to_cpu_present(int phys_apicid) -{ - static int id = 0; - physid_mask_t mask; - - mask = physid_mask_of_physid(id); - ++id; - - return mask; -} - -/* Mapping from cpu number to logical apicid */ -static int es7000_cpu_to_logical_apicid(int cpu) -{ -#ifdef CONFIG_SMP - if (cpu >= nr_cpu_ids) - return BAD_APICID; - return (int)cpu_2_logical_apicid[cpu]; -#else - return logical_smp_processor_id(); -#endif -} - -static physid_mask_t es7000_ioapic_phys_id_map(physid_mask_t phys_map) -{ - /* For clustered we don't have a good way to do this yet - hack */ - return physids_promote(0xff); -} - -static int es7000_check_phys_apicid_present(int cpu_physical_apicid) -{ - boot_cpu_physical_apicid = read_apic_id(); - return (1); -} - -static unsigned int -es7000_cpu_mask_to_apicid_cluster(const struct cpumask *cpumask) -{ - int cpus_found = 0; - int num_bits_set; - int apicid; - int cpu; - - num_bits_set = cpumask_weight(cpumask); - /* Return id to all */ - if (num_bits_set == nr_cpu_ids) - return 0xFF; - /* - * The cpus in the mask must all be on the apic cluster. If are not - * on the same apicid cluster return default value of target_cpus(): - */ - cpu = cpumask_first(cpumask); - apicid = es7000_cpu_to_logical_apicid(cpu); - - while (cpus_found < num_bits_set) { - if (cpumask_test_cpu(cpu, cpumask)) { - int new_apicid = es7000_cpu_to_logical_apicid(cpu); - - if (apicid_cluster(apicid) != - apicid_cluster(new_apicid)) { - printk ("%s: Not a valid mask!\n", __func__); - - return 0xFF; - } - apicid = new_apicid; - cpus_found++; - } - cpu++; - } - return apicid; -} - -static unsigned int es7000_cpu_mask_to_apicid(const cpumask_t *cpumask) -{ - int cpus_found = 0; - int num_bits_set; - int apicid; - int cpu; - - num_bits_set = cpus_weight(*cpumask); - /* Return id to all */ - if (num_bits_set == nr_cpu_ids) - return es7000_cpu_to_logical_apicid(0); - /* - * The cpus in the mask must all be on the apic cluster. If are not - * on the same apicid cluster return default value of target_cpus(): - */ - cpu = first_cpu(*cpumask); - apicid = es7000_cpu_to_logical_apicid(cpu); - while (cpus_found < num_bits_set) { - if (cpu_isset(cpu, *cpumask)) { - int new_apicid = es7000_cpu_to_logical_apicid(cpu); - - if (apicid_cluster(apicid) != - apicid_cluster(new_apicid)) { - printk ("%s: Not a valid mask!\n", __func__); - - return es7000_cpu_to_logical_apicid(0); - } - apicid = new_apicid; - cpus_found++; - } - cpu++; - } - return apicid; -} - -static unsigned int -es7000_cpu_mask_to_apicid_and(const struct cpumask *inmask, - const struct cpumask *andmask) -{ - int apicid = es7000_cpu_to_logical_apicid(0); - cpumask_var_t cpumask; - - if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC)) - return apicid; - - cpumask_and(cpumask, inmask, andmask); - cpumask_and(cpumask, cpumask, cpu_online_mask); - apicid = es7000_cpu_mask_to_apicid(cpumask); - - free_cpumask_var(cpumask); - - return apicid; -} - -static int es7000_phys_pkg_id(int cpuid_apic, int index_msb) -{ - return cpuid_apic >> index_msb; -} - -void __init es7000_update_genapic_to_cluster(void) -{ - apic->target_cpus = target_cpus_cluster; - apic->irq_delivery_mode = INT_DELIVERY_MODE_CLUSTER; - apic->irq_dest_mode = INT_DEST_MODE_CLUSTER; - - apic->init_apic_ldr = es7000_init_apic_ldr_cluster; - - apic->cpu_mask_to_apicid = es7000_cpu_mask_to_apicid_cluster; -} - -static int probe_es7000(void) -{ - /* probed later in mptable/ACPI hooks */ - return 0; -} - -static __init int -es7000_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) -{ - if (mpc->oemptr) { - struct mpc_oemtable *oem_table = - (struct mpc_oemtable *)mpc->oemptr; - - if (!strncmp(oem, "UNISYS", 6)) - return parse_unisys_oem((char *)oem_table); - } - return 0; -} - -#ifdef CONFIG_ACPI -/* Hook from generic ACPI tables.c */ -static int __init es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id) -{ - unsigned long oem_addr = 0; - int check_dsdt; - int ret = 0; - - /* check dsdt at first to avoid clear fix_map for oem_addr */ - check_dsdt = es7000_check_dsdt(); - - if (!find_unisys_acpi_oem_table(&oem_addr)) { - if (check_dsdt) - ret = parse_unisys_oem((char *)oem_addr); - else { - setup_unisys(); - ret = 1; - } - /* - * we need to unmap it - */ - unmap_unisys_acpi_oem_table(oem_addr); - } - return ret; -} -#else -static int __init es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id) -{ - return 0; -} -#endif - - -struct genapic apic_es7000 = { - - .name = "es7000", - .probe = probe_es7000, - .acpi_madt_oem_check = es7000_acpi_madt_oem_check, - .apic_id_registered = es7000_apic_id_registered, - - .irq_delivery_mode = dest_Fixed, - /* phys delivery to target CPUs: */ - .irq_dest_mode = 0, - - .target_cpus = es7000_target_cpus, - .disable_esr = 1, - .dest_logical = 0, - .check_apicid_used = es7000_check_apicid_used, - .check_apicid_present = es7000_check_apicid_present, - - .vector_allocation_domain = es7000_vector_allocation_domain, - .init_apic_ldr = es7000_init_apic_ldr, - - .ioapic_phys_id_map = es7000_ioapic_phys_id_map, - .setup_apic_routing = es7000_setup_apic_routing, - .multi_timer_check = NULL, - .apicid_to_node = es7000_apicid_to_node, - .cpu_to_logical_apicid = es7000_cpu_to_logical_apicid, - .cpu_present_to_apicid = es7000_cpu_present_to_apicid, - .apicid_to_cpu_present = es7000_apicid_to_cpu_present, - .setup_portio_remap = NULL, - .check_phys_apicid_present = es7000_check_phys_apicid_present, - .enable_apic_mode = es7000_enable_apic_mode, - .phys_pkg_id = es7000_phys_pkg_id, - .mps_oem_check = es7000_mps_oem_check, - - .get_apic_id = es7000_get_apic_id, - .set_apic_id = NULL, - .apic_id_mask = 0xFF << 24, - - .cpu_mask_to_apicid = es7000_cpu_mask_to_apicid, - .cpu_mask_to_apicid_and = es7000_cpu_mask_to_apicid_and, - - .send_IPI_mask = es7000_send_IPI_mask, - .send_IPI_mask_allbutself = NULL, - .send_IPI_allbutself = es7000_send_IPI_allbutself, - .send_IPI_all = es7000_send_IPI_all, - .send_IPI_self = NULL, - - .wakeup_cpu = NULL, - - .trampoline_phys_low = 0x467, - .trampoline_phys_high = 0x469, - - .wait_for_init_deassert = es7000_wait_for_init_deassert, - - /* Nothing to do for most platforms, since cleared by the INIT cycle: */ - .smp_callin_clear_local_apic = NULL, - .store_NMI_vector = NULL, - .inquire_remote_apic = default_inquire_remote_apic, -}; -- GitLab From 61b90b7ca10cc65d8b850ab542859dc593e5a381 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 19:01:05 +0100 Subject: [PATCH 0622/4982] x86, NUMAQ: Consolidate code Move all NUMAQ code into arch/x86/kernel/numaq.c. With this it ceases to rely on any build-time subarch features. Signed-off-by: Ingo Molnar --- arch/x86/kernel/numaq_32.c | 278 +++++++++++++++++++++++++++++++++ arch/x86/mach-generic/Makefile | 1 - arch/x86/mach-generic/numaq.c | 277 -------------------------------- 3 files changed, 278 insertions(+), 278 deletions(-) delete mode 100644 arch/x86/mach-generic/numaq.c diff --git a/arch/x86/kernel/numaq_32.c b/arch/x86/kernel/numaq_32.c index 3928280278f..83bb05524f4 100644 --- a/arch/x86/kernel/numaq_32.c +++ b/arch/x86/kernel/numaq_32.c @@ -291,3 +291,281 @@ int __init get_memcfg_numaq(void) smp_dump_qct(); return 1; } + +/* + * APIC driver for the IBM NUMAQ chipset. + */ +#define APIC_DEFINITION 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NUMAQ_APIC_DFR_VALUE (APIC_DFR_CLUSTER) + +static inline unsigned int numaq_get_apic_id(unsigned long x) +{ + return (x >> 24) & 0x0F; +} + +void default_send_IPI_mask_sequence(const struct cpumask *mask, int vector); +void default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector); + +static inline void numaq_send_IPI_mask(const struct cpumask *mask, int vector) +{ + default_send_IPI_mask_sequence(mask, vector); +} + +static inline void numaq_send_IPI_allbutself(int vector) +{ + default_send_IPI_mask_allbutself(cpu_online_mask, vector); +} + +static inline void numaq_send_IPI_all(int vector) +{ + numaq_send_IPI_mask(cpu_online_mask, vector); +} + +extern void numaq_mps_oem_check(struct mpc_table *, char *, char *); + +#define NUMAQ_TRAMPOLINE_PHYS_LOW (0x8) +#define NUMAQ_TRAMPOLINE_PHYS_HIGH (0xa) + +/* + * Because we use NMIs rather than the INIT-STARTUP sequence to + * bootstrap the CPUs, the APIC may be in a weird state. Kick it: + */ +static inline void numaq_smp_callin_clear_local_apic(void) +{ + clear_local_APIC(); +} + +static inline void +numaq_store_NMI_vector(unsigned short *high, unsigned short *low) +{ + printk("Storing NMI vector\n"); + *high = + *((volatile unsigned short *)phys_to_virt(NUMAQ_TRAMPOLINE_PHYS_HIGH)); + *low = + *((volatile unsigned short *)phys_to_virt(NUMAQ_TRAMPOLINE_PHYS_LOW)); +} + +static inline const cpumask_t *numaq_target_cpus(void) +{ + return &CPU_MASK_ALL; +} + +static inline unsigned long +numaq_check_apicid_used(physid_mask_t bitmap, int apicid) +{ + return physid_isset(apicid, bitmap); +} + +static inline unsigned long numaq_check_apicid_present(int bit) +{ + return physid_isset(bit, phys_cpu_present_map); +} + +#define apicid_cluster(apicid) (apicid & 0xF0) + +static inline int numaq_apic_id_registered(void) +{ + return 1; +} + +static inline void numaq_init_apic_ldr(void) +{ + /* Already done in NUMA-Q firmware */ +} + +static inline void numaq_setup_apic_routing(void) +{ + printk("Enabling APIC mode: %s. Using %d I/O APICs\n", + "NUMA-Q", nr_ioapics); +} + +/* + * Skip adding the timer int on secondary nodes, which causes + * a small but painful rift in the time-space continuum. + */ +static inline int numaq_multi_timer_check(int apic, int irq) +{ + return apic != 0 && irq == 0; +} + +static inline physid_mask_t numaq_ioapic_phys_id_map(physid_mask_t phys_map) +{ + /* We don't have a good way to do this yet - hack */ + return physids_promote(0xFUL); +} + +/* Mapping from cpu number to logical apicid */ +extern u8 cpu_2_logical_apicid[]; + +static inline int numaq_cpu_to_logical_apicid(int cpu) +{ + if (cpu >= nr_cpu_ids) + return BAD_APICID; + return (int)cpu_2_logical_apicid[cpu]; +} + +/* + * Supporting over 60 cpus on NUMA-Q requires a locality-dependent + * cpu to APIC ID relation to properly interact with the intelligent + * mode of the cluster controller. + */ +static inline int numaq_cpu_present_to_apicid(int mps_cpu) +{ + if (mps_cpu < 60) + return ((mps_cpu >> 2) << 4) | (1 << (mps_cpu & 0x3)); + else + return BAD_APICID; +} + +static inline int numaq_apicid_to_node(int logical_apicid) +{ + return logical_apicid >> 4; +} + +static inline physid_mask_t numaq_apicid_to_cpu_present(int logical_apicid) +{ + int node = numaq_apicid_to_node(logical_apicid); + int cpu = __ffs(logical_apicid & 0xf); + + return physid_mask_of_physid(cpu + 4*node); +} + +extern void *xquad_portio; + +static inline int numaq_check_phys_apicid_present(int boot_cpu_physical_apicid) +{ + return 1; +} + +/* + * We use physical apicids here, not logical, so just return the default + * physical broadcast to stop people from breaking us + */ +static inline unsigned int numaq_cpu_mask_to_apicid(const cpumask_t *cpumask) +{ + return 0x0F; +} + +static inline unsigned int +numaq_cpu_mask_to_apicid_and(const struct cpumask *cpumask, + const struct cpumask *andmask) +{ + return 0x0F; +} + +/* No NUMA-Q box has a HT CPU, but it can't hurt to use the default code. */ +static inline int numaq_phys_pkg_id(int cpuid_apic, int index_msb) +{ + return cpuid_apic >> index_msb; +} +static int __numaq_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) +{ + numaq_mps_oem_check(mpc, oem, productid); + return found_numaq; +} + +static int probe_numaq(void) +{ + /* already know from get_memcfg_numaq() */ + return found_numaq; +} + +static void numaq_vector_allocation_domain(int cpu, cpumask_t *retmask) +{ + /* Careful. Some cpus do not strictly honor the set of cpus + * specified in the interrupt destination when using lowest + * priority interrupt delivery mode. + * + * In particular there was a hyperthreading cpu observed to + * deliver interrupts to the wrong hyperthread when only one + * hyperthread was specified in the interrupt desitination. + */ + *retmask = (cpumask_t){ { [0] = APIC_ALL_CPUS, } }; +} + +static void numaq_setup_portio_remap(void) +{ + int num_quads = num_online_nodes(); + + if (num_quads <= 1) + return; + + printk("Remapping cross-quad port I/O for %d quads\n", num_quads); + xquad_portio = ioremap(XQUAD_PORTIO_BASE, num_quads*XQUAD_PORTIO_QUAD); + printk("xquad_portio vaddr 0x%08lx, len %08lx\n", + (u_long) xquad_portio, (u_long) num_quads*XQUAD_PORTIO_QUAD); +} + +struct genapic apic_numaq = { + + .name = "NUMAQ", + .probe = probe_numaq, + .acpi_madt_oem_check = NULL, + .apic_id_registered = numaq_apic_id_registered, + + .irq_delivery_mode = dest_LowestPrio, + /* physical delivery on LOCAL quad: */ + .irq_dest_mode = 0, + + .target_cpus = numaq_target_cpus, + .disable_esr = 1, + .dest_logical = APIC_DEST_LOGICAL, + .check_apicid_used = numaq_check_apicid_used, + .check_apicid_present = numaq_check_apicid_present, + + .vector_allocation_domain = numaq_vector_allocation_domain, + .init_apic_ldr = numaq_init_apic_ldr, + + .ioapic_phys_id_map = numaq_ioapic_phys_id_map, + .setup_apic_routing = numaq_setup_apic_routing, + .multi_timer_check = numaq_multi_timer_check, + .apicid_to_node = numaq_apicid_to_node, + .cpu_to_logical_apicid = numaq_cpu_to_logical_apicid, + .cpu_present_to_apicid = numaq_cpu_present_to_apicid, + .apicid_to_cpu_present = numaq_apicid_to_cpu_present, + .setup_portio_remap = numaq_setup_portio_remap, + .check_phys_apicid_present = numaq_check_phys_apicid_present, + .enable_apic_mode = NULL, + .phys_pkg_id = numaq_phys_pkg_id, + .mps_oem_check = __numaq_mps_oem_check, + + .get_apic_id = numaq_get_apic_id, + .set_apic_id = NULL, + .apic_id_mask = 0x0F << 24, + + .cpu_mask_to_apicid = numaq_cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = numaq_cpu_mask_to_apicid_and, + + .send_IPI_mask = numaq_send_IPI_mask, + .send_IPI_mask_allbutself = NULL, + .send_IPI_allbutself = numaq_send_IPI_allbutself, + .send_IPI_all = numaq_send_IPI_all, + .send_IPI_self = NULL, + + .wakeup_cpu = NULL, + .trampoline_phys_low = NUMAQ_TRAMPOLINE_PHYS_LOW, + .trampoline_phys_high = NUMAQ_TRAMPOLINE_PHYS_HIGH, + + /* We don't do anything here because we use NMI's to boot instead */ + .wait_for_init_deassert = NULL, + + .smp_callin_clear_local_apic = numaq_smp_callin_clear_local_apic, + .store_NMI_vector = numaq_store_NMI_vector, + .inquire_remote_apic = NULL, +}; diff --git a/arch/x86/mach-generic/Makefile b/arch/x86/mach-generic/Makefile index 05e47acfd66..4ede08d309e 100644 --- a/arch/x86/mach-generic/Makefile +++ b/arch/x86/mach-generic/Makefile @@ -5,5 +5,4 @@ EXTRA_CFLAGS := -Iarch/x86/kernel obj-y := probe.o default.o -obj-$(CONFIG_X86_NUMAQ) += numaq.o obj-$(CONFIG_X86_BIGSMP) += bigsmp.o diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c deleted file mode 100644 index c221cfb2c2d..00000000000 --- a/arch/x86/mach-generic/numaq.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * APIC driver for the IBM NUMAQ chipset. - */ -#define APIC_DEFINITION 1 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define NUMAQ_APIC_DFR_VALUE (APIC_DFR_CLUSTER) - -static inline unsigned int numaq_get_apic_id(unsigned long x) -{ - return (x >> 24) & 0x0F; -} - -void default_send_IPI_mask_sequence(const struct cpumask *mask, int vector); -void default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector); - -static inline void numaq_send_IPI_mask(const struct cpumask *mask, int vector) -{ - default_send_IPI_mask_sequence(mask, vector); -} - -static inline void numaq_send_IPI_allbutself(int vector) -{ - default_send_IPI_mask_allbutself(cpu_online_mask, vector); -} - -static inline void numaq_send_IPI_all(int vector) -{ - numaq_send_IPI_mask(cpu_online_mask, vector); -} - -extern void numaq_mps_oem_check(struct mpc_table *, char *, char *); - -#define NUMAQ_TRAMPOLINE_PHYS_LOW (0x8) -#define NUMAQ_TRAMPOLINE_PHYS_HIGH (0xa) - -/* - * Because we use NMIs rather than the INIT-STARTUP sequence to - * bootstrap the CPUs, the APIC may be in a weird state. Kick it: - */ -static inline void numaq_smp_callin_clear_local_apic(void) -{ - clear_local_APIC(); -} - -static inline void -numaq_store_NMI_vector(unsigned short *high, unsigned short *low) -{ - printk("Storing NMI vector\n"); - *high = - *((volatile unsigned short *)phys_to_virt(NUMAQ_TRAMPOLINE_PHYS_HIGH)); - *low = - *((volatile unsigned short *)phys_to_virt(NUMAQ_TRAMPOLINE_PHYS_LOW)); -} - -static inline const cpumask_t *numaq_target_cpus(void) -{ - return &CPU_MASK_ALL; -} - -static inline unsigned long -numaq_check_apicid_used(physid_mask_t bitmap, int apicid) -{ - return physid_isset(apicid, bitmap); -} - -static inline unsigned long numaq_check_apicid_present(int bit) -{ - return physid_isset(bit, phys_cpu_present_map); -} - -#define apicid_cluster(apicid) (apicid & 0xF0) - -static inline int numaq_apic_id_registered(void) -{ - return 1; -} - -static inline void numaq_init_apic_ldr(void) -{ - /* Already done in NUMA-Q firmware */ -} - -static inline void numaq_setup_apic_routing(void) -{ - printk("Enabling APIC mode: %s. Using %d I/O APICs\n", - "NUMA-Q", nr_ioapics); -} - -/* - * Skip adding the timer int on secondary nodes, which causes - * a small but painful rift in the time-space continuum. - */ -static inline int numaq_multi_timer_check(int apic, int irq) -{ - return apic != 0 && irq == 0; -} - -static inline physid_mask_t numaq_ioapic_phys_id_map(physid_mask_t phys_map) -{ - /* We don't have a good way to do this yet - hack */ - return physids_promote(0xFUL); -} - -/* Mapping from cpu number to logical apicid */ -extern u8 cpu_2_logical_apicid[]; - -static inline int numaq_cpu_to_logical_apicid(int cpu) -{ - if (cpu >= nr_cpu_ids) - return BAD_APICID; - return (int)cpu_2_logical_apicid[cpu]; -} - -/* - * Supporting over 60 cpus on NUMA-Q requires a locality-dependent - * cpu to APIC ID relation to properly interact with the intelligent - * mode of the cluster controller. - */ -static inline int numaq_cpu_present_to_apicid(int mps_cpu) -{ - if (mps_cpu < 60) - return ((mps_cpu >> 2) << 4) | (1 << (mps_cpu & 0x3)); - else - return BAD_APICID; -} - -static inline int numaq_apicid_to_node(int logical_apicid) -{ - return logical_apicid >> 4; -} - -static inline physid_mask_t numaq_apicid_to_cpu_present(int logical_apicid) -{ - int node = numaq_apicid_to_node(logical_apicid); - int cpu = __ffs(logical_apicid & 0xf); - - return physid_mask_of_physid(cpu + 4*node); -} - -extern void *xquad_portio; - -static inline int numaq_check_phys_apicid_present(int boot_cpu_physical_apicid) -{ - return 1; -} - -/* - * We use physical apicids here, not logical, so just return the default - * physical broadcast to stop people from breaking us - */ -static inline unsigned int numaq_cpu_mask_to_apicid(const cpumask_t *cpumask) -{ - return 0x0F; -} - -static inline unsigned int -numaq_cpu_mask_to_apicid_and(const struct cpumask *cpumask, - const struct cpumask *andmask) -{ - return 0x0F; -} - -/* No NUMA-Q box has a HT CPU, but it can't hurt to use the default code. */ -static inline int numaq_phys_pkg_id(int cpuid_apic, int index_msb) -{ - return cpuid_apic >> index_msb; -} -static int __numaq_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) -{ - numaq_mps_oem_check(mpc, oem, productid); - return found_numaq; -} - -static int probe_numaq(void) -{ - /* already know from get_memcfg_numaq() */ - return found_numaq; -} - -static void numaq_vector_allocation_domain(int cpu, cpumask_t *retmask) -{ - /* Careful. Some cpus do not strictly honor the set of cpus - * specified in the interrupt destination when using lowest - * priority interrupt delivery mode. - * - * In particular there was a hyperthreading cpu observed to - * deliver interrupts to the wrong hyperthread when only one - * hyperthread was specified in the interrupt desitination. - */ - *retmask = (cpumask_t){ { [0] = APIC_ALL_CPUS, } }; -} - -static void numaq_setup_portio_remap(void) -{ - int num_quads = num_online_nodes(); - - if (num_quads <= 1) - return; - - printk("Remapping cross-quad port I/O for %d quads\n", num_quads); - xquad_portio = ioremap(XQUAD_PORTIO_BASE, num_quads*XQUAD_PORTIO_QUAD); - printk("xquad_portio vaddr 0x%08lx, len %08lx\n", - (u_long) xquad_portio, (u_long) num_quads*XQUAD_PORTIO_QUAD); -} - -struct genapic apic_numaq = { - - .name = "NUMAQ", - .probe = probe_numaq, - .acpi_madt_oem_check = NULL, - .apic_id_registered = numaq_apic_id_registered, - - .irq_delivery_mode = dest_LowestPrio, - /* physical delivery on LOCAL quad: */ - .irq_dest_mode = 0, - - .target_cpus = numaq_target_cpus, - .disable_esr = 1, - .dest_logical = APIC_DEST_LOGICAL, - .check_apicid_used = numaq_check_apicid_used, - .check_apicid_present = numaq_check_apicid_present, - - .vector_allocation_domain = numaq_vector_allocation_domain, - .init_apic_ldr = numaq_init_apic_ldr, - - .ioapic_phys_id_map = numaq_ioapic_phys_id_map, - .setup_apic_routing = numaq_setup_apic_routing, - .multi_timer_check = numaq_multi_timer_check, - .apicid_to_node = numaq_apicid_to_node, - .cpu_to_logical_apicid = numaq_cpu_to_logical_apicid, - .cpu_present_to_apicid = numaq_cpu_present_to_apicid, - .apicid_to_cpu_present = numaq_apicid_to_cpu_present, - .setup_portio_remap = numaq_setup_portio_remap, - .check_phys_apicid_present = numaq_check_phys_apicid_present, - .enable_apic_mode = NULL, - .phys_pkg_id = numaq_phys_pkg_id, - .mps_oem_check = __numaq_mps_oem_check, - - .get_apic_id = numaq_get_apic_id, - .set_apic_id = NULL, - .apic_id_mask = 0x0F << 24, - - .cpu_mask_to_apicid = numaq_cpu_mask_to_apicid, - .cpu_mask_to_apicid_and = numaq_cpu_mask_to_apicid_and, - - .send_IPI_mask = numaq_send_IPI_mask, - .send_IPI_mask_allbutself = NULL, - .send_IPI_allbutself = numaq_send_IPI_allbutself, - .send_IPI_all = numaq_send_IPI_all, - .send_IPI_self = NULL, - - .wakeup_cpu = NULL, - .trampoline_phys_low = NUMAQ_TRAMPOLINE_PHYS_LOW, - .trampoline_phys_high = NUMAQ_TRAMPOLINE_PHYS_HIGH, - - /* We don't do anything here because we use NMI's to boot instead */ - .wait_for_init_deassert = NULL, - - .smp_callin_clear_local_apic = numaq_smp_callin_clear_local_apic, - .store_NMI_vector = numaq_store_NMI_vector, - .inquire_remote_apic = NULL, -}; -- GitLab From b3daa3a1a56cf09fb91773f3658692fd02d08bb1 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 19:04:37 +0100 Subject: [PATCH 0623/4982] x86, bigsmp: consolidate code Move all code to arch/x86/kernel/bigsmp_32.c. With this it ceases to rely on any build-time subarch features. Signed-off-by: Ingo Molnar --- arch/x86/kernel/Makefile | 1 + arch/x86/{mach-generic/bigsmp.c => kernel/bigsmp_32.c} | 0 arch/x86/mach-generic/Makefile | 1 - 3 files changed, 1 insertion(+), 1 deletion(-) rename arch/x86/{mach-generic/bigsmp.c => kernel/bigsmp_32.c} (100%) diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index a382ca6f6a1..4239847906a 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -71,6 +71,7 @@ obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o obj-$(CONFIG_KEXEC) += machine_kexec_$(BITS).o obj-$(CONFIG_KEXEC) += relocate_kernel_$(BITS).o crash.o obj-$(CONFIG_CRASH_DUMP) += crash_dump_$(BITS).o +obj-$(CONFIG_X86_BIGSMP) += bigsmp_32.o obj-$(CONFIG_X86_NUMAQ) += numaq_32.o obj-$(CONFIG_X86_ES7000) += es7000_32.o obj-$(CONFIG_X86_SUMMIT) += summit_32.o diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/kernel/bigsmp_32.c similarity index 100% rename from arch/x86/mach-generic/bigsmp.c rename to arch/x86/kernel/bigsmp_32.c diff --git a/arch/x86/mach-generic/Makefile b/arch/x86/mach-generic/Makefile index 4ede08d309e..05e4a7ca774 100644 --- a/arch/x86/mach-generic/Makefile +++ b/arch/x86/mach-generic/Makefile @@ -5,4 +5,3 @@ EXTRA_CFLAGS := -Iarch/x86/kernel obj-y := probe.o default.o -obj-$(CONFIG_X86_BIGSMP) += bigsmp.o -- GitLab From 9f4187f0a3b93fc215b4472063b6c0b44364e60c Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 19:19:12 +0100 Subject: [PATCH 0624/4982] x86, bigsmp: consolidate header code Move all the asm/bigsmp/*.h definitions into bigsmp_32.c. Signed-off-by: Ingo Molnar --- arch/x86/kernel/bigsmp_32.c | 163 +++++++++++++++++++++++++++++++++++- 1 file changed, 159 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/bigsmp_32.c b/arch/x86/kernel/bigsmp_32.c index 626f45ca4e7..b1f91931003 100644 --- a/arch/x86/kernel/bigsmp_32.c +++ b/arch/x86/kernel/bigsmp_32.c @@ -12,10 +12,165 @@ #include #include #include -#include #include -#include -#include + + +static inline unsigned bigsmp_get_apic_id(unsigned long x) +{ + return (x >> 24) & 0xFF; +} + +#define xapic_phys_to_log_apicid(cpu) (per_cpu(x86_bios_cpu_apicid, cpu)) + +static inline int bigsmp_apic_id_registered(void) +{ + return 1; +} + +static inline const cpumask_t *bigsmp_target_cpus(void) +{ +#ifdef CONFIG_SMP + return &cpu_online_map; +#else + return &cpumask_of_cpu(0); +#endif +} + +#define APIC_DFR_VALUE (APIC_DFR_FLAT) + +static inline unsigned long +bigsmp_check_apicid_used(physid_mask_t bitmap, int apicid) +{ + return 0; +} + +static inline unsigned long bigsmp_check_apicid_present(int bit) +{ + return 1; +} + +static inline unsigned long calculate_ldr(int cpu) +{ + unsigned long val, id; + val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; + id = xapic_phys_to_log_apicid(cpu); + val |= SET_APIC_LOGICAL_ID(id); + return val; +} + +/* + * Set up the logical destination ID. + * + * Intel recommends to set DFR, LDR and TPR before enabling + * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel + * document number 292116). So here it goes... + */ +static inline void bigsmp_init_apic_ldr(void) +{ + unsigned long val; + int cpu = smp_processor_id(); + + apic_write(APIC_DFR, APIC_DFR_VALUE); + val = calculate_ldr(cpu); + apic_write(APIC_LDR, val); +} + +static inline void bigsmp_setup_apic_routing(void) +{ + printk("Enabling APIC mode: %s. Using %d I/O APICs\n", + "Physflat", nr_ioapics); +} + +static inline int bigsmp_apicid_to_node(int logical_apicid) +{ + return apicid_2_node[hard_smp_processor_id()]; +} + +static inline int bigsmp_cpu_present_to_apicid(int mps_cpu) +{ + if (mps_cpu < nr_cpu_ids) + return (int) per_cpu(x86_bios_cpu_apicid, mps_cpu); + + return BAD_APICID; +} + +static inline physid_mask_t bigsmp_apicid_to_cpu_present(int phys_apicid) +{ + return physid_mask_of_physid(phys_apicid); +} + +extern u8 cpu_2_logical_apicid[]; +/* Mapping from cpu number to logical apicid */ +static inline int bigsmp_cpu_to_logical_apicid(int cpu) +{ + if (cpu >= nr_cpu_ids) + return BAD_APICID; + return cpu_physical_id(cpu); +} + +static inline physid_mask_t bigsmp_ioapic_phys_id_map(physid_mask_t phys_map) +{ + /* For clustered we don't have a good way to do this yet - hack */ + return physids_promote(0xFFL); +} + +static inline void bigsmp_setup_portio_remap(void) +{ +} + +static inline int bigsmp_check_phys_apicid_present(int boot_cpu_physical_apicid) +{ + return 1; +} + +/* As we are using single CPU as destination, pick only one CPU here */ +static inline unsigned int bigsmp_cpu_mask_to_apicid(const cpumask_t *cpumask) +{ + return bigsmp_cpu_to_logical_apicid(first_cpu(*cpumask)); +} + +static inline unsigned int +bigsmp_cpu_mask_to_apicid_and(const struct cpumask *cpumask, + const struct cpumask *andmask) +{ + int cpu; + + /* + * We're using fixed IRQ delivery, can only return one phys APIC ID. + * May as well be the first. + */ + for_each_cpu_and(cpu, cpumask, andmask) { + if (cpumask_test_cpu(cpu, cpu_online_mask)) + break; + } + if (cpu < nr_cpu_ids) + return bigsmp_cpu_to_logical_apicid(cpu); + + return BAD_APICID; +} + +static inline int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb) +{ + return cpuid_apic >> index_msb; +} + +void default_send_IPI_mask_sequence(const struct cpumask *mask, int vector); +void default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector); + +static inline void bigsmp_send_IPI_mask(const struct cpumask *mask, int vector) +{ + default_send_IPI_mask_sequence(mask, vector); +} + +static inline void bigsmp_send_IPI_allbutself(int vector) +{ + default_send_IPI_mask_allbutself(cpu_online_mask, vector); +} + +static inline void bigsmp_send_IPI_all(int vector) +{ + bigsmp_send_IPI_mask(cpu_online_mask, vector); +} static int dmi_bigsmp; /* can be set by dmi scanners */ @@ -95,7 +250,7 @@ struct genapic apic_bigsmp = { .cpu_mask_to_apicid = bigsmp_cpu_mask_to_apicid, .cpu_mask_to_apicid_and = bigsmp_cpu_mask_to_apicid_and, - .send_IPI_mask = default_send_IPI_mask, + .send_IPI_mask = bigsmp_send_IPI_mask, .send_IPI_mask_allbutself = NULL, .send_IPI_allbutself = bigsmp_send_IPI_allbutself, .send_IPI_all = bigsmp_send_IPI_all, -- GitLab From d53e2f2855f1c7c2725d550c1ae6b26f4d671c50 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 19:14:52 +0100 Subject: [PATCH 0625/4982] x86, smp: remove mach_ipi.h Move mach_ipi.h definitions into genapic.h. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/genapic.h | 1 + arch/x86/include/asm/ipi.h | 61 ++++++++++++++++++- arch/x86/include/asm/mach-default/mach_ipi.h | 58 ------------------ arch/x86/include/asm/mach-generic/gpio.h | 15 ----- arch/x86/include/asm/mach-generic/mach_ipi.h | 6 -- .../include/asm/mach-generic/mach_wakecpu.h | 4 -- arch/x86/kernel/apic.c | 2 +- arch/x86/kernel/crash.c | 2 +- arch/x86/kernel/io_apic.c | 1 - arch/x86/kernel/ipi.c | 1 - arch/x86/kernel/kgdb.c | 2 +- arch/x86/kernel/reboot.c | 2 +- arch/x86/kernel/smp.c | 1 - arch/x86/kernel/visws_quirks.c | 2 +- arch/x86/mach-default/setup.c | 2 +- arch/x86/mach-generic/default.c | 2 +- arch/x86/mm/tlb.c | 2 +- 17 files changed, 68 insertions(+), 96 deletions(-) delete mode 100644 arch/x86/include/asm/mach-default/mach_ipi.h delete mode 100644 arch/x86/include/asm/mach-generic/gpio.h delete mode 100644 arch/x86/include/asm/mach-generic/mach_ipi.h delete mode 100644 arch/x86/include/asm/mach-generic/mach_wakecpu.h diff --git a/arch/x86/include/asm/genapic.h b/arch/x86/include/asm/genapic.h index ccfcd19d5b7..273b99452ae 100644 --- a/arch/x86/include/asm/genapic.h +++ b/arch/x86/include/asm/genapic.h @@ -259,4 +259,5 @@ static inline physid_mask_t default_apicid_to_cpu_present(int phys_apicid) } #endif /* CONFIG_X86_LOCAL_APIC */ + #endif /* _ASM_X86_GENAPIC_64_H */ diff --git a/arch/x86/include/asm/ipi.h b/arch/x86/include/asm/ipi.h index a8d717f2c7e..e2e8e4e0a65 100644 --- a/arch/x86/include/asm/ipi.h +++ b/arch/x86/include/asm/ipi.h @@ -1,6 +1,8 @@ #ifndef _ASM_X86_IPI_H #define _ASM_X86_IPI_H +#ifdef CONFIG_X86_LOCAL_APIC + /* * Copyright 2004 James Cleverdon, IBM. * Subject to the GNU Public License, v.2 @@ -56,8 +58,7 @@ static inline void __xapic_wait_icr_idle(void) } static inline void -__default_send_IPI_shortcut(unsigned int shortcut, - int vector, unsigned int dest) +__default_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest) { /* * Subtle. In the case of the 'never do double writes' workaround @@ -156,4 +157,60 @@ default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector) local_irq_restore(flags); } + +/* Avoid include hell */ +#define NMI_VECTOR 0x02 + +void default_send_IPI_mask_bitmask(const struct cpumask *mask, int vector); +void default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector); + +extern int no_broadcast; + +#ifdef CONFIG_X86_64 +#include +#else +static inline void default_send_IPI_mask(const struct cpumask *mask, int vector) +{ + default_send_IPI_mask_bitmask(mask, vector); +} +void default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector); +#endif + +static inline void __default_local_send_IPI_allbutself(int vector) +{ + if (no_broadcast || vector == NMI_VECTOR) + apic->send_IPI_mask_allbutself(cpu_online_mask, vector); + else + __default_send_IPI_shortcut(APIC_DEST_ALLBUT, vector, apic->dest_logical); +} + +static inline void __default_local_send_IPI_all(int vector) +{ + if (no_broadcast || vector == NMI_VECTOR) + apic->send_IPI_mask(cpu_online_mask, vector); + else + __default_send_IPI_shortcut(APIC_DEST_ALLINC, vector, apic->dest_logical); +} + +#ifdef CONFIG_X86_32 +static inline void default_send_IPI_allbutself(int vector) +{ + /* + * if there are no other CPUs in the system then we get an APIC send + * error if we try to broadcast, thus avoid sending IPIs in this case. + */ + if (!(num_online_cpus() > 1)) + return; + + __default_local_send_IPI_allbutself(vector); +} + +static inline void default_send_IPI_all(int vector) +{ + __default_local_send_IPI_all(vector); +} +#endif + +#endif + #endif /* _ASM_X86_IPI_H */ diff --git a/arch/x86/include/asm/mach-default/mach_ipi.h b/arch/x86/include/asm/mach-default/mach_ipi.h deleted file mode 100644 index 85dec630c69..00000000000 --- a/arch/x86/include/asm/mach-default/mach_ipi.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef _ASM_X86_MACH_DEFAULT_MACH_IPI_H -#define _ASM_X86_MACH_DEFAULT_MACH_IPI_H - -/* Avoid include hell */ -#define NMI_VECTOR 0x02 - -void default_send_IPI_mask_bitmask(const struct cpumask *mask, int vector); -void default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector); -void __default_send_IPI_shortcut(unsigned int shortcut, int vector); - -extern int no_broadcast; - -#ifdef CONFIG_X86_64 -#include -#else -static inline void default_send_IPI_mask(const struct cpumask *mask, int vector) -{ - default_send_IPI_mask_bitmask(mask, vector); -} -void default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector); -#endif - -static inline void __default_local_send_IPI_allbutself(int vector) -{ - if (no_broadcast || vector == NMI_VECTOR) - apic->send_IPI_mask_allbutself(cpu_online_mask, vector); - else - __default_send_IPI_shortcut(APIC_DEST_ALLBUT, vector); -} - -static inline void __default_local_send_IPI_all(int vector) -{ - if (no_broadcast || vector == NMI_VECTOR) - apic->send_IPI_mask(cpu_online_mask, vector); - else - __default_send_IPI_shortcut(APIC_DEST_ALLINC, vector); -} - -#ifdef CONFIG_X86_32 -static inline void default_send_IPI_allbutself(int vector) -{ - /* - * if there are no other CPUs in the system then we get an APIC send - * error if we try to broadcast, thus avoid sending IPIs in this case. - */ - if (!(num_online_cpus() > 1)) - return; - - __default_local_send_IPI_allbutself(vector); -} - -static inline void default_send_IPI_all(int vector) -{ - __default_local_send_IPI_all(vector); -} -#endif - -#endif /* _ASM_X86_MACH_DEFAULT_MACH_IPI_H */ diff --git a/arch/x86/include/asm/mach-generic/gpio.h b/arch/x86/include/asm/mach-generic/gpio.h deleted file mode 100644 index 995c45efdb3..00000000000 --- a/arch/x86/include/asm/mach-generic/gpio.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _ASM_X86_MACH_GENERIC_GPIO_H -#define _ASM_X86_MACH_GENERIC_GPIO_H - -int gpio_request(unsigned gpio, const char *label); -void gpio_free(unsigned gpio); -int gpio_direction_input(unsigned gpio); -int gpio_direction_output(unsigned gpio, int value); -int gpio_get_value(unsigned gpio); -void gpio_set_value(unsigned gpio, int value); -int gpio_to_irq(unsigned gpio); -int irq_to_gpio(unsigned irq); - -#include /* cansleep wrappers */ - -#endif /* _ASM_X86_MACH_GENERIC_GPIO_H */ diff --git a/arch/x86/include/asm/mach-generic/mach_ipi.h b/arch/x86/include/asm/mach-generic/mach_ipi.h deleted file mode 100644 index 5691c09645c..00000000000 --- a/arch/x86/include/asm/mach-generic/mach_ipi.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_X86_MACH_GENERIC_MACH_IPI_H -#define _ASM_X86_MACH_GENERIC_MACH_IPI_H - -#include - -#endif /* _ASM_X86_MACH_GENERIC_MACH_IPI_H */ diff --git a/arch/x86/include/asm/mach-generic/mach_wakecpu.h b/arch/x86/include/asm/mach-generic/mach_wakecpu.h deleted file mode 100644 index 0b884c03a3f..00000000000 --- a/arch/x86/include/asm/mach-generic/mach_wakecpu.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef _ASM_X86_MACH_GENERIC_MACH_WAKECPU_H -#define _ASM_X86_MACH_GENERIC_MACH_WAKECPU_H - -#endif /* _ASM_X86_MACH_GENERIC_MACH_APIC_H */ diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 41a0ba34d6b..81efe86eca8 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -49,7 +49,7 @@ #include #include -#include +#include /* * Sanity check diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c index 11b93cabdf7..ad7f2a696f4 100644 --- a/arch/x86/kernel/crash.c +++ b/arch/x86/kernel/crash.c @@ -28,7 +28,7 @@ #include #include -#include +#include #if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC) diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index e0744ea6d0f..241a01d6fd4 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -62,7 +62,6 @@ #include #include -#include #include #define __apicdebuginit(type) static type __init diff --git a/arch/x86/kernel/ipi.c b/arch/x86/kernel/ipi.c index 50076d92fbc..0893fa14458 100644 --- a/arch/x86/kernel/ipi.c +++ b/arch/x86/kernel/ipi.c @@ -20,7 +20,6 @@ #ifdef CONFIG_X86_32 #include -#include /* * the following functions deal with sending IPIs between CPUs. diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index b62a3811e01..5c4f5548384 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c @@ -46,7 +46,7 @@ #include #include -#include +#include /* * Put the error code here just in case the user cares: diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 38dace28d62..32e8f0af292 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -24,7 +24,7 @@ # include #endif -#include +#include /* * Power off function, if any diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index 892e7c389be..0eb32ae9bf1 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c @@ -26,7 +26,6 @@ #include #include #include -#include #include /* * Some notes on x86 processor bugs affecting SMP operation: diff --git a/arch/x86/kernel/visws_quirks.c b/arch/x86/kernel/visws_quirks.c index 3bd7f47a91b..4fd646e6dd4 100644 --- a/arch/x86/kernel/visws_quirks.c +++ b/arch/x86/kernel/visws_quirks.c @@ -32,7 +32,7 @@ #include #include -#include +#include #include diff --git a/arch/x86/mach-default/setup.c b/arch/x86/mach-default/setup.c index df167f26562..b65ff0bf730 100644 --- a/arch/x86/mach-default/setup.c +++ b/arch/x86/mach-default/setup.c @@ -10,7 +10,7 @@ #include #include -#include +#include #ifdef CONFIG_HOTPLUG_CPU #define DEFAULT_SEND_IPI (1) diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index 7d5123e474e..d9d44c8c3db 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include static void default_vector_allocation_domain(int cpu, struct cpumask *retmask) { diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 6348e114692..14c5af4d11e 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -14,7 +14,7 @@ DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) = { &init_mm, 0, }; -#include +#include /* * Smarter SMP flushing macros. * c/o Linus Torvalds. -- GitLab From 7b38725318f4517af6168ccbff99060d67aba1c8 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 19:11:44 +0100 Subject: [PATCH 0626/4982] x86: remove subarchitecture support code Remove remaining bits of the subarchitecture code. Now that all the special platforms are runtime probed and runtime handled, we can remove these facilities. Signed-off-by: Ingo Molnar --- arch/x86/Makefile | 5 - arch/x86/kernel/Makefile | 2 +- .../probe.c => kernel/probe_32.c} | 92 +++++++++++++++++++ arch/x86/mach-generic/Makefile | 7 -- 4 files changed, 93 insertions(+), 13 deletions(-) rename arch/x86/{mach-generic/probe.c => kernel/probe_32.c} (54%) delete mode 100644 arch/x86/mach-generic/Makefile diff --git a/arch/x86/Makefile b/arch/x86/Makefile index cacee981d16..799a0d931c8 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -113,11 +113,6 @@ mcore-y := arch/x86/mach-default/ mflags-$(CONFIG_X86_VOYAGER) := -Iarch/x86/include/asm/mach-voyager mcore-$(CONFIG_X86_VOYAGER) := arch/x86/mach-voyager/ -# generic subarchitecture -mflags-$(CONFIG_X86_GENERICARCH):= -Iarch/x86/include/asm/mach-generic -fcore-$(CONFIG_X86_GENERICARCH) += arch/x86/mach-generic/ -mcore-$(CONFIG_X86_GENERICARCH) := arch/x86/mach-default/ - # default subarch .h files mflags-y += -Iarch/x86/include/asm/mach-default diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 4239847906a..d3f8f49aed6 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -30,7 +30,7 @@ obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o obj-y += time_$(BITS).o ioport.o ldt.o dumpstack.o obj-y += setup.o i8259.o irqinit_$(BITS).o obj-$(CONFIG_X86_VISWS) += visws_quirks.o -obj-$(CONFIG_X86_32) += probe_roms_32.o +obj-$(CONFIG_X86_32) += probe_32.o probe_roms_32.o obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o obj-$(CONFIG_X86_64) += syscall_64.o vsyscall_64.o diff --git a/arch/x86/mach-generic/probe.c b/arch/x86/kernel/probe_32.c similarity index 54% rename from arch/x86/mach-generic/probe.c rename to arch/x86/kernel/probe_32.c index c03c7222132..a6fba691416 100644 --- a/arch/x86/mach-generic/probe.c +++ b/arch/x86/kernel/probe_32.c @@ -1,4 +1,6 @@ /* + * Default generic APIC driver. This handles up to 8 CPUs. + * * Copyright 2003 Andi Kleen, SuSE Labs. * Subject to the GNU Public License, v.2 * @@ -17,6 +19,96 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void default_vector_allocation_domain(int cpu, struct cpumask *retmask) +{ + /* + * Careful. Some cpus do not strictly honor the set of cpus + * specified in the interrupt destination when using lowest + * priority interrupt delivery mode. + * + * In particular there was a hyperthreading cpu observed to + * deliver interrupts to the wrong hyperthread when only one + * hyperthread was specified in the interrupt desitination. + */ + *retmask = (cpumask_t) { { [0] = APIC_ALL_CPUS } }; +} + +/* should be called last. */ +static int probe_default(void) +{ + return 1; +} + +struct genapic apic_default = { + + .name = "default", + .probe = probe_default, + .acpi_madt_oem_check = NULL, + .apic_id_registered = default_apic_id_registered, + + .irq_delivery_mode = dest_LowestPrio, + /* logical delivery broadcast to all CPUs: */ + .irq_dest_mode = 1, + + .target_cpus = default_target_cpus, + .disable_esr = 0, + .dest_logical = APIC_DEST_LOGICAL, + .check_apicid_used = default_check_apicid_used, + .check_apicid_present = default_check_apicid_present, + + .vector_allocation_domain = default_vector_allocation_domain, + .init_apic_ldr = default_init_apic_ldr, + + .ioapic_phys_id_map = default_ioapic_phys_id_map, + .setup_apic_routing = default_setup_apic_routing, + .multi_timer_check = NULL, + .apicid_to_node = default_apicid_to_node, + .cpu_to_logical_apicid = default_cpu_to_logical_apicid, + .cpu_present_to_apicid = default_cpu_present_to_apicid, + .apicid_to_cpu_present = default_apicid_to_cpu_present, + .setup_portio_remap = NULL, + .check_phys_apicid_present = default_check_phys_apicid_present, + .enable_apic_mode = NULL, + .phys_pkg_id = default_phys_pkg_id, + .mps_oem_check = NULL, + + .get_apic_id = default_get_apic_id, + .set_apic_id = NULL, + .apic_id_mask = 0x0F << 24, + + .cpu_mask_to_apicid = default_cpu_mask_to_apicid, + .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, + + .send_IPI_mask = default_send_IPI_mask, + .send_IPI_mask_allbutself = NULL, + .send_IPI_allbutself = default_send_IPI_allbutself, + .send_IPI_all = default_send_IPI_all, + .send_IPI_self = NULL, + + .wakeup_cpu = NULL, + .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, + .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, + + .wait_for_init_deassert = default_wait_for_init_deassert, + + .smp_callin_clear_local_apic = NULL, + .store_NMI_vector = NULL, + .inquire_remote_apic = default_inquire_remote_apic, +}; + extern struct genapic apic_numaq; extern struct genapic apic_summit; extern struct genapic apic_bigsmp; diff --git a/arch/x86/mach-generic/Makefile b/arch/x86/mach-generic/Makefile deleted file mode 100644 index 05e4a7ca774..00000000000 --- a/arch/x86/mach-generic/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# Makefile for the generic architecture -# - -EXTRA_CFLAGS := -Iarch/x86/kernel - -obj-y := probe.o default.o -- GitLab From 1164dd0099c0d79146a55319670f57ab7ad1d352 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 19:34:09 +0100 Subject: [PATCH 0627/4982] x86: move mach-default/*.h files to asm/ We are getting rid of subarchitecture support - move the hook files to asm/. (These are now stale and should be replaced with more explicit runtime mechanisms - but the transition is simpler this way.) Signed-off-by: Ingo Molnar --- arch/x86/include/asm/{mach-default => }/apm.h | 0 arch/x86/include/asm/{mach-default => }/do_timer.h | 0 arch/x86/include/asm/{mach-default => }/entry_arch.h | 5 +++++ arch/x86/include/asm/{mach-default => }/mach_timer.h | 0 arch/x86/include/asm/{mach-default => }/mach_traps.h | 0 arch/x86/include/asm/{mach-default => }/pci-functions.h | 0 arch/x86/include/asm/{mach-default => }/setup_arch.h | 0 arch/x86/include/asm/{mach-default => }/smpboot_hooks.h | 0 arch/x86/kernel/apm_32.c | 2 +- arch/x86/kernel/entry_32.S | 2 +- arch/x86/kernel/nmi.c | 2 +- arch/x86/kernel/probe_roms_32.c | 2 +- arch/x86/kernel/setup.c | 2 +- arch/x86/kernel/smpboot.c | 2 +- arch/x86/kernel/time_32.c | 2 +- arch/x86/kernel/traps.c | 2 +- arch/x86/pci/pcbios.c | 2 +- drivers/clocksource/acpi_pm.c | 2 +- drivers/clocksource/cyclone.c | 2 +- 19 files changed, 16 insertions(+), 11 deletions(-) rename arch/x86/include/asm/{mach-default => }/apm.h (100%) rename arch/x86/include/asm/{mach-default => }/do_timer.h (100%) rename arch/x86/include/asm/{mach-default => }/entry_arch.h (95%) rename arch/x86/include/asm/{mach-default => }/mach_timer.h (100%) rename arch/x86/include/asm/{mach-default => }/mach_traps.h (100%) rename arch/x86/include/asm/{mach-default => }/pci-functions.h (100%) rename arch/x86/include/asm/{mach-default => }/setup_arch.h (100%) rename arch/x86/include/asm/{mach-default => }/smpboot_hooks.h (100%) diff --git a/arch/x86/include/asm/mach-default/apm.h b/arch/x86/include/asm/apm.h similarity index 100% rename from arch/x86/include/asm/mach-default/apm.h rename to arch/x86/include/asm/apm.h diff --git a/arch/x86/include/asm/mach-default/do_timer.h b/arch/x86/include/asm/do_timer.h similarity index 100% rename from arch/x86/include/asm/mach-default/do_timer.h rename to arch/x86/include/asm/do_timer.h diff --git a/arch/x86/include/asm/mach-default/entry_arch.h b/arch/x86/include/asm/entry_arch.h similarity index 95% rename from arch/x86/include/asm/mach-default/entry_arch.h rename to arch/x86/include/asm/entry_arch.h index 6fa399ad1de..b87b077cc23 100644 --- a/arch/x86/include/asm/mach-default/entry_arch.h +++ b/arch/x86/include/asm/entry_arch.h @@ -41,10 +41,15 @@ BUILD_INTERRUPT3(invalidate_interrupt7,INVALIDATE_TLB_VECTOR_START+7, * a much simpler SMP time architecture: */ #ifdef CONFIG_X86_LOCAL_APIC + BUILD_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR) BUILD_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR) BUILD_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR) +#ifdef CONFIG_PERF_COUNTERS +BUILD_INTERRUPT(perf_counter_interrupt, LOCAL_PERF_VECTOR) +#endif + #ifdef CONFIG_X86_MCE_P4THERMAL BUILD_INTERRUPT(thermal_interrupt,THERMAL_APIC_VECTOR) #endif diff --git a/arch/x86/include/asm/mach-default/mach_timer.h b/arch/x86/include/asm/mach_timer.h similarity index 100% rename from arch/x86/include/asm/mach-default/mach_timer.h rename to arch/x86/include/asm/mach_timer.h diff --git a/arch/x86/include/asm/mach-default/mach_traps.h b/arch/x86/include/asm/mach_traps.h similarity index 100% rename from arch/x86/include/asm/mach-default/mach_traps.h rename to arch/x86/include/asm/mach_traps.h diff --git a/arch/x86/include/asm/mach-default/pci-functions.h b/arch/x86/include/asm/pci-functions.h similarity index 100% rename from arch/x86/include/asm/mach-default/pci-functions.h rename to arch/x86/include/asm/pci-functions.h diff --git a/arch/x86/include/asm/mach-default/setup_arch.h b/arch/x86/include/asm/setup_arch.h similarity index 100% rename from arch/x86/include/asm/mach-default/setup_arch.h rename to arch/x86/include/asm/setup_arch.h diff --git a/arch/x86/include/asm/mach-default/smpboot_hooks.h b/arch/x86/include/asm/smpboot_hooks.h similarity index 100% rename from arch/x86/include/asm/mach-default/smpboot_hooks.h rename to arch/x86/include/asm/smpboot_hooks.h diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index 98807bb095a..37ba5f85b71 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c @@ -301,7 +301,7 @@ extern int (*console_blank_hook)(int); */ #define APM_ZERO_SEGS -#include "apm.h" +#include /* * Define to re-initialize the interrupt 0 timer to 100 Hz after a suspend. diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index a0b91aac72a..65efd42454b 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S @@ -688,7 +688,7 @@ ENDPROC(name) #define BUILD_INTERRUPT(name, nr) BUILD_INTERRUPT3(name, nr, smp_##name) /* The include is where all of the SMP etc. interrupts come from */ -#include "entry_arch.h" +#include ENTRY(coprocessor_error) RING0_INT_FRAME diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c index 23b6d9e6e4f..bdfad80c3cf 100644 --- a/arch/x86/kernel/nmi.c +++ b/arch/x86/kernel/nmi.c @@ -34,7 +34,7 @@ #include -#include +#include int unknown_nmi_panic; int nmi_watchdog_enabled; diff --git a/arch/x86/kernel/probe_roms_32.c b/arch/x86/kernel/probe_roms_32.c index 675a48c404a..071e7fea42e 100644 --- a/arch/x86/kernel/probe_roms_32.c +++ b/arch/x86/kernel/probe_roms_32.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include static struct resource system_rom_resource = { .name = "System ROM", diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 92e42939fb0..e645d4793e4 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -81,7 +81,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 489fde9d947..e90b3e50b54 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -66,7 +66,7 @@ #include #include -#include +#include #ifdef CONFIG_X86_32 u8 apicid_2_node[MAX_APICID]; diff --git a/arch/x86/kernel/time_32.c b/arch/x86/kernel/time_32.c index 3985cac0ed4..764c74e871f 100644 --- a/arch/x86/kernel/time_32.c +++ b/arch/x86/kernel/time_32.c @@ -38,7 +38,7 @@ #include #include -#include "do_timer.h" +#include int timer_ack; diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index ed5aee5f3fc..214bc327a0c 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -54,7 +54,7 @@ #include #include -#include +#include #ifdef CONFIG_X86_64 #include diff --git a/arch/x86/pci/pcbios.c b/arch/x86/pci/pcbios.c index b82cae970df..1c975cc9839 100644 --- a/arch/x86/pci/pcbios.c +++ b/arch/x86/pci/pcbios.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include /* BIOS32 signature: "_32_" */ #define BIOS32_SIGNATURE (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24)) diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c index e1129fad96d..ee19b6e8fcb 100644 --- a/drivers/clocksource/acpi_pm.c +++ b/drivers/clocksource/acpi_pm.c @@ -143,7 +143,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE, #endif #ifndef CONFIG_X86_64 -#include "mach_timer.h" +#include #define PMTMR_EXPECTED_RATE \ ((CALIBRATE_LATCH * (PMTMR_TICKS_PER_SEC >> 10)) / (CLOCK_TICK_RATE>>10)) /* diff --git a/drivers/clocksource/cyclone.c b/drivers/clocksource/cyclone.c index 1bde303b970..8615059a872 100644 --- a/drivers/clocksource/cyclone.c +++ b/drivers/clocksource/cyclone.c @@ -7,7 +7,7 @@ #include #include -#include "mach_timer.h" +#include #define CYCLONE_CBAR_ADDR 0xFEB00CD0 /* base address ptr */ #define CYCLONE_PMCC_OFFSET 0x51A0 /* offset to control register */ -- GitLab From 6bda2c8b32febeb38ee128047253751e080bad52 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 19:32:55 +0100 Subject: [PATCH 0628/4982] x86: remove subarchitecture support Remove the 32-bit subarchitecture support code. All subarchitectures but Voyager have been converted. Voyager will be done later or will be removed. Signed-off-by: Ingo Molnar --- arch/x86/Makefile | 21 ---- arch/x86/include/asm/apic.h | 2 + arch/x86/kernel/Makefile | 2 +- arch/x86/kernel/io_apic.c | 17 ---- arch/x86/kernel/probe_32.c | 163 ++++++++++++++++++++++++++++++++ arch/x86/mach-default/setup.c | 162 ------------------------------- arch/x86/mach-generic/default.c | 93 ------------------ 7 files changed, 166 insertions(+), 294 deletions(-) delete mode 100644 arch/x86/mach-default/setup.c delete mode 100644 arch/x86/mach-generic/default.c diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 799a0d931c8..99550c40799 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -102,24 +102,6 @@ KBUILD_CFLAGS += -fno-asynchronous-unwind-tables # prevent gcc from generating any FP code by mistake KBUILD_CFLAGS += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,) -### -# Sub architecture support -# fcore-y is linked before mcore-y files. - -# Default subarch .c files -mcore-y := arch/x86/mach-default/ - -# Voyager subarch support -mflags-$(CONFIG_X86_VOYAGER) := -Iarch/x86/include/asm/mach-voyager -mcore-$(CONFIG_X86_VOYAGER) := arch/x86/mach-voyager/ - -# default subarch .h files -mflags-y += -Iarch/x86/include/asm/mach-default - -# 64 bit does not support subarch support - clear sub arch variables -fcore-$(CONFIG_X86_64) := -mcore-$(CONFIG_X86_64) := - KBUILD_CFLAGS += $(mflags-y) KBUILD_AFLAGS += $(mflags-y) @@ -145,9 +127,6 @@ core-$(CONFIG_LGUEST_GUEST) += arch/x86/lguest/ core-y += arch/x86/kernel/ core-y += arch/x86/mm/ -# Remaining sub architecture files -core-y += $(mcore-y) - core-y += arch/x86/crypto/ core-y += arch/x86/vdso/ core-$(CONFIG_IA32_EMULATION) += arch/x86/ia32/ diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 6a77068e261..b03711d7990 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -215,6 +215,7 @@ static inline void disable_local_APIC(void) { } #define SET_APIC_ID(x) (apic->set_apic_id(x)) #else +#ifdef CONFIG_X86_LOCAL_APIC static inline unsigned default_get_apic_id(unsigned long x) { unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR)); @@ -224,6 +225,7 @@ static inline unsigned default_get_apic_id(unsigned long x) else return (x >> 24) & 0x0F; } +#endif #endif diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index d3f8f49aed6..1bc4cdc797d 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -63,7 +63,7 @@ obj-$(CONFIG_SMP) += setup_percpu.o obj-$(CONFIG_X86_64_SMP) += tsc_sync.o obj-$(CONFIG_X86_TRAMPOLINE) += trampoline_$(BITS).o obj-$(CONFIG_X86_MPPARSE) += mpparse.o -obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o +obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o ipi.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups_32.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 241a01d6fd4..3378ffb2140 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -797,23 +797,6 @@ static void clear_IO_APIC (void) clear_IO_APIC_pin(apic, pin); } -#if !defined(CONFIG_SMP) && defined(CONFIG_X86_32) -void default_send_IPI_self(int vector) -{ - unsigned int cfg; - - /* - * Wait for idle. - */ - apic_wait_icr_idle(); - cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | apic->dest_logical; - /* - * Send the IPI. The write to APIC_ICR fires this off. - */ - apic_write(APIC_ICR, cfg); -} -#endif /* !CONFIG_SMP && CONFIG_X86_32*/ - #ifdef CONFIG_X86_32 /* * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to diff --git a/arch/x86/kernel/probe_32.c b/arch/x86/kernel/probe_32.c index a6fba691416..61339a0d55c 100644 --- a/arch/x86/kernel/probe_32.c +++ b/arch/x86/kernel/probe_32.c @@ -32,6 +32,26 @@ #include #include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef CONFIG_HOTPLUG_CPU +#define DEFAULT_SEND_IPI (1) +#else +#define DEFAULT_SEND_IPI (0) +#endif + +int no_broadcast = DEFAULT_SEND_IPI; + +#ifdef CONFIG_X86_LOCAL_APIC + static void default_vector_allocation_domain(int cpu, struct cpumask *retmask) { /* @@ -246,3 +266,146 @@ int __init default_acpi_madt_oem_check(char *oem_id, char *oem_table_id) } return 0; } + +#endif /* CONFIG_X86_LOCAL_APIC */ + +/** + * pre_intr_init_hook - initialisation prior to setting up interrupt vectors + * + * Description: + * Perform any necessary interrupt initialisation prior to setting up + * the "ordinary" interrupt call gates. For legacy reasons, the ISA + * interrupts should be initialised here if the machine emulates a PC + * in any way. + **/ +void __init pre_intr_init_hook(void) +{ + if (x86_quirks->arch_pre_intr_init) { + if (x86_quirks->arch_pre_intr_init()) + return; + } + init_ISA_irqs(); +} + +/** + * intr_init_hook - post gate setup interrupt initialisation + * + * Description: + * Fill in any interrupts that may have been left out by the general + * init_IRQ() routine. interrupts having to do with the machine rather + * than the devices on the I/O bus (like APIC interrupts in intel MP + * systems) are started here. + **/ +void __init intr_init_hook(void) +{ + if (x86_quirks->arch_intr_init) { + if (x86_quirks->arch_intr_init()) + return; + } +} + +/** + * pre_setup_arch_hook - hook called prior to any setup_arch() execution + * + * Description: + * generally used to activate any machine specific identification + * routines that may be needed before setup_arch() runs. On Voyager + * this is used to get the board revision and type. + **/ +void __init pre_setup_arch_hook(void) +{ +} + +/** + * trap_init_hook - initialise system specific traps + * + * Description: + * Called as the final act of trap_init(). Used in VISWS to initialise + * the various board specific APIC traps. + **/ +void __init trap_init_hook(void) +{ + if (x86_quirks->arch_trap_init) { + if (x86_quirks->arch_trap_init()) + return; + } +} + +static struct irqaction irq0 = { + .handler = timer_interrupt, + .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL, + .mask = CPU_MASK_NONE, + .name = "timer" +}; + +/** + * pre_time_init_hook - do any specific initialisations before. + * + **/ +void __init pre_time_init_hook(void) +{ + if (x86_quirks->arch_pre_time_init) + x86_quirks->arch_pre_time_init(); +} + +/** + * time_init_hook - do any specific initialisations for the system timer. + * + * Description: + * Must plug the system timer interrupt source at HZ into the IRQ listed + * in irq_vectors.h:TIMER_IRQ + **/ +void __init time_init_hook(void) +{ + if (x86_quirks->arch_time_init) { + /* + * A nonzero return code does not mean failure, it means + * that the architecture quirk does not want any + * generic (timer) setup to be performed after this: + */ + if (x86_quirks->arch_time_init()) + return; + } + + irq0.mask = cpumask_of_cpu(0); + setup_irq(0, &irq0); +} + +#ifdef CONFIG_MCA +/** + * mca_nmi_hook - hook into MCA specific NMI chain + * + * Description: + * The MCA (Microchannel Architecture) has an NMI chain for NMI sources + * along the MCA bus. Use this to hook into that chain if you will need + * it. + **/ +void mca_nmi_hook(void) +{ + /* + * If I recall correctly, there's a whole bunch of other things that + * we can do to check for NMI problems, but that's all I know about + * at the moment. + */ + pr_warning("NMI generated from unknown source!\n"); +} +#endif + +static __init int no_ipi_broadcast(char *str) +{ + get_option(&str, &no_broadcast); + pr_info("Using %s mode\n", + no_broadcast ? "No IPI Broadcast" : "IPI Broadcast"); + return 1; +} +__setup("no_ipi_broadcast=", no_ipi_broadcast); + +static int __init print_ipi_mode(void) +{ + pr_info("Using IPI %s mode\n", + no_broadcast ? "No-Shortcut" : "Shortcut"); + return 0; +} + +late_initcall(print_ipi_mode); + diff --git a/arch/x86/mach-default/setup.c b/arch/x86/mach-default/setup.c deleted file mode 100644 index b65ff0bf730..00000000000 --- a/arch/x86/mach-default/setup.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Machine specific setup for generic - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifdef CONFIG_HOTPLUG_CPU -#define DEFAULT_SEND_IPI (1) -#else -#define DEFAULT_SEND_IPI (0) -#endif - -int no_broadcast = DEFAULT_SEND_IPI; - -/** - * pre_intr_init_hook - initialisation prior to setting up interrupt vectors - * - * Description: - * Perform any necessary interrupt initialisation prior to setting up - * the "ordinary" interrupt call gates. For legacy reasons, the ISA - * interrupts should be initialised here if the machine emulates a PC - * in any way. - **/ -void __init pre_intr_init_hook(void) -{ - if (x86_quirks->arch_pre_intr_init) { - if (x86_quirks->arch_pre_intr_init()) - return; - } - init_ISA_irqs(); -} - -/** - * intr_init_hook - post gate setup interrupt initialisation - * - * Description: - * Fill in any interrupts that may have been left out by the general - * init_IRQ() routine. interrupts having to do with the machine rather - * than the devices on the I/O bus (like APIC interrupts in intel MP - * systems) are started here. - **/ -void __init intr_init_hook(void) -{ - if (x86_quirks->arch_intr_init) { - if (x86_quirks->arch_intr_init()) - return; - } -} - -/** - * pre_setup_arch_hook - hook called prior to any setup_arch() execution - * - * Description: - * generally used to activate any machine specific identification - * routines that may be needed before setup_arch() runs. On Voyager - * this is used to get the board revision and type. - **/ -void __init pre_setup_arch_hook(void) -{ -} - -/** - * trap_init_hook - initialise system specific traps - * - * Description: - * Called as the final act of trap_init(). Used in VISWS to initialise - * the various board specific APIC traps. - **/ -void __init trap_init_hook(void) -{ - if (x86_quirks->arch_trap_init) { - if (x86_quirks->arch_trap_init()) - return; - } -} - -static struct irqaction irq0 = { - .handler = timer_interrupt, - .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL, - .mask = CPU_MASK_NONE, - .name = "timer" -}; - -/** - * pre_time_init_hook - do any specific initialisations before. - * - **/ -void __init pre_time_init_hook(void) -{ - if (x86_quirks->arch_pre_time_init) - x86_quirks->arch_pre_time_init(); -} - -/** - * time_init_hook - do any specific initialisations for the system timer. - * - * Description: - * Must plug the system timer interrupt source at HZ into the IRQ listed - * in irq_vectors.h:TIMER_IRQ - **/ -void __init time_init_hook(void) -{ - if (x86_quirks->arch_time_init) { - /* - * A nonzero return code does not mean failure, it means - * that the architecture quirk does not want any - * generic (timer) setup to be performed after this: - */ - if (x86_quirks->arch_time_init()) - return; - } - - irq0.mask = cpumask_of_cpu(0); - setup_irq(0, &irq0); -} - -#ifdef CONFIG_MCA -/** - * mca_nmi_hook - hook into MCA specific NMI chain - * - * Description: - * The MCA (Microchannel Architecture) has an NMI chain for NMI sources - * along the MCA bus. Use this to hook into that chain if you will need - * it. - **/ -void mca_nmi_hook(void) -{ - /* - * If I recall correctly, there's a whole bunch of other things that - * we can do to check for NMI problems, but that's all I know about - * at the moment. - */ - pr_warning("NMI generated from unknown source!\n"); -} -#endif - -static __init int no_ipi_broadcast(char *str) -{ - get_option(&str, &no_broadcast); - pr_info("Using %s mode\n", - no_broadcast ? "No IPI Broadcast" : "IPI Broadcast"); - return 1; -} -__setup("no_ipi_broadcast=", no_ipi_broadcast); - -static int __init print_ipi_mode(void) -{ - pr_info("Using IPI %s mode\n", - no_broadcast ? "No-Shortcut" : "Shortcut"); - return 0; -} - -late_initcall(print_ipi_mode); - diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c deleted file mode 100644 index d9d44c8c3db..00000000000 --- a/arch/x86/mach-generic/default.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Default generic APIC driver. This handles up to 8 CPUs. - */ -#define APIC_DEFINITION 1 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static void default_vector_allocation_domain(int cpu, struct cpumask *retmask) -{ - /* - * Careful. Some cpus do not strictly honor the set of cpus - * specified in the interrupt destination when using lowest - * priority interrupt delivery mode. - * - * In particular there was a hyperthreading cpu observed to - * deliver interrupts to the wrong hyperthread when only one - * hyperthread was specified in the interrupt desitination. - */ - *retmask = (cpumask_t) { { [0] = APIC_ALL_CPUS } }; -} - -/* should be called last. */ -static int probe_default(void) -{ - return 1; -} - -struct genapic apic_default = { - - .name = "default", - .probe = probe_default, - .acpi_madt_oem_check = NULL, - .apic_id_registered = default_apic_id_registered, - - .irq_delivery_mode = dest_LowestPrio, - /* logical delivery broadcast to all CPUs: */ - .irq_dest_mode = 1, - - .target_cpus = default_target_cpus, - .disable_esr = 0, - .dest_logical = APIC_DEST_LOGICAL, - .check_apicid_used = default_check_apicid_used, - .check_apicid_present = default_check_apicid_present, - - .vector_allocation_domain = default_vector_allocation_domain, - .init_apic_ldr = default_init_apic_ldr, - - .ioapic_phys_id_map = default_ioapic_phys_id_map, - .setup_apic_routing = default_setup_apic_routing, - .multi_timer_check = NULL, - .apicid_to_node = default_apicid_to_node, - .cpu_to_logical_apicid = default_cpu_to_logical_apicid, - .cpu_present_to_apicid = default_cpu_present_to_apicid, - .apicid_to_cpu_present = default_apicid_to_cpu_present, - .setup_portio_remap = NULL, - .check_phys_apicid_present = default_check_phys_apicid_present, - .enable_apic_mode = NULL, - .phys_pkg_id = default_phys_pkg_id, - .mps_oem_check = NULL, - - .get_apic_id = default_get_apic_id, - .set_apic_id = NULL, - .apic_id_mask = 0x0F << 24, - - .cpu_mask_to_apicid = default_cpu_mask_to_apicid, - .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, - - .send_IPI_mask = default_send_IPI_mask, - .send_IPI_mask_allbutself = NULL, - .send_IPI_allbutself = default_send_IPI_allbutself, - .send_IPI_all = default_send_IPI_all, - .send_IPI_self = NULL, - - .wakeup_cpu = NULL, - .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, - .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, - - .wait_for_init_deassert = default_wait_for_init_deassert, - - .smp_callin_clear_local_apic = NULL, - .store_NMI_vector = NULL, - .inquire_remote_apic = default_inquire_remote_apic, -}; -- GitLab From e7c64981949ec983ee41c2927c036fdb00d8e68b Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 17:54:17 +0100 Subject: [PATCH 0629/4982] x86/Voyager: clean up BROKEN Kconfig reference CONFIG_BROKEN has been removed from the upstream kernel years ago, but X86_VOYAGER still had a stale reference to it - remove it. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index d6218e6c982..45c7bdbc156 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -303,7 +303,7 @@ config X86_ELAN config X86_VOYAGER bool "Voyager (NCR)" - depends on X86_32 && (SMP || BROKEN) && !PCI + depends on X86_32 && SMP && !PCI help Voyager is an MCA-based 32-way capable SMP architecture proprietary to NCR Corp. Machine classes 345x/35xx/4100/51xx are Voyager-based. -- GitLab From 61b8172e57c4b8db1fcb7f5fd8dfda85ffd8e052 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 28 Jan 2009 19:55:34 +0100 Subject: [PATCH 0630/4982] x86: disable Voyager temporarily x86/Voyager does not build right now and it's unclear whether it will be cleaned up and ported to the subarch-less 32-bit x86 code - so disable it for now. If it's fixed we'll re-enable it - or remove it after some time. There's a very low number of systems running development kernels on x86/Voyager currently. (one or two on the whole planet) Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 45c7bdbc156..f983f4055b1 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -303,7 +303,7 @@ config X86_ELAN config X86_VOYAGER bool "Voyager (NCR)" - depends on X86_32 && SMP && !PCI + depends on X86_32 && SMP && !PCI && BROKEN help Voyager is an MCA-based 32-way capable SMP architecture proprietary to NCR Corp. Machine classes 345x/35xx/4100/51xx are Voyager-based. -- GitLab From 72ee6ebbb3fe1ac23d1a669b177b858d2028bf09 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 16:57:49 +0100 Subject: [PATCH 0631/4982] x86/Voyager: remove MCA Kconfig quirk Remove Voyager Kconfig quirk: just like any other hardware platform users of Voyager systems can configure in the hardware drivers they need. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index f983f4055b1..ae37a7504b5 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1873,8 +1873,7 @@ config EISA source "drivers/eisa/Kconfig" config MCA - bool "MCA support" if !X86_VOYAGER - default y if X86_VOYAGER + bool "MCA support" help MicroChannel Architecture is found in some IBM PS/2 machines and laptops. It is a bus system similar to PCI or ISA. See -- GitLab From 07ef83ae9e99377f38f4d0e472ba6ff09324e5e9 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 16:59:11 +0100 Subject: [PATCH 0632/4982] x86/Voyager: remove NATSEMI Kconfig quirk x86/Voyager has this quirk for SCx200 support: config SCx200 tristate "NatSemi SCx200 support" depends on !X86_VOYAGER Remove it - Voyager users can disable drivers they dont need. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ae37a7504b5..9727dd59f54 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1884,7 +1884,6 @@ source "drivers/mca/Kconfig" config SCx200 tristate "NatSemi SCx200 support" - depends on !X86_VOYAGER help This provides basic support for National Semiconductor's (now AMD's) Geode processors. The driver probes for the -- GitLab From e0ec9483dbe8f534e0f3ef413f9eba9a5ff78050 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 17:01:14 +0100 Subject: [PATCH 0633/4982] x86/Voyager: remove KVM Kconfig quirk Voyager and other subarchitectures have this Kconfig quirk: select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64) This is unnecessary, as KVM cleanly detects based on CPUID capabilities. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 9727dd59f54..a783fe7759c 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -34,7 +34,7 @@ config X86 select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_TRACE_MCOUNT_TEST - select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64) + select HAVE_KVM select HAVE_ARCH_KGDB if !X86_VOYAGER select HAVE_ARCH_TRACEHOOK select HAVE_GENERIC_DMA_COHERENT if X86_32 -- GitLab From 49793b0341a802cf5ee4179e837a2eb20f12c9fe Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 17:02:29 +0100 Subject: [PATCH 0634/4982] x86/Voyager: remove KGDB Kconfig quirk x86/Voyager has this KGDB quirk: select HAVE_ARCH_KGDB if !X86_VOYAGER This is completely pointless - there's nothing in KGDB that cannot work on Voyager. Remove it. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index a783fe7759c..12b433aaaa6 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -35,7 +35,7 @@ config X86 select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_TRACE_MCOUNT_TEST select HAVE_KVM - select HAVE_ARCH_KGDB if !X86_VOYAGER + select HAVE_ARCH_KGDB select HAVE_ARCH_TRACEHOOK select HAVE_GENERIC_DMA_COHERENT if X86_32 select HAVE_EFFICIENT_UNALIGNED_ACCESS -- GitLab From aced3cee555f0b2fd58501e9b8a8a1295011e134 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 17:03:24 +0100 Subject: [PATCH 0635/4982] x86/Voyager: remove HIBERNATION Kconfig quirk Voyager has this hibernation quirk: config ARCH_HIBERNATION_POSSIBLE def_bool y depends on !SMP || !X86_VOYAGER Hibernation is a generic facility provided on all x86 platforms. If it is buggy on Voyager then that bug should be fixed - not worked around. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 12b433aaaa6..df952e788a6 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -140,7 +140,7 @@ config HAVE_CPUMASK_OF_CPU_MAP config ARCH_HIBERNATION_POSSIBLE def_bool y - depends on !SMP || !X86_VOYAGER + depends on !SMP config ARCH_SUSPEND_POSSIBLE def_bool y -- GitLab From f2fc0e3071230bb9ea9f64a08c3e619ad1357cfb Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 17:04:39 +0100 Subject: [PATCH 0636/4982] x86/Voyager: remove ARCH_SUSPEND_POSSIBLE Kconfig quirk Voyager has this Kconfig quirk for suspend/resume: config ARCH_SUSPEND_POSSIBLE def_bool y depends on !X86_VOYAGER The proper mechanism to not suspend on a piece of hardware to disable CONFIG_SUSPEND. Remove the quirk. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index df952e788a6..8e6413e0e7c 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -144,7 +144,6 @@ config ARCH_HIBERNATION_POSSIBLE config ARCH_SUSPEND_POSSIBLE def_bool y - depends on !X86_VOYAGER config ZONE_DMA32 bool -- GitLab From 3e5095d15276efd14a45393666b1bb7536bf179f Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 17:07:08 +0100 Subject: [PATCH 0637/4982] x86: replace CONFIG_X86_SMP with CONFIG_SMP The x86/Voyager subarch used to have this distinction between 'x86 SMP support' and 'Voyager SMP support': config X86_SMP bool depends on SMP && ((X86_32 && !X86_VOYAGER) || X86_64) This is a pointless distinction - Voyager can (and already does) use smp_ops to implement various SMP quirks it has - and it can be extended more to cover all the specialities of Voyager. So remove this complication in the Kconfig space. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 7 +------ arch/x86/Kconfig.debug | 2 +- arch/x86/include/asm/entry_arch.h | 2 +- arch/x86/include/asm/hw_irq.h | 2 +- arch/x86/kernel/Makefile | 4 ++-- arch/x86/kernel/apic.c | 2 +- arch/x86/kernel/cpu/addon_cpuid_features.c | 2 +- arch/x86/kernel/process.c | 2 +- arch/x86/kernel/setup.c | 2 +- arch/x86/kernel/tsc.c | 2 +- arch/x86/kernel/vmiclock_32.c | 2 +- arch/x86/mm/Makefile | 2 +- 12 files changed, 13 insertions(+), 18 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 8e6413e0e7c..3671506fb8d 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -173,11 +173,6 @@ config GENERIC_PENDING_IRQ depends on GENERIC_HARDIRQS && SMP default y -config X86_SMP - bool - depends on SMP && ((X86_32 && !X86_VOYAGER) || X86_64) - default y - config USE_GENERIC_SMP_HELPERS def_bool y depends on SMP @@ -203,7 +198,7 @@ config X86_BIOS_REBOOT config X86_TRAMPOLINE bool - depends on X86_SMP || (X86_VOYAGER && SMP) || (64BIT && ACPI_SLEEP) + depends on SMP || (64BIT && ACPI_SLEEP) default y config KTIME_SCALAR diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 28f111461ca..a38dd6064f1 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -83,7 +83,7 @@ config DEBUG_PAGEALLOC config DEBUG_PER_CPU_MAPS bool "Debug access to per_cpu maps" depends on DEBUG_KERNEL - depends on X86_SMP + depends on SMP default n help Say Y to verify that the per_cpu map being accessed has diff --git a/arch/x86/include/asm/entry_arch.h b/arch/x86/include/asm/entry_arch.h index b87b077cc23..854d538ae85 100644 --- a/arch/x86/include/asm/entry_arch.h +++ b/arch/x86/include/asm/entry_arch.h @@ -9,7 +9,7 @@ * is no hardware IRQ pin equivalent for them, they are triggered * through the ICC by us (IPIs) */ -#ifdef CONFIG_X86_SMP +#ifdef CONFIG_SMP BUILD_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR) BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR) BUILD_INTERRUPT(call_function_single_interrupt,CALL_FUNCTION_SINGLE_VECTOR) diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index bfa921fad13..41550797396 100644 --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h @@ -98,7 +98,7 @@ extern asmlinkage void qic_call_function_interrupt(void); extern void smp_apic_timer_interrupt(struct pt_regs *); extern void smp_spurious_interrupt(struct pt_regs *); extern void smp_error_interrupt(struct pt_regs *); -#ifdef CONFIG_X86_SMP +#ifdef CONFIG_SMP extern void smp_reschedule_interrupt(struct pt_regs *); extern void smp_call_function_interrupt(struct pt_regs *); extern void smp_call_function_single_interrupt(struct pt_regs *); diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 1bc4cdc797d..dc05a57a474 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -57,8 +57,8 @@ obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_PCI) += early-quirks.o apm-y := apm_32.o obj-$(CONFIG_APM) += apm.o -obj-$(CONFIG_X86_SMP) += smp.o -obj-$(CONFIG_X86_SMP) += smpboot.o tsc_sync.o ipi.o +obj-$(CONFIG_SMP) += smp.o +obj-$(CONFIG_SMP) += smpboot.o tsc_sync.o ipi.o obj-$(CONFIG_SMP) += setup_percpu.o obj-$(CONFIG_X86_64_SMP) += tsc_sync.o obj-$(CONFIG_X86_TRAMPOLINE) += trampoline_$(BITS).o diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 81efe86eca8..968c817762a 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -1900,7 +1900,7 @@ void __cpuinit generic_processor_info(int apicid, int version) } #endif -#if defined(CONFIG_X86_SMP) || defined(CONFIG_X86_64) +#if defined(CONFIG_SMP) || defined(CONFIG_X86_64) early_per_cpu(x86_cpu_to_apicid, cpu) = apicid; early_per_cpu(x86_bios_cpu_apicid, cpu) = apicid; #endif diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c index 4a48bb40974..e48640cfac0 100644 --- a/arch/x86/kernel/cpu/addon_cpuid_features.c +++ b/arch/x86/kernel/cpu/addon_cpuid_features.c @@ -69,7 +69,7 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) */ void __cpuinit detect_extended_topology(struct cpuinfo_x86 *c) { -#ifdef CONFIG_X86_SMP +#ifdef CONFIG_SMP unsigned int eax, ebx, ecx, edx, sub_index; unsigned int ht_mask_width, core_plus_mask_width; unsigned int core_select_mask, core_level_siblings; diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index e68bb9e3086..89537f678b2 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -344,7 +344,7 @@ static void c1e_idle(void) void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) { -#ifdef CONFIG_X86_SMP +#ifdef CONFIG_SMP if (pm_idle == poll_idle && smp_num_siblings > 1) { printk(KERN_WARNING "WARNING: polling idle and HT enabled," " performance may degrade.\n"); diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index e645d4793e4..eeb180b1d7a 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -588,7 +588,7 @@ early_param("elfcorehdr", setup_elfcorehdr); static int __init default_update_genapic(void) { -#ifdef CONFIG_X86_SMP +#ifdef CONFIG_SMP if (!apic->wakeup_cpu) apic->wakeup_cpu = wakeup_secondary_cpu_via_init; #endif diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 599e5816863..83d53ce5d4c 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -773,7 +773,7 @@ __cpuinit int unsynchronized_tsc(void) if (!cpu_has_tsc || tsc_unstable) return 1; -#ifdef CONFIG_X86_SMP +#ifdef CONFIG_SMP if (apic_is_clustered_box()) return 1; #endif diff --git a/arch/x86/kernel/vmiclock_32.c b/arch/x86/kernel/vmiclock_32.c index c4c1f9e0940..a4791ef412d 100644 --- a/arch/x86/kernel/vmiclock_32.c +++ b/arch/x86/kernel/vmiclock_32.c @@ -256,7 +256,7 @@ void __devinit vmi_time_bsp_init(void) */ clockevents_notify(CLOCK_EVT_NOTIFY_SUSPEND, NULL); local_irq_disable(); -#ifdef CONFIG_X86_SMP +#ifdef CONFIG_SMP /* * XXX handle_percpu_irq only defined for SMP; we need to switch over * to using it, since this is a local interrupt, which each CPU must diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile index 9f05157220f..2b938a38491 100644 --- a/arch/x86/mm/Makefile +++ b/arch/x86/mm/Makefile @@ -1,7 +1,7 @@ obj-y := init_$(BITS).o fault.o ioremap.o extable.o pageattr.o mmap.o \ pat.o pgtable.o gup.o -obj-$(CONFIG_X86_SMP) += tlb.o +obj-$(CONFIG_SMP) += tlb.o obj-$(CONFIG_X86_32) += pgtable_32.o iomap_32.o -- GitLab From c0b5842a457d44c8788b3fd0c64969be7ef673cd Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 17:13:05 +0100 Subject: [PATCH 0638/4982] x86: generalize boot_cpu_id x86/Voyager can boot on non-zero processors. While that can probably be fixed by properly remapping the physical CPU IDs, keep boot_cpu_id for now for easier transition - and expand it to all of x86. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 4 ---- arch/x86/include/asm/cpu.h | 6 +----- arch/x86/kernel/setup.c | 14 ++++++++++++++ arch/x86/kernel/smpboot.c | 12 ------------ 4 files changed, 15 insertions(+), 21 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 3671506fb8d..f4dd851384d 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -238,10 +238,6 @@ config SMP If you don't know what to do here, say N. -config X86_HAS_BOOT_CPU_ID - def_bool y - depends on X86_VOYAGER - config SPARSE_IRQ bool "Support sparse irq numbering" depends on PCI_MSI || HT_IRQ diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index f03b23e3286..b185091bf19 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h @@ -32,10 +32,6 @@ extern void arch_unregister_cpu(int); DECLARE_PER_CPU(int, cpu_state); -#ifdef CONFIG_X86_HAS_BOOT_CPU_ID -extern unsigned char boot_cpu_id; -#else -#define boot_cpu_id 0 -#endif +extern unsigned int boot_cpu_id; #endif /* _ASM_X86_CPU_H */ diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index eeb180b1d7a..609e5af6028 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -112,6 +112,20 @@ #define ARCH_SETUP #endif +unsigned int boot_cpu_id __read_mostly; + +#ifdef CONFIG_X86_64 +int default_cpu_present_to_apicid(int mps_cpu) +{ + return __default_cpu_present_to_apicid(mps_cpu); +} + +int default_check_phys_apicid_present(int boot_cpu_physical_apicid) +{ + return __default_check_phys_apicid_present(boot_cpu_physical_apicid); +} +#endif + #ifndef CONFIG_DEBUG_BOOT_PARAMS struct boot_params __initdata boot_params; #else diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index e90b3e50b54..bc7e220ba0b 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -905,18 +905,6 @@ do_rest: return boot_error; } -#ifdef CONFIG_X86_64 -int default_cpu_present_to_apicid(int mps_cpu) -{ - return __default_cpu_present_to_apicid(mps_cpu); -} - -int default_check_phys_apicid_present(int boot_cpu_physical_apicid) -{ - return __default_check_phys_apicid_present(boot_cpu_physical_apicid); -} -#endif - int __cpuinit native_cpu_up(unsigned int cpu) { int apicid = apic->cpu_present_to_apicid(cpu); -- GitLab From 23394d1c9346d9c0aabbc1b6fca52a9c0aa1c297 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 17:16:16 +0100 Subject: [PATCH 0639/4982] x86/Voyager: remove X86_HT Kconfig quirk Voyager has this Kconfig quirk: depends on (X86_32 && !X86_VOYAGER) || X86_64 That is unnecessary as HT support is CPUID driven and explicitly enumerated. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index f4dd851384d..1d50c9de4d2 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -188,7 +188,6 @@ config X86_64_SMP config X86_HT bool depends on SMP - depends on (X86_32 && !X86_VOYAGER) || X86_64 default y config X86_BIOS_REBOOT -- GitLab From f095df0a0cb35a52605541f619d038339b90d7cc Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 17:17:55 +0100 Subject: [PATCH 0640/4982] x86/Voyager: remove X86_BIOS_REBOOT Kconfig quirk Voyager has this Kconfig quirk: config X86_BIOS_REBOOT bool depends on !X86_VOYAGER default y Voyager should use the existing machine_ops.emergency_restart reboot quirk mechanism instead of a build-time quirk. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 6 ------ arch/x86/include/asm/proto.h | 4 ---- arch/x86/kernel/Makefile | 2 +- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 1d50c9de4d2..c0d79ab366d 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -190,11 +190,6 @@ config X86_HT depends on SMP default y -config X86_BIOS_REBOOT - bool - depends on !X86_VOYAGER - default y - config X86_TRAMPOLINE bool depends on SMP || (64BIT && ACPI_SLEEP) @@ -1361,7 +1356,6 @@ source kernel/Kconfig.hz config KEXEC bool "kexec system call" - depends on X86_BIOS_REBOOT help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot diff --git a/arch/x86/include/asm/proto.h b/arch/x86/include/asm/proto.h index d6a22f92ba7..49fb3ecf3bb 100644 --- a/arch/x86/include/asm/proto.h +++ b/arch/x86/include/asm/proto.h @@ -18,11 +18,7 @@ extern void syscall32_cpu_init(void); extern void check_efer(void); -#ifdef CONFIG_X86_BIOS_REBOOT extern int reboot_force; -#else -static const int reboot_force = 0; -#endif long do_arch_prctl(struct task_struct *task, int code, unsigned long addr); diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index dc05a57a474..24f357e7557 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -50,7 +50,7 @@ obj-y += step.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-y += cpu/ obj-y += acpi/ -obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o +obj-y += reboot.o obj-$(CONFIG_MCA) += mca_32.o obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_CPUID) += cpuid.o -- GitLab From 550fe4f198558c147c6b8273a709568222a1668a Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 17:28:08 +0100 Subject: [PATCH 0641/4982] x86/Voyager: remove X86_FIND_SMP_CONFIG Kconfig quirk x86/Voyager had this Kconfig quirk: config X86_FIND_SMP_CONFIG def_bool y depends on X86_MPPARSE || X86_VOYAGER Which splits off the find_smp_config() callback into a build-time quirk. Voyager should use the existing x86_quirks.mach_find_smp_config() callback to introduce SMP-config quirks. NUMAQ-32 and VISWS already use this. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 4 ---- arch/x86/include/asm/mpspec.h | 4 +++- arch/x86/kernel/setup.c | 3 +-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index c0d79ab366d..df7cb8d68e2 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -254,10 +254,6 @@ config NUMA_MIGRATE_IRQ_DESC If you don't know what to do here, say N. -config X86_FIND_SMP_CONFIG - def_bool y - depends on X86_MPPARSE || X86_VOYAGER - config X86_MPPARSE bool "Enable MPS table" if ACPI default y diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h index 03fb0d39654..d22f732eab8 100644 --- a/arch/x86/include/asm/mpspec.h +++ b/arch/x86/include/asm/mpspec.h @@ -56,11 +56,13 @@ extern int smp_found_config; extern int mpc_default_type; extern unsigned long mp_lapic_addr; -extern void find_smp_config(void); extern void get_smp_config(void); + #ifdef CONFIG_X86_MPPARSE +extern void find_smp_config(void); extern void early_reserve_e820_mpc_new(void); #else +static inline void find_smp_config(void) { } static inline void early_reserve_e820_mpc_new(void) { } #endif diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 609e5af6028..6abce6703c5 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -905,12 +905,11 @@ void __init setup_arch(char **cmdline_p) */ acpi_reserve_bootmem(); #endif -#ifdef CONFIG_X86_FIND_SMP_CONFIG /* * Find and reserve possible boot-time SMP configuration: */ find_smp_config(); -#endif + reserve_crashkernel(); #ifdef CONFIG_X86_64 -- GitLab From 36619a8a80793a803588a17f772313d5c948357d Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 17:33:34 +0100 Subject: [PATCH 0642/4982] x86/VisWS: remove Kconfig quirk VisWS has this quirk currently: config X86_VISWS bool "SGI 320/540 (Visual Workstation)" depends on X86_32 && PCI && !X86_VOYAGER && X86_MPPARSE && PCI_GODIRECT The !Voyager quirk is unnecessary. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index df7cb8d68e2..f59d2920198 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -351,7 +351,7 @@ endchoice config X86_VISWS bool "SGI 320/540 (Visual Workstation)" - depends on X86_32 && PCI && !X86_VOYAGER && X86_MPPARSE && PCI_GODIRECT + depends on X86_32 && PCI && X86_MPPARSE && PCI_GODIRECT help The SGI Visual Workstation series is an IA32-based workstation based on SGI systems chips with some legacy PC hardware attached. -- GitLab From f154f47d5180c2012bf97999e6c600d45db8af2d Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 17:34:56 +0100 Subject: [PATCH 0643/4982] x86/Voyager: remove VMI Kconfig quirk x86/Voyager has this build-time quirk: bool "VMI Guest support" select PARAVIRT depends on X86_32 depends on !X86_VOYAGER Since VMI is auto-detected (and Voyager will be auto-detected) there's no reason for this quirk. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index f59d2920198..4bd0c8febae 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -406,7 +406,6 @@ config VMI bool "VMI Guest support" select PARAVIRT depends on X86_32 - depends on !X86_VOYAGER help VMI provides a paravirtualized interface to the VMware ESX server (it could be used by other hypervisors in theory too, but is not -- GitLab From e084e531000a488d2d27864266c13ac824575a8b Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 17:36:31 +0100 Subject: [PATCH 0644/4982] x86/Voyager: remove KVM_CLOCK quirk Voyager has this build-time quirk to exclude KVM_CLOCK: bool "KVM paravirtualized clock" select PARAVIRT select PARAVIRT_CLOCK depends on !X86_VOYAGER Voyager support built into a kernel image does not exclude KVM paravirt clock support - so remove this quirk. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 4bd0c8febae..0bf0653969d 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -416,7 +416,6 @@ config KVM_CLOCK bool "KVM paravirtualized clock" select PARAVIRT select PARAVIRT_CLOCK - depends on !X86_VOYAGER help Turning on this option will allow you to run a paravirtualized clock when running over the KVM hypervisor. Instead of relying on a PIT -- GitLab From 54523edd237b9e792a3b76988fde23a91d739f43 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 17:37:33 +0100 Subject: [PATCH 0645/4982] x86/Voyager: remove KVM_GUEST quirk Voyager has this quirk currently: config KVM_GUEST bool "KVM Guest support" select PARAVIRT depends on !X86_VOYAGER Voyager support built into a kernel image does not exclude KVM paravirt guest support - so remove this quirk. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 0bf0653969d..363111f40f3 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -426,7 +426,6 @@ config KVM_CLOCK config KVM_GUEST bool "KVM Guest support" select PARAVIRT - depends on !X86_VOYAGER help This option enables various optimizations for running under the KVM hypervisor. -- GitLab From c3e6a2042fef33b747d2ae3961f5312af801973d Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 17:38:46 +0100 Subject: [PATCH 0646/4982] x86/Voyager: remove PARAVIRT Kconfig quirk Remove this Kconfig quirk: config PARAVIRT bool "Enable paravirtualization code" depends on !X86_VOYAGER help Voyager support built into a kernel does not preclude paravirt support. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 363111f40f3..82105349612 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -434,7 +434,6 @@ source "arch/x86/lguest/Kconfig" config PARAVIRT bool "Enable paravirtualization code" - depends on !X86_VOYAGER help This changes the kernel so it can modify itself when it is run under a hypervisor, potentially improving performance significantly -- GitLab From 7cd92366a593246650cc7d6198e2c7d3af8c1d8a Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 17:40:48 +0100 Subject: [PATCH 0647/4982] x86/Voyager: remove APIC/IO-APIC Kbuild quirk The lapic/ioapic code properly auto-detects and is safe to run on CPUs that have no local APIC. (or which have their lapic turned off in the hardware) Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 82105349612..6fbb3639d7b 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -642,7 +642,7 @@ source "kernel/Kconfig.preempt" config X86_UP_APIC bool "Local APIC support on uniprocessors" - depends on X86_32 && !SMP && !(X86_VOYAGER || X86_GENERICARCH) + depends on X86_32 && !SMP && !X86_GENERICARCH help A local APIC (Advanced Programmable Interrupt Controller) is an integrated interrupt controller in the CPU. If you have a single-CPU @@ -667,11 +667,11 @@ config X86_UP_IOAPIC config X86_LOCAL_APIC def_bool y - depends on X86_64 || (X86_32 && (X86_UP_APIC || (SMP && !X86_VOYAGER) || X86_GENERICARCH)) + depends on X86_64 || SMP || X86_GENERICARCH || X86_UP_APIC config X86_IO_APIC def_bool y - depends on X86_64 || (X86_32 && (X86_UP_IOAPIC || (SMP && !X86_VOYAGER) || X86_GENERICARCH)) + depends on X86_64 || SMP || X86_GENERICARCH || X86_UP_APIC config X86_VISWS_APIC def_bool y -- GitLab From e006235e5b9cfb785ecbc05551788e33f96ea0ce Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 17:45:17 +0100 Subject: [PATCH 0648/4982] x86/Voyager: remove MCE quirk If no MCE code is desired on Voyager hw then the solution is to turn them off in the .config - and to extend the MCE code to not initialize on Voyager. Remove the build-time quirk. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 6fbb3639d7b..7cf9f0a8c8c 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -703,7 +703,6 @@ config X86_REROUTE_FOR_BROKEN_BOOT_IRQS config X86_MCE bool "Machine Check Exception" - depends on !X86_VOYAGER ---help--- Machine Check Exception support allows the processor to notify the kernel if it detects a problem (e.g. overheating, component failure). -- GitLab From 4b19ed915576e8034c3653b4b10b79bde10f69fa Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 17:47:24 +0100 Subject: [PATCH 0649/4982] x86/Voyager: remove HOTPLUG_CPU Kconfig quirk Voyager has this Kconfig quirk: config HOTPLUG_CPU bool "Support for hot-pluggable CPUs" depends on SMP && HOTPLUG && !X86_VOYAGER But this exception will be moot once Voyager starts using the generic x86 code. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 7cf9f0a8c8c..206645ac6f6 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1470,7 +1470,7 @@ config PHYSICAL_ALIGN config HOTPLUG_CPU bool "Support for hot-pluggable CPUs" - depends on SMP && HOTPLUG && !X86_VOYAGER + depends on SMP && HOTPLUG ---help--- Say Y here to allow turning CPUs off and on. CPUs can be controlled through /sys/devices/system/cpu. -- GitLab From 1c61d8c309a4080980474de8c6689527be180782 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 17:49:22 +0100 Subject: [PATCH 0650/4982] x86/Voyager: remove power management Kconfig quirk Voyager has this PM/ACPI Kconfig quirk: menu "Power management and ACPI options" depends on !X86_VOYAGER Most of the PM features are auto-detect so they should be safe to run on just about any hardware. (If not, those instances need fixing.) In any case, if a kernel is built for Voyager, the power management options can be disabled. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 206645ac6f6..f95c3b40e45 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1551,7 +1551,6 @@ config HAVE_ARCH_EARLY_PFN_TO_NID depends on NUMA menu "Power management and ACPI options" - depends on !X86_VOYAGER config ARCH_HIBERNATION_HEADER def_bool y -- GitLab From 1ec2dafd937c0f6fed46cbd8f6878f2c1db4a623 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 17:51:37 +0100 Subject: [PATCH 0651/4982] x86/Voyager: remove ISA quirk Voyager has this ISA quirk (because Voyager has no ISA support): config ISA bool "ISA support" depends on !X86_VOYAGER There's a ton of x86 hardware that does not support ISA, and because most ISA drivers cannot auto-detect in a safe way, the convention in the kernel has always been to not enable ISA drivers if they are not needed. Voyager users can do likewise - no need for a Kconfig quirk. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index f95c3b40e45..38ed1a6c6d8 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1819,7 +1819,6 @@ if X86_32 config ISA bool "ISA support" - depends on !X86_VOYAGER help Find out whether you have ISA slots on your motherboard. ISA is the name of a bus system, i.e. the way the CPU talks to the other stuff -- GitLab From 06ac8346af04f6a972072f6c5780ba734832ad13 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 18:11:43 +0100 Subject: [PATCH 0652/4982] x86: cleanup, introduce CONFIG_NON_STANDARD_PLATFORMS Introduce a Y/N Kconfig option for non-PC x86 platforms. Make VisWS, RDC321 and SGI/UV depend on this. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 38ed1a6c6d8..b090e5a27da 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -349,9 +349,23 @@ config X86_VSMP endchoice +config X86_NON_STANDARD + bool "Support for non-standard x86 platforms" + help + If you disable this option then the kernel will only support + standard PC platforms. (which covers the vast majority of + systems out there.) + + If you enable this option then you'll be able to select a number + of less common non-PC x86 platforms: VisWS, RDC321, SGI/UV. + + If you have one of these systems, or if you want to build a + generic distribution kernel, say Y here - otherwise say N. + config X86_VISWS bool "SGI 320/540 (Visual Workstation)" depends on X86_32 && PCI && X86_MPPARSE && PCI_GODIRECT + depends on X86_NON_STANDARD help The SGI Visual Workstation series is an IA32-based workstation based on SGI systems chips with some legacy PC hardware attached. @@ -364,6 +378,7 @@ config X86_VISWS config X86_RDC321X bool "RDC R-321x SoC" depends on X86_32 + depends on X86_NON_STANDARD select M486 select X86_REBOOTFIXUPS help @@ -374,6 +389,7 @@ config X86_RDC321X config X86_UV bool "SGI Ultraviolet" depends on X86_64 + depends on X86_NON_STANDARD help This option is needed in order to support SGI Ultraviolet systems. If you don't have one of these, you should say N here. -- GitLab From 9e111f3e167a14dd6252cff14fc7dd2ba4c650c6 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 18:18:25 +0100 Subject: [PATCH 0653/4982] x86: move ELAN to the NON_STANDARD_PLATFORM section Move X86_ELAN (old, AMD based web-boxes) from the subarchitecture menu to the non-standard-platform section. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index b090e5a27da..b7617e3781a 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -271,16 +271,6 @@ config X86_PC help Choose this option if your computer is a standard PC or compatible. -config X86_ELAN - bool "AMD Elan" - depends on X86_32 - help - Select this for an AMD Elan processor. - - Do not use this option for K6/Athlon/Opteron processors! - - If unsure, choose "PC-compatible" instead. - config X86_VOYAGER bool "Voyager (NCR)" depends on X86_32 && SMP && !PCI && BROKEN @@ -394,6 +384,17 @@ config X86_UV This option is needed in order to support SGI Ultraviolet systems. If you don't have one of these, you should say N here. +config X86_ELAN + bool "AMD Elan" + depends on X86_32 + depends on X86_NON_STANDARD + help + Select this for an AMD Elan processor. + + Do not use this option for K6/Athlon/Opteron processors! + + If unsure, choose "PC-compatible" instead. + config SCHED_OMIT_FRAME_POINTER def_bool y prompt "Single-depth WCHAN output" -- GitLab From f67ae5c9e52e385492b94c14376e322004701555 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 18:20:09 +0100 Subject: [PATCH 0654/4982] x86: move VOYAGER to the NON_STANDARD_PLATFORM section Move X86_ELAN (old, NCR hw platform built on Intel CPUs) from the subarchitecture menu to the non-standard-platform section. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index b7617e3781a..207dc9592d5 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -271,18 +271,6 @@ config X86_PC help Choose this option if your computer is a standard PC or compatible. -config X86_VOYAGER - bool "Voyager (NCR)" - depends on X86_32 && SMP && !PCI && BROKEN - help - Voyager is an MCA-based 32-way capable SMP architecture proprietary - to NCR Corp. Machine classes 345x/35xx/4100/51xx are Voyager-based. - - *** WARNING *** - - If you do not specifically know you have a Voyager based machine, - say N here, otherwise the kernel you build will not be bootable. - config X86_GENERICARCH bool "Generic architecture" depends on X86_32 @@ -395,6 +383,19 @@ config X86_ELAN If unsure, choose "PC-compatible" instead. +config X86_VOYAGER + bool "Voyager (NCR)" + depends on X86_32 && SMP && !PCI && BROKEN + depends on X86_NON_STANDARD + help + Voyager is an MCA-based 32-way capable SMP architecture proprietary + to NCR Corp. Machine classes 345x/35xx/4100/51xx are Voyager-based. + + *** WARNING *** + + If you do not specifically know you have a Voyager based machine, + say N here, otherwise the kernel you build will not be bootable. + config SCHED_OMIT_FRAME_POINTER def_bool y prompt "Single-depth WCHAN output" -- GitLab From 9c39801763ed6e08ea8bc694c5ab936643a2b763 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 18:24:57 +0100 Subject: [PATCH 0655/4982] x86: move non-standard 32-bit platform Kconfig entries - make X86_GENERICARCH depend X86_NON_STANDARD - move X86_SUMMIT, X86_ES7000 and X86_BIGSMP out of the subarchitecture menu and under this option Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 88 +++++++++++++++++++++++------------------------- 1 file changed, 43 insertions(+), 45 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 207dc9592d5..2fe298297ce 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -271,51 +271,6 @@ config X86_PC help Choose this option if your computer is a standard PC or compatible. -config X86_GENERICARCH - bool "Generic architecture" - depends on X86_32 - help - This option compiles in the NUMAQ, Summit, bigsmp, ES7000, default - subarchitectures. It is intended for a generic binary kernel. - if you select them all, kernel will probe it one by one. and will - fallback to default. - -if X86_GENERICARCH - -config X86_NUMAQ - bool "NUMAQ (IBM/Sequent)" - depends on SMP && X86_32 && PCI && X86_MPPARSE - select NUMA - help - This option is used for getting Linux to run on a NUMAQ (IBM/Sequent) - NUMA multiquad box. This changes the way that processors are - bootstrapped, and uses Clustered Logical APIC addressing mode instead - of Flat Logical. You will need a new lynxer.elf file to flash your - firmware with - send email to . - -config X86_SUMMIT - bool "Summit/EXA (IBM x440)" - depends on X86_32 && SMP - help - This option is needed for IBM systems that use the Summit/EXA chipset. - In particular, it is needed for the x440. - -config X86_ES7000 - bool "Support for Unisys ES7000 IA32 series" - depends on X86_32 && SMP - help - Support for Unisys ES7000 systems. Say 'Y' here if this kernel is - supposed to run on an IA32-based Unisys ES7000 system. - -config X86_BIGSMP - bool "Support for big SMP systems with more than 8 CPUs" - depends on X86_32 && SMP - help - This option is needed for the systems that have more than 8 CPUs - and if the system is not of any sub-arch type above. - -endif - config X86_VSMP bool "Support for ScaleMP vSMP" select PARAVIRT @@ -396,6 +351,49 @@ config X86_VOYAGER If you do not specifically know you have a Voyager based machine, say N here, otherwise the kernel you build will not be bootable. +config X86_GENERICARCH + bool "Support non-standard 32-bit SMP architectures" + depends on X86_32 && SMP + depends on X86_NON_STANDARD + help + This option compiles in the NUMAQ, Summit, bigsmp, ES7000, default + subarchitectures. It is intended for a generic binary kernel. + if you select them all, kernel will probe it one by one. and will + fallback to default. + +config X86_NUMAQ + bool "NUMAQ (IBM/Sequent)" + depends on X86_GENERICARCH + select NUMA + select X86_MPPARSE + help + This option is used for getting Linux to run on a NUMAQ (IBM/Sequent) + NUMA multiquad box. This changes the way that processors are + bootstrapped, and uses Clustered Logical APIC addressing mode instead + of Flat Logical. You will need a new lynxer.elf file to flash your + firmware with - send email to . + +config X86_SUMMIT + bool "Summit/EXA (IBM x440)" + depends on X86_GENERICARCH + help + This option is needed for IBM systems that use the Summit/EXA chipset. + In particular, it is needed for the x440. + +config X86_ES7000 + bool "Support for Unisys ES7000 IA32 series" + depends on X86_GENERICARCH + help + Support for Unisys ES7000 systems. Say 'Y' here if this kernel is + supposed to run on an IA32-based Unisys ES7000 system. + +config X86_BIGSMP + bool "Support for big SMP systems with more than 8 CPUs" + depends on X86_GENERICARCH + help + This option is needed for the systems that have more than 8 CPUs + and if the system is not of any sub-arch type above. + config SCHED_OMIT_FRAME_POINTER def_bool y prompt "Single-depth WCHAN output" -- GitLab From 6a48565ed6ac76f351def25cd5e9f181331065f6 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 18:29:13 +0100 Subject: [PATCH 0656/4982] x86: move X86_VSMP from subarch menu Move X86_VSMP out of the subarch menu - this way it can be enabled together with standard PC support as well, in the same kernel. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 2fe298297ce..ddddfb8fe09 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -271,15 +271,6 @@ config X86_PC help Choose this option if your computer is a standard PC or compatible. -config X86_VSMP - bool "Support for ScaleMP vSMP" - select PARAVIRT - depends on X86_64 && PCI - help - Support for ScaleMP vSMP systems. Say 'Y' here if this kernel is - supposed to run on these EM64T-based machines. Only choose this option - if you have one of these machines. - endchoice config X86_NON_STANDARD @@ -327,6 +318,16 @@ config X86_UV This option is needed in order to support SGI Ultraviolet systems. If you don't have one of these, you should say N here. +config X86_VSMP + bool "Support for ScaleMP vSMP" + select PARAVIRT + depends on X86_64 && PCI + depends on X86_NON_STANDARD + help + Support for ScaleMP vSMP systems. Say 'Y' here if this kernel is + supposed to run on these EM64T-based machines. Only choose this option + if you have one of these machines. + config X86_ELAN bool "AMD Elan" depends on X86_32 -- GitLab From e2c75d9f54334646b3dcdf1fea0d1afe7bfbf644 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 18:31:41 +0100 Subject: [PATCH 0657/4982] x86: remove the subarch menu Remove the subarch menu and standardize on X86_PC. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ddddfb8fe09..4773f1c54fb 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -262,16 +262,8 @@ config X86_MPPARSE For old smp systems that do not have proper acpi support. Newer systems (esp with 64bit cpus) with acpi support, MADT and DSDT will override it -choice - prompt "Subarchitecture Type" - default X86_PC - config X86_PC - bool "PC-compatible" - help - Choose this option if your computer is a standard PC or compatible. - -endchoice + def_bool y config X86_NON_STANDARD bool "Support for non-standard x86 platforms" -- GitLab From e0c7ae376a13fd79a4dad8becab51040d13dfa90 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 18:43:09 +0100 Subject: [PATCH 0658/4982] x86: rename X86_GENERICARCH to X86_32_NON_STANDARD X86_GENERICARCH is a misnomer - it contains non-PC 32-bit architectures that are not included in the default build. Rename it to X86_32_NON_STANDARD. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 22 +++++++++++----------- arch/x86/kernel/acpi/boot.c | 2 +- arch/x86/kernel/mpparse.c | 2 +- arch/x86/kernel/setup.c | 2 +- arch/x86/kernel/smpboot.c | 2 +- drivers/mtd/nand/Kconfig | 2 +- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 4773f1c54fb..1427cb1ccd9 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -344,7 +344,7 @@ config X86_VOYAGER If you do not specifically know you have a Voyager based machine, say N here, otherwise the kernel you build will not be bootable. -config X86_GENERICARCH +config X86_32_NON_STANDARD bool "Support non-standard 32-bit SMP architectures" depends on X86_32 && SMP depends on X86_NON_STANDARD @@ -356,7 +356,7 @@ config X86_GENERICARCH config X86_NUMAQ bool "NUMAQ (IBM/Sequent)" - depends on X86_GENERICARCH + depends on X86_32_NON_STANDARD select NUMA select X86_MPPARSE help @@ -368,21 +368,21 @@ config X86_NUMAQ config X86_SUMMIT bool "Summit/EXA (IBM x440)" - depends on X86_GENERICARCH + depends on X86_32_NON_STANDARD help This option is needed for IBM systems that use the Summit/EXA chipset. In particular, it is needed for the x440. config X86_ES7000 bool "Support for Unisys ES7000 IA32 series" - depends on X86_GENERICARCH + depends on X86_32_NON_STANDARD help Support for Unisys ES7000 systems. Say 'Y' here if this kernel is supposed to run on an IA32-based Unisys ES7000 system. config X86_BIGSMP bool "Support for big SMP systems with more than 8 CPUs" - depends on X86_GENERICARCH + depends on X86_32_NON_STANDARD help This option is needed for the systems that have more than 8 CPUs and if the system is not of any sub-arch type above. @@ -475,11 +475,11 @@ config MEMTEST config X86_SUMMIT_NUMA def_bool y - depends on X86_32 && NUMA && X86_GENERICARCH + depends on X86_32 && NUMA && X86_32_NON_STANDARD config X86_CYCLONE_TIMER def_bool y - depends on X86_GENERICARCH + depends on X86_32_NON_STANDARD source "arch/x86/Kconfig.cpu" @@ -651,7 +651,7 @@ source "kernel/Kconfig.preempt" config X86_UP_APIC bool "Local APIC support on uniprocessors" - depends on X86_32 && !SMP && !X86_GENERICARCH + depends on X86_32 && !SMP && !X86_32_NON_STANDARD help A local APIC (Advanced Programmable Interrupt Controller) is an integrated interrupt controller in the CPU. If you have a single-CPU @@ -676,11 +676,11 @@ config X86_UP_IOAPIC config X86_LOCAL_APIC def_bool y - depends on X86_64 || SMP || X86_GENERICARCH || X86_UP_APIC + depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC config X86_IO_APIC def_bool y - depends on X86_64 || SMP || X86_GENERICARCH || X86_UP_APIC + depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC config X86_VISWS_APIC def_bool y @@ -1122,7 +1122,7 @@ config ARCH_SPARSEMEM_DEFAULT config ARCH_SPARSEMEM_ENABLE def_bool y - depends on X86_64 || NUMA || (EXPERIMENTAL && X86_PC) || X86_GENERICARCH + depends on X86_64 || NUMA || (EXPERIMENTAL && X86_PC) || X86_32_NON_STANDARD select SPARSEMEM_STATIC if X86_32 select SPARSEMEM_VMEMMAP_ENABLE if X86_64 diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index cb8b52785e3..7352c60f29d 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -1335,7 +1335,7 @@ static void __init acpi_process_madt(void) if (!error) { acpi_lapic = 1; -#ifdef CONFIG_X86_GENERICARCH +#ifdef CONFIG_X86_32_NON_STANDARD generic_bigsmp_probe(); #endif /* diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 94fe71029c3..89aaced51bd 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -372,7 +372,7 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) (*x86_quirks->mpc_record)++; } -#ifdef CONFIG_X86_GENERICARCH +#ifdef CONFIG_X86_32_NON_STANDARD generic_bigsmp_probe(); #endif diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 6abce6703c5..f64e1a487c9 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -936,7 +936,7 @@ void __init setup_arch(char **cmdline_p) map_vsyscall(); #endif -#ifdef CONFIG_X86_GENERICARCH +#ifdef CONFIG_X86_32_NON_STANDARD generic_apic_probe(); #endif diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index bc7e220ba0b..fc80bc18943 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1007,7 +1007,7 @@ static int __init smp_sanity_check(unsigned max_cpus) printk(KERN_WARNING "More than 8 CPUs detected - skipping them.\n" - "Use CONFIG_X86_GENERICARCH and CONFIG_X86_BIGSMP.\n"); + "Use CONFIG_X86_32_NON_STANDARD and CONFIG_X86_BIGSMP.\n"); nr = 0; for_each_present_cpu(cpu) { diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 8b12e6e109d..928923665f6 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -273,7 +273,7 @@ config MTD_NAND_CAFE config MTD_NAND_CS553X tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)" - depends on X86_32 && (X86_PC || X86_GENERICARCH) + depends on X86_32 && (X86_PC || X86_32_NON_STANDARD) help The CS553x companion chips for the AMD Geode processor include NAND flash controllers with built-in hardware ECC -- GitLab From 3769e7b4d8ef113e08221a210f849ba57475aff5 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 27 Jan 2009 18:46:23 +0100 Subject: [PATCH 0659/4982] x86/Voyager: move to the X86_32_NON_STANDARD code section Make Voyager depend on X86_32_NON_STANDARD - it is a non-standard 32-bit SMP architecture. Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 1427cb1ccd9..5bf0e0c5828 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -331,19 +331,6 @@ config X86_ELAN If unsure, choose "PC-compatible" instead. -config X86_VOYAGER - bool "Voyager (NCR)" - depends on X86_32 && SMP && !PCI && BROKEN - depends on X86_NON_STANDARD - help - Voyager is an MCA-based 32-way capable SMP architecture proprietary - to NCR Corp. Machine classes 345x/35xx/4100/51xx are Voyager-based. - - *** WARNING *** - - If you do not specifically know you have a Voyager based machine, - say N here, otherwise the kernel you build will not be bootable. - config X86_32_NON_STANDARD bool "Support non-standard 32-bit SMP architectures" depends on X86_32 && SMP @@ -354,6 +341,13 @@ config X86_32_NON_STANDARD if you select them all, kernel will probe it one by one. and will fallback to default. +config X86_BIGSMP + bool "Support for big SMP systems with more than 8 CPUs" + depends on X86_32_NON_STANDARD + help + This option is needed for the systems that have more than 8 CPUs + and if the system is not of any sub-arch type above. + config X86_NUMAQ bool "NUMAQ (IBM/Sequent)" depends on X86_32_NON_STANDARD @@ -380,12 +374,18 @@ config X86_ES7000 Support for Unisys ES7000 systems. Say 'Y' here if this kernel is supposed to run on an IA32-based Unisys ES7000 system. -config X86_BIGSMP - bool "Support for big SMP systems with more than 8 CPUs" +config X86_VOYAGER + bool "Voyager (NCR)" + depends on SMP && !PCI && BROKEN depends on X86_32_NON_STANDARD help - This option is needed for the systems that have more than 8 CPUs - and if the system is not of any sub-arch type above. + Voyager is an MCA-based 32-way capable SMP architecture proprietary + to NCR Corp. Machine classes 345x/35xx/4100/51xx are Voyager-based. + + *** WARNING *** + + If you do not specifically know you have a Voyager based machine, + say N here, otherwise the kernel you build will not be bootable. config SCHED_OMIT_FRAME_POINTER def_bool y -- GitLab From 0a1e8869f453ceda121a1ff8d6c4380832377be7 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Wed, 28 Jan 2009 23:21:25 +0300 Subject: [PATCH 0660/4982] x86: trampoline_64.S - use predefined constants with simplification Impact: cleanup We may use macros from processor-flags.h instead of hardcoding bits. Actually it's not direct mapping of old instructions with new ones -- BTS does change CF flag while MOV does not. But i didn't find any dependency on CF in this code. Signed-off-by: Cyrill Gorcunov Acked-by: Alexander van Heukelum Signed-off-by: Ingo Molnar --- arch/x86/kernel/trampoline_64.S | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/arch/x86/kernel/trampoline_64.S b/arch/x86/kernel/trampoline_64.S index 894293c598d..95a012a4664 100644 --- a/arch/x86/kernel/trampoline_64.S +++ b/arch/x86/kernel/trampoline_64.S @@ -29,6 +29,7 @@ #include #include #include +#include .section .rodata, "a", @progbits @@ -37,7 +38,7 @@ ENTRY(trampoline_data) r_base = . cli # We should be safe anyway - wbinvd + wbinvd mov %cs, %ax # Code and data in the same place mov %ax, %ds mov %ax, %es @@ -73,9 +74,8 @@ r_base = . lidtl tidt - r_base # load idt with 0, 0 lgdtl tgdt - r_base # load gdt with whatever is appropriate - xor %ax, %ax - inc %ax # protected mode (PE) bit - lmsw %ax # into protected mode + mov $X86_CR0_PE, %ax # protected mode (PE) bit + lmsw %ax # into protected mode # flush prefetch and jump to startup_32 ljmpl *(startup_32_vector - r_base) @@ -86,9 +86,8 @@ startup_32: movl $__KERNEL_DS, %eax # Initialize the %ds segment register movl %eax, %ds - xorl %eax, %eax - btsl $5, %eax # Enable PAE mode - movl %eax, %cr4 + movl $X86_CR4_PAE, %eax + movl %eax, %cr4 # Enable PAE mode # Setup trampoline 4 level pagetables leal (trampoline_level4_pgt - r_base)(%esi), %eax @@ -99,9 +98,9 @@ startup_32: xorl %edx, %edx wrmsr - xorl %eax, %eax - btsl $31, %eax # Enable paging and in turn activate Long Mode - btsl $0, %eax # Enable protected mode + # Enable paging and in turn activate Long Mode + # Enable protected mode + movl $(X86_CR0_PG | X86_CR0_PE), %eax movl %eax, %cr0 /* -- GitLab From 7393958f630ac91e591e62058f2bdb61523ec60c Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 29 Jan 2009 14:57:50 +0200 Subject: [PATCH 0661/4982] ASoC: TWL4030: Add analog loopback support This patch adds the analog loopback/bypass support for twl4030 codec. Details for the implementation: It seams that the analog loopback needs the DAC powered on on the channel, where the loopback is selected. The switch for the DACs has been moved from the DAPM_DAC to the "Analog XX Playback Mixer". In this way the DAC will be powered while the audio playback is used or/and the loopback is enabled for the channel. The twl4030 codec powering has been reworked. Now the codec will be powered as long as it does not receives the SND_SOC_BIAS_OFF event. The exceptions are when the given change in the registers needs the codec power down/up cycle in order to take effect. Otherwise the codec is on. When the codec enters to STANDBY state and none of the loopback paths are enabled, than the amplifiers, which are no in the DAPM path are forced to turn off and the PLL is disabled. When playback/capture starts the disabled gains are restored and the PLL is enabled. When one of the loopback enabled in STANDBY mode, the disabled gains are restored and the PLL is enabled also. In short: the codec always goes to the lowest power state based on the bias_level and the bypass_state. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/codecs/twl4030.c | 212 ++++++++++++++++++++++++++++++++++--- sound/soc/codecs/twl4030.h | 15 +++ 2 files changed, 214 insertions(+), 13 deletions(-) diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index f985bef40a3..c26854b398d 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -117,6 +117,13 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = { 0x00, /* REG_MISC_SET_2 (0x49) */ }; +/* codec private data */ +struct twl4030_priv { + unsigned int bypass_state; + unsigned int codec_powered; + unsigned int codec_muted; +}; + /* * read twl4030 register cache */ @@ -156,8 +163,12 @@ static int twl4030_write(struct snd_soc_codec *codec, static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) { + struct twl4030_priv *twl4030 = codec->private_data; u8 mode; + if (enable == twl4030->codec_powered) + return; + mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE); if (enable) mode |= TWL4030_CODECPDZ; @@ -165,6 +176,7 @@ static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) mode &= ~TWL4030_CODECPDZ; twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode); + twl4030->codec_powered = enable; /* REVISIT: this delay is present in TI sample drivers */ /* but there seems to be no TRM requirement for it */ @@ -184,11 +196,82 @@ static void twl4030_init_chip(struct snd_soc_codec *codec) } +static void twl4030_codec_mute(struct snd_soc_codec *codec, int mute) +{ + struct twl4030_priv *twl4030 = codec->private_data; + u8 reg_val; + + if (mute == twl4030->codec_muted) + return; + + if (mute) { + /* Bypass the reg_cache and mute the volumes + * Headset mute is done in it's own event handler + * Things to mute: Earpiece, PreDrivL/R, CarkitL/R + */ + reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_EAR_CTL); + twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + reg_val & (~TWL4030_EAR_GAIN), + TWL4030_REG_EAR_CTL); + + reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PREDL_CTL); + twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + reg_val & (~TWL4030_PREDL_GAIN), + TWL4030_REG_PREDL_CTL); + reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PREDR_CTL); + twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + reg_val & (~TWL4030_PREDR_GAIN), + TWL4030_REG_PREDL_CTL); + + reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PRECKL_CTL); + twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + reg_val & (~TWL4030_PRECKL_GAIN), + TWL4030_REG_PRECKL_CTL); + reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PRECKR_CTL); + twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + reg_val & (~TWL4030_PRECKL_GAIN), + TWL4030_REG_PRECKR_CTL); + + /* Disable PLL */ + reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL); + reg_val &= ~TWL4030_APLL_EN; + twl4030_write(codec, TWL4030_REG_APLL_CTL, reg_val); + } else { + /* Restore the volumes + * Headset mute is done in it's own event handler + * Things to restore: Earpiece, PreDrivL/R, CarkitL/R + */ + twl4030_write(codec, TWL4030_REG_EAR_CTL, + twl4030_read_reg_cache(codec, TWL4030_REG_EAR_CTL)); + + twl4030_write(codec, TWL4030_REG_PREDL_CTL, + twl4030_read_reg_cache(codec, TWL4030_REG_PREDL_CTL)); + twl4030_write(codec, TWL4030_REG_PREDR_CTL, + twl4030_read_reg_cache(codec, TWL4030_REG_PREDR_CTL)); + + twl4030_write(codec, TWL4030_REG_PRECKL_CTL, + twl4030_read_reg_cache(codec, TWL4030_REG_PRECKL_CTL)); + twl4030_write(codec, TWL4030_REG_PRECKR_CTL, + twl4030_read_reg_cache(codec, TWL4030_REG_PRECKR_CTL)); + + /* Enable PLL */ + reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL); + reg_val |= TWL4030_APLL_EN; + twl4030_write(codec, TWL4030_REG_APLL_CTL, reg_val); + } + + twl4030->codec_muted = mute; +} + static void twl4030_power_up(struct snd_soc_codec *codec) { + struct twl4030_priv *twl4030 = codec->private_data; u8 anamicl, regmisc1, byte; int i = 0; + if (twl4030->codec_powered) + return; + /* set CODECPDZ to turn on codec */ twl4030_codec_enable(codec, 1); @@ -220,6 +303,9 @@ static void twl4030_power_up(struct snd_soc_codec *codec) twl4030_codec_enable(codec, 1); } +/* + * Unconditional power down + */ static void twl4030_power_down(struct snd_soc_codec *codec) { /* power down */ @@ -402,6 +488,22 @@ static const struct soc_enum twl4030_micpathtx2_enum = static const struct snd_kcontrol_new twl4030_dapm_micpathtx2_control = SOC_DAPM_ENUM("Route", twl4030_micpathtx2_enum); +/* Analog bypass for AudioR1 */ +static const struct snd_kcontrol_new twl4030_dapm_abypassr1_control = + SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXR1_APGA_CTL, 2, 1, 0); + +/* Analog bypass for AudioL1 */ +static const struct snd_kcontrol_new twl4030_dapm_abypassl1_control = + SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXL1_APGA_CTL, 2, 1, 0); + +/* Analog bypass for AudioR2 */ +static const struct snd_kcontrol_new twl4030_dapm_abypassr2_control = + SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXR2_APGA_CTL, 2, 1, 0); + +/* Analog bypass for AudioL2 */ +static const struct snd_kcontrol_new twl4030_dapm_abypassl2_control = + SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXL2_APGA_CTL, 2, 1, 0); + static int micpath_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -497,6 +599,31 @@ static int headsetl_event(struct snd_soc_dapm_widget *w, return 0; } +static int bypass_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct soc_mixer_control *m = + (struct soc_mixer_control *)w->kcontrols->private_value; + struct twl4030_priv *twl4030 = w->codec->private_data; + unsigned char reg; + + reg = twl4030_read_reg_cache(w->codec, m->reg); + if (reg & (1 << m->shift)) + twl4030->bypass_state |= + (1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL)); + else + twl4030->bypass_state &= + ~(1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL)); + + if (w->codec->bias_level == SND_SOC_BIAS_STANDBY) { + if (twl4030->bypass_state) + twl4030_codec_mute(w->codec, 0); + else + twl4030_codec_mute(w->codec, 1); + } + return 0; +} + /* * Some of the gain controls in TWL (mostly those which are associated with * the outputs) are implemented in an interesting way: @@ -775,13 +902,13 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { /* DACs */ SND_SOC_DAPM_DAC("DAC Right1", "Right Front Playback", - TWL4030_REG_AVDAC_CTL, 0, 0), + SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_DAC("DAC Left1", "Left Front Playback", - TWL4030_REG_AVDAC_CTL, 1, 0), + SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_DAC("DAC Right2", "Right Rear Playback", - TWL4030_REG_AVDAC_CTL, 2, 0), + SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_DAC("DAC Left2", "Left Rear Playback", - TWL4030_REG_AVDAC_CTL, 3, 0), + SND_SOC_NOPM, 0, 0), /* Analog PGAs */ SND_SOC_DAPM_PGA("ARXR1_APGA", TWL4030_REG_ARXR1_APGA_CTL, @@ -793,6 +920,29 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { SND_SOC_DAPM_PGA("ARXL2_APGA", TWL4030_REG_ARXL2_APGA_CTL, 0, 0, NULL, 0), + /* Analog bypasses */ + SND_SOC_DAPM_SWITCH_E("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0, + &twl4030_dapm_abypassr1_control, bypass_event, + SND_SOC_DAPM_POST_REG), + SND_SOC_DAPM_SWITCH_E("Left1 Analog Loopback", SND_SOC_NOPM, 0, 0, + &twl4030_dapm_abypassl1_control, + bypass_event, SND_SOC_DAPM_POST_REG), + SND_SOC_DAPM_SWITCH_E("Right2 Analog Loopback", SND_SOC_NOPM, 0, 0, + &twl4030_dapm_abypassr2_control, + bypass_event, SND_SOC_DAPM_POST_REG), + SND_SOC_DAPM_SWITCH_E("Left2 Analog Loopback", SND_SOC_NOPM, 0, 0, + &twl4030_dapm_abypassl2_control, + bypass_event, SND_SOC_DAPM_POST_REG), + + SND_SOC_DAPM_MIXER("Analog R1 Playback Mixer", TWL4030_REG_AVDAC_CTL, + 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("Analog L1 Playback Mixer", TWL4030_REG_AVDAC_CTL, + 1, 0, NULL, 0), + SND_SOC_DAPM_MIXER("Analog R2 Playback Mixer", TWL4030_REG_AVDAC_CTL, + 2, 0, NULL, 0), + SND_SOC_DAPM_MIXER("Analog L2 Playback Mixer", TWL4030_REG_AVDAC_CTL, + 3, 0, NULL, 0), + /* Output MUX controls */ /* Earpiece */ SND_SOC_DAPM_VALUE_MUX("Earpiece Mux", SND_SOC_NOPM, 0, 0, @@ -863,13 +1013,19 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { SND_SOC_DAPM_MICBIAS("Mic Bias 1", TWL4030_REG_MICBIAS_CTL, 0, 0), SND_SOC_DAPM_MICBIAS("Mic Bias 2", TWL4030_REG_MICBIAS_CTL, 1, 0), SND_SOC_DAPM_MICBIAS("Headset Mic Bias", TWL4030_REG_MICBIAS_CTL, 2, 0), + }; static const struct snd_soc_dapm_route intercon[] = { - {"ARXL1_APGA", NULL, "DAC Left1"}, - {"ARXR1_APGA", NULL, "DAC Right1"}, - {"ARXL2_APGA", NULL, "DAC Left2"}, - {"ARXR2_APGA", NULL, "DAC Right2"}, + {"Analog L1 Playback Mixer", NULL, "DAC Left1"}, + {"Analog R1 Playback Mixer", NULL, "DAC Right1"}, + {"Analog L2 Playback Mixer", NULL, "DAC Left2"}, + {"Analog R2 Playback Mixer", NULL, "DAC Right2"}, + + {"ARXL1_APGA", NULL, "Analog L1 Playback Mixer"}, + {"ARXR1_APGA", NULL, "Analog R1 Playback Mixer"}, + {"ARXL2_APGA", NULL, "Analog L2 Playback Mixer"}, + {"ARXR2_APGA", NULL, "Analog R2 Playback Mixer"}, /* Internal playback routings */ /* Earpiece */ @@ -951,6 +1107,17 @@ static const struct snd_soc_dapm_route intercon[] = { {"ADC Virtual Left2", NULL, "TX2 Capture Route"}, {"ADC Virtual Right2", NULL, "TX2 Capture Route"}, + /* Analog bypass routes */ + {"Right1 Analog Loopback", "Switch", "Analog Right Capture Route"}, + {"Left1 Analog Loopback", "Switch", "Analog Left Capture Route"}, + {"Right2 Analog Loopback", "Switch", "Analog Right Capture Route"}, + {"Left2 Analog Loopback", "Switch", "Analog Left Capture Route"}, + + {"Analog R1 Playback Mixer", NULL, "Right1 Analog Loopback"}, + {"Analog L1 Playback Mixer", NULL, "Left1 Analog Loopback"}, + {"Analog R2 Playback Mixer", NULL, "Right2 Analog Loopback"}, + {"Analog L2 Playback Mixer", NULL, "Left2 Analog Loopback"}, + }; static int twl4030_add_widgets(struct snd_soc_codec *codec) @@ -967,16 +1134,25 @@ static int twl4030_add_widgets(struct snd_soc_codec *codec) static int twl4030_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct twl4030_priv *twl4030 = codec->private_data; + switch (level) { case SND_SOC_BIAS_ON: - twl4030_power_up(codec); + twl4030_codec_mute(codec, 0); break; case SND_SOC_BIAS_PREPARE: - /* TODO: develop a twl4030_prepare function */ + twl4030_power_up(codec); + if (twl4030->bypass_state) + twl4030_codec_mute(codec, 0); + else + twl4030_codec_mute(codec, 1); break; case SND_SOC_BIAS_STANDBY: - /* TODO: develop a twl4030_standby function */ - twl4030_power_down(codec); + twl4030_power_up(codec); + if (twl4030->bypass_state) + twl4030_codec_mute(codec, 0); + else + twl4030_codec_mute(codec, 1); break; case SND_SOC_BIAS_OFF: twl4030_power_down(codec); @@ -996,7 +1172,6 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = socdev->card->codec; u8 mode, old_mode, format, old_format; - /* bit rate */ old_mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ; @@ -1038,6 +1213,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream, if (mode != old_mode) { /* change rate and set CODECPDZ */ + twl4030_codec_enable(codec, 0); twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode); twl4030_codec_enable(codec, 1); } @@ -1258,11 +1434,19 @@ static int twl4030_probe(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct snd_soc_codec *codec; + struct twl4030_priv *twl4030; codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); if (codec == NULL) return -ENOMEM; + twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL); + if (twl4030 == NULL) { + kfree(codec); + return -ENOMEM; + } + + codec->private_data = twl4030; socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); @@ -1280,8 +1464,10 @@ static int twl4030_remove(struct platform_device *pdev) struct snd_soc_codec *codec = socdev->card->codec; printk(KERN_INFO "TWL4030 Audio Codec remove\n"); + twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); + kfree(codec->private_data); kfree(codec); return 0; diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h index 442e5a82861..33dbb144dad 100644 --- a/sound/soc/codecs/twl4030.h +++ b/sound/soc/codecs/twl4030.h @@ -170,6 +170,9 @@ #define TWL4030_CLK256FS_EN 0x02 #define TWL4030_AIF_EN 0x01 +/* EAR_CTL (0x21) */ +#define TWL4030_EAR_GAIN 0x30 + /* HS_GAIN_SET (0x23) Fields */ #define TWL4030_HSR_GAIN 0x0C @@ -198,6 +201,18 @@ #define TWL4030_RAMP_DELAY_2581MS 0x1C #define TWL4030_RAMP_EN 0x02 +/* PREDL_CTL (0x25) */ +#define TWL4030_PREDL_GAIN 0x30 + +/* PREDR_CTL (0x26) */ +#define TWL4030_PREDR_GAIN 0x30 + +/* PRECKL_CTL (0x27) */ +#define TWL4030_PRECKL_GAIN 0x30 + +/* PRECKR_CTL (0x28) */ +#define TWL4030_PRECKR_GAIN 0x30 + /* HFL_CTL (0x29, 0x2A) Fields */ #define TWL4030_HF_CTL_HB_EN 0x04 #define TWL4030_HF_CTL_LOOP_EN 0x08 -- GitLab From 010060741ad35eacb504414bc6fb9bb575b15f62 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 29 Jan 2009 16:02:12 +0100 Subject: [PATCH 0662/4982] x86: add might_sleep() to do_page_fault() Impact: widen debug checks VirtualBox calls do_page_fault() from an atomic context but runs into a might_sleep() way pas this point, cure that. Signed-off-by: Peter Zijlstra Signed-off-by: Ingo Molnar --- arch/x86/mm/fault.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 8f4b859a04b..eb4d7fe0593 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -888,6 +888,12 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) return; } down_read(&mm->mmap_sem); + } else { + /* + * The above down_read_trylock() might have succeeded in which + * case we'll have missed the might_sleep() from down_read(). + */ + might_sleep(); } vma = find_vma(mm, address); -- GitLab From b98b7b347eed333d6fa2f74770beb8106e576cc6 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Thu, 29 Jan 2009 13:18:31 -0200 Subject: [PATCH 0663/4982] ALSA: hda - make alc882_auto_init_input_src aware of selectors In the case of having a selector instead of mixer while initing input sources, the case that happens with ALC889, we must select instead of muting input. Problem was found while testing with hda-emu. Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index d81cb5eb8c5..3666cc5dc3b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6924,18 +6924,21 @@ static void alc882_auto_init_analog_input(struct hda_codec *codec) static void alc882_auto_init_input_src(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - const struct hda_input_mux *imux = spec->input_mux; int c; for (c = 0; c < spec->num_adc_nids; c++) { hda_nid_t conn_list[HDA_MAX_NUM_INPUTS]; hda_nid_t nid = spec->capsrc_nids[c]; + unsigned int mux_idx; + const struct hda_input_mux *imux; int conns, mute, idx, item; conns = snd_hda_get_connections(codec, nid, conn_list, ARRAY_SIZE(conn_list)); if (conns < 0) continue; + mux_idx = c >= spec->num_mux_defs ? 0 : c; + imux = &spec->input_mux[mux_idx]; for (idx = 0; idx < conns; idx++) { /* if the current connection is the selected one, * unmute it as default - otherwise mute it @@ -6948,8 +6951,20 @@ static void alc882_auto_init_input_src(struct hda_codec *codec) break; } } - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, mute); + /* check if we have a selector or mixer + * we could check for the widget type instead, but + * just check for Amp-In presence (in case of mixer + * without amp-in there is something wrong, this + * function shouldn't be used or capsrc nid is wrong) + */ + if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_AMP_GAIN_MUTE, + mute); + else if (mute != AMP_IN_MUTE(idx)) + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_CONNECT_SEL, + idx); } } } -- GitLab From dba3d36b2f0842ed7f25c33cd3a2ccdb3d0df9db Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 29 Jan 2009 17:10:12 +0100 Subject: [PATCH 0664/4982] Revert "generic, x86: fix __per_cpu_load relocation" This reverts commit 5a611268b69f05262936dd177205acbce4471358. It is causing occasional boot crashes, caused by certain linker versions (GNU ld version 2.18.50.0.6-2 20080403) messing up: 82dcc000 D __per_cpu_load c16e6000 A __per_cpu_load_abs The __per_cpu_load value is out of whack. Hpa noticed the following detail: * (gdb) p/x -(0xc16e6000-0x82dcc000) * $2 = 0xc16e6000 * I.e. one is the other << 1 The two symbols should be equal. Signed-off-by: Ingo Molnar --- include/asm-generic/vmlinux.lds.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index f3180a85c66..53e21f36a80 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -451,18 +451,17 @@ * end offset. */ #define PERCPU_VADDR(vaddr, phdr) \ - VMLINUX_SYMBOL(__per_cpu_load_abs) = .; \ - .data.percpu vaddr : AT(VMLINUX_SYMBOL(__per_cpu_load_abs) \ + VMLINUX_SYMBOL(__per_cpu_load) = .; \ + .data.percpu vaddr : AT(VMLINUX_SYMBOL(__per_cpu_load) \ - LOAD_OFFSET) { \ VMLINUX_SYMBOL(__per_cpu_start) = .; \ - VMLINUX_SYMBOL(__per_cpu_load) = LOADADDR(.data.percpu) + LOAD_OFFSET;\ *(.data.percpu.first) \ *(.data.percpu.page_aligned) \ *(.data.percpu) \ *(.data.percpu.shared_aligned) \ VMLINUX_SYMBOL(__per_cpu_end) = .; \ } phdr \ - . = VMLINUX_SYMBOL(__per_cpu_load_abs) + SIZEOF(.data.percpu); + . = VMLINUX_SYMBOL(__per_cpu_load) + SIZEOF(.data.percpu); /** * PERCPU - define output section for percpu area, simple version -- GitLab From fbeb2ca0224182033f196cf8f63989c3e6b90aba Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 29 Jan 2009 12:11:08 -0800 Subject: [PATCH 0665/4982] x86: unify genapic code, unify subarchitectures, remove old subarchitecture code, xapic fix xapic fix for 32bit platform with less than 8 cpu's. Signed-off-by: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/probe_32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/probe_32.c b/arch/x86/kernel/probe_32.c index 61339a0d55c..b5db26f8e06 100644 --- a/arch/x86/kernel/probe_32.c +++ b/arch/x86/kernel/probe_32.c @@ -113,7 +113,7 @@ struct genapic apic_default = { .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, .send_IPI_mask = default_send_IPI_mask, - .send_IPI_mask_allbutself = NULL, + .send_IPI_mask_allbutself = default_send_IPI_mask_allbutself, .send_IPI_allbutself = default_send_IPI_allbutself, .send_IPI_all = default_send_IPI_all, .send_IPI_self = NULL, -- GitLab From 019a1369667c3978f9644982ebe6d261dd2bbc40 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Thu, 29 Jan 2009 11:49:18 -0800 Subject: [PATCH 0666/4982] x86: uaccess: fix compilation error on CONFIG_M386 In case of !CONFIG_X86_WP_WORKS_OK, __put_user_size_ex() is not defined. Add macros for !CONFIG_X86_WP_WORKS_OK case. Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/include/asm/uaccess.h | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index 0ec6de4bcb0..b9a24155f7a 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -525,8 +525,6 @@ struct __large_struct { unsigned long buf[100]; }; */ #define get_user_try uaccess_try #define get_user_catch(err) uaccess_catch(err) -#define put_user_try uaccess_try -#define put_user_catch(err) uaccess_catch(err) #define get_user_ex(x, ptr) do { \ unsigned long __gue_val; \ @@ -534,9 +532,29 @@ struct __large_struct { unsigned long buf[100]; }; (x) = (__force __typeof__(*(ptr)))__gue_val; \ } while (0) +#ifdef CONFIG_X86_WP_WORKS_OK + +#define put_user_try uaccess_try +#define put_user_catch(err) uaccess_catch(err) + #define put_user_ex(x, ptr) \ __put_user_size_ex((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) +#else /* !CONFIG_X86_WP_WORKS_OK */ + +#define put_user_try do { \ + int __uaccess_err = 0; + +#define put_user_catch(err) \ + (err) |= __uaccess_err; \ +} while (0) + +#define put_user_ex(x, ptr) do { \ + __uaccess_err |= __put_user(x, ptr); \ +} while (0) + +#endif /* CONFIG_X86_WP_WORKS_OK */ + /* * movsl can be slow when source and dest are not both 8-byte aligned */ -- GitLab From e808e586b77a10949e209f8a00cb8bf27e51df12 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 19 Dec 2008 21:30:52 +0100 Subject: [PATCH 0667/4982] b43: Fixup set_key handling This fixes the key handling for mac80211's new key->flags. It also adds TX locking to the set_key handler and adds a comment why this is required. This doesn't fix any known bugs. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 36 ++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index c788bad1066..dad0781b4b6 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -937,8 +937,7 @@ static int b43_key_write(struct b43_wldev *dev, B43_WARN_ON(dev->key[i].keyconf == keyconf); } if (index < 0) { - /* Either pairwise key or address is 00:00:00:00:00:00 - * for transmit-only keys. Search the index. */ + /* Pairwise key. Get an empty slot for the key. */ if (b43_new_kidx_api(dev)) sta_keys_start = 4; else @@ -951,7 +950,7 @@ static int b43_key_write(struct b43_wldev *dev, } } if (index < 0) { - b43err(dev->wl, "Out of hardware key memory\n"); + b43warn(dev->wl, "Out of hardware key memory\n"); return -ENOSPC; } } else @@ -3525,7 +3524,6 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, { struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev; - unsigned long flags; u8 algorithm; u8 index; int err; @@ -3534,7 +3532,15 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -ENOSPC; /* User disabled HW-crypto */ mutex_lock(&wl->mutex); - spin_lock_irqsave(&wl->irq_lock, flags); + spin_lock_irq(&wl->irq_lock); + write_lock(&wl->tx_lock); + /* Why do we need all this locking here? + * mutex -> Every config operation must take it. + * irq_lock -> We modify the dev->key array, which is accessed + * in the IRQ handlers. + * tx_lock -> We modify the dev->key array, which is accessed + * in the TX handler. + */ dev = wl->current_dev; err = -ENODEV; @@ -3551,7 +3557,7 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, err = -EINVAL; switch (key->alg) { case ALG_WEP: - if (key->keylen == 5) + if (key->keylen == LEN_WEP40) algorithm = B43_SEC_ALGO_WEP40; else algorithm = B43_SEC_ALGO_WEP104; @@ -3578,17 +3584,14 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, goto out_unlock; } - if (is_broadcast_ether_addr(addr)) { - /* addr is FF:FF:FF:FF:FF:FF for default keys */ - err = b43_key_write(dev, index, algorithm, - key->key, key->keylen, NULL, key); - } else { - /* - * either pairwise key or address is 00:00:00:00:00:00 - * for transmit-only keys - */ + if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { + /* Pairwise key with an assigned MAC address. */ err = b43_key_write(dev, -1, algorithm, key->key, key->keylen, addr, key); + } else { + /* Group key */ + err = b43_key_write(dev, index, algorithm, + key->key, key->keylen, NULL, key); } if (err) goto out_unlock; @@ -3620,7 +3623,8 @@ out_unlock: addr); b43_dump_keymemory(dev); } - spin_unlock_irqrestore(&wl->irq_lock, flags); + write_unlock(&wl->tx_lock); + spin_unlock_irq(&wl->irq_lock); mutex_unlock(&wl->mutex); return err; -- GitLab From 3ebbbb56a162b8f9b9a77bc7810b9d4e0868e039 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 19 Dec 2008 22:51:57 +0100 Subject: [PATCH 0668/4982] b43: Use 64bit atomic register access for TSF On modern b43 devices with core rev >=3, the hardware guarantees us an atomic 64bit read/write of the TSF, if we access the lower 32bits first. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 89 ++++++++------------------------- 1 file changed, 20 insertions(+), 69 deletions(-) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index dad0781b4b6..ba989ae132a 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -526,52 +526,20 @@ void b43_hf_write(struct b43_wldev *dev, u64 value) b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI, hi); } -void b43_tsf_read(struct b43_wldev *dev, u64 * tsf) +void b43_tsf_read(struct b43_wldev *dev, u64 *tsf) { - /* We need to be careful. As we read the TSF from multiple - * registers, we should take care of register overflows. - * In theory, the whole tsf read process should be atomic. - * We try to be atomic here, by restaring the read process, - * if any of the high registers changed (overflew). - */ - if (dev->dev->id.revision >= 3) { - u32 low, high, high2; - - do { - high = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_HIGH); - low = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_LOW); - high2 = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_HIGH); - } while (unlikely(high != high2)); - - *tsf = high; - *tsf <<= 32; - *tsf |= low; - } else { - u64 tmp; - u16 v0, v1, v2, v3; - u16 test1, test2, test3; + u32 low, high; - do { - v3 = b43_read16(dev, B43_MMIO_TSF_3); - v2 = b43_read16(dev, B43_MMIO_TSF_2); - v1 = b43_read16(dev, B43_MMIO_TSF_1); - v0 = b43_read16(dev, B43_MMIO_TSF_0); + B43_WARN_ON(dev->dev->id.revision < 3); - test3 = b43_read16(dev, B43_MMIO_TSF_3); - test2 = b43_read16(dev, B43_MMIO_TSF_2); - test1 = b43_read16(dev, B43_MMIO_TSF_1); - } while (v3 != test3 || v2 != test2 || v1 != test1); + /* The hardware guarantees us an atomic read, if we + * read the low register first. */ + low = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_LOW); + high = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_HIGH); - *tsf = v3; - *tsf <<= 48; - tmp = v2; - tmp <<= 32; - *tsf |= tmp; - tmp = v1; - tmp <<= 16; - *tsf |= tmp; - *tsf |= v0; - } + *tsf = high; + *tsf <<= 32; + *tsf |= low; } static void b43_time_lock(struct b43_wldev *dev) @@ -598,35 +566,18 @@ static void b43_time_unlock(struct b43_wldev *dev) static void b43_tsf_write_locked(struct b43_wldev *dev, u64 tsf) { - /* Be careful with the in-progress timer. - * First zero out the low register, so we have a full - * register-overflow duration to complete the operation. - */ - if (dev->dev->id.revision >= 3) { - u32 lo = (tsf & 0x00000000FFFFFFFFULL); - u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32; + u32 low, high; - b43_write32(dev, B43_MMIO_REV3PLUS_TSF_LOW, 0); - mmiowb(); - b43_write32(dev, B43_MMIO_REV3PLUS_TSF_HIGH, hi); - mmiowb(); - b43_write32(dev, B43_MMIO_REV3PLUS_TSF_LOW, lo); - } else { - u16 v0 = (tsf & 0x000000000000FFFFULL); - u16 v1 = (tsf & 0x00000000FFFF0000ULL) >> 16; - u16 v2 = (tsf & 0x0000FFFF00000000ULL) >> 32; - u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48; + B43_WARN_ON(dev->dev->id.revision < 3); - b43_write16(dev, B43_MMIO_TSF_0, 0); - mmiowb(); - b43_write16(dev, B43_MMIO_TSF_3, v3); - mmiowb(); - b43_write16(dev, B43_MMIO_TSF_2, v2); - mmiowb(); - b43_write16(dev, B43_MMIO_TSF_1, v1); - mmiowb(); - b43_write16(dev, B43_MMIO_TSF_0, v0); - } + low = tsf; + high = (tsf >> 32); + /* The hardware guarantees us an atomic write, if we + * write the low register first. */ + b43_write32(dev, B43_MMIO_REV3PLUS_TSF_LOW, low); + mmiowb(); + b43_write32(dev, B43_MMIO_REV3PLUS_TSF_HIGH, high); + mmiowb(); } void b43_tsf_write(struct b43_wldev *dev, u64 tsf) -- GitLab From 7d7f19ccb777946df0a8fb7c83189ba2ae08b02e Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 20 Dec 2008 10:52:42 +0100 Subject: [PATCH 0669/4982] rt2x00: Implement Powersaving Listen to IEEE80211_CONF_PS to determine if the device should drop into powersaving mode. This feature depends on the dynamic power save functionality in mac80211. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 28 +++++++++++++ drivers/net/wireless/rt2x00/rt2500pci.c | 28 +++++++++++++ drivers/net/wireless/rt2x00/rt2500usb.c | 28 +++++++++++++ drivers/net/wireless/rt2x00/rt61pci.c | 53 +++++++++++++++++++++---- drivers/net/wireless/rt2x00/rt61pci.h | 4 ++ drivers/net/wireless/rt2x00/rt73usb.c | 40 +++++++++++++++++++ 6 files changed, 174 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 6a977679124..1afba42cc12 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -524,6 +524,32 @@ static void rt2400pci_config_duration(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_write(rt2x00dev, CSR12, reg); } +static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf) +{ + enum dev_state state = + (libconf->conf->flags & IEEE80211_CONF_PS) ? + STATE_SLEEP : STATE_AWAKE; + u32 reg; + + if (state == STATE_SLEEP) { + rt2x00pci_register_read(rt2x00dev, CSR20, ®); + rt2x00_set_field32(®, CSR20_DELAY_AFTER_TBCN, + (libconf->conf->beacon_int - 20) * 16); + rt2x00_set_field32(®, CSR20_TBCN_BEFORE_WAKEUP, + libconf->conf->listen_interval - 1); + + /* We must first disable autowake before it can be enabled */ + rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); + rt2x00pci_register_write(rt2x00dev, CSR20, reg); + + rt2x00_set_field32(®, CSR20_AUTOWAKE, 1); + rt2x00pci_register_write(rt2x00dev, CSR20, reg); + } + + rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); +} + static void rt2400pci_config(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_conf *libconf, const unsigned int flags) @@ -537,6 +563,8 @@ static void rt2400pci_config(struct rt2x00_dev *rt2x00dev, rt2400pci_config_retry_limit(rt2x00dev, libconf); if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) rt2400pci_config_duration(rt2x00dev, libconf); + if (flags & IEEE80211_CONF_CHANGE_PS) + rt2400pci_config_ps(rt2x00dev, libconf); } static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index d3bc218ec85..bf5e81162f2 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -573,6 +573,32 @@ static void rt2500pci_config_duration(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_write(rt2x00dev, CSR12, reg); } +static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf) +{ + enum dev_state state = + (libconf->conf->flags & IEEE80211_CONF_PS) ? + STATE_SLEEP : STATE_AWAKE; + u32 reg; + + if (state == STATE_SLEEP) { + rt2x00pci_register_read(rt2x00dev, CSR20, ®); + rt2x00_set_field32(®, CSR20_DELAY_AFTER_TBCN, + (libconf->conf->beacon_int - 20) * 16); + rt2x00_set_field32(®, CSR20_TBCN_BEFORE_WAKEUP, + libconf->conf->listen_interval - 1); + + /* We must first disable autowake before it can be enabled */ + rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); + rt2x00pci_register_write(rt2x00dev, CSR20, reg); + + rt2x00_set_field32(®, CSR20_AUTOWAKE, 1); + rt2x00pci_register_write(rt2x00dev, CSR20, reg); + } + + rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); +} + static void rt2500pci_config(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_conf *libconf, const unsigned int flags) @@ -588,6 +614,8 @@ static void rt2500pci_config(struct rt2x00_dev *rt2x00dev, rt2500pci_config_retry_limit(rt2x00dev, libconf); if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) rt2500pci_config_duration(rt2x00dev, libconf); + if (flags & IEEE80211_CONF_CHANGE_PS) + rt2500pci_config_ps(rt2x00dev, libconf); } /* diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index af6b5847be5..23cf585f03a 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -634,6 +634,32 @@ static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev, rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); } +static void rt2500usb_config_ps(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf) +{ + enum dev_state state = + (libconf->conf->flags & IEEE80211_CONF_PS) ? + STATE_SLEEP : STATE_AWAKE; + u16 reg; + + if (state == STATE_SLEEP) { + rt2500usb_register_read(rt2x00dev, MAC_CSR18, ®); + rt2x00_set_field16(®, MAC_CSR18_DELAY_AFTER_BEACON, + libconf->conf->beacon_int - 20); + rt2x00_set_field16(®, MAC_CSR18_BEACONS_BEFORE_WAKEUP, + libconf->conf->listen_interval - 1); + + /* We must first disable autowake before it can be enabled */ + rt2x00_set_field16(®, MAC_CSR18_AUTO_WAKE, 0); + rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg); + + rt2x00_set_field16(®, MAC_CSR18_AUTO_WAKE, 1); + rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg); + } + + rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); +} + static void rt2500usb_config(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_conf *libconf, const unsigned int flags) @@ -647,6 +673,8 @@ static void rt2500usb_config(struct rt2x00_dev *rt2x00dev, libconf->conf->power_level); if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) rt2500usb_config_duration(rt2x00dev, libconf); + if (flags & IEEE80211_CONF_CHANGE_PS) + rt2500usb_config_ps(rt2x00dev, libconf); } /* diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 987e89009f7..c7ab744f005 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -146,12 +146,6 @@ static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev, mutex_unlock(&rt2x00dev->csr_mutex); } -#ifdef CONFIG_RT2X00_LIB_LEDS -/* - * This function is only called from rt61pci_led_brightness() - * make gcc happy by placing this function inside the - * same ifdef statement as the caller. - */ static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev, const u8 command, const u8 token, const u8 arg0, const u8 arg1) @@ -180,7 +174,6 @@ static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev, mutex_unlock(&rt2x00dev->csr_mutex); } -#endif /* CONFIG_RT2X00_LIB_LEDS */ static void rt61pci_eepromregister_read(struct eeprom_93cx6 *eeprom) { @@ -967,6 +960,50 @@ static void rt61pci_config_duration(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); } +static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf) +{ + enum dev_state state = + (libconf->conf->flags & IEEE80211_CONF_PS) ? + STATE_SLEEP : STATE_AWAKE; + u32 reg; + + if (state == STATE_SLEEP) { + rt2x00pci_register_read(rt2x00dev, MAC_CSR11, ®); + rt2x00_set_field32(®, MAC_CSR11_DELAY_AFTER_TBCN, + libconf->conf->beacon_int - 10); + rt2x00_set_field32(®, MAC_CSR11_TBCN_BEFORE_WAKEUP, + libconf->conf->listen_interval - 1); + rt2x00_set_field32(®, MAC_CSR11_WAKEUP_LATENCY, 5); + + /* We must first disable autowake before it can be enabled */ + rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 0); + rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg); + + rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 1); + rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg); + + rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000005); + rt2x00pci_register_write(rt2x00dev, IO_CNTL_CSR, 0x0000001c); + rt2x00pci_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000060); + + rt61pci_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 0); + } else { + rt2x00pci_register_read(rt2x00dev, MAC_CSR11, ®); + rt2x00_set_field32(®, MAC_CSR11_DELAY_AFTER_TBCN, 0); + rt2x00_set_field32(®, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0); + rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 0); + rt2x00_set_field32(®, MAC_CSR11_WAKEUP_LATENCY, 0); + rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg); + + rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000007); + rt2x00pci_register_write(rt2x00dev, IO_CNTL_CSR, 0x00000018); + rt2x00pci_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000020); + + rt61pci_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0); + } +} + static void rt61pci_config(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_conf *libconf, const unsigned int flags) @@ -984,6 +1021,8 @@ static void rt61pci_config(struct rt2x00_dev *rt2x00dev, rt61pci_config_retry_limit(rt2x00dev, libconf); if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) rt61pci_config_duration(rt2x00dev, libconf); + if (flags & IEEE80211_CONF_CHANGE_PS) + rt61pci_config_ps(rt2x00dev, libconf); } /* diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index 65fe3332364..86590c6de0e 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -88,8 +88,10 @@ /* * SOFT_RESET_CSR + * FORCE_CLOCK_ON: Host force MAC clock ON */ #define SOFT_RESET_CSR 0x0010 +#define SOFT_RESET_CSR_FORCE_CLOCK_ON FIELD32(0x00000002) /* * MCU_INT_SOURCE_CSR: MCU interrupt source/mask register. @@ -1054,8 +1056,10 @@ struct hw_pairwise_ta_entry { /* * IO_CNTL_CSR + * RF_PS: Set RF interface value to power save */ #define IO_CNTL_CSR 0x3498 +#define IO_CNTL_CSR_RF_PS FIELD32(0x00000004) /* * UART_INT_SOURCE_CSR diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 96a8d69f879..ae3b31d0d51 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -844,6 +844,44 @@ static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev, rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); } +static void rt73usb_config_ps(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf) +{ + enum dev_state state = + (libconf->conf->flags & IEEE80211_CONF_PS) ? + STATE_SLEEP : STATE_AWAKE; + u32 reg; + + if (state == STATE_SLEEP) { + rt2x00usb_register_read(rt2x00dev, MAC_CSR11, ®); + rt2x00_set_field32(®, MAC_CSR11_DELAY_AFTER_TBCN, + libconf->conf->beacon_int - 10); + rt2x00_set_field32(®, MAC_CSR11_TBCN_BEFORE_WAKEUP, + libconf->conf->listen_interval - 1); + rt2x00_set_field32(®, MAC_CSR11_WAKEUP_LATENCY, 5); + + /* We must first disable autowake before it can be enabled */ + rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 0); + rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg); + + rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 1); + rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg); + + rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, + USB_MODE_SLEEP, REGISTER_TIMEOUT); + } else { + rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, + USB_MODE_WAKEUP, REGISTER_TIMEOUT); + + rt2x00usb_register_read(rt2x00dev, MAC_CSR11, ®); + rt2x00_set_field32(®, MAC_CSR11_DELAY_AFTER_TBCN, 0); + rt2x00_set_field32(®, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0); + rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 0); + rt2x00_set_field32(®, MAC_CSR11_WAKEUP_LATENCY, 0); + rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg); + } +} + static void rt73usb_config(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_conf *libconf, const unsigned int flags) @@ -861,6 +899,8 @@ static void rt73usb_config(struct rt2x00_dev *rt2x00dev, rt73usb_config_retry_limit(rt2x00dev, libconf); if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) rt73usb_config_duration(rt2x00dev, libconf); + if (flags & IEEE80211_CONF_CHANGE_PS) + rt73usb_config_ps(rt2x00dev, libconf); } /* -- GitLab From 84e3196ff867c623056eea02c11a45e046490d89 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 20 Dec 2008 10:53:29 +0100 Subject: [PATCH 0670/4982] rt2x00: Move link tuning into seperate file Move link and antenna tuning into a seperate file named rt2x00link.c, this makes the interface to the link tuner a lot cleaner. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Makefile | 1 + drivers/net/wireless/rt2x00/rt2x00.h | 29 +- drivers/net/wireless/rt2x00/rt2x00config.c | 5 +- drivers/net/wireless/rt2x00/rt2x00debug.c | 4 +- drivers/net/wireless/rt2x00/rt2x00dev.c | 303 +--------------- drivers/net/wireless/rt2x00/rt2x00lib.h | 81 ++++- drivers/net/wireless/rt2x00/rt2x00link.c | 402 +++++++++++++++++++++ 7 files changed, 494 insertions(+), 331 deletions(-) create mode 100644 drivers/net/wireless/rt2x00/rt2x00link.c diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile index 917cb4f3b03..f22d808d8c5 100644 --- a/drivers/net/wireless/rt2x00/Makefile +++ b/drivers/net/wireless/rt2x00/Makefile @@ -2,6 +2,7 @@ rt2x00lib-y += rt2x00dev.o rt2x00lib-y += rt2x00mac.o rt2x00lib-y += rt2x00config.o rt2x00lib-y += rt2x00queue.o +rt2x00lib-y += rt2x00link.o rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS) += rt2x00debug.o rt2x00lib-$(CONFIG_RT2X00_LIB_CRYPTO) += rt2x00crypto.o rt2x00lib-$(CONFIG_RT2X00_LIB_RFKILL) += rt2x00rfkill.o diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 39ecf3b82ca..19c068727a8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -212,7 +212,7 @@ struct link_qual { * (WEIGHT_TX * tx_percentage) + * (WEIGHT_RX * rx_percentage)) / 100 * - * This value should then be checked to not be greated then 100. + * This value should then be checked to not be greater then 100. */ int rx_percentage; int rx_success; @@ -318,33 +318,6 @@ static inline int rt2x00_get_link_rssi(struct link *link) return DEFAULT_RSSI; } -static inline int rt2x00_get_link_ant_rssi(struct link *link) -{ - if (link->ant.rssi_ant && link->qual.rx_success) - return link->ant.rssi_ant; - return DEFAULT_RSSI; -} - -static inline void rt2x00_reset_link_ant_rssi(struct link *link) -{ - link->ant.rssi_ant = 0; -} - -static inline int rt2x00_get_link_ant_rssi_history(struct link *link, - enum antenna ant) -{ - if (link->ant.rssi_history[ant - ANTENNA_A]) - return link->ant.rssi_history[ant - ANTENNA_A]; - return DEFAULT_RSSI; -} - -static inline int rt2x00_update_ant_rssi(struct link *link, int rssi) -{ - int old_rssi = link->ant.rssi_history[link->ant.active.rx - ANTENNA_A]; - link->ant.rssi_history[link->ant.active.rx - ANTENNA_A] = rssi; - return old_rssi; -} - /* * Interface structure * Per interface configuration details, this structure diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index e66fb316cd6..2f4cb8de998 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -152,8 +152,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, */ rt2x00dev->ops->lib->config_ant(rt2x00dev, ant); - rt2x00lib_reset_link_tuner(rt2x00dev); - rt2x00_reset_link_ant_rssi(&rt2x00dev->link); + rt2x00link_reset_tuner(rt2x00dev, true); memcpy(active, ant, sizeof(*ant)); @@ -191,7 +190,7 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, * which means we need to reset the link tuner. */ if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) - rt2x00lib_reset_link_tuner(rt2x00dev); + rt2x00link_reset_tuner(rt2x00dev, false); rt2x00dev->curr_band = conf->channel->band; rt2x00dev->tx_power = conf->power_level; diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index 54dd10060bf..cc194060534 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -130,9 +130,11 @@ struct rt2x00debug_intf { }; void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev, - enum cipher cipher, enum rx_crypto status) + struct rxdone_entry_desc *rxdesc) { struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf; + enum cipher cipher = rxdesc->cipher; + enum rx_crypto status = rxdesc->cipher_status; if (cipher == CIPHER_TKIP_NO_MIC) cipher = CIPHER_TKIP; diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 87c0f2c8307..81d7fc8635d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -29,60 +29,6 @@ #include "rt2x00.h" #include "rt2x00lib.h" -/* - * Link tuning handlers - */ -void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev) -{ - if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - return; - - /* - * Reset link information. - * Both the currently active vgc level as well as - * the link tuner counter should be reset. Resetting - * the counter is important for devices where the - * device should only perform link tuning during the - * first minute after being enabled. - */ - rt2x00dev->link.count = 0; - rt2x00dev->link.vgc_level = 0; - - /* - * Reset the link tuner. - */ - rt2x00dev->ops->lib->reset_tuner(rt2x00dev); -} - -static void rt2x00lib_start_link_tuner(struct rt2x00_dev *rt2x00dev) -{ - /* - * Clear all (possibly) pre-existing quality statistics. - */ - memset(&rt2x00dev->link.qual, 0, sizeof(rt2x00dev->link.qual)); - - /* - * The RX and TX percentage should start at 50% - * this will assure we will get at least get some - * decent value when the link tuner starts. - * The value will be dropped and overwritten with - * the correct (measured )value anyway during the - * first run of the link tuner. - */ - rt2x00dev->link.qual.rx_percentage = 50; - rt2x00dev->link.qual.tx_percentage = 50; - - rt2x00lib_reset_link_tuner(rt2x00dev); - - queue_delayed_work(rt2x00dev->hw->workqueue, - &rt2x00dev->link.work, LINK_TUNE_INTERVAL); -} - -static void rt2x00lib_stop_link_tuner(struct rt2x00_dev *rt2x00dev) -{ - cancel_delayed_work_sync(&rt2x00dev->link.work); -} - /* * Radio control handlers. */ @@ -161,238 +107,15 @@ void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state) * When we are disabling the RX, we should also stop the link tuner. */ if (state == STATE_RADIO_RX_OFF) - rt2x00lib_stop_link_tuner(rt2x00dev); + rt2x00link_stop_tuner(rt2x00dev); rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); /* * When we are enabling the RX, we should also start the link tuner. */ - if (state == STATE_RADIO_RX_ON && - (rt2x00dev->intf_ap_count || rt2x00dev->intf_sta_count)) - rt2x00lib_start_link_tuner(rt2x00dev); -} - -static void rt2x00lib_evaluate_antenna_sample(struct rt2x00_dev *rt2x00dev) -{ - struct antenna_setup ant; - int sample_a = - rt2x00_get_link_ant_rssi_history(&rt2x00dev->link, ANTENNA_A); - int sample_b = - rt2x00_get_link_ant_rssi_history(&rt2x00dev->link, ANTENNA_B); - - memcpy(&ant, &rt2x00dev->link.ant.active, sizeof(ant)); - - /* - * We are done sampling. Now we should evaluate the results. - */ - rt2x00dev->link.ant.flags &= ~ANTENNA_MODE_SAMPLE; - - /* - * During the last period we have sampled the RSSI - * from both antenna's. It now is time to determine - * which antenna demonstrated the best performance. - * When we are already on the antenna with the best - * performance, then there really is nothing for us - * left to do. - */ - if (sample_a == sample_b) - return; - - if (rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) - ant.rx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B; - - if (rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY) - ant.tx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B; - - rt2x00lib_config_antenna(rt2x00dev, &ant); -} - -static void rt2x00lib_evaluate_antenna_eval(struct rt2x00_dev *rt2x00dev) -{ - struct antenna_setup ant; - int rssi_curr = rt2x00_get_link_ant_rssi(&rt2x00dev->link); - int rssi_old = rt2x00_update_ant_rssi(&rt2x00dev->link, rssi_curr); - - memcpy(&ant, &rt2x00dev->link.ant.active, sizeof(ant)); - - /* - * Legacy driver indicates that we should swap antenna's - * when the difference in RSSI is greater that 5. This - * also should be done when the RSSI was actually better - * then the previous sample. - * When the difference exceeds the threshold we should - * sample the rssi from the other antenna to make a valid - * comparison between the 2 antennas. - */ - if (abs(rssi_curr - rssi_old) < 5) - return; - - rt2x00dev->link.ant.flags |= ANTENNA_MODE_SAMPLE; - - if (rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) - ant.rx = (ant.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A; - - if (rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY) - ant.tx = (ant.tx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A; - - rt2x00lib_config_antenna(rt2x00dev, &ant); -} - -static void rt2x00lib_evaluate_antenna(struct rt2x00_dev *rt2x00dev) -{ - /* - * Determine if software diversity is enabled for - * either the TX or RX antenna (or both). - * Always perform this check since within the link - * tuner interval the configuration might have changed. - */ - rt2x00dev->link.ant.flags &= ~ANTENNA_RX_DIVERSITY; - rt2x00dev->link.ant.flags &= ~ANTENNA_TX_DIVERSITY; - - if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY) - rt2x00dev->link.ant.flags |= ANTENNA_RX_DIVERSITY; - if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY) - rt2x00dev->link.ant.flags |= ANTENNA_TX_DIVERSITY; - - if (!(rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) && - !(rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY)) { - rt2x00dev->link.ant.flags = 0; - return; - } - - /* - * If we have only sampled the data over the last period - * we should now harvest the data. Otherwise just evaluate - * the data. The latter should only be performed once - * every 2 seconds. - */ - if (rt2x00dev->link.ant.flags & ANTENNA_MODE_SAMPLE) - rt2x00lib_evaluate_antenna_sample(rt2x00dev); - else if (rt2x00dev->link.count & 1) - rt2x00lib_evaluate_antenna_eval(rt2x00dev); -} - -static void rt2x00lib_update_link_stats(struct link *link, int rssi) -{ - int avg_rssi = rssi; - - /* - * Update global RSSI - */ - if (link->qual.avg_rssi) - avg_rssi = MOVING_AVERAGE(link->qual.avg_rssi, rssi, 8); - link->qual.avg_rssi = avg_rssi; - - /* - * Update antenna RSSI - */ - if (link->ant.rssi_ant) - rssi = MOVING_AVERAGE(link->ant.rssi_ant, rssi, 8); - link->ant.rssi_ant = rssi; -} - -static void rt2x00lib_precalculate_link_signal(struct link_qual *qual) -{ - if (qual->rx_failed || qual->rx_success) - qual->rx_percentage = - (qual->rx_success * 100) / - (qual->rx_failed + qual->rx_success); - else - qual->rx_percentage = 50; - - if (qual->tx_failed || qual->tx_success) - qual->tx_percentage = - (qual->tx_success * 100) / - (qual->tx_failed + qual->tx_success); - else - qual->tx_percentage = 50; - - qual->rx_success = 0; - qual->rx_failed = 0; - qual->tx_success = 0; - qual->tx_failed = 0; -} - -static int rt2x00lib_calculate_link_signal(struct rt2x00_dev *rt2x00dev, - int rssi) -{ - int rssi_percentage = 0; - int signal; - - /* - * We need a positive value for the RSSI. - */ - if (rssi < 0) - rssi += rt2x00dev->rssi_offset; - - /* - * Calculate the different percentages, - * which will be used for the signal. - */ - if (rt2x00dev->rssi_offset) - rssi_percentage = (rssi * 100) / rt2x00dev->rssi_offset; - - /* - * Add the individual percentages and use the WEIGHT - * defines to calculate the current link signal. - */ - signal = ((WEIGHT_RSSI * rssi_percentage) + - (WEIGHT_TX * rt2x00dev->link.qual.tx_percentage) + - (WEIGHT_RX * rt2x00dev->link.qual.rx_percentage)) / 100; - - return (signal > 100) ? 100 : signal; -} - -static void rt2x00lib_link_tuner(struct work_struct *work) -{ - struct rt2x00_dev *rt2x00dev = - container_of(work, struct rt2x00_dev, link.work.work); - - /* - * When the radio is shutting down we should - * immediately cease all link tuning. - */ - if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - return; - - /* - * Update statistics. - */ - rt2x00dev->ops->lib->link_stats(rt2x00dev, &rt2x00dev->link.qual); - rt2x00dev->low_level_stats.dot11FCSErrorCount += - rt2x00dev->link.qual.rx_failed; - - /* - * Only perform the link tuning when Link tuning - * has been enabled (This could have been disabled from the EEPROM). - */ - if (!test_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags)) - rt2x00dev->ops->lib->link_tuner(rt2x00dev); - - /* - * Precalculate a portion of the link signal which is - * in based on the tx/rx success/failure counters. - */ - rt2x00lib_precalculate_link_signal(&rt2x00dev->link.qual); - - /* - * Send a signal to the led to update the led signal strength. - */ - rt2x00leds_led_quality(rt2x00dev, rt2x00dev->link.qual.avg_rssi); - - /* - * Evaluate antenna setup, make this the last step since this could - * possibly reset some statistics. - */ - rt2x00lib_evaluate_antenna(rt2x00dev); - - /* - * Increase tuner counter, and reschedule the next link tuner run. - */ - rt2x00dev->link.count++; - queue_delayed_work(rt2x00dev->hw->workqueue, - &rt2x00dev->link.work, LINK_TUNE_INTERVAL); + if (state == STATE_RADIO_RX_ON) + rt2x00link_start_tuner(rt2x00dev); } static void rt2x00lib_packetfilter_scheduled(struct work_struct *work) @@ -597,7 +320,6 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb; struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; struct ieee80211_supported_band *sband; - struct ieee80211_hdr *hdr; const struct rt2x00_rate *rate; unsigned int header_length; unsigned int align; @@ -674,23 +396,14 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, } /* - * Only update link status if this is a beacon frame carrying our bssid. + * Update extra components */ - hdr = (struct ieee80211_hdr *)entry->skb->data; - if (ieee80211_is_beacon(hdr->frame_control) && - (rxdesc.dev_flags & RXDONE_MY_BSS)) - rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc.rssi); - - rt2x00debug_update_crypto(rt2x00dev, - rxdesc.cipher, - rxdesc.cipher_status); - - rt2x00dev->link.qual.rx_success++; + rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc); + rt2x00debug_update_crypto(rt2x00dev, &rxdesc); rx_status->mactime = rxdesc.timestamp; rx_status->rate_idx = idx; - rx_status->qual = - rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc.rssi); + rx_status->qual = rt2x00link_calculate_signal(rt2x00dev, rxdesc.rssi); rx_status->signal = rxdesc.rssi; rx_status->flag = rxdesc.flags; rx_status->antenna = rt2x00dev->link.ant.active.rx; @@ -1083,7 +796,6 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) */ INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled); - INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner); /* * Allocate queue array. @@ -1104,6 +816,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) /* * Register extra components. */ + rt2x00link_register(rt2x00dev); rt2x00leds_register(rt2x00dev); rt2x00rfkill_allocate(rt2x00dev); rt2x00debug_register(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 86cd26fbf76..fccaffde6f5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -63,7 +63,6 @@ static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value) int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev); void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev); void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state); -void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev); /* * Initialization handlers. @@ -154,6 +153,81 @@ void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev); int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev); void rt2x00queue_free(struct rt2x00_dev *rt2x00dev); +/** + * rt2x00link_update_stats - Update link statistics from RX frame + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * @skb: Received frame + * @rxdesc: Received frame descriptor + * + * Update link statistics based on the information from the + * received frame descriptor. + */ +void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev, + struct sk_buff *skb, + struct rxdone_entry_desc *rxdesc); + +/** + * rt2x00link_calculate_signal - Calculate signal quality + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * @rssi: RX Frame RSSI + * + * Calculate the signal quality of a frame based on the rssi + * measured during the receiving of the frame and the global + * link quality statistics measured since the start of the + * link tuning. The result is a value between 0 and 100 which + * is an indication of the signal quality. + */ +int rt2x00link_calculate_signal(struct rt2x00_dev *rt2x00dev, int rssi); + +/** + * rt2x00link_start_tuner - Start periodic link tuner work + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * + * This start the link tuner periodic work, this work will + * be executed periodically until &rt2x00link_stop_tuner has + * been called. + */ +void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev); + +/** + * rt2x00link_stop_tuner - Stop periodic link tuner work + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * + * After this function completed the link tuner will not + * be running until &rt2x00link_start_tuner is called. + */ +void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev); + +/** + * rt2x00link_reset_tuner - Reset periodic link tuner work + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * @antenna: Should the antenna tuning also be reset + * + * The VGC limit configured in the hardware will be reset to 0 + * which forces the driver to rediscover the correct value for + * the current association. This is needed when configuration + * options have changed which could drastically change the + * SNR level or link quality (i.e. changing the antenna setting). + * + * Resetting the link tuner will also cause the periodic work counter + * to be reset. Any driver which has a fixed limit on the number + * of rounds the link tuner is supposed to work will accept the + * tuner actions again if this limit was previously reached. + * + * If @antenna is set to true a the software antenna diversity + * tuning will also be reset. + */ +void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna); + +/** + * rt2x00link_register - Initialize link tuning functionality + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * + * Initialize work structure and all link tuning related + * paramters. This will not start the link tuning process itself. + */ +void rt2x00link_register(struct rt2x00_dev *rt2x00dev); + /* * Firmware handlers. */ @@ -179,7 +253,7 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev); void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, enum rt2x00_dump_type type, struct sk_buff *skb); void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev, - enum cipher cipher, enum rx_crypto status); + struct rxdone_entry_desc *rxdesc); #else static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) { @@ -196,8 +270,7 @@ static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, } static inline void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev, - enum cipher cipher, - enum rx_crypto status) + struct rxdone_entry_desc *rxdesc) { } #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c new file mode 100644 index 00000000000..0462d5ab6e9 --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2x00link.c @@ -0,0 +1,402 @@ +/* + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the + Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + Module: rt2x00lib + Abstract: rt2x00 generic link tuning routines. + */ + +#include +#include + +#include "rt2x00.h" +#include "rt2x00lib.h" + +static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev) +{ + struct link_ant *ant = &rt2x00dev->link.ant; + + if (ant->rssi_ant && rt2x00dev->link.qual.rx_success) + return ant->rssi_ant; + return DEFAULT_RSSI; +} + +static int rt2x00link_antenna_get_rssi_history(struct rt2x00_dev *rt2x00dev, + enum antenna antenna) +{ + struct link_ant *ant = &rt2x00dev->link.ant; + + if (ant->rssi_history[antenna - ANTENNA_A]) + return ant->rssi_history[antenna - ANTENNA_A]; + return DEFAULT_RSSI; +} +/* Small wrapper for rt2x00link_antenna_get_rssi_history() */ +#define rt2x00link_antenna_get_rssi_rx_history(__dev) \ + rt2x00link_antenna_get_rssi_history((__dev), \ + (__dev)->link.ant.active.rx) +#define rt2x00link_antenna_get_rssi_tx_history(__dev) \ + rt2x00link_antenna_get_rssi_history((__dev), \ + (__dev)->link.ant.active.tx) + +static void rt2x00link_antenna_update_rssi_history(struct rt2x00_dev *rt2x00dev, + enum antenna antenna, + int rssi) +{ + struct link_ant *ant = &rt2x00dev->link.ant; + ant->rssi_history[ant->active.rx - ANTENNA_A] = rssi; +} +/* Small wrapper for rt2x00link_antenna_get_rssi_history() */ +#define rt2x00link_antenna_update_rssi_rx_history(__dev, __rssi) \ + rt2x00link_antenna_update_rssi_history((__dev), \ + (__dev)->link.ant.active.rx, \ + (__rssi)) +#define rt2x00link_antenna_update_rssi_tx_history(__dev, __rssi) \ + rt2x00link_antenna_update_rssi_history((__dev), \ + (__dev)->link.ant.active.tx, \ + (__rssi)) + +static void rt2x00link_antenna_reset(struct rt2x00_dev *rt2x00dev) +{ + rt2x00dev->link.ant.rssi_ant = 0; +} + +static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev) +{ + struct link_ant *ant = &rt2x00dev->link.ant; + struct antenna_setup new_ant; + int sample_a = rt2x00link_antenna_get_rssi_history(rt2x00dev, ANTENNA_A); + int sample_b = rt2x00link_antenna_get_rssi_history(rt2x00dev, ANTENNA_B); + + memcpy(&new_ant, &ant->active, sizeof(new_ant)); + + /* + * We are done sampling. Now we should evaluate the results. + */ + ant->flags &= ~ANTENNA_MODE_SAMPLE; + + /* + * During the last period we have sampled the RSSI + * from both antenna's. It now is time to determine + * which antenna demonstrated the best performance. + * When we are already on the antenna with the best + * performance, then there really is nothing for us + * left to do. + */ + if (sample_a == sample_b) + return; + + if (ant->flags & ANTENNA_RX_DIVERSITY) + new_ant.rx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B; + + if (ant->flags & ANTENNA_TX_DIVERSITY) + new_ant.tx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B; + + rt2x00lib_config_antenna(rt2x00dev, &new_ant); +} + +static void rt2x00lib_antenna_diversity_eval(struct rt2x00_dev *rt2x00dev) +{ + struct link_ant *ant = &rt2x00dev->link.ant; + struct antenna_setup new_ant; + int rssi_curr; + int rssi_old; + + memcpy(&new_ant, &ant->active, sizeof(new_ant)); + + /* + * Get current RSSI value along with the historical value, + * after that update the history with the current value. + */ + rssi_curr = rt2x00link_antenna_get_link_rssi(rt2x00dev); + rssi_old = rt2x00link_antenna_get_rssi_rx_history(rt2x00dev); + rt2x00link_antenna_update_rssi_rx_history(rt2x00dev, rssi_curr); + + /* + * Legacy driver indicates that we should swap antenna's + * when the difference in RSSI is greater that 5. This + * also should be done when the RSSI was actually better + * then the previous sample. + * When the difference exceeds the threshold we should + * sample the rssi from the other antenna to make a valid + * comparison between the 2 antennas. + */ + if (abs(rssi_curr - rssi_old) < 5) + return; + + ant->flags |= ANTENNA_MODE_SAMPLE; + + if (ant->flags & ANTENNA_RX_DIVERSITY) + new_ant.rx = (new_ant.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A; + + if (ant->flags & ANTENNA_TX_DIVERSITY) + new_ant.tx = (new_ant.tx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A; + + rt2x00lib_config_antenna(rt2x00dev, &new_ant); +} + +static void rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev) +{ + struct link_ant *ant = &rt2x00dev->link.ant; + + /* + * Determine if software diversity is enabled for + * either the TX or RX antenna (or both). + * Always perform this check since within the link + * tuner interval the configuration might have changed. + */ + ant->flags &= ~ANTENNA_RX_DIVERSITY; + ant->flags &= ~ANTENNA_TX_DIVERSITY; + + if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY) + ant->flags |= ANTENNA_RX_DIVERSITY; + if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY) + ant->flags |= ANTENNA_TX_DIVERSITY; + + if (!(ant->flags & ANTENNA_RX_DIVERSITY) && + !(ant->flags & ANTENNA_TX_DIVERSITY)) { + ant->flags = 0; + return; + } + + /* + * If we have only sampled the data over the last period + * we should now harvest the data. Otherwise just evaluate + * the data. The latter should only be performed once + * every 2 seconds. + */ + if (ant->flags & ANTENNA_MODE_SAMPLE) + rt2x00lib_antenna_diversity_sample(rt2x00dev); + else if (rt2x00dev->link.count & 1) + rt2x00lib_antenna_diversity_eval(rt2x00dev); +} + +void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev, + struct sk_buff *skb, + struct rxdone_entry_desc *rxdesc) +{ + struct link_qual *qual = &rt2x00dev->link.qual; + struct link_ant *ant = &rt2x00dev->link.ant; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + int avg_rssi = rxdesc->rssi; + int ant_rssi = rxdesc->rssi; + + /* + * Frame was received successfully since non-succesfull + * frames would have been dropped by the hardware. + */ + qual->rx_success++; + + /* + * We are only interested in quality statistics from + * beacons which came from the BSS which we are + * associated with. + */ + if (!ieee80211_is_beacon(hdr->frame_control) || + !(rxdesc->dev_flags & RXDONE_MY_BSS)) + return; + + /* + * Update global RSSI + */ + if (qual->avg_rssi) + avg_rssi = MOVING_AVERAGE(qual->avg_rssi, rxdesc->rssi, 8); + qual->avg_rssi = avg_rssi; + + /* + * Update antenna RSSI + */ + if (ant->rssi_ant) + ant_rssi = MOVING_AVERAGE(ant->rssi_ant, rxdesc->rssi, 8); + ant->rssi_ant = ant_rssi; +} + +static void rt2x00link_precalculate_signal(struct rt2x00_dev *rt2x00dev) +{ + struct link_qual *qual = &rt2x00dev->link.qual; + + if (qual->rx_failed || qual->rx_success) + qual->rx_percentage = + (qual->rx_success * 100) / + (qual->rx_failed + qual->rx_success); + else + qual->rx_percentage = 50; + + if (qual->tx_failed || qual->tx_success) + qual->tx_percentage = + (qual->tx_success * 100) / + (qual->tx_failed + qual->tx_success); + else + qual->tx_percentage = 50; + + qual->rx_success = 0; + qual->rx_failed = 0; + qual->tx_success = 0; + qual->tx_failed = 0; +} + +int rt2x00link_calculate_signal(struct rt2x00_dev *rt2x00dev, int rssi) +{ + struct link_qual *qual = &rt2x00dev->link.qual; + int rssi_percentage = 0; + int signal; + + /* + * We need a positive value for the RSSI. + */ + if (rssi < 0) + rssi += rt2x00dev->rssi_offset; + + /* + * Calculate the different percentages, + * which will be used for the signal. + */ + rssi_percentage = (rssi * 100) / rt2x00dev->rssi_offset; + + /* + * Add the individual percentages and use the WEIGHT + * defines to calculate the current link signal. + */ + signal = ((WEIGHT_RSSI * rssi_percentage) + + (WEIGHT_TX * qual->tx_percentage) + + (WEIGHT_RX * qual->rx_percentage)) / 100; + + return max_t(int, signal, 100); +} + +void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev) +{ + struct link_qual *qual = &rt2x00dev->link.qual; + + /* + * Link tuning should only be performed when + * an active sta or master interface exists. + * Single monitor mode interfaces should never have + * work with link tuners. + */ + if (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count) + return; + + /* + * Clear all (possibly) pre-existing quality statistics. + */ + memset(qual, 0, sizeof(*qual)); + + /* + * The RX and TX percentage should start at 50% + * this will assure we will get at least get some + * decent value when the link tuner starts. + * The value will be dropped and overwritten with + * the correct (measured) value anyway during the + * first run of the link tuner. + */ + qual->rx_percentage = 50; + qual->tx_percentage = 50; + + rt2x00link_reset_tuner(rt2x00dev, false); + + queue_delayed_work(rt2x00dev->hw->workqueue, + &rt2x00dev->link.work, LINK_TUNE_INTERVAL); +} + +void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev) +{ + cancel_delayed_work_sync(&rt2x00dev->link.work); +} + +void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna) +{ + if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) + return; + + /* + * Reset link information. + * Both the currently active vgc level as well as + * the link tuner counter should be reset. Resetting + * the counter is important for devices where the + * device should only perform link tuning during the + * first minute after being enabled. + */ + rt2x00dev->link.count = 0; + rt2x00dev->link.vgc_level = 0; + + /* + * Reset the link tuner. + */ + rt2x00dev->ops->lib->reset_tuner(rt2x00dev); + + if (antenna) + rt2x00link_antenna_reset(rt2x00dev); +} + +static void rt2x00link_tuner(struct work_struct *work) +{ + struct rt2x00_dev *rt2x00dev = + container_of(work, struct rt2x00_dev, link.work.work); + struct link_qual *qual = &rt2x00dev->link.qual; + + /* + * When the radio is shutting down we should + * immediately cease all link tuning. + */ + if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) + return; + + /* + * Update statistics. + */ + rt2x00dev->ops->lib->link_stats(rt2x00dev, qual); + rt2x00dev->low_level_stats.dot11FCSErrorCount += qual->rx_failed; + + /* + * Only perform the link tuning when Link tuning + * has been enabled (This could have been disabled from the EEPROM). + */ + if (!test_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags)) + rt2x00dev->ops->lib->link_tuner(rt2x00dev); + + /* + * Precalculate a portion of the link signal which is + * in based on the tx/rx success/failure counters. + */ + rt2x00link_precalculate_signal(rt2x00dev); + + /* + * Send a signal to the led to update the led signal strength. + */ + rt2x00leds_led_quality(rt2x00dev, qual->avg_rssi); + + /* + * Evaluate antenna setup, make this the last step since this could + * possibly reset some statistics. + */ + rt2x00lib_antenna_diversity(rt2x00dev); + + /* + * Increase tuner counter, and reschedule the next link tuner run. + */ + rt2x00dev->link.count++; + queue_delayed_work(rt2x00dev->hw->workqueue, + &rt2x00dev->link.work, LINK_TUNE_INTERVAL); +} + +void rt2x00link_register(struct rt2x00_dev *rt2x00dev) +{ + INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner); +} -- GitLab From eb20b4e8a6998ca68d9ac0963ee36a1a36fe241d Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 20 Dec 2008 10:54:22 +0100 Subject: [PATCH 0671/4982] rt2x00: Reduce calls to bbp_read() The link_tuner() function will always call bbp_read() at the start of the function. Because this is an indirect register access has some costs attached to it (especially for USB hardware). We already store the value read from the register into the vgc_level value inside the link structure. Instead of reading from the register we can read that field directly and base the tuner on that value. This reduces the time the registers are locked with the csr_mutex and speeds up the link_tuner processing. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 27 ++++++------- drivers/net/wireless/rt2x00/rt2500pci.c | 50 ++++++++++++------------ drivers/net/wireless/rt2x00/rt2x00.h | 9 ++++- drivers/net/wireless/rt2x00/rt61pci.c | 49 +++++++++++------------ drivers/net/wireless/rt2x00/rt73usb.c | 52 ++++++++++++------------- 5 files changed, 92 insertions(+), 95 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 1afba42cc12..e87ad43e8e8 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -600,35 +600,36 @@ static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev, qual->false_cca = bbp; } +static inline void rt2400pci_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level) +{ + rt2400pci_bbp_write(rt2x00dev, 13, vgc_level); + rt2x00dev->link.vgc_level = vgc_level; + rt2x00dev->link.vgc_level_reg = vgc_level; +} + static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev) { - rt2400pci_bbp_write(rt2x00dev, 13, 0x08); - rt2x00dev->link.vgc_level = 0x08; + rt2400pci_set_vgc(rt2x00dev, 0x08); } static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev) { - u8 reg; + struct link *link = &rt2x00dev->link; /* * The link tuner should not run longer then 60 seconds, * and should run once every 2 seconds. */ - if (rt2x00dev->link.count > 60 || !(rt2x00dev->link.count & 1)) + if (link->count > 60 || !(link->count & 1)) return; /* * Base r13 link tuning on the false cca count. */ - rt2400pci_bbp_read(rt2x00dev, 13, ®); - - if (rt2x00dev->link.qual.false_cca > 512 && reg < 0x20) { - rt2400pci_bbp_write(rt2x00dev, 13, ++reg); - rt2x00dev->link.vgc_level = reg; - } else if (rt2x00dev->link.qual.false_cca < 100 && reg > 0x08) { - rt2400pci_bbp_write(rt2x00dev, 13, --reg); - rt2x00dev->link.vgc_level = reg; - } + if ((link->qual.false_cca > 512) && (link->vgc_level < 0x20)) + rt2400pci_set_vgc(rt2x00dev, ++link->vgc_level); + else if ((link->qual.false_cca < 100) && (link->vgc_level > 0x08)) + rt2400pci_set_vgc(rt2x00dev, --link->vgc_level); } /* diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index bf5e81162f2..5b98a74a255 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -639,16 +639,23 @@ static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev, qual->false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA); } +static inline void rt2500pci_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level) +{ + if (rt2x00dev->link.vgc_level_reg != vgc_level) { + rt2500pci_bbp_write(rt2x00dev, 17, vgc_level); + rt2x00dev->link.vgc_level_reg = vgc_level; + } +} + static void rt2500pci_reset_tuner(struct rt2x00_dev *rt2x00dev) { - rt2500pci_bbp_write(rt2x00dev, 17, 0x48); - rt2x00dev->link.vgc_level = 0x48; + rt2500pci_set_vgc(rt2x00dev, 0x48); } static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) { - int rssi = rt2x00_get_link_rssi(&rt2x00dev->link); - u8 r17; + struct link *link = &rt2x00dev->link; + int rssi = rt2x00_get_link_rssi(link); /* * To prevent collisions with MAC ASIC on chipsets @@ -656,12 +663,9 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) * seconds while being associated. */ if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D && - rt2x00dev->intf_associated && - rt2x00dev->link.count > 20) + rt2x00dev->intf_associated && link->count > 20) return; - rt2500pci_bbp_read(rt2x00dev, 17, &r17); - /* * Chipset versions C and lower should directly continue * to the dynamic CCA tuning. Chipset version D and higher @@ -677,11 +681,9 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) * then corrupt the R17 tuning. To remidy this the tuning should * be stopped (While making sure the R17 value will not exceed limits) */ - if (rssi < -80 && rt2x00dev->link.count > 20) { - if (r17 >= 0x41) { - r17 = rt2x00dev->link.vgc_level; - rt2500pci_bbp_write(rt2x00dev, 17, r17); - } + if (rssi < -80 && link->count > 20) { + if (link->vgc_level_reg >= 0x41) + rt2500pci_set_vgc(rt2x00dev, link->vgc_level); return; } @@ -689,8 +691,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) * Special big-R17 for short distance */ if (rssi >= -58) { - if (r17 != 0x50) - rt2500pci_bbp_write(rt2x00dev, 17, 0x50); + rt2500pci_set_vgc(rt2x00dev, 0x50); return; } @@ -698,8 +699,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) * Special mid-R17 for middle distance */ if (rssi >= -74) { - if (r17 != 0x41) - rt2500pci_bbp_write(rt2x00dev, 17, 0x41); + rt2500pci_set_vgc(rt2x00dev, 0x41); return; } @@ -707,8 +707,8 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) * Leave short or middle distance condition, restore r17 * to the dynamic tuning range. */ - if (r17 >= 0x41) { - rt2500pci_bbp_write(rt2x00dev, 17, rt2x00dev->link.vgc_level); + if (link->vgc_level_reg >= 0x41) { + rt2500pci_set_vgc(rt2x00dev, link->vgc_level); return; } @@ -718,12 +718,12 @@ dynamic_cca_tune: * R17 is inside the dynamic tuning range, * start tuning the link based on the false cca counter. */ - if (rt2x00dev->link.qual.false_cca > 512 && r17 < 0x40) { - rt2500pci_bbp_write(rt2x00dev, 17, ++r17); - rt2x00dev->link.vgc_level = r17; - } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > 0x32) { - rt2500pci_bbp_write(rt2x00dev, 17, --r17); - rt2x00dev->link.vgc_level = r17; + if (link->qual.false_cca > 512 && link->vgc_level_reg < 0x40) { + rt2500pci_set_vgc(rt2x00dev, ++link->vgc_level_reg); + link->vgc_level = link->vgc_level_reg; + } else if (link->qual.false_cca < 100 && link->vgc_level_reg > 0x32) { + rt2500pci_set_vgc(rt2x00dev, --link->vgc_level_reg); + link->vgc_level = link->vgc_level_reg; } } diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 19c068727a8..8935f2c005c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -286,9 +286,14 @@ struct link { struct link_ant ant; /* - * Active VGC level + * Active VGC level (for false cca tuning) */ - int vgc_level; + u8 vgc_level; + + /* + * VGC level as configured in register + */ + u8 vgc_level_reg; /* * Work structure for scheduling periodic link tuning. diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index c7ab744f005..94523f7f0d8 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1046,21 +1046,27 @@ static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev, qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR); } +static inline void rt61pci_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level) +{ + if (rt2x00dev->link.vgc_level != vgc_level) { + rt61pci_bbp_write(rt2x00dev, 17, vgc_level); + rt2x00dev->link.vgc_level = vgc_level; + rt2x00dev->link.vgc_level_reg = vgc_level; + } +} + static void rt61pci_reset_tuner(struct rt2x00_dev *rt2x00dev) { - rt61pci_bbp_write(rt2x00dev, 17, 0x20); - rt2x00dev->link.vgc_level = 0x20; + rt61pci_set_vgc(rt2x00dev, 0x20); } static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) { - int rssi = rt2x00_get_link_rssi(&rt2x00dev->link); - u8 r17; + struct link *link = &rt2x00dev->link; + int rssi = rt2x00_get_link_rssi(link); u8 up_bound; u8 low_bound; - rt61pci_bbp_read(rt2x00dev, 17, &r17); - /* * Determine r17 bounds. */ @@ -1091,8 +1097,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) * Special big-R17 for very short distance */ if (rssi >= -35) { - if (r17 != 0x60) - rt61pci_bbp_write(rt2x00dev, 17, 0x60); + rt61pci_set_vgc(rt2x00dev, 0x60); return; } @@ -1100,8 +1105,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) * Special big-R17 for short distance */ if (rssi >= -58) { - if (r17 != up_bound) - rt61pci_bbp_write(rt2x00dev, 17, up_bound); + rt61pci_set_vgc(rt2x00dev, up_bound); return; } @@ -1109,9 +1113,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) * Special big-R17 for middle-short distance */ if (rssi >= -66) { - low_bound += 0x10; - if (r17 != low_bound) - rt61pci_bbp_write(rt2x00dev, 17, low_bound); + rt61pci_set_vgc(rt2x00dev, low_bound + 0x10); return; } @@ -1119,9 +1121,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) * Special mid-R17 for middle distance */ if (rssi >= -74) { - low_bound += 0x08; - if (r17 != low_bound) - rt61pci_bbp_write(rt2x00dev, 17, low_bound); + rt61pci_set_vgc(rt2x00dev, low_bound + 0x08); return; } @@ -1133,8 +1133,8 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) if (low_bound > up_bound) up_bound = low_bound; - if (r17 > up_bound) { - rt61pci_bbp_write(rt2x00dev, 17, up_bound); + if (link->vgc_level > up_bound) { + rt61pci_set_vgc(rt2x00dev, up_bound); return; } @@ -1144,15 +1144,10 @@ dynamic_cca_tune: * r17 does not yet exceed upper limit, continue and base * the r17 tuning on the false CCA count. */ - if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) { - if (++r17 > up_bound) - r17 = up_bound; - rt61pci_bbp_write(rt2x00dev, 17, r17); - } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) { - if (--r17 < low_bound) - r17 = low_bound; - rt61pci_bbp_write(rt2x00dev, 17, r17); - } + if ((link->qual.false_cca > 512) && (link->vgc_level < up_bound)) + rt61pci_set_vgc(rt2x00dev, ++link->vgc_level); + else if ((link->qual.false_cca < 100) && (link->vgc_level > low_bound)) + rt61pci_set_vgc(rt2x00dev, --link->vgc_level); } /* diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ae3b31d0d51..b5443148d62 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -924,21 +924,27 @@ static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev, qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR); } +static inline void rt73usb_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level) +{ + if (rt2x00dev->link.vgc_level != vgc_level) { + rt73usb_bbp_write(rt2x00dev, 17, vgc_level); + rt2x00dev->link.vgc_level = vgc_level; + rt2x00dev->link.vgc_level_reg = vgc_level; + } +} + static void rt73usb_reset_tuner(struct rt2x00_dev *rt2x00dev) { - rt73usb_bbp_write(rt2x00dev, 17, 0x20); - rt2x00dev->link.vgc_level = 0x20; + rt73usb_set_vgc(rt2x00dev, 0x20); } static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) { - int rssi = rt2x00_get_link_rssi(&rt2x00dev->link); - u8 r17; + struct link *link = &rt2x00dev->link; + int rssi = rt2x00_get_link_rssi(link); u8 up_bound; u8 low_bound; - rt73usb_bbp_read(rt2x00dev, 17, &r17); - /* * Determine r17 bounds. */ @@ -979,8 +985,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) * Special big-R17 for very short distance */ if (rssi > -35) { - if (r17 != 0x60) - rt73usb_bbp_write(rt2x00dev, 17, 0x60); + rt73usb_set_vgc(rt2x00dev, 0x60); return; } @@ -988,8 +993,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) * Special big-R17 for short distance */ if (rssi >= -58) { - if (r17 != up_bound) - rt73usb_bbp_write(rt2x00dev, 17, up_bound); + rt73usb_set_vgc(rt2x00dev, up_bound); return; } @@ -997,9 +1001,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) * Special big-R17 for middle-short distance */ if (rssi >= -66) { - low_bound += 0x10; - if (r17 != low_bound) - rt73usb_bbp_write(rt2x00dev, 17, low_bound); + rt73usb_set_vgc(rt2x00dev, low_bound + 0x10); return; } @@ -1007,8 +1009,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) * Special mid-R17 for middle distance */ if (rssi >= -74) { - if (r17 != (low_bound + 0x10)) - rt73usb_bbp_write(rt2x00dev, 17, low_bound + 0x08); + rt73usb_set_vgc(rt2x00dev, low_bound + 0x08); return; } @@ -1020,8 +1021,8 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) if (low_bound > up_bound) up_bound = low_bound; - if (r17 > up_bound) { - rt73usb_bbp_write(rt2x00dev, 17, up_bound); + if (link->vgc_level > up_bound) { + rt73usb_set_vgc(rt2x00dev, up_bound); return; } @@ -1031,17 +1032,12 @@ dynamic_cca_tune: * r17 does not yet exceed upper limit, continue and base * the r17 tuning on the false CCA count. */ - if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) { - r17 += 4; - if (r17 > up_bound) - r17 = up_bound; - rt73usb_bbp_write(rt2x00dev, 17, r17); - } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) { - r17 -= 4; - if (r17 < low_bound) - r17 = low_bound; - rt73usb_bbp_write(rt2x00dev, 17, r17); - } + if ((link->qual.false_cca > 512) && (link->vgc_level < up_bound)) + rt73usb_set_vgc(rt2x00dev, + min_t(u8, link->vgc_level + 4, up_bound)); + else if ((link->qual.false_cca < 100) && (link->vgc_level > low_bound)) + rt73usb_set_vgc(rt2x00dev, + max_t(u8, link->vgc_level - 4, low_bound)); } /* -- GitLab From 5352ff6510422d9a9bf13b7272f865eb53247f4d Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 20 Dec 2008 10:54:54 +0100 Subject: [PATCH 0672/4982] rt2x00: Restrict interface between rt2x00link and drivers Restrict drivers to only access link_qual structure during link tuning. The contents of these fields are for the drivers and all fields are allowed to be changed to values the driver considers correct. This means that some fields need to be moved outside of this structure to restrict access only to rt2x00link itself. This allows some code to be moved outside of the rt2x00.h header and into rt2x00link.c. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 27 +++-- drivers/net/wireless/rt2x00/rt2500pci.c | 50 ++++---- drivers/net/wireless/rt2x00/rt2500usb.c | 5 +- drivers/net/wireless/rt2x00/rt2x00.h | 99 ++++++---------- drivers/net/wireless/rt2x00/rt2x00link.c | 145 ++++++++++++++++------- drivers/net/wireless/rt2x00/rt61pci.c | 49 ++++---- drivers/net/wireless/rt2x00/rt73usb.c | 57 ++++----- 7 files changed, 233 insertions(+), 199 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index e87ad43e8e8..9104113270d 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -600,36 +600,37 @@ static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev, qual->false_cca = bbp; } -static inline void rt2400pci_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level) +static inline void rt2400pci_set_vgc(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, u8 vgc_level) { rt2400pci_bbp_write(rt2x00dev, 13, vgc_level); - rt2x00dev->link.vgc_level = vgc_level; - rt2x00dev->link.vgc_level_reg = vgc_level; + qual->vgc_level = vgc_level; + qual->vgc_level_reg = vgc_level; } -static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev) +static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual) { - rt2400pci_set_vgc(rt2x00dev, 0x08); + rt2400pci_set_vgc(rt2x00dev, qual, 0x08); } -static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev) +static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, const u32 count) { - struct link *link = &rt2x00dev->link; - /* * The link tuner should not run longer then 60 seconds, * and should run once every 2 seconds. */ - if (link->count > 60 || !(link->count & 1)) + if (count > 60 || !(count & 1)) return; /* * Base r13 link tuning on the false cca count. */ - if ((link->qual.false_cca > 512) && (link->vgc_level < 0x20)) - rt2400pci_set_vgc(rt2x00dev, ++link->vgc_level); - else if ((link->qual.false_cca < 100) && (link->vgc_level > 0x08)) - rt2400pci_set_vgc(rt2x00dev, --link->vgc_level); + if ((qual->false_cca > 512) && (qual->vgc_level < 0x20)) + rt2400pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level); + else if ((qual->false_cca < 100) && (qual->vgc_level > 0x08)) + rt2400pci_set_vgc(rt2x00dev, qual, --qual->vgc_level); } /* diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 5b98a74a255..fb86e2c5524 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -639,31 +639,31 @@ static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev, qual->false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA); } -static inline void rt2500pci_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level) +static inline void rt2500pci_set_vgc(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, u8 vgc_level) { - if (rt2x00dev->link.vgc_level_reg != vgc_level) { + if (qual->vgc_level_reg != vgc_level) { rt2500pci_bbp_write(rt2x00dev, 17, vgc_level); - rt2x00dev->link.vgc_level_reg = vgc_level; + qual->vgc_level_reg = vgc_level; } } -static void rt2500pci_reset_tuner(struct rt2x00_dev *rt2x00dev) +static void rt2500pci_reset_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual) { - rt2500pci_set_vgc(rt2x00dev, 0x48); + rt2500pci_set_vgc(rt2x00dev, qual, 0x48); } -static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) +static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, const u32 count) { - struct link *link = &rt2x00dev->link; - int rssi = rt2x00_get_link_rssi(link); - /* * To prevent collisions with MAC ASIC on chipsets * up to version C the link tuning should halt after 20 * seconds while being associated. */ if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D && - rt2x00dev->intf_associated && link->count > 20) + rt2x00dev->intf_associated && count > 20) return; /* @@ -681,25 +681,25 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) * then corrupt the R17 tuning. To remidy this the tuning should * be stopped (While making sure the R17 value will not exceed limits) */ - if (rssi < -80 && link->count > 20) { - if (link->vgc_level_reg >= 0x41) - rt2500pci_set_vgc(rt2x00dev, link->vgc_level); + if (qual->rssi < -80 && count > 20) { + if (qual->vgc_level_reg >= 0x41) + rt2500pci_set_vgc(rt2x00dev, qual, qual->vgc_level); return; } /* * Special big-R17 for short distance */ - if (rssi >= -58) { - rt2500pci_set_vgc(rt2x00dev, 0x50); + if (qual->rssi >= -58) { + rt2500pci_set_vgc(rt2x00dev, qual, 0x50); return; } /* * Special mid-R17 for middle distance */ - if (rssi >= -74) { - rt2500pci_set_vgc(rt2x00dev, 0x41); + if (qual->rssi >= -74) { + rt2500pci_set_vgc(rt2x00dev, qual, 0x41); return; } @@ -707,8 +707,8 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) * Leave short or middle distance condition, restore r17 * to the dynamic tuning range. */ - if (link->vgc_level_reg >= 0x41) { - rt2500pci_set_vgc(rt2x00dev, link->vgc_level); + if (qual->vgc_level_reg >= 0x41) { + rt2500pci_set_vgc(rt2x00dev, qual, qual->vgc_level); return; } @@ -718,12 +718,12 @@ dynamic_cca_tune: * R17 is inside the dynamic tuning range, * start tuning the link based on the false cca counter. */ - if (link->qual.false_cca > 512 && link->vgc_level_reg < 0x40) { - rt2500pci_set_vgc(rt2x00dev, ++link->vgc_level_reg); - link->vgc_level = link->vgc_level_reg; - } else if (link->qual.false_cca < 100 && link->vgc_level_reg > 0x32) { - rt2500pci_set_vgc(rt2x00dev, --link->vgc_level_reg); - link->vgc_level = link->vgc_level_reg; + if (qual->false_cca > 512 && qual->vgc_level_reg < 0x40) { + rt2500pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level_reg); + qual->vgc_level = qual->vgc_level_reg; + } else if (qual->false_cca < 100 && qual->vgc_level_reg > 0x32) { + rt2500pci_set_vgc(rt2x00dev, qual, --qual->vgc_level_reg); + qual->vgc_level = qual->vgc_level_reg; } } diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 23cf585f03a..557fcf2b30e 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -698,7 +698,8 @@ static void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev, qual->false_cca = rt2x00_get_field16(reg, STA_CSR3_FALSE_CCA_ERROR); } -static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev) +static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual) { u16 eeprom; u16 value; @@ -719,7 +720,7 @@ static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev) value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_VGCUPPER); rt2500usb_bbp_write(rt2x00dev, 17, value); - rt2x00dev->link.vgc_level = value; + qual->vgc_level = value; } /* diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 8935f2c005c..dea502234cf 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -177,52 +177,41 @@ struct antenna_setup { */ struct link_qual { /* - * Statistics required for Link tuning. - * For the average RSSI value we use the "Walking average" approach. - * When adding RSSI to the average value the following calculation - * is needed: - * - * avg_rssi = ((avg_rssi * 7) + rssi) / 8; + * Statistics required for Link tuning by driver + * The rssi value is provided by rt2x00lib during the + * link_tuner() callback function. + * The false_cca field is filled during the link_stats() + * callback function and could be used during the + * link_tuner() callback function. + */ + int rssi; + int false_cca; + + /* + * VGC levels + * Hardware driver will tune the VGC level during each call + * to the link_tuner() callback function. This vgc_level is + * is determined based on the link quality statistics like + * average RSSI and the false CCA count. * - * The advantage of this approach is that we only need 1 variable - * to store the average in (No need for a count and a total). - * But more importantly, normal average values will over time - * move less and less towards newly added values this results - * that with link tuning, the device can have a very good RSSI - * for a few minutes but when the device is moved away from the AP - * the average will not decrease fast enough to compensate. - * The walking average compensates this and will move towards - * the new values correctly allowing a effective link tuning. + * In some cases the drivers need to differentiate between + * the currently "desired" VGC level and the level configured + * in the hardware. The latter is important to reduce the + * number of BBP register reads to reduce register access + * overhead. For this reason we store both values here. */ - int avg_rssi; - int false_cca; + u8 vgc_level; + u8 vgc_level_reg; /* * Statistics required for Signal quality calculation. - * For calculating the Signal quality we have to determine - * the total number of success and failed RX and TX frames. - * After that we also use the average RSSI value to help - * determining the signal quality. - * For the calculation we will use the following algorithm: - * - * rssi_percentage = (avg_rssi * 100) / rssi_offset - * rx_percentage = (rx_success * 100) / rx_total - * tx_percentage = (tx_success * 100) / tx_total - * avg_signal = ((WEIGHT_RSSI * avg_rssi) + - * (WEIGHT_TX * tx_percentage) + - * (WEIGHT_RX * rx_percentage)) / 100 - * - * This value should then be checked to not be greater then 100. + * These fields might be changed during the link_stats() + * callback function. */ - int rx_percentage; int rx_success; int rx_failed; - int tx_percentage; int tx_success; int tx_failed; -#define WEIGHT_RSSI 20 -#define WEIGHT_RX 40 -#define WEIGHT_TX 40 }; /* @@ -286,14 +275,16 @@ struct link { struct link_ant ant; /* - * Active VGC level (for false cca tuning) + * Currently active average RSSI value */ - u8 vgc_level; + int avg_rssi; /* - * VGC level as configured in register + * Currently precalculated percentages of successful + * TX and RX frames. */ - u8 vgc_level_reg; + int rx_percentage; + int tx_percentage; /* * Work structure for scheduling periodic link tuning. @@ -301,28 +292,6 @@ struct link { struct delayed_work work; }; -/* - * Small helper macro to work with moving/walking averages. - */ -#define MOVING_AVERAGE(__avg, __val, __samples) \ - ( (((__avg) * ((__samples) - 1)) + (__val)) / (__samples) ) - -/* - * When we lack RSSI information return something less then -80 to - * tell the driver to tune the device to maximum sensitivity. - */ -#define DEFAULT_RSSI ( -128 ) - -/* - * Link quality access functions. - */ -static inline int rt2x00_get_link_rssi(struct link *link) -{ - if (link->qual.avg_rssi && link->qual.rx_success) - return link->qual.avg_rssi; - return DEFAULT_RSSI; -} - /* * Interface structure * Per interface configuration details, this structure @@ -522,8 +491,10 @@ struct rt2x00lib_ops { int (*rfkill_poll) (struct rt2x00_dev *rt2x00dev); void (*link_stats) (struct rt2x00_dev *rt2x00dev, struct link_qual *qual); - void (*reset_tuner) (struct rt2x00_dev *rt2x00dev); - void (*link_tuner) (struct rt2x00_dev *rt2x00dev); + void (*reset_tuner) (struct rt2x00_dev *rt2x00dev, + struct link_qual *qual); + void (*link_tuner) (struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, const u32 count); /* * TX control handlers diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index 0462d5ab6e9..ee08f1167f5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c @@ -29,6 +29,71 @@ #include "rt2x00.h" #include "rt2x00lib.h" +/* + * When we lack RSSI information return something less then -80 to + * tell the driver to tune the device to maximum sensitivity. + */ +#define DEFAULT_RSSI -128 + +/* + * When no TX/RX percentage could be calculated due to lack of + * frames on the air, we fallback to a percentage of 50%. + * This will assure we will get at least get some decent value + * when the link tuner starts. + * The value will be dropped and overwritten with the correct (measured) + * value anyway during the first run of the link tuner. + */ +#define DEFAULT_PERCENTAGE 50 + +/* + * Small helper macro to work with moving/walking averages. + * When adding a value to the average value the following calculation + * is needed: + * + * avg_rssi = ((avg_rssi * 7) + rssi) / 8; + * + * The advantage of this approach is that we only need 1 variable + * to store the average in (No need for a count and a total). + * But more importantly, normal average values will over time + * move less and less towards newly added values this results + * that with link tuning, the device can have a very good RSSI + * for a few minutes but when the device is moved away from the AP + * the average will not decrease fast enough to compensate. + * The walking average compensates this and will move towards + * the new values correctly allowing a effective link tuning. + */ +#define MOVING_AVERAGE(__avg, __val, __samples) \ + ( (((__avg) * ((__samples) - 1)) + (__val)) / (__samples) ) + +/* + * Small helper macro for percentage calculation + * This is a very simple macro with the only catch that it will + * produce a default value in case no total value was provided. + */ +#define PERCENTAGE(__value, __total) \ + ( (__total) ? (((__value) * 100) / (__total)) : (DEFAULT_PERCENTAGE) ) + +/* + * For calculating the Signal quality we have determined + * the total number of success and failed RX and TX frames. + * With the addition of the average RSSI value we can determine + * the link quality using the following algorithm: + * + * rssi_percentage = (avg_rssi * 100) / rssi_offset + * rx_percentage = (rx_success * 100) / rx_total + * tx_percentage = (tx_success * 100) / tx_total + * avg_signal = ((WEIGHT_RSSI * avg_rssi) + + * (WEIGHT_TX * tx_percentage) + + * (WEIGHT_RX * rx_percentage)) / 100 + * + * This value should then be checked to not be greater then 100. + * This means the values of WEIGHT_RSSI, WEIGHT_RX, WEIGHT_TX must + * sum up to 100 as well. + */ +#define WEIGHT_RSSI 20 +#define WEIGHT_RX 40 +#define WEIGHT_TX 40 + static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev) { struct link_ant *ant = &rt2x00dev->link.ant; @@ -191,6 +256,7 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, struct rxdone_entry_desc *rxdesc) { + struct link *link = &rt2x00dev->link; struct link_qual *qual = &rt2x00dev->link.qual; struct link_ant *ant = &rt2x00dev->link.ant; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; @@ -215,9 +281,9 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev, /* * Update global RSSI */ - if (qual->avg_rssi) - avg_rssi = MOVING_AVERAGE(qual->avg_rssi, rxdesc->rssi, 8); - qual->avg_rssi = avg_rssi; + if (link->avg_rssi) + avg_rssi = MOVING_AVERAGE(link->avg_rssi, rxdesc->rssi, 8); + link->avg_rssi = avg_rssi; /* * Update antenna RSSI @@ -229,21 +295,13 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev, static void rt2x00link_precalculate_signal(struct rt2x00_dev *rt2x00dev) { + struct link *link = &rt2x00dev->link; struct link_qual *qual = &rt2x00dev->link.qual; - if (qual->rx_failed || qual->rx_success) - qual->rx_percentage = - (qual->rx_success * 100) / - (qual->rx_failed + qual->rx_success); - else - qual->rx_percentage = 50; - - if (qual->tx_failed || qual->tx_success) - qual->tx_percentage = - (qual->tx_success * 100) / - (qual->tx_failed + qual->tx_success); - else - qual->tx_percentage = 50; + link->rx_percentage = + PERCENTAGE(qual->rx_success, qual->rx_failed + qual->rx_success); + link->tx_percentage = + PERCENTAGE(qual->tx_success, qual->tx_failed + qual->tx_success); qual->rx_success = 0; qual->rx_failed = 0; @@ -253,7 +311,7 @@ static void rt2x00link_precalculate_signal(struct rt2x00_dev *rt2x00dev) int rt2x00link_calculate_signal(struct rt2x00_dev *rt2x00dev, int rssi) { - struct link_qual *qual = &rt2x00dev->link.qual; + struct link *link = &rt2x00dev->link; int rssi_percentage = 0; int signal; @@ -267,22 +325,22 @@ int rt2x00link_calculate_signal(struct rt2x00_dev *rt2x00dev, int rssi) * Calculate the different percentages, * which will be used for the signal. */ - rssi_percentage = (rssi * 100) / rt2x00dev->rssi_offset; + rssi_percentage = PERCENTAGE(rssi, rt2x00dev->rssi_offset); /* * Add the individual percentages and use the WEIGHT * defines to calculate the current link signal. */ signal = ((WEIGHT_RSSI * rssi_percentage) + - (WEIGHT_TX * qual->tx_percentage) + - (WEIGHT_RX * qual->rx_percentage)) / 100; + (WEIGHT_TX * link->tx_percentage) + + (WEIGHT_RX * link->rx_percentage)) / 100; return max_t(int, signal, 100); } void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev) { - struct link_qual *qual = &rt2x00dev->link.qual; + struct link *link = &rt2x00dev->link; /* * Link tuning should only be performed when @@ -293,26 +351,13 @@ void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev) if (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count) return; - /* - * Clear all (possibly) pre-existing quality statistics. - */ - memset(qual, 0, sizeof(*qual)); - - /* - * The RX and TX percentage should start at 50% - * this will assure we will get at least get some - * decent value when the link tuner starts. - * The value will be dropped and overwritten with - * the correct (measured) value anyway during the - * first run of the link tuner. - */ - qual->rx_percentage = 50; - qual->tx_percentage = 50; + link->rx_percentage = DEFAULT_PERCENTAGE; + link->tx_percentage = DEFAULT_PERCENTAGE; rt2x00link_reset_tuner(rt2x00dev, false); queue_delayed_work(rt2x00dev->hw->workqueue, - &rt2x00dev->link.work, LINK_TUNE_INTERVAL); + &link->work, LINK_TUNE_INTERVAL); } void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev) @@ -322,6 +367,8 @@ void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev) void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna) { + struct link_qual *qual = &rt2x00dev->link.qual; + if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) return; @@ -334,12 +381,12 @@ void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna) * first minute after being enabled. */ rt2x00dev->link.count = 0; - rt2x00dev->link.vgc_level = 0; + memset(qual, 0, sizeof(*qual)); /* * Reset the link tuner. */ - rt2x00dev->ops->lib->reset_tuner(rt2x00dev); + rt2x00dev->ops->lib->reset_tuner(rt2x00dev, qual); if (antenna) rt2x00link_antenna_reset(rt2x00dev); @@ -349,6 +396,7 @@ static void rt2x00link_tuner(struct work_struct *work) { struct rt2x00_dev *rt2x00dev = container_of(work, struct rt2x00_dev, link.work.work); + struct link *link = &rt2x00dev->link; struct link_qual *qual = &rt2x00dev->link.qual; /* @@ -364,12 +412,23 @@ static void rt2x00link_tuner(struct work_struct *work) rt2x00dev->ops->lib->link_stats(rt2x00dev, qual); rt2x00dev->low_level_stats.dot11FCSErrorCount += qual->rx_failed; + /* + * Update quality RSSI for link tuning, + * when we have received some frames and we managed to + * collect the RSSI data we could use this. Otherwise we + * must fallback to the default RSSI value. + */ + if (!link->avg_rssi || !qual->rx_success) + qual->rssi = DEFAULT_RSSI; + else + qual->rssi = link->avg_rssi; + /* * Only perform the link tuning when Link tuning * has been enabled (This could have been disabled from the EEPROM). */ if (!test_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags)) - rt2x00dev->ops->lib->link_tuner(rt2x00dev); + rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count); /* * Precalculate a portion of the link signal which is @@ -380,7 +439,7 @@ static void rt2x00link_tuner(struct work_struct *work) /* * Send a signal to the led to update the led signal strength. */ - rt2x00leds_led_quality(rt2x00dev, qual->avg_rssi); + rt2x00leds_led_quality(rt2x00dev, link->avg_rssi); /* * Evaluate antenna setup, make this the last step since this could @@ -391,9 +450,9 @@ static void rt2x00link_tuner(struct work_struct *work) /* * Increase tuner counter, and reschedule the next link tuner run. */ - rt2x00dev->link.count++; + link->count++; queue_delayed_work(rt2x00dev->hw->workqueue, - &rt2x00dev->link.work, LINK_TUNE_INTERVAL); + &link->work, LINK_TUNE_INTERVAL); } void rt2x00link_register(struct rt2x00_dev *rt2x00dev) diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 94523f7f0d8..ed829879c94 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1046,24 +1046,25 @@ static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev, qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR); } -static inline void rt61pci_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level) +static inline void rt61pci_set_vgc(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, u8 vgc_level) { - if (rt2x00dev->link.vgc_level != vgc_level) { + if (qual->vgc_level != vgc_level) { rt61pci_bbp_write(rt2x00dev, 17, vgc_level); - rt2x00dev->link.vgc_level = vgc_level; - rt2x00dev->link.vgc_level_reg = vgc_level; + qual->vgc_level = vgc_level; + qual->vgc_level_reg = vgc_level; } } -static void rt61pci_reset_tuner(struct rt2x00_dev *rt2x00dev) +static void rt61pci_reset_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual) { - rt61pci_set_vgc(rt2x00dev, 0x20); + rt61pci_set_vgc(rt2x00dev, qual, 0x20); } -static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) +static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, const u32 count) { - struct link *link = &rt2x00dev->link; - int rssi = rt2x00_get_link_rssi(link); u8 up_bound; u8 low_bound; @@ -1096,32 +1097,32 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) /* * Special big-R17 for very short distance */ - if (rssi >= -35) { - rt61pci_set_vgc(rt2x00dev, 0x60); + if (qual->rssi >= -35) { + rt61pci_set_vgc(rt2x00dev, qual, 0x60); return; } /* * Special big-R17 for short distance */ - if (rssi >= -58) { - rt61pci_set_vgc(rt2x00dev, up_bound); + if (qual->rssi >= -58) { + rt61pci_set_vgc(rt2x00dev, qual, up_bound); return; } /* * Special big-R17 for middle-short distance */ - if (rssi >= -66) { - rt61pci_set_vgc(rt2x00dev, low_bound + 0x10); + if (qual->rssi >= -66) { + rt61pci_set_vgc(rt2x00dev, qual, low_bound + 0x10); return; } /* * Special mid-R17 for middle distance */ - if (rssi >= -74) { - rt61pci_set_vgc(rt2x00dev, low_bound + 0x08); + if (qual->rssi >= -74) { + rt61pci_set_vgc(rt2x00dev, qual, low_bound + 0x08); return; } @@ -1129,12 +1130,12 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) * Special case: Change up_bound based on the rssi. * Lower up_bound when rssi is weaker then -74 dBm. */ - up_bound -= 2 * (-74 - rssi); + up_bound -= 2 * (-74 - qual->rssi); if (low_bound > up_bound) up_bound = low_bound; - if (link->vgc_level > up_bound) { - rt61pci_set_vgc(rt2x00dev, up_bound); + if (qual->vgc_level > up_bound) { + rt61pci_set_vgc(rt2x00dev, qual, up_bound); return; } @@ -1144,10 +1145,10 @@ dynamic_cca_tune: * r17 does not yet exceed upper limit, continue and base * the r17 tuning on the false CCA count. */ - if ((link->qual.false_cca > 512) && (link->vgc_level < up_bound)) - rt61pci_set_vgc(rt2x00dev, ++link->vgc_level); - else if ((link->qual.false_cca < 100) && (link->vgc_level > low_bound)) - rt61pci_set_vgc(rt2x00dev, --link->vgc_level); + if ((qual->false_cca > 512) && (qual->vgc_level < up_bound)) + rt61pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level); + else if ((qual->false_cca < 100) && (qual->vgc_level > low_bound)) + rt61pci_set_vgc(rt2x00dev, qual, --qual->vgc_level); } /* diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index b5443148d62..e99bcacfc19 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -924,24 +924,25 @@ static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev, qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR); } -static inline void rt73usb_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level) +static inline void rt73usb_set_vgc(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, u8 vgc_level) { - if (rt2x00dev->link.vgc_level != vgc_level) { + if (qual->vgc_level != vgc_level) { rt73usb_bbp_write(rt2x00dev, 17, vgc_level); - rt2x00dev->link.vgc_level = vgc_level; - rt2x00dev->link.vgc_level_reg = vgc_level; + qual->vgc_level = vgc_level; + qual->vgc_level_reg = vgc_level; } } -static void rt73usb_reset_tuner(struct rt2x00_dev *rt2x00dev) +static void rt73usb_reset_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual) { - rt73usb_set_vgc(rt2x00dev, 0x20); + rt73usb_set_vgc(rt2x00dev, qual, 0x20); } -static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) +static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, const u32 count) { - struct link *link = &rt2x00dev->link; - int rssi = rt2x00_get_link_rssi(link); u8 up_bound; u8 low_bound; @@ -957,10 +958,10 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) up_bound += 0x10; } } else { - if (rssi > -82) { + if (qual->rssi > -82) { low_bound = 0x1c; up_bound = 0x40; - } else if (rssi > -84) { + } else if (qual->rssi > -84) { low_bound = 0x1c; up_bound = 0x20; } else { @@ -984,32 +985,32 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) /* * Special big-R17 for very short distance */ - if (rssi > -35) { - rt73usb_set_vgc(rt2x00dev, 0x60); + if (qual->rssi > -35) { + rt73usb_set_vgc(rt2x00dev, qual, 0x60); return; } /* * Special big-R17 for short distance */ - if (rssi >= -58) { - rt73usb_set_vgc(rt2x00dev, up_bound); + if (qual->rssi >= -58) { + rt73usb_set_vgc(rt2x00dev, qual, up_bound); return; } /* * Special big-R17 for middle-short distance */ - if (rssi >= -66) { - rt73usb_set_vgc(rt2x00dev, low_bound + 0x10); + if (qual->rssi >= -66) { + rt73usb_set_vgc(rt2x00dev, qual, low_bound + 0x10); return; } /* * Special mid-R17 for middle distance */ - if (rssi >= -74) { - rt73usb_set_vgc(rt2x00dev, low_bound + 0x08); + if (qual->rssi >= -74) { + rt73usb_set_vgc(rt2x00dev, qual, low_bound + 0x08); return; } @@ -1017,12 +1018,12 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) * Special case: Change up_bound based on the rssi. * Lower up_bound when rssi is weaker then -74 dBm. */ - up_bound -= 2 * (-74 - rssi); + up_bound -= 2 * (-74 - qual->rssi); if (low_bound > up_bound) up_bound = low_bound; - if (link->vgc_level > up_bound) { - rt73usb_set_vgc(rt2x00dev, up_bound); + if (qual->vgc_level > up_bound) { + rt73usb_set_vgc(rt2x00dev, qual, up_bound); return; } @@ -1032,12 +1033,12 @@ dynamic_cca_tune: * r17 does not yet exceed upper limit, continue and base * the r17 tuning on the false CCA count. */ - if ((link->qual.false_cca > 512) && (link->vgc_level < up_bound)) - rt73usb_set_vgc(rt2x00dev, - min_t(u8, link->vgc_level + 4, up_bound)); - else if ((link->qual.false_cca < 100) && (link->vgc_level > low_bound)) - rt73usb_set_vgc(rt2x00dev, - max_t(u8, link->vgc_level - 4, low_bound)); + if ((qual->false_cca > 512) && (qual->vgc_level < up_bound)) + rt73usb_set_vgc(rt2x00dev, qual, + min_t(u8, qual->vgc_level + 4, up_bound)); + else if ((qual->false_cca < 100) && (qual->vgc_level > low_bound)) + rt73usb_set_vgc(rt2x00dev, qual, + max_t(u8, qual->vgc_level - 4, low_bound)); } /* -- GitLab From a07dbea210e146aedf8929cdabe082b58696260c Mon Sep 17 00:00:00 2001 From: Andrey Yurovsky Date: Sat, 20 Dec 2008 10:55:34 +0100 Subject: [PATCH 0673/4982] rt2x00: Add mesh support This adds initial support for Mesh Point mode. For this we tell mac80211 that we support NL80211_IFTYPE_MESH_POINT. We also need to send beacons. mac80211 will configure our RX filter accordingly. Signed-off-by: Andrey Yurovsky Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00config.c | 1 + drivers/net/wireless/rt2x00/rt2x00dev.c | 11 +++++++---- drivers/net/wireless/rt2x00/rt2x00mac.c | 1 + 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 2f4cb8de998..a35265cc754 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -42,6 +42,7 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, switch (type) { case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: conf.sync = TSF_SYNC_BEACON; break; case NL80211_IFTYPE_STATION: diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 81d7fc8635d..6a5712c6614 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -190,7 +190,8 @@ static void rt2x00lib_beacondone_iter(void *data, u8 *mac, struct rt2x00_intf *intf = vif_to_intf(vif); if (vif->type != NL80211_IFTYPE_AP && - vif->type != NL80211_IFTYPE_ADHOC) + vif->type != NL80211_IFTYPE_ADHOC && + vif->type != NL80211_IFTYPE_MESH_POINT) return; /* @@ -780,7 +781,8 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) if (rt2x00dev->ops->bcn->entry_num > 0) rt2x00dev->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_AP); + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_MESH_POINT); /* * Let the driver probe the device to detect the capabilities. @@ -935,10 +937,11 @@ static void rt2x00lib_resume_intf(void *data, u8 *mac, /* - * Master or Ad-hoc mode require a new beacon update. + * AP, Ad-hoc, and Mesh Point mode require a new beacon update. */ if (vif->type == NL80211_IFTYPE_AP || - vif->type == NL80211_IFTYPE_ADHOC) + vif->type == NL80211_IFTYPE_ADHOC || + vif->type == NL80211_IFTYPE_MESH_POINT) intf->delayed_flags |= DELAYED_UPDATE_BEACON; spin_unlock(&intf->lock); diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 38edee5fe16..137386ebf68 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -226,6 +226,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, break; case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: /* * We don't support mixed combinations of * sta and ap interfaces. -- GitLab From 7396faf4f3228b88c6c815c7a93081b456716d5f Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 20 Dec 2008 10:55:57 +0100 Subject: [PATCH 0674/4982] rt2x00: Add RFKILL support to rt2500usb and rt73usb Some very rare Ralink USB hardware exists which features the RFKILL switch on the USB stick. This patch adds the EEPROM check function to see if RFKILL is supported and the polling function to rt2500usb and rt73usb in order to support RFKILL for that hardware. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 21 +++++++++++++++++++++ drivers/net/wireless/rt2x00/rt2500usb.h | 8 ++++++++ drivers/net/wireless/rt2x00/rt73usb.c | 21 +++++++++++++++++++++ drivers/net/wireless/rt2x00/rt73usb.h | 13 +++++++++++++ 4 files changed, 63 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 557fcf2b30e..01e5584d8f7 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -280,6 +280,18 @@ static const struct rt2x00debug rt2500usb_rt2x00debug = { }; #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ +#ifdef CONFIG_RT2X00_LIB_RFKILL +static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev) +{ + u16 reg; + + rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); + return rt2x00_get_field32(reg, MAC_CSR19_BIT7); +} +#else +#define rt2500usb_rfkill_poll NULL +#endif /* CONFIG_RT2X00_LIB_RFKILL */ + #ifdef CONFIG_RT2X00_LIB_LEDS static void rt2500usb_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness) @@ -1596,6 +1608,14 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) LED_TYPE_ACTIVITY); #endif /* CONFIG_RT2X00_LIB_LEDS */ + /* + * Detect if this device has an hardware controlled radio. + */ +#ifdef CONFIG_RT2X00_LIB_RFKILL + if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) + __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); +#endif /* CONFIG_RT2X00_LIB_RFKILL */ + /* * Check if the BBP tuning should be disabled. */ @@ -1902,6 +1922,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .uninitialize = rt2x00usb_uninitialize, .clear_entry = rt2x00usb_clear_entry, .set_device_state = rt2500usb_set_device_state, + .rfkill_poll = rt2500usb_rfkill_poll, .link_stats = rt2500usb_link_stats, .reset_tuner = rt2500usb_reset_tuner, .link_tuner = rt2500usb_link_tuner, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index 4347dfdabcd..e1f714e82af 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -189,6 +189,14 @@ * MAC_CSR19: GPIO control register. */ #define MAC_CSR19 0x0426 +#define MAC_CSR19_BIT0 FIELD32(0x0001) +#define MAC_CSR19_BIT1 FIELD32(0x0002) +#define MAC_CSR19_BIT2 FIELD32(0x0004) +#define MAC_CSR19_BIT3 FIELD32(0x0008) +#define MAC_CSR19_BIT4 FIELD32(0x0010) +#define MAC_CSR19_BIT5 FIELD32(0x0020) +#define MAC_CSR19_BIT6 FIELD32(0x0040) +#define MAC_CSR19_BIT7 FIELD32(0x0080) /* * MAC_CSR20: LED control register. diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index e99bcacfc19..c2658108d9c 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -186,6 +186,18 @@ static const struct rt2x00debug rt73usb_rt2x00debug = { }; #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ +#ifdef CONFIG_RT2X00_LIB_RFKILL +static int rt73usb_rfkill_poll(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + + rt2x00usb_register_read(rt2x00dev, MAC_CSR13, ®); + return rt2x00_get_field32(reg, MAC_CSR13_BIT7); +} +#else +#define rt73usb_rfkill_poll NULL +#endif /* CONFIG_RT2X00_LIB_RFKILL */ + #ifdef CONFIG_RT2X00_LIB_LEDS static void rt73usb_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness) @@ -1852,6 +1864,14 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE)) __set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags); + /* + * Detect if this device has an hardware controlled radio. + */ +#ifdef CONFIG_RT2X00_LIB_RFKILL + if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) + __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); +#endif /* CONFIG_RT2X00_LIB_RFKILL */ + /* * Read frequency offset. */ @@ -2257,6 +2277,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .uninitialize = rt2x00usb_uninitialize, .clear_entry = rt2x00usb_clear_entry, .set_device_state = rt73usb_set_device_state, + .rfkill_poll = rt73usb_rfkill_poll, .link_stats = rt73usb_link_stats, .reset_tuner = rt73usb_reset_tuner, .link_tuner = rt73usb_link_tuner, diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 46e1405eb0e..204bbd5b7c5 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -267,6 +267,19 @@ struct hw_pairwise_ta_entry { * MAC_CSR13: GPIO. */ #define MAC_CSR13 0x3034 +#define MAC_CSR13_BIT0 FIELD32(0x00000001) +#define MAC_CSR13_BIT1 FIELD32(0x00000002) +#define MAC_CSR13_BIT2 FIELD32(0x00000004) +#define MAC_CSR13_BIT3 FIELD32(0x00000008) +#define MAC_CSR13_BIT4 FIELD32(0x00000010) +#define MAC_CSR13_BIT5 FIELD32(0x00000020) +#define MAC_CSR13_BIT6 FIELD32(0x00000040) +#define MAC_CSR13_BIT7 FIELD32(0x00000080) +#define MAC_CSR13_BIT8 FIELD32(0x00000100) +#define MAC_CSR13_BIT9 FIELD32(0x00000200) +#define MAC_CSR13_BIT10 FIELD32(0x00000400) +#define MAC_CSR13_BIT11 FIELD32(0x00000800) +#define MAC_CSR13_BIT12 FIELD32(0x00001000) /* * MAC_CSR14: LED control register. -- GitLab From 3f787bd6d596ff56625f440910944ef6f937af8d Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 20 Dec 2008 10:56:36 +0100 Subject: [PATCH 0675/4982] rt2x00: Rename CONFIG_CRYPTO_COPY_IV CONFIG_CRYPTO_COPY_IV is a bad name since it is part of the driver requirements instead of a configuration option. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 2 +- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- drivers/net/wireless/rt2x00/rt2x00queue.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 01e5584d8f7..7b97160e2b5 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1888,7 +1888,7 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags); if (!modparam_nohwcrypt) { __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); - __set_bit(CONFIG_CRYPTO_COPY_IV, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags); } __set_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags); diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index dea502234cf..1612a9cf4d7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -586,6 +586,7 @@ enum rt2x00_flags { DRIVER_REQUIRE_ATIM_QUEUE, DRIVER_REQUIRE_SCHEDULED, DRIVER_REQUIRE_DMA, + DRIVER_REQUIRE_COPY_IV, /* * Driver features @@ -602,7 +603,6 @@ enum rt2x00_flags { CONFIG_EXTERNAL_LNA_BG, CONFIG_DOUBLE_ANTENNA, CONFIG_DISABLE_LINK_TUNING, - CONFIG_CRYPTO_COPY_IV, }; /* diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 0709decec9c..01125563aba 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -403,7 +403,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) */ if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) && !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) { - if (test_bit(CONFIG_CRYPTO_COPY_IV, &queue->rt2x00dev->flags)) + if (test_bit(DRIVER_REQUIRE_COPY_IV, &queue->rt2x00dev->flags)) rt2x00crypto_tx_copy_iv(skb, iv_len); else rt2x00crypto_tx_remove_iv(skb, iv_len); -- GitLab From ce292a640228fded0d2e232216a19cba33e2cd0f Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 20 Dec 2008 10:57:02 +0100 Subject: [PATCH 0676/4982] rt2x00: Implement WDS support WDS support should be very easy to handle, mac80211 handles everything for us, so all that is needed is to set the support flags and handle it in the add_interface() callback. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00config.c | 1 + drivers/net/wireless/rt2x00/rt2x00dev.c | 9 ++++++--- drivers/net/wireless/rt2x00/rt2x00mac.c | 1 + 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index a35265cc754..ab139f2698b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -43,6 +43,7 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_AP: case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_WDS: conf.sync = TSF_SYNC_BEACON; break; case NL80211_IFTYPE_STATION: diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 6a5712c6614..8c0dae530ae 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -191,7 +191,8 @@ static void rt2x00lib_beacondone_iter(void *data, u8 *mac, if (vif->type != NL80211_IFTYPE_AP && vif->type != NL80211_IFTYPE_ADHOC && - vif->type != NL80211_IFTYPE_MESH_POINT) + vif->type != NL80211_IFTYPE_MESH_POINT && + vif->type != NL80211_IFTYPE_WDS) return; /* @@ -782,7 +783,8 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) rt2x00dev->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_MESH_POINT); + BIT(NL80211_IFTYPE_MESH_POINT) | + BIT(NL80211_IFTYPE_WDS); /* * Let the driver probe the device to detect the capabilities. @@ -941,7 +943,8 @@ static void rt2x00lib_resume_intf(void *data, u8 *mac, */ if (vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_ADHOC || - vif->type == NL80211_IFTYPE_MESH_POINT) + vif->type == NL80211_IFTYPE_MESH_POINT || + vif->type == NL80211_IFTYPE_WDS) intf->delayed_flags |= DELAYED_UPDATE_BEACON; spin_unlock(&intf->lock); diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 137386ebf68..e6fba830d1d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -227,6 +227,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_WDS: /* * We don't support mixed combinations of * sta and ap interfaces. -- GitLab From 91581b627287d8cc3ee382ee038e04c4beca8176 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 20 Dec 2008 10:57:47 +0100 Subject: [PATCH 0677/4982] rt2x00: Split EEPROM_NIC_TX_RX_FIXED The 2 bits in EEPROM_NIC_TX_RX_FIXED each influence a different antenna. We might as well split the definition and directly read the correct bit. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt61pci.c | 25 ++++++------------------- drivers/net/wireless/rt2x00/rt61pci.h | 3 ++- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index ed829879c94..875bcdcf6bc 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2230,7 +2230,8 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) if (word == 0xffff) { rt2x00_set_field16(&word, EEPROM_NIC_ENABLE_DIVERSITY, 0); rt2x00_set_field16(&word, EEPROM_NIC_TX_DIVERSITY, 0); - rt2x00_set_field16(&word, EEPROM_NIC_TX_RX_FIXED, 0); + rt2x00_set_field16(&word, EEPROM_NIC_RX_FIXED, 0); + rt2x00_set_field16(&word, EEPROM_NIC_TX_FIXED, 0); rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_BG, 0); rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0); rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0); @@ -2374,24 +2375,10 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) */ if (rt2x00_rf(&rt2x00dev->chip, RF2529) && !test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) { - switch (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_RX_FIXED)) { - case 0: - rt2x00dev->default_ant.tx = ANTENNA_B; - rt2x00dev->default_ant.rx = ANTENNA_A; - break; - case 1: - rt2x00dev->default_ant.tx = ANTENNA_B; - rt2x00dev->default_ant.rx = ANTENNA_B; - break; - case 2: - rt2x00dev->default_ant.tx = ANTENNA_A; - rt2x00dev->default_ant.rx = ANTENNA_A; - break; - case 3: - rt2x00dev->default_ant.tx = ANTENNA_A; - rt2x00dev->default_ant.rx = ANTENNA_B; - break; - } + rt2x00dev->default_ant.rx = + ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED); + rt2x00dev->default_ant.tx = + ANTENNA_B - rt2x00_get_field16(eeprom, EEPROM_NIC_TX_FIXED); if (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_DIVERSITY)) rt2x00dev->default_ant.tx = ANTENNA_SW_DIVERSITY; diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index 86590c6de0e..cd86def8de5 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -1190,7 +1190,8 @@ struct hw_pairwise_ta_entry { #define EEPROM_NIC 0x0011 #define EEPROM_NIC_ENABLE_DIVERSITY FIELD16(0x0001) #define EEPROM_NIC_TX_DIVERSITY FIELD16(0x0002) -#define EEPROM_NIC_TX_RX_FIXED FIELD16(0x000c) +#define EEPROM_NIC_RX_FIXED FIELD16(0x0004) +#define EEPROM_NIC_TX_FIXED FIELD16(0x0008) #define EEPROM_NIC_EXTERNAL_LNA_BG FIELD16(0x0010) #define EEPROM_NIC_CARDBUS_ACCEL FIELD16(0x0020) #define EEPROM_NIC_EXTERNAL_LNA_A FIELD16(0x0040) -- GitLab From 7b40982e235d6ff9343d38703eb48a0143afcc26 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 20 Dec 2008 10:58:33 +0100 Subject: [PATCH 0678/4982] rt2x00: Move code into seperate functions Some functions have grown rapidly in size over the last time, some of those functions (like the rt2x00queue_create_tx_descriptor) will further increase in size soon, so it is best to start cutting it into logical pieces. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00crypto.c | 13 +- drivers/net/wireless/rt2x00/rt2x00lib.h | 6 +- drivers/net/wireless/rt2x00/rt2x00mac.c | 40 +++-- drivers/net/wireless/rt2x00/rt2x00queue.c | 193 +++++++++++---------- 4 files changed, 138 insertions(+), 114 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index aee9cba13eb..e9d3ddae278 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c @@ -49,9 +49,14 @@ enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key) void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry, struct txentry_desc *txdesc) { + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; + if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) || + !hw_key || entry->skb->do_not_encrypt) + return; + __set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags); txdesc->cipher = rt2x00crypto_key_to_cipher(hw_key); @@ -69,11 +74,17 @@ void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry, __set_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags); } -unsigned int rt2x00crypto_tx_overhead(struct ieee80211_tx_info *tx_info) +unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev, + struct sk_buff *skb) { + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_key_conf *key = tx_info->control.hw_key; unsigned int overhead = 0; + if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) || + !key || skb->do_not_encrypt) + return overhead; + /* * Extend frame length to include IV/EIV/ICV/MMIC, * note that these lengths should only be added when diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index fccaffde6f5..5e8df250e50 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -282,7 +282,8 @@ static inline void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev, enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key); void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry, struct txentry_desc *txdesc); -unsigned int rt2x00crypto_tx_overhead(struct ieee80211_tx_info *tx_info); +unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev, + struct sk_buff *skb); void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, unsigned int iv_len); void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, unsigned int iv_len); void rt2x00crypto_tx_insert_iv(struct sk_buff *skb); @@ -300,7 +301,8 @@ static inline void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry, { } -static inline unsigned int rt2x00crypto_tx_overhead(struct ieee80211_tx_info *tx_info) +static inline unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev, + struct sk_buff *skb) { return 0; } diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index e6fba830d1d..bf7755a2164 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -79,8 +79,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, * RTS/CTS frame should use the length of the frame plus any * encryption overhead that will be added by the hardware. */ - if (!frag_skb->do_not_encrypt) - data_length += rt2x00crypto_tx_overhead(tx_info); + data_length += rt2x00crypto_tx_overhead(rt2x00dev, skb); if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) ieee80211_ctstoself_get(rt2x00dev->hw, tx_info->control.vif, @@ -484,6 +483,24 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw, EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); #ifdef CONFIG_RT2X00_LIB_CRYPTO +static void memcpy_tkip(struct rt2x00lib_crypto *crypto, u8 *key, u8 key_len) +{ + if (key_len > NL80211_TKIP_DATA_OFFSET_ENCR_KEY) + memcpy(&crypto->key, + &key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY], + sizeof(crypto->key)); + + if (key_len > NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY) + memcpy(&crypto->tx_mic, + &key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY], + sizeof(crypto->tx_mic)); + + if (key_len > NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY) + memcpy(&crypto->rx_mic, + &key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY], + sizeof(crypto->rx_mic)); +} + int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, const u8 *local_address, const u8 *address, struct ieee80211_key_conf *key) @@ -521,22 +538,9 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, crypto.cmd = cmd; crypto.address = address; - if (crypto.cipher == CIPHER_TKIP) { - if (key->keylen > NL80211_TKIP_DATA_OFFSET_ENCR_KEY) - memcpy(&crypto.key, - &key->key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY], - sizeof(crypto.key)); - - if (key->keylen > NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY) - memcpy(&crypto.tx_mic, - &key->key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY], - sizeof(crypto.tx_mic)); - - if (key->keylen > NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY) - memcpy(&crypto.rx_mic, - &key->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY], - sizeof(crypto.rx_mic)); - } else + if (crypto.cipher == CIPHER_TKIP) + memcpy_tkip(&crypto, &key->key[0], key->keylen); + else memcpy(&crypto.key, &key->key[0], key->keylen); /* diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 01125563aba..f4a951338f8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -148,20 +148,105 @@ void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) dev_kfree_skb_any(skb); } +static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry, + struct txentry_desc *txdesc) +{ + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; + struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); + unsigned long irqflags; + + if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) || + unlikely(!tx_info->control.vif)) + return; + + /* + * Hardware should insert sequence counter. + * FIXME: We insert a software sequence counter first for + * hardware that doesn't support hardware sequence counting. + * + * This is wrong because beacons are not getting sequence + * numbers assigned properly. + * + * A secondary problem exists for drivers that cannot toggle + * sequence counting per-frame, since those will override the + * sequence counter given by mac80211. + */ + spin_lock_irqsave(&intf->seqlock, irqflags); + + if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) + intf->seqno += 0x10; + hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); + hdr->seq_ctrl |= cpu_to_le16(intf->seqno); + + spin_unlock_irqrestore(&intf->seqlock, irqflags); + + __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); +} + +static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry, + struct txentry_desc *txdesc, + const struct rt2x00_rate *hwrate) +{ + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); + struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; + unsigned int data_length; + unsigned int duration; + unsigned int residual; + + /* Data length + CRC + Crypto overhead (IV/EIV/ICV/MIC) */ + data_length = entry->skb->len + 4; + data_length += rt2x00crypto_tx_overhead(rt2x00dev, entry->skb); + + /* + * PLCP setup + * Length calculation depends on OFDM/CCK rate. + */ + txdesc->signal = hwrate->plcp; + txdesc->service = 0x04; + + if (hwrate->flags & DEV_RATE_OFDM) { + txdesc->length_high = (data_length >> 6) & 0x3f; + txdesc->length_low = data_length & 0x3f; + } else { + /* + * Convert length to microseconds. + */ + residual = GET_DURATION_RES(data_length, hwrate->bitrate); + duration = GET_DURATION(data_length, hwrate->bitrate); + + if (residual != 0) { + duration++; + + /* + * Check if we need to set the Length Extension + */ + if (hwrate->bitrate == 110 && residual <= 30) + txdesc->service |= 0x80; + } + + txdesc->length_high = (duration >> 8) & 0xff; + txdesc->length_low = duration & 0xff; + + /* + * When preamble is enabled we should set the + * preamble bit for the signal. + */ + if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) + txdesc->signal |= 0x08; + } +} + static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, struct txentry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; - struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; struct ieee80211_rate *rate = ieee80211_get_tx_rate(rt2x00dev->hw, tx_info); const struct rt2x00_rate *hwrate; - unsigned int data_length; - unsigned int duration; - unsigned int residual; - unsigned long irqflags; memset(txdesc, 0, sizeof(*txdesc)); @@ -173,27 +258,12 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, txdesc->cw_max = entry->queue->cw_max; txdesc->aifs = entry->queue->aifs; - /* Data length + CRC */ - data_length = entry->skb->len + 4; - /* * Check whether this frame is to be acked. */ if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) __set_bit(ENTRY_TXD_ACK, &txdesc->flags); - if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) && - !entry->skb->do_not_encrypt) { - /* Apply crypto specific descriptor information */ - rt2x00crypto_create_tx_descriptor(entry, txdesc); - - /* - * Extend frame length to include all encryption overhead - * that will be added by the hardware. - */ - data_length += rt2x00crypto_tx_overhead(tx_info); - } - /* * Check if this is a RTS/CTS frame */ @@ -237,86 +307,23 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, * Set ifs to IFS_SIFS when the this is not the first fragment, * or this fragment came after RTS/CTS. */ - if (test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags)) { - txdesc->ifs = IFS_SIFS; - } else if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) { + if ((tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) && + !test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags)) { __set_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags); txdesc->ifs = IFS_BACKOFF; - } else { + } else txdesc->ifs = IFS_SIFS; - } - /* - * Hardware should insert sequence counter. - * FIXME: We insert a software sequence counter first for - * hardware that doesn't support hardware sequence counting. - * - * This is wrong because beacons are not getting sequence - * numbers assigned properly. - * - * A secondary problem exists for drivers that cannot toggle - * sequence counting per-frame, since those will override the - * sequence counter given by mac80211. - */ - if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - if (likely(tx_info->control.vif)) { - struct rt2x00_intf *intf; - - intf = vif_to_intf(tx_info->control.vif); - - spin_lock_irqsave(&intf->seqlock, irqflags); - - if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) - intf->seqno += 0x10; - hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(intf->seqno); - - spin_unlock_irqrestore(&intf->seqlock, irqflags); - - __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); - } - } - - /* - * PLCP setup - * Length calculation depends on OFDM/CCK rate. - */ hwrate = rt2x00_get_rate(rate->hw_value); - txdesc->signal = hwrate->plcp; - txdesc->service = 0x04; - - if (hwrate->flags & DEV_RATE_OFDM) { + if (hwrate->flags & DEV_RATE_OFDM) __set_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags); - txdesc->length_high = (data_length >> 6) & 0x3f; - txdesc->length_low = data_length & 0x3f; - } else { - /* - * Convert length to microseconds. - */ - residual = GET_DURATION_RES(data_length, hwrate->bitrate); - duration = GET_DURATION(data_length, hwrate->bitrate); - - if (residual != 0) { - duration++; - - /* - * Check if we need to set the Length Extension - */ - if (hwrate->bitrate == 110 && residual <= 30) - txdesc->service |= 0x80; - } - - txdesc->length_high = (duration >> 8) & 0xff; - txdesc->length_low = duration & 0xff; - - /* - * When preamble is enabled we should set the - * preamble bit for the signal. - */ - if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) - txdesc->signal |= 0x08; - } + /* + * Apply TX descriptor handling by components + */ + rt2x00crypto_create_tx_descriptor(entry, txdesc); + rt2x00queue_create_tx_descriptor_seq(entry, txdesc); + rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate); } static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, -- GitLab From 076f9582a6b82e54339ee815130315744b730787 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 20 Dec 2008 10:59:02 +0100 Subject: [PATCH 0679/4982] rt2x00: Remove ENTRY_TXD_OFDM_RATE The flag ENTRY_TXD_OFDM_RATE isn't flexible enough to indicate which rate modulation should be used for a frame. This will become a problem when 11n support is added. Remove the flag and replace it with an enum value which can better indicate the exact rate modulation. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500pci.c | 2 +- drivers/net/wireless/rt2x00/rt2500usb.c | 2 +- drivers/net/wireless/rt2x00/rt2x00queue.c | 6 +++++- drivers/net/wireless/rt2x00/rt2x00queue.h | 5 +++-- drivers/net/wireless/rt2x00/rt2x00reg.h | 10 ++++++++++ drivers/net/wireless/rt2x00/rt61pci.c | 2 +- drivers/net/wireless/rt2x00/rt73usb.c | 2 +- 7 files changed, 22 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index fb86e2c5524..ebcc4977092 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1233,7 +1233,7 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_OFDM, - test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags)); + (txdesc->rate_mode == RATE_MODE_OFDM)); rt2x00_set_field32(&word, TXD_W0_CIPHER_OWNER, 1); rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 7b97160e2b5..e992bad6464 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1217,7 +1217,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_OFDM, - test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags)); + (txdesc->rate_mode == RATE_MODE_OFDM)); rt2x00_set_field32(&word, TXD_W0_NEW_SEQ, test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index f4a951338f8..67140e75608 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -314,9 +314,13 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, } else txdesc->ifs = IFS_SIFS; + /* + * Determine rate modulation. + */ hwrate = rt2x00_get_rate(rate->hw_value); + txdesc->rate_mode = RATE_MODE_CCK; if (hwrate->flags & DEV_RATE_OFDM) - __set_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags); + txdesc->rate_mode = RATE_MODE_OFDM; /* * Apply TX descriptor handling by components diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 28293715340..5a9d2c3d1bb 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -222,7 +222,6 @@ struct txdone_entry_desc { * * @ENTRY_TXD_RTS_FRAME: This frame is a RTS frame. * @ENTRY_TXD_CTS_FRAME: This frame is a CTS-to-self frame. - * @ENTRY_TXD_OFDM_RATE: This frame is send out with an OFDM rate. * @ENTRY_TXD_GENERATE_SEQ: This frame requires sequence counter. * @ENTRY_TXD_FIRST_FRAGMENT: This is the first frame. * @ENTRY_TXD_MORE_FRAG: This frame is followed by another fragment. @@ -238,7 +237,6 @@ struct txdone_entry_desc { enum txentry_desc_flags { ENTRY_TXD_RTS_FRAME, ENTRY_TXD_CTS_FRAME, - ENTRY_TXD_OFDM_RATE, ENTRY_TXD_GENERATE_SEQ, ENTRY_TXD_FIRST_FRAGMENT, ENTRY_TXD_MORE_FRAG, @@ -263,6 +261,7 @@ enum txentry_desc_flags { * @length_low: PLCP length low word. * @signal: PLCP signal. * @service: PLCP service. + * @rate_mode: Rate mode (See @enum rate_modulation). * @retry_limit: Max number of retries. * @aifs: AIFS value. * @ifs: IFS value. @@ -282,6 +281,8 @@ struct txentry_desc { u16 signal; u16 service; + u16 rate_mode; + short retry_limit; short aifs; short ifs; diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index c2fba7c9f05..93f8427055c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h @@ -124,6 +124,16 @@ enum cipher { CIPHER_MAX = 4, }; +/* + * Rate modulations + */ +enum rate_modulation { + RATE_MODE_CCK = 0, + RATE_MODE_OFDM = 1, + RATE_MODE_HT_MIX = 2, + RATE_MODE_HT_GREENFIELD = 3, +}; + /* * Register handlers. * We store the position of a register field inside a field structure, diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 875bcdcf6bc..82d35a5a4aa 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1847,7 +1847,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_OFDM, - test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags)); + (txdesc->rate_mode == RATE_MODE_OFDM)); rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags)); diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index c2658108d9c..2b70c01b55e 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1498,7 +1498,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_OFDM, - test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags)); + (txdesc->rate_mode == RATE_MODE_OFDM)); rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags)); -- GitLab From 2bdb35c7ffb61f4b9d963dd447a2c54add5f02c5 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 20 Dec 2008 10:59:29 +0100 Subject: [PATCH 0680/4982] rt2x00: Allow drivers to pass the noise value during rxdone Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 1 + drivers/net/wireless/rt2x00/rt2x00queue.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 8c0dae530ae..c7bd212656d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -407,6 +407,7 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, rx_status->rate_idx = idx; rx_status->qual = rt2x00link_calculate_signal(rt2x00dev, rxdesc.rssi); rx_status->signal = rxdesc.rssi; + rx_status->noise = rxdesc.noise; rx_status->flag = rxdesc.flags; rx_status->antenna = rt2x00dev->link.ant.active.rx; diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 5a9d2c3d1bb..1bd1a952e42 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -165,6 +165,7 @@ enum rxdone_entry_desc_flags { * @timestamp: RX Timestamp * @signal: Signal of the received frame. * @rssi: RSSI of the received frame. + * @noise: Measured noise during frame reception. * @size: Data size of the received frame. * @flags: MAC80211 receive flags (See &enum mac80211_rx_flags). * @dev_flags: Ralink receive flags (See &enum rxdone_entry_desc_flags). @@ -177,6 +178,7 @@ struct rxdone_entry_desc { u64 timestamp; int signal; int rssi; + int noise; int size; int flags; int dev_flags; -- GitLab From b30dd5c043eda4b3d23659ef550c16ce4f6ecb47 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 20 Dec 2008 10:59:55 +0100 Subject: [PATCH 0681/4982] rt2x00: Introduce RXDONE_SIGNAL_MASK mask Improve error message reporting when a frame was received with unknown rate. Instead of using the boolean check if the frame is supposed to be a PLCP value or not, we should add a new mask (RXDONE_SIGNAL_MASK) which returns the type identification for a signal value (i.e. PLCP). At the moment we only have 2 different types, but more will arrive when support for 11n is added. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 4 ++-- drivers/net/wireless/rt2x00/rt2x00queue.h | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index c7bd212656d..12331b15fe7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -392,8 +392,8 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, if (idx < 0) { WARNING(rt2x00dev, "Frame received with unrecognized signal," - "signal=0x%.2x, plcp=%d.\n", rxdesc.signal, - !!(rxdesc.dev_flags & RXDONE_SIGNAL_PLCP)); + "signal=0x%.2x, type=%d.\n", rxdesc.signal, + (rxdesc.dev_flags & RXDONE_SIGNAL_MASK)); idx = 0; } diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 1bd1a952e42..98209d2e93a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -157,6 +157,14 @@ enum rxdone_entry_desc_flags { RXDONE_CRYPTO_ICV = 1 << 4, }; +/** + * RXDONE_SIGNAL_MASK - Define to mask off all &rxdone_entry_desc_flags flags + * except for the RXDONE_SIGNAL_* flags. This is useful to convert the dev_flags + * from &rxdone_entry_desc to a signal value type. + */ +#define RXDONE_SIGNAL_MASK \ + ( RXDONE_SIGNAL_PLCP | RXDONE_SIGNAL_BITRATE ) + /** * struct rxdone_entry_desc: RX Entry descriptor * -- GitLab From 754be3098b22d1bea9620b40fe2f9f2286c55101 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 20 Dec 2008 11:00:49 +0100 Subject: [PATCH 0682/4982] rt2x00: Release rt2x00 2.3.0 Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 1612a9cf4d7..1ef3434a2ba 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -44,7 +44,7 @@ /* * Module information. */ -#define DRV_VERSION "2.2.3" +#define DRV_VERSION "2.3.0" #define DRV_PROJECT "http://rt2x00.serialmonkey.com" /* -- GitLab From 0ea9c00c9d4e6309637a2defe18d26b6cda0fdc0 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Sun, 21 Dec 2008 04:47:39 +0200 Subject: [PATCH 0683/4982] ath5k: Update EEPROM code *Read misc2...6 values from eeprom since we want to use them (fixes wrong power calibration info offset on RF2413+ chips) *Initialize num_piers to 0 for RF2413 chips (note that we read 2GHz frequency piers while reading mode sections, we have to ignore them -usualy they are 0xff anyway but during my tests i got a 1 on b mode with no data- and use the newer eemap. *Add some more comments (please forgive my poor English ;-( ) and some minor code cleanup *Tested on 2425 and 2112 and has the same data with ath_info (i wrote some debug code on debug.c to print everything like ath_info but i haven't tested it yet on 5111 and it's full of > 80 col lines, if anyone wants to play with it let me know). Signed-Off-by: Nick Kossifidis Acked-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/eeprom.c | 143 ++++++++++++++++++++++------ 1 file changed, 116 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/ath5k/eeprom.c b/drivers/net/wireless/ath5k/eeprom.c index 1cb7edfae62..079e9ca168d 100644 --- a/drivers/net/wireless/ath5k/eeprom.c +++ b/drivers/net/wireless/ath5k/eeprom.c @@ -137,6 +137,18 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0); AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1); + + /* XXX: Don't know which versions include these two */ + AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC2, ee_misc2); + + if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3) + AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC3, ee_misc3); + + if (ee->ee_version >= AR5K_EEPROM_VERSION_5_0) { + AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC4, ee_misc4); + AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC5, ee_misc5); + AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC6, ee_misc6); + } } if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) { @@ -213,7 +225,8 @@ static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset, } /* - * Read supported modes from eeprom + * Read supported modes and some mode-specific calibration data + * from eeprom */ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, unsigned int mode) @@ -315,6 +328,9 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_0) goto done; + /* Note: >= v5 have bg freq piers on another location + * so these freq piers are ignored for >= v5 (should be 0xff + * anyway) */ switch(mode) { case AR5K_EEPROM_MODE_11A: if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_1) @@ -442,7 +458,7 @@ ath5k_eeprom_read_turbo_modes(struct ath5k_hw *ah, return 0; } - +/* Read mode-specific data (except power calibration data) */ static int ath5k_eeprom_init_modes(struct ath5k_hw *ah) { @@ -488,6 +504,16 @@ ath5k_eeprom_init_modes(struct ath5k_hw *ah) return 0; } +/* Used to match PCDAC steps with power values on RF5111 chips + * (eeprom versions < 4). For RF5111 we have 10 pre-defined PCDAC + * steps that match with the power values we read from eeprom. On + * older eeprom versions (< 3.2) these steps are equaly spaced at + * 10% of the pcdac curve -until the curve reaches it's maximum- + * (10 steps from 0 to 100%) but on newer eeprom versions (>= 3.2) + * these 10 steps are spaced in a different way. This function returns + * the pcdac steps based on eeprom version and curve min/max so that we + * can have pcdac/pwr points. + */ static inline void ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp) { @@ -507,37 +533,48 @@ ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp) *vp++ = (ip[i] * max + (100 - ip[i]) * min) / 100; } +/* Read the frequency piers for each mode (mostly used on newer eeproms with 0xff + * frequency mask) */ static inline int ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max, - struct ath5k_chan_pcal_info *pc, u8 *count) + struct ath5k_chan_pcal_info *pc, unsigned int mode) { + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; int o = *offset; int i = 0; - u8 f1, f2; + u8 freq1, freq2; int ret; u16 val; while(i < max) { AR5K_EEPROM_READ(o++, val); - f1 = (val >> 8) & 0xff; - f2 = val & 0xff; + freq1 = (val >> 8) & 0xff; + freq2 = val & 0xff; - if (f1) - pc[i++].freq = f1; + if (freq1) { + pc[i++].freq = ath5k_eeprom_bin2freq(ee, + freq1, mode); + ee->ee_n_piers[mode]++; + } - if (f2) - pc[i++].freq = f2; + if (freq2) { + pc[i++].freq = ath5k_eeprom_bin2freq(ee, + freq2, mode); + ee->ee_n_piers[mode]++; + } - if (!f1 || !f2) + if (!freq1 || !freq2) break; } + + /* return new offset */ *offset = o; - *count = i; return 0; } +/* Read frequency piers for 802.11a */ static int ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset) { @@ -550,7 +587,7 @@ ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset) if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) { ath5k_eeprom_read_freq_list(ah, &offset, AR5K_EEPROM_N_5GHZ_CHAN, pcal, - &ee->ee_n_piers[AR5K_EEPROM_MODE_11A]); + AR5K_EEPROM_MODE_11A); } else { mask = AR5K_EEPROM_FREQ_M(ah->ah_ee_version); @@ -577,23 +614,25 @@ ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset) AR5K_EEPROM_READ(offset++, val); pcal[9].freq |= (val >> 10) & 0x3f; + + /* Fixed number of piers */ ee->ee_n_piers[AR5K_EEPROM_MODE_11A] = 10; - } - for(i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i += 1) { - pcal[i].freq = ath5k_eeprom_bin2freq(ee, + for (i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i++) { + pcal[i].freq = ath5k_eeprom_bin2freq(ee, pcal[i].freq, AR5K_EEPROM_MODE_11A); + } } return 0; } +/* Read frequency piers for 802.11bg on eeprom versions >= 5 and eemap >= 2 */ static inline int ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset) { struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; struct ath5k_chan_pcal_info *pcal; - int i; switch(mode) { case AR5K_EEPROM_MODE_11B: @@ -608,16 +647,18 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset) ath5k_eeprom_read_freq_list(ah, &offset, AR5K_EEPROM_N_2GHZ_CHAN_2413, pcal, - &ee->ee_n_piers[mode]); - for(i = 0; i < AR5K_EEPROM_N_2GHZ_CHAN_2413; i += 1) { - pcal[i].freq = ath5k_eeprom_bin2freq(ee, - pcal[i].freq, mode); - } + mode); return 0; } - +/* Read power calibration for RF5111 chips + * For RF5111 we have an XPD -eXternal Power Detector- curve + * for each calibrated channel. Each curve has PCDAC steps on + * x axis and power on y axis and looks like a logarithmic + * function. To recreate the curve and pass the power values + * on the pcdac table, we read 10 points here and interpolate later. + */ static int ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode) { @@ -714,6 +755,17 @@ ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode) return 0; } +/* Read power calibration for RF5112 chips + * For RF5112 we have 4 XPD -eXternal Power Detector- curves + * for each calibrated channel on 0, -6, -12 and -18dbm but we only + * use the higher (3) and the lower (0) curves. Each curve has PCDAC + * steps on x axis and power on y axis and looks like a linear + * function. To recreate the curve and pass the power values + * on the pcdac table, we read 4 points for xpd 0 and 3 points + * for xpd 3 here and interpolate later. + * + * Note: Many vendors just use xpd 0 so xpd 3 is zeroed. + */ static int ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) { @@ -790,7 +842,7 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) /* PCDAC steps * corresponding to the above power - * measurements (static) */ + * measurements (fixed) */ chan_pcal_info->pcdac_x3[0] = 20; chan_pcal_info->pcdac_x3[1] = 35; chan_pcal_info->pcdac_x3[2] = 63; @@ -814,6 +866,13 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) return 0; } +/* For RF2413 power calibration data doesn't start on a fixed location and + * if a mode is not supported, it's section is missing -not zeroed-. + * So we need to calculate the starting offset for each section by using + * these two functions */ + +/* Return the size of each section based on the mode and the number of pd + * gains available (maximum 4). */ static inline unsigned int ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode) { @@ -826,6 +885,8 @@ ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode) return sz; } +/* Return the starting offset for a section based on the modes supported + * and each section's size. */ static unsigned int ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode) { @@ -834,11 +895,13 @@ ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode) switch(mode) { case AR5K_EEPROM_MODE_11G: if (AR5K_EEPROM_HDR_11B(ee->ee_header)) - offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11B) + 2; + offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11B) + + AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2; /* fall through */ case AR5K_EEPROM_MODE_11B: if (AR5K_EEPROM_HDR_11A(ee->ee_header)) - offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11A) + 5; + offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11A) + + AR5K_EEPROM_N_5GHZ_CHAN / 2; /* fall through */ case AR5K_EEPROM_MODE_11A: break; @@ -849,6 +912,17 @@ ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode) return offset; } +/* Read power calibration for RF2413 chips + * For RF2413 we have a PDDAC table (Power Detector) instead + * of a PCDAC and 4 pd gain curves for each calibrated channel. + * Each curve has PDDAC steps on x axis and power on y axis and + * looks like an exponential function. To recreate the curves + * we read here the points and interpolate later. Note that + * in most cases only higher and lower curves are used (like + * RF5112) but vendors have the oportunity to include all 4 + * curves on eeprom. The final curve (higher power) has an extra + * point for better accuracy like RF5112. + */ static int ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) { @@ -868,6 +942,7 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) ee->ee_pd_gains[mode] = pd_gains; offset = ath5k_cal_data_offset_2413(ee, mode); + ee->ee_n_piers[mode] = 0; switch (mode) { case AR5K_EEPROM_MODE_11A: if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) @@ -1163,6 +1238,20 @@ static int ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned return 0; } +/* + * Read per channel calibration info from EEPROM + * + * This info is used to calibrate the baseband power table. Imagine + * that for each channel there is a power curve that's hw specific + * (depends on amplifier etc) and we try to "correct" this curve using + * offests we pass on to phy chip (baseband -> before amplifier) so that + * it can use accurate power values when setting tx power (takes amplifier's + * performance on each channel into account). + * + * EEPROM provides us with the offsets for some pre-calibrated channels + * and we have to interpolate to create the full table for these channels and + * also the table for any channel. + */ static int ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah) { @@ -1193,7 +1282,7 @@ ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah) return 0; } -/* Read conformance test limits */ +/* Read conformance test limits used for regulatory control */ static int ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) { -- GitLab From a15bd00543a859a72546e4b09342b70e79e9ef1e Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 21 Dec 2008 20:54:34 +0100 Subject: [PATCH 0684/4982] p54: label queues with their corresponding names This patch introduce new shiny named labels for our 8 (4 - on old firmware) queues. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 50 +++++++++++++--------------- drivers/net/wireless/p54/p54common.h | 19 ++++++++++- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 34561e6e816..3298cb464f7 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -239,11 +239,11 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) if (priv->fw_var >= 0x300) { /* Firmware supports QoS, use it! */ - priv->tx_stats[4].limit = 3; /* AC_VO */ - priv->tx_stats[5].limit = 4; /* AC_VI */ - priv->tx_stats[6].limit = 3; /* AC_BE */ - priv->tx_stats[7].limit = 2; /* AC_BK */ - dev->queues = 4; + priv->tx_stats[P54_QUEUE_AC_VO].limit = 3; + priv->tx_stats[P54_QUEUE_AC_VI].limit = 4; + priv->tx_stats[P54_QUEUE_AC_BE].limit = 3; + priv->tx_stats[P54_QUEUE_AC_BK].limit = 2; + dev->queues = P54_QUEUE_AC_NUM; } if (!modparam_nohwcrypt) @@ -655,7 +655,8 @@ static void inline p54_wake_free_queues(struct ieee80211_hw *dev) return ; for (i = 0; i < dev->queues; i++) - if (priv->tx_stats[i + 4].len < priv->tx_stats[i + 4].limit) + if (priv->tx_stats[i + P54_QUEUE_DATA].len < + priv->tx_stats[i + P54_QUEUE_DATA].limit) ieee80211_wake_queue(dev, i); } @@ -1244,22 +1245,22 @@ static int p54_tx_fill(struct ieee80211_hw *dev, struct sk_buff *skb, if (unlikely(ieee80211_is_mgmt(hdr->frame_control))) { if (ieee80211_is_beacon(hdr->frame_control)) { *aid = 0; - *queue = 0; + *queue = P54_QUEUE_BEACON; *extra_len = IEEE80211_MAX_TIM_LEN; *flags = P54_HDR_FLAG_DATA_OUT_TIMESTAMP; return 0; } else if (ieee80211_is_probe_resp(hdr->frame_control)) { *aid = 0; - *queue = 2; + *queue = P54_QUEUE_MGMT; *flags = P54_HDR_FLAG_DATA_OUT_TIMESTAMP | P54_HDR_FLAG_DATA_OUT_NOCANCEL; return 0; } else { - *queue = 2; + *queue = P54_QUEUE_MGMT; ret = 0; } } else { - *queue += 4; + *queue += P54_QUEUE_DATA; ret = 1; } @@ -1272,7 +1273,7 @@ static int p54_tx_fill(struct ieee80211_hw *dev, struct sk_buff *skb, case NL80211_IFTYPE_MESH_POINT: if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { *aid = 0; - *queue = 3; + *queue = P54_QUEUE_CAB; return 0; } if (info->control.sta) @@ -1300,7 +1301,7 @@ static u8 p54_convert_algo(enum ieee80211_key_alg alg) static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_tx_queue_stats *current_queue = NULL; + struct ieee80211_tx_queue_stats *current_queue; struct p54_common *priv = dev->priv; struct p54_hdr *hdr; struct p54_tx_data *txhdr; @@ -1443,10 +1444,7 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) } txhdr->crypt_offset = crypt_offset; txhdr->hw_queue = queue; - if (current_queue) - txhdr->backlog = current_queue->len; - else - txhdr->backlog = 0; + txhdr->backlog = current_queue->len; memset(txhdr->durations, 0, sizeof(txhdr->durations)); txhdr->tx_antenna = (info->antenna_sel_tx == 0) ? 2 : info->antenna_sel_tx - 1; @@ -1468,10 +1466,8 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) err: skb_pull(skb, sizeof(*hdr) + sizeof(*txhdr) + padding); - if (current_queue) { - current_queue->len--; - current_queue->count--; - } + current_queue->len--; + current_queue->count--; return NETDEV_TX_BUSY; } @@ -2019,8 +2015,8 @@ static int p54_get_tx_stats(struct ieee80211_hw *dev, { struct p54_common *priv = dev->priv; - memcpy(stats, &priv->tx_stats[4], sizeof(stats[0]) * dev->queues); - + memcpy(stats, &priv->tx_stats[P54_QUEUE_DATA], + sizeof(stats[0]) * dev->queues); return 0; } @@ -2181,11 +2177,11 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) BIT(NL80211_IFTYPE_MESH_POINT); dev->channel_change_time = 1000; /* TODO: find actual value */ - priv->tx_stats[0].limit = 1; /* Beacon queue */ - priv->tx_stats[1].limit = 1; /* Probe queue for HW scan */ - priv->tx_stats[2].limit = 3; /* queue for MLMEs */ - priv->tx_stats[3].limit = 3; /* Broadcast / MC queue */ - priv->tx_stats[4].limit = 5; /* Data */ + priv->tx_stats[P54_QUEUE_BEACON].limit = 1; + priv->tx_stats[P54_QUEUE_FWSCAN].limit = 1; + priv->tx_stats[P54_QUEUE_MGMT].limit = 3; + priv->tx_stats[P54_QUEUE_CAB].limit = 3; + priv->tx_stats[P54_QUEUE_DATA].limit = 5; dev->queues = 1; priv->noise = -94; /* diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h index f5729de83fe..514f660d0be 100644 --- a/drivers/net/wireless/p54/p54common.h +++ b/drivers/net/wireless/p54/p54common.h @@ -329,7 +329,7 @@ struct p54_frame_sent { u8 padding; } __attribute__ ((packed)); -enum p54_tx_data_crypt { +enum p54_tx_data_crypt { P54_CRYPTO_NONE = 0, P54_CRYPTO_WEP, P54_CRYPTO_TKIP, @@ -340,6 +340,23 @@ enum p54_tx_data_crypt { P54_CRYPTO_AESCCMP }; +enum p54_tx_data_queue { + P54_QUEUE_BEACON = 0, + P54_QUEUE_FWSCAN = 1, + P54_QUEUE_MGMT = 2, + P54_QUEUE_CAB = 3, + P54_QUEUE_DATA = 4, + + P54_QUEUE_AC_NUM = 4, + P54_QUEUE_AC_VO = 4, + P54_QUEUE_AC_VI = 5, + P54_QUEUE_AC_BE = 6, + P54_QUEUE_AC_BK = 7, + + /* keep last */ + P54_QUEUE_NUM = 8, +}; + struct p54_tx_data { u8 rateset[8]; u8 rts_rate_idx; -- GitLab From 29701e5abf155d76fc8ab785a172c4ccf6cf47ee Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 21 Dec 2008 22:52:10 +0100 Subject: [PATCH 0685/4982] p54: enable proper frame injection This patch enables frame injection in monitor mode for all p54 devices. As a result, any user can finally use the aircrack-ng suite out of the box. e.g: aireplay-ng --test wlan0 Trying broadcast probe requests... Injection is working! Found 1 AP Trying directed probe requests... XX:XX:XX:XX:XX:XX - channel: i - 'SSID' Ping (min/avg/max): 1.536ms/3.193ms/4.377ms Power: 193.00 30/30: 100% Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 95 ++++++++++++++++++++-------- 1 file changed, 69 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 3298cb464f7..28d98338957 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -775,9 +775,16 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) priv->tx_stats[entry_data->hw_queue].len--; priv->stats.dot11ACKFailureCount += payload->tries - 1; - if (unlikely(entry == priv->cached_beacon)) { + /* + * Frames in P54_QUEUE_FWSCAN and P54_QUEUE_BEACON are + * generated by the driver. Therefore tx_status is bogus + * and we don't want to confuse the mac80211 stack. + */ + if (unlikely(entry_data->hw_queue < P54_QUEUE_FWSCAN)) { + if (entry_data->hw_queue == P54_QUEUE_BEACON) + priv->cached_beacon = NULL; + kfree_skb(entry); - priv->cached_beacon = NULL; goto out; } @@ -1240,33 +1247,26 @@ static int p54_tx_fill(struct ieee80211_hw *dev, struct sk_buff *skb, { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct p54_common *priv = dev->priv; - int ret = 0; - - if (unlikely(ieee80211_is_mgmt(hdr->frame_control))) { - if (ieee80211_is_beacon(hdr->frame_control)) { - *aid = 0; - *queue = P54_QUEUE_BEACON; - *extra_len = IEEE80211_MAX_TIM_LEN; - *flags = P54_HDR_FLAG_DATA_OUT_TIMESTAMP; - return 0; - } else if (ieee80211_is_probe_resp(hdr->frame_control)) { - *aid = 0; - *queue = P54_QUEUE_MGMT; - *flags = P54_HDR_FLAG_DATA_OUT_TIMESTAMP | - P54_HDR_FLAG_DATA_OUT_NOCANCEL; - return 0; - } else { - *queue = P54_QUEUE_MGMT; - ret = 0; - } - } else { - *queue += P54_QUEUE_DATA; - ret = 1; - } + int ret = 1; switch (priv->mode) { + case NL80211_IFTYPE_MONITOR: + /* + * We have to set P54_HDR_FLAG_DATA_OUT_PROMISC for + * every frame in promiscuous/monitor mode. + * see STSW45x0C LMAC API - page 12. + */ + *aid = 0; + *flags = P54_HDR_FLAG_DATA_OUT_PROMISC; + *queue += P54_QUEUE_DATA; + break; case NL80211_IFTYPE_STATION: *aid = 1; + if (unlikely(ieee80211_is_mgmt(hdr->frame_control))) { + *queue = P54_QUEUE_MGMT; + ret = 0; + } else + *queue += P54_QUEUE_DATA; break; case NL80211_IFTYPE_AP: case NL80211_IFTYPE_ADHOC: @@ -1276,10 +1276,44 @@ static int p54_tx_fill(struct ieee80211_hw *dev, struct sk_buff *skb, *queue = P54_QUEUE_CAB; return 0; } + + if (unlikely(ieee80211_is_mgmt(hdr->frame_control))) { + if (ieee80211_is_probe_resp(hdr->frame_control)) { + *aid = 0; + *queue = P54_QUEUE_MGMT; + *flags = P54_HDR_FLAG_DATA_OUT_TIMESTAMP | + P54_HDR_FLAG_DATA_OUT_NOCANCEL; + return 0; + } else if (ieee80211_is_beacon(hdr->frame_control)) { + *aid = 0; + + if (info->flags & IEEE80211_TX_CTL_INJECTED) { + /* + * Injecting beacons on top of a AP is + * not a good idea... nevertheless, + * it should be doable. + */ + + *queue += P54_QUEUE_DATA; + return 1; + } + + *flags = P54_HDR_FLAG_DATA_OUT_TIMESTAMP; + *queue = P54_QUEUE_BEACON; + *extra_len = IEEE80211_MAX_TIM_LEN; + return 0; + } else { + *queue = P54_QUEUE_MGMT; + ret = 0; + } + } else + *queue += P54_QUEUE_DATA; + if (info->control.sta) *aid = info->control.sta->aid; else *flags |= P54_HDR_FLAG_DATA_OUT_NOCANCEL; + break; } return ret; } @@ -1497,11 +1531,20 @@ static int p54_setup_mac(struct ieee80211_hw *dev) case NL80211_IFTYPE_MESH_POINT: mode = P54_FILTER_TYPE_IBSS; break; + case NL80211_IFTYPE_MONITOR: + mode = P54_FILTER_TYPE_PROMISCUOUS; + break; default: mode = P54_FILTER_TYPE_NONE; break; } - if (priv->filter_flags & FIF_PROMISC_IN_BSS) + + /* + * "TRANSPARENT and PROMISCUOUS are mutually exclusive" + * STSW45X0C LMAC API - page 12 + */ + if ((priv->filter_flags & FIF_PROMISC_IN_BSS) && + (mode != P54_FILTER_TYPE_PROMISCUOUS)) mode |= P54_FILTER_TYPE_TRANSPARENT; } else mode = P54_FILTER_TYPE_RX_DISABLED; -- GitLab From 2ddfa129bbf3dca708ffb0eb29d08de32cacd547 Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Mon, 22 Dec 2008 11:31:20 +0800 Subject: [PATCH 0686/4982] iwlwifi: move sysfs status entry to debugfs This patch moves priv->status sysfs entry to debugfs. It is for debugging only anyway. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 11 ----------- drivers/net/wireless/iwlwifi/iwl-debug.h | 1 + drivers/net/wireless/iwlwifi/iwl-debugfs.c | 10 +++++++++- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 0dc8eed1640..01e744962d6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3652,16 +3652,6 @@ static ssize_t show_statistics(struct device *d, static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL); -static ssize_t show_status(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; - if (!iwl_is_alive(priv)) - return -EAGAIN; - return sprintf(buf, "0x%08x\n", (int)priv->status); -} - -static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); /***************************************************************************** * @@ -3717,7 +3707,6 @@ static struct attribute *iwl_sysfs_entries[] = { &dev_attr_power_level.attr, &dev_attr_retry_rate.attr, &dev_attr_statistics.attr, - &dev_attr_status.attr, &dev_attr_temperature.attr, &dev_attr_tx_power.attr, #ifdef CONFIG_IWLWIFI_DEBUG diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 56c13b458de..7c4ee0cd81c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -61,6 +61,7 @@ struct iwl_debugfs { struct dentry *file_tx_statistics; struct dentry *file_log_event; struct dentry *file_channels; + struct dentry *file_status; } dbgfs_data_files; struct dir_rf_files { struct dentry *file_disable_sensitivity; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index d5253a179de..1e142fbac61 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -63,6 +63,14 @@ goto err; \ } while (0) +#define DEBUGFS_ADD_X32(name, parent, ptr) do { \ + dbgfs->dbgfs_##parent##_files.file_##name = \ + debugfs_create_x32(#name, 0444, dbgfs->dir_##parent, ptr); \ + if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \ + || !dbgfs->dbgfs_##parent##_files.file_##name) \ + goto err; \ +} while (0) + #define DEBUGFS_REMOVE(name) do { \ debugfs_remove(name); \ name = NULL; \ @@ -420,7 +428,6 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, return ret; } - DEBUGFS_READ_WRITE_FILE_OPS(sram); DEBUGFS_WRITE_FILE_OPS(log_event); DEBUGFS_READ_FILE_OPS(eeprom); @@ -462,6 +469,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(rx_statistics, data); DEBUGFS_ADD_FILE(tx_statistics, data); DEBUGFS_ADD_FILE(channels, data); + DEBUGFS_ADD_X32(status, data, (u32 *)&priv->status); DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); DEBUGFS_ADD_BOOL(disable_chain_noise, rf, &priv->disable_chain_noise_cal); -- GitLab From b306b82c58069159791df5a377a1f1f49b42c4d3 Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Mon, 22 Dec 2008 11:31:21 +0800 Subject: [PATCH 0687/4982] iwlwifi: kill retry_rate sysfs for iwlagn This patch kills retry_rate in sysfs for iwlagn. It's not used. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 26 ------------------------- drivers/net/wireless/iwlwifi/iwl-core.c | 1 - 2 files changed, 27 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 01e744962d6..1e5aadd9e6a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3525,31 +3525,6 @@ static ssize_t store_filter_flags(struct device *d, static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, store_filter_flags); -static ssize_t store_retry_rate(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - long val; - int ret = strict_strtol(buf, 10, &val); - if (!ret) - return ret; - - priv->retry_rate = (val > 0) ? val : 1; - - return count; -} - -static ssize_t show_retry_rate(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - return sprintf(buf, "%d", priv->retry_rate); -} - -static DEVICE_ATTR(retry_rate, S_IWUSR | S_IRUSR, show_retry_rate, - store_retry_rate); - static ssize_t store_power_level(struct device *d, struct device_attribute *attr, const char *buf, size_t count) @@ -3705,7 +3680,6 @@ static struct attribute *iwl_sysfs_entries[] = { &dev_attr_flags.attr, &dev_attr_filter_flags.attr, &dev_attr_power_level.attr, - &dev_attr_retry_rate.attr, &dev_attr_statistics.attr, &dev_attr_temperature.attr, &dev_attr_tx_power.attr, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 73d7973707e..313976b29da 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -863,7 +863,6 @@ int iwl_init_drv(struct iwl_priv *priv) { int ret; - priv->retry_rate = 1; priv->ibss_beacon = NULL; spin_lock_init(&priv->lock); -- GitLab From eaee7cc2c180c291084a1c1f49cd2bf13002b3e1 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Mon, 22 Dec 2008 12:35:55 +0200 Subject: [PATCH 0688/4982] ath5k: More EEPROM code updates * Don't scale power values on RF5111 EEPROMs because they get out of bounds (power is u8, so multiplying power by 50 is too much and there is no reason to do so -we don't do it on other chips anyway-). HAL does it as a technique to handle 0.5 dbm steps but i believe it's not the right thing to do and certainly not the right place to do it. We 'll work this out on interpolation code for all chips (0.5 or 0.25 steps etc) in a generic way. Signed-Off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/eeprom.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath5k/eeprom.c b/drivers/net/wireless/ath5k/eeprom.c index 079e9ca168d..b4ec539c464 100644 --- a/drivers/net/wireless/ath5k/eeprom.c +++ b/drivers/net/wireless/ath5k/eeprom.c @@ -665,7 +665,7 @@ ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode) struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; struct ath5k_chan_pcal_info *pcal; int offset, ret; - int i, j; + int i; u16 val; offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); @@ -745,11 +745,6 @@ ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode) ath5k_get_pcdac_intercepts(ah, cdata->pcdac_min, cdata->pcdac_max, cdata->pcdac); - - for (j = 0; j < AR5K_EEPROM_N_PCDAC; j++) { - cdata->pwr[j] = (u16) - (AR5K_EEPROM_POWER_STEP * cdata->pwr[j]); - } } return 0; -- GitLab From 9ee677c2276bfcbcf68042ec2718a504af0c5fd7 Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Tue, 23 Dec 2008 14:03:38 +0000 Subject: [PATCH 0689/4982] wireless: Add channel/frequency conversions to ieee80211.h Added mappings for FHSS, DSSS and OFDM channels - with macros to point HR DSSS and ERP to the DSSS mappings. Currently just static inline functions. Use the new functions in the older fullmac drivers. This eliminates a number of const static buffers and removes a couple of range checks that are now redundant. Signed-off-by: David Kilroy Acked-by: Arnaldo Carvalho de Melo Acked-by: Richard Farina Acked-by: Jeroen Vreeken Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 25 ++---- drivers/net/wireless/atmel.c | 20 ++--- drivers/net/wireless/orinoco/orinoco.c | 33 +++---- drivers/net/wireless/rndis_wlan.c | 13 ++- drivers/net/wireless/wl3501_cs.c | 9 +- drivers/net/wireless/zd1201.c | 7 +- include/linux/ieee80211.h | 116 +++++++++++++++++++++++++ 7 files changed, 155 insertions(+), 68 deletions(-) diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index fc4322ca669..2ff588bb0a7 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -1070,10 +1070,6 @@ static WifiCtlHdr wifictlhdr8023 = { } }; -// Frequency list (map channels to frequencies) -static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442, - 2447, 2452, 2457, 2462, 2467, 2472, 2484 }; - // A few details needed for WEP (Wireless Equivalent Privacy) #define MAX_KEY_SIZE 13 // 128 (?) bits #define MIN_KEY_SIZE 5 // 40 bits RC4 - WEP @@ -5725,16 +5721,12 @@ static int airo_set_freq(struct net_device *dev, int rc = -EINPROGRESS; /* Call commit handler */ /* If setting by frequency, convert to a channel */ - if((fwrq->e == 1) && - (fwrq->m >= (int) 2.412e8) && - (fwrq->m <= (int) 2.487e8)) { + if(fwrq->e == 1) { int f = fwrq->m / 100000; - int c = 0; - while((c < 14) && (f != frequency_list[c])) - c++; + /* Hack to fall through... */ fwrq->e = 0; - fwrq->m = c + 1; + fwrq->m = ieee80211_freq_to_dsss_chan(f); } /* Setting by channel number */ if((fwrq->m > 1000) || (fwrq->e > 0)) @@ -5778,7 +5770,7 @@ static int airo_get_freq(struct net_device *dev, ch = le16_to_cpu(status_rid.channel); if((ch > 0) && (ch < 15)) { - fwrq->m = frequency_list[ch - 1] * 100000; + fwrq->m = ieee80211_dsss_chan_to_freq(ch) * 100000; fwrq->e = 1; } else { fwrq->m = ch; @@ -6795,8 +6787,8 @@ static int airo_get_range(struct net_device *dev, k = 0; for(i = 0; i < 14; i++) { range->freq[k].i = i + 1; /* List index */ - range->freq[k].m = frequency_list[i] * 100000; - range->freq[k++].e = 1; /* Values in table in MHz -> * 10^5 * 10 */ + range->freq[k].m = ieee80211_dsss_chan_to_freq(i + 1) * 100000; + range->freq[k++].e = 1; /* Values in MHz -> * 10^5 * 10 */ } range->num_frequency = k; @@ -7189,10 +7181,7 @@ static inline char *airo_translate_scan(struct net_device *dev, /* Add frequency */ iwe.cmd = SIOCGIWFREQ; iwe.u.freq.m = le16_to_cpu(bss->dsChannel); - /* iwe.u.freq.m containt the channel (starting 1), our - * frequency_list array start at index 0... - */ - iwe.u.freq.m = frequency_list[iwe.u.freq.m - 1] * 100000; + iwe.u.freq.m = ieee80211_dsss_chan_to_freq(iwe.u.freq.m) * 100000; iwe.u.freq.e = 1; current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 4223672c443..91930a2c3c6 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -2204,9 +2204,6 @@ static int atmel_get_frag(struct net_device *dev, return 0; } -static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442, - 2447, 2452, 2457, 2462, 2467, 2472, 2484 }; - static int atmel_set_freq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *fwrq, @@ -2216,16 +2213,12 @@ static int atmel_set_freq(struct net_device *dev, int rc = -EINPROGRESS; /* Call commit handler */ /* If setting by frequency, convert to a channel */ - if ((fwrq->e == 1) && - (fwrq->m >= (int) 241200000) && - (fwrq->m <= (int) 248700000)) { + if (fwrq->e == 1) { int f = fwrq->m / 100000; - int c = 0; - while ((c < 14) && (f != frequency_list[c])) - c++; + /* Hack to fall through... */ fwrq->e = 0; - fwrq->m = c + 1; + fwrq->m = ieee80211_freq_to_dsss_chan(f); } /* Setting by channel number */ if ((fwrq->m > 1000) || (fwrq->e > 0)) @@ -2384,8 +2377,11 @@ static int atmel_get_range(struct net_device *dev, if (range->num_channels != 0) { for (k = 0, i = channel_table[j].min; i <= channel_table[j].max; i++) { range->freq[k].i = i; /* List index */ - range->freq[k].m = frequency_list[i - 1] * 100000; - range->freq[k++].e = 1; /* Values in table in MHz -> * 10^5 * 10 */ + + /* Values in MHz -> * 10^5 * 10 */ + range->freq[k].m = (ieee80211_dsss_chan_to_freq(i) * + 100000); + range->freq[k++].e = 1; } range->num_frequency = k; } diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c index 45a04faa781..beb4d1f8c18 100644 --- a/drivers/net/wireless/orinoco/orinoco.c +++ b/drivers/net/wireless/orinoco/orinoco.c @@ -178,12 +178,7 @@ static const struct ethtool_ops orinoco_ethtool_ops; /* Data tables */ /********************************************************************/ -/* The frequency of each channel in MHz */ -static const long channel_frequency[] = { - 2412, 2417, 2422, 2427, 2432, 2437, 2442, - 2447, 2452, 2457, 2462, 2467, 2472, 2484 -}; -#define NUM_CHANNELS ARRAY_SIZE(channel_frequency) +#define NUM_CHANNELS 14 /* This tables gives the actual meanings of the bitrate IDs returned * by the firmware. */ @@ -3742,13 +3737,13 @@ static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, return err; } -static long orinoco_hw_get_freq(struct orinoco_private *priv) +static int orinoco_hw_get_freq(struct orinoco_private *priv) { hermes_t *hw = &priv->hw; int err = 0; u16 channel; - long freq = 0; + int freq = 0; unsigned long flags; if (orinoco_lock(priv, &flags) != 0) @@ -3771,7 +3766,7 @@ static long orinoco_hw_get_freq(struct orinoco_private *priv) goto out; } - freq = channel_frequency[channel-1] * 100000; + freq = ieee80211_dsss_chan_to_freq(channel); out: orinoco_unlock(priv, &flags); @@ -3998,7 +3993,8 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, for (i = 0; i < NUM_CHANNELS; i++) { if (priv->channel_mask & (1 << i)) { range->freq[k].i = i + 1; - range->freq[k].m = channel_frequency[i] * 100000; + range->freq[k].m = (ieee80211_dsss_chan_to_freq(i + 1) * + 100000); range->freq[k].e = 1; k++; } @@ -4346,16 +4342,15 @@ static int orinoco_ioctl_setfreq(struct net_device *dev, /* Setting by channel number */ chan = frq->m; } else { - /* Setting by frequency - search the table */ - int mult = 1; + /* Setting by frequency */ + int denom = 1; int i; + /* Calculate denominator to rescale to MHz */ for (i = 0; i < (6 - frq->e); i++) - mult *= 10; + denom *= 10; - for (i = 0; i < NUM_CHANNELS; i++) - if (frq->m == (channel_frequency[i] * mult)) - chan = i+1; + chan = ieee80211_freq_to_dsss_chan(frq->m / denom); } if ( (chan < 1) || (chan > NUM_CHANNELS) || @@ -4392,7 +4387,7 @@ static int orinoco_ioctl_getfreq(struct net_device *dev, return tmp; } - frq->m = tmp; + frq->m = tmp * 100000; frq->e = 1; return 0; @@ -5609,7 +5604,7 @@ static inline char *orinoco_translate_scan(struct net_device *dev, current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); - iwe.u.freq.m = channel_frequency[channel-1] * 100000; + iwe.u.freq.m = ieee80211_dsss_chan_to_freq(channel) * 100000; iwe.u.freq.e = 1; current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); @@ -5760,7 +5755,7 @@ static inline char *orinoco_translate_ext_scan(struct net_device *dev, current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); - iwe.u.freq.m = channel_frequency[channel-1] * 100000; + iwe.u.freq.m = ieee80211_dsss_chan_to_freq(channel) * 100000; iwe.u.freq.e = 1; current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index ed93ac41297..105f214e21f 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -369,9 +369,6 @@ struct rndis_wext_private { }; -static const int freq_chan[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442, - 2447, 2452, 2457, 2462, 2467, 2472, 2484 }; - static const int rates_80211g[8] = { 6, 9, 12, 18, 24, 36, 48, 54 }; static const int bcm4320_power_output[4] = { 25, 50, 75, 100 }; @@ -640,8 +637,8 @@ static void dsconfig_to_freq(unsigned int dsconfig, struct iw_freq *freq) static int freq_to_dsconfig(struct iw_freq *freq, unsigned int *dsconfig) { if (freq->m < 1000 && freq->e == 0) { - if (freq->m >= 1 && freq->m <= ARRAY_SIZE(freq_chan)) - *dsconfig = freq_chan[freq->m - 1] * 1000; + if (freq->m >= 1 && freq->m <= 14) + *dsconfig = ieee80211_dsss_chan_to_freq(freq->m) * 1000; else return -1; } else { @@ -1178,11 +1175,11 @@ static int rndis_iw_get_range(struct net_device *dev, range->throughput = 11 * 1000 * 1000 / 2; } - range->num_channels = ARRAY_SIZE(freq_chan); + range->num_channels = 14; - for (i = 0; i < ARRAY_SIZE(freq_chan) && i < IW_MAX_FREQUENCIES; i++) { + for (i = 0; (i < 14) && (i < IW_MAX_FREQUENCIES); i++) { range->freq[i].i = i + 1; - range->freq[i].m = freq_chan[i] * 100000; + range->freq[i].m = ieee80211_dsss_chan_to_freq(i + 1) * 100000; range->freq[i].e = 1; } range->num_frequency = i; diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index c99a1b6b948..c8d5c34e8dd 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -44,6 +44,7 @@ #include #include #include +#include #include @@ -111,12 +112,6 @@ static void wl3501_release(struct pcmcia_device *link); */ static dev_info_t wl3501_dev_info = "wl3501_cs"; -static int wl3501_chan2freq[] = { - [0] = 2412, [1] = 2417, [2] = 2422, [3] = 2427, [4] = 2432, - [5] = 2437, [6] = 2442, [7] = 2447, [8] = 2452, [9] = 2457, - [10] = 2462, [11] = 2467, [12] = 2472, [13] = 2477, -}; - static const struct { int reg_domain; int min, max, deflt; @@ -1510,7 +1505,7 @@ static int wl3501_get_freq(struct net_device *dev, struct iw_request_info *info, { struct wl3501_card *this = netdev_priv(dev); - wrqu->freq.m = wl3501_chan2freq[this->chan - 1] * 100000; + wrqu->freq.m = ieee80211_dsss_chan_to_freq(this->chan) * 100000; wrqu->freq.e = 1; return 0; } diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index b45c27d42fd..6226ac2357f 100644 --- a/drivers/net/wireless/zd1201.c +++ b/drivers/net/wireless/zd1201.c @@ -919,10 +919,9 @@ static int zd1201_set_freq(struct net_device *dev, if (freq->e == 0) channel = freq->m; else { - if (freq->m >= 2482) - channel = 14; - if (freq->m >= 2407) - channel = (freq->m-2407)/5; + channel = ieee80211_freq_to_dsss_chan(freq->m); + if (channel < 0) + channel = 0; } err = zd1201_setconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, channel); diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index c4e6ca1a630..cade2556af0 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1185,4 +1185,120 @@ static inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr) return hdr->addr1; } +/** + * ieee80211_fhss_chan_to_freq - get channel frequency + * @channel: the FHSS channel + * + * Convert IEEE802.11 FHSS channel to frequency (MHz) + * Ref IEEE 802.11-2007 section 14.6 + */ +static inline int ieee80211_fhss_chan_to_freq(int channel) +{ + if ((channel > 1) && (channel < 96)) + return channel + 2400; + else + return -1; +} + +/** + * ieee80211_freq_to_fhss_chan - get channel + * @freq: the channels frequency + * + * Convert frequency (MHz) to IEEE802.11 FHSS channel + * Ref IEEE 802.11-2007 section 14.6 + */ +static inline int ieee80211_freq_to_fhss_chan(int freq) +{ + if ((freq > 2401) && (freq < 2496)) + return freq - 2400; + else + return -1; +} + +/** + * ieee80211_dsss_chan_to_freq - get channel center frequency + * @channel: the DSSS channel + * + * Convert IEEE802.11 DSSS channel to the center frequency (MHz). + * Ref IEEE 802.11-2007 section 15.6 + */ +static inline int ieee80211_dsss_chan_to_freq(int channel) +{ + if ((channel > 0) && (channel < 14)) + return 2407 + (channel * 5); + else if (channel == 14) + return 2484; + else + return -1; +} + +/** + * ieee80211_freq_to_dsss_chan - get channel + * @freq: the frequency + * + * Convert frequency (MHz) to IEEE802.11 DSSS channel + * Ref IEEE 802.11-2007 section 15.6 + * + * This routine selects the channel with the closest center frequency. + */ +static inline int ieee80211_freq_to_dsss_chan(int freq) +{ + if ((freq >= 2410) && (freq < 2475)) + return (freq - 2405) / 5; + else if ((freq >= 2482) && (freq < 2487)) + return 14; + else + return -1; +} + +/* Convert IEEE802.11 HR DSSS channel to frequency (MHz) and back + * Ref IEEE 802.11-2007 section 18.4.6.2 + * + * The channels and frequencies are the same as those defined for DSSS + */ +#define ieee80211_hr_chan_to_freq(chan) ieee80211_dsss_chan_to_freq(chan) +#define ieee80211_freq_to_hr_chan(freq) ieee80211_freq_to_dsss_chan(freq) + +/* Convert IEEE802.11 ERP channel to frequency (MHz) and back + * Ref IEEE 802.11-2007 section 19.4.2 + */ +#define ieee80211_erp_chan_to_freq(chan) ieee80211_hr_chan_to_freq(chan) +#define ieee80211_freq_to_erp_chan(freq) ieee80211_freq_to_hr_chan(freq) + +/** + * ieee80211_ofdm_chan_to_freq - get channel center frequency + * @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz + * @channel: the OFDM channel + * + * Convert IEEE802.11 OFDM channel to center frequency (MHz) + * Ref IEEE 802.11-2007 section 17.3.8.3.2 + */ +static inline int ieee80211_ofdm_chan_to_freq(int s_freq, int channel) +{ + if ((channel > 0) && (channel <= 200) && + (s_freq >= 4000)) + return s_freq + (channel * 5); + else + return -1; +} + +/** + * ieee80211_freq_to_ofdm_channel - get channel + * @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz + * @freq: the frequency + * + * Convert frequency (MHz) to IEEE802.11 OFDM channel + * Ref IEEE 802.11-2007 section 17.3.8.3.2 + * + * This routine selects the channel with the closest center frequency. + */ +static inline int ieee80211_freq_to_ofdm_chan(int s_freq, int freq) +{ + if ((freq > (s_freq + 2)) && (freq <= (s_freq + 1202)) && + (s_freq >= 4000)) + return (freq + 2 - s_freq) / 5; + else + return -1; +} + #endif /* LINUX_IEEE80211_H */ -- GitLab From eb46936b9f2b639f4edeeaf9154d49476fc30fe5 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 23 Dec 2008 21:30:50 +0530 Subject: [PATCH 0690/4982] mac80211: Scale down to non-HT association with TKIP/WEP as pairwise cipher As TKIP is not updated to new security needs which arise when TKIP is used to encrypt A-MPDU aggregated data frames, IEEE802.11n does not allow any cipher other than CCMP (Which has new extensions defined) as pairwise cipher between HT peers. When such configuration (TKIP/WEP in HT) is forced, we still associate in non-HT mode (11a/b/g). Signed-off-by: Vasanthakumar Thiagarajan Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 1 + net/mac80211/iface.c | 3 ++- net/mac80211/mlme.c | 9 ++++++++- net/mac80211/wext.c | 12 +++++++++++- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index f3eec989662..5f8ad885a48 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -258,6 +258,7 @@ struct mesh_preq_queue { #define IEEE80211_STA_AUTO_BSSID_SEL BIT(11) #define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12) #define IEEE80211_STA_PRIVACY_INVOKED BIT(13) +#define IEEE80211_STA_TKIP_WEP_USED BIT(14) /* flags for MLME request */ #define IEEE80211_STA_REQ_SCAN 0 #define IEEE80211_STA_REQ_DIRECT_PROBE 1 diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index b9074824862..1eefc5df495 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -459,7 +459,8 @@ static int ieee80211_stop(struct net_device *dev) synchronize_rcu(); skb_queue_purge(&sdata->u.sta.skb_queue); - sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED; + sdata->u.sta.flags &= ~(IEEE80211_STA_PRIVACY_INVOKED | + IEEE80211_STA_TKIP_WEP_USED); kfree(sdata->u.sta.extra_ie); sdata->u.sta.extra_ie = NULL; sdata->u.sta.extra_ie_len = 0; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2b890af01ba..b688425d755 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -391,10 +391,17 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, } /* wmm support is a must to HT */ + /* + * IEEE802.11n does not allow TKIP/WEP as pairwise + * ciphers in HT mode. We still associate in non-ht + * mode (11a/b/g) if any one of these ciphers is + * configured as pairwise. + */ if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) && sband->ht_cap.ht_supported && (ht_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_INFORMATION)) && - ht_ie[1] >= sizeof(struct ieee80211_ht_info)) { + ht_ie[1] >= sizeof(struct ieee80211_ht_info) && + (!(ifsta->flags & IEEE80211_STA_TKIP_WEP_USED))) { struct ieee80211_ht_info *ht_info = (struct ieee80211_ht_info *)(ht_ie + 2); u16 cap = sband->ht_cap.cap; diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 7162d5816f3..011592fd452 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -903,12 +903,22 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev, switch (data->flags & IW_AUTH_INDEX) { case IW_AUTH_WPA_VERSION: - case IW_AUTH_CIPHER_PAIRWISE: case IW_AUTH_CIPHER_GROUP: case IW_AUTH_WPA_ENABLED: case IW_AUTH_RX_UNENCRYPTED_EAPOL: case IW_AUTH_KEY_MGMT: break; + case IW_AUTH_CIPHER_PAIRWISE: + if (sdata->vif.type == NL80211_IFTYPE_STATION) { + if (data->value & (IW_AUTH_CIPHER_WEP40 | + IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_TKIP)) + sdata->u.sta.flags |= + IEEE80211_STA_TKIP_WEP_USED; + else + sdata->u.sta.flags &= + ~IEEE80211_STA_TKIP_WEP_USED; + } + break; case IW_AUTH_DROP_UNENCRYPTED: sdata->drop_unencrypted = !!data->value; break; -- GitLab From d063ed0f0cd623b45edc6f4781dda6478c56bb4f Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Tue, 23 Dec 2008 18:17:19 -0800 Subject: [PATCH 0691/4982] mac80211: Reset the power save timer from master_start_xmit. When a null data frame is generated from mac80211, it goes through master_start_xmit and not through subif_start_xmit. Hence for the power save timer to be triggered while sending this null data frame also, the timer has to be reset from master_start_xmit. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- net/mac80211/tx.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 4278e545638..0bf2272200a 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1296,6 +1296,19 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } + if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) && + local->dynamic_ps_timeout > 0) { + if (local->hw.conf.flags & IEEE80211_CONF_PS) { + ieee80211_stop_queues_by_reason(&local->hw, + IEEE80211_QUEUE_STOP_REASON_PS); + queue_work(local->hw.workqueue, + &local->dynamic_ps_disable_work); + } + + mod_timer(&local->dynamic_ps_timer, jiffies + + msecs_to_jiffies(local->dynamic_ps_timeout)); + } + memset(info, 0, sizeof(*info)); info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; @@ -1475,19 +1488,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, goto fail; } - if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) && - local->dynamic_ps_timeout > 0) { - if (local->hw.conf.flags & IEEE80211_CONF_PS) { - ieee80211_stop_queues_by_reason(&local->hw, - IEEE80211_QUEUE_STOP_REASON_PS); - queue_work(local->hw.workqueue, - &local->dynamic_ps_disable_work); - } - - mod_timer(&local->dynamic_ps_timer, jiffies + - msecs_to_jiffies(local->dynamic_ps_timeout)); - } - nh_pos = skb_network_header(skb) - skb->data; h_pos = skb_transport_header(skb) - skb->data; -- GitLab From 869717fbe43eb831cbebd03a9a66a4a4c3b406a9 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Tue, 23 Dec 2008 18:28:34 -0800 Subject: [PATCH 0692/4982] mac80211: A couple of fixes to dynamic power save. a) hw_config() should not be called from siwpower() for the drivers which do not support dynamic powersave. b) IEEE80211_HW_NO_STACK_DYNAMIC_PS needs to be verified in set_associated() also before enabling the power save timers. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 3 ++- net/mac80211/wext.c | 9 +++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index b688425d755..b3c99d3c61b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -751,7 +751,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, bss_info_changed |= BSS_CHANGED_BASIC_RATES; ieee80211_bss_info_change_notify(sdata, bss_info_changed); - if (local->powersave) { + if (local->powersave && + !(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS)) { if (local->dynamic_ps_timeout > 0) mod_timer(&local->dynamic_ps_timer, jiffies + msecs_to_jiffies(local->dynamic_ps_timeout)); diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 011592fd452..8568f1e7266 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -865,9 +865,9 @@ set: local->powersave = ps; local->dynamic_ps_timeout = timeout; - if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { - if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) && - local->dynamic_ps_timeout > 0) + if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) && + (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED)) { + if (local->dynamic_ps_timeout > 0) mod_timer(&local->dynamic_ps_timer, jiffies + msecs_to_jiffies(local->dynamic_ps_timeout)); else { @@ -875,8 +875,9 @@ set: conf->flags |= IEEE80211_CONF_PS; else conf->flags &= ~IEEE80211_CONF_PS; + ret = ieee80211_hw_config(local, + IEEE80211_CONF_CHANGE_PS); } - ret = ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); } return ret; -- GitLab From a97b77b90decf27a86ac40ea53a741ffb5ead21a Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Tue, 23 Dec 2008 18:39:02 -0800 Subject: [PATCH 0693/4982] mac80211: Enhancements to dynamic power save. This patch enables mac80211 to send a null frame and also to check for tim in the beacon if dynamic power save is enabled. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 3 +++ net/mac80211/mlme.c | 41 +++++++++++++++++++++++++++++++++++++- net/mac80211/scan.c | 2 +- net/mac80211/wext.c | 13 ++++++++---- 4 files changed, 53 insertions(+), 6 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 5f8ad885a48..117718bd96e 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -987,6 +987,9 @@ u64 ieee80211_mandatory_rates(struct ieee80211_local *local, void ieee80211_dynamic_ps_enable_work(struct work_struct *work); void ieee80211_dynamic_ps_disable_work(struct work_struct *work); void ieee80211_dynamic_ps_timer(unsigned long data); +void ieee80211_send_nullfunc(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + int powersave); void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, enum queue_stop_reason reason); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index b3c99d3c61b..599a42172a1 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -575,6 +575,30 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, } } +static bool check_tim(struct ieee802_11_elems *elems, u16 aid, bool *is_mc) +{ + u8 mask; + u8 index, indexn1, indexn2; + struct ieee80211_tim_ie *tim = (struct ieee80211_tim_ie *) elems->tim; + + aid &= 0x3fff; + index = aid / 8; + mask = 1 << (aid & 7); + + if (tim->bitmap_ctrl & 0x01) + *is_mc = true; + + indexn1 = tim->bitmap_ctrl & 0xfe; + indexn2 = elems->tim_len + indexn1 - 4; + + if (index < indexn1 || index > indexn2) + return false; + + index -= indexn1; + + return !!(tim->virtual_map[index] & mask); +} + static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, u16 capab, bool erp_valid, u8 erp) { @@ -757,6 +781,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, mod_timer(&local->dynamic_ps_timer, jiffies + msecs_to_jiffies(local->dynamic_ps_timeout)); else { + ieee80211_send_nullfunc(local, sdata, 1); conf->flags |= IEEE80211_CONF_PS; ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); @@ -1720,7 +1745,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, struct ieee802_11_elems elems; struct ieee80211_local *local = sdata->local; u32 changed = 0; - bool erp_valid; + bool erp_valid, directed_tim, is_mc = false; u8 erp_value = 0; /* Process beacon from the current BSS */ @@ -1743,6 +1768,18 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, elems.wmm_param_len); + if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS)) { + directed_tim = check_tim(&elems, ifsta->aid, &is_mc); + + if (directed_tim || is_mc) { + if (local->hw.conf.flags && IEEE80211_CONF_PS) { + local->hw.conf.flags &= ~IEEE80211_CONF_PS; + ieee80211_hw_config(local, + IEEE80211_CONF_CHANGE_PS); + ieee80211_send_nullfunc(local, sdata, 0); + } + } + } if (elems.erp_info && elems.erp_info_len >= 1) { erp_valid = true; @@ -2631,10 +2668,12 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) struct ieee80211_local *local = container_of(work, struct ieee80211_local, dynamic_ps_enable_work); + struct ieee80211_sub_if_data *sdata = local->scan_sdata; if (local->hw.conf.flags & IEEE80211_CONF_PS) return; + ieee80211_send_nullfunc(local, sdata, 1); local->hw.conf.flags |= IEEE80211_CONF_PS; ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index f5c7c337192..a2caeed57f4 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -395,7 +395,7 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, return RX_QUEUED; } -static void ieee80211_send_nullfunc(struct ieee80211_local *local, +void ieee80211_send_nullfunc(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, int powersave) { diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 8568f1e7266..48fc6b9a62a 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -871,12 +871,17 @@ set: mod_timer(&local->dynamic_ps_timer, jiffies + msecs_to_jiffies(local->dynamic_ps_timeout)); else { - if (local->powersave) + if (local->powersave) { + ieee80211_send_nullfunc(local, sdata, 1); conf->flags |= IEEE80211_CONF_PS; - else + ret = ieee80211_hw_config(local, + IEEE80211_CONF_CHANGE_PS); + } else { conf->flags &= ~IEEE80211_CONF_PS; - ret = ieee80211_hw_config(local, - IEEE80211_CONF_CHANGE_PS); + ret = ieee80211_hw_config(local, + IEEE80211_CONF_CHANGE_PS); + ieee80211_send_nullfunc(local, sdata, 0); + } } } -- GitLab From 7cbf0ba5193d1f3bb3caaa06668e22bc86776e41 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Wed, 24 Dec 2008 00:34:37 -0800 Subject: [PATCH 0694/4982] mac80211: Cancel the power save timer in ieee80211_stop. Since the station info is flushed before calling set_disassoc in ieee80211_stop, the power save timer is never cancelled when the driver is unloaded. Hence the timer cancellation has to be done in ieee80211_stop itself. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- net/mac80211/iface.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 1eefc5df495..8e0e3303ca8 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -383,6 +383,8 @@ static int ieee80211_stop(struct net_device *dev) atomic_dec(&local->iff_promiscs); dev_mc_unsync(local->mdev, dev); + del_timer_sync(&local->dynamic_ps_timer); + cancel_work_sync(&local->dynamic_ps_enable_work); /* APs need special treatment */ if (sdata->vif.type == NL80211_IFTYPE_AP) { -- GitLab From bddadf86fb284f237d6e2d3496772c8f5c68370e Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 19 Dec 2008 10:37:01 +0800 Subject: [PATCH 0695/4982] iwlwifi: 3945 extract flow handler definitions into iwl-3945-fh.h This patch moves 3945 definitions into iwl-3945-fh.h It renames FH_ to FH39 to help inclusion of 3945 into iwlcore framework Signed-off-by: Tomas Winkler Acked-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-fh.h | 178 ++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 101 ----------- drivers/net/wireless/iwlwifi/iwl-3945.c | 83 ++++----- drivers/net/wireless/iwlwifi/iwl-3945.h | 3 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 10 +- 5 files changed, 226 insertions(+), 149 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-3945-fh.h diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-fh.h b/drivers/net/wireless/iwlwifi/iwl-3945-fh.h new file mode 100644 index 00000000000..bbcd0cefc72 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-3945-fh.h @@ -0,0 +1,178 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef __iwl_3945_fh_h__ +#define __iwl_3945_fh_h__ + +/************************************/ +/* iwl3945 Flow Handler Definitions */ +/************************************/ + +/** + * This I/O area is directly read/writable by driver (e.g. Linux uses writel()) + * Addresses are offsets from device's PCI hardware base address. + */ +#define FH39_MEM_LOWER_BOUND (0x0800) +#define FH39_MEM_UPPER_BOUND (0x1000) + +#define FH39_CBCC_TABLE (FH39_MEM_LOWER_BOUND + 0x140) +#define FH39_TFDB_TABLE (FH39_MEM_LOWER_BOUND + 0x180) +#define FH39_RCSR_TABLE (FH39_MEM_LOWER_BOUND + 0x400) +#define FH39_RSSR_TABLE (FH39_MEM_LOWER_BOUND + 0x4c0) +#define FH39_TCSR_TABLE (FH39_MEM_LOWER_BOUND + 0x500) +#define FH39_TSSR_TABLE (FH39_MEM_LOWER_BOUND + 0x680) + +/* TFDB (Transmit Frame Buffer Descriptor) */ +#define FH39_TFDB(_ch, buf) (FH39_TFDB_TABLE + \ + ((_ch) * 2 + (buf)) * 0x28) +#define FH39_TFDB_CHNL_BUF_CTRL_REG(_ch) (FH39_TFDB_TABLE + 0x50 * (_ch)) + +/* CBCC channel is [0,2] */ +#define FH39_CBCC(_ch) (FH39_CBCC_TABLE + (_ch) * 0x8) +#define FH39_CBCC_CTRL(_ch) (FH39_CBCC(_ch) + 0x00) +#define FH39_CBCC_BASE(_ch) (FH39_CBCC(_ch) + 0x04) + +/* RCSR channel is [0,2] */ +#define FH39_RCSR(_ch) (FH39_RCSR_TABLE + (_ch) * 0x40) +#define FH39_RCSR_CONFIG(_ch) (FH39_RCSR(_ch) + 0x00) +#define FH39_RCSR_RBD_BASE(_ch) (FH39_RCSR(_ch) + 0x04) +#define FH39_RCSR_WPTR(_ch) (FH39_RCSR(_ch) + 0x20) +#define FH39_RCSR_RPTR_ADDR(_ch) (FH39_RCSR(_ch) + 0x24) + +#define FH39_RSCSR_CHNL0_WPTR (FH39_RCSR_WPTR(0)) + +/* RSSR */ +#define FH39_RSSR_CTRL (FH39_RSSR_TABLE + 0x000) +#define FH39_RSSR_STATUS (FH39_RSSR_TABLE + 0x004) + +/* TCSR */ +#define FH39_TCSR(_ch) (FH39_TCSR_TABLE + (_ch) * 0x20) +#define FH39_TCSR_CONFIG(_ch) (FH39_TCSR(_ch) + 0x00) +#define FH39_TCSR_CREDIT(_ch) (FH39_TCSR(_ch) + 0x04) +#define FH39_TCSR_BUFF_STTS(_ch) (FH39_TCSR(_ch) + 0x08) + +/* TSSR */ +#define FH39_TSSR_CBB_BASE (FH39_TSSR_TABLE + 0x000) +#define FH39_TSSR_MSG_CONFIG (FH39_TSSR_TABLE + 0x008) +#define FH39_TSSR_TX_STATUS (FH39_TSSR_TABLE + 0x010) + + +/* DBM */ + +#define FH39_SRVC_CHNL (6) + +#define FH39_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE (20) +#define FH39_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH (4) + +#define FH39_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN (0x08000000) + +#define FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE (0x80000000) + +#define FH39_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE (0x20000000) + +#define FH39_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128 (0x01000000) + +#define FH39_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST (0x00001000) + +#define FH39_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH (0x00000000) + +#define FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF (0x00000000) +#define FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRIVER (0x00000001) + +#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL (0x00000000) +#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL (0x00000008) + +#define FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD (0x00200000) + +#define FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT (0x00000000) + +#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE (0x00000000) +#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE (0x80000000) + +#define FH39_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID (0x00004000) + +#define FH39_TCSR_CHNL_TX_BUF_STS_REG_BIT_TFDB_WPTR (0x00000001) + +#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON (0xFF000000) +#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON (0x00FF0000) + +#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B (0x00000400) + +#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON (0x00000100) +#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON (0x00000080) + +#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH (0x00000020) +#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH (0x00000005) + +#define FH39_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_ch) (BIT(_ch) << 24) +#define FH39_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_ch) (BIT(_ch) << 16) + +#define FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_ch) \ + (FH39_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_ch) | \ + FH39_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_ch)) + +#define FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (0x01000000) + +#define TFD_QUEUE_SIZE_MAX (256) + +#endif /* __iwl_3945_fh_h__ */ + diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 94ea0e60c41..1df385b7c39 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -288,107 +288,6 @@ struct iwl3945_eeprom { #define PCI_REG_WUM8 0x0E8 #define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT (0x80000000) -/*=== FH (data Flow Handler) ===*/ -#define FH_BASE (0x800) - -#define FH_CBCC_TABLE (FH_BASE+0x140) -#define FH_TFDB_TABLE (FH_BASE+0x180) -#define FH_RCSR_TABLE (FH_BASE+0x400) -#define FH_RSSR_TABLE (FH_BASE+0x4c0) -#define FH_TCSR_TABLE (FH_BASE+0x500) -#define FH_TSSR_TABLE (FH_BASE+0x680) - -/* TFDB (Transmit Frame Buffer Descriptor) */ -#define FH_TFDB(_channel, buf) \ - (FH_TFDB_TABLE+((_channel)*2+(buf))*0x28) -#define ALM_FH_TFDB_CHNL_BUF_CTRL_REG(_channel) \ - (FH_TFDB_TABLE + 0x50 * _channel) -/* CBCC _channel is [0,2] */ -#define FH_CBCC(_channel) (FH_CBCC_TABLE+(_channel)*0x8) -#define FH_CBCC_CTRL(_channel) (FH_CBCC(_channel)+0x00) -#define FH_CBCC_BASE(_channel) (FH_CBCC(_channel)+0x04) - -/* RCSR _channel is [0,2] */ -#define FH_RCSR(_channel) (FH_RCSR_TABLE+(_channel)*0x40) -#define FH_RCSR_CONFIG(_channel) (FH_RCSR(_channel)+0x00) -#define FH_RCSR_RBD_BASE(_channel) (FH_RCSR(_channel)+0x04) -#define FH_RCSR_WPTR(_channel) (FH_RCSR(_channel)+0x20) -#define FH_RCSR_RPTR_ADDR(_channel) (FH_RCSR(_channel)+0x24) - -#define FH_RSCSR_CHNL0_WPTR (FH_RCSR_WPTR(0)) - -/* RSSR */ -#define FH_RSSR_CTRL (FH_RSSR_TABLE+0x000) -#define FH_RSSR_STATUS (FH_RSSR_TABLE+0x004) -#define FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (0x01000000) -/* TCSR */ -#define FH_TCSR(_channel) (FH_TCSR_TABLE+(_channel)*0x20) -#define FH_TCSR_CONFIG(_channel) (FH_TCSR(_channel)+0x00) -#define FH_TCSR_CREDIT(_channel) (FH_TCSR(_channel)+0x04) -#define FH_TCSR_BUFF_STTS(_channel) (FH_TCSR(_channel)+0x08) -/* TSSR */ -#define FH_TSSR_CBB_BASE (FH_TSSR_TABLE+0x000) -#define FH_TSSR_MSG_CONFIG (FH_TSSR_TABLE+0x008) -#define FH_TSSR_TX_STATUS (FH_TSSR_TABLE+0x010) - - -/* DBM */ - -#define ALM_FH_SRVC_CHNL (6) - -#define ALM_FH_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE (20) -#define ALM_FH_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH (4) - -#define ALM_FH_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN (0x08000000) - -#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE (0x80000000) - -#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE (0x20000000) - -#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128 (0x01000000) - -#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST (0x00001000) - -#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH (0x00000000) - -#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF (0x00000000) -#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRIVER (0x00000001) - -#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL (0x00000000) -#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL (0x00000008) - -#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD (0x00200000) - -#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT (0x00000000) - -#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE (0x00000000) -#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE (0x80000000) - -#define ALM_FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID (0x00004000) - -#define ALM_FH_TCSR_CHNL_TX_BUF_STS_REG_BIT_TFDB_WPTR (0x00000001) - -#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON (0xFF000000) -#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON (0x00FF0000) - -#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B (0x00000400) - -#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON (0x00000100) -#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON (0x00000080) - -#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH (0x00000020) -#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH (0x00000005) - -#define ALM_TB_MAX_BYTES_COUNT (0xFFF0) - -#define ALM_FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_channel) \ - ((1LU << _channel) << 24) -#define ALM_FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_channel) \ - ((1LU << _channel) << 16) - -#define ALM_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_channel) \ - (ALM_FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_channel) | \ - ALM_FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_channel)) #define PCI_CFG_REV_ID_BIT_BASIC_SKU (0x40) /* bit 6 */ #define PCI_CFG_REV_ID_BIT_RTP (0x80) /* bit 7 */ diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 45cfa1cf194..f4fee0a91b6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -39,6 +39,7 @@ #include #include "iwl-3945-core.h" +#include "iwl-3945-fh.h" #include "iwl-3945.h" #include "iwl-helpers.h" #include "iwl-3945-rs.h" @@ -984,23 +985,23 @@ static int iwl3945_rx_init(struct iwl3945_priv *priv, struct iwl3945_rx_queue *r return rc; } - iwl3945_write_direct32(priv, FH_RCSR_RBD_BASE(0), rxq->dma_addr); - iwl3945_write_direct32(priv, FH_RCSR_RPTR_ADDR(0), + iwl3945_write_direct32(priv, FH39_RCSR_RBD_BASE(0), rxq->dma_addr); + iwl3945_write_direct32(priv, FH39_RCSR_RPTR_ADDR(0), priv->hw_setting.shared_phys + offsetof(struct iwl3945_shared, rx_read_ptr[0])); - iwl3945_write_direct32(priv, FH_RCSR_WPTR(0), 0); - iwl3945_write_direct32(priv, FH_RCSR_CONFIG(0), - ALM_FH_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE | - ALM_FH_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE | - ALM_FH_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN | - ALM_FH_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128 | - (RX_QUEUE_SIZE_LOG << ALM_FH_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE) | - ALM_FH_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST | - (1 << ALM_FH_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH) | - ALM_FH_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH); + iwl3945_write_direct32(priv, FH39_RCSR_WPTR(0), 0); + iwl3945_write_direct32(priv, FH39_RCSR_CONFIG(0), + FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE | + FH39_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE | + FH39_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN | + FH39_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128 | + (RX_QUEUE_SIZE_LOG << FH39_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE) | + FH39_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST | + (1 << FH39_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH) | + FH39_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH); /* fake read to flush all prev I/O */ - iwl3945_read_direct32(priv, FH_RSSR_CTRL); + iwl3945_read_direct32(priv, FH39_RSSR_CTRL); iwl3945_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); @@ -1034,17 +1035,17 @@ static int iwl3945_tx_reset(struct iwl3945_priv *priv) iwl3945_write_prph(priv, ALM_SCD_TXF4MF_REG, 0x000004); iwl3945_write_prph(priv, ALM_SCD_TXF5MF_REG, 0x000005); - iwl3945_write_direct32(priv, FH_TSSR_CBB_BASE, + iwl3945_write_direct32(priv, FH39_TSSR_CBB_BASE, priv->hw_setting.shared_phys); - iwl3945_write_direct32(priv, FH_TSSR_MSG_CONFIG, - ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON | - ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON | - ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B | - ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON | - ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON | - ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH | - ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH); + iwl3945_write_direct32(priv, FH39_TSSR_MSG_CONFIG, + FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON | + FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON | + FH39_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B | + FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON | + FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON | + FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH | + FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH); iwl3945_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); @@ -1210,7 +1211,7 @@ int iwl3945_hw_nic_init(struct iwl3945_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); return rc; } - iwl3945_write_direct32(priv, FH_RCSR_WPTR(0), rxq->write & ~7); + iwl3945_write_direct32(priv, FH39_RCSR_WPTR(0), rxq->write & ~7); iwl3945_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); @@ -1240,7 +1241,7 @@ void iwl3945_hw_txq_ctx_free(struct iwl3945_priv *priv) void iwl3945_hw_txq_ctx_stop(struct iwl3945_priv *priv) { - int queue; + int txq_id; unsigned long flags; spin_lock_irqsave(&priv->lock, flags); @@ -1254,10 +1255,10 @@ void iwl3945_hw_txq_ctx_stop(struct iwl3945_priv *priv) iwl3945_write_prph(priv, ALM_SCD_MODE_REG, 0); /* reset TFD queues */ - for (queue = TFD_QUEUE_MIN; queue < TFD_QUEUE_MAX; queue++) { - iwl3945_write_direct32(priv, FH_TCSR_CONFIG(queue), 0x0); - iwl3945_poll_direct_bit(priv, FH_TSSR_TX_STATUS, - ALM_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(queue), + for (txq_id = 0; txq_id < TFD_QUEUE_MAX; txq_id++) { + iwl3945_write_direct32(priv, FH39_TCSR_CONFIG(txq_id), 0x0); + iwl3945_poll_direct_bit(priv, FH39_TSSR_TX_STATUS, + FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id), 1000); } @@ -2307,9 +2308,9 @@ int iwl3945_hw_rxq_stop(struct iwl3945_priv *priv) return rc; } - iwl3945_write_direct32(priv, FH_RCSR_CONFIG(0), 0); - rc = iwl3945_poll_direct_bit(priv, FH_RSSR_STATUS, - FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); + iwl3945_write_direct32(priv, FH39_RCSR_CONFIG(0), 0); + rc = iwl3945_poll_direct_bit(priv, FH39_RSSR_STATUS, + FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); if (rc < 0) IWL_ERROR("Can't stop Rx DMA.\n"); @@ -2335,19 +2336,19 @@ int iwl3945_hw_tx_queue_init(struct iwl3945_priv *priv, struct iwl3945_tx_queue spin_unlock_irqrestore(&priv->lock, flags); return rc; } - iwl3945_write_direct32(priv, FH_CBCC_CTRL(txq_id), 0); - iwl3945_write_direct32(priv, FH_CBCC_BASE(txq_id), 0); - - iwl3945_write_direct32(priv, FH_TCSR_CONFIG(txq_id), - ALM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT | - ALM_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF | - ALM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD | - ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL | - ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE); + iwl3945_write_direct32(priv, FH39_CBCC_CTRL(txq_id), 0); + iwl3945_write_direct32(priv, FH39_CBCC_BASE(txq_id), 0); + + iwl3945_write_direct32(priv, FH39_TCSR_CONFIG(txq_id), + FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT | + FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF | + FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD | + FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL | + FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE); iwl3945_release_nic_access(priv); /* fake read to flush all prev. writes */ - iwl3945_read32(priv, FH_TSSR_CBB_BASE); + iwl3945_read32(priv, FH39_TSSR_CBB_BASE); spin_unlock_irqrestore(&priv->lock, flags); return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 2c0ddc5110c..d8f40bdb316 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -691,7 +691,6 @@ static inline void iwl3945_rfkill_unregister(struct iwl3945_priv *priv) {} static inline int iwl3945_rfkill_init(struct iwl3945_priv *priv) { return 0; } #endif -#define IWL_MAX_NUM_QUEUES IWL39_MAX_NUM_QUEUES struct iwl3945_priv { @@ -815,7 +814,7 @@ struct iwl3945_priv { /* Rx and Tx DMA processing queues */ struct iwl3945_rx_queue rxq; - struct iwl3945_tx_queue txq[IWL_MAX_NUM_QUEUES]; + struct iwl3945_tx_queue txq[IWL39_MAX_NUM_QUEUES]; unsigned long status; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 95d01984c80..fee3e93ca56 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -48,6 +48,7 @@ #include "iwl-3945-core.h" #include "iwl-3945.h" +#include "iwl-3945-fh.h" #include "iwl-helpers.h" #ifdef CONFIG_IWL3945_DEBUG @@ -3479,14 +3480,14 @@ int iwl3945_rx_queue_update_write_ptr(struct iwl3945_priv *priv, struct iwl3945_ goto exit_unlock; /* Device expects a multiple of 8 */ - iwl3945_write_direct32(priv, FH_RSCSR_CHNL0_WPTR, + iwl3945_write_direct32(priv, FH39_RSCSR_CHNL0_WPTR, q->write & ~0x7); iwl3945_release_nic_access(priv); /* Else device is assumed to be awake */ } else /* Device expects a multiple of 8 */ - iwl3945_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7); + iwl3945_write32(priv, FH39_RSCSR_CHNL0_WPTR, q->write & ~0x7); q->need_update = 0; @@ -4339,9 +4340,8 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv) iwl3945_write32(priv, CSR_FH_INT_STATUS, (1 << 6)); if (!iwl3945_grab_nic_access(priv)) { - iwl3945_write_direct32(priv, - FH_TCSR_CREDIT - (ALM_FH_SRVC_CHNL), 0x0); + iwl3945_write_direct32(priv, FH39_TCSR_CREDIT + (FH39_SRVC_CHNL), 0x0); iwl3945_release_nic_access(priv); } handled |= CSR_INT_BIT_FH_TX; -- GitLab From 69d00d2722e7478e590e40b1a8b791b4aeea195f Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 19 Dec 2008 10:37:02 +0800 Subject: [PATCH 0696/4982] iwlwifi: 3945 unfold iwl-3945-commands.h This patch unfolds includes of iwl-3945-commands.h Signed-off-by: Tomas Winkler Acked-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-commands.h | 5 +++++ drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 10 +--------- drivers/net/wireless/iwlwifi/iwl-3945-led.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 1 + drivers/net/wireless/iwlwifi/iwl-3945.c | 1 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 1 + 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h index c6f4eb54a2b..e9ccd07db8d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h @@ -144,6 +144,11 @@ enum { REPLY_MAX = 0xff }; +/* Tx rates */ +#define IWL_CCK_RATES 4 +#define IWL_OFDM_RATES 8 +#define IWL_MAX_RATES (IWL_CCK_RATES + IWL_OFDM_RATES) + /****************************************************************************** * (0) * Commonly used structures and definitions: diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 1df385b7c39..21719eb7e14 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -73,13 +73,7 @@ * uCode queue management definitions ... * Queue #4 is the command queue for 3945 and 4965. */ -#define IWL_CMD_QUEUE_NUM 4 - -/* Tx rates */ -#define IWL_CCK_RATES 4 -#define IWL_OFDM_RATES 8 -#define IWL_HT_RATES 0 -#define IWL_MAX_RATES (IWL_CCK_RATES+IWL_OFDM_RATES+IWL_HT_RATES) +#define IWL_CMD_QUEUE_NUM 4 /* Time constants */ #define SHORT_SLOT_TIME 9 @@ -281,8 +275,6 @@ struct iwl3945_eeprom { /* End of EEPROM */ -#include "iwl-3945-commands.h" - #define PCI_LINK_CTRL 0x0F0 #define PCI_POWER_SOURCE 0x0C8 #define PCI_REG_WUM8 0x0E8 diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index 4c638909a7d..b0d420f68ec 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -38,8 +38,8 @@ #include #include +#include "iwl-3945-commands.h" #include "iwl-3945.h" -#include "iwl-helpers.h" static const struct { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 21c841847d8..56226032333 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -36,6 +36,7 @@ #include +#include "iwl-3945-commands.h" #include "iwl-3945.h" #define RS_NAME "iwl-3945-rs" diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index f4fee0a91b6..5a316d501c3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -40,6 +40,7 @@ #include "iwl-3945-core.h" #include "iwl-3945-fh.h" +#include "iwl-3945-commands.h" #include "iwl-3945.h" #include "iwl-helpers.h" #include "iwl-3945-rs.h" diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index fee3e93ca56..541cdbe8172 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -47,6 +47,7 @@ #include #include "iwl-3945-core.h" +#include "iwl-3945-commands.h" #include "iwl-3945.h" #include "iwl-3945-fh.h" #include "iwl-helpers.h" -- GitLab From b936d9be05d66172b2c035eaca002a134f078c64 Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Fri, 19 Dec 2008 10:37:03 +0800 Subject: [PATCH 0697/4982] iwlwifi: 3945 remove current_rate from station entry. This patch removes current_rate from station_entry it was write only variable Signed-off-by: Tomas Winkler Acked-by: Samuel Ortiz Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 13 ------------- drivers/net/wireless/iwlwifi/iwl-3945.h | 7 ------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 -- 3 files changed, 22 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 5a316d501c3..c16640ddd3d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -831,7 +831,6 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv, struct ieee80211_tx_info *info, struct ieee80211_hdr *hdr, int sta_id, int tx_id) { - unsigned long flags; u16 hw_value = ieee80211_get_tx_rate(priv->hw, info)->hw_value; u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT - 1); u16 rate_mask; @@ -848,17 +847,6 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv, * in this running context */ rate_mask = IWL_RATES_MASK; - spin_lock_irqsave(&priv->sta_lock, flags); - - priv->stations[sta_id].current_rate.rate_n_flags = rate; - - if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && - (sta_id != priv->hw_setting.bcast_sta_id) && - (sta_id != IWL_MULTICAST_ID)) - priv->stations[IWL_STA_ID].current_rate.rate_n_flags = rate; - - spin_unlock_irqrestore(&priv->sta_lock, flags); - if (tx_id >= IWL_CMD_QUEUE_NUM) rts_retry_limit = 3; else @@ -921,7 +909,6 @@ u8 iwl3945_sync_sta(struct iwl3945_priv *priv, int sta_id, u16 tx_rate, u8 flags station->sta.sta.modify_mask = STA_MODIFY_TX_RATE_MSK; station->sta.rate_n_flags = cpu_to_le16(tx_rate); - station->current_rate.rate_n_flags = tx_rate; station->sta.mode = STA_CONTROL_MODIFY_MSK; spin_unlock_irqrestore(&priv->sta_lock, flags_spin); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index d8f40bdb316..d07aafe5ccc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -481,13 +481,6 @@ struct iwl3945_qos_info { struct iwl3945_station_entry { struct iwl3945_addsta_cmd sta; struct iwl3945_tid_data tid[MAX_TID_COUNT]; - union { - struct { - u8 rate; - u8 flags; - } s; - u16 rate_n_flags; - } current_rate; u8 used; u8 ps_status; struct iwl3945_hw_key keyinfo; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 541cdbe8172..d5fb65e5434 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -462,8 +462,6 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8 /* Turn on both antennas for the station... */ station->sta.rate_n_flags = iwl3945_hw_set_rate_n_flags(rate, RATE_MCS_ANT_AB_MSK); - station->current_rate.rate_n_flags = - le16_to_cpu(station->sta.rate_n_flags); spin_unlock_irqrestore(&priv->sta_lock, flags_spin); -- GitLab From 600c0e11ea6161e00e8cb4b4dda39a64ce988c60 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 19 Dec 2008 10:37:04 +0800 Subject: [PATCH 0698/4982] iwlwifi: use iwl-commands.h also in 3945 This patch uses iwl-commands.h also for iwl3945 more clean ups are required but this get to stage where it compiles cleanly. Most massive changes are in spectrum and power managment. Signed-off-by: Tomas Winkler Acked-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- .../net/wireless/iwlwifi/iwl-3945-commands.h | 426 +----------------- drivers/net/wireless/iwlwifi/iwl-3945-led.c | 1 + drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 1 + drivers/net/wireless/iwlwifi/iwl-3945.c | 1 + drivers/net/wireless/iwlwifi/iwl-3945.h | 12 +- drivers/net/wireless/iwlwifi/iwl-commands.h | 31 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 31 +- 7 files changed, 61 insertions(+), 442 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h index e9ccd07db8d..acc584f4377 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h @@ -75,74 +75,6 @@ #define IWL_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8) #define IWL_UCODE_SERIAL(ver) ((ver) & 0x000000FF) -enum { - REPLY_ALIVE = 0x1, - REPLY_ERROR = 0x2, - - /* RXON and QOS commands */ - REPLY_RXON = 0x10, - REPLY_RXON_ASSOC = 0x11, - REPLY_QOS_PARAM = 0x13, - REPLY_RXON_TIMING = 0x14, - - /* Multi-Station support */ - REPLY_ADD_STA = 0x18, - REPLY_REMOVE_STA = 0x19, /* not used */ - REPLY_REMOVE_ALL_STA = 0x1a, /* not used */ - - /* RX, TX, LEDs */ - REPLY_3945_RX = 0x1b, /* 3945 only */ - REPLY_TX = 0x1c, - REPLY_RATE_SCALE = 0x47, /* 3945 only */ - REPLY_LEDS_CMD = 0x48, - REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* 4965 only */ - - /* 802.11h related */ - RADAR_NOTIFICATION = 0x70, /* not used */ - REPLY_QUIET_CMD = 0x71, /* not used */ - REPLY_CHANNEL_SWITCH = 0x72, - CHANNEL_SWITCH_NOTIFICATION = 0x73, - REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74, - SPECTRUM_MEASURE_NOTIFICATION = 0x75, - - /* Power Management */ - POWER_TABLE_CMD = 0x77, - PM_SLEEP_NOTIFICATION = 0x7A, - PM_DEBUG_STATISTIC_NOTIFIC = 0x7B, - - /* Scan commands and notifications */ - REPLY_SCAN_CMD = 0x80, - REPLY_SCAN_ABORT_CMD = 0x81, - SCAN_START_NOTIFICATION = 0x82, - SCAN_RESULTS_NOTIFICATION = 0x83, - SCAN_COMPLETE_NOTIFICATION = 0x84, - - /* IBSS/AP commands */ - BEACON_NOTIFICATION = 0x90, - REPLY_TX_BEACON = 0x91, - WHO_IS_AWAKE_NOTIFICATION = 0x94, /* not used */ - - /* Miscellaneous commands */ - QUIET_NOTIFICATION = 0x96, /* not used */ - REPLY_TX_PWR_TABLE_CMD = 0x97, - MEASURE_ABORT_NOTIFICATION = 0x99, /* not used */ - - /* Bluetooth device coexistence config command */ - REPLY_BT_CONFIG = 0x9b, - - /* Statistics */ - REPLY_STATISTICS_CMD = 0x9c, - STATISTICS_NOTIFICATION = 0x9d, - - /* RF-KILL commands and notifications */ - REPLY_CARD_STATE_CMD = 0xa0, - CARD_STATE_NOTIFICATION = 0xa1, - - /* Missed beacons notification */ - MISSED_BEACONS_NOTIFICATION = 0xa2, - - REPLY_MAX = 0xff -}; /* Tx rates */ #define IWL_CCK_RATES 4 @@ -320,17 +252,6 @@ struct iwl3945_error_resp { * *****************************************************************************/ -/* - * Rx config defines & structure - */ -/* rx_config device types */ -enum { - RXON_DEV_TYPE_AP = 1, - RXON_DEV_TYPE_ESS = 3, - RXON_DEV_TYPE_IBSS = 4, - RXON_DEV_TYPE_SNIFFER = 6, -}; - /* rx_config flags */ /* band & modulation selection */ #define RXON_FLG_BAND_24G_MSK cpu_to_le32(1 << 0) @@ -546,18 +467,6 @@ struct iwl3945_qosparam_cmd { #define STA_MODIFY_TID_DISABLE_TX 0x02 #define STA_MODIFY_TX_RATE_MSK 0x04 -/* - * Antenna masks: - * bit14:15 01 B inactive, A active - * 10 B active, A inactive - * 11 Both active - */ -#define RATE_MCS_ANT_A_POS 14 -#define RATE_MCS_ANT_B_POS 15 -#define RATE_MCS_ANT_A_MSK 0x4000 -#define RATE_MCS_ANT_B_MSK 0x8000 -#define RATE_MCS_ANT_AB_MSK 0xc000 - struct iwl3945_keyinfo { __le16 key_flags; u8 tkip_rx_tsc_byte2; /* TSC[2] for key mix ph1 detection */ @@ -568,26 +477,6 @@ struct iwl3945_keyinfo { u8 key[16]; /* 16-byte unicast decryption key */ } __attribute__ ((packed)); -/** - * struct sta_id_modify - * @addr[ETH_ALEN]: station's MAC address - * @sta_id: index of station in uCode's station table - * @modify_mask: STA_MODIFY_*, 1: modify, 0: don't change - * - * Driver selects unused table index when adding new station, - * or the index to a pre-existing station entry when modifying that station. - * Some indexes have special purposes (IWL_AP_ID, index 0, is for AP). - * - * modify_mask flags select which parameters to modify vs. leave alone. - */ -struct sta_id_modify { - u8 addr[ETH_ALEN]; - __le16 reserved1; - u8 sta_id; - u8 modify_mask; - __le16 reserved2; -} __attribute__ ((packed)); - /* * REPLY_ADD_STA = 0x18 (command) * @@ -881,73 +770,6 @@ struct iwl3945_tx_cmd { struct ieee80211_hdr hdr[0]; } __attribute__ ((packed)); -/* TX command response is sent after *all* transmission attempts. - * - * NOTES: - * - * TX_STATUS_FAIL_NEXT_FRAG - * - * If the fragment flag in the MAC header for the frame being transmitted - * is set and there is insufficient time to transmit the next frame, the - * TX status will be returned with 'TX_STATUS_FAIL_NEXT_FRAG'. - * - * TX_STATUS_FIFO_UNDERRUN - * - * Indicates the host did not provide bytes to the FIFO fast enough while - * a TX was in progress. - * - * TX_STATUS_FAIL_MGMNT_ABORT - * - * This status is only possible if the ABORT ON MGMT RX parameter was - * set to true with the TX command. - * - * If the MSB of the status parameter is set then an abort sequence is - * required. This sequence consists of the host activating the TX Abort - * control line, and then waiting for the TX Abort command response. This - * indicates that a the device is no longer in a transmit state, and that the - * command FIFO has been cleared. The host must then deactivate the TX Abort - * control line. Receiving is still allowed in this case. - */ -enum { - TX_STATUS_SUCCESS = 0x01, - TX_STATUS_DIRECT_DONE = 0x02, - TX_STATUS_FAIL_SHORT_LIMIT = 0x82, - TX_STATUS_FAIL_LONG_LIMIT = 0x83, - TX_STATUS_FAIL_FIFO_UNDERRUN = 0x84, - TX_STATUS_FAIL_MGMNT_ABORT = 0x85, - TX_STATUS_FAIL_NEXT_FRAG = 0x86, - TX_STATUS_FAIL_LIFE_EXPIRE = 0x87, - TX_STATUS_FAIL_DEST_PS = 0x88, - TX_STATUS_FAIL_ABORTED = 0x89, - TX_STATUS_FAIL_BT_RETRY = 0x8a, - TX_STATUS_FAIL_STA_INVALID = 0x8b, - TX_STATUS_FAIL_FRAG_DROPPED = 0x8c, - TX_STATUS_FAIL_TID_DISABLE = 0x8d, - TX_STATUS_FAIL_FRAME_FLUSHED = 0x8e, - TX_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f, - TX_STATUS_FAIL_TX_LOCKED = 0x90, - TX_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91, -}; - -#define TX_PACKET_MODE_REGULAR 0x0000 -#define TX_PACKET_MODE_BURST_SEQ 0x0100 -#define TX_PACKET_MODE_BURST_FIRST 0x0200 - -enum { - TX_POWER_PA_NOT_ACTIVE = 0x0, -}; - -enum { - TX_STATUS_MSK = 0x000000ff, /* bits 0:7 */ - TX_STATUS_DELAY_MSK = 0x00000040, - TX_STATUS_ABORT_MSK = 0x00000080, - TX_PACKET_MODE_MSK = 0x0000ff00, /* bits 8:15 */ - TX_FIFO_NUMBER_MSK = 0x00070000, /* bits 16:18 */ - TX_RESERVED = 0x00780000, /* bits 19:22 */ - TX_POWER_PA_DETECT_MSK = 0x7f800000, /* bits 23:30 */ - TX_ABORT_REQUIRED_MSK = 0x80000000, /* bits 31:31 */ -}; - /* * REPLY_TX = 0x1c (response) */ @@ -1038,191 +860,6 @@ struct iwl3945_measure_channel { __le16 reserved; } __attribute__ ((packed)); -/* - * REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (command) - */ -struct iwl3945_spectrum_cmd { - __le16 len; /* number of bytes starting from token */ - u8 token; /* token id */ - u8 id; /* measurement id -- 0 or 1 */ - u8 origin; /* 0 = TGh, 1 = other, 2 = TGk */ - u8 periodic; /* 1 = periodic */ - __le16 path_loss_timeout; - __le32 start_time; /* start time in extended beacon format */ - __le32 reserved2; - __le32 flags; /* rxon flags */ - __le32 filter_flags; /* rxon filter flags */ - __le16 channel_count; /* minimum 1, maximum 10 */ - __le16 reserved3; - struct iwl3945_measure_channel channels[10]; -} __attribute__ ((packed)); - -/* - * REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (response) - */ -struct iwl3945_spectrum_resp { - u8 token; - u8 id; /* id of the prior command replaced, or 0xff */ - __le16 status; /* 0 - command will be handled - * 1 - cannot handle (conflicts with another - * measurement) */ -} __attribute__ ((packed)); - -enum iwl3945_measurement_state { - IWL_MEASUREMENT_START = 0, - IWL_MEASUREMENT_STOP = 1, -}; - -enum iwl3945_measurement_status { - IWL_MEASUREMENT_OK = 0, - IWL_MEASUREMENT_CONCURRENT = 1, - IWL_MEASUREMENT_CSA_CONFLICT = 2, - IWL_MEASUREMENT_TGH_CONFLICT = 3, - /* 4-5 reserved */ - IWL_MEASUREMENT_STOPPED = 6, - IWL_MEASUREMENT_TIMEOUT = 7, - IWL_MEASUREMENT_PERIODIC_FAILED = 8, -}; - -#define NUM_ELEMENTS_IN_HISTOGRAM 8 - -struct iwl3945_measurement_histogram { - __le32 ofdm[NUM_ELEMENTS_IN_HISTOGRAM]; /* in 0.8usec counts */ - __le32 cck[NUM_ELEMENTS_IN_HISTOGRAM]; /* in 1usec counts */ -} __attribute__ ((packed)); - -/* clear channel availability counters */ -struct iwl3945_measurement_cca_counters { - __le32 ofdm; - __le32 cck; -} __attribute__ ((packed)); - -enum iwl3945_measure_type { - IWL_MEASURE_BASIC = (1 << 0), - IWL_MEASURE_CHANNEL_LOAD = (1 << 1), - IWL_MEASURE_HISTOGRAM_RPI = (1 << 2), - IWL_MEASURE_HISTOGRAM_NOISE = (1 << 3), - IWL_MEASURE_FRAME = (1 << 4), - /* bits 5:6 are reserved */ - IWL_MEASURE_IDLE = (1 << 7), -}; - -/* - * SPECTRUM_MEASURE_NOTIFICATION = 0x75 (notification only, not a command) - */ -struct iwl3945_spectrum_notification { - u8 id; /* measurement id -- 0 or 1 */ - u8 token; - u8 channel_index; /* index in measurement channel list */ - u8 state; /* 0 - start, 1 - stop */ - __le32 start_time; /* lower 32-bits of TSF */ - u8 band; /* 0 - 5.2GHz, 1 - 2.4GHz */ - u8 channel; - u8 type; /* see enum iwl3945_measurement_type */ - u8 reserved1; - /* NOTE: cca_ofdm, cca_cck, basic_type, and histogram are only only - * valid if applicable for measurement type requested. */ - __le32 cca_ofdm; /* cca fraction time in 40Mhz clock periods */ - __le32 cca_cck; /* cca fraction time in 44Mhz clock periods */ - __le32 cca_time; /* channel load time in usecs */ - u8 basic_type; /* 0 - bss, 1 - ofdm preamble, 2 - - * unidentified */ - u8 reserved2[3]; - struct iwl3945_measurement_histogram histogram; - __le32 stop_time; /* lower 32-bits of TSF */ - __le32 status; /* see iwl3945_measurement_status */ -} __attribute__ ((packed)); - -/****************************************************************************** - * (7) - * Power Management Commands, Responses, Notifications: - * - *****************************************************************************/ - -/** - * struct iwl3945_powertable_cmd - Power Table Command - * @flags: See below: - * - * POWER_TABLE_CMD = 0x77 (command, has simple generic response) - * - * PM allow: - * bit 0 - '0' Driver not allow power management - * '1' Driver allow PM (use rest of parameters) - * uCode send sleep notifications: - * bit 1 - '0' Don't send sleep notification - * '1' send sleep notification (SEND_PM_NOTIFICATION) - * Sleep over DTIM - * bit 2 - '0' PM have to walk up every DTIM - * '1' PM could sleep over DTIM till listen Interval. - * PCI power managed - * bit 3 - '0' (PCI_LINK_CTRL & 0x1) - * '1' !(PCI_LINK_CTRL & 0x1) - * Force sleep Modes - * bit 31/30- '00' use both mac/xtal sleeps - * '01' force Mac sleep - * '10' force xtal sleep - * '11' Illegal set - * - * NOTE: if sleep_interval[SLEEP_INTRVL_TABLE_SIZE-1] > DTIM period then - * ucode assume sleep over DTIM is allowed and we don't need to wakeup - * for every DTIM. - */ -#define IWL_POWER_VEC_SIZE 5 - -#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK cpu_to_le32(1 << 0) -#define IWL_POWER_SLEEP_OVER_DTIM_MSK cpu_to_le32(1 << 2) -#define IWL_POWER_PCI_PM_MSK cpu_to_le32(1 << 3) -struct iwl3945_powertable_cmd { - __le32 flags; - __le32 rx_data_timeout; - __le32 tx_data_timeout; - __le32 sleep_interval[IWL_POWER_VEC_SIZE]; -} __attribute__((packed)); - -/* - * PM_SLEEP_NOTIFICATION = 0x7A (notification only, not a command) - * 3945 and 4965 identical. - */ -struct iwl3945_sleep_notification { - u8 pm_sleep_mode; - u8 pm_wakeup_src; - __le16 reserved; - __le32 sleep_time; - __le32 tsf_low; - __le32 bcon_timer; -} __attribute__ ((packed)); - -/* Sleep states. 3945 and 4965 identical. */ -enum { - IWL_PM_NO_SLEEP = 0, - IWL_PM_SLP_MAC = 1, - IWL_PM_SLP_FULL_MAC_UNASSOCIATE = 2, - IWL_PM_SLP_FULL_MAC_CARD_STATE = 3, - IWL_PM_SLP_PHY = 4, - IWL_PM_SLP_REPENT = 5, - IWL_PM_WAKEUP_BY_TIMER = 6, - IWL_PM_WAKEUP_BY_DRIVER = 7, - IWL_PM_WAKEUP_BY_RFKILL = 8, - /* 3 reserved */ - IWL_PM_NUM_OF_MODES = 12, -}; - -/* - * REPLY_CARD_STATE_CMD = 0xa0 (command, has simple generic response) - */ -#define CARD_STATE_CMD_DISABLE 0x00 /* Put card to sleep */ -#define CARD_STATE_CMD_ENABLE 0x01 /* Wake up card */ -#define CARD_STATE_CMD_HALT 0x02 /* Power down permanently */ -struct iwl3945_card_state_cmd { - __le32 status; /* CARD_STATE_CMD_* request new power state */ -} __attribute__ ((packed)); - -/* - * CARD_STATE_NOTIFICATION = 0xa1 (notification only, not a command) - */ -struct iwl3945_card_state_notif { - __le32 flags; -} __attribute__ ((packed)); #define HW_CARD_DISABLED 0x01 #define SW_CARD_DISABLED 0x02 @@ -1288,7 +925,8 @@ struct iwl3945_ssid_ie { u8 ssid[32]; } __attribute__ ((packed)); -#define PROBE_OPTION_MAX 0x4 +/* uCode API-1 take 4 probes */ +#define PROBE_OPTION_MAX_API1 0x4 #define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF) #define IWL_GOOD_CRC_TH cpu_to_le16(1) #define IWL_MAX_SCAN_SIZE 1024 @@ -1369,7 +1007,7 @@ struct iwl3945_scan_cmd { struct iwl3945_tx_cmd tx_cmd; /* For directed active scans (set to all-0s otherwise) */ - struct iwl3945_ssid_ie direct_scan[PROBE_OPTION_MAX]; + struct iwl3945_ssid_ie direct_scan[PROBE_OPTION_MAX_API1]; /* * Probe request frame, followed by channel list. @@ -1476,29 +1114,7 @@ struct iwl3945_tx_beacon_cmd { * *****************************************************************************/ -#define IWL_TEMP_CONVERT 260 - -#define SUP_RATE_11A_MAX_NUM_CHANNELS 8 -#define SUP_RATE_11B_MAX_NUM_CHANNELS 4 -#define SUP_RATE_11G_MAX_NUM_CHANNELS 12 - -/* Used for passing to driver number of successes and failures per rate */ -struct rate_histogram { - union { - __le32 a[SUP_RATE_11A_MAX_NUM_CHANNELS]; - __le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS]; - __le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS]; - } success; - union { - __le32 a[SUP_RATE_11A_MAX_NUM_CHANNELS]; - __le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS]; - __le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS]; - } failed; -} __attribute__ ((packed)); - -/* statistics command response */ - -struct statistics_rx_phy { +struct iwl39_statistics_rx_phy { __le32 ina_cnt; __le32 fina_cnt; __le32 plcp_err; @@ -1516,7 +1132,7 @@ struct statistics_rx_phy { __le32 sent_cts_cnt; } __attribute__ ((packed)); -struct statistics_rx_non_phy { +struct iwl39_statistics_rx_non_phy { __le32 bogus_cts; /* CTS received when not expecting CTS */ __le32 bogus_ack; /* ACK received when not expecting ACK */ __le32 non_bssid_frames; /* number of frames with BSSID that @@ -1527,13 +1143,13 @@ struct statistics_rx_non_phy { * our serving channel */ } __attribute__ ((packed)); -struct statistics_rx { - struct statistics_rx_phy ofdm; - struct statistics_rx_phy cck; - struct statistics_rx_non_phy general; +struct iwl39_statistics_rx { + struct iwl39_statistics_rx_phy ofdm; + struct iwl39_statistics_rx_phy cck; + struct iwl39_statistics_rx_non_phy general; } __attribute__ ((packed)); -struct statistics_tx { +struct iwl39_statistics_tx { __le32 preamble_cnt; __le32 rx_detected_cnt; __le32 bt_prio_defer_cnt; @@ -1545,27 +1161,21 @@ struct statistics_tx { __le32 actual_ack_cnt; } __attribute__ ((packed)); -struct statistics_dbg { - __le32 burst_check; - __le32 burst_count; - __le32 reserved[4]; -} __attribute__ ((packed)); - -struct statistics_div { +struct iwl39_statistics_div { __le32 tx_on_a; __le32 tx_on_b; __le32 exec_time; __le32 probe_time; } __attribute__ ((packed)); -struct statistics_general { +struct iwl39_statistics_general { __le32 temperature; struct statistics_dbg dbg; __le32 sleep_time; __le32 slots_out; __le32 slots_idle; __le32 ttl_timestamp; - struct statistics_div div; + struct iwl39_statistics_div div; } __attribute__ ((packed)); /* @@ -1688,14 +1298,14 @@ struct iwl3945_rx_packet { struct iwl3945_alive_resp alive_frame; struct iwl3945_rx_frame rx_frame; struct iwl3945_tx_resp tx_resp; - struct iwl3945_spectrum_notification spectrum_notif; - struct iwl3945_csa_notification csa_notif; + struct iwl_spectrum_notification spectrum_notif; + struct iwl_csa_notification csa_notif; struct iwl3945_error_resp err_resp; - struct iwl3945_card_state_notif card_state_notif; + struct iwl_card_state_notif card_state_notif; struct iwl3945_beacon_notif beacon_status; struct iwl3945_add_sta_resp add_sta; - struct iwl3945_sleep_notification sleep_notif; - struct iwl3945_spectrum_resp spectrum; + struct iwl_sleep_notification sleep_notif; + struct iwl_spectrum_resp spectrum; struct iwl3945_notif_statistics stats; __le32 status; u8 raw[0]; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index b0d420f68ec..525e90bdc47 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -38,6 +38,7 @@ #include #include +#include "iwl-commands.h" #include "iwl-3945-commands.h" #include "iwl-3945.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 56226032333..2da42b89540 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -36,6 +36,7 @@ #include +#include "iwl-commands.h" #include "iwl-3945-commands.h" #include "iwl-3945.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index c16640ddd3d..11e047de6cc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -40,6 +40,7 @@ #include "iwl-3945-core.h" #include "iwl-3945-fh.h" +#include "iwl-commands.h" #include "iwl-3945-commands.h" #include "iwl-3945.h" #include "iwl-helpers.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index d07aafe5ccc..00109324b33 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -250,7 +250,7 @@ struct iwl3945_clip_group { /* Power management (not Tx power) structures */ struct iwl3945_power_vec_entry { - struct iwl3945_powertable_cmd cmd; + struct iwl_powertable_cmd cmd; u8 no_dtim; }; #define IWL_POWER_RANGE_0 (0) @@ -289,12 +289,6 @@ struct iwl3945_frame { struct list_head list; }; -#define SEQ_TO_QUEUE(x) ((x >> 8) & 0xbf) -#define QUEUE_TO_SEQ(x) ((x & 0xbf) << 8) -#define SEQ_TO_INDEX(x) ((u8)(x & 0xff)) -#define INDEX_TO_SEQ(x) ((u8)(x & 0xff)) -#define SEQ_HUGE_FRAME (0x4000) -#define SEQ_RX_FRAME __constant_cpu_to_le16(0x8000) #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) @@ -344,7 +338,7 @@ struct iwl3945_cmd { u32 val32; struct iwl3945_bt_cmd bt; struct iwl3945_rxon_time_cmd rxon_time; - struct iwl3945_powertable_cmd powertable; + struct iwl_powertable_cmd powertable; struct iwl3945_qosparam_cmd qosparam; struct iwl3945_tx_cmd tx; struct iwl3945_tx_beacon_cmd tx_beacon; @@ -707,7 +701,7 @@ struct iwl3945_priv { #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT /* spectrum measurement report caching */ - struct iwl3945_spectrum_notification measure_report; + struct iwl_spectrum_notification measure_report; u8 measurement_status; #endif /* ucode beacon time */ diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index ba997204c8d..20ab7fb75c3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -300,11 +300,12 @@ struct iwl_cmd_header { * 5350 has 3 transmitters * bit14:16 */ -#define RATE_MCS_ANT_POS 14 -#define RATE_MCS_ANT_A_MSK 0x04000 -#define RATE_MCS_ANT_B_MSK 0x08000 -#define RATE_MCS_ANT_C_MSK 0x10000 -#define RATE_MCS_ANT_ABC_MSK 0x1C000 +#define RATE_MCS_ANT_POS 14 +#define RATE_MCS_ANT_A_MSK 0x04000 +#define RATE_MCS_ANT_B_MSK 0x08000 +#define RATE_MCS_ANT_C_MSK 0x10000 +#define RATE_MCS_ANT_AB_MSK (RATE_MCS_ANT_A_MSK | RATE_MCS_ANT_B_MSK) +#define RATE_MCS_ANT_ABC_MSK (RATE_MCS_ANT_AB_MSK | RATE_MCS_ANT_C_MSK) #define RATE_ANT_NUM 3 #define POWER_TABLE_NUM_ENTRIES 33 @@ -2044,15 +2045,23 @@ struct iwl_spectrum_notification { */ #define IWL_POWER_VEC_SIZE 5 -#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK cpu_to_le16(1 << 0) -#define IWL_POWER_SLEEP_OVER_DTIM_MSK cpu_to_le16(1 << 2) -#define IWL_POWER_PCI_PM_MSK cpu_to_le16(1 << 3) -#define IWL_POWER_FAST_PD cpu_to_le16(1 << 4) +#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK cpu_to_le16(BIT(0)) +#define IWL_POWER_SLEEP_OVER_DTIM_MSK cpu_to_le16(BIT(2)) +#define IWL_POWER_PCI_PM_MSK cpu_to_le16(BIT(3)) +#define IWL_POWER_FAST_PD cpu_to_le16(BIT(4)) + +struct iwl3945_powertable_cmd { + __le16 flags; + u8 reserved[2]; + __le32 rx_data_timeout; + __le32 tx_data_timeout; + __le32 sleep_interval[IWL_POWER_VEC_SIZE]; +} __attribute__ ((packed)); struct iwl_powertable_cmd { __le16 flags; - u8 keep_alive_seconds; - u8 debug_flags; + u8 keep_alive_seconds; /* 3945 reserved */ + u8 debug_flags; /* 3945 reserved */ __le32 rx_data_timeout; __le32 tx_data_timeout; __le32 sleep_interval[IWL_POWER_VEC_SIZE]; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index d5fb65e5434..13a0b9a3ec7 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -47,6 +47,7 @@ #include #include "iwl-3945-core.h" +#include "iwl-commands.h" #include "iwl-3945-commands.h" #include "iwl-3945.h" #include "iwl-3945-fh.h" @@ -634,7 +635,7 @@ static int iwl3945_enqueue_hcmd(struct iwl3945_priv *priv, struct iwl3945_host_c out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(IWL_CMD_QUEUE_NUM) | INDEX_TO_SEQ(q->write_ptr)); if (out_cmd->meta.flags & CMD_SIZE_HUGE) - out_cmd->hdr.sequence |= cpu_to_le16(SEQ_HUGE_FRAME); + out_cmd->hdr.sequence |= SEQ_HUGE_FRAME; phys_addr = txq->dma_addr_cmd + sizeof(txq->cmd[0]) * idx + offsetof(struct iwl3945_cmd, hdr); @@ -1804,8 +1805,9 @@ static void iwl3945_activate_qos(struct iwl3945_priv *priv, u8 force) */ #define MSEC_TO_USEC 1024 -#define NOSLP __constant_cpu_to_le32(0) -#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK + +#define NOSLP __constant_cpu_to_le16(0), 0, 0 +#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0 #define SLP_TIMEOUT(T) __constant_cpu_to_le32((T) * MSEC_TO_USEC) #define SLP_VEC(X0, X1, X2, X3, X4) {__constant_cpu_to_le32(X0), \ __constant_cpu_to_le32(X1), \ @@ -1813,7 +1815,6 @@ static void iwl3945_activate_qos(struct iwl3945_priv *priv, u8 force) __constant_cpu_to_le32(X3), \ __constant_cpu_to_le32(X4)} - /* default power management (not Tx power) table values */ /* for TIM 0-10 */ static struct iwl3945_power_vec_entry range_0[IWL_POWER_AC] = { @@ -1862,7 +1863,7 @@ int iwl3945_power_init_handle(struct iwl3945_priv *priv) if (rc != 0) return 0; else { - struct iwl3945_powertable_cmd *cmd; + struct iwl_powertable_cmd *cmd; IWL_DEBUG_POWER("adjust power command flags\n"); @@ -1879,7 +1880,7 @@ int iwl3945_power_init_handle(struct iwl3945_priv *priv) } static int iwl3945_update_power_cmd(struct iwl3945_priv *priv, - struct iwl3945_powertable_cmd *cmd, u32 mode) + struct iwl_powertable_cmd *cmd, u32 mode) { int rc = 0, i; u8 skip; @@ -1946,7 +1947,7 @@ static int iwl3945_send_power_mode(struct iwl3945_priv *priv, u32 mode) { u32 uninitialized_var(final_mode); int rc; - struct iwl3945_powertable_cmd cmd; + struct iwl_powertable_cmd cmd; /* If on battery, set to 3, * if plugged into AC power, set to CAM ("continuously aware mode"), @@ -1965,7 +1966,9 @@ static int iwl3945_send_power_mode(struct iwl3945_priv *priv, u32 mode) iwl3945_update_power_cmd(priv, &cmd, final_mode); - rc = iwl3945_send_cmd_pdu(priv, POWER_TABLE_CMD, sizeof(cmd), &cmd); + /* FIXME use get_hcmd_size 3945 command is 4 bytes shorter */ + rc = iwl3945_send_cmd_pdu(priv, POWER_TABLE_CMD, + sizeof(struct iwl3945_powertable_cmd), &cmd); if (final_mode == IWL_POWER_MODE_CAM) clear_bit(STATUS_POWER_PMI, &priv->status); @@ -2867,7 +2870,7 @@ static int iwl3945_get_measurement(struct iwl3945_priv *priv, struct ieee80211_measurement_params *params, u8 type) { - struct iwl3945_spectrum_cmd spectrum; + struct iwl_spectrum_cmd spectrum; struct iwl3945_rx_packet *res; struct iwl3945_host_cmd cmd = { .id = REPLY_SPECTRUM_MEASUREMENT_CMD, @@ -3008,7 +3011,7 @@ static void iwl3945_rx_csa(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buff { struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; struct iwl3945_rxon_cmd *rxon = (void *)&priv->active_rxon; - struct iwl3945_csa_notification *csa = &(pkt->u.csa_notif); + struct iwl_csa_notification *csa = &(pkt->u.csa_notif); IWL_DEBUG_11H("CSA notif: channel %d, status %d\n", le16_to_cpu(csa->channel), le32_to_cpu(csa->status)); rxon->channel = csa->channel; @@ -3020,7 +3023,7 @@ static void iwl3945_rx_spectrum_measure_notif(struct iwl3945_priv *priv, { #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; - struct iwl3945_spectrum_notification *report = &(pkt->u.spectrum_notif); + struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif); if (!report->state) { IWL_DEBUG(IWL_DL_11H | IWL_DL_INFO, @@ -3038,7 +3041,7 @@ static void iwl3945_rx_pm_sleep_notif(struct iwl3945_priv *priv, { #ifdef CONFIG_IWL3945_DEBUG struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; - struct iwl3945_sleep_notification *sleep = &(pkt->u.sleep_notif); + struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif); IWL_DEBUG_RX("sleep mode: %d, src: %d\n", sleep->pm_sleep_mode, sleep->pm_wakeup_src); #endif @@ -3345,7 +3348,7 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv, u16 sequence = le16_to_cpu(pkt->hdr.sequence); int txq_id = SEQ_TO_QUEUE(sequence); int index = SEQ_TO_INDEX(sequence); - int huge = sequence & SEQ_HUGE_FRAME; + int huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME); int cmd_index; struct iwl3945_cmd *cmd; @@ -7407,7 +7410,7 @@ static ssize_t show_measurement(struct device *d, struct device_attribute *attr, char *buf) { struct iwl3945_priv *priv = dev_get_drvdata(d); - struct iwl3945_spectrum_notification measure_report; + struct iwl_spectrum_notification measure_report; u32 size = sizeof(measure_report), len = 0, ofs = 0; u8 *data = (u8 *)&measure_report; unsigned long flags; -- GitLab From 4c897253cc9ae1c6a2798b27b5fe8e6d94ab6185 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 19 Dec 2008 10:37:05 +0800 Subject: [PATCH 0699/4982] iwlwifi: 3945 remove duplicated code from iwl-3945-commands.h This patch remove trivial (renames) commands and defines from iwl-3945-commands.h Signed-off-by: Tomas Winkler Acked-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- .../net/wireless/iwlwifi/iwl-3945-commands.h | 525 +----------------- drivers/net/wireless/iwlwifi/iwl-3945-led.c | 13 +- drivers/net/wireless/iwlwifi/iwl-3945.h | 10 +- drivers/net/wireless/iwlwifi/iwl-commands.h | 11 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 27 +- 5 files changed, 39 insertions(+), 547 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h index acc584f4377..fe71e0aa371 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h @@ -69,64 +69,12 @@ #ifndef __iwl_3945_commands_h__ #define __iwl_3945_commands_h__ -/* uCode version contains 4 values: Major/Minor/API/Serial */ -#define IWL_UCODE_MAJOR(ver) (((ver) & 0xFF000000) >> 24) -#define IWL_UCODE_MINOR(ver) (((ver) & 0x00FF0000) >> 16) -#define IWL_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8) -#define IWL_UCODE_SERIAL(ver) ((ver) & 0x000000FF) - - -/* Tx rates */ -#define IWL_CCK_RATES 4 -#define IWL_OFDM_RATES 8 -#define IWL_MAX_RATES (IWL_CCK_RATES + IWL_OFDM_RATES) - /****************************************************************************** * (0) * Commonly used structures and definitions: * Command header, txpower * *****************************************************************************/ - -/* iwl3945_cmd_header flags value */ -#define IWL_CMD_FAILED_MSK 0x40 - -/** - * struct iwl3945_cmd_header - * - * This header format appears in the beginning of each command sent from the - * driver, and each response/notification received from uCode. - */ -struct iwl3945_cmd_header { - u8 cmd; /* Command ID: REPLY_RXON, etc. */ - u8 flags; /* IWL_CMD_* */ - /* - * The driver sets up the sequence number to values of its choosing. - * uCode does not use this value, but passes it back to the driver - * when sending the response to each driver-originated command, so - * the driver can match the response to the command. Since the values - * don't get used by uCode, the driver may set up an arbitrary format. - * - * There is one exception: uCode sets bit 15 when it originates - * the response/notification, i.e. when the response/notification - * is not a direct response to a command sent by the driver. For - * example, uCode issues REPLY_3945_RX when it sends a received frame - * to the driver; it is not a direct response to any driver command. - * - * The Linux driver uses the following format: - * - * 0:7 index/position within Tx queue - * 8:13 Tx queue selection - * 14:14 driver sets this to indicate command is in the 'huge' - * storage at the end of the command buffers, i.e. scan cmd - * 15:15 uCode sets this in uCode-originated response/notification - */ - __le16 sequence; - - /* command or response/notification data follows immediately */ - u8 data[0]; -} __attribute__ ((packed)); - /** * struct iwl3945_tx_power * @@ -163,8 +111,6 @@ struct iwl3945_power_per_rate { * *****************************************************************************/ -#define UCODE_VALID_OK cpu_to_le32(0x1) -#define INITIALIZE_SUBTYPE (9) /* * ("Initialize") REPLY_ALIVE = 0x1 (response only, not a command) @@ -252,45 +198,6 @@ struct iwl3945_error_resp { * *****************************************************************************/ -/* rx_config flags */ -/* band & modulation selection */ -#define RXON_FLG_BAND_24G_MSK cpu_to_le32(1 << 0) -#define RXON_FLG_CCK_MSK cpu_to_le32(1 << 1) -/* auto detection enable */ -#define RXON_FLG_AUTO_DETECT_MSK cpu_to_le32(1 << 2) -/* TGg protection when tx */ -#define RXON_FLG_TGG_PROTECT_MSK cpu_to_le32(1 << 3) -/* cck short slot & preamble */ -#define RXON_FLG_SHORT_SLOT_MSK cpu_to_le32(1 << 4) -#define RXON_FLG_SHORT_PREAMBLE_MSK cpu_to_le32(1 << 5) -/* antenna selection */ -#define RXON_FLG_DIS_DIV_MSK cpu_to_le32(1 << 7) -#define RXON_FLG_ANT_SEL_MSK cpu_to_le32(0x0f00) -#define RXON_FLG_ANT_A_MSK cpu_to_le32(1 << 8) -#define RXON_FLG_ANT_B_MSK cpu_to_le32(1 << 9) -/* radar detection enable */ -#define RXON_FLG_RADAR_DETECT_MSK cpu_to_le32(1 << 12) -#define RXON_FLG_TGJ_NARROW_BAND_MSK cpu_to_le32(1 << 13) -/* rx response to host with 8-byte TSF -* (according to ON_AIR deassertion) */ -#define RXON_FLG_TSF2HOST_MSK cpu_to_le32(1 << 15) - -/* rx_config filter flags */ -/* accept all data frames */ -#define RXON_FILTER_PROMISC_MSK cpu_to_le32(1 << 0) -/* pass control & management to host */ -#define RXON_FILTER_CTL2HOST_MSK cpu_to_le32(1 << 1) -/* accept multi-cast */ -#define RXON_FILTER_ACCEPT_GRP_MSK cpu_to_le32(1 << 2) -/* don't decrypt uni-cast frames */ -#define RXON_FILTER_DIS_DECRYPT_MSK cpu_to_le32(1 << 3) -/* don't decrypt multi-cast frames */ -#define RXON_FILTER_DIS_GRP_DECRYPT_MSK cpu_to_le32(1 << 4) -/* STA is associated */ -#define RXON_FILTER_ASSOC_MSK cpu_to_le32(1 << 5) -/* transfer to host non bssid beacons in associated state */ -#define RXON_FILTER_BCON_AWARE_MSK cpu_to_le32(1 << 6) - /** * REPLY_RXON = 0x10 (command, has simple generic response) * @@ -363,120 +270,11 @@ struct iwl3945_channel_switch_cmd { struct iwl3945_power_per_rate power[IWL_MAX_RATES]; } __attribute__ ((packed)); -/* - * CHANNEL_SWITCH_NOTIFICATION = 0x73 (notification only, not a command) - */ -struct iwl3945_csa_notification { - __le16 band; - __le16 channel; - __le32 status; /* 0 - OK, 1 - fail */ -} __attribute__ ((packed)); - -/****************************************************************************** - * (2) - * Quality-of-Service (QOS) Commands & Responses: - * - *****************************************************************************/ - -/** - * struct iwl_ac_qos -- QOS timing params for REPLY_QOS_PARAM - * One for each of 4 EDCA access categories in struct iwl_qosparam_cmd - * - * @cw_min: Contention window, start value in numbers of slots. - * Should be a power-of-2, minus 1. Device's default is 0x0f. - * @cw_max: Contention window, max value in numbers of slots. - * Should be a power-of-2, minus 1. Device's default is 0x3f. - * @aifsn: Number of slots in Arbitration Interframe Space (before - * performing random backoff timing prior to Tx). Device default 1. - * @edca_txop: Length of Tx opportunity, in uSecs. Device default is 0. - * - * Device will automatically increase contention window by (2*CW) + 1 for each - * transmission retry. Device uses cw_max as a bit mask, ANDed with new CW - * value, to cap the CW value. - */ -struct iwl3945_ac_qos { - __le16 cw_min; - __le16 cw_max; - u8 aifsn; - u8 reserved1; - __le16 edca_txop; -} __attribute__ ((packed)); - -/* QoS flags defines */ -#define QOS_PARAM_FLG_UPDATE_EDCA_MSK cpu_to_le32(0x01) -#define QOS_PARAM_FLG_TGN_MSK cpu_to_le32(0x02) -#define QOS_PARAM_FLG_TXOP_TYPE_MSK cpu_to_le32(0x10) - -/* Number of Access Categories (AC) (EDCA), queues 0..3 */ -#define AC_NUM 4 - -/* - * REPLY_QOS_PARAM = 0x13 (command, has simple generic response) - * - * This command sets up timings for each of the 4 prioritized EDCA Tx FIFOs - * 0: Background, 1: Best Effort, 2: Video, 3: Voice. - */ -struct iwl3945_qosparam_cmd { - __le32 qos_flags; - struct iwl3945_ac_qos ac[AC_NUM]; -} __attribute__ ((packed)); - /****************************************************************************** * (3) * Add/Modify Stations Commands & Responses: * *****************************************************************************/ -/* - * Multi station support - */ - -/* Special, dedicated locations within device's station table */ -#define IWL_AP_ID 0 -#define IWL_MULTICAST_ID 1 -#define IWL_STA_ID 2 -#define IWL3945_BROADCAST_ID 24 -#define IWL3945_STATION_COUNT 25 - -#define IWL_STATION_COUNT 32 /* MAX(3945,4965)*/ -#define IWL_INVALID_STATION 255 - -#define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2); -#define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8); - -/* Use in mode field. 1: modify existing entry, 0: add new station entry */ -#define STA_CONTROL_MODIFY_MSK 0x01 - -/* key flags __le16*/ -#define STA_KEY_FLG_ENCRYPT_MSK cpu_to_le16(0x0007) -#define STA_KEY_FLG_NO_ENC cpu_to_le16(0x0000) -#define STA_KEY_FLG_WEP cpu_to_le16(0x0001) -#define STA_KEY_FLG_CCMP cpu_to_le16(0x0002) -#define STA_KEY_FLG_TKIP cpu_to_le16(0x0003) - -#define STA_KEY_FLG_KEYID_POS 8 -#define STA_KEY_FLG_INVALID cpu_to_le16(0x0800) -/* wep key is either from global key (0) or from station info array (1) */ -#define STA_KEY_FLG_WEP_KEY_MAP_MSK cpu_to_le16(0x0008) - -/* wep key in STA: 5-bytes (0) or 13-bytes (1) */ -#define STA_KEY_FLG_KEY_SIZE_MSK cpu_to_le16(0x1000) -#define STA_KEY_MULTICAST_MSK cpu_to_le16(0x4000) - -/* Flags indicate whether to modify vs. don't change various station params */ -#define STA_MODIFY_KEY_MASK 0x01 -#define STA_MODIFY_TID_DISABLE_TX 0x02 -#define STA_MODIFY_TX_RATE_MSK 0x04 - -struct iwl3945_keyinfo { - __le16 key_flags; - u8 tkip_rx_tsc_byte2; /* TSC[2] for key mix ph1 detection */ - u8 reserved1; - __le16 tkip_rx_ttak[5]; /* 10-byte unicast TKIP TTAK */ - u8 key_offset; - u8 reserved2; - u8 key[16]; /* 16-byte unicast decryption key */ -} __attribute__ ((packed)); - /* * REPLY_ADD_STA = 0x18 (command) * @@ -506,7 +304,7 @@ struct iwl3945_addsta_cmd { u8 mode; /* 1: modify existing, 0: add new station */ u8 reserved[3]; struct sta_id_modify sta; - struct iwl3945_keyinfo key; + struct iwl4965_keyinfo key; __le32 station_flags; /* STA_FLG_* */ __le32 station_flags_msk; /* STA_FLG_* */ @@ -530,16 +328,6 @@ struct iwl3945_addsta_cmd { __le16 add_immediate_ba_ssn; } __attribute__ ((packed)); -#define ADD_STA_SUCCESS_MSK 0x1 -#define ADD_STA_NO_ROOM_IN_TABLE 0x2 -#define ADD_STA_NO_BLOCK_ACK_RESOURCE 0x4 -/* - * REPLY_ADD_STA = 0x18 (response) - */ -struct iwl3945_add_sta_resp { - u8 status; /* ADD_STA_* */ -} __attribute__ ((packed)); - /****************************************************************************** * (4) @@ -566,26 +354,7 @@ struct iwl3945_rx_frame_hdr { u8 payload[0]; } __attribute__ ((packed)); -#define RX_RES_STATUS_NO_CRC32_ERROR cpu_to_le32(1 << 0) -#define RX_RES_STATUS_NO_RXE_OVERFLOW cpu_to_le32(1 << 1) -#define RX_RES_PHY_FLAGS_BAND_24_MSK cpu_to_le16(1 << 0) -#define RX_RES_PHY_FLAGS_MOD_CCK_MSK cpu_to_le16(1 << 1) -#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK cpu_to_le16(1 << 2) -#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK cpu_to_le16(1 << 3) -#define RX_RES_PHY_FLAGS_ANTENNA_MSK cpu_to_le16(0xf0) - -#define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8) -#define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8) -#define RX_RES_STATUS_SEC_TYPE_WEP (0x1 << 8) -#define RX_RES_STATUS_SEC_TYPE_CCMP (0x2 << 8) -#define RX_RES_STATUS_SEC_TYPE_TKIP (0x3 << 8) - -#define RX_RES_STATUS_DECRYPT_TYPE_MSK (0x3 << 11) -#define RX_RES_STATUS_NOT_DECRYPT (0x0 << 11) -#define RX_RES_STATUS_DECRYPT_OK (0x3 << 11) -#define RX_RES_STATUS_BAD_ICV_MIC (0x1 << 11) -#define RX_RES_STATUS_BAD_KEY_TTAK (0x2 << 11) struct iwl3945_rx_frame_end { __le32 status; @@ -629,83 +398,6 @@ struct iwl3945_rx_frame { * This command must be executed after every RXON command, before Tx can occur. *****************************************************************************/ -/* REPLY_TX Tx flags field */ - -/* 1: Use Request-To-Send protocol before this frame. - * Mutually exclusive vs. TX_CMD_FLG_CTS_MSK. */ -#define TX_CMD_FLG_RTS_MSK cpu_to_le32(1 << 1) - -/* 1: Transmit Clear-To-Send to self before this frame. - * Driver should set this for AUTH/DEAUTH/ASSOC-REQ/REASSOC mgmnt frames. - * Mutually exclusive vs. TX_CMD_FLG_RTS_MSK. */ -#define TX_CMD_FLG_CTS_MSK cpu_to_le32(1 << 2) - -/* 1: Expect ACK from receiving station - * 0: Don't expect ACK (MAC header's duration field s/b 0) - * Set this for unicast frames, but not broadcast/multicast. */ -#define TX_CMD_FLG_ACK_MSK cpu_to_le32(1 << 3) - -/* 1: Use rate scale table (see REPLY_TX_LINK_QUALITY_CMD). - * Tx command's initial_rate_index indicates first rate to try; - * uCode walks through table for additional Tx attempts. - * 0: Use Tx rate/MCS from Tx command's rate_n_flags field. - * This rate will be used for all Tx attempts; it will not be scaled. */ -#define TX_CMD_FLG_STA_RATE_MSK cpu_to_le32(1 << 4) - -/* 1: Expect immediate block-ack. - * Set when Txing a block-ack request frame. Also set TX_CMD_FLG_ACK_MSK. */ -#define TX_CMD_FLG_IMM_BA_RSP_MASK cpu_to_le32(1 << 6) - -/* 1: Frame requires full Tx-Op protection. - * Set this if either RTS or CTS Tx Flag gets set. */ -#define TX_CMD_FLG_FULL_TXOP_PROT_MSK cpu_to_le32(1 << 7) - -/* Tx antenna selection field; used only for 3945, reserved (0) for 4965. - * Set field to "0" to allow 3945 uCode to select antenna (normal usage). */ -#define TX_CMD_FLG_ANT_SEL_MSK cpu_to_le32(0xf00) -#define TX_CMD_FLG_ANT_A_MSK cpu_to_le32(1 << 8) -#define TX_CMD_FLG_ANT_B_MSK cpu_to_le32(1 << 9) - -/* 1: Ignore Bluetooth priority for this frame. - * 0: Delay Tx until Bluetooth device is done (normal usage). */ -#define TX_CMD_FLG_BT_DIS_MSK cpu_to_le32(1 << 12) - -/* 1: uCode overrides sequence control field in MAC header. - * 0: Driver provides sequence control field in MAC header. - * Set this for management frames, non-QOS data frames, non-unicast frames, - * and also in Tx command embedded in REPLY_SCAN_CMD for active scans. */ -#define TX_CMD_FLG_SEQ_CTL_MSK cpu_to_le32(1 << 13) - -/* 1: This frame is non-last MPDU; more fragments are coming. - * 0: Last fragment, or not using fragmentation. */ -#define TX_CMD_FLG_MORE_FRAG_MSK cpu_to_le32(1 << 14) - -/* 1: uCode calculates and inserts Timestamp Function (TSF) in outgoing frame. - * 0: No TSF required in outgoing frame. - * Set this for transmitting beacons and probe responses. */ -#define TX_CMD_FLG_TSF_MSK cpu_to_le32(1 << 16) - -/* 1: Driver inserted 2 bytes pad after the MAC header, for (required) dword - * alignment of frame's payload data field. - * 0: No pad - * Set this for MAC headers with 26 or 30 bytes, i.e. those with QOS or ADDR4 - * field (but not both). Driver must align frame data (i.e. data following - * MAC header) to DWORD boundary. */ -#define TX_CMD_FLG_MH_PAD_MSK cpu_to_le32(1 << 20) - -/* HCCA-AP - disable duration overwriting. */ -#define TX_CMD_FLG_DUR_MSK cpu_to_le32(1 << 25) - -/* - * TX command security control - */ -#define TX_CMD_SEC_WEP 0x01 -#define TX_CMD_SEC_CCM 0x02 -#define TX_CMD_SEC_TKIP 0x03 -#define TX_CMD_SEC_MSK 0x03 -#define TX_CMD_SEC_SHIFT 6 -#define TX_CMD_SEC_KEY128 0x08 - /* * REPLY_TX = 0x1c (command) */ @@ -819,59 +511,6 @@ struct iwl3945_rate_scaling_cmd { struct iwl3945_rate_scaling_info table[IWL_MAX_RATES]; } __attribute__ ((packed)); -/* - * REPLY_BT_CONFIG = 0x9b (command, has simple generic response) - * - * 3945 and 4965 support hardware handshake with Bluetooth device on - * same platform. Bluetooth device alerts wireless device when it will Tx; - * wireless device can delay or kill its own Tx to accommodate. - */ -struct iwl3945_bt_cmd { - u8 flags; - u8 lead_time; - u8 max_kill; - u8 reserved; - __le32 kill_ack_mask; - __le32 kill_cts_mask; -} __attribute__ ((packed)); - -/****************************************************************************** - * (6) - * Spectrum Management (802.11h) Commands, Responses, Notifications: - * - *****************************************************************************/ - -/* - * Spectrum Management - */ -#define MEASUREMENT_FILTER_FLAG (RXON_FILTER_PROMISC_MSK | \ - RXON_FILTER_CTL2HOST_MSK | \ - RXON_FILTER_ACCEPT_GRP_MSK | \ - RXON_FILTER_DIS_DECRYPT_MSK | \ - RXON_FILTER_DIS_GRP_DECRYPT_MSK | \ - RXON_FILTER_ASSOC_MSK | \ - RXON_FILTER_BCON_AWARE_MSK) - -struct iwl3945_measure_channel { - __le32 duration; /* measurement duration in extended beacon - * format */ - u8 channel; /* channel to measure */ - u8 type; /* see enum iwl3945_measure_type */ - __le16 reserved; -} __attribute__ ((packed)); - - -#define HW_CARD_DISABLED 0x01 -#define SW_CARD_DISABLED 0x02 -#define RF_CARD_DISABLED 0x04 -#define RXON_CARD_DISABLED 0x10 - -struct iwl3945_ct_kill_config { - __le32 reserved; - __le32 critical_temperature_M; - __le32 critical_temperature_R; -} __attribute__ ((packed)); - /****************************************************************************** * (8) * Scan Commands, Responses, Notifications: @@ -912,24 +551,6 @@ struct iwl3945_scan_channel { __le16 passive_dwell; /* in 1024-uSec TU (time units), typ 20-500 */ } __attribute__ ((packed)); -/** - * struct iwl3945_ssid_ie - directed scan network information element - * - * Up to 4 of these may appear in REPLY_SCAN_CMD, selected by "type" field - * in struct iwl3945_scan_channel; each channel may select different ssids from - * among the 4 entries. SSID IEs get transmitted in reverse order of entry. - */ -struct iwl3945_ssid_ie { - u8 id; - u8 len; - u8 ssid[32]; -} __attribute__ ((packed)); - -/* uCode API-1 take 4 probes */ -#define PROBE_OPTION_MAX_API1 0x4 -#define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF) -#define IWL_GOOD_CRC_TH cpu_to_le16(1) -#define IWL_MAX_SCAN_SIZE 1024 /* * REPLY_SCAN_CMD = 0x80 (command) @@ -1007,7 +628,7 @@ struct iwl3945_scan_cmd { struct iwl3945_tx_cmd tx_cmd; /* For directed active scans (set to all-0s otherwise) */ - struct iwl3945_ssid_ie direct_scan[PROBE_OPTION_MAX_API1]; + struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX_API1]; /* * Probe request frame, followed by channel list. @@ -1027,60 +648,6 @@ struct iwl3945_scan_cmd { u8 data[0]; } __attribute__ ((packed)); -/* Can abort will notify by complete notification with abort status. */ -#define CAN_ABORT_STATUS cpu_to_le32(0x1) -/* complete notification statuses */ -#define ABORT_STATUS 0x2 - -/* - * REPLY_SCAN_CMD = 0x80 (response) - */ -struct iwl3945_scanreq_notification { - __le32 status; /* 1: okay, 2: cannot fulfill request */ -} __attribute__ ((packed)); - -/* - * SCAN_START_NOTIFICATION = 0x82 (notification only, not a command) - */ -struct iwl3945_scanstart_notification { - __le32 tsf_low; - __le32 tsf_high; - __le32 beacon_timer; - u8 channel; - u8 band; - u8 reserved[2]; - __le32 status; -} __attribute__ ((packed)); - -#define SCAN_OWNER_STATUS 0x1; -#define MEASURE_OWNER_STATUS 0x2; - -#define NUMBER_OF_STATISTICS 1 /* first __le32 is good CRC */ -/* - * SCAN_RESULTS_NOTIFICATION = 0x83 (notification only, not a command) - */ -struct iwl3945_scanresults_notification { - u8 channel; - u8 band; - u8 reserved[2]; - __le32 tsf_low; - __le32 tsf_high; - __le32 statistics[NUMBER_OF_STATISTICS]; -} __attribute__ ((packed)); - -/* - * SCAN_COMPLETE_NOTIFICATION = 0x84 (notification only, not a command) - */ -struct iwl3945_scancomplete_notification { - u8 scanned_channels; - u8 status; - u8 reserved; - u8 last_channel; - __le32 tsf_low; - __le32 tsf_high; -} __attribute__ ((packed)); - - /****************************************************************************** * (9) * IBSS/AP Commands and Notifications: @@ -1178,27 +745,6 @@ struct iwl39_statistics_general { struct iwl39_statistics_div div; } __attribute__ ((packed)); -/* - * REPLY_STATISTICS_CMD = 0x9c, - * 3945 and 4965 identical. - * - * This command triggers an immediate response containing uCode statistics. - * The response is in the same format as STATISTICS_NOTIFICATION 0x9d, below. - * - * If the CLEAR_STATS configuration flag is set, uCode will clear its - * internal copy of the statistics (counters) after issuing the response. - * This flag does not affect STATISTICS_NOTIFICATIONs after beacons (see below). - * - * If the DISABLE_NOTIF configuration flag is set, uCode will not issue - * STATISTICS_NOTIFICATIONs after received beacons (see below). This flag - * does not affect the response to the REPLY_STATISTICS_CMD 0x9c itself. - */ -#define IWL_STATS_CONF_CLEAR_STATS cpu_to_le32(0x1) /* see above */ -#define IWL_STATS_CONF_DISABLE_NOTIF cpu_to_le32(0x2)/* see above */ -struct iwl3945_statistics_cmd { - __le32 configuration_flags; /* IWL_STATS_CONF_* */ -} __attribute__ ((packed)); - /* * STATISTICS_NOTIFICATION = 0x9d (notification only, not a command) * @@ -1214,8 +760,6 @@ struct iwl3945_statistics_cmd { * appropriately so that each notification contains statistics for only the * one channel that has just been scanned. */ -#define STATISTICS_REPLY_FLG_BAND_24G_MSK cpu_to_le32(0x2) -#define STATISTICS_REPLY_FLG_FAT_MODE_MSK cpu_to_le32(0x8) struct iwl3945_notif_statistics { __le32 flag; struct statistics_rx rx; @@ -1224,67 +768,6 @@ struct iwl3945_notif_statistics { } __attribute__ ((packed)); -/* - * MISSED_BEACONS_NOTIFICATION = 0xa2 (notification only, not a command) - */ -/* if ucode missed CONSECUTIVE_MISSED_BCONS_TH beacons in a row, - * then this notification will be sent. */ -#define CONSECUTIVE_MISSED_BCONS_TH 20 - -struct iwl3945_missed_beacon_notif { - __le32 consequtive_missed_beacons; - __le32 total_missed_becons; - __le32 num_expected_beacons; - __le32 num_recvd_beacons; -} __attribute__ ((packed)); - -/****************************************************************************** - * (11) - * Rx Calibration Commands: - * - *****************************************************************************/ - -#define PHY_CALIBRATE_DIFF_GAIN_CMD (7) -#define HD_TABLE_SIZE (11) - -struct iwl3945_sensitivity_cmd { - __le16 control; - __le16 table[HD_TABLE_SIZE]; -} __attribute__ ((packed)); - -struct iwl3945_calibration_cmd { - u8 opCode; - u8 flags; - __le16 reserved; - s8 diff_gain_a; - s8 diff_gain_b; - s8 diff_gain_c; - u8 reserved1; -} __attribute__ ((packed)); - -/****************************************************************************** - * (12) - * Miscellaneous Commands: - * - *****************************************************************************/ - -/* - * LEDs Command & Response - * REPLY_LEDS_CMD = 0x48 (command, has simple generic response) - * - * For each of 3 possible LEDs (Activity/Link/Tech, selected by "id" field), - * this command turns it on or off, or sets up a periodic blinking cycle. - */ -struct iwl3945_led_cmd { - __le32 interval; /* "interval" in uSec */ - u8 id; /* 1: Activity, 2: Link, 3: Tech */ - u8 off; /* # intervals off while blinking; - * "0", with >0 "on" value, turns LED on */ - u8 on; /* # intervals on while blinking; - * "0", regardless of "off", turns LED off */ - u8 reserved; -} __attribute__ ((packed)); - /****************************************************************************** * (13) * Union of all expected notifications/responses: @@ -1293,7 +776,7 @@ struct iwl3945_led_cmd { struct iwl3945_rx_packet { __le32 len; - struct iwl3945_cmd_header hdr; + struct iwl_cmd_header hdr; union { struct iwl3945_alive_resp alive_frame; struct iwl3945_rx_frame rx_frame; @@ -1303,7 +786,7 @@ struct iwl3945_rx_packet { struct iwl3945_error_resp err_resp; struct iwl_card_state_notif card_state_notif; struct iwl3945_beacon_notif beacon_status; - struct iwl3945_add_sta_resp add_sta; + struct iwl_add_sta_resp add_sta; struct iwl_sleep_notification sleep_notif; struct iwl_spectrum_resp spectrum; struct iwl3945_notif_statistics stats; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index 525e90bdc47..b34bef4891b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -82,11 +82,11 @@ static inline int iwl3945_brightness_to_idx(enum led_brightness brightness) /* Send led command */ static int iwl_send_led_cmd(struct iwl3945_priv *priv, - struct iwl3945_led_cmd *led_cmd) + struct iwl_led_cmd *led_cmd) { struct iwl3945_host_cmd cmd = { .id = REPLY_LEDS_CMD, - .len = sizeof(struct iwl3945_led_cmd), + .len = sizeof(struct iwl_led_cmd), .data = led_cmd, .meta.flags = CMD_ASYNC, .meta.u.callback = iwl3945_led_cmd_callback, @@ -101,7 +101,7 @@ static int iwl_send_led_cmd(struct iwl3945_priv *priv, static int iwl3945_led_pattern(struct iwl3945_priv *priv, int led_id, unsigned int idx) { - struct iwl3945_led_cmd led_cmd = { + struct iwl_led_cmd led_cmd = { .id = led_id, .interval = IWL_DEF_LED_INTRVL }; @@ -115,11 +115,10 @@ static int iwl3945_led_pattern(struct iwl3945_priv *priv, int led_id, } -#if 1 /* Set led on command */ static int iwl3945_led_on(struct iwl3945_priv *priv, int led_id) { - struct iwl3945_led_cmd led_cmd = { + struct iwl_led_cmd led_cmd = { .id = led_id, .on = IWL_LED_SOLID, .off = 0, @@ -131,7 +130,7 @@ static int iwl3945_led_on(struct iwl3945_priv *priv, int led_id) /* Set led off command */ static int iwl3945_led_off(struct iwl3945_priv *priv, int led_id) { - struct iwl3945_led_cmd led_cmd = { + struct iwl_led_cmd led_cmd = { .id = led_id, .on = 0, .off = 0, @@ -140,8 +139,6 @@ static int iwl3945_led_off(struct iwl3945_priv *priv, int led_id) IWL_DEBUG_LED("led off %d\n", led_id); return iwl_send_led_cmd(priv, &led_cmd); } -#endif - /* * brightness call back function for Tx/Rx LED diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 00109324b33..1c9e126dd23 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -328,18 +328,18 @@ struct iwl3945_cmd_meta { */ struct iwl3945_cmd { struct iwl3945_cmd_meta meta; - struct iwl3945_cmd_header hdr; + struct iwl_cmd_header hdr; union { struct iwl3945_addsta_cmd addsta; - struct iwl3945_led_cmd led; + struct iwl_led_cmd led; u32 flags; u8 val8; u16 val16; u32 val32; - struct iwl3945_bt_cmd bt; + struct iwl_bt_cmd bt; struct iwl3945_rxon_time_cmd rxon_time; struct iwl_powertable_cmd powertable; - struct iwl3945_qosparam_cmd qosparam; + struct iwl_qosparam_cmd qosparam; struct iwl3945_tx_cmd tx; struct iwl3945_tx_beacon_cmd tx_beacon; struct iwl3945_rxon_assoc_cmd rxon_assoc; @@ -466,7 +466,7 @@ union iwl3945_qos_capabity { struct iwl3945_qos_info { int qos_active; union iwl3945_qos_capabity qos_cap; - struct iwl3945_qosparam_cmd def_qos_parm; + struct iwl_qosparam_cmd def_qos_parm; }; #define STA_PS_STATUS_WAKE 0 diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 20ab7fb75c3..8b2d7012a2a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -75,6 +75,12 @@ #define IWL_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8) #define IWL_UCODE_SERIAL(ver) ((ver) & 0x000000FF) + +/* Tx rates */ +#define IWL_CCK_RATES 4 +#define IWL_OFDM_RATES 8 +#define IWL_MAX_RATES (IWL_CCK_RATES + IWL_OFDM_RATES) + enum { REPLY_ALIVE = 0x1, REPLY_ERROR = 0x2, @@ -784,6 +790,8 @@ struct iwl_qosparam_cmd { #define IWL_AP_ID 0 #define IWL_MULTICAST_ID 1 #define IWL_STA_ID 2 +#define IWL3945_BROADCAST_ID 24 +#define IWL3945_STATION_COUNT 25 #define IWL4965_BROADCAST_ID 31 #define IWL4965_STATION_COUNT 32 #define IWL5000_BROADCAST_ID 15 @@ -792,6 +800,8 @@ struct iwl_qosparam_cmd { #define IWL_STATION_COUNT 32 /* MAX(3945,4965)*/ #define IWL_INVALID_STATION 255 +#define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2); +#define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8); #define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8); #define STA_FLG_RTS_MIMO_PROT_MSK cpu_to_le32(1 << 17) #define STA_FLG_AGG_MPDU_8US_MSK cpu_to_le32(1 << 18) @@ -2181,6 +2191,7 @@ struct iwl_ssid_ie { u8 ssid[32]; } __attribute__ ((packed)); +#define PROBE_OPTION_MAX_API1 0x4 #define PROBE_OPTION_MAX 0x14 #define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF) #define IWL_GOOD_CRC_TH cpu_to_le16(1) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 13a0b9a3ec7..0be3e7d9714 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1139,7 +1139,7 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv) static int iwl3945_send_bt_config(struct iwl3945_priv *priv) { - struct iwl3945_bt_cmd bt_cmd = { + struct iwl_bt_cmd bt_cmd = { .flags = 3, .lead_time = 0xAA, .max_kill = 1, @@ -1148,7 +1148,7 @@ static int iwl3945_send_bt_config(struct iwl3945_priv *priv) }; return iwl3945_send_cmd_pdu(priv, REPLY_BT_CONFIG, - sizeof(struct iwl3945_bt_cmd), &bt_cmd); + sizeof(bt_cmd), &bt_cmd); } static int iwl3945_send_scan_abort(struct iwl3945_priv *priv) @@ -1343,7 +1343,8 @@ static int iwl3945_clear_sta_key_info(struct iwl3945_priv *priv, u8 sta_id) spin_lock_irqsave(&priv->sta_lock, flags); memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl3945_hw_key)); - memset(&priv->stations[sta_id].sta.key, 0, sizeof(struct iwl3945_keyinfo)); + memset(&priv->stations[sta_id].sta.key, 0, + sizeof(struct iwl4965_keyinfo)); priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC; priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; @@ -1672,11 +1673,11 @@ static u16 iwl3945_fill_probe_req(struct iwl3945_priv *priv, * QoS support */ static int iwl3945_send_qos_params_command(struct iwl3945_priv *priv, - struct iwl3945_qosparam_cmd *qos) + struct iwl_qosparam_cmd *qos) { return iwl3945_send_cmd_pdu(priv, REPLY_QOS_PARAM, - sizeof(struct iwl3945_qosparam_cmd), qos); + sizeof(struct iwl_qosparam_cmd), qos); } static void iwl3945_reset_qos(struct iwl3945_priv *priv) @@ -2581,7 +2582,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) * We'll tell device about this padding later. */ len = priv->hw_setting.tx_cmd_len + - sizeof(struct iwl3945_cmd_header) + hdr_len; + sizeof(struct iwl_cmd_header) + hdr_len; len_org = len; len = (len + 3) & ~3; @@ -3110,8 +3111,8 @@ static void iwl3945_rx_reply_scan(struct iwl3945_priv *priv, { #ifdef CONFIG_IWL3945_DEBUG struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; - struct iwl3945_scanreq_notification *notif = - (struct iwl3945_scanreq_notification *)pkt->u.raw; + struct iwl_scanreq_notification *notif = + (struct iwl_scanreq_notification *)pkt->u.raw; IWL_DEBUG_RX("Scan request status = 0x%x\n", notif->status); #endif @@ -3122,8 +3123,8 @@ static void iwl3945_rx_scan_start_notif(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) { struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; - struct iwl3945_scanstart_notification *notif = - (struct iwl3945_scanstart_notification *)pkt->u.raw; + struct iwl_scanstart_notification *notif = + (struct iwl_scanstart_notification *)pkt->u.raw; priv->scan_start_tsf = le32_to_cpu(notif->tsf_low); IWL_DEBUG_SCAN("Scan start: " "%d [802.11%s] " @@ -3139,8 +3140,8 @@ static void iwl3945_rx_scan_results_notif(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) { struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; - struct iwl3945_scanresults_notification *notif = - (struct iwl3945_scanresults_notification *)pkt->u.raw; + struct iwl_scanresults_notification *notif = + (struct iwl_scanresults_notification *)pkt->u.raw; IWL_DEBUG_SCAN("Scan ch.res: " "%d [802.11%s] " @@ -3164,7 +3165,7 @@ static void iwl3945_rx_scan_complete_notif(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) { struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; - struct iwl3945_scancomplete_notification *scan_notif = (void *)pkt->u.raw; + struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw; IWL_DEBUG_SCAN("Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n", scan_notif->scanned_channels, -- GitLab From 28afaf9139ce9f1c26452f34808e322e8e868850 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 19 Dec 2008 10:37:06 +0800 Subject: [PATCH 0700/4982] iwlwifi: 3945 drop usage of union tsf This patch replaces union tsf with u64 This also allows to use iwl_error_res and iwl_rxon_time_cmd instead of 3945 structures Signed-off-by: Tomas Winkler Acked-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- .../net/wireless/iwlwifi/iwl-3945-commands.h | 33 +------------------ drivers/net/wireless/iwlwifi/iwl-3945.h | 7 ++-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 18 ++++------ 3 files changed, 10 insertions(+), 48 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h index fe71e0aa371..42ef51f4d12 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h @@ -173,25 +173,6 @@ struct iwl3945_alive_resp { __le32 is_valid; } __attribute__ ((packed)); -union tsf { - u8 byte[8]; - __le16 word[4]; - __le32 dw[2]; -}; - -/* - * REPLY_ERROR = 0x2 (response only, not a command) - */ -struct iwl3945_error_resp { - __le32 error_type; - u8 cmd_id; - u8 reserved1; - __le16 bad_cmd_seq_num; - __le16 reserved2; - __le32 error_info; - union tsf timestamp; -} __attribute__ ((packed)); - /****************************************************************************** * (1) * RXON Commands & Responses: @@ -245,18 +226,6 @@ struct iwl3945_rxon_assoc_cmd { __le16 reserved; } __attribute__ ((packed)); -/* - * REPLY_RXON_TIMING = 0x14 (command, has simple generic response) - */ -struct iwl3945_rxon_time_cmd { - union tsf timestamp; - __le16 beacon_interval; - __le16 atim_window; - __le32 beacon_init_val; - __le16 listen_interval; - __le16 reserved; -} __attribute__ ((packed)); - /* * REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response) */ @@ -783,7 +752,7 @@ struct iwl3945_rx_packet { struct iwl3945_tx_resp tx_resp; struct iwl_spectrum_notification spectrum_notif; struct iwl_csa_notification csa_notif; - struct iwl3945_error_resp err_resp; + struct iwl_error_resp err_resp; struct iwl_card_state_notif card_state_notif; struct iwl3945_beacon_notif beacon_status; struct iwl_add_sta_resp add_sta; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 1c9e126dd23..12ead388702 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -337,7 +337,7 @@ struct iwl3945_cmd { u16 val16; u32 val32; struct iwl_bt_cmd bt; - struct iwl3945_rxon_time_cmd rxon_time; + struct iwl_rxon_time_cmd rxon_time; struct iwl_powertable_cmd powertable; struct iwl_qosparam_cmd qosparam; struct iwl3945_tx_cmd tx; @@ -754,7 +754,7 @@ struct iwl3945_priv { struct fw_desc ucode_boot; /* bootstrap inst */ - struct iwl3945_rxon_time_cmd rxon_timing; + struct iwl_rxon_time_cmd rxon_timing; /* We declare this const so it can only be * changed via explicit cast within the @@ -844,8 +844,7 @@ struct iwl3945_priv { struct sk_buff *ibss_beacon; /* Last Rx'd beacon timestamp */ - u32 timestamp0; - u32 timestamp1; + u64 timestamp; u16 beacon_int; struct iwl3945_driver_hw_info hw_setting; struct ieee80211_vif *vif; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 0be3e7d9714..621e0877ca2 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2058,13 +2058,10 @@ static void iwl3945_setup_rxon_timing(struct iwl3945_priv *priv) conf = ieee80211_get_hw_conf(priv->hw); spin_lock_irqsave(&priv->lock, flags); - priv->rxon_timing.timestamp.dw[1] = cpu_to_le32(priv->timestamp1); - priv->rxon_timing.timestamp.dw[0] = cpu_to_le32(priv->timestamp0); - + priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp); priv->rxon_timing.listen_interval = INTEL_CONN_LISTEN_INTERVAL; - tsf = priv->timestamp1; - tsf = ((tsf << 32) | priv->timestamp0); + tsf = priv->timestamp; beacon_int = priv->beacon_int; spin_unlock_irqrestore(&priv->lock, flags); @@ -6306,7 +6303,7 @@ static void iwl3945_post_associate(struct iwl3945_priv *priv) priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl3945_commit_rxon(priv); - memset(&priv->rxon_timing, 0, sizeof(struct iwl3945_rxon_time_cmd)); + memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); iwl3945_setup_rxon_timing(priv); rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON_TIMING, sizeof(priv->rxon_timing), &priv->rxon_timing); @@ -6686,7 +6683,7 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv) iwl3945_commit_rxon(priv); /* RXON Timing */ - memset(&priv->rxon_timing, 0, sizeof(struct iwl3945_rxon_time_cmd)); + memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); iwl3945_setup_rxon_timing(priv); rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON_TIMING, sizeof(priv->rxon_timing), &priv->rxon_timing); @@ -6934,9 +6931,7 @@ static void iwl3945_bss_info_changed(struct ieee80211_hw *hw, if (bss_conf->assoc) { priv->assoc_id = bss_conf->aid; priv->beacon_int = bss_conf->beacon_int; - priv->timestamp0 = bss_conf->timestamp & 0xFFFFFFFF; - priv->timestamp1 = (bss_conf->timestamp >> 32) & - 0xFFFFFFFF; + priv->timestamp = bss_conf->timestamp; priv->assoc_capability = bss_conf->assoc_capability; priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; @@ -7178,8 +7173,7 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) priv->ibss_beacon = NULL; priv->beacon_int = priv->hw->conf.beacon_int; - priv->timestamp1 = 0; - priv->timestamp0 = 0; + priv->timestamp = 0; if ((priv->iw_mode == NL80211_IFTYPE_STATION)) priv->beacon_int = 0; -- GitLab From 3d24a9f790c0e39cfdef1446c7100e89c542805c Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 19 Dec 2008 10:37:07 +0800 Subject: [PATCH 0701/4982] iwlwifi: 3945 remove iwl-3945-commands.h This patch remove iwl-3945-commands.h eliminating duplicated and moving all definitions to iwl-commands.h Signed-off-by: Tomas Winkler Acked-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- .../net/wireless/iwlwifi/iwl-3945-commands.h | 769 ------------------ drivers/net/wireless/iwlwifi/iwl-3945-led.c | 1 - drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 1 - drivers/net/wireless/iwlwifi/iwl-3945.c | 15 +- drivers/net/wireless/iwlwifi/iwl-3945.h | 5 +- drivers/net/wireless/iwlwifi/iwl-commands.h | 448 +++++++++- drivers/net/wireless/iwlwifi/iwl3945-base.c | 64 +- 7 files changed, 468 insertions(+), 835 deletions(-) delete mode 100644 drivers/net/wireless/iwlwifi/iwl-3945-commands.h diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h deleted file mode 100644 index 42ef51f4d12..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h +++ /dev/null @@ -1,769 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ -/* - * Please use this file (iwl-3945-commands.h) only for uCode API definitions. - * Please use iwl-3945-hw.h for hardware-related definitions. - * Please use iwl-3945.h for driver implementation definitions. - */ - -#ifndef __iwl_3945_commands_h__ -#define __iwl_3945_commands_h__ - -/****************************************************************************** - * (0) - * Commonly used structures and definitions: - * Command header, txpower - * - *****************************************************************************/ -/** - * struct iwl3945_tx_power - * - * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_SCAN_CMD, REPLY_CHANNEL_SWITCH - * - * Each entry contains two values: - * 1) DSP gain (or sometimes called DSP attenuation). This is a fine-grained - * linear value that multiplies the output of the digital signal processor, - * before being sent to the analog radio. - * 2) Radio gain. This sets the analog gain of the radio Tx path. - * It is a coarser setting, and behaves in a logarithmic (dB) fashion. - * - * Driver obtains values from struct iwl3945_tx_power power_gain_table[][]. - */ -struct iwl3945_tx_power { - u8 tx_gain; /* gain for analog radio */ - u8 dsp_atten; /* gain for DSP */ -} __attribute__ ((packed)); - -/** - * struct iwl3945_power_per_rate - * - * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH - */ -struct iwl3945_power_per_rate { - u8 rate; /* plcp */ - struct iwl3945_tx_power tpc; - u8 reserved; -} __attribute__ ((packed)); - -/****************************************************************************** - * (0a) - * Alive and Error Commands & Responses: - * - *****************************************************************************/ - - -/* - * ("Initialize") REPLY_ALIVE = 0x1 (response only, not a command) - * - * uCode issues this "initialize alive" notification once the initialization - * uCode image has completed its work, and is ready to load the runtime image. - * This is the *first* "alive" notification that the driver will receive after - * rebooting uCode; the "initialize" alive is indicated by subtype field == 9. - * - * See comments documenting "BSM" (bootstrap state machine). - */ -struct iwl3945_init_alive_resp { - u8 ucode_minor; - u8 ucode_major; - __le16 reserved1; - u8 sw_rev[8]; - u8 ver_type; - u8 ver_subtype; /* "9" for initialize alive */ - __le16 reserved2; - __le32 log_event_table_ptr; - __le32 error_event_table_ptr; - __le32 timestamp; - __le32 is_valid; -} __attribute__ ((packed)); - - -/** - * REPLY_ALIVE = 0x1 (response only, not a command) - * - * uCode issues this "alive" notification once the runtime image is ready - * to receive commands from the driver. This is the *second* "alive" - * notification that the driver will receive after rebooting uCode; - * this "alive" is indicated by subtype field != 9. - * - * See comments documenting "BSM" (bootstrap state machine). - * - * This response includes two pointers to structures within the device's - * data SRAM (access via HBUS_TARG_MEM_* regs) that are useful for debugging: - * - * 1) log_event_table_ptr indicates base of the event log. This traces - * a 256-entry history of uCode execution within a circular buffer. - * - * 2) error_event_table_ptr indicates base of the error log. This contains - * information about any uCode error that occurs. - * - * The Linux driver can print both logs to the system log when a uCode error - * occurs. - */ -struct iwl3945_alive_resp { - u8 ucode_minor; - u8 ucode_major; - __le16 reserved1; - u8 sw_rev[8]; - u8 ver_type; - u8 ver_subtype; /* not "9" for runtime alive */ - __le16 reserved2; - __le32 log_event_table_ptr; /* SRAM address for event log */ - __le32 error_event_table_ptr; /* SRAM address for error log */ - __le32 timestamp; - __le32 is_valid; -} __attribute__ ((packed)); - -/****************************************************************************** - * (1) - * RXON Commands & Responses: - * - *****************************************************************************/ - -/** - * REPLY_RXON = 0x10 (command, has simple generic response) - * - * RXON tunes the radio tuner to a service channel, and sets up a number - * of parameters that are used primarily for Rx, but also for Tx operations. - * - * NOTE: When tuning to a new channel, driver must set the - * RXON_FILTER_ASSOC_MSK to 0. This will clear station-dependent - * info within the device, including the station tables, tx retry - * rate tables, and txpower tables. Driver must build a new station - * table and txpower table before transmitting anything on the RXON - * channel. - * - * NOTE: All RXONs wipe clean the internal txpower table. Driver must - * issue a new REPLY_TX_PWR_TABLE_CMD after each REPLY_RXON (0x10), - * regardless of whether RXON_FILTER_ASSOC_MSK is set. - */ -struct iwl3945_rxon_cmd { - u8 node_addr[6]; - __le16 reserved1; - u8 bssid_addr[6]; - __le16 reserved2; - u8 wlap_bssid_addr[6]; - __le16 reserved3; - u8 dev_type; - u8 air_propagation; - __le16 reserved4; - u8 ofdm_basic_rates; - u8 cck_basic_rates; - __le16 assoc_id; - __le32 flags; - __le32 filter_flags; - __le16 channel; - __le16 reserved5; -} __attribute__ ((packed)); - -/* - * REPLY_RXON_ASSOC = 0x11 (command, has simple generic response) - */ -struct iwl3945_rxon_assoc_cmd { - __le32 flags; - __le32 filter_flags; - u8 ofdm_basic_rates; - u8 cck_basic_rates; - __le16 reserved; -} __attribute__ ((packed)); - -/* - * REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response) - */ -struct iwl3945_channel_switch_cmd { - u8 band; - u8 expect_beacon; - __le16 channel; - __le32 rxon_flags; - __le32 rxon_filter_flags; - __le32 switch_time; - struct iwl3945_power_per_rate power[IWL_MAX_RATES]; -} __attribute__ ((packed)); - -/****************************************************************************** - * (3) - * Add/Modify Stations Commands & Responses: - * - *****************************************************************************/ -/* - * REPLY_ADD_STA = 0x18 (command) - * - * The device contains an internal table of per-station information, - * with info on security keys, aggregation parameters, and Tx rates for - * initial Tx attempt and any retries (4965 uses REPLY_TX_LINK_QUALITY_CMD, - * 3945 uses REPLY_RATE_SCALE to set up rate tables). - * - * REPLY_ADD_STA sets up the table entry for one station, either creating - * a new entry, or modifying a pre-existing one. - * - * NOTE: RXON command (without "associated" bit set) wipes the station table - * clean. Moving into RF_KILL state does this also. Driver must set up - * new station table before transmitting anything on the RXON channel - * (except active scans or active measurements; those commands carry - * their own txpower/rate setup data). - * - * When getting started on a new channel, driver must set up the - * IWL_BROADCAST_ID entry (last entry in the table). For a client - * station in a BSS, once an AP is selected, driver sets up the AP STA - * in the IWL_AP_ID entry (1st entry in the table). BROADCAST and AP - * are all that are needed for a BSS client station. If the device is - * used as AP, or in an IBSS network, driver must set up station table - * entries for all STAs in network, starting with index IWL_STA_ID. - */ -struct iwl3945_addsta_cmd { - u8 mode; /* 1: modify existing, 0: add new station */ - u8 reserved[3]; - struct sta_id_modify sta; - struct iwl4965_keyinfo key; - __le32 station_flags; /* STA_FLG_* */ - __le32 station_flags_msk; /* STA_FLG_* */ - - /* bit field to disable (1) or enable (0) Tx for Traffic ID (TID) - * corresponding to bit (e.g. bit 5 controls TID 5). - * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */ - __le16 tid_disable_tx; - - __le16 rate_n_flags; - - /* TID for which to add block-ack support. - * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ - u8 add_immediate_ba_tid; - - /* TID for which to remove block-ack support. - * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */ - u8 remove_immediate_ba_tid; - - /* Starting Sequence Number for added block-ack support. - * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ - __le16 add_immediate_ba_ssn; -} __attribute__ ((packed)); - - -/****************************************************************************** - * (4) - * Rx Responses: - * - *****************************************************************************/ - -struct iwl3945_rx_frame_stats { - u8 phy_count; - u8 id; - u8 rssi; - u8 agc; - __le16 sig_avg; - __le16 noise_diff; - u8 payload[0]; -} __attribute__ ((packed)); - -struct iwl3945_rx_frame_hdr { - __le16 channel; - __le16 phy_flags; - u8 reserved1; - u8 rate; - __le16 len; - u8 payload[0]; -} __attribute__ ((packed)); - - - -struct iwl3945_rx_frame_end { - __le32 status; - __le64 timestamp; - __le32 beacon_timestamp; -} __attribute__ ((packed)); - -/* - * REPLY_3945_RX = 0x1b (response only, not a command) - * - * NOTE: DO NOT dereference from casts to this structure - * It is provided only for calculating minimum data set size. - * The actual offsets of the hdr and end are dynamic based on - * stats.phy_count - */ -struct iwl3945_rx_frame { - struct iwl3945_rx_frame_stats stats; - struct iwl3945_rx_frame_hdr hdr; - struct iwl3945_rx_frame_end end; -} __attribute__ ((packed)); - -/****************************************************************************** - * (5) - * Tx Commands & Responses: - * - * Driver must place each REPLY_TX command into one of the prioritized Tx - * queues in host DRAM, shared between driver and device. When the device's - * Tx scheduler and uCode are preparing to transmit, the device pulls the - * Tx command over the PCI bus via one of the device's Tx DMA channels, - * to fill an internal FIFO from which data will be transmitted. - * - * uCode handles all timing and protocol related to control frames - * (RTS/CTS/ACK), based on flags in the Tx command. - * - * uCode handles retrying Tx when an ACK is expected but not received. - * This includes trying lower data rates than the one requested in the Tx - * command, as set up by the REPLY_RATE_SCALE (for 3945) or - * REPLY_TX_LINK_QUALITY_CMD (4965). - * - * Driver sets up transmit power for various rates via REPLY_TX_PWR_TABLE_CMD. - * This command must be executed after every RXON command, before Tx can occur. - *****************************************************************************/ - -/* - * REPLY_TX = 0x1c (command) - */ -struct iwl3945_tx_cmd { - /* - * MPDU byte count: - * MAC header (24/26/30/32 bytes) + 2 bytes pad if 26/30 header size, - * + 8 byte IV for CCM or TKIP (not used for WEP) - * + Data payload - * + 8-byte MIC (not used for CCM/WEP) - * NOTE: Does not include Tx command bytes, post-MAC pad bytes, - * MIC (CCM) 8 bytes, ICV (WEP/TKIP/CKIP) 4 bytes, CRC 4 bytes.i - * Range: 14-2342 bytes. - */ - __le16 len; - - /* - * MPDU or MSDU byte count for next frame. - * Used for fragmentation and bursting, but not 11n aggregation. - * Same as "len", but for next frame. Set to 0 if not applicable. - */ - __le16 next_frame_len; - - __le32 tx_flags; /* TX_CMD_FLG_* */ - - u8 rate; - - /* Index of recipient station in uCode's station table */ - u8 sta_id; - u8 tid_tspec; - u8 sec_ctl; - u8 key[16]; - union { - u8 byte[8]; - __le16 word[4]; - __le32 dw[2]; - } tkip_mic; - __le32 next_frame_info; - union { - __le32 life_time; - __le32 attempt; - } stop_time; - u8 supp_rates[2]; - u8 rts_retry_limit; /*byte 50 */ - u8 data_retry_limit; /*byte 51 */ - union { - __le16 pm_frame_timeout; - __le16 attempt_duration; - } timeout; - - /* - * Duration of EDCA burst Tx Opportunity, in 32-usec units. - * Set this if txop time is not specified by HCCA protocol (e.g. by AP). - */ - __le16 driver_txop; - - /* - * MAC header goes here, followed by 2 bytes padding if MAC header - * length is 26 or 30 bytes, followed by payload data - */ - u8 payload[0]; - struct ieee80211_hdr hdr[0]; -} __attribute__ ((packed)); - -/* - * REPLY_TX = 0x1c (response) - */ -struct iwl3945_tx_resp { - u8 failure_rts; - u8 failure_frame; - u8 bt_kill_count; - u8 rate; - __le32 wireless_media_time; - __le32 status; /* TX status */ -} __attribute__ ((packed)); - -/* - * REPLY_TX_PWR_TABLE_CMD = 0x97 (command, has simple generic response) - */ -struct iwl3945_txpowertable_cmd { - u8 band; /* 0: 5 GHz, 1: 2.4 GHz */ - u8 reserved; - __le16 channel; - struct iwl3945_power_per_rate power[IWL_MAX_RATES]; -} __attribute__ ((packed)); - -struct iwl3945_rate_scaling_info { - __le16 rate_n_flags; - u8 try_cnt; - u8 next_rate_index; -} __attribute__ ((packed)); - -/** - * struct iwl3945_rate_scaling_cmd - Rate Scaling Command & Response - * - * REPLY_RATE_SCALE = 0x47 (command, has simple generic response) - * - * NOTE: The table of rates passed to the uCode via the - * RATE_SCALE command sets up the corresponding order of - * rates used for all related commands, including rate - * masks, etc. - * - * For example, if you set 9MB (PLCP 0x0f) as the first - * rate in the rate table, the bit mask for that rate - * when passed through ofdm_basic_rates on the REPLY_RXON - * command would be bit 0 (1 << 0) - */ -struct iwl3945_rate_scaling_cmd { - u8 table_id; - u8 reserved[3]; - struct iwl3945_rate_scaling_info table[IWL_MAX_RATES]; -} __attribute__ ((packed)); - -/****************************************************************************** - * (8) - * Scan Commands, Responses, Notifications: - * - *****************************************************************************/ - -/** - * struct iwl3945_scan_channel - entry in REPLY_SCAN_CMD channel table - * - * One for each channel in the scan list. - * Each channel can independently select: - * 1) SSID for directed active scans - * 2) Txpower setting (for rate specified within Tx command) - * 3) How long to stay on-channel (behavior may be modified by quiet_time, - * quiet_plcp_th, good_CRC_th) - * - * To avoid uCode errors, make sure the following are true (see comments - * under struct iwl3945_scan_cmd about max_out_time and quiet_time): - * 1) If using passive_dwell (i.e. passive_dwell != 0): - * active_dwell <= passive_dwell (< max_out_time if max_out_time != 0) - * 2) quiet_time <= active_dwell - * 3) If restricting off-channel time (i.e. max_out_time !=0): - * passive_dwell < max_out_time - * active_dwell < max_out_time - */ -struct iwl3945_scan_channel { - /* - * type is defined as: - * 0:0 1 = active, 0 = passive - * 1:4 SSID direct bit map; if a bit is set, then corresponding - * SSID IE is transmitted in probe request. - * 5:7 reserved - */ - u8 type; - u8 channel; /* band is selected by iwl3945_scan_cmd "flags" field */ - struct iwl3945_tx_power tpc; - __le16 active_dwell; /* in 1024-uSec TU (time units), typ 5-50 */ - __le16 passive_dwell; /* in 1024-uSec TU (time units), typ 20-500 */ -} __attribute__ ((packed)); - - -/* - * REPLY_SCAN_CMD = 0x80 (command) - * - * The hardware scan command is very powerful; the driver can set it up to - * maintain (relatively) normal network traffic while doing a scan in the - * background. The max_out_time and suspend_time control the ratio of how - * long the device stays on an associated network channel ("service channel") - * vs. how long it's away from the service channel, tuned to other channels - * for scanning. - * - * max_out_time is the max time off-channel (in usec), and suspend_time - * is how long (in "extended beacon" format) that the scan is "suspended" - * after returning to the service channel. That is, suspend_time is the - * time that we stay on the service channel, doing normal work, between - * scan segments. The driver may set these parameters differently to support - * scanning when associated vs. not associated, and light vs. heavy traffic - * loads when associated. - * - * After receiving this command, the device's scan engine does the following; - * - * 1) Sends SCAN_START notification to driver - * 2) Checks to see if it has time to do scan for one channel - * 3) Sends NULL packet, with power-save (PS) bit set to 1, - * to tell AP that we're going off-channel - * 4) Tunes to first channel in scan list, does active or passive scan - * 5) Sends SCAN_RESULT notification to driver - * 6) Checks to see if it has time to do scan on *next* channel in list - * 7) Repeats 4-6 until it no longer has time to scan the next channel - * before max_out_time expires - * 8) Returns to service channel - * 9) Sends NULL packet with PS=0 to tell AP that we're back - * 10) Stays on service channel until suspend_time expires - * 11) Repeats entire process 2-10 until list is complete - * 12) Sends SCAN_COMPLETE notification - * - * For fast, efficient scans, the scan command also has support for staying on - * a channel for just a short time, if doing active scanning and getting no - * responses to the transmitted probe request. This time is controlled by - * quiet_time, and the number of received packets below which a channel is - * considered "quiet" is controlled by quiet_plcp_threshold. - * - * For active scanning on channels that have regulatory restrictions against - * blindly transmitting, the scan can listen before transmitting, to make sure - * that there is already legitimate activity on the channel. If enough - * packets are cleanly received on the channel (controlled by good_CRC_th, - * typical value 1), the scan engine starts transmitting probe requests. - * - * Driver must use separate scan commands for 2.4 vs. 5 GHz bands. - * - * To avoid uCode errors, see timing restrictions described under - * struct iwl3945_scan_channel. - */ -struct iwl3945_scan_cmd { - __le16 len; - u8 reserved0; - u8 channel_count; /* # channels in channel list */ - __le16 quiet_time; /* dwell only this # millisecs on quiet channel - * (only for active scan) */ - __le16 quiet_plcp_th; /* quiet chnl is < this # pkts (typ. 1) */ - __le16 good_CRC_th; /* passive -> active promotion threshold */ - __le16 reserved1; - __le32 max_out_time; /* max usec to be away from associated (service) - * channel */ - __le32 suspend_time; /* pause scan this long (in "extended beacon - * format") when returning to service channel: - * 3945; 31:24 # beacons, 19:0 additional usec, - * 4965; 31:22 # beacons, 21:0 additional usec. - */ - __le32 flags; /* RXON_FLG_* */ - __le32 filter_flags; /* RXON_FILTER_* */ - - /* For active scans (set to all-0s for passive scans). - * Does not include payload. Must specify Tx rate; no rate scaling. */ - struct iwl3945_tx_cmd tx_cmd; - - /* For directed active scans (set to all-0s otherwise) */ - struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX_API1]; - - /* - * Probe request frame, followed by channel list. - * - * Size of probe request frame is specified by byte count in tx_cmd. - * Channel list follows immediately after probe request frame. - * Number of channels in list is specified by channel_count. - * Each channel in list is of type: - * - * struct iwl3945_scan_channel channels[0]; - * - * NOTE: Only one band of channels can be scanned per pass. You - * must not mix 2.4GHz channels and 5.2GHz channels, and you must wait - * for one scan to complete (i.e. receive SCAN_COMPLETE_NOTIFICATION) - * before requesting another scan. - */ - u8 data[0]; -} __attribute__ ((packed)); - -/****************************************************************************** - * (9) - * IBSS/AP Commands and Notifications: - * - *****************************************************************************/ - -/* - * BEACON_NOTIFICATION = 0x90 (notification only, not a command) - */ -struct iwl3945_beacon_notif { - struct iwl3945_tx_resp beacon_notify_hdr; - __le32 low_tsf; - __le32 high_tsf; - __le32 ibss_mgr_status; -} __attribute__ ((packed)); - -/* - * REPLY_TX_BEACON = 0x91 (command, has simple generic response) - */ -struct iwl3945_tx_beacon_cmd { - struct iwl3945_tx_cmd tx; - __le16 tim_idx; - u8 tim_size; - u8 reserved1; - struct ieee80211_hdr frame[0]; /* beacon frame */ -} __attribute__ ((packed)); - -/****************************************************************************** - * (10) - * Statistics Commands and Notifications: - * - *****************************************************************************/ - -struct iwl39_statistics_rx_phy { - __le32 ina_cnt; - __le32 fina_cnt; - __le32 plcp_err; - __le32 crc32_err; - __le32 overrun_err; - __le32 early_overrun_err; - __le32 crc32_good; - __le32 false_alarm_cnt; - __le32 fina_sync_err_cnt; - __le32 sfd_timeout; - __le32 fina_timeout; - __le32 unresponded_rts; - __le32 rxe_frame_limit_overrun; - __le32 sent_ack_cnt; - __le32 sent_cts_cnt; -} __attribute__ ((packed)); - -struct iwl39_statistics_rx_non_phy { - __le32 bogus_cts; /* CTS received when not expecting CTS */ - __le32 bogus_ack; /* ACK received when not expecting ACK */ - __le32 non_bssid_frames; /* number of frames with BSSID that - * doesn't belong to the STA BSSID */ - __le32 filtered_frames; /* count frames that were dumped in the - * filtering process */ - __le32 non_channel_beacons; /* beacons with our bss id but not on - * our serving channel */ -} __attribute__ ((packed)); - -struct iwl39_statistics_rx { - struct iwl39_statistics_rx_phy ofdm; - struct iwl39_statistics_rx_phy cck; - struct iwl39_statistics_rx_non_phy general; -} __attribute__ ((packed)); - -struct iwl39_statistics_tx { - __le32 preamble_cnt; - __le32 rx_detected_cnt; - __le32 bt_prio_defer_cnt; - __le32 bt_prio_kill_cnt; - __le32 few_bytes_cnt; - __le32 cts_timeout; - __le32 ack_timeout; - __le32 expected_ack_cnt; - __le32 actual_ack_cnt; -} __attribute__ ((packed)); - -struct iwl39_statistics_div { - __le32 tx_on_a; - __le32 tx_on_b; - __le32 exec_time; - __le32 probe_time; -} __attribute__ ((packed)); - -struct iwl39_statistics_general { - __le32 temperature; - struct statistics_dbg dbg; - __le32 sleep_time; - __le32 slots_out; - __le32 slots_idle; - __le32 ttl_timestamp; - struct iwl39_statistics_div div; -} __attribute__ ((packed)); - -/* - * STATISTICS_NOTIFICATION = 0x9d (notification only, not a command) - * - * By default, uCode issues this notification after receiving a beacon - * while associated. To disable this behavior, set DISABLE_NOTIF flag in the - * REPLY_STATISTICS_CMD 0x9c, above. - * - * Statistics counters continue to increment beacon after beacon, but are - * cleared when changing channels or when driver issues REPLY_STATISTICS_CMD - * 0x9c with CLEAR_STATS bit set (see above). - * - * uCode also issues this notification during scans. uCode clears statistics - * appropriately so that each notification contains statistics for only the - * one channel that has just been scanned. - */ -struct iwl3945_notif_statistics { - __le32 flag; - struct statistics_rx rx; - struct statistics_tx tx; - struct statistics_general general; -} __attribute__ ((packed)); - - -/****************************************************************************** - * (13) - * Union of all expected notifications/responses: - * - *****************************************************************************/ - -struct iwl3945_rx_packet { - __le32 len; - struct iwl_cmd_header hdr; - union { - struct iwl3945_alive_resp alive_frame; - struct iwl3945_rx_frame rx_frame; - struct iwl3945_tx_resp tx_resp; - struct iwl_spectrum_notification spectrum_notif; - struct iwl_csa_notification csa_notif; - struct iwl_error_resp err_resp; - struct iwl_card_state_notif card_state_notif; - struct iwl3945_beacon_notif beacon_status; - struct iwl_add_sta_resp add_sta; - struct iwl_sleep_notification sleep_notif; - struct iwl_spectrum_resp spectrum; - struct iwl3945_notif_statistics stats; - __le32 status; - u8 raw[0]; - } u; -} __attribute__ ((packed)); - -#define IWL_RX_FRAME_SIZE (4 + sizeof(struct iwl3945_rx_frame)) - -#endif /* __iwl3945_3945_commands_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index b34bef4891b..32d09ba3e69 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -39,7 +39,6 @@ #include #include "iwl-commands.h" -#include "iwl-3945-commands.h" #include "iwl-3945.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 2da42b89540..9d63cdb5ea0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -37,7 +37,6 @@ #include #include "iwl-commands.h" -#include "iwl-3945-commands.h" #include "iwl-3945.h" #define RS_NAME "iwl-3945-rs" diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 11e047de6cc..080f1a85632 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -41,7 +41,6 @@ #include "iwl-3945-core.h" #include "iwl-3945-fh.h" #include "iwl-commands.h" -#include "iwl-3945-commands.h" #include "iwl-3945.h" #include "iwl-helpers.h" #include "iwl-3945-rs.h" @@ -333,7 +332,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv, static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) { - struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; + struct iwl_rx_packet *pkt = (void *)rxb->skb->data; u16 sequence = le16_to_cpu(pkt->hdr.sequence); int txq_id = SEQ_TO_QUEUE(sequence); int index = SEQ_TO_INDEX(sequence); @@ -392,7 +391,7 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) { - struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; + struct iwl_rx_packet *pkt = (void *)rxb->skb->data; IWL_DEBUG_RX("Statistics notification received (%d vs %d).\n", (int)sizeof(struct iwl3945_notif_statistics), le32_to_cpu(pkt->len)); @@ -419,7 +418,7 @@ void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl3945_rx_mem_b * group100 parameter selects whether to show 1 out of 100 good frames. */ static void iwl3945_dbg_report_frame(struct iwl3945_priv *priv, - struct iwl3945_rx_packet *pkt, + struct iwl_rx_packet *pkt, struct ieee80211_hdr *header, int group100) { u32 to_us; @@ -547,7 +546,7 @@ static void iwl3945_dbg_report_frame(struct iwl3945_priv *priv, } #else static inline void iwl3945_dbg_report_frame(struct iwl3945_priv *priv, - struct iwl3945_rx_packet *pkt, + struct iwl_rx_packet *pkt, struct ieee80211_hdr *header, int group100) { } @@ -575,7 +574,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb, struct ieee80211_rx_status *stats) { - struct iwl3945_rx_packet *pkt = (struct iwl3945_rx_packet *)rxb->skb->data; + struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; #ifdef CONFIG_IWL3945_LEDS struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); #endif @@ -584,7 +583,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl3945_priv *priv, short len = le16_to_cpu(rx_hdr->len); /* We received data from the HW, so stop the watchdog */ - if (unlikely((len + IWL_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) { + if (unlikely((len + IWL39_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) { IWL_DEBUG_DROP("Corruption detected!\n"); return; } @@ -619,7 +618,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, { struct ieee80211_hdr *header; struct ieee80211_rx_status rx_status; - struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; + struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 12ead388702..5d5176a6256 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -768,8 +768,9 @@ struct iwl3945_priv { /* 1st responses from initialize and runtime uCode images. * 4965's initialize alive response contains some calibration data. */ - struct iwl3945_init_alive_resp card_alive_init; - struct iwl3945_alive_resp card_alive; + /* FIXME: 4965 uses bigger structure for init */ + struct iwl_alive_resp card_alive_init; + struct iwl_alive_resp card_alive; #ifdef CONFIG_IWL3945_RFKILL struct rfkill *rfkill; diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 8b2d7012a2a..958c4a70d51 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -225,6 +225,37 @@ struct iwl_cmd_header { u8 data[0]; } __attribute__ ((packed)); + +/** + * struct iwl3945_tx_power + * + * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_SCAN_CMD, REPLY_CHANNEL_SWITCH + * + * Each entry contains two values: + * 1) DSP gain (or sometimes called DSP attenuation). This is a fine-grained + * linear value that multiplies the output of the digital signal processor, + * before being sent to the analog radio. + * 2) Radio gain. This sets the analog gain of the radio Tx path. + * It is a coarser setting, and behaves in a logarithmic (dB) fashion. + * + * Driver obtains values from struct iwl3945_tx_power power_gain_table[][]. + */ +struct iwl3945_tx_power { + u8 tx_gain; /* gain for analog radio */ + u8 dsp_atten; /* gain for DSP */ +} __attribute__ ((packed)); + +/** + * struct iwl3945_power_per_rate + * + * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH + */ +struct iwl3945_power_per_rate { + u8 rate; /* plcp */ + struct iwl3945_tx_power tpc; + u8 reserved; +} __attribute__ ((packed)); + /** * iwlagn rate_n_flags bit fields * @@ -499,8 +530,6 @@ struct iwl_alive_resp { __le32 is_valid; } __attribute__ ((packed)); - - /* * REPLY_ERROR = 0x2 (response only, not a command) */ @@ -618,6 +647,26 @@ enum { * issue a new REPLY_TX_PWR_TABLE_CMD after each REPLY_RXON (0x10), * regardless of whether RXON_FILTER_ASSOC_MSK is set. */ + +struct iwl3945_rxon_cmd { + u8 node_addr[6]; + __le16 reserved1; + u8 bssid_addr[6]; + __le16 reserved2; + u8 wlap_bssid_addr[6]; + __le16 reserved3; + u8 dev_type; + u8 air_propagation; + __le16 reserved4; + u8 ofdm_basic_rates; + u8 cck_basic_rates; + __le16 assoc_id; + __le32 flags; + __le32 filter_flags; + __le16 channel; + __le16 reserved5; +} __attribute__ ((packed)); + struct iwl4965_rxon_cmd { u8 node_addr[6]; __le16 reserved1; @@ -663,33 +712,41 @@ struct iwl_rxon_cmd { __le16 reserved6; } __attribute__ ((packed)); -struct iwl5000_rxon_assoc_cmd { +/* + * REPLY_RXON_ASSOC = 0x11 (command, has simple generic response) + */ +struct iwl3945_rxon_assoc_cmd { + __le32 flags; + __le32 filter_flags; + u8 ofdm_basic_rates; + u8 cck_basic_rates; + __le16 reserved; +} __attribute__ ((packed)); + +struct iwl4965_rxon_assoc_cmd { __le32 flags; __le32 filter_flags; u8 ofdm_basic_rates; u8 cck_basic_rates; - __le16 reserved1; u8 ofdm_ht_single_stream_basic_rates; u8 ofdm_ht_dual_stream_basic_rates; - u8 ofdm_ht_triple_stream_basic_rates; - u8 reserved2; __le16 rx_chain_select_flags; - __le16 acquisition_data; - __le32 reserved3; + __le16 reserved; } __attribute__ ((packed)); -/* - * REPLY_RXON_ASSOC = 0x11 (command, has simple generic response) - */ -struct iwl4965_rxon_assoc_cmd { +struct iwl5000_rxon_assoc_cmd { __le32 flags; __le32 filter_flags; u8 ofdm_basic_rates; u8 cck_basic_rates; + __le16 reserved1; u8 ofdm_ht_single_stream_basic_rates; u8 ofdm_ht_dual_stream_basic_rates; + u8 ofdm_ht_triple_stream_basic_rates; + u8 reserved2; __le16 rx_chain_select_flags; - __le16 reserved; + __le16 acquisition_data; + __le32 reserved3; } __attribute__ ((packed)); #define IWL_CONN_MAX_LISTEN_INTERVAL 10 @@ -709,6 +766,16 @@ struct iwl_rxon_time_cmd { /* * REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response) */ +struct iwl3945_channel_switch_cmd { + u8 band; + u8 expect_beacon; + __le16 channel; + __le32 rxon_flags; + __le32 rxon_filter_flags; + __le32 switch_time; + struct iwl3945_power_per_rate power[IWL_MAX_RATES]; +} __attribute__ ((packed)); + struct iwl_channel_switch_cmd { u8 band; u8 expect_beacon; @@ -912,6 +979,35 @@ struct sta_id_modify { * used as AP, or in an IBSS network, driver must set up station table * entries for all STAs in network, starting with index IWL_STA_ID. */ + +struct iwl3945_addsta_cmd { + u8 mode; /* 1: modify existing, 0: add new station */ + u8 reserved[3]; + struct sta_id_modify sta; + struct iwl4965_keyinfo key; + __le32 station_flags; /* STA_FLG_* */ + __le32 station_flags_msk; /* STA_FLG_* */ + + /* bit field to disable (1) or enable (0) Tx for Traffic ID (TID) + * corresponding to bit (e.g. bit 5 controls TID 5). + * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */ + __le16 tid_disable_tx; + + __le16 rate_n_flags; + + /* TID for which to add block-ack support. + * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ + u8 add_immediate_ba_tid; + + /* TID for which to remove block-ack support. + * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */ + u8 remove_immediate_ba_tid; + + /* Starting Sequence Number for added block-ack support. + * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ + __le16 add_immediate_ba_ssn; +} __attribute__ ((packed)); + struct iwl4965_addsta_cmd { u8 mode; /* 1: modify existing, 0: add new station */ u8 reserved[3]; @@ -1065,6 +1161,48 @@ struct iwl_wep_cmd { #define RX_MPDU_RES_STATUS_TTAK_OK (1 << 7) #define RX_MPDU_RES_STATUS_DEC_DONE_MSK (0x800) + +struct iwl3945_rx_frame_stats { + u8 phy_count; + u8 id; + u8 rssi; + u8 agc; + __le16 sig_avg; + __le16 noise_diff; + u8 payload[0]; +} __attribute__ ((packed)); + +struct iwl3945_rx_frame_hdr { + __le16 channel; + __le16 phy_flags; + u8 reserved1; + u8 rate; + __le16 len; + u8 payload[0]; +} __attribute__ ((packed)); + +struct iwl3945_rx_frame_end { + __le32 status; + __le64 timestamp; + __le32 beacon_timestamp; +} __attribute__ ((packed)); + +/* + * REPLY_3945_RX = 0x1b (response only, not a command) + * + * NOTE: DO NOT dereference from casts to this structure + * It is provided only for calculating minimum data set size. + * The actual offsets of the hdr and end are dynamic based on + * stats.phy_count + */ +struct iwl3945_rx_frame { + struct iwl3945_rx_frame_stats stats; + struct iwl3945_rx_frame_hdr hdr; + struct iwl3945_rx_frame_end end; +} __attribute__ ((packed)); + +#define IWL39_RX_FRAME_SIZE (4 + sizeof(struct iwl3945_rx_frame)) + /* Fixed (non-configurable) rx data from phy */ #define IWL49_RX_RES_PHY_CNT 14 @@ -1244,6 +1382,84 @@ struct iwl4965_rx_mpdu_res_start { #define CCMP_MIC_LEN 8 #define TKIP_ICV_LEN 4 +/* + * REPLY_TX = 0x1c (command) + */ + +struct iwl3945_tx_cmd { + /* + * MPDU byte count: + * MAC header (24/26/30/32 bytes) + 2 bytes pad if 26/30 header size, + * + 8 byte IV for CCM or TKIP (not used for WEP) + * + Data payload + * + 8-byte MIC (not used for CCM/WEP) + * NOTE: Does not include Tx command bytes, post-MAC pad bytes, + * MIC (CCM) 8 bytes, ICV (WEP/TKIP/CKIP) 4 bytes, CRC 4 bytes.i + * Range: 14-2342 bytes. + */ + __le16 len; + + /* + * MPDU or MSDU byte count for next frame. + * Used for fragmentation and bursting, but not 11n aggregation. + * Same as "len", but for next frame. Set to 0 if not applicable. + */ + __le16 next_frame_len; + + __le32 tx_flags; /* TX_CMD_FLG_* */ + + u8 rate; + + /* Index of recipient station in uCode's station table */ + u8 sta_id; + u8 tid_tspec; + u8 sec_ctl; + u8 key[16]; + union { + u8 byte[8]; + __le16 word[4]; + __le32 dw[2]; + } tkip_mic; + __le32 next_frame_info; + union { + __le32 life_time; + __le32 attempt; + } stop_time; + u8 supp_rates[2]; + u8 rts_retry_limit; /*byte 50 */ + u8 data_retry_limit; /*byte 51 */ + union { + __le16 pm_frame_timeout; + __le16 attempt_duration; + } timeout; + + /* + * Duration of EDCA burst Tx Opportunity, in 32-usec units. + * Set this if txop time is not specified by HCCA protocol (e.g. by AP). + */ + __le16 driver_txop; + + /* + * MAC header goes here, followed by 2 bytes padding if MAC header + * length is 26 or 30 bytes, followed by payload data + */ + u8 payload[0]; + struct ieee80211_hdr hdr[0]; +} __attribute__ ((packed)); + +/* + * REPLY_TX = 0x1c (response) + */ +struct iwl3945_tx_resp { + u8 failure_rts; + u8 failure_frame; + u8 bt_kill_count; + u8 rate; + __le32 wireless_media_time; + __le32 status; /* TX status */ +} __attribute__ ((packed)); + + /* * 4965 uCode updates these Tx attempt count values in host DRAM. * Used for managing Tx retries when expecting block-acks. @@ -1255,9 +1471,6 @@ struct iwl_dram_scratch { __le16 reserved; } __attribute__ ((packed)); -/* - * REPLY_TX = 0x1c (command) - */ struct iwl_tx_cmd { /* * MPDU byte count: @@ -1595,6 +1808,14 @@ struct iwl_compressed_ba_resp { * * See details under "TXPOWER" in iwl-4965-hw.h. */ + +struct iwl3945_txpowertable_cmd { + u8 band; /* 0: 5 GHz, 1: 2.4 GHz */ + u8 reserved; + __le16 channel; + struct iwl3945_power_per_rate power[IWL_MAX_RATES]; +} __attribute__ ((packed)); + struct iwl4965_txpowertable_cmd { u8 band; /* 0: 5 GHz, 1: 2.4 GHz */ u8 reserved; @@ -1602,6 +1823,35 @@ struct iwl4965_txpowertable_cmd { struct iwl4965_tx_power_db tx_power; } __attribute__ ((packed)); + +/** + * struct iwl3945_rate_scaling_cmd - Rate Scaling Command & Response + * + * REPLY_RATE_SCALE = 0x47 (command, has simple generic response) + * + * NOTE: The table of rates passed to the uCode via the + * RATE_SCALE command sets up the corresponding order of + * rates used for all related commands, including rate + * masks, etc. + * + * For example, if you set 9MB (PLCP 0x0f) as the first + * rate in the rate table, the bit mask for that rate + * when passed through ofdm_basic_rates on the REPLY_RXON + * command would be bit 0 (1 << 0) + */ +struct iwl3945_rate_scaling_info { + __le16 rate_n_flags; + u8 try_cnt; + u8 next_rate_index; +} __attribute__ ((packed)); + +struct iwl3945_rate_scaling_cmd { + u8 table_id; + u8 reserved[3]; + struct iwl3945_rate_scaling_info table[IWL_MAX_RATES]; +} __attribute__ ((packed)); + + /*RS_NEW_API: only TLC_RTS remains and moved to bit 0 */ #define LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK (1 << 0) @@ -2162,6 +2412,23 @@ struct iwl_ct_kill_config { * passive_dwell < max_out_time * active_dwell < max_out_time */ + +/* FIXME: rename to AP1, remove tpc */ +struct iwl3945_scan_channel { + /* + * type is defined as: + * 0:0 1 = active, 0 = passive + * 1:4 SSID direct bit map; if a bit is set, then corresponding + * SSID IE is transmitted in probe request. + * 5:7 reserved + */ + u8 type; + u8 channel; /* band is selected by iwl3945_scan_cmd "flags" field */ + struct iwl3945_tx_power tpc; + __le16 active_dwell; /* in 1024-uSec TU (time units), typ 5-50 */ + __le16 passive_dwell; /* in 1024-uSec TU (time units), typ 20-500 */ +} __attribute__ ((packed)); + struct iwl_scan_channel { /* * type is defined as: @@ -2249,6 +2516,51 @@ struct iwl_ssid_ie { * To avoid uCode errors, see timing restrictions described under * struct iwl_scan_channel. */ + +struct iwl3945_scan_cmd { + __le16 len; + u8 reserved0; + u8 channel_count; /* # channels in channel list */ + __le16 quiet_time; /* dwell only this # millisecs on quiet channel + * (only for active scan) */ + __le16 quiet_plcp_th; /* quiet chnl is < this # pkts (typ. 1) */ + __le16 good_CRC_th; /* passive -> active promotion threshold */ + __le16 reserved1; + __le32 max_out_time; /* max usec to be away from associated (service) + * channel */ + __le32 suspend_time; /* pause scan this long (in "extended beacon + * format") when returning to service channel: + * 3945; 31:24 # beacons, 19:0 additional usec, + * 4965; 31:22 # beacons, 21:0 additional usec. + */ + __le32 flags; /* RXON_FLG_* */ + __le32 filter_flags; /* RXON_FILTER_* */ + + /* For active scans (set to all-0s for passive scans). + * Does not include payload. Must specify Tx rate; no rate scaling. */ + struct iwl3945_tx_cmd tx_cmd; + + /* For directed active scans (set to all-0s otherwise) */ + struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX_API1]; + + /* + * Probe request frame, followed by channel list. + * + * Size of probe request frame is specified by byte count in tx_cmd. + * Channel list follows immediately after probe request frame. + * Number of channels in list is specified by channel_count. + * Each channel in list is of type: + * + * struct iwl3945_scan_channel channels[0]; + * + * NOTE: Only one band of channels can be scanned per pass. You + * must not mix 2.4GHz channels and 5.2GHz channels, and you must wait + * for one scan to complete (i.e. receive SCAN_COMPLETE_NOTIFICATION) + * before requesting another scan. + */ + u8 data[0]; +} __attribute__ ((packed)); + struct iwl_scan_cmd { __le16 len; u8 reserved0; @@ -2356,6 +2668,14 @@ struct iwl_scancomplete_notification { /* * BEACON_NOTIFICATION = 0x90 (notification only, not a command) */ + +struct iwl3945_beacon_notif { + struct iwl3945_tx_resp beacon_notify_hdr; + __le32 low_tsf; + __le32 high_tsf; + __le32 ibss_mgr_status; +} __attribute__ ((packed)); + struct iwl4965_beacon_notif { struct iwl4965_tx_resp beacon_notify_hdr; __le32 low_tsf; @@ -2366,6 +2686,15 @@ struct iwl4965_beacon_notif { /* * REPLY_TX_BEACON = 0x91 (command, has simple generic response) */ + +struct iwl3945_tx_beacon_cmd { + struct iwl3945_tx_cmd tx; + __le16 tim_idx; + u8 tim_size; + u8 reserved1; + struct ieee80211_hdr frame[0]; /* beacon frame */ +} __attribute__ ((packed)); + struct iwl_tx_beacon_cmd { struct iwl_tx_cmd tx; __le16 tim_idx; @@ -2402,6 +2731,76 @@ struct rate_histogram { /* statistics command response */ +struct iwl39_statistics_rx_phy { + __le32 ina_cnt; + __le32 fina_cnt; + __le32 plcp_err; + __le32 crc32_err; + __le32 overrun_err; + __le32 early_overrun_err; + __le32 crc32_good; + __le32 false_alarm_cnt; + __le32 fina_sync_err_cnt; + __le32 sfd_timeout; + __le32 fina_timeout; + __le32 unresponded_rts; + __le32 rxe_frame_limit_overrun; + __le32 sent_ack_cnt; + __le32 sent_cts_cnt; +} __attribute__ ((packed)); + +struct iwl39_statistics_rx_non_phy { + __le32 bogus_cts; /* CTS received when not expecting CTS */ + __le32 bogus_ack; /* ACK received when not expecting ACK */ + __le32 non_bssid_frames; /* number of frames with BSSID that + * doesn't belong to the STA BSSID */ + __le32 filtered_frames; /* count frames that were dumped in the + * filtering process */ + __le32 non_channel_beacons; /* beacons with our bss id but not on + * our serving channel */ +} __attribute__ ((packed)); + +struct iwl39_statistics_rx { + struct iwl39_statistics_rx_phy ofdm; + struct iwl39_statistics_rx_phy cck; + struct iwl39_statistics_rx_non_phy general; +} __attribute__ ((packed)); + +struct iwl39_statistics_tx { + __le32 preamble_cnt; + __le32 rx_detected_cnt; + __le32 bt_prio_defer_cnt; + __le32 bt_prio_kill_cnt; + __le32 few_bytes_cnt; + __le32 cts_timeout; + __le32 ack_timeout; + __le32 expected_ack_cnt; + __le32 actual_ack_cnt; +} __attribute__ ((packed)); + +struct statistics_dbg { + __le32 burst_check; + __le32 burst_count; + __le32 reserved[4]; +} __attribute__ ((packed)); + +struct iwl39_statistics_div { + __le32 tx_on_a; + __le32 tx_on_b; + __le32 exec_time; + __le32 probe_time; +} __attribute__ ((packed)); + +struct iwl39_statistics_general { + __le32 temperature; + struct statistics_dbg dbg; + __le32 sleep_time; + __le32 slots_out; + __le32 slots_idle; + __le32 ttl_timestamp; + struct iwl39_statistics_div div; +} __attribute__ ((packed)); + struct statistics_rx_phy { __le32 ina_cnt; __le32 fina_cnt; @@ -2513,11 +2912,6 @@ struct statistics_tx { struct statistics_tx_non_phy_agg agg; } __attribute__ ((packed)); -struct statistics_dbg { - __le32 burst_check; - __le32 burst_count; - __le32 reserved[4]; -} __attribute__ ((packed)); struct statistics_div { __le32 tx_on_a; @@ -2581,6 +2975,14 @@ struct iwl_statistics_cmd { */ #define STATISTICS_REPLY_FLG_BAND_24G_MSK cpu_to_le32(0x2) #define STATISTICS_REPLY_FLG_FAT_MODE_MSK cpu_to_le32(0x8) + +struct iwl3945_notif_statistics { + __le32 flag; + struct iwl39_statistics_rx rx; + struct iwl39_statistics_tx tx; + struct iwl39_statistics_general general; +} __attribute__ ((packed)); + struct iwl_notif_statistics { __le32 flag; struct statistics_rx rx; @@ -3032,6 +3434,10 @@ struct iwl_rx_packet { __le32 len; struct iwl_cmd_header hdr; union { + struct iwl3945_rx_frame rx_frame; + struct iwl3945_tx_resp tx_resp; + struct iwl3945_beacon_notif beacon_status; + struct iwl_alive_resp alive_frame; struct iwl_spectrum_notification spectrum_notif; struct iwl_csa_notification csa_notif; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 621e0877ca2..3d8669c6cc8 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -48,7 +48,6 @@ #include "iwl-3945-core.h" #include "iwl-commands.h" -#include "iwl-3945-commands.h" #include "iwl-3945.h" #include "iwl-3945-fh.h" #include "iwl-helpers.h" @@ -970,7 +969,7 @@ static int iwl3945_full_rxon_required(struct iwl3945_priv *priv) static int iwl3945_send_rxon_assoc(struct iwl3945_priv *priv) { int rc = 0; - struct iwl3945_rx_packet *res = NULL; + struct iwl_rx_packet *res = NULL; struct iwl3945_rxon_assoc_cmd rxon_assoc; struct iwl3945_host_cmd cmd = { .id = REPLY_RXON_ASSOC, @@ -999,7 +998,7 @@ static int iwl3945_send_rxon_assoc(struct iwl3945_priv *priv) if (rc) return rc; - res = (struct iwl3945_rx_packet *)cmd.meta.u.skb->data; + res = (struct iwl_rx_packet *)cmd.meta.u.skb->data; if (res->hdr.flags & IWL_CMD_FAILED_MSK) { IWL_ERROR("Bad return from REPLY_RXON_ASSOC command\n"); rc = -EIO; @@ -1154,7 +1153,7 @@ static int iwl3945_send_bt_config(struct iwl3945_priv *priv) static int iwl3945_send_scan_abort(struct iwl3945_priv *priv) { int rc = 0; - struct iwl3945_rx_packet *res; + struct iwl_rx_packet *res; struct iwl3945_host_cmd cmd = { .id = REPLY_SCAN_ABORT_CMD, .meta.flags = CMD_WANT_SKB, @@ -1174,7 +1173,7 @@ static int iwl3945_send_scan_abort(struct iwl3945_priv *priv) return rc; } - res = (struct iwl3945_rx_packet *)cmd.meta.u.skb->data; + res = (struct iwl_rx_packet *)cmd.meta.u.skb->data; if (res->u.status != CAN_ABORT_STATUS) { /* The scan abort will return 1 for success or * 2 for "failure". A failure condition can be @@ -1227,14 +1226,14 @@ static int iwl3945_send_card_state(struct iwl3945_priv *priv, u32 flags, u8 meta static int iwl3945_add_sta_sync_callback(struct iwl3945_priv *priv, struct iwl3945_cmd *cmd, struct sk_buff *skb) { - struct iwl3945_rx_packet *res = NULL; + struct iwl_rx_packet *res = NULL; if (!skb) { IWL_ERROR("Error: Response NULL in REPLY_ADD_STA.\n"); return 1; } - res = (struct iwl3945_rx_packet *)skb->data; + res = (struct iwl_rx_packet *)skb->data; if (res->hdr.flags & IWL_CMD_FAILED_MSK) { IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n", res->hdr.flags); @@ -1255,7 +1254,7 @@ static int iwl3945_add_sta_sync_callback(struct iwl3945_priv *priv, int iwl3945_send_add_station(struct iwl3945_priv *priv, struct iwl3945_addsta_cmd *sta, u8 flags) { - struct iwl3945_rx_packet *res = NULL; + struct iwl_rx_packet *res = NULL; int rc = 0; struct iwl3945_host_cmd cmd = { .id = REPLY_ADD_STA, @@ -1274,7 +1273,7 @@ int iwl3945_send_add_station(struct iwl3945_priv *priv, if (rc || (flags & CMD_ASYNC)) return rc; - res = (struct iwl3945_rx_packet *)cmd.meta.u.skb->data; + res = (struct iwl_rx_packet *)cmd.meta.u.skb->data; if (res->hdr.flags & IWL_CMD_FAILED_MSK) { IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n", res->hdr.flags); @@ -2869,7 +2868,7 @@ static int iwl3945_get_measurement(struct iwl3945_priv *priv, u8 type) { struct iwl_spectrum_cmd spectrum; - struct iwl3945_rx_packet *res; + struct iwl_rx_packet *res; struct iwl3945_host_cmd cmd = { .id = REPLY_SPECTRUM_MEASUREMENT_CMD, .data = (void *)&spectrum, @@ -2914,7 +2913,7 @@ static int iwl3945_get_measurement(struct iwl3945_priv *priv, if (rc) return rc; - res = (struct iwl3945_rx_packet *)cmd.meta.u.skb->data; + res = (struct iwl_rx_packet *)cmd.meta.u.skb->data; if (res->hdr.flags & IWL_CMD_FAILED_MSK) { IWL_ERROR("Bad return from REPLY_RX_ON_ASSOC command\n"); rc = -EIO; @@ -2946,8 +2945,8 @@ static int iwl3945_get_measurement(struct iwl3945_priv *priv, static void iwl3945_rx_reply_alive(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) { - struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; - struct iwl3945_alive_resp *palive; + struct iwl_rx_packet *pkt = (void *)rxb->skb->data; + struct iwl_alive_resp *palive; struct delayed_work *pwork; palive = &pkt->u.alive_frame; @@ -2959,14 +2958,13 @@ static void iwl3945_rx_reply_alive(struct iwl3945_priv *priv, if (palive->ver_subtype == INITIALIZE_SUBTYPE) { IWL_DEBUG_INFO("Initialization Alive received.\n"); - memcpy(&priv->card_alive_init, - &pkt->u.alive_frame, - sizeof(struct iwl3945_init_alive_resp)); + memcpy(&priv->card_alive_init, &pkt->u.alive_frame, + sizeof(struct iwl_alive_resp)); pwork = &priv->init_alive_start; } else { IWL_DEBUG_INFO("Runtime Alive received.\n"); memcpy(&priv->card_alive, &pkt->u.alive_frame, - sizeof(struct iwl3945_alive_resp)); + sizeof(struct iwl_alive_resp)); pwork = &priv->alive_start; iwl3945_disable_events(priv); } @@ -2983,7 +2981,7 @@ static void iwl3945_rx_reply_alive(struct iwl3945_priv *priv, static void iwl3945_rx_reply_add_sta(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) { - struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; + struct iwl_rx_packet *pkt = (void *)rxb->skb->data; IWL_DEBUG_RX("Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status); return; @@ -2992,7 +2990,7 @@ static void iwl3945_rx_reply_add_sta(struct iwl3945_priv *priv, static void iwl3945_rx_reply_error(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) { - struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; + struct iwl_rx_packet *pkt = (void *)rxb->skb->data; IWL_ERROR("Error Reply type 0x%08X cmd %s (0x%02X) " "seq 0x%04X ser 0x%08X\n", @@ -3007,7 +3005,7 @@ static void iwl3945_rx_reply_error(struct iwl3945_priv *priv, static void iwl3945_rx_csa(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) { - struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; + struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl3945_rxon_cmd *rxon = (void *)&priv->active_rxon; struct iwl_csa_notification *csa = &(pkt->u.csa_notif); IWL_DEBUG_11H("CSA notif: channel %d, status %d\n", @@ -3020,7 +3018,7 @@ static void iwl3945_rx_spectrum_measure_notif(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) { #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT - struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; + struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif); if (!report->state) { @@ -3038,7 +3036,7 @@ static void iwl3945_rx_pm_sleep_notif(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) { #ifdef CONFIG_IWL3945_DEBUG - struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; + struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif); IWL_DEBUG_RX("sleep mode: %d, src: %d\n", sleep->pm_sleep_mode, sleep->pm_wakeup_src); @@ -3048,7 +3046,7 @@ static void iwl3945_rx_pm_sleep_notif(struct iwl3945_priv *priv, static void iwl3945_rx_pm_debug_statistics_notif(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) { - struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; + struct iwl_rx_packet *pkt = (void *)rxb->skb->data; IWL_DEBUG_RADIO("Dumping %d bytes of unhandled " "notification for %s:\n", le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd)); @@ -3084,7 +3082,7 @@ static void iwl3945_rx_beacon_notif(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) { #ifdef CONFIG_IWL3945_DEBUG - struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; + struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status); u8 rate = beacon->beacon_notify_hdr.rate; @@ -3107,7 +3105,7 @@ static void iwl3945_rx_reply_scan(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) { #ifdef CONFIG_IWL3945_DEBUG - struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; + struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl_scanreq_notification *notif = (struct iwl_scanreq_notification *)pkt->u.raw; @@ -3119,7 +3117,7 @@ static void iwl3945_rx_reply_scan(struct iwl3945_priv *priv, static void iwl3945_rx_scan_start_notif(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) { - struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; + struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl_scanstart_notification *notif = (struct iwl_scanstart_notification *)pkt->u.raw; priv->scan_start_tsf = le32_to_cpu(notif->tsf_low); @@ -3136,7 +3134,7 @@ static void iwl3945_rx_scan_start_notif(struct iwl3945_priv *priv, static void iwl3945_rx_scan_results_notif(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) { - struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; + struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl_scanresults_notification *notif = (struct iwl_scanresults_notification *)pkt->u.raw; @@ -3161,7 +3159,7 @@ static void iwl3945_rx_scan_results_notif(struct iwl3945_priv *priv, static void iwl3945_rx_scan_complete_notif(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) { - struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; + struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw; IWL_DEBUG_SCAN("Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n", @@ -3224,7 +3222,7 @@ reschedule: static void iwl3945_rx_card_state_notif(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) { - struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; + struct iwl_rx_packet *pkt = (void *)rxb->skb->data; u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); unsigned long status = priv->status; @@ -3342,7 +3340,7 @@ static void iwl3945_cmd_queue_reclaim(struct iwl3945_priv *priv, static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) { - struct iwl3945_rx_packet *pkt = (struct iwl3945_rx_packet *)rxb->skb->data; + struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; u16 sequence = le16_to_cpu(pkt->hdr.sequence); int txq_id = SEQ_TO_QUEUE(sequence); int index = SEQ_TO_INDEX(sequence); @@ -3804,7 +3802,7 @@ int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm) static void iwl3945_rx_handle(struct iwl3945_priv *priv) { struct iwl3945_rx_mem_buffer *rxb; - struct iwl3945_rx_packet *pkt; + struct iwl_rx_packet *pkt; struct iwl3945_rx_queue *rxq = &priv->rxq; u32 r, i; int reclaim; @@ -3836,7 +3834,7 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv) pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr, IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); - pkt = (struct iwl3945_rx_packet *)rxb->skb->data; + pkt = (struct iwl_rx_packet *)rxb->skb->data; /* Reclaim a command buffer only if this packet is a response * to a (driver-originated) command. @@ -5837,7 +5835,7 @@ static void __iwl3945_down(struct iwl3945_priv *priv) iwl3945_hw_nic_reset(priv); exit: - memset(&priv->card_alive, 0, sizeof(struct iwl3945_alive_resp)); + memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); if (priv->ibss_beacon) dev_kfree_skb(priv->ibss_beacon); -- GitLab From 40b8ec0bfa2d96c9feae2bc1596e9b427c77b8da Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 19 Dec 2008 10:37:08 +0800 Subject: [PATCH 0702/4982] iwl3945: Getting rid of iwl-3945-debug.h At the cost of adding a debug_level field to iwl3945_priv, we are now able to get rid of iwl-3945-debug.h, and use iwl-debug.h instead. Signed-off-by: Samuel Ortiz Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-debug.h | 167 ------------------ drivers/net/wireless/iwlwifi/iwl-3945-io.h | 2 +- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 13 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 4 +- drivers/net/wireless/iwlwifi/iwl-3945.h | 3 +- drivers/net/wireless/iwlwifi/iwl-debug.h | 2 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 95 +++++----- 7 files changed, 59 insertions(+), 227 deletions(-) delete mode 100644 drivers/net/wireless/iwlwifi/iwl-3945-debug.h diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-debug.h b/drivers/net/wireless/iwlwifi/iwl-3945-debug.h deleted file mode 100644 index 85eb778f9df..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-3945-debug.h +++ /dev/null @@ -1,167 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#ifndef __iwl3945_debug_h__ -#define __iwl3945_debug_h__ - -#ifdef CONFIG_IWL3945_DEBUG -extern u32 iwl3945_debug_level; -#define IWL_DEBUG(level, fmt, args...) \ -do { if (iwl3945_debug_level & (level)) \ - printk(KERN_ERR DRV_NAME": %c %s " fmt, \ - in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0) - -#define IWL_DEBUG_LIMIT(level, fmt, args...) \ -do { if ((iwl3945_debug_level & (level)) && net_ratelimit()) \ - printk(KERN_ERR DRV_NAME": %c %s " fmt, \ - in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0) - -static inline void iwl3945_print_hex_dump(int level, void *p, u32 len) -{ - if (!(iwl3945_debug_level & level)) - return; - - print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1, - p, len, 1); -} -#else -static inline void IWL_DEBUG(int level, const char *fmt, ...) -{ -} -static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...) -{ -} -static inline void iwl3945_print_hex_dump(int level, void *p, u32 len) -{ -} -#endif /* CONFIG_IWL3945_DEBUG */ - - - -/* - * To use the debug system; - * - * If you are defining a new debug classification, simply add it to the #define - * list here in the form of: - * - * #define IWL_DL_xxxx VALUE - * - * shifting value to the left one bit from the previous entry. xxxx should be - * the name of the classification (for example, WEP) - * - * You then need to either add a IWL_xxxx_DEBUG() macro definition for your - * classification, or use IWL_DEBUG(IWL_DL_xxxx, ...) whenever you want - * to send output to that classification. - * - * To add your debug level to the list of levels seen when you perform - * - * % cat /proc/net/iwl/debug_level - * - * you simply need to add your entry to the iwl3945_debug_levels array. - * - * If you do not see debug_level in /proc/net/iwl then you do not have - * CONFIG_IWL3945_DEBUG defined in your kernel configuration - * - */ - -#define IWL_DL_INFO (1 << 0) -#define IWL_DL_MAC80211 (1 << 1) -#define IWL_DL_HOST_COMMAND (1 << 2) -#define IWL_DL_STATE (1 << 3) - -#define IWL_DL_RADIO (1 << 7) -#define IWL_DL_POWER (1 << 8) -#define IWL_DL_TEMP (1 << 9) - -#define IWL_DL_NOTIF (1 << 10) -#define IWL_DL_SCAN (1 << 11) -#define IWL_DL_ASSOC (1 << 12) -#define IWL_DL_DROP (1 << 13) - -#define IWL_DL_TXPOWER (1 << 14) - -#define IWL_DL_AP (1 << 15) - -#define IWL_DL_FW (1 << 16) -#define IWL_DL_RF_KILL (1 << 17) -#define IWL_DL_FW_ERRORS (1 << 18) - -#define IWL_DL_LED (1 << 19) - -#define IWL_DL_RATE (1 << 20) - -#define IWL_DL_CALIB (1 << 21) -#define IWL_DL_WEP (1 << 22) -#define IWL_DL_TX (1 << 23) -#define IWL_DL_RX (1 << 24) -#define IWL_DL_ISR (1 << 25) -#define IWL_DL_HT (1 << 26) -#define IWL_DL_IO (1 << 27) -#define IWL_DL_11H (1 << 28) - -#define IWL_DL_STATS (1 << 29) -#define IWL_DL_TX_REPLY (1 << 30) -#define IWL_DL_QOS (1 << 31) - -#define IWL_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a) -#define IWL_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a) -#define IWL_DEBUG_INFO(f, a...) IWL_DEBUG(IWL_DL_INFO, f, ## a) - -#define IWL_DEBUG_MAC80211(f, a...) IWL_DEBUG(IWL_DL_MAC80211, f, ## a) -#define IWL_DEBUG_TEMP(f, a...) IWL_DEBUG(IWL_DL_TEMP, f, ## a) -#define IWL_DEBUG_SCAN(f, a...) IWL_DEBUG(IWL_DL_SCAN, f, ## a) -#define IWL_DEBUG_RX(f, a...) IWL_DEBUG(IWL_DL_RX, f, ## a) -#define IWL_DEBUG_TX(f, a...) IWL_DEBUG(IWL_DL_TX, f, ## a) -#define IWL_DEBUG_ISR(f, a...) IWL_DEBUG(IWL_DL_ISR, f, ## a) -#define IWL_DEBUG_LED(f, a...) IWL_DEBUG(IWL_DL_LED, f, ## a) -#define IWL_DEBUG_WEP(f, a...) IWL_DEBUG(IWL_DL_WEP, f, ## a) -#define IWL_DEBUG_HC(f, a...) IWL_DEBUG(IWL_DL_HOST_COMMAND, f, ## a) -#define IWL_DEBUG_CALIB(f, a...) IWL_DEBUG(IWL_DL_CALIB, f, ## a) -#define IWL_DEBUG_FW(f, a...) IWL_DEBUG(IWL_DL_FW, f, ## a) -#define IWL_DEBUG_RF_KILL(f, a...) IWL_DEBUG(IWL_DL_RF_KILL, f, ## a) -#define IWL_DEBUG_DROP(f, a...) IWL_DEBUG(IWL_DL_DROP, f, ## a) -#define IWL_DEBUG_DROP_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_DROP, f, ## a) -#define IWL_DEBUG_AP(f, a...) IWL_DEBUG(IWL_DL_AP, f, ## a) -#define IWL_DEBUG_TXPOWER(f, a...) IWL_DEBUG(IWL_DL_TXPOWER, f, ## a) -#define IWL_DEBUG_IO(f, a...) IWL_DEBUG(IWL_DL_IO, f, ## a) -#define IWL_DEBUG_RATE(f, a...) IWL_DEBUG(IWL_DL_RATE, f, ## a) -#define IWL_DEBUG_RATE_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_RATE, f, ## a) -#define IWL_DEBUG_NOTIF(f, a...) IWL_DEBUG(IWL_DL_NOTIF, f, ## a) -#define IWL_DEBUG_ASSOC(f, a...) IWL_DEBUG(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a) -#define IWL_DEBUG_ASSOC_LIMIT(f, a...) \ - IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a) -#define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a) -#define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a) -#define IWL_DEBUG_STATS_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_STATS, f, ## a) -#define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a) -#define IWL_DEBUG_QOS(f, a...) IWL_DEBUG(IWL_DL_QOS, f, ## a) -#define IWL_DEBUG_RADIO(f, a...) IWL_DEBUG(IWL_DL_RADIO, f, ## a) -#define IWL_DEBUG_POWER(f, a...) IWL_DEBUG(IWL_DL_POWER, f, ## a) -#define IWL_DEBUG_11H(f, a...) IWL_DEBUG(IWL_DL_11H, f, ## a) - -#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-io.h b/drivers/net/wireless/iwlwifi/iwl-3945-io.h index 2440fd664dd..d49dfd1ff53 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-io.h @@ -31,7 +31,7 @@ #include -#include "iwl-3945-debug.h" +#include "iwl-debug.h" /* * IO, register, and NIC memory access functions diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 9d63cdb5ea0..42b8bc495d8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -52,6 +52,7 @@ struct iwl3945_rate_scale_data { struct iwl3945_rs_sta { spinlock_t lock; + struct iwl3945_priv *priv; s32 *expected_tpt; unsigned long last_partial_flush; unsigned long last_flush; @@ -182,6 +183,7 @@ static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta) int unflushed = 0; int i; unsigned long flags; + struct iwl3945_priv *priv = rs_sta->priv; /* * For each rate, if we have collected data on that rate @@ -214,6 +216,7 @@ static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta) static void iwl3945_bg_rate_scale_flush(unsigned long data) { struct iwl3945_rs_sta *rs_sta = (void *)data; + struct iwl3945_priv *priv = rs_sta->priv; int unflushed = 0; unsigned long flags; u32 packet_count, duration, pps; @@ -287,6 +290,7 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, { unsigned long flags; s32 fail_count; + struct iwl3945_priv *priv = rs_sta->priv; if (!retries) { IWL_DEBUG_RATE("leave: retries == 0 -- should be at least 1\n"); @@ -380,10 +384,11 @@ static void rs_free(void *priv) return; } -static void *rs_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) +static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp) { struct iwl3945_rs_sta *rs_sta; struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; + struct iwl3945_priv *priv = iwl_priv; int i; /* @@ -403,6 +408,8 @@ static void *rs_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) spin_lock_init(&rs_sta->lock); + rs_sta->priv = priv; + rs_sta->start_rate = IWL_RATE_INVALID; /* default to just 802.11b */ @@ -426,11 +433,12 @@ static void *rs_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) return rs_sta; } -static void rs_free_sta(void *priv, struct ieee80211_sta *sta, +static void rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta, void *priv_sta) { struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; struct iwl3945_rs_sta *rs_sta = priv_sta; + struct iwl3945_priv *priv = rs_sta->priv; psta->rs_sta = NULL; @@ -548,6 +556,7 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, { u8 high = IWL_RATE_INVALID; u8 low = IWL_RATE_INVALID; + struct iwl3945_priv *priv = rs_sta->priv; /* 802.11A walks to the next literal adjacent rate in * the rate table */ diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 080f1a85632..b64e07f0dad 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -542,7 +542,7 @@ static void iwl3945_dbg_report_frame(struct iwl3945_priv *priv, } } if (print_dump) - iwl3945_print_hex_dump(IWL_DL_RX, data, length); + iwl_print_hex_dump(priv, IWL_DL_RX, data, length); } #else static inline void iwl3945_dbg_report_frame(struct iwl3945_priv *priv, @@ -708,7 +708,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, rx_status.noise, rx_status.rate_idx); #ifdef CONFIG_IWL3945_DEBUG - if (iwl3945_debug_level & (IWL_DL_RX)) + if (priv->debug_level & (IWL_DL_RX)) /* Set "1" to report good data frames in groups of 100 */ iwl3945_dbg_report_frame(priv, pkt, header, 1); #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 5d5176a6256..d5154ecbe89 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -47,7 +47,7 @@ extern struct pci_device_id iwl3945_hw_card_ids[]; #include "iwl-csr.h" #include "iwl-prph.h" #include "iwl-3945-hw.h" -#include "iwl-3945-debug.h" +#include "iwl-debug.h" #include "iwl-3945-led.h" /* Highest firmware API version supported */ @@ -889,6 +889,7 @@ struct iwl3945_priv { #ifdef CONFIG_IWL3945_DEBUG /* debugging info */ + u32 debug_level; u32 framecnt_to_us; atomic_t restrict_refcnt; #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 7c4ee0cd81c..f98921880ab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -29,6 +29,8 @@ #ifndef __iwl_debug_h__ #define __iwl_debug_h__ +struct iwl_priv; + #ifdef CONFIG_IWLWIFI_DEBUG #define IWL_DEBUG(level, fmt, args...) \ do { if (priv->debug_level & (level)) \ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 3d8669c6cc8..c706ccff159 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -52,10 +52,6 @@ #include "iwl-3945-fh.h" #include "iwl-helpers.h" -#ifdef CONFIG_IWL3945_DEBUG -u32 iwl3945_debug_level; -#endif - static int iwl3945_tx_queue_update_write_ptr(struct iwl3945_priv *priv, struct iwl3945_tx_queue *txq); @@ -2434,7 +2430,7 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h IWL_DEBUG_DROP("Station %pM not in station map. " "Defaulting to broadcast...\n", hdr->addr1); - iwl3945_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); + iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); return priv->hw_setting.bcast_sta_id; } /* If we are in monitor mode, use BCAST. This is required for @@ -2640,10 +2636,10 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) txq->need_update = 0; } - iwl3945_print_hex_dump(IWL_DL_TX, out_cmd->cmd.payload, + iwl_print_hex_dump(priv, IWL_DL_TX, out_cmd->cmd.payload, sizeof(out_cmd->cmd.tx)); - iwl3945_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr, + iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr, ieee80211_hdrlen(fc)); /* Tell device the write index *just past* this latest filled TFD */ @@ -3050,7 +3046,8 @@ static void iwl3945_rx_pm_debug_statistics_notif(struct iwl3945_priv *priv, IWL_DEBUG_RADIO("Dumping %d bytes of unhandled " "notification for %s:\n", le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd)); - iwl3945_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len)); + iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, + le32_to_cpu(pkt->len)); } static void iwl3945_bg_beacon_update(struct work_struct *work) @@ -3850,13 +3847,13 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv) * handle those that need handling via function in * rx_handlers table. See iwl3945_setup_rx_handlers() */ if (priv->rx_handlers[pkt->hdr.cmd]) { - IWL_DEBUG(IWL_DL_HOST_COMMAND | IWL_DL_RX | IWL_DL_ISR, + IWL_DEBUG(IWL_DL_HCMD | IWL_DL_RX | IWL_DL_ISR, "r = %d, i = %d, %s, 0x%02x\n", r, i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); } else { /* No handling needed */ - IWL_DEBUG(IWL_DL_HOST_COMMAND | IWL_DL_RX | IWL_DL_ISR, + IWL_DEBUG(IWL_DL_HCMD | IWL_DL_RX | IWL_DL_ISR, "r %d i %d No handler needed for %s, 0x%02x\n", r, i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); @@ -3951,10 +3948,11 @@ static int iwl3945_tx_queue_update_write_ptr(struct iwl3945_priv *priv, } #ifdef CONFIG_IWL3945_DEBUG -static void iwl3945_print_rx_config_cmd(struct iwl3945_rxon_cmd *rxon) +static void iwl3945_print_rx_config_cmd(struct iwl3945_priv *priv, + struct iwl3945_rxon_cmd *rxon) { IWL_DEBUG_RADIO("RX CONFIG:\n"); - iwl3945_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon)); + iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon)); IWL_DEBUG_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel)); IWL_DEBUG_RADIO("u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags)); IWL_DEBUG_RADIO("u32 filter_flags: 0x%08x\n", @@ -4188,10 +4186,10 @@ static void iwl3945_irq_handle_error(struct iwl3945_priv *priv) clear_bit(STATUS_HCMD_ACTIVE, &priv->status); #ifdef CONFIG_IWL3945_DEBUG - if (iwl3945_debug_level & IWL_DL_FW_ERRORS) { + if (priv->debug_level & IWL_DL_FW_ERRORS) { iwl3945_dump_nic_error_log(priv); iwl3945_dump_nic_event_log(priv); - iwl3945_print_rx_config_cmd(&priv->staging_rxon); + iwl3945_print_rx_config_cmd(priv, &priv->staging_rxon); } #endif @@ -4255,7 +4253,7 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv) iwl3945_write32(priv, CSR_FH_INT_STATUS, inta_fh); #ifdef CONFIG_IWL3945_DEBUG - if (iwl3945_debug_level & IWL_DL_ISR) { + if (priv->debug_level & IWL_DL_ISR) { /* just for debug */ inta_mask = iwl3945_read32(priv, CSR_INT_MASK); IWL_DEBUG_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", @@ -4289,7 +4287,7 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv) } #ifdef CONFIG_IWL3945_DEBUG - if (iwl3945_debug_level & (IWL_DL_ISR)) { + if (priv->debug_level & (IWL_DL_ISR)) { /* NIC fires this, but we don't use it, redundant with WAKEUP */ if (inta & CSR_INT_BIT_SCD) IWL_DEBUG_ISR("Scheduler finished to transmit " @@ -4360,7 +4358,7 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv) iwl3945_enable_interrupts(priv); #ifdef CONFIG_IWL3945_DEBUG - if (iwl3945_debug_level & (IWL_DL_ISR)) { + if (priv->debug_level & (IWL_DL_ISR)) { inta = iwl3945_read32(priv, CSR_INT); inta_mask = iwl3945_read32(priv, CSR_INT_MASK); inta_fh = iwl3945_read32(priv, CSR_FH_INT_STATUS); @@ -7143,9 +7141,6 @@ static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw, static int iwl3945_mac_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats) { - IWL_DEBUG_MAC80211("enter\n"); - IWL_DEBUG_MAC80211("leave\n"); - return 0; } @@ -7260,29 +7255,33 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk * * See the level definitions in iwl for details. */ - -static ssize_t show_debug_level(struct device_driver *d, char *buf) +static ssize_t show_debug_level(struct device *d, + struct device_attribute *attr, char *buf) { - return sprintf(buf, "0x%08X\n", iwl3945_debug_level); + struct iwl3945_priv *priv = d->driver_data; + + return sprintf(buf, "0x%08X\n", priv->debug_level); } -static ssize_t store_debug_level(struct device_driver *d, +static ssize_t store_debug_level(struct device *d, + struct device_attribute *attr, const char *buf, size_t count) { - char *p = (char *)buf; - u32 val; + struct iwl3945_priv *priv = d->driver_data; + unsigned long val; + int ret; - val = simple_strtoul(p, &p, 0); - if (p == buf) + ret = strict_strtoul(buf, 0, &val); + if (ret) printk(KERN_INFO DRV_NAME ": %s is not in hex or decimal form.\n", buf); else - iwl3945_debug_level = val; + priv->debug_level = val; return strnlen(buf, count); } -static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, - show_debug_level, store_debug_level); +static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, + show_debug_level, store_debug_level); #endif /* CONFIG_IWL3945_DEBUG */ @@ -7763,7 +7762,9 @@ static struct attribute *iwl3945_sysfs_entries[] = { &dev_attr_status.attr, &dev_attr_temperature.attr, &dev_attr_tx_power.attr, - +#ifdef CONFIG_IWL3945_DEBUG + &dev_attr_debug_level.attr, +#endif NULL }; @@ -7802,13 +7803,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e * 1. Allocating HW data * ********************/ - /* Disabling hardware scan means that mac80211 will perform scans - * "the hard way", rather than using device's scan. */ - if (iwl3945_param_disable_hw_scan) { - IWL_DEBUG_INFO("Disabling hw_scan\n"); - iwl3945_hw_ops.hw_scan = NULL; - } - if ((iwl3945_param_queues_num > IWL39_MAX_NUM_QUEUES) || (iwl3945_param_queues_num < IWL_MIN_NUM_QUEUES)) { IWL_ERROR("invalid queues_num, should be between %d and %d\n", @@ -7833,6 +7827,13 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->pci_dev = pdev; priv->cfg = cfg; + /* Disabling hardware scan means that mac80211 will perform scans + * "the hard way", rather than using device's scan. */ + if (iwl3945_param_disable_hw_scan) { + IWL_DEBUG_INFO("Disabling hw_scan\n"); + iwl3945_hw_ops.hw_scan = NULL; + } + IWL_DEBUG_INFO("*** LOAD DRIVER ***\n"); hw->rate_control_algorithm = "iwl-3945-rs"; hw->sta_data_size = sizeof(struct iwl3945_sta_priv); @@ -7840,7 +7841,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e /* Select antenna (may be helpful if only one antenna is connected) */ priv->antenna = (enum iwl3945_antenna)iwl3945_param_antenna; #ifdef CONFIG_IWL3945_DEBUG - iwl3945_debug_level = iwl3945_param_debug; + priv->debug_level = iwl3945_param_debug; atomic_set(&priv->restrict_refcnt, 0); #endif @@ -8301,20 +8302,9 @@ static int __init iwl3945_init(void) IWL_ERROR("Unable to initialize PCI module\n"); goto error_register; } -#ifdef CONFIG_IWL3945_DEBUG - ret = driver_create_file(&iwl3945_driver.driver, &driver_attr_debug_level); - if (ret) { - IWL_ERROR("Unable to create driver sysfs file\n"); - goto error_debug; - } -#endif return ret; -#ifdef CONFIG_IWL3945_DEBUG -error_debug: - pci_unregister_driver(&iwl3945_driver); -#endif error_register: iwl3945_rate_control_unregister(); return ret; @@ -8322,9 +8312,6 @@ error_register: static void __exit iwl3945_exit(void) { -#ifdef CONFIG_IWL3945_DEBUG - driver_remove_file(&iwl3945_driver.driver, &driver_attr_debug_level); -#endif pci_unregister_driver(&iwl3945_driver); iwl3945_rate_control_unregister(); } -- GitLab From a3139c5956702c9ff957ac9fe2d902de355b063e Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 19 Dec 2008 10:37:09 +0800 Subject: [PATCH 0703/4982] iwl3945: Remove DRV_NAME dependenies As DRV_NAME is defined in 2 different header files, including both is not possible. This patch defines this constant from iwl3945-base.c and iwl-agn.c. It also redefines the IWL_ERROR and IWL_WARNING macros to use dev_printk, as the IWL_DEBUG_* macros do. Signed-off-by: Samuel Ortiz Acked-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.h | 1 - drivers/net/wireless/iwlwifi/iwl-4965.c | 6 ++-- .../net/wireless/iwlwifi/iwl-agn-hcmd-check.c | 3 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 9 ++++-- drivers/net/wireless/iwlwifi/iwl-agn.c | 11 ++++--- drivers/net/wireless/iwlwifi/iwl-commands.h | 4 ++- drivers/net/wireless/iwlwifi/iwl-core.c | 21 +++++++------ drivers/net/wireless/iwlwifi/iwl-debug.h | 6 ++-- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - drivers/net/wireless/iwlwifi/iwl-rx.c | 4 +-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 31 ++++++++++--------- 11 files changed, 55 insertions(+), 42 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index d5154ecbe89..7e9ba5449c5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -43,7 +43,6 @@ /* Hardware specific file defines the PCI IDs table for that hardware module */ extern struct pci_device_id iwl3945_hw_card_ids[]; -#define DRV_NAME "iwl3945" #include "iwl-csr.h" #include "iwl-prph.h" #include "iwl-3945-hw.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 5a72bc0377d..bb9617092c4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -902,7 +902,6 @@ static s32 iwl4965_get_tx_atten_grp(u16 channel) channel <= CALIB_IWL_TX_ATTEN_GR4_LCH) return CALIB_CH_GROUP_4; - IWL_ERROR("Can't find txatten group for channel %d.\n", channel); return -1; } @@ -1319,8 +1318,11 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, /* get txatten group, used to select 1) thermal txpower adjustment * and 2) mimo txpower balance between Tx chains. */ txatten_grp = iwl4965_get_tx_atten_grp(channel); - if (txatten_grp < 0) + if (txatten_grp < 0) { + IWL_ERROR("Can't find txatten group for channel %d.\n", + channel); return -EINVAL; + } IWL_DEBUG_TXPOWER("channel %d belongs to txatten group %d\n", channel, txatten_grp); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c index b8137eeae1d..392d96df0b6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c @@ -40,10 +40,11 @@ * be #ifdef'd out once the driver is stable and folks aren't actively * making changes */ -int iwl_agn_check_rxon_cmd(struct iwl_rxon_cmd *rxon) +int iwl_agn_check_rxon_cmd(struct iwl_priv *priv) { int error = 0; int counter = 1; + struct iwl_rxon_cmd *rxon = &priv->staging_rxon; if (rxon->flags & RXON_FLG_BAND_24G_MSK) { error |= le32_to_cpu(rxon->flags & diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 27f50471aed..19dd9fd9c09 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -475,7 +475,8 @@ static u32 rate_n_flags_from_tbl(struct iwl_scale_tbl_info *tbl, } else if (is_Ht(tbl->lq_type)) { if (index > IWL_LAST_OFDM_RATE) { - IWL_ERROR("invalid HT rate index %d\n", index); + printk(KERN_ERR RS_NAME": Invalid HT rate index %d\n", + index); index = IWL_LAST_OFDM_RATE; } rate_n_flags = RATE_MCS_HT_MSK; @@ -487,7 +488,8 @@ static u32 rate_n_flags_from_tbl(struct iwl_scale_tbl_info *tbl, else rate_n_flags |= iwl_rates[index].plcp_mimo3; } else { - IWL_ERROR("Invalid tbl->lq_type %d\n", tbl->lq_type); + printk(KERN_ERR RS_NAME": Invalid tbl->lq_type %d\n", + tbl->lq_type); } rate_n_flags |= ((tbl->ant_type << RATE_MCS_ANT_POS) & @@ -507,7 +509,8 @@ static u32 rate_n_flags_from_tbl(struct iwl_scale_tbl_info *tbl, rate_n_flags |= RATE_MCS_GF_MSK; if (is_siso(tbl->lq_type) && tbl->is_SGI) { rate_n_flags &= ~RATE_MCS_SGI_MSK; - IWL_ERROR("GF was set with SGI:SISO\n"); + printk(KERN_ERR RS_NAME + ": GF was set with SGI:SISO\n"); } } } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 1e5aadd9e6a..24e906f75ea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -44,6 +44,8 @@ #include +#define DRV_NAME "iwlagn" + #include "iwl-eeprom.h" #include "iwl-dev.h" #include "iwl-core.h" @@ -61,9 +63,7 @@ /* * module name, copyright, version, etc. - * NOTE: DRV_NAME is defined in iwlwifi.h for use by iwl-debug.h and printk */ - #define DRV_DESCRIPTION "Intel(R) Wireless WiFi Link AGN driver for Linux" #ifdef CONFIG_IWLWIFI_DEBUG @@ -179,7 +179,7 @@ static int iwl_commit_rxon(struct iwl_priv *priv) * 5000, but will not damage 4965 */ priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN; - ret = iwl_agn_check_rxon_cmd(&priv->staging_rxon); + ret = iwl_agn_check_rxon_cmd(priv); if (ret) { IWL_ERROR("Invalid RXON configuration. Not committing.\n"); return -EINVAL; @@ -4077,13 +4077,14 @@ static int __init iwl_init(void) ret = iwlagn_rate_control_register(); if (ret) { - IWL_ERROR("Unable to register rate control algorithm: %d\n", ret); + printk(KERN_ERR DRV_NAME + "Unable to register rate control algorithm: %d\n", ret); return ret; } ret = pci_register_driver(&iwl_driver); if (ret) { - IWL_ERROR("Unable to initialize PCI module\n"); + printk(KERN_ERR DRV_NAME "Unable to initialize PCI module\n"); goto error_register; } diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 958c4a70d51..6a2445da22f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -69,6 +69,8 @@ #ifndef __iwl_commands_h__ #define __iwl_commands_h__ +struct iwl_priv; + /* uCode version contains 4 values: Major/Minor/API/Serial */ #define IWL_UCODE_MAJOR(ver) (((ver) & 0xFF000000) >> 24) #define IWL_UCODE_MINOR(ver) (((ver) & 0x00FF0000) >> 16) @@ -3455,6 +3457,6 @@ struct iwl_rx_packet { } u; } __attribute__ ((packed)); -int iwl_agn_check_rxon_cmd(struct iwl_rxon_cmd *rxon); +int iwl_agn_check_rxon_cmd(struct iwl_priv *priv); #endif /* __iwl_commands_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 313976b29da..327d1bd4ff0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -170,7 +170,8 @@ struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, struct ieee80211_hw *hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), hw_ops); if (hw == NULL) { - IWL_ERROR("Can not allocate network device\n"); + printk(KERN_ERR "%s: Can not allocate network device\n", + cfg->name); goto out; } @@ -510,18 +511,18 @@ static int iwlcore_init_geos(struct iwl_priv *priv) if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && priv->cfg->sku & IWL_SKU_A) { - printk(KERN_INFO DRV_NAME - ": Incorrectly detected BG card as ABG. Please send " - "your PCI ID 0x%04X:0x%04X to maintainer.\n", - priv->pci_dev->device, priv->pci_dev->subsystem_device); + dev_printk(KERN_INFO, &(priv->hw->wiphy->dev), + "Incorrectly detected BG card as ABG. Please send " + "your PCI ID 0x%04X:0x%04X to maintainer.\n", + priv->pci_dev->device, + priv->pci_dev->subsystem_device); priv->cfg->sku &= ~IWL_SKU_A; } - printk(KERN_INFO DRV_NAME - ": Tunable channels: %d 802.11bg, %d 802.11a channels\n", - priv->bands[IEEE80211_BAND_2GHZ].n_channels, - priv->bands[IEEE80211_BAND_5GHZ].n_channels); - + dev_printk(KERN_INFO, &(priv->hw->wiphy->dev), + "Tunable channels: %d 802.11bg, %d 802.11a channels\n", + priv->bands[IEEE80211_BAND_2GHZ].n_channels, + priv->bands[IEEE80211_BAND_5GHZ].n_channels); set_bit(STATUS_GEO_CONFIGURED, &priv->status); diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index f98921880ab..9c209d635d5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -160,8 +160,10 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) #define IWL_DL_TX_REPLY (1 << 30) #define IWL_DL_QOS (1 << 31) -#define IWL_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a) -#define IWL_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a) +#define IWL_ERROR(f, a...) dev_printk(KERN_ERR, \ + &(priv->hw->wiphy->dev), f, ## a) +#define IWL_WARNING(f, a...) dev_printk(KERN_WARNING, \ + &(priv->hw->wiphy->dev), f, ## a) #define IWL_DEBUG_INFO(f, a...) IWL_DEBUG(IWL_DL_INFO, f, ## a) #define IWL_DEBUG_MAC80211(f, a...) IWL_DEBUG(IWL_DL_MAC80211, f, ## a) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 0468fcc1ea9..73a0b6c53e1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -36,7 +36,6 @@ #include #include -#define DRV_NAME "iwlagn" #include "iwl-rfkill.h" #include "iwl-eeprom.h" #include "iwl-4965-hw.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index c5f1aa0feac..610a7c2b0ad 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -262,8 +262,8 @@ void iwl_rx_allocate(struct iwl_priv *priv) rxb->skb = alloc_skb(priv->hw_params.rx_buf_size + 256, GFP_KERNEL); if (!rxb->skb) { - printk(KERN_CRIT DRV_NAME - "Can not allocate SKB buffers\n"); + dev_printk(KERN_CRIT, &(priv->hw->wiphy->dev), + "Can not allocate SKB buffers\n"); /* We don't reschedule replenish work here -- we will * call the restock method and if it still needs * more buffers it will schedule replenish */ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index c706ccff159..c2e0152108d 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -46,6 +46,8 @@ #include +#define DRV_NAME "iwl3945" + #include "iwl-3945-core.h" #include "iwl-commands.h" #include "iwl-3945.h" @@ -71,7 +73,6 @@ int iwl3945_param_queues_num = IWL39_MAX_NUM_QUEUES; /* def: 8 Tx queues */ /* * module name, copyright, version, etc. - * NOTE: DRV_NAME is defined in iwlwifi.h for use by iwl-debug.h and printk */ #define DRV_DESCRIPTION \ @@ -847,10 +848,11 @@ static int iwl3945_set_rxon_channel(struct iwl3945_priv *priv, * be #ifdef'd out once the driver is stable and folks aren't actively * making changes */ -static int iwl3945_check_rxon_cmd(struct iwl3945_rxon_cmd *rxon) +static int iwl3945_check_rxon_cmd(struct iwl3945_priv *priv) { int error = 0; int counter = 1; + struct iwl3945_rxon_cmd *rxon = &priv->staging_rxon; if (rxon->flags & RXON_FLG_BAND_24G_MSK) { error |= le32_to_cpu(rxon->flags & @@ -1031,7 +1033,7 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv) ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK); priv->staging_rxon.flags |= iwl3945_get_antenna_flags(priv); - rc = iwl3945_check_rxon_cmd(&priv->staging_rxon); + rc = iwl3945_check_rxon_cmd(priv); if (rc) { IWL_ERROR("Invalid RXON configuration. Not committing.\n"); return -EINVAL; @@ -7803,19 +7805,11 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e * 1. Allocating HW data * ********************/ - if ((iwl3945_param_queues_num > IWL39_MAX_NUM_QUEUES) || - (iwl3945_param_queues_num < IWL_MIN_NUM_QUEUES)) { - IWL_ERROR("invalid queues_num, should be between %d and %d\n", - IWL_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES); - err = -EINVAL; - goto out; - } - /* mac80211 allocates memory for this device instance, including * space for this driver's private structure */ hw = ieee80211_alloc_hw(sizeof(struct iwl3945_priv), &iwl3945_hw_ops); if (hw == NULL) { - IWL_ERROR("Can not allocate network device\n"); + printk(KERN_ERR DRV_NAME "Can not allocate network device\n"); err = -ENOMEM; goto out; } @@ -7827,6 +7821,14 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->pci_dev = pdev; priv->cfg = cfg; + if ((iwl3945_param_queues_num > IWL39_MAX_NUM_QUEUES) || + (iwl3945_param_queues_num < IWL_MIN_NUM_QUEUES)) { + IWL_ERROR("invalid queues_num, should be between %d and %d\n", + IWL_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES); + err = -EINVAL; + goto out; + } + /* Disabling hardware scan means that mac80211 will perform scans * "the hard way", rather than using device's scan. */ if (iwl3945_param_disable_hw_scan) { @@ -8293,13 +8295,14 @@ static int __init iwl3945_init(void) ret = iwl3945_rate_control_register(); if (ret) { - IWL_ERROR("Unable to register rate control algorithm: %d\n", ret); + printk(KERN_ERR DRV_NAME + "Unable to register rate control algorithm: %d\n", ret); return ret; } ret = pci_register_driver(&iwl3945_driver); if (ret) { - IWL_ERROR("Unable to initialize PCI module\n"); + printk(KERN_ERR DRV_NAME "Unable to initialize PCI module\n"); goto error_register; } -- GitLab From 0f741d9992ad043026218677c06042ac9f834f8f Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 19 Dec 2008 10:37:10 +0800 Subject: [PATCH 0704/4982] iwl3945: Getting rid of iwl3945_eeprom_channel The corresponding iwl structure is identical. Signed-off-by: Samuel Ortiz Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 59 +++------------------ drivers/net/wireless/iwlwifi/iwl-3945.h | 4 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 +- 3 files changed, 11 insertions(+), 56 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 21719eb7e14..b6145b0b925 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -69,6 +69,8 @@ #ifndef __iwl_3945_hw__ #define __iwl_3945_hw__ +#include "iwl-eeprom.h" + /* * uCode queue management definitions ... * Queue #4 is the command queue for 3945 and 4965. @@ -85,55 +87,8 @@ /* * EEPROM related constants, enums, and structures. */ - -/* - * EEPROM access time values: - * - * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG, - * then clearing (with subsequent read/modify/write) CSR_EEPROM_REG bit - * CSR_EEPROM_REG_BIT_CMD (0x2). - * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1). - * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec. - * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG. - */ -#define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */ - -/* - * Regulatory channel usage flags in EEPROM struct iwl_eeprom_channel.flags. - * - * IBSS and/or AP operation is allowed *only* on those channels with - * (VALID && IBSS && ACTIVE && !RADAR). This restriction is in place because - * RADAR detection is not supported by the 3945 driver, but is a - * requirement for establishing a new network for legal operation on channels - * requiring RADAR detection or restricting ACTIVE scanning. - * - * NOTE: "WIDE" flag indicates that 20 MHz channel is supported; - * 3945 does not support FAT 40 MHz-wide channels. - * - * NOTE: Using a channel inappropriately will result in a uCode error! - */ -enum { - EEPROM_CHANNEL_VALID = (1 << 0), /* usable for this SKU/geo */ - EEPROM_CHANNEL_IBSS = (1 << 1), /* usable as an IBSS channel */ - /* Bit 2 Reserved */ - EEPROM_CHANNEL_ACTIVE = (1 << 3), /* active scanning allowed */ - EEPROM_CHANNEL_RADAR = (1 << 4), /* radar detection required */ - EEPROM_CHANNEL_WIDE = (1 << 5), /* 20 MHz channel okay */ - /* Bit 6 Reserved (was Narrow Channel) */ - EEPROM_CHANNEL_DFS = (1 << 7), /* dynamic freq selection candidate */ -}; - -/* SKU Capabilities */ -#define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE (1 << 0) -#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE (1 << 1) #define EEPROM_SKU_CAP_OP_MODE_MRC (1 << 7) -/* *regulatory* channel data from eeprom, one for each channel */ -struct iwl3945_eeprom_channel { - u8 flags; /* flags copied from EEPROM */ - s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */ -} __attribute__ ((packed)); - /* * Mapping of a Tx power level, at factory calibration temperature, * to a radio/DSP gain table index. @@ -227,7 +182,7 @@ struct iwl3945_eeprom { * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 */ u16 band_1_count; /* abs.ofs: 196 */ - struct iwl3945_eeprom_channel band_1_channels[14]; /* abs.ofs: 196 */ + struct iwl_eeprom_channel band_1_channels[14]; /* abs.ofs: 196 */ /* * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196, @@ -235,28 +190,28 @@ struct iwl3945_eeprom { * (4915-5080MHz) (none of these is ever supported) */ u16 band_2_count; /* abs.ofs: 226 */ - struct iwl3945_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */ + struct iwl_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */ /* * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 * (5170-5320MHz) */ u16 band_3_count; /* abs.ofs: 254 */ - struct iwl3945_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */ + struct iwl_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */ /* * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 * (5500-5700MHz) */ u16 band_4_count; /* abs.ofs: 280 */ - struct iwl3945_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */ + struct iwl_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */ /* * 5.7 GHz channels 145, 149, 153, 157, 161, 165 * (5725-5825MHz) */ u16 band_5_count; /* abs.ofs: 304 */ - struct iwl3945_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */ + struct iwl_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */ u8 reserved9[194]; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 7e9ba5449c5..3295244caf4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -203,8 +203,8 @@ struct iwl3945_scan_power_info { struct iwl3945_channel_info { struct iwl3945_channel_tgd_info tgd; struct iwl3945_channel_tgh_info tgh; - struct iwl3945_eeprom_channel eeprom; /* EEPROM regulatory limit */ - struct iwl3945_eeprom_channel fat_eeprom; /* EEPROM regulatory limit for + struct iwl_eeprom_channel eeprom; /* EEPROM regulatory limit */ + struct iwl_eeprom_channel fat_eeprom; /* EEPROM regulatory limit for * FAT channel */ u8 channel; /* channel number */ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index c2e0152108d..b42354fda2c 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4483,7 +4483,7 @@ static const u8 iwl3945_eeprom_band_5[] = { /* 5725-5825MHz */ static void iwl3945_init_band_reference(const struct iwl3945_priv *priv, int band, int *eeprom_ch_count, - const struct iwl3945_eeprom_channel + const struct iwl_eeprom_channel **eeprom_ch_info, const u8 **eeprom_ch_index) { @@ -4558,7 +4558,7 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv) { int eeprom_ch_count = 0; const u8 *eeprom_ch_index = NULL; - const struct iwl3945_eeprom_channel *eeprom_ch_info = NULL; + const struct iwl_eeprom_channel *eeprom_ch_info = NULL; int band, ch; struct iwl3945_channel_info *ch_info; -- GitLab From 250bdd216c95907760b3fcc3aac1ed436d21c66c Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 19 Dec 2008 10:37:11 +0800 Subject: [PATCH 0705/4982] iwl3945: Have consistant and not redefined HW constants SRAM addresses are different for 3945, 4065, and 5000, let's give them different names. Also, the RSSI_OFFSET is different for 3945 and 4965, thus they should be named differently. Signed-off-by: Samuel Ortiz Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 26 +++++++++++---------- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +- drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 20 +++++++++------- drivers/net/wireless/iwlwifi/iwl-4965.c | 6 ++--- drivers/net/wireless/iwlwifi/iwl-5000-hw.h | 10 ++++++-- drivers/net/wireless/iwlwifi/iwl-5000.c | 9 +++---- drivers/net/wireless/iwlwifi/iwl-core.c | 5 ++-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 19 ++++++++------- 8 files changed, 55 insertions(+), 42 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index b6145b0b925..1182e6847a0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -82,7 +82,7 @@ #define LONG_SLOT_TIME 20 /* RSSI to dBm */ -#define IWL_RSSI_OFFSET 95 +#define IWL39_RSSI_OFFSET 95 /* * EEPROM related constants, enums, and structures. @@ -276,27 +276,29 @@ struct iwl3945_eeprom { /* Sizes and addresses for instruction and data memory (SRAM) in * 3945's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */ -#define RTC_INST_LOWER_BOUND (0x000000) -#define ALM_RTC_INST_UPPER_BOUND (0x014000) +#define IWL39_RTC_INST_LOWER_BOUND (0x000000) +#define IWL39_RTC_INST_UPPER_BOUND (0x014000) -#define RTC_DATA_LOWER_BOUND (0x800000) -#define ALM_RTC_DATA_UPPER_BOUND (0x808000) +#define IWL39_RTC_DATA_LOWER_BOUND (0x800000) +#define IWL39_RTC_DATA_UPPER_BOUND (0x808000) -#define ALM_RTC_INST_SIZE (ALM_RTC_INST_UPPER_BOUND - RTC_INST_LOWER_BOUND) -#define ALM_RTC_DATA_SIZE (ALM_RTC_DATA_UPPER_BOUND - RTC_DATA_LOWER_BOUND) +#define IWL39_RTC_INST_SIZE (IWL39_RTC_INST_UPPER_BOUND - \ + IWL39_RTC_INST_LOWER_BOUND) +#define IWL39_RTC_DATA_SIZE (IWL39_RTC_DATA_UPPER_BOUND - \ + IWL39_RTC_DATA_LOWER_BOUND) -#define IWL_MAX_INST_SIZE ALM_RTC_INST_SIZE -#define IWL_MAX_DATA_SIZE ALM_RTC_DATA_SIZE +#define IWL39_MAX_INST_SIZE IWL39_RTC_INST_SIZE +#define IWL39_MAX_DATA_SIZE IWL39_RTC_DATA_SIZE /* Size of uCode instruction memory in bootstrap state machine */ -#define IWL_MAX_BSM_SIZE ALM_RTC_INST_SIZE +#define IWL39_MAX_BSM_SIZE IWL39_RTC_INST_SIZE #define IWL39_MAX_NUM_QUEUES 8 static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr) { - return (addr >= RTC_DATA_LOWER_BOUND) && - (addr < ALM_RTC_DATA_UPPER_BOUND); + return (addr >= IWL39_RTC_DATA_LOWER_BOUND) && + (addr < IWL39_RTC_DATA_UPPER_BOUND); } /* Base physical address of iwl3945_shared is provided to FH_TSSR_CBB_BASE diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index b64e07f0dad..7ce43cbf0fa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -661,7 +661,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, /* Convert 3945's rssi indicator to dBm */ - rx_status.signal = rx_stats->rssi - IWL_RSSI_OFFSET; + rx_status.signal = rx_stats->rssi - IWL39_RSSI_OFFSET; /* Set default noise value to -127 */ if (priv->last_rx_noise == 0) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 6649f7b5565..9330b5a1aab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -89,7 +89,7 @@ #define LONG_SLOT_TIME 20 /* RSSI to dBm */ -#define IWL_RSSI_OFFSET 44 +#define IWL49_RSSI_OFFSET 44 @@ -129,24 +129,26 @@ /* Sizes and addresses for instruction and data memory (SRAM) in * 4965's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */ -#define RTC_INST_LOWER_BOUND (0x000000) +#define IWL49_RTC_INST_LOWER_BOUND (0x000000) #define IWL49_RTC_INST_UPPER_BOUND (0x018000) -#define RTC_DATA_LOWER_BOUND (0x800000) +#define IWL49_RTC_DATA_LOWER_BOUND (0x800000) #define IWL49_RTC_DATA_UPPER_BOUND (0x80A000) -#define IWL49_RTC_INST_SIZE (IWL49_RTC_INST_UPPER_BOUND - RTC_INST_LOWER_BOUND) -#define IWL49_RTC_DATA_SIZE (IWL49_RTC_DATA_UPPER_BOUND - RTC_DATA_LOWER_BOUND) +#define IWL49_RTC_INST_SIZE (IWL49_RTC_INST_UPPER_BOUND - \ + IWL49_RTC_INST_LOWER_BOUND) +#define IWL49_RTC_DATA_SIZE (IWL49_RTC_DATA_UPPER_BOUND - \ + IWL49_RTC_DATA_LOWER_BOUND) -#define IWL_MAX_INST_SIZE IWL49_RTC_INST_SIZE -#define IWL_MAX_DATA_SIZE IWL49_RTC_DATA_SIZE +#define IWL49_MAX_INST_SIZE IWL49_RTC_INST_SIZE +#define IWL49_MAX_DATA_SIZE IWL49_RTC_DATA_SIZE /* Size of uCode instruction memory in bootstrap state machine */ -#define IWL_MAX_BSM_SIZE BSM_SRAM_SIZE +#define IWL49_MAX_BSM_SIZE BSM_SRAM_SIZE static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr) { - return (addr >= RTC_DATA_LOWER_BOUND) && + return (addr >= IWL49_RTC_DATA_LOWER_BOUND) && (addr < IWL49_RTC_DATA_UPPER_BOUND); } diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index bb9617092c4..48223627dd2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -149,7 +149,7 @@ static int iwl4965_load_bsm(struct iwl_priv *priv) priv->ucode_type = UCODE_RT; /* make sure bootstrap program is no larger than BSM's SRAM size */ - if (len > IWL_MAX_BSM_SIZE) + if (len > IWL49_MAX_BSM_SIZE) return -EINVAL; /* Tell bootstrap uCode where to find the "Initialize" uCode @@ -186,7 +186,7 @@ static int iwl4965_load_bsm(struct iwl_priv *priv) /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */ iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0); - iwl_write_prph(priv, BSM_WR_MEM_DST_REG, RTC_INST_LOWER_BOUND); + iwl_write_prph(priv, BSM_WR_MEM_DST_REG, IWL49_RTC_INST_LOWER_BOUND); iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32)); /* Load bootstrap code into instruction SRAM now, @@ -2246,7 +2246,7 @@ static int iwl4965_calc_rssi(struct iwl_priv *priv, /* dBm = max_rssi dB - agc dB - constant. * Higher AGC (higher radio gain) means lower signal. */ - return max_rssi - agc - IWL_RSSI_OFFSET; + return max_rssi - agc - IWL49_RSSI_OFFSET; } diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h index 82c3859ce0f..d83e60577b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h @@ -68,10 +68,16 @@ #ifndef __iwl_5000_hw_h__ #define __iwl_5000_hw_h__ +#define IWL50_RTC_INST_LOWER_BOUND (0x000000) #define IWL50_RTC_INST_UPPER_BOUND (0x020000) + +#define IWL50_RTC_DATA_LOWER_BOUND (0x800000) #define IWL50_RTC_DATA_UPPER_BOUND (0x80C000) -#define IWL50_RTC_INST_SIZE (IWL50_RTC_INST_UPPER_BOUND - RTC_INST_LOWER_BOUND) -#define IWL50_RTC_DATA_SIZE (IWL50_RTC_DATA_UPPER_BOUND - RTC_DATA_LOWER_BOUND) + +#define IWL50_RTC_INST_SIZE (IWL50_RTC_INST_UPPER_BOUND - \ + IWL50_RTC_INST_LOWER_BOUND) +#define IWL50_RTC_DATA_SIZE (IWL50_RTC_DATA_UPPER_BOUND - \ + IWL50_RTC_DATA_LOWER_BOUND) /* EEPROM */ #define IWL_5000_EEPROM_IMG_SIZE 2048 diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 66d053d28a7..338444ab003 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -580,7 +580,8 @@ static int iwl5000_load_given_ucode(struct iwl_priv *priv, { int ret = 0; - ret = iwl5000_load_section(priv, inst_image, RTC_INST_LOWER_BOUND); + ret = iwl5000_load_section(priv, inst_image, + IWL50_RTC_INST_LOWER_BOUND); if (ret) return ret; @@ -600,7 +601,7 @@ static int iwl5000_load_given_ucode(struct iwl_priv *priv, priv->ucode_write_complete = 0; ret = iwl5000_load_section( - priv, data_image, RTC_DATA_LOWER_BOUND); + priv, data_image, IWL50_RTC_DATA_LOWER_BOUND); if (ret) return ret; @@ -1356,7 +1357,7 @@ static void iwl5000_rx_handler_setup(struct iwl_priv *priv) static int iwl5000_hw_valid_rtc_data_addr(u32 addr) { - return (addr >= RTC_DATA_LOWER_BOUND) && + return (addr >= IWL50_RTC_DATA_LOWER_BOUND) && (addr < IWL50_RTC_DATA_UPPER_BOUND); } @@ -1460,7 +1461,7 @@ static int iwl5000_calc_rssi(struct iwl_priv *priv, /* dBm = max_rssi dB - agc dB - constant. * Higher AGC (higher radio gain) means lower signal. */ - return max_rssi - agc - IWL_RSSI_OFFSET; + return max_rssi - agc - IWL49_RSSI_OFFSET; } static struct iwl_hcmd_ops iwl5000_hcmd = { diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 327d1bd4ff0..bee83d6a51c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1018,7 +1018,7 @@ static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 /* NOTE: Use the debugless read so we don't flood kernel log * if IWL_DL_IO is set */ iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, - i + RTC_INST_LOWER_BOUND); + i + IWL49_RTC_INST_LOWER_BOUND); val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); if (val != le32_to_cpu(*image)) { ret = -EIO; @@ -1051,7 +1051,8 @@ static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 *image, if (ret) return ret; - iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, RTC_INST_LOWER_BOUND); + iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, + IWL49_RTC_INST_LOWER_BOUND); errcnt = 0; for (; len > 0; len -= sizeof(u32), image++) { diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index b42354fda2c..3738ffa2dcd 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -5018,7 +5018,8 @@ static int iwl3945_verify_inst_full(struct iwl3945_priv *priv, __le32 *image, u3 if (rc) return rc; - iwl3945_write_direct32(priv, HBUS_TARG_MEM_RADDR, RTC_INST_LOWER_BOUND); + iwl3945_write_direct32(priv, HBUS_TARG_MEM_RADDR, + IWL39_RTC_INST_LOWER_BOUND); errcnt = 0; for (; len > 0; len -= sizeof(u32), image++) { @@ -5069,7 +5070,7 @@ static int iwl3945_verify_inst_sparse(struct iwl3945_priv *priv, __le32 *image, /* NOTE: Use the debugless read so we don't flood kernel log * if IWL_DL_IO is set */ iwl3945_write_direct32(priv, HBUS_TARG_MEM_RADDR, - i + RTC_INST_LOWER_BOUND); + i + IWL39_RTC_INST_LOWER_BOUND); val = _iwl3945_read_direct32(priv, HBUS_TARG_MEM_RDAT); if (val != le32_to_cpu(*image)) { #if 0 /* Enable this if you want to see details */ @@ -5219,7 +5220,7 @@ static int iwl3945_load_bsm(struct iwl3945_priv *priv) IWL_DEBUG_INFO("Begin load bsm\n"); /* make sure bootstrap program is no larger than BSM's SRAM size */ - if (len > IWL_MAX_BSM_SIZE) + if (len > IWL39_MAX_BSM_SIZE) return -EINVAL; /* Tell bootstrap uCode where to find the "Initialize" uCode @@ -5257,7 +5258,7 @@ static int iwl3945_load_bsm(struct iwl3945_priv *priv) /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */ iwl3945_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0); iwl3945_write_prph(priv, BSM_WR_MEM_DST_REG, - RTC_INST_LOWER_BOUND); + IWL39_RTC_INST_LOWER_BOUND); iwl3945_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32)); /* Load bootstrap code into instruction SRAM now, @@ -5401,32 +5402,32 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv) } /* Verify that uCode images will fit in card's SRAM */ - if (inst_size > IWL_MAX_INST_SIZE) { + if (inst_size > IWL39_MAX_INST_SIZE) { IWL_DEBUG_INFO("uCode instr len %d too large to fit in\n", inst_size); ret = -EINVAL; goto err_release; } - if (data_size > IWL_MAX_DATA_SIZE) { + if (data_size > IWL39_MAX_DATA_SIZE) { IWL_DEBUG_INFO("uCode data len %d too large to fit in\n", data_size); ret = -EINVAL; goto err_release; } - if (init_size > IWL_MAX_INST_SIZE) { + if (init_size > IWL39_MAX_INST_SIZE) { IWL_DEBUG_INFO("uCode init instr len %d too large to fit in\n", init_size); ret = -EINVAL; goto err_release; } - if (init_data_size > IWL_MAX_DATA_SIZE) { + if (init_data_size > IWL39_MAX_DATA_SIZE) { IWL_DEBUG_INFO("uCode init data len %d too large to fit in\n", init_data_size); ret = -EINVAL; goto err_release; } - if (boot_size > IWL_MAX_BSM_SIZE) { + if (boot_size > IWL39_MAX_BSM_SIZE) { IWL_DEBUG_INFO("uCode boot instr len %d too large to fit in\n", boot_size); ret = -EINVAL; -- GitLab From d9829a67f953379b5cab6b78ae8f7a879a591eb1 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 19 Dec 2008 10:37:12 +0800 Subject: [PATCH 0706/4982] iwl3945: Use iwl-agn-rs.h rates definitions. A lot of rate relates definition are shared between iwl-3945-rs.h and iwl-agn-rs.h. Let's just use the agn version, and add the 3945 specific constants there. Signed-off-by: Samuel Ortiz Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 45 +++-- drivers/net/wireless/iwlwifi/iwl-3945-rs.h | 206 -------------------- drivers/net/wireless/iwlwifi/iwl-3945.c | 6 +- drivers/net/wireless/iwlwifi/iwl-3945.h | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.h | 53 ++++- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 6 files changed, 80 insertions(+), 234 deletions(-) delete mode 100644 drivers/net/wireless/iwlwifi/iwl-3945-rs.h diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 42b8bc495d8..3fa9570f82b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -64,7 +64,7 @@ struct iwl3945_rs_sta { u8 start_rate; u8 ibss_sta_added; struct timer_list rate_scale_flush; - struct iwl3945_rate_scale_data win[IWL_RATE_COUNT]; + struct iwl3945_rate_scale_data win[IWL_RATE_COUNT_3945]; #ifdef CONFIG_MAC80211_DEBUGFS struct dentry *rs_sta_dbgfs_stats_table_file; #endif @@ -73,19 +73,19 @@ struct iwl3945_rs_sta { int last_txrate_idx; }; -static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT] = { +static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT_3945] = { 7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202 }; -static s32 iwl3945_expected_tpt_g_prot[IWL_RATE_COUNT] = { +static s32 iwl3945_expected_tpt_g_prot[IWL_RATE_COUNT_3945] = { 7, 13, 35, 58, 0, 0, 0, 80, 93, 113, 123, 125 }; -static s32 iwl3945_expected_tpt_a[IWL_RATE_COUNT] = { +static s32 iwl3945_expected_tpt_a[IWL_RATE_COUNT_3945] = { 0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186 }; -static s32 iwl3945_expected_tpt_b[IWL_RATE_COUNT] = { +static s32 iwl3945_expected_tpt_b[IWL_RATE_COUNT_3945] = { 7, 13, 35, 58, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -121,7 +121,7 @@ static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = { #define IWL_RATE_MAX_WINDOW 62 #define IWL_RATE_FLUSH (3*HZ) #define IWL_RATE_WIN_FLUSH (HZ/2) -#define IWL_RATE_HIGH_TH 11520 +#define IWL39_RATE_HIGH_TH 11520 #define IWL_SUCCESS_UP_TH 8960 #define IWL_SUCCESS_DOWN_TH 10880 #define IWL_RATE_MIN_FAILURE_TH 8 @@ -167,7 +167,7 @@ static void iwl3945_clear_window(struct iwl3945_rate_scale_data *window) window->success_counter = 0; window->success_ratio = -1; window->counter = 0; - window->average_tpt = IWL_INV_TPT; + window->average_tpt = IWL_INVALID_VALUE; window->stamp = 0; } @@ -190,7 +190,7 @@ static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta) * and it has been more than IWL_RATE_WIN_FLUSH * since we flushed, clear out the gathered statistics */ - for (i = 0; i < IWL_RATE_COUNT; i++) { + for (i = 0; i < IWL_RATE_COUNT_3945; i++) { if (!rs_sta->win[i].counter) continue; @@ -334,7 +334,7 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, window->average_tpt = ((window->success_ratio * rs_sta->expected_tpt[index] + 64) / 128); else - window->average_tpt = IWL_INV_TPT; + window->average_tpt = IWL_INVALID_VALUE; spin_unlock_irqrestore(&rs_sta->lock, flags); @@ -425,7 +425,7 @@ static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp) rs_sta->rate_scale_flush.data = (unsigned long)rs_sta; rs_sta->rate_scale_flush.function = &iwl3945_bg_rate_scale_flush; - for (i = 0; i < IWL_RATE_COUNT; i++) + for (i = 0; i < IWL_RATE_COUNT_3945; i++) iwl3945_clear_window(&rs_sta->win[i]); IWL_DEBUG_RATE("leave\n"); @@ -471,7 +471,7 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband retries = info->status.rates[0].count; first_index = sband->bitrates[info->status.rates[0].idx].hw_value; - if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) { + if ((first_index < 0) || (first_index >= IWL_RATE_COUNT_3945)) { IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index); return; } @@ -575,7 +575,8 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, /* Find the next rate that is in the rate mask */ i = index + 1; - for (mask = (1 << i); i < IWL_RATE_COUNT; i++, mask <<= 1) { + for (mask = (1 << i); i < IWL_RATE_COUNT_3945; + i++, mask <<= 1) { if (rate_mask & mask) { high = i; break; @@ -641,9 +642,9 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, int index; struct iwl3945_rs_sta *rs_sta = priv_sta; struct iwl3945_rate_scale_data *window = NULL; - int current_tpt = IWL_INV_TPT; - int low_tpt = IWL_INV_TPT; - int high_tpt = IWL_INV_TPT; + int current_tpt = IWL_INVALID_VALUE; + int low_tpt = IWL_INVALID_VALUE; + int high_tpt = IWL_INVALID_VALUE; u32 fail_count; s8 scale_action = 0; unsigned long flags; @@ -674,7 +675,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, return; } - index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1); + index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT_3945 - 1); if (sband->band == IEEE80211_BAND_5GHZ) rate_mask = rate_mask << IWL_FIRST_OFDM_RATE; @@ -744,16 +745,18 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) { IWL_DEBUG_RATE("decrease rate because of low success_ratio\n"); scale_action = -1; - } else if ((low_tpt == IWL_INV_TPT) && (high_tpt == IWL_INV_TPT)) + } else if ((low_tpt == IWL_INVALID_VALUE) && + (high_tpt == IWL_INVALID_VALUE)) scale_action = 1; - else if ((low_tpt != IWL_INV_TPT) && (high_tpt != IWL_INV_TPT) && + else if ((low_tpt != IWL_INVALID_VALUE) && + (high_tpt != IWL_INVALID_VALUE) && (low_tpt < current_tpt) && (high_tpt < current_tpt)) { IWL_DEBUG_RATE("No action -- low [%d] & high [%d] < " "current_tpt [%d]\n", low_tpt, high_tpt, current_tpt); scale_action = 0; } else { - if (high_tpt != IWL_INV_TPT) { + if (high_tpt != IWL_INVALID_VALUE) { if (high_tpt > current_tpt) scale_action = 1; else { @@ -761,7 +764,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, ("decrease rate because of high tpt\n"); scale_action = -1; } - } else if (low_tpt != IWL_INV_TPT) { + } else if (low_tpt != IWL_INVALID_VALUE) { if (low_tpt > current_tpt) { IWL_DEBUG_RATE ("decrease rate because of low tpt\n"); @@ -835,7 +838,7 @@ static ssize_t iwl3945_sta_dbgfs_stats_table_read(struct file *file, lq_sta->tx_packets, lq_sta->last_txrate_idx, lq_sta->start_rate, jiffies_to_msecs(lq_sta->flush_time)); - for (j = 0; j < IWL_RATE_COUNT; j++) { + for (j = 0; j < IWL_RATE_COUNT_3945; j++) { desc += sprintf(buff+desc, "counter=%d success=%d %%=%d\n", lq_sta->win[j].counter, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h deleted file mode 100644 index b5a66135ded..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h +++ /dev/null @@ -1,206 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#ifndef __iwl_3945_rs_h__ -#define __iwl_3945_rs_h__ - -struct iwl3945_rate_info { - u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ - u8 ieee; /* MAC header: IWL_RATE_6M_IEEE, etc. */ - u8 prev_ieee; /* previous rate in IEEE speeds */ - u8 next_ieee; /* next rate in IEEE speeds */ - u8 prev_rs; /* previous rate used in rs algo */ - u8 next_rs; /* next rate used in rs algo */ - u8 prev_rs_tgg; /* previous rate used in TGG rs algo */ - u8 next_rs_tgg; /* next rate used in TGG rs algo */ - u8 table_rs_index; /* index in rate scale table cmd */ - u8 prev_table_rs; /* prev in rate table cmd */ -}; - -/* - * These serve as indexes into - * struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT]; - */ -enum { - IWL_RATE_1M_INDEX = 0, - IWL_RATE_2M_INDEX, - IWL_RATE_5M_INDEX, - IWL_RATE_11M_INDEX, - IWL_RATE_6M_INDEX, - IWL_RATE_9M_INDEX, - IWL_RATE_12M_INDEX, - IWL_RATE_18M_INDEX, - IWL_RATE_24M_INDEX, - IWL_RATE_36M_INDEX, - IWL_RATE_48M_INDEX, - IWL_RATE_54M_INDEX, - IWL_RATE_COUNT, - IWL_RATE_INVM_INDEX, - IWL_RATE_INVALID = IWL_RATE_INVM_INDEX -}; - -enum { - IWL_RATE_6M_INDEX_TABLE = 0, - IWL_RATE_9M_INDEX_TABLE, - IWL_RATE_12M_INDEX_TABLE, - IWL_RATE_18M_INDEX_TABLE, - IWL_RATE_24M_INDEX_TABLE, - IWL_RATE_36M_INDEX_TABLE, - IWL_RATE_48M_INDEX_TABLE, - IWL_RATE_54M_INDEX_TABLE, - IWL_RATE_1M_INDEX_TABLE, - IWL_RATE_2M_INDEX_TABLE, - IWL_RATE_5M_INDEX_TABLE, - IWL_RATE_11M_INDEX_TABLE, - IWL_RATE_INVM_INDEX_TABLE = IWL_RATE_INVM_INDEX, -}; - -enum { - IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX, - IWL_LAST_OFDM_RATE = IWL_RATE_54M_INDEX, - IWL_FIRST_CCK_RATE = IWL_RATE_1M_INDEX, - IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX, -}; - -/* #define vs. enum to keep from defaulting to 'large integer' */ -#define IWL_RATE_6M_MASK (1 << IWL_RATE_6M_INDEX) -#define IWL_RATE_9M_MASK (1 << IWL_RATE_9M_INDEX) -#define IWL_RATE_12M_MASK (1 << IWL_RATE_12M_INDEX) -#define IWL_RATE_18M_MASK (1 << IWL_RATE_18M_INDEX) -#define IWL_RATE_24M_MASK (1 << IWL_RATE_24M_INDEX) -#define IWL_RATE_36M_MASK (1 << IWL_RATE_36M_INDEX) -#define IWL_RATE_48M_MASK (1 << IWL_RATE_48M_INDEX) -#define IWL_RATE_54M_MASK (1 << IWL_RATE_54M_INDEX) -#define IWL_RATE_1M_MASK (1 << IWL_RATE_1M_INDEX) -#define IWL_RATE_2M_MASK (1 << IWL_RATE_2M_INDEX) -#define IWL_RATE_5M_MASK (1 << IWL_RATE_5M_INDEX) -#define IWL_RATE_11M_MASK (1 << IWL_RATE_11M_INDEX) - -/* 3945 uCode API values for (legacy) bit rates, both OFDM and CCK */ -enum { - IWL_RATE_6M_PLCP = 13, - IWL_RATE_9M_PLCP = 15, - IWL_RATE_12M_PLCP = 5, - IWL_RATE_18M_PLCP = 7, - IWL_RATE_24M_PLCP = 9, - IWL_RATE_36M_PLCP = 11, - IWL_RATE_48M_PLCP = 1, - IWL_RATE_54M_PLCP = 3, - IWL_RATE_1M_PLCP = 10, - IWL_RATE_2M_PLCP = 20, - IWL_RATE_5M_PLCP = 55, - IWL_RATE_11M_PLCP = 110, -}; - -/* MAC header values for bit rates */ -enum { - IWL_RATE_6M_IEEE = 12, - IWL_RATE_9M_IEEE = 18, - IWL_RATE_12M_IEEE = 24, - IWL_RATE_18M_IEEE = 36, - IWL_RATE_24M_IEEE = 48, - IWL_RATE_36M_IEEE = 72, - IWL_RATE_48M_IEEE = 96, - IWL_RATE_54M_IEEE = 108, - IWL_RATE_1M_IEEE = 2, - IWL_RATE_2M_IEEE = 4, - IWL_RATE_5M_IEEE = 11, - IWL_RATE_11M_IEEE = 22, -}; - -#define IWL_CCK_BASIC_RATES_MASK \ - (IWL_RATE_1M_MASK | \ - IWL_RATE_2M_MASK) - -#define IWL_CCK_RATES_MASK \ - (IWL_BASIC_RATES_MASK | \ - IWL_RATE_5M_MASK | \ - IWL_RATE_11M_MASK) - -#define IWL_OFDM_BASIC_RATES_MASK \ - (IWL_RATE_6M_MASK | \ - IWL_RATE_12M_MASK | \ - IWL_RATE_24M_MASK) - -#define IWL_OFDM_RATES_MASK \ - (IWL_OFDM_BASIC_RATES_MASK | \ - IWL_RATE_9M_MASK | \ - IWL_RATE_18M_MASK | \ - IWL_RATE_36M_MASK | \ - IWL_RATE_48M_MASK | \ - IWL_RATE_54M_MASK) - -#define IWL_BASIC_RATES_MASK \ - (IWL_OFDM_BASIC_RATES_MASK | \ - IWL_CCK_BASIC_RATES_MASK) - -#define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1) - -#define IWL_INV_TPT -1 - -#define IWL_MIN_RSSI_VAL -100 -#define IWL_MAX_RSSI_VAL 0 - -extern const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT]; - -static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index) -{ - u8 rate = iwl3945_rates[rate_index].prev_ieee; - - if (rate == IWL_RATE_INVALID) - rate = rate_index; - return rate; -} - -/** - * iwl3945_rate_scale_init - Initialize the rate scale table based on assoc info - * - * The specific throughput table used is based on the type of network - * the associated with, including A, B, G, and G w/ TGG protection - */ -extern void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id); - -/** - * iwl3945_rate_control_register - Register the rate control algorithm callbacks - * - * Since the rate control algorithm is hardware specific, there is no need - * or reason to place it as a stand alone module. The driver can call - * iwl3945_rate_control_register in order to register the rate control callbacks - * with the mac80211 subsystem. This should be performed prior to calling - * ieee80211_register_hw - * - */ -extern int iwl3945_rate_control_register(void); - -/** - * iwl3945_rate_control_unregister - Unregister the rate control callbacks - * - * This should be called after calling ieee80211_unregister_hw, but before - * the driver is unloaded. - */ -extern void iwl3945_rate_control_unregister(void); - -#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 7ce43cbf0fa..d7d40ecc6b6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -43,7 +43,7 @@ #include "iwl-commands.h" #include "iwl-3945.h" #include "iwl-helpers.h" -#include "iwl-3945-rs.h" +#include "iwl-agn-rs.h" #define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np) \ [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ @@ -65,7 +65,7 @@ * maps to IWL_RATE_INVALID * */ -const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT] = { +const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945] = { IWL_DECLARE_RATE_INFO(1, INV, 2, INV, 2, INV, 2), /* 1mbps */ IWL_DECLARE_RATE_INFO(2, 1, 5, 1, 5, 1, 5), /* 2mbps */ IWL_DECLARE_RATE_INFO(5, 2, 6, 2, 11, 2, 11), /*5.5mbps */ @@ -1700,7 +1700,7 @@ int iwl3945_hw_reg_send_txpower(struct iwl3945_priv *priv) /* fill cmd with power settings for all rates for current channel */ /* Fill OFDM rate */ for (rate_idx = IWL_FIRST_OFDM_RATE, i = 0; - rate_idx <= IWL_LAST_OFDM_RATE; rate_idx++, i++) { + rate_idx <= IWL39_LAST_OFDM_RATE; rate_idx++, i++) { txpower.power[i].tpc = ch_info->power_info[i].tpc; txpower.power[i].rate = iwl3945_rates[rate_idx].plcp; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 3295244caf4..6d0ec0a65b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -233,7 +233,7 @@ struct iwl3945_clip_group { const s8 clip_powers[IWL_MAX_RATES]; }; -#include "iwl-3945-rs.h" +#include "iwl-agn-rs.h" #define IWL_TX_FIFO_AC0 0 #define IWL_TX_FIFO_AC1 1 diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index 78ee83adf74..7c21292b3ae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h @@ -27,8 +27,6 @@ #ifndef __iwl_agn_rs_h__ #define __iwl_agn_rs_h__ -#include "iwl-dev.h" - struct iwl_rate_info { u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ u8 plcp_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */ @@ -43,6 +41,19 @@ struct iwl_rate_info { u8 next_rs_tgg; /* next rate used in TGG rs algo */ }; +struct iwl3945_rate_info { + u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ + u8 ieee; /* MAC header: IWL_RATE_6M_IEEE, etc. */ + u8 prev_ieee; /* previous rate in IEEE speeds */ + u8 next_ieee; /* next rate in IEEE speeds */ + u8 prev_rs; /* previous rate used in rs algo */ + u8 next_rs; /* next rate used in rs algo */ + u8 prev_rs_tgg; /* previous rate used in TGG rs algo */ + u8 next_rs_tgg; /* next rate used in TGG rs algo */ + u8 table_rs_index; /* index in rate scale table cmd */ + u8 prev_table_rs; /* prev in rate table cmd */ +}; + /* * These serve as indexes into * struct iwl_rate_info iwl_rates[IWL_RATE_COUNT]; @@ -62,12 +73,30 @@ enum { IWL_RATE_54M_INDEX, IWL_RATE_60M_INDEX, IWL_RATE_COUNT, /*FIXME:RS:change to IWL_RATE_INDEX_COUNT,*/ + IWL_RATE_COUNT_3945 = IWL_RATE_COUNT - 1, IWL_RATE_INVM_INDEX = IWL_RATE_COUNT, IWL_RATE_INVALID = IWL_RATE_COUNT, }; +enum { + IWL_RATE_6M_INDEX_TABLE = 0, + IWL_RATE_9M_INDEX_TABLE, + IWL_RATE_12M_INDEX_TABLE, + IWL_RATE_18M_INDEX_TABLE, + IWL_RATE_24M_INDEX_TABLE, + IWL_RATE_36M_INDEX_TABLE, + IWL_RATE_48M_INDEX_TABLE, + IWL_RATE_54M_INDEX_TABLE, + IWL_RATE_1M_INDEX_TABLE, + IWL_RATE_2M_INDEX_TABLE, + IWL_RATE_5M_INDEX_TABLE, + IWL_RATE_11M_INDEX_TABLE, + IWL_RATE_INVM_INDEX_TABLE = IWL_RATE_INVM_INDEX - 1, +}; + enum { IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX, + IWL39_LAST_OFDM_RATE = IWL_RATE_54M_INDEX, IWL_LAST_OFDM_RATE = IWL_RATE_60M_INDEX, IWL_FIRST_CCK_RATE = IWL_RATE_1M_INDEX, IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX, @@ -248,6 +277,7 @@ enum { #define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y)) extern const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT]; +extern const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945]; enum iwl_table_type { LQ_NONE, @@ -303,6 +333,23 @@ static inline u8 iwl_get_prev_ieee_rate(u8 rate_index) return rate; } +static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index) +{ + u8 rate = iwl3945_rates[rate_index].prev_ieee; + + if (rate == IWL_RATE_INVALID) + rate = rate_index; + return rate; +} + +/** + * iwl3945_rate_scale_init - Initialize the rate scale table based on assoc info + * + * The specific throughput table used is based on the type of network + * the associated with, including A, B, G, and G w/ TGG protection + */ +extern void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id); + /** * iwl_rate_control_register - Register the rate control algorithm callbacks * @@ -314,6 +361,7 @@ static inline u8 iwl_get_prev_ieee_rate(u8 rate_index) * */ extern int iwlagn_rate_control_register(void); +extern int iwl3945_rate_control_register(void); /** * iwl_rate_control_unregister - Unregister the rate control callbacks @@ -322,5 +370,6 @@ extern int iwlagn_rate_control_register(void); * the driver is unloaded. */ extern void iwlagn_rate_control_unregister(void); +extern void iwl3945_rate_control_unregister(void); #endif /* __iwl_agn__rs__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 3738ffa2dcd..df785246ba1 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4843,7 +4843,7 @@ static void iwl3945_init_hw_rates(struct iwl3945_priv *priv, rates[i].hw_value = i; /* Rate scaling will work on indexes */ rates[i].hw_value_short = i; rates[i].flags = 0; - if ((i > IWL_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) { + if ((i > IWL39_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) { /* * If CCK != 1M then set short preamble rate flag. */ -- GitLab From b5b83239e7a3540ff31db24249b90f9f6d7f5be8 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 19 Dec 2008 10:37:13 +0800 Subject: [PATCH 0707/4982] iwl3945: Getting rid of iwl-3945-led.h The duplicated LED definitions prevent one from including iwl-dev.h from the 3945 specific C files. Moreover, we are sharing many definitions between iwl-3945-led.h and iwl-led.h, so let's just use the iwl one. Note that this file will get more cleanups once we share a common iwl_priv structure. Signed-off-by: Samuel Ortiz Acked-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-led.h | 16 +--------------- drivers/net/wireless/iwlwifi/iwl-led.h | 4 +++- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.h b/drivers/net/wireless/iwlwifi/iwl-3945-led.h index 749ac035fd6..b697c890f62 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.h @@ -30,22 +30,8 @@ struct iwl3945_priv; #ifdef CONFIG_IWL3945_LEDS -#define IWL_LED_SOLID 11 -#define IWL_LED_NAME_LEN 31 -#define IWL_DEF_LED_INTRVL __constant_cpu_to_le32(1000) -#define IWL_LED_ACTIVITY (0<<1) -#define IWL_LED_LINK (1<<1) - -enum led_type { - IWL_LED_TRG_TX, - IWL_LED_TRG_RX, - IWL_LED_TRG_ASSOC, - IWL_LED_TRG_RADIO, - IWL_LED_TRG_MAX, -}; - -#include +#include "iwl-led.h" struct iwl3945_led { struct iwl3945_priv *priv; diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h index 021e00bcd1b..0b50b909939 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-led.h @@ -30,7 +30,7 @@ struct iwl_priv; -#ifdef CONFIG_IWLWIFI_LEDS +#if defined(CONFIG_IWLWIFI_LEDS) || defined(CONFIG_IWL3945_LEDS) #include #define IWL_LED_SOLID 11 @@ -47,7 +47,9 @@ enum led_type { IWL_LED_TRG_RADIO, IWL_LED_TRG_MAX, }; +#endif +#ifdef CONFIG_IWLWIFI_LEDS struct iwl_led { struct iwl_priv *priv; -- GitLab From 1125eff3ae26b2e39c6bf940b5e0b8774ebd2896 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 19 Dec 2008 10:37:14 +0800 Subject: [PATCH 0708/4982] iwl3945: Remove power related definitions from 3945 code Most of the power (not TX power, but power management) structures and definitions are duplicated accross iwl-power.h and iwl-3945.h. We should try to only use the iwl header. Signed-off-by: Samuel Ortiz Acked-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.h | 28 +-------------------- drivers/net/wireless/iwlwifi/iwl-power.h | 16 ++++++++++++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 25 +++++++++--------- 3 files changed, 30 insertions(+), 39 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 6d0ec0a65b1..dd15b3203a6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -47,6 +47,7 @@ extern struct pci_device_id iwl3945_hw_card_ids[]; #include "iwl-prph.h" #include "iwl-3945-hw.h" #include "iwl-debug.h" +#include "iwl-power.h" #include "iwl-3945-led.h" /* Highest firmware API version supported */ @@ -246,33 +247,6 @@ struct iwl3945_clip_group { /* Minimum number of queues. MAX_NUM is defined in hw specific files */ #define IWL_MIN_NUM_QUEUES 4 -/* Power management (not Tx power) structures */ - -struct iwl3945_power_vec_entry { - struct iwl_powertable_cmd cmd; - u8 no_dtim; -}; -#define IWL_POWER_RANGE_0 (0) -#define IWL_POWER_RANGE_1 (1) - -#define IWL_POWER_MODE_CAM 0x00 /* Continuously Aware Mode, always on */ -#define IWL_POWER_INDEX_3 0x03 -#define IWL_POWER_INDEX_5 0x05 -#define IWL_POWER_AC 0x06 -#define IWL_POWER_BATTERY 0x07 -#define IWL_POWER_LIMIT 0x07 -#define IWL_POWER_MASK 0x0F -#define IWL_POWER_ENABLED 0x10 -#define IWL_POWER_LEVEL(x) ((x) & IWL_POWER_MASK) - -struct iwl3945_power_mgr { - spinlock_t lock; - struct iwl3945_power_vec_entry pwr_range_0[IWL_POWER_AC]; - struct iwl3945_power_vec_entry pwr_range_1[IWL_POWER_AC]; - u8 active_index; - u32 dtim_val; -}; - #define IEEE80211_DATA_LEN 2304 #define IEEE80211_4ADDR_LEN 30 #define IEEE80211_HLEN (IEEE80211_4ADDR_LEN) diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h index fa098d8975c..7cab04f1bf4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/iwl-power.h @@ -42,7 +42,10 @@ enum { IWL_POWER_INDEX_5, IWL_POWER_AUTO, IWL_POWER_MAX = IWL_POWER_AUTO, + IWL39_POWER_AC = IWL_POWER_AUTO, /* 0x06 */ IWL_POWER_AC, + IWL39_POWER_BATTERY = IWL_POWER_AC, /* 0x07 */ + IWL39_POWER_LIMIT = IWL_POWER_AC, IWL_POWER_BATTERY, }; @@ -56,6 +59,11 @@ enum { #define IWL_POWER_MASK 0x0F #define IWL_POWER_ENABLED 0x10 +#define IWL_POWER_RANGE_0 (0) +#define IWL_POWER_RANGE_1 (1) + +#define IWL_POWER_LEVEL(x) ((x) & IWL_POWER_MASK) + /* Power management (not Tx power) structures */ struct iwl_power_vec_entry { @@ -78,6 +86,14 @@ struct iwl_power_mgr { u8 power_disabled; /* flag to disable using power saving level */ }; +struct iwl3945_power_mgr { + spinlock_t lock; + struct iwl_power_vec_entry pwr_range_0[IWL_POWER_AC]; + struct iwl_power_vec_entry pwr_range_1[IWL_POWER_AC]; + u8 active_index; + u32 dtim_val; +}; + void iwl_setup_power_deferred_work(struct iwl_priv *priv); void iwl_power_cancel_timeout(struct iwl_priv *priv); int iwl_power_update_mode(struct iwl_priv *priv, bool force); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index df785246ba1..aac8825237f 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1815,7 +1815,7 @@ static void iwl3945_activate_qos(struct iwl3945_priv *priv, u8 force) /* default power management (not Tx power) table values */ /* for TIM 0-10 */ -static struct iwl3945_power_vec_entry range_0[IWL_POWER_AC] = { +static struct iwl_power_vec_entry range_0[IWL39_POWER_AC] = { {{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, {{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0}, {{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(300), SLP_VEC(2, 4, 6, 7, 7)}, 0}, @@ -1825,7 +1825,7 @@ static struct iwl3945_power_vec_entry range_0[IWL_POWER_AC] = { }; /* for TIM > 10 */ -static struct iwl3945_power_vec_entry range_1[IWL_POWER_AC] = { +static struct iwl_power_vec_entry range_1[IWL39_POWER_AC] = { {{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, {{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0}, @@ -1842,7 +1842,7 @@ int iwl3945_power_init_handle(struct iwl3945_priv *priv) { int rc = 0, i; struct iwl3945_power_mgr *pow_data; - int size = sizeof(struct iwl3945_power_vec_entry) * IWL_POWER_AC; + int size = sizeof(struct iwl_power_vec_entry) * IWL39_POWER_AC; u16 pci_pm; IWL_DEBUG_POWER("Initialize power \n"); @@ -1865,7 +1865,7 @@ int iwl3945_power_init_handle(struct iwl3945_priv *priv) IWL_DEBUG_POWER("adjust power command flags\n"); - for (i = 0; i < IWL_POWER_AC; i++) { + for (i = 0; i < IWL39_POWER_AC; i++) { cmd = &pow_data->pwr_range_0[i].cmd; if (pci_pm & 0x1) @@ -1883,7 +1883,7 @@ static int iwl3945_update_power_cmd(struct iwl3945_priv *priv, int rc = 0, i; u8 skip; u32 max_sleep = 0; - struct iwl3945_power_vec_entry *range; + struct iwl_power_vec_entry *range; u8 period = 0; struct iwl3945_power_mgr *pow_data; @@ -1951,10 +1951,10 @@ static int iwl3945_send_power_mode(struct iwl3945_priv *priv, u32 mode) * if plugged into AC power, set to CAM ("continuously aware mode"), * else user level */ switch (mode) { - case IWL_POWER_BATTERY: + case IWL39_POWER_BATTERY: final_mode = IWL_POWER_INDEX_3; break; - case IWL_POWER_AC: + case IWL39_POWER_AC: final_mode = IWL_POWER_MODE_CAM; break; default: @@ -7511,8 +7511,9 @@ static ssize_t store_power_level(struct device *d, goto out; } - if ((mode < 1) || (mode > IWL_POWER_LIMIT) || (mode == IWL_POWER_AC)) - mode = IWL_POWER_AC; + if ((mode < 1) || (mode > IWL39_POWER_LIMIT) || + (mode == IWL39_POWER_AC)) + mode = IWL39_POWER_AC; else mode |= IWL_POWER_ENABLED; @@ -7560,10 +7561,10 @@ static ssize_t show_power_level(struct device *d, p += sprintf(p, "%d ", level); switch (level) { case IWL_POWER_MODE_CAM: - case IWL_POWER_AC: + case IWL39_POWER_AC: p += sprintf(p, "(AC)"); break; - case IWL_POWER_BATTERY: + case IWL39_POWER_BATTERY: p += sprintf(p, "(BATTERY)"); break; default: @@ -7968,7 +7969,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->rates_mask = IWL_RATES_MASK; /* If power management is turned on, default to AC mode */ - priv->power_mode = IWL_POWER_AC; + priv->power_mode = IWL39_POWER_AC; priv->user_txpower_limit = IWL_DEFAULT_TX_POWER; err = iwl3945_init_channel_map(priv); -- GitLab From d20b3c65f2a3e18ea86542e6ca4fe1c6d16c91df Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 19 Dec 2008 10:37:15 +0800 Subject: [PATCH 0709/4982] iwl3945: iwl3945_queue and iwl3945_channel_info replacement This patch replaces the queue and channel info 3945 structures with the iwl ones. The initial goal was to replace the channel info structure. Once we do that, and then include iwl-dev.h instead of iwl-3945.h, we still get build errors due to several routines and macro redefinitions. This is why this patch also includes: - TFD39_MAX_PAYLOAD definition for 3945. - CMD_SIZE, CMD_HUGE, CMD_SKB duplication removal. - iwl3945_queue replacement in order to also get rid of the duplicated get_cmd_index routine. Getting rid of any of those needs the iwl-dev.h inclusion which then creates build errors due to definitions duplication. This is why we include all those in the same patch. Signed-off-by: Samuel Ortiz Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 3 - drivers/net/wireless/iwlwifi/iwl-3945.c | 20 +-- drivers/net/wireless/iwlwifi/iwl-3945.h | 155 +------------------- drivers/net/wireless/iwlwifi/iwl-dev.h | 33 +++++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 69 +++------ 5 files changed, 71 insertions(+), 209 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 1182e6847a0..5d461bd7756 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -265,9 +265,6 @@ struct iwl3945_eeprom { #define TFD_TX_CMD_SLOTS 256 #define TFD_CMD_SLOTS 32 -#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl3945_cmd) - \ - sizeof(struct iwl3945_cmd_meta)) - /* * RX related structures and functions */ diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index d7d40ecc6b6..14f0923a475 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -306,7 +306,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv, int txq_id, int index) { struct iwl3945_tx_queue *txq = &priv->txq[txq_id]; - struct iwl3945_queue *q = &txq->q; + struct iwl_queue *q = &txq->q; struct iwl3945_tx_info *tx_info; BUG_ON(txq_id == IWL_CMD_QUEUE_NUM); @@ -320,7 +320,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv, iwl3945_hw_txq_free_tfd(priv, txq); } - if (iwl3945_queue_space(q) > q->low_mark && (txq_id >= 0) && + if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) && (txq_id != IWL_CMD_QUEUE_NUM) && priv->mac80211_registered) ieee80211_wake_queue(priv->hw, txq_id); @@ -1618,7 +1618,7 @@ static inline u8 iwl3945_hw_reg_fix_power_index(int index) */ static void iwl3945_hw_reg_set_scan_power(struct iwl3945_priv *priv, u32 scan_tbl_index, s32 rate_index, const s8 *clip_pwrs, - struct iwl3945_channel_info *ch_info, + struct iwl_channel_info *ch_info, int band_index) { struct iwl3945_scan_power_info *scan_power_info; @@ -1675,7 +1675,7 @@ static void iwl3945_hw_reg_set_scan_power(struct iwl3945_priv *priv, u32 scan_tb int iwl3945_hw_reg_send_txpower(struct iwl3945_priv *priv) { int rate_idx, i; - const struct iwl3945_channel_info *ch_info = NULL; + const struct iwl_channel_info *ch_info = NULL; struct iwl3945_txpowertable_cmd txpower = { .channel = priv->active_rxon.channel, }; @@ -1748,7 +1748,7 @@ int iwl3945_hw_reg_send_txpower(struct iwl3945_priv *priv) * and send changes to NIC */ static int iwl3945_hw_reg_set_new_power(struct iwl3945_priv *priv, - struct iwl3945_channel_info *ch_info) + struct iwl_channel_info *ch_info) { struct iwl3945_channel_power_info *power_info; int power_changed = 0; @@ -1810,7 +1810,7 @@ static int iwl3945_hw_reg_set_new_power(struct iwl3945_priv *priv, * based strictly on regulatory (eeprom and spectrum mgt) limitations * (no consideration for h/w clipping limitations). */ -static int iwl3945_hw_reg_get_ch_txpower_limit(struct iwl3945_channel_info *ch_info) +static int iwl3945_hw_reg_get_ch_txpower_limit(struct iwl_channel_info *ch_info) { s8 max_power; @@ -1840,7 +1840,7 @@ static int iwl3945_hw_reg_get_ch_txpower_limit(struct iwl3945_channel_info *ch_i */ static int iwl3945_hw_reg_comp_txpower_temp(struct iwl3945_priv *priv) { - struct iwl3945_channel_info *ch_info = NULL; + struct iwl_channel_info *ch_info = NULL; int delta_index; const s8 *clip_pwrs; /* array of h/w max power levels for each rate */ u8 a_band; @@ -1901,7 +1901,7 @@ static int iwl3945_hw_reg_comp_txpower_temp(struct iwl3945_priv *priv) int iwl3945_hw_reg_set_txpower(struct iwl3945_priv *priv, s8 power) { - struct iwl3945_channel_info *ch_info; + struct iwl_channel_info *ch_info; s8 max_power; u8 a_band; u8 i; @@ -1999,7 +1999,7 @@ static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work) * channel in each group 1-4. Group 5 All B/G channels are in group 0. */ static u16 iwl3945_hw_reg_get_ch_grp_index(struct iwl3945_priv *priv, - const struct iwl3945_channel_info *ch_info) + const struct iwl_channel_info *ch_info) { struct iwl3945_eeprom_txpower_group *ch_grp = &priv->eeprom.groups[0]; u8 group; @@ -2162,7 +2162,7 @@ static void iwl3945_hw_reg_init_channel_groups(struct iwl3945_priv *priv) */ int iwl3945_txpower_set_from_eeprom(struct iwl3945_priv *priv) { - struct iwl3945_channel_info *ch_info = NULL; + struct iwl_channel_info *ch_info = NULL; struct iwl3945_channel_power_info *pwr_info; int delta_index; u8 rate_index; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index dd15b3203a6..46bbd8180ba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -48,6 +48,7 @@ extern struct pci_device_id iwl3945_hw_card_ids[]; #include "iwl-3945-hw.h" #include "iwl-debug.h" #include "iwl-power.h" +#include "iwl-dev.h" #include "iwl-3945-led.h" /* Highest firmware API version supported */ @@ -111,26 +112,7 @@ struct iwl3945_rx_mem_buffer { struct list_head list; }; -/* - * Generic queue structure - * - * Contains common data for Rx and Tx queues - */ -struct iwl3945_queue { - int n_bd; /* number of BDs in this queue */ - int write_ptr; /* 1-st empty entry (index) host_w*/ - int read_ptr; /* last used entry (index) host_r*/ - dma_addr_t dma_addr; /* physical addr for BD's */ - int n_window; /* safe queue window */ - u32 id; - int low_mark; /* low watermark, resume queue if free - * space more than this */ - int high_mark; /* high watermark, stop queue if free - * space less than this */ -} __attribute__ ((packed)); - -int iwl3945_queue_space(const struct iwl3945_queue *q); -int iwl3945_x2_queue_used(const struct iwl3945_queue *q, int i); +int iwl3945_x2_queue_used(const struct iwl_queue *q, int i); #define MAX_NUM_OF_TBS (20) @@ -152,7 +134,7 @@ struct iwl3945_tx_info { * descriptors) and required locking structures. */ struct iwl3945_tx_queue { - struct iwl3945_queue q; + struct iwl_queue q; struct iwl3945_tfd_frame *bd; struct iwl3945_cmd *cmd; dma_addr_t dma_addr_cmd; @@ -161,73 +143,6 @@ struct iwl3945_tx_queue { int active; }; -#define IWL_NUM_SCAN_RATES (2) - -struct iwl3945_channel_tgd_info { - u8 type; - s8 max_power; -}; - -struct iwl3945_channel_tgh_info { - s64 last_radar_time; -}; - -/* current Tx power values to use, one for each rate for each channel. - * requested power is limited by: - * -- regulatory EEPROM limits for this channel - * -- hardware capabilities (clip-powers) - * -- spectrum management - * -- user preference (e.g. iwconfig) - * when requested power is set, base power index must also be set. */ -struct iwl3945_channel_power_info { - struct iwl3945_tx_power tpc; /* actual radio and DSP gain settings */ - s8 power_table_index; /* actual (compenst'd) index into gain table */ - s8 base_power_index; /* gain index for power at factory temp. */ - s8 requested_power; /* power (dBm) requested for this chnl/rate */ -}; - -/* current scan Tx power values to use, one for each scan rate for each - * channel. */ -struct iwl3945_scan_power_info { - struct iwl3945_tx_power tpc; /* actual radio and DSP gain settings */ - s8 power_table_index; /* actual (compenst'd) index into gain table */ - s8 requested_power; /* scan pwr (dBm) requested for chnl/rate */ -}; - -/* - * One for each channel, holds all channel setup data - * Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant - * with one another! - */ -#define IWL4965_MAX_RATE (33) - -struct iwl3945_channel_info { - struct iwl3945_channel_tgd_info tgd; - struct iwl3945_channel_tgh_info tgh; - struct iwl_eeprom_channel eeprom; /* EEPROM regulatory limit */ - struct iwl_eeprom_channel fat_eeprom; /* EEPROM regulatory limit for - * FAT channel */ - - u8 channel; /* channel number */ - u8 flags; /* flags copied from EEPROM */ - s8 max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */ - s8 curr_txpow; /* (dBm) regulatory/spectrum/user (not h/w) */ - s8 min_power; /* always 0 */ - s8 scan_power; /* (dBm) regul. eeprom, direct scans, any rate */ - - u8 group_index; /* 0-4, maps channel to group1/2/3/4/5 */ - u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */ - enum ieee80211_band band; - - /* Radio/DSP gain settings for each "normal" data Tx rate. - * These include, in addition to RF and DSP gain, a few fields for - * remembering/modifying gain settings (indexes). */ - struct iwl3945_channel_power_info power_info[IWL4965_MAX_RATE]; - - /* Radio/DSP gain settings for each scan rate, for directed scans. */ - struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES]; -}; - struct iwl3945_clip_group { /* maximum power level to prevent clipping for each rate, derived by * us from this band's saturation power in EEPROM */ @@ -266,15 +181,6 @@ struct iwl3945_frame { #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) -enum { - /* CMD_SIZE_NORMAL = 0, */ - CMD_SIZE_HUGE = (1 << 0), - /* CMD_SYNC = 0, */ - CMD_ASYNC = (1 << 1), - /* CMD_NO_SKB = 0, */ - CMD_WANT_SKB = (1 << 2), -}; - struct iwl3945_cmd; struct iwl3945_priv; @@ -328,7 +234,7 @@ struct iwl3945_host_cmd { const void *data; }; -#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl3945_cmd) - \ +#define TFD39_MAX_PAYLOAD_SIZE (sizeof(struct iwl3945_cmd) - \ sizeof(struct iwl3945_cmd_meta)) /* @@ -453,13 +359,6 @@ struct iwl3945_station_entry { struct iwl3945_hw_key keyinfo; }; -/* one for each uCode image (inst/data, boot/init/runtime) */ -struct fw_desc { - void *v_addr; /* access by driver */ - dma_addr_t p_addr; /* access by card's busmaster DMA */ - u32 len; /* bytes */ -}; - /* uCode file layout */ struct iwl3945_ucode { __le32 ver; /* major/minor/API/serial */ @@ -629,16 +528,6 @@ extern int iwl3945_txpower_set_from_eeprom(struct iwl3945_priv *priv); extern u8 iwl3945_sync_sta(struct iwl3945_priv *priv, int sta_id, u16 tx_rate, u8 flags); - -#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT - -enum { - MEASUREMENT_READY = (1 << 0), - MEASUREMENT_ACTIVE = (1 << 1), -}; - -#endif - #ifdef CONFIG_IWL3945_RFKILL struct iwl3945_priv; @@ -682,7 +571,7 @@ struct iwl3945_priv { /* we allocate array of iwl3945_channel_info for NIC's valid channels. * Access via channel # using indirect index array */ - struct iwl3945_channel_info *channel_info; /* channel info array */ + struct iwl_channel_info *channel_info; /* channel info array */ u8 channel_count; /* # of channels */ /* each calibration channel group in the EEPROM has a derived @@ -873,39 +762,7 @@ static inline int iwl3945_is_associated(struct iwl3945_priv *priv) return (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0; } -static inline int is_channel_valid(const struct iwl3945_channel_info *ch_info) -{ - if (ch_info == NULL) - return 0; - return (ch_info->flags & EEPROM_CHANNEL_VALID) ? 1 : 0; -} - -static inline int is_channel_radar(const struct iwl3945_channel_info *ch_info) -{ - return (ch_info->flags & EEPROM_CHANNEL_RADAR) ? 1 : 0; -} - -static inline u8 is_channel_a_band(const struct iwl3945_channel_info *ch_info) -{ - return ch_info->band == IEEE80211_BAND_5GHZ; -} - -static inline u8 is_channel_bg_band(const struct iwl3945_channel_info *ch_info) -{ - return ch_info->band == IEEE80211_BAND_2GHZ; -} - -static inline int is_channel_passive(const struct iwl3945_channel_info *ch) -{ - return (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) ? 1 : 0; -} - -static inline int is_channel_ibss(const struct iwl3945_channel_info *ch) -{ - return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0; -} - -extern const struct iwl3945_channel_info *iwl3945_get_channel_info( +extern const struct iwl_channel_info *iwl3945_get_channel_info( const struct iwl3945_priv *priv, enum ieee80211_band band, u16 channel); extern int iwl3945_rs_next_rate(struct iwl3945_priv *priv, int rate); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 73a0b6c53e1..f63209aaeaf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -39,6 +39,7 @@ #include "iwl-rfkill.h" #include "iwl-eeprom.h" #include "iwl-4965-hw.h" +#include "iwl-3945-hw.h" #include "iwl-csr.h" #include "iwl-prph.h" #include "iwl-debug.h" @@ -153,6 +154,30 @@ struct iwl4965_channel_tgh_info { s64 last_radar_time; }; +#define IWL4965_MAX_RATE (33) + +/* current Tx power values to use, one for each rate for each channel. + * requested power is limited by: + * -- regulatory EEPROM limits for this channel + * -- hardware capabilities (clip-powers) + * -- spectrum management + * -- user preference (e.g. iwconfig) + * when requested power is set, base power index must also be set. */ +struct iwl3945_channel_power_info { + struct iwl3945_tx_power tpc; /* actual radio and DSP gain settings */ + s8 power_table_index; /* actual (compenst'd) index into gain table */ + s8 base_power_index; /* gain index for power at factory temp. */ + s8 requested_power; /* power (dBm) requested for this chnl/rate */ +}; + +/* current scan Tx power values to use, one for each scan rate for each + * channel. */ +struct iwl3945_scan_power_info { + struct iwl3945_tx_power tpc; /* actual radio and DSP gain settings */ + s8 power_table_index; /* actual (compenst'd) index into gain table */ + s8 requested_power; /* scan pwr (dBm) requested for chnl/rate */ +}; + /* * One for each channel, holds all channel setup data * Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant @@ -183,6 +208,14 @@ struct iwl_channel_info { s8 fat_scan_power; /* (dBm) eeprom, direct scans, any rate */ u8 fat_flags; /* flags copied from EEPROM */ u8 fat_extension_channel; /* HT_IE_EXT_CHANNEL_* */ + + /* Radio/DSP gain settings for each "normal" data Tx rate. + * These include, in addition to RF and DSP gain, a few fields for + * remembering/modifying gain settings (indexes). */ + struct iwl3945_channel_power_info power_info[IWL4965_MAX_RATE]; + + /* Radio/DSP gain settings for each scan rate, for directed scans. */ + struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES]; }; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index aac8825237f..421c944b187 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -53,6 +53,7 @@ #include "iwl-3945.h" #include "iwl-3945-fh.h" #include "iwl-helpers.h" +#include "iwl-dev.h" static int iwl3945_tx_queue_update_write_ptr(struct iwl3945_priv *priv, struct iwl3945_tx_queue *txq); @@ -132,44 +133,17 @@ static const struct ieee80211_supported_band *iwl3945_get_band( * (#0-3) for data tx via EDCA. An additional 2 HCCA queues are unused. ***************************************************/ -int iwl3945_queue_space(const struct iwl3945_queue *q) -{ - int s = q->read_ptr - q->write_ptr; - - if (q->read_ptr > q->write_ptr) - s -= q->n_bd; - - if (s <= 0) - s += q->n_window; - /* keep some reserve to not confuse empty and full situations */ - s -= 2; - if (s < 0) - s = 0; - return s; -} - -int iwl3945_x2_queue_used(const struct iwl3945_queue *q, int i) +int iwl3945_x2_queue_used(const struct iwl_queue *q, int i) { return q->write_ptr > q->read_ptr ? (i >= q->read_ptr && i < q->write_ptr) : !(i < q->read_ptr && i >= q->write_ptr); } - -static inline u8 get_cmd_index(struct iwl3945_queue *q, u32 index, int is_huge) -{ - /* This is for scan command, the big buffer at end of command array */ - if (is_huge) - return q->n_window; /* must be power of 2 */ - - /* Otherwise, use normal size buffers */ - return index & (q->n_window - 1); -} - /** * iwl3945_queue_init - Initialize queue's high/low-water and read/write indexes */ -static int iwl3945_queue_init(struct iwl3945_priv *priv, struct iwl3945_queue *q, +static int iwl3945_queue_init(struct iwl3945_priv *priv, struct iwl_queue *q, int count, int slots_num, u32 id) { q->n_bd = count; @@ -297,7 +271,7 @@ int iwl3945_tx_queue_init(struct iwl3945_priv *priv, */ void iwl3945_tx_queue_free(struct iwl3945_priv *priv, struct iwl3945_tx_queue *txq) { - struct iwl3945_queue *q = &txq->q; + struct iwl_queue *q = &txq->q; struct pci_dev *dev = priv->pci_dev; int len; @@ -581,7 +555,7 @@ static const char *get_cmd_string(u8 cmd) static int iwl3945_enqueue_hcmd(struct iwl3945_priv *priv, struct iwl3945_host_cmd *cmd) { struct iwl3945_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; - struct iwl3945_queue *q = &txq->q; + struct iwl_queue *q = &txq->q; struct iwl3945_tfd_frame *tfd; u32 *control_flags; struct iwl3945_cmd *out_cmd; @@ -596,7 +570,7 @@ static int iwl3945_enqueue_hcmd(struct iwl3945_priv *priv, struct iwl3945_host_c /* If any of the command structures end up being larger than * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then * we will need to increase the size of the TFD entries */ - BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && + BUG_ON((fix_size > TFD39_MAX_PAYLOAD_SIZE) && !(cmd->meta.flags & CMD_SIZE_HUGE)); @@ -605,7 +579,7 @@ static int iwl3945_enqueue_hcmd(struct iwl3945_priv *priv, struct iwl3945_host_c return -EIO; } - if (iwl3945_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) { + if (iwl_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) { IWL_ERROR("No space for Tx\n"); return -ENOSPC; } @@ -2171,7 +2145,7 @@ static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv, int mode) { - const struct iwl3945_channel_info *ch_info; + const struct iwl_channel_info *ch_info; memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon)); @@ -2241,7 +2215,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv, static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode) { if (mode == NL80211_IFTYPE_ADHOC) { - const struct iwl3945_channel_info *ch_info; + const struct iwl_channel_info *ch_info; ch_info = iwl3945_get_channel_info(priv, priv->band, @@ -2457,7 +2431,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) u32 *control_flags; int txq_id = skb_get_queue_mapping(skb); struct iwl3945_tx_queue *txq = NULL; - struct iwl3945_queue *q = NULL; + struct iwl_queue *q = NULL; dma_addr_t phys_addr; dma_addr_t txcmd_phys; struct iwl3945_cmd *out_cmd = NULL; @@ -2652,7 +2626,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) if (rc) return rc; - if ((iwl3945_queue_space(q) < q->high_mark) + if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { if (wait_write_ptr) { spin_lock_irqsave(&priv->lock, flags); @@ -3305,7 +3279,7 @@ static void iwl3945_cmd_queue_reclaim(struct iwl3945_priv *priv, int txq_id, int index) { struct iwl3945_tx_queue *txq = &priv->txq[txq_id]; - struct iwl3945_queue *q = &txq->q; + struct iwl_queue *q = &txq->q; int nfreed = 0; if ((index >= q->n_bd) || (iwl3945_x2_queue_used(q, index) == 0)) { @@ -4524,8 +4498,9 @@ static void iwl3945_init_band_reference(const struct iwl3945_priv *priv, int ban * * Based on band and channel number. */ -const struct iwl3945_channel_info *iwl3945_get_channel_info(const struct iwl3945_priv *priv, - enum ieee80211_band band, u16 channel) +const struct iwl_channel_info * +iwl3945_get_channel_info(const struct iwl3945_priv *priv, + enum ieee80211_band band, u16 channel) { int i; @@ -4560,7 +4535,7 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv) const u8 *eeprom_ch_index = NULL; const struct iwl_eeprom_channel *eeprom_ch_info = NULL; int band, ch; - struct iwl3945_channel_info *ch_info; + struct iwl_channel_info *ch_info; if (priv->channel_count) { IWL_DEBUG_INFO("Channel map already initialized.\n"); @@ -4584,7 +4559,7 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv) IWL_DEBUG_INFO("Parsing data for %d channels.\n", priv->channel_count); - priv->channel_info = kzalloc(sizeof(struct iwl3945_channel_info) * + priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) * priv->channel_count, GFP_KERNEL); if (!priv->channel_info) { IWL_ERROR("Could not allocate channel_info\n"); @@ -4746,7 +4721,7 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, { const struct ieee80211_channel *channels = NULL; const struct ieee80211_supported_band *sband; - const struct iwl3945_channel_info *ch_info; + const struct iwl_channel_info *ch_info; u16 passive_dwell = 0; u16 active_dwell = 0; int added, i; @@ -4858,7 +4833,7 @@ static void iwl3945_init_hw_rates(struct iwl3945_priv *priv, */ static int iwl3945_init_geos(struct iwl3945_priv *priv) { - struct iwl3945_channel_info *ch; + struct iwl_channel_info *ch; struct ieee80211_supported_band *sband; struct ieee80211_channel *channels; struct ieee80211_channel *geo_ch; @@ -6585,7 +6560,7 @@ static int iwl3945_mac_add_interface(struct ieee80211_hw *hw, static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed) { struct iwl3945_priv *priv = hw->priv; - const struct iwl3945_channel_info *ch_info; + const struct iwl_channel_info *ch_info; struct ieee80211_conf *conf = &hw->conf; unsigned long flags; int ret = 0; @@ -7112,7 +7087,7 @@ static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw, struct iwl3945_priv *priv = hw->priv; int i, avail; struct iwl3945_tx_queue *txq; - struct iwl3945_queue *q; + struct iwl_queue *q; unsigned long flags; IWL_DEBUG_MAC80211("enter\n"); @@ -7127,7 +7102,7 @@ static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw, for (i = 0; i < AC_NUM; i++) { txq = &priv->txq[i]; q = &txq->q; - avail = iwl3945_queue_space(q); + avail = iwl_queue_space(q); stats[i].len = q->n_window - avail; stats[i].limit = q->n_window - q->high_mark; -- GitLab From 6d6498947da40485f691bcbafdc4e9b3280a9b3b Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Fri, 19 Dec 2008 10:37:16 +0800 Subject: [PATCH 0710/4982] iwlwifi: emliminate iwl3945_mac_get_stats mac80211 handler This patch removes empty iwl3945_mac_get_stats mac80211 handler. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 421c944b187..667ea7068f3 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -7116,12 +7116,6 @@ static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw, return 0; } -static int iwl3945_mac_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) -{ - return 0; -} - static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) { struct iwl3945_priv *priv = hw->priv; @@ -7762,7 +7756,6 @@ static struct ieee80211_ops iwl3945_hw_ops = { .config_interface = iwl3945_mac_config_interface, .configure_filter = iwl3945_configure_filter, .set_key = iwl3945_mac_set_key, - .get_stats = iwl3945_mac_get_stats, .get_tx_stats = iwl3945_mac_get_tx_stats, .conf_tx = iwl3945_mac_conf_tx, .reset_tsf = iwl3945_mac_reset_tsf, -- GitLab From eaa686c37d12aac37f955eb7643a62370c84ee12 Mon Sep 17 00:00:00 2001 From: "Kolekar, Abhijeet" Date: Fri, 19 Dec 2008 10:37:17 +0800 Subject: [PATCH 0711/4982] iwl3945: Change IWLWIFI_VERSION constant name Change IWLWIFI_VERSION to IWL3945_VERSION. Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 667ea7068f3..063ee65e7ec 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -91,10 +91,10 @@ int iwl3945_param_queues_num = IWL39_MAX_NUM_QUEUES; /* def: 8 Tx queues */ #define VS #endif -#define IWLWIFI_VERSION "1.2.26k" VD VS +#define IWL39_VERSION "1.2.26k" VD VS #define DRV_COPYRIGHT "Copyright(c) 2003-2008 Intel Corporation" #define DRV_AUTHOR "" -#define DRV_VERSION IWLWIFI_VERSION +#define DRV_VERSION IWL39_VERSION MODULE_DESCRIPTION(DRV_DESCRIPTION); -- GitLab From 5747d47fb469613901e76a1380daf14901e76092 Mon Sep 17 00:00:00 2001 From: "Kolekar, Abhijeet" Date: Fri, 19 Dec 2008 10:37:18 +0800 Subject: [PATCH 0712/4982] iwl3945: include iwl-core.h Use iwl-core.h instead of iwl-3945-core.h. Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-core.h | 104 ------------------- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +- drivers/net/wireless/iwlwifi/iwl-core.h | 30 ++++++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 52 +--------- 4 files changed, 32 insertions(+), 156 deletions(-) delete mode 100644 drivers/net/wireless/iwlwifi/iwl-3945-core.h diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-core.h b/drivers/net/wireless/iwlwifi/iwl-3945-core.h deleted file mode 100644 index 6f463555402..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-3945-core.h +++ /dev/null @@ -1,104 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef __iwl_3945_dev_h__ -#define __iwl_3945_dev_h__ - -#define IWL_PCI_DEVICE(dev, subdev, cfg) \ - .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \ - .subvendor = PCI_ANY_ID, .subdevice = (subdev), \ - .driver_data = (kernel_ulong_t)&(cfg) - -#define IWL_SKU_G 0x1 -#define IWL_SKU_A 0x2 - -/** - * struct iwl_3945_cfg - * @fw_name_pre: Firmware filename prefix. The api version and extension - * (.ucode) will be added to filename before loading from disk. The - * filename is constructed as fw_name_pre.ucode. - * @ucode_api_max: Highest version of uCode API supported by driver. - * @ucode_api_min: Lowest version of uCode API supported by driver. - * - * We enable the driver to be backward compatible wrt API version. The - * driver specifies which APIs it supports (with @ucode_api_max being the - * highest and @ucode_api_min the lowest). Firmware will only be loaded if - * it has a supported API version. The firmware's API version will be - * stored in @iwl_priv, enabling the driver to make runtime changes based - * on firmware version used. - * - * For example, - * if (IWL_UCODE_API(priv->ucode_ver) >= 2) { - * Driver interacts with Firmware API version >= 2. - * } else { - * Driver interacts with Firmware API version 1. - * } - */ -struct iwl_3945_cfg { - const char *name; - const char *fw_name_pre; - const unsigned int ucode_api_max; - const unsigned int ucode_api_min; - unsigned int sku; -}; - -#endif /* __iwl_dev_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 14f0923a475..8c40f669978 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -38,11 +38,11 @@ #include #include -#include "iwl-3945-core.h" #include "iwl-3945-fh.h" #include "iwl-commands.h" #include "iwl-3945.h" #include "iwl-helpers.h" +#include "iwl-core.h" #include "iwl-agn-rs.h" #define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np) \ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 7c3a20a986b..a3cc43dd845 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -205,6 +205,36 @@ struct iwl_cfg { const struct iwl_mod_params *mod_params; }; +/** + * struct iwl_3945_cfg + * @fw_name_pre: Firmware filename prefix. The api version and extension + * (.ucode) will be added to filename before loading from disk. The + * filename is constructed as fw_name_pre.ucode. + * @ucode_api_max: Highest version of uCode API supported by driver. + * @ucode_api_min: Lowest version of uCode API supported by driver. + * + * We enable the driver to be backward compatible wrt API version. The + * driver specifies which APIs it supports (with @ucode_api_max being the + * highest and @ucode_api_min the lowest). Firmware will only be loaded if + * it has a supported API version. The firmware's API version will be + * stored in @iwl_priv, enabling the driver to make runtime changes based + * on firmware version used. + * + * For example, + * if (IWL_UCODE_API(priv->ucode_ver) >= 2) { + * Driver interacts with Firmware API version >= 2. + * } else { + * Driver interacts with Firmware API version 1. + * } + */ +struct iwl_3945_cfg { + const char *name; + const char *fw_name_pre; + const unsigned int ucode_api_max; + const unsigned int ucode_api_min; + unsigned int sku; +}; + /*************************** * L i b * ***************************/ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 063ee65e7ec..c3fd7c651ba 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -48,11 +48,11 @@ #define DRV_NAME "iwl3945" -#include "iwl-3945-core.h" #include "iwl-commands.h" #include "iwl-3945.h" #include "iwl-3945-fh.h" #include "iwl-helpers.h" +#include "iwl-core.h" #include "iwl-dev.h" static int iwl3945_tx_queue_update_write_ptr(struct iwl3945_priv *priv, @@ -491,56 +491,6 @@ static inline int iwl3945_is_ready_rf(struct iwl3945_priv *priv) /*************** HOST COMMAND QUEUE FUNCTIONS *****/ #define IWL_CMD(x) case x: return #x - -static const char *get_cmd_string(u8 cmd) -{ - switch (cmd) { - IWL_CMD(REPLY_ALIVE); - IWL_CMD(REPLY_ERROR); - IWL_CMD(REPLY_RXON); - IWL_CMD(REPLY_RXON_ASSOC); - IWL_CMD(REPLY_QOS_PARAM); - IWL_CMD(REPLY_RXON_TIMING); - IWL_CMD(REPLY_ADD_STA); - IWL_CMD(REPLY_REMOVE_STA); - IWL_CMD(REPLY_REMOVE_ALL_STA); - IWL_CMD(REPLY_3945_RX); - IWL_CMD(REPLY_TX); - IWL_CMD(REPLY_RATE_SCALE); - IWL_CMD(REPLY_LEDS_CMD); - IWL_CMD(REPLY_TX_LINK_QUALITY_CMD); - IWL_CMD(RADAR_NOTIFICATION); - IWL_CMD(REPLY_QUIET_CMD); - IWL_CMD(REPLY_CHANNEL_SWITCH); - IWL_CMD(CHANNEL_SWITCH_NOTIFICATION); - IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD); - IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION); - IWL_CMD(POWER_TABLE_CMD); - IWL_CMD(PM_SLEEP_NOTIFICATION); - IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC); - IWL_CMD(REPLY_SCAN_CMD); - IWL_CMD(REPLY_SCAN_ABORT_CMD); - IWL_CMD(SCAN_START_NOTIFICATION); - IWL_CMD(SCAN_RESULTS_NOTIFICATION); - IWL_CMD(SCAN_COMPLETE_NOTIFICATION); - IWL_CMD(BEACON_NOTIFICATION); - IWL_CMD(REPLY_TX_BEACON); - IWL_CMD(WHO_IS_AWAKE_NOTIFICATION); - IWL_CMD(QUIET_NOTIFICATION); - IWL_CMD(REPLY_TX_PWR_TABLE_CMD); - IWL_CMD(MEASURE_ABORT_NOTIFICATION); - IWL_CMD(REPLY_BT_CONFIG); - IWL_CMD(REPLY_STATISTICS_CMD); - IWL_CMD(STATISTICS_NOTIFICATION); - IWL_CMD(REPLY_CARD_STATE_CMD); - IWL_CMD(CARD_STATE_NOTIFICATION); - IWL_CMD(MISSED_BEACONS_NOTIFICATION); - default: - return "UNKNOWN"; - - } -} - #define HOST_COMPLETE_TIMEOUT (HZ / 2) /** -- GitLab From c0f20d91417bc8a4b54e1917a45f8fd4cf9f2991 Mon Sep 17 00:00:00 2001 From: "Kolekar, Abhijeet" Date: Fri, 19 Dec 2008 10:37:19 +0800 Subject: [PATCH 0713/4982] iwl3945: replace iwl_3945_cfg with iwl_cfg The patch replaces iwl_3945_cfg with iwl_cfg for 3945. Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 4 +-- drivers/net/wireless/iwlwifi/iwl-3945.h | 2 +- drivers/net/wireless/iwlwifi/iwl-core.h | 30 --------------------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 4 files changed, 4 insertions(+), 34 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 8c40f669978..93e5c52d91d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2507,7 +2507,7 @@ void iwl3945_hw_cancel_deferred_work(struct iwl3945_priv *priv) cancel_delayed_work(&priv->thermal_periodic); } -static struct iwl_3945_cfg iwl3945_bg_cfg = { +static struct iwl_cfg iwl3945_bg_cfg = { .name = "3945BG", .fw_name_pre = IWL3945_FW_PRE, .ucode_api_max = IWL3945_UCODE_API_MAX, @@ -2515,7 +2515,7 @@ static struct iwl_3945_cfg iwl3945_bg_cfg = { .sku = IWL_SKU_G, }; -static struct iwl_3945_cfg iwl3945_abg_cfg = { +static struct iwl_cfg iwl3945_abg_cfg = { .name = "3945ABG", .fw_name_pre = IWL3945_FW_PRE, .ucode_api_max = IWL3945_UCODE_API_MAX, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 46bbd8180ba..760482e1201 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -547,7 +547,7 @@ struct iwl3945_priv { struct ieee80211_hw *hw; struct ieee80211_channel *ieee_channels; struct ieee80211_rate *ieee_rates; - struct iwl_3945_cfg *cfg; /* device configuration */ + struct iwl_cfg *cfg; /* device configuration */ /* temporary frame storage list */ struct list_head free_frames; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index a3cc43dd845..7c3a20a986b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -205,36 +205,6 @@ struct iwl_cfg { const struct iwl_mod_params *mod_params; }; -/** - * struct iwl_3945_cfg - * @fw_name_pre: Firmware filename prefix. The api version and extension - * (.ucode) will be added to filename before loading from disk. The - * filename is constructed as fw_name_pre.ucode. - * @ucode_api_max: Highest version of uCode API supported by driver. - * @ucode_api_min: Lowest version of uCode API supported by driver. - * - * We enable the driver to be backward compatible wrt API version. The - * driver specifies which APIs it supports (with @ucode_api_max being the - * highest and @ucode_api_min the lowest). Firmware will only be loaded if - * it has a supported API version. The firmware's API version will be - * stored in @iwl_priv, enabling the driver to make runtime changes based - * on firmware version used. - * - * For example, - * if (IWL_UCODE_API(priv->ucode_ver) >= 2) { - * Driver interacts with Firmware API version >= 2. - * } else { - * Driver interacts with Firmware API version 1. - * } - */ -struct iwl_3945_cfg { - const char *name; - const char *fw_name_pre; - const unsigned int ucode_api_max; - const unsigned int ucode_api_min; - unsigned int sku; -}; - /*************************** * L i b * ***************************/ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index c3fd7c651ba..c597c242292 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -7718,7 +7718,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e int err = 0; struct iwl3945_priv *priv; struct ieee80211_hw *hw; - struct iwl_3945_cfg *cfg = (struct iwl_3945_cfg *)(ent->driver_data); + struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); unsigned long flags; /*********************** -- GitLab From 85d4149533e07e5ca4c94010a52fe5496d998611 Mon Sep 17 00:00:00 2001 From: "Kolekar, Abhijeet" Date: Fri, 19 Dec 2008 10:37:20 +0800 Subject: [PATCH 0714/4982] iwl3945: move structures from iwl-3945.h to iwl-dev.h The patch moves few structres from iwl-3945.h to iwl-dev.h. Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.h | 46 ----------------------- drivers/net/wireless/iwlwifi/iwl-dev.h | 49 +++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 46 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 760482e1201..f51393046de 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -121,34 +121,6 @@ struct iwl3945_tx_info { struct sk_buff *skb[MAX_NUM_OF_TBS]; }; -/** - * struct iwl3945_tx_queue - Tx Queue for DMA - * @q: generic Rx/Tx queue descriptor - * @bd: base of circular buffer of TFDs - * @cmd: array of command/Tx buffers - * @dma_addr_cmd: physical address of cmd/tx buffer array - * @txb: array of per-TFD driver data - * @need_update: indicates need to update read/write index - * - * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame - * descriptors) and required locking structures. - */ -struct iwl3945_tx_queue { - struct iwl_queue q; - struct iwl3945_tfd_frame *bd; - struct iwl3945_cmd *cmd; - dma_addr_t dma_addr_cmd; - struct iwl3945_tx_info *txb; - int need_update; - int active; -}; - -struct iwl3945_clip_group { - /* maximum power level to prevent clipping for each rate, derived by - * us from this band's saturation power in EEPROM */ - const s8 clip_powers[IWL_MAX_RATES]; -}; - #include "iwl-agn-rs.h" #define IWL_TX_FIFO_AC0 0 @@ -303,16 +275,6 @@ struct iwl3945_rx_queue { #define IWL_INVALID_RATE 0xFF #define IWL_INVALID_VALUE -1 -struct iwl3945_tid_data { - u16 seq_number; -}; - -struct iwl3945_hw_key { - enum ieee80211_key_alg alg; - int keylen; - u8 key[32]; -}; - union iwl3945_ht_rate_supp { u16 rates; struct { @@ -351,14 +313,6 @@ struct iwl3945_qos_info { #define STA_PS_STATUS_WAKE 0 #define STA_PS_STATUS_SLEEP 1 -struct iwl3945_station_entry { - struct iwl3945_addsta_cmd sta; - struct iwl3945_tid_data tid[MAX_TID_COUNT]; - u8 used; - u8 ps_status; - struct iwl3945_hw_key keyinfo; -}; - /* uCode file layout */ struct iwl3945_ucode { __le32 ver; /* major/minor/API/serial */ diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index f63209aaeaf..73318a95319 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -156,6 +156,12 @@ struct iwl4965_channel_tgh_info { #define IWL4965_MAX_RATE (33) +struct iwl3945_clip_group { + /* maximum power level to prevent clipping for each rate, derived by + * us from this band's saturation power in EEPROM */ + const s8 clip_powers[IWL_MAX_RATES]; +}; + /* current Tx power values to use, one for each rate for each channel. * requested power is limited by: * -- regulatory EEPROM limits for this channel @@ -218,6 +224,27 @@ struct iwl_channel_info { struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES]; }; +/** + * struct iwl3945_tx_queue - Tx Queue for DMA + * @q: generic Rx/Tx queue descriptor + * @bd: base of circular buffer of TFDs + * @cmd: array of command/Tx buffers + * @dma_addr_cmd: physical address of cmd/tx buffer array + * @txb: array of per-TFD driver data + * @need_update: indicates need to update read/write index + * + * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame + * descriptors) and required locking structures. + */ +struct iwl3945_tx_queue { + struct iwl_queue q; + struct iwl3945_tfd_frame *bd; + struct iwl3945_cmd *cmd; + dma_addr_t dma_addr_cmd; + struct iwl3945_tx_info *txb; + int need_update; + int active; +}; #define IWL_TX_FIFO_AC0 0 #define IWL_TX_FIFO_AC1 1 @@ -462,6 +489,24 @@ struct iwl_qos_info { #define STA_PS_STATUS_WAKE 0 #define STA_PS_STATUS_SLEEP 1 +struct iwl3945_tid_data { + u16 seq_number; +}; + +struct iwl3945_hw_key { + enum ieee80211_key_alg alg; + int keylen; + u8 key[32]; +}; + +struct iwl3945_station_entry { + struct iwl3945_addsta_cmd sta; + struct iwl3945_tid_data tid[MAX_TID_COUNT]; + u8 used; + u8 ps_status; + struct iwl3945_hw_key keyinfo; +}; + struct iwl_station_entry { struct iwl_addsta_cmd sta; struct iwl_tid_data tid[MAX_TID_COUNT]; @@ -800,6 +845,10 @@ struct iwl_priv { struct iwl_channel_info *channel_info; /* channel info array */ u8 channel_count; /* # of channels */ + /* each calibration channel group in the EEPROM has a derived + * clip setting for each rate. 3945 only.*/ + const struct iwl3945_clip_group clip39_groups[5]; + /* thermal calibration */ s32 temperature; /* degrees Kelvin */ s32 last_temperature; -- GitLab From a78fe754e0e5a77ca968ee0c348f027e84659d8b Mon Sep 17 00:00:00 2001 From: "Kolekar, Abhijeet" Date: Fri, 19 Dec 2008 10:37:21 +0800 Subject: [PATCH 0715/4982] iwl3945: remove duplicate structures from iwl-3945.h The patch renames and deletes duplicate structure from iwl-3945.h. The following structures are renamed with iwlwifi counterparts: 1) iwl3945_ac_qos 2) iwl3945_ucode 3) iwl3945_qos_capabity Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.h | 50 +-------------------- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 3 files changed, 4 insertions(+), 50 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index f51393046de..4f8e6b83fdc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -275,55 +275,9 @@ struct iwl3945_rx_queue { #define IWL_INVALID_RATE 0xFF #define IWL_INVALID_VALUE -1 -union iwl3945_ht_rate_supp { - u16 rates; - struct { - u8 siso_rate; - u8 mimo_rate; - }; -}; - -union iwl3945_qos_capabity { - struct { - u8 edca_count:4; /* bit 0-3 */ - u8 q_ack:1; /* bit 4 */ - u8 queue_request:1; /* bit 5 */ - u8 txop_request:1; /* bit 6 */ - u8 reserved:1; /* bit 7 */ - } q_AP; - struct { - u8 acvo_APSD:1; /* bit 0 */ - u8 acvi_APSD:1; /* bit 1 */ - u8 ac_bk_APSD:1; /* bit 2 */ - u8 ac_be_APSD:1; /* bit 3 */ - u8 q_ack:1; /* bit 4 */ - u8 max_len:2; /* bit 5-6 */ - u8 more_data_ack:1; /* bit 7 */ - } q_STA; - u8 val; -}; - -/* QoS structures */ -struct iwl3945_qos_info { - int qos_active; - union iwl3945_qos_capabity qos_cap; - struct iwl_qosparam_cmd def_qos_parm; -}; - #define STA_PS_STATUS_WAKE 0 #define STA_PS_STATUS_SLEEP 1 -/* uCode file layout */ -struct iwl3945_ucode { - __le32 ver; /* major/minor/API/serial */ - __le32 inst_size; /* bytes of runtime instructions */ - __le32 data_size; /* bytes of runtime data */ - __le32 init_size; /* bytes of initialization instructions */ - __le32 init_data_size; /* bytes of initialization data */ - __le32 boot_size; /* bytes of bootstrap instructions */ - u8 data[0]; /* data in same order as "size" elements */ -}; - struct iwl3945_ibss_seq { u8 mac[ETH_ALEN]; u16 seq_num; @@ -561,7 +515,7 @@ struct iwl3945_priv { /* uCode images, save to reload in case of failure */ u32 ucode_ver; /* ucode version, copy of - iwl3945_ucode.ver */ + iwl_ucode.ver */ struct fw_desc ucode_code; /* runtime inst */ struct fw_desc ucode_data; /* runtime data original */ struct fw_desc ucode_data_backup; /* runtime data save/restore */ @@ -672,7 +626,7 @@ struct iwl3945_priv { u16 assoc_capability; u8 ps_mode; - struct iwl3945_qos_info qos_data; + struct iwl_qos_info qos_data; struct workqueue_struct *workqueue; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 73318a95319..245f1d2fa32 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -429,7 +429,7 @@ struct iwl_hw_key { u8 key[32]; }; -union iwl4965_ht_rate_supp { +union iwl_ht_rate_supp { u16 rates; struct { u8 siso_rate; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index c597c242292..313826da45c 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -5228,7 +5228,7 @@ static void iwl3945_nic_start(struct iwl3945_priv *priv) */ static int iwl3945_read_ucode(struct iwl3945_priv *priv) { - struct iwl3945_ucode *ucode; + struct iwl_ucode *ucode; int ret = -EINVAL, index; const struct firmware *ucode_raw; /* firmware file name contains uCode/driver compatibility version */ -- GitLab From b5323d36637909481318e7dfcba9f3e3b9368881 Mon Sep 17 00:00:00 2001 From: "Kolekar, Abhijeet" Date: Fri, 19 Dec 2008 10:37:22 +0800 Subject: [PATCH 0716/4982] iwl3945: replace iwl3945_broadcast_addr with iwl_bcast_addr The patch replaces iwl3945_broadcast_addr with iwl_bcast_addr for 3945. Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.h | 1 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 10 ++++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 4f8e6b83fdc..e794cd56f61 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -358,7 +358,6 @@ extern int iwl3945_send_statistics_request(struct iwl3945_priv *priv); extern void iwl3945_set_decrypted_flag(struct iwl3945_priv *priv, struct sk_buff *skb, u32 decrypt_res, struct ieee80211_rx_status *stats); -extern const u8 iwl3945_broadcast_addr[ETH_ALEN]; /* * Currently used by iwl-3945-rs... look at restructuring so that it doesn't diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 313826da45c..6fb5d07ec6b 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -303,8 +303,6 @@ void iwl3945_tx_queue_free(struct iwl3945_priv *priv, struct iwl3945_tx_queue *t memset(txq, 0, sizeof(*txq)); } -const u8 iwl3945_broadcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - /*************** STATION TABLE MANAGEMENT **** * mac80211 should be examined to determine if sta_info is duplicating * the functionality provided here @@ -1032,7 +1030,7 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv) } /* Add the broadcast address so we can send broadcast frames */ - if (iwl3945_add_station(priv, iwl3945_broadcast_addr, 0, 0) == + if (iwl3945_add_station(priv, iwl_bcast_addr, 0, 0) == IWL_INVALID_STATION) { IWL_ERROR("Error adding BROADCAST address for transmit.\n"); return -EIO; @@ -1529,9 +1527,9 @@ static u16 iwl3945_fill_probe_req(struct iwl3945_priv *priv, len += 24; frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); - memcpy(frame->da, iwl3945_broadcast_addr, ETH_ALEN); + memcpy(frame->da, iwl_bcast_addr, ETH_ALEN); memcpy(frame->sa, priv->mac_addr, ETH_ALEN); - memcpy(frame->bssid, iwl3945_broadcast_addr, ETH_ALEN); + memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN); frame->seq_ctrl = 0; /* fill in our indirect SSID IE */ @@ -6640,7 +6638,7 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv) /* restore RXON assoc */ priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; iwl3945_commit_rxon(priv); - iwl3945_add_station(priv, iwl3945_broadcast_addr, 0, 0); + iwl3945_add_station(priv, iwl_bcast_addr, 0, 0); } iwl3945_send_beacon_cmd(priv); -- GitLab From d2bf55839ad77486a02ec32f8411f432621da110 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Fri, 19 Dec 2008 10:37:23 +0800 Subject: [PATCH 0717/4982] iwlwifi: beautify code This patch beautifies macros in iwl-debug.h. Signed-off-by: Wu Fengguang Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-debug.h | 167 ++++++++++++----------- 1 file changed, 85 insertions(+), 82 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 9c209d635d5..0617965c968 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -32,15 +32,19 @@ struct iwl_priv; #ifdef CONFIG_IWLWIFI_DEBUG -#define IWL_DEBUG(level, fmt, args...) \ -do { if (priv->debug_level & (level)) \ - dev_printk(KERN_ERR, &(priv->hw->wiphy->dev), "%c %s " fmt, \ - in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0) +#define IWL_DEBUG(level, fmt, args...) \ +do { \ + if (priv->debug_level & (level)) \ + dev_printk(KERN_ERR, &(priv->hw->wiphy->dev), "%c %s " fmt, \ + in_interrupt() ? 'I' : 'U', __func__ , ## args); \ +} while (0) -#define IWL_DEBUG_LIMIT(level, fmt, args...) \ -do { if ((priv->debug_level & (level)) && net_ratelimit()) \ - dev_printk(KERN_ERR, &(priv->hw->wiphy->dev), "%c %s " fmt, \ - in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0) +#define IWL_DEBUG_LIMIT(level, fmt, args...) \ +do { \ + if ((priv->debug_level & (level)) && net_ratelimit()) \ + dev_printk(KERN_ERR, &(priv->hw->wiphy->dev), "%c %s " fmt, \ + in_interrupt() ? 'I' : 'U', __func__ , ## args); \ +} while (0) #define iwl_print_hex_dump(priv, level, p, len) \ do { \ @@ -120,86 +124,85 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) * when CONFIG_IWLWIFI_DEBUG=y. */ +/* 0x0000000F - 0x00000001 */ #define IWL_DL_INFO (1 << 0) #define IWL_DL_MAC80211 (1 << 1) #define IWL_DL_HCMD (1 << 2) #define IWL_DL_STATE (1 << 3) +/* 0x000000F0 - 0x00000010 */ #define IWL_DL_MACDUMP (1 << 4) #define IWL_DL_HCMD_DUMP (1 << 5) -#define IWL_DL_RADIO (1 << 7) -#define IWL_DL_POWER (1 << 8) -#define IWL_DL_TEMP (1 << 9) - -#define IWL_DL_NOTIF (1 << 10) -#define IWL_DL_SCAN (1 << 11) -#define IWL_DL_ASSOC (1 << 12) -#define IWL_DL_DROP (1 << 13) - -#define IWL_DL_TXPOWER (1 << 14) - -#define IWL_DL_AP (1 << 15) - -#define IWL_DL_FW (1 << 16) -#define IWL_DL_RF_KILL (1 << 17) -#define IWL_DL_FW_ERRORS (1 << 18) - -#define IWL_DL_LED (1 << 19) - -#define IWL_DL_RATE (1 << 20) - -#define IWL_DL_CALIB (1 << 21) -#define IWL_DL_WEP (1 << 22) -#define IWL_DL_TX (1 << 23) -#define IWL_DL_RX (1 << 24) -#define IWL_DL_ISR (1 << 25) -#define IWL_DL_HT (1 << 26) -#define IWL_DL_IO (1 << 27) -#define IWL_DL_11H (1 << 28) - -#define IWL_DL_STATS (1 << 29) -#define IWL_DL_TX_REPLY (1 << 30) -#define IWL_DL_QOS (1 << 31) - -#define IWL_ERROR(f, a...) dev_printk(KERN_ERR, \ - &(priv->hw->wiphy->dev), f, ## a) -#define IWL_WARNING(f, a...) dev_printk(KERN_WARNING, \ - &(priv->hw->wiphy->dev), f, ## a) -#define IWL_DEBUG_INFO(f, a...) IWL_DEBUG(IWL_DL_INFO, f, ## a) - -#define IWL_DEBUG_MAC80211(f, a...) IWL_DEBUG(IWL_DL_MAC80211, f, ## a) -#define IWL_DEBUG_MACDUMP(f, a...) IWL_DEBUG(IWL_DL_MACDUMP, f, ## a) -#define IWL_DEBUG_TEMP(f, a...) IWL_DEBUG(IWL_DL_TEMP, f, ## a) -#define IWL_DEBUG_SCAN(f, a...) IWL_DEBUG(IWL_DL_SCAN, f, ## a) -#define IWL_DEBUG_RX(f, a...) IWL_DEBUG(IWL_DL_RX, f, ## a) -#define IWL_DEBUG_TX(f, a...) IWL_DEBUG(IWL_DL_TX, f, ## a) -#define IWL_DEBUG_ISR(f, a...) IWL_DEBUG(IWL_DL_ISR, f, ## a) -#define IWL_DEBUG_LED(f, a...) IWL_DEBUG(IWL_DL_LED, f, ## a) -#define IWL_DEBUG_WEP(f, a...) IWL_DEBUG(IWL_DL_WEP, f, ## a) -#define IWL_DEBUG_HC(f, a...) IWL_DEBUG(IWL_DL_HCMD, f, ## a) -#define IWL_DEBUG_HC_DUMP(f, a...) IWL_DEBUG(IWL_DL_HCMD_DUMP, f, ## a) -#define IWL_DEBUG_CALIB(f, a...) IWL_DEBUG(IWL_DL_CALIB, f, ## a) -#define IWL_DEBUG_FW(f, a...) IWL_DEBUG(IWL_DL_FW, f, ## a) -#define IWL_DEBUG_RF_KILL(f, a...) IWL_DEBUG(IWL_DL_RF_KILL, f, ## a) -#define IWL_DEBUG_DROP(f, a...) IWL_DEBUG(IWL_DL_DROP, f, ## a) -#define IWL_DEBUG_DROP_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_DROP, f, ## a) -#define IWL_DEBUG_AP(f, a...) IWL_DEBUG(IWL_DL_AP, f, ## a) -#define IWL_DEBUG_TXPOWER(f, a...) IWL_DEBUG(IWL_DL_TXPOWER, f, ## a) -#define IWL_DEBUG_IO(f, a...) IWL_DEBUG(IWL_DL_IO, f, ## a) -#define IWL_DEBUG_RATE(f, a...) IWL_DEBUG(IWL_DL_RATE, f, ## a) -#define IWL_DEBUG_RATE_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_RATE, f, ## a) -#define IWL_DEBUG_NOTIF(f, a...) IWL_DEBUG(IWL_DL_NOTIF, f, ## a) -#define IWL_DEBUG_ASSOC(f, a...) IWL_DEBUG(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a) -#define IWL_DEBUG_ASSOC_LIMIT(f, a...) \ - IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a) -#define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a) -#define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a) -#define IWL_DEBUG_STATS_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_STATS, f, ## a) -#define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a) +#define IWL_DL_RADIO (1 << 7) + +#define IWL_DL_POWER (1 << 8) +#define IWL_DL_TEMP (1 << 9) +#define IWL_DL_NOTIF (1 << 10) +#define IWL_DL_SCAN (1 << 11) + +#define IWL_DL_ASSOC (1 << 12) +#define IWL_DL_DROP (1 << 13) +#define IWL_DL_TXPOWER (1 << 14) +#define IWL_DL_AP (1 << 15) + +#define IWL_DL_FW (1 << 16) +#define IWL_DL_RF_KILL (1 << 17) +#define IWL_DL_FW_ERRORS (1 << 18) +#define IWL_DL_LED (1 << 19) + +#define IWL_DL_RATE (1 << 20) +#define IWL_DL_CALIB (1 << 21) +#define IWL_DL_WEP (1 << 22) +#define IWL_DL_TX (1 << 23) +#define IWL_DL_RX (1 << 24) +#define IWL_DL_ISR (1 << 25) +#define IWL_DL_HT (1 << 26) +#define IWL_DL_IO (1 << 27) +#define IWL_DL_11H (1 << 28) +#define IWL_DL_STATS (1 << 29) +#define IWL_DL_TX_REPLY (1 << 30) +#define IWL_DL_QOS (1 << 31) + +#define IWL_ERROR(f, a...) \ + dev_printk(KERN_ERR, &(priv->hw->wiphy->dev), f, ## a) +#define IWL_WARNING(f, a...) \ + dev_printk(KERN_WARNING, &(priv->hw->wiphy->dev), f, ## a) + +#define IWL_DEBUG_INFO(f, a...) IWL_DEBUG(IWL_DL_INFO, f, ## a) +#define IWL_DEBUG_MAC80211(f, a...) IWL_DEBUG(IWL_DL_MAC80211, f, ## a) +#define IWL_DEBUG_MACDUMP(f, a...) IWL_DEBUG(IWL_DL_MACDUMP, f, ## a) +#define IWL_DEBUG_TEMP(f, a...) IWL_DEBUG(IWL_DL_TEMP, f, ## a) +#define IWL_DEBUG_SCAN(f, a...) IWL_DEBUG(IWL_DL_SCAN, f, ## a) +#define IWL_DEBUG_RX(f, a...) IWL_DEBUG(IWL_DL_RX, f, ## a) +#define IWL_DEBUG_TX(f, a...) IWL_DEBUG(IWL_DL_TX, f, ## a) +#define IWL_DEBUG_ISR(f, a...) IWL_DEBUG(IWL_DL_ISR, f, ## a) +#define IWL_DEBUG_LED(f, a...) IWL_DEBUG(IWL_DL_LED, f, ## a) +#define IWL_DEBUG_WEP(f, a...) IWL_DEBUG(IWL_DL_WEP, f, ## a) +#define IWL_DEBUG_HC(f, a...) IWL_DEBUG(IWL_DL_HCMD, f, ## a) +#define IWL_DEBUG_HC_DUMP(f, a...) IWL_DEBUG(IWL_DL_HCMD_DUMP, f, ## a) +#define IWL_DEBUG_CALIB(f, a...) IWL_DEBUG(IWL_DL_CALIB, f, ## a) +#define IWL_DEBUG_FW(f, a...) IWL_DEBUG(IWL_DL_FW, f, ## a) +#define IWL_DEBUG_RF_KILL(f, a...) IWL_DEBUG(IWL_DL_RF_KILL, f, ## a) +#define IWL_DEBUG_DROP(f, a...) IWL_DEBUG(IWL_DL_DROP, f, ## a) +#define IWL_DEBUG_DROP_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_DROP, f, ## a) +#define IWL_DEBUG_AP(f, a...) IWL_DEBUG(IWL_DL_AP, f, ## a) +#define IWL_DEBUG_TXPOWER(f, a...) IWL_DEBUG(IWL_DL_TXPOWER, f, ## a) +#define IWL_DEBUG_IO(f, a...) IWL_DEBUG(IWL_DL_IO, f, ## a) +#define IWL_DEBUG_RATE(f, a...) IWL_DEBUG(IWL_DL_RATE, f, ## a) +#define IWL_DEBUG_RATE_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_RATE, f, ## a) +#define IWL_DEBUG_NOTIF(f, a...) IWL_DEBUG(IWL_DL_NOTIF, f, ## a) +#define IWL_DEBUG_ASSOC(f, a...) \ + IWL_DEBUG(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a) +#define IWL_DEBUG_ASSOC_LIMIT(f, a...) \ + IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a) +#define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a) +#define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a) +#define IWL_DEBUG_STATS_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_STATS, f, ## a) +#define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a) #define IWL_DEBUG_TX_REPLY_LIMIT(f, a...) \ - IWL_DEBUG_LIMIT(IWL_DL_TX_REPLY, f, ## a) -#define IWL_DEBUG_QOS(f, a...) IWL_DEBUG(IWL_DL_QOS, f, ## a) -#define IWL_DEBUG_RADIO(f, a...) IWL_DEBUG(IWL_DL_RADIO, f, ## a) -#define IWL_DEBUG_POWER(f, a...) IWL_DEBUG(IWL_DL_POWER, f, ## a) -#define IWL_DEBUG_11H(f, a...) IWL_DEBUG(IWL_DL_11H, f, ## a) + IWL_DEBUG_LIMIT(IWL_DL_TX_REPLY, f, ## a) +#define IWL_DEBUG_QOS(f, a...) IWL_DEBUG(IWL_DL_QOS, f, ## a) +#define IWL_DEBUG_RADIO(f, a...) IWL_DEBUG(IWL_DL_RADIO, f, ## a) +#define IWL_DEBUG_POWER(f, a...) IWL_DEBUG(IWL_DL_POWER, f, ## a) +#define IWL_DEBUG_11H(f, a...) IWL_DEBUG(IWL_DL_11H, f, ## a) #endif -- GitLab From 6100b58806e6307f959af79334ac553825400242 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Fri, 19 Dec 2008 10:37:24 +0800 Subject: [PATCH 0718/4982] iwl3945: use iwl_rx_mem_buffer The patch replaces iwl3945_rx_mem_buffer with iwl_rx_mem_buffer. Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 8 ++-- drivers/net/wireless/iwlwifi/iwl-3945.h | 16 ++----- drivers/net/wireless/iwlwifi/iwl3945-base.c | 52 ++++++++++----------- 3 files changed, 35 insertions(+), 41 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 93e5c52d91d..f283b1dea9d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -330,7 +330,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv, * iwl3945_rx_reply_tx - Handle Tx response */ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, - struct iwl3945_rx_mem_buffer *rxb) + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; u16 sequence = le16_to_cpu(pkt->hdr.sequence); @@ -389,7 +389,7 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, * *****************************************************************************/ -void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) +void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; IWL_DEBUG_RX("Statistics notification received (%d vs %d).\n", @@ -571,7 +571,7 @@ static int iwl3945_is_network_packet(struct iwl3945_priv *priv, } static void iwl3945_pass_packet_to_mac80211(struct iwl3945_priv *priv, - struct iwl3945_rx_mem_buffer *rxb, + struct iwl_rx_mem_buffer *rxb, struct ieee80211_rx_status *stats) { struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; @@ -614,7 +614,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl3945_priv *priv, #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, - struct iwl3945_rx_mem_buffer *rxb) + struct iwl_rx_mem_buffer *rxb) { struct ieee80211_hdr *header; struct ieee80211_rx_status rx_status; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index e794cd56f61..410a8bd0d4f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -106,12 +106,6 @@ enum iwl3945_antenna { #define DEFAULT_SHORT_RETRY_LIMIT 7U #define DEFAULT_LONG_RETRY_LIMIT 4U -struct iwl3945_rx_mem_buffer { - dma_addr_t dma_addr; - struct sk_buff *skb; - struct list_head list; -}; - int iwl3945_x2_queue_used(const struct iwl_queue *q, int i); #define MAX_NUM_OF_TBS (20) @@ -229,13 +223,13 @@ struct iwl3945_host_cmd { * @rx_used: List of Rx buffers with no SKB * @need_update: flag to indicate we need to update read/write index * - * NOTE: rx_free and rx_used are used as a FIFO for iwl3945_rx_mem_buffers + * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers */ struct iwl3945_rx_queue { __le32 *bd; dma_addr_t dma_addr; - struct iwl3945_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; - struct iwl3945_rx_mem_buffer *queue[RX_QUEUE_SIZE]; + struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; + struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; u32 processed; u32 read; u32 write; @@ -409,7 +403,7 @@ extern void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv, extern int iwl3945_hw_reg_send_txpower(struct iwl3945_priv *priv); extern int iwl3945_hw_reg_set_txpower(struct iwl3945_priv *priv, s8 power); extern void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, - struct iwl3945_rx_mem_buffer *rxb); + struct iwl_rx_mem_buffer *rxb); extern void iwl3945_disable_events(struct iwl3945_priv *priv); extern int iwl4965_get_temperature(const struct iwl3945_priv *priv); @@ -464,7 +458,7 @@ struct iwl3945_priv { int alloc_rxb_skb; void (*rx_handlers[REPLY_MAX])(struct iwl3945_priv *priv, - struct iwl3945_rx_mem_buffer *rxb); + struct iwl_rx_mem_buffer *rxb); struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 6fb5d07ec6b..47db9087e68 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2863,7 +2863,7 @@ static int iwl3945_get_measurement(struct iwl3945_priv *priv, #endif static void iwl3945_rx_reply_alive(struct iwl3945_priv *priv, - struct iwl3945_rx_mem_buffer *rxb) + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl_alive_resp *palive; @@ -2899,7 +2899,7 @@ static void iwl3945_rx_reply_alive(struct iwl3945_priv *priv, } static void iwl3945_rx_reply_add_sta(struct iwl3945_priv *priv, - struct iwl3945_rx_mem_buffer *rxb) + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; @@ -2908,7 +2908,7 @@ static void iwl3945_rx_reply_add_sta(struct iwl3945_priv *priv, } static void iwl3945_rx_reply_error(struct iwl3945_priv *priv, - struct iwl3945_rx_mem_buffer *rxb) + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; @@ -2923,7 +2923,7 @@ static void iwl3945_rx_reply_error(struct iwl3945_priv *priv, #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x -static void iwl3945_rx_csa(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) +static void iwl3945_rx_csa(struct iwl3945_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl3945_rxon_cmd *rxon = (void *)&priv->active_rxon; @@ -2935,7 +2935,7 @@ static void iwl3945_rx_csa(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buff } static void iwl3945_rx_spectrum_measure_notif(struct iwl3945_priv *priv, - struct iwl3945_rx_mem_buffer *rxb) + struct iwl_rx_mem_buffer *rxb) { #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT struct iwl_rx_packet *pkt = (void *)rxb->skb->data; @@ -2953,7 +2953,7 @@ static void iwl3945_rx_spectrum_measure_notif(struct iwl3945_priv *priv, } static void iwl3945_rx_pm_sleep_notif(struct iwl3945_priv *priv, - struct iwl3945_rx_mem_buffer *rxb) + struct iwl_rx_mem_buffer *rxb) { #ifdef CONFIG_IWL3945_DEBUG struct iwl_rx_packet *pkt = (void *)rxb->skb->data; @@ -2964,7 +2964,7 @@ static void iwl3945_rx_pm_sleep_notif(struct iwl3945_priv *priv, } static void iwl3945_rx_pm_debug_statistics_notif(struct iwl3945_priv *priv, - struct iwl3945_rx_mem_buffer *rxb) + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; IWL_DEBUG_RADIO("Dumping %d bytes of unhandled " @@ -3000,7 +3000,7 @@ static void iwl3945_bg_beacon_update(struct work_struct *work) } static void iwl3945_rx_beacon_notif(struct iwl3945_priv *priv, - struct iwl3945_rx_mem_buffer *rxb) + struct iwl_rx_mem_buffer *rxb) { #ifdef CONFIG_IWL3945_DEBUG struct iwl_rx_packet *pkt = (void *)rxb->skb->data; @@ -3023,7 +3023,7 @@ static void iwl3945_rx_beacon_notif(struct iwl3945_priv *priv, /* Service response to REPLY_SCAN_CMD (0x80) */ static void iwl3945_rx_reply_scan(struct iwl3945_priv *priv, - struct iwl3945_rx_mem_buffer *rxb) + struct iwl_rx_mem_buffer *rxb) { #ifdef CONFIG_IWL3945_DEBUG struct iwl_rx_packet *pkt = (void *)rxb->skb->data; @@ -3036,7 +3036,7 @@ static void iwl3945_rx_reply_scan(struct iwl3945_priv *priv, /* Service SCAN_START_NOTIFICATION (0x82) */ static void iwl3945_rx_scan_start_notif(struct iwl3945_priv *priv, - struct iwl3945_rx_mem_buffer *rxb) + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl_scanstart_notification *notif = @@ -3053,7 +3053,7 @@ static void iwl3945_rx_scan_start_notif(struct iwl3945_priv *priv, /* Service SCAN_RESULTS_NOTIFICATION (0x83) */ static void iwl3945_rx_scan_results_notif(struct iwl3945_priv *priv, - struct iwl3945_rx_mem_buffer *rxb) + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl_scanresults_notification *notif = @@ -3078,7 +3078,7 @@ static void iwl3945_rx_scan_results_notif(struct iwl3945_priv *priv, /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */ static void iwl3945_rx_scan_complete_notif(struct iwl3945_priv *priv, - struct iwl3945_rx_mem_buffer *rxb) + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw; @@ -3141,7 +3141,7 @@ reschedule: /* Handle notification from uCode that card's power state is changing * due to software, hardware, or critical temperature RFKILL */ static void iwl3945_rx_card_state_notif(struct iwl3945_priv *priv, - struct iwl3945_rx_mem_buffer *rxb) + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); @@ -3259,7 +3259,7 @@ static void iwl3945_cmd_queue_reclaim(struct iwl3945_priv *priv, * if the callback returns 1 */ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv, - struct iwl3945_rx_mem_buffer *rxb) + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; u16 sequence = le16_to_cpu(pkt->hdr.sequence); @@ -3346,7 +3346,7 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv, * are available, schedules iwl3945_rx_replenish * * -- enable interrupts -- - * ISR - iwl3945_rx() Detach iwl3945_rx_mem_buffers from pool up to the + * ISR - iwl3945_rx() Detach iwl_rx_mem_buffers from pool up to the * READ INDEX, detaching the SKB from the pool. * Moves the packet buffer from queue to rx_used. * Calls iwl3945_rx_queue_restock to refill any empty @@ -3440,7 +3440,7 @@ static int iwl3945_rx_queue_restock(struct iwl3945_priv *priv) { struct iwl3945_rx_queue *rxq = &priv->rxq; struct list_head *element; - struct iwl3945_rx_mem_buffer *rxb; + struct iwl_rx_mem_buffer *rxb; unsigned long flags; int write, rc; @@ -3449,11 +3449,11 @@ static int iwl3945_rx_queue_restock(struct iwl3945_priv *priv) while ((iwl3945_rx_queue_space(rxq) > 0) && (rxq->free_count)) { /* Get next free Rx buffer, remove from free list */ element = rxq->rx_free.next; - rxb = list_entry(element, struct iwl3945_rx_mem_buffer, list); + rxb = list_entry(element, struct iwl_rx_mem_buffer, list); list_del(element); /* Point to Rx buffer via next RBD in circular buffer */ - rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->dma_addr); + rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->real_dma_addr); rxq->queue[rxq->write] = rxb; rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; rxq->free_count--; @@ -3492,12 +3492,12 @@ static void iwl3945_rx_allocate(struct iwl3945_priv *priv) { struct iwl3945_rx_queue *rxq = &priv->rxq; struct list_head *element; - struct iwl3945_rx_mem_buffer *rxb; + struct iwl_rx_mem_buffer *rxb; unsigned long flags; spin_lock_irqsave(&rxq->lock, flags); while (!list_empty(&rxq->rx_used)) { element = rxq->rx_used.next; - rxb = list_entry(element, struct iwl3945_rx_mem_buffer, list); + rxb = list_entry(element, struct iwl_rx_mem_buffer, list); /* Alloc a new receive buffer */ rxb->skb = @@ -3524,7 +3524,7 @@ static void iwl3945_rx_allocate(struct iwl3945_priv *priv) list_del(element); /* Get physical address of RB/SKB */ - rxb->dma_addr = + rxb->real_dma_addr = pci_map_single(priv->pci_dev, rxb->skb->data, IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); list_add_tail(&rxb->list, &rxq->rx_free); @@ -3568,7 +3568,7 @@ static void iwl3945_rx_queue_free(struct iwl3945_priv *priv, struct iwl3945_rx_q for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { if (rxq->pool[i].skb != NULL) { pci_unmap_single(priv->pci_dev, - rxq->pool[i].dma_addr, + rxq->pool[i].real_dma_addr, IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); dev_kfree_skb(rxq->pool[i].skb); } @@ -3619,7 +3619,7 @@ void iwl3945_rx_queue_reset(struct iwl3945_priv *priv, struct iwl3945_rx_queue * * to an SKB, so we need to unmap and free potential storage */ if (rxq->pool[i].skb != NULL) { pci_unmap_single(priv->pci_dev, - rxq->pool[i].dma_addr, + rxq->pool[i].real_dma_addr, IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); priv->alloc_rxb_skb--; dev_kfree_skb(rxq->pool[i].skb); @@ -3722,7 +3722,7 @@ int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm) */ static void iwl3945_rx_handle(struct iwl3945_priv *priv) { - struct iwl3945_rx_mem_buffer *rxb; + struct iwl_rx_mem_buffer *rxb; struct iwl_rx_packet *pkt; struct iwl3945_rx_queue *rxq = &priv->rxq; u32 r, i; @@ -3752,7 +3752,7 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv) rxq->queue[i] = NULL; - pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr, + pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->real_dma_addr, IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); pkt = (struct iwl_rx_packet *)rxb->skb->data; @@ -3802,7 +3802,7 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv) rxb->skb = NULL; } - pci_unmap_single(priv->pci_dev, rxb->dma_addr, + pci_unmap_single(priv->pci_dev, rxb->real_dma_addr, IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); spin_lock_irqsave(&rxq->lock, flags); list_add_tail(&rxb->list, &priv->rxq.rx_used); -- GitLab From cc2f362c360af35b74530f3c896511b8dbd0264c Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Fri, 19 Dec 2008 10:37:25 +0800 Subject: [PATCH 0719/4982] iwl3945: use iwl_rx_queue in iwl3945 The patch replaces iwl3945_rx_queue with iwl_rx_queue. Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 4 +-- drivers/net/wireless/iwlwifi/iwl-3945.h | 33 ++------------------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 16 +++++----- 3 files changed, 13 insertions(+), 40 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index f283b1dea9d..82b2023c6ad 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -961,7 +961,7 @@ static int iwl3945_nic_set_pwr_src(struct iwl3945_priv *priv, int pwr_max) return rc; } -static int iwl3945_rx_init(struct iwl3945_priv *priv, struct iwl3945_rx_queue *rxq) +static int iwl3945_rx_init(struct iwl3945_priv *priv, struct iwl_rx_queue *rxq) { int rc; unsigned long flags; @@ -1082,7 +1082,7 @@ int iwl3945_hw_nic_init(struct iwl3945_priv *priv) u8 rev_id; int rc; unsigned long flags; - struct iwl3945_rx_queue *rxq = &priv->rxq; + struct iwl_rx_queue *rxq = &priv->rxq; iwl3945_power_init_handle(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 410a8bd0d4f..c4d56ef0fa8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -213,33 +213,6 @@ struct iwl3945_host_cmd { #define SUP_RATE_11B_MAX_NUM_CHANNELS 4 #define SUP_RATE_11G_MAX_NUM_CHANNELS 12 -/** - * struct iwl3945_rx_queue - Rx queue - * @processed: Internal index to last handled Rx packet - * @read: Shared index to newest available Rx buffer - * @write: Shared index to oldest written Rx packet - * @free_count: Number of pre-allocated buffers in rx_free - * @rx_free: list of free SKBs for use - * @rx_used: List of Rx buffers with no SKB - * @need_update: flag to indicate we need to update read/write index - * - * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers - */ -struct iwl3945_rx_queue { - __le32 *bd; - dma_addr_t dma_addr; - struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; - struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; - u32 processed; - u32 read; - u32 write; - u32 free_count; - struct list_head rx_free; - struct list_head rx_used; - int need_update; - spinlock_t lock; -}; - #define IWL_SUPPORTED_RATES_IE_LEN 8 #define SCAN_INTERVAL 100 @@ -333,7 +306,7 @@ extern int iwl3945_power_init_handle(struct iwl3945_priv *priv); extern int iwl3945_eeprom_init(struct iwl3945_priv *priv); extern int iwl3945_rx_queue_alloc(struct iwl3945_priv *priv); extern void iwl3945_rx_queue_reset(struct iwl3945_priv *priv, - struct iwl3945_rx_queue *rxq); + struct iwl_rx_queue *rxq); extern int iwl3945_calc_db_from_ratio(int sig_ratio); extern int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm); extern int iwl3945_tx_queue_init(struct iwl3945_priv *priv, @@ -347,7 +320,7 @@ extern int __must_check iwl3945_send_cmd(struct iwl3945_priv *priv, extern unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv, struct ieee80211_hdr *hdr,int left); extern int iwl3945_rx_queue_update_write_ptr(struct iwl3945_priv *priv, - struct iwl3945_rx_queue *q); + struct iwl_rx_queue *q); extern int iwl3945_send_statistics_request(struct iwl3945_priv *priv); extern void iwl3945_set_decrypted_flag(struct iwl3945_priv *priv, struct sk_buff *skb, u32 decrypt_res, @@ -564,7 +537,7 @@ struct iwl3945_priv { int activity_timer_active; /* Rx and Tx DMA processing queues */ - struct iwl3945_rx_queue rxq; + struct iwl_rx_queue rxq; struct iwl3945_tx_queue txq[IWL39_MAX_NUM_QUEUES]; unsigned long status; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 47db9087e68..da5309e69bd 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3358,7 +3358,7 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv, /** * iwl3945_rx_queue_space - Return number of free slots available in queue. */ -static int iwl3945_rx_queue_space(const struct iwl3945_rx_queue *q) +static int iwl3945_rx_queue_space(const struct iwl_rx_queue *q) { int s = q->read - q->write; if (s <= 0) @@ -3373,7 +3373,7 @@ static int iwl3945_rx_queue_space(const struct iwl3945_rx_queue *q) /** * iwl3945_rx_queue_update_write_ptr - Update the write pointer for the RX queue */ -int iwl3945_rx_queue_update_write_ptr(struct iwl3945_priv *priv, struct iwl3945_rx_queue *q) +int iwl3945_rx_queue_update_write_ptr(struct iwl3945_priv *priv, struct iwl_rx_queue *q) { u32 reg = 0; int rc = 0; @@ -3438,7 +3438,7 @@ static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl3945_priv *priv, */ static int iwl3945_rx_queue_restock(struct iwl3945_priv *priv) { - struct iwl3945_rx_queue *rxq = &priv->rxq; + struct iwl_rx_queue *rxq = &priv->rxq; struct list_head *element; struct iwl_rx_mem_buffer *rxb; unsigned long flags; @@ -3490,7 +3490,7 @@ static int iwl3945_rx_queue_restock(struct iwl3945_priv *priv) */ static void iwl3945_rx_allocate(struct iwl3945_priv *priv) { - struct iwl3945_rx_queue *rxq = &priv->rxq; + struct iwl_rx_queue *rxq = &priv->rxq; struct list_head *element; struct iwl_rx_mem_buffer *rxb; unsigned long flags; @@ -3562,7 +3562,7 @@ void iwl3945_rx_replenish(void *data) * This free routine walks the list of POOL entries and if SKB is set to * non NULL it is unmapped and freed */ -static void iwl3945_rx_queue_free(struct iwl3945_priv *priv, struct iwl3945_rx_queue *rxq) +static void iwl3945_rx_queue_free(struct iwl3945_priv *priv, struct iwl_rx_queue *rxq) { int i; for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { @@ -3581,7 +3581,7 @@ static void iwl3945_rx_queue_free(struct iwl3945_priv *priv, struct iwl3945_rx_q int iwl3945_rx_queue_alloc(struct iwl3945_priv *priv) { - struct iwl3945_rx_queue *rxq = &priv->rxq; + struct iwl_rx_queue *rxq = &priv->rxq; struct pci_dev *dev = priv->pci_dev; int i; @@ -3606,7 +3606,7 @@ int iwl3945_rx_queue_alloc(struct iwl3945_priv *priv) return 0; } -void iwl3945_rx_queue_reset(struct iwl3945_priv *priv, struct iwl3945_rx_queue *rxq) +void iwl3945_rx_queue_reset(struct iwl3945_priv *priv, struct iwl_rx_queue *rxq) { unsigned long flags; int i; @@ -3724,7 +3724,7 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv) { struct iwl_rx_mem_buffer *rxb; struct iwl_rx_packet *pkt; - struct iwl3945_rx_queue *rxq = &priv->rxq; + struct iwl_rx_queue *rxq = &priv->rxq; u32 r, i; int reclaim; unsigned long flags; -- GitLab From 3832ec9dc919a0994d713390eb4fb3c7e7500b94 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Fri, 19 Dec 2008 10:37:26 +0800 Subject: [PATCH 0720/4982] iwl3945: use iwl_hw_params in iwl3945_priv The patch makes changed necessary to use iwl_hw_params to replace iwl3945_driver_hw_info. Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 41 ++++++++++----------- drivers/net/wireless/iwlwifi/iwl-3945.h | 34 ++--------------- drivers/net/wireless/iwlwifi/iwl-dev.h | 7 ++++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 36 +++++++++--------- 4 files changed, 49 insertions(+), 69 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 82b2023c6ad..b5b23b1ad24 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -804,10 +804,10 @@ u8 iwl3945_hw_find_station(struct iwl3945_priv *priv, const u8 *addr) start = IWL_STA_ID; if (is_broadcast_ether_addr(addr)) - return priv->hw_setting.bcast_sta_id; + return priv->hw_params.bcast_sta_id; spin_lock_irqsave(&priv->sta_lock, flags); - for (i = start; i < priv->hw_setting.max_stations; i++) + for (i = start; i < priv->hw_params.max_stations; i++) if ((priv->stations[i].used) && (!compare_ether_addr (priv->stations[i].sta.sta.addr, addr))) { @@ -975,7 +975,7 @@ static int iwl3945_rx_init(struct iwl3945_priv *priv, struct iwl_rx_queue *rxq) iwl3945_write_direct32(priv, FH39_RCSR_RBD_BASE(0), rxq->dma_addr); iwl3945_write_direct32(priv, FH39_RCSR_RPTR_ADDR(0), - priv->hw_setting.shared_phys + + priv->shared_phys + offsetof(struct iwl3945_shared, rx_read_ptr[0])); iwl3945_write_direct32(priv, FH39_RCSR_WPTR(0), 0); iwl3945_write_direct32(priv, FH39_RCSR_CONFIG(0), @@ -1024,7 +1024,7 @@ static int iwl3945_tx_reset(struct iwl3945_priv *priv) iwl3945_write_prph(priv, ALM_SCD_TXF5MF_REG, 0x000005); iwl3945_write_direct32(priv, FH39_TSSR_CBB_BASE, - priv->hw_setting.shared_phys); + priv->shared_phys); iwl3945_write_direct32(priv, FH39_TSSR_MSG_CONFIG, FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON | @@ -2314,7 +2314,7 @@ int iwl3945_hw_tx_queue_init(struct iwl3945_priv *priv, struct iwl3945_tx_queue unsigned long flags; int txq_id = txq->q.id; - struct iwl3945_shared *shared_data = priv->hw_setting.shared_virt; + struct iwl3945_shared *shared_data = priv->shared_virt; shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32)txq->q.dma_addr); @@ -2344,7 +2344,7 @@ int iwl3945_hw_tx_queue_init(struct iwl3945_priv *priv, struct iwl3945_tx_queue int iwl3945_hw_get_rx_read(struct iwl3945_priv *priv) { - struct iwl3945_shared *shared_data = priv->hw_setting.shared_virt; + struct iwl3945_shared *shared_data = priv->shared_virt; return le32_to_cpu(shared_data->rx_read_ptr[0]); } @@ -2429,31 +2429,30 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv) } /* Called when initializing driver */ -int iwl3945_hw_set_hw_setting(struct iwl3945_priv *priv) +int iwl3945_hw_set_hw_params(struct iwl3945_priv *priv) { - memset((void *)&priv->hw_setting, 0, - sizeof(struct iwl3945_driver_hw_info)); + memset((void *)&priv->hw_params, 0, + sizeof(struct iwl_hw_params)); - priv->hw_setting.shared_virt = + priv->shared_virt = pci_alloc_consistent(priv->pci_dev, sizeof(struct iwl3945_shared), - &priv->hw_setting.shared_phys); + &priv->shared_phys); - if (!priv->hw_setting.shared_virt) { + if (!priv->shared_virt) { IWL_ERROR("failed to allocate pci memory\n"); mutex_unlock(&priv->mutex); return -ENOMEM; } - priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE; - priv->hw_setting.max_pkt_size = 2342; - priv->hw_setting.tx_cmd_len = sizeof(struct iwl3945_tx_cmd); - priv->hw_setting.max_rxq_size = RX_QUEUE_SIZE; - priv->hw_setting.max_rxq_log = RX_QUEUE_SIZE_LOG; - priv->hw_setting.max_stations = IWL3945_STATION_COUNT; - priv->hw_setting.bcast_sta_id = IWL3945_BROADCAST_ID; + priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE; + priv->hw_params.max_pkt_size = 2342; + priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; + priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; + priv->hw_params.max_stations = IWL3945_STATION_COUNT; + priv->hw_params.bcast_sta_id = IWL3945_BROADCAST_ID; - priv->hw_setting.tx_ant_num = 2; + priv->hw_params.tx_ant_num = 2; return 0; } @@ -2466,7 +2465,7 @@ unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv, tx_beacon_cmd = (struct iwl3945_tx_beacon_cmd *)&frame->u; memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); - tx_beacon_cmd->tx.sta_id = priv->hw_setting.bcast_sta_id; + tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id; tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; frame_size = iwl3945_fill_beacon_frame(priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index c4d56ef0fa8..cfceee18814 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -253,34 +253,6 @@ struct iwl3945_ibss_seq { struct list_head list; }; -/** - * struct iwl3945_driver_hw_info - * @max_txq_num: Max # Tx queues supported - * @tx_cmd_len: Size of Tx command (but not including frame itself) - * @tx_ant_num: Number of TX antennas - * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2) - * @rx_buf_size: - * @max_pkt_size: - * @max_rxq_log: Log-base-2 of max_rxq_size - * @max_stations: - * @bcast_sta_id: - * @shared_virt: Pointer to driver/uCode shared Tx Byte Counts and Rx status - * @shared_phys: Physical Pointer to Tx Byte Counts and Rx status - */ -struct iwl3945_driver_hw_info { - u16 max_txq_num; - u16 tx_cmd_len; - u16 tx_ant_num; - u16 max_rxq_size; - u32 rx_buf_size; - u32 max_pkt_size; - u16 max_rxq_log; - u8 max_stations; - u8 bcast_sta_id; - void *shared_virt; - dma_addr_t shared_phys; -}; - #define IWL_RX_HDR(x) ((struct iwl3945_rx_frame_hdr *)(\ x->u.rx_frame.stats.payload + \ x->u.rx_frame.stats.phy_count)) @@ -353,7 +325,7 @@ extern void iwl3945_hw_rx_handler_setup(struct iwl3945_priv *priv); extern void iwl3945_hw_setup_deferred_work(struct iwl3945_priv *priv); extern void iwl3945_hw_cancel_deferred_work(struct iwl3945_priv *priv); extern int iwl3945_hw_rxq_stop(struct iwl3945_priv *priv); -extern int iwl3945_hw_set_hw_setting(struct iwl3945_priv *priv); +extern int iwl3945_hw_set_hw_params(struct iwl3945_priv *priv); extern int iwl3945_hw_nic_init(struct iwl3945_priv *priv); extern int iwl3945_hw_nic_stop_master(struct iwl3945_priv *priv); extern void iwl3945_hw_txq_ctx_free(struct iwl3945_priv *priv); @@ -583,7 +555,9 @@ struct iwl3945_priv { /* Last Rx'd beacon timestamp */ u64 timestamp; u16 beacon_int; - struct iwl3945_driver_hw_info hw_setting; + void *shared_virt; + dma_addr_t shared_phys; + struct iwl_hw_params hw_params; struct ieee80211_vif *vif; /* Current association information needed to configure the diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 245f1d2fa32..9904406ae36 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -611,6 +611,9 @@ struct iwl_hw_params { u32 ct_kill_threshold; /* value in hw-dependent units */ u32 calib_init_cfg; const struct iwl_sensitivity_ranges *sens; + + /* for 3945 */ + u16 tx_ant_num; }; @@ -1010,6 +1013,10 @@ struct iwl_priv { u16 beacon_int; struct ieee80211_vif *vif; + /*Added for 3945 */ + void *shared_virt; + dma_addr_t shared_phys; + /*End*/ struct iwl_hw_params hw_params; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index da5309e69bd..b42bb8433a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -326,9 +326,9 @@ static u8 iwl3945_remove_station(struct iwl3945_priv *priv, const u8 *addr, int if (is_ap) index = IWL_AP_ID; else if (is_broadcast_ether_addr(addr)) - index = priv->hw_setting.bcast_sta_id; + index = priv->hw_params.bcast_sta_id; else - for (i = IWL_STA_ID; i < priv->hw_setting.max_stations; i++) + for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) if (priv->stations[i].used && !compare_ether_addr(priv->stations[i].sta.sta.addr, addr)) { @@ -384,9 +384,9 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8 if (is_ap) index = IWL_AP_ID; else if (is_broadcast_ether_addr(addr)) - index = priv->hw_setting.bcast_sta_id; + index = priv->hw_params.bcast_sta_id; else - for (i = IWL_STA_ID; i < priv->hw_setting.max_stations; i++) { + for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) { if (!compare_ether_addr(priv->stations[i].sta.sta.addr, addr)) { index = i; @@ -1470,13 +1470,13 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv) return 0; } -static void iwl3945_unset_hw_setting(struct iwl3945_priv *priv) +static void iwl3945_unset_hw_params(struct iwl3945_priv *priv) { - if (priv->hw_setting.shared_virt) + if (priv->shared_virt) pci_free_consistent(priv->pci_dev, sizeof(struct iwl3945_shared), - priv->hw_setting.shared_virt, - priv->hw_setting.shared_phys); + priv->shared_virt, + priv->shared_phys); } /** @@ -2322,7 +2322,7 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h /* If this frame is broadcast or management, use broadcast station id */ if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) || is_multicast_ether_addr(hdr->addr1)) - return priv->hw_setting.bcast_sta_id; + return priv->hw_params.bcast_sta_id; switch (priv->iw_mode) { @@ -2336,7 +2336,7 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h sta_id = iwl3945_hw_find_station(priv, hdr->addr1); if (sta_id != IWL_INVALID_STATION) return sta_id; - return priv->hw_setting.bcast_sta_id; + return priv->hw_params.bcast_sta_id; /* If this frame is going out to an IBSS network, find the station, * or create a new station table entry */ @@ -2355,16 +2355,16 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h "Defaulting to broadcast...\n", hdr->addr1); iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); - return priv->hw_setting.bcast_sta_id; + return priv->hw_params.bcast_sta_id; } /* If we are in monitor mode, use BCAST. This is required for * packet injection. */ case NL80211_IFTYPE_MONITOR: - return priv->hw_setting.bcast_sta_id; + return priv->hw_params.bcast_sta_id; default: IWL_WARNING("Unknown mode of operation: %d\n", priv->iw_mode); - return priv->hw_setting.bcast_sta_id; + return priv->hw_params.bcast_sta_id; } } @@ -2497,7 +2497,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) * of the MAC header (device reads on dword boundaries). * We'll tell device about this padding later. */ - len = priv->hw_setting.tx_cmd_len + + len = sizeof(struct iwl3945_tx_cmd) + sizeof(struct iwl_cmd_header) + hdr_len; len_org = len; @@ -6094,7 +6094,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) iwl3945_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data, IWL_MAX_SCAN_SIZE - sizeof(*scan))); scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; - scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id; + scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id; scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; /* flags + rate selection */ @@ -7848,7 +7848,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e * 5. Setup HW Constants * ********************/ /* Device-specific setup */ - if (iwl3945_hw_set_hw_setting(priv)) { + if (iwl3945_hw_set_hw_params(priv)) { IWL_ERROR("failed to set hw settings\n"); goto out_iounmap; } @@ -7971,7 +7971,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e out_release_irq: destroy_workqueue(priv->workqueue); priv->workqueue = NULL; - iwl3945_unset_hw_setting(priv); + iwl3945_unset_hw_params(priv); out_iounmap: pci_iounmap(pdev, priv->hw_base); @@ -8018,7 +8018,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) iwl3945_rx_queue_free(priv, &priv->rxq); iwl3945_hw_txq_ctx_free(priv); - iwl3945_unset_hw_setting(priv); + iwl3945_unset_hw_params(priv); iwl3945_clear_stations_table(priv); if (priv->mac80211_registered) -- GitLab From f2c7e52100545e54af064fe0345d141fdcf2d243 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Fri, 19 Dec 2008 10:37:27 +0800 Subject: [PATCH 0721/4982] iwl3945: rename iwl3945_priv variables The patch renames iwl3945 specific variables in iwl3945_priv structure. iwl3945_priv structure differs with iwl_priv structure with these variables. Goal of this patch is to make transition from iwl3945_priv to iwl_priv smoothly. Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-led.c | 56 +-- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 4 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 66 ++-- drivers/net/wireless/iwlwifi/iwl-3945.h | 24 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 376 ++++++++++---------- 5 files changed, 263 insertions(+), 263 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index 32d09ba3e69..1ef21b6b3c4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -313,66 +313,66 @@ int iwl3945_led_register(struct iwl3945_priv *priv) priv->allow_blinking = 0; trigger = ieee80211_get_radio_led_name(priv->hw); - snprintf(priv->led[IWL_LED_TRG_RADIO].name, - sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s:radio", + snprintf(priv->led39[IWL_LED_TRG_RADIO].name, + sizeof(priv->led39[IWL_LED_TRG_RADIO].name), "iwl-%s:radio", wiphy_name(priv->hw->wiphy)); - priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on; - priv->led[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off; - priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; + priv->led39[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on; + priv->led39[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off; + priv->led39[IWL_LED_TRG_RADIO].led_pattern = NULL; ret = iwl3945_led_register_led(priv, - &priv->led[IWL_LED_TRG_RADIO], + &priv->led39[IWL_LED_TRG_RADIO], IWL_LED_TRG_RADIO, 1, trigger); if (ret) goto exit_fail; trigger = ieee80211_get_assoc_led_name(priv->hw); - snprintf(priv->led[IWL_LED_TRG_ASSOC].name, - sizeof(priv->led[IWL_LED_TRG_ASSOC].name), "iwl-%s:assoc", + snprintf(priv->led39[IWL_LED_TRG_ASSOC].name, + sizeof(priv->led39[IWL_LED_TRG_ASSOC].name), "iwl-%s:assoc", wiphy_name(priv->hw->wiphy)); ret = iwl3945_led_register_led(priv, - &priv->led[IWL_LED_TRG_ASSOC], + &priv->led39[IWL_LED_TRG_ASSOC], IWL_LED_TRG_ASSOC, 0, trigger); /* for assoc always turn led on */ - priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on; - priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on; - priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL; + priv->led39[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on; + priv->led39[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on; + priv->led39[IWL_LED_TRG_ASSOC].led_pattern = NULL; if (ret) goto exit_fail; trigger = ieee80211_get_rx_led_name(priv->hw); - snprintf(priv->led[IWL_LED_TRG_RX].name, - sizeof(priv->led[IWL_LED_TRG_RX].name), "iwl-%s:RX", + snprintf(priv->led39[IWL_LED_TRG_RX].name, + sizeof(priv->led39[IWL_LED_TRG_RX].name), "iwl-%s:RX", wiphy_name(priv->hw->wiphy)); ret = iwl3945_led_register_led(priv, - &priv->led[IWL_LED_TRG_RX], + &priv->led39[IWL_LED_TRG_RX], IWL_LED_TRG_RX, 0, trigger); - priv->led[IWL_LED_TRG_RX].led_on = iwl3945_led_associated; - priv->led[IWL_LED_TRG_RX].led_off = iwl3945_led_associated; - priv->led[IWL_LED_TRG_RX].led_pattern = iwl3945_led_pattern; + priv->led39[IWL_LED_TRG_RX].led_on = iwl3945_led_associated; + priv->led39[IWL_LED_TRG_RX].led_off = iwl3945_led_associated; + priv->led39[IWL_LED_TRG_RX].led_pattern = iwl3945_led_pattern; if (ret) goto exit_fail; trigger = ieee80211_get_tx_led_name(priv->hw); - snprintf(priv->led[IWL_LED_TRG_TX].name, - sizeof(priv->led[IWL_LED_TRG_TX].name), "iwl-%s:TX", + snprintf(priv->led39[IWL_LED_TRG_TX].name, + sizeof(priv->led39[IWL_LED_TRG_TX].name), "iwl-%s:TX", wiphy_name(priv->hw->wiphy)); ret = iwl3945_led_register_led(priv, - &priv->led[IWL_LED_TRG_TX], + &priv->led39[IWL_LED_TRG_TX], IWL_LED_TRG_TX, 0, trigger); - priv->led[IWL_LED_TRG_TX].led_on = iwl3945_led_associated; - priv->led[IWL_LED_TRG_TX].led_off = iwl3945_led_associated; - priv->led[IWL_LED_TRG_TX].led_pattern = iwl3945_led_pattern; + priv->led39[IWL_LED_TRG_TX].led_on = iwl3945_led_associated; + priv->led39[IWL_LED_TRG_TX].led_off = iwl3945_led_associated; + priv->led39[IWL_LED_TRG_TX].led_pattern = iwl3945_led_pattern; if (ret) goto exit_fail; @@ -401,9 +401,9 @@ static void iwl3945_led_unregister_led(struct iwl3945_led *led, u8 set_led) /* Unregister all led handlers */ void iwl3945_led_unregister(struct iwl3945_priv *priv) { - iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_ASSOC], 0); - iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RX], 0); - iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_TX], 0); - iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RADIO], 1); + iwl3945_led_unregister_led(&priv->led39[IWL_LED_TRG_ASSOC], 0); + iwl3945_led_unregister_led(&priv->led39[IWL_LED_TRG_RX], 0); + iwl3945_led_unregister_led(&priv->led39[IWL_LED_TRG_TX], 0); + iwl3945_led_unregister_led(&priv->led39[IWL_LED_TRG_RADIO], 1); } diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 3fa9570f82b..daaac3196ce 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -901,7 +901,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) rcu_read_lock(); - sta = ieee80211_find_sta(hw, priv->stations[sta_id].sta.sta.addr); + sta = ieee80211_find_sta(hw, priv->stations_39[sta_id].sta.sta.addr); if (!sta) { rcu_read_unlock(); return; @@ -916,7 +916,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) switch (priv->band) { case IEEE80211_BAND_2GHZ: /* TODO: this always does G, not a regression */ - if (priv->active_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) { + if (priv->active39_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) { rs_sta->tgg = 1; rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot; } else diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index b5b23b1ad24..f480c437cd6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -199,7 +199,7 @@ static int iwl3945_hwrate_to_plcp_idx(u8 plcp) * iwl3945_get_antenna_flags - Get antenna flags for RXON command * @priv: eeprom and antenna fields are used to determine antenna flags * - * priv->eeprom is used to determine if antenna AUX/MAIN are reversed + * priv->eeprom39 is used to determine if antenna AUX/MAIN are reversed * priv->antenna specifies the antenna diversity mode: * * IWL_ANTENNA_DIVERSITY - NIC selects best antenna by itself @@ -213,12 +213,12 @@ __le32 iwl3945_get_antenna_flags(const struct iwl3945_priv *priv) return 0; case IWL_ANTENNA_MAIN: - if (priv->eeprom.antenna_switch_type) + if (priv->eeprom39.antenna_switch_type) return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK; return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK; case IWL_ANTENNA_AUX: - if (priv->eeprom.antenna_switch_type) + if (priv->eeprom39.antenna_switch_type) return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK; return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK; } @@ -305,7 +305,7 @@ int iwl3945_rs_next_rate(struct iwl3945_priv *priv, int rate) static void iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv, int txq_id, int index) { - struct iwl3945_tx_queue *txq = &priv->txq[txq_id]; + struct iwl3945_tx_queue *txq = &priv->txq39[txq_id]; struct iwl_queue *q = &txq->q; struct iwl3945_tx_info *tx_info; @@ -336,7 +336,7 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, u16 sequence = le16_to_cpu(pkt->hdr.sequence); int txq_id = SEQ_TO_QUEUE(sequence); int index = SEQ_TO_INDEX(sequence); - struct iwl3945_tx_queue *txq = &priv->txq[txq_id]; + struct iwl3945_tx_queue *txq = &priv->txq39[txq_id]; struct ieee80211_tx_info *info; struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; u32 status = le32_to_cpu(tx_resp->status); @@ -396,7 +396,7 @@ void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl_rx_mem_buffe (int)sizeof(struct iwl3945_notif_statistics), le32_to_cpu(pkt->len)); - memcpy(&priv->statistics, pkt->u.raw, sizeof(priv->statistics)); + memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39)); iwl3945_led_background(priv); @@ -808,9 +808,9 @@ u8 iwl3945_hw_find_station(struct iwl3945_priv *priv, const u8 *addr) spin_lock_irqsave(&priv->sta_lock, flags); for (i = start; i < priv->hw_params.max_stations; i++) - if ((priv->stations[i].used) && + if ((priv->stations_39[i].used) && (!compare_ether_addr - (priv->stations[i].sta.sta.addr, addr))) { + (priv->stations_39[i].sta.sta.addr, addr))) { ret = i; goto out; } @@ -905,7 +905,7 @@ u8 iwl3945_sync_sta(struct iwl3945_priv *priv, int sta_id, u16 tx_rate, u8 flags return IWL_INVALID_STATION; spin_lock_irqsave(&priv->sta_lock, flags_spin); - station = &priv->stations[sta_id]; + station = &priv->stations_39[sta_id]; station->sta.sta.modify_mask = STA_MODIFY_TX_RATE_MSK; station->sta.rate_n_flags = cpu_to_le16(tx_rate); @@ -1062,7 +1062,7 @@ static int iwl3945_txq_ctx_reset(struct iwl3945_priv *priv) for (txq_id = 0; txq_id < TFD_QUEUE_MAX; txq_id++) { slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; - rc = iwl3945_tx_queue_init(priv, &priv->txq[txq_id], slots_num, + rc = iwl3945_tx_queue_init(priv, &priv->txq39[txq_id], slots_num, txq_id); if (rc) { IWL_ERROR("Tx %d queue init failed\n", txq_id); @@ -1135,42 +1135,42 @@ int iwl3945_hw_nic_init(struct iwl3945_priv *priv) CSR39_HW_IF_CONFIG_REG_BIT_3945_MM); } - if (EEPROM_SKU_CAP_OP_MODE_MRC == priv->eeprom.sku_cap) { + if (EEPROM_SKU_CAP_OP_MODE_MRC == priv->eeprom39.sku_cap) { IWL_DEBUG_INFO("SKU OP mode is mrc\n"); iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC); } else IWL_DEBUG_INFO("SKU OP mode is basic\n"); - if ((priv->eeprom.board_revision & 0xF0) == 0xD0) { + if ((priv->eeprom39.board_revision & 0xF0) == 0xD0) { IWL_DEBUG_INFO("3945ABG revision is 0x%X\n", - priv->eeprom.board_revision); + priv->eeprom39.board_revision); iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE); } else { IWL_DEBUG_INFO("3945ABG revision is 0x%X\n", - priv->eeprom.board_revision); + priv->eeprom39.board_revision); iwl3945_clear_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE); } - if (priv->eeprom.almgor_m_version <= 1) { + if (priv->eeprom39.almgor_m_version <= 1) { iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A); IWL_DEBUG_INFO("Card M type A version is 0x%X\n", - priv->eeprom.almgor_m_version); + priv->eeprom39.almgor_m_version); } else { IWL_DEBUG_INFO("Card M type B version is 0x%X\n", - priv->eeprom.almgor_m_version); + priv->eeprom39.almgor_m_version); iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B); } spin_unlock_irqrestore(&priv->lock, flags); - if (priv->eeprom.sku_cap & EEPROM_SKU_CAP_SW_RF_KILL_ENABLE) + if (priv->eeprom39.sku_cap & EEPROM_SKU_CAP_SW_RF_KILL_ENABLE) IWL_DEBUG_RF_KILL("SW RF KILL supported in EEPROM.\n"); - if (priv->eeprom.sku_cap & EEPROM_SKU_CAP_HW_RF_KILL_ENABLE) + if (priv->eeprom39.sku_cap & EEPROM_SKU_CAP_HW_RF_KILL_ENABLE) IWL_DEBUG_RF_KILL("HW RF KILL supported in EEPROM.\n"); /* Allocate the RX queue, or reset if it is already allocated */ @@ -1224,7 +1224,7 @@ void iwl3945_hw_txq_ctx_free(struct iwl3945_priv *priv) /* Tx queues */ for (txq_id = 0; txq_id < TFD_QUEUE_MAX; txq_id++) - iwl3945_tx_queue_free(priv, &priv->txq[txq_id]); + iwl3945_tx_queue_free(priv, &priv->txq39[txq_id]); } void iwl3945_hw_txq_ctx_stop(struct iwl3945_priv *priv) @@ -1382,7 +1382,7 @@ static int iwl3945_hw_reg_txpower_get_temperature(struct iwl3945_priv *priv) /* if really really hot(?), * substitute the 3rd band/group's temp measured at factory */ if (priv->last_temperature > 100) - temperature = priv->eeprom.groups[2].temperature; + temperature = priv->eeprom39.groups[2].temperature; else /* else use most recent "sane" value from driver */ temperature = priv->last_temperature; } @@ -1677,17 +1677,17 @@ int iwl3945_hw_reg_send_txpower(struct iwl3945_priv *priv) int rate_idx, i; const struct iwl_channel_info *ch_info = NULL; struct iwl3945_txpowertable_cmd txpower = { - .channel = priv->active_rxon.channel, + .channel = priv->active39_rxon.channel, }; txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1; ch_info = iwl3945_get_channel_info(priv, priv->band, - le16_to_cpu(priv->active_rxon.channel)); + le16_to_cpu(priv->active39_rxon.channel)); if (!ch_info) { IWL_ERROR ("Failed to get channel info for channel %d [%d]\n", - le16_to_cpu(priv->active_rxon.channel), priv->band); + le16_to_cpu(priv->active39_rxon.channel), priv->band); return -EINVAL; } @@ -1757,7 +1757,7 @@ static int iwl3945_hw_reg_set_new_power(struct iwl3945_priv *priv, int power; /* Get this chnlgrp's rate-to-max/clip-powers table */ - clip_pwrs = priv->clip_groups[ch_info->group_index].clip_powers; + clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers; /* Get this channel's rate-to-current-power settings table */ power_info = ch_info->power_info; @@ -1856,7 +1856,7 @@ static int iwl3945_hw_reg_comp_txpower_temp(struct iwl3945_priv *priv) a_band = is_channel_a_band(ch_info); /* Get this chnlgrp's factory calibration temperature */ - ref_temp = (s16)priv->eeprom.groups[ch_info->group_index]. + ref_temp = (s16)priv->eeprom39.groups[ch_info->group_index]. temperature; /* get power index adjustment based on current and factory @@ -1882,7 +1882,7 @@ static int iwl3945_hw_reg_comp_txpower_temp(struct iwl3945_priv *priv) } /* Get this chnlgrp's rate-to-max/clip-powers table */ - clip_pwrs = priv->clip_groups[ch_info->group_index].clip_powers; + clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers; /* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */ for (scan_tbl_index = 0; @@ -2001,7 +2001,7 @@ static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work) static u16 iwl3945_hw_reg_get_ch_grp_index(struct iwl3945_priv *priv, const struct iwl_channel_info *ch_info) { - struct iwl3945_eeprom_txpower_group *ch_grp = &priv->eeprom.groups[0]; + struct iwl3945_eeprom_txpower_group *ch_grp = &priv->eeprom39.groups[0]; u8 group; u16 group_index = 0; /* based on factory calib frequencies */ u8 grp_channel; @@ -2045,7 +2045,7 @@ static int iwl3945_hw_reg_get_matched_power_index(struct iwl3945_priv *priv, s32 res; s32 denominator; - chnl_grp = &priv->eeprom.groups[setting_index]; + chnl_grp = &priv->eeprom39.groups[setting_index]; samples = chnl_grp->samples; for (i = 0; i < 5; i++) { if (power == samples[i].power) { @@ -2091,7 +2091,7 @@ static void iwl3945_hw_reg_init_channel_groups(struct iwl3945_priv *priv) for (i = 0; i < IWL_NUM_TX_CALIB_GROUPS; i++) { s8 *clip_pwrs; /* table of power levels for each rate */ s8 satur_pwr; /* saturation power for each chnl group */ - group = &priv->eeprom.groups[i]; + group = &priv->eeprom39.groups[i]; /* sanity check on factory saturation power value */ if (group->saturation_power < 40) { @@ -2110,7 +2110,7 @@ static void iwl3945_hw_reg_init_channel_groups(struct iwl3945_priv *priv) * power peaks, without too much distortion (clipping). */ /* we'll fill in this array with h/w max power levels */ - clip_pwrs = (s8 *) priv->clip_groups[i].clip_powers; + clip_pwrs = (s8 *) priv->clip39_groups[i].clip_powers; /* divide factory saturation power by 2 to find -3dB level */ satur_pwr = (s8) (group->saturation_power >> 1); @@ -2193,12 +2193,12 @@ int iwl3945_txpower_set_from_eeprom(struct iwl3945_priv *priv) iwl3945_hw_reg_get_ch_grp_index(priv, ch_info); /* Get this chnlgrp's rate->max/clip-powers table */ - clip_pwrs = priv->clip_groups[ch_info->group_index].clip_powers; + clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers; /* calculate power index *adjustment* value according to * diff between current temperature and factory temperature */ delta_index = iwl3945_hw_reg_adjust_power_by_temp(temperature, - priv->eeprom.groups[ch_info->group_index]. + priv->eeprom39.groups[ch_info->group_index]. temperature); IWL_DEBUG_POWER("Delta index for channel %d: %d [%d]\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index cfceee18814..788cd9cc4b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -422,7 +422,7 @@ struct iwl3945_priv { /* each calibration channel group in the EEPROM has a derived * clip setting for each rate. */ - const struct iwl3945_clip_group clip_groups[5]; + const struct iwl3945_clip_group clip39_groups[5]; /* thermal calibration */ s32 temperature; /* degrees Kelvin */ @@ -438,7 +438,7 @@ struct iwl3945_priv { int one_direct_scan; u8 direct_ssid_len; u8 direct_ssid[IW_ESSID_MAX_SIZE]; - struct iwl3945_scan_cmd *scan; + struct iwl3945_scan_cmd *scan39; /* spinlock */ spinlock_t lock; /* protect general shared data */ @@ -468,11 +468,11 @@ struct iwl3945_priv { * changed via explicit cast within the * routines that actually update the physical * hardware */ - const struct iwl3945_rxon_cmd active_rxon; - struct iwl3945_rxon_cmd staging_rxon; + const struct iwl3945_rxon_cmd active39_rxon; + struct iwl3945_rxon_cmd staging39_rxon; int error_recovering; - struct iwl3945_rxon_cmd recovery_rxon; + struct iwl3945_rxon_cmd recovery39_rxon; /* 1st responses from initialize and runtime uCode images. * 4965's initialize alive response contains some calibration data. */ @@ -485,7 +485,7 @@ struct iwl3945_priv { #endif #ifdef CONFIG_IWL3945_LEDS - struct iwl3945_led led[IWL_LED_TRG_MAX]; + struct iwl3945_led led39[IWL_LED_TRG_MAX]; unsigned long last_blink_time; u8 last_blink_rate; u8 allow_blinking; @@ -510,16 +510,16 @@ struct iwl3945_priv { /* Rx and Tx DMA processing queues */ struct iwl_rx_queue rxq; - struct iwl3945_tx_queue txq[IWL39_MAX_NUM_QUEUES]; + struct iwl3945_tx_queue txq39[IWL39_MAX_NUM_QUEUES]; unsigned long status; int last_rx_rssi; /* From Rx packet statisitics */ int last_rx_noise; /* From beacon statistics */ - struct iwl3945_power_mgr power_data; + struct iwl3945_power_mgr power_data_39; - struct iwl3945_notif_statistics statistics; + struct iwl3945_notif_statistics statistics_39; unsigned long last_statistics_time; /* context information */ @@ -534,7 +534,7 @@ struct iwl3945_priv { /*station table variables */ spinlock_t sta_lock; int num_stations; - struct iwl3945_station_entry stations[IWL_STATION_COUNT]; + struct iwl3945_station_entry stations_39[IWL_STATION_COUNT]; /* Indication if ieee80211_ops->open has been called */ u8 is_open; @@ -546,7 +546,7 @@ struct iwl3945_priv { u64 last_tsf; /* eeprom */ - struct iwl3945_eeprom eeprom; + struct iwl3945_eeprom eeprom39; enum nl80211_iftype iw_mode; @@ -607,7 +607,7 @@ struct iwl3945_priv { static inline int iwl3945_is_associated(struct iwl3945_priv *priv) { - return (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0; + return (priv->active39_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0; } extern const struct iwl_channel_info *iwl3945_get_channel_info( diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index b42bb8433a5..43af2595c69 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -329,8 +329,8 @@ static u8 iwl3945_remove_station(struct iwl3945_priv *priv, const u8 *addr, int index = priv->hw_params.bcast_sta_id; else for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) - if (priv->stations[i].used && - !compare_ether_addr(priv->stations[i].sta.sta.addr, + if (priv->stations_39[i].used && + !compare_ether_addr(priv->stations_39[i].sta.sta.addr, addr)) { index = i; break; @@ -339,8 +339,8 @@ static u8 iwl3945_remove_station(struct iwl3945_priv *priv, const u8 *addr, int if (unlikely(index == IWL_INVALID_STATION)) goto out; - if (priv->stations[index].used) { - priv->stations[index].used = 0; + if (priv->stations_39[index].used) { + priv->stations_39[index].used = 0; priv->num_stations--; } @@ -364,7 +364,7 @@ static void iwl3945_clear_stations_table(struct iwl3945_priv *priv) spin_lock_irqsave(&priv->sta_lock, flags); priv->num_stations = 0; - memset(priv->stations, 0, sizeof(priv->stations)); + memset(priv->stations_39, 0, sizeof(priv->stations_39)); spin_unlock_irqrestore(&priv->sta_lock, flags); } @@ -387,13 +387,13 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8 index = priv->hw_params.bcast_sta_id; else for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) { - if (!compare_ether_addr(priv->stations[i].sta.sta.addr, + if (!compare_ether_addr(priv->stations_39[i].sta.sta.addr, addr)) { index = i; break; } - if (!priv->stations[i].used && + if (!priv->stations_39[i].used && index == IWL_INVALID_STATION) index = i; } @@ -405,14 +405,14 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8 return index; } - if (priv->stations[index].used && - !compare_ether_addr(priv->stations[index].sta.sta.addr, addr)) { + if (priv->stations_39[index].used && + !compare_ether_addr(priv->stations_39[index].sta.sta.addr, addr)) { spin_unlock_irqrestore(&priv->sta_lock, flags_spin); return index; } IWL_DEBUG_ASSOC("Add STA ID %d: %pM\n", index, addr); - station = &priv->stations[index]; + station = &priv->stations_39[index]; station->used = 1; priv->num_stations++; @@ -502,7 +502,7 @@ static inline int iwl3945_is_ready_rf(struct iwl3945_priv *priv) */ static int iwl3945_enqueue_hcmd(struct iwl3945_priv *priv, struct iwl3945_host_cmd *cmd) { - struct iwl3945_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; + struct iwl3945_tx_queue *txq = &priv->txq39[IWL_CMD_QUEUE_NUM]; struct iwl_queue *q = &txq->q; struct iwl3945_tfd_frame *tfd; u32 *control_flags; @@ -678,7 +678,7 @@ cancel: * TX cmd queue. Otherwise in case the cmd comes * in later, it will possibly set an invalid * address (cmd->meta.source). */ - qcmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx]; + qcmd = &priv->txq39[IWL_CMD_QUEUE_NUM].cmd[cmd_idx]; qcmd->meta.flags &= ~CMD_WANT_SKB; } fail: @@ -746,15 +746,15 @@ static int iwl3945_set_rxon_channel(struct iwl3945_priv *priv, return -EINVAL; } - if ((le16_to_cpu(priv->staging_rxon.channel) == channel) && + if ((le16_to_cpu(priv->staging39_rxon.channel) == channel) && (priv->band == band)) return 0; - priv->staging_rxon.channel = cpu_to_le16(channel); + priv->staging39_rxon.channel = cpu_to_le16(channel); if (band == IEEE80211_BAND_5GHZ) - priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK; + priv->staging39_rxon.flags &= ~RXON_FLG_BAND_24G_MSK; else - priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; + priv->staging39_rxon.flags |= RXON_FLG_BAND_24G_MSK; priv->band = band; @@ -774,7 +774,7 @@ static int iwl3945_check_rxon_cmd(struct iwl3945_priv *priv) { int error = 0; int counter = 1; - struct iwl3945_rxon_cmd *rxon = &priv->staging_rxon; + struct iwl3945_rxon_cmd *rxon = &priv->staging39_rxon; if (rxon->flags & RXON_FLG_BAND_24G_MSK) { error |= le32_to_cpu(rxon->flags & @@ -856,17 +856,17 @@ static int iwl3945_full_rxon_required(struct iwl3945_priv *priv) /* These items are only settable from the full RXON command */ if (!(iwl3945_is_associated(priv)) || - compare_ether_addr(priv->staging_rxon.bssid_addr, - priv->active_rxon.bssid_addr) || - compare_ether_addr(priv->staging_rxon.node_addr, - priv->active_rxon.node_addr) || - compare_ether_addr(priv->staging_rxon.wlap_bssid_addr, - priv->active_rxon.wlap_bssid_addr) || - (priv->staging_rxon.dev_type != priv->active_rxon.dev_type) || - (priv->staging_rxon.channel != priv->active_rxon.channel) || - (priv->staging_rxon.air_propagation != - priv->active_rxon.air_propagation) || - (priv->staging_rxon.assoc_id != priv->active_rxon.assoc_id)) + compare_ether_addr(priv->staging39_rxon.bssid_addr, + priv->active39_rxon.bssid_addr) || + compare_ether_addr(priv->staging39_rxon.node_addr, + priv->active39_rxon.node_addr) || + compare_ether_addr(priv->staging39_rxon.wlap_bssid_addr, + priv->active39_rxon.wlap_bssid_addr) || + (priv->staging39_rxon.dev_type != priv->active39_rxon.dev_type) || + (priv->staging39_rxon.channel != priv->active39_rxon.channel) || + (priv->staging39_rxon.air_propagation != + priv->active39_rxon.air_propagation) || + (priv->staging39_rxon.assoc_id != priv->active39_rxon.assoc_id)) return 1; /* flags, filter_flags, ofdm_basic_rates, and cck_basic_rates can @@ -874,13 +874,13 @@ static int iwl3945_full_rxon_required(struct iwl3945_priv *priv) * flag transitions are allowed using RXON_ASSOC */ /* Check if we are not switching bands */ - if ((priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) != - (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK)) + if ((priv->staging39_rxon.flags & RXON_FLG_BAND_24G_MSK) != + (priv->active39_rxon.flags & RXON_FLG_BAND_24G_MSK)) return 1; /* Check if we are switching association toggle */ - if ((priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) != - (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) + if ((priv->staging39_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) != + (priv->active39_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) return 1; return 0; @@ -897,8 +897,8 @@ static int iwl3945_send_rxon_assoc(struct iwl3945_priv *priv) .meta.flags = CMD_WANT_SKB, .data = &rxon_assoc, }; - const struct iwl3945_rxon_cmd *rxon1 = &priv->staging_rxon; - const struct iwl3945_rxon_cmd *rxon2 = &priv->active_rxon; + const struct iwl3945_rxon_cmd *rxon1 = &priv->staging39_rxon; + const struct iwl3945_rxon_cmd *rxon2 = &priv->active39_rxon; if ((rxon1->flags == rxon2->flags) && (rxon1->filter_flags == rxon2->filter_flags) && @@ -908,10 +908,10 @@ static int iwl3945_send_rxon_assoc(struct iwl3945_priv *priv) return 0; } - rxon_assoc.flags = priv->staging_rxon.flags; - rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; - rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; - rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; + rxon_assoc.flags = priv->staging39_rxon.flags; + rxon_assoc.filter_flags = priv->staging39_rxon.filter_flags; + rxon_assoc.ofdm_basic_rates = priv->staging39_rxon.ofdm_basic_rates; + rxon_assoc.cck_basic_rates = priv->staging39_rxon.cck_basic_rates; rxon_assoc.reserved = 0; rc = iwl3945_send_cmd_sync(priv, &cmd); @@ -941,19 +941,19 @@ static int iwl3945_send_rxon_assoc(struct iwl3945_priv *priv) static int iwl3945_commit_rxon(struct iwl3945_priv *priv) { /* cast away the const for active_rxon in this function */ - struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon; + struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active39_rxon; int rc = 0; if (!iwl3945_is_alive(priv)) return -1; /* always get timestamp with Rx frame */ - priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK; + priv->staging39_rxon.flags |= RXON_FLG_TSF2HOST_MSK; /* select antenna */ - priv->staging_rxon.flags &= + priv->staging39_rxon.flags &= ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK); - priv->staging_rxon.flags |= iwl3945_get_antenna_flags(priv); + priv->staging39_rxon.flags |= iwl3945_get_antenna_flags(priv); rc = iwl3945_check_rxon_cmd(priv); if (rc) { @@ -972,7 +972,7 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv) return rc; } - memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); + memcpy(active_rxon, &priv->staging39_rxon, sizeof(*active_rxon)); return 0; } @@ -982,13 +982,13 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv) * we must clear the associated from the active configuration * before we apply the new config */ if (iwl3945_is_associated(priv) && - (priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) { + (priv->staging39_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) { IWL_DEBUG_INFO("Toggling associated bit on current RXON\n"); active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON, sizeof(struct iwl3945_rxon_cmd), - &priv->active_rxon); + &priv->active39_rxon); /* If the mask clearing failed then we set * active_rxon back to what it was previously */ @@ -1004,20 +1004,20 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv) "* with%s RXON_FILTER_ASSOC_MSK\n" "* channel = %d\n" "* bssid = %pM\n", - ((priv->staging_rxon.filter_flags & + ((priv->staging39_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? "" : "out"), - le16_to_cpu(priv->staging_rxon.channel), + le16_to_cpu(priv->staging39_rxon.channel), priv->staging_rxon.bssid_addr); /* Apply the new configuration */ rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON, - sizeof(struct iwl3945_rxon_cmd), &priv->staging_rxon); + sizeof(struct iwl3945_rxon_cmd), &priv->staging39_rxon); if (rc) { IWL_ERROR("Error setting new configuration (%d).\n", rc); return rc; } - memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); + memcpy(active_rxon, &priv->staging39_rxon, sizeof(*active_rxon)); iwl3945_clear_stations_table(priv); @@ -1040,7 +1040,7 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv) * add the IWL_AP_ID to the station rate table */ if (iwl3945_is_associated(priv) && (priv->iw_mode == NL80211_IFTYPE_STATION)) - if (iwl3945_add_station(priv, priv->active_rxon.bssid_addr, 1, 0) + if (iwl3945_add_station(priv, priv->active39_rxon.bssid_addr, 1, 0) == IWL_INVALID_STATION) { IWL_ERROR("Error adding AP address for transmit.\n"); return -EIO; @@ -1238,21 +1238,21 @@ static int iwl3945_update_sta_key_info(struct iwl3945_priv *priv, return -EINVAL; } spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].keyinfo.alg = keyconf->alg; - priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; - memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, + priv->stations_39[sta_id].keyinfo.alg = keyconf->alg; + priv->stations_39[sta_id].keyinfo.keylen = keyconf->keylen; + memcpy(priv->stations_39[sta_id].keyinfo.key, keyconf->key, keyconf->keylen); - memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, + memcpy(priv->stations_39[sta_id].sta.key.key, keyconf->key, keyconf->keylen); - priv->stations[sta_id].sta.key.key_flags = key_flags; - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; + priv->stations_39[sta_id].sta.key.key_flags = key_flags; + priv->stations_39[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; + priv->stations_39[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; spin_unlock_irqrestore(&priv->sta_lock, flags); IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n"); - iwl3945_send_add_station(priv, &priv->stations[sta_id].sta, 0); + iwl3945_send_add_station(priv, &priv->stations_39[sta_id].sta, 0); return 0; } @@ -1261,16 +1261,16 @@ static int iwl3945_clear_sta_key_info(struct iwl3945_priv *priv, u8 sta_id) unsigned long flags; spin_lock_irqsave(&priv->sta_lock, flags); - memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl3945_hw_key)); - memset(&priv->stations[sta_id].sta.key, 0, + memset(&priv->stations_39[sta_id].keyinfo, 0, sizeof(struct iwl3945_hw_key)); + memset(&priv->stations_39[sta_id].sta.key, 0, sizeof(struct iwl4965_keyinfo)); - priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC; - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; + priv->stations_39[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC; + priv->stations_39[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; + priv->stations_39[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; spin_unlock_irqrestore(&priv->sta_lock, flags); IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n"); - iwl3945_send_add_station(priv, &priv->stations[sta_id].sta, 0); + iwl3945_send_add_station(priv, &priv->stations_39[sta_id].sta, 0); return 0; } @@ -1345,7 +1345,7 @@ static u8 iwl3945_rate_get_lowest_plcp(struct iwl3945_priv *priv) int rate_mask; /* Set rate mask*/ - if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) + if (priv->staging39_rxon.flags & RXON_FLG_BAND_24G_MSK) rate_mask = priv->active_rate_basic & IWL_CCK_RATES_MASK; else rate_mask = priv->active_rate_basic & IWL_OFDM_RATES_MASK; @@ -1357,7 +1357,7 @@ static u8 iwl3945_rate_get_lowest_plcp(struct iwl3945_priv *priv) } /* No valid rate was found. Assign the lowest one */ - if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) + if (priv->staging39_rxon.flags & RXON_FLG_BAND_24G_MSK) return IWL_RATE_1M_PLCP; else return IWL_RATE_6M_PLCP; @@ -1398,7 +1398,7 @@ static int iwl3945_send_beacon_cmd(struct iwl3945_priv *priv) static void get_eeprom_mac(struct iwl3945_priv *priv, u8 *mac) { - memcpy(mac, priv->eeprom.mac_address, 6); + memcpy(mac, priv->eeprom39.mac_address, 6); } /* @@ -1418,15 +1418,15 @@ static inline int iwl3945_eeprom_acquire_semaphore(struct iwl3945_priv *priv) /** * iwl3945_eeprom_init - read EEPROM contents * - * Load the EEPROM contents from adapter into priv->eeprom + * Load the EEPROM contents from adapter into priv->eeprom39 * * NOTE: This routine uses the non-debug IO access functions. */ int iwl3945_eeprom_init(struct iwl3945_priv *priv) { - u16 *e = (u16 *)&priv->eeprom; + u16 *e = (u16 *)&priv->eeprom39; u32 gp = iwl3945_read32(priv, CSR_EEPROM_GP); - int sz = sizeof(priv->eeprom); + int sz = sizeof(priv->eeprom39); int ret; u16 addr; @@ -1434,7 +1434,7 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv) * and when adding new EEPROM maps is subject to programmer errors * which may be very difficult to identify without explicitly * checking the resulting size of the eeprom map. */ - BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE); + BUILD_BUG_ON(sizeof(priv->eeprom39) != IWL_EEPROM_IMAGE_SIZE); if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) { IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x\n", gp); @@ -1625,7 +1625,7 @@ static void iwl3945_reset_qos(struct iwl3945_priv *priv) if ((priv->iw_mode == NL80211_IFTYPE_ADHOC && (priv->active_rate & IWL_OFDM_RATES_MASK) == 0) || (priv->iw_mode == NL80211_IFTYPE_STATION && - (priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK) == 0)) { + (priv->staging39_rxon.flags & RXON_FLG_SHORT_SLOT_MSK) == 0)) { cw_min = 31; is_legacy = 1; } @@ -1769,7 +1769,7 @@ int iwl3945_power_init_handle(struct iwl3945_priv *priv) IWL_DEBUG_POWER("Initialize power \n"); - pow_data = &(priv->power_data); + pow_data = &(priv->power_data_39); memset(pow_data, 0, sizeof(*pow_data)); @@ -1813,7 +1813,7 @@ static int iwl3945_update_power_cmd(struct iwl3945_priv *priv, IWL_DEBUG_POWER("Error invalid power mode \n"); return -1; } - pow_data = &(priv->power_data); + pow_data = &(priv->power_data_39); if (pow_data->active_index == IWL_POWER_RANGE_0) range = &pow_data->pwr_range_0[0]; @@ -2053,7 +2053,7 @@ static int iwl3945_scan_initiate(struct iwl3945_priv *priv) static int iwl3945_set_rxon_hwcrypto(struct iwl3945_priv *priv, int hw_decrypt) { - struct iwl3945_rxon_cmd *rxon = &priv->staging_rxon; + struct iwl3945_rxon_cmd *rxon = &priv->staging39_rxon; if (hw_decrypt) rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK; @@ -2067,23 +2067,23 @@ static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, enum ieee80211_band band) { if (band == IEEE80211_BAND_5GHZ) { - priv->staging_rxon.flags &= + priv->staging39_rxon.flags &= ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_CCK_MSK); - priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; + priv->staging39_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; } else { /* Copied from iwl3945_bg_post_associate() */ if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) - priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; + priv->staging39_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; else - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; + priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; if (priv->iw_mode == NL80211_IFTYPE_ADHOC) - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; + priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; - priv->staging_rxon.flags |= RXON_FLG_AUTO_DETECT_MSK; - priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK; + priv->staging39_rxon.flags |= RXON_FLG_BAND_24G_MSK; + priv->staging39_rxon.flags |= RXON_FLG_AUTO_DETECT_MSK; + priv->staging39_rxon.flags &= ~RXON_FLG_CCK_MSK; } } @@ -2095,28 +2095,28 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv, { const struct iwl_channel_info *ch_info; - memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon)); + memset(&priv->staging39_rxon, 0, sizeof(priv->staging39_rxon)); switch (mode) { case NL80211_IFTYPE_AP: - priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP; + priv->staging39_rxon.dev_type = RXON_DEV_TYPE_AP; break; case NL80211_IFTYPE_STATION: - priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS; - priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; + priv->staging39_rxon.dev_type = RXON_DEV_TYPE_ESS; + priv->staging39_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; break; case NL80211_IFTYPE_ADHOC: - priv->staging_rxon.dev_type = RXON_DEV_TYPE_IBSS; - priv->staging_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK; - priv->staging_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK | + priv->staging39_rxon.dev_type = RXON_DEV_TYPE_IBSS; + priv->staging39_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK; + priv->staging39_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; break; case NL80211_IFTYPE_MONITOR: - priv->staging_rxon.dev_type = RXON_DEV_TYPE_SNIFFER; - priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK | + priv->staging39_rxon.dev_type = RXON_DEV_TYPE_SNIFFER; + priv->staging39_rxon.filter_flags = RXON_FILTER_PROMISC_MSK | RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK; break; default: @@ -2128,13 +2128,13 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv, /* TODO: Figure out when short_preamble would be set and cache from * that */ if (!hw_to_local(priv->hw)->short_preamble) - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; else - priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + priv->staging39_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; #endif ch_info = iwl3945_get_channel_info(priv, priv->band, - le16_to_cpu(priv->active_rxon.channel)); + le16_to_cpu(priv->active39_rxon.channel)); if (!ch_info) ch_info = &priv->channel_info[0]; @@ -2146,7 +2146,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv, if ((mode == NL80211_IFTYPE_ADHOC) && !(is_channel_ibss(ch_info))) ch_info = &priv->channel_info[0]; - priv->staging_rxon.channel = cpu_to_le16(ch_info->channel); + priv->staging39_rxon.channel = cpu_to_le16(ch_info->channel); if (is_channel_a_band(ch_info)) priv->band = IEEE80211_BAND_5GHZ; else @@ -2154,9 +2154,9 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv, iwl3945_set_flags_for_phymode(priv, priv->band); - priv->staging_rxon.ofdm_basic_rates = + priv->staging39_rxon.ofdm_basic_rates = (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; - priv->staging_rxon.cck_basic_rates = + priv->staging39_rxon.cck_basic_rates = (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; } @@ -2167,17 +2167,17 @@ static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode) ch_info = iwl3945_get_channel_info(priv, priv->band, - le16_to_cpu(priv->staging_rxon.channel)); + le16_to_cpu(priv->staging39_rxon.channel)); if (!ch_info || !is_channel_ibss(ch_info)) { IWL_ERROR("channel %d not IBSS channel\n", - le16_to_cpu(priv->staging_rxon.channel)); + le16_to_cpu(priv->staging39_rxon.channel)); return -EINVAL; } } iwl3945_connection_init_rx_config(priv, mode); - memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); + memcpy(priv->staging39_rxon.node_addr, priv->mac_addr, ETH_ALEN); iwl3945_clear_stations_table(priv); @@ -2204,7 +2204,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl3945_priv *priv, int last_frag) { struct iwl3945_hw_key *keyinfo = - &priv->stations[info->control.hw_key->hw_key_idx].keyinfo; + &priv->stations_39[info->control.hw_key->hw_key_idx].keyinfo; switch (keyinfo->alg) { case ALG_CCMP: @@ -2446,7 +2446,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) if (ieee80211_is_data_qos(fc)) { qc = ieee80211_get_qos_ctl(hdr); tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; - seq_number = priv->stations[sta_id].tid[tid].seq_number & + seq_number = priv->stations_39[sta_id].tid[tid].seq_number & IEEE80211_SCTL_SEQ; hdr->seq_ctrl = cpu_to_le16(seq_number) | (hdr->seq_ctrl & @@ -2455,7 +2455,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) } /* Descriptor for chosen Tx queue */ - txq = &priv->txq[txq_id]; + txq = &priv->txq39[txq_id]; q = &txq->q; spin_lock_irqsave(&priv->lock, flags); @@ -2554,7 +2554,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) if (!ieee80211_has_morefrags(hdr->frame_control)) { txq->need_update = 1; if (qc) - priv->stations[sta_id].tid[tid].seq_number = seq_number; + priv->stations_39[sta_id].tid[tid].seq_number = seq_number; } else { wait_write_ptr = 1; txq->need_update = 0; @@ -2631,20 +2631,20 @@ static void iwl3945_set_rate(struct iwl3945_priv *priv) * OFDM */ if (priv->active_rate_basic & IWL_CCK_BASIC_RATES_MASK) - priv->staging_rxon.cck_basic_rates = + priv->staging39_rxon.cck_basic_rates = ((priv->active_rate_basic & IWL_CCK_RATES_MASK) >> IWL_FIRST_CCK_RATE) & 0xF; else - priv->staging_rxon.cck_basic_rates = + priv->staging39_rxon.cck_basic_rates = (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; if (priv->active_rate_basic & IWL_OFDM_BASIC_RATES_MASK) - priv->staging_rxon.ofdm_basic_rates = + priv->staging39_rxon.ofdm_basic_rates = ((priv->active_rate_basic & (IWL_OFDM_BASIC_RATES_MASK | IWL_RATE_6M_MASK)) >> IWL_FIRST_OFDM_RATE) & 0xFF; else - priv->staging_rxon.ofdm_basic_rates = + priv->staging39_rxon.ofdm_basic_rates = (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; } @@ -2704,7 +2704,7 @@ void iwl3945_set_decrypted_flag(struct iwl3945_priv *priv, struct sk_buff *skb, u16 fc = le16_to_cpu(((struct ieee80211_hdr *)skb->data)->frame_control); - if (priv->active_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK) + if (priv->active39_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK) return; if (!(fc & IEEE80211_FCTL_PROTECTED)) @@ -2825,7 +2825,7 @@ static int iwl3945_get_measurement(struct iwl3945_priv *priv, spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT); spectrum.channels[0].channel = params->channel; spectrum.channels[0].type = type; - if (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK) + if (priv->active39_rxon.flags & RXON_FLG_BAND_24G_MSK) spectrum.flags |= RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK; @@ -2926,12 +2926,12 @@ static void iwl3945_rx_reply_error(struct iwl3945_priv *priv, static void iwl3945_rx_csa(struct iwl3945_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; - struct iwl3945_rxon_cmd *rxon = (void *)&priv->active_rxon; + struct iwl3945_rxon_cmd *rxon = (void *)&priv->active39_rxon; struct iwl_csa_notification *csa = &(pkt->u.csa_notif); IWL_DEBUG_11H("CSA notif: channel %d, status %d\n", le16_to_cpu(csa->channel), le32_to_cpu(csa->status)); rxon->channel = csa->channel; - priv->staging_rxon.channel = csa->channel; + priv->staging39_rxon.channel = csa->channel; } static void iwl3945_rx_spectrum_measure_notif(struct iwl3945_priv *priv, @@ -3226,7 +3226,7 @@ static void iwl3945_setup_rx_handlers(struct iwl3945_priv *priv) static void iwl3945_cmd_queue_reclaim(struct iwl3945_priv *priv, int txq_id, int index) { - struct iwl3945_tx_queue *txq = &priv->txq[txq_id]; + struct iwl3945_tx_queue *txq = &priv->txq39[txq_id]; struct iwl_queue *q = &txq->q; int nfreed = 0; @@ -3271,8 +3271,8 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv, BUG_ON(txq_id != IWL_CMD_QUEUE_NUM); - cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); - cmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; + cmd_index = get_cmd_index(&priv->txq39[IWL_CMD_QUEUE_NUM].q, index, huge); + cmd = &priv->txq39[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; /* Input error checking is done when commands are added to queue. */ if (cmd->meta.flags & CMD_WANT_SKB) { @@ -4113,7 +4113,7 @@ static void iwl3945_irq_handle_error(struct iwl3945_priv *priv) if (priv->debug_level & IWL_DL_FW_ERRORS) { iwl3945_dump_nic_error_log(priv); iwl3945_dump_nic_event_log(priv); - iwl3945_print_rx_config_cmd(priv, &priv->staging_rxon); + iwl3945_print_rx_config_cmd(priv, &priv->staging39_rxon); } #endif @@ -4128,8 +4128,8 @@ static void iwl3945_irq_handle_error(struct iwl3945_priv *priv) "Restarting adapter due to uCode error.\n"); if (iwl3945_is_associated(priv)) { - memcpy(&priv->recovery_rxon, &priv->active_rxon, - sizeof(priv->recovery_rxon)); + memcpy(&priv->recovery39_rxon, &priv->active39_rxon, + sizeof(priv->recovery39_rxon)); priv->error_recovering = 1; } queue_work(priv->workqueue, &priv->restart); @@ -4140,15 +4140,15 @@ static void iwl3945_error_recovery(struct iwl3945_priv *priv) { unsigned long flags; - memcpy(&priv->staging_rxon, &priv->recovery_rxon, - sizeof(priv->staging_rxon)); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + memcpy(&priv->staging39_rxon, &priv->recovery39_rxon, + sizeof(priv->staging39_rxon)); + priv->staging39_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl3945_commit_rxon(priv); iwl3945_add_station(priv, priv->bssid, 1, 0); spin_lock_irqsave(&priv->lock, flags); - priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id); + priv->assoc_id = le16_to_cpu(priv->staging39_rxon.assoc_id); priv->error_recovering = 0; spin_unlock_irqrestore(&priv->lock, flags); } @@ -4237,12 +4237,12 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv) if (inta & CSR_INT_BIT_WAKEUP) { IWL_DEBUG_ISR("Wakeup interrupt\n"); iwl3945_rx_queue_update_write_ptr(priv, &priv->rxq); - iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[0]); - iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[1]); - iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[2]); - iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[3]); - iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[4]); - iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[5]); + iwl3945_tx_queue_update_write_ptr(priv, &priv->txq39[0]); + iwl3945_tx_queue_update_write_ptr(priv, &priv->txq39[1]); + iwl3945_tx_queue_update_write_ptr(priv, &priv->txq39[2]); + iwl3945_tx_queue_update_write_ptr(priv, &priv->txq39[3]); + iwl3945_tx_queue_update_write_ptr(priv, &priv->txq39[4]); + iwl3945_tx_queue_update_write_ptr(priv, &priv->txq39[5]); handled |= CSR_INT_BIT_WAKEUP; } @@ -4356,7 +4356,7 @@ unplugged: * EEPROM contents to the specific channel number supported for each * band. * - * For example, iwl3945_priv->eeprom.band_3_channels[4] from the band_3 + * For example, iwl3945_priv->eeprom39.band_3_channels[4] from the band_3 * definition below maps to physical channel 42 in the 5.2GHz spectrum. * The specific geography and calibration information for that channel * is contained in the eeprom map itself. @@ -4412,27 +4412,27 @@ static void iwl3945_init_band_reference(const struct iwl3945_priv *priv, int ban switch (band) { case 1: /* 2.4GHz band */ *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_1); - *eeprom_ch_info = priv->eeprom.band_1_channels; + *eeprom_ch_info = priv->eeprom39.band_1_channels; *eeprom_ch_index = iwl3945_eeprom_band_1; break; case 2: /* 4.9GHz band */ *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_2); - *eeprom_ch_info = priv->eeprom.band_2_channels; + *eeprom_ch_info = priv->eeprom39.band_2_channels; *eeprom_ch_index = iwl3945_eeprom_band_2; break; case 3: /* 5.2GHz band */ *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_3); - *eeprom_ch_info = priv->eeprom.band_3_channels; + *eeprom_ch_info = priv->eeprom39.band_3_channels; *eeprom_ch_index = iwl3945_eeprom_band_3; break; case 4: /* 5.5GHz band */ *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_4); - *eeprom_ch_info = priv->eeprom.band_4_channels; + *eeprom_ch_info = priv->eeprom39.band_4_channels; *eeprom_ch_index = iwl3945_eeprom_band_4; break; case 5: /* 5.7GHz band */ *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_5); - *eeprom_ch_info = priv->eeprom.band_5_channels; + *eeprom_ch_info = priv->eeprom39.band_5_channels; *eeprom_ch_index = iwl3945_eeprom_band_5; break; default: @@ -4490,9 +4490,9 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv) return 0; } - if (priv->eeprom.version < 0x2f) { + if (priv->eeprom39.version < 0x2f) { IWL_WARNING("Unsupported EEPROM version: 0x%04X\n", - priv->eeprom.version); + priv->eeprom39.version); return -EINVAL; } @@ -5626,15 +5626,15 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv) if (iwl3945_is_associated(priv)) { struct iwl3945_rxon_cmd *active_rxon = - (struct iwl3945_rxon_cmd *)(&priv->active_rxon); + (struct iwl3945_rxon_cmd *)(&priv->active39_rxon); - memcpy(&priv->staging_rxon, &priv->active_rxon, - sizeof(priv->staging_rxon)); + memcpy(&priv->staging39_rxon, &priv->active39_rxon, + sizeof(priv->staging39_rxon)); active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; } else { /* Initialize our rx_config data */ iwl3945_connection_init_rx_config(priv, priv->iw_mode); - memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); + memcpy(priv->staging39_rxon.node_addr, priv->mac_addr, ETH_ALEN); } /* Configure Bluetooth device coexistence support */ @@ -6027,15 +6027,15 @@ static void iwl3945_bg_request_scan(struct work_struct *data) goto done; } - if (!priv->scan) { - priv->scan = kmalloc(sizeof(struct iwl3945_scan_cmd) + + if (!priv->scan39) { + priv->scan39 = kmalloc(sizeof(struct iwl3945_scan_cmd) + IWL_MAX_SCAN_SIZE, GFP_KERNEL); - if (!priv->scan) { + if (!priv->scan39) { rc = -ENOMEM; goto done; } } - scan = priv->scan; + scan = priv->scan39; memset(scan, 0, sizeof(struct iwl3945_scan_cmd) + IWL_MAX_SCAN_SIZE); scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; @@ -6210,7 +6210,7 @@ static void iwl3945_post_associate(struct iwl3945_priv *priv) IWL_DEBUG_ASSOC("Associated as %d to: %pM\n", - priv->assoc_id, priv->active_rxon.bssid_addr); + priv->assoc_id, priv->active39_rxon.bssid_addr); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -6222,7 +6222,7 @@ static void iwl3945_post_associate(struct iwl3945_priv *priv) conf = ieee80211_get_hw_conf(priv->hw); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + priv->staging39_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl3945_commit_rxon(priv); memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); @@ -6233,26 +6233,26 @@ static void iwl3945_post_associate(struct iwl3945_priv *priv) IWL_WARNING("REPLY_RXON_TIMING failed - " "Attempting to continue.\n"); - priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; + priv->staging39_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; - priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); + priv->staging39_rxon.assoc_id = cpu_to_le16(priv->assoc_id); IWL_DEBUG_ASSOC("assoc id %d beacon interval %d\n", priv->assoc_id, priv->beacon_int); if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + priv->staging39_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { + if (priv->staging39_rxon.flags & RXON_FLG_BAND_24G_MSK) { if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) - priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; + priv->staging39_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; else - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; + priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; if (priv->iw_mode == NL80211_IFTYPE_ADHOC) - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; + priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } @@ -6359,7 +6359,7 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) /* we should be verifying the device is ready to be opened */ mutex_lock(&priv->mutex); - memset(&priv->staging_rxon, 0, sizeof(struct iwl3945_rxon_cmd)); + memset(&priv->staging39_rxon, 0, sizeof(struct iwl3945_rxon_cmd)); /* fetch ucode file from disk, alloc and copy to bus-master buffers ... * ucode filename and max sizes are card-specific. */ @@ -6576,8 +6576,8 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed) iwl3945_set_rate(priv); - if (memcmp(&priv->active_rxon, - &priv->staging_rxon, sizeof(priv->staging_rxon))) + if (memcmp(&priv->active39_rxon, + &priv->staging39_rxon, sizeof(priv->staging39_rxon))) iwl3945_commit_rxon(priv); else IWL_DEBUG_INFO("No re-sending same RXON configuration.\n"); @@ -6601,7 +6601,7 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv) if (!(iwl3945_is_associated(priv))) { /* RXON - unassoc (to set timing command) */ - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + priv->staging39_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl3945_commit_rxon(priv); /* RXON Timing */ @@ -6614,29 +6614,29 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv) "Attempting to continue.\n"); /* FIXME: what should be the assoc_id for AP? */ - priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); + priv->staging39_rxon.assoc_id = cpu_to_le16(priv->assoc_id); if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - priv->staging_rxon.flags |= + priv->staging39_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else - priv->staging_rxon.flags &= + priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { + if (priv->staging39_rxon.flags & RXON_FLG_BAND_24G_MSK) { if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) - priv->staging_rxon.flags |= + priv->staging39_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; else - priv->staging_rxon.flags &= + priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; if (priv->iw_mode == NL80211_IFTYPE_ADHOC) - priv->staging_rxon.flags &= + priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } /* restore RXON assoc */ - priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; + priv->staging39_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; iwl3945_commit_rxon(priv); iwl3945_add_station(priv, iwl_bcast_addr, 0, 0); } @@ -6717,7 +6717,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, mutex_unlock(&priv->mutex); return -EAGAIN; } - memcpy(priv->staging_rxon.bssid_addr, conf->bssid, ETH_ALEN); + memcpy(priv->staging39_rxon.bssid_addr, conf->bssid, ETH_ALEN); /* TODO: Audit driver for usage of these members and see * if mac80211 deprecates them (priv->bssid looks like it @@ -6731,12 +6731,12 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, rc = iwl3945_commit_rxon(priv); if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc) iwl3945_add_station(priv, - priv->active_rxon.bssid_addr, 1, 0); + priv->active39_rxon.bssid_addr, 1, 0); } } else { iwl3945_scan_cancel_timeout(priv, 100); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + priv->staging39_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl3945_commit_rxon(priv); } @@ -6753,7 +6753,7 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw, int mc_count, struct dev_addr_list *mc_list) { struct iwl3945_priv *priv = hw->priv; - __le32 *filter_flags = &priv->staging_rxon.filter_flags; + __le32 *filter_flags = &priv->staging39_rxon.filter_flags; IWL_DEBUG_MAC80211("Enter: changed: 0x%x, total: 0x%x\n", changed_flags, *total_flags); @@ -6804,7 +6804,7 @@ static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw, if (iwl3945_is_ready_rf(priv)) { iwl3945_scan_cancel_timeout(priv, 100); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + priv->staging39_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl3945_commit_rxon(priv); } if (priv->vif == conf->vif) { @@ -6831,17 +6831,17 @@ static void iwl3945_bss_info_changed(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211("ERP_PREAMBLE %d\n", bss_conf->use_short_preamble); if (bss_conf->use_short_preamble) - priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + priv->staging39_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; } if (changes & BSS_CHANGED_ERP_CTS_PROT) { IWL_DEBUG_MAC80211("ERP_CTS %d\n", bss_conf->use_cts_prot); if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) - priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; + priv->staging39_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; else - priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; + priv->staging39_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; } if (changes & BSS_CHANGED_ASSOC) { @@ -7048,7 +7048,7 @@ static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw, spin_lock_irqsave(&priv->lock, flags); for (i = 0; i < AC_NUM; i++) { - txq = &priv->txq[i]; + txq = &priv->txq39[i]; q = &txq->q; avail = iwl_queue_space(q); @@ -7103,7 +7103,7 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) */ if (priv->iw_mode != NL80211_IFTYPE_AP) { iwl3945_scan_cancel_timeout(priv, 100); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + priv->staging39_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl3945_commit_rxon(priv); } @@ -7250,7 +7250,7 @@ static ssize_t show_flags(struct device *d, { struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data; - return sprintf(buf, "0x%04X\n", priv->active_rxon.flags); + return sprintf(buf, "0x%04X\n", priv->active39_rxon.flags); } static ssize_t store_flags(struct device *d, @@ -7261,14 +7261,14 @@ static ssize_t store_flags(struct device *d, u32 flags = simple_strtoul(buf, NULL, 0); mutex_lock(&priv->mutex); - if (le32_to_cpu(priv->staging_rxon.flags) != flags) { + if (le32_to_cpu(priv->staging39_rxon.flags) != flags) { /* Cancel any currently running scans... */ if (iwl3945_scan_cancel_timeout(priv, 100)) IWL_WARNING("Could not cancel scan.\n"); else { IWL_DEBUG_INFO("Committing rxon.flags = 0x%04X\n", flags); - priv->staging_rxon.flags = cpu_to_le32(flags); + priv->staging39_rxon.flags = cpu_to_le32(flags); iwl3945_commit_rxon(priv); } } @@ -7285,7 +7285,7 @@ static ssize_t show_filter_flags(struct device *d, struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data; return sprintf(buf, "0x%04X\n", - le32_to_cpu(priv->active_rxon.filter_flags)); + le32_to_cpu(priv->active39_rxon.filter_flags)); } static ssize_t store_filter_flags(struct device *d, @@ -7296,14 +7296,14 @@ static ssize_t store_filter_flags(struct device *d, u32 filter_flags = simple_strtoul(buf, NULL, 0); mutex_lock(&priv->mutex); - if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) { + if (le32_to_cpu(priv->staging39_rxon.filter_flags) != filter_flags) { /* Cancel any currently running scans... */ if (iwl3945_scan_cancel_timeout(priv, 100)) IWL_WARNING("Could not cancel scan.\n"); else { IWL_DEBUG_INFO("Committing rxon.filter_flags = " "0x%04X\n", filter_flags); - priv->staging_rxon.filter_flags = + priv->staging39_rxon.filter_flags = cpu_to_le32(filter_flags); iwl3945_commit_rxon(priv); } @@ -7356,7 +7356,7 @@ static ssize_t store_measurement(struct device *d, { struct iwl3945_priv *priv = dev_get_drvdata(d); struct ieee80211_measurement_params params = { - .channel = le16_to_cpu(priv->active_rxon.channel), + .channel = le16_to_cpu(priv->active39_rxon.channel), .start_time = cpu_to_le64(priv->last_tsf), .duration = cpu_to_le16(1), }; @@ -7518,7 +7518,7 @@ static ssize_t show_statistics(struct device *d, struct iwl3945_priv *priv = dev_get_drvdata(d); u32 size = sizeof(struct iwl3945_notif_statistics); u32 len = 0, ofs = 0; - u8 *data = (u8 *)&priv->statistics; + u8 *data = (u8 *)&priv->statistics_39; int rc = 0; if (!iwl3945_is_alive(priv)) @@ -7860,7 +7860,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->ibss_beacon = NULL; spin_lock_init(&priv->lock); - spin_lock_init(&priv->power_data.lock); + spin_lock_init(&priv->power_data_39.lock); spin_lock_init(&priv->sta_lock); spin_lock_init(&priv->hcmd_lock); @@ -8040,7 +8040,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) iwl3945_free_channel_map(priv); iwl3945_free_geos(priv); - kfree(priv->scan); + kfree(priv->scan39); if (priv->ibss_beacon) dev_kfree_skb(priv->ibss_beacon); -- GitLab From 4a8a43222db6f04c88def2160a95f978f704b515 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Fri, 19 Dec 2008 10:37:28 +0800 Subject: [PATCH 0722/4982] iwl3945: replaces iwl3945_priv with iwl_priv The patch replaces iwl3945_priv to iwl_priv. It adds 3945 specific data members to iwl_priv. Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-io.h | 58 +-- drivers/net/wireless/iwlwifi/iwl-3945-led.c | 26 +- drivers/net/wireless/iwlwifi/iwl-3945-led.h | 22 +- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 24 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 98 ++--- drivers/net/wireless/iwlwifi/iwl-3945.h | 333 +++------------- drivers/net/wireless/iwlwifi/iwl-dev.h | 51 ++- drivers/net/wireless/iwlwifi/iwl3945-base.c | 400 ++++++++++---------- 8 files changed, 417 insertions(+), 595 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-io.h b/drivers/net/wireless/iwlwifi/iwl-3945-io.h index d49dfd1ff53..0b84815dd69 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-io.h @@ -61,7 +61,7 @@ #define _iwl3945_write32(priv, ofs, val) iowrite32((val), (priv)->hw_base + (ofs)) #ifdef CONFIG_IWL3945_DEBUG -static inline void __iwl3945_write32(const char *f, u32 l, struct iwl3945_priv *priv, +static inline void __iwl3945_write32(const char *f, u32 l, struct iwl_priv *priv, u32 ofs, u32 val) { IWL_DEBUG_IO("write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l); @@ -75,7 +75,7 @@ static inline void __iwl3945_write32(const char *f, u32 l, struct iwl3945_priv * #define _iwl3945_read32(priv, ofs) ioread32((priv)->hw_base + (ofs)) #ifdef CONFIG_IWL3945_DEBUG -static inline u32 __iwl3945_read32(char *f, u32 l, struct iwl3945_priv *priv, u32 ofs) +static inline u32 __iwl3945_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs) { IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l); return _iwl3945_read32(priv, ofs); @@ -85,7 +85,7 @@ static inline u32 __iwl3945_read32(char *f, u32 l, struct iwl3945_priv *priv, u3 #define iwl3945_read32(p, o) _iwl3945_read32(p, o) #endif -static inline int _iwl3945_poll_bit(struct iwl3945_priv *priv, u32 addr, +static inline int _iwl3945_poll_bit(struct iwl_priv *priv, u32 addr, u32 bits, u32 mask, int timeout) { int i = 0; @@ -101,7 +101,7 @@ static inline int _iwl3945_poll_bit(struct iwl3945_priv *priv, u32 addr, } #ifdef CONFIG_IWL3945_DEBUG static inline int __iwl3945_poll_bit(const char *f, u32 l, - struct iwl3945_priv *priv, u32 addr, + struct iwl_priv *priv, u32 addr, u32 bits, u32 mask, int timeout) { int ret = _iwl3945_poll_bit(priv, addr, bits, mask, timeout); @@ -116,13 +116,13 @@ static inline int __iwl3945_poll_bit(const char *f, u32 l, #define iwl3945_poll_bit(p, a, b, m, t) _iwl3945_poll_bit(p, a, b, m, t) #endif -static inline void _iwl3945_set_bit(struct iwl3945_priv *priv, u32 reg, u32 mask) +static inline void _iwl3945_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) { _iwl3945_write32(priv, reg, _iwl3945_read32(priv, reg) | mask); } #ifdef CONFIG_IWL3945_DEBUG static inline void __iwl3945_set_bit(const char *f, u32 l, - struct iwl3945_priv *priv, u32 reg, u32 mask) + struct iwl_priv *priv, u32 reg, u32 mask) { u32 val = _iwl3945_read32(priv, reg) | mask; IWL_DEBUG_IO("set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); @@ -133,13 +133,13 @@ static inline void __iwl3945_set_bit(const char *f, u32 l, #define iwl3945_set_bit(p, r, m) _iwl3945_set_bit(p, r, m) #endif -static inline void _iwl3945_clear_bit(struct iwl3945_priv *priv, u32 reg, u32 mask) +static inline void _iwl3945_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) { _iwl3945_write32(priv, reg, _iwl3945_read32(priv, reg) & ~mask); } #ifdef CONFIG_IWL3945_DEBUG static inline void __iwl3945_clear_bit(const char *f, u32 l, - struct iwl3945_priv *priv, u32 reg, u32 mask) + struct iwl_priv *priv, u32 reg, u32 mask) { u32 val = _iwl3945_read32(priv, reg) & ~mask; IWL_DEBUG_IO("clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); @@ -150,7 +150,7 @@ static inline void __iwl3945_clear_bit(const char *f, u32 l, #define iwl3945_clear_bit(p, r, m) _iwl3945_clear_bit(p, r, m) #endif -static inline int _iwl3945_grab_nic_access(struct iwl3945_priv *priv) +static inline int _iwl3945_grab_nic_access(struct iwl_priv *priv) { int ret; #ifdef CONFIG_IWL3945_DEBUG @@ -176,7 +176,7 @@ static inline int _iwl3945_grab_nic_access(struct iwl3945_priv *priv) #ifdef CONFIG_IWL3945_DEBUG static inline int __iwl3945_grab_nic_access(const char *f, u32 l, - struct iwl3945_priv *priv) + struct iwl_priv *priv) { if (atomic_read(&priv->restrict_refcnt)) IWL_DEBUG_INFO("Grabbing access while already held at " @@ -192,7 +192,7 @@ static inline int __iwl3945_grab_nic_access(const char *f, u32 l, _iwl3945_grab_nic_access(priv) #endif -static inline void _iwl3945_release_nic_access(struct iwl3945_priv *priv) +static inline void _iwl3945_release_nic_access(struct iwl_priv *priv) { #ifdef CONFIG_IWL3945_DEBUG if (atomic_dec_and_test(&priv->restrict_refcnt)) @@ -202,7 +202,7 @@ static inline void _iwl3945_release_nic_access(struct iwl3945_priv *priv) } #ifdef CONFIG_IWL3945_DEBUG static inline void __iwl3945_release_nic_access(const char *f, u32 l, - struct iwl3945_priv *priv) + struct iwl_priv *priv) { if (atomic_read(&priv->restrict_refcnt) <= 0) IWL_ERROR("Release unheld nic access at line %d.\n", l); @@ -217,13 +217,13 @@ static inline void __iwl3945_release_nic_access(const char *f, u32 l, _iwl3945_release_nic_access(priv) #endif -static inline u32 _iwl3945_read_direct32(struct iwl3945_priv *priv, u32 reg) +static inline u32 _iwl3945_read_direct32(struct iwl_priv *priv, u32 reg) { return _iwl3945_read32(priv, reg); } #ifdef CONFIG_IWL3945_DEBUG static inline u32 __iwl3945_read_direct32(const char *f, u32 l, - struct iwl3945_priv *priv, u32 reg) + struct iwl_priv *priv, u32 reg) { u32 value = _iwl3945_read_direct32(priv, reg); if (!atomic_read(&priv->restrict_refcnt)) @@ -238,14 +238,14 @@ static inline u32 __iwl3945_read_direct32(const char *f, u32 l, #define iwl3945_read_direct32 _iwl3945_read_direct32 #endif -static inline void _iwl3945_write_direct32(struct iwl3945_priv *priv, +static inline void _iwl3945_write_direct32(struct iwl_priv *priv, u32 reg, u32 value) { _iwl3945_write32(priv, reg, value); } #ifdef CONFIG_IWL3945_DEBUG static void __iwl3945_write_direct32(u32 line, - struct iwl3945_priv *priv, u32 reg, u32 value) + struct iwl_priv *priv, u32 reg, u32 value) { if (!atomic_read(&priv->restrict_refcnt)) IWL_ERROR("Nic access not held from line %d\n", line); @@ -257,7 +257,7 @@ static void __iwl3945_write_direct32(u32 line, #define iwl3945_write_direct32 _iwl3945_write_direct32 #endif -static inline void iwl3945_write_reg_buf(struct iwl3945_priv *priv, +static inline void iwl3945_write_reg_buf(struct iwl_priv *priv, u32 reg, u32 len, u32 *values) { u32 count = sizeof(u32); @@ -268,7 +268,7 @@ static inline void iwl3945_write_reg_buf(struct iwl3945_priv *priv, } } -static inline int _iwl3945_poll_direct_bit(struct iwl3945_priv *priv, +static inline int _iwl3945_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask, int timeout) { return _iwl3945_poll_bit(priv, addr, mask, mask, timeout); @@ -276,7 +276,7 @@ static inline int _iwl3945_poll_direct_bit(struct iwl3945_priv *priv, #ifdef CONFIG_IWL3945_DEBUG static inline int __iwl3945_poll_direct_bit(const char *f, u32 l, - struct iwl3945_priv *priv, + struct iwl_priv *priv, u32 addr, u32 mask, int timeout) { int ret = _iwl3945_poll_direct_bit(priv, addr, mask, timeout); @@ -295,14 +295,14 @@ static inline int __iwl3945_poll_direct_bit(const char *f, u32 l, #define iwl3945_poll_direct_bit _iwl3945_poll_direct_bit #endif -static inline u32 _iwl3945_read_prph(struct iwl3945_priv *priv, u32 reg) +static inline u32 _iwl3945_read_prph(struct iwl_priv *priv, u32 reg) { _iwl3945_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); rmb(); return _iwl3945_read_direct32(priv, HBUS_TARG_PRPH_RDAT); } #ifdef CONFIG_IWL3945_DEBUG -static inline u32 __iwl3945_read_prph(u32 line, struct iwl3945_priv *priv, u32 reg) +static inline u32 __iwl3945_read_prph(u32 line, struct iwl_priv *priv, u32 reg) { if (!atomic_read(&priv->restrict_refcnt)) IWL_ERROR("Nic access not held from line %d\n", line); @@ -315,7 +315,7 @@ static inline u32 __iwl3945_read_prph(u32 line, struct iwl3945_priv *priv, u32 r #define iwl3945_read_prph _iwl3945_read_prph #endif -static inline void _iwl3945_write_prph(struct iwl3945_priv *priv, +static inline void _iwl3945_write_prph(struct iwl_priv *priv, u32 addr, u32 val) { _iwl3945_write_direct32(priv, HBUS_TARG_PRPH_WADDR, @@ -324,7 +324,7 @@ static inline void _iwl3945_write_prph(struct iwl3945_priv *priv, _iwl3945_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val); } #ifdef CONFIG_IWL3945_DEBUG -static inline void __iwl3945_write_prph(u32 line, struct iwl3945_priv *priv, +static inline void __iwl3945_write_prph(u32 line, struct iwl_priv *priv, u32 addr, u32 val) { if (!atomic_read(&priv->restrict_refcnt)) @@ -341,7 +341,7 @@ static inline void __iwl3945_write_prph(u32 line, struct iwl3945_priv *priv, #define _iwl3945_set_bits_prph(priv, reg, mask) \ _iwl3945_write_prph(priv, reg, (_iwl3945_read_prph(priv, reg) | mask)) #ifdef CONFIG_IWL3945_DEBUG -static inline void __iwl3945_set_bits_prph(u32 line, struct iwl3945_priv *priv, +static inline void __iwl3945_set_bits_prph(u32 line, struct iwl_priv *priv, u32 reg, u32 mask) { if (!atomic_read(&priv->restrict_refcnt)) @@ -360,7 +360,7 @@ static inline void __iwl3945_set_bits_prph(u32 line, struct iwl3945_priv *priv, #ifdef CONFIG_IWL3945_DEBUG static inline void __iwl3945_set_bits_mask_prph(u32 line, - struct iwl3945_priv *priv, u32 reg, u32 bits, u32 mask) + struct iwl_priv *priv, u32 reg, u32 bits, u32 mask) { if (!atomic_read(&priv->restrict_refcnt)) IWL_ERROR("Nic access not held from line %d\n", line); @@ -372,28 +372,28 @@ static inline void __iwl3945_set_bits_mask_prph(u32 line, #define iwl3945_set_bits_mask_prph _iwl3945_set_bits_mask_prph #endif -static inline void iwl3945_clear_bits_prph(struct iwl3945_priv +static inline void iwl3945_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) { u32 val = _iwl3945_read_prph(priv, reg); _iwl3945_write_prph(priv, reg, (val & ~mask)); } -static inline u32 iwl3945_read_targ_mem(struct iwl3945_priv *priv, u32 addr) +static inline u32 iwl3945_read_targ_mem(struct iwl_priv *priv, u32 addr) { iwl3945_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr); rmb(); return iwl3945_read_direct32(priv, HBUS_TARG_MEM_RDAT); } -static inline void iwl3945_write_targ_mem(struct iwl3945_priv *priv, u32 addr, u32 val) +static inline void iwl3945_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val) { iwl3945_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); wmb(); iwl3945_write_direct32(priv, HBUS_TARG_MEM_WDAT, val); } -static inline void iwl3945_write_targ_mem_buf(struct iwl3945_priv *priv, u32 addr, +static inline void iwl3945_write_targ_mem_buf(struct iwl_priv *priv, u32 addr, u32 len, u32 *values) { iwl3945_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index 1ef21b6b3c4..165da9e314d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -67,7 +67,7 @@ static const struct { #define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /*Exclude Solid on*/ #define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1) -static int iwl3945_led_cmd_callback(struct iwl3945_priv *priv, +static int iwl3945_led_cmd_callback(struct iwl_priv *priv, struct iwl3945_cmd *cmd, struct sk_buff *skb) { @@ -80,7 +80,7 @@ static inline int iwl3945_brightness_to_idx(enum led_brightness brightness) } /* Send led command */ -static int iwl_send_led_cmd(struct iwl3945_priv *priv, +static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) { struct iwl3945_host_cmd cmd = { @@ -97,7 +97,7 @@ static int iwl_send_led_cmd(struct iwl3945_priv *priv, /* Set led on command */ -static int iwl3945_led_pattern(struct iwl3945_priv *priv, int led_id, +static int iwl3945_led_pattern(struct iwl_priv *priv, int led_id, unsigned int idx) { struct iwl_led_cmd led_cmd = { @@ -115,7 +115,7 @@ static int iwl3945_led_pattern(struct iwl3945_priv *priv, int led_id, /* Set led on command */ -static int iwl3945_led_on(struct iwl3945_priv *priv, int led_id) +static int iwl3945_led_on(struct iwl_priv *priv, int led_id) { struct iwl_led_cmd led_cmd = { .id = led_id, @@ -127,7 +127,7 @@ static int iwl3945_led_on(struct iwl3945_priv *priv, int led_id) } /* Set led off command */ -static int iwl3945_led_off(struct iwl3945_priv *priv, int led_id) +static int iwl3945_led_off(struct iwl_priv *priv, int led_id) { struct iwl_led_cmd led_cmd = { .id = led_id, @@ -142,7 +142,7 @@ static int iwl3945_led_off(struct iwl3945_priv *priv, int led_id) /* * brightness call back function for Tx/Rx LED */ -static int iwl3945_led_associated(struct iwl3945_priv *priv, int led_id) +static int iwl3945_led_associated(struct iwl_priv *priv, int led_id) { if (test_bit(STATUS_EXIT_PENDING, &priv->status) || !test_bit(STATUS_READY, &priv->status)) @@ -163,7 +163,7 @@ static void iwl3945_led_brightness_set(struct led_classdev *led_cdev, { struct iwl3945_led *led = container_of(led_cdev, struct iwl3945_led, led_dev); - struct iwl3945_priv *priv = led->priv; + struct iwl_priv *priv = led->priv; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -199,7 +199,7 @@ static void iwl3945_led_brightness_set(struct led_classdev *led_cdev, /* * Register led class with the system */ -static int iwl3945_led_register_led(struct iwl3945_priv *priv, +static int iwl3945_led_register_led(struct iwl_priv *priv, struct iwl3945_led *led, enum led_type type, u8 set_led, char *trigger) @@ -231,7 +231,7 @@ static int iwl3945_led_register_led(struct iwl3945_priv *priv, /* * calculate blink rate according to last 2 sec Tx/Rx activities */ -static inline u8 get_blink_rate(struct iwl3945_priv *priv) +static inline u8 get_blink_rate(struct iwl_priv *priv) { int index; u64 current_tpt = priv->rxtxpackets; @@ -250,7 +250,7 @@ static inline u8 get_blink_rate(struct iwl3945_priv *priv) return index; } -static inline int is_rf_kill(struct iwl3945_priv *priv) +static inline int is_rf_kill(struct iwl_priv *priv) { return test_bit(STATUS_RF_KILL_HW, &priv->status) || test_bit(STATUS_RF_KILL_SW, &priv->status); @@ -261,7 +261,7 @@ static inline int is_rf_kill(struct iwl3945_priv *priv) * happen very frequent we postpone led command to be called from * REPLY handler so we know ucode is up */ -void iwl3945_led_background(struct iwl3945_priv *priv) +void iwl3945_led_background(struct iwl_priv *priv) { u8 blink_idx; @@ -301,7 +301,7 @@ void iwl3945_led_background(struct iwl3945_priv *priv) /* Register all led handler */ -int iwl3945_led_register(struct iwl3945_priv *priv) +int iwl3945_led_register(struct iwl_priv *priv) { char *trigger; int ret; @@ -399,7 +399,7 @@ static void iwl3945_led_unregister_led(struct iwl3945_led *led, u8 set_led) } /* Unregister all led handlers */ -void iwl3945_led_unregister(struct iwl3945_priv *priv) +void iwl3945_led_unregister(struct iwl_priv *priv) { iwl3945_led_unregister_led(&priv->led39[IWL_LED_TRG_ASSOC], 0); iwl3945_led_unregister_led(&priv->led39[IWL_LED_TRG_RX], 0); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.h b/drivers/net/wireless/iwlwifi/iwl-3945-led.h index b697c890f62..859bb9b1e1b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.h @@ -27,34 +27,34 @@ #ifndef IWL3945_LEDS_H #define IWL3945_LEDS_H -struct iwl3945_priv; +struct iwl_priv; #ifdef CONFIG_IWL3945_LEDS #include "iwl-led.h" struct iwl3945_led { - struct iwl3945_priv *priv; + struct iwl_priv *priv; struct led_classdev led_dev; char name[32]; - int (*led_on) (struct iwl3945_priv *priv, int led_id); - int (*led_off) (struct iwl3945_priv *priv, int led_id); - int (*led_pattern) (struct iwl3945_priv *priv, int led_id, + int (*led_on) (struct iwl_priv *priv, int led_id); + int (*led_off) (struct iwl_priv *priv, int led_id); + int (*led_pattern) (struct iwl_priv *priv, int led_id, unsigned int idx); enum led_type type; unsigned int registered; }; -extern int iwl3945_led_register(struct iwl3945_priv *priv); -extern void iwl3945_led_unregister(struct iwl3945_priv *priv); -extern void iwl3945_led_background(struct iwl3945_priv *priv); +extern int iwl3945_led_register(struct iwl_priv *priv); +extern void iwl3945_led_unregister(struct iwl_priv *priv); +extern void iwl3945_led_background(struct iwl_priv *priv); #else -static inline int iwl3945_led_register(struct iwl3945_priv *priv) { return 0; } -static inline void iwl3945_led_unregister(struct iwl3945_priv *priv) {} -static inline void iwl3945_led_background(struct iwl3945_priv *priv) {} +static inline int iwl3945_led_register(struct iwl_priv *priv) { return 0; } +static inline void iwl3945_led_unregister(struct iwl_priv *priv) {} +static inline void iwl3945_led_background(struct iwl_priv *priv) {} #endif /* CONFIG_IWL3945_LEDS */ #endif /* IWL3945_LEDS_H */ diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index daaac3196ce..52901ac74e5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -52,7 +52,7 @@ struct iwl3945_rate_scale_data { struct iwl3945_rs_sta { spinlock_t lock; - struct iwl3945_priv *priv; + struct iwl_priv *priv; s32 *expected_tpt; unsigned long last_partial_flush; unsigned long last_flush; @@ -183,7 +183,7 @@ static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta) int unflushed = 0; int i; unsigned long flags; - struct iwl3945_priv *priv = rs_sta->priv; + struct iwl_priv *priv = rs_sta->priv; /* * For each rate, if we have collected data on that rate @@ -216,7 +216,7 @@ static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta) static void iwl3945_bg_rate_scale_flush(unsigned long data) { struct iwl3945_rs_sta *rs_sta = (void *)data; - struct iwl3945_priv *priv = rs_sta->priv; + struct iwl_priv *priv = rs_sta->priv; int unflushed = 0; unsigned long flags; u32 packet_count, duration, pps; @@ -290,7 +290,7 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, { unsigned long flags; s32 fail_count; - struct iwl3945_priv *priv = rs_sta->priv; + struct iwl_priv *priv = rs_sta->priv; if (!retries) { IWL_DEBUG_RATE("leave: retries == 0 -- should be at least 1\n"); @@ -344,7 +344,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, void *priv_sta) { struct iwl3945_rs_sta *rs_sta = priv_sta; - struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r; + struct iwl_priv *priv = (struct iwl_priv *)priv_r; int i; IWL_DEBUG_RATE("enter\n"); @@ -388,7 +388,7 @@ static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp) { struct iwl3945_rs_sta *rs_sta; struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; - struct iwl3945_priv *priv = iwl_priv; + struct iwl_priv *priv = iwl_priv; int i; /* @@ -438,7 +438,7 @@ static void rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta, { struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; struct iwl3945_rs_sta *rs_sta = priv_sta; - struct iwl3945_priv *priv = rs_sta->priv; + struct iwl_priv *priv = rs_sta->priv; psta->rs_sta = NULL; @@ -452,7 +452,7 @@ static void rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta, /** * rs_tx_status - Update rate control values based on Tx results * - * NOTE: Uses iwl3945_priv->retry_rate for the # of retries attempted by + * NOTE: Uses iwl_priv->retry_rate for the # of retries attempted by * the hardware for each rate. */ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband, @@ -462,7 +462,7 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband s8 retries = 0, current_count; int scale_rate_index, first_index, last_index; unsigned long flags; - struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate; + struct iwl_priv *priv = (struct iwl_priv *)priv_rate; struct iwl3945_rs_sta *rs_sta = priv_sta; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); @@ -556,7 +556,7 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, { u8 high = IWL_RATE_INVALID; u8 low = IWL_RATE_INVALID; - struct iwl3945_priv *priv = rs_sta->priv; + struct iwl_priv *priv = rs_sta->priv; /* 802.11A walks to the next literal adjacent rate in * the rate table */ @@ -651,7 +651,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; u16 fc; u16 rate_mask = 0; - struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r; + struct iwl_priv *priv = (struct iwl_priv *)priv_r; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); IWL_DEBUG_RATE("enter\n"); @@ -890,7 +890,7 @@ static struct rate_control_ops rs_ops = { void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) { - struct iwl3945_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; s32 rssi = 0; unsigned long flags; struct iwl3945_rs_sta *rs_sta; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index f480c437cd6..50e729ed018 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -93,7 +93,7 @@ const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945] = { * Use for only special debugging. This function is just a placeholder as-is, * you'll need to provide the special bits! ... * ... and set IWL_EVT_DISABLE to 1. */ -void iwl3945_disable_events(struct iwl3945_priv *priv) +void iwl3945_disable_events(struct iwl_priv *priv) { int ret; int i; @@ -206,7 +206,7 @@ static int iwl3945_hwrate_to_plcp_idx(u8 plcp) * IWL_ANTENNA_MAIN - Force MAIN antenna * IWL_ANTENNA_AUX - Force AUX antenna */ -__le32 iwl3945_get_antenna_flags(const struct iwl3945_priv *priv) +__le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv) { switch (priv->antenna) { case IWL_ANTENNA_DIVERSITY: @@ -268,7 +268,7 @@ static inline const char *iwl3945_get_tx_fail_reason(u32 status) * for A and B mode we need to overright prev * value */ -int iwl3945_rs_next_rate(struct iwl3945_priv *priv, int rate) +int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate) { int next_rate = iwl3945_get_prev_ieee_rate(rate); @@ -302,7 +302,7 @@ int iwl3945_rs_next_rate(struct iwl3945_priv *priv, int rate) * need to be reclaimed. As result, some free space forms. If there is * enough free space (> low mark), wake the stack that feeds us. */ -static void iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv, +static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) { struct iwl3945_tx_queue *txq = &priv->txq39[txq_id]; @@ -329,7 +329,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv, /** * iwl3945_rx_reply_tx - Handle Tx response */ -static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, +static void iwl3945_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; @@ -389,7 +389,7 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, * *****************************************************************************/ -void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl_rx_mem_buffer *rxb) +void iwl3945_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; IWL_DEBUG_RX("Statistics notification received (%d vs %d).\n", @@ -417,7 +417,7 @@ void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl_rx_mem_buffe * including selective frame dumps. * group100 parameter selects whether to show 1 out of 100 good frames. */ -static void iwl3945_dbg_report_frame(struct iwl3945_priv *priv, +static void iwl3945_dbg_report_frame(struct iwl_priv *priv, struct iwl_rx_packet *pkt, struct ieee80211_hdr *header, int group100) { @@ -545,7 +545,7 @@ static void iwl3945_dbg_report_frame(struct iwl3945_priv *priv, iwl_print_hex_dump(priv, IWL_DL_RX, data, length); } #else -static inline void iwl3945_dbg_report_frame(struct iwl3945_priv *priv, +static inline void iwl3945_dbg_report_frame(struct iwl_priv *priv, struct iwl_rx_packet *pkt, struct ieee80211_hdr *header, int group100) { @@ -553,7 +553,7 @@ static inline void iwl3945_dbg_report_frame(struct iwl3945_priv *priv, #endif /* This is necessary only for a number of statistics, see the caller. */ -static int iwl3945_is_network_packet(struct iwl3945_priv *priv, +static int iwl3945_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *header) { /* Filter incoming packets to determine if they are targeted toward @@ -570,7 +570,7 @@ static int iwl3945_is_network_packet(struct iwl3945_priv *priv, } } -static void iwl3945_pass_packet_to_mac80211(struct iwl3945_priv *priv, +static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, struct ieee80211_rx_status *stats) { @@ -613,7 +613,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl3945_priv *priv, #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) -static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, +static void iwl3945_rx_reply_rx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct ieee80211_hdr *header; @@ -723,7 +723,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status); } -int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl3945_priv *priv, void *ptr, +int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr, dma_addr_t addr, u16 len) { int count; @@ -755,7 +755,7 @@ int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl3945_priv *priv, void *ptr, * * Does NOT advance any indexes */ -int iwl3945_hw_txq_free_tfd(struct iwl3945_priv *priv, struct iwl3945_tx_queue *txq) +int iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl3945_tx_queue *txq) { struct iwl3945_tfd_frame *bd_tmp = (struct iwl3945_tfd_frame *)&txq->bd[0]; struct iwl3945_tfd_frame *bd = &bd_tmp[txq->q.read_ptr]; @@ -793,7 +793,7 @@ int iwl3945_hw_txq_free_tfd(struct iwl3945_priv *priv, struct iwl3945_tx_queue * return 0; } -u8 iwl3945_hw_find_station(struct iwl3945_priv *priv, const u8 *addr) +u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *addr) { int i, start = IWL_AP_ID; int ret = IWL_INVALID_STATION; @@ -826,7 +826,7 @@ u8 iwl3945_hw_find_station(struct iwl3945_priv *priv, const u8 *addr) * iwl3945_hw_build_tx_cmd_rate - Add rate portion to TX_CMD: * */ -void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv, +void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, struct iwl3945_cmd *cmd, struct ieee80211_tx_info *info, struct ieee80211_hdr *hdr, int sta_id, int tx_id) @@ -896,7 +896,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv, cmd->cmd.tx.supp_rates[1], cmd->cmd.tx.supp_rates[0]); } -u8 iwl3945_sync_sta(struct iwl3945_priv *priv, int sta_id, u16 tx_rate, u8 flags) +u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags) { unsigned long flags_spin; struct iwl3945_station_entry *station; @@ -919,7 +919,7 @@ u8 iwl3945_sync_sta(struct iwl3945_priv *priv, int sta_id, u16 tx_rate, u8 flags return sta_id; } -static int iwl3945_nic_set_pwr_src(struct iwl3945_priv *priv, int pwr_max) +static int iwl3945_nic_set_pwr_src(struct iwl_priv *priv, int pwr_max) { int rc; unsigned long flags; @@ -961,7 +961,7 @@ static int iwl3945_nic_set_pwr_src(struct iwl3945_priv *priv, int pwr_max) return rc; } -static int iwl3945_rx_init(struct iwl3945_priv *priv, struct iwl_rx_queue *rxq) +static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) { int rc; unsigned long flags; @@ -997,7 +997,7 @@ static int iwl3945_rx_init(struct iwl3945_priv *priv, struct iwl_rx_queue *rxq) return 0; } -static int iwl3945_tx_reset(struct iwl3945_priv *priv) +static int iwl3945_tx_reset(struct iwl_priv *priv) { int rc; unsigned long flags; @@ -1046,7 +1046,7 @@ static int iwl3945_tx_reset(struct iwl3945_priv *priv) * * Destroys all DMA structures and initialize them again */ -static int iwl3945_txq_ctx_reset(struct iwl3945_priv *priv) +static int iwl3945_txq_ctx_reset(struct iwl_priv *priv) { int rc; int txq_id, slots_num; @@ -1077,7 +1077,7 @@ static int iwl3945_txq_ctx_reset(struct iwl3945_priv *priv) return rc; } -int iwl3945_hw_nic_init(struct iwl3945_priv *priv) +int iwl3945_hw_nic_init(struct iwl_priv *priv) { u8 rev_id; int rc; @@ -1218,7 +1218,7 @@ int iwl3945_hw_nic_init(struct iwl3945_priv *priv) * * Destroy all TX DMA queues and structures */ -void iwl3945_hw_txq_ctx_free(struct iwl3945_priv *priv) +void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv) { int txq_id; @@ -1227,7 +1227,7 @@ void iwl3945_hw_txq_ctx_free(struct iwl3945_priv *priv) iwl3945_tx_queue_free(priv, &priv->txq39[txq_id]); } -void iwl3945_hw_txq_ctx_stop(struct iwl3945_priv *priv) +void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) { int txq_id; unsigned long flags; @@ -1256,7 +1256,7 @@ void iwl3945_hw_txq_ctx_stop(struct iwl3945_priv *priv) iwl3945_hw_txq_ctx_free(priv); } -int iwl3945_hw_nic_stop_master(struct iwl3945_priv *priv) +int iwl3945_hw_nic_stop_master(struct iwl_priv *priv) { int rc = 0; u32 reg_val; @@ -1288,7 +1288,7 @@ int iwl3945_hw_nic_stop_master(struct iwl3945_priv *priv) return rc; } -int iwl3945_hw_nic_reset(struct iwl3945_priv *priv) +int iwl3945_hw_nic_reset(struct iwl_priv *priv) { int rc; unsigned long flags; @@ -1356,7 +1356,7 @@ static inline int iwl3945_hw_reg_temp_out_of_range(int temperature) return ((temperature < -260) || (temperature > 25)) ? 1 : 0; } -int iwl3945_hw_get_temperature(struct iwl3945_priv *priv) +int iwl3945_hw_get_temperature(struct iwl_priv *priv) { return iwl3945_read32(priv, CSR_UCODE_DRV_GP2); } @@ -1365,7 +1365,7 @@ int iwl3945_hw_get_temperature(struct iwl3945_priv *priv) * iwl3945_hw_reg_txpower_get_temperature * get the current temperature by reading from NIC */ -static int iwl3945_hw_reg_txpower_get_temperature(struct iwl3945_priv *priv) +static int iwl3945_hw_reg_txpower_get_temperature(struct iwl_priv *priv) { int temperature; @@ -1401,7 +1401,7 @@ static int iwl3945_hw_reg_txpower_get_temperature(struct iwl3945_priv *priv) * records new temperature in tx_mgr->temperature. * replaces tx_mgr->last_temperature *only* if calib needed * (assumes caller will actually do the calibration!). */ -static int is_temp_calib_needed(struct iwl3945_priv *priv) +static int is_temp_calib_needed(struct iwl_priv *priv) { int temp_diff; @@ -1616,7 +1616,7 @@ static inline u8 iwl3945_hw_reg_fix_power_index(int index) * Set (in our channel info database) the direct scan Tx power for 1 Mbit (CCK) * or 6 Mbit (OFDM) rates. */ -static void iwl3945_hw_reg_set_scan_power(struct iwl3945_priv *priv, u32 scan_tbl_index, +static void iwl3945_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index, s32 rate_index, const s8 *clip_pwrs, struct iwl_channel_info *ch_info, int band_index) @@ -1672,7 +1672,7 @@ static void iwl3945_hw_reg_set_scan_power(struct iwl3945_priv *priv, u32 scan_tb * Configures power settings for all rates for the current channel, * using values from channel info struct, and send to NIC */ -int iwl3945_hw_reg_send_txpower(struct iwl3945_priv *priv) +int iwl3945_hw_reg_send_txpower(struct iwl_priv *priv) { int rate_idx, i; const struct iwl_channel_info *ch_info = NULL; @@ -1747,7 +1747,7 @@ int iwl3945_hw_reg_send_txpower(struct iwl3945_priv *priv) * properly fill out the scan powers, and actual h/w gain settings, * and send changes to NIC */ -static int iwl3945_hw_reg_set_new_power(struct iwl3945_priv *priv, +static int iwl3945_hw_reg_set_new_power(struct iwl_priv *priv, struct iwl_channel_info *ch_info) { struct iwl3945_channel_power_info *power_info; @@ -1838,7 +1838,7 @@ static int iwl3945_hw_reg_get_ch_txpower_limit(struct iwl_channel_info *ch_info) * * If RxOn is "associated", this sends the new Txpower to NIC! */ -static int iwl3945_hw_reg_comp_txpower_temp(struct iwl3945_priv *priv) +static int iwl3945_hw_reg_comp_txpower_temp(struct iwl_priv *priv) { struct iwl_channel_info *ch_info = NULL; int delta_index; @@ -1899,7 +1899,7 @@ static int iwl3945_hw_reg_comp_txpower_temp(struct iwl3945_priv *priv) return iwl3945_hw_reg_send_txpower(priv); } -int iwl3945_hw_reg_set_txpower(struct iwl3945_priv *priv, s8 power) +int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power) { struct iwl_channel_info *ch_info; s8 max_power; @@ -1942,7 +1942,7 @@ int iwl3945_hw_reg_set_txpower(struct iwl3945_priv *priv, s8 power) } /* will add 3945 channel switch cmd handling later */ -int iwl3945_hw_channel_switch(struct iwl3945_priv *priv, u16 channel) +int iwl3945_hw_channel_switch(struct iwl_priv *priv, u16 channel) { return 0; } @@ -1957,7 +1957,7 @@ int iwl3945_hw_channel_switch(struct iwl3945_priv *priv, u16 channel) * -- send new set of gain settings to NIC * NOTE: This should continue working, even when we're not associated, * so we can keep our internal table of scan powers current. */ -void iwl3945_reg_txpower_periodic(struct iwl3945_priv *priv) +void iwl3945_reg_txpower_periodic(struct iwl_priv *priv) { /* This will kick in the "brute force" * iwl3945_hw_reg_comp_txpower_temp() below */ @@ -1976,7 +1976,7 @@ void iwl3945_reg_txpower_periodic(struct iwl3945_priv *priv) static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work) { - struct iwl3945_priv *priv = container_of(work, struct iwl3945_priv, + struct iwl_priv *priv = container_of(work, struct iwl_priv, thermal_periodic.work); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) @@ -1998,7 +1998,7 @@ static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work) * on A-band, EEPROM's "group frequency" entries represent the top * channel in each group 1-4. Group 5 All B/G channels are in group 0. */ -static u16 iwl3945_hw_reg_get_ch_grp_index(struct iwl3945_priv *priv, +static u16 iwl3945_hw_reg_get_ch_grp_index(struct iwl_priv *priv, const struct iwl_channel_info *ch_info) { struct iwl3945_eeprom_txpower_group *ch_grp = &priv->eeprom39.groups[0]; @@ -2032,7 +2032,7 @@ static u16 iwl3945_hw_reg_get_ch_grp_index(struct iwl3945_priv *priv, * Interpolate to get nominal (i.e. at factory calibration temperature) index * into radio/DSP gain settings table for requested power. */ -static int iwl3945_hw_reg_get_matched_power_index(struct iwl3945_priv *priv, +static int iwl3945_hw_reg_get_matched_power_index(struct iwl_priv *priv, s8 requested_power, s32 setting_index, s32 *new_index) { @@ -2080,7 +2080,7 @@ static int iwl3945_hw_reg_get_matched_power_index(struct iwl3945_priv *priv, return 0; } -static void iwl3945_hw_reg_init_channel_groups(struct iwl3945_priv *priv) +static void iwl3945_hw_reg_init_channel_groups(struct iwl_priv *priv) { u32 i; s32 rate_index; @@ -2160,7 +2160,7 @@ static void iwl3945_hw_reg_init_channel_groups(struct iwl3945_priv *priv) * * This does *not* write values to NIC, just sets up our internal table. */ -int iwl3945_txpower_set_from_eeprom(struct iwl3945_priv *priv) +int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv) { struct iwl_channel_info *ch_info = NULL; struct iwl3945_channel_power_info *pwr_info; @@ -2284,7 +2284,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl3945_priv *priv) return 0; } -int iwl3945_hw_rxq_stop(struct iwl3945_priv *priv) +int iwl3945_hw_rxq_stop(struct iwl_priv *priv) { int rc; unsigned long flags; @@ -2308,7 +2308,7 @@ int iwl3945_hw_rxq_stop(struct iwl3945_priv *priv) return 0; } -int iwl3945_hw_tx_queue_init(struct iwl3945_priv *priv, struct iwl3945_tx_queue *txq) +int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl3945_tx_queue *txq) { int rc; unsigned long flags; @@ -2342,7 +2342,7 @@ int iwl3945_hw_tx_queue_init(struct iwl3945_priv *priv, struct iwl3945_tx_queue return 0; } -int iwl3945_hw_get_rx_read(struct iwl3945_priv *priv) +int iwl3945_hw_get_rx_read(struct iwl_priv *priv) { struct iwl3945_shared *shared_data = priv->shared_virt; @@ -2352,7 +2352,7 @@ int iwl3945_hw_get_rx_read(struct iwl3945_priv *priv) /** * iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table */ -int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv) +int iwl3945_init_hw_rate_table(struct iwl_priv *priv) { int rc, i, index, prev_index; struct iwl3945_rate_scaling_cmd rate_cmd = { @@ -2429,7 +2429,7 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv) } /* Called when initializing driver */ -int iwl3945_hw_set_hw_params(struct iwl3945_priv *priv) +int iwl3945_hw_set_hw_params(struct iwl_priv *priv) { memset((void *)&priv->hw_params, 0, sizeof(struct iwl_hw_params)); @@ -2456,7 +2456,7 @@ int iwl3945_hw_set_hw_params(struct iwl3945_priv *priv) return 0; } -unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv, +unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv, struct iwl3945_frame *frame, u8 rate) { struct iwl3945_tx_beacon_cmd *tx_beacon_cmd; @@ -2489,19 +2489,19 @@ unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv, return sizeof(struct iwl3945_tx_beacon_cmd) + frame_size; } -void iwl3945_hw_rx_handler_setup(struct iwl3945_priv *priv) +void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv) { priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx; priv->rx_handlers[REPLY_3945_RX] = iwl3945_rx_reply_rx; } -void iwl3945_hw_setup_deferred_work(struct iwl3945_priv *priv) +void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv) { INIT_DELAYED_WORK(&priv->thermal_periodic, iwl3945_bg_reg_txpower_periodic); } -void iwl3945_hw_cancel_deferred_work(struct iwl3945_priv *priv) +void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv) { cancel_delayed_work(&priv->thermal_periodic); } diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 788cd9cc4b1..098ac768ee2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -148,13 +148,13 @@ struct iwl3945_frame { #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) struct iwl3945_cmd; -struct iwl3945_priv; +struct iwl_priv; struct iwl3945_cmd_meta { struct iwl3945_cmd_meta *source; union { struct sk_buff *skb; - int (*callback)(struct iwl3945_priv *priv, + int (*callback)(struct iwl_priv *priv, struct iwl3945_cmd *cmd, struct sk_buff *skb); } __attribute__ ((packed)) u; @@ -270,31 +270,31 @@ struct iwl3945_ibss_seq { * *****************************************************************************/ struct iwl3945_addsta_cmd; -extern int iwl3945_send_add_station(struct iwl3945_priv *priv, +extern int iwl3945_send_add_station(struct iwl_priv *priv, struct iwl3945_addsta_cmd *sta, u8 flags); -extern u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *bssid, +extern u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *bssid, int is_ap, u8 flags); -extern int iwl3945_power_init_handle(struct iwl3945_priv *priv); -extern int iwl3945_eeprom_init(struct iwl3945_priv *priv); -extern int iwl3945_rx_queue_alloc(struct iwl3945_priv *priv); -extern void iwl3945_rx_queue_reset(struct iwl3945_priv *priv, +extern int iwl3945_power_init_handle(struct iwl_priv *priv); +extern int iwl3945_eeprom_init(struct iwl_priv *priv); +extern int iwl3945_rx_queue_alloc(struct iwl_priv *priv); +extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); extern int iwl3945_calc_db_from_ratio(int sig_ratio); extern int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm); -extern int iwl3945_tx_queue_init(struct iwl3945_priv *priv, +extern int iwl3945_tx_queue_init(struct iwl_priv *priv, struct iwl3945_tx_queue *txq, int count, u32 id); extern void iwl3945_rx_replenish(void *data); -extern void iwl3945_tx_queue_free(struct iwl3945_priv *priv, struct iwl3945_tx_queue *txq); -extern int iwl3945_send_cmd_pdu(struct iwl3945_priv *priv, u8 id, u16 len, +extern void iwl3945_tx_queue_free(struct iwl_priv *priv, struct iwl3945_tx_queue *txq); +extern int iwl3945_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data); -extern int __must_check iwl3945_send_cmd(struct iwl3945_priv *priv, +extern int __must_check iwl3945_send_cmd(struct iwl_priv *priv, struct iwl3945_host_cmd *cmd); -extern unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv, +extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, struct ieee80211_hdr *hdr,int left); -extern int iwl3945_rx_queue_update_write_ptr(struct iwl3945_priv *priv, +extern int iwl3945_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q); -extern int iwl3945_send_statistics_request(struct iwl3945_priv *priv); -extern void iwl3945_set_decrypted_flag(struct iwl3945_priv *priv, struct sk_buff *skb, +extern int iwl3945_send_statistics_request(struct iwl_priv *priv); +extern void iwl3945_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb, u32 decrypt_res, struct ieee80211_rx_status *stats); @@ -302,7 +302,7 @@ extern void iwl3945_set_decrypted_flag(struct iwl3945_priv *priv, struct sk_buff * Currently used by iwl-3945-rs... look at restructuring so that it doesn't * call this... todo... fix that. */ -extern u8 iwl3945_sync_station(struct iwl3945_priv *priv, int sta_id, +extern u8 iwl3945_sync_station(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags); /****************************************************************************** @@ -321,36 +321,36 @@ extern u8 iwl3945_sync_station(struct iwl3945_priv *priv, int sta_id, * iwl3945_mac_ <-- mac80211 callback * ****************************************************************************/ -extern void iwl3945_hw_rx_handler_setup(struct iwl3945_priv *priv); -extern void iwl3945_hw_setup_deferred_work(struct iwl3945_priv *priv); -extern void iwl3945_hw_cancel_deferred_work(struct iwl3945_priv *priv); -extern int iwl3945_hw_rxq_stop(struct iwl3945_priv *priv); -extern int iwl3945_hw_set_hw_params(struct iwl3945_priv *priv); -extern int iwl3945_hw_nic_init(struct iwl3945_priv *priv); -extern int iwl3945_hw_nic_stop_master(struct iwl3945_priv *priv); -extern void iwl3945_hw_txq_ctx_free(struct iwl3945_priv *priv); -extern void iwl3945_hw_txq_ctx_stop(struct iwl3945_priv *priv); -extern int iwl3945_hw_nic_reset(struct iwl3945_priv *priv); -extern int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl3945_priv *priv, void *tfd, +extern void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv); +extern void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv); +extern void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv); +extern int iwl3945_hw_rxq_stop(struct iwl_priv *priv); +extern int iwl3945_hw_set_hw_params(struct iwl_priv *priv); +extern int iwl3945_hw_nic_init(struct iwl_priv *priv); +extern int iwl3945_hw_nic_stop_master(struct iwl_priv *priv); +extern void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv); +extern void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv); +extern int iwl3945_hw_nic_reset(struct iwl_priv *priv); +extern int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *tfd, dma_addr_t addr, u16 len); -extern int iwl3945_hw_txq_free_tfd(struct iwl3945_priv *priv, struct iwl3945_tx_queue *txq); -extern int iwl3945_hw_get_temperature(struct iwl3945_priv *priv); -extern int iwl3945_hw_tx_queue_init(struct iwl3945_priv *priv, +extern int iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl3945_tx_queue *txq); +extern int iwl3945_hw_get_temperature(struct iwl_priv *priv); +extern int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl3945_tx_queue *txq); -extern unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv, +extern unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv, struct iwl3945_frame *frame, u8 rate); -extern int iwl3945_hw_get_rx_read(struct iwl3945_priv *priv); -extern void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv, +extern int iwl3945_hw_get_rx_read(struct iwl_priv *priv); +extern void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, struct iwl3945_cmd *cmd, struct ieee80211_tx_info *info, struct ieee80211_hdr *hdr, int sta_id, int tx_id); -extern int iwl3945_hw_reg_send_txpower(struct iwl3945_priv *priv); -extern int iwl3945_hw_reg_set_txpower(struct iwl3945_priv *priv, s8 power); -extern void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, +extern int iwl3945_hw_reg_send_txpower(struct iwl_priv *priv); +extern int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power); +extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); -extern void iwl3945_disable_events(struct iwl3945_priv *priv); -extern int iwl4965_get_temperature(const struct iwl3945_priv *priv); +extern void iwl3945_disable_events(struct iwl_priv *priv); +extern int iwl4965_get_temperature(const struct iwl_priv *priv); /** * iwl3945_hw_find_station - Find station id for a given BSSID @@ -360,262 +360,43 @@ extern int iwl4965_get_temperature(const struct iwl3945_priv *priv); * not yet been merged into a single common layer for managing the * station tables. */ -extern u8 iwl3945_hw_find_station(struct iwl3945_priv *priv, const u8 *bssid); +extern u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *bssid); -extern int iwl3945_hw_channel_switch(struct iwl3945_priv *priv, u16 channel); +extern int iwl3945_hw_channel_switch(struct iwl_priv *priv, u16 channel); /* * Forward declare iwl-3945.c functions for iwl-base.c */ -extern __le32 iwl3945_get_antenna_flags(const struct iwl3945_priv *priv); -extern int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv); -extern void iwl3945_reg_txpower_periodic(struct iwl3945_priv *priv); -extern int iwl3945_txpower_set_from_eeprom(struct iwl3945_priv *priv); -extern u8 iwl3945_sync_sta(struct iwl3945_priv *priv, int sta_id, +extern __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv); +extern int iwl3945_init_hw_rate_table(struct iwl_priv *priv); +extern void iwl3945_reg_txpower_periodic(struct iwl_priv *priv); +extern int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv); +extern u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags); #ifdef CONFIG_IWL3945_RFKILL -struct iwl3945_priv; +struct iwl_priv; -void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv); -void iwl3945_rfkill_unregister(struct iwl3945_priv *priv); -int iwl3945_rfkill_init(struct iwl3945_priv *priv); +void iwl3945_rfkill_set_hw_state(struct iwl_priv *priv); +void iwl3945_rfkill_unregister(struct iwl_priv *priv); +int iwl3945_rfkill_init(struct iwl_priv *priv); #else -static inline void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv) {} -static inline void iwl3945_rfkill_unregister(struct iwl3945_priv *priv) {} -static inline int iwl3945_rfkill_init(struct iwl3945_priv *priv) { return 0; } +static inline void iwl3945_rfkill_set_hw_state(struct iwl_priv *priv) {} +static inline void iwl3945_rfkill_unregister(struct iwl_priv *priv) {} +static inline int iwl3945_rfkill_init(struct iwl_priv *priv) { return 0; } #endif - -struct iwl3945_priv { - - /* ieee device used by generic ieee processing code */ - struct ieee80211_hw *hw; - struct ieee80211_channel *ieee_channels; - struct ieee80211_rate *ieee_rates; - struct iwl_cfg *cfg; /* device configuration */ - - /* temporary frame storage list */ - struct list_head free_frames; - int frames_count; - - enum ieee80211_band band; - int alloc_rxb_skb; - - void (*rx_handlers[REPLY_MAX])(struct iwl3945_priv *priv, - struct iwl_rx_mem_buffer *rxb); - - struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; - -#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT - /* spectrum measurement report caching */ - struct iwl_spectrum_notification measure_report; - u8 measurement_status; -#endif - /* ucode beacon time */ - u32 ucode_beacon_time; - - /* we allocate array of iwl3945_channel_info for NIC's valid channels. - * Access via channel # using indirect index array */ - struct iwl_channel_info *channel_info; /* channel info array */ - u8 channel_count; /* # of channels */ - - /* each calibration channel group in the EEPROM has a derived - * clip setting for each rate. */ - const struct iwl3945_clip_group clip39_groups[5]; - - /* thermal calibration */ - s32 temperature; /* degrees Kelvin */ - s32 last_temperature; - - /* Scan related variables */ - unsigned long last_scan_jiffies; - unsigned long next_scan_jiffies; - unsigned long scan_start; - unsigned long scan_pass_start; - unsigned long scan_start_tsf; - int scan_bands; - int one_direct_scan; - u8 direct_ssid_len; - u8 direct_ssid[IW_ESSID_MAX_SIZE]; - struct iwl3945_scan_cmd *scan39; - - /* spinlock */ - spinlock_t lock; /* protect general shared data */ - spinlock_t hcmd_lock; /* protect hcmd */ - struct mutex mutex; - - /* basic pci-network driver stuff */ - struct pci_dev *pci_dev; - - /* pci hardware address support */ - void __iomem *hw_base; - - /* uCode images, save to reload in case of failure */ - u32 ucode_ver; /* ucode version, copy of - iwl_ucode.ver */ - struct fw_desc ucode_code; /* runtime inst */ - struct fw_desc ucode_data; /* runtime data original */ - struct fw_desc ucode_data_backup; /* runtime data save/restore */ - struct fw_desc ucode_init; /* initialization inst */ - struct fw_desc ucode_init_data; /* initialization data */ - struct fw_desc ucode_boot; /* bootstrap inst */ - - - struct iwl_rxon_time_cmd rxon_timing; - - /* We declare this const so it can only be - * changed via explicit cast within the - * routines that actually update the physical - * hardware */ - const struct iwl3945_rxon_cmd active39_rxon; - struct iwl3945_rxon_cmd staging39_rxon; - - int error_recovering; - struct iwl3945_rxon_cmd recovery39_rxon; - - /* 1st responses from initialize and runtime uCode images. - * 4965's initialize alive response contains some calibration data. */ - /* FIXME: 4965 uses bigger structure for init */ - struct iwl_alive_resp card_alive_init; - struct iwl_alive_resp card_alive; - -#ifdef CONFIG_IWL3945_RFKILL - struct rfkill *rfkill; -#endif - -#ifdef CONFIG_IWL3945_LEDS - struct iwl3945_led led39[IWL_LED_TRG_MAX]; - unsigned long last_blink_time; - u8 last_blink_rate; - u8 allow_blinking; - unsigned int rxtxpackets; - u64 led_tpt; -#endif - - - u16 active_rate; - u16 active_rate_basic; - - u32 sta_supp_rates; - - u8 call_post_assoc_from_beacon; - /* Rate scaling data */ - s8 data_retry_limit; - u8 retry_rate; - - wait_queue_head_t wait_command_queue; - - int activity_timer_active; - - /* Rx and Tx DMA processing queues */ - struct iwl_rx_queue rxq; - struct iwl3945_tx_queue txq39[IWL39_MAX_NUM_QUEUES]; - - unsigned long status; - - int last_rx_rssi; /* From Rx packet statisitics */ - int last_rx_noise; /* From beacon statistics */ - - struct iwl3945_power_mgr power_data_39; - - struct iwl3945_notif_statistics statistics_39; - unsigned long last_statistics_time; - - /* context information */ - u16 rates_mask; - - u32 power_mode; - u32 antenna; - u8 bssid[ETH_ALEN]; - u16 rts_threshold; - u8 mac_addr[ETH_ALEN]; - - /*station table variables */ - spinlock_t sta_lock; - int num_stations; - struct iwl3945_station_entry stations_39[IWL_STATION_COUNT]; - - /* Indication if ieee80211_ops->open has been called */ - u8 is_open; - - u8 mac80211_registered; - - /* Rx'd packet timing information */ - u32 last_beacon_time; - u64 last_tsf; - - /* eeprom */ - struct iwl3945_eeprom eeprom39; - - enum nl80211_iftype iw_mode; - - struct sk_buff *ibss_beacon; - - /* Last Rx'd beacon timestamp */ - u64 timestamp; - u16 beacon_int; - void *shared_virt; - dma_addr_t shared_phys; - struct iwl_hw_params hw_params; - struct ieee80211_vif *vif; - - /* Current association information needed to configure the - * hardware */ - u16 assoc_id; - u16 assoc_capability; - u8 ps_mode; - - struct iwl_qos_info qos_data; - - struct workqueue_struct *workqueue; - - struct work_struct up; - struct work_struct restart; - struct work_struct calibrated_work; - struct work_struct scan_completed; - struct work_struct rx_replenish; - struct work_struct rf_kill; - struct work_struct abort_scan; - struct work_struct update_link_led; - struct work_struct auth_work; - struct work_struct report_work; - struct work_struct request_scan; - struct work_struct beacon_update; - - struct tasklet_struct irq_tasklet; - - struct delayed_work init_alive_start; - struct delayed_work alive_start; - struct delayed_work activity_timer; - struct delayed_work thermal_periodic; - struct delayed_work gather_stats; - struct delayed_work scan_check; - -#define IWL_DEFAULT_TX_POWER 0x0F - s8 user_txpower_limit; - s8 max_channel_txpower_limit; - - -#ifdef CONFIG_IWL3945_DEBUG - /* debugging info */ - u32 debug_level; - u32 framecnt_to_us; - atomic_t restrict_refcnt; -#endif -}; /*iwl3945_priv */ - -static inline int iwl3945_is_associated(struct iwl3945_priv *priv) +static inline int iwl3945_is_associated(struct iwl_priv *priv) { return (priv->active39_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0; } extern const struct iwl_channel_info *iwl3945_get_channel_info( - const struct iwl3945_priv *priv, enum ieee80211_band band, u16 channel); + const struct iwl_priv *priv, enum ieee80211_band band, u16 channel); -extern int iwl3945_rs_next_rate(struct iwl3945_priv *priv, int rate); +extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate); -/* Requires full declaration of iwl3945_priv before including */ +/* Requires full declaration of iwl_priv before including */ #include "iwl-3945-io.h" #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 9904406ae36..5cc6c5e1865 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -40,6 +40,7 @@ #include "iwl-eeprom.h" #include "iwl-4965-hw.h" #include "iwl-3945-hw.h" +#include "iwl-3945-led.h" #include "iwl-csr.h" #include "iwl-prph.h" #include "iwl-debug.h" @@ -835,7 +836,7 @@ struct iwl_priv { struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; -#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT +#if defined(CONFIG_IWLAGN_SPECTRUM_MEASUREMENT) || defined(CONFIG_IWL3945_SPECTRUM_MEASUREMENT) /* spectrum measurement report caching */ struct iwl_spectrum_notification measure_report; u8 measurement_status; @@ -916,18 +917,25 @@ struct iwl_priv { * 4965's initialize alive response contains some calibration data. */ struct iwl_init_alive_resp card_alive_init; struct iwl_alive_resp card_alive; -#ifdef CONFIG_IWLWIFI_RFKILL +#if defined(CONFIG_IWLWIFI_RFKILL) || defined(CONFIG_IWL3945_RFKILL) struct rfkill *rfkill; #endif -#ifdef CONFIG_IWLWIFI_LEDS - struct iwl_led led[IWL_LED_TRG_MAX]; +#if defined(CONFIG_IWLWIFI_LEDS) || defined(CONFIG_IWL3945_LEDS) unsigned long last_blink_time; u8 last_blink_rate; u8 allow_blinking; u64 led_tpt; #endif +#ifdef CONFIG_IWLWIFI_LEDS + struct iwl_led led[IWL_LED_TRG_MAX]; +#endif + +#ifdef CONFIG_IWL3945_LEDS + struct iwl3945_led led39[IWL_LED_TRG_MAX]; + unsigned int rxtxpackets; +#endif u16 active_rate; u16 active_rate_basic; @@ -1048,12 +1056,16 @@ struct iwl_priv { struct delayed_work init_alive_start; struct delayed_work alive_start; struct delayed_work scan_check; + + /*For 3945 only*/ + struct delayed_work thermal_periodic; + /* TX Power */ s8 tx_power_user_lmt; s8 tx_power_channel_lmt; -#ifdef CONFIG_IWLWIFI_DEBUG +#if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWL3945_DEBUG) /* debugging info */ u32 debug_level; u32 framecnt_to_us; @@ -1070,6 +1082,35 @@ struct iwl_priv { u32 disable_tx_power_cal; struct work_struct run_time_calib_work; struct timer_list statistics_periodic; + + /*For 3945*/ +#define IWL_DEFAULT_TX_POWER 0x0F + s8 user_txpower_limit; + s8 max_channel_txpower_limit; + + struct iwl3945_scan_cmd *scan39; + + /* We declare this const so it can only be + * changed via explicit cast within the + * routines that actually update the physical + * hardware */ + const struct iwl3945_rxon_cmd active39_rxon; + struct iwl3945_rxon_cmd staging39_rxon; + struct iwl3945_rxon_cmd recovery39_rxon; + + struct iwl3945_tx_queue txq39[IWL39_MAX_NUM_QUEUES]; + + struct iwl3945_power_mgr power_data_39; + struct iwl3945_notif_statistics statistics_39; + + struct iwl3945_station_entry stations_39[IWL_STATION_COUNT]; + + /* eeprom */ + struct iwl3945_eeprom eeprom39; + + u32 sta_supp_rates; + u8 call_post_assoc_from_beacon; + }; /*iwl_priv */ static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 43af2595c69..f80294e6bd9 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -55,7 +55,7 @@ #include "iwl-core.h" #include "iwl-dev.h" -static int iwl3945_tx_queue_update_write_ptr(struct iwl3945_priv *priv, +static int iwl3945_tx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl3945_tx_queue *txq); /****************************************************************************** @@ -103,7 +103,7 @@ MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); MODULE_LICENSE("GPL"); static const struct ieee80211_supported_band *iwl3945_get_band( - struct iwl3945_priv *priv, enum ieee80211_band band) + struct iwl_priv *priv, enum ieee80211_band band) { return priv->hw->wiphy->bands[band]; } @@ -143,7 +143,7 @@ int iwl3945_x2_queue_used(const struct iwl_queue *q, int i) /** * iwl3945_queue_init - Initialize queue's high/low-water and read/write indexes */ -static int iwl3945_queue_init(struct iwl3945_priv *priv, struct iwl_queue *q, +static int iwl3945_queue_init(struct iwl_priv *priv, struct iwl_queue *q, int count, int slots_num, u32 id) { q->n_bd = count; @@ -174,7 +174,7 @@ static int iwl3945_queue_init(struct iwl3945_priv *priv, struct iwl_queue *q, /** * iwl3945_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue */ -static int iwl3945_tx_queue_alloc(struct iwl3945_priv *priv, +static int iwl3945_tx_queue_alloc(struct iwl_priv *priv, struct iwl3945_tx_queue *txq, u32 id) { struct pci_dev *dev = priv->pci_dev; @@ -217,7 +217,7 @@ static int iwl3945_tx_queue_alloc(struct iwl3945_priv *priv, /** * iwl3945_tx_queue_init - Allocate and initialize one tx/cmd queue */ -int iwl3945_tx_queue_init(struct iwl3945_priv *priv, +int iwl3945_tx_queue_init(struct iwl_priv *priv, struct iwl3945_tx_queue *txq, int slots_num, u32 txq_id) { struct pci_dev *dev = priv->pci_dev; @@ -269,7 +269,7 @@ int iwl3945_tx_queue_init(struct iwl3945_priv *priv, * Free all buffers. * 0-fill, but do not free "txq" descriptor structure. */ -void iwl3945_tx_queue_free(struct iwl3945_priv *priv, struct iwl3945_tx_queue *txq) +void iwl3945_tx_queue_free(struct iwl_priv *priv, struct iwl3945_tx_queue *txq) { struct iwl_queue *q = &txq->q; struct pci_dev *dev = priv->pci_dev; @@ -315,7 +315,7 @@ void iwl3945_tx_queue_free(struct iwl3945_priv *priv, struct iwl3945_tx_queue *t * * NOTE: This does not remove station from device's station table. */ -static u8 iwl3945_remove_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap) +static u8 iwl3945_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap) { int index = IWL_INVALID_STATION; int i; @@ -357,7 +357,7 @@ out: * * NOTE: This does not clear or otherwise alter the device's station table. */ -static void iwl3945_clear_stations_table(struct iwl3945_priv *priv) +static void iwl3945_clear_stations_table(struct iwl_priv *priv) { unsigned long flags; @@ -372,7 +372,7 @@ static void iwl3945_clear_stations_table(struct iwl3945_priv *priv) /** * iwl3945_add_station - Add station to station tables in driver and device */ -u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8 flags) +u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flags) { int i; int index = IWL_INVALID_STATION; @@ -442,7 +442,7 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8 /*************** DRIVER STATUS FUNCTIONS *****/ -static inline int iwl3945_is_ready(struct iwl3945_priv *priv) +static inline int iwl3945_is_ready(struct iwl_priv *priv) { /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are * set but EXIT_PENDING is not */ @@ -451,33 +451,33 @@ static inline int iwl3945_is_ready(struct iwl3945_priv *priv) !test_bit(STATUS_EXIT_PENDING, &priv->status); } -static inline int iwl3945_is_alive(struct iwl3945_priv *priv) +static inline int iwl3945_is_alive(struct iwl_priv *priv) { return test_bit(STATUS_ALIVE, &priv->status); } -static inline int iwl3945_is_init(struct iwl3945_priv *priv) +static inline int iwl3945_is_init(struct iwl_priv *priv) { return test_bit(STATUS_INIT, &priv->status); } -static inline int iwl3945_is_rfkill_sw(struct iwl3945_priv *priv) +static inline int iwl3945_is_rfkill_sw(struct iwl_priv *priv) { return test_bit(STATUS_RF_KILL_SW, &priv->status); } -static inline int iwl3945_is_rfkill_hw(struct iwl3945_priv *priv) +static inline int iwl3945_is_rfkill_hw(struct iwl_priv *priv) { return test_bit(STATUS_RF_KILL_HW, &priv->status); } -static inline int iwl3945_is_rfkill(struct iwl3945_priv *priv) +static inline int iwl3945_is_rfkill(struct iwl_priv *priv) { return iwl3945_is_rfkill_hw(priv) || iwl3945_is_rfkill_sw(priv); } -static inline int iwl3945_is_ready_rf(struct iwl3945_priv *priv) +static inline int iwl3945_is_ready_rf(struct iwl_priv *priv) { if (iwl3945_is_rfkill(priv)) @@ -500,7 +500,7 @@ static inline int iwl3945_is_ready_rf(struct iwl3945_priv *priv) * failed. On success, it turns the index (> 0) of command in the * command queue. */ -static int iwl3945_enqueue_hcmd(struct iwl3945_priv *priv, struct iwl3945_host_cmd *cmd) +static int iwl3945_enqueue_hcmd(struct iwl_priv *priv, struct iwl3945_host_cmd *cmd) { struct iwl3945_tx_queue *txq = &priv->txq39[IWL_CMD_QUEUE_NUM]; struct iwl_queue *q = &txq->q; @@ -579,7 +579,7 @@ static int iwl3945_enqueue_hcmd(struct iwl3945_priv *priv, struct iwl3945_host_c return ret ? ret : idx; } -static int iwl3945_send_cmd_async(struct iwl3945_priv *priv, struct iwl3945_host_cmd *cmd) +static int iwl3945_send_cmd_async(struct iwl_priv *priv, struct iwl3945_host_cmd *cmd) { int ret; @@ -603,7 +603,7 @@ static int iwl3945_send_cmd_async(struct iwl3945_priv *priv, struct iwl3945_host return 0; } -static int iwl3945_send_cmd_sync(struct iwl3945_priv *priv, struct iwl3945_host_cmd *cmd) +static int iwl3945_send_cmd_sync(struct iwl_priv *priv, struct iwl3945_host_cmd *cmd) { int cmd_idx; int ret; @@ -691,7 +691,7 @@ out: return ret; } -int iwl3945_send_cmd(struct iwl3945_priv *priv, struct iwl3945_host_cmd *cmd) +int iwl3945_send_cmd(struct iwl_priv *priv, struct iwl3945_host_cmd *cmd) { if (cmd->meta.flags & CMD_ASYNC) return iwl3945_send_cmd_async(priv, cmd); @@ -699,7 +699,7 @@ int iwl3945_send_cmd(struct iwl3945_priv *priv, struct iwl3945_host_cmd *cmd) return iwl3945_send_cmd_sync(priv, cmd); } -int iwl3945_send_cmd_pdu(struct iwl3945_priv *priv, u8 id, u16 len, const void *data) +int iwl3945_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data) { struct iwl3945_host_cmd cmd = { .id = id, @@ -710,7 +710,7 @@ int iwl3945_send_cmd_pdu(struct iwl3945_priv *priv, u8 id, u16 len, const void * return iwl3945_send_cmd_sync(priv, &cmd); } -static int __must_check iwl3945_send_cmd_u32(struct iwl3945_priv *priv, u8 id, u32 val) +static int __must_check iwl3945_send_cmd_u32(struct iwl_priv *priv, u8 id, u32 val) { struct iwl3945_host_cmd cmd = { .id = id, @@ -721,7 +721,7 @@ static int __must_check iwl3945_send_cmd_u32(struct iwl3945_priv *priv, u8 id, u return iwl3945_send_cmd_sync(priv, &cmd); } -int iwl3945_send_statistics_request(struct iwl3945_priv *priv) +int iwl3945_send_statistics_request(struct iwl_priv *priv) { return iwl3945_send_cmd_u32(priv, REPLY_STATISTICS_CMD, 0); } @@ -736,7 +736,7 @@ int iwl3945_send_statistics_request(struct iwl3945_priv *priv) * NOTE: Does not commit to the hardware; it sets appropriate bit fields * in the staging RXON flag structure based on the band */ -static int iwl3945_set_rxon_channel(struct iwl3945_priv *priv, +static int iwl3945_set_rxon_channel(struct iwl_priv *priv, enum ieee80211_band band, u16 channel) { @@ -770,7 +770,7 @@ static int iwl3945_set_rxon_channel(struct iwl3945_priv *priv, * be #ifdef'd out once the driver is stable and folks aren't actively * making changes */ -static int iwl3945_check_rxon_cmd(struct iwl3945_priv *priv) +static int iwl3945_check_rxon_cmd(struct iwl_priv *priv) { int error = 0; int counter = 1; @@ -851,7 +851,7 @@ static int iwl3945_check_rxon_cmd(struct iwl3945_priv *priv) * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. */ -static int iwl3945_full_rxon_required(struct iwl3945_priv *priv) +static int iwl3945_full_rxon_required(struct iwl_priv *priv) { /* These items are only settable from the full RXON command */ @@ -886,7 +886,7 @@ static int iwl3945_full_rxon_required(struct iwl3945_priv *priv) return 0; } -static int iwl3945_send_rxon_assoc(struct iwl3945_priv *priv) +static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) { int rc = 0; struct iwl_rx_packet *res = NULL; @@ -938,7 +938,7 @@ static int iwl3945_send_rxon_assoc(struct iwl3945_priv *priv) * function correctly transitions out of the RXON_ASSOC_MSK state if * a HW tune is required based on the RXON structure changes. */ -static int iwl3945_commit_rxon(struct iwl3945_priv *priv) +static int iwl3945_commit_rxon(struct iwl_priv *priv) { /* cast away the const for active_rxon in this function */ struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active39_rxon; @@ -1056,7 +1056,7 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv) return 0; } -static int iwl3945_send_bt_config(struct iwl3945_priv *priv) +static int iwl3945_send_bt_config(struct iwl_priv *priv) { struct iwl_bt_cmd bt_cmd = { .flags = 3, @@ -1070,7 +1070,7 @@ static int iwl3945_send_bt_config(struct iwl3945_priv *priv) sizeof(bt_cmd), &bt_cmd); } -static int iwl3945_send_scan_abort(struct iwl3945_priv *priv) +static int iwl3945_send_scan_abort(struct iwl_priv *priv) { int rc = 0; struct iwl_rx_packet *res; @@ -1111,7 +1111,7 @@ static int iwl3945_send_scan_abort(struct iwl3945_priv *priv) return rc; } -static int iwl3945_card_state_sync_callback(struct iwl3945_priv *priv, +static int iwl3945_card_state_sync_callback(struct iwl_priv *priv, struct iwl3945_cmd *cmd, struct sk_buff *skb) { @@ -1128,7 +1128,7 @@ static int iwl3945_card_state_sync_callback(struct iwl3945_priv *priv, * When in the 'halt' state, the card is shut down and must be fully * restarted to come back on. */ -static int iwl3945_send_card_state(struct iwl3945_priv *priv, u32 flags, u8 meta_flag) +static int iwl3945_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag) { struct iwl3945_host_cmd cmd = { .id = REPLY_CARD_STATE_CMD, @@ -1143,7 +1143,7 @@ static int iwl3945_send_card_state(struct iwl3945_priv *priv, u32 flags, u8 meta return iwl3945_send_cmd(priv, &cmd); } -static int iwl3945_add_sta_sync_callback(struct iwl3945_priv *priv, +static int iwl3945_add_sta_sync_callback(struct iwl_priv *priv, struct iwl3945_cmd *cmd, struct sk_buff *skb) { struct iwl_rx_packet *res = NULL; @@ -1171,7 +1171,7 @@ static int iwl3945_add_sta_sync_callback(struct iwl3945_priv *priv, return 1; } -int iwl3945_send_add_station(struct iwl3945_priv *priv, +int iwl3945_send_add_station(struct iwl_priv *priv, struct iwl3945_addsta_cmd *sta, u8 flags) { struct iwl_rx_packet *res = NULL; @@ -1218,7 +1218,7 @@ int iwl3945_send_add_station(struct iwl3945_priv *priv, return rc; } -static int iwl3945_update_sta_key_info(struct iwl3945_priv *priv, +static int iwl3945_update_sta_key_info(struct iwl_priv *priv, struct ieee80211_key_conf *keyconf, u8 sta_id) { @@ -1256,7 +1256,7 @@ static int iwl3945_update_sta_key_info(struct iwl3945_priv *priv, return 0; } -static int iwl3945_clear_sta_key_info(struct iwl3945_priv *priv, u8 sta_id) +static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) { unsigned long flags; @@ -1274,7 +1274,7 @@ static int iwl3945_clear_sta_key_info(struct iwl3945_priv *priv, u8 sta_id) return 0; } -static void iwl3945_clear_free_frames(struct iwl3945_priv *priv) +static void iwl3945_clear_free_frames(struct iwl_priv *priv) { struct list_head *element; @@ -1295,7 +1295,7 @@ static void iwl3945_clear_free_frames(struct iwl3945_priv *priv) } } -static struct iwl3945_frame *iwl3945_get_free_frame(struct iwl3945_priv *priv) +static struct iwl3945_frame *iwl3945_get_free_frame(struct iwl_priv *priv) { struct iwl3945_frame *frame; struct list_head *element; @@ -1315,13 +1315,13 @@ static struct iwl3945_frame *iwl3945_get_free_frame(struct iwl3945_priv *priv) return list_entry(element, struct iwl3945_frame, list); } -static void iwl3945_free_frame(struct iwl3945_priv *priv, struct iwl3945_frame *frame) +static void iwl3945_free_frame(struct iwl_priv *priv, struct iwl3945_frame *frame) { memset(frame, 0, sizeof(*frame)); list_add(&frame->list, &priv->free_frames); } -unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv, +unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, struct ieee80211_hdr *hdr, int left) { @@ -1339,7 +1339,7 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv, return priv->ibss_beacon->len; } -static u8 iwl3945_rate_get_lowest_plcp(struct iwl3945_priv *priv) +static u8 iwl3945_rate_get_lowest_plcp(struct iwl_priv *priv) { u8 i; int rate_mask; @@ -1363,7 +1363,7 @@ static u8 iwl3945_rate_get_lowest_plcp(struct iwl3945_priv *priv) return IWL_RATE_6M_PLCP; } -static int iwl3945_send_beacon_cmd(struct iwl3945_priv *priv) +static int iwl3945_send_beacon_cmd(struct iwl_priv *priv) { struct iwl3945_frame *frame; unsigned int frame_size; @@ -1396,7 +1396,7 @@ static int iwl3945_send_beacon_cmd(struct iwl3945_priv *priv) * ******************************************************************************/ -static void get_eeprom_mac(struct iwl3945_priv *priv, u8 *mac) +static void get_eeprom_mac(struct iwl_priv *priv, u8 *mac) { memcpy(mac, priv->eeprom39.mac_address, 6); } @@ -1409,7 +1409,7 @@ static void get_eeprom_mac(struct iwl3945_priv *priv, u8 *mac) * simply claims ownership, which should be safe when this function is called * (i.e. before loading uCode!). */ -static inline int iwl3945_eeprom_acquire_semaphore(struct iwl3945_priv *priv) +static inline int iwl3945_eeprom_acquire_semaphore(struct iwl_priv *priv) { _iwl3945_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK); return 0; @@ -1422,7 +1422,7 @@ static inline int iwl3945_eeprom_acquire_semaphore(struct iwl3945_priv *priv) * * NOTE: This routine uses the non-debug IO access functions. */ -int iwl3945_eeprom_init(struct iwl3945_priv *priv) +int iwl3945_eeprom_init(struct iwl_priv *priv) { u16 *e = (u16 *)&priv->eeprom39; u32 gp = iwl3945_read32(priv, CSR_EEPROM_GP); @@ -1470,7 +1470,7 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv) return 0; } -static void iwl3945_unset_hw_params(struct iwl3945_priv *priv) +static void iwl3945_unset_hw_params(struct iwl_priv *priv) { if (priv->shared_virt) pci_free_consistent(priv->pci_dev, @@ -1511,7 +1511,7 @@ static u16 iwl3945_supported_rate_to_ie(u8 *ie, u16 supported_rate, /** * iwl3945_fill_probe_req - fill in all required fields and IE for probe request */ -static u16 iwl3945_fill_probe_req(struct iwl3945_priv *priv, +static u16 iwl3945_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, int left) { @@ -1591,7 +1591,7 @@ static u16 iwl3945_fill_probe_req(struct iwl3945_priv *priv, /* * QoS support */ -static int iwl3945_send_qos_params_command(struct iwl3945_priv *priv, +static int iwl3945_send_qos_params_command(struct iwl_priv *priv, struct iwl_qosparam_cmd *qos) { @@ -1599,7 +1599,7 @@ static int iwl3945_send_qos_params_command(struct iwl3945_priv *priv, sizeof(struct iwl_qosparam_cmd), qos); } -static void iwl3945_reset_qos(struct iwl3945_priv *priv) +static void iwl3945_reset_qos(struct iwl_priv *priv) { u16 cw_min = 15; u16 cw_max = 1023; @@ -1690,7 +1690,7 @@ static void iwl3945_reset_qos(struct iwl3945_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } -static void iwl3945_activate_qos(struct iwl3945_priv *priv, u8 force) +static void iwl3945_activate_qos(struct iwl_priv *priv, u8 force) { unsigned long flags; @@ -1760,7 +1760,7 @@ static struct iwl_power_vec_entry range_1[IWL39_POWER_AC] = { SLP_VEC(4, 7, 10, 10, 0xFF)}, 0} }; -int iwl3945_power_init_handle(struct iwl3945_priv *priv) +int iwl3945_power_init_handle(struct iwl_priv *priv) { int rc = 0, i; struct iwl3945_power_mgr *pow_data; @@ -1799,7 +1799,7 @@ int iwl3945_power_init_handle(struct iwl3945_priv *priv) return rc; } -static int iwl3945_update_power_cmd(struct iwl3945_priv *priv, +static int iwl3945_update_power_cmd(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, u32 mode) { int rc = 0, i; @@ -1863,7 +1863,7 @@ static int iwl3945_update_power_cmd(struct iwl3945_priv *priv, return rc; } -static int iwl3945_send_power_mode(struct iwl3945_priv *priv, u32 mode) +static int iwl3945_send_power_mode(struct iwl_priv *priv, u32 mode) { u32 uninitialized_var(final_mode); int rc; @@ -1903,7 +1903,7 @@ static int iwl3945_send_power_mode(struct iwl3945_priv *priv, u32 mode) * * NOTE: priv->mutex is not required before calling this function */ -static int iwl3945_scan_cancel(struct iwl3945_priv *priv) +static int iwl3945_scan_cancel(struct iwl_priv *priv) { if (!test_bit(STATUS_SCAN_HW, &priv->status)) { clear_bit(STATUS_SCANNING, &priv->status); @@ -1931,7 +1931,7 @@ static int iwl3945_scan_cancel(struct iwl3945_priv *priv) * * NOTE: priv->mutex must be held before calling this function */ -static int iwl3945_scan_cancel_timeout(struct iwl3945_priv *priv, unsigned long ms) +static int iwl3945_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) { unsigned long now = jiffies; int ret; @@ -1966,7 +1966,7 @@ static __le16 iwl3945_adjust_beacon_interval(u16 beacon_val) return cpu_to_le16(new_val); } -static void iwl3945_setup_rxon_timing(struct iwl3945_priv *priv) +static void iwl3945_setup_rxon_timing(struct iwl_priv *priv) { u64 interval_tm_unit; u64 tsf, result; @@ -2019,7 +2019,7 @@ static void iwl3945_setup_rxon_timing(struct iwl3945_priv *priv) le16_to_cpu(priv->rxon_timing.atim_window)); } -static int iwl3945_scan_initiate(struct iwl3945_priv *priv) +static int iwl3945_scan_initiate(struct iwl_priv *priv) { if (!iwl3945_is_ready_rf(priv)) { IWL_DEBUG_SCAN("Aborting scan due to not ready.\n"); @@ -2051,7 +2051,7 @@ static int iwl3945_scan_initiate(struct iwl3945_priv *priv) return 0; } -static int iwl3945_set_rxon_hwcrypto(struct iwl3945_priv *priv, int hw_decrypt) +static int iwl3945_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) { struct iwl3945_rxon_cmd *rxon = &priv->staging39_rxon; @@ -2063,7 +2063,7 @@ static int iwl3945_set_rxon_hwcrypto(struct iwl3945_priv *priv, int hw_decrypt) return 0; } -static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, +static void iwl3945_set_flags_for_phymode(struct iwl_priv *priv, enum ieee80211_band band) { if (band == IEEE80211_BAND_5GHZ) { @@ -2090,7 +2090,7 @@ static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, /* * initialize rxon structure with default values from eeprom */ -static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv, +static void iwl3945_connection_init_rx_config(struct iwl_priv *priv, int mode) { const struct iwl_channel_info *ch_info; @@ -2160,7 +2160,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv, (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; } -static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode) +static int iwl3945_set_mode(struct iwl_priv *priv, int mode) { if (mode == NL80211_IFTYPE_ADHOC) { const struct iwl_channel_info *ch_info; @@ -2197,7 +2197,7 @@ static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode) return 0; } -static void iwl3945_build_tx_cmd_hwcrypto(struct iwl3945_priv *priv, +static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, struct ieee80211_tx_info *info, struct iwl3945_cmd *cmd, struct sk_buff *skb_frag, @@ -2247,7 +2247,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl3945_priv *priv, /* * handle build REPLY_TX command notification. */ -static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv, +static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv, struct iwl3945_cmd *cmd, struct ieee80211_tx_info *info, struct ieee80211_hdr *hdr, @@ -2314,7 +2314,7 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv, /** * iwl3945_get_sta_id - Find station's index within station table */ -static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *hdr) +static int iwl3945_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) { int sta_id; u16 fc = le16_to_cpu(hdr->frame_control); @@ -2371,7 +2371,7 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h /* * start REPLY_TX command process */ -static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) +static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); @@ -2594,7 +2594,7 @@ drop: return -1; } -static void iwl3945_set_rate(struct iwl3945_priv *priv) +static void iwl3945_set_rate(struct iwl_priv *priv) { const struct ieee80211_supported_band *sband = NULL; struct ieee80211_rate *rate; @@ -2648,7 +2648,7 @@ static void iwl3945_set_rate(struct iwl3945_priv *priv) (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; } -static void iwl3945_radio_kill_sw(struct iwl3945_priv *priv, int disable_radio) +static void iwl3945_radio_kill_sw(struct iwl_priv *priv, int disable_radio) { unsigned long flags; @@ -2698,7 +2698,7 @@ static void iwl3945_radio_kill_sw(struct iwl3945_priv *priv, int disable_radio) return; } -void iwl3945_set_decrypted_flag(struct iwl3945_priv *priv, struct sk_buff *skb, +void iwl3945_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb, u32 decrypt_res, struct ieee80211_rx_status *stats) { u16 fc = @@ -2783,7 +2783,7 @@ static __le32 iwl3945_add_beacon_time(u32 base, u32 addon, u32 beacon_interval) return cpu_to_le32(res); } -static int iwl3945_get_measurement(struct iwl3945_priv *priv, +static int iwl3945_get_measurement(struct iwl_priv *priv, struct ieee80211_measurement_params *params, u8 type) { @@ -2862,7 +2862,7 @@ static int iwl3945_get_measurement(struct iwl3945_priv *priv, } #endif -static void iwl3945_rx_reply_alive(struct iwl3945_priv *priv, +static void iwl3945_rx_reply_alive(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; @@ -2898,7 +2898,7 @@ static void iwl3945_rx_reply_alive(struct iwl3945_priv *priv, IWL_WARNING("uCode did not respond OK.\n"); } -static void iwl3945_rx_reply_add_sta(struct iwl3945_priv *priv, +static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; @@ -2907,7 +2907,7 @@ static void iwl3945_rx_reply_add_sta(struct iwl3945_priv *priv, return; } -static void iwl3945_rx_reply_error(struct iwl3945_priv *priv, +static void iwl3945_rx_reply_error(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; @@ -2923,7 +2923,7 @@ static void iwl3945_rx_reply_error(struct iwl3945_priv *priv, #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x -static void iwl3945_rx_csa(struct iwl3945_priv *priv, struct iwl_rx_mem_buffer *rxb) +static void iwl3945_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl3945_rxon_cmd *rxon = (void *)&priv->active39_rxon; @@ -2934,7 +2934,7 @@ static void iwl3945_rx_csa(struct iwl3945_priv *priv, struct iwl_rx_mem_buffer * priv->staging39_rxon.channel = csa->channel; } -static void iwl3945_rx_spectrum_measure_notif(struct iwl3945_priv *priv, +static void iwl3945_rx_spectrum_measure_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT @@ -2952,7 +2952,7 @@ static void iwl3945_rx_spectrum_measure_notif(struct iwl3945_priv *priv, #endif } -static void iwl3945_rx_pm_sleep_notif(struct iwl3945_priv *priv, +static void iwl3945_rx_pm_sleep_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { #ifdef CONFIG_IWL3945_DEBUG @@ -2963,7 +2963,7 @@ static void iwl3945_rx_pm_sleep_notif(struct iwl3945_priv *priv, #endif } -static void iwl3945_rx_pm_debug_statistics_notif(struct iwl3945_priv *priv, +static void iwl3945_rx_pm_debug_statistics_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; @@ -2976,8 +2976,8 @@ static void iwl3945_rx_pm_debug_statistics_notif(struct iwl3945_priv *priv, static void iwl3945_bg_beacon_update(struct work_struct *work) { - struct iwl3945_priv *priv = - container_of(work, struct iwl3945_priv, beacon_update); + struct iwl_priv *priv = + container_of(work, struct iwl_priv, beacon_update); struct sk_buff *beacon; /* Pull updated AP beacon from mac80211. will fail if not in AP mode */ @@ -2999,7 +2999,7 @@ static void iwl3945_bg_beacon_update(struct work_struct *work) iwl3945_send_beacon_cmd(priv); } -static void iwl3945_rx_beacon_notif(struct iwl3945_priv *priv, +static void iwl3945_rx_beacon_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { #ifdef CONFIG_IWL3945_DEBUG @@ -3022,7 +3022,7 @@ static void iwl3945_rx_beacon_notif(struct iwl3945_priv *priv, } /* Service response to REPLY_SCAN_CMD (0x80) */ -static void iwl3945_rx_reply_scan(struct iwl3945_priv *priv, +static void iwl3945_rx_reply_scan(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { #ifdef CONFIG_IWL3945_DEBUG @@ -3035,7 +3035,7 @@ static void iwl3945_rx_reply_scan(struct iwl3945_priv *priv, } /* Service SCAN_START_NOTIFICATION (0x82) */ -static void iwl3945_rx_scan_start_notif(struct iwl3945_priv *priv, +static void iwl3945_rx_scan_start_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; @@ -3052,7 +3052,7 @@ static void iwl3945_rx_scan_start_notif(struct iwl3945_priv *priv, } /* Service SCAN_RESULTS_NOTIFICATION (0x83) */ -static void iwl3945_rx_scan_results_notif(struct iwl3945_priv *priv, +static void iwl3945_rx_scan_results_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; @@ -3077,7 +3077,7 @@ static void iwl3945_rx_scan_results_notif(struct iwl3945_priv *priv, } /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */ -static void iwl3945_rx_scan_complete_notif(struct iwl3945_priv *priv, +static void iwl3945_rx_scan_complete_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; @@ -3140,7 +3140,7 @@ reschedule: /* Handle notification from uCode that card's power state is changing * due to software, hardware, or critical temperature RFKILL */ -static void iwl3945_rx_card_state_notif(struct iwl3945_priv *priv, +static void iwl3945_rx_card_state_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; @@ -3185,7 +3185,7 @@ static void iwl3945_rx_card_state_notif(struct iwl3945_priv *priv, * This function chains into the hardware specific files for them to setup * any hardware specific handlers as well. */ -static void iwl3945_setup_rx_handlers(struct iwl3945_priv *priv) +static void iwl3945_setup_rx_handlers(struct iwl_priv *priv) { priv->rx_handlers[REPLY_ALIVE] = iwl3945_rx_reply_alive; priv->rx_handlers[REPLY_ADD_STA] = iwl3945_rx_reply_add_sta; @@ -3223,7 +3223,7 @@ static void iwl3945_setup_rx_handlers(struct iwl3945_priv *priv) * When FW advances 'R' index, all entries between old and new 'R' index * need to be reclaimed. */ -static void iwl3945_cmd_queue_reclaim(struct iwl3945_priv *priv, +static void iwl3945_cmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) { struct iwl3945_tx_queue *txq = &priv->txq39[txq_id]; @@ -3258,7 +3258,7 @@ static void iwl3945_cmd_queue_reclaim(struct iwl3945_priv *priv, * will be executed. The attached skb (if present) will only be freed * if the callback returns 1 */ -static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv, +static void iwl3945_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; @@ -3373,7 +3373,7 @@ static int iwl3945_rx_queue_space(const struct iwl_rx_queue *q) /** * iwl3945_rx_queue_update_write_ptr - Update the write pointer for the RX queue */ -int iwl3945_rx_queue_update_write_ptr(struct iwl3945_priv *priv, struct iwl_rx_queue *q) +int iwl3945_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) { u32 reg = 0; int rc = 0; @@ -3419,7 +3419,7 @@ int iwl3945_rx_queue_update_write_ptr(struct iwl3945_priv *priv, struct iwl_rx_q /** * iwl3945_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr */ -static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl3945_priv *priv, +static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl_priv *priv, dma_addr_t dma_addr) { return cpu_to_le32((u32)dma_addr); @@ -3436,7 +3436,7 @@ static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl3945_priv *priv, * also updates the memory address in the firmware to reference the new * target buffer. */ -static int iwl3945_rx_queue_restock(struct iwl3945_priv *priv) +static int iwl3945_rx_queue_restock(struct iwl_priv *priv) { struct iwl_rx_queue *rxq = &priv->rxq; struct list_head *element; @@ -3488,7 +3488,7 @@ static int iwl3945_rx_queue_restock(struct iwl3945_priv *priv) * Also restock the Rx queue via iwl3945_rx_queue_restock. * This is called as a scheduled work item (except for during initialization) */ -static void iwl3945_rx_allocate(struct iwl3945_priv *priv) +static void iwl3945_rx_allocate(struct iwl_priv *priv) { struct iwl_rx_queue *rxq = &priv->rxq; struct list_head *element; @@ -3538,7 +3538,7 @@ static void iwl3945_rx_allocate(struct iwl3945_priv *priv) */ static void __iwl3945_rx_replenish(void *data) { - struct iwl3945_priv *priv = data; + struct iwl_priv *priv = data; iwl3945_rx_allocate(priv); iwl3945_rx_queue_restock(priv); @@ -3547,7 +3547,7 @@ static void __iwl3945_rx_replenish(void *data) void iwl3945_rx_replenish(void *data) { - struct iwl3945_priv *priv = data; + struct iwl_priv *priv = data; unsigned long flags; iwl3945_rx_allocate(priv); @@ -3562,7 +3562,7 @@ void iwl3945_rx_replenish(void *data) * This free routine walks the list of POOL entries and if SKB is set to * non NULL it is unmapped and freed */ -static void iwl3945_rx_queue_free(struct iwl3945_priv *priv, struct iwl_rx_queue *rxq) +static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) { int i; for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { @@ -3579,7 +3579,7 @@ static void iwl3945_rx_queue_free(struct iwl3945_priv *priv, struct iwl_rx_queue rxq->bd = NULL; } -int iwl3945_rx_queue_alloc(struct iwl3945_priv *priv) +int iwl3945_rx_queue_alloc(struct iwl_priv *priv) { struct iwl_rx_queue *rxq = &priv->rxq; struct pci_dev *dev = priv->pci_dev; @@ -3606,7 +3606,7 @@ int iwl3945_rx_queue_alloc(struct iwl3945_priv *priv) return 0; } -void iwl3945_rx_queue_reset(struct iwl3945_priv *priv, struct iwl_rx_queue *rxq) +void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) { unsigned long flags; int i; @@ -3720,7 +3720,7 @@ int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm) * the appropriate handlers, including command responses, * frame-received notifications, and other notifications. */ -static void iwl3945_rx_handle(struct iwl3945_priv *priv) +static void iwl3945_rx_handle(struct iwl_priv *priv) { struct iwl_rx_mem_buffer *rxb; struct iwl_rx_packet *pkt; @@ -3828,7 +3828,7 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv) /** * iwl3945_tx_queue_update_write_ptr - Send new write index to hardware */ -static int iwl3945_tx_queue_update_write_ptr(struct iwl3945_priv *priv, +static int iwl3945_tx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl3945_tx_queue *txq) { u32 reg = 0; @@ -3872,7 +3872,7 @@ static int iwl3945_tx_queue_update_write_ptr(struct iwl3945_priv *priv, } #ifdef CONFIG_IWL3945_DEBUG -static void iwl3945_print_rx_config_cmd(struct iwl3945_priv *priv, +static void iwl3945_print_rx_config_cmd(struct iwl_priv *priv, struct iwl3945_rxon_cmd *rxon) { IWL_DEBUG_RADIO("RX CONFIG:\n"); @@ -3891,7 +3891,7 @@ static void iwl3945_print_rx_config_cmd(struct iwl3945_priv *priv, } #endif -static void iwl3945_enable_interrupts(struct iwl3945_priv *priv) +static void iwl3945_enable_interrupts(struct iwl_priv *priv) { IWL_DEBUG_ISR("Enabling interrupts\n"); set_bit(STATUS_INT_ENABLED, &priv->status); @@ -3900,7 +3900,7 @@ static void iwl3945_enable_interrupts(struct iwl3945_priv *priv) /* call this function to flush any scheduled tasklet */ -static inline void iwl_synchronize_irq(struct iwl3945_priv *priv) +static inline void iwl_synchronize_irq(struct iwl_priv *priv) { /* wait to make sure we flush pending tasklet*/ synchronize_irq(priv->pci_dev->irq); @@ -3908,7 +3908,7 @@ static inline void iwl_synchronize_irq(struct iwl3945_priv *priv) } -static inline void iwl3945_disable_interrupts(struct iwl3945_priv *priv) +static inline void iwl3945_disable_interrupts(struct iwl_priv *priv) { clear_bit(STATUS_INT_ENABLED, &priv->status); @@ -3945,7 +3945,7 @@ static const char *desc_lookup(int i) #define ERROR_START_OFFSET (1 * sizeof(u32)) #define ERROR_ELEM_SIZE (7 * sizeof(u32)) -static void iwl3945_dump_nic_error_log(struct iwl3945_priv *priv) +static void iwl3945_dump_nic_error_log(struct iwl_priv *priv) { u32 i; u32 desc, time, count, base, data1; @@ -4008,7 +4008,7 @@ static void iwl3945_dump_nic_error_log(struct iwl3945_priv *priv) * * NOTE: Must be called with iwl3945_grab_nic_access() already obtained! */ -static void iwl3945_print_event_log(struct iwl3945_priv *priv, u32 start_idx, +static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, u32 num_events, u32 mode) { u32 i; @@ -4046,7 +4046,7 @@ static void iwl3945_print_event_log(struct iwl3945_priv *priv, u32 start_idx, } } -static void iwl3945_dump_nic_event_log(struct iwl3945_priv *priv) +static void iwl3945_dump_nic_event_log(struct iwl_priv *priv) { int rc; u32 base; /* SRAM byte address of event log header */ @@ -4101,7 +4101,7 @@ static void iwl3945_dump_nic_event_log(struct iwl3945_priv *priv) /** * iwl3945_irq_handle_error - called for HW or SW error interrupt from card */ -static void iwl3945_irq_handle_error(struct iwl3945_priv *priv) +static void iwl3945_irq_handle_error(struct iwl_priv *priv) { /* Set the FW error flag -- cleared on iwl3945_down */ set_bit(STATUS_FW_ERROR, &priv->status); @@ -4136,7 +4136,7 @@ static void iwl3945_irq_handle_error(struct iwl3945_priv *priv) } } -static void iwl3945_error_recovery(struct iwl3945_priv *priv) +static void iwl3945_error_recovery(struct iwl_priv *priv) { unsigned long flags; @@ -4153,7 +4153,7 @@ static void iwl3945_error_recovery(struct iwl3945_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } -static void iwl3945_irq_tasklet(struct iwl3945_priv *priv) +static void iwl3945_irq_tasklet(struct iwl_priv *priv) { u32 inta, handled = 0; u32 inta_fh; @@ -4295,7 +4295,7 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv) static irqreturn_t iwl3945_isr(int irq, void *data) { - struct iwl3945_priv *priv = data; + struct iwl_priv *priv = data; u32 inta, inta_mask; u32 inta_fh; if (!priv) @@ -4403,7 +4403,7 @@ static const u8 iwl3945_eeprom_band_5[] = { /* 5725-5825MHz */ 145, 149, 153, 157, 161, 165 }; -static void iwl3945_init_band_reference(const struct iwl3945_priv *priv, int band, +static void iwl3945_init_band_reference(const struct iwl_priv *priv, int band, int *eeprom_ch_count, const struct iwl_eeprom_channel **eeprom_ch_info, @@ -4447,7 +4447,7 @@ static void iwl3945_init_band_reference(const struct iwl3945_priv *priv, int ban * Based on band and channel number. */ const struct iwl_channel_info * -iwl3945_get_channel_info(const struct iwl3945_priv *priv, +iwl3945_get_channel_info(const struct iwl_priv *priv, enum ieee80211_band band, u16 channel) { int i; @@ -4477,7 +4477,7 @@ iwl3945_get_channel_info(const struct iwl3945_priv *priv, /** * iwl3945_init_channel_map - Set up driver's info for all possible channels */ -static int iwl3945_init_channel_map(struct iwl3945_priv *priv) +static int iwl3945_init_channel_map(struct iwl_priv *priv) { int eeprom_ch_count = 0; const u8 *eeprom_ch_index = NULL; @@ -4596,7 +4596,7 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv) /* * iwl3945_free_channel_map - undo allocations in iwl3945_init_channel_map */ -static void iwl3945_free_channel_map(struct iwl3945_priv *priv) +static void iwl3945_free_channel_map(struct iwl_priv *priv) { kfree(priv->channel_info); priv->channel_count = 0; @@ -4630,7 +4630,7 @@ static void iwl3945_free_channel_map(struct iwl3945_priv *priv) #define IWL_SCAN_PROBE_MASK(n) (BIT(n) | (BIT(n) - BIT(1))) -static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv, +static inline u16 iwl3945_get_active_dwell_time(struct iwl_priv *priv, enum ieee80211_band band, u8 n_probes) { @@ -4642,7 +4642,7 @@ static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv, IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1); } -static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv, +static u16 iwl3945_get_passive_dwell_time(struct iwl_priv *priv, enum ieee80211_band band) { u16 passive = (band == IEEE80211_BAND_2GHZ) ? @@ -4662,7 +4662,7 @@ static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv, return passive; } -static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, +static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, enum ieee80211_band band, u8 is_active, u8 n_probes, struct iwl3945_scan_channel *scan_ch) @@ -4756,7 +4756,7 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, return added; } -static void iwl3945_init_hw_rates(struct iwl3945_priv *priv, +static void iwl3945_init_hw_rates(struct iwl_priv *priv, struct ieee80211_rate *rates) { int i; @@ -4779,7 +4779,7 @@ static void iwl3945_init_hw_rates(struct iwl3945_priv *priv, /** * iwl3945_init_geos - Initialize mac80211's geo/channel info based from eeprom */ -static int iwl3945_init_geos(struct iwl3945_priv *priv) +static int iwl3945_init_geos(struct iwl_priv *priv) { struct iwl_channel_info *ch; struct ieee80211_supported_band *sband; @@ -4901,7 +4901,7 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv) /* * iwl3945_free_geos - undo allocations in iwl3945_init_geos */ -static void iwl3945_free_geos(struct iwl3945_priv *priv) +static void iwl3945_free_geos(struct iwl_priv *priv) { kfree(priv->ieee_channels); kfree(priv->ieee_rates); @@ -4914,7 +4914,7 @@ static void iwl3945_free_geos(struct iwl3945_priv *priv) * ******************************************************************************/ -static void iwl3945_dealloc_ucode_pci(struct iwl3945_priv *priv) +static void iwl3945_dealloc_ucode_pci(struct iwl_priv *priv) { iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code); iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data); @@ -4928,7 +4928,7 @@ static void iwl3945_dealloc_ucode_pci(struct iwl3945_priv *priv) * iwl3945_verify_inst_full - verify runtime uCode image in card vs. host, * looking at all data. */ -static int iwl3945_verify_inst_full(struct iwl3945_priv *priv, __le32 *image, u32 len) +static int iwl3945_verify_inst_full(struct iwl_priv *priv, __le32 *image, u32 len) { u32 val; u32 save_len = len; @@ -4975,7 +4975,7 @@ static int iwl3945_verify_inst_full(struct iwl3945_priv *priv, __le32 *image, u3 * using sample data 100 bytes apart. If these sample points are good, * it's a pretty good bet that everything between them is good, too. */ -static int iwl3945_verify_inst_sparse(struct iwl3945_priv *priv, __le32 *image, u32 len) +static int iwl3945_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len) { u32 val; int rc = 0; @@ -5018,7 +5018,7 @@ static int iwl3945_verify_inst_sparse(struct iwl3945_priv *priv, __le32 *image, * iwl3945_verify_ucode - determine which instruction image is in SRAM, * and verify its contents */ -static int iwl3945_verify_ucode(struct iwl3945_priv *priv) +static int iwl3945_verify_ucode(struct iwl_priv *priv) { __le32 *image; u32 len; @@ -5065,7 +5065,7 @@ static int iwl3945_verify_ucode(struct iwl3945_priv *priv) /* check contents of special bootstrap uCode SRAM */ -static int iwl3945_verify_bsm(struct iwl3945_priv *priv) +static int iwl3945_verify_bsm(struct iwl_priv *priv) { __le32 *image = priv->ucode_boot.v_addr; u32 len = priv->ucode_boot.len; @@ -5127,7 +5127,7 @@ static int iwl3945_verify_bsm(struct iwl3945_priv *priv) * the runtime uCode instructions and the backup data cache into SRAM, * and re-launches the runtime uCode from where it left off. */ -static int iwl3945_load_bsm(struct iwl3945_priv *priv) +static int iwl3945_load_bsm(struct iwl_priv *priv) { __le32 *image = priv->ucode_boot.v_addr; u32 len = priv->ucode_boot.len; @@ -5213,7 +5213,7 @@ static int iwl3945_load_bsm(struct iwl3945_priv *priv) return 0; } -static void iwl3945_nic_start(struct iwl3945_priv *priv) +static void iwl3945_nic_start(struct iwl_priv *priv) { /* Remove all resets to allow NIC to operate */ iwl3945_write32(priv, CSR_RESET, 0); @@ -5224,7 +5224,7 @@ static void iwl3945_nic_start(struct iwl3945_priv *priv) * * Copy into buffers for card to fetch via bus-mastering */ -static int iwl3945_read_ucode(struct iwl3945_priv *priv) +static int iwl3945_read_ucode(struct iwl_priv *priv) { struct iwl_ucode *ucode; int ret = -EINVAL, index; @@ -5465,7 +5465,7 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv) * We need to replace them to load runtime uCode inst and data, * and to save runtime data when powering down. */ -static int iwl3945_set_ucode_ptrs(struct iwl3945_priv *priv) +static int iwl3945_set_ucode_ptrs(struct iwl_priv *priv) { dma_addr_t pinst; dma_addr_t pdata; @@ -5510,7 +5510,7 @@ static int iwl3945_set_ucode_ptrs(struct iwl3945_priv *priv) * * Tell "initialize" uCode to go ahead and load the runtime uCode. */ -static void iwl3945_init_alive_start(struct iwl3945_priv *priv) +static void iwl3945_init_alive_start(struct iwl_priv *priv) { /* Check alive response for "valid" sign from uCode */ if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { @@ -5556,7 +5556,7 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, * from protocol/runtime uCode (initialization uCode's * Alive gets handled by iwl3945_init_alive_start()). */ -static void iwl3945_alive_start(struct iwl3945_priv *priv) +static void iwl3945_alive_start(struct iwl_priv *priv) { int rc = 0; int thermal_spin = 0; @@ -5668,9 +5668,9 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv) queue_work(priv->workqueue, &priv->restart); } -static void iwl3945_cancel_deferred_work(struct iwl3945_priv *priv); +static void iwl3945_cancel_deferred_work(struct iwl_priv *priv); -static void __iwl3945_down(struct iwl3945_priv *priv) +static void __iwl3945_down(struct iwl_priv *priv) { unsigned long flags; int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status); @@ -5769,7 +5769,7 @@ static void __iwl3945_down(struct iwl3945_priv *priv) iwl3945_clear_free_frames(priv); } -static void iwl3945_down(struct iwl3945_priv *priv) +static void iwl3945_down(struct iwl_priv *priv) { mutex_lock(&priv->mutex); __iwl3945_down(priv); @@ -5780,7 +5780,7 @@ static void iwl3945_down(struct iwl3945_priv *priv) #define MAX_HW_RESTARTS 5 -static int __iwl3945_up(struct iwl3945_priv *priv) +static int __iwl3945_up(struct iwl_priv *priv) { int rc, i; @@ -5884,8 +5884,8 @@ static int __iwl3945_up(struct iwl3945_priv *priv) static void iwl3945_bg_init_alive_start(struct work_struct *data) { - struct iwl3945_priv *priv = - container_of(data, struct iwl3945_priv, init_alive_start.work); + struct iwl_priv *priv = + container_of(data, struct iwl_priv, init_alive_start.work); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -5897,8 +5897,8 @@ static void iwl3945_bg_init_alive_start(struct work_struct *data) static void iwl3945_bg_alive_start(struct work_struct *data) { - struct iwl3945_priv *priv = - container_of(data, struct iwl3945_priv, alive_start.work); + struct iwl_priv *priv = + container_of(data, struct iwl_priv, alive_start.work); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -5910,7 +5910,7 @@ static void iwl3945_bg_alive_start(struct work_struct *data) static void iwl3945_bg_rf_kill(struct work_struct *work) { - struct iwl3945_priv *priv = container_of(work, struct iwl3945_priv, rf_kill); + struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill); wake_up_interruptible(&priv->wait_command_queue); @@ -5944,8 +5944,8 @@ static void iwl3945_bg_rf_kill(struct work_struct *work) static void iwl3945_bg_scan_check(struct work_struct *data) { - struct iwl3945_priv *priv = - container_of(data, struct iwl3945_priv, scan_check.work); + struct iwl_priv *priv = + container_of(data, struct iwl_priv, scan_check.work); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -5965,8 +5965,8 @@ static void iwl3945_bg_scan_check(struct work_struct *data) static void iwl3945_bg_request_scan(struct work_struct *data) { - struct iwl3945_priv *priv = - container_of(data, struct iwl3945_priv, request_scan); + struct iwl_priv *priv = + container_of(data, struct iwl_priv, request_scan); struct iwl3945_host_cmd cmd = { .id = REPLY_SCAN_CMD, .len = sizeof(struct iwl3945_scan_cmd), @@ -6161,7 +6161,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) static void iwl3945_bg_up(struct work_struct *data) { - struct iwl3945_priv *priv = container_of(data, struct iwl3945_priv, up); + struct iwl_priv *priv = container_of(data, struct iwl_priv, up); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -6174,7 +6174,7 @@ static void iwl3945_bg_up(struct work_struct *data) static void iwl3945_bg_restart(struct work_struct *data) { - struct iwl3945_priv *priv = container_of(data, struct iwl3945_priv, restart); + struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -6185,8 +6185,8 @@ static void iwl3945_bg_restart(struct work_struct *data) static void iwl3945_bg_rx_replenish(struct work_struct *data) { - struct iwl3945_priv *priv = - container_of(data, struct iwl3945_priv, rx_replenish); + struct iwl_priv *priv = + container_of(data, struct iwl_priv, rx_replenish); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -6198,7 +6198,7 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data) #define IWL_DELAY_NEXT_SCAN (HZ*2) -static void iwl3945_post_associate(struct iwl3945_priv *priv) +static void iwl3945_post_associate(struct iwl_priv *priv) { int rc = 0; struct ieee80211_conf *conf = NULL; @@ -6290,7 +6290,7 @@ static void iwl3945_post_associate(struct iwl3945_priv *priv) static void iwl3945_bg_abort_scan(struct work_struct *work) { - struct iwl3945_priv *priv = container_of(work, struct iwl3945_priv, abort_scan); + struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); if (!iwl3945_is_ready(priv)) return; @@ -6307,8 +6307,8 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed); static void iwl3945_bg_scan_completed(struct work_struct *work) { - struct iwl3945_priv *priv = - container_of(work, struct iwl3945_priv, scan_completed); + struct iwl_priv *priv = + container_of(work, struct iwl_priv, scan_completed); IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN, "SCAN complete scan\n"); @@ -6337,7 +6337,7 @@ static void iwl3945_bg_scan_completed(struct work_struct *work) static int iwl3945_mac_start(struct ieee80211_hw *hw) { - struct iwl3945_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; int ret; IWL_DEBUG_MAC80211("enter\n"); @@ -6416,7 +6416,7 @@ out_disable_msi: static void iwl3945_mac_stop(struct ieee80211_hw *hw) { - struct iwl3945_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; IWL_DEBUG_MAC80211("enter\n"); @@ -6449,7 +6449,7 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw) static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { - struct iwl3945_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; IWL_DEBUG_MAC80211("enter\n"); @@ -6466,7 +6466,7 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) static int iwl3945_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) { - struct iwl3945_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; unsigned long flags; IWL_DEBUG_MAC80211("enter: type %d\n", conf->type); @@ -6507,7 +6507,7 @@ static int iwl3945_mac_add_interface(struct ieee80211_hw *hw, */ static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed) { - struct iwl3945_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; const struct iwl_channel_info *ch_info; struct ieee80211_conf *conf = &hw->conf; unsigned long flags; @@ -6590,7 +6590,7 @@ out: return ret; } -static void iwl3945_config_ap(struct iwl3945_priv *priv) +static void iwl3945_config_ap(struct iwl_priv *priv) { int rc = 0; @@ -6649,9 +6649,9 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv) static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) + struct ieee80211_if_conf *conf) { - struct iwl3945_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; int rc; if (conf == NULL) @@ -6752,7 +6752,7 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw, unsigned int *total_flags, int mc_count, struct dev_addr_list *mc_list) { - struct iwl3945_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; __le32 *filter_flags = &priv->staging39_rxon.filter_flags; IWL_DEBUG_MAC80211("Enter: changed: 0x%x, total: 0x%x\n", @@ -6796,7 +6796,7 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw, static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) { - struct iwl3945_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; IWL_DEBUG_MAC80211("enter\n"); @@ -6823,7 +6823,7 @@ static void iwl3945_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_bss_conf *bss_conf, u32 changes) { - struct iwl3945_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; IWL_DEBUG_MAC80211("changes = 0x%X\n", changes); @@ -6875,7 +6875,7 @@ static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) { int rc = 0; unsigned long flags; - struct iwl3945_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; DECLARE_SSID_BUF(ssid_buf); IWL_DEBUG_MAC80211("enter\n"); @@ -6928,7 +6928,7 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, const u8 *local_addr, const u8 *addr, struct ieee80211_key_conf *key) { - struct iwl3945_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; int rc = 0; u8 sta_id; @@ -6986,7 +6986,7 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { - struct iwl3945_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; unsigned long flags; int q; @@ -7032,7 +7032,7 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw, struct ieee80211_tx_queue_stats *stats) { - struct iwl3945_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; int i, avail; struct iwl3945_tx_queue *txq; struct iwl_queue *q; @@ -7066,7 +7066,7 @@ static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw, static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) { - struct iwl3945_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; unsigned long flags; mutex_lock(&priv->mutex); @@ -7125,7 +7125,7 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) { - struct iwl3945_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; unsigned long flags; IWL_DEBUG_MAC80211("enter\n"); @@ -7178,7 +7178,7 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk static ssize_t show_debug_level(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl3945_priv *priv = d->driver_data; + struct iwl_priv *priv = d->driver_data; return sprintf(buf, "0x%08X\n", priv->debug_level); } @@ -7186,7 +7186,7 @@ static ssize_t store_debug_level(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl3945_priv *priv = d->driver_data; + struct iwl_priv *priv = d->driver_data; unsigned long val; int ret; @@ -7208,7 +7208,7 @@ static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, static ssize_t show_temperature(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data; + struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; if (!iwl3945_is_alive(priv)) return -EAGAIN; @@ -7221,7 +7221,7 @@ static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL); static ssize_t show_tx_power(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data; + struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; return sprintf(buf, "%d\n", priv->user_txpower_limit); } @@ -7229,7 +7229,7 @@ static ssize_t store_tx_power(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data; + struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; char *p = (char *)buf; u32 val; @@ -7248,7 +7248,7 @@ static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); static ssize_t show_flags(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data; + struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; return sprintf(buf, "0x%04X\n", priv->active39_rxon.flags); } @@ -7257,7 +7257,7 @@ static ssize_t store_flags(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data; + struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; u32 flags = simple_strtoul(buf, NULL, 0); mutex_lock(&priv->mutex); @@ -7282,7 +7282,7 @@ static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags); static ssize_t show_filter_flags(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data; + struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; return sprintf(buf, "0x%04X\n", le32_to_cpu(priv->active39_rxon.filter_flags)); @@ -7292,7 +7292,7 @@ static ssize_t store_filter_flags(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data; + struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; u32 filter_flags = simple_strtoul(buf, NULL, 0); mutex_lock(&priv->mutex); @@ -7321,7 +7321,7 @@ static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, static ssize_t show_measurement(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl3945_priv *priv = dev_get_drvdata(d); + struct iwl_priv *priv = dev_get_drvdata(d); struct iwl_spectrum_notification measure_report; u32 size = sizeof(measure_report), len = 0, ofs = 0; u8 *data = (u8 *)&measure_report; @@ -7354,7 +7354,7 @@ static ssize_t store_measurement(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl3945_priv *priv = dev_get_drvdata(d); + struct iwl_priv *priv = dev_get_drvdata(d); struct ieee80211_measurement_params params = { .channel = le16_to_cpu(priv->active39_rxon.channel), .start_time = cpu_to_le64(priv->last_tsf), @@ -7393,7 +7393,7 @@ static ssize_t store_retry_rate(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl3945_priv *priv = dev_get_drvdata(d); + struct iwl_priv *priv = dev_get_drvdata(d); priv->retry_rate = simple_strtoul(buf, NULL, 0); if (priv->retry_rate <= 0) @@ -7405,7 +7405,7 @@ static ssize_t store_retry_rate(struct device *d, static ssize_t show_retry_rate(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl3945_priv *priv = dev_get_drvdata(d); + struct iwl_priv *priv = dev_get_drvdata(d); return sprintf(buf, "%d", priv->retry_rate); } @@ -7416,7 +7416,7 @@ static ssize_t store_power_level(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl3945_priv *priv = dev_get_drvdata(d); + struct iwl_priv *priv = dev_get_drvdata(d); int rc; int mode; @@ -7471,7 +7471,7 @@ static const s32 period_duration[] = { static ssize_t show_power_level(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl3945_priv *priv = dev_get_drvdata(d); + struct iwl_priv *priv = dev_get_drvdata(d); int level = IWL_POWER_LEVEL(priv->power_mode); char *p = buf; @@ -7515,7 +7515,7 @@ static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL); static ssize_t show_statistics(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl3945_priv *priv = dev_get_drvdata(d); + struct iwl_priv *priv = dev_get_drvdata(d); u32 size = sizeof(struct iwl3945_notif_statistics); u32 len = 0, ofs = 0; u8 *data = (u8 *)&priv->statistics_39; @@ -7553,7 +7553,7 @@ static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL); static ssize_t show_antenna(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl3945_priv *priv = dev_get_drvdata(d); + struct iwl_priv *priv = dev_get_drvdata(d); if (!iwl3945_is_alive(priv)) return -EAGAIN; @@ -7566,7 +7566,7 @@ static ssize_t store_antenna(struct device *d, const char *buf, size_t count) { int ant; - struct iwl3945_priv *priv = dev_get_drvdata(d); + struct iwl_priv *priv = dev_get_drvdata(d); if (count == 0) return 0; @@ -7591,7 +7591,7 @@ static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, show_antenna, store_antenna); static ssize_t show_status(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data; + struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; if (!iwl3945_is_alive(priv)) return -EAGAIN; return sprintf(buf, "0x%08x\n", (int)priv->status); @@ -7606,7 +7606,7 @@ static ssize_t dump_error_log(struct device *d, char *p = (char *)buf; if (p[0] == '1') - iwl3945_dump_nic_error_log((struct iwl3945_priv *)d->driver_data); + iwl3945_dump_nic_error_log((struct iwl_priv *)d->driver_data); return strnlen(buf, count); } @@ -7620,7 +7620,7 @@ static ssize_t dump_event_log(struct device *d, char *p = (char *)buf; if (p[0] == '1') - iwl3945_dump_nic_event_log((struct iwl3945_priv *)d->driver_data); + iwl3945_dump_nic_event_log((struct iwl_priv *)d->driver_data); return strnlen(buf, count); } @@ -7633,7 +7633,7 @@ static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log); * *****************************************************************************/ -static void iwl3945_setup_deferred_work(struct iwl3945_priv *priv) +static void iwl3945_setup_deferred_work(struct iwl_priv *priv) { priv->workqueue = create_workqueue(DRV_NAME); @@ -7657,7 +7657,7 @@ static void iwl3945_setup_deferred_work(struct iwl3945_priv *priv) iwl3945_irq_tasklet, (unsigned long)priv); } -static void iwl3945_cancel_deferred_work(struct iwl3945_priv *priv) +static void iwl3945_cancel_deferred_work(struct iwl_priv *priv) { iwl3945_hw_cancel_deferred_work(priv); @@ -7714,7 +7714,7 @@ static struct ieee80211_ops iwl3945_hw_ops = { static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int err = 0; - struct iwl3945_priv *priv; + struct iwl_priv *priv; struct ieee80211_hw *hw; struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); unsigned long flags; @@ -7725,7 +7725,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e /* mac80211 allocates memory for this device instance, including * space for this driver's private structure */ - hw = ieee80211_alloc_hw(sizeof(struct iwl3945_priv), &iwl3945_hw_ops); + hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), &iwl3945_hw_ops); if (hw == NULL) { printk(KERN_ERR DRV_NAME "Can not allocate network device\n"); err = -ENOMEM; @@ -7988,7 +7988,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) { - struct iwl3945_priv *priv = pci_get_drvdata(pdev); + struct iwl_priv *priv = pci_get_drvdata(pdev); unsigned long flags; if (!priv) @@ -8051,7 +8051,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state) { - struct iwl3945_priv *priv = pci_get_drvdata(pdev); + struct iwl_priv *priv = pci_get_drvdata(pdev); if (priv->is_open) { set_bit(STATUS_IN_SUSPEND, &priv->status); @@ -8066,7 +8066,7 @@ static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state) static int iwl3945_pci_resume(struct pci_dev *pdev) { - struct iwl3945_priv *priv = pci_get_drvdata(pdev); + struct iwl_priv *priv = pci_get_drvdata(pdev); pci_set_power_state(pdev, PCI_D0); @@ -8084,7 +8084,7 @@ static int iwl3945_pci_resume(struct pci_dev *pdev) /* software rf-kill from user */ static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state) { - struct iwl3945_priv *priv = data; + struct iwl_priv *priv = data; int err = 0; if (!priv->rfkill) @@ -8117,7 +8117,7 @@ out_unlock: return err; } -int iwl3945_rfkill_init(struct iwl3945_priv *priv) +int iwl3945_rfkill_init(struct iwl_priv *priv) { struct device *device = wiphy_dev(priv->hw->wiphy); int ret = 0; @@ -8160,7 +8160,7 @@ error: return ret; } -void iwl3945_rfkill_unregister(struct iwl3945_priv *priv) +void iwl3945_rfkill_unregister(struct iwl_priv *priv) { if (priv->rfkill) rfkill_unregister(priv->rfkill); @@ -8169,7 +8169,7 @@ void iwl3945_rfkill_unregister(struct iwl3945_priv *priv) } /* set rf-kill to the right state. */ -void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv) +void iwl3945_rfkill_set_hw_state(struct iwl_priv *priv) { if (!priv->rfkill) -- GitLab From 5d49f498a29360592dea4693724fef242278e0d3 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Fri, 19 Dec 2008 10:37:29 +0800 Subject: [PATCH 0723/4982] iwl3945: use iwl-io.h and delete iwl-3945-io.h The patch deletes iwl-3945-io.h and uses iwl-io.h functions. Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-io.h | 404 -------------------- drivers/net/wireless/iwlwifi/iwl-3945.c | 162 ++++---- drivers/net/wireless/iwlwifi/iwl-3945.h | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 230 +++++------ 4 files changed, 197 insertions(+), 601 deletions(-) delete mode 100644 drivers/net/wireless/iwlwifi/iwl-3945-io.h diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-io.h b/drivers/net/wireless/iwlwifi/iwl-3945-io.h deleted file mode 100644 index 0b84815dd69..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-3945-io.h +++ /dev/null @@ -1,404 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#ifndef __iwl3945_io_h__ -#define __iwl3945_io_h__ - -#include - -#include "iwl-debug.h" - -/* - * IO, register, and NIC memory access functions - * - * NOTE on naming convention and macro usage for these - * - * A single _ prefix before a an access function means that no state - * check or debug information is printed when that function is called. - * - * A double __ prefix before an access function means that state is checked - * and the current line number is printed in addition to any other debug output. - * - * The non-prefixed name is the #define that maps the caller into a - * #define that provides the caller's __LINE__ to the double prefix version. - * - * If you wish to call the function without any debug or state checking, - * you should use the single _ prefix version (as is used by dependent IO - * routines, for example _iwl3945_read_direct32 calls the non-check version of - * _iwl3945_read32.) - * - * These declarations are *extremely* useful in quickly isolating code deltas - * which result in misconfiguration of the hardware I/O. In combination with - * git-bisect and the IO debug level you can quickly determine the specific - * commit which breaks the IO sequence to the hardware. - * - */ - -#define _iwl3945_write32(priv, ofs, val) iowrite32((val), (priv)->hw_base + (ofs)) -#ifdef CONFIG_IWL3945_DEBUG -static inline void __iwl3945_write32(const char *f, u32 l, struct iwl_priv *priv, - u32 ofs, u32 val) -{ - IWL_DEBUG_IO("write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l); - _iwl3945_write32(priv, ofs, val); -} -#define iwl3945_write32(priv, ofs, val) \ - __iwl3945_write32(__FILE__, __LINE__, priv, ofs, val) -#else -#define iwl3945_write32(priv, ofs, val) _iwl3945_write32(priv, ofs, val) -#endif - -#define _iwl3945_read32(priv, ofs) ioread32((priv)->hw_base + (ofs)) -#ifdef CONFIG_IWL3945_DEBUG -static inline u32 __iwl3945_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs) -{ - IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l); - return _iwl3945_read32(priv, ofs); -} -#define iwl3945_read32(priv, ofs)__iwl3945_read32(__FILE__, __LINE__, priv, ofs) -#else -#define iwl3945_read32(p, o) _iwl3945_read32(p, o) -#endif - -static inline int _iwl3945_poll_bit(struct iwl_priv *priv, u32 addr, - u32 bits, u32 mask, int timeout) -{ - int i = 0; - - do { - if ((_iwl3945_read32(priv, addr) & mask) == (bits & mask)) - return i; - udelay(10); - i += 10; - } while (i < timeout); - - return -ETIMEDOUT; -} -#ifdef CONFIG_IWL3945_DEBUG -static inline int __iwl3945_poll_bit(const char *f, u32 l, - struct iwl_priv *priv, u32 addr, - u32 bits, u32 mask, int timeout) -{ - int ret = _iwl3945_poll_bit(priv, addr, bits, mask, timeout); - IWL_DEBUG_IO("poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n", - addr, bits, mask, - unlikely(ret == -ETIMEDOUT) ? "timeout" : "", f, l); - return ret; -} -#define iwl3945_poll_bit(priv, addr, bits, mask, timeout) \ - __iwl3945_poll_bit(__FILE__, __LINE__, priv, addr, bits, mask, timeout) -#else -#define iwl3945_poll_bit(p, a, b, m, t) _iwl3945_poll_bit(p, a, b, m, t) -#endif - -static inline void _iwl3945_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) -{ - _iwl3945_write32(priv, reg, _iwl3945_read32(priv, reg) | mask); -} -#ifdef CONFIG_IWL3945_DEBUG -static inline void __iwl3945_set_bit(const char *f, u32 l, - struct iwl_priv *priv, u32 reg, u32 mask) -{ - u32 val = _iwl3945_read32(priv, reg) | mask; - IWL_DEBUG_IO("set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); - _iwl3945_write32(priv, reg, val); -} -#define iwl3945_set_bit(p, r, m) __iwl3945_set_bit(__FILE__, __LINE__, p, r, m) -#else -#define iwl3945_set_bit(p, r, m) _iwl3945_set_bit(p, r, m) -#endif - -static inline void _iwl3945_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) -{ - _iwl3945_write32(priv, reg, _iwl3945_read32(priv, reg) & ~mask); -} -#ifdef CONFIG_IWL3945_DEBUG -static inline void __iwl3945_clear_bit(const char *f, u32 l, - struct iwl_priv *priv, u32 reg, u32 mask) -{ - u32 val = _iwl3945_read32(priv, reg) & ~mask; - IWL_DEBUG_IO("clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); - _iwl3945_write32(priv, reg, val); -} -#define iwl3945_clear_bit(p, r, m) __iwl3945_clear_bit(__FILE__, __LINE__, p, r, m) -#else -#define iwl3945_clear_bit(p, r, m) _iwl3945_clear_bit(p, r, m) -#endif - -static inline int _iwl3945_grab_nic_access(struct iwl_priv *priv) -{ - int ret; -#ifdef CONFIG_IWL3945_DEBUG - if (atomic_read(&priv->restrict_refcnt)) - return 0; -#endif - /* this bit wakes up the NIC */ - _iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - ret = _iwl3945_poll_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, - (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | - CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 50); - if (ret < 0) { - IWL_ERROR("MAC is in deep sleep!\n"); - return -EIO; - } - -#ifdef CONFIG_IWL3945_DEBUG - atomic_inc(&priv->restrict_refcnt); -#endif - return 0; -} - -#ifdef CONFIG_IWL3945_DEBUG -static inline int __iwl3945_grab_nic_access(const char *f, u32 l, - struct iwl_priv *priv) -{ - if (atomic_read(&priv->restrict_refcnt)) - IWL_DEBUG_INFO("Grabbing access while already held at " - "line %d.\n", l); - - IWL_DEBUG_IO("grabbing nic access - %s %d\n", f, l); - return _iwl3945_grab_nic_access(priv); -} -#define iwl3945_grab_nic_access(priv) \ - __iwl3945_grab_nic_access(__FILE__, __LINE__, priv) -#else -#define iwl3945_grab_nic_access(priv) \ - _iwl3945_grab_nic_access(priv) -#endif - -static inline void _iwl3945_release_nic_access(struct iwl_priv *priv) -{ -#ifdef CONFIG_IWL3945_DEBUG - if (atomic_dec_and_test(&priv->restrict_refcnt)) -#endif - _iwl3945_clear_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); -} -#ifdef CONFIG_IWL3945_DEBUG -static inline void __iwl3945_release_nic_access(const char *f, u32 l, - struct iwl_priv *priv) -{ - if (atomic_read(&priv->restrict_refcnt) <= 0) - IWL_ERROR("Release unheld nic access at line %d.\n", l); - - IWL_DEBUG_IO("releasing nic access - %s %d\n", f, l); - _iwl3945_release_nic_access(priv); -} -#define iwl3945_release_nic_access(priv) \ - __iwl3945_release_nic_access(__FILE__, __LINE__, priv) -#else -#define iwl3945_release_nic_access(priv) \ - _iwl3945_release_nic_access(priv) -#endif - -static inline u32 _iwl3945_read_direct32(struct iwl_priv *priv, u32 reg) -{ - return _iwl3945_read32(priv, reg); -} -#ifdef CONFIG_IWL3945_DEBUG -static inline u32 __iwl3945_read_direct32(const char *f, u32 l, - struct iwl_priv *priv, u32 reg) -{ - u32 value = _iwl3945_read_direct32(priv, reg); - if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Nic access not held from %s %d\n", f, l); - IWL_DEBUG_IO("read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value, - f, l); - return value; -} -#define iwl3945_read_direct32(priv, reg) \ - __iwl3945_read_direct32(__FILE__, __LINE__, priv, reg) -#else -#define iwl3945_read_direct32 _iwl3945_read_direct32 -#endif - -static inline void _iwl3945_write_direct32(struct iwl_priv *priv, - u32 reg, u32 value) -{ - _iwl3945_write32(priv, reg, value); -} -#ifdef CONFIG_IWL3945_DEBUG -static void __iwl3945_write_direct32(u32 line, - struct iwl_priv *priv, u32 reg, u32 value) -{ - if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Nic access not held from line %d\n", line); - _iwl3945_write_direct32(priv, reg, value); -} -#define iwl3945_write_direct32(priv, reg, value) \ - __iwl3945_write_direct32(__LINE__, priv, reg, value) -#else -#define iwl3945_write_direct32 _iwl3945_write_direct32 -#endif - -static inline void iwl3945_write_reg_buf(struct iwl_priv *priv, - u32 reg, u32 len, u32 *values) -{ - u32 count = sizeof(u32); - - if ((priv != NULL) && (values != NULL)) { - for (; 0 < len; len -= count, reg += count, values++) - _iwl3945_write_direct32(priv, reg, *values); - } -} - -static inline int _iwl3945_poll_direct_bit(struct iwl_priv *priv, - u32 addr, u32 mask, int timeout) -{ - return _iwl3945_poll_bit(priv, addr, mask, mask, timeout); -} - -#ifdef CONFIG_IWL3945_DEBUG -static inline int __iwl3945_poll_direct_bit(const char *f, u32 l, - struct iwl_priv *priv, - u32 addr, u32 mask, int timeout) -{ - int ret = _iwl3945_poll_direct_bit(priv, addr, mask, timeout); - - if (unlikely(ret == -ETIMEDOUT)) - IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) - " - "timedout - %s %d\n", addr, mask, f, l); - else - IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) = 0x%08X " - "- %s %d\n", addr, mask, ret, f, l); - return ret; -} -#define iwl3945_poll_direct_bit(priv, addr, mask, timeout) \ - __iwl3945_poll_direct_bit(__FILE__, __LINE__, priv, addr, mask, timeout) -#else -#define iwl3945_poll_direct_bit _iwl3945_poll_direct_bit -#endif - -static inline u32 _iwl3945_read_prph(struct iwl_priv *priv, u32 reg) -{ - _iwl3945_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); - rmb(); - return _iwl3945_read_direct32(priv, HBUS_TARG_PRPH_RDAT); -} -#ifdef CONFIG_IWL3945_DEBUG -static inline u32 __iwl3945_read_prph(u32 line, struct iwl_priv *priv, u32 reg) -{ - if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Nic access not held from line %d\n", line); - return _iwl3945_read_prph(priv, reg); -} - -#define iwl3945_read_prph(priv, reg) \ - __iwl3945_read_prph(__LINE__, priv, reg) -#else -#define iwl3945_read_prph _iwl3945_read_prph -#endif - -static inline void _iwl3945_write_prph(struct iwl_priv *priv, - u32 addr, u32 val) -{ - _iwl3945_write_direct32(priv, HBUS_TARG_PRPH_WADDR, - ((addr & 0x0000FFFF) | (3 << 24))); - wmb(); - _iwl3945_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val); -} -#ifdef CONFIG_IWL3945_DEBUG -static inline void __iwl3945_write_prph(u32 line, struct iwl_priv *priv, - u32 addr, u32 val) -{ - if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Nic access from line %d\n", line); - _iwl3945_write_prph(priv, addr, val); -} - -#define iwl3945_write_prph(priv, addr, val) \ - __iwl3945_write_prph(__LINE__, priv, addr, val); -#else -#define iwl3945_write_prph _iwl3945_write_prph -#endif - -#define _iwl3945_set_bits_prph(priv, reg, mask) \ - _iwl3945_write_prph(priv, reg, (_iwl3945_read_prph(priv, reg) | mask)) -#ifdef CONFIG_IWL3945_DEBUG -static inline void __iwl3945_set_bits_prph(u32 line, struct iwl_priv *priv, - u32 reg, u32 mask) -{ - if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Nic access not held from line %d\n", line); - - _iwl3945_set_bits_prph(priv, reg, mask); -} -#define iwl3945_set_bits_prph(priv, reg, mask) \ - __iwl3945_set_bits_prph(__LINE__, priv, reg, mask) -#else -#define iwl3945_set_bits_prph _iwl3945_set_bits_prph -#endif - -#define _iwl3945_set_bits_mask_prph(priv, reg, bits, mask) \ - _iwl3945_write_prph(priv, reg, ((_iwl3945_read_prph(priv, reg) & mask) | bits)) - -#ifdef CONFIG_IWL3945_DEBUG -static inline void __iwl3945_set_bits_mask_prph(u32 line, - struct iwl_priv *priv, u32 reg, u32 bits, u32 mask) -{ - if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Nic access not held from line %d\n", line); - _iwl3945_set_bits_mask_prph(priv, reg, bits, mask); -} -#define iwl3945_set_bits_mask_prph(priv, reg, bits, mask) \ - __iwl3945_set_bits_mask_prph(__LINE__, priv, reg, bits, mask) -#else -#define iwl3945_set_bits_mask_prph _iwl3945_set_bits_mask_prph -#endif - -static inline void iwl3945_clear_bits_prph(struct iwl_priv - *priv, u32 reg, u32 mask) -{ - u32 val = _iwl3945_read_prph(priv, reg); - _iwl3945_write_prph(priv, reg, (val & ~mask)); -} - -static inline u32 iwl3945_read_targ_mem(struct iwl_priv *priv, u32 addr) -{ - iwl3945_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr); - rmb(); - return iwl3945_read_direct32(priv, HBUS_TARG_MEM_RDAT); -} - -static inline void iwl3945_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val) -{ - iwl3945_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); - wmb(); - iwl3945_write_direct32(priv, HBUS_TARG_MEM_WDAT, val); -} - -static inline void iwl3945_write_targ_mem_buf(struct iwl_priv *priv, u32 addr, - u32 len, u32 *values) -{ - iwl3945_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); - wmb(); - for (; 0 < len; len -= sizeof(u32), values++) - iwl3945_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values); -} -#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 50e729ed018..328e55f84d9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -156,26 +156,26 @@ void iwl3945_disable_events(struct iwl_priv *priv) return; } - ret = iwl3945_grab_nic_access(priv); + ret = iwl_grab_nic_access(priv); if (ret) { IWL_WARNING("Can not read from adapter at this time.\n"); return; } - disable_ptr = iwl3945_read_targ_mem(priv, base + (4 * sizeof(u32))); - array_size = iwl3945_read_targ_mem(priv, base + (5 * sizeof(u32))); - iwl3945_release_nic_access(priv); + disable_ptr = iwl_read_targ_mem(priv, base + (4 * sizeof(u32))); + array_size = iwl_read_targ_mem(priv, base + (5 * sizeof(u32))); + iwl_release_nic_access(priv); if (IWL_EVT_DISABLE && (array_size == IWL_EVT_DISABLE_SIZE)) { IWL_DEBUG_INFO("Disabling selected uCode log events at 0x%x\n", disable_ptr); - ret = iwl3945_grab_nic_access(priv); + ret = iwl_grab_nic_access(priv); for (i = 0; i < IWL_EVT_DISABLE_SIZE; i++) - iwl3945_write_targ_mem(priv, + iwl_write_targ_mem(priv, disable_ptr + (i * sizeof(u32)), evt_disable[i]); - iwl3945_release_nic_access(priv); + iwl_release_nic_access(priv); } else { IWL_DEBUG_INFO("Selected uCode log events may be disabled\n"); IWL_DEBUG_INFO(" by writing \"1\"s into disable bitmap\n"); @@ -925,7 +925,7 @@ static int iwl3945_nic_set_pwr_src(struct iwl_priv *priv, int pwr_max) unsigned long flags; spin_lock_irqsave(&priv->lock, flags); - rc = iwl3945_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) { spin_unlock_irqrestore(&priv->lock, flags); return rc; @@ -937,23 +937,23 @@ static int iwl3945_nic_set_pwr_src(struct iwl_priv *priv, int pwr_max) rc = pci_read_config_dword(priv->pci_dev, PCI_POWER_SOURCE, &val); if (val & PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT) { - iwl3945_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_PWR_SRC_VAUX, ~APMG_PS_CTRL_MSK_PWR_SRC); - iwl3945_release_nic_access(priv); + iwl_release_nic_access(priv); - iwl3945_poll_bit(priv, CSR_GPIO_IN, + iwl_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VAUX_PWR_SRC, CSR_GPIO_IN_BIT_AUX_POWER, 5000); } else - iwl3945_release_nic_access(priv); + iwl_release_nic_access(priv); } else { - iwl3945_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, ~APMG_PS_CTRL_MSK_PWR_SRC); - iwl3945_release_nic_access(priv); - iwl3945_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC, + iwl_release_nic_access(priv); + iwl_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC, CSR_GPIO_IN_BIT_AUX_POWER, 5000); /* uS */ } spin_unlock_irqrestore(&priv->lock, flags); @@ -967,18 +967,18 @@ static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) unsigned long flags; spin_lock_irqsave(&priv->lock, flags); - rc = iwl3945_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) { spin_unlock_irqrestore(&priv->lock, flags); return rc; } - iwl3945_write_direct32(priv, FH39_RCSR_RBD_BASE(0), rxq->dma_addr); - iwl3945_write_direct32(priv, FH39_RCSR_RPTR_ADDR(0), + iwl_write_direct32(priv, FH39_RCSR_RBD_BASE(0), rxq->dma_addr); + iwl_write_direct32(priv, FH39_RCSR_RPTR_ADDR(0), priv->shared_phys + offsetof(struct iwl3945_shared, rx_read_ptr[0])); - iwl3945_write_direct32(priv, FH39_RCSR_WPTR(0), 0); - iwl3945_write_direct32(priv, FH39_RCSR_CONFIG(0), + iwl_write_direct32(priv, FH39_RCSR_WPTR(0), 0); + iwl_write_direct32(priv, FH39_RCSR_CONFIG(0), FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE | FH39_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE | FH39_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN | @@ -989,9 +989,9 @@ static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) FH39_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH); /* fake read to flush all prev I/O */ - iwl3945_read_direct32(priv, FH39_RSSR_CTRL); + iwl_read_direct32(priv, FH39_RSSR_CTRL); - iwl3945_release_nic_access(priv); + iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); return 0; @@ -1003,30 +1003,30 @@ static int iwl3945_tx_reset(struct iwl_priv *priv) unsigned long flags; spin_lock_irqsave(&priv->lock, flags); - rc = iwl3945_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) { spin_unlock_irqrestore(&priv->lock, flags); return rc; } /* bypass mode */ - iwl3945_write_prph(priv, ALM_SCD_MODE_REG, 0x2); + iwl_write_prph(priv, ALM_SCD_MODE_REG, 0x2); /* RA 0 is active */ - iwl3945_write_prph(priv, ALM_SCD_ARASTAT_REG, 0x01); + iwl_write_prph(priv, ALM_SCD_ARASTAT_REG, 0x01); /* all 6 fifo are active */ - iwl3945_write_prph(priv, ALM_SCD_TXFACT_REG, 0x3f); + iwl_write_prph(priv, ALM_SCD_TXFACT_REG, 0x3f); - iwl3945_write_prph(priv, ALM_SCD_SBYP_MODE_1_REG, 0x010000); - iwl3945_write_prph(priv, ALM_SCD_SBYP_MODE_2_REG, 0x030002); - iwl3945_write_prph(priv, ALM_SCD_TXF4MF_REG, 0x000004); - iwl3945_write_prph(priv, ALM_SCD_TXF5MF_REG, 0x000005); + iwl_write_prph(priv, ALM_SCD_SBYP_MODE_1_REG, 0x010000); + iwl_write_prph(priv, ALM_SCD_SBYP_MODE_2_REG, 0x030002); + iwl_write_prph(priv, ALM_SCD_TXF4MF_REG, 0x000004); + iwl_write_prph(priv, ALM_SCD_TXF5MF_REG, 0x000005); - iwl3945_write_direct32(priv, FH39_TSSR_CBB_BASE, + iwl_write_direct32(priv, FH39_TSSR_CBB_BASE, priv->shared_phys); - iwl3945_write_direct32(priv, FH39_TSSR_MSG_CONFIG, + iwl_write_direct32(priv, FH39_TSSR_MSG_CONFIG, FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON | FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON | FH39_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B | @@ -1035,7 +1035,7 @@ static int iwl3945_tx_reset(struct iwl_priv *priv) FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH | FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH); - iwl3945_release_nic_access(priv); + iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); return 0; @@ -1087,12 +1087,12 @@ int iwl3945_hw_nic_init(struct iwl_priv *priv) iwl3945_power_init_handle(priv); spin_lock_irqsave(&priv->lock, flags); - iwl3945_set_bit(priv, CSR_ANA_PLL_CFG, CSR39_ANA_PLL_CFG_VAL); - iwl3945_set_bit(priv, CSR_GIO_CHICKEN_BITS, + iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR39_ANA_PLL_CFG_VAL); + iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); - iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - rc = iwl3945_poll_direct_bit(priv, CSR_GP_CNTRL, + iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + rc = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); if (rc < 0) { spin_unlock_irqrestore(&priv->lock, flags); @@ -1100,18 +1100,18 @@ int iwl3945_hw_nic_init(struct iwl_priv *priv) return rc; } - rc = iwl3945_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) { spin_unlock_irqrestore(&priv->lock, flags); return rc; } - iwl3945_write_prph(priv, APMG_CLK_EN_REG, + iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT); udelay(20); - iwl3945_set_bits_prph(priv, APMG_PCIDEV_STT_REG, + iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, APMG_PCIDEV_STT_VAL_L1_ACT_DIS); - iwl3945_release_nic_access(priv); + iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); /* Determine HW type */ @@ -1127,17 +1127,17 @@ int iwl3945_hw_nic_init(struct iwl_priv *priv) IWL_DEBUG_INFO("RTP type \n"); else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) { IWL_DEBUG_INFO("3945 RADIO-MB type\n"); - iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BIT_3945_MB); } else { IWL_DEBUG_INFO("3945 RADIO-MM type\n"); - iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BIT_3945_MM); } if (EEPROM_SKU_CAP_OP_MODE_MRC == priv->eeprom39.sku_cap) { IWL_DEBUG_INFO("SKU OP mode is mrc\n"); - iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC); } else IWL_DEBUG_INFO("SKU OP mode is basic\n"); @@ -1145,24 +1145,24 @@ int iwl3945_hw_nic_init(struct iwl_priv *priv) if ((priv->eeprom39.board_revision & 0xF0) == 0xD0) { IWL_DEBUG_INFO("3945ABG revision is 0x%X\n", priv->eeprom39.board_revision); - iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE); } else { IWL_DEBUG_INFO("3945ABG revision is 0x%X\n", priv->eeprom39.board_revision); - iwl3945_clear_bit(priv, CSR_HW_IF_CONFIG_REG, + iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE); } if (priv->eeprom39.almgor_m_version <= 1) { - iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A); IWL_DEBUG_INFO("Card M type A version is 0x%X\n", priv->eeprom39.almgor_m_version); } else { IWL_DEBUG_INFO("Card M type B version is 0x%X\n", priv->eeprom39.almgor_m_version); - iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B); } spin_unlock_irqrestore(&priv->lock, flags); @@ -1194,13 +1194,13 @@ int iwl3945_hw_nic_init(struct iwl_priv *priv) iwl3945_rx_queue_update_write_ptr(priv, rxq); */ - rc = iwl3945_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) { spin_unlock_irqrestore(&priv->lock, flags); return rc; } - iwl3945_write_direct32(priv, FH39_RCSR_WPTR(0), rxq->write & ~7); - iwl3945_release_nic_access(priv); + iwl_write_direct32(priv, FH39_RCSR_WPTR(0), rxq->write & ~7); + iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); @@ -1233,24 +1233,24 @@ void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) unsigned long flags; spin_lock_irqsave(&priv->lock, flags); - if (iwl3945_grab_nic_access(priv)) { + if (iwl_grab_nic_access(priv)) { spin_unlock_irqrestore(&priv->lock, flags); iwl3945_hw_txq_ctx_free(priv); return; } /* stop SCD */ - iwl3945_write_prph(priv, ALM_SCD_MODE_REG, 0); + iwl_write_prph(priv, ALM_SCD_MODE_REG, 0); /* reset TFD queues */ for (txq_id = 0; txq_id < TFD_QUEUE_MAX; txq_id++) { - iwl3945_write_direct32(priv, FH39_TCSR_CONFIG(txq_id), 0x0); - iwl3945_poll_direct_bit(priv, FH39_TSSR_TX_STATUS, + iwl_write_direct32(priv, FH39_TCSR_CONFIG(txq_id), 0x0); + iwl_poll_direct_bit(priv, FH39_TSSR_TX_STATUS, FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id), 1000); } - iwl3945_release_nic_access(priv); + iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); iwl3945_hw_txq_ctx_free(priv); @@ -1265,16 +1265,16 @@ int iwl3945_hw_nic_stop_master(struct iwl_priv *priv) spin_lock_irqsave(&priv->lock, flags); /* set stop master bit */ - iwl3945_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); + iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); - reg_val = iwl3945_read32(priv, CSR_GP_CNTRL); + reg_val = iwl_read32(priv, CSR_GP_CNTRL); if (CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE == (reg_val & CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE)) IWL_DEBUG_INFO("Card in power save, master is already " "stopped\n"); else { - rc = iwl3945_poll_direct_bit(priv, CSR_RESET, + rc = iwl_poll_direct_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); if (rc < 0) { spin_unlock_irqrestore(&priv->lock, flags); @@ -1297,37 +1297,37 @@ int iwl3945_hw_nic_reset(struct iwl_priv *priv) spin_lock_irqsave(&priv->lock, flags); - iwl3945_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); + iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); - iwl3945_poll_direct_bit(priv, CSR_GP_CNTRL, + iwl_poll_direct_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); - rc = iwl3945_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (!rc) { - iwl3945_write_prph(priv, APMG_CLK_CTRL_REG, + iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_BSM_CLK_RQT); udelay(10); - iwl3945_set_bit(priv, CSR_GP_CNTRL, + iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - iwl3945_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0); - iwl3945_write_prph(priv, APMG_RTC_INT_STT_REG, + iwl_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0); + iwl_write_prph(priv, APMG_RTC_INT_STT_REG, 0xFFFFFFFF); /* enable DMA */ - iwl3945_write_prph(priv, APMG_CLK_EN_REG, + iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT); udelay(10); - iwl3945_set_bits_prph(priv, APMG_PS_CTRL_REG, + iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); udelay(5); - iwl3945_clear_bits_prph(priv, APMG_PS_CTRL_REG, + iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); - iwl3945_release_nic_access(priv); + iwl_release_nic_access(priv); } /* Clear the 'host command active' bit... */ @@ -1358,7 +1358,7 @@ static inline int iwl3945_hw_reg_temp_out_of_range(int temperature) int iwl3945_hw_get_temperature(struct iwl_priv *priv) { - return iwl3945_read32(priv, CSR_UCODE_DRV_GP2); + return iwl_read32(priv, CSR_UCODE_DRV_GP2); } /** @@ -2290,19 +2290,19 @@ int iwl3945_hw_rxq_stop(struct iwl_priv *priv) unsigned long flags; spin_lock_irqsave(&priv->lock, flags); - rc = iwl3945_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) { spin_unlock_irqrestore(&priv->lock, flags); return rc; } - iwl3945_write_direct32(priv, FH39_RCSR_CONFIG(0), 0); - rc = iwl3945_poll_direct_bit(priv, FH39_RSSR_STATUS, + iwl_write_direct32(priv, FH39_RCSR_CONFIG(0), 0); + rc = iwl_poll_direct_bit(priv, FH39_RSSR_STATUS, FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); if (rc < 0) IWL_ERROR("Can't stop Rx DMA.\n"); - iwl3945_release_nic_access(priv); + iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); return 0; @@ -2319,24 +2319,24 @@ int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl3945_tx_queue *txq shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32)txq->q.dma_addr); spin_lock_irqsave(&priv->lock, flags); - rc = iwl3945_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) { spin_unlock_irqrestore(&priv->lock, flags); return rc; } - iwl3945_write_direct32(priv, FH39_CBCC_CTRL(txq_id), 0); - iwl3945_write_direct32(priv, FH39_CBCC_BASE(txq_id), 0); + iwl_write_direct32(priv, FH39_CBCC_CTRL(txq_id), 0); + iwl_write_direct32(priv, FH39_CBCC_BASE(txq_id), 0); - iwl3945_write_direct32(priv, FH39_TCSR_CONFIG(txq_id), + iwl_write_direct32(priv, FH39_TCSR_CONFIG(txq_id), FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT | FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF | FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD | FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL | FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE); - iwl3945_release_nic_access(priv); + iwl_release_nic_access(priv); /* fake read to flush all prev. writes */ - iwl3945_read32(priv, FH39_TSSR_CBB_BASE); + iwl_read32(priv, FH39_TSSR_CBB_BASE); spin_unlock_irqrestore(&priv->lock, flags); return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 098ac768ee2..63bf832ef76 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -397,6 +397,6 @@ extern const struct iwl_channel_info *iwl3945_get_channel_info( extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate); /* Requires full declaration of iwl_priv before including */ -#include "iwl-3945-io.h" +#include "iwl-io.h" #endif diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index f80294e6bd9..6bbc887449c 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1411,7 +1411,7 @@ static void get_eeprom_mac(struct iwl_priv *priv, u8 *mac) */ static inline int iwl3945_eeprom_acquire_semaphore(struct iwl_priv *priv) { - _iwl3945_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK); + _iwl_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK); return 0; } @@ -1425,7 +1425,7 @@ static inline int iwl3945_eeprom_acquire_semaphore(struct iwl_priv *priv) int iwl3945_eeprom_init(struct iwl_priv *priv) { u16 *e = (u16 *)&priv->eeprom39; - u32 gp = iwl3945_read32(priv, CSR_EEPROM_GP); + u32 gp = iwl_read32(priv, CSR_EEPROM_GP); int sz = sizeof(priv->eeprom39); int ret; u16 addr; @@ -1452,10 +1452,10 @@ int iwl3945_eeprom_init(struct iwl_priv *priv) for (addr = 0; addr < sz; addr += sizeof(u16)) { u32 r; - _iwl3945_write32(priv, CSR_EEPROM_REG, + _iwl_write32(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); - _iwl3945_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD); - ret = iwl3945_poll_direct_bit(priv, CSR_EEPROM_REG, + _iwl_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD); + ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_READ_VALID_MSK, IWL_EEPROM_ACCESS_TIMEOUT); if (ret < 0) { @@ -1463,7 +1463,7 @@ int iwl3945_eeprom_init(struct iwl_priv *priv) return ret; } - r = _iwl3945_read_direct32(priv, CSR_EEPROM_REG); + r = _iwl_read_direct32(priv, CSR_EEPROM_REG); e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); } @@ -2663,7 +2663,7 @@ static void iwl3945_radio_kill_sw(struct iwl_priv *priv, int disable_radio) /* FIXME: This is a workaround for AP */ if (priv->iw_mode != NL80211_IFTYPE_AP) { spin_lock_irqsave(&priv->lock, flags); - iwl3945_write32(priv, CSR_UCODE_DRV_GP1_SET, + iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_SW_BIT_RFKILL); spin_unlock_irqrestore(&priv->lock, flags); iwl3945_send_card_state(priv, CARD_STATE_CMD_DISABLE, 0); @@ -2673,7 +2673,7 @@ static void iwl3945_radio_kill_sw(struct iwl_priv *priv, int disable_radio) } spin_lock_irqsave(&priv->lock, flags); - iwl3945_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); clear_bit(STATUS_RF_KILL_SW, &priv->status); spin_unlock_irqrestore(&priv->lock, flags); @@ -2682,9 +2682,9 @@ static void iwl3945_radio_kill_sw(struct iwl_priv *priv, int disable_radio) msleep(10); spin_lock_irqsave(&priv->lock, flags); - iwl3945_read32(priv, CSR_UCODE_DRV_GP1); - if (!iwl3945_grab_nic_access(priv)) - iwl3945_release_nic_access(priv); + iwl_read32(priv, CSR_UCODE_DRV_GP1); + if (!iwl_grab_nic_access(priv)) + iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { @@ -3151,7 +3151,7 @@ static void iwl3945_rx_card_state_notif(struct iwl_priv *priv, (flags & HW_CARD_DISABLED) ? "Kill" : "On", (flags & SW_CARD_DISABLED) ? "Kill" : "On"); - iwl3945_write32(priv, CSR_UCODE_DRV_GP1_SET, + iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); if (flags & HW_CARD_DISABLED) @@ -3386,27 +3386,27 @@ int iwl3945_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue /* If power-saving is in use, make sure device is awake */ if (test_bit(STATUS_POWER_PMI, &priv->status)) { - reg = iwl3945_read32(priv, CSR_UCODE_DRV_GP1); + reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { - iwl3945_set_bit(priv, CSR_GP_CNTRL, + iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); goto exit_unlock; } - rc = iwl3945_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) goto exit_unlock; /* Device expects a multiple of 8 */ - iwl3945_write_direct32(priv, FH39_RSCSR_CHNL0_WPTR, + iwl_write_direct32(priv, FH39_RSCSR_CHNL0_WPTR, q->write & ~0x7); - iwl3945_release_nic_access(priv); + iwl_release_nic_access(priv); /* Else device is assumed to be awake */ } else /* Device expects a multiple of 8 */ - iwl3945_write32(priv, FH39_RSCSR_CHNL0_WPTR, q->write & ~0x7); + iwl_write32(priv, FH39_RSCSR_CHNL0_WPTR, q->write & ~0x7); q->need_update = 0; @@ -3843,27 +3843,27 @@ static int iwl3945_tx_queue_update_write_ptr(struct iwl_priv *priv, /* wake up nic if it's powered down ... * uCode will wake up, and interrupt us again, so next * time we'll skip this part. */ - reg = iwl3945_read32(priv, CSR_UCODE_DRV_GP1); + reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { IWL_DEBUG_INFO("Requesting wakeup, GP1 = 0x%x\n", reg); - iwl3945_set_bit(priv, CSR_GP_CNTRL, + iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); return rc; } /* restore this queue's parameters in nic hardware. */ - rc = iwl3945_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) return rc; - iwl3945_write_direct32(priv, HBUS_TARG_WRPTR, + iwl_write_direct32(priv, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); - iwl3945_release_nic_access(priv); + iwl_release_nic_access(priv); /* else not in power-save mode, uCode will never sleep when we're * trying to tx (during RFKILL, we're not trying to tx). */ } else - iwl3945_write32(priv, HBUS_TARG_WRPTR, + iwl_write32(priv, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); txq->need_update = 0; @@ -3895,7 +3895,7 @@ static void iwl3945_enable_interrupts(struct iwl_priv *priv) { IWL_DEBUG_ISR("Enabling interrupts\n"); set_bit(STATUS_INT_ENABLED, &priv->status); - iwl3945_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK); + iwl_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK); } @@ -3913,12 +3913,12 @@ static inline void iwl3945_disable_interrupts(struct iwl_priv *priv) clear_bit(STATUS_INT_ENABLED, &priv->status); /* disable interrupts from uCode/NIC to host */ - iwl3945_write32(priv, CSR_INT_MASK, 0x00000000); + iwl_write32(priv, CSR_INT_MASK, 0x00000000); /* acknowledge/clear/reset any interrupts still pending * from uCode or flow handler (Rx/Tx DMA) */ - iwl3945_write32(priv, CSR_INT, 0xffffffff); - iwl3945_write32(priv, CSR_FH_INT_STATUS, 0xffffffff); + iwl_write32(priv, CSR_INT, 0xffffffff); + iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff); IWL_DEBUG_ISR("Disabled interrupts\n"); } @@ -3959,13 +3959,13 @@ static void iwl3945_dump_nic_error_log(struct iwl_priv *priv) return; } - rc = iwl3945_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) { IWL_WARNING("Can not read from adapter at this time.\n"); return; } - count = iwl3945_read_targ_mem(priv, base); + count = iwl_read_targ_mem(priv, base); if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { IWL_ERROR("Start IWL Error Log Dump:\n"); @@ -3977,19 +3977,19 @@ static void iwl3945_dump_nic_error_log(struct iwl_priv *priv) for (i = ERROR_START_OFFSET; i < (count * ERROR_ELEM_SIZE) + ERROR_START_OFFSET; i += ERROR_ELEM_SIZE) { - desc = iwl3945_read_targ_mem(priv, base + i); + desc = iwl_read_targ_mem(priv, base + i); time = - iwl3945_read_targ_mem(priv, base + i + 1 * sizeof(u32)); + iwl_read_targ_mem(priv, base + i + 1 * sizeof(u32)); blink1 = - iwl3945_read_targ_mem(priv, base + i + 2 * sizeof(u32)); + iwl_read_targ_mem(priv, base + i + 2 * sizeof(u32)); blink2 = - iwl3945_read_targ_mem(priv, base + i + 3 * sizeof(u32)); + iwl_read_targ_mem(priv, base + i + 3 * sizeof(u32)); ilink1 = - iwl3945_read_targ_mem(priv, base + i + 4 * sizeof(u32)); + iwl_read_targ_mem(priv, base + i + 4 * sizeof(u32)); ilink2 = - iwl3945_read_targ_mem(priv, base + i + 5 * sizeof(u32)); + iwl_read_targ_mem(priv, base + i + 5 * sizeof(u32)); data1 = - iwl3945_read_targ_mem(priv, base + i + 6 * sizeof(u32)); + iwl_read_targ_mem(priv, base + i + 6 * sizeof(u32)); IWL_ERROR ("%-13s (#%d) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n", @@ -3997,7 +3997,7 @@ static void iwl3945_dump_nic_error_log(struct iwl_priv *priv) ilink1, ilink2, data1); } - iwl3945_release_nic_access(priv); + iwl_release_nic_access(priv); } @@ -4006,7 +4006,7 @@ static void iwl3945_dump_nic_error_log(struct iwl_priv *priv) /** * iwl3945_print_event_log - Dump error event log to syslog * - * NOTE: Must be called with iwl3945_grab_nic_access() already obtained! + * NOTE: Must be called with iwl_grab_nic_access() already obtained! */ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, u32 num_events, u32 mode) @@ -4032,14 +4032,14 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, /* "time" is actually "data" for mode 0 (no timestamp). * place event id # at far right for easier visual parsing. */ for (i = 0; i < num_events; i++) { - ev = iwl3945_read_targ_mem(priv, ptr); + ev = iwl_read_targ_mem(priv, ptr); ptr += sizeof(u32); - time = iwl3945_read_targ_mem(priv, ptr); + time = iwl_read_targ_mem(priv, ptr); ptr += sizeof(u32); if (mode == 0) IWL_ERROR("0x%08x\t%04u\n", time, ev); /* data, ev */ else { - data = iwl3945_read_targ_mem(priv, ptr); + data = iwl_read_targ_mem(priv, ptr); ptr += sizeof(u32); IWL_ERROR("%010u\t0x%08x\t%04u\n", time, data, ev); } @@ -4062,24 +4062,24 @@ static void iwl3945_dump_nic_event_log(struct iwl_priv *priv) return; } - rc = iwl3945_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) { IWL_WARNING("Can not read from adapter at this time.\n"); return; } /* event log header */ - capacity = iwl3945_read_targ_mem(priv, base); - mode = iwl3945_read_targ_mem(priv, base + (1 * sizeof(u32))); - num_wraps = iwl3945_read_targ_mem(priv, base + (2 * sizeof(u32))); - next_entry = iwl3945_read_targ_mem(priv, base + (3 * sizeof(u32))); + capacity = iwl_read_targ_mem(priv, base); + mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); + num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); + next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); size = num_wraps ? capacity : next_entry; /* bail out if nothing in log */ if (size == 0) { IWL_ERROR("Start IWL Event Log Dump: nothing in log\n"); - iwl3945_release_nic_access(priv); + iwl_release_nic_access(priv); return; } @@ -4095,7 +4095,7 @@ static void iwl3945_dump_nic_event_log(struct iwl_priv *priv) /* (then/else) start at top of log */ iwl3945_print_event_log(priv, 0, next_entry, mode); - iwl3945_release_nic_access(priv); + iwl_release_nic_access(priv); } /** @@ -4167,19 +4167,19 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) /* Ack/clear/reset pending uCode interrupts. * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, * and will clear only when CSR_FH_INT_STATUS gets cleared. */ - inta = iwl3945_read32(priv, CSR_INT); - iwl3945_write32(priv, CSR_INT, inta); + inta = iwl_read32(priv, CSR_INT); + iwl_write32(priv, CSR_INT, inta); /* Ack/clear/reset pending flow-handler (DMA) interrupts. * Any new interrupts that happen after this, either while we're * in this tasklet, or later, will show up in next ISR/tasklet. */ - inta_fh = iwl3945_read32(priv, CSR_FH_INT_STATUS); - iwl3945_write32(priv, CSR_FH_INT_STATUS, inta_fh); + inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); + iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh); #ifdef CONFIG_IWL3945_DEBUG if (priv->debug_level & IWL_DL_ISR) { /* just for debug */ - inta_mask = iwl3945_read32(priv, CSR_INT_MASK); + inta_mask = iwl_read32(priv, CSR_INT_MASK); IWL_DEBUG_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", inta, inta_mask, inta_fh); } @@ -4258,11 +4258,11 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) if (inta & CSR_INT_BIT_FH_TX) { IWL_DEBUG_ISR("Tx interrupt\n"); - iwl3945_write32(priv, CSR_FH_INT_STATUS, (1 << 6)); - if (!iwl3945_grab_nic_access(priv)) { - iwl3945_write_direct32(priv, FH39_TCSR_CREDIT + iwl_write32(priv, CSR_FH_INT_STATUS, (1 << 6)); + if (!iwl_grab_nic_access(priv)) { + iwl_write_direct32(priv, FH39_TCSR_CREDIT (FH39_SRVC_CHNL), 0x0); - iwl3945_release_nic_access(priv); + iwl_release_nic_access(priv); } handled |= CSR_INT_BIT_FH_TX; } @@ -4283,9 +4283,9 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) #ifdef CONFIG_IWL3945_DEBUG if (priv->debug_level & (IWL_DL_ISR)) { - inta = iwl3945_read32(priv, CSR_INT); - inta_mask = iwl3945_read32(priv, CSR_INT_MASK); - inta_fh = iwl3945_read32(priv, CSR_FH_INT_STATUS); + inta = iwl_read32(priv, CSR_INT); + inta_mask = iwl_read32(priv, CSR_INT_MASK); + inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); IWL_DEBUG_ISR("End inta 0x%08x, enabled 0x%08x, fh 0x%08x, " "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags); } @@ -4307,12 +4307,12 @@ static irqreturn_t iwl3945_isr(int irq, void *data) * back-to-back ISRs and sporadic interrupts from our NIC. * If we have something to service, the tasklet will re-enable ints. * If we *don't* have something, we'll re-enable before leaving here. */ - inta_mask = iwl3945_read32(priv, CSR_INT_MASK); /* just for debug */ - iwl3945_write32(priv, CSR_INT_MASK, 0x00000000); + inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ + iwl_write32(priv, CSR_INT_MASK, 0x00000000); /* Discover which interrupts are active/pending */ - inta = iwl3945_read32(priv, CSR_INT); - inta_fh = iwl3945_read32(priv, CSR_FH_INT_STATUS); + inta = iwl_read32(priv, CSR_INT); + inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); /* Ignore interrupt if there's nothing in NIC to service. * This may be due to IRQ shared with another device, @@ -4937,11 +4937,11 @@ static int iwl3945_verify_inst_full(struct iwl_priv *priv, __le32 *image, u32 le IWL_DEBUG_INFO("ucode inst image size is %u\n", len); - rc = iwl3945_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) return rc; - iwl3945_write_direct32(priv, HBUS_TARG_MEM_RADDR, + iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, IWL39_RTC_INST_LOWER_BOUND); errcnt = 0; @@ -4949,7 +4949,7 @@ static int iwl3945_verify_inst_full(struct iwl_priv *priv, __le32 *image, u32 le /* read data comes through single port, auto-incr addr */ /* NOTE: Use the debugless read so we don't flood kernel log * if IWL_DL_IO is set */ - val = _iwl3945_read_direct32(priv, HBUS_TARG_MEM_RDAT); + val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); if (val != le32_to_cpu(*image)) { IWL_ERROR("uCode INST section is invalid at " "offset 0x%x, is 0x%x, s/b 0x%x\n", @@ -4961,7 +4961,7 @@ static int iwl3945_verify_inst_full(struct iwl_priv *priv, __le32 *image, u32 le } } - iwl3945_release_nic_access(priv); + iwl_release_nic_access(priv); if (!errcnt) IWL_DEBUG_INFO("ucode image in INSTRUCTION memory is good\n"); @@ -4984,7 +4984,7 @@ static int iwl3945_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 IWL_DEBUG_INFO("ucode inst image size is %u\n", len); - rc = iwl3945_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) return rc; @@ -4992,9 +4992,9 @@ static int iwl3945_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 /* read data comes through single port, auto-incr addr */ /* NOTE: Use the debugless read so we don't flood kernel log * if IWL_DL_IO is set */ - iwl3945_write_direct32(priv, HBUS_TARG_MEM_RADDR, + iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, i + IWL39_RTC_INST_LOWER_BOUND); - val = _iwl3945_read_direct32(priv, HBUS_TARG_MEM_RDAT); + val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); if (val != le32_to_cpu(*image)) { #if 0 /* Enable this if you want to see details */ IWL_ERROR("uCode INST section is invalid at " @@ -5008,7 +5008,7 @@ static int iwl3945_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 } } - iwl3945_release_nic_access(priv); + iwl_release_nic_access(priv); return rc; } @@ -5075,11 +5075,11 @@ static int iwl3945_verify_bsm(struct iwl_priv *priv) IWL_DEBUG_INFO("Begin verify bsm\n"); /* verify BSM SRAM contents */ - val = iwl3945_read_prph(priv, BSM_WR_DWCOUNT_REG); + val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG); for (reg = BSM_SRAM_LOWER_BOUND; reg < BSM_SRAM_LOWER_BOUND + len; reg += sizeof(u32), image++) { - val = iwl3945_read_prph(priv, reg); + val = iwl_read_prph(priv, reg); if (val != le32_to_cpu(*image)) { IWL_ERROR("BSM uCode verification failed at " "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n", @@ -5156,42 +5156,42 @@ static int iwl3945_load_bsm(struct iwl_priv *priv) inst_len = priv->ucode_init.len; data_len = priv->ucode_init_data.len; - rc = iwl3945_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) return rc; - iwl3945_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); - iwl3945_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); - iwl3945_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len); - iwl3945_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len); + iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); + iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); + iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len); + iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len); /* Fill BSM memory with bootstrap instructions */ for (reg_offset = BSM_SRAM_LOWER_BOUND; reg_offset < BSM_SRAM_LOWER_BOUND + len; reg_offset += sizeof(u32), image++) - _iwl3945_write_prph(priv, reg_offset, + _iwl_write_prph(priv, reg_offset, le32_to_cpu(*image)); rc = iwl3945_verify_bsm(priv); if (rc) { - iwl3945_release_nic_access(priv); + iwl_release_nic_access(priv); return rc; } /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */ - iwl3945_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0); - iwl3945_write_prph(priv, BSM_WR_MEM_DST_REG, + iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0); + iwl_write_prph(priv, BSM_WR_MEM_DST_REG, IWL39_RTC_INST_LOWER_BOUND); - iwl3945_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32)); + iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32)); /* Load bootstrap code into instruction SRAM now, * to prepare to load "initialize" uCode */ - iwl3945_write_prph(priv, BSM_WR_CTRL_REG, + iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START); /* Wait for load of bootstrap uCode to finish */ for (i = 0; i < 100; i++) { - done = iwl3945_read_prph(priv, BSM_WR_CTRL_REG); + done = iwl_read_prph(priv, BSM_WR_CTRL_REG); if (!(done & BSM_WR_CTRL_REG_BIT_START)) break; udelay(10); @@ -5205,10 +5205,10 @@ static int iwl3945_load_bsm(struct iwl_priv *priv) /* Enable future boot loads whenever power management unit triggers it * (e.g. when powering back up after power-save shutdown) */ - iwl3945_write_prph(priv, BSM_WR_CTRL_REG, + iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN); - iwl3945_release_nic_access(priv); + iwl_release_nic_access(priv); return 0; } @@ -5216,7 +5216,7 @@ static int iwl3945_load_bsm(struct iwl_priv *priv) static void iwl3945_nic_start(struct iwl_priv *priv) { /* Remove all resets to allow NIC to operate */ - iwl3945_write32(priv, CSR_RESET, 0); + iwl_write32(priv, CSR_RESET, 0); } /** @@ -5477,24 +5477,24 @@ static int iwl3945_set_ucode_ptrs(struct iwl_priv *priv) pdata = priv->ucode_data_backup.p_addr; spin_lock_irqsave(&priv->lock, flags); - rc = iwl3945_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) { spin_unlock_irqrestore(&priv->lock, flags); return rc; } /* Tell bootstrap uCode where to find image to load */ - iwl3945_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); - iwl3945_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); - iwl3945_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, + iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); + iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); + iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, priv->ucode_data.len); /* Inst byte count must be last to set up, bit 31 signals uCode * that all new ptr/size info is in place */ - iwl3945_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, + iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, priv->ucode_code.len | BSM_DRAM_INST_LOAD); - iwl3945_release_nic_access(priv); + iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); @@ -5583,15 +5583,15 @@ static void iwl3945_alive_start(struct iwl_priv *priv) iwl3945_clear_stations_table(priv); - rc = iwl3945_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) { IWL_WARNING("Can not read RFKILL status from adapter\n"); return; } - rfkill = iwl3945_read_prph(priv, APMG_RFKILL_REG); + rfkill = iwl_read_prph(priv, APMG_RFKILL_REG); IWL_DEBUG_INFO("RFKILL status: 0x%x\n", rfkill); - iwl3945_release_nic_access(priv); + iwl_release_nic_access(priv); if (rfkill & 0x1) { clear_bit(STATUS_RF_KILL_HW, &priv->status); @@ -5695,7 +5695,7 @@ static void __iwl3945_down(struct iwl_priv *priv) clear_bit(STATUS_EXIT_PENDING, &priv->status); /* stop and reset the on-board processor */ - iwl3945_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); + iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); /* tell the device to stop sending interrupts */ spin_lock_irqsave(&priv->lock, flags); @@ -5738,24 +5738,24 @@ static void __iwl3945_down(struct iwl_priv *priv) STATUS_EXIT_PENDING; spin_lock_irqsave(&priv->lock, flags); - iwl3945_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); spin_unlock_irqrestore(&priv->lock, flags); iwl3945_hw_txq_ctx_stop(priv); iwl3945_hw_rxq_stop(priv); spin_lock_irqsave(&priv->lock, flags); - if (!iwl3945_grab_nic_access(priv)) { - iwl3945_write_prph(priv, APMG_CLK_DIS_REG, + if (!iwl_grab_nic_access(priv)) { + iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); - iwl3945_release_nic_access(priv); + iwl_release_nic_access(priv); } spin_unlock_irqrestore(&priv->lock, flags); udelay(5); iwl3945_hw_nic_stop_master(priv); - iwl3945_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); + iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); iwl3945_hw_nic_reset(priv); exit: @@ -5801,7 +5801,7 @@ static int __iwl3945_up(struct iwl_priv *priv) } /* If platform's RF_KILL switch is NOT set to KILL */ - if (iwl3945_read32(priv, CSR_GP_CNTRL) & + if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) clear_bit(STATUS_RF_KILL_HW, &priv->status); else { @@ -5812,7 +5812,7 @@ static int __iwl3945_up(struct iwl_priv *priv) } } - iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF); + iwl_write32(priv, CSR_INT, 0xFFFFFFFF); rc = iwl3945_hw_nic_init(priv); if (rc) { @@ -5821,17 +5821,17 @@ static int __iwl3945_up(struct iwl_priv *priv) } /* make sure rfkill handshake bits are cleared */ - iwl3945_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl3945_write32(priv, CSR_UCODE_DRV_GP1_CLR, + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); /* clear (again), then enable host interrupts */ - iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF); + iwl_write32(priv, CSR_INT, 0xFFFFFFFF); iwl3945_enable_interrupts(priv); /* really make sure rfkill handshake bits are cleared */ - iwl3945_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl3945_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); /* Copy original ucode data image from disk into backup cache. * This will be used to initialize the on-board processor's @@ -7819,11 +7819,11 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e pci_write_config_byte(pdev, 0x41, 0x00); /* nic init */ - iwl3945_set_bit(priv, CSR_GIO_CHICKEN_BITS, + iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); - iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - err = iwl3945_poll_direct_bit(priv, CSR_GP_CNTRL, + iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + err = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); if (err < 0) { IWL_DEBUG_INFO("Failed to init the card\n"); -- GitLab From 146846aed534aa0eb1fb0a8e6c0394190e5c1ad7 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Fri, 19 Dec 2008 10:37:30 +0800 Subject: [PATCH 0724/4982] iwlwifi: add more comments to IWL_DL_xx This adds more comments to IWL_DL_xx macros. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-debug.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 0617965c968..fa0eb8f20cd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -133,30 +133,32 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) #define IWL_DL_MACDUMP (1 << 4) #define IWL_DL_HCMD_DUMP (1 << 5) #define IWL_DL_RADIO (1 << 7) - +/* 0x00000F00 - 0x00000100 */ #define IWL_DL_POWER (1 << 8) #define IWL_DL_TEMP (1 << 9) #define IWL_DL_NOTIF (1 << 10) #define IWL_DL_SCAN (1 << 11) - +/* 0x0000F000 - 0x00001000 */ #define IWL_DL_ASSOC (1 << 12) #define IWL_DL_DROP (1 << 13) #define IWL_DL_TXPOWER (1 << 14) #define IWL_DL_AP (1 << 15) - +/* 0x000F0000 - 0x00010000 */ #define IWL_DL_FW (1 << 16) #define IWL_DL_RF_KILL (1 << 17) #define IWL_DL_FW_ERRORS (1 << 18) #define IWL_DL_LED (1 << 19) - +/* 0x00F00000 - 0x00100000 */ #define IWL_DL_RATE (1 << 20) #define IWL_DL_CALIB (1 << 21) #define IWL_DL_WEP (1 << 22) #define IWL_DL_TX (1 << 23) +/* 0x0F000000 - 0x01000000 */ #define IWL_DL_RX (1 << 24) #define IWL_DL_ISR (1 << 25) #define IWL_DL_HT (1 << 26) #define IWL_DL_IO (1 << 27) +/* 0xF0000000 - 0x10000000 */ #define IWL_DL_11H (1 << 28) #define IWL_DL_STATS (1 << 29) #define IWL_DL_TX_REPLY (1 << 30) -- GitLab From 978785a3892b34448446e8c8a17f48454f1bdd6a Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 19 Dec 2008 10:37:31 +0800 Subject: [PATCH 0725/4982] iwlwifi: clean up printing Use IWL_ macros where possible to unify debug output usage. Define new unconditional printouts IWL_ERR, IWL_WARN, IWL_INFO, and IWL_CRIT which don't use hidden priv pointer. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 36 +++++++++---------- drivers/net/wireless/iwlwifi/iwl-agn.c | 24 ++++++------- drivers/net/wireless/iwlwifi/iwl-core.c | 8 ++--- drivers/net/wireless/iwlwifi/iwl-debug.h | 12 ++++--- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 3 -- drivers/net/wireless/iwlwifi/iwl-rx.c | 3 +- drivers/net/wireless/iwlwifi/iwl-tx.c | 4 +-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 38 +++++++++------------ 8 files changed, 58 insertions(+), 70 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 19dd9fd9c09..c0f8b96b9f8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -463,8 +463,9 @@ static int rs_collect_tx_data(struct iwl_rate_scale_data *windows, * Fill uCode API rate_n_flags field, based on "search" or "active" table. */ /* FIXME:RS:remove this function and put the flags statically in the table */ -static u32 rate_n_flags_from_tbl(struct iwl_scale_tbl_info *tbl, - int index, u8 use_green) +static u32 rate_n_flags_from_tbl(struct iwl_priv *priv, + struct iwl_scale_tbl_info *tbl, + int index, u8 use_green) { u32 rate_n_flags = 0; @@ -475,8 +476,7 @@ static u32 rate_n_flags_from_tbl(struct iwl_scale_tbl_info *tbl, } else if (is_Ht(tbl->lq_type)) { if (index > IWL_LAST_OFDM_RATE) { - printk(KERN_ERR RS_NAME": Invalid HT rate index %d\n", - index); + IWL_ERR(priv, "Invalid HT rate index %d\n", index); index = IWL_LAST_OFDM_RATE; } rate_n_flags = RATE_MCS_HT_MSK; @@ -488,8 +488,7 @@ static u32 rate_n_flags_from_tbl(struct iwl_scale_tbl_info *tbl, else rate_n_flags |= iwl_rates[index].plcp_mimo3; } else { - printk(KERN_ERR RS_NAME": Invalid tbl->lq_type %d\n", - tbl->lq_type); + IWL_ERR(priv, "Invalid tbl->lq_type %d\n", tbl->lq_type); } rate_n_flags |= ((tbl->ant_type << RATE_MCS_ANT_POS) & @@ -509,8 +508,7 @@ static u32 rate_n_flags_from_tbl(struct iwl_scale_tbl_info *tbl, rate_n_flags |= RATE_MCS_GF_MSK; if (is_siso(tbl->lq_type) && tbl->is_SGI) { rate_n_flags &= ~RATE_MCS_SGI_MSK; - printk(KERN_ERR RS_NAME - ": GF was set with SGI:SISO\n"); + IWL_ERR(priv, "GF was set with SGI:SISO\n"); } } } @@ -761,7 +759,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, low = scale_index; out: - return rate_n_flags_from_tbl(tbl, low, is_green); + return rate_n_flags_from_tbl(lq_sta->drv, tbl, low, is_green); } /* @@ -1179,7 +1177,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, rate, rate_mask); return -1; } - tbl->current_rate = rate_n_flags_from_tbl(tbl, rate, is_green); + tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, rate, is_green); IWL_DEBUG_RATE("LQ: Switch to new mcs %X index is green %X\n", tbl->current_rate, is_green); @@ -1239,7 +1237,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv, rate, rate_mask); return -1; } - tbl->current_rate = rate_n_flags_from_tbl(tbl, rate, is_green); + tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, rate, is_green); IWL_DEBUG_RATE("LQ: Switch to new mcs %X index is green %X\n", tbl->current_rate, is_green); return 0; @@ -1442,8 +1440,9 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, if (tpt >= search_tbl->expected_tpt[index]) break; } - search_tbl->current_rate = rate_n_flags_from_tbl( - search_tbl, index, is_green); + search_tbl->current_rate = + rate_n_flags_from_tbl(priv, search_tbl, + index, is_green); goto out; } tbl->action++; @@ -1554,8 +1553,9 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv, if (tpt >= search_tbl->expected_tpt[index]) break; } - search_tbl->current_rate = rate_n_flags_from_tbl( - search_tbl, index, is_green); + search_tbl->current_rate = + rate_n_flags_from_tbl(priv, search_tbl, + index, is_green); goto out; } @@ -1947,7 +1947,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, lq_update: /* Replace uCode's rate table for the destination station. */ if (update_lq) { - rate = rate_n_flags_from_tbl(tbl, index, is_green); + rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); rs_fill_link_cmd(priv, lq_sta, rate); iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); } @@ -2031,7 +2031,7 @@ lq_update: } out: - tbl->current_rate = rate_n_flags_from_tbl(tbl, index, is_green); + tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); i = index; lq_sta->last_txrate_idx = i; @@ -2084,7 +2084,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, if (!rs_is_valid_ant(valid_tx_ant, tbl->ant_type)) rs_toggle_antenna(valid_tx_ant, &rate, tbl); - rate = rate_n_flags_from_tbl(tbl, rate_idx, use_green); + rate = rate_n_flags_from_tbl(priv, tbl, rate_idx, use_green); tbl->current_rate = rate; rs_set_expected_tpt_table(lq_sta, tbl); rs_fill_link_cmd(NULL, lq_sta, rate); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 24e906f75ea..6e8ab2e5f3d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1634,16 +1634,16 @@ static int iwl_read_ucode(struct iwl_priv *priv) goto err_release; } if (api_ver != api_max) - IWL_ERROR("Firmware has old API version. Expected v%u, " + IWL_ERR(priv, "Firmware has old API version. Expected v%u, " "got v%u. New firmware can be obtained " "from http://www.intellinuxwireless.org.\n", api_max, api_ver); - printk(KERN_INFO DRV_NAME " loaded firmware version %u.%u.%u.%u\n", - IWL_UCODE_MAJOR(priv->ucode_ver), - IWL_UCODE_MINOR(priv->ucode_ver), - IWL_UCODE_API(priv->ucode_ver), - IWL_UCODE_SERIAL(priv->ucode_ver)); + IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u\n", + IWL_UCODE_MAJOR(priv->ucode_ver), + IWL_UCODE_MINOR(priv->ucode_ver), + IWL_UCODE_API(priv->ucode_ver), + IWL_UCODE_SERIAL(priv->ucode_ver)); IWL_DEBUG_INFO("f/w package hdr ucode version raw = 0x%x\n", priv->ucode_ver); @@ -3355,8 +3355,7 @@ static ssize_t store_debug_level(struct device *d, ret = strict_strtoul(buf, 0, &val); if (ret) - printk(KERN_INFO DRV_NAME - ": %s is not in hex or decimal form.\n", buf); + IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf); else priv->debug_level = val; @@ -3435,8 +3434,7 @@ static ssize_t store_tx_power(struct device *d, ret = strict_strtoul(buf, 10, &val); if (ret) - printk(KERN_INFO DRV_NAME - ": %s is not in decimal form.\n", buf); + IWL_INFO(priv, "%s is not in decimal form.\n", buf); else iwl_set_tx_power(priv, val, false); @@ -3775,8 +3773,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); /* both attempts failed: */ if (err) { - printk(KERN_WARNING "%s: No suitable DMA available.\n", - DRV_NAME); + IWL_WARN(priv, "No suitable DMA available.\n"); goto out_pci_disable_device; } } @@ -3802,8 +3799,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) IWL_DEBUG_INFO("pci_resource_base = %p\n", priv->hw_base); iwl_hw_detect(priv); - printk(KERN_INFO DRV_NAME - ": Detected Intel Wireless WiFi Link %s REV=0x%X\n", + IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n", priv->cfg->name, priv->hw_rev); /* We disable the RETRY_TIMEOUT register (0x41) to keep diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index bee83d6a51c..4100b155531 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -511,16 +511,14 @@ static int iwlcore_init_geos(struct iwl_priv *priv) if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && priv->cfg->sku & IWL_SKU_A) { - dev_printk(KERN_INFO, &(priv->hw->wiphy->dev), - "Incorrectly detected BG card as ABG. Please send " - "your PCI ID 0x%04X:0x%04X to maintainer.\n", + IWL_INFO(priv, "Incorrectly detected BG card as ABG. " + "Please send your PCI ID 0x%04X:0x%04X to maintainer.\n", priv->pci_dev->device, priv->pci_dev->subsystem_device); priv->cfg->sku &= ~IWL_SKU_A; } - dev_printk(KERN_INFO, &(priv->hw->wiphy->dev), - "Tunable channels: %d 802.11bg, %d 802.11a channels\n", + IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n", priv->bands[IEEE80211_BAND_2GHZ].n_channels, priv->bands[IEEE80211_BAND_5GHZ].n_channels); diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index fa0eb8f20cd..d593b83873e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -31,6 +31,13 @@ struct iwl_priv; +#define IWL_ERROR(f, a...) dev_err(&(priv->pci_dev->dev), f, ## a) +#define IWL_WARNING(f, a...) dev_warn(&(priv->pci_dev->dev), f, ## a) +#define IWL_ERR(p, f, a...) dev_err(&((p)->pci_dev->dev), f, ## a) +#define IWL_WARN(p, f, a...) dev_warn(&((p)->pci_dev->dev), f, ## a) +#define IWL_INFO(p, f, a...) dev_info(&((p)->pci_dev->dev), f, ## a) +#define IWL_CRIT(p, f, a...) dev_crit(&((p)->pci_dev->dev), f, ## a) + #ifdef CONFIG_IWLWIFI_DEBUG #define IWL_DEBUG(level, fmt, args...) \ do { \ @@ -164,11 +171,6 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) #define IWL_DL_TX_REPLY (1 << 30) #define IWL_DL_QOS (1 << 31) -#define IWL_ERROR(f, a...) \ - dev_printk(KERN_ERR, &(priv->hw->wiphy->dev), f, ## a) -#define IWL_WARNING(f, a...) \ - dev_printk(KERN_WARNING, &(priv->hw->wiphy->dev), f, ## a) - #define IWL_DEBUG_INFO(f, a...) IWL_DEBUG(IWL_DL_INFO, f, ## a) #define IWL_DEBUG_MAC80211(f, a...) IWL_DEBUG(IWL_DL_MAC80211, f, ## a) #define IWL_DEBUG_MACDUMP(f, a...) IWL_DEBUG(IWL_DL_MACDUMP, f, ## a) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 1e142fbac61..f27dbb92273 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -172,9 +172,6 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, struct iwl_priv *priv = (struct iwl_priv *)file->private_data; const size_t bufsz = sizeof(buf); - printk(KERN_DEBUG "offset is: 0x%x\tlen is: 0x%x\n", - priv->dbgfs->sram_offset, priv->dbgfs->sram_len); - iwl_grab_nic_access(priv); for (i = priv->dbgfs->sram_len; i > 0; i -= 4) { val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \ diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 610a7c2b0ad..18c630d74a3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -262,8 +262,7 @@ void iwl_rx_allocate(struct iwl_priv *priv) rxb->skb = alloc_skb(priv->hw_params.rx_buf_size + 256, GFP_KERNEL); if (!rxb->skb) { - dev_printk(KERN_CRIT, &(priv->hw->wiphy->dev), - "Can not allocate SKB buffers\n"); + IWL_CRIT(priv, "Can not allocate SKB buffers\n"); /* We don't reschedule replenish work here -- we will * call the restock method and if it still needs * more buffers it will schedule replenish */ diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index b0ee86c6268..13aad392b1b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -802,7 +802,7 @@ static void iwl_tx_cmd_build_hwcrypto(struct iwl_priv *priv, break; default: - printk(KERN_ERR "Unknown encode alg %d\n", keyconf->alg); + IWL_ERR(priv, "Unknown encode alg %d\n", keyconf->alg); break; } } @@ -1334,7 +1334,7 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) return ret; if (tid_data->tfds_in_queue == 0) { - printk(KERN_ERR "HW queue is empty\n"); + IWL_ERR(priv, "HW queue is empty\n"); tid_data->agg.state = IWL_AGG_ON; ieee80211_start_tx_ba_cb_irqsafe(priv->hw, ra, tid); } else { diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 6bbc887449c..14864cc6775 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2239,7 +2239,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, break; default: - printk(KERN_ERR "Unknown encode alg %d\n", keyinfo->alg); + IWL_ERR(priv, "Unknown encode alg %d\n", keyinfo->alg); break; } } @@ -3504,8 +3504,7 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv) alloc_skb(IWL_RX_BUF_SIZE, __GFP_NOWARN | GFP_ATOMIC); if (!rxb->skb) { if (net_ratelimit()) - printk(KERN_CRIT DRV_NAME - ": Can not allocate SKB buffers\n"); + IWL_CRIT(priv, ": Can not allocate SKB buffers\n"); /* We don't reschedule replenish work here -- we will * call the restock method and if it still needs * more buffers it will schedule replenish */ @@ -4874,15 +4873,13 @@ static int iwl3945_init_geos(struct iwl_priv *priv) if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && priv->cfg->sku & IWL_SKU_A) { - printk(KERN_INFO DRV_NAME - ": Incorrectly detected BG card as ABG. Please send " - "your PCI ID 0x%04X:0x%04X to maintainer.\n", - priv->pci_dev->device, priv->pci_dev->subsystem_device); + IWL_INFO(priv, "Incorrectly detected BG card as ABG. " + "Please send your PCI ID 0x%04X:0x%04X to maintainer.\n", + priv->pci_dev->device, priv->pci_dev->subsystem_device); priv->cfg->sku &= ~IWL_SKU_A; } - printk(KERN_INFO DRV_NAME - ": Tunable channels: %d 802.11bg, %d 802.11a channels\n", + IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n", priv->bands[IEEE80211_BAND_2GHZ].n_channels, priv->bands[IEEE80211_BAND_5GHZ].n_channels); @@ -5299,11 +5296,12 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) "from http://www.intellinuxwireless.org.\n", api_max, api_ver); - printk(KERN_INFO DRV_NAME " loaded firmware version %u.%u.%u.%u\n", - IWL_UCODE_MAJOR(priv->ucode_ver), - IWL_UCODE_MINOR(priv->ucode_ver), - IWL_UCODE_API(priv->ucode_ver), - IWL_UCODE_SERIAL(priv->ucode_ver)); + IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u\n", + IWL_UCODE_MAJOR(priv->ucode_ver), + IWL_UCODE_MINOR(priv->ucode_ver), + IWL_UCODE_API(priv->ucode_ver), + IWL_UCODE_SERIAL(priv->ucode_ver)); + IWL_DEBUG_INFO("f/w package hdr ucode version raw = 0x%x\n", priv->ucode_ver); IWL_DEBUG_INFO("f/w package hdr runtime inst size = %u\n", inst_size); @@ -7192,8 +7190,7 @@ static ssize_t store_debug_level(struct device *d, ret = strict_strtoul(buf, 0, &val); if (ret) - printk(KERN_INFO DRV_NAME - ": %s is not in hex or decimal form.\n", buf); + IWL_INFO(priv, "%s is not in hex or decimal form.\n", buf); else priv->debug_level = val; @@ -7235,8 +7232,7 @@ static ssize_t store_tx_power(struct device *d, val = simple_strtoul(p, &p, 10); if (p == buf) - printk(KERN_INFO DRV_NAME - ": %s is not in decimal form.\n", buf); + IWL_INFO(priv, ": %s is not in decimal form.\n", buf); else iwl3945_hw_reg_set_txpower(priv, val); @@ -7792,7 +7788,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e if (!err) err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); if (err) { - printk(KERN_WARNING DRV_NAME ": No suitable DMA available.\n"); + IWL_WARN(priv, "No suitable DMA available.\n"); goto out_pci_disable_device; } @@ -7900,8 +7896,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e goto out_free_channel_map; } - printk(KERN_INFO DRV_NAME - ": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name); + IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s\n", + priv->cfg->name); /*********************************** * 7. Initialize Module Parameters -- GitLab From 39aadf8c29ad959e823efca15381bea9d0770b1e Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Fri, 19 Dec 2008 10:37:32 +0800 Subject: [PATCH 0726/4982] iwlwifi: replace IWL_WARNING with IWL_WARN IWL_WARN doesn't use hidden priv pointer. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 4 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 12 +-- drivers/net/wireless/iwlwifi/iwl-5000.c | 9 ++- .../net/wireless/iwlwifi/iwl-agn-hcmd-check.c | 20 ++--- drivers/net/wireless/iwlwifi/iwl-agn.c | 34 ++++----- drivers/net/wireless/iwlwifi/iwl-core.c | 8 +- drivers/net/wireless/iwlwifi/iwl-debug.h | 1 - drivers/net/wireless/iwlwifi/iwl-rfkill.c | 3 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 4 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 9 ++- drivers/net/wireless/iwlwifi/iwl-tx.c | 4 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 73 ++++++++++--------- 12 files changed, 94 insertions(+), 87 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 328e55f84d9..4a2cc78f0d7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -158,7 +158,7 @@ void iwl3945_disable_events(struct iwl_priv *priv) ret = iwl_grab_nic_access(priv); if (ret) { - IWL_WARNING("Can not read from adapter at this time.\n"); + IWL_WARN(priv, "Can not read from adapter at this time.\n"); return; } @@ -2095,7 +2095,7 @@ static void iwl3945_hw_reg_init_channel_groups(struct iwl_priv *priv) /* sanity check on factory saturation power value */ if (group->saturation_power < 40) { - IWL_WARNING("Error: saturation power is %d, " + IWL_WARN(priv, "Error: saturation power is %d, " "less than minimum expected 40\n", group->saturation_power); return; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 48223627dd2..3de8d641399 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1485,12 +1485,12 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, /* stay within the table! */ if (power_index > 107) { - IWL_WARNING("txpower index %d > 107\n", + IWL_WARN(priv, "txpower index %d > 107\n", power_index); power_index = 107; } if (power_index < 0) { - IWL_WARNING("txpower index %d < 0\n", + IWL_WARN(priv, "txpower index %d < 0\n", power_index); power_index = 0; } @@ -1533,7 +1533,7 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv) /* If this gets hit a lot, switch it to a BUG() and catch * the stack trace to find out who is calling this during * a scan. */ - IWL_WARNING("TX Power requested while scanning!\n"); + IWL_WARN(priv, "TX Power requested while scanning!\n"); return -EAGAIN; } @@ -1839,7 +1839,8 @@ static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) { - IWL_WARNING("queue number out of range: %d, must be %d to %d\n", + IWL_WARN(priv, + "queue number out of range: %d, must be %d to %d\n", txq_id, IWL49_FIRST_AMPDU_QUEUE, IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1); return -EINVAL; @@ -1910,7 +1911,8 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) { - IWL_WARNING("queue number out of range: %d, must be %d to %d\n", + IWL_WARN(priv, + "queue number out of range: %d, must be %d to %d\n", txq_id, IWL49_FIRST_AMPDU_QUEUE, IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1); return -EINVAL; diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 338444ab003..448bdb65bff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -676,7 +676,8 @@ static void iwl5000_init_alive_start(struct iwl_priv *priv) iwl_clear_stations_table(priv); ret = priv->cfg->ops->lib->alive_notify(priv); if (ret) { - IWL_WARNING("Could not complete ALIVE transition: %d\n", ret); + IWL_WARN(priv, + "Could not complete ALIVE transition: %d\n", ret); goto restart; } @@ -1012,7 +1013,8 @@ static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id, if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || (IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) { - IWL_WARNING("queue number out of range: %d, must be %d to %d\n", + IWL_WARN(priv, + "queue number out of range: %d, must be %d to %d\n", txq_id, IWL50_FIRST_AMPDU_QUEUE, IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES - 1); return -EINVAL; @@ -1077,7 +1079,8 @@ static int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || (IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) { - IWL_WARNING("queue number out of range: %d, must be %d to %d\n", + IWL_WARN(priv, + "queue number out of range: %d, must be %d to %d\n", txq_id, IWL50_FIRST_AMPDU_QUEUE, IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES - 1); return -EINVAL; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c index 392d96df0b6..16e656a311a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c @@ -51,53 +51,53 @@ int iwl_agn_check_rxon_cmd(struct iwl_priv *priv) (RXON_FLG_TGJ_NARROW_BAND_MSK | RXON_FLG_RADAR_DETECT_MSK)); if (error) - IWL_WARNING("check 24G fields %d | %d\n", + IWL_WARN(priv, "check 24G fields %d | %d\n", counter++, error); } else { error |= (rxon->flags & RXON_FLG_SHORT_SLOT_MSK) ? 0 : le32_to_cpu(RXON_FLG_SHORT_SLOT_MSK); if (error) - IWL_WARNING("check 52 fields %d | %d\n", + IWL_WARN(priv, "check 52 fields %d | %d\n", counter++, error); error |= le32_to_cpu(rxon->flags & RXON_FLG_CCK_MSK); if (error) - IWL_WARNING("check 52 CCK %d | %d\n", + IWL_WARN(priv, "check 52 CCK %d | %d\n", counter++, error); } error |= (rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1; if (error) - IWL_WARNING("check mac addr %d | %d\n", counter++, error); + IWL_WARN(priv, "check mac addr %d | %d\n", counter++, error); /* make sure basic rates 6Mbps and 1Mbps are supported */ error |= (((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0) && ((rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0)); if (error) - IWL_WARNING("check basic rate %d | %d\n", counter++, error); + IWL_WARN(priv, "check basic rate %d | %d\n", counter++, error); error |= (le16_to_cpu(rxon->assoc_id) > 2007); if (error) - IWL_WARNING("check assoc id %d | %d\n", counter++, error); + IWL_WARN(priv, "check assoc id %d | %d\n", counter++, error); error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) == (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)); if (error) - IWL_WARNING("check CCK and short slot %d | %d\n", + IWL_WARN(priv, "check CCK and short slot %d | %d\n", counter++, error); error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) == (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)); if (error) - IWL_WARNING("check CCK & auto detect %d | %d\n", + IWL_WARN(priv, "check CCK & auto detect %d | %d\n", counter++, error); error |= ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK)) == RXON_FLG_TGG_PROTECT_MSK); if (error) - IWL_WARNING("check TGG and auto detect %d | %d\n", + IWL_WARN(priv, "check TGG and auto detect %d | %d\n", counter++, error); if (error) - IWL_WARNING("Tuning to channel %d\n", + IWL_WARN(priv, "Tuning to channel %d\n", le16_to_cpu(rxon->channel)); if (error) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 6e8ab2e5f3d..ce290f6867f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -337,7 +337,7 @@ static void iwl_clear_free_frames(struct iwl_priv *priv) } if (priv->frames_count) { - IWL_WARNING("%d frames still in use. Did we lose one?\n", + IWL_WARN(priv, "%d frames still in use. Did we lose one?\n", priv->frames_count); priv->frames_count = 0; } @@ -745,7 +745,7 @@ static int iwl_set_mode(struct iwl_priv *priv, int mode) cancel_delayed_work(&priv->scan_check); if (iwl_scan_cancel_timeout(priv, 100)) { - IWL_WARNING("Aborted scan still in progress after 100ms\n"); + IWL_WARN(priv, "Aborted scan still in progress after 100ms\n"); IWL_DEBUG_MAC80211("leaving - scan abort failed.\n"); return -EAGAIN; } @@ -841,7 +841,7 @@ static void iwl_rx_reply_alive(struct iwl_priv *priv, queue_delayed_work(priv->workqueue, pwork, msecs_to_jiffies(5)); else - IWL_WARNING("uCode did not respond OK.\n"); + IWL_WARN(priv, "uCode did not respond OK.\n"); } static void iwl_rx_reply_error(struct iwl_priv *priv, @@ -1193,7 +1193,7 @@ void iwl_rx_handle(struct iwl_priv *priv) if (rxb && rxb->skb) iwl_tx_cmd_complete(priv, rxb); else - IWL_WARNING("Claim null rxb?\n"); + IWL_WARN(priv, "Claim null rxb?\n"); } /* For now we just don't re-use anything. We can tweak this @@ -1457,9 +1457,9 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) IWL_ERROR("Unhandled INTA bits 0x%08x\n", inta & ~handled); if (inta & ~CSR_INI_SET_MASK) { - IWL_WARNING("Disabled INTA bits 0x%08x were pending\n", + IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", inta & ~CSR_INI_SET_MASK); - IWL_WARNING(" with FH_INT = 0x%08x\n", inta_fh); + IWL_WARN(priv, " with FH_INT = 0x%08x\n", inta_fh); } /* Re-enable all interrupts */ @@ -1511,7 +1511,7 @@ static irqreturn_t iwl_isr(int irq, void *data) if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { /* Hardware disappeared. It might have already raised * an interrupt */ - IWL_WARNING("HARDWARE GONE?? INTA == 0x%08x\n", inta); + IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta); goto unplugged; } @@ -1833,8 +1833,8 @@ static void iwl_alive_start(struct iwl_priv *priv) iwl_clear_stations_table(priv); ret = priv->cfg->ops->lib->alive_notify(priv); if (ret) { - IWL_WARNING("Could not complete ALIVE transition [ntf]: %d\n", - ret); + IWL_WARN(priv, + "Could not complete ALIVE transition [ntf]: %d\n", ret); goto restart; } @@ -2020,7 +2020,7 @@ static int __iwl_up(struct iwl_priv *priv) int ret; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { - IWL_WARNING("Exit pending; will not bring the NIC up\n"); + IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); return -EIO; } @@ -2037,7 +2037,7 @@ static int __iwl_up(struct iwl_priv *priv) if (iwl_is_rfkill(priv)) { iwl_enable_interrupts(priv); - IWL_WARNING("Radio disabled by %s RF Kill switch\n", + IWL_WARN(priv, "Radio disabled by %s RF Kill switch\n", test_bit(STATUS_RF_KILL_HW, &priv->status) ? "HW" : "SW"); return 0; } @@ -2163,7 +2163,7 @@ static void iwl_bg_rf_kill(struct work_struct *work) IWL_DEBUG_RF_KILL("Can not turn radio back on - " "disabled by SW switch\n"); else - IWL_WARNING("Radio Frequency Kill Switch is On:\n" + IWL_WARN(priv, "Radio Frequency Kill Switch is On:\n" "Kill switch must be turned off for " "wireless networking to work.\n"); } @@ -2267,7 +2267,7 @@ static void iwl_post_associate(struct iwl_priv *priv) ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, sizeof(priv->rxon_timing), &priv->rxon_timing); if (ret) - IWL_WARNING("REPLY_RXON_TIMING failed - " + IWL_WARN(priv, "REPLY_RXON_TIMING failed - " "Attempting to continue.\n"); priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; @@ -2668,7 +2668,7 @@ static void iwl_config_ap(struct iwl_priv *priv) ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, sizeof(priv->rxon_timing), &priv->rxon_timing); if (ret) - IWL_WARNING("REPLY_RXON_TIMING failed - " + IWL_WARN(priv, "REPLY_RXON_TIMING failed - " "Attempting to continue.\n"); iwl_set_rxon_chain(priv); @@ -2774,7 +2774,7 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, /* If there is currently a HW scan going on in the background * then we need to cancel it else the RXON below will fail. */ if (iwl_scan_cancel_timeout(priv, 100)) { - IWL_WARNING("Aborted scan still in progress " + IWL_WARN(priv, "Aborted scan still in progress " "after 100ms\n"); IWL_DEBUG_MAC80211("leaving - scan abort failed.\n"); mutex_unlock(&priv->mutex); @@ -3467,7 +3467,7 @@ static ssize_t store_flags(struct device *d, if (le32_to_cpu(priv->staging_rxon.flags) != flags) { /* Cancel any currently running scans... */ if (iwl_scan_cancel_timeout(priv, 100)) - IWL_WARNING("Could not cancel scan.\n"); + IWL_WARN(priv, "Could not cancel scan.\n"); else { IWL_DEBUG_INFO("Commit rxon.flags = 0x%04X\n", flags); priv->staging_rxon.flags = cpu_to_le32(flags); @@ -3506,7 +3506,7 @@ static ssize_t store_filter_flags(struct device *d, if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) { /* Cancel any currently running scans... */ if (iwl_scan_cancel_timeout(priv, 100)) - IWL_WARNING("Could not cancel scan.\n"); + IWL_WARN(priv, "Could not cancel scan.\n"); else { IWL_DEBUG_INFO("Committing rxon.filter_flags = " "0x%04X\n", filter_flags); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 4100b155531..2bc461a610a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -924,13 +924,13 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) { int ret = 0; if (tx_power < IWL_TX_POWER_TARGET_POWER_MIN) { - IWL_WARNING("Requested user TXPOWER %d below limit.\n", + IWL_WARN(priv, "Requested user TXPOWER %d below limit.\n", priv->tx_power_user_lmt); return -EINVAL; } if (tx_power > IWL_TX_POWER_TARGET_POWER_MAX) { - IWL_WARNING("Requested user TXPOWER %d above limit.\n", + IWL_WARN(priv, "Requested user TXPOWER %d above limit.\n", priv->tx_power_user_lmt); return -EINVAL; } @@ -1193,7 +1193,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) ret = iwl_grab_nic_access(priv); if (ret) { - IWL_WARNING("Can not read from adapter at this time.\n"); + IWL_WARN(priv, "Can not read from adapter at this time.\n"); return; } @@ -1297,7 +1297,7 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv) ret = iwl_grab_nic_access(priv); if (ret) { - IWL_WARNING("Can not read from adapter at this time.\n"); + IWL_WARN(priv, "Can not read from adapter at this time.\n"); return; } diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index d593b83873e..654dc9cdd23 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -32,7 +32,6 @@ struct iwl_priv; #define IWL_ERROR(f, a...) dev_err(&(priv->pci_dev->dev), f, ## a) -#define IWL_WARNING(f, a...) dev_warn(&(priv->pci_dev->dev), f, ## a) #define IWL_ERR(p, f, a...) dev_err(&((p)->pci_dev->dev), f, ## a) #define IWL_WARN(p, f, a...) dev_warn(&((p)->pci_dev->dev), f, ## a) #define IWL_INFO(p, f, a...) dev_info(&((p)->pci_dev->dev), f, ## a) diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c index 4b69da30665..cece1c56393 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c @@ -62,7 +62,8 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) iwl_radio_kill_sw_disable_radio(priv); break; default: - IWL_WARNING("we received unexpected RFKILL state %d\n", state); + IWL_WARN(priv, "we received unexpected RFKILL state %d\n", + state); break; } out_unlock: diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 3c803f6922e..de55d3c5db6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -650,7 +650,7 @@ static void iwl_bg_request_scan(struct work_struct *data) mutex_lock(&priv->mutex); if (!iwl_is_ready(priv)) { - IWL_WARNING("request scan called when driver not ready.\n"); + IWL_WARN(priv, "request scan called when driver not ready.\n"); goto done; } @@ -773,7 +773,7 @@ static void iwl_bg_request_scan(struct work_struct *data) if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) rx_chain = 0x6; } else { - IWL_WARNING("Invalid scan band count\n"); + IWL_WARN(priv, "Invalid scan band count\n"); goto done; } diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 412f66bac1a..41e9013c742 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -168,7 +168,7 @@ static int iwl_send_add_sta(struct iwl_priv *priv, break; default: ret = -EIO; - IWL_WARNING("REPLY_ADD_STA failed\n"); + IWL_WARN(priv, "REPLY_ADD_STA failed\n"); break; } } @@ -204,7 +204,7 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, case WLAN_HT_CAP_SM_PS_DISABLED: break; default: - IWL_WARNING("Invalid MIMO PS mode %d\n", mimo_ps_mode); + IWL_WARN(priv, "Invalid MIMO PS mode %d\n", mimo_ps_mode); break; } @@ -812,7 +812,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, } if (priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) { - IWL_WARNING("Removing wrong key %d 0x%x\n", + IWL_WARN(priv, "Removing wrong key %d 0x%x\n", keyconf->keyidx, key_flags); spin_unlock_irqrestore(&priv->sta_lock, flags); return 0; @@ -1069,7 +1069,8 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) return priv->hw_params.bcast_sta_id; default: - IWL_WARNING("Unknown mode of operation: %d\n", priv->iw_mode); + IWL_WARN(priv, "Unknown mode of operation: %d\n", + priv->iw_mode); return priv->hw_params.bcast_sta_id; } } diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 13aad392b1b..e829e86181e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -1306,7 +1306,7 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) else return -EINVAL; - IWL_WARNING("%s on ra = %pM tid = %d\n", + IWL_WARN(priv, "%s on ra = %pM tid = %d\n", __func__, ra, tid); sta_id = iwl_find_station(priv, ra); @@ -1369,7 +1369,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) return -ENXIO; if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON) - IWL_WARNING("Stopping AGG while state not IWL_AGG_ON\n"); + IWL_WARN(priv, "Stopping AGG while state not IWL_AGG_ON\n"); tid_data = &priv->stations[sta_id].tid[tid]; ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 14864cc6775..26f53647bf3 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -781,59 +781,59 @@ static int iwl3945_check_rxon_cmd(struct iwl_priv *priv) (RXON_FLG_TGJ_NARROW_BAND_MSK | RXON_FLG_RADAR_DETECT_MSK)); if (error) - IWL_WARNING("check 24G fields %d | %d\n", + IWL_WARN(priv, "check 24G fields %d | %d\n", counter++, error); } else { error |= (rxon->flags & RXON_FLG_SHORT_SLOT_MSK) ? 0 : le32_to_cpu(RXON_FLG_SHORT_SLOT_MSK); if (error) - IWL_WARNING("check 52 fields %d | %d\n", + IWL_WARN(priv, "check 52 fields %d | %d\n", counter++, error); error |= le32_to_cpu(rxon->flags & RXON_FLG_CCK_MSK); if (error) - IWL_WARNING("check 52 CCK %d | %d\n", + IWL_WARN(priv, "check 52 CCK %d | %d\n", counter++, error); } error |= (rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1; if (error) - IWL_WARNING("check mac addr %d | %d\n", counter++, error); + IWL_WARN(priv, "check mac addr %d | %d\n", counter++, error); /* make sure basic rates 6Mbps and 1Mbps are supported */ error |= (((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0) && ((rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0)); if (error) - IWL_WARNING("check basic rate %d | %d\n", counter++, error); + IWL_WARN(priv, "check basic rate %d | %d\n", counter++, error); error |= (le16_to_cpu(rxon->assoc_id) > 2007); if (error) - IWL_WARNING("check assoc id %d | %d\n", counter++, error); + IWL_WARN(priv, "check assoc id %d | %d\n", counter++, error); error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) == (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)); if (error) - IWL_WARNING("check CCK and short slot %d | %d\n", + IWL_WARN(priv, "check CCK and short slot %d | %d\n", counter++, error); error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) == (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)); if (error) - IWL_WARNING("check CCK & auto detect %d | %d\n", + IWL_WARN(priv, "check CCK & auto detect %d | %d\n", counter++, error); error |= ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK)) == RXON_FLG_TGG_PROTECT_MSK); if (error) - IWL_WARNING("check TGG and auto detect %d | %d\n", + IWL_WARN(priv, "check TGG and auto detect %d | %d\n", counter++, error); if ((rxon->flags & RXON_FLG_DIS_DIV_MSK)) error |= ((rxon->flags & (RXON_FLG_ANT_B_MSK | RXON_FLG_ANT_A_MSK)) == 0); if (error) - IWL_WARNING("check antenna %d %d\n", counter++, error); + IWL_WARN(priv, "check antenna %d %d\n", counter++, error); if (error) - IWL_WARNING("Tuning to channel %d\n", + IWL_WARN(priv, "Tuning to channel %d\n", le16_to_cpu(rxon->channel)); if (error) { @@ -1207,7 +1207,7 @@ int iwl3945_send_add_station(struct iwl_priv *priv, break; default: rc = -EIO; - IWL_WARNING("REPLY_ADD_STA failed\n"); + IWL_WARN(priv, "REPLY_ADD_STA failed\n"); break; } } @@ -1289,7 +1289,7 @@ static void iwl3945_clear_free_frames(struct iwl_priv *priv) } if (priv->frames_count) { - IWL_WARNING("%d frames still in use. Did we lose one?\n", + IWL_WARN(priv, "%d frames still in use. Did we lose one?\n", priv->frames_count); priv->frames_count = 0; } @@ -2187,7 +2187,7 @@ static int iwl3945_set_mode(struct iwl_priv *priv, int mode) cancel_delayed_work(&priv->scan_check); if (iwl3945_scan_cancel_timeout(priv, 100)) { - IWL_WARNING("Aborted scan still in progress after 100ms\n"); + IWL_WARN(priv, "Aborted scan still in progress after 100ms\n"); IWL_DEBUG_MAC80211("leaving - scan abort failed.\n"); return -EAGAIN; } @@ -2363,7 +2363,8 @@ static int iwl3945_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) return priv->hw_params.bcast_sta_id; default: - IWL_WARNING("Unknown mode of operation: %d\n", priv->iw_mode); + IWL_WARN(priv, "Unknown mode of operation: %d\n", + priv->iw_mode); return priv->hw_params.bcast_sta_id; } } @@ -2895,7 +2896,7 @@ static void iwl3945_rx_reply_alive(struct iwl_priv *priv, queue_delayed_work(priv->workqueue, pwork, msecs_to_jiffies(5)); else - IWL_WARNING("uCode did not respond OK.\n"); + IWL_WARN(priv, "uCode did not respond OK.\n"); } static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv, @@ -3789,7 +3790,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) if (rxb && rxb->skb) iwl3945_tx_cmd_complete(priv, rxb); else - IWL_WARNING("Claim null rxb?\n"); + IWL_WARN(priv, "Claim null rxb?\n"); } /* For now we just don't re-use anything. We can tweak this @@ -3960,7 +3961,7 @@ static void iwl3945_dump_nic_error_log(struct iwl_priv *priv) rc = iwl_grab_nic_access(priv); if (rc) { - IWL_WARNING("Can not read from adapter at this time.\n"); + IWL_WARN(priv, "Can not read from adapter at this time.\n"); return; } @@ -4063,7 +4064,7 @@ static void iwl3945_dump_nic_event_log(struct iwl_priv *priv) rc = iwl_grab_nic_access(priv); if (rc) { - IWL_WARNING("Can not read from adapter at this time.\n"); + IWL_WARN(priv, "Can not read from adapter at this time.\n"); return; } @@ -4270,9 +4271,9 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) IWL_ERROR("Unhandled INTA bits 0x%08x\n", inta & ~handled); if (inta & ~CSR_INI_SET_MASK) { - IWL_WARNING("Disabled INTA bits 0x%08x were pending\n", + IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", inta & ~CSR_INI_SET_MASK); - IWL_WARNING(" with FH_INT = 0x%08x\n", inta_fh); + IWL_WARN(priv, " with FH_INT = 0x%08x\n", inta_fh); } /* Re-enable all interrupts */ @@ -4323,7 +4324,7 @@ static irqreturn_t iwl3945_isr(int irq, void *data) if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { /* Hardware disappeared */ - IWL_WARNING("HARDWARE GONE?? INTA == 0x%08x\n", inta); + IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta); goto unplugged; } @@ -4490,7 +4491,7 @@ static int iwl3945_init_channel_map(struct iwl_priv *priv) } if (priv->eeprom39.version < 0x2f) { - IWL_WARNING("Unsupported EEPROM version: 0x%04X\n", + IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n", priv->eeprom39.version); return -EINVAL; } @@ -5583,7 +5584,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) rc = iwl_grab_nic_access(priv); if (rc) { - IWL_WARNING("Can not read RFKILL status from adapter\n"); + IWL_WARN(priv, "Can not read RFKILL status from adapter\n"); return; } @@ -5783,12 +5784,12 @@ static int __iwl3945_up(struct iwl_priv *priv) int rc, i; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { - IWL_WARNING("Exit pending; will not bring the NIC up\n"); + IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); return -EIO; } if (test_bit(STATUS_RF_KILL_SW, &priv->status)) { - IWL_WARNING("Radio disabled by SW RF kill (module " + IWL_WARN(priv, "Radio disabled by SW RF kill (module " "parameter)\n"); return -ENODEV; } @@ -5805,7 +5806,7 @@ static int __iwl3945_up(struct iwl_priv *priv) else { set_bit(STATUS_RF_KILL_HW, &priv->status); if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) { - IWL_WARNING("Radio disabled by HW RF Kill switch\n"); + IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n"); return -ENODEV; } } @@ -5929,7 +5930,7 @@ static void iwl3945_bg_rf_kill(struct work_struct *work) IWL_DEBUG_RF_KILL("Can not turn radio back on - " "disabled by SW switch\n"); else - IWL_WARNING("Radio Frequency Kill Switch is On:\n" + IWL_WARN(priv, "Radio Frequency Kill Switch is On:\n" "Kill switch must be turned off for " "wireless networking to work.\n"); } @@ -5982,7 +5983,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) mutex_lock(&priv->mutex); if (!iwl3945_is_ready(priv)) { - IWL_WARNING("request scan called when driver not ready.\n"); + IWL_WARN(priv, "request scan called when driver not ready.\n"); goto done; } @@ -6107,7 +6108,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) scan->good_CRC_th = IWL_GOOD_CRC_TH; band = IEEE80211_BAND_5GHZ; } else { - IWL_WARNING("Invalid scan band count\n"); + IWL_WARN(priv, "Invalid scan band count\n"); goto done; } @@ -6228,7 +6229,7 @@ static void iwl3945_post_associate(struct iwl_priv *priv) rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON_TIMING, sizeof(priv->rxon_timing), &priv->rxon_timing); if (rc) - IWL_WARNING("REPLY_RXON_TIMING failed - " + IWL_WARN(priv, "REPLY_RXON_TIMING failed - " "Attempting to continue.\n"); priv->staging39_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; @@ -6608,7 +6609,7 @@ static void iwl3945_config_ap(struct iwl_priv *priv) rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON_TIMING, sizeof(priv->rxon_timing), &priv->rxon_timing); if (rc) - IWL_WARNING("REPLY_RXON_TIMING failed - " + IWL_WARN(priv, "REPLY_RXON_TIMING failed - " "Attempting to continue.\n"); /* FIXME: what should be the assoc_id for AP? */ @@ -6709,7 +6710,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, /* If there is currently a HW scan going on in the background * then we need to cancel it else the RXON below will fail. */ if (iwl3945_scan_cancel_timeout(priv, 100)) { - IWL_WARNING("Aborted scan still in progress " + IWL_WARN(priv, "Aborted scan still in progress " "after 100ms\n"); IWL_DEBUG_MAC80211("leaving - scan abort failed.\n"); mutex_unlock(&priv->mutex); @@ -7260,7 +7261,7 @@ static ssize_t store_flags(struct device *d, if (le32_to_cpu(priv->staging39_rxon.flags) != flags) { /* Cancel any currently running scans... */ if (iwl3945_scan_cancel_timeout(priv, 100)) - IWL_WARNING("Could not cancel scan.\n"); + IWL_WARN(priv, "Could not cancel scan.\n"); else { IWL_DEBUG_INFO("Committing rxon.flags = 0x%04X\n", flags); @@ -7295,7 +7296,7 @@ static ssize_t store_filter_flags(struct device *d, if (le32_to_cpu(priv->staging39_rxon.filter_flags) != filter_flags) { /* Cancel any currently running scans... */ if (iwl3945_scan_cancel_timeout(priv, 100)) - IWL_WARNING("Could not cancel scan.\n"); + IWL_WARN(priv, "Could not cancel scan.\n"); else { IWL_DEBUG_INFO("Committing rxon.filter_flags = " "0x%04X\n", filter_flags); @@ -8104,7 +8105,7 @@ static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state) iwl3945_radio_kill_sw(priv, 1); break; default: - IWL_WARNING("we received unexpected RFKILL state %d\n", state); + IWL_WARN(priv, "received unexpected RFKILL state %d\n", state); break; } out_unlock: -- GitLab From 15b1687cb4f45b87ddbe4dfc7759ff5bb69497d2 Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Fri, 19 Dec 2008 10:37:33 +0800 Subject: [PATCH 0727/4982] iwlwifi: replace IWL_ERROR with IWL_ERR IWL_ERR doesn't use hidden priv pointer. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-led.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 30 +-- drivers/net/wireless/iwlwifi/iwl-4965.c | 32 +-- drivers/net/wireless/iwlwifi/iwl-5000.c | 29 +-- .../net/wireless/iwlwifi/iwl-agn-hcmd-check.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 7 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 88 ++++---- drivers/net/wireless/iwlwifi/iwl-calib.c | 4 +- drivers/net/wireless/iwlwifi/iwl-core.c | 41 ++-- drivers/net/wireless/iwlwifi/iwl-debug.h | 1 - drivers/net/wireless/iwlwifi/iwl-debugfs.c | 8 +- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 12 +- drivers/net/wireless/iwlwifi/iwl-hcmd.c | 22 +- drivers/net/wireless/iwlwifi/iwl-io.h | 18 +- drivers/net/wireless/iwlwifi/iwl-led.c | 2 +- drivers/net/wireless/iwlwifi/iwl-rfkill.c | 4 +- drivers/net/wireless/iwlwifi/iwl-rx.c | 4 +- drivers/net/wireless/iwlwifi/iwl-spectrum.c | 2 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 36 ++-- drivers/net/wireless/iwlwifi/iwl-tx.c | 35 ++-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 192 +++++++++--------- 21 files changed, 299 insertions(+), 272 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index 165da9e314d..958e705ec33 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -216,7 +216,7 @@ static int iwl3945_led_register_led(struct iwl_priv *priv, ret = led_classdev_register(device, &led->led_dev); if (ret) { - IWL_ERROR("Error: failed to register led handler.\n"); + IWL_ERR(priv, "Error: failed to register led handler.\n"); return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 4a2cc78f0d7..8cf40bcd6a0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -152,7 +152,7 @@ void iwl3945_disable_events(struct iwl_priv *priv) base = le32_to_cpu(priv->card_alive.log_event_table_ptr); if (!iwl3945_hw_valid_rtc_data_addr(base)) { - IWL_ERROR("Invalid event log pointer 0x%08X\n", base); + IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); return; } @@ -224,7 +224,7 @@ __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv) } /* bad antenna selector value */ - IWL_ERROR("Bad antenna selector value (0x%x)\n", priv->antenna); + IWL_ERR(priv, "Bad antenna selector value (0x%x)\n", priv->antenna); return 0; /* "diversity" is default if error */ } @@ -344,7 +344,7 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv, int fail; if ((index >= txq->q.n_bd) || (iwl3945_x2_queue_used(&txq->q, index) == 0)) { - IWL_ERROR("Read index for DMA queue txq_id (%d) index %d " + IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " "is out of range [0-%d] %d %d\n", txq_id, index, txq->q.n_bd, txq->q.write_ptr, txq->q.read_ptr); @@ -376,7 +376,7 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv, iwl3945_tx_queue_reclaim(priv, txq_id, index); if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) - IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n"); + IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); } @@ -734,7 +734,7 @@ int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr, pad = TFD_CTL_PAD_GET(le32_to_cpu(tfd->control_flags)); if ((count >= NUM_TFD_CHUNKS) || (count < 0)) { - IWL_ERROR("Error can not send more than %d chunks\n", + IWL_ERR(priv, "Error can not send more than %d chunks\n", NUM_TFD_CHUNKS); return -EINVAL; } @@ -771,7 +771,7 @@ int iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl3945_tx_queue *txq) /* sanity check */ counter = TFD_CTL_COUNT_GET(le32_to_cpu(bd->control_flags)); if (counter > NUM_TFD_CHUNKS) { - IWL_ERROR("Too many chunks: %i\n", counter); + IWL_ERR(priv, "Too many chunks: %i\n", counter); /* @todo issue fatal error, it is quite serious situation */ return 0; } @@ -1065,7 +1065,7 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv) rc = iwl3945_tx_queue_init(priv, &priv->txq39[txq_id], slots_num, txq_id); if (rc) { - IWL_ERROR("Tx %d queue init failed\n", txq_id); + IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); goto error; } } @@ -1177,7 +1177,7 @@ int iwl3945_hw_nic_init(struct iwl_priv *priv) if (!rxq->bd) { rc = iwl3945_rx_queue_alloc(priv); if (rc) { - IWL_ERROR("Unable to initialize Rx queue\n"); + IWL_ERR(priv, "Unable to initialize Rx queue\n"); return -ENOMEM; } } else @@ -1377,7 +1377,7 @@ static int iwl3945_hw_reg_txpower_get_temperature(struct iwl_priv *priv) /* handle insane temp reading */ if (iwl3945_hw_reg_temp_out_of_range(temperature)) { - IWL_ERROR("Error bad temperature value %d\n", temperature); + IWL_ERR(priv, "Error bad temperature value %d\n", temperature); /* if really really hot(?), * substitute the 3rd band/group's temp measured at factory */ @@ -1685,9 +1685,9 @@ int iwl3945_hw_reg_send_txpower(struct iwl_priv *priv) priv->band, le16_to_cpu(priv->active39_rxon.channel)); if (!ch_info) { - IWL_ERROR - ("Failed to get channel info for channel %d [%d]\n", - le16_to_cpu(priv->active39_rxon.channel), priv->band); + IWL_ERR(priv, + "Failed to get channel info for channel %d [%d]\n", + le16_to_cpu(priv->active39_rxon.channel), priv->band); return -EINVAL; } @@ -2224,7 +2224,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv) ch_info->group_index, &power_idx); if (rc) { - IWL_ERROR("Invalid power index\n"); + IWL_ERR(priv, "Invalid power index\n"); return rc; } pwr_info->base_power_index = (u8) power_idx; @@ -2300,7 +2300,7 @@ int iwl3945_hw_rxq_stop(struct iwl_priv *priv) rc = iwl_poll_direct_bit(priv, FH39_RSSR_STATUS, FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); if (rc < 0) - IWL_ERROR("Can't stop Rx DMA.\n"); + IWL_ERR(priv, "Can't stop Rx DMA.\n"); iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); @@ -2440,7 +2440,7 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) &priv->shared_phys); if (!priv->shared_virt) { - IWL_ERROR("failed to allocate pci memory\n"); + IWL_ERR(priv, "failed to allocate pci memory\n"); mutex_unlock(&priv->mutex); return -ENOMEM; } diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 3de8d641399..e68d587a44b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -85,7 +85,7 @@ static int iwl4965_verify_bsm(struct iwl_priv *priv) reg += sizeof(u32), image++) { val = iwl_read_prph(priv, reg); if (val != le32_to_cpu(*image)) { - IWL_ERROR("BSM uCode verification failed at " + IWL_ERR(priv, "BSM uCode verification failed at " "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n", BSM_SRAM_LOWER_BOUND, reg - BSM_SRAM_LOWER_BOUND, len, @@ -203,7 +203,7 @@ static int iwl4965_load_bsm(struct iwl_priv *priv) if (i < 100) IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i); else { - IWL_ERROR("BSM write did not complete!\n"); + IWL_ERR(priv, "BSM write did not complete!\n"); return -EIO; } @@ -523,7 +523,8 @@ static void iwl4965_chain_noise_reset(struct iwl_priv *priv) cmd.diff_gain_c = 0; if (iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, sizeof(cmd), &cmd)) - IWL_ERROR("Could not send REPLY_PHY_CALIBRATION_CMD\n"); + IWL_ERR(priv, + "Could not send REPLY_PHY_CALIBRATION_CMD\n"); data->state = IWL_CHAIN_NOISE_ACCUMULATE; IWL_DEBUG_CALIB("Run chain_noise_calibrate\n"); } @@ -804,8 +805,9 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) if ((priv->cfg->mod_params->num_of_queues > IWL49_NUM_QUEUES) || (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) { - IWL_ERROR("invalid queues_num, should be between %d and %d\n", - IWL_MIN_NUM_QUEUES, IWL49_NUM_QUEUES); + IWL_ERR(priv, + "invalid queues_num, should be between %d and %d\n", + IWL_MIN_NUM_QUEUES, IWL49_NUM_QUEUES); return -EINVAL; } @@ -955,7 +957,7 @@ static int iwl4965_interpolate_chan(struct iwl_priv *priv, u32 channel, s = iwl4965_get_sub_band(priv, channel); if (s >= EEPROM_TX_POWER_BANDS) { - IWL_ERROR("Tx Power can not find channel %d\n", channel); + IWL_ERR(priv, "Tx Power can not find channel %d\n", channel); return -1; } @@ -1319,7 +1321,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, * and 2) mimo txpower balance between Tx chains. */ txatten_grp = iwl4965_get_tx_atten_grp(channel); if (txatten_grp < 0) { - IWL_ERROR("Can't find txatten group for channel %d.\n", + IWL_ERR(priv, "Can't find txatten group for channel %d.\n", channel); return -EINVAL; } @@ -1727,7 +1729,7 @@ static int iwl4965_hw_get_temperature(const struct iwl_priv *priv) IWL_DEBUG_TEMP("Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt); if (R3 == R1) { - IWL_ERROR("Calibration conflict R1 == R3\n"); + IWL_ERR(priv, "Calibration conflict R1 == R3\n"); return -1; } @@ -2071,10 +2073,10 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, sc = le16_to_cpu(hdr->seq_ctrl); if (idx != (SEQ_TO_SN(sc) & 0xff)) { - IWL_ERROR("BUG_ON idx doesn't match seq control" - " idx=%d, seq_idx=%d, seq=%d\n", - idx, SEQ_TO_SN(sc), - hdr->seq_ctrl); + IWL_ERR(priv, + "BUG_ON idx doesn't match seq control" + " idx=%d, seq_idx=%d, seq=%d\n", + idx, SEQ_TO_SN(sc), hdr->seq_ctrl); return -1; } @@ -2133,7 +2135,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, u8 *qc = NULL; if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { - IWL_ERROR("Read index for DMA queue txq_id (%d) index %d " + IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " "is out of range [0-%d] %d %d\n", txq_id, index, txq->q.n_bd, txq->q.write_ptr, txq->q.read_ptr); @@ -2151,7 +2153,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, sta_id = iwl_get_ra_sta_id(priv, hdr); if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) { - IWL_ERROR("Station not known\n"); + IWL_ERR(priv, "Station not known\n"); return; } @@ -2214,7 +2216,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, iwl_txq_check_empty(priv, sta_id, tid, txq_id); if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) - IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n"); + IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); } static int iwl4965_calc_rssi(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 448bdb65bff..76d86fe2b41 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -289,7 +289,7 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address) offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_OTHERS); break; default: - IWL_ERROR("illegal indirect type: 0x%X\n", + IWL_ERR(priv, "illegal indirect type: 0x%X\n", address & INDIRECT_TYPE_MSK); break; } @@ -384,7 +384,8 @@ static void iwl5000_chain_noise_reset(struct iwl_priv *priv) ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, sizeof(cmd), &cmd); if (ret) - IWL_ERROR("Could not send REPLY_PHY_CALIBRATION_CMD\n"); + IWL_ERR(priv, + "Could not send REPLY_PHY_CALIBRATION_CMD\n"); data->state = IWL_CHAIN_NOISE_ACCUMULATE; IWL_DEBUG_CALIB("Run chain_noise_calibrate\n"); } @@ -507,7 +508,7 @@ static void iwl5000_rx_calib_result(struct iwl_priv *priv, index = IWL_CALIB_BASE_BAND; break; default: - IWL_ERROR("Unknown calibration notification %d\n", + IWL_ERR(priv, "Unknown calibration notification %d\n", hdr->op_code); return; } @@ -589,12 +590,12 @@ static int iwl5000_load_given_ucode(struct iwl_priv *priv, ret = wait_event_interruptible_timeout(priv->wait_command_queue, priv->ucode_write_complete, 5 * HZ); if (ret == -ERESTARTSYS) { - IWL_ERROR("Could not load the INST uCode section due " + IWL_ERR(priv, "Could not load the INST uCode section due " "to interrupt\n"); return ret; } if (!ret) { - IWL_ERROR("Could not load the INST uCode section\n"); + IWL_ERR(priv, "Could not load the INST uCode section\n"); return -ETIMEDOUT; } @@ -610,11 +611,11 @@ static int iwl5000_load_given_ucode(struct iwl_priv *priv, ret = wait_event_interruptible_timeout(priv->wait_command_queue, priv->ucode_write_complete, 5 * HZ); if (ret == -ERESTARTSYS) { - IWL_ERROR("Could not load the INST uCode section due " + IWL_ERR(priv, "Could not load the INST uCode section due " "to interrupt\n"); return ret; } else if (!ret) { - IWL_ERROR("Could not load the DATA uCode section\n"); + IWL_ERR(priv, "Could not load the DATA uCode section\n"); return -ETIMEDOUT; } else ret = 0; @@ -826,8 +827,9 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) { if ((priv->cfg->mod_params->num_of_queues > IWL50_NUM_QUEUES) || (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) { - IWL_ERROR("invalid queues_num, should be between %d and %d\n", - IWL_MIN_NUM_QUEUES, IWL50_NUM_QUEUES); + IWL_ERR(priv, + "invalid queues_num, should be between %d and %d\n", + IWL_MIN_NUM_QUEUES, IWL50_NUM_QUEUES); return -EINVAL; } @@ -1201,8 +1203,9 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, sc = le16_to_cpu(hdr->seq_ctrl); if (idx != (SEQ_TO_SN(sc) & 0xff)) { - IWL_ERROR("BUG_ON idx doesn't match seq control" - " idx=%d, seq_idx=%d, seq=%d\n", + IWL_ERR(priv, + "BUG_ON idx doesn't match seq control" + " idx=%d, seq_idx=%d, seq=%d\n", idx, SEQ_TO_SN(sc), hdr->seq_ctrl); return -1; @@ -1258,7 +1261,7 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, int freed; if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { - IWL_ERROR("Read index for DMA queue txq_id (%d) index %d " + IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " "is out of range [0-%d] %d %d\n", txq_id, index, txq->q.n_bd, txq->q.write_ptr, txq->q.read_ptr); @@ -1332,7 +1335,7 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, iwl_txq_check_empty(priv, sta_id, tid, txq_id); if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) - IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n"); + IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); } /* Currently 5000 is the superset of everything */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c index 16e656a311a..2c8e676c4b5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c @@ -101,7 +101,7 @@ int iwl_agn_check_rxon_cmd(struct iwl_priv *priv) le16_to_cpu(rxon->channel)); if (error) { - IWL_ERROR("Not a valid iwl4965_rxon_assoc_cmd field values\n"); + IWL_ERR(priv, "Not a valid iwl_rxon_assoc_cmd field values\n"); return -1; } return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index c0f8b96b9f8..75b418e5e87 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -1431,7 +1431,8 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, if (!tbl->is_SGI) break; else - IWL_ERROR("SGI was set in GF+SISO\n"); + IWL_ERR(priv, + "SGI was set in GF+SISO\n"); } search_tbl->is_SGI = !tbl->is_SGI; rs_set_expected_tpt_table(lq_sta, search_tbl); @@ -1748,13 +1749,13 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, rate_scale_index_msk = rate_mask; if (!((1 << index) & rate_scale_index_msk)) { - IWL_ERROR("Current Rate is not valid\n"); + IWL_ERR(priv, "Current Rate is not valid\n"); return; } /* Get expected throughput table and history window for current rate */ if (!tbl->expected_tpt) { - IWL_ERROR("tbl->expected_tpt is NULL\n"); + IWL_ERR(priv, "tbl->expected_tpt is NULL\n"); return; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index ce290f6867f..1ef9f58fec8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -181,7 +181,7 @@ static int iwl_commit_rxon(struct iwl_priv *priv) ret = iwl_agn_check_rxon_cmd(priv); if (ret) { - IWL_ERROR("Invalid RXON configuration. Not committing.\n"); + IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); return -EINVAL; } @@ -191,7 +191,7 @@ static int iwl_commit_rxon(struct iwl_priv *priv) if (!iwl_full_rxon_required(priv)) { ret = iwl_send_rxon_assoc(priv); if (ret) { - IWL_ERROR("Error setting RXON_ASSOC (%d)\n", ret); + IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret); return ret; } @@ -218,7 +218,7 @@ static int iwl_commit_rxon(struct iwl_priv *priv) * active_rxon back to what it was previously */ if (ret) { active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK; - IWL_ERROR("Error clearing ASSOC_MSK (%d)\n", ret); + IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret); return ret; } } @@ -242,7 +242,7 @@ static int iwl_commit_rxon(struct iwl_priv *priv) ret = iwl_send_cmd_pdu(priv, REPLY_RXON, sizeof(struct iwl_rxon_cmd), &priv->staging_rxon); if (ret) { - IWL_ERROR("Error setting new RXON (%d)\n", ret); + IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); return ret; } memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); @@ -256,7 +256,7 @@ static int iwl_commit_rxon(struct iwl_priv *priv) /* Add the broadcast address so we can send broadcast frames */ if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) == IWL_INVALID_STATION) { - IWL_ERROR("Error adding BROADCAST address for transmit.\n"); + IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n"); return -EIO; } @@ -267,13 +267,15 @@ static int iwl_commit_rxon(struct iwl_priv *priv) ret = iwl_rxon_add_station(priv, priv->active_rxon.bssid_addr, 1); if (ret == IWL_INVALID_STATION) { - IWL_ERROR("Error adding AP address for TX.\n"); + IWL_ERR(priv, + "Error adding AP address for TX.\n"); return -EIO; } priv->assoc_station_added = 1; if (priv->default_wep_key && iwl_send_static_wepkey_cmd(priv, 0)) - IWL_ERROR("Could not send WEP static key.\n"); + IWL_ERR(priv, + "Could not send WEP static key.\n"); } /* Apply the new configuration @@ -282,7 +284,7 @@ static int iwl_commit_rxon(struct iwl_priv *priv) ret = iwl_send_cmd_pdu(priv, REPLY_RXON, sizeof(struct iwl_rxon_cmd), &priv->staging_rxon); if (ret) { - IWL_ERROR("Error setting new RXON (%d)\n", ret); + IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); return ret; } memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); @@ -294,7 +296,7 @@ static int iwl_commit_rxon(struct iwl_priv *priv) * send a new TXPOWER command or we won't be able to Tx any frames */ ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); if (ret) { - IWL_ERROR("Error sending TX power (%d)\n", ret); + IWL_ERR(priv, "Error sending TX power (%d)\n", ret); return ret; } @@ -350,7 +352,7 @@ static struct iwl_frame *iwl_get_free_frame(struct iwl_priv *priv) if (list_empty(&priv->free_frames)) { frame = kzalloc(sizeof(*frame), GFP_KERNEL); if (!frame) { - IWL_ERROR("Could not allocate frame!\n"); + IWL_ERR(priv, "Could not allocate frame!\n"); return NULL; } @@ -452,7 +454,7 @@ static int iwl_send_beacon_cmd(struct iwl_priv *priv) frame = iwl_get_free_frame(priv); if (!frame) { - IWL_ERROR("Could not obtain free frame buffer for beacon " + IWL_ERR(priv, "Could not obtain free frame buffer for beacon " "command.\n"); return -ENOMEM; } @@ -686,7 +688,7 @@ static void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode) RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK; break; default: - IWL_ERROR("Unsupported interface type %d\n", mode); + IWL_ERR(priv, "Unsupported interface type %d\n", mode); break; } @@ -763,7 +765,7 @@ static void iwl_set_rate(struct iwl_priv *priv) hw = iwl_get_hw_mode(priv, priv->band); if (!hw) { - IWL_ERROR("Failed to set rate: unable to get hw mode\n"); + IWL_ERR(priv, "Failed to set rate: unable to get hw mode\n"); return; } @@ -849,7 +851,7 @@ static void iwl_rx_reply_error(struct iwl_priv *priv, { struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - IWL_ERROR("Error Reply type 0x%08X cmd %s (0x%02X) " + IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) " "seq 0x%04X ser 0x%08X\n", le32_to_cpu(pkt->u.err_resp.error_type), get_cmd_string(pkt->u.err_resp.cmd_id), @@ -902,7 +904,7 @@ static void iwl_bg_beacon_update(struct work_struct *work) beacon = ieee80211_beacon_get(priv->hw, priv->vif); if (!beacon) { - IWL_ERROR("update beacon failed\n"); + IWL_ERR(priv, "update beacon failed\n"); return; } @@ -1357,7 +1359,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) /* Now service all interrupt bits discovered above. */ if (inta & CSR_INT_BIT_HW_ERR) { - IWL_ERROR("Microcode HW error detected. Restarting.\n"); + IWL_ERR(priv, "Microcode HW error detected. Restarting.\n"); /* Tell the device to stop sending interrupts */ iwl_disable_interrupts(priv); @@ -1411,14 +1413,14 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) /* Chip got too hot and stopped itself */ if (inta & CSR_INT_BIT_CT_KILL) { - IWL_ERROR("Microcode CT kill error detected.\n"); + IWL_ERR(priv, "Microcode CT kill error detected.\n"); handled |= CSR_INT_BIT_CT_KILL; } /* Error detected by uCode */ if (inta & CSR_INT_BIT_SW_ERR) { - IWL_ERROR("Microcode SW error detected. Restarting 0x%X.\n", - inta); + IWL_ERR(priv, "Microcode SW error detected. " + " Restarting 0x%X.\n", inta); iwl_irq_handle_error(priv); handled |= CSR_INT_BIT_SW_ERR; } @@ -1454,7 +1456,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) } if (inta & ~handled) - IWL_ERROR("Unhandled INTA bits 0x%08x\n", inta & ~handled); + IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled); if (inta & ~CSR_INI_SET_MASK) { IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", @@ -1584,7 +1586,7 @@ static int iwl_read_ucode(struct iwl_priv *priv) sprintf(buf, "%s%d%s", name_pre, index, ".ucode"); ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev); if (ret < 0) { - IWL_ERROR("%s firmware file req failed: Reason %d\n", + IWL_ERR(priv, "%s firmware file req failed: %d\n", buf, ret); if (ret == -ENOENT) continue; @@ -1592,8 +1594,11 @@ static int iwl_read_ucode(struct iwl_priv *priv) goto error; } else { if (index < api_max) - IWL_ERROR("Loaded firmware %s, which is deprecated. Please use API v%u instead.\n", + IWL_ERR(priv, "Loaded firmware %s, " + "which is deprecated. " + "Please use API v%u instead.\n", buf, api_max); + IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n", buf, ucode_raw->size); break; @@ -1605,7 +1610,7 @@ static int iwl_read_ucode(struct iwl_priv *priv) /* Make sure that we got at least our header! */ if (ucode_raw->size < sizeof(*ucode)) { - IWL_ERROR("File size way too small!\n"); + IWL_ERR(priv, "File size way too small!\n"); ret = -EINVAL; goto err_release; } @@ -1626,7 +1631,7 @@ static int iwl_read_ucode(struct iwl_priv *priv) * on the API version read from firware header from here on forward */ if (api_ver < api_min || api_ver > api_max) { - IWL_ERROR("Driver unable to support your firmware API. " + IWL_ERR(priv, "Driver unable to support your firmware API. " "Driver supports v%u, firmware is v%u.\n", api_max, api_ver); priv->ucode_ver = 0; @@ -1787,7 +1792,7 @@ static int iwl_read_ucode(struct iwl_priv *priv) return 0; err_pci_alloc: - IWL_ERROR("failed to allocate pci memory\n"); + IWL_ERR(priv, "failed to allocate pci memory\n"); ret = -ENOMEM; iwl_dealloc_ucode_pci(priv); @@ -2025,7 +2030,7 @@ static int __iwl_up(struct iwl_priv *priv) } if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) { - IWL_ERROR("ucode not available for device bringup\n"); + IWL_ERR(priv, "ucode not available for device bringup\n"); return -EIO; } @@ -2046,7 +2051,7 @@ static int __iwl_up(struct iwl_priv *priv) ret = iwl_hw_nic_init(priv); if (ret) { - IWL_ERROR("Unable to init nic\n"); + IWL_ERR(priv, "Unable to init nic\n"); return ret; } @@ -2079,7 +2084,8 @@ static int __iwl_up(struct iwl_priv *priv) ret = priv->cfg->ops->lib->load_ucode(priv); if (ret) { - IWL_ERROR("Unable to set up bootstrap uCode: %d\n", ret); + IWL_ERR(priv, "Unable to set up bootstrap uCode: %d\n", + ret); continue; } @@ -2100,7 +2106,7 @@ static int __iwl_up(struct iwl_priv *priv) /* tried to restart and config the device for as long as our * patience could withstand */ - IWL_ERROR("Unable to initialize device after %d attempts.\n", i); + IWL_ERR(priv, "Unable to initialize device after %d attempts.\n", i); return -EIO; } @@ -2240,7 +2246,7 @@ static void iwl_post_associate(struct iwl_priv *priv) unsigned long flags; if (priv->iw_mode == NL80211_IFTYPE_AP) { - IWL_ERROR("%s Should not be called in AP mode\n", __func__); + IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); return; } @@ -2313,7 +2319,7 @@ static void iwl_post_associate(struct iwl_priv *priv) break; default: - IWL_ERROR("%s Should not be called in %d mode\n", + IWL_ERR(priv, "%s Should not be called in %d mode\n", __func__, priv->iw_mode); break; } @@ -2354,7 +2360,7 @@ static int iwl_mac_start(struct ieee80211_hw *hw) IWL_DEBUG_MAC80211("enter\n"); if (pci_enable_device(priv->pci_dev)) { - IWL_ERROR("Fail to pci_enable_device\n"); + IWL_ERR(priv, "Fail to pci_enable_device\n"); return -ENODEV; } pci_restore_state(priv->pci_dev); @@ -2370,7 +2376,7 @@ static int iwl_mac_start(struct ieee80211_hw *hw) ret = request_irq(priv->pci_dev->irq, iwl_isr, IRQF_SHARED, DRV_NAME, priv); if (ret) { - IWL_ERROR("Error allocating IRQ %d\n", priv->pci_dev->irq); + IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); goto out_disable_msi; } @@ -2384,7 +2390,7 @@ static int iwl_mac_start(struct ieee80211_hw *hw) if (!priv->ucode_code.len) { ret = iwl_read_ucode(priv); if (ret) { - IWL_ERROR("Could not read microcode: %d\n", ret); + IWL_ERR(priv, "Could not read microcode: %d\n", ret); mutex_unlock(&priv->mutex); goto out_release_irq; } @@ -2414,7 +2420,7 @@ static int iwl_mac_start(struct ieee80211_hw *hw) UCODE_READY_TIMEOUT); if (!ret) { if (!test_bit(STATUS_READY, &priv->status)) { - IWL_ERROR("START_ALIVE timeout after %dms.\n", + IWL_ERR(priv, "START_ALIVE timeout after %dms.\n", jiffies_to_msecs(UCODE_READY_TIMEOUT)); ret = -ETIMEDOUT; goto out_release_irq; @@ -2573,7 +2579,7 @@ static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) if (priv->iw_mode == NL80211_IFTYPE_ADHOC && !is_channel_ibss(ch_info)) { - IWL_ERROR("channel %d in band %d not IBSS channel\n", + IWL_ERR(priv, "channel %d in band %d not IBSS channel\n", conf->channel->hw_value, conf->channel->band); ret = -EINVAL; goto out; @@ -3818,7 +3824,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Read the EEPROM */ err = iwl_eeprom_init(priv); if (err) { - IWL_ERROR("Unable to init EEPROM\n"); + IWL_ERR(priv, "Unable to init EEPROM\n"); goto out_iounmap; } err = iwl_eeprom_check_version(priv); @@ -3834,7 +3840,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) * 5. Setup HW constants ************************/ if (iwl_set_hw_params(priv)) { - IWL_ERROR("failed to set hw parameters\n"); + IWL_ERR(priv, "failed to set hw parameters\n"); goto out_free_eeprom; } @@ -3866,7 +3872,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group); if (err) { - IWL_ERROR("failed to create sysfs device attributes\n"); + IWL_ERR(priv, "failed to create sysfs device attributes\n"); goto out_uninit_drv; } @@ -3890,11 +3896,11 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = iwl_dbgfs_register(priv, DRV_NAME); if (err) - IWL_ERROR("failed to create debugfs files\n"); + IWL_ERR(priv, "failed to create debugfs files\n"); err = iwl_rfkill_init(priv); if (err) - IWL_ERROR("Unable to initialize RFKILL system. " + IWL_ERR(priv, "Unable to initialize RFKILL system. " "Ignoring error: %d\n", err); iwl_power_initialize(priv); return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index f836ecc5575..d2aabbc38d6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c @@ -102,7 +102,7 @@ int iwl_send_calib_results(struct iwl_priv *priv) return 0; err: - IWL_ERROR("Error %d iteration %d\n", ret, i); + IWL_ERR(priv, "Error %d iteration %d\n", ret, i); return ret; } EXPORT_SYMBOL(iwl_send_calib_results); @@ -483,7 +483,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv) ret = iwl_send_cmd(priv, &cmd_out); if (ret) - IWL_ERROR("SENSITIVITY_CMD failed\n"); + IWL_ERR(priv, "SENSITIVITY_CMD failed\n"); return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 2bc461a610a..cde233d1574 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -211,7 +211,7 @@ int iwl_hw_nic_init(struct iwl_priv *priv) if (!rxq->bd) { ret = iwl_rx_queue_alloc(priv); if (ret) { - IWL_ERROR("Unable to initialize Rx queue\n"); + IWL_ERR(priv, "Unable to initialize Rx queue\n"); return -ENOMEM; } } else @@ -678,7 +678,7 @@ static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) break; case WLAN_HT_CAP_SM_PS_INVALID: default: - IWL_ERROR("invalid mimo ps mode %d\n", + IWL_ERR(priv, "invalid mimo ps mode %d\n", priv->current_ht_config.sm_ps); WARN_ON(1); idle_cnt = -1; @@ -830,7 +830,7 @@ int iwl_setup_mac(struct iwl_priv *priv) ret = ieee80211_register_hw(priv->hw); if (ret) { - IWL_ERROR("Failed to register hw (error %d)\n", ret); + IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); return ret; } priv->mac80211_registered = 1; @@ -901,13 +901,13 @@ int iwl_init_drv(struct iwl_priv *priv) ret = iwl_init_channel_map(priv); if (ret) { - IWL_ERROR("initializing regulatory failed: %d\n", ret); + IWL_ERR(priv, "initializing regulatory failed: %d\n", ret); goto err; } ret = iwlcore_init_geos(priv); if (ret) { - IWL_ERROR("initializing geos failed: %d\n", ret); + IWL_ERR(priv, "initializing geos failed: %d\n", ret); goto err_free_channel_map; } @@ -1059,7 +1059,7 @@ static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 *image, * if IWL_DL_IO is set */ val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); if (val != le32_to_cpu(*image)) { - IWL_ERROR("uCode INST section is invalid at " + IWL_ERR(priv, "uCode INST section is invalid at " "offset 0x%x, is 0x%x, s/b 0x%x\n", save_len - len, val, le32_to_cpu(*image)); ret = -EIO; @@ -1115,7 +1115,7 @@ int iwl_verify_ucode(struct iwl_priv *priv) return 0; } - IWL_ERROR("NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n"); + IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n"); /* Since nothing seems to match, show first several data entries in * instruction SRAM, so maybe visual inspection will give a clue. @@ -1187,7 +1187,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) base = le32_to_cpu(priv->card_alive.error_event_table_ptr); if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { - IWL_ERROR("Not valid error log pointer 0x%08X\n", base); + IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base); return; } @@ -1200,8 +1200,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) count = iwl_read_targ_mem(priv, base); if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { - IWL_ERROR("Start IWL Error Log Dump:\n"); - IWL_ERROR("Status: 0x%08lX, count: %d\n", priv->status, count); + IWL_ERR(priv, "Start IWL Error Log Dump:\n"); + IWL_ERR(priv, "Status: 0x%08lX, count: %d\n", + priv->status, count); } desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32)); @@ -1214,12 +1215,12 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32)); time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32)); - IWL_ERROR("Desc Time " + IWL_ERR(priv, "Desc Time " "data1 data2 line\n"); - IWL_ERROR("%-28s (#%02d) %010u 0x%08X 0x%08X %u\n", + IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n", desc_lookup(desc), desc, time, data1, data2, line); - IWL_ERROR("blink1 blink2 ilink1 ilink2\n"); - IWL_ERROR("0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2, + IWL_ERR(priv, "blink1 blink2 ilink1 ilink2\n"); + IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2, ilink1, ilink2); iwl_release_nic_access(priv); @@ -1265,11 +1266,11 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, ptr += sizeof(u32); if (mode == 0) { /* data, ev */ - IWL_ERROR("EVT_LOG:0x%08x:%04u\n", time, ev); + IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev); } else { data = iwl_read_targ_mem(priv, ptr); ptr += sizeof(u32); - IWL_ERROR("EVT_LOGT:%010u:0x%08x:%04u\n", + IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", time, data, ev); } } @@ -1291,7 +1292,7 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv) base = le32_to_cpu(priv->card_alive.log_event_table_ptr); if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { - IWL_ERROR("Invalid event log pointer 0x%08X\n", base); + IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); return; } @@ -1311,12 +1312,12 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv) /* bail out if nothing in log */ if (size == 0) { - IWL_ERROR("Start IWL Event Log Dump: nothing in log\n"); + IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); iwl_release_nic_access(priv); return; } - IWL_ERROR("Start IWL Event Log Dump: display count %d, wraps %d\n", + IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n", size, num_wraps); /* if uCode has wrapped back to top of log, start at the oldest entry, @@ -1348,7 +1349,7 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv) ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, sizeof(cmd), &cmd); if (ret) - IWL_ERROR("REPLY_CT_KILL_CONFIG_CMD failed\n"); + IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); else IWL_DEBUG_INFO("REPLY_CT_KILL_CONFIG_CMD succeeded, " "critical temperature is %d\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 654dc9cdd23..057781c8f82 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -31,7 +31,6 @@ struct iwl_priv; -#define IWL_ERROR(f, a...) dev_err(&(priv->pci_dev->dev), f, ## a) #define IWL_ERR(p, f, a...) dev_err(&((p)->pci_dev->dev), f, ## a) #define IWL_WARN(p, f, a...) dev_warn(&((p)->pci_dev->dev), f, ## a) #define IWL_INFO(p, f, a...) dev_info(&((p)->pci_dev->dev), f, ## a) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index f27dbb92273..40441b8db89 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -306,14 +306,14 @@ static ssize_t iwl_dbgfs_eeprom_read(struct file *file, buf_size = 4 * eeprom_len + 256; if (eeprom_len % 16) { - IWL_ERROR("EEPROM size is not multiple of 16.\n"); + IWL_ERR(priv, "EEPROM size is not multiple of 16.\n"); return -ENODATA; } /* 4 characters for byte 0xYY */ buf = kzalloc(buf_size, GFP_KERNEL); if (!buf) { - IWL_ERROR("Can not allocate Buffer\n"); + IWL_ERR(priv, "Can not allocate Buffer\n"); return -ENOMEM; } @@ -370,7 +370,7 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, buf = kzalloc(bufsz, GFP_KERNEL); if (!buf) { - IWL_ERROR("Can not allocate Buffer\n"); + IWL_ERR(priv, "Can not allocate Buffer\n"); return -ENOMEM; } @@ -474,7 +474,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) return 0; err: - IWL_ERROR("Can't open the debugfs directory\n"); + IWL_ERR(priv, "Can't open the debugfs directory\n"); iwl_dbgfs_unregister(priv); return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index ce2f47306ce..59abac09a78 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -145,7 +145,7 @@ int iwlcore_eeprom_verify_signature(struct iwl_priv *priv) { u32 gp = iwl_read32(priv, CSR_EEPROM_GP); if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) { - IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x\n", gp); + IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); return -ENOENT; } return 0; @@ -223,7 +223,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv); if (ret < 0) { - IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x\n", gp); + IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); ret = -ENOENT; goto err; } @@ -231,7 +231,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) /* Make sure driver (instead of uCode) is allowed to read EEPROM */ ret = priv->cfg->ops->lib->eeprom_ops.acquire_semaphore(priv); if (ret < 0) { - IWL_ERROR("Failed to acquire EEPROM semaphore.\n"); + IWL_ERR(priv, "Failed to acquire EEPROM semaphore.\n"); ret = -ENOENT; goto err; } @@ -247,7 +247,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) CSR_EEPROM_REG_READ_VALID_MSK, IWL_EEPROM_ACCESS_TIMEOUT); if (ret < 0) { - IWL_ERROR("Time out reading EEPROM[%d]\n", addr); + IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr); goto done; } r = _iwl_read_direct32(priv, CSR_EEPROM_REG); @@ -285,7 +285,7 @@ int iwl_eeprom_check_version(struct iwl_priv *priv) return 0; err: - IWL_ERROR("Unsupported EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n", + IWL_ERR(priv, "Unsupported EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n", eeprom_ver, priv->cfg->eeprom_ver, calib_ver, priv->cfg->eeprom_calib_ver); return -EINVAL; @@ -450,7 +450,7 @@ int iwl_init_channel_map(struct iwl_priv *priv) priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) * priv->channel_count, GFP_KERNEL); if (!priv->channel_info) { - IWL_ERROR("Could not allocate channel_info\n"); + IWL_ERR(priv, "Could not allocate channel_info\n"); priv->channel_count = 0; return -ENOMEM; } diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 4b35b30e493..af14d8fdcc7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -109,14 +109,14 @@ static int iwl_generic_cmd_callback(struct iwl_priv *priv, struct iwl_rx_packet *pkt = NULL; if (!skb) { - IWL_ERROR("Error: Response NULL in %s.\n", + IWL_ERR(priv, "Error: Response NULL in %s.\n", get_cmd_string(cmd->hdr.cmd)); return 1; } pkt = (struct iwl_rx_packet *)skb->data; if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERROR("Bad return from %s (0x%08X)\n", + IWL_ERR(priv, "Bad return from %s (0x%08X)\n", get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); return 1; } @@ -156,7 +156,7 @@ static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd) ret = iwl_enqueue_hcmd(priv, cmd); if (ret < 0) { - IWL_ERROR("Error sending %s: enqueue_hcmd failed: %d\n", + IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n", get_cmd_string(cmd->id), ret); return ret; } @@ -174,8 +174,9 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) BUG_ON(cmd->meta.u.callback != NULL); if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) { - IWL_ERROR("Error sending %s: Already sending a host command\n", - get_cmd_string(cmd->id)); + IWL_ERR(priv, + "Error sending %s: Already sending a host command\n", + get_cmd_string(cmd->id)); ret = -EBUSY; goto out; } @@ -188,7 +189,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) cmd_idx = iwl_enqueue_hcmd(priv, cmd); if (cmd_idx < 0) { ret = cmd_idx; - IWL_ERROR("Error sending %s: enqueue_hcmd failed: %d\n", + IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n", get_cmd_string(cmd->id), ret); goto out; } @@ -198,9 +199,10 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) HOST_COMPLETE_TIMEOUT); if (!ret) { if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) { - IWL_ERROR("Error sending %s: time out after %dms.\n", - get_cmd_string(cmd->id), - jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); + IWL_ERR(priv, + "Error sending %s: time out after %dms.\n", + get_cmd_string(cmd->id), + jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); clear_bit(STATUS_HCMD_ACTIVE, &priv->status); ret = -ETIMEDOUT; @@ -221,7 +223,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) goto fail; } if ((cmd->meta.flags & CMD_WANT_SKB) && !cmd->meta.u.skb) { - IWL_ERROR("Error: Response NULL in '%s'\n", + IWL_ERR(priv, "Error: Response NULL in '%s'\n", get_cmd_string(cmd->id)); ret = -EIO; goto cancel; diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 0a92e7431ad..801d5ffd21e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -167,7 +167,7 @@ static inline int _iwl_grab_nic_access(struct iwl_priv *priv) (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 50); if (ret < 0) { - IWL_ERROR("MAC is in deep sleep!\n"); + IWL_ERR(priv, "MAC is in deep sleep!\n"); return -EIO; } @@ -182,7 +182,7 @@ static inline int __iwl_grab_nic_access(const char *f, u32 l, struct iwl_priv *priv) { if (atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Grabbing access while already held %s %d.\n", f, l); + IWL_ERR(priv, "Grabbing access while already held %s %d.\n", f, l); IWL_DEBUG_IO("grabbing nic access - %s %d\n", f, l); return _iwl_grab_nic_access(priv); @@ -207,7 +207,7 @@ static inline void __iwl_release_nic_access(const char *f, u32 l, struct iwl_priv *priv) { if (atomic_read(&priv->restrict_refcnt) <= 0) - IWL_ERROR("Release unheld nic access at line %s %d.\n", f, l); + IWL_ERR(priv, "Release unheld nic access at line %s %d.\n", f, l); IWL_DEBUG_IO("releasing nic access - %s %d\n", f, l); _iwl_release_nic_access(priv); @@ -229,7 +229,7 @@ static inline u32 __iwl_read_direct32(const char *f, u32 l, { u32 value = _iwl_read_direct32(priv, reg); if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Nic access not held from %s %d\n", f, l); + IWL_ERR(priv, "Nic access not held from %s %d\n", f, l); IWL_DEBUG_IO("read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value, f, l); return value; @@ -250,7 +250,7 @@ static void __iwl_write_direct32(const char *f , u32 line, struct iwl_priv *priv, u32 reg, u32 value) { if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Nic access not held from %s line %d\n", f, line); + IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line); _iwl_write_direct32(priv, reg, value); } #define iwl_write_direct32(priv, reg, value) \ @@ -308,7 +308,7 @@ static inline u32 __iwl_read_prph(const char *f, u32 line, struct iwl_priv *priv, u32 reg) { if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Nic access not held from %s line %d\n", f, line); + IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line); return _iwl_read_prph(priv, reg); } @@ -331,7 +331,7 @@ static inline void __iwl_write_prph(const char *f, u32 line, struct iwl_priv *priv, u32 addr, u32 val) { if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Nic access not held from %s line %d\n", f, line); + IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line); _iwl_write_prph(priv, addr, val); } @@ -349,7 +349,7 @@ static inline void __iwl_set_bits_prph(const char *f, u32 line, u32 reg, u32 mask) { if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Nic access not held from %s line %d\n", f, line); + IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line); _iwl_set_bits_prph(priv, reg, mask); } @@ -367,7 +367,7 @@ static inline void __iwl_set_bits_mask_prph(const char *f, u32 line, struct iwl_priv *priv, u32 reg, u32 bits, u32 mask) { if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Nic access not held from %s line %d\n", f, line); + IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line); _iwl_set_bits_mask_prph(priv, reg, bits, mask); } #define iwl_set_bits_mask_prph(priv, reg, bits, mask) \ diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 11eccd7d268..98be90f245c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -254,7 +254,7 @@ static int iwl_leds_register_led(struct iwl_priv *priv, struct iwl_led *led, ret = led_classdev_register(device, &led->led_dev); if (ret) { - IWL_ERROR("Error: failed to register led handler.\n"); + IWL_ERR(priv, "Error: failed to register led handler.\n"); return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c index cece1c56393..98df755e21b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c @@ -82,7 +82,7 @@ int iwl_rfkill_init(struct iwl_priv *priv) IWL_DEBUG_RF_KILL("Initializing RFKILL.\n"); priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); if (!priv->rfkill) { - IWL_ERROR("Unable to allocate RFKILL device.\n"); + IWL_ERR(priv, "Unable to allocate RFKILL device.\n"); ret = -ENOMEM; goto error; } @@ -98,7 +98,7 @@ int iwl_rfkill_init(struct iwl_priv *priv) ret = rfkill_register(priv->rfkill); if (ret) { - IWL_ERROR("Unable to register RFKILL: %d\n", ret); + IWL_ERR(priv, "Unable to register RFKILL: %d\n", ret); goto free_rfkill; } diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 18c630d74a3..bc3febe74d6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -894,7 +894,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, rx_start = (struct iwl_rx_phy_res *)&priv->last_phy_res[1]; if (!rx_start) { - IWL_ERROR("MPDU frame without a PHY data\n"); + IWL_ERR(priv, "MPDU frame without a PHY data\n"); return; } if (include_phy) { @@ -1020,7 +1020,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, } if (!rx_start) { - IWL_ERROR("MPDU frame without a PHY data\n"); + IWL_ERR(priv, "MPDU frame without a PHY data\n"); return; } diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.c b/drivers/net/wireless/iwlwifi/iwl-spectrum.c index 836c3c80b69..f4ed49701f6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-spectrum.c +++ b/drivers/net/wireless/iwlwifi/iwl-spectrum.c @@ -146,7 +146,7 @@ static int iwl_get_measurement(struct iwl_priv *priv, res = (struct iwl_rx_packet *)cmd.meta.u.skb->data; if (res->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERROR("Bad return from REPLY_RX_ON_ASSOC command\n"); + IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n"); rc = -EIO; } diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 41e9013c742..672574fb526 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -87,7 +87,8 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) spin_lock_irqsave(&priv->sta_lock, flags); if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) - IWL_ERROR("ACTIVATE a non DRIVER active station %d\n", sta_id); + IWL_ERR(priv, "ACTIVATE a non DRIVER active station %d\n", + sta_id); priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE; IWL_DEBUG_ASSOC("Added STA to Ucode: %pM\n", @@ -105,13 +106,13 @@ static int iwl_add_sta_callback(struct iwl_priv *priv, u8 sta_id = addsta->sta.sta_id; if (!skb) { - IWL_ERROR("Error: Response NULL in REPLY_ADD_STA.\n"); + IWL_ERR(priv, "Error: Response NULL in REPLY_ADD_STA.\n"); return 1; } res = (struct iwl_rx_packet *)skb->data; if (res->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n", + IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", res->hdr.flags); return 1; } @@ -155,7 +156,7 @@ static int iwl_send_add_sta(struct iwl_priv *priv, res = (struct iwl_rx_packet *)cmd.meta.u.skb->data; if (res->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n", + IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", res->hdr.flags); ret = -EIO; } @@ -307,7 +308,7 @@ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr) /* Ucode must be active and driver must be non active */ if (priv->stations[sta_id].used != IWL_STA_UCODE_ACTIVE) - IWL_ERROR("removed non active STA %d\n", sta_id); + IWL_ERR(priv, "removed non active STA %d\n", sta_id); priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE; @@ -324,13 +325,13 @@ static int iwl_remove_sta_callback(struct iwl_priv *priv, const char *addr = rm_sta->addr; if (!skb) { - IWL_ERROR("Error: Response NULL in REPLY_REMOVE_STA.\n"); + IWL_ERR(priv, "Error: Response NULL in REPLY_REMOVE_STA.\n"); return 1; } res = (struct iwl_rx_packet *)skb->data; if (res->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERROR("Bad return from REPLY_REMOVE_STA (0x%08X)\n", + IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n", res->hdr.flags); return 1; } @@ -340,7 +341,7 @@ static int iwl_remove_sta_callback(struct iwl_priv *priv, iwl_sta_ucode_deactivate(priv, addr); break; default: - IWL_ERROR("REPLY_REMOVE_STA failed\n"); + IWL_ERR(priv, "REPLY_REMOVE_STA failed\n"); break; } @@ -378,7 +379,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, res = (struct iwl_rx_packet *)cmd.meta.u.skb->data; if (res->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERROR("Bad return from REPLY_REMOVE_STA (0x%08X)\n", + IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n", res->hdr.flags); ret = -EIO; } @@ -391,7 +392,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, break; default: ret = -EIO; - IWL_ERROR("REPLY_REMOVE_STA failed\n"); + IWL_ERR(priv, "REPLY_REMOVE_STA failed\n"); break; } } @@ -433,13 +434,13 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap) sta_id, addr); if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { - IWL_ERROR("Removing %pM but non DRIVER active\n", + IWL_ERR(priv, "Removing %pM but non DRIVER active\n", addr); goto out; } if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) { - IWL_ERROR("Removing %pM but non UCODE active\n", + IWL_ERR(priv, "Removing %pM but non UCODE active\n", addr); goto out; } @@ -475,7 +476,7 @@ void iwl_clear_stations_table(struct iwl_priv *priv) if (iwl_is_alive(priv) && !test_bit(STATUS_EXIT_PENDING, &priv->status) && iwl_send_cmd_pdu_async(priv, REPLY_REMOVE_ALL_STA, 0, NULL, NULL)) - IWL_ERROR("Couldn't clear the station table\n"); + IWL_ERR(priv, "Couldn't clear the station table\n"); priv->num_stations = 0; memset(priv->stations, 0, sizeof(priv->stations)); @@ -548,7 +549,7 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, spin_lock_irqsave(&priv->sta_lock, flags); if (!test_and_clear_bit(keyconf->keyidx, &priv->ucode_key_table)) - IWL_ERROR("index %d not used in uCode key table.\n", + IWL_ERR(priv, "index %d not used in uCode key table.\n", keyconf->keyidx); priv->default_wep_key--; @@ -582,7 +583,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, priv->default_wep_key++; if (test_and_set_bit(keyconf->keyidx, &priv->ucode_key_table)) - IWL_ERROR("index %d already used in uCode key table.\n", + IWL_ERR(priv, "index %d already used in uCode key table.\n", keyconf->keyidx); priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; @@ -820,7 +821,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset, &priv->ucode_key_table)) - IWL_ERROR("index %d not used in uCode key table.\n", + IWL_ERR(priv, "index %d not used in uCode key table.\n", priv->stations[sta_id].sta.key.key_offset); memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key)); @@ -857,7 +858,8 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, ret = iwl_set_wep_dynamic_key_info(priv, keyconf, sta_id); break; default: - IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, keyconf->alg); + IWL_ERR(priv, + "Unknown alg: %s alg = %d\n", __func__, keyconf->alg); ret = -EINVAL; } diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index e829e86181e..77a573f2c6e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -138,7 +138,7 @@ static void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) num_tbs = iwl_tfd_get_num_tbs(tfd); if (num_tbs >= IWL_NUM_OF_TBS) { - IWL_ERROR("Too many chunks: %i\n", num_tbs); + IWL_ERR(priv, "Too many chunks: %i\n", num_tbs); /* @todo issue fatal error, it is quite serious situation */ return; } @@ -171,14 +171,14 @@ static int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, /* Each TFD can point to a maximum 20 Tx buffers */ if (num_tbs >= IWL_NUM_OF_TBS) { - IWL_ERROR("Error can not send more than %d chunks\n", + IWL_ERR(priv, "Error can not send more than %d chunks\n", IWL_NUM_OF_TBS); return -EINVAL; } BUG_ON(addr & ~DMA_BIT_MASK(36)); if (unlikely(addr & ~IWL_TX_DMA_MASK)) - IWL_ERROR("Unaligned address = %llx\n", + IWL_ERR(priv, "Unaligned address = %llx\n", (unsigned long long)addr); iwl_tfd_set_tb(tfd, num_tbs, addr, len); @@ -395,7 +395,7 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv, txq->txb = kmalloc(sizeof(txq->txb[0]) * TFD_QUEUE_SIZE_MAX, GFP_KERNEL); if (!txq->txb) { - IWL_ERROR("kmalloc for auxiliary BD " + IWL_ERR(priv, "kmalloc for auxiliary BD " "structures failed\n"); goto error; } @@ -409,7 +409,7 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv, &txq->q.dma_addr); if (!txq->tfds) { - IWL_ERROR("pci_alloc_consistent(%zd) failed\n", + IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", sizeof(txq->tfds[0]) * TFD_QUEUE_SIZE_MAX); goto error; } @@ -557,13 +557,13 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) ret = iwl_alloc_dma_ptr(priv, &priv->scd_bc_tbls, priv->hw_params.scd_bc_tbls_size); if (ret) { - IWL_ERROR("Scheduler BC Table allocation failed\n"); + IWL_ERR(priv, "Scheduler BC Table allocation failed\n"); goto error_bc_tbls; } /* Alloc keep-warm buffer */ ret = iwl_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE); if (ret) { - IWL_ERROR("Keep Warm allocation failed\n"); + IWL_ERR(priv, "Keep Warm allocation failed\n"); goto error_kw; } spin_lock_irqsave(&priv->lock, flags); @@ -589,7 +589,7 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, txq_id); if (ret) { - IWL_ERROR("Tx %d queue init failed\n", txq_id); + IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); goto error; } } @@ -850,7 +850,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) == IWL_INVALID_RATE) { - IWL_ERROR("ERROR: No TX rate available.\n"); + IWL_ERR(priv, "ERROR: No TX rate available.\n"); goto drop_unlock; } @@ -1086,7 +1086,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) } if (iwl_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) { - IWL_ERROR("No space for Tx\n"); + IWL_ERR(priv, "No space for Tx\n"); return -ENOSPC; } @@ -1163,7 +1163,7 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) int nfreed = 0; if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { - IWL_ERROR("Read index for DMA queue txq id (%d), index %d, " + IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, " "is out of range [0-%d] %d %d.\n", txq_id, index, q->n_bd, q->write_ptr, q->read_ptr); return 0; @@ -1203,7 +1203,7 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int nfreed = 0; if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) { - IWL_ERROR("Read index for DMA queue txq id (%d), index %d, " + IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, " "is out of range [0-%d] %d %d.\n", txq_id, idx, q->n_bd, q->write_ptr, q->read_ptr); return; @@ -1218,7 +1218,7 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { if (nfreed++ > 0) { - IWL_ERROR("HCMD skipped: index (%d) %d %d\n", idx, + IWL_ERR(priv, "HCMD skipped: index (%d) %d %d\n", idx, q->write_ptr, q->read_ptr); queue_work(priv->workqueue, &priv->restart); } @@ -1314,7 +1314,7 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) return -ENXIO; if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) { - IWL_ERROR("Start AGG when state is not IWL_AGG_OFF !\n"); + IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n"); return -ENXIO; } @@ -1354,7 +1354,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) unsigned long flags; if (!ra) { - IWL_ERROR("ra = NULL\n"); + IWL_ERR(priv, "ra = NULL\n"); return -EINVAL; } @@ -1455,7 +1455,7 @@ static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv, struct ieee80211_tx_info *info; if (unlikely(!agg->wait_for_ba)) { - IWL_ERROR("Received BA when not expected\n"); + IWL_ERR(priv, "Received BA when not expected\n"); return -EINVAL; } @@ -1528,7 +1528,8 @@ void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); if (scd_flow >= priv->hw_params.max_txq_num) { - IWL_ERROR("BUG_ON scd_flow is bigger than number of queues\n"); + IWL_ERR(priv, + "BUG_ON scd_flow is bigger than number of queues\n"); return; } diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 26f53647bf3..52c9075b188 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -185,7 +185,7 @@ static int iwl3945_tx_queue_alloc(struct iwl_priv *priv, txq->txb = kmalloc(sizeof(txq->txb[0]) * TFD_QUEUE_SIZE_MAX, GFP_KERNEL); if (!txq->txb) { - IWL_ERROR("kmalloc for auxiliary BD " + IWL_ERR(priv, "kmalloc for auxiliary BD " "structures failed\n"); goto error; } @@ -199,7 +199,7 @@ static int iwl3945_tx_queue_alloc(struct iwl_priv *priv, &txq->q.dma_addr); if (!txq->bd) { - IWL_ERROR("pci_alloc_consistent(%zd) failed\n", + IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX); goto error; } @@ -528,7 +528,7 @@ static int iwl3945_enqueue_hcmd(struct iwl_priv *priv, struct iwl3945_host_cmd * } if (iwl_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) { - IWL_ERROR("No space for Tx\n"); + IWL_ERR(priv, "No space for Tx\n"); return -ENOSPC; } @@ -596,8 +596,9 @@ static int iwl3945_send_cmd_async(struct iwl_priv *priv, struct iwl3945_host_cmd ret = iwl3945_enqueue_hcmd(priv, cmd); if (ret < 0) { - IWL_ERROR("Error sending %s: iwl3945_enqueue_hcmd failed: %d\n", - get_cmd_string(cmd->id), ret); + IWL_ERR(priv, + "Error sending %s: iwl3945_enqueue_hcmd failed: %d\n", + get_cmd_string(cmd->id), ret); return ret; } return 0; @@ -614,8 +615,9 @@ static int iwl3945_send_cmd_sync(struct iwl_priv *priv, struct iwl3945_host_cmd BUG_ON(cmd->meta.u.callback != NULL); if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) { - IWL_ERROR("Error sending %s: Already sending a host command\n", - get_cmd_string(cmd->id)); + IWL_ERR(priv, + "Error sending %s: Already sending a host command\n", + get_cmd_string(cmd->id)); ret = -EBUSY; goto out; } @@ -628,8 +630,9 @@ static int iwl3945_send_cmd_sync(struct iwl_priv *priv, struct iwl3945_host_cmd cmd_idx = iwl3945_enqueue_hcmd(priv, cmd); if (cmd_idx < 0) { ret = cmd_idx; - IWL_ERROR("Error sending %s: iwl3945_enqueue_hcmd failed: %d\n", - get_cmd_string(cmd->id), ret); + IWL_ERR(priv, + "Error sending %s: iwl3945_enqueue_hcmd failed: %d\n", + get_cmd_string(cmd->id), ret); goto out; } @@ -638,7 +641,7 @@ static int iwl3945_send_cmd_sync(struct iwl_priv *priv, struct iwl3945_host_cmd HOST_COMPLETE_TIMEOUT); if (!ret) { if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) { - IWL_ERROR("Error sending %s: time out after %dms.\n", + IWL_ERR(priv, "Error sending %s: time out after %dms\n", get_cmd_string(cmd->id), jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); @@ -661,7 +664,7 @@ static int iwl3945_send_cmd_sync(struct iwl_priv *priv, struct iwl3945_host_cmd goto fail; } if ((cmd->meta.flags & CMD_WANT_SKB) && !cmd->meta.u.skb) { - IWL_ERROR("Error: Response NULL in '%s'\n", + IWL_ERR(priv, "Error: Response NULL in '%s'\n", get_cmd_string(cmd->id)); ret = -EIO; goto cancel; @@ -837,7 +840,7 @@ static int iwl3945_check_rxon_cmd(struct iwl_priv *priv) le16_to_cpu(rxon->channel)); if (error) { - IWL_ERROR("Not a valid iwl3945_rxon_assoc_cmd field values\n"); + IWL_ERR(priv, "Not a valid rxon_assoc_cmd field values\n"); return -1; } return 0; @@ -920,7 +923,7 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) res = (struct iwl_rx_packet *)cmd.meta.u.skb->data; if (res->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERROR("Bad return from REPLY_RXON_ASSOC command\n"); + IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n"); rc = -EIO; } @@ -957,7 +960,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) rc = iwl3945_check_rxon_cmd(priv); if (rc) { - IWL_ERROR("Invalid RXON configuration. Not committing.\n"); + IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); return -EINVAL; } @@ -967,7 +970,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) if (!iwl3945_full_rxon_required(priv)) { rc = iwl3945_send_rxon_assoc(priv); if (rc) { - IWL_ERROR("Error setting RXON_ASSOC " + IWL_ERR(priv, "Error setting RXON_ASSOC " "configuration (%d).\n", rc); return rc; } @@ -994,7 +997,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) * active_rxon back to what it was previously */ if (rc) { active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK; - IWL_ERROR("Error clearing ASSOC_MSK on current " + IWL_ERR(priv, "Error clearing ASSOC_MSK on current " "configuration (%d).\n", rc); return rc; } @@ -1013,7 +1016,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON, sizeof(struct iwl3945_rxon_cmd), &priv->staging39_rxon); if (rc) { - IWL_ERROR("Error setting new configuration (%d).\n", rc); + IWL_ERR(priv, "Error setting new configuration (%d).\n", rc); return rc; } @@ -1025,14 +1028,14 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) * send a new TXPOWER command or we won't be able to Tx any frames */ rc = iwl3945_hw_reg_send_txpower(priv); if (rc) { - IWL_ERROR("Error setting Tx power (%d).\n", rc); + IWL_ERR(priv, "Error setting Tx power (%d).\n", rc); return rc; } /* Add the broadcast address so we can send broadcast frames */ if (iwl3945_add_station(priv, iwl_bcast_addr, 0, 0) == IWL_INVALID_STATION) { - IWL_ERROR("Error adding BROADCAST address for transmit.\n"); + IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n"); return -EIO; } @@ -1042,14 +1045,14 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) (priv->iw_mode == NL80211_IFTYPE_STATION)) if (iwl3945_add_station(priv, priv->active39_rxon.bssid_addr, 1, 0) == IWL_INVALID_STATION) { - IWL_ERROR("Error adding AP address for transmit.\n"); + IWL_ERR(priv, "Error adding AP address for transmit\n"); return -EIO; } /* Init the hardware's rate fallback order based on the band */ rc = iwl3945_init_hw_rate_table(priv); if (rc) { - IWL_ERROR("Error setting HW rate table: %02X\n", rc); + IWL_ERR(priv, "Error setting HW rate table: %02X\n", rc); return -EIO; } @@ -1149,13 +1152,13 @@ static int iwl3945_add_sta_sync_callback(struct iwl_priv *priv, struct iwl_rx_packet *res = NULL; if (!skb) { - IWL_ERROR("Error: Response NULL in REPLY_ADD_STA.\n"); + IWL_ERR(priv, "Error: Response NULL in REPLY_ADD_STA.\n"); return 1; } res = (struct iwl_rx_packet *)skb->data; if (res->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n", + IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", res->hdr.flags); return 1; } @@ -1195,7 +1198,7 @@ int iwl3945_send_add_station(struct iwl_priv *priv, res = (struct iwl_rx_packet *)cmd.meta.u.skb->data; if (res->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n", + IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", res->hdr.flags); rc = -EIO; } @@ -1302,7 +1305,7 @@ static struct iwl3945_frame *iwl3945_get_free_frame(struct iwl_priv *priv) if (list_empty(&priv->free_frames)) { frame = kzalloc(sizeof(*frame), GFP_KERNEL); if (!frame) { - IWL_ERROR("Could not allocate frame!\n"); + IWL_ERR(priv, "Could not allocate frame!\n"); return NULL; } @@ -1373,7 +1376,7 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv) frame = iwl3945_get_free_frame(priv); if (!frame) { - IWL_ERROR("Could not obtain free frame buffer for beacon " + IWL_ERR(priv, "Could not obtain free frame buffer for beacon " "command.\n"); return -ENOMEM; } @@ -1437,14 +1440,14 @@ int iwl3945_eeprom_init(struct iwl_priv *priv) BUILD_BUG_ON(sizeof(priv->eeprom39) != IWL_EEPROM_IMAGE_SIZE); if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) { - IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x\n", gp); + IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); return -ENOENT; } /* Make sure driver (instead of uCode) is allowed to read EEPROM */ ret = iwl3945_eeprom_acquire_semaphore(priv); if (ret < 0) { - IWL_ERROR("Failed to acquire EEPROM semaphore.\n"); + IWL_ERR(priv, "Failed to acquire EEPROM semaphore.\n"); return -ENOENT; } @@ -1459,7 +1462,7 @@ int iwl3945_eeprom_init(struct iwl_priv *priv) CSR_EEPROM_REG_READ_VALID_MSK, IWL_EEPROM_ACCESS_TIMEOUT); if (ret < 0) { - IWL_ERROR("Time out reading EEPROM[%d]\n", addr); + IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr); return ret; } @@ -2120,7 +2123,7 @@ static void iwl3945_connection_init_rx_config(struct iwl_priv *priv, RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK; break; default: - IWL_ERROR("Unsupported interface type %d\n", mode); + IWL_ERR(priv, "Unsupported interface type %d\n", mode); break; } @@ -2170,7 +2173,7 @@ static int iwl3945_set_mode(struct iwl_priv *priv, int mode) le16_to_cpu(priv->staging39_rxon.channel)); if (!ch_info || !is_channel_ibss(ch_info)) { - IWL_ERROR("channel %d not IBSS channel\n", + IWL_ERR(priv, "channel %d not IBSS channel\n", le16_to_cpu(priv->staging39_rxon.channel)); return -EINVAL; } @@ -2403,7 +2406,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) } if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) == IWL_INVALID_RATE) { - IWL_ERROR("ERROR: No TX rate available.\n"); + IWL_ERR(priv, "ERROR: No TX rate available.\n"); goto drop_unlock; } @@ -2603,7 +2606,7 @@ static void iwl3945_set_rate(struct iwl_priv *priv) sband = iwl3945_get_band(priv, priv->band); if (!sband) { - IWL_ERROR("Failed to set rate: unable to get hw mode\n"); + IWL_ERR(priv, "Failed to set rate: unable to get hw mode\n"); return; } @@ -2836,7 +2839,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, res = (struct iwl_rx_packet *)cmd.meta.u.skb->data; if (res->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERROR("Bad return from REPLY_RX_ON_ASSOC command\n"); + IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n"); rc = -EIO; } @@ -2913,7 +2916,7 @@ static void iwl3945_rx_reply_error(struct iwl_priv *priv, { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; - IWL_ERROR("Error Reply type 0x%08X cmd %s (0x%02X) " + IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) " "seq 0x%04X ser 0x%08X\n", le32_to_cpu(pkt->u.err_resp.error_type), get_cmd_string(pkt->u.err_resp.cmd_id), @@ -2985,7 +2988,7 @@ static void iwl3945_bg_beacon_update(struct work_struct *work) beacon = ieee80211_beacon_get(priv->hw, priv->vif); if (!beacon) { - IWL_ERROR("update beacon failed\n"); + IWL_ERR(priv, "update beacon failed\n"); return; } @@ -3232,7 +3235,7 @@ static void iwl3945_cmd_queue_reclaim(struct iwl_priv *priv, int nfreed = 0; if ((index >= q->n_bd) || (iwl3945_x2_queue_used(q, index) == 0)) { - IWL_ERROR("Read index for DMA queue txq id (%d), index %d, " + IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, " "is out of range [0-%d] %d %d.\n", txq_id, index, q->n_bd, q->write_ptr, q->read_ptr); return; @@ -3241,7 +3244,7 @@ static void iwl3945_cmd_queue_reclaim(struct iwl_priv *priv, for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index; q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { if (nfreed > 1) { - IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index, + IWL_ERR(priv, "HCMD skipped: index (%d) %d %d\n", index, q->write_ptr, q->read_ptr); queue_work(priv->workqueue, &priv->restart); break; @@ -3955,7 +3958,7 @@ static void iwl3945_dump_nic_error_log(struct iwl_priv *priv) base = le32_to_cpu(priv->card_alive.error_event_table_ptr); if (!iwl3945_hw_valid_rtc_data_addr(base)) { - IWL_ERROR("Not valid error log pointer 0x%08X\n", base); + IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base); return; } @@ -3968,11 +3971,12 @@ static void iwl3945_dump_nic_error_log(struct iwl_priv *priv) count = iwl_read_targ_mem(priv, base); if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { - IWL_ERROR("Start IWL Error Log Dump:\n"); - IWL_ERROR("Status: 0x%08lX, count: %d\n", priv->status, count); + IWL_ERR(priv, "Start IWL Error Log Dump:\n"); + IWL_ERR(priv, "Status: 0x%08lX, count: %d\n", + priv->status, count); } - IWL_ERROR("Desc Time asrtPC blink2 " + IWL_ERR(priv, "Desc Time asrtPC blink2 " "ilink1 nmiPC Line\n"); for (i = ERROR_START_OFFSET; i < (count * ERROR_ELEM_SIZE) + ERROR_START_OFFSET; @@ -3991,10 +3995,10 @@ static void iwl3945_dump_nic_error_log(struct iwl_priv *priv) data1 = iwl_read_targ_mem(priv, base + i + 6 * sizeof(u32)); - IWL_ERROR - ("%-13s (#%d) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n", - desc_lookup(desc), desc, time, blink1, blink2, - ilink1, ilink2, data1); + IWL_ERR(priv, + "%-13s (#%d) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n", + desc_lookup(desc), desc, time, blink1, blink2, + ilink1, ilink2, data1); } iwl_release_nic_access(priv); @@ -4036,12 +4040,13 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, ptr += sizeof(u32); time = iwl_read_targ_mem(priv, ptr); ptr += sizeof(u32); - if (mode == 0) - IWL_ERROR("0x%08x\t%04u\n", time, ev); /* data, ev */ - else { + if (mode == 0) { + /* data, ev */ + IWL_ERR(priv, "0x%08x\t%04u\n", time, ev); + } else { data = iwl_read_targ_mem(priv, ptr); ptr += sizeof(u32); - IWL_ERROR("%010u\t0x%08x\t%04u\n", time, data, ev); + IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", time, data, ev); } } } @@ -4058,7 +4063,7 @@ static void iwl3945_dump_nic_event_log(struct iwl_priv *priv) base = le32_to_cpu(priv->card_alive.log_event_table_ptr); if (!iwl3945_hw_valid_rtc_data_addr(base)) { - IWL_ERROR("Invalid event log pointer 0x%08X\n", base); + IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); return; } @@ -4078,12 +4083,12 @@ static void iwl3945_dump_nic_event_log(struct iwl_priv *priv) /* bail out if nothing in log */ if (size == 0) { - IWL_ERROR("Start IWL Event Log Dump: nothing in log\n"); + IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); iwl_release_nic_access(priv); return; } - IWL_ERROR("Start IWL Event Log Dump: display count %d, wraps %d\n", + IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n", size, num_wraps); /* if uCode has wrapped back to top of log, start at the oldest entry, @@ -4196,7 +4201,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) /* Now service all interrupt bits discovered above. */ if (inta & CSR_INT_BIT_HW_ERR) { - IWL_ERROR("Microcode HW error detected. Restarting.\n"); + IWL_ERR(priv, "Microcode HW error detected. Restarting.\n"); /* Tell the device to stop sending interrupts */ iwl3945_disable_interrupts(priv); @@ -4227,8 +4232,8 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) /* Error detected by uCode */ if (inta & CSR_INT_BIT_SW_ERR) { - IWL_ERROR("Microcode SW error detected. Restarting 0x%X.\n", - inta); + IWL_ERR(priv, "Microcode SW error detected. " + "Restarting 0x%X.\n", inta); iwl3945_irq_handle_error(priv); handled |= CSR_INT_BIT_SW_ERR; } @@ -4268,7 +4273,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) } if (inta & ~handled) - IWL_ERROR("Unhandled INTA bits 0x%08x\n", inta & ~handled); + IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled); if (inta & ~CSR_INI_SET_MASK) { IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", @@ -4510,7 +4515,7 @@ static int iwl3945_init_channel_map(struct iwl_priv *priv) priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) * priv->channel_count, GFP_KERNEL); if (!priv->channel_info) { - IWL_ERROR("Could not allocate channel_info\n"); + IWL_ERR(priv, "Could not allocate channel_info\n"); priv->channel_count = 0; return -ENOMEM; } @@ -4949,7 +4954,7 @@ static int iwl3945_verify_inst_full(struct iwl_priv *priv, __le32 *image, u32 le * if IWL_DL_IO is set */ val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); if (val != le32_to_cpu(*image)) { - IWL_ERROR("uCode INST section is invalid at " + IWL_ERR(priv, "uCode INST section is invalid at " "offset 0x%x, is 0x%x, s/b 0x%x\n", save_len - len, val, le32_to_cpu(*image)); rc = -EIO; @@ -4995,7 +5000,7 @@ static int iwl3945_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); if (val != le32_to_cpu(*image)) { #if 0 /* Enable this if you want to see details */ - IWL_ERROR("uCode INST section is invalid at " + IWL_ERR(priv, "uCode INST section is invalid at " "offset 0x%x, is 0x%x, s/b 0x%x\n", i, val, *image); #endif @@ -5049,7 +5054,7 @@ static int iwl3945_verify_ucode(struct iwl_priv *priv) return 0; } - IWL_ERROR("NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n"); + IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n"); /* Since nothing seems to match, show first several data entries in * instruction SRAM, so maybe visual inspection will give a clue. @@ -5079,7 +5084,7 @@ static int iwl3945_verify_bsm(struct iwl_priv *priv) reg += sizeof(u32), image++) { val = iwl_read_prph(priv, reg); if (val != le32_to_cpu(*image)) { - IWL_ERROR("BSM uCode verification failed at " + IWL_ERR(priv, "BSM uCode verification failed at " "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n", BSM_SRAM_LOWER_BOUND, reg - BSM_SRAM_LOWER_BOUND, len, @@ -5197,7 +5202,7 @@ static int iwl3945_load_bsm(struct iwl_priv *priv) if (i < 100) IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i); else { - IWL_ERROR("BSM write did not complete!\n"); + IWL_ERR(priv, "BSM write did not complete!\n"); return -EIO; } @@ -5242,7 +5247,7 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) sprintf(buf, "%s%u%s", name_pre, index, ".ucode"); ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev); if (ret < 0) { - IWL_ERROR("%s firmware file req failed: Reason %d\n", + IWL_ERR(priv, "%s firmware file req failed: %d\n", buf, ret); if (ret == -ENOENT) continue; @@ -5250,7 +5255,9 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) goto error; } else { if (index < api_max) - IWL_ERROR("Loaded firmware %s, which is deprecated. Please use API v%u instead.\n", + IWL_ERR(priv, "Loaded firmware %s, " + "which is deprecated. " + " Please use API v%u instead.\n", buf, api_max); IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n", buf, ucode_raw->size); @@ -5263,7 +5270,7 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) /* Make sure that we got at least our header! */ if (ucode_raw->size < sizeof(*ucode)) { - IWL_ERROR("File size way too small!\n"); + IWL_ERR(priv, "File size way too small!\n"); ret = -EINVAL; goto err_release; } @@ -5284,7 +5291,7 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) * on the API version read from firware header from here on forward */ if (api_ver < api_min || api_ver > api_max) { - IWL_ERROR("Driver unable to support your firmware API. " + IWL_ERR(priv, "Driver unable to support your firmware API. " "Driver supports v%u, firmware is v%u.\n", api_max, api_ver); priv->ucode_ver = 0; @@ -5292,7 +5299,7 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) goto err_release; } if (api_ver != api_max) - IWL_ERROR("Firmware has old API version. Expected %u, " + IWL_ERR(priv, "Firmware has old API version. Expected %u, " "got %u. New firmware can be obtained " "from http://www.intellinuxwireless.org.\n", api_max, api_ver); @@ -5443,7 +5450,7 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) return 0; err_pci_alloc: - IWL_ERROR("failed to allocate pci memory\n"); + IWL_ERR(priv, "failed to allocate pci memory\n"); ret = -ENOMEM; iwl3945_dealloc_ucode_pci(priv); @@ -5795,7 +5802,7 @@ static int __iwl3945_up(struct iwl_priv *priv) } if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) { - IWL_ERROR("ucode not available for device bring up\n"); + IWL_ERR(priv, "ucode not available for device bring up\n"); return -EIO; } @@ -5815,7 +5822,7 @@ static int __iwl3945_up(struct iwl_priv *priv) rc = iwl3945_hw_nic_init(priv); if (rc) { - IWL_ERROR("Unable to int nic\n"); + IWL_ERR(priv, "Unable to int nic\n"); return rc; } @@ -5852,7 +5859,8 @@ static int __iwl3945_up(struct iwl_priv *priv) rc = iwl3945_load_bsm(priv); if (rc) { - IWL_ERROR("Unable to set up bootstrap uCode: %d\n", rc); + IWL_ERR(priv, + "Unable to set up bootstrap uCode: %d\n", rc); continue; } @@ -5870,7 +5878,7 @@ static int __iwl3945_up(struct iwl_priv *priv) /* tried to restart and config the device for as long as our * patience could withstand */ - IWL_ERROR("Unable to initialize device after %d attempts.\n", i); + IWL_ERR(priv, "Unable to initialize device after %d attempts.\n", i); return -EIO; } @@ -6203,7 +6211,7 @@ static void iwl3945_post_associate(struct iwl_priv *priv) struct ieee80211_conf *conf = NULL; if (priv->iw_mode == NL80211_IFTYPE_AP) { - IWL_ERROR("%s Should not be called in AP mode\n", __func__); + IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); return; } @@ -6276,7 +6284,7 @@ static void iwl3945_post_associate(struct iwl_priv *priv) break; default: - IWL_ERROR("%s Should not be called in %d mode\n", + IWL_ERR(priv, "%s Should not be called in %d mode\n", __func__, priv->iw_mode); break; } @@ -6342,7 +6350,7 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) IWL_DEBUG_MAC80211("enter\n"); if (pci_enable_device(priv->pci_dev)) { - IWL_ERROR("Fail to pci_enable_device\n"); + IWL_ERR(priv, "Fail to pci_enable_device\n"); return -ENODEV; } pci_restore_state(priv->pci_dev); @@ -6351,7 +6359,7 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) ret = request_irq(priv->pci_dev->irq, iwl3945_isr, IRQF_SHARED, DRV_NAME, priv); if (ret) { - IWL_ERROR("Error allocating IRQ %d\n", priv->pci_dev->irq); + IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); goto out_disable_msi; } @@ -6365,7 +6373,7 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) if (!priv->ucode_code.len) { ret = iwl3945_read_ucode(priv); if (ret) { - IWL_ERROR("Could not read microcode: %d\n", ret); + IWL_ERR(priv, "Could not read microcode: %d\n", ret); mutex_unlock(&priv->mutex); goto out_release_irq; } @@ -6392,8 +6400,9 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) UCODE_READY_TIMEOUT); if (!ret) { if (!test_bit(STATUS_READY, &priv->status)) { - IWL_ERROR("Wait for START_ALIVE timeout after %dms.\n", - jiffies_to_msecs(UCODE_READY_TIMEOUT)); + IWL_ERR(priv, + "Wait for START_ALIVE timeout after %dms.\n", + jiffies_to_msecs(UCODE_READY_TIMEOUT)); ret = -ETIMEDOUT; goto out_release_irq; } @@ -7738,8 +7747,9 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e if ((iwl3945_param_queues_num > IWL39_MAX_NUM_QUEUES) || (iwl3945_param_queues_num < IWL_MIN_NUM_QUEUES)) { - IWL_ERROR("invalid queues_num, should be between %d and %d\n", - IWL_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES); + IWL_ERR(priv, + "invalid queues_num, should be between %d and %d\n", + IWL_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES); err = -EINVAL; goto out; } @@ -7833,7 +7843,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e /* Read the EEPROM */ err = iwl3945_eeprom_init(priv); if (err) { - IWL_ERROR("Unable to init EEPROM\n"); + IWL_ERR(priv, "Unable to init EEPROM\n"); goto out_remove_sysfs; } /* MAC Address location in EEPROM same for 3945/4965 */ @@ -7846,7 +7856,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e * ********************/ /* Device-specific setup */ if (iwl3945_hw_set_hw_params(priv)) { - IWL_ERROR("failed to set hw settings\n"); + IWL_ERR(priv, "failed to set hw settings\n"); goto out_iounmap; } @@ -7887,13 +7897,13 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e err = iwl3945_init_channel_map(priv); if (err) { - IWL_ERROR("initializing regulatory failed: %d\n", err); + IWL_ERR(priv, "initializing regulatory failed: %d\n", err); goto out_release_irq; } err = iwl3945_init_geos(priv); if (err) { - IWL_ERROR("initializing geos failed: %d\n", err); + IWL_ERR(priv, "initializing geos failed: %d\n", err); goto out_free_channel_map; } @@ -7922,7 +7932,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group); if (err) { - IWL_ERROR("failed to create sysfs device attributes\n"); + IWL_ERR(priv, "failed to create sysfs device attributes\n"); goto out_free_geos; } @@ -7942,7 +7952,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e err = ieee80211_register_hw(priv->hw); if (err) { - IWL_ERROR("Failed to register network device (error %d)\n", err); + IWL_ERR(priv, "Failed to register network device: %d\n", err); goto out_remove_sysfs; } @@ -7952,7 +7962,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e err = iwl3945_rfkill_init(priv); if (err) - IWL_ERROR("Unable to initialize RFKILL system. " + IWL_ERR(priv, "Unable to initialize RFKILL system. " "Ignoring error: %d\n", err); return 0; @@ -8124,7 +8134,7 @@ int iwl3945_rfkill_init(struct iwl_priv *priv) IWL_DEBUG_RF_KILL("Initializing RFKILL.\n"); priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); if (!priv->rfkill) { - IWL_ERROR("Unable to allocate rfkill device.\n"); + IWL_ERR(priv, "Unable to allocate rfkill device.\n"); ret = -ENOMEM; goto error; } @@ -8140,7 +8150,7 @@ int iwl3945_rfkill_init(struct iwl_priv *priv) ret = rfkill_register(priv->rfkill); if (ret) { - IWL_ERROR("Unable to register rfkill: %d\n", ret); + IWL_ERR(priv, "Unable to register rfkill: %d\n", ret); goto freed_rfkill; } -- GitLab From c2d79b488a33a77d337092c967ce50614edc5d25 Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Fri, 19 Dec 2008 10:37:34 +0800 Subject: [PATCH 0728/4982] iwlwifi: use iwl_cmd instead of iwl3945_cmd This patch makes use of iwl_cmd instead of iwl3945_cmd and related structures which were just the same. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-led.c | 4 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 22 ++++---- drivers/net/wireless/iwlwifi/iwl-3945.h | 61 +-------------------- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 54 +++++++++--------- 5 files changed, 44 insertions(+), 99 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index 958e705ec33..10e68d64e6c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -68,7 +68,7 @@ static const struct { #define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1) static int iwl3945_led_cmd_callback(struct iwl_priv *priv, - struct iwl3945_cmd *cmd, + struct iwl_cmd *cmd, struct sk_buff *skb) { return 1; @@ -83,7 +83,7 @@ static inline int iwl3945_brightness_to_idx(enum led_brightness brightness) static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) { - struct iwl3945_host_cmd cmd = { + struct iwl_host_cmd cmd = { .id = REPLY_LEDS_CMD, .len = sizeof(struct iwl_led_cmd), .data = led_cmd, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 8cf40bcd6a0..422de88f128 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -826,8 +826,7 @@ u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *addr) * iwl3945_hw_build_tx_cmd_rate - Add rate portion to TX_CMD: * */ -void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, - struct iwl3945_cmd *cmd, +void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, struct iwl_cmd *cmd, struct ieee80211_tx_info *info, struct ieee80211_hdr *hdr, int sta_id, int tx_id) { @@ -839,9 +838,10 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, u8 data_retry_limit; __le32 tx_flags; __le16 fc = hdr->frame_control; + struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload; rate = iwl3945_rates[rate_index].plcp; - tx_flags = cmd->cmd.tx.tx_flags; + tx_flags = tx->tx_flags; /* We need to figure out how to get the sta->supp_rates while * in this running context */ @@ -878,22 +878,22 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, } } - cmd->cmd.tx.rts_retry_limit = rts_retry_limit; - cmd->cmd.tx.data_retry_limit = data_retry_limit; - cmd->cmd.tx.rate = rate; - cmd->cmd.tx.tx_flags = tx_flags; + tx->rts_retry_limit = rts_retry_limit; + tx->data_retry_limit = data_retry_limit; + tx->rate = rate; + tx->tx_flags = tx_flags; /* OFDM */ - cmd->cmd.tx.supp_rates[0] = + tx->supp_rates[0] = ((rate_mask & IWL_OFDM_RATES_MASK) >> IWL_FIRST_OFDM_RATE) & 0xFF; /* CCK */ - cmd->cmd.tx.supp_rates[1] = (rate_mask & 0xF); + tx->supp_rates[1] = (rate_mask & 0xF); IWL_DEBUG_RATE("Tx sta id: %d, rate: %d (plcp), flags: 0x%4X " "cck/ofdm mask: 0x%x/0x%x\n", sta_id, - cmd->cmd.tx.rate, le32_to_cpu(cmd->cmd.tx.tx_flags), - cmd->cmd.tx.supp_rates[1], cmd->cmd.tx.supp_rates[0]); + tx->rate, le32_to_cpu(tx->tx_flags), + tx->supp_rates[1], tx->supp_rates[0]); } u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 63bf832ef76..18424a308d1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -147,62 +147,6 @@ struct iwl3945_frame { #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) -struct iwl3945_cmd; -struct iwl_priv; - -struct iwl3945_cmd_meta { - struct iwl3945_cmd_meta *source; - union { - struct sk_buff *skb; - int (*callback)(struct iwl_priv *priv, - struct iwl3945_cmd *cmd, struct sk_buff *skb); - } __attribute__ ((packed)) u; - - /* The CMD_SIZE_HUGE flag bit indicates that the command - * structure is stored at the end of the shared queue memory. */ - u32 flags; - -} __attribute__ ((packed)); - -/** - * struct iwl3945_cmd - * - * For allocation of the command and tx queues, this establishes the overall - * size of the largest command we send to uCode, except for a scan command - * (which is relatively huge; space is allocated separately). - */ -struct iwl3945_cmd { - struct iwl3945_cmd_meta meta; - struct iwl_cmd_header hdr; - union { - struct iwl3945_addsta_cmd addsta; - struct iwl_led_cmd led; - u32 flags; - u8 val8; - u16 val16; - u32 val32; - struct iwl_bt_cmd bt; - struct iwl_rxon_time_cmd rxon_time; - struct iwl_powertable_cmd powertable; - struct iwl_qosparam_cmd qosparam; - struct iwl3945_tx_cmd tx; - struct iwl3945_tx_beacon_cmd tx_beacon; - struct iwl3945_rxon_assoc_cmd rxon_assoc; - u8 *indirect; - u8 payload[360]; - } __attribute__ ((packed)) cmd; -} __attribute__ ((packed)); - -struct iwl3945_host_cmd { - u8 id; - u16 len; - struct iwl3945_cmd_meta meta; - const void *data; -}; - -#define TFD39_MAX_PAYLOAD_SIZE (sizeof(struct iwl3945_cmd) - \ - sizeof(struct iwl3945_cmd_meta)) - /* * RX related structures and functions */ @@ -288,7 +232,7 @@ extern void iwl3945_tx_queue_free(struct iwl_priv *priv, struct iwl3945_tx_queue extern int iwl3945_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data); extern int __must_check iwl3945_send_cmd(struct iwl_priv *priv, - struct iwl3945_host_cmd *cmd); + struct iwl_host_cmd *cmd); extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, struct ieee80211_hdr *hdr,int left); extern int iwl3945_rx_queue_update_write_ptr(struct iwl_priv *priv, @@ -340,8 +284,7 @@ extern int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, extern unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv, struct iwl3945_frame *frame, u8 rate); extern int iwl3945_hw_get_rx_read(struct iwl_priv *priv); -extern void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, - struct iwl3945_cmd *cmd, +void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, struct iwl_cmd *cmd, struct ieee80211_tx_info *info, struct ieee80211_hdr *hdr, int sta_id, int tx_id); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 5cc6c5e1865..6a07a686f85 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -240,7 +240,7 @@ struct iwl_channel_info { struct iwl3945_tx_queue { struct iwl_queue q; struct iwl3945_tfd_frame *bd; - struct iwl3945_cmd *cmd; + struct iwl_cmd *cmd; dma_addr_t dma_addr_cmd; struct iwl3945_tx_info *txb; int need_update; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 52c9075b188..0af710b8fb7 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -232,7 +232,7 @@ int iwl3945_tx_queue_init(struct iwl_priv *priv, * For data Tx queues (all other queues), no super-size command * space is needed. */ - len = sizeof(struct iwl3945_cmd) * slots_num; + len = sizeof(struct iwl_cmd) * slots_num; if (txq_id == IWL_CMD_QUEUE_NUM) len += IWL_MAX_SCAN_SIZE; txq->cmd = pci_alloc_consistent(dev, len, &txq->dma_addr_cmd); @@ -283,7 +283,7 @@ void iwl3945_tx_queue_free(struct iwl_priv *priv, struct iwl3945_tx_queue *txq) q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) iwl3945_hw_txq_free_tfd(priv, txq); - len = sizeof(struct iwl3945_cmd) * q->n_window; + len = sizeof(struct iwl_cmd) * q->n_window; if (q->id == IWL_CMD_QUEUE_NUM) len += IWL_MAX_SCAN_SIZE; @@ -500,13 +500,13 @@ static inline int iwl3945_is_ready_rf(struct iwl_priv *priv) * failed. On success, it turns the index (> 0) of command in the * command queue. */ -static int iwl3945_enqueue_hcmd(struct iwl_priv *priv, struct iwl3945_host_cmd *cmd) +static int iwl3945_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { struct iwl3945_tx_queue *txq = &priv->txq39[IWL_CMD_QUEUE_NUM]; struct iwl_queue *q = &txq->q; struct iwl3945_tfd_frame *tfd; u32 *control_flags; - struct iwl3945_cmd *out_cmd; + struct iwl_cmd *out_cmd; u32 idx; u16 fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); dma_addr_t phys_addr; @@ -518,7 +518,7 @@ static int iwl3945_enqueue_hcmd(struct iwl_priv *priv, struct iwl3945_host_cmd * /* If any of the command structures end up being larger than * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then * we will need to increase the size of the TFD entries */ - BUG_ON((fix_size > TFD39_MAX_PAYLOAD_SIZE) && + BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && !(cmd->meta.flags & CMD_SIZE_HUGE)); @@ -556,7 +556,7 @@ static int iwl3945_enqueue_hcmd(struct iwl_priv *priv, struct iwl3945_host_cmd * out_cmd->hdr.sequence |= SEQ_HUGE_FRAME; phys_addr = txq->dma_addr_cmd + sizeof(txq->cmd[0]) * idx + - offsetof(struct iwl3945_cmd, hdr); + offsetof(struct iwl_cmd, hdr); iwl3945_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size); pad = U32_PAD(cmd->len); @@ -579,7 +579,8 @@ static int iwl3945_enqueue_hcmd(struct iwl_priv *priv, struct iwl3945_host_cmd * return ret ? ret : idx; } -static int iwl3945_send_cmd_async(struct iwl_priv *priv, struct iwl3945_host_cmd *cmd) +static int iwl3945_send_cmd_async(struct iwl_priv *priv, + struct iwl_host_cmd *cmd) { int ret; @@ -604,7 +605,8 @@ static int iwl3945_send_cmd_async(struct iwl_priv *priv, struct iwl3945_host_cmd return 0; } -static int iwl3945_send_cmd_sync(struct iwl_priv *priv, struct iwl3945_host_cmd *cmd) +static int iwl3945_send_cmd_sync(struct iwl_priv *priv, + struct iwl_host_cmd *cmd) { int cmd_idx; int ret; @@ -675,7 +677,7 @@ static int iwl3945_send_cmd_sync(struct iwl_priv *priv, struct iwl3945_host_cmd cancel: if (cmd->meta.flags & CMD_WANT_SKB) { - struct iwl3945_cmd *qcmd; + struct iwl_cmd *qcmd; /* Cancel the CMD_WANT_SKB flag for the cmd in the * TX cmd queue. Otherwise in case the cmd comes @@ -694,7 +696,7 @@ out: return ret; } -int iwl3945_send_cmd(struct iwl_priv *priv, struct iwl3945_host_cmd *cmd) +int iwl3945_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { if (cmd->meta.flags & CMD_ASYNC) return iwl3945_send_cmd_async(priv, cmd); @@ -704,7 +706,7 @@ int iwl3945_send_cmd(struct iwl_priv *priv, struct iwl3945_host_cmd *cmd) int iwl3945_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data) { - struct iwl3945_host_cmd cmd = { + struct iwl_host_cmd cmd = { .id = id, .len = len, .data = data, @@ -715,7 +717,7 @@ int iwl3945_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data static int __must_check iwl3945_send_cmd_u32(struct iwl_priv *priv, u8 id, u32 val) { - struct iwl3945_host_cmd cmd = { + struct iwl_host_cmd cmd = { .id = id, .len = sizeof(val), .data = &val, @@ -894,7 +896,7 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) int rc = 0; struct iwl_rx_packet *res = NULL; struct iwl3945_rxon_assoc_cmd rxon_assoc; - struct iwl3945_host_cmd cmd = { + struct iwl_host_cmd cmd = { .id = REPLY_RXON_ASSOC, .len = sizeof(rxon_assoc), .meta.flags = CMD_WANT_SKB, @@ -1077,7 +1079,7 @@ static int iwl3945_send_scan_abort(struct iwl_priv *priv) { int rc = 0; struct iwl_rx_packet *res; - struct iwl3945_host_cmd cmd = { + struct iwl_host_cmd cmd = { .id = REPLY_SCAN_ABORT_CMD, .meta.flags = CMD_WANT_SKB, }; @@ -1115,7 +1117,7 @@ static int iwl3945_send_scan_abort(struct iwl_priv *priv) } static int iwl3945_card_state_sync_callback(struct iwl_priv *priv, - struct iwl3945_cmd *cmd, + struct iwl_cmd *cmd, struct sk_buff *skb) { return 1; @@ -1133,7 +1135,7 @@ static int iwl3945_card_state_sync_callback(struct iwl_priv *priv, */ static int iwl3945_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag) { - struct iwl3945_host_cmd cmd = { + struct iwl_host_cmd cmd = { .id = REPLY_CARD_STATE_CMD, .len = sizeof(u32), .data = &flags, @@ -1147,7 +1149,7 @@ static int iwl3945_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_fla } static int iwl3945_add_sta_sync_callback(struct iwl_priv *priv, - struct iwl3945_cmd *cmd, struct sk_buff *skb) + struct iwl_cmd *cmd, struct sk_buff *skb) { struct iwl_rx_packet *res = NULL; @@ -1179,7 +1181,7 @@ int iwl3945_send_add_station(struct iwl_priv *priv, { struct iwl_rx_packet *res = NULL; int rc = 0; - struct iwl3945_host_cmd cmd = { + struct iwl_host_cmd cmd = { .id = REPLY_ADD_STA, .len = sizeof(struct iwl3945_addsta_cmd), .meta.flags = flags, @@ -2202,7 +2204,7 @@ static int iwl3945_set_mode(struct iwl_priv *priv, int mode) static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, struct ieee80211_tx_info *info, - struct iwl3945_cmd *cmd, + struct iwl_cmd *cmd, struct sk_buff *skb_frag, int last_frag) { @@ -2251,7 +2253,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, * handle build REPLY_TX command notification. */ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv, - struct iwl3945_cmd *cmd, + struct iwl_cmd *cmd, struct ieee80211_tx_info *info, struct ieee80211_hdr *hdr, int is_unicast, u8 std_id) @@ -2386,7 +2388,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) struct iwl_queue *q = NULL; dma_addr_t phys_addr; dma_addr_t txcmd_phys; - struct iwl3945_cmd *out_cmd = NULL; + struct iwl_cmd *out_cmd = NULL; u16 len, idx, len_org, hdr_len; u8 id; u8 unicast; @@ -2514,8 +2516,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* Physical address of this Tx command's header (not MAC header!), * within command buffer array. */ - txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl3945_cmd) * idx + - offsetof(struct iwl3945_cmd, hdr); + txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl_cmd) * idx + + offsetof(struct iwl_cmd, hdr); /* Add buffer containing Tx command and MAC(!) header to TFD's * first entry */ @@ -2793,7 +2795,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, { struct iwl_spectrum_cmd spectrum; struct iwl_rx_packet *res; - struct iwl3945_host_cmd cmd = { + struct iwl_host_cmd cmd = { .id = REPLY_SPECTRUM_MEASUREMENT_CMD, .data = (void *)&spectrum, .meta.flags = CMD_WANT_SKB, @@ -3271,7 +3273,7 @@ static void iwl3945_tx_cmd_complete(struct iwl_priv *priv, int index = SEQ_TO_INDEX(sequence); int huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME); int cmd_index; - struct iwl3945_cmd *cmd; + struct iwl_cmd *cmd; BUG_ON(txq_id != IWL_CMD_QUEUE_NUM); @@ -5974,7 +5976,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) { struct iwl_priv *priv = container_of(data, struct iwl_priv, request_scan); - struct iwl3945_host_cmd cmd = { + struct iwl_host_cmd cmd = { .id = REPLY_SCAN_CMD, .len = sizeof(struct iwl3945_scan_cmd), .meta.flags = CMD_SIZE_HUGE, -- GitLab From df878d8f0156ec2b41da5ae9c70af4a27cb2eb0a Mon Sep 17 00:00:00 2001 From: "Kolekar, Abhijeet" Date: Fri, 19 Dec 2008 10:37:35 +0800 Subject: [PATCH 0729/4982] iwl3945: use iwl_mod_params for 3945 Use iwl_mod_params for 3945. Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 4 +- drivers/net/wireless/iwlwifi/iwl-3945.h | 3 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 48 +++++++++------------ 3 files changed, 24 insertions(+), 31 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 422de88f128..d5509d58938 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -599,7 +599,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, /* Set the size of the skb to the size of the frame */ skb_put(rxb->skb, le16_to_cpu(rx_hdr->len)); - if (iwl3945_param_hwcrypto) + if (iwl3945_mod_params.sw_crypto) iwl3945_set_decrypted_flag(priv, rxb->skb, le32_to_cpu(rx_end->status), stats); @@ -2512,6 +2512,7 @@ static struct iwl_cfg iwl3945_bg_cfg = { .ucode_api_max = IWL3945_UCODE_API_MAX, .ucode_api_min = IWL3945_UCODE_API_MIN, .sku = IWL_SKU_G, + .mod_params = &iwl3945_mod_params }; static struct iwl_cfg iwl3945_abg_cfg = { @@ -2520,6 +2521,7 @@ static struct iwl_cfg iwl3945_abg_cfg = { .ucode_api_max = IWL3945_UCODE_API_MAX, .ucode_api_min = IWL3945_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G, + .mod_params = &iwl3945_mod_params }; struct pci_device_id iwl3945_hw_card_ids[] = { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 18424a308d1..9c520c455a4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -75,8 +75,7 @@ extern struct pci_device_id iwl3945_hw_card_ids[]; #define IWL_NOISE_MEAS_NOT_AVAILABLE (-127) /* Module parameters accessible from iwl-*.c */ -extern int iwl3945_param_hwcrypto; -extern int iwl3945_param_queues_num; +extern struct iwl_mod_params iwl3945_mod_params; struct iwl3945_sta_priv { struct iwl3945_rs_sta *rs_sta; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 0af710b8fb7..d057ab3022a 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -58,20 +58,6 @@ static int iwl3945_tx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl3945_tx_queue *txq); -/****************************************************************************** - * - * module boiler plate - * - ******************************************************************************/ - -/* module parameters */ -static int iwl3945_param_disable_hw_scan; /* def: 0 = use 3945's h/w scan */ -static u32 iwl3945_param_debug; /* def: 0 = minimal debug log messages */ -static int iwl3945_param_disable; /* def: 0 = enable radio */ -static int iwl3945_param_antenna; /* def: 0 = both antennas (use diversity) */ -int iwl3945_param_hwcrypto; /* def: 0 = use software encryption */ -int iwl3945_param_queues_num = IWL39_MAX_NUM_QUEUES; /* def: 8 Tx queues */ - /* * module name, copyright, version, etc. */ @@ -102,6 +88,12 @@ MODULE_VERSION(DRV_VERSION); MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); MODULE_LICENSE("GPL"); + /* module parameters */ +struct iwl_mod_params iwl3945_mod_params = { + .num_of_queues = IWL39_MAX_NUM_QUEUES, + /* the rest are 0 by default */ +}; + static const struct ieee80211_supported_band *iwl3945_get_band( struct iwl_priv *priv, enum ieee80211_band band) { @@ -6532,7 +6524,7 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed) goto out; } - if (unlikely(!iwl3945_param_disable_hw_scan && + if (unlikely(!iwl3945_mod_params.disable_hw_scan && test_bit(STATUS_SCANNING, &priv->status))) { IWL_DEBUG_MAC80211("leave - scanning\n"); set_bit(STATUS_CONF_PENDING, &priv->status); @@ -6944,7 +6936,7 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, IWL_DEBUG_MAC80211("enter\n"); - if (!iwl3945_param_hwcrypto) { + if (iwl3945_mod_params.sw_crypto) { IWL_DEBUG_MAC80211("leave - hwcrypto disabled\n"); return -EOPNOTSUPP; } @@ -7747,8 +7739,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->pci_dev = pdev; priv->cfg = cfg; - if ((iwl3945_param_queues_num > IWL39_MAX_NUM_QUEUES) || - (iwl3945_param_queues_num < IWL_MIN_NUM_QUEUES)) { + if ((iwl3945_mod_params.num_of_queues > IWL39_MAX_NUM_QUEUES) || + (iwl3945_mod_params.num_of_queues < IWL_MIN_NUM_QUEUES)) { IWL_ERR(priv, "invalid queues_num, should be between %d and %d\n", IWL_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES); @@ -7758,7 +7750,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e /* Disabling hardware scan means that mac80211 will perform scans * "the hard way", rather than using device's scan. */ - if (iwl3945_param_disable_hw_scan) { + if (iwl3945_mod_params.disable_hw_scan) { IWL_DEBUG_INFO("Disabling hw_scan\n"); iwl3945_hw_ops.hw_scan = NULL; } @@ -7768,9 +7760,9 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e hw->sta_data_size = sizeof(struct iwl3945_sta_priv); /* Select antenna (may be helpful if only one antenna is connected) */ - priv->antenna = (enum iwl3945_antenna)iwl3945_param_antenna; + priv->antenna = (enum iwl3945_antenna)iwl3945_mod_params.antenna; #ifdef CONFIG_IWL3945_DEBUG - priv->debug_level = iwl3945_param_debug; + priv->debug_level = iwl3945_mod_params.debug; atomic_set(&priv->restrict_refcnt, 0); #endif @@ -7918,7 +7910,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e /* Initialize module parameter values here */ /* Disable radio (SW RF KILL) via parameter when loading driver */ - if (iwl3945_param_disable) { + if (iwl3945_mod_params.disable) { set_bit(STATUS_RF_KILL_SW, &priv->status); IWL_DEBUG_INFO("Radio disabled.\n"); } @@ -8248,19 +8240,19 @@ static void __exit iwl3945_exit(void) MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX)); -module_param_named(antenna, iwl3945_param_antenna, int, 0444); +module_param_named(antenna, iwl3945_mod_params.antenna, int, 0444); MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); -module_param_named(disable, iwl3945_param_disable, int, 0444); +module_param_named(disable, iwl3945_mod_params.disable, int, 0444); MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])"); -module_param_named(hwcrypto, iwl3945_param_hwcrypto, int, 0444); +module_param_named(hwcrypto, iwl3945_mod_params.sw_crypto, int, 0444); MODULE_PARM_DESC(hwcrypto, "using hardware crypto engine (default 0 [software])\n"); -module_param_named(debug, iwl3945_param_debug, uint, 0444); +module_param_named(debug, iwl3945_mod_params.debug, uint, 0444); MODULE_PARM_DESC(debug, "debug output mask"); -module_param_named(disable_hw_scan, iwl3945_param_disable_hw_scan, int, 0444); +module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, int, 0444); MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); -module_param_named(queues_num, iwl3945_param_queues_num, int, 0444); +module_param_named(queues_num, iwl3945_mod_params.num_of_queues, int, 0444); MODULE_PARM_DESC(queues_num, "number of hw queues."); module_exit(iwl3945_exit); -- GitLab From 775a6e27bfca9d19f3ea6006a7e60a4a54aaf69c Mon Sep 17 00:00:00 2001 From: "Kolekar, Abhijeet" Date: Fri, 19 Dec 2008 10:37:36 +0800 Subject: [PATCH 0730/4982] iwl3945: cleanup and remove duplicate code The patch removes the following duplicate structures: iwl3945_is_alive iwl3945_is_ready iwl3945_is_init iwl3945_is_rfkill_sw iwl3945_is_rfkill iwl3945_reset_qos Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 204 ++++---------------- 1 file changed, 34 insertions(+), 170 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index d057ab3022a..52c03cf2908 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -432,51 +432,6 @@ u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flag } -/*************** DRIVER STATUS FUNCTIONS *****/ - -static inline int iwl3945_is_ready(struct iwl_priv *priv) -{ - /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are - * set but EXIT_PENDING is not */ - return test_bit(STATUS_READY, &priv->status) && - test_bit(STATUS_GEO_CONFIGURED, &priv->status) && - !test_bit(STATUS_EXIT_PENDING, &priv->status); -} - -static inline int iwl3945_is_alive(struct iwl_priv *priv) -{ - return test_bit(STATUS_ALIVE, &priv->status); -} - -static inline int iwl3945_is_init(struct iwl_priv *priv) -{ - return test_bit(STATUS_INIT, &priv->status); -} - -static inline int iwl3945_is_rfkill_sw(struct iwl_priv *priv) -{ - return test_bit(STATUS_RF_KILL_SW, &priv->status); -} - -static inline int iwl3945_is_rfkill_hw(struct iwl_priv *priv) -{ - return test_bit(STATUS_RF_KILL_HW, &priv->status); -} - -static inline int iwl3945_is_rfkill(struct iwl_priv *priv) -{ - return iwl3945_is_rfkill_hw(priv) || - iwl3945_is_rfkill_sw(priv); -} - -static inline int iwl3945_is_ready_rf(struct iwl_priv *priv) -{ - - if (iwl3945_is_rfkill(priv)) - return 0; - - return iwl3945_is_ready(priv); -} /*************** HOST COMMAND QUEUE FUNCTIONS *****/ @@ -514,7 +469,7 @@ static int iwl3945_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) !(cmd->meta.flags & CMD_SIZE_HUGE)); - if (iwl3945_is_rfkill(priv)) { + if (iwl_is_rfkill(priv)) { IWL_DEBUG_INFO("Not sending command - RF KILL"); return -EIO; } @@ -941,7 +896,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active39_rxon; int rc = 0; - if (!iwl3945_is_alive(priv)) + if (!iwl_is_alive(priv)) return -1; /* always get timestamp with Rx frame */ @@ -1596,97 +1551,6 @@ static int iwl3945_send_qos_params_command(struct iwl_priv *priv, sizeof(struct iwl_qosparam_cmd), qos); } -static void iwl3945_reset_qos(struct iwl_priv *priv) -{ - u16 cw_min = 15; - u16 cw_max = 1023; - u8 aifs = 2; - u8 is_legacy = 0; - unsigned long flags; - int i; - - spin_lock_irqsave(&priv->lock, flags); - priv->qos_data.qos_active = 0; - - /* QoS always active in AP and ADHOC mode - * In STA mode wait for association - */ - if (priv->iw_mode == NL80211_IFTYPE_ADHOC || - priv->iw_mode == NL80211_IFTYPE_AP) - priv->qos_data.qos_active = 1; - else - priv->qos_data.qos_active = 0; - - - /* check for legacy mode */ - if ((priv->iw_mode == NL80211_IFTYPE_ADHOC && - (priv->active_rate & IWL_OFDM_RATES_MASK) == 0) || - (priv->iw_mode == NL80211_IFTYPE_STATION && - (priv->staging39_rxon.flags & RXON_FLG_SHORT_SLOT_MSK) == 0)) { - cw_min = 31; - is_legacy = 1; - } - - if (priv->qos_data.qos_active) - aifs = 3; - - priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min); - priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max); - priv->qos_data.def_qos_parm.ac[0].aifsn = aifs; - priv->qos_data.def_qos_parm.ac[0].edca_txop = 0; - priv->qos_data.def_qos_parm.ac[0].reserved1 = 0; - - if (priv->qos_data.qos_active) { - i = 1; - priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min); - priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max); - priv->qos_data.def_qos_parm.ac[i].aifsn = 7; - priv->qos_data.def_qos_parm.ac[i].edca_txop = 0; - priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; - - i = 2; - priv->qos_data.def_qos_parm.ac[i].cw_min = - cpu_to_le16((cw_min + 1) / 2 - 1); - priv->qos_data.def_qos_parm.ac[i].cw_max = - cpu_to_le16(cw_max); - priv->qos_data.def_qos_parm.ac[i].aifsn = 2; - if (is_legacy) - priv->qos_data.def_qos_parm.ac[i].edca_txop = - cpu_to_le16(6016); - else - priv->qos_data.def_qos_parm.ac[i].edca_txop = - cpu_to_le16(3008); - priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; - - i = 3; - priv->qos_data.def_qos_parm.ac[i].cw_min = - cpu_to_le16((cw_min + 1) / 4 - 1); - priv->qos_data.def_qos_parm.ac[i].cw_max = - cpu_to_le16((cw_max + 1) / 2 - 1); - priv->qos_data.def_qos_parm.ac[i].aifsn = 2; - priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; - if (is_legacy) - priv->qos_data.def_qos_parm.ac[i].edca_txop = - cpu_to_le16(3264); - else - priv->qos_data.def_qos_parm.ac[i].edca_txop = - cpu_to_le16(1504); - } else { - for (i = 1; i < 4; i++) { - priv->qos_data.def_qos_parm.ac[i].cw_min = - cpu_to_le16(cw_min); - priv->qos_data.def_qos_parm.ac[i].cw_max = - cpu_to_le16(cw_max); - priv->qos_data.def_qos_parm.ac[i].aifsn = aifs; - priv->qos_data.def_qos_parm.ac[i].edca_txop = 0; - priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; - } - } - IWL_DEBUG_QOS("set QoS to default \n"); - - spin_unlock_irqrestore(&priv->lock, flags); -} - static void iwl3945_activate_qos(struct iwl_priv *priv, u8 force) { unsigned long flags; @@ -2018,7 +1882,7 @@ static void iwl3945_setup_rxon_timing(struct iwl_priv *priv) static int iwl3945_scan_initiate(struct iwl_priv *priv) { - if (!iwl3945_is_ready_rf(priv)) { + if (!iwl_is_ready_rf(priv)) { IWL_DEBUG_SCAN("Aborting scan due to not ready.\n"); return -EIO; } @@ -2179,7 +2043,7 @@ static int iwl3945_set_mode(struct iwl_priv *priv, int mode) iwl3945_clear_stations_table(priv); /* don't commit rxon if rf-kill is on*/ - if (!iwl3945_is_ready_rf(priv)) + if (!iwl_is_ready_rf(priv)) return -EAGAIN; cancel_delayed_work(&priv->scan_check); @@ -2394,7 +2258,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) int rc; spin_lock_irqsave(&priv->lock, flags); - if (iwl3945_is_rfkill(priv)) { + if (iwl_is_rfkill(priv)) { IWL_DEBUG_DROP("Dropping - RF KILL\n"); goto drop_unlock; } @@ -5614,7 +5478,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) /* Clear out the uCode error bit if it is set */ clear_bit(STATUS_FW_ERROR, &priv->status); - if (iwl3945_is_rfkill(priv)) + if (iwl_is_rfkill(priv)) return; ieee80211_wake_queues(priv->hw); @@ -5708,7 +5572,7 @@ static void __iwl3945_down(struct iwl_priv *priv) /* If we have not previously called iwl3945_init() then * clear all bits but the RF Kill and SUSPEND bits and return */ - if (!iwl3945_is_init(priv)) { + if (!iwl_is_init(priv)) { priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) << STATUS_RF_KILL_HW | test_bit(STATUS_RF_KILL_SW, &priv->status) << @@ -5920,7 +5784,7 @@ static void iwl3945_bg_rf_kill(struct work_struct *work) mutex_lock(&priv->mutex); - if (!iwl3945_is_rfkill(priv)) { + if (!iwl_is_rfkill(priv)) { IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL, "HW and/or SW RF Kill no longer active, restarting " "device\n"); @@ -5984,7 +5848,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) mutex_lock(&priv->mutex); - if (!iwl3945_is_ready(priv)) { + if (!iwl_is_ready(priv)) { IWL_WARN(priv, "request scan called when driver not ready.\n"); goto done; } @@ -6013,7 +5877,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) goto done; } - if (iwl3945_is_rfkill(priv)) { + if (iwl_is_rfkill(priv)) { IWL_DEBUG_HC("Aborting scan due to RF Kill activation\n"); goto done; } @@ -6293,7 +6157,7 @@ static void iwl3945_bg_abort_scan(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); - if (!iwl3945_is_ready(priv)) + if (!iwl_is_ready(priv)) return; mutex_lock(&priv->mutex); @@ -6429,7 +6293,7 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw) priv->is_open = 0; - if (iwl3945_is_ready_rf(priv)) { + if (iwl_is_ready_rf(priv)) { /* stop mac, cancel any scan request and clear * RXON_FILTER_ASSOC_MSK BIT */ @@ -6491,7 +6355,7 @@ static int iwl3945_mac_add_interface(struct ieee80211_hw *hw, memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); } - if (iwl3945_is_ready(priv)) + if (iwl_is_ready(priv)) iwl3945_set_mode(priv, conf->type); mutex_unlock(&priv->mutex); @@ -6518,7 +6382,7 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed) mutex_lock(&priv->mutex); IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value); - if (!iwl3945_is_ready(priv)) { + if (!iwl_is_ready(priv)) { IWL_DEBUG_MAC80211("leave - not ready\n"); ret = -EIO; goto out; @@ -6570,7 +6434,7 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed) goto out; } - if (iwl3945_is_rfkill(priv)) { + if (iwl_is_rfkill(priv)) { IWL_DEBUG_MAC80211("leave - RF kill\n"); ret = -EIO; goto out; @@ -6677,7 +6541,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, return rc; } - if (!iwl3945_is_alive(priv)) + if (!iwl_is_alive(priv)) return -EAGAIN; mutex_lock(&priv->mutex); @@ -6705,7 +6569,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, priv->ibss_beacon = ieee80211_beacon_get(hw, vif); } - if (iwl3945_is_rfkill(priv)) + if (iwl_is_rfkill(priv)) goto done; if (conf->bssid && !is_zero_ether_addr(conf->bssid) && @@ -6804,7 +6668,7 @@ static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); - if (iwl3945_is_ready_rf(priv)) { + if (iwl_is_ready_rf(priv)) { iwl3945_scan_cancel_timeout(priv, 100); priv->staging39_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl3945_commit_rxon(priv); @@ -6885,7 +6749,7 @@ static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) mutex_lock(&priv->mutex); spin_lock_irqsave(&priv->lock, flags); - if (!iwl3945_is_ready_rf(priv)) { + if (!iwl_is_ready_rf(priv)) { rc = -EIO; IWL_DEBUG_MAC80211("leave - not ready or exit pending\n"); goto out_unlock; @@ -6994,7 +6858,7 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, IWL_DEBUG_MAC80211("enter\n"); - if (!iwl3945_is_ready_rf(priv)) { + if (!iwl_is_ready_rf(priv)) { IWL_DEBUG_MAC80211("leave - RF not ready\n"); return -EIO; } @@ -7042,7 +6906,7 @@ static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211("enter\n"); - if (!iwl3945_is_ready_rf(priv)) { + if (!iwl_is_ready_rf(priv)) { IWL_DEBUG_MAC80211("leave - RF not ready\n"); return -EIO; } @@ -7074,7 +6938,7 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) mutex_lock(&priv->mutex); IWL_DEBUG_MAC80211("enter\n"); - iwl3945_reset_qos(priv); + iwl_reset_qos(priv); spin_lock_irqsave(&priv->lock, flags); priv->assoc_id = 0; @@ -7094,7 +6958,7 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) spin_unlock_irqrestore(&priv->lock, flags); - if (!iwl3945_is_ready_rf(priv)) { + if (!iwl_is_ready_rf(priv)) { IWL_DEBUG_MAC80211("leave - not ready\n"); mutex_unlock(&priv->mutex); return; @@ -7132,7 +6996,7 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk IWL_DEBUG_MAC80211("enter\n"); - if (!iwl3945_is_ready_rf(priv)) { + if (!iwl_is_ready_rf(priv)) { IWL_DEBUG_MAC80211("leave - RF not ready\n"); return -EIO; } @@ -7154,7 +7018,7 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk IWL_DEBUG_MAC80211("leave\n"); spin_unlock_irqrestore(&priv->lock, flags); - iwl3945_reset_qos(priv); + iwl_reset_qos(priv); iwl3945_post_associate(priv); @@ -7211,7 +7075,7 @@ static ssize_t show_temperature(struct device *d, { struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; - if (!iwl3945_is_alive(priv)) + if (!iwl_is_alive(priv)) return -EAGAIN; return sprintf(buf, "%d\n", iwl3945_hw_get_temperature(priv)); @@ -7423,7 +7287,7 @@ static ssize_t store_power_level(struct device *d, mode = simple_strtoul(buf, NULL, 0); mutex_lock(&priv->mutex); - if (!iwl3945_is_ready(priv)) { + if (!iwl_is_ready(priv)) { rc = -EAGAIN; goto out; } @@ -7521,7 +7385,7 @@ static ssize_t show_statistics(struct device *d, u8 *data = (u8 *)&priv->statistics_39; int rc = 0; - if (!iwl3945_is_alive(priv)) + if (!iwl_is_alive(priv)) return -EAGAIN; mutex_lock(&priv->mutex); @@ -7555,7 +7419,7 @@ static ssize_t show_antenna(struct device *d, { struct iwl_priv *priv = dev_get_drvdata(d); - if (!iwl3945_is_alive(priv)) + if (!iwl_is_alive(priv)) return -EAGAIN; return sprintf(buf, "%d\n", priv->antenna); @@ -7592,7 +7456,7 @@ static ssize_t show_status(struct device *d, struct device_attribute *attr, char *buf) { struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; - if (!iwl3945_is_alive(priv)) + if (!iwl_is_alive(priv)) return -EAGAIN; return sprintf(buf, "0x%08x\n", (int)priv->status); } @@ -7878,7 +7742,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->iw_mode = NL80211_IFTYPE_STATION; - iwl3945_reset_qos(priv); + iwl_reset_qos(priv); priv->qos_data.qos_active = 0; priv->qos_data.qos_cap.val = 0; @@ -8099,7 +7963,7 @@ static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state) switch (state) { case RFKILL_STATE_UNBLOCKED: - if (iwl3945_is_rfkill_hw(priv)) { + if (iwl_is_rfkill_hw(priv)) { err = -EBUSY; goto out_unlock; } @@ -8176,12 +8040,12 @@ void iwl3945_rfkill_set_hw_state(struct iwl_priv *priv) if (!priv->rfkill) return; - if (iwl3945_is_rfkill_hw(priv)) { + if (iwl_is_rfkill_hw(priv)) { rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED); return; } - if (!iwl3945_is_rfkill_sw(priv)) + if (!iwl_is_rfkill_sw(priv)) rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED); else rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED); -- GitLab From 0164b9b45dbee4a3c4c95f59f9dd538b1e9c2635 Mon Sep 17 00:00:00 2001 From: "Kolekar, Abhijeet" Date: Fri, 19 Dec 2008 10:37:37 +0800 Subject: [PATCH 0731/4982] iwl3945: add load ucode op The patch adds 3945 iwl_lib_ops->load_ucode to the driver. Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 159 ++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 152 +------------------ 2 files changed, 160 insertions(+), 151 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index d5509d58938..1071dac99c5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2506,12 +2506,170 @@ void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv) cancel_delayed_work(&priv->thermal_periodic); } +/* check contents of special bootstrap uCode SRAM */ +static int iwl3945_verify_bsm(struct iwl_priv *priv) + { + __le32 *image = priv->ucode_boot.v_addr; + u32 len = priv->ucode_boot.len; + u32 reg; + u32 val; + + IWL_DEBUG_INFO("Begin verify bsm\n"); + + /* verify BSM SRAM contents */ + val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG); + for (reg = BSM_SRAM_LOWER_BOUND; + reg < BSM_SRAM_LOWER_BOUND + len; + reg += sizeof(u32), image++) { + val = iwl_read_prph(priv, reg); + if (val != le32_to_cpu(*image)) { + IWL_ERR(priv, "BSM uCode verification failed at " + "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n", + BSM_SRAM_LOWER_BOUND, + reg - BSM_SRAM_LOWER_BOUND, len, + val, le32_to_cpu(*image)); + return -EIO; + } + } + + IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n"); + + return 0; +} + + /** + * iwl3945_load_bsm - Load bootstrap instructions + * + * BSM operation: + * + * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program + * in special SRAM that does not power down during RFKILL. When powering back + * up after power-saving sleeps (or during initial uCode load), the BSM loads + * the bootstrap program into the on-board processor, and starts it. + * + * The bootstrap program loads (via DMA) instructions and data for a new + * program from host DRAM locations indicated by the host driver in the + * BSM_DRAM_* registers. Once the new program is loaded, it starts + * automatically. + * + * When initializing the NIC, the host driver points the BSM to the + * "initialize" uCode image. This uCode sets up some internal data, then + * notifies host via "initialize alive" that it is complete. + * + * The host then replaces the BSM_DRAM_* pointer values to point to the + * normal runtime uCode instructions and a backup uCode data cache buffer + * (filled initially with starting data values for the on-board processor), + * then triggers the "initialize" uCode to load and launch the runtime uCode, + * which begins normal operation. + * + * When doing a power-save shutdown, runtime uCode saves data SRAM into + * the backup data cache in DRAM before SRAM is powered down. + * + * When powering back up, the BSM loads the bootstrap program. This reloads + * the runtime uCode instructions and the backup data cache into SRAM, + * and re-launches the runtime uCode from where it left off. + */ +static int iwl3945_load_bsm(struct iwl_priv *priv) +{ + __le32 *image = priv->ucode_boot.v_addr; + u32 len = priv->ucode_boot.len; + dma_addr_t pinst; + dma_addr_t pdata; + u32 inst_len; + u32 data_len; + int rc; + int i; + u32 done; + u32 reg_offset; + + IWL_DEBUG_INFO("Begin load bsm\n"); + + /* make sure bootstrap program is no larger than BSM's SRAM size */ + if (len > IWL39_MAX_BSM_SIZE) + return -EINVAL; + + /* Tell bootstrap uCode where to find the "Initialize" uCode + * in host DRAM ... host DRAM physical address bits 31:0 for 3945. + * NOTE: iwl3945_initialize_alive_start() will replace these values, + * after the "initialize" uCode has run, to point to + * runtime/protocol instructions and backup data cache. */ + pinst = priv->ucode_init.p_addr; + pdata = priv->ucode_init_data.p_addr; + inst_len = priv->ucode_init.len; + data_len = priv->ucode_init_data.len; + + rc = iwl_grab_nic_access(priv); + if (rc) + return rc; + + iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); + iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); + iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len); + iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len); + + /* Fill BSM memory with bootstrap instructions */ + for (reg_offset = BSM_SRAM_LOWER_BOUND; + reg_offset < BSM_SRAM_LOWER_BOUND + len; + reg_offset += sizeof(u32), image++) + _iwl_write_prph(priv, reg_offset, + le32_to_cpu(*image)); + + rc = iwl3945_verify_bsm(priv); + if (rc) { + iwl_release_nic_access(priv); + return rc; + } + + /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */ + iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0); + iwl_write_prph(priv, BSM_WR_MEM_DST_REG, + IWL39_RTC_INST_LOWER_BOUND); + iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32)); + + /* Load bootstrap code into instruction SRAM now, + * to prepare to load "initialize" uCode */ + iwl_write_prph(priv, BSM_WR_CTRL_REG, + BSM_WR_CTRL_REG_BIT_START); + + /* Wait for load of bootstrap uCode to finish */ + for (i = 0; i < 100; i++) { + done = iwl_read_prph(priv, BSM_WR_CTRL_REG); + if (!(done & BSM_WR_CTRL_REG_BIT_START)) + break; + udelay(10); + } + if (i < 100) + IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i); + else { + IWL_ERR(priv, "BSM write did not complete!\n"); + return -EIO; + } + + /* Enable future boot loads whenever power management unit triggers it + * (e.g. when powering back up after power-save shutdown) */ + iwl_write_prph(priv, BSM_WR_CTRL_REG, + BSM_WR_CTRL_REG_BIT_START_EN); + + iwl_release_nic_access(priv); + + return 0; +} + +static struct iwl_lib_ops iwl3945_lib = { + .load_ucode = iwl3945_load_bsm, +}; + +static struct iwl_ops iwl3945_ops = { + .lib = &iwl3945_lib, +}; + static struct iwl_cfg iwl3945_bg_cfg = { .name = "3945BG", .fw_name_pre = IWL3945_FW_PRE, .ucode_api_max = IWL3945_UCODE_API_MAX, .ucode_api_min = IWL3945_UCODE_API_MIN, .sku = IWL_SKU_G, + .ops = &iwl3945_ops, .mod_params = &iwl3945_mod_params }; @@ -2521,6 +2679,7 @@ static struct iwl_cfg iwl3945_abg_cfg = { .ucode_api_max = IWL3945_UCODE_API_MAX, .ucode_api_min = IWL3945_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G, + .ops = &iwl3945_ops, .mod_params = &iwl3945_mod_params }; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 52c03cf2908..6669ab0d3f5 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4924,156 +4924,6 @@ static int iwl3945_verify_ucode(struct iwl_priv *priv) return rc; } - -/* check contents of special bootstrap uCode SRAM */ -static int iwl3945_verify_bsm(struct iwl_priv *priv) -{ - __le32 *image = priv->ucode_boot.v_addr; - u32 len = priv->ucode_boot.len; - u32 reg; - u32 val; - - IWL_DEBUG_INFO("Begin verify bsm\n"); - - /* verify BSM SRAM contents */ - val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG); - for (reg = BSM_SRAM_LOWER_BOUND; - reg < BSM_SRAM_LOWER_BOUND + len; - reg += sizeof(u32), image++) { - val = iwl_read_prph(priv, reg); - if (val != le32_to_cpu(*image)) { - IWL_ERR(priv, "BSM uCode verification failed at " - "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n", - BSM_SRAM_LOWER_BOUND, - reg - BSM_SRAM_LOWER_BOUND, len, - val, le32_to_cpu(*image)); - return -EIO; - } - } - - IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n"); - - return 0; -} - -/** - * iwl3945_load_bsm - Load bootstrap instructions - * - * BSM operation: - * - * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program - * in special SRAM that does not power down during RFKILL. When powering back - * up after power-saving sleeps (or during initial uCode load), the BSM loads - * the bootstrap program into the on-board processor, and starts it. - * - * The bootstrap program loads (via DMA) instructions and data for a new - * program from host DRAM locations indicated by the host driver in the - * BSM_DRAM_* registers. Once the new program is loaded, it starts - * automatically. - * - * When initializing the NIC, the host driver points the BSM to the - * "initialize" uCode image. This uCode sets up some internal data, then - * notifies host via "initialize alive" that it is complete. - * - * The host then replaces the BSM_DRAM_* pointer values to point to the - * normal runtime uCode instructions and a backup uCode data cache buffer - * (filled initially with starting data values for the on-board processor), - * then triggers the "initialize" uCode to load and launch the runtime uCode, - * which begins normal operation. - * - * When doing a power-save shutdown, runtime uCode saves data SRAM into - * the backup data cache in DRAM before SRAM is powered down. - * - * When powering back up, the BSM loads the bootstrap program. This reloads - * the runtime uCode instructions and the backup data cache into SRAM, - * and re-launches the runtime uCode from where it left off. - */ -static int iwl3945_load_bsm(struct iwl_priv *priv) -{ - __le32 *image = priv->ucode_boot.v_addr; - u32 len = priv->ucode_boot.len; - dma_addr_t pinst; - dma_addr_t pdata; - u32 inst_len; - u32 data_len; - int rc; - int i; - u32 done; - u32 reg_offset; - - IWL_DEBUG_INFO("Begin load bsm\n"); - - /* make sure bootstrap program is no larger than BSM's SRAM size */ - if (len > IWL39_MAX_BSM_SIZE) - return -EINVAL; - - /* Tell bootstrap uCode where to find the "Initialize" uCode - * in host DRAM ... host DRAM physical address bits 31:0 for 3945. - * NOTE: iwl3945_initialize_alive_start() will replace these values, - * after the "initialize" uCode has run, to point to - * runtime/protocol instructions and backup data cache. */ - pinst = priv->ucode_init.p_addr; - pdata = priv->ucode_init_data.p_addr; - inst_len = priv->ucode_init.len; - data_len = priv->ucode_init_data.len; - - rc = iwl_grab_nic_access(priv); - if (rc) - return rc; - - iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); - iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); - iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len); - iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len); - - /* Fill BSM memory with bootstrap instructions */ - for (reg_offset = BSM_SRAM_LOWER_BOUND; - reg_offset < BSM_SRAM_LOWER_BOUND + len; - reg_offset += sizeof(u32), image++) - _iwl_write_prph(priv, reg_offset, - le32_to_cpu(*image)); - - rc = iwl3945_verify_bsm(priv); - if (rc) { - iwl_release_nic_access(priv); - return rc; - } - - /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */ - iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0); - iwl_write_prph(priv, BSM_WR_MEM_DST_REG, - IWL39_RTC_INST_LOWER_BOUND); - iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32)); - - /* Load bootstrap code into instruction SRAM now, - * to prepare to load "initialize" uCode */ - iwl_write_prph(priv, BSM_WR_CTRL_REG, - BSM_WR_CTRL_REG_BIT_START); - - /* Wait for load of bootstrap uCode to finish */ - for (i = 0; i < 100; i++) { - done = iwl_read_prph(priv, BSM_WR_CTRL_REG); - if (!(done & BSM_WR_CTRL_REG_BIT_START)) - break; - udelay(10); - } - if (i < 100) - IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i); - else { - IWL_ERR(priv, "BSM write did not complete!\n"); - return -EIO; - } - - /* Enable future boot loads whenever power management unit triggers it - * (e.g. when powering back up after power-save shutdown) */ - iwl_write_prph(priv, BSM_WR_CTRL_REG, - BSM_WR_CTRL_REG_BIT_START_EN); - - iwl_release_nic_access(priv); - - return 0; -} - static void iwl3945_nic_start(struct iwl_priv *priv) { /* Remove all resets to allow NIC to operate */ @@ -5714,7 +5564,7 @@ static int __iwl3945_up(struct iwl_priv *priv) /* load bootstrap state machine, * load bootstrap program into processor's memory, * prepare to load the "initialize" uCode */ - rc = iwl3945_load_bsm(priv); + priv->cfg->ops->lib->load_ucode(priv); if (rc) { IWL_ERR(priv, -- GitLab From 01ec616d8ccbfac41c87dafc0fc0aa4abe13b8f8 Mon Sep 17 00:00:00 2001 From: "Kolekar, Abhijeet" Date: Fri, 19 Dec 2008 10:37:38 +0800 Subject: [PATCH 0732/4982] iwl3945: add apm ops The patch adds 3945 iwl_lib_ops->apm_ops to the driver. Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 134 +++++++++++++------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 7 +- 2 files changed, 88 insertions(+), 53 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 1071dac99c5..2d6daa88e8c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1077,50 +1077,54 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv) return rc; } -int iwl3945_hw_nic_init(struct iwl_priv *priv) +static int iwl3945_apm_init(struct iwl_priv *priv) { - u8 rev_id; - int rc; - unsigned long flags; - struct iwl_rx_queue *rxq = &priv->rxq; + int ret = 0; iwl3945_power_init_handle(priv); - spin_lock_irqsave(&priv->lock, flags); - iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR39_ANA_PLL_CFG_VAL); iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, - CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); + CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); + + /* disable L0s without affecting L1 :don't wait for ICH L0s bug W/A) */ + iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, + CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); + /* set "initialization complete" bit to move adapter + * D0U* --> D0A* state */ iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - rc = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); - if (rc < 0) { - spin_unlock_irqrestore(&priv->lock, flags); + + iwl_poll_direct_bit(priv, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); + if (ret < 0) { IWL_DEBUG_INFO("Failed to init the card\n"); - return rc; + goto out; } - rc = iwl_grab_nic_access(priv); - if (rc) { - spin_unlock_irqrestore(&priv->lock, flags); - return rc; - } - iwl_write_prph(priv, APMG_CLK_EN_REG, - APMG_CLK_VAL_DMA_CLK_RQT | - APMG_CLK_VAL_BSM_CLK_RQT); + ret = iwl_grab_nic_access(priv); + if (ret) + goto out; + + /* enable DMA */ + iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_DMA_CLK_RQT | + APMG_CLK_VAL_BSM_CLK_RQT); + udelay(20); + + /* disable L1-Active */ iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, - APMG_PCIDEV_STT_VAL_L1_ACT_DIS); + APMG_PCIDEV_STT_VAL_L1_ACT_DIS); + iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->lock, flags); +out: + return ret; +} - /* Determine HW type */ - rc = pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id); - if (rc) - return rc; - IWL_DEBUG_INFO("HW Revision ID = 0x%X\n", rev_id); +static void iwl3945_nic_config(struct iwl_priv *priv) +{ + unsigned long flags; + u8 rev_id = 0; - iwl3945_nic_set_pwr_src(priv, 1); spin_lock_irqsave(&priv->lock, flags); if (rev_id & PCI_CFG_REV_ID_BIT_RTP) @@ -1172,6 +1176,27 @@ int iwl3945_hw_nic_init(struct iwl_priv *priv) if (priv->eeprom39.sku_cap & EEPROM_SKU_CAP_HW_RF_KILL_ENABLE) IWL_DEBUG_RF_KILL("HW RF KILL supported in EEPROM.\n"); +} + +int iwl3945_hw_nic_init(struct iwl_priv *priv) +{ + u8 rev_id; + int rc; + unsigned long flags; + struct iwl_rx_queue *rxq = &priv->rxq; + + spin_lock_irqsave(&priv->lock, flags); + priv->cfg->ops->lib->apm_ops.init(priv); + spin_unlock_irqrestore(&priv->lock, flags); + + /* Determine HW type */ + rc = pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id); + if (rc) + return rc; + IWL_DEBUG_INFO("HW Revision ID = 0x%X\n", rev_id); + + iwl3945_nic_set_pwr_src(priv, 1); + priv->cfg->ops->lib->apm_ops.config(priv); /* Allocate the RX queue, or reset if it is already allocated */ if (!rxq->bd) { @@ -1256,10 +1281,9 @@ void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) iwl3945_hw_txq_ctx_free(priv); } -int iwl3945_hw_nic_stop_master(struct iwl_priv *priv) +static int iwl3945_apm_stop_master(struct iwl_priv *priv) { - int rc = 0; - u32 reg_val; + int ret = 0; unsigned long flags; spin_lock_irqsave(&priv->lock, flags); @@ -1267,33 +1291,41 @@ int iwl3945_hw_nic_stop_master(struct iwl_priv *priv) /* set stop master bit */ iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); - reg_val = iwl_read32(priv, CSR_GP_CNTRL); + iwl_poll_direct_bit(priv, CSR_RESET, + CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); - if (CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE == - (reg_val & CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE)) - IWL_DEBUG_INFO("Card in power save, master is already " - "stopped\n"); - else { - rc = iwl_poll_direct_bit(priv, CSR_RESET, - CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); - if (rc < 0) { - spin_unlock_irqrestore(&priv->lock, flags); - return rc; - } - } + if (ret < 0) + goto out; +out: spin_unlock_irqrestore(&priv->lock, flags); IWL_DEBUG_INFO("stop master\n"); - return rc; + return ret; +} + +static void iwl3945_apm_stop(struct iwl_priv *priv) +{ + unsigned long flags; + + iwl3945_apm_stop_master(priv); + + spin_lock_irqsave(&priv->lock, flags); + + iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); + + udelay(10); + /* clear "init complete" move adapter D0A* --> D0U state */ + iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + spin_unlock_irqrestore(&priv->lock, flags); } -int iwl3945_hw_nic_reset(struct iwl_priv *priv) +int iwl3945_apm_reset(struct iwl_priv *priv) { int rc; unsigned long flags; - iwl3945_hw_nic_stop_master(priv); + iwl3945_apm_stop_master(priv); spin_lock_irqsave(&priv->lock, flags); @@ -2657,6 +2689,12 @@ static int iwl3945_load_bsm(struct iwl_priv *priv) static struct iwl_lib_ops iwl3945_lib = { .load_ucode = iwl3945_load_bsm, + .apm_ops = { + .init = iwl3945_apm_init, + .reset = iwl3945_apm_reset, + .stop = iwl3945_apm_stop, + .config = iwl3945_nic_config, + }, }; static struct iwl_ops iwl3945_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 6669ab0d3f5..11660f67d6a 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -5468,10 +5468,7 @@ static void __iwl3945_down(struct iwl_priv *priv) udelay(5); - iwl3945_hw_nic_stop_master(priv); - iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); - iwl3945_hw_nic_reset(priv); - + priv->cfg->ops->lib->apm_ops.reset(priv); exit: memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); @@ -7541,7 +7538,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e err = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); if (err < 0) { - IWL_DEBUG_INFO("Failed to init the card\n"); + IWL_DEBUG_INFO("Failed to init the APMG\n"); goto out_remove_sysfs; } -- GitLab From 854682ed2892836d7cff77931a79183c1fc59fef Mon Sep 17 00:00:00 2001 From: "Kolekar, Abhijeet" Date: Fri, 19 Dec 2008 10:37:39 +0800 Subject: [PATCH 0733/4982] iwl3945: add set_pwr_src The patch adds 3945 iwl_lib_ops->set_pwr_src to the driver Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 2d6daa88e8c..5a8b75d94d7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -919,7 +919,7 @@ u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags) return sta_id; } -static int iwl3945_nic_set_pwr_src(struct iwl_priv *priv, int pwr_max) +static int iwl3945_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src) { int rc; unsigned long flags; @@ -931,7 +931,7 @@ static int iwl3945_nic_set_pwr_src(struct iwl_priv *priv, int pwr_max) return rc; } - if (!pwr_max) { + if (src == IWL_PWR_SRC_VAUX) { u32 val; rc = pci_read_config_dword(priv->pci_dev, @@ -1195,7 +1195,10 @@ int iwl3945_hw_nic_init(struct iwl_priv *priv) return rc; IWL_DEBUG_INFO("HW Revision ID = 0x%X\n", rev_id); - iwl3945_nic_set_pwr_src(priv, 1); + rc = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); + if(rc) + return rc; + priv->cfg->ops->lib->apm_ops.config(priv); /* Allocate the RX queue, or reset if it is already allocated */ @@ -2694,6 +2697,7 @@ static struct iwl_lib_ops iwl3945_lib = { .reset = iwl3945_apm_reset, .stop = iwl3945_apm_stop, .config = iwl3945_nic_config, + .set_pwr_src = iwl3945_set_pwr_src, }, }; -- GitLab From 90a30a021eec15da64a354656cb66987216361eb Mon Sep 17 00:00:00 2001 From: "Kolekar, Abhijeet" Date: Fri, 19 Dec 2008 10:37:40 +0800 Subject: [PATCH 0734/4982] iwl3945: simplify iwl3945_pci_probe The patch simplifies iwl3945_pci_probe. It also uses apm_ops for apm init. Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 146 +++++++++++--------- 1 file changed, 79 insertions(+), 67 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 11660f67d6a..b84509763ac 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -7422,6 +7422,62 @@ static struct ieee80211_ops iwl3945_hw_ops = { .hw_scan = iwl3945_mac_hw_scan }; +int iwl3945_init_drv(struct iwl_priv *priv) +{ + int ret; + + priv->retry_rate = 1; + priv->ibss_beacon = NULL; + + spin_lock_init(&priv->lock); + spin_lock_init(&priv->power_data.lock); + spin_lock_init(&priv->sta_lock); + spin_lock_init(&priv->hcmd_lock); + + INIT_LIST_HEAD(&priv->free_frames); + + mutex_init(&priv->mutex); + + /* Clear the driver's (not device's) station table */ + iwl3945_clear_stations_table(priv); + + priv->data_retry_limit = -1; + priv->ieee_channels = NULL; + priv->ieee_rates = NULL; + priv->band = IEEE80211_BAND_2GHZ; + + priv->iw_mode = NL80211_IFTYPE_STATION; + + iwl_reset_qos(priv); + + priv->qos_data.qos_active = 0; + priv->qos_data.qos_cap.val = 0; + + priv->rates_mask = IWL_RATES_MASK; + /* If power management is turned on, default to AC mode */ + priv->power_mode = IWL_POWER_AC; + priv->user_txpower_limit = IWL_DEFAULT_TX_POWER; + + ret = iwl3945_init_channel_map(priv); + if (ret) { + IWL_ERR(priv, "initializing regulatory failed: %d\n", ret); + goto err; + } + + ret = iwl3945_init_geos(priv); + if (ret) { + IWL_ERR(priv, "initializing geos failed: %d\n", ret); + goto err_free_channel_map; + } + + return 0; + +err_free_channel_map: + iwl3945_free_channel_map(priv); +err: + return ret; +} + static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int err = 0; @@ -7436,19 +7492,14 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e /* mac80211 allocates memory for this device instance, including * space for this driver's private structure */ - hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), &iwl3945_hw_ops); + hw = iwl_alloc_all(cfg, &iwl3945_hw_ops); if (hw == NULL) { printk(KERN_ERR DRV_NAME "Can not allocate network device\n"); err = -ENOMEM; goto out; } - - SET_IEEE80211_DEV(hw, &pdev->dev); - priv = hw->priv; - priv->hw = hw; - priv->pci_dev = pdev; - priv->cfg = cfg; + SET_IEEE80211_DEV(hw, &pdev->dev); if ((iwl3945_mod_params.num_of_queues > IWL39_MAX_NUM_QUEUES) || (iwl3945_mod_params.num_of_queues < IWL_MIN_NUM_QUEUES)) { @@ -7459,23 +7510,29 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e goto out; } - /* Disabling hardware scan means that mac80211 will perform scans - * "the hard way", rather than using device's scan. */ + /* + * Disabling hardware scan means that mac80211 will perform scans + * "the hard way", rather than using device's scan. + */ if (iwl3945_mod_params.disable_hw_scan) { IWL_DEBUG_INFO("Disabling hw_scan\n"); iwl3945_hw_ops.hw_scan = NULL; } + IWL_DEBUG_INFO("*** LOAD DRIVER ***\n"); - hw->rate_control_algorithm = "iwl-3945-rs"; - hw->sta_data_size = sizeof(struct iwl3945_sta_priv); + priv->cfg = cfg; + priv->pci_dev = pdev; - /* Select antenna (may be helpful if only one antenna is connected) */ - priv->antenna = (enum iwl3945_antenna)iwl3945_mod_params.antenna; #ifdef CONFIG_IWL3945_DEBUG priv->debug_level = iwl3945_mod_params.debug; atomic_set(&priv->restrict_refcnt, 0); #endif + hw->rate_control_algorithm = "iwl-3945-rs"; + hw->sta_data_size = sizeof(struct iwl3945_sta_priv); + + /* Select antenna (may be helpful if only one antenna is connected) */ + priv->antenna = (enum iwl3945_antenna)iwl3945_mod_params.antenna; /* Tell mac80211 our characteristics */ hw->flags = IEEE80211_HW_SIGNAL_DBM | @@ -7530,21 +7587,17 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e * PCI Tx retries from interfering with C3 CPU state */ pci_write_config_byte(pdev, 0x41, 0x00); - /* nic init */ - iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, - CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); - - iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - err = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); + /* amp init */ + err = priv->cfg->ops->lib->apm_ops.init(priv); if (err < 0) { - IWL_DEBUG_INFO("Failed to init the APMG\n"); - goto out_remove_sysfs; + IWL_DEBUG_INFO("Failed to init APMG\n"); + goto out_iounmap; } /*********************** * 4. Read EEPROM * ********************/ + /* Read the EEPROM */ err = iwl3945_eeprom_init(priv); if (err) { @@ -7568,48 +7621,11 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e /*********************** * 6. Setup priv * ********************/ - priv->retry_rate = 1; - priv->ibss_beacon = NULL; - - spin_lock_init(&priv->lock); - spin_lock_init(&priv->power_data_39.lock); - spin_lock_init(&priv->sta_lock); - spin_lock_init(&priv->hcmd_lock); - - INIT_LIST_HEAD(&priv->free_frames); - mutex_init(&priv->mutex); - - /* Clear the driver's (not device's) station table */ - iwl3945_clear_stations_table(priv); - priv->data_retry_limit = -1; - priv->ieee_channels = NULL; - priv->ieee_rates = NULL; - priv->band = IEEE80211_BAND_2GHZ; - - priv->iw_mode = NL80211_IFTYPE_STATION; - - iwl_reset_qos(priv); - - priv->qos_data.qos_active = 0; - priv->qos_data.qos_cap.val = 0; - - - priv->rates_mask = IWL_RATES_MASK; - /* If power management is turned on, default to AC mode */ - priv->power_mode = IWL39_POWER_AC; - priv->user_txpower_limit = IWL_DEFAULT_TX_POWER; - - err = iwl3945_init_channel_map(priv); - if (err) { - IWL_ERR(priv, "initializing regulatory failed: %d\n", err); - goto out_release_irq; - } - - err = iwl3945_init_geos(priv); + err = iwl3945_init_drv(priv); if (err) { - IWL_ERR(priv, "initializing geos failed: %d\n", err); - goto out_free_channel_map; + IWL_ERR(priv, "initializing driver failed\n"); + goto out_free_geos; } IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s\n", @@ -7638,7 +7654,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group); if (err) { IWL_ERR(priv, "failed to create sysfs device attributes\n"); - goto out_free_geos; + goto out_release_irq; } iwl3945_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6); @@ -7664,7 +7680,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->hw->conf.beacon_int = 100; priv->mac80211_registered = 1; - err = iwl3945_rfkill_init(priv); if (err) IWL_ERR(priv, "Unable to initialize RFKILL system. " @@ -7676,9 +7691,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); out_free_geos: iwl3945_free_geos(priv); - out_free_channel_map: - iwl3945_free_channel_map(priv); - out_release_irq: destroy_workqueue(priv->workqueue); -- GitLab From d552bfb65241a35d48e44ddb0d27e0454f579ab4 Mon Sep 17 00:00:00 2001 From: "Kolekar, Abhijeet" Date: Fri, 19 Dec 2008 10:37:41 +0800 Subject: [PATCH 0735/4982] iwl3945: release resources before shutting down Release resource before shutting down and notify upper stack. Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index b84509763ac..17f01a69287 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -7722,7 +7722,12 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) set_bit(STATUS_EXIT_PENDING, &priv->status); - iwl3945_down(priv); + if (priv->mac80211_registered) { + ieee80211_unregister_hw(priv->hw); + priv->mac80211_registered = 0; + } else { + iwl3945_down(priv); + } /* make sure we flush any pending irq or * tasklet for the driver @@ -7745,9 +7750,6 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) iwl3945_unset_hw_params(priv); iwl3945_clear_stations_table(priv); - if (priv->mac80211_registered) - ieee80211_unregister_hw(priv->hw); - /*netif_stop_queue(dev); */ flush_workqueue(priv->workqueue); -- GitLab From cbba18c6e3d1b2610f9a63c4636247af26141686 Mon Sep 17 00:00:00 2001 From: "Kolekar, Abhijeet" Date: Fri, 19 Dec 2008 10:37:42 +0800 Subject: [PATCH 0736/4982] iwl3945: use iwl_get_hw_mode Use iwl_get_hw_mode for 3945. Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 17f01a69287..aaa6058dd8b 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -94,12 +94,6 @@ struct iwl_mod_params iwl3945_mod_params = { /* the rest are 0 by default */ }; -static const struct ieee80211_supported_band *iwl3945_get_band( - struct iwl_priv *priv, enum ieee80211_band band) -{ - return priv->hw->wiphy->bands[band]; -} - /*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** * DMA services * @@ -2462,7 +2456,7 @@ static void iwl3945_set_rate(struct iwl_priv *priv) struct ieee80211_rate *rate; int i; - sband = iwl3945_get_band(priv, priv->band); + sband = iwl_get_hw_mode(priv, priv->band); if (!sband) { IWL_ERR(priv, "Failed to set rate: unable to get hw mode\n"); return; @@ -4537,7 +4531,7 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, u16 active_dwell = 0; int added, i; - sband = iwl3945_get_band(priv, band); + sband = iwl_get_hw_mode(priv, band); if (!sband) return 0; -- GitLab From 8cd812bcda06645160b0b279e1a125271a73411c Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Fri, 19 Dec 2008 10:37:43 +0800 Subject: [PATCH 0737/4982] iwl3945: use iwl_rb_status This patch makes use of iwl_rb_status also in 3945. The structure for 3945 is not the same but since only closed_rb_num filed is used in both cases there is no reason to duplicate it. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 1 - drivers/net/wireless/iwlwifi/iwl-3945.c | 11 +---------- drivers/net/wireless/iwlwifi/iwl-3945.h | 1 - drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl-fh.h | 1 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 6 files changed, 4 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 5d461bd7756..fc1b774c806 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -302,7 +302,6 @@ static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr) * and &iwl3945_shared.rx_read_ptr[0] is provided to FH_RCSR_RPTR_ADDR(0) */ struct iwl3945_shared { __le32 tx_base_ptr[8]; - __le32 rx_read_ptr[3]; } __attribute__ ((packed)); struct iwl3945_tfd_frame_data { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 5a8b75d94d7..cb864449c39 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -974,9 +974,7 @@ static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) } iwl_write_direct32(priv, FH39_RCSR_RBD_BASE(0), rxq->dma_addr); - iwl_write_direct32(priv, FH39_RCSR_RPTR_ADDR(0), - priv->shared_phys + - offsetof(struct iwl3945_shared, rx_read_ptr[0])); + iwl_write_direct32(priv, FH39_RCSR_RPTR_ADDR(0), rxq->rb_stts_dma); iwl_write_direct32(priv, FH39_RCSR_WPTR(0), 0); iwl_write_direct32(priv, FH39_RCSR_CONFIG(0), FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE | @@ -2377,13 +2375,6 @@ int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl3945_tx_queue *txq return 0; } -int iwl3945_hw_get_rx_read(struct iwl_priv *priv) -{ - struct iwl3945_shared *shared_data = priv->shared_virt; - - return le32_to_cpu(shared_data->rx_read_ptr[0]); -} - /** * iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table */ diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 9c520c455a4..aff6a3a5389 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -282,7 +282,6 @@ extern int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl3945_tx_queue *txq); extern unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv, struct iwl3945_frame *frame, u8 rate); -extern int iwl3945_hw_get_rx_read(struct iwl_priv *priv); void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, struct iwl_cmd *cmd, struct ieee80211_tx_info *info, struct ieee80211_hdr *hdr, diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 6a07a686f85..8981c054a4c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1021,7 +1021,7 @@ struct iwl_priv { u16 beacon_int; struct ieee80211_vif *vif; - /*Added for 3945 */ + /*Added for 3945 */ void *shared_virt; dma_addr_t shared_phys; /*End*/ diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index d7da1986455..7c19790a3ea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -414,6 +414,7 @@ struct iwl_rb_status { __le16 closed_fr_num; __le16 finished_rb_num; __le16 finished_fr_nam; + __le32 __unused; /* 3945 only */ } __attribute__ ((packed)); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index aaa6058dd8b..207d55bea5f 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3588,7 +3588,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) /* uCode's read index (stored in shared DRAM) indicates the last Rx * buffer that the driver may process (last buffer filled by ucode). */ - r = iwl3945_hw_get_rx_read(priv); + r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF; i = rxq->read; if (iwl3945_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2)) -- GitLab From dbb6654c411e2030ed969ef0c531eb7fda8b27a3 Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Mon, 22 Dec 2008 11:31:14 +0800 Subject: [PATCH 0738/4982] iwl3945: rearrange 3945 tfd This patch moves 3945 TFD structures to iwl-3945-fh.h. It renames them similarly to AGN naming. This patch also eliminates iwl3945_tx_info and fixes endianity issue in iwl3945_tx_skb and iwl3945_enqueue_hcmd caused by ugly casting. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-fh.h | 12 ++++++- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 11 ------ drivers/net/wireless/iwlwifi/iwl-3945.c | 19 +++++----- drivers/net/wireless/iwlwifi/iwl-3945.h | 8 +---- drivers/net/wireless/iwlwifi/iwl-dev.h | 13 +++---- drivers/net/wireless/iwlwifi/iwl3945-base.c | 40 +++++++++------------ 6 files changed, 46 insertions(+), 57 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-fh.h b/drivers/net/wireless/iwlwifi/iwl-3945-fh.h index bbcd0cefc72..53ed24942a0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-fh.h @@ -172,7 +172,17 @@ #define FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (0x01000000) -#define TFD_QUEUE_SIZE_MAX (256) +struct iwl3945_tfd_tb { + __le32 addr; + __le32 len; +} __attribute__ ((packed)); + +struct iwl3945_tfd { + __le32 control_flags; + struct iwl3945_tfd_tb tbs[4]; + u8 __pad[28]; +} __attribute__ ((packed)); + #endif /* __iwl_3945_fh_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index fc1b774c806..1ba59dfacd1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -304,17 +304,6 @@ struct iwl3945_shared { __le32 tx_base_ptr[8]; } __attribute__ ((packed)); -struct iwl3945_tfd_frame_data { - __le32 addr; - __le32 len; -} __attribute__ ((packed)); - -struct iwl3945_tfd_frame { - __le32 control_flags; - struct iwl3945_tfd_frame_data pa[4]; - u8 reserved[28]; -} __attribute__ ((packed)); - static inline u8 iwl3945_hw_get_rate(__le16 rate_n_flags) { return le16_to_cpu(rate_n_flags) & 0xFF; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index cb864449c39..6810909f3fe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -38,6 +38,7 @@ #include #include +#include "iwl-fh.h" #include "iwl-3945-fh.h" #include "iwl-commands.h" #include "iwl-3945.h" @@ -307,7 +308,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv, { struct iwl3945_tx_queue *txq = &priv->txq39[txq_id]; struct iwl_queue *q = &txq->q; - struct iwl3945_tx_info *tx_info; + struct iwl_tx_info *tx_info; BUG_ON(txq_id == IWL_CMD_QUEUE_NUM); @@ -728,7 +729,7 @@ int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr, { int count; u32 pad; - struct iwl3945_tfd_frame *tfd = (struct iwl3945_tfd_frame *)ptr; + struct iwl3945_tfd *tfd = (struct iwl3945_tfd *)ptr; count = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags)); pad = TFD_CTL_PAD_GET(le32_to_cpu(tfd->control_flags)); @@ -739,8 +740,8 @@ int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr, return -EINVAL; } - tfd->pa[count].addr = cpu_to_le32(addr); - tfd->pa[count].len = cpu_to_le32(len); + tfd->tbs[count].addr = cpu_to_le32(addr); + tfd->tbs[count].len = cpu_to_le32(len); count++; @@ -757,8 +758,8 @@ int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr, */ int iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl3945_tx_queue *txq) { - struct iwl3945_tfd_frame *bd_tmp = (struct iwl3945_tfd_frame *)&txq->bd[0]; - struct iwl3945_tfd_frame *bd = &bd_tmp[txq->q.read_ptr]; + struct iwl3945_tfd *tfd_tmp = (struct iwl3945_tfd *)&txq->tfds[0]; + struct iwl3945_tfd *tfd = &tfd_tmp[txq->q.read_ptr]; struct pci_dev *dev = priv->pci_dev; int i; int counter; @@ -769,7 +770,7 @@ int iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl3945_tx_queue *txq) return 0; /* sanity check */ - counter = TFD_CTL_COUNT_GET(le32_to_cpu(bd->control_flags)); + counter = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags)); if (counter > NUM_TFD_CHUNKS) { IWL_ERR(priv, "Too many chunks: %i\n", counter); /* @todo issue fatal error, it is quite serious situation */ @@ -779,8 +780,8 @@ int iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl3945_tx_queue *txq) /* unmap chunks if any */ for (i = 1; i < counter; i++) { - pci_unmap_single(dev, le32_to_cpu(bd->pa[i].addr), - le32_to_cpu(bd->pa[i].len), PCI_DMA_TODEVICE); + pci_unmap_single(dev, le32_to_cpu(tfd->tbs[i].addr), + le32_to_cpu(tfd->tbs[i].len), PCI_DMA_TODEVICE); if (txq->txb[txq->q.read_ptr].skb[0]) { struct sk_buff *skb = txq->txb[txq->q.read_ptr].skb[0]; if (txq->txb[txq->q.read_ptr].skb[0]) { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index aff6a3a5389..716c4b46233 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -45,6 +45,7 @@ extern struct pci_device_id iwl3945_hw_card_ids[]; #include "iwl-csr.h" #include "iwl-prph.h" +#include "iwl-fh.h" #include "iwl-3945-hw.h" #include "iwl-debug.h" #include "iwl-power.h" @@ -107,13 +108,6 @@ enum iwl3945_antenna { int iwl3945_x2_queue_used(const struct iwl_queue *q, int i); -#define MAX_NUM_OF_TBS (20) - -/* One for each TFD */ -struct iwl3945_tx_info { - struct sk_buff *skb[MAX_NUM_OF_TBS]; -}; - #include "iwl-agn-rs.h" #define IWL_TX_FIFO_AC0 0 diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 8981c054a4c..1ad4d084e35 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -36,14 +36,15 @@ #include #include -#include "iwl-rfkill.h" #include "iwl-eeprom.h" -#include "iwl-4965-hw.h" -#include "iwl-3945-hw.h" -#include "iwl-3945-led.h" #include "iwl-csr.h" #include "iwl-prph.h" +#include "iwl-fh.h" #include "iwl-debug.h" +#include "iwl-rfkill.h" +#include "iwl-4965-hw.h" +#include "iwl-3945-hw.h" +#include "iwl-3945-led.h" #include "iwl-led.h" #include "iwl-power.h" #include "iwl-agn-rs.h" @@ -239,10 +240,10 @@ struct iwl_channel_info { */ struct iwl3945_tx_queue { struct iwl_queue q; - struct iwl3945_tfd_frame *bd; + struct iwl3945_tfd *tfds; struct iwl_cmd *cmd; dma_addr_t dma_addr_cmd; - struct iwl3945_tx_info *txb; + struct iwl_tx_info *txb; int need_update; int active; }; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 207d55bea5f..c37fa00af6d 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -48,9 +48,10 @@ #define DRV_NAME "iwl3945" +#include "iwl-fh.h" +#include "iwl-3945-fh.h" #include "iwl-commands.h" #include "iwl-3945.h" -#include "iwl-3945-fh.h" #include "iwl-helpers.h" #include "iwl-core.h" #include "iwl-dev.h" @@ -180,13 +181,13 @@ static int iwl3945_tx_queue_alloc(struct iwl_priv *priv, /* Circular buffer of transmit frame descriptors (TFDs), * shared with device */ - txq->bd = pci_alloc_consistent(dev, - sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX, + txq->tfds = pci_alloc_consistent(dev, + sizeof(txq->tfds[0]) * TFD_QUEUE_SIZE_MAX, &txq->q.dma_addr); - if (!txq->bd) { + if (!txq->tfds) { IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", - sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX); + sizeof(txq->tfds[0]) * TFD_QUEUE_SIZE_MAX); goto error; } txq->q.id = id; @@ -278,8 +279,8 @@ void iwl3945_tx_queue_free(struct iwl_priv *priv, struct iwl3945_tx_queue *txq) /* De-alloc circular buffer of TFDs */ if (txq->q.n_bd) - pci_free_consistent(dev, sizeof(struct iwl3945_tfd_frame) * - txq->q.n_bd, txq->bd, txq->q.dma_addr); + pci_free_consistent(dev, sizeof(struct iwl3945_tfd) * + txq->q.n_bd, txq->tfds, txq->q.dma_addr); /* De-alloc array of per-TFD driver data */ kfree(txq->txb); @@ -445,14 +446,12 @@ static int iwl3945_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { struct iwl3945_tx_queue *txq = &priv->txq39[IWL_CMD_QUEUE_NUM]; struct iwl_queue *q = &txq->q; - struct iwl3945_tfd_frame *tfd; - u32 *control_flags; + struct iwl3945_tfd *tfd; struct iwl_cmd *out_cmd; u32 idx; u16 fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); dma_addr_t phys_addr; int pad; - u16 count; int ret; unsigned long flags; @@ -475,11 +474,9 @@ static int iwl3945_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) spin_lock_irqsave(&priv->hcmd_lock, flags); - tfd = &txq->bd[q->write_ptr]; + tfd = &txq->tfds[q->write_ptr]; memset(tfd, 0, sizeof(*tfd)); - control_flags = (u32 *) tfd; - idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE); out_cmd = &txq->cmd[idx]; @@ -501,8 +498,7 @@ static int iwl3945_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) iwl3945_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size); pad = U32_PAD(cmd->len); - count = TFD_CTL_COUNT_GET(*control_flags); - *control_flags = TFD_CTL_COUNT_SET(count) | TFD_CTL_PAD_SET(pad); + tfd->control_flags |= cpu_to_le32(TFD_CTL_PAD_SET(pad)); IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, " "%d bytes at %d[%d]:%d\n", @@ -2231,8 +2227,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct iwl3945_tfd_frame *tfd; - u32 *control_flags; + struct iwl3945_tfd *tfd; int txq_id = skb_get_queue_mapping(skb); struct iwl3945_tx_queue *txq = NULL; struct iwl_queue *q = NULL; @@ -2317,13 +2312,12 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) spin_lock_irqsave(&priv->lock, flags); /* Set up first empty TFD within this queue's circular TFD buffer */ - tfd = &txq->bd[q->write_ptr]; + tfd = &txq->tfds[q->write_ptr]; memset(tfd, 0, sizeof(*tfd)); - control_flags = (u32 *) tfd; idx = get_cmd_index(q, q->write_ptr, 0); /* Set up driver data for this TFD */ - memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl3945_tx_info)); + memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); txq->txb[q->write_ptr].skb[0] = skb; /* Init first empty entry in queue's array of Tx/cmd buffers */ @@ -2387,12 +2381,12 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (!len) /* If there is no payload, then we use only one Tx buffer */ - *control_flags = TFD_CTL_COUNT_SET(1); + tfd->control_flags = cpu_to_le32(TFD_CTL_COUNT_SET(1)); else /* Else use 2 buffers. * Tell 3945 about any padding after MAC header */ - *control_flags = TFD_CTL_COUNT_SET(2) | - TFD_CTL_PAD_SET(U32_PAD(len)); + tfd->control_flags = cpu_to_le32(TFD_CTL_COUNT_SET(2) | + TFD_CTL_PAD_SET(U32_PAD(len))); /* Total # bytes to be transmitted */ len = (u16)skb->len; -- GitLab From 42427b4e436bbbf038742ecbb3bf09815f93ed7a Mon Sep 17 00:00:00 2001 From: "Kolekar, Abhijeet" Date: Mon, 22 Dec 2008 11:31:15 +0800 Subject: [PATCH 0739/4982] iwl3945: adding utils ops The patch implements iwl_hcmd_utils_ops for 3945. Signed-off-by: Samuel Ortiz Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 6810909f3fe..be0974d528e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2376,6 +2376,19 @@ int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl3945_tx_queue *txq return 0; } +/* + * HCMD utils + */ +static u16 iwl3945_get_hcmd_size(u8 cmd_id, u16 len) +{ + switch (cmd_id) { + case REPLY_RXON: + return (u16) sizeof(struct iwl3945_rxon_cmd); + default: + return len; + } +} + /** * iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table */ @@ -2693,8 +2706,13 @@ static struct iwl_lib_ops iwl3945_lib = { }, }; +static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { + .get_hcmd_size = iwl3945_get_hcmd_size, +}; + static struct iwl_ops iwl3945_ops = { .lib = &iwl3945_lib, + .utils = &iwl3945_hcmd_utils, }; static struct iwl_cfg iwl3945_bg_cfg = { -- GitLab From 188cf6c73a72be1d8c118580a40d70cd76415eec Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 22 Dec 2008 11:31:16 +0800 Subject: [PATCH 0740/4982] iwl3945: sync tx queue data structure with iwlagn We are now using the iwl_tx_queue for iwl3945. To reach that goal, we included the 3945 specific tfd frame structure to iwl_tx_queue. This has no effect on the current iwlagn code. Signed-off-by: Samuel Ortiz Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 4 - drivers/net/wireless/iwlwifi/iwl-3945.c | 14 +-- drivers/net/wireless/iwlwifi/iwl-3945.h | 8 +- drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 3 - drivers/net/wireless/iwlwifi/iwl-dev.h | 28 +---- drivers/net/wireless/iwlwifi/iwl-fh.h | 11 ++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 125 ++++++++++++-------- 7 files changed, 103 insertions(+), 90 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 1ba59dfacd1..c9db98cd0e4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -240,7 +240,6 @@ struct iwl3945_eeprom { #define TFD_QUEUE_MIN 0 #define TFD_QUEUE_MAX 6 -#define TFD_QUEUE_SIZE_MAX (256) #define IWL_NUM_SCAN_RATES (2) @@ -262,9 +261,6 @@ struct iwl3945_eeprom { #define TFD_CTL_PAD_SET(n) (n << 28) #define TFD_CTL_PAD_GET(ctl) (ctl >> 28) -#define TFD_TX_CMD_SLOTS 256 -#define TFD_CMD_SLOTS 32 - /* * RX related structures and functions */ diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index be0974d528e..54ad07722b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -306,7 +306,7 @@ int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate) static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) { - struct iwl3945_tx_queue *txq = &priv->txq39[txq_id]; + struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct iwl_queue *q = &txq->q; struct iwl_tx_info *tx_info; @@ -337,7 +337,7 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv, u16 sequence = le16_to_cpu(pkt->hdr.sequence); int txq_id = SEQ_TO_QUEUE(sequence); int index = SEQ_TO_INDEX(sequence); - struct iwl3945_tx_queue *txq = &priv->txq39[txq_id]; + struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct ieee80211_tx_info *info; struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; u32 status = le32_to_cpu(tx_resp->status); @@ -756,9 +756,9 @@ int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr, * * Does NOT advance any indexes */ -int iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl3945_tx_queue *txq) +int iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) { - struct iwl3945_tfd *tfd_tmp = (struct iwl3945_tfd *)&txq->tfds[0]; + struct iwl3945_tfd *tfd_tmp = (struct iwl3945_tfd *)&txq->tfds39[0]; struct iwl3945_tfd *tfd = &tfd_tmp[txq->q.read_ptr]; struct pci_dev *dev = priv->pci_dev; int i; @@ -1061,7 +1061,7 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv) for (txq_id = 0; txq_id < TFD_QUEUE_MAX; txq_id++) { slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; - rc = iwl3945_tx_queue_init(priv, &priv->txq39[txq_id], slots_num, + rc = iwl3945_tx_queue_init(priv, &priv->txq[txq_id], slots_num, txq_id); if (rc) { IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); @@ -1251,7 +1251,7 @@ void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv) /* Tx queues */ for (txq_id = 0; txq_id < TFD_QUEUE_MAX; txq_id++) - iwl3945_tx_queue_free(priv, &priv->txq39[txq_id]); + iwl3945_tx_queue_free(priv, &priv->txq[txq_id]); } void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) @@ -2342,7 +2342,7 @@ int iwl3945_hw_rxq_stop(struct iwl_priv *priv) return 0; } -int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl3945_tx_queue *txq) +int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq) { int rc; unsigned long flags; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 716c4b46233..e584032a1a3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -219,9 +219,9 @@ extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, extern int iwl3945_calc_db_from_ratio(int sig_ratio); extern int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm); extern int iwl3945_tx_queue_init(struct iwl_priv *priv, - struct iwl3945_tx_queue *txq, int count, u32 id); + struct iwl_tx_queue *txq, int count, u32 id); extern void iwl3945_rx_replenish(void *data); -extern void iwl3945_tx_queue_free(struct iwl_priv *priv, struct iwl3945_tx_queue *txq); +extern void iwl3945_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq); extern int iwl3945_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data); extern int __must_check iwl3945_send_cmd(struct iwl_priv *priv, @@ -270,10 +270,10 @@ extern void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv); extern int iwl3945_hw_nic_reset(struct iwl_priv *priv); extern int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *tfd, dma_addr_t addr, u16 len); -extern int iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl3945_tx_queue *txq); +extern int iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); extern int iwl3945_hw_get_temperature(struct iwl_priv *priv); extern int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, - struct iwl3945_tx_queue *txq); + struct iwl_tx_queue *txq); extern unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv, struct iwl3945_frame *frame, u8 rate); void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, struct iwl_cmd *cmd, diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 9330b5a1aab..e751c53ae1f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -114,9 +114,6 @@ #define RX_QUEUE_MASK 255 #define RX_QUEUE_SIZE_LOG 8 -#define TFD_TX_CMD_SLOTS 256 -#define TFD_CMD_SLOTS 32 - /* * RX related structures and functions */ diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 1ad4d084e35..9b9d7435321 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -134,9 +134,13 @@ struct iwl_tx_info { * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame * descriptors) and required locking structures. */ +#define TFD_TX_CMD_SLOTS 256 +#define TFD_CMD_SLOTS 32 + struct iwl_tx_queue { struct iwl_queue q; struct iwl_tfd *tfds; + struct iwl3945_tfd *tfds39; struct iwl_cmd *cmd[TFD_TX_CMD_SLOTS]; struct iwl_tx_info *txb; u8 need_update; @@ -226,28 +230,6 @@ struct iwl_channel_info { struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES]; }; -/** - * struct iwl3945_tx_queue - Tx Queue for DMA - * @q: generic Rx/Tx queue descriptor - * @bd: base of circular buffer of TFDs - * @cmd: array of command/Tx buffers - * @dma_addr_cmd: physical address of cmd/tx buffer array - * @txb: array of per-TFD driver data - * @need_update: indicates need to update read/write index - * - * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame - * descriptors) and required locking structures. - */ -struct iwl3945_tx_queue { - struct iwl_queue q; - struct iwl3945_tfd *tfds; - struct iwl_cmd *cmd; - dma_addr_t dma_addr_cmd; - struct iwl_tx_info *txb; - int need_update; - int active; -}; - #define IWL_TX_FIFO_AC0 0 #define IWL_TX_FIFO_AC1 1 #define IWL_TX_FIFO_AC2 2 @@ -1099,8 +1081,6 @@ struct iwl_priv { struct iwl3945_rxon_cmd staging39_rxon; struct iwl3945_rxon_cmd recovery39_rxon; - struct iwl3945_tx_queue txq39[IWL39_MAX_NUM_QUEUES]; - struct iwl3945_power_mgr power_data_39; struct iwl3945_notif_statistics statistics_39; diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index 7c19790a3ea..313b03b5b4c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -478,6 +478,17 @@ struct iwl_tfd { __le32 __pad; } __attribute__ ((packed)); +struct iwl3945_tfd_frame_data { + __le32 addr; + __le32 len; +} __attribute__ ((packed)); + +struct iwl3945_tfd_frame { + __le32 control_flags; + struct iwl3945_tfd_frame_data pa[4]; + u8 reserved[28]; +} __attribute__ ((packed)); + /* Keep Warm Size */ #define IWL_KW_SIZE 0x1000 /* 4k */ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index c37fa00af6d..53e274a5f4f 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -57,7 +57,7 @@ #include "iwl-dev.h" static int iwl3945_tx_queue_update_write_ptr(struct iwl_priv *priv, - struct iwl3945_tx_queue *txq); + struct iwl_tx_queue *txq); /* * module name, copyright, version, etc. @@ -162,7 +162,7 @@ static int iwl3945_queue_init(struct iwl_priv *priv, struct iwl_queue *q, * iwl3945_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue */ static int iwl3945_tx_queue_alloc(struct iwl_priv *priv, - struct iwl3945_tx_queue *txq, u32 id) + struct iwl_tx_queue *txq, u32 id) { struct pci_dev *dev = priv->pci_dev; @@ -181,13 +181,13 @@ static int iwl3945_tx_queue_alloc(struct iwl_priv *priv, /* Circular buffer of transmit frame descriptors (TFDs), * shared with device */ - txq->tfds = pci_alloc_consistent(dev, - sizeof(txq->tfds[0]) * TFD_QUEUE_SIZE_MAX, + txq->tfds39 = pci_alloc_consistent(dev, + sizeof(txq->tfds39[0]) * TFD_QUEUE_SIZE_MAX, &txq->q.dma_addr); - if (!txq->tfds) { + if (!txq->tfds39) { IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", - sizeof(txq->tfds[0]) * TFD_QUEUE_SIZE_MAX); + sizeof(txq->tfds39[0]) * TFD_QUEUE_SIZE_MAX); goto error; } txq->q.id = id; @@ -205,10 +205,9 @@ static int iwl3945_tx_queue_alloc(struct iwl_priv *priv, * iwl3945_tx_queue_init - Allocate and initialize one tx/cmd queue */ int iwl3945_tx_queue_init(struct iwl_priv *priv, - struct iwl3945_tx_queue *txq, int slots_num, u32 txq_id) + struct iwl_tx_queue *txq, int slots_num, u32 txq_id) { - struct pci_dev *dev = priv->pci_dev; - int len; + int len, i; int rc = 0; /* @@ -219,20 +218,25 @@ int iwl3945_tx_queue_init(struct iwl_priv *priv, * For data Tx queues (all other queues), no super-size command * space is needed. */ - len = sizeof(struct iwl_cmd) * slots_num; - if (txq_id == IWL_CMD_QUEUE_NUM) - len += IWL_MAX_SCAN_SIZE; - txq->cmd = pci_alloc_consistent(dev, len, &txq->dma_addr_cmd); - if (!txq->cmd) - return -ENOMEM; + len = sizeof(struct iwl_cmd); + for (i = 0; i <= slots_num; i++) { + if (i == slots_num) { + if (txq_id == IWL_CMD_QUEUE_NUM) + len += IWL_MAX_SCAN_SIZE; + else + continue; + } + + txq->cmd[i] = kmalloc(len, GFP_KERNEL); + if (!txq->cmd[i]) + goto err; + } /* Alloc driver data array and TFD circular buffer */ rc = iwl3945_tx_queue_alloc(priv, txq, txq_id); - if (rc) { - pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd); + if (rc) + goto err; - return -ENOMEM; - } txq->need_update = 0; /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise @@ -246,6 +250,17 @@ int iwl3945_tx_queue_init(struct iwl_priv *priv, iwl3945_hw_tx_queue_init(priv, txq); return 0; +err: + for (i = 0; i < slots_num; i++) { + kfree(txq->cmd[i]); + txq->cmd[i] = NULL; + } + + if (txq_id == IWL_CMD_QUEUE_NUM) { + kfree(txq->cmd[slots_num]); + txq->cmd[slots_num] = NULL; + } + return -ENOMEM; } /** @@ -256,11 +271,11 @@ int iwl3945_tx_queue_init(struct iwl_priv *priv, * Free all buffers. * 0-fill, but do not free "txq" descriptor structure. */ -void iwl3945_tx_queue_free(struct iwl_priv *priv, struct iwl3945_tx_queue *txq) +void iwl3945_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq) { struct iwl_queue *q = &txq->q; struct pci_dev *dev = priv->pci_dev; - int len; + int len, i; if (q->n_bd == 0) return; @@ -275,12 +290,13 @@ void iwl3945_tx_queue_free(struct iwl_priv *priv, struct iwl3945_tx_queue *txq) len += IWL_MAX_SCAN_SIZE; /* De-alloc array of command/tx buffers */ - pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd); + for (i = 0; i < TFD_TX_CMD_SLOTS; i++) + kfree(txq->cmd[i]); /* De-alloc circular buffer of TFDs */ if (txq->q.n_bd) pci_free_consistent(dev, sizeof(struct iwl3945_tfd) * - txq->q.n_bd, txq->tfds, txq->q.dma_addr); + txq->q.n_bd, txq->tfds39, txq->q.dma_addr); /* De-alloc array of per-TFD driver data */ kfree(txq->txb); @@ -444,7 +460,7 @@ u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flag */ static int iwl3945_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { - struct iwl3945_tx_queue *txq = &priv->txq39[IWL_CMD_QUEUE_NUM]; + struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; struct iwl_queue *q = &txq->q; struct iwl3945_tfd *tfd; struct iwl_cmd *out_cmd; @@ -452,7 +468,7 @@ static int iwl3945_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) u16 fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); dma_addr_t phys_addr; int pad; - int ret; + int ret, len; unsigned long flags; /* If any of the command structures end up being larger than @@ -474,11 +490,11 @@ static int iwl3945_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) spin_lock_irqsave(&priv->hcmd_lock, flags); - tfd = &txq->tfds[q->write_ptr]; + tfd = &txq->tfds39[q->write_ptr]; memset(tfd, 0, sizeof(*tfd)); idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE); - out_cmd = &txq->cmd[idx]; + out_cmd = txq->cmd[idx]; out_cmd->hdr.cmd = cmd->id; memcpy(&out_cmd->meta, &cmd->meta, sizeof(cmd->meta)); @@ -493,8 +509,15 @@ static int iwl3945_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) if (out_cmd->meta.flags & CMD_SIZE_HUGE) out_cmd->hdr.sequence |= SEQ_HUGE_FRAME; - phys_addr = txq->dma_addr_cmd + sizeof(txq->cmd[0]) * idx + - offsetof(struct iwl_cmd, hdr); + len = (idx == TFD_CMD_SLOTS) ? + IWL_MAX_SCAN_SIZE : sizeof(struct iwl_cmd); + + phys_addr = pci_map_single(priv->pci_dev, out_cmd, + len, PCI_DMA_TODEVICE); + pci_unmap_addr_set(&out_cmd->meta, mapping, phys_addr); + pci_unmap_len_set(&out_cmd->meta, len, len); + phys_addr += offsetof(struct iwl_cmd, hdr); + iwl3945_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size); pad = U32_PAD(cmd->len); @@ -620,7 +643,7 @@ cancel: * TX cmd queue. Otherwise in case the cmd comes * in later, it will possibly set an invalid * address (cmd->meta.source). */ - qcmd = &priv->txq39[IWL_CMD_QUEUE_NUM].cmd[cmd_idx]; + qcmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx]; qcmd->meta.flags &= ~CMD_WANT_SKB; } fail: @@ -2229,7 +2252,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct iwl3945_tfd *tfd; int txq_id = skb_get_queue_mapping(skb); - struct iwl3945_tx_queue *txq = NULL; + struct iwl_tx_queue *txq = NULL; struct iwl_queue *q = NULL; dma_addr_t phys_addr; dma_addr_t txcmd_phys; @@ -2306,13 +2329,13 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) } /* Descriptor for chosen Tx queue */ - txq = &priv->txq39[txq_id]; + txq = &priv->txq[txq_id]; q = &txq->q; spin_lock_irqsave(&priv->lock, flags); /* Set up first empty TFD within this queue's circular TFD buffer */ - tfd = &txq->tfds[q->write_ptr]; + tfd = &txq->tfds39[q->write_ptr]; memset(tfd, 0, sizeof(*tfd)); idx = get_cmd_index(q, q->write_ptr, 0); @@ -2321,7 +2344,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) txq->txb[q->write_ptr].skb[0] = skb; /* Init first empty entry in queue's array of Tx/cmd buffers */ - out_cmd = &txq->cmd[idx]; + out_cmd = txq->cmd[idx]; memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); memset(&out_cmd->cmd.tx, 0, sizeof(out_cmd->cmd.tx)); @@ -2360,8 +2383,14 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* Physical address of this Tx command's header (not MAC header!), * within command buffer array. */ - txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl_cmd) * idx + - offsetof(struct iwl_cmd, hdr); + txcmd_phys = pci_map_single(priv->pci_dev, + out_cmd, sizeof(struct iwl_cmd), + PCI_DMA_TODEVICE); + pci_unmap_addr_set(&out_cmd->meta, mapping, txcmd_phys); + pci_unmap_len_set(&out_cmd->meta, len, sizeof(struct iwl_cmd)); + /* Add buffer containing Tx command and MAC(!) header to TFD's + * first entry */ + txcmd_phys += offsetof(struct iwl_cmd, hdr); /* Add buffer containing Tx command and MAC(!) header to TFD's * first entry */ @@ -3076,7 +3105,7 @@ static void iwl3945_setup_rx_handlers(struct iwl_priv *priv) static void iwl3945_cmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) { - struct iwl3945_tx_queue *txq = &priv->txq39[txq_id]; + struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct iwl_queue *q = &txq->q; int nfreed = 0; @@ -3121,8 +3150,8 @@ static void iwl3945_tx_cmd_complete(struct iwl_priv *priv, BUG_ON(txq_id != IWL_CMD_QUEUE_NUM); - cmd_index = get_cmd_index(&priv->txq39[IWL_CMD_QUEUE_NUM].q, index, huge); - cmd = &priv->txq39[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; + cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); + cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; /* Input error checking is done when commands are added to queue. */ if (cmd->meta.flags & CMD_WANT_SKB) { @@ -3678,7 +3707,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) * iwl3945_tx_queue_update_write_ptr - Send new write index to hardware */ static int iwl3945_tx_queue_update_write_ptr(struct iwl_priv *priv, - struct iwl3945_tx_queue *txq) + struct iwl_tx_queue *txq) { u32 reg = 0; int rc = 0; @@ -4088,12 +4117,12 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) if (inta & CSR_INT_BIT_WAKEUP) { IWL_DEBUG_ISR("Wakeup interrupt\n"); iwl3945_rx_queue_update_write_ptr(priv, &priv->rxq); - iwl3945_tx_queue_update_write_ptr(priv, &priv->txq39[0]); - iwl3945_tx_queue_update_write_ptr(priv, &priv->txq39[1]); - iwl3945_tx_queue_update_write_ptr(priv, &priv->txq39[2]); - iwl3945_tx_queue_update_write_ptr(priv, &priv->txq39[3]); - iwl3945_tx_queue_update_write_ptr(priv, &priv->txq39[4]); - iwl3945_tx_queue_update_write_ptr(priv, &priv->txq39[5]); + iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[0]); + iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[1]); + iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[2]); + iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[3]); + iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[4]); + iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[5]); handled |= CSR_INT_BIT_WAKEUP; } @@ -6735,7 +6764,7 @@ static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw, { struct iwl_priv *priv = hw->priv; int i, avail; - struct iwl3945_tx_queue *txq; + struct iwl_tx_queue *txq; struct iwl_queue *q; unsigned long flags; @@ -6749,7 +6778,7 @@ static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw, spin_lock_irqsave(&priv->lock, flags); for (i = 0; i < AC_NUM; i++) { - txq = &priv->txq39[i]; + txq = &priv->txq[i]; q = &txq->q; avail = iwl_queue_space(q); -- GitLab From c496294efe6ebc9bd5dd1e0d3cce5d1ad6a1ea2c Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 22 Dec 2008 11:31:18 +0800 Subject: [PATCH 0741/4982] iwl3945: switch to the iwl-core send_card_state routine Switch iwl3945 to use iwl-core:send_card_state routine. Signed-off-by: Samuel Ortiz Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 3 +- drivers/net/wireless/iwlwifi/iwl-core.h | 3 ++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 34 +-------------------- 3 files changed, 6 insertions(+), 34 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index cde233d1574..76315c30e6f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1368,7 +1368,7 @@ EXPORT_SYMBOL(iwl_rf_kill_ct_config); * When in the 'halt' state, the card is shut down and must be fully * restarted to come back on. */ -static int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag) +int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag) { struct iwl_host_cmd cmd = { .id = REPLY_CARD_STATE_CMD, @@ -1379,6 +1379,7 @@ static int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag) return iwl_send_cmd(priv, &cmd); } +EXPORT_SYMBOL(iwl_send_card_state); void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv) { diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 7c3a20a986b..2abda89daaf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -342,6 +342,9 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len, int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); +int iwl_send_card_state(struct iwl_priv *priv, u32 flags, + u8 meta_flag); + /***************************************************** * PCI * *****************************************************/ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 53e274a5f4f..afde87bc499 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1076,38 +1076,6 @@ static int iwl3945_send_scan_abort(struct iwl_priv *priv) return rc; } -static int iwl3945_card_state_sync_callback(struct iwl_priv *priv, - struct iwl_cmd *cmd, - struct sk_buff *skb) -{ - return 1; -} - -/* - * CARD_STATE_CMD - * - * Use: Sets the device's internal card state to enable, disable, or halt - * - * When in the 'enable' state the card operates as normal. - * When in the 'disable' state, the card enters into a low power mode. - * When in the 'halt' state, the card is shut down and must be fully - * restarted to come back on. - */ -static int iwl3945_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag) -{ - struct iwl_host_cmd cmd = { - .id = REPLY_CARD_STATE_CMD, - .len = sizeof(u32), - .data = &flags, - .meta.flags = meta_flag, - }; - - if (meta_flag & CMD_ASYNC) - cmd.meta.u.callback = iwl3945_card_state_sync_callback; - - return iwl3945_send_cmd(priv, &cmd); -} - static int iwl3945_add_sta_sync_callback(struct iwl_priv *priv, struct iwl_cmd *cmd, struct sk_buff *skb) { @@ -2545,7 +2513,7 @@ static void iwl3945_radio_kill_sw(struct iwl_priv *priv, int disable_radio) iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_SW_BIT_RFKILL); spin_unlock_irqrestore(&priv->lock, flags); - iwl3945_send_card_state(priv, CARD_STATE_CMD_DISABLE, 0); + iwl_send_card_state(priv, CARD_STATE_CMD_DISABLE, 0); set_bit(STATUS_RF_KILL_SW, &priv->status); } return; -- GitLab From e52119c50d6a35506b1c063eeacf7acc40b4e03d Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Mon, 22 Dec 2008 11:31:19 +0800 Subject: [PATCH 0742/4982] iwl3945: use iwl3945_tx_cmd instead of iwl_tx_cmd The patch replaces iwl_tx_cmd with iwl3945_tx_cmd to complete transitions introduced by "iwlwifi: use iwl_cmd instead of iwl3945_cmd" Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 66 +++++++++++---------- 2 files changed, 35 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 54ad07722b0..0260545e356 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1322,7 +1322,7 @@ static void iwl3945_apm_stop(struct iwl_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } -int iwl3945_apm_reset(struct iwl_priv *priv) +static int iwl3945_apm_reset(struct iwl_priv *priv) { int rc; unsigned long flags; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index afde87bc499..0059d288931 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2045,36 +2045,37 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, struct sk_buff *skb_frag, int last_frag) { + struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload; struct iwl3945_hw_key *keyinfo = &priv->stations_39[info->control.hw_key->hw_key_idx].keyinfo; switch (keyinfo->alg) { case ALG_CCMP: - cmd->cmd.tx.sec_ctl = TX_CMD_SEC_CCM; - memcpy(cmd->cmd.tx.key, keyinfo->key, keyinfo->keylen); + tx->sec_ctl = TX_CMD_SEC_CCM; + memcpy(tx->key, keyinfo->key, keyinfo->keylen); IWL_DEBUG_TX("tx_cmd with AES hwcrypto\n"); break; case ALG_TKIP: #if 0 - cmd->cmd.tx.sec_ctl = TX_CMD_SEC_TKIP; + tx->sec_ctl = TX_CMD_SEC_TKIP; if (last_frag) - memcpy(cmd->cmd.tx.tkip_mic.byte, skb_frag->tail - 8, + memcpy(tx->tkip_mic.byte, skb_frag->tail - 8, 8); else - memset(cmd->cmd.tx.tkip_mic.byte, 0, 8); + memset(tx->tkip_mic.byte, 0, 8); #endif break; case ALG_WEP: - cmd->cmd.tx.sec_ctl = TX_CMD_SEC_WEP | + tx->sec_ctl = TX_CMD_SEC_WEP | (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT; if (keyinfo->keylen == 13) - cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128; + tx->sec_ctl |= TX_CMD_SEC_KEY128; - memcpy(&cmd->cmd.tx.key[3], keyinfo->key, keyinfo->keylen); + memcpy(&tx->key[3], keyinfo->key, keyinfo->keylen); IWL_DEBUG_TX("Configuring packet for WEP encryption " "with key %d\n", info->control.hw_key->hw_key_idx); @@ -2092,14 +2093,14 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv, struct iwl_cmd *cmd, struct ieee80211_tx_info *info, - struct ieee80211_hdr *hdr, - int is_unicast, u8 std_id) + struct ieee80211_hdr *hdr, u8 std_id) { + struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload; + __le32 tx_flags = tx->tx_flags; __le16 fc = hdr->frame_control; - __le32 tx_flags = cmd->cmd.tx.tx_flags; u8 rc_flags = info->control.rates[0].flags; - cmd->cmd.tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; + tx->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { tx_flags |= TX_CMD_FLG_ACK_MSK; if (ieee80211_is_mgmt(fc)) @@ -2112,13 +2113,13 @@ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv, tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; } - cmd->cmd.tx.sta_id = std_id; + tx->sta_id = std_id; if (ieee80211_has_morefrags(fc)) tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; if (ieee80211_is_data_qos(fc)) { u8 *qc = ieee80211_get_qos_ctl(hdr); - cmd->cmd.tx.tid_tspec = qc[0] & 0xf; + tx->tid_tspec = qc[0] & 0xf; tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; } else { tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; @@ -2138,19 +2139,19 @@ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv, tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); if (ieee80211_is_mgmt(fc)) { if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc)) - cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(3); + tx->timeout.pm_frame_timeout = cpu_to_le16(3); else - cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(2); + tx->timeout.pm_frame_timeout = cpu_to_le16(2); } else { - cmd->cmd.tx.timeout.pm_frame_timeout = 0; + tx->timeout.pm_frame_timeout = 0; #ifdef CONFIG_IWL3945_LEDS priv->rxtxpackets += le16_to_cpu(cmd->cmd.tx.len); #endif } - cmd->cmd.tx.driver_txop = 0; - cmd->cmd.tx.tx_flags = tx_flags; - cmd->cmd.tx.next_frame_len = 0; + tx->driver_txop = 0; + tx->tx_flags = tx_flags; + tx->next_frame_len = 0; } /** @@ -2219,12 +2220,13 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct iwl3945_tfd *tfd; - int txq_id = skb_get_queue_mapping(skb); + struct iwl3945_tx_cmd *tx; struct iwl_tx_queue *txq = NULL; struct iwl_queue *q = NULL; + struct iwl_cmd *out_cmd = NULL; dma_addr_t phys_addr; dma_addr_t txcmd_phys; - struct iwl_cmd *out_cmd = NULL; + int txq_id = skb_get_queue_mapping(skb); u16 len, idx, len_org, hdr_len; u8 id; u8 unicast; @@ -2313,8 +2315,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* Init first empty entry in queue's array of Tx/cmd buffers */ out_cmd = txq->cmd[idx]; + tx = (struct iwl3945_tx_cmd *)out_cmd->cmd.payload; memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); - memset(&out_cmd->cmd.tx, 0, sizeof(out_cmd->cmd.tx)); + memset(tx, 0, sizeof(*tx)); /* * Set up the Tx-command (not MAC!) header. @@ -2327,7 +2330,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) INDEX_TO_SEQ(q->write_ptr))); /* Copy MAC header from skb into command buffer */ - memcpy(out_cmd->cmd.tx.hdr, hdr, hdr_len); + memcpy(tx->hdr, hdr, hdr_len); /* * Use the first empty entry in this queue's command buffer array @@ -2387,16 +2390,16 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* Total # bytes to be transmitted */ len = (u16)skb->len; - out_cmd->cmd.tx.len = cpu_to_le16(len); + tx->len = cpu_to_le16(len); /* TODO need this for burst mode later on */ - iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, unicast, sta_id); + iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, sta_id); /* set is_hcca to 0; it probably will never be implemented */ iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, info, hdr, sta_id, 0); - out_cmd->cmd.tx.tx_flags &= ~TX_CMD_FLG_ANT_A_MSK; - out_cmd->cmd.tx.tx_flags &= ~TX_CMD_FLG_ANT_B_MSK; + tx->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK; + tx->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK; if (!ieee80211_has_morefrags(hdr->frame_control)) { txq->need_update = 1; @@ -2407,10 +2410,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) txq->need_update = 0; } - iwl_print_hex_dump(priv, IWL_DL_TX, out_cmd->cmd.payload, - sizeof(out_cmd->cmd.tx)); + iwl_print_hex_dump(priv, IWL_DL_TX, tx, sizeof(*tx)); - iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr, + iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx->hdr, ieee80211_hdrlen(fc)); /* Tell device the write index *just past* this latest filled TFD */ @@ -7407,7 +7409,7 @@ static struct ieee80211_ops iwl3945_hw_ops = { .hw_scan = iwl3945_mac_hw_scan }; -int iwl3945_init_drv(struct iwl_priv *priv) +static int iwl3945_init_drv(struct iwl_priv *priv) { int ret; -- GitLab From 51af3d3fbbe326077a7e245268a7de325de6ecd2 Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Mon, 22 Dec 2008 11:31:23 +0800 Subject: [PATCH 0743/4982] iwl3945: use rx queue management infrastructure from iwlcore This patch uses rx queue alloc free and reset function from iwlcore. This should fix the regression reported by Kalle Valo. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 4 +- drivers/net/wireless/iwlwifi/iwl-3945.h | 3 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 81 +-------------------- 3 files changed, 3 insertions(+), 85 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 0260545e356..d4ee15ed5e4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1202,13 +1202,13 @@ int iwl3945_hw_nic_init(struct iwl_priv *priv) /* Allocate the RX queue, or reset if it is already allocated */ if (!rxq->bd) { - rc = iwl3945_rx_queue_alloc(priv); + rc = iwl_rx_queue_alloc(priv); if (rc) { IWL_ERR(priv, "Unable to initialize Rx queue\n"); return -ENOMEM; } } else - iwl3945_rx_queue_reset(priv, rxq); + iwl_rx_queue_reset(priv, rxq); iwl3945_rx_replenish(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index e584032a1a3..c5f5481edb3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -213,9 +213,6 @@ extern u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *bssid, int is_ap, u8 flags); extern int iwl3945_power_init_handle(struct iwl_priv *priv); extern int iwl3945_eeprom_init(struct iwl_priv *priv); -extern int iwl3945_rx_queue_alloc(struct iwl_priv *priv); -extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, - struct iwl_rx_queue *rxq); extern int iwl3945_calc_db_from_ratio(int sig_ratio); extern int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm); extern int iwl3945_tx_queue_init(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 0059d288931..a176f42fd7c 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3186,7 +3186,6 @@ static void iwl3945_tx_cmd_complete(struct iwl_priv *priv, * * Driver sequence: * - * iwl3945_rx_queue_alloc() Allocates rx_free * iwl3945_rx_replenish() Replenishes rx_free list from rx_used, and calls * iwl3945_rx_queue_restock * iwl3945_rx_queue_restock() Moves available buffers from rx_free into Rx @@ -3405,84 +3404,6 @@ void iwl3945_rx_replenish(void *data) spin_unlock_irqrestore(&priv->lock, flags); } -/* Assumes that the skb field of the buffers in 'pool' is kept accurate. - * If an SKB has been detached, the POOL needs to have its SKB set to NULL - * This free routine walks the list of POOL entries and if SKB is set to - * non NULL it is unmapped and freed - */ -static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) -{ - int i; - for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { - if (rxq->pool[i].skb != NULL) { - pci_unmap_single(priv->pci_dev, - rxq->pool[i].real_dma_addr, - IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); - dev_kfree_skb(rxq->pool[i].skb); - } - } - - pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd, - rxq->dma_addr); - rxq->bd = NULL; -} - -int iwl3945_rx_queue_alloc(struct iwl_priv *priv) -{ - struct iwl_rx_queue *rxq = &priv->rxq; - struct pci_dev *dev = priv->pci_dev; - int i; - - spin_lock_init(&rxq->lock); - INIT_LIST_HEAD(&rxq->rx_free); - INIT_LIST_HEAD(&rxq->rx_used); - - /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ - rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr); - if (!rxq->bd) - return -ENOMEM; - - /* Fill the rx_used queue with _all_ of the Rx buffers */ - for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) - list_add_tail(&rxq->pool[i].list, &rxq->rx_used); - - /* Set us so that we have processed and used all buffers, but have - * not restocked the Rx queue with fresh buffers */ - rxq->read = rxq->write = 0; - rxq->free_count = 0; - rxq->need_update = 0; - return 0; -} - -void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) -{ - unsigned long flags; - int i; - spin_lock_irqsave(&rxq->lock, flags); - INIT_LIST_HEAD(&rxq->rx_free); - INIT_LIST_HEAD(&rxq->rx_used); - /* Fill the rx_used queue with _all_ of the Rx buffers */ - for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { - /* In the reset function, these buffers may have been allocated - * to an SKB, so we need to unmap and free potential storage */ - if (rxq->pool[i].skb != NULL) { - pci_unmap_single(priv->pci_dev, - rxq->pool[i].real_dma_addr, - IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); - priv->alloc_rxb_skb--; - dev_kfree_skb(rxq->pool[i].skb); - rxq->pool[i].skb = NULL; - } - list_add_tail(&rxq->pool[i].list, &rxq->rx_used); - } - - /* Set us so that we have processed and used all buffers, but have - * not restocked the Rx queue with fresh buffers */ - rxq->read = rxq->write = 0; - rxq->free_count = 0; - spin_unlock_irqrestore(&rxq->lock, flags); -} - /* Convert linear signal-to-noise ratio into dB */ static u8 ratio2dB[100] = { /* 0 1 2 3 4 5 6 7 8 9 */ @@ -7731,7 +7652,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) iwl3945_dealloc_ucode_pci(priv); if (priv->rxq.bd) - iwl3945_rx_queue_free(priv, &priv->rxq); + iwl_rx_queue_free(priv, &priv->rxq); iwl3945_hw_txq_ctx_free(priv); iwl3945_unset_hw_params(priv); -- GitLab From 10c806b32db1c9f010945e92043ef2a3f6fffc3f Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 23 Dec 2008 15:58:36 -0800 Subject: [PATCH 0744/4982] mac80211: add HT conf helpers In HT capable drivers you often need to check if you are currently using HT20 or HT40. This adds a few small helpers to let drivers figure that out. Signed-off-by: Luis R. Rodriguez Acked-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 559422fc094..1e8db8ae615 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1962,4 +1962,34 @@ rate_lowest_index(struct ieee80211_supported_band *sband, int ieee80211_rate_control_register(struct rate_control_ops *ops); void ieee80211_rate_control_unregister(struct rate_control_ops *ops); +static inline bool +conf_is_ht20(struct ieee80211_conf *conf) +{ + return conf->ht.channel_type == NL80211_CHAN_HT20; +} + +static inline bool +conf_is_ht40_minus(struct ieee80211_conf *conf) +{ + return conf->ht.channel_type == NL80211_CHAN_HT40MINUS; +} + +static inline bool +conf_is_ht40_plus(struct ieee80211_conf *conf) +{ + return conf->ht.channel_type == NL80211_CHAN_HT40PLUS; +} + +static inline bool +conf_is_ht40(struct ieee80211_conf *conf) +{ + return conf_is_ht40_minus(conf) || conf_is_ht40_plus(conf); +} + +static inline bool +conf_is_ht(struct ieee80211_conf *conf) +{ + return conf->ht.channel_type != NL80211_CHAN_NO_HT; +} + #endif /* MAC80211_H */ -- GitLab From 030bb495c0c34aa74903ab8cf9c35e4f2f0aedea Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 23 Dec 2008 15:58:37 -0800 Subject: [PATCH 0745/4982] ath9k: use hw->conf on ath_setcurmode() We don't need to use our own mode for setting the the routine tries to do, in fact lets remove ath_chan2mode() now as we can simply use the currently set band and the HT configuration provided by mac80211 through the ieee80211_conf. This works on changing channels as well as the internal ath9k_channel we use is based on the ieee80211_channel in the config. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 72 +++++++++++++++++-------------- 1 file changed, 40 insertions(+), 32 deletions(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 727f067aca4..699d248efc4 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -59,41 +59,47 @@ static void bus_read_cachesize(struct ath_softc *sc, int *csz) *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */ } -static void ath_setcurmode(struct ath_softc *sc, enum wireless_mode mode) +static void ath_setcurmode(struct ath_softc *sc, struct ieee80211_conf *conf) { - sc->cur_rate_table = sc->hw_rate_table[mode]; /* * All protection frames are transmited at 2Mb/s for * 11g, otherwise at 1Mb/s. * XXX select protection rate index from rate table. */ - sc->sc_protrix = (mode == ATH9K_MODE_11G ? 1 : 0); -} - -static enum wireless_mode ath_chan2mode(struct ath9k_channel *chan) -{ - if (chan->chanmode == CHANNEL_A) - return ATH9K_MODE_11A; - else if (chan->chanmode == CHANNEL_G) - return ATH9K_MODE_11G; - else if (chan->chanmode == CHANNEL_B) - return ATH9K_MODE_11B; - else if (chan->chanmode == CHANNEL_A_HT20) - return ATH9K_MODE_11NA_HT20; - else if (chan->chanmode == CHANNEL_G_HT20) - return ATH9K_MODE_11NG_HT20; - else if (chan->chanmode == CHANNEL_A_HT40PLUS) - return ATH9K_MODE_11NA_HT40PLUS; - else if (chan->chanmode == CHANNEL_A_HT40MINUS) - return ATH9K_MODE_11NA_HT40MINUS; - else if (chan->chanmode == CHANNEL_G_HT40PLUS) - return ATH9K_MODE_11NG_HT40PLUS; - else if (chan->chanmode == CHANNEL_G_HT40MINUS) - return ATH9K_MODE_11NG_HT40MINUS; - - WARN_ON(1); /* should not get here */ - - return ATH9K_MODE_11B; + sc->sc_protrix = 0; + switch (conf->channel->band) { + case IEEE80211_BAND_2GHZ: + if (conf_is_ht20(conf)) + sc->cur_rate_table = + sc->hw_rate_table[ATH9K_MODE_11NG_HT20]; + else if (conf_is_ht40_minus(conf)) + sc->cur_rate_table = + sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS]; + else if (conf_is_ht40_plus(conf)) + sc->cur_rate_table = + sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS]; + else { + sc->sc_protrix = 1; + sc->cur_rate_table = + sc->hw_rate_table[ATH9K_MODE_11G]; + } + break; + case IEEE80211_BAND_5GHZ: + if (conf_is_ht20(conf)) + sc->cur_rate_table = + sc->hw_rate_table[ATH9K_MODE_11NA_HT20]; + else if (conf_is_ht40_minus(conf)) + sc->cur_rate_table = + sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS]; + else if (conf_is_ht40_plus(conf)) + sc->cur_rate_table = + sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS]; + else + sc->cur_rate_table = sc->hw_rate_table[ATH9K_MODE_11A]; + break; + default: + break; + } } static void ath_update_txpow(struct ath_softc *sc) @@ -258,6 +264,7 @@ static int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan) { struct ath_hal *ah = sc->sc_ah; bool fastcc = true, stopped; + struct ieee80211_hw *hw = sc->hw; if (sc->sc_flags & SC_OP_INVALID) return -EIO; @@ -316,7 +323,7 @@ static int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan) return -EIO; } - ath_setcurmode(sc, ath_chan2mode(hchan)); + ath_setcurmode(sc, &hw->conf); ath_update_txpow(sc); ath9k_hw_set_interrupts(ah, sc->sc_imask); } @@ -1619,6 +1626,7 @@ detach: int ath_reset(struct ath_softc *sc, bool retry_tx) { struct ath_hal *ah = sc->sc_ah; + struct ieee80211_hw *hw = sc->hw; int status; int error = 0; @@ -1646,7 +1654,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) * that changes the channel so update any state that * might change as a result. */ - ath_setcurmode(sc, ath_chan2mode(sc->sc_ah->ah_curchan)); + ath_setcurmode(sc, &hw->conf); ath_update_txpow(sc); @@ -1943,7 +1951,7 @@ static int ath9k_start(struct ieee80211_hw *hw) !sc->sc_config.swBeaconProcess) sc->sc_imask |= ATH9K_INT_TIM; - ath_setcurmode(sc, ath_chan2mode(init_channel)); + ath_setcurmode(sc, &hw->conf); sc->sc_flags &= ~SC_OP_INVALID; -- GitLab From 96742256aba8c458d49af42610557977245be82d Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 23 Dec 2008 15:58:38 -0800 Subject: [PATCH 0746/4982] ath9k: remove cache of rate preference when using 11g protection No need to cache when we want to use 2Mbit/s for all protection frames for 802.11g as we can determine that dynamically on ath_buf_set_rate() itself. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/core.h | 1 - drivers/net/wireless/ath9k/main.c | 13 +++---------- drivers/net/wireless/ath9k/xmit.c | 13 ++++++++++--- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index 4ca2aed236e..2bb35dda6b9 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -718,7 +718,6 @@ struct ath_softc { u32 sc_keymax; DECLARE_BITMAP(sc_keymap, ATH_KEYMAX); u8 sc_splitmic; - u8 sc_protrix; enum ath9k_int sc_imask; enum PROT_MODE sc_protmode; enum ath9k_ht_extprotspacing sc_ht_extprotspacing; diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 699d248efc4..e26a9a6fbfc 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -61,12 +61,6 @@ static void bus_read_cachesize(struct ath_softc *sc, int *csz) static void ath_setcurmode(struct ath_softc *sc, struct ieee80211_conf *conf) { - /* - * All protection frames are transmited at 2Mb/s for - * 11g, otherwise at 1Mb/s. - * XXX select protection rate index from rate table. - */ - sc->sc_protrix = 0; switch (conf->channel->band) { case IEEE80211_BAND_2GHZ: if (conf_is_ht20(conf)) @@ -78,11 +72,9 @@ static void ath_setcurmode(struct ath_softc *sc, struct ieee80211_conf *conf) else if (conf_is_ht40_plus(conf)) sc->cur_rate_table = sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS]; - else { - sc->sc_protrix = 1; + else sc->cur_rate_table = sc->hw_rate_table[ATH9K_MODE_11G]; - } break; case IEEE80211_BAND_5GHZ: if (conf_is_ht20(conf)) @@ -95,7 +87,8 @@ static void ath_setcurmode(struct ath_softc *sc, struct ieee80211_conf *conf) sc->cur_rate_table = sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS]; else - sc->cur_rate_table = sc->hw_rate_table[ATH9K_MODE_11A]; + sc->cur_rate_table = + sc->hw_rate_table[ATH9K_MODE_11A]; break; default: break; diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index c92f0c6e4ad..3e192fd9591 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -546,7 +546,8 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) struct ieee80211_tx_info *tx_info; struct ieee80211_tx_rate *rates; struct ieee80211_hdr *hdr; - int i, flags, rtsctsena = 0; + struct ieee80211_hw *hw = sc->hw; + int i, flags, rtsctsena = 0, enable_g_protection = 0; u32 ctsduration = 0; u8 rix = 0, cix, ctsrate = 0; __le16 fc; @@ -578,6 +579,12 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) flags = (bf->bf_flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)); cix = rt->info[rix].ctrl_rate; + /* All protection frames are transmited at 2Mb/s for 802.11g, + * otherwise we transmit them at 1Mb/s */ + if (hw->conf.channel->band == IEEE80211_BAND_2GHZ && + !conf_is_ht(&hw->conf)) + enable_g_protection = 1; + /* * If 802.11g protection is enabled, determine whether to use RTS/CTS or * just CTS. Note that this is only done for OFDM/HT unicast frames. @@ -590,7 +597,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) else if (sc->sc_protmode == PROT_M_CTSONLY) flags = ATH9K_TXDESC_CTSENA; - cix = rt->info[sc->sc_protrix].ctrl_rate; + cix = rt->info[enable_g_protection].ctrl_rate; rtsctsena = 1; } @@ -608,7 +615,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) if (sc->sc_config.ath_aggr_prot && (!bf_isaggr(bf) || (bf_isaggr(bf) && bf->bf_al < 8192))) { flags = ATH9K_TXDESC_RTSENA; - cix = rt->info[sc->sc_protrix].ctrl_rate; + cix = rt->info[enable_g_protection].ctrl_rate; rtsctsena = 1; } -- GitLab From ce111badf5ac387e9eefe1f2bba751f595994cb2 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 23 Dec 2008 15:58:39 -0800 Subject: [PATCH 0747/4982] ath9k: Rename ath_setcurmode() to ath_cache_conf_rate() ath_setcurmode() is a bit misleading, all we are doing is caching the rate for the corresponding configuration we are using. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index e26a9a6fbfc..0087a907aac 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -59,7 +59,8 @@ static void bus_read_cachesize(struct ath_softc *sc, int *csz) *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */ } -static void ath_setcurmode(struct ath_softc *sc, struct ieee80211_conf *conf) +static void ath_cache_conf_rate(struct ath_softc *sc, + struct ieee80211_conf *conf) { switch (conf->channel->band) { case IEEE80211_BAND_2GHZ: @@ -91,6 +92,7 @@ static void ath_setcurmode(struct ath_softc *sc, struct ieee80211_conf *conf) sc->hw_rate_table[ATH9K_MODE_11A]; break; default: + BUG_ON(1); break; } } @@ -316,7 +318,7 @@ static int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan) return -EIO; } - ath_setcurmode(sc, &hw->conf); + ath_cache_conf_rate(sc, &hw->conf); ath_update_txpow(sc); ath9k_hw_set_interrupts(ah, sc->sc_imask); } @@ -1647,7 +1649,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) * that changes the channel so update any state that * might change as a result. */ - ath_setcurmode(sc, &hw->conf); + ath_cache_conf_rate(sc, &hw->conf); ath_update_txpow(sc); @@ -1944,7 +1946,7 @@ static int ath9k_start(struct ieee80211_hw *hw) !sc->sc_config.swBeaconProcess) sc->sc_imask |= ATH9K_INT_TIM; - ath_setcurmode(sc, &hw->conf); + ath_cache_conf_rate(sc, &hw->conf); sc->sc_flags &= ~SC_OP_INVALID; -- GitLab From ae8d2858c54f52dc4df513a818cc4e1257fd9143 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 23 Dec 2008 15:58:40 -0800 Subject: [PATCH 0748/4982] ath9k: consolidate arguments on hw reset HW reset calls pass the same variables or structs which we can obtain easily from ah. Although this also applies during channel changes as we will keep around the ath9k_channel passed as an argument for now. We now also now propagate the hw reset errors down. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ath9k.h | 7 +- drivers/net/wireless/ath9k/hw.c | 68 +++++++----------- drivers/net/wireless/ath9k/main.c | 110 +++++++++++------------------ drivers/net/wireless/ath9k/xmit.c | 16 ++--- 4 files changed, 74 insertions(+), 127 deletions(-) diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index d2781350295..0f6a99a3f21 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -843,11 +843,8 @@ void ath9k_hw_rfdetach(struct ath_hal *ah); /* HW Reset */ -bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan, - enum ath9k_ht_macmode macmode, - u8 txchainmask, u8 rxchainmask, - enum ath9k_ht_extprotspacing extprotspacing, - bool bChannelChange, int *status); +int ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan, + bool bChannelChange); /* Key Cache Management */ diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 34474edefc9..46029ec1354 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -2222,23 +2222,20 @@ static void ath9k_hw_spur_mitigate(struct ath_hal *ah, struct ath9k_channel *cha REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); } -bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan, - enum ath9k_ht_macmode macmode, - u8 txchainmask, u8 rxchainmask, - enum ath9k_ht_extprotspacing extprotspacing, - bool bChannelChange, int *status) +int ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan, + bool bChannelChange) { u32 saveLedState; + struct ath_softc *sc = ah->ah_sc; struct ath_hal_5416 *ahp = AH5416(ah); struct ath9k_channel *curchan = ah->ah_curchan; u32 saveDefAntenna; u32 macStaId1; - int ecode; - int i, rx_chainmask; + int i, rx_chainmask, r; - ahp->ah_extprotspacing = extprotspacing; - ahp->ah_txchainmask = txchainmask; - ahp->ah_rxchainmask = rxchainmask; + ahp->ah_extprotspacing = sc->sc_ht_extprotspacing; + ahp->ah_txchainmask = sc->sc_tx_chainmask; + ahp->ah_rxchainmask = sc->sc_rx_chainmask; if (AR_SREV_9280(ah)) { ahp->ah_txchainmask &= 0x3; @@ -2249,14 +2246,11 @@ bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan, DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, "invalid channel %u/0x%x; no mapping\n", chan->channel, chan->channelFlags); - ecode = -EINVAL; - goto bad; + return -EINVAL; } - if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { - ecode = -EIO; - goto bad; - } + if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) + return -EIO; if (curchan) ath9k_hw_getnf(ah, curchan); @@ -2270,10 +2264,10 @@ bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan, (!AR_SREV_9280(ah) || (!IS_CHAN_A_5MHZ_SPACED(chan) && !IS_CHAN_A_5MHZ_SPACED(ah->ah_curchan)))) { - if (ath9k_hw_channel_change(ah, chan, macmode)) { + if (ath9k_hw_channel_change(ah, chan, sc->tx_chan_width)) { ath9k_hw_loadnf(ah, ah->ah_curchan); ath9k_hw_start_nfcal(ah); - return true; + return 0; } } @@ -2291,8 +2285,7 @@ bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan, if (!ath9k_hw_chip_reset(ah, chan)) { DPRINTF(ah->ah_sc, ATH_DBG_RESET, "chip reset failed\n"); - ecode = -EINVAL; - goto bad; + return -EINVAL; } if (AR_SREV_9280(ah)) { @@ -2308,11 +2301,9 @@ bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan, ath9k_hw_cfg_output(ah, 9, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); } - ecode = ath9k_hw_process_ini(ah, chan, macmode); - if (ecode != 0) { - ecode = -EINVAL; - goto bad; - } + r = ath9k_hw_process_ini(ah, chan, sc->tx_chan_width); + if (r) + return r; if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) ath9k_hw_set_delta_slope(ah, chan); @@ -2325,8 +2316,7 @@ bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan, if (!ath9k_hw_eeprom_set_board_values(ah, chan)) { DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "error setting board options\n"); - ecode = -EIO; - goto bad; + return -EIO; } ath9k_hw_decrease_chain_power(ah, chan); @@ -2354,15 +2344,11 @@ bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan, REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); if (AR_SREV_9280_10_OR_LATER(ah)) { - if (!(ath9k_hw_ar9280_set_channel(ah, chan))) { - ecode = -EIO; - goto bad; - } + if (!(ath9k_hw_ar9280_set_channel(ah, chan))) + return -EIO; } else { - if (!(ath9k_hw_set_channel(ah, chan))) { - ecode = -EIO; - goto bad; - } + if (!(ath9k_hw_set_channel(ah, chan))) + return -EIO; } for (i = 0; i < AR_NUM_DCU; i++) @@ -2396,10 +2382,8 @@ bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan, ath9k_hw_init_bb(ah, chan); - if (!ath9k_hw_init_cal(ah, chan)){ - ecode = -EIO;; - goto bad; - } + if (!ath9k_hw_init_cal(ah, chan)) + return -EIO;; rx_chainmask = ahp->ah_rxchainmask; if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) { @@ -2428,11 +2412,7 @@ bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan, #endif } - return true; -bad: - if (status) - *status = ecode; - return false; + return 0; } /************************/ diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 0087a907aac..c65b27bd9f5 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -260,6 +260,8 @@ static int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan) struct ath_hal *ah = sc->sc_ah; bool fastcc = true, stopped; struct ieee80211_hw *hw = sc->hw; + struct ieee80211_channel *channel = hw->conf.channel; + int r; if (sc->sc_flags & SC_OP_INVALID) return -EIO; @@ -268,7 +270,6 @@ static int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan) hchan->channelFlags != sc->sc_ah->ah_curchan->channelFlags || (sc->sc_flags & SC_OP_CHAINMASK_UPDATE) || (sc->sc_flags & SC_OP_FULL_RESET)) { - int status; /* * This is only performed if the channel settings have * actually changed. @@ -290,22 +291,20 @@ static int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan) fastcc = false; DPRINTF(sc, ATH_DBG_CONFIG, - "(%u MHz) -> (%u MHz), cflags:%x, chanwidth: %d\n", + "(%u MHz) -> (%u MHz), chanwidth: %d\n", sc->sc_ah->ah_curchan->channel, - hchan->channel, hchan->channelFlags, sc->tx_chan_width); + channel->center_freq, sc->tx_chan_width); spin_lock_bh(&sc->sc_resetlock); - if (!ath9k_hw_reset(ah, hchan, sc->tx_chan_width, - sc->sc_tx_chainmask, sc->sc_rx_chainmask, - sc->sc_ht_extprotspacing, fastcc, &status)) { + + r = ath9k_hw_reset(ah, hchan, fastcc); + if (r) { DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset channel %u (%uMhz) " - "flags 0x%x hal status %u\n", - ath9k_hw_mhz2ieee(ah, hchan->channel, - hchan->channelFlags), - hchan->channel, hchan->channelFlags, status); + "Unable to reset channel (%u Mhz) " + "reset status %u\n", + channel->center_freq, r); spin_unlock_bh(&sc->sc_resetlock); - return -EIO; + return r; } spin_unlock_bh(&sc->sc_resetlock); @@ -1069,23 +1068,18 @@ fail: static void ath_radio_enable(struct ath_softc *sc) { struct ath_hal *ah = sc->sc_ah; - int status; + struct ieee80211_channel *channel = sc->hw->conf.channel; + int r; spin_lock_bh(&sc->sc_resetlock); - if (!ath9k_hw_reset(ah, ah->ah_curchan, - sc->tx_chan_width, - sc->sc_tx_chainmask, - sc->sc_rx_chainmask, - sc->sc_ht_extprotspacing, - false, &status)) { + + r = ath9k_hw_reset(ah, ah->ah_curchan, false); + + if (r) { DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset channel %u (%uMhz) " - "flags 0x%x hal status %u\n", - ath9k_hw_mhz2ieee(ah, - ah->ah_curchan->channel, - ah->ah_curchan->channelFlags), - ah->ah_curchan->channel, - ah->ah_curchan->channelFlags, status); + "Unable to reset channel %u (%uMhz) ", + "reset status %u\n", + channel->center_freq, r); } spin_unlock_bh(&sc->sc_resetlock); @@ -1113,8 +1107,8 @@ static void ath_radio_enable(struct ath_softc *sc) static void ath_radio_disable(struct ath_softc *sc) { struct ath_hal *ah = sc->sc_ah; - int status; - + struct ieee80211_channel *channel = sc->hw->conf.channel; + int r; ieee80211_stop_queues(sc->hw); @@ -1130,20 +1124,12 @@ static void ath_radio_disable(struct ath_softc *sc) ath_flushrecv(sc); /* flush recv queue */ spin_lock_bh(&sc->sc_resetlock); - if (!ath9k_hw_reset(ah, ah->ah_curchan, - sc->tx_chan_width, - sc->sc_tx_chainmask, - sc->sc_rx_chainmask, - sc->sc_ht_extprotspacing, - false, &status)) { + r = ath9k_hw_reset(ah, ah->ah_curchan, false); + if (r) { DPRINTF(sc, ATH_DBG_FATAL, "Unable to reset channel %u (%uMhz) " - "flags 0x%x hal status %u\n", - ath9k_hw_mhz2ieee(ah, - ah->ah_curchan->channel, - ah->ah_curchan->channelFlags), - ah->ah_curchan->channel, - ah->ah_curchan->channelFlags, status); + "reset status %u\n", + channel->center_freq, r); } spin_unlock_bh(&sc->sc_resetlock); @@ -1622,8 +1608,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) { struct ath_hal *ah = sc->sc_ah; struct ieee80211_hw *hw = sc->hw; - int status; - int error = 0; + int r; ath9k_hw_set_interrupts(ah, 0); ath_draintxq(sc, retry_tx); @@ -1631,14 +1616,10 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) ath_flushrecv(sc); spin_lock_bh(&sc->sc_resetlock); - if (!ath9k_hw_reset(ah, sc->sc_ah->ah_curchan, - sc->tx_chan_width, - sc->sc_tx_chainmask, sc->sc_rx_chainmask, - sc->sc_ht_extprotspacing, false, &status)) { + r = ath9k_hw_reset(ah, sc->sc_ah->ah_curchan, false); + if (r) DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset hardware; hal status %u\n", status); - error = -EIO; - } + "Unable to reset hardware; reset status %u\n", r); spin_unlock_bh(&sc->sc_resetlock); if (ath_startrecv(sc) != 0) @@ -1669,7 +1650,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) } } - return error; + return r; } /* @@ -1852,7 +1833,7 @@ static int ath9k_start(struct ieee80211_hw *hw) struct ath_softc *sc = hw->priv; struct ieee80211_channel *curchan = hw->conf.channel; struct ath9k_channel *init_channel; - int error = 0, pos, status; + int r, pos; DPRINTF(sc, ATH_DBG_CONFIG, "Starting driver with " "initial channel: %d MHz\n", curchan->center_freq); @@ -1862,8 +1843,7 @@ static int ath9k_start(struct ieee80211_hw *hw) pos = ath_get_channel(sc, curchan); if (pos == -1) { DPRINTF(sc, ATH_DBG_FATAL, "Invalid channel: %d\n", curchan->center_freq); - error = -EINVAL; - goto error; + return -EINVAL; } sc->tx_chan_width = ATH9K_HT_MACMODE_20; @@ -1882,17 +1862,14 @@ static int ath9k_start(struct ieee80211_hw *hw) * and then setup of the interrupt mask. */ spin_lock_bh(&sc->sc_resetlock); - if (!ath9k_hw_reset(sc->sc_ah, init_channel, - sc->tx_chan_width, - sc->sc_tx_chainmask, sc->sc_rx_chainmask, - sc->sc_ht_extprotspacing, false, &status)) { + r = ath9k_hw_reset(sc->sc_ah, init_channel, false); + if (r) { DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset hardware; hal status %u " - "(freq %u flags 0x%x)\n", status, - init_channel->channel, init_channel->channelFlags); - error = -EIO; + "Unable to reset hardware; reset status %u " + "(freq %u MHz)\n", r, + curchan->center_freq); spin_unlock_bh(&sc->sc_resetlock); - goto error; + return r; } spin_unlock_bh(&sc->sc_resetlock); @@ -1912,8 +1889,7 @@ static int ath9k_start(struct ieee80211_hw *hw) if (ath_startrecv(sc) != 0) { DPRINTF(sc, ATH_DBG_FATAL, "Unable to start recv logic\n"); - error = -EIO; - goto error; + return -EIO; } /* Setup our intr mask. */ @@ -1957,11 +1933,9 @@ static int ath9k_start(struct ieee80211_hw *hw) ieee80211_wake_queues(sc->hw); #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) - error = ath_start_rfkill_poll(sc); + r = ath_start_rfkill_poll(sc); #endif - -error: - return error; + return r; } static int ath9k_tx(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 3e192fd9591..e28889bc0ac 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -1140,7 +1140,7 @@ static void ath_tx_stopdma(struct ath_softc *sc, struct ath_txq *txq) static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx) { struct ath_hal *ah = sc->sc_ah; - int i, status, npend = 0; + int i, npend = 0; if (!(sc->sc_flags & SC_OP_INVALID)) { for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { @@ -1155,20 +1155,16 @@ static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx) } if (npend) { + int r; /* TxDMA not stopped, reset the hal */ DPRINTF(sc, ATH_DBG_XMIT, "Unable to stop TxDMA. Reset HAL!\n"); spin_lock_bh(&sc->sc_resetlock); - if (!ath9k_hw_reset(ah, - sc->sc_ah->ah_curchan, - sc->tx_chan_width, - sc->sc_tx_chainmask, sc->sc_rx_chainmask, - sc->sc_ht_extprotspacing, true, &status)) { - + r = ath9k_hw_reset(ah, sc->sc_ah->ah_curchan, true); + if (r) DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset hardware; hal status %u\n", - status); - } + "Unable to reset hardware; reset status %u\n", + r); spin_unlock_bh(&sc->sc_resetlock); } -- GitLab From 76061abbbb39ba4bdf42fe28aa3157df8bb03d38 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 23 Dec 2008 15:58:41 -0800 Subject: [PATCH 0749/4982] ath9k: make request to get the noisefloor threshold band specific Lets make the request to get the current noise floor threshold from the EEPROM band specific as it is band specific, not mode specific. This also adds a backpointer on the private channel structure back to the ieee80211_channel structure as this is now needed during ath9k_hw_getnf(). Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ath9k.h | 1 + drivers/net/wireless/ath9k/calib.c | 21 +++++++-------------- drivers/net/wireless/ath9k/main.c | 2 ++ 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index 0f6a99a3f21..78fffdf9339 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -453,6 +453,7 @@ struct ath9k_11n_rate_series { CHANNEL_HT40MINUS) struct ath9k_channel { + struct ieee80211_channel *chan; u16 channel; u32 channelFlags; u8 privFlags; diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c index 3c7454fc51b..2a6b8a4d6e9 100644 --- a/drivers/net/wireless/ath9k/calib.c +++ b/drivers/net/wireless/ath9k/calib.c @@ -168,26 +168,18 @@ static void ath9k_hw_do_getnf(struct ath_hal *ah, } static bool getNoiseFloorThresh(struct ath_hal *ah, - const struct ath9k_channel *chan, + enum ieee80211_band band, int16_t *nft) { - switch (chan->chanmode) { - case CHANNEL_A: - case CHANNEL_A_HT20: - case CHANNEL_A_HT40PLUS: - case CHANNEL_A_HT40MINUS: + switch (band) { + case IEEE80211_BAND_5GHZ: *nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_5); break; - case CHANNEL_B: - case CHANNEL_G: - case CHANNEL_G_HT20: - case CHANNEL_G_HT40PLUS: - case CHANNEL_G_HT40MINUS: + case IEEE80211_BAND_2GHZ: *nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_2); break; default: - DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, - "invalid channel flags 0x%x\n", chan->channelFlags); + BUG_ON(1); return false; } @@ -692,6 +684,7 @@ int16_t ath9k_hw_getnf(struct ath_hal *ah, int16_t nf, nfThresh; int16_t nfarray[NUM_NF_READINGS] = { 0 }; struct ath9k_nfcal_hist *h; + struct ieee80211_channel *c = chan->chan; u8 chainmask; if (AR_SREV_9280(ah)) @@ -709,7 +702,7 @@ int16_t ath9k_hw_getnf(struct ath_hal *ah, } else { ath9k_hw_do_getnf(ah, nfarray); nf = nfarray[0]; - if (getNoiseFloorThresh(ah, chan, &nfThresh) + if (getNoiseFloorThresh(ah, c->band, &nfThresh) && nf > nfThresh) { DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "noise floor failed detected; " diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index c65b27bd9f5..12c5b9a4490 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -218,6 +218,7 @@ static int ath_setup_channels(struct ath_softc *sc) chan_2ghz[a].band = IEEE80211_BAND_2GHZ; chan_2ghz[a].center_freq = c->channel; chan_2ghz[a].max_power = c->maxTxPower; + c->chan = &chan_2ghz[a]; if (c->privFlags & CHANNEL_DISALLOW_ADHOC) chan_2ghz[a].flags |= IEEE80211_CHAN_NO_IBSS; @@ -233,6 +234,7 @@ static int ath_setup_channels(struct ath_softc *sc) chan_5ghz[b].band = IEEE80211_BAND_5GHZ; chan_5ghz[b].center_freq = c->channel; chan_5ghz[b].max_power = c->maxTxPower; + c->chan = &chan_5ghz[a]; if (c->privFlags & CHANNEL_DISALLOW_ADHOC) chan_5ghz[b].flags |= IEEE80211_CHAN_NO_IBSS; -- GitLab From c9e27d94f5fc726f88897914025619fbfc18b23c Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 23 Dec 2008 15:58:42 -0800 Subject: [PATCH 0750/4982] ath9k: use ieee80211_conf on ath9k_hw_iscal_supported() ath9k_hw_iscal_supported() just needs to be aware of your band and if HT20 is being used so lets abandon our internal channel, HT appended values and internal mode values and use ieee80211_conf which already carries this information. This works as calibration is being done for the currently configured channel. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ath9k.h | 3 +- drivers/net/wireless/ath9k/calib.c | 63 ++++++++++++------------------ drivers/net/wireless/ath9k/main.c | 3 +- 3 files changed, 27 insertions(+), 42 deletions(-) diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index 78fffdf9339..adcd34249a8 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -949,8 +949,7 @@ void ath9k_hw_ani_detach(struct ath_hal *ah); /* Calibration */ -void ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan, - bool *isCalDone); +bool ath9k_hw_reset_calvalid(struct ath_hal *ah); void ath9k_hw_start_nfcal(struct ath_hal *ah); void ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan); int16_t ath9k_hw_getnf(struct ath_hal *ah, diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c index 2a6b8a4d6e9..707289685b4 100644 --- a/drivers/net/wireless/ath9k/calib.c +++ b/drivers/net/wireless/ath9k/calib.c @@ -277,27 +277,24 @@ static void ath9k_hw_per_calibration(struct ath_hal *ah, } } +/* Assumes you are talking about the currently configured channel */ static bool ath9k_hw_iscal_supported(struct ath_hal *ah, - struct ath9k_channel *chan, enum hal_cal_types calType) { struct ath_hal_5416 *ahp = AH5416(ah); - bool retval = false; + struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; switch (calType & ahp->ah_suppCals) { - case IQ_MISMATCH_CAL: - if (!IS_CHAN_B(chan)) - retval = true; - break; + case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */ + return true; case ADC_GAIN_CAL: case ADC_DC_CAL: - if (!IS_CHAN_B(chan) - && !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan))) - retval = true; + if (conf->channel->band == IEEE80211_BAND_5GHZ && + conf_is_ht20(conf)) + return true; break; } - - return retval; + return false; } static void ath9k_hw_iqcal_collect(struct ath_hal *ah) @@ -565,50 +562,40 @@ static void ath9k_hw_adc_dccal_calibrate(struct ath_hal *ah, u8 numChains) AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE); } -void ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan, - bool *isCalDone) +/* This is done for the currently configured channel */ +bool ath9k_hw_reset_calvalid(struct ath_hal *ah) { struct ath_hal_5416 *ahp = AH5416(ah); - struct ath9k_channel *ichan = - ath9k_regd_check_channel(ah, chan); + struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; struct hal_cal_list *currCal = ahp->ah_cal_list_curr; - *isCalDone = true; + if (!ah->ah_curchan) + return true; if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah)) - return; + return true; if (currCal == NULL) - return; - - if (ichan == NULL) { - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "invalid channel %u/0x%x; no mapping\n", - chan->channel, chan->channelFlags); - return; - } - + return true; if (currCal->calState != CAL_DONE) { DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "Calibration state incorrect, %d\n", currCal->calState); - return; + return true; } - - if (!ath9k_hw_iscal_supported(ah, chan, currCal->calData->calType)) - return; + if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType)) + return true; DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Resetting Cal %d state for channel %u/0x%x\n", - currCal->calData->calType, chan->channel, - chan->channelFlags); + "Resetting Cal %d state for channel %u\n", + currCal->calData->calType, conf->channel->center_freq); - ichan->CalValid &= ~currCal->calData->calType; + ah->ah_curchan->CalValid &= ~currCal->calData->calType; currCal->calState = CAL_WAITING; - *isCalDone = false; + return false; } void ath9k_hw_start_nfcal(struct ath_hal *ah) @@ -933,19 +920,19 @@ bool ath9k_hw_init_cal(struct ath_hal *ah, ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = NULL; if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { - if (ath9k_hw_iscal_supported(ah, chan, ADC_GAIN_CAL)) { + if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) { INIT_CAL(&ahp->ah_adcGainCalData); INSERT_CAL(ahp, &ahp->ah_adcGainCalData); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "enabling ADC Gain Calibration.\n"); } - if (ath9k_hw_iscal_supported(ah, chan, ADC_DC_CAL)) { + if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) { INIT_CAL(&ahp->ah_adcDcCalData); INSERT_CAL(ahp, &ahp->ah_adcDcCalData); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "enabling ADC DC Calibration.\n"); } - if (ath9k_hw_iscal_supported(ah, chan, IQ_MISMATCH_CAL)) { + if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { INIT_CAL(&ahp->ah_iqCalData); INSERT_CAL(ahp, &ahp->ah_iqCalData); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 12c5b9a4490..7d9a263ea0a 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -372,8 +372,7 @@ static void ath_ani_calibrate(unsigned long data) } else { if ((timestamp - sc->sc_ani.sc_resetcal_timer) >= ATH_RESTART_CALINTERVAL) { - ath9k_hw_reset_calvalid(ah, ah->ah_curchan, - &sc->sc_ani.sc_caldone); + sc->sc_ani.sc_caldone = ath9k_hw_reset_calvalid(ah); if (sc->sc_ani.sc_caldone) sc->sc_ani.sc_resetcal_timer = timestamp; } -- GitLab From ecf70441a3d53dd96cb1b454060fe39f9c3db301 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 23 Dec 2008 15:58:43 -0800 Subject: [PATCH 0751/4982] ath9k: make use of conf_is_ht*() in the rest of the driver Use shiny new conf_is_ht*() helpers, we can later remove ht.enabled if desired. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 7 +++---- drivers/net/wireless/ath9k/rc.c | 4 ++-- drivers/net/wireless/ath9k/xmit.c | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 7d9a263ea0a..75660448553 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -2132,9 +2132,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) (curchan->band == IEEE80211_BAND_2GHZ) ? CHANNEL_G : CHANNEL_A; - if (conf->ht.enabled) { - if (conf->ht.channel_type == NL80211_CHAN_HT40PLUS || - conf->ht.channel_type == NL80211_CHAN_HT40MINUS) + if (conf_is_ht(conf)) { + if (conf_is_ht40(conf)) sc->tx_chan_width = ATH9K_HT_MACMODE_2040; sc->sc_ah->ah_channels[pos].chanmode = @@ -2142,7 +2141,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) conf->ht.channel_type); } - ath_update_chainmask(sc, conf->ht.enabled); + ath_update_chainmask(sc, conf_is_ht(conf)); if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) { DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel\n"); diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 1b71b934bb5..0686a7c9ced 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -875,7 +875,7 @@ static void ath_rc_ratefind(struct ath_softc *sc, * above conditions. */ if ((sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ) && - (sc->hw->conf.ht.enabled)) { + (conf_is_ht(&sc->hw->conf))) { u8 dot11rate = rate_table->info[rix].dot11rate; u8 phy = rate_table->info[rix].phy; if (i == 4 && @@ -1511,7 +1511,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, tx_info, &is_probe, false); /* Check if aggregation has to be enabled for this tid */ - if (hw->conf.ht.enabled) { + if (conf_is_ht(&hw->conf)) { if (ieee80211_is_data_qos(fc)) { u8 *qc, tid; struct ath_node *an; diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index e28889bc0ac..9e910f7a2f3 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -1690,7 +1690,7 @@ static int ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf, (sc->sc_flags & SC_OP_PREAMBLE_SHORT) ? (bf->bf_state.bf_type |= BUF_SHORT_PREAMBLE) : (bf->bf_state.bf_type &= ~BUF_SHORT_PREAMBLE); - (sc->hw->conf.ht.enabled && !is_pae(skb) && + (conf_is_ht(&sc->hw->conf) && !is_pae(skb) && (tx_info->flags & IEEE80211_TX_CTL_AMPDU)) ? (bf->bf_state.bf_type |= BUF_HT) : (bf->bf_state.bf_type &= ~BUF_HT); -- GitLab From de27e64e5eb72ff3edcaf5edce2f306ada1f094d Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 23 Dec 2008 15:58:44 -0800 Subject: [PATCH 0752/4982] iwlwifi: make use of conf_is_ht*() helpers Signed-off-by: Luis R. Rodriguez Acked-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-agn.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 75b418e5e87..d3ae04112c3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -1130,7 +1130,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, s32 rate; s8 is_green = lq_sta->is_green; - if (!conf->ht.enabled || !sta->ht_cap.ht_supported) + if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) return -1; if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2) @@ -1197,7 +1197,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv, u8 is_green = lq_sta->is_green; s32 rate; - if (!conf->ht.enabled || !sta->ht_cap.ht_supported) + if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) return -1; IWL_DEBUG_RATE("LQ: try to switch to SISO\n"); @@ -1997,7 +1997,7 @@ lq_update: * stay with best antenna legacy modulation for a while * before next round of mode comparisons. */ tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]); - if (is_legacy(tbl1->lq_type) && !conf->ht.enabled && + if (is_legacy(tbl1->lq_type) && !conf_is_ht(conf) && lq_sta->action_counter >= 1) { lq_sta->action_counter = 0; IWL_DEBUG_RATE("LQ: STAY in legacy table\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 1ef9f58fec8..f3f6dba7a67 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -522,9 +522,9 @@ static void iwl_ht_conf(struct iwl_priv *priv, */ iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; - if (priv->hw->conf.ht.channel_type == NL80211_CHAN_HT40MINUS) + if (conf_is_ht40_minus(&priv->hw->conf)) iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW; - else if(priv->hw->conf.ht.channel_type == NL80211_CHAN_HT40PLUS) + else if (conf_is_ht40_plus(&priv->hw->conf)) iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; /* If no above or below channel supplied disable FAT channel */ @@ -2546,7 +2546,7 @@ static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) mutex_lock(&priv->mutex); IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value); - priv->current_ht_config.is_ht = conf->ht.enabled; + priv->current_ht_config.is_ht = conf_is_ht(conf); if (conf->radio_enabled && iwl_radio_kill_sw_enable_radio(priv)) { IWL_DEBUG_MAC80211("leave - RF-KILL - waiting for uCode\n"); -- GitLab From 285256a59d790c6a9afe8ec82804a369d956ac06 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 23 Dec 2008 15:58:45 -0800 Subject: [PATCH 0753/4982] mac80211: no need for ht.enabled We can simply use conf_is_ht() check where needed. Signed-off-by: Luis R. Rodriguez Acked-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 1 - net/mac80211/ht.c | 3 +-- net/mac80211/main.c | 10 ---------- net/mac80211/mlme.c | 1 - 4 files changed, 1 insertion(+), 14 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 1e8db8ae615..9d67fdf1c26 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -508,7 +508,6 @@ static inline int __deprecated __IEEE80211_CONF_SHORT_SLOT_TIME(void) #define IEEE80211_CONF_SHORT_SLOT_TIME (__IEEE80211_CONF_SHORT_SLOT_TIME()) struct ieee80211_ht_conf { - bool enabled; enum nl80211_channel_type channel_type; }; diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index c5c0c527109..f6547de5ac6 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -130,11 +130,10 @@ u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, } } - ht_changed = local->hw.conf.ht.enabled != enable_ht || + ht_changed = conf_is_ht(&local->hw.conf) != enable_ht || channel_type != local->hw.conf.ht.channel_type; local->oper_channel_type = channel_type; - local->hw.conf.ht.enabled = enable_ht; if (ht_changed) ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 24b14363d6e..a6cb480dda0 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -211,16 +211,6 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) channel_type != local->hw.conf.ht.channel_type) { local->hw.conf.channel = chan; local->hw.conf.ht.channel_type = channel_type; - switch (channel_type) { - case NL80211_CHAN_NO_HT: - local->hw.conf.ht.enabled = false; - break; - case NL80211_CHAN_HT20: - case NL80211_CHAN_HT40MINUS: - case NL80211_CHAN_HT40PLUS: - local->hw.conf.ht.enabled = true; - break; - } changed |= IEEE80211_CONF_CHANGE_CHANNEL; } diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 599a42172a1..12976026cc4 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -901,7 +901,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, rcu_read_unlock(); - local->hw.conf.ht.enabled = false; local->oper_channel_type = NL80211_CHAN_NO_HT; config_changed |= IEEE80211_CONF_CHANGE_HT; -- GitLab From 38b33707a1ec77f7b4c92ae41cfe93318014f5bf Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 23 Dec 2008 15:58:46 -0800 Subject: [PATCH 0754/4982] ath9k: Make ANI CCK and OFDM error triggers band specific The CCK and OFDM ANI error triggers are not mode specific but rather band specific so just make use of the already available band from ieee80211_conf. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ani.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath9k/ani.c b/drivers/net/wireless/ath9k/ani.c index 251e2d9a7a4..4dd086073ad 100644 --- a/drivers/net/wireless/ath9k/ani.c +++ b/drivers/net/wireless/ath9k/ani.c @@ -279,9 +279,8 @@ static void ath9k_ani_restart(struct ath_hal *ah) static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hal *ah) { struct ath_hal_5416 *ahp = AH5416(ah); - struct ath9k_channel *chan = ah->ah_curchan; + struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; struct ar5416AniState *aniState; - enum wireless_mode mode; int32_t rssi; if (!DO_ANI(ah)) @@ -336,8 +335,7 @@ static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hal *ah) aniState->firstepLevel + 1); return; } else { - mode = ath9k_hw_chan2wmode(ah, chan); - if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) { + if (conf->channel->band == IEEE80211_BAND_2GHZ) { if (!aniState->ofdmWeakSigDetectOff) ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, @@ -353,9 +351,8 @@ static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hal *ah) static void ath9k_hw_ani_cck_err_trigger(struct ath_hal *ah) { struct ath_hal_5416 *ahp = AH5416(ah); - struct ath9k_channel *chan = ah->ah_curchan; + struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; struct ar5416AniState *aniState; - enum wireless_mode mode; int32_t rssi; if (!DO_ANI(ah)) @@ -381,8 +378,7 @@ static void ath9k_hw_ani_cck_err_trigger(struct ath_hal *ah) ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, aniState->firstepLevel + 1); } else { - mode = ath9k_hw_chan2wmode(ah, chan); - if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) { + if (conf->channel->band == IEEE80211_BAND_2GHZ) { if (aniState->firstepLevel > 0) ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0); -- GitLab From e56db718468416ce5ff1ba05e7fa5026424befd5 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 23 Dec 2008 15:58:47 -0800 Subject: [PATCH 0755/4982] ath9k: remove mode specific default noise floor values The NOISE_FLOOR array we have is mode specific, and the only possible indexed values are A, B and G. The mode routine only can return G or A, so this is band specific. Then since the values for A and G (5ghz or 2ghz) are the same (-96) we simply remove the array and use a static value. If we later determine we want to use special values for HT configurations we can use the new mac80211 conf_is_ht*() helpers. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/calib.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c index 707289685b4..8e073d6513d 100644 --- a/drivers/net/wireless/ath9k/calib.c +++ b/drivers/net/wireless/ath9k/calib.c @@ -19,8 +19,6 @@ #include "reg.h" #include "phy.h" -static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93, -96 }; - /* We can tune this as we go by monitoring really low values */ #define ATH9K_NF_TOO_LOW -60 @@ -740,10 +738,9 @@ s16 ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan) chan->channel, chan->channelFlags); return ATH_DEFAULT_NOISE_FLOOR; } - if (ichan->rawNoiseFloor == 0) { - enum wireless_mode mode = ath9k_hw_chan2wmode(ah, chan); - nf = NOISE_FLOOR[mode]; - } else + if (ichan->rawNoiseFloor == 0) + nf = -96; + else nf = ichan->rawNoiseFloor; if (!ath9k_hw_nf_in_range(ah, nf)) -- GitLab From 4febf7b8f4f2c7052cffbccba9e5ddf041b41330 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 23 Dec 2008 15:58:48 -0800 Subject: [PATCH 0756/4982] ath9k: remove ath9k_hw_chan2wmode() The only left users are for timing for ACK timeout, slotime and CTS timeout. We currently use an array CLOCK_RATE to keep these values per mode and since as only will use A and G we can depend on the band to get the appropriate values. We note that we should be using a different clock rate value for CCK, we can do this in separate patch, currently this is being disregarded and should only affect when we want to change the default ACK/CTS timeout or slot time and stuck with using using 802.11b. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/hw.c | 46 ++++++++++++++------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 46029ec1354..08b9a0d421b 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -23,7 +23,9 @@ #include "phy.h" #include "initvals.h" -static const u8 CLOCK_RATE[] = { 40, 80, 22, 44, 88, 40 }; +#define ATH9K_CLOCK_RATE_CCK 22 +#define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 +#define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 extern struct hal_percal_data iq_cal_multi_sample; extern struct hal_percal_data iq_cal_single_sample; @@ -48,17 +50,18 @@ static void ath9k_hw_spur_mitigate(struct ath_hal *ah, struct ath9k_channel *cha static u32 ath9k_hw_mac_usec(struct ath_hal *ah, u32 clks) { - if (ah->ah_curchan != NULL) - return clks / CLOCK_RATE[ath9k_hw_chan2wmode(ah, ah->ah_curchan)]; - else - return clks / CLOCK_RATE[ATH9K_MODE_11B]; + struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; + if (!ah->ah_curchan) /* should really check for CCK instead */ + return clks / ATH9K_CLOCK_RATE_CCK; + if (conf->channel->band == IEEE80211_BAND_2GHZ) + return clks / ATH9K_CLOCK_RATE_2GHZ_OFDM; + return clks / ATH9K_CLOCK_RATE_5GHZ_OFDM; } static u32 ath9k_hw_mac_to_usec(struct ath_hal *ah, u32 clks) { - struct ath9k_channel *chan = ah->ah_curchan; - - if (chan && IS_CHAN_HT40(chan)) + struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; + if (conf_is_ht40(conf)) return ath9k_hw_mac_usec(ah, clks) / 2; else return ath9k_hw_mac_usec(ah, clks); @@ -66,34 +69,23 @@ static u32 ath9k_hw_mac_to_usec(struct ath_hal *ah, u32 clks) static u32 ath9k_hw_mac_clks(struct ath_hal *ah, u32 usecs) { - if (ah->ah_curchan != NULL) - return usecs * CLOCK_RATE[ath9k_hw_chan2wmode(ah, - ah->ah_curchan)]; - else - return usecs * CLOCK_RATE[ATH9K_MODE_11B]; + struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; + if (!ah->ah_curchan) /* should really check for CCK instead */ + return usecs *ATH9K_CLOCK_RATE_CCK; + if (conf->channel->band == IEEE80211_BAND_2GHZ) + return usecs *ATH9K_CLOCK_RATE_2GHZ_OFDM; + return usecs *ATH9K_CLOCK_RATE_5GHZ_OFDM; } static u32 ath9k_hw_mac_to_clks(struct ath_hal *ah, u32 usecs) { - struct ath9k_channel *chan = ah->ah_curchan; - - if (chan && IS_CHAN_HT40(chan)) + struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; + if (conf_is_ht40(conf)) return ath9k_hw_mac_clks(ah, usecs) * 2; else return ath9k_hw_mac_clks(ah, usecs); } -enum wireless_mode ath9k_hw_chan2wmode(struct ath_hal *ah, - const struct ath9k_channel *chan) -{ - if (IS_CHAN_B(chan)) - return ATH9K_MODE_11B; - if (IS_CHAN_G(chan)) - return ATH9K_MODE_11G; - - return ATH9K_MODE_11A; -} - bool ath9k_hw_wait(struct ath_hal *ah, u32 reg, u32 mask, u32 val) { int i; -- GitLab From 0de57d991b82eb64b7a0f4cf406251713ee633cf Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 23 Dec 2008 15:58:49 -0800 Subject: [PATCH 0757/4982] ath9k: remove ath9k_hw_check_chan() The only check we care about in ath9k_hw_check_chan() is the internal regulatory check so use that. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/hw.c | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 08b9a0d421b..1d44aa8e511 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -1666,30 +1666,6 @@ static bool ath9k_hw_chip_reset(struct ath_hal *ah, return true; } -static struct ath9k_channel *ath9k_hw_check_chan(struct ath_hal *ah, - struct ath9k_channel *chan) -{ - if (!(IS_CHAN_2GHZ(chan) ^ IS_CHAN_5GHZ(chan))) { - DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, - "invalid channel %u/0x%x; not marked as " - "2GHz or 5GHz\n", chan->channel, chan->channelFlags); - return NULL; - } - - if (!IS_CHAN_OFDM(chan) && - !IS_CHAN_B(chan) && - !IS_CHAN_HT20(chan) && - !IS_CHAN_HT40(chan)) { - DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, - "invalid channel %u/0x%x; not marked as " - "OFDM or CCK or HT20 or HT40PLUS or HT40MINUS\n", - chan->channel, chan->channelFlags); - return NULL; - } - - return ath9k_regd_check_channel(ah, chan); -} - static bool ath9k_hw_channel_change(struct ath_hal *ah, struct ath9k_channel *chan, enum ath9k_ht_macmode macmode) @@ -2234,7 +2210,7 @@ int ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan, ahp->ah_rxchainmask &= 0x3; } - if (ath9k_hw_check_chan(ah, chan) == NULL) { + if (ath9k_regd_check_channel(ah, chan) == NULL) { DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, "invalid channel %u/0x%x; no mapping\n", chan->channel, chan->channelFlags); -- GitLab From c0d7c7af0a8298a43449d54762e655ab57739539 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 23 Dec 2008 15:58:50 -0800 Subject: [PATCH 0758/4982] ath9k: remove superfluous check on changing channel When we try to change the channel in ath9k its because either the configuration indicates we *have* changed channels or HT configuration has changed. In both cases we want to do a reset. Either way mac80211 will inform us when we want to actually change the channel so trust those calls. Although in the patch it may seem as I am doing more code changes I am not, all I am doing is removing the initial branch conditional and shifting the code to the left. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 87 +++++++++++++++---------------- 1 file changed, 41 insertions(+), 46 deletions(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 75660448553..5cbda924556 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -268,61 +268,56 @@ static int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan) if (sc->sc_flags & SC_OP_INVALID) return -EIO; - if (hchan->channel != sc->sc_ah->ah_curchan->channel || - hchan->channelFlags != sc->sc_ah->ah_curchan->channelFlags || - (sc->sc_flags & SC_OP_CHAINMASK_UPDATE) || - (sc->sc_flags & SC_OP_FULL_RESET)) { - /* - * This is only performed if the channel settings have - * actually changed. - * - * To switch channels clear any pending DMA operations; - * wait long enough for the RX fifo to drain, reset the - * hardware at the new frequency, and then re-enable - * the relevant bits of the h/w. - */ - ath9k_hw_set_interrupts(ah, 0); - ath_draintxq(sc, false); - stopped = ath_stoprecv(sc); + /* + * This is only performed if the channel settings have + * actually changed. + * + * To switch channels clear any pending DMA operations; + * wait long enough for the RX fifo to drain, reset the + * hardware at the new frequency, and then re-enable + * the relevant bits of the h/w. + */ + ath9k_hw_set_interrupts(ah, 0); + ath_draintxq(sc, false); + stopped = ath_stoprecv(sc); - /* XXX: do not flush receive queue here. We don't want - * to flush data frames already in queue because of - * changing channel. */ + /* XXX: do not flush receive queue here. We don't want + * to flush data frames already in queue because of + * changing channel. */ - if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET)) - fastcc = false; + if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET)) + fastcc = false; - DPRINTF(sc, ATH_DBG_CONFIG, - "(%u MHz) -> (%u MHz), chanwidth: %d\n", - sc->sc_ah->ah_curchan->channel, - channel->center_freq, sc->tx_chan_width); + DPRINTF(sc, ATH_DBG_CONFIG, + "(%u MHz) -> (%u MHz), chanwidth: %d\n", + sc->sc_ah->ah_curchan->channel, + channel->center_freq, sc->tx_chan_width); - spin_lock_bh(&sc->sc_resetlock); + spin_lock_bh(&sc->sc_resetlock); - r = ath9k_hw_reset(ah, hchan, fastcc); - if (r) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset channel (%u Mhz) " - "reset status %u\n", - channel->center_freq, r); - spin_unlock_bh(&sc->sc_resetlock); - return r; - } + r = ath9k_hw_reset(ah, hchan, fastcc); + if (r) { + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to reset channel (%u Mhz) " + "reset status %u\n", + channel->center_freq, r); spin_unlock_bh(&sc->sc_resetlock); + return r; + } + spin_unlock_bh(&sc->sc_resetlock); - sc->sc_flags &= ~SC_OP_CHAINMASK_UPDATE; - sc->sc_flags &= ~SC_OP_FULL_RESET; - - if (ath_startrecv(sc) != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to restart recv logic\n"); - return -EIO; - } + sc->sc_flags &= ~SC_OP_CHAINMASK_UPDATE; + sc->sc_flags &= ~SC_OP_FULL_RESET; - ath_cache_conf_rate(sc, &hw->conf); - ath_update_txpow(sc); - ath9k_hw_set_interrupts(ah, sc->sc_imask); + if (ath_startrecv(sc) != 0) { + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to restart recv logic\n"); + return -EIO; } + + ath_cache_conf_rate(sc, &hw->conf); + ath_update_txpow(sc); + ath9k_hw_set_interrupts(ah, sc->sc_imask); return 0; } -- GitLab From a085ff718c8c9f14c44feb337774fadfd982e1a5 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 23 Dec 2008 15:58:51 -0800 Subject: [PATCH 0759/4982] ath9k: fix sparse warnings Fix sparse warnings: drivers/net/wireless/ath9k/hw.c:1850:17: warning: symbol 'tmp' shadows an earlier one drivers/net/wireless/ath9k/hw.c:1713:6: originally declared here drivers/net/wireless/ath9k/hw.c:2051:17: warning: symbol 'tmp' shadows an earlier one drivers/net/wireless/ath9k/hw.c:1961:6: originally declared here drivers/net/wireless/ath9k/eeprom.c:195:6: warning: symbol 'ath9k_fill_eeprom' was not declared. Should it be static? drivers/net/wireless/ath9k/eeprom.c:463:5: warning: symbol 'ath9k_check_eeprom' was not declared. Should it be static? drivers/net/wireless/ath9k/eeprom.c:1219:6: warning: symbol 'ath9k_hw_set_def_power_per_rate_table' was not declared. Should it be static? drivers/net/wireless/ath9k/eeprom.c:1510:6: warning: symbol 'ath9k_hw_set_4k_power_per_rate_table' was not declared. Should it be static? drivers/net/wireless/ath9k/eeprom.c:2007:5: warning: symbol 'ath9k_set_txpower' was not declared. Should it be static? drivers/net/wireless/ath9k/eeprom.c:2106:6: warning: symbol 'ath9k_set_addac' was not declared. Should it be static? drivers/net/wireless/ath9k/eeprom.c:2543:6: warning: symbol 'ath9k_eeprom_set_board_values' was not declared. Should it be static? drivers/net/wireless/ath9k/eeprom.c:2606:5: warning: symbol 'ath9k_get_eeprom_antenna_cfg' was not declared. Should it be static? drivers/net/wireless/ath9k/eeprom.c:2622:4: warning: symbol 'ath9k_hw_get_4k_num_ant_config' was not declared. Should it be static? drivers/net/wireless/ath9k/eeprom.c:2628:4: warning: symbol 'ath9k_hw_get_def_num_ant_config' was not declared. Should it be static? drivers/net/wireless/ath9k/eeprom.c:2647:4: warning: symbol 'ath9k_get_num_ant_config' was not declared. Should it be static? drivers/net/wireless/ath9k/eeprom.c:2790:5: warning: symbol 'ath9k_get_eeprom' was not declared. Should it be static? drivers/net/wireless/ath9k/calib.c:962:30: warning: symbol 'iq_cal_multi_sample' was not declared. Should it be static? drivers/net/wireless/ath9k/calib.c:969:30: warning: symbol 'iq_cal_single_sample' was not declared. Should it be static? drivers/net/wireless/ath9k/calib.c:976:30: warning: symbol 'adc_gain_cal_multi_sample' was not declared. Should it be static? drivers/net/wireless/ath9k/calib.c:983:30: warning: symbol 'adc_gain_cal_single_sample' was not declared. Should it be static? drivers/net/wireless/ath9k/calib.c:990:30: warning: symbol 'adc_dc_cal_multi_sample' was not declared. Should it be static? drivers/net/wireless/ath9k/calib.c:997:30: warning: symbol 'adc_dc_cal_single_sample' was not declared. Should it be static? drivers/net/wireless/ath9k/calib.c:1004:30: warning: symbol 'adc_init_dc_cal' was not declared. Should it be static? Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/hw.c | 16 ++++------------ drivers/net/wireless/ath9k/hw.h | 8 ++++++++ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 1d44aa8e511..a7f44e5b2e8 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -27,14 +27,6 @@ #define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 #define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 -extern struct hal_percal_data iq_cal_multi_sample; -extern struct hal_percal_data iq_cal_single_sample; -extern struct hal_percal_data adc_gain_cal_multi_sample; -extern struct hal_percal_data adc_gain_cal_single_sample; -extern struct hal_percal_data adc_dc_cal_multi_sample; -extern struct hal_percal_data adc_dc_cal_single_sample; -extern struct hal_percal_data adc_init_dc_cal; - static bool ath9k_hw_set_reset_reg(struct ath_hal *ah, u32 type); static void ath9k_hw_set_regs(struct ath_hal *ah, struct ath9k_channel *chan, enum ath9k_ht_macmode macmode); @@ -1886,9 +1878,9 @@ static void ath9k_hw_9280_spur_mitigate(struct ath_hal *ah, struct ath9k_channel if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { /* workaround for gcc bug #37014 */ - volatile int tmp = abs(cur_vit_mask - bin); + volatile int tmp_v = abs(cur_vit_mask - bin); - if (tmp < 75) + if (tmp_v < 75) mask_amt = 1; else mask_amt = 0; @@ -2087,9 +2079,9 @@ static void ath9k_hw_spur_mitigate(struct ath_hal *ah, struct ath9k_channel *cha if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { /* workaround for gcc bug #37014 */ - volatile int tmp = abs(cur_vit_mask - bin); + volatile int tmp_v = abs(cur_vit_mask - bin); - if (tmp < 75) + if (tmp_v < 75) mask_amt = 1; else mask_amt = 0; diff --git a/drivers/net/wireless/ath9k/hw.h b/drivers/net/wireless/ath9k/hw.h index 91d8f594af8..3ae3b881deb 100644 --- a/drivers/net/wireless/ath9k/hw.h +++ b/drivers/net/wireless/ath9k/hw.h @@ -20,6 +20,14 @@ #include #include +extern const struct hal_percal_data iq_cal_multi_sample; +extern const struct hal_percal_data iq_cal_single_sample; +extern const struct hal_percal_data adc_gain_cal_multi_sample; +extern const struct hal_percal_data adc_gain_cal_single_sample; +extern const struct hal_percal_data adc_dc_cal_multi_sample; +extern const struct hal_percal_data adc_dc_cal_single_sample; +extern const struct hal_percal_data adc_init_dc_cal; + struct ar5416_desc { u32 ds_link; u32 ds_data; -- GitLab From e3c92df08cbf6a0cb60a9c7ce377378383967e07 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Wed, 24 Dec 2008 13:53:11 +0530 Subject: [PATCH 0760/4982] mac80211: Fix tx power setting power_level in ieee80211_conf is being used for more than one purpose. It being used as user configured power limit and the final power limit given to the driver. By doing so, except very first time, the tx power limit is taken from min(chan->max_power, local->hw.conf.power_level) which is not what we want. This patch defines a new memeber in ieee80211_conf which is meant only for user configured power limit. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- include/net/mac80211.h | 2 ++ net/mac80211/main.c | 4 ++-- net/mac80211/wext.c | 5 ++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 9d67fdf1c26..ffcbd12775a 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -546,6 +546,7 @@ enum ieee80211_conf_changed { * @listen_interval: listen interval in units of beacon interval * @flags: configuration flags defined above * @power_level: requested transmit power (in dBm) + * @user_power_level: User configured transmit power (in dBm) * @channel: the channel to tune to * @ht: the HT configuration for the device * @long_frame_max_tx_count: Maximum number of transmissions for a "long" frame @@ -559,6 +560,7 @@ struct ieee80211_conf { int beacon_int; u32 flags; int power_level; + int user_power_level; u16 listen_interval; bool radio_enabled; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index a6cb480dda0..dca4b7da6ca 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -214,10 +214,10 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) changed |= IEEE80211_CONF_CHANGE_CHANNEL; } - if (!local->hw.conf.power_level) + if (!local->hw.conf.user_power_level) power = chan->max_power; else - power = min(chan->max_power, local->hw.conf.power_level); + power = min(chan->max_power, local->hw.conf.user_power_level); if (local->hw.conf.power_level != power) { changed |= IEEE80211_CONF_CHANGE_POWER; local->hw.conf.power_level = power; diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 48fc6b9a62a..654041b9373 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -549,10 +549,9 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev, else /* Automatic power level setting */ new_power_level = chan->max_power; - if (local->hw.conf.power_level != new_power_level) { - local->hw.conf.power_level = new_power_level; + local->hw.conf.user_power_level = new_power_level; + if (local->hw.conf.power_level != new_power_level) reconf_flags |= IEEE80211_CONF_CHANGE_POWER; - } if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) { local->hw.conf.radio_enabled = !(data->txpower.disabled); -- GitLab From 92d6128e1766bb7a7b6dc58f012fdf772fdf1100 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 24 Dec 2008 12:44:09 +0100 Subject: [PATCH 0761/4982] ssb/b43: add new N PHY device This is used on my macbook. N PHY, obviously nothing works yet, but we can detect the chip with this patch. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 1 + drivers/ssb/b43_pci_bridge.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index ba989ae132a..a2b1e375f83 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -97,6 +97,7 @@ static const struct ssb_device_id b43_ssb_tbl[] = { SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 10), SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 11), SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 13), + SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 16), SSB_DEVTABLE_END }; diff --git a/drivers/ssb/b43_pci_bridge.c b/drivers/ssb/b43_pci_bridge.c index 2d27d6d6d08..6433a7ed39f 100644 --- a/drivers/ssb/b43_pci_bridge.c +++ b/drivers/ssb/b43_pci_bridge.c @@ -29,6 +29,7 @@ static const struct pci_device_id b43_pci_bridge_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4325) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4328) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4329) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432b) }, { 0, }, }; MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl); -- GitLab From cb33c4126ba9825b047463352d12dc3ed983d320 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Wed, 24 Dec 2008 18:03:58 +0530 Subject: [PATCH 0762/4982] ath9k: INI update for Atheros AR9280 and AR9285 chipset. Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/eeprom.c | 36 +- drivers/net/wireless/ath9k/hw.c | 21 +- drivers/net/wireless/ath9k/hw.h | 12 +- drivers/net/wireless/ath9k/initvals.h | 563 +++++++++++++------------- drivers/net/wireless/ath9k/reg.h | 7 + 5 files changed, 337 insertions(+), 302 deletions(-) diff --git a/drivers/net/wireless/ath9k/eeprom.c b/drivers/net/wireless/ath9k/eeprom.c index acd6c5374d4..1ef8b5a70e5 100644 --- a/drivers/net/wireless/ath9k/eeprom.c +++ b/drivers/net/wireless/ath9k/eeprom.c @@ -2121,6 +2121,7 @@ void ath9k_hw_set_addac(struct ath_hal *ah, struct ath9k_channel *chan) static bool ath9k_hw_eeprom_set_def_board_values(struct ath_hal *ah, struct ath9k_channel *chan) { +#define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) struct modal_eep_header *pModal; struct ath_hal_5416 *ahp = AH5416(ah); struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def; @@ -2163,9 +2164,7 @@ static bool ath9k_hw_eeprom_set_def_board_values(struct ath_hal *ah, AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) { - if ((eep->baseEepHeader.version & - AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_3) { + if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { txRxAttenLocal = pModal->txRxAttenCh[i]; if (AR_SREV_9280_10_OR_LATER(ah)) { REG_RMW_FIELD(ah, @@ -2332,8 +2331,7 @@ static bool ath9k_hw_eeprom_set_def_board_values(struct ath_hal *ah, pModal->thresh62); } - if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_2) { + if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) { REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START, pModal->txFrameToDataStart); @@ -2341,15 +2339,29 @@ static bool ath9k_hw_eeprom_set_def_board_values(struct ath_hal *ah, pModal->txFrameToPaOn); } - if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_3) { + if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { if (IS_CHAN_HT40(chan)) REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40); } + if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) { + if (IS_CHAN_HT20(chan)) + REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, + eep->baseEepHeader.dacLpMode); + else if (eep->baseEepHeader.dacHiPwrMode_5G) + REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0); + else + REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, + eep->baseEepHeader.dacLpMode); + + REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP, + pModal->miscBits >> 2); + } + return true; +#undef AR5416_VER_MASK } static bool ath9k_hw_eeprom_set_4k_board_values(struct ath_hal *ah, @@ -2739,6 +2751,7 @@ static u32 ath9k_hw_get_eeprom_4k(struct ath_hal *ah, static u32 ath9k_hw_get_eeprom_def(struct ath_hal *ah, enum eeprom_param param) { +#define AR5416_VER_MASK (pBase->version & AR5416_EEP_VER_MINOR_MASK) struct ath_hal_5416 *ahp = AH5416(ah); struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def; struct modal_eep_header *pModal = eep->modalHeader; @@ -2774,7 +2787,7 @@ static u32 ath9k_hw_get_eeprom_def(struct ath_hal *ah, case EEP_DB_2: return pModal[1].db; case EEP_MINOR_REV: - return pBase->version & AR5416_EEP_VER_MINOR_MASK; + return AR5416_VER_MASK; case EEP_TX_MASK: return pBase->txMask; case EEP_RX_MASK: @@ -2783,10 +2796,15 @@ static u32 ath9k_hw_get_eeprom_def(struct ath_hal *ah, return pBase->rxGainType; case EEP_TXGAIN_TYPE: return pBase->txGainType; - + case EEP_DAC_HPWR_5G: + if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) + return pBase->dacHiPwrMode_5G; + else + return 0; default: return 0; } +#undef AR5416_VER_MASK } static u32 (*ath9k_get_eeprom[])(struct ath_hal *, enum eeprom_param) = { diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index a7f44e5b2e8..19144caa797 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -3272,7 +3272,9 @@ bool ath9k_hw_fill_cap_info(struct ath_hal *ah) pCap->num_mr_retries = 4; pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD; - if (AR_SREV_9280_10_OR_LATER(ah)) + if (AR_SREV_9285_10_OR_LATER(ah)) + pCap->num_gpio_pins = AR9285_NUM_GPIO; + else if (AR_SREV_9280_10_OR_LATER(ah)) pCap->num_gpio_pins = AR928X_NUM_GPIO; else pCap->num_gpio_pins = AR_NUM_GPIO; @@ -3517,17 +3519,18 @@ void ath9k_hw_cfg_gpio_input(struct ath_hal *ah, u32 gpio) u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio) { +#define MS_REG_READ(x, y) \ + (MS(REG_READ(ah, AR_GPIO_IN_OUT), x##_GPIO_IN_VAL) & (AR_GPIO_BIT(y))) + if (gpio >= ah->ah_caps.num_gpio_pins) return 0xffffffff; - if (AR_SREV_9280_10_OR_LATER(ah)) { - return (MS - (REG_READ(ah, AR_GPIO_IN_OUT), - AR928X_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) != 0; - } else { - return (MS(REG_READ(ah, AR_GPIO_IN_OUT), AR_GPIO_IN_VAL) & - AR_GPIO_BIT(gpio)) != 0; - } + if (AR_SREV_9285_10_OR_LATER(ah)) + return MS_REG_READ(AR9285, gpio) != 0; + else if (AR_SREV_9280_10_OR_LATER(ah)) + return MS_REG_READ(AR928X, gpio) != 0; + else + return MS_REG_READ(AR, gpio) != 0; } void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio, diff --git a/drivers/net/wireless/ath9k/hw.h b/drivers/net/wireless/ath9k/hw.h index 3ae3b881deb..d44e016f988 100644 --- a/drivers/net/wireless/ath9k/hw.h +++ b/drivers/net/wireless/ath9k/hw.h @@ -426,6 +426,7 @@ struct ar5416Stats { #define AR5416_EEP_MINOR_VER_16 0x10 #define AR5416_EEP_MINOR_VER_17 0x11 #define AR5416_EEP_MINOR_VER_19 0x13 +#define AR5416_EEP_MINOR_VER_20 0x14 #define AR5416_NUM_5G_CAL_PIERS 8 #define AR5416_NUM_2G_CAL_PIERS 4 @@ -488,6 +489,7 @@ enum eeprom_param { EEP_RX_MASK, EEP_RXGAIN_TYPE, EEP_TXGAIN_TYPE, + EEP_DAC_HPWR_5G, }; enum ar5416_rates { @@ -526,9 +528,13 @@ struct base_eep_header { u8 pwdclkind; u8 futureBase_1[2]; u8 rxGainType; - u8 futureBase_2[3]; + u8 dacHiPwrMode_5G; + u8 futureBase_2; + u8 dacLpMode; u8 txGainType; - u8 futureBase_3[25]; + u8 rcChainMask; + u8 desiredScaleCCK; + u8 futureBase_3[23]; } __packed; struct base_eep_header_4k { @@ -595,7 +601,7 @@ struct modal_eep_header { force_xpaon:1, local_bias:1, femBandSelectUsed:1, xlnabufin:1, xlnaisel:2, xlnabufmode:1; - u8 futureModalar9280; + u8 miscBits; u16 xpaBiasLvlFreq[3]; u8 futureModal[6]; diff --git a/drivers/net/wireless/ath9k/initvals.h b/drivers/net/wireless/ath9k/initvals.h index f3cfa16525e..a1bc6312dcc 100644 --- a/drivers/net/wireless/ath9k/initvals.h +++ b/drivers/net/wireless/ath9k/initvals.h @@ -14,7 +14,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* AR5416 to Fowl ar5146.ini */ static const u32 ar5416Modes_9100[][6] = { { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, @@ -662,7 +661,6 @@ static const u32 ar5416Addac_9100[][2] = { {0x000098c4, 0x00000000 }, }; -/* ar5416 - howl ar5416_howl.ini */ static const u32 ar5416Modes[][6] = { { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, @@ -1313,7 +1311,6 @@ static const u32 ar5416Addac[][2] = { {0x000098cc, 0x00000000 }, }; -/* AR5416 9160 Sowl ar5416_sowl.ini */ static const u32 ar5416Modes_9160[][6] = { { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, @@ -2549,6 +2546,8 @@ static const u32 ar9280Modes_9280_2[][6] = { { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, + { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 }, + { 0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a }, { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, @@ -2587,7 +2586,6 @@ static const u32 ar9280Modes_9280_2[][6] = { { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, { 0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000 }, - { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, { 0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000 }, @@ -2719,7 +2717,6 @@ static const u32 ar9280Common_9280_2[][2] = { { 0x00008110, 0x00000168 }, { 0x00008118, 0x000100aa }, { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04800 }, { 0x00008124, 0x00000000 }, { 0x00008128, 0x00000000 }, { 0x0000812c, 0x00000000 }, @@ -2735,7 +2732,6 @@ static const u32 ar9280Common_9280_2[][2] = { { 0x00008178, 0x00000100 }, { 0x0000817c, 0x00000000 }, { 0x000081c0, 0x00000000 }, - { 0x000081d0, 0x00003210 }, { 0x000081ec, 0x00000000 }, { 0x000081f0, 0x00000000 }, { 0x000081f4, 0x00000000 }, @@ -2817,7 +2813,7 @@ static const u32 ar9280Common_9280_2[][2] = { { 0x00009958, 0x2108ecff }, { 0x00009940, 0x14750604 }, { 0x0000c95c, 0x004b6a8e }, - { 0x00009968, 0x000003ce }, + { 0x0000c968, 0x000003ce }, { 0x00009970, 0x190fb515 }, { 0x00009974, 0x00000000 }, { 0x00009978, 0x00000001 }, @@ -2909,16 +2905,12 @@ static const u32 ar9280Common_9280_2[][2] = { { 0x0000780c, 0x21084210 }, { 0x00007810, 0x6d801300 }, { 0x00007818, 0x07e41000 }, - { 0x0000781c, 0x00392000 }, - { 0x00007820, 0x92592480 }, { 0x00007824, 0x00040000 }, { 0x00007828, 0xdb005012 }, { 0x0000782c, 0x04924914 }, { 0x00007830, 0x21084210 }, { 0x00007834, 0x6d801300 }, { 0x0000783c, 0x07e40000 }, - { 0x00007840, 0x00392000 }, - { 0x00007844, 0x92592480 }, { 0x00007848, 0x00100000 }, { 0x0000784c, 0x773f0567 }, { 0x00007850, 0x54214514 }, @@ -2954,7 +2946,6 @@ static const u32 ar9280Modes_fast_clock_9280_2[][3] = { { 0x00009844, 0x03721821, 0x03721821 }, { 0x00009914, 0x00000898, 0x00001130 }, { 0x00009918, 0x0000000b, 0x00000016 }, - { 0x00009944, 0xdfbc1210, 0xdfbc1210 }, }; static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][6] = { @@ -3366,21 +3357,26 @@ static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = { { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a, 0x0001820a }, { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211, 0x0001b211 }, { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, - { 0x0000a324, 0x00020092, 0x00020092, 0x00022411, 0x00022411, 0x00022411 }, - { 0x0000a328, 0x0002410a, 0x0002410a, 0x00025413, 0x00025413, 0x00025413 }, - { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00029811, 0x00029811, 0x00029811 }, - { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002c813, 0x0002c813, 0x0002c813 }, - { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030a14, 0x00030a14, 0x00030a14 }, - { 0x0000a338, 0x000321ec, 0x000321ec, 0x00035a50, 0x00035a50, 0x00035a50 }, - { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00039c4c, 0x00039c4c, 0x00039c4c }, - { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003de8a, 0x0003de8a, 0x0003de8a }, - { 0x0000a344, 0x000321ec, 0x000321ec, 0x00042e92, 0x00042e92, 0x00042e92 }, - { 0x0000a348, 0x000321ec, 0x000321ec, 0x00046ed2, 0x00046ed2, 0x00046ed2 }, - { 0x0000a34c, 0x000321ec, 0x000321ec, 0x0004bed5, 0x0004bed5, 0x0004bed5 }, - { 0x0000a350, 0x000321ec, 0x000321ec, 0x0004ff54, 0x0004ff54, 0x0004ff54 }, - { 0x0000a354, 0x000321ec, 0x000321ec, 0x00053fd5, 0x00053fd5, 0x00053fd5 }, + { 0x0000a324, 0x00021092, 0x00021092, 0x00022411, 0x00022411, 0x00022411 }, + { 0x0000a328, 0x0002510a, 0x0002510a, 0x00025413, 0x00025413, 0x00025413 }, + { 0x0000a32c, 0x0002910c, 0x0002910c, 0x00029811, 0x00029811, 0x00029811 }, + { 0x0000a330, 0x0002c18b, 0x0002c18b, 0x0002c813, 0x0002c813, 0x0002c813 }, + { 0x0000a334, 0x0002f1cc, 0x0002f1cc, 0x00030a14, 0x00030a14, 0x00030a14 }, + { 0x0000a338, 0x000321eb, 0x000321eb, 0x00035a50, 0x00035a50, 0x00035a50 }, + { 0x0000a33c, 0x000341ec, 0x000341ec, 0x00039c4c, 0x00039c4c, 0x00039c4c }, + { 0x0000a340, 0x000341ec, 0x000341ec, 0x0003de8a, 0x0003de8a, 0x0003de8a }, + { 0x0000a344, 0x000341ec, 0x000341ec, 0x00042e92, 0x00042e92, 0x00042e92 }, + { 0x0000a348, 0x000341ec, 0x000341ec, 0x00046ed2, 0x00046ed2, 0x00046ed2 }, + { 0x0000a34c, 0x000341ec, 0x000341ec, 0x0004bed5, 0x0004bed5, 0x0004bed5 }, + { 0x0000a350, 0x000341ec, 0x000341ec, 0x0004ff54, 0x0004ff54, 0x0004ff54 }, + { 0x0000a354, 0x000341ec, 0x000341ec, 0x00055fd5, 0x00055fd5, 0x00055fd5 }, { 0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff }, { 0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff }, + { 0x0000781c, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 }, + { 0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 }, + { 0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 }, + { 0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 }, + { 0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, { 0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce }, }; @@ -3409,6 +3405,11 @@ static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = { { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 }, { 0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff }, { 0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff }, + { 0x0000781c, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 }, + { 0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 }, + { 0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 }, + { 0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 }, + { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce }, }; @@ -4135,11 +4136,11 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e }, - { 0x00009844, 0x0372161e, 0x0372161e, 0x03720020, 0x03720020, 0x037216a0 }, - { 0x00009848, 0x00001066, 0x00001066, 0x00000057, 0x00000057, 0x00001059 }, + { 0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0 }, + { 0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, - { 0x0000985c, 0x3139605e, 0x3139605e, 0x3136605e, 0x3136605e, 0x3139605e }, + { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e }, { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18 }, { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, @@ -4159,264 +4160,264 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x00009a00, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 }, - { 0x00009a04, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 }, - { 0x00009a08, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 }, - { 0x00009a0c, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 }, - { 0x00009a10, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 }, - { 0x00009a14, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 }, - { 0x00009a18, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 }, - { 0x00009a1c, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 }, - { 0x00009a20, 0x00000000, 0x00000000, 0x00068114, 0x00068114, 0x00000000 }, - { 0x00009a24, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 }, - { 0x00009a28, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 }, - { 0x00009a2c, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 }, - { 0x00009a30, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 }, - { 0x00009a34, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 }, - { 0x00009a38, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 }, - { 0x00009a3c, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 }, - { 0x00009a40, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 }, - { 0x00009a44, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 }, - { 0x00009a48, 0x00000000, 0x00000000, 0x00068284, 0x00068284, 0x00000000 }, - { 0x00009a4c, 0x00000000, 0x00000000, 0x00068288, 0x00068288, 0x00000000 }, - { 0x00009a50, 0x00000000, 0x00000000, 0x00068220, 0x00068220, 0x00000000 }, - { 0x00009a54, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 }, - { 0x00009a58, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 }, - { 0x00009a5c, 0x00000000, 0x00000000, 0x00068304, 0x00068304, 0x00000000 }, - { 0x00009a60, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 }, - { 0x00009a64, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 }, - { 0x00009a68, 0x00000000, 0x00000000, 0x00068380, 0x00068380, 0x00000000 }, - { 0x00009a6c, 0x00000000, 0x00000000, 0x00068384, 0x00068384, 0x00000000 }, + { 0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 }, + { 0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 }, + { 0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 }, + { 0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 }, + { 0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 }, + { 0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 }, + { 0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 }, + { 0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 }, + { 0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 }, + { 0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 }, + { 0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 }, + { 0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 }, + { 0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 }, + { 0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 }, + { 0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 }, + { 0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 }, + { 0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 }, + { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, + { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, + { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, + { 0x00009a50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, + { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, + { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, + { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, + { 0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 }, + { 0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 }, + { 0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 }, + { 0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 }, { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, - { 0x00009a88, 0x00000000, 0x00000000, 0x00068b04, 0x00068b04, 0x00000000 }, - { 0x00009a8c, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 }, - { 0x00009a90, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 }, - { 0x00009a94, 0x00000000, 0x00000000, 0x00068b0c, 0x00068b0c, 0x00000000 }, - { 0x00009a98, 0x00000000, 0x00000000, 0x00068b80, 0x00068b80, 0x00000000 }, - { 0x00009a9c, 0x00000000, 0x00000000, 0x00068b84, 0x00068b84, 0x00000000 }, - { 0x00009aa0, 0x00000000, 0x00000000, 0x00068b88, 0x00068b88, 0x00000000 }, - { 0x00009aa4, 0x00000000, 0x00000000, 0x00068b8c, 0x00068b8c, 0x00000000 }, - { 0x00009aa8, 0x00000000, 0x00000000, 0x000b8b90, 0x000b8b90, 0x00000000 }, - { 0x00009aac, 0x00000000, 0x00000000, 0x000b8f80, 0x000b8f80, 0x00000000 }, - { 0x00009ab0, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 }, - { 0x00009ab4, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 }, - { 0x00009ab8, 0x00000000, 0x00000000, 0x000b8f8c, 0x000b8f8c, 0x00000000 }, - { 0x00009abc, 0x00000000, 0x00000000, 0x000b8f90, 0x000b8f90, 0x00000000 }, - { 0x00009ac0, 0x00000000, 0x00000000, 0x000bb30c, 0x000bb30c, 0x00000000 }, - { 0x00009ac4, 0x00000000, 0x00000000, 0x000bb310, 0x000bb310, 0x00000000 }, - { 0x00009ac8, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 }, - { 0x00009acc, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 }, - { 0x00009ad0, 0x00000000, 0x00000000, 0x000bb324, 0x000bb324, 0x00000000 }, - { 0x00009ad4, 0x00000000, 0x00000000, 0x000bb704, 0x000bb704, 0x00000000 }, - { 0x00009ad8, 0x00000000, 0x00000000, 0x000f96a4, 0x000f96a4, 0x00000000 }, - { 0x00009adc, 0x00000000, 0x00000000, 0x000f96a8, 0x000f96a8, 0x00000000 }, - { 0x00009ae0, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 }, - { 0x00009ae4, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 }, - { 0x00009ae8, 0x00000000, 0x00000000, 0x000f9720, 0x000f9720, 0x00000000 }, - { 0x00009aec, 0x00000000, 0x00000000, 0x000f9724, 0x000f9724, 0x00000000 }, - { 0x00009af0, 0x00000000, 0x00000000, 0x000f9728, 0x000f9728, 0x00000000 }, - { 0x00009af4, 0x00000000, 0x00000000, 0x000f972c, 0x000f972c, 0x00000000 }, - { 0x00009af8, 0x00000000, 0x00000000, 0x000f97a0, 0x000f97a0, 0x00000000 }, - { 0x00009afc, 0x00000000, 0x00000000, 0x000f97a4, 0x000f97a4, 0x00000000 }, - { 0x00009b00, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 }, - { 0x00009b04, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 }, - { 0x00009b08, 0x00000000, 0x00000000, 0x000fb7b4, 0x000fb7b4, 0x00000000 }, - { 0x00009b0c, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 }, - { 0x00009b10, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 }, - { 0x00009b14, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 }, - { 0x00009b18, 0x00000000, 0x00000000, 0x000fb7ad, 0x000fb7ad, 0x00000000 }, - { 0x00009b1c, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 }, - { 0x00009b20, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 }, - { 0x00009b24, 0x00000000, 0x00000000, 0x000fb7b9, 0x000fb7b9, 0x00000000 }, - { 0x00009b28, 0x00000000, 0x00000000, 0x000fb7c5, 0x000fb7c5, 0x00000000 }, - { 0x00009b2c, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 }, - { 0x00009b30, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 }, - { 0x00009b34, 0x00000000, 0x00000000, 0x000fb7d5, 0x000fb7d5, 0x00000000 }, - { 0x00009b38, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 }, - { 0x00009b3c, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 }, - { 0x00009b40, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 }, - { 0x00009b44, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 }, - { 0x00009b48, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 }, - { 0x00009b4c, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 }, - { 0x00009b50, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 }, - { 0x00009b54, 0x00000000, 0x00000000, 0x000fb7c7, 0x000fb7c7, 0x00000000 }, - { 0x00009b58, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 }, - { 0x00009b5c, 0x00000000, 0x00000000, 0x000fb7cf, 0x000fb7cf, 0x00000000 }, - { 0x00009b60, 0x00000000, 0x00000000, 0x000fb7d7, 0x000fb7d7, 0x00000000 }, - { 0x00009b64, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b68, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b6c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b70, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b74, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b78, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b7c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b80, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b84, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b88, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b8c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b90, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b94, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b98, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b9c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009ba0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009ba4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009ba8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bac, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bb0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bb4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bb8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bbc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bc0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bc4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bc8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bcc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bd0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bd4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bd8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bdc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009be0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009be4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009be8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bec, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bf0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bf4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bf8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bfc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x0000aa00, 0x00000000, 0x00000000, 0x0006801c, 0x0006801c, 0x00000000 }, - { 0x0000aa04, 0x00000000, 0x00000000, 0x0006801c, 0x0006801c, 0x00000000 }, - { 0x0000aa08, 0x00000000, 0x00000000, 0x0006801c, 0x0006801c, 0x00000000 }, - { 0x0000aa0c, 0x00000000, 0x00000000, 0x00068080, 0x00068080, 0x00000000 }, - { 0x0000aa10, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 }, - { 0x0000aa14, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 }, - { 0x0000aa18, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 }, - { 0x0000aa1c, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 }, - { 0x0000aa20, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 }, - { 0x0000aa24, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 }, - { 0x0000aa28, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 }, - { 0x0000aa2c, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 }, - { 0x0000aa30, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 }, - { 0x0000aa34, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 }, - { 0x0000aa38, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 }, - { 0x0000aa3c, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 }, - { 0x0000aa40, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 }, - { 0x0000aa44, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 }, - { 0x0000aa48, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 }, - { 0x0000aa4c, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 }, - { 0x0000aa50, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 }, - { 0x0000aa54, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 }, - { 0x0000aa58, 0x00000000, 0x00000000, 0x000681ac, 0x000681ac, 0x00000000 }, - { 0x0000aa5c, 0x00000000, 0x00000000, 0x0006821c, 0x0006821c, 0x00000000 }, - { 0x0000aa60, 0x00000000, 0x00000000, 0x00068224, 0x00068224, 0x00000000 }, - { 0x0000aa64, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 }, - { 0x0000aa68, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 }, - { 0x0000aa6c, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 }, - { 0x0000aa70, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 }, - { 0x0000aa74, 0x00000000, 0x00000000, 0x00068310, 0x00068310, 0x00000000 }, - { 0x0000aa78, 0x00000000, 0x00000000, 0x00068788, 0x00068788, 0x00000000 }, - { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006878c, 0x0006878c, 0x00000000 }, - { 0x0000aa80, 0x00000000, 0x00000000, 0x00068790, 0x00068790, 0x00000000 }, - { 0x0000aa84, 0x00000000, 0x00000000, 0x00068794, 0x00068794, 0x00000000 }, - { 0x0000aa88, 0x00000000, 0x00000000, 0x00068798, 0x00068798, 0x00000000 }, - { 0x0000aa8c, 0x00000000, 0x00000000, 0x0006879c, 0x0006879c, 0x00000000 }, - { 0x0000aa90, 0x00000000, 0x00000000, 0x00068b89, 0x00068b89, 0x00000000 }, - { 0x0000aa94, 0x00000000, 0x00000000, 0x00068b8d, 0x00068b8d, 0x00000000 }, - { 0x0000aa98, 0x00000000, 0x00000000, 0x00068b91, 0x00068b91, 0x00000000 }, - { 0x0000aa9c, 0x00000000, 0x00000000, 0x00068b95, 0x00068b95, 0x00000000 }, - { 0x0000aaa0, 0x00000000, 0x00000000, 0x00068b99, 0x00068b99, 0x00000000 }, - { 0x0000aaa4, 0x00000000, 0x00000000, 0x00068ba5, 0x00068ba5, 0x00000000 }, - { 0x0000aaa8, 0x00000000, 0x00000000, 0x00068ba9, 0x00068ba9, 0x00000000 }, - { 0x0000aaac, 0x00000000, 0x00000000, 0x00068bad, 0x00068bad, 0x00000000 }, - { 0x0000aab0, 0x00000000, 0x00000000, 0x000b8b0c, 0x000b8b0c, 0x00000000 }, - { 0x0000aab4, 0x00000000, 0x00000000, 0x000b8f10, 0x000b8f10, 0x00000000 }, - { 0x0000aab8, 0x00000000, 0x00000000, 0x000b8f14, 0x000b8f14, 0x00000000 }, - { 0x0000aabc, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 }, - { 0x0000aac0, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 }, - { 0x0000aac4, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 }, - { 0x0000aac8, 0x00000000, 0x00000000, 0x000bb380, 0x000bb380, 0x00000000 }, - { 0x0000aacc, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 }, - { 0x0000aad0, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 }, - { 0x0000aad4, 0x00000000, 0x00000000, 0x000bb38c, 0x000bb38c, 0x00000000 }, - { 0x0000aad8, 0x00000000, 0x00000000, 0x000bb394, 0x000bb394, 0x00000000 }, - { 0x0000aadc, 0x00000000, 0x00000000, 0x000bb798, 0x000bb798, 0x00000000 }, - { 0x0000aae0, 0x00000000, 0x00000000, 0x000f970c, 0x000f970c, 0x00000000 }, - { 0x0000aae4, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 }, - { 0x0000aae8, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 }, - { 0x0000aaec, 0x00000000, 0x00000000, 0x000f9718, 0x000f9718, 0x00000000 }, - { 0x0000aaf0, 0x00000000, 0x00000000, 0x000f9705, 0x000f9705, 0x00000000 }, - { 0x0000aaf4, 0x00000000, 0x00000000, 0x000f9709, 0x000f9709, 0x00000000 }, - { 0x0000aaf8, 0x00000000, 0x00000000, 0x000f970d, 0x000f970d, 0x00000000 }, - { 0x0000aafc, 0x00000000, 0x00000000, 0x000f9711, 0x000f9711, 0x00000000 }, - { 0x0000ab00, 0x00000000, 0x00000000, 0x000f9715, 0x000f9715, 0x00000000 }, - { 0x0000ab04, 0x00000000, 0x00000000, 0x000f9719, 0x000f9719, 0x00000000 }, - { 0x0000ab08, 0x00000000, 0x00000000, 0x000fb7a4, 0x000fb7a4, 0x00000000 }, - { 0x0000ab0c, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 }, - { 0x0000ab10, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 }, - { 0x0000ab14, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 }, - { 0x0000ab18, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 }, - { 0x0000ab1c, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 }, - { 0x0000ab20, 0x00000000, 0x00000000, 0x000fb7bc, 0x000fb7bc, 0x00000000 }, - { 0x0000ab24, 0x00000000, 0x00000000, 0x000fb7a1, 0x000fb7a1, 0x00000000 }, - { 0x0000ab28, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 }, - { 0x0000ab2c, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 }, - { 0x0000ab30, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 }, - { 0x0000ab34, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 }, - { 0x0000ab38, 0x00000000, 0x00000000, 0x000fb7bd, 0x000fb7bd, 0x00000000 }, - { 0x0000ab3c, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 }, - { 0x0000ab40, 0x00000000, 0x00000000, 0x000fb7cd, 0x000fb7cd, 0x00000000 }, - { 0x0000ab44, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 }, - { 0x0000ab48, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 }, - { 0x0000ab4c, 0x00000000, 0x00000000, 0x000fb7c2, 0x000fb7c2, 0x00000000 }, - { 0x0000ab50, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 }, - { 0x0000ab54, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 }, - { 0x0000ab58, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 }, - { 0x0000ab5c, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 }, - { 0x0000ab60, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 }, - { 0x0000ab64, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 }, - { 0x0000ab68, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 }, - { 0x0000ab6c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab70, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab74, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab78, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab7c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab80, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab84, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab88, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab8c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab90, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab94, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab98, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab9c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000aba0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000aba4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000aba8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abac, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abb0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abb4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abb8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abbc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abc0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abc4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abc8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abcc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abd0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abd4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abd8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abdc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abe0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abe4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abe8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abec, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abf0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abf4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abf8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abfc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x00009a88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, + { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, + { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, + { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, + { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, + { 0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 }, + { 0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 }, + { 0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 }, + { 0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 }, + { 0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 }, + { 0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 }, + { 0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 }, + { 0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 }, + { 0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 }, + { 0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 }, + { 0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 }, + { 0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 }, + { 0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 }, + { 0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 }, + { 0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 }, + { 0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 }, + { 0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 }, + { 0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 }, + { 0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 }, + { 0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 }, + { 0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 }, + { 0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 }, + { 0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 }, + { 0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 }, + { 0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 }, + { 0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 }, + { 0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 }, + { 0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 }, + { 0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 }, + { 0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 }, + { 0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 }, + { 0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 }, + { 0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 }, + { 0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 }, + { 0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 }, + { 0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 }, + { 0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 }, + { 0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 }, + { 0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 }, + { 0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 }, + { 0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 }, + { 0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 }, + { 0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 }, + { 0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 }, + { 0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 }, + { 0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 }, + { 0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 }, + { 0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 }, + { 0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 }, + { 0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 }, + { 0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 }, + { 0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 }, + { 0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 }, + { 0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 }, + { 0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 }, + { 0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 }, + { 0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 }, + { 0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 }, + { 0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 }, + { 0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 }, + { 0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 }, + { 0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 }, + { 0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 }, + { 0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 }, + { 0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 }, + { 0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 }, + { 0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 }, + { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, + { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, + { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, + { 0x0000aa50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, + { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, + { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, + { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, + { 0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 }, + { 0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 }, + { 0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 }, + { 0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 }, + { 0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, + { 0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, + { 0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, + { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, + { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, + { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, + { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, + { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, + { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, + { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, + { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, + { 0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 }, + { 0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 }, + { 0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 }, + { 0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 }, + { 0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 }, + { 0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 }, + { 0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 }, + { 0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 }, + { 0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 }, + { 0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 }, + { 0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 }, + { 0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 }, + { 0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 }, + { 0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 }, + { 0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 }, + { 0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 }, + { 0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 }, + { 0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 }, + { 0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 }, + { 0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 }, + { 0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 }, + { 0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 }, + { 0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 }, + { 0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 }, + { 0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 }, + { 0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 }, + { 0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 }, + { 0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 }, + { 0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 }, + { 0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 }, + { 0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 }, + { 0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 }, + { 0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 }, + { 0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 }, + { 0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 }, + { 0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 }, + { 0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 }, + { 0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 }, + { 0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 }, + { 0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 }, + { 0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 }, + { 0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 }, + { 0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 }, + { 0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 }, + { 0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 }, + { 0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 }, + { 0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 }, + { 0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 }, + { 0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 }, + { 0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 }, + { 0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 }, - { 0x0000a20c, 0x00000014, 0x00000014, 0x00000000, 0x00000000, 0x0001f000 }, + { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 }, @@ -4679,7 +4680,7 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { { 0x000099a0, 0x00000000 }, { 0x000099a4, 0x00000001 }, { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x2def1000 }, + { 0x000099ac, 0x2def0400 }, { 0x000099b0, 0x03051000 }, { 0x000099b4, 0x00000820 }, { 0x000099dc, 0x00000000 }, @@ -4688,7 +4689,7 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { { 0x000099e8, 0x3c466478 }, { 0x000099ec, 0x0cc80caa }, { 0x000099f0, 0x00000000 }, - { 0x0000a208, 0x803e6788 }, + { 0x0000a208, 0x803e68c8 }, { 0x0000a210, 0x4080a333 }, { 0x0000a214, 0x00206c10 }, { 0x0000a218, 0x009c4060 }, diff --git a/drivers/net/wireless/ath9k/reg.h b/drivers/net/wireless/ath9k/reg.h index 9fedb4911bc..8cc9beff5ec 100644 --- a/drivers/net/wireless/ath9k/reg.h +++ b/drivers/net/wireless/ath9k/reg.h @@ -875,12 +875,15 @@ enum { #define AR_NUM_GPIO 14 #define AR928X_NUM_GPIO 10 +#define AR9285_NUM_GPIO 12 #define AR_GPIO_IN_OUT 0x4048 #define AR_GPIO_IN_VAL 0x0FFFC000 #define AR_GPIO_IN_VAL_S 14 #define AR928X_GPIO_IN_VAL 0x000FFC00 #define AR928X_GPIO_IN_VAL_S 10 +#define AR9285_GPIO_IN_VAL 0x00FFF000 +#define AR9285_GPIO_IN_VAL_S 12 #define AR_GPIO_OE_OUT 0x404c #define AR_GPIO_OE_OUT_DRV 0x3 @@ -1021,6 +1024,10 @@ enum { #define AR_AN_RF5G1_CH1_DB5 0x00380000 #define AR_AN_RF5G1_CH1_DB5_S 19 +#define AR_AN_TOP1 0x7890 +#define AR_AN_TOP1_DACIPMODE 0x00040000 +#define AR_AN_TOP1_DACIPMODE_S 18 + #define AR_AN_TOP2 0x7894 #define AR_AN_TOP2_XPABIAS_LVL 0xC0000000 #define AR_AN_TOP2_XPABIAS_LVL_S 30 -- GitLab From bb519bee07eed4fac9921ad658fb1f7ed78defb5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 24 Dec 2008 15:26:40 +0100 Subject: [PATCH 0763/4982] b43: detect N PHY revision/radio Does nothing unless you enable the hidden N PHY config. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index a2b1e375f83..26e733a5a56 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3752,7 +3752,7 @@ static int b43_phy_versioning(struct b43_wldev *dev) break; #ifdef CONFIG_B43_NPHY case B43_PHYTYPE_N: - if (phy_rev > 1) + if (phy_rev > 4) unsupported = 1; break; #endif @@ -3805,7 +3805,7 @@ static int b43_phy_versioning(struct b43_wldev *dev) unsupported = 1; break; case B43_PHYTYPE_N: - if (radio_ver != 0x2055) + if (radio_ver != 0x2055 && radio_ver != 0x2056) unsupported = 1; break; default: -- GitLab From 6b1c7c67603efdf0b39f6056989b0f8194cdc1f3 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Thu, 25 Dec 2008 00:39:28 +0100 Subject: [PATCH 0764/4982] b43/ssb: Add SPROM8 extraction and LP-PHY detection This adds detection code for the LP-PHY and SPROM extraction code for version 8, which is needed by the LP-PHY and newer N-PHY. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 12 ++++++ drivers/ssb/b43_pci_bridge.c | 1 + drivers/ssb/pci.c | 74 +++++++++++++++++++++++++++------ include/linux/ssb/ssb_regs.h | 36 ++++++++++++++++ 4 files changed, 111 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 26e733a5a56..c627bac87a4 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -97,6 +97,7 @@ static const struct ssb_device_id b43_ssb_tbl[] = { SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 10), SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 11), SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 13), + SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 15), SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 16), SSB_DEVTABLE_END }; @@ -3755,6 +3756,12 @@ static int b43_phy_versioning(struct b43_wldev *dev) if (phy_rev > 4) unsupported = 1; break; +#endif +#ifdef CONFIG_B43_PHY_LP + case B43_PHYTYPE_LP: + if (phy_rev > 1) + unsupported = 1; + break; #endif default: unsupported = 1; @@ -3808,6 +3815,10 @@ static int b43_phy_versioning(struct b43_wldev *dev) if (radio_ver != 0x2055 && radio_ver != 0x2056) unsupported = 1; break; + case B43_PHYTYPE_LP: + if (radio_ver != 0x2062) + unsupported = 1; + break; default: B43_WARN_ON(1); } @@ -4402,6 +4413,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) break; case B43_PHYTYPE_G: case B43_PHYTYPE_N: + case B43_PHYTYPE_LP: have_2ghz_phy = 1; break; default: diff --git a/drivers/ssb/b43_pci_bridge.c b/drivers/ssb/b43_pci_bridge.c index 6433a7ed39f..27a677584a4 100644 --- a/drivers/ssb/b43_pci_bridge.c +++ b/drivers/ssb/b43_pci_bridge.c @@ -21,6 +21,7 @@ static const struct pci_device_id b43_pci_bridge_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4307) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4311) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4312) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4315) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4318) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) }, diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index d5cde051806..c958ac16423 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c @@ -467,6 +467,51 @@ static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) /* TODO - get remaining rev 4 stuff needed */ } +static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) +{ + int i; + u16 v; + + /* extract the MAC address */ + for (i = 0; i < 3; i++) { + v = in[SPOFF(SSB_SPROM1_IL0MAC) + i]; + *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); + } + SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0); + SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0); + SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0); + SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A, + SSB_SPROM8_ANTAVAIL_A_SHIFT); + SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG, + SSB_SPROM8_ANTAVAIL_BG_SHIFT); + SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0); + SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG, + SSB_SPROM8_ITSSI_BG_SHIFT); + SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0); + SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A, + SSB_SPROM8_ITSSI_A_SHIFT); + SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0); + SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1, + SSB_SPROM8_GPIOA_P1_SHIFT); + SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0); + SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3, + SSB_SPROM8_GPIOB_P3_SHIFT); + + /* Extract the antenna gain values. */ + SPEX(antenna_gain.ghz24.a0, SSB_SPROM8_AGAIN01, + SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT); + SPEX(antenna_gain.ghz24.a1, SSB_SPROM8_AGAIN01, + SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT); + SPEX(antenna_gain.ghz24.a2, SSB_SPROM8_AGAIN23, + SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT); + SPEX(antenna_gain.ghz24.a3, SSB_SPROM8_AGAIN23, + SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT); + memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24, + sizeof(out->antenna_gain.ghz5)); + + /* TODO - get remaining rev 8 stuff needed */ +} + static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, const u16 *in, u16 size) { @@ -487,15 +532,25 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, out->revision = 4; sprom_extract_r45(out, in); } else { - if (out->revision == 0) - goto unsupported; - if (out->revision >= 1 && out->revision <= 3) { + switch (out->revision) { + case 1: + case 2: + case 3: sprom_extract_r123(out, in); - } - if (out->revision == 4 || out->revision == 5) + break; + case 4: + case 5: sprom_extract_r45(out, in); - if (out->revision > 5) - goto unsupported; + break; + case 8: + sprom_extract_r8(out, in); + break; + default: + ssb_printk(KERN_WARNING PFX "Unsupported SPROM" + " revision %d detected. Will extract" + " v1\n", out->revision); + sprom_extract_r123(out, in); + } } if (out->boardflags_lo == 0xFFFF) @@ -504,11 +559,6 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, out->boardflags_hi = 0; /* per specs */ return 0; -unsupported: - ssb_printk(KERN_WARNING PFX "Unsupported SPROM revision %d " - "detected. Will extract v1\n", out->revision); - sprom_extract_r123(out, in); - return 0; } static int ssb_pci_sprom_get(struct ssb_bus *bus, diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h index 99a0f991e85..a01b982b578 100644 --- a/include/linux/ssb/ssb_regs.h +++ b/include/linux/ssb/ssb_regs.h @@ -326,6 +326,42 @@ #define SSB_SPROM5_GPIOB_P3 0xFF00 /* Pin 3 */ #define SSB_SPROM5_GPIOB_P3_SHIFT 8 +/* SPROM Revision 8 */ +#define SSB_SPROM8_BFLLO 0x1084 /* Boardflags (low 16 bits) */ +#define SSB_SPROM8_BFLHI 0x1086 /* Boardflags Hi */ +#define SSB_SPROM8_IL0MAC 0x108C /* 6 byte MAC address */ +#define SSB_SPROM8_CCODE 0x1092 /* 2 byte country code */ +#define SSB_SPROM8_ANTAVAIL 0x109C /* Antenna available bitfields*/ +#define SSB_SPROM8_ANTAVAIL_A 0xFF00 /* A-PHY bitfield */ +#define SSB_SPROM8_ANTAVAIL_A_SHIFT 8 +#define SSB_SPROM8_ANTAVAIL_BG 0x00FF /* B-PHY and G-PHY bitfield */ +#define SSB_SPROM8_ANTAVAIL_BG_SHIFT 0 +#define SSB_SPROM8_AGAIN01 0x109E /* Antenna Gain (in dBm Q5.2) */ +#define SSB_SPROM8_AGAIN0 0x00FF /* Antenna 0 */ +#define SSB_SPROM8_AGAIN0_SHIFT 0 +#define SSB_SPROM8_AGAIN1 0xFF00 /* Antenna 1 */ +#define SSB_SPROM8_AGAIN1_SHIFT 8 +#define SSB_SPROM8_AGAIN23 0x10A0 +#define SSB_SPROM8_AGAIN2 0x00FF /* Antenna 2 */ +#define SSB_SPROM8_AGAIN2_SHIFT 0 +#define SSB_SPROM8_AGAIN3 0xFF00 /* Antenna 3 */ +#define SSB_SPROM8_AGAIN3_SHIFT 8 +#define SSB_SPROM8_GPIOA 0x1096 /*Gen. Purpose IO # 0 and 1 */ +#define SSB_SPROM8_GPIOA_P0 0x00FF /* Pin 0 */ +#define SSB_SPROM8_GPIOA_P1 0xFF00 /* Pin 1 */ +#define SSB_SPROM8_GPIOA_P1_SHIFT 8 +#define SSB_SPROM8_GPIOB 0x1098 /* Gen. Purpose IO # 2 and 3 */ +#define SSB_SPROM8_GPIOB_P2 0x00FF /* Pin 2 */ +#define SSB_SPROM8_GPIOB_P3 0xFF00 /* Pin 3 */ +#define SSB_SPROM8_GPIOB_P3_SHIFT 8 +#define SSB_SPROM8_MAXP_BG 0x10C0 /* Max Power BG in path 1 */ +#define SSB_SPROM8_MAXP_BG_MASK 0x00FF /* Mask for Max Power BG */ +#define SSB_SPROM8_ITSSI_BG 0xFF00 /* Mask for path 1 itssi_bg */ +#define SSB_SPROM8_ITSSI_BG_SHIFT 8 +#define SSB_SPROM8_MAXP_A 0x10C8 /* Max Power A in path 1 */ +#define SSB_SPROM8_MAXP_A_MASK 0x00FF /* Mask for Max Power A */ +#define SSB_SPROM8_ITSSI_A 0xFF00 /* Mask for path 1 itssi_a */ +#define SSB_SPROM8_ITSSI_A_SHIFT 8 /* Values for SSB_SPROM1_BINF_CCODE */ enum { -- GitLab From 6982869d993009c02cefcca98a67b212d0e61c5f Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 26 Dec 2008 19:08:31 +0100 Subject: [PATCH 0765/4982] p54usb: utilize usb_reset_device for 3887 Sometimes on unload or reboot the 3887 USB devices become stuck. kernel: usbcore: registered new interface driver p54usb kernel: usb 2-10: (p54usb) reset failed! (-110) kernel: p54usb: probe of 2-10:1.0 failed with error -110 [...] and a physical unplug and replug was necessary. However we should be able to do this in software as well, without any user interaction. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54usb.c | 70 +++++++++++++++++++++++++------ drivers/net/wireless/p54/p54usb.h | 1 + 2 files changed, 58 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 5de2ebfb28c..3c31c15267b 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -424,9 +424,44 @@ static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep, data, len, &alen, 2000); } +static const char p54u_romboot_3887[] = "~~~~"; +static const char p54u_firmware_upload_3887[] = "<\r"; + +static int p54u_device_reset_3887(struct ieee80211_hw *dev) +{ + struct p54u_priv *priv = dev->priv; + int ret, lock; + u8 buf[4]; + + ret = lock = usb_lock_device_for_reset(priv->udev, priv->intf); + if (ret < 0) { + dev_err(&priv->udev->dev, "(p54usb) unable to lock device for " + "reset: %d\n", ret); + return ret; + } + + ret = usb_reset_device(priv->udev); + if (lock) + usb_unlock_device(priv->udev); + + if (ret) { + dev_err(&priv->udev->dev, "(p54usb) unable to reset " + "device: %d\n", ret); + return ret; + } + + memcpy(&buf, p54u_romboot_3887, sizeof(buf)); + ret = p54u_bulk_msg(priv, P54U_PIPE_DATA, + buf, sizeof(buf)); + if (ret) + dev_err(&priv->udev->dev, "(p54usb) unable to jump to " + "boot ROM: %d\n", ret); + + return ret; +} + static int p54u_upload_firmware_3887(struct ieee80211_hw *dev) { - static char start_string[] = "~~~~<\r"; struct p54u_priv *priv = dev->priv; const struct firmware *fw_entry = NULL; int err, alen; @@ -445,12 +480,9 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev) goto err_bufalloc; } - memcpy(buf, start_string, 4); - err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 4); - if (err) { - dev_err(&priv->udev->dev, "(p54usb) reset failed! (%d)\n", err); + err = p54u_device_reset_3887(dev); + if (err) goto err_reset; - } err = request_firmware(&fw_entry, "isl3887usb", &priv->udev->dev); if (err) { @@ -467,14 +499,14 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev) goto err_upload_failed; left = block_size = min((size_t)P54U_FW_BLOCK, fw_entry->size); - strcpy(buf, start_string); - left -= strlen(start_string); - tmp += strlen(start_string); + strcpy(buf, p54u_firmware_upload_3887); + left -= strlen(p54u_firmware_upload_3887); + tmp += strlen(p54u_firmware_upload_3887); data = fw_entry->data; remains = fw_entry->size; - hdr = (struct x2_header *)(buf + strlen(start_string)); + hdr = (struct x2_header *)(buf + strlen(p54u_firmware_upload_3887)); memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE); hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR); hdr->fw_length = cpu_to_le32(fw_entry->size); @@ -876,6 +908,9 @@ static int __devinit p54u_probe(struct usb_interface *intf, SET_IEEE80211_DEV(dev, &intf->dev); usb_set_intfdata(intf, dev); priv->udev = udev; + priv->intf = intf; + skb_queue_head_init(&priv->rx_queue); + init_usb_anchor(&priv->submitted); usb_get_dev(udev); @@ -918,9 +953,6 @@ static int __devinit p54u_probe(struct usb_interface *intf, if (err) goto err_free_dev; - skb_queue_head_init(&priv->rx_queue); - init_usb_anchor(&priv->submitted); - p54u_open(dev); err = p54_read_eeprom(dev); p54u_stop(dev); @@ -958,11 +990,23 @@ static void __devexit p54u_disconnect(struct usb_interface *intf) ieee80211_free_hw(dev); } +static int p54u_pre_reset(struct usb_interface *intf) +{ + return 0; +} + +static int p54u_post_reset(struct usb_interface *intf) +{ + return 0; +} + static struct usb_driver p54u_driver = { .name = "p54usb", .id_table = p54u_table, .probe = p54u_probe, .disconnect = p54u_disconnect, + .pre_reset = p54u_pre_reset, + .post_reset = p54u_post_reset, }; static int __init p54u_init(void) diff --git a/drivers/net/wireless/p54/p54usb.h b/drivers/net/wireless/p54/p54usb.h index 54ee738bf2a..8bc58982d8d 100644 --- a/drivers/net/wireless/p54/p54usb.h +++ b/drivers/net/wireless/p54/p54usb.h @@ -126,6 +126,7 @@ struct p54u_rx_info { struct p54u_priv { struct p54_common common; struct usb_device *udev; + struct usb_interface *intf; enum { P54U_NET2280 = 0, P54U_3887 -- GitLab From e365f16046b72977ec22364215b57af840f0907e Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 26 Dec 2008 19:09:34 +0100 Subject: [PATCH 0766/4982] p54: prevent upload of wrong firmwares This patch will prevent anyone to upload a firmware which was not designed for his device. There's still a catch: There is no easy way to detect if a firmware is for PCI or for USB (1st Gen), because they all share the same LM86 identifier. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54pci.c | 6 ++++++ drivers/net/wireless/p54/p54usb.c | 15 +++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index aa367a0ddc4..3f9a6b04ea9 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -79,6 +79,12 @@ static int p54p_upload_firmware(struct ieee80211_hw *dev) if (err) return err; + if (priv->common.fw_interface != FW_LM86) { + dev_err(&priv->pdev->dev, "wrong firmware, " + "please get a LM86(PCI) firmware a try again.\n"); + return -EINVAL; + } + data = (__le32 *) priv->firmware->data; remains = priv->firmware->size; device_addr = ISL38XX_DEV_FIRMWARE_ADDR; diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 3c31c15267b..44d6855bd17 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -498,6 +498,13 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev) if (err) goto err_upload_failed; + if (priv->common.fw_interface != FW_LM87) { + dev_err(&priv->udev->dev, "wrong firmware, " + "please get a LM87 firmware and try again.\n"); + err = -EINVAL; + goto err_upload_failed; + } + left = block_size = min((size_t)P54U_FW_BLOCK, fw_entry->size); strcpy(buf, p54u_firmware_upload_3887); left -= strlen(p54u_firmware_upload_3887); @@ -648,6 +655,14 @@ static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev) return err; } + if (priv->common.fw_interface != FW_LM86) { + dev_err(&priv->udev->dev, "wrong firmware, " + "please get a LM86(USB) firmware and try again.\n"); + kfree(buf); + release_firmware(fw_entry); + return -EINVAL; + } + #define P54U_WRITE(type, addr, data) \ do {\ err = p54u_write(priv, buf, type,\ -- GitLab From 98a8d1a8f22237e2aa7db5453df0f68935a5ede0 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 26 Dec 2008 21:50:33 +0100 Subject: [PATCH 0767/4982] p54: regulatory domain hints This patch adds a sub-routine that parses the default country eeprom entry and forwards the obtained Alpha2 identifier to the regulatory sub-system. Note: I dropped the p54 specific regdomain<->alpha2 conversion code for now. But it will be added as soon as there's the common library function is ready. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 34 +++++++++++++++++++++++++++- drivers/net/wireless/p54/p54common.h | 6 +++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 28d98338957..8d2df5b6ecb 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -376,6 +376,36 @@ static void p54_parse_rssical(struct ieee80211_hw *dev, void *data, int len, } } +static void p54_parse_default_country(struct ieee80211_hw *dev, + void *data, int len) +{ + struct pda_country *country; + + if (len != sizeof(*country)) { + printk(KERN_ERR "%s: found possible invalid default country " + "eeprom entry. (entry size: %d)\n", + wiphy_name(dev->wiphy), len); + + print_hex_dump_bytes("country:", DUMP_PREFIX_NONE, + data, len); + + printk(KERN_ERR "%s: please report this issue.\n", + wiphy_name(dev->wiphy)); + return; + } + + country = (struct pda_country *) data; + if (country->flags == PDR_COUNTRY_CERT_CODE_PSEUDO) + regulatory_hint(dev->wiphy, country->alpha2); + else { + /* TODO: + * write a shared/common function that converts + * "Regulatory domain codes" (802.11-2007 14.8.2.2) + * into ISO/IEC 3166-1 alpha2 for regulatory_hint. + */ + } +} + static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) { struct p54_common *priv = dev->priv; @@ -463,6 +493,9 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) memcpy(priv->iq_autocal, entry->data, data_len); priv->iq_autocal_len = data_len / sizeof(struct pda_iq_autocal_entry); break; + case PDR_DEFAULT_COUNTRY: + p54_parse_default_country(dev, entry->data, data_len); + break; case PDR_INTERFACE_LIST: tmp = entry->data; while ((u8 *)tmp < entry->data + data_len) { @@ -497,7 +530,6 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) case PDR_UTF8_OEM_NAME: case PDR_UTF8_PRODUCT_NAME: case PDR_COUNTRY_LIST: - case PDR_DEFAULT_COUNTRY: case PDR_ANTENNA_GAIN: case PDR_PRISM_INDIGO_PA_CALIBRATION_DATA: case PDR_REGULATORY_POWER_LIMITS: diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h index 514f660d0be..163e3adba42 100644 --- a/drivers/net/wireless/p54/p54common.h +++ b/drivers/net/wireless/p54/p54common.h @@ -180,6 +180,12 @@ struct pda_rssi_cal_entry { __le16 add; } __attribute__ ((packed)); +struct pda_country { + u8 regdomain; + u8 alpha2[2]; + u8 flags; +} __attribute__ ((packed)); + /* * this defines the PDR codes used to build PDAs as defined in document * number 553155. The current implementation mirrors version 1.1 of the -- GitLab From c557289cb8ea063bd09db88f8a687a841556e291 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 27 Dec 2008 18:26:39 +0100 Subject: [PATCH 0768/4982] b43: Change schedule for old-fw support removal The scheduled date for the removal of old fw support was in July 2008. However, we're not going to remove the support unless it causes a major headache. So change the schedule from "July 2008" to "when it causes headaches". Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- Documentation/feature-removal-schedule.txt | 4 +++- drivers/net/wireless/b43/main.c | 10 +++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 5ddbe350487..ac98851f7a0 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -229,7 +229,9 @@ Who: Jan Engelhardt --------------------------- What: b43 support for firmware revision < 410 -When: July 2008 +When: The schedule was July 2008, but it was decided that we are going to keep the + code as long as there are no major maintanance headaches. + So it _could_ be removed _any_ time now, if it conflicts with something new. Why: The support code for the old firmware hurts code readability/maintainability and slightly hurts runtime performance. Bugfixes for the old firmware are not provided by Broadcom anymore. diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index c627bac87a4..5ca55dcd034 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1954,8 +1954,9 @@ static void b43_print_fw_helptext(struct b43_wl *wl, bool error) const char *text; text = "You must go to " - "http://linuxwireless.org/en/users/Drivers/b43#devicefirmware " - "and download the latest firmware (version 4).\n"; + "http://wireless.kernel.org/en/users/Drivers/b43#devicefirmware " + "and download the correct firmware for this driver version. " + "Please carefully read all instructions on this website.\n"; if (error) b43err(wl, text); else @@ -2271,8 +2272,11 @@ static int b43_upload_microcode(struct b43_wldev *dev) } if (b43_is_old_txhdr_format(dev)) { + /* We're over the deadline, but we keep support for old fw + * until it turns out to be in major conflict with something new. */ b43warn(dev->wl, "You are using an old firmware image. " - "Support for old firmware will be removed in July 2008.\n"); + "Support for old firmware will be removed soon " + "(official deadline was July 2008).\n"); b43_print_fw_helptext(dev->wl, 0); } -- GitLab From b3093664c931aa06fc50da42e25b3b6dc307a915 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 29 Dec 2008 10:02:48 +0200 Subject: [PATCH 0769/4982] mac80211: make wake/stop_queue_by_reason() functions static Fixes sparse warnings: net/mac80211/util.c:355:6: warning: symbol 'ieee80211_wake_queue_by_reason' was not declared. Should it be static? net/mac80211/util.c:385:6: warning: symbol 'ieee80211_stop_queue_by_reason' was not declared. Should it be static? Thanks to Johannes Berg for reporting this. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- net/mac80211/util.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index fb89e1d0aa0..5cd430333f0 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -352,8 +352,8 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, } } -void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, - enum queue_stop_reason reason) +static void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, + enum queue_stop_reason reason) { struct ieee80211_local *local = hw_to_local(hw); unsigned long flags; @@ -382,8 +382,8 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, netif_stop_subqueue(local->mdev, queue); } -void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, - enum queue_stop_reason reason) +static void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, + enum queue_stop_reason reason) { struct ieee80211_local *local = hw_to_local(hw); unsigned long flags; -- GitLab From dc822b5db479dc0178d5c04cbb656dad0b6564fb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 29 Dec 2008 12:55:09 +0100 Subject: [PATCH 0770/4982] mac80211: clean up set_key callback The set_key callback now seems rather odd, passing a MAC address instead of a station struct, and a local address instead of a vif struct. Change that. Signed-off-by: Johannes Berg Acked-by: Bob Copeland [ath5k] Acked-by: Ivo van Doorn [rt2x00] Acked-by: Christian Lamparter [p54] Tested-by: Kalle Valo [iwl3945] Tested-by: Samuel Ortiz [iwl3945] Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 9 ++-- drivers/net/wireless/ath5k/pcu.c | 2 +- drivers/net/wireless/ath9k/main.c | 18 +++++--- drivers/net/wireless/b43/main.c | 13 ++++-- drivers/net/wireless/iwlwifi/iwl-agn.c | 10 ++-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 12 +++-- drivers/net/wireless/p54/p54common.c | 6 +-- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- drivers/net/wireless/rt2x00/rt2x00mac.c | 29 +++++------- include/net/mac80211.h | 20 ++++---- net/mac80211/key.c | 51 ++++++++++----------- 11 files changed, 89 insertions(+), 83 deletions(-) diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 8ef87356e08..88618645a7e 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -232,7 +232,7 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, int mc_count, struct dev_mc_list *mclist); static int ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - const u8 *local_addr, const u8 *addr, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key); static int ath5k_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats); @@ -2991,8 +2991,8 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, static int ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - const u8 *local_addr, const u8 *addr, - struct ieee80211_key_conf *key) + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) { struct ath5k_softc *sc = hw->priv; int ret = 0; @@ -3015,7 +3015,8 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, switch (cmd) { case SET_KEY: - ret = ath5k_hw_set_key(sc->ah, key->keyidx, key, addr); + ret = ath5k_hw_set_key(sc->ah, key->keyidx, key, + sta ? sta->addr : NULL); if (ret) { ATH5K_ERR(sc, "can't set the key\n"); goto unlock; diff --git a/drivers/net/wireless/ath5k/pcu.c b/drivers/net/wireless/ath5k/pcu.c index 75eb9f43c74..5b416ed6529 100644 --- a/drivers/net/wireless/ath5k/pcu.c +++ b/drivers/net/wireless/ath5k/pcu.c @@ -1139,7 +1139,7 @@ int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac) /* MAC may be NULL if it's a broadcast key. In this case no need to * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */ - if (unlikely(mac == NULL)) { + if (!mac) { low_id = 0xffffffff; high_id = 0xffff | AR5K_KEYTABLE_VALID; } else { diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 5cbda924556..a4046a97c01 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -794,7 +794,7 @@ static int ath_reserve_key_cache_slot(struct ath_softc *sc) } static int ath_key_config(struct ath_softc *sc, - const u8 *addr, + struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { struct ath9k_keyval hk; @@ -828,7 +828,10 @@ static int ath_key_config(struct ath_softc *sc, } else if (key->keyidx) { struct ieee80211_vif *vif; - mac = addr; + if (WARN_ON(!sta)) + return -EOPNOTSUPP; + mac = sta->addr; + vif = sc->sc_vaps[0]; if (vif->type != NL80211_IFTYPE_AP) { /* Only keyidx 0 should be used with unicast key, but @@ -837,7 +840,10 @@ static int ath_key_config(struct ath_softc *sc, } else return -EIO; } else { - mac = addr; + if (WARN_ON(!sta)) + return -EOPNOTSUPP; + mac = sta->addr; + if (key->alg == ALG_TKIP) idx = ath_reserve_key_cache_slot_tkip(sc); else @@ -2320,8 +2326,8 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, static int ath9k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - const u8 *local_addr, - const u8 *addr, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { struct ath_softc *sc = hw->priv; @@ -2331,7 +2337,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, switch (cmd) { case SET_KEY: - ret = ath_key_config(sc, addr, key); + ret = ath_key_config(sc, sta, key); if (ret >= 0) { key->hw_key_idx = ret; /* push IV and Michael MIC generation to stack */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 5ca55dcd034..19ad5164fce 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3476,8 +3476,8 @@ out_unlock_mutex: } static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - const u8 *local_addr, const u8 *addr, - struct ieee80211_key_conf *key) + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) { struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev; @@ -3542,9 +3542,14 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, } if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { + if (WARN_ON(!sta)) { + err = -EOPNOTSUPP; + goto out_unlock; + } /* Pairwise key with an assigned MAC address. */ err = b43_key_write(dev, -1, algorithm, - key->key, key->keylen, addr, key); + key->key, key->keylen, + sta->addr, key); } else { /* Group key */ err = b43_key_write(dev, index, algorithm, @@ -3577,7 +3582,7 @@ out_unlock: b43dbg(wl, "%s hardware based encryption for keyidx: %d, " "mac: %pM\n", cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, - addr); + sta ? sta->addr : ""); b43_dump_keymemory(dev); } write_unlock(&wl->tx_lock); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index f3f6dba7a67..dbfee28107a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3021,13 +3021,17 @@ static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, } static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - const u8 *local_addr, const u8 *addr, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { struct iwl_priv *priv = hw->priv; int ret = 0; u8 sta_id = IWL_INVALID_STATION; u8 is_default_wep_key = 0; + static const u8 bcast_addr[ETH_ALEN] = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; + static const u8 *addr; IWL_DEBUG_MAC80211("enter\n"); @@ -3036,9 +3040,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } - if (is_zero_ether_addr(addr)) - /* only support pairwise keys */ - return -EOPNOTSUPP; + addr = sta ? sta->addr : bcast_addr; sta_id = iwl_find_station(priv, addr); if (sta_id == IWL_INVALID_STATION) { diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index a176f42fd7c..43cfc6ec516 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -6546,12 +6546,16 @@ out_unlock: } static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - const u8 *local_addr, const u8 *addr, - struct ieee80211_key_conf *key) + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) { struct iwl_priv *priv = hw->priv; + const u8 *addr; int rc = 0; u8 sta_id; + static const u8 bcast_addr[ETH_ALEN] = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; IWL_DEBUG_MAC80211("enter\n"); @@ -6560,9 +6564,7 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } - if (is_zero_ether_addr(addr)) - /* only support pairwise keys */ - return -EOPNOTSUPP; + addr = sta ? sta->addr : bcast_addr; sta_id = iwl3945_hw_find_station(priv, addr); if (sta_id == IWL_INVALID_STATION) { diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 8d2df5b6ecb..0907e6f246e 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -2127,7 +2127,7 @@ static void p54_bss_info_changed(struct ieee80211_hw *dev, } static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, - const u8 *local_address, const u8 *address, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { struct p54_common *priv = dev->priv; @@ -2191,8 +2191,8 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, rxkey->entry = key->keyidx; rxkey->key_id = key->keyidx; rxkey->key_type = algo; - if (address) - memcpy(rxkey->mac, address, ETH_ALEN); + if (sta) + memcpy(rxkey->mac, sta->addr, ETH_ALEN); else memset(rxkey->mac, ~0, ETH_ALEN); if (key->alg != ALG_TKIP) { diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 1ef3434a2ba..890c7216cf3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -931,7 +931,7 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw, int mc_count, struct dev_addr_list *mc_list); #ifdef CONFIG_RT2X00_LIB_CRYPTO int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - const u8 *local_address, const u8 *address, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key); #else #define rt2x00mac_set_key NULL diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index bf7755a2164..3e204406f44 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -502,15 +502,17 @@ static void memcpy_tkip(struct rt2x00lib_crypto *crypto, u8 *key, u8 key_len) } int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - const u8 *local_address, const u8 *address, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct ieee80211_sta *sta; + struct rt2x00_intf *intf = vif_to_intf(vif); int (*set_key) (struct rt2x00_dev *rt2x00dev, struct rt2x00lib_crypto *crypto, struct ieee80211_key_conf *key); struct rt2x00lib_crypto crypto; + static const u8 bcast_addr[ETH_ALEN] = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) return 0; @@ -528,32 +530,25 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (rt2x00dev->intf_sta_count) crypto.bssidx = 0; else - crypto.bssidx = - local_address[5] & (rt2x00dev->ops->max_ap_intf - 1); + crypto.bssidx = intf->mac[5] & (rt2x00dev->ops->max_ap_intf - 1); crypto.cipher = rt2x00crypto_key_to_cipher(key); if (crypto.cipher == CIPHER_NONE) return -EOPNOTSUPP; crypto.cmd = cmd; - crypto.address = address; + + if (sta) { + /* some drivers need the AID */ + crypto.aid = sta->aid; + crypto.address = sta->addr; + } else + crypto.address = bcast_addr; if (crypto.cipher == CIPHER_TKIP) memcpy_tkip(&crypto, &key->key[0], key->keylen); else memcpy(&crypto.key, &key->key[0], key->keylen); - - /* - * Discover the Association ID from mac80211. - * Some drivers need this information when updating the - * hardware key (either adding or removing). - */ - rcu_read_lock(); - sta = ieee80211_find_sta(hw, address); - if (sta) - crypto.aid = sta->aid; - rcu_read_unlock(); - /* * Each BSS has a maximum of 4 shared keys. * Shared key index values: diff --git a/include/net/mac80211.h b/include/net/mac80211.h index ffcbd12775a..9215b1ec90e 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -715,8 +715,8 @@ enum ieee80211_key_flags { * - Temporal Encryption Key (128 bits) * - Temporal Authenticator Tx MIC Key (64 bits) * - Temporal Authenticator Rx MIC Key (64 bits) - * @icv_len: FIXME - * @iv_len: FIXME + * @icv_len: The ICV length for this key type + * @iv_len: The IV length for this key type */ struct ieee80211_key_conf { enum ieee80211_key_alg alg; @@ -1019,16 +1019,12 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, * * The set_key() callback in the &struct ieee80211_ops for a given * device is called to enable hardware acceleration of encryption and - * decryption. The callback takes an @address parameter that will be - * the broadcast address for default keys, the other station's hardware - * address for individual keys or the zero address for keys that will - * be used only for transmission. + * decryption. The callback takes a @sta parameter that will be NULL + * for default keys or keys used for transmission only, or point to + * the station information for the peer for individual keys. * Multiple transmission keys with the same key index may be used when * VLANs are configured for an access point. * - * The @local_address parameter will always be set to our own address, - * this is only relevant if you support multiple local addresses. - * * When transmitting, the TX control data will use the @hw_key_idx * selected by the driver by modifying the &struct ieee80211_key_conf * pointed to by the @key parameter to the set_key() function. @@ -1233,8 +1229,8 @@ enum ieee80211_ampdu_mlme_action { * * @set_key: See the section "Hardware crypto acceleration" * This callback can sleep, and is only called between add_interface - * and remove_interface calls, i.e. while the interface with the - * given local_address is enabled. + * and remove_interface calls, i.e. while the given virtual interface + * is enabled. * * @update_tkip_key: See the section "Hardware crypto acceleration" * This callback will be called in the context of Rx. Called for drivers @@ -1311,7 +1307,7 @@ struct ieee80211_ops { int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set); int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd, - const u8 *local_address, const u8 *address, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key); void (*update_tkip_key)(struct ieee80211_hw *hw, struct ieee80211_key_conf *conf, const u8 *address, diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 999f7aa4232..b0a025c9b61 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -47,7 +47,6 @@ */ static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; -static const u8 zero_addr[ETH_ALEN]; /* key mutex: used to synchronise todo runners */ static DEFINE_MUTEX(key_mutex); @@ -108,29 +107,18 @@ static void assert_key_lock(void) WARN_ON(!mutex_is_locked(&key_mutex)); } -static const u8 *get_mac_for_key(struct ieee80211_key *key) +static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key) { - const u8 *addr = bcast_addr; - - /* - * If we're an AP we won't ever receive frames with a non-WEP - * group key so we tell the driver that by using the zero MAC - * address to indicate a transmit-only key. - */ - if (key->conf.alg != ALG_WEP && - (key->sdata->vif.type == NL80211_IFTYPE_AP || - key->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) - addr = zero_addr; - if (key->sta) - addr = key->sta->sta.addr; + return &key->sta->sta; - return addr; + return NULL; } static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) { - const u8 *addr; + struct ieee80211_sub_if_data *sdata; + struct ieee80211_sta *sta; int ret; assert_key_lock(); @@ -139,11 +127,16 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) if (!key->local->ops->set_key) return; - addr = get_mac_for_key(key); + sta = get_sta_for_key(key); + + sdata = key->sdata; + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + sdata = container_of(sdata->bss, + struct ieee80211_sub_if_data, + u.ap); ret = key->local->ops->set_key(local_to_hw(key->local), SET_KEY, - key->sdata->dev->dev_addr, addr, - &key->conf); + &sdata->vif, sta, &key->conf); if (!ret) { spin_lock(&todo_lock); @@ -155,12 +148,13 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) printk(KERN_ERR "mac80211-%s: failed to set key " "(%d, %pM) to hardware (%d)\n", wiphy_name(key->local->hw.wiphy), - key->conf.keyidx, addr, ret); + key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); } static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) { - const u8 *addr; + struct ieee80211_sub_if_data *sdata; + struct ieee80211_sta *sta; int ret; assert_key_lock(); @@ -176,17 +170,22 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) } spin_unlock(&todo_lock); - addr = get_mac_for_key(key); + sta = get_sta_for_key(key); + sdata = key->sdata; + + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + sdata = container_of(sdata->bss, + struct ieee80211_sub_if_data, + u.ap); ret = key->local->ops->set_key(local_to_hw(key->local), DISABLE_KEY, - key->sdata->dev->dev_addr, addr, - &key->conf); + &sdata->vif, sta, &key->conf); if (ret) printk(KERN_ERR "mac80211-%s: failed to remove key " "(%d, %pM) from hardware (%d)\n", wiphy_name(key->local->hw.wiphy), - key->conf.keyidx, addr, ret); + key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); spin_lock(&todo_lock); key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; -- GitLab From 295834fe3605fd50265399c266fe0a5ccc76edc8 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 29 Dec 2008 21:07:42 +0100 Subject: [PATCH 0771/4982] ath9k: use signed format to print HAL status Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index a4046a97c01..9c1fb96acc5 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1342,7 +1342,7 @@ static int ath_init(u16 devid, struct ath_softc *sc) ah = ath9k_hw_attach(devid, sc, sc->mem, &status); if (ah == NULL) { DPRINTF(sc, ATH_DBG_FATAL, - "Unable to attach hardware; HAL status %u\n", status); + "Unable to attach hardware; HAL status %d\n", status); error = -ENXIO; goto bad; } -- GitLab From 78eb7484fadddd2860d4503b3c8c1710c1bfa1b3 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 30 Dec 2008 13:48:19 +0100 Subject: [PATCH 0772/4982] p54: enable rx/tx antenna diversity by eeprom bits Respect all documented bits in the eeprom about the device diversity features. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54.h | 2 ++ drivers/net/wireless/p54/p54common.c | 10 +++++++--- drivers/net/wireless/p54/p54common.h | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index ab79e32f0b2..6bd147c47ae 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -99,6 +99,8 @@ struct p54_common { struct mutex conf_mutex; u8 mac_addr[ETH_ALEN]; u8 bssid[ETH_ALEN]; + u8 rx_diversity_mask; + u8 tx_diversity_mask; struct pda_iq_autocal_entry *iq_autocal; unsigned int iq_autocal_len; struct pda_channel_output_limit *output_limit; diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 0907e6f246e..6e9f73745b6 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -563,6 +563,10 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz; if (!(synth & PDR_SYNTH_5_GHZ_DISABLED)) dev->wiphy->bands[IEEE80211_BAND_5GHZ] = &band_5GHz; + if ((synth & PDR_SYNTH_RX_DIV_MASK) == PDR_SYNTH_RX_DIV_SUPPORTED) + priv->rx_diversity_mask = 3; + if ((synth & PDR_SYNTH_TX_DIV_MASK) == PDR_SYNTH_TX_DIV_SUPPORTED) + priv->tx_diversity_mask = 3; if (!is_valid_ether_addr(dev->wiphy->perm_addr)) { u8 perm_addr[ETH_ALEN]; @@ -1512,8 +1516,8 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) txhdr->hw_queue = queue; txhdr->backlog = current_queue->len; memset(txhdr->durations, 0, sizeof(txhdr->durations)); - txhdr->tx_antenna = (info->antenna_sel_tx == 0) ? - 2 : info->antenna_sel_tx - 1; + txhdr->tx_antenna = ((info->antenna_sel_tx == 0) ? + 2 : info->antenna_sel_tx - 1) & priv->tx_diversity_mask; txhdr->output_power = priv->output_power; txhdr->cts_rate = cts_rate; if (padding) @@ -1584,7 +1588,7 @@ static int p54_setup_mac(struct ieee80211_hw *dev) setup->mac_mode = cpu_to_le16(mode); memcpy(setup->mac_addr, priv->mac_addr, ETH_ALEN); memcpy(setup->bssid, priv->bssid, ETH_ALEN); - setup->rx_antenna = 2; /* automatic */ + setup->rx_antenna = 2 & priv->rx_diversity_mask; /* automatic */ setup->rx_align = 0; if (priv->fw_var < 0x500) { setup->v1.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h index 163e3adba42..035e7731248 100644 --- a/drivers/net/wireless/p54/p54common.h +++ b/drivers/net/wireless/p54/p54common.h @@ -31,7 +31,7 @@ struct bootrec { #define PDR_SYNTH_IQ_CAL_DISABLED 0x0008 #define PDR_SYNTH_IQ_CAL_ZIF 0x0010 #define PDR_SYNTH_FAA_SWITCH_MASK 0x0020 -#define PDR_SYNTH_FAA_SWITCH_ENABLED 0x0001 +#define PDR_SYNTH_FAA_SWITCH_ENABLED 0x0020 #define PDR_SYNTH_24_GHZ_MASK 0x0040 #define PDR_SYNTH_24_GHZ_DISABLED 0x0040 #define PDR_SYNTH_5_GHZ_MASK 0x0080 -- GitLab From 51eed9923d98477e7f7473edd60d876d1cecc8c5 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 30 Dec 2008 13:48:29 +0100 Subject: [PATCH 0773/4982] p54: implement FIF_OTHER_BSS filter setting According to STMicroelectronics' LMAC documentation, the P54_FILTER_TYPE_TRANSPARENT flag "configures the receive frame filter to pass all frames without regard to type and address matching." Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 6e9f73745b6..d85a6bafd79 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -1579,7 +1579,8 @@ static int p54_setup_mac(struct ieee80211_hw *dev) * "TRANSPARENT and PROMISCUOUS are mutually exclusive" * STSW45X0C LMAC API - page 12 */ - if ((priv->filter_flags & FIF_PROMISC_IN_BSS) && + if (((priv->filter_flags & FIF_PROMISC_IN_BSS) || + (priv->filter_flags & FIF_OTHER_BSS)) && (mode != P54_FILTER_TYPE_PROMISCUOUS)) mode |= P54_FILTER_TYPE_TRANSPARENT; } else @@ -2007,12 +2008,13 @@ static void p54_configure_filter(struct ieee80211_hw *dev, struct p54_common *priv = dev->priv; *total_flags &= FIF_PROMISC_IN_BSS | + FIF_OTHER_BSS | (*total_flags & FIF_PROMISC_IN_BSS) ? FIF_FCSFAIL : 0; priv->filter_flags = *total_flags; - if (changed_flags & FIF_PROMISC_IN_BSS) + if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) p54_setup_mac(dev); } -- GitLab From 2b8d4e2eea711b6dfe1878ff3c94ebe757656f6d Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 30 Dec 2008 13:48:41 +0100 Subject: [PATCH 0774/4982] p54: power save management This patch implements dynamic power save feature for p54. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 42 ++++++++++++++++++++++++++++ drivers/net/wireless/p54/p54common.h | 1 + 2 files changed, 43 insertions(+) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index d85a6bafd79..6c175df48b0 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -1765,6 +1765,43 @@ static int p54_set_edcf(struct ieee80211_hw *dev) return 0; } +static int p54_set_ps(struct ieee80211_hw *dev) +{ + struct p54_common *priv = dev->priv; + struct sk_buff *skb; + struct p54_psm *psm; + u16 mode; + int i; + + if (dev->conf.flags & IEEE80211_CONF_PS) + mode = cpu_to_le16(P54_PSM | P54_PSM_DTIM | P54_PSM_MCBC); + else + mode = P54_PSM_CAM; + + skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*psm) + + sizeof(struct p54_hdr), P54_CONTROL_TYPE_PSM, + GFP_ATOMIC); + if (!skb) + return -ENOMEM; + + psm = (struct p54_psm *)skb_put(skb, sizeof(*psm)); + psm->mode = cpu_to_le16(mode); + psm->aid = cpu_to_le16(priv->aid); + for (i = 0; i < ARRAY_SIZE(psm->intervals); i++) { + psm->intervals[i].interval = + cpu_to_le16(dev->conf.listen_interval); + psm->intervals[i].periods = 1; + } + + psm->beacon_rssi_skip_max = 60; + psm->rssi_delta_threshold = 0; + psm->nr = 0; + + priv->tx(dev, skb); + + return 0; +} + static int p54_beacon_tim(struct sk_buff *skb) { /* @@ -1957,6 +1994,11 @@ static int p54_config(struct ieee80211_hw *dev, u32 changed) if (ret) goto out; } + if (changed & IEEE80211_CONF_CHANGE_PS) { + ret = p54_set_ps(dev); + if (ret) + goto out; + } out: mutex_unlock(&priv->conf_mutex); diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h index 035e7731248..6207323848b 100644 --- a/drivers/net/wireless/p54/p54common.h +++ b/drivers/net/wireless/p54/p54common.h @@ -534,6 +534,7 @@ struct p54_psm_interval { __le16 periods; } __attribute__ ((packed)); +#define P54_PSM_CAM 0 #define P54_PSM BIT(0) #define P54_PSM_DTIM BIT(1) #define P54_PSM_MCBC BIT(2) -- GitLab From 63649b6cf0a964582af2b4d4734e28ca90ec8f5c Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Thu, 1 Jan 2009 15:01:44 -0500 Subject: [PATCH 0775/4982] ath5k: support LEDs on Acer Aspire One netbook Add vendor ID for Foxconn and use it to set the ath5k LED gpio and polarity for Acer branded laptops. base.c: Changes-licensed-under: 3-Clause-BSD Reported-by: Maxim Levitsky Tested-by: Maxim Levitsky Tested-by: Andreas Mohr Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 7 +++++++ include/linux/pci_ids.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 88618645a7e..fdf7733e76e 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -2596,6 +2596,13 @@ ath5k_init_leds(struct ath5k_softc *sc) sc->led_pin = 1; sc->led_on = 1; /* active high */ } + /* Pin 3 on Foxconn chips used in Acer Aspire One (0x105b:e008) */ + if (pdev->subsystem_vendor == PCI_VENDOR_ID_FOXCONN) { + __set_bit(ATH_STAT_LEDSOFT, sc->status); + sc->led_pin = 3; + sc->led_on = 0; /* active low */ + } + if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) goto out; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 302423afa13..5b7a48c1d61 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -834,6 +834,8 @@ #define PCI_DEVICE_ID_PROMISE_20276 0x5275 #define PCI_DEVICE_ID_PROMISE_20277 0x7275 +#define PCI_VENDOR_ID_FOXCONN 0x105b + #define PCI_VENDOR_ID_UMC 0x1060 #define PCI_DEVICE_ID_UMC_UM8673F 0x0101 #define PCI_DEVICE_ID_UMC_UM8886BF 0x673a -- GitLab From 7d969204882882585336b0fa19ad4587d8fb15a2 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Thu, 1 Jan 2009 15:01:45 -0500 Subject: [PATCH 0776/4982] ath5k: fix off-by-one in gpio checks Sanity checks against AR5K_NUM_GPIO were all broken. This doesn't currently cause any problems since we only use the first four gpios. Changes-licensed-under: ISC Reported-by: Andreas Mohr Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/gpio.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath5k/gpio.c b/drivers/net/wireless/ath5k/gpio.c index b77205adc18..64a27e73d02 100644 --- a/drivers/net/wireless/ath5k/gpio.c +++ b/drivers/net/wireless/ath5k/gpio.c @@ -83,7 +83,7 @@ void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state) int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) { ATH5K_TRACE(ah->ah_sc); - if (gpio > AR5K_NUM_GPIO) + if (gpio >= AR5K_NUM_GPIO) return -EINVAL; ath5k_hw_reg_write(ah, @@ -99,7 +99,7 @@ int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) { ATH5K_TRACE(ah->ah_sc); - if (gpio > AR5K_NUM_GPIO) + if (gpio >= AR5K_NUM_GPIO) return -EINVAL; ath5k_hw_reg_write(ah, @@ -115,7 +115,7 @@ int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio) { ATH5K_TRACE(ah->ah_sc); - if (gpio > AR5K_NUM_GPIO) + if (gpio >= AR5K_NUM_GPIO) return 0xffffffff; /* GPIO input magic */ @@ -131,7 +131,7 @@ int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val) u32 data; ATH5K_TRACE(ah->ah_sc); - if (gpio > AR5K_NUM_GPIO) + if (gpio >= AR5K_NUM_GPIO) return -EINVAL; /* GPIO output magic */ @@ -154,7 +154,7 @@ void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 data; ATH5K_TRACE(ah->ah_sc); - if (gpio > AR5K_NUM_GPIO) + if (gpio >= AR5K_NUM_GPIO) return; /* -- GitLab From c97c92d92715ea4ea2d7cf00957e8a014439bdd8 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Fri, 2 Jan 2009 15:35:46 +0530 Subject: [PATCH 0777/4982] ath9k: Enable Bluetooth Coexistence support Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ath9k.h | 5 +++++ drivers/net/wireless/ath9k/hw.c | 33 ++++++++++++++++++++++++++++++ drivers/net/wireless/ath9k/main.c | 9 ++++++-- drivers/net/wireless/ath9k/reg.h | 10 +++++++++ 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index adcd34249a8..f2ad62536bf 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -198,6 +198,7 @@ enum ath9k_hw_caps { ATH9K_HW_CAP_AUTOSLEEP = BIT(19), ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(20), ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT = BIT(21), + ATH9K_HW_CAP_BT_COEX = BIT(22) }; enum ath9k_capability_type { @@ -752,6 +753,7 @@ struct ath9k_node_stats { #define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0 #define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1 #define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2 +#define AR_GPIO_OUTPUT_MUX_AS_TX_FRAME 3 #define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5 #define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6 @@ -801,6 +803,8 @@ struct ath_hal { u16 ah_rfsilent; u32 ah_rfkill_gpio; u32 ah_rfkill_polarity; + u32 ah_btactive_gpio; + u32 ah_wlanactive_gpio; #ifndef ATH_NF_PER_CHAN struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; @@ -1050,5 +1054,6 @@ void ath9k_hw_rxena(struct ath_hal *ah); void ath9k_hw_startpcureceive(struct ath_hal *ah); void ath9k_hw_stoppcurecv(struct ath_hal *ah); bool ath9k_hw_stopdmarecv(struct ath_hal *ah); +void ath9k_hw_btcoex_enable(struct ath_hal *ah); #endif diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 19144caa797..3c026e6b245 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -3341,6 +3341,12 @@ bool ath9k_hw_fill_cap_info(struct ath_hal *ah) pCap->num_antcfg_2ghz = ath9k_hw_get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ); + if (AR_SREV_9280_10_OR_LATER(ah)) { + pCap->hw_caps |= ATH9K_HW_CAP_BT_COEX; + ah->ah_btactive_gpio = 6; + ah->ah_wlanactive_gpio = 5; + } + return true; } @@ -3836,3 +3842,30 @@ void ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode) REG_WRITE(ah, AR_2040_MODE, macmode); } + +/***************************/ +/* Bluetooth Coexistence */ +/***************************/ + +void ath9k_hw_btcoex_enable(struct ath_hal *ah) +{ + /* connect bt_active to baseband */ + REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL, + (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF | + AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF)); + + REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, + AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB); + + /* Set input mux for bt_active to gpio pin */ + REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, + AR_GPIO_INPUT_MUX1_BT_ACTIVE, + ah->ah_btactive_gpio); + + /* Configure the desired gpio port for input */ + ath9k_hw_cfg_gpio_input(ah, ah->ah_btactive_gpio); + + /* Configure the desired GPIO port for TX_FRAME output */ + ath9k_hw_cfg_output(ah, ah->ah_wlanactive_gpio, + AR_GPIO_OUTPUT_MUX_AS_TX_FRAME); +} diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 9c1fb96acc5..8929b02aa22 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -431,12 +431,14 @@ static void ath_ani_calibrate(unsigned long data) /* * Update tx/rx chainmask. For legacy association, * hard code chainmask to 1x1, for 11n association, use - * the chainmask configuration. + * the chainmask configuration, for bt coexistence, use + * the chainmask configuration even in legacy mode. */ static void ath_update_chainmask(struct ath_softc *sc, int is_ht) { sc->sc_flags |= SC_OP_CHAINMASK_UPDATE; - if (is_ht) { + if (is_ht || + (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_BT_COEX)) { sc->sc_tx_chainmask = sc->sc_ah->ah_caps.tx_chainmask; sc->sc_rx_chainmask = sc->sc_ah->ah_caps.rx_chainmask; } else { @@ -1519,6 +1521,9 @@ static int ath_init(u16 devid, struct ath_softc *sc) sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; } + if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_BT_COEX) + ath9k_hw_btcoex_enable(sc->sc_ah); + return 0; bad2: /* cleanup tx queues */ diff --git a/drivers/net/wireless/ath9k/reg.h b/drivers/net/wireless/ath9k/reg.h index 8cc9beff5ec..9a615224e4f 100644 --- a/drivers/net/wireless/ath9k/reg.h +++ b/drivers/net/wireless/ath9k/reg.h @@ -897,14 +897,24 @@ enum { #define AR_GPIO_INTR_POL_VAL_S 0 #define AR_GPIO_INPUT_EN_VAL 0x4054 +#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF 0x00000004 +#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_S 2 +#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF 0x00000008 +#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_S 3 +#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_DEF 0x00000010 +#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_S 4 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF 0x00000080 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S 7 +#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB 0x00001000 +#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB_S 12 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB 0x00008000 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S 15 #define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000 #define AR_GPIO_JTAG_DISABLE 0x00020000 #define AR_GPIO_INPUT_MUX1 0x4058 +#define AR_GPIO_INPUT_MUX1_BT_ACTIVE 0x000f0000 +#define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S 16 #define AR_GPIO_INPUT_MUX2 0x405c #define AR_GPIO_INPUT_MUX2_CLK25 0x0000000f -- GitLab From cca3e99861e883358ceb39ad17c9eaee082138a5 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 3 Jan 2009 19:56:02 +0100 Subject: [PATCH 0778/4982] rt2x00: Replace RFKILL with INPUT As discussed on linux-wireless rt2x00 does not offer a true RFKILL key, for that reason RFKILL support should be entirely removed. The key which is attached to the hardware should be treated as normal input device instead. Implement input_poll_dev support to poll the device frequently. When the key status has changed report it as a SW event. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 7 +- drivers/net/wireless/rt2x00/rt2x00.h | 5 +- drivers/net/wireless/rt2x00/rt2x00lib.h | 2 +- drivers/net/wireless/rt2x00/rt2x00rfkill.c | 122 +++++++-------------- 4 files changed, 46 insertions(+), 90 deletions(-) diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 178b313293b..bfc5d9cf716 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -97,10 +97,11 @@ config RT2X00_LIB_CRYPTO config RT2X00_LIB_RFKILL boolean - default y if (RT2X00_LIB=y && RFKILL=y) || (RT2X00_LIB=m && RFKILL!=n) + default y if (RT2X00_LIB=y && INPUT=y) || (RT2X00_LIB=m && INPUT!=n) + select INPUT_POLLDEV -comment "rt2x00 rfkill support disabled due to modularized RFKILL and built-in rt2x00" - depends on RT2X00_LIB=y && RFKILL=m +comment "rt2x00 rfkill support disabled due to modularized INPUT and built-in rt2x00" + depends on RT2X00_LIB=y && INPUT=m config RT2X00_LIB_LEDS boolean diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 890c7216cf3..27c0f335f40 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -638,8 +639,8 @@ struct rt2x00_dev { unsigned long rfkill_state; #define RFKILL_STATE_ALLOCATED 1 #define RFKILL_STATE_REGISTERED 2 - struct rfkill *rfkill; - struct delayed_work rfkill_work; +#define RFKILL_STATE_BLOCKED 3 + struct input_polled_dev *rfkill_poll_dev; #endif /* CONFIG_RT2X00_LIB_RFKILL */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 5e8df250e50..92918f315ee 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -33,7 +33,7 @@ * Both the link tuner as the rfkill will be called once per second. */ #define LINK_TUNE_INTERVAL ( round_jiffies_relative(HZ) ) -#define RFKILL_POLL_INTERVAL ( round_jiffies_relative(HZ) ) +#define RFKILL_POLL_INTERVAL ( 1000 ) /* * rt2x00_rate: Per rate device information diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c index 3298cae1e12..595efd05ce4 100644 --- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c +++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c @@ -25,73 +25,30 @@ #include #include -#include #include "rt2x00.h" #include "rt2x00lib.h" -static int rt2x00rfkill_toggle_radio(void *data, enum rfkill_state state) +static void rt2x00rfkill_poll(struct input_polled_dev *poll_dev) { - struct rt2x00_dev *rt2x00dev = data; - int retval = 0; - - if (unlikely(!rt2x00dev)) - return 0; - - /* - * Only continue if there are enabled interfaces. - */ - if (!test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) - return 0; - - if (state == RFKILL_STATE_UNBLOCKED) { - INFO(rt2x00dev, "RFKILL event: enabling radio.\n"); - clear_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags); - retval = rt2x00lib_enable_radio(rt2x00dev); - } else if (state == RFKILL_STATE_SOFT_BLOCKED) { - INFO(rt2x00dev, "RFKILL event: disabling radio.\n"); - set_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags); - rt2x00lib_disable_radio(rt2x00dev); - } else { - WARNING(rt2x00dev, "RFKILL event: unknown state %d.\n", state); - } - - return retval; -} - -static int rt2x00rfkill_get_state(void *data, enum rfkill_state *state) -{ - struct rt2x00_dev *rt2x00dev = data; - - /* - * rfkill_poll reports 1 when the key has been pressed and the - * radio should be blocked. - */ - *state = rt2x00dev->ops->lib->rfkill_poll(rt2x00dev) ? - RFKILL_STATE_SOFT_BLOCKED : RFKILL_STATE_UNBLOCKED; - - return 0; -} - -static void rt2x00rfkill_poll(struct work_struct *work) -{ - struct rt2x00_dev *rt2x00dev = - container_of(work, struct rt2x00_dev, rfkill_work.work); - enum rfkill_state state; + struct rt2x00_dev *rt2x00dev = poll_dev->private; + int state, old_state; if (!test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state) || !test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) return; /* - * Poll latest state and report it to rfkill who should sort - * out if the state should be toggled or not. + * Poll latest state, if the state is different then the previous state, + * we should generate an input event. */ - if (!rt2x00rfkill_get_state(rt2x00dev, &state)) - rfkill_force_state(rt2x00dev->rfkill, state); + state = !!rt2x00dev->ops->lib->rfkill_poll(rt2x00dev); + old_state = !!test_bit(RFKILL_STATE_BLOCKED, &rt2x00dev->rfkill_state); - queue_delayed_work(rt2x00dev->hw->workqueue, - &rt2x00dev->rfkill_work, RFKILL_POLL_INTERVAL); + if (old_state != state) { + input_report_switch(poll_dev->input, SW_RFKILL_ALL, state); + change_bit(RFKILL_STATE_BLOCKED, &rt2x00dev->rfkill_state); + } } void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) @@ -100,8 +57,8 @@ void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state)) return; - if (rfkill_register(rt2x00dev->rfkill)) { - ERROR(rt2x00dev, "Failed to register rfkill handler.\n"); + if (input_register_polled_device(rt2x00dev->rfkill_poll_dev)) { + ERROR(rt2x00dev, "Failed to register polled device.\n"); return; } @@ -109,10 +66,10 @@ void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) /* * Force initial poll which will detect the initial device state, - * and correctly sends the signal to the rfkill layer about this + * and correctly sends the signal to the input layer about this * state. */ - rt2x00rfkill_poll(&rt2x00dev->rfkill_work.work); + rt2x00rfkill_poll(rt2x00dev->rfkill_poll_dev); } void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev) @@ -121,52 +78,49 @@ void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev) !test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state)) return; - cancel_delayed_work_sync(&rt2x00dev->rfkill_work); - - rfkill_unregister(rt2x00dev->rfkill); + input_unregister_polled_device(rt2x00dev->rfkill_poll_dev); __clear_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state); } void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev) { - struct device *dev = wiphy_dev(rt2x00dev->hw->wiphy); + struct input_polled_dev *poll_dev; if (test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) return; - rt2x00dev->rfkill = rfkill_allocate(dev, RFKILL_TYPE_WLAN); - if (!rt2x00dev->rfkill) { - ERROR(rt2x00dev, "Failed to allocate rfkill handler.\n"); + poll_dev = input_allocate_polled_device(); + if (!poll_dev) { + ERROR(rt2x00dev, "Failed to allocate polled device.\n"); return; } - __set_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state); + poll_dev->private = rt2x00dev; + poll_dev->poll = rt2x00rfkill_poll; + poll_dev->poll_interval = RFKILL_POLL_INTERVAL; - rt2x00dev->rfkill->name = rt2x00dev->ops->name; - rt2x00dev->rfkill->data = rt2x00dev; - rt2x00dev->rfkill->toggle_radio = rt2x00rfkill_toggle_radio; - if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) { - rt2x00dev->rfkill->get_state = rt2x00rfkill_get_state; - rt2x00dev->rfkill->state = - rt2x00dev->ops->lib->rfkill_poll(rt2x00dev) ? - RFKILL_STATE_SOFT_BLOCKED : RFKILL_STATE_UNBLOCKED; - } else { - rt2x00dev->rfkill->state = RFKILL_STATE_UNBLOCKED; - } + poll_dev->input->name = rt2x00dev->ops->name; + poll_dev->input->phys = wiphy_name(rt2x00dev->hw->wiphy); + poll_dev->input->id.bustype = BUS_HOST; + poll_dev->input->id.vendor = 0x1814; + poll_dev->input->id.product = rt2x00dev->chip.rt; + poll_dev->input->id.version = rt2x00dev->chip.rev; + poll_dev->input->dev.parent = wiphy_dev(rt2x00dev->hw->wiphy); + poll_dev->input->evbit[0] = BIT(EV_SW); + poll_dev->input->swbit[0] = BIT(SW_RFKILL_ALL); - INIT_DELAYED_WORK(&rt2x00dev->rfkill_work, rt2x00rfkill_poll); + rt2x00dev->rfkill_poll_dev = poll_dev; - return; + __set_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state); } void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev) { - if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) + if (!__test_and_clear_bit(RFKILL_STATE_ALLOCATED, + &rt2x00dev->rfkill_state)) return; - cancel_delayed_work_sync(&rt2x00dev->rfkill_work); - - rfkill_free(rt2x00dev->rfkill); - rt2x00dev->rfkill = NULL; + input_free_polled_device(rt2x00dev->rfkill_poll_dev); + rt2x00dev->rfkill_poll_dev = NULL; } -- GitLab From 0efcdfd6ed4e7ac74c45e7c3218fd1a7416fdb3f Mon Sep 17 00:00:00 2001 From: Alina Friedrichsen Date: Tue, 6 Jan 2009 02:41:35 +0100 Subject: [PATCH 0779/4982] mac80211: Disallow to set multicast BSSID Okay, here is the first of the five patches. After applying all of them you should be able to build/join huge city mesh networks (e.g. with the OLSR protocol) with the most of the mac80211 wireless drivers by setting a fixed BSSID in the ad hoc mode. (If you found no other bug/problem.) This was not specified in the original standard, but is a widely used de facto standard. The first patch now completely disallow to set multicast MAC addresses as BSSID. The behavior before was really strange. Signed-off-by: Alina Friedrichsen Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 12976026cc4..f80dc253570 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2548,11 +2548,16 @@ int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid) { struct ieee80211_if_sta *ifsta; int res; + bool valid; ifsta = &sdata->u.sta; + valid = is_valid_ether_addr(bssid); if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { - memcpy(ifsta->bssid, bssid, ETH_ALEN); + if(valid) + memcpy(ifsta->bssid, bssid, ETH_ALEN); + else + memset(ifsta->bssid, 0, ETH_ALEN); res = 0; /* * Hack! See also ieee80211_sta_set_ssid. @@ -2566,7 +2571,7 @@ int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid) } } - if (is_valid_ether_addr(bssid)) + if (valid) ifsta->flags |= IEEE80211_STA_BSSID_SET; else ifsta->flags &= ~IEEE80211_STA_BSSID_SET; -- GitLab From 137f9f46a4edf8a937ffe9e3dba498b5cfaa1e5b Mon Sep 17 00:00:00 2001 From: Alina Friedrichsen Date: Tue, 6 Jan 2009 02:49:07 +0100 Subject: [PATCH 0780/4982] mac80211: Don't scan if BSSID and channel are set manually If you set a fixed BSSID and channel it's not necessary to scan for neighbors to merge, because you really don't want to merge with it. So don't do it. Signed-off-by: Alina Friedrichsen Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f80dc253570..563ceb4d225 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2009,6 +2009,10 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata, if (ieee80211_sta_active_ibss(sdata)) return; + if ((sdata->u.sta.flags & IEEE80211_STA_BSSID_SET) && + (!(sdata->u.sta.flags & IEEE80211_STA_AUTO_CHANNEL_SEL))) + return; + printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " "IBSS networks with same SSID (merge)\n", sdata->dev->name); ieee80211_request_scan(sdata, ifsta->ssid, ifsta->ssid_len); -- GitLab From 65f0e6a36e25fbfa6adf706d9c53bf64b13096eb Mon Sep 17 00:00:00 2001 From: Alina Friedrichsen Date: Tue, 6 Jan 2009 03:08:10 +0100 Subject: [PATCH 0781/4982] mac80211: Don't merge if BSSID is set manually If you set a fixed BSSID manually, you never want that the driver change it back, or your ad-hoc mesh network will break into peaces. So don't do it. Signed-off-by: Alina Friedrichsen Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 563ceb4d225..2db56605a2b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1644,6 +1644,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, /* check if we need to merge IBSS */ if (sdata->vif.type == NL80211_IFTYPE_ADHOC && beacon && + (!(sdata->u.sta.flags & IEEE80211_STA_BSSID_SET)) && bss->capability & WLAN_CAPABILITY_IBSS && bss->freq == local->oper_channel->center_freq && elems->ssid_len == sdata->u.sta.ssid_len && -- GitLab From b522ed56ef90f5078a2a1253e390299723510a89 Mon Sep 17 00:00:00 2001 From: Alina Friedrichsen Date: Tue, 6 Jan 2009 03:15:23 +0100 Subject: [PATCH 0782/4982] mac80211: Allow to set channel in adhoc properly The last patch fixes a bug that it was not possible to set the channel manually in the ad hoc mode properly. Please commit this patches so that we don't need the proprietary Broadcom driver in the near future anymore. Signed-off-by: Alina Friedrichsen Signed-off-by: John W. Linville --- net/mac80211/wext.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 654041b9373..bb2c7135a1c 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -230,13 +230,15 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev, { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type == NL80211_IFTYPE_STATION) + if (sdata->vif.type == NL80211_IFTYPE_ADHOC || + sdata->vif.type == NL80211_IFTYPE_STATION) sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL; /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */ if (freq->e == 0) { if (freq->m < 0) { - if (sdata->vif.type == NL80211_IFTYPE_STATION) + if (sdata->vif.type == NL80211_IFTYPE_ADHOC || + sdata->vif.type == NL80211_IFTYPE_STATION) sdata->u.sta.flags |= IEEE80211_STA_AUTO_CHANNEL_SEL; return 0; -- GitLab From c481ec9705d4a5d566393bc17374cfd82c870715 Mon Sep 17 00:00:00 2001 From: Sujith Date: Tue, 6 Jan 2009 09:28:37 +0530 Subject: [PATCH 0783/4982] mac80211: Add 802.11h CSA support Move to the advertised channel on reception of a CSA element. This is needed for 802.11h compliance. Signed-off-by: Sujith Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 11 +++++- net/mac80211/iface.c | 2 + net/mac80211/mlme.c | 13 +++++++ net/mac80211/rx.c | 20 ++++++++++ net/mac80211/spectmgmt.c | 77 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 122 insertions(+), 1 deletion(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 117718bd96e..d2a007aa8e7 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -259,6 +259,7 @@ struct mesh_preq_queue { #define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12) #define IEEE80211_STA_PRIVACY_INVOKED BIT(13) #define IEEE80211_STA_TKIP_WEP_USED BIT(14) +#define IEEE80211_STA_CSA_RECEIVED BIT(15) /* flags for MLME request */ #define IEEE80211_STA_REQ_SCAN 0 #define IEEE80211_STA_REQ_DIRECT_PROBE 1 @@ -283,7 +284,9 @@ enum ieee80211_sta_mlme_state { struct ieee80211_if_sta { struct timer_list timer; + struct timer_list chswitch_timer; struct work_struct work; + struct work_struct chswitch_work; u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; u8 ssid[IEEE80211_MAX_SSID_LEN]; enum ieee80211_sta_mlme_state state; @@ -542,6 +545,7 @@ enum { enum queue_stop_reason { IEEE80211_QUEUE_STOP_REASON_DRIVER, IEEE80211_QUEUE_STOP_REASON_PS, + IEEE80211_QUEUE_STOP_REASON_CSA }; /* maximum number of hardware queues we support. */ @@ -631,7 +635,7 @@ struct ieee80211_local { unsigned long last_scan_completed; struct delayed_work scan_work; struct ieee80211_sub_if_data *scan_sdata; - struct ieee80211_channel *oper_channel, *scan_channel; + struct ieee80211_channel *oper_channel, *scan_channel, *csa_channel; enum nl80211_channel_type oper_channel_type; u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; size_t scan_ssid_len; @@ -964,6 +968,11 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len); +void ieee80211_chswitch_timer(unsigned long data); +void ieee80211_chswitch_work(struct work_struct *work); +void ieee80211_process_chanswitch(struct ieee80211_sub_if_data *sdata, + struct ieee80211_channel_sw_ie *sw_elem, + struct ieee80211_bss *bss); /* utility functions/constants */ extern void *mac80211_wiphy_privid; /* for wiphy privid */ diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 8e0e3303ca8..5d5a029228b 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -443,6 +443,7 @@ static int ieee80211_stop(struct net_device *dev) WLAN_REASON_DEAUTH_LEAVING); memset(sdata->u.sta.bssid, 0, ETH_ALEN); + del_timer_sync(&sdata->u.sta.chswitch_timer); del_timer_sync(&sdata->u.sta.timer); /* * If the timer fired while we waited for it, it will have @@ -452,6 +453,7 @@ static int ieee80211_stop(struct net_device *dev) * it no longer is. */ cancel_work_sync(&sdata->u.sta.work); + cancel_work_sync(&sdata->u.sta.chswitch_work); /* * When we get here, the interface is marked down. * Call synchronize_rcu() to wait for the RX path diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2db56605a2b..cac4f65d9e6 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1629,6 +1629,13 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, if (!bss) return; + if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) && + (memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0)) { + struct ieee80211_channel_sw_ie *sw_elem = + (struct ieee80211_channel_sw_ie *)elems->ch_switch_elem; + ieee80211_process_chanswitch(sdata, sw_elem, bss); + } + /* was just updated in ieee80211_bss_info_update */ beacon_timestamp = bss->timestamp; @@ -1765,6 +1772,9 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) return; + if (rx_status->freq != local->hw.conf.channel->center_freq) + return; + ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, elems.wmm_param_len); @@ -2425,8 +2435,11 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) ifsta = &sdata->u.sta; INIT_WORK(&ifsta->work, ieee80211_sta_work); + INIT_WORK(&ifsta->chswitch_work, ieee80211_chswitch_work); setup_timer(&ifsta->timer, ieee80211_sta_timer, (unsigned long) sdata); + setup_timer(&ifsta->chswitch_timer, ieee80211_chswitch_timer, + (unsigned long) sdata); skb_queue_head_init(&ifsta->skb_queue); ifsta->capab = WLAN_CAPABILITY_ESS; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 7175ae80c36..ddb966f5888 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1552,7 +1552,9 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) { struct ieee80211_local *local = rx->local; struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); + struct ieee80211_if_sta *ifsta = &sdata->u.sta; struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; + struct ieee80211_bss *bss; int len = rx->skb->len; if (!ieee80211_is_action(mgmt->frame_control)) @@ -1601,6 +1603,24 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) return RX_DROP_MONITOR; ieee80211_process_measurement_req(sdata, mgmt, len); break; + case WLAN_ACTION_SPCT_CHL_SWITCH: + if (len < (IEEE80211_MIN_ACTION_SIZE + + sizeof(mgmt->u.action.u.chan_switch))) + return RX_DROP_MONITOR; + + if (memcmp(mgmt->bssid, ifsta->bssid, ETH_ALEN) != 0) + return RX_DROP_MONITOR; + + bss = ieee80211_rx_bss_get(local, ifsta->bssid, + local->hw.conf.channel->center_freq, + ifsta->ssid, ifsta->ssid_len); + if (!bss) + return RX_DROP_MONITOR; + + ieee80211_process_chanswitch(sdata, + &mgmt->u.action.u.chan_switch.sw_elem, bss); + ieee80211_rx_bss_put(local, bss); + break; } break; default: diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c index f72bad636d8..22ad4808e01 100644 --- a/net/mac80211/spectmgmt.c +++ b/net/mac80211/spectmgmt.c @@ -84,3 +84,80 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, mgmt->sa, mgmt->bssid, mgmt->u.action.u.measurement.dialog_token); } + +void ieee80211_chswitch_work(struct work_struct *work) +{ + struct ieee80211_sub_if_data *sdata = + container_of(work, struct ieee80211_sub_if_data, u.sta.chswitch_work); + struct ieee80211_bss *bss; + struct ieee80211_if_sta *ifsta = &sdata->u.sta; + + if (!netif_running(sdata->dev)) + return; + + bss = ieee80211_rx_bss_get(sdata->local, ifsta->bssid, + sdata->local->hw.conf.channel->center_freq, + ifsta->ssid, ifsta->ssid_len); + if (!bss) + goto exit; + + sdata->local->oper_channel = sdata->local->csa_channel; + if (!ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL)) + bss->freq = sdata->local->oper_channel->center_freq; + + ieee80211_rx_bss_put(sdata->local, bss); +exit: + ifsta->flags &= ~IEEE80211_STA_CSA_RECEIVED; + ieee80211_wake_queues_by_reason(&sdata->local->hw, + IEEE80211_QUEUE_STOP_REASON_CSA); +} + +void ieee80211_chswitch_timer(unsigned long data) +{ + struct ieee80211_sub_if_data *sdata = + (struct ieee80211_sub_if_data *) data; + struct ieee80211_if_sta *ifsta = &sdata->u.sta; + + queue_work(sdata->local->hw.workqueue, &ifsta->chswitch_work); +} + +void ieee80211_process_chanswitch(struct ieee80211_sub_if_data *sdata, + struct ieee80211_channel_sw_ie *sw_elem, + struct ieee80211_bss *bss) +{ + struct ieee80211_channel *new_ch; + struct ieee80211_if_sta *ifsta = &sdata->u.sta; + int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num); + + /* FIXME: Handle ADHOC later */ + if (sdata->vif.type != NL80211_IFTYPE_STATION) + return; + + if (ifsta->state != IEEE80211_STA_MLME_ASSOCIATED) + return; + + if (sdata->local->sw_scanning || sdata->local->hw_scanning) + return; + + /* Disregard subsequent beacons if we are already running a timer + processing a CSA */ + + if (ifsta->flags & IEEE80211_STA_CSA_RECEIVED) + return; + + new_ch = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); + if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED) + return; + + sdata->local->csa_channel = new_ch; + + if (sw_elem->count <= 1) { + queue_work(sdata->local->hw.workqueue, &ifsta->chswitch_work); + } else { + ieee80211_stop_queues_by_reason(&sdata->local->hw, + IEEE80211_QUEUE_STOP_REASON_CSA); + ifsta->flags |= IEEE80211_STA_CSA_RECEIVED; + mod_timer(&ifsta->chswitch_timer, + jiffies + msecs_to_jiffies(sw_elem->count * bss->beacon_int)); + } +} -- GitLab From def1343971b2abd158ece1a71dd1c7a20e4c2fcb Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Tue, 6 Jan 2009 10:50:33 +0200 Subject: [PATCH 0784/4982] mac80211: remove an unnecessary assignment to info in __ieee80211_tx(). This patch removes an unnecessary assignment to info in __ieee80211_tx() , tx.c. Signed-off-by: Rami Rosen Signed-off-by: John W. Linville --- net/mac80211/tx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 0bf2272200a..96eca341160 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1053,7 +1053,6 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, if (skb) { if (netif_subqueue_stopped(local->mdev, skb)) return IEEE80211_TX_AGAIN; - info = IEEE80211_SKB_CB(skb); ret = local->ops->tx(local_to_hw(local), skb); if (ret) -- GitLab From 504a71e4c2718d8ef5dc5bff89dea47a91cf87e5 Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Tue, 6 Jan 2009 10:50:51 +0200 Subject: [PATCH 0785/4982] mac80211: remove an unused parameter in ieee80211_rx_mgmt_probe_req(). This patch removes an unused parameter (rx_status) in ieee80211_rx_mgmt_probe_req(), in mlme.c. Signed-off-by: Rami Rosen Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index cac4f65d9e6..aafa112ae09 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1842,8 +1842,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, - size_t len, - struct ieee80211_rx_status *rx_status) + size_t len) { struct ieee80211_local *local = sdata->local; int tx_last_beacon; @@ -1958,8 +1957,7 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, switch (fc & IEEE80211_FCTL_STYPE) { case IEEE80211_STYPE_PROBE_REQ: - ieee80211_rx_mgmt_probe_req(sdata, ifsta, mgmt, skb->len, - rx_status); + ieee80211_rx_mgmt_probe_req(sdata, ifsta, mgmt, skb->len); break; case IEEE80211_STYPE_PROBE_RESP: ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, rx_status); -- GitLab From 81d963a1f6aeefca5527cc605f863eb82a634eab Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Tue, 6 Jan 2009 10:51:01 +0200 Subject: [PATCH 0786/4982] mac80211: remove an unused definition (MAX_STA_COUNT) in sta_info.h. This patch removes an unused definition of MAX_STA_COUNT in sta_info.h. Signed-off-by: Rami Rosen Signed-off-by: John W. Linville --- net/mac80211/sta_info.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index e49a5b99cf1..b683d3f5ef8 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -382,8 +382,6 @@ static inline u32 get_sta_flags(struct sta_info *sta) } -/* Maximum number of concurrently registered stations */ -#define MAX_STA_COUNT 2007 #define STA_HASH_SIZE 256 #define STA_HASH(sta) (sta[5]) -- GitLab From 8fe12920dc5fa0a0db7cad3661223d5f78a39c60 Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Tue, 6 Jan 2009 15:24:57 +0200 Subject: [PATCH 0787/4982] mac80211: remove unused variable in ieee80211_local (dot11WEPUndecryptableCount). This patch removes an unused declaration of dot11WEPUndecryptableCount (an snmp counter) in ieee80211_local structure and its usage in debugfs.c since this counter is not incremented/decremented anywhere. Signed-off-by: Rami Rosen Signed-off-by: John W. Linville --- net/mac80211/debugfs.c | 4 ---- net/mac80211/ieee80211_i.h | 1 - 2 files changed, 5 deletions(-) diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 2697a2fe608..18541bb7509 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -136,8 +136,6 @@ DEBUGFS_STATS_FILE(multicast_received_frame_count, 20, "%u", local->dot11MulticastReceivedFrameCount); DEBUGFS_STATS_FILE(transmitted_frame_count, 20, "%u", local->dot11TransmittedFrameCount); -DEBUGFS_STATS_FILE(wep_undecryptable_count, 20, "%u", - local->dot11WEPUndecryptableCount); #ifdef CONFIG_MAC80211_DEBUG_COUNTERS DEBUGFS_STATS_FILE(tx_handlers_drop, 20, "%u", local->tx_handlers_drop); @@ -221,7 +219,6 @@ void debugfs_hw_add(struct ieee80211_local *local) DEBUGFS_STATS_ADD(received_fragment_count); DEBUGFS_STATS_ADD(multicast_received_frame_count); DEBUGFS_STATS_ADD(transmitted_frame_count); - DEBUGFS_STATS_ADD(wep_undecryptable_count); #ifdef CONFIG_MAC80211_DEBUG_COUNTERS DEBUGFS_STATS_ADD(tx_handlers_drop); DEBUGFS_STATS_ADD(tx_handlers_queued); @@ -268,7 +265,6 @@ void debugfs_hw_del(struct ieee80211_local *local) DEBUGFS_STATS_DEL(received_fragment_count); DEBUGFS_STATS_DEL(multicast_received_frame_count); DEBUGFS_STATS_DEL(transmitted_frame_count); - DEBUGFS_STATS_DEL(wep_undecryptable_count); DEBUGFS_STATS_DEL(num_scans); #ifdef CONFIG_MAC80211_DEBUG_COUNTERS DEBUGFS_STATS_DEL(tx_handlers_drop); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index d2a007aa8e7..85c4d3144f9 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -654,7 +654,6 @@ struct ieee80211_local { u32 dot11ReceivedFragmentCount; u32 dot11MulticastReceivedFrameCount; u32 dot11TransmittedFrameCount; - u32 dot11WEPUndecryptableCount; #ifdef CONFIG_MAC80211_LEDS int tx_led_counter, rx_led_counter; -- GitLab From 8465676241cad5e28a1b745c32a0e18e1f67e18e Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Tue, 6 Jan 2009 17:27:06 +0200 Subject: [PATCH 0788/4982] ath5k: Minor QCU updates * Sync qcu.c with legacy-hal * Add some more comments * Set QCU mask to save power (QCU mask controls which QCUs are attached to each DCU, we do a 1:1 mapping) TODO: Use max QCU from EEPROM, further sync with legacy-hal and sam's hal and a few more minor fixes. I think after this we are ready to implement WME on the driver part. Anyone interested ? Signed-Off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/qcu.c | 47 ++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ath5k/qcu.c b/drivers/net/wireless/ath5k/qcu.c index 1b7bc50ea8e..5094c394a4b 100644 --- a/drivers/net/wireless/ath5k/qcu.c +++ b/drivers/net/wireless/ath5k/qcu.c @@ -148,6 +148,7 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, */ u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) { + u32 pending; ATH5K_TRACE(ah->ah_sc); AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); @@ -159,7 +160,15 @@ u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) if (ah->ah_version == AR5K_AR5210) return false; - return AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT; + pending = (AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT); + + /* It's possible to have no frames pending even if TXE + * is set. To indicate that q has not stopped return + * true */ + if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) + return true; + + return pending; } /* @@ -324,8 +333,18 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) /* * Set misc registers */ - ath5k_hw_reg_write(ah, AR5K_QCU_MISC_DCU_EARLY, - AR5K_QUEUE_MISC(queue)); + /* Enable DCU early termination for this queue */ + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), + AR5K_QCU_MISC_DCU_EARLY); + + /* Enable DCU to wait for next fragment from QCU */ + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), + AR5K_DCU_MISC_FRAG_WAIT); + + /* On Maui and Spirit use the global seqnum on DCU */ + if (ah->ah_mac_version < AR5K_SREV_AR5211) + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), + AR5K_DCU_MISC_SEQNUM_CTL); if (tq->tqi_cbr_period) { ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period, @@ -341,7 +360,8 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) AR5K_QCU_MISC_CBR_THRES_ENABLE); } - if (tq->tqi_ready_time) + if (tq->tqi_ready_time && + (tq->tqi_type != AR5K_TX_QUEUE_ID_CAB)) ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time, AR5K_QCU_RDYTIMECFG_INTVAL) | AR5K_QCU_RDYTIMECFG_ENABLE, @@ -383,13 +403,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) AR5K_DCU_MISC_ARBLOCK_CTL_S) | AR5K_DCU_MISC_POST_FR_BKOFF_DIS | AR5K_DCU_MISC_BCN_ENABLE); - - ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL - - (AR5K_TUNE_SW_BEACON_RESP - - AR5K_TUNE_DMA_BEACON_RESP) - - AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | - AR5K_QCU_RDYTIMECFG_ENABLE, - AR5K_QUEUE_RDYTIMECFG(queue)); break; case AR5K_TX_QUEUE_CAB: @@ -398,6 +411,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) AR5K_QCU_MISC_CBREXP_DIS | AR5K_QCU_MISC_CBREXP_BCN_DIS); + ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL - + (AR5K_TUNE_SW_BEACON_RESP - + AR5K_TUNE_DMA_BEACON_RESP) - + AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | + AR5K_QCU_RDYTIMECFG_ENABLE, + AR5K_QUEUE_RDYTIMECFG(queue)); + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << AR5K_DCU_MISC_ARBLOCK_CTL_S)); @@ -413,6 +433,8 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) break; } + /* TODO: Handle frame compression */ + /* * Enable interrupts for this tx queue * in the secondary interrupt mask registers @@ -483,6 +505,9 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) * by setting AR5K_TXNOFRM to zero */ if (ah->ah_txq_imr_nofrm == 0) ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM); + + /* Set QCU mask for this DCU to save power */ + AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue); } return 0; -- GitLab From 2bf30fabadbdcb535b057afc92aba015884847dc Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Jan 2009 23:23:56 +0100 Subject: [PATCH 0789/4982] mac80211: remove user_power_level from driver API I missed this during review of "mac80211: Fix tx power setting", the user_power_level shouldn't be available to the driver but rather be an internal value used to calculate the value for the driver. Signed-off-by: Johannes Berg Cc: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- include/net/mac80211.h | 2 -- net/mac80211/ieee80211_i.h | 2 ++ net/mac80211/main.c | 4 ++-- net/mac80211/wext.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 9215b1ec90e..0ffe932942f 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -546,7 +546,6 @@ enum ieee80211_conf_changed { * @listen_interval: listen interval in units of beacon interval * @flags: configuration flags defined above * @power_level: requested transmit power (in dBm) - * @user_power_level: User configured transmit power (in dBm) * @channel: the channel to tune to * @ht: the HT configuration for the device * @long_frame_max_tx_count: Maximum number of transmissions for a "long" frame @@ -560,7 +559,6 @@ struct ieee80211_conf { int beacon_int; u32 flags; int power_level; - int user_power_level; u16 listen_interval; bool radio_enabled; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 85c4d3144f9..fa5ca14517f 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -705,6 +705,8 @@ struct ieee80211_local { struct work_struct dynamic_ps_disable_work; struct timer_list dynamic_ps_timer; + int user_power_level; /* in dBm */ + #ifdef CONFIG_MAC80211_DEBUGFS struct local_debugfsdentries { struct dentry *rcdir; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index dca4b7da6ca..b55b9970dc9 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -214,10 +214,10 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) changed |= IEEE80211_CONF_CHANGE_CHANNEL; } - if (!local->hw.conf.user_power_level) + if (!local->user_power_level) power = chan->max_power; else - power = min(chan->max_power, local->hw.conf.user_power_level); + power = min(chan->max_power, local->user_power_level); if (local->hw.conf.power_level != power) { changed |= IEEE80211_CONF_CHANGE_POWER; local->hw.conf.power_level = power; diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index bb2c7135a1c..5690c3d41e7 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -551,7 +551,7 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev, else /* Automatic power level setting */ new_power_level = chan->max_power; - local->hw.conf.user_power_level = new_power_level; + local->user_power_level = new_power_level; if (local->hw.conf.power_level != new_power_level) reconf_flags |= IEEE80211_CONF_CHANGE_POWER; -- GitLab From d1c3a37ceeb1a5ea02991a0476355f1a1d3b3e83 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 7 Jan 2009 00:26:10 +0100 Subject: [PATCH 0790/4982] mac80211: clarify alignment docs, fix up alignment Not all drivers are capable of passing properly aligned frames, in particular with mesh networking no hardware will support completely aligning it correctly. This patch adds code to align the data payload to a 4-byte boundary in memory for those platforms that require this, or when CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT is set. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- Documentation/DocBook/mac80211.tmpl | 4 +- net/mac80211/rx.c | 110 +++++++++++++++++++--------- 2 files changed, 79 insertions(+), 35 deletions(-) diff --git a/Documentation/DocBook/mac80211.tmpl b/Documentation/DocBook/mac80211.tmpl index 77c3c202991..bdf908a6e54 100644 --- a/Documentation/DocBook/mac80211.tmpl +++ b/Documentation/DocBook/mac80211.tmpl @@ -165,8 +165,8 @@ usage should require reading the full document. !Pinclude/net/mac80211.h Frame format - Alignment issues - TBD + Packet alignment +!Pnet/mac80211/rx.c Packet alignment Calling into mac80211 from interrupts diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index ddb966f5888..b68e082e99c 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -102,7 +102,7 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local, return len; } -/** +/* * ieee80211_add_rx_radiotap_header - add radiotap header * * add a radiotap header containing all the fields which the hardware provided. @@ -371,39 +371,50 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) rx->skb->priority = (tid > 7) ? 0 : tid; } -static void ieee80211_verify_ip_alignment(struct ieee80211_rx_data *rx) +/** + * DOC: Packet alignment + * + * Drivers always need to pass packets that are aligned to two-byte boundaries + * to the stack. + * + * Additionally, should, if possible, align the payload data in a way that + * guarantees that the contained IP header is aligned to a four-byte + * boundary. In the case of regular frames, this simply means aligning the + * payload to a four-byte boundary (because either the IP header is directly + * contained, or IV/RFC1042 headers that have a length divisible by four are + * in front of it). + * + * With A-MSDU frames, however, the payload data address must yield two modulo + * four because there are 14-byte 802.3 headers within the A-MSDU frames that + * push the IP header further back to a multiple of four again. Thankfully, the + * specs were sane enough this time around to require padding each A-MSDU + * subframe to a length that is a multiple of four. + * + * Padding like Atheros hardware adds which is inbetween the 802.11 header and + * the payload is not supported, the driver is required to move the 802.11 + * header to be directly in front of the payload in that case. + */ +static void ieee80211_verify_alignment(struct ieee80211_rx_data *rx) { -#ifdef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; int hdrlen; +#ifndef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT + return; +#endif + + if (WARN_ONCE((unsigned long)rx->skb->data & 1, + "unaligned packet at 0x%p\n", rx->skb->data)) + return; + if (!ieee80211_is_data_present(hdr->frame_control)) return; - /* - * Drivers are required to align the payload data in a way that - * guarantees that the contained IP header is aligned to a four- - * byte boundary. In the case of regular frames, this simply means - * aligning the payload to a four-byte boundary (because either - * the IP header is directly contained, or IV/RFC1042 headers that - * have a length divisible by four are in front of it. - * - * With A-MSDU frames, however, the payload data address must - * yield two modulo four because there are 14-byte 802.3 headers - * within the A-MSDU frames that push the IP header further back - * to a multiple of four again. Thankfully, the specs were sane - * enough this time around to require padding each A-MSDU subframe - * to a length that is a multiple of four. - * - * Padding like atheros hardware adds which is inbetween the 802.11 - * header and the payload is not supported, the driver is required - * to move the 802.11 header further back in that case. - */ hdrlen = ieee80211_hdrlen(hdr->frame_control); if (rx->flags & IEEE80211_RX_AMSDU) hdrlen += ETH_HLEN; - WARN_ON_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3); -#endif + WARN_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3, + "unaligned IP payload at 0x%p\n", rx->skb->data + hdrlen); } @@ -1267,10 +1278,37 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) } if (skb) { - /* deliver to local stack */ - skb->protocol = eth_type_trans(skb, dev); - memset(skb->cb, 0, sizeof(skb->cb)); - netif_rx(skb); + int align __maybe_unused; + +#if defined(CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT) || !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) + /* + * 'align' will only take the values 0 or 2 here + * since all frames are required to be aligned + * to 2-byte boundaries when being passed to + * mac80211. That also explains the __skb_push() + * below. + */ + align = (unsigned long)skb->data & 4; + if (align) { + if (WARN_ON(skb_headroom(skb) < 3)) { + dev_kfree_skb(skb); + skb = NULL; + } else { + u8 *data = skb->data; + size_t len = skb->len; + u8 *new = __skb_push(skb, align); + memmove(new, data, len); + __skb_trim(skb, len); + } + } +#endif + + if (skb) { + /* deliver to local stack */ + skb->protocol = eth_type_trans(skb, dev); + memset(skb->cb, 0, sizeof(skb->cb)); + netif_rx(skb); + } } if (xmit_skb) { @@ -1339,14 +1377,20 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) if (remaining <= subframe_len + padding) frame = skb; else { - frame = dev_alloc_skb(local->hw.extra_tx_headroom + - subframe_len); + /* + * Allocate and reserve two bytes more for payload + * alignment since sizeof(struct ethhdr) is 14. + */ + frame = dev_alloc_skb( + ALIGN(local->hw.extra_tx_headroom, 4) + + subframe_len + 2); if (frame == NULL) return RX_DROP_UNUSABLE; - skb_reserve(frame, local->hw.extra_tx_headroom + - sizeof(struct ethhdr)); + skb_reserve(frame, + ALIGN(local->hw.extra_tx_headroom, 4) + + sizeof(struct ethhdr) + 2); memcpy(skb_put(frame, ntohs(len)), skb->data, ntohs(len)); @@ -1976,7 +2020,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, rx.flags |= IEEE80211_RX_IN_SCAN; ieee80211_parse_qos(&rx); - ieee80211_verify_ip_alignment(&rx); + ieee80211_verify_alignment(&rx); skb = rx.skb; -- GitLab From 47166791b7296db5c0a7189401e42b8c7f4cca25 Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Wed, 7 Jan 2009 00:43:54 +0000 Subject: [PATCH 0791/4982] orinoco: Remove unused variable rx_data Probably something leftover from experimentation with tasklets. Now the structure declaration orinoco_rx_data can be relocated to orinoco.c Signed-off-by: David Kilroy Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/orinoco.c | 6 ++++++ drivers/net/wireless/orinoco/orinoco.h | 9 --------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c index beb4d1f8c18..41aa51bc49a 100644 --- a/drivers/net/wireless/orinoco/orinoco.c +++ b/drivers/net/wireless/orinoco/orinoco.c @@ -235,6 +235,12 @@ struct hermes_rx_descriptor { __le16 data_len; } __attribute__ ((packed)); +struct orinoco_rx_data { + struct hermes_rx_descriptor *desc; + struct sk_buff *skb; + struct list_head list; +}; + /********************************************************************/ /* Function prototypes */ /********************************************************************/ diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h index 00750c8ba7d..c653816ef5f 100644 --- a/drivers/net/wireless/orinoco/orinoco.h +++ b/drivers/net/wireless/orinoco/orinoco.h @@ -59,14 +59,6 @@ struct xbss_element { struct list_head list; }; -struct hermes_rx_descriptor; - -struct orinoco_rx_data { - struct hermes_rx_descriptor *desc; - struct sk_buff *skb; - struct list_head list; -}; - struct firmware; struct orinoco_private { @@ -83,7 +75,6 @@ struct orinoco_private { /* Interrupt tasklets */ struct tasklet_struct rx_tasklet; struct list_head rx_list; - struct orinoco_rx_data *rx_data; /* driver state */ int open; -- GitLab From 4797938c5dfa22af30fd16679192972f878419a1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 7 Jan 2009 10:13:27 +0100 Subject: [PATCH 0792/4982] mac80211: clean up channel type config The channel_type really doesn't need to be the only member in a new structure, so remove the struct. Additionally, remove the _CONF_CHANGE_HT flag and use _CONF_CHANGE_CHANNEL when the channel type changes, since that's enough of a change to require reprogramming the hardware anyway. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 5 ++--- include/net/mac80211.h | 20 +++++++------------- net/mac80211/ht.c | 8 +++++--- net/mac80211/main.c | 4 ++-- net/mac80211/mlme.c | 2 +- 5 files changed, 17 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 8929b02aa22..5e9a3e19da4 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -2117,8 +2117,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) struct ieee80211_conf *conf = &hw->conf; mutex_lock(&sc->mutex); - if (changed & (IEEE80211_CONF_CHANGE_CHANNEL | - IEEE80211_CONF_CHANGE_HT)) { + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { struct ieee80211_channel *curchan = hw->conf.channel; int pos; @@ -2144,7 +2143,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) sc->sc_ah->ah_channels[pos].chanmode = ath_get_extchanmode(sc, curchan, - conf->ht.channel_type); + conf->channel_type); } ath_update_chainmask(sc, conf_is_ht(conf)); diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 0ffe932942f..76537f10387 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -507,10 +507,6 @@ static inline int __deprecated __IEEE80211_CONF_SHORT_SLOT_TIME(void) } #define IEEE80211_CONF_SHORT_SLOT_TIME (__IEEE80211_CONF_SHORT_SLOT_TIME()) -struct ieee80211_ht_conf { - enum nl80211_channel_type channel_type; -}; - /** * enum ieee80211_conf_changed - denotes which configuration changed * @@ -520,9 +516,8 @@ struct ieee80211_ht_conf { * @IEEE80211_CONF_CHANGE_RADIOTAP: the radiotap flag changed * @IEEE80211_CONF_CHANGE_PS: the PS flag changed * @IEEE80211_CONF_CHANGE_POWER: the TX power changed - * @IEEE80211_CONF_CHANGE_CHANNEL: the channel changed + * @IEEE80211_CONF_CHANGE_CHANNEL: the channel/channel_type changed * @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed - * @IEEE80211_CONF_CHANGE_HT: HT configuration changed */ enum ieee80211_conf_changed { IEEE80211_CONF_CHANGE_RADIO_ENABLED = BIT(0), @@ -533,7 +528,6 @@ enum ieee80211_conf_changed { IEEE80211_CONF_CHANGE_POWER = BIT(5), IEEE80211_CONF_CHANGE_CHANNEL = BIT(6), IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(7), - IEEE80211_CONF_CHANGE_HT = BIT(8), }; /** @@ -547,7 +541,7 @@ enum ieee80211_conf_changed { * @flags: configuration flags defined above * @power_level: requested transmit power (in dBm) * @channel: the channel to tune to - * @ht: the HT configuration for the device + * @channel_type: the channel (HT) type * @long_frame_max_tx_count: Maximum number of transmissions for a "long" frame * (a frame not RTS protected), called "dot11LongRetryLimit" in 802.11, * but actually means the number of transmissions not the number of retries @@ -566,7 +560,7 @@ struct ieee80211_conf { u8 long_frame_max_tx_count, short_frame_max_tx_count; struct ieee80211_channel *channel; - struct ieee80211_ht_conf ht; + enum nl80211_channel_type channel_type; }; /** @@ -1960,19 +1954,19 @@ void ieee80211_rate_control_unregister(struct rate_control_ops *ops); static inline bool conf_is_ht20(struct ieee80211_conf *conf) { - return conf->ht.channel_type == NL80211_CHAN_HT20; + return conf->channel_type == NL80211_CHAN_HT20; } static inline bool conf_is_ht40_minus(struct ieee80211_conf *conf) { - return conf->ht.channel_type == NL80211_CHAN_HT40MINUS; + return conf->channel_type == NL80211_CHAN_HT40MINUS; } static inline bool conf_is_ht40_plus(struct ieee80211_conf *conf) { - return conf->ht.channel_type == NL80211_CHAN_HT40PLUS; + return conf->channel_type == NL80211_CHAN_HT40PLUS; } static inline bool @@ -1984,7 +1978,7 @@ conf_is_ht40(struct ieee80211_conf *conf) static inline bool conf_is_ht(struct ieee80211_conf *conf) { - return conf->ht.channel_type != NL80211_CHAN_NO_HT; + return conf->channel_type != NL80211_CHAN_NO_HT; } #endif /* MAC80211_H */ diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index f6547de5ac6..832adf888ac 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -131,12 +131,14 @@ u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, } ht_changed = conf_is_ht(&local->hw.conf) != enable_ht || - channel_type != local->hw.conf.ht.channel_type; + channel_type != local->hw.conf.channel_type; local->oper_channel_type = channel_type; - if (ht_changed) - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT); + if (ht_changed) { + /* channel_type change automatically detected */ + ieee80211_hw_config(local, 0); + } /* disable HT */ if (!enable_ht) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index b55b9970dc9..e9f3e85d1a9 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -208,9 +208,9 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) } if (chan != local->hw.conf.channel || - channel_type != local->hw.conf.ht.channel_type) { + channel_type != local->hw.conf.channel_type) { local->hw.conf.channel = chan; - local->hw.conf.ht.channel_type = channel_type; + local->hw.conf.channel_type = channel_type; changed |= IEEE80211_CONF_CHANGE_CHANNEL; } diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index aafa112ae09..6a90171c859 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -901,8 +901,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, rcu_read_unlock(); + /* channel(_type) changes are handled by ieee80211_hw_config */ local->oper_channel_type = NL80211_CHAN_NO_HT; - config_changed |= IEEE80211_CONF_CHANGE_HT; del_timer_sync(&local->dynamic_ps_timer); cancel_work_sync(&local->dynamic_ps_enable_work); -- GitLab From e9aeabaeb9a0bece50100dc74bbd720a68cb8f5c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Jan 2009 18:12:35 +0100 Subject: [PATCH 0793/4982] mac80211: validate SIOCSIWPOWER arguments better Don't accept any arguments we don't handle, and return error codes instead of using an uninitialised stack value. Signed-off-by: Johannes Berg Reviewed-by: Kalle Valo Signed-off-by: John W. Linville --- net/mac80211/wext.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 5690c3d41e7..3fc1b903bfb 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -853,9 +853,12 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev, ps = true; break; default: /* Otherwise we ignore */ - break; + return -EINVAL; } + if (wrq->flags & ~(IW_POWER_MODE | IW_POWER_TIMEOUT)) + return -EINVAL; + if (wrq->flags & IW_POWER_TIMEOUT) timeout = wrq->value / 1000; -- GitLab From 46f2c4bd7e2ba2cfedbcd4fe15d316eebc608cba Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Jan 2009 18:13:18 +0100 Subject: [PATCH 0794/4982] mac80211: move dynamic PS timeout to hardware config This will be needed for drivers that set the IEEE80211_HW_NO_STACK_DYNAMIC_PS flag and still want to handle dynamic PS. Signed-off-by: Johannes Berg Reviewed-by: Kalle Valo Signed-off-by: John W. Linville --- include/net/mac80211.h | 11 +++++++---- net/mac80211/ieee80211_i.h | 1 - net/mac80211/mlme.c | 5 +++-- net/mac80211/tx.c | 4 ++-- net/mac80211/wext.c | 14 ++++++++------ 5 files changed, 20 insertions(+), 15 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 76537f10387..83ee8a21229 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -515,6 +515,7 @@ static inline int __deprecated __IEEE80211_CONF_SHORT_SLOT_TIME(void) * @IEEE80211_CONF_CHANGE_LISTEN_INTERVAL: the listen interval changed * @IEEE80211_CONF_CHANGE_RADIOTAP: the radiotap flag changed * @IEEE80211_CONF_CHANGE_PS: the PS flag changed + * @IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT: the dynamic PS timeout changed * @IEEE80211_CONF_CHANGE_POWER: the TX power changed * @IEEE80211_CONF_CHANGE_CHANNEL: the channel/channel_type changed * @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed @@ -525,9 +526,10 @@ enum ieee80211_conf_changed { IEEE80211_CONF_CHANGE_LISTEN_INTERVAL = BIT(2), IEEE80211_CONF_CHANGE_RADIOTAP = BIT(3), IEEE80211_CONF_CHANGE_PS = BIT(4), - IEEE80211_CONF_CHANGE_POWER = BIT(5), - IEEE80211_CONF_CHANGE_CHANNEL = BIT(6), - IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(7), + IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT = BIT(5), + IEEE80211_CONF_CHANGE_POWER = BIT(6), + IEEE80211_CONF_CHANGE_CHANNEL = BIT(7), + IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(8), }; /** @@ -540,6 +542,7 @@ enum ieee80211_conf_changed { * @listen_interval: listen interval in units of beacon interval * @flags: configuration flags defined above * @power_level: requested transmit power (in dBm) + * @dynamic_ps_timeout: dynamic powersave timeout (in ms) * @channel: the channel to tune to * @channel_type: the channel (HT) type * @long_frame_max_tx_count: Maximum number of transmissions for a "long" frame @@ -552,7 +555,7 @@ enum ieee80211_conf_changed { struct ieee80211_conf { int beacon_int; u32 flags; - int power_level; + int power_level, dynamic_ps_timeout; u16 listen_interval; bool radio_enabled; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index fa5ca14517f..3db6bc3cdaf 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -700,7 +700,6 @@ struct ieee80211_local { unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ bool powersave; - int dynamic_ps_timeout; struct work_struct dynamic_ps_enable_work; struct work_struct dynamic_ps_disable_work; struct timer_list dynamic_ps_timer; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 6a90171c859..7709e764567 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -777,9 +777,10 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, if (local->powersave && !(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS)) { - if (local->dynamic_ps_timeout > 0) + if (local->hw.conf.dynamic_ps_timeout > 0) mod_timer(&local->dynamic_ps_timer, jiffies + - msecs_to_jiffies(local->dynamic_ps_timeout)); + msecs_to_jiffies( + local->hw.conf.dynamic_ps_timeout)); else { ieee80211_send_nullfunc(local, sdata, 1); conf->flags |= IEEE80211_CONF_PS; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 96eca341160..b18a7269011 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1296,7 +1296,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) } if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) && - local->dynamic_ps_timeout > 0) { + local->hw.conf.dynamic_ps_timeout > 0) { if (local->hw.conf.flags & IEEE80211_CONF_PS) { ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_QUEUE_STOP_REASON_PS); @@ -1305,7 +1305,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) } mod_timer(&local->dynamic_ps_timer, jiffies + - msecs_to_jiffies(local->dynamic_ps_timeout)); + msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); } memset(info, 0, sizeof(*info)); diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 3fc1b903bfb..3f2db0bda46 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -863,17 +863,19 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev, timeout = wrq->value / 1000; set: - if (ps == local->powersave && timeout == local->dynamic_ps_timeout) + if (ps == local->powersave && timeout == conf->dynamic_ps_timeout) return ret; local->powersave = ps; - local->dynamic_ps_timeout = timeout; + conf->dynamic_ps_timeout = timeout; - if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) && - (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED)) { - if (local->dynamic_ps_timeout > 0) + if (local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) { + ret = ieee80211_hw_config(local, + IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT); + } else if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { + if (conf->dynamic_ps_timeout > 0) mod_timer(&local->dynamic_ps_timer, jiffies + - msecs_to_jiffies(local->dynamic_ps_timeout)); + msecs_to_jiffies(conf->dynamic_ps_timeout)); else { if (local->powersave) { ieee80211_send_nullfunc(local, sdata, 1); -- GitLab From 64d74681433415855da02d2516f28d2ed859cde9 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Wed, 7 Jan 2009 14:51:41 +0100 Subject: [PATCH 0795/4982] rt2x00: Only register rfkill input when key is present rt2x00 should only register the RFKILL input device when the hardware indicated the key was present. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00rfkill.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c index 595efd05ce4..53f64b76a8c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c +++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c @@ -87,7 +87,8 @@ void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev) { struct input_polled_dev *poll_dev; - if (test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) + if (test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state) || + !test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) return; poll_dev = input_allocate_polled_device(); -- GitLab From acbaf32e94cb70218792cac68e5149e482e77441 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Wed, 7 Jan 2009 16:40:08 +0100 Subject: [PATCH 0796/4982] p54: return NETDEV_TX_OK in p54_tx and fix sparse warnings This patch addresses all recent comments from Johannes Berg: 1st: (reference http://marc.info/?l=linux-wireless&m=123124685019631 ) >First off: all those should return NETDEV_TX_OK/BUSY. >iwl-agn: returns 0 (== NETDEV_TX_OK, but still should be changed) >[...] >p54: same (some paths) 2nd: > due to your PS patch ("p54: power save management"), please run sparse: > make C=2 CF=-D__CHECK_ENDIAN__ M=... > +drivers/net/wireless/p54/p54common.c:1753:8: warning: incorrect type in assignment (different base types) > +drivers/net/wireless/p54/p54common.c:1769:29: warning: incorrect type in assignment (different base types) The cpu_to_le16 ended up in the wrong line... Sorry! Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 6c175df48b0..e463c7c3a7e 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -1532,7 +1532,7 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) queue_delayed_work(dev->workqueue, &priv->work, msecs_to_jiffies(P54_TX_FRAME_LIFETIME)); - return 0; + return NETDEV_TX_OK; err: skb_pull(skb, sizeof(*hdr) + sizeof(*txhdr) + padding); @@ -1774,7 +1774,7 @@ static int p54_set_ps(struct ieee80211_hw *dev) int i; if (dev->conf.flags & IEEE80211_CONF_PS) - mode = cpu_to_le16(P54_PSM | P54_PSM_DTIM | P54_PSM_MCBC); + mode = P54_PSM | P54_PSM_DTIM | P54_PSM_MCBC; else mode = P54_PSM_CAM; @@ -1790,7 +1790,7 @@ static int p54_set_ps(struct ieee80211_hw *dev) for (i = 0; i < ARRAY_SIZE(psm->intervals); i++) { psm->intervals[i].interval = cpu_to_le16(dev->conf.listen_interval); - psm->intervals[i].periods = 1; + psm->intervals[i].periods = cpu_to_le16(1); } psm->beacon_rssi_skip_max = 60; -- GitLab From 4be8c3873e0b88397866d3ede578503e188f9ad2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 7 Jan 2009 18:28:20 +0100 Subject: [PATCH 0797/4982] mac80211: extend/document powersave API This modifies hardware flags for powersave to support three different flags: * IEEE80211_HW_SUPPORTS_PS - indicates general PS support * IEEE80211_HW_PS_NULLFUNC_STACK - indicates nullfunc sending in software * IEEE80211_HW_SUPPORTS_DYNAMIC_PS - indicates dynamic PS on the device It also adds documentation for all this which explains how to set the various flags. Additionally, it fixes a few things: * a spot where && was used to test flags * enable CONF_PS only when associated again Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- Documentation/DocBook/mac80211.tmpl | 8 +++- drivers/net/wireless/iwlwifi/iwl-core.c | 3 +- drivers/net/wireless/rt2x00/rt2400pci.c | 4 +- drivers/net/wireless/rt2x00/rt2500pci.c | 4 +- drivers/net/wireless/rt2x00/rt2500usb.c | 4 +- drivers/net/wireless/rt2x00/rt61pci.c | 4 +- drivers/net/wireless/rt2x00/rt73usb.c | 4 +- include/net/mac80211.h | 53 ++++++++++++++++++++++--- net/mac80211/mlme.c | 31 +++++++-------- net/mac80211/tx.c | 2 +- net/mac80211/wext.c | 40 +++++++++++-------- 11 files changed, 111 insertions(+), 46 deletions(-) diff --git a/Documentation/DocBook/mac80211.tmpl b/Documentation/DocBook/mac80211.tmpl index bdf908a6e54..8af6d962687 100644 --- a/Documentation/DocBook/mac80211.tmpl +++ b/Documentation/DocBook/mac80211.tmpl @@ -17,8 +17,7 @@ - 2007 - 2008 + 2007-2009 Johannes Berg @@ -223,6 +222,11 @@ usage should require reading the full document. !Finclude/net/mac80211.h ieee80211_key_flags + + Powersave support +!Pinclude/net/mac80211.h Powersave support + + Multiple queues and QoS support TBD diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 76315c30e6f..07c3870365b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -805,7 +805,8 @@ int iwl_setup_mac(struct iwl_priv *priv) /* Tell mac80211 our characteristics */ hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM | - IEEE80211_HW_AMPDU_AGGREGATION; + IEEE80211_HW_AMPDU_AGGREGATION | + IEEE80211_HW_SUPPORTS_PS; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 9104113270d..ae8bfd6b59d 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1449,7 +1449,9 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) * Initialize all hw fields. */ rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM; + IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_PS_NULLFUNC_STACK; rt2x00dev->hw->extra_tx_headroom = 0; SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index ebcc4977092..bca6798be15 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1749,7 +1749,9 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) * Initialize all hw fields. */ rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM; + IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_PS_NULLFUNC_STACK; rt2x00dev->hw->extra_tx_headroom = 0; diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index e992bad6464..27a6971df57 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1801,7 +1801,9 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) rt2x00dev->hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM; + IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_PS_NULLFUNC_STACK; rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE; diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 82d35a5a4aa..549480a963e 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2556,7 +2556,9 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) */ rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM; + IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_PS_NULLFUNC_STACK; rt2x00dev->hw->extra_tx_headroom = 0; SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 2b70c01b55e..849220236c7 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2077,7 +2077,9 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) */ rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM; + IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_PS_NULLFUNC_STACK; rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE; SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 83ee8a21229..8a305bfdb87 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -850,10 +850,15 @@ enum ieee80211_tkip_key_type { * @IEEE80211_HW_AMPDU_AGGREGATION: * Hardware supports 11n A-MPDU aggregation. * - * @IEEE80211_HW_NO_STACK_DYNAMIC_PS: - * Hardware which has dynamic power save support, meaning - * that power save is enabled in idle periods, and don't need support - * from stack. + * @IEEE80211_HW_SUPPORTS_PS: + * Hardware has power save support (i.e. can go to sleep). + * + * @IEEE80211_HW_PS_NULLFUNC_STACK: + * Hardware requires nullfunc frame handling in stack, implies + * stack support for dynamic PS. + * + * @IEEE80211_HW_SUPPORTS_DYNAMIC_PS: + * Hardware has support for dynamic PS. */ enum ieee80211_hw_flags { IEEE80211_HW_RX_INCLUDES_FCS = 1<<1, @@ -866,7 +871,9 @@ enum ieee80211_hw_flags { IEEE80211_HW_NOISE_DBM = 1<<8, IEEE80211_HW_SPECTRUM_MGMT = 1<<9, IEEE80211_HW_AMPDU_AGGREGATION = 1<<10, - IEEE80211_HW_NO_STACK_DYNAMIC_PS = 1<<11, + IEEE80211_HW_SUPPORTS_PS = 1<<11, + IEEE80211_HW_PS_NULLFUNC_STACK = 1<<12, + IEEE80211_HW_SUPPORTS_DYNAMIC_PS = 1<<13, }; /** @@ -1052,6 +1059,42 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, * handler is software decryption with wrap around of iv16. */ +/** + * DOC: Powersave support + * + * mac80211 has support for various powersave implementations. + * + * First, it can support hardware that handles all powersaving by + * itself, such hardware should simply set the %IEEE80211_HW_SUPPORTS_PS + * hardware flag. In that case, it will be told about the desired + * powersave mode depending on the association status, and the driver + * must take care of sending nullfunc frames when necessary, i.e. when + * entering and leaving powersave mode. The driver is required to look at + * the AID in beacons and signal to the AP that it woke up when it finds + * traffic directed to it. This mode supports dynamic PS by simply + * enabling/disabling PS. + * + * Additionally, such hardware may set the %IEEE80211_HW_SUPPORTS_DYNAMIC_PS + * flag to indicate that it can support dynamic PS mode itself (see below). + * + * Other hardware designs cannot send nullfunc frames by themselves and also + * need software support for parsing the TIM bitmap. This is also supported + * by mac80211 by combining the %IEEE80211_HW_SUPPORTS_PS and + * %IEEE80211_HW_PS_NULLFUNC_STACK flags. The hardware is of course still + * required to pass up beacons. Additionally, in this case, mac80211 will + * wake up the hardware when multicast traffic is announced in the beacon. + * + * FIXME: I don't think we can be fast enough in software when we want to + * receive multicast traffic? + * + * Dynamic powersave mode is an extension to normal powersave mode in which + * the hardware stays awake for a user-specified period of time after sending + * a frame so that reply frames need not be buffered and therefore delayed + * to the next wakeup. This can either be supported by hardware, in which case + * the driver needs to look at the @dynamic_ps_timeout hardware configuration + * value, or by the stack if all nullfunc handling is in the stack. + */ + /** * DOC: Frame filtering * diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 7709e764567..a1e683e305f 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -775,17 +775,17 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, bss_info_changed |= BSS_CHANGED_BASIC_RATES; ieee80211_bss_info_change_notify(sdata, bss_info_changed); - if (local->powersave && - !(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS)) { - if (local->hw.conf.dynamic_ps_timeout > 0) + if (local->powersave) { + if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) && + local->hw.conf.dynamic_ps_timeout > 0) { mod_timer(&local->dynamic_ps_timer, jiffies + msecs_to_jiffies( local->hw.conf.dynamic_ps_timeout)); - else { - ieee80211_send_nullfunc(local, sdata, 1); + } else { + if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) + ieee80211_send_nullfunc(local, sdata, 1); conf->flags |= IEEE80211_CONF_PS; - ieee80211_hw_config(local, - IEEE80211_CONF_CHANGE_PS); + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); } } @@ -1779,16 +1779,14 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, elems.wmm_param_len); - if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS)) { + if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK && + local->hw.conf.flags & IEEE80211_CONF_PS) { directed_tim = check_tim(&elems, ifsta->aid, &is_mc); if (directed_tim || is_mc) { - if (local->hw.conf.flags && IEEE80211_CONF_PS) { - local->hw.conf.flags &= ~IEEE80211_CONF_PS; - ieee80211_hw_config(local, - IEEE80211_CONF_CHANGE_PS); - ieee80211_send_nullfunc(local, sdata, 0); - } + local->hw.conf.flags &= ~IEEE80211_CONF_PS; + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + ieee80211_send_nullfunc(local, sdata, 0); } } @@ -2694,9 +2692,10 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) if (local->hw.conf.flags & IEEE80211_CONF_PS) return; - ieee80211_send_nullfunc(local, sdata, 1); - local->hw.conf.flags |= IEEE80211_CONF_PS; + if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) + ieee80211_send_nullfunc(local, sdata, 1); + local->hw.conf.flags |= IEEE80211_CONF_PS; ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); } diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index b18a7269011..cd6bc87eec7 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1295,7 +1295,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } - if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) && + if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && local->hw.conf.dynamic_ps_timeout > 0) { if (local->hw.conf.flags & IEEE80211_CONF_PS) { ieee80211_stop_queues_by_reason(&local->hw, diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 3f2db0bda46..1e5b29bdb3a 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -837,6 +837,9 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev, int ret = 0, timeout = 0; bool ps; + if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) + return -EOPNOTSUPP; + if (sdata->vif.type != NL80211_IFTYPE_STATION) return -EINVAL; @@ -862,32 +865,37 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev, if (wrq->flags & IW_POWER_TIMEOUT) timeout = wrq->value / 1000; -set: + set: if (ps == local->powersave && timeout == conf->dynamic_ps_timeout) return ret; local->powersave = ps; conf->dynamic_ps_timeout = timeout; - if (local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) { + if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) ret = ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT); - } else if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { - if (conf->dynamic_ps_timeout > 0) - mod_timer(&local->dynamic_ps_timer, jiffies + - msecs_to_jiffies(conf->dynamic_ps_timeout)); - else { - if (local->powersave) { + + if (!(sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED)) + return ret; + + if (conf->dynamic_ps_timeout > 0 && + !(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)) { + mod_timer(&local->dynamic_ps_timer, jiffies + + msecs_to_jiffies(conf->dynamic_ps_timeout)); + } else { + if (local->powersave) { + if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) ieee80211_send_nullfunc(local, sdata, 1); - conf->flags |= IEEE80211_CONF_PS; - ret = ieee80211_hw_config(local, - IEEE80211_CONF_CHANGE_PS); - } else { - conf->flags &= ~IEEE80211_CONF_PS; - ret = ieee80211_hw_config(local, - IEEE80211_CONF_CHANGE_PS); + conf->flags |= IEEE80211_CONF_PS; + ret = ieee80211_hw_config(local, + IEEE80211_CONF_CHANGE_PS); + } else { + conf->flags &= ~IEEE80211_CONF_PS; + ret = ieee80211_hw_config(local, + IEEE80211_CONF_CHANGE_PS); + if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) ieee80211_send_nullfunc(local, sdata, 0); - } } } -- GitLab From 560e28e14f69ad3440a6e8c283dcfd37e1e41c2d Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 7 Jan 2009 17:43:32 -0800 Subject: [PATCH 0798/4982] cfg80211: call reg_notifier() once We are calling the reg_notifier() callback per band, this is not necessary, just call it once. Signed-off-by: Luis R. Rodriguez Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/reg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index bc494cef210..0f93d4526f3 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -947,9 +947,9 @@ void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby) for (band = 0; band < IEEE80211_NUM_BANDS; band++) { if (wiphy->bands[band]) handle_band(wiphy, band); - if (wiphy->reg_notifier) - wiphy->reg_notifier(wiphy, setby); } + if (wiphy->reg_notifier) + wiphy->reg_notifier(wiphy, setby); } /* Return value which can be used by ignore_request() to indicate -- GitLab From 3e0c3ff36c4c7b9e39af7d600e399664ca04e817 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 7 Jan 2009 17:43:34 -0800 Subject: [PATCH 0799/4982] cfg80211: allow multiple driver regulatory_hints() We add support for multiple drivers to provide a regulatory_hint() on a system by adding a wiphy specific regulatory domain cache. This allows drivers to keep around cache their own regulatory domain structure queried from CRDA. We handle conflicts by intersecting multiple regulatory domains, each driver will stick to its own regulatory domain though unless a country IE has been received and processed. If the user already requested a regulatory domain and a driver requests the same regulatory domain then simply copy to the driver's regd the same regulatory domain and do not call CRDA, do not collect $200. Signed-off-by: Luis R. Rodriguez Acked-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/wireless.h | 6 +++ net/wireless/reg.c | 104 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 98 insertions(+), 12 deletions(-) diff --git a/include/net/wireless.h b/include/net/wireless.h index 21c5d966142..9e73aae40c5 100644 --- a/include/net/wireless.h +++ b/include/net/wireless.h @@ -187,6 +187,10 @@ struct ieee80211_supported_band { * we will disregard the first regulatory hint (when the * initiator is %REGDOM_SET_BY_CORE). * @reg_notifier: the driver's regulatory notification callback + * @regd: the driver's regulatory domain, if one was requested via + * the regulatory_hint() API. This can be used by the driver + * on the reg_notifier() if it chooses to ignore future + * regulatory domain changes caused by other drivers. */ struct wiphy { /* assign these fields before you register the wiphy */ @@ -213,6 +217,8 @@ struct wiphy { /* fields below are read-only, assigned by cfg80211 */ + const struct ieee80211_regdomain *regd; + /* the item in /sys/class/ieee80211/ points to this, * you need use set_wiphy_dev() (see below) */ struct device dev; diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 0f93d4526f3..5a746cd114a 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -784,6 +784,7 @@ static u32 map_regdom_flags(u32 rd_flags) /** * freq_reg_info - get regulatory information for the given frequency + * @wiphy: the wiphy for which we want to process this rule for * @center_freq: Frequency in KHz for which we want regulatory information for * @bandwidth: the bandwidth requirement you have in KHz, if you do not have one * you can set this to 0. If this frequency is allowed we then set @@ -802,22 +803,31 @@ static u32 map_regdom_flags(u32 rd_flags) * freq_in_rule_band() for our current definition of a band -- this is purely * subjective and right now its 802.11 specific. */ -static int freq_reg_info(u32 center_freq, u32 *bandwidth, +static int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, const struct ieee80211_reg_rule **reg_rule) { int i; bool band_rule_found = false; + const struct ieee80211_regdomain *regd; u32 max_bandwidth = 0; - if (!cfg80211_regdomain) + regd = cfg80211_regdomain; + + /* Follow the driver's regulatory domain, if present, unless a country + * IE has been processed */ + if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE && + wiphy->regd) + regd = wiphy->regd; + + if (!regd) return -EINVAL; - for (i = 0; i < cfg80211_regdomain->n_reg_rules; i++) { + for (i = 0; i < regd->n_reg_rules; i++) { const struct ieee80211_reg_rule *rr; const struct ieee80211_freq_range *fr = NULL; const struct ieee80211_power_rule *pr = NULL; - rr = &cfg80211_regdomain->reg_rules[i]; + rr = ®d->reg_rules[i]; fr = &rr->freq_range; pr = &rr->power_rule; @@ -859,7 +869,7 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, flags = chan->orig_flags; - r = freq_reg_info(MHZ_TO_KHZ(chan->center_freq), + r = freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq), &max_bandwidth, ®_rule); if (r) { @@ -952,6 +962,30 @@ void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby) wiphy->reg_notifier(wiphy, setby); } +static int reg_copy_regd(const struct ieee80211_regdomain **dst_regd, + const struct ieee80211_regdomain *src_regd) +{ + struct ieee80211_regdomain *regd; + int size_of_regd = 0; + unsigned int i; + + size_of_regd = sizeof(struct ieee80211_regdomain) + + ((src_regd->n_reg_rules + 1) * sizeof(struct ieee80211_reg_rule)); + + regd = kzalloc(size_of_regd, GFP_KERNEL); + if (!regd) + return -ENOMEM; + + memcpy(regd, src_regd, sizeof(struct ieee80211_regdomain)); + + for (i = 0; i < src_regd->n_reg_rules; i++) + memcpy(®d->reg_rules[i], &src_regd->reg_rules[i], + sizeof(struct ieee80211_reg_rule)); + + *dst_regd = regd; + return 0; +} + /* Return value which can be used by ignore_request() to indicate * it has been determined we should intersect two regulatory domains */ #define REG_INTERSECT 1 @@ -999,9 +1033,9 @@ static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by, } return REG_INTERSECT; case REGDOM_SET_BY_DRIVER: - if (last_request->initiator == REGDOM_SET_BY_DRIVER) - return -EALREADY; - return 0; + if (last_request->initiator == REGDOM_SET_BY_CORE) + return 0; + return REG_INTERSECT; case REGDOM_SET_BY_USER: if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) return REG_INTERSECT; @@ -1028,11 +1062,28 @@ int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, r = ignore_request(wiphy, set_by, alpha2); - if (r == REG_INTERSECT) + if (r == REG_INTERSECT) { + if (set_by == REGDOM_SET_BY_DRIVER) { + r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain); + if (r) + return r; + } intersect = true; - else if (r) + } else if (r) { + /* If the regulatory domain being requested by the + * driver has already been set just copy it to the + * wiphy */ + if (r == -EALREADY && set_by == REGDOM_SET_BY_DRIVER) { + r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain); + if (r) + return r; + r = -EALREADY; + goto new_request; + } return r; + } +new_request: request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL); if (!request) @@ -1048,6 +1099,11 @@ int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, kfree(last_request); last_request = request; + + /* When r == REG_INTERSECT we do need to call CRDA */ + if (r < 0) + return r; + /* * Note: When CONFIG_WIRELESS_OLD_REGULATORY is enabled * AND if CRDA is NOT present nothing will happen, if someone @@ -1341,6 +1397,23 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) } if (!last_request->intersect) { + int r; + + if (last_request->initiator != REGDOM_SET_BY_DRIVER) { + reset_regdomains(); + cfg80211_regdomain = rd; + return 0; + } + + /* For a driver hint, lets copy the regulatory domain the + * driver wanted to the wiphy to deal with conflicts */ + + BUG_ON(last_request->wiphy->regd); + + r = reg_copy_regd(&last_request->wiphy->regd, rd); + if (r) + return r; + reset_regdomains(); cfg80211_regdomain = rd; return 0; @@ -1354,8 +1427,14 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) if (!intersected_rd) return -EINVAL; - /* We can trash what CRDA provided now */ - kfree(rd); + /* We can trash what CRDA provided now. + * However if a driver requested this specific regulatory + * domain we keep it for its private use */ + if (last_request->initiator == REGDOM_SET_BY_DRIVER) + last_request->wiphy->regd = rd; + else + kfree(rd); + rd = NULL; reset_regdomains(); @@ -1439,6 +1518,7 @@ int set_regdom(const struct ieee80211_regdomain *rd) /* Caller must hold cfg80211_drv_mutex */ void reg_device_remove(struct wiphy *wiphy) { + kfree(wiphy->regd); if (!last_request || !last_request->wiphy) return; if (last_request->wiphy != wiphy) -- GitLab From 039498c6ec67bd718ac1c8e7f6b4e2cfe2146773 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 7 Jan 2009 17:43:35 -0800 Subject: [PATCH 0800/4982] cfg80211: fix typo on message after intersection Signed-off-by: Luis R. Rodriguez Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/reg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 5a746cd114a..b34fd84b3e2 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1295,7 +1295,7 @@ static void print_regdomain(const struct ieee80211_regdomain *rd) "domain intersected: \n"); } else printk(KERN_INFO "cfg80211: Current regulatory " - "intersected: \n"); + "domain intersected: \n"); } else if (is_world_regdom(rd->alpha2)) printk(KERN_INFO "cfg80211: World regulatory " "domain updated:\n"); -- GitLab From 5394af4d86ae51b369ff243c3f75b6f9a74e164b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 8 Jan 2009 13:31:59 +0200 Subject: [PATCH 0801/4982] mac80211: 802.11w - STA flag for MFP Add flags for setting STA entries and struct ieee80211_if_sta to indicate whether management frame protection (MFP) is used. Signed-off-by: Jouni Malinen Acked-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/nl80211.h | 2 ++ include/net/cfg80211.h | 2 ++ net/mac80211/cfg.c | 4 ++++ net/mac80211/debugfs_sta.c | 5 +++-- net/mac80211/ieee80211_i.h | 1 + net/mac80211/mlme.c | 7 +++++-- net/mac80211/sta_info.h | 2 ++ 7 files changed, 19 insertions(+), 4 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index e86ed59f9ad..218f0e73a7a 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -412,12 +412,14 @@ enum nl80211_iftype { * @NL80211_STA_FLAG_SHORT_PREAMBLE: station is capable of receiving frames * with short barker preamble * @NL80211_STA_FLAG_WME: station is WME/QoS capable + * @NL80211_STA_FLAG_MFP: station uses management frame protection */ enum nl80211_sta_flags { __NL80211_STA_FLAG_INVALID, NL80211_STA_FLAG_AUTHORIZED, NL80211_STA_FLAG_SHORT_PREAMBLE, NL80211_STA_FLAG_WME, + NL80211_STA_FLAG_MFP, /* keep last */ __NL80211_STA_FLAG_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 23c0ab74ded..6619ed10613 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -112,12 +112,14 @@ struct beacon_parameters { * @STATION_FLAG_SHORT_PREAMBLE: station is capable of receiving frames * with short preambles * @STATION_FLAG_WME: station is WME/QoS capable + * @STATION_FLAG_MFP: station uses management frame protection */ enum station_flags { STATION_FLAG_CHANGED = 1<<0, STATION_FLAG_AUTHORIZED = 1<flags &= ~WLAN_STA_WME; if (params->station_flags & STATION_FLAG_WME) sta->flags |= WLAN_STA_WME; + + sta->flags &= ~WLAN_STA_MFP; + if (params->station_flags & STATION_FLAG_MFP) + sta->flags |= WLAN_STA_MFP; spin_unlock_bh(&sta->lock); } diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index a2fbe013131..90230c718b5 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -67,14 +67,15 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, char buf[100]; struct sta_info *sta = file->private_data; u32 staflags = get_sta_flags(sta); - int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s", + int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s", staflags & WLAN_STA_AUTH ? "AUTH\n" : "", staflags & WLAN_STA_ASSOC ? "ASSOC\n" : "", staflags & WLAN_STA_PS ? "PS\n" : "", staflags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "", staflags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "", staflags & WLAN_STA_WME ? "WME\n" : "", - staflags & WLAN_STA_WDS ? "WDS\n" : ""); + staflags & WLAN_STA_WDS ? "WDS\n" : "", + staflags & WLAN_STA_MFP ? "MFP\n" : ""); return simple_read_from_buffer(userbuf, count, ppos, buf, res); } STA_OPS(flags); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3db6bc3cdaf..b5f86cb1763 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -260,6 +260,7 @@ struct mesh_preq_queue { #define IEEE80211_STA_PRIVACY_INVOKED BIT(13) #define IEEE80211_STA_TKIP_WEP_USED BIT(14) #define IEEE80211_STA_CSA_RECEIVED BIT(15) +#define IEEE80211_STA_MFP_ENABLED BIT(16) /* flags for MLME request */ #define IEEE80211_STA_REQ_SCAN 0 #define IEEE80211_STA_REQ_DIRECT_PROBE 1 diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a1e683e305f..bc8a7f1a6a1 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1,6 +1,6 @@ /* * BSS client mode implementation - * Copyright 2003, Jouni Malinen + * Copyright 2003-2008, Jouni Malinen * Copyright 2004, Instant802 Networks, Inc. * Copyright 2005, Devicescape Software, Inc. * Copyright 2006-2007 Jiri Benc @@ -472,7 +472,7 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, /* u.deauth.reason_code == u.disassoc.reason_code */ mgmt->u.deauth.reason_code = cpu_to_le16(reason); - ieee80211_tx_skb(sdata, skb, 0); + ieee80211_tx_skb(sdata, skb, ifsta->flags & IEEE80211_STA_MFP_ENABLED); } /* MLME */ @@ -1408,6 +1408,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, rate_control_rate_init(sta); + if (ifsta->flags & IEEE80211_STA_MFP_ENABLED) + set_sta_flags(sta, WLAN_STA_MFP); + if (elems.wmm_param) set_sta_flags(sta, WLAN_STA_WME); diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index b683d3f5ef8..d13a44b935e 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -34,6 +34,7 @@ * @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the * IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next * frame to this station is transmitted. + * @WLAN_STA_MFP: Management frame protection is used with this STA. */ enum ieee80211_sta_info_flags { WLAN_STA_AUTH = 1<<0, @@ -46,6 +47,7 @@ enum ieee80211_sta_info_flags { WLAN_STA_WDS = 1<<7, WLAN_STA_PSPOLL = 1<<8, WLAN_STA_CLEAR_PS_FILT = 1<<9, + WLAN_STA_MFP = 1<<10, }; #define STA_TID_NUM 16 -- GitLab From fb7333367632c67d8b6b06fb8d906cdabb11b02a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 8 Jan 2009 13:32:00 +0200 Subject: [PATCH 0802/4982] mac80211: 802.11w - CCMP for management frames Extend CCMP to support encryption and decryption of unicast management frames. Signed-off-by: Jouni Malinen Acked-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 30 ++++++++++++++++++++++++++++++ net/mac80211/tx.c | 23 ++++++++++++++++++++++- net/mac80211/wpa.c | 18 ++++++++++++------ 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index cade2556af0..d5165895f31 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1030,6 +1030,7 @@ enum ieee80211_category { WLAN_CATEGORY_QOS = 1, WLAN_CATEGORY_DLS = 2, WLAN_CATEGORY_BACK = 3, + WLAN_CATEGORY_PUBLIC = 4, WLAN_CATEGORY_WMM = 17, }; @@ -1185,6 +1186,35 @@ static inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr) return hdr->addr1; } +/** + * ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame + * @hdr: the frame (buffer must include at least the first octet of payload) + */ +static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr) +{ + if (ieee80211_is_disassoc(hdr->frame_control) || + ieee80211_is_deauth(hdr->frame_control)) + return true; + + if (ieee80211_is_action(hdr->frame_control)) { + u8 *category; + + /* + * Action frames, excluding Public Action frames, are Robust + * Management Frames. However, if we are looking at a Protected + * frame, skip the check since the data may be encrypted and + * the frame has already been found to be a Robust Management + * Frame (by the other end). + */ + if (ieee80211_has_protected(hdr->frame_control)) + return true; + category = ((u8 *) hdr) + 24; + return *category != WLAN_CATEGORY_PUBLIC; + } + + return false; +} + /** * ieee80211_fhss_chan_to_freq - get channel frequency * @channel: the FHSS channel diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index cd6bc87eec7..50c6c4fabea 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -330,6 +330,22 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) return TX_CONTINUE; } +static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta, + struct sk_buff *skb) +{ + if (!ieee80211_is_mgmt(fc)) + return 0; + + if (sta == NULL || !test_sta_flags(sta, WLAN_STA_MFP)) + return 0; + + if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) + skb->data)) + return 0; + + return 1; +} + static ieee80211_tx_result ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) { @@ -428,10 +444,15 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) if (ieee80211_is_auth(hdr->frame_control)) break; case ALG_TKIP: - case ALG_CCMP: if (!ieee80211_is_data_present(hdr->frame_control)) tx->key = NULL; break; + case ALG_CCMP: + if (!ieee80211_is_data_present(hdr->frame_control) && + !ieee80211_use_mfp(hdr->frame_control, tx->sta, + tx->skb)) + tx->key = NULL; + break; } } diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 7aa63caf8d5..aff46adde3f 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -266,7 +266,7 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, int encrypted) { __le16 mask_fc; - int a4_included; + int a4_included, mgmt; u8 qos_tid; u8 *b_0, *aad; u16 data_len, len_a; @@ -277,12 +277,15 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, aad = scratch + 4 * AES_BLOCK_LEN; /* - * Mask FC: zero subtype b4 b5 b6 + * Mask FC: zero subtype b4 b5 b6 (if not mgmt) * Retry, PwrMgt, MoreData; set Protected */ + mgmt = ieee80211_is_mgmt(hdr->frame_control); mask_fc = hdr->frame_control; - mask_fc &= ~cpu_to_le16(0x0070 | IEEE80211_FCTL_RETRY | + mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY | IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA); + if (!mgmt) + mask_fc &= ~cpu_to_le16(0x0070); mask_fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); hdrlen = ieee80211_hdrlen(hdr->frame_control); @@ -300,8 +303,10 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, /* First block, b_0 */ b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ - /* Nonce: QoS Priority | A2 | PN */ - b_0[1] = qos_tid; + /* Nonce: Nonce Flags | A2 | PN + * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7) + */ + b_0[1] = qos_tid | (mgmt << 4); memcpy(&b_0[2], hdr->addr2, ETH_ALEN); memcpy(&b_0[8], pn, CCMP_PN_LEN); /* l(m) */ @@ -446,7 +451,8 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) hdrlen = ieee80211_hdrlen(hdr->frame_control); - if (!ieee80211_is_data(hdr->frame_control)) + if (!ieee80211_is_data(hdr->frame_control) && + !ieee80211_is_robust_mgmt_frame(hdr)) return RX_CONTINUE; data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN; -- GitLab From 765cb46a3fc856245ea68a7c961ac87c77e4ae2d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 8 Jan 2009 13:32:01 +0200 Subject: [PATCH 0803/4982] mac80211: 802.11w - Add BIP (AES-128-CMAC) Implement Broadcast/Multicast Integrity Protocol for management frame protection. This patch adds the needed definitions for the new information element (MMIE) and implementation for the new "encryption" type (though, BIP is actually not encrypting data, it provides only integrity protection). These routines will be used by a follow-on patch that enables BIP for multicast/broadcast robust management frames. Signed-off-by: Jouni Malinen Acked-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 10 +++ net/mac80211/Makefile | 1 + net/mac80211/aes_cmac.c | 135 +++++++++++++++++++++++++++++++++++++ net/mac80211/aes_cmac.h | 19 ++++++ net/mac80211/ieee80211_i.h | 2 +- net/mac80211/key.h | 10 +++ net/mac80211/wpa.c | 125 ++++++++++++++++++++++++++++++++++ net/mac80211/wpa.h | 5 ++ 8 files changed, 306 insertions(+), 1 deletion(-) create mode 100644 net/mac80211/aes_cmac.c create mode 100644 net/mac80211/aes_cmac.h diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index d5165895f31..cceb9e86c74 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -655,6 +655,15 @@ struct ieee80211_mgmt { #define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u) +/* Management MIC information element (IEEE 802.11w) */ +struct ieee80211_mmie { + u8 element_id; + u8 length; + __le16 key_id; + u8 sequence_number[6]; + u8 mic[8]; +} __attribute__ ((packed)); + /* Control frames */ struct ieee80211_rts { __le16 frame_control; @@ -1018,6 +1027,7 @@ enum ieee80211_eid { WLAN_EID_HT_INFORMATION = 61, /* 802.11i */ WLAN_EID_RSN = 48, + WLAN_EID_MMIE = 76 /* 802.11w */, WLAN_EID_WPA = 221, WLAN_EID_GENERIC = 221, WLAN_EID_VENDOR_SPECIFIC = 221, diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 7d4971aa443..5c6fadfb6a0 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile @@ -15,6 +15,7 @@ mac80211-y := \ michael.o \ tkip.o \ aes_ccm.o \ + aes_cmac.o \ cfg.o \ rx.o \ spectmgmt.o \ diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c new file mode 100644 index 00000000000..3d097b3d7b6 --- /dev/null +++ b/net/mac80211/aes_cmac.c @@ -0,0 +1,135 @@ +/* + * AES-128-CMAC with TLen 16 for IEEE 802.11w BIP + * Copyright 2008, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include +#include "key.h" +#include "aes_cmac.h" + +#define AES_BLOCK_SIZE 16 +#define AES_CMAC_KEY_LEN 16 +#define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */ +#define AAD_LEN 20 + + +static void gf_mulx(u8 *pad) +{ + int i, carry; + + carry = pad[0] & 0x80; + for (i = 0; i < AES_BLOCK_SIZE - 1; i++) + pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); + pad[AES_BLOCK_SIZE - 1] <<= 1; + if (carry) + pad[AES_BLOCK_SIZE - 1] ^= 0x87; +} + + +static void aes_128_cmac_vector(struct crypto_cipher *tfm, u8 *scratch, + size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac) +{ + u8 *cbc, *pad; + const u8 *pos, *end; + size_t i, e, left, total_len; + + cbc = scratch; + pad = scratch + AES_BLOCK_SIZE; + + memset(cbc, 0, AES_BLOCK_SIZE); + + total_len = 0; + for (e = 0; e < num_elem; e++) + total_len += len[e]; + left = total_len; + + e = 0; + pos = addr[0]; + end = pos + len[0]; + + while (left >= AES_BLOCK_SIZE) { + for (i = 0; i < AES_BLOCK_SIZE; i++) { + cbc[i] ^= *pos++; + if (pos >= end) { + e++; + pos = addr[e]; + end = pos + len[e]; + } + } + if (left > AES_BLOCK_SIZE) + crypto_cipher_encrypt_one(tfm, cbc, cbc); + left -= AES_BLOCK_SIZE; + } + + memset(pad, 0, AES_BLOCK_SIZE); + crypto_cipher_encrypt_one(tfm, pad, pad); + gf_mulx(pad); + + if (left || total_len == 0) { + for (i = 0; i < left; i++) { + cbc[i] ^= *pos++; + if (pos >= end) { + e++; + pos = addr[e]; + end = pos + len[e]; + } + } + cbc[left] ^= 0x80; + gf_mulx(pad); + } + + for (i = 0; i < AES_BLOCK_SIZE; i++) + pad[i] ^= cbc[i]; + crypto_cipher_encrypt_one(tfm, pad, pad); + memcpy(mac, pad, CMAC_TLEN); +} + + +void ieee80211_aes_cmac(struct crypto_cipher *tfm, u8 *scratch, const u8 *aad, + const u8 *data, size_t data_len, u8 *mic) +{ + const u8 *addr[3]; + size_t len[3]; + u8 zero[CMAC_TLEN]; + + memset(zero, 0, CMAC_TLEN); + addr[0] = aad; + len[0] = AAD_LEN; + addr[1] = data; + len[1] = data_len - CMAC_TLEN; + addr[2] = zero; + len[2] = CMAC_TLEN; + + aes_128_cmac_vector(tfm, scratch, 3, addr, len, mic); +} + + +struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]) +{ + struct crypto_cipher *tfm; + + tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(tfm)) + return NULL; + + crypto_cipher_setkey(tfm, key, AES_CMAC_KEY_LEN); + + return tfm; +} + + +void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm) +{ + if (tfm) + crypto_free_cipher(tfm); +} diff --git a/net/mac80211/aes_cmac.h b/net/mac80211/aes_cmac.h new file mode 100644 index 00000000000..0eb9a483150 --- /dev/null +++ b/net/mac80211/aes_cmac.h @@ -0,0 +1,19 @@ +/* + * Copyright 2008, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef AES_CMAC_H +#define AES_CMAC_H + +#include + +struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]); +void ieee80211_aes_cmac(struct crypto_cipher *tfm, u8 *scratch, const u8 *aad, + const u8 *data, size_t data_len, u8 *mic); +void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm); + +#endif /* AES_CMAC_H */ diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index b5f86cb1763..20af92abd61 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -43,7 +43,7 @@ struct ieee80211_local; /* Required encryption head and tailroom */ #define IEEE80211_ENCRYPT_HEADROOM 8 -#define IEEE80211_ENCRYPT_TAILROOM 12 +#define IEEE80211_ENCRYPT_TAILROOM 18 /* IEEE 802.11 (Ch. 9.5 Defragmentation) requires support for concurrent * reception of at least three fragmented frames. This limit can be increased diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 425816e0996..73ac28ca2ed 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h @@ -96,6 +96,16 @@ struct ieee80211_key { u8 tx_crypto_buf[6 * AES_BLOCK_LEN]; u8 rx_crypto_buf[6 * AES_BLOCK_LEN]; } ccmp; + struct { + u8 tx_pn[6]; + u8 rx_pn[6]; + struct crypto_cipher *tfm; + u32 replays; /* dot11RSNAStatsCMACReplays */ + u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ + /* scratch buffers for virt_to_page() (crypto API) */ + u8 tx_crypto_buf[2 * AES_BLOCK_LEN]; + u8 rx_crypto_buf[2 * AES_BLOCK_LEN]; + } aes_cmac; } u; /* number of times this key has been used */ diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index aff46adde3f..53e11e6ff66 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -1,5 +1,6 @@ /* * Copyright 2002-2004, Instant802 Networks, Inc. + * Copyright 2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -19,6 +20,7 @@ #include "michael.h" #include "tkip.h" #include "aes_ccm.h" +#include "aes_cmac.h" #include "wpa.h" ieee80211_tx_result @@ -491,3 +493,126 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) return RX_CONTINUE; } + + +static void bip_aad(struct sk_buff *skb, u8 *aad) +{ + /* BIP AAD: FC(masked) || A1 || A2 || A3 */ + + /* FC type/subtype */ + aad[0] = skb->data[0]; + /* Mask FC Retry, PwrMgt, MoreData flags to zero */ + aad[1] = skb->data[1] & ~(BIT(4) | BIT(5) | BIT(6)); + /* A1 || A2 || A3 */ + memcpy(aad + 2, skb->data + 4, 3 * ETH_ALEN); +} + + +static inline void bip_ipn_swap(u8 *d, const u8 *s) +{ + *d++ = s[5]; + *d++ = s[4]; + *d++ = s[3]; + *d++ = s[2]; + *d++ = s[1]; + *d = s[0]; +} + + +ieee80211_tx_result +ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx) +{ + struct sk_buff *skb = tx->skb; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_key *key = tx->key; + struct ieee80211_mmie *mmie; + u8 *pn, aad[20]; + int i; + + if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { + /* hwaccel */ + info->control.hw_key = &tx->key->conf; + return 0; + } + + if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie))) + return TX_DROP; + + mmie = (struct ieee80211_mmie *) skb_put(skb, sizeof(*mmie)); + mmie->element_id = WLAN_EID_MMIE; + mmie->length = sizeof(*mmie) - 2; + mmie->key_id = cpu_to_le16(key->conf.keyidx); + + /* PN = PN + 1 */ + pn = key->u.aes_cmac.tx_pn; + + for (i = sizeof(key->u.aes_cmac.tx_pn) - 1; i >= 0; i--) { + pn[i]++; + if (pn[i]) + break; + } + bip_ipn_swap(mmie->sequence_number, pn); + + bip_aad(skb, aad); + + /* + * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64) + */ + ieee80211_aes_cmac(key->u.aes_cmac.tfm, key->u.aes_cmac.tx_crypto_buf, + aad, skb->data + 24, skb->len - 24, mmie->mic); + + return TX_CONTINUE; +} + + +ieee80211_rx_result +ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx) +{ + struct sk_buff *skb = rx->skb; + struct ieee80211_key *key = rx->key; + struct ieee80211_mmie *mmie; + u8 aad[20], mic[8], ipn[6]; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + + if (!ieee80211_is_mgmt(hdr->frame_control)) + return RX_CONTINUE; + + if ((rx->status->flag & RX_FLAG_DECRYPTED) && + (rx->status->flag & RX_FLAG_IV_STRIPPED)) + return RX_CONTINUE; + + if (skb->len < 24 + sizeof(*mmie)) + return RX_DROP_UNUSABLE; + + mmie = (struct ieee80211_mmie *) + (skb->data + skb->len - sizeof(*mmie)); + if (mmie->element_id != WLAN_EID_MMIE || + mmie->length != sizeof(*mmie) - 2) + return RX_DROP_UNUSABLE; /* Invalid MMIE */ + + bip_ipn_swap(ipn, mmie->sequence_number); + + if (memcmp(ipn, key->u.aes_cmac.rx_pn, 6) <= 0) { + key->u.aes_cmac.replays++; + return RX_DROP_UNUSABLE; + } + + if (!(rx->status->flag & RX_FLAG_DECRYPTED)) { + /* hardware didn't decrypt/verify MIC */ + bip_aad(skb, aad); + ieee80211_aes_cmac(key->u.aes_cmac.tfm, + key->u.aes_cmac.rx_crypto_buf, aad, + skb->data + 24, skb->len - 24, mic); + if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { + key->u.aes_cmac.icverrors++; + return RX_DROP_UNUSABLE; + } + } + + memcpy(key->u.aes_cmac.rx_pn, ipn, 6); + + /* Remove MMIE */ + skb_trim(skb, skb->len - sizeof(*mmie)); + + return RX_CONTINUE; +} diff --git a/net/mac80211/wpa.h b/net/mac80211/wpa.h index d42d221d8a1..baba0608313 100644 --- a/net/mac80211/wpa.h +++ b/net/mac80211/wpa.h @@ -28,4 +28,9 @@ ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx); ieee80211_rx_result ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx); +ieee80211_tx_result +ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx); +ieee80211_rx_result +ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx); + #endif /* WPA_H */ -- GitLab From 3cfcf6ac6d69dc290e96416731eea5c88ac7d426 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 8 Jan 2009 13:32:02 +0200 Subject: [PATCH 0804/4982] mac80211: 802.11w - Use BIP (AES-128-CMAC) Add mechanism for managing BIP keys (IGTK) and integrate BIP into the TX/RX paths. Signed-off-by: Jouni Malinen Acked-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/pcu.c | 3 ++ include/linux/ieee80211.h | 1 + include/linux/nl80211.h | 6 ++- include/net/cfg80211.h | 5 ++ include/net/mac80211.h | 2 + net/mac80211/cfg.c | 31 +++++++++++ net/mac80211/debugfs_key.c | 79 +++++++++++++++++++++++++++- net/mac80211/debugfs_key.h | 10 ++++ net/mac80211/ieee80211_i.h | 5 +- net/mac80211/key.c | 62 +++++++++++++++++++++- net/mac80211/key.h | 6 +++ net/mac80211/rx.c | 90 +++++++++++++++++++++++++++++--- net/mac80211/tx.c | 9 ++++ net/wireless/nl80211.c | 29 +++++++--- 14 files changed, 317 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/ath5k/pcu.c b/drivers/net/wireless/ath5k/pcu.c index 5b416ed6529..e758b70ab7e 100644 --- a/drivers/net/wireless/ath5k/pcu.c +++ b/drivers/net/wireless/ath5k/pcu.c @@ -1026,6 +1026,9 @@ int ath5k_keycache_type(const struct ieee80211_key_conf *key) return AR5K_KEYTABLE_TYPE_40; else if (key->keylen == LEN_WEP104) return AR5K_KEYTABLE_TYPE_104; + return -EINVAL; + default: + return -EINVAL; } return -EINVAL; } diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index cceb9e86c74..df98a8a549a 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1139,6 +1139,7 @@ enum ieee80211_back_parties { /* reserved: 0x000FAC03 */ #define WLAN_CIPHER_SUITE_CCMP 0x000FAC04 #define WLAN_CIPHER_SUITE_WEP104 0x000FAC05 +#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06 #define WLAN_MAX_KEY_LEN 32 diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 218f0e73a7a..ee742bc9761 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -72,8 +72,8 @@ * * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified * by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC. - * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT or - * %NL80211_ATTR_KEY_THRESHOLD. + * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT, + * %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD. * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA, * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC and %NL80211_ATTR_KEY_CIPHER * attributes. @@ -346,6 +346,8 @@ enum nl80211_attrs { NL80211_ATTR_WIPHY_FREQ, NL80211_ATTR_WIPHY_CHANNEL_TYPE, + NL80211_ATTR_KEY_DEFAULT_MGMT, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 6619ed10613..df78abc496f 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -473,6 +473,8 @@ struct ieee80211_channel; * * @set_default_key: set the default key on an interface * + * @set_default_mgmt_key: set the default management frame key on an interface + * * @add_beacon: Add a beacon with given parameters, @head, @interval * and @dtim_period will be valid, @tail is optional. * @set_beacon: Change the beacon parameters for an access point mode @@ -520,6 +522,9 @@ struct cfg80211_ops { int (*set_default_key)(struct wiphy *wiphy, struct net_device *netdev, u8 key_index); + int (*set_default_mgmt_key)(struct wiphy *wiphy, + struct net_device *netdev, + u8 key_index); int (*add_beacon)(struct wiphy *wiphy, struct net_device *dev, struct beacon_parameters *info); diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 8a305bfdb87..61f1f37a9e2 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -651,11 +651,13 @@ struct ieee80211_if_conf { * @ALG_WEP: WEP40 or WEP104 * @ALG_TKIP: TKIP * @ALG_CCMP: CCMP (AES) + * @ALG_AES_CMAC: AES-128-CMAC */ enum ieee80211_key_alg { ALG_WEP, ALG_TKIP, ALG_CCMP, + ALG_AES_CMAC, }; /** diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 309d9189aa4..72c10691543 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -133,6 +133,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, case WLAN_CIPHER_SUITE_CCMP: alg = ALG_CCMP; break; + case WLAN_CIPHER_SUITE_AES_CMAC: + alg = ALG_AES_CMAC; + break; default: return -EINVAL; } @@ -275,6 +278,17 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, else params.cipher = WLAN_CIPHER_SUITE_WEP104; break; + case ALG_AES_CMAC: + params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; + seq[0] = key->u.aes_cmac.tx_pn[5]; + seq[1] = key->u.aes_cmac.tx_pn[4]; + seq[2] = key->u.aes_cmac.tx_pn[3]; + seq[3] = key->u.aes_cmac.tx_pn[2]; + seq[4] = key->u.aes_cmac.tx_pn[1]; + seq[5] = key->u.aes_cmac.tx_pn[0]; + params.seq = seq; + params.seq_len = 6; + break; } params.key = key->conf.key; @@ -304,6 +318,22 @@ static int ieee80211_config_default_key(struct wiphy *wiphy, return 0; } +static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy, + struct net_device *dev, + u8 key_idx) +{ + struct ieee80211_sub_if_data *sdata; + + rcu_read_lock(); + + sdata = IEEE80211_DEV_TO_SUB_IF(dev); + ieee80211_set_default_mgmt_key(sdata, key_idx); + + rcu_read_unlock(); + + return 0; +} + static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) { struct ieee80211_sub_if_data *sdata = sta->sdata; @@ -1153,6 +1183,7 @@ struct cfg80211_ops mac80211_config_ops = { .del_key = ieee80211_del_key, .get_key = ieee80211_get_key, .set_default_key = ieee80211_config_default_key, + .set_default_mgmt_key = ieee80211_config_default_mgmt_key, .add_beacon = ieee80211_add_beacon, .set_beacon = ieee80211_set_beacon, .del_beacon = ieee80211_del_beacon, diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index 6424ac565ae..99c752588b3 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c @@ -76,6 +76,9 @@ static ssize_t key_algorithm_read(struct file *file, case ALG_CCMP: alg = "CCMP\n"; break; + case ALG_AES_CMAC: + alg = "AES-128-CMAC\n"; + break; default: return 0; } @@ -105,6 +108,12 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]); break; + case ALG_AES_CMAC: + tpn = key->u.aes_cmac.tx_pn; + len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", + tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], + tpn[5]); + break; default: return 0; } @@ -142,6 +151,14 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, } len = p - buf; break; + case ALG_AES_CMAC: + rpn = key->u.aes_cmac.rx_pn; + p += scnprintf(p, sizeof(buf)+buf-p, + "%02x%02x%02x%02x%02x%02x\n", + rpn[0], rpn[1], rpn[2], + rpn[3], rpn[4], rpn[5]); + len = p - buf; + break; default: return 0; } @@ -156,13 +173,40 @@ static ssize_t key_replays_read(struct file *file, char __user *userbuf, char buf[20]; int len; - if (key->conf.alg != ALG_CCMP) + switch (key->conf.alg) { + case ALG_CCMP: + len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays); + break; + case ALG_AES_CMAC: + len = scnprintf(buf, sizeof(buf), "%u\n", + key->u.aes_cmac.replays); + break; + default: return 0; - len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays); + } return simple_read_from_buffer(userbuf, count, ppos, buf, len); } KEY_OPS(replays); +static ssize_t key_icverrors_read(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct ieee80211_key *key = file->private_data; + char buf[20]; + int len; + + switch (key->conf.alg) { + case ALG_AES_CMAC: + len = scnprintf(buf, sizeof(buf), "%u\n", + key->u.aes_cmac.icverrors); + break; + default: + return 0; + } + return simple_read_from_buffer(userbuf, count, ppos, buf, len); +} +KEY_OPS(icverrors); + static ssize_t key_key_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { @@ -222,6 +266,7 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key) DEBUGFS_ADD(tx_spec); DEBUGFS_ADD(rx_spec); DEBUGFS_ADD(replays); + DEBUGFS_ADD(icverrors); DEBUGFS_ADD(key); DEBUGFS_ADD(ifindex); }; @@ -243,6 +288,7 @@ void ieee80211_debugfs_key_remove(struct ieee80211_key *key) DEBUGFS_DEL(tx_spec); DEBUGFS_DEL(rx_spec); DEBUGFS_DEL(replays); + DEBUGFS_DEL(icverrors); DEBUGFS_DEL(key); DEBUGFS_DEL(ifindex); @@ -280,6 +326,35 @@ void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata) sdata->common_debugfs.default_key = NULL; } +void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) +{ + char buf[50]; + struct ieee80211_key *key; + + if (!sdata->debugfsdir) + return; + + /* this is running under the key lock */ + + key = sdata->default_mgmt_key; + if (key) { + sprintf(buf, "../keys/%d", key->debugfs.cnt); + sdata->common_debugfs.default_mgmt_key = + debugfs_create_symlink("default_mgmt_key", + sdata->debugfsdir, buf); + } else + ieee80211_debugfs_key_remove_mgmt_default(sdata); +} + +void ieee80211_debugfs_key_remove_mgmt_default(struct ieee80211_sub_if_data *sdata) +{ + if (!sdata) + return; + + debugfs_remove(sdata->common_debugfs.default_mgmt_key); + sdata->common_debugfs.default_mgmt_key = NULL; +} + void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, struct sta_info *sta) { diff --git a/net/mac80211/debugfs_key.h b/net/mac80211/debugfs_key.h index b1a3754ee24..54717b4e137 100644 --- a/net/mac80211/debugfs_key.h +++ b/net/mac80211/debugfs_key.h @@ -6,6 +6,10 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key); void ieee80211_debugfs_key_remove(struct ieee80211_key *key); void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata); void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata); +void ieee80211_debugfs_key_add_mgmt_default( + struct ieee80211_sub_if_data *sdata); +void ieee80211_debugfs_key_remove_mgmt_default( + struct ieee80211_sub_if_data *sdata); void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, struct sta_info *sta); #else @@ -19,6 +23,12 @@ static inline void ieee80211_debugfs_key_add_default( static inline void ieee80211_debugfs_key_remove_default( struct ieee80211_sub_if_data *sdata) {} +static inline void ieee80211_debugfs_key_add_mgmt_default( + struct ieee80211_sub_if_data *sdata) +{} +static inline void ieee80211_debugfs_key_remove_mgmt_default( + struct ieee80211_sub_if_data *sdata) +{} static inline void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, struct sta_info *sta) {} diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 20af92abd61..8c3245717c5 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -409,8 +409,10 @@ struct ieee80211_sub_if_data { unsigned int fragment_next; #define NUM_DEFAULT_KEYS 4 - struct ieee80211_key *keys[NUM_DEFAULT_KEYS]; +#define NUM_DEFAULT_MGMT_KEYS 2 + struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; struct ieee80211_key *default_key; + struct ieee80211_key *default_mgmt_key; u16 sequence_number; @@ -482,6 +484,7 @@ struct ieee80211_sub_if_data { } debugfs; struct { struct dentry *default_key; + struct dentry *default_mgmt_key; } common_debugfs; #ifdef CONFIG_MAC80211_MESH diff --git a/net/mac80211/key.c b/net/mac80211/key.c index b0a025c9b61..19b480de4bb 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -18,6 +18,7 @@ #include "ieee80211_i.h" #include "debugfs_key.h" #include "aes_ccm.h" +#include "aes_cmac.h" /** @@ -215,13 +216,38 @@ void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx) spin_unlock_irqrestore(&sdata->local->key_lock, flags); } +static void +__ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx) +{ + struct ieee80211_key *key = NULL; + + if (idx >= NUM_DEFAULT_KEYS && + idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) + key = sdata->keys[idx]; + + rcu_assign_pointer(sdata->default_mgmt_key, key); + + if (key) + add_todo(key, KEY_FLAG_TODO_DEFMGMTKEY); +} + +void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, + int idx) +{ + unsigned long flags; + + spin_lock_irqsave(&sdata->local->key_lock, flags); + __ieee80211_set_default_mgmt_key(sdata, idx); + spin_unlock_irqrestore(&sdata->local->key_lock, flags); +} + static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, struct sta_info *sta, struct ieee80211_key *old, struct ieee80211_key *new) { - int idx, defkey; + int idx, defkey, defmgmtkey; if (new) list_add(&new->list, &sdata->key_list); @@ -237,13 +263,19 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, idx = new->conf.keyidx; defkey = old && sdata->default_key == old; + defmgmtkey = old && sdata->default_mgmt_key == old; if (defkey && !new) __ieee80211_set_default_key(sdata, -1); + if (defmgmtkey && !new) + __ieee80211_set_default_mgmt_key(sdata, -1); rcu_assign_pointer(sdata->keys[idx], new); if (defkey && new) __ieee80211_set_default_key(sdata, new->conf.keyidx); + if (defmgmtkey && new) + __ieee80211_set_default_mgmt_key(sdata, + new->conf.keyidx); } if (old) { @@ -262,7 +294,7 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, { struct ieee80211_key *key; - BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS); + BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS); key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL); if (!key) @@ -291,6 +323,10 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, key->conf.iv_len = CCMP_HDR_LEN; key->conf.icv_len = CCMP_MIC_LEN; break; + case ALG_AES_CMAC: + key->conf.iv_len = 0; + key->conf.icv_len = sizeof(struct ieee80211_mmie); + break; } memcpy(key->conf.key, key_data, key_len); INIT_LIST_HEAD(&key->list); @@ -308,6 +344,19 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, } } + if (alg == ALG_AES_CMAC) { + /* + * Initialize AES key state here as an optimization so that + * it does not need to be initialized for every packet. + */ + key->u.aes_cmac.tfm = + ieee80211_aes_cmac_key_setup(key_data); + if (!key->u.aes_cmac.tfm) { + kfree(key); + return NULL; + } + } + return key; } @@ -461,6 +510,8 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key) if (key->conf.alg == ALG_CCMP) ieee80211_aes_key_free(key->u.ccmp.tfm); + if (key->conf.alg == ALG_AES_CMAC) + ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); ieee80211_debugfs_key_remove(key); kfree(key); @@ -483,6 +534,7 @@ static void __ieee80211_key_todo(void) list_del_init(&key->todo); todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS | KEY_FLAG_TODO_DEFKEY | + KEY_FLAG_TODO_DEFMGMTKEY | KEY_FLAG_TODO_HWACCEL_ADD | KEY_FLAG_TODO_HWACCEL_REMOVE | KEY_FLAG_TODO_DELETE); @@ -500,6 +552,11 @@ static void __ieee80211_key_todo(void) ieee80211_debugfs_key_add_default(key->sdata); work_done = true; } + if (todoflags & KEY_FLAG_TODO_DEFMGMTKEY) { + ieee80211_debugfs_key_remove_mgmt_default(key->sdata); + ieee80211_debugfs_key_add_mgmt_default(key->sdata); + work_done = true; + } if (todoflags & KEY_FLAG_TODO_HWACCEL_ADD) { ieee80211_key_enable_hw_accel(key); work_done = true; @@ -535,6 +592,7 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) ieee80211_key_lock(); ieee80211_debugfs_key_remove_default(sdata); + ieee80211_debugfs_key_remove_mgmt_default(sdata); spin_lock_irqsave(&sdata->local->key_lock, flags); list_for_each_entry_safe(key, tmp, &sdata->key_list, list) diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 73ac28ca2ed..215d3ef42a4 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h @@ -46,6 +46,8 @@ struct sta_info; * acceleration. * @KEY_FLAG_TODO_DEFKEY: Key is default key and debugfs needs to be updated. * @KEY_FLAG_TODO_ADD_DEBUGFS: Key needs to be added to debugfs. + * @KEY_FLAG_TODO_DEFMGMTKEY: Key is default management key and debugfs needs + * to be updated. */ enum ieee80211_internal_key_flags { KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0), @@ -54,6 +56,7 @@ enum ieee80211_internal_key_flags { KEY_FLAG_TODO_HWACCEL_REMOVE = BIT(3), KEY_FLAG_TODO_DEFKEY = BIT(4), KEY_FLAG_TODO_ADD_DEBUGFS = BIT(5), + KEY_FLAG_TODO_DEFMGMTKEY = BIT(6), }; struct tkip_ctx { @@ -124,6 +127,7 @@ struct ieee80211_key { struct dentry *tx_spec; struct dentry *rx_spec; struct dentry *replays; + struct dentry *icverrors; struct dentry *key; struct dentry *ifindex; int cnt; @@ -150,6 +154,8 @@ void ieee80211_key_link(struct ieee80211_key *key, struct sta_info *sta); void ieee80211_key_free(struct ieee80211_key *key); void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx); +void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, + int idx); void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index b68e082e99c..abc3aa583ca 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -446,6 +446,52 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) return RX_CONTINUE; } + +static int ieee80211_is_unicast_robust_mgmt_frame(struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + + if (skb->len < 24 || is_multicast_ether_addr(hdr->addr1)) + return 0; + + return ieee80211_is_robust_mgmt_frame(hdr); +} + + +static int ieee80211_is_multicast_robust_mgmt_frame(struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + + if (skb->len < 24 || !is_multicast_ether_addr(hdr->addr1)) + return 0; + + return ieee80211_is_robust_mgmt_frame(hdr); +} + + +/* Get the BIP key index from MMIE; return -1 if this is not a BIP frame */ +static int ieee80211_get_mmie_keyidx(struct sk_buff *skb) +{ + struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *) skb->data; + struct ieee80211_mmie *mmie; + + if (skb->len < 24 + sizeof(*mmie) || + !is_multicast_ether_addr(hdr->da)) + return -1; + + if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) hdr)) + return -1; /* not a robust management frame */ + + mmie = (struct ieee80211_mmie *) + (skb->data + skb->len - sizeof(*mmie)); + if (mmie->element_id != WLAN_EID_MMIE || + mmie->length != sizeof(*mmie) - 2) + return -1; + + return le16_to_cpu(mmie->key_id); +} + + static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) { @@ -561,21 +607,23 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) int hdrlen; ieee80211_rx_result result = RX_DROP_UNUSABLE; struct ieee80211_key *stakey = NULL; + int mmie_keyidx = -1; /* * Key selection 101 * - * There are three types of keys: + * There are four types of keys: * - GTK (group keys) + * - IGTK (group keys for management frames) * - PTK (pairwise keys) * - STK (station-to-station pairwise keys) * * When selecting a key, we have to distinguish between multicast * (including broadcast) and unicast frames, the latter can only - * use PTKs and STKs while the former always use GTKs. Unless, of - * course, actual WEP keys ("pre-RSNA") are used, then unicast - * frames can also use key indizes like GTKs. Hence, if we don't - * have a PTK/STK we check the key index for a WEP key. + * use PTKs and STKs while the former always use GTKs and IGTKs. + * Unless, of course, actual WEP keys ("pre-RSNA") are used, then + * unicast frames can also use key indices like GTKs. Hence, if we + * don't have a PTK/STK we check the key index for a WEP key. * * Note that in a regular BSS, multicast frames are sent by the * AP only, associated stations unicast the frame to the AP first @@ -588,8 +636,14 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) * possible. */ - if (!ieee80211_has_protected(hdr->frame_control)) - return RX_CONTINUE; + if (!ieee80211_has_protected(hdr->frame_control)) { + if (!ieee80211_is_mgmt(hdr->frame_control) || + rx->sta == NULL || !test_sta_flags(rx->sta, WLAN_STA_MFP)) + return RX_CONTINUE; + mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb); + if (mmie_keyidx < 0) + return RX_CONTINUE; + } /* * No point in finding a key and decrypting if the frame is neither @@ -603,6 +657,16 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) if (!is_multicast_ether_addr(hdr->addr1) && stakey) { rx->key = stakey; + } else if (mmie_keyidx >= 0) { + /* Broadcast/multicast robust management frame / BIP */ + if ((rx->status->flag & RX_FLAG_DECRYPTED) && + (rx->status->flag & RX_FLAG_IV_STRIPPED)) + return RX_CONTINUE; + + if (mmie_keyidx < NUM_DEFAULT_KEYS || + mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) + return RX_DROP_MONITOR; /* unexpected BIP keyidx */ + rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]); } else { /* * The device doesn't give us the IV so we won't be @@ -665,6 +729,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) case ALG_CCMP: result = ieee80211_crypto_ccmp_decrypt(rx); break; + case ALG_AES_CMAC: + result = ieee80211_crypto_aes_cmac_decrypt(rx); + break; } /* either the frame has been decrypted or will be dropped */ @@ -1112,6 +1179,15 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) /* Drop unencrypted frames if key is set. */ if (unlikely(!ieee80211_has_protected(fc) && !ieee80211_is_nullfunc(fc) && + (!ieee80211_is_mgmt(fc) || + (ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && + rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP))) && + (rx->key || rx->sdata->drop_unencrypted))) + return -EACCES; + /* BIP does not use Protected field, so need to check MMIE */ + if (unlikely(rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP) && + ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && + ieee80211_get_mmie_keyidx(rx->skb) < 0 && (rx->key || rx->sdata->drop_unencrypted))) return -EACCES; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 50c6c4fabea..ad53ea9e9c7 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -425,6 +425,9 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) tx->key = NULL; else if (tx->sta && (key = rcu_dereference(tx->sta->key))) tx->key = key; + else if (ieee80211_is_mgmt(hdr->frame_control) && + (key = rcu_dereference(tx->sdata->default_mgmt_key))) + tx->key = key; else if ((key = rcu_dereference(tx->sdata->default_key))) tx->key = key; else if (tx->sdata->drop_unencrypted && @@ -453,6 +456,10 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) tx->skb)) tx->key = NULL; break; + case ALG_AES_CMAC: + if (!ieee80211_is_mgmt(hdr->frame_control)) + tx->key = NULL; + break; } } @@ -808,6 +815,8 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) return ieee80211_crypto_tkip_encrypt(tx); case ALG_CCMP: return ieee80211_crypto_ccmp_encrypt(tx); + case ALG_AES_CMAC: + return ieee80211_crypto_aes_cmac_encrypt(tx); } /* not reached */ diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 1e728fff474..123d3b160fa 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -738,7 +738,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NL80211_ATTR_KEY_IDX]) key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); - if (key_idx > 3) + if (key_idx > 5) return -EINVAL; if (info->attrs[NL80211_ATTR_MAC]) @@ -804,30 +804,41 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) int err; struct net_device *dev; u8 key_idx; + int (*func)(struct wiphy *wiphy, struct net_device *netdev, + u8 key_index); if (!info->attrs[NL80211_ATTR_KEY_IDX]) return -EINVAL; key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); - if (key_idx > 3) + if (info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]) { + if (key_idx < 4 || key_idx > 5) + return -EINVAL; + } else if (key_idx > 3) return -EINVAL; /* currently only support setting default key */ - if (!info->attrs[NL80211_ATTR_KEY_DEFAULT]) + if (!info->attrs[NL80211_ATTR_KEY_DEFAULT] && + !info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]) return -EINVAL; err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) return err; - if (!drv->ops->set_default_key) { + if (info->attrs[NL80211_ATTR_KEY_DEFAULT]) + func = drv->ops->set_default_key; + else + func = drv->ops->set_default_mgmt_key; + + if (!func) { err = -EOPNOTSUPP; goto out; } rtnl_lock(); - err = drv->ops->set_default_key(&drv->wiphy, dev, key_idx); + err = func(&drv->wiphy, dev, key_idx); rtnl_unlock(); out: @@ -863,7 +874,7 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NL80211_ATTR_MAC]) mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); - if (key_idx > 3) + if (key_idx > 5) return -EINVAL; /* @@ -894,6 +905,10 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) if (params.key_len != 13) return -EINVAL; break; + case WLAN_CIPHER_SUITE_AES_CMAC: + if (params.key_len != 16) + return -EINVAL; + break; default: return -EINVAL; } @@ -928,7 +943,7 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NL80211_ATTR_KEY_IDX]) key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); - if (key_idx > 3) + if (key_idx > 5) return -EINVAL; if (info->attrs[NL80211_ATTR_MAC]) -- GitLab From 54604d3a827b37525ef017adba313c7112e0f484 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 8 Jan 2009 13:32:03 +0200 Subject: [PATCH 0805/4982] mac80211: 802.11w - WEXT parameter for setting mgmt cipher Add a new IW_AUTH parameter for setting cipher suite for multicast/broadcast management frames. This is for full-mac drivers that take care of RSN IE generation for (re)association request frames. Signed-off-by: Jouni Malinen Acked-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/wireless.h | 5 ++++- net/mac80211/wext.c | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/linux/wireless.h b/include/linux/wireless.h index d7958f9b52c..d426dce47e7 100644 --- a/include/linux/wireless.h +++ b/include/linux/wireless.h @@ -577,18 +577,21 @@ #define IW_AUTH_RX_UNENCRYPTED_EAPOL 8 #define IW_AUTH_ROAMING_CONTROL 9 #define IW_AUTH_PRIVACY_INVOKED 10 +#define IW_AUTH_CIPHER_GROUP_MGMT 11 /* IW_AUTH_WPA_VERSION values (bit field) */ #define IW_AUTH_WPA_VERSION_DISABLED 0x00000001 #define IW_AUTH_WPA_VERSION_WPA 0x00000002 #define IW_AUTH_WPA_VERSION_WPA2 0x00000004 -/* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */ +/* IW_AUTH_PAIRWISE_CIPHER, IW_AUTH_GROUP_CIPHER, and IW_AUTH_CIPHER_GROUP_MGMT + * values (bit field) */ #define IW_AUTH_CIPHER_NONE 0x00000001 #define IW_AUTH_CIPHER_WEP40 0x00000002 #define IW_AUTH_CIPHER_TKIP 0x00000004 #define IW_AUTH_CIPHER_CCMP 0x00000008 #define IW_AUTH_CIPHER_WEP104 0x00000010 +#define IW_AUTH_CIPHER_AES_CMAC 0x00000020 /* IW_AUTH_KEY_MGMT values (bit field) */ #define IW_AUTH_KEY_MGMT_802_1X 1 diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 1e5b29bdb3a..c3b2dd5706f 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -927,6 +927,7 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev, case IW_AUTH_WPA_ENABLED: case IW_AUTH_RX_UNENCRYPTED_EAPOL: case IW_AUTH_KEY_MGMT: + case IW_AUTH_CIPHER_GROUP_MGMT: break; case IW_AUTH_CIPHER_PAIRWISE: if (sdata->vif.type == NL80211_IFTYPE_STATION) { -- GitLab From 22787dbaa3b952602542506e0426ea6d5f104042 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 8 Jan 2009 13:32:04 +0200 Subject: [PATCH 0806/4982] mac80211: 802.11w - WEXT configuration for IGTK Added new SIOCSIWENCODEEXT algorithm for configuring BIP (AES-CMAC) keys (IGTK). Signed-off-by: Jouni Malinen Acked-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/wireless.h | 1 + net/mac80211/wext.c | 62 +++++++++++++++++++++++++++++++--------- 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/include/linux/wireless.h b/include/linux/wireless.h index d426dce47e7..5d1f3fbffd7 100644 --- a/include/linux/wireless.h +++ b/include/linux/wireless.h @@ -615,6 +615,7 @@ #define IW_ENCODE_ALG_TKIP 2 #define IW_ENCODE_ALG_CCMP 3 #define IW_ENCODE_ALG_PMK 4 +#define IW_ENCODE_ALG_AES_CMAC 5 /* struct iw_encode_ext ->ext_flags */ #define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001 #define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002 diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index c3b2dd5706f..7ba1d5ba3af 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -37,7 +37,14 @@ static int ieee80211_set_encryption(struct ieee80211_sub_if_data *sdata, u8 *sta struct ieee80211_key *key; int err; - if (idx < 0 || idx >= NUM_DEFAULT_KEYS) { + if (alg == ALG_AES_CMAC) { + if (idx < NUM_DEFAULT_KEYS || + idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) { + printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d " + "(BIP)\n", sdata->dev->name, idx); + return -EINVAL; + } + } else if (idx < 0 || idx >= NUM_DEFAULT_KEYS) { printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n", sdata->dev->name, idx); return -EINVAL; @@ -103,6 +110,9 @@ static int ieee80211_set_encryption(struct ieee80211_sub_if_data *sdata, u8 *sta if (set_tx_key || (!sta && !sdata->default_key && key)) ieee80211_set_default_key(sdata, idx); + if (alg == ALG_AES_CMAC && + (set_tx_key || (!sta && !sdata->default_mgmt_key && key))) + ieee80211_set_default_mgmt_key(sdata, idx); } out_unlock: @@ -1048,6 +1058,9 @@ static int ieee80211_ioctl_siwencodeext(struct net_device *dev, case IW_ENCODE_ALG_CCMP: alg = ALG_CCMP; break; + case IW_ENCODE_ALG_AES_CMAC: + alg = ALG_AES_CMAC; + break; default: return -EOPNOTSUPP; } @@ -1056,20 +1069,41 @@ static int ieee80211_ioctl_siwencodeext(struct net_device *dev, remove = 1; idx = erq->flags & IW_ENCODE_INDEX; - if (idx < 1 || idx > 4) { - idx = -1; - if (!sdata->default_key) - idx = 0; - else for (i = 0; i < NUM_DEFAULT_KEYS; i++) { - if (sdata->default_key == sdata->keys[i]) { - idx = i; - break; + if (alg == ALG_AES_CMAC) { + if (idx < NUM_DEFAULT_KEYS + 1 || + idx > NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) { + idx = -1; + if (!sdata->default_mgmt_key) + idx = 0; + else for (i = NUM_DEFAULT_KEYS; + i < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS; + i++) { + if (sdata->default_mgmt_key == sdata->keys[i]) + { + idx = i; + break; + } } - } - if (idx < 0) - return -EINVAL; - } else - idx--; + if (idx < 0) + return -EINVAL; + } else + idx--; + } else { + if (idx < 1 || idx > 4) { + idx = -1; + if (!sdata->default_key) + idx = 0; + else for (i = 0; i < NUM_DEFAULT_KEYS; i++) { + if (sdata->default_key == sdata->keys[i]) { + idx = i; + break; + } + } + if (idx < 0) + return -EINVAL; + } else + idx--; + } return ieee80211_set_encryption(sdata, ext->addr.sa_data, idx, alg, remove, -- GitLab From fdfacf0ae2e8339098b1164d2317b792d7662c0a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 8 Jan 2009 13:32:05 +0200 Subject: [PATCH 0807/4982] mac80211: 802.11w - Configuration of MFP disabled/optional/required Add new WEXT IW_AUTH_* parameter for setting MFP disabled/optional/required. Signed-off-by: Jouni Malinen Acked-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/wireless.h | 6 ++++++ net/mac80211/ieee80211_i.h | 6 ++++++ net/mac80211/mlme.c | 4 ++++ net/mac80211/wext.c | 7 +++++++ 4 files changed, 23 insertions(+) diff --git a/include/linux/wireless.h b/include/linux/wireless.h index 5d1f3fbffd7..cb24204851f 100644 --- a/include/linux/wireless.h +++ b/include/linux/wireless.h @@ -578,6 +578,7 @@ #define IW_AUTH_ROAMING_CONTROL 9 #define IW_AUTH_PRIVACY_INVOKED 10 #define IW_AUTH_CIPHER_GROUP_MGMT 11 +#define IW_AUTH_MFP 12 /* IW_AUTH_WPA_VERSION values (bit field) */ #define IW_AUTH_WPA_VERSION_DISABLED 0x00000001 @@ -607,6 +608,11 @@ #define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming * control */ +/* IW_AUTH_MFP (management frame protection) values */ +#define IW_AUTH_MFP_DISABLED 0 /* MFP disabled */ +#define IW_AUTH_MFP_OPTIONAL 1 /* MFP optional */ +#define IW_AUTH_MFP_REQUIRED 2 /* MFP required */ + /* SIOCSIWENCODEEXT definitions */ #define IW_ENCODE_SEQ_MAX_SIZE 8 /* struct iw_encode_ext ->alg */ diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 8c3245717c5..212c732fbba 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -320,6 +320,12 @@ struct ieee80211_if_sta { int auth_alg; /* currently used IEEE 802.11 authentication algorithm */ int auth_transaction; + enum { + IEEE80211_MFP_DISABLED, + IEEE80211_MFP_OPTIONAL, + IEEE80211_MFP_REQUIRED + } mfp; /* management frame protection */ + unsigned long ibss_join_req; struct sk_buff *probe_resp; /* ProbeResp template for IBSS */ u32 supp_rates_bits[IEEE80211_NUM_BANDS]; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index bc8a7f1a6a1..42c5f981c71 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2317,6 +2317,10 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, selected->ssid_len); ieee80211_sta_set_bssid(sdata, selected->bssid); ieee80211_sta_def_wmm_params(sdata, selected); + if (sdata->u.sta.mfp == IEEE80211_MFP_REQUIRED) + sdata->u.sta.flags |= IEEE80211_STA_MFP_ENABLED; + else + sdata->u.sta.flags &= ~IEEE80211_STA_MFP_ENABLED; /* Send out direct probe if no probe resp was received or * the one we have is outdated diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 7ba1d5ba3af..2dd387495df 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -975,6 +975,13 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev, else ret = -EOPNOTSUPP; break; + case IW_AUTH_MFP: + if (sdata->vif.type == NL80211_IFTYPE_STATION || + sdata->vif.type == NL80211_IFTYPE_ADHOC) + sdata->u.sta.mfp = data->value; + else + ret = -EOPNOTSUPP; + break; default: ret = -EOPNOTSUPP; break; -- GitLab From fea147328908b7e2bfcaf9dc4377909d5507ca35 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 8 Jan 2009 13:32:06 +0200 Subject: [PATCH 0808/4982] mac80211: 802.11w - SA Query processing Process SA Query Requests for client mode in mac80211. AP side processing of SA Query Response frames is in user space (hostapd). Signed-off-by: Jouni Malinen Acked-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 14 ++++++++ net/mac80211/rx.c | 69 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index df98a8a549a..9fe1948d28d 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -527,6 +527,8 @@ struct ieee80211_tim_ie { u8 virtual_map[0]; } __attribute__ ((packed)); +#define WLAN_SA_QUERY_TR_ID_LEN 16 + struct ieee80211_mgmt { __le16 frame_control; __le16 duration; @@ -646,6 +648,10 @@ struct ieee80211_mgmt { u8 action_code; u8 variable[0]; } __attribute__((packed)) mesh_action; + struct { + u8 action; + u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; + } __attribute__ ((packed)) sa_query; } u; } __attribute__ ((packed)) action; } u; @@ -1041,6 +1047,7 @@ enum ieee80211_category { WLAN_CATEGORY_DLS = 2, WLAN_CATEGORY_BACK = 3, WLAN_CATEGORY_PUBLIC = 4, + WLAN_CATEGORY_SA_QUERY = 8, WLAN_CATEGORY_WMM = 17, }; @@ -1129,6 +1136,13 @@ enum ieee80211_back_parties { WLAN_BACK_TIMER = 2, }; +/* SA Query action */ +enum ieee80211_sa_query_action { + WLAN_ACTION_SA_QUERY_REQUEST = 0, + WLAN_ACTION_SA_QUERY_RESPONSE = 1, +}; + + /* A-MSDU 802.11n */ #define IEEE80211_QOS_CONTROL_A_MSDU_PRESENT 0x0080 diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index abc3aa583ca..63db89aef3e 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1667,6 +1667,57 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) return RX_CONTINUE; } +void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, + size_t len) +{ + struct ieee80211_local *local = sdata->local; + struct sk_buff *skb; + struct ieee80211_mgmt *resp; + + if (compare_ether_addr(mgmt->da, sdata->dev->dev_addr) != 0) { + /* Not to own unicast address */ + return; + } + + if (compare_ether_addr(mgmt->sa, sdata->u.sta.bssid) != 0 || + compare_ether_addr(mgmt->bssid, sdata->u.sta.bssid) != 0) { + /* Not from the current AP. */ + return; + } + + if (sdata->u.sta.state == IEEE80211_STA_MLME_ASSOCIATE) { + /* Association in progress; ignore SA Query */ + return; + } + + if (len < 24 + 1 + sizeof(resp->u.action.u.sa_query)) { + /* Too short SA Query request frame */ + return; + } + + skb = dev_alloc_skb(sizeof(*resp) + local->hw.extra_tx_headroom); + if (skb == NULL) + return; + + skb_reserve(skb, local->hw.extra_tx_headroom); + resp = (struct ieee80211_mgmt *) skb_put(skb, 24); + memset(resp, 0, 24); + memcpy(resp->da, mgmt->sa, ETH_ALEN); + memcpy(resp->sa, sdata->dev->dev_addr, ETH_ALEN); + memcpy(resp->bssid, sdata->u.sta.bssid, ETH_ALEN); + resp->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); + skb_put(skb, 1 + sizeof(resp->u.action.u.sa_query)); + resp->u.action.category = WLAN_CATEGORY_SA_QUERY; + resp->u.action.u.sa_query.action = WLAN_ACTION_SA_QUERY_RESPONSE; + memcpy(resp->u.action.u.sa_query.trans_id, + mgmt->u.action.u.sa_query.trans_id, + WLAN_SA_QUERY_TR_ID_LEN); + + ieee80211_tx_skb(sdata, skb, 1); +} + static ieee80211_rx_result debug_noinline ieee80211_rx_h_action(struct ieee80211_rx_data *rx) { @@ -1743,6 +1794,24 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) break; } break; + case WLAN_CATEGORY_SA_QUERY: + if (len < (IEEE80211_MIN_ACTION_SIZE + + sizeof(mgmt->u.action.u.sa_query))) + return RX_DROP_MONITOR; + switch (mgmt->u.action.u.sa_query.action) { + case WLAN_ACTION_SA_QUERY_REQUEST: + if (sdata->vif.type != NL80211_IFTYPE_STATION) + return RX_DROP_MONITOR; + ieee80211_process_sa_query_req(sdata, mgmt, len); + break; + case WLAN_ACTION_SA_QUERY_RESPONSE: + /* + * SA Query response is currently only used in AP mode + * and it is processed in user space. + */ + return RX_CONTINUE; + } + break; default: return RX_CONTINUE; } -- GitLab From 1acc97b63a3f32481ebbb4e831323e9aa8834f66 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 8 Jan 2009 13:32:07 +0200 Subject: [PATCH 0809/4982] mac80211: 802.11w - Do not force Action frames to disable encryption When sending out Action frames, allow ieee80211_tx_skb() to send them without enforcing do_not_encrypt. These frames will be encrypted if MFP has been negotiated. Signed-off-by: Jouni Malinen Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ht.c | 6 +++--- net/mac80211/mesh_hwmp.c | 4 ++-- net/mac80211/mesh_plink.c | 2 +- net/mac80211/spectmgmt.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 832adf888ac..6be48526423 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -202,7 +202,7 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, mgmt->u.action.u.addba_req.start_seq_num = cpu_to_le16(start_seq_num << 4); - ieee80211_tx_skb(sdata, skb, 0); + ieee80211_tx_skb(sdata, skb, 1); } static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, @@ -248,7 +248,7 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout); mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); - ieee80211_tx_skb(sdata, skb, 0); + ieee80211_tx_skb(sdata, skb, 1); } static void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, @@ -291,7 +291,7 @@ static void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, mgmt->u.action.u.delba.params = cpu_to_le16(params); mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); - ieee80211_tx_skb(sdata, skb, 0); + ieee80211_tx_skb(sdata, skb, 1); } void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn) diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 71fe6096123..3f1785c1bac 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -149,7 +149,7 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, pos += ETH_ALEN; memcpy(pos, &dst_dsn, 4); - ieee80211_tx_skb(sdata, skb, 0); + ieee80211_tx_skb(sdata, skb, 1); return 0; } @@ -198,7 +198,7 @@ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra, pos += ETH_ALEN; memcpy(pos, &dst_dsn, 4); - ieee80211_tx_skb(sdata, skb, 0); + ieee80211_tx_skb(sdata, skb, 1); return 0; } diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 1159bdb4119..8a6c02ba162 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -218,7 +218,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, memcpy(pos, &reason, 2); } - ieee80211_tx_skb(sdata, skb, 0); + ieee80211_tx_skb(sdata, skb, 1); return 0; } diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c index 22ad4808e01..8396b5a77e8 100644 --- a/net/mac80211/spectmgmt.c +++ b/net/mac80211/spectmgmt.c @@ -65,7 +65,7 @@ static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_da IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED; msr_report->u.action.u.measurement.msr_elem.type = request_ie->type; - ieee80211_tx_skb(sdata, skb, 0); + ieee80211_tx_skb(sdata, skb, 1); } void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, -- GitLab From 97ebe12a035e11f8af7a06a34f4d848f9b2f0b49 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 8 Jan 2009 13:32:08 +0200 Subject: [PATCH 0810/4982] mac80211: 802.11w - Drop unprotected robust management frames if MFP is used Use ieee80211_drop_unencrypted() to decide whether a received frame should be dropped with management frames, too. If MFP is negotiated, unprotected robust management frames will be dropped. Signed-off-by: Jouni Malinen Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/rx.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 63db89aef3e..57ce697e325 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1737,6 +1737,9 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) if (!(rx->flags & IEEE80211_RX_RA_MATCH)) return RX_DROP_MONITOR; + if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) + return RX_DROP_MONITOR; + /* all categories we currently handle have action_code */ if (len < IEEE80211_MIN_ACTION_SIZE + 1) return RX_DROP_MONITOR; @@ -1825,10 +1828,14 @@ static ieee80211_rx_result debug_noinline ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; if (!(rx->flags & IEEE80211_RX_RA_MATCH)) return RX_DROP_MONITOR; + if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) + return RX_DROP_MONITOR; + if (ieee80211_vif_is_mesh(&sdata->vif)) return ieee80211_mesh_rx_mgmt(sdata, rx->skb, rx->status); -- GitLab From 63a5ab82255a4ff5d0783f16427210f1d45d7ec8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 8 Jan 2009 13:32:09 +0200 Subject: [PATCH 0811/4982] mac80211: 802.11w - Implement Association Comeback processing When MFP is enabled, the AP does not allow a STA to associate if an existing security association exists without first going through SA Query process. When this happens, the association request is denied with a new status code ("temporarily rejected") ans Association Comeback IE is used to notify when the association may be tried again (i.e., when the SA Query procedure has timed out). Use the comeback time to update the mac80211 client MLME timer for next association attempt to minimize waiting time if association is temporarily rejected. Signed-off-by: Jouni Malinen Acked-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 4 ++++ net/mac80211/ieee80211_i.h | 2 ++ net/mac80211/mlme.c | 20 +++++++++++++++++--- net/mac80211/util.c | 4 ++++ 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 9fe1948d28d..7800e20f197 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -914,6 +914,9 @@ enum ieee80211_statuscode { /* 802.11g */ WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25, WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26, + /* 802.11w */ + WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY = 30, + WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION = 31, /* 802.11i */ WLAN_STATUS_INVALID_IE = 40, WLAN_STATUS_INVALID_GROUP_CIPHER = 41, @@ -1034,6 +1037,7 @@ enum ieee80211_eid { /* 802.11i */ WLAN_EID_RSN = 48, WLAN_EID_MMIE = 76 /* 802.11w */, + WLAN_EID_ASSOC_COMEBACK_TIME = 77, WLAN_EID_WPA = 221, WLAN_EID_GENERIC = 221, WLAN_EID_VENDOR_SPECIFIC = 221, diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 212c732fbba..9112c5247c3 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -820,6 +820,7 @@ struct ieee802_11_elems { u8 *country_elem; u8 *pwr_constr_elem; u8 *quiet_elem; /* first quite element */ + u8 *assoc_comeback; /* length of them, respectively */ u8 ssid_len; @@ -847,6 +848,7 @@ struct ieee802_11_elems { u8 pwr_constr_elem_len; u8 quiet_elem_len; u8 num_of_quiet_elem; /* can be more the one */ + u8 assoc_comeback_len; }; static inline struct ieee80211_local *hw_to_local( diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 42c5f981c71..82c598a8368 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1275,6 +1275,23 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, sdata->dev->name, reassoc ? "Rea" : "A", mgmt->sa, capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); + pos = mgmt->u.assoc_resp.variable; + ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); + + if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY && + elems.assoc_comeback && elems.assoc_comeback_len == 4) { + u32 tu, ms; + tu = get_unaligned_le32(elems.assoc_comeback); + ms = tu * 1024 / 1000; + printk(KERN_DEBUG "%s: AP rejected association temporarily; " + "comeback duration %u TU (%u ms)\n", + sdata->dev->name, tu, ms); + if (ms > IEEE80211_ASSOC_TIMEOUT) + mod_timer(&ifsta->timer, + jiffies + msecs_to_jiffies(ms)); + return; + } + if (status_code != WLAN_STATUS_SUCCESS) { printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", sdata->dev->name, status_code); @@ -1290,9 +1307,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, "set\n", sdata->dev->name, aid); aid &= ~(BIT(15) | BIT(14)); - pos = mgmt->u.assoc_resp.variable; - ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); - if (!elems.supp_rates) { printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", sdata->dev->name); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 5cd430333f0..963e0473205 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -653,6 +653,10 @@ void ieee802_11_parse_elems(u8 *start, size_t len, elems->pwr_constr_elem = pos; elems->pwr_constr_elem_len = elen; break; + case WLAN_EID_ASSOC_COMEBACK_TIME: + elems->assoc_comeback = pos; + elems->assoc_comeback_len = elen; + break; default: break; } -- GitLab From 1f7d77ab69789980dad44e1af7afd3a68cd48276 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 8 Jan 2009 13:32:10 +0200 Subject: [PATCH 0812/4982] mac80211: 802.11w - Optional software CCMP for management frames If driver/firmware/hardware does not support CCMP for management frames, it can now request mac80211 to take care of encrypting and decrypting management frames (when MFP is enabled) in software. The will need to add this new IEEE80211_KEY_FLAG_SW_MGMT flag when a CCMP key is being configured for TX side and return the undecrypted frames on RX side without RX_FLAG_DECRYPTED flag to use software CCMP for management frames (but hardware for data frames). Signed-off-by: Jouni Malinen Acked-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 4 ++++ net/mac80211/wpa.c | 9 +++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 61f1f37a9e2..00a50a38c7f 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -686,12 +686,16 @@ enum ieee80211_key_len { * generation in software. * @IEEE80211_KEY_FLAG_PAIRWISE: Set by mac80211, this flag indicates * that the key is pairwise rather then a shared key. + * @IEEE80211_KEY_FLAG_SW_MGMT: This flag should be set by the driver for a + * CCMP key if it requires CCMP encryption of management frames (MFP) to + * be done in software. */ enum ieee80211_key_flags { IEEE80211_KEY_FLAG_WMM_STA = 1<<0, IEEE80211_KEY_FLAG_GENERATE_IV = 1<<1, IEEE80211_KEY_FLAG_GENERATE_MMIC= 1<<2, IEEE80211_KEY_FLAG_PAIRWISE = 1<<3, + IEEE80211_KEY_FLAG_SW_MGMT = 1<<4, }; /** diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 53e11e6ff66..9101b48ec2a 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -367,9 +367,14 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) int hdrlen, len, tail; u8 *pos, *pn; int i; + bool skip_hw; + + skip_hw = (tx->key->conf.flags & IEEE80211_KEY_FLAG_SW_MGMT) && + ieee80211_is_mgmt(hdr->frame_control); if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && - !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { + !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) && + !skip_hw) { /* hwaccel - with no need for preallocated room for CCMP * header or MIC fields */ info->control.hw_key = &tx->key->conf; @@ -404,7 +409,7 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) ccmp_pn2hdr(pos, pn, key->conf.keyidx); - if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { + if ((key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && !skip_hw) { /* hwaccel - with preallocated room for CCMP header */ info->control.hw_key = &tx->key->conf; return 0; -- GitLab From 4375d08350e3661d5e8860d33eea084e47ba01cf Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 8 Jan 2009 13:32:11 +0200 Subject: [PATCH 0813/4982] mac80211: 802.11w - Add driver capability flag for MFP This allows user space to determine whether a driver supports MFP and behave properly without having to ask user to configure this in MFP-optional mode. Signed-off-by: Jouni Malinen Acked-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 4 ++++ net/mac80211/wext.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 00a50a38c7f..9bca2abbf03 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -865,6 +865,9 @@ enum ieee80211_tkip_key_type { * * @IEEE80211_HW_SUPPORTS_DYNAMIC_PS: * Hardware has support for dynamic PS. + * + * @IEEE80211_HW_MFP_CAPABLE: + * Hardware supports management frame protection (MFP, IEEE 802.11w). */ enum ieee80211_hw_flags { IEEE80211_HW_RX_INCLUDES_FCS = 1<<1, @@ -880,6 +883,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_SUPPORTS_PS = 1<<11, IEEE80211_HW_PS_NULLFUNC_STACK = 1<<12, IEEE80211_HW_SUPPORTS_DYNAMIC_PS = 1<<13, + IEEE80211_HW_MFP_CAPABLE = 1<<14, }; /** diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 2dd387495df..70a29b657b6 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -976,6 +976,10 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev, ret = -EOPNOTSUPP; break; case IW_AUTH_MFP: + if (!(sdata->local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) { + ret = -EOPNOTSUPP; + break; + } if (sdata->vif.type == NL80211_IFTYPE_STATION || sdata->vif.type == NL80211_IFTYPE_ADHOC) sdata->u.sta.mfp = data->value; -- GitLab From ca470b29027f093d8d63abc0fa401cf4f72e427b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 8 Jan 2009 13:32:12 +0200 Subject: [PATCH 0814/4982] ath9k: Fix set_key error codes Return -EOPNOTSUPP if the algorithm is not supported and -ENOSPC if there is no room in the key cache. This avoids KERN_ERR printk in mac80211 for "errors" that are actually expected to happen in normal operating conditions. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 5e9a3e19da4..fc4439f9750 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -817,7 +817,7 @@ static int ath_key_config(struct ath_softc *sc, hk.kv_type = ATH9K_CIPHER_AES_CCM; break; default: - return -EINVAL; + return -EOPNOTSUPP; } hk.kv_len = key->keylen; @@ -851,7 +851,7 @@ static int ath_key_config(struct ath_softc *sc, else idx = ath_reserve_key_cache_slot(sc); if (idx < 0) - return -EIO; /* no free key cache entries */ + return -ENOSPC; /* no free key cache entries */ } if (key->alg == ALG_TKIP) -- GitLab From 0ced0e176ab854df15bd307188decba9c06650e5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 8 Jan 2009 13:32:13 +0200 Subject: [PATCH 0815/4982] ath9k: Setup MFP options for CCMP Configure hardware CCMP for management frame protection and use software crypto when needed. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ath9k.h | 2 ++ drivers/net/wireless/ath9k/hw.c | 17 +++++++++++++++++ drivers/net/wireless/ath9k/main.c | 5 +++++ drivers/net/wireless/ath9k/recv.c | 6 ++++++ drivers/net/wireless/ath9k/reg.h | 6 ++++++ 5 files changed, 36 insertions(+) diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index f2ad62536bf..3817645b85d 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -809,6 +809,8 @@ struct ath_hal { #ifndef ATH_NF_PER_CHAN struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; #endif + + bool sw_mgmt_crypto; }; struct chan_centers { diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 3c026e6b245..e9a3951996e 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -2265,6 +2265,23 @@ int ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan, if (r) return r; + /* Setup MFP options for CCMP */ + if (AR_SREV_9280_20_OR_LATER(ah)) { + /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt + * frames when constructing CCMP AAD. */ + REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT, + 0xc7ff); + ah->sw_mgmt_crypto = false; + } else if (AR_SREV_9160_10_OR_LATER(ah)) { + /* Disable hardware crypto for management frames */ + REG_CLR_BIT(ah, AR_PCU_MISC_MODE2, + AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE); + REG_SET_BIT(ah, AR_PCU_MISC_MODE2, + AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT); + ah->sw_mgmt_crypto = true; + } else + ah->sw_mgmt_crypto = true; + if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) ath9k_hw_set_delta_slope(ah, chan); diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index fc4439f9750..72f2956c4c5 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1557,6 +1557,9 @@ static int ath_attach(u16 devid, struct ath_softc *sc) IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION; + if (AR_SREV_9160_10_OR_LATER(sc->sc_ah)) + hw->flags |= IEEE80211_HW_MFP_CAPABLE; + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION) | @@ -2348,6 +2351,8 @@ static int ath9k_set_key(struct ieee80211_hw *hw, key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; if (key->alg == ALG_TKIP) key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + if (sc->sc_ah->sw_mgmt_crypto && key->alg == ALG_CCMP) + key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; ret = 0; } break; diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c index 462e08c3d09..dbf24be23cc 100644 --- a/drivers/net/wireless/ath9k/recv.c +++ b/drivers/net/wireless/ath9k/recv.c @@ -593,6 +593,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) if (test_bit(keyix, sc->sc_keymap)) rx_status.flag |= RX_FLAG_DECRYPTED; } + if (ah->sw_mgmt_crypto && + (rx_status.flag & RX_FLAG_DECRYPTED) && + ieee80211_is_mgmt(hdr->frame_control)) { + /* Use software decrypt for management frames. */ + rx_status.flag &= ~RX_FLAG_DECRYPTED; + } /* Send the frame to mac80211 */ __ieee80211_rx(sc->hw, skb, &rx_status); diff --git a/drivers/net/wireless/ath9k/reg.h b/drivers/net/wireless/ath9k/reg.h index 9a615224e4f..2dffe371ffe 100644 --- a/drivers/net/wireless/ath9k/reg.h +++ b/drivers/net/wireless/ath9k/reg.h @@ -1253,6 +1253,8 @@ enum { #define AR_AES_MUTE_MASK1 0x8060 #define AR_AES_MUTE_MASK1_SEQ 0x0000FFFF +#define AR_AES_MUTE_MASK1_FC_MGMT 0xFFFF0000 +#define AR_AES_MUTE_MASK1_FC_MGMT_S 16 #define AR_GATED_CLKS 0x8064 #define AR_GATED_CLKS_TX 0x00000002 @@ -1477,6 +1479,10 @@ enum { #define AR_PCU_TXBUF_CTRL_USABLE_SIZE 0x700 #define AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE 0x380 +#define AR_PCU_MISC_MODE2 0x8344 +#define AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE 0x00000002 +#define AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT 0x00000004 + #define AR_KEYTABLE_0 0x8800 #define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32)) #define AR_KEY_CACHE_SIZE 128 -- GitLab From fa77533e2e1e5c7d9d80618db21266b9eac1b205 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 8 Jan 2009 13:32:14 +0200 Subject: [PATCH 0816/4982] mac80211_hwsim: Report driver as MFP capable mac80211_hwsim has no problems with MFP, so report it as MFP capable. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index f83d69e813d..fce49ba061d 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -779,6 +779,8 @@ static int __init init_mac80211_hwsim(void) BIT(NL80211_IFTYPE_MESH_POINT); hw->ampdu_queues = 1; + hw->flags = IEEE80211_HW_MFP_CAPABLE; + /* ask mac80211 to reserve space for magic */ hw->vif_data_size = sizeof(struct hwsim_vif_priv); hw->sta_data_size = sizeof(struct hwsim_sta_priv); -- GitLab From f5965955e0107b116b379cccb94de612281bdf55 Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Thu, 8 Jan 2009 10:19:52 -0800 Subject: [PATCH 0817/4982] iwl3945: kill hw_params.tx_ant_num This patch removes tx_ant_num for hw_params structure. It is not used. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 1 - drivers/net/wireless/iwlwifi/iwl-dev.h | 3 --- 2 files changed, 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index d4ee15ed5e4..8efe33805e1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2492,7 +2492,6 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.max_stations = IWL3945_STATION_COUNT; priv->hw_params.bcast_sta_id = IWL3945_BROADCAST_ID; - priv->hw_params.tx_ant_num = 2; return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 9b9d7435321..a092401fd9c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -595,9 +595,6 @@ struct iwl_hw_params { u32 ct_kill_threshold; /* value in hw-dependent units */ u32 calib_init_cfg; const struct iwl_sensitivity_ranges *sens; - - /* for 3945 */ - u16 tx_ant_num; }; -- GitLab From 141c43a3e4c7e8543fea982284765fda5e73837e Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Thu, 8 Jan 2009 10:19:53 -0800 Subject: [PATCH 0818/4982] iwl3945: kill iwl3945_rx_queue_restock This patch kills iwl3945_rx_queue_restock function on prise of new hw_params.rx_wrt_ptr_reg which holds per NIC RX write pointer register. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 4 +- drivers/net/wireless/iwlwifi/iwl-3945.h | 2 - drivers/net/wireless/iwlwifi/iwl-4965.c | 2 + drivers/net/wireless/iwlwifi/iwl-5000.c | 2 + drivers/net/wireless/iwlwifi/iwl-dev.h | 2 + drivers/net/wireless/iwlwifi/iwl-rx.c | 14 +++--- drivers/net/wireless/iwlwifi/iwl3945-base.c | 50 +-------------------- 7 files changed, 18 insertions(+), 58 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 8efe33805e1..24d818d1b06 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1218,7 +1218,7 @@ int iwl3945_hw_nic_init(struct iwl_priv *priv) /* Look at using this instead: rxq->need_update = 1; - iwl3945_rx_queue_update_write_ptr(priv, rxq); + iwl_rx_queue_update_write_ptr(priv, rxq); */ rc = iwl_grab_nic_access(priv); @@ -2492,6 +2492,8 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.max_stations = IWL3945_STATION_COUNT; priv->hw_params.bcast_sta_id = IWL3945_BROADCAST_ID; + priv->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR; + return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index c5f5481edb3..3041616d39c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -225,8 +225,6 @@ extern int __must_check iwl3945_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, struct ieee80211_hdr *hdr,int left); -extern int iwl3945_rx_queue_update_write_ptr(struct iwl_priv *priv, - struct iwl_rx_queue *q); extern int iwl3945_send_statistics_request(struct iwl_priv *priv); extern void iwl3945_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb, u32 decrypt_res, diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index e68d587a44b..57efd4890dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -822,6 +822,8 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.max_bsm_size = BSM_SRAM_SIZE; priv->hw_params.fat_channel = BIT(IEEE80211_BAND_5GHZ); + priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; + priv->hw_params.tx_chains_num = 2; priv->hw_params.rx_chains_num = 2; priv->hw_params.valid_tx_ant = ANT_A | ANT_B; diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 76d86fe2b41..d20d2ba0c10 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -844,6 +844,8 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.max_bsm_size = 0; priv->hw_params.fat_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); + priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; + priv->hw_params.sens = &iwl5000_sensitivity; switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index a092401fd9c..fbc4822c19a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -563,6 +563,7 @@ struct iwl_sensitivity_ranges { * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2) * @max_rxq_log: Log-base-2 of max_rxq_size * @rx_buf_size: Rx buffer size + * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR * @max_stations: * @bcast_sta_id: * @fat_channel: is 40MHz width possible in band 2.4 @@ -584,6 +585,7 @@ struct iwl_hw_params { u16 max_rxq_size; u16 max_rxq_log; u32 rx_buf_size; + u32 rx_wrt_ptr_reg; u32 max_pkt_size; u8 max_stations; u8 bcast_sta_id; diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index bc3febe74d6..60be47f8c4a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -125,9 +125,10 @@ EXPORT_SYMBOL(iwl_rx_queue_space); */ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) { - u32 reg = 0; - int ret = 0; unsigned long flags; + u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg; + u32 reg; + int ret = 0; spin_lock_irqsave(&q->lock, flags); @@ -149,15 +150,14 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) goto exit_unlock; /* Device expects a multiple of 8 */ - iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR, - q->write & ~0x7); + iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write & ~0x7); iwl_release_nic_access(priv); /* Else device is assumed to be awake */ - } else + } else { /* Device expects a multiple of 8 */ - iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7); - + iwl_write32(priv, rx_wrt_ptr_reg, q->write & ~0x7); + } q->need_update = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 43cfc6ec516..04466d30fe4 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3218,52 +3218,6 @@ static int iwl3945_rx_queue_space(const struct iwl_rx_queue *q) return s; } -/** - * iwl3945_rx_queue_update_write_ptr - Update the write pointer for the RX queue - */ -int iwl3945_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) -{ - u32 reg = 0; - int rc = 0; - unsigned long flags; - - spin_lock_irqsave(&q->lock, flags); - - if (q->need_update == 0) - goto exit_unlock; - - /* If power-saving is in use, make sure device is awake */ - if (test_bit(STATUS_POWER_PMI, &priv->status)) { - reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); - - if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { - iwl_set_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - goto exit_unlock; - } - - rc = iwl_grab_nic_access(priv); - if (rc) - goto exit_unlock; - - /* Device expects a multiple of 8 */ - iwl_write_direct32(priv, FH39_RSCSR_CHNL0_WPTR, - q->write & ~0x7); - iwl_release_nic_access(priv); - - /* Else device is assumed to be awake */ - } else - /* Device expects a multiple of 8 */ - iwl_write32(priv, FH39_RSCSR_CHNL0_WPTR, q->write & ~0x7); - - - q->need_update = 0; - - exit_unlock: - spin_unlock_irqrestore(&q->lock, flags); - return rc; -} - /** * iwl3945_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr */ @@ -3320,7 +3274,7 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv) spin_lock_irqsave(&rxq->lock, flags); rxq->need_update = 1; spin_unlock_irqrestore(&rxq->lock, flags); - rc = iwl3945_rx_queue_update_write_ptr(priv, rxq); + rc = iwl_rx_queue_update_write_ptr(priv, rxq); if (rc) return rc; } @@ -4007,7 +3961,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) /* uCode wakes up after power-down sleep */ if (inta & CSR_INT_BIT_WAKEUP) { IWL_DEBUG_ISR("Wakeup interrupt\n"); - iwl3945_rx_queue_update_write_ptr(priv, &priv->rxq); + iwl_rx_queue_update_write_ptr(priv, &priv->rxq); iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[0]); iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[1]); iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[2]); -- GitLab From 37d68317add2b769ad232a5d199bece41c59e13f Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Thu, 8 Jan 2009 10:19:54 -0800 Subject: [PATCH 0819/4982] iwl3945: kill iwl3945_rx_queue_space This patch replaces iwl3945_rx_queue_space with iwl_rx_queue_space. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 04466d30fe4..eacef54636a 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3203,21 +3203,6 @@ static void iwl3945_tx_cmd_complete(struct iwl_priv *priv, * */ -/** - * iwl3945_rx_queue_space - Return number of free slots available in queue. - */ -static int iwl3945_rx_queue_space(const struct iwl_rx_queue *q) -{ - int s = q->read - q->write; - if (s <= 0) - s += RX_QUEUE_SIZE; - /* keep some buffer to not confuse full and empty queue */ - s -= 2; - if (s < 0) - s = 0; - return s; -} - /** * iwl3945_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr */ @@ -3248,7 +3233,7 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv) spin_lock_irqsave(&rxq->lock, flags); write = rxq->write & ~0x7; - while ((iwl3945_rx_queue_space(rxq) > 0) && (rxq->free_count)) { + while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) { /* Get next free Rx buffer, remove from free list */ element = rxq->rx_free.next; rxb = list_entry(element, struct iwl_rx_mem_buffer, list); @@ -3459,7 +3444,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF; i = rxq->read; - if (iwl3945_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2)) + if (iwl_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2)) fill_rx = 1; /* Rx interrupt, but nothing sent from uCode */ if (i == r) -- GitLab From 625a381ab870b190c1899c08467c0e6dcc5d94d4 Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Thu, 8 Jan 2009 10:19:55 -0800 Subject: [PATCH 0820/4982] iwl3945: kill iwl3945_x2_queue_used This patch replaces iwl3945_x2_queue_used with iwl_queue_used. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.h | 2 -- drivers/net/wireless/iwlwifi/iwl3945-base.c | 9 +-------- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 24d818d1b06..db7b949020c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -344,7 +344,7 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv, int rate_idx; int fail; - if ((index >= txq->q.n_bd) || (iwl3945_x2_queue_used(&txq->q, index) == 0)) { + if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " "is out of range [0-%d] %d %d\n", txq_id, index, txq->q.n_bd, txq->q.write_ptr, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 3041616d39c..be301345335 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -106,8 +106,6 @@ enum iwl3945_antenna { #define DEFAULT_SHORT_RETRY_LIMIT 7U #define DEFAULT_LONG_RETRY_LIMIT 4U -int iwl3945_x2_queue_used(const struct iwl_queue *q, int i); - #include "iwl-agn-rs.h" #define IWL_TX_FIFO_AC0 0 diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index eacef54636a..e05a9d604b9 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -120,13 +120,6 @@ struct iwl_mod_params iwl3945_mod_params = { * (#0-3) for data tx via EDCA. An additional 2 HCCA queues are unused. ***************************************************/ -int iwl3945_x2_queue_used(const struct iwl_queue *q, int i) -{ - return q->write_ptr > q->read_ptr ? - (i >= q->read_ptr && i < q->write_ptr) : - !(i < q->read_ptr && i >= q->write_ptr); -} - /** * iwl3945_queue_init - Initialize queue's high/low-water and read/write indexes */ @@ -3079,7 +3072,7 @@ static void iwl3945_cmd_queue_reclaim(struct iwl_priv *priv, struct iwl_queue *q = &txq->q; int nfreed = 0; - if ((index >= q->n_bd) || (iwl3945_x2_queue_used(q, index) == 0)) { + if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, " "is out of range [0-%d] %d %d.\n", txq_id, index, q->n_bd, q->write_ptr, q->read_ptr); -- GitLab From d45aadd04b60c6d4f846e7ec2564654567065e5f Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Thu, 8 Jan 2009 10:19:56 -0800 Subject: [PATCH 0821/4982] iwl3945: remove double defined 3945 tfd structures This patch removes doubly defined struct iwl3945_tfd_frame_data and struct iwl3945_tfd_frame. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-fh.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index 313b03b5b4c..a72aa1b32c8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -478,18 +478,6 @@ struct iwl_tfd { __le32 __pad; } __attribute__ ((packed)); -struct iwl3945_tfd_frame_data { - __le32 addr; - __le32 len; -} __attribute__ ((packed)); - -struct iwl3945_tfd_frame { - __le32 control_flags; - struct iwl3945_tfd_frame_data pa[4]; - u8 reserved[28]; -} __attribute__ ((packed)); - - /* Keep Warm Size */ #define IWL_KW_SIZE 0x1000 /* 4k */ -- GitLab From 1e33dc64475790c10a7cda3ca23d2eb678760d85 Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Thu, 8 Jan 2009 10:19:57 -0800 Subject: [PATCH 0822/4982] iwl3945: use hw_params.rx_buf_size This patch makes 3945 use of hw_params.rx_buf_size instead of IWL_RX_BUF_SIZE. It also renames IWL_RX_BUF_SIZE to IWL_RX_BUF_SIZE_3K and moves rx buffer defines into iwl-fh.h. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.h | 1 - drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 13 ------------- drivers/net/wireless/iwlwifi/iwl-fh.h | 15 +++++++++++++++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 15 +++++++++------ 5 files changed, 25 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index db7b949020c..8a378bd1a7a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2485,7 +2485,7 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) return -ENOMEM; } - priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE; + priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_3K; priv->hw_params.max_pkt_size = 2342; priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index be301345335..491313baba6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -96,7 +96,6 @@ enum iwl3945_antenna { * else RTS for data/management frames where MPDU is larger * than RTS value. */ -#define IWL_RX_BUF_SIZE 3000U #define DEFAULT_RTS_THRESHOLD 2347U #define MIN_RTS_THRESHOLD 0U #define MAX_RTS_THRESHOLD 2347U diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index e751c53ae1f..ed6baa539f5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -110,19 +110,6 @@ #define IWL_DEFAULT_TX_RETRY 15 -#define RX_QUEUE_SIZE 256 -#define RX_QUEUE_MASK 255 -#define RX_QUEUE_SIZE_LOG 8 - -/* - * RX related structures and functions - */ -#define RX_FREE_BUFFERS 64 -#define RX_LOW_WATERMARK 8 - -/* Size of one Rx buffer in host DRAM */ -#define IWL_RX_BUF_SIZE_4K (4 * 1024) -#define IWL_RX_BUF_SIZE_8K (8 * 1024) /* Sizes and addresses for instruction and data memory (SRAM) in * 4965's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */ diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index a72aa1b32c8..ad5a24ecc2d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -399,6 +399,21 @@ */ #define FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN (0x00000002) +#define RX_QUEUE_SIZE 256 +#define RX_QUEUE_MASK 255 +#define RX_QUEUE_SIZE_LOG 8 + +/* + * RX related structures and functions + */ +#define RX_FREE_BUFFERS 64 +#define RX_LOW_WATERMARK 8 + +/* Size of one Rx buffer in host DRAM */ +#define IWL_RX_BUF_SIZE_3K (3 * 1000) /* 3945 only */ +#define IWL_RX_BUF_SIZE_4K (4 * 1024) +#define IWL_RX_BUF_SIZE_8K (8 * 1024) + /** * struct iwl_rb_status - reseve buffer status * host memory mapped FH registers diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index e05a9d604b9..d145002d0a6 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3281,7 +3281,8 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv) /* Alloc a new receive buffer */ rxb->skb = - alloc_skb(IWL_RX_BUF_SIZE, __GFP_NOWARN | GFP_ATOMIC); + alloc_skb(priv->hw_params.rx_buf_size, + __GFP_NOWARN | GFP_ATOMIC); if (!rxb->skb) { if (net_ratelimit()) IWL_CRIT(priv, ": Can not allocate SKB buffers\n"); @@ -3303,9 +3304,10 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv) list_del(element); /* Get physical address of RB/SKB */ - rxb->real_dma_addr = - pci_map_single(priv->pci_dev, rxb->skb->data, - IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); + rxb->real_dma_addr = pci_map_single(priv->pci_dev, + rxb->skb->data, + priv->hw_params.rx_buf_size, + PCI_DMA_FROMDEVICE); list_add_tail(&rxb->list, &rxq->rx_free); rxq->free_count++; } @@ -3454,7 +3456,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) rxq->queue[i] = NULL; pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->real_dma_addr, - IWL_RX_BUF_SIZE, + priv->hw_params.rx_buf_size, PCI_DMA_FROMDEVICE); pkt = (struct iwl_rx_packet *)rxb->skb->data; @@ -3504,7 +3506,8 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) } pci_unmap_single(priv->pci_dev, rxb->real_dma_addr, - IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); + priv->hw_params.rx_buf_size, + PCI_DMA_FROMDEVICE); spin_lock_irqsave(&rxq->lock, flags); list_add_tail(&rxb->list, &priv->rxq.rx_used); spin_unlock_irqrestore(&rxq->lock, flags); -- GitLab From 9c74d9fbd59f3a69cbe08a6bd66479c190effe5f Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Thu, 8 Jan 2009 10:19:59 -0800 Subject: [PATCH 0823/4982] iwl3945: Change crypto parameter name Now that we're using iwl_mod_params, we want our module parameters names to be in sync with the structure. So, to set iwl_mod_params.sw_crypto, we'd better use a "swcrypto" parameter name instead of the "hwcrypto" current one. Moreover, by setting the decrypted flag properly, this patch also fixes the HW crypto path for 3945 (the current code is not setting it when running HW crypto). This is a bug fix for bug #1872 ( http://www.intellinuxwireless.org/bugzilla/show_bug.cgi?id=1872 ) Signed-off-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 8a378bd1a7a..e7d166d2255 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -600,7 +600,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, /* Set the size of the skb to the size of the frame */ skb_put(rxb->skb, le16_to_cpu(rx_hdr->len)); - if (iwl3945_mod_params.sw_crypto) + if (!iwl3945_mod_params.sw_crypto) iwl3945_set_decrypted_flag(priv, rxb->skb, le32_to_cpu(rx_end->status), stats); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index d145002d0a6..6a32f568215 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -92,6 +92,7 @@ MODULE_LICENSE("GPL"); /* module parameters */ struct iwl_mod_params iwl3945_mod_params = { .num_of_queues = IWL39_MAX_NUM_QUEUES, + .sw_crypto = 1, /* the rest are 0 by default */ }; @@ -7814,9 +7815,9 @@ module_param_named(antenna, iwl3945_mod_params.antenna, int, 0444); MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); module_param_named(disable, iwl3945_mod_params.disable, int, 0444); MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])"); -module_param_named(hwcrypto, iwl3945_mod_params.sw_crypto, int, 0444); -MODULE_PARM_DESC(hwcrypto, - "using hardware crypto engine (default 0 [software])\n"); +module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, 0444); +MODULE_PARM_DESC(swcrypto, + "using software crypto (default 1 [software])\n"); module_param_named(debug, iwl3945_mod_params.debug, uint, 0444); MODULE_PARM_DESC(debug, "debug output mask"); module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, int, 0444); -- GitLab From 01f8162a854df7f9c259c839ad3c1168ac13b7b8 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Thu, 8 Jan 2009 10:20:02 -0800 Subject: [PATCH 0824/4982] iwlwifi: update copyright year to 2009 Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-fh.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-3945-led.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945-led.h | 2 +- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.h | 2 +- drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- drivers/net/wireless/iwlwifi/iwl-5000-hw.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-5000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.h | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-calib.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-calib.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-commands.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- drivers/net/wireless/iwlwifi/iwl-core.h | 6 +++--- drivers/net/wireless/iwlwifi/iwl-csr.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-debug.h | 2 +- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-eeprom.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-fh.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-hcmd.c | 2 +- drivers/net/wireless/iwlwifi/iwl-helpers.h | 2 +- drivers/net/wireless/iwlwifi/iwl-io.h | 2 +- drivers/net/wireless/iwlwifi/iwl-led.c | 2 +- drivers/net/wireless/iwlwifi/iwl-led.h | 2 +- drivers/net/wireless/iwlwifi/iwl-power.c | 2 +- drivers/net/wireless/iwlwifi/iwl-power.h | 2 +- drivers/net/wireless/iwlwifi/iwl-prph.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-rfkill.c | 2 +- drivers/net/wireless/iwlwifi/iwl-rfkill.h | 2 +- drivers/net/wireless/iwlwifi/iwl-rx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 2 +- drivers/net/wireless/iwlwifi/iwl-spectrum.c | 2 +- drivers/net/wireless/iwlwifi/iwl-spectrum.h | 2 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 2 +- drivers/net/wireless/iwlwifi/iwl-sta.h | 2 +- drivers/net/wireless/iwlwifi/iwl-tx.c | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 ++-- 45 files changed, 60 insertions(+), 60 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-fh.h b/drivers/net/wireless/iwlwifi/iwl-3945-fh.h index 53ed24942a0..08ce259a0e6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-fh.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index c9db98cd0e4..013e24edf0e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index 10e68d64e6c..e35dc54923f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.h b/drivers/net/wireless/iwlwifi/iwl-3945-led.h index 859bb9b1e1b..88185a6ccd6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 52901ac74e5..25b4356fcc1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index e7d166d2255..e6d4503cd21 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 491313baba6..97dfa7c5a3c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index ed6baa539f5..af4c1bb0de1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 57efd4890dd..6171ba533f2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h index d83e60577b1..15cac70e36e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index d20d2ba0c10..429dcbeff16 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c index 2c8e676c4b5..1217a1da88f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index d3ae04112c3..a82cce5fbff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index 7c21292b3ae..345806dd887 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index dbfee28107a..b18596fed90 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index d2aabbc38d6..8e5e6663be3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.h b/drivers/net/wireless/iwlwifi/iwl-calib.h index 1abe84bb74a..b6cef989a79 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.h +++ b/drivers/net/wireless/iwlwifi/iwl-calib.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 6a2445da22f..3ced5e5b682 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 07c3870365b..d2ef3e142bc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 2abda89daaf..466130ff07a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -71,7 +71,7 @@ struct iwl_cmd; #define IWLWIFI_VERSION "1.3.27k" -#define DRV_COPYRIGHT "Copyright(c) 2003-2008 Intel Corporation" +#define DRV_COPYRIGHT "Copyright(c) 2003-2009 Intel Corporation" #define DRV_AUTHOR "" #define IWL_PCI_DEVICE(dev, subdev, cfg) \ diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index f34ede44ed1..74d3d43fa67 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 057781c8f82..7192d3249ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project. * diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 40441b8db89..36cfeccfafb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index fbc4822c19a..fd34ba81a0d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 59abac09a78..c8afcd1ed2c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 603c84bed63..dd2e7d2c508 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index ad5a24ecc2d..65fa8a69fd5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index af14d8fdcc7..65ae2af61c8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index ca4f638ab9d..fb64d297dd4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 801d5ffd21e..bc3f3daef6e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project. * diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 98be90f245c..501cffeff5f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h index 0b50b909939..1d798d08669 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-led.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 75ca6a54217..a9f9ffe4b94 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h index 7cab04f1bf4..476c2aa2bf7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/iwl-power.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index b7a5f23351c..3b9cac3fd21 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c index 98df755e21b..f67d7be1074 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.h b/drivers/net/wireless/iwlwifi/iwl-rfkill.h index 86dc055a2e9..633dafb4bf1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.h +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 60be47f8c4a..33145207fc1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index de55d3c5db6..e510f516599 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.c b/drivers/net/wireless/iwlwifi/iwl-spectrum.c index f4ed49701f6..aba1ef22fc6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-spectrum.c +++ b/drivers/net/wireless/iwlwifi/iwl-spectrum.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.h b/drivers/net/wireless/iwlwifi/iwl-spectrum.h index b7d7943e476..a77c1e61906 100644 --- a/drivers/net/wireless/iwlwifi/iwl-spectrum.h +++ b/drivers/net/wireless/iwlwifi/iwl-spectrum.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ieee80211 subsystem header files. * diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 672574fb526..5a214d7690a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 9bb7cefc1f3..3fe7cc575fa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 77a573f2c6e..913c77a2fea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 6a32f568215..76577b6bc9e 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -79,7 +79,7 @@ static int iwl3945_tx_queue_update_write_ptr(struct iwl_priv *priv, #endif #define IWL39_VERSION "1.2.26k" VD VS -#define DRV_COPYRIGHT "Copyright(c) 2003-2008 Intel Corporation" +#define DRV_COPYRIGHT "Copyright(c) 2003-2009 Intel Corporation" #define DRV_AUTHOR "" #define DRV_VERSION IWL39_VERSION -- GitLab From a8302de934b5d1897ff146cd0c7ab87d1417c092 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Fri, 9 Jan 2009 18:14:15 +0530 Subject: [PATCH 0825/4982] mac80211: Handle power constraint level advertised in 11d+h beacon This patch uses power constraint level while determining the maximum transmit power, there by it makes sure that any power mitigation requirement for the channel in the current regulatory domain is met. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 4 ++++ net/mac80211/main.c | 10 ++++++++-- net/mac80211/mlme.c | 9 +++++++++ net/mac80211/spectmgmt.c | 21 +++++++++++++++++++++ 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 9112c5247c3..c9ffadb55d3 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -715,6 +715,7 @@ struct ieee80211_local { struct timer_list dynamic_ps_timer; int user_power_level; /* in dBm */ + int power_constr_level; /* in dBm */ #ifdef CONFIG_MAC80211_DEBUGFS struct local_debugfsdentries { @@ -985,6 +986,9 @@ void ieee80211_chswitch_work(struct work_struct *work); void ieee80211_process_chanswitch(struct ieee80211_sub_if_data *sdata, struct ieee80211_channel_sw_ie *sw_elem, struct ieee80211_bss *bss); +void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, + u16 capab_info, u8 *pwr_constr_elem, + u8 pwr_constr_elem_len); /* utility functions/constants */ extern void *mac80211_wiphy_privid; /* for wiphy privid */ diff --git a/net/mac80211/main.c b/net/mac80211/main.c index e9f3e85d1a9..c78304db475 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -214,10 +214,16 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) changed |= IEEE80211_CONF_CHANGE_CHANNEL; } - if (!local->user_power_level) + if (local->sw_scanning) power = chan->max_power; else - power = min(chan->max_power, local->user_power_level); + power = local->power_constr_level ? + (chan->max_power - local->power_constr_level) : + chan->max_power; + + if (local->user_power_level) + power = min(power, local->user_power_level); + if (local->hw.conf.power_level != power) { changed |= IEEE80211_CONF_CHANGE_POWER; local->hw.conf.power_level = power; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 82c598a8368..f0d42498c25 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -905,6 +905,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, /* channel(_type) changes are handled by ieee80211_hw_config */ local->oper_channel_type = NL80211_CHAN_NO_HT; + local->power_constr_level = 0; + del_timer_sync(&local->dynamic_ps_timer); cancel_work_sync(&local->dynamic_ps_enable_work); @@ -1849,6 +1851,13 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, * for the BSSID we are associated to */ regulatory_hint_11d(local->hw.wiphy, elems.country_elem, elems.country_elem_len); + + /* TODO: IBSS also needs this */ + if (elems.pwr_constr_elem) + ieee80211_handle_pwr_constr(sdata, + le16_to_cpu(mgmt->u.probe_resp.capab_info), + elems.pwr_constr_elem, + elems.pwr_constr_elem_len); } ieee80211_bss_info_change_notify(sdata, changed); diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c index 8396b5a77e8..8d4ec2968f8 100644 --- a/net/mac80211/spectmgmt.c +++ b/net/mac80211/spectmgmt.c @@ -161,3 +161,24 @@ void ieee80211_process_chanswitch(struct ieee80211_sub_if_data *sdata, jiffies + msecs_to_jiffies(sw_elem->count * bss->beacon_int)); } } + +void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, + u16 capab_info, u8 *pwr_constr_elem, + u8 pwr_constr_elem_len) +{ + struct ieee80211_conf *conf = &sdata->local->hw.conf; + + if (!(capab_info & WLAN_CAPABILITY_SPECTRUM_MGMT)) + return; + + /* Power constraint IE length should be 1 octet */ + if (pwr_constr_elem_len != 1) + return; + + if ((*pwr_constr_elem <= conf->channel->max_power) && + (*pwr_constr_elem != sdata->local->power_constr_level)) { + sdata->local->power_constr_level = *pwr_constr_elem; + ieee80211_hw_config(sdata->local, 0); + } +} + -- GitLab From c7a7c8ecd43b4bc796a8e79c46305e2a677b55f3 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Thu, 8 Jan 2009 10:20:01 -0800 Subject: [PATCH 0826/4982] iwl3945: Fix iwl3945_init_drv() iwl3945_init_drv() initialises the wrong lock, and sets the wrong power saving default level. With this power saving mode, we are losing a lot of frames in Ad-Hoc mode. This is a bug fix for bug #1873. ( http://www.intellinuxwireless.org/bugzilla/show_bug.cgi?id=1873 ) Signed-off-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 76577b6bc9e..1b04284c4ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -7276,7 +7276,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv) priv->ibss_beacon = NULL; spin_lock_init(&priv->lock); - spin_lock_init(&priv->power_data.lock); + spin_lock_init(&priv->power_data_39.lock); spin_lock_init(&priv->sta_lock); spin_lock_init(&priv->hcmd_lock); @@ -7301,7 +7301,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv) priv->rates_mask = IWL_RATES_MASK; /* If power management is turned on, default to AC mode */ - priv->power_mode = IWL_POWER_AC; + priv->power_mode = IWL39_POWER_AC; priv->user_txpower_limit = IWL_DEFAULT_TX_POWER; ret = iwl3945_init_channel_map(priv); -- GitLab From b48365994b1b5cce8078c0707a06cf9897007fb5 Mon Sep 17 00:00:00 2001 From: Colin McCabe Date: Fri, 2 Jan 2009 19:00:22 -0800 Subject: [PATCH 0827/4982] libertas: Update libertas core with GSPI constants Add GSPI constants to libertas core. Fix misleading comment in lbs_setup_firmware. Signed-off-by: Colin McCabe Signed-off-by: Andrey Yurovsky Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/host.h | 1 + drivers/net/wireless/libertas/hostcmd.h | 8 ++++++++ drivers/net/wireless/libertas/main.c | 5 ++--- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h index 277ff1975bd..d4457ef808a 100644 --- a/drivers/net/wireless/libertas/host.h +++ b/drivers/net/wireless/libertas/host.h @@ -66,6 +66,7 @@ #define CMD_802_11_LED_GPIO_CTRL 0x004e #define CMD_802_11_EEPROM_ACCESS 0x0059 #define CMD_802_11_BAND_CONFIG 0x0058 +#define CMD_GSPI_BUS_CONFIG 0x005a #define CMD_802_11D_DOMAIN_INFO 0x005b #define CMD_802_11_KEY_MATERIAL 0x005e #define CMD_802_11_SLEEP_PARAMS 0x0066 diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h index f6a79a653b7..a899aeb676b 100644 --- a/drivers/net/wireless/libertas/hostcmd.h +++ b/drivers/net/wireless/libertas/hostcmd.h @@ -221,6 +221,14 @@ struct cmd_ds_mac_multicast_adr { u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE]; } __attribute__ ((packed)); +struct cmd_ds_gspi_bus_config { + struct cmd_header hdr; + __le16 action; + __le16 bus_delay_mode; + __le16 host_time_delay_to_read_port; + __le16 host_time_delay_to_read_register; +} __attribute__ ((packed)); + struct cmd_ds_802_11_authenticate { u8 macaddr[ETH_ALEN]; u8 authtype; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 4e0007d2003..8a7eb2778eb 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -1006,9 +1006,8 @@ void lbs_resume(struct lbs_private *priv) EXPORT_SYMBOL_GPL(lbs_resume); /** - * @brief This function downloads firmware image, gets - * HW spec from firmware and set basic parameters to - * firmware. + * @brief This function gets the HW spec from the firmware and sets + * some basic parameters. * * @param priv A pointer to struct lbs_private structure * @return 0 or -1 -- GitLab From e724b8fef6088e5dd240b53a38443e48fbcc8e93 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Jan 2009 17:06:06 +0100 Subject: [PATCH 0828/4982] IWL: fix WARN typo new kew -> a new key Signed-off-by: Jiri Slaby Cc: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-sta.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 5a214d7690a..0cbb4495c06 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -639,7 +639,7 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, * in uCode. */ WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, - "no space for new kew"); + "no space for a new key"); priv->stations[sta_id].sta.key.key_flags = key_flags; priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; @@ -687,7 +687,7 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, * in uCode. */ WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, - "no space for new kew"); + "no space for a new key"); priv->stations[sta_id].sta.key.key_flags = key_flags; priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; @@ -723,7 +723,7 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, * in uCode. */ WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, - "no space for new kew"); + "no space for a new key"); /* This copy is acutally not needed: we get the key with each TX */ memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16); -- GitLab From 6dd1bf3118b62a3ce241dc2b7e05e3d4a28c9eb1 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Thu, 8 Jan 2009 21:00:34 -0500 Subject: [PATCH 0829/4982] mac80211: document return codes from ops callbacks For any callbacks in ieee80211_ops, specify what values the return codes represent. While at it, fix a couple of capitalization and punctuation differences. Signed-off-by: Bob Copeland Reviewed-by: Kalle Valo Signed-off-by: John W. Linville --- include/net/mac80211.h | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 9bca2abbf03..9a5869e9ecf 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1217,6 +1217,8 @@ enum ieee80211_ampdu_mlme_action { * configuration in the TX control data. This handler should, * preferably, never fail and stop queues appropriately, more * importantly, however, it must never fail for A-MPDU-queues. + * This function should return NETDEV_TX_OK except in very + * limited cases. * Must be implemented and atomic. * * @start: Called before the first netdevice attached to the hardware @@ -1257,9 +1259,12 @@ enum ieee80211_ampdu_mlme_action { * * @config: Handler for configuration requests. IEEE 802.11 code calls this * function to change hardware configuration, e.g., channel. + * This function should never fail but returns a negative error code + * if it does. * * @config_interface: Handler for configuration requests related to interfaces * (e.g. BSSID changes.) + * Returns a negative error code which will be seen in userspace. * * @bss_info_changed: Handler for configuration requests related to BSS * parameters that may vary during BSS's lifespan, and may affect low @@ -1279,6 +1284,7 @@ enum ieee80211_ampdu_mlme_action { * This callback can sleep, and is only called between add_interface * and remove_interface calls, i.e. while the given virtual interface * is enabled. + * Returns a negative error code if the key can't be added. * * @update_tkip_key: See the section "Hardware crypto acceleration" * This callback will be called in the context of Rx. Called for drivers @@ -1290,8 +1296,10 @@ enum ieee80211_ampdu_mlme_action { * bands. When the scan finishes, ieee80211_scan_completed() must be * called; note that it also must be called when the scan cannot finish * because the hardware is turned off! Anything else is a bug! + * Returns a negative error code which will be seen in userspace. * - * @get_stats: return low-level statistics + * @get_stats: Return low-level statistics. + * Returns zero if statistics are available. * * @get_tkip_seq: If your device implements TKIP encryption in hardware this * callback should be provided to read the TKIP transmit IVs (both IV32 @@ -1305,6 +1313,7 @@ enum ieee80211_ampdu_mlme_action { * * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), * bursting) for a hardware TX queue. + * Returns a negative error code on failure. * * @get_tx_stats: Get statistics of the current TX queue status. This is used * to get number of currently queued packets (queue length), maximum queue @@ -1324,13 +1333,15 @@ enum ieee80211_ampdu_mlme_action { * @tx_last_beacon: Determine whether the last IBSS beacon was sent by us. * This is needed only for IBSS mode and the result of this function is * used to determine whether to reply to Probe Requests. + * Returns non-zero if this device sent the last beacon. * * @ampdu_action: Perform a certain A-MPDU action * The RA/TID combination determines the destination and TID we want * the ampdu action to be performed for. The action is defined through * ieee80211_ampdu_mlme_action. Starting sequence number (@ssn) - * is the first frame we expect to perform the action on. notice + * is the first frame we expect to perform the action on. Notice * that TX/RX_STOP can pass NULL for this parameter. + * Returns a negative error code on failure. */ struct ieee80211_ops { int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); -- GitLab From 63f2dc9f2fd63c8b66f49c53cd26236f3f0785fd Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 9 Jan 2009 21:05:31 +0100 Subject: [PATCH 0830/4982] p54: refactor p54_alloc_skb Old firmwares had no problems processing frames which filled eighth of the memory window. However we have to be a bit more careful with fat frames when we talk to new firmwares. Apart from that, I confess the old logic was a bit weird and not very sophisticated. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54.h | 2 + drivers/net/wireless/p54/p54common.c | 74 +++++++++++++--------------- 2 files changed, 35 insertions(+), 41 deletions(-) diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 6bd147c47ae..ce933387792 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -44,6 +44,8 @@ enum p54_control_frame_types { P54_CONTROL_TYPE_BT_OPTIONS = 35 }; +#define P54_MAX_CTRL_FRAME_LEN 0x1000 + #define P54_HDR_FLAG_CONTROL BIT(15) #define P54_HDR_FLAG_CONTROL_OPSET (BIT(15) + BIT(0)) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index e463c7c3a7e..c6dcf98aad3 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -1104,25 +1104,29 @@ static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb, return 0; } -static struct sk_buff *p54_alloc_skb(struct ieee80211_hw *dev, - u16 hdr_flags, u16 len, u16 type, gfp_t memflags) +static struct sk_buff *p54_alloc_skb(struct ieee80211_hw *dev, u16 hdr_flags, + u16 payload_len, u16 type, gfp_t memflags) { struct p54_common *priv = dev->priv; struct p54_hdr *hdr; struct sk_buff *skb; + size_t frame_len = sizeof(*hdr) + payload_len; - skb = __dev_alloc_skb(len + priv->tx_hdr_len, memflags); + if (frame_len > P54_MAX_CTRL_FRAME_LEN) + return NULL; + + skb = __dev_alloc_skb(priv->tx_hdr_len + frame_len, memflags); if (!skb) return NULL; skb_reserve(skb, priv->tx_hdr_len); hdr = (struct p54_hdr *) skb_put(skb, sizeof(*hdr)); hdr->flags = cpu_to_le16(hdr_flags); - hdr->len = cpu_to_le16(len - sizeof(*hdr)); + hdr->len = cpu_to_le16(payload_len); hdr->type = cpu_to_le16(type); hdr->tries = hdr->rts_tries = 0; - if (unlikely(p54_assign_address(dev, skb, hdr, len))) { + if (p54_assign_address(dev, skb, hdr, frame_len)) { kfree_skb(skb); return NULL; } @@ -1132,7 +1136,6 @@ static struct sk_buff *p54_alloc_skb(struct ieee80211_hw *dev, int p54_read_eeprom(struct ieee80211_hw *dev) { struct p54_common *priv = dev->priv; - struct p54_hdr *hdr = NULL; struct p54_eeprom_lm86 *eeprom_hdr; struct sk_buff *skb; size_t eeprom_size = 0x2020, offset = 0, blocksize, maxblocksize; @@ -1145,9 +1148,9 @@ int p54_read_eeprom(struct ieee80211_hw *dev) else maxblocksize -= 0x4; - skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL, sizeof(*hdr) + - sizeof(*eeprom_hdr) + maxblocksize, - P54_CONTROL_TYPE_EEPROM_READBACK, GFP_KERNEL); + skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL, sizeof(*eeprom_hdr) + + maxblocksize, P54_CONTROL_TYPE_EEPROM_READBACK, + GFP_KERNEL); if (!skb) goto free; priv->eeprom = kzalloc(EEPROM_READBACK_LEN, GFP_KERNEL); @@ -1203,9 +1206,8 @@ static int p54_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta, struct sk_buff *skb; struct p54_tim *tim; - skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, - sizeof(struct p54_hdr) + sizeof(*tim), - P54_CONTROL_TYPE_TIM, GFP_ATOMIC); + skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*tim), + P54_CONTROL_TYPE_TIM, GFP_ATOMIC); if (!skb) return -ENOMEM; @@ -1222,9 +1224,8 @@ static int p54_sta_unlock(struct ieee80211_hw *dev, u8 *addr) struct sk_buff *skb; struct p54_sta_unlock *sta; - skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, - sizeof(struct p54_hdr) + sizeof(*sta), - P54_CONTROL_TYPE_PSM_STA_UNLOCK, GFP_ATOMIC); + skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*sta), + P54_CONTROL_TYPE_PSM_STA_UNLOCK, GFP_ATOMIC); if (!skb) return -ENOMEM; @@ -1264,9 +1265,8 @@ static int p54_tx_cancel(struct ieee80211_hw *dev, struct sk_buff *entry) struct p54_hdr *hdr; struct p54_txcancel *cancel; - skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, - sizeof(struct p54_hdr) + sizeof(*cancel), - P54_CONTROL_TYPE_TXCANCEL, GFP_ATOMIC); + skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*cancel), + P54_CONTROL_TYPE_TXCANCEL, GFP_ATOMIC); if (!skb) return -ENOMEM; @@ -1548,9 +1548,8 @@ static int p54_setup_mac(struct ieee80211_hw *dev) struct p54_setup_mac *setup; u16 mode; - skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*setup) + - sizeof(struct p54_hdr), P54_CONTROL_TYPE_SETUP, - GFP_ATOMIC); + skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*setup), + P54_CONTROL_TYPE_SETUP, GFP_ATOMIC); if (!skb) return -ENOMEM; @@ -1628,9 +1627,8 @@ static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell) __le16 freq = cpu_to_le16(dev->conf.channel->center_freq); int band = dev->conf.channel->band; - skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*chan) + - sizeof(struct p54_hdr), P54_CONTROL_TYPE_SCAN, - GFP_ATOMIC); + skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*chan), + P54_CONTROL_TYPE_SCAN, GFP_ATOMIC); if (!skb) return -ENOMEM; @@ -1710,9 +1708,8 @@ static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act) struct sk_buff *skb; struct p54_led *led; - skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*led) + - sizeof(struct p54_hdr), P54_CONTROL_TYPE_LED, - GFP_ATOMIC); + skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*led), + P54_CONTROL_TYPE_LED, GFP_ATOMIC); if (!skb) return -ENOMEM; @@ -1739,9 +1736,8 @@ static int p54_set_edcf(struct ieee80211_hw *dev) struct sk_buff *skb; struct p54_edcf *edcf; - skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*edcf) + - sizeof(struct p54_hdr), P54_CONTROL_TYPE_DCFINIT, - GFP_ATOMIC); + skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*edcf), + P54_CONTROL_TYPE_DCFINIT, GFP_ATOMIC); if (!skb) return -ENOMEM; @@ -1778,9 +1774,8 @@ static int p54_set_ps(struct ieee80211_hw *dev) else mode = P54_PSM_CAM; - skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*psm) + - sizeof(struct p54_hdr), P54_CONTROL_TYPE_PSM, - GFP_ATOMIC); + skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*psm), + P54_CONTROL_TYPE_PSM, GFP_ATOMIC); if (!skb) return -ENOMEM; @@ -2083,10 +2078,8 @@ static int p54_init_xbow_synth(struct ieee80211_hw *dev) struct sk_buff *skb; struct p54_xbow_synth *xbow; - skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*xbow) + - sizeof(struct p54_hdr), - P54_CONTROL_TYPE_XBOW_SYNTH_CFG, - GFP_KERNEL); + skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*xbow), + P54_CONTROL_TYPE_XBOW_SYNTH_CFG, GFP_KERNEL); if (!skb) return -ENOMEM; @@ -2115,7 +2108,7 @@ static void p54_work(struct work_struct *work) * 2. cancel stuck frames / reset the device if necessary. */ - skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL, sizeof(struct p54_hdr) + + skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL, sizeof(struct p54_statistics), P54_CONTROL_TYPE_STAT_READBACK, GFP_KERNEL); if (!skb) @@ -2226,9 +2219,8 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, } mutex_lock(&priv->conf_mutex); - skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*rxkey) + - sizeof(struct p54_hdr), P54_CONTROL_TYPE_RX_KEYCACHE, - GFP_ATOMIC); + skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*rxkey), + P54_CONTROL_TYPE_RX_KEYCACHE, GFP_ATOMIC); if (!skb) { mutex_unlock(&priv->conf_mutex); return -ENOMEM; -- GitLab From 3cd08b383b2efe163272045afc415c75afc9e9c5 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 9 Jan 2009 21:06:06 +0100 Subject: [PATCH 0831/4982] p54: upgrade memrecord to p54_tx_info mac80211 reserves 24 bytes in skb->cb for the driver. So far, we only used them to keep track of used and free device memory. But p54spi will need a slice of it, as well as the stuck frame detection. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54.h | 10 ++++++++++ drivers/net/wireless/p54/p54common.c | 22 +++++++++++----------- drivers/net/wireless/p54/p54common.h | 6 ------ 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index ce933387792..a06c2a676df 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -44,6 +44,16 @@ enum p54_control_frame_types { P54_CONTROL_TYPE_BT_OPTIONS = 35 }; +/* provide 16 bytes for the transport back-end */ +#define P54_TX_INFO_DATA_SIZE 16 + +/* stored in ieee80211_tx_info's rate_driver_data */ +struct p54_tx_info { + u32 start_addr; + u32 end_addr; + void *data[P54_TX_INFO_DATA_SIZE / sizeof(void *)]; +}; + #define P54_MAX_CTRL_FRAME_LEN 0x1000 #define P54_HDR_FLAG_CONTROL BIT(15) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index c6dcf98aad3..85aff1685a1 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -700,7 +700,7 @@ void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb) { struct p54_common *priv = dev->priv; struct ieee80211_tx_info *info; - struct memrecord *range; + struct p54_tx_info *range; unsigned long flags; u32 freed = 0, last_addr = priv->rx_start; @@ -718,18 +718,18 @@ void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb) range = (void *)info->rate_driver_data; if (skb->prev != (struct sk_buff *)&priv->tx_queue) { struct ieee80211_tx_info *ni; - struct memrecord *mr; + struct p54_tx_info *mr; ni = IEEE80211_SKB_CB(skb->prev); - mr = (struct memrecord *)ni->rate_driver_data; + mr = (struct p54_tx_info *)ni->rate_driver_data; last_addr = mr->end_addr; } if (skb->next != (struct sk_buff *)&priv->tx_queue) { struct ieee80211_tx_info *ni; - struct memrecord *mr; + struct p54_tx_info *mr; ni = IEEE80211_SKB_CB(skb->next); - mr = (struct memrecord *)ni->rate_driver_data; + mr = (struct p54_tx_info *)ni->rate_driver_data; freed = mr->start_addr - last_addr; } else freed = priv->rx_end - last_addr; @@ -771,7 +771,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) struct p54_frame_sent *payload = (struct p54_frame_sent *) hdr->data; struct sk_buff *entry = (struct sk_buff *) priv->tx_queue.next; u32 addr = le32_to_cpu(hdr->req_id) - priv->headroom; - struct memrecord *range = NULL; + struct p54_tx_info *range = NULL; u32 freed = 0; u32 last_addr = priv->rx_start; unsigned long flags; @@ -793,10 +793,10 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) if (entry->next != (struct sk_buff *)&priv->tx_queue) { struct ieee80211_tx_info *ni; - struct memrecord *mr; + struct p54_tx_info *mr; ni = IEEE80211_SKB_CB(entry->next); - mr = (struct memrecord *)ni->rate_driver_data; + mr = (struct p54_tx_info *)ni->rate_driver_data; freed = mr->start_addr - last_addr; } else freed = priv->rx_end - last_addr; @@ -1013,8 +1013,8 @@ EXPORT_SYMBOL_GPL(p54_rx); * can find some unused memory to upload our packets to. However, data that we * want the card to TX needs to stay intact until the card has told us that * it is done with it. This function finds empty places we can upload to and - * marks allocated areas as reserved if necessary. p54_rx_frame_sent frees - * allocated areas. + * marks allocated areas as reserved if necessary. p54_rx_frame_sent or + * p54_free_skb frees allocated areas. */ static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb, struct p54_hdr *data, u32 len) @@ -1023,7 +1023,7 @@ static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb, struct sk_buff *entry = priv->tx_queue.next; struct sk_buff *target_skb = NULL; struct ieee80211_tx_info *info; - struct memrecord *range; + struct p54_tx_info *range; u32 last_addr = priv->rx_start; u32 largest_hole = 0; u32 target_addr = priv->rx_start; diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h index 6207323848b..bcfb75a4d6b 100644 --- a/drivers/net/wireless/p54/p54common.h +++ b/drivers/net/wireless/p54/p54common.h @@ -247,12 +247,6 @@ struct pda_country { #define PDR_COUNTRY_CERT_IODOOR_OUTDOOR 0x30 #define PDR_COUNTRY_CERT_INDEX 0x0F -/* stored in skb->cb */ -struct memrecord { - u32 start_addr; - u32 end_addr; -}; - struct p54_eeprom_lm86 { union { struct { -- GitLab From d2b21f191753abd12c4063776cb1a3d635397509 Mon Sep 17 00:00:00 2001 From: Colin McCabe Date: Fri, 9 Jan 2009 14:58:09 -0800 Subject: [PATCH 0832/4982] libertas: if_spi, driver for libertas GSPI devices Add initial support for libertas devices using a GSPI interface. This has been tested with the 8686. GSPI is intended to be used on embedded systems. Board-specific parameters are required (see libertas_spi.h). Thanks to everyone who took a look at the earlier versions of the patch. Signed-off-by: Colin McCabe Signed-off-by: Andrey Yurovsky Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 6 + drivers/net/wireless/libertas/Makefile | 2 + drivers/net/wireless/libertas/defs.h | 2 + drivers/net/wireless/libertas/if_spi.c | 1203 ++++++++++++++++++++++++ drivers/net/wireless/libertas/if_spi.h | 208 ++++ include/linux/spi/libertas_spi.h | 25 + 6 files changed, 1446 insertions(+) create mode 100644 drivers/net/wireless/libertas/if_spi.c create mode 100644 drivers/net/wireless/libertas/if_spi.h create mode 100644 include/linux/spi/libertas_spi.h diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index e4f9f747de8..2dddbd012a9 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -151,6 +151,12 @@ config LIBERTAS_SDIO ---help--- A driver for Marvell Libertas 8385 and 8686 SDIO devices. +config LIBERTAS_SPI + tristate "Marvell Libertas 8686 SPI 802.11b/g cards" + depends on LIBERTAS && SPI && GENERIC_GPIO + ---help--- + A driver for Marvell Libertas 8686 SPI devices. + config LIBERTAS_DEBUG bool "Enable full debugging output in the Libertas module." depends on LIBERTAS diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile index 02080a3682a..0b691858450 100644 --- a/drivers/net/wireless/libertas/Makefile +++ b/drivers/net/wireless/libertas/Makefile @@ -4,8 +4,10 @@ libertas-objs := main.o wext.o rx.o tx.o cmd.o cmdresp.o scan.o 11d.o \ usb8xxx-objs += if_usb.o libertas_cs-objs += if_cs.o libertas_sdio-objs += if_sdio.o +libertas_spi-objs += if_spi.o obj-$(CONFIG_LIBERTAS) += libertas.o obj-$(CONFIG_LIBERTAS_USB) += usb8xxx.o obj-$(CONFIG_LIBERTAS_CS) += libertas_cs.o obj-$(CONFIG_LIBERTAS_SDIO) += libertas_sdio.o +obj-$(CONFIG_LIBERTAS_SPI) += libertas_spi.o diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index c364e4c01d1..6388b05df4f 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h @@ -41,6 +41,7 @@ #define LBS_DEB_HEX 0x00200000 #define LBS_DEB_SDIO 0x00400000 #define LBS_DEB_SYSFS 0x00800000 +#define LBS_DEB_SPI 0x01000000 extern unsigned int lbs_debug; @@ -84,6 +85,7 @@ do { if ((lbs_debug & (grp)) == (grp)) \ #define lbs_deb_thread(fmt, args...) LBS_DEB_LL(LBS_DEB_THREAD, " thread", fmt, ##args) #define lbs_deb_sdio(fmt, args...) LBS_DEB_LL(LBS_DEB_SDIO, " sdio", fmt, ##args) #define lbs_deb_sysfs(fmt, args...) LBS_DEB_LL(LBS_DEB_SYSFS, " sysfs", fmt, ##args) +#define lbs_deb_spi(fmt, args...) LBS_DEB_LL(LBS_DEB_SPI, " spi", fmt, ##args) #define lbs_pr_info(format, args...) \ printk(KERN_INFO DRV_NAME": " format, ## args) diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c new file mode 100644 index 00000000000..7c02ea314fd --- /dev/null +++ b/drivers/net/wireless/libertas/if_spi.c @@ -0,0 +1,1203 @@ +/* + * linux/drivers/net/wireless/libertas/if_spi.c + * + * Driver for Marvell SPI WLAN cards. + * + * Copyright 2008 Analog Devices Inc. + * + * Authors: + * Andrey Yurovsky + * Colin McCabe + * + * Inspired by if_sdio.c, Copyright 2007-2008 Pierre Ossman + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "host.h" +#include "decl.h" +#include "defs.h" +#include "dev.h" +#include "if_spi.h" + +struct if_spi_packet { + struct list_head list; + u16 blen; + u8 buffer[0] __attribute__((aligned(4))); +}; + +struct if_spi_card { + struct spi_device *spi; + struct lbs_private *priv; + + char helper_fw_name[FIRMWARE_NAME_MAX]; + char main_fw_name[FIRMWARE_NAME_MAX]; + + /* The card ID and card revision, as reported by the hardware. */ + u16 card_id; + u8 card_rev; + + /* Pin number for our GPIO chip-select. */ + /* TODO: Once the generic SPI layer has some additional features, we + * should take this out and use the normal chip select here. + * We need support for chip select delays, and not dropping chipselect + * after each word. */ + int gpio_cs; + + /* The last time that we initiated an SPU operation */ + unsigned long prev_xfer_time; + + int use_dummy_writes; + unsigned long spu_port_delay; + unsigned long spu_reg_delay; + + /* Handles all SPI communication (except for FW load) */ + struct task_struct *spi_thread; + int run_thread; + + /* Used to wake up the spi_thread */ + struct semaphore spi_ready; + struct semaphore spi_thread_terminated; + + u8 cmd_buffer[IF_SPI_CMD_BUF_SIZE]; + + /* A buffer of incoming packets from libertas core. + * Since we can't sleep in hw_host_to_card, we have to buffer + * them. */ + struct list_head cmd_packet_list; + struct list_head data_packet_list; + + /* Protects cmd_packet_list and data_packet_list */ + spinlock_t buffer_lock; +}; + +static void free_if_spi_card(struct if_spi_card *card) +{ + struct list_head *cursor, *next; + struct if_spi_packet *packet; + + BUG_ON(card->run_thread); + list_for_each_safe(cursor, next, &card->cmd_packet_list) { + packet = container_of(cursor, struct if_spi_packet, list); + list_del(&packet->list); + kfree(packet); + } + list_for_each_safe(cursor, next, &card->data_packet_list) { + packet = container_of(cursor, struct if_spi_packet, list); + list_del(&packet->list); + kfree(packet); + } + spi_set_drvdata(card->spi, NULL); + kfree(card); +} + +static struct chip_ident chip_id_to_device_name[] = { + { .chip_id = 0x04, .name = 8385 }, + { .chip_id = 0x0b, .name = 8686 }, +}; + +/* + * SPI Interface Unit Routines + * + * The SPU sits between the host and the WLAN module. + * All communication with the firmware is through SPU transactions. + * + * First we have to put a SPU register name on the bus. Then we can + * either read from or write to that register. + * + * For 16-bit transactions, byte order on the bus is big-endian. + * We don't have to worry about that here, though. + * The translation takes place in the SPI routines. + */ + +static void spu_transaction_init(struct if_spi_card *card) +{ + if (!time_after(jiffies, card->prev_xfer_time + 1)) { + /* Unfortunately, the SPU requires a delay between successive + * transactions. If our last transaction was more than a jiffy + * ago, we have obviously already delayed enough. + * If not, we have to busy-wait to be on the safe side. */ + ndelay(400); + } + gpio_set_value(card->gpio_cs, 0); /* assert CS */ +} + +static void spu_transaction_finish(struct if_spi_card *card) +{ + gpio_set_value(card->gpio_cs, 1); /* drop CS */ + card->prev_xfer_time = jiffies; +} + +/* Write out a byte buffer to an SPI register, + * using a series of 16-bit transfers. */ +static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len) +{ + int err = 0; + u16 reg_out = reg | IF_SPI_WRITE_OPERATION_MASK; + + /* You must give an even number of bytes to the SPU, even if it + * doesn't care about the last one. */ + BUG_ON(len & 0x1); + + spu_transaction_init(card); + + /* write SPU register index */ + err = spi_write(card->spi, (u8 *)®_out, sizeof(u16)); + if (err) + goto out; + + err = spi_write(card->spi, buf, len); + +out: + spu_transaction_finish(card); + return err; +} + +static inline int spu_write_u16(struct if_spi_card *card, u16 reg, u16 val) +{ + return spu_write(card, reg, (u8 *)&val, sizeof(u16)); +} + +static inline int spu_write_u32(struct if_spi_card *card, u16 reg, u32 val) +{ + /* The lower 16 bits are written first. */ + u16 out[2]; + out[0] = val & 0xffff; + out[1] = (val & 0xffff0000) >> 16; + return spu_write(card, reg, (u8 *)&out, sizeof(u32)); +} + +static inline int spu_reg_is_port_reg(u16 reg) +{ + switch (reg) { + case IF_SPI_IO_RDWRPORT_REG: + case IF_SPI_CMD_RDWRPORT_REG: + case IF_SPI_DATA_RDWRPORT_REG: + return 1; + default: + return 0; + } +} + +static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len) +{ + unsigned int i, delay; + int err = 0; + u16 zero = 0; + u16 reg_out = reg | IF_SPI_READ_OPERATION_MASK; + + /* You must take an even number of bytes from the SPU, even if you + * don't care about the last one. */ + BUG_ON(len & 0x1); + + spu_transaction_init(card); + + /* write SPU register index */ + err = spi_write(card->spi, (u8 *)®_out, sizeof(u16)); + if (err) + goto out; + + delay = spu_reg_is_port_reg(reg) ? card->spu_port_delay : + card->spu_reg_delay; + if (card->use_dummy_writes) { + /* Clock in dummy cycles while the SPU fills the FIFO */ + for (i = 0; i < delay / 16; ++i) { + err = spi_write(card->spi, (u8 *)&zero, sizeof(u16)); + if (err) + return err; + } + } else { + /* Busy-wait while the SPU fills the FIFO */ + ndelay(100 + (delay * 10)); + } + + /* read in data */ + err = spi_read(card->spi, buf, len); + +out: + spu_transaction_finish(card); + return err; +} + +/* Read 16 bits from an SPI register */ +static inline int spu_read_u16(struct if_spi_card *card, u16 reg, u16 *val) +{ + return spu_read(card, reg, (u8 *)val, sizeof(u16)); +} + +/* Read 32 bits from an SPI register. + * The low 16 bits are read first. */ +static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val) +{ + u16 buf[2]; + int err; + err = spu_read(card, reg, (u8 *)buf, sizeof(u32)); + if (!err) + *val = buf[0] | (buf[1] << 16); + return err; +} + +/* Keep reading 16 bits from an SPI register until you get the correct result. + * + * If mask = 0, the correct result is any non-zero number. + * If mask != 0, the correct result is any number where + * number & target_mask == target + * + * Returns -ETIMEDOUT if a second passes without the correct result. */ +static int spu_wait_for_u16(struct if_spi_card *card, u16 reg, + u16 target_mask, u16 target) +{ + int err; + unsigned long timeout = jiffies + 5*HZ; + while (1) { + u16 val; + err = spu_read_u16(card, reg, &val); + if (err) + return err; + if (target_mask) { + if ((val & target_mask) == target) + return 0; + } else { + if (val) + return 0; + } + udelay(100); + if (time_after(jiffies, timeout)) { + lbs_pr_err("%s: timeout with val=%02x, " + "target_mask=%02x, target=%02x\n", + __func__, val, target_mask, target); + return -ETIMEDOUT; + } + } +} + +/* Read 16 bits from an SPI register until you receive a specific value. + * Returns -ETIMEDOUT if a 4 tries pass without success. */ +static int spu_wait_for_u32(struct if_spi_card *card, u32 reg, u32 target) +{ + int err, try; + for (try = 0; try < 4; ++try) { + u32 val = 0; + err = spu_read_u32(card, reg, &val); + if (err) + return err; + if (val == target) + return 0; + mdelay(100); + } + return -ETIMEDOUT; +} + +static int spu_set_interrupt_mode(struct if_spi_card *card, + int suppress_host_int, + int auto_int) +{ + int err = 0; + + /* We can suppress a host interrupt by clearing the appropriate + * bit in the "host interrupt status mask" register */ + if (suppress_host_int) { + err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, 0); + if (err) + return err; + } else { + err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, + IF_SPI_HISM_TX_DOWNLOAD_RDY | + IF_SPI_HISM_RX_UPLOAD_RDY | + IF_SPI_HISM_CMD_DOWNLOAD_RDY | + IF_SPI_HISM_CARDEVENT | + IF_SPI_HISM_CMD_UPLOAD_RDY); + if (err) + return err; + } + + /* If auto-interrupts are on, the completion of certain transactions + * will trigger an interrupt automatically. If auto-interrupts + * are off, we need to set the "Card Interrupt Cause" register to + * trigger a card interrupt. */ + if (auto_int) { + err = spu_write_u16(card, IF_SPI_HOST_INT_CTRL_REG, + IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO | + IF_SPI_HICT_RX_UPLOAD_OVER_AUTO | + IF_SPI_HICT_CMD_DOWNLOAD_OVER_AUTO | + IF_SPI_HICT_CMD_UPLOAD_OVER_AUTO); + if (err) + return err; + } else { + err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, 0); + if (err) + return err; + } + return err; +} + +static int spu_get_chip_revision(struct if_spi_card *card, + u16 *card_id, u8 *card_rev) +{ + int err = 0; + u32 dev_ctrl; + err = spu_read_u32(card, IF_SPI_DEVICEID_CTRL_REG, &dev_ctrl); + if (err) + return err; + *card_id = IF_SPI_DEVICEID_CTRL_REG_TO_CARD_ID(dev_ctrl); + *card_rev = IF_SPI_DEVICEID_CTRL_REG_TO_CARD_REV(dev_ctrl); + return err; +} + +static int spu_set_bus_mode(struct if_spi_card *card, u16 mode) +{ + int err = 0; + u16 rval; + /* set bus mode */ + err = spu_write_u16(card, IF_SPI_SPU_BUS_MODE_REG, mode); + if (err) + return err; + /* Check that we were able to read back what we just wrote. */ + err = spu_read_u16(card, IF_SPI_SPU_BUS_MODE_REG, &rval); + if (err) + return err; + if (rval != mode) { + lbs_pr_err("Can't read bus mode register.\n"); + return -EIO; + } + return 0; +} + +static int spu_init(struct if_spi_card *card, int use_dummy_writes) +{ + int err = 0; + u32 delay; + + /* We have to start up in timed delay mode so that we can safely + * read the Delay Read Register. */ + card->use_dummy_writes = 0; + err = spu_set_bus_mode(card, + IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING | + IF_SPI_BUS_MODE_DELAY_METHOD_TIMED | + IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA); + if (err) + return err; + card->spu_port_delay = 1000; + card->spu_reg_delay = 1000; + err = spu_read_u32(card, IF_SPI_DELAY_READ_REG, &delay); + if (err) + return err; + card->spu_port_delay = delay & 0x0000ffff; + card->spu_reg_delay = (delay & 0xffff0000) >> 16; + + /* If dummy clock delay mode has been requested, switch to it now */ + if (use_dummy_writes) { + card->use_dummy_writes = 1; + err = spu_set_bus_mode(card, + IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING | + IF_SPI_BUS_MODE_DELAY_METHOD_DUMMY_CLOCK | + IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA); + if (err) + return err; + } + + lbs_deb_spi("Initialized SPU unit. " + "spu_port_delay=0x%04lx, spu_reg_delay=0x%04lx\n", + card->spu_port_delay, card->spu_reg_delay); + return err; +} + +/* + * Firmware Loading + */ + +static int if_spi_prog_helper_firmware(struct if_spi_card *card) +{ + int err = 0; + const struct firmware *firmware = NULL; + int bytes_remaining; + const u8 *fw; + u8 temp[HELPER_FW_LOAD_CHUNK_SZ]; + struct spi_device *spi = card->spi; + + lbs_deb_enter(LBS_DEB_SPI); + + err = spu_set_interrupt_mode(card, 1, 0); + if (err) + goto out; + /* Get helper firmware image */ + err = request_firmware(&firmware, card->helper_fw_name, &spi->dev); + if (err) { + lbs_pr_err("request_firmware failed with err = %d\n", err); + goto out; + } + bytes_remaining = firmware->size; + fw = firmware->data; + + /* Load helper firmware image */ + while (bytes_remaining > 0) { + /* Scratch pad 1 should contain the number of bytes we + * want to download to the firmware */ + err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, + HELPER_FW_LOAD_CHUNK_SZ); + if (err) + goto release_firmware; + + err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG, + IF_SPI_HIST_CMD_DOWNLOAD_RDY, + IF_SPI_HIST_CMD_DOWNLOAD_RDY); + if (err) + goto release_firmware; + + /* Feed the data into the command read/write port reg + * in chunks of 64 bytes */ + memset(temp, 0, sizeof(temp)); + memcpy(temp, fw, + min(bytes_remaining, HELPER_FW_LOAD_CHUNK_SZ)); + mdelay(10); + err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, + temp, HELPER_FW_LOAD_CHUNK_SZ); + if (err) + goto release_firmware; + + /* Interrupt the boot code */ + err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); + if (err) + goto release_firmware; + err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, + IF_SPI_CIC_CMD_DOWNLOAD_OVER); + if (err) + goto release_firmware; + bytes_remaining -= HELPER_FW_LOAD_CHUNK_SZ; + fw += HELPER_FW_LOAD_CHUNK_SZ; + } + + /* Once the helper / single stage firmware download is complete, + * write 0 to scratch pad 1 and interrupt the + * bootloader. This completes the helper download. */ + err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK); + if (err) + goto release_firmware; + err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); + if (err) + goto release_firmware; + err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, + IF_SPI_CIC_CMD_DOWNLOAD_OVER); + goto release_firmware; + + lbs_deb_spi("waiting for helper to boot...\n"); + +release_firmware: + release_firmware(firmware); +out: + if (err) + lbs_pr_err("failed to load helper firmware (err=%d)\n", err); + lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err); + return err; +} + +/* Returns the length of the next packet the firmware expects us to send + * Sets crc_err if the previous transfer had a CRC error. */ +static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card, + int *crc_err) +{ + u16 len; + int err = 0; + + /* wait until the host interrupt status register indicates + * that we are ready to download */ + err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG, + IF_SPI_HIST_CMD_DOWNLOAD_RDY, + IF_SPI_HIST_CMD_DOWNLOAD_RDY); + if (err) { + lbs_pr_err("timed out waiting for host_int_status\n"); + return err; + } + + /* Ask the device how many bytes of firmware it wants. */ + err = spu_read_u16(card, IF_SPI_SCRATCH_1_REG, &len); + if (err) + return err; + + if (len > IF_SPI_CMD_BUF_SIZE) { + lbs_pr_err("firmware load device requested a larger " + "tranfer than we are prepared to " + "handle. (len = %d)\n", len); + return -EIO; + } + if (len & 0x1) { + lbs_deb_spi("%s: crc error\n", __func__); + len &= ~0x1; + *crc_err = 1; + } else + *crc_err = 0; + + return len; +} + +static int if_spi_prog_main_firmware(struct if_spi_card *card) +{ + int len, prev_len; + int bytes, crc_err = 0, err = 0; + const struct firmware *firmware = NULL; + const u8 *fw; + struct spi_device *spi = card->spi; + u16 num_crc_errs; + + lbs_deb_enter(LBS_DEB_SPI); + + err = spu_set_interrupt_mode(card, 1, 0); + if (err) + goto out; + + /* Get firmware image */ + err = request_firmware(&firmware, card->main_fw_name, &spi->dev); + if (err) { + lbs_pr_err("%s: can't get firmware '%s' from kernel. " + "err = %d\n", __func__, card->main_fw_name, err); + goto out; + } + + err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0); + if (err) { + lbs_pr_err("%s: timed out waiting for initial " + "scratch reg = 0\n", __func__); + goto release_firmware; + } + + num_crc_errs = 0; + prev_len = 0; + bytes = firmware->size; + fw = firmware->data; + while ((len = if_spi_prog_main_firmware_check_len(card, &crc_err))) { + if (len < 0) { + err = len; + goto release_firmware; + } + if (bytes < 0) { + /* If there are no more bytes left, we would normally + * expect to have terminated with len = 0 */ + lbs_pr_err("Firmware load wants more bytes " + "than we have to offer.\n"); + break; + } + if (crc_err) { + /* Previous transfer failed. */ + if (++num_crc_errs > MAX_MAIN_FW_LOAD_CRC_ERR) { + lbs_pr_err("Too many CRC errors encountered " + "in firmware load.\n"); + err = -EIO; + goto release_firmware; + } + } else { + /* Previous transfer succeeded. Advance counters. */ + bytes -= prev_len; + fw += prev_len; + } + if (bytes < len) { + memset(card->cmd_buffer, 0, len); + memcpy(card->cmd_buffer, fw, bytes); + } else + memcpy(card->cmd_buffer, fw, len); + + err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); + if (err) + goto release_firmware; + err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, + card->cmd_buffer, len); + if (err) + goto release_firmware; + err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG , + IF_SPI_CIC_CMD_DOWNLOAD_OVER); + if (err) + goto release_firmware; + prev_len = len; + } + if (bytes > prev_len) { + lbs_pr_err("firmware load wants fewer bytes than " + "we have to offer.\n"); + } + + /* Confirm firmware download */ + err = spu_wait_for_u32(card, IF_SPI_SCRATCH_4_REG, + SUCCESSFUL_FW_DOWNLOAD_MAGIC); + if (err) { + lbs_pr_err("failed to confirm the firmware download\n"); + goto release_firmware; + } + +release_firmware: + release_firmware(firmware); + +out: + if (err) + lbs_pr_err("failed to load firmware (err=%d)\n", err); + lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err); + return err; +} + +/* + * SPI Transfer Thread + * + * The SPI thread handles all SPI transfers, so there is no need for a lock. + */ + +/* Move a command from the card to the host */ +static int if_spi_c2h_cmd(struct if_spi_card *card) +{ + struct lbs_private *priv = card->priv; + unsigned long flags; + int err = 0; + u16 len; + u8 i; + + /* We need a buffer big enough to handle whatever people send to + * hw_host_to_card */ + BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_CMD_BUFFER_SIZE); + BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_UPLD_SIZE); + + /* It's just annoying if the buffer size isn't a multiple of 4, because + * then we might have len < IF_SPI_CMD_BUF_SIZE but + * ALIGN(len, 4) > IF_SPI_CMD_BUF_SIZE */ + BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE % 4 != 0); + + lbs_deb_enter(LBS_DEB_SPI); + + /* How many bytes are there to read? */ + err = spu_read_u16(card, IF_SPI_SCRATCH_2_REG, &len); + if (err) + goto out; + if (!len) { + lbs_pr_err("%s: error: card has no data for host\n", + __func__); + err = -EINVAL; + goto out; + } else if (len > IF_SPI_CMD_BUF_SIZE) { + lbs_pr_err("%s: error: response packet too large: " + "%d bytes, but maximum is %d\n", + __func__, len, IF_SPI_CMD_BUF_SIZE); + err = -EINVAL; + goto out; + } + + /* Read the data from the WLAN module into our command buffer */ + err = spu_read(card, IF_SPI_CMD_RDWRPORT_REG, + card->cmd_buffer, ALIGN(len, 4)); + if (err) + goto out; + + spin_lock_irqsave(&priv->driver_lock, flags); + i = (priv->resp_idx == 0) ? 1 : 0; + BUG_ON(priv->resp_len[i]); + priv->resp_len[i] = len; + memcpy(priv->resp_buf[i], card->cmd_buffer, len); + lbs_notify_command_response(priv, i); + spin_unlock_irqrestore(&priv->driver_lock, flags); + +out: + if (err) + lbs_pr_err("%s: err=%d\n", __func__, err); + lbs_deb_leave(LBS_DEB_SPI); + return err; +} + +/* Move data from the card to the host */ +static int if_spi_c2h_data(struct if_spi_card *card) +{ + struct sk_buff *skb; + char *data; + u16 len; + int err = 0; + + lbs_deb_enter(LBS_DEB_SPI); + + /* How many bytes are there to read? */ + err = spu_read_u16(card, IF_SPI_SCRATCH_1_REG, &len); + if (err) + goto out; + if (!len) { + lbs_pr_err("%s: error: card has no data for host\n", + __func__); + err = -EINVAL; + goto out; + } else if (len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { + lbs_pr_err("%s: error: card has %d bytes of data, but " + "our maximum skb size is %u\n", + __func__, len, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE); + err = -EINVAL; + goto out; + } + + /* TODO: should we allocate a smaller skb if we have less data? */ + skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE); + if (!skb) { + err = -ENOBUFS; + goto out; + } + skb_reserve(skb, IPFIELD_ALIGN_OFFSET); + data = skb_put(skb, len); + + /* Read the data from the WLAN module into our skb... */ + err = spu_read(card, IF_SPI_DATA_RDWRPORT_REG, data, ALIGN(len, 4)); + if (err) + goto free_skb; + + /* pass the SKB to libertas */ + err = lbs_process_rxed_packet(card->priv, skb); + if (err) + goto free_skb; + + /* success */ + goto out; + +free_skb: + dev_kfree_skb(skb); +out: + if (err) + lbs_pr_err("%s: err=%d\n", __func__, err); + lbs_deb_leave(LBS_DEB_SPI); + return err; +} + +/* Move data or a command from the host to the card. */ +static void if_spi_h2c(struct if_spi_card *card, + struct if_spi_packet *packet, int type) +{ + int err = 0; + u16 int_type, port_reg; + + switch (type) { + case MVMS_DAT: + int_type = IF_SPI_CIC_TX_DOWNLOAD_OVER; + port_reg = IF_SPI_DATA_RDWRPORT_REG; + break; + case MVMS_CMD: + int_type = IF_SPI_CIC_CMD_DOWNLOAD_OVER; + port_reg = IF_SPI_CMD_RDWRPORT_REG; + break; + default: + lbs_pr_err("can't transfer buffer of type %d\n", type); + err = -EINVAL; + goto out; + } + + /* Write the data to the card */ + err = spu_write(card, port_reg, packet->buffer, packet->blen); + if (err) + goto out; + +out: + kfree(packet); + + if (err) + lbs_pr_err("%s: error %d\n", __func__, err); +} + +/* Inform the host about a card event */ +static void if_spi_e2h(struct if_spi_card *card) +{ + int err = 0; + unsigned long flags; + u32 cause; + struct lbs_private *priv = card->priv; + + err = spu_read_u32(card, IF_SPI_SCRATCH_3_REG, &cause); + if (err) + goto out; + + spin_lock_irqsave(&priv->driver_lock, flags); + lbs_queue_event(priv, cause & 0xff); + spin_unlock_irqrestore(&priv->driver_lock, flags); + +out: + if (err) + lbs_pr_err("%s: error %d\n", __func__, err); +} + +static int lbs_spi_thread(void *data) +{ + int err; + struct if_spi_card *card = data; + u16 hiStatus; + unsigned long flags; + struct if_spi_packet *packet; + + while (1) { + /* Wait to be woken up by one of two things. First, our ISR + * could tell us that something happened on the WLAN. + * Secondly, libertas could call hw_host_to_card with more + * data, which we might be able to send. + */ + do { + err = down_interruptible(&card->spi_ready); + if (!card->run_thread) { + up(&card->spi_thread_terminated); + do_exit(0); + } + } while (err == EINTR); + + /* Read the host interrupt status register to see what we + * can do. */ + err = spu_read_u16(card, IF_SPI_HOST_INT_STATUS_REG, + &hiStatus); + if (err) { + lbs_pr_err("I/O error\n"); + goto err; + } + + if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY) + err = if_spi_c2h_cmd(card); + if (err) + goto err; + if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY) + err = if_spi_c2h_data(card); + if (err) + goto err; + if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY) { + /* This means two things. First of all, + * if there was a previous command sent, the card has + * successfully received it. + * Secondly, it is now ready to download another + * command. + */ + lbs_host_to_card_done(card->priv); + + /* Do we have any command packets from the host to + * send? */ + packet = NULL; + spin_lock_irqsave(&card->buffer_lock, flags); + if (!list_empty(&card->cmd_packet_list)) { + packet = (struct if_spi_packet *)(card-> + cmd_packet_list.next); + list_del(&packet->list); + } + spin_unlock_irqrestore(&card->buffer_lock, flags); + + if (packet) + if_spi_h2c(card, packet, MVMS_CMD); + } + if (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY) { + /* Do we have any data packets from the host to + * send? */ + packet = NULL; + spin_lock_irqsave(&card->buffer_lock, flags); + if (!list_empty(&card->data_packet_list)) { + packet = (struct if_spi_packet *)(card-> + data_packet_list.next); + list_del(&packet->list); + } + spin_unlock_irqrestore(&card->buffer_lock, flags); + + if (packet) + if_spi_h2c(card, packet, MVMS_DAT); + } + if (hiStatus & IF_SPI_HIST_CARD_EVENT) + if_spi_e2h(card); + +err: + if (err) + lbs_pr_err("%s: got error %d\n", __func__, err); + } +} + +/* Block until lbs_spi_thread thread has terminated */ +static void if_spi_terminate_spi_thread(struct if_spi_card *card) +{ + /* It would be nice to use kthread_stop here, but that function + * can't wake threads waiting for a semaphore. */ + card->run_thread = 0; + up(&card->spi_ready); + down(&card->spi_thread_terminated); +} + +/* + * Host to Card + * + * Called from Libertas to transfer some data to the WLAN device + * We can't sleep here. */ +static int if_spi_host_to_card(struct lbs_private *priv, + u8 type, u8 *buf, u16 nb) +{ + int err = 0; + unsigned long flags; + struct if_spi_card *card = priv->card; + struct if_spi_packet *packet; + u16 blen; + + lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb); + + if (nb == 0) { + lbs_pr_err("%s: invalid size requested: %d\n", __func__, nb); + err = -EINVAL; + goto out; + } + blen = ALIGN(nb, 4); + packet = kzalloc(sizeof(struct if_spi_packet) + blen, GFP_ATOMIC); + if (!packet) { + err = -ENOMEM; + goto out; + } + packet->blen = blen; + memcpy(packet->buffer, buf, nb); + memset(packet->buffer + nb, 0, blen - nb); + + switch (type) { + case MVMS_CMD: + priv->dnld_sent = DNLD_CMD_SENT; + spin_lock_irqsave(&card->buffer_lock, flags); + list_add_tail(&packet->list, &card->cmd_packet_list); + spin_unlock_irqrestore(&card->buffer_lock, flags); + break; + case MVMS_DAT: + priv->dnld_sent = DNLD_DATA_SENT; + spin_lock_irqsave(&card->buffer_lock, flags); + list_add_tail(&packet->list, &card->data_packet_list); + spin_unlock_irqrestore(&card->buffer_lock, flags); + break; + default: + lbs_pr_err("can't transfer buffer of type %d", type); + err = -EINVAL; + break; + } + + /* Wake up the spi thread */ + up(&card->spi_ready); +out: + lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err); + return err; +} + +/* + * Host Interrupts + * + * Service incoming interrupts from the WLAN device. We can't sleep here, so + * don't try to talk on the SPI bus, just wake up the SPI thread. + */ +static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id) +{ + struct if_spi_card *card = dev_id; + + up(&card->spi_ready); + return IRQ_HANDLED; +} + +/* + * SPI callbacks + */ + +static int if_spi_calculate_fw_names(u16 card_id, + char *helper_fw, char *main_fw) +{ + int i; + for (i = 0; i < ARRAY_SIZE(chip_id_to_device_name); ++i) { + if (card_id == chip_id_to_device_name[i].chip_id) + break; + } + if (i == ARRAY_SIZE(chip_id_to_device_name)) { + lbs_pr_err("Unsupported chip_id: 0x%02x\n", card_id); + return -EAFNOSUPPORT; + } + snprintf(helper_fw, FIRMWARE_NAME_MAX, "libertas/gspi%d_hlp.bin", + chip_id_to_device_name[i].name); + snprintf(main_fw, FIRMWARE_NAME_MAX, "libertas/gspi%d.bin", + chip_id_to_device_name[i].name); + return 0; +} + +static int __devinit if_spi_probe(struct spi_device *spi) +{ + struct if_spi_card *card; + struct lbs_private *priv = NULL; + struct libertas_spi_platform_data *pdata = spi->dev.platform_data; + int err = 0; + u32 scratch; + + lbs_deb_enter(LBS_DEB_SPI); + + /* Allocate card structure to represent this specific device */ + card = kzalloc(sizeof(struct if_spi_card), GFP_KERNEL); + if (!card) { + err = -ENOMEM; + goto out; + } + spi_set_drvdata(spi, card); + card->spi = spi; + card->gpio_cs = pdata->gpio_cs; + card->prev_xfer_time = jiffies; + + sema_init(&card->spi_ready, 0); + sema_init(&card->spi_thread_terminated, 0); + INIT_LIST_HEAD(&card->cmd_packet_list); + INIT_LIST_HEAD(&card->data_packet_list); + spin_lock_init(&card->buffer_lock); + + /* set up GPIO CS line. TODO: use regular CS line */ + err = gpio_request(card->gpio_cs, "if_spi_gpio_chip_select"); + if (err) + goto free_card; + err = gpio_direction_output(card->gpio_cs, 1); + if (err) + goto free_gpio; + + /* Initialize the SPI Interface Unit */ + err = spu_init(card, pdata->use_dummy_writes); + if (err) + goto free_gpio; + err = spu_get_chip_revision(card, &card->card_id, &card->card_rev); + if (err) + goto free_gpio; + + /* Firmware load */ + err = spu_read_u32(card, IF_SPI_SCRATCH_4_REG, &scratch); + if (err) + goto free_gpio; + if (scratch == SUCCESSFUL_FW_DOWNLOAD_MAGIC) + lbs_deb_spi("Firmware is already loaded for " + "Marvell WLAN 802.11 adapter\n"); + else { + err = if_spi_calculate_fw_names(card->card_id, + card->helper_fw_name, card->main_fw_name); + if (err) + goto free_gpio; + + lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter " + "(chip_id = 0x%04x, chip_rev = 0x%02x) " + "attached to SPI bus_num %d, chip_select %d. " + "spi->max_speed_hz=%d\n", + card->card_id, card->card_rev, + spi->master->bus_num, spi->chip_select, + spi->max_speed_hz); + err = if_spi_prog_helper_firmware(card); + if (err) + goto free_gpio; + err = if_spi_prog_main_firmware(card); + if (err) + goto free_gpio; + lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n"); + } + + err = spu_set_interrupt_mode(card, 0, 1); + if (err) + goto free_gpio; + + /* Register our card with libertas. + * This will call alloc_etherdev */ + priv = lbs_add_card(card, &spi->dev); + if (!priv) { + err = -ENOMEM; + goto free_gpio; + } + card->priv = priv; + priv->card = card; + priv->hw_host_to_card = if_spi_host_to_card; + priv->fw_ready = 1; + priv->ps_supported = 1; + + /* Initialize interrupt handling stuff. */ + card->run_thread = 1; + card->spi_thread = kthread_run(lbs_spi_thread, card, "lbs_spi_thread"); + if (IS_ERR(card->spi_thread)) { + card->run_thread = 0; + err = PTR_ERR(card->spi_thread); + lbs_pr_err("error creating SPI thread: err=%d\n", err); + goto remove_card; + } + err = request_irq(spi->irq, if_spi_host_interrupt, + IRQF_TRIGGER_FALLING, "libertas_spi", card); + if (err) { + lbs_pr_err("can't get host irq line-- request_irq failed\n"); + goto terminate_thread; + } + + /* Start the card. + * This will call register_netdev, and we'll start + * getting interrupts... */ + err = lbs_start_card(priv); + if (err) + goto release_irq; + + lbs_deb_spi("Finished initializing WLAN module.\n"); + + /* successful exit */ + goto out; + +release_irq: + free_irq(spi->irq, card); +terminate_thread: + if_spi_terminate_spi_thread(card); +remove_card: + lbs_remove_card(priv); /* will call free_netdev */ +free_gpio: + gpio_free(card->gpio_cs); +free_card: + free_if_spi_card(card); +out: + lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); + return err; +} + +static int __devexit libertas_spi_remove(struct spi_device *spi) +{ + struct if_spi_card *card = spi_get_drvdata(spi); + struct lbs_private *priv = card->priv; + + lbs_deb_spi("libertas_spi_remove\n"); + lbs_deb_enter(LBS_DEB_SPI); + priv->surpriseremoved = 1; + + lbs_stop_card(priv); + free_irq(spi->irq, card); + if_spi_terminate_spi_thread(card); + lbs_remove_card(priv); /* will call free_netdev */ + gpio_free(card->gpio_cs); + free_if_spi_card(card); + lbs_deb_leave(LBS_DEB_SPI); + return 0; +} + +static struct spi_driver libertas_spi_driver = { + .probe = if_spi_probe, + .remove = __devexit_p(libertas_spi_remove), + .driver = { + .name = "libertas_spi", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, +}; + +/* + * Module functions + */ + +static int __init if_spi_init_module(void) +{ + int ret = 0; + lbs_deb_enter(LBS_DEB_SPI); + printk(KERN_INFO "libertas_spi: Libertas SPI driver\n"); + ret = spi_register_driver(&libertas_spi_driver); + lbs_deb_leave(LBS_DEB_SPI); + return ret; +} + +static void __exit if_spi_exit_module(void) +{ + lbs_deb_enter(LBS_DEB_SPI); + spi_unregister_driver(&libertas_spi_driver); + lbs_deb_leave(LBS_DEB_SPI); +} + +module_init(if_spi_init_module); +module_exit(if_spi_exit_module); + +MODULE_DESCRIPTION("Libertas SPI WLAN Driver"); +MODULE_AUTHOR("Andrey Yurovsky , " + "Colin McCabe "); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/libertas/if_spi.h b/drivers/net/wireless/libertas/if_spi.h new file mode 100644 index 00000000000..2103869cc5b --- /dev/null +++ b/drivers/net/wireless/libertas/if_spi.h @@ -0,0 +1,208 @@ +/* + * linux/drivers/net/wireless/libertas/if_spi.c + * + * Driver for Marvell SPI WLAN cards. + * + * Copyright 2008 Analog Devices Inc. + * + * Authors: + * Andrey Yurovsky + * Colin McCabe + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ + +#ifndef _LBS_IF_SPI_H_ +#define _LBS_IF_SPI_H_ + +#define IPFIELD_ALIGN_OFFSET 2 +#define IF_SPI_CMD_BUF_SIZE 2400 + +/***************** Firmware *****************/ +struct chip_ident { + u16 chip_id; + u16 name; +}; + +#define MAX_MAIN_FW_LOAD_CRC_ERR 10 + +/* Chunk size when loading the helper firmware */ +#define HELPER_FW_LOAD_CHUNK_SZ 64 + +/* Value to write to indicate end of helper firmware dnld */ +#define FIRMWARE_DNLD_OK 0x0000 + +/* Value to check once the main firmware is downloaded */ +#define SUCCESSFUL_FW_DOWNLOAD_MAGIC 0x88888888 + +/***************** SPI Interface Unit *****************/ +/* Masks used in SPI register read/write operations */ +#define IF_SPI_READ_OPERATION_MASK 0x0 +#define IF_SPI_WRITE_OPERATION_MASK 0x8000 + +/* SPI register offsets. 4-byte aligned. */ +#define IF_SPI_DEVICEID_CTRL_REG 0x00 /* DeviceID controller reg */ +#define IF_SPI_IO_READBASE_REG 0x04 /* Read I/O base reg */ +#define IF_SPI_IO_WRITEBASE_REG 0x08 /* Write I/O base reg */ +#define IF_SPI_IO_RDWRPORT_REG 0x0C /* Read/Write I/O port reg */ + +#define IF_SPI_CMD_READBASE_REG 0x10 /* Read command base reg */ +#define IF_SPI_CMD_WRITEBASE_REG 0x14 /* Write command base reg */ +#define IF_SPI_CMD_RDWRPORT_REG 0x18 /* Read/Write command port reg */ + +#define IF_SPI_DATA_READBASE_REG 0x1C /* Read data base reg */ +#define IF_SPI_DATA_WRITEBASE_REG 0x20 /* Write data base reg */ +#define IF_SPI_DATA_RDWRPORT_REG 0x24 /* Read/Write data port reg */ + +#define IF_SPI_SCRATCH_1_REG 0x28 /* Scratch reg 1 */ +#define IF_SPI_SCRATCH_2_REG 0x2C /* Scratch reg 2 */ +#define IF_SPI_SCRATCH_3_REG 0x30 /* Scratch reg 3 */ +#define IF_SPI_SCRATCH_4_REG 0x34 /* Scratch reg 4 */ + +#define IF_SPI_TX_FRAME_SEQ_NUM_REG 0x38 /* Tx frame sequence number reg */ +#define IF_SPI_TX_FRAME_STATUS_REG 0x3C /* Tx frame status reg */ + +#define IF_SPI_HOST_INT_CTRL_REG 0x40 /* Host interrupt controller reg */ + +#define IF_SPI_CARD_INT_CAUSE_REG 0x44 /* Card interrupt cause reg */ +#define IF_SPI_CARD_INT_STATUS_REG 0x48 /* Card interupt status reg */ +#define IF_SPI_CARD_INT_EVENT_MASK_REG 0x4C /* Card interrupt event mask */ +#define IF_SPI_CARD_INT_STATUS_MASK_REG 0x50 /* Card interrupt status mask */ + +#define IF_SPI_CARD_INT_RESET_SELECT_REG 0x54 /* Card interrupt reset select */ + +#define IF_SPI_HOST_INT_CAUSE_REG 0x58 /* Host interrupt cause reg */ +#define IF_SPI_HOST_INT_STATUS_REG 0x5C /* Host interrupt status reg */ +#define IF_SPI_HOST_INT_EVENT_MASK_REG 0x60 /* Host interrupt event mask */ +#define IF_SPI_HOST_INT_STATUS_MASK_REG 0x64 /* Host interrupt status mask */ +#define IF_SPI_HOST_INT_RESET_SELECT_REG 0x68 /* Host interrupt reset select */ + +#define IF_SPI_DELAY_READ_REG 0x6C /* Delay read reg */ +#define IF_SPI_SPU_BUS_MODE_REG 0x70 /* SPU BUS mode reg */ + +/***************** IF_SPI_DEVICEID_CTRL_REG *****************/ +#define IF_SPI_DEVICEID_CTRL_REG_TO_CARD_ID(dc) ((dc & 0xffff0000)>>16) +#define IF_SPI_DEVICEID_CTRL_REG_TO_CARD_REV(dc) (dc & 0x000000ff) + +/***************** IF_SPI_HOST_INT_CTRL_REG *****************/ +/** Host Interrupt Control bit : Wake up */ +#define IF_SPI_HICT_WAKE_UP (1<<0) +/** Host Interrupt Control bit : WLAN ready */ +#define IF_SPI_HICT_WLAN_READY (1<<1) +/*#define IF_SPI_HICT_FIFO_FIRST_HALF_EMPTY (1<<2) */ +/*#define IF_SPI_HICT_FIFO_SECOND_HALF_EMPTY (1<<3) */ +/*#define IF_SPI_HICT_IRQSRC_WLAN (1<<4) */ +/** Host Interrupt Control bit : Tx auto download */ +#define IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO (1<<5) +/** Host Interrupt Control bit : Rx auto upload */ +#define IF_SPI_HICT_RX_UPLOAD_OVER_AUTO (1<<6) +/** Host Interrupt Control bit : Command auto download */ +#define IF_SPI_HICT_CMD_DOWNLOAD_OVER_AUTO (1<<7) +/** Host Interrupt Control bit : Command auto upload */ +#define IF_SPI_HICT_CMD_UPLOAD_OVER_AUTO (1<<8) + +/***************** IF_SPI_CARD_INT_CAUSE_REG *****************/ +/** Card Interrupt Case bit : Tx download over */ +#define IF_SPI_CIC_TX_DOWNLOAD_OVER (1<<0) +/** Card Interrupt Case bit : Rx upload over */ +#define IF_SPI_CIC_RX_UPLOAD_OVER (1<<1) +/** Card Interrupt Case bit : Command download over */ +#define IF_SPI_CIC_CMD_DOWNLOAD_OVER (1<<2) +/** Card Interrupt Case bit : Host event */ +#define IF_SPI_CIC_HOST_EVENT (1<<3) +/** Card Interrupt Case bit : Command upload over */ +#define IF_SPI_CIC_CMD_UPLOAD_OVER (1<<4) +/** Card Interrupt Case bit : Power down */ +#define IF_SPI_CIC_POWER_DOWN (1<<5) + +/***************** IF_SPI_CARD_INT_STATUS_REG *****************/ +#define IF_SPI_CIS_TX_DOWNLOAD_OVER (1<<0) +#define IF_SPI_CIS_RX_UPLOAD_OVER (1<<1) +#define IF_SPI_CIS_CMD_DOWNLOAD_OVER (1<<2) +#define IF_SPI_CIS_HOST_EVENT (1<<3) +#define IF_SPI_CIS_CMD_UPLOAD_OVER (1<<4) +#define IF_SPI_CIS_POWER_DOWN (1<<5) + +/***************** IF_SPI_HOST_INT_CAUSE_REG *****************/ +#define IF_SPI_HICU_TX_DOWNLOAD_RDY (1<<0) +#define IF_SPI_HICU_RX_UPLOAD_RDY (1<<1) +#define IF_SPI_HICU_CMD_DOWNLOAD_RDY (1<<2) +#define IF_SPI_HICU_CARD_EVENT (1<<3) +#define IF_SPI_HICU_CMD_UPLOAD_RDY (1<<4) +#define IF_SPI_HICU_IO_WR_FIFO_OVERFLOW (1<<5) +#define IF_SPI_HICU_IO_RD_FIFO_UNDERFLOW (1<<6) +#define IF_SPI_HICU_DATA_WR_FIFO_OVERFLOW (1<<7) +#define IF_SPI_HICU_DATA_RD_FIFO_UNDERFLOW (1<<8) +#define IF_SPI_HICU_CMD_WR_FIFO_OVERFLOW (1<<9) +#define IF_SPI_HICU_CMD_RD_FIFO_UNDERFLOW (1<<10) + +/***************** IF_SPI_HOST_INT_STATUS_REG *****************/ +/** Host Interrupt Status bit : Tx download ready */ +#define IF_SPI_HIST_TX_DOWNLOAD_RDY (1<<0) +/** Host Interrupt Status bit : Rx upload ready */ +#define IF_SPI_HIST_RX_UPLOAD_RDY (1<<1) +/** Host Interrupt Status bit : Command download ready */ +#define IF_SPI_HIST_CMD_DOWNLOAD_RDY (1<<2) +/** Host Interrupt Status bit : Card event */ +#define IF_SPI_HIST_CARD_EVENT (1<<3) +/** Host Interrupt Status bit : Command upload ready */ +#define IF_SPI_HIST_CMD_UPLOAD_RDY (1<<4) +/** Host Interrupt Status bit : I/O write FIFO overflow */ +#define IF_SPI_HIST_IO_WR_FIFO_OVERFLOW (1<<5) +/** Host Interrupt Status bit : I/O read FIFO underflow */ +#define IF_SPI_HIST_IO_RD_FIFO_UNDRFLOW (1<<6) +/** Host Interrupt Status bit : Data write FIFO overflow */ +#define IF_SPI_HIST_DATA_WR_FIFO_OVERFLOW (1<<7) +/** Host Interrupt Status bit : Data read FIFO underflow */ +#define IF_SPI_HIST_DATA_RD_FIFO_UNDERFLOW (1<<8) +/** Host Interrupt Status bit : Command write FIFO overflow */ +#define IF_SPI_HIST_CMD_WR_FIFO_OVERFLOW (1<<9) +/** Host Interrupt Status bit : Command read FIFO underflow */ +#define IF_SPI_HIST_CMD_RD_FIFO_UNDERFLOW (1<<10) + +/***************** IF_SPI_HOST_INT_STATUS_MASK_REG *****************/ +/** Host Interrupt Status Mask bit : Tx download ready */ +#define IF_SPI_HISM_TX_DOWNLOAD_RDY (1<<0) +/** Host Interrupt Status Mask bit : Rx upload ready */ +#define IF_SPI_HISM_RX_UPLOAD_RDY (1<<1) +/** Host Interrupt Status Mask bit : Command download ready */ +#define IF_SPI_HISM_CMD_DOWNLOAD_RDY (1<<2) +/** Host Interrupt Status Mask bit : Card event */ +#define IF_SPI_HISM_CARDEVENT (1<<3) +/** Host Interrupt Status Mask bit : Command upload ready */ +#define IF_SPI_HISM_CMD_UPLOAD_RDY (1<<4) +/** Host Interrupt Status Mask bit : I/O write FIFO overflow */ +#define IF_SPI_HISM_IO_WR_FIFO_OVERFLOW (1<<5) +/** Host Interrupt Status Mask bit : I/O read FIFO underflow */ +#define IF_SPI_HISM_IO_RD_FIFO_UNDERFLOW (1<<6) +/** Host Interrupt Status Mask bit : Data write FIFO overflow */ +#define IF_SPI_HISM_DATA_WR_FIFO_OVERFLOW (1<<7) +/** Host Interrupt Status Mask bit : Data write FIFO underflow */ +#define IF_SPI_HISM_DATA_RD_FIFO_UNDERFLOW (1<<8) +/** Host Interrupt Status Mask bit : Command write FIFO overflow */ +#define IF_SPI_HISM_CMD_WR_FIFO_OVERFLOW (1<<9) +/** Host Interrupt Status Mask bit : Command write FIFO underflow */ +#define IF_SPI_HISM_CMD_RD_FIFO_UNDERFLOW (1<<10) + +/***************** IF_SPI_SPU_BUS_MODE_REG *****************/ +/* SCK edge on which the WLAN module outputs data on MISO */ +#define IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_FALLING 0x8 +#define IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING 0x0 + +/* In a SPU read operation, there is a delay between writing the SPU + * register name and getting back data from the WLAN module. + * This can be specified in terms of nanoseconds or in terms of dummy + * clock cycles which the master must output before receiving a response. */ +#define IF_SPI_BUS_MODE_DELAY_METHOD_DUMMY_CLOCK 0x4 +#define IF_SPI_BUS_MODE_DELAY_METHOD_TIMED 0x0 + +/* Some different modes of SPI operation */ +#define IF_SPI_BUS_MODE_8_BIT_ADDRESS_16_BIT_DATA 0x00 +#define IF_SPI_BUS_MODE_8_BIT_ADDRESS_32_BIT_DATA 0x01 +#define IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA 0x02 +#define IF_SPI_BUS_MODE_16_BIT_ADDRESS_32_BIT_DATA 0x03 + +#endif diff --git a/include/linux/spi/libertas_spi.h b/include/linux/spi/libertas_spi.h new file mode 100644 index 00000000000..ada71b4f378 --- /dev/null +++ b/include/linux/spi/libertas_spi.h @@ -0,0 +1,25 @@ +/* + * board-specific data for the libertas_spi driver. + * + * Copyright 2008 Analog Devices Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ +#ifndef _LIBERTAS_SPI_H_ +#define _LIBERTAS_SPI_H_ +struct libertas_spi_platform_data { + /* There are two ways to read data from the WLAN module's SPI + * interface. Setting 0 or 1 here controls which one is used. + * + * Usually you want to set use_dummy_writes = 1. + * However, if that doesn't work or if you are using a slow SPI clock + * speed, you may want to use 0 here. */ + u16 use_dummy_writes; + + /* GPIO number to use as chip select */ + u16 gpio_cs; +}; +#endif -- GitLab From f4f727a6c84a6ba8f099b84b2a9f0b2ceddc1c8a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 10 Jan 2009 11:46:53 +0200 Subject: [PATCH 0833/4982] mac80211: Mark ieee80211_process_sa_query_req() static This function is only used within rx.c, so mark it static. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/mac80211/rx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 57ce697e325..b648c4550d9 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1667,9 +1667,9 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) return RX_CONTINUE; } -void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata, - struct ieee80211_mgmt *mgmt, - size_t len) +static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, + size_t len) { struct ieee80211_local *local = sdata->local; struct sk_buff *skb; -- GitLab From ebe6c7ba9b63539d3b1daba1a8ef4cc9ed0f6941 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 10 Jan 2009 11:47:33 +0200 Subject: [PATCH 0834/4982] mac80211: Fix radiotap header it_present on big endian CPUs When the IEEE80211_RADIOTAP_RATE flag was moved to be conditional, it was mistakenly left without cpu_to_le32(). Fix that. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/mac80211/rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index b648c4550d9..19ffc8ef1d1 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -158,7 +158,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, */ *pos = 0; } else { - rthdr->it_present |= (1 << IEEE80211_RADIOTAP_RATE); + rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE); *pos = rate->bitrate / 5; } pos++; -- GitLab From 217875a37d4db3354c4c297d07b359abbf52e5e1 Mon Sep 17 00:00:00 2001 From: Andrew Price Date: Sat, 10 Jan 2009 19:38:05 +0000 Subject: [PATCH 0835/4982] rt2400,rt2500: init led_qual for LED_MODE_DEFAULT Add a check for LED_MODE_DEFAULT so that we use the link LED for rt2400 and rt2500 devices. Signed-off-by: Andrew Price Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 2 +- drivers/net/wireless/rt2x00/rt2500pci.c | 2 +- drivers/net/wireless/rt2x00/rt2500usb.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index ae8bfd6b59d..76c6cb518f2 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1395,7 +1395,7 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); rt2400pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); - if (value == LED_MODE_TXRX_ACTIVITY) + if (value == LED_MODE_TXRX_ACTIVITY || value == LED_MODE_DEFAULT) rt2400pci_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_ACTIVITY); #endif /* CONFIG_RT2X00_LIB_LEDS */ diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index bca6798be15..c1203e37a6f 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1552,7 +1552,7 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); rt2500pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); - if (value == LED_MODE_TXRX_ACTIVITY) + if (value == LED_MODE_TXRX_ACTIVITY || value == LED_MODE_DEFAULT) rt2500pci_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_ACTIVITY); #endif /* CONFIG_RT2X00_LIB_LEDS */ diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 27a6971df57..67dd84ce58b 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1603,7 +1603,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); - if (value == LED_MODE_TXRX_ACTIVITY) + if (value == LED_MODE_TXRX_ACTIVITY || value == LED_MODE_DEFAULT) rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_ACTIVITY); #endif /* CONFIG_RT2X00_LIB_LEDS */ -- GitLab From 138ab2e44e99a9544aad60cf137b8ac1f54131c5 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Sat, 10 Jan 2009 17:07:09 +0530 Subject: [PATCH 0836/4982] ath9k: Fix basic connectivity issue This patch temporarily fixes a regression introduced by BT coexistence support. There is an instability in connection when BT coexistence is enabled on some h/w. This interim fix introduces a module parameter for BT coexistence configuration. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/hw.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index e9a3951996e..55ed0830588 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -23,6 +23,10 @@ #include "phy.h" #include "initvals.h" +static int btcoex_enable; +module_param(btcoex_enable, bool, 0); +MODULE_PARM_DESC(btcoex_enable, "Enable Bluetooth coexistence support"); + #define ATH9K_CLOCK_RATE_CCK 22 #define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 #define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 @@ -3358,7 +3362,7 @@ bool ath9k_hw_fill_cap_info(struct ath_hal *ah) pCap->num_antcfg_2ghz = ath9k_hw_get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ); - if (AR_SREV_9280_10_OR_LATER(ah)) { + if (AR_SREV_9280_10_OR_LATER(ah) && btcoex_enable) { pCap->hw_caps |= ATH9K_HW_CAP_BT_COEX; ah->ah_btactive_gpio = 6; ah->ah_wlanactive_gpio = 5; -- GitLab From b6ea03562f04382776ad825624daefe27f5d3f9c Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sat, 10 Jan 2009 14:42:54 -0500 Subject: [PATCH 0837/4982] ath5k: fix bf->skb==NULL panic in ath5k_tasklet_rx Under memory pressure, we may not be able to allocate a new skb for new packets. If the allocation fails, ath5k_tasklet_rx will exit but will leave a buffer in the list with a NULL skb, eventually triggering a BUG_ON. Extract the skb allocation from ath5k_rxbuf_setup() and change the tasklet to allocate the next skb before accepting a packet. Changes-licensed-under: 3-Clause-BSD Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 85 +++++++++++++++++++------------ 1 file changed, 53 insertions(+), 32 deletions(-) diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index fdf7733e76e..d3178731adc 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -1096,6 +1096,42 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix) * Buffers setup * \***************/ +static +struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr) +{ + struct sk_buff *skb; + unsigned int off; + + /* + * Allocate buffer with headroom_needed space for the + * fake physical layer header at the start. + */ + skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1); + + if (!skb) { + ATH5K_ERR(sc, "can't alloc skbuff of size %u\n", + sc->rxbufsize + sc->cachelsz - 1); + return NULL; + } + /* + * Cache-line-align. This is important (for the + * 5210 at least) as not doing so causes bogus data + * in rx'd frames. + */ + off = ((unsigned long)skb->data) % sc->cachelsz; + if (off != 0) + skb_reserve(skb, sc->cachelsz - off); + + *skb_addr = pci_map_single(sc->pdev, + skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE); + if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) { + ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__); + dev_kfree_skb(skb); + return NULL; + } + return skb; +} + static int ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) { @@ -1103,37 +1139,11 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) struct sk_buff *skb = bf->skb; struct ath5k_desc *ds; - if (likely(skb == NULL)) { - unsigned int off; - - /* - * Allocate buffer with headroom_needed space for the - * fake physical layer header at the start. - */ - skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1); - if (unlikely(skb == NULL)) { - ATH5K_ERR(sc, "can't alloc skbuff of size %u\n", - sc->rxbufsize + sc->cachelsz - 1); + if (!skb) { + skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr); + if (!skb) return -ENOMEM; - } - /* - * Cache-line-align. This is important (for the - * 5210 at least) as not doing so causes bogus data - * in rx'd frames. - */ - off = ((unsigned long)skb->data) % sc->cachelsz; - if (off != 0) - skb_reserve(skb, sc->cachelsz - off); - bf->skb = skb; - bf->skbaddr = pci_map_single(sc->pdev, - skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE); - if (unlikely(pci_dma_mapping_error(sc->pdev, bf->skbaddr))) { - ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__); - dev_kfree_skb(skb); - bf->skb = NULL; - return -ENOMEM; - } } /* @@ -1662,7 +1672,8 @@ ath5k_tasklet_rx(unsigned long data) { struct ieee80211_rx_status rxs = {}; struct ath5k_rx_status rs = {}; - struct sk_buff *skb; + struct sk_buff *skb, *next_skb; + dma_addr_t next_skb_addr; struct ath5k_softc *sc = (void *)data; struct ath5k_buf *bf, *bf_last; struct ath5k_desc *ds; @@ -1747,10 +1758,17 @@ ath5k_tasklet_rx(unsigned long data) goto next; } accept: + next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr); + + /* + * If we can't replace bf->skb with a new skb under memory + * pressure, just skip this packet + */ + if (!next_skb) + goto next; + pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, PCI_DMA_FROMDEVICE); - bf->skb = NULL; - skb_put(skb, rs.rs_datalen); /* The MAC header is padded to have 32-bit boundary if the @@ -1823,6 +1841,9 @@ accept: ath5k_check_ibss_tsf(sc, skb, &rxs); __ieee80211_rx(sc->hw, skb, &rxs); + + bf->skb = next_skb; + bf->skbaddr = next_skb_addr; next: list_move_tail(&bf->list, &sc->rxbuf); } while (ath5k_rxbuf_setup(sc, bf) == 0); -- GitLab From 83cf1b6edba6bde87c8cf852b182d44b12ae7f88 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 11 Jan 2009 01:10:33 +0100 Subject: [PATCH 0838/4982] p54: prepare the eeprom parser routines for longbow This patch adds support to upload pre-calculated calibration data to the firmware. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54.h | 13 +- drivers/net/wireless/p54/p54common.c | 188 ++++++++++++++++++++------- drivers/net/wireless/p54/p54common.h | 19 ++- 3 files changed, 169 insertions(+), 51 deletions(-) diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index a06c2a676df..ac11efd19db 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -87,6 +87,14 @@ struct p54_rssi_linear_approximation { s16 longbow_unk2; }; +struct p54_cal_database { + size_t entries; + size_t entry_size; + size_t offset; + size_t len; + u8 data[0]; +}; + #define EEPROM_READBACK_LEN 0x3fc #define ISL38XX_DEV_FIRMWARE_ADDR 0x20000 @@ -115,9 +123,8 @@ struct p54_common { u8 tx_diversity_mask; struct pda_iq_autocal_entry *iq_autocal; unsigned int iq_autocal_len; - struct pda_channel_output_limit *output_limit; - unsigned int output_limit_len; - struct pda_pa_curve_data *curve_data; + struct p54_cal_database *output_limit; + struct p54_cal_database *curve_data; struct p54_rssi_linear_approximation rssical_db[IEEE80211_NUM_BANDS]; unsigned int filter_flags; bool use_short_slot; diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 85aff1685a1..ec0d109c009 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -272,13 +272,19 @@ static int p54_convert_rev0(struct ieee80211_hw *dev, unsigned int i, j; void *source, *target; - priv->curve_data = kmalloc(cd_len, GFP_KERNEL); + priv->curve_data = kmalloc(sizeof(*priv->curve_data) + cd_len, + GFP_KERNEL); if (!priv->curve_data) return -ENOMEM; - memcpy(priv->curve_data, curve_data, sizeof(*curve_data)); + priv->curve_data->entries = curve_data->channels; + priv->curve_data->entry_size = sizeof(__le16) + + sizeof(*dst) * curve_data->points_per_channel; + priv->curve_data->offset = offsetof(struct pda_pa_curve_data, data); + priv->curve_data->len = cd_len; + memcpy(priv->curve_data->data, curve_data, sizeof(*curve_data)); source = curve_data->data; - target = priv->curve_data->data; + target = ((struct pda_pa_curve_data *) priv->curve_data->data)->data; for (i = 0; i < curve_data->channels; i++) { __le16 *freq = source; source += sizeof(__le16); @@ -318,13 +324,19 @@ static int p54_convert_rev1(struct ieee80211_hw *dev, unsigned int i, j; void *source, *target; - priv->curve_data = kmalloc(cd_len, GFP_KERNEL); + priv->curve_data = kzalloc(cd_len + sizeof(*priv->curve_data), + GFP_KERNEL); if (!priv->curve_data) return -ENOMEM; - memcpy(priv->curve_data, curve_data, sizeof(*curve_data)); + priv->curve_data->entries = curve_data->channels; + priv->curve_data->entry_size = sizeof(__le16) + + sizeof(*dst) * curve_data->points_per_channel; + priv->curve_data->offset = offsetof(struct pda_pa_curve_data, data); + priv->curve_data->len = cd_len; + memcpy(priv->curve_data->data, curve_data, sizeof(*curve_data)); source = curve_data->data; - target = priv->curve_data->data; + target = ((struct pda_pa_curve_data *) priv->curve_data->data)->data; for (i = 0; i < curve_data->channels; i++) { __le16 *freq = source; source += sizeof(__le16); @@ -406,6 +418,71 @@ static void p54_parse_default_country(struct ieee80211_hw *dev, } } +static int p54_convert_output_limits(struct ieee80211_hw *dev, + u8 *data, size_t len) +{ + struct p54_common *priv = dev->priv; + + if (len < 2) + return -EINVAL; + + if (data[0] != 0) { + printk(KERN_ERR "%s: unknown output power db revision:%x\n", + wiphy_name(dev->wiphy), data[0]); + return -EINVAL; + } + + if (2 + data[1] * sizeof(struct pda_channel_output_limit) > len) + return -EINVAL; + + priv->output_limit = kmalloc(data[1] * + sizeof(struct pda_channel_output_limit) + + sizeof(*priv->output_limit), GFP_KERNEL); + + if (!priv->output_limit) + return -ENOMEM; + + priv->output_limit->offset = 0; + priv->output_limit->entries = data[1]; + priv->output_limit->entry_size = + sizeof(struct pda_channel_output_limit); + priv->output_limit->len = priv->output_limit->entry_size * + priv->output_limit->entries + + priv->output_limit->offset; + + memcpy(priv->output_limit->data, &data[2], + data[1] * sizeof(struct pda_channel_output_limit)); + + return 0; +} + +static struct p54_cal_database *p54_convert_db(struct pda_custom_wrapper *src, + size_t total_len) +{ + struct p54_cal_database *dst; + size_t payload_len, entries, entry_size, offset; + + payload_len = le16_to_cpu(src->len); + entries = le16_to_cpu(src->entries); + entry_size = le16_to_cpu(src->entry_size); + offset = le16_to_cpu(src->offset); + if (((entries * entry_size + offset) != payload_len) || + (payload_len + sizeof(*src) != total_len)) + return NULL; + + dst = kmalloc(sizeof(*dst) + payload_len, GFP_KERNEL); + if (!dst) + return NULL; + + dst->entries = entries; + dst->entry_size = entry_size; + dst->offset = offset; + dst->len = payload_len; + + memcpy(dst->data, src->data, payload_len); + return dst; +} + static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) { struct p54_common *priv = dev->priv; @@ -431,30 +508,17 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) switch (le16_to_cpu(entry->code)) { case PDR_MAC_ADDRESS: + if (data_len != ETH_ALEN) + break; SET_IEEE80211_PERM_ADDR(dev, entry->data); break; case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS: - if (data_len < 2) { - err = -EINVAL; - goto err; - } - - if (2 + entry->data[1]*sizeof(*priv->output_limit) > data_len) { - err = -EINVAL; - goto err; - } - - priv->output_limit = kmalloc(entry->data[1] * - sizeof(*priv->output_limit), GFP_KERNEL); - - if (!priv->output_limit) { - err = -ENOMEM; + if (priv->output_limit) + break; + err = p54_convert_output_limits(dev, entry->data, + data_len); + if (err) goto err; - } - - memcpy(priv->output_limit, &entry->data[2], - entry->data[1]*sizeof(*priv->output_limit)); - priv->output_limit_len = entry->data[1]; break; case PDR_PRISM_PA_CAL_CURVE_DATA: { struct pda_pa_curve_data *curve_data = @@ -506,6 +570,8 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) } break; case PDR_HARDWARE_PLATFORM_COMPONENT_ID: + if (data_len < 2) + break; priv->version = *(u8 *)(entry->data + 1); break; case PDR_RSSI_LINEAR_APPROXIMATION: @@ -514,6 +580,34 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) p54_parse_rssical(dev, entry->data, data_len, le16_to_cpu(entry->code)); break; + case PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM: { + __le16 *src = (void *) entry->data; + s16 *dst = (void *) &priv->rssical_db; + int i; + + if (data_len != sizeof(priv->rssical_db)) { + err = -EINVAL; + goto err; + } + for (i = 0; i < sizeof(priv->rssical_db) / + sizeof(*src); i++) + *(dst++) = (s16) le16_to_cpu(*(src++)); + } + break; + case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM: { + struct pda_custom_wrapper *pda = (void *) entry->data; + if (priv->output_limit || data_len < sizeof(*pda)) + break; + priv->output_limit = p54_convert_db(pda, data_len); + } + break; + case PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM: { + struct pda_custom_wrapper *pda = (void *) entry->data; + if (priv->curve_data || data_len < sizeof(*pda)) + break; + priv->curve_data = p54_convert_db(pda, data_len); + } + break; case PDR_END: /* make it overrun */ entry_len = len; @@ -1624,8 +1718,8 @@ static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell) struct p54_scan *chan; unsigned int i; void *entry; - __le16 freq = cpu_to_le16(dev->conf.channel->center_freq); int band = dev->conf.channel->band; + __le16 freq = cpu_to_le16(dev->conf.channel->center_freq); skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*chan), P54_CONTROL_TYPE_SCAN, GFP_ATOMIC); @@ -1633,7 +1727,7 @@ static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell) return -ENOMEM; chan = (struct p54_scan *) skb_put(skb, sizeof(*chan)); - memset(chan->padding1, 0, sizeof(chan->padding1)); + memset(chan->scan_params, 0, sizeof(chan->scan_params)); chan->mode = cpu_to_le16(mode); chan->dwell = cpu_to_le16(dwell); @@ -1648,41 +1742,45 @@ static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell) if (i == priv->iq_autocal_len) goto err; - for (i = 0; i < priv->output_limit_len; i++) { - if (priv->output_limit[i].freq != freq) + for (i = 0; i < priv->output_limit->entries; i++) { + struct pda_channel_output_limit *limits; + __le16 *entry_freq = (void *) (priv->output_limit->data + + priv->output_limit->entry_size * i); + + if (*entry_freq != freq) continue; + limits = (void *) entry_freq; chan->val_barker = 0x38; - chan->val_bpsk = chan->dup_bpsk = - priv->output_limit[i].val_bpsk; - chan->val_qpsk = chan->dup_qpsk = - priv->output_limit[i].val_qpsk; - chan->val_16qam = chan->dup_16qam = - priv->output_limit[i].val_16qam; - chan->val_64qam = chan->dup_64qam = - priv->output_limit[i].val_64qam; + chan->val_bpsk = chan->dup_bpsk = limits->val_bpsk; + chan->val_qpsk = chan->dup_qpsk = limits->val_qpsk; + chan->val_16qam = chan->dup_16qam = limits->val_16qam; + chan->val_64qam = chan->dup_64qam = limits->val_64qam; break; } - if (i == priv->output_limit_len) + if (i == priv->output_limit->entries) goto err; - entry = priv->curve_data->data; - for (i = 0; i < priv->curve_data->channels; i++) { + entry = (void *)(priv->curve_data->data + priv->curve_data->offset); + for (i = 0; i < priv->curve_data->entries; i++) { + struct pda_pa_curve_data *curve_data; if (*((__le16 *)entry) != freq) { - entry += sizeof(__le16); - entry += sizeof(struct p54_pa_curve_data_sample) * - priv->curve_data->points_per_channel; + entry += priv->curve_data->entry_size; continue; } entry += sizeof(__le16); chan->pa_points_per_curve = 8; memset(chan->curve_data, 0, sizeof(*chan->curve_data)); + curve_data = (void *) priv->curve_data->data; + memcpy(chan->curve_data, entry, sizeof(struct p54_pa_curve_data_sample) * - min((u8)8, priv->curve_data->points_per_channel)); + min_t(u8, 8, curve_data->points_per_channel)); break; } + if (i == priv->curve_data->entries) + goto err; if (priv->fw_var < 0x500) { chan->v1_rssi.mul = cpu_to_le16(priv->rssical_db[band].mul); diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h index bcfb75a4d6b..d9aa255b471 100644 --- a/drivers/net/wireless/p54/p54common.h +++ b/drivers/net/wireless/p54/p54common.h @@ -186,6 +186,14 @@ struct pda_country { u8 flags; } __attribute__ ((packed)); +struct pda_custom_wrapper { + __le16 entries; + __le16 entry_size; + __le16 offset; + __le16 len; + u8 data[0]; +} __attribute__ ((packed)); + /* * this defines the PDR codes used to build PDAs as defined in document * number 553155. The current implementation mirrors version 1.1 of the @@ -231,8 +239,13 @@ struct pda_country { /* reserved range (0x2000 - 0x7fff) */ /* customer range (0x8000 - 0xffff) */ -#define PDR_BASEBAND_REGISTERS 0x8000 -#define PDR_PER_CHANNEL_BASEBAND_REGISTERS 0x8001 +#define PDR_BASEBAND_REGISTERS 0x8000 +#define PDR_PER_CHANNEL_BASEBAND_REGISTERS 0x8001 + +/* used by our modificated eeprom image */ +#define PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM 0xDEAD +#define PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM 0xBEEF +#define PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM 0xB05D /* PDR definitions for default country & country list */ #define PDR_COUNTRY_CERT_CODE 0x80 @@ -434,7 +447,7 @@ struct p54_setup_mac { struct p54_scan { __le16 mode; __le16 dwell; - u8 padding1[20]; + u8 scan_params[20]; struct pda_iq_autocal_entry iq_autocal; u8 pa_points_per_curve; u8 val_barker; -- GitLab From 6917f506a03b6bd7389683e8a8e08a1ad977b33e Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 11 Jan 2009 01:14:18 +0100 Subject: [PATCH 0839/4982] p54: longbow frontend support This patch adds support for longbow RF chip. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 141 ++++++++++++++++++++------- drivers/net/wireless/p54/p54common.h | 72 +++++++++++--- 2 files changed, 160 insertions(+), 53 deletions(-) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index ec0d109c009..9fc0c9efe70 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -651,7 +651,7 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) } priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK; - if (priv->rxhw == 4) + if (priv->rxhw == PDR_SYNTH_FRONTEND_XBOW) p54_init_xbow_synth(dev); if (!(synth & PDR_SYNTH_24_GHZ_DISABLED)) dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz; @@ -704,7 +704,14 @@ static int p54_rssi_to_dbm(struct ieee80211_hw *dev, int rssi) struct p54_common *priv = dev->priv; int band = dev->conf.channel->band; - return ((rssi * priv->rssical_db[band].mul) / 64 + + if (priv->rxhw != PDR_SYNTH_FRONTEND_LONGBOW) + return ((rssi * priv->rssical_db[band].mul) / 64 + + priv->rssical_db[band].add) / 4; + else + /* + * TODO: find the correct formula + */ + return ((rssi * priv->rssical_db[band].mul) / 64 + priv->rssical_db[band].add) / 4; } @@ -1612,8 +1619,13 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) memset(txhdr->durations, 0, sizeof(txhdr->durations)); txhdr->tx_antenna = ((info->antenna_sel_tx == 0) ? 2 : info->antenna_sel_tx - 1) & priv->tx_diversity_mask; - txhdr->output_power = priv->output_power; - txhdr->cts_rate = cts_rate; + if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) { + txhdr->longbow.cts_rate = cts_rate; + txhdr->longbow.output_power = cpu_to_le16(priv->output_power); + } else { + txhdr->normal.output_power = priv->output_power; + txhdr->normal.cts_rate = cts_rate; + } if (padding) txhdr->align[0] = padding; @@ -1715,47 +1727,77 @@ static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell) { struct p54_common *priv = dev->priv; struct sk_buff *skb; - struct p54_scan *chan; + struct p54_hdr *hdr; + struct p54_scan_head *head; + struct p54_iq_autocal_entry *iq_autocal; + union p54_scan_body_union *body; + struct p54_scan_tail_rate *rate; + struct pda_rssi_cal_entry *rssi; unsigned int i; void *entry; int band = dev->conf.channel->band; __le16 freq = cpu_to_le16(dev->conf.channel->center_freq); - skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*chan), + skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*head) + + 2 + sizeof(*iq_autocal) + sizeof(*body) + + sizeof(*rate) + 2 * sizeof(*rssi), P54_CONTROL_TYPE_SCAN, GFP_ATOMIC); if (!skb) return -ENOMEM; - chan = (struct p54_scan *) skb_put(skb, sizeof(*chan)); - memset(chan->scan_params, 0, sizeof(chan->scan_params)); - chan->mode = cpu_to_le16(mode); - chan->dwell = cpu_to_le16(dwell); + head = (struct p54_scan_head *) skb_put(skb, sizeof(*head)); + memset(head->scan_params, 0, sizeof(head->scan_params)); + head->mode = cpu_to_le16(mode); + head->dwell = cpu_to_le16(dwell); + head->freq = freq; + if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) { + __le16 *pa_power_points = (__le16 *) skb_put(skb, 2); + *pa_power_points = cpu_to_le16(0x0c); + } + + iq_autocal = (void *) skb_put(skb, sizeof(*iq_autocal)); for (i = 0; i < priv->iq_autocal_len; i++) { if (priv->iq_autocal[i].freq != freq) continue; - memcpy(&chan->iq_autocal, &priv->iq_autocal[i], - sizeof(*priv->iq_autocal)); + memcpy(iq_autocal, &priv->iq_autocal[i].params, + sizeof(struct p54_iq_autocal_entry)); break; } if (i == priv->iq_autocal_len) goto err; + if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) + body = (void *) skb_put(skb, sizeof(body->longbow)); + else + body = (void *) skb_put(skb, sizeof(body->normal)); + for (i = 0; i < priv->output_limit->entries; i++) { - struct pda_channel_output_limit *limits; __le16 *entry_freq = (void *) (priv->output_limit->data + - priv->output_limit->entry_size * i); + priv->output_limit->entry_size * i); if (*entry_freq != freq) continue; - limits = (void *) entry_freq; - chan->val_barker = 0x38; - chan->val_bpsk = chan->dup_bpsk = limits->val_bpsk; - chan->val_qpsk = chan->dup_qpsk = limits->val_qpsk; - chan->val_16qam = chan->dup_16qam = limits->val_16qam; - chan->val_64qam = chan->dup_64qam = limits->val_64qam; + if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) { + memcpy(&body->longbow.power_limits, + (void *) entry_freq + sizeof(__le16), + priv->output_limit->entry_size); + } else { + struct pda_channel_output_limit *limits = + (void *) entry_freq; + + body->normal.val_barker = 0x38; + body->normal.val_bpsk = body->normal.dup_bpsk = + limits->val_bpsk; + body->normal.val_qpsk = body->normal.dup_qpsk = + limits->val_qpsk; + body->normal.val_16qam = body->normal.dup_16qam = + limits->val_16qam; + body->normal.val_64qam = body->normal.dup_64qam = + limits->val_64qam; + } break; } if (i == priv->output_limit->entries) @@ -1763,34 +1805,59 @@ static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell) entry = (void *)(priv->curve_data->data + priv->curve_data->offset); for (i = 0; i < priv->curve_data->entries; i++) { - struct pda_pa_curve_data *curve_data; if (*((__le16 *)entry) != freq) { entry += priv->curve_data->entry_size; continue; } - entry += sizeof(__le16); - chan->pa_points_per_curve = 8; - memset(chan->curve_data, 0, sizeof(*chan->curve_data)); - curve_data = (void *) priv->curve_data->data; - - memcpy(chan->curve_data, entry, - sizeof(struct p54_pa_curve_data_sample) * - min_t(u8, 8, curve_data->points_per_channel)); + if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) { + memcpy(&body->longbow.curve_data, + (void *) entry + sizeof(__le16), + priv->curve_data->entry_size); + } else { + struct p54_scan_body *chan = &body->normal; + struct pda_pa_curve_data *curve_data = + (void *) priv->curve_data->data; + + entry += sizeof(__le16); + chan->pa_points_per_curve = 8; + memset(chan->curve_data, 0, sizeof(*chan->curve_data)); + memcpy(chan->curve_data, entry, + sizeof(struct p54_pa_curve_data_sample) * + min((u8)8, curve_data->points_per_channel)); + } break; } if (i == priv->curve_data->entries) goto err; - if (priv->fw_var < 0x500) { - chan->v1_rssi.mul = cpu_to_le16(priv->rssical_db[band].mul); - chan->v1_rssi.add = cpu_to_le16(priv->rssical_db[band].add); - } else { - chan->v2.rssi.mul = cpu_to_le16(priv->rssical_db[band].mul); - chan->v2.rssi.add = cpu_to_le16(priv->rssical_db[band].add); - chan->v2.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); - memset(chan->v2.rts_rates, 0, 8); + if ((priv->fw_var >= 0x500) && (priv->fw_var < 0x509)) { + rate = (void *) skb_put(skb, sizeof(*rate)); + rate->basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); + for (i = 0; i < sizeof(rate->rts_rates); i++) + rate->rts_rates[i] = i; } + + rssi = (struct pda_rssi_cal_entry *) skb_put(skb, sizeof(*rssi)); + rssi->mul = cpu_to_le16(priv->rssical_db[band].mul); + rssi->add = cpu_to_le16(priv->rssical_db[band].add); + if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) { + /* Longbow frontend needs ever more */ + rssi = (void *) skb_put(skb, sizeof(*rssi)); + rssi->mul = cpu_to_le16(priv->rssical_db[band].longbow_unkn); + rssi->add = cpu_to_le16(priv->rssical_db[band].longbow_unk2); + } + + if (priv->fw_var >= 0x509) { + rate = (void *) skb_put(skb, sizeof(*rate)); + rate->basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); + for (i = 0; i < sizeof(rate->rts_rates); i++) + rate->rts_rates[i] = i; + } + + hdr = (struct p54_hdr *) skb->data; + hdr->len = cpu_to_le16(skb->len - sizeof(*hdr)); + priv->tx(dev, skb); return 0; diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h index d9aa255b471..def23b1f49e 100644 --- a/drivers/net/wireless/p54/p54common.h +++ b/drivers/net/wireless/p54/p54common.h @@ -26,6 +26,11 @@ struct bootrec { } __attribute__((packed)); #define PDR_SYNTH_FRONTEND_MASK 0x0007 +#define PDR_SYNTH_FRONTEND_DUETTE3 0x0001 +#define PDR_SYNTH_FRONTEND_DUETTE2 0x0002 +#define PDR_SYNTH_FRONTEND_FRISBEE 0x0003 +#define PDR_SYNTH_FRONTEND_XBOW 0x0004 +#define PDR_SYNTH_FRONTEND_LONGBOW 0x0005 #define PDR_SYNTH_IQ_CAL_MASK 0x0018 #define PDR_SYNTH_IQ_CAL_PA_DETECTOR 0x0000 #define PDR_SYNTH_IQ_CAL_DISABLED 0x0008 @@ -125,9 +130,13 @@ struct eeprom_pda_wrap { u8 data[0]; } __attribute__ ((packed)); +struct p54_iq_autocal_entry { + __le16 iq_param[4]; +} __attribute__ ((packed)); + struct pda_iq_autocal_entry { __le16 freq; - __le16 iq_param[4]; + struct p54_iq_autocal_entry params; } __attribute__ ((packed)); struct pda_channel_output_limit { @@ -186,6 +195,21 @@ struct pda_country { u8 flags; } __attribute__ ((packed)); +/* + * Warning: Longbow's structures are bogus. + */ +struct p54_channel_output_limit_longbow { + __le16 rf_power_points[12]; +} __attribute__ ((packed)); + +struct p54_pa_curve_data_sample_longbow { + __le16 rf_power; + __le16 pa_detector; + struct { + __le16 data[4]; + } points[3] __attribute__ ((packed)); +} __attribute__ ((packed)); + struct pda_custom_wrapper { __le16 entries; __le16 entry_size; @@ -381,9 +405,18 @@ struct p54_tx_data { u8 backlog; __le16 durations[4]; u8 tx_antenna; - u8 output_power; - u8 cts_rate; - u8 unalloc2[3]; + union { + struct { + u8 cts_rate; + __le16 output_power; + } __attribute__((packed)) longbow; + struct { + u8 output_power; + u8 cts_rate; + u8 unalloc; + } __attribute__ ((packed)) normal; + } __attribute__ ((packed)); + u8 unalloc2[2]; u8 align[0]; } __attribute__ ((packed)); @@ -444,11 +477,14 @@ struct p54_setup_mac { #define P54_SCAN_ACTIVE BIT(2) #define P54_SCAN_FILTER BIT(3) -struct p54_scan { +struct p54_scan_head { __le16 mode; __le16 dwell; u8 scan_params[20]; - struct pda_iq_autocal_entry iq_autocal; + __le16 freq; +} __attribute__ ((packed)); + +struct p54_scan_body { u8 pa_points_per_curve; u8 val_barker; u8 val_bpsk; @@ -460,19 +496,23 @@ struct p54_scan { u8 dup_qpsk; u8 dup_16qam; u8 dup_64qam; - union { - struct pda_rssi_cal_entry v1_rssi; +} __attribute__ ((packed)); - struct { - __le32 basic_rate_mask; - u8 rts_rates[8]; - struct pda_rssi_cal_entry rssi; - } v2 __attribute__ ((packed)); - } __attribute__ ((packed)); +struct p54_scan_body_longbow { + struct p54_channel_output_limit_longbow power_limits; + struct p54_pa_curve_data_sample_longbow curve_data[8]; + __le16 unkn[6]; /* maybe more power_limits or rate_mask */ } __attribute__ ((packed)); -#define P54_SCAN_V1_LEN 0x70 -#define P54_SCAN_V2_LEN 0x7c +union p54_scan_body_union { + struct p54_scan_body normal; + struct p54_scan_body_longbow longbow; +} __attribute__ ((packed)); + +struct p54_scan_tail_rate { + __le32 basic_rate_mask; + u8 rts_rates[8]; +} __attribute__ ((packed)); struct p54_led { __le16 mode; -- GitLab From 4628ae75583311fcbbd02f4eebcfc08514dfbd65 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 11 Jan 2009 01:16:09 +0100 Subject: [PATCH 0840/4982] p54spi: stlc45xx eeprom blob Usually every prism54 design hardware has a tiny eeprom chip in which all device specific data for calibration and link-tuning is stored. The stlc45xx chips are the only exception. They are made for embedded devices, where space is scarce. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54spi_eeprom.h | 678 +++++++++++++++++++++++ 1 file changed, 678 insertions(+) create mode 100644 drivers/net/wireless/p54/p54spi_eeprom.h diff --git a/drivers/net/wireless/p54/p54spi_eeprom.h b/drivers/net/wireless/p54/p54spi_eeprom.h new file mode 100644 index 00000000000..1ea1050911d --- /dev/null +++ b/drivers/net/wireless/p54/p54spi_eeprom.h @@ -0,0 +1,678 @@ +/* + * Copyright (C) 2003 Conexant Americas Inc. All Rights Reserved. + * Copyright (C) 2004, 2005, 2006 Nokia Corporation + * Copyright 2008 Johannes Berg + * Copyright 2008 Christian Lamparter + * + * based on: + * - cx3110x's pda.h from Nokia + * - cx3110-transfer.log by Johannes Berg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef P54SPI_EEPROM_H +#define P54SPI_EEPROM_H + +static unsigned char p54spi_eeprom[] = { + +/* struct eeprom_pda_wrap */ +0x47, 0x4d, 0x55, 0xaa, /* magic */ +0x00, 0x00, /* pad */ +0x00, 0x00, /* eeprom_pda_data_wrap length */ +0x00, 0x00, 0x00, 0x00, /* arm opcode */ + +/* bogus MAC address */ +0x04, 0x00, 0x01, 0x01, /* PDR_MAC_ADDRESS */ + 0x00, 0x02, 0xee, 0xc0, 0xff, 0xee, + +/* struct bootrec_exp_if */ +0x06, 0x00, 0x01, 0x10, /* PDR_INTERFACE_LIST */ + 0x00, 0x00, /* role */ + 0x0f, 0x00, /* if_id */ + 0x85, 0x00, /* variant = Longbow RF, 2GHz */ + 0x01, 0x00, /* btm_compat */ + 0x1f, 0x00, /* top_compat */ + +0x03, 0x00, 0x02, 0x10, /* PDR_HARDWARE_PLATFORM_COMPONENT_ID */ + 0x03, 0x20, 0x00, 0x43, + +/* struct pda_country[6] */ +0x0d, 0x00, 0x07, 0x10, /* PDR_COUNTRY_LIST */ + 0x10, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, + 0x31, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, + +/* struct pda_country */ +0x03, 0x00, 0x08, 0x10, /* PDR_DEFAULT_COUNTRY */ + 0x30, 0x00, 0x00, 0x00, /* ETSI */ + +0x03, 0x00, 0x00, 0x11, /* PDR_ANTENNA_GAIN */ + 0x08, 0x08, 0x08, 0x08, + +0x09, 0x00, 0xad, 0xde, /* PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM */ + 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +/* struct pda_custom_wrapper */ +0x10, 0x06, 0x5d, 0xb0, /* PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM */ + 0x0d, 0x00, 0xee, 0x00, /* 13 entries, 238 bytes per entry */ + 0x00, 0x00, 0x16, 0x0c, /* no offset, 3094 total len */ + /* 2412 MHz */ + 0x6c, 0x09, + 0x10, 0x01, 0x9a, 0x84, + 0xaa, 0x8a, 0xaa, 0x8a, 0xaa, 0x8a, 0xaa, 0x8a, + 0x3c, 0xb6, 0x3c, 0xb6, 0x3c, 0xb6, 0x3c, 0xb6, + 0x3c, 0xb6, 0x3c, 0xb6, 0x3c, 0xb6, 0x3c, 0xb6, + 0xf0, 0x00, 0x94, 0x6c, + 0x99, 0x82, 0x99, 0x82, 0x99, 0x82, 0x99, 0x82, + 0x2b, 0xae, 0x2b, 0xae, 0x2b, 0xae, 0x2b, 0xae, + 0x2b, 0xae, 0x2b, 0xae, 0x2b, 0xae, 0x2b, 0xae, + 0xd0, 0x00, 0xaa, 0x5a, + 0x88, 0x7a, 0x88, 0x7a, 0x88, 0x7a, 0x88, 0x7a, + 0x1a, 0xa6, 0x1a, 0xa6, 0x1a, 0xa6, 0x1a, 0xa6, + 0x1a, 0xa6, 0x1a, 0xa6, 0x1a, 0xa6, 0x1a, 0xa6, + 0xa0, 0x00, 0xf3, 0x47, + 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, + 0x00, 0x9a, 0x00, 0x9a, 0x00, 0x9a, 0x00, 0x9a, + 0x00, 0x9a, 0x00, 0x9a, 0x00, 0x9a, 0x00, 0x9a, + 0x50, 0x00, 0x59, 0x36, + 0x43, 0x5a, 0x43, 0x5a, 0x43, 0x5a, 0x43, 0x5a, + 0xd5, 0x85, 0xd5, 0x85, 0xd5, 0x85, 0xd5, 0x85, + 0xd5, 0x85, 0xd5, 0x85, 0xd5, 0x85, 0xd5, 0x85, + 0x00, 0x00, 0xe4, 0x2d, + 0x18, 0x46, 0x18, 0x46, 0x18, 0x46, 0x18, 0x46, + 0xaa, 0x71, 0xaa, 0x71, 0xaa, 0x71, 0xaa, 0x71, + 0xaa, 0x71, 0xaa, 0x71, 0xaa, 0x71, 0xaa, 0x71, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, + + /* 2417 MHz */ + 0x71, 0x09, + 0x10, 0x01, 0xb9, 0x83, + 0x7d, 0x8a, 0x7d, 0x8a, 0x7d, 0x8a, 0x7d, 0x8a, + 0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6, + 0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6, + 0xf0, 0x00, 0x2e, 0x6c, + 0x68, 0x82, 0x68, 0x82, 0x68, 0x82, 0x68, 0x82, + 0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad, + 0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad, + 0xd0, 0x00, 0x8d, 0x5a, + 0x52, 0x7a, 0x52, 0x7a, 0x52, 0x7a, 0x52, 0x7a, + 0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5, + 0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5, + 0xa0, 0x00, 0x0a, 0x48, + 0x32, 0x6e, 0x32, 0x6e, 0x32, 0x6e, 0x32, 0x6e, + 0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99, + 0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99, + 0x50, 0x00, 0x7c, 0x36, + 0xfc, 0x59, 0xfc, 0x59, 0xfc, 0x59, 0xfc, 0x59, + 0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85, + 0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85, + 0x00, 0x00, 0xf5, 0x2d, + 0xc6, 0x45, 0xc6, 0x45, 0xc6, 0x45, 0xc6, 0x45, + 0x58, 0x71, 0x58, 0x71, 0x58, 0x71, 0x58, 0x71, + 0x58, 0x71, 0x58, 0x71, 0x58, 0x71, 0x58, 0x71, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, + + /* 2422 MHz */ + 0x76, 0x09, + 0x10, 0x01, 0xb9, 0x83, + 0x7d, 0x8a, 0x7d, 0x8a, 0x7d, 0x8a, 0x7d, 0x8a, + 0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6, + 0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6, + 0xf0, 0x00, 0x2e, 0x6c, + 0x68, 0x82, 0x68, 0x82, 0x68, 0x82, 0x68, 0x82, + 0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad, + 0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad, + 0xd0, 0x00, 0x8d, 0x5a, + 0x52, 0x7a, 0x52, 0x7a, 0x52, 0x7a, 0x52, 0x7a, + 0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5, + 0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5, + 0xa0, 0x00, 0x0a, 0x48, + 0x32, 0x6e, 0x32, 0x6e, 0x32, 0x6e, 0x32, 0x6e, + 0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99, + 0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99, + 0x50, 0x00, 0x7c, 0x36, + 0xfc, 0x59, 0xfc, 0x59, 0xfc, 0x59, 0xfc, 0x59, + 0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85, + 0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85, + 0x00, 0x00, 0xf5, 0x2d, + 0xc6, 0x45, 0xc6, 0x45, 0xc6, 0x45, 0xc6, 0x45, + 0x58, 0x71, 0x58, 0x71, 0x58, 0x71, 0x58, 0x71, + 0x58, 0x71, 0x58, 0x71, 0x58, 0x71, 0x58, 0x71, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, + + /* 2427 MHz */ + 0x7b, 0x09, + 0x10, 0x01, 0x48, 0x83, + 0x67, 0x8a, 0x67, 0x8a, 0x67, 0x8a, 0x67, 0x8a, + 0xf9, 0xb5, 0xf9, 0xb5, 0xf9, 0xb5, 0xf9, 0xb5, + 0xf9, 0xb5, 0xf9, 0xb5, 0xf9, 0xb5, 0xf9, 0xb5, + 0xf0, 0x00, 0xfb, 0x6b, + 0x50, 0x82, 0x50, 0x82, 0x50, 0x82, 0x50, 0x82, + 0xe2, 0xad, 0xe2, 0xad, 0xe2, 0xad, 0xe2, 0xad, + 0xe2, 0xad, 0xe2, 0xad, 0xe2, 0xad, 0xe2, 0xad, + 0xd0, 0x00, 0x7e, 0x5a, + 0x38, 0x7a, 0x38, 0x7a, 0x38, 0x7a, 0x38, 0x7a, + 0xca, 0xa5, 0xca, 0xa5, 0xca, 0xa5, 0xca, 0xa5, + 0xca, 0xa5, 0xca, 0xa5, 0xca, 0xa5, 0xca, 0xa5, + 0xa0, 0x00, 0x15, 0x48, + 0x14, 0x6e, 0x14, 0x6e, 0x14, 0x6e, 0x14, 0x6e, + 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, + 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, + 0x50, 0x00, 0x8e, 0x36, + 0xd9, 0x59, 0xd9, 0x59, 0xd9, 0x59, 0xd9, 0x59, + 0x6b, 0x85, 0x6b, 0x85, 0x6b, 0x85, 0x6b, 0x85, + 0x6b, 0x85, 0x6b, 0x85, 0x6b, 0x85, 0x6b, 0x85, + 0x00, 0x00, 0xfe, 0x2d, + 0x9d, 0x45, 0x9d, 0x45, 0x9d, 0x45, 0x9d, 0x45, + 0x2f, 0x71, 0x2f, 0x71, 0x2f, 0x71, 0x2f, 0x71, + 0x2f, 0x71, 0x2f, 0x71, 0x2f, 0x71, 0x2f, 0x71, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, + + /* 2432 MHz */ + 0x80, 0x09, + 0x10, 0x01, 0xd7, 0x82, + 0x51, 0x8a, 0x51, 0x8a, 0x51, 0x8a, 0x51, 0x8a, + 0xe3, 0xb5, 0xe3, 0xb5, 0xe3, 0xb5, 0xe3, 0xb5, + 0xe3, 0xb5, 0xe3, 0xb5, 0xe3, 0xb5, 0xe3, 0xb5, + 0xf0, 0x00, 0xc8, 0x6b, + 0x37, 0x82, 0x37, 0x82, 0x37, 0x82, 0x37, 0x82, + 0xc9, 0xad, 0xc9, 0xad, 0xc9, 0xad, 0xc9, 0xad, + 0xc9, 0xad, 0xc9, 0xad, 0xc9, 0xad, 0xc9, 0xad, + 0xd0, 0x00, 0x6f, 0x5a, + 0x1d, 0x7a, 0x1d, 0x7a, 0x1d, 0x7a, 0x1d, 0x7a, + 0xaf, 0xa5, 0xaf, 0xa5, 0xaf, 0xa5, 0xaf, 0xa5, + 0xaf, 0xa5, 0xaf, 0xa5, 0xaf, 0xa5, 0xaf, 0xa5, + 0xa0, 0x00, 0x20, 0x48, + 0xf6, 0x6d, 0xf6, 0x6d, 0xf6, 0x6d, 0xf6, 0x6d, + 0x88, 0x99, 0x88, 0x99, 0x88, 0x99, 0x88, 0x99, + 0x88, 0x99, 0x88, 0x99, 0x88, 0x99, 0x88, 0x99, + 0x50, 0x00, 0x9f, 0x36, + 0xb5, 0x59, 0xb5, 0x59, 0xb5, 0x59, 0xb5, 0x59, + 0x47, 0x85, 0x47, 0x85, 0x47, 0x85, 0x47, 0x85, + 0x47, 0x85, 0x47, 0x85, 0x47, 0x85, 0x47, 0x85, + 0x00, 0x00, 0x06, 0x2e, + 0x74, 0x45, 0x74, 0x45, 0x74, 0x45, 0x74, 0x45, + 0x06, 0x71, 0x06, 0x71, 0x06, 0x71, 0x06, 0x71, + 0x06, 0x71, 0x06, 0x71, 0x06, 0x71, 0x06, 0x71, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, + + /* 2437 MHz */ + 0x85, 0x09, + 0x10, 0x01, 0x67, 0x82, + 0x3a, 0x8a, 0x3a, 0x8a, 0x3a, 0x8a, 0x3a, 0x8a, + 0xcc, 0xb5, 0xcc, 0xb5, 0xcc, 0xb5, 0xcc, 0xb5, + 0xcc, 0xb5, 0xcc, 0xb5, 0xcc, 0xb5, 0xcc, 0xb5, + 0xf0, 0x00, 0x95, 0x6b, + 0x1f, 0x82, 0x1f, 0x82, 0x1f, 0x82, 0x1f, 0x82, + 0xb1, 0xad, 0xb1, 0xad, 0xb1, 0xad, 0xb1, 0xad, + 0xb1, 0xad, 0xb1, 0xad, 0xb1, 0xad, 0xb1, 0xad, + 0xd0, 0x00, 0x61, 0x5a, + 0x02, 0x7a, 0x02, 0x7a, 0x02, 0x7a, 0x02, 0x7a, + 0x94, 0xa5, 0x94, 0xa5, 0x94, 0xa5, 0x94, 0xa5, + 0x94, 0xa5, 0x94, 0xa5, 0x94, 0xa5, 0x94, 0xa5, + 0xa0, 0x00, 0x2c, 0x48, + 0xd8, 0x6d, 0xd8, 0x6d, 0xd8, 0x6d, 0xd8, 0x6d, + 0x6a, 0x99, 0x6a, 0x99, 0x6a, 0x99, 0x6a, 0x99, + 0x6a, 0x99, 0x6a, 0x99, 0x6a, 0x99, 0x6a, 0x99, + 0x50, 0x00, 0xb1, 0x36, + 0x92, 0x59, 0x92, 0x59, 0x92, 0x59, 0x92, 0x59, + 0x24, 0x85, 0x24, 0x85, 0x24, 0x85, 0x24, 0x85, + 0x24, 0x85, 0x24, 0x85, 0x24, 0x85, 0x24, 0x85, + 0x00, 0x00, 0x0f, 0x2e, + 0x4b, 0x45, 0x4b, 0x45, 0x4b, 0x45, 0x4b, 0x45, + 0xdd, 0x70, 0xdd, 0x70, 0xdd, 0x70, 0xdd, 0x70, + 0xdd, 0x70, 0xdd, 0x70, 0xdd, 0x70, 0xdd, 0x70, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, + + /* 2442 MHz */ + 0x8a, 0x09, + 0x10, 0x01, 0xf6, 0x81, + 0x24, 0x8a, 0x24, 0x8a, 0x24, 0x8a, 0x24, 0x8a, + 0xb6, 0xb5, 0xb6, 0xb5, 0xb6, 0xb5, 0xb6, 0xb5, + 0xb6, 0xb5, 0xb6, 0xb5, 0xb6, 0xb5, 0xb6, 0xb5, + 0xf0, 0x00, 0x62, 0x6b, + 0x06, 0x82, 0x06, 0x82, 0x06, 0x82, 0x06, 0x82, + 0x98, 0xad, 0x98, 0xad, 0x98, 0xad, 0x98, 0xad, + 0x98, 0xad, 0x98, 0xad, 0x98, 0xad, 0x98, 0xad, + 0xd0, 0x00, 0x52, 0x5a, + 0xe7, 0x79, 0xe7, 0x79, 0xe7, 0x79, 0xe7, 0x79, + 0x79, 0xa5, 0x79, 0xa5, 0x79, 0xa5, 0x79, 0xa5, + 0x79, 0xa5, 0x79, 0xa5, 0x79, 0xa5, 0x79, 0xa5, + 0xa0, 0x00, 0x37, 0x48, + 0xba, 0x6d, 0xba, 0x6d, 0xba, 0x6d, 0xba, 0x6d, + 0x4c, 0x99, 0x4c, 0x99, 0x4c, 0x99, 0x4c, 0x99, + 0x4c, 0x99, 0x4c, 0x99, 0x4c, 0x99, 0x4c, 0x99, + 0x50, 0x00, 0xc2, 0x36, + 0x6e, 0x59, 0x6e, 0x59, 0x6e, 0x59, 0x6e, 0x59, + 0x00, 0x85, 0x00, 0x85, 0x00, 0x85, 0x00, 0x85, + 0x00, 0x85, 0x00, 0x85, 0x00, 0x85, 0x00, 0x85, + 0x00, 0x00, 0x17, 0x2e, + 0x22, 0x45, 0x22, 0x45, 0x22, 0x45, 0x22, 0x45, + 0xb4, 0x70, 0xb4, 0x70, 0xb4, 0x70, 0xb4, 0x70, + 0xb4, 0x70, 0xb4, 0x70, 0xb4, 0x70, 0xb4, 0x70, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, + + /* 2447 MHz */ + 0x8f, 0x09, + 0x10, 0x01, 0x75, 0x83, + 0x61, 0x8a, 0x61, 0x8a, 0x61, 0x8a, 0x61, 0x8a, + 0xf3, 0xb5, 0xf3, 0xb5, 0xf3, 0xb5, 0xf3, 0xb5, + 0xf3, 0xb5, 0xf3, 0xb5, 0xf3, 0xb5, 0xf3, 0xb5, + 0xf0, 0x00, 0x4b, 0x6c, + 0x3f, 0x82, 0x3f, 0x82, 0x3f, 0x82, 0x3f, 0x82, + 0xd1, 0xad, 0xd1, 0xad, 0xd1, 0xad, 0xd1, 0xad, + 0xd1, 0xad, 0xd1, 0xad, 0xd1, 0xad, 0xd1, 0xad, + 0xd0, 0x00, 0xda, 0x5a, + 0x1c, 0x7a, 0x1c, 0x7a, 0x1c, 0x7a, 0x1c, 0x7a, + 0xae, 0xa5, 0xae, 0xa5, 0xae, 0xa5, 0xae, 0xa5, + 0xae, 0xa5, 0xae, 0xa5, 0xae, 0xa5, 0xae, 0xa5, + 0xa0, 0x00, 0x6d, 0x48, + 0xe9, 0x6d, 0xe9, 0x6d, 0xe9, 0x6d, 0xe9, 0x6d, + 0x7b, 0x99, 0x7b, 0x99, 0x7b, 0x99, 0x7b, 0x99, + 0x7b, 0x99, 0x7b, 0x99, 0x7b, 0x99, 0x7b, 0x99, + 0x50, 0x00, 0xc6, 0x36, + 0x92, 0x59, 0x92, 0x59, 0x92, 0x59, 0x92, 0x59, + 0x24, 0x85, 0x24, 0x85, 0x24, 0x85, 0x24, 0x85, + 0x24, 0x85, 0x24, 0x85, 0x24, 0x85, 0x24, 0x85, + 0x00, 0x00, 0x15, 0x2e, + 0x3c, 0x45, 0x3c, 0x45, 0x3c, 0x45, 0x3c, 0x45, + 0xce, 0x70, 0xce, 0x70, 0xce, 0x70, 0xce, 0x70, + 0xce, 0x70, 0xce, 0x70, 0xce, 0x70, 0xce, 0x70, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, + + /* 2452 MHz */ + 0x94, 0x09, + 0x10, 0x01, 0xf4, 0x84, + 0x9e, 0x8a, 0x9e, 0x8a, 0x9e, 0x8a, 0x9e, 0x8a, + 0x30, 0xb6, 0x30, 0xb6, 0x30, 0xb6, 0x30, 0xb6, + 0x30, 0xb6, 0x30, 0xb6, 0x30, 0xb6, 0x30, 0xb6, + 0xf0, 0x00, 0x34, 0x6d, + 0x77, 0x82, 0x77, 0x82, 0x77, 0x82, 0x77, 0x82, + 0x09, 0xae, 0x09, 0xae, 0x09, 0xae, 0x09, 0xae, + 0x09, 0xae, 0x09, 0xae, 0x09, 0xae, 0x09, 0xae, + 0xd0, 0x00, 0x62, 0x5b, + 0x50, 0x7a, 0x50, 0x7a, 0x50, 0x7a, 0x50, 0x7a, + 0xe2, 0xa5, 0xe2, 0xa5, 0xe2, 0xa5, 0xe2, 0xa5, + 0xe2, 0xa5, 0xe2, 0xa5, 0xe2, 0xa5, 0xe2, 0xa5, + 0xa0, 0x00, 0xa2, 0x48, + 0x17, 0x6e, 0x17, 0x6e, 0x17, 0x6e, 0x17, 0x6e, + 0xa9, 0x99, 0xa9, 0x99, 0xa9, 0x99, 0xa9, 0x99, + 0xa9, 0x99, 0xa9, 0x99, 0xa9, 0x99, 0xa9, 0x99, + 0x50, 0x00, 0xc9, 0x36, + 0xb7, 0x59, 0xb7, 0x59, 0xb7, 0x59, 0xb7, 0x59, + 0x49, 0x85, 0x49, 0x85, 0x49, 0x85, 0x49, 0x85, + 0x49, 0x85, 0x49, 0x85, 0x49, 0x85, 0x49, 0x85, + 0x00, 0x00, 0x12, 0x2e, + 0x57, 0x45, 0x57, 0x45, 0x57, 0x45, 0x57, 0x45, + 0xe9, 0x70, 0xe9, 0x70, 0xe9, 0x70, 0xe9, 0x70, + 0xe9, 0x70, 0xe9, 0x70, 0xe9, 0x70, 0xe9, 0x70, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, + + /* 2452 MHz */ + 0x99, 0x09, + 0x10, 0x01, 0x74, 0x86, + 0xdb, 0x8a, 0xdb, 0x8a, 0xdb, 0x8a, 0xdb, 0x8a, + 0x6d, 0xb6, 0x6d, 0xb6, 0x6d, 0xb6, 0x6d, 0xb6, + 0x6d, 0xb6, 0x6d, 0xb6, 0x6d, 0xb6, 0x6d, 0xb6, + 0xf0, 0x00, 0x1e, 0x6e, + 0xb0, 0x82, 0xb0, 0x82, 0xb0, 0x82, 0xb0, 0x82, + 0x42, 0xae, 0x42, 0xae, 0x42, 0xae, 0x42, 0xae, + 0x42, 0xae, 0x42, 0xae, 0x42, 0xae, 0x42, 0xae, + 0xd0, 0x00, 0xeb, 0x5b, + 0x85, 0x7a, 0x85, 0x7a, 0x85, 0x7a, 0x85, 0x7a, + 0x17, 0xa6, 0x17, 0xa6, 0x17, 0xa6, 0x17, 0xa6, + 0x17, 0xa6, 0x17, 0xa6, 0x17, 0xa6, 0x17, 0xa6, + 0xa0, 0x00, 0xd8, 0x48, + 0x46, 0x6e, 0x46, 0x6e, 0x46, 0x6e, 0x46, 0x6e, + 0xd8, 0x99, 0xd8, 0x99, 0xd8, 0x99, 0xd8, 0x99, + 0xd8, 0x99, 0xd8, 0x99, 0xd8, 0x99, 0xd8, 0x99, + 0x50, 0x00, 0xcd, 0x36, + 0xdb, 0x59, 0xdb, 0x59, 0xdb, 0x59, 0xdb, 0x59, + 0x6d, 0x85, 0x6d, 0x85, 0x6d, 0x85, 0x6d, 0x85, + 0x6d, 0x85, 0x6d, 0x85, 0x6d, 0x85, 0x6d, 0x85, + 0x00, 0x00, 0x10, 0x2e, + 0x71, 0x45, 0x71, 0x45, 0x71, 0x45, 0x71, 0x45, + 0x03, 0x71, 0x03, 0x71, 0x03, 0x71, 0x03, 0x71, + 0x03, 0x71, 0x03, 0x71, 0x03, 0x71, 0x03, 0x71, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, + + /* 2557 MHz */ + 0x9e, 0x09, + 0x10, 0x01, 0xf3, 0x87, + 0x17, 0x8b, 0x17, 0x8b, 0x17, 0x8b, 0x17, 0x8b, + 0xa9, 0xb6, 0xa9, 0xb6, 0xa9, 0xb6, 0xa9, 0xb6, + 0xa9, 0xb6, 0xa9, 0xb6, 0xa9, 0xb6, 0xa9, 0xb6, + 0xf0, 0x00, 0x07, 0x6f, + 0xe9, 0x82, 0xe9, 0x82, 0xe9, 0x82, 0xe9, 0x82, + 0x7b, 0xae, 0x7b, 0xae, 0x7b, 0xae, 0x7b, 0xae, + 0x7b, 0xae, 0x7b, 0xae, 0x7b, 0xae, 0x7b, 0xae, + 0xd0, 0x00, 0x73, 0x5c, + 0xba, 0x7a, 0xba, 0x7a, 0xba, 0x7a, 0xba, 0x7a, + 0x4c, 0xa6, 0x4c, 0xa6, 0x4c, 0xa6, 0x4c, 0xa6, + 0x4c, 0xa6, 0x4c, 0xa6, 0x4c, 0xa6, 0x4c, 0xa6, + 0xa0, 0x00, 0x0d, 0x49, + 0x74, 0x6e, 0x74, 0x6e, 0x74, 0x6e, 0x74, 0x6e, + 0x06, 0x9a, 0x06, 0x9a, 0x06, 0x9a, 0x06, 0x9a, + 0x06, 0x9a, 0x06, 0x9a, 0x06, 0x9a, 0x06, 0x9a, + 0x50, 0x00, 0xd1, 0x36, + 0xff, 0x59, 0xff, 0x59, 0xff, 0x59, 0xff, 0x59, + 0x91, 0x85, 0x91, 0x85, 0x91, 0x85, 0x91, 0x85, + 0x91, 0x85, 0x91, 0x85, 0x91, 0x85, 0x91, 0x85, + 0x00, 0x00, 0x0e, 0x2e, + 0x8b, 0x45, 0x8b, 0x45, 0x8b, 0x45, 0x8b, 0x45, + 0x1d, 0x71, 0x1d, 0x71, 0x1d, 0x71, 0x1d, 0x71, + 0x1d, 0x71, 0x1d, 0x71, 0x1d, 0x71, 0x1d, 0x71, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, + + /* 2562 MHz */ + 0xa3, 0x09, + 0x10, 0x01, 0x72, 0x89, + 0x54, 0x8b, 0x54, 0x8b, 0x54, 0x8b, 0x54, 0x8b, + 0xe6, 0xb6, 0xe6, 0xb6, 0xe6, 0xb6, 0xe6, 0xb6, + 0xe6, 0xb6, 0xe6, 0xb6, 0xe6, 0xb6, 0xe6, 0xb6, + 0xf0, 0x00, 0xf0, 0x6f, + 0x21, 0x83, 0x21, 0x83, 0x21, 0x83, 0x21, 0x83, + 0xb3, 0xae, 0xb3, 0xae, 0xb3, 0xae, 0xb3, 0xae, + 0xb3, 0xae, 0xb3, 0xae, 0xb3, 0xae, 0xb3, 0xae, + 0xd0, 0x00, 0xfb, 0x5c, + 0xee, 0x7a, 0xee, 0x7a, 0xee, 0x7a, 0xee, 0x7a, + 0x80, 0xa6, 0x80, 0xa6, 0x80, 0xa6, 0x80, 0xa6, + 0x80, 0xa6, 0x80, 0xa6, 0x80, 0xa6, 0x80, 0xa6, + 0xa0, 0x00, 0x43, 0x49, + 0xa3, 0x6e, 0xa3, 0x6e, 0xa3, 0x6e, 0xa3, 0x6e, + 0x35, 0x9a, 0x35, 0x9a, 0x35, 0x9a, 0x35, 0x9a, + 0x35, 0x9a, 0x35, 0x9a, 0x35, 0x9a, 0x35, 0x9a, + 0x50, 0x00, 0xd4, 0x36, + 0x24, 0x5a, 0x24, 0x5a, 0x24, 0x5a, 0x24, 0x5a, + 0xb6, 0x85, 0xb6, 0x85, 0xb6, 0x85, 0xb6, 0x85, + 0xb6, 0x85, 0xb6, 0x85, 0xb6, 0x85, 0xb6, 0x85, + 0x00, 0x00, 0x0b, 0x2e, + 0xa6, 0x45, 0xa6, 0x45, 0xa6, 0x45, 0xa6, 0x45, + 0x38, 0x71, 0x38, 0x71, 0x38, 0x71, 0x38, 0x71, + 0x38, 0x71, 0x38, 0x71, 0x38, 0x71, 0x38, 0x71, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, + + /* 2572 MHz */ + 0xa8, 0x09, + 0x10, 0x01, 0xf1, 0x8a, + 0x91, 0x8b, 0x91, 0x8b, 0x91, 0x8b, 0x91, 0x8b, + 0x23, 0xb7, 0x23, 0xb7, 0x23, 0xb7, 0x23, 0xb7, + 0x23, 0xb7, 0x23, 0xb7, 0x23, 0xb7, 0x23, 0xb7, + 0xf0, 0x00, 0xd9, 0x70, + 0x5a, 0x83, 0x5a, 0x83, 0x5a, 0x83, 0x5a, 0x83, + 0xec, 0xae, 0xec, 0xae, 0xec, 0xae, 0xec, 0xae, + 0xec, 0xae, 0xec, 0xae, 0xec, 0xae, 0xec, 0xae, + 0xd0, 0x00, 0x83, 0x5d, + 0x23, 0x7b, 0x23, 0x7b, 0x23, 0x7b, 0x23, 0x7b, + 0xb5, 0xa6, 0xb5, 0xa6, 0xb5, 0xa6, 0xb5, 0xa6, + 0xb5, 0xa6, 0xb5, 0xa6, 0xb5, 0xa6, 0xb5, 0xa6, + 0xa0, 0x00, 0x78, 0x49, + 0xd1, 0x6e, 0xd1, 0x6e, 0xd1, 0x6e, 0xd1, 0x6e, + 0x63, 0x9a, 0x63, 0x9a, 0x63, 0x9a, 0x63, 0x9a, + 0x63, 0x9a, 0x63, 0x9a, 0x63, 0x9a, 0x63, 0x9a, + 0x50, 0x00, 0xd8, 0x36, + 0x48, 0x5a, 0x48, 0x5a, 0x48, 0x5a, 0x48, 0x5a, + 0xda, 0x85, 0xda, 0x85, 0xda, 0x85, 0xda, 0x85, + 0xda, 0x85, 0xda, 0x85, 0xda, 0x85, 0xda, 0x85, + 0x00, 0x00, 0x09, 0x2e, + 0xc0, 0x45, 0xc0, 0x45, 0xc0, 0x45, 0xc0, 0x45, + 0x52, 0x71, 0x52, 0x71, 0x52, 0x71, 0x52, 0x71, + 0x52, 0x71, 0x52, 0x71, 0x52, 0x71, 0x52, 0x71, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, + +/* + * Not really sure if this is actually the power_limit database, + * it looks a bit "related" to PDR_PRISM_ZIF_TX_IQ_CALIBRATION + */ +/* struct pda_custom_wrapper */ +0xae, 0x00, 0xef, 0xbe, /* PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM */ + 0x0d, 0x00, 0x1a, 0x00, /* 13 entries, 26 bytes per entry */ + 0x00, 0x00, 0x52, 0x01, /* no offset, 338 bytes total */ + + /* 2412 MHz */ + 0x6c, 0x09, + 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, + 0xe0, 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xe0, 0x00, + 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, + + /* 2417 MHz */ + 0x71, 0x09, + 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, + 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, + 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, + + /* 2422 MHz */ + 0x76, 0x09, + 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, + 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, + 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, + + /* 2427 MHz */ + 0x7b, 0x09, + 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, + 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, + 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, + + /* 2432 MHz */ + 0x80, 0x09, + 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, + 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, + 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, + + /* 2437 MHz */ + 0x85, 0x09, + 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, + 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, + 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, + + /* 2442 MHz */ + 0x8a, 0x09, + 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, + 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, + 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, + + /* 2447 MHz */ + 0x8f, 0x09, + 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, + 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, + 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, + + /* 2452 MHz */ + 0x94, 0x09, + 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, + 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, + 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, + + /* 2457 MHz */ + 0x99, 0x09, + 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, + 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, + 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, + + /* 2462 MHz */ + 0x9e, 0x09, + 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, + 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, + 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, + + /* 2467 MHz */ + 0xa3, 0x09, + 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, + 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, + 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, + + /* 2472 MHz */ + 0xa8, 0x09, + 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, + 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, + 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, + +/* struct pda_iq_autocal_entry[13] */ +0x42, 0x00, 0x06, 0x19, /* PDR_PRISM_ZIF_TX_IQ_CALIBRATION */ + /* 2412 MHz */ + 0x6c, 0x09, 0x26, 0x00, 0xf8, 0xff, 0xf7, 0xff, 0xff, 0x00, + /* 2417 MHz */ + 0x71, 0x09, 0x26, 0x00, 0xf8, 0xff, 0xf7, 0xff, 0xff, 0x00, + /* 2422 MHz */ + 0x76, 0x09, 0x26, 0x00, 0xf8, 0xff, 0xf7, 0xff, 0xff, 0x00, + /* 2427 MHz */ + 0x7b, 0x09, 0x26, 0x00, 0xf8, 0xff, 0xf7, 0xff, 0xff, 0x00, + /* 2432 MHz */ + 0x80, 0x09, 0x25, 0x00, 0xf7, 0xff, 0xf7, 0xff, 0xff, 0x00, + /* 2437 MHz */ + 0x85, 0x09, 0x25, 0x00, 0xf7, 0xff, 0xf7, 0xff, 0xff, 0x00, + /* 2442 MHz */ + 0x8a, 0x09, 0x25, 0x00, 0xf7, 0xff, 0xf7, 0xff, 0xff, 0x00, + /* 2447 MHz */ + 0x8f, 0x09, 0x25, 0x00, 0xf7, 0xff, 0xf7, 0xff, 0xff, 0x00, + /* 2452 MHz */ + 0x94, 0x09, 0x25, 0x00, 0xf7, 0xff, 0xf7, 0xff, 0xff, 0x00, + /* 2457 MHz */ + 0x99, 0x09, 0x25, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0x00, 0x01, + /* 2462 MHz */ + 0x9e, 0x09, 0x25, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0x00, 0x01, + /* 2467 MHz */ + 0xa3, 0x09, 0x25, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0x00, 0x01, + /* 2472 MHz */ + 0xa8, 0x09, 0x25, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0x00, 0x01, + +0x02, 0x00, 0x00, 0x00, /* PDR_END */ + 0xa8, 0xf5 /* bogus data */ +}; + +#endif /* P54SPI_EEPROM_H */ + -- GitLab From cd8d3d321285a34b4e29cb7b04e552c49cc0f018 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 11 Jan 2009 01:18:38 +0100 Subject: [PATCH 0841/4982] p54spi: p54spi driver This patch adds the p54spi driver. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/Kconfig | 10 + drivers/net/wireless/p54/Makefile | 1 + drivers/net/wireless/p54/p54.h | 9 + drivers/net/wireless/p54/p54common.c | 3 +- drivers/net/wireless/p54/p54spi.c | 759 +++++++++++++++++++++++++++ drivers/net/wireless/p54/p54spi.h | 127 +++++ 6 files changed, 908 insertions(+), 1 deletion(-) create mode 100644 drivers/net/wireless/p54/p54spi.c create mode 100644 drivers/net/wireless/p54/p54spi.h diff --git a/drivers/net/wireless/p54/Kconfig b/drivers/net/wireless/p54/Kconfig index d3469d08f96..cfc5f41aa13 100644 --- a/drivers/net/wireless/p54/Kconfig +++ b/drivers/net/wireless/p54/Kconfig @@ -61,3 +61,13 @@ config P54_PCI http://prism54.org/ If you choose to build a module, it'll be called p54pci. + +config P54_SPI + tristate "Prism54 SPI (stlc45xx) support" + depends on P54_COMMON && SPI_MASTER + ---help--- + This driver is for stlc4550 or stlc4560 based wireless chips. + This driver is experimental, untested and will probably only work on + Nokia's N800/N810 Portable Internet Tablet. + + If you choose to build a module, it'll be called p54spi. diff --git a/drivers/net/wireless/p54/Makefile b/drivers/net/wireless/p54/Makefile index 4fa9ce71736..c2050dee629 100644 --- a/drivers/net/wireless/p54/Makefile +++ b/drivers/net/wireless/p54/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_P54_COMMON) += p54common.o obj-$(CONFIG_P54_USB) += p54usb.o obj-$(CONFIG_P54_PCI) += p54pci.o +obj-$(CONFIG_P54_SPI) += p54spi.o diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index ac11efd19db..64492feca9b 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -104,6 +104,14 @@ struct p54_cal_database { #define FW_LM87 0x4c4d3837 #define FW_LM20 0x4c4d3230 +enum fw_state { + FW_STATE_OFF, + FW_STATE_BOOTING, + FW_STATE_READY, + FW_STATE_RESET, + FW_STATE_RESETTING, +}; + struct p54_common { struct ieee80211_hw *hw; u32 rx_start; @@ -154,6 +162,7 @@ struct p54_common { int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb); void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb); int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw); +int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len); int p54_read_eeprom(struct ieee80211_hw *dev); struct ieee80211_hw *p54_init_common(size_t priv_data_len); void p54_free_common(struct ieee80211_hw *dev); diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 9fc0c9efe70..45c2e7ad3ac 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -483,7 +483,7 @@ static struct p54_cal_database *p54_convert_db(struct pda_custom_wrapper *src, return dst; } -static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) +int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) { struct p54_common *priv = dev->priv; struct eeprom_pda_wrap *wrap = NULL; @@ -698,6 +698,7 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) wiphy_name(dev->wiphy)); return err; } +EXPORT_SYMBOL_GPL(p54_parse_eeprom); static int p54_rssi_to_dbm(struct ieee80211_hw *dev, int rssi) { diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c new file mode 100644 index 00000000000..b8dede741ef --- /dev/null +++ b/drivers/net/wireless/p54/p54spi.c @@ -0,0 +1,759 @@ +/* + * Copyright (C) 2008 Christian Lamparter + * Copyright 2008 Johannes Berg + * + * This driver is a port from stlc45xx: + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "p54spi.h" +#include "p54spi_eeprom.h" +#include "p54.h" + +#include "p54common.h" + +MODULE_FIRMWARE("3826.arm"); +MODULE_ALIAS("stlc45xx"); + +static void p54spi_spi_read(struct p54s_priv *priv, u8 address, + void *buf, size_t len) +{ + struct spi_transfer t[2]; + struct spi_message m; + __le16 addr; + + /* We first push the address */ + addr = cpu_to_le16(address << 8 | SPI_ADRS_READ_BIT_15); + + spi_message_init(&m); + memset(t, 0, sizeof(t)); + + t[0].tx_buf = &addr; + t[0].len = sizeof(addr); + spi_message_add_tail(&t[0], &m); + + t[1].rx_buf = buf; + t[1].len = len; + spi_message_add_tail(&t[1], &m); + + spi_sync(priv->spi, &m); +} + + +static void p54spi_spi_write(struct p54s_priv *priv, u8 address, + const void *buf, size_t len) +{ + struct spi_transfer t[3]; + struct spi_message m; + __le16 addr; + + /* We first push the address */ + addr = cpu_to_le16(address << 8); + + spi_message_init(&m); + memset(t, 0, sizeof(t)); + + t[0].tx_buf = &addr; + t[0].len = sizeof(addr); + spi_message_add_tail(&t[0], &m); + + t[1].tx_buf = buf; + t[1].len = len; + spi_message_add_tail(&t[1], &m); + + if (len % 2) { + __le16 last_word; + last_word = cpu_to_le16(((u8 *)buf)[len - 1]); + + t[2].tx_buf = &last_word; + t[2].len = sizeof(last_word); + spi_message_add_tail(&t[2], &m); + } + + spi_sync(priv->spi, &m); +} + +static u16 p54spi_read16(struct p54s_priv *priv, u8 addr) +{ + __le16 val; + + p54spi_spi_read(priv, addr, &val, sizeof(val)); + + return le16_to_cpu(val); +} + +static u32 p54spi_read32(struct p54s_priv *priv, u8 addr) +{ + __le32 val; + + p54spi_spi_read(priv, addr, &val, sizeof(val)); + + return le32_to_cpu(val); +} + +static inline void p54spi_write16(struct p54s_priv *priv, u8 addr, __le16 val) +{ + p54spi_spi_write(priv, addr, &val, sizeof(val)); +} + +static inline void p54spi_write32(struct p54s_priv *priv, u8 addr, __le32 val) +{ + p54spi_spi_write(priv, addr, &val, sizeof(val)); +} + +struct p54spi_spi_reg { + u16 address; /* __le16 ? */ + u16 length; + char *name; +}; + +static const struct p54spi_spi_reg p54spi_registers_array[] = +{ + { SPI_ADRS_ARM_INTERRUPTS, 32, "ARM_INT " }, + { SPI_ADRS_ARM_INT_EN, 32, "ARM_INT_ENA " }, + { SPI_ADRS_HOST_INTERRUPTS, 32, "HOST_INT " }, + { SPI_ADRS_HOST_INT_EN, 32, "HOST_INT_ENA" }, + { SPI_ADRS_HOST_INT_ACK, 32, "HOST_INT_ACK" }, + { SPI_ADRS_GEN_PURP_1, 32, "GP1_COMM " }, + { SPI_ADRS_GEN_PURP_2, 32, "GP2_COMM " }, + { SPI_ADRS_DEV_CTRL_STAT, 32, "DEV_CTRL_STA" }, + { SPI_ADRS_DMA_DATA, 16, "DMA_DATA " }, + { SPI_ADRS_DMA_WRITE_CTRL, 16, "DMA_WR_CTRL " }, + { SPI_ADRS_DMA_WRITE_LEN, 16, "DMA_WR_LEN " }, + { SPI_ADRS_DMA_WRITE_BASE, 32, "DMA_WR_BASE " }, + { SPI_ADRS_DMA_READ_CTRL, 16, "DMA_RD_CTRL " }, + { SPI_ADRS_DMA_READ_LEN, 16, "DMA_RD_LEN " }, + { SPI_ADRS_DMA_WRITE_BASE, 32, "DMA_RD_BASE " } +}; + +static int p54spi_wait_bit(struct p54s_priv *priv, u16 reg, __le32 bits) +{ + int i; + __le32 buffer; + + for (i = 0; i < 2000; i++) { + p54spi_spi_read(priv, reg, &buffer, sizeof(buffer)); + if (buffer == bits) + return 1; + + msleep(1); + } + return 0; +} + +static int p54spi_request_firmware(struct ieee80211_hw *dev) +{ + struct p54s_priv *priv = dev->priv; + int ret; + + /* FIXME: should driver use it's own struct device? */ + ret = request_firmware(&priv->firmware, "3826.arm", &priv->spi->dev); + + if (ret < 0) { + dev_err(&priv->spi->dev, "request_firmware() failed: %d", ret); + return ret; + } + + ret = p54_parse_firmware(dev, priv->firmware); + if (ret) { + release_firmware(priv->firmware); + return ret; + } + + return 0; +} + +static int p54spi_request_eeprom(struct ieee80211_hw *dev) +{ + struct p54s_priv *priv = dev->priv; + const struct firmware *eeprom; + int ret; + + /* + * allow users to customize their eeprom. + */ + + ret = request_firmware(&eeprom, "3826.eeprom", &priv->spi->dev); + if (ret < 0) { + dev_info(&priv->spi->dev, "loading default eeprom...\n"); + ret = p54_parse_eeprom(dev, (void *) p54spi_eeprom, + sizeof(p54spi_eeprom)); + } else { + dev_info(&priv->spi->dev, "loading user eeprom...\n"); + ret = p54_parse_eeprom(dev, (void *) eeprom->data, + (int)eeprom->size); + release_firmware(eeprom); + } + return ret; +} + +static int p54spi_upload_firmware(struct ieee80211_hw *dev) +{ + struct p54s_priv *priv = dev->priv; + unsigned long fw_len, fw_addr; + long _fw_len; + + /* stop the device */ + p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16( + SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_HOST_RESET | + SPI_CTRL_STAT_START_HALTED)); + + msleep(TARGET_BOOT_SLEEP); + + p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16( + SPI_CTRL_STAT_HOST_OVERRIDE | + SPI_CTRL_STAT_START_HALTED)); + + msleep(TARGET_BOOT_SLEEP); + + fw_addr = ISL38XX_DEV_FIRMWARE_ADDR; + fw_len = priv->firmware->size; + + while (fw_len > 0) { + _fw_len = min_t(long, fw_len, SPI_MAX_PACKET_SIZE); + + p54spi_write16(priv, SPI_ADRS_DMA_WRITE_CTRL, + cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE)); + + if (p54spi_wait_bit(priv, SPI_ADRS_DMA_WRITE_CTRL, + cpu_to_le32(HOST_ALLOWED)) == 0) { + dev_err(&priv->spi->dev, "fw_upload not allowed " + "to DMA write."); + return -EAGAIN; + } + + p54spi_write16(priv, SPI_ADRS_DMA_WRITE_LEN, + cpu_to_le16(_fw_len)); + p54spi_write32(priv, SPI_ADRS_DMA_WRITE_BASE, + cpu_to_le32(fw_addr)); + + p54spi_spi_write(priv, SPI_ADRS_DMA_DATA, + &priv->firmware->data, _fw_len); + + fw_len -= _fw_len; + fw_addr += _fw_len; + + /* FIXME: I think this doesn't work if firmware is large, + * this loop goes to second round. fw->data is not + * increased at all! */ + } + + BUG_ON(fw_len != 0); + + /* enable host interrupts */ + p54spi_write32(priv, SPI_ADRS_HOST_INT_EN, + cpu_to_le32(SPI_HOST_INTS_DEFAULT)); + + /* boot the device */ + p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16( + SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_HOST_RESET | + SPI_CTRL_STAT_RAM_BOOT)); + + msleep(TARGET_BOOT_SLEEP); + + p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16( + SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_RAM_BOOT)); + msleep(TARGET_BOOT_SLEEP); + return 0; +} + +static void p54spi_power_off(struct p54s_priv *priv) +{ + disable_irq(gpio_to_irq(priv->config->irq_gpio)); + gpio_set_value(priv->config->power_gpio, 0); +} + +static void p54spi_power_on(struct p54s_priv *priv) +{ + gpio_set_value(priv->config->power_gpio, 1); + enable_irq(gpio_to_irq(priv->config->irq_gpio)); + + /* + * need to wait a while before device can be accessed, the lenght + * is just a guess + */ + msleep(10); +} + +static inline void p54spi_int_ack(struct p54s_priv *priv, u32 val) +{ + p54spi_write32(priv, SPI_ADRS_HOST_INT_ACK, cpu_to_le32(val)); +} + +static void p54spi_wakeup(struct p54s_priv *priv) +{ + unsigned long timeout; + u32 ints; + + /* wake the chip */ + p54spi_write32(priv, SPI_ADRS_ARM_INTERRUPTS, + cpu_to_le32(SPI_TARGET_INT_WAKEUP)); + + /* And wait for the READY interrupt */ + timeout = jiffies + HZ; + + ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); + while (!(ints & SPI_HOST_INT_READY)) { + if (time_after(jiffies, timeout)) + goto out; + ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); + } + + p54spi_int_ack(priv, SPI_HOST_INT_READY); + +out: + return; +} + +static inline void p54spi_sleep(struct p54s_priv *priv) +{ + p54spi_write32(priv, SPI_ADRS_ARM_INTERRUPTS, + cpu_to_le32(SPI_TARGET_INT_SLEEP)); +} + +static void p54spi_int_ready(struct p54s_priv *priv) +{ + p54spi_write32(priv, SPI_ADRS_HOST_INT_EN, cpu_to_le32( + SPI_HOST_INT_UPDATE | SPI_HOST_INT_SW_UPDATE)); + + switch (priv->fw_state) { + case FW_STATE_BOOTING: + priv->fw_state = FW_STATE_READY; + complete(&priv->fw_comp); + break; + case FW_STATE_RESETTING: + priv->fw_state = FW_STATE_READY; + /* TODO: reinitialize state */ + break; + default: + break; + } +} + +static int p54spi_rx(struct p54s_priv *priv) +{ + struct sk_buff *skb; + u16 len; + + p54spi_wakeup(priv); + + /* dummy read to flush SPI DMA controller bug */ + p54spi_read16(priv, SPI_ADRS_GEN_PURP_1); + + len = p54spi_read16(priv, SPI_ADRS_DMA_DATA); + + if (len == 0) { + dev_err(&priv->spi->dev, "rx request of zero bytes"); + return 0; + } + + skb = dev_alloc_skb(len); + if (!skb) { + dev_err(&priv->spi->dev, "could not alloc skb"); + return 0; + } + + p54spi_spi_read(priv, SPI_ADRS_DMA_DATA, skb_put(skb, len), len); + p54spi_sleep(priv); + + if (p54_rx(priv->hw, skb) == 0) + dev_kfree_skb(skb); + + return 0; +} + + +static irqreturn_t p54spi_interrupt(int irq, void *config) +{ + struct spi_device *spi = config; + struct p54s_priv *priv = dev_get_drvdata(&spi->dev); + + queue_work(priv->hw->workqueue, &priv->work); + + return IRQ_HANDLED; +} + +static int p54spi_tx_frame(struct p54s_priv *priv, struct sk_buff *skb) +{ + struct p54_hdr *hdr = (struct p54_hdr *) skb->data; + struct p54s_dma_regs dma_regs; + unsigned long timeout; + int ret = 0; + u32 ints; + + p54spi_wakeup(priv); + + dma_regs.cmd = cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE); + dma_regs.len = cpu_to_le16(skb->len); + dma_regs.addr = hdr->req_id; + + p54spi_spi_write(priv, SPI_ADRS_DMA_WRITE_CTRL, &dma_regs, + sizeof(dma_regs)); + + p54spi_spi_write(priv, SPI_ADRS_DMA_DATA, skb->data, skb->len); + + timeout = jiffies + 2 * HZ; + ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); + while (!(ints & SPI_HOST_INT_WR_READY)) { + if (time_after(jiffies, timeout)) { + dev_err(&priv->spi->dev, "WR_READY timeout"); + ret = -1; + goto out; + } + ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); + } + + p54spi_int_ack(priv, SPI_HOST_INT_WR_READY); + p54spi_sleep(priv); + +out: + if (FREE_AFTER_TX(skb)) + p54_free_skb(priv->hw, skb); + return ret; +} + +static int p54spi_wq_tx(struct p54s_priv *priv) +{ + struct p54s_tx_info *entry; + struct sk_buff *skb; + struct ieee80211_tx_info *info; + struct p54_tx_info *minfo; + struct p54s_tx_info *dinfo; + int ret = 0; + + spin_lock_bh(&priv->tx_lock); + + while (!list_empty(&priv->tx_pending)) { + entry = list_entry(priv->tx_pending.next, + struct p54s_tx_info, tx_list); + + list_del_init(&entry->tx_list); + + spin_unlock_bh(&priv->tx_lock); + + dinfo = container_of((void *) entry, struct p54s_tx_info, + tx_list); + minfo = container_of((void *) dinfo, struct p54_tx_info, + data); + info = container_of((void *) minfo, struct ieee80211_tx_info, + rate_driver_data); + skb = container_of((void *) info, struct sk_buff, cb); + + ret = p54spi_tx_frame(priv, skb); + + spin_lock_bh(&priv->tx_lock); + + if (ret < 0) { + p54_free_skb(priv->hw, skb); + goto out; + } + } + +out: + spin_unlock_bh(&priv->tx_lock); + return ret; +} + +static void p54spi_op_tx(struct ieee80211_hw *dev, struct sk_buff *skb) +{ + struct p54s_priv *priv = dev->priv; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct p54_tx_info *mi = (struct p54_tx_info *) info->rate_driver_data; + struct p54s_tx_info *di = (struct p54s_tx_info *) mi->data; + + BUILD_BUG_ON(sizeof(*di) > sizeof((mi->data))); + + spin_lock_bh(&priv->tx_lock); + list_add_tail(&di->tx_list, &priv->tx_pending); + spin_unlock_bh(&priv->tx_lock); + + queue_work(priv->hw->workqueue, &priv->work); +} + +static void p54spi_work(struct work_struct *work) +{ + struct p54s_priv *priv = container_of(work, struct p54s_priv, work); + u32 ints; + int ret; + + mutex_lock(&priv->mutex); + + if (priv->fw_state == FW_STATE_OFF && + priv->fw_state == FW_STATE_RESET) + goto out; + + ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); + + if (ints & SPI_HOST_INT_READY) { + p54spi_int_ready(priv); + p54spi_int_ack(priv, SPI_HOST_INT_READY); + } + + if (priv->fw_state != FW_STATE_READY) + goto out; + + if (ints & SPI_HOST_INT_UPDATE) { + p54spi_int_ack(priv, SPI_HOST_INT_UPDATE); + ret = p54spi_rx(priv); + if (ret < 0) + goto out; + } + if (ints & SPI_HOST_INT_SW_UPDATE) { + p54spi_int_ack(priv, SPI_HOST_INT_SW_UPDATE); + ret = p54spi_rx(priv); + if (ret < 0) + goto out; + } + + ret = p54spi_wq_tx(priv); + if (ret < 0) + goto out; + + ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); + +out: + mutex_unlock(&priv->mutex); +} + +static int p54spi_op_start(struct ieee80211_hw *dev) +{ + struct p54s_priv *priv = dev->priv; + unsigned long timeout; + int ret = 0; + + if (mutex_lock_interruptible(&priv->mutex)) { + ret = -EINTR; + goto out; + } + + priv->fw_state = FW_STATE_BOOTING; + + p54spi_power_on(priv); + + ret = p54spi_upload_firmware(dev); + if (ret < 0) { + p54spi_power_off(priv); + goto out_unlock; + } + + mutex_unlock(&priv->mutex); + + timeout = msecs_to_jiffies(2000); + timeout = wait_for_completion_interruptible_timeout(&priv->fw_comp, + timeout); + if (!timeout) { + dev_err(&priv->spi->dev, "firmware boot failed"); + p54spi_power_off(priv); + ret = -1; + goto out; + } + + if (mutex_lock_interruptible(&priv->mutex)) { + ret = -EINTR; + p54spi_power_off(priv); + goto out; + } + + WARN_ON(priv->fw_state != FW_STATE_READY); + +out_unlock: + mutex_unlock(&priv->mutex); + +out: + return ret; +} + +static void p54spi_op_stop(struct ieee80211_hw *dev) +{ + struct p54s_priv *priv = dev->priv; + + if (mutex_lock_interruptible(&priv->mutex)) { + /* FIXME: how to handle this error? */ + return; + } + + WARN_ON(priv->fw_state != FW_STATE_READY); + + cancel_work_sync(&priv->work); + + p54spi_power_off(priv); + spin_lock_bh(&priv->tx_lock); + INIT_LIST_HEAD(&priv->tx_pending); + spin_unlock_bh(&priv->tx_lock); + + priv->fw_state = FW_STATE_OFF; + mutex_unlock(&priv->mutex); +} + +static int __devinit p54spi_probe(struct spi_device *spi) +{ + struct p54s_priv *priv = NULL; + struct ieee80211_hw *hw; + int ret = -EINVAL; + + hw = p54_init_common(sizeof(*priv)); + if (!hw) { + dev_err(&priv->spi->dev, "could not alloc ieee80211_hw"); + return -ENOMEM; + } + + priv = hw->priv; + priv->hw = hw; + dev_set_drvdata(&spi->dev, priv); + priv->spi = spi; + + priv->config = omap_get_config(OMAP_TAG_WLAN_CX3110X, + struct omap_wlan_cx3110x_config); + + spi->bits_per_word = 16; + spi->max_speed_hz = 24000000; + + ret = spi_setup(spi); + if (ret < 0) { + dev_err(&priv->spi->dev, "spi_setup failed"); + goto err_free_common; + } + + ret = gpio_request(priv->config->power_gpio, "p54spi power"); + if (ret < 0) { + dev_err(&priv->spi->dev, "power GPIO request failed: %d", ret); + goto err_free_common; + } + + ret = gpio_request(priv->config->irq_gpio, "p54spi irq"); + if (ret < 0) { + dev_err(&priv->spi->dev, "irq GPIO request failed: %d", ret); + goto err_free_common; + } + + gpio_direction_output(priv->config->power_gpio, 0); + gpio_direction_input(priv->config->irq_gpio); + + ret = request_irq(OMAP_GPIO_IRQ(priv->config->irq_gpio), + p54spi_interrupt, IRQF_DISABLED, "p54spi", + priv->spi); + if (ret < 0) { + dev_err(&priv->spi->dev, "request_irq() failed"); + goto err_free_common; + } + + set_irq_type(gpio_to_irq(priv->config->irq_gpio), + IRQ_TYPE_EDGE_RISING); + + disable_irq(gpio_to_irq(priv->config->irq_gpio)); + + INIT_WORK(&priv->work, p54spi_work); + init_completion(&priv->fw_comp); + INIT_LIST_HEAD(&priv->tx_pending); + mutex_init(&priv->mutex); + SET_IEEE80211_DEV(hw, &spi->dev); + priv->common.open = p54spi_op_start; + priv->common.stop = p54spi_op_stop; + priv->common.tx = p54spi_op_tx; + + ret = p54spi_request_firmware(hw); + if (ret < 0) + goto err_free_common; + + ret = p54spi_request_eeprom(hw); + if (ret) + goto err_free_common; + + ret = ieee80211_register_hw(hw); + if (ret) { + dev_err(&priv->spi->dev, "unable to register " + "mac80211 hw: %d", ret); + goto err_free_common; + } + + dev_info(&priv->spi->dev, "device is bound to %s\n", + wiphy_name(hw->wiphy)); + return 0; + +err_free_common: + p54_free_common(priv->hw); + return ret; +} + +static int __devexit p54spi_remove(struct spi_device *spi) +{ + struct p54s_priv *priv = dev_get_drvdata(&spi->dev); + + ieee80211_unregister_hw(priv->hw); + + free_irq(gpio_to_irq(priv->config->irq_gpio), spi); + + gpio_free(priv->config->power_gpio); + gpio_free(priv->config->irq_gpio); + release_firmware(priv->firmware); + + mutex_destroy(&priv->mutex); + + p54_free_common(priv->hw); + ieee80211_free_hw(priv->hw); + + return 0; +} + + +static struct spi_driver p54spi_driver = { + .driver = { + /* use cx3110x name because board-n800.c uses that for the + * SPI port */ + .name = "cx3110x", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + + .probe = p54spi_probe, + .remove = __devexit_p(p54spi_remove), +}; + +static int __init p54spi_init(void) +{ + int ret; + + ret = spi_register_driver(&p54spi_driver); + if (ret < 0) { + printk(KERN_ERR "failed to register SPI driver: %d", ret); + goto out; + } + +out: + return ret; +} + +static void __exit p54spi_exit(void) +{ + spi_unregister_driver(&p54spi_driver); +} + +module_init(p54spi_init); +module_exit(p54spi_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Christian Lamparter "); diff --git a/drivers/net/wireless/p54/p54spi.h b/drivers/net/wireless/p54/p54spi.h new file mode 100644 index 00000000000..5013ebc8712 --- /dev/null +++ b/drivers/net/wireless/p54/p54spi.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2008 Christian Lamparter + * + * This driver is a port from stlc45xx: + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef P54SPI_H +#define P54SPI_H + +#include +#include +#include +#include + +#include "p54.h" + +/* Bit 15 is read/write bit; ON = READ, OFF = WRITE */ +#define SPI_ADRS_READ_BIT_15 0x8000 + +#define SPI_ADRS_ARM_INTERRUPTS 0x00 +#define SPI_ADRS_ARM_INT_EN 0x04 + +#define SPI_ADRS_HOST_INTERRUPTS 0x08 +#define SPI_ADRS_HOST_INT_EN 0x0c +#define SPI_ADRS_HOST_INT_ACK 0x10 + +#define SPI_ADRS_GEN_PURP_1 0x14 +#define SPI_ADRS_GEN_PURP_2 0x18 + +#define SPI_ADRS_DEV_CTRL_STAT 0x26 /* high word */ + +#define SPI_ADRS_DMA_DATA 0x28 + +#define SPI_ADRS_DMA_WRITE_CTRL 0x2c +#define SPI_ADRS_DMA_WRITE_LEN 0x2e +#define SPI_ADRS_DMA_WRITE_BASE 0x30 + +#define SPI_ADRS_DMA_READ_CTRL 0x34 +#define SPI_ADRS_DMA_READ_LEN 0x36 +#define SPI_ADRS_DMA_READ_BASE 0x38 + +#define SPI_CTRL_STAT_HOST_OVERRIDE 0x8000 +#define SPI_CTRL_STAT_START_HALTED 0x4000 +#define SPI_CTRL_STAT_RAM_BOOT 0x2000 +#define SPI_CTRL_STAT_HOST_RESET 0x1000 +#define SPI_CTRL_STAT_HOST_CPU_EN 0x0800 + +#define SPI_DMA_WRITE_CTRL_ENABLE 0x0001 +#define SPI_DMA_READ_CTRL_ENABLE 0x0001 +#define HOST_ALLOWED (1 << 7) + +#define SPI_TIMEOUT 100 /* msec */ + +#define SPI_MAX_TX_PACKETS 32 + +#define SPI_MAX_PACKET_SIZE 32767 + +#define SPI_TARGET_INT_WAKEUP 0x00000001 +#define SPI_TARGET_INT_SLEEP 0x00000002 +#define SPI_TARGET_INT_RDDONE 0x00000004 + +#define SPI_TARGET_INT_CTS 0x00004000 +#define SPI_TARGET_INT_DR 0x00008000 + +#define SPI_HOST_INT_READY 0x00000001 +#define SPI_HOST_INT_WR_READY 0x00000002 +#define SPI_HOST_INT_SW_UPDATE 0x00000004 +#define SPI_HOST_INT_UPDATE 0x10000000 + +/* clear to send */ +#define SPI_HOST_INT_CR 0x00004000 + +/* data ready */ +#define SPI_HOST_INT_DR 0x00008000 + +#define SPI_HOST_INTS_DEFAULT \ + (SPI_HOST_INT_READY | SPI_HOST_INT_UPDATE | SPI_HOST_INT_SW_UPDATE) + +#define TARGET_BOOT_SLEEP 50 + +struct p54s_dma_regs { + __le16 cmd; + __le16 len; + __le32 addr; +} __attribute__ ((packed)); + +struct p54s_tx_info { + struct list_head tx_list; +}; + +struct p54s_priv { + /* p54_common has to be the first entry */ + struct p54_common common; + struct ieee80211_hw *hw; + struct spi_device *spi; + const struct omap_wlan_cx3110x_config *config; + + struct work_struct work; + + struct mutex mutex; + struct completion fw_comp; + + spinlock_t tx_lock; + + /* protected by tx_lock */ + struct list_head tx_pending; + + enum fw_state fw_state; + const struct firmware *firmware; +}; + +#endif /* P54SPI_H */ -- GitLab From 81094888bfbb759ea395f1857a7c38982acb99a9 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 12 Jan 2009 13:04:06 +0100 Subject: [PATCH 0842/4982] ath5k: discard 11g caps if reported by an ar5211 eeprom At least one ar5211 card (GIGABYTE GN-WLMA101, 168c:0012 subsystem 1458:e800) reports itself as 11g capable which seems to be a bug in the eeprom. initvals.c assumes that ar5211 is only 11b capable and thus refuses to initialize this card. Hence this patch changes the probing for 11g capabilities to discard 11g capabilities for ar5211 cards which allows this specific card to work fine in 11b and 11a modes. Signed-off-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/caps.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath5k/caps.c b/drivers/net/wireless/ath5k/caps.c index 150f5ed204a..367a6c7d3cc 100644 --- a/drivers/net/wireless/ath5k/caps.c +++ b/drivers/net/wireless/ath5k/caps.c @@ -85,7 +85,8 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) /* Enable 802.11b if a 2GHz capable radio (2111/5112) is * connected */ if (AR5K_EEPROM_HDR_11B(ee_header) || - AR5K_EEPROM_HDR_11G(ee_header)) { + (AR5K_EEPROM_HDR_11G(ee_header) && + ah->ah_version != AR5K_AR5211)) { /* 2312 */ ah->ah_capabilities.cap_range.range_2ghz_min = 2412; ah->ah_capabilities.cap_range.range_2ghz_max = 2732; @@ -94,7 +95,8 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) __set_bit(AR5K_MODE_11B, ah->ah_capabilities.cap_mode); - if (AR5K_EEPROM_HDR_11G(ee_header)) + if (AR5K_EEPROM_HDR_11G(ee_header) && + ah->ah_version != AR5K_AR5211) __set_bit(AR5K_MODE_11G, ah->ah_capabilities.cap_mode); } -- GitLab From d03415e6771cd709b2b2ec64d3e6315cc3ebfa74 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 12 Jan 2009 14:24:40 +0200 Subject: [PATCH 0843/4982] nl80211: Fix documentation errors Couple of '_ATTR's were missing and SEC_CHAN_OFFSET to CHANNEL_TYPE rename was missed in couple of places. Signed-off-by: Jouni Malinen Acked-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/nl80211.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index ee742bc9761..4e7a7986a52 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -47,7 +47,7 @@ * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME, * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ, and/or - * %NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET. + * %NL80211_ATTR_WIPHY_CHANNEL_TYPE. * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request * or rename notification. Has attributes %NL80211_ATTR_WIPHY and * %NL80211_ATTR_WIPHY_NAME. @@ -84,7 +84,7 @@ * %NL80222_CMD_NEW_BEACON message) * @NL80211_CMD_SET_BEACON: set the beacon on an access point interface * using the %NL80211_ATTR_BEACON_INTERVAL, %NL80211_ATTR_DTIM_PERIOD, - * %NL80211_BEACON_HEAD and %NL80211_BEACON_TAIL attributes. + * %NL80211_ATTR_BEACON_HEAD and %NL80211_ATTR_BEACON_TAIL attributes. * @NL80211_CMD_NEW_BEACON: add a new beacon to an access point interface, * parameters are like for %NL80211_CMD_SET_BEACON. * @NL80211_CMD_DEL_BEACON: remove the beacon, stop sending it @@ -362,7 +362,7 @@ enum nl80211_attrs { #define NL80211_ATTR_BSS_BASIC_RATES NL80211_ATTR_BSS_BASIC_RATES #define NL80211_ATTR_WIPHY_TXQ_PARAMS NL80211_ATTR_WIPHY_TXQ_PARAMS #define NL80211_ATTR_WIPHY_FREQ NL80211_ATTR_WIPHY_FREQ -#define NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET +#define NL80211_ATTR_WIPHY_CHANNEL_TYPE NL80211_ATTR_WIPHY_CHANNEL_TYPE #define NL80211_MAX_SUPP_RATES 32 #define NL80211_MAX_SUPP_REG_RULES 32 -- GitLab From 07e74348c76368c3d694a06677c200dc8d9b00e8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 13 Jan 2009 14:32:37 +0200 Subject: [PATCH 0844/4982] ath9k: Use a defined value for pci_set_power_state() Silence sparse by using a defined value PCI_D3hot instead of a magic constant in a pci_set_power_state() call. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 72f2956c4c5..b93ada8f15c 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -2692,7 +2692,7 @@ static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state) pci_save_state(pdev); pci_disable_device(pdev); - pci_set_power_state(pdev, 3); + pci_set_power_state(pdev, PCI_D3hot); return 0; } -- GitLab From a1d88210955e56f7a0d54ac72747075b683b0850 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 14 Jan 2009 11:15:25 -0600 Subject: [PATCH 0845/4982] b43: Eliminate compilation warning in b43_op_set_key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A recent pull from wireless testing generates the following warning: CC [M] drivers/net/wireless/b43/main.o drivers/net/wireless/b43/main.c: In function ‘b43_op_set_key’: drivers/net/wireless/b43/main.c:3636: warning: pointer type mismatch in conditional expression This fix was suggested by Johannes Berg . Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 19ad5164fce..8bb6659c0b3 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3484,6 +3484,9 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, u8 algorithm; u8 index; int err; +#if B43_DEBUG + static const u8 bcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +#endif if (modparam_nohwcrypt) return -ENOSPC; /* User disabled HW-crypto */ @@ -3582,7 +3585,7 @@ out_unlock: b43dbg(wl, "%s hardware based encryption for keyidx: %d, " "mac: %pM\n", cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, - sta ? sta->addr : ""); + sta ? sta->addr : bcast_addr); b43_dump_keymemory(dev); } write_unlock(&wl->tx_lock); -- GitLab From c95741deef31d14c3a3d58397f9a3d2126d452e5 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 14 Jan 2009 23:10:55 -0800 Subject: [PATCH 0846/4982] prism54: remove private implementation of le32_add_cpu Signed-off-by: Harvey Harrison Signed-off-by: John W. Linville --- drivers/net/wireless/prism54/islpci_eth.c | 5 +++-- drivers/net/wireless/prism54/islpci_mgt.h | 6 ------ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index e43bae97ed8..88895bd9e49 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "prismcompat.h" #include "isl_38xx.h" @@ -471,8 +472,8 @@ islpci_eth_receive(islpci_private *priv) wmb(); /* increment the driver read pointer */ - add_le32p(&control_block-> - driver_curr_frag[ISL38XX_CB_RX_DATA_LQ], 1); + le32_add_cpu(&control_block-> + driver_curr_frag[ISL38XX_CB_RX_DATA_LQ], 1); } /* trigger the device */ diff --git a/drivers/net/wireless/prism54/islpci_mgt.h b/drivers/net/wireless/prism54/islpci_mgt.h index f91a88fc1e3..87a1734663d 100644 --- a/drivers/net/wireless/prism54/islpci_mgt.h +++ b/drivers/net/wireless/prism54/islpci_mgt.h @@ -85,12 +85,6 @@ extern int pc_debug; #define PIMFOR_FLAG_APPLIC_ORIGIN 0x01 #define PIMFOR_FLAG_LITTLE_ENDIAN 0x02 -static inline void -add_le32p(__le32 * le_number, u32 add) -{ - *le_number = cpu_to_le32(le32_to_cpup(le_number) + add); -} - void display_buffer(char *, int); /* -- GitLab From 2663516d8fb896430bf42dce41b3e2f141d63bd5 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Thu, 15 Jan 2009 09:38:44 +0100 Subject: [PATCH 0847/4982] iwl3945: report killswitch changes even if the interface is down Currently iwl3945 is not able to report hw-killswitch events while the interface is down. This has implications on user space tools (like NetworkManager) relying on rfkill notifications to bring the interface up once the wireless gets enabled through a hw killswitch. Thus, enable the device already in iwl3945_pci_probe instead of iwl3945_up and poll the CSR_GP_CNTRL register to update the killswitch state every two seconds. The polling is only needed on 3945 hardware as this adapter does not use interrupts to signal rfkill changes to the driver (in case no firmware is loaded). The firmware loading is still done in iwl3945_up. Signed-off-by: Helmut Schaa Acked-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 88 +++++++++++++-------- 2 files changed, 57 insertions(+), 32 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index fd34ba81a0d..4d437cf50c8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1041,6 +1041,7 @@ struct iwl_priv { /*For 3945 only*/ struct delayed_work thermal_periodic; + struct delayed_work rfkill_poll; /* TX Power */ s8 tx_power_user_lmt; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 1b04284c4ca..050d532475c 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -5479,7 +5479,8 @@ static void iwl3945_bg_rf_kill(struct work_struct *work) IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL, "HW and/or SW RF Kill no longer active, restarting " "device\n"); - if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (!test_bit(STATUS_EXIT_PENDING, &priv->status) && + test_bit(STATUS_ALIVE, &priv->status)) queue_work(priv->workqueue, &priv->restart); } else { @@ -5496,6 +5497,25 @@ static void iwl3945_bg_rf_kill(struct work_struct *work) iwl3945_rfkill_set_hw_state(priv); } +static void iwl3945_rfkill_poll(struct work_struct *data) +{ + struct iwl_priv *priv = + container_of(data, struct iwl_priv, rfkill_poll.work); + unsigned long status = priv->status; + + if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) + clear_bit(STATUS_RF_KILL_HW, &priv->status); + else + set_bit(STATUS_RF_KILL_HW, &priv->status); + + if (test_bit(STATUS_RF_KILL_HW, &status) != test_bit(STATUS_RF_KILL_HW, &priv->status)) + queue_work(priv->workqueue, &priv->rf_kill); + + queue_delayed_work(priv->workqueue, &priv->rfkill_poll, + round_jiffies_relative(2 * HZ)); + +} + #define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) static void iwl3945_bg_scan_check(struct work_struct *data) @@ -5898,20 +5918,6 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) IWL_DEBUG_MAC80211("enter\n"); - if (pci_enable_device(priv->pci_dev)) { - IWL_ERR(priv, "Fail to pci_enable_device\n"); - return -ENODEV; - } - pci_restore_state(priv->pci_dev); - pci_enable_msi(priv->pci_dev); - - ret = request_irq(priv->pci_dev->irq, iwl3945_isr, IRQF_SHARED, - DRV_NAME, priv); - if (ret) { - IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); - goto out_disable_msi; - } - /* we should be verifying the device is ready to be opened */ mutex_lock(&priv->mutex); @@ -5957,15 +5963,15 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) } } + /* ucode is running and will send rfkill notifications, + * no need to poll the killswitch state anymore */ + cancel_delayed_work(&priv->rfkill_poll); + priv->is_open = 1; IWL_DEBUG_MAC80211("leave\n"); return 0; out_release_irq: - free_irq(priv->pci_dev->irq, priv); -out_disable_msi: - pci_disable_msi(priv->pci_dev); - pci_disable_device(priv->pci_dev); priv->is_open = 0; IWL_DEBUG_MAC80211("leave - failed\n"); return ret; @@ -5996,10 +6002,10 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw) iwl3945_down(priv); flush_workqueue(priv->workqueue); - free_irq(priv->pci_dev->irq, priv); - pci_disable_msi(priv->pci_dev); - pci_save_state(priv->pci_dev); - pci_disable_device(priv->pci_dev); + + /* start polling the killswitch state again */ + queue_delayed_work(priv->workqueue, &priv->rfkill_poll, + round_jiffies_relative(2 * HZ)); IWL_DEBUG_MAC80211("leave\n"); } @@ -7207,6 +7213,7 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv) INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start); INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start); INIT_DELAYED_WORK(&priv->scan_check, iwl3945_bg_scan_check); + INIT_DELAYED_WORK(&priv->rfkill_poll, iwl3945_rfkill_poll); iwl3945_hw_setup_deferred_work(priv); @@ -7497,6 +7504,15 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e iwl3945_disable_interrupts(priv); spin_unlock_irqrestore(&priv->lock, flags); + pci_enable_msi(priv->pci_dev); + + err = request_irq(priv->pci_dev->irq, iwl3945_isr, IRQF_SHARED, + DRV_NAME, priv); + if (err) { + IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); + goto out_disable_msi; + } + err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group); if (err) { IWL_ERR(priv, "failed to create sysfs device attributes\n"); @@ -7507,14 +7523,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e iwl3945_setup_deferred_work(priv); iwl3945_setup_rx_handlers(priv); - /*********************** - * 9. Conclude - * ********************/ - pci_save_state(pdev); - pci_disable_device(pdev); - /********************************* - * 10. Setup and Register mac80211 + * 9. Setup and Register mac80211 * *******************************/ err = ieee80211_register_hw(priv->hw); @@ -7531,6 +7541,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e IWL_ERR(priv, "Unable to initialize RFKILL system. " "Ignoring error: %d\n", err); + /* Start monitoring the killswitch */ + queue_delayed_work(priv->workqueue, &priv->rfkill_poll, + 2 * HZ); + return 0; out_remove_sysfs: @@ -7539,10 +7553,12 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e iwl3945_free_geos(priv); out_release_irq: + free_irq(priv->pci_dev->irq, priv); destroy_workqueue(priv->workqueue); priv->workqueue = NULL; iwl3945_unset_hw_params(priv); - + out_disable_msi: + pci_disable_msi(priv->pci_dev); out_iounmap: pci_iounmap(pdev, priv->hw_base); out_pci_release_regions: @@ -7587,6 +7603,8 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); iwl3945_rfkill_unregister(priv); + cancel_delayed_work(&priv->rfkill_poll); + iwl3945_dealloc_ucode_pci(priv); if (priv->rxq.bd) @@ -7605,6 +7623,9 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) destroy_workqueue(priv->workqueue); priv->workqueue = NULL; + free_irq(pdev->irq, priv); + pci_disable_msi(pdev); + pci_iounmap(pdev, priv->hw_base); pci_release_regions(pdev); pci_disable_device(pdev); @@ -7630,7 +7651,8 @@ static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state) iwl3945_mac_stop(priv->hw); priv->is_open = 1; } - + pci_save_state(pdev); + pci_disable_device(pdev); pci_set_power_state(pdev, PCI_D3hot); return 0; @@ -7641,6 +7663,8 @@ static int iwl3945_pci_resume(struct pci_dev *pdev) struct iwl_priv *priv = pci_get_drvdata(pdev); pci_set_power_state(pdev, PCI_D0); + pci_enable_device(pdev); + pci_restore_state(pdev); if (priv->is_open) iwl3945_mac_start(priv->hw); -- GitLab From f5870acb3a8e2cad57b6c5ffd3157a7dfbb47942 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Jan 2009 20:17:02 +0100 Subject: [PATCH 0848/4982] ath9k: convert to struct device Convert 'struct pci_dev' to 'struct device' to make it usable on the AHB bus as well. Changes-licensed-under: ISC Signed-off-by: Gabor Juhos Signed-off-by: Imre Kaloz Tested-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/beacon.c | 17 ++++++++++------- drivers/net/wireless/ath9k/core.h | 2 +- drivers/net/wireless/ath9k/main.c | 21 +++++++++++---------- drivers/net/wireless/ath9k/recv.c | 15 +++++++++------ drivers/net/wireless/ath9k/xmit.c | 7 ++++--- 5 files changed, 35 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c index 3ab0b43aaf9..f02b099d3e3 100644 --- a/drivers/net/wireless/ath9k/beacon.c +++ b/drivers/net/wireless/ath9k/beacon.c @@ -164,7 +164,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) bf = avp->av_bcbuf; skb = (struct sk_buff *)bf->bf_mpdu; if (skb) { - pci_unmap_single(sc->pdev, bf->bf_dmacontext, + pci_unmap_single(to_pci_dev(sc->dev), bf->bf_dmacontext, skb->len, PCI_DMA_TODEVICE); dev_kfree_skb_any(skb); @@ -188,10 +188,11 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) } bf->bf_buf_addr = bf->bf_dmacontext = - pci_map_single(sc->pdev, skb->data, + pci_map_single(to_pci_dev(sc->dev), skb->data, skb->len, PCI_DMA_TODEVICE); - if (unlikely(pci_dma_mapping_error(sc->pdev, bf->bf_buf_addr))) { + if (unlikely(pci_dma_mapping_error(to_pci_dev(sc->dev), + bf->bf_buf_addr))) { dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; DPRINTF(sc, ATH_DBG_CONFIG, @@ -343,7 +344,7 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) bf = avp->av_bcbuf; if (bf->bf_mpdu != NULL) { skb = (struct sk_buff *)bf->bf_mpdu; - pci_unmap_single(sc->pdev, bf->bf_dmacontext, + pci_unmap_single(to_pci_dev(sc->dev), bf->bf_dmacontext, skb->len, PCI_DMA_TODEVICE); dev_kfree_skb_any(skb); @@ -402,10 +403,11 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) bf->bf_mpdu = skb; bf->bf_buf_addr = bf->bf_dmacontext = - pci_map_single(sc->pdev, skb->data, + pci_map_single(to_pci_dev(sc->dev), skb->data, skb->len, PCI_DMA_TODEVICE); - if (unlikely(pci_dma_mapping_error(sc->pdev, bf->bf_buf_addr))) { + if (unlikely(pci_dma_mapping_error(to_pci_dev(sc->dev), + bf->bf_buf_addr))) { dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; DPRINTF(sc, ATH_DBG_CONFIG, @@ -429,7 +431,8 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp) bf = avp->av_bcbuf; if (bf->bf_mpdu != NULL) { struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; - pci_unmap_single(sc->pdev, bf->bf_dmacontext, + pci_unmap_single(to_pci_dev(sc->dev), + bf->bf_dmacontext, skb->len, PCI_DMA_TODEVICE); dev_kfree_skb_any(skb); diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index 2bb35dda6b9..2256ba47dd4 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -695,7 +695,7 @@ enum PROT_MODE { struct ath_softc { struct ieee80211_hw *hw; - struct pci_dev *pdev; + struct device *dev; struct tasklet_struct intr_tq; struct tasklet_struct bcon_tasklet; struct ath_hal *sc_ah; diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index b93ada8f15c..44931e42e2b 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -46,7 +46,8 @@ static void bus_read_cachesize(struct ath_softc *sc, int *csz) { u8 u8tmp; - pci_read_config_byte(sc->pdev, PCI_CACHE_LINE_SIZE, (u8 *)&u8tmp); + pci_read_config_byte(to_pci_dev(sc->dev), PCI_CACHE_LINE_SIZE, + (u8 *)&u8tmp); *csz = (int)u8tmp; /* @@ -1267,11 +1268,11 @@ static int ath_start_rfkill_poll(struct ath_softc *sc) /* Deinitialize the device */ ath_detach(sc); - if (sc->pdev->irq) - free_irq(sc->pdev->irq, sc); - pci_iounmap(sc->pdev, sc->mem); - pci_release_region(sc->pdev, 0); - pci_disable_device(sc->pdev); + if (to_pci_dev(sc->dev)->irq) + free_irq(to_pci_dev(sc->dev)->irq, sc); + pci_iounmap(to_pci_dev(sc->dev), sc->mem); + pci_release_region(to_pci_dev(sc->dev), 0); + pci_disable_device(to_pci_dev(sc->dev)); ieee80211_free_hw(sc->hw); return -EIO; } else { @@ -1714,7 +1715,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, } /* allocate descriptors */ - dd->dd_desc = pci_alloc_consistent(sc->pdev, + dd->dd_desc = pci_alloc_consistent(to_pci_dev(sc->dev), dd->dd_desc_len, &dd->dd_desc_paddr); if (dd->dd_desc == NULL) { @@ -1762,7 +1763,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, } return 0; fail2: - pci_free_consistent(sc->pdev, + pci_free_consistent(to_pci_dev(sc->dev), dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr); fail: memset(dd, 0, sizeof(*dd)); @@ -1776,7 +1777,7 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, struct list_head *head) { - pci_free_consistent(sc->pdev, + pci_free_consistent(to_pci_dev(sc->dev), dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr); INIT_LIST_HEAD(head); @@ -2620,7 +2621,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) sc = hw->priv; sc->hw = hw; - sc->pdev = pdev; + sc->dev = &pdev->dev; sc->mem = mem; if (ath_attach(id->device, sc) != 0) { diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c index dbf24be23cc..645fae2f49d 100644 --- a/drivers/net/wireless/ath9k/recv.c +++ b/drivers/net/wireless/ath9k/recv.c @@ -291,10 +291,11 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) } bf->bf_mpdu = skb; - bf->bf_buf_addr = pci_map_single(sc->pdev, skb->data, + bf->bf_buf_addr = pci_map_single(to_pci_dev(sc->dev), + skb->data, sc->rx.bufsize, PCI_DMA_FROMDEVICE); - if (unlikely(pci_dma_mapping_error(sc->pdev, + if (unlikely(pci_dma_mapping_error(to_pci_dev(sc->dev), bf->bf_buf_addr))) { dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; @@ -524,7 +525,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) * 1. accessing the frame * 2. requeueing the same buffer to h/w */ - pci_dma_sync_single_for_cpu(sc->pdev, bf->bf_buf_addr, + pci_dma_sync_single_for_cpu(to_pci_dev(sc->dev), + bf->bf_buf_addr, sc->rx.bufsize, PCI_DMA_FROMDEVICE); @@ -557,7 +559,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) goto requeue; /* Unmap the frame */ - pci_unmap_single(sc->pdev, bf->bf_buf_addr, + pci_unmap_single(to_pci_dev(sc->dev), bf->bf_buf_addr, sc->rx.bufsize, PCI_DMA_FROMDEVICE); @@ -605,10 +607,11 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) /* We will now give hardware our shiny new allocated skb */ bf->bf_mpdu = requeue_skb; - bf->bf_buf_addr = pci_map_single(sc->pdev, requeue_skb->data, + bf->bf_buf_addr = pci_map_single(to_pci_dev(sc->dev), + requeue_skb->data, sc->rx.bufsize, PCI_DMA_FROMDEVICE); - if (unlikely(pci_dma_mapping_error(sc->pdev, + if (unlikely(pci_dma_mapping_error(to_pci_dev(sc->dev), bf->bf_buf_addr))) { dev_kfree_skb_any(requeue_skb); bf->bf_mpdu = NULL; diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 9e910f7a2f3..27cb9d523f5 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -340,7 +340,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, } /* Unmap this frame */ - pci_unmap_single(sc->pdev, + pci_unmap_single(to_pci_dev(sc->dev), bf->bf_dmacontext, skb->len, PCI_DMA_TODEVICE); @@ -1716,9 +1716,10 @@ static int ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf, /* DMA setup */ bf->bf_mpdu = skb; - bf->bf_dmacontext = pci_map_single(sc->pdev, skb->data, + bf->bf_dmacontext = pci_map_single(to_pci_dev(sc->dev), skb->data, skb->len, PCI_DMA_TODEVICE); - if (unlikely(pci_dma_mapping_error(sc->pdev, bf->bf_dmacontext))) { + if (unlikely(pci_dma_mapping_error(to_pci_dev(sc->dev), + bf->bf_dmacontext))) { bf->bf_mpdu = NULL; DPRINTF(sc, ATH_DBG_CONFIG, "pci_dma_mapping_error() on TX\n"); -- GitLab From 7da3c55ce849e17fd9017c7bf770a03fa083d95b Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Jan 2009 20:17:03 +0100 Subject: [PATCH 0849/4982] ath9k: convert to use bus-agnostic DMA routines Convert to use bus-agnostic DMA routines to make it usable on AHB bus as well. Changes-licensed-under: ISC Signed-off-by: Gabor Juhos Signed-off-by: Imre Kaloz Tested-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/beacon.c | 31 +++++++++++++---------------- drivers/net/wireless/ath9k/main.c | 13 ++++++------ drivers/net/wireless/ath9k/recv.c | 27 +++++++++++-------------- drivers/net/wireless/ath9k/xmit.c | 15 ++++++-------- 4 files changed, 38 insertions(+), 48 deletions(-) diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c index f02b099d3e3..be1d84a5daf 100644 --- a/drivers/net/wireless/ath9k/beacon.c +++ b/drivers/net/wireless/ath9k/beacon.c @@ -164,9 +164,9 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) bf = avp->av_bcbuf; skb = (struct sk_buff *)bf->bf_mpdu; if (skb) { - pci_unmap_single(to_pci_dev(sc->dev), bf->bf_dmacontext, + dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, - PCI_DMA_TODEVICE); + DMA_TO_DEVICE); dev_kfree_skb_any(skb); } @@ -188,15 +188,14 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) } bf->bf_buf_addr = bf->bf_dmacontext = - pci_map_single(to_pci_dev(sc->dev), skb->data, + dma_map_single(sc->dev, skb->data, skb->len, - PCI_DMA_TODEVICE); - if (unlikely(pci_dma_mapping_error(to_pci_dev(sc->dev), - bf->bf_buf_addr))) { + DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; DPRINTF(sc, ATH_DBG_CONFIG, - "pci_dma_mapping_error() on beaconing\n"); + "dma_mapping_error() on beaconing\n"); return NULL; } @@ -344,9 +343,9 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) bf = avp->av_bcbuf; if (bf->bf_mpdu != NULL) { skb = (struct sk_buff *)bf->bf_mpdu; - pci_unmap_single(to_pci_dev(sc->dev), bf->bf_dmacontext, + dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, - PCI_DMA_TODEVICE); + DMA_TO_DEVICE); dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; } @@ -403,15 +402,14 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) bf->bf_mpdu = skb; bf->bf_buf_addr = bf->bf_dmacontext = - pci_map_single(to_pci_dev(sc->dev), skb->data, + dma_map_single(sc->dev, skb->data, skb->len, - PCI_DMA_TODEVICE); - if (unlikely(pci_dma_mapping_error(to_pci_dev(sc->dev), - bf->bf_buf_addr))) { + DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; DPRINTF(sc, ATH_DBG_CONFIG, - "pci_dma_mapping_error() on beacon alloc\n"); + "dma_mapping_error() on beacon alloc\n"); return -ENOMEM; } @@ -431,10 +429,9 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp) bf = avp->av_bcbuf; if (bf->bf_mpdu != NULL) { struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; - pci_unmap_single(to_pci_dev(sc->dev), - bf->bf_dmacontext, + dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, - PCI_DMA_TODEVICE); + DMA_TO_DEVICE); dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; } diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 44931e42e2b..ebf0467674c 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1715,9 +1715,8 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, } /* allocate descriptors */ - dd->dd_desc = pci_alloc_consistent(to_pci_dev(sc->dev), - dd->dd_desc_len, - &dd->dd_desc_paddr); + dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len, + &dd->dd_desc_paddr, GFP_ATOMIC); if (dd->dd_desc == NULL) { error = -ENOMEM; goto fail; @@ -1763,8 +1762,8 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, } return 0; fail2: - pci_free_consistent(to_pci_dev(sc->dev), - dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr); + dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, + dd->dd_desc_paddr); fail: memset(dd, 0, sizeof(*dd)); return error; @@ -1777,8 +1776,8 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, struct list_head *head) { - pci_free_consistent(to_pci_dev(sc->dev), - dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr); + dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, + dd->dd_desc_paddr); INIT_LIST_HEAD(head); kfree(dd->dd_bufptr); diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c index 645fae2f49d..648bb49e673 100644 --- a/drivers/net/wireless/ath9k/recv.c +++ b/drivers/net/wireless/ath9k/recv.c @@ -291,16 +291,15 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) } bf->bf_mpdu = skb; - bf->bf_buf_addr = pci_map_single(to_pci_dev(sc->dev), - skb->data, + bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, sc->rx.bufsize, - PCI_DMA_FROMDEVICE); - if (unlikely(pci_dma_mapping_error(to_pci_dev(sc->dev), + DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; DPRINTF(sc, ATH_DBG_CONFIG, - "pci_dma_mapping_error() on RX init\n"); + "dma_mapping_error() on RX init\n"); error = -ENOMEM; break; } @@ -525,10 +524,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) * 1. accessing the frame * 2. requeueing the same buffer to h/w */ - pci_dma_sync_single_for_cpu(to_pci_dev(sc->dev), - bf->bf_buf_addr, + dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr, sc->rx.bufsize, - PCI_DMA_FROMDEVICE); + DMA_FROM_DEVICE); /* * If we're asked to flush receive queue, directly @@ -559,9 +557,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) goto requeue; /* Unmap the frame */ - pci_unmap_single(to_pci_dev(sc->dev), bf->bf_buf_addr, + dma_unmap_single(sc->dev, bf->bf_buf_addr, sc->rx.bufsize, - PCI_DMA_FROMDEVICE); + DMA_FROM_DEVICE); skb_put(skb, ds->ds_rxstat.rs_datalen); skb->protocol = cpu_to_be16(ETH_P_CONTROL); @@ -607,16 +605,15 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) /* We will now give hardware our shiny new allocated skb */ bf->bf_mpdu = requeue_skb; - bf->bf_buf_addr = pci_map_single(to_pci_dev(sc->dev), - requeue_skb->data, + bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data, sc->rx.bufsize, - PCI_DMA_FROMDEVICE); - if (unlikely(pci_dma_mapping_error(to_pci_dev(sc->dev), + DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { dev_kfree_skb_any(requeue_skb); bf->bf_mpdu = NULL; DPRINTF(sc, ATH_DBG_CONFIG, - "pci_dma_mapping_error() on RX\n"); + "dma_mapping_error() on RX\n"); break; } bf->bf_dmacontext = bf->bf_buf_addr; diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 27cb9d523f5..522078d8093 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -340,10 +340,8 @@ static void ath_tx_complete_buf(struct ath_softc *sc, } /* Unmap this frame */ - pci_unmap_single(to_pci_dev(sc->dev), - bf->bf_dmacontext, - skb->len, - PCI_DMA_TODEVICE); + dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); + /* complete this frame */ ath_tx_complete(sc, skb, &tx_status); @@ -1716,13 +1714,12 @@ static int ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf, /* DMA setup */ bf->bf_mpdu = skb; - bf->bf_dmacontext = pci_map_single(to_pci_dev(sc->dev), skb->data, - skb->len, PCI_DMA_TODEVICE); - if (unlikely(pci_dma_mapping_error(to_pci_dev(sc->dev), - bf->bf_dmacontext))) { + bf->bf_dmacontext = dma_map_single(sc->dev, skb->data, + skb->len, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(sc->dev, bf->bf_dmacontext))) { bf->bf_mpdu = NULL; DPRINTF(sc, ATH_DBG_CONFIG, - "pci_dma_mapping_error() on TX\n"); + "dma_mapping_error() on TX\n"); return -ENOMEM; } -- GitLab From 88d15707644fad1a137af7a17b00da6135f1c1a8 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Jan 2009 20:17:04 +0100 Subject: [PATCH 0850/4982] ath9k: introduce bus specific cache size routine The PCI specific bus_read_cachesize routine won't work on the AHB bus, we have to replace it with a suitable one later. Changes-licensed-under: ISC Signed-off-by: Gabor Juhos Signed-off-by: Imre Kaloz Tested-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/core.h | 10 ++++++++++ drivers/net/wireless/ath9k/main.c | 9 +++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index 2256ba47dd4..8e93d11d57a 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -693,6 +693,10 @@ enum PROT_MODE { #define SC_OP_RFKILL_SW_BLOCKED BIT(12) #define SC_OP_RFKILL_HW_BLOCKED BIT(13) +struct ath_bus_ops { + void (*read_cachesize)(struct ath_softc *sc, int *csz); +}; + struct ath_softc { struct ieee80211_hw *hw; struct device *dev; @@ -743,6 +747,7 @@ struct ath_softc { #ifdef CONFIG_ATH9K_DEBUG struct ath9k_debug sc_debug; #endif + struct ath_bus_ops *bus_ops; }; int ath_reset(struct ath_softc *sc, bool retry_tx); @@ -750,4 +755,9 @@ int ath_get_hal_qnum(u16 queue, struct ath_softc *sc); int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); int ath_cabq_update(struct ath_softc *); +static inline void ath_read_cachesize(struct ath_softc *sc, int *csz) +{ + sc->bus_ops->read_cachesize(sc, csz); +} + #endif /* CORE_H */ diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index ebf0467674c..884469a3023 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -42,7 +42,7 @@ static void ath_detach(struct ath_softc *sc); /* return bus cachesize in 4B word units */ -static void bus_read_cachesize(struct ath_softc *sc, int *csz) +static void ath_pci_read_cachesize(struct ath_softc *sc, int *csz) { u8 u8tmp; @@ -1338,7 +1338,7 @@ static int ath_init(u16 devid, struct ath_softc *sc) * Cache line size is used to size and align various * structures used to communicate with the hardware. */ - bus_read_cachesize(sc, &csz); + ath_read_cachesize(sc, &csz); /* XXX assert csz is non-zero */ sc->sc_cachelsz = csz << 2; /* convert to bytes */ @@ -2534,6 +2534,10 @@ ath_rf_name(u16 rf_version) return "????"; } +static struct ath_bus_ops ath_pci_bus_ops = { + .read_cachesize = ath_pci_read_cachesize, +}; + static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { void __iomem *mem; @@ -2622,6 +2626,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) sc->hw = hw; sc->dev = &pdev->dev; sc->mem = mem; + sc->bus_ops = &ath_pci_bus_ops; if (ath_attach(id->device, sc) != 0) { ret = -ENODEV; -- GitLab From 39c3c2f2de6bccf698bfb5b9c4f56ddf99de0dbc Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Jan 2009 20:17:05 +0100 Subject: [PATCH 0851/4982] ath9k: introduce bus specific cleanup routine We have left only some PCI specific cleanup code. We have to convert them as well. Changes-licensed-under: ISC Signed-off-by: Gabor Juhos Signed-off-by: Imre Kaloz Tested-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/core.h | 7 ++++++ drivers/net/wireless/ath9k/main.c | 37 +++++++++++++++++++------------ 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index 8e93d11d57a..f9fa5c64c77 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -695,6 +695,7 @@ enum PROT_MODE { struct ath_bus_ops { void (*read_cachesize)(struct ath_softc *sc, int *csz); + void (*cleanup)(struct ath_softc *sc); }; struct ath_softc { @@ -704,6 +705,7 @@ struct ath_softc { struct tasklet_struct bcon_tasklet; struct ath_hal *sc_ah; void __iomem *mem; + int irq; spinlock_t sc_resetlock; struct mutex mutex; @@ -760,4 +762,9 @@ static inline void ath_read_cachesize(struct ath_softc *sc, int *csz) sc->bus_ops->read_cachesize(sc, csz); } +static inline void ath_bus_cleanup(struct ath_softc *sc) +{ + sc->bus_ops->cleanup(sc); +} + #endif /* CORE_H */ diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 884469a3023..dd2be2644ca 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -39,6 +39,7 @@ static struct pci_device_id ath_pci_id_table[] __devinitdata = { }; static void ath_detach(struct ath_softc *sc); +static void ath_cleanup(struct ath_softc *sc); /* return bus cachesize in 4B word units */ @@ -1267,13 +1268,7 @@ static int ath_start_rfkill_poll(struct ath_softc *sc) rfkill_free(sc->rf_kill.rfkill); /* Deinitialize the device */ - ath_detach(sc); - if (to_pci_dev(sc->dev)->irq) - free_irq(to_pci_dev(sc->dev)->irq, sc); - pci_iounmap(to_pci_dev(sc->dev), sc->mem); - pci_release_region(to_pci_dev(sc->dev), 0); - pci_disable_device(to_pci_dev(sc->dev)); - ieee80211_free_hw(sc->hw); + ath_cleanup(sc); return -EIO; } else { sc->sc_flags |= SC_OP_RFKILL_REGISTERED; @@ -1284,6 +1279,14 @@ static int ath_start_rfkill_poll(struct ath_softc *sc) } #endif /* CONFIG_RFKILL */ +static void ath_cleanup(struct ath_softc *sc) +{ + ath_detach(sc); + free_irq(sc->irq, sc); + ath_bus_cleanup(sc); + ieee80211_free_hw(sc->hw); +} + static void ath_detach(struct ath_softc *sc) { struct ieee80211_hw *hw = sc->hw; @@ -2534,8 +2537,18 @@ ath_rf_name(u16 rf_version) return "????"; } +static void ath_pci_cleanup(struct ath_softc *sc) +{ + struct pci_dev *pdev = to_pci_dev(sc->dev); + + pci_iounmap(pdev, sc->mem); + pci_release_region(pdev, 0); + pci_disable_device(pdev); +} + static struct ath_bus_ops ath_pci_bus_ops = { .read_cachesize = ath_pci_read_cachesize, + .cleanup = ath_pci_cleanup, }; static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) @@ -2642,6 +2655,8 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto bad4; } + sc->irq = pdev->irq; + ah = sc->sc_ah; printk(KERN_INFO "%s: Atheros AR%s MAC/BB Rev:%x " @@ -2672,13 +2687,7 @@ static void ath_pci_remove(struct pci_dev *pdev) struct ieee80211_hw *hw = pci_get_drvdata(pdev); struct ath_softc *sc = hw->priv; - ath_detach(sc); - if (pdev->irq) - free_irq(pdev->irq, sc); - pci_iounmap(pdev, sc->mem); - pci_release_region(pdev, 0); - pci_disable_device(pdev); - ieee80211_free_hw(hw); + ath_cleanup(sc); } #ifdef CONFIG_PM -- GitLab From 6baff7f9a6c571dcd9a59820e3c094f7490cb0fd Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Jan 2009 20:17:06 +0100 Subject: [PATCH 0852/4982] ath9k: move PCI code into separate file Now that we have converted all bus specific routines to replaceable, we can move the PCI specific codes into a separate file. Changes-licensed-under: ISC Signed-off-by: Gabor Juhos Signed-off-by: Imre Kaloz Tested-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/Makefile | 1 + drivers/net/wireless/ath9k/core.h | 19 +- drivers/net/wireless/ath9k/main.c | 300 ++-------------------------- drivers/net/wireless/ath9k/pci.c | 287 ++++++++++++++++++++++++++ 4 files changed, 328 insertions(+), 279 deletions(-) create mode 100644 drivers/net/wireless/ath9k/pci.c diff --git a/drivers/net/wireless/ath9k/Makefile b/drivers/net/wireless/ath9k/Makefile index 1209d14613a..af3f39bbddd 100644 --- a/drivers/net/wireless/ath9k/Makefile +++ b/drivers/net/wireless/ath9k/Makefile @@ -11,6 +11,7 @@ ath9k-y += hw.o \ xmit.o \ rc.o +ath9k-$(CONFIG_PCI) += pci.o ath9k-$(CONFIG_ATH9K_DEBUG) += debug.o obj-$(CONFIG_ATH9K) += ath9k.o diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index f9fa5c64c77..1e86a9cbe42 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -18,7 +18,7 @@ #define CORE_H #include -#include +#include #include #include #include @@ -767,4 +767,21 @@ static inline void ath_bus_cleanup(struct ath_softc *sc) sc->bus_ops->cleanup(sc); } +extern struct ieee80211_ops ath9k_ops; + +irqreturn_t ath_isr(int irq, void *dev); +void ath_cleanup(struct ath_softc *sc); +int ath_attach(u16 devid, struct ath_softc *sc); +void ath_detach(struct ath_softc *sc); +const char *ath_mac_bb_name(u32 mac_bb_version); +const char *ath_rf_name(u16 rf_version); + +#ifdef CONFIG_PCI +int ath_pci_init(void); +void ath_pci_exit(void); +#else +static inline int ath_pci_init(void) { return 0; }; +static inline void ath_pci_exit(void) {}; +#endif + #endif /* CORE_H */ diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index dd2be2644ca..6257790e49d 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -28,39 +28,6 @@ MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards."); MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards"); MODULE_LICENSE("Dual BSD/GPL"); -static struct pci_device_id ath_pci_id_table[] __devinitdata = { - { PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI */ - { PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */ - { PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */ - { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ - { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ - { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */ - { 0 } -}; - -static void ath_detach(struct ath_softc *sc); -static void ath_cleanup(struct ath_softc *sc); - -/* return bus cachesize in 4B word units */ - -static void ath_pci_read_cachesize(struct ath_softc *sc, int *csz) -{ - u8 u8tmp; - - pci_read_config_byte(to_pci_dev(sc->dev), PCI_CACHE_LINE_SIZE, - (u8 *)&u8tmp); - *csz = (int)u8tmp; - - /* - * This check was put in to avoid "unplesant" consequences if - * the bootrom has not fully initialized all PCI devices. - * Sometimes the cache line size register is not set - */ - - if (*csz == 0) - *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */ -} - static void ath_cache_conf_rate(struct ath_softc *sc, struct ieee80211_conf *conf) { @@ -500,7 +467,7 @@ static void ath9k_tasklet(unsigned long data) ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask); } -static irqreturn_t ath_isr(int irq, void *dev) +irqreturn_t ath_isr(int irq, void *dev) { struct ath_softc *sc = dev; struct ath_hal *ah = sc->sc_ah; @@ -1279,7 +1246,7 @@ static int ath_start_rfkill_poll(struct ath_softc *sc) } #endif /* CONFIG_RFKILL */ -static void ath_cleanup(struct ath_softc *sc) +void ath_cleanup(struct ath_softc *sc) { ath_detach(sc); free_irq(sc->irq, sc); @@ -1287,7 +1254,7 @@ static void ath_cleanup(struct ath_softc *sc) ieee80211_free_hw(sc->hw); } -static void ath_detach(struct ath_softc *sc) +void ath_detach(struct ath_softc *sc) { struct ieee80211_hw *hw = sc->hw; int i = 0; @@ -1541,7 +1508,7 @@ bad: return error; } -static int ath_attach(u16 devid, struct ath_softc *sc) +int ath_attach(u16 devid, struct ath_softc *sc) { struct ieee80211_hw *hw = sc->hw; int error = 0; @@ -2462,7 +2429,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, return ret; } -static struct ieee80211_ops ath9k_ops = { +struct ieee80211_ops ath9k_ops = { .tx = ath9k_tx, .start = ath9k_start, .stop = ath9k_stop, @@ -2506,7 +2473,7 @@ static struct { /* * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown. */ -static const char * +const char * ath_mac_bb_name(u32 mac_bb_version) { int i; @@ -2523,7 +2490,7 @@ ath_mac_bb_name(u32 mac_bb_version) /* * Return the RF name. "????" is returned if the RF is unknown. */ -static const char * +const char * ath_rf_name(u16 rf_version) { int i; @@ -2537,234 +2504,7 @@ ath_rf_name(u16 rf_version) return "????"; } -static void ath_pci_cleanup(struct ath_softc *sc) -{ - struct pci_dev *pdev = to_pci_dev(sc->dev); - - pci_iounmap(pdev, sc->mem); - pci_release_region(pdev, 0); - pci_disable_device(pdev); -} - -static struct ath_bus_ops ath_pci_bus_ops = { - .read_cachesize = ath_pci_read_cachesize, - .cleanup = ath_pci_cleanup, -}; - -static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - void __iomem *mem; - struct ath_softc *sc; - struct ieee80211_hw *hw; - u8 csz; - u32 val; - int ret = 0; - struct ath_hal *ah; - - if (pci_enable_device(pdev)) - return -EIO; - - ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - - if (ret) { - printk(KERN_ERR "ath9k: 32-bit DMA not available\n"); - goto bad; - } - - ret = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); - - if (ret) { - printk(KERN_ERR "ath9k: 32-bit DMA consistent " - "DMA enable failed\n"); - goto bad; - } - - /* - * Cache line size is used to size and align various - * structures used to communicate with the hardware. - */ - pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); - if (csz == 0) { - /* - * Linux 2.4.18 (at least) writes the cache line size - * register as a 16-bit wide register which is wrong. - * We must have this setup properly for rx buffer - * DMA to work so force a reasonable value here if it - * comes up zero. - */ - csz = L1_CACHE_BYTES / sizeof(u32); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); - } - /* - * The default setting of latency timer yields poor results, - * set it to the value used by other systems. It may be worth - * tweaking this setting more. - */ - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); - - pci_set_master(pdev); - - /* - * Disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state. - */ - pci_read_config_dword(pdev, 0x40, &val); - if ((val & 0x0000ff00) != 0) - pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); - - ret = pci_request_region(pdev, 0, "ath9k"); - if (ret) { - dev_err(&pdev->dev, "PCI memory region reserve error\n"); - ret = -ENODEV; - goto bad; - } - - mem = pci_iomap(pdev, 0, 0); - if (!mem) { - printk(KERN_ERR "PCI memory map error\n") ; - ret = -EIO; - goto bad1; - } - - hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops); - if (hw == NULL) { - printk(KERN_ERR "ath_pci: no memory for ieee80211_hw\n"); - goto bad2; - } - - SET_IEEE80211_DEV(hw, &pdev->dev); - pci_set_drvdata(pdev, hw); - - sc = hw->priv; - sc->hw = hw; - sc->dev = &pdev->dev; - sc->mem = mem; - sc->bus_ops = &ath_pci_bus_ops; - - if (ath_attach(id->device, sc) != 0) { - ret = -ENODEV; - goto bad3; - } - - /* setup interrupt service routine */ - - if (request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath", sc)) { - printk(KERN_ERR "%s: request_irq failed\n", - wiphy_name(hw->wiphy)); - ret = -EIO; - goto bad4; - } - - sc->irq = pdev->irq; - - ah = sc->sc_ah; - printk(KERN_INFO - "%s: Atheros AR%s MAC/BB Rev:%x " - "AR%s RF Rev:%x: mem=0x%lx, irq=%d\n", - wiphy_name(hw->wiphy), - ath_mac_bb_name(ah->ah_macVersion), - ah->ah_macRev, - ath_rf_name((ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR)), - ah->ah_phyRev, - (unsigned long)mem, pdev->irq); - - return 0; -bad4: - ath_detach(sc); -bad3: - ieee80211_free_hw(hw); -bad2: - pci_iounmap(pdev, mem); -bad1: - pci_release_region(pdev, 0); -bad: - pci_disable_device(pdev); - return ret; -} - -static void ath_pci_remove(struct pci_dev *pdev) -{ - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct ath_softc *sc = hw->priv; - - ath_cleanup(sc); -} - -#ifdef CONFIG_PM - -static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct ath_softc *sc = hw->priv; - - ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); - -#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) - if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) - cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); -#endif - - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -static int ath_pci_resume(struct pci_dev *pdev) -{ - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct ath_softc *sc = hw->priv; - u32 val; - int err; - - err = pci_enable_device(pdev); - if (err) - return err; - pci_restore_state(pdev); - /* - * Suspend/Resume resets the PCI configuration space, so we have to - * re-disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state - */ - pci_read_config_dword(pdev, 0x40, &val); - if ((val & 0x0000ff00) != 0) - pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); - - /* Enable LED */ - ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); - -#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) - /* - * check the h/w rfkill state on resume - * and start the rfkill poll timer - */ - if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) - queue_delayed_work(sc->hw->workqueue, - &sc->rf_kill.rfkill_poll, 0); -#endif - - return 0; -} - -#endif /* CONFIG_PM */ - -MODULE_DEVICE_TABLE(pci, ath_pci_id_table); - -static struct pci_driver ath_pci_driver = { - .name = "ath9k", - .id_table = ath_pci_id_table, - .probe = ath_pci_probe, - .remove = ath_pci_remove, -#ifdef CONFIG_PM - .suspend = ath_pci_suspend, - .resume = ath_pci_resume, -#endif /* CONFIG_PM */ -}; - -static int __init init_ath_pci(void) +static int __init ath9k_init(void) { int error; @@ -2776,26 +2516,30 @@ static int __init init_ath_pci(void) printk(KERN_ERR "Unable to register rate control algorithm: %d\n", error); - ath_rate_control_unregister(); - return error; + goto err_out; } - if (pci_register_driver(&ath_pci_driver) < 0) { + error = ath_pci_init(); + if (error < 0) { printk(KERN_ERR "ath_pci: No devices found, driver not installed.\n"); - ath_rate_control_unregister(); - pci_unregister_driver(&ath_pci_driver); - return -ENODEV; + error = -ENODEV; + goto err_rate_unregister; } return 0; + + err_rate_unregister: + ath_rate_control_unregister(); + err_out: + return error; } -module_init(init_ath_pci); +module_init(ath9k_init); -static void __exit exit_ath_pci(void) +static void __exit ath9k_exit(void) { + ath_pci_exit(); ath_rate_control_unregister(); - pci_unregister_driver(&ath_pci_driver); printk(KERN_INFO "%s: Driver unloaded\n", dev_info); } -module_exit(exit_ath_pci); +module_exit(ath9k_exit); diff --git a/drivers/net/wireless/ath9k/pci.c b/drivers/net/wireless/ath9k/pci.c new file mode 100644 index 00000000000..4ff1caa9ba9 --- /dev/null +++ b/drivers/net/wireless/ath9k/pci.c @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2008 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include "core.h" +#include "reg.h" +#include "hw.h" + +static struct pci_device_id ath_pci_id_table[] __devinitdata = { + { PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI */ + { PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */ + { PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */ + { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ + { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ + { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */ + { 0 } +}; + +/* return bus cachesize in 4B word units */ +static void ath_pci_read_cachesize(struct ath_softc *sc, int *csz) +{ + u8 u8tmp; + + pci_read_config_byte(to_pci_dev(sc->dev), PCI_CACHE_LINE_SIZE, + (u8 *)&u8tmp); + *csz = (int)u8tmp; + + /* + * This check was put in to avoid "unplesant" consequences if + * the bootrom has not fully initialized all PCI devices. + * Sometimes the cache line size register is not set + */ + + if (*csz == 0) + *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */ +} + +static void ath_pci_cleanup(struct ath_softc *sc) +{ + struct pci_dev *pdev = to_pci_dev(sc->dev); + + pci_iounmap(pdev, sc->mem); + pci_release_region(pdev, 0); + pci_disable_device(pdev); +} + +static struct ath_bus_ops ath_pci_bus_ops = { + .read_cachesize = ath_pci_read_cachesize, + .cleanup = ath_pci_cleanup, +}; + +static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + void __iomem *mem; + struct ath_softc *sc; + struct ieee80211_hw *hw; + u8 csz; + u32 val; + int ret = 0; + struct ath_hal *ah; + + if (pci_enable_device(pdev)) + return -EIO; + + ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + + if (ret) { + printk(KERN_ERR "ath9k: 32-bit DMA not available\n"); + goto bad; + } + + ret = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + + if (ret) { + printk(KERN_ERR "ath9k: 32-bit DMA consistent " + "DMA enable failed\n"); + goto bad; + } + + /* + * Cache line size is used to size and align various + * structures used to communicate with the hardware. + */ + pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); + if (csz == 0) { + /* + * Linux 2.4.18 (at least) writes the cache line size + * register as a 16-bit wide register which is wrong. + * We must have this setup properly for rx buffer + * DMA to work so force a reasonable value here if it + * comes up zero. + */ + csz = L1_CACHE_BYTES / sizeof(u32); + pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); + } + /* + * The default setting of latency timer yields poor results, + * set it to the value used by other systems. It may be worth + * tweaking this setting more. + */ + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); + + pci_set_master(pdev); + + /* + * Disable the RETRY_TIMEOUT register (0x41) to keep + * PCI Tx retries from interfering with C3 CPU state. + */ + pci_read_config_dword(pdev, 0x40, &val); + if ((val & 0x0000ff00) != 0) + pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); + + ret = pci_request_region(pdev, 0, "ath9k"); + if (ret) { + dev_err(&pdev->dev, "PCI memory region reserve error\n"); + ret = -ENODEV; + goto bad; + } + + mem = pci_iomap(pdev, 0, 0); + if (!mem) { + printk(KERN_ERR "PCI memory map error\n") ; + ret = -EIO; + goto bad1; + } + + hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops); + if (hw == NULL) { + printk(KERN_ERR "ath_pci: no memory for ieee80211_hw\n"); + goto bad2; + } + + SET_IEEE80211_DEV(hw, &pdev->dev); + pci_set_drvdata(pdev, hw); + + sc = hw->priv; + sc->hw = hw; + sc->dev = &pdev->dev; + sc->mem = mem; + sc->bus_ops = &ath_pci_bus_ops; + + if (ath_attach(id->device, sc) != 0) { + ret = -ENODEV; + goto bad3; + } + + /* setup interrupt service routine */ + + if (request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath", sc)) { + printk(KERN_ERR "%s: request_irq failed\n", + wiphy_name(hw->wiphy)); + ret = -EIO; + goto bad4; + } + + sc->irq = pdev->irq; + + ah = sc->sc_ah; + printk(KERN_INFO + "%s: Atheros AR%s MAC/BB Rev:%x " + "AR%s RF Rev:%x: mem=0x%lx, irq=%d\n", + wiphy_name(hw->wiphy), + ath_mac_bb_name(ah->ah_macVersion), + ah->ah_macRev, + ath_rf_name((ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR)), + ah->ah_phyRev, + (unsigned long)mem, pdev->irq); + + return 0; +bad4: + ath_detach(sc); +bad3: + ieee80211_free_hw(hw); +bad2: + pci_iounmap(pdev, mem); +bad1: + pci_release_region(pdev, 0); +bad: + pci_disable_device(pdev); + return ret; +} + +static void ath_pci_remove(struct pci_dev *pdev) +{ + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct ath_softc *sc = hw->priv; + + ath_cleanup(sc); +} + +#ifdef CONFIG_PM + +static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct ath_softc *sc = hw->priv; + + ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); + +#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) + if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) + cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); +#endif + + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, PCI_D3hot); + + return 0; +} + +static int ath_pci_resume(struct pci_dev *pdev) +{ + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct ath_softc *sc = hw->priv; + u32 val; + int err; + + err = pci_enable_device(pdev); + if (err) + return err; + pci_restore_state(pdev); + /* + * Suspend/Resume resets the PCI configuration space, so we have to + * re-disable the RETRY_TIMEOUT register (0x41) to keep + * PCI Tx retries from interfering with C3 CPU state + */ + pci_read_config_dword(pdev, 0x40, &val); + if ((val & 0x0000ff00) != 0) + pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); + + /* Enable LED */ + ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); + +#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) + /* + * check the h/w rfkill state on resume + * and start the rfkill poll timer + */ + if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) + queue_delayed_work(sc->hw->workqueue, + &sc->rf_kill.rfkill_poll, 0); +#endif + + return 0; +} + +#endif /* CONFIG_PM */ + +MODULE_DEVICE_TABLE(pci, ath_pci_id_table); + +static struct pci_driver ath_pci_driver = { + .name = "ath9k", + .id_table = ath_pci_id_table, + .probe = ath_pci_probe, + .remove = ath_pci_remove, +#ifdef CONFIG_PM + .suspend = ath_pci_suspend, + .resume = ath_pci_resume, +#endif /* CONFIG_PM */ +}; + +int __init ath_pci_init(void) +{ + return pci_register_driver(&ath_pci_driver); +} + +void ath_pci_exit(void) +{ + pci_unregister_driver(&ath_pci_driver); +} -- GitLab From 09329d371e57ff9fcb645b8e2cdee1ec8b9b539f Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Jan 2009 20:17:07 +0100 Subject: [PATCH 0853/4982] ath9k: introduce platform driver for AHB bus support This patch adds the platform_driver itself, and modifies the main driver to register it. Changes-licensed-under: ISC Signed-off-by: Gabor Juhos Signed-off-by: Imre Kaloz Tested-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/Makefile | 1 + drivers/net/wireless/ath9k/ahb.c | 160 ++++++++++++++++++++++++++++ drivers/net/wireless/ath9k/core.h | 8 ++ drivers/net/wireless/ath9k/main.c | 10 ++ 4 files changed, 179 insertions(+) create mode 100644 drivers/net/wireless/ath9k/ahb.c diff --git a/drivers/net/wireless/ath9k/Makefile b/drivers/net/wireless/ath9k/Makefile index af3f39bbddd..00629587b79 100644 --- a/drivers/net/wireless/ath9k/Makefile +++ b/drivers/net/wireless/ath9k/Makefile @@ -12,6 +12,7 @@ ath9k-y += hw.o \ rc.o ath9k-$(CONFIG_PCI) += pci.o +ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o ath9k-$(CONFIG_ATH9K_DEBUG) += debug.o obj-$(CONFIG_ATH9K) += ath9k.o diff --git a/drivers/net/wireless/ath9k/ahb.c b/drivers/net/wireless/ath9k/ahb.c new file mode 100644 index 00000000000..8cbd4c2a7fa --- /dev/null +++ b/drivers/net/wireless/ath9k/ahb.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2009 Gabor Juhos + * Copyright (c) 2009 Imre Kaloz + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include "core.h" +#include "reg.h" +#include "hw.h" + +/* return bus cachesize in 4B word units */ +static void ath_ahb_read_cachesize(struct ath_softc *sc, int *csz) +{ + *csz = L1_CACHE_BYTES >> 2; +} + +static void ath_ahb_cleanup(struct ath_softc *sc) +{ + iounmap(sc->mem); +} + +static struct ath_bus_ops ath_ahb_bus_ops = { + .read_cachesize = ath_ahb_read_cachesize, + .cleanup = ath_ahb_cleanup, +}; + +static int ath_ahb_probe(struct platform_device *pdev) +{ + void __iomem *mem; + struct ath_softc *sc; + struct ieee80211_hw *hw; + struct resource *res; + int irq; + int ret = 0; + struct ath_hal *ah; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, "no memory resource found\n"); + ret = -ENXIO; + goto err_out; + } + + mem = ioremap_nocache(res->start, res->end - res->start + 1); + if (mem == NULL) { + dev_err(&pdev->dev, "ioremap failed\n"); + ret = -ENOMEM; + goto err_out; + } + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (res == NULL) { + dev_err(&pdev->dev, "no IRQ resource found\n"); + ret = -ENXIO; + goto err_iounmap; + } + + irq = res->start; + + hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops); + if (hw == NULL) { + dev_err(&pdev->dev, "no memory for ieee80211_hw\n"); + ret = -ENOMEM; + goto err_iounmap; + } + + SET_IEEE80211_DEV(hw, &pdev->dev); + platform_set_drvdata(pdev, hw); + + sc = hw->priv; + sc->hw = hw; + sc->dev = &pdev->dev; + sc->mem = mem; + sc->bus_ops = &ath_ahb_bus_ops; + sc->irq = irq; + + ret = ath_attach(AR5416_AR9100_DEVID, sc); + if (ret != 0) { + dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret); + ret = -ENODEV; + goto err_free_hw; + } + + ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc); + if (ret) { + dev_err(&pdev->dev, "request_irq failed, err=%d\n", ret); + ret = -EIO; + goto err_detach; + } + + ah = sc->sc_ah; + printk(KERN_INFO + "%s: Atheros AR%s MAC/BB Rev:%x, " + "AR%s RF Rev:%x, mem=0x%lx, irq=%d\n", + wiphy_name(hw->wiphy), + ath_mac_bb_name(ah->ah_macVersion), + ah->ah_macRev, + ath_rf_name((ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR)), + ah->ah_phyRev, + (unsigned long)mem, irq); + + return 0; + + err_detach: + ath_detach(sc); + err_free_hw: + ieee80211_free_hw(hw); + platform_set_drvdata(pdev, NULL); + err_iounmap: + iounmap(mem); + err_out: + return ret; +} + +static int ath_ahb_remove(struct platform_device *pdev) +{ + struct ieee80211_hw *hw = platform_get_drvdata(pdev); + + if (hw) { + struct ath_softc *sc = hw->priv; + + ath_cleanup(sc); + platform_set_drvdata(pdev, NULL); + } + + return 0; +} + +static struct platform_driver ath_ahb_driver = { + .probe = ath_ahb_probe, + .remove = ath_ahb_remove, + .driver = { + .name = "ath9k", + .owner = THIS_MODULE, + }, +}; + +int ath_ahb_init(void) +{ + return platform_driver_register(&ath_ahb_driver); +} + +void ath_ahb_exit(void) +{ + platform_driver_unregister(&ath_ahb_driver); +} diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index 1e86a9cbe42..c5dae11d608 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -784,4 +784,12 @@ static inline int ath_pci_init(void) { return 0; }; static inline void ath_pci_exit(void) {}; #endif +#ifdef CONFIG_ATHEROS_AR71XX +int ath_ahb_init(void); +void ath_ahb_exit(void); +#else +static inline int ath_ahb_init(void) { return 0; }; +static inline void ath_ahb_exit(void) {}; +#endif + #endif /* CORE_H */ diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 6257790e49d..7f4d1bbaf6c 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -2527,8 +2527,17 @@ static int __init ath9k_init(void) goto err_rate_unregister; } + error = ath_ahb_init(); + if (error < 0) { + error = -ENODEV; + goto err_pci_exit; + } + return 0; + err_pci_exit: + ath_pci_exit(); + err_rate_unregister: ath_rate_control_unregister(); err_out: @@ -2538,6 +2547,7 @@ module_init(ath9k_init); static void __exit ath9k_exit(void) { + ath_ahb_exit(); ath_pci_exit(); ath_rate_control_unregister(); printk(KERN_INFO "%s: Driver unloaded\n", dev_info); -- GitLab From 9dbeb91a8b97e2892c04461e28d2bdd0198b719d Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Jan 2009 20:17:08 +0100 Subject: [PATCH 0854/4982] ath9k: get EEPROM contents from platform data on AHB bus On the AR913x SOCs we have to provide EEPROM contents via platform_data, because accessing the flash via MMIO is not safe. Additionally different boards may store the radio calibration data at different locations. Changes-licensed-under: ISC Signed-off-by: Gabor Juhos Signed-off-by: Imre Kaloz Tested-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ahb.c | 27 +++++++++++++++ drivers/net/wireless/ath9k/core.h | 1 + drivers/net/wireless/ath9k/eeprom.c | 51 ++--------------------------- drivers/net/wireless/ath9k/pci.c | 18 ++++++++++ include/linux/ath9k_platform.h | 28 ++++++++++++++++ 5 files changed, 77 insertions(+), 48 deletions(-) create mode 100644 include/linux/ath9k_platform.h diff --git a/drivers/net/wireless/ath9k/ahb.c b/drivers/net/wireless/ath9k/ahb.c index 8cbd4c2a7fa..7f2c3a09bca 100644 --- a/drivers/net/wireless/ath9k/ahb.c +++ b/drivers/net/wireless/ath9k/ahb.c @@ -18,6 +18,7 @@ #include #include +#include #include "core.h" #include "reg.h" #include "hw.h" @@ -33,9 +34,29 @@ static void ath_ahb_cleanup(struct ath_softc *sc) iounmap(sc->mem); } +static bool ath_ahb_eeprom_read(struct ath_hal *ah, u32 off, u16 *data) +{ + struct ath_softc *sc = ah->ah_sc; + struct platform_device *pdev = to_platform_device(sc->dev); + struct ath9k_platform_data *pdata; + + pdata = (struct ath9k_platform_data *) pdev->dev.platform_data; + if (off >= (ARRAY_SIZE(pdata->eeprom_data))) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "%s: flash read failed, offset %08x is out of range\n", + __func__, off); + return false; + } + + *data = pdata->eeprom_data[off]; + return true; +} + static struct ath_bus_ops ath_ahb_bus_ops = { .read_cachesize = ath_ahb_read_cachesize, .cleanup = ath_ahb_cleanup, + + .eeprom_read = ath_ahb_eeprom_read, }; static int ath_ahb_probe(struct platform_device *pdev) @@ -48,6 +69,12 @@ static int ath_ahb_probe(struct platform_device *pdev) int ret = 0; struct ath_hal *ah; + if (!pdev->dev.platform_data) { + dev_err(&pdev->dev, "no platform data specified\n"); + ret = -EINVAL; + goto err_out; + } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { dev_err(&pdev->dev, "no memory resource found\n"); diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index c5dae11d608..b687ae9c9e1 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -696,6 +696,7 @@ enum PROT_MODE { struct ath_bus_ops { void (*read_cachesize)(struct ath_softc *sc, int *csz); void (*cleanup)(struct ath_softc *sc); + bool (*eeprom_read)(struct ath_hal *ah, u32 off, u16 *data); }; struct ath_softc { diff --git a/drivers/net/wireless/ath9k/eeprom.c b/drivers/net/wireless/ath9k/eeprom.c index 1ef8b5a70e5..50cb3883416 100644 --- a/drivers/net/wireless/ath9k/eeprom.c +++ b/drivers/net/wireless/ath9k/eeprom.c @@ -91,53 +91,11 @@ static inline bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, return false; } -static bool ath9k_hw_eeprom_read(struct ath_hal *ah, u32 off, u16 *data) -{ - (void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); - - if (!ath9k_hw_wait(ah, - AR_EEPROM_STATUS_DATA, - AR_EEPROM_STATUS_DATA_BUSY | - AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0)) { - return false; - } - - *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA), - AR_EEPROM_STATUS_DATA_VAL); - - return true; -} - -static int ath9k_hw_flash_map(struct ath_hal *ah) -{ - struct ath_hal_5416 *ahp = AH5416(ah); - - ahp->ah_cal_mem = ioremap(AR5416_EEPROM_START_ADDR, AR5416_EEPROM_MAX); - - if (!ahp->ah_cal_mem) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "cannot remap eeprom region \n"); - return -EIO; - } - - return 0; -} - -static bool ath9k_hw_flash_read(struct ath_hal *ah, u32 off, u16 *data) -{ - struct ath_hal_5416 *ahp = AH5416(ah); - - *data = ioread16(ahp->ah_cal_mem + off); - - return true; -} - static inline bool ath9k_hw_nvram_read(struct ath_hal *ah, u32 off, u16 *data) { - if (ath9k_hw_use_flash(ah)) - return ath9k_hw_flash_read(ah, off, data); - else - return ath9k_hw_eeprom_read(ah, off, data); + struct ath_softc *sc = ah->ah_sc; + + return sc->bus_ops->eeprom_read(ah, off, data); } static bool ath9k_hw_fill_4k_eeprom(struct ath_hal *ah) @@ -2825,9 +2783,6 @@ int ath9k_hw_eeprom_attach(struct ath_hal *ah) int status; struct ath_hal_5416 *ahp = AH5416(ah); - if (ath9k_hw_use_flash(ah)) - ath9k_hw_flash_map(ah); - if (AR_SREV_9285(ah)) ahp->ah_eep_map = EEP_MAP_4KBITS; else diff --git a/drivers/net/wireless/ath9k/pci.c b/drivers/net/wireless/ath9k/pci.c index 4ff1caa9ba9..05612bf2836 100644 --- a/drivers/net/wireless/ath9k/pci.c +++ b/drivers/net/wireless/ath9k/pci.c @@ -58,9 +58,27 @@ static void ath_pci_cleanup(struct ath_softc *sc) pci_disable_device(pdev); } +static bool ath_pci_eeprom_read(struct ath_hal *ah, u32 off, u16 *data) +{ + (void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); + + if (!ath9k_hw_wait(ah, + AR_EEPROM_STATUS_DATA, + AR_EEPROM_STATUS_DATA_BUSY | + AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0)) { + return false; + } + + *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA), + AR_EEPROM_STATUS_DATA_VAL); + + return true; +} + static struct ath_bus_ops ath_pci_bus_ops = { .read_cachesize = ath_pci_read_cachesize, .cleanup = ath_pci_cleanup, + .eeprom_read = ath_pci_eeprom_read, }; static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) diff --git a/include/linux/ath9k_platform.h b/include/linux/ath9k_platform.h new file mode 100644 index 00000000000..b847fc7b93f --- /dev/null +++ b/include/linux/ath9k_platform.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2009 Gabor Juhos + * Copyright (c) 2009 Imre Kaloz + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _LINUX_ATH9K_PLATFORM_H +#define _LINUX_ATH9K_PLATFORM_H + +#define ATH9K_PLAT_EEP_MAX_WORDS 2048 + +struct ath9k_platform_data { + u16 eeprom_data[ATH9K_PLAT_EEP_MAX_WORDS]; +}; + +#endif /* _LINUX_ATH9K_PLATFORM_H */ -- GitLab From d03a66c17ab94f7cfec9b343d415111386216847 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Jan 2009 20:17:09 +0100 Subject: [PATCH 0855/4982] ath9k: remove (u16) casts from rtc register access The RTC register offsets don't fit into 'u16' on the AR913x, so we have to remove the existing casts. Changes-licensed-under: ISC Signed-off-by: Gabor Juhos Signed-off-by: Imre Kaloz Tested-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/hw.c | 14 +++++++------- drivers/net/wireless/ath9k/reg.h | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 55ed0830588..ed731b9cac8 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -1011,7 +1011,7 @@ static void ath9k_hw_init_pll(struct ath_hal *ah, pll |= SM(0xb, AR_RTC_PLL_DIV); } } - REG_WRITE(ah, (u16) (AR_RTC_PLL_CONTROL), pll); + REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); udelay(RTC_PLL_SETTLE_DELAY); @@ -1550,11 +1550,11 @@ static bool ath9k_hw_set_reset(struct ath_hal *ah, int type) rst_flags |= AR_RTC_RC_MAC_COLD; } - REG_WRITE(ah, (u16) (AR_RTC_RC), rst_flags); + REG_WRITE(ah, AR_RTC_RC, rst_flags); udelay(50); - REG_WRITE(ah, (u16) (AR_RTC_RC), 0); - if (!ath9k_hw_wait(ah, (u16) (AR_RTC_RC), AR_RTC_RC_M, 0)) { + REG_WRITE(ah, AR_RTC_RC, 0); + if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0)) { DPRINTF(ah->ah_sc, ATH_DBG_RESET, "RTC stuck in MAC reset\n"); return false; @@ -1576,8 +1576,8 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hal *ah) REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); - REG_WRITE(ah, (u16) (AR_RTC_RESET), 0); - REG_WRITE(ah, (u16) (AR_RTC_RESET), 1); + REG_WRITE(ah, AR_RTC_RESET, 0); + REG_WRITE(ah, AR_RTC_RESET, 1); if (!ath9k_hw_wait(ah, AR_RTC_STATUS, @@ -2619,7 +2619,7 @@ static void ath9k_set_power_sleep(struct ath_hal *ah, int setChip) if (!AR_SREV_9100(ah)) REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); - REG_CLR_BIT(ah, (u16) (AR_RTC_RESET), + REG_CLR_BIT(ah, (AR_RTC_RESET), AR_RTC_RESET_EN); } } diff --git a/drivers/net/wireless/ath9k/reg.h b/drivers/net/wireless/ath9k/reg.h index 2dffe371ffe..150eda56055 100644 --- a/drivers/net/wireless/ath9k/reg.h +++ b/drivers/net/wireless/ath9k/reg.h @@ -953,7 +953,7 @@ enum { #define AR_RTC_BASE 0x00020000 #define AR_RTC_RC \ - (AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0000) : 0x7000 + ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0000) : 0x7000) #define AR_RTC_RC_M 0x00000003 #define AR_RTC_RC_MAC_WARM 0x00000001 #define AR_RTC_RC_MAC_COLD 0x00000002 @@ -961,7 +961,7 @@ enum { #define AR_RTC_RC_WARM_RESET 0x00000008 #define AR_RTC_PLL_CONTROL \ - (AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0014) : 0x7014 + ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0014) : 0x7014) #define AR_RTC_PLL_DIV 0x0000001f #define AR_RTC_PLL_DIV_S 0 -- GitLab From 1975ef2039c63f58e6c80861a24236bcd0483aa9 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Jan 2009 20:17:10 +0100 Subject: [PATCH 0856/4982] ath9k: fix ar5416Addac_9100 values Writing the register at offset 0x98c4 causes a deadlock on the AR913x SoCs. Although i don't have detailed knowledge about these registers, but if i change the register offset according to the 'ar5416Addac' table, it works. Additionally there is no reference to the 0x98c4 elsewhere. Changes-licensed-under: ISC Signed-off-by: Gabor Juhos Signed-off-by: Imre Kaloz Tested-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/initvals.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath9k/initvals.h b/drivers/net/wireless/ath9k/initvals.h index a1bc6312dcc..d49236368a1 100644 --- a/drivers/net/wireless/ath9k/initvals.h +++ b/drivers/net/wireless/ath9k/initvals.h @@ -658,7 +658,7 @@ static const u32 ar5416Addac_9100[][2] = { {0x0000989c, 0x00000000 }, {0x0000989c, 0x00000000 }, {0x0000989c, 0x00000000 }, - {0x000098c4, 0x00000000 }, + {0x000098cc, 0x00000000 }, }; static const u32 ar5416Modes[][6] = { -- GitLab From 9950688263dcd74560582f590d270728f4e92ed0 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Jan 2009 20:17:11 +0100 Subject: [PATCH 0857/4982] ath9k: fix null pointer dereference in ani monitor code In 'ath9k_ani_reset' the 'ahp->ah_curani' will be initialized only if 'DO_ANI(ah)' true. In 'ath9k_hw_ani_monitor' we are using 'ahp->ah_curani' unconditionally, and it will cause a NULL pointer dereference on AR9100. Changes-licensed-under: ISC Signed-off-by: Gabor Juhos Signed-off-by: Imre Kaloz Tested-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ani.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath9k/ani.c b/drivers/net/wireless/ath9k/ani.c index 4dd086073ad..42197fff2a4 100644 --- a/drivers/net/wireless/ath9k/ani.c +++ b/drivers/net/wireless/ath9k/ani.c @@ -551,6 +551,9 @@ void ath9k_hw_ani_monitor(struct ath_hal *ah, struct ar5416AniState *aniState; int32_t listenTime; + if (!DO_ANI(ah)) + return; + aniState = ahp->ah_curani; ahp->ah_stats.ast_nodestats = *stats; @@ -610,9 +613,6 @@ void ath9k_hw_ani_monitor(struct ath_hal *ah, aniState->cckPhyErrCount = cckPhyErrCnt; } - if (!DO_ANI(ah)) - return; - if (aniState->listenTime > 5 * ahp->ah_aniPeriod) { if (aniState->ofdmPhyErrCount <= aniState->listenTime * aniState->ofdmTrigLow / 1000 && -- GitLab From 0c1aa495961f03c964b3287cf5800217cf6f2cee Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Jan 2009 20:17:12 +0100 Subject: [PATCH 0858/4982] ath9k: enable support for AR9100 Because we have support for the AR9100 devices now, we can enable them. Changes-licensed-under: ISC Signed-off-by: Gabor Juhos Signed-off-by: Imre Kaloz Tested-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/hw.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index ed731b9cac8..88c8a62e1b8 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -377,6 +377,8 @@ static const char *ath9k_hw_devname(u16 devid) return "Atheros 5418"; case AR9160_DEVID_PCI: return "Atheros 9160"; + case AR5416_AR9100_DEVID: + return "Atheros 9100"; case AR9280_DEVID_PCI: case AR9280_DEVID_PCIE: return "Atheros 9280"; @@ -1179,6 +1181,7 @@ struct ath_hal *ath9k_hw_attach(u16 devid, struct ath_softc *sc, switch (devid) { case AR5416_DEVID_PCI: case AR5416_DEVID_PCIE: + case AR5416_AR9100_DEVID: case AR9160_DEVID_PCI: case AR9280_DEVID_PCI: case AR9280_DEVID_PCIE: -- GitLab From 9aed3cc124343d92be6697e9af3928bdfe8eb03e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 13 Jan 2009 16:03:29 +0200 Subject: [PATCH 0859/4982] nl80211: New command for adding extra IE(s) into management frames A new nl80211 command, NL80211_CMD_SET_MGMT_EXTRA_IE, can be used to add arbitrary IE data into the end of management frames. The interface allows extra IEs to be configured for each management frame subtype, but only some of them (ProbeReq, ProbeResp, Auth, (Re)AssocReq, Deauth, Disassoc) are currently accepted in mac80211 implementation. This makes it easier to implement IEEE 802.11 extensions like WPS and FT that add IE(s) into some management frames. In addition, this can be useful for testing and experimentation purposes. Signed-off-by: Jouni Malinen Acked-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/nl80211.h | 22 ++++++++++ include/net/cfg80211.h | 26 ++++++++++++ net/mac80211/cfg.c | 82 ++++++++++++++++++++++++++++++++++++++ net/mac80211/ieee80211_i.h | 16 ++++++++ net/mac80211/iface.c | 7 ++++ net/mac80211/mlme.c | 52 +++++++++++++++++++++--- net/wireless/nl80211.c | 47 ++++++++++++++++++++++ 7 files changed, 246 insertions(+), 6 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 4e7a7986a52..76aae3d8e97 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -133,6 +133,14 @@ * @NL80211_CMD_SET_MESH_PARAMS: Set mesh networking properties for the * interface identified by %NL80211_ATTR_IFINDEX * + * @NL80211_CMD_SET_MGMT_EXTRA_IE: Set extra IEs for management frames. The + * interface is identified with %NL80211_ATTR_IFINDEX and the management + * frame subtype with %NL80211_ATTR_MGMT_SUBTYPE. The extra IE data to be + * added to the end of the specified management frame is specified with + * %NL80211_ATTR_IE. If the command succeeds, the requested data will be + * added to all specified management frames generated by + * kernel/firmware/driver. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -178,6 +186,8 @@ enum nl80211_commands { NL80211_CMD_GET_MESH_PARAMS, NL80211_CMD_SET_MESH_PARAMS, + NL80211_CMD_SET_MGMT_EXTRA_IE, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -190,6 +200,7 @@ enum nl80211_commands { * here */ #define NL80211_CMD_SET_BSS NL80211_CMD_SET_BSS +#define NL80211_CMD_SET_MGMT_EXTRA_IE NL80211_CMD_SET_MGMT_EXTRA_IE /** * enum nl80211_attrs - nl80211 netlink attributes @@ -284,6 +295,12 @@ enum nl80211_commands { * supported interface types, each a flag attribute with the number * of the interface mode. * + * @NL80211_ATTR_MGMT_SUBTYPE: Management frame subtype for + * %NL80211_CMD_SET_MGMT_EXTRA_IE. + * + * @NL80211_ATTR_IE: Information element(s) data (used, e.g., with + * %NL80211_CMD_SET_MGMT_EXTRA_IE). + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -348,6 +365,9 @@ enum nl80211_attrs { NL80211_ATTR_KEY_DEFAULT_MGMT, + NL80211_ATTR_MGMT_SUBTYPE, + NL80211_ATTR_IE, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -363,6 +383,8 @@ enum nl80211_attrs { #define NL80211_ATTR_WIPHY_TXQ_PARAMS NL80211_ATTR_WIPHY_TXQ_PARAMS #define NL80211_ATTR_WIPHY_FREQ NL80211_ATTR_WIPHY_FREQ #define NL80211_ATTR_WIPHY_CHANNEL_TYPE NL80211_ATTR_WIPHY_CHANNEL_TYPE +#define NL80211_ATTR_MGMT_SUBTYPE NL80211_ATTR_MGMT_SUBTYPE +#define NL80211_ATTR_IE NL80211_ATTR_IE #define NL80211_MAX_SUPP_RATES 32 #define NL80211_MAX_SUPP_REG_RULES 32 diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index df78abc496f..c7da88fb15b 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -433,6 +433,26 @@ struct ieee80211_txq_params { u8 aifs; }; +/** + * struct mgmt_extra_ie_params - Extra management frame IE parameters + * + * Used to add extra IE(s) into management frames. If the driver cannot add the + * requested data into all management frames of the specified subtype that are + * generated in kernel or firmware/hardware, it must reject the configuration + * call. The IE data buffer is added to the end of the specified management + * frame body after all other IEs. This addition is not applied to frames that + * are injected through a monitor interface. + * + * @subtype: Management frame subtype + * @ies: IE data buffer or %NULL to remove previous data + * @ies_len: Length of @ies in octets + */ +struct mgmt_extra_ie_params { + u8 subtype; + u8 *ies; + int ies_len; +}; + /* from net/wireless.h */ struct wiphy; @@ -501,6 +521,8 @@ struct ieee80211_channel; * @set_txq_params: Set TX queue parameters * * @set_channel: Set channel + * + * @set_mgmt_extra_ie: Set extra IE data for management frames */ struct cfg80211_ops { int (*add_virtual_intf)(struct wiphy *wiphy, char *name, @@ -571,6 +593,10 @@ struct cfg80211_ops { int (*set_channel)(struct wiphy *wiphy, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type); + + int (*set_mgmt_extra_ie)(struct wiphy *wiphy, + struct net_device *dev, + struct mgmt_extra_ie_params *params); }; /* temporary wext handlers */ diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 72c10691543..d1ac3ab2c51 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1175,6 +1175,87 @@ static int ieee80211_set_channel(struct wiphy *wiphy, return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); } +static int set_mgmt_extra_ie_sta(struct ieee80211_if_sta *ifsta, u8 subtype, + u8 *ies, size_t ies_len) +{ + switch (subtype) { + case IEEE80211_STYPE_PROBE_REQ >> 4: + kfree(ifsta->ie_probereq); + ifsta->ie_probereq = ies; + ifsta->ie_probereq_len = ies_len; + return 0; + case IEEE80211_STYPE_PROBE_RESP >> 4: + kfree(ifsta->ie_proberesp); + ifsta->ie_proberesp = ies; + ifsta->ie_proberesp_len = ies_len; + return 0; + case IEEE80211_STYPE_AUTH >> 4: + kfree(ifsta->ie_auth); + ifsta->ie_auth = ies; + ifsta->ie_auth_len = ies_len; + return 0; + case IEEE80211_STYPE_ASSOC_REQ >> 4: + kfree(ifsta->ie_assocreq); + ifsta->ie_assocreq = ies; + ifsta->ie_assocreq_len = ies_len; + return 0; + case IEEE80211_STYPE_REASSOC_REQ >> 4: + kfree(ifsta->ie_reassocreq); + ifsta->ie_reassocreq = ies; + ifsta->ie_reassocreq_len = ies_len; + return 0; + case IEEE80211_STYPE_DEAUTH >> 4: + kfree(ifsta->ie_deauth); + ifsta->ie_deauth = ies; + ifsta->ie_deauth_len = ies_len; + return 0; + case IEEE80211_STYPE_DISASSOC >> 4: + kfree(ifsta->ie_disassoc); + ifsta->ie_disassoc = ies; + ifsta->ie_disassoc_len = ies_len; + return 0; + } + + return -EOPNOTSUPP; +} + +static int ieee80211_set_mgmt_extra_ie(struct wiphy *wiphy, + struct net_device *dev, + struct mgmt_extra_ie_params *params) +{ + struct ieee80211_sub_if_data *sdata; + u8 *ies; + size_t ies_len; + int ret = -EOPNOTSUPP; + + if (params->ies) { + ies = kmemdup(params->ies, params->ies_len, GFP_KERNEL); + if (ies == NULL) + return -ENOMEM; + ies_len = params->ies_len; + } else { + ies = NULL; + ies_len = 0; + } + + sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + switch (sdata->vif.type) { + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + ret = set_mgmt_extra_ie_sta(&sdata->u.sta, params->subtype, + ies, ies_len); + break; + default: + ret = -EOPNOTSUPP; + break; + } + + if (ret) + kfree(ies); + return ret; +} + struct cfg80211_ops mac80211_config_ops = { .add_virtual_intf = ieee80211_add_iface, .del_virtual_intf = ieee80211_del_iface, @@ -1204,4 +1285,5 @@ struct cfg80211_ops mac80211_config_ops = { .change_bss = ieee80211_change_bss, .set_txq_params = ieee80211_set_txq_params, .set_channel = ieee80211_set_channel, + .set_mgmt_extra_ie = ieee80211_set_mgmt_extra_ie, }; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index c9ffadb55d3..5eafd3affe2 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -331,6 +331,22 @@ struct ieee80211_if_sta { u32 supp_rates_bits[IEEE80211_NUM_BANDS]; int wmm_last_param_set; + + /* Extra IE data for management frames */ + u8 *ie_probereq; + size_t ie_probereq_len; + u8 *ie_proberesp; + size_t ie_proberesp_len; + u8 *ie_auth; + size_t ie_auth_len; + u8 *ie_assocreq; + size_t ie_assocreq_len; + u8 *ie_reassocreq; + size_t ie_reassocreq_len; + u8 *ie_deauth; + size_t ie_deauth_len; + u8 *ie_disassoc; + size_t ie_disassoc_len; }; struct ieee80211_if_mesh { diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 5d5a029228b..8dc2c2188d9 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -632,6 +632,13 @@ static void ieee80211_teardown_sdata(struct net_device *dev) kfree(sdata->u.sta.assocreq_ies); kfree(sdata->u.sta.assocresp_ies); kfree_skb(sdata->u.sta.probe_resp); + kfree(sdata->u.sta.ie_probereq); + kfree(sdata->u.sta.ie_proberesp); + kfree(sdata->u.sta.ie_auth); + kfree(sdata->u.sta.ie_assocreq); + kfree(sdata->u.sta.ie_reassocreq); + kfree(sdata->u.sta.ie_deauth); + kfree(sdata->u.sta.ie_disassoc); break; case NL80211_IFTYPE_WDS: case NL80211_IFTYPE_AP_VLAN: diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f0d42498c25..43da6227b37 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -131,6 +131,12 @@ u64 ieee80211_sta_get_rates(struct ieee80211_local *local, /* frame sending functions */ +static void add_extra_ies(struct sk_buff *skb, u8 *ies, size_t ies_len) +{ + if (ies) + memcpy(skb_put(skb, ies_len), ies, ies_len); +} + /* also used by scanning code */ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, u8 *ssid, size_t ssid_len) @@ -142,7 +148,8 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, u8 *pos, *supp_rates, *esupp_rates = NULL; int i; - skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200); + skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 + + sdata->u.sta.ie_probereq_len); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for probe " "request\n", sdata->dev->name); @@ -189,6 +196,9 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, *pos = rate->bitrate / 5; } + add_extra_ies(skb, sdata->u.sta.ie_probereq, + sdata->u.sta.ie_probereq_len); + ieee80211_tx_skb(sdata, skb, 0); } @@ -202,7 +212,8 @@ static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt; skb = dev_alloc_skb(local->hw.extra_tx_headroom + - sizeof(*mgmt) + 6 + extra_len); + sizeof(*mgmt) + 6 + extra_len + + sdata->u.sta.ie_auth_len); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for auth " "frame\n", sdata->dev->name); @@ -225,6 +236,7 @@ static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, mgmt->u.auth.status_code = cpu_to_le16(0); if (extra) memcpy(skb_put(skb, extra_len), extra, extra_len); + add_extra_ies(skb, sdata->u.sta.ie_auth, sdata->u.sta.ie_auth_len); ieee80211_tx_skb(sdata, skb, encrypt); } @@ -235,17 +247,26 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; - u8 *pos, *ies, *ht_ie; + u8 *pos, *ies, *ht_ie, *e_ies; int i, len, count, rates_len, supp_rates_len; u16 capab; struct ieee80211_bss *bss; int wmm = 0; struct ieee80211_supported_band *sband; u64 rates = 0; + size_t e_ies_len; + + if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) { + e_ies = sdata->u.sta.ie_reassocreq; + e_ies_len = sdata->u.sta.ie_reassocreq_len; + } else { + e_ies = sdata->u.sta.ie_assocreq; + e_ies_len = sdata->u.sta.ie_assocreq_len; + } skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 + ifsta->extra_ie_len + - ifsta->ssid_len); + ifsta->ssid_len + e_ies_len); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " "frame\n", sdata->dev->name); @@ -436,6 +457,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); } + add_extra_ies(skb, e_ies, e_ies_len); + kfree(ifsta->assocreq_ies); ifsta->assocreq_ies_len = (skb->data + skb->len) - ies; ifsta->assocreq_ies = kmalloc(ifsta->assocreq_ies_len, GFP_KERNEL); @@ -453,8 +476,19 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta = &sdata->u.sta; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; + u8 *ies; + size_t ies_len; - skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); + if (stype == IEEE80211_STYPE_DEAUTH) { + ies = sdata->u.sta.ie_deauth; + ies_len = sdata->u.sta.ie_deauth_len; + } else { + ies = sdata->u.sta.ie_disassoc; + ies_len = sdata->u.sta.ie_disassoc_len; + } + + skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + + ies_len); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for " "deauth/disassoc frame\n", sdata->dev->name); @@ -472,6 +506,8 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, /* u.deauth.reason_code == u.disassoc.reason_code */ mgmt->u.deauth.reason_code = cpu_to_le16(reason); + add_extra_ies(skb, ies, ies_len); + ieee80211_tx_skb(sdata, skb, ifsta->flags & IEEE80211_STA_MFP_ENABLED); } @@ -1473,7 +1509,8 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_supported_band *sband; union iwreq_data wrqu; - skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); + skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 + + sdata->u.sta.ie_proberesp_len); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for probe " "response\n", sdata->dev->name); @@ -1556,6 +1593,9 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, memcpy(pos, &bss->supp_rates[8], rates); } + add_extra_ies(skb, sdata->u.sta.ie_proberesp, + sdata->u.sta.ie_proberesp_len); + ifsta->probe_resp = skb; ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 123d3b160fa..09a5d0f1d6d 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -105,6 +105,10 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY, .len = NL80211_HT_CAPABILITY_LEN }, + + [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 }, + [NL80211_ATTR_IE] = { .type = NLA_BINARY, + .len = IEEE80211_MAX_DATA_LEN }, }; /* message building helper */ @@ -2149,6 +2153,43 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) return -EINVAL; } +static int nl80211_set_mgmt_extra_ie(struct sk_buff *skb, + struct genl_info *info) +{ + struct cfg80211_registered_device *drv; + int err; + struct net_device *dev; + struct mgmt_extra_ie_params params; + + memset(¶ms, 0, sizeof(params)); + + if (!info->attrs[NL80211_ATTR_MGMT_SUBTYPE]) + return -EINVAL; + params.subtype = nla_get_u8(info->attrs[NL80211_ATTR_MGMT_SUBTYPE]); + if (params.subtype > 15) + return -EINVAL; /* FC Subtype field is 4 bits (0..15) */ + + if (info->attrs[NL80211_ATTR_IE]) { + params.ies = nla_data(info->attrs[NL80211_ATTR_IE]); + params.ies_len = nla_len(info->attrs[NL80211_ATTR_IE]); + } + + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); + if (err) + return err; + + if (drv->ops->set_mgmt_extra_ie) { + rtnl_lock(); + err = drv->ops->set_mgmt_extra_ie(&drv->wiphy, dev, ¶ms); + rtnl_unlock(); + } else + err = -EOPNOTSUPP; + + cfg80211_put_dev(drv); + dev_put(dev); + return err; +} + static struct genl_ops nl80211_ops[] = { { .cmd = NL80211_CMD_GET_WIPHY, @@ -2310,6 +2351,12 @@ static struct genl_ops nl80211_ops[] = { .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, }, + { + .cmd = NL80211_CMD_SET_MGMT_EXTRA_IE, + .doit = nl80211_set_mgmt_extra_ie, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, }; /* multicast groups */ -- GitLab From 6642fe6f5d033128086c8b64737780454e53625e Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 16 Jan 2009 21:38:28 +0530 Subject: [PATCH 0860/4982] ath9k: rateCodeToIndex is not used, remove it Calculation of rate indices from ratecode is done in recv.c in a straightforward manner for both HT and legacy rates. This variable is not needed anymore. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/rc.c | 13 ------------- drivers/net/wireless/ath9k/rc.h | 1 - 2 files changed, 14 deletions(-) diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 0686a7c9ced..182884a1cde 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -19,7 +19,6 @@ static struct ath_rate_table ar5416_11na_ratetable = { 42, - {0}, { { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ 5400, 0x0b, 0x00, 12, @@ -158,7 +157,6 @@ static struct ath_rate_table ar5416_11na_ratetable = { static struct ath_rate_table ar5416_11ng_ratetable = { 46, - {0}, { { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ 900, 0x1b, 0x00, 2, @@ -306,7 +304,6 @@ static struct ath_rate_table ar5416_11ng_ratetable = { static struct ath_rate_table ar5416_11a_ratetable = { 8, - {0}, { { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ 5400, 0x0b, 0x00, (0x80|12), @@ -340,7 +337,6 @@ static struct ath_rate_table ar5416_11a_ratetable = { static struct ath_rate_table ar5416_11g_ratetable = { 12, - {0}, { { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ 900, 0x1b, 0x00, 2, @@ -386,7 +382,6 @@ static struct ath_rate_table ar5416_11g_ratetable = { static struct ath_rate_table ar5416_11b_ratetable = { 4, - {0}, { { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ 900, 0x1b, 0x00, (0x80|2), @@ -1607,16 +1602,8 @@ static void ath_setup_rate_table(struct ath_softc *sc, { int i; - for (i = 0; i < 256; i++) - rate_table->rateCodeToIndex[i] = (u8)-1; - for (i = 0; i < rate_table->rate_cnt; i++) { - u8 code = rate_table->info[i].ratecode; u8 cix = rate_table->info[i].ctrl_rate; - u8 sh = rate_table->info[i].short_preamble; - - rate_table->rateCodeToIndex[code] = i; - rate_table->rateCodeToIndex[code | sh] = i; rate_table->info[i].lpAckDuration = ath9k_hw_computetxtime(sc->sc_ah, rate_table, diff --git a/drivers/net/wireless/ath9k/rc.h b/drivers/net/wireless/ath9k/rc.h index 97c60d12e8a..a987cb9e74e 100644 --- a/drivers/net/wireless/ath9k/rc.h +++ b/drivers/net/wireless/ath9k/rc.h @@ -90,7 +90,6 @@ struct ath_softc; */ struct ath_rate_table { int rate_cnt; - u8 rateCodeToIndex[256]; struct { int valid; int valid_single_stream; -- GitLab From dd006395688cd3ce6c92de288d8db090d98dc2c7 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 16 Jan 2009 21:38:40 +0530 Subject: [PATCH 0861/4982] ath9k: Update short guard interval in rate control The rate control algorithm needs to know if a STA allows short guard interval, fixing this allows RC to use the correct table. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/rc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 182884a1cde..68bda2309ce 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -1361,6 +1361,8 @@ static void ath_rc_init(struct ath_softc *sc, ath_rc_priv->ht_cap = (WLAN_RC_HT_FLAG | WLAN_RC_DS_FLAG); if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ath_rc_priv->ht_cap |= WLAN_RC_40_FLAG; + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) + ath_rc_priv->ht_cap |= WLAN_RC_SGI_FLAG; } /* Initial rate table size. Will change depending -- GitLab From e8324357902698ffb7615d128d612c85d8e21912 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 16 Jan 2009 21:38:42 +0530 Subject: [PATCH 0862/4982] ath9k: Reorganize code in xmit.c This patch starts cleaning up all the crufty code in transmission path, grouping functions into logical blocks. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/core.h | 6 - drivers/net/wireless/ath9k/rc.c | 2 +- drivers/net/wireless/ath9k/xmit.c | 3362 ++++++++++++++--------------- 3 files changed, 1563 insertions(+), 1807 deletions(-) diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index b687ae9c9e1..4eb21a7f0d8 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -490,23 +490,17 @@ void ath_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx); void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an); void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an); -void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an); void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq); int ath_tx_init(struct ath_softc *sc, int nbufs); int ath_tx_cleanup(struct ath_softc *sc); -int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype); struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb); int ath_txq_update(struct ath_softc *sc, int qnum, struct ath9k_tx_queue_info *q); int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb, struct ath_tx_control *txctl); void ath_tx_tasklet(struct ath_softc *sc); -u32 ath_txq_depth(struct ath_softc *sc, int qnum); -u32 ath_txq_aggr_depth(struct ath_softc *sc, int qnum); void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb); -void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid); bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno); -void ath_tx_aggr_teardown(struct ath_softc *sc, struct ath_node *an, u8 tidno); int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid, u16 *ssn); int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 68bda2309ce..46172b5f492 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -23,7 +23,7 @@ static struct ath_rate_table ar5416_11na_ratetable = { { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ 5400, 0x0b, 0x00, 12, 0, 2, 1, 0, 0, 0, 0, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ + { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ 7800, 0x0f, 0x00, 18, 0, 3, 1, 1, 1, 1, 1, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 522078d8093..5e6e5cf9b67 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -55,94 +55,19 @@ static u32 bits_per_symbol[][2] = { #define IS_HT_RATE(_rate) ((_rate) & 0x80) -/* - * Insert a chain of ath_buf (descriptors) on a txq and - * assume the descriptors are already chained together by caller. - * NB: must be called with txq lock held - */ - +static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, + struct ath_atx_tid *tid, + struct list_head *bf_head); +static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, + struct list_head *bf_q, + int txok, int sendbar); static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, - struct list_head *head) -{ - struct ath_hal *ah = sc->sc_ah; - struct ath_buf *bf; - - /* - * Insert the frame on the outbound list and - * pass it on to the hardware. - */ - - if (list_empty(head)) - return; - - bf = list_first_entry(head, struct ath_buf, list); - - list_splice_tail_init(head, &txq->axq_q); - txq->axq_depth++; - txq->axq_totalqueued++; - txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list); - - DPRINTF(sc, ATH_DBG_QUEUE, - "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth); - - if (txq->axq_link == NULL) { - ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); - DPRINTF(sc, ATH_DBG_XMIT, - "TXDP[%u] = %llx (%p)\n", - txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc); - } else { - *txq->axq_link = bf->bf_daddr; - DPRINTF(sc, ATH_DBG_XMIT, "link[%u] (%p)=%llx (%p)\n", - txq->axq_qnum, txq->axq_link, - ito64(bf->bf_daddr), bf->bf_desc); - } - txq->axq_link = &(bf->bf_lastbf->bf_desc->ds_link); - ath9k_hw_txstart(ah, txq->axq_qnum); -} - -static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, - struct ath_xmit_status *tx_status) -{ - struct ieee80211_hw *hw = sc->hw; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); - int hdrlen, padsize; - - DPRINTF(sc, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); - - if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK || - tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) { - kfree(tx_info_priv); - tx_info->rate_driver_data[0] = NULL; - } - - if (tx_status->flags & ATH_TX_BAR) { - tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; - tx_status->flags &= ~ATH_TX_BAR; - } + struct list_head *head); +static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf); - if (!(tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) { - /* Frame was ACKed */ - tx_info->flags |= IEEE80211_TX_STAT_ACK; - } - - tx_info->status.rates[0].count = tx_status->retries + 1; - - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - padsize = hdrlen & 3; - if (padsize && hdrlen >= 24) { - /* - * Remove MAC header padding before giving the frame back to - * mac80211. - */ - memmove(skb->data + padsize, skb->data, hdrlen); - skb_pull(skb, padsize); - } - - ieee80211_tx_status(hw, skb); -} - -/* Check if it's okay to send out aggregates */ +/*********************/ +/* Aggregation logic */ +/*********************/ static int ath_aggr_query(struct ath_softc *sc, struct ath_node *an, u8 tidno) { @@ -156,984 +81,820 @@ static int ath_aggr_query(struct ath_softc *sc, struct ath_node *an, u8 tidno) return 0; } -static void ath_get_beaconconfig(struct ath_softc *sc, int if_id, - struct ath_beacon_config *conf) +static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid) { - struct ieee80211_hw *hw = sc->hw; + struct ath_atx_ac *ac = tid->ac; - /* fill in beacon config data */ + if (tid->paused) + return; - conf->beacon_interval = hw->conf.beacon_int; - conf->listen_interval = 100; - conf->dtim_count = 1; - conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval; -} + if (tid->sched) + return; -/* Calculate Atheros packet type from IEEE80211 packet header */ + tid->sched = true; + list_add_tail(&tid->list, &ac->tid_q); -static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr; - enum ath9k_pkt_type htype; - __le16 fc; + if (ac->sched) + return; - hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; + ac->sched = true; + list_add_tail(&ac->list, &txq->axq_acq); +} - if (ieee80211_is_beacon(fc)) - htype = ATH9K_PKT_TYPE_BEACON; - else if (ieee80211_is_probe_resp(fc)) - htype = ATH9K_PKT_TYPE_PROBE_RESP; - else if (ieee80211_is_atim(fc)) - htype = ATH9K_PKT_TYPE_ATIM; - else if (ieee80211_is_pspoll(fc)) - htype = ATH9K_PKT_TYPE_PSPOLL; - else - htype = ATH9K_PKT_TYPE_NORMAL; +static void ath_tx_pause_tid(struct ath_softc *sc, struct ath_atx_tid *tid) +{ + struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; - return htype; + spin_lock_bh(&txq->axq_lock); + tid->paused++; + spin_unlock_bh(&txq->axq_lock); } -static bool is_pae(struct sk_buff *skb) +static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid) { - struct ieee80211_hdr *hdr; - __le16 fc; - - hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; + struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; - if (ieee80211_is_data(fc)) { - if (ieee80211_is_nullfunc(fc) || - /* Port Access Entity (IEEE 802.1X) */ - (skb->protocol == cpu_to_be16(ETH_P_PAE))) { - return true; - } - } + ASSERT(tid->paused > 0); + spin_lock_bh(&txq->axq_lock); - return false; -} + tid->paused--; -static int get_hw_crypto_keytype(struct sk_buff *skb) -{ - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + if (tid->paused > 0) + goto unlock; - if (tx_info->control.hw_key) { - if (tx_info->control.hw_key->alg == ALG_WEP) - return ATH9K_KEY_TYPE_WEP; - else if (tx_info->control.hw_key->alg == ALG_TKIP) - return ATH9K_KEY_TYPE_TKIP; - else if (tx_info->control.hw_key->alg == ALG_CCMP) - return ATH9K_KEY_TYPE_AES; - } + if (list_empty(&tid->buf_q)) + goto unlock; - return ATH9K_KEY_TYPE_CLEAR; + ath_tx_queue_tid(txq, tid); + ath_txq_schedule(sc, txq); +unlock: + spin_unlock_bh(&txq->axq_lock); } -/* Called only when tx aggregation is enabled and HT is supported */ - -static void assign_aggr_tid_seqno(struct sk_buff *skb, - struct ath_buf *bf) +static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) { - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr; - struct ath_node *an; - struct ath_atx_tid *tid; - __le16 fc; - u8 *qc; + struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; + struct ath_buf *bf; + struct list_head bf_head; + INIT_LIST_HEAD(&bf_head); - if (!tx_info->control.sta) - return; + ASSERT(tid->paused > 0); + spin_lock_bh(&txq->axq_lock); - an = (struct ath_node *)tx_info->control.sta->drv_priv; - hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; + tid->paused--; - /* Get tidno */ + if (tid->paused > 0) { + spin_unlock_bh(&txq->axq_lock); + return; + } - if (ieee80211_is_data_qos(fc)) { - qc = ieee80211_get_qos_ctl(hdr); - bf->bf_tidno = qc[0] & 0xf; + while (!list_empty(&tid->buf_q)) { + bf = list_first_entry(&tid->buf_q, struct ath_buf, list); + ASSERT(!bf_isretried(bf)); + list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list); + ath_tx_send_normal(sc, txq, tid, &bf_head); } - /* Get seqno */ - /* For HT capable stations, we save tidno for later use. - * We also override seqno set by upper layer with the one - * in tx aggregation state. - * - * If fragmentation is on, the sequence number is - * not overridden, since it has been - * incremented by the fragmentation routine. - * - * FIXME: check if the fragmentation threshold exceeds - * IEEE80211 max. - */ - tid = ATH_AN_2_TID(an, bf->bf_tidno); - hdr->seq_ctrl = cpu_to_le16(tid->seq_next << - IEEE80211_SEQ_SEQ_SHIFT); - bf->bf_seqno = tid->seq_next; - INCR(tid->seq_next, IEEE80211_SEQ_MAX); + spin_unlock_bh(&txq->axq_lock); } -static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb, - struct ath_txq *txq) +static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, + int seqno) { - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - int flags = 0; + int index, cindex; - flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */ - flags |= ATH9K_TXDESC_INTREQ; + index = ATH_BA_INDEX(tid->seq_start, seqno); + cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); - if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) - flags |= ATH9K_TXDESC_NOACK; - if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) - flags |= ATH9K_TXDESC_RTSENA; + tid->tx_buf[cindex] = NULL; - return flags; + while (tid->baw_head != tid->baw_tail && !tid->tx_buf[tid->baw_head]) { + INCR(tid->seq_start, IEEE80211_SEQ_MAX); + INCR(tid->baw_head, ATH_TID_MAX_BUFS); + } } -static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc) +static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid, + struct ath_buf *bf) { - struct ath_buf *bf = NULL; + int index, cindex; - spin_lock_bh(&sc->tx.txbuflock); + if (bf_isretried(bf)) + return; - if (unlikely(list_empty(&sc->tx.txbuf))) { - spin_unlock_bh(&sc->tx.txbuflock); - return NULL; - } + index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno); + cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); - bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); - list_del(&bf->list); - - spin_unlock_bh(&sc->tx.txbuflock); - - return bf; -} - -/* To complete a chain of buffers associated a frame */ - -static void ath_tx_complete_buf(struct ath_softc *sc, - struct ath_buf *bf, - struct list_head *bf_q, - int txok, int sendbar) -{ - struct sk_buff *skb = bf->bf_mpdu; - struct ath_xmit_status tx_status; - unsigned long flags; - - /* - * Set retry information. - * NB: Don't use the information in the descriptor, because the frame - * could be software retried. - */ - tx_status.retries = bf->bf_retries; - tx_status.flags = 0; - - if (sendbar) - tx_status.flags = ATH_TX_BAR; - - if (!txok) { - tx_status.flags |= ATH_TX_ERROR; + ASSERT(tid->tx_buf[cindex] == NULL); + tid->tx_buf[cindex] = bf; - if (bf_isxretried(bf)) - tx_status.flags |= ATH_TX_XRETRY; + if (index >= ((tid->baw_tail - tid->baw_head) & + (ATH_TID_MAX_BUFS - 1))) { + tid->baw_tail = cindex; + INCR(tid->baw_tail, ATH_TID_MAX_BUFS); } - - /* Unmap this frame */ - dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); - - /* complete this frame */ - ath_tx_complete(sc, skb, &tx_status); - - /* - * Return the list of ath_buf of this mpdu to free queue - */ - spin_lock_irqsave(&sc->tx.txbuflock, flags); - list_splice_tail_init(bf_q, &sc->tx.txbuf); - spin_unlock_irqrestore(&sc->tx.txbuflock, flags); } /* - * queue up a dest/ac pair for tx scheduling - * NB: must be called with txq lock held + * TODO: For frame(s) that are in the retry state, we will reuse the + * sequence number(s) without setting the retry bit. The + * alternative is to give up on these and BAR the receiver's window + * forward. */ +static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, + struct ath_atx_tid *tid) -static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid) { - struct ath_atx_ac *ac = tid->ac; - - /* - * if tid is paused, hold off - */ - if (tid->paused) - return; - - /* - * add tid to ac atmost once - */ - if (tid->sched) - return; - - tid->sched = true; - list_add_tail(&tid->list, &ac->tid_q); - - /* - * add node ac to txq atmost once - */ - if (ac->sched) - return; - - ac->sched = true; - list_add_tail(&ac->list, &txq->axq_acq); -} + struct ath_buf *bf; + struct list_head bf_head; + INIT_LIST_HEAD(&bf_head); -/* pause a tid */ + for (;;) { + if (list_empty(&tid->buf_q)) + break; + bf = list_first_entry(&tid->buf_q, struct ath_buf, list); -static void ath_tx_pause_tid(struct ath_softc *sc, struct ath_atx_tid *tid) -{ - struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; + list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list); - spin_lock_bh(&txq->axq_lock); + if (bf_isretried(bf)) + ath_tx_update_baw(sc, tid, bf->bf_seqno); - tid->paused++; + spin_unlock(&txq->axq_lock); + ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); + spin_lock(&txq->axq_lock); + } - spin_unlock_bh(&txq->axq_lock); + tid->seq_next = tid->seq_start; + tid->baw_tail = tid->baw_head; } -/* resume a tid and schedule aggregate */ - -void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid) +static void ath_tx_set_retry(struct ath_softc *sc, struct ath_buf *bf) { - struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; - - ASSERT(tid->paused > 0); - spin_lock_bh(&txq->axq_lock); - - tid->paused--; - - if (tid->paused > 0) - goto unlock; + struct sk_buff *skb; + struct ieee80211_hdr *hdr; - if (list_empty(&tid->buf_q)) - goto unlock; + bf->bf_state.bf_type |= BUF_RETRY; + bf->bf_retries++; - /* - * Add this TID to scheduler and try to send out aggregates - */ - ath_tx_queue_tid(txq, tid); - ath_txq_schedule(sc, txq); -unlock: - spin_unlock_bh(&txq->axq_lock); + skb = bf->bf_mpdu; + hdr = (struct ieee80211_hdr *)skb->data; + hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY); } -/* Compute the number of bad frames */ - -static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, - int txok) +static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, struct ath_txq *txq, + struct ath_buf *bf, struct list_head *bf_q, + int txok) { + struct ath_node *an = NULL; + struct sk_buff *skb; + struct ieee80211_tx_info *tx_info; + struct ath_atx_tid *tid = NULL; struct ath_buf *bf_last = bf->bf_lastbf; struct ath_desc *ds = bf_last->bf_desc; + struct ath_buf *bf_next, *bf_lastq = NULL; + struct list_head bf_head, bf_pending; u16 seq_st = 0; u32 ba[WME_BA_BMP_SIZE >> 5]; - int ba_index; - int nbad = 0; - int isaggr = 0; + int isaggr, txfail, txpending, sendbar = 0, needreset = 0; - if (ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED) - return 0; + skb = (struct sk_buff *)bf->bf_mpdu; + tx_info = IEEE80211_SKB_CB(skb); - isaggr = bf_isaggr(bf); - if (isaggr) { - seq_st = ATH_DS_BA_SEQ(ds); - memcpy(ba, ATH_DS_BA_BITMAP(ds), WME_BA_BMP_SIZE >> 3); + if (tx_info->control.sta) { + an = (struct ath_node *)tx_info->control.sta->drv_priv; + tid = ATH_AN_2_TID(an, bf->bf_tidno); } - while (bf) { - ba_index = ATH_BA_INDEX(seq_st, bf->bf_seqno); - if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index))) - nbad++; + isaggr = bf_isaggr(bf); + if (isaggr) { + if (txok) { + if (ATH_DS_TX_BA(ds)) { + seq_st = ATH_DS_BA_SEQ(ds); + memcpy(ba, ATH_DS_BA_BITMAP(ds), + WME_BA_BMP_SIZE >> 3); + } else { + memset(ba, 0, WME_BA_BMP_SIZE >> 3); - bf = bf->bf_next; + /* + * AR5416 can become deaf/mute when BA + * issue happens. Chip needs to be reset. + * But AP code may have sychronization issues + * when perform internal reset in this routine. + * Only enable reset in STA mode for now. + */ + if (sc->sc_ah->ah_opmode == + NL80211_IFTYPE_STATION) + needreset = 1; + } + } else { + memset(ba, 0, WME_BA_BMP_SIZE >> 3); + } } - return nbad; -} + INIT_LIST_HEAD(&bf_pending); + INIT_LIST_HEAD(&bf_head); -static void ath_tx_set_retry(struct ath_softc *sc, struct ath_buf *bf) -{ - struct sk_buff *skb; - struct ieee80211_hdr *hdr; + while (bf) { + txfail = txpending = 0; + bf_next = bf->bf_next; - bf->bf_state.bf_type |= BUF_RETRY; - bf->bf_retries++; + if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) { + /* transmit completion, subframe is + * acked by block ack */ + } else if (!isaggr && txok) { + /* transmit completion */ + } else { - skb = bf->bf_mpdu; - hdr = (struct ieee80211_hdr *)skb->data; - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY); -} + if (!(tid->state & AGGR_CLEANUP) && + ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) { + if (bf->bf_retries < ATH_MAX_SW_RETRIES) { + ath_tx_set_retry(sc, bf); + txpending = 1; + } else { + bf->bf_state.bf_type |= BUF_XRETRY; + txfail = 1; + sendbar = 1; + } + } else { + /* + * cleanup in progress, just fail + * the un-acked sub-frames + */ + txfail = 1; + } + } -/* Update block ack window */ + if (bf_next == NULL) { + ASSERT(bf->bf_lastfrm == bf_last); + if (!list_empty(bf_q)) { + bf_lastq = list_entry(bf_q->prev, + struct ath_buf, list); + list_cut_position(&bf_head, + bf_q, &bf_lastq->list); + } else { + INIT_LIST_HEAD(&bf_head); + } + } else { + ASSERT(!list_empty(bf_q)); + list_cut_position(&bf_head, + bf_q, &bf->bf_lastfrm->list); + } -static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, - int seqno) -{ - int index, cindex; + if (!txpending) { + /* + * complete the acked-ones/xretried ones; update + * block-ack window + */ + spin_lock_bh(&txq->axq_lock); + ath_tx_update_baw(sc, tid, bf->bf_seqno); + spin_unlock_bh(&txq->axq_lock); - index = ATH_BA_INDEX(tid->seq_start, seqno); - cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); + ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar); + } else { + /* + * retry the un-acked ones + */ + if (bf->bf_next == NULL && + bf_last->bf_status & ATH_BUFSTATUS_STALE) { + struct ath_buf *tbf; - tid->tx_buf[cindex] = NULL; + /* allocate new descriptor */ + spin_lock_bh(&sc->tx.txbuflock); + ASSERT(!list_empty((&sc->tx.txbuf))); + tbf = list_first_entry(&sc->tx.txbuf, + struct ath_buf, list); + list_del(&tbf->list); + spin_unlock_bh(&sc->tx.txbuflock); - while (tid->baw_head != tid->baw_tail && !tid->tx_buf[tid->baw_head]) { - INCR(tid->seq_start, IEEE80211_SEQ_MAX); - INCR(tid->baw_head, ATH_TID_MAX_BUFS); + ATH_TXBUF_RESET(tbf); + + /* copy descriptor content */ + tbf->bf_mpdu = bf_last->bf_mpdu; + tbf->bf_buf_addr = bf_last->bf_buf_addr; + *(tbf->bf_desc) = *(bf_last->bf_desc); + + /* link it to the frame */ + if (bf_lastq) { + bf_lastq->bf_desc->ds_link = + tbf->bf_daddr; + bf->bf_lastfrm = tbf; + ath9k_hw_cleartxdesc(sc->sc_ah, + bf->bf_lastfrm->bf_desc); + } else { + tbf->bf_state = bf_last->bf_state; + tbf->bf_lastfrm = tbf; + ath9k_hw_cleartxdesc(sc->sc_ah, + tbf->bf_lastfrm->bf_desc); + + /* copy the DMA context */ + tbf->bf_dmacontext = + bf_last->bf_dmacontext; + } + list_add_tail(&tbf->list, &bf_head); + } else { + /* + * Clear descriptor status words for + * software retry + */ + ath9k_hw_cleartxdesc(sc->sc_ah, + bf->bf_lastfrm->bf_desc); + } + + /* + * Put this buffer to the temporary pending + * queue to retain ordering + */ + list_splice_tail_init(&bf_head, &bf_pending); + } + + bf = bf_next; } -} -/* - * ath_pkt_dur - compute packet duration (NB: not NAV) - * - * rix - rate index - * pktlen - total bytes (delims + data + fcs + pads + pad delims) - * width - 0 for 20 MHz, 1 for 40 MHz - * half_gi - to use 4us v/s 3.6 us for symbol time - */ -static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, - int width, int half_gi, bool shortPreamble) -{ - struct ath_rate_table *rate_table = sc->cur_rate_table; - u32 nbits, nsymbits, duration, nsymbols; - u8 rc; - int streams, pktlen; + if (tid->state & AGGR_CLEANUP) { + /* check to see if we're done with cleaning the h/w queue */ + spin_lock_bh(&txq->axq_lock); - pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen; - rc = rate_table->info[rix].ratecode; + if (tid->baw_head == tid->baw_tail) { + tid->state &= ~AGGR_ADDBA_COMPLETE; + tid->addba_exchangeattempts = 0; + spin_unlock_bh(&txq->axq_lock); - /* for legacy rates, use old function to compute packet duration */ - if (!IS_HT_RATE(rc)) - return ath9k_hw_computetxtime(sc->sc_ah, rate_table, pktlen, - rix, shortPreamble); + tid->state &= ~AGGR_CLEANUP; - /* find number of symbols: PLCP + data */ - nbits = (pktlen << 3) + OFDM_PLCP_BITS; - nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width]; - nsymbols = (nbits + nsymbits - 1) / nsymbits; + /* send buffered frames as singles */ + ath_tx_flush_tid(sc, tid); + } else + spin_unlock_bh(&txq->axq_lock); - if (!half_gi) - duration = SYMBOL_TIME(nsymbols); - else - duration = SYMBOL_TIME_HALFGI(nsymbols); + return; + } - /* addup duration for legacy/ht training and signal fields */ - streams = HT_RC_2_STREAMS(rc); - duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams); + /* + * prepend un-acked frames to the beginning of the pending frame queue + */ + if (!list_empty(&bf_pending)) { + spin_lock_bh(&txq->axq_lock); + list_splice(&bf_pending, &tid->buf_q); + ath_tx_queue_tid(txq, tid); + spin_unlock_bh(&txq->axq_lock); + } - return duration; -} + if (needreset) + ath_reset(sc, false); -/* Rate module function to set rate related fields in tx descriptor */ + return; +} -static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) +static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, + struct ath_atx_tid *tid) { - struct ath_hal *ah = sc->sc_ah; - struct ath_rate_table *rt; - struct ath_desc *ds = bf->bf_desc; - struct ath_desc *lastds = bf->bf_lastbf->bf_desc; - struct ath9k_11n_rate_series series[4]; + struct ath_rate_table *rate_table = sc->cur_rate_table; struct sk_buff *skb; struct ieee80211_tx_info *tx_info; struct ieee80211_tx_rate *rates; - struct ieee80211_hdr *hdr; - struct ieee80211_hw *hw = sc->hw; - int i, flags, rtsctsena = 0, enable_g_protection = 0; - u32 ctsduration = 0; - u8 rix = 0, cix, ctsrate = 0; - __le16 fc; - - memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); + struct ath_tx_info_priv *tx_info_priv; + u32 max_4ms_framelen, frame_length; + u16 aggr_limit, legacy = 0, maxampdu; + int i; skb = (struct sk_buff *)bf->bf_mpdu; - hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; tx_info = IEEE80211_SKB_CB(skb); rates = tx_info->control.rates; + tx_info_priv = + (struct ath_tx_info_priv *)tx_info->rate_driver_data[0]; - if (ieee80211_has_morefrags(fc) || - (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) { - rates[1].count = rates[2].count = rates[3].count = 0; - rates[1].idx = rates[2].idx = rates[3].idx = 0; - rates[0].count = ATH_TXMAXTRY; - } + /* + * Find the lowest frame length among the rate series that will have a + * 4ms transmit duration. + * TODO - TXOP limit needs to be considered. + */ + max_4ms_framelen = ATH_AMPDU_LIMIT_MAX; - /* get the cix for the lowest valid rix */ - rt = sc->cur_rate_table; - for (i = 3; i >= 0; i--) { - if (rates[i].count && (rates[i].idx >= 0)) { - rix = rates[i].idx; - break; + for (i = 0; i < 4; i++) { + if (rates[i].count) { + if (!WLAN_RC_PHY_HT(rate_table->info[rates[i].idx].phy)) { + legacy = 1; + break; + } + + frame_length = + rate_table->info[rates[i].idx].max_4ms_framelen; + max_4ms_framelen = min(max_4ms_framelen, frame_length); } } - flags = (bf->bf_flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)); - cix = rt->info[rix].ctrl_rate; - - /* All protection frames are transmited at 2Mb/s for 802.11g, - * otherwise we transmit them at 1Mb/s */ - if (hw->conf.channel->band == IEEE80211_BAND_2GHZ && - !conf_is_ht(&hw->conf)) - enable_g_protection = 1; - /* - * If 802.11g protection is enabled, determine whether to use RTS/CTS or - * just CTS. Note that this is only done for OFDM/HT unicast frames. + * limit aggregate size by the minimum rate if rate selected is + * not a probe rate, if rate selected is a probe rate then + * avoid aggregation of this packet. */ - if (sc->sc_protmode != PROT_M_NONE && !(bf->bf_flags & ATH9K_TXDESC_NOACK) - && (rt->info[rix].phy == WLAN_RC_PHY_OFDM || - WLAN_RC_PHY_HT(rt->info[rix].phy))) { - if (sc->sc_protmode == PROT_M_RTSCTS) - flags = ATH9K_TXDESC_RTSENA; - else if (sc->sc_protmode == PROT_M_CTSONLY) - flags = ATH9K_TXDESC_CTSENA; + if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy) + return 0; - cix = rt->info[enable_g_protection].ctrl_rate; - rtsctsena = 1; - } + aggr_limit = min(max_4ms_framelen, + (u32)ATH_AMPDU_LIMIT_DEFAULT); - /* For 11n, the default behavior is to enable RTS for hw retried frames. - * We enable the global flag here and let rate series flags determine - * which rates will actually use RTS. + /* + * h/w can accept aggregates upto 16 bit lengths (65535). + * The IE, however can hold upto 65536, which shows up here + * as zero. Ignore 65536 since we are constrained by hw. */ - if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) && bf_isdata(bf)) { - /* 802.11g protection not needed, use our default behavior */ - if (!rtsctsena) - flags = ATH9K_TXDESC_RTSENA; - } + maxampdu = tid->an->maxampdu; + if (maxampdu) + aggr_limit = min(aggr_limit, maxampdu); - /* Set protection if aggregate protection on */ - if (sc->sc_config.ath_aggr_prot && - (!bf_isaggr(bf) || (bf_isaggr(bf) && bf->bf_al < 8192))) { - flags = ATH9K_TXDESC_RTSENA; - cix = rt->info[enable_g_protection].ctrl_rate; - rtsctsena = 1; - } + return aggr_limit; +} - /* For AR5416 - RTS cannot be followed by a frame larger than 8K */ - if (bf_isaggr(bf) && (bf->bf_al > ah->ah_caps.rts_aggr_limit)) - flags &= ~(ATH9K_TXDESC_RTSENA); +/* + * returns the number of delimiters to be added to + * meet the minimum required mpdudensity. + * caller should make sure that the rate is HT rate . + */ +static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, + struct ath_buf *bf, u16 frmlen) +{ + struct ath_rate_table *rt = sc->cur_rate_table; + struct sk_buff *skb = bf->bf_mpdu; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + u32 nsymbits, nsymbols, mpdudensity; + u16 minlen; + u8 rc, flags, rix; + int width, half_gi, ndelim, mindelim; + + /* Select standard number of delimiters based on frame length alone */ + ndelim = ATH_AGGR_GET_NDELIM(frmlen); /* - * CTS transmit rate is derived from the transmit rate by looking in the - * h/w rate table. We must also factor in whether or not a short - * preamble is to be used. NB: cix is set above where RTS/CTS is enabled + * If encryption enabled, hardware requires some more padding between + * subframes. + * TODO - this could be improved to be dependent on the rate. + * The hardware can keep up at lower rates, but not higher rates */ - ctsrate = rt->info[cix].ratecode | - (bf_isshpreamble(bf) ? rt->info[cix].short_preamble : 0); + if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) + ndelim += ATH_AGGR_ENCRYPTDELIM; - for (i = 0; i < 4; i++) { - if (!rates[i].count || (rates[i].idx < 0)) - continue; + /* + * Convert desired mpdu density from microeconds to bytes based + * on highest rate in rate series (i.e. first rate) to determine + * required minimum length for subframe. Take into account + * whether high rate is 20 or 40Mhz and half or full GI. + */ + mpdudensity = tid->an->mpdudensity; - rix = rates[i].idx; + /* + * If there is no mpdu density restriction, no further calculation + * is needed. + */ + if (mpdudensity == 0) + return ndelim; - series[i].Rate = rt->info[rix].ratecode | - (bf_isshpreamble(bf) ? rt->info[rix].short_preamble : 0); - - series[i].Tries = rates[i].count; + rix = tx_info->control.rates[0].idx; + flags = tx_info->control.rates[0].flags; + rc = rt->info[rix].ratecode; + width = (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 1 : 0; + half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0; - series[i].RateFlags = ( - (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) ? - ATH9K_RATESERIES_RTS_CTS : 0) | - ((rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? - ATH9K_RATESERIES_2040 : 0) | - ((rates[i].flags & IEEE80211_TX_RC_SHORT_GI) ? - ATH9K_RATESERIES_HALFGI : 0); + if (half_gi) + nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity); + else + nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity); - series[i].PktDuration = ath_pkt_duration(sc, rix, bf, - (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) != 0, - (rates[i].flags & IEEE80211_TX_RC_SHORT_GI), - bf_isshpreamble(bf)); + if (nsymbols == 0) + nsymbols = 1; - series[i].ChSel = sc->sc_tx_chainmask; + nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width]; + minlen = (nsymbols * nsymbits) / BITS_PER_BYTE; - if (rtsctsena) - series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; + /* Is frame shorter than required minimum length? */ + if (frmlen < minlen) { + /* Get the minimum number of delimiters required. */ + mindelim = (minlen - frmlen) / ATH_AGGR_DELIM_SZ; + ndelim = max(mindelim, ndelim); } - /* set dur_update_en for l-sig computation except for PS-Poll frames */ - ath9k_hw_set11n_ratescenario(ah, ds, lastds, !bf_ispspoll(bf), - ctsrate, ctsduration, - series, 4, flags); - - if (sc->sc_config.ath_aggr_prot && flags) - ath9k_hw_set11n_burstduration(ah, ds, 8192); + return ndelim; } -/* - * Function to send a normal HT (non-AMPDU) frame - * NB: must be called with txq lock held - */ -static int ath_tx_send_normal(struct ath_softc *sc, - struct ath_txq *txq, - struct ath_atx_tid *tid, - struct list_head *bf_head) +static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, + struct ath_atx_tid *tid, struct list_head *bf_q, + struct ath_buf **bf_last, struct aggr_rifs_param *param, + int *prev_frames) { - struct ath_buf *bf; +#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) + struct ath_buf *bf, *tbf, *bf_first, *bf_prev = NULL; + struct list_head bf_head; + int rl = 0, nframes = 0, ndelim; + u16 aggr_limit = 0, al = 0, bpad = 0, + al_delta, h_baw = tid->baw_size / 2; + enum ATH_AGGR_STATUS status = ATH_AGGR_DONE; + int prev_al = 0; + INIT_LIST_HEAD(&bf_head); - BUG_ON(list_empty(bf_head)); + BUG_ON(list_empty(&tid->buf_q)); - bf = list_first_entry(bf_head, struct ath_buf, list); - bf->bf_state.bf_type &= ~BUF_AMPDU; /* regular HT frame */ + bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list); - /* update starting sequence number for subsequent ADDBA request */ - INCR(tid->seq_start, IEEE80211_SEQ_MAX); + do { + bf = list_first_entry(&tid->buf_q, struct ath_buf, list); - /* Queue to h/w without aggregation */ - bf->bf_nframes = 1; - bf->bf_lastbf = bf->bf_lastfrm; /* one single frame */ - ath_buf_set_rate(sc, bf); - ath_tx_txqaddbuf(sc, txq, bf_head); + /* + * do not step over block-ack window + */ + if (!BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno)) { + status = ATH_AGGR_BAW_CLOSED; + break; + } - return 0; -} + if (!rl) { + aggr_limit = ath_lookup_rate(sc, bf, tid); + rl = 1; + } -/* flush tid's software queue and send frames as non-ampdu's */ + /* + * do not exceed aggregation limit + */ + al_delta = ATH_AGGR_DELIM_SZ + bf->bf_frmlen; -static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) -{ - struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; - struct ath_buf *bf; - struct list_head bf_head; - INIT_LIST_HEAD(&bf_head); + if (nframes && (aggr_limit < + (al + bpad + al_delta + prev_al))) { + status = ATH_AGGR_LIMITED; + break; + } - ASSERT(tid->paused > 0); - spin_lock_bh(&txq->axq_lock); + /* + * do not exceed subframe limit + */ + if ((nframes + *prev_frames) >= + min((int)h_baw, ATH_AMPDU_SUBFRAME_DEFAULT)) { + status = ATH_AGGR_LIMITED; + break; + } - tid->paused--; + /* + * add padding for previous frame to aggregation length + */ + al += bpad + al_delta; - if (tid->paused > 0) { - spin_unlock_bh(&txq->axq_lock); - return; - } + /* + * Get the delimiters needed to meet the MPDU + * density for this node. + */ + ndelim = ath_compute_num_delims(sc, tid, bf_first, bf->bf_frmlen); - while (!list_empty(&tid->buf_q)) { - bf = list_first_entry(&tid->buf_q, struct ath_buf, list); - ASSERT(!bf_isretried(bf)); - list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list); - ath_tx_send_normal(sc, txq, tid, &bf_head); - } + bpad = PADBYTES(al_delta) + (ndelim << 2); - spin_unlock_bh(&txq->axq_lock); -} + bf->bf_next = NULL; + bf->bf_lastfrm->bf_desc->ds_link = 0; -/* Completion routine of an aggregate */ + /* + * this packet is part of an aggregate + * - remove all descriptors belonging to this frame from + * software queue + * - add it to block ack window + * - set up descriptors for aggregation + */ + list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list); + ath_tx_addto_baw(sc, tid, bf); -static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, - struct ath_txq *txq, - struct ath_buf *bf, - struct list_head *bf_q, - int txok) -{ - struct ath_node *an = NULL; - struct sk_buff *skb; - struct ieee80211_tx_info *tx_info; - struct ath_atx_tid *tid = NULL; - struct ath_buf *bf_last = bf->bf_lastbf; - struct ath_desc *ds = bf_last->bf_desc; - struct ath_buf *bf_next, *bf_lastq = NULL; - struct list_head bf_head, bf_pending; - u16 seq_st = 0; - u32 ba[WME_BA_BMP_SIZE >> 5]; - int isaggr, txfail, txpending, sendbar = 0, needreset = 0; + list_for_each_entry(tbf, &bf_head, list) { + ath9k_hw_set11n_aggr_middle(sc->sc_ah, + tbf->bf_desc, ndelim); + } - skb = (struct sk_buff *)bf->bf_mpdu; - tx_info = IEEE80211_SKB_CB(skb); + /* + * link buffers of this frame to the aggregate + */ + list_splice_tail_init(&bf_head, bf_q); + nframes++; - if (tx_info->control.sta) { - an = (struct ath_node *)tx_info->control.sta->drv_priv; - tid = ATH_AN_2_TID(an, bf->bf_tidno); - } + if (bf_prev) { + bf_prev->bf_next = bf; + bf_prev->bf_lastfrm->bf_desc->ds_link = bf->bf_daddr; + } + bf_prev = bf; - isaggr = bf_isaggr(bf); - if (isaggr) { - if (txok) { - if (ATH_DS_TX_BA(ds)) { - /* - * extract starting sequence and - * block-ack bitmap - */ - seq_st = ATH_DS_BA_SEQ(ds); - memcpy(ba, - ATH_DS_BA_BITMAP(ds), - WME_BA_BMP_SIZE >> 3); - } else { - memset(ba, 0, WME_BA_BMP_SIZE >> 3); + } while (!list_empty(&tid->buf_q)); - /* - * AR5416 can become deaf/mute when BA - * issue happens. Chip needs to be reset. - * But AP code may have sychronization issues - * when perform internal reset in this routine. - * Only enable reset in STA mode for now. - */ - if (sc->sc_ah->ah_opmode == - NL80211_IFTYPE_STATION) - needreset = 1; - } - } else { - memset(ba, 0, WME_BA_BMP_SIZE >> 3); - } - } + bf_first->bf_al = al; + bf_first->bf_nframes = nframes; + *bf_last = bf_prev; + return status; +#undef PADBYTES +} - INIT_LIST_HEAD(&bf_pending); - INIT_LIST_HEAD(&bf_head); +static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, + struct ath_atx_tid *tid) +{ + struct ath_buf *bf, *tbf, *bf_last, *bf_lastaggr = NULL; + enum ATH_AGGR_STATUS status; + struct list_head bf_q; + struct aggr_rifs_param param = {0, 0, 0, 0, NULL}; + int prev_frames = 0; - while (bf) { - txfail = txpending = 0; - bf_next = bf->bf_next; + do { + if (list_empty(&tid->buf_q)) + return; - if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) { - /* transmit completion, subframe is - * acked by block ack */ - } else if (!isaggr && txok) { - /* transmit completion */ - } else { + INIT_LIST_HEAD(&bf_q); + + status = ath_tx_form_aggr(sc, tid, &bf_q, &bf_lastaggr, ¶m, + &prev_frames); - if (!(tid->state & AGGR_CLEANUP) && - ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) { - if (bf->bf_retries < ATH_MAX_SW_RETRIES) { - ath_tx_set_retry(sc, bf); - txpending = 1; - } else { - bf->bf_state.bf_type |= BUF_XRETRY; - txfail = 1; - sendbar = 1; - } - } else { - /* - * cleanup in progress, just fail - * the un-acked sub-frames - */ - txfail = 1; - } - } /* - * Remove ath_buf's of this sub-frame from aggregate queue. + * no frames picked up to be aggregated; block-ack + * window is not open */ - if (bf_next == NULL) { /* last subframe in the aggregate */ - ASSERT(bf->bf_lastfrm == bf_last); - - /* - * The last descriptor of the last sub frame could be - * a holding descriptor for h/w. If that's the case, - * bf->bf_lastfrm won't be in the bf_q. - * Make sure we handle bf_q properly here. - */ + if (list_empty(&bf_q)) + break; - if (!list_empty(bf_q)) { - bf_lastq = list_entry(bf_q->prev, - struct ath_buf, list); - list_cut_position(&bf_head, - bf_q, &bf_lastq->list); - } else { - /* - * XXX: if the last subframe only has one - * descriptor which is also being used as - * a holding descriptor. Then the ath_buf - * is not in the bf_q at all. - */ - INIT_LIST_HEAD(&bf_head); - } - } else { - ASSERT(!list_empty(bf_q)); - list_cut_position(&bf_head, - bf_q, &bf->bf_lastfrm->list); - } + bf = list_first_entry(&bf_q, struct ath_buf, list); + bf_last = list_entry(bf_q.prev, struct ath_buf, list); + bf->bf_lastbf = bf_last; - if (!txpending) { - /* - * complete the acked-ones/xretried ones; update - * block-ack window - */ - spin_lock_bh(&txq->axq_lock); - ath_tx_update_baw(sc, tid, bf->bf_seqno); - spin_unlock_bh(&txq->axq_lock); + /* + * if only one frame, send as non-aggregate + */ + if (bf->bf_nframes == 1) { + ASSERT(bf->bf_lastfrm == bf_last); - /* complete this sub-frame */ - ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar); - } else { - /* - * retry the un-acked ones - */ + bf->bf_state.bf_type &= ~BUF_AGGR; /* - * XXX: if the last descriptor is holding descriptor, - * in order to requeue the frame to software queue, we - * need to allocate a new descriptor and - * copy the content of holding descriptor to it. + * clear aggr bits for every descriptor + * XXX TODO: is there a way to optimize it? */ - if (bf->bf_next == NULL && - bf_last->bf_status & ATH_BUFSTATUS_STALE) { - struct ath_buf *tbf; + list_for_each_entry(tbf, &bf_q, list) { + ath9k_hw_clr11n_aggr(sc->sc_ah, tbf->bf_desc); + } - /* allocate new descriptor */ - spin_lock_bh(&sc->tx.txbuflock); - ASSERT(!list_empty((&sc->tx.txbuf))); - tbf = list_first_entry(&sc->tx.txbuf, - struct ath_buf, list); - list_del(&tbf->list); - spin_unlock_bh(&sc->tx.txbuflock); + ath_buf_set_rate(sc, bf); + ath_tx_txqaddbuf(sc, txq, &bf_q); + continue; + } - ATH_TXBUF_RESET(tbf); + /* + * setup first desc with rate and aggr info + */ + bf->bf_state.bf_type |= BUF_AGGR; + ath_buf_set_rate(sc, bf); + ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, bf->bf_al); - /* copy descriptor content */ - tbf->bf_mpdu = bf_last->bf_mpdu; - tbf->bf_buf_addr = bf_last->bf_buf_addr; - *(tbf->bf_desc) = *(bf_last->bf_desc); + /* + * anchor last frame of aggregate correctly + */ + ASSERT(bf_lastaggr); + ASSERT(bf_lastaggr->bf_lastfrm == bf_last); + tbf = bf_lastaggr; + ath9k_hw_set11n_aggr_last(sc->sc_ah, tbf->bf_desc); - /* link it to the frame */ - if (bf_lastq) { - bf_lastq->bf_desc->ds_link = - tbf->bf_daddr; - bf->bf_lastfrm = tbf; - ath9k_hw_cleartxdesc(sc->sc_ah, - bf->bf_lastfrm->bf_desc); - } else { - tbf->bf_state = bf_last->bf_state; - tbf->bf_lastfrm = tbf; - ath9k_hw_cleartxdesc(sc->sc_ah, - tbf->bf_lastfrm->bf_desc); + /* XXX: We don't enter into this loop, consider removing this */ + while (!list_empty(&bf_q) && !list_is_last(&tbf->list, &bf_q)) { + tbf = list_entry(tbf->list.next, struct ath_buf, list); + ath9k_hw_set11n_aggr_last(sc->sc_ah, tbf->bf_desc); + } - /* copy the DMA context */ - tbf->bf_dmacontext = - bf_last->bf_dmacontext; - } - list_add_tail(&tbf->list, &bf_head); - } else { - /* - * Clear descriptor status words for - * software retry - */ - ath9k_hw_cleartxdesc(sc->sc_ah, - bf->bf_lastfrm->bf_desc); - } + txq->axq_aggr_depth++; - /* - * Put this buffer to the temporary pending - * queue to retain ordering - */ - list_splice_tail_init(&bf_head, &bf_pending); - } + /* + * Normal aggregate, queue to hardware + */ + ath_tx_txqaddbuf(sc, txq, &bf_q); - bf = bf_next; + } while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH && + status != ATH_AGGR_BAW_CLOSED); +} + +int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, + u16 tid, u16 *ssn) +{ + struct ath_atx_tid *txtid; + struct ath_node *an; + + an = (struct ath_node *)sta->drv_priv; + + if (sc->sc_flags & SC_OP_TXAGGR) { + txtid = ATH_AN_2_TID(an, tid); + txtid->state |= AGGR_ADDBA_PROGRESS; + ath_tx_pause_tid(sc, txtid); } - if (tid->state & AGGR_CLEANUP) { - /* check to see if we're done with cleaning the h/w queue */ - spin_lock_bh(&txq->axq_lock); + return 0; +} - if (tid->baw_head == tid->baw_tail) { - tid->state &= ~AGGR_ADDBA_COMPLETE; - tid->addba_exchangeattempts = 0; - spin_unlock_bh(&txq->axq_lock); +int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) +{ + struct ath_node *an = (struct ath_node *)sta->drv_priv; + struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); + struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum]; + struct ath_buf *bf; + struct list_head bf_head; + INIT_LIST_HEAD(&bf_head); - tid->state &= ~AGGR_CLEANUP; + if (txtid->state & AGGR_CLEANUP) + return 0; - /* send buffered frames as singles */ - ath_tx_flush_tid(sc, tid); - } else - spin_unlock_bh(&txq->axq_lock); + if (!(txtid->state & AGGR_ADDBA_COMPLETE)) { + txtid->addba_exchangeattempts = 0; + return 0; + } - return; + ath_tx_pause_tid(sc, txtid); + + /* drop all software retried frames and mark this TID */ + spin_lock_bh(&txq->axq_lock); + while (!list_empty(&txtid->buf_q)) { + bf = list_first_entry(&txtid->buf_q, struct ath_buf, list); + if (!bf_isretried(bf)) { + /* + * NB: it's based on the assumption that + * software retried frame will always stay + * at the head of software queue. + */ + break; + } + list_cut_position(&bf_head, + &txtid->buf_q, &bf->bf_lastfrm->list); + ath_tx_update_baw(sc, txtid, bf->bf_seqno); + ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); } - /* - * prepend un-acked frames to the beginning of the pending frame queue - */ - if (!list_empty(&bf_pending)) { - spin_lock_bh(&txq->axq_lock); - /* Note: we _prepend_, we _do_not_ at to - * the end of the queue ! */ - list_splice(&bf_pending, &tid->buf_q); - ath_tx_queue_tid(txq, tid); + if (txtid->baw_head != txtid->baw_tail) { + spin_unlock_bh(&txq->axq_lock); + txtid->state |= AGGR_CLEANUP; + } else { + txtid->state &= ~AGGR_ADDBA_COMPLETE; + txtid->addba_exchangeattempts = 0; spin_unlock_bh(&txq->axq_lock); + ath_tx_flush_tid(sc, txtid); } - if (needreset) - ath_reset(sc, false); + return 0; +} - return; +void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) +{ + struct ath_atx_tid *txtid; + struct ath_node *an; + + an = (struct ath_node *)sta->drv_priv; + + if (sc->sc_flags & SC_OP_TXAGGR) { + txtid = ATH_AN_2_TID(an, tid); + txtid->baw_size = + IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor; + txtid->state |= AGGR_ADDBA_COMPLETE; + txtid->state &= ~AGGR_ADDBA_PROGRESS; + ath_tx_resume_tid(sc, txtid); + } } -static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, int nbad) +bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno) { - struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); + struct ath_atx_tid *txtid; - tx_info_priv->update_rc = false; - if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) - tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; + if (!(sc->sc_flags & SC_OP_TXAGGR)) + return false; - if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && - (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) { - if (bf_isdata(bf)) { - memcpy(&tx_info_priv->tx, &ds->ds_txstat, - sizeof(tx_info_priv->tx)); - tx_info_priv->n_frames = bf->bf_nframes; - tx_info_priv->n_bad_frames = nbad; - tx_info_priv->update_rc = true; + txtid = ATH_AN_2_TID(an, tidno); + + if (!(txtid->state & AGGR_ADDBA_COMPLETE)) { + if (!(txtid->state & AGGR_ADDBA_PROGRESS) && + (txtid->addba_exchangeattempts < ADDBA_EXCHANGE_ATTEMPTS)) { + txtid->addba_exchangeattempts++; + return true; } } + + return false; } -/* Process completed xmit descriptors from the specified queue */ +/********************/ +/* Queue Management */ +/********************/ -static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) +static u32 ath_txq_depth(struct ath_softc *sc, int qnum) +{ + return sc->tx.txq[qnum].axq_depth; +} + +static void ath_tx_stopdma(struct ath_softc *sc, struct ath_txq *txq) { struct ath_hal *ah = sc->sc_ah; - struct ath_buf *bf, *lastbf, *bf_held = NULL; - struct list_head bf_head; - struct ath_desc *ds; - int txok, nbad = 0; - int status; + (void) ath9k_hw_stoptxdma(ah, txq->axq_qnum); +} - DPRINTF(sc, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n", - txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum), - txq->axq_link); - - for (;;) { - spin_lock_bh(&txq->axq_lock); - if (list_empty(&txq->axq_q)) { - txq->axq_link = NULL; - txq->axq_linkbuf = NULL; - spin_unlock_bh(&txq->axq_lock); - break; - } - bf = list_first_entry(&txq->axq_q, struct ath_buf, list); - - /* - * There is a race condition that a BH gets scheduled - * after sw writes TxE and before hw re-load the last - * descriptor to get the newly chained one. - * Software must keep the last DONE descriptor as a - * holding descriptor - software does so by marking - * it with the STALE flag. - */ - bf_held = NULL; - if (bf->bf_status & ATH_BUFSTATUS_STALE) { - bf_held = bf; - if (list_is_last(&bf_held->list, &txq->axq_q)) { - /* FIXME: - * The holding descriptor is the last - * descriptor in queue. It's safe to remove - * the last holding descriptor in BH context. - */ - spin_unlock_bh(&txq->axq_lock); - break; - } else { - /* Lets work with the next buffer now */ - bf = list_entry(bf_held->list.next, - struct ath_buf, list); - } - } - - lastbf = bf->bf_lastbf; - ds = lastbf->bf_desc; /* NB: last decriptor */ - - status = ath9k_hw_txprocdesc(ah, ds); - if (status == -EINPROGRESS) { - spin_unlock_bh(&txq->axq_lock); - break; - } - if (bf->bf_desc == txq->axq_lastdsWithCTS) - txq->axq_lastdsWithCTS = NULL; - if (ds == txq->axq_gatingds) - txq->axq_gatingds = NULL; - - /* - * Remove ath_buf's of the same transmit unit from txq, - * however leave the last descriptor back as the holding - * descriptor for hw. - */ - lastbf->bf_status |= ATH_BUFSTATUS_STALE; - INIT_LIST_HEAD(&bf_head); - - if (!list_is_singular(&lastbf->list)) - list_cut_position(&bf_head, - &txq->axq_q, lastbf->list.prev); - - txq->axq_depth--; - - if (bf_isaggr(bf)) - txq->axq_aggr_depth--; - - txok = (ds->ds_txstat.ts_status == 0); - - spin_unlock_bh(&txq->axq_lock); - - if (bf_held) { - list_del(&bf_held->list); - spin_lock_bh(&sc->tx.txbuflock); - list_add_tail(&bf_held->list, &sc->tx.txbuf); - spin_unlock_bh(&sc->tx.txbuflock); - } - - if (!bf_isampdu(bf)) { - /* - * This frame is sent out as a single frame. - * Use hardware retry status for this frame. - */ - bf->bf_retries = ds->ds_txstat.ts_longretry; - if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) - bf->bf_state.bf_type |= BUF_XRETRY; - nbad = 0; - } else { - nbad = ath_tx_num_badfrms(sc, bf, txok); - } - - ath_tx_rc_status(bf, ds, nbad); - - /* - * Complete this transmit unit - */ - if (bf_isampdu(bf)) - ath_tx_complete_aggr_rifs(sc, txq, bf, &bf_head, txok); - else - ath_tx_complete_buf(sc, bf, &bf_head, txok, 0); - - /* Wake up mac80211 queue */ - - spin_lock_bh(&txq->axq_lock); - if (txq->stopped && ath_txq_depth(sc, txq->axq_qnum) <= - (ATH_TXBUF - 20)) { - int qnum; - qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc); - if (qnum != -1) { - ieee80211_wake_queue(sc->hw, qnum); - txq->stopped = 0; - } - - } - - /* - * schedule any pending packets if aggregation is enabled - */ - if (sc->sc_flags & SC_OP_TXAGGR) - ath_txq_schedule(sc, txq); - spin_unlock_bh(&txq->axq_lock); - } -} - -static void ath_tx_stopdma(struct ath_softc *sc, struct ath_txq *txq) +static void ath_get_beaconconfig(struct ath_softc *sc, int if_id, + struct ath_beacon_config *conf) { - struct ath_hal *ah = sc->sc_ah; + struct ieee80211_hw *hw = sc->hw; - (void) ath9k_hw_stoptxdma(ah, txq->axq_qnum); - DPRINTF(sc, ATH_DBG_XMIT, "tx queue [%u] %x, link %p\n", - txq->axq_qnum, ath9k_hw_gettxbuf(ah, txq->axq_qnum), - txq->axq_link); -} + /* fill in beacon config data */ -/* Drain only the data queues */ + conf->beacon_interval = hw->conf.beacon_int; + conf->listen_interval = 100; + conf->dtim_count = 1; + conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval; +} static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx) { @@ -1144,8 +905,6 @@ static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx) for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { if (ATH_TXQ_SETUP(sc, i)) { ath_tx_stopdma(sc, &sc->tx.txq[i]); - /* The TxDMA may not really be stopped. - * Double check the hal tx pending count */ npend += ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum); } @@ -1154,7 +913,7 @@ static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx) if (npend) { int r; - /* TxDMA not stopped, reset the hal */ + DPRINTF(sc, ATH_DBG_XMIT, "Unable to stop TxDMA. Reset HAL!\n"); spin_lock_bh(&sc->sc_resetlock); @@ -1172,485 +931,751 @@ static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx) } } -/* Add a sub-frame to block ack window */ - -static void ath_tx_addto_baw(struct ath_softc *sc, - struct ath_atx_tid *tid, - struct ath_buf *bf) +static void ath_txq_drain_pending_buffers(struct ath_softc *sc, + struct ath_txq *txq) { - int index, cindex; - - if (bf_isretried(bf)) - return; - - index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno); - cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); - - ASSERT(tid->tx_buf[cindex] == NULL); - tid->tx_buf[cindex] = bf; + struct ath_atx_ac *ac, *ac_tmp; + struct ath_atx_tid *tid, *tid_tmp; - if (index >= ((tid->baw_tail - tid->baw_head) & - (ATH_TID_MAX_BUFS - 1))) { - tid->baw_tail = cindex; - INCR(tid->baw_tail, ATH_TID_MAX_BUFS); + list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) { + list_del(&ac->list); + ac->sched = false; + list_for_each_entry_safe(tid, tid_tmp, &ac->tid_q, list) { + list_del(&tid->list); + tid->sched = false; + ath_tid_drain(sc, txq, tid); + } } } -/* - * Function to send an A-MPDU - * NB: must be called with txq lock held - */ -static int ath_tx_send_ampdu(struct ath_softc *sc, - struct ath_atx_tid *tid, - struct list_head *bf_head, - struct ath_tx_control *txctl) +struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) { - struct ath_buf *bf; - - BUG_ON(list_empty(bf_head)); + struct ath_hal *ah = sc->sc_ah; + struct ath9k_tx_queue_info qi; + int qnum; - bf = list_first_entry(bf_head, struct ath_buf, list); - bf->bf_state.bf_type |= BUF_AMPDU; + memset(&qi, 0, sizeof(qi)); + qi.tqi_subtype = subtype; + qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; + qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; + qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; + qi.tqi_physCompBuf = 0; /* - * Do not queue to h/w when any of the following conditions is true: - * - there are pending frames in software queue - * - the TID is currently paused for ADDBA/BAR request - * - seqno is not within block-ack window - * - h/w queue depth exceeds low water mark + * Enable interrupts only for EOL and DESC conditions. + * We mark tx descriptors to receive a DESC interrupt + * when a tx queue gets deep; otherwise waiting for the + * EOL to reap descriptors. Note that this is done to + * reduce interrupt load and this only defers reaping + * descriptors, never transmitting frames. Aside from + * reducing interrupts this also permits more concurrency. + * The only potential downside is if the tx queue backs + * up in which case the top half of the kernel may backup + * due to a lack of tx descriptors. + * + * The UAPSD queue is an exception, since we take a desc- + * based intr on the EOSP frames. */ - if (!list_empty(&tid->buf_q) || tid->paused || - !BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno) || - txctl->txq->axq_depth >= ATH_AGGR_MIN_QDEPTH) { + if (qtype == ATH9K_TX_QUEUE_UAPSD) + qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE; + else + qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | + TXQ_FLAG_TXDESCINT_ENABLE; + qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi); + if (qnum == -1) { /* - * Add this frame to software queue for scheduling later - * for aggregation. + * NB: don't print a message, this happens + * normally on parts with too few tx queues */ - list_splice_tail_init(bf_head, &tid->buf_q); - ath_tx_queue_tid(txctl->txq, tid); - return 0; + return NULL; } + if (qnum >= ARRAY_SIZE(sc->tx.txq)) { + DPRINTF(sc, ATH_DBG_FATAL, + "qnum %u out of range, max %u!\n", + qnum, (unsigned int)ARRAY_SIZE(sc->tx.txq)); + ath9k_hw_releasetxqueue(ah, qnum); + return NULL; + } + if (!ATH_TXQ_SETUP(sc, qnum)) { + struct ath_txq *txq = &sc->tx.txq[qnum]; - /* Add sub-frame to BAW */ - ath_tx_addto_baw(sc, tid, bf); - - /* Queue to h/w without aggregation */ - bf->bf_nframes = 1; - bf->bf_lastbf = bf->bf_lastfrm; /* one single frame */ - ath_buf_set_rate(sc, bf); - ath_tx_txqaddbuf(sc, txctl->txq, bf_head); - - return 0; + txq->axq_qnum = qnum; + txq->axq_link = NULL; + INIT_LIST_HEAD(&txq->axq_q); + INIT_LIST_HEAD(&txq->axq_acq); + spin_lock_init(&txq->axq_lock); + txq->axq_depth = 0; + txq->axq_aggr_depth = 0; + txq->axq_totalqueued = 0; + txq->axq_linkbuf = NULL; + sc->tx.txqsetup |= 1<tx.txq[qnum]; } -/* - * looks up the rate - * returns aggr limit based on lowest of the rates - */ -static u32 ath_lookup_rate(struct ath_softc *sc, - struct ath_buf *bf, - struct ath_atx_tid *tid) +static int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype) { - struct ath_rate_table *rate_table = sc->cur_rate_table; - struct sk_buff *skb; - struct ieee80211_tx_info *tx_info; - struct ieee80211_tx_rate *rates; - struct ath_tx_info_priv *tx_info_priv; - u32 max_4ms_framelen, frame_length; - u16 aggr_limit, legacy = 0, maxampdu; - int i; + int qnum; - skb = (struct sk_buff *)bf->bf_mpdu; - tx_info = IEEE80211_SKB_CB(skb); - rates = tx_info->control.rates; - tx_info_priv = - (struct ath_tx_info_priv *)tx_info->rate_driver_data[0]; + switch (qtype) { + case ATH9K_TX_QUEUE_DATA: + if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) { + DPRINTF(sc, ATH_DBG_FATAL, + "HAL AC %u out of range, max %zu!\n", + haltype, ARRAY_SIZE(sc->tx.hwq_map)); + return -1; + } + qnum = sc->tx.hwq_map[haltype]; + break; + case ATH9K_TX_QUEUE_BEACON: + qnum = sc->beacon.beaconq; + break; + case ATH9K_TX_QUEUE_CAB: + qnum = sc->beacon.cabq->axq_qnum; + break; + default: + qnum = -1; + } + return qnum; +} - /* - * Find the lowest frame length among the rate series that will have a - * 4ms transmit duration. - * TODO - TXOP limit needs to be considered. - */ - max_4ms_framelen = ATH_AMPDU_LIMIT_MAX; +struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb) +{ + struct ath_txq *txq = NULL; + int qnum; - for (i = 0; i < 4; i++) { - if (rates[i].count) { - if (!WLAN_RC_PHY_HT(rate_table->info[rates[i].idx].phy)) { - legacy = 1; - break; - } + qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc); + txq = &sc->tx.txq[qnum]; - frame_length = - rate_table->info[rates[i].idx].max_4ms_framelen; - max_4ms_framelen = min(max_4ms_framelen, frame_length); - } + spin_lock_bh(&txq->axq_lock); + + if (txq->axq_depth >= (ATH_TXBUF - 20)) { + DPRINTF(sc, ATH_DBG_FATAL, + "TX queue: %d is full, depth: %d\n", + qnum, txq->axq_depth); + ieee80211_stop_queue(sc->hw, skb_get_queue_mapping(skb)); + txq->stopped = 1; + spin_unlock_bh(&txq->axq_lock); + return NULL; } - /* - * limit aggregate size by the minimum rate if rate selected is - * not a probe rate, if rate selected is a probe rate then - * avoid aggregation of this packet. - */ - if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy) + spin_unlock_bh(&txq->axq_lock); + + return txq; +} + +int ath_txq_update(struct ath_softc *sc, int qnum, + struct ath9k_tx_queue_info *qinfo) +{ + struct ath_hal *ah = sc->sc_ah; + int error = 0; + struct ath9k_tx_queue_info qi; + + if (qnum == sc->beacon.beaconq) { + /* + * XXX: for beacon queue, we just save the parameter. + * It will be picked up by ath_beaconq_config when + * it's necessary. + */ + sc->beacon.beacon_qi = *qinfo; return 0; + } - aggr_limit = min(max_4ms_framelen, - (u32)ATH_AMPDU_LIMIT_DEFAULT); + ASSERT(sc->tx.txq[qnum].axq_qnum == qnum); + + ath9k_hw_get_txq_props(ah, qnum, &qi); + qi.tqi_aifs = qinfo->tqi_aifs; + qi.tqi_cwmin = qinfo->tqi_cwmin; + qi.tqi_cwmax = qinfo->tqi_cwmax; + qi.tqi_burstTime = qinfo->tqi_burstTime; + qi.tqi_readyTime = qinfo->tqi_readyTime; + + if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) { + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to update hardware queue %u!\n", qnum); + error = -EIO; + } else { + ath9k_hw_resettxqueue(ah, qnum); + } + + return error; +} + +int ath_cabq_update(struct ath_softc *sc) +{ + struct ath9k_tx_queue_info qi; + int qnum = sc->beacon.cabq->axq_qnum; + struct ath_beacon_config conf; + ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi); /* - * h/w can accept aggregates upto 16 bit lengths (65535). - * The IE, however can hold upto 65536, which shows up here - * as zero. Ignore 65536 since we are constrained by hw. + * Ensure the readytime % is within the bounds. */ - maxampdu = tid->an->maxampdu; - if (maxampdu) - aggr_limit = min(aggr_limit, maxampdu); + if (sc->sc_config.cabqReadytime < ATH9K_READY_TIME_LO_BOUND) + sc->sc_config.cabqReadytime = ATH9K_READY_TIME_LO_BOUND; + else if (sc->sc_config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND) + sc->sc_config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND; - return aggr_limit; + ath_get_beaconconfig(sc, ATH_IF_ID_ANY, &conf); + qi.tqi_readyTime = + (conf.beacon_interval * sc->sc_config.cabqReadytime) / 100; + ath_txq_update(sc, qnum, &qi); + + return 0; } -/* - * returns the number of delimiters to be added to - * meet the minimum required mpdudensity. - * caller should make sure that the rate is HT rate . - */ -static int ath_compute_num_delims(struct ath_softc *sc, - struct ath_atx_tid *tid, - struct ath_buf *bf, - u16 frmlen) +void ath_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) { - struct ath_rate_table *rt = sc->cur_rate_table; - struct sk_buff *skb = bf->bf_mpdu; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - u32 nsymbits, nsymbols, mpdudensity; - u16 minlen; - u8 rc, flags, rix; - int width, half_gi, ndelim, mindelim; + struct ath_buf *bf, *lastbf; + struct list_head bf_head; - /* Select standard number of delimiters based on frame length alone */ - ndelim = ATH_AGGR_GET_NDELIM(frmlen); + INIT_LIST_HEAD(&bf_head); /* - * If encryption enabled, hardware requires some more padding between - * subframes. - * TODO - this could be improved to be dependent on the rate. - * The hardware can keep up at lower rates, but not higher rates + * NB: this assumes output has been stopped and + * we do not need to block ath_tx_tasklet */ - if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) - ndelim += ATH_AGGR_ENCRYPTDELIM; + for (;;) { + spin_lock_bh(&txq->axq_lock); - /* - * Convert desired mpdu density from microeconds to bytes based - * on highest rate in rate series (i.e. first rate) to determine - * required minimum length for subframe. Take into account - * whether high rate is 20 or 40Mhz and half or full GI. - */ - mpdudensity = tid->an->mpdudensity; + if (list_empty(&txq->axq_q)) { + txq->axq_link = NULL; + txq->axq_linkbuf = NULL; + spin_unlock_bh(&txq->axq_lock); + break; + } - /* - * If there is no mpdu density restriction, no further calculation - * is needed. - */ - if (mpdudensity == 0) - return ndelim; + bf = list_first_entry(&txq->axq_q, struct ath_buf, list); - rix = tx_info->control.rates[0].idx; - flags = tx_info->control.rates[0].flags; - rc = rt->info[rix].ratecode; - width = (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 1 : 0; - half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0; + if (bf->bf_status & ATH_BUFSTATUS_STALE) { + list_del(&bf->list); + spin_unlock_bh(&txq->axq_lock); - if (half_gi) - nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity); - else - nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity); + spin_lock_bh(&sc->tx.txbuflock); + list_add_tail(&bf->list, &sc->tx.txbuf); + spin_unlock_bh(&sc->tx.txbuflock); + continue; + } - if (nsymbols == 0) - nsymbols = 1; + lastbf = bf->bf_lastbf; + if (!retry_tx) + lastbf->bf_desc->ds_txstat.ts_flags = + ATH9K_TX_SW_ABORTED; - nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width]; - minlen = (nsymbols * nsymbits) / BITS_PER_BYTE; + /* remove ath_buf's of the same mpdu from txq */ + list_cut_position(&bf_head, &txq->axq_q, &lastbf->list); + txq->axq_depth--; - /* Is frame shorter than required minimum length? */ - if (frmlen < minlen) { - /* Get the minimum number of delimiters required. */ - mindelim = (minlen - frmlen) / ATH_AGGR_DELIM_SZ; - ndelim = max(mindelim, ndelim); + spin_unlock_bh(&txq->axq_lock); + + if (bf_isampdu(bf)) + ath_tx_complete_aggr_rifs(sc, txq, bf, &bf_head, 0); + else + ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); } - return ndelim; + /* flush any pending frames if aggregation is enabled */ + if (sc->sc_flags & SC_OP_TXAGGR) { + if (!retry_tx) { + spin_lock_bh(&txq->axq_lock); + ath_txq_drain_pending_buffers(sc, txq); + spin_unlock_bh(&txq->axq_lock); + } + } } -/* - * For aggregation from software buffer queue. - * NB: must be called with txq lock held - */ -static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, - struct ath_atx_tid *tid, - struct list_head *bf_q, - struct ath_buf **bf_last, - struct aggr_rifs_param *param, - int *prev_frames) +void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq) { -#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) - struct ath_buf *bf, *tbf, *bf_first, *bf_prev = NULL; - struct list_head bf_head; - int rl = 0, nframes = 0, ndelim; - u16 aggr_limit = 0, al = 0, bpad = 0, - al_delta, h_baw = tid->baw_size / 2; - enum ATH_AGGR_STATUS status = ATH_AGGR_DONE; - int prev_al = 0; - INIT_LIST_HEAD(&bf_head); + ath9k_hw_releasetxqueue(sc->sc_ah, txq->axq_qnum); + sc->tx.txqsetup &= ~(1<axq_qnum); +} - BUG_ON(list_empty(&tid->buf_q)); +void ath_draintxq(struct ath_softc *sc, bool retry_tx) +{ + if (!(sc->sc_flags & SC_OP_INVALID)) + (void) ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); - bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list); + ath_drain_txdataq(sc, retry_tx); +} - do { - bf = list_first_entry(&tid->buf_q, struct ath_buf, list); +void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) +{ + struct ath_atx_ac *ac; + struct ath_atx_tid *tid; - /* - * do not step over block-ack window - */ - if (!BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno)) { - status = ATH_AGGR_BAW_CLOSED; - break; - } - - if (!rl) { - aggr_limit = ath_lookup_rate(sc, bf, tid); - rl = 1; - } - - /* - * do not exceed aggregation limit - */ - al_delta = ATH_AGGR_DELIM_SZ + bf->bf_frmlen; - - if (nframes && (aggr_limit < - (al + bpad + al_delta + prev_al))) { - status = ATH_AGGR_LIMITED; - break; - } + if (list_empty(&txq->axq_acq)) + return; - /* - * do not exceed subframe limit - */ - if ((nframes + *prev_frames) >= - min((int)h_baw, ATH_AMPDU_SUBFRAME_DEFAULT)) { - status = ATH_AGGR_LIMITED; - break; - } + ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list); + list_del(&ac->list); + ac->sched = false; - /* - * add padding for previous frame to aggregation length - */ - al += bpad + al_delta; + do { + if (list_empty(&ac->tid_q)) + return; - /* - * Get the delimiters needed to meet the MPDU - * density for this node. - */ - ndelim = ath_compute_num_delims(sc, tid, bf_first, bf->bf_frmlen); + tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, list); + list_del(&tid->list); + tid->sched = false; - bpad = PADBYTES(al_delta) + (ndelim << 2); + if (tid->paused) + continue; - bf->bf_next = NULL; - bf->bf_lastfrm->bf_desc->ds_link = 0; + if ((txq->axq_depth % 2) == 0) + ath_tx_sched_aggr(sc, txq, tid); /* - * this packet is part of an aggregate - * - remove all descriptors belonging to this frame from - * software queue - * - add it to block ack window - * - set up descriptors for aggregation + * add tid to round-robin queue if more frames + * are pending for the tid */ - list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list); - ath_tx_addto_baw(sc, tid, bf); - - list_for_each_entry(tbf, &bf_head, list) { - ath9k_hw_set11n_aggr_middle(sc->sc_ah, - tbf->bf_desc, ndelim); - } + if (!list_empty(&tid->buf_q)) + ath_tx_queue_tid(txq, tid); - /* - * link buffers of this frame to the aggregate - */ - list_splice_tail_init(&bf_head, bf_q); - nframes++; + break; + } while (!list_empty(&ac->tid_q)); - if (bf_prev) { - bf_prev->bf_next = bf; - bf_prev->bf_lastfrm->bf_desc->ds_link = bf->bf_daddr; + if (!list_empty(&ac->tid_q)) { + if (!ac->sched) { + ac->sched = true; + list_add_tail(&ac->list, &txq->axq_acq); } - bf_prev = bf; + } +} -#ifdef AGGR_NOSHORT - /* - * terminate aggregation on a small packet boundary - */ - if (bf->bf_frmlen < ATH_AGGR_MINPLEN) { - status = ATH_AGGR_SHORTPKT; - break; - } -#endif - } while (!list_empty(&tid->buf_q)); +int ath_tx_setup(struct ath_softc *sc, int haltype) +{ + struct ath_txq *txq; - bf_first->bf_al = al; - bf_first->bf_nframes = nframes; - *bf_last = bf_prev; - return status; -#undef PADBYTES + if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) { + DPRINTF(sc, ATH_DBG_FATAL, + "HAL AC %u out of range, max %zu!\n", + haltype, ARRAY_SIZE(sc->tx.hwq_map)); + return 0; + } + txq = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, haltype); + if (txq != NULL) { + sc->tx.hwq_map[haltype] = txq->axq_qnum; + return 1; + } else + return 0; } +/***********/ +/* TX, DMA */ +/***********/ + /* - * process pending frames possibly doing a-mpdu aggregation - * NB: must be called with txq lock held + * Insert a chain of ath_buf (descriptors) on a txq and + * assume the descriptors are already chained together by caller. */ -static void ath_tx_sched_aggr(struct ath_softc *sc, - struct ath_txq *txq, struct ath_atx_tid *tid) +static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, + struct list_head *head) { - struct ath_buf *bf, *tbf, *bf_last, *bf_lastaggr = NULL; - enum ATH_AGGR_STATUS status; - struct list_head bf_q; - struct aggr_rifs_param param = {0, 0, 0, 0, NULL}; - int prev_frames = 0; - - do { - if (list_empty(&tid->buf_q)) - return; - - INIT_LIST_HEAD(&bf_q); + struct ath_hal *ah = sc->sc_ah; + struct ath_buf *bf; - status = ath_tx_form_aggr(sc, tid, &bf_q, &bf_lastaggr, ¶m, - &prev_frames); + /* + * Insert the frame on the outbound list and + * pass it on to the hardware. + */ - /* - * no frames picked up to be aggregated; block-ack - * window is not open - */ - if (list_empty(&bf_q)) - break; + if (list_empty(head)) + return; - bf = list_first_entry(&bf_q, struct ath_buf, list); - bf_last = list_entry(bf_q.prev, struct ath_buf, list); - bf->bf_lastbf = bf_last; + bf = list_first_entry(head, struct ath_buf, list); - /* - * if only one frame, send as non-aggregate - */ - if (bf->bf_nframes == 1) { - ASSERT(bf->bf_lastfrm == bf_last); + list_splice_tail_init(head, &txq->axq_q); + txq->axq_depth++; + txq->axq_totalqueued++; + txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list); - bf->bf_state.bf_type &= ~BUF_AGGR; - /* - * clear aggr bits for every descriptor - * XXX TODO: is there a way to optimize it? - */ - list_for_each_entry(tbf, &bf_q, list) { - ath9k_hw_clr11n_aggr(sc->sc_ah, tbf->bf_desc); - } + DPRINTF(sc, ATH_DBG_QUEUE, + "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth); - ath_buf_set_rate(sc, bf); - ath_tx_txqaddbuf(sc, txq, &bf_q); - continue; - } + if (txq->axq_link == NULL) { + ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); + DPRINTF(sc, ATH_DBG_XMIT, + "TXDP[%u] = %llx (%p)\n", + txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc); + } else { + *txq->axq_link = bf->bf_daddr; + DPRINTF(sc, ATH_DBG_XMIT, "link[%u] (%p)=%llx (%p)\n", + txq->axq_qnum, txq->axq_link, + ito64(bf->bf_daddr), bf->bf_desc); + } + txq->axq_link = &(bf->bf_lastbf->bf_desc->ds_link); + ath9k_hw_txstart(ah, txq->axq_qnum); +} - /* - * setup first desc with rate and aggr info - */ - bf->bf_state.bf_type |= BUF_AGGR; - ath_buf_set_rate(sc, bf); - ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, bf->bf_al); +static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc) +{ + struct ath_buf *bf = NULL; - /* - * anchor last frame of aggregate correctly - */ - ASSERT(bf_lastaggr); - ASSERT(bf_lastaggr->bf_lastfrm == bf_last); - tbf = bf_lastaggr; - ath9k_hw_set11n_aggr_last(sc->sc_ah, tbf->bf_desc); + spin_lock_bh(&sc->tx.txbuflock); - /* XXX: We don't enter into this loop, consider removing this */ - while (!list_empty(&bf_q) && !list_is_last(&tbf->list, &bf_q)) { - tbf = list_entry(tbf->list.next, struct ath_buf, list); - ath9k_hw_set11n_aggr_last(sc->sc_ah, tbf->bf_desc); - } + if (unlikely(list_empty(&sc->tx.txbuf))) { + spin_unlock_bh(&sc->tx.txbuflock); + return NULL; + } - txq->axq_aggr_depth++; + bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); + list_del(&bf->list); - /* - * Normal aggregate, queue to hardware - */ - ath_tx_txqaddbuf(sc, txq, &bf_q); + spin_unlock_bh(&sc->tx.txbuflock); - } while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH && - status != ATH_AGGR_BAW_CLOSED); + return bf; } -/* Called with txq lock held */ - -static void ath_tid_drain(struct ath_softc *sc, - struct ath_txq *txq, - struct ath_atx_tid *tid) - +static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, + struct list_head *bf_head, + struct ath_tx_control *txctl) { struct ath_buf *bf; - struct list_head bf_head; - INIT_LIST_HEAD(&bf_head); - - for (;;) { - if (list_empty(&tid->buf_q)) - break; - bf = list_first_entry(&tid->buf_q, struct ath_buf, list); - list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list); + BUG_ON(list_empty(bf_head)); - /* update baw for software retried frame */ - if (bf_isretried(bf)) - ath_tx_update_baw(sc, tid, bf->bf_seqno); + bf = list_first_entry(bf_head, struct ath_buf, list); + bf->bf_state.bf_type |= BUF_AMPDU; + /* + * Do not queue to h/w when any of the following conditions is true: + * - there are pending frames in software queue + * - the TID is currently paused for ADDBA/BAR request + * - seqno is not within block-ack window + * - h/w queue depth exceeds low water mark + */ + if (!list_empty(&tid->buf_q) || tid->paused || + !BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno) || + txctl->txq->axq_depth >= ATH_AGGR_MIN_QDEPTH) { /* - * do not indicate packets while holding txq spinlock. - * unlock is intentional here + * Add this frame to software queue for scheduling later + * for aggregation. */ - spin_unlock(&txq->axq_lock); + list_splice_tail_init(bf_head, &tid->buf_q); + ath_tx_queue_tid(txctl->txq, tid); + return; + } + + /* Add sub-frame to BAW */ + ath_tx_addto_baw(sc, tid, bf); + + /* Queue to h/w without aggregation */ + bf->bf_nframes = 1; + bf->bf_lastbf = bf->bf_lastfrm; /* one single frame */ + ath_buf_set_rate(sc, bf); + ath_tx_txqaddbuf(sc, txctl->txq, bf_head); + + return; +} + +static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, + struct ath_atx_tid *tid, + struct list_head *bf_head) +{ + struct ath_buf *bf; + + BUG_ON(list_empty(bf_head)); + + bf = list_first_entry(bf_head, struct ath_buf, list); + bf->bf_state.bf_type &= ~BUF_AMPDU; + + /* update starting sequence number for subsequent ADDBA request */ + INCR(tid->seq_start, IEEE80211_SEQ_MAX); + + bf->bf_nframes = 1; + bf->bf_lastbf = bf->bf_lastfrm; + ath_buf_set_rate(sc, bf); + ath_tx_txqaddbuf(sc, txq, bf_head); +} + +static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr; + enum ath9k_pkt_type htype; + __le16 fc; + + hdr = (struct ieee80211_hdr *)skb->data; + fc = hdr->frame_control; + + if (ieee80211_is_beacon(fc)) + htype = ATH9K_PKT_TYPE_BEACON; + else if (ieee80211_is_probe_resp(fc)) + htype = ATH9K_PKT_TYPE_PROBE_RESP; + else if (ieee80211_is_atim(fc)) + htype = ATH9K_PKT_TYPE_ATIM; + else if (ieee80211_is_pspoll(fc)) + htype = ATH9K_PKT_TYPE_PSPOLL; + else + htype = ATH9K_PKT_TYPE_NORMAL; + + return htype; +} + +static bool is_pae(struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr; + __le16 fc; + + hdr = (struct ieee80211_hdr *)skb->data; + fc = hdr->frame_control; + + if (ieee80211_is_data(fc)) { + if (ieee80211_is_nullfunc(fc) || + /* Port Access Entity (IEEE 802.1X) */ + (skb->protocol == cpu_to_be16(ETH_P_PAE))) { + return true; + } + } + + return false; +} + +static int get_hw_crypto_keytype(struct sk_buff *skb) +{ + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + + if (tx_info->control.hw_key) { + if (tx_info->control.hw_key->alg == ALG_WEP) + return ATH9K_KEY_TYPE_WEP; + else if (tx_info->control.hw_key->alg == ALG_TKIP) + return ATH9K_KEY_TYPE_TKIP; + else if (tx_info->control.hw_key->alg == ALG_CCMP) + return ATH9K_KEY_TYPE_AES; + } + + return ATH9K_KEY_TYPE_CLEAR; +} + +static void assign_aggr_tid_seqno(struct sk_buff *skb, + struct ath_buf *bf) +{ + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr; + struct ath_node *an; + struct ath_atx_tid *tid; + __le16 fc; + u8 *qc; + + if (!tx_info->control.sta) + return; + + an = (struct ath_node *)tx_info->control.sta->drv_priv; + hdr = (struct ieee80211_hdr *)skb->data; + fc = hdr->frame_control; + + if (ieee80211_is_data_qos(fc)) { + qc = ieee80211_get_qos_ctl(hdr); + bf->bf_tidno = qc[0] & 0xf; + } + + /* + * For HT capable stations, we save tidno for later use. + * We also override seqno set by upper layer with the one + * in tx aggregation state. + * + * If fragmentation is on, the sequence number is + * not overridden, since it has been + * incremented by the fragmentation routine. + * + * FIXME: check if the fragmentation threshold exceeds + * IEEE80211 max. + */ + tid = ATH_AN_2_TID(an, bf->bf_tidno); + hdr->seq_ctrl = cpu_to_le16(tid->seq_next << + IEEE80211_SEQ_SEQ_SHIFT); + bf->bf_seqno = tid->seq_next; + INCR(tid->seq_next, IEEE80211_SEQ_MAX); +} + +static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb, + struct ath_txq *txq) +{ + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + int flags = 0; + + flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */ + flags |= ATH9K_TXDESC_INTREQ; + + if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) + flags |= ATH9K_TXDESC_NOACK; + if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) + flags |= ATH9K_TXDESC_RTSENA; + + return flags; +} + +/* + * rix - rate index + * pktlen - total bytes (delims + data + fcs + pads + pad delims) + * width - 0 for 20 MHz, 1 for 40 MHz + * half_gi - to use 4us v/s 3.6 us for symbol time + */ +static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, + int width, int half_gi, bool shortPreamble) +{ + struct ath_rate_table *rate_table = sc->cur_rate_table; + u32 nbits, nsymbits, duration, nsymbols; + u8 rc; + int streams, pktlen; + + pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen; + rc = rate_table->info[rix].ratecode; + + /* for legacy rates, use old function to compute packet duration */ + if (!IS_HT_RATE(rc)) + return ath9k_hw_computetxtime(sc->sc_ah, rate_table, pktlen, + rix, shortPreamble); + + /* find number of symbols: PLCP + data */ + nbits = (pktlen << 3) + OFDM_PLCP_BITS; + nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width]; + nsymbols = (nbits + nsymbits - 1) / nsymbits; + + if (!half_gi) + duration = SYMBOL_TIME(nsymbols); + else + duration = SYMBOL_TIME_HALFGI(nsymbols); + + /* addup duration for legacy/ht training and signal fields */ + streams = HT_RC_2_STREAMS(rc); + duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams); + + return duration; +} + +static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) +{ + struct ath_hal *ah = sc->sc_ah; + struct ath_rate_table *rt; + struct ath_desc *ds = bf->bf_desc; + struct ath_desc *lastds = bf->bf_lastbf->bf_desc; + struct ath9k_11n_rate_series series[4]; + struct sk_buff *skb; + struct ieee80211_tx_info *tx_info; + struct ieee80211_tx_rate *rates; + struct ieee80211_hdr *hdr; + struct ieee80211_hw *hw = sc->hw; + int i, flags, rtsctsena = 0, enable_g_protection = 0; + u32 ctsduration = 0; + u8 rix = 0, cix, ctsrate = 0; + __le16 fc; + + memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); + + skb = (struct sk_buff *)bf->bf_mpdu; + hdr = (struct ieee80211_hdr *)skb->data; + fc = hdr->frame_control; + tx_info = IEEE80211_SKB_CB(skb); + rates = tx_info->control.rates; + + if (ieee80211_has_morefrags(fc) || + (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) { + rates[1].count = rates[2].count = rates[3].count = 0; + rates[1].idx = rates[2].idx = rates[3].idx = 0; + rates[0].count = ATH_TXMAXTRY; + } + + /* get the cix for the lowest valid rix */ + rt = sc->cur_rate_table; + for (i = 3; i >= 0; i--) { + if (rates[i].count && (rates[i].idx >= 0)) { + rix = rates[i].idx; + break; + } + } + + flags = (bf->bf_flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)); + cix = rt->info[rix].ctrl_rate; + + /* All protection frames are transmited at 2Mb/s for 802.11g, + * otherwise we transmit them at 1Mb/s */ + if (hw->conf.channel->band == IEEE80211_BAND_2GHZ && + !conf_is_ht(&hw->conf)) + enable_g_protection = 1; + + /* + * If 802.11g protection is enabled, determine whether to use RTS/CTS or + * just CTS. Note that this is only done for OFDM/HT unicast frames. + */ + if (sc->sc_protmode != PROT_M_NONE && !(bf->bf_flags & ATH9K_TXDESC_NOACK) + && (rt->info[rix].phy == WLAN_RC_PHY_OFDM || + WLAN_RC_PHY_HT(rt->info[rix].phy))) { + if (sc->sc_protmode == PROT_M_RTSCTS) + flags = ATH9K_TXDESC_RTSENA; + else if (sc->sc_protmode == PROT_M_CTSONLY) + flags = ATH9K_TXDESC_CTSENA; + + cix = rt->info[enable_g_protection].ctrl_rate; + rtsctsena = 1; + } + + /* For 11n, the default behavior is to enable RTS for hw retried frames. + * We enable the global flag here and let rate series flags determine + * which rates will actually use RTS. + */ + if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) && bf_isdata(bf)) { + /* 802.11g protection not needed, use our default behavior */ + if (!rtsctsena) + flags = ATH9K_TXDESC_RTSENA; + } + + /* Set protection if aggregate protection on */ + if (sc->sc_config.ath_aggr_prot && + (!bf_isaggr(bf) || (bf_isaggr(bf) && bf->bf_al < 8192))) { + flags = ATH9K_TXDESC_RTSENA; + cix = rt->info[enable_g_protection].ctrl_rate; + rtsctsena = 1; + } + + /* For AR5416 - RTS cannot be followed by a frame larger than 8K */ + if (bf_isaggr(bf) && (bf->bf_al > ah->ah_caps.rts_aggr_limit)) + flags &= ~(ATH9K_TXDESC_RTSENA); + + /* + * CTS transmit rate is derived from the transmit rate by looking in the + * h/w rate table. We must also factor in whether or not a short + * preamble is to be used. NB: cix is set above where RTS/CTS is enabled + */ + ctsrate = rt->info[cix].ratecode | + (bf_isshpreamble(bf) ? rt->info[cix].short_preamble : 0); + + for (i = 0; i < 4; i++) { + if (!rates[i].count || (rates[i].idx < 0)) + continue; + + rix = rates[i].idx; + + series[i].Rate = rt->info[rix].ratecode | + (bf_isshpreamble(bf) ? rt->info[rix].short_preamble : 0); + + series[i].Tries = rates[i].count; + + series[i].RateFlags = ( + (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) ? + ATH9K_RATESERIES_RTS_CTS : 0) | + ((rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? + ATH9K_RATESERIES_2040 : 0) | + ((rates[i].flags & IEEE80211_TX_RC_SHORT_GI) ? + ATH9K_RATESERIES_HALFGI : 0); + + series[i].PktDuration = ath_pkt_duration(sc, rix, bf, + (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) != 0, + (rates[i].flags & IEEE80211_TX_RC_SHORT_GI), + bf_isshpreamble(bf)); - /* complete this sub-frame */ - ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); + series[i].ChSel = sc->sc_tx_chainmask; - spin_lock(&txq->axq_lock); + if (rtsctsena) + series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; } - /* - * TODO: For frame(s) that are in the retry state, we will reuse the - * sequence number(s) without setting the retry bit. The - * alternative is to give up on these and BAR the receiver's window - * forward. - */ - tid->seq_next = tid->seq_start; - tid->baw_tail = tid->baw_head; -} - -/* - * Drain all pending buffers - * NB: must be called with txq lock held - */ -static void ath_txq_drain_pending_buffers(struct ath_softc *sc, - struct ath_txq *txq) -{ - struct ath_atx_ac *ac, *ac_tmp; - struct ath_atx_tid *tid, *tid_tmp; + /* set dur_update_en for l-sig computation except for PS-Poll frames */ + ath9k_hw_set11n_ratescenario(ah, ds, lastds, !bf_ispspoll(bf), + ctsrate, ctsduration, + series, 4, flags); - list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) { - list_del(&ac->list); - ac->sched = false; - list_for_each_entry_safe(tid, tid_tmp, &ac->tid_q, list) { - list_del(&tid->list); - tid->sched = false; - ath_tid_drain(sc, txq, tid); - } - } + if (sc->sc_config.ath_aggr_prot && flags) + ath9k_hw_set11n_burstduration(ah, ds, 8192); } static int ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf, @@ -1672,8 +1697,6 @@ static int ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf, ATH_TXBUF_RESET(bf); - /* Frame type */ - bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3); ieee80211_is_data(fc) ? @@ -1695,8 +1718,6 @@ static int ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf, bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq); - /* Crypto */ - bf->bf_keytype = get_hw_crypto_keytype(skb); if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) { @@ -1706,12 +1727,9 @@ static int ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf, bf->bf_keyix = ATH9K_TXKEYIX_INVALID; } - /* Assign seqno, tidno */ - if (ieee80211_is_data_qos(fc) && (sc->sc_flags & SC_OP_TXAGGR)) assign_aggr_tid_seqno(skb, bf); - /* DMA setup */ bf->bf_mpdu = skb; bf->bf_dmacontext = dma_map_single(sc->dev, skb->data, @@ -1745,14 +1763,10 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, INIT_LIST_HEAD(&bf_head); list_add_tail(&bf->list, &bf_head); - /* setup descriptor */ - ds = bf->bf_desc; ds->ds_link = 0; ds->ds_data = bf->bf_buf_addr; - /* Formulate first tx descriptor with tx controls */ - ath9k_hw_set11n_txdesc(ah, ds, bf->bf_frmlen, frm_type, MAX_RATE_POWER, bf->bf_keyix, bf->bf_keytype, bf->bf_flags); @@ -1803,8 +1817,6 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb, struct ath_buf *bf; int r; - /* Check if a tx buffer is available */ - bf = ath_tx_get_buffer(sc); if (!bf) { DPRINTF(sc, ATH_DBG_XMIT, "TX buffers are full\n"); @@ -1841,570 +1853,378 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb, return 0; } -/* Initialize TX queue and h/w */ - -int ath_tx_init(struct ath_softc *sc, int nbufs) -{ - int error = 0; - - do { - spin_lock_init(&sc->tx.txbuflock); - - /* Setup tx descriptors */ - error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf, - "tx", nbufs, 1); - if (error != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "Failed to allocate tx descriptors: %d\n", - error); - break; - } - - /* XXX allocate beacon state together with vap */ - error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf, - "beacon", ATH_BCBUF, 1); - if (error != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "Failed to allocate beacon descriptors: %d\n", - error); - break; - } - - } while (0); - - if (error != 0) - ath_tx_cleanup(sc); - - return error; -} - -/* Reclaim all tx queue resources */ - -int ath_tx_cleanup(struct ath_softc *sc) -{ - /* cleanup beacon descriptors */ - if (sc->beacon.bdma.dd_desc_len != 0) - ath_descdma_cleanup(sc, &sc->beacon.bdma, &sc->beacon.bbuf); - - /* cleanup tx descriptors */ - if (sc->tx.txdma.dd_desc_len != 0) - ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf); - - return 0; -} - -/* Setup a h/w transmit queue */ - -struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) +void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb) { - struct ath_hal *ah = sc->sc_ah; - struct ath9k_tx_queue_info qi; - int qnum; + int hdrlen, padsize; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ath_tx_control txctl; - memset(&qi, 0, sizeof(qi)); - qi.tqi_subtype = subtype; - qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; - qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; - qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; - qi.tqi_physCompBuf = 0; + memset(&txctl, 0, sizeof(struct ath_tx_control)); /* - * Enable interrupts only for EOL and DESC conditions. - * We mark tx descriptors to receive a DESC interrupt - * when a tx queue gets deep; otherwise waiting for the - * EOL to reap descriptors. Note that this is done to - * reduce interrupt load and this only defers reaping - * descriptors, never transmitting frames. Aside from - * reducing interrupts this also permits more concurrency. - * The only potential downside is if the tx queue backs - * up in which case the top half of the kernel may backup - * due to a lack of tx descriptors. - * - * The UAPSD queue is an exception, since we take a desc- - * based intr on the EOSP frames. + * As a temporary workaround, assign seq# here; this will likely need + * to be cleaned up to work better with Beacon transmission and virtual + * BSSes. */ - if (qtype == ATH9K_TX_QUEUE_UAPSD) - qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE; - else - qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | - TXQ_FLAG_TXDESCINT_ENABLE; - qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi); - if (qnum == -1) { - /* - * NB: don't print a message, this happens - * normally on parts with too few tx queues - */ - return NULL; - } - if (qnum >= ARRAY_SIZE(sc->tx.txq)) { - DPRINTF(sc, ATH_DBG_FATAL, - "qnum %u out of range, max %u!\n", - qnum, (unsigned int)ARRAY_SIZE(sc->tx.txq)); - ath9k_hw_releasetxqueue(ah, qnum); - return NULL; + if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) + sc->tx.seq_no += 0x10; + hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); + hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); } - if (!ATH_TXQ_SETUP(sc, qnum)) { - struct ath_txq *txq = &sc->tx.txq[qnum]; - txq->axq_qnum = qnum; - txq->axq_link = NULL; - INIT_LIST_HEAD(&txq->axq_q); - INIT_LIST_HEAD(&txq->axq_acq); - spin_lock_init(&txq->axq_lock); - txq->axq_depth = 0; - txq->axq_aggr_depth = 0; - txq->axq_totalqueued = 0; - txq->axq_linkbuf = NULL; - sc->tx.txqsetup |= 1<data, skb->data + padsize, hdrlen); } - return &sc->tx.txq[qnum]; -} - -/* Reclaim resources for a setup queue */ - -void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq) -{ - ath9k_hw_releasetxqueue(sc->sc_ah, txq->axq_qnum); - sc->tx.txqsetup &= ~(1<axq_qnum); -} -/* - * Setup a hardware data transmit queue for the specified - * access control. The hal may not support all requested - * queues in which case it will return a reference to a - * previously setup queue. We record the mapping from ac's - * to h/w queues for use by ath_tx_start and also track - * the set of h/w queues being used to optimize work in the - * transmit interrupt handler and related routines. - */ + txctl.txq = sc->beacon.cabq; -int ath_tx_setup(struct ath_softc *sc, int haltype) -{ - struct ath_txq *txq; + DPRINTF(sc, ATH_DBG_XMIT, "transmitting CABQ packet, skb: %p\n", skb); - if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) { - DPRINTF(sc, ATH_DBG_FATAL, - "HAL AC %u out of range, max %zu!\n", - haltype, ARRAY_SIZE(sc->tx.hwq_map)); - return 0; + if (ath_tx_start(sc, skb, &txctl) != 0) { + DPRINTF(sc, ATH_DBG_XMIT, "CABQ TX failed\n"); + goto exit; } - txq = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, haltype); - if (txq != NULL) { - sc->tx.hwq_map[haltype] = txq->axq_qnum; - return 1; - } else - return 0; -} - -int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype) -{ - int qnum; - switch (qtype) { - case ATH9K_TX_QUEUE_DATA: - if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) { - DPRINTF(sc, ATH_DBG_FATAL, - "HAL AC %u out of range, max %zu!\n", - haltype, ARRAY_SIZE(sc->tx.hwq_map)); - return -1; - } - qnum = sc->tx.hwq_map[haltype]; - break; - case ATH9K_TX_QUEUE_BEACON: - qnum = sc->beacon.beaconq; - break; - case ATH9K_TX_QUEUE_CAB: - qnum = sc->beacon.cabq->axq_qnum; - break; - default: - qnum = -1; - } - return qnum; + return; +exit: + dev_kfree_skb_any(skb); } -/* Get a transmit queue, if available */ +/*****************/ +/* TX Completion */ +/*****************/ -struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb) +static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, + struct ath_xmit_status *tx_status) { - struct ath_txq *txq = NULL; - int qnum; + struct ieee80211_hw *hw = sc->hw; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); + int hdrlen, padsize; - qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc); - txq = &sc->tx.txq[qnum]; + DPRINTF(sc, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); - spin_lock_bh(&txq->axq_lock); + if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK || + tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) { + kfree(tx_info_priv); + tx_info->rate_driver_data[0] = NULL; + } - /* Try to avoid running out of descriptors */ - if (txq->axq_depth >= (ATH_TXBUF - 20)) { - DPRINTF(sc, ATH_DBG_FATAL, - "TX queue: %d is full, depth: %d\n", - qnum, txq->axq_depth); - ieee80211_stop_queue(sc->hw, skb_get_queue_mapping(skb)); - txq->stopped = 1; - spin_unlock_bh(&txq->axq_lock); - return NULL; + if (tx_status->flags & ATH_TX_BAR) { + tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; + tx_status->flags &= ~ATH_TX_BAR; + } + + if (!(tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) { + /* Frame was ACKed */ + tx_info->flags |= IEEE80211_TX_STAT_ACK; } - spin_unlock_bh(&txq->axq_lock); + tx_info->status.rates[0].count = tx_status->retries + 1; - return txq; -} + hdrlen = ieee80211_get_hdrlen_from_skb(skb); + padsize = hdrlen & 3; + if (padsize && hdrlen >= 24) { + /* + * Remove MAC header padding before giving the frame back to + * mac80211. + */ + memmove(skb->data + padsize, skb->data, hdrlen); + skb_pull(skb, padsize); + } -/* Update parameters for a transmit queue */ + ieee80211_tx_status(hw, skb); +} -int ath_txq_update(struct ath_softc *sc, int qnum, - struct ath9k_tx_queue_info *qinfo) +static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, + struct list_head *bf_q, + int txok, int sendbar) { - struct ath_hal *ah = sc->sc_ah; - int error = 0; - struct ath9k_tx_queue_info qi; + struct sk_buff *skb = bf->bf_mpdu; + struct ath_xmit_status tx_status; + unsigned long flags; - if (qnum == sc->beacon.beaconq) { - /* - * XXX: for beacon queue, we just save the parameter. - * It will be picked up by ath_beaconq_config when - * it's necessary. - */ - sc->beacon.beacon_qi = *qinfo; - return 0; - } + /* + * Set retry information. + * NB: Don't use the information in the descriptor, because the frame + * could be software retried. + */ + tx_status.retries = bf->bf_retries; + tx_status.flags = 0; - ASSERT(sc->tx.txq[qnum].axq_qnum == qnum); + if (sendbar) + tx_status.flags = ATH_TX_BAR; - ath9k_hw_get_txq_props(ah, qnum, &qi); - qi.tqi_aifs = qinfo->tqi_aifs; - qi.tqi_cwmin = qinfo->tqi_cwmin; - qi.tqi_cwmax = qinfo->tqi_cwmax; - qi.tqi_burstTime = qinfo->tqi_burstTime; - qi.tqi_readyTime = qinfo->tqi_readyTime; + if (!txok) { + tx_status.flags |= ATH_TX_ERROR; - if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to update hardware queue %u!\n", qnum); - error = -EIO; - } else { - ath9k_hw_resettxqueue(ah, qnum); /* push to h/w */ + if (bf_isxretried(bf)) + tx_status.flags |= ATH_TX_XRETRY; } - return error; + dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); + ath_tx_complete(sc, skb, &tx_status); + + /* + * Return the list of ath_buf of this mpdu to free queue + */ + spin_lock_irqsave(&sc->tx.txbuflock, flags); + list_splice_tail_init(bf_q, &sc->tx.txbuf); + spin_unlock_irqrestore(&sc->tx.txbuflock, flags); } -int ath_cabq_update(struct ath_softc *sc) +static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, + int txok) { - struct ath9k_tx_queue_info qi; - int qnum = sc->beacon.cabq->axq_qnum; - struct ath_beacon_config conf; + struct ath_buf *bf_last = bf->bf_lastbf; + struct ath_desc *ds = bf_last->bf_desc; + u16 seq_st = 0; + u32 ba[WME_BA_BMP_SIZE >> 5]; + int ba_index; + int nbad = 0; + int isaggr = 0; - ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi); - /* - * Ensure the readytime % is within the bounds. - */ - if (sc->sc_config.cabqReadytime < ATH9K_READY_TIME_LO_BOUND) - sc->sc_config.cabqReadytime = ATH9K_READY_TIME_LO_BOUND; - else if (sc->sc_config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND) - sc->sc_config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND; + if (ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED) + return 0; - ath_get_beaconconfig(sc, ATH_IF_ID_ANY, &conf); - qi.tqi_readyTime = - (conf.beacon_interval * sc->sc_config.cabqReadytime) / 100; - ath_txq_update(sc, qnum, &qi); + isaggr = bf_isaggr(bf); + if (isaggr) { + seq_st = ATH_DS_BA_SEQ(ds); + memcpy(ba, ATH_DS_BA_BITMAP(ds), WME_BA_BMP_SIZE >> 3); + } - return 0; -} + while (bf) { + ba_index = ATH_BA_INDEX(seq_st, bf->bf_seqno); + if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index))) + nbad++; + + bf = bf->bf_next; + } -/* Deferred processing of transmit interrupt */ + return nbad; +} -void ath_tx_tasklet(struct ath_softc *sc) +static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, int nbad) { - int i; - u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1); + struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); - ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask); + tx_info_priv->update_rc = false; + if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) + tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; - /* - * Process each active queue. - */ - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i))) - ath_tx_processq(sc, &sc->tx.txq[i]); + if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && + (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) { + if (bf_isdata(bf)) { + memcpy(&tx_info_priv->tx, &ds->ds_txstat, + sizeof(tx_info_priv->tx)); + tx_info_priv->n_frames = bf->bf_nframes; + tx_info_priv->n_bad_frames = nbad; + tx_info_priv->update_rc = true; + } } } -void ath_tx_draintxq(struct ath_softc *sc, - struct ath_txq *txq, bool retry_tx) +static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) { - struct ath_buf *bf, *lastbf; + struct ath_hal *ah = sc->sc_ah; + struct ath_buf *bf, *lastbf, *bf_held = NULL; struct list_head bf_head; + struct ath_desc *ds; + int txok, nbad = 0; + int status; - INIT_LIST_HEAD(&bf_head); + DPRINTF(sc, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n", + txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum), + txq->axq_link); - /* - * NB: this assumes output has been stopped and - * we do not need to block ath_tx_tasklet - */ for (;;) { spin_lock_bh(&txq->axq_lock); - if (list_empty(&txq->axq_q)) { txq->axq_link = NULL; txq->axq_linkbuf = NULL; spin_unlock_bh(&txq->axq_lock); break; } - bf = list_first_entry(&txq->axq_q, struct ath_buf, list); + /* + * There is a race condition that a BH gets scheduled + * after sw writes TxE and before hw re-load the last + * descriptor to get the newly chained one. + * Software must keep the last DONE descriptor as a + * holding descriptor - software does so by marking + * it with the STALE flag. + */ + bf_held = NULL; if (bf->bf_status & ATH_BUFSTATUS_STALE) { - list_del(&bf->list); - spin_unlock_bh(&txq->axq_lock); - - spin_lock_bh(&sc->tx.txbuflock); - list_add_tail(&bf->list, &sc->tx.txbuf); - spin_unlock_bh(&sc->tx.txbuflock); - continue; + bf_held = bf; + if (list_is_last(&bf_held->list, &txq->axq_q)) { + /* FIXME: + * The holding descriptor is the last + * descriptor in queue. It's safe to remove + * the last holding descriptor in BH context. + */ + spin_unlock_bh(&txq->axq_lock); + break; + } else { + bf = list_entry(bf_held->list.next, + struct ath_buf, list); + } } lastbf = bf->bf_lastbf; - if (!retry_tx) - lastbf->bf_desc->ds_txstat.ts_flags = - ATH9K_TX_SW_ABORTED; - - /* remove ath_buf's of the same mpdu from txq */ - list_cut_position(&bf_head, &txq->axq_q, &lastbf->list); - txq->axq_depth--; - - spin_unlock_bh(&txq->axq_lock); - - if (bf_isampdu(bf)) - ath_tx_complete_aggr_rifs(sc, txq, bf, &bf_head, 0); - else - ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); - } + ds = lastbf->bf_desc; - /* flush any pending frames if aggregation is enabled */ - if (sc->sc_flags & SC_OP_TXAGGR) { - if (!retry_tx) { - spin_lock_bh(&txq->axq_lock); - ath_txq_drain_pending_buffers(sc, txq); + status = ath9k_hw_txprocdesc(ah, ds); + if (status == -EINPROGRESS) { spin_unlock_bh(&txq->axq_lock); + break; } - } -} - -/* Drain the transmit queues and reclaim resources */ - -void ath_draintxq(struct ath_softc *sc, bool retry_tx) -{ - /* stop beacon queue. The beacon will be freed when - * we go to INIT state */ - if (!(sc->sc_flags & SC_OP_INVALID)) { - (void) ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); - DPRINTF(sc, ATH_DBG_XMIT, "beacon queue %x\n", - ath9k_hw_gettxbuf(sc->sc_ah, sc->beacon.beaconq)); - } - - ath_drain_txdataq(sc, retry_tx); -} - -u32 ath_txq_depth(struct ath_softc *sc, int qnum) -{ - return sc->tx.txq[qnum].axq_depth; -} - -u32 ath_txq_aggr_depth(struct ath_softc *sc, int qnum) -{ - return sc->tx.txq[qnum].axq_aggr_depth; -} - -bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno) -{ - struct ath_atx_tid *txtid; - - if (!(sc->sc_flags & SC_OP_TXAGGR)) - return false; - - txtid = ATH_AN_2_TID(an, tidno); - - if (!(txtid->state & AGGR_ADDBA_COMPLETE)) { - if (!(txtid->state & AGGR_ADDBA_PROGRESS) && - (txtid->addba_exchangeattempts < ADDBA_EXCHANGE_ATTEMPTS)) { - txtid->addba_exchangeattempts++; - return true; - } - } + if (bf->bf_desc == txq->axq_lastdsWithCTS) + txq->axq_lastdsWithCTS = NULL; + if (ds == txq->axq_gatingds) + txq->axq_gatingds = NULL; - return false; -} + /* + * Remove ath_buf's of the same transmit unit from txq, + * however leave the last descriptor back as the holding + * descriptor for hw. + */ + lastbf->bf_status |= ATH_BUFSTATUS_STALE; + INIT_LIST_HEAD(&bf_head); -/* Start TX aggregation */ + if (!list_is_singular(&lastbf->list)) + list_cut_position(&bf_head, + &txq->axq_q, lastbf->list.prev); -int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, - u16 tid, u16 *ssn) -{ - struct ath_atx_tid *txtid; - struct ath_node *an; + txq->axq_depth--; - an = (struct ath_node *)sta->drv_priv; + if (bf_isaggr(bf)) + txq->axq_aggr_depth--; - if (sc->sc_flags & SC_OP_TXAGGR) { - txtid = ATH_AN_2_TID(an, tid); - txtid->state |= AGGR_ADDBA_PROGRESS; - ath_tx_pause_tid(sc, txtid); - } + txok = (ds->ds_txstat.ts_status == 0); - return 0; -} + spin_unlock_bh(&txq->axq_lock); -/* Stop tx aggregation */ + if (bf_held) { + list_del(&bf_held->list); + spin_lock_bh(&sc->tx.txbuflock); + list_add_tail(&bf_held->list, &sc->tx.txbuf); + spin_unlock_bh(&sc->tx.txbuflock); + } -int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) -{ - struct ath_node *an = (struct ath_node *)sta->drv_priv; + if (!bf_isampdu(bf)) { + /* + * This frame is sent out as a single frame. + * Use hardware retry status for this frame. + */ + bf->bf_retries = ds->ds_txstat.ts_longretry; + if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) + bf->bf_state.bf_type |= BUF_XRETRY; + nbad = 0; + } else { + nbad = ath_tx_num_badfrms(sc, bf, txok); + } - ath_tx_aggr_teardown(sc, an, tid); - return 0; -} + ath_tx_rc_status(bf, ds, nbad); -/* Resume tx aggregation */ + if (bf_isampdu(bf)) + ath_tx_complete_aggr_rifs(sc, txq, bf, &bf_head, txok); + else + ath_tx_complete_buf(sc, bf, &bf_head, txok, 0); -void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) -{ - struct ath_atx_tid *txtid; - struct ath_node *an; + spin_lock_bh(&txq->axq_lock); + if (txq->stopped && ath_txq_depth(sc, txq->axq_qnum) <= + (ATH_TXBUF - 20)) { + int qnum; + qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc); + if (qnum != -1) { + ieee80211_wake_queue(sc->hw, qnum); + txq->stopped = 0; + } - an = (struct ath_node *)sta->drv_priv; + } - if (sc->sc_flags & SC_OP_TXAGGR) { - txtid = ATH_AN_2_TID(an, tid); - txtid->baw_size = - IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor; - txtid->state |= AGGR_ADDBA_COMPLETE; - txtid->state &= ~AGGR_ADDBA_PROGRESS; - ath_tx_resume_tid(sc, txtid); + if (sc->sc_flags & SC_OP_TXAGGR) + ath_txq_schedule(sc, txq); + spin_unlock_bh(&txq->axq_lock); } } -/* - * Performs transmit side cleanup when TID changes from aggregated to - * unaggregated. - * - Pause the TID and mark cleanup in progress - * - Discard all retry frames from the s/w queue. - */ -void ath_tx_aggr_teardown(struct ath_softc *sc, struct ath_node *an, u8 tid) +void ath_tx_tasklet(struct ath_softc *sc) { - struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); - struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum]; - struct ath_buf *bf; - struct list_head bf_head; - INIT_LIST_HEAD(&bf_head); - - if (txtid->state & AGGR_CLEANUP) /* cleanup is in progress */ - return; - - if (!(txtid->state & AGGR_ADDBA_COMPLETE)) { - txtid->addba_exchangeattempts = 0; - return; - } - - /* TID must be paused first */ - ath_tx_pause_tid(sc, txtid); - - /* drop all software retried frames and mark this TID */ - spin_lock_bh(&txq->axq_lock); - while (!list_empty(&txtid->buf_q)) { - bf = list_first_entry(&txtid->buf_q, struct ath_buf, list); - if (!bf_isretried(bf)) { - /* - * NB: it's based on the assumption that - * software retried frame will always stay - * at the head of software queue. - */ - break; - } - list_cut_position(&bf_head, - &txtid->buf_q, &bf->bf_lastfrm->list); - ath_tx_update_baw(sc, txtid, bf->bf_seqno); + int i; + u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1); - /* complete this sub-frame */ - ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); - } + ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask); - if (txtid->baw_head != txtid->baw_tail) { - spin_unlock_bh(&txq->axq_lock); - txtid->state |= AGGR_CLEANUP; - } else { - txtid->state &= ~AGGR_ADDBA_COMPLETE; - txtid->addba_exchangeattempts = 0; - spin_unlock_bh(&txq->axq_lock); - ath_tx_flush_tid(sc, txtid); + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { + if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i))) + ath_tx_processq(sc, &sc->tx.txq[i]); } } -/* - * Tx scheduling logic - * NB: must be called with txq lock held - */ +/*****************/ +/* Init, Cleanup */ +/*****************/ -void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) +int ath_tx_init(struct ath_softc *sc, int nbufs) { - struct ath_atx_ac *ac; - struct ath_atx_tid *tid; - - /* nothing to schedule */ - if (list_empty(&txq->axq_acq)) - return; - /* - * get the first node/ac pair on the queue - */ - ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list); - list_del(&ac->list); - ac->sched = false; + int error = 0; - /* - * process a single tid per destination - */ do { - /* nothing to schedule */ - if (list_empty(&ac->tid_q)) - return; - - tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, list); - list_del(&tid->list); - tid->sched = false; + spin_lock_init(&sc->tx.txbuflock); - if (tid->paused) /* check next tid to keep h/w busy */ - continue; + error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf, + "tx", nbufs, 1); + if (error != 0) { + DPRINTF(sc, ATH_DBG_FATAL, + "Failed to allocate tx descriptors: %d\n", + error); + break; + } - if ((txq->axq_depth % 2) == 0) - ath_tx_sched_aggr(sc, txq, tid); + error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf, + "beacon", ATH_BCBUF, 1); + if (error != 0) { + DPRINTF(sc, ATH_DBG_FATAL, + "Failed to allocate beacon descriptors: %d\n", + error); + break; + } - /* - * add tid to round-robin queue if more frames - * are pending for the tid - */ - if (!list_empty(&tid->buf_q)) - ath_tx_queue_tid(txq, tid); + } while (0); - /* only schedule one TID at a time */ - break; - } while (!list_empty(&ac->tid_q)); + if (error != 0) + ath_tx_cleanup(sc); - /* - * schedule AC if more TIDs need processing - */ - if (!list_empty(&ac->tid_q)) { - /* - * add dest ac to txq if not already added - */ - if (!ac->sched) { - ac->sched = true; - list_add_tail(&ac->list, &txq->axq_acq); - } - } + return error; } -/* Initialize per-node transmit state */ +int ath_tx_cleanup(struct ath_softc *sc) +{ + if (sc->beacon.bdma.dd_desc_len != 0) + ath_descdma_cleanup(sc, &sc->beacon.bdma, &sc->beacon.bbuf); + + if (sc->tx.txdma.dd_desc_len != 0) + ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf); + + return 0; +} void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) { @@ -2412,9 +2232,6 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) struct ath_atx_ac *ac; int tidno, acno; - /* - * Init per tid tx state - */ for (tidno = 0, tid = &an->tid[tidno]; tidno < WME_NUM_TID; tidno++, tid++) { @@ -2424,22 +2241,16 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) tid->baw_size = WME_MAX_BA; tid->baw_head = tid->baw_tail = 0; tid->sched = false; - tid->paused = false; + tid->paused = false; tid->state &= ~AGGR_CLEANUP; INIT_LIST_HEAD(&tid->buf_q); - acno = TID_TO_WME_AC(tidno); tid->ac = &an->ac[acno]; - - /* ADDBA state */ tid->state &= ~AGGR_ADDBA_COMPLETE; tid->state &= ~AGGR_ADDBA_PROGRESS; tid->addba_exchangeattempts = 0; } - /* - * Init per ac tx state - */ for (acno = 0, ac = &an->ac[acno]; acno < WME_NUM_AC; acno++, ac++) { ac->sched = false; @@ -2466,14 +2277,13 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) } } -/* Cleanupthe pending buffers for the node. */ - void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) { int i; struct ath_atx_ac *ac, *ac_tmp; struct ath_atx_tid *tid, *tid_tmp; struct ath_txq *txq; + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { if (ATH_TXQ_SETUP(sc, i)) { txq = &sc->tx.txq[i]; @@ -2504,51 +2314,3 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) } } } - -void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb) -{ - int hdrlen, padsize; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ath_tx_control txctl; - - memset(&txctl, 0, sizeof(struct ath_tx_control)); - - /* - * As a temporary workaround, assign seq# here; this will likely need - * to be cleaned up to work better with Beacon transmission and virtual - * BSSes. - */ - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) - sc->tx.seq_no += 0x10; - hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); - } - - /* Add the padding after the header if this is not already done */ - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - if (hdrlen & 3) { - padsize = hdrlen % 4; - if (skb_headroom(skb) < padsize) { - DPRINTF(sc, ATH_DBG_XMIT, "TX CABQ padding failed\n"); - dev_kfree_skb_any(skb); - return; - } - skb_push(skb, padsize); - memmove(skb->data, skb->data + padsize, hdrlen); - } - - txctl.txq = sc->beacon.cabq; - - DPRINTF(sc, ATH_DBG_XMIT, "transmitting CABQ packet, skb: %p\n", skb); - - if (ath_tx_start(sc, skb, &txctl) != 0) { - DPRINTF(sc, ATH_DBG_XMIT, "CABQ TX failed\n"); - goto exit; - } - - return; -exit: - dev_kfree_skb_any(skb); -} -- GitLab From 55f5e4a9800ae6e6e052380a8b3c9c4996d5cd05 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 16 Jan 2009 21:38:45 +0530 Subject: [PATCH 0863/4982] ath9k: Remove ath_tx_stopdma and call ath9k_hw_stoptxdma directly Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/xmit.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 5e6e5cf9b67..c9ead1ba88d 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -877,12 +877,6 @@ static u32 ath_txq_depth(struct ath_softc *sc, int qnum) return sc->tx.txq[qnum].axq_depth; } -static void ath_tx_stopdma(struct ath_softc *sc, struct ath_txq *txq) -{ - struct ath_hal *ah = sc->sc_ah; - (void) ath9k_hw_stoptxdma(ah, txq->axq_qnum); -} - static void ath_get_beaconconfig(struct ath_softc *sc, int if_id, struct ath_beacon_config *conf) { @@ -899,15 +893,17 @@ static void ath_get_beaconconfig(struct ath_softc *sc, int if_id, static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx) { struct ath_hal *ah = sc->sc_ah; + struct ath_txq *txq; int i, npend = 0; - if (!(sc->sc_flags & SC_OP_INVALID)) { - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (ATH_TXQ_SETUP(sc, i)) { - ath_tx_stopdma(sc, &sc->tx.txq[i]); - npend += ath9k_hw_numtxpending(ah, - sc->tx.txq[i].axq_qnum); - } + if (sc->sc_flags & SC_OP_INVALID) + return; + + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { + if (ATH_TXQ_SETUP(sc, i)) { + txq = &sc->tx.txq[i]; + ath9k_hw_stoptxdma(ah, txq->axq_qnum); + npend += ath9k_hw_numtxpending(ah, txq->axq_qnum); } } -- GitLab From 043a040503b0d0c21bf3fba971813eba3322267d Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 16 Jan 2009 21:38:47 +0530 Subject: [PATCH 0864/4982] ath9k: Merge queue draining functions The TX queue draining routines have confusing names, rename them approprately and merge ath_drain_txdataq() with ath_drain_all_txq(). Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/beacon.c | 2 +- drivers/net/wireless/ath9k/core.h | 4 +- drivers/net/wireless/ath9k/main.c | 8 +-- drivers/net/wireless/ath9k/xmit.c | 98 ++++++++++++++--------------- 4 files changed, 55 insertions(+), 57 deletions(-) diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c index be1d84a5daf..61d37be9717 100644 --- a/drivers/net/wireless/ath9k/beacon.c +++ b/drivers/net/wireless/ath9k/beacon.c @@ -220,7 +220,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) * acquires txq lock inside. */ if (sc->sc_nvaps > 1) { - ath_tx_draintxq(sc, cabq, false); + ath_draintxq(sc, cabq, false); DPRINTF(sc, ATH_DBG_BEACON, "flush previous cabq traffic\n"); } diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index 4eb21a7f0d8..04bc6fd611d 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -485,8 +485,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush); struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype); void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); int ath_tx_setup(struct ath_softc *sc, int haltype); -void ath_draintxq(struct ath_softc *sc, bool retry_tx); -void ath_tx_draintxq(struct ath_softc *sc, +void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx); +void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx); void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an); void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an); diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 7f4d1bbaf6c..8ad927a8870 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -247,7 +247,7 @@ static int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan) * the relevant bits of the h/w. */ ath9k_hw_set_interrupts(ah, 0); - ath_draintxq(sc, false); + ath_drain_all_txq(sc, false); stopped = ath_stoprecv(sc); /* XXX: do not flush receive queue here. We don't want @@ -1092,7 +1092,7 @@ static void ath_radio_disable(struct ath_softc *sc) /* Disable interrupts */ ath9k_hw_set_interrupts(ah, 0); - ath_draintxq(sc, false); /* clear pending tx frames */ + ath_drain_all_txq(sc, false); /* clear pending tx frames */ ath_stoprecv(sc); /* turn off frame recv */ ath_flushrecv(sc); /* flush recv queue */ @@ -1592,7 +1592,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) int r; ath9k_hw_set_interrupts(ah, 0); - ath_draintxq(sc, retry_tx); + ath_drain_all_txq(sc, retry_tx); ath_stoprecv(sc); ath_flushrecv(sc); @@ -1988,7 +1988,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) ath9k_hw_set_interrupts(sc->sc_ah, 0); if (!(sc->sc_flags & SC_OP_INVALID)) { - ath_draintxq(sc, false); + ath_drain_all_txq(sc, false); ath_stoprecv(sc); ath9k_hw_phy_disable(sc->sc_ah); } else diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index c9ead1ba88d..a29b998fac6 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -890,43 +890,6 @@ static void ath_get_beaconconfig(struct ath_softc *sc, int if_id, conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval; } -static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx) -{ - struct ath_hal *ah = sc->sc_ah; - struct ath_txq *txq; - int i, npend = 0; - - if (sc->sc_flags & SC_OP_INVALID) - return; - - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (ATH_TXQ_SETUP(sc, i)) { - txq = &sc->tx.txq[i]; - ath9k_hw_stoptxdma(ah, txq->axq_qnum); - npend += ath9k_hw_numtxpending(ah, txq->axq_qnum); - } - } - - if (npend) { - int r; - - DPRINTF(sc, ATH_DBG_XMIT, "Unable to stop TxDMA. Reset HAL!\n"); - - spin_lock_bh(&sc->sc_resetlock); - r = ath9k_hw_reset(ah, sc->sc_ah->ah_curchan, true); - if (r) - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset hardware; reset status %u\n", - r); - spin_unlock_bh(&sc->sc_resetlock); - } - - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (ATH_TXQ_SETUP(sc, i)) - ath_tx_draintxq(sc, &sc->tx.txq[i], retry_tx); - } -} - static void ath_txq_drain_pending_buffers(struct ath_softc *sc, struct ath_txq *txq) { @@ -1120,17 +1083,19 @@ int ath_cabq_update(struct ath_softc *sc) return 0; } -void ath_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) +/* + * Drain a given TX queue (could be Beacon or Data) + * + * This assumes output has been stopped and + * we do not need to block ath_tx_tasklet. + */ +void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) { struct ath_buf *bf, *lastbf; struct list_head bf_head; INIT_LIST_HEAD(&bf_head); - /* - * NB: this assumes output has been stopped and - * we do not need to block ath_tx_tasklet - */ for (;;) { spin_lock_bh(&txq->axq_lock); @@ -1180,18 +1145,51 @@ void ath_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) } } -void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq) +void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) { - ath9k_hw_releasetxqueue(sc->sc_ah, txq->axq_qnum); - sc->tx.txqsetup &= ~(1<axq_qnum); + struct ath_hal *ah = sc->sc_ah; + struct ath_txq *txq; + int i, npend = 0; + + if (sc->sc_flags & SC_OP_INVALID) + return; + + /* Stop beacon queue */ + ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); + + /* Stop data queues */ + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { + if (ATH_TXQ_SETUP(sc, i)) { + txq = &sc->tx.txq[i]; + ath9k_hw_stoptxdma(ah, txq->axq_qnum); + npend += ath9k_hw_numtxpending(ah, txq->axq_qnum); + } + } + + if (npend) { + int r; + + DPRINTF(sc, ATH_DBG_XMIT, "Unable to stop TxDMA. Reset HAL!\n"); + + spin_lock_bh(&sc->sc_resetlock); + r = ath9k_hw_reset(ah, sc->sc_ah->ah_curchan, true); + if (r) + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to reset hardware; reset status %u\n", + r); + spin_unlock_bh(&sc->sc_resetlock); + } + + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { + if (ATH_TXQ_SETUP(sc, i)) + ath_draintxq(sc, &sc->tx.txq[i], retry_tx); + } } -void ath_draintxq(struct ath_softc *sc, bool retry_tx) +void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq) { - if (!(sc->sc_flags & SC_OP_INVALID)) - (void) ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); - - ath_drain_txdataq(sc, retry_tx); + ath9k_hw_releasetxqueue(sc->sc_ah, txq->axq_qnum); + sc->tx.txqsetup &= ~(1<axq_qnum); } void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) -- GitLab From 059d806cdcad3848582519f0546cf8b3bfede7a3 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 16 Jan 2009 21:38:49 +0530 Subject: [PATCH 0865/4982] ath9k: Add a helper function to wake mac80211 queues Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/xmit.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index a29b998fac6..841bd9c5410 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -2031,6 +2031,22 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, int nbad) } } +static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) +{ + int qnum; + + spin_lock_bh(&txq->axq_lock); + if (txq->stopped && + ath_txq_depth(sc, txq->axq_qnum) <= (ATH_TXBUF - 20)) { + qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc); + if (qnum != -1) { + ieee80211_wake_queue(sc->hw, qnum); + txq->stopped = 0; + } + } + spin_unlock_bh(&txq->axq_lock); +} + static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) { struct ath_hal *ah = sc->sc_ah; @@ -2140,18 +2156,9 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) else ath_tx_complete_buf(sc, bf, &bf_head, txok, 0); - spin_lock_bh(&txq->axq_lock); - if (txq->stopped && ath_txq_depth(sc, txq->axq_qnum) <= - (ATH_TXBUF - 20)) { - int qnum; - qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc); - if (qnum != -1) { - ieee80211_wake_queue(sc->hw, qnum); - txq->stopped = 0; - } - - } + ath_wake_mac80211_queue(sc, txq); + spin_lock_bh(&txq->axq_lock); if (sc->sc_flags & SC_OP_TXAGGR) ath_txq_schedule(sc, txq); spin_unlock_bh(&txq->axq_lock); -- GitLab From 6ef9b13db24757a9856f2feb1e571f34938567c9 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 16 Jan 2009 21:38:51 +0530 Subject: [PATCH 0866/4982] ath9k: Handle holding descriptor in TX completion properly If the current holding descriptor is the last one in the TX queue, *and* it has been marked as STALE, then move it to the free list and bail out, as it has already been processed. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/xmit.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 841bd9c5410..d7cec0fee34 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -2082,16 +2082,23 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) if (bf->bf_status & ATH_BUFSTATUS_STALE) { bf_held = bf; if (list_is_last(&bf_held->list, &txq->axq_q)) { - /* FIXME: + txq->axq_link = NULL; + txq->axq_linkbuf = NULL; + spin_unlock_bh(&txq->axq_lock); + + /* * The holding descriptor is the last * descriptor in queue. It's safe to remove * the last holding descriptor in BH context. */ - spin_unlock_bh(&txq->axq_lock); + spin_lock_bh(&sc->tx.txbuflock); + list_move_tail(&bf_held->list, &sc->tx.txbuf); + spin_unlock_bh(&sc->tx.txbuflock); + break; } else { bf = list_entry(bf_held->list.next, - struct ath_buf, list); + struct ath_buf, list); } } @@ -2115,24 +2122,20 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) */ lastbf->bf_status |= ATH_BUFSTATUS_STALE; INIT_LIST_HEAD(&bf_head); - if (!list_is_singular(&lastbf->list)) list_cut_position(&bf_head, &txq->axq_q, lastbf->list.prev); txq->axq_depth--; - if (bf_isaggr(bf)) txq->axq_aggr_depth--; txok = (ds->ds_txstat.ts_status == 0); - spin_unlock_bh(&txq->axq_lock); if (bf_held) { - list_del(&bf_held->list); spin_lock_bh(&sc->tx.txbuflock); - list_add_tail(&bf_held->list, &sc->tx.txbuf); + list_move_tail(&bf_held->list, &sc->tx.txbuf); spin_unlock_bh(&sc->tx.txbuflock); } -- GitLab From d43f301520aa64bb331736a4568d435762f980b0 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 16 Jan 2009 21:38:53 +0530 Subject: [PATCH 0867/4982] ath9k: Revamp TX aggregation This patch cleans up the convoluted buffer management logic for TX aggregation. Both aggregation creation and completion are addressed. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/core.h | 10 - drivers/net/wireless/ath9k/xmit.c | 305 +++++++++--------------------- 2 files changed, 93 insertions(+), 222 deletions(-) diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index 04bc6fd611d..f65933d9c65 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -187,7 +187,6 @@ struct ath_config { #define ATH_TXBUF_RESET(_bf) do { \ (_bf)->bf_status = 0; \ (_bf)->bf_lastbf = NULL; \ - (_bf)->bf_lastfrm = NULL; \ (_bf)->bf_next = NULL; \ memset(&((_bf)->bf_state), 0, \ sizeof(struct ath_buf_state)); \ @@ -245,10 +244,8 @@ struct ath_buf_state { */ struct ath_buf { struct list_head list; - struct list_head *last; struct ath_buf *bf_lastbf; /* last buf of this unit (a frame or an aggregate) */ - struct ath_buf *bf_lastfrm; /* last buf of this frame */ struct ath_buf *bf_next; /* next subframe in the aggregate */ void *bf_mpdu; /* enclosing frame structure */ struct ath_desc *bf_desc; /* virtual addr of desc */ @@ -261,13 +258,7 @@ struct ath_buf { }; #define ATH_RXBUF_RESET(_bf) ((_bf)->bf_status = 0) - -/* hw processing complete, desc processed by hal */ -#define ATH_BUFSTATUS_DONE 0x00000001 -/* hw processing complete, desc hold for hw */ #define ATH_BUFSTATUS_STALE 0x00000002 -/* Rx-only: OS is done with this packet and it's ok to queued it to hw */ -#define ATH_BUFSTATUS_FREE 0x00000004 /* DMA state for tx/rx descriptors */ @@ -360,7 +351,6 @@ struct ath_txq { u32 *axq_link; /* link ptr in last TX desc */ struct list_head axq_q; /* transmit queue */ spinlock_t axq_lock; - unsigned long axq_lockflags; /* intr state when must cli */ u32 axq_depth; /* queue depth */ u8 axq_aggr_depth; /* aggregates queued */ u32 axq_totalqueued; /* total ever queued */ diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index d7cec0fee34..0d05a7f8903 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -151,7 +151,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) while (!list_empty(&tid->buf_q)) { bf = list_first_entry(&tid->buf_q, struct ath_buf, list); ASSERT(!bf_isretried(bf)); - list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list); + list_move_tail(&bf->list, &bf_head); ath_tx_send_normal(sc, txq, tid, &bf_head); } @@ -212,9 +212,9 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, for (;;) { if (list_empty(&tid->buf_q)) break; - bf = list_first_entry(&tid->buf_q, struct ath_buf, list); - list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list); + bf = list_first_entry(&tid->buf_q, struct ath_buf, list); + list_move_tail(&bf->list, &bf_head); if (bf_isretried(bf)) ath_tx_update_baw(sc, tid, bf->bf_seqno); @@ -241,17 +241,37 @@ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_buf *bf) hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY); } -static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, struct ath_txq *txq, - struct ath_buf *bf, struct list_head *bf_q, - int txok) +static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf) +{ + struct ath_buf *tbf; + + spin_lock_bh(&sc->tx.txbuflock); + ASSERT(!list_empty((&sc->tx.txbuf))); + tbf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); + list_del(&tbf->list); + spin_unlock_bh(&sc->tx.txbuflock); + + ATH_TXBUF_RESET(tbf); + + tbf->bf_mpdu = bf->bf_mpdu; + tbf->bf_buf_addr = bf->bf_buf_addr; + *(tbf->bf_desc) = *(bf->bf_desc); + tbf->bf_state = bf->bf_state; + tbf->bf_dmacontext = bf->bf_dmacontext; + + return tbf; +} + +static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, + struct ath_buf *bf, struct list_head *bf_q, + int txok) { struct ath_node *an = NULL; struct sk_buff *skb; struct ieee80211_tx_info *tx_info; struct ath_atx_tid *tid = NULL; - struct ath_buf *bf_last = bf->bf_lastbf; + struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; struct ath_desc *ds = bf_last->bf_desc; - struct ath_buf *bf_next, *bf_lastq = NULL; struct list_head bf_head, bf_pending; u16 seq_st = 0; u32 ba[WME_BA_BMP_SIZE >> 5]; @@ -266,28 +286,23 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, struct ath_txq *txq, } isaggr = bf_isaggr(bf); - if (isaggr) { - if (txok) { - if (ATH_DS_TX_BA(ds)) { - seq_st = ATH_DS_BA_SEQ(ds); - memcpy(ba, ATH_DS_BA_BITMAP(ds), - WME_BA_BMP_SIZE >> 3); - } else { - memset(ba, 0, WME_BA_BMP_SIZE >> 3); + memset(ba, 0, WME_BA_BMP_SIZE >> 3); - /* - * AR5416 can become deaf/mute when BA - * issue happens. Chip needs to be reset. - * But AP code may have sychronization issues - * when perform internal reset in this routine. - * Only enable reset in STA mode for now. - */ - if (sc->sc_ah->ah_opmode == - NL80211_IFTYPE_STATION) - needreset = 1; - } + if (isaggr && txok) { + if (ATH_DS_TX_BA(ds)) { + seq_st = ATH_DS_BA_SEQ(ds); + memcpy(ba, ATH_DS_BA_BITMAP(ds), + WME_BA_BMP_SIZE >> 3); } else { - memset(ba, 0, WME_BA_BMP_SIZE >> 3); + /* + * AR5416 can become deaf/mute when BA + * issue happens. Chip needs to be reset. + * But AP code may have sychronization issues + * when perform internal reset in this routine. + * Only enable reset in STA mode for now. + */ + if (sc->sc_ah->ah_opmode == NL80211_IFTYPE_STATION) + needreset = 1; } } @@ -304,7 +319,6 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, struct ath_txq *txq, } else if (!isaggr && txok) { /* transmit completion */ } else { - if (!(tid->state & AGGR_CLEANUP) && ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) { if (bf->bf_retries < ATH_MAX_SW_RETRIES) { @@ -325,19 +339,10 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, struct ath_txq *txq, } if (bf_next == NULL) { - ASSERT(bf->bf_lastfrm == bf_last); - if (!list_empty(bf_q)) { - bf_lastq = list_entry(bf_q->prev, - struct ath_buf, list); - list_cut_position(&bf_head, - bf_q, &bf_lastq->list); - } else { - INIT_LIST_HEAD(&bf_head); - } + INIT_LIST_HEAD(&bf_head); } else { ASSERT(!list_empty(bf_q)); - list_cut_position(&bf_head, - bf_q, &bf->bf_lastfrm->list); + list_move_tail(&bf->list, &bf_head); } if (!txpending) { @@ -351,53 +356,20 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, struct ath_txq *txq, ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar); } else { - /* - * retry the un-acked ones - */ + /* retry the un-acked ones */ if (bf->bf_next == NULL && bf_last->bf_status & ATH_BUFSTATUS_STALE) { struct ath_buf *tbf; - /* allocate new descriptor */ - spin_lock_bh(&sc->tx.txbuflock); - ASSERT(!list_empty((&sc->tx.txbuf))); - tbf = list_first_entry(&sc->tx.txbuf, - struct ath_buf, list); - list_del(&tbf->list); - spin_unlock_bh(&sc->tx.txbuflock); - - ATH_TXBUF_RESET(tbf); - - /* copy descriptor content */ - tbf->bf_mpdu = bf_last->bf_mpdu; - tbf->bf_buf_addr = bf_last->bf_buf_addr; - *(tbf->bf_desc) = *(bf_last->bf_desc); - - /* link it to the frame */ - if (bf_lastq) { - bf_lastq->bf_desc->ds_link = - tbf->bf_daddr; - bf->bf_lastfrm = tbf; - ath9k_hw_cleartxdesc(sc->sc_ah, - bf->bf_lastfrm->bf_desc); - } else { - tbf->bf_state = bf_last->bf_state; - tbf->bf_lastfrm = tbf; - ath9k_hw_cleartxdesc(sc->sc_ah, - tbf->bf_lastfrm->bf_desc); - - /* copy the DMA context */ - tbf->bf_dmacontext = - bf_last->bf_dmacontext; - } + tbf = ath_clone_txbuf(sc, bf_last); + ath9k_hw_cleartxdesc(sc->sc_ah, tbf->bf_desc); list_add_tail(&tbf->list, &bf_head); } else { /* * Clear descriptor status words for * software retry */ - ath9k_hw_cleartxdesc(sc->sc_ah, - bf->bf_lastfrm->bf_desc); + ath9k_hw_cleartxdesc(sc->sc_ah, bf->bf_desc); } /* @@ -411,27 +383,18 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, struct ath_txq *txq, } if (tid->state & AGGR_CLEANUP) { - /* check to see if we're done with cleaning the h/w queue */ - spin_lock_bh(&txq->axq_lock); - if (tid->baw_head == tid->baw_tail) { tid->state &= ~AGGR_ADDBA_COMPLETE; tid->addba_exchangeattempts = 0; - spin_unlock_bh(&txq->axq_lock); - tid->state &= ~AGGR_CLEANUP; /* send buffered frames as singles */ ath_tx_flush_tid(sc, tid); - } else - spin_unlock_bh(&txq->axq_lock); - + } return; } - /* - * prepend un-acked frames to the beginning of the pending frame queue - */ + /* prepend un-acked frames to the beginning of the pending frame queue */ if (!list_empty(&bf_pending)) { spin_lock_bh(&txq->axq_lock); list_splice(&bf_pending, &tid->buf_q); @@ -441,8 +404,6 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, struct ath_txq *txq, if (needreset) ath_reset(sc, false); - - return; } static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, @@ -453,15 +414,14 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, struct ieee80211_tx_info *tx_info; struct ieee80211_tx_rate *rates; struct ath_tx_info_priv *tx_info_priv; - u32 max_4ms_framelen, frame_length; + u32 max_4ms_framelen, frmlen; u16 aggr_limit, legacy = 0, maxampdu; int i; skb = (struct sk_buff *)bf->bf_mpdu; tx_info = IEEE80211_SKB_CB(skb); rates = tx_info->control.rates; - tx_info_priv = - (struct ath_tx_info_priv *)tx_info->rate_driver_data[0]; + tx_info_priv = (struct ath_tx_info_priv *)tx_info->rate_driver_data[0]; /* * Find the lowest frame length among the rate series that will have a @@ -477,9 +437,8 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, break; } - frame_length = - rate_table->info[rates[i].idx].max_4ms_framelen; - max_4ms_framelen = min(max_4ms_framelen, frame_length); + frmlen = rate_table->info[rates[i].idx].max_4ms_framelen; + max_4ms_framelen = min(max_4ms_framelen, frmlen); } } @@ -491,8 +450,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy) return 0; - aggr_limit = min(max_4ms_framelen, - (u32)ATH_AMPDU_LIMIT_DEFAULT); + aggr_limit = min(max_4ms_framelen, (u32)ATH_AMPDU_LIMIT_DEFAULT); /* * h/w can accept aggregates upto 16 bit lengths (65535). @@ -507,9 +465,9 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, } /* - * returns the number of delimiters to be added to + * Returns the number of delimiters to be added to * meet the minimum required mpdudensity. - * caller should make sure that the rate is HT rate . + * caller should make sure that the rate is HT rate . */ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, struct ath_buf *bf, u16 frmlen) @@ -566,9 +524,7 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width]; minlen = (nsymbols * nsymbits) / BITS_PER_BYTE; - /* Is frame shorter than required minimum length? */ if (frmlen < minlen) { - /* Get the minimum number of delimiters required. */ mindelim = (minlen - frmlen) / ATH_AGGR_DELIM_SZ; ndelim = max(mindelim, ndelim); } @@ -577,30 +533,22 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, } static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, - struct ath_atx_tid *tid, struct list_head *bf_q, - struct ath_buf **bf_last, struct aggr_rifs_param *param, - int *prev_frames) + struct ath_atx_tid *tid, + struct list_head *bf_q) { #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) - struct ath_buf *bf, *tbf, *bf_first, *bf_prev = NULL; - struct list_head bf_head; - int rl = 0, nframes = 0, ndelim; + struct ath_buf *bf, *bf_first, *bf_prev = NULL; + int rl = 0, nframes = 0, ndelim, prev_al = 0; u16 aggr_limit = 0, al = 0, bpad = 0, al_delta, h_baw = tid->baw_size / 2; enum ATH_AGGR_STATUS status = ATH_AGGR_DONE; - int prev_al = 0; - INIT_LIST_HEAD(&bf_head); - - BUG_ON(list_empty(&tid->buf_q)); bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list); do { bf = list_first_entry(&tid->buf_q, struct ath_buf, list); - /* - * do not step over block-ack window - */ + /* do not step over block-ack window */ if (!BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno)) { status = ATH_AGGR_BAW_CLOSED; break; @@ -611,29 +559,23 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, rl = 1; } - /* - * do not exceed aggregation limit - */ + /* do not exceed aggregation limit */ al_delta = ATH_AGGR_DELIM_SZ + bf->bf_frmlen; - if (nframes && (aggr_limit < - (al + bpad + al_delta + prev_al))) { + if (nframes && + (aggr_limit < (al + bpad + al_delta + prev_al))) { status = ATH_AGGR_LIMITED; break; } - /* - * do not exceed subframe limit - */ - if ((nframes + *prev_frames) >= - min((int)h_baw, ATH_AMPDU_SUBFRAME_DEFAULT)) { + /* do not exceed subframe limit */ + if (nframes >= min((int)h_baw, ATH_AMPDU_SUBFRAME_DEFAULT)) { status = ATH_AGGR_LIMITED; break; } + nframes++; - /* - * add padding for previous frame to aggregation length - */ + /* add padding for previous frame to aggregation length */ al += bpad + al_delta; /* @@ -641,44 +583,25 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, * density for this node. */ ndelim = ath_compute_num_delims(sc, tid, bf_first, bf->bf_frmlen); - bpad = PADBYTES(al_delta) + (ndelim << 2); bf->bf_next = NULL; - bf->bf_lastfrm->bf_desc->ds_link = 0; + bf->bf_desc->ds_link = 0; - /* - * this packet is part of an aggregate - * - remove all descriptors belonging to this frame from - * software queue - * - add it to block ack window - * - set up descriptors for aggregation - */ - list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list); + /* link buffers of this frame to the aggregate */ ath_tx_addto_baw(sc, tid, bf); - - list_for_each_entry(tbf, &bf_head, list) { - ath9k_hw_set11n_aggr_middle(sc->sc_ah, - tbf->bf_desc, ndelim); - } - - /* - * link buffers of this frame to the aggregate - */ - list_splice_tail_init(&bf_head, bf_q); - nframes++; - + ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim); + list_move_tail(&bf->list, bf_q); if (bf_prev) { bf_prev->bf_next = bf; - bf_prev->bf_lastfrm->bf_desc->ds_link = bf->bf_daddr; + bf_prev->bf_desc->ds_link = bf->bf_daddr; } bf_prev = bf; - } while (!list_empty(&tid->buf_q)); bf_first->bf_al = al; bf_first->bf_nframes = nframes; - *bf_last = bf_prev; + return status; #undef PADBYTES } @@ -686,11 +609,9 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, struct ath_atx_tid *tid) { - struct ath_buf *bf, *tbf, *bf_last, *bf_lastaggr = NULL; + struct ath_buf *bf; enum ATH_AGGR_STATUS status; struct list_head bf_q; - struct aggr_rifs_param param = {0, 0, 0, 0, NULL}; - int prev_frames = 0; do { if (list_empty(&tid->buf_q)) @@ -698,66 +619,36 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, INIT_LIST_HEAD(&bf_q); - status = ath_tx_form_aggr(sc, tid, &bf_q, &bf_lastaggr, ¶m, - &prev_frames); + status = ath_tx_form_aggr(sc, tid, &bf_q); /* - * no frames picked up to be aggregated; block-ack - * window is not open + * no frames picked up to be aggregated; + * block-ack window is not open. */ if (list_empty(&bf_q)) break; bf = list_first_entry(&bf_q, struct ath_buf, list); - bf_last = list_entry(bf_q.prev, struct ath_buf, list); - bf->bf_lastbf = bf_last; + bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list); - /* - * if only one frame, send as non-aggregate - */ + /* if only one frame, send as non-aggregate */ if (bf->bf_nframes == 1) { - ASSERT(bf->bf_lastfrm == bf_last); - bf->bf_state.bf_type &= ~BUF_AGGR; - /* - * clear aggr bits for every descriptor - * XXX TODO: is there a way to optimize it? - */ - list_for_each_entry(tbf, &bf_q, list) { - ath9k_hw_clr11n_aggr(sc->sc_ah, tbf->bf_desc); - } - + ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc); ath_buf_set_rate(sc, bf); ath_tx_txqaddbuf(sc, txq, &bf_q); continue; } - /* - * setup first desc with rate and aggr info - */ + /* setup first desc of aggregate */ bf->bf_state.bf_type |= BUF_AGGR; ath_buf_set_rate(sc, bf); ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, bf->bf_al); - /* - * anchor last frame of aggregate correctly - */ - ASSERT(bf_lastaggr); - ASSERT(bf_lastaggr->bf_lastfrm == bf_last); - tbf = bf_lastaggr; - ath9k_hw_set11n_aggr_last(sc->sc_ah, tbf->bf_desc); - - /* XXX: We don't enter into this loop, consider removing this */ - while (!list_empty(&bf_q) && !list_is_last(&tbf->list, &bf_q)) { - tbf = list_entry(tbf->list.next, struct ath_buf, list); - ath9k_hw_set11n_aggr_last(sc->sc_ah, tbf->bf_desc); - } + /* anchor last desc of aggregate */ + ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc); txq->axq_aggr_depth++; - - /* - * Normal aggregate, queue to hardware - */ ath_tx_txqaddbuf(sc, txq, &bf_q); } while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH && @@ -812,19 +703,17 @@ int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) */ break; } - list_cut_position(&bf_head, - &txtid->buf_q, &bf->bf_lastfrm->list); + list_move_tail(&bf->list, &bf_head); ath_tx_update_baw(sc, txtid, bf->bf_seqno); ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); } + spin_unlock_bh(&txq->axq_lock); if (txtid->baw_head != txtid->baw_tail) { - spin_unlock_bh(&txq->axq_lock); txtid->state |= AGGR_CLEANUP; } else { txtid->state &= ~AGGR_ADDBA_COMPLETE; txtid->addba_exchangeattempts = 0; - spin_unlock_bh(&txq->axq_lock); ath_tx_flush_tid(sc, txtid); } @@ -1130,7 +1019,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) spin_unlock_bh(&txq->axq_lock); if (bf_isampdu(bf)) - ath_tx_complete_aggr_rifs(sc, txq, bf, &bf_head, 0); + ath_tx_complete_aggr(sc, txq, bf, &bf_head, 0); else ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); } @@ -1326,8 +1215,6 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, { struct ath_buf *bf; - BUG_ON(list_empty(bf_head)); - bf = list_first_entry(bf_head, struct ath_buf, list); bf->bf_state.bf_type |= BUF_AMPDU; @@ -1345,7 +1232,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, * Add this frame to software queue for scheduling later * for aggregation. */ - list_splice_tail_init(bf_head, &tid->buf_q); + list_move_tail(&bf->list, &tid->buf_q); ath_tx_queue_tid(txctl->txq, tid); return; } @@ -1355,11 +1242,9 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, /* Queue to h/w without aggregation */ bf->bf_nframes = 1; - bf->bf_lastbf = bf->bf_lastfrm; /* one single frame */ + bf->bf_lastbf = bf; ath_buf_set_rate(sc, bf); ath_tx_txqaddbuf(sc, txctl->txq, bf_head); - - return; } static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, @@ -1368,8 +1253,6 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, { struct ath_buf *bf; - BUG_ON(list_empty(bf_head)); - bf = list_first_entry(bf_head, struct ath_buf, list); bf->bf_state.bf_type &= ~BUF_AMPDU; @@ -1377,7 +1260,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, INCR(tid->seq_start, IEEE80211_SEQ_MAX); bf->bf_nframes = 1; - bf->bf_lastbf = bf->bf_lastfrm; + bf->bf_lastbf = bf; ath_buf_set_rate(sc, bf); ath_tx_txqaddbuf(sc, txq, bf_head); } @@ -1770,8 +1653,6 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, true, /* last segment */ ds); /* first descriptor */ - bf->bf_lastfrm = bf; - spin_lock_bh(&txctl->txq->axq_lock); if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR) && @@ -2155,7 +2036,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) ath_tx_rc_status(bf, ds, nbad); if (bf_isampdu(bf)) - ath_tx_complete_aggr_rifs(sc, txq, bf, &bf_head, txok); + ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok); else ath_tx_complete_buf(sc, bf, &bf_head, txok, 0); -- GitLab From c656bbb582cebd988d8c39c4912722dc47578eab Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 16 Jan 2009 21:38:56 +0530 Subject: [PATCH 0868/4982] ath9k: Cleanup buffer type assignment The buffer state is already cleared in ATH_TXBUF_RESET. Remove redundant code clearing the type variable. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/xmit.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 0d05a7f8903..1b83673c3df 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -1576,27 +1576,21 @@ static int ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf, bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3); - ieee80211_is_data(fc) ? - (bf->bf_state.bf_type |= BUF_DATA) : - (bf->bf_state.bf_type &= ~BUF_DATA); - ieee80211_is_back_req(fc) ? - (bf->bf_state.bf_type |= BUF_BAR) : - (bf->bf_state.bf_type &= ~BUF_BAR); - ieee80211_is_pspoll(fc) ? - (bf->bf_state.bf_type |= BUF_PSPOLL) : - (bf->bf_state.bf_type &= ~BUF_PSPOLL); - (sc->sc_flags & SC_OP_PREAMBLE_SHORT) ? - (bf->bf_state.bf_type |= BUF_SHORT_PREAMBLE) : - (bf->bf_state.bf_type &= ~BUF_SHORT_PREAMBLE); - (conf_is_ht(&sc->hw->conf) && !is_pae(skb) && - (tx_info->flags & IEEE80211_TX_CTL_AMPDU)) ? - (bf->bf_state.bf_type |= BUF_HT) : - (bf->bf_state.bf_type &= ~BUF_HT); + if (ieee80211_is_data(fc)) + bf->bf_state.bf_type |= BUF_DATA; + if (ieee80211_is_back_req(fc)) + bf->bf_state.bf_type |= BUF_BAR; + if (ieee80211_is_pspoll(fc)) + bf->bf_state.bf_type |= BUF_PSPOLL; + if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) + bf->bf_state.bf_type |= BUF_SHORT_PREAMBLE; + if ((conf_is_ht(&sc->hw->conf) && !is_pae(skb) && + (tx_info->flags & IEEE80211_TX_CTL_AMPDU))) + bf->bf_state.bf_type |= BUF_HT; bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq); bf->bf_keytype = get_hw_crypto_keytype(skb); - if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) { bf->bf_frmlen += tx_info->control.hw_key->icv_len; bf->bf_keyix = tx_info->control.hw_key->hw_key_idx; -- GitLab From c88a768d7ed1bc38eedf18d16419ef2f01cd2d0d Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 16 Jan 2009 20:24:31 +0100 Subject: [PATCH 0869/4982] p54usb: fix conflict with recent usb changes A recent change in the usb core "USB: change interface to usb_lock_device_for_reset()" conflicts with "p54usb: utilize usb_reset_device for 3887". Sadly, we have to call usb_reset_device before we can upload the firmware on 3887. Unless someone figures out how to reliably stop the 3887 so the hardware is still usable next time we want to start it. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54usb.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 44d6855bd17..9539ddcf379 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -430,14 +430,16 @@ static const char p54u_firmware_upload_3887[] = "<\r"; static int p54u_device_reset_3887(struct ieee80211_hw *dev) { struct p54u_priv *priv = dev->priv; - int ret, lock; + int ret, lock = (priv->intf->condition != USB_INTERFACE_BINDING); u8 buf[4]; - ret = lock = usb_lock_device_for_reset(priv->udev, priv->intf); - if (ret < 0) { - dev_err(&priv->udev->dev, "(p54usb) unable to lock device for " - "reset: %d\n", ret); - return ret; + if (lock) { + ret = usb_lock_device_for_reset(priv->udev, priv->intf); + if (ret < 0) { + dev_err(&priv->udev->dev, "(p54usb) unable to lock " + " device for reset: %d\n", ret); + return ret; + } } ret = usb_reset_device(priv->udev); -- GitLab From a2116993c172bbb0c62f83d25cc3fe5dc7fece0d Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 16 Jan 2009 22:34:15 +0100 Subject: [PATCH 0870/4982] p54spi: remove arch specific dependencies On Friday 16 January 2009 20:33:43 Kalle Valo wrote: > N800 and N810 support is not on mainline yet, for stlc45xx I decided > to add module parameters for the gpio numbers. Here's the commit from > stlc45xx repo: > > http://gitorious.org/projects/stlc45xx/repos/mainline/commits/35afc5df0027d02d49e6f5bf986dcc4deb4ee6cf This is the same patch for p54spi. It removes all N800/N810 specific code from p54spi, so the driver can be used on other architectures, or configurations as well. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54spi.c | 45 +++++++++++++++++++------------ drivers/net/wireless/p54/p54spi.h | 2 -- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index b8dede741ef..7fde243b3d5 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c @@ -39,6 +39,20 @@ MODULE_FIRMWARE("3826.arm"); MODULE_ALIAS("stlc45xx"); +/* + * gpios should be handled in board files and provided via platform data, + * but because it's currently impossible for p54spi to have a header file + * in include/linux, let's use module paramaters for now + */ + +static int p54spi_gpio_power = 97; +module_param(p54spi_gpio_power, int, 0444); +MODULE_PARM_DESC(p54spi_gpio_power, "gpio number for power line"); + +static int p54spi_gpio_irq = 87; +module_param(p54spi_gpio_irq, int, 0444); +MODULE_PARM_DESC(p54spi_gpio_irq, "gpio number for irq line"); + static void p54spi_spi_read(struct p54s_priv *priv, u8 address, void *buf, size_t len) { @@ -283,14 +297,14 @@ static int p54spi_upload_firmware(struct ieee80211_hw *dev) static void p54spi_power_off(struct p54s_priv *priv) { - disable_irq(gpio_to_irq(priv->config->irq_gpio)); - gpio_set_value(priv->config->power_gpio, 0); + disable_irq(gpio_to_irq(p54spi_gpio_irq)); + gpio_set_value(p54spi_gpio_power, 0); } static void p54spi_power_on(struct p54s_priv *priv) { - gpio_set_value(priv->config->power_gpio, 1); - enable_irq(gpio_to_irq(priv->config->irq_gpio)); + gpio_set_value(p54spi_gpio_power, 1); + enable_irq(gpio_to_irq(p54spi_gpio_irq)); /* * need to wait a while before device can be accessed, the lenght @@ -626,9 +640,6 @@ static int __devinit p54spi_probe(struct spi_device *spi) dev_set_drvdata(&spi->dev, priv); priv->spi = spi; - priv->config = omap_get_config(OMAP_TAG_WLAN_CX3110X, - struct omap_wlan_cx3110x_config); - spi->bits_per_word = 16; spi->max_speed_hz = 24000000; @@ -638,22 +649,22 @@ static int __devinit p54spi_probe(struct spi_device *spi) goto err_free_common; } - ret = gpio_request(priv->config->power_gpio, "p54spi power"); + ret = gpio_request(p54spi_gpio_power, "p54spi power"); if (ret < 0) { dev_err(&priv->spi->dev, "power GPIO request failed: %d", ret); goto err_free_common; } - ret = gpio_request(priv->config->irq_gpio, "p54spi irq"); + ret = gpio_request(p54spi_gpio_irq, "p54spi irq"); if (ret < 0) { dev_err(&priv->spi->dev, "irq GPIO request failed: %d", ret); goto err_free_common; } - gpio_direction_output(priv->config->power_gpio, 0); - gpio_direction_input(priv->config->irq_gpio); + gpio_direction_output(p54spi_gpio_power, 0); + gpio_direction_input(p54spi_gpio_irq); - ret = request_irq(OMAP_GPIO_IRQ(priv->config->irq_gpio), + ret = request_irq(gpio_to_irq(p54spi_gpio_irq), p54spi_interrupt, IRQF_DISABLED, "p54spi", priv->spi); if (ret < 0) { @@ -661,10 +672,10 @@ static int __devinit p54spi_probe(struct spi_device *spi) goto err_free_common; } - set_irq_type(gpio_to_irq(priv->config->irq_gpio), + set_irq_type(gpio_to_irq(p54spi_gpio_irq), IRQ_TYPE_EDGE_RISING); - disable_irq(gpio_to_irq(priv->config->irq_gpio)); + disable_irq(gpio_to_irq(p54spi_gpio_irq)); INIT_WORK(&priv->work, p54spi_work); init_completion(&priv->fw_comp); @@ -705,10 +716,10 @@ static int __devexit p54spi_remove(struct spi_device *spi) ieee80211_unregister_hw(priv->hw); - free_irq(gpio_to_irq(priv->config->irq_gpio), spi); + free_irq(gpio_to_irq(p54spi_gpio_irq), spi); - gpio_free(priv->config->power_gpio); - gpio_free(priv->config->irq_gpio); + gpio_free(p54spi_gpio_power); + gpio_free(p54spi_gpio_irq); release_firmware(priv->firmware); mutex_destroy(&priv->mutex); diff --git a/drivers/net/wireless/p54/p54spi.h b/drivers/net/wireless/p54/p54spi.h index 5013ebc8712..7fbe8d8fc67 100644 --- a/drivers/net/wireless/p54/p54spi.h +++ b/drivers/net/wireless/p54/p54spi.h @@ -25,7 +25,6 @@ #include #include #include -#include #include "p54.h" @@ -108,7 +107,6 @@ struct p54s_priv { struct p54_common common; struct ieee80211_hw *hw; struct spi_device *spi; - const struct omap_wlan_cx3110x_config *config; struct work_struct work; -- GitLab From 49c1d2085b92a392189d44a06840cbd9ec147da2 Mon Sep 17 00:00:00 2001 From: Andrey Borzenkov Date: Sat, 17 Jan 2009 15:53:45 +0300 Subject: [PATCH 0871/4982] Move orinoco Kconfig entries into drivers/net/wireless/orinoco/Kconfig Since driver now lives in separate subdirectory, move Kconfig entries in own file so they can be tweaked indepndently. It complements "orinoco: Move sources to a subdirectory". Signed-off-by: Andrey Borzenkov Acked-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 122 +-------------------------- drivers/net/wireless/orinoco/Kconfig | 120 ++++++++++++++++++++++++++ 2 files changed, 121 insertions(+), 121 deletions(-) create mode 100644 drivers/net/wireless/orinoco/Kconfig diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 2dddbd012a9..fe819a78571 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -194,127 +194,6 @@ config AIRO The driver can be compiled as a module and will be named "airo". -config HERMES - tristate "Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)" - depends on (PPC_PMAC || PCI || PCMCIA) && WLAN_80211 - select WIRELESS_EXT - select FW_LOADER - select CRYPTO - select CRYPTO_MICHAEL_MIC - ---help--- - A driver for 802.11b wireless cards based on the "Hermes" or - Intersil HFA384x (Prism 2) MAC controller. This includes the vast - majority of the PCMCIA 802.11b cards (which are nearly all rebadges) - - except for the Cisco/Aironet cards. Cards supported include the - Apple Airport (not a PCMCIA card), WavelanIEEE/Orinoco, - Cabletron/EnteraSys Roamabout, ELSA AirLancer, MELCO Buffalo, Avaya, - IBM High Rate Wireless, Farralon Syyline, Samsung MagicLAN, Netgear - MA401, LinkSys WPC-11, D-Link DWL-650, 3Com AirConnect, Intel - IPW2011, and Symbol Spectrum24 High Rate amongst others. - - This option includes the guts of the driver, but in order to - actually use a card you will also need to enable support for PCMCIA - Hermes cards, PLX9052 based PCI adaptors or the Apple Airport below. - - You will also very likely also need the Wireless Tools in order to - configure your card and that /etc/pcmcia/wireless.opts works : - - -config HERMES_CACHE_FW_ON_INIT - bool "Cache Hermes firmware on driver initialisation" - depends on HERMES - default y - ---help--- - Say Y to cache any firmware required by the Hermes drivers - on startup. The firmware will remain cached until the - driver is unloaded. The cache uses 64K of RAM. - - Otherwise load the firmware from userspace as required. In - this case the driver should be unloaded and restarted - whenever the firmware is changed. - - If you are not sure, say Y. - -config APPLE_AIRPORT - tristate "Apple Airport support (built-in)" - depends on PPC_PMAC && HERMES - help - Say Y here to support the Airport 802.11b wireless Ethernet hardware - built into the Macintosh iBook and other recent PowerPC-based - Macintosh machines. This is essentially a Lucent Orinoco card with - a non-standard interface. - - This driver does not support the Airport Extreme (802.11b/g). Use - the BCM43xx driver for Airport Extreme cards. - -config PLX_HERMES - tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.)" - depends on PCI && HERMES - help - Enable support for PCMCIA cards supported by the "Hermes" (aka - orinoco) driver when used in PLX9052 based PCI adaptors. These - adaptors are not a full PCMCIA controller but act as a more limited - PCI <-> PCMCIA bridge. Several vendors sell such adaptors so that - 802.11b PCMCIA cards can be used in desktop machines. The Netgear - MA301 is such an adaptor. - -config TMD_HERMES - tristate "Hermes in TMD7160 based PCI adaptor support" - depends on PCI && HERMES - help - Enable support for PCMCIA cards supported by the "Hermes" (aka - orinoco) driver when used in TMD7160 based PCI adaptors. These - adaptors are not a full PCMCIA controller but act as a more limited - PCI <-> PCMCIA bridge. Several vendors sell such adaptors so that - 802.11b PCMCIA cards can be used in desktop machines. - -config NORTEL_HERMES - tristate "Nortel emobility PCI adaptor support" - depends on PCI && HERMES - help - Enable support for PCMCIA cards supported by the "Hermes" (aka - orinoco) driver when used in Nortel emobility PCI adaptors. These - adaptors are not full PCMCIA controllers, but act as a more limited - PCI <-> PCMCIA bridge. - -config PCI_HERMES - tristate "Prism 2.5 PCI 802.11b adaptor support" - depends on PCI && HERMES - help - Enable support for PCI and mini-PCI 802.11b wireless NICs based on - the Prism 2.5 chipset. These are true PCI cards, not the 802.11b - PCMCIA cards bundled with PCI<->PCMCIA adaptors which are also - common. Some of the built-in wireless adaptors in laptops are of - this variety. - -config PCMCIA_HERMES - tristate "Hermes PCMCIA card support" - depends on PCMCIA && HERMES - ---help--- - A driver for "Hermes" chipset based PCMCIA wireless adaptors, such - as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/ - EnteraSys RoamAbout 802.11, ELSA Airlancer, Melco Buffalo and - others). It should also be usable on various Prism II based cards - such as the Linksys, D-Link and Farallon Skyline. It should also - work on Symbol cards such as the 3Com AirConnect and Ericsson WLAN. - - You will very likely need the Wireless Tools in order to - configure your card and that /etc/pcmcia/wireless.opts works: - . - -config PCMCIA_SPECTRUM - tristate "Symbol Spectrum24 Trilogy PCMCIA card support" - depends on PCMCIA && HERMES - ---help--- - - This is a driver for 802.11b cards using RAM-loadable Symbol - firmware, such as Symbol Wireless Networker LA4100, CompactFlash - cards by Socket Communications and Intel PRO/Wireless 2011B. - - This driver requires firmware download on startup. Utilities - for downloading Symbol firmware are available at - - config ATMEL tristate "Atmel at76c50x chipset 802.11b support" depends on (PCI || PCMCIA) && WLAN_80211 @@ -596,5 +475,6 @@ source "drivers/net/wireless/b43/Kconfig" source "drivers/net/wireless/b43legacy/Kconfig" source "drivers/net/wireless/zd1211rw/Kconfig" source "drivers/net/wireless/rt2x00/Kconfig" +source "drivers/net/wireless/orinoco/Kconfig" endmenu diff --git a/drivers/net/wireless/orinoco/Kconfig b/drivers/net/wireless/orinoco/Kconfig new file mode 100644 index 00000000000..44411eb4e91 --- /dev/null +++ b/drivers/net/wireless/orinoco/Kconfig @@ -0,0 +1,120 @@ +config HERMES + tristate "Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)" + depends on (PPC_PMAC || PCI || PCMCIA) && WLAN_80211 + select WIRELESS_EXT + select FW_LOADER + select CRYPTO + select CRYPTO_MICHAEL_MIC + ---help--- + A driver for 802.11b wireless cards based on the "Hermes" or + Intersil HFA384x (Prism 2) MAC controller. This includes the vast + majority of the PCMCIA 802.11b cards (which are nearly all rebadges) + - except for the Cisco/Aironet cards. Cards supported include the + Apple Airport (not a PCMCIA card), WavelanIEEE/Orinoco, + Cabletron/EnteraSys Roamabout, ELSA AirLancer, MELCO Buffalo, Avaya, + IBM High Rate Wireless, Farralon Syyline, Samsung MagicLAN, Netgear + MA401, LinkSys WPC-11, D-Link DWL-650, 3Com AirConnect, Intel + IPW2011, and Symbol Spectrum24 High Rate amongst others. + + This option includes the guts of the driver, but in order to + actually use a card you will also need to enable support for PCMCIA + Hermes cards, PLX9052 based PCI adaptors or the Apple Airport below. + + You will also very likely also need the Wireless Tools in order to + configure your card and that /etc/pcmcia/wireless.opts works : + + +config HERMES_CACHE_FW_ON_INIT + bool "Cache Hermes firmware on driver initialisation" + depends on HERMES + default y + ---help--- + Say Y to cache any firmware required by the Hermes drivers + on startup. The firmware will remain cached until the + driver is unloaded. The cache uses 64K of RAM. + + Otherwise load the firmware from userspace as required. In + this case the driver should be unloaded and restarted + whenever the firmware is changed. + + If you are not sure, say Y. + +config APPLE_AIRPORT + tristate "Apple Airport support (built-in)" + depends on PPC_PMAC && HERMES + help + Say Y here to support the Airport 802.11b wireless Ethernet hardware + built into the Macintosh iBook and other recent PowerPC-based + Macintosh machines. This is essentially a Lucent Orinoco card with + a non-standard interface. + + This driver does not support the Airport Extreme (802.11b/g). Use + the BCM43xx driver for Airport Extreme cards. + +config PLX_HERMES + tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.)" + depends on PCI && HERMES + help + Enable support for PCMCIA cards supported by the "Hermes" (aka + orinoco) driver when used in PLX9052 based PCI adaptors. These + adaptors are not a full PCMCIA controller but act as a more limited + PCI <-> PCMCIA bridge. Several vendors sell such adaptors so that + 802.11b PCMCIA cards can be used in desktop machines. The Netgear + MA301 is such an adaptor. + +config TMD_HERMES + tristate "Hermes in TMD7160 based PCI adaptor support" + depends on PCI && HERMES + help + Enable support for PCMCIA cards supported by the "Hermes" (aka + orinoco) driver when used in TMD7160 based PCI adaptors. These + adaptors are not a full PCMCIA controller but act as a more limited + PCI <-> PCMCIA bridge. Several vendors sell such adaptors so that + 802.11b PCMCIA cards can be used in desktop machines. + +config NORTEL_HERMES + tristate "Nortel emobility PCI adaptor support" + depends on PCI && HERMES + help + Enable support for PCMCIA cards supported by the "Hermes" (aka + orinoco) driver when used in Nortel emobility PCI adaptors. These + adaptors are not full PCMCIA controllers, but act as a more limited + PCI <-> PCMCIA bridge. + +config PCI_HERMES + tristate "Prism 2.5 PCI 802.11b adaptor support" + depends on PCI && HERMES + help + Enable support for PCI and mini-PCI 802.11b wireless NICs based on + the Prism 2.5 chipset. These are true PCI cards, not the 802.11b + PCMCIA cards bundled with PCI<->PCMCIA adaptors which are also + common. Some of the built-in wireless adaptors in laptops are of + this variety. + +config PCMCIA_HERMES + tristate "Hermes PCMCIA card support" + depends on PCMCIA && HERMES + ---help--- + A driver for "Hermes" chipset based PCMCIA wireless adaptors, such + as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/ + EnteraSys RoamAbout 802.11, ELSA Airlancer, Melco Buffalo and + others). It should also be usable on various Prism II based cards + such as the Linksys, D-Link and Farallon Skyline. It should also + work on Symbol cards such as the 3Com AirConnect and Ericsson WLAN. + + You will very likely need the Wireless Tools in order to + configure your card and that /etc/pcmcia/wireless.opts works: + . + +config PCMCIA_SPECTRUM + tristate "Symbol Spectrum24 Trilogy PCMCIA card support" + depends on PCMCIA && HERMES + ---help--- + + This is a driver for 802.11b cards using RAM-loadable Symbol + firmware, such as Symbol Wireless Networker LA4100, CompactFlash + cards by Socket Communications and Intel PRO/Wireless 2011B. + + This driver requires firmware download on startup. Utilities + for downloading Symbol firmware are available at + -- GitLab From 4e54c711b42c3cc8da8a3fdcde3407b86d67ebcc Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 17 Jan 2009 20:42:32 +0100 Subject: [PATCH 0872/4982] rt2x00: Update copyright year to 2009 Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 2 +- drivers/net/wireless/rt2x00/rt2400pci.h | 2 +- drivers/net/wireless/rt2x00/rt2500pci.c | 2 +- drivers/net/wireless/rt2x00/rt2500pci.h | 2 +- drivers/net/wireless/rt2x00/rt2500usb.c | 2 +- drivers/net/wireless/rt2x00/rt2500usb.h | 2 +- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- drivers/net/wireless/rt2x00/rt2x00config.c | 2 +- drivers/net/wireless/rt2x00/rt2x00crypto.c | 2 +- drivers/net/wireless/rt2x00/rt2x00debug.c | 2 +- drivers/net/wireless/rt2x00/rt2x00debug.h | 2 +- drivers/net/wireless/rt2x00/rt2x00dev.c | 2 +- drivers/net/wireless/rt2x00/rt2x00dump.h | 2 +- drivers/net/wireless/rt2x00/rt2x00firmware.c | 2 +- drivers/net/wireless/rt2x00/rt2x00leds.c | 2 +- drivers/net/wireless/rt2x00/rt2x00leds.h | 2 +- drivers/net/wireless/rt2x00/rt2x00lib.h | 2 +- drivers/net/wireless/rt2x00/rt2x00link.c | 2 +- drivers/net/wireless/rt2x00/rt2x00mac.c | 2 +- drivers/net/wireless/rt2x00/rt2x00pci.c | 2 +- drivers/net/wireless/rt2x00/rt2x00pci.h | 2 +- drivers/net/wireless/rt2x00/rt2x00queue.c | 2 +- drivers/net/wireless/rt2x00/rt2x00queue.h | 2 +- drivers/net/wireless/rt2x00/rt2x00reg.h | 2 +- drivers/net/wireless/rt2x00/rt2x00rfkill.c | 2 +- drivers/net/wireless/rt2x00/rt2x00usb.c | 2 +- drivers/net/wireless/rt2x00/rt2x00usb.h | 2 +- drivers/net/wireless/rt2x00/rt61pci.c | 2 +- drivers/net/wireless/rt2x00/rt61pci.h | 2 +- drivers/net/wireless/rt2x00/rt73usb.c | 2 +- drivers/net/wireless/rt2x00/rt73usb.h | 2 +- 31 files changed, 31 insertions(+), 31 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 76c6cb518f2..b0867a71285 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index 9aefda4ab3c..72ac31c3cb7 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index c1203e37a6f..d2b36b1e929 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h index e135247f7f8..17a0c9c8c18 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.h +++ b/drivers/net/wireless/rt2x00/rt2500pci.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 67dd84ce58b..71de7868bb8 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index e1f714e82af..afce0e0322c 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 27c0f335f40..cc56637e73b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index ab139f2698b..6b3bb0f661d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index e9d3ddae278..0b41845d954 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index cc194060534..dcdce7f746b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.h b/drivers/net/wireless/rt2x00/rt2x00debug.h index a92104dfee9..035cbc98c59 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.h +++ b/drivers/net/wireless/rt2x00/rt2x00debug.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 12331b15fe7..cd4447502d8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00dump.h b/drivers/net/wireless/rt2x00/rt2x00dump.h index 7169c222a48..fdedb512292 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dump.h +++ b/drivers/net/wireless/rt2x00/rt2x00dump.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c index bab05a56e7a..2a7e8bc0016 100644 --- a/drivers/net/wireless/rt2x00/rt2x00firmware.c +++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c index a0cd35b6beb..9b531e0ca0c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00leds.c +++ b/drivers/net/wireless/rt2x00/rt2x00leds.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.h b/drivers/net/wireless/rt2x00/rt2x00leds.h index 9df4a49bdca..1046977e6a1 100644 --- a/drivers/net/wireless/rt2x00/rt2x00leds.h +++ b/drivers/net/wireless/rt2x00/rt2x00leds.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 92918f315ee..daf0def915d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index ee08f1167f5..9223a6d1f1d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 3e204406f44..71de8a7144f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index d52b22b82d1..e616c20d4a7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index 9c0a4d77bc1..15a12487e04 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 67140e75608..c86fb647175 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 98209d2e93a..97e2ab08f08 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index 93f8427055c..9ddc2d07eef 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c index 53f64b76a8c..b6d4c6700bf 100644 --- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c +++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 0b29d767a25..c89d1520838 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index 2bd4ac855f5..fe4523887bd 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 549480a963e..8a8753e2930 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index cd86def8de5..2f97fee7a8d 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 849220236c7..961f9f9352d 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 204bbd5b7c5..834b28ce6cd 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify -- GitLab From 5e790023620ee02486fd64c7e5a6115ce004495d Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 17 Jan 2009 20:42:58 +0100 Subject: [PATCH 0873/4982] rt2x00: conf_tx() only need register access for WMM queues conf_tx() in rt61pci and rt73usb only have to check once if the queue_idx indicates a non-WMM queue and break of the function immediately if that is the case. Only the WMM queues need to have the TX configuration written to the registers. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt61pci.c | 30 +++++++++++++-------------- drivers/net/wireless/rt2x00/rt73usb.c | 30 +++++++++++++-------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 8a8753e2930..3a7eccac885 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2657,6 +2657,7 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, struct rt2x00_field32 field; int retval; u32 reg; + u32 offset; /* * First pass the configuration through rt2x00lib, that will @@ -2668,24 +2669,23 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, if (retval) return retval; + /* + * We only need to perform additional register initialization + * for WMM queues/ + */ + if (queue_idx >= 4) + return 0; + queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); /* Update WMM TXOP register */ - if (queue_idx < 2) { - field.bit_offset = queue_idx * 16; - field.bit_mask = 0xffff << field.bit_offset; - - rt2x00pci_register_read(rt2x00dev, AC_TXOP_CSR0, ®); - rt2x00_set_field32(®, field, queue->txop); - rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR0, reg); - } else if (queue_idx < 4) { - field.bit_offset = (queue_idx - 2) * 16; - field.bit_mask = 0xffff << field.bit_offset; - - rt2x00pci_register_read(rt2x00dev, AC_TXOP_CSR1, ®); - rt2x00_set_field32(®, field, queue->txop); - rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR1, reg); - } + offset = AC_TXOP_CSR0 + (sizeof(u32) * (!!(queue_idx & 2))); + field.bit_offset = (queue_idx & 1) * 16; + field.bit_mask = 0xffff << field.bit_offset; + + rt2x00pci_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, field, queue->txop); + rt2x00pci_register_write(rt2x00dev, offset, reg); /* Update WMM registers */ field.bit_offset = queue_idx * 4; diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 961f9f9352d..60c43c11bc1 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2180,6 +2180,7 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, struct rt2x00_field32 field; int retval; u32 reg; + u32 offset; /* * First pass the configuration through rt2x00lib, that will @@ -2191,24 +2192,23 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, if (retval) return retval; + /* + * We only need to perform additional register initialization + * for WMM queues/ + */ + if (queue_idx >= 4) + return 0; + queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); /* Update WMM TXOP register */ - if (queue_idx < 2) { - field.bit_offset = queue_idx * 16; - field.bit_mask = 0xffff << field.bit_offset; - - rt2x00usb_register_read(rt2x00dev, AC_TXOP_CSR0, ®); - rt2x00_set_field32(®, field, queue->txop); - rt2x00usb_register_write(rt2x00dev, AC_TXOP_CSR0, reg); - } else if (queue_idx < 4) { - field.bit_offset = (queue_idx - 2) * 16; - field.bit_mask = 0xffff << field.bit_offset; - - rt2x00usb_register_read(rt2x00dev, AC_TXOP_CSR1, ®); - rt2x00_set_field32(®, field, queue->txop); - rt2x00usb_register_write(rt2x00dev, AC_TXOP_CSR1, reg); - } + offset = AC_TXOP_CSR0 + (sizeof(u32) * (!!(queue_idx & 2))); + field.bit_offset = (queue_idx & 1) * 16; + field.bit_mask = 0xffff << field.bit_offset; + + rt2x00usb_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, field, queue->txop); + rt2x00usb_register_write(rt2x00dev, offset, reg); /* Update WMM registers */ field.bit_offset = queue_idx * 4; -- GitLab From 3d3e451ff71b4e951d4b522b460a94f36fb5b276 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 17 Jan 2009 20:44:08 +0100 Subject: [PATCH 0874/4982] rt2x00: Add LED_MODE_ASUS support When the led mode is asus, the activity led mode must be registered otherwise the second LED will not be enabled. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 4 +++- drivers/net/wireless/rt2x00/rt2500pci.c | 4 +++- drivers/net/wireless/rt2x00/rt2500usb.c | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index b0867a71285..4a2c0b971ca 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1395,7 +1395,9 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); rt2400pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); - if (value == LED_MODE_TXRX_ACTIVITY || value == LED_MODE_DEFAULT) + if (value == LED_MODE_TXRX_ACTIVITY || + value == LED_MODE_DEFAULT || + value == LED_MODE_ASUS) rt2400pci_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_ACTIVITY); #endif /* CONFIG_RT2X00_LIB_LEDS */ diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index d2b36b1e929..b9104e28bc2 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1552,7 +1552,9 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); rt2500pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); - if (value == LED_MODE_TXRX_ACTIVITY || value == LED_MODE_DEFAULT) + if (value == LED_MODE_TXRX_ACTIVITY || + value == LED_MODE_DEFAULT || + value == LED_MODE_ASUS) rt2500pci_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_ACTIVITY); #endif /* CONFIG_RT2X00_LIB_LEDS */ diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 71de7868bb8..c526e737fca 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1603,7 +1603,9 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); - if (value == LED_MODE_TXRX_ACTIVITY || value == LED_MODE_DEFAULT) + if (value == LED_MODE_TXRX_ACTIVITY || + value == LED_MODE_DEFAULT || + value == LED_MODE_ASUS) rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_ACTIVITY); #endif /* CONFIG_RT2X00_LIB_LEDS */ -- GitLab From 672cf3cefe5f686637dec72b9f3d21fe1cdc8c94 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Sun, 18 Jan 2009 23:50:27 +0100 Subject: [PATCH 0875/4982] ath5k: notice a negative keytype To notice a negative keytype Signed-off-by: Roel Kluin Acked-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/pcu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath5k/pcu.c b/drivers/net/wireless/ath5k/pcu.c index e758b70ab7e..86f53a55b0f 100644 --- a/drivers/net/wireless/ath5k/pcu.c +++ b/drivers/net/wireless/ath5k/pcu.c @@ -1044,7 +1044,7 @@ int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, __le32 key_v[5] = {}; __le32 key0 = 0, key1 = 0; __le32 *rxmic, *txmic; - u32 keytype; + int keytype; u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; bool is_tkip; const u8 *key_ptr; -- GitLab From e9648179706448d50884f172711b00a6e5ab9e42 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 15 Jan 2009 17:41:16 +0800 Subject: [PATCH 0876/4982] mac80211: cleanup kmalloc/memset -> kcalloc Transform calls kmalloc/memset to a single kcalloc. Signed-off-by: Wei Yongjun Signed-off-by: John W. Linville --- net/mac80211/ht.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 6be48526423..7a38d2e76ca 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -950,7 +950,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, /* prepare reordering buffer */ tid_agg_rx->reorder_buf = - kmalloc(buf_size * sizeof(struct sk_buff *), GFP_ATOMIC); + kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC); if (!tid_agg_rx->reorder_buf) { #ifdef CONFIG_MAC80211_HT_DEBUG if (net_ratelimit()) @@ -960,8 +960,6 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, kfree(sta->ampdu_mlme.tid_rx[tid]); goto end; } - memset(tid_agg_rx->reorder_buf, 0, - buf_size * sizeof(struct sk_buff *)); if (local->ops->ampdu_action) ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START, -- GitLab From 9cf2d186e4c52308cad8ecd893924e22ed020605 Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Mon, 19 Jan 2009 13:50:27 +0200 Subject: [PATCH 0877/4982] mac80211: remove mesh_plink_close() method. This patch removes mesh_plink_close() method as it is unused. Signed-off-by: Rami Rosen Signed-off-by: John W. Linville --- net/mac80211/mesh.h | 1 - net/mac80211/mesh_plink.c | 30 ------------------------------ 2 files changed, 31 deletions(-) diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index c197ab545e5..c5b0b583346 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -243,7 +243,6 @@ void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); void mesh_plink_broken(struct sta_info *sta); void mesh_plink_deactivate(struct sta_info *sta); int mesh_plink_open(struct sta_info *sta); -int mesh_plink_close(struct sta_info *sta); void mesh_plink_block(struct sta_info *sta); void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len, diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 8a6c02ba162..c140a1b71a5 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -361,36 +361,6 @@ void mesh_plink_block(struct sta_info *sta) spin_unlock_bh(&sta->lock); } -int mesh_plink_close(struct sta_info *sta) -{ - struct ieee80211_sub_if_data *sdata = sta->sdata; - __le16 llid, plid, reason; - - mpl_dbg("Mesh plink: closing link with %pM\n", sta->sta.addr); - spin_lock_bh(&sta->lock); - sta->reason = cpu_to_le16(MESH_LINK_CANCELLED); - reason = sta->reason; - - if (sta->plink_state == PLINK_LISTEN || - sta->plink_state == PLINK_BLOCKED) { - mesh_plink_fsm_restart(sta); - spin_unlock_bh(&sta->lock); - return 0; - } else if (sta->plink_state == PLINK_ESTAB) { - __mesh_plink_deactivate(sta); - /* The timer should not be running */ - mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); - } else if (!mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata))) - sta->ignore_plink_timer = true; - - sta->plink_state = PLINK_HOLDING; - llid = sta->llid; - plid = sta->plid; - spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sta->sdata, PLINK_CLOSE, sta->sta.addr, llid, - plid, reason); - return 0; -} void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status) -- GitLab From eb80ed8d1fc0f3005ab356fbd8d61d870e3038e6 Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Mon, 19 Jan 2009 13:50:32 +0200 Subject: [PATCH 0878/4982] mac80211: trivial documentation fixes (enum mesh_path_flags). This patch fixes documentation of enum mesh_path_flags in mesh.h. Signed-off-by: Rami Rosen Signed-off-by: John W. Linville --- net/mac80211/mesh.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index c5b0b583346..f1196f5c3ef 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -24,15 +24,15 @@ * * * - * @MESH_PATH_ACTIVE: the mesh path is can be used for forwarding - * @MESH_PATH_RESOLVED: the discovery process is running for this mesh path + * @MESH_PATH_ACTIVE: the mesh path can be used for forwarding + * @MESH_PATH_RESOLVING: the discovery process is running for this mesh path * @MESH_PATH_DSN_VALID: the mesh path contains a valid destination sequence * number * @MESH_PATH_FIXED: the mesh path has been manually set and should not be * modified * @MESH_PATH_RESOLVED: the mesh path can has been resolved * - * MESH_PATH_RESOLVED and MESH_PATH_DELETE are used by the mesh path timer to + * MESH_PATH_RESOLVED is used by the mesh path timer to * decide when to stop or cancel the mesh path discovery. */ enum mesh_path_flags { -- GitLab From 2182b830fe0258477d469429d2dfb5702b84587e Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Mon, 19 Jan 2009 13:50:37 +0200 Subject: [PATCH 0879/4982] mac80211: trivial documentation fix (mesh_nexthop_lookup()). This patch fixes the documentation of mesh_nexthop_lookup() in mesh_hwmp.c. Signed-off-by: Rami Rosen Signed-off-by: John W. Linville --- net/mac80211/mesh_hwmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 3f1785c1bac..4f862b2a004 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -759,7 +759,7 @@ enddiscovery: } /** - * ieee80211s_lookup_nexthop - put the appropriate next hop on a mesh frame + * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame * * @skb: 802.11 frame to be sent * @sdata: network subif the frame will be sent through -- GitLab From c7e035a95d68819491b5250c6854f144c941e305 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 19 Jan 2009 13:02:15 +0100 Subject: [PATCH 0880/4982] iwl3945: fix some warnings when compiled without debug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the following warnings if compiled without CONFIG_IWLWIFI_DEBUG. drivers/net/wireless/iwlwifi/iwl3945-base.c: In function ‘iwl3945_rx_reply_add_sta’: drivers/net/wireless/iwlwifi/iwl3945-base.c:2748: warning: unused variable ‘pkt’ drivers/net/wireless/iwlwifi/iwl3945-base.c: In function ‘iwl3945_rx_scan_results_notif’: drivers/net/wireless/iwlwifi/iwl3945-base.c:2903: warning: unused variable ‘notif’ drivers/net/wireless/iwlwifi/iwl3945-base.c: In function ‘iwl3945_rx_scan_complete_notif’: drivers/net/wireless/iwlwifi/iwl3945-base.c:2928: warning: unused variable ‘scan_notif’ Signed-off-by: Helmut Schaa Acked-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 050d532475c..b916f00b61b 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2744,7 +2744,9 @@ static void iwl3945_rx_reply_alive(struct iwl_priv *priv, static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { +#ifdef CONFIG_IWLWIFI_DEBUG struct iwl_rx_packet *pkt = (void *)rxb->skb->data; +#endif IWL_DEBUG_RX("Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status); return; @@ -2898,9 +2900,11 @@ static void iwl3945_rx_scan_start_notif(struct iwl_priv *priv, static void iwl3945_rx_scan_results_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { +#ifdef CONFIG_IWLWIFI_DEBUG struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl_scanresults_notification *notif = (struct iwl_scanresults_notification *)pkt->u.raw; +#endif IWL_DEBUG_SCAN("Scan ch.res: " "%d [802.11%s] " @@ -2923,8 +2927,10 @@ static void iwl3945_rx_scan_results_notif(struct iwl_priv *priv, static void iwl3945_rx_scan_complete_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { +#ifdef CONFIG_IWLWIFI_DEBUG struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw; +#endif IWL_DEBUG_SCAN("Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n", scan_notif->scanned_channels, -- GitLab From 6cd0b1cb872b3bf9fc5de4536404206ab74bafdd Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 19 Jan 2009 13:10:07 +0100 Subject: [PATCH 0881/4982] iwlagn: fix hw-rfkill while the interface is down Currently iwlagn is not able to report hw-killswitch events while the interface is down. This has implications on user space tools (like NetworkManager) relying on rfkill notifications to bring the interface up once the wireless gets enabled through a hw killswitch. Thus, enable the device already in iwl_pci_probe instead of iwl_up and enable interrups while the interface is down in order to get notified about killswitch state changes. The firmware loading is still done in iwl_up. Signed-off-by: Helmut Schaa Acked-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 110 +++++++++++++------------ 1 file changed, 56 insertions(+), 54 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b18596fed90..be14cd942a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1399,13 +1399,16 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) hw_rf_kill ? "disable radio" : "enable radio"); /* driver only loads ucode once setting the interface up. - * the driver as well won't allow loading if RFKILL is set - * therefore no need to restart the driver from this handler + * the driver allows loading the ucode even if the radio + * is killed. Hence update the killswitch state here. The + * rfkill handler will care about restarting if needed. */ - if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) { - clear_bit(STATUS_RF_KILL_HW, &priv->status); - if (priv->is_open && !iwl_is_rfkill(priv)) - queue_work(priv->workqueue, &priv->up); + if (!test_bit(STATUS_ALIVE, &priv->status)) { + if (hw_rf_kill) + set_bit(STATUS_RF_KILL_HW, &priv->status); + else + clear_bit(STATUS_RF_KILL_HW, &priv->status); + queue_work(priv->workqueue, &priv->rf_kill); } handled |= CSR_INT_BIT_RF_KILL; @@ -2158,7 +2161,8 @@ static void iwl_bg_rf_kill(struct work_struct *work) IWL_DEBUG(IWL_DL_RF_KILL, "HW and/or SW RF Kill no longer active, restarting " "device\n"); - if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) + if (!test_bit(STATUS_EXIT_PENDING, &priv->status) && + test_bit(STATUS_ALIVE, &priv->status)) queue_work(priv->workqueue, &priv->restart); } else { /* make sure mac80211 stop sending Tx frame */ @@ -2355,31 +2359,9 @@ static int iwl_mac_start(struct ieee80211_hw *hw) { struct iwl_priv *priv = hw->priv; int ret; - u16 pci_cmd; IWL_DEBUG_MAC80211("enter\n"); - if (pci_enable_device(priv->pci_dev)) { - IWL_ERR(priv, "Fail to pci_enable_device\n"); - return -ENODEV; - } - pci_restore_state(priv->pci_dev); - pci_enable_msi(priv->pci_dev); - - /* enable interrupts if needed: hw bug w/a */ - pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd); - if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { - pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; - pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd); - } - - ret = request_irq(priv->pci_dev->irq, iwl_isr, IRQF_SHARED, - DRV_NAME, priv); - if (ret) { - IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); - goto out_disable_msi; - } - /* we should be verifying the device is ready to be opened */ mutex_lock(&priv->mutex); @@ -2392,7 +2374,7 @@ static int iwl_mac_start(struct ieee80211_hw *hw) if (ret) { IWL_ERR(priv, "Could not read microcode: %d\n", ret); mutex_unlock(&priv->mutex); - goto out_release_irq; + return ret; } } @@ -2403,7 +2385,7 @@ static int iwl_mac_start(struct ieee80211_hw *hw) iwl_rfkill_set_hw_state(priv); if (ret) - goto out_release_irq; + return ret; if (iwl_is_rfkill(priv)) goto out; @@ -2422,8 +2404,7 @@ static int iwl_mac_start(struct ieee80211_hw *hw) if (!test_bit(STATUS_READY, &priv->status)) { IWL_ERR(priv, "START_ALIVE timeout after %dms.\n", jiffies_to_msecs(UCODE_READY_TIMEOUT)); - ret = -ETIMEDOUT; - goto out_release_irq; + return -ETIMEDOUT; } } @@ -2431,15 +2412,6 @@ out: priv->is_open = 1; IWL_DEBUG_MAC80211("leave\n"); return 0; - -out_release_irq: - free_irq(priv->pci_dev->irq, priv); -out_disable_msi: - pci_disable_msi(priv->pci_dev); - pci_disable_device(priv->pci_dev); - priv->is_open = 0; - IWL_DEBUG_MAC80211("leave - failed\n"); - return ret; } static void iwl_mac_stop(struct ieee80211_hw *hw) @@ -2467,10 +2439,10 @@ static void iwl_mac_stop(struct ieee80211_hw *hw) iwl_down(priv); flush_workqueue(priv->workqueue); - free_irq(priv->pci_dev->irq, priv); - pci_disable_msi(priv->pci_dev); - pci_save_state(priv->pci_dev); - pci_disable_device(priv->pci_dev); + + /* enable interrupts again in order to receive rfkill changes */ + iwl_write32(priv, CSR_INT, 0xFFFFFFFF); + iwl_enable_interrupts(priv); IWL_DEBUG_MAC80211("leave\n"); } @@ -3729,6 +3701,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct ieee80211_hw *hw; struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); unsigned long flags; + u16 pci_cmd; /************************ * 1. Allocating HW data @@ -3872,26 +3845,36 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) iwl_disable_interrupts(priv); spin_unlock_irqrestore(&priv->lock, flags); + pci_enable_msi(priv->pci_dev); + + err = request_irq(priv->pci_dev->irq, iwl_isr, IRQF_SHARED, + DRV_NAME, priv); + if (err) { + IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); + goto out_disable_msi; + } err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group); if (err) { IWL_ERR(priv, "failed to create sysfs device attributes\n"); goto out_uninit_drv; } - iwl_setup_deferred_work(priv); iwl_setup_rx_handlers(priv); - /******************** - * 9. Conclude - ********************/ - pci_save_state(pdev); - pci_disable_device(pdev); - /********************************** - * 10. Setup and register mac80211 + * 9. Setup and register mac80211 **********************************/ + /* enable interrupts if needed: hw bug w/a */ + pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd); + if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { + pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; + pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd); + } + + iwl_enable_interrupts(priv); + err = iwl_setup_mac(priv); if (err) goto out_remove_sysfs; @@ -3900,15 +3883,27 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (err) IWL_ERR(priv, "failed to create debugfs files\n"); + /* If platform's RF_KILL switch is NOT set to KILL */ + if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) + clear_bit(STATUS_RF_KILL_HW, &priv->status); + else + set_bit(STATUS_RF_KILL_HW, &priv->status); + err = iwl_rfkill_init(priv); if (err) IWL_ERR(priv, "Unable to initialize RFKILL system. " "Ignoring error: %d\n", err); + else + iwl_rfkill_set_hw_state(priv); + iwl_power_initialize(priv); return 0; out_remove_sysfs: sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group); + out_disable_msi: + pci_disable_msi(priv->pci_dev); + pci_disable_device(priv->pci_dev); out_uninit_drv: iwl_uninit_drv(priv); out_free_eeprom: @@ -3980,6 +3975,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) destroy_workqueue(priv->workqueue); priv->workqueue = NULL; + free_irq(priv->pci_dev->irq, priv); + pci_disable_msi(priv->pci_dev); pci_iounmap(pdev, priv->hw_base); pci_release_regions(pdev); pci_disable_device(pdev); @@ -4005,6 +4002,8 @@ static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) priv->is_open = 1; } + pci_save_state(pdev); + pci_disable_device(pdev); pci_set_power_state(pdev, PCI_D3hot); return 0; @@ -4015,6 +4014,9 @@ static int iwl_pci_resume(struct pci_dev *pdev) struct iwl_priv *priv = pci_get_drvdata(pdev); pci_set_power_state(pdev, PCI_D0); + pci_enable_device(pdev); + pci_restore_state(pdev); + iwl_enable_interrupts(priv); if (priv->is_open) iwl_mac_start(priv->hw); -- GitLab From e0463f501fb945c1fde536d98eefc5ba156ff497 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 19 Jan 2009 16:52:00 +0200 Subject: [PATCH 0882/4982] mac80211: Fix drop-unencrypted for management frames ADDBA request Action frame was sent out before 4-way handshake was completed and the initial 802.11w code ended up dropping the frame even if MFP was not enabled. While the sending of Action frames this early is not really a good idea (will break with MFP enabled), we should not break this for the MFP disabled case. This patch fixes ieee80211_tx_h_select_key() not to drop management frames if MFP is disabled. If MFP is enabled, Action frames will be dropped before keys are set per IEEE 802.11w/D7.0. Other robust management frames (i.e., Deauthentication and Disassociation frames) are allowed unprotected prior to key configuration. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/mac80211/tx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index ad53ea9e9c7..7b013fb0d27 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -432,7 +432,10 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) tx->key = key; else if (tx->sdata->drop_unencrypted && (tx->skb->protocol != cpu_to_be16(ETH_P_PAE)) && - !(info->flags & IEEE80211_TX_CTL_INJECTED)) { + !(info->flags & IEEE80211_TX_CTL_INJECTED) && + (!ieee80211_is_robust_mgmt_frame(hdr) || + (ieee80211_is_action(hdr->frame_control) && + tx->sta && test_sta_flags(tx->sta, WLAN_STA_MFP)))) { I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); return TX_DROP; } else -- GitLab From 0378b3f1c49d48ed524eabda7e4340163d9483c9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 19 Jan 2009 11:20:52 -0500 Subject: [PATCH 0883/4982] cfg80211: add PM hooks This should help implement suspend/resume in mac80211, these hooks will be run before the device is suspended and after it resumes. Therefore, they can touch the hardware as much as they want to. Signed-off-by: Johannes Berg Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- include/net/cfg80211.h | 6 ++++++ net/wireless/sysfs.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index c7da88fb15b..f19c3e16366 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -472,6 +472,9 @@ struct ieee80211_channel; * wireless extensions but this is subject to reevaluation as soon as this * code is used more widely and we have a first user without wext. * + * @suspend: wiphy device needs to be suspended + * @resume: wiphy device needs to be resumed + * * @add_virtual_intf: create a new virtual interface with the given name, * must set the struct wireless_dev's iftype. * @@ -525,6 +528,9 @@ struct ieee80211_channel; * @set_mgmt_extra_ie: Set extra IE data for management frames */ struct cfg80211_ops { + int (*suspend)(struct wiphy *wiphy); + int (*resume)(struct wiphy *wiphy); + int (*add_virtual_intf)(struct wiphy *wiphy, char *name, enum nl80211_iftype type, u32 *flags, struct vif_params *params); diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c index 79a38287764..26a72b0797a 100644 --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c @@ -55,6 +55,34 @@ static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env) } #endif +static int wiphy_suspend(struct device *dev, pm_message_t state) +{ + struct cfg80211_registered_device *rdev = dev_to_rdev(dev); + int ret = 0; + + if (rdev->ops->suspend) { + rtnl_lock(); + ret = rdev->ops->suspend(&rdev->wiphy); + rtnl_unlock(); + } + + return ret; +} + +static int wiphy_resume(struct device *dev) +{ + struct cfg80211_registered_device *rdev = dev_to_rdev(dev); + int ret = 0; + + if (rdev->ops->resume) { + rtnl_lock(); + ret = rdev->ops->resume(&rdev->wiphy); + rtnl_unlock(); + } + + return ret; +} + struct class ieee80211_class = { .name = "ieee80211", .owner = THIS_MODULE, @@ -63,6 +91,8 @@ struct class ieee80211_class = { #ifdef CONFIG_HOTPLUG .dev_uevent = wiphy_uevent, #endif + .suspend = wiphy_suspend, + .resume = wiphy_resume, }; int wiphy_sysfs_init(void) -- GitLab From 665af4fc8979734d8f73c9a6732be07e545ce4cc Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 19 Jan 2009 11:20:53 -0500 Subject: [PATCH 0884/4982] mac80211: add suspend/resume callbacks This patch introduces suspend and resume callbacks to mac80211, allowing mac80211 to quiesce its state (bringing down interfaces, removing keys, etc) in preparation for suspend. cfg80211 will call the suspend hook before the device suspend, and resume hook after the device resume. Signed-off-by: Bob Copeland Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/Makefile | 2 + net/mac80211/cfg.c | 17 ++++++ net/mac80211/ieee80211_i.h | 4 ++ net/mac80211/pm.c | 114 +++++++++++++++++++++++++++++++++++++ 4 files changed, 137 insertions(+) create mode 100644 net/mac80211/pm.c diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 5c6fadfb6a0..58c94bb38e8 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile @@ -38,6 +38,8 @@ mac80211-$(CONFIG_MAC80211_MESH) += \ mesh_plink.o \ mesh_hwmp.o +mac80211-$(CONFIG_PM) += pm.o + # objects for PID algorithm rc80211_pid-y := rc80211_pid_algo.o rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index d1ac3ab2c51..3527de22caf 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1256,6 +1256,21 @@ static int ieee80211_set_mgmt_extra_ie(struct wiphy *wiphy, return ret; } +#ifdef CONFIG_PM +static int ieee80211_suspend(struct wiphy *wiphy) +{ + return __ieee80211_suspend(wiphy_priv(wiphy)); +} + +static int ieee80211_resume(struct wiphy *wiphy) +{ + return __ieee80211_resume(wiphy_priv(wiphy)); +} +#else +#define ieee80211_suspend NULL +#define ieee80211_resume NULL +#endif + struct cfg80211_ops mac80211_config_ops = { .add_virtual_intf = ieee80211_add_iface, .del_virtual_intf = ieee80211_del_iface, @@ -1286,4 +1301,6 @@ struct cfg80211_ops mac80211_config_ops = { .set_txq_params = ieee80211_set_txq_params, .set_channel = ieee80211_set_channel, .set_mgmt_extra_ie = ieee80211_set_mgmt_extra_ie, + .suspend = ieee80211_suspend, + .resume = ieee80211_resume, }; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 5eafd3affe2..faa2476a245 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1006,6 +1006,10 @@ void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, u16 capab_info, u8 *pwr_constr_elem, u8 pwr_constr_elem_len); +/* Suspend/resume */ +int __ieee80211_suspend(struct ieee80211_hw *hw); +int __ieee80211_resume(struct ieee80211_hw *hw); + /* utility functions/constants */ extern void *mac80211_wiphy_privid; /* for wiphy privid */ extern const unsigned char rfc1042_header[6]; diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c new file mode 100644 index 00000000000..6d17ed7fd49 --- /dev/null +++ b/net/mac80211/pm.c @@ -0,0 +1,114 @@ +#include +#include + +#include "ieee80211_i.h" +#include "led.h" + +int __ieee80211_suspend(struct ieee80211_hw *hw) +{ + struct ieee80211_local *local = hw_to_local(hw); + struct ieee80211_sub_if_data *sdata; + struct ieee80211_if_init_conf conf; + struct sta_info *sta; + + flush_workqueue(local->hw.workqueue); + + /* disable keys */ + list_for_each_entry(sdata, &local->interfaces, list) + ieee80211_disable_keys(sdata); + + /* remove STAs */ + list_for_each_entry(sta, &local->sta_list, list) { + + if (local->ops->sta_notify) { + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + sdata = container_of(sdata->bss, + struct ieee80211_sub_if_data, + u.ap); + + local->ops->sta_notify(hw, &sdata->vif, + STA_NOTIFY_REMOVE, &sta->sta); + } + } + + /* remove all interfaces */ + list_for_each_entry(sdata, &local->interfaces, list) { + + if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && + sdata->vif.type != NL80211_IFTYPE_MONITOR && + netif_running(sdata->dev)) { + conf.vif = &sdata->vif; + conf.type = sdata->vif.type; + conf.mac_addr = sdata->dev->dev_addr; + local->ops->remove_interface(hw, &conf); + } + } + + /* stop hardware */ + if (local->open_count) { + ieee80211_led_radio(local, false); + local->ops->stop(hw); + } + return 0; +} + +int __ieee80211_resume(struct ieee80211_hw *hw) +{ + struct ieee80211_local *local = hw_to_local(hw); + struct ieee80211_sub_if_data *sdata; + struct ieee80211_if_init_conf conf; + struct sta_info *sta; + int res; + + /* restart hardware */ + if (local->open_count) { + res = local->ops->start(hw); + + ieee80211_led_radio(local, hw->conf.radio_enabled); + } + + /* add interfaces */ + list_for_each_entry(sdata, &local->interfaces, list) { + + if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && + sdata->vif.type != NL80211_IFTYPE_MONITOR && + netif_running(sdata->dev)) { + conf.vif = &sdata->vif; + conf.type = sdata->vif.type; + conf.mac_addr = sdata->dev->dev_addr; + res = local->ops->add_interface(hw, &conf); + } + } + + /* add STAs back */ + list_for_each_entry(sta, &local->sta_list, list) { + + if (local->ops->sta_notify) { + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + sdata = container_of(sdata->bss, + struct ieee80211_sub_if_data, + u.ap); + + local->ops->sta_notify(hw, &sdata->vif, + STA_NOTIFY_ADD, &sta->sta); + } + } + + /* add back keys */ + list_for_each_entry(sdata, &local->interfaces, list) + if (netif_running(sdata->dev)) + ieee80211_enable_keys(sdata); + + /* setup RTS threshold */ + if (local->ops->set_rts_threshold) + local->ops->set_rts_threshold(hw, local->rts_threshold); + + /* reconfigure hardware */ + ieee80211_hw_config(local, ~0); + + netif_addr_lock_bh(local->mdev); + ieee80211_configure_filter(local); + netif_addr_unlock_bh(local->mdev); + + return 0; +} -- GitLab From bb2becac91f13e862d4601a8c5364bc758c35b8e Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 19 Jan 2009 11:20:54 -0500 Subject: [PATCH 0885/4982] ath5k: remove stop/start calls from within suspend/resume mac80211 now takes down interfaces automatically during suspend so doing it in the driver is unnecessary. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index d3178731adc..747b49682c5 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -347,9 +347,9 @@ static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) } /* Interrupt handling */ -static int ath5k_init(struct ath5k_softc *sc, bool is_resume); +static int ath5k_init(struct ath5k_softc *sc); static int ath5k_stop_locked(struct ath5k_softc *sc); -static int ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend); +static int ath5k_stop_hw(struct ath5k_softc *sc); static irqreturn_t ath5k_intr(int irq, void *dev_id); static void ath5k_tasklet_reset(unsigned long data); @@ -653,8 +653,6 @@ ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state) ath5k_led_off(sc); - ath5k_stop_hw(sc, true); - free_irq(pdev->irq, sc); pci_save_state(pdev); pci_disable_device(pdev); @@ -689,14 +687,9 @@ ath5k_pci_resume(struct pci_dev *pdev) goto err_no_irq; } - err = ath5k_init(sc, true); - if (err) - goto err_irq; ath5k_led_enable(sc); - return 0; -err_irq: - free_irq(pdev->irq, sc); + err_no_irq: pci_disable_device(pdev); return err; @@ -2226,18 +2219,13 @@ ath5k_beacon_config(struct ath5k_softc *sc) \********************/ static int -ath5k_init(struct ath5k_softc *sc, bool is_resume) +ath5k_init(struct ath5k_softc *sc) { struct ath5k_hw *ah = sc->ah; int ret, i; mutex_lock(&sc->lock); - if (is_resume && !test_bit(ATH_STAT_STARTED, sc->status)) - goto out_ok; - - __clear_bit(ATH_STAT_STARTED, sc->status); - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode); /* @@ -2269,15 +2257,12 @@ ath5k_init(struct ath5k_softc *sc, bool is_resume) for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) ath5k_hw_reset_key(ah, i); - __set_bit(ATH_STAT_STARTED, sc->status); - /* Set ack to be sent at low bit-rates */ ath5k_hw_set_ack_bitrate_high(ah, false); mod_timer(&sc->calib_tim, round_jiffies(jiffies + msecs_to_jiffies(ath5k_calinterval * 1000))); -out_ok: ret = 0; done: mmiowb(); @@ -2332,7 +2317,7 @@ ath5k_stop_locked(struct ath5k_softc *sc) * stop is preempted). */ static int -ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend) +ath5k_stop_hw(struct ath5k_softc *sc) { int ret; @@ -2363,8 +2348,6 @@ ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend) } } ath5k_txbuf_free(sc, sc->bbuf); - if (!is_suspend) - __clear_bit(ATH_STAT_STARTED, sc->status); mmiowb(); mutex_unlock(&sc->lock); @@ -2771,12 +2754,12 @@ ath5k_reset_wake(struct ath5k_softc *sc) static int ath5k_start(struct ieee80211_hw *hw) { - return ath5k_init(hw->priv, false); + return ath5k_init(hw->priv); } static void ath5k_stop(struct ieee80211_hw *hw) { - ath5k_stop_hw(hw->priv, false); + ath5k_stop_hw(hw->priv); } static int ath5k_add_interface(struct ieee80211_hw *hw, -- GitLab From f797eb7e2903571e9c0e7e5d64113f51209f8dc4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 19 Jan 2009 18:48:46 +0200 Subject: [PATCH 0886/4982] mac80211: Fix MFP Association Comeback to use Timeout Interval IE The separate Association Comeback Time IE was removed from IEEE 802.11w and the Timeout Interval IE (from IEEE 802.11r) is used instead. The editing on this is still somewhat incomplete in IEEE 802.11w/D7.0, but still, the use of Timeout Interval IE is the expected mechanism. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 8 +++++++- net/mac80211/ieee80211_i.h | 4 ++-- net/mac80211/mlme.c | 5 +++-- net/mac80211/util.c | 6 +++--- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 7800e20f197..b1bb817d142 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1036,8 +1036,8 @@ enum ieee80211_eid { WLAN_EID_HT_INFORMATION = 61, /* 802.11i */ WLAN_EID_RSN = 48, + WLAN_EID_TIMEOUT_INTERVAL = 56, WLAN_EID_MMIE = 76 /* 802.11w */, - WLAN_EID_ASSOC_COMEBACK_TIME = 77, WLAN_EID_WPA = 221, WLAN_EID_GENERIC = 221, WLAN_EID_VENDOR_SPECIFIC = 221, @@ -1126,6 +1126,12 @@ struct ieee80211_country_ie_triplet { }; } __attribute__ ((packed)); +enum ieee80211_timeout_interval_type { + WLAN_TIMEOUT_REASSOC_DEADLINE = 1 /* 802.11r */, + WLAN_TIMEOUT_KEY_LIFETIME = 2 /* 802.11r */, + WLAN_TIMEOUT_ASSOC_COMEBACK = 3 /* 802.11w */, +}; + /* BACK action code */ enum ieee80211_back_actioncode { WLAN_ACTION_ADDBA_REQ = 0, diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index faa2476a245..a8c72742a8b 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -837,7 +837,7 @@ struct ieee802_11_elems { u8 *country_elem; u8 *pwr_constr_elem; u8 *quiet_elem; /* first quite element */ - u8 *assoc_comeback; + u8 *timeout_int; /* length of them, respectively */ u8 ssid_len; @@ -865,7 +865,7 @@ struct ieee802_11_elems { u8 pwr_constr_elem_len; u8 quiet_elem_len; u8 num_of_quiet_elem; /* can be more the one */ - u8 assoc_comeback_len; + u8 timeout_int_len; }; static inline struct ieee80211_local *hw_to_local( diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 43da6227b37..b9e4b93089c 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1317,9 +1317,10 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY && - elems.assoc_comeback && elems.assoc_comeback_len == 4) { + elems.timeout_int && elems.timeout_int_len == 5 && + elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) { u32 tu, ms; - tu = get_unaligned_le32(elems.assoc_comeback); + tu = get_unaligned_le32(elems.timeout_int + 1); ms = tu * 1024 / 1000; printk(KERN_DEBUG "%s: AP rejected association temporarily; " "comeback duration %u TU (%u ms)\n", diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 963e0473205..3f559e3d0a7 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -653,9 +653,9 @@ void ieee802_11_parse_elems(u8 *start, size_t len, elems->pwr_constr_elem = pos; elems->pwr_constr_elem_len = elen; break; - case WLAN_EID_ASSOC_COMEBACK_TIME: - elems->assoc_comeback = pos; - elems->assoc_comeback_len = elen; + case WLAN_EID_TIMEOUT_INTERVAL: + elems->timeout_int = pos; + elems->timeout_int_len = elen; break; default: break; -- GitLab From 5cd19c5f15f4bd3354cc7f8f8b1125018a84a25c Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Mon, 19 Jan 2009 15:30:21 -0800 Subject: [PATCH 0887/4982] iwlwifi: make iwl-power.c more readable This patch rearrange code in iwl-power.c function to make it a little more readable. No functional changes. Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-power.c | 51 +++++++++++------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index a9f9ffe4b94..0276d51d37c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -149,7 +149,7 @@ static u16 iwl_get_auto_power_mode(struct iwl_priv *priv) } /* initialize to default */ -static int iwl_power_init_handle(struct iwl_priv *priv) +static void iwl_power_init_handle(struct iwl_priv *priv) { struct iwl_power_mgr *pow_data; int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_MAX; @@ -159,7 +159,7 @@ static int iwl_power_init_handle(struct iwl_priv *priv) IWL_DEBUG_POWER("Initialize power \n"); - pow_data = &(priv->power_data); + pow_data = &priv->power_data; memset(pow_data, 0, sizeof(*pow_data)); @@ -179,26 +179,25 @@ static int iwl_power_init_handle(struct iwl_priv *priv) else cmd->flags |= IWL_POWER_PCI_PM_MSK; } - return 0; } /* adjust power command according to DTIM period and power level*/ -static int iwl_update_power_command(struct iwl_priv *priv, - struct iwl_powertable_cmd *cmd, - u16 mode) +static int iwl_update_power_cmd(struct iwl_priv *priv, + struct iwl_powertable_cmd *cmd, u16 mode) { - int ret = 0, i; - u8 skip; - u32 max_sleep = 0; struct iwl_power_vec_entry *range; - u8 period = 0; struct iwl_power_mgr *pow_data; + int i; + u32 max_sleep = 0; + u8 period; + bool skip; if (mode > IWL_POWER_INDEX_5) { IWL_DEBUG_POWER("Error invalid power mode \n"); - return -1; + return -EINVAL; } - pow_data = &(priv->power_data); + + pow_data = &priv->power_data; if (pow_data->dtim_period <= IWL_POWER_RANGE_0_MAX) range = &pow_data->pwr_range_0[0]; @@ -212,14 +211,12 @@ static int iwl_update_power_command(struct iwl_priv *priv, if (period == 0) { period = 1; - skip = 0; - } else - skip = range[mode].no_dtim; - - if (skip == 0) { - max_sleep = period; - cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK; + skip = false; } else { + skip = !!range[mode].no_dtim; + } + + if (skip) { __le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]; max_sleep = le32_to_cpu(slp_itrvl); if (max_sleep == 0xFF) @@ -227,12 +224,14 @@ static int iwl_update_power_command(struct iwl_priv *priv, else if (max_sleep > period) max_sleep = (le32_to_cpu(slp_itrvl) / period) * period; cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK; + } else { + max_sleep = period; + cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK; } - for (i = 0; i < IWL_POWER_VEC_SIZE; i++) { + for (i = 0; i < IWL_POWER_VEC_SIZE; i++) if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep) cmd->sleep_interval[i] = cpu_to_le32(max_sleep); - } IWL_DEBUG_POWER("Flags value = 0x%08X\n", cmd->flags); IWL_DEBUG_POWER("Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout)); @@ -244,7 +243,7 @@ static int iwl_update_power_command(struct iwl_priv *priv, le32_to_cpu(cmd->sleep_interval[3]), le32_to_cpu(cmd->sleep_interval[4])); - return ret; + return 0; } @@ -295,7 +294,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) if (final_mode != IWL_POWER_MODE_CAM) set_bit(STATUS_POWER_PMI, &priv->status); - iwl_update_power_command(priv, &cmd, final_mode); + iwl_update_power_cmd(priv, &cmd, final_mode); cmd.keep_alive_beacons = 0; if (final_mode == IWL_POWER_INDEX_5) @@ -392,13 +391,11 @@ EXPORT_SYMBOL(iwl_power_set_system_mode); /* initialize to default */ void iwl_power_initialize(struct iwl_priv *priv) { - iwl_power_init_handle(priv); priv->power_data.user_power_setting = IWL_POWER_AUTO; - priv->power_data.power_disabled = 0; priv->power_data.system_power_setting = IWL_POWER_SYS_AUTO; - priv->power_data.is_battery_active = 0; priv->power_data.power_disabled = 0; + priv->power_data.is_battery_active = 0; priv->power_data.critical_power_setting = 0; } EXPORT_SYMBOL(iwl_power_initialize); @@ -407,8 +404,8 @@ EXPORT_SYMBOL(iwl_power_initialize); int iwl_power_temperature_change(struct iwl_priv *priv) { int ret = 0; - u16 new_critical = priv->power_data.critical_power_setting; s32 temperature = KELVIN_TO_CELSIUS(priv->last_temperature); + u16 new_critical = priv->power_data.critical_power_setting; if (temperature > IWL_CT_KILL_TEMPERATURE) return 0; -- GitLab From 42986796409a6293351207150edb7b4689b6013d Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Mon, 19 Jan 2009 15:30:22 -0800 Subject: [PATCH 0888/4982] iwlwifi: fix iwl_mac_set_key and iwl3945_mac_set_key This patch fix iwl_mac_set_key function changed in patch "mac80211: clean up set_key callback" 1. removing 'static' const u8 *addr' that can possible cause conflict when two or more NICs are present in the system. 2. simplifying functions Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 14 +++++--------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 19 ++++++++----------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index be14cd942a5..7e0baf6deed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2998,12 +2998,10 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_key_conf *key) { struct iwl_priv *priv = hw->priv; - int ret = 0; - u8 sta_id = IWL_INVALID_STATION; - u8 is_default_wep_key = 0; - static const u8 bcast_addr[ETH_ALEN] = - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; - static const u8 *addr; + const u8 *addr; + int ret; + u8 sta_id; + bool is_default_wep_key = false; IWL_DEBUG_MAC80211("enter\n"); @@ -3011,9 +3009,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, IWL_DEBUG_MAC80211("leave - hwcrypto disabled\n"); return -EOPNOTSUPP; } - - addr = sta ? sta->addr : bcast_addr; - + addr = sta ? sta->addr : iwl_bcast_addr; sta_id = iwl_find_station(priv, addr); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_MAC80211("leave - %pM not in station map.\n", diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index b916f00b61b..010df19d01e 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -6500,10 +6500,8 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, { struct iwl_priv *priv = hw->priv; const u8 *addr; - int rc = 0; + int ret; u8 sta_id; - static const u8 bcast_addr[ETH_ALEN] = - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; IWL_DEBUG_MAC80211("enter\n"); @@ -6512,8 +6510,7 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } - addr = sta ? sta->addr : bcast_addr; - + addr = sta ? sta->addr : iwl_bcast_addr; sta_id = iwl3945_hw_find_station(priv, addr); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_MAC80211("leave - %pM not in station map.\n", @@ -6527,8 +6524,8 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, switch (cmd) { case SET_KEY: - rc = iwl3945_update_sta_key_info(priv, key, sta_id); - if (!rc) { + ret = iwl3945_update_sta_key_info(priv, key, sta_id); + if (!ret) { iwl3945_set_rxon_hwcrypto(priv, 1); iwl3945_commit_rxon(priv); key->hw_key_idx = sta_id; @@ -6537,21 +6534,21 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, } break; case DISABLE_KEY: - rc = iwl3945_clear_sta_key_info(priv, sta_id); - if (!rc) { + ret = iwl3945_clear_sta_key_info(priv, sta_id); + if (!ret) { iwl3945_set_rxon_hwcrypto(priv, 0); iwl3945_commit_rxon(priv); IWL_DEBUG_MAC80211("disable hwcrypto key\n"); } break; default: - rc = -EINVAL; + ret = -EINVAL; } IWL_DEBUG_MAC80211("leave\n"); mutex_unlock(&priv->mutex); - return rc; + return ret; } static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, -- GitLab From af0053d660f7c330ed1a5c6538938283fd79662f Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Mon, 19 Jan 2009 15:30:23 -0800 Subject: [PATCH 0889/4982] iwlwifi: kill iwl3945_scan_cancel and iwl3945_scan_cancel_timeout This patch removes iwl3945_scan_cancel and iwl3945_scan_cancel_timeout because iwl_scan_cancel iwl_scan_cancel_timeout are just same. Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 76 ++++----------------- 1 file changed, 12 insertions(+), 64 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 010df19d01e..d8cb94894d5 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1734,58 +1734,6 @@ static int iwl3945_send_power_mode(struct iwl_priv *priv, u32 mode) return rc; } -/** - * iwl3945_scan_cancel - Cancel any currently executing HW scan - * - * NOTE: priv->mutex is not required before calling this function - */ -static int iwl3945_scan_cancel(struct iwl_priv *priv) -{ - if (!test_bit(STATUS_SCAN_HW, &priv->status)) { - clear_bit(STATUS_SCANNING, &priv->status); - return 0; - } - - if (test_bit(STATUS_SCANNING, &priv->status)) { - if (!test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_SCAN("Queuing scan abort.\n"); - set_bit(STATUS_SCAN_ABORTING, &priv->status); - queue_work(priv->workqueue, &priv->abort_scan); - - } else - IWL_DEBUG_SCAN("Scan abort already in progress.\n"); - - return test_bit(STATUS_SCANNING, &priv->status); - } - - return 0; -} - -/** - * iwl3945_scan_cancel_timeout - Cancel any currently executing HW scan - * @ms: amount of time to wait (in milliseconds) for scan to abort - * - * NOTE: priv->mutex must be held before calling this function - */ -static int iwl3945_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) -{ - unsigned long now = jiffies; - int ret; - - ret = iwl3945_scan_cancel(priv); - if (ret && ms) { - mutex_unlock(&priv->mutex); - while (!time_after(jiffies, now + msecs_to_jiffies(ms)) && - test_bit(STATUS_SCANNING, &priv->status)) - msleep(1); - mutex_lock(&priv->mutex); - - return test_bit(STATUS_SCANNING, &priv->status); - } - - return ret; -} - #define MAX_UCODE_BEACON_INTERVAL 1024 #define INTEL_CONN_LISTEN_INTERVAL __constant_cpu_to_le16(0xA) @@ -2022,7 +1970,7 @@ static int iwl3945_set_mode(struct iwl_priv *priv, int mode) return -EAGAIN; cancel_delayed_work(&priv->scan_check); - if (iwl3945_scan_cancel_timeout(priv, 100)) { + if (iwl_scan_cancel_timeout(priv, 100)) { IWL_WARN(priv, "Aborted scan still in progress after 100ms\n"); IWL_DEBUG_MAC80211("leaving - scan abort failed.\n"); return -EAGAIN; @@ -2502,7 +2450,7 @@ static void iwl3945_radio_kill_sw(struct iwl_priv *priv, int disable_radio) disable_radio ? "OFF" : "ON"); if (disable_radio) { - iwl3945_scan_cancel(priv); + iwl_scan_cancel(priv); /* FIXME: This is a workaround for AP */ if (priv->iw_mode != NL80211_IFTYPE_AP) { spin_lock_irqsave(&priv->lock, flags); @@ -3014,7 +2962,7 @@ static void iwl3945_rx_card_state_notif(struct iwl_priv *priv, else clear_bit(STATUS_RF_KILL_SW, &priv->status); - iwl3945_scan_cancel(priv); + iwl_scan_cancel(priv); if ((test_bit(STATUS_RF_KILL_HW, &status) != test_bit(STATUS_RF_KILL_HW, &priv->status)) || @@ -5800,7 +5748,7 @@ static void iwl3945_post_associate(struct iwl_priv *priv) if (!priv->vif || !priv->is_open) return; - iwl3945_scan_cancel_timeout(priv, 200); + iwl_scan_cancel_timeout(priv, 200); conf = ieee80211_get_hw_conf(priv->hw); @@ -6001,7 +5949,7 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw) * RXON_FILTER_ASSOC_MSK BIT */ mutex_lock(&priv->mutex); - iwl3945_scan_cancel_timeout(priv, 100); + iwl_scan_cancel_timeout(priv, 100); mutex_unlock(&priv->mutex); } @@ -6279,7 +6227,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, !is_multicast_ether_addr(conf->bssid)) { /* If there is currently a HW scan going on in the background * then we need to cancel it else the RXON below will fail. */ - if (iwl3945_scan_cancel_timeout(priv, 100)) { + if (iwl_scan_cancel_timeout(priv, 100)) { IWL_WARN(priv, "Aborted scan still in progress " "after 100ms\n"); IWL_DEBUG_MAC80211("leaving - scan abort failed.\n"); @@ -6304,7 +6252,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, } } else { - iwl3945_scan_cancel_timeout(priv, 100); + iwl_scan_cancel_timeout(priv, 100); priv->staging39_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl3945_commit_rxon(priv); } @@ -6372,7 +6320,7 @@ static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); if (iwl_is_ready_rf(priv)) { - iwl3945_scan_cancel_timeout(priv, 100); + iwl_scan_cancel_timeout(priv, 100); priv->staging39_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl3945_commit_rxon(priv); } @@ -6520,7 +6468,7 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, mutex_lock(&priv->mutex); - iwl3945_scan_cancel_timeout(priv, 100); + iwl_scan_cancel_timeout(priv, 100); switch (cmd) { case SET_KEY: @@ -6670,7 +6618,7 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) * clear RXON_FILTER_ASSOC_MSK bit */ if (priv->iw_mode != NL80211_IFTYPE_AP) { - iwl3945_scan_cancel_timeout(priv, 100); + iwl_scan_cancel_timeout(priv, 100); priv->staging39_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl3945_commit_rxon(priv); } @@ -6829,7 +6777,7 @@ static ssize_t store_flags(struct device *d, mutex_lock(&priv->mutex); if (le32_to_cpu(priv->staging39_rxon.flags) != flags) { /* Cancel any currently running scans... */ - if (iwl3945_scan_cancel_timeout(priv, 100)) + if (iwl_scan_cancel_timeout(priv, 100)) IWL_WARN(priv, "Could not cancel scan.\n"); else { IWL_DEBUG_INFO("Committing rxon.flags = 0x%04X\n", @@ -6864,7 +6812,7 @@ static ssize_t store_filter_flags(struct device *d, mutex_lock(&priv->mutex); if (le32_to_cpu(priv->staging39_rxon.filter_flags) != filter_flags) { /* Cancel any currently running scans... */ - if (iwl3945_scan_cancel_timeout(priv, 100)) + if (iwl_scan_cancel_timeout(priv, 100)) IWL_WARN(priv, "Could not cancel scan.\n"); else { IWL_DEBUG_INFO("Committing rxon.filter_flags = " -- GitLab From 638d0eb9197d1e285451f6594184fcfc9c2a5d44 Mon Sep 17 00:00:00 2001 From: "Chatre, Reinette" Date: Mon, 19 Jan 2009 15:30:24 -0800 Subject: [PATCH 0890/4982] iwl3945: add debugging for wrong command queue We encountered a problem related to this BUG and need to obtain more debugging information. See bug report at http://marc.info/?l=linux-wireless&m=123147215829854&w=2 Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index d8cb94894d5..d1efdc7021b 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3066,7 +3066,14 @@ static void iwl3945_tx_cmd_complete(struct iwl_priv *priv, int cmd_index; struct iwl_cmd *cmd; - BUG_ON(txq_id != IWL_CMD_QUEUE_NUM); + if (WARN(txq_id != IWL_CMD_QUEUE_NUM, + "wrong command queue %d, sequence 0x%X readp=%d writep=%d\n", + txq_id, sequence, + priv->txq[IWL_CMD_QUEUE_NUM].q.read_ptr, + priv->txq[IWL_CMD_QUEUE_NUM].q.write_ptr)) { + iwl_print_hex_dump(priv, IWL_DL_INFO , rxb, 32); + return; + } cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; -- GitLab From 4f3602c8a3cf8d31e8b08b82d7ea9b0c30f28965 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 19 Jan 2009 15:30:25 -0800 Subject: [PATCH 0891/4982] iwl3945: Use iwl_txq_update_write_ptr The iwl3945 and the iwl versions are identical. Signed-off-by: Samuel Ortiz Acked-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 67 +++------------------ 1 file changed, 9 insertions(+), 58 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index d1efdc7021b..66b7e22d7e8 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -56,9 +56,6 @@ #include "iwl-core.h" #include "iwl-dev.h" -static int iwl3945_tx_queue_update_write_ptr(struct iwl_priv *priv, - struct iwl_tx_queue *txq); - /* * module name, copyright, version, etc. */ @@ -527,7 +524,7 @@ static int iwl3945_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) /* Increment and update queue's write index */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); - ret = iwl3945_tx_queue_update_write_ptr(priv, txq); + ret = iwl_txq_update_write_ptr(priv, txq); spin_unlock_irqrestore(&priv->hcmd_lock, flags); return ret ? ret : idx; @@ -2359,7 +2356,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* Tell device the write index *just past* this latest filled TFD */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); - rc = iwl3945_tx_queue_update_write_ptr(priv, txq); + rc = iwl_txq_update_write_ptr(priv, txq); spin_unlock_irqrestore(&priv->lock, flags); if (rc) @@ -2370,7 +2367,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (wait_write_ptr) { spin_lock_irqsave(&priv->lock, flags); txq->need_update = 1; - iwl3945_tx_queue_update_write_ptr(priv, txq); + iwl_txq_update_write_ptr(priv, txq); spin_unlock_irqrestore(&priv->lock, flags); } @@ -3491,52 +3488,6 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) iwl3945_rx_queue_restock(priv); } -/** - * iwl3945_tx_queue_update_write_ptr - Send new write index to hardware - */ -static int iwl3945_tx_queue_update_write_ptr(struct iwl_priv *priv, - struct iwl_tx_queue *txq) -{ - u32 reg = 0; - int rc = 0; - int txq_id = txq->q.id; - - if (txq->need_update == 0) - return rc; - - /* if we're trying to save power */ - if (test_bit(STATUS_POWER_PMI, &priv->status)) { - /* wake up nic if it's powered down ... - * uCode will wake up, and interrupt us again, so next - * time we'll skip this part. */ - reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); - - if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { - IWL_DEBUG_INFO("Requesting wakeup, GP1 = 0x%x\n", reg); - iwl_set_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - return rc; - } - - /* restore this queue's parameters in nic hardware. */ - rc = iwl_grab_nic_access(priv); - if (rc) - return rc; - iwl_write_direct32(priv, HBUS_TARG_WRPTR, - txq->q.write_ptr | (txq_id << 8)); - iwl_release_nic_access(priv); - - /* else not in power-save mode, uCode will never sleep when we're - * trying to tx (during RFKILL, we're not trying to tx). */ - } else - iwl_write32(priv, HBUS_TARG_WRPTR, - txq->q.write_ptr | (txq_id << 8)); - - txq->need_update = 0; - - return rc; -} - #ifdef CONFIG_IWL3945_DEBUG static void iwl3945_print_rx_config_cmd(struct iwl_priv *priv, struct iwl3945_rxon_cmd *rxon) @@ -3905,12 +3856,12 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) if (inta & CSR_INT_BIT_WAKEUP) { IWL_DEBUG_ISR("Wakeup interrupt\n"); iwl_rx_queue_update_write_ptr(priv, &priv->rxq); - iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[0]); - iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[1]); - iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[2]); - iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[3]); - iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[4]); - iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[5]); + iwl_txq_update_write_ptr(priv, &priv->txq[0]); + iwl_txq_update_write_ptr(priv, &priv->txq[1]); + iwl_txq_update_write_ptr(priv, &priv->txq[2]); + iwl_txq_update_write_ptr(priv, &priv->txq[3]); + iwl_txq_update_write_ptr(priv, &priv->txq[4]); + iwl_txq_update_write_ptr(priv, &priv->txq[5]); handled |= CSR_INT_BIT_WAKEUP; } -- GitLab From 7aaa1d79e3a2d573ac469744506f17b1c9386840 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 19 Jan 2009 15:30:26 -0800 Subject: [PATCH 0892/4982] iwlwifi: Add TFD library operations The TFD structures for 3945 and agn HWs are fundamentally different. We thus need to define operations for attaching and freeing them. This will allow us to share a fair amount of code (cmd and tx queue related) between both drivers. Signed-off-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 28 ++-- drivers/net/wireless/iwlwifi/iwl-3945.h | 9 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 + drivers/net/wireless/iwlwifi/iwl-5000.c | 2 + drivers/net/wireless/iwlwifi/iwl-agn.c | 120 ++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 10 ++ drivers/net/wireless/iwlwifi/iwl-tx.c | 134 ++------------------ drivers/net/wireless/iwlwifi/iwl3945-base.c | 34 ++--- 8 files changed, 176 insertions(+), 163 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index e6d4503cd21..18e0f0e3a74 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -318,7 +318,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv, tx_info = &txq->txb[txq->q.read_ptr]; ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0]); tx_info->skb[0] = NULL; - iwl3945_hw_txq_free_tfd(priv, txq); + priv->cfg->ops->lib->txq_free_tfd(priv, txq); } if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) && @@ -724,15 +724,21 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status); } -int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr, - dma_addr_t addr, u16 len) +int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, + struct iwl_tx_queue *txq, + dma_addr_t addr, u16 len, u8 reset, u8 pad) { int count; - u32 pad; - struct iwl3945_tfd *tfd = (struct iwl3945_tfd *)ptr; + struct iwl_queue *q; + struct iwl3945_tfd *tfd; + + q = &txq->q; + tfd = &txq->tfds39[q->write_ptr]; + + if (reset) + memset(tfd, 0, sizeof(*tfd)); count = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags)); - pad = TFD_CTL_PAD_GET(le32_to_cpu(tfd->control_flags)); if ((count >= NUM_TFD_CHUNKS) || (count < 0)) { IWL_ERR(priv, "Error can not send more than %d chunks\n", @@ -756,7 +762,7 @@ int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr, * * Does NOT advance any indexes */ -int iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) +void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) { struct iwl3945_tfd *tfd_tmp = (struct iwl3945_tfd *)&txq->tfds39[0]; struct iwl3945_tfd *tfd = &tfd_tmp[txq->q.read_ptr]; @@ -767,14 +773,14 @@ int iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) /* classify bd */ if (txq->q.id == IWL_CMD_QUEUE_NUM) /* nothing to cleanup after for host commands */ - return 0; + return; /* sanity check */ counter = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags)); if (counter > NUM_TFD_CHUNKS) { IWL_ERR(priv, "Too many chunks: %i\n", counter); /* @todo issue fatal error, it is quite serious situation */ - return 0; + return; } /* unmap chunks if any */ @@ -791,7 +797,7 @@ int iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) } } } - return 0; + return ; } u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *addr) @@ -2697,6 +2703,8 @@ static int iwl3945_load_bsm(struct iwl_priv *priv) } static struct iwl_lib_ops iwl3945_lib = { + .txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd, + .txq_free_tfd = iwl3945_hw_txq_free_tfd, .load_ucode = iwl3945_load_bsm, .apm_ops = { .init = iwl3945_apm_init, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 97dfa7c5a3c..54538df50d3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -260,9 +260,12 @@ extern int iwl3945_hw_nic_stop_master(struct iwl_priv *priv); extern void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv); extern void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv); extern int iwl3945_hw_nic_reset(struct iwl_priv *priv); -extern int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *tfd, - dma_addr_t addr, u16 len); -extern int iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); +extern int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, + struct iwl_tx_queue *txq, + dma_addr_t addr, u16 len, + u8 reset, u8 pad); +extern void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, + struct iwl_tx_queue *txq); extern int iwl3945_hw_get_temperature(struct iwl_priv *priv); extern int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 6171ba533f2..31315decc07 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2295,6 +2295,8 @@ static struct iwl_lib_ops iwl4965_lib = { .txq_set_sched = iwl4965_txq_set_sched, .txq_agg_enable = iwl4965_txq_agg_enable, .txq_agg_disable = iwl4965_txq_agg_disable, + .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, + .txq_free_tfd = iwl_hw_txq_free_tfd, .rx_handler_setup = iwl4965_rx_handler_setup, .setup_deferred_work = iwl4965_setup_deferred_work, .cancel_deferred_work = iwl4965_cancel_deferred_work, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 429dcbeff16..a35af671f85 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1492,6 +1492,8 @@ static struct iwl_lib_ops iwl5000_lib = { .txq_set_sched = iwl5000_txq_set_sched, .txq_agg_enable = iwl5000_txq_agg_enable, .txq_agg_disable = iwl5000_txq_agg_disable, + .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, + .txq_free_tfd = iwl_hw_txq_free_tfd, .rx_handler_setup = iwl5000_rx_handler_setup, .setup_deferred_work = iwl5000_setup_deferred_work, .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 7e0baf6deed..4a15e42ad00 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -471,6 +471,126 @@ static int iwl_send_beacon_cmd(struct iwl_priv *priv) return rc; } +static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) +{ + struct iwl_tfd_tb *tb = &tfd->tbs[idx]; + + dma_addr_t addr = get_unaligned_le32(&tb->lo); + if (sizeof(dma_addr_t) > sizeof(u32)) + addr |= + ((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16; + + return addr; +} + +static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx) +{ + struct iwl_tfd_tb *tb = &tfd->tbs[idx]; + + return le16_to_cpu(tb->hi_n_len) >> 4; +} + +static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx, + dma_addr_t addr, u16 len) +{ + struct iwl_tfd_tb *tb = &tfd->tbs[idx]; + u16 hi_n_len = len << 4; + + put_unaligned_le32(addr, &tb->lo); + if (sizeof(dma_addr_t) > sizeof(u32)) + hi_n_len |= ((addr >> 16) >> 16) & 0xF; + + tb->hi_n_len = cpu_to_le16(hi_n_len); + + tfd->num_tbs = idx + 1; +} + +static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd) +{ + return tfd->num_tbs & 0x1f; +} + +/** + * iwl_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] + * @priv - driver private data + * @txq - tx queue + * + * Does NOT advance any TFD circular buffer read/write indexes + * Does NOT free the TFD itself (which is within circular buffer) + */ +void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) +{ + struct iwl_tfd *tfd_tmp = (struct iwl_tfd *)&txq->tfds[0]; + struct iwl_tfd *tfd; + struct pci_dev *dev = priv->pci_dev; + int index = txq->q.read_ptr; + int i; + int num_tbs; + + tfd = &tfd_tmp[index]; + + /* Sanity check on number of chunks */ + num_tbs = iwl_tfd_get_num_tbs(tfd); + + if (num_tbs >= IWL_NUM_OF_TBS) { + IWL_ERR(priv, "Too many chunks: %i\n", num_tbs); + /* @todo issue fatal error, it is quite serious situation */ + return; + } + + /* Unmap tx_cmd */ + if (num_tbs) + pci_unmap_single(dev, + pci_unmap_addr(&txq->cmd[index]->meta, mapping), + pci_unmap_len(&txq->cmd[index]->meta, len), + PCI_DMA_TODEVICE); + + /* Unmap chunks, if any. */ + for (i = 1; i < num_tbs; i++) { + pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i), + iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE); + + if (txq->txb) { + dev_kfree_skb(txq->txb[txq->q.read_ptr].skb[i - 1]); + txq->txb[txq->q.read_ptr].skb[i - 1] = NULL; + } + } +} + +int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, + struct iwl_tx_queue *txq, + dma_addr_t addr, u16 len, + u8 reset, u8 pad) +{ + struct iwl_queue *q; + struct iwl_tfd *tfd; + u32 num_tbs; + + q = &txq->q; + tfd = &txq->tfds[q->write_ptr]; + + if (reset) + memset(tfd, 0, sizeof(*tfd)); + + num_tbs = iwl_tfd_get_num_tbs(tfd); + + /* Each TFD can point to a maximum 20 Tx buffers */ + if (num_tbs >= IWL_NUM_OF_TBS) { + IWL_ERR(priv, "Error can not send more than %d chunks\n", + IWL_NUM_OF_TBS); + return -EINVAL; + } + + BUG_ON(addr & ~DMA_BIT_MASK(36)); + if (unlikely(addr & ~IWL_TX_DMA_MASK)) + IWL_ERR(priv, "Unaligned address = %llx\n", + (unsigned long long)addr); + + iwl_tfd_set_tb(tfd, num_tbs, addr, len); + + return 0; +} + /****************************************************************************** * * Misc. internal state and helper functions diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 466130ff07a..9abdfb4acbf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -110,6 +110,12 @@ struct iwl_lib_ops { void (*txq_inval_byte_cnt_tbl)(struct iwl_priv *priv, struct iwl_tx_queue *txq); void (*txq_set_sched)(struct iwl_priv *priv, u32 mask); + int (*txq_attach_buf_to_tfd)(struct iwl_priv *priv, + struct iwl_tx_queue *txq, + dma_addr_t addr, + u16 len, u8 reset, u8 pad); + void (*txq_free_tfd)(struct iwl_priv *priv, + struct iwl_tx_queue *txq); /* aggregations */ int (*txq_agg_enable)(struct iwl_priv *priv, int txq_id, int tx_fifo, int sta_id, int tid, u16 ssn_idx); @@ -252,6 +258,10 @@ void iwl_rx_statistics(struct iwl_priv *priv, * TX ******************************************************/ int iwl_txq_ctx_reset(struct iwl_priv *priv); +void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); +int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, + struct iwl_tx_queue *txq, + dma_addr_t addr, u16 len, u8 reset, u8 pad); int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); void iwl_hw_txq_ctx_free(struct iwl_priv *priv); int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 913c77a2fea..487a1d65229 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -76,116 +76,6 @@ static inline void iwl_free_dma_ptr(struct iwl_priv *priv, memset(ptr, 0, sizeof(*ptr)); } -static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) -{ - struct iwl_tfd_tb *tb = &tfd->tbs[idx]; - - dma_addr_t addr = get_unaligned_le32(&tb->lo); - if (sizeof(dma_addr_t) > sizeof(u32)) - addr |= - ((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16; - - return addr; -} - -static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx) -{ - struct iwl_tfd_tb *tb = &tfd->tbs[idx]; - - return le16_to_cpu(tb->hi_n_len) >> 4; -} - -static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx, - dma_addr_t addr, u16 len) -{ - struct iwl_tfd_tb *tb = &tfd->tbs[idx]; - u16 hi_n_len = len << 4; - - put_unaligned_le32(addr, &tb->lo); - if (sizeof(dma_addr_t) > sizeof(u32)) - hi_n_len |= ((addr >> 16) >> 16) & 0xF; - - tb->hi_n_len = cpu_to_le16(hi_n_len); - - tfd->num_tbs = idx + 1; -} - -static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd) -{ - return tfd->num_tbs & 0x1f; -} - -/** - * iwl_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] - * @priv - driver private data - * @txq - tx queue - * - * Does NOT advance any TFD circular buffer read/write indexes - * Does NOT free the TFD itself (which is within circular buffer) - */ -static void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) -{ - struct iwl_tfd *tfd_tmp = (struct iwl_tfd *)&txq->tfds[0]; - struct iwl_tfd *tfd; - struct pci_dev *dev = priv->pci_dev; - int index = txq->q.read_ptr; - int i; - int num_tbs; - - tfd = &tfd_tmp[index]; - - /* Sanity check on number of chunks */ - num_tbs = iwl_tfd_get_num_tbs(tfd); - - if (num_tbs >= IWL_NUM_OF_TBS) { - IWL_ERR(priv, "Too many chunks: %i\n", num_tbs); - /* @todo issue fatal error, it is quite serious situation */ - return; - } - - /* Unmap tx_cmd */ - if (num_tbs) - pci_unmap_single(dev, - pci_unmap_addr(&txq->cmd[index]->meta, mapping), - pci_unmap_len(&txq->cmd[index]->meta, len), - PCI_DMA_TODEVICE); - - /* Unmap chunks, if any. */ - for (i = 1; i < num_tbs; i++) { - pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i), - iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE); - - if (txq->txb) { - dev_kfree_skb(txq->txb[txq->q.read_ptr].skb[i - 1]); - txq->txb[txq->q.read_ptr].skb[i - 1] = NULL; - } - } -} - -static int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, - struct iwl_tfd *tfd, - dma_addr_t addr, u16 len) -{ - - u32 num_tbs = iwl_tfd_get_num_tbs(tfd); - - /* Each TFD can point to a maximum 20 Tx buffers */ - if (num_tbs >= IWL_NUM_OF_TBS) { - IWL_ERR(priv, "Error can not send more than %d chunks\n", - IWL_NUM_OF_TBS); - return -EINVAL; - } - - BUG_ON(addr & ~DMA_BIT_MASK(36)); - if (unlikely(addr & ~IWL_TX_DMA_MASK)) - IWL_ERR(priv, "Unaligned address = %llx\n", - (unsigned long long)addr); - - iwl_tfd_set_tb(tfd, num_tbs, addr, len); - - return 0; -} - /** * iwl_txq_update_write_ptr - Send new write index to hardware */ @@ -254,7 +144,7 @@ static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) /* first, empty all BD's */ for (; q->write_ptr != q->read_ptr; q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) - iwl_hw_txq_free_tfd(priv, txq); + priv->cfg->ops->lib->txq_free_tfd(priv, txq); len = sizeof(struct iwl_cmd) * q->n_window; @@ -822,7 +712,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct iwl_tfd *tfd; struct iwl_tx_queue *txq; struct iwl_queue *q; struct iwl_cmd *out_cmd; @@ -913,10 +802,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) spin_lock_irqsave(&priv->lock, flags); - /* Set up first empty TFD within this queue's circular TFD buffer */ - tfd = &txq->tfds[q->write_ptr]; - memset(tfd, 0, sizeof(*tfd)); - /* Set up driver data for this TFD */ memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); txq->txb[q->write_ptr].skb[0] = skb; @@ -970,7 +855,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* Add buffer containing Tx command and MAC(!) header to TFD's * first entry */ txcmd_phys += offsetof(struct iwl_cmd, hdr); - iwl_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len); + priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, + txcmd_phys, len, 1, 0); if (info->control.hw_key) iwl_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id); @@ -981,7 +867,9 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (len) { phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, len, PCI_DMA_TODEVICE); - iwl_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, len); + priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, + phys_addr, len, + 0, 0); } /* Tell NIC about any 2-byte padding after MAC header */ @@ -1063,7 +951,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; struct iwl_queue *q = &txq->q; - struct iwl_tfd *tfd; struct iwl_cmd *out_cmd; dma_addr_t phys_addr; unsigned long flags; @@ -1092,10 +979,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) spin_lock_irqsave(&priv->hcmd_lock, flags); - tfd = &txq->tfds[q->write_ptr]; - memset(tfd, 0, sizeof(*tfd)); - - idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE); out_cmd = txq->cmd[idx]; @@ -1120,7 +1003,8 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) pci_unmap_len_set(&out_cmd->meta, len, len); phys_addr += offsetof(struct iwl_cmd, hdr); - iwl_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size); + priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, + phys_addr, fix_size, 1, 0); #ifdef CONFIG_IWLWIFI_DEBUG switch (out_cmd->hdr.cmd) { @@ -1180,7 +1064,7 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); - iwl_hw_txq_free_tfd(priv, txq); + priv->cfg->ops->lib->txq_free_tfd(priv, txq); nfreed++; } return nfreed; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 66b7e22d7e8..4474a4c3ddc 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -274,7 +274,7 @@ void iwl3945_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq) /* first, empty all BD's */ for (; q->write_ptr != q->read_ptr; q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) - iwl3945_hw_txq_free_tfd(priv, txq); + priv->cfg->ops->lib->txq_free_tfd(priv, txq); len = sizeof(struct iwl_cmd) * q->n_window; if (q->id == IWL_CMD_QUEUE_NUM) @@ -453,12 +453,10 @@ static int iwl3945_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; struct iwl_queue *q = &txq->q; - struct iwl3945_tfd *tfd; struct iwl_cmd *out_cmd; u32 idx; u16 fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); dma_addr_t phys_addr; - int pad; int ret, len; unsigned long flags; @@ -481,9 +479,6 @@ static int iwl3945_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) spin_lock_irqsave(&priv->hcmd_lock, flags); - tfd = &txq->tfds39[q->write_ptr]; - memset(tfd, 0, sizeof(*tfd)); - idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE); out_cmd = txq->cmd[idx]; @@ -509,10 +504,9 @@ static int iwl3945_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) pci_unmap_len_set(&out_cmd->meta, len, len); phys_addr += offsetof(struct iwl_cmd, hdr); - iwl3945_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size); - - pad = U32_PAD(cmd->len); - tfd->control_flags |= cpu_to_le32(TFD_CTL_PAD_SET(pad)); + priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, + phys_addr, fix_size, + 1, U32_PAD(cmd->len)); IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, " "%d bytes at %d[%d]:%d\n", @@ -2158,7 +2152,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct iwl3945_tfd *tfd; struct iwl3945_tx_cmd *tx; struct iwl_tx_queue *txq = NULL; struct iwl_queue *q = NULL; @@ -2243,9 +2236,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) spin_lock_irqsave(&priv->lock, flags); - /* Set up first empty TFD within this queue's circular TFD buffer */ - tfd = &txq->tfds39[q->write_ptr]; - memset(tfd, 0, sizeof(*tfd)); idx = get_cmd_index(q, q->write_ptr, 0); /* Set up driver data for this TFD */ @@ -2304,7 +2294,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* Add buffer containing Tx command and MAC(!) header to TFD's * first entry */ - iwl3945_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len); + priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, + txcmd_phys, len, 1, 0); if (info->control.hw_key) iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, 0); @@ -2315,18 +2306,11 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (len) { phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, len, PCI_DMA_TODEVICE); - iwl3945_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, len); + priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, + phys_addr, len, + 0, U32_PAD(len)); } - if (!len) - /* If there is no payload, then we use only one Tx buffer */ - tfd->control_flags = cpu_to_le32(TFD_CTL_COUNT_SET(1)); - else - /* Else use 2 buffers. - * Tell 3945 about any padding after MAC header */ - tfd->control_flags = cpu_to_le32(TFD_CTL_COUNT_SET(2) | - TFD_CTL_PAD_SET(U32_PAD(len))); - /* Total # bytes to be transmitted */ len = (u16)skb->len; tx->len = cpu_to_le16(len); -- GitLab From 518099a870ef3f5f97d96aa0c284ce1b403436fa Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 19 Jan 2009 15:30:27 -0800 Subject: [PATCH 0893/4982] iwl3945: Use iwl-hcmd host command routines With the previously added tfd related ops, we can now use the iwl-tx.c host command enqueue routine. Since the 3945 host command specific routines are identical to the agn ones, we can just remove them from the 3945 code. Signed-off-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-led.c | 4 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 9 +- drivers/net/wireless/iwlwifi/iwl-tx.c | 8 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 270 ++------------------ 4 files changed, 34 insertions(+), 257 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index e35dc54923f..fab13736500 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -40,6 +40,8 @@ #include "iwl-commands.h" #include "iwl-3945.h" +#include "iwl-core.h" +#include "iwl-dev.h" static const struct { @@ -91,7 +93,7 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, .meta.u.callback = iwl3945_led_cmd_callback, }; - return iwl3945_send_cmd(priv, &cmd); + return iwl_send_cmd(priv, &cmd); } diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 18e0f0e3a74..1f3305b36d0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1766,8 +1766,9 @@ int iwl3945_hw_reg_send_txpower(struct iwl_priv *priv) txpower.power[i].rate); } - return iwl3945_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD, - sizeof(struct iwl3945_txpowertable_cmd), &txpower); + return iwl_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD, + sizeof(struct iwl3945_txpowertable_cmd), + &txpower); } @@ -2463,14 +2464,14 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv) /* Update the rate scaling for control frame Tx */ rate_cmd.table_id = 0; - rc = iwl3945_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd), + rc = iwl_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd), &rate_cmd); if (rc) return rc; /* Update the rate scaling for data frame Tx */ rate_cmd.table_id = 1; - return iwl3945_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd), + return iwl_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd), &rate_cmd); } diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 487a1d65229..1a2cfbebb17 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -1004,7 +1004,8 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) phys_addr += offsetof(struct iwl_cmd, hdr); priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, - phys_addr, fix_size, 1, 0); + phys_addr, fix_size, 1, + U32_PAD(cmd->len)); #ifdef CONFIG_IWLWIFI_DEBUG switch (out_cmd->hdr.cmd) { @@ -1028,8 +1029,9 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) #endif txq->need_update = 1; - /* Set up entry in queue's byte count circular buffer */ - priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, 0); + if (priv->cfg->ops->lib->txq_update_byte_cnt_tbl) + /* Set up entry in queue's byte count circular buffer */ + priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, 0); /* Increment and update queue's write index */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 4474a4c3ddc..c8a1bdeaa43 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -434,246 +434,17 @@ u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flag } - -/*************** HOST COMMAND QUEUE FUNCTIONS *****/ - -#define IWL_CMD(x) case x: return #x -#define HOST_COMPLETE_TIMEOUT (HZ / 2) - -/** - * iwl3945_enqueue_hcmd - enqueue a uCode command - * @priv: device private data point - * @cmd: a point to the ucode command structure - * - * The function returns < 0 values to indicate the operation is - * failed. On success, it turns the index (> 0) of command in the - * command queue. - */ -static int iwl3945_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) -{ - struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; - struct iwl_queue *q = &txq->q; - struct iwl_cmd *out_cmd; - u32 idx; - u16 fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); - dma_addr_t phys_addr; - int ret, len; - unsigned long flags; - - /* If any of the command structures end up being larger than - * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then - * we will need to increase the size of the TFD entries */ - BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && - !(cmd->meta.flags & CMD_SIZE_HUGE)); - - - if (iwl_is_rfkill(priv)) { - IWL_DEBUG_INFO("Not sending command - RF KILL"); - return -EIO; - } - - if (iwl_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) { - IWL_ERR(priv, "No space for Tx\n"); - return -ENOSPC; - } - - spin_lock_irqsave(&priv->hcmd_lock, flags); - - idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE); - out_cmd = txq->cmd[idx]; - - out_cmd->hdr.cmd = cmd->id; - memcpy(&out_cmd->meta, &cmd->meta, sizeof(cmd->meta)); - memcpy(&out_cmd->cmd.payload, cmd->data, cmd->len); - - /* At this point, the out_cmd now has all of the incoming cmd - * information */ - - out_cmd->hdr.flags = 0; - out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(IWL_CMD_QUEUE_NUM) | - INDEX_TO_SEQ(q->write_ptr)); - if (out_cmd->meta.flags & CMD_SIZE_HUGE) - out_cmd->hdr.sequence |= SEQ_HUGE_FRAME; - - len = (idx == TFD_CMD_SLOTS) ? - IWL_MAX_SCAN_SIZE : sizeof(struct iwl_cmd); - - phys_addr = pci_map_single(priv->pci_dev, out_cmd, - len, PCI_DMA_TODEVICE); - pci_unmap_addr_set(&out_cmd->meta, mapping, phys_addr); - pci_unmap_len_set(&out_cmd->meta, len, len); - phys_addr += offsetof(struct iwl_cmd, hdr); - - priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, - phys_addr, fix_size, - 1, U32_PAD(cmd->len)); - - IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, " - "%d bytes at %d[%d]:%d\n", - get_cmd_string(out_cmd->hdr.cmd), - out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence), - fix_size, q->write_ptr, idx, IWL_CMD_QUEUE_NUM); - - txq->need_update = 1; - - /* Increment and update queue's write index */ - q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); - ret = iwl_txq_update_write_ptr(priv, txq); - - spin_unlock_irqrestore(&priv->hcmd_lock, flags); - return ret ? ret : idx; -} - -static int iwl3945_send_cmd_async(struct iwl_priv *priv, - struct iwl_host_cmd *cmd) -{ - int ret; - - BUG_ON(!(cmd->meta.flags & CMD_ASYNC)); - - /* An asynchronous command can not expect an SKB to be set. */ - BUG_ON(cmd->meta.flags & CMD_WANT_SKB); - - /* An asynchronous command MUST have a callback. */ - BUG_ON(!cmd->meta.u.callback); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return -EBUSY; - - ret = iwl3945_enqueue_hcmd(priv, cmd); - if (ret < 0) { - IWL_ERR(priv, - "Error sending %s: iwl3945_enqueue_hcmd failed: %d\n", - get_cmd_string(cmd->id), ret); - return ret; - } - return 0; -} - -static int iwl3945_send_cmd_sync(struct iwl_priv *priv, - struct iwl_host_cmd *cmd) -{ - int cmd_idx; - int ret; - - BUG_ON(cmd->meta.flags & CMD_ASYNC); - - /* A synchronous command can not have a callback set. */ - BUG_ON(cmd->meta.u.callback != NULL); - - if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) { - IWL_ERR(priv, - "Error sending %s: Already sending a host command\n", - get_cmd_string(cmd->id)); - ret = -EBUSY; - goto out; - } - - set_bit(STATUS_HCMD_ACTIVE, &priv->status); - - if (cmd->meta.flags & CMD_WANT_SKB) - cmd->meta.source = &cmd->meta; - - cmd_idx = iwl3945_enqueue_hcmd(priv, cmd); - if (cmd_idx < 0) { - ret = cmd_idx; - IWL_ERR(priv, - "Error sending %s: iwl3945_enqueue_hcmd failed: %d\n", - get_cmd_string(cmd->id), ret); - goto out; - } - - ret = wait_event_interruptible_timeout(priv->wait_command_queue, - !test_bit(STATUS_HCMD_ACTIVE, &priv->status), - HOST_COMPLETE_TIMEOUT); - if (!ret) { - if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) { - IWL_ERR(priv, "Error sending %s: time out after %dms\n", - get_cmd_string(cmd->id), - jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); - - clear_bit(STATUS_HCMD_ACTIVE, &priv->status); - ret = -ETIMEDOUT; - goto cancel; - } - } - - if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { - IWL_DEBUG_INFO("Command %s aborted: RF KILL Switch\n", - get_cmd_string(cmd->id)); - ret = -ECANCELED; - goto fail; - } - if (test_bit(STATUS_FW_ERROR, &priv->status)) { - IWL_DEBUG_INFO("Command %s failed: FW Error\n", - get_cmd_string(cmd->id)); - ret = -EIO; - goto fail; - } - if ((cmd->meta.flags & CMD_WANT_SKB) && !cmd->meta.u.skb) { - IWL_ERR(priv, "Error: Response NULL in '%s'\n", - get_cmd_string(cmd->id)); - ret = -EIO; - goto cancel; - } - - ret = 0; - goto out; - -cancel: - if (cmd->meta.flags & CMD_WANT_SKB) { - struct iwl_cmd *qcmd; - - /* Cancel the CMD_WANT_SKB flag for the cmd in the - * TX cmd queue. Otherwise in case the cmd comes - * in later, it will possibly set an invalid - * address (cmd->meta.source). */ - qcmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx]; - qcmd->meta.flags &= ~CMD_WANT_SKB; - } -fail: - if (cmd->meta.u.skb) { - dev_kfree_skb_any(cmd->meta.u.skb); - cmd->meta.u.skb = NULL; - } -out: - clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status); - return ret; -} - -int iwl3945_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) -{ - if (cmd->meta.flags & CMD_ASYNC) - return iwl3945_send_cmd_async(priv, cmd); - - return iwl3945_send_cmd_sync(priv, cmd); -} - -int iwl3945_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data) +int iwl3945_send_statistics_request(struct iwl_priv *priv) { - struct iwl_host_cmd cmd = { - .id = id, - .len = len, - .data = data, - }; - - return iwl3945_send_cmd_sync(priv, &cmd); -} + u32 val = 0; -static int __must_check iwl3945_send_cmd_u32(struct iwl_priv *priv, u8 id, u32 val) -{ struct iwl_host_cmd cmd = { - .id = id, + .id = REPLY_STATISTICS_CMD, .len = sizeof(val), .data = &val, }; - return iwl3945_send_cmd_sync(priv, &cmd); -} - -int iwl3945_send_statistics_request(struct iwl_priv *priv) -{ - return iwl3945_send_cmd_u32(priv, REPLY_STATISTICS_CMD, 0); + return iwl_send_cmd_sync(priv, &cmd); } /** @@ -864,7 +635,7 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) rxon_assoc.cck_basic_rates = priv->staging39_rxon.cck_basic_rates; rxon_assoc.reserved = 0; - rc = iwl3945_send_cmd_sync(priv, &cmd); + rc = iwl_send_cmd_sync(priv, &cmd); if (rc) return rc; @@ -936,7 +707,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) IWL_DEBUG_INFO("Toggling associated bit on current RXON\n"); active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON, + rc = iwl_send_cmd_pdu(priv, REPLY_RXON, sizeof(struct iwl3945_rxon_cmd), &priv->active39_rxon); @@ -960,7 +731,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) priv->staging_rxon.bssid_addr); /* Apply the new configuration */ - rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON, + rc = iwl_send_cmd_pdu(priv, REPLY_RXON, sizeof(struct iwl3945_rxon_cmd), &priv->staging39_rxon); if (rc) { IWL_ERR(priv, "Error setting new configuration (%d).\n", rc); @@ -1016,7 +787,7 @@ static int iwl3945_send_bt_config(struct iwl_priv *priv) .kill_cts_mask = 0, }; - return iwl3945_send_cmd_pdu(priv, REPLY_BT_CONFIG, + return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, sizeof(bt_cmd), &bt_cmd); } @@ -1037,7 +808,7 @@ static int iwl3945_send_scan_abort(struct iwl_priv *priv) return 0; } - rc = iwl3945_send_cmd_sync(priv, &cmd); + rc = iwl_send_cmd_sync(priv, &cmd); if (rc) { clear_bit(STATUS_SCAN_ABORTING, &priv->status); return rc; @@ -1106,7 +877,7 @@ int iwl3945_send_add_station(struct iwl_priv *priv, else cmd.meta.flags |= CMD_WANT_SKB; - rc = iwl3945_send_cmd(priv, &cmd); + rc = iwl_send_cmd(priv, &cmd); if (rc || (flags & CMD_ASYNC)) return rc; @@ -1300,7 +1071,7 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv) frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate); - rc = iwl3945_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size, + rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size, &frame->u.cmd[0]); iwl3945_free_frame(priv, frame); @@ -1513,7 +1284,7 @@ static int iwl3945_send_qos_params_command(struct iwl_priv *priv, struct iwl_qosparam_cmd *qos) { - return iwl3945_send_cmd_pdu(priv, REPLY_QOS_PARAM, + return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM, sizeof(struct iwl_qosparam_cmd), qos); } @@ -1714,8 +1485,8 @@ static int iwl3945_send_power_mode(struct iwl_priv *priv, u32 mode) iwl3945_update_power_cmd(priv, &cmd, final_mode); /* FIXME use get_hcmd_size 3945 command is 4 bytes shorter */ - rc = iwl3945_send_cmd_pdu(priv, POWER_TABLE_CMD, - sizeof(struct iwl3945_powertable_cmd), &cmd); + rc = iwl_send_cmd_pdu(priv, POWER_TABLE_CMD, + sizeof(struct iwl3945_powertable_cmd), &cmd); if (final_mode == IWL_POWER_MODE_CAM) clear_bit(STATUS_POWER_PMI, &priv->status); @@ -2601,7 +2372,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, spectrum.flags |= RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK; - rc = iwl3945_send_cmd_sync(priv, &cmd); + rc = iwl_send_cmd_sync(priv, &cmd); if (rc) return rc; @@ -3431,7 +3202,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) if (reclaim) { /* Invoke any callbacks, transfer the skb to caller, and - * fire off the (possibly) blocking iwl3945_send_cmd() + * fire off the (possibly) blocking iwl_send_cmd() * as we reclaim the driver command queue */ if (rxb && rxb->skb) iwl3945_tx_cmd_complete(priv, rxb); @@ -5607,7 +5378,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) scan->len = cpu_to_le16(cmd.len); set_bit(STATUS_SCAN_HW, &priv->status); - rc = iwl3945_send_cmd_sync(priv, &cmd); + rc = iwl_send_cmd_sync(priv, &cmd); if (rc) goto done; @@ -5699,7 +5470,7 @@ static void iwl3945_post_associate(struct iwl_priv *priv) memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); iwl3945_setup_rxon_timing(priv); - rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON_TIMING, + rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, sizeof(priv->rxon_timing), &priv->rxon_timing); if (rc) IWL_WARN(priv, "REPLY_RXON_TIMING failed - " @@ -6066,8 +5837,9 @@ static void iwl3945_config_ap(struct iwl_priv *priv) /* RXON Timing */ memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); iwl3945_setup_rxon_timing(priv); - rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON_TIMING, - sizeof(priv->rxon_timing), &priv->rxon_timing); + rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, + sizeof(priv->rxon_timing), + &priv->rxon_timing); if (rc) IWL_WARN(priv, "REPLY_RXON_TIMING failed - " "Attempting to continue.\n"); -- GitLab From 805cee5b81f1e493820601fe7990aef935c2c621 Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Mon, 19 Jan 2009 15:30:28 -0800 Subject: [PATCH 0894/4982] iwlwifi: kill scan39 scan and scan39 can be represented by void * in iwl_priv Signed-off-by: Tomas Winkler Acked-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-dev.h | 4 +--- drivers/net/wireless/iwlwifi/iwl3945-base.c | 10 +++++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 4d437cf50c8..5b5e011497c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -848,7 +848,7 @@ struct iwl_priv { unsigned long scan_start; unsigned long scan_pass_start; unsigned long scan_start_tsf; - struct iwl_scan_cmd *scan; + void *scan; int scan_bands; int one_direct_scan; u8 direct_ssid_len; @@ -1071,8 +1071,6 @@ struct iwl_priv { s8 user_txpower_limit; s8 max_channel_txpower_limit; - struct iwl3945_scan_cmd *scan39; - /* We declare this const so it can only be * changed via explicit cast within the * routines that actually update the physical diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index c8a1bdeaa43..9df3eef10c2 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -5270,15 +5270,15 @@ static void iwl3945_bg_request_scan(struct work_struct *data) goto done; } - if (!priv->scan39) { - priv->scan39 = kmalloc(sizeof(struct iwl3945_scan_cmd) + + if (!priv->scan) { + priv->scan = kmalloc(sizeof(struct iwl3945_scan_cmd) + IWL_MAX_SCAN_SIZE, GFP_KERNEL); - if (!priv->scan39) { + if (!priv->scan) { rc = -ENOMEM; goto done; } } - scan = priv->scan39; + scan = priv->scan; memset(scan, 0, sizeof(struct iwl3945_scan_cmd) + IWL_MAX_SCAN_SIZE); scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; @@ -7298,7 +7298,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) iwl3945_free_channel_map(priv); iwl3945_free_geos(priv); - kfree(priv->scan39); + kfree(priv->scan); if (priv->ibss_beacon) dev_kfree_skb(priv->ibss_beacon); -- GitLab From 62ea9c5b9e531dbf6b2601e6c9e2705a56983b6e Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Mon, 19 Jan 2009 15:30:29 -0800 Subject: [PATCH 0895/4982] iwlwifi: remove unused or twice defined members in iwl_priv This patch removes user_txpower_limit and max_channel_txpower_limit and use tx_power_user_lmt and tx_power_channel_lmt instead call_post_assoc_from_beacon is not used Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 5 ----- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 15 +++++++-------- 5 files changed, 12 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 1f3305b36d0..fe907f35336 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1675,7 +1675,7 @@ static void iwl3945_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_in /* further limit to user's max power preference. * FIXME: Other spectrum management power limitations do not * seem to apply?? */ - power = min(power, priv->user_txpower_limit); + power = min(power, priv->tx_power_user_lmt); scan_power_info->requested_power = power; /* find difference between new scan *power* and current "normal" @@ -1947,14 +1947,14 @@ int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power) u8 a_band; u8 i; - if (priv->user_txpower_limit == power) { + if (priv->tx_power_user_lmt == power) { IWL_DEBUG_POWER("Requested Tx power same as current " "limit: %ddBm.\n", power); return 0; } IWL_DEBUG_POWER("Setting upper limit clamp to %ddBm.\n", power); - priv->user_txpower_limit = power; + priv->tx_power_user_lmt = power; /* set up new Tx powers for each and every channel, 2.4 and 5.x */ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 31315decc07..b2985e25dc8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1306,7 +1306,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, s32 factory_actual_pwr[2]; s32 power_index; - /* user_txpower_limit is in dBm, convert to half-dBm (half-dB units + /* tx_power_user_lmt is in dBm, convert to half-dBm (half-dB units * are used for indexing into txpower table) */ user_target_power = 2 * priv->tx_power_user_lmt; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 5b5e011497c..75ef8d87c18 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1068,9 +1068,6 @@ struct iwl_priv { /*For 3945*/ #define IWL_DEFAULT_TX_POWER 0x0F - s8 user_txpower_limit; - s8 max_channel_txpower_limit; - /* We declare this const so it can only be * changed via explicit cast within the * routines that actually update the physical @@ -1088,8 +1085,6 @@ struct iwl_priv { struct iwl3945_eeprom eeprom39; u32 sta_supp_rates; - u8 call_post_assoc_from_beacon; - }; /*iwl_priv */ static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index c8afcd1ed2c..cebfb8fa5da 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -520,7 +520,7 @@ int iwl_init_channel_map(struct iwl_priv *priv) flags & EEPROM_CHANNEL_RADAR)) ? "" : "not "); - /* Set the user_txpower_limit to the highest power + /* Set the tx_power_user_lmt to the highest power * supported by any channel */ if (eeprom_ch_info[ch].max_power_avg > priv->tx_power_user_lmt) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 9df3eef10c2..0301df58148 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3949,11 +3949,11 @@ static int iwl3945_init_channel_map(struct iwl_priv *priv) flags & EEPROM_CHANNEL_RADAR)) ? "" : "not "); - /* Set the user_txpower_limit to the highest power + /* Set the tx_power_user_lmt to the highest power * supported by any channel */ if (eeprom_ch_info[ch].max_power_avg > - priv->user_txpower_limit) - priv->user_txpower_limit = + priv->tx_power_user_lmt) + priv->tx_power_user_lmt = eeprom_ch_info[ch].max_power_avg; ch_info++; @@ -4228,8 +4228,8 @@ static int iwl3945_init_geos(struct iwl_priv *priv) if (ch->flags & EEPROM_CHANNEL_RADAR) geo_ch->flags |= IEEE80211_CHAN_RADAR; - if (ch->max_power_avg > priv->max_channel_txpower_limit) - priv->max_channel_txpower_limit = + if (ch->max_power_avg > priv->tx_power_channel_lmt) + priv->tx_power_channel_lmt = ch->max_power_avg; } else { geo_ch->flags |= IEEE80211_CHAN_DISABLED; @@ -6307,7 +6307,6 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) spin_lock_irqsave(&priv->lock, flags); priv->assoc_id = 0; priv->assoc_capability = 0; - priv->call_post_assoc_from_beacon = 0; /* new association get rid of ibss beacon skb */ if (priv->ibss_beacon) @@ -6451,7 +6450,7 @@ static ssize_t show_tx_power(struct device *d, struct device_attribute *attr, char *buf) { struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; - return sprintf(buf, "%d\n", priv->user_txpower_limit); + return sprintf(buf, "%d\n", priv->tx_power_user_lmt); } static ssize_t store_tx_power(struct device *d, @@ -6974,7 +6973,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv) priv->rates_mask = IWL_RATES_MASK; /* If power management is turned on, default to AC mode */ priv->power_mode = IWL39_POWER_AC; - priv->user_txpower_limit = IWL_DEFAULT_TX_POWER; + priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER; ret = iwl3945_init_channel_map(priv); if (ret) { -- GitLab From 3dae0c42ba1d51ae49bf149d1dcc38ffbb357409 Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Mon, 19 Jan 2009 15:30:30 -0800 Subject: [PATCH 0896/4982] iwlwifi: eliminate power_data_39. This patch eliminates 3945 power_data structure and make use of of iwl_power_data. Signed-off-by: Tomas Winkler Acked-by: Mohamed Abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - drivers/net/wireless/iwlwifi/iwl-power.c | 8 -- drivers/net/wireless/iwlwifi/iwl-power.h | 16 ++-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 94 ++++++++------------- 4 files changed, 45 insertions(+), 74 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 75ef8d87c18..9dc6e3cc247 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1076,7 +1076,6 @@ struct iwl_priv { struct iwl3945_rxon_cmd staging39_rxon; struct iwl3945_rxon_cmd recovery39_rxon; - struct iwl3945_power_mgr power_data_39; struct iwl3945_notif_statistics statistics_39; struct iwl3945_station_entry stations_39[IWL_STATION_COUNT]; diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 0276d51d37c..a4634595c59 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -60,14 +60,6 @@ #define IWL_POWER_RANGE_1_MAX (10) -#define NOSLP __constant_cpu_to_le16(0), 0, 0 -#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0 -#define SLP_TOUT(T) __constant_cpu_to_le32((T) * MSEC_TO_USEC) -#define SLP_VEC(X0, X1, X2, X3, X4) {__constant_cpu_to_le32(X0), \ - __constant_cpu_to_le32(X1), \ - __constant_cpu_to_le32(X2), \ - __constant_cpu_to_le32(X3), \ - __constant_cpu_to_le32(X4)} #define IWL_POWER_ON_BATTERY IWL_POWER_INDEX_5 #define IWL_POWER_ON_AC_DISASSOC IWL_POWER_MODE_CAM diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h index 476c2aa2bf7..859b60b5335 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/iwl-power.h @@ -66,6 +66,14 @@ enum { /* Power management (not Tx power) structures */ +#define NOSLP __constant_cpu_to_le16(0), 0, 0 +#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0 +#define SLP_TOUT(T) __constant_cpu_to_le32((T) * MSEC_TO_USEC) +#define SLP_VEC(X0, X1, X2, X3, X4) {__constant_cpu_to_le32(X0), \ + __constant_cpu_to_le32(X1), \ + __constant_cpu_to_le32(X2), \ + __constant_cpu_to_le32(X3), \ + __constant_cpu_to_le32(X4)} struct iwl_power_vec_entry { struct iwl_powertable_cmd cmd; u8 no_dtim; @@ -86,14 +94,6 @@ struct iwl_power_mgr { u8 power_disabled; /* flag to disable using power saving level */ }; -struct iwl3945_power_mgr { - spinlock_t lock; - struct iwl_power_vec_entry pwr_range_0[IWL_POWER_AC]; - struct iwl_power_vec_entry pwr_range_1[IWL_POWER_AC]; - u8 active_index; - u32 dtim_val; -}; - void iwl_setup_power_deferred_work(struct iwl_priv *priv); void iwl_power_cancel_timeout(struct iwl_priv *priv); int iwl_power_update_mode(struct iwl_priv *priv, bool force); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 0301df58148..c9f6f8e8644 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1324,55 +1324,41 @@ static void iwl3945_activate_qos(struct iwl_priv *priv, u8 force) #define MSEC_TO_USEC 1024 -#define NOSLP __constant_cpu_to_le16(0), 0, 0 -#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0 -#define SLP_TIMEOUT(T) __constant_cpu_to_le32((T) * MSEC_TO_USEC) -#define SLP_VEC(X0, X1, X2, X3, X4) {__constant_cpu_to_le32(X0), \ - __constant_cpu_to_le32(X1), \ - __constant_cpu_to_le32(X2), \ - __constant_cpu_to_le32(X3), \ - __constant_cpu_to_le32(X4)} - /* default power management (not Tx power) table values */ /* for TIM 0-10 */ -static struct iwl_power_vec_entry range_0[IWL39_POWER_AC] = { - {{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, - {{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0}, - {{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(300), SLP_VEC(2, 4, 6, 7, 7)}, 0}, - {{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(100), SLP_VEC(2, 6, 9, 9, 10)}, 0}, - {{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(25), SLP_VEC(2, 7, 9, 9, 10)}, 1}, - {{SLP, SLP_TIMEOUT(25), SLP_TIMEOUT(25), SLP_VEC(4, 7, 10, 10, 10)}, 1} +static struct iwl_power_vec_entry range_0[IWL_POWER_MAX] = { + {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, + {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0}, + {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 7)}, 0}, + {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 6, 9, 9, 10)}, 0}, + {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 7, 9, 9, 10)}, 1}, + {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 10)}, 1} }; /* for TIM > 10 */ -static struct iwl_power_vec_entry range_1[IWL39_POWER_AC] = { - {{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, - {{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500), - SLP_VEC(1, 2, 3, 4, 0xFF)}, 0}, - {{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(300), - SLP_VEC(2, 4, 6, 7, 0xFF)}, 0}, - {{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(100), - SLP_VEC(2, 6, 9, 9, 0xFF)}, 0}, - {{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(25), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0}, - {{SLP, SLP_TIMEOUT(25), SLP_TIMEOUT(25), - SLP_VEC(4, 7, 10, 10, 0xFF)}, 0} +static struct iwl_power_vec_entry range_1[IWL_POWER_MAX] = { + {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, + {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0}, + {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0}, + {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 6, 9, 9, 0xFF)}, 0}, + {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0}, + {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0} }; int iwl3945_power_init_handle(struct iwl_priv *priv) { int rc = 0, i; - struct iwl3945_power_mgr *pow_data; - int size = sizeof(struct iwl_power_vec_entry) * IWL39_POWER_AC; + struct iwl_power_mgr *pow_data; + int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_MAX; u16 pci_pm; IWL_DEBUG_POWER("Initialize power \n"); - pow_data = &(priv->power_data_39); + pow_data = &priv->power_data; memset(pow_data, 0, sizeof(*pow_data)); - pow_data->active_index = IWL_POWER_RANGE_0; - pow_data->dtim_val = 0xffff; + pow_data->dtim_period = 1; memcpy(&pow_data->pwr_range_0[0], &range_0[0], size); memcpy(&pow_data->pwr_range_1[0], &range_1[0], size); @@ -1385,7 +1371,7 @@ int iwl3945_power_init_handle(struct iwl_priv *priv) IWL_DEBUG_POWER("adjust power command flags\n"); - for (i = 0; i < IWL39_POWER_AC; i++) { + for (i = 0; i < IWL_POWER_MAX; i++) { cmd = &pow_data->pwr_range_0[i].cmd; if (pci_pm & 0x1) @@ -1400,53 +1386,46 @@ int iwl3945_power_init_handle(struct iwl_priv *priv) static int iwl3945_update_power_cmd(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, u32 mode) { - int rc = 0, i; - u8 skip; - u32 max_sleep = 0; + struct iwl_power_mgr *pow_data; struct iwl_power_vec_entry *range; + u32 max_sleep = 0; + int i; u8 period = 0; - struct iwl3945_power_mgr *pow_data; + bool skip; if (mode > IWL_POWER_INDEX_5) { IWL_DEBUG_POWER("Error invalid power mode \n"); - return -1; + return -EINVAL; } - pow_data = &(priv->power_data_39); + pow_data = &priv->power_data; - if (pow_data->active_index == IWL_POWER_RANGE_0) + if (pow_data->dtim_period < 10) range = &pow_data->pwr_range_0[0]; else range = &pow_data->pwr_range_1[1]; memcpy(cmd, &range[mode].cmd, sizeof(struct iwl3945_powertable_cmd)); -#ifdef IWL_MAC80211_DISABLE - if (priv->assoc_network != NULL) { - unsigned long flags; - - period = priv->assoc_network->tim.tim_period; - } -#endif /*IWL_MAC80211_DISABLE */ - skip = range[mode].no_dtim; if (period == 0) { period = 1; - skip = 0; + skip = false; + } else { + skip = !!range[mode].no_dtim; } - if (skip == 0) { - max_sleep = period; - cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK; - } else { + if (skip) { __le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]; max_sleep = (le32_to_cpu(slp_itrvl) / period) * period; cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK; + } else { + max_sleep = period; + cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK; } - for (i = 0; i < IWL_POWER_VEC_SIZE; i++) { + for (i = 0; i < IWL_POWER_VEC_SIZE; i++) if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep) cmd->sleep_interval[i] = cpu_to_le32(max_sleep); - } IWL_DEBUG_POWER("Flags value = 0x%08X\n", cmd->flags); IWL_DEBUG_POWER("Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout)); @@ -1458,7 +1437,7 @@ static int iwl3945_update_power_cmd(struct iwl_priv *priv, le32_to_cpu(cmd->sleep_interval[3]), le32_to_cpu(cmd->sleep_interval[4])); - return rc; + return 0; } static int iwl3945_send_power_mode(struct iwl_priv *priv, u32 mode) @@ -6086,6 +6065,7 @@ static void iwl3945_bss_info_changed(struct ieee80211_hw *hw, priv->beacon_int = bss_conf->beacon_int; priv->timestamp = bss_conf->timestamp; priv->assoc_capability = bss_conf->assoc_capability; + priv->power_data.dtim_period = bss_conf->dtim_period; priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; mutex_lock(&priv->mutex); @@ -6947,7 +6927,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv) priv->ibss_beacon = NULL; spin_lock_init(&priv->lock); - spin_lock_init(&priv->power_data_39.lock); + spin_lock_init(&priv->power_data.lock); spin_lock_init(&priv->sta_lock); spin_lock_init(&priv->hcmd_lock); -- GitLab From f82d8d9724b6054b63fb3a0108937064029b2c00 Mon Sep 17 00:00:00 2001 From: Jay Sternberg Date: Mon, 19 Jan 2009 15:30:31 -0800 Subject: [PATCH 0897/4982] iwlwifi: correct Kconfig to prevent following entries from not indenting defining configurations that are not visible caused the following entries to not be indented. changing the tree structure to name the top level selection and have all others reference IWLWIFI directly corrects this issue. Signed-off-by: Jay Sternberg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Kconfig | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 47bee0ee0a7..022122603c1 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -1,21 +1,22 @@ config IWLWIFI - tristate + bool "Intel Wireless Wifi" + depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL + default y config IWLCORE tristate "Intel Wireless Wifi Core" - depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL + depends on IWLWIFI select LIB80211 - select IWLWIFI select MAC80211_LEDS if IWLWIFI_LEDS select LEDS_CLASS if IWLWIFI_LEDS select RFKILL if IWLWIFI_RFKILL config IWLWIFI_LEDS - bool - default n + bool "Enable LED support in iwlagn driver" + depends on IWLCORE config IWLWIFI_RFKILL - boolean "Iwlwifi RF kill support" + bool "Enable RF kill support in iwlagn driver" depends on IWLCORE config IWLWIFI_DEBUG @@ -51,7 +52,7 @@ config IWLWIFI_DEBUGFS config IWLAGN tristate "Intel Wireless WiFi Next Gen AGN" - depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL + depends on IWLWIFI select FW_LOADER select IWLCORE ---help--- @@ -104,10 +105,9 @@ config IWL5000 config IWL3945 tristate "Intel PRO/Wireless 3945ABG/BG Network Connection" - depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL + depends on IWLWIFI select FW_LOADER select LIB80211 - select IWLWIFI select MAC80211_LEDS if IWL3945_LEDS select LEDS_CLASS if IWL3945_LEDS select RFKILL if IWL3945_RFKILL -- GitLab From cec2d3f38c11f4c7e28ec2a065698653dbccfbb7 Mon Sep 17 00:00:00 2001 From: Jay Sternberg Date: Mon, 19 Jan 2009 15:30:33 -0800 Subject: [PATCH 0898/4982] iwlwifi: remove static from 5000 structures remove static from config structures which will be used by new hardware that is similar to 5000. This way the new devices can use them without the new structures having to be stored in the already overloaded iwl-5000.c file. Signed-off-by: Jay Sternberg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-5000.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-dev.h | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index a35af671f85..04c2585a634 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1528,13 +1528,13 @@ static struct iwl_lib_ops iwl5000_lib = { }, }; -static struct iwl_ops iwl5000_ops = { +struct iwl_ops iwl5000_ops = { .lib = &iwl5000_lib, .hcmd = &iwl5000_hcmd, .utils = &iwl5000_hcmd_utils, }; -static struct iwl_mod_params iwl50_mod_params = { +struct iwl_mod_params iwl50_mod_params = { .num_of_queues = IWL50_NUM_QUEUES, .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, .amsdu_size_8K = 1, diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 9dc6e3cc247..2602944a08a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -58,6 +58,10 @@ extern struct iwl_cfg iwl5100_bg_cfg; extern struct iwl_cfg iwl5100_abg_cfg; extern struct iwl_cfg iwl5150_agn_cfg; +/* shared structures from iwl-5000.c */ +extern struct iwl_mod_params iwl50_mod_params; +extern struct iwl_ops iwl5000_ops; + /* CT-KILL constants */ #define CT_KILL_THRESHOLD 110 /* in Celsius */ -- GitLab From e1228374d648efe451973bc5f3d1f9a8e943ec0b Mon Sep 17 00:00:00 2001 From: Jay Sternberg Date: Mon, 19 Jan 2009 15:30:34 -0800 Subject: [PATCH 0899/4982] iwlwifi: add recognition of Intel WiFi Link 6000 and 6050 Series add configuration for new Intel WiFi Link Series as part of the iwlagn driver under the umbrella of 5000 family of devices. Signed-off-by: Jay Sternberg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Makefile | 1 + drivers/net/wireless/iwlwifi/iwl-6000-hw.h | 81 +++++++++++++ drivers/net/wireless/iwlwifi/iwl-6000.c | 130 +++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.c | 12 ++ drivers/net/wireless/iwlwifi/iwl-dev.h | 5 + 5 files changed, 229 insertions(+) create mode 100644 drivers/net/wireless/iwlwifi/iwl-6000-hw.h create mode 100644 drivers/net/wireless/iwlwifi/iwl-6000.c diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 0be9e6b66aa..1347d0cf03f 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -12,6 +12,7 @@ iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-hcmd-check.o iwlagn-$(CONFIG_IWL4965) += iwl-4965.o iwlagn-$(CONFIG_IWL5000) += iwl-5000.o +iwlagn-$(CONFIG_IWL5000) += iwl-6000.o obj-$(CONFIG_IWL3945) += iwl3945.o iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o diff --git a/drivers/net/wireless/iwlwifi/iwl-6000-hw.h b/drivers/net/wireless/iwlwifi/iwl-6000-hw.h new file mode 100644 index 00000000000..90185777d98 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-6000-hw.h @@ -0,0 +1,81 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/* + * Please use this file (iwl-6000-hw.h) only for hardware-related definitions. + * Use iwl-5000-commands.h for uCode API definitions. + */ + +#ifndef __iwl_6000_hw_h__ +#define __iwl_6000_hw_h__ + +#define IWL60_RTC_INST_LOWER_BOUND (0x000000) +#define IWL60_RTC_INST_UPPER_BOUND (0x040000) +#define IWL60_RTC_DATA_LOWER_BOUND (0x800000) +#define IWL60_RTC_DATA_UPPER_BOUND (0x814000) +#define IWL60_RTC_INST_SIZE \ + (IWL60_RTC_INST_UPPER_BOUND - IWL60_RTC_INST_LOWER_BOUND) +#define IWL60_RTC_DATA_SIZE \ + (IWL60_RTC_DATA_UPPER_BOUND - IWL60_RTC_DATA_LOWER_BOUND) + +#endif /* __iwl_6000_hw_h__ */ + diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c new file mode 100644 index 00000000000..4515a6053dd --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -0,0 +1,130 @@ +/****************************************************************************** + * + * Copyright(c) 2008-2009 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iwl-eeprom.h" +#include "iwl-dev.h" +#include "iwl-core.h" +#include "iwl-io.h" +#include "iwl-sta.h" +#include "iwl-helpers.h" +#include "iwl-5000-hw.h" + +/* Highest firmware API version supported */ +#define IWL6000_UCODE_API_MAX 1 +#define IWL6050_UCODE_API_MAX 1 + +/* Lowest firmware API version supported */ +#define IWL6000_UCODE_API_MIN 1 +#define IWL6050_UCODE_API_MIN 1 + +#define IWL6000_FW_PRE "iwlwifi-6000-" +#define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" +#define IWL6000_MODULE_FIRMWARE(api) _IWL6000_MODULE_FIRMWARE(api) + +#define IWL6050_FW_PRE "iwlwifi-6050-" +#define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode" +#define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api) + +struct iwl_cfg iwl6000_2ag_cfg = { + .name = "6000 Series 2x2 AG", + .fw_name_pre = IWL6000_FW_PRE, + .ucode_api_max = IWL6000_UCODE_API_MAX, + .ucode_api_min = IWL6000_UCODE_API_MIN, + .sku = IWL_SKU_A|IWL_SKU_G, + .ops = &iwl5000_ops, + .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, + .eeprom_ver = EEPROM_5000_EEPROM_VERSION, + .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, + .mod_params = &iwl50_mod_params, +}; + +struct iwl_cfg iwl6000_2agn_cfg = { + .name = "6000 Series 2x2 AGN", + .fw_name_pre = IWL6000_FW_PRE, + .ucode_api_max = IWL6000_UCODE_API_MAX, + .ucode_api_min = IWL6000_UCODE_API_MIN, + .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, + .ops = &iwl5000_ops, + .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, + .eeprom_ver = EEPROM_5000_EEPROM_VERSION, + .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, + .mod_params = &iwl50_mod_params, +}; + +struct iwl_cfg iwl6050_2agn_cfg = { + .name = "6050 Series 2x2 AGN", + .fw_name_pre = IWL6050_FW_PRE, + .ucode_api_max = IWL6050_UCODE_API_MAX, + .ucode_api_min = IWL6050_UCODE_API_MIN, + .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, + .ops = &iwl5000_ops, + .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, + .eeprom_ver = EEPROM_5000_EEPROM_VERSION, + .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, + .mod_params = &iwl50_mod_params, +}; + +struct iwl_cfg iwl6000_3agn_cfg = { + .name = "6000 Series 3x3 AGN", + .fw_name_pre = IWL6000_FW_PRE, + .ucode_api_max = IWL6000_UCODE_API_MAX, + .ucode_api_min = IWL6000_UCODE_API_MIN, + .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, + .ops = &iwl5000_ops, + .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, + .eeprom_ver = EEPROM_5000_EEPROM_VERSION, + .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, + .mod_params = &iwl50_mod_params, +}; + +struct iwl_cfg iwl6050_3agn_cfg = { + .name = "6050 Series 3x3 AGN", + .fw_name_pre = IWL6050_FW_PRE, + .ucode_api_max = IWL6050_UCODE_API_MAX, + .ucode_api_min = IWL6050_UCODE_API_MIN, + .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, + .ops = &iwl5000_ops, + .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, + .eeprom_ver = EEPROM_5000_EEPROM_VERSION, + .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, + .mod_params = &iwl50_mod_params, +}; + +MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 4a15e42ad00..632add14fa9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -4173,6 +4173,18 @@ static struct pci_device_id iwl_hw_card_ids[] = { /* 5150 Wifi/WiMax */ {IWL_PCI_DEVICE(0x423C, PCI_ANY_ID, iwl5150_agn_cfg)}, {IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)}, +/* 6000/6050 Series */ + {IWL_PCI_DEVICE(0x0082, 0x1102, iwl6000_2ag_cfg)}, + {IWL_PCI_DEVICE(0x0085, 0x1112, iwl6000_2ag_cfg)}, + {IWL_PCI_DEVICE(0x0082, 0x1122, iwl6000_2ag_cfg)}, + {IWL_PCI_DEVICE(0x422B, PCI_ANY_ID, iwl6000_3agn_cfg)}, + {IWL_PCI_DEVICE(0x4238, PCI_ANY_ID, iwl6000_3agn_cfg)}, + {IWL_PCI_DEVICE(0x0082, PCI_ANY_ID, iwl6000_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0085, PCI_ANY_ID, iwl6000_3agn_cfg)}, + {IWL_PCI_DEVICE(0x0086, PCI_ANY_ID, iwl6050_3agn_cfg)}, + {IWL_PCI_DEVICE(0x0087, PCI_ANY_ID, iwl6050_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0088, PCI_ANY_ID, iwl6050_3agn_cfg)}, + {IWL_PCI_DEVICE(0x0089, PCI_ANY_ID, iwl6050_2agn_cfg)}, #endif /* CONFIG_IWL5000 */ {0} diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 2602944a08a..199e331da4d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -57,6 +57,11 @@ extern struct iwl_cfg iwl5350_agn_cfg; extern struct iwl_cfg iwl5100_bg_cfg; extern struct iwl_cfg iwl5100_abg_cfg; extern struct iwl_cfg iwl5150_agn_cfg; +extern struct iwl_cfg iwl6000_2ag_cfg; +extern struct iwl_cfg iwl6000_2agn_cfg; +extern struct iwl_cfg iwl6000_3agn_cfg; +extern struct iwl_cfg iwl6050_2agn_cfg; +extern struct iwl_cfg iwl6050_3agn_cfg; /* shared structures from iwl-5000.c */ extern struct iwl_mod_params iwl50_mod_params; -- GitLab From c5d0569882b9c264be31dcb0758961bfc479deea Mon Sep 17 00:00:00 2001 From: Jay Sternberg Date: Mon, 19 Jan 2009 15:30:35 -0800 Subject: [PATCH 0900/4982] iwlwifi: add recognition of Intel WiFi Link 100 Series add configuration for new Intel WiFi Link 100 series as part of the iwlagn driver under the umbrella of 5000 family of devices. Signed-off-by: Jay Sternberg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Makefile | 1 + drivers/net/wireless/iwlwifi/iwl-100.c | 70 ++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.c | 3 ++ drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + 4 files changed, 75 insertions(+) create mode 100644 drivers/net/wireless/iwlwifi/iwl-100.c diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 1347d0cf03f..fec2fbf8dc0 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -13,6 +13,7 @@ iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-hcmd-check.o iwlagn-$(CONFIG_IWL4965) += iwl-4965.o iwlagn-$(CONFIG_IWL5000) += iwl-5000.o iwlagn-$(CONFIG_IWL5000) += iwl-6000.o +iwlagn-$(CONFIG_IWL5000) += iwl-100.o obj-$(CONFIG_IWL3945) += iwl3945.o iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o diff --git a/drivers/net/wireless/iwlwifi/iwl-100.c b/drivers/net/wireless/iwlwifi/iwl-100.c new file mode 100644 index 00000000000..dbadaf44f57 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-100.c @@ -0,0 +1,70 @@ +/****************************************************************************** + * + * Copyright(c) 2008-2009 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iwl-eeprom.h" +#include "iwl-dev.h" +#include "iwl-core.h" +#include "iwl-io.h" +#include "iwl-sta.h" +#include "iwl-helpers.h" +#include "iwl-5000-hw.h" + +/* Highest firmware API version supported */ +#define IWL100_UCODE_API_MAX 1 + +/* Lowest firmware API version supported */ +#define IWL100_UCODE_API_MIN 1 + +#define IWL100_FW_PRE "iwlwifi-100-" +#define _IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE #api ".ucode" +#define IWL100_MODULE_FIRMWARE(api) _IWL100_MODULE_FIRMWARE(api) + +struct iwl_cfg iwl100_bgn_cfg = { + .name = "100 Series BGN", + .fw_name_pre = IWL100_FW_PRE, + .ucode_api_max = IWL100_UCODE_API_MAX, + .ucode_api_min = IWL100_UCODE_API_MIN, + .sku = IWL_SKU_G|IWL_SKU_N, + .ops = &iwl5000_ops, + .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, + .eeprom_ver = EEPROM_5000_EEPROM_VERSION, + .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, + .mod_params = &iwl50_mod_params, +}; + diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 632add14fa9..fc92c37735f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -4185,6 +4185,9 @@ static struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x0087, PCI_ANY_ID, iwl6050_2agn_cfg)}, {IWL_PCI_DEVICE(0x0088, PCI_ANY_ID, iwl6050_3agn_cfg)}, {IWL_PCI_DEVICE(0x0089, PCI_ANY_ID, iwl6050_2agn_cfg)}, +/* 100 Series WiFi */ + {IWL_PCI_DEVICE(0x0083, PCI_ANY_ID, iwl100_bgn_cfg)}, + {IWL_PCI_DEVICE(0x0084, PCI_ANY_ID, iwl100_bgn_cfg)}, #endif /* CONFIG_IWL5000 */ {0} diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 199e331da4d..79f2d45a9fc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -62,6 +62,7 @@ extern struct iwl_cfg iwl6000_2agn_cfg; extern struct iwl_cfg iwl6000_3agn_cfg; extern struct iwl_cfg iwl6050_2agn_cfg; extern struct iwl_cfg iwl6050_3agn_cfg; +extern struct iwl_cfg iwl100_bgn_cfg; /* shared structures from iwl-5000.c */ extern struct iwl_mod_params iwl50_mod_params; -- GitLab From 3cbb5dd73697b3f1c677daffe29f00ace22b71e9 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Tue, 20 Jan 2009 11:17:08 +0530 Subject: [PATCH 0901/4982] ath9k: Enable dynamic power save in ath9k. This patch implements dynamic power save feature for ath9k. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ath9k.h | 2 ++ drivers/net/wireless/ath9k/core.h | 18 ++++++++++++++ drivers/net/wireless/ath9k/hw.c | 4 +-- drivers/net/wireless/ath9k/hw.h | 1 - drivers/net/wireless/ath9k/main.c | 39 +++++++++++++++++++++++++++++- drivers/net/wireless/ath9k/recv.c | 6 +++++ 6 files changed, 66 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index 3817645b85d..0b305b832a8 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -793,6 +793,8 @@ struct ath_hal { u16 ah_currentRD5G; u16 ah_currentRD2G; char ah_iso[4]; + enum ath9k_power_mode ah_power_mode; + enum ath9k_power_mode ah_restore_mode; struct ath9k_channel ah_channels[150]; struct ath9k_channel *ah_curchan; diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index f65933d9c65..0f50767712a 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -676,6 +676,7 @@ enum PROT_MODE { #define SC_OP_RFKILL_REGISTERED BIT(11) #define SC_OP_RFKILL_SW_BLOCKED BIT(12) #define SC_OP_RFKILL_HW_BLOCKED BIT(13) +#define SC_OP_WAIT_FOR_BEACON BIT(14) struct ath_bus_ops { void (*read_cachesize)(struct ath_softc *sc, int *csz); @@ -709,6 +710,7 @@ struct ath_softc { u32 sc_keymax; DECLARE_BITMAP(sc_keymap, ATH_KEYMAX); u8 sc_splitmic; + atomic_t ps_usecount; enum ath9k_int sc_imask; enum PROT_MODE sc_protmode; enum ath9k_ht_extprotspacing sc_ht_extprotspacing; @@ -777,4 +779,20 @@ static inline int ath_ahb_init(void) { return 0; }; static inline void ath_ahb_exit(void) {}; #endif +static inline void ath9k_ps_wakeup(struct ath_softc *sc) +{ + if (atomic_inc_return(&sc->ps_usecount) == 1) + if (sc->sc_ah->ah_power_mode != ATH9K_PM_AWAKE) { + sc->sc_ah->ah_restore_mode = sc->sc_ah->ah_power_mode; + ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); + } +} + +static inline void ath9k_ps_restore(struct ath_softc *sc) +{ + if (atomic_dec_and_test(&sc->ps_usecount)) + if (sc->hw->conf.flags & IEEE80211_CONF_PS) + ath9k_hw_setpower(sc->sc_ah, + sc->sc_ah->ah_restore_mode); +} #endif /* CORE_H */ diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 88c8a62e1b8..ab15e55317c 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -2698,7 +2698,7 @@ bool ath9k_hw_setpower(struct ath_hal *ah, int status = true, setChip = true; DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, "%s -> %s (%s)\n", - modes[ahp->ah_powerMode], modes[mode], + modes[ah->ah_power_mode], modes[mode], setChip ? "set chip " : ""); switch (mode) { @@ -2717,7 +2717,7 @@ bool ath9k_hw_setpower(struct ath_hal *ah, "Unknown power mode %u\n", mode); return false; } - ahp->ah_powerMode = mode; + ah->ah_power_mode = mode; return status; } diff --git a/drivers/net/wireless/ath9k/hw.h b/drivers/net/wireless/ath9k/hw.h index d44e016f988..087c5718707 100644 --- a/drivers/net/wireless/ath9k/hw.h +++ b/drivers/net/wireless/ath9k/hw.h @@ -844,7 +844,6 @@ struct ath_hal_5416 { bool ah_chipFullSleep; u32 ah_atimWindow; u16 ah_antennaSwitchSwap; - enum ath9k_power_mode ah_powerMode; enum ath9k_ant_setting ah_diversityControl; /* Calibration */ diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 8ad927a8870..b494a0d7e8b 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -237,6 +237,8 @@ static int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan) if (sc->sc_flags & SC_OP_INVALID) return -EIO; + ath9k_ps_wakeup(sc); + /* * This is only performed if the channel settings have * actually changed. @@ -287,6 +289,7 @@ static int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan) ath_cache_conf_rate(sc, &hw->conf); ath_update_txpow(sc); ath9k_hw_set_interrupts(ah, sc->sc_imask); + ath9k_ps_restore(sc); return 0; } @@ -559,8 +562,10 @@ irqreturn_t ath_isr(int irq, void *dev) ATH9K_HW_CAP_AUTOSLEEP)) { /* Clear RxAbort bit so that we can * receive frames */ + ath9k_hw_setpower(ah, ATH9K_PM_AWAKE); ath9k_hw_setrxabort(ah, 0); sched = true; + sc->sc_flags |= SC_OP_WAIT_FOR_BEACON; } } } @@ -1044,6 +1049,7 @@ static void ath_radio_enable(struct ath_softc *sc) struct ieee80211_channel *channel = sc->hw->conf.channel; int r; + ath9k_ps_wakeup(sc); spin_lock_bh(&sc->sc_resetlock); r = ath9k_hw_reset(ah, ah->ah_curchan, false); @@ -1075,6 +1081,7 @@ static void ath_radio_enable(struct ath_softc *sc) ath9k_hw_set_gpio(ah, ATH_LED_PIN, 0); ieee80211_wake_queues(sc->hw); + ath9k_ps_restore(sc); } static void ath_radio_disable(struct ath_softc *sc) @@ -1083,6 +1090,7 @@ static void ath_radio_disable(struct ath_softc *sc) struct ieee80211_channel *channel = sc->hw->conf.channel; int r; + ath9k_ps_wakeup(sc); ieee80211_stop_queues(sc->hw); /* Disable LED */ @@ -1108,6 +1116,7 @@ static void ath_radio_disable(struct ath_softc *sc) ath9k_hw_phy_disable(ah); ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); + ath9k_ps_restore(sc); } static bool ath_is_rfkill_set(struct ath_softc *sc) @@ -1259,6 +1268,8 @@ void ath_detach(struct ath_softc *sc) struct ieee80211_hw *hw = sc->hw; int i = 0; + ath9k_ps_wakeup(sc); + DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n"); #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) @@ -1283,6 +1294,7 @@ void ath_detach(struct ath_softc *sc) ath9k_hw_detach(sc->sc_ah); ath9k_exit_debug(sc); + ath9k_ps_restore(sc); } static int ath_init(u16 devid, struct ath_softc *sc) @@ -1526,7 +1538,9 @@ int ath_attach(u16 devid, struct ath_softc *sc) hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_AMPDU_AGGREGATION; + IEEE80211_HW_AMPDU_AGGREGATION | + IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_PS_NULLFUNC_STACK; if (AR_SREV_9160_10_OR_LATER(sc->sc_ah)) hw->flags |= IEEE80211_HW_MFP_CAPABLE; @@ -2090,6 +2104,27 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) struct ieee80211_conf *conf = &hw->conf; mutex_lock(&sc->mutex); + if (changed & IEEE80211_CONF_CHANGE_PS) { + if (conf->flags & IEEE80211_CONF_PS) { + if ((sc->sc_imask & ATH9K_INT_TIM_TIMER) == 0) { + sc->sc_imask |= ATH9K_INT_TIM_TIMER; + ath9k_hw_set_interrupts(sc->sc_ah, + sc->sc_imask); + } + ath9k_hw_setrxabort(sc->sc_ah, 1); + ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); + } else { + ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); + ath9k_hw_setrxabort(sc->sc_ah, 0); + sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON; + if (sc->sc_imask & ATH9K_INT_TIM_TIMER) { + sc->sc_imask &= ~ATH9K_INT_TIM_TIMER; + ath9k_hw_set_interrupts(sc->sc_ah, + sc->sc_imask); + } + } + } + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { struct ieee80211_channel *curchan = hw->conf.channel; int pos; @@ -2310,6 +2345,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, struct ath_softc *sc = hw->priv; int ret = 0; + ath9k_ps_wakeup(sc); DPRINTF(sc, ATH_DBG_KEYCACHE, "Set HW Key\n"); switch (cmd) { @@ -2333,6 +2369,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, ret = -EINVAL; } + ath9k_ps_restore(sc); return ret; } diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c index 648bb49e673..8da08f9b463 100644 --- a/drivers/net/wireless/ath9k/recv.c +++ b/drivers/net/wireless/ath9k/recv.c @@ -628,6 +628,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) } else { sc->rx.rxotherant = 0; } + + if (ieee80211_is_beacon(hdr->frame_control) && + (sc->sc_flags & SC_OP_WAIT_FOR_BEACON)) { + sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON; + ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); + } requeue: list_move_tail(&bf->list, &sc->rx.rxbuf); ath_rx_buf_link(sc, bf); -- GitLab From c6ec7a9b17875e3a5a9cdd23f7914d74069316c8 Mon Sep 17 00:00:00 2001 From: "Abbas, Mohamed" Date: Tue, 20 Jan 2009 21:33:52 -0800 Subject: [PATCH 0902/4982] iwlwifi: allow user to set max rate allow user to set max rate through #iwconfig rate XXX. mac80211 will try to force this if user set it, but driver is not in sync which cause mac80211 to report wrong current rate. This patch will check if max rate is set and force it in rate scaling Signed-off-by: mohamed abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 18 +++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 27 ++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 25b4356fcc1..044abf734eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -651,6 +651,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; u16 fc; u16 rate_mask = 0; + s8 max_rate_idx = -1; struct iwl_priv *priv = (struct iwl_priv *)priv_r; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); @@ -675,6 +676,13 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, return; } + /* get user max rate if set */ + max_rate_idx = txrc->max_rate_idx; + if ((sband->band == IEEE80211_BAND_5GHZ) && (max_rate_idx != -1)) + max_rate_idx += IWL_FIRST_OFDM_RATE; + if ((max_rate_idx < 0) || (max_rate_idx >= IWL_RATE_COUNT)) + max_rate_idx = -1; + index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT_3945 - 1); if (sband->band == IEEE80211_BAND_5GHZ) @@ -706,6 +714,12 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, rs_sta->start_rate = IWL_RATE_INVALID; } + /* force user max rate if set by user */ + if ((max_rate_idx != -1) && (max_rate_idx < index)) { + if (rate_mask & (1 << max_rate_idx)) + index = max_rate_idx; + } + window = &(rs_sta->win[index]); fail_count = window->counter - window->success_counter; @@ -732,6 +746,10 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, low = high_low & 0xff; high = (high_low >> 8) & 0xff; + /* If user set max rate, dont allow higher than user constrain */ + if ((max_rate_idx != -1) && (max_rate_idx < high)) + high = IWL_RATE_INVALID; + if (low != IWL_RATE_INVALID) low_tpt = rs_sta->win[low].average_tpt; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index a82cce5fbff..12c5e5d6e91 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -148,6 +148,7 @@ struct iwl_lq_sta { u16 active_mimo2_rate; u16 active_mimo3_rate; u16 active_rate_basic; + s8 max_rate_idx; /* Max rate set by user */ struct iwl_link_quality_cmd lq; struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ @@ -1759,6 +1760,15 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, return; } + /* force user max rate if set by user */ + if ((lq_sta->max_rate_idx != -1) && + (lq_sta->max_rate_idx < index)) { + index = lq_sta->max_rate_idx; + update_lq = 1; + window = &(tbl->win[index]); + goto lq_update; + } + window = &(tbl->win[index]); /* @@ -1850,6 +1860,11 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, low = high_low & 0xff; high = (high_low >> 8) & 0xff; + /* If user set max rate, dont allow higher than user constrain */ + if ((lq_sta->max_rate_idx != -1) && + (lq_sta->max_rate_idx < high)) + high = IWL_RATE_INVALID; + sr = window->success_ratio; /* Collect measured throughputs for current and adjacent rates */ @@ -2110,6 +2125,17 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n"); + /* Get max rate if user set max rate */ + if (lq_sta) { + lq_sta->max_rate_idx = txrc->max_rate_idx; + if ((sband->band == IEEE80211_BAND_5GHZ) && + (lq_sta->max_rate_idx != -1)) + lq_sta->max_rate_idx += IWL_FIRST_OFDM_RATE; + if ((lq_sta->max_rate_idx < 0) || + (lq_sta->max_rate_idx >= IWL_RATE_COUNT)) + lq_sta->max_rate_idx = -1; + } + if (sta) mask_bit = sta->supp_rates[sband->band]; @@ -2220,6 +2246,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, } lq_sta->is_dup = 0; + lq_sta->max_rate_idx = -1; lq_sta->is_green = rs_use_green(priv, conf); lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000); lq_sta->active_rate_basic = priv->active_rate_basic; -- GitLab From 7d049e5abe77c82d6f11a4e5869203f7b2838380 Mon Sep 17 00:00:00 2001 From: "Abbas, Mohamed" Date: Tue, 20 Jan 2009 21:33:53 -0800 Subject: [PATCH 0903/4982] iwlagn: fix agn rate scaling Sometime Tx reply rate different than what rate scale expecting causing rate scale to bail out. This could cause failing to commit LQ cmd. This patch will try to solve this instead of just bail out. It also make sure we start with a valid rate. Signed-off-by: mohamed abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 31 +++++++++++++++++------ 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 12c5e5d6e91..13039a02447 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -49,6 +49,8 @@ #define IWL_RATE_MIN_FAILURE_TH 6 /* min failures to calc tpt */ #define IWL_RATE_MIN_SUCCESS_TH 8 /* min successes to calc tpt */ +/* max allowed rate miss before sync LQ cmd */ +#define IWL_MISSED_RATE_MAX 15 /* max time to accum history 2 seconds */ #define IWL_RATE_SCALE_FLUSH_INTVL (2*HZ) @@ -149,6 +151,7 @@ struct iwl_lq_sta { u16 active_mimo3_rate; u16 active_rate_basic; s8 max_rate_idx; /* Max rate set by user */ + u8 missed_rate_counter; struct iwl_link_quality_cmd lq; struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ @@ -841,10 +844,15 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, /* the last LQ command could failed so the LQ in ucode not * the same in driver sync up */ - iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); + lq_sta->missed_rate_counter++; + if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { + lq_sta->missed_rate_counter = 0; + iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); + } goto out; } + lq_sta->missed_rate_counter = 0; /* Update frame history window with "failure" for each Tx retry. */ while (retries) { /* Look up the rate and other info used for each tx attempt. @@ -2212,6 +2220,8 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, struct ieee80211_conf *conf = &priv->hw->conf; struct iwl_lq_sta *lq_sta = priv_sta; u16 mask_bit = 0; + int count; + int start_rate = 0; lq_sta->flush_timer = 0; lq_sta->supp_rates = sta->supp_rates[sband->band]; @@ -2247,6 +2257,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, lq_sta->is_dup = 0; lq_sta->max_rate_idx = -1; + lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; lq_sta->is_green = rs_use_green(priv, conf); lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000); lq_sta->active_rate_basic = priv->active_rate_basic; @@ -2285,16 +2296,20 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, lq_sta->drv = priv; /* Find highest tx rate supported by hardware and destination station */ - mask_bit = sta->supp_rates[sband->band] & lq_sta->active_legacy_rate; - lq_sta->last_txrate_idx = 3; - for (i = 0; i < sband->n_bitrates; i++) + mask_bit = sta->supp_rates[sband->band]; + count = sband->n_bitrates; + if (sband->band == IEEE80211_BAND_5GHZ) { + count += IWL_FIRST_OFDM_RATE; + start_rate = IWL_FIRST_OFDM_RATE; + mask_bit <<= IWL_FIRST_OFDM_RATE; + } + + mask_bit = mask_bit & lq_sta->active_legacy_rate; + lq_sta->last_txrate_idx = 4; + for (i = start_rate; i < count; i++) if (mask_bit & BIT(i)) lq_sta->last_txrate_idx = i; - /* For MODE_IEEE80211A, skip over cck rates in global rate table */ - if (sband->band == IEEE80211_BAND_5GHZ) - lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; - rs_initialize_lq(priv, conf, sta, lq_sta); } -- GitLab From c0af96a6e63ef93c605ce495fff79c692d4b8c4d Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Wed, 21 Jan 2009 18:27:54 +0100 Subject: [PATCH 0904/4982] iwl3945: Use iwl-rfkill Here again, the rfkill routines are duplicated between agn and 3945. Let's move the agn one to iwlcore, and so we can get rid of the 3945 ones. Signed-off-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Kconfig | 6 +- drivers/net/wireless/iwlwifi/iwl-3945.h | 12 -- drivers/net/wireless/iwlwifi/iwl-agn.c | 35 ----- drivers/net/wireless/iwlwifi/iwl-core.c | 36 +++++ drivers/net/wireless/iwlwifi/iwl-core.h | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 151 +------------------- 6 files changed, 43 insertions(+), 199 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 022122603c1..f38130abab0 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -110,7 +110,7 @@ config IWL3945 select LIB80211 select MAC80211_LEDS if IWL3945_LEDS select LEDS_CLASS if IWL3945_LEDS - select RFKILL if IWL3945_RFKILL + select RFKILL if IWLWIFI_RFKILL ---help--- Select to build the driver supporting the: @@ -133,10 +133,6 @@ config IWL3945 say M here and read . The module will be called iwl3945.ko. -config IWL3945_RFKILL - bool "Enable RF kill support in iwl3945 drivers" - depends on IWL3945 - config IWL3945_SPECTRUM_MEASUREMENT bool "Enable Spectrum Measurement in iwl3945 drivers" depends on IWL3945 diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 54538df50d3..77e97eaa4e4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -304,18 +304,6 @@ extern int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv); extern u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags); -#ifdef CONFIG_IWL3945_RFKILL -struct iwl_priv; - -void iwl3945_rfkill_set_hw_state(struct iwl_priv *priv); -void iwl3945_rfkill_unregister(struct iwl_priv *priv); -int iwl3945_rfkill_init(struct iwl_priv *priv); -#else -static inline void iwl3945_rfkill_set_hw_state(struct iwl_priv *priv) {} -static inline void iwl3945_rfkill_unregister(struct iwl_priv *priv) {} -static inline int iwl3945_rfkill_init(struct iwl_priv *priv) { return 0; } -#endif - static inline int iwl3945_is_associated(struct iwl_priv *priv) { return (priv->active39_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index fc92c37735f..c72a99a9ab3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2266,41 +2266,6 @@ static void iwl_bg_alive_start(struct work_struct *data) mutex_unlock(&priv->mutex); } -static void iwl_bg_rf_kill(struct work_struct *work) -{ - struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill); - - wake_up_interruptible(&priv->wait_command_queue); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - mutex_lock(&priv->mutex); - - if (!iwl_is_rfkill(priv)) { - IWL_DEBUG(IWL_DL_RF_KILL, - "HW and/or SW RF Kill no longer active, restarting " - "device\n"); - if (!test_bit(STATUS_EXIT_PENDING, &priv->status) && - test_bit(STATUS_ALIVE, &priv->status)) - queue_work(priv->workqueue, &priv->restart); - } else { - /* make sure mac80211 stop sending Tx frame */ - if (priv->mac80211_registered) - ieee80211_stop_queues(priv->hw); - - if (!test_bit(STATUS_RF_KILL_HW, &priv->status)) - IWL_DEBUG_RF_KILL("Can not turn radio back on - " - "disabled by SW switch\n"); - else - IWL_WARN(priv, "Radio Frequency Kill Switch is On:\n" - "Kill switch must be turned off for " - "wireless networking to work.\n"); - } - mutex_unlock(&priv->mutex); - iwl_rfkill_set_hw_state(priv); -} - static void iwl_bg_run_time_calib_work(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index d2ef3e142bc..f24d3b40e8e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1465,3 +1465,39 @@ int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv) return 1; } EXPORT_SYMBOL(iwl_radio_kill_sw_enable_radio); + +void iwl_bg_rf_kill(struct work_struct *work) +{ + struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill); + + wake_up_interruptible(&priv->wait_command_queue); + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + mutex_lock(&priv->mutex); + + if (!iwl_is_rfkill(priv)) { + IWL_DEBUG(IWL_DL_RF_KILL, + "HW and/or SW RF Kill no longer active, restarting " + "device\n"); + if (!test_bit(STATUS_EXIT_PENDING, &priv->status) && + test_bit(STATUS_ALIVE, &priv->status)) + queue_work(priv->workqueue, &priv->restart); + } else { + /* make sure mac80211 stop sending Tx frame */ + if (priv->mac80211_registered) + ieee80211_stop_queues(priv->hw); + + if (!test_bit(STATUS_RF_KILL_HW, &priv->status)) + IWL_DEBUG_RF_KILL("Can not turn radio back on - " + "disabled by SW switch\n"); + else + IWL_WARN(priv, "Radio Frequency Kill Switch is On:\n" + "Kill switch must be turned off for " + "wireless networking to work.\n"); + } + mutex_unlock(&priv->mutex); + iwl_rfkill_set_hw_state(priv); +} +EXPORT_SYMBOL(iwl_bg_rf_kill); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 9abdfb4acbf..2f23f78296e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -277,7 +277,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force); * RF -Kill - here and not in iwl-rfkill.h to be available when * RF-kill subsystem is not compiled. ****************************************************/ -void iwl_rf_kill(struct iwl_priv *priv); +void iwl_bg_rf_kill(struct work_struct *work); void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv); int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index c9f6f8e8644..78271936801 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -5110,39 +5110,6 @@ static void iwl3945_bg_alive_start(struct work_struct *data) mutex_unlock(&priv->mutex); } -static void iwl3945_bg_rf_kill(struct work_struct *work) -{ - struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill); - - wake_up_interruptible(&priv->wait_command_queue); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - mutex_lock(&priv->mutex); - - if (!iwl_is_rfkill(priv)) { - IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL, - "HW and/or SW RF Kill no longer active, restarting " - "device\n"); - if (!test_bit(STATUS_EXIT_PENDING, &priv->status) && - test_bit(STATUS_ALIVE, &priv->status)) - queue_work(priv->workqueue, &priv->restart); - } else { - - if (!test_bit(STATUS_RF_KILL_HW, &priv->status)) - IWL_DEBUG_RF_KILL("Can not turn radio back on - " - "disabled by SW switch\n"); - else - IWL_WARN(priv, "Radio Frequency Kill Switch is On:\n" - "Kill switch must be turned off for " - "wireless networking to work.\n"); - } - - mutex_unlock(&priv->mutex); - iwl3945_rfkill_set_hw_state(priv); -} - static void iwl3945_rfkill_poll(struct work_struct *data) { struct iwl_priv *priv = @@ -5391,7 +5358,7 @@ static void iwl3945_bg_up(struct work_struct *data) mutex_lock(&priv->mutex); __iwl3945_up(priv); mutex_unlock(&priv->mutex); - iwl3945_rfkill_set_hw_state(priv); + iwl_rfkill_set_hw_state(priv); } static void iwl3945_bg_restart(struct work_struct *data) @@ -5584,7 +5551,7 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) mutex_unlock(&priv->mutex); - iwl3945_rfkill_set_hw_state(priv); + iwl_rfkill_set_hw_state(priv); if (ret) goto out_release_irq; @@ -6852,7 +6819,7 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv) INIT_WORK(&priv->scan_completed, iwl3945_bg_scan_completed); INIT_WORK(&priv->request_scan, iwl3945_bg_request_scan); INIT_WORK(&priv->abort_scan, iwl3945_bg_abort_scan); - INIT_WORK(&priv->rf_kill, iwl3945_bg_rf_kill); + INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill); INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update); INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start); INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start); @@ -7180,7 +7147,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->hw->conf.beacon_int = 100; priv->mac80211_registered = 1; - err = iwl3945_rfkill_init(priv); + err = iwl_rfkill_init(priv); if (err) IWL_ERR(priv, "Unable to initialize RFKILL system. " "Ignoring error: %d\n", err); @@ -7246,7 +7213,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); - iwl3945_rfkill_unregister(priv); + iwl_rfkill_unregister(priv); cancel_delayed_work(&priv->rfkill_poll); iwl3945_dealloc_ucode_pci(priv); @@ -7319,114 +7286,6 @@ static int iwl3945_pci_resume(struct pci_dev *pdev) #endif /* CONFIG_PM */ -/*************** RFKILL FUNCTIONS **********/ -#ifdef CONFIG_IWL3945_RFKILL -/* software rf-kill from user */ -static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state) -{ - struct iwl_priv *priv = data; - int err = 0; - - if (!priv->rfkill) - return 0; - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return 0; - - IWL_DEBUG_RF_KILL("we received soft RFKILL set to state %d\n", state); - mutex_lock(&priv->mutex); - - switch (state) { - case RFKILL_STATE_UNBLOCKED: - if (iwl_is_rfkill_hw(priv)) { - err = -EBUSY; - goto out_unlock; - } - iwl3945_radio_kill_sw(priv, 0); - break; - case RFKILL_STATE_SOFT_BLOCKED: - iwl3945_radio_kill_sw(priv, 1); - break; - default: - IWL_WARN(priv, "received unexpected RFKILL state %d\n", state); - break; - } -out_unlock: - mutex_unlock(&priv->mutex); - - return err; -} - -int iwl3945_rfkill_init(struct iwl_priv *priv) -{ - struct device *device = wiphy_dev(priv->hw->wiphy); - int ret = 0; - - BUG_ON(device == NULL); - - IWL_DEBUG_RF_KILL("Initializing RFKILL.\n"); - priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); - if (!priv->rfkill) { - IWL_ERR(priv, "Unable to allocate rfkill device.\n"); - ret = -ENOMEM; - goto error; - } - - priv->rfkill->name = priv->cfg->name; - priv->rfkill->data = priv; - priv->rfkill->state = RFKILL_STATE_UNBLOCKED; - priv->rfkill->toggle_radio = iwl3945_rfkill_soft_rf_kill; - priv->rfkill->user_claim_unsupported = 1; - - priv->rfkill->dev.class->suspend = NULL; - priv->rfkill->dev.class->resume = NULL; - - ret = rfkill_register(priv->rfkill); - if (ret) { - IWL_ERR(priv, "Unable to register rfkill: %d\n", ret); - goto freed_rfkill; - } - - IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); - return ret; - -freed_rfkill: - if (priv->rfkill != NULL) - rfkill_free(priv->rfkill); - priv->rfkill = NULL; - -error: - IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); - return ret; -} - -void iwl3945_rfkill_unregister(struct iwl_priv *priv) -{ - if (priv->rfkill) - rfkill_unregister(priv->rfkill); - - priv->rfkill = NULL; -} - -/* set rf-kill to the right state. */ -void iwl3945_rfkill_set_hw_state(struct iwl_priv *priv) -{ - - if (!priv->rfkill) - return; - - if (iwl_is_rfkill_hw(priv)) { - rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED); - return; - } - - if (!iwl_is_rfkill_sw(priv)) - rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED); - else - rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED); -} -#endif - /***************************************************************************** * * driver and module entry point -- GitLab From e9414b6b3f34dcc3683e66dffa4f5f167d49df51 Mon Sep 17 00:00:00 2001 From: "Abbas, Mohamed" Date: Tue, 20 Jan 2009 21:33:55 -0800 Subject: [PATCH 0905/4982] iwl3945: fix deep sleep when removing the driver. A warning message "MAC is in deep sleep" sometimes happen when user removes the driver. This warning is related to card not being ready. In __iwl3945_down function some of the going down steps are in wrong order, to fix this this patch do the following: 1- make sure we are calling iwl3945_apm_reset and iwl3945_apm_stop in the right order. 2- make sure we set CSR_GP_CNTRL_REG_FLAG_INIT_DONE in apm_reset before poll on CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY. 3- set correct polling counter. This fixes bug http://www.intellinuxwireless.org/bugzilla/show_bug.cgi?id=1834 Signed-off-by: mohamed abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 8 +++----- drivers/net/wireless/iwlwifi/iwl-io.h | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 7 ++++++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index fe907f35336..4aeb101fc45 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1338,6 +1338,9 @@ static int iwl3945_apm_reset(struct iwl_priv *priv) spin_lock_irqsave(&priv->lock, flags); iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); + udelay(10); + + iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); iwl_poll_direct_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); @@ -1347,11 +1350,6 @@ static int iwl3945_apm_reset(struct iwl_priv *priv) iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_BSM_CLK_RQT); - udelay(10); - - iwl_set_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - iwl_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0); iwl_write_prph(priv, APMG_RTC_INT_STT_REG, 0xFFFFFFFF); diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index bc3f3daef6e..7341a2da843 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -165,7 +165,7 @@ static inline int _iwl_grab_nic_access(struct iwl_priv *priv) ret = _iwl_poll_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | - CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 50); + CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); if (ret < 0) { IWL_ERR(priv, "MAC is in deep sleep!\n"); return -EIO; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 78271936801..d520bfe2db9 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4941,6 +4941,7 @@ static void __iwl3945_down(struct iwl_priv *priv) test_bit(STATUS_EXIT_PENDING, &priv->status) << STATUS_EXIT_PENDING; + priv->cfg->ops->lib->apm_ops.reset(priv); spin_lock_irqsave(&priv->lock, flags); iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); spin_unlock_irqrestore(&priv->lock, flags); @@ -4958,7 +4959,11 @@ static void __iwl3945_down(struct iwl_priv *priv) udelay(5); - priv->cfg->ops->lib->apm_ops.reset(priv); + if (exit_pending || test_bit(STATUS_IN_SUSPEND, &priv->status)) + priv->cfg->ops->lib->apm_ops.stop(priv); + else + priv->cfg->ops->lib->apm_ops.reset(priv); + exit: memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); -- GitLab From 5f936f11613c32ca7f8ed5fa333bb38a4501deeb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 21 Jan 2009 12:47:05 +0100 Subject: [PATCH 0906/4982] mac80211: constify ieee80211_if_conf.bssid Then one place can be a static const. Signed-off-by: Johannes Berg Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/libertas_tf/cmd.c | 2 +- drivers/net/wireless/libertas_tf/libertas_tf.h | 2 +- drivers/net/wireless/rt2x00/rt2x00config.c | 2 +- drivers/net/wireless/rt2x00/rt2x00lib.h | 2 +- include/net/mac80211.h | 2 +- net/mac80211/main.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/libertas_tf/cmd.c b/drivers/net/wireless/libertas_tf/cmd.c index 3d3914c83b1..28790e03dc4 100644 --- a/drivers/net/wireless/libertas_tf/cmd.c +++ b/drivers/net/wireless/libertas_tf/cmd.c @@ -286,7 +286,7 @@ void lbtf_set_mode(struct lbtf_private *priv, enum lbtf_mode mode) lbtf_cmd_async(priv, CMD_802_11_SET_MODE, &cmd.hdr, sizeof(cmd)); } -void lbtf_set_bssid(struct lbtf_private *priv, bool activate, u8 *bssid) +void lbtf_set_bssid(struct lbtf_private *priv, bool activate, const u8 *bssid) { struct cmd_ds_set_bssid cmd; diff --git a/drivers/net/wireless/libertas_tf/libertas_tf.h b/drivers/net/wireless/libertas_tf/libertas_tf.h index 8995cd7c29b..4cc42dd5a00 100644 --- a/drivers/net/wireless/libertas_tf/libertas_tf.h +++ b/drivers/net/wireless/libertas_tf/libertas_tf.h @@ -463,7 +463,7 @@ int lbtf_set_radio_control(struct lbtf_private *priv); int lbtf_update_hw_spec(struct lbtf_private *priv); int lbtf_cmd_set_mac_multicast_addr(struct lbtf_private *priv); void lbtf_set_mode(struct lbtf_private *priv, enum lbtf_mode mode); -void lbtf_set_bssid(struct lbtf_private *priv, bool activate, u8 *bssid); +void lbtf_set_bssid(struct lbtf_private *priv, bool activate, const u8 *bssid); int lbtf_set_mac_address(struct lbtf_private *priv, uint8_t *mac_addr); int lbtf_set_channel(struct lbtf_private *priv, u8 channel); diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 6b3bb0f661d..9c2f5517af2 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -32,7 +32,7 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, enum nl80211_iftype type, - u8 *mac, u8 *bssid) + const u8 *mac, const u8 *bssid) { struct rt2x00intf_conf conf; unsigned int flags = 0; diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index daf0def915d..34efe465354 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -76,7 +76,7 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev); void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, enum nl80211_iftype type, - u8 *mac, u8 *bssid); + const u8 *mac, const u8 *bssid); void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, struct ieee80211_bss_conf *conf); diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 9a5869e9ecf..ef42559694f 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -643,7 +643,7 @@ enum ieee80211_if_conf_change { */ struct ieee80211_if_conf { u32 changed; - u8 *bssid; + const u8 *bssid; }; /** diff --git a/net/mac80211/main.c b/net/mac80211/main.c index c78304db475..6f0fe3564ca 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -176,7 +176,7 @@ int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) else if (sdata->vif.type == NL80211_IFTYPE_AP) conf.bssid = sdata->dev->dev_addr; else if (ieee80211_vif_is_mesh(&sdata->vif)) { - u8 zero[ETH_ALEN] = { 0 }; + static const u8 zero[ETH_ALEN] = { 0 }; conf.bssid = zero; } else { WARN_ON(1); -- GitLab From e6799cc2e8c755a0317e664f29de0b08ddd0eb35 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Wed, 21 Jan 2009 17:18:48 +0530 Subject: [PATCH 0907/4982] ath9k: Fix typo in chip version check Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index ab15e55317c..baa7a7e47c2 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -2255,7 +2255,7 @@ int ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan, return -EINVAL; } - if (AR_SREV_9280(ah)) { + if (AR_SREV_9280_10_OR_LATER(ah)) { REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); -- GitLab From 369391db1aabd089cefaadaabb6d9fc82e78b0a7 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Wed, 21 Jan 2009 19:24:13 +0530 Subject: [PATCH 0908/4982] ath9k: Remove unnecessary gpio configuration in ath9k_hw_reset() Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/hw.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index baa7a7e47c2..65e0d80f3b4 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -2255,18 +2255,8 @@ int ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan, return -EINVAL; } - if (AR_SREV_9280_10_OR_LATER(ah)) { - REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, - AR_GPIO_JTAG_DISABLE); - - if (test_bit(ATH9K_MODE_11A, ah->ah_caps.wireless_modes)) { - if (IS_CHAN_5GHZ(chan)) - ath9k_hw_set_gpio(ah, 9, 0); - else - ath9k_hw_set_gpio(ah, 9, 1); - } - ath9k_hw_cfg_output(ah, 9, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - } + if (AR_SREV_9280_10_OR_LATER(ah)) + REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); r = ath9k_hw_process_ini(ah, chan, sc->tx_chan_width); if (r) -- GitLab From 881d948c23442173a011f1adcfe4c95bf7f27515 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 21 Jan 2009 15:13:48 +0100 Subject: [PATCH 0909/4982] wireless: restrict to 32 legacy rates Since the standards only define 12 legacy rates, 32 is certainly a sane upper limit and we don't need to use u64 everywhere. Add sanity checking that no more than 32 rates are registered and change the variables to u32 throughout. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 2 +- drivers/net/wireless/b43legacy/main.c | 2 +- drivers/net/wireless/p54/p54.h | 2 +- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- include/net/mac80211.h | 4 ++-- include/net/wireless.h | 2 +- net/mac80211/ieee80211_i.h | 6 +++--- net/mac80211/mesh.c | 2 +- net/mac80211/mesh.h | 2 +- net/mac80211/mesh_plink.c | 6 +++--- net/mac80211/mlme.c | 16 ++++++++-------- net/mac80211/util.c | 4 ++-- net/wireless/core.c | 12 +++++++++--- net/wireless/util.c | 2 +- 14 files changed, 35 insertions(+), 29 deletions(-) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 8bb6659c0b3..675a73a9807 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3398,7 +3398,7 @@ out_unlock_mutex: return err; } -static void b43_update_basic_rates(struct b43_wldev *dev, u64 brates) +static void b43_update_basic_rates(struct b43_wldev *dev, u32 brates) { struct ieee80211_supported_band *sband = dev->wl->hw->wiphy->bands[b43_current_band(dev->wl)]; diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index fb996c27a19..879edc78671 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -2650,7 +2650,7 @@ out_unlock_mutex: return err; } -static void b43legacy_update_basic_rates(struct b43legacy_wldev *dev, u64 brates) +static void b43legacy_update_basic_rates(struct b43legacy_wldev *dev, u32 brates) { struct ieee80211_supported_band *sband = dev->wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ]; diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 64492feca9b..94c3acd1fca 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -144,7 +144,7 @@ struct p54_common { unsigned int output_power; u32 tsf_low32; u32 tsf_high32; - u64 basic_rate_mask; + u32 basic_rate_mask; u16 wakeup_timer; u16 aid; struct ieee80211_tx_queue_stats tx_stats[8]; diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index cc56637e73b..46918deceda 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -396,7 +396,7 @@ struct rt2x00lib_erp { int ack_timeout; int ack_consume_time; - u64 basic_rates; + u32 basic_rates; int slot_time; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index ef42559694f..c76484009ba 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -207,7 +207,7 @@ struct ieee80211_bss_conf { u16 beacon_int; u16 assoc_capability; u64 timestamp; - u64 basic_rates; + u32 basic_rates; struct ieee80211_bss_ht_conf ht; }; @@ -761,7 +761,7 @@ enum set_key_cmd { * sizeof(void *), size is determined in hw information. */ struct ieee80211_sta { - u64 supp_rates[IEEE80211_NUM_BANDS]; + u32 supp_rates[IEEE80211_NUM_BANDS]; u8 addr[ETH_ALEN]; u16 aid; struct ieee80211_sta_ht_cap ht_cap; diff --git a/include/net/wireless.h b/include/net/wireless.h index 9e73aae40c5..6c5b0820423 100644 --- a/include/net/wireless.h +++ b/include/net/wireless.h @@ -367,7 +367,7 @@ ieee80211_get_channel(struct wiphy *wiphy, int freq) */ struct ieee80211_rate * ieee80211_get_response_rate(struct ieee80211_supported_band *sband, - u64 basic_rates, int bitrate); + u32 basic_rates, int bitrate); /** * regulatory_hint - driver hint to the wireless core a regulatory domain diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a8c72742a8b..70366efc792 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -909,11 +909,11 @@ int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid); void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta); struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, - u8 *bssid, u8 *addr, u64 supp_rates); + u8 *bssid, u8 *addr, u32 supp_rates); int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason); int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason); u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); -u64 ieee80211_sta_get_rates(struct ieee80211_local *local, +u32 ieee80211_sta_get_rates(struct ieee80211_local *local, struct ieee802_11_elems *elems, enum ieee80211_band band); void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, @@ -1026,7 +1026,7 @@ void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, void ieee802_11_parse_elems(u8 *start, size_t len, struct ieee802_11_elems *elems); int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq); -u64 ieee80211_mandatory_rates(struct ieee80211_local *local, +u32 ieee80211_mandatory_rates(struct ieee80211_local *local, enum ieee80211_band band); void ieee80211_dynamic_ps_enable_work(struct work_struct *work); diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 82f568e9436..2d573f8470d 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -476,7 +476,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct ieee802_11_elems elems; struct ieee80211_channel *channel; - u64 supp_rates = 0; + u32 supp_rates = 0; size_t baselen; int freq; enum ieee80211_band band = rx_status->band; diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index f1196f5c3ef..9e064ee98ee 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -236,7 +236,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len); int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata); /* Mesh plinks */ -void mesh_neighbour_update(u8 *hw_addr, u64 rates, +void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data *sdata, bool add); bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index c140a1b71a5..a8bbdeca013 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -93,7 +93,7 @@ static inline void mesh_plink_fsm_restart(struct sta_info *sta) * on it in the lifecycle management section! */ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, - u8 *hw_addr, u64 rates) + u8 *hw_addr, u32 rates) { struct ieee80211_local *local = sdata->local; struct sta_info *sta; @@ -222,7 +222,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, return 0; } -void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct ieee80211_sub_if_data *sdata, +void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data *sdata, bool peer_accepting_plinks) { struct ieee80211_local *local = sdata->local; @@ -447,7 +447,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m spin_lock_bh(&sta->lock); } else if (!sta) { /* ftype == PLINK_OPEN */ - u64 rates; + u32 rates; if (!mesh_plink_free_count(sdata)) { mpl_dbg("Mesh plink error: no more free plinks\n"); rcu_read_unlock(); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index b9e4b93089c..9852da54f5e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -73,7 +73,7 @@ static u8 *ieee80211_bss_get_ie(struct ieee80211_bss *bss, u8 ie) static int ieee80211_compatible_rates(struct ieee80211_bss *bss, struct ieee80211_supported_band *sband, - u64 *rates) + u32 *rates) { int i, j, count; *rates = 0; @@ -93,14 +93,14 @@ static int ieee80211_compatible_rates(struct ieee80211_bss *bss, } /* also used by mesh code */ -u64 ieee80211_sta_get_rates(struct ieee80211_local *local, +u32 ieee80211_sta_get_rates(struct ieee80211_local *local, struct ieee802_11_elems *elems, enum ieee80211_band band) { struct ieee80211_supported_band *sband; struct ieee80211_rate *bitrates; size_t num_rates; - u64 supp_rates; + u32 supp_rates; int i, j; sband = local->hw.wiphy->bands[band]; @@ -253,7 +253,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_bss *bss; int wmm = 0; struct ieee80211_supported_band *sband; - u64 rates = 0; + u32 rates = 0; size_t e_ies_len; if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) { @@ -1282,7 +1282,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; struct sta_info *sta; - u64 rates, basic_rates; + u32 rates, basic_rates; u16 capab_info, status_code, aid; struct ieee802_11_elems elems; struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; @@ -1639,7 +1639,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, struct sta_info *sta; struct ieee80211_channel *channel; u64 beacon_timestamp, rx_timestamp; - u64 supp_rates = 0; + u32 supp_rates = 0; enum ieee80211_band band = rx_status->band; if (elems->ds_params && elems->ds_params_len == 1) @@ -1660,7 +1660,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, sta = sta_info_get(local, mgmt->sa); if (sta) { - u64 prev_rates; + u32 prev_rates; prev_rates = sta->sta.supp_rates[band]; /* make sure mandatory rates are always added */ @@ -2526,7 +2526,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) * must be callable in atomic context. */ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, - u8 *bssid,u8 *addr, u64 supp_rates) + u8 *bssid,u8 *addr, u32 supp_rates) { struct ieee80211_local *local = sdata->local; struct sta_info *sta; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 3f559e3d0a7..ede96c4fea2 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -731,12 +731,12 @@ int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz) return ret; } -u64 ieee80211_mandatory_rates(struct ieee80211_local *local, +u32 ieee80211_mandatory_rates(struct ieee80211_local *local, enum ieee80211_band band) { struct ieee80211_supported_band *sband; struct ieee80211_rate *bitrates; - u64 mandatory_rates; + u32 mandatory_rates; enum ieee80211_rate_flags mandatory_flag; int i; diff --git a/net/wireless/core.c b/net/wireless/core.c index b96fc0c3f1c..12522647608 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -273,10 +273,16 @@ int wiphy_register(struct wiphy *wiphy) sband->band = band; - if (!sband->n_channels || !sband->n_bitrates) { - WARN_ON(1); + if (WARN_ON(!sband->n_channels || !sband->n_bitrates)) + return -EINVAL; + + /* + * Since we use a u32 for rate bitmaps in + * ieee80211_get_response_rate, we cannot + * have more than 32 legacy rates. + */ + if (WARN_ON(sband->n_bitrates > 32)) return -EINVAL; - } for (i = 0; i < sband->n_channels; i++) { sband->channels[i].orig_flags = diff --git a/net/wireless/util.c b/net/wireless/util.c index e76cc28b034..487cdd9bcff 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -9,7 +9,7 @@ struct ieee80211_rate * ieee80211_get_response_rate(struct ieee80211_supported_band *sband, - u64 basic_rates, int bitrate) + u32 basic_rates, int bitrate) { struct ieee80211_rate *result = &sband->bitrates[0]; int i; -- GitLab From 89ea40905fb48e2bf92211b57ab6be51c0797657 Mon Sep 17 00:00:00 2001 From: Andrey Borzenkov Date: Wed, 21 Jan 2009 20:46:46 +0300 Subject: [PATCH 0910/4982] orinoco: convert to struct net_device_ops No functional changes; use new kernel interface for netdev methods. Signed-off-by: Andrey Borzenkov Acked-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/orinoco.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c index 41aa51bc49a..05c157698db 100644 --- a/drivers/net/wireless/orinoco/orinoco.c +++ b/drivers/net/wireless/orinoco/orinoco.c @@ -3583,6 +3583,17 @@ static int orinoco_init(struct net_device *dev) return err; } +static const struct net_device_ops orinoco_netdev_ops = { + .ndo_init = orinoco_init, + .ndo_open = orinoco_open, + .ndo_stop = orinoco_stop, + .ndo_start_xmit = orinoco_xmit, + .ndo_set_multicast_list = orinoco_set_multicast_list, + .ndo_change_mtu = orinoco_change_mtu, + .ndo_tx_timeout = orinoco_tx_timeout, + .ndo_get_stats = orinoco_get_stats, +}; + struct net_device *alloc_orinocodev(int sizeof_card, struct device *device, @@ -3605,27 +3616,20 @@ struct net_device priv->dev = device; /* Setup / override net_device fields */ - dev->init = orinoco_init; - dev->hard_start_xmit = orinoco_xmit; - dev->tx_timeout = orinoco_tx_timeout; + dev->netdev_ops = &orinoco_netdev_ops; dev->watchdog_timeo = HZ; /* 1 second timeout */ - dev->get_stats = orinoco_get_stats; dev->ethtool_ops = &orinoco_ethtool_ops; dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def; #ifdef WIRELESS_SPY priv->wireless_data.spy_data = &priv->spy_data; dev->wireless_data = &priv->wireless_data; #endif - dev->change_mtu = orinoco_change_mtu; - dev->set_multicast_list = orinoco_set_multicast_list; /* we use the default eth_mac_addr for setting the MAC addr */ /* Reserve space in skb for the SNAP header */ dev->hard_header_len += ENCAPS_OVERHEAD; /* Set up default callbacks */ - dev->open = orinoco_open; - dev->stop = orinoco_stop; priv->hard_reset = hard_reset; priv->stop_fw = stop_fw; -- GitLab From e129a948c906200db87727822559c09b62278824 Mon Sep 17 00:00:00 2001 From: Andrey Borzenkov Date: Wed, 21 Jan 2009 21:55:29 +0300 Subject: [PATCH 0911/4982] orinoco: trivial cleanup in alloc_orinocodev Remove extra space; remove redundant cast Signed-off-by: Andrey Borzenkov Acked-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/orinoco.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c index 05c157698db..6514e4611b9 100644 --- a/drivers/net/wireless/orinoco/orinoco.c +++ b/drivers/net/wireless/orinoco/orinoco.c @@ -3604,7 +3604,7 @@ struct net_device struct orinoco_private *priv; dev = alloc_etherdev(sizeof(struct orinoco_private) + sizeof_card); - if (! dev) + if (!dev) return NULL; priv = netdev_priv(dev); priv->ndev = dev; @@ -3619,7 +3619,7 @@ struct net_device dev->netdev_ops = &orinoco_netdev_ops; dev->watchdog_timeo = HZ; /* 1 second timeout */ dev->ethtool_ops = &orinoco_ethtool_ops; - dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def; + dev->wireless_handlers = &orinoco_handler_def; #ifdef WIRELESS_SPY priv->wireless_data.spy_data = &priv->spy_data; dev->wireless_data = &priv->wireless_data; -- GitLab From 2134e7e724798cf8d54ae822afe235abb607d9b2 Mon Sep 17 00:00:00 2001 From: Sujith Date: Thu, 22 Jan 2009 09:00:52 +0530 Subject: [PATCH 0912/4982] mac80211: Add documentation bits for mac80211_rate_control_flags Signed-off-by: Sujith Acked-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index c76484009ba..634c08de6ac 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -262,6 +262,26 @@ enum mac80211_tx_control_flags { IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), }; +/** + * enum mac80211_rate_control_flags - per-rate flags set by the + * Rate Control algorithm. + * + * These flags are set by the Rate control algorithm for each rate during tx, + * in the @flags member of struct ieee80211_tx_rate. + * + * @IEEE80211_TX_RC_USE_RTS_CTS: Use RTS/CTS exchange for this rate. + * @IEEE80211_TX_RC_USE_CTS_PROTECT: CTS-to-self protection is required. + * This is set if the current BSS requires ERP protection. + * @IEEE80211_TX_RC_USE_SHORT_PREAMBLE: Use short preamble. + * @IEEE80211_TX_RC_MCS: HT rate. + * @IEEE80211_TX_RC_GREEN_FIELD: Indicates whether this rate should be used in + * Greenfield mode. + * @IEEE80211_TX_RC_40_MHZ_WIDTH: Indicates if the Channel Width should be 40 MHz. + * @IEEE80211_TX_RC_DUP_DATA: The frame should be transmitted on both of the + * adjacent 20 MHz channels, if the current channel type is + * NL80211_CHAN_HT40MINUS or NL80211_CHAN_HT40PLUS. + * @IEEE80211_TX_RC_SHORT_GI: Short Guard interval should be used for this rate. + */ enum mac80211_rate_control_flags { IEEE80211_TX_RC_USE_RTS_CTS = BIT(0), IEEE80211_TX_RC_USE_CTS_PROTECT = BIT(1), -- GitLab From 5ef4017a72f77f0bc07d8efb35c140b42e064f70 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Thu, 22 Jan 2009 08:44:19 -0500 Subject: [PATCH 0913/4982] ath5k: remove unused led_off parameter ath5k_softc->led_off hasn't been used since commit 3a078876caee9634dbb9b41e6269262e30e8b535, "convert LED code to use mac80211 triggers." Changes-licensed-under: 3-Clause-BSD Reported-by: Tobias Doerffel Signed-off-by: Bob Copeland Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath5k/base.h b/drivers/net/wireless/ath5k/base.h index facc60ddada..c0fb8b5c42f 100644 --- a/drivers/net/wireless/ath5k/base.h +++ b/drivers/net/wireless/ath5k/base.h @@ -148,8 +148,7 @@ struct ath5k_softc { u8 bssidmask[ETH_ALEN]; unsigned int led_pin, /* GPIO pin for driving LED */ - led_on, /* pin setting for LED on */ - led_off; /* off time for current blink */ + led_on; /* pin setting for LED on */ struct tasklet_struct restq; /* reset tasklet */ -- GitLab From 8902ff4e5666c04ca5829c9fd7fc28d73e81ee90 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Thu, 22 Jan 2009 08:44:20 -0500 Subject: [PATCH 0914/4982] ath5k: use short preamble when possible ath5k previously ignored TX_RC_SHORT_PREAMBLE and did not use config->use_short_preamble, so the long preamble was always used for transmitted packets. Changes-licensed-under: 3-Clause-BSD Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 747b49682c5..fc0ff713401 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -1179,6 +1179,8 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) struct ieee80211_rate *rate; unsigned int mrr_rate[3], mrr_tries[3]; int i, ret; + u16 hw_rate; + u8 rc_flags; flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK; @@ -1186,9 +1188,15 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); + rate = ieee80211_get_tx_rate(sc->hw, info); + if (info->flags & IEEE80211_TX_CTL_NO_ACK) flags |= AR5K_TXDESC_NOACK; + rc_flags = info->control.rates[0].flags; + hw_rate = (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) ? + rate->hw_value_short : rate->hw_value; + pktlen = skb->len; if (info->control.hw_key) { @@ -1198,7 +1206,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) ret = ah->ah_setup_tx_desc(ah, ds, pktlen, ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, (sc->power_level * 2), - ieee80211_get_tx_rate(sc->hw, info)->hw_value, + hw_rate, info->control.rates[0].count, keyidx, 0, flags, 0, 0); if (ret) goto err_unmap; -- GitLab From 07c1e852514e862e246b9f2962ce8fc0d7ac8ed1 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Thu, 22 Jan 2009 08:44:21 -0500 Subject: [PATCH 0915/4982] ath5k: honor the RTS/CTS bits The ath5k driver didn't use set_rts_threshold or use_cts_prot, and also didn't check the IEEE80211_TX_RC_USE_{RTS_CTS,CTS_PROTECT} RC flags. Tell the hardware about these so RTS/CTS will work, and so the device will work better in mixed b/g environments. Changes-licensed-under: 3-Clause-BSD Signed-off-by: Bob Copeland Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index fc0ff713401..fa39f21c36c 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -1180,6 +1180,8 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) unsigned int mrr_rate[3], mrr_tries[3]; int i, ret; u16 hw_rate; + u16 cts_rate = 0; + u16 duration = 0; u8 rc_flags; flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK; @@ -1199,6 +1201,19 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) pktlen = skb->len; + if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { + flags |= AR5K_TXDESC_RTSENA; + cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value; + duration = le16_to_cpu(ieee80211_rts_duration(sc->hw, + sc->vif, pktlen, info)); + } + if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { + flags |= AR5K_TXDESC_CTSENA; + cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value; + duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw, + sc->vif, pktlen, info)); + } + if (info->control.hw_key) { keyidx = info->control.hw_key->hw_key_idx; pktlen += info->control.hw_key->icv_len; @@ -1207,7 +1222,8 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, (sc->power_level * 2), hw_rate, - info->control.rates[0].count, keyidx, 0, flags, 0, 0); + info->control.rates[0].count, keyidx, 0, flags, + cts_rate, duration); if (ret) goto err_unmap; -- GitLab From 078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ff Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 22 Jan 2009 18:07:31 +0100 Subject: [PATCH 0916/4982] mac80211: Add capability to enable/disable beaconing This patch adds a flag to notify drivers to start and stop beaconing when needed, for example, during a scan run. Based on Sujith's first patch to do the same, but now disables beaconing for all virtual interfaces while scanning, has a separate change flag and tracks user-space requests. Signed-off-by: Sujith Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 9 +++++++-- net/mac80211/cfg.c | 5 +++-- net/mac80211/main.c | 42 +++++++++++++++++++++++++++++++++++++++++- net/mac80211/mesh.c | 3 ++- net/mac80211/mlme.c | 3 ++- net/mac80211/scan.c | 18 +++++++++++------- 6 files changed, 66 insertions(+), 14 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 634c08de6ac..35643c55827 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -646,10 +646,12 @@ struct ieee80211_if_init_conf { * @IEEE80211_IFCC_BSSID: The BSSID changed. * @IEEE80211_IFCC_BEACON: The beacon for this interface changed * (currently AP and MESH only), use ieee80211_beacon_get(). + * @IEEE80211_IFCC_BEACON_ENABLED: The enable_beacon value changed. */ enum ieee80211_if_conf_change { - IEEE80211_IFCC_BSSID = BIT(0), - IEEE80211_IFCC_BEACON = BIT(1), + IEEE80211_IFCC_BSSID = BIT(0), + IEEE80211_IFCC_BEACON = BIT(1), + IEEE80211_IFCC_BEACON_ENABLED = BIT(2), }; /** @@ -657,6 +659,8 @@ enum ieee80211_if_conf_change { * * @changed: parameters that have changed, see &enum ieee80211_if_conf_change. * @bssid: BSSID of the network we are associated to/creating. + * @enable_beacon: Indicates whether beacons can be sent. + * This is valid only for AP/IBSS/MESH modes. * * This structure is passed to the config_interface() callback of * &struct ieee80211_hw. @@ -664,6 +668,7 @@ enum ieee80211_if_conf_change { struct ieee80211_if_conf { u32 changed; const u8 *bssid; + bool enable_beacon; }; /** diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 3527de22caf..a1a1344c5c4 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -523,7 +523,8 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, kfree(old); - return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); + return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | + IEEE80211_IFCC_BEACON_ENABLED); } static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, @@ -583,7 +584,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) synchronize_rcu(); kfree(old); - return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); + return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED); } /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 6f0fe3564ca..8d5c19e4a1b 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -168,7 +168,6 @@ int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) return 0; memset(&conf, 0, sizeof(conf)); - conf.changed = changed; if (sdata->vif.type == NL80211_IFTYPE_STATION || sdata->vif.type == NL80211_IFTYPE_ADHOC) @@ -183,9 +182,50 @@ int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) return -EINVAL; } + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: + break; + default: + /* do not warn to simplify caller in scan.c */ + changed &= ~IEEE80211_IFCC_BEACON_ENABLED; + if (WARN_ON(changed & IEEE80211_IFCC_BEACON)) + return -EINVAL; + changed &= ~IEEE80211_IFCC_BEACON; + break; + } + + if (changed & IEEE80211_IFCC_BEACON_ENABLED) { + if (local->sw_scanning) { + conf.enable_beacon = false; + } else { + /* + * Beacon should be enabled, but AP mode must + * check whether there is a beacon configured. + */ + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP: + conf.enable_beacon = + !!rcu_dereference(sdata->u.ap.beacon); + break; + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: + conf.enable_beacon = true; + break; + default: + /* not reached */ + WARN_ON(1); + break; + } + } + } + if (WARN_ON(!conf.bssid && (changed & IEEE80211_IFCC_BSSID))) return -EINVAL; + conf.changed = changed; + return local->ops->config_interface(local_to_hw(local), &sdata->vif, &conf); } diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 2d573f8470d..8a1fcaeee4f 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -442,7 +442,8 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) ifmsh->housekeeping = true; queue_work(local->hw.workqueue, &ifmsh->work); - ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); + ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | + IEEE80211_IFCC_BEACON_ENABLED); } void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 9852da54f5e..ec400479c5f 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1599,7 +1599,8 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, ifsta->probe_resp = skb; - ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); + ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | + IEEE80211_IFCC_BEACON_ENABLED); rates = 0; diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index a2caeed57f4..8248d7b6ae8 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -472,8 +473,8 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) netif_addr_unlock(local->mdev); netif_tx_unlock_bh(local->mdev); - rcu_read_lock(); - list_for_each_entry_rcu(sdata, &local->interfaces, list) { + mutex_lock(&local->iflist_mtx); + list_for_each_entry(sdata, &local->interfaces, list) { /* Tell AP we're back */ if (sdata->vif.type == NL80211_IFTYPE_STATION) { if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { @@ -482,8 +483,10 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) } } else netif_tx_wake_all_queues(sdata->dev); + + ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED); } - rcu_read_unlock(); + mutex_unlock(&local->iflist_mtx); done: ieee80211_mlme_notify_scan_completed(local); @@ -491,7 +494,6 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) } EXPORT_SYMBOL(ieee80211_scan_completed); - void ieee80211_scan_work(struct work_struct *work) { struct ieee80211_local *local = @@ -633,8 +635,10 @@ int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, local->sw_scanning = true; - rcu_read_lock(); - list_for_each_entry_rcu(sdata, &local->interfaces, list) { + mutex_lock(&local->iflist_mtx); + list_for_each_entry(sdata, &local->interfaces, list) { + ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED); + if (sdata->vif.type == NL80211_IFTYPE_STATION) { if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { netif_tx_stop_all_queues(sdata->dev); @@ -643,7 +647,7 @@ int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, } else netif_tx_stop_all_queues(sdata->dev); } - rcu_read_unlock(); + mutex_unlock(&local->iflist_mtx); if (ssid) { local->scan_ssid_len = ssid_len; -- GitLab From 1fa25e413659f943dfec65da2abe713d566c7fdf Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 22 Jan 2009 15:05:44 -0800 Subject: [PATCH 0917/4982] cfg80211: add wiphy_apply_custom_regulatory() This adds wiphy_apply_custom_regulatory() to be used by drivers prior to wiphy registration to apply a custom regulatory domain. This can be used by drivers that do not have a direct 1-1 mapping between a regulatory domain and a country. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- include/net/wireless.h | 17 ++++++ net/wireless/reg.c | 115 ++++++++++++++++++++++++++++++++--------- 2 files changed, 108 insertions(+), 24 deletions(-) diff --git a/include/net/wireless.h b/include/net/wireless.h index 6c5b0820423..c5538b923af 100644 --- a/include/net/wireless.h +++ b/include/net/wireless.h @@ -401,4 +401,21 @@ extern void regulatory_hint(struct wiphy *wiphy, const char *alpha2); extern void regulatory_hint_11d(struct wiphy *wiphy, u8 *country_ie, u8 country_ie_len); + +/** + * wiphy_apply_custom_regulatory - apply a custom driver regulatory domain + * @wiphy: the wireless device we want to process the regulatory domain on + * @regd: the custom regulatory domain to use for this wiphy + * + * Drivers can sometimes have custom regulatory domains which do not apply + * to a specific country. Drivers can use this to apply such custom regulatory + * domains. This routine must be called prior to wiphy registration. The + * custom regulatory domain will be trusted completely and as such previous + * default channel settings will be disregarded. If no rule is found for a + * channel on the regulatory domain the channel will be disabled. + */ +extern void wiphy_apply_custom_regulatory( + struct wiphy *wiphy, + const struct ieee80211_regdomain *regd); + #endif /* __NET_WIRELESS_H */ diff --git a/net/wireless/reg.c b/net/wireless/reg.c index b34fd84b3e2..0d6059502b4 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -782,36 +782,18 @@ static u32 map_regdom_flags(u32 rd_flags) return channel_flags; } -/** - * freq_reg_info - get regulatory information for the given frequency - * @wiphy: the wiphy for which we want to process this rule for - * @center_freq: Frequency in KHz for which we want regulatory information for - * @bandwidth: the bandwidth requirement you have in KHz, if you do not have one - * you can set this to 0. If this frequency is allowed we then set - * this value to the maximum allowed bandwidth. - * @reg_rule: the regulatory rule which we have for this frequency - * - * Use this function to get the regulatory rule for a specific frequency on - * a given wireless device. If the device has a specific regulatory domain - * it wants to follow we respect that unless a country IE has been received - * and processed already. - * - * Returns 0 if it was able to find a valid regulatory rule which does - * apply to the given center_freq otherwise it returns non-zero. It will - * also return -ERANGE if we determine the given center_freq does not even have - * a regulatory rule for a frequency range in the center_freq's band. See - * freq_in_rule_band() for our current definition of a band -- this is purely - * subjective and right now its 802.11 specific. - */ -static int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, - const struct ieee80211_reg_rule **reg_rule) +static int freq_reg_info_regd(struct wiphy *wiphy, + u32 center_freq, + u32 *bandwidth, + const struct ieee80211_reg_rule **reg_rule, + const struct ieee80211_regdomain *custom_regd) { int i; bool band_rule_found = false; const struct ieee80211_regdomain *regd; u32 max_bandwidth = 0; - regd = cfg80211_regdomain; + regd = custom_regd ? custom_regd : cfg80211_regdomain; /* Follow the driver's regulatory domain, if present, unless a country * IE has been processed */ @@ -852,6 +834,34 @@ static int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, return !max_bandwidth; } +/** + * freq_reg_info - get regulatory information for the given frequency + * @wiphy: the wiphy for which we want to process this rule for + * @center_freq: Frequency in KHz for which we want regulatory information for + * @bandwidth: the bandwidth requirement you have in KHz, if you do not have one + * you can set this to 0. If this frequency is allowed we then set + * this value to the maximum allowed bandwidth. + * @reg_rule: the regulatory rule which we have for this frequency + * + * Use this function to get the regulatory rule for a specific frequency on + * a given wireless device. If the device has a specific regulatory domain + * it wants to follow we respect that unless a country IE has been received + * and processed already. + * + * Returns 0 if it was able to find a valid regulatory rule which does + * apply to the given center_freq otherwise it returns non-zero. It will + * also return -ERANGE if we determine the given center_freq does not even have + * a regulatory rule for a frequency range in the center_freq's band. See + * freq_in_rule_band() for our current definition of a band -- this is purely + * subjective and right now its 802.11 specific. + */ +static int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, + const struct ieee80211_reg_rule **reg_rule) +{ + return freq_reg_info_regd(wiphy, center_freq, + bandwidth, reg_rule, NULL); +} + static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, unsigned int chan_idx) { @@ -962,6 +972,63 @@ void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby) wiphy->reg_notifier(wiphy, setby); } +static void handle_channel_custom(struct wiphy *wiphy, + enum ieee80211_band band, + unsigned int chan_idx, + const struct ieee80211_regdomain *regd) +{ + int r; + u32 max_bandwidth = 0; + const struct ieee80211_reg_rule *reg_rule = NULL; + const struct ieee80211_power_rule *power_rule = NULL; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *chan; + + sband = wiphy->bands[band]; + BUG_ON(chan_idx >= sband->n_channels); + chan = &sband->channels[chan_idx]; + + r = freq_reg_info_regd(wiphy, MHZ_TO_KHZ(chan->center_freq), + &max_bandwidth, ®_rule, regd); + + if (r) { + chan->flags = IEEE80211_CHAN_DISABLED; + return; + } + + power_rule = ®_rule->power_rule; + + chan->flags |= map_regdom_flags(reg_rule->flags); + chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain); + chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth); + chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); +} + +static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band, + const struct ieee80211_regdomain *regd) +{ + unsigned int i; + struct ieee80211_supported_band *sband; + + BUG_ON(!wiphy->bands[band]); + sband = wiphy->bands[band]; + + for (i = 0; i < sband->n_channels; i++) + handle_channel_custom(wiphy, band, i, regd); +} + +/* Used by drivers prior to wiphy registration */ +void wiphy_apply_custom_regulatory(struct wiphy *wiphy, + const struct ieee80211_regdomain *regd) +{ + enum ieee80211_band band; + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + if (wiphy->bands[band]) + handle_band_custom(wiphy, band, regd); + } +} +EXPORT_SYMBOL(wiphy_apply_custom_regulatory); + static int reg_copy_regd(const struct ieee80211_regdomain **dst_regd, const struct ieee80211_regdomain *src_regd) { -- GitLab From 34f573473a659f8c2727d8d408e17b241900c28e Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 22 Jan 2009 15:05:45 -0800 Subject: [PATCH 0918/4982] cfg80211: export freq_reg_info() This can be used by drivers on the reg_notifier() Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- include/net/wireless.h | 24 ++++++++++++++++++++++++ net/wireless/reg.c | 24 ++---------------------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/include/net/wireless.h b/include/net/wireless.h index c5538b923af..f68602eb416 100644 --- a/include/net/wireless.h +++ b/include/net/wireless.h @@ -418,4 +418,28 @@ extern void wiphy_apply_custom_regulatory( struct wiphy *wiphy, const struct ieee80211_regdomain *regd); +/** + * freq_reg_info - get regulatory information for the given frequency + * @wiphy: the wiphy for which we want to process this rule for + * @center_freq: Frequency in KHz for which we want regulatory information for + * @bandwidth: the bandwidth requirement you have in KHz, if you do not have one + * you can set this to 0. If this frequency is allowed we then set + * this value to the maximum allowed bandwidth. + * @reg_rule: the regulatory rule which we have for this frequency + * + * Use this function to get the regulatory rule for a specific frequency on + * a given wireless device. If the device has a specific regulatory domain + * it wants to follow we respect that unless a country IE has been received + * and processed already. + * + * Returns 0 if it was able to find a valid regulatory rule which does + * apply to the given center_freq otherwise it returns non-zero. It will + * also return -ERANGE if we determine the given center_freq does not even have + * a regulatory rule for a frequency range in the center_freq's band. See + * freq_in_rule_band() for our current definition of a band -- this is purely + * subjective and right now its 802.11 specific. + */ +extern int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, + const struct ieee80211_reg_rule **reg_rule); + #endif /* __NET_WIRELESS_H */ diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 0d6059502b4..d663795d694 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -833,29 +833,9 @@ static int freq_reg_info_regd(struct wiphy *wiphy, return !max_bandwidth; } +EXPORT_SYMBOL(freq_reg_info); -/** - * freq_reg_info - get regulatory information for the given frequency - * @wiphy: the wiphy for which we want to process this rule for - * @center_freq: Frequency in KHz for which we want regulatory information for - * @bandwidth: the bandwidth requirement you have in KHz, if you do not have one - * you can set this to 0. If this frequency is allowed we then set - * this value to the maximum allowed bandwidth. - * @reg_rule: the regulatory rule which we have for this frequency - * - * Use this function to get the regulatory rule for a specific frequency on - * a given wireless device. If the device has a specific regulatory domain - * it wants to follow we respect that unless a country IE has been received - * and processed already. - * - * Returns 0 if it was able to find a valid regulatory rule which does - * apply to the given center_freq otherwise it returns non-zero. It will - * also return -ERANGE if we determine the given center_freq does not even have - * a regulatory rule for a frequency range in the center_freq's band. See - * freq_in_rule_band() for our current definition of a band -- this is purely - * subjective and right now its 802.11 specific. - */ -static int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, +int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, const struct ieee80211_reg_rule **reg_rule) { return freq_reg_info_regd(wiphy, center_freq, -- GitLab From 5eebade608d695e30e89d4c5ca6136a58f24ed14 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 22 Jan 2009 15:05:47 -0800 Subject: [PATCH 0919/4982] cfg80211: process user requests only after previous user/driver/core requests This prevents user regulatory changes to be considered prior to previous pending user, core or driver requests which have not be applied. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index d663795d694..4d2d2d4cc0d 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1091,6 +1091,16 @@ static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by, if (last_request->initiator == REGDOM_SET_BY_USER && last_request->intersect) return -EOPNOTSUPP; + /* Process user requests only after previous user/driver/core + * requests have been processed */ + if (last_request->initiator == REGDOM_SET_BY_CORE || + last_request->initiator == REGDOM_SET_BY_DRIVER || + last_request->initiator == REGDOM_SET_BY_USER) { + if (!alpha2_equal(last_request->alpha2, + cfg80211_regdomain->alpha2)) + return -EAGAIN; + } + return 0; } -- GitLab From e74b1e7fb2f12db36f25af2158ee6e2940e4f138 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 22 Jan 2009 15:05:48 -0800 Subject: [PATCH 0920/4982] cfg80211: ignore consecutive equal regulatory hints We ignore regulatory hints for the same alpha2 if we already have processed the same alpha2 on the current regulatory domain. For a driver regulatory_hint() this means we copy onto its wiphy->regd the previously procesed regulatory domain from CRDA without having to call CRDA again. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 4d2d2d4cc0d..c201abd38ad 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1080,8 +1080,13 @@ static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by, } return REG_INTERSECT; case REGDOM_SET_BY_DRIVER: - if (last_request->initiator == REGDOM_SET_BY_CORE) - return 0; + if (last_request->initiator == REGDOM_SET_BY_CORE) { + if (is_old_static_regdom(cfg80211_regdomain)) + return 0; + if (!alpha2_equal(cfg80211_regdomain->alpha2, alpha2)) + return 0; + return -EALREADY; + } return REG_INTERSECT; case REGDOM_SET_BY_USER: if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) @@ -1101,6 +1106,10 @@ static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by, return -EAGAIN; } + if (!is_old_static_regdom(cfg80211_regdomain) && + alpha2_equal(cfg80211_regdomain->alpha2, alpha2)) + return -EALREADY; + return 0; } -- GitLab From 2a44f911d8bac3e6c97a25cc612e4324dfbdfdc4 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 22 Jan 2009 15:05:49 -0800 Subject: [PATCH 0921/4982] cfg80211: rename fw_handles_regulatory to custom_regulatory Drivers without firmware can also have custom regulatory maps which do not map to a specific ISO / IEC alpha2 country code. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- include/net/wireless.h | 6 +++--- net/wireless/reg.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index f24d3b40e8e..9f284ebb6c2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -811,7 +811,7 @@ int iwl_setup_mac(struct iwl_priv *priv) BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); - hw->wiphy->fw_handles_regulatory = true; + hw->wiphy->custom_regulatory = true; /* Default value; 4 EDCA QOS priorities */ hw->queues = 4; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index d520bfe2db9..de8c8d7ca0f 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -7011,7 +7011,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); - hw->wiphy->fw_handles_regulatory = true; + hw->wiphy->custom_regulatory = true; /* 4 EDCA QOS priorities */ hw->queues = 4; diff --git a/include/net/wireless.h b/include/net/wireless.h index f68602eb416..c3f6e462ec2 100644 --- a/include/net/wireless.h +++ b/include/net/wireless.h @@ -181,8 +181,8 @@ struct ieee80211_supported_band { * struct wiphy - wireless hardware description * @idx: the wiphy index assigned to this item * @class_dev: the class device representing /sys/class/ieee80211/ - * @fw_handles_regulatory: tells us the firmware for this device - * has its own regulatory solution and cannot identify the + * @custom_regulatory: tells us the driver for this device + * has its own custom regulatory domain and cannot identify the * ISO / IEC 3166 alpha2 it belongs to. When this is enabled * we will disregard the first regulatory hint (when the * initiator is %REGDOM_SET_BY_CORE). @@ -201,7 +201,7 @@ struct wiphy { /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ u16 interface_modes; - bool fw_handles_regulatory; + bool custom_regulatory; /* If multiple wiphys are registered and you're handed e.g. * a regular netdev with assigned ieee80211_ptr, you won't diff --git a/net/wireless/reg.c b/net/wireless/reg.c index c201abd38ad..5db02a3d9c0 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -927,7 +927,7 @@ static bool ignore_reg_update(struct wiphy *wiphy, enum reg_set_by setby) if (!last_request) return true; if (setby == REGDOM_SET_BY_CORE && - wiphy->fw_handles_regulatory) + wiphy->custom_regulatory) return true; return false; } -- GitLab From d46e5b1d0c617a2a46353812d7f02115c17b5e72 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 22 Jan 2009 15:05:50 -0800 Subject: [PATCH 0922/4982] cfg80211: move check for ignore_reg_update() on wiphy_update_regulatory() This ensures that the initial REGDOM_SET_BY_CORE upon wiphy registration respects the wiphy->custom_regulatory setting. Without this and if OLD_REG is disabled (which will be default soon as we remove it) the wiphy->custom_regulatory is simply ignored. Signed-off-by: Luis R. Rodriguez Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/reg.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 5db02a3d9c0..81acb07f1d4 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -937,13 +937,15 @@ static void update_all_wiphy_regulatory(enum reg_set_by setby) struct cfg80211_registered_device *drv; list_for_each_entry(drv, &cfg80211_drv_list, list) - if (!ignore_reg_update(&drv->wiphy, setby)) - wiphy_update_regulatory(&drv->wiphy, setby); + wiphy_update_regulatory(&drv->wiphy, setby); } void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby) { enum ieee80211_band band; + + if (ignore_reg_update(wiphy, setby)) + return; for (band = 0; band < IEEE80211_NUM_BANDS; band++) { if (wiphy->bands[band]) handle_band(wiphy, band); -- GitLab From 716f9392e2b84cacc18cc11f7427cb98adeb1c3d Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 22 Jan 2009 15:05:51 -0800 Subject: [PATCH 0923/4982] cfg80211: pass more detailed regulatory request information on reg_notifier() Drivers may need more information than just who set the last regulatory domain, as such lets just pass the last regulatory_request receipt. To do this we need to move out to headers struct regulatory_request, and enum environment_cap. While at it lets add documentation for enum environment_cap. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- include/net/cfg80211.h | 45 ++++++++++++++++++++++++++++++++++++++++++ include/net/wireless.h | 3 ++- net/wireless/reg.c | 34 +------------------------------ net/wireless/reg.h | 7 ------- 4 files changed, 48 insertions(+), 41 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index f19c3e16366..dd1fd51638f 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -357,6 +357,51 @@ enum reg_set_by { REGDOM_SET_BY_COUNTRY_IE, }; +/** + * enum environment_cap - Environment parsed from country IE + * @ENVIRON_ANY: indicates country IE applies to both indoor and + * outdoor operation. + * @ENVIRON_INDOOR: indicates country IE applies only to indoor operation + * @ENVIRON_OUTDOOR: indicates country IE applies only to outdoor operation + */ +enum environment_cap { + ENVIRON_ANY, + ENVIRON_INDOOR, + ENVIRON_OUTDOOR, +}; + +/** + * struct regulatory_request - receipt of last regulatory request + * + * @wiphy: this is set if this request's initiator is + * %REGDOM_SET_BY_COUNTRY_IE or %REGDOM_SET_BY_DRIVER. This + * can be used by the wireless core to deal with conflicts + * and potentially inform users of which devices specifically + * cased the conflicts. + * @initiator: indicates who sent this request, could be any of + * of those set in reg_set_by, %REGDOM_SET_BY_* + * @alpha2: the ISO / IEC 3166 alpha2 country code of the requested + * regulatory domain. We have a few special codes: + * 00 - World regulatory domain + * 99 - built by driver but a specific alpha2 cannot be determined + * 98 - result of an intersection between two regulatory domains + * @intersect: indicates whether the wireless core should intersect + * the requested regulatory domain with the presently set regulatory + * domain. + * @country_ie_checksum: checksum of the last processed and accepted + * country IE + * @country_ie_env: lets us know if the AP is telling us we are outdoor, + * indoor, or if it doesn't matter + */ +struct regulatory_request { + struct wiphy *wiphy; + enum reg_set_by initiator; + char alpha2[2]; + bool intersect; + u32 country_ie_checksum; + enum environment_cap country_ie_env; +}; + struct ieee80211_freq_range { u32 start_freq_khz; u32 end_freq_khz; diff --git a/include/net/wireless.h b/include/net/wireless.h index c3f6e462ec2..9c19764a484 100644 --- a/include/net/wireless.h +++ b/include/net/wireless.h @@ -213,7 +213,8 @@ struct wiphy { struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS]; /* Lets us get back the wiphy on the callback */ - int (*reg_notifier)(struct wiphy *wiphy, enum reg_set_by setby); + int (*reg_notifier)(struct wiphy *wiphy, + struct regulatory_request *request); /* fields below are read-only, assigned by cfg80211 */ diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 81acb07f1d4..cad4daadba0 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -42,38 +42,6 @@ #include "core.h" #include "reg.h" -/** - * struct regulatory_request - receipt of last regulatory request - * - * @wiphy: this is set if this request's initiator is - * %REGDOM_SET_BY_COUNTRY_IE or %REGDOM_SET_BY_DRIVER. This - * can be used by the wireless core to deal with conflicts - * and potentially inform users of which devices specifically - * cased the conflicts. - * @initiator: indicates who sent this request, could be any of - * of those set in reg_set_by, %REGDOM_SET_BY_* - * @alpha2: the ISO / IEC 3166 alpha2 country code of the requested - * regulatory domain. We have a few special codes: - * 00 - World regulatory domain - * 99 - built by driver but a specific alpha2 cannot be determined - * 98 - result of an intersection between two regulatory domains - * @intersect: indicates whether the wireless core should intersect - * the requested regulatory domain with the presently set regulatory - * domain. - * @country_ie_checksum: checksum of the last processed and accepted - * country IE - * @country_ie_env: lets us know if the AP is telling us we are outdoor, - * indoor, or if it doesn't matter - */ -struct regulatory_request { - struct wiphy *wiphy; - enum reg_set_by initiator; - char alpha2[2]; - bool intersect; - u32 country_ie_checksum; - enum environment_cap country_ie_env; -}; - /* Receipt of information from last regulatory request */ static struct regulatory_request *last_request; @@ -951,7 +919,7 @@ void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby) handle_band(wiphy, band); } if (wiphy->reg_notifier) - wiphy->reg_notifier(wiphy, setby); + wiphy->reg_notifier(wiphy, last_request); } static void handle_channel_custom(struct wiphy *wiphy, diff --git a/net/wireless/reg.h b/net/wireless/reg.h index a76ea3ff7cd..eb1dd5bc9b2 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h @@ -11,13 +11,6 @@ void regulatory_exit(void); int set_regdom(const struct ieee80211_regdomain *rd); -enum environment_cap { - ENVIRON_ANY, - ENVIRON_INDOOR, - ENVIRON_OUTDOOR, -}; - - /** * __regulatory_hint - hint to the wireless core a regulatory domain * @wiphy: if the hint comes from country information from an AP, this -- GitLab From f976376de0d6a9697fb635369f12ae00251f4566 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 22 Jan 2009 15:05:52 -0800 Subject: [PATCH 0924/4982] cfg80211: Allow for strict regulatory settings This allows drivers to request strict regulatory settings to be applied to its devices. This is desirable for devices where proper calibration and compliance can only be gauranteed for for the device's programmed regulatory domain. Regulatory domain settings will be ignored until the device's own regulatory domain is properly configured. If no regulatory domain is received only the world regulatory domain will be applied -- if OLD_REG (default to "US") is not enabled. If OLD_REG behaviour is not acceptable to drivers they must update their wiphy with a custom reuglatory prior to wiphy registration. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- include/net/wireless.h | 10 ++++++++++ net/wireless/reg.c | 28 +++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/include/net/wireless.h b/include/net/wireless.h index 9c19764a484..a42c1562d52 100644 --- a/include/net/wireless.h +++ b/include/net/wireless.h @@ -186,6 +186,15 @@ struct ieee80211_supported_band { * ISO / IEC 3166 alpha2 it belongs to. When this is enabled * we will disregard the first regulatory hint (when the * initiator is %REGDOM_SET_BY_CORE). + * @strict_regulatory: tells us the driver for this device will ignore + * regulatory domain settings until it gets its own regulatory domain + * via its regulatory_hint(). After its gets its own regulatory domain + * it will only allow further regulatory domain settings to further + * enhance compliance. For example if channel 13 and 14 are disabled + * by this regulatory domain no user regulatory domain can enable these + * channels at a later time. This can be used for devices which do not + * have calibration information gauranteed for frequencies or settings + * outside of its regulatory domain. * @reg_notifier: the driver's regulatory notification callback * @regd: the driver's regulatory domain, if one was requested via * the regulatory_hint() API. This can be used by the driver @@ -202,6 +211,7 @@ struct wiphy { u16 interface_modes; bool custom_regulatory; + bool strict_regulatory; /* If multiple wiphys are registered and you're handed e.g. * a regular netdev with assigned ieee80211_ptr, you won't diff --git a/net/wireless/reg.c b/net/wireless/reg.c index cad4daadba0..89e0d8b3cf1 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -867,6 +867,22 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, power_rule = ®_rule->power_rule; + if (last_request->initiator == REGDOM_SET_BY_DRIVER && + last_request->wiphy && last_request->wiphy == wiphy && + last_request->wiphy->strict_regulatory) { + /* This gaurantees the driver's requested regulatory domain + * will always be used as a base for further regulatory + * settings */ + chan->flags = chan->orig_flags = + map_regdom_flags(reg_rule->flags); + chan->max_antenna_gain = chan->orig_mag = + (int) MBI_TO_DBI(power_rule->max_antenna_gain); + chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth); + chan->max_power = chan->orig_mpwr = + (int) MBM_TO_DBM(power_rule->max_eirp); + return; + } + chan->flags = flags | map_regdom_flags(reg_rule->flags); chan->max_antenna_gain = min(chan->orig_mag, (int) MBI_TO_DBI(power_rule->max_antenna_gain)); @@ -897,6 +913,11 @@ static bool ignore_reg_update(struct wiphy *wiphy, enum reg_set_by setby) if (setby == REGDOM_SET_BY_CORE && wiphy->custom_regulatory) return true; + /* wiphy->regd will be set once the device has its own + * desired regulatory domain set */ + if (wiphy->strict_regulatory && !wiphy->regd && + !is_world_regdom(last_request->alpha2)) + return true; return false; } @@ -1155,10 +1176,15 @@ new_request: void regulatory_hint(struct wiphy *wiphy, const char *alpha2) { + int r; BUG_ON(!alpha2); mutex_lock(&cfg80211_drv_mutex); - __regulatory_hint(wiphy, REGDOM_SET_BY_DRIVER, alpha2, 0, ENVIRON_ANY); + r = __regulatory_hint(wiphy, REGDOM_SET_BY_DRIVER, + alpha2, 0, ENVIRON_ANY); + /* This is required so that the orig_* parameters are saved */ + if (r == -EALREADY && wiphy->strict_regulatory) + wiphy_update_regulatory(wiphy, REGDOM_SET_BY_DRIVER); mutex_unlock(&cfg80211_drv_mutex); } EXPORT_SYMBOL(regulatory_hint); -- GitLab From 9a95371aa26e3cb9fb1340362912000088ff3c3e Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 22 Jan 2009 15:05:53 -0800 Subject: [PATCH 0925/4982] mac80211: allow mac80211 drivers to get to struct ieee80211_hw from wiphy If a driver is given a wiphy and it wants to get to its private mac80211 driver area it can use wiphy_to_ieee80211_hw() to get first to its ieee80211_hw and then access the private structure via hw->priv. The wiphy_priv() is already being used internally by mac80211 and drivers should not use this. This can be helpful in a drivers reg_notifier(). Signed-off-by: Luis R. Rodriguez Acked-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 13 +++++++++++++ net/mac80211/util.c | 9 +++++++++ 2 files changed, 22 insertions(+) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 35643c55827..c1e8261e899 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -989,6 +989,19 @@ struct ieee80211_hw { u8 max_rate_tries; }; +/** + * wiphy_to_ieee80211_hw - return a mac80211 driver hw struct from a wiphy + * + * @wiphy: the &struct wiphy which we want to query + * + * mac80211 drivers can use this to get to their respective + * &struct ieee80211_hw. Drivers wishing to get to their own private + * structure can then access it via hw->priv. Note that mac802111 drivers should + * not use wiphy_priv() to try to get their private driver structure as this + * is already used internally by mac80211. + */ +struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy); + /** * SET_IEEE80211_DEV - set device for 802.11 hardware * diff --git a/net/mac80211/util.c b/net/mac80211/util.c index ede96c4fea2..fc30f2940e1 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -41,6 +41,15 @@ const unsigned char rfc1042_header[] __aligned(2) = const unsigned char bridge_tunnel_header[] __aligned(2) = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; +struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy) +{ + struct ieee80211_local *local; + BUG_ON(!wiphy); + + local = wiphy_priv(wiphy); + return &local->hw; +} +EXPORT_SYMBOL(wiphy_to_ieee80211_hw); u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, enum nl80211_iftype type) -- GitLab From 24ed1da1337b92e3b0a89f2c2b7cd33b9a8fcb62 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 22 Jan 2009 15:05:54 -0800 Subject: [PATCH 0926/4982] cfg80211: allow users to help a driver's compliance Let users be more compliant if so desired. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 89e0d8b3cf1..af9132cea93 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -764,8 +764,9 @@ static int freq_reg_info_regd(struct wiphy *wiphy, regd = custom_regd ? custom_regd : cfg80211_regdomain; /* Follow the driver's regulatory domain, if present, unless a country - * IE has been processed */ + * IE has been processed or a user wants to help complaince further */ if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE && + last_request->initiator != REGDOM_SET_BY_USER && wiphy->regd) regd = wiphy->regd; -- GitLab From 5f8e077c0adc0dc7cfad64cdc05276e1961a1394 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 22 Jan 2009 15:16:48 -0800 Subject: [PATCH 0927/4982] ath9k: simplify regulatory code Now that cfg80211 has its own regulatory infrastructure we can condense ath9k's regulatory code considerably. We only keep data we need to provide our own regulatory_hint(), reg_notifier() and information necessary for calibration. Atheros hardware supports 12 world regulatory domains, since these are custom we apply them through the the new wiphy_apply_custom_regulatory(). Although we have 12 we can consolidate these into 5 structures based on frequency and apply a different set of flags that differentiate them on a case by case basis through the reg_notifier(). If CRDA is not found our own custom world regulatory domain is applied, this is identical to cfg80211's except we enable passive scan on most frequencies. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ath9k.h | 44 +- drivers/net/wireless/ath9k/calib.c | 41 +- drivers/net/wireless/ath9k/core.h | 1 - drivers/net/wireless/ath9k/hw.c | 63 +- drivers/net/wireless/ath9k/main.c | 263 +-- drivers/net/wireless/ath9k/regd.c | 1188 ++++--------- drivers/net/wireless/ath9k/regd.h | 181 +- drivers/net/wireless/ath9k/regd_common.h | 2058 ++++------------------ 8 files changed, 809 insertions(+), 3030 deletions(-) diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index 0b305b832a8..f158cba0140 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -457,22 +457,12 @@ struct ath9k_channel { struct ieee80211_channel *chan; u16 channel; u32 channelFlags; - u8 privFlags; - int8_t maxRegTxPower; - int8_t maxTxPower; - int8_t minTxPower; u32 chanmode; int32_t CalValid; bool oneTimeCalsDone; int8_t iCoff; int8_t qCoff; int16_t rawNoiseFloor; - int8_t antennaMax; - u32 regDmnFlags; - u32 conformanceTestLimit[3]; /* 0:11a, 1: 11b, 2:11g */ -#ifdef ATH_NF_PER_CHAN - struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; -#endif }; #define IS_CHAN_A(_c) ((((_c)->channelFlags & CHANNEL_A) == CHANNEL_A) || \ @@ -500,7 +490,6 @@ struct ath9k_channel { ((_c)->chanmode == CHANNEL_G_HT40MINUS)) #define IS_CHAN_HT(_c) (IS_CHAN_HT20((_c)) || IS_CHAN_HT40((_c))) -#define IS_CHAN_IN_PUBLIC_SAFETY_BAND(_c) ((_c) > 4940 && (_c) < 4990) #define IS_CHAN_A_5MHZ_SPACED(_c) \ ((((_c)->channelFlags & CHANNEL_5GHZ) != 0) && \ (((_c)->channel % 20) != 0) && \ @@ -790,15 +779,13 @@ struct ath_hal { u16 ah_currentRD; u16 ah_currentRDExt; u16 ah_currentRDInUse; - u16 ah_currentRD5G; - u16 ah_currentRD2G; - char ah_iso[4]; + char alpha2[2]; + struct reg_dmn_pair_mapping *regpair; enum ath9k_power_mode ah_power_mode; enum ath9k_power_mode ah_restore_mode; - struct ath9k_channel ah_channels[150]; + struct ath9k_channel ah_channels[38]; struct ath9k_channel *ah_curchan; - u32 ah_nchan; bool ah_isPciExpress; u16 ah_txTrigLevel; @@ -807,10 +794,7 @@ struct ath_hal { u32 ah_rfkill_polarity; u32 ah_btactive_gpio; u32 ah_wlanactive_gpio; - -#ifndef ATH_NF_PER_CHAN struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; -#endif bool sw_mgmt_crypto; }; @@ -825,8 +809,6 @@ struct ath_rate_table; /* Helpers */ -enum wireless_mode ath9k_hw_chan2wmode(struct ath_hal *ah, - const struct ath9k_channel *chan); bool ath9k_hw_wait(struct ath_hal *ah, u32 reg, u32 mask, u32 val); u32 ath9k_hw_reverse_bits(u32 val, u32 n); bool ath9k_get_channel_edges(struct ath_hal *ah, @@ -836,7 +818,6 @@ u16 ath9k_hw_computetxtime(struct ath_hal *ah, struct ath_rate_table *rates, u32 frameLen, u16 rateix, bool shortPreamble); -u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags); void ath9k_hw_get_channel_centers(struct ath_hal *ah, struct ath9k_channel *chan, struct chan_centers *centers); @@ -924,17 +905,18 @@ bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us); void ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode); /* Regulatory */ +u16 ath9k_regd_get_rd(struct ath_hal *ah); +bool ath9k_is_world_regd(struct ath_hal *ah); +const struct ieee80211_regdomain *ath9k_world_regdomain(struct ath_hal *ah); +const struct ieee80211_regdomain *ath9k_default_world_regdomain(void); + +void ath9k_reg_apply_world_flags(struct wiphy *wiphy, enum reg_set_by setby); +void ath9k_reg_apply_radar_flags(struct wiphy *wiphy); -bool ath9k_regd_is_public_safety_sku(struct ath_hal *ah); -struct ath9k_channel* ath9k_regd_check_channel(struct ath_hal *ah, - const struct ath9k_channel *c); +int ath9k_regd_init(struct ath_hal *ah); +bool ath9k_regd_is_eeprom_valid(struct ath_hal *ah); u32 ath9k_regd_get_ctl(struct ath_hal *ah, struct ath9k_channel *chan); -u32 ath9k_regd_get_antenna_allowed(struct ath_hal *ah, - struct ath9k_channel *chan); -bool ath9k_regd_init_channels(struct ath_hal *ah, - u32 maxchans, u32 *nchans, u8 *regclassids, - u32 maxregids, u32 *nregids, u16 cc, - bool enableOutdoor, bool enableExtendedChannels); +int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request); /* ANI */ diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c index 8e073d6513d..d16f9fe48a9 100644 --- a/drivers/net/wireless/ath9k/calib.c +++ b/drivers/net/wireless/ath9k/calib.c @@ -625,11 +625,7 @@ void ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan) else chainmask = 0x3F; -#ifdef ATH_NF_PER_CHAN - h = chan->nfCalHist; -#else h = ah->nfCalHist; -#endif for (i = 0; i < NUM_NF_READINGS; i++) { if (chainmask & (1 << i)) { @@ -697,11 +693,7 @@ int16_t ath9k_hw_getnf(struct ath_hal *ah, } } -#ifdef ATH_NF_PER_CHAN - h = chan->nfCalHist; -#else h = ah->nfCalHist; -#endif ath9k_hw_update_nfcal_hist_buffer(h, nfarray); chan->rawNoiseFloor = h[0].privNF; @@ -728,20 +720,12 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hal *ah) s16 ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan) { - struct ath9k_channel *ichan; s16 nf; - ichan = ath9k_regd_check_channel(ah, chan); - if (ichan == NULL) { - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "invalid channel %u/0x%x; no mapping\n", - chan->channel, chan->channelFlags); - return ATH_DEFAULT_NOISE_FLOOR; - } - if (ichan->rawNoiseFloor == 0) + if (chan->rawNoiseFloor == 0) nf = -96; else - nf = ichan->rawNoiseFloor; + nf = chan->rawNoiseFloor; if (!ath9k_hw_nf_in_range(ah, nf)) nf = ATH_DEFAULT_NOISE_FLOOR; @@ -755,21 +739,13 @@ bool ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan, { struct ath_hal_5416 *ahp = AH5416(ah); struct hal_cal_list *currCal = ahp->ah_cal_list_curr; - struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan); *isCalDone = true; - if (ichan == NULL) { - DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, - "invalid channel %u/0x%x; no mapping\n", - chan->channel, chan->channelFlags); - return false; - } - if (currCal && (currCal->calState == CAL_RUNNING || currCal->calState == CAL_WAITING)) { - ath9k_hw_per_calibration(ah, ichan, rxchainmask, currCal, + ath9k_hw_per_calibration(ah, chan, rxchainmask, currCal, isCalDone); if (*isCalDone) { ahp->ah_cal_list_curr = currCal = currCal->calNext; @@ -782,14 +758,12 @@ bool ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan, } if (longcal) { - ath9k_hw_getnf(ah, ichan); + ath9k_hw_getnf(ah, chan); ath9k_hw_loadnf(ah, ah->ah_curchan); ath9k_hw_start_nfcal(ah); - if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) { - chan->channelFlags |= CHANNEL_CW_INT; - ichan->channelFlags &= ~CHANNEL_CW_INT; - } + if (chan->channelFlags & CHANNEL_CW_INT) + chan->channelFlags &= ~CHANNEL_CW_INT; } return true; @@ -894,7 +868,6 @@ bool ath9k_hw_init_cal(struct ath_hal *ah, struct ath9k_channel *chan) { struct ath_hal_5416 *ahp = AH5416(ah); - struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan); REG_WRITE(ah, AR_PHY_AGC_CONTROL, REG_READ(ah, AR_PHY_AGC_CONTROL) | @@ -942,7 +915,7 @@ bool ath9k_hw_init_cal(struct ath_hal *ah, ath9k_hw_reset_calibration(ah, ahp->ah_cal_list_curr); } - ichan->CalValid = 0; + chan->CalValid = 0; return true; } diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index 0f50767712a..29251f8dabb 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -724,7 +724,6 @@ struct ath_softc { struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX]; struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX]; struct ath_rate_table *cur_rate_table; - struct ieee80211_channel channels[IEEE80211_NUM_BANDS][ATH_CHAN_MAX]; struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; struct ath_led radio_led; struct ath_led assoc_led; diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 65e0d80f3b4..f2922bab776 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -187,46 +187,6 @@ u16 ath9k_hw_computetxtime(struct ath_hal *ah, return txTime; } -u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags) -{ - if (flags & CHANNEL_2GHZ) { - if (freq == 2484) - return 14; - if (freq < 2484) - return (freq - 2407) / 5; - else - return 15 + ((freq - 2512) / 20); - } else if (flags & CHANNEL_5GHZ) { - if (ath9k_regd_is_public_safety_sku(ah) && - IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) { - return ((freq * 10) + - (((freq % 5) == 2) ? 5 : 0) - 49400) / 5; - } else if ((flags & CHANNEL_A) && (freq <= 5000)) { - return (freq - 4000) / 5; - } else { - return (freq - 5000) / 5; - } - } else { - if (freq == 2484) - return 14; - if (freq < 2484) - return (freq - 2407) / 5; - if (freq < 5000) { - if (ath9k_regd_is_public_safety_sku(ah) - && IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) { - return ((freq * 10) + - (((freq % 5) == - 2) ? 5 : 0) - 49400) / 5; - } else if (freq > 4900) { - return (freq - 4000) / 5; - } else { - return 15 + ((freq - 2512) / 20); - } - } - return (freq - 5000) / 5; - } -} - void ath9k_hw_get_channel_centers(struct ath_hal *ah, struct ath9k_channel *chan, struct chan_centers *centers) @@ -1270,6 +1230,7 @@ static int ath9k_hw_process_ini(struct ath_hal *ah, { int i, regWrites = 0; struct ath_hal_5416 *ahp = AH5416(ah); + struct ieee80211_channel *channel = chan->chan; u32 modesIndex, freqIndex; int status; @@ -1374,9 +1335,8 @@ static int ath9k_hw_process_ini(struct ath_hal *ah, status = ath9k_hw_set_txpower(ah, chan, ath9k_regd_get_ctl(ah, chan), - ath9k_regd_get_antenna_allowed(ah, - chan), - chan->maxRegTxPower * 2, + channel->max_antenna_gain * 2, + channel->max_power * 2, min((u32) MAX_RATE_POWER, (u32) ah->ah_powerLimit)); if (status != 0) { @@ -1669,6 +1629,7 @@ static bool ath9k_hw_channel_change(struct ath_hal *ah, struct ath9k_channel *chan, enum ath9k_ht_macmode macmode) { + struct ieee80211_channel *channel = chan->chan; u32 synthDelay, qnum; for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { @@ -1705,8 +1666,8 @@ static bool ath9k_hw_channel_change(struct ath_hal *ah, if (ath9k_hw_set_txpower(ah, chan, ath9k_regd_get_ctl(ah, chan), - ath9k_regd_get_antenna_allowed(ah, chan), - chan->maxRegTxPower * 2, + channel->max_antenna_gain * 2, + channel->max_power * 2, min((u32) MAX_RATE_POWER, (u32) ah->ah_powerLimit)) != 0) { DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, @@ -2209,13 +2170,6 @@ int ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan, ahp->ah_rxchainmask &= 0x3; } - if (ath9k_regd_check_channel(ah, chan) == NULL) { - DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, - "invalid channel %u/0x%x; no mapping\n", - chan->channel, chan->channelFlags); - return -EINVAL; - } - if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) return -EIO; @@ -3718,13 +3672,14 @@ bool ath9k_hw_disable(struct ath_hal *ah) bool ath9k_hw_set_txpowerlimit(struct ath_hal *ah, u32 limit) { struct ath9k_channel *chan = ah->ah_curchan; + struct ieee80211_channel *channel = chan->chan; ah->ah_powerLimit = min(limit, (u32) MAX_RATE_POWER); if (ath9k_hw_set_txpower(ah, chan, ath9k_regd_get_ctl(ah, chan), - ath9k_regd_get_antenna_allowed(ah, chan), - chan->maxRegTxPower * 2, + channel->max_antenna_gain * 2, + channel->max_power * 2, min((u32) MAX_RATE_POWER, (u32) ah->ah_powerLimit)) != 0) return false; diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index b494a0d7e8b..561a2c3adbb 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -28,6 +28,77 @@ MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards."); MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards"); MODULE_LICENSE("Dual BSD/GPL"); +/* We use the hw_value as an index into our private channel structure */ + +#define CHAN2G(_freq, _idx) { \ + .center_freq = (_freq), \ + .hw_value = (_idx), \ + .max_power = 30, \ +} + +#define CHAN5G(_freq, _idx) { \ + .band = IEEE80211_BAND_5GHZ, \ + .center_freq = (_freq), \ + .hw_value = (_idx), \ + .max_power = 30, \ +} + +/* Some 2 GHz radios are actually tunable on 2312-2732 + * on 5 MHz steps, we support the channels which we know + * we have calibration data for all cards though to make + * this static */ +static struct ieee80211_channel ath9k_2ghz_chantable[] = { + CHAN2G(2412, 0), /* Channel 1 */ + CHAN2G(2417, 1), /* Channel 2 */ + CHAN2G(2422, 2), /* Channel 3 */ + CHAN2G(2427, 3), /* Channel 4 */ + CHAN2G(2432, 4), /* Channel 5 */ + CHAN2G(2437, 5), /* Channel 6 */ + CHAN2G(2442, 6), /* Channel 7 */ + CHAN2G(2447, 7), /* Channel 8 */ + CHAN2G(2452, 8), /* Channel 9 */ + CHAN2G(2457, 9), /* Channel 10 */ + CHAN2G(2462, 10), /* Channel 11 */ + CHAN2G(2467, 11), /* Channel 12 */ + CHAN2G(2472, 12), /* Channel 13 */ + CHAN2G(2484, 13), /* Channel 14 */ +}; + +/* Some 5 GHz radios are actually tunable on XXXX-YYYY + * on 5 MHz steps, we support the channels which we know + * we have calibration data for all cards though to make + * this static */ +static struct ieee80211_channel ath9k_5ghz_chantable[] = { + /* _We_ call this UNII 1 */ + CHAN5G(5180, 14), /* Channel 36 */ + CHAN5G(5200, 15), /* Channel 40 */ + CHAN5G(5220, 16), /* Channel 44 */ + CHAN5G(5240, 17), /* Channel 48 */ + /* _We_ call this UNII 2 */ + CHAN5G(5260, 18), /* Channel 52 */ + CHAN5G(5280, 19), /* Channel 56 */ + CHAN5G(5300, 20), /* Channel 60 */ + CHAN5G(5320, 21), /* Channel 64 */ + /* _We_ call this "Middle band" */ + CHAN5G(5500, 22), /* Channel 100 */ + CHAN5G(5520, 23), /* Channel 104 */ + CHAN5G(5540, 24), /* Channel 108 */ + CHAN5G(5560, 25), /* Channel 112 */ + CHAN5G(5580, 26), /* Channel 116 */ + CHAN5G(5600, 27), /* Channel 120 */ + CHAN5G(5620, 28), /* Channel 124 */ + CHAN5G(5640, 29), /* Channel 128 */ + CHAN5G(5660, 30), /* Channel 132 */ + CHAN5G(5680, 31), /* Channel 136 */ + CHAN5G(5700, 32), /* Channel 140 */ + /* _We_ call this UNII 3 */ + CHAN5G(5745, 33), /* Channel 149 */ + CHAN5G(5765, 34), /* Channel 153 */ + CHAN5G(5785, 35), /* Channel 157 */ + CHAN5G(5805, 36), /* Channel 161 */ + CHAN5G(5825, 37), /* Channel 165 */ +}; + static void ath_cache_conf_rate(struct ath_softc *sc, struct ieee80211_conf *conf) { @@ -152,75 +223,6 @@ static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band) } } -static int ath_setup_channels(struct ath_softc *sc) -{ - struct ath_hal *ah = sc->sc_ah; - int nchan, i, a = 0, b = 0; - u8 regclassids[ATH_REGCLASSIDS_MAX]; - u32 nregclass = 0; - struct ieee80211_supported_band *band_2ghz; - struct ieee80211_supported_band *band_5ghz; - struct ieee80211_channel *chan_2ghz; - struct ieee80211_channel *chan_5ghz; - struct ath9k_channel *c; - - /* Fill in ah->ah_channels */ - if (!ath9k_regd_init_channels(ah, ATH_CHAN_MAX, (u32 *)&nchan, - regclassids, ATH_REGCLASSIDS_MAX, - &nregclass, CTRY_DEFAULT, false, 1)) { - u32 rd = ah->ah_currentRD; - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to collect channel list; " - "regdomain likely %u country code %u\n", - rd, CTRY_DEFAULT); - return -EINVAL; - } - - band_2ghz = &sc->sbands[IEEE80211_BAND_2GHZ]; - band_5ghz = &sc->sbands[IEEE80211_BAND_5GHZ]; - chan_2ghz = sc->channels[IEEE80211_BAND_2GHZ]; - chan_5ghz = sc->channels[IEEE80211_BAND_5GHZ]; - - for (i = 0; i < nchan; i++) { - c = &ah->ah_channels[i]; - if (IS_CHAN_2GHZ(c)) { - chan_2ghz[a].band = IEEE80211_BAND_2GHZ; - chan_2ghz[a].center_freq = c->channel; - chan_2ghz[a].max_power = c->maxTxPower; - c->chan = &chan_2ghz[a]; - - if (c->privFlags & CHANNEL_DISALLOW_ADHOC) - chan_2ghz[a].flags |= IEEE80211_CHAN_NO_IBSS; - if (c->channelFlags & CHANNEL_PASSIVE) - chan_2ghz[a].flags |= IEEE80211_CHAN_PASSIVE_SCAN; - - band_2ghz->n_channels = ++a; - - DPRINTF(sc, ATH_DBG_CONFIG, "2MHz channel: %d, " - "channelFlags: 0x%x\n", - c->channel, c->channelFlags); - } else if (IS_CHAN_5GHZ(c)) { - chan_5ghz[b].band = IEEE80211_BAND_5GHZ; - chan_5ghz[b].center_freq = c->channel; - chan_5ghz[b].max_power = c->maxTxPower; - c->chan = &chan_5ghz[a]; - - if (c->privFlags & CHANNEL_DISALLOW_ADHOC) - chan_5ghz[b].flags |= IEEE80211_CHAN_NO_IBSS; - if (c->channelFlags & CHANNEL_PASSIVE) - chan_5ghz[b].flags |= IEEE80211_CHAN_PASSIVE_SCAN; - - band_5ghz->n_channels = ++b; - - DPRINTF(sc, ATH_DBG_CONFIG, "5MHz channel: %d, " - "channelFlags: 0x%x\n", - c->channel, c->channelFlags); - } - } - - return 0; -} - /* * Set/change channels. If the channel is really being changed, it's done * by reseting the chip. To accomplish this we must first cleanup any pending @@ -582,19 +584,6 @@ irqreturn_t ath_isr(int irq, void *dev) return IRQ_HANDLED; } -static int ath_get_channel(struct ath_softc *sc, - struct ieee80211_channel *chan) -{ - int i; - - for (i = 0; i < sc->sc_ah->ah_nchan; i++) { - if (sc->sc_ah->ah_channels[i].channel == chan->center_freq) - return i; - } - - return -1; -} - static u32 ath_get_extchanmode(struct ath_softc *sc, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type) @@ -1349,16 +1338,12 @@ static int ath_init(u16 devid, struct ath_softc *sc) for (i = 0; i < sc->sc_keymax; i++) ath9k_hw_keyreset(ah, (u16) i); - /* Collect the channel list using the default country code */ - - error = ath_setup_channels(sc); - if (error) + if (ath9k_regd_init(sc->sc_ah)) goto bad; /* default to MONITOR mode */ sc->sc_ah->ah_opmode = NL80211_IFTYPE_MONITOR; - /* Setup rate tables */ ath_rate_attach(sc); @@ -1490,18 +1475,20 @@ static int ath_init(u16 devid, struct ath_softc *sc) /* setup channels and rates */ - sc->sbands[IEEE80211_BAND_2GHZ].channels = - sc->channels[IEEE80211_BAND_2GHZ]; + sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable; sc->sbands[IEEE80211_BAND_2GHZ].bitrates = sc->rates[IEEE80211_BAND_2GHZ]; sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; + sc->sbands[IEEE80211_BAND_2GHZ].n_channels = + ARRAY_SIZE(ath9k_2ghz_chantable); if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) { - sc->sbands[IEEE80211_BAND_5GHZ].channels = - sc->channels[IEEE80211_BAND_5GHZ]; + sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable; sc->sbands[IEEE80211_BAND_5GHZ].bitrates = sc->rates[IEEE80211_BAND_5GHZ]; sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; + sc->sbands[IEEE80211_BAND_5GHZ].n_channels = + ARRAY_SIZE(ath9k_5ghz_chantable); } if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_BT_COEX) @@ -1550,6 +1537,9 @@ int ath_attach(u16 devid, struct ath_softc *sc) BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); + hw->wiphy->reg_notifier = ath9k_reg_notifier; + hw->wiphy->strict_regulatory = true; + hw->queues = 4; hw->max_rates = 4; hw->max_rate_tries = ATH_11N_TXMAXTRY; @@ -1588,11 +1578,36 @@ int ath_attach(u16 devid, struct ath_softc *sc) goto detach; #endif + if (ath9k_is_world_regd(sc->sc_ah)) { + /* Anything applied here (prior to wiphy registratoin) gets + * saved on the wiphy orig_* parameters */ + const struct ieee80211_regdomain *regd = + ath9k_world_regdomain(sc->sc_ah); + hw->wiphy->custom_regulatory = true; + hw->wiphy->strict_regulatory = false; + wiphy_apply_custom_regulatory(sc->hw->wiphy, regd); + ath9k_reg_apply_radar_flags(hw->wiphy); + ath9k_reg_apply_world_flags(hw->wiphy, REGDOM_SET_BY_INIT); + } else { + /* This gets applied in the case of the absense of CRDA, + * its our own custom world regulatory domain, similar to + * cfg80211's but we enable passive scanning */ + const struct ieee80211_regdomain *regd = + ath9k_default_world_regdomain(); + wiphy_apply_custom_regulatory(sc->hw->wiphy, regd); + ath9k_reg_apply_radar_flags(hw->wiphy); + ath9k_reg_apply_world_flags(hw->wiphy, REGDOM_SET_BY_INIT); + } + error = ieee80211_register_hw(hw); + if (!ath9k_is_world_regd(sc->sc_ah)) + regulatory_hint(hw->wiphy, sc->sc_ah->alpha2); + /* Initialize LED control */ ath_init_leds(sc); + return 0; detach: ath_detach(sc); @@ -1818,6 +1833,37 @@ int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc) return qnum; } +/* XXX: Remove me once we don't depend on ath9k_channel for all + * this redundant data */ +static void ath9k_update_ichannel(struct ath_softc *sc, + struct ath9k_channel *ichan) +{ + struct ieee80211_hw *hw = sc->hw; + struct ieee80211_channel *chan = hw->conf.channel; + struct ieee80211_conf *conf = &hw->conf; + + ichan->channel = chan->center_freq; + ichan->chan = chan; + + if (chan->band == IEEE80211_BAND_2GHZ) { + ichan->chanmode = CHANNEL_G; + ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM; + } else { + ichan->chanmode = CHANNEL_A; + ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; + } + + sc->tx_chan_width = ATH9K_HT_MACMODE_20; + + if (conf_is_ht(conf)) { + if (conf_is_ht40(conf)) + sc->tx_chan_width = ATH9K_HT_MACMODE_2040; + + ichan->chanmode = ath_get_extchanmode(sc, chan, + conf->channel_type); + } +} + /**********************/ /* mac80211 callbacks */ /**********************/ @@ -1834,16 +1880,10 @@ static int ath9k_start(struct ieee80211_hw *hw) /* setup initial channel */ - pos = ath_get_channel(sc, curchan); - if (pos == -1) { - DPRINTF(sc, ATH_DBG_FATAL, "Invalid channel: %d\n", curchan->center_freq); - return -EINVAL; - } + pos = curchan->hw_value; - sc->tx_chan_width = ATH9K_HT_MACMODE_20; - sc->sc_ah->ah_channels[pos].chanmode = - (curchan->band == IEEE80211_BAND_2GHZ) ? CHANNEL_G : CHANNEL_A; init_channel = &sc->sc_ah->ah_channels[pos]; + ath9k_update_ichannel(sc, init_channel); /* Reset SERDES registers */ ath9k_hw_configpcipowersave(sc->sc_ah, 0); @@ -2127,32 +2167,13 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { struct ieee80211_channel *curchan = hw->conf.channel; - int pos; + int pos = curchan->hw_value; DPRINTF(sc, ATH_DBG_CONFIG, "Set channel: %d MHz\n", curchan->center_freq); - pos = ath_get_channel(sc, curchan); - if (pos == -1) { - DPRINTF(sc, ATH_DBG_FATAL, "Invalid channel: %d\n", - curchan->center_freq); - mutex_unlock(&sc->mutex); - return -EINVAL; - } - - sc->tx_chan_width = ATH9K_HT_MACMODE_20; - sc->sc_ah->ah_channels[pos].chanmode = - (curchan->band == IEEE80211_BAND_2GHZ) ? - CHANNEL_G : CHANNEL_A; - - if (conf_is_ht(conf)) { - if (conf_is_ht40(conf)) - sc->tx_chan_width = ATH9K_HT_MACMODE_2040; - - sc->sc_ah->ah_channels[pos].chanmode = - ath_get_extchanmode(sc, curchan, - conf->channel_type); - } + /* XXX: remove me eventualy */ + ath9k_update_ichannel(sc, &sc->sc_ah->ah_channels[pos]); ath_update_chainmask(sc, conf_is_ht(conf)); diff --git a/drivers/net/wireless/ath9k/regd.c b/drivers/net/wireless/ath9k/regd.c index 64043e99fac..90f0c982430 100644 --- a/drivers/net/wireless/ath9k/regd.c +++ b/drivers/net/wireless/ath9k/regd.c @@ -21,174 +21,323 @@ #include "regd.h" #include "regd_common.h" -static int ath9k_regd_chansort(const void *a, const void *b) -{ - const struct ath9k_channel *ca = a; - const struct ath9k_channel *cb = b; - - return (ca->channel == cb->channel) ? - (ca->channelFlags & CHAN_FLAGS) - - (cb->channelFlags & CHAN_FLAGS) : ca->channel - cb->channel; -} +/* + * This is a set of common rules used by our world regulatory domains. + * We have 12 world regulatory domains. To save space we consolidate + * the regulatory domains in 5 structures by frequency and change + * the flags on our reg_notifier() on a case by case basis. + */ -static void -ath9k_regd_sort(void *a, u32 n, u32 size, ath_hal_cmp_t *cmp) -{ - u8 *aa = a; - u8 *ai, *t; - - for (ai = aa + size; --n >= 1; ai += size) - for (t = ai; t > aa; t -= size) { - u8 *u = t - size; - if (cmp(u, t) <= 0) - break; - swap_array(u, t, size); - } -} +/* Only these channels all allow active scan on all world regulatory domains */ +#define ATH9K_2GHZ_CH01_11 REG_RULE(2412-10, 2462+10, 40, 0, 20, 0) + +/* We enable active scan on these a case by case basis by regulatory domain */ +#define ATH9K_2GHZ_CH12_13 REG_RULE(2467-10, 2472+10, 40, 0, 20,\ + NL80211_RRF_PASSIVE_SCAN) +#define ATH9K_2GHZ_CH14 REG_RULE(2484-10, 2484+10, 40, 0, 20,\ + NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM) + +/* We allow IBSS on these on a case by case basis by regulatory domain */ +#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 40, 0, 30,\ + NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) +#define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 40, 0, 30,\ + NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) +#define ATH9K_5GHZ_5725_5850 REG_RULE(5725-10, 5850+10, 40, 0, 30,\ + NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) + +#define ATH9K_2GHZ_ALL ATH9K_2GHZ_CH01_11, \ + ATH9K_2GHZ_CH12_13, \ + ATH9K_2GHZ_CH14 + +#define ATH9K_5GHZ_ALL ATH9K_5GHZ_5150_5350, \ + ATH9K_5GHZ_5470_5850 +/* This one skips what we call "mid band" */ +#define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \ + ATH9K_5GHZ_5725_5850 + +/* Can be used for: + * 0x60, 0x61, 0x62 */ +static const struct ieee80211_regdomain ath9k_world_regdom_60_61_62 = { + .n_reg_rules = 5, + .alpha2 = "99", + .reg_rules = { + ATH9K_2GHZ_ALL, + ATH9K_5GHZ_ALL, + } +}; + +/* Can be used by 0x63 and 0x65 */ +static const struct ieee80211_regdomain ath9k_world_regdom_63_65 = { + .n_reg_rules = 4, + .alpha2 = "99", + .reg_rules = { + ATH9K_2GHZ_CH01_11, + ATH9K_2GHZ_CH12_13, + ATH9K_5GHZ_NO_MIDBAND, + } +}; + +/* Can be used by 0x64 only */ +static const struct ieee80211_regdomain ath9k_world_regdom_64 = { + .n_reg_rules = 3, + .alpha2 = "99", + .reg_rules = { + ATH9K_2GHZ_CH01_11, + ATH9K_5GHZ_NO_MIDBAND, + } +}; + +/* Can be used by 0x66 and 0x69 */ +static const struct ieee80211_regdomain ath9k_world_regdom_66_69 = { + .n_reg_rules = 3, + .alpha2 = "99", + .reg_rules = { + ATH9K_2GHZ_CH01_11, + ATH9K_5GHZ_ALL, + } +}; + +/* Can be used by 0x67, 0x6A and 0x68 */ +static const struct ieee80211_regdomain ath9k_world_regdom_67_68_6A = { + .n_reg_rules = 4, + .alpha2 = "99", + .reg_rules = { + ATH9K_2GHZ_CH01_11, + ATH9K_2GHZ_CH12_13, + ATH9K_5GHZ_ALL, + } +}; static u16 ath9k_regd_get_eepromRD(struct ath_hal *ah) { return ah->ah_currentRD & ~WORLDWIDE_ROAMING_FLAG; } -static bool ath9k_regd_is_chan_bm_zero(u64 *bitmask) +u16 ath9k_regd_get_rd(struct ath_hal *ah) { - int i; + return ath9k_regd_get_eepromRD(ah); +} - for (i = 0; i < BMLEN; i++) { - if (bitmask[i] != 0) - return false; - } - return true; +bool ath9k_is_world_regd(struct ath_hal *ah) +{ + return isWwrSKU(ah); } -static bool ath9k_regd_is_eeprom_valid(struct ath_hal *ah) +const struct ieee80211_regdomain *ath9k_default_world_regdomain(void) { - u16 rd = ath9k_regd_get_eepromRD(ah); - int i; + /* this is the most restrictive */ + return &ath9k_world_regdom_64; +} - if (rd & COUNTRY_ERD_FLAG) { - u16 cc = rd & ~COUNTRY_ERD_FLAG; - for (i = 0; i < ARRAY_SIZE(allCountries); i++) - if (allCountries[i].countryCode == cc) - return true; - } else { - for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) - if (regDomainPairs[i].regDmnEnum == rd) - return true; +const struct ieee80211_regdomain *ath9k_world_regdomain(struct ath_hal *ah) +{ + switch (ah->regpair->regDmnEnum) { + case 0x60: + case 0x61: + case 0x62: + return &ath9k_world_regdom_60_61_62; + case 0x63: + case 0x65: + return &ath9k_world_regdom_63_65; + case 0x64: + return &ath9k_world_regdom_64; + case 0x66: + case 0x69: + return &ath9k_world_regdom_66_69; + case 0x67: + case 0x68: + case 0x6A: + return &ath9k_world_regdom_67_68_6A; + default: + WARN_ON(1); + return ath9k_default_world_regdomain(); } - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "invalid regulatory domain/country code 0x%x\n", rd); - return false; } -static bool ath9k_regd_is_fcc_midband_supported(struct ath_hal *ah) +/* Enable adhoc on 5 GHz if allowed by 11d */ +static void ath9k_reg_apply_5ghz_adhoc_flags(struct wiphy *wiphy, + enum reg_set_by setby) { - u32 regcap; - - regcap = ah->ah_caps.reg_cap; + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct ath_softc *sc = hw->priv; + struct ieee80211_supported_band *sband; + const struct ieee80211_reg_rule *reg_rule; + struct ieee80211_channel *ch; + unsigned int i; + u32 bandwidth = 0; + int r; + + if (setby != REGDOM_SET_BY_COUNTRY_IE) + return; + if (!test_bit(ATH9K_MODE_11A, + sc->sc_ah->ah_caps.wireless_modes)) + return; - if (regcap & AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND) - return true; - else - return false; + sband = wiphy->bands[IEEE80211_BAND_5GHZ]; + for (i = 0; i < sband->n_channels; i++) { + ch = &sband->channels[i]; + r = freq_reg_info(wiphy, ch->center_freq, + &bandwidth, ®_rule); + if (r) + continue; + /* If 11d had a rule for this channel ensure we enable adhoc + * if it allows us to use it. Note that we would have disabled + * it by applying our static world regdomain by default during + * probe */ + if (!(reg_rule->flags & NL80211_RRF_NO_IBSS)) + ch->flags &= ~NL80211_RRF_NO_IBSS; + } } -static bool ath9k_regd_is_ccode_valid(struct ath_hal *ah, - u16 cc) +/* Allows active scan scan on Ch 12 and 13 */ +static void ath9k_reg_apply_active_scan_flags(struct wiphy *wiphy, + enum reg_set_by setby) { - u16 rd; - int i; - - if (cc == CTRY_DEFAULT) - return true; - if (cc == CTRY_DEBUG) - return true; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + const struct ieee80211_reg_rule *reg_rule; + u32 bandwidth = 0; + int r; + + /* Force passive scan on Channels 12-13 */ + sband = wiphy->bands[IEEE80211_BAND_2GHZ]; + + /* If no country IE has been received always enable active scan + * on these channels */ + if (setby != REGDOM_SET_BY_COUNTRY_IE) { + ch = &sband->channels[11]; /* CH 12 */ + if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) + ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + ch = &sband->channels[12]; /* CH 13 */ + if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) + ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + return; + } - rd = ath9k_regd_get_eepromRD(ah); - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "EEPROM regdomain 0x%x\n", rd); + /* If a country IE has been recieved check its rule for this + * channel first before enabling active scan. The passive scan + * would have been enforced by the initial probe processing on + * our custom regulatory domain. */ - if (rd & COUNTRY_ERD_FLAG) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "EEPROM setting is country code %u\n", - rd & ~COUNTRY_ERD_FLAG); - return cc == (rd & ~COUNTRY_ERD_FLAG); + ch = &sband->channels[11]; /* CH 12 */ + r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, ®_rule); + if (!r) { + if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) + if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) + ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; } - for (i = 0; i < ARRAY_SIZE(allCountries); i++) { - if (cc == allCountries[i].countryCode) { -#ifdef AH_SUPPORT_11D - if ((rd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) - return true; -#endif - if (allCountries[i].regDmnEnum == rd || - rd == DEBUG_REG_DMN || rd == NO_ENUMRD) - return true; - } + ch = &sband->channels[12]; /* CH 13 */ + r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, ®_rule); + if (!r) { + if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) + if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) + ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; } - return false; } -static void -ath9k_regd_get_wmodes_nreg(struct ath_hal *ah, - struct country_code_to_enum_rd *country, - struct regDomain *rd5GHz, - unsigned long *modes_allowed) +/* Always apply Radar/DFS rules on freq range 5260 MHz - 5700 MHz */ +void ath9k_reg_apply_radar_flags(struct wiphy *wiphy) { - bitmap_copy(modes_allowed, ah->ah_caps.wireless_modes, ATH9K_MODE_MAX); + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + unsigned int i; - if (test_bit(ATH9K_MODE_11G, ah->ah_caps.wireless_modes) && - (!country->allow11g)) - clear_bit(ATH9K_MODE_11G, modes_allowed); + if (!wiphy->bands[IEEE80211_BAND_5GHZ]) + return; - if (test_bit(ATH9K_MODE_11A, ah->ah_caps.wireless_modes) && - (ath9k_regd_is_chan_bm_zero(rd5GHz->chan11a))) - clear_bit(ATH9K_MODE_11A, modes_allowed); + sband = wiphy->bands[IEEE80211_BAND_5GHZ]; - if (test_bit(ATH9K_MODE_11NG_HT20, ah->ah_caps.wireless_modes) - && (!country->allow11ng20)) - clear_bit(ATH9K_MODE_11NG_HT20, modes_allowed); + for (i = 0; i < sband->n_channels; i++) { + ch = &sband->channels[i]; + if (ch->center_freq < 5260) + continue; + if (ch->center_freq > 5700) + continue; + /* We always enable radar detection/DFS on this + * frequency range. Additionally we also apply on + * this frequency range: + * - If STA mode does not yet have DFS supports disable + * active scanning + * - If adhoc mode does not support DFS yet then + * disable adhoc in the frequency. + * - If AP mode does not yet support radar detection/DFS + * do not allow AP mode + */ + if (!(ch->flags & IEEE80211_CHAN_DISABLED)) + ch->flags |= IEEE80211_CHAN_RADAR | + IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_PASSIVE_SCAN; + } +} - if (test_bit(ATH9K_MODE_11NA_HT20, ah->ah_caps.wireless_modes) - && (!country->allow11na20)) - clear_bit(ATH9K_MODE_11NA_HT20, modes_allowed); +void ath9k_reg_apply_world_flags(struct wiphy *wiphy, enum reg_set_by setby) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct ath_softc *sc = hw->priv; + struct ath_hal *ah = sc->sc_ah; + + switch (ah->regpair->regDmnEnum) { + case 0x60: + case 0x63: + case 0x66: + case 0x67: + ath9k_reg_apply_5ghz_adhoc_flags(wiphy, setby); + break; + case 0x68: + ath9k_reg_apply_5ghz_adhoc_flags(wiphy, setby); + ath9k_reg_apply_active_scan_flags(wiphy, setby); + break; + } + return; +} - if (test_bit(ATH9K_MODE_11NG_HT40PLUS, ah->ah_caps.wireless_modes) && - (!country->allow11ng40)) - clear_bit(ATH9K_MODE_11NG_HT40PLUS, modes_allowed); +int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct ath_softc *sc = hw->priv; - if (test_bit(ATH9K_MODE_11NG_HT40MINUS, ah->ah_caps.wireless_modes) && - (!country->allow11ng40)) - clear_bit(ATH9K_MODE_11NG_HT40MINUS, modes_allowed); + /* We always apply this */ + ath9k_reg_apply_radar_flags(wiphy); - if (test_bit(ATH9K_MODE_11NA_HT40PLUS, ah->ah_caps.wireless_modes) && - (!country->allow11na40)) - clear_bit(ATH9K_MODE_11NA_HT40PLUS, modes_allowed); + switch (request->initiator) { + case REGDOM_SET_BY_DRIVER: + case REGDOM_SET_BY_INIT: + case REGDOM_SET_BY_CORE: + case REGDOM_SET_BY_USER: + break; + case REGDOM_SET_BY_COUNTRY_IE: + if (ath9k_is_world_regd(sc->sc_ah)) + ath9k_reg_apply_world_flags(wiphy, request->initiator); + break; + } - if (test_bit(ATH9K_MODE_11NA_HT40MINUS, ah->ah_caps.wireless_modes) && - (!country->allow11na40)) - clear_bit(ATH9K_MODE_11NA_HT40MINUS, modes_allowed); + return 0; } -bool ath9k_regd_is_public_safety_sku(struct ath_hal *ah) +bool ath9k_regd_is_eeprom_valid(struct ath_hal *ah) { - u16 rd; - - rd = ath9k_regd_get_eepromRD(ah); + u16 rd = ath9k_regd_get_eepromRD(ah); + int i; - switch (rd) { - case FCC4_FCCA: - case (CTRY_UNITED_STATES_FCC49 | COUNTRY_ERD_FLAG): - return true; - case DEBUG_REG_DMN: - case NO_ENUMRD: - if (ah->ah_countryCode == CTRY_UNITED_STATES_FCC49) - return true; - break; + if (rd & COUNTRY_ERD_FLAG) { + /* EEPROM value is a country code */ + u16 cc = rd & ~COUNTRY_ERD_FLAG; + for (i = 0; i < ARRAY_SIZE(allCountries); i++) + if (allCountries[i].countryCode == cc) + return true; + } else { + /* EEPROM value is a regpair value */ + for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) + if (regDomainPairs[i].regDmnEnum == rd) + return true; } + DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, + "invalid regulatory domain/country code 0x%x\n", rd); return false; } +/* EEPROM country code to regpair mapping */ static struct country_code_to_enum_rd* ath9k_regd_find_country(u16 countryCode) { @@ -201,10 +350,23 @@ ath9k_regd_find_country(u16 countryCode) return NULL; } +/* EEPROM rd code to regpair mapping */ +static struct country_code_to_enum_rd* +ath9k_regd_find_country_by_rd(int regdmn) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(allCountries); i++) { + if (allCountries[i].regDmnEnum == regdmn) + return &allCountries[i]; + } + return NULL; +} + +/* Returns the map of the EEPROM set RD to a country code */ static u16 ath9k_regd_get_default_country(struct ath_hal *ah) { u16 rd; - int i; rd = ath9k_regd_get_eepromRD(ah); if (rd & COUNTRY_ERD_FLAG) { @@ -216,798 +378,104 @@ static u16 ath9k_regd_get_default_country(struct ath_hal *ah) return cc; } - for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) - if (regDomainPairs[i].regDmnEnum == rd) { - if (regDomainPairs[i].singleCC != 0) - return regDomainPairs[i].singleCC; - else - i = ARRAY_SIZE(regDomainPairs); - } return CTRY_DEFAULT; } -static bool ath9k_regd_is_valid_reg_domain(int regDmn, - struct regDomain *rd) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(regDomains); i++) { - if (regDomains[i].regDmnEnum == regDmn) { - if (rd != NULL) { - memcpy(rd, ®Domains[i], - sizeof(struct regDomain)); - } - return true; - } - } - return false; -} - -static bool ath9k_regd_is_valid_reg_domainPair(int regDmnPair) +static struct reg_dmn_pair_mapping* +ath9k_get_regpair(int regdmn) { int i; - if (regDmnPair == NO_ENUMRD) - return false; + if (regdmn == NO_ENUMRD) + return NULL; for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) { - if (regDomainPairs[i].regDmnEnum == regDmnPair) - return true; + if (regDomainPairs[i].regDmnEnum == regdmn) + return ®DomainPairs[i]; } - return false; -} - -static bool -ath9k_regd_get_wmode_regdomain(struct ath_hal *ah, int regDmn, - u16 channelFlag, struct regDomain *rd) -{ - int i, found; - u64 flags = NO_REQ; - struct reg_dmn_pair_mapping *regPair = NULL; - int regOrg; - - regOrg = regDmn; - if (regDmn == CTRY_DEFAULT) { - u16 rdnum; - rdnum = ath9k_regd_get_eepromRD(ah); - - if (!(rdnum & COUNTRY_ERD_FLAG)) { - if (ath9k_regd_is_valid_reg_domain(rdnum, NULL) || - ath9k_regd_is_valid_reg_domainPair(rdnum)) { - regDmn = rdnum; - } - } - } - - if ((regDmn & MULTI_DOMAIN_MASK) == 0) { - for (i = 0, found = 0; - (i < ARRAY_SIZE(regDomainPairs)) && (!found); i++) { - if (regDomainPairs[i].regDmnEnum == regDmn) { - regPair = ®DomainPairs[i]; - found = 1; - } - } - if (!found) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "Failed to find reg domain pair %u\n", regDmn); - return false; - } - if (!(channelFlag & CHANNEL_2GHZ)) { - regDmn = regPair->regDmn5GHz; - flags = regPair->flags5GHz; - } - if (channelFlag & CHANNEL_2GHZ) { - regDmn = regPair->regDmn2GHz; - flags = regPair->flags2GHz; - } - } - - found = ath9k_regd_is_valid_reg_domain(regDmn, rd); - if (!found) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "Failed to find unitary reg domain %u\n", regDmn); - return false; - } else { - rd->pscan &= regPair->pscanMask; - if (((regOrg & MULTI_DOMAIN_MASK) == 0) && - (flags != NO_REQ)) { - rd->flags = flags; - } - - rd->flags &= (channelFlag & CHANNEL_2GHZ) ? - REG_DOMAIN_2GHZ_MASK : REG_DOMAIN_5GHZ_MASK; - return true; - } -} - -static bool ath9k_regd_is_bit_set(int bit, u64 *bitmask) -{ - int byteOffset, bitnum; - u64 val; - - byteOffset = bit / 64; - bitnum = bit - byteOffset * 64; - val = ((u64) 1) << bitnum; - if (bitmask[byteOffset] & val) - return true; - else - return false; -} - -static void -ath9k_regd_add_reg_classid(u8 *regclassids, u32 maxregids, - u32 *nregids, u8 regclassid) -{ - int i; - - if (regclassid == 0) - return; - - for (i = 0; i < maxregids; i++) { - if (regclassids[i] == regclassid) - return; - if (regclassids[i] == 0) - break; - } - - if (i == maxregids) - return; - else { - regclassids[i] = regclassid; - *nregids += 1; - } - - return; -} - -static bool -ath9k_regd_get_eeprom_reg_ext_bits(struct ath_hal *ah, - enum reg_ext_bitmap bit) -{ - return (ah->ah_currentRDExt & (1 << bit)) ? true : false; -} - -#ifdef ATH_NF_PER_CHAN - -static void ath9k_regd_init_rf_buffer(struct ath9k_channel *ichans, - int nchans) -{ - int i, j, next; - - for (next = 0; next < nchans; next++) { - for (i = 0; i < NUM_NF_READINGS; i++) { - ichans[next].nfCalHist[i].currIndex = 0; - ichans[next].nfCalHist[i].privNF = - AR_PHY_CCA_MAX_GOOD_VALUE; - ichans[next].nfCalHist[i].invalidNFcount = - AR_PHY_CCA_FILTERWINDOW_LENGTH; - for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) { - ichans[next].nfCalHist[i].nfCalBuffer[j] = - AR_PHY_CCA_MAX_GOOD_VALUE; - } - } - } -} -#endif - -static int ath9k_regd_is_chan_present(struct ath_hal *ah, - u16 c) -{ - int i; - - for (i = 0; i < 150; i++) { - if (!ah->ah_channels[i].channel) - return -1; - else if (ah->ah_channels[i].channel == c) - return i; - } - - return -1; -} - -static bool -ath9k_regd_add_channel(struct ath_hal *ah, - u16 c, - u16 c_lo, - u16 c_hi, - u16 maxChan, - u8 ctl, - int pos, - struct regDomain rd5GHz, - struct RegDmnFreqBand *fband, - struct regDomain *rd, - const struct cmode *cm, - struct ath9k_channel *ichans, - bool enableExtendedChannels) -{ - struct ath9k_channel *chan; - int ret; - u32 channelFlags = 0; - u8 privFlags = 0; - - if (!(c_lo <= c && c <= c_hi)) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "c %u out of range [%u..%u]\n", - c, c_lo, c_hi); - return false; - } - if ((fband->channelBW == CHANNEL_HALF_BW) && - !(ah->ah_caps.hw_caps & ATH9K_HW_CAP_CHAN_HALFRATE)) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "Skipping %u half rate channel\n", c); - return false; - } - - if ((fband->channelBW == CHANNEL_QUARTER_BW) && - !(ah->ah_caps.hw_caps & ATH9K_HW_CAP_CHAN_QUARTERRATE)) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "Skipping %u quarter rate channel\n", c); - return false; - } - - if (((c + fband->channelSep) / 2) > (maxChan + HALF_MAXCHANBW)) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "c %u > maxChan %u\n", c, maxChan); - return false; - } - - if ((fband->usePassScan & IS_ECM_CHAN) && !enableExtendedChannels) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "Skipping ecm channel\n"); - return false; - } - - if ((rd->flags & NO_HOSTAP) && (ah->ah_opmode == NL80211_IFTYPE_AP)) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "Skipping HOSTAP channel\n"); - return false; - } - - if (IS_HT40_MODE(cm->mode) && - !(ath9k_regd_get_eeprom_reg_ext_bits(ah, REG_EXT_FCC_DFS_HT40)) && - (fband->useDfs) && - (rd->conformanceTestLimit != MKK)) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "Skipping HT40 channel (en_fcc_dfs_ht40 = 0)\n"); - return false; - } - - if (IS_HT40_MODE(cm->mode) && - !(ath9k_regd_get_eeprom_reg_ext_bits(ah, - REG_EXT_JAPAN_NONDFS_HT40)) && - !(fband->useDfs) && (rd->conformanceTestLimit == MKK)) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "Skipping HT40 channel (en_jap_ht40 = 0)\n"); - return false; - } - - if (IS_HT40_MODE(cm->mode) && - !(ath9k_regd_get_eeprom_reg_ext_bits(ah, REG_EXT_JAPAN_DFS_HT40)) && - (fband->useDfs) && - (rd->conformanceTestLimit == MKK)) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "Skipping HT40 channel (en_jap_dfs_ht40 = 0)\n"); - return false; - } - - /* Calculate channel flags */ - - channelFlags = cm->flags; - - switch (fband->channelBW) { - case CHANNEL_HALF_BW: - channelFlags |= CHANNEL_HALF; - break; - case CHANNEL_QUARTER_BW: - channelFlags |= CHANNEL_QUARTER; - break; - } - - if (fband->usePassScan & rd->pscan) - channelFlags |= CHANNEL_PASSIVE; - else - channelFlags &= ~CHANNEL_PASSIVE; - if (fband->useDfs & rd->dfsMask) - privFlags = CHANNEL_DFS; - else - privFlags = 0; - if (rd->flags & LIMIT_FRAME_4MS) - privFlags |= CHANNEL_4MS_LIMIT; - if (privFlags & CHANNEL_DFS) - privFlags |= CHANNEL_DISALLOW_ADHOC; - if (rd->flags & ADHOC_PER_11D) - privFlags |= CHANNEL_PER_11D_ADHOC; - - if (channelFlags & CHANNEL_PASSIVE) { - if ((c < 2412) || (c > 2462)) { - if (rd5GHz.regDmnEnum == MKK1 || - rd5GHz.regDmnEnum == MKK2) { - u32 regcap = ah->ah_caps.reg_cap; - if (!(regcap & - (AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN | - AR_EEPROM_EEREGCAP_EN_KK_U2 | - AR_EEPROM_EEREGCAP_EN_KK_MIDBAND)) && - isUNII1OddChan(c)) { - channelFlags &= ~CHANNEL_PASSIVE; - } else { - privFlags |= CHANNEL_DISALLOW_ADHOC; - } - } else { - privFlags |= CHANNEL_DISALLOW_ADHOC; - } - } - } - - if ((cm->mode == ATH9K_MODE_11A) || - (cm->mode == ATH9K_MODE_11NA_HT20) || - (cm->mode == ATH9K_MODE_11NA_HT40PLUS) || - (cm->mode == ATH9K_MODE_11NA_HT40MINUS)) { - if (rd->flags & (ADHOC_NO_11A | DISALLOW_ADHOC_11A)) - privFlags |= CHANNEL_DISALLOW_ADHOC; - } - - /* Fill in channel details */ - - ret = ath9k_regd_is_chan_present(ah, c); - if (ret == -1) { - chan = &ah->ah_channels[pos]; - chan->channel = c; - chan->maxRegTxPower = fband->powerDfs; - chan->antennaMax = fband->antennaMax; - chan->regDmnFlags = rd->flags; - chan->maxTxPower = AR5416_MAX_RATE_POWER; - chan->minTxPower = AR5416_MAX_RATE_POWER; - chan->channelFlags = channelFlags; - chan->privFlags = privFlags; - } else { - chan = &ah->ah_channels[ret]; - chan->channelFlags |= channelFlags; - chan->privFlags |= privFlags; - } - - /* Set CTLs */ - - if ((cm->flags & CHANNEL_ALL) == CHANNEL_A) - chan->conformanceTestLimit[0] = ctl; - else if ((cm->flags & CHANNEL_ALL) == CHANNEL_B) - chan->conformanceTestLimit[1] = ctl; - else if ((cm->flags & CHANNEL_ALL) == CHANNEL_G) - chan->conformanceTestLimit[2] = ctl; - - return (ret == -1) ? true : false; -} - -static bool ath9k_regd_japan_check(struct ath_hal *ah, - int b, - struct regDomain *rd5GHz) -{ - bool skipband = false; - int i; - u32 regcap; - - for (i = 0; i < ARRAY_SIZE(j_bandcheck); i++) { - if (j_bandcheck[i].freqbandbit == b) { - regcap = ah->ah_caps.reg_cap; - if ((j_bandcheck[i].eepromflagtocheck & regcap) == 0) { - skipband = true; - } else if ((regcap & AR_EEPROM_EEREGCAP_EN_KK_U2) || - (regcap & AR_EEPROM_EEREGCAP_EN_KK_MIDBAND)) { - rd5GHz->dfsMask |= DFS_MKK4; - rd5GHz->pscan |= PSCAN_MKK3; - } - break; - } - } - - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "Skipping %d freq band\n", j_bandcheck[i].freqbandbit); - - return skipband; + return NULL; } -bool -ath9k_regd_init_channels(struct ath_hal *ah, - u32 maxchans, - u32 *nchans, u8 *regclassids, - u32 maxregids, u32 *nregids, u16 cc, - bool enableOutdoor, - bool enableExtendedChannels) +int ath9k_regd_init(struct ath_hal *ah) { - u16 maxChan = 7000; struct country_code_to_enum_rd *country = NULL; - struct regDomain rd5GHz, rd2GHz; - const struct cmode *cm; - struct ath9k_channel *ichans = &ah->ah_channels[0]; - int next = 0, b; - u8 ctl; int regdmn; - u16 chanSep; - unsigned long *modes_avail; - DECLARE_BITMAP(modes_allowed, ATH9K_MODE_MAX); - - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "cc %u %s %s\n", cc, - enableOutdoor ? "Enable outdoor" : "", - enableExtendedChannels ? "Enable ecm" : ""); - - if (!ath9k_regd_is_ccode_valid(ah, cc)) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "Invalid country code %d\n", cc); - return false; - } if (!ath9k_regd_is_eeprom_valid(ah)) { DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "Invalid EEPROM contents\n"); - return false; + return -EINVAL; } ah->ah_countryCode = ath9k_regd_get_default_country(ah); - if (ah->ah_countryCode == CTRY_DEFAULT) { - ah->ah_countryCode = cc & COUNTRY_CODE_MASK; - if ((ah->ah_countryCode == CTRY_DEFAULT) && - (ath9k_regd_get_eepromRD(ah) == CTRY_DEFAULT)) { - ah->ah_countryCode = CTRY_UNITED_STATES; - } - } + if (ah->ah_countryCode == CTRY_DEFAULT && + ath9k_regd_get_eepromRD(ah) == CTRY_DEFAULT) + ah->ah_countryCode = CTRY_UNITED_STATES; -#ifdef AH_SUPPORT_11D if (ah->ah_countryCode == CTRY_DEFAULT) { regdmn = ath9k_regd_get_eepromRD(ah); country = NULL; } else { -#endif country = ath9k_regd_find_country(ah->ah_countryCode); if (country == NULL) { DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "Country is NULL!!!!, cc= %d\n", ah->ah_countryCode); - return false; - } else { + return -EINVAL; + } else regdmn = country->regDmnEnum; -#ifdef AH_SUPPORT_11D - if (((ath9k_regd_get_eepromRD(ah) & - WORLD_SKU_MASK) == WORLD_SKU_PREFIX) && - (cc == CTRY_UNITED_STATES)) { - if (!isWwrSKU_NoMidband(ah) - && ath9k_regd_is_fcc_midband_supported(ah)) - regdmn = FCC3_FCCA; - else - regdmn = FCC1_FCCA; - } -#endif - } -#ifdef AH_SUPPORT_11D - } -#endif - if (!ath9k_regd_get_wmode_regdomain(ah, - regdmn, - ~CHANNEL_2GHZ, - &rd5GHz)) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "Couldn't find unitary " - "5GHz reg domain for country %u\n", - ah->ah_countryCode); - return false; - } - if (!ath9k_regd_get_wmode_regdomain(ah, - regdmn, - CHANNEL_2GHZ, - &rd2GHz)) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "Couldn't find unitary 2GHz " - "reg domain for country %u\n", - ah->ah_countryCode); - return false; } - if (!isWwrSKU(ah) && ((rd5GHz.regDmnEnum == FCC1) || - (rd5GHz.regDmnEnum == FCC2))) { - if (ath9k_regd_is_fcc_midband_supported(ah)) { - if (!ath9k_regd_get_wmode_regdomain(ah, - FCC3_FCCA, - ~CHANNEL_2GHZ, - &rd5GHz)) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "Couldn't find unitary 5GHz " - "reg domain for country %u\n", - ah->ah_countryCode); - return false; - } - } - } - - if (country == NULL) { - modes_avail = ah->ah_caps.wireless_modes; - } else { - ath9k_regd_get_wmodes_nreg(ah, country, &rd5GHz, modes_allowed); - modes_avail = modes_allowed; - - if (!enableOutdoor) - maxChan = country->outdoorChanStart; - } - - next = 0; - - if (maxchans > ARRAY_SIZE(ah->ah_channels)) - maxchans = ARRAY_SIZE(ah->ah_channels); - - for (cm = modes; cm < &modes[ARRAY_SIZE(modes)]; cm++) { - u16 c, c_hi, c_lo; - u64 *channelBM = NULL; - struct regDomain *rd = NULL; - struct RegDmnFreqBand *fband = NULL, *freqs; - int8_t low_adj = 0, hi_adj = 0; - - if (!test_bit(cm->mode, modes_avail)) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "!avail mode %d flags 0x%x\n", - cm->mode, cm->flags); - continue; - } - if (!ath9k_get_channel_edges(ah, cm->flags, &c_lo, &c_hi)) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "channels 0x%x not supported " - "by hardware\n", cm->flags); - continue; - } - - switch (cm->mode) { - case ATH9K_MODE_11A: - case ATH9K_MODE_11NA_HT20: - case ATH9K_MODE_11NA_HT40PLUS: - case ATH9K_MODE_11NA_HT40MINUS: - rd = &rd5GHz; - channelBM = rd->chan11a; - freqs = ®Dmn5GhzFreq[0]; - ctl = rd->conformanceTestLimit; - break; - case ATH9K_MODE_11B: - rd = &rd2GHz; - channelBM = rd->chan11b; - freqs = ®Dmn2GhzFreq[0]; - ctl = rd->conformanceTestLimit | CTL_11B; - break; - case ATH9K_MODE_11G: - case ATH9K_MODE_11NG_HT20: - case ATH9K_MODE_11NG_HT40PLUS: - case ATH9K_MODE_11NG_HT40MINUS: - rd = &rd2GHz; - channelBM = rd->chan11g; - freqs = ®Dmn2Ghz11gFreq[0]; - ctl = rd->conformanceTestLimit | CTL_11G; - break; - default: - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "Unknown HAL mode 0x%x\n", cm->mode); - continue; - } - - if (ath9k_regd_is_chan_bm_zero(channelBM)) - continue; - - if ((cm->mode == ATH9K_MODE_11NA_HT40PLUS) || - (cm->mode == ATH9K_MODE_11NG_HT40PLUS)) { - hi_adj = -20; - } - - if ((cm->mode == ATH9K_MODE_11NA_HT40MINUS) || - (cm->mode == ATH9K_MODE_11NG_HT40MINUS)) { - low_adj = 20; - } - - /* XXX: Add a helper here instead */ - for (b = 0; b < 64 * BMLEN; b++) { - if (ath9k_regd_is_bit_set(b, channelBM)) { - fband = &freqs[b]; - if (rd5GHz.regDmnEnum == MKK1 - || rd5GHz.regDmnEnum == MKK2) { - if (ath9k_regd_japan_check(ah, - b, - &rd5GHz)) - continue; - } - - ath9k_regd_add_reg_classid(regclassids, - maxregids, - nregids, - fband-> - regClassId); - - if (IS_HT40_MODE(cm->mode) && (rd == &rd5GHz)) { - chanSep = 40; - if (fband->lowChannel == 5280) - low_adj += 20; - - if (fband->lowChannel == 5170) - continue; - } else - chanSep = fband->channelSep; - - for (c = fband->lowChannel + low_adj; - ((c <= (fband->highChannel + hi_adj)) && - (c >= (fband->lowChannel + low_adj))); - c += chanSep) { - if (next >= maxchans) { - DPRINTF(ah->ah_sc, - ATH_DBG_REGULATORY, - "too many channels " - "for channel table\n"); - goto done; - } - if (ath9k_regd_add_channel(ah, - c, c_lo, c_hi, - maxChan, ctl, - next, - rd5GHz, - fband, rd, cm, - ichans, - enableExtendedChannels)) - next++; - } - if (IS_HT40_MODE(cm->mode) && - (fband->lowChannel == 5280)) { - low_adj -= 20; - } - } - } - } -done: - if (next != 0) { - int i; + ah->ah_currentRDInUse = regdmn; + ah->regpair = ath9k_get_regpair(regdmn); - if (next > ARRAY_SIZE(ah->ah_channels)) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "too many channels %u; truncating to %u\n", - next, (int) ARRAY_SIZE(ah->ah_channels)); - next = ARRAY_SIZE(ah->ah_channels); - } -#ifdef ATH_NF_PER_CHAN - ath9k_regd_init_rf_buffer(ichans, next); -#endif - ath9k_regd_sort(ichans, next, - sizeof(struct ath9k_channel), - ath9k_regd_chansort); - - ah->ah_nchan = next; - - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "Channel list:\n"); - for (i = 0; i < next; i++) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "chan: %d flags: 0x%x\n", - ah->ah_channels[i].channel, - ah->ah_channels[i].channelFlags); - } + if (!ah->regpair) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "No regulatory domain pair found, cannot continue\n"); + return -EINVAL; } - *nchans = next; - ah->ah_countryCode = ah->ah_countryCode; + if (!country) + country = ath9k_regd_find_country_by_rd(regdmn); - ah->ah_currentRDInUse = regdmn; - ah->ah_currentRD5G = rd5GHz.regDmnEnum; - ah->ah_currentRD2G = rd2GHz.regDmnEnum; - if (country == NULL) { - ah->ah_iso[0] = 0; - ah->ah_iso[1] = 0; + if (country) { + ah->alpha2[0] = country->isoName[0]; + ah->alpha2[1] = country->isoName[1]; } else { - ah->ah_iso[0] = country->isoName[0]; - ah->ah_iso[1] = country->isoName[1]; + ah->alpha2[0] = '0'; + ah->alpha2[1] = '0'; } - return next != 0; -} - -struct ath9k_channel* -ath9k_regd_check_channel(struct ath_hal *ah, - const struct ath9k_channel *c) -{ - struct ath9k_channel *base, *cc; - - int flags = c->channelFlags & CHAN_FLAGS; - int n, lim; - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "channel %u/0x%x (0x%x) requested\n", - c->channel, c->channelFlags, flags); - - cc = ah->ah_curchan; - if (cc != NULL && cc->channel == c->channel && - (cc->channelFlags & CHAN_FLAGS) == flags) { - if ((cc->privFlags & CHANNEL_INTERFERENCE) && - (cc->privFlags & CHANNEL_DFS)) - return NULL; - else - return cc; - } + "Country alpha2 being used: %c%c\n", + "Regpair detected: 0x%0x\n", + ah->alpha2[0], ah->alpha2[1], + ah->regpair->regDmnEnum); - base = ah->ah_channels; - n = ah->ah_nchan; - - for (lim = n; lim != 0; lim >>= 1) { - int d; - cc = &base[lim >> 1]; - d = c->channel - cc->channel; - if (d == 0) { - if ((cc->channelFlags & CHAN_FLAGS) == flags) { - if ((cc->privFlags & CHANNEL_INTERFERENCE) && - (cc->privFlags & CHANNEL_DFS)) - return NULL; - else - return cc; - } - d = flags - (cc->channelFlags & CHAN_FLAGS); - } - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "channel %u/0x%x d %d\n", - cc->channel, cc->channelFlags, d); - if (d > 0) { - base = cc + 1; - lim--; - } - } - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "no match for %u/0x%x\n", - c->channel, c->channelFlags); - return NULL; -} - -u32 -ath9k_regd_get_antenna_allowed(struct ath_hal *ah, - struct ath9k_channel *chan) -{ - struct ath9k_channel *ichan = NULL; - - ichan = ath9k_regd_check_channel(ah, chan); - if (!ichan) - return 0; - - return ichan->antennaMax; + return 0; } u32 ath9k_regd_get_ctl(struct ath_hal *ah, struct ath9k_channel *chan) { u32 ctl = NO_CTL; - struct ath9k_channel *ichan; - if (ah->ah_countryCode == CTRY_DEFAULT && isWwrSKU(ah)) { + if (!ah->regpair || + (ah->ah_countryCode == CTRY_DEFAULT && isWwrSKU(ah))) { if (IS_CHAN_B(chan)) ctl = SD_NO_CTL | CTL_11B; else if (IS_CHAN_G(chan)) ctl = SD_NO_CTL | CTL_11G; else ctl = SD_NO_CTL | CTL_11A; - } else { - ichan = ath9k_regd_check_channel(ah, chan); - if (ichan != NULL) { - /* FIXME */ - if (IS_CHAN_A(ichan)) - ctl = ichan->conformanceTestLimit[0]; - else if (IS_CHAN_B(ichan)) - ctl = ichan->conformanceTestLimit[1]; - else if (IS_CHAN_G(ichan)) - ctl = ichan->conformanceTestLimit[2]; - - if (IS_CHAN_G(chan) && (ctl & 0xf) == CTL_11B) - ctl = (ctl & ~0xf) | CTL_11G; - } + return ctl; } - return ctl; -} -void ath9k_regd_get_current_country(struct ath_hal *ah, - struct ath9k_country_entry *ctry) -{ - u16 rd = ath9k_regd_get_eepromRD(ah); + if (IS_CHAN_B(chan)) + ctl = ah->regpair->reg_2ghz_ctl | CTL_11B; + else if (IS_CHAN_G(chan)) + ctl = ah->regpair->reg_5ghz_ctl | CTL_11G; + else + ctl = ah->regpair->reg_5ghz_ctl | CTL_11A; - ctry->isMultidomain = false; - if (rd == CTRY_DEFAULT) - ctry->isMultidomain = true; - else if (!(rd & COUNTRY_ERD_FLAG)) - ctry->isMultidomain = isWwrSKU(ah); - - ctry->countryCode = ah->ah_countryCode; - ctry->regDmnEnum = ah->ah_currentRD; - ctry->regDmn5G = ah->ah_currentRD5G; - ctry->regDmn2G = ah->ah_currentRD2G; - ctry->iso[0] = ah->ah_iso[0]; - ctry->iso[1] = ah->ah_iso[1]; - ctry->iso[2] = ah->ah_iso[2]; + return ctl; } diff --git a/drivers/net/wireless/ath9k/regd.h b/drivers/net/wireless/ath9k/regd.h index 512d990aa7e..ba2d2dfb0d1 100644 --- a/drivers/net/wireless/ath9k/regd.h +++ b/drivers/net/wireless/ath9k/regd.h @@ -19,126 +19,14 @@ #include "ath9k.h" -#define BMLEN 2 -#define BMZERO {(u64) 0, (u64) 0} - -#define BM(_fa, _fb, _fc, _fd, _fe, _ff, _fg, _fh, _fi, _fj, _fk, _fl) \ - {((((_fa >= 0) && (_fa < 64)) ? \ - (((u64) 1) << _fa) : (u64) 0) | \ - (((_fb >= 0) && (_fb < 64)) ? \ - (((u64) 1) << _fb) : (u64) 0) | \ - (((_fc >= 0) && (_fc < 64)) ? \ - (((u64) 1) << _fc) : (u64) 0) | \ - (((_fd >= 0) && (_fd < 64)) ? \ - (((u64) 1) << _fd) : (u64) 0) | \ - (((_fe >= 0) && (_fe < 64)) ? \ - (((u64) 1) << _fe) : (u64) 0) | \ - (((_ff >= 0) && (_ff < 64)) ? \ - (((u64) 1) << _ff) : (u64) 0) | \ - (((_fg >= 0) && (_fg < 64)) ? \ - (((u64) 1) << _fg) : (u64) 0) | \ - (((_fh >= 0) && (_fh < 64)) ? \ - (((u64) 1) << _fh) : (u64) 0) | \ - (((_fi >= 0) && (_fi < 64)) ? \ - (((u64) 1) << _fi) : (u64) 0) | \ - (((_fj >= 0) && (_fj < 64)) ? \ - (((u64) 1) << _fj) : (u64) 0) | \ - (((_fk >= 0) && (_fk < 64)) ? \ - (((u64) 1) << _fk) : (u64) 0) | \ - (((_fl >= 0) && (_fl < 64)) ? \ - (((u64) 1) << _fl) : (u64) 0) | \ - ((((_fa > 63) && (_fa < 128)) ? \ - (((u64) 1) << (_fa - 64)) : (u64) 0) | \ - (((_fb > 63) && (_fb < 128)) ? \ - (((u64) 1) << (_fb - 64)) : (u64) 0) | \ - (((_fc > 63) && (_fc < 128)) ? \ - (((u64) 1) << (_fc - 64)) : (u64) 0) | \ - (((_fd > 63) && (_fd < 128)) ? \ - (((u64) 1) << (_fd - 64)) : (u64) 0) | \ - (((_fe > 63) && (_fe < 128)) ? \ - (((u64) 1) << (_fe - 64)) : (u64) 0) | \ - (((_ff > 63) && (_ff < 128)) ? \ - (((u64) 1) << (_ff - 64)) : (u64) 0) | \ - (((_fg > 63) && (_fg < 128)) ? \ - (((u64) 1) << (_fg - 64)) : (u64) 0) | \ - (((_fh > 63) && (_fh < 128)) ? \ - (((u64) 1) << (_fh - 64)) : (u64) 0) | \ - (((_fi > 63) && (_fi < 128)) ? \ - (((u64) 1) << (_fi - 64)) : (u64) 0) | \ - (((_fj > 63) && (_fj < 128)) ? \ - (((u64) 1) << (_fj - 64)) : (u64) 0) | \ - (((_fk > 63) && (_fk < 128)) ? \ - (((u64) 1) << (_fk - 64)) : (u64) 0) | \ - (((_fl > 63) && (_fl < 128)) ? \ - (((u64) 1) << (_fl - 64)) : (u64) 0)))} - -#define DEF_REGDMN FCC1_FCCA -#define DEF_DMN_5 FCC1 -#define DEF_DMN_2 FCCA #define COUNTRY_ERD_FLAG 0x8000 #define WORLDWIDE_ROAMING_FLAG 0x4000 -#define SUPER_DOMAIN_MASK 0x0fff -#define COUNTRY_CODE_MASK 0x3fff -#define CF_INTERFERENCE (CHANNEL_CW_INT | CHANNEL_RADAR_INT) -#define CHANNEL_14 (2484) -#define IS_11G_CH14(_ch,_cf) \ - (((_ch) == CHANNEL_14) && ((_cf) == CHANNEL_G)) - -#define NO_PSCAN 0x0ULL -#define PSCAN_FCC 0x0000000000000001ULL -#define PSCAN_FCC_T 0x0000000000000002ULL -#define PSCAN_ETSI 0x0000000000000004ULL -#define PSCAN_MKK1 0x0000000000000008ULL -#define PSCAN_MKK2 0x0000000000000010ULL -#define PSCAN_MKKA 0x0000000000000020ULL -#define PSCAN_MKKA_G 0x0000000000000040ULL -#define PSCAN_ETSIA 0x0000000000000080ULL -#define PSCAN_ETSIB 0x0000000000000100ULL -#define PSCAN_ETSIC 0x0000000000000200ULL -#define PSCAN_WWR 0x0000000000000400ULL -#define PSCAN_MKKA1 0x0000000000000800ULL -#define PSCAN_MKKA1_G 0x0000000000001000ULL -#define PSCAN_MKKA2 0x0000000000002000ULL -#define PSCAN_MKKA2_G 0x0000000000004000ULL -#define PSCAN_MKK3 0x0000000000008000ULL -#define PSCAN_DEFER 0x7FFFFFFFFFFFFFFFULL -#define IS_ECM_CHAN 0x8000000000000000ULL #define isWwrSKU(_ah) \ (((ath9k_regd_get_eepromRD((_ah)) & WORLD_SKU_MASK) == \ WORLD_SKU_PREFIX) || \ (ath9k_regd_get_eepromRD(_ah) == WORLD)) -#define isWwrSKU_NoMidband(_ah) \ - ((ath9k_regd_get_eepromRD((_ah)) == WOR3_WORLD) || \ - (ath9k_regd_get_eepromRD(_ah) == WOR4_WORLD) || \ - (ath9k_regd_get_eepromRD(_ah) == WOR5_ETSIC)) - -#define isUNII1OddChan(ch) \ - ((ch == 5170) || (ch == 5190) || (ch == 5210) || (ch == 5230)) - -#define IS_HT40_MODE(_mode) \ - (((_mode == ATH9K_MODE_11NA_HT40PLUS || \ - _mode == ATH9K_MODE_11NG_HT40PLUS || \ - _mode == ATH9K_MODE_11NA_HT40MINUS || \ - _mode == ATH9K_MODE_11NG_HT40MINUS) ? true : false)) - -#define CHAN_FLAGS (CHANNEL_ALL|CHANNEL_HALF|CHANNEL_QUARTER) - -#define swap_array(_a, _b, _size) { \ - u8 *s = _b; \ - int i = _size; \ - do { \ - u8 tmp = *_a; \ - *_a++ = *s; \ - *s++ = tmp; \ - } while (--i); \ - _a -= _size; \ -} - - -#define HALF_MAXCHANBW 10 - #define MULTI_DOMAIN_MASK 0xFF00 #define WORLD_SKU_MASK 0x00F0 @@ -147,81 +35,16 @@ #define CHANNEL_HALF_BW 10 #define CHANNEL_QUARTER_BW 5 -typedef int ath_hal_cmp_t(const void *, const void *); - struct reg_dmn_pair_mapping { u16 regDmnEnum; - u16 regDmn5GHz; - u16 regDmn2GHz; - u32 flags5GHz; - u32 flags2GHz; - u64 pscanMask; - u16 singleCC; -}; - -struct ccmap { - char isoName[3]; - u16 countryCode; + u16 reg_5ghz_ctl; + u16 reg_2ghz_ctl; }; struct country_code_to_enum_rd { u16 countryCode; u16 regDmnEnum; const char *isoName; - const char *name; - bool allow11g; - bool allow11aTurbo; - bool allow11gTurbo; - bool allow11ng20; - bool allow11ng40; - bool allow11na20; - bool allow11na40; - u16 outdoorChanStart; -}; - -struct RegDmnFreqBand { - u16 lowChannel; - u16 highChannel; - u8 powerDfs; - u8 antennaMax; - u8 channelBW; - u8 channelSep; - u64 useDfs; - u64 usePassScan; - u8 regClassId; -}; - -struct regDomain { - u16 regDmnEnum; - u8 conformanceTestLimit; - u64 dfsMask; - u64 pscan; - u32 flags; - u64 chan11a[BMLEN]; - u64 chan11a_turbo[BMLEN]; - u64 chan11a_dyn_turbo[BMLEN]; - u64 chan11b[BMLEN]; - u64 chan11g[BMLEN]; - u64 chan11g_turbo[BMLEN]; -}; - -struct cmode { - u32 mode; - u32 flags; -}; - -#define YES true -#define NO false - -struct japan_bandcheck { - u16 freqbandbit; - u32 eepromflagtocheck; -}; - -struct common_mode_power { - u16 lchan; - u16 hchan; - u8 pwrlvl; }; enum CountryCode { diff --git a/drivers/net/wireless/ath9k/regd_common.h b/drivers/net/wireless/ath9k/regd_common.h index 6df1b3b77c2..b41d0002f3f 100644 --- a/drivers/net/wireless/ath9k/regd_common.h +++ b/drivers/net/wireless/ath9k/regd_common.h @@ -150,1766 +150,324 @@ enum EnumRd { MKK9_MKKC = 0xFE, MKK9_MKKA2 = 0xFF, - APL1 = 0x0150, - APL2 = 0x0250, - APL3 = 0x0350, - APL4 = 0x0450, - APL5 = 0x0550, - APL6 = 0x0650, - APL7 = 0x0750, - APL8 = 0x0850, - APL9 = 0x0950, - APL10 = 0x1050, - - ETSI1 = 0x0130, - ETSI2 = 0x0230, - ETSI3 = 0x0330, - ETSI4 = 0x0430, - ETSI5 = 0x0530, - ETSI6 = 0x0630, - ETSIA = 0x0A30, - ETSIB = 0x0B30, - ETSIC = 0x0C30, - - FCC1 = 0x0110, - FCC2 = 0x0120, - FCC3 = 0x0160, - FCC4 = 0x0165, - FCC5 = 0x0510, - FCC6 = 0x0610, - FCCA = 0x0A10, - - APLD = 0x0D50, - - MKK1 = 0x0140, - MKK2 = 0x0240, - MKK3 = 0x0340, - MKK4 = 0x0440, - MKK5 = 0x0540, - MKK6 = 0x0640, - MKK7 = 0x0740, - MKK8 = 0x0840, - MKK9 = 0x0940, - MKK10 = 0x0B40, - MKK11 = 0x1140, - MKK12 = 0x1240, - MKK13 = 0x0C40, - MKK14 = 0x1440, - MKK15 = 0x1540, - MKKA = 0x0A40, - MKKC = 0x0A50, - - NULL1 = 0x0198, WORLD = 0x0199, DEBUG_REG_DMN = 0x01ff, }; -enum { - FCC = 0x10, - MKK = 0x40, - ETSI = 0x30, -}; - -enum { - NO_REQ = 0x00000000, - DISALLOW_ADHOC_11A = 0x00000001, - DISALLOW_ADHOC_11A_TURB = 0x00000002, - NEED_NFC = 0x00000004, - - ADHOC_PER_11D = 0x00000008, - ADHOC_NO_11A = 0x00000010, - - PUBLIC_SAFETY_DOMAIN = 0x00000020, - LIMIT_FRAME_4MS = 0x00000040, - - NO_HOSTAP = 0x00000080, - - REQ_MASK = 0x000000FF, +enum ctl_group { + CTL_FCC = 0x10, + CTL_MKK = 0x40, + CTL_ETSI = 0x30, }; -#define REG_DOMAIN_2GHZ_MASK (REQ_MASK & \ - (~(ADHOC_NO_11A | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB))) -#define REG_DOMAIN_5GHZ_MASK REQ_MASK - +/* Regpair to CTL band mapping */ static struct reg_dmn_pair_mapping regDomainPairs[] = { - {NO_ENUMRD, DEBUG_REG_DMN, DEBUG_REG_DMN, NO_REQ, NO_REQ, - PSCAN_DEFER, 0}, - {NULL1_WORLD, NULL1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - {NULL1_ETSIB, NULL1, ETSIB, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - {NULL1_ETSIC, NULL1, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - - {FCC2_FCCA, FCC2, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - {FCC2_WORLD, FCC2, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - {FCC2_ETSIC, FCC2, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - {FCC3_FCCA, FCC3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - {FCC3_WORLD, FCC3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - {FCC4_FCCA, FCC4, FCCA, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, - 0}, - {FCC5_FCCA, FCC5, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - {FCC6_FCCA, FCC6, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - {FCC6_WORLD, FCC6, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - - {ETSI1_WORLD, ETSI1, WORLD, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, - 0}, - {ETSI2_WORLD, ETSI2, WORLD, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, - 0}, - {ETSI3_WORLD, ETSI3, WORLD, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, - 0}, - {ETSI4_WORLD, ETSI4, WORLD, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, - 0}, - {ETSI5_WORLD, ETSI5, WORLD, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, - 0}, - {ETSI6_WORLD, ETSI6, WORLD, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, - 0}, - - {ETSI3_ETSIA, ETSI3, WORLD, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, - 0}, - {FRANCE_RES, ETSI3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - - {FCC1_WORLD, FCC1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - {FCC1_FCCA, FCC1, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - {APL1_WORLD, APL1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - {APL2_WORLD, APL2, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - {APL3_WORLD, APL3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - {APL4_WORLD, APL4, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - {APL5_WORLD, APL5, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - {APL6_WORLD, APL6, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - {APL8_WORLD, APL8, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - {APL9_WORLD, APL9, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - - {APL3_FCCA, APL3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - {APL1_ETSIC, APL1, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - {APL2_ETSIC, APL2, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - {APL2_APLD, APL2, APLD, NO_REQ, NO_REQ, PSCAN_DEFER,}, - - {MKK1_MKKA, MKK1, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1 | PSCAN_MKKA, CTRY_JAPAN}, - {MKK1_MKKB, MKK1, MKKA, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | - LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G, - CTRY_JAPAN1}, - {MKK1_FCCA, MKK1, FCCA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1, CTRY_JAPAN2}, - {MKK1_MKKA1, MKK1, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN4}, - {MKK1_MKKA2, MKK1, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN5}, - {MKK1_MKKC, MKK1, MKKC, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1, CTRY_JAPAN6}, - - {MKK2_MKKA, MKK2, MKKA, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | - LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK2 | PSCAN_MKKA | PSCAN_MKKA_G, - CTRY_JAPAN3}, - - {MKK3_MKKA, MKK3, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKKA, CTRY_JAPAN25}, - {MKK3_MKKB, MKK3, MKKA, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | - LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA | PSCAN_MKKA_G, - CTRY_JAPAN7}, - {MKK3_MKKA1, MKK3, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN26}, - {MKK3_MKKA2, MKK3, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN8}, - {MKK3_MKKC, MKK3, MKKC, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - NO_PSCAN, CTRY_JAPAN9}, - {MKK3_FCCA, MKK3, FCCA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - NO_PSCAN, CTRY_JAPAN27}, - - {MKK4_MKKA, MKK4, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK3, CTRY_JAPAN36}, - {MKK4_MKKB, MKK4, MKKA, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | - LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, - CTRY_JAPAN10}, - {MKK4_MKKA1, MKK4, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN28}, - {MKK4_MKKA2, MKK4, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN11}, - {MKK4_MKKC, MKK4, MKKC, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK3, CTRY_JAPAN12}, - {MKK4_FCCA, MKK4, FCCA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK3, CTRY_JAPAN29}, - - {MKK5_MKKB, MKK5, MKKA, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | - LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, - CTRY_JAPAN13}, - {MKK5_MKKA2, MKK5, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN14}, - {MKK5_MKKC, MKK5, MKKC, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK3, CTRY_JAPAN15}, - - {MKK6_MKKB, MKK6, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN16}, - {MKK6_MKKA1, MKK6, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN30}, - {MKK6_MKKA2, MKK6, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN17}, - {MKK6_MKKC, MKK6, MKKC, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1, CTRY_JAPAN18}, - {MKK6_FCCA, MKK6, FCCA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - NO_PSCAN, CTRY_JAPAN31}, - - {MKK7_MKKB, MKK7, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, - CTRY_JAPAN19}, - {MKK7_MKKA1, MKK7, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN32}, - {MKK7_MKKA2, MKK7, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, - CTRY_JAPAN20}, - {MKK7_MKKC, MKK7, MKKC, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN21}, - {MKK7_FCCA, MKK7, FCCA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN33}, - - {MKK8_MKKB, MKK8, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, - CTRY_JAPAN22}, - {MKK8_MKKA2, MKK8, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, - CTRY_JAPAN23}, - {MKK8_MKKC, MKK8, MKKC, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN24}, - - {MKK9_MKKA, MKK9, MKKA, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | - LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK2 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, - CTRY_JAPAN34}, - {MKK9_FCCA, MKK9, FCCA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - NO_PSCAN, CTRY_JAPAN37}, - {MKK9_MKKA1, MKK9, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN38}, - {MKK9_MKKA2, MKK9, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN40}, - {MKK9_MKKC, MKK9, MKKC, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - NO_PSCAN, CTRY_JAPAN39}, - - {MKK10_MKKA, MKK10, MKKA, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | - LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK2 | PSCAN_MKK3, CTRY_JAPAN35}, - {MKK10_FCCA, MKK10, FCCA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - NO_PSCAN, CTRY_JAPAN41}, - {MKK10_MKKA1, MKK10, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN42}, - {MKK10_MKKA2, MKK10, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN44}, - {MKK10_MKKC, MKK10, MKKC, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - NO_PSCAN, CTRY_JAPAN43}, - - {MKK11_MKKA, MKK11, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK3, CTRY_JAPAN45}, - {MKK11_FCCA, MKK11, FCCA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK3, CTRY_JAPAN46}, - {MKK11_MKKA1, MKK11, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN47}, - {MKK11_MKKA2, MKK11, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN49}, - {MKK11_MKKC, MKK11, MKKC, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK3, CTRY_JAPAN48}, - - {MKK12_MKKA, MKK12, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN50}, - {MKK12_FCCA, MKK12, FCCA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN51}, - {MKK12_MKKA1, MKK12, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, - CTRY_JAPAN52}, - {MKK12_MKKA2, MKK12, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, - CTRY_JAPAN54}, - {MKK12_MKKC, MKK12, MKKC, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN53}, - - {MKK13_MKKB, MKK13, MKKA, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | - LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, - CTRY_JAPAN57}, - - {MKK14_MKKA1, MKK14, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN58}, - {MKK15_MKKA1, MKK15, MKKA, - DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, - PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN59}, - - {WOR0_WORLD, WOR0_WORLD, WOR0_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, - 0}, - {WOR1_WORLD, WOR1_WORLD, WOR1_WORLD, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, - 0}, - {WOR2_WORLD, WOR2_WORLD, WOR2_WORLD, DISALLOW_ADHOC_11A_TURB, - NO_REQ, PSCAN_DEFER, 0}, - {WOR3_WORLD, WOR3_WORLD, WOR3_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, - 0}, - {WOR4_WORLD, WOR4_WORLD, WOR4_WORLD, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, - 0}, - {WOR5_ETSIC, WOR5_ETSIC, WOR5_ETSIC, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, - 0}, - {WOR01_WORLD, WOR01_WORLD, WOR01_WORLD, NO_REQ, NO_REQ, - PSCAN_DEFER, 0}, - {WOR02_WORLD, WOR02_WORLD, WOR02_WORLD, NO_REQ, NO_REQ, - PSCAN_DEFER, 0}, - {EU1_WORLD, EU1_WORLD, EU1_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, - {WOR9_WORLD, WOR9_WORLD, WOR9_WORLD, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, - 0}, - {WORA_WORLD, WORA_WORLD, WORA_WORLD, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, - 0}, - {WORB_WORLD, WORB_WORLD, WORB_WORLD, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, - 0}, + /* regpair, 5 GHz CTL, 2 GHz CTL */ + {NO_ENUMRD, DEBUG_REG_DMN, DEBUG_REG_DMN}, + {NULL1_WORLD, NO_CTL, CTL_ETSI}, + {NULL1_ETSIB, NO_CTL, CTL_ETSI}, + {NULL1_ETSIC, NO_CTL, CTL_ETSI}, + + {FCC2_FCCA, CTL_FCC, CTL_FCC}, + {FCC2_WORLD, CTL_FCC, CTL_ETSI}, + {FCC2_ETSIC, CTL_FCC, CTL_ETSI}, + {FCC3_FCCA, CTL_FCC, CTL_FCC}, + {FCC3_WORLD, CTL_FCC, CTL_ETSI}, + {FCC4_FCCA, CTL_FCC, CTL_FCC}, + {FCC5_FCCA, CTL_FCC, CTL_FCC}, + {FCC6_FCCA, CTL_FCC, CTL_FCC}, + {FCC6_WORLD, CTL_FCC, CTL_ETSI}, + + {ETSI1_WORLD, CTL_ETSI, CTL_ETSI}, + {ETSI2_WORLD, CTL_ETSI, CTL_ETSI}, + {ETSI3_WORLD, CTL_ETSI, CTL_ETSI}, + {ETSI4_WORLD, CTL_ETSI, CTL_ETSI}, + {ETSI5_WORLD, CTL_ETSI, CTL_ETSI}, + {ETSI6_WORLD, CTL_ETSI, CTL_ETSI}, + + /* XXX: For ETSI3_ETSIA, Was NO_CTL meant for the 2 GHz band ? */ + {ETSI3_ETSIA, CTL_ETSI, CTL_ETSI}, + {FRANCE_RES, CTL_ETSI, CTL_ETSI}, + + {FCC1_WORLD, CTL_FCC, CTL_ETSI}, + {FCC1_FCCA, CTL_FCC, CTL_FCC}, + {APL1_WORLD, CTL_FCC, CTL_ETSI}, + {APL2_WORLD, CTL_FCC, CTL_ETSI}, + {APL3_WORLD, CTL_FCC, CTL_ETSI}, + {APL4_WORLD, CTL_FCC, CTL_ETSI}, + {APL5_WORLD, CTL_FCC, CTL_ETSI}, + {APL6_WORLD, CTL_ETSI, CTL_ETSI}, + {APL8_WORLD, CTL_ETSI, CTL_ETSI}, + {APL9_WORLD, CTL_ETSI, CTL_ETSI}, + + {APL3_FCCA, CTL_FCC, CTL_FCC}, + {APL1_ETSIC, CTL_FCC, CTL_ETSI}, + {APL2_ETSIC, CTL_FCC, CTL_ETSI}, + {APL2_APLD, CTL_FCC, NO_CTL}, + + {MKK1_MKKA, CTL_MKK, CTL_MKK}, + {MKK1_MKKB, CTL_MKK, CTL_MKK}, + {MKK1_FCCA, CTL_MKK, CTL_FCC}, + {MKK1_MKKA1, CTL_MKK, CTL_MKK}, + {MKK1_MKKA2, CTL_MKK, CTL_MKK}, + {MKK1_MKKC, CTL_MKK, CTL_MKK}, + + {MKK2_MKKA, CTL_MKK, CTL_MKK}, + {MKK3_MKKA, CTL_MKK, CTL_MKK}, + {MKK3_MKKB, CTL_MKK, CTL_MKK}, + {MKK3_MKKA1, CTL_MKK, CTL_MKK}, + {MKK3_MKKA2, CTL_MKK, CTL_MKK}, + {MKK3_MKKC, CTL_MKK, CTL_MKK}, + {MKK3_FCCA, CTL_MKK, CTL_FCC}, + + {MKK4_MKKA, CTL_MKK, CTL_MKK}, + {MKK4_MKKB, CTL_MKK, CTL_MKK}, + {MKK4_MKKA1, CTL_MKK, CTL_MKK}, + {MKK4_MKKA2, CTL_MKK, CTL_MKK}, + {MKK4_MKKC, CTL_MKK, CTL_MKK}, + {MKK4_FCCA, CTL_MKK, CTL_FCC}, + + {MKK5_MKKB, CTL_MKK, CTL_MKK}, + {MKK5_MKKA2, CTL_MKK, CTL_MKK}, + {MKK5_MKKC, CTL_MKK, CTL_MKK}, + + {MKK6_MKKB, CTL_MKK, CTL_MKK}, + {MKK6_MKKA1, CTL_MKK, CTL_MKK}, + {MKK6_MKKA2, CTL_MKK, CTL_MKK}, + {MKK6_MKKC, CTL_MKK, CTL_MKK}, + {MKK6_FCCA, CTL_MKK, CTL_FCC}, + + {MKK7_MKKB, CTL_MKK, CTL_MKK}, + {MKK7_MKKA1, CTL_MKK, CTL_MKK}, + {MKK7_MKKA2, CTL_MKK, CTL_MKK}, + {MKK7_MKKC, CTL_MKK, CTL_MKK}, + {MKK7_FCCA, CTL_MKK, CTL_FCC}, + + {MKK8_MKKB, CTL_MKK, CTL_MKK}, + {MKK8_MKKA2, CTL_MKK, CTL_MKK}, + {MKK8_MKKC, CTL_MKK, CTL_MKK}, + + {MKK9_MKKA, CTL_MKK, CTL_MKK}, + {MKK9_FCCA, CTL_MKK, CTL_FCC}, + {MKK9_MKKA1, CTL_MKK, CTL_MKK}, + {MKK9_MKKA2, CTL_MKK, CTL_MKK}, + {MKK9_MKKC, CTL_MKK, CTL_MKK}, + + {MKK10_MKKA, CTL_MKK, CTL_MKK}, + {MKK10_FCCA, CTL_MKK, CTL_FCC}, + {MKK10_MKKA1, CTL_MKK, CTL_MKK}, + {MKK10_MKKA2, CTL_MKK, CTL_MKK}, + {MKK10_MKKC, CTL_MKK, CTL_MKK}, + + {MKK11_MKKA, CTL_MKK, CTL_MKK}, + {MKK11_FCCA, CTL_MKK, CTL_FCC}, + {MKK11_MKKA1, CTL_MKK, CTL_MKK}, + {MKK11_MKKA2, CTL_MKK, CTL_MKK}, + {MKK11_MKKC, CTL_MKK, CTL_MKK}, + + {MKK12_MKKA, CTL_MKK, CTL_MKK}, + {MKK12_FCCA, CTL_MKK, CTL_FCC}, + {MKK12_MKKA1, CTL_MKK, CTL_MKK}, + {MKK12_MKKA2, CTL_MKK, CTL_MKK}, + {MKK12_MKKC, CTL_MKK, CTL_MKK}, + + {MKK13_MKKB, CTL_MKK, CTL_MKK}, + {MKK14_MKKA1, CTL_MKK, CTL_MKK}, + {MKK15_MKKA1, CTL_MKK, CTL_MKK}, + + {WOR0_WORLD, NO_CTL, NO_CTL}, + {WOR1_WORLD, NO_CTL, NO_CTL}, + {WOR2_WORLD, NO_CTL, NO_CTL}, + {WOR3_WORLD, NO_CTL, NO_CTL}, + {WOR4_WORLD, NO_CTL, NO_CTL}, + {WOR5_ETSIC, NO_CTL, NO_CTL}, + {WOR01_WORLD, NO_CTL, NO_CTL}, + {WOR02_WORLD, NO_CTL, NO_CTL}, + {EU1_WORLD, NO_CTL, NO_CTL}, + {WOR9_WORLD, NO_CTL, NO_CTL}, + {WORA_WORLD, NO_CTL, NO_CTL}, + {WORB_WORLD, NO_CTL, NO_CTL}, }; -#define NO_INTERSECT_REQ 0xFFFFFFFF -#define NO_UNION_REQ 0 - static struct country_code_to_enum_rd allCountries[] = { - {CTRY_DEBUG, NO_ENUMRD, "DB", "DEBUG", YES, YES, YES, YES, YES, - YES, YES, 7000}, - {CTRY_DEFAULT, DEF_REGDMN, "NA", "NO_COUNTRY_SET", YES, YES, YES, - YES, YES, YES, YES, 7000}, - {CTRY_ALBANIA, NULL1_WORLD, "AL", "ALBANIA", YES, NO, YES, YES, NO, - NO, NO, 7000}, - {CTRY_ALGERIA, NULL1_WORLD, "DZ", "ALGERIA", YES, NO, YES, YES, NO, - NO, NO, 7000}, - {CTRY_ARGENTINA, APL3_WORLD, "AR", "ARGENTINA", YES, NO, NO, YES, - NO, YES, NO, 7000}, - {CTRY_ARMENIA, ETSI4_WORLD, "AM", "ARMENIA", YES, NO, YES, YES, - YES, NO, NO, 7000}, - {CTRY_AUSTRALIA, FCC2_WORLD, "AU", "AUSTRALIA", YES, YES, YES, YES, - YES, YES, YES, 7000}, - {CTRY_AUSTRALIA2, FCC6_WORLD, "AU", "AUSTRALIA2", YES, YES, YES, - YES, YES, YES, YES, 7000}, - {CTRY_AUSTRIA, ETSI1_WORLD, "AT", "AUSTRIA", YES, NO, YES, YES, - YES, YES, YES, 7000}, - {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ", "AZERBAIJAN", YES, YES, YES, - YES, YES, YES, YES, 7000}, - {CTRY_BAHRAIN, APL6_WORLD, "BH", "BAHRAIN", YES, NO, YES, YES, YES, - YES, NO, 7000}, - {CTRY_BELARUS, ETSI1_WORLD, "BY", "BELARUS", YES, NO, YES, YES, - YES, YES, YES, 7000}, - {CTRY_BELGIUM, ETSI1_WORLD, "BE", "BELGIUM", YES, NO, YES, YES, - YES, YES, YES, 7000}, - {CTRY_BELGIUM2, ETSI4_WORLD, "BL", "BELGIUM", YES, NO, YES, YES, - YES, YES, YES, 7000}, - {CTRY_BELIZE, APL1_ETSIC, "BZ", "BELIZE", YES, YES, YES, YES, YES, - YES, YES, 7000}, - {CTRY_BOLIVIA, APL1_ETSIC, "BO", "BOLVIA", YES, YES, YES, YES, YES, - YES, YES, 7000}, - {CTRY_BOSNIA_HERZ, ETSI1_WORLD, "BA", "BOSNIA_HERZGOWINA", YES, NO, - YES, YES, YES, YES, NO, 7000}, - {CTRY_BRAZIL, FCC3_WORLD, "BR", "BRAZIL", YES, NO, NO, YES, NO, - YES, NO, 7000}, - {CTRY_BRUNEI_DARUSSALAM, APL1_WORLD, "BN", "BRUNEI DARUSSALAM", - YES, YES, YES, YES, YES, YES, YES, 7000}, - {CTRY_BULGARIA, ETSI6_WORLD, "BG", "BULGARIA", YES, NO, YES, YES, - YES, YES, YES, 7000}, - {CTRY_CANADA, FCC2_FCCA, "CA", "CANADA", YES, YES, YES, YES, YES, - YES, YES, 7000}, - {CTRY_CANADA2, FCC6_FCCA, "CA", "CANADA2", YES, YES, YES, YES, YES, - YES, YES, 7000}, - {CTRY_CHILE, APL6_WORLD, "CL", "CHILE", YES, YES, YES, YES, YES, - YES, YES, 7000}, - {CTRY_CHINA, APL1_WORLD, "CN", "CHINA", YES, YES, YES, YES, YES, - YES, YES, 7000}, - {CTRY_COLOMBIA, FCC1_FCCA, "CO", "COLOMBIA", YES, NO, YES, YES, - YES, YES, NO, 7000}, - {CTRY_COSTA_RICA, FCC1_WORLD, "CR", "COSTA RICA", YES, NO, YES, - YES, YES, YES, NO, 7000}, - {CTRY_CROATIA, ETSI3_WORLD, "HR", "CROATIA", YES, NO, YES, YES, - YES, YES, NO, 7000}, - {CTRY_CYPRUS, ETSI1_WORLD, "CY", "CYPRUS", YES, YES, YES, YES, YES, - YES, YES, 7000}, - {CTRY_CZECH, ETSI3_WORLD, "CZ", "CZECH REPUBLIC", YES, NO, YES, - YES, YES, YES, YES, 7000}, - {CTRY_DENMARK, ETSI1_WORLD, "DK", "DENMARK", YES, NO, YES, YES, - YES, YES, YES, 7000}, - {CTRY_DOMINICAN_REPUBLIC, FCC1_FCCA, "DO", "DOMINICAN REPUBLIC", - YES, YES, YES, YES, YES, YES, YES, 7000}, - {CTRY_ECUADOR, FCC1_WORLD, "EC", "ECUADOR", YES, NO, NO, YES, YES, - YES, NO, 7000}, - {CTRY_EGYPT, ETSI3_WORLD, "EG", "EGYPT", YES, NO, YES, YES, YES, - YES, NO, 7000}, - {CTRY_EL_SALVADOR, FCC1_WORLD, "SV", "EL SALVADOR", YES, NO, YES, - YES, YES, YES, NO, 7000}, - {CTRY_ESTONIA, ETSI1_WORLD, "EE", "ESTONIA", YES, NO, YES, YES, - YES, YES, YES, 7000}, - {CTRY_FINLAND, ETSI1_WORLD, "FI", "FINLAND", YES, NO, YES, YES, - YES, YES, YES, 7000}, - {CTRY_FRANCE, ETSI1_WORLD, "FR", "FRANCE", YES, NO, YES, YES, YES, - YES, YES, 7000}, - {CTRY_GEORGIA, ETSI4_WORLD, "GE", "GEORGIA", YES, YES, YES, YES, - YES, YES, YES, 7000}, - {CTRY_GERMANY, ETSI1_WORLD, "DE", "GERMANY", YES, NO, YES, YES, - YES, YES, YES, 7000}, - {CTRY_GREECE, ETSI1_WORLD, "GR", "GREECE", YES, NO, YES, YES, YES, - YES, YES, 7000}, - {CTRY_GUATEMALA, FCC1_FCCA, "GT", "GUATEMALA", YES, YES, YES, YES, - YES, YES, YES, 7000}, - {CTRY_HONDURAS, NULL1_WORLD, "HN", "HONDURAS", YES, NO, YES, YES, - YES, NO, NO, 7000}, - {CTRY_HONG_KONG, FCC2_WORLD, "HK", "HONG KONG", YES, YES, YES, YES, - YES, YES, YES, 7000}, - {CTRY_HUNGARY, ETSI1_WORLD, "HU", "HUNGARY", YES, NO, YES, YES, - YES, YES, YES, 7000}, - {CTRY_ICELAND, ETSI1_WORLD, "IS", "ICELAND", YES, NO, YES, YES, - YES, YES, YES, 7000}, - {CTRY_INDIA, APL6_WORLD, "IN", "INDIA", YES, NO, YES, YES, YES, - YES, NO, 7000}, - {CTRY_INDONESIA, APL1_WORLD, "ID", "INDONESIA", YES, NO, YES, YES, - YES, YES, NO, 7000}, - {CTRY_IRAN, APL1_WORLD, "IR", "IRAN", YES, YES, YES, YES, YES, YES, - YES, 7000}, - {CTRY_IRELAND, ETSI1_WORLD, "IE", "IRELAND", YES, NO, YES, YES, - YES, YES, YES, 7000}, - {CTRY_ISRAEL, NULL1_WORLD, "IL", "ISRAEL", YES, NO, YES, YES, YES, - NO, NO, 7000}, - {CTRY_ITALY, ETSI1_WORLD, "IT", "ITALY", YES, NO, YES, YES, YES, - YES, YES, 7000}, - {CTRY_JAMAICA, ETSI1_WORLD, "JM", "JAMAICA", YES, NO, YES, YES, - YES, YES, YES, 7000}, - - {CTRY_JAPAN, MKK1_MKKA, "JP", "JAPAN", YES, NO, NO, YES, YES, YES, - YES, 7000}, - {CTRY_JAPAN1, MKK1_MKKB, "JP", "JAPAN1", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN2, MKK1_FCCA, "JP", "JAPAN2", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN3, MKK2_MKKA, "JP", "JAPAN3", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN4, MKK1_MKKA1, "JP", "JAPAN4", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN5, MKK1_MKKA2, "JP", "JAPAN5", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN6, MKK1_MKKC, "JP", "JAPAN6", YES, NO, NO, YES, YES, - YES, YES, 7000}, - - {CTRY_JAPAN7, MKK3_MKKB, "JP", "JAPAN7", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN8, MKK3_MKKA2, "JP", "JAPAN8", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN9, MKK3_MKKC, "JP", "JAPAN9", YES, NO, NO, YES, YES, - YES, YES, 7000}, - - {CTRY_JAPAN10, MKK4_MKKB, "JP", "JAPAN10", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN11, MKK4_MKKA2, "JP", "JAPAN11", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN12, MKK4_MKKC, "JP", "JAPAN12", YES, NO, NO, YES, YES, - YES, YES, 7000}, - - {CTRY_JAPAN13, MKK5_MKKB, "JP", "JAPAN13", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN14, MKK5_MKKA2, "JP", "JAPAN14", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN15, MKK5_MKKC, "JP", "JAPAN15", YES, NO, NO, YES, YES, - YES, YES, 7000}, - - {CTRY_JAPAN16, MKK6_MKKB, "JP", "JAPAN16", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN17, MKK6_MKKA2, "JP", "JAPAN17", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN18, MKK6_MKKC, "JP", "JAPAN18", YES, NO, NO, YES, YES, - YES, YES, 7000}, - - {CTRY_JAPAN19, MKK7_MKKB, "JP", "JAPAN19", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN20, MKK7_MKKA2, "JP", "JAPAN20", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN21, MKK7_MKKC, "JP", "JAPAN21", YES, NO, NO, YES, YES, - YES, YES, 7000}, - - {CTRY_JAPAN22, MKK8_MKKB, "JP", "JAPAN22", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN23, MKK8_MKKA2, "JP", "JAPAN23", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN24, MKK8_MKKC, "JP", "JAPAN24", YES, NO, NO, YES, YES, - YES, YES, 7000}, - - {CTRY_JAPAN25, MKK3_MKKA, "JP", "JAPAN25", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN26, MKK3_MKKA1, "JP", "JAPAN26", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN27, MKK3_FCCA, "JP", "JAPAN27", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN28, MKK4_MKKA1, "JP", "JAPAN28", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN29, MKK4_FCCA, "JP", "JAPAN29", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN30, MKK6_MKKA1, "JP", "JAPAN30", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN31, MKK6_FCCA, "JP", "JAPAN31", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN32, MKK7_MKKA1, "JP", "JAPAN32", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN33, MKK7_FCCA, "JP", "JAPAN33", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN34, MKK9_MKKA, "JP", "JAPAN34", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN35, MKK10_MKKA, "JP", "JAPAN35", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN36, MKK4_MKKA, "JP", "JAPAN36", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN37, MKK9_FCCA, "JP", "JAPAN37", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN38, MKK9_MKKA1, "JP", "JAPAN38", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN39, MKK9_MKKC, "JP", "JAPAN39", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN40, MKK9_MKKA2, "JP", "JAPAN40", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN41, MKK10_FCCA, "JP", "JAPAN41", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN42, MKK10_MKKA1, "JP", "JAPAN42", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN43, MKK10_MKKC, "JP", "JAPAN43", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN44, MKK10_MKKA2, "JP", "JAPAN44", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN45, MKK11_MKKA, "JP", "JAPAN45", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN46, MKK11_FCCA, "JP", "JAPAN46", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN47, MKK11_MKKA1, "JP", "JAPAN47", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN48, MKK11_MKKC, "JP", "JAPAN48", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN49, MKK11_MKKA2, "JP", "JAPAN49", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN50, MKK12_MKKA, "JP", "JAPAN50", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN51, MKK12_FCCA, "JP", "JAPAN51", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN52, MKK12_MKKA1, "JP", "JAPAN52", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN53, MKK12_MKKC, "JP", "JAPAN53", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN54, MKK12_MKKA2, "JP", "JAPAN54", YES, NO, NO, YES, YES, - YES, YES, 7000}, - - {CTRY_JAPAN57, MKK13_MKKB, "JP", "JAPAN57", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN58, MKK14_MKKA1, "JP", "JAPAN58", YES, NO, NO, YES, YES, - YES, YES, 7000}, - {CTRY_JAPAN59, MKK15_MKKA1, "JP", "JAPAN59", YES, NO, NO, YES, YES, - YES, YES, 7000}, - - {CTRY_JORDAN, ETSI2_WORLD, "JO", "JORDAN", YES, NO, YES, YES, YES, - YES, NO, 7000}, - {CTRY_KAZAKHSTAN, NULL1_WORLD, "KZ", "KAZAKHSTAN", YES, NO, YES, - YES, YES, NO, NO, 7000}, - {CTRY_KOREA_NORTH, APL9_WORLD, "KP", "NORTH KOREA", YES, NO, NO, - YES, YES, YES, YES, 7000}, - {CTRY_KOREA_ROC, APL9_WORLD, "KR", "KOREA REPUBLIC", YES, NO, NO, - YES, NO, YES, NO, 7000}, - {CTRY_KOREA_ROC2, APL2_WORLD, "K2", "KOREA REPUBLIC2", YES, NO, NO, - YES, NO, YES, NO, 7000}, - {CTRY_KOREA_ROC3, APL9_WORLD, "K3", "KOREA REPUBLIC3", YES, NO, NO, - YES, NO, YES, NO, 7000}, - {CTRY_KUWAIT, NULL1_WORLD, "KW", "KUWAIT", YES, NO, YES, YES, YES, - NO, NO, 7000}, - {CTRY_LATVIA, ETSI1_WORLD, "LV", "LATVIA", YES, NO, YES, YES, YES, - YES, YES, 7000}, - {CTRY_LEBANON, NULL1_WORLD, "LB", "LEBANON", YES, NO, YES, YES, - YES, NO, NO, 7000}, - {CTRY_LIECHTENSTEIN, ETSI1_WORLD, "LI", "LIECHTENSTEIN", YES, NO, - YES, YES, YES, YES, YES, 7000}, - {CTRY_LITHUANIA, ETSI1_WORLD, "LT", "LITHUANIA", YES, NO, YES, YES, - YES, YES, YES, 7000}, - {CTRY_LUXEMBOURG, ETSI1_WORLD, "LU", "LUXEMBOURG", YES, NO, YES, - YES, YES, YES, YES, 7000}, - {CTRY_MACAU, FCC2_WORLD, "MO", "MACAU", YES, YES, YES, YES, YES, - YES, YES, 7000}, - {CTRY_MACEDONIA, NULL1_WORLD, "MK", "MACEDONIA", YES, NO, YES, YES, - YES, NO, NO, 7000}, - {CTRY_MALAYSIA, APL8_WORLD, "MY", "MALAYSIA", YES, NO, NO, YES, NO, - YES, NO, 7000}, - {CTRY_MALTA, ETSI1_WORLD, "MT", "MALTA", YES, NO, YES, YES, YES, - YES, YES, 7000}, - {CTRY_MEXICO, FCC1_FCCA, "MX", "MEXICO", YES, YES, YES, YES, YES, - YES, YES, 7000}, - {CTRY_MONACO, ETSI4_WORLD, "MC", "MONACO", YES, YES, YES, YES, YES, - YES, YES, 7000}, - {CTRY_MOROCCO, NULL1_WORLD, "MA", "MOROCCO", YES, NO, YES, YES, - YES, NO, NO, 7000}, - {CTRY_NEPAL, APL1_WORLD, "NP", "NEPAL", YES, NO, YES, YES, YES, - YES, YES, 7000}, - {CTRY_NETHERLANDS, ETSI1_WORLD, "NL", "NETHERLANDS", YES, NO, YES, - YES, YES, YES, YES, 7000}, - {CTRY_NETHERLANDS_ANTILLES, ETSI1_WORLD, "AN", - "NETHERLANDS-ANTILLES", YES, NO, YES, YES, YES, YES, YES, 7000}, - {CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ", "NEW ZEALAND", YES, NO, YES, - YES, YES, YES, NO, 7000}, - {CTRY_NORWAY, ETSI1_WORLD, "NO", "NORWAY", YES, NO, YES, YES, YES, - YES, YES, 7000}, - {CTRY_OMAN, APL6_WORLD, "OM", "OMAN", YES, NO, YES, YES, YES, YES, - NO, 7000}, - {CTRY_PAKISTAN, NULL1_WORLD, "PK", "PAKISTAN", YES, NO, YES, YES, - YES, NO, NO, 7000}, - {CTRY_PANAMA, FCC1_FCCA, "PA", "PANAMA", YES, YES, YES, YES, YES, - YES, YES, 7000}, - {CTRY_PAPUA_NEW_GUINEA, FCC1_WORLD, "PG", "PAPUA NEW GUINEA", YES, - YES, YES, YES, YES, YES, YES, 7000}, - {CTRY_PERU, APL1_WORLD, "PE", "PERU", YES, NO, YES, YES, YES, YES, - NO, 7000}, - {CTRY_PHILIPPINES, APL1_WORLD, "PH", "PHILIPPINES", YES, YES, YES, - YES, YES, YES, YES, 7000}, - {CTRY_POLAND, ETSI1_WORLD, "PL", "POLAND", YES, NO, YES, YES, YES, - YES, YES, 7000}, - {CTRY_PORTUGAL, ETSI1_WORLD, "PT", "PORTUGAL", YES, NO, YES, YES, - YES, YES, YES, 7000}, - {CTRY_PUERTO_RICO, FCC1_FCCA, "PR", "PUERTO RICO", YES, YES, YES, - YES, YES, YES, YES, 7000}, - {CTRY_QATAR, NULL1_WORLD, "QA", "QATAR", YES, NO, YES, YES, YES, - NO, NO, 7000}, - {CTRY_ROMANIA, NULL1_WORLD, "RO", "ROMANIA", YES, NO, YES, YES, - YES, NO, NO, 7000}, - {CTRY_RUSSIA, NULL1_WORLD, "RU", "RUSSIA", YES, NO, YES, YES, YES, - NO, NO, 7000}, - {CTRY_SAUDI_ARABIA, NULL1_WORLD, "SA", "SAUDI ARABIA", YES, NO, - YES, YES, YES, NO, NO, 7000}, - {CTRY_SERBIA_MONTENEGRO, ETSI1_WORLD, "CS", "SERBIA & MONTENEGRO", - YES, NO, YES, YES, YES, YES, YES, 7000}, - {CTRY_SINGAPORE, APL6_WORLD, "SG", "SINGAPORE", YES, YES, YES, YES, - YES, YES, YES, 7000}, - {CTRY_SLOVAKIA, ETSI1_WORLD, "SK", "SLOVAK REPUBLIC", YES, NO, YES, - YES, YES, YES, YES, 7000}, - {CTRY_SLOVENIA, ETSI1_WORLD, "SI", "SLOVENIA", YES, NO, YES, YES, - YES, YES, YES, 7000}, - {CTRY_SOUTH_AFRICA, FCC3_WORLD, "ZA", "SOUTH AFRICA", YES, NO, YES, - YES, YES, YES, NO, 7000}, - {CTRY_SPAIN, ETSI1_WORLD, "ES", "SPAIN", YES, NO, YES, YES, YES, - YES, YES, 7000}, - {CTRY_SRI_LANKA, FCC3_WORLD, "LK", "SRI LANKA", YES, NO, YES, YES, - YES, YES, NO, 7000}, - {CTRY_SWEDEN, ETSI1_WORLD, "SE", "SWEDEN", YES, NO, YES, YES, YES, - YES, YES, 7000}, - {CTRY_SWITZERLAND, ETSI1_WORLD, "CH", "SWITZERLAND", YES, NO, YES, - YES, YES, YES, YES, 7000}, - {CTRY_SYRIA, NULL1_WORLD, "SY", "SYRIA", YES, NO, YES, YES, YES, - NO, NO, 7000}, - {CTRY_TAIWAN, APL3_FCCA, "TW", "TAIWAN", YES, YES, YES, YES, YES, - YES, YES, 7000}, - {CTRY_THAILAND, NULL1_WORLD, "TH", "THAILAND", YES, NO, YES, YES, - YES, NO, NO, 7000}, - {CTRY_TRINIDAD_Y_TOBAGO, ETSI4_WORLD, "TT", "TRINIDAD & TOBAGO", - YES, NO, YES, YES, YES, YES, NO, 7000}, - {CTRY_TUNISIA, ETSI3_WORLD, "TN", "TUNISIA", YES, NO, YES, YES, - YES, YES, NO, 7000}, - {CTRY_TURKEY, ETSI3_WORLD, "TR", "TURKEY", YES, NO, YES, YES, YES, - YES, NO, 7000}, - {CTRY_UKRAINE, NULL1_WORLD, "UA", "UKRAINE", YES, NO, YES, YES, - YES, NO, NO, 7000}, - {CTRY_UAE, NULL1_WORLD, "AE", "UNITED ARAB EMIRATES", YES, NO, YES, - YES, YES, NO, NO, 7000}, - {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB", "UNITED KINGDOM", YES, NO, - YES, YES, YES, YES, YES, 7000}, - {CTRY_UNITED_STATES, FCC3_FCCA, "US", "UNITED STATES", YES, YES, - YES, YES, YES, YES, YES, 5825}, - {CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS", - "UNITED STATES (PUBLIC SAFETY)", YES, YES, YES, YES, YES, YES, - YES, 7000}, - {CTRY_URUGUAY, APL2_WORLD, "UY", "URUGUAY", YES, NO, YES, YES, YES, - YES, NO, 7000}, - {CTRY_UZBEKISTAN, FCC3_FCCA, "UZ", "UZBEKISTAN", YES, YES, YES, - YES, YES, YES, YES, 7000}, - {CTRY_VENEZUELA, APL2_ETSIC, "VE", "VENEZUELA", YES, NO, YES, YES, - YES, YES, NO, 7000}, - {CTRY_VIET_NAM, NULL1_WORLD, "VN", "VIET NAM", YES, NO, YES, YES, - YES, NO, NO, 7000}, - {CTRY_YEMEN, NULL1_WORLD, "YE", "YEMEN", YES, NO, YES, YES, YES, - NO, NO, 7000}, - {CTRY_ZIMBABWE, NULL1_WORLD, "ZW", "ZIMBABWE", YES, NO, YES, YES, - YES, NO, NO, 7000} -}; - -enum { - NO_DFS = 0x0000000000000000ULL, - DFS_FCC3 = 0x0000000000000001ULL, - DFS_ETSI = 0x0000000000000002ULL, - DFS_MKK4 = 0x0000000000000004ULL, -}; - -enum { - F1_4915_4925, - F1_4935_4945, - F1_4920_4980, - F1_4942_4987, - F1_4945_4985, - F1_4950_4980, - F1_5035_5040, - F1_5040_5080, - F1_5055_5055, - - F1_5120_5240, - - F1_5170_5230, - F2_5170_5230, - - F1_5180_5240, - F2_5180_5240, - F3_5180_5240, - F4_5180_5240, - F5_5180_5240, - F6_5180_5240, - F7_5180_5240, - F8_5180_5240, - - F1_5180_5320, - - F1_5240_5280, - - F1_5260_5280, - - F1_5260_5320, - F2_5260_5320, - F3_5260_5320, - F4_5260_5320, - F5_5260_5320, - F6_5260_5320, - - F1_5260_5700, - - F1_5280_5320, - - F1_5500_5580, - - F1_5500_5620, - - F1_5500_5700, - F2_5500_5700, - F3_5500_5700, - F4_5500_5700, - F5_5500_5700, - - F1_5660_5700, - - F1_5745_5805, - F2_5745_5805, - F3_5745_5805, - - F1_5745_5825, - F2_5745_5825, - F3_5745_5825, - F4_5745_5825, - F5_5745_5825, - F6_5745_5825, - - W1_4920_4980, - W1_5040_5080, - W1_5170_5230, - W1_5180_5240, - W1_5260_5320, - W1_5745_5825, - W1_5500_5700, - A_DEMO_ALL_CHANNELS -}; - -static struct RegDmnFreqBand regDmn5GhzFreq[] = { - {4915, 4925, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 16}, - {4935, 4945, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 16}, - {4920, 4980, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2, 7}, - {4942, 4987, 27, 6, 5, 5, NO_DFS, PSCAN_FCC, 0}, - {4945, 4985, 30, 6, 10, 5, NO_DFS, PSCAN_FCC, 0}, - {4950, 4980, 33, 6, 20, 5, NO_DFS, PSCAN_FCC, 0}, - {5035, 5040, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 12}, - {5040, 5080, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2, 2}, - {5055, 5055, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 12}, - - {5120, 5240, 5, 6, 20, 20, NO_DFS, NO_PSCAN, 0}, - - {5170, 5230, 23, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2, 1}, - {5170, 5230, 20, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2, 1}, - - {5180, 5240, 15, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0}, - {5180, 5240, 17, 6, 20, 20, NO_DFS, NO_PSCAN, 1}, - {5180, 5240, 18, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0}, - {5180, 5240, 20, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0}, - {5180, 5240, 23, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0}, - {5180, 5240, 23, 6, 20, 20, NO_DFS, PSCAN_FCC, 0}, - {5180, 5240, 20, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK3, 0}, - {5180, 5240, 23, 6, 20, 20, NO_DFS, NO_PSCAN, 0}, - - {5180, 5320, 20, 6, 20, 20, NO_DFS, PSCAN_ETSI, 0}, - - {5240, 5280, 23, 0, 20, 20, DFS_FCC3, PSCAN_FCC | PSCAN_ETSI, 0}, - - {5260, 5280, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI, - PSCAN_FCC | PSCAN_ETSI, 0}, - - {5260, 5320, 18, 0, 20, 20, DFS_FCC3 | DFS_ETSI, - PSCAN_FCC | PSCAN_ETSI, 0}, - - {5260, 5320, 20, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, - PSCAN_FCC | PSCAN_ETSI | PSCAN_MKK3, 0}, - - - {5260, 5320, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, - PSCAN_FCC | PSCAN_ETSI, 2}, - {5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2}, - {5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 0}, - {5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0}, - - {5260, 5700, 5, 6, 20, 20, DFS_FCC3 | DFS_ETSI, NO_PSCAN, 0}, - - {5280, 5320, 17, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 0}, - - {5500, 5580, 23, 6, 20, 20, DFS_FCC3, PSCAN_FCC, 0}, - - {5500, 5620, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0}, - - {5500, 5700, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 4}, - {5500, 5700, 27, 0, 20, 20, DFS_FCC3 | DFS_ETSI, - PSCAN_FCC | PSCAN_ETSI, 0}, - {5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, - PSCAN_FCC | PSCAN_ETSI, 0}, - {5500, 5700, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, - PSCAN_MKK3 | PSCAN_FCC, 0}, - {5500, 5700, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0}, - - {5660, 5700, 23, 6, 20, 20, DFS_FCC3, PSCAN_FCC, 0}, - - {5745, 5805, 23, 0, 20, 20, NO_DFS, NO_PSCAN, 0}, - {5745, 5805, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0}, - {5745, 5805, 30, 6, 20, 20, NO_DFS, PSCAN_ETSI, 0}, - {5745, 5825, 5, 6, 20, 20, NO_DFS, NO_PSCAN, 0}, - {5745, 5825, 17, 0, 20, 20, NO_DFS, NO_PSCAN, 0}, - {5745, 5825, 20, 0, 20, 20, NO_DFS, NO_PSCAN, 0}, - {5745, 5825, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0}, - {5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 3}, - {5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0}, - - - {4920, 4980, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0}, - {5040, 5080, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0}, - {5170, 5230, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0}, - {5180, 5240, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0}, - {5260, 5320, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0}, - {5745, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0}, - {5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0}, - {4920, 6100, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0}, -}; - -enum { - T1_5130_5650, - T1_5150_5670, - - T1_5200_5200, - T2_5200_5200, - T3_5200_5200, - T4_5200_5200, - T5_5200_5200, - T6_5200_5200, - T7_5200_5200, - T8_5200_5200, - - T1_5200_5280, - T2_5200_5280, - T3_5200_5280, - T4_5200_5280, - T5_5200_5280, - T6_5200_5280, - - T1_5200_5240, - T1_5210_5210, - T2_5210_5210, - T3_5210_5210, - T4_5210_5210, - T5_5210_5210, - T6_5210_5210, - T7_5210_5210, - T8_5210_5210, - T9_5210_5210, - T10_5210_5210, - T1_5240_5240, - - T1_5210_5250, - T1_5210_5290, - T2_5210_5290, - T3_5210_5290, - - T1_5280_5280, - T2_5280_5280, - T1_5290_5290, - T2_5290_5290, - T3_5290_5290, - T1_5250_5290, - T2_5250_5290, - T3_5250_5290, - T4_5250_5290, - - T1_5540_5660, - T2_5540_5660, - T3_5540_5660, - T1_5760_5800, - T2_5760_5800, - T3_5760_5800, - T4_5760_5800, - T5_5760_5800, - T6_5760_5800, - T7_5760_5800, - - T1_5765_5805, - T2_5765_5805, - T3_5765_5805, - T4_5765_5805, - T5_5765_5805, - T6_5765_5805, - T7_5765_5805, - T8_5765_5805, - T9_5765_5805, - - WT1_5210_5250, - WT1_5290_5290, - WT1_5540_5660, - WT1_5760_5800, -}; - -enum { - F1_2312_2372, - F2_2312_2372, - - F1_2412_2472, - F2_2412_2472, - F3_2412_2472, - - F1_2412_2462, - F2_2412_2462, - - F1_2432_2442, - - F1_2457_2472, - - F1_2467_2472, - - F1_2484_2484, - F2_2484_2484, - - F1_2512_2732, - - W1_2312_2372, - W1_2412_2412, - W1_2417_2432, - W1_2437_2442, - W1_2447_2457, - W1_2462_2462, - W1_2467_2467, - W2_2467_2467, - W1_2472_2472, - W2_2472_2472, - W1_2484_2484, - W2_2484_2484, -}; - -static struct RegDmnFreqBand regDmn2GhzFreq[] = { - {2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, - {2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, - - {2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, - {2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0}, - {2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, - - {2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, - {2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0}, - - {2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, - - {2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, - - {2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 0}, - - {2484, 2484, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, - {2484, 2484, 20, 0, 20, 5, NO_DFS, - PSCAN_MKKA | PSCAN_MKKA1 | PSCAN_MKKA2, 0}, - - {2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, - - {2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, - {2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, - {2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, - {2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, - {2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, - {2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, - {2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, - {2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, - {2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, - {2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, - {2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, - {2484, 2484, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, -}; - -enum { - G1_2312_2372, - G2_2312_2372, - - G1_2412_2472, - G2_2412_2472, - G3_2412_2472, - - G1_2412_2462, - G2_2412_2462, - - G1_2432_2442, - - G1_2457_2472, - - G1_2512_2732, - - G1_2467_2472, - - WG1_2312_2372, - WG1_2412_2462, - WG1_2467_2472, - WG2_2467_2472, - G_DEMO_ALL_CHANNELS -}; - -static struct RegDmnFreqBand regDmn2Ghz11gFreq[] = { - {2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, - {2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, - - {2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, - {2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G, 0}, - {2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, - - {2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, - {2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G, 0}, - - {2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, - - {2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, - - {2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, - - {2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 0}, - - {2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, - {2412, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, - {2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, - {2467, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, - {2312, 2732, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, -}; - -enum { - T1_2312_2372, - T1_2437_2437, - T2_2437_2437, - T3_2437_2437, - T1_2512_2732 + {CTRY_DEBUG, NO_ENUMRD, "DB"}, + {CTRY_DEFAULT, FCC1_FCCA, "CO"}, + {CTRY_ALBANIA, NULL1_WORLD, "AL"}, + {CTRY_ALGERIA, NULL1_WORLD, "DZ"}, + {CTRY_ARGENTINA, APL3_WORLD, "AR"}, + {CTRY_ARMENIA, ETSI4_WORLD, "AM"}, + {CTRY_AUSTRALIA, FCC2_WORLD, "AU"}, + {CTRY_AUSTRALIA2, FCC6_WORLD, "AU"}, + {CTRY_AUSTRIA, ETSI1_WORLD, "AT"}, + {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ"}, + {CTRY_BAHRAIN, APL6_WORLD, "BH"}, + {CTRY_BELARUS, ETSI1_WORLD, "BY"}, + {CTRY_BELGIUM, ETSI1_WORLD, "BE"}, + {CTRY_BELGIUM2, ETSI4_WORLD, "BL"}, + {CTRY_BELIZE, APL1_ETSIC, "BZ"}, + {CTRY_BOLIVIA, APL1_ETSIC, "BO"}, + {CTRY_BOSNIA_HERZ, ETSI1_WORLD, "BA"}, + {CTRY_BRAZIL, FCC3_WORLD, "BR"}, + {CTRY_BRUNEI_DARUSSALAM, APL1_WORLD, "BN"}, + {CTRY_BULGARIA, ETSI6_WORLD, "BG"}, + {CTRY_CANADA, FCC2_FCCA, "CA"}, + {CTRY_CANADA2, FCC6_FCCA, "CA"}, + {CTRY_CHILE, APL6_WORLD, "CL"}, + {CTRY_CHINA, APL1_WORLD, "CN"}, + {CTRY_COLOMBIA, FCC1_FCCA, "CO"}, + {CTRY_COSTA_RICA, FCC1_WORLD, "CR"}, + {CTRY_CROATIA, ETSI3_WORLD, "HR"}, + {CTRY_CYPRUS, ETSI1_WORLD, "CY"}, + {CTRY_CZECH, ETSI3_WORLD, "CZ"}, + {CTRY_DENMARK, ETSI1_WORLD, "DK"}, + {CTRY_DOMINICAN_REPUBLIC, FCC1_FCCA, "DO"}, + {CTRY_ECUADOR, FCC1_WORLD, "EC"}, + {CTRY_EGYPT, ETSI3_WORLD, "EG"}, + {CTRY_EL_SALVADOR, FCC1_WORLD, "SV"}, + {CTRY_ESTONIA, ETSI1_WORLD, "EE"}, + {CTRY_FINLAND, ETSI1_WORLD, "FI"}, + {CTRY_FRANCE, ETSI1_WORLD, "FR"}, + {CTRY_GEORGIA, ETSI4_WORLD, "GE"}, + {CTRY_GERMANY, ETSI1_WORLD, "DE"}, + {CTRY_GREECE, ETSI1_WORLD, "GR"}, + {CTRY_GUATEMALA, FCC1_FCCA, "GT"}, + {CTRY_HONDURAS, NULL1_WORLD, "HN"}, + {CTRY_HONG_KONG, FCC2_WORLD, "HK"}, + {CTRY_HUNGARY, ETSI1_WORLD, "HU"}, + {CTRY_ICELAND, ETSI1_WORLD, "IS"}, + {CTRY_INDIA, APL6_WORLD, "IN"}, + {CTRY_INDONESIA, APL1_WORLD, "ID"}, + {CTRY_IRAN, APL1_WORLD, "IR"}, + {CTRY_IRELAND, ETSI1_WORLD, "IE"}, + {CTRY_ISRAEL, NULL1_WORLD, "IL"}, + {CTRY_ITALY, ETSI1_WORLD, "IT"}, + {CTRY_JAMAICA, ETSI1_WORLD, "JM"}, + + {CTRY_JAPAN, MKK1_MKKA, "JP"}, + {CTRY_JAPAN1, MKK1_MKKB, "JP"}, + {CTRY_JAPAN2, MKK1_FCCA, "JP"}, + {CTRY_JAPAN3, MKK2_MKKA, "JP"}, + {CTRY_JAPAN4, MKK1_MKKA1, "JP"}, + {CTRY_JAPAN5, MKK1_MKKA2, "JP"}, + {CTRY_JAPAN6, MKK1_MKKC, "JP"}, + {CTRY_JAPAN7, MKK3_MKKB, "JP"}, + {CTRY_JAPAN8, MKK3_MKKA2, "JP"}, + {CTRY_JAPAN9, MKK3_MKKC, "JP"}, + {CTRY_JAPAN10, MKK4_MKKB, "JP"}, + {CTRY_JAPAN11, MKK4_MKKA2, "JP"}, + {CTRY_JAPAN12, MKK4_MKKC, "JP"}, + {CTRY_JAPAN13, MKK5_MKKB, "JP"}, + {CTRY_JAPAN14, MKK5_MKKA2, "JP"}, + {CTRY_JAPAN15, MKK5_MKKC, "JP"}, + {CTRY_JAPAN16, MKK6_MKKB, "JP"}, + {CTRY_JAPAN17, MKK6_MKKA2, "JP"}, + {CTRY_JAPAN18, MKK6_MKKC, "JP"}, + {CTRY_JAPAN19, MKK7_MKKB, "JP"}, + {CTRY_JAPAN20, MKK7_MKKA2, "JP"}, + {CTRY_JAPAN21, MKK7_MKKC, "JP"}, + {CTRY_JAPAN22, MKK8_MKKB, "JP"}, + {CTRY_JAPAN23, MKK8_MKKA2, "JP"}, + {CTRY_JAPAN24, MKK8_MKKC, "JP"}, + {CTRY_JAPAN25, MKK3_MKKA, "JP"}, + {CTRY_JAPAN26, MKK3_MKKA1, "JP"}, + {CTRY_JAPAN27, MKK3_FCCA, "JP"}, + {CTRY_JAPAN28, MKK4_MKKA1, "JP"}, + {CTRY_JAPAN29, MKK4_FCCA, "JP"}, + {CTRY_JAPAN30, MKK6_MKKA1, "JP"}, + {CTRY_JAPAN31, MKK6_FCCA, "JP"}, + {CTRY_JAPAN32, MKK7_MKKA1, "JP"}, + {CTRY_JAPAN33, MKK7_FCCA, "JP"}, + {CTRY_JAPAN34, MKK9_MKKA, "JP"}, + {CTRY_JAPAN35, MKK10_MKKA, "JP"}, + {CTRY_JAPAN36, MKK4_MKKA, "JP"}, + {CTRY_JAPAN37, MKK9_FCCA, "JP"}, + {CTRY_JAPAN38, MKK9_MKKA1, "JP"}, + {CTRY_JAPAN39, MKK9_MKKC, "JP"}, + {CTRY_JAPAN40, MKK9_MKKA2, "JP"}, + {CTRY_JAPAN41, MKK10_FCCA, "JP"}, + {CTRY_JAPAN42, MKK10_MKKA1, "JP"}, + {CTRY_JAPAN43, MKK10_MKKC, "JP"}, + {CTRY_JAPAN44, MKK10_MKKA2, "JP"}, + {CTRY_JAPAN45, MKK11_MKKA, "JP"}, + {CTRY_JAPAN46, MKK11_FCCA, "JP"}, + {CTRY_JAPAN47, MKK11_MKKA1, "JP"}, + {CTRY_JAPAN48, MKK11_MKKC, "JP"}, + {CTRY_JAPAN49, MKK11_MKKA2, "JP"}, + {CTRY_JAPAN50, MKK12_MKKA, "JP"}, + {CTRY_JAPAN51, MKK12_FCCA, "JP"}, + {CTRY_JAPAN52, MKK12_MKKA1, "JP"}, + {CTRY_JAPAN53, MKK12_MKKC, "JP"}, + {CTRY_JAPAN54, MKK12_MKKA2, "JP"}, + {CTRY_JAPAN57, MKK13_MKKB, "JP"}, + {CTRY_JAPAN58, MKK14_MKKA1, "JP"}, + {CTRY_JAPAN59, MKK15_MKKA1, "JP"}, + + {CTRY_JORDAN, ETSI2_WORLD, "JO"}, + {CTRY_KAZAKHSTAN, NULL1_WORLD, "KZ"}, + {CTRY_KOREA_NORTH, APL9_WORLD, "KP"}, + {CTRY_KOREA_ROC, APL9_WORLD, "KR"}, + {CTRY_KOREA_ROC2, APL2_WORLD, "K2"}, + {CTRY_KOREA_ROC3, APL9_WORLD, "K3"}, + {CTRY_KUWAIT, NULL1_WORLD, "KW"}, + {CTRY_LATVIA, ETSI1_WORLD, "LV"}, + {CTRY_LEBANON, NULL1_WORLD, "LB"}, + {CTRY_LIECHTENSTEIN, ETSI1_WORLD, "LI"}, + {CTRY_LITHUANIA, ETSI1_WORLD, "LT"}, + {CTRY_LUXEMBOURG, ETSI1_WORLD, "LU"}, + {CTRY_MACAU, FCC2_WORLD, "MO"}, + {CTRY_MACEDONIA, NULL1_WORLD, "MK"}, + {CTRY_MALAYSIA, APL8_WORLD, "MY"}, + {CTRY_MALTA, ETSI1_WORLD, "MT"}, + {CTRY_MEXICO, FCC1_FCCA, "MX"}, + {CTRY_MONACO, ETSI4_WORLD, "MC"}, + {CTRY_MOROCCO, NULL1_WORLD, "MA"}, + {CTRY_NEPAL, APL1_WORLD, "NP"}, + {CTRY_NETHERLANDS, ETSI1_WORLD, "NL"}, + {CTRY_NETHERLANDS_ANTILLES, ETSI1_WORLD, "AN"}, + {CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ"}, + {CTRY_NORWAY, ETSI1_WORLD, "NO"}, + {CTRY_OMAN, APL6_WORLD, "OM"}, + {CTRY_PAKISTAN, NULL1_WORLD, "PK"}, + {CTRY_PANAMA, FCC1_FCCA, "PA"}, + {CTRY_PAPUA_NEW_GUINEA, FCC1_WORLD, "PG"}, + {CTRY_PERU, APL1_WORLD, "PE"}, + {CTRY_PHILIPPINES, APL1_WORLD, "PH"}, + {CTRY_POLAND, ETSI1_WORLD, "PL"}, + {CTRY_PORTUGAL, ETSI1_WORLD, "PT"}, + {CTRY_PUERTO_RICO, FCC1_FCCA, "PR"}, + {CTRY_QATAR, NULL1_WORLD, "QA"}, + {CTRY_ROMANIA, NULL1_WORLD, "RO"}, + {CTRY_RUSSIA, NULL1_WORLD, "RU"}, + {CTRY_SAUDI_ARABIA, NULL1_WORLD, "SA"}, + {CTRY_SERBIA_MONTENEGRO, ETSI1_WORLD, "CS"}, + {CTRY_SINGAPORE, APL6_WORLD, "SG"}, + {CTRY_SLOVAKIA, ETSI1_WORLD, "SK"}, + {CTRY_SLOVENIA, ETSI1_WORLD, "SI"}, + {CTRY_SOUTH_AFRICA, FCC3_WORLD, "ZA"}, + {CTRY_SPAIN, ETSI1_WORLD, "ES"}, + {CTRY_SRI_LANKA, FCC3_WORLD, "LK"}, + {CTRY_SWEDEN, ETSI1_WORLD, "SE"}, + {CTRY_SWITZERLAND, ETSI1_WORLD, "CH"}, + {CTRY_SYRIA, NULL1_WORLD, "SY"}, + {CTRY_TAIWAN, APL3_FCCA, "TW"}, + {CTRY_THAILAND, NULL1_WORLD, "TH"}, + {CTRY_TRINIDAD_Y_TOBAGO, ETSI4_WORLD, "TT"}, + {CTRY_TUNISIA, ETSI3_WORLD, "TN"}, + {CTRY_TURKEY, ETSI3_WORLD, "TR"}, + {CTRY_UKRAINE, NULL1_WORLD, "UA"}, + {CTRY_UAE, NULL1_WORLD, "AE"}, + {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"}, + {CTRY_UNITED_STATES, FCC3_FCCA, "US"}, + /* This "PS" is for US public safety actually... to support this we + * would need to assign new special alpha2 to CRDA db as with the world + * regdomain and use another alpha2 */ + {CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS"}, + {CTRY_URUGUAY, APL2_WORLD, "UY"}, + {CTRY_UZBEKISTAN, FCC3_FCCA, "UZ"}, + {CTRY_VENEZUELA, APL2_ETSIC, "VE"}, + {CTRY_VIET_NAM, NULL1_WORLD, "VN"}, + {CTRY_YEMEN, NULL1_WORLD, "YE"}, + {CTRY_ZIMBABWE, NULL1_WORLD, "ZW"}, }; -static struct regDomain regDomains[] = { - - {DEBUG_REG_DMN, FCC, DFS_FCC3, NO_PSCAN, NO_REQ, - BM(A_DEMO_ALL_CHANNELS, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BM(T1_5130_5650, T1_5150_5670, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BM(T1_5200_5240, T1_5280_5280, T1_5540_5660, T1_5765_5805, -1, -1, - -1, -1, -1, -1, -1, -1), - BM(F1_2312_2372, F1_2412_2472, F1_2484_2484, F1_2512_2732, -1, -1, - -1, -1, -1, -1, -1, -1), - BM(G_DEMO_ALL_CHANNELS, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BM(T1_2312_2372, T1_2437_2437, T1_2512_2732, -1, -1, -1, -1, -1, - -1, -1, -1, -1)}, - - {APL1, FCC, NO_DFS, NO_PSCAN, NO_REQ, - BM(F4_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, - - {APL2, FCC, NO_DFS, NO_PSCAN, NO_REQ, - BM(F1_5745_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T2_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, - - {APL3, FCC, NO_DFS, NO_PSCAN, NO_REQ, - BM(F1_5280_5320, F2_5745_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BM(T1_5290_5290, T1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BM(T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, - - {APL4, FCC, NO_DFS, NO_PSCAN, NO_REQ, - BM(F4_5180_5240, F3_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BM(T1_5210_5210, T3_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BM(T1_5200_5200, T3_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BMZERO, - BMZERO, - BMZERO}, - - {APL5, FCC, NO_DFS, NO_PSCAN, NO_REQ, - BM(F2_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T4_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T4_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, - - {APL6, ETSI, DFS_ETSI, PSCAN_FCC_T | PSCAN_FCC, NO_REQ, - BM(F4_5180_5240, F2_5260_5320, F3_5745_5825, -1, -1, -1, -1, -1, - -1, -1, -1, -1), - BM(T2_5210_5210, T1_5250_5290, T1_5760_5800, -1, -1, -1, -1, -1, - -1, -1, -1, -1), - BM(T1_5200_5280, T5_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BMZERO, - BMZERO, - BMZERO}, - - {APL7, ETSI, DFS_ETSI, PSCAN_ETSI, NO_REQ, - BM(F1_5280_5320, F5_5500_5700, F3_5745_5805, -1, -1, -1, -1, -1, - -1, -1, -1, -1), - BM(T3_5290_5290, T5_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BM(T1_5540_5660, T6_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BMZERO, - BMZERO, - BMZERO}, - - {APL8, ETSI, NO_DFS, NO_PSCAN, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - BM(F6_5260_5320, F4_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BM(T2_5290_5290, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BM(T1_5280_5280, T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BMZERO, - BMZERO, - BMZERO}, - - {APL9, ETSI, DFS_ETSI, PSCAN_ETSI, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - BM(F1_5180_5320, F1_5500_5620, F3_5745_5805, -1, -1, -1, -1, -1, - -1, -1, -1, -1), - BM(T3_5290_5290, T5_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BM(T1_5540_5660, T6_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BMZERO, - BMZERO, - BMZERO}, - - {APL10, ETSI, DFS_ETSI, PSCAN_ETSI, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - BM(F1_5180_5320, F5_5500_5700, F3_5745_5805, -1, -1, -1, -1, -1, - -1, -1, -1, -1), - BM(T3_5290_5290, T5_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BM(T1_5540_5660, T6_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BMZERO, - BMZERO, - BMZERO}, - - {ETSI1, ETSI, DFS_ETSI, PSCAN_ETSI, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - BM(F4_5180_5240, F2_5260_5320, F2_5500_5700, -1, -1, -1, -1, -1, - -1, -1, -1, -1), - BM(T1_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T2_5200_5280, T2_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BMZERO, - BMZERO, - BMZERO}, - - {ETSI2, ETSI, DFS_ETSI, PSCAN_ETSI, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - BM(F3_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T3_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T2_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, - - {ETSI3, ETSI, DFS_ETSI, PSCAN_ETSI, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - BM(F4_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BM(T1_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T2_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, - - {ETSI4, ETSI, DFS_ETSI, PSCAN_ETSI, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - BM(F3_5180_5240, F1_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BM(T2_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T3_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, - - {ETSI5, ETSI, DFS_ETSI, PSCAN_ETSI, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - BM(F1_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T4_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T3_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, - - {ETSI6, ETSI, DFS_ETSI, PSCAN_ETSI, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - BM(F5_5180_5240, F1_5260_5280, F3_5500_5700, -1, -1, -1, -1, -1, - -1, -1, -1, -1), - BM(T1_5210_5250, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T4_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, - - {FCC1, FCC, NO_DFS, NO_PSCAN, NO_REQ, - BM(F2_5180_5240, F4_5260_5320, F5_5745_5825, -1, -1, -1, -1, -1, - -1, -1, -1, -1), - BM(T6_5210_5210, T2_5250_5290, T6_5760_5800, -1, -1, -1, -1, -1, - -1, -1, -1, -1), - BM(T1_5200_5240, T2_5280_5280, T7_5765_5805, -1, -1, -1, -1, -1, - -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, - - {FCC2, FCC, NO_DFS, NO_PSCAN, NO_REQ, - BM(F6_5180_5240, F5_5260_5320, F6_5745_5825, -1, -1, -1, -1, -1, - -1, -1, -1, -1), - BM(T7_5210_5210, T3_5250_5290, T2_5760_5800, -1, -1, -1, -1, -1, - -1, -1, -1, -1), - BM(T7_5200_5200, T1_5240_5240, T2_5280_5280, T1_5765_5805, -1, -1, - -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, - - {FCC3, FCC, DFS_FCC3, PSCAN_FCC | PSCAN_FCC_T, NO_REQ, - BM(F2_5180_5240, F3_5260_5320, F1_5500_5700, F5_5745_5825, -1, -1, - -1, -1, -1, -1, -1, -1), - BM(T6_5210_5210, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BM(T4_5200_5200, T8_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BMZERO, - BMZERO, - BMZERO}, - - {FCC4, FCC, DFS_FCC3, PSCAN_FCC | PSCAN_FCC_T, NO_REQ, - BM(F1_4942_4987, F1_4945_4985, F1_4950_4980, -1, -1, -1, -1, -1, - -1, -1, -1, -1), - BM(T8_5210_5210, T4_5250_5290, T7_5760_5800, -1, -1, -1, -1, -1, - -1, -1, -1, -1), - BM(T1_5200_5240, T1_5280_5280, T9_5765_5805, -1, -1, -1, -1, -1, - -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, - - {FCC5, FCC, NO_DFS, NO_PSCAN, NO_REQ, - BM(F2_5180_5240, F6_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BM(T6_5210_5210, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BM(T8_5200_5200, T7_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BMZERO, - BMZERO, - BMZERO}, - - {FCC6, FCC, DFS_FCC3, PSCAN_FCC, NO_REQ, - BM(F8_5180_5240, F5_5260_5320, F1_5500_5580, F1_5660_5700, - F6_5745_5825, -1, -1, -1, -1, -1, -1, -1), - BM(T7_5210_5210, T3_5250_5290, T2_5760_5800, -1, -1, -1, -1, -1, - -1, -1, -1, -1), - BM(T7_5200_5200, T1_5240_5240, T2_5280_5280, T1_5765_5805, -1, -1, - -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, - - {MKK1, MKK, NO_DFS, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB, - BM(F1_5170_5230, F4_5180_5240, F2_5260_5320, F4_5500_5700, -1, -1, - -1, -1, -1, -1, -1, -1), - BM(T7_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T5_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, - - {MKK2, MKK, NO_DFS, PSCAN_MKK2, DISALLOW_ADHOC_11A_TURB, - BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040, - F1_5055_5055, F1_5040_5080, F1_5170_5230, F4_5180_5240, - F2_5260_5320, F4_5500_5700, -1, -1), - BM(T7_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T5_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, - - - {MKK3, MKK, NO_DFS, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, - BM(F4_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T9_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T1_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, - - - {MKK4, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, - BM(F4_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BM(T10_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T6_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, - - - {MKK5, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, - BM(F4_5180_5240, F2_5260_5320, F4_5500_5700, -1, -1, -1, -1, -1, - -1, -1, -1, -1), - BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T5_5200_5280, T3_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BMZERO, - BMZERO, - BMZERO}, - - - {MKK6, MKK, NO_DFS, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB, - BM(F2_5170_5230, F4_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BM(T3_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T6_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, - - - {MKK7, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3, - DISALLOW_ADHOC_11A_TURB, - BM(F1_5170_5230, F4_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1, - -1, -1, -1, -1), - BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T5_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, - - - {MKK8, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3, - DISALLOW_ADHOC_11A_TURB, - BM(F1_5170_5230, F4_5180_5240, F2_5260_5320, F4_5500_5700, -1, -1, - -1, -1, -1, -1, -1, -1), - BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T5_5200_5280, T3_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BMZERO, - BMZERO, - BMZERO}, - - - {MKK9, MKK, NO_DFS, PSCAN_MKK2 | PSCAN_MKK3, - DISALLOW_ADHOC_11A_TURB, - BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040, - F1_5055_5055, F1_5040_5080, F4_5180_5240, -1, -1, -1, -1, -1), - BM(T9_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T1_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, - - - {MKK10, MKK, DFS_MKK4, PSCAN_MKK2 | PSCAN_MKK3, - DISALLOW_ADHOC_11A_TURB, - BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040, - F1_5055_5055, F1_5040_5080, F4_5180_5240, F2_5260_5320, -1, -1, - -1, -1), - BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T1_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, - - - {MKK11, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, - BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040, - F1_5055_5055, F1_5040_5080, F4_5180_5240, F2_5260_5320, - F4_5500_5700, -1, -1, -1), - BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T1_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, - - - {MKK12, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3, - DISALLOW_ADHOC_11A_TURB, - BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040, - F1_5055_5055, F1_5040_5080, F1_5170_5230, F4_5180_5240, - F2_5260_5320, F4_5500_5700, -1, -1), - BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T1_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO}, - - - {MKK13, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - BM(F1_5170_5230, F7_5180_5240, F2_5260_5320, F4_5500_5700, -1, -1, - -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, - - - {MKK14, MKK, DFS_MKK4, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB, - BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040, - F1_5040_5080, F1_5055_5055, F1_5170_5230, F4_5180_5240, -1, -1, - -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, - - - {MKK15, MKK, DFS_MKK4, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB, - BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040, - F1_5040_5080, F1_5055_5055, F1_5170_5230, F4_5180_5240, - F2_5260_5320, -1, -1, -1), - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO}, - - - {APLD, NO_CTL, NO_DFS, NO_PSCAN, NO_REQ, - BMZERO, - BMZERO, - BMZERO, - BM(F2_2312_2372, F2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BM(G2_2312_2372, G2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BMZERO}, - - {ETSIA, NO_CTL, NO_DFS, PSCAN_ETSIA, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - BMZERO, - BMZERO, - BMZERO, - BM(F1_2457_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(G1_2457_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, - - {ETSIB, ETSI, NO_DFS, PSCAN_ETSIB, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - BMZERO, - BMZERO, - BMZERO, - BM(F1_2432_2442, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(G1_2432_2442, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, - - {ETSIC, ETSI, NO_DFS, PSCAN_ETSIC, - DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, - BMZERO, - BMZERO, - BMZERO, - BM(F3_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(G3_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, - - {FCCA, FCC, NO_DFS, NO_PSCAN, NO_REQ, - BMZERO, - BMZERO, - BMZERO, - BM(F1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(G1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, - - {MKKA, MKK, NO_DFS, - PSCAN_MKKA | PSCAN_MKKA_G | PSCAN_MKKA1 | PSCAN_MKKA1_G | - PSCAN_MKKA2 | PSCAN_MKKA2_G, DISALLOW_ADHOC_11A_TURB, - BMZERO, - BMZERO, - BMZERO, - BM(F2_2412_2462, F1_2467_2472, F2_2484_2484, -1, -1, -1, -1, -1, - -1, -1, -1, -1), - BM(G2_2412_2462, G1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1), - BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, - - {MKKC, MKK, NO_DFS, NO_PSCAN, NO_REQ, - BMZERO, - BMZERO, - BMZERO, - BM(F2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(G2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, - - {WORLD, ETSI, NO_DFS, NO_PSCAN, NO_REQ, - BMZERO, - BMZERO, - BMZERO, - BM(F2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(G2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, - - {WOR0_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D, - BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, - W1_5500_5700, -1, -1, -1, -1, -1, -1, -1), - BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, - -1, -1, -1, -1, -1), - BMZERO, - BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, - W1_2417_2432, W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1, - -1, -1), - BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1), - BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, - - {WOR01_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, - ADHOC_PER_11D, - BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, - W1_5500_5700, -1, -1, -1, -1, -1, -1, -1), - BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, - -1, -1, -1, -1, -1), - BMZERO, - BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2417_2432, - W1_2447_2457, -1, -1, -1, -1, -1, -1, -1), - BM(WG1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, - - {WOR02_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, - ADHOC_PER_11D, - BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, - W1_5500_5700, -1, -1, -1, -1, -1, -1, -1), - BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, - -1, -1, -1, -1, -1), - BMZERO, - BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, - W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), - BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1), - BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, - - {EU1_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D, - BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, - W1_5500_5700, -1, -1, -1, -1, -1, -1, -1), - BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, - -1, -1, -1, -1, -1), - BMZERO, - BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W2_2472_2472, - W1_2417_2432, W1_2447_2457, W2_2467_2467, -1, -1, -1, -1, -1), - BM(WG1_2412_2462, WG2_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1), - BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, - - {WOR1_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, - BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, - W1_5500_5700, -1, -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, - W1_2417_2432, W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1, - -1, -1), - BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1), - BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, - - {WOR2_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, - BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, - W1_5500_5700, -1, -1, -1, -1, -1, -1, -1), - BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, - -1, -1, -1, -1, -1), - BMZERO, - BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, - W1_2417_2432, W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1, - -1, -1), - BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1), - BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, - - {WOR3_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D, - BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, -1, -1, - -1, -1, -1, -1, -1, -1), - BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, - -1, -1, -1, -1, -1), - BMZERO, - BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, - W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), - BM(WG1_2412_2462, WG2_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1), - BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, - - {WOR4_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, - BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, -1, -1, -1, -1, -1, - -1, -1, -1, -1), - BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, - -1, -1, -1, -1, -1), - BMZERO, - BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2417_2432, - W1_2447_2457, -1, -1, -1, -1, -1, -1, -1), - BM(WG1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, - - {WOR5_ETSIC, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, - BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, -1, -1, -1, -1, -1, - -1, -1, -1, -1), - BMZERO, - BMZERO, - BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, - W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), - BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1), - BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, - - {WOR9_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, - BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, W1_5500_5700, -1, -1, - -1, -1, -1, -1, -1, -1), - BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, - -1, -1, -1, -1, -1), - BMZERO, - BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2417_2432, - W1_2447_2457, -1, -1, -1, -1, -1, -1, -1), - BM(WG1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), - BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, - - {WORA_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, - BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, W1_5500_5700, -1, -1, - -1, -1, -1, -1, -1, -1), - BMZERO, - BMZERO, - BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, - W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), - BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1), - BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, - - {WORB_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, - BM(W1_5260_5320, W1_5180_5240, W1_5500_5700, -1, -1, -1, -1, -1, - -1, -1, -1, -1), - BMZERO, - BMZERO, - BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, - W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), - BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1), - BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, - - {NULL1, NO_CTL, NO_DFS, NO_PSCAN, NO_REQ, - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO, - BMZERO} -}; - -static const struct cmode modes[] = { - {ATH9K_MODE_11A, CHANNEL_A}, - {ATH9K_MODE_11B, CHANNEL_B}, - {ATH9K_MODE_11G, CHANNEL_G}, - {ATH9K_MODE_11NG_HT20, CHANNEL_G_HT20}, - {ATH9K_MODE_11NG_HT40PLUS, CHANNEL_G_HT40PLUS}, - {ATH9K_MODE_11NG_HT40MINUS, CHANNEL_G_HT40MINUS}, - {ATH9K_MODE_11NA_HT20, CHANNEL_A_HT20}, - {ATH9K_MODE_11NA_HT40PLUS, CHANNEL_A_HT40PLUS}, - {ATH9K_MODE_11NA_HT40MINUS, CHANNEL_A_HT40MINUS}, -}; - -static struct japan_bandcheck j_bandcheck[] = { - {F1_5170_5230, AR_EEPROM_EEREGCAP_EN_KK_U1_ODD}, - {F4_5180_5240, AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN}, - {F2_5260_5320, AR_EEPROM_EEREGCAP_EN_KK_U2}, - {F4_5500_5700, AR_EEPROM_EEREGCAP_EN_KK_MIDBAND} -}; - - #endif -- GitLab From ae54c985cc7daa502da6e7eb3b223a30fbbf4cfb Mon Sep 17 00:00:00 2001 From: Alina Friedrichsen Date: Fri, 23 Jan 2009 05:33:37 +0100 Subject: [PATCH 0928/4982] mac80211: Read the TSF via debugfs This patch adds an low-level driver independent entry to read the TSF value into the debugfs of mac80211. This makes debugging the IBSS handling of wifi drivers easier. Signed-off-by: Alina Friedrichsen Signed-off-by: John W. Linville --- net/mac80211/debugfs.c | 4 ++++ net/mac80211/ieee80211_i.h | 1 + 2 files changed, 5 insertions(+) diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 18541bb7509..717d5484e1e 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -61,6 +61,8 @@ DEBUGFS_READONLY_FILE(wep_iv, 20, "%#06x", local->wep_iv & 0xffffff); DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s", local->rate_ctrl ? local->rate_ctrl->ops->name : ""); +DEBUGFS_READONLY_FILE(tsf, 20, "%#018llx", + (unsigned long long) (local->ops->get_tsf ? local->ops->get_tsf(local_to_hw(local)) : 0)); /* statistics stuff */ @@ -202,6 +204,7 @@ void debugfs_hw_add(struct ieee80211_local *local) DEBUGFS_ADD(long_retry_limit); DEBUGFS_ADD(total_ps_buffered); DEBUGFS_ADD(wep_iv); + DEBUGFS_ADD(tsf); statsd = debugfs_create_dir("statistics", phyd); local->debugfs.statistics = statsd; @@ -255,6 +258,7 @@ void debugfs_hw_del(struct ieee80211_local *local) DEBUGFS_DEL(long_retry_limit); DEBUGFS_DEL(total_ps_buffered); DEBUGFS_DEL(wep_iv); + DEBUGFS_DEL(tsf); DEBUGFS_STATS_DEL(transmitted_fragment_count); DEBUGFS_STATS_DEL(multicast_transmitted_frame_count); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 70366efc792..927cbde8c19 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -744,6 +744,7 @@ struct ieee80211_local { struct dentry *long_retry_limit; struct dentry *total_ps_buffered; struct dentry *wep_iv; + struct dentry *tsf; struct dentry *statistics; struct local_debugfsdentries_statsdentries { struct dentry *transmitted_fragment_count; -- GitLab From 8cab7581dba90b0519e25784e08feb5dedde737f Mon Sep 17 00:00:00 2001 From: Alina Friedrichsen Date: Fri, 23 Jan 2009 05:39:13 +0100 Subject: [PATCH 0929/4982] ath5k: Read and write the TSF via debugfs This patch updates the ath5k specific entry in the debugfs to read and reset the TSF value, to allowing write it, too. This makes debugging the IBSS handling of wifi drivers _much_ easier. Signed-off-by: Alina Friedrichsen Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/ath5k.h | 1 + drivers/net/wireless/ath5k/debug.c | 11 +++++++++-- drivers/net/wireless/ath5k/pcu.c | 17 +++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index 183ffc8e62c..0eda785fe62 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h @@ -1206,6 +1206,7 @@ extern void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter); /* Beacon control functions */ extern u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah); extern u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); +extern void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); extern void ath5k_hw_reset_tsf(struct ath5k_hw *ah); extern void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); #if 0 diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c index d281b6e3862..129b72684da 100644 --- a/drivers/net/wireless/ath5k/debug.c +++ b/drivers/net/wireless/ath5k/debug.c @@ -210,15 +210,22 @@ static ssize_t write_file_tsf(struct file *file, size_t count, loff_t *ppos) { struct ath5k_softc *sc = file->private_data; - char buf[20]; + char buf[21]; + unsigned long long tsf; - if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) + if (copy_from_user(buf, userbuf, min(count, sizeof(buf) - 1))) return -EFAULT; + buf[sizeof(buf) - 1] = '\0'; if (strncmp(buf, "reset", 5) == 0) { ath5k_hw_reset_tsf(sc->ah); printk(KERN_INFO "debugfs reset TSF\n"); + } else { + tsf = simple_strtoul(buf, NULL, 0); + ath5k_hw_set_tsf64(sc->ah, tsf); + printk(KERN_INFO "debugfs set TSF to %#018llx\n", tsf); } + return count; } diff --git a/drivers/net/wireless/ath5k/pcu.c b/drivers/net/wireless/ath5k/pcu.c index 86f53a55b0f..f8a4a696027 100644 --- a/drivers/net/wireless/ath5k/pcu.c +++ b/drivers/net/wireless/ath5k/pcu.c @@ -645,6 +645,23 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32); } +/** + * ath5k_hw_set_tsf64 - Set a new 64bit TSF + * + * @ah: The &struct ath5k_hw + * @tsf64: The new 64bit TSF + * + * Sets the new TSF + */ +void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64) +{ + ATH5K_TRACE(ah->ah_sc); + + ath5k_hw_reg_write(ah, 0x00000000, AR5K_TSF_L32); + ath5k_hw_reg_write(ah, (tsf64 >> 32) & 0xffffffff, AR5K_TSF_U32); + ath5k_hw_reg_write(ah, tsf64 & 0xffffffff, AR5K_TSF_L32); +} + /** * ath5k_hw_reset_tsf - Force a TSF reset * -- GitLab From 27abe060aa9d3410545ef663676c7183fc2512c6 Mon Sep 17 00:00:00 2001 From: Alina Friedrichsen Date: Fri, 23 Jan 2009 05:44:21 +0100 Subject: [PATCH 0930/4982] ath9k: Read and write the TSF via debugfs This patch adds an ath9k specific entry to read, write and reset the TSF into the debugfs, like in ath5k. This makes debugging the IBSS handling of wifi drivers _much_ easier. Signed-off-by: Alina Friedrichsen Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ath9k.h | 1 + drivers/net/wireless/ath9k/core.h | 1 + drivers/net/wireless/ath9k/debug.c | 49 ++++++++++++++++++++++++++++++ drivers/net/wireless/ath9k/hw.c | 7 +++++ 4 files changed, 58 insertions(+) diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index f158cba0140..f44aab50a2d 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -899,6 +899,7 @@ void ath9k_hw_getbssidmask(struct ath_hal *ah, u8 *mask); bool ath9k_hw_setbssidmask(struct ath_hal *ah, const u8 *mask); void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid, u16 assocId); u64 ath9k_hw_gettsf64(struct ath_hal *ah); +void ath9k_hw_settsf64(struct ath_hal *ah, u64 tsf64); void ath9k_hw_reset_tsf(struct ath_hal *ah); bool ath9k_hw_set_tsfadjust(struct ath_hal *ah, u32 setting); bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us); diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index 29251f8dabb..acbd8881ef8 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -141,6 +141,7 @@ struct ath9k_debug { struct dentry *debugfs_phy; struct dentry *debugfs_dma; struct dentry *debugfs_interrupt; + struct dentry *debugfs_tsf; struct ath_stats stats; }; diff --git a/drivers/net/wireless/ath9k/debug.c b/drivers/net/wireless/ath9k/debug.c index a80ed576830..05e1f82cc7a 100644 --- a/drivers/net/wireless/ath9k/debug.c +++ b/drivers/net/wireless/ath9k/debug.c @@ -222,6 +222,49 @@ static const struct file_operations fops_interrupt = { .owner = THIS_MODULE }; + +static ssize_t read_file_tsf(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + char buf[100]; + snprintf(buf, sizeof(buf), "0x%016llx\n", + (unsigned long long)ath9k_hw_gettsf64(sc->sc_ah)); + return simple_read_from_buffer(user_buf, count, ppos, buf, 19); +} + +static ssize_t write_file_tsf(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + char buf[21]; + unsigned long long tsf; + + if (copy_from_user(buf, user_buf, min(count, sizeof(buf) - 1))) + return -EFAULT; + buf[sizeof(buf) - 1] = '\0'; + + if (strncmp(buf, "reset", 5) == 0) { + ath9k_hw_reset_tsf(sc->sc_ah); + printk(KERN_INFO "debugfs reset TSF\n"); + } else { + tsf = simple_strtoul(buf, NULL, 0); + ath9k_hw_settsf64(sc->sc_ah, tsf); + printk(KERN_INFO "debugfs set TSF to %#018llx\n", tsf); + } + + return count; +} + +static const struct file_operations fops_tsf = { + .read = read_file_tsf, + .write = write_file_tsf, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE +}; + + int ath9k_init_debug(struct ath_softc *sc) { sc->sc_debug.debug_mask = ath9k_debug; @@ -247,6 +290,11 @@ int ath9k_init_debug(struct ath_softc *sc) if (!sc->sc_debug.debugfs_interrupt) goto err; + sc->sc_debug.debugfs_tsf = debugfs_create_file("tsf", S_IRUGO, + sc->sc_debug.debugfs_phy, sc, &fops_tsf); + if (!sc->sc_debug.debugfs_tsf) + goto err; + return 0; err: ath9k_exit_debug(sc); @@ -255,6 +303,7 @@ err: void ath9k_exit_debug(struct ath_softc *sc) { + debugfs_remove(sc->sc_debug.debugfs_tsf); debugfs_remove(sc->sc_debug.debugfs_interrupt); debugfs_remove(sc->sc_debug.debugfs_dma); debugfs_remove(sc->sc_debug.debugfs_phy); diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index f2922bab776..1a49743151b 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -3755,6 +3755,13 @@ u64 ath9k_hw_gettsf64(struct ath_hal *ah) return tsf; } +void ath9k_hw_settsf64(struct ath_hal *ah, u64 tsf64) +{ + REG_WRITE(ah, AR_TSF_L32, 0x00000000); + REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff); + REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff); +} + void ath9k_hw_reset_tsf(struct ath_hal *ah) { int count; -- GitLab From eb2599ca25be212bd37dd3e90ef13ea45758e838 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 23 Jan 2009 11:20:44 +0530 Subject: [PATCH 0931/4982] ath9k: Fix MCS rates registration bug for AR9285 AR9285 based devices support only single stream MCS rates. This patch fixes a bug where dual stream stream rates were also being registered. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 561a2c3adbb..15a7f90bc84 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -854,7 +854,8 @@ static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key) } } -static void setup_ht_cap(struct ieee80211_sta_ht_cap *ht_info) +static void setup_ht_cap(struct ath_softc *sc, + struct ieee80211_sta_ht_cap *ht_info) { #define ATH9K_HT_CAP_MAXRXAMPDU_65536 0x3 /* 2 ^ 16 */ #define ATH9K_HT_CAP_MPDUDENSITY_8 0x6 /* 8 usec */ @@ -867,10 +868,22 @@ static void setup_ht_cap(struct ieee80211_sta_ht_cap *ht_info) ht_info->ampdu_factor = ATH9K_HT_CAP_MAXRXAMPDU_65536; ht_info->ampdu_density = ATH9K_HT_CAP_MPDUDENSITY_8; + /* set up supported mcs set */ memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); - ht_info->mcs.rx_mask[0] = 0xff; - ht_info->mcs.rx_mask[1] = 0xff; + + switch(sc->sc_rx_chainmask) { + case 1: + ht_info->mcs.rx_mask[0] = 0xff; + break; + case 5: + case 7: + default: + ht_info->mcs.rx_mask[0] = 0xff; + ht_info->mcs.rx_mask[1] = 0xff; + break; + } + ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; } @@ -1549,9 +1562,9 @@ int ath_attach(u16 devid, struct ath_softc *sc) hw->rate_control_algorithm = "ath9k_rate_control"; if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) { - setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); + setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) - setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); + setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); } hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &sc->sbands[IEEE80211_BAND_2GHZ]; -- GitLab From f8206e053498174ef4b5f994e2a7091a74f7da30 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 23 Jan 2009 11:20:51 +0530 Subject: [PATCH 0932/4982] ath9k: Fix bug in rate control capability registration Dual stream capability must be registered only when the hardware supports it. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/rc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 46172b5f492..8e1528d487b 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -1358,7 +1358,9 @@ static void ath_rc_init(struct ath_softc *sc, } if (sta->ht_cap.ht_supported) { - ath_rc_priv->ht_cap = (WLAN_RC_HT_FLAG | WLAN_RC_DS_FLAG); + ath_rc_priv->ht_cap = WLAN_RC_HT_FLAG; + if (sc->sc_tx_chainmask != 1) + ath_rc_priv->ht_cap |= WLAN_RC_DS_FLAG; if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ath_rc_priv->ht_cap |= WLAN_RC_40_FLAG; if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) -- GitLab From 5dad40c13e7753e7b62eb7c2fca9b4034679882a Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 23 Jan 2009 11:20:55 +0530 Subject: [PATCH 0933/4982] ath9k: Fix bug in NF calibration The number of chainmasks for AR9285 weren't being setup when running NF calibration. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/calib.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c index d16f9fe48a9..c6d1de0f1e2 100644 --- a/drivers/net/wireless/ath9k/calib.c +++ b/drivers/net/wireless/ath9k/calib.c @@ -620,7 +620,9 @@ void ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan) }; u8 chainmask; - if (AR_SREV_9280(ah)) + if (AR_SREV_9285(ah)) + chainmask = 0x9; + else if (AR_SREV_9280(ah)) chainmask = 0x1B; else chainmask = 0x3F; -- GitLab From 3aa24e6031a0ca7a8803a103f5c183cd94e5ac98 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Fri, 23 Jan 2009 14:40:36 +0530 Subject: [PATCH 0934/4982] ath9k: Remove unused ath9k_hw_select_antconfig() from hw.c Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ath9k.h | 1 - drivers/net/wireless/ath9k/hw.c | 21 --------------------- 2 files changed, 22 deletions(-) diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index f44aab50a2d..455a53649b3 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -874,7 +874,6 @@ void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 val); #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) void ath9k_enable_rfkill(struct ath_hal *ah); #endif -int ath9k_hw_select_antconfig(struct ath_hal *ah, u32 cfg); u32 ath9k_hw_getdefantenna(struct ath_hal *ah); void ath9k_hw_setantenna(struct ath_hal *ah, u32 antenna); bool ath9k_hw_setantennaswitch(struct ath_hal *ah, diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 1a49743151b..bb8628c7efa 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -3542,27 +3542,6 @@ void ath9k_enable_rfkill(struct ath_hal *ah) } #endif -int ath9k_hw_select_antconfig(struct ath_hal *ah, u32 cfg) -{ - struct ath9k_channel *chan = ah->ah_curchan; - const struct ath9k_hw_capabilities *pCap = &ah->ah_caps; - u16 ant_config; - u32 halNumAntConfig; - - halNumAntConfig = IS_CHAN_2GHZ(chan) ? - pCap->num_antcfg_2ghz : pCap->num_antcfg_5ghz; - - if (cfg < halNumAntConfig) { - if (!ath9k_hw_get_eeprom_antenna_cfg(ah, chan, - cfg, &ant_config)) { - REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config); - return 0; - } - } - - return -EINVAL; -} - u32 ath9k_hw_getdefantenna(struct ath_hal *ah) { return REG_READ(ah, AR_DEF_ANTENNA) & 0x7; -- GitLab From 81b1e19ac2cadc2f8a05c82ffb1abe20a0594d1f Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Fri, 23 Jan 2009 14:40:37 +0530 Subject: [PATCH 0935/4982] ath9k: Clean up the way the eeprom antenna configuration is read Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ath9k.h | 5 +-- drivers/net/wireless/ath9k/eeprom.c | 63 +++++++---------------------- 2 files changed, 17 insertions(+), 51 deletions(-) diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index 455a53649b3..5289d287811 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -974,9 +974,8 @@ bool ath9k_hw_set_power_cal_table(struct ath_hal *ah, int16_t *pTxPowerIndexOffset); bool ath9k_hw_eeprom_set_board_values(struct ath_hal *ah, struct ath9k_channel *chan); -int ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal *ah, - struct ath9k_channel *chan, - u8 index, u16 *config); +u16 ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal *ah, + struct ath9k_channel *chan); u8 ath9k_hw_get_num_ant_config(struct ath_hal *ah, enum ieee80211_band freq_band); u16 ath9k_hw_eeprom_get_spur_chan(struct ath_hal *ah, u16 i, bool is2GHz); diff --git a/drivers/net/wireless/ath9k/eeprom.c b/drivers/net/wireless/ath9k/eeprom.c index 50cb3883416..5038907e743 100644 --- a/drivers/net/wireless/ath9k/eeprom.c +++ b/drivers/net/wireless/ath9k/eeprom.c @@ -2085,14 +2085,13 @@ static bool ath9k_hw_eeprom_set_def_board_values(struct ath_hal *ah, struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def; int i, regChainOffset; u8 txRxAttenLocal; - u16 ant_config; pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44; - ath9k_hw_get_eeprom_antenna_cfg(ah, chan, 0, &ant_config); - REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config); + REG_WRITE(ah, AR_PHY_SWITCH_COM, + ath9k_hw_get_eeprom_antenna_cfg(ah, chan)); for (i = 0; i < AR5416_MAX_CHAINS; i++) { if (AR_SREV_9280(ah)) { @@ -2330,7 +2329,6 @@ static bool ath9k_hw_eeprom_set_4k_board_values(struct ath_hal *ah, struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k; int regChainOffset; u8 txRxAttenLocal; - u16 ant_config = 0; u8 ob[5], db1[5], db2[5]; u8 ant_div_control1, ant_div_control2; u32 regVal; @@ -2340,8 +2338,8 @@ static bool ath9k_hw_eeprom_set_4k_board_values(struct ath_hal *ah, txRxAttenLocal = 23; - ath9k_hw_get_eeprom_antenna_cfg(ah, chan, 0, &ant_config); - REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config); + REG_WRITE(ah, AR_PHY_SWITCH_COM, + ath9k_hw_get_eeprom_antenna_cfg(ah, chan)); regChainOffset = 0; REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, @@ -2524,70 +2522,39 @@ bool ath9k_hw_eeprom_set_board_values(struct ath_hal *ah, return ath9k_eeprom_set_board_values[ahp->ah_eep_map](ah, chan); } -static int ath9k_hw_get_def_eeprom_antenna_cfg(struct ath_hal *ah, - struct ath9k_channel *chan, - u8 index, u16 *config) +static u16 ath9k_hw_get_def_eeprom_antenna_cfg(struct ath_hal *ah, + struct ath9k_channel *chan) { struct ath_hal_5416 *ahp = AH5416(ah); struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def; struct modal_eep_header *pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); - struct base_eep_header *pBase = &eep->baseEepHeader; - switch (index) { - case 0: - *config = pModal->antCtrlCommon & 0xFFFF; - return 0; - case 1: - if (pBase->version >= 0x0E0D) { - if (pModal->useAnt1) { - *config = - ((pModal->antCtrlCommon & 0xFFFF0000) >> 16); - return 0; - } - } - break; - default: - break; - } - - return -EINVAL; + return pModal->antCtrlCommon & 0xFFFF; } -static int ath9k_hw_get_4k_eeprom_antenna_cfg(struct ath_hal *ah, - struct ath9k_channel *chan, - u8 index, u16 *config) +static u16 ath9k_hw_get_4k_eeprom_antenna_cfg(struct ath_hal *ah, + struct ath9k_channel *chan) { struct ath_hal_5416 *ahp = AH5416(ah); struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k; struct modal_eep_4k_header *pModal = &eep->modalHeader; - switch (index) { - case 0: - *config = pModal->antCtrlCommon & 0xFFFF; - return 0; - default: - break; - } - - return -EINVAL; + return pModal->antCtrlCommon & 0xFFFF; } -static int (*ath9k_get_eeprom_antenna_cfg[])(struct ath_hal *, - struct ath9k_channel *, - u8, u16 *) = { +static u16 (*ath9k_get_eeprom_antenna_cfg[])(struct ath_hal *, + struct ath9k_channel *) = { ath9k_hw_get_def_eeprom_antenna_cfg, ath9k_hw_get_4k_eeprom_antenna_cfg }; -int ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal *ah, - struct ath9k_channel *chan, - u8 index, u16 *config) +u16 ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal *ah, + struct ath9k_channel *chan) { struct ath_hal_5416 *ahp = AH5416(ah); - return ath9k_get_eeprom_antenna_cfg[ahp->ah_eep_map](ah, chan, - index, config); + return ath9k_get_eeprom_antenna_cfg[ahp->ah_eep_map](ah, chan); } static u8 ath9k_hw_get_4k_num_ant_config(struct ath_hal *ah, -- GitLab From 6ba265e9cc764bc401cda284954cf2bdd4408c38 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Fri, 23 Jan 2009 17:03:06 +0100 Subject: [PATCH 0936/4982] rt2x00: rt2x00_rev() should return u32 The "rev" field in chipset definition is an u32, which means that rt2x00_rev() which returns that field should be of the same type. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 46918deceda..2a9909dd551 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -868,7 +868,7 @@ static inline char rt2x00_rf(const struct rt2x00_chip *chipset, const u16 chip) return (chipset->rf == chip); } -static inline u16 rt2x00_rev(const struct rt2x00_chip *chipset) +static inline u32 rt2x00_rev(const struct rt2x00_chip *chipset) { return chipset->rev; } -- GitLab From 9752a7bd7f36557f34283f5d75dfa32578437f08 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Fri, 23 Jan 2009 17:03:24 +0100 Subject: [PATCH 0937/4982] rt2x00: Restrict firmware file lengths Add extra security to the drivers for firmware loading, check the firmware file length before uploading it to the hardware. Incorrect lengths might indicate a firmware upgrade (which is not yet supported by the driver) or otherwise incorrect firmware. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt61pci.c | 5 +++++ drivers/net/wireless/rt2x00/rt73usb.c | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 3a7eccac885..d81a8de9dc1 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1199,6 +1199,11 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, const void *data, int i; u32 reg; + if (len != 8192) { + ERROR(rt2x00dev, "Invalid firmware file length (len=%zu)\n", len); + return -ENOENT; + } + /* * Wait for stable hardware. */ diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 60c43c11bc1..f854551be75 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1085,6 +1085,11 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, const void *data, int status; u32 reg; + if (len != 2048) { + ERROR(rt2x00dev, "Invalid firmware file length (len=%zu)\n", len); + return -ENOENT; + } + /* * Wait for stable hardware. */ -- GitLab From 0712612741e1dccf10353c70ebe90ba8cc60d5fb Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Fri, 23 Jan 2009 17:04:05 +0100 Subject: [PATCH 0938/4982] rt2x00: Simplify suspend/resume handling With mac80211 handling all open interfaces during suspend and resume we can simplify suspend/resume within rt2x00lib. The only thing rt2x00 needs to do is free up memory during suspend and bring back the minimal required components during resume. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 1 - drivers/net/wireless/rt2x00/rt2x00dev.c | 93 ++----------------------- 2 files changed, 5 insertions(+), 89 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 2a9909dd551..d0a82563818 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -575,7 +575,6 @@ enum rt2x00_flags { DEVICE_STATE_REGISTERED_HW, DEVICE_STATE_INITIALIZED, DEVICE_STATE_STARTED, - DEVICE_STATE_STARTED_SUSPEND, DEVICE_STATE_ENABLED_RADIO, DEVICE_STATE_DISABLED_RADIO_HW, diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index cd4447502d8..e1b40545a9b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -881,23 +881,17 @@ EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev); #ifdef CONFIG_PM int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state) { - int retval; - NOTICE(rt2x00dev, "Going to sleep.\n"); /* - * Only continue if mac80211 has open interfaces. + * Prevent mac80211 from accessing driver while suspended. */ - if (!test_and_clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || - !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) - goto exit; - - set_bit(DEVICE_STATE_STARTED_SUSPEND, &rt2x00dev->flags); + if (!test_and_clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) + return 0; /* - * Disable radio. + * Cleanup as much as possible. */ - rt2x00lib_stop(rt2x00dev); rt2x00lib_uninitialize(rt2x00dev); /* @@ -906,7 +900,6 @@ int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state) rt2x00leds_suspend(rt2x00dev); rt2x00debug_deregister(rt2x00dev); -exit: /* * Set device mode to sleep for power management, * on some hardware this call seems to consistently fail. @@ -918,8 +911,7 @@ exit: * the radio and the other components already disabled the * device is as good as disabled. */ - retval = rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_SLEEP); - if (retval) + if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_SLEEP)) WARNING(rt2x00dev, "Device failed to enter sleep state, " "continue suspending.\n"); @@ -927,34 +919,8 @@ exit: } EXPORT_SYMBOL_GPL(rt2x00lib_suspend); -static void rt2x00lib_resume_intf(void *data, u8 *mac, - struct ieee80211_vif *vif) -{ - struct rt2x00_dev *rt2x00dev = data; - struct rt2x00_intf *intf = vif_to_intf(vif); - - spin_lock(&intf->lock); - - rt2x00lib_config_intf(rt2x00dev, intf, - vif->type, intf->mac, intf->bssid); - - - /* - * AP, Ad-hoc, and Mesh Point mode require a new beacon update. - */ - if (vif->type == NL80211_IFTYPE_AP || - vif->type == NL80211_IFTYPE_ADHOC || - vif->type == NL80211_IFTYPE_MESH_POINT || - vif->type == NL80211_IFTYPE_WDS) - intf->delayed_flags |= DELAYED_UPDATE_BEACON; - - spin_unlock(&intf->lock); -} - int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) { - int retval; - NOTICE(rt2x00dev, "Waking up.\n"); /* @@ -963,61 +929,12 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) rt2x00debug_register(rt2x00dev); rt2x00leds_resume(rt2x00dev); - /* - * Only continue if mac80211 had open interfaces. - */ - if (!test_and_clear_bit(DEVICE_STATE_STARTED_SUSPEND, &rt2x00dev->flags)) - return 0; - - /* - * Reinitialize device and all active interfaces. - */ - retval = rt2x00lib_start(rt2x00dev); - if (retval) - goto exit; - - /* - * Reconfigure device. - */ - retval = rt2x00mac_config(rt2x00dev->hw, ~0); - if (retval) - goto exit; - - /* - * Iterator over each active interface to - * reconfigure the hardware. - */ - ieee80211_iterate_active_interfaces(rt2x00dev->hw, - rt2x00lib_resume_intf, rt2x00dev); - /* * We are ready again to receive requests from mac80211. */ set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); - /* - * It is possible that during that mac80211 has attempted - * to send frames while we were suspending or resuming. - * In that case we have disabled the TX queue and should - * now enable it again - */ - ieee80211_wake_queues(rt2x00dev->hw); - - /* - * During interface iteration we might have changed the - * delayed_flags, time to handles the event by calling - * the work handler directly. - */ - rt2x00lib_intf_scheduled(&rt2x00dev->intf_work); - return 0; - -exit: - rt2x00lib_stop(rt2x00dev); - rt2x00lib_uninitialize(rt2x00dev); - rt2x00debug_deregister(rt2x00dev); - - return retval; } EXPORT_SYMBOL_GPL(rt2x00lib_resume); #endif /* CONFIG_PM */ -- GitLab From 1fac36ee7d5a0611e1216b02b485b154c8aa6dad Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 23 Jan 2009 11:55:33 -0500 Subject: [PATCH 0939/4982] libertas: fix CF firmware loading for some cards if_cs_poll_while_fw_download() returned the number of iterations remaining on success, which in turn got returned as the value from if_cs_prog_real() and if_cs_prog_helper(). But since if_cs_probe() interprets non-zero return values from firmware load functions as an error, this sometimes caused spurious firmware load failures. Signed-off-by: Dan Williams Tested-by: Ryan Mallon Acked-by: Ryan Mallon Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 842a08d1f10..8f8934a5ba3 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c @@ -151,7 +151,7 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r for (i = 0; i < 100000; i++) { u8 val = if_cs_read8(card, addr); if (val == reg) - return i; + return 0; udelay(5); } return -ETIME; -- GitLab From 66aafd9a3108da465a73bd755366416e75fb9d3d Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 23 Jan 2009 11:30:11 -0600 Subject: [PATCH 0940/4982] rtl8187: Fix locking of private data In rtl8187_add_interface(), the mutex that protects the data in struct rtl8187_priv does not include all references to that structure. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8187_dev.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 22bc07ef2f3..313ede7d7b4 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -974,19 +974,21 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev, { struct rtl8187_priv *priv = dev->priv; int i; + int ret = -EOPNOTSUPP; + mutex_lock(&priv->conf_mutex); if (priv->mode != NL80211_IFTYPE_MONITOR) - return -EOPNOTSUPP; + goto exit; switch (conf->type) { case NL80211_IFTYPE_STATION: priv->mode = conf->type; break; default: - return -EOPNOTSUPP; + goto exit; } - mutex_lock(&priv->conf_mutex); + ret = 0; priv->vif = conf->vif; rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); @@ -995,8 +997,9 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev, ((u8 *)conf->mac_addr)[i]); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); +exit: mutex_unlock(&priv->conf_mutex); - return 0; + return ret; } static void rtl8187_remove_interface(struct ieee80211_hw *dev, -- GitLab From 2a57cf3e83f89150f2ac9b6f01caf3fcdbb36486 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 23 Jan 2009 11:30:54 -0600 Subject: [PATCH 0941/4982] rtl8187: Increase receive queue depth The receive queue depth in rtl8187 may not be long enough to keep the pipe full. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8187_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 313ede7d7b4..db7318d1d40 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -391,7 +391,7 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev) struct rtl8187_rx_info *info; int ret = 0; - while (skb_queue_len(&priv->rx_queue) < 8) { + while (skb_queue_len(&priv->rx_queue) < 16) { skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL); if (!skb) { ret = -ENOMEM; -- GitLab From 2f47690ed42a85820783dee7f16ae47edadf8fad Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 23 Jan 2009 11:40:22 -0600 Subject: [PATCH 0942/4982] rtl8187: Fix driver to return TX retry info for RTL8187L MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current code for the RTL8187 is not returning valid retry information, thus the rate-setting mechanism is not functioning. As a further complication, this info is only obtained by reading a register, which cannot be read while in interrupt context. This patch implements the TX status return to mac80211 through the use of a work queue. One additional problem is that the driver currently enables the rate fallback mechanism of the device, which conflicts with the mac80211 rate-setting algorithm. This version of the patch disables rate fallback. Signed-off-by: Larry Finger Tested-by: Herton Ronaldo Krzesinski Tested-by: Martín Ernesto Barreyro Acked-by: Hin-Tak Leung Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8187.h | 4 +- drivers/net/wireless/rtl818x/rtl8187_dev.c | 73 ++++++++++++++++------ 2 files changed, 58 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h index 3b1e1c2aad2..9718f61809c 100644 --- a/drivers/net/wireless/rtl818x/rtl8187.h +++ b/drivers/net/wireless/rtl818x/rtl8187.h @@ -100,6 +100,8 @@ struct rtl8187_priv { struct usb_device *udev; u32 rx_conf; struct usb_anchor anchored; + struct delayed_work work; + struct ieee80211_hw *dev; u16 txpwr_base; u8 asic_rev; u8 is_rtl8187b; @@ -117,7 +119,7 @@ struct rtl8187_priv { struct { __le64 buf; struct sk_buff_head queue; - } b_tx_status; + } b_tx_status; /* This queue is used by both -b and non-b devices */ }; void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data); diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index db7318d1d40..82bd47e7c61 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -177,25 +177,33 @@ static void rtl8187_tx_cb(struct urb *urb) sizeof(struct rtl8187_tx_hdr)); ieee80211_tx_info_clear_status(info); - if (!urb->status && - !(info->flags & IEEE80211_TX_CTL_NO_ACK) && - priv->is_rtl8187b) { - skb_queue_tail(&priv->b_tx_status.queue, skb); + if (!(urb->status) && !(info->flags & IEEE80211_TX_CTL_NO_ACK)) { + if (priv->is_rtl8187b) { + skb_queue_tail(&priv->b_tx_status.queue, skb); - /* queue is "full", discard last items */ - while (skb_queue_len(&priv->b_tx_status.queue) > 5) { - struct sk_buff *old_skb; + /* queue is "full", discard last items */ + while (skb_queue_len(&priv->b_tx_status.queue) > 5) { + struct sk_buff *old_skb; - dev_dbg(&priv->udev->dev, - "transmit status queue full\n"); + dev_dbg(&priv->udev->dev, + "transmit status queue full\n"); - old_skb = skb_dequeue(&priv->b_tx_status.queue); - ieee80211_tx_status_irqsafe(hw, old_skb); - } - } else { - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && !urb->status) + old_skb = skb_dequeue(&priv->b_tx_status.queue); + ieee80211_tx_status_irqsafe(hw, old_skb); + } + return; + } else { info->flags |= IEEE80211_TX_STAT_ACK; + } + } + if (priv->is_rtl8187b) ieee80211_tx_status_irqsafe(hw, skb); + else { + /* Retry information for the RTI8187 is only available by + * reading a register in the device. We are in interrupt mode + * here, thus queue the skb and finish on a work queue. */ + skb_queue_tail(&priv->b_tx_status.queue, skb); + queue_delayed_work(hw->workqueue, &priv->work, 0); } } @@ -645,7 +653,7 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev) rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0); rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0); - rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0x81); + rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0); // TODO: set RESP_RATE and BRSR properly rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (8 << 4) | 0); @@ -765,9 +773,6 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev) rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg); rtl818x_iowrite16_idx(priv, (__le16 *)0xFFE0, 0x0FFF, 1); - reg = rtl818x_ioread8(priv, &priv->map->RATE_FALLBACK); - reg |= RTL818X_RATE_FALLBACK_ENABLE; - rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, reg); rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100); rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2); @@ -855,6 +860,34 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev) return 0; } +static void rtl8187_work(struct work_struct *work) +{ + /* The RTL8187 returns the retry count through register 0xFFFA. In + * addition, it appears to be a cumulative retry count, not the + * value for the current TX packet. When multiple TX entries are + * queued, the retry count will be valid for the last one in the queue. + * The "error" should not matter for purposes of rate setting. */ + struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv, + work.work); + struct ieee80211_tx_info *info; + struct ieee80211_hw *dev = priv->dev; + static u16 retry; + u16 tmp; + + mutex_lock(&priv->conf_mutex); + tmp = rtl818x_ioread16(priv, (__le16 *)0xFFFA); + while (skb_queue_len(&priv->b_tx_status.queue) > 0) { + struct sk_buff *old_skb; + + old_skb = skb_dequeue(&priv->b_tx_status.queue); + info = IEEE80211_SKB_CB(old_skb); + info->status.rates[0].count = tmp - retry + 1; + ieee80211_tx_status_irqsafe(dev, old_skb); + } + retry = tmp; + mutex_unlock(&priv->conf_mutex); +} + static int rtl8187_start(struct ieee80211_hw *dev) { struct rtl8187_priv *priv = dev->priv; @@ -869,6 +902,7 @@ static int rtl8187_start(struct ieee80211_hw *dev) mutex_lock(&priv->conf_mutex); init_usb_anchor(&priv->anchored); + priv->dev = dev; if (priv->is_rtl8187b) { reg = RTL818X_RX_CONF_MGMT | @@ -936,6 +970,7 @@ static int rtl8187_start(struct ieee80211_hw *dev) reg |= RTL818X_CMD_TX_ENABLE; reg |= RTL818X_CMD_RX_ENABLE; rtl818x_iowrite8(priv, &priv->map->CMD, reg); + INIT_DELAYED_WORK(&priv->work, rtl8187_work); mutex_unlock(&priv->conf_mutex); return 0; @@ -966,6 +1001,8 @@ static void rtl8187_stop(struct ieee80211_hw *dev) dev_kfree_skb_any(skb); usb_kill_anchored_urbs(&priv->anchored); + if (!priv->is_rtl8187b) + cancel_delayed_work_sync(&priv->work); mutex_unlock(&priv->conf_mutex); } -- GitLab From 1a9f509368ceb24fc66be961be15c69966f5eb5d Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 23 Jan 2009 21:21:51 +0100 Subject: [PATCH 0943/4982] b43: Automatically probe for opensource firmware First probe for proprietary firmware and then probe for opensource firmware. This way around it's a win-win situation. 1) If proprietary fw is available, it will work. 2) If opensource firmware is available, but no proprietary (Distros can only ship open fw) it might work. 3) If both open and proprietary are available, it will work, because it selects the proprietary. We currently don't prefer the open fw in this case, because it doesn't work on all devices. It would introduce a regression otherwise. The remaining FIXMEs in this patch are harmless, because they only matter on multiband devices, which are not implemented yet anyway. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/b43.h | 32 ++++++- drivers/net/wireless/b43/main.c | 154 +++++++++++++++++++++++--------- drivers/net/wireless/b43/main.h | 7 ++ 3 files changed, 149 insertions(+), 44 deletions(-) diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index a53c378e748..9e0da212f8c 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -655,10 +655,39 @@ struct b43_wl { struct work_struct txpower_adjust_work; }; +/* The type of the firmware file. */ +enum b43_firmware_file_type { + B43_FWTYPE_PROPRIETARY, + B43_FWTYPE_OPENSOURCE, + B43_NR_FWTYPES, +}; + +/* Context data for fetching firmware. */ +struct b43_request_fw_context { + /* The device we are requesting the fw for. */ + struct b43_wldev *dev; + /* The type of firmware to request. */ + enum b43_firmware_file_type req_type; + /* Error messages for each firmware type. */ + char errors[B43_NR_FWTYPES][128]; + /* Temporary buffer for storing the firmware name. */ + char fwname[64]; + /* A fatal error occured while requesting. Firmware reqest + * can not continue, as any other reqest will also fail. */ + int fatal_failure; +}; + /* In-memory representation of a cached microcode file. */ struct b43_firmware_file { const char *filename; const struct firmware *data; + /* Type of the firmware file name. Note that this does only indicate + * the type by the firmware name. NOT the file contents. + * If you want to check for proprietary vs opensource, use (struct b43_firmware)->opensource + * instead! The (struct b43_firmware)->opensource flag is derived from the actual firmware + * binary code, not just the filename. + */ + enum b43_firmware_file_type type; }; /* Pointers to the firmware data and meta information about it. */ @@ -677,7 +706,8 @@ struct b43_firmware { /* Firmware patchlevel */ u16 patch; - /* Set to true, if we are using an opensource firmware. */ + /* Set to true, if we are using an opensource firmware. + * Use this to check for proprietary vs opensource. */ bool opensource; /* Set to true, if the core needs a PCM firmware, but * we failed to load one. This is always false for diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 675a73a9807..cbb3d45f6fc 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1934,7 +1934,7 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id) return ret; } -static void do_release_fw(struct b43_firmware_file *fw) +void b43_do_release_fw(struct b43_firmware_file *fw) { release_firmware(fw->data); fw->data = NULL; @@ -1943,10 +1943,10 @@ static void do_release_fw(struct b43_firmware_file *fw) static void b43_release_firmware(struct b43_wldev *dev) { - do_release_fw(&dev->fw.ucode); - do_release_fw(&dev->fw.pcm); - do_release_fw(&dev->fw.initvals); - do_release_fw(&dev->fw.initvals_band); + b43_do_release_fw(&dev->fw.ucode); + b43_do_release_fw(&dev->fw.pcm); + b43_do_release_fw(&dev->fw.initvals); + b43_do_release_fw(&dev->fw.initvals_band); } static void b43_print_fw_helptext(struct b43_wl *wl, bool error) @@ -1963,12 +1963,10 @@ static void b43_print_fw_helptext(struct b43_wl *wl, bool error) b43warn(wl, text); } -static int do_request_fw(struct b43_wldev *dev, - const char *name, - struct b43_firmware_file *fw, - bool silent) +int b43_do_request_fw(struct b43_request_fw_context *ctx, + const char *name, + struct b43_firmware_file *fw) { - char path[sizeof(modparam_fwpostfix) + 32]; const struct firmware *blob; struct b43_fw_header *hdr; u32 size; @@ -1976,29 +1974,49 @@ static int do_request_fw(struct b43_wldev *dev, if (!name) { /* Don't fetch anything. Free possibly cached firmware. */ - do_release_fw(fw); + /* FIXME: We should probably keep it anyway, to save some headache + * on suspend/resume with multiband devices. */ + b43_do_release_fw(fw); return 0; } if (fw->filename) { - if (strcmp(fw->filename, name) == 0) + if ((fw->type == ctx->req_type) && + (strcmp(fw->filename, name) == 0)) return 0; /* Already have this fw. */ /* Free the cached firmware first. */ - do_release_fw(fw); + /* FIXME: We should probably do this later after we successfully + * got the new fw. This could reduce headache with multiband devices. + * We could also redesign this to cache the firmware for all possible + * bands all the time. */ + b43_do_release_fw(fw); + } + + switch (ctx->req_type) { + case B43_FWTYPE_PROPRIETARY: + snprintf(ctx->fwname, sizeof(ctx->fwname), + "b43%s/%s.fw", + modparam_fwpostfix, name); + break; + case B43_FWTYPE_OPENSOURCE: + snprintf(ctx->fwname, sizeof(ctx->fwname), + "b43-open%s/%s.fw", + modparam_fwpostfix, name); + break; + default: + B43_WARN_ON(1); + return -ENOSYS; } - - snprintf(path, ARRAY_SIZE(path), - "b43%s/%s.fw", - modparam_fwpostfix, name); - err = request_firmware(&blob, path, dev->dev->dev); + err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev); if (err == -ENOENT) { - if (!silent) { - b43err(dev->wl, "Firmware file \"%s\" not found\n", - path); - } + snprintf(ctx->errors[ctx->req_type], + sizeof(ctx->errors[ctx->req_type]), + "Firmware file \"%s\" not found\n", ctx->fwname); return err; } else if (err) { - b43err(dev->wl, "Firmware file \"%s\" request failed (err=%d)\n", - path, err); + snprintf(ctx->errors[ctx->req_type], + sizeof(ctx->errors[ctx->req_type]), + "Firmware file \"%s\" request failed (err=%d)\n", + ctx->fwname, err); return err; } if (blob->size < sizeof(struct b43_fw_header)) @@ -2021,20 +2039,24 @@ static int do_request_fw(struct b43_wldev *dev, fw->data = blob; fw->filename = name; + fw->type = ctx->req_type; return 0; err_format: - b43err(dev->wl, "Firmware file \"%s\" format error.\n", path); + snprintf(ctx->errors[ctx->req_type], + sizeof(ctx->errors[ctx->req_type]), + "Firmware file \"%s\" format error.\n", ctx->fwname); release_firmware(blob); return -EPROTO; } -static int b43_request_firmware(struct b43_wldev *dev) +static int b43_try_request_fw(struct b43_request_fw_context *ctx) { - struct b43_firmware *fw = &dev->fw; - const u8 rev = dev->dev->id.revision; + struct b43_wldev *dev = ctx->dev; + struct b43_firmware *fw = &ctx->dev->fw; + const u8 rev = ctx->dev->dev->id.revision; const char *filename; u32 tmshigh; int err; @@ -2049,7 +2071,7 @@ static int b43_request_firmware(struct b43_wldev *dev) filename = "ucode13"; else goto err_no_ucode; - err = do_request_fw(dev, filename, &fw->ucode, 0); + err = b43_do_request_fw(ctx, filename, &fw->ucode); if (err) goto err_load; @@ -2061,7 +2083,7 @@ static int b43_request_firmware(struct b43_wldev *dev) else goto err_no_pcm; fw->pcm_request_failed = 0; - err = do_request_fw(dev, filename, &fw->pcm, 1); + err = b43_do_request_fw(ctx, filename, &fw->pcm); if (err == -ENOENT) { /* We did not find a PCM file? Not fatal, but * core rev <= 10 must do without hwcrypto then. */ @@ -2097,7 +2119,7 @@ static int b43_request_firmware(struct b43_wldev *dev) default: goto err_no_initvals; } - err = do_request_fw(dev, filename, &fw->initvals, 0); + err = b43_do_request_fw(ctx, filename, &fw->initvals); if (err) goto err_load; @@ -2131,30 +2153,34 @@ static int b43_request_firmware(struct b43_wldev *dev) default: goto err_no_initvals; } - err = do_request_fw(dev, filename, &fw->initvals_band, 0); + err = b43_do_request_fw(ctx, filename, &fw->initvals_band); if (err) goto err_load; return 0; -err_load: - b43_print_fw_helptext(dev->wl, 1); - goto error; - err_no_ucode: - err = -ENODEV; - b43err(dev->wl, "No microcode available for core rev %u\n", rev); + err = ctx->fatal_failure = -EOPNOTSUPP; + b43err(dev->wl, "The driver does not know which firmware (ucode) " + "is required for your device (wl-core rev %u)\n", rev); goto error; err_no_pcm: - err = -ENODEV; - b43err(dev->wl, "No PCM available for core rev %u\n", rev); + err = ctx->fatal_failure = -EOPNOTSUPP; + b43err(dev->wl, "The driver does not know which firmware (PCM) " + "is required for your device (wl-core rev %u)\n", rev); goto error; err_no_initvals: - err = -ENODEV; - b43err(dev->wl, "No Initial Values firmware file for PHY %u, " - "core rev %u\n", dev->phy.type, rev); + err = ctx->fatal_failure = -EOPNOTSUPP; + b43err(dev->wl, "The driver does not know which firmware (initvals) " + "is required for your device (wl-core rev %u)\n", rev); + goto error; + +err_load: + /* We failed to load this firmware image. The error message + * already is in ctx->errors. Return and let our caller decide + * what to do. */ goto error; error: @@ -2162,6 +2188,48 @@ error: return err; } +static int b43_request_firmware(struct b43_wldev *dev) +{ + struct b43_request_fw_context *ctx; + unsigned int i; + int err; + const char *errmsg; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + ctx->dev = dev; + + ctx->req_type = B43_FWTYPE_PROPRIETARY; + err = b43_try_request_fw(ctx); + if (!err) + goto out; /* Successfully loaded it. */ + err = ctx->fatal_failure; + if (err) + goto out; + + ctx->req_type = B43_FWTYPE_OPENSOURCE; + err = b43_try_request_fw(ctx); + if (!err) + goto out; /* Successfully loaded it. */ + err = ctx->fatal_failure; + if (err) + goto out; + + /* Could not find a usable firmware. Print the errors. */ + for (i = 0; i < B43_NR_FWTYPES; i++) { + errmsg = ctx->errors[i]; + if (strlen(errmsg)) + b43err(dev->wl, errmsg); + } + b43_print_fw_helptext(dev->wl, 1); + err = -ENOENT; + +out: + kfree(ctx); + return err; +} + static int b43_upload_microcode(struct b43_wldev *dev) { const size_t hdr_len = sizeof(struct b43_fw_header); diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index f871a252cb5..e6d90f377d9 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h @@ -121,4 +121,11 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags); void b43_mac_suspend(struct b43_wldev *dev); void b43_mac_enable(struct b43_wldev *dev); + +struct b43_request_fw_context; +int b43_do_request_fw(struct b43_request_fw_context *ctx, + const char *name, + struct b43_firmware_file *fw); +void b43_do_release_fw(struct b43_firmware_file *fw); + #endif /* B43_MAIN_H_ */ -- GitLab From 4c4df78f5e224fd59fe337773878eca681ed02a9 Mon Sep 17 00:00:00 2001 From: "Chatre, Reinette" Date: Fri, 23 Jan 2009 13:45:09 -0800 Subject: [PATCH 0944/4982] iwlwifi: add test to determine if interface in monitor mode mac80211 sets driver in monitor mode through configuring the RX filters. We cannot trust priv->iw_mode to be accurate regarding monitor mode as iw_mode is only set in add_interface, which is not called by mac80211 when in monitor mode. Signed-off-by: Reinette Chatre Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 9f284ebb6c2..ef4a7c54c73 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -698,6 +698,18 @@ static u8 iwl_count_chain_bitmap(u32 chain_bitmap) return res; } +/** + * iwl_is_monitor_mode - Determine if interface in monitor mode + * + * priv->iw_mode is set in add_interface, but add_interface is + * never called for monitor mode. The only way mac80211 informs us about + * monitor mode is through configuring filters (call to configure_filter). + */ +static bool iwl_is_monitor_mode(struct iwl_priv *priv) +{ + return !!(priv->staging_rxon.filter_flags & RXON_FILTER_PROMISC_MSK); +} + /** * iwl_set_rxon_chain - Set up Rx chain usage in "staging" RXON image * -- GitLab From 7b841727d2715d97592f46164804b34d6241644f Mon Sep 17 00:00:00 2001 From: Rick Farrington Date: Fri, 23 Jan 2009 13:45:10 -0800 Subject: [PATCH 0945/4982] iwlagn: reduce off channel reception for 4965 Force use of chains B and C (0x6) for Rx for 4965 Avoid A (0x1) because of its off-channel reception on A-band. Signed-off-by: Rick Farrington Signed-off-by: Ben Cahill Signed-off-by: Reinette Chatre Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 3 +++ drivers/net/wireless/iwlwifi/iwl-commands.h | 1 + drivers/net/wireless/iwlwifi/iwl-core.c | 13 +++++++++++++ 3 files changed, 17 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c72a99a9ab3..61788a50897 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2698,6 +2698,9 @@ static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) iwl_set_rate(priv); + /* call to ensure that 4965 rx_chain is set properly in monitor mode */ + iwl_set_rxon_chain(priv); + if (memcmp(&priv->active_rxon, &priv->staging_rxon, sizeof(priv->staging_rxon))) iwl_commit_rxon(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 3ced5e5b682..7571110f5f1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -563,6 +563,7 @@ enum { #define RXON_RX_CHAIN_DRIVER_FORCE_MSK cpu_to_le16(0x1 << 0) +#define RXON_RX_CHAIN_DRIVER_FORCE_POS (0) #define RXON_RX_CHAIN_VALID_MSK cpu_to_le16(0x7 << 1) #define RXON_RX_CHAIN_VALID_POS (1) #define RXON_RX_CHAIN_FORCE_SEL_MSK cpu_to_le16(0x7 << 4) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index ef4a7c54c73..b64377e760e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -753,6 +753,19 @@ void iwl_set_rxon_chain(struct iwl_priv *priv) rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS; rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS; + /* copied from 'iwl_bg_request_scan()' */ + /* Force use of chains B and C (0x6) for Rx for 4965 + * Avoid A (0x1) because of its off-channel reception on A-band. + * MIMO is not used here, but value is required */ + if (iwl_is_monitor_mode(priv) && + !(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) && + ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)) { + rx_chain = 0x07 << RXON_RX_CHAIN_VALID_POS; + rx_chain |= 0x06 << RXON_RX_CHAIN_FORCE_SEL_POS; + rx_chain |= 0x07 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; + rx_chain |= 0x01 << RXON_RX_CHAIN_DRIVER_FORCE_POS; + } + priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain); if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam) -- GitLab From 75bcfae97d71756263ccbffc2dcdd8b3020a1a0f Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 23 Jan 2009 13:45:11 -0800 Subject: [PATCH 0946/4982] iwl3945: Define send_tx_power We can define this iwl_lib ops for 3945, as this would help us cleaning the scanning code. Signed-off-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 7 ++++--- drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 4aeb101fc45..602a3a91568 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1705,12 +1705,12 @@ static void iwl3945_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_in } /** - * iwl3945_hw_reg_send_txpower - fill in Tx Power command with gain settings + * iwl3945_send_tx_power - fill in Tx Power command with gain settings * * Configures power settings for all rates for the current channel, * using values from channel info struct, and send to NIC */ -int iwl3945_hw_reg_send_txpower(struct iwl_priv *priv) +int iwl3945_send_tx_power(struct iwl_priv *priv) { int rate_idx, i; const struct iwl_channel_info *ch_info = NULL; @@ -1935,7 +1935,7 @@ static int iwl3945_hw_reg_comp_txpower_temp(struct iwl_priv *priv) } /* send Txpower command for current channel to ucode */ - return iwl3945_hw_reg_send_txpower(priv); + return priv->cfg->ops->lib->send_tx_power(priv); } int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power) @@ -2712,6 +2712,7 @@ static struct iwl_lib_ops iwl3945_lib = { .config = iwl3945_nic_config, .set_pwr_src = iwl3945_set_pwr_src, }, + .send_tx_power = iwl3945_send_tx_power, }; static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index de8c8d7ca0f..997ac33500f 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -744,7 +744,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) /* If we issue a new RXON command which required a tune then we must * send a new TXPOWER command or we won't be able to Tx any frames */ - rc = iwl3945_hw_reg_send_txpower(priv); + rc = priv->cfg->ops->lib->send_tx_power(priv); if (rc) { IWL_ERR(priv, "Error setting Tx power (%d).\n", rc); return rc; @@ -5517,7 +5517,7 @@ static void iwl3945_bg_scan_completed(struct work_struct *work) /* Since setting the TXPOWER may have been deferred while * performing the scan, fire one off */ mutex_lock(&priv->mutex); - iwl3945_hw_reg_send_txpower(priv); + priv->cfg->ops->lib->send_tx_power(priv); mutex_unlock(&priv->mutex); } -- GitLab From 77fecfb88f8ad64420e06a96f1bd3b38498bfb4f Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 23 Jan 2009 13:45:12 -0800 Subject: [PATCH 0947/4982] iwl3945: Use iwlcore scan code A lot of the scanning related code is duplicated between 3945 and agn. Let's use the iwlcore one and get rid of the 3945. Signed-off-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.h | 21 ++ drivers/net/wireless/iwlwifi/iwl-scan.c | 42 ++- drivers/net/wireless/iwlwifi/iwl3945-base.c | 289 +------------------- 3 files changed, 51 insertions(+), 301 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 2f23f78296e..409caaa31bb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -316,9 +316,30 @@ void iwl_init_scan_params(struct iwl_priv *priv); int iwl_scan_cancel(struct iwl_priv *priv); int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); int iwl_scan_initiate(struct iwl_priv *priv); +u16 iwl_fill_probe_req(struct iwl_priv *priv, enum ieee80211_band band, + struct ieee80211_mgmt *frame, int left); void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); +u16 iwl_get_active_dwell_time(struct iwl_priv *priv, + enum ieee80211_band band, + u8 n_probes); +u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, + enum ieee80211_band band); +void iwl_bg_scan_check(struct work_struct *data); +void iwl_bg_abort_scan(struct work_struct *work); +void iwl_bg_scan_completed(struct work_struct *work); void iwl_setup_scan_deferred_work(struct iwl_priv *priv); +/* For faster active scanning, scan will move to the next channel if fewer than + * PLCP_QUIET_THRESH packets are heard on this channel within + * ACTIVE_QUIET_TIME after sending probe request. This shortens the dwell + * time if it's a quiet channel (nothing responded to our probe, and there's + * no other traffic). + * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */ +#define IWL_ACTIVE_QUIET_TIME __constant_cpu_to_le16(10) /* msec */ +#define IWL_PLCP_QUIET_THRESH __constant_cpu_to_le16(1) /* packets */ + +#define IWL_SCAN_PROBE_MASK(n) cpu_to_le32((BIT(n) | (BIT(n) - BIT(1)))) + /******************************************************************************* * Calibrations - implemented in iwl-calib.c ******************************************************************************/ diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index e510f516599..0ce122a1734 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -46,15 +46,6 @@ #define IWL_ACTIVE_DWELL_FACTOR_24GHZ (3) #define IWL_ACTIVE_DWELL_FACTOR_52GHZ (2) -/* For faster active scanning, scan will move to the next channel if fewer than - * PLCP_QUIET_THRESH packets are heard on this channel within - * ACTIVE_QUIET_TIME after sending probe request. This shortens the dwell - * time if it's a quiet channel (nothing responded to our probe, and there's - * no other traffic). - * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */ -#define IWL_PLCP_QUIET_THRESH __constant_cpu_to_le16(1) /* packets */ -#define IWL_ACTIVE_QUIET_TIME __constant_cpu_to_le16(10) /* msec */ - /* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel. * Must be set longer than active dwell time. * For the most reliable scan, set > AP beacon interval (typically 100msec). */ @@ -63,7 +54,6 @@ #define IWL_PASSIVE_DWELL_BASE (100) #define IWL_CHANNEL_TUNE_TIME 5 -#define IWL_SCAN_PROBE_MASK(n) cpu_to_le32((BIT(n) | (BIT(n) - BIT(1)))) /** @@ -296,9 +286,9 @@ void iwl_setup_rx_scan_handlers(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_setup_rx_scan_handlers); -static inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, - enum ieee80211_band band, - u8 n_probes) +inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, + enum ieee80211_band band, + u8 n_probes) { if (band == IEEE80211_BAND_5GHZ) return IWL_ACTIVE_DWELL_TIME_52 + @@ -307,9 +297,10 @@ static inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, return IWL_ACTIVE_DWELL_TIME_24 + IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1); } +EXPORT_SYMBOL(iwl_get_active_dwell_time); -static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, - enum ieee80211_band band) +u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, + enum ieee80211_band band) { u16 passive = (band == IEEE80211_BAND_2GHZ) ? IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : @@ -327,6 +318,7 @@ static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, return passive; } +EXPORT_SYMBOL(iwl_get_passive_dwell_time); static int iwl_get_channels_for_scan(struct iwl_priv *priv, enum ieee80211_band band, @@ -450,7 +442,7 @@ EXPORT_SYMBOL(iwl_scan_initiate); #define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) -static void iwl_bg_scan_check(struct work_struct *data) +void iwl_bg_scan_check(struct work_struct *data) { struct iwl_priv *priv = container_of(data, struct iwl_priv, scan_check.work); @@ -470,6 +462,8 @@ static void iwl_bg_scan_check(struct work_struct *data) } mutex_unlock(&priv->mutex); } +EXPORT_SYMBOL(iwl_bg_scan_check); + /** * iwl_supported_rate_to_ie - fill in the supported rate in IE field * @@ -527,10 +521,10 @@ static void iwl_ht_cap_to_ie(const struct ieee80211_supported_band *sband, * iwl_fill_probe_req - fill in all required fields and IE for probe request */ -static u16 iwl_fill_probe_req(struct iwl_priv *priv, - enum ieee80211_band band, - struct ieee80211_mgmt *frame, - int left) +u16 iwl_fill_probe_req(struct iwl_priv *priv, + enum ieee80211_band band, + struct ieee80211_mgmt *frame, + int left) { int len = 0; u8 *pos = NULL; @@ -624,6 +618,7 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv, return (u16)len; } +EXPORT_SYMBOL(iwl_fill_probe_req); static void iwl_bg_request_scan(struct work_struct *data) { @@ -839,7 +834,7 @@ static void iwl_bg_request_scan(struct work_struct *data) mutex_unlock(&priv->mutex); } -static void iwl_bg_abort_scan(struct work_struct *work) +void iwl_bg_abort_scan(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); @@ -853,8 +848,9 @@ static void iwl_bg_abort_scan(struct work_struct *work) mutex_unlock(&priv->mutex); } +EXPORT_SYMBOL(iwl_bg_abort_scan); -static void iwl_bg_scan_completed(struct work_struct *work) +void iwl_bg_scan_completed(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, scan_completed); @@ -872,7 +868,7 @@ static void iwl_bg_scan_completed(struct work_struct *work) iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); mutex_unlock(&priv->mutex); } - +EXPORT_SYMBOL(iwl_bg_scan_completed); void iwl_setup_scan_deferred_work(struct iwl_priv *priv) { diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 997ac33500f..c7bb9c19a90 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -791,47 +791,6 @@ static int iwl3945_send_bt_config(struct iwl_priv *priv) sizeof(bt_cmd), &bt_cmd); } -static int iwl3945_send_scan_abort(struct iwl_priv *priv) -{ - int rc = 0; - struct iwl_rx_packet *res; - struct iwl_host_cmd cmd = { - .id = REPLY_SCAN_ABORT_CMD, - .meta.flags = CMD_WANT_SKB, - }; - - /* If there isn't a scan actively going on in the hardware - * then we are in between scan bands and not actually - * actively scanning, so don't send the abort command */ - if (!test_bit(STATUS_SCAN_HW, &priv->status)) { - clear_bit(STATUS_SCAN_ABORTING, &priv->status); - return 0; - } - - rc = iwl_send_cmd_sync(priv, &cmd); - if (rc) { - clear_bit(STATUS_SCAN_ABORTING, &priv->status); - return rc; - } - - res = (struct iwl_rx_packet *)cmd.meta.u.skb->data; - if (res->u.status != CAN_ABORT_STATUS) { - /* The scan abort will return 1 for success or - * 2 for "failure". A failure condition can be - * due to simply not being in an active scan which - * can occur if we send the scan abort before we - * the microcode has notified us that a scan is - * completed. */ - IWL_DEBUG_INFO("SCAN_ABORT returned %d.\n", res->u.status); - clear_bit(STATUS_SCAN_ABORTING, &priv->status); - clear_bit(STATUS_SCAN_HW, &priv->status); - } - - dev_kfree_skb_any(cmd.meta.u.skb); - - return rc; -} - static int iwl3945_add_sta_sync_callback(struct iwl_priv *priv, struct iwl_cmd *cmd, struct sk_buff *skb) { @@ -1168,115 +1127,6 @@ static void iwl3945_unset_hw_params(struct iwl_priv *priv) priv->shared_phys); } -/** - * iwl3945_supported_rate_to_ie - fill in the supported rate in IE field - * - * return : set the bit for each supported rate insert in ie - */ -static u16 iwl3945_supported_rate_to_ie(u8 *ie, u16 supported_rate, - u16 basic_rate, int *left) -{ - u16 ret_rates = 0, bit; - int i; - u8 *cnt = ie; - u8 *rates = ie + 1; - - for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) { - if (bit & supported_rate) { - ret_rates |= bit; - rates[*cnt] = iwl3945_rates[i].ieee | - ((bit & basic_rate) ? 0x80 : 0x00); - (*cnt)++; - (*left)--; - if ((*left <= 0) || - (*cnt >= IWL_SUPPORTED_RATES_IE_LEN)) - break; - } - } - - return ret_rates; -} - -/** - * iwl3945_fill_probe_req - fill in all required fields and IE for probe request - */ -static u16 iwl3945_fill_probe_req(struct iwl_priv *priv, - struct ieee80211_mgmt *frame, - int left) -{ - int len = 0; - u8 *pos = NULL; - u16 active_rates, ret_rates, cck_rates; - - /* Make sure there is enough space for the probe request, - * two mandatory IEs and the data */ - left -= 24; - if (left < 0) - return 0; - len += 24; - - frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); - memcpy(frame->da, iwl_bcast_addr, ETH_ALEN); - memcpy(frame->sa, priv->mac_addr, ETH_ALEN); - memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN); - frame->seq_ctrl = 0; - - /* fill in our indirect SSID IE */ - /* ...next IE... */ - - left -= 2; - if (left < 0) - return 0; - len += 2; - pos = &(frame->u.probe_req.variable[0]); - *pos++ = WLAN_EID_SSID; - *pos++ = 0; - - /* fill in supported rate */ - /* ...next IE... */ - left -= 2; - if (left < 0) - return 0; - - /* ... fill it in... */ - *pos++ = WLAN_EID_SUPP_RATES; - *pos = 0; - - priv->active_rate = priv->rates_mask; - active_rates = priv->active_rate; - priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; - - cck_rates = IWL_CCK_RATES_MASK & active_rates; - ret_rates = iwl3945_supported_rate_to_ie(pos, cck_rates, - priv->active_rate_basic, &left); - active_rates &= ~ret_rates; - - ret_rates = iwl3945_supported_rate_to_ie(pos, active_rates, - priv->active_rate_basic, &left); - active_rates &= ~ret_rates; - - len += 2 + *pos; - pos += (*pos) + 1; - if (active_rates == 0) - goto fill_end; - - /* fill in supported extended rate */ - /* ...next IE... */ - left -= 2; - if (left < 0) - return 0; - /* ... fill it in... */ - *pos++ = WLAN_EID_EXT_SUPP_RATES; - *pos = 0; - iwl3945_supported_rate_to_ie(pos, active_rates, - priv->active_rate_basic, &left); - if (*pos > 0) - len += 2 + *pos; - - fill_end: - return (u16)len; -} - /* * QoS support */ @@ -3955,66 +3805,6 @@ static void iwl3945_free_channel_map(struct iwl_priv *priv) priv->channel_count = 0; } -/* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after - * sending probe req. This should be set long enough to hear probe responses - * from more than one AP. */ -#define IWL_ACTIVE_DWELL_TIME_24 (30) /* all times in msec */ -#define IWL_ACTIVE_DWELL_TIME_52 (20) - -#define IWL_ACTIVE_DWELL_FACTOR_24GHZ (3) -#define IWL_ACTIVE_DWELL_FACTOR_52GHZ (2) - -/* For faster active scanning, scan will move to the next channel if fewer than - * PLCP_QUIET_THRESH packets are heard on this channel within - * ACTIVE_QUIET_TIME after sending probe request. This shortens the dwell - * time if it's a quiet channel (nothing responded to our probe, and there's - * no other traffic). - * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */ -#define IWL_PLCP_QUIET_THRESH __constant_cpu_to_le16(1) /* packets */ -#define IWL_ACTIVE_QUIET_TIME __constant_cpu_to_le16(10) /* msec */ - -/* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel. - * Must be set longer than active dwell time. - * For the most reliable scan, set > AP beacon interval (typically 100msec). */ -#define IWL_PASSIVE_DWELL_TIME_24 (20) /* all times in msec */ -#define IWL_PASSIVE_DWELL_TIME_52 (10) -#define IWL_PASSIVE_DWELL_BASE (100) -#define IWL_CHANNEL_TUNE_TIME 5 - -#define IWL_SCAN_PROBE_MASK(n) (BIT(n) | (BIT(n) - BIT(1))) - -static inline u16 iwl3945_get_active_dwell_time(struct iwl_priv *priv, - enum ieee80211_band band, - u8 n_probes) -{ - if (band == IEEE80211_BAND_5GHZ) - return IWL_ACTIVE_DWELL_TIME_52 + - IWL_ACTIVE_DWELL_FACTOR_52GHZ * (n_probes + 1); - else - return IWL_ACTIVE_DWELL_TIME_24 + - IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1); -} - -static u16 iwl3945_get_passive_dwell_time(struct iwl_priv *priv, - enum ieee80211_band band) -{ - u16 passive = (band == IEEE80211_BAND_2GHZ) ? - IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : - IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; - - if (iwl3945_is_associated(priv)) { - /* If we're associated, we clamp the maximum passive - * dwell time to be 98% of the beacon interval (minus - * 2 * channel tune time) */ - passive = priv->beacon_int; - if ((passive > IWL_PASSIVE_DWELL_BASE) || !passive) - passive = IWL_PASSIVE_DWELL_BASE; - passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; - } - - return passive; -} - static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, enum ieee80211_band band, u8 is_active, u8 n_probes, @@ -4033,8 +3823,8 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, channels = sband->channels; - active_dwell = iwl3945_get_active_dwell_time(priv, band, n_probes); - passive_dwell = iwl3945_get_passive_dwell_time(priv, band); + active_dwell = iwl_get_active_dwell_time(priv, band, n_probes); + passive_dwell = iwl_get_passive_dwell_time(priv, band); if (passive_dwell <= active_dwell) passive_dwell = active_dwell + 1; @@ -5135,28 +4925,6 @@ static void iwl3945_rfkill_poll(struct work_struct *data) } #define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) - -static void iwl3945_bg_scan_check(struct work_struct *data) -{ - struct iwl_priv *priv = - container_of(data, struct iwl_priv, scan_check.work); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - mutex_lock(&priv->mutex); - if (test_bit(STATUS_SCANNING, &priv->status) || - test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN, - "Scan completion watchdog resetting adapter (%dms)\n", - jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG)); - - if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) - iwl3945_send_scan_abort(priv); - } - mutex_unlock(&priv->mutex); -} - static void iwl3945_bg_request_scan(struct work_struct *data) { struct iwl_priv *priv = @@ -5284,9 +5052,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data) /* We don't build a direct scan probe request; the uCode will do * that based on the direct_mask added to each channel entry */ - scan->tx_cmd.len = cpu_to_le16( - iwl3945_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data, - IWL_MAX_SCAN_SIZE - sizeof(*scan))); scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id; scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; @@ -5307,6 +5072,11 @@ static void iwl3945_bg_request_scan(struct work_struct *data) goto done; } + scan->tx_cmd.len = cpu_to_le16( + iwl_fill_probe_req(priv, band, + (struct ieee80211_mgmt *)scan->data, + IWL_MAX_SCAN_SIZE - sizeof(*scan))); + /* select Rx antennas */ scan->flags |= iwl3945_get_antenna_flags(priv); @@ -5482,45 +5252,8 @@ static void iwl3945_post_associate(struct iwl_priv *priv) priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; } -static void iwl3945_bg_abort_scan(struct work_struct *work) -{ - struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); - - if (!iwl_is_ready(priv)) - return; - - mutex_lock(&priv->mutex); - - set_bit(STATUS_SCAN_ABORTING, &priv->status); - iwl3945_send_scan_abort(priv); - - mutex_unlock(&priv->mutex); -} - static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed); -static void iwl3945_bg_scan_completed(struct work_struct *work) -{ - struct iwl_priv *priv = - container_of(work, struct iwl_priv, scan_completed); - - IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN, "SCAN complete scan\n"); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - if (test_bit(STATUS_CONF_PENDING, &priv->status)) - iwl3945_mac_config(priv->hw, 0); - - ieee80211_scan_completed(priv->hw); - - /* Since setting the TXPOWER may have been deferred while - * performing the scan, fire one off */ - mutex_lock(&priv->mutex); - priv->cfg->ops->lib->send_tx_power(priv); - mutex_unlock(&priv->mutex); -} - /***************************************************************************** * * mac80211 entry point functions @@ -6821,15 +6554,15 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv) INIT_WORK(&priv->up, iwl3945_bg_up); INIT_WORK(&priv->restart, iwl3945_bg_restart); INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish); - INIT_WORK(&priv->scan_completed, iwl3945_bg_scan_completed); - INIT_WORK(&priv->request_scan, iwl3945_bg_request_scan); - INIT_WORK(&priv->abort_scan, iwl3945_bg_abort_scan); INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill); INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update); INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start); INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start); - INIT_DELAYED_WORK(&priv->scan_check, iwl3945_bg_scan_check); INIT_DELAYED_WORK(&priv->rfkill_poll, iwl3945_rfkill_poll); + INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); + INIT_WORK(&priv->request_scan, iwl3945_bg_request_scan); + INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); + INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); iwl3945_hw_setup_deferred_work(priv); -- GitLab From 59606ffa9146538b73bbe1ca1285321cd7474bc0 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 23 Jan 2009 13:45:13 -0800 Subject: [PATCH 0948/4982] iwlwifi: make iwl_tx_queue->tfds void* Instead of having both tfds and tfds39, we can just have a void *tfds. It makes the tx_queue structure nicer, and the code cleaner. It also helps with further TX queues management code merging. Signed-off-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 7 ++++--- drivers/net/wireless/iwlwifi/iwl-agn.c | 7 ++++--- drivers/net/wireless/iwlwifi/iwl-dev.h | 3 +-- drivers/net/wireless/iwlwifi/iwl-tx.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 12 ++++++------ 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 602a3a91568..22770f44c2f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -730,10 +730,11 @@ int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, { int count; struct iwl_queue *q; - struct iwl3945_tfd *tfd; + struct iwl3945_tfd *tfd, *tfd_tmp; q = &txq->q; - tfd = &txq->tfds39[q->write_ptr]; + tfd_tmp = (struct iwl3945_tfd *)txq->tfds; + tfd = &tfd_tmp[q->write_ptr]; if (reset) memset(tfd, 0, sizeof(*tfd)); @@ -764,7 +765,7 @@ int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, */ void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) { - struct iwl3945_tfd *tfd_tmp = (struct iwl3945_tfd *)&txq->tfds39[0]; + struct iwl3945_tfd *tfd_tmp = (struct iwl3945_tfd *)txq->tfds; struct iwl3945_tfd *tfd = &tfd_tmp[txq->q.read_ptr]; struct pci_dev *dev = priv->pci_dev; int i; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 61788a50897..4ce3d6a63d1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -520,7 +520,7 @@ static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd) */ void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) { - struct iwl_tfd *tfd_tmp = (struct iwl_tfd *)&txq->tfds[0]; + struct iwl_tfd *tfd_tmp = (struct iwl_tfd *)txq->tfds; struct iwl_tfd *tfd; struct pci_dev *dev = priv->pci_dev; int index = txq->q.read_ptr; @@ -563,11 +563,12 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, u8 reset, u8 pad) { struct iwl_queue *q; - struct iwl_tfd *tfd; + struct iwl_tfd *tfd, *tfd_tmp; u32 num_tbs; q = &txq->q; - tfd = &txq->tfds[q->write_ptr]; + tfd_tmp = (struct iwl_tfd *)txq->tfds; + tfd = &tfd_tmp[q->write_ptr]; if (reset) memset(tfd, 0, sizeof(*tfd)); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 79f2d45a9fc..78ce4f49c56 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -149,8 +149,7 @@ struct iwl_tx_info { struct iwl_tx_queue { struct iwl_queue q; - struct iwl_tfd *tfds; - struct iwl3945_tfd *tfds39; + void *tfds; struct iwl_cmd *cmd[TFD_TX_CMD_SLOTS]; struct iwl_tx_info *txb; u8 need_update; diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 1a2cfbebb17..83e9f32cbd8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -295,12 +295,12 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv, /* Circular buffer of transmit frame descriptors (TFDs), * shared with device */ txq->tfds = pci_alloc_consistent(dev, - sizeof(txq->tfds[0]) * TFD_QUEUE_SIZE_MAX, + sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX, &txq->q.dma_addr); if (!txq->tfds) { IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", - sizeof(txq->tfds[0]) * TFD_QUEUE_SIZE_MAX); + sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX); goto error; } txq->q.id = id; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index c7bb9c19a90..bc10e2ae597 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -172,13 +172,13 @@ static int iwl3945_tx_queue_alloc(struct iwl_priv *priv, /* Circular buffer of transmit frame descriptors (TFDs), * shared with device */ - txq->tfds39 = pci_alloc_consistent(dev, - sizeof(txq->tfds39[0]) * TFD_QUEUE_SIZE_MAX, - &txq->q.dma_addr); + txq->tfds = pci_alloc_consistent(dev, + sizeof(struct iwl3945_tfd) * TFD_QUEUE_SIZE_MAX, + &txq->q.dma_addr); - if (!txq->tfds39) { + if (!txq->tfds) { IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", - sizeof(txq->tfds39[0]) * TFD_QUEUE_SIZE_MAX); + sizeof(struct iwl3945_tfd) * TFD_QUEUE_SIZE_MAX); goto error; } txq->q.id = id; @@ -287,7 +287,7 @@ void iwl3945_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq) /* De-alloc circular buffer of TFDs */ if (txq->q.n_bd) pci_free_consistent(dev, sizeof(struct iwl3945_tfd) * - txq->q.n_bd, txq->tfds39, txq->q.dma_addr); + txq->q.n_bd, txq->tfds, txq->q.dma_addr); /* De-alloc array of per-TFD driver data */ kfree(txq->txb); -- GitLab From a8e74e2774cd1aecfef0460de07e6e178df89232 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 23 Jan 2009 13:45:14 -0800 Subject: [PATCH 0949/4982] iwl3945: Use iwlcore TX queue management routines By adding an additional hw_params (tfd_size) and a new iwl_lib ops (txq_init), we can now use the iwlcore TX queue management routines. We had to add a new hw_params because we need to allocate the right DMA buffer for TFDs, and those have a different sizes depending if you're on 3945 or agn. Signed-off-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 8 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 + drivers/net/wireless/iwlwifi/iwl-5000.c | 2 + drivers/net/wireless/iwlwifi/iwl-agn.c | 32 +++ drivers/net/wireless/iwlwifi/iwl-core.h | 7 + drivers/net/wireless/iwlwifi/iwl-dev.h | 2 + drivers/net/wireless/iwlwifi/iwl-tx.c | 49 +---- drivers/net/wireless/iwlwifi/iwl3945-base.c | 204 -------------------- 8 files changed, 60 insertions(+), 246 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 22770f44c2f..2689113f4e6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1068,8 +1068,8 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv) for (txq_id = 0; txq_id < TFD_QUEUE_MAX; txq_id++) { slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; - rc = iwl3945_tx_queue_init(priv, &priv->txq[txq_id], slots_num, - txq_id); + rc = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, + txq_id); if (rc) { IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); goto error; @@ -1258,7 +1258,7 @@ void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv) /* Tx queues */ for (txq_id = 0; txq_id < TFD_QUEUE_MAX; txq_id++) - iwl3945_tx_queue_free(priv, &priv->txq[txq_id]); + iwl_tx_queue_free(priv, txq_id); } void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) @@ -2491,6 +2491,7 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) return -ENOMEM; } + priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd); priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_3K; priv->hw_params.max_pkt_size = 2342; priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; @@ -2705,6 +2706,7 @@ static int iwl3945_load_bsm(struct iwl_priv *priv) static struct iwl_lib_ops iwl3945_lib = { .txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl3945_hw_txq_free_tfd, + .txq_init = iwl3945_hw_tx_queue_init, .load_ucode = iwl3945_load_bsm, .apm_ops = { .init = iwl3945_apm_init, diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index b2985e25dc8..d7d956db19d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -815,6 +815,7 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM; priv->hw_params.scd_bc_tbls_size = IWL49_NUM_QUEUES * sizeof(struct iwl4965_scd_bc_tbl); + priv->hw_params.tfd_size = sizeof(struct iwl_tfd); priv->hw_params.max_stations = IWL4965_STATION_COUNT; priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID; priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE; @@ -2297,6 +2298,7 @@ static struct iwl_lib_ops iwl4965_lib = { .txq_agg_disable = iwl4965_txq_agg_disable, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, + .txq_init = iwl_hw_tx_queue_init, .rx_handler_setup = iwl4965_rx_handler_setup, .setup_deferred_work = iwl4965_setup_deferred_work, .cancel_deferred_work = iwl4965_cancel_deferred_work, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 04c2585a634..89d92a8ca15 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -837,6 +837,7 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; priv->hw_params.scd_bc_tbls_size = IWL50_NUM_QUEUES * sizeof(struct iwl5000_scd_bc_tbl); + priv->hw_params.tfd_size = sizeof(struct iwl_tfd); priv->hw_params.max_stations = IWL5000_STATION_COUNT; priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; @@ -1494,6 +1495,7 @@ static struct iwl_lib_ops iwl5000_lib = { .txq_agg_disable = iwl5000_txq_agg_disable, .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl_hw_txq_free_tfd, + .txq_init = iwl_hw_tx_queue_init, .rx_handler_setup = iwl5000_rx_handler_setup, .setup_deferred_work = iwl5000_setup_deferred_work, .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 4ce3d6a63d1..5c6b3fe3eed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -592,6 +592,38 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, return 0; } +/* + * Tell nic where to find circular buffer of Tx Frame Descriptors for + * given Tx queue, and enable the DMA channel used for that queue. + * + * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA + * channels supported in hardware. + */ +int iwl_hw_tx_queue_init(struct iwl_priv *priv, + struct iwl_tx_queue *txq) +{ + int ret; + unsigned long flags; + int txq_id = txq->q.id; + + spin_lock_irqsave(&priv->lock, flags); + ret = iwl_grab_nic_access(priv); + if (ret) { + spin_unlock_irqrestore(&priv->lock, flags); + return ret; + } + + /* Circular buffer (TFD queue in DRAM) physical base address */ + iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), + txq->q.dma_addr >> 8); + + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} + + /****************************************************************************** * * Misc. internal state and helper functions diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 409caaa31bb..9a350806a21 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -116,6 +116,8 @@ struct iwl_lib_ops { u16 len, u8 reset, u8 pad); void (*txq_free_tfd)(struct iwl_priv *priv, struct iwl_tx_queue *txq); + int (*txq_init)(struct iwl_priv *priv, + struct iwl_tx_queue *txq); /* aggregations */ int (*txq_agg_enable)(struct iwl_priv *priv, int txq_id, int tx_fifo, int sta_id, int tid, u16 ssn_idx); @@ -264,7 +266,12 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, dma_addr_t addr, u16 len, u8 reset, u8 pad); int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); void iwl_hw_txq_ctx_free(struct iwl_priv *priv); +int iwl_hw_tx_queue_init(struct iwl_priv *priv, + struct iwl_tx_queue *txq); int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); +int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, + int slots_num, u32 txq_id); +void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 78ce4f49c56..5aa22d61e39 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -567,6 +567,7 @@ struct iwl_sensitivity_ranges { * @max_txq_num: Max # Tx queues supported * @dma_chnl_num: Number of Tx DMA/FIFO channels * @scd_bc_tbls_size: size of scheduler byte count tables + * @tfd_size: TFD size * @tx/rx_chains_num: Number of TX/RX chains * @valid_tx/rx_ant: usable antennas * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2) @@ -587,6 +588,7 @@ struct iwl_hw_params { u8 max_txq_num; u8 dma_chnl_num; u16 scd_bc_tbls_size; + u32 tfd_size; u8 tx_chains_num; u8 rx_chains_num; u8 valid_tx_ant; diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 83e9f32cbd8..58118c8224c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -131,7 +131,7 @@ EXPORT_SYMBOL(iwl_txq_update_write_ptr); * Free all buffers. * 0-fill, but do not free "txq" descriptor structure. */ -static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) +void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) { struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct iwl_queue *q = &txq->q; @@ -154,7 +154,7 @@ static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) /* De-alloc circular buffer of TFDs */ if (txq->q.n_bd) - pci_free_consistent(dev, sizeof(struct iwl_tfd) * + pci_free_consistent(dev, priv->hw_params.tfd_size * txq->q.n_bd, txq->tfds, txq->q.dma_addr); /* De-alloc array of per-TFD driver data */ @@ -164,7 +164,7 @@ static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) /* 0-fill queue descriptor structure */ memset(txq, 0, sizeof(*txq)); } - +EXPORT_SYMBOL(iwl_tx_queue_free); /** * iwl_cmd_queue_free - Deallocate DMA queue. @@ -295,12 +295,12 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv, /* Circular buffer of transmit frame descriptors (TFDs), * shared with device */ txq->tfds = pci_alloc_consistent(dev, - sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX, + priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX, &txq->q.dma_addr); if (!txq->tfds) { IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", - sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX); + priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX); goto error; } txq->q.id = id; @@ -314,42 +314,11 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv, return -ENOMEM; } -/* - * Tell nic where to find circular buffer of Tx Frame Descriptors for - * given Tx queue, and enable the DMA channel used for that queue. - * - * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA - * channels supported in hardware. - */ -static int iwl_hw_tx_queue_init(struct iwl_priv *priv, - struct iwl_tx_queue *txq) -{ - int ret; - unsigned long flags; - int txq_id = txq->q.id; - - spin_lock_irqsave(&priv->lock, flags); - ret = iwl_grab_nic_access(priv); - if (ret) { - spin_unlock_irqrestore(&priv->lock, flags); - return ret; - } - - /* Circular buffer (TFD queue in DRAM) physical base address */ - iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), - txq->q.dma_addr >> 8); - - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->lock, flags); - - return 0; -} - /** * iwl_tx_queue_init - Allocate and initialize one tx/cmd queue */ -static int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, - int slots_num, u32 txq_id) +int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, + int slots_num, u32 txq_id) { int i, len; int ret; @@ -391,7 +360,7 @@ static int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); /* Tell device where to find queue */ - iwl_hw_tx_queue_init(priv, txq); + priv->cfg->ops->lib->txq_init(priv, txq); return 0; err: @@ -406,6 +375,8 @@ err: } return -ENOMEM; } +EXPORT_SYMBOL(iwl_tx_queue_init); + /** * iwl_hw_txq_ctx_free - Free TXQ Context * diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index bc10e2ae597..14f95238059 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -93,210 +93,6 @@ struct iwl_mod_params iwl3945_mod_params = { /* the rest are 0 by default */ }; -/*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** - * DMA services - * - * Theory of operation - * - * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer - * of buffer descriptors, each of which points to one or more data buffers for - * the device to read from or fill. Driver and device exchange status of each - * queue via "read" and "write" pointers. Driver keeps minimum of 2 empty - * entries in each circular buffer, to protect against confusing empty and full - * queue states. - * - * The device reads or writes the data in the queues via the device's several - * DMA/FIFO channels. Each queue is mapped to a single DMA channel. - * - * For Tx queue, there are low mark and high mark limits. If, after queuing - * the packet for Tx, free space become < low mark, Tx queue stopped. When - * reclaiming packets (on 'tx done IRQ), if free space become > high mark, - * Tx queue resumed. - * - * The 3945 operates with six queues: One receive queue, one transmit queue - * (#4) for sending commands to the device firmware, and four transmit queues - * (#0-3) for data tx via EDCA. An additional 2 HCCA queues are unused. - ***************************************************/ - -/** - * iwl3945_queue_init - Initialize queue's high/low-water and read/write indexes - */ -static int iwl3945_queue_init(struct iwl_priv *priv, struct iwl_queue *q, - int count, int slots_num, u32 id) -{ - q->n_bd = count; - q->n_window = slots_num; - q->id = id; - - /* count must be power-of-two size, otherwise iwl_queue_inc_wrap - * and iwl_queue_dec_wrap are broken. */ - BUG_ON(!is_power_of_2(count)); - - /* slots_num must be power-of-two size, otherwise - * get_cmd_index is broken. */ - BUG_ON(!is_power_of_2(slots_num)); - - q->low_mark = q->n_window / 4; - if (q->low_mark < 4) - q->low_mark = 4; - - q->high_mark = q->n_window / 8; - if (q->high_mark < 2) - q->high_mark = 2; - - q->write_ptr = q->read_ptr = 0; - - return 0; -} - -/** - * iwl3945_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue - */ -static int iwl3945_tx_queue_alloc(struct iwl_priv *priv, - struct iwl_tx_queue *txq, u32 id) -{ - struct pci_dev *dev = priv->pci_dev; - - /* Driver private data, only for Tx (not command) queues, - * not shared with device. */ - if (id != IWL_CMD_QUEUE_NUM) { - txq->txb = kmalloc(sizeof(txq->txb[0]) * - TFD_QUEUE_SIZE_MAX, GFP_KERNEL); - if (!txq->txb) { - IWL_ERR(priv, "kmalloc for auxiliary BD " - "structures failed\n"); - goto error; - } - } else - txq->txb = NULL; - - /* Circular buffer of transmit frame descriptors (TFDs), - * shared with device */ - txq->tfds = pci_alloc_consistent(dev, - sizeof(struct iwl3945_tfd) * TFD_QUEUE_SIZE_MAX, - &txq->q.dma_addr); - - if (!txq->tfds) { - IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", - sizeof(struct iwl3945_tfd) * TFD_QUEUE_SIZE_MAX); - goto error; - } - txq->q.id = id; - - return 0; - - error: - kfree(txq->txb); - txq->txb = NULL; - - return -ENOMEM; -} - -/** - * iwl3945_tx_queue_init - Allocate and initialize one tx/cmd queue - */ -int iwl3945_tx_queue_init(struct iwl_priv *priv, - struct iwl_tx_queue *txq, int slots_num, u32 txq_id) -{ - int len, i; - int rc = 0; - - /* - * Alloc buffer array for commands (Tx or other types of commands). - * For the command queue (#4), allocate command space + one big - * command for scan, since scan command is very huge; the system will - * not have two scans at the same time, so only one is needed. - * For data Tx queues (all other queues), no super-size command - * space is needed. - */ - len = sizeof(struct iwl_cmd); - for (i = 0; i <= slots_num; i++) { - if (i == slots_num) { - if (txq_id == IWL_CMD_QUEUE_NUM) - len += IWL_MAX_SCAN_SIZE; - else - continue; - } - - txq->cmd[i] = kmalloc(len, GFP_KERNEL); - if (!txq->cmd[i]) - goto err; - } - - /* Alloc driver data array and TFD circular buffer */ - rc = iwl3945_tx_queue_alloc(priv, txq, txq_id); - if (rc) - goto err; - - txq->need_update = 0; - - /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise - * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */ - BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); - - /* Initialize queue high/low-water, head/tail indexes */ - iwl3945_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); - - /* Tell device where to find queue, enable DMA channel. */ - iwl3945_hw_tx_queue_init(priv, txq); - - return 0; -err: - for (i = 0; i < slots_num; i++) { - kfree(txq->cmd[i]); - txq->cmd[i] = NULL; - } - - if (txq_id == IWL_CMD_QUEUE_NUM) { - kfree(txq->cmd[slots_num]); - txq->cmd[slots_num] = NULL; - } - return -ENOMEM; -} - -/** - * iwl3945_tx_queue_free - Deallocate DMA queue. - * @txq: Transmit queue to deallocate. - * - * Empty queue by removing and destroying all BD's. - * Free all buffers. - * 0-fill, but do not free "txq" descriptor structure. - */ -void iwl3945_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq) -{ - struct iwl_queue *q = &txq->q; - struct pci_dev *dev = priv->pci_dev; - int len, i; - - if (q->n_bd == 0) - return; - - /* first, empty all BD's */ - for (; q->write_ptr != q->read_ptr; - q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) - priv->cfg->ops->lib->txq_free_tfd(priv, txq); - - len = sizeof(struct iwl_cmd) * q->n_window; - if (q->id == IWL_CMD_QUEUE_NUM) - len += IWL_MAX_SCAN_SIZE; - - /* De-alloc array of command/tx buffers */ - for (i = 0; i < TFD_TX_CMD_SLOTS; i++) - kfree(txq->cmd[i]); - - /* De-alloc circular buffer of TFDs */ - if (txq->q.n_bd) - pci_free_consistent(dev, sizeof(struct iwl3945_tfd) * - txq->q.n_bd, txq->tfds, txq->q.dma_addr); - - /* De-alloc array of per-TFD driver data */ - kfree(txq->txb); - txq->txb = NULL; - - /* 0-fill queue descriptor structure */ - memset(txq, 0, sizeof(*txq)); -} - /*************** STATION TABLE MANAGEMENT **** * mac80211 should be examined to determine if sta_info is duplicating * the functionality provided here -- GitLab From e6148917db2c223fa7edd3dfb64d99756a86b452 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 23 Jan 2009 13:45:15 -0800 Subject: [PATCH 0950/4982] iwl3945: Use iwl-eeprom.c routines By adding the eeprom ops to the 3945 code, we can now use the iwlcore eeprom routines (defined in iwl-eeprom.c). We also removed the heavy eeprom39 reference from iwl_priv and use the eeprom pointer instead. Signed-off-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 4 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 92 ++++- drivers/net/wireless/iwlwifi/iwl-dev.h | 3 - drivers/net/wireless/iwlwifi/iwl-eeprom.c | 8 + drivers/net/wireless/iwlwifi/iwl-eeprom.h | 3 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 372 ++------------------ 6 files changed, 115 insertions(+), 367 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 013e24edf0e..1327b2ac1c5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -182,7 +182,7 @@ struct iwl3945_eeprom { * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 */ u16 band_1_count; /* abs.ofs: 196 */ - struct iwl_eeprom_channel band_1_channels[14]; /* abs.ofs: 196 */ + struct iwl_eeprom_channel band_1_channels[14]; /* abs.ofs: 198 */ /* * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196, @@ -225,7 +225,7 @@ struct iwl3945_eeprom { u8 reserved16[172]; /* fill out to full 1024 byte block */ } __attribute__ ((packed)); -#define IWL_EEPROM_IMAGE_SIZE 1024 +#define IWL3945_EEPROM_IMG_SIZE 1024 /* End of EEPROM */ diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 2689113f4e6..75e9553a940 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -42,6 +42,7 @@ #include "iwl-3945-fh.h" #include "iwl-commands.h" #include "iwl-3945.h" +#include "iwl-eeprom.h" #include "iwl-helpers.h" #include "iwl-core.h" #include "iwl-agn-rs.h" @@ -209,17 +210,19 @@ static int iwl3945_hwrate_to_plcp_idx(u8 plcp) */ __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv) { + struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; + switch (priv->antenna) { case IWL_ANTENNA_DIVERSITY: return 0; case IWL_ANTENNA_MAIN: - if (priv->eeprom39.antenna_switch_type) + if (eeprom->antenna_switch_type) return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK; return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK; case IWL_ANTENNA_AUX: - if (priv->eeprom39.antenna_switch_type) + if (eeprom->antenna_switch_type) return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK; return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK; } @@ -1128,6 +1131,7 @@ out: static void iwl3945_nic_config(struct iwl_priv *priv) { + struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; unsigned long flags; u8 rev_id = 0; @@ -1145,42 +1149,42 @@ static void iwl3945_nic_config(struct iwl_priv *priv) CSR39_HW_IF_CONFIG_REG_BIT_3945_MM); } - if (EEPROM_SKU_CAP_OP_MODE_MRC == priv->eeprom39.sku_cap) { + if (EEPROM_SKU_CAP_OP_MODE_MRC == eeprom->sku_cap) { IWL_DEBUG_INFO("SKU OP mode is mrc\n"); iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC); } else IWL_DEBUG_INFO("SKU OP mode is basic\n"); - if ((priv->eeprom39.board_revision & 0xF0) == 0xD0) { + if ((eeprom->board_revision & 0xF0) == 0xD0) { IWL_DEBUG_INFO("3945ABG revision is 0x%X\n", - priv->eeprom39.board_revision); + eeprom->board_revision); iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE); } else { IWL_DEBUG_INFO("3945ABG revision is 0x%X\n", - priv->eeprom39.board_revision); + eeprom->board_revision); iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE); } - if (priv->eeprom39.almgor_m_version <= 1) { + if (eeprom->almgor_m_version <= 1) { iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A); IWL_DEBUG_INFO("Card M type A version is 0x%X\n", - priv->eeprom39.almgor_m_version); + eeprom->almgor_m_version); } else { IWL_DEBUG_INFO("Card M type B version is 0x%X\n", - priv->eeprom39.almgor_m_version); + eeprom->almgor_m_version); iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B); } spin_unlock_irqrestore(&priv->lock, flags); - if (priv->eeprom39.sku_cap & EEPROM_SKU_CAP_SW_RF_KILL_ENABLE) + if (eeprom->sku_cap & EEPROM_SKU_CAP_SW_RF_KILL_ENABLE) IWL_DEBUG_RF_KILL("SW RF KILL supported in EEPROM.\n"); - if (priv->eeprom39.sku_cap & EEPROM_SKU_CAP_HW_RF_KILL_ENABLE) + if (eeprom->sku_cap & EEPROM_SKU_CAP_HW_RF_KILL_ENABLE) IWL_DEBUG_RF_KILL("HW RF KILL supported in EEPROM.\n"); } @@ -1406,6 +1410,7 @@ int iwl3945_hw_get_temperature(struct iwl_priv *priv) */ static int iwl3945_hw_reg_txpower_get_temperature(struct iwl_priv *priv) { + struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; int temperature; temperature = iwl3945_hw_get_temperature(priv); @@ -1421,7 +1426,7 @@ static int iwl3945_hw_reg_txpower_get_temperature(struct iwl_priv *priv) /* if really really hot(?), * substitute the 3rd band/group's temp measured at factory */ if (priv->last_temperature > 100) - temperature = priv->eeprom39.groups[2].temperature; + temperature = eeprom->groups[2].temperature; else /* else use most recent "sane" value from driver */ temperature = priv->last_temperature; } @@ -1720,7 +1725,7 @@ int iwl3945_send_tx_power(struct iwl_priv *priv) }; txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1; - ch_info = iwl3945_get_channel_info(priv, + ch_info = iwl_get_channel_info(priv, priv->band, le16_to_cpu(priv->active39_rxon.channel)); if (!ch_info) { @@ -1881,6 +1886,7 @@ static int iwl3945_hw_reg_get_ch_txpower_limit(struct iwl_channel_info *ch_info) static int iwl3945_hw_reg_comp_txpower_temp(struct iwl_priv *priv) { struct iwl_channel_info *ch_info = NULL; + struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; int delta_index; const s8 *clip_pwrs; /* array of h/w max power levels for each rate */ u8 a_band; @@ -1896,7 +1902,7 @@ static int iwl3945_hw_reg_comp_txpower_temp(struct iwl_priv *priv) a_band = is_channel_a_band(ch_info); /* Get this chnlgrp's factory calibration temperature */ - ref_temp = (s16)priv->eeprom39.groups[ch_info->group_index]. + ref_temp = (s16)eeprom->groups[ch_info->group_index]. temperature; /* get power index adjustment based on current and factory @@ -2041,7 +2047,8 @@ static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work) static u16 iwl3945_hw_reg_get_ch_grp_index(struct iwl_priv *priv, const struct iwl_channel_info *ch_info) { - struct iwl3945_eeprom_txpower_group *ch_grp = &priv->eeprom39.groups[0]; + struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; + struct iwl3945_eeprom_txpower_group *ch_grp = &eeprom->groups[0]; u8 group; u16 group_index = 0; /* based on factory calib frequencies */ u8 grp_channel; @@ -2077,6 +2084,7 @@ static int iwl3945_hw_reg_get_matched_power_index(struct iwl_priv *priv, s32 setting_index, s32 *new_index) { const struct iwl3945_eeprom_txpower_group *chnl_grp = NULL; + struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; s32 index0, index1; s32 power = 2 * requested_power; s32 i; @@ -2085,7 +2093,7 @@ static int iwl3945_hw_reg_get_matched_power_index(struct iwl_priv *priv, s32 res; s32 denominator; - chnl_grp = &priv->eeprom39.groups[setting_index]; + chnl_grp = &eeprom->groups[setting_index]; samples = chnl_grp->samples; for (i = 0; i < 5; i++) { if (power == samples[i].power) { @@ -2124,6 +2132,7 @@ static void iwl3945_hw_reg_init_channel_groups(struct iwl_priv *priv) { u32 i; s32 rate_index; + struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; const struct iwl3945_eeprom_txpower_group *group; IWL_DEBUG_POWER("Initializing factory calib info from EEPROM\n"); @@ -2131,7 +2140,7 @@ static void iwl3945_hw_reg_init_channel_groups(struct iwl_priv *priv) for (i = 0; i < IWL_NUM_TX_CALIB_GROUPS; i++) { s8 *clip_pwrs; /* table of power levels for each rate */ s8 satur_pwr; /* saturation power for each chnl group */ - group = &priv->eeprom39.groups[i]; + group = &eeprom->groups[i]; /* sanity check on factory saturation power value */ if (group->saturation_power < 40) { @@ -2204,6 +2213,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv) { struct iwl_channel_info *ch_info = NULL; struct iwl3945_channel_power_info *pwr_info; + struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; int delta_index; u8 rate_index; u8 scan_tbl_index; @@ -2238,7 +2248,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv) /* calculate power index *adjustment* value according to * diff between current temperature and factory temperature */ delta_index = iwl3945_hw_reg_adjust_power_by_temp(temperature, - priv->eeprom39.groups[ch_info->group_index]. + eeprom->groups[ch_info->group_index]. temperature); IWL_DEBUG_POWER("Delta index for channel %d: %d [%d]\n", @@ -2585,6 +2595,33 @@ static int iwl3945_verify_bsm(struct iwl_priv *priv) return 0; } + +/****************************************************************************** + * + * EEPROM related functions + * + ******************************************************************************/ + +/* + * Clear the OWNER_MSK, to establish driver (instead of uCode running on + * embedded controller) as EEPROM reader; each read is a series of pulses + * to/from the EEPROM chip, not a single event, so even reads could conflict + * if they weren't arbitrated by some ownership mechanism. Here, the driver + * simply claims ownership, which should be safe when this function is called + * (i.e. before loading uCode!). + */ +static int iwl3945_eeprom_acquire_semaphore(struct iwl_priv *priv) +{ + _iwl_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK); + return 0; +} + + +static void iwl3945_eeprom_release_semaphore(struct iwl_priv *priv) +{ + return; +} + /** * iwl3945_load_bsm - Load bootstrap instructions * @@ -2715,6 +2752,21 @@ static struct iwl_lib_ops iwl3945_lib = { .config = iwl3945_nic_config, .set_pwr_src = iwl3945_set_pwr_src, }, + .eeprom_ops = { + .regulatory_bands = { + EEPROM_REGULATORY_BAND_1_CHANNELS, + EEPROM_REGULATORY_BAND_2_CHANNELS, + EEPROM_REGULATORY_BAND_3_CHANNELS, + EEPROM_REGULATORY_BAND_4_CHANNELS, + EEPROM_REGULATORY_BAND_5_CHANNELS, + IWL3945_EEPROM_IMG_SIZE, + IWL3945_EEPROM_IMG_SIZE, + }, + .verify_signature = iwlcore_eeprom_verify_signature, + .acquire_semaphore = iwl3945_eeprom_acquire_semaphore, + .release_semaphore = iwl3945_eeprom_release_semaphore, + .query_addr = iwlcore_eeprom_query_addr, + }, .send_tx_power = iwl3945_send_tx_power, }; @@ -2733,6 +2785,8 @@ static struct iwl_cfg iwl3945_bg_cfg = { .ucode_api_max = IWL3945_UCODE_API_MAX, .ucode_api_min = IWL3945_UCODE_API_MIN, .sku = IWL_SKU_G, + .eeprom_size = IWL3945_EEPROM_IMG_SIZE, + .eeprom_ver = EEPROM_3945_EEPROM_VERSION, .ops = &iwl3945_ops, .mod_params = &iwl3945_mod_params }; @@ -2743,6 +2797,8 @@ static struct iwl_cfg iwl3945_abg_cfg = { .ucode_api_max = IWL3945_UCODE_API_MAX, .ucode_api_min = IWL3945_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G, + .eeprom_size = IWL3945_EEPROM_IMG_SIZE, + .eeprom_ver = EEPROM_3945_EEPROM_VERSION, .ops = &iwl3945_ops, .mod_params = &iwl3945_mod_params }; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 5aa22d61e39..d4e07785d91 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1091,9 +1091,6 @@ struct iwl_priv { struct iwl3945_station_entry stations_39[IWL_STATION_COUNT]; - /* eeprom */ - struct iwl3945_eeprom eeprom39; - u32 sta_supp_rates; }; /*iwl_priv */ diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index cebfb8fa5da..eaa658f9e54 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -531,6 +531,13 @@ int iwl_init_channel_map(struct iwl_priv *priv) } } + /* Check if we do have FAT channels */ + if (priv->cfg->ops->lib->eeprom_ops.regulatory_bands[5] >= + priv->cfg->eeprom_size && + priv->cfg->ops->lib->eeprom_ops.regulatory_bands[6] >= + priv->cfg->eeprom_size) + return 0; + /* Two additional EEPROM bands for 2.4 and 5 GHz FAT channels */ for (band = 6; band <= 7; band++) { enum ieee80211_band ieeeband; @@ -582,6 +589,7 @@ void iwl_free_channel_map(struct iwl_priv *priv) kfree(priv->channel_info); priv->channel_count = 0; } +EXPORT_SYMBOL(iwl_free_channel_map); /** * iwl_get_channel_info - Find driver's private channel info diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index dd2e7d2c508..17fed49f9d9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -118,6 +118,9 @@ struct iwl_eeprom_channel { s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */ } __attribute__ ((packed)); +/* 3945 Specific */ +#define EEPROM_3945_EEPROM_VERSION (0x2f) + /* 4965 has two radio transmitters (and 3 radio receivers) */ #define EEPROM_TX_POWER_TX_CHAINS (2) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 14f95238059..b57c2b8c8dc 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -257,7 +257,7 @@ static int iwl3945_set_rxon_channel(struct iwl_priv *priv, enum ieee80211_band band, u16 channel) { - if (!iwl3945_get_channel_info(priv, band, channel)) { + if (!iwl_get_channel_info(priv, band, channel)) { IWL_DEBUG_INFO("Could not set channel to %d [%d]\n", channel, band); return -EINVAL; @@ -834,86 +834,6 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv) return rc; } -/****************************************************************************** - * - * EEPROM related functions - * - ******************************************************************************/ - -static void get_eeprom_mac(struct iwl_priv *priv, u8 *mac) -{ - memcpy(mac, priv->eeprom39.mac_address, 6); -} - -/* - * Clear the OWNER_MSK, to establish driver (instead of uCode running on - * embedded controller) as EEPROM reader; each read is a series of pulses - * to/from the EEPROM chip, not a single event, so even reads could conflict - * if they weren't arbitrated by some ownership mechanism. Here, the driver - * simply claims ownership, which should be safe when this function is called - * (i.e. before loading uCode!). - */ -static inline int iwl3945_eeprom_acquire_semaphore(struct iwl_priv *priv) -{ - _iwl_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK); - return 0; -} - -/** - * iwl3945_eeprom_init - read EEPROM contents - * - * Load the EEPROM contents from adapter into priv->eeprom39 - * - * NOTE: This routine uses the non-debug IO access functions. - */ -int iwl3945_eeprom_init(struct iwl_priv *priv) -{ - u16 *e = (u16 *)&priv->eeprom39; - u32 gp = iwl_read32(priv, CSR_EEPROM_GP); - int sz = sizeof(priv->eeprom39); - int ret; - u16 addr; - - /* The EEPROM structure has several padding buffers within it - * and when adding new EEPROM maps is subject to programmer errors - * which may be very difficult to identify without explicitly - * checking the resulting size of the eeprom map. */ - BUILD_BUG_ON(sizeof(priv->eeprom39) != IWL_EEPROM_IMAGE_SIZE); - - if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) { - IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); - return -ENOENT; - } - - /* Make sure driver (instead of uCode) is allowed to read EEPROM */ - ret = iwl3945_eeprom_acquire_semaphore(priv); - if (ret < 0) { - IWL_ERR(priv, "Failed to acquire EEPROM semaphore.\n"); - return -ENOENT; - } - - /* eeprom is an array of 16bit values */ - for (addr = 0; addr < sz; addr += sizeof(u16)) { - u32 r; - - _iwl_write32(priv, CSR_EEPROM_REG, - CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); - _iwl_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD); - ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG, - CSR_EEPROM_REG_READ_VALID_MSK, - IWL_EEPROM_ACCESS_TIMEOUT); - if (ret < 0) { - IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr); - return ret; - } - - r = _iwl_read_direct32(priv, CSR_EEPROM_REG); - e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); - } - - return 0; -} - static void iwl3945_unset_hw_params(struct iwl_priv *priv) { if (priv->shared_virt) @@ -1304,7 +1224,7 @@ static void iwl3945_connection_init_rx_config(struct iwl_priv *priv, priv->staging39_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; #endif - ch_info = iwl3945_get_channel_info(priv, priv->band, + ch_info = iwl_get_channel_info(priv, priv->band, le16_to_cpu(priv->active39_rxon.channel)); if (!ch_info) @@ -1336,7 +1256,7 @@ static int iwl3945_set_mode(struct iwl_priv *priv, int mode) if (mode == NL80211_IFTYPE_ADHOC) { const struct iwl_channel_info *ch_info; - ch_info = iwl3945_get_channel_info(priv, + ch_info = iwl_get_channel_info(priv, priv->band, le16_to_cpu(priv->staging39_rxon.channel)); @@ -3349,258 +3269,6 @@ unplugged: return IRQ_NONE; } -/************************** EEPROM BANDS **************************** - * - * The iwl3945_eeprom_band definitions below provide the mapping from the - * EEPROM contents to the specific channel number supported for each - * band. - * - * For example, iwl3945_priv->eeprom39.band_3_channels[4] from the band_3 - * definition below maps to physical channel 42 in the 5.2GHz spectrum. - * The specific geography and calibration information for that channel - * is contained in the eeprom map itself. - * - * During init, we copy the eeprom information and channel map - * information into priv->channel_info_24/52 and priv->channel_map_24/52 - * - * channel_map_24/52 provides the index in the channel_info array for a - * given channel. We have to have two separate maps as there is channel - * overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and - * band_2 - * - * A value of 0xff stored in the channel_map indicates that the channel - * is not supported by the hardware at all. - * - * A value of 0xfe in the channel_map indicates that the channel is not - * valid for Tx with the current hardware. This means that - * while the system can tune and receive on a given channel, it may not - * be able to associate or transmit any frames on that - * channel. There is no corresponding channel information for that - * entry. - * - *********************************************************************/ - -/* 2.4 GHz */ -static const u8 iwl3945_eeprom_band_1[14] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 -}; - -/* 5.2 GHz bands */ -static const u8 iwl3945_eeprom_band_2[] = { /* 4915-5080MHz */ - 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 -}; - -static const u8 iwl3945_eeprom_band_3[] = { /* 5170-5320MHz */ - 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 -}; - -static const u8 iwl3945_eeprom_band_4[] = { /* 5500-5700MHz */ - 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 -}; - -static const u8 iwl3945_eeprom_band_5[] = { /* 5725-5825MHz */ - 145, 149, 153, 157, 161, 165 -}; - -static void iwl3945_init_band_reference(const struct iwl_priv *priv, int band, - int *eeprom_ch_count, - const struct iwl_eeprom_channel - **eeprom_ch_info, - const u8 **eeprom_ch_index) -{ - switch (band) { - case 1: /* 2.4GHz band */ - *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_1); - *eeprom_ch_info = priv->eeprom39.band_1_channels; - *eeprom_ch_index = iwl3945_eeprom_band_1; - break; - case 2: /* 4.9GHz band */ - *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_2); - *eeprom_ch_info = priv->eeprom39.band_2_channels; - *eeprom_ch_index = iwl3945_eeprom_band_2; - break; - case 3: /* 5.2GHz band */ - *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_3); - *eeprom_ch_info = priv->eeprom39.band_3_channels; - *eeprom_ch_index = iwl3945_eeprom_band_3; - break; - case 4: /* 5.5GHz band */ - *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_4); - *eeprom_ch_info = priv->eeprom39.band_4_channels; - *eeprom_ch_index = iwl3945_eeprom_band_4; - break; - case 5: /* 5.7GHz band */ - *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_5); - *eeprom_ch_info = priv->eeprom39.band_5_channels; - *eeprom_ch_index = iwl3945_eeprom_band_5; - break; - default: - BUG(); - return; - } -} - -/** - * iwl3945_get_channel_info - Find driver's private channel info - * - * Based on band and channel number. - */ -const struct iwl_channel_info * -iwl3945_get_channel_info(const struct iwl_priv *priv, - enum ieee80211_band band, u16 channel) -{ - int i; - - switch (band) { - case IEEE80211_BAND_5GHZ: - for (i = 14; i < priv->channel_count; i++) { - if (priv->channel_info[i].channel == channel) - return &priv->channel_info[i]; - } - break; - - case IEEE80211_BAND_2GHZ: - if (channel >= 1 && channel <= 14) - return &priv->channel_info[channel - 1]; - break; - case IEEE80211_NUM_BANDS: - WARN_ON(1); - } - - return NULL; -} - -#define CHECK_AND_PRINT(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \ - ? # x " " : "") - -/** - * iwl3945_init_channel_map - Set up driver's info for all possible channels - */ -static int iwl3945_init_channel_map(struct iwl_priv *priv) -{ - int eeprom_ch_count = 0; - const u8 *eeprom_ch_index = NULL; - const struct iwl_eeprom_channel *eeprom_ch_info = NULL; - int band, ch; - struct iwl_channel_info *ch_info; - - if (priv->channel_count) { - IWL_DEBUG_INFO("Channel map already initialized.\n"); - return 0; - } - - if (priv->eeprom39.version < 0x2f) { - IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n", - priv->eeprom39.version); - return -EINVAL; - } - - IWL_DEBUG_INFO("Initializing regulatory info from EEPROM\n"); - - priv->channel_count = - ARRAY_SIZE(iwl3945_eeprom_band_1) + - ARRAY_SIZE(iwl3945_eeprom_band_2) + - ARRAY_SIZE(iwl3945_eeprom_band_3) + - ARRAY_SIZE(iwl3945_eeprom_band_4) + - ARRAY_SIZE(iwl3945_eeprom_band_5); - - IWL_DEBUG_INFO("Parsing data for %d channels.\n", priv->channel_count); - - priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) * - priv->channel_count, GFP_KERNEL); - if (!priv->channel_info) { - IWL_ERR(priv, "Could not allocate channel_info\n"); - priv->channel_count = 0; - return -ENOMEM; - } - - ch_info = priv->channel_info; - - /* Loop through the 5 EEPROM bands adding them in order to the - * channel map we maintain (that contains additional information than - * what just in the EEPROM) */ - for (band = 1; band <= 5; band++) { - - iwl3945_init_band_reference(priv, band, &eeprom_ch_count, - &eeprom_ch_info, &eeprom_ch_index); - - /* Loop through each band adding each of the channels */ - for (ch = 0; ch < eeprom_ch_count; ch++) { - ch_info->channel = eeprom_ch_index[ch]; - ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ : - IEEE80211_BAND_5GHZ; - - /* permanently store EEPROM's channel regulatory flags - * and max power in channel info database. */ - ch_info->eeprom = eeprom_ch_info[ch]; - - /* Copy the run-time flags so they are there even on - * invalid channels */ - ch_info->flags = eeprom_ch_info[ch].flags; - - if (!(is_channel_valid(ch_info))) { - IWL_DEBUG_INFO("Ch. %d Flags %x [%sGHz] - " - "No traffic\n", - ch_info->channel, - ch_info->flags, - is_channel_a_band(ch_info) ? - "5.2" : "2.4"); - ch_info++; - continue; - } - - /* Initialize regulatory-based run-time data */ - ch_info->max_power_avg = ch_info->curr_txpow = - eeprom_ch_info[ch].max_power_avg; - ch_info->scan_power = eeprom_ch_info[ch].max_power_avg; - ch_info->min_power = 0; - - IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x" - " %ddBm): Ad-Hoc %ssupported\n", - ch_info->channel, - is_channel_a_band(ch_info) ? - "5.2" : "2.4", - CHECK_AND_PRINT(VALID), - CHECK_AND_PRINT(IBSS), - CHECK_AND_PRINT(ACTIVE), - CHECK_AND_PRINT(RADAR), - CHECK_AND_PRINT(WIDE), - CHECK_AND_PRINT(DFS), - eeprom_ch_info[ch].flags, - eeprom_ch_info[ch].max_power_avg, - ((eeprom_ch_info[ch]. - flags & EEPROM_CHANNEL_IBSS) - && !(eeprom_ch_info[ch]. - flags & EEPROM_CHANNEL_RADAR)) - ? "" : "not "); - - /* Set the tx_power_user_lmt to the highest power - * supported by any channel */ - if (eeprom_ch_info[ch].max_power_avg > - priv->tx_power_user_lmt) - priv->tx_power_user_lmt = - eeprom_ch_info[ch].max_power_avg; - - ch_info++; - } - } - - /* Set up txpower settings in driver for all channels */ - if (iwl3945_txpower_set_from_eeprom(priv)) - return -EIO; - - return 0; -} - -/* - * iwl3945_free_channel_map - undo allocations in iwl3945_init_channel_map - */ -static void iwl3945_free_channel_map(struct iwl_priv *priv) -{ - kfree(priv->channel_info); - priv->channel_count = 0; -} - static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, enum ieee80211_band band, u8 is_active, u8 n_probes, @@ -3631,7 +3299,7 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, scan_ch->channel = channels[i].hw_value; - ch_info = iwl3945_get_channel_info(priv, band, scan_ch->channel); + ch_info = iwl_get_channel_info(priv, band, scan_ch->channel); if (!is_channel_valid(ch_info)) { IWL_DEBUG_SCAN("Channel %d is INVALID for this band.\n", scan_ch->channel); @@ -3718,6 +3386,7 @@ static void iwl3945_init_hw_rates(struct iwl_priv *priv, /** * iwl3945_init_geos - Initialize mac80211's geo/channel info based from eeprom */ +#define IEEE80211_24GHZ_MAX_CHANNEL 14 static int iwl3945_init_geos(struct iwl_priv *priv) { struct iwl_channel_info *ch; @@ -3748,7 +3417,7 @@ static int iwl3945_init_geos(struct iwl_priv *priv) /* 5.2GHz channels start after the 2.4GHz channels */ sband = &priv->bands[IEEE80211_BAND_5GHZ]; - sband->channels = &channels[ARRAY_SIZE(iwl3945_eeprom_band_1)]; + sband->channels = &channels[IEEE80211_24GHZ_MAX_CHANNEL]; /* just OFDM */ sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE; @@ -5242,8 +4911,8 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed) spin_lock_irqsave(&priv->lock, flags); - ch_info = iwl3945_get_channel_info(priv, conf->channel->band, - conf->channel->hw_value); + ch_info = iwl_get_channel_info(priv, conf->channel->band, + conf->channel->hw_value); if (!is_channel_valid(ch_info)) { IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this band.\n", conf->channel->hw_value, conf->channel->band); @@ -6423,6 +6092,7 @@ static struct ieee80211_ops iwl3945_hw_ops = { static int iwl3945_init_drv(struct iwl_priv *priv) { int ret; + struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; priv->retry_rate = 1; priv->ibss_beacon = NULL; @@ -6456,12 +6126,24 @@ static int iwl3945_init_drv(struct iwl_priv *priv) priv->power_mode = IWL39_POWER_AC; priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER; - ret = iwl3945_init_channel_map(priv); + if (eeprom->version < EEPROM_3945_EEPROM_VERSION) { + IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n", + eeprom->version); + ret = -EINVAL; + goto err; + } + ret = iwl_init_channel_map(priv); if (ret) { IWL_ERR(priv, "initializing regulatory failed: %d\n", ret); goto err; } + /* Set up txpower settings in driver for all channels */ + if (iwl3945_txpower_set_from_eeprom(priv)) { + ret = -EIO; + goto err_free_channel_map; + } + ret = iwl3945_init_geos(priv); if (ret) { IWL_ERR(priv, "initializing geos failed: %d\n", ret); @@ -6471,7 +6153,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv) return 0; err_free_channel_map: - iwl3945_free_channel_map(priv); + iwl_free_channel_map(priv); err: return ret; } @@ -6482,6 +6164,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e struct iwl_priv *priv; struct ieee80211_hw *hw; struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); + struct iwl3945_eeprom *eeprom; unsigned long flags; /*********************** @@ -6597,13 +6280,14 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e * ********************/ /* Read the EEPROM */ - err = iwl3945_eeprom_init(priv); + err = iwl_eeprom_init(priv); if (err) { IWL_ERR(priv, "Unable to init EEPROM\n"); goto out_remove_sysfs; } /* MAC Address location in EEPROM same for 3945/4965 */ - get_eeprom_mac(priv, priv->mac_addr); + eeprom = (struct iwl3945_eeprom *)priv->eeprom; + memcpy(priv->mac_addr, eeprom->mac_address, ETH_ALEN); IWL_DEBUG_INFO("MAC address: %pM\n", priv->mac_addr); SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); @@ -6776,7 +6460,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); - iwl3945_free_channel_map(priv); + iwl_free_channel_map(priv); iwl3945_free_geos(priv); kfree(priv->scan); if (priv->ibss_beacon) -- GitLab From 534166dedaa9a660c7221b145b5e4088a2d9ac69 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 23 Jan 2009 13:45:16 -0800 Subject: [PATCH 0951/4982] iwl3945: Use the iwlcore geos routines By removing the init_rates() routine outside of the init_geos() one, we can share the geos routines between 3945 and agn. Signed-off-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 9 +- drivers/net/wireless/iwlwifi/iwl-core.h | 5 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 145 ++------------------ 3 files changed, 21 insertions(+), 138 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index b64377e760e..902b75f25ea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -406,7 +406,7 @@ static void iwlcore_init_hw_rates(struct iwl_priv *priv, /** * iwlcore_init_geos - Initialize mac80211's geo/channel info based from eeprom */ -static int iwlcore_init_geos(struct iwl_priv *priv) +int iwlcore_init_geos(struct iwl_priv *priv) { struct iwl_channel_info *ch; struct ieee80211_supported_band *sband; @@ -458,8 +458,6 @@ static int iwlcore_init_geos(struct iwl_priv *priv) priv->ieee_channels = channels; priv->ieee_rates = rates; - iwlcore_init_hw_rates(priv, rates); - for (i = 0; i < priv->channel_count; i++) { ch = &priv->channel_info[i]; @@ -526,16 +524,18 @@ static int iwlcore_init_geos(struct iwl_priv *priv) return 0; } +EXPORT_SYMBOL(iwlcore_init_geos); /* * iwlcore_free_geos - undo allocations in iwlcore_init_geos */ -static void iwlcore_free_geos(struct iwl_priv *priv) +void iwlcore_free_geos(struct iwl_priv *priv) { kfree(priv->ieee_channels); kfree(priv->ieee_rates); clear_bit(STATUS_GEO_CONFIGURED, &priv->status); } +EXPORT_SYMBOL(iwlcore_free_geos); static bool is_single_rx_stream(struct iwl_priv *priv) { @@ -936,6 +936,7 @@ int iwl_init_drv(struct iwl_priv *priv) IWL_ERR(priv, "initializing geos failed: %d\n", ret); goto err_free_channel_map; } + iwlcore_init_hw_rates(priv, priv->ieee_rates); return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 9a350806a21..0c6250cd51d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -395,6 +395,11 @@ void iwl_enable_interrupts(struct iwl_priv *priv); void iwl_dump_nic_error_log(struct iwl_priv *priv); void iwl_dump_nic_event_log(struct iwl_priv *priv); +/***************************************************** +* GEOS +******************************************************/ +int iwlcore_init_geos(struct iwl_priv *priv); +void iwlcore_free_geos(struct iwl_priv *priv); /*************** DRIVER STATUS FUNCTIONS *****/ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index b57c2b8c8dc..5fa5cb2c21a 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3383,137 +3383,6 @@ static void iwl3945_init_hw_rates(struct iwl_priv *priv, } } -/** - * iwl3945_init_geos - Initialize mac80211's geo/channel info based from eeprom - */ -#define IEEE80211_24GHZ_MAX_CHANNEL 14 -static int iwl3945_init_geos(struct iwl_priv *priv) -{ - struct iwl_channel_info *ch; - struct ieee80211_supported_band *sband; - struct ieee80211_channel *channels; - struct ieee80211_channel *geo_ch; - struct ieee80211_rate *rates; - int i = 0; - - if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || - priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { - IWL_DEBUG_INFO("Geography modes already initialized.\n"); - set_bit(STATUS_GEO_CONFIGURED, &priv->status); - return 0; - } - - channels = kzalloc(sizeof(struct ieee80211_channel) * - priv->channel_count, GFP_KERNEL); - if (!channels) - return -ENOMEM; - - rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_RATE_COUNT + 1)), - GFP_KERNEL); - if (!rates) { - kfree(channels); - return -ENOMEM; - } - - /* 5.2GHz channels start after the 2.4GHz channels */ - sband = &priv->bands[IEEE80211_BAND_5GHZ]; - sband->channels = &channels[IEEE80211_24GHZ_MAX_CHANNEL]; - /* just OFDM */ - sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; - sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE; - - sband = &priv->bands[IEEE80211_BAND_2GHZ]; - sband->channels = channels; - /* OFDM & CCK */ - sband->bitrates = rates; - sband->n_bitrates = IWL_RATE_COUNT; - - priv->ieee_channels = channels; - priv->ieee_rates = rates; - - iwl3945_init_hw_rates(priv, rates); - - for (i = 0; i < priv->channel_count; i++) { - ch = &priv->channel_info[i]; - - /* FIXME: might be removed if scan is OK*/ - if (!is_channel_valid(ch)) - continue; - - if (is_channel_a_band(ch)) - sband = &priv->bands[IEEE80211_BAND_5GHZ]; - else - sband = &priv->bands[IEEE80211_BAND_2GHZ]; - - geo_ch = &sband->channels[sband->n_channels++]; - - geo_ch->center_freq = ieee80211_channel_to_frequency(ch->channel); - geo_ch->max_power = ch->max_power_avg; - geo_ch->max_antenna_gain = 0xff; - geo_ch->hw_value = ch->channel; - - if (is_channel_valid(ch)) { - if (!(ch->flags & EEPROM_CHANNEL_IBSS)) - geo_ch->flags |= IEEE80211_CHAN_NO_IBSS; - - if (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) - geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN; - - if (ch->flags & EEPROM_CHANNEL_RADAR) - geo_ch->flags |= IEEE80211_CHAN_RADAR; - - if (ch->max_power_avg > priv->tx_power_channel_lmt) - priv->tx_power_channel_lmt = - ch->max_power_avg; - } else { - geo_ch->flags |= IEEE80211_CHAN_DISABLED; - } - - /* Save flags for reg domain usage */ - geo_ch->orig_flags = geo_ch->flags; - - IWL_DEBUG_INFO("Channel %d Freq=%d[%sGHz] %s flag=0%X\n", - ch->channel, geo_ch->center_freq, - is_channel_a_band(ch) ? "5.2" : "2.4", - geo_ch->flags & IEEE80211_CHAN_DISABLED ? - "restricted" : "valid", - geo_ch->flags); - } - - if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && - priv->cfg->sku & IWL_SKU_A) { - IWL_INFO(priv, "Incorrectly detected BG card as ABG. " - "Please send your PCI ID 0x%04X:0x%04X to maintainer.\n", - priv->pci_dev->device, priv->pci_dev->subsystem_device); - priv->cfg->sku &= ~IWL_SKU_A; - } - - IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n", - priv->bands[IEEE80211_BAND_2GHZ].n_channels, - priv->bands[IEEE80211_BAND_5GHZ].n_channels); - - if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) - priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = - &priv->bands[IEEE80211_BAND_2GHZ]; - if (priv->bands[IEEE80211_BAND_5GHZ].n_channels) - priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = - &priv->bands[IEEE80211_BAND_5GHZ]; - - set_bit(STATUS_GEO_CONFIGURED, &priv->status); - - return 0; -} - -/* - * iwl3945_free_geos - undo allocations in iwl3945_init_geos - */ -static void iwl3945_free_geos(struct iwl_priv *priv) -{ - kfree(priv->ieee_channels); - kfree(priv->ieee_rates); - clear_bit(STATUS_GEO_CONFIGURED, &priv->status); -} - /****************************************************************************** * * uCode download functions @@ -6144,11 +6013,19 @@ static int iwl3945_init_drv(struct iwl_priv *priv) goto err_free_channel_map; } - ret = iwl3945_init_geos(priv); + ret = iwlcore_init_geos(priv); if (ret) { IWL_ERR(priv, "initializing geos failed: %d\n", ret); goto err_free_channel_map; } + iwl3945_init_hw_rates(priv, priv->ieee_rates); + + if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) + priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = + &priv->bands[IEEE80211_BAND_2GHZ]; + if (priv->bands[IEEE80211_BAND_5GHZ].n_channels) + priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = + &priv->bands[IEEE80211_BAND_5GHZ]; return 0; @@ -6379,7 +6256,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e out_remove_sysfs: sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); out_free_geos: - iwl3945_free_geos(priv); + iwlcore_free_geos(priv); out_release_irq: free_irq(priv->pci_dev->irq, priv); @@ -6461,7 +6338,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) pci_set_drvdata(pdev, NULL); iwl_free_channel_map(priv); - iwl3945_free_geos(priv); + iwlcore_free_geos(priv); kfree(priv->scan); if (priv->ibss_beacon) dev_kfree_skb(priv->ibss_beacon); -- GitLab From d08853a3995cfc2985307da7400fb57bfa5773e2 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 23 Jan 2009 13:45:17 -0800 Subject: [PATCH 0952/4982] iwlwifi: Remove IWL3945_DEBUG IWL3945_DEBUG is pointless and obsolete. We already have an IWLWIFI_DEBUG symbol, that needs to be set if we actually want to get 3945 debug (see iwl-debug.h). Thus, we can simply get rid of this symbol. Signed-off-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Kconfig | 29 +------------------- drivers/net/wireless/iwlwifi/iwl-3945.c | 22 +++++++++------ drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 30 ++++++++++----------- 4 files changed, 31 insertions(+), 52 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index f38130abab0..7b3bad1796c 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -20,7 +20,7 @@ config IWLWIFI_RFKILL depends on IWLCORE config IWLWIFI_DEBUG - bool "Enable full debugging output in iwlagn driver" + bool "Enable full debugging output in iwlagn and iwl3945 drivers" depends on IWLCORE ---help--- This option will enable debug tracing output for the iwlwifi drivers @@ -144,30 +144,3 @@ config IWL3945_LEDS depends on IWL3945 ---help--- This option enables LEDS for the iwl3945 driver. - -config IWL3945_DEBUG - bool "Enable full debugging output in iwl3945 driver" - depends on IWL3945 - ---help--- - This option will enable debug tracing output for the iwl3945 - driver. - - This will result in the kernel module being ~100k larger. You can - control which debug output is sent to the kernel log by setting the - value in - - /sys/bus/pci/drivers/${DRIVER}/debug_level - - This entry will only exist if this option is enabled. - - To set a value, simply echo an 8-byte hex value to the same file: - - % echo 0x43fff > /sys/bus/pci/drivers/${DRIVER}/debug_level - - You can find the list of debug mask values in: - drivers/net/wireless/iwlwifi/iwl-3945-debug.h - - If this is your first time using this driver, you should say Y here - as the debug information can assist others in helping you resolve - any problems you may encounter. - diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 75e9553a940..b9c5cf9a671 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -232,7 +232,7 @@ __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv) return 0; /* "diversity" is default if error */ } -#ifdef CONFIG_IWL3945_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x static const char *iwl3945_get_tx_fail_reason(u32 status) @@ -412,7 +412,7 @@ void iwl3945_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *r * Misc. internal state and helper functions * ******************************************************************************/ -#ifdef CONFIG_IWL3945_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG /** * iwl3945_report_frame - dump frame to syslog during debug sessions @@ -421,7 +421,7 @@ void iwl3945_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *r * including selective frame dumps. * group100 parameter selects whether to show 1 out of 100 good frames. */ -static void iwl3945_dbg_report_frame(struct iwl_priv *priv, +static void _iwl3945_dbg_report_frame(struct iwl_priv *priv, struct iwl_rx_packet *pkt, struct ieee80211_hdr *header, int group100) { @@ -548,6 +548,15 @@ static void iwl3945_dbg_report_frame(struct iwl_priv *priv, if (print_dump) iwl_print_hex_dump(priv, IWL_DL_RX, data, length); } + +static void iwl3945_dbg_report_frame(struct iwl_priv *priv, + struct iwl_rx_packet *pkt, + struct ieee80211_hdr *header, int group100) +{ + if (priv->debug_level & IWL_DL_RX) + _iwl3945_dbg_report_frame(priv, pkt, header, group100); +} + #else static inline void iwl3945_dbg_report_frame(struct iwl_priv *priv, struct iwl_rx_packet *pkt, @@ -711,11 +720,8 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, rx_status.signal, rx_status.signal, rx_status.noise, rx_status.rate_idx); -#ifdef CONFIG_IWL3945_DEBUG - if (priv->debug_level & (IWL_DL_RX)) - /* Set "1" to report good data frames in groups of 100 */ - iwl3945_dbg_report_frame(priv, pkt, header, 1); -#endif + /* Set "1" to report good data frames in groups of 100 */ + iwl3945_dbg_report_frame(priv, pkt, header, 1); if (network_packet) { priv->last_beacon_time = le32_to_cpu(rx_end->beacon_timestamp); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index d4e07785d91..5dbab7662b8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1059,7 +1059,7 @@ struct iwl_priv { s8 tx_power_channel_lmt; -#if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWL3945_DEBUG) +#ifdef CONFIG_IWLWIFI_DEBUG /* debugging info */ u32 debug_level; u32 framecnt_to_us; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 5fa5cb2c21a..d832cb95a92 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -63,7 +63,7 @@ #define DRV_DESCRIPTION \ "Intel(R) PRO/Wireless 3945ABG/BG Network Connection driver for Linux" -#ifdef CONFIG_IWL3945_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG #define VD "d" #else #define VD @@ -1503,7 +1503,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) fc = hdr->frame_control; -#ifdef CONFIG_IWL3945_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG if (ieee80211_is_auth(fc)) IWL_DEBUG_TX("Sending AUTH frame\n"); else if (ieee80211_is_assoc_req(fc)) @@ -2045,7 +2045,7 @@ static void iwl3945_rx_spectrum_measure_notif(struct iwl_priv *priv, static void iwl3945_rx_pm_sleep_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { -#ifdef CONFIG_IWL3945_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif); IWL_DEBUG_RX("sleep mode: %d, src: %d\n", @@ -2092,7 +2092,7 @@ static void iwl3945_bg_beacon_update(struct work_struct *work) static void iwl3945_rx_beacon_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { -#ifdef CONFIG_IWL3945_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status); u8 rate = beacon->beacon_notify_hdr.rate; @@ -2115,7 +2115,7 @@ static void iwl3945_rx_beacon_notif(struct iwl_priv *priv, static void iwl3945_rx_reply_scan(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { -#ifdef CONFIG_IWL3945_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl_scanreq_notification *notif = (struct iwl_scanreq_notification *)pkt->u.raw; @@ -2788,7 +2788,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) iwl3945_rx_queue_restock(priv); } -#ifdef CONFIG_IWL3945_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG static void iwl3945_print_rx_config_cmd(struct iwl_priv *priv, struct iwl3945_rxon_cmd *rxon) { @@ -3028,7 +3028,7 @@ static void iwl3945_irq_handle_error(struct iwl_priv *priv) /* Cancel currently queued command. */ clear_bit(STATUS_HCMD_ACTIVE, &priv->status); -#ifdef CONFIG_IWL3945_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG if (priv->debug_level & IWL_DL_FW_ERRORS) { iwl3945_dump_nic_error_log(priv); iwl3945_dump_nic_event_log(priv); @@ -3077,7 +3077,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) u32 inta, handled = 0; u32 inta_fh; unsigned long flags; -#ifdef CONFIG_IWL3945_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG u32 inta_mask; #endif @@ -3095,7 +3095,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh); -#ifdef CONFIG_IWL3945_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG if (priv->debug_level & IWL_DL_ISR) { /* just for debug */ inta_mask = iwl_read32(priv, CSR_INT_MASK); @@ -3129,7 +3129,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) return; } -#ifdef CONFIG_IWL3945_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG if (priv->debug_level & (IWL_DL_ISR)) { /* NIC fires this, but we don't use it, redundant with WAKEUP */ if (inta & CSR_INT_BIT_SCD) @@ -3200,7 +3200,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) if (test_bit(STATUS_INT_ENABLED, &priv->status)) iwl3945_enable_interrupts(priv); -#ifdef CONFIG_IWL3945_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG if (priv->debug_level & (IWL_DL_ISR)) { inta = iwl_read32(priv, CSR_INT); inta_mask = iwl_read32(priv, CSR_INT_MASK); @@ -5414,7 +5414,7 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk * *****************************************************************************/ -#ifdef CONFIG_IWL3945_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG /* * The following adds a new attribute to the sysfs representation @@ -5450,7 +5450,7 @@ static ssize_t store_debug_level(struct device *d, static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, show_debug_level, store_debug_level); -#endif /* CONFIG_IWL3945_DEBUG */ +#endif /* CONFIG_IWLWIFI_DEBUG */ static ssize_t show_temperature(struct device *d, struct device_attribute *attr, char *buf) @@ -5930,7 +5930,7 @@ static struct attribute *iwl3945_sysfs_entries[] = { &dev_attr_status.attr, &dev_attr_temperature.attr, &dev_attr_tx_power.attr, -#ifdef CONFIG_IWL3945_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG &dev_attr_debug_level.attr, #endif NULL @@ -6082,7 +6082,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->cfg = cfg; priv->pci_dev = pdev; -#ifdef CONFIG_IWL3945_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG priv->debug_level = iwl3945_mod_params.debug; atomic_set(&priv->restrict_refcnt, 0); #endif -- GitLab From 7e4bca5e5b8dffd9373470693e20f43b0aee566c Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 23 Jan 2009 13:45:18 -0800 Subject: [PATCH 0953/4982] iwl3945: Getting rid of priv->antenna The iwl_priv antenna field is useless as we can simply use the corresponding mod_params antenna field. Signed-off-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 35 ---------------- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 44 ++++++++++++++++++--- 3 files changed, 39 insertions(+), 41 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index b9c5cf9a671..7f1e04205f3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -197,41 +197,6 @@ static int iwl3945_hwrate_to_plcp_idx(u8 plcp) return -1; } -/** - * iwl3945_get_antenna_flags - Get antenna flags for RXON command - * @priv: eeprom and antenna fields are used to determine antenna flags - * - * priv->eeprom39 is used to determine if antenna AUX/MAIN are reversed - * priv->antenna specifies the antenna diversity mode: - * - * IWL_ANTENNA_DIVERSITY - NIC selects best antenna by itself - * IWL_ANTENNA_MAIN - Force MAIN antenna - * IWL_ANTENNA_AUX - Force AUX antenna - */ -__le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv) -{ - struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; - - switch (priv->antenna) { - case IWL_ANTENNA_DIVERSITY: - return 0; - - case IWL_ANTENNA_MAIN: - if (eeprom->antenna_switch_type) - return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK; - return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK; - - case IWL_ANTENNA_AUX: - if (eeprom->antenna_switch_type) - return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK; - return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK; - } - - /* bad antenna selector value */ - IWL_ERR(priv, "Bad antenna selector value (0x%x)\n", priv->antenna); - return 0; /* "diversity" is default if error */ -} - #ifdef CONFIG_IWLWIFI_DEBUG #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 5dbab7662b8..437c05b9a33 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -978,7 +978,6 @@ struct iwl_priv { u16 rates_mask; u32 power_mode; - u32 antenna; u8 bssid[ETH_ALEN]; u16 rts_threshold; u8 mac_addr[ETH_ALEN]; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index d832cb95a92..8aaa6bfd128 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -447,6 +447,43 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) return rc; } +/** + * iwl3945_get_antenna_flags - Get antenna flags for RXON command + * @priv: eeprom and antenna fields are used to determine antenna flags + * + * priv->eeprom39 is used to determine if antenna AUX/MAIN are reversed + * iwl3945_mod_params.antenna specifies the antenna diversity mode: + * + * IWL_ANTENNA_DIVERSITY - NIC selects best antenna by itself + * IWL_ANTENNA_MAIN - Force MAIN antenna + * IWL_ANTENNA_AUX - Force AUX antenna + */ +__le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv) +{ + struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; + + switch (iwl3945_mod_params.antenna) { + case IWL_ANTENNA_DIVERSITY: + return 0; + + case IWL_ANTENNA_MAIN: + if (eeprom->antenna_switch_type) + return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK; + return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK; + + case IWL_ANTENNA_AUX: + if (eeprom->antenna_switch_type) + return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK; + return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK; + } + + /* bad antenna selector value */ + IWL_ERR(priv, "Bad antenna selector value (0x%x)\n", + iwl3945_mod_params.antenna); + + return 0; /* "diversity" is default if error */ +} + /** * iwl3945_commit_rxon - commit staging_rxon to hardware * @@ -5804,7 +5841,7 @@ static ssize_t show_antenna(struct device *d, if (!iwl_is_alive(priv)) return -EAGAIN; - return sprintf(buf, "%d\n", priv->antenna); + return sprintf(buf, "%d\n", iwl3945_mod_params.antenna); } static ssize_t store_antenna(struct device *d, @@ -5824,7 +5861,7 @@ static ssize_t store_antenna(struct device *d, if ((ant >= 0) && (ant <= 2)) { IWL_DEBUG_INFO("Setting antenna select to %d.\n", ant); - priv->antenna = (enum iwl3945_antenna)ant; + iwl3945_mod_params.antenna = (enum iwl3945_antenna)ant; } else IWL_DEBUG_INFO("Bad antenna select value %d.\n", ant); @@ -6089,9 +6126,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e hw->rate_control_algorithm = "iwl-3945-rs"; hw->sta_data_size = sizeof(struct iwl3945_sta_priv); - /* Select antenna (may be helpful if only one antenna is connected) */ - priv->antenna = (enum iwl3945_antenna)iwl3945_mod_params.antenna; - /* Tell mac80211 our characteristics */ hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; -- GitLab From af48d048ac5f10981df093c7566ae0fea9ba1967 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 23 Jan 2009 13:45:19 -0800 Subject: [PATCH 0954/4982] iwl3945: Add restart_fw module parameter In order to be in sync with the agn code, we're ading a fw_restart3945 module parameter to iwl3945. Signed-off-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 8aaa6bfd128..13fb6185184 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -90,6 +90,7 @@ MODULE_LICENSE("GPL"); struct iwl_mod_params iwl3945_mod_params = { .num_of_queues = IWL39_MAX_NUM_QUEUES, .sw_crypto = 1, + .restart_fw = 1, /* the rest are 0 by default */ }; @@ -3088,7 +3089,8 @@ static void iwl3945_irq_handle_error(struct iwl_priv *priv) sizeof(priv->recovery39_rxon)); priv->error_recovering = 1; } - queue_work(priv->workqueue, &priv->restart); + if (priv->cfg->mod_params->restart_fw) + queue_work(priv->workqueue, &priv->restart); } } @@ -6482,5 +6484,8 @@ MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); module_param_named(queues_num, iwl3945_mod_params.num_of_queues, int, 0444); MODULE_PARM_DESC(queues_num, "number of hw queues."); +module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, 0444); +MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error"); + module_exit(iwl3945_exit); module_init(iwl3945_init); -- GitLab From 17f841cd6cb0837ba0599ad18a746c30ddd83e08 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 23 Jan 2009 13:45:20 -0800 Subject: [PATCH 0955/4982] iwl3945: Remaining host command cleanups With the recent host command routines merge, we can now look at the various host command helpers and get rid of the duplicated ones. Signed-off-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 12 +- drivers/net/wireless/iwlwifi/iwl-3945.h | 1 - drivers/net/wireless/iwlwifi/iwl-agn.c | 14 --- drivers/net/wireless/iwlwifi/iwl-core.c | 15 +++ drivers/net/wireless/iwlwifi/iwl-core.h | 2 + drivers/net/wireless/iwlwifi/iwl-scan.c | 4 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 6 +- drivers/net/wireless/iwlwifi/iwl-sta.h | 2 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 116 ++------------------ 9 files changed, 45 insertions(+), 127 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 7f1e04205f3..12f93b6207d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -41,6 +41,7 @@ #include "iwl-fh.h" #include "iwl-3945-fh.h" #include "iwl-commands.h" +#include "iwl-sta.h" #include "iwl-3945.h" #include "iwl-eeprom.h" #include "iwl-helpers.h" @@ -895,7 +896,8 @@ u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags) spin_unlock_irqrestore(&priv->sta_lock, flags_spin); - iwl3945_send_add_station(priv, &station->sta, flags); + iwl_send_add_sta(priv, + (struct iwl_addsta_cmd *)&station->sta, flags); IWL_DEBUG_RATE("SCALE sync station %d to rate %d\n", sta_id, tx_rate); return sta_id; @@ -2376,6 +2378,13 @@ static u16 iwl3945_get_hcmd_size(u8 cmd_id, u16 len) } } +static u16 iwl3945_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) +{ + u16 size = (u16)sizeof(struct iwl3945_addsta_cmd); + memcpy(data, cmd, size); + return size; +} + /** * iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table */ @@ -2743,6 +2752,7 @@ static struct iwl_lib_ops iwl3945_lib = { static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { .get_hcmd_size = iwl3945_get_hcmd_size, + .build_addsta_hcmd = iwl3945_build_addsta_hcmd, }; static struct iwl_ops iwl3945_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 77e97eaa4e4..fef54e9cf8a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -222,7 +222,6 @@ extern int __must_check iwl3945_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, struct ieee80211_hdr *hdr,int left); -extern int iwl3945_send_statistics_request(struct iwl_priv *priv); extern void iwl3945_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb, u32 decrypt_res, struct ieee80211_rx_status *stats); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 5c6b3fe3eed..757a9bd3ecd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -310,20 +310,6 @@ void iwl_update_chain_flags(struct iwl_priv *priv) iwl_commit_rxon(priv); } -static int iwl_send_bt_config(struct iwl_priv *priv) -{ - struct iwl_bt_cmd bt_cmd = { - .flags = 3, - .lead_time = 0xAA, - .max_kill = 1, - .kill_ack_mask = 0, - .kill_cts_mask = 0, - }; - - return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, - sizeof(struct iwl_bt_cmd), &bt_cmd); -} - static void iwl_clear_free_frames(struct iwl_priv *priv) { struct list_head *element; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 902b75f25ea..21f386568c9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1007,6 +1007,21 @@ void iwl_enable_interrupts(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_enable_interrupts); +int iwl_send_bt_config(struct iwl_priv *priv) +{ + struct iwl_bt_cmd bt_cmd = { + .flags = 3, + .lead_time = 0xAA, + .max_kill = 1, + .kill_ack_mask = 0, + .kill_cts_mask = 0, + }; + + return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, + sizeof(struct iwl_bt_cmd), &bt_cmd); +} +EXPORT_SYMBOL(iwl_send_bt_config); + int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags) { u32 stat_flags = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 0c6250cd51d..c8e1dad6fb5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -335,6 +335,7 @@ void iwl_bg_scan_check(struct work_struct *data); void iwl_bg_abort_scan(struct work_struct *work); void iwl_bg_scan_completed(struct work_struct *work); void iwl_setup_scan_deferred_work(struct iwl_priv *priv); +int iwl_send_scan_abort(struct iwl_priv *priv); /* For faster active scanning, scan will move to the next channel if fewer than * PLCP_QUIET_THRESH packets are heard on this channel within @@ -468,6 +469,7 @@ static inline int iwl_is_ready_rf(struct iwl_priv *priv) } extern void iwl_rf_kill_ct_config(struct iwl_priv *priv); +extern int iwl_send_bt_config(struct iwl_priv *priv); extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags); extern int iwl_verify_ucode(struct iwl_priv *priv); extern int iwl_send_lq_cmd(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 0ce122a1734..c282d1d294e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -109,7 +109,7 @@ int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) } EXPORT_SYMBOL(iwl_scan_cancel_timeout); -static int iwl_send_scan_abort(struct iwl_priv *priv) +int iwl_send_scan_abort(struct iwl_priv *priv) { int ret = 0; struct iwl_rx_packet *res; @@ -150,7 +150,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) return ret; } - +EXPORT_SYMBOL(iwl_send_scan_abort); /* Service response to REPLY_SCAN_CMD (0x80) */ static void iwl_rx_reply_scan(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 0cbb4495c06..9bba98e5e05 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -86,7 +86,8 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) spin_lock_irqsave(&priv->sta_lock, flags); - if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) + if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE) && + !(priv->stations_39[sta_id].used & IWL_STA_DRIVER_ACTIVE)) IWL_ERR(priv, "ACTIVATE a non DRIVER active station %d\n", sta_id); @@ -131,7 +132,7 @@ static int iwl_add_sta_callback(struct iwl_priv *priv, return 1; } -static int iwl_send_add_sta(struct iwl_priv *priv, +int iwl_send_add_sta(struct iwl_priv *priv, struct iwl_addsta_cmd *sta, u8 flags) { struct iwl_rx_packet *res = NULL; @@ -179,6 +180,7 @@ static int iwl_send_add_sta(struct iwl_priv *priv, return ret; } +EXPORT_SYMBOL(iwl_send_add_sta); static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, struct ieee80211_sta_ht_cap *sta_ht_inf) diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 3fe7cc575fa..97f6169007f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -56,6 +56,8 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap); void iwl_clear_stations_table(struct iwl_priv *priv); int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); +int iwl_send_add_sta(struct iwl_priv *priv, + struct iwl_addsta_cmd *sta, u8 flags); u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flags, struct ieee80211_sta_ht_cap *ht_info); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 13fb6185184..d09325591de 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -51,6 +51,7 @@ #include "iwl-fh.h" #include "iwl-3945-fh.h" #include "iwl-commands.h" +#include "iwl-sta.h" #include "iwl-3945.h" #include "iwl-helpers.h" #include "iwl-core.h" @@ -226,24 +227,12 @@ u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flag spin_unlock_irqrestore(&priv->sta_lock, flags_spin); /* Add station to device's station table */ - iwl3945_send_add_station(priv, &station->sta, flags); + iwl_send_add_sta(priv, + (struct iwl_addsta_cmd *)&station->sta, flags); return index; } -int iwl3945_send_statistics_request(struct iwl_priv *priv) -{ - u32 val = 0; - - struct iwl_host_cmd cmd = { - .id = REPLY_STATISTICS_CMD, - .len = sizeof(val), - .data = &val, - }; - - return iwl_send_cmd_sync(priv, &cmd); -} - /** * iwl3945_set_rxon_channel - Set the phymode and channel values in staging RXON * @band: 2.4 or 5 GHz band @@ -611,95 +600,6 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) return 0; } -static int iwl3945_send_bt_config(struct iwl_priv *priv) -{ - struct iwl_bt_cmd bt_cmd = { - .flags = 3, - .lead_time = 0xAA, - .max_kill = 1, - .kill_ack_mask = 0, - .kill_cts_mask = 0, - }; - - return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, - sizeof(bt_cmd), &bt_cmd); -} - -static int iwl3945_add_sta_sync_callback(struct iwl_priv *priv, - struct iwl_cmd *cmd, struct sk_buff *skb) -{ - struct iwl_rx_packet *res = NULL; - - if (!skb) { - IWL_ERR(priv, "Error: Response NULL in REPLY_ADD_STA.\n"); - return 1; - } - - res = (struct iwl_rx_packet *)skb->data; - if (res->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", - res->hdr.flags); - return 1; - } - - switch (res->u.add_sta.status) { - case ADD_STA_SUCCESS_MSK: - break; - default: - break; - } - - /* We didn't cache the SKB; let the caller free it */ - return 1; -} - -int iwl3945_send_add_station(struct iwl_priv *priv, - struct iwl3945_addsta_cmd *sta, u8 flags) -{ - struct iwl_rx_packet *res = NULL; - int rc = 0; - struct iwl_host_cmd cmd = { - .id = REPLY_ADD_STA, - .len = sizeof(struct iwl3945_addsta_cmd), - .meta.flags = flags, - .data = sta, - }; - - if (flags & CMD_ASYNC) - cmd.meta.u.callback = iwl3945_add_sta_sync_callback; - else - cmd.meta.flags |= CMD_WANT_SKB; - - rc = iwl_send_cmd(priv, &cmd); - - if (rc || (flags & CMD_ASYNC)) - return rc; - - res = (struct iwl_rx_packet *)cmd.meta.u.skb->data; - if (res->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", - res->hdr.flags); - rc = -EIO; - } - - if (rc == 0) { - switch (res->u.add_sta.status) { - case ADD_STA_SUCCESS_MSK: - IWL_DEBUG_INFO("REPLY_ADD_STA PASSED\n"); - break; - default: - rc = -EIO; - IWL_WARN(priv, "REPLY_ADD_STA failed\n"); - break; - } - } - - priv->alloc_rxb_skb--; - dev_kfree_skb_any(cmd.meta.u.skb); - - return rc; -} - static int iwl3945_update_sta_key_info(struct iwl_priv *priv, struct ieee80211_key_conf *keyconf, u8 sta_id) @@ -734,7 +634,8 @@ static int iwl3945_update_sta_key_info(struct iwl_priv *priv, spin_unlock_irqrestore(&priv->sta_lock, flags); IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n"); - iwl3945_send_add_station(priv, &priv->stations_39[sta_id].sta, 0); + iwl_send_add_sta(priv, + (struct iwl_addsta_cmd *)&priv->stations_39[sta_id].sta, 0); return 0; } @@ -752,7 +653,8 @@ static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) spin_unlock_irqrestore(&priv->sta_lock, flags); IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n"); - iwl3945_send_add_station(priv, &priv->stations_39[sta_id].sta, 0); + iwl_send_add_sta(priv, + (struct iwl_addsta_cmd *)&priv->stations_39[sta_id].sta, 0); return 0; } @@ -4005,7 +3907,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) } /* Configure Bluetooth device coexistence support */ - iwl3945_send_bt_config(priv); + iwl_send_bt_config(priv); /* Configure the adapter for unassociated operation */ iwl3945_commit_rxon(priv); @@ -5810,7 +5712,7 @@ static ssize_t show_statistics(struct device *d, return -EAGAIN; mutex_lock(&priv->mutex); - rc = iwl3945_send_statistics_request(priv); + rc = iwl_send_statistics_request(priv, 0); mutex_unlock(&priv->mutex); if (rc) { -- GitLab From 0d21044effa10044930419c6f837f75191229c3a Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Fri, 23 Jan 2009 13:45:21 -0800 Subject: [PATCH 0956/4982] iwlwifi: fix probe mask for 39 scan API This pach make use of 39 own scan probe mask the variables or of different types Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-commands.h | 6 ++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 1 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 7571110f5f1..e49415c7fb2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2432,6 +2432,9 @@ struct iwl3945_scan_channel { __le16 passive_dwell; /* in 1024-uSec TU (time units), typ 20-500 */ } __attribute__ ((packed)); +/* set number of direct probes u8 type */ +#define IWL39_SCAN_PROBE_MASK(n) ((BIT(n) | (BIT(n) - BIT(1)))) + struct iwl_scan_channel { /* * type is defined as: @@ -2448,6 +2451,9 @@ struct iwl_scan_channel { __le16 passive_dwell; /* in 1024-uSec TU (time units), typ 20-500 */ } __attribute__ ((packed)); +/* set number of direct probes __le32 type */ +#define IWL_SCAN_PROBE_MASK(n) cpu_to_le32((BIT(n) | (BIT(n) - BIT(1)))) + /** * struct iwl_ssid_ie - directed scan network information element * diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index c8e1dad6fb5..3c6a4b0c2c3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -346,7 +346,6 @@ int iwl_send_scan_abort(struct iwl_priv *priv); #define IWL_ACTIVE_QUIET_TIME __constant_cpu_to_le16(10) /* msec */ #define IWL_PLCP_QUIET_THRESH __constant_cpu_to_le16(1) /* packets */ -#define IWL_SCAN_PROBE_MASK(n) cpu_to_le32((BIT(n) | (BIT(n) - BIT(1)))) /******************************************************************************* * Calibrations - implemented in iwl-calib.c diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index d09325591de..25a350810a1 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3267,12 +3267,12 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, * hearing clear Rx packet).*/ if (IWL_UCODE_API(priv->ucode_ver) >= 2) { if (n_probes) - scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes); + scan_ch->type |= IWL39_SCAN_PROBE_MASK(n_probes); } else { /* uCode v1 does not allow setting direct probe bits on * passive channel. */ if ((scan_ch->type & 1) && n_probes) - scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes); + scan_ch->type |= IWL39_SCAN_PROBE_MASK(n_probes); } /* Set txpower levels to defaults */ -- GitLab From f55d4517ebdd6de627d42a24baefaeb689978087 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 24 Jan 2009 09:04:12 -0500 Subject: [PATCH 0957/4982] airo: clean up and clarify interrupt-time task handling Split each specific interrupt-time task out into its own function to make airo_interrupt() actually readable. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 613 +++++++++++++++++++----------------- 1 file changed, 327 insertions(+), 286 deletions(-) diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 2ff588bb0a7..a192c4472e0 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -981,6 +981,14 @@ typedef struct { dma_addr_t host_addr; } TxFid; +struct rx_hdr { + __le16 status, len; + u8 rssi[2]; + u8 rate; + u8 freq; + __le16 tmp[4]; +} __attribute__ ((packed)); + typedef struct { unsigned int ctl: 15; unsigned int rdy: 1; @@ -3123,314 +3131,354 @@ static int header_len(__le16 ctl) return 24; } -static irqreturn_t airo_interrupt(int irq, void *dev_id) +static void airo_handle_cisco_mic(struct airo_info *ai) { - struct net_device *dev = dev_id; + if (test_bit(FLAG_MIC_CAPABLE, &ai->flags)) { + set_bit(JOB_MIC, &ai->jobs); + wake_up_interruptible(&ai->thr_wait); + } +} + +/* Airo Status codes */ +#define STAT_NOBEACON 0x8000 /* Loss of sync - missed beacons */ +#define STAT_MAXRETRIES 0x8001 /* Loss of sync - max retries */ +#define STAT_MAXARL 0x8002 /* Loss of sync - average retry level exceeded*/ +#define STAT_FORCELOSS 0x8003 /* Loss of sync - host request */ +#define STAT_TSFSYNC 0x8004 /* Loss of sync - TSF synchronization */ +#define STAT_DEAUTH 0x8100 /* low byte is 802.11 reason code */ +#define STAT_DISASSOC 0x8200 /* low byte is 802.11 reason code */ +#define STAT_ASSOC_FAIL 0x8400 /* low byte is 802.11 reason code */ +#define STAT_AUTH_FAIL 0x0300 /* low byte is 802.11 reason code */ +#define STAT_ASSOC 0x0400 /* Associated */ +#define STAT_REASSOC 0x0600 /* Reassociated? Only on firmware >= 5.30.17 */ + +static void airo_print_status(const char *devname, u16 status) +{ + u8 reason = status & 0xFF; + + switch (status) { + case STAT_NOBEACON: + airo_print_dbg(devname, "link lost (missed beacons)"); + break; + case STAT_MAXRETRIES: + case STAT_MAXARL: + airo_print_dbg(devname, "link lost (max retries)"); + break; + case STAT_FORCELOSS: + airo_print_dbg(devname, "link lost (local choice)"); + break; + case STAT_TSFSYNC: + airo_print_dbg(devname, "link lost (TSF sync lost)"); + break; + case STAT_DEAUTH: + airo_print_dbg(devname, "deauthenticated (reason: %d)", reason); + break; + case STAT_DISASSOC: + airo_print_dbg(devname, "disassociated (reason: %d)", reason); + break; + case STAT_ASSOC_FAIL: + airo_print_dbg(devname, "association failed (reason: %d)", + reason); + break; + case STAT_AUTH_FAIL: + airo_print_dbg(devname, "authentication failed (reason: %d)", + reason); + break; + default: + break; + } +} + +static void airo_handle_link(struct airo_info *ai) +{ + union iwreq_data wrqu; + int scan_forceloss = 0; u16 status; - u16 fid; - struct airo_info *apriv = dev->ml_priv; - u16 savedInterrupts = 0; - int handled = 0; - if (!netif_device_present(dev)) - return IRQ_NONE; + /* Get new status and acknowledge the link change */ + status = le16_to_cpu(IN4500(ai, LINKSTAT)); + OUT4500(ai, EVACK, EV_LINK); - for (;;) { - status = IN4500( apriv, EVSTAT ); - if ( !(status & STATUS_INTS) || status == 0xffff ) break; + if ((status == STAT_FORCELOSS) && (ai->scan_timeout > 0)) + scan_forceloss = 1; - handled = 1; + airo_print_status(ai->dev->name, status); - if ( status & EV_AWAKE ) { - OUT4500( apriv, EVACK, EV_AWAKE ); - OUT4500( apriv, EVACK, EV_AWAKE ); - } + if ((status == STAT_ASSOC) || (status == STAT_REASSOC)) { + if (auto_wep) + ai->expires = 0; + if (ai->list_bss_task) + wake_up_process(ai->list_bss_task); + set_bit(FLAG_UPDATE_UNI, &ai->flags); + set_bit(FLAG_UPDATE_MULTI, &ai->flags); - if (!savedInterrupts) { - savedInterrupts = IN4500( apriv, EVINTEN ); - OUT4500( apriv, EVINTEN, 0 ); + if (down_trylock(&ai->sem) != 0) { + set_bit(JOB_EVENT, &ai->jobs); + wake_up_interruptible(&ai->thr_wait); + } else + airo_send_event(ai->dev); + } else if (!scan_forceloss) { + if (auto_wep && !ai->expires) { + ai->expires = RUN_AT(3*HZ); + wake_up_interruptible(&ai->thr_wait); } - if ( status & EV_MIC ) { - OUT4500( apriv, EVACK, EV_MIC ); - if (test_bit(FLAG_MIC_CAPABLE, &apriv->flags)) { - set_bit(JOB_MIC, &apriv->jobs); - wake_up_interruptible(&apriv->thr_wait); - } - } - if ( status & EV_LINK ) { - union iwreq_data wrqu; - int scan_forceloss = 0; - /* The link status has changed, if you want to put a - monitor hook in, do it here. (Remember that - interrupts are still disabled!) - */ - u16 newStatus = IN4500(apriv, LINKSTAT); - OUT4500( apriv, EVACK, EV_LINK); - /* Here is what newStatus means: */ -#define NOBEACON 0x8000 /* Loss of sync - missed beacons */ -#define MAXRETRIES 0x8001 /* Loss of sync - max retries */ -#define MAXARL 0x8002 /* Loss of sync - average retry level exceeded*/ -#define FORCELOSS 0x8003 /* Loss of sync - host request */ -#define TSFSYNC 0x8004 /* Loss of sync - TSF synchronization */ -#define DEAUTH 0x8100 /* Deauthentication (low byte is reason code) */ -#define DISASS 0x8200 /* Disassociation (low byte is reason code) */ -#define ASSFAIL 0x8400 /* Association failure (low byte is reason - code) */ -#define AUTHFAIL 0x0300 /* Authentication failure (low byte is reason - code) */ -#define ASSOCIATED 0x0400 /* Associated */ -#define REASSOCIATED 0x0600 /* Reassociated? Only on firmware >= 5.30.17 */ -#define RC_RESERVED 0 /* Reserved return code */ -#define RC_NOREASON 1 /* Unspecified reason */ -#define RC_AUTHINV 2 /* Previous authentication invalid */ -#define RC_DEAUTH 3 /* Deauthenticated because sending station is - leaving */ -#define RC_NOACT 4 /* Disassociated due to inactivity */ -#define RC_MAXLOAD 5 /* Disassociated because AP is unable to handle - all currently associated stations */ -#define RC_BADCLASS2 6 /* Class 2 frame received from - non-Authenticated station */ -#define RC_BADCLASS3 7 /* Class 3 frame received from - non-Associated station */ -#define RC_STATLEAVE 8 /* Disassociated because sending station is - leaving BSS */ -#define RC_NOAUTH 9 /* Station requesting (Re)Association is not - Authenticated with the responding station */ - if (newStatus == FORCELOSS && apriv->scan_timeout > 0) - scan_forceloss = 1; - if(newStatus == ASSOCIATED || newStatus == REASSOCIATED) { - if (auto_wep) - apriv->expires = 0; - if (apriv->list_bss_task) - wake_up_process(apriv->list_bss_task); - set_bit(FLAG_UPDATE_UNI, &apriv->flags); - set_bit(FLAG_UPDATE_MULTI, &apriv->flags); - - if (down_trylock(&apriv->sem) != 0) { - set_bit(JOB_EVENT, &apriv->jobs); - wake_up_interruptible(&apriv->thr_wait); - } else - airo_send_event(dev); - } else if (!scan_forceloss) { - if (auto_wep && !apriv->expires) { - apriv->expires = RUN_AT(3*HZ); - wake_up_interruptible(&apriv->thr_wait); - } + /* Send event to user space */ + memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + wireless_send_event(ai->dev, SIOCGIWAP, &wrqu, NULL); + } +} - /* Send event to user space */ - memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(dev, SIOCGIWAP, &wrqu,NULL); - } - } +static void airo_handle_rx(struct airo_info *ai) +{ + struct sk_buff *skb = NULL; + __le16 fc, v, *buffer, tmpbuf[4]; + u16 len, hdrlen = 0, gap, fid; + struct rx_hdr hdr; + int success = 0; - /* Check to see if there is something to receive */ - if ( status & EV_RX ) { - struct sk_buff *skb = NULL; - __le16 fc, v; - u16 len, hdrlen = 0; -#pragma pack(1) - struct { - __le16 status, len; - u8 rssi[2]; - u8 rate; - u8 freq; - __le16 tmp[4]; - } hdr; -#pragma pack() - u16 gap; - __le16 tmpbuf[4]; - __le16 *buffer; - - if (test_bit(FLAG_MPI,&apriv->flags)) { - if (test_bit(FLAG_802_11, &apriv->flags)) - mpi_receive_802_11(apriv); - else - mpi_receive_802_3(apriv); - OUT4500(apriv, EVACK, EV_RX); - goto exitrx; - } + if (test_bit(FLAG_MPI, &ai->flags)) { + if (test_bit(FLAG_802_11, &ai->flags)) + mpi_receive_802_11(ai); + else + mpi_receive_802_3(ai); + OUT4500(ai, EVACK, EV_RX); + return; + } - fid = IN4500( apriv, RXFID ); - - /* Get the packet length */ - if (test_bit(FLAG_802_11, &apriv->flags)) { - bap_setup (apriv, fid, 4, BAP0); - bap_read (apriv, (__le16*)&hdr, sizeof(hdr), BAP0); - /* Bad CRC. Ignore packet */ - if (le16_to_cpu(hdr.status) & 2) - hdr.len = 0; - if (apriv->wifidev == NULL) - hdr.len = 0; - } else { - bap_setup (apriv, fid, 0x36, BAP0); - bap_read (apriv, &hdr.len, 2, BAP0); - } - len = le16_to_cpu(hdr.len); + fid = IN4500(ai, RXFID); - if (len > AIRO_DEF_MTU) { - airo_print_err(apriv->dev->name, "Bad size %d", len); - goto badrx; - } - if (len == 0) - goto badrx; + /* Get the packet length */ + if (test_bit(FLAG_802_11, &ai->flags)) { + bap_setup (ai, fid, 4, BAP0); + bap_read (ai, (__le16*)&hdr, sizeof(hdr), BAP0); + /* Bad CRC. Ignore packet */ + if (le16_to_cpu(hdr.status) & 2) + hdr.len = 0; + if (ai->wifidev == NULL) + hdr.len = 0; + } else { + bap_setup(ai, fid, 0x36, BAP0); + bap_read(ai, &hdr.len, 2, BAP0); + } + len = le16_to_cpu(hdr.len); - if (test_bit(FLAG_802_11, &apriv->flags)) { - bap_read (apriv, &fc, sizeof(fc), BAP0); - hdrlen = header_len(fc); - } else - hdrlen = ETH_ALEN * 2; + if (len > AIRO_DEF_MTU) { + airo_print_err(ai->dev->name, "Bad size %d", len); + goto done; + } + if (len == 0) + goto done; - skb = dev_alloc_skb( len + hdrlen + 2 + 2 ); - if ( !skb ) { - dev->stats.rx_dropped++; - goto badrx; - } - skb_reserve(skb, 2); /* This way the IP header is aligned */ - buffer = (__le16*)skb_put (skb, len + hdrlen); - if (test_bit(FLAG_802_11, &apriv->flags)) { - buffer[0] = fc; - bap_read (apriv, buffer + 1, hdrlen - 2, BAP0); - if (hdrlen == 24) - bap_read (apriv, tmpbuf, 6, BAP0); - - bap_read (apriv, &v, sizeof(v), BAP0); - gap = le16_to_cpu(v); - if (gap) { - if (gap <= 8) { - bap_read (apriv, tmpbuf, gap, BAP0); - } else { - airo_print_err(apriv->dev->name, "gaplen too " - "big. Problems will follow..."); - } - } - bap_read (apriv, buffer + hdrlen/2, len, BAP0); + if (test_bit(FLAG_802_11, &ai->flags)) { + bap_read(ai, &fc, sizeof (fc), BAP0); + hdrlen = header_len(fc); + } else + hdrlen = ETH_ALEN * 2; + + skb = dev_alloc_skb(len + hdrlen + 2 + 2); + if (!skb) { + ai->dev->stats.rx_dropped++; + goto done; + } + + skb_reserve(skb, 2); /* This way the IP header is aligned */ + buffer = (__le16 *) skb_put(skb, len + hdrlen); + if (test_bit(FLAG_802_11, &ai->flags)) { + buffer[0] = fc; + bap_read(ai, buffer + 1, hdrlen - 2, BAP0); + if (hdrlen == 24) + bap_read(ai, tmpbuf, 6, BAP0); + + bap_read(ai, &v, sizeof(v), BAP0); + gap = le16_to_cpu(v); + if (gap) { + if (gap <= 8) { + bap_read(ai, tmpbuf, gap, BAP0); } else { - MICBuffer micbuf; - bap_read (apriv, buffer, ETH_ALEN*2, BAP0); - if (apriv->micstats.enabled) { - bap_read (apriv,(__le16*)&micbuf,sizeof(micbuf),BAP0); - if (ntohs(micbuf.typelen) > 0x05DC) - bap_setup (apriv, fid, 0x44, BAP0); - else { - if (len <= sizeof(micbuf)) - goto badmic; - - len -= sizeof(micbuf); - skb_trim (skb, len + hdrlen); - } - } - bap_read(apriv,buffer+ETH_ALEN,len,BAP0); - if (decapsulate(apriv,&micbuf,(etherHead*)buffer,len)) { -badmic: - dev_kfree_skb_irq (skb); -badrx: - OUT4500( apriv, EVACK, EV_RX); - goto exitrx; + airo_print_err(ai->dev->name, "gaplen too " + "big. Problems will follow..."); + } + } + bap_read(ai, buffer + hdrlen/2, len, BAP0); + } else { + MICBuffer micbuf; + + bap_read(ai, buffer, ETH_ALEN * 2, BAP0); + if (ai->micstats.enabled) { + bap_read(ai, (__le16 *) &micbuf, sizeof (micbuf), BAP0); + if (ntohs(micbuf.typelen) > 0x05DC) + bap_setup(ai, fid, 0x44, BAP0); + else { + if (len <= sizeof (micbuf)) { + dev_kfree_skb_irq(skb); + goto done; } + + len -= sizeof(micbuf); + skb_trim(skb, len + hdrlen); } + } + + bap_read(ai, buffer + ETH_ALEN, len, BAP0); + if (decapsulate(ai, &micbuf, (etherHead*) buffer, len)) + dev_kfree_skb_irq (skb); + else + success = 1; + } + #ifdef WIRELESS_SPY - if (apriv->spy_data.spy_number > 0) { - char *sa; - struct iw_quality wstats; - /* Prepare spy data : addr + qual */ - if (!test_bit(FLAG_802_11, &apriv->flags)) { - sa = (char*)buffer + 6; - bap_setup (apriv, fid, 8, BAP0); - bap_read (apriv, (__le16*)hdr.rssi, 2, BAP0); - } else - sa = (char*)buffer + 10; - wstats.qual = hdr.rssi[0]; - if (apriv->rssi) - wstats.level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm; - else - wstats.level = (hdr.rssi[1] + 321) / 2; - wstats.noise = apriv->wstats.qual.noise; - wstats.updated = IW_QUAL_LEVEL_UPDATED - | IW_QUAL_QUAL_UPDATED - | IW_QUAL_DBM; - /* Update spy records */ - wireless_spy_update(dev, sa, &wstats); - } + if (success && (ai->spy_data.spy_number > 0)) { + char *sa; + struct iw_quality wstats; + + /* Prepare spy data : addr + qual */ + if (!test_bit(FLAG_802_11, &ai->flags)) { + sa = (char *) buffer + 6; + bap_setup(ai, fid, 8, BAP0); + bap_read(ai, (__le16 *) hdr.rssi, 2, BAP0); + } else + sa = (char *) buffer + 10; + wstats.qual = hdr.rssi[0]; + if (ai->rssi) + wstats.level = 0x100 - ai->rssi[hdr.rssi[1]].rssidBm; + else + wstats.level = (hdr.rssi[1] + 321) / 2; + wstats.noise = ai->wstats.qual.noise; + wstats.updated = IW_QUAL_LEVEL_UPDATED + | IW_QUAL_QUAL_UPDATED + | IW_QUAL_DBM; + /* Update spy records */ + wireless_spy_update(ai->dev, sa, &wstats); + } #endif /* WIRELESS_SPY */ - OUT4500( apriv, EVACK, EV_RX); - if (test_bit(FLAG_802_11, &apriv->flags)) { - skb_reset_mac_header(skb); - skb->pkt_type = PACKET_OTHERHOST; - skb->dev = apriv->wifidev; - skb->protocol = htons(ETH_P_802_2); - } else - skb->protocol = eth_type_trans(skb,dev); - skb->ip_summed = CHECKSUM_NONE; +done: + OUT4500(ai, EVACK, EV_RX); + + if (success) { + if (test_bit(FLAG_802_11, &ai->flags)) { + skb_reset_mac_header(skb); + skb->pkt_type = PACKET_OTHERHOST; + skb->dev = ai->wifidev; + skb->protocol = htons(ETH_P_802_2); + } else + skb->protocol = eth_type_trans(skb, ai->dev); + skb->ip_summed = CHECKSUM_NONE; + + netif_rx(skb); + } +} + +static void airo_handle_tx(struct airo_info *ai, u16 status) +{ + int i, len = 0, index = -1; + u16 fid; - netif_rx( skb ); + if (test_bit(FLAG_MPI, &ai->flags)) { + unsigned long flags; + + if (status & EV_TXEXC) + get_tx_error(ai, -1); + + spin_lock_irqsave(&ai->aux_lock, flags); + if (!skb_queue_empty(&ai->txq)) { + spin_unlock_irqrestore(&ai->aux_lock,flags); + mpi_send_packet(ai->dev); + } else { + clear_bit(FLAG_PENDING_XMIT, &ai->flags); + spin_unlock_irqrestore(&ai->aux_lock,flags); + netif_wake_queue(ai->dev); } -exitrx: + OUT4500(ai, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC)); + return; + } - /* Check to see if a packet has been transmitted */ - if ( status & ( EV_TX|EV_TXCPY|EV_TXEXC ) ) { - int i; - int len = 0; - int index = -1; - - if (test_bit(FLAG_MPI,&apriv->flags)) { - unsigned long flags; - - if (status & EV_TXEXC) - get_tx_error(apriv, -1); - spin_lock_irqsave(&apriv->aux_lock, flags); - if (!skb_queue_empty(&apriv->txq)) { - spin_unlock_irqrestore(&apriv->aux_lock,flags); - mpi_send_packet (dev); - } else { - clear_bit(FLAG_PENDING_XMIT, &apriv->flags); - spin_unlock_irqrestore(&apriv->aux_lock,flags); - netif_wake_queue (dev); - } - OUT4500( apriv, EVACK, - status & (EV_TX|EV_TXCPY|EV_TXEXC)); - goto exittx; - } + fid = IN4500(ai, TXCOMPLFID); + + for(i = 0; i < MAX_FIDS; i++) { + if ((ai->fids[i] & 0xffff) == fid) { + len = ai->fids[i] >> 16; + index = i; + } + } - fid = IN4500(apriv, TXCOMPLFID); + if (index != -1) { + if (status & EV_TXEXC) + get_tx_error(ai, index); - for( i = 0; i < MAX_FIDS; i++ ) { - if ( ( apriv->fids[i] & 0xffff ) == fid ) { - len = apriv->fids[i] >> 16; - index = i; - } - } - if (index != -1) { - if (status & EV_TXEXC) - get_tx_error(apriv, index); - OUT4500( apriv, EVACK, status & (EV_TX | EV_TXEXC)); - /* Set up to be used again */ - apriv->fids[index] &= 0xffff; - if (index < MAX_FIDS / 2) { - if (!test_bit(FLAG_PENDING_XMIT, &apriv->flags)) - netif_wake_queue(dev); - } else { - if (!test_bit(FLAG_PENDING_XMIT11, &apriv->flags)) - netif_wake_queue(apriv->wifidev); - } - } else { - OUT4500( apriv, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC)); - airo_print_err(apriv->dev->name, "Unallocated FID was " - "used to xmit" ); - } + OUT4500(ai, EVACK, status & (EV_TX | EV_TXEXC)); + + /* Set up to be used again */ + ai->fids[index] &= 0xffff; + if (index < MAX_FIDS / 2) { + if (!test_bit(FLAG_PENDING_XMIT, &ai->flags)) + netif_wake_queue(ai->dev); + } else { + if (!test_bit(FLAG_PENDING_XMIT11, &ai->flags)) + netif_wake_queue(ai->wifidev); } -exittx: - if ( status & ~STATUS_INTS & ~IGNORE_INTS ) - airo_print_warn(apriv->dev->name, "Got weird status %x", + } else { + OUT4500(ai, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC)); + airo_print_err(ai->dev->name, "Unallocated FID was used to xmit"); + } +} + +static irqreturn_t airo_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + u16 status, savedInterrupts = 0; + struct airo_info *ai = dev->ml_priv; + int handled = 0; + + if (!netif_device_present(dev)) + return IRQ_NONE; + + for (;;) { + status = IN4500(ai, EVSTAT); + if (!(status & STATUS_INTS) || (status == 0xffff)) + break; + + handled = 1; + + if (status & EV_AWAKE) { + OUT4500(ai, EVACK, EV_AWAKE); + OUT4500(ai, EVACK, EV_AWAKE); + } + + if (!savedInterrupts) { + savedInterrupts = IN4500(ai, EVINTEN); + OUT4500(ai, EVINTEN, 0); + } + + if (status & EV_MIC) { + OUT4500(ai, EVACK, EV_MIC); + airo_handle_cisco_mic(ai); + } + + if (status & EV_LINK) { + /* Link status changed */ + airo_handle_link(ai); + } + + /* Check to see if there is something to receive */ + if (status & EV_RX) + airo_handle_rx(ai); + + /* Check to see if a packet has been transmitted */ + if (status & (EV_TX | EV_TXCPY | EV_TXEXC)) + airo_handle_tx(ai, status); + + if ( status & ~STATUS_INTS & ~IGNORE_INTS ) { + airo_print_warn(ai->dev->name, "Got weird status %x", status & ~STATUS_INTS & ~IGNORE_INTS ); + } } if (savedInterrupts) - OUT4500( apriv, EVINTEN, savedInterrupts ); + OUT4500(ai, EVINTEN, savedInterrupts); - /* done.. */ return IRQ_RETVAL(handled); } @@ -3609,18 +3657,10 @@ static void mpi_receive_802_11(struct airo_info *ai) struct sk_buff *skb = NULL; u16 len, hdrlen = 0; __le16 fc; -#pragma pack(1) - struct { - __le16 status, len; - u8 rssi[2]; - u8 rate; - u8 freq; - __le16 tmp[4]; - } hdr; -#pragma pack() + struct rx_hdr hdr; u16 gap; u16 *buffer; - char *ptr = ai->rxfids[0].virtual_host_addr+4; + char *ptr = ai->rxfids[0].virtual_host_addr + 4; memcpy_fromio(&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd)); memcpy ((char *)&hdr, ptr, sizeof(hdr)); @@ -3687,6 +3727,7 @@ static void mpi_receive_802_11(struct airo_info *ai) skb->protocol = htons(ETH_P_802_2); skb->ip_summed = CHECKSUM_NONE; netif_rx( skb ); + badrx: if (rxd.valid == 0) { rxd.valid = 1; -- GitLab From f65b56d67b48eec7ffe174f223e98db58c3bf2b5 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 24 Jan 2009 09:10:42 -0500 Subject: [PATCH 0958/4982] airo: re-arrange WPA capability checks The capability register has to be read for other (upcoming) stuff, so fold the WPA test function back into _init_airo_card() and move the netdevice registration stuff above it so that the netdevice has a name by the time the card's capabilities are printed out. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 66 ++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index a192c4472e0..a08aadfa09a 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -2734,28 +2734,6 @@ static void airo_networks_initialize(struct airo_info *ai) &ai->network_free_list); } -static int airo_test_wpa_capable(struct airo_info *ai) -{ - int status; - CapabilityRid cap_rid; - - status = readCapabilityRid(ai, &cap_rid, 1); - if (status != SUCCESS) return 0; - - /* Only firmware versions 5.30.17 or better can do WPA */ - if (le16_to_cpu(cap_rid.softVer) > 0x530 - || (le16_to_cpu(cap_rid.softVer) == 0x530 - && le16_to_cpu(cap_rid.softSubVer) >= 17)) { - airo_print_info("", "WPA is supported."); - return 1; - } - - /* No WPA support */ - airo_print_info("", "WPA unsupported (only firmware versions 5.30.17" - " and greater support WPA. Detected %s)", cap_rid.prodVer); - return 0; -} - static struct net_device *_init_airo_card( unsigned short irq, int port, int is_pcmcia, struct pci_dev *pci, struct device *dmdev ) @@ -2763,6 +2741,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, struct net_device *dev; struct airo_info *ai; int i, rc; + CapabilityRid cap_rid; /* Create the network device object. */ dev = alloc_netdev(sizeof(*ai), "", ether_setup); @@ -2832,7 +2811,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, } if (probe) { - if ( setup_card( ai, dev->dev_addr, 1 ) != SUCCESS ) { + if (setup_card(ai, dev->dev_addr, 1) != SUCCESS) { airo_print_err(dev->name, "MAC could not be enabled" ); rc = -EIO; goto err_out_map; @@ -2842,28 +2821,47 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, set_bit(FLAG_FLASHING, &ai->flags); } + strcpy(dev->name, "eth%d"); + rc = register_netdev(dev); + if (rc) { + airo_print_err(dev->name, "Couldn't register_netdev"); + goto err_out_map; + } + ai->wifidev = init_wifidev(ai, dev); + if (!ai->wifidev) + goto err_out_reg; + + rc = readCapabilityRid(ai, &cap_rid, 1); + if (rc != SUCCESS) { + rc = -EIO; + goto err_out_wifi; + } + + airo_print_info(dev->name, "Firmware version %x.%x.%02x", + ((le16_to_cpu(cap_rid.softVer) >> 8) & 0xF), + (le16_to_cpu(cap_rid.softVer) & 0xFF), + le16_to_cpu(cap_rid.softSubVer)); + /* Test for WPA support */ - if (airo_test_wpa_capable(ai)) { + /* Only firmware versions 5.30.17 or better can do WPA */ + if (le16_to_cpu(cap_rid.softVer) > 0x530 + || (le16_to_cpu(cap_rid.softVer) == 0x530 + && le16_to_cpu(cap_rid.softSubVer) >= 17)) { + airo_print_info(ai->dev->name, "WPA supported."); + set_bit(FLAG_WPA_CAPABLE, &ai->flags); ai->bssListFirst = RID_WPA_BSSLISTFIRST; ai->bssListNext = RID_WPA_BSSLISTNEXT; ai->bssListRidLen = sizeof(BSSListRid); } else { + airo_print_info(ai->dev->name, "WPA unsupported with firmware " + "versions older than 5.30.17."); + ai->bssListFirst = RID_BSSLISTFIRST; ai->bssListNext = RID_BSSLISTNEXT; ai->bssListRidLen = sizeof(BSSListRid) - sizeof(BSSListRidExtra); } - strcpy(dev->name, "eth%d"); - rc = register_netdev(dev); - if (rc) { - airo_print_err(dev->name, "Couldn't register_netdev"); - goto err_out_map; - } - ai->wifidev = init_wifidev(ai, dev); - if (!ai->wifidev) - goto err_out_reg; - set_bit(FLAG_REGISTERED,&ai->flags); airo_print_info(dev->name, "MAC enabled %pM", dev->dev_addr); -- GitLab From 138c0c688262b7f4ed07cdc6d0592299c4f12998 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 24 Jan 2009 09:11:35 -0500 Subject: [PATCH 0959/4982] airo: simplify WEP index and capability checks Do the computation once at init time; don't ask the hardware every time. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 59 +++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 32 deletions(-) diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index a08aadfa09a..e4ca5f84d61 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -1233,6 +1233,9 @@ struct airo_info { #define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE char proc_name[IFNAMSIZ]; + int wep_capable; + int max_wep_idx; + /* WPA-related stuff */ unsigned int bssListFirst; unsigned int bssListNext; @@ -2836,6 +2839,9 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, rc = -EIO; goto err_out_wifi; } + /* WEP capability discovery */ + ai->wep_capable = (cap_rid.softCap & cpu_to_le16(0x02)) ? 1 : 0; + ai->max_wep_idx = (cap_rid.softCap & cpu_to_le16(0x80)) ? 3 : 0; airo_print_info(dev->name, "Firmware version %x.%x.%02x", ((le16_to_cpu(cap_rid.softVer) >> 8) & 0xF), @@ -6265,11 +6271,9 @@ static int airo_get_mode(struct net_device *dev, return 0; } -static inline int valid_index(CapabilityRid *p, int index) +static inline int valid_index(struct airo_info *ai, int index) { - if (index < 0) - return 0; - return index < (p->softCap & cpu_to_le16(0x80) ? 4 : 1); + return (index >= 0) && (index <= ai->max_wep_idx); } /*------------------------------------------------------------------*/ @@ -6282,16 +6286,12 @@ static int airo_set_encode(struct net_device *dev, char *extra) { struct airo_info *local = dev->ml_priv; - CapabilityRid cap_rid; /* Card capability info */ int perm = ( dwrq->flags & IW_ENCODE_TEMP ? 0 : 1 ); __le16 currentAuthType = local->config.authType; - /* Is WEP supported ? */ - readCapabilityRid(local, &cap_rid, 1); - /* Older firmware doesn't support this... - if(!(cap_rid.softCap & cpu_to_le16(2))) { + if (!local->wep_capable) return -EOPNOTSUPP; - } */ + readConfigRid(local, 1); /* Basic checking: do we have a key to set ? @@ -6304,13 +6304,16 @@ static int airo_set_encode(struct net_device *dev, wep_key_t key; int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; int current_index = get_wep_key(local, 0xffff); + /* Check the size of the key */ if (dwrq->length > MAX_KEY_SIZE) { return -EINVAL; } + /* Check the index (none -> use current) */ - if (!valid_index(&cap_rid, index)) + if (!valid_index(local, index)) index = current_index; + /* Set the length */ if (dwrq->length > MIN_KEY_SIZE) key.len = MAX_KEY_SIZE; @@ -6339,12 +6342,13 @@ static int airo_set_encode(struct net_device *dev, } else { /* Do we want to just set the transmit key index ? */ int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - if (valid_index(&cap_rid, index)) { + if (valid_index(local, index)) set_wep_key(local, index, NULL, 0, perm, 1); - } else + else { /* Don't complain if only change the mode */ if (!(dwrq->flags & IW_ENCODE_MODE)) return -EINVAL; + } } /* Read the flags */ if(dwrq->flags & IW_ENCODE_DISABLED) @@ -6370,14 +6374,12 @@ static int airo_get_encode(struct net_device *dev, { struct airo_info *local = dev->ml_priv; int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - CapabilityRid cap_rid; /* Card capability info */ - /* Is it supported ? */ - readCapabilityRid(local, &cap_rid, 1); - if(!(cap_rid.softCap & cpu_to_le16(2))) { + if (!local->wep_capable) return -EOPNOTSUPP; - } + readConfigRid(local, 1); + /* Check encryption mode */ switch(local->config.authType) { case AUTH_ENCRYPT: @@ -6396,7 +6398,7 @@ static int airo_get_encode(struct net_device *dev, memset(extra, 0, 16); /* Which key do we want ? -1 -> tx index */ - if (!valid_index(&cap_rid, index)) + if (!valid_index(local, index)) index = get_wep_key(local, 0xffff); dwrq->flags |= index + 1; /* Copy the key to the user buffer */ @@ -6419,24 +6421,20 @@ static int airo_set_encodeext(struct net_device *dev, struct airo_info *local = dev->ml_priv; struct iw_point *encoding = &wrqu->encoding; struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - CapabilityRid cap_rid; /* Card capability info */ int perm = ( encoding->flags & IW_ENCODE_TEMP ? 0 : 1 ); __le16 currentAuthType = local->config.authType; int idx, key_len, alg = ext->alg, set_key = 1; wep_key_t key; - /* Is WEP supported ? */ - readCapabilityRid(local, &cap_rid, 1); - /* Older firmware doesn't support this... - if(!(cap_rid.softCap & cpu_to_le16(2))) { + if (!local->wep_capable) return -EOPNOTSUPP; - } */ + readConfigRid(local, 1); /* Determine and validate the key index */ idx = encoding->flags & IW_ENCODE_INDEX; if (idx) { - if (!valid_index(&cap_rid, idx - 1)) + if (!valid_index(local, idx - 1)) return -EINVAL; idx--; } else @@ -6505,14 +6503,11 @@ static int airo_get_encodeext(struct net_device *dev, struct airo_info *local = dev->ml_priv; struct iw_point *encoding = &wrqu->encoding; struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - CapabilityRid cap_rid; /* Card capability info */ int idx, max_key_len; - /* Is it supported ? */ - readCapabilityRid(local, &cap_rid, 1); - if(!(cap_rid.softCap & cpu_to_le16(2))) { + if (!local->wep_capable) return -EOPNOTSUPP; - } + readConfigRid(local, 1); max_key_len = encoding->length - sizeof(*ext); @@ -6521,7 +6516,7 @@ static int airo_get_encodeext(struct net_device *dev, idx = encoding->flags & IW_ENCODE_INDEX; if (idx) { - if (!valid_index(&cap_rid, idx - 1)) + if (!valid_index(local, idx - 1)) return -EINVAL; idx--; } else -- GitLab From c0380693520b1a1e4f756799a0edc379378b462a Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 24 Jan 2009 09:12:15 -0500 Subject: [PATCH 0960/4982] airo: clean up WEP key operations get_wep_key() and set_wep_key() combind both get/set of the actual WEP key and get/set of the transmit index into the same functions. Split those out so it's clearer what is going one where. Add error checking to WEP key hardware operations too. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 202 ++++++++++++++++++++++++++---------- 1 file changed, 146 insertions(+), 56 deletions(-) diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index e4ca5f84d61..2306b1a3325 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -5172,55 +5172,98 @@ static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data, return rc; } -/* Returns the length of the key at the index. If index == 0xffff - * the index of the transmit key is returned. If the key doesn't exist, - * -1 will be returned. +/* Returns the WEP key at the specified index, or -1 if that key does + * not exist. The buffer is assumed to be at least 16 bytes in length. */ -static int get_wep_key(struct airo_info *ai, u16 index) { +static int get_wep_key(struct airo_info *ai, u16 index, char *buf, u16 buflen) +{ WepKeyRid wkr; int rc; __le16 lastindex; rc = readWepKeyRid(ai, &wkr, 1, 1); - if (rc == SUCCESS) do { + if (rc != SUCCESS) + return -1; + do { lastindex = wkr.kindex; - if (wkr.kindex == cpu_to_le16(index)) { - if (index == 0xffff) { - return wkr.mac[0]; - } - return le16_to_cpu(wkr.klen); + if (le16_to_cpu(wkr.kindex) == index) { + int klen = min_t(int, buflen, le16_to_cpu(wkr.klen)); + memcpy(buf, wkr.key, klen); + return klen; } - readWepKeyRid(ai, &wkr, 0, 1); + rc = readWepKeyRid(ai, &wkr, 0, 1); + if (rc != SUCCESS) + return -1; + } while (lastindex != wkr.kindex); + return -1; +} + +static int get_wep_tx_idx(struct airo_info *ai) +{ + WepKeyRid wkr; + int rc; + __le16 lastindex; + + rc = readWepKeyRid(ai, &wkr, 1, 1); + if (rc != SUCCESS) + return -1; + do { + lastindex = wkr.kindex; + if (wkr.kindex == cpu_to_le16(0xffff)) + return wkr.mac[0]; + rc = readWepKeyRid(ai, &wkr, 0, 1); + if (rc != SUCCESS) + return -1; } while (lastindex != wkr.kindex); return -1; } -static int set_wep_key(struct airo_info *ai, u16 index, - const char *key, u16 keylen, int perm, int lock ) +static int set_wep_key(struct airo_info *ai, u16 index, const char *key, + u16 keylen, int perm, int lock) { static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 }; WepKeyRid wkr; + int rc; - memset(&wkr, 0, sizeof(wkr)); if (keylen == 0) { -// We are selecting which key to use - wkr.len = cpu_to_le16(sizeof(wkr)); - wkr.kindex = cpu_to_le16(0xffff); - wkr.mac[0] = (char)index; - if (perm) ai->defindex = (char)index; - } else { -// We are actually setting the key - wkr.len = cpu_to_le16(sizeof(wkr)); - wkr.kindex = cpu_to_le16(index); - wkr.klen = cpu_to_le16(keylen); - memcpy( wkr.key, key, keylen ); - memcpy( wkr.mac, macaddr, ETH_ALEN ); + airo_print_err(ai->dev->name, "%s: key length to set was zero", + __func__); + return -1; } + memset(&wkr, 0, sizeof(wkr)); + wkr.len = cpu_to_le16(sizeof(wkr)); + wkr.kindex = cpu_to_le16(index); + wkr.klen = cpu_to_le16(keylen); + memcpy(wkr.key, key, keylen); + memcpy(wkr.mac, macaddr, ETH_ALEN); + if (perm) disable_MAC(ai, lock); - writeWepKeyRid(ai, &wkr, perm, lock); + rc = writeWepKeyRid(ai, &wkr, perm, lock); if (perm) enable_MAC(ai, lock); - return 0; + return rc; +} + +static int set_wep_tx_idx(struct airo_info *ai, u16 index, int perm, int lock) +{ + WepKeyRid wkr; + int rc; + + memset(&wkr, 0, sizeof(wkr)); + wkr.len = cpu_to_le16(sizeof(wkr)); + wkr.kindex = cpu_to_le16(0xffff); + wkr.mac[0] = (char)index; + + if (perm) { + ai->defindex = (char)index; + disable_MAC(ai, lock); + } + + rc = writeWepKeyRid(ai, &wkr, perm, lock); + + if (perm) + enable_MAC(ai, lock); + return rc; } static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { @@ -5228,7 +5271,7 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; struct airo_info *ai = dev->ml_priv; - int i; + int i, rc; char key[16]; u16 index = 0; int j = 0; @@ -5242,7 +5285,12 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { (data->wbuffer[1] == ' ' || data->wbuffer[1] == '\n')) { index = data->wbuffer[0] - '0'; if (data->wbuffer[1] == '\n') { - set_wep_key(ai, index, NULL, 0, 1, 1); + rc = set_wep_tx_idx(ai, index, 1, 1); + if (rc < 0) { + airo_print_err(ai->dev->name, "failed to set " + "WEP transmit index to %d: %d.", + index, rc); + } return; } j = 2; @@ -5261,7 +5309,12 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { break; } } - set_wep_key(ai, index, key, i/3, 1, 1); + + rc = set_wep_key(ai, index, key, i/3, 1, 1); + if (rc < 0) { + airo_print_err(ai->dev->name, "failed to set WEP key at index " + "%d: %d.", index, rc); + } } static int proc_wepkey_open( struct inode *inode, struct file *file ) @@ -5492,13 +5545,13 @@ static void timer_func( struct net_device *dev ) { break; case AUTH_SHAREDKEY: if (apriv->keyindex < auto_wep) { - set_wep_key(apriv, apriv->keyindex, NULL, 0, 0, 0); + set_wep_tx_idx(apriv, apriv->keyindex, 0, 0); apriv->config.authType = AUTH_SHAREDKEY; apriv->keyindex++; } else { /* Drop to ENCRYPT */ apriv->keyindex = 0; - set_wep_key(apriv, apriv->defindex, NULL, 0, 0, 0); + set_wep_tx_idx(apriv, apriv->defindex, 0, 0); apriv->config.authType = AUTH_ENCRYPT; } break; @@ -6286,8 +6339,9 @@ static int airo_set_encode(struct net_device *dev, char *extra) { struct airo_info *local = dev->ml_priv; - int perm = ( dwrq->flags & IW_ENCODE_TEMP ? 0 : 1 ); + int perm = (dwrq->flags & IW_ENCODE_TEMP ? 0 : 1); __le16 currentAuthType = local->config.authType; + int rc = 0; if (!local->wep_capable) return -EOPNOTSUPP; @@ -6303,13 +6357,17 @@ static int airo_set_encode(struct net_device *dev, if (dwrq->length > 0) { wep_key_t key; int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - int current_index = get_wep_key(local, 0xffff); + int current_index; /* Check the size of the key */ if (dwrq->length > MAX_KEY_SIZE) { return -EINVAL; } + current_index = get_wep_tx_idx(local); + if (current_index < 0) + current_index = 0; + /* Check the index (none -> use current) */ if (!valid_index(local, index)) index = current_index; @@ -6330,7 +6388,13 @@ static int airo_set_encode(struct net_device *dev, /* Copy the key in the driver */ memcpy(key.key, extra, dwrq->length); /* Send the key to the card */ - set_wep_key(local, index, key.key, key.len, perm, 1); + rc = set_wep_key(local, index, key.key, key.len, perm, 1); + if (rc < 0) { + airo_print_err(local->dev->name, "failed to set" + " WEP key at index %d: %d.", + index, rc); + return rc; + } } /* WE specify that if a valid key is set, encryption * should be enabled (user may turn it off later) @@ -6342,9 +6406,15 @@ static int airo_set_encode(struct net_device *dev, } else { /* Do we want to just set the transmit key index ? */ int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - if (valid_index(local, index)) - set_wep_key(local, index, NULL, 0, perm, 1); - else { + if (valid_index(local, index)) { + rc = set_wep_tx_idx(local, index, perm, 1); + if (rc < 0) { + airo_print_err(local->dev->name, "failed to set" + " WEP transmit index to %d: %d.", + index, rc); + return rc; + } + } else { /* Don't complain if only change the mode */ if (!(dwrq->flags & IW_ENCODE_MODE)) return -EINVAL; @@ -6374,6 +6444,7 @@ static int airo_get_encode(struct net_device *dev, { struct airo_info *local = dev->ml_priv; int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; + u8 buf[16]; if (!local->wep_capable) return -EOPNOTSUPP; @@ -6398,14 +6469,17 @@ static int airo_get_encode(struct net_device *dev, memset(extra, 0, 16); /* Which key do we want ? -1 -> tx index */ - if (!valid_index(local, index)) - index = get_wep_key(local, 0xffff); + if (!valid_index(local, index)) { + index = get_wep_tx_idx(local); + if (index < 0) + index = 0; + } dwrq->flags |= index + 1; + /* Copy the key to the user buffer */ - dwrq->length = get_wep_key(local, index); - if (dwrq->length > 16) { - dwrq->length=0; - } + dwrq->length = get_wep_key(local, index, &buf[0], sizeof(buf)); + memcpy(extra, buf, dwrq->length); + return 0; } @@ -6423,7 +6497,7 @@ static int airo_set_encodeext(struct net_device *dev, struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; int perm = ( encoding->flags & IW_ENCODE_TEMP ? 0 : 1 ); __le16 currentAuthType = local->config.authType; - int idx, key_len, alg = ext->alg, set_key = 1; + int idx, key_len, alg = ext->alg, set_key = 1, rc; wep_key_t key; if (!local->wep_capable) @@ -6437,8 +6511,11 @@ static int airo_set_encodeext(struct net_device *dev, if (!valid_index(local, idx - 1)) return -EINVAL; idx--; - } else - idx = get_wep_key(local, 0xffff); + } else { + idx = get_wep_tx_idx(local); + if (idx < 0) + idx = 0; + } if (encoding->flags & IW_ENCODE_DISABLED) alg = IW_ENCODE_ALG_NONE; @@ -6447,7 +6524,13 @@ static int airo_set_encodeext(struct net_device *dev, /* Only set transmit key index here, actual * key is set below if needed. */ - set_wep_key(local, idx, NULL, 0, perm, 1); + rc = set_wep_tx_idx(local, idx, perm, 1); + if (rc < 0) { + airo_print_err(local->dev->name, "failed to set " + "WEP transmit index to %d: %d.", + idx, rc); + return rc; + } set_key = ext->key_len > 0 ? 1 : 0; } @@ -6473,7 +6556,12 @@ static int airo_set_encodeext(struct net_device *dev, return -EINVAL; } /* Send the key to the card */ - set_wep_key(local, idx, key.key, key.len, perm, 1); + rc = set_wep_key(local, idx, key.key, key.len, perm, 1); + if (rc < 0) { + airo_print_err(local->dev->name, "failed to set WEP key" + " at index %d: %d.", idx, rc); + return rc; + } } /* Read the flags */ @@ -6504,6 +6592,7 @@ static int airo_get_encodeext(struct net_device *dev, struct iw_point *encoding = &wrqu->encoding; struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; int idx, max_key_len; + u8 buf[16]; if (!local->wep_capable) return -EOPNOTSUPP; @@ -6519,8 +6608,11 @@ static int airo_get_encodeext(struct net_device *dev, if (!valid_index(local, idx - 1)) return -EINVAL; idx--; - } else - idx = get_wep_key(local, 0xffff); + } else { + idx = get_wep_tx_idx(local); + if (idx < 0) + idx = 0; + } encoding->flags = idx + 1; memset(ext, 0, sizeof(*ext)); @@ -6543,10 +6635,8 @@ static int airo_get_encodeext(struct net_device *dev, memset(extra, 0, 16); /* Copy the key to the user buffer */ - ext->key_len = get_wep_key(local, idx); - if (ext->key_len > 16) { - ext->key_len=0; - } + ext->key_len = get_wep_key(local, idx, &buf[0], sizeof(buf)); + memcpy(extra, buf, ext->key_len); return 0; } -- GitLab From dfe670121a2719be6ead12eb5306d4d2714c09cb Mon Sep 17 00:00:00 2001 From: Alina Friedrichsen Date: Sat, 24 Jan 2009 01:19:04 +0100 Subject: [PATCH 0961/4982] mac80211: Fixed BSSID handling revisited This patch cleanup the fixed BSSID handling, that ieee80211_sta_set_bssid() works like ieee80211_sta_set_ssid(). So that the BSSID is only a second selection criterion besides the SSID. This allows us to create new IBSS networks with fixed BSSIDs, which was broken before. In the second version of this patch the handling of the stupid merges to the same BSSID is moved out to get reworked into an other patch. And this version hopefully solves the problems with some low-level drivers and re-adds the config BSSID warning to help debugging the low-level drivers. Much thanks to all who have helped testing! :) Signed-off-by: Alina Friedrichsen Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 72 +++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 39 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ec400479c5f..9d51e278c1e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1615,6 +1615,7 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, ieee80211_sta_def_wmm_params(sdata, bss); + ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET; ifsta->state = IEEE80211_STA_MLME_IBSS_JOINED; mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); @@ -2178,19 +2179,18 @@ static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata, int i; int ret; -#if 0 - /* Easier testing, use fixed BSSID. */ - memset(bssid, 0xfe, ETH_ALEN); -#else - /* Generate random, not broadcast, locally administered BSSID. Mix in - * own MAC address to make sure that devices that do not have proper - * random number generator get different BSSID. */ - get_random_bytes(bssid, ETH_ALEN); - for (i = 0; i < ETH_ALEN; i++) - bssid[i] ^= sdata->dev->dev_addr[i]; - bssid[0] &= ~0x01; - bssid[0] |= 0x02; -#endif + if (sdata->u.sta.flags & IEEE80211_STA_BSSID_SET) { + memcpy(bssid, ifsta->bssid, ETH_ALEN); + } else { + /* Generate random, not broadcast, locally administered BSSID. Mix in + * own MAC address to make sure that devices that do not have proper + * random number generator get different BSSID. */ + get_random_bytes(bssid, ETH_ALEN); + for (i = 0; i < ETH_ALEN; i++) + bssid[i] ^= sdata->dev->dev_addr[i]; + bssid[0] &= ~0x01; + bssid[0] |= 0x02; + } printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n", sdata->dev->name, bssid); @@ -2251,6 +2251,9 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, memcmp(ifsta->ssid, bss->ssid, bss->ssid_len) != 0 || !(bss->capability & WLAN_CAPABILITY_IBSS)) continue; + if ((ifsta->flags & IEEE80211_STA_BSSID_SET) && + memcmp(ifsta->bssid, bss->bssid, ETH_ALEN) != 0) + continue; #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG " bssid=%pM found\n", bss->bssid); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ @@ -2267,7 +2270,9 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, "%pM\n", bssid, ifsta->bssid); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ - if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { + if (found && + ((!(ifsta->flags & IEEE80211_STA_PREV_BSSID_SET)) || + memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0)) { int ret; int search_freq; @@ -2605,16 +2610,16 @@ int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size memset(ifsta->ssid, 0, sizeof(ifsta->ssid)); memcpy(ifsta->ssid, ssid, len); ifsta->ssid_len = len; - ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET; } + ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET; + if (len) ifsta->flags |= IEEE80211_STA_SSID_SET; else ifsta->flags &= ~IEEE80211_STA_SSID_SET; - if (sdata->vif.type == NL80211_IFTYPE_ADHOC && - !(ifsta->flags & IEEE80211_STA_BSSID_SET)) { + if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { ifsta->ibss_join_req = jiffies; ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH; return ieee80211_sta_find_ibss(sdata, ifsta); @@ -2634,36 +2639,25 @@ int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid) { struct ieee80211_if_sta *ifsta; - int res; - bool valid; ifsta = &sdata->u.sta; - valid = is_valid_ether_addr(bssid); - if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { - if(valid) - memcpy(ifsta->bssid, bssid, ETH_ALEN); - else - memset(ifsta->bssid, 0, ETH_ALEN); - res = 0; - /* - * Hack! See also ieee80211_sta_set_ssid. - */ - if (netif_running(sdata->dev)) - res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); - if (res) { + if (is_valid_ether_addr(bssid)) { + memcpy(ifsta->bssid, bssid, ETH_ALEN); + ifsta->flags |= IEEE80211_STA_BSSID_SET; + } else { + memset(ifsta->bssid, 0, ETH_ALEN); + ifsta->flags &= ~IEEE80211_STA_BSSID_SET; + } + + if (netif_running(sdata->dev)) { + if (ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID)) { printk(KERN_DEBUG "%s: Failed to config new BSSID to " "the low-level driver\n", sdata->dev->name); - return res; } } - if (valid) - ifsta->flags |= IEEE80211_STA_BSSID_SET; - else - ifsta->flags &= ~IEEE80211_STA_BSSID_SET; - - return 0; + return ieee80211_sta_set_ssid(sdata, ifsta->ssid, ifsta->ssid_len); } int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len) -- GitLab From 30d3ef41b4395d9bee5f481395eef2d3b8b6ee50 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Fri, 23 Jan 2009 23:09:35 -0500 Subject: [PATCH 0962/4982] mac80211: change workqueue back to non-freezeable "mac80211: make workqueue freezable" made the mac80211 workqueue freezeable to prevent us from doing any work after the driver went away. This was fine before mac80211 had any suspend support. However, now we want to flush this workqueue in suspend(). Because the thread for a freezeable workqueue is stopped before the device class suspend() is called, flush_workqueue() will hang in the suspend-to-disk case. Converting it back to a non-freezeable queue will keep suspend from hanging. Moreover, since we flush the workqueue under RTNL and userspace is stopped, there won't be any new work in the workqueue until after resume. Thus we still don't have to worry about pinging the AP without hardware. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- net/mac80211/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 8d5c19e4a1b..210dfe3cf6c 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -858,7 +858,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) mdev->set_multicast_list = ieee80211_master_set_multicast_list; local->hw.workqueue = - create_freezeable_workqueue(wiphy_name(local->hw.wiphy)); + create_singlethread_workqueue(wiphy_name(local->hw.wiphy)); if (!local->hw.workqueue) { result = -ENOMEM; goto fail_workqueue; -- GitLab From e874e6585539f6706b8e5f96125c9fca89cce716 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sat, 24 Jan 2009 13:21:14 -0500 Subject: [PATCH 0963/4982] mac80211: flush workqueue a second time in suspend() Drivers can theoretically queue more work in one of their callbacks from mac80211 suspend, so let's flush it once more to be on the safe side, just before calling ->stop(). Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- net/mac80211/pm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 6d17ed7fd49..44525f51707 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -44,6 +44,9 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) } } + /* flush again, in case driver queued work */ + flush_workqueue(local->hw.workqueue); + /* stop hardware */ if (local->open_count) { ieee80211_led_radio(local, false); -- GitLab From dff8ccd9f5ff76b7449bf833f4646f70036b2256 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 24 Jan 2009 22:36:57 +0100 Subject: [PATCH 0964/4982] b43: Fix phy_g.c compiler warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix compile warning for non-debug builds: drivers/net/wireless/b43/phy_g.c: In function ‘b43_gphy_op_recalc_txpower’: drivers/net/wireless/b43/phy_g.c:3195: warning: unused variable ‘dbm’ Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_g.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c index caac4a45f0b..88bb303ae9d 100644 --- a/drivers/net/wireless/b43/phy_g.c +++ b/drivers/net/wireless/b43/phy_g.c @@ -3191,6 +3191,7 @@ static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev, * Baseband attennuation. Subtract it. */ bbatt_delta -= 4 * rfatt_delta; +#if B43_DEBUG if (b43_debug(dev, B43_DBG_XMITPOWER)) { int dbm = pwr_adjust < 0 ? -pwr_adjust : pwr_adjust; b43dbg(dev->wl, @@ -3199,6 +3200,8 @@ static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev, (pwr_adjust < 0 ? "-" : ""), Q52_ARG(dbm), bbatt_delta, rfatt_delta); } +#endif /* DEBUG */ + /* So do we finally need to adjust something in hardware? */ if ((rfatt_delta == 0) && (bbatt_delta == 0)) goto no_adjustment_needed; -- GitLab From 99590ffefc803caaf6ba923da092cde739269c06 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 24 Jan 2009 09:12:58 -0500 Subject: [PATCH 0965/4982] airo: use __attribute__ ((packed)) not #pragma Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 90 ++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 41 deletions(-) diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 2306b1a3325..49872db8951 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -496,39 +496,41 @@ typedef struct { * so all rid access should use the read/writeXXXRid routines. */ -/* This is redundant for x86 archs, but it seems necessary for ARM */ -#pragma pack(1) - /* This structure came from an email sent to me from an engineer at aironet for inclusion into this driver */ -typedef struct { +typedef struct WepKeyRid WepKeyRid; +struct WepKeyRid { __le16 len; __le16 kindex; u8 mac[ETH_ALEN]; __le16 klen; u8 key[16]; -} WepKeyRid; +} __attribute__ ((packed)); /* These structures are from the Aironet's PC4500 Developers Manual */ -typedef struct { +typedef struct Ssid Ssid; +struct Ssid { __le16 len; u8 ssid[32]; -} Ssid; +} __attribute__ ((packed)); -typedef struct { +typedef struct SsidRid SsidRid; +struct SsidRid { __le16 len; Ssid ssids[3]; -} SsidRid; +} __attribute__ ((packed)); -typedef struct { +typedef struct ModulationRid ModulationRid; +struct ModulationRid { __le16 len; __le16 modulation; #define MOD_DEFAULT cpu_to_le16(0) #define MOD_CCK cpu_to_le16(1) #define MOD_MOK cpu_to_le16(2) -} ModulationRid; +} __attribute__ ((packed)); -typedef struct { +typedef struct ConfigRid ConfigRid; +struct ConfigRid { __le16 len; /* sizeof(ConfigRid) */ __le16 opmode; /* operating mode */ #define MODE_STA_IBSS cpu_to_le16(0) @@ -649,9 +651,10 @@ typedef struct { #define MAGIC_STAY_IN_CAM (1<<10) u8 magicControl; __le16 autoWake; -} ConfigRid; +} __attribute__ ((packed)); -typedef struct { +typedef struct StatusRid StatusRid; +struct StatusRid { __le16 len; u8 mac[ETH_ALEN]; __le16 mode; @@ -707,21 +710,23 @@ typedef struct { #define STAT_LEAPFAILED 91 #define STAT_LEAPTIMEDOUT 92 #define STAT_LEAPCOMPLETE 93 -} StatusRid; +} __attribute__ ((packed)); -typedef struct { +typedef struct StatsRid StatsRid; +struct StatsRid { __le16 len; __le16 spacer; __le32 vals[100]; -} StatsRid; - +} __attribute__ ((packed)); -typedef struct { +typedef struct APListRid APListRid; +struct APListRid { __le16 len; u8 ap[4][ETH_ALEN]; -} APListRid; +} __attribute__ ((packed)); -typedef struct { +typedef struct CapabilityRid CapabilityRid; +struct CapabilityRid { __le16 len; char oui[3]; char zero; @@ -748,17 +753,18 @@ typedef struct { __le16 bootBlockVer; __le16 requiredHard; __le16 extSoftCap; -} CapabilityRid; - +} __attribute__ ((packed)); /* Only present on firmware >= 5.30.17 */ -typedef struct { +typedef struct BSSListRidExtra BSSListRidExtra; +struct BSSListRidExtra { __le16 unknown[4]; u8 fixed[12]; /* WLAN management frame */ u8 iep[624]; -} BSSListRidExtra; +} __attribute__ ((packed)); -typedef struct { +typedef struct BSSListRid BSSListRid; +struct BSSListRid { __le16 len; __le16 index; /* First is 0 and 0xffff means end of list */ #define RADIO_FH 1 /* Frequency hopping radio type */ @@ -789,33 +795,37 @@ typedef struct { /* Only present on firmware >= 5.30.17 */ BSSListRidExtra extra; -} BSSListRid; +} __attribute__ ((packed)); typedef struct { BSSListRid bss; struct list_head list; } BSSListElement; -typedef struct { +typedef struct tdsRssiEntry tdsRssiEntry; +struct tdsRssiEntry { u8 rssipct; u8 rssidBm; -} tdsRssiEntry; +} __attribute__ ((packed)); -typedef struct { +typedef struct tdsRssiRid tdsRssiRid; +struct tdsRssiRid { u16 len; tdsRssiEntry x[256]; -} tdsRssiRid; +} __attribute__ ((packed)); -typedef struct { - u16 len; - u16 state; - u16 multicastValid; +typedef struct MICRid MICRid; +struct MICRid { + __le16 len; + __le16 state; + __le16 multicastValid; u8 multicast[16]; - u16 unicastValid; + __le16 unicastValid; u8 unicast[16]; -} MICRid; +} __attribute__ ((packed)); -typedef struct { +typedef struct MICBuffer MICBuffer; +struct MICBuffer { __be16 typelen; union { @@ -830,15 +840,13 @@ typedef struct { } u; __be32 mic; __be32 seq; -} MICBuffer; +} __attribute__ ((packed)); typedef struct { u8 da[ETH_ALEN]; u8 sa[ETH_ALEN]; } etherHead; -#pragma pack() - #define TXCTL_TXOK (1<<1) /* report if tx is ok */ #define TXCTL_TXEX (1<<2) /* report if tx fails */ #define TXCTL_802_3 (0<<3) /* 802.3 packet */ -- GitLab From 018697d178717d63f668b9e5f3b473f4e37f6304 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 24 Jan 2009 09:13:32 -0500 Subject: [PATCH 0966/4982] airo: clean up and clarify micinit() Fix some endian issues too. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 82 ++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 49872db8951..c047580e52d 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -1302,6 +1302,29 @@ static void emmh32_update(emmh32_context *context, u8 *pOctets, int len); static void emmh32_final(emmh32_context *context, u8 digest[4]); static int flashpchar(struct airo_info *ai,int byte,int dwelltime); +static void age_mic_context(miccntx *cur, miccntx *old, u8 *key, int key_len, + struct crypto_cipher *tfm) +{ + /* If the current MIC context is valid and its key is the same as + * the MIC register, there's nothing to do. + */ + if (cur->valid && (memcmp(cur->key, key, key_len) == 0)) + return; + + /* Age current mic Context */ + memcpy(old, cur, sizeof(*cur)); + + /* Initialize new context */ + memcpy(cur->key, key, key_len); + cur->window = 33; /* Window always points to the middle */ + cur->rx = 0; /* Rx Sequence numbers */ + cur->tx = 0; /* Tx sequence numbers */ + cur->valid = 1; /* Key is now valid */ + + /* Give key to mic seed */ + emmh32_setseed(&cur->seed, key, key_len, tfm); +} + /* micinit - Initialize mic seed */ static void micinit(struct airo_info *ai) @@ -1312,49 +1335,26 @@ static void micinit(struct airo_info *ai) PC4500_readrid(ai, RID_MIC, &mic_rid, sizeof(mic_rid), 0); up(&ai->sem); - ai->micstats.enabled = (mic_rid.state & 0x00FF) ? 1 : 0; - - if (ai->micstats.enabled) { - /* Key must be valid and different */ - if (mic_rid.multicastValid && (!ai->mod[0].mCtx.valid || - (memcmp (ai->mod[0].mCtx.key, mic_rid.multicast, - sizeof(ai->mod[0].mCtx.key)) != 0))) { - /* Age current mic Context */ - memcpy(&ai->mod[1].mCtx,&ai->mod[0].mCtx,sizeof(miccntx)); - /* Initialize new context */ - memcpy(&ai->mod[0].mCtx.key,mic_rid.multicast,sizeof(mic_rid.multicast)); - ai->mod[0].mCtx.window = 33; //Window always points to the middle - ai->mod[0].mCtx.rx = 0; //Rx Sequence numbers - ai->mod[0].mCtx.tx = 0; //Tx sequence numbers - ai->mod[0].mCtx.valid = 1; //Key is now valid - - /* Give key to mic seed */ - emmh32_setseed(&ai->mod[0].mCtx.seed,mic_rid.multicast,sizeof(mic_rid.multicast), ai->tfm); - } - - /* Key must be valid and different */ - if (mic_rid.unicastValid && (!ai->mod[0].uCtx.valid || - (memcmp(ai->mod[0].uCtx.key, mic_rid.unicast, - sizeof(ai->mod[0].uCtx.key)) != 0))) { - /* Age current mic Context */ - memcpy(&ai->mod[1].uCtx,&ai->mod[0].uCtx,sizeof(miccntx)); - /* Initialize new context */ - memcpy(&ai->mod[0].uCtx.key,mic_rid.unicast,sizeof(mic_rid.unicast)); - - ai->mod[0].uCtx.window = 33; //Window always points to the middle - ai->mod[0].uCtx.rx = 0; //Rx Sequence numbers - ai->mod[0].uCtx.tx = 0; //Tx sequence numbers - ai->mod[0].uCtx.valid = 1; //Key is now valid - - //Give key to mic seed - emmh32_setseed(&ai->mod[0].uCtx.seed, mic_rid.unicast, sizeof(mic_rid.unicast), ai->tfm); - } - } else { - /* So next time we have a valid key and mic is enabled, we will update - * the sequence number if the key is the same as before. - */ + ai->micstats.enabled = (le16_to_cpu(mic_rid.state) & 0x00FF) ? 1 : 0; + if (!ai->micstats.enabled) { + /* So next time we have a valid key and mic is enabled, we will + * update the sequence number if the key is the same as before. + */ ai->mod[0].uCtx.valid = 0; ai->mod[0].mCtx.valid = 0; + return; + } + + if (mic_rid.multicastValid) { + age_mic_context(&ai->mod[0].mCtx, &ai->mod[1].mCtx, + mic_rid.multicast, sizeof(mic_rid.multicast), + ai->tfm); + } + + if (mic_rid.unicastValid) { + age_mic_context(&ai->mod[0].uCtx, &ai->mod[1].uCtx, + mic_rid.unicast, sizeof(mic_rid.unicast), + ai->tfm); } } -- GitLab From 506d03f97d10e54fd27c58c872a98242326d6419 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 24 Jan 2009 09:13:58 -0500 Subject: [PATCH 0967/4982] airo: remove useless #defines Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index c047580e52d..acda45838e9 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -1094,12 +1094,6 @@ typedef struct wep_key_t { u8 key[16]; /* 40-bit and 104-bit keys */ } wep_key_t; -/* Backward compatibility */ -#ifndef IW_ENCODE_NOKEY -#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ -#define IW_ENCODE_MODE (IW_ENCODE_DISABLED | IW_ENCODE_RESTRICTED | IW_ENCODE_OPEN) -#endif /* IW_ENCODE_NOKEY */ - /* List of Wireless Handlers (new API) */ static const struct iw_handler_def airo_handler_def; -- GitLab From c771c9d8da1e8292ef8bf7fd4ce135dacc650130 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 23 Jan 2009 22:54:03 +0100 Subject: [PATCH 0968/4982] mac80211: add interface list lock Using only the RTNL has a number of problems, most notably that ieee80211_iterate_active_interfaces() and other interface list traversals cannot be done from the internal workqueue because it needs to be flushed under the RTNL. This patch introduces a new mutex that protects the interface list against modifications. A more detailed explanation is part of the code change. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 5 ++--- net/mac80211/ieee80211_i.h | 2 ++ net/mac80211/iface.c | 31 +++++++++++++++++++++++++++++++ net/mac80211/main.c | 3 +++ net/mac80211/util.c | 4 ++-- 5 files changed, 40 insertions(+), 5 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index c1e8261e899..8e65adf0a64 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -928,9 +928,8 @@ enum ieee80211_hw_flags { * @workqueue: single threaded workqueue available for driver use, * allocated by mac80211 on registration and flushed when an * interface is removed. - * NOTICE: All work performed on this workqueue should NEVER - * acquire the RTNL lock (i.e. Don't use the function - * ieee80211_iterate_active_interfaces()) + * NOTICE: All work performed on this workqueue must not + * acquire the RTNL lock. * * @priv: pointer to private area that was allocated for driver use * along with this structure. diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 927cbde8c19..eaf3603862b 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -643,7 +643,9 @@ struct ieee80211_local { struct crypto_blkcipher *wep_rx_tfm; u32 wep_iv; + /* see iface.c */ struct list_head interfaces; + struct mutex iflist_mtx; /* * Key lock, protects sdata's key_list and sta_info's diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 8dc2c2188d9..00562a8b99c 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -21,6 +21,23 @@ #include "mesh.h" #include "led.h" +/** + * DOC: Interface list locking + * + * The interface list in each struct ieee80211_local is protected + * three-fold: + * + * (1) modifications may only be done under the RTNL + * (2) modifications and readers are protected against each other by + * the iflist_mtx. + * (3) modifications are done in an RCU manner so atomic readers + * can traverse the list in RCU-safe blocks. + * + * As a consequence, reads (traversals) of the list can be protected + * by either the RTNL, the iflist_mtx or RCU. + */ + + static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) { int meshhdrlen; @@ -800,7 +817,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, params->mesh_id_len, params->mesh_id); + mutex_lock(&local->iflist_mtx); list_add_tail_rcu(&sdata->list, &local->interfaces); + mutex_unlock(&local->iflist_mtx); if (new_dev) *new_dev = ndev; @@ -816,7 +835,10 @@ void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata) { ASSERT_RTNL(); + mutex_lock(&sdata->local->iflist_mtx); list_del_rcu(&sdata->list); + mutex_unlock(&sdata->local->iflist_mtx); + synchronize_rcu(); unregister_netdevice(sdata->dev); } @@ -832,7 +854,16 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) ASSERT_RTNL(); list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { + /* + * we cannot hold the iflist_mtx across unregister_netdevice, + * but we only need to hold it for list modifications to lock + * out readers since we're under the RTNL here as all other + * writers. + */ + mutex_lock(&local->iflist_mtx); list_del(&sdata->list); + mutex_unlock(&local->iflist_mtx); + unregister_netdevice(sdata->dev); } } diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 210dfe3cf6c..a109c06e8e4 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -758,6 +758,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, local->hw.conf.radio_enabled = true; INIT_LIST_HEAD(&local->interfaces); + mutex_init(&local->iflist_mtx); spin_lock_init(&local->key_lock); @@ -1008,6 +1009,8 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); + mutex_destroy(&local->iflist_mtx); + wiphy_free(local->hw.wiphy); } EXPORT_SYMBOL(ieee80211_free_hw); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index fc30f2940e1..73c7d7345ab 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -468,7 +468,7 @@ void ieee80211_iterate_active_interfaces( struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata; - rtnl_lock(); + mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { switch (sdata->vif.type) { @@ -489,7 +489,7 @@ void ieee80211_iterate_active_interfaces( &sdata->vif); } - rtnl_unlock(); + mutex_unlock(&local->iflist_mtx); } EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); -- GitLab From 3978e5bce63484789891c67413372da3915bcbd6 Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Fri, 23 Jan 2009 13:45:23 -0800 Subject: [PATCH 0969/4982] iwlwifi: iwl_tx_queue_alloc : fix warning in printk formatting This patch fix compilation warning in printk formatting iwl_tx_queue_alloc function. Cleanup the code a bit on the way. Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-tx.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 58118c8224c..7d2b6e11f73 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -278,6 +278,7 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv, struct iwl_tx_queue *txq, u32 id) { struct pci_dev *dev = priv->pci_dev; + size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX; /* Driver private data, only for Tx (not command) queues, * not shared with device. */ @@ -289,18 +290,16 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv, "structures failed\n"); goto error; } - } else + } else { txq->txb = NULL; + } /* Circular buffer of transmit frame descriptors (TFDs), * shared with device */ - txq->tfds = pci_alloc_consistent(dev, - priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX, - &txq->q.dma_addr); + txq->tfds = pci_alloc_consistent(dev, tfd_sz, &txq->q.dma_addr); if (!txq->tfds) { - IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", - priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX); + IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz); goto error; } txq->q.id = id; -- GitLab From 3b5d665b51cda73ef1a774b515afd879a38e3674 Mon Sep 17 00:00:00 2001 From: Alina Friedrichsen Date: Sat, 24 Jan 2009 07:09:59 +0100 Subject: [PATCH 0970/4982] mac80211: Generic TSF debugging This patch enables low-level driver independent debugging of the TSF and remove the driver specific things of ath5k and ath9k from the debugfs. Signed-off-by: Alina Friedrichsen Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 10 ++++++ drivers/net/wireless/ath5k/debug.c | 48 -------------------------- drivers/net/wireless/ath5k/debug.h | 1 - drivers/net/wireless/ath9k/core.h | 1 - drivers/net/wireless/ath9k/debug.c | 48 -------------------------- drivers/net/wireless/ath9k/main.c | 9 +++++ include/net/mac80211.h | 7 +++- net/mac80211/debugfs.c | 55 ++++++++++++++++++++++++++++-- 8 files changed, 77 insertions(+), 102 deletions(-) diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index fa39f21c36c..b3f41acb906 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -239,6 +239,7 @@ static int ath5k_get_stats(struct ieee80211_hw *hw, static int ath5k_get_tx_stats(struct ieee80211_hw *hw, struct ieee80211_tx_queue_stats *stats); static u64 ath5k_get_tsf(struct ieee80211_hw *hw); +static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf); static void ath5k_reset_tsf(struct ieee80211_hw *hw); static int ath5k_beacon_update(struct ath5k_softc *sc, struct sk_buff *skb); @@ -261,6 +262,7 @@ static struct ieee80211_ops ath5k_hw_ops = { .conf_tx = NULL, .get_tx_stats = ath5k_get_tx_stats, .get_tsf = ath5k_get_tsf, + .set_tsf = ath5k_set_tsf, .reset_tsf = ath5k_reset_tsf, .bss_info_changed = ath5k_bss_info_changed, }; @@ -3110,6 +3112,14 @@ ath5k_get_tsf(struct ieee80211_hw *hw) return ath5k_hw_get_tsf64(sc->ah); } +static void +ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf) +{ + struct ath5k_softc *sc = hw->priv; + + ath5k_hw_set_tsf64(sc->ah, tsf); +} + static void ath5k_reset_tsf(struct ieee80211_hw *hw) { diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c index 129b72684da..413ed689cd5 100644 --- a/drivers/net/wireless/ath5k/debug.c +++ b/drivers/net/wireless/ath5k/debug.c @@ -193,50 +193,6 @@ static const struct file_operations fops_registers = { }; -/* debugfs: TSF */ - -static ssize_t read_file_tsf(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath5k_softc *sc = file->private_data; - char buf[100]; - snprintf(buf, sizeof(buf), "0x%016llx\n", - (unsigned long long)ath5k_hw_get_tsf64(sc->ah)); - return simple_read_from_buffer(user_buf, count, ppos, buf, 19); -} - -static ssize_t write_file_tsf(struct file *file, - const char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct ath5k_softc *sc = file->private_data; - char buf[21]; - unsigned long long tsf; - - if (copy_from_user(buf, userbuf, min(count, sizeof(buf) - 1))) - return -EFAULT; - buf[sizeof(buf) - 1] = '\0'; - - if (strncmp(buf, "reset", 5) == 0) { - ath5k_hw_reset_tsf(sc->ah); - printk(KERN_INFO "debugfs reset TSF\n"); - } else { - tsf = simple_strtoul(buf, NULL, 0); - ath5k_hw_set_tsf64(sc->ah, tsf); - printk(KERN_INFO "debugfs set TSF to %#018llx\n", tsf); - } - - return count; -} - -static const struct file_operations fops_tsf = { - .read = read_file_tsf, - .write = write_file_tsf, - .open = ath5k_debugfs_open, - .owner = THIS_MODULE, -}; - - /* debugfs: beacons */ static ssize_t read_file_beacon(struct file *file, char __user *user_buf, @@ -430,9 +386,6 @@ ath5k_debug_init_device(struct ath5k_softc *sc) sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUGO, sc->debug.debugfs_phydir, sc, &fops_registers); - sc->debug.debugfs_tsf = debugfs_create_file("tsf", S_IWUSR | S_IRUGO, - sc->debug.debugfs_phydir, sc, &fops_tsf); - sc->debug.debugfs_beacon = debugfs_create_file("beacon", S_IWUSR | S_IRUGO, sc->debug.debugfs_phydir, sc, &fops_beacon); @@ -451,7 +404,6 @@ ath5k_debug_finish_device(struct ath5k_softc *sc) { debugfs_remove(sc->debug.debugfs_debug); debugfs_remove(sc->debug.debugfs_registers); - debugfs_remove(sc->debug.debugfs_tsf); debugfs_remove(sc->debug.debugfs_beacon); debugfs_remove(sc->debug.debugfs_reset); debugfs_remove(sc->debug.debugfs_phydir); diff --git a/drivers/net/wireless/ath5k/debug.h b/drivers/net/wireless/ath5k/debug.h index ffc52939330..66f69f04e55 100644 --- a/drivers/net/wireless/ath5k/debug.h +++ b/drivers/net/wireless/ath5k/debug.h @@ -72,7 +72,6 @@ struct ath5k_dbg_info { struct dentry *debugfs_phydir; struct dentry *debugfs_debug; struct dentry *debugfs_registers; - struct dentry *debugfs_tsf; struct dentry *debugfs_beacon; struct dentry *debugfs_reset; }; diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index acbd8881ef8..29251f8dabb 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -141,7 +141,6 @@ struct ath9k_debug { struct dentry *debugfs_phy; struct dentry *debugfs_dma; struct dentry *debugfs_interrupt; - struct dentry *debugfs_tsf; struct ath_stats stats; }; diff --git a/drivers/net/wireless/ath9k/debug.c b/drivers/net/wireless/ath9k/debug.c index 05e1f82cc7a..1680164b4ad 100644 --- a/drivers/net/wireless/ath9k/debug.c +++ b/drivers/net/wireless/ath9k/debug.c @@ -223,48 +223,6 @@ static const struct file_operations fops_interrupt = { }; -static ssize_t read_file_tsf(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - char buf[100]; - snprintf(buf, sizeof(buf), "0x%016llx\n", - (unsigned long long)ath9k_hw_gettsf64(sc->sc_ah)); - return simple_read_from_buffer(user_buf, count, ppos, buf, 19); -} - -static ssize_t write_file_tsf(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - char buf[21]; - unsigned long long tsf; - - if (copy_from_user(buf, user_buf, min(count, sizeof(buf) - 1))) - return -EFAULT; - buf[sizeof(buf) - 1] = '\0'; - - if (strncmp(buf, "reset", 5) == 0) { - ath9k_hw_reset_tsf(sc->sc_ah); - printk(KERN_INFO "debugfs reset TSF\n"); - } else { - tsf = simple_strtoul(buf, NULL, 0); - ath9k_hw_settsf64(sc->sc_ah, tsf); - printk(KERN_INFO "debugfs set TSF to %#018llx\n", tsf); - } - - return count; -} - -static const struct file_operations fops_tsf = { - .read = read_file_tsf, - .write = write_file_tsf, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE -}; - - int ath9k_init_debug(struct ath_softc *sc) { sc->sc_debug.debug_mask = ath9k_debug; @@ -290,11 +248,6 @@ int ath9k_init_debug(struct ath_softc *sc) if (!sc->sc_debug.debugfs_interrupt) goto err; - sc->sc_debug.debugfs_tsf = debugfs_create_file("tsf", S_IRUGO, - sc->sc_debug.debugfs_phy, sc, &fops_tsf); - if (!sc->sc_debug.debugfs_tsf) - goto err; - return 0; err: ath9k_exit_debug(sc); @@ -303,7 +256,6 @@ err: void ath9k_exit_debug(struct ath_softc *sc) { - debugfs_remove(sc->sc_debug.debugfs_tsf); debugfs_remove(sc->sc_debug.debugfs_interrupt); debugfs_remove(sc->sc_debug.debugfs_dma); debugfs_remove(sc->sc_debug.debugfs_phy); diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 15a7f90bc84..90e687b5a8b 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -2451,6 +2451,14 @@ static u64 ath9k_get_tsf(struct ieee80211_hw *hw) return tsf; } +static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf) +{ + struct ath_softc *sc = hw->priv; + struct ath_hal *ah = sc->sc_ah; + + ath9k_hw_settsf64(ah, tsf); +} + static void ath9k_reset_tsf(struct ieee80211_hw *hw) { struct ath_softc *sc = hw->priv; @@ -2514,6 +2522,7 @@ struct ieee80211_ops ath9k_ops = { .bss_info_changed = ath9k_bss_info_changed, .set_key = ath9k_set_key, .get_tsf = ath9k_get_tsf, + .set_tsf = ath9k_set_tsf, .reset_tsf = ath9k_reset_tsf, .ampdu_action = ath9k_ampdu_action, }; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 8e65adf0a64..e2144f0e872 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1359,7 +1359,11 @@ enum ieee80211_ampdu_mlme_action { * hw->ampdu_queues items. * * @get_tsf: Get the current TSF timer value from firmware/hardware. Currently, - * this is only used for IBSS mode debugging and, as such, is not a + * this is only used for IBSS mode BSSID merging and debugging. Is not a + * required function. Must be atomic. + * + * @set_tsf: Set the TSF timer to the specified value in the firmware/hardware. + * Currently, this is only used for IBSS mode debugging. Is not a * required function. Must be atomic. * * @reset_tsf: Reset the TSF timer and allow firmware/hardware to synchronize @@ -1421,6 +1425,7 @@ struct ieee80211_ops { int (*get_tx_stats)(struct ieee80211_hw *hw, struct ieee80211_tx_queue_stats *stats); u64 (*get_tsf)(struct ieee80211_hw *hw); + void (*set_tsf)(struct ieee80211_hw *hw, u64 tsf); void (*reset_tsf)(struct ieee80211_hw *hw); int (*tx_last_beacon)(struct ieee80211_hw *hw); int (*ampdu_action)(struct ieee80211_hw *hw, diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 717d5484e1e..e37f557de3f 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -57,12 +57,61 @@ DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d", local->hw.conf.long_frame_max_tx_count); DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d", local->total_ps_buffered); -DEBUGFS_READONLY_FILE(wep_iv, 20, "%#06x", +DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x", local->wep_iv & 0xffffff); DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s", local->rate_ctrl ? local->rate_ctrl->ops->name : ""); -DEBUGFS_READONLY_FILE(tsf, 20, "%#018llx", - (unsigned long long) (local->ops->get_tsf ? local->ops->get_tsf(local_to_hw(local)) : 0)); + +static ssize_t tsf_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_local *local = file->private_data; + u64 tsf = 0; + char buf[100]; + + if (local->ops->get_tsf) + tsf = local->ops->get_tsf(local_to_hw(local)); + + snprintf(buf, sizeof(buf), "0x%016llx\n", (unsigned long long) tsf); + + return simple_read_from_buffer(user_buf, count, ppos, buf, 19); +} + +static ssize_t tsf_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_local *local = file->private_data; + unsigned long long tsf; + char buf[100]; + size_t len; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + buf[len] = '\0'; + + if (strncmp(buf, "reset", 5) == 0) { + if (local->ops->reset_tsf) { + local->ops->reset_tsf(local_to_hw(local)); + printk(KERN_INFO "%s: debugfs reset TSF\n", wiphy_name(local->hw.wiphy)); + } + } else { + tsf = simple_strtoul(buf, NULL, 0); + if (local->ops->set_tsf) { + local->ops->set_tsf(local_to_hw(local), tsf); + printk(KERN_INFO "%s: debugfs set TSF to %#018llx\n", wiphy_name(local->hw.wiphy), tsf); + } + } + + return count; +} + +static const struct file_operations tsf_ops = { + .read = tsf_read, + .write = tsf_write, + .open = mac80211_open_file_generic +}; /* statistics stuff */ -- GitLab From 08e87a833f5e77ff33b64c9ac27cb7fb9ecd4a48 Mon Sep 17 00:00:00 2001 From: Alina Friedrichsen Date: Sun, 25 Jan 2009 15:28:28 +0100 Subject: [PATCH 0971/4982] b43: Accessing the TSF via mac80211 This allows the mac80211 high level code to access the TSF. This is e.g. needed for BSSID merges in the IBSS mode. The second version adds locking and removes the now unnecessary debugfs entries. Thanks to Michael Buesch! :) Signed-off-by: Alina Friedrichsen Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/debugfs.c | 31 ------------------------ drivers/net/wireless/b43/debugfs.h | 1 - drivers/net/wireless/b43/main.c | 39 ++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 32 deletions(-) diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c index e04fc91f569..7ed0eeeddea 100644 --- a/drivers/net/wireless/b43/debugfs.c +++ b/drivers/net/wireless/b43/debugfs.c @@ -367,34 +367,6 @@ static int mmio32write__write_file(struct b43_wldev *dev, return 0; } -/* wl->irq_lock is locked */ -static ssize_t tsf_read_file(struct b43_wldev *dev, - char *buf, size_t bufsize) -{ - ssize_t count = 0; - u64 tsf; - - b43_tsf_read(dev, &tsf); - fappend("0x%08x%08x\n", - (unsigned int)((tsf & 0xFFFFFFFF00000000ULL) >> 32), - (unsigned int)(tsf & 0xFFFFFFFFULL)); - - return count; -} - -/* wl->irq_lock is locked */ -static int tsf_write_file(struct b43_wldev *dev, - const char *buf, size_t count) -{ - u64 tsf; - - if (sscanf(buf, "%llu", (unsigned long long *)(&tsf)) != 1) - return -EINVAL; - b43_tsf_write(dev, tsf); - - return 0; -} - static ssize_t txstat_read_file(struct b43_wldev *dev, char *buf, size_t bufsize) { @@ -691,7 +663,6 @@ B43_DEBUGFS_FOPS(mmio16read, mmio16read__read_file, mmio16read__write_file, 1); B43_DEBUGFS_FOPS(mmio16write, NULL, mmio16write__write_file, 1); B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file, 1); B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file, 1); -B43_DEBUGFS_FOPS(tsf, tsf_read_file, tsf_write_file, 1); B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0); B43_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1); B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL, 0); @@ -805,7 +776,6 @@ void b43_debugfs_add_device(struct b43_wldev *dev) ADD_FILE(mmio16write, 0200); ADD_FILE(mmio32read, 0600); ADD_FILE(mmio32write, 0200); - ADD_FILE(tsf, 0600); ADD_FILE(txstat, 0400); ADD_FILE(restart, 0200); ADD_FILE(loctls, 0400); @@ -834,7 +804,6 @@ void b43_debugfs_remove_device(struct b43_wldev *dev) debugfs_remove(e->file_mmio16write.dentry); debugfs_remove(e->file_mmio32read.dentry); debugfs_remove(e->file_mmio32write.dentry); - debugfs_remove(e->file_tsf.dentry); debugfs_remove(e->file_txstat.dentry); debugfs_remove(e->file_restart.dentry); debugfs_remove(e->file_loctls.dentry); diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h index 7886cbe2d1d..91a2f2918a2 100644 --- a/drivers/net/wireless/b43/debugfs.h +++ b/drivers/net/wireless/b43/debugfs.h @@ -46,7 +46,6 @@ struct b43_dfsentry { struct b43_dfs_file file_mmio16write; struct b43_dfs_file file_mmio32read; struct b43_dfs_file file_mmio32write; - struct b43_dfs_file file_tsf; struct b43_dfs_file file_txstat; struct b43_dfs_file file_txpower_g; struct b43_dfs_file file_restart; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index cbb3d45f6fc..e41c10fd31d 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3245,6 +3245,43 @@ static int b43_op_get_stats(struct ieee80211_hw *hw, return 0; } +static u64 b43_op_get_tsf(struct ieee80211_hw *hw) +{ + struct b43_wl *wl = hw_to_b43_wl(hw); + struct b43_wldev *dev; + u64 tsf; + + mutex_lock(&wl->mutex); + spin_lock_irq(&wl->irq_lock); + dev = wl->current_dev; + + if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED)) + b43_tsf_read(dev, &tsf); + else + tsf = 0; + + spin_unlock_irq(&wl->irq_lock); + mutex_unlock(&wl->mutex); + + return tsf; +} + +static void b43_op_set_tsf(struct ieee80211_hw *hw, u64 tsf) +{ + struct b43_wl *wl = hw_to_b43_wl(hw); + struct b43_wldev *dev; + + mutex_lock(&wl->mutex); + spin_lock_irq(&wl->irq_lock); + dev = wl->current_dev; + + if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED)) + b43_tsf_write(dev, tsf); + + spin_unlock_irq(&wl->irq_lock); + mutex_unlock(&wl->mutex); +} + static void b43_put_phy_into_reset(struct b43_wldev *dev) { struct ssb_device *sdev = dev->dev; @@ -4364,6 +4401,8 @@ static const struct ieee80211_ops b43_hw_ops = { .set_key = b43_op_set_key, .get_stats = b43_op_get_stats, .get_tx_stats = b43_op_get_tx_stats, + .get_tsf = b43_op_get_tsf, + .set_tsf = b43_op_set_tsf, .start = b43_op_start, .stop = b43_op_stop, .set_tim = b43_op_beacon_set_tim, -- GitLab From 060210f938d8aa0b9d795588a2274cd67ba9d6a4 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 25 Jan 2009 15:49:59 +0100 Subject: [PATCH 0972/4982] b43: Dynamically control log verbosity Dynamically control the log verbosity with a module parameter. This enables us to dynamically enable debugging messages (or disable info, warn, error messages) via module parameter or /sys/module/b43/parameters/verbose. This increases the module size by about 3k. But in practice it reduces the module size for the user, because some distributions ship the b43 module with CONFIG_B43_DEBUG set, which increases the module by about 15k. So with this patch applied, distributions should really _disable_ CONFIG_B43_DEBUG. There is no reason to keep it in a production-release kernel. So we have a net reduction in size by about 12k. This patch also adds a printk of the wireless core revision, so people don't have to enable SSB debugging to get the wireless core revision. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/Kconfig | 14 +++++++++++--- drivers/net/wireless/b43/b43.h | 5 +---- drivers/net/wireless/b43/debugfs.c | 13 +++++++++++-- drivers/net/wireless/b43/debugfs.h | 4 ++-- drivers/net/wireless/b43/main.c | 25 +++++++++++++++++-------- drivers/net/wireless/b43/main.h | 18 ++++++++++++++++++ 6 files changed, 60 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 1f81d36f87c..aab71a70ba7 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -110,10 +110,18 @@ config B43_DEBUG bool "Broadcom 43xx debugging" depends on B43 ---help--- - Broadcom 43xx debugging messages. + Broadcom 43xx debugging. - Say Y, if you want to find out why the driver does not - work for you. + This adds additional runtime sanity checks and statistics to the driver. + These checks and statistics might me expensive and hurt runtime performance + of your system. + This also adds the b43 debugfs interface. + + Do not enable this, unless you are debugging the driver. + + Say N, if you are a distributor or user building a release kernel + for production use. + Only say Y, if you are debugging a problem in the b43 driver sourcecode. config B43_FORCE_PIO bool "Force usage of PIO instead of DMA" diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 9e0da212f8c..e9d60f0910b 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -878,12 +878,9 @@ void b43err(struct b43_wl *wl, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); void b43warn(struct b43_wl *wl, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); -#if B43_DEBUG void b43dbg(struct b43_wl *wl, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); -#else /* DEBUG */ -# define b43dbg(wl, fmt...) do { /* nothing */ } while (0) -#endif /* DEBUG */ + /* A WARN_ON variant that vanishes when b43 debugging is disabled. * This _also_ evaluates the arg with debugging disabled. */ diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c index 7ed0eeeddea..bc2767da46e 100644 --- a/drivers/net/wireless/b43/debugfs.c +++ b/drivers/net/wireless/b43/debugfs.c @@ -668,9 +668,18 @@ B43_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1); B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL, 0); -int b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature) +bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature) { - return !!(dev->dfsentry && dev->dfsentry->dyn_debug[feature]); + bool enabled; + + enabled = (dev->dfsentry && dev->dfsentry->dyn_debug[feature]); + if (unlikely(enabled)) { + /* Force full debugging messages, if the user enabled + * some dynamic debugging feature. */ + b43_modparam_verbose = B43_VERBOSITY_MAX; + } + + return enabled; } static void b43_remove_dynamic_debug(struct b43_wldev *dev) diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h index 91a2f2918a2..b9d4de4a979 100644 --- a/drivers/net/wireless/b43/debugfs.h +++ b/drivers/net/wireless/b43/debugfs.h @@ -71,7 +71,7 @@ struct b43_dfsentry { struct dentry *dyn_debug_dentries[__B43_NR_DYNDBG]; }; -int b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature); +bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature); void b43_debugfs_init(void); void b43_debugfs_exit(void); @@ -82,7 +82,7 @@ void b43_debugfs_log_txstat(struct b43_wldev *dev, #else /* CONFIG_B43_DEBUG */ -static inline int b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature) +static inline bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature) { return 0; } diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index e41c10fd31d..dbb8765506e 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4,7 +4,7 @@ Copyright (c) 2005 Martin Langer Copyright (c) 2005 Stefano Brivio - Copyright (c) 2005, 2006 Michael Buesch + Copyright (c) 2005-2009 Michael Buesch Copyright (c) 2005 Danny van Dyk Copyright (c) 2005 Andreas Jaggi @@ -88,6 +88,10 @@ static int modparam_btcoex = 1; module_param_named(btcoex, modparam_btcoex, int, 0444); MODULE_PARM_DESC(btcoex, "Enable Bluetooth coexistance (default on)"); +int b43_modparam_verbose = B43_VERBOSITY_DEFAULT; +module_param_named(verbose, b43_modparam_verbose, int, 0644); +MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug"); + static const struct ssb_device_id b43_ssb_tbl[] = { SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5), @@ -300,6 +304,8 @@ void b43info(struct b43_wl *wl, const char *fmt, ...) { va_list args; + if (b43_modparam_verbose < B43_VERBOSITY_INFO) + return; if (!b43_ratelimit(wl)) return; va_start(args, fmt); @@ -313,6 +319,8 @@ void b43err(struct b43_wl *wl, const char *fmt, ...) { va_list args; + if (b43_modparam_verbose < B43_VERBOSITY_ERROR) + return; if (!b43_ratelimit(wl)) return; va_start(args, fmt); @@ -326,6 +334,8 @@ void b43warn(struct b43_wl *wl, const char *fmt, ...) { va_list args; + if (b43_modparam_verbose < B43_VERBOSITY_WARN) + return; if (!b43_ratelimit(wl)) return; va_start(args, fmt); @@ -335,18 +345,18 @@ void b43warn(struct b43_wl *wl, const char *fmt, ...) va_end(args); } -#if B43_DEBUG void b43dbg(struct b43_wl *wl, const char *fmt, ...) { va_list args; + if (b43_modparam_verbose < B43_VERBOSITY_DEBUG) + return; va_start(args, fmt); printk(KERN_DEBUG "b43-%s debug: ", (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); vprintk(fmt, args); va_end(args); } -#endif /* DEBUG */ static void b43_ram_write(struct b43_wldev *dev, u16 offset, u32 val) { @@ -3589,9 +3599,7 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, u8 algorithm; u8 index; int err; -#if B43_DEBUG - static const u8 bcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; -#endif + static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; if (modparam_nohwcrypt) return -ENOSPC; /* User disabled HW-crypto */ @@ -4744,9 +4752,10 @@ static int b43_wireless_init(struct ssb_device *dev) INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work); ssb_set_devtypedata(dev, wl); - b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id); + b43info(wl, "Broadcom %04X WLAN found (core revision %u)\n", + dev->bus->chip_id, dev->id.revision); err = 0; - out: +out: return err; } diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index e6d90f377d9..40abcf5d1b4 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h @@ -40,6 +40,24 @@ extern int b43_modparam_qos; +extern int b43_modparam_verbose; + +/* Logmessage verbosity levels. Update the b43_modparam_verbose helptext, if + * you add or remove levels. */ +enum b43_verbosity { + B43_VERBOSITY_ERROR, + B43_VERBOSITY_WARN, + B43_VERBOSITY_INFO, + B43_VERBOSITY_DEBUG, + __B43_VERBOSITY_AFTERLAST, /* keep last */ + + B43_VERBOSITY_MAX = __B43_VERBOSITY_AFTERLAST - 1, +#if B43_DEBUG + B43_VERBOSITY_DEFAULT = B43_VERBOSITY_DEBUG, +#else + B43_VERBOSITY_DEFAULT = B43_VERBOSITY_INFO, +#endif +}; /* Lightweight function to convert a frequency (in Mhz) to a channel number. */ -- GitLab From f677d7702d48b7b3dfcce3b2c0db601dbee0aa24 Mon Sep 17 00:00:00 2001 From: Tulio Magno Quites Machado Filho Date: Sun, 25 Jan 2009 23:54:25 +0100 Subject: [PATCH 0973/4982] ath5k: support LED's on emachines E510 notebook Add vendor ID for AMBIT and use it to set the ath5k LED gpio. base.c: Changes-licensed-under: 3-Clause-BSD Signed-off-by: Tulio Magno Quites Machado Filho Acked-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 8 ++++++-- include/linux/pci_ids.h | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index b3f41acb906..368db944f11 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -2626,8 +2626,12 @@ ath5k_init_leds(struct ath5k_softc *sc) sc->led_pin = 1; sc->led_on = 1; /* active high */ } - /* Pin 3 on Foxconn chips used in Acer Aspire One (0x105b:e008) */ - if (pdev->subsystem_vendor == PCI_VENDOR_ID_FOXCONN) { + /* + * Pin 3 on Foxconn chips used in Acer Aspire One (0x105b:e008) and + * in emachines notebooks with AMBIT subsystem. + */ + if (pdev->subsystem_vendor == PCI_VENDOR_ID_FOXCONN || + pdev->subsystem_vendor == PCI_VENDOR_ID_AMBIT) { __set_bit(ATH_STAT_LEDSOFT, sc->status); sc->led_pin = 3; sc->led_on = 0; /* active low */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 5b7a48c1d61..b7697c934a4 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1967,6 +1967,8 @@ #define PCI_VENDOR_ID_SAMSUNG 0x144d +#define PCI_VENDOR_ID_AMBIT 0x1468 + #define PCI_VENDOR_ID_MYRICOM 0x14c1 #define PCI_VENDOR_ID_TITAN 0x14D2 -- GitLab From 0c6666e4c43a10a224c63e3270c963d97f7e8cc8 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 26 Jan 2009 06:48:10 -0800 Subject: [PATCH 0974/4982] ath9k: fix debug print on regd With debugging enabled and with ATH_DBG_REGULATORY selected we wouldn't get the full print out of one line, reason is we used "," instead of nothing to separate two lines. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/regd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath9k/regd.c b/drivers/net/wireless/ath9k/regd.c index 90f0c982430..ec88f78743e 100644 --- a/drivers/net/wireless/ath9k/regd.c +++ b/drivers/net/wireless/ath9k/regd.c @@ -447,7 +447,7 @@ int ath9k_regd_init(struct ath_hal *ah) } DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "Country alpha2 being used: %c%c\n", + "Country alpha2 being used: %c%c\n" "Regpair detected: 0x%0x\n", ah->alpha2[0], ah->alpha2[1], ah->regpair->regDmnEnum); -- GitLab From 793c592995b841667fa6d1a36a98880430dcc8f4 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Mon, 26 Jan 2009 20:28:14 +0530 Subject: [PATCH 0975/4982] ath9k: Fix AR9285 specific noise floor eeprom reads. Fix AR9285 specific noise floor reads and initialize tx and rx chainmask during reset. This along with the following earlier patches of ath9k fixes an issue with association noticed in noisy environment. ath9k: Fix typo in chip version check ath9k: Remove unnecessary gpio configuration in ath9k_hw_reset() ath9k: Fix bug in NF calibration Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/calib.c | 78 +++++++++++++++--------------- drivers/net/wireless/ath9k/hw.c | 5 +- 2 files changed, 42 insertions(+), 41 deletions(-) diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c index c6d1de0f1e2..69ff01ce968 100644 --- a/drivers/net/wireless/ath9k/calib.c +++ b/drivers/net/wireless/ath9k/calib.c @@ -105,27 +105,29 @@ static void ath9k_hw_do_getnf(struct ath_hal *ah, "NF calibrated [ctl] [chain 0] is %d\n", nf); nfarray[0] = nf; - if (AR_SREV_9280_10_OR_LATER(ah)) - nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), - AR9280_PHY_CH1_MINCCA_PWR); - else - nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), - AR_PHY_CH1_MINCCA_PWR); - - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "NF calibrated [ctl] [chain 1] is %d\n", nf); - nfarray[1] = nf; + if (!AR_SREV_9285(ah)) { + if (AR_SREV_9280_10_OR_LATER(ah)) + nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), + AR9280_PHY_CH1_MINCCA_PWR); + else + nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), + AR_PHY_CH1_MINCCA_PWR); - if (!AR_SREV_9280(ah)) { - nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), - AR_PHY_CH2_MINCCA_PWR); if (nf & 0x100) nf = 0 - ((nf ^ 0x1ff) + 1); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "NF calibrated [ctl] [chain 2] is %d\n", nf); - nfarray[2] = nf; + "NF calibrated [ctl] [chain 1] is %d\n", nf); + nfarray[1] = nf; + + if (!AR_SREV_9280(ah)) { + nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), + AR_PHY_CH2_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "NF calibrated [ctl] [chain 2] is %d\n", nf); + nfarray[2] = nf; + } } if (AR_SREV_9280_10_OR_LATER(ah)) @@ -141,27 +143,29 @@ static void ath9k_hw_do_getnf(struct ath_hal *ah, "NF calibrated [ext] [chain 0] is %d\n", nf); nfarray[3] = nf; - if (AR_SREV_9280_10_OR_LATER(ah)) - nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), - AR9280_PHY_CH1_EXT_MINCCA_PWR); - else - nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), - AR_PHY_CH1_EXT_MINCCA_PWR); + if (!AR_SREV_9285(ah)) { + if (AR_SREV_9280_10_OR_LATER(ah)) + nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), + AR9280_PHY_CH1_EXT_MINCCA_PWR); + else + nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), + AR_PHY_CH1_EXT_MINCCA_PWR); - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "NF calibrated [ext] [chain 1] is %d\n", nf); - nfarray[4] = nf; - - if (!AR_SREV_9280(ah)) { - nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), - AR_PHY_CH2_EXT_MINCCA_PWR); if (nf & 0x100) nf = 0 - ((nf ^ 0x1ff) + 1); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "NF calibrated [ext] [chain 2] is %d\n", nf); - nfarray[5] = nf; + "NF calibrated [ext] [chain 1] is %d\n", nf); + nfarray[4] = nf; + + if (!AR_SREV_9280(ah)) { + nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), + AR_PHY_CH2_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "NF calibrated [ext] [chain 2] is %d\n", nf); + nfarray[5] = nf; + } } } @@ -668,12 +672,6 @@ int16_t ath9k_hw_getnf(struct ath_hal *ah, int16_t nfarray[NUM_NF_READINGS] = { 0 }; struct ath9k_nfcal_hist *h; struct ieee80211_channel *c = chan->chan; - u8 chainmask; - - if (AR_SREV_9280(ah)) - chainmask = 0x1B; - else - chainmask = 0x3F; chan->channelFlags &= (~CHANNEL_CW_INT); if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index bb8628c7efa..77282345efc 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -2165,7 +2165,10 @@ int ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan, ahp->ah_txchainmask = sc->sc_tx_chainmask; ahp->ah_rxchainmask = sc->sc_rx_chainmask; - if (AR_SREV_9280(ah)) { + if (AR_SREV_9285(ah)) { + ahp->ah_txchainmask &= 0x1; + ahp->ah_rxchainmask &= 0x1; + } else if (AR_SREV_9280(ah)) { ahp->ah_txchainmask &= 0x3; ahp->ah_rxchainmask &= 0x3; } -- GitLab From b51bb3cd6c8078b8b8cc1d1725b100267eaa726e Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 26 Jan 2009 07:30:03 -0800 Subject: [PATCH 0976/4982] ath9k: remove useless ath9k driver version information Versioning for ath9k is pointless we have kept it at 0.1 since the initial release so its meaningless. We put more emphasis on kernel release or dated wireless-testing master tag as per John's tagging. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 90e687b5a8b..ede8980be96 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -2588,13 +2588,12 @@ static int __init ath9k_init(void) { int error; - printk(KERN_INFO "%s: %s\n", dev_info, ATH_PCI_VERSION); - /* Register rate control algorithm */ error = ath_rate_control_register(); if (error != 0) { printk(KERN_ERR - "Unable to register rate control algorithm: %d\n", + "ath9k: Unable to register rate control " + "algorithm: %d\n", error); goto err_out; } @@ -2602,7 +2601,7 @@ static int __init ath9k_init(void) error = ath_pci_init(); if (error < 0) { printk(KERN_ERR - "ath_pci: No devices found, driver not installed.\n"); + "ath9k: No PCI devices found, driver not installed.\n"); error = -ENODEV; goto err_rate_unregister; } -- GitLab From d81c2d9c909e95ee8a5745da95bbb35f8ded3d17 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 26 Jan 2009 09:00:51 -0800 Subject: [PATCH 0977/4982] cfg80211: do not pass -EALREADY to userspace on regdomain change request If the regulatory domain is already set it is technically not an error so do not pass an errno to userspace. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 09a5d0f1d6d..e69da8d2047 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1908,6 +1908,11 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) mutex_lock(&cfg80211_drv_mutex); r = __regulatory_hint(NULL, REGDOM_SET_BY_USER, data, 0, ENVIRON_ANY); mutex_unlock(&cfg80211_drv_mutex); + /* This means the regulatory domain was already set, however + * we don't want to confuse userspace with a "successful error" + * message so lets just treat it as a success */ + if (r == -EALREADY) + r = 0; return r; } -- GitLab From fb9ddbf086591ab4c90c44d10468f84d465b3fdf Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 26 Jan 2009 19:11:57 +0100 Subject: [PATCH 0978/4982] mac80211: don't try to powersave/config disabled interfaces Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/scan.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 8248d7b6ae8..282e6a0dec0 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -475,6 +475,9 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { + if (!netif_running(sdata->dev)) + continue; + /* Tell AP we're back */ if (sdata->vif.type == NL80211_IFTYPE_STATION) { if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { @@ -637,6 +640,9 @@ int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { + if (!netif_running(sdata->dev)) + continue; + ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED); if (sdata->vif.type == NL80211_IFTYPE_STATION) { -- GitLab From bc05595845f58c065adc0763a678187647ec040f Mon Sep 17 00:00:00 2001 From: James Morris Date: Thu, 29 Jan 2009 11:28:33 +1100 Subject: [PATCH 0979/4982] selinux: remove unused bprm_check_security hook Remove unused bprm_check_security hook from SELinux. This currently calls into the capabilities hook, which is a noop. Acked-by: Eric Paris Acked-by: Serge Hallyn Signed-off-by: James Morris --- security/selinux/hooks.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 3bb4942e39c..8251c6ba36c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2182,11 +2182,6 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) return 0; } -static int selinux_bprm_check_security(struct linux_binprm *bprm) -{ - return secondary_ops->bprm_check_security(bprm); -} - static int selinux_bprm_secureexec(struct linux_binprm *bprm) { const struct cred *cred = current_cred(); @@ -5608,7 +5603,6 @@ static struct security_operations selinux_ops = { .netlink_recv = selinux_netlink_recv, .bprm_set_creds = selinux_bprm_set_creds, - .bprm_check_security = selinux_bprm_check_security, .bprm_committing_creds = selinux_bprm_committing_creds, .bprm_committed_creds = selinux_bprm_committed_creds, .bprm_secureexec = selinux_bprm_secureexec, -- GitLab From 2ec5dbe23d68bddc043a85d1226bfc499a724b1c Mon Sep 17 00:00:00 2001 From: James Morris Date: Thu, 29 Jan 2009 11:46:14 +1100 Subject: [PATCH 0980/4982] selinux: remove secondary ops call to bprm_committing_creds Remove secondary ops call to bprm_committing_creds, which is a noop in capabilities. Acked-by: Serge Hallyn Acked-by: Eric Paris Signed-off-by: James Morris --- security/selinux/hooks.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8251c6ba36c..fc01ffa0b69 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2311,8 +2311,6 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm) struct rlimit *rlim, *initrlim; int rc, i; - secondary_ops->bprm_committing_creds(bprm); - new_tsec = bprm->cred->security; if (new_tsec->sid == new_tsec->osid) return; -- GitLab From 5565b0b865f672e3d7e31936ad1d40710ab7bfc4 Mon Sep 17 00:00:00 2001 From: James Morris Date: Thu, 29 Jan 2009 11:47:49 +1100 Subject: [PATCH 0981/4982] selinux: remove secondary ops call to bprm_committed_creds Remove secondary ops call to bprm_committed_creds, which is a noop in capabilities. Acked-by: Serge Hallyn Acked-by: Eric Paris Signed-off-by: James Morris --- security/selinux/hooks.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index fc01ffa0b69..516058ff063 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2356,8 +2356,6 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm) int rc, i; unsigned long flags; - secondary_ops->bprm_committed_creds(bprm); - osid = tsec->osid; sid = tsec->sid; -- GitLab From ef935b9136eeaa203f75bf0b4d6e398c29f44d27 Mon Sep 17 00:00:00 2001 From: James Morris Date: Thu, 29 Jan 2009 11:51:11 +1100 Subject: [PATCH 0982/4982] selinux: remove secondary ops call to sb_mount Remove secondary ops call to sb_mount, which is a noop in capabilities. Acked-by: Serge Hallyn Acked-by: Eric Paris Signed-off-by: James Morris --- security/selinux/hooks.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 516058ff063..bdd483096b3 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2531,11 +2531,6 @@ static int selinux_mount(char *dev_name, void *data) { const struct cred *cred = current_cred(); - int rc; - - rc = secondary_ops->sb_mount(dev_name, path, type, flags, data); - if (rc) - return rc; if (flags & MS_REMOUNT) return superblock_has_perm(cred, path->mnt->mnt_sb, -- GitLab From 97422ab9ef45118cb7418d799dc69040f17108ce Mon Sep 17 00:00:00 2001 From: James Morris Date: Thu, 29 Jan 2009 11:55:02 +1100 Subject: [PATCH 0983/4982] selinux: remove secondary ops call to sb_umount Remove secondary ops call to sb_umount, which is a noop in capabilities. Acked-by: Serge Hallyn Acked-by: Eric Paris Signed-off-by: James Morris --- security/selinux/hooks.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index bdd483096b3..42aa8de5f59 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2543,11 +2543,6 @@ static int selinux_mount(char *dev_name, static int selinux_umount(struct vfsmount *mnt, int flags) { const struct cred *cred = current_cred(); - int rc; - - rc = secondary_ops->sb_umount(mnt, flags); - if (rc) - return rc; return superblock_has_perm(cred, mnt->mnt_sb, FILESYSTEM__UNMOUNT, NULL); -- GitLab From efdfac437607e4acfed66c383091a376525eaec4 Mon Sep 17 00:00:00 2001 From: James Morris Date: Thu, 29 Jan 2009 11:57:34 +1100 Subject: [PATCH 0984/4982] selinux: remove secondary ops call to inode_link Remove secondary ops call to inode_link, which is a noop in capabilities. Acked-by: Serge Hallyn Acked-by: Eric Paris Signed-off-by: James Morris --- security/selinux/hooks.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 42aa8de5f59..da0e523157d 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2630,11 +2630,6 @@ static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int ma static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) { - int rc; - - rc = secondary_ops->inode_link(old_dentry, dir, new_dentry); - if (rc) - return rc; return may_link(dir, old_dentry, MAY_LINK); } -- GitLab From e4737250b751b4e0e802adae9a4d3ae0227b580b Mon Sep 17 00:00:00 2001 From: James Morris Date: Thu, 29 Jan 2009 12:00:08 +1100 Subject: [PATCH 0985/4982] selinux: remove secondary ops call to inode_unlink Remove secondary ops call to inode_unlink, which is a noop in capabilities. Acked-by: Serge Hallyn Acked-by: Eric Paris Signed-off-by: James Morris --- security/selinux/hooks.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index da0e523157d..ec834dc0b41 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2635,11 +2635,6 @@ static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, stru static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry) { - int rc; - - rc = secondary_ops->inode_unlink(dir, dentry); - if (rc) - return rc; return may_link(dir, dentry, MAY_UNLINK); } -- GitLab From dd4907a6d4e038dc65839fcd4030ebefe2f5f439 Mon Sep 17 00:00:00 2001 From: James Morris Date: Thu, 29 Jan 2009 12:08:34 +1100 Subject: [PATCH 0986/4982] selinux: remove secondary ops call to inode_mknod Remove secondary ops call to inode_mknod, which is a noop in capabilities. Acked-by: Serge Hallyn Acked-by: Eric Paris Signed-off-by: James Morris --- security/selinux/hooks.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index ec834dc0b41..03621928f1b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2655,12 +2655,6 @@ static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry) static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) { - int rc; - - rc = secondary_ops->inode_mknod(dir, dentry, mode, dev); - if (rc) - return rc; - return may_create(dir, dentry, inode_mode_to_security_class(mode)); } -- GitLab From f51115b9ab5b9cfd0b7be1cce75afbf3ffbcdd87 Mon Sep 17 00:00:00 2001 From: James Morris Date: Thu, 29 Jan 2009 12:10:56 +1100 Subject: [PATCH 0987/4982] selinux: remove secondary ops call to inode_follow_link Remove secondary ops call to inode_follow_link, which is a noop in capabilities. Acked-by: Serge Hallyn Signed-off-by: James Morris --- security/selinux/hooks.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 03621928f1b..67291a385c7 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2674,11 +2674,7 @@ static int selinux_inode_readlink(struct dentry *dentry) static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata) { const struct cred *cred = current_cred(); - int rc; - rc = secondary_ops->inode_follow_link(dentry, nameidata); - if (rc) - return rc; return dentry_has_perm(cred, NULL, dentry, FILE__READ); } -- GitLab From 188fbcca9dd02f15dcf45cfc51ce0dd6c13993f6 Mon Sep 17 00:00:00 2001 From: James Morris Date: Thu, 29 Jan 2009 12:14:03 +1100 Subject: [PATCH 0988/4982] selinux: remove secondary ops call to inode_permission Remove secondary ops call to inode_permission, which is a noop in capabilities. Acked-by: Serge Hallyn Acked-by: Eric Paris Signed-off-by: James Morris --- security/selinux/hooks.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 67291a385c7..7e90c9e5865 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2681,11 +2681,6 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na static int selinux_inode_permission(struct inode *inode, int mask) { const struct cred *cred = current_cred(); - int rc; - - rc = secondary_ops->inode_permission(inode, mask); - if (rc) - return rc; if (!mask) { /* No permission to check. Existence test. */ -- GitLab From 438add6b32d9295db6e3ecd4d9e137086ec5b5d9 Mon Sep 17 00:00:00 2001 From: James Morris Date: Thu, 29 Jan 2009 12:15:59 +1100 Subject: [PATCH 0989/4982] selinux: remove secondary ops call to inode_setattr Remove secondary ops call to inode_setattr, which is a noop in capabilities. Acked-by: Serge Hallyn Acked-by: Eric Paris Signed-off-by: James Morris --- security/selinux/hooks.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 7e90c9e5865..08b506846a1 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2694,11 +2694,6 @@ static int selinux_inode_permission(struct inode *inode, int mask) static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) { const struct cred *cred = current_cred(); - int rc; - - rc = secondary_ops->inode_setattr(dentry, iattr); - if (rc) - return rc; if (iattr->ia_valid & ATTR_FORCE) return 0; -- GitLab From d541bbee6902d5ffb8a03d63ac8f4b1364c2ff93 Mon Sep 17 00:00:00 2001 From: James Morris Date: Thu, 29 Jan 2009 12:19:51 +1100 Subject: [PATCH 0990/4982] selinux: remove secondary ops call to file_mprotect Remove secondary ops call to file_mprotect, which is a noop in capabilities. Acked-by: Serge Hallyn Acked-by: Eric Paris Signed-off-by: James Morris --- security/selinux/hooks.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 08b506846a1..2c98071fba8 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3056,18 +3056,13 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, unsigned long prot) { const struct cred *cred = current_cred(); - int rc; - - rc = secondary_ops->file_mprotect(vma, reqprot, prot); - if (rc) - return rc; if (selinux_checkreqprot) prot = reqprot; #ifndef CONFIG_PPC32 if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { - rc = 0; + int rc = 0; if (vma->vm_start >= vma->vm_mm->start_brk && vma->vm_end <= vma->vm_mm->brk) { rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP); -- GitLab From af294e41d0c95a291cc821a1b43ec2cd13976a8b Mon Sep 17 00:00:00 2001 From: James Morris Date: Thu, 29 Jan 2009 12:23:36 +1100 Subject: [PATCH 0991/4982] selinux: remove secondary ops call to task_create Remove secondary ops call to task_create, which is a noop in capabilities. Acked-by: Serge Hallyn Acked-by: Eric Paris Signed-off-by: James Morris --- security/selinux/hooks.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 2c98071fba8..72c1e5cd26d 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3212,12 +3212,6 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred) static int selinux_task_create(unsigned long clone_flags) { - int rc; - - rc = secondary_ops->task_create(clone_flags); - if (rc) - return rc; - return current_has_perm(current, PROCESS__FORK); } -- GitLab From ca5143d3ff3c7a4e1c2c8bdcf0f53aea227a7722 Mon Sep 17 00:00:00 2001 From: James Morris Date: Thu, 29 Jan 2009 12:26:14 +1100 Subject: [PATCH 0992/4982] selinux: remove unused cred_commit hook Remove unused cred_commit hook from SELinux. This currently calls into the capabilities hook, which is a noop. Acked-by: Serge Hallyn Acked-by: Eric Paris Signed-off-by: James Morris --- security/selinux/hooks.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 72c1e5cd26d..afccada1f26 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3244,14 +3244,6 @@ static int selinux_cred_prepare(struct cred *new, const struct cred *old, return 0; } -/* - * commit new credentials - */ -static void selinux_cred_commit(struct cred *new, const struct cred *old) -{ - secondary_ops->cred_commit(new, old); -} - /* * set the security data for a kernel service * - all the creation contexts are set to unlabelled @@ -5610,7 +5602,6 @@ static struct security_operations selinux_ops = { .task_create = selinux_task_create, .cred_free = selinux_cred_free, .cred_prepare = selinux_cred_prepare, - .cred_commit = selinux_cred_commit, .kernel_act_as = selinux_kernel_act_as, .kernel_create_files_as = selinux_kernel_create_files_as, .task_setuid = selinux_task_setuid, -- GitLab From ef76e748faa823a738d632ee4c8ed9adaabc8a40 Mon Sep 17 00:00:00 2001 From: James Morris Date: Thu, 29 Jan 2009 12:30:28 +1100 Subject: [PATCH 0993/4982] selinux: remove secondary ops call to task_setrlimit Remove secondary ops call to task_setrlimit, which is a noop in capabilities. Acked-by: Serge Hallyn Acked-by: Eric Paris Signed-off-by: James Morris --- security/selinux/hooks.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index afccada1f26..3aaa63cc5c7 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3367,11 +3367,6 @@ static int selinux_task_getioprio(struct task_struct *p) static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim) { struct rlimit *old_rlim = current->signal->rlim + resource; - int rc; - - rc = secondary_ops->task_setrlimit(resource, new_rlim); - if (rc) - return rc; /* Control the ability to change the hard limit (whether lowering or raising it), so that the hard limit can -- GitLab From 2cbbd19812b7636c1c37bcf50c403e7af5278d73 Mon Sep 17 00:00:00 2001 From: James Morris Date: Thu, 29 Jan 2009 12:32:50 +1100 Subject: [PATCH 0994/4982] selinux: remove secondary ops call to task_kill Remove secondary ops call to task_kill, which is a noop in capabilities. Acked-by: Serge Hallyn Acked-by: Eric Paris Signed-off-by: James Morris --- security/selinux/hooks.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 3aaa63cc5c7..0bd36a17587 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3405,10 +3405,6 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info, u32 perm; int rc; - rc = secondary_ops->task_kill(p, info, sig, secid); - if (rc) - return rc; - if (!sig) perm = PROCESS__SIGNULL; /* null signal; existence test */ else -- GitLab From 5c4054ccfafb6a446e9b65c524af1741656c6c60 Mon Sep 17 00:00:00 2001 From: James Morris Date: Thu, 29 Jan 2009 12:34:53 +1100 Subject: [PATCH 0995/4982] selinux: remove secondary ops call to unix_stream_connect Remove secondary ops call to unix_stream_connect, which is a noop in capabilities. Acked-by: Serge Hallyn Acked-by: Eric Paris Signed-off-by: James Morris --- security/selinux/hooks.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 0bd36a17587..25198e9896f 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3997,10 +3997,6 @@ static int selinux_socket_unix_stream_connect(struct socket *sock, struct avc_audit_data ad; int err; - err = secondary_ops->unix_stream_connect(sock, other, newsk); - if (err) - return err; - isec = SOCK_INODE(sock)->i_security; other_isec = SOCK_INODE(other)->i_security; -- GitLab From 95c14904b6f6f8a35365f0c58d530c85b4fb96b4 Mon Sep 17 00:00:00 2001 From: James Morris Date: Thu, 29 Jan 2009 12:37:58 +1100 Subject: [PATCH 0996/4982] selinux: remove secondary ops call to shm_shmat Remove secondary ops call to shm_shmat, which is a noop in capabilities. Acked-by: Serge Hallyn Acked-by: Eric Paris Signed-off-by: James Morris --- security/selinux/hooks.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 25198e9896f..d9604794a4d 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -5113,11 +5113,6 @@ static int selinux_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, int shmflg) { u32 perms; - int rc; - - rc = secondary_ops->shm_shmat(shp, shmaddr, shmflg); - if (rc) - return rc; if (shmflg & SHM_RDONLY) perms = SHM__READ; -- GitLab From 4272ebfbefd0db40073f3ee5990bceaf2894f08b Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 29 Jan 2009 15:14:46 -0800 Subject: [PATCH 0997/4982] x86: allow more than 8 cpus to be used on 32-bit X86_PC is the only remaining 'sub' architecture, so we dont need it anymore. This also cleans up a few spurious references to X86_PC in the driver space - those certainly should be X86. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 6 +----- arch/x86/configs/i386_defconfig | 1 - arch/x86/configs/x86_64_defconfig | 1 - arch/x86/kernel/smpboot.c | 2 +- drivers/eisa/Kconfig | 6 +++--- drivers/input/keyboard/Kconfig | 4 ++-- drivers/input/mouse/Kconfig | 2 +- drivers/mtd/nand/Kconfig | 2 +- sound/drivers/Kconfig | 2 +- 9 files changed, 10 insertions(+), 16 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 5bf0e0c5828..afaf2cb7c1a 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -262,9 +262,6 @@ config X86_MPPARSE For old smp systems that do not have proper acpi support. Newer systems (esp with 64bit cpus) with acpi support, MADT and DSDT will override it -config X86_PC - def_bool y - config X86_NON_STANDARD bool "Support for non-standard x86 platforms" help @@ -1019,7 +1016,6 @@ config NUMA bool "Numa Memory Allocation and Scheduler Support" depends on SMP depends on X86_64 || (X86_32 && HIGHMEM64G && (X86_NUMAQ || X86_BIGSMP || X86_SUMMIT && ACPI) && EXPERIMENTAL) - default n if X86_PC default y if (X86_NUMAQ || X86_SUMMIT || X86_BIGSMP) help Enable NUMA (Non Uniform Memory Access) support. @@ -1122,7 +1118,7 @@ config ARCH_SPARSEMEM_DEFAULT config ARCH_SPARSEMEM_ENABLE def_bool y - depends on X86_64 || NUMA || (EXPERIMENTAL && X86_PC) || X86_32_NON_STANDARD + depends on X86_64 || NUMA || (EXPERIMENTAL && X86_32) || X86_32_NON_STANDARD select SPARSEMEM_STATIC if X86_32 select SPARSEMEM_VMEMMAP_ENABLE if X86_64 diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig index edba00d98ac..739bce993b5 100644 --- a/arch/x86/configs/i386_defconfig +++ b/arch/x86/configs/i386_defconfig @@ -188,7 +188,6 @@ CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_SMP=y CONFIG_X86_FIND_SMP_CONFIG=y CONFIG_X86_MPPARSE=y -CONFIG_X86_PC=y # CONFIG_X86_ELAN is not set # CONFIG_X86_VOYAGER is not set # CONFIG_X86_GENERICARCH is not set diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig index 322dd2748fc..02b514e8f4c 100644 --- a/arch/x86/configs/x86_64_defconfig +++ b/arch/x86/configs/x86_64_defconfig @@ -187,7 +187,6 @@ CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_SMP=y CONFIG_X86_FIND_SMP_CONFIG=y CONFIG_X86_MPPARSE=y -CONFIG_X86_PC=y # CONFIG_X86_ELAN is not set # CONFIG_X86_VOYAGER is not set # CONFIG_X86_GENERICARCH is not set diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index fc80bc18943..2912fa3a8ef 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1000,7 +1000,7 @@ static int __init smp_sanity_check(unsigned max_cpus) { preempt_disable(); -#if defined(CONFIG_X86_PC) && defined(CONFIG_X86_32) +#ifndef CONFIG_X86_BIGSMP if (def_to_bigsmp && nr_cpu_ids > 8) { unsigned int cpu; unsigned nr; diff --git a/drivers/eisa/Kconfig b/drivers/eisa/Kconfig index c0646576cf4..2705284f622 100644 --- a/drivers/eisa/Kconfig +++ b/drivers/eisa/Kconfig @@ -3,7 +3,7 @@ # config EISA_VLB_PRIMING bool "Vesa Local Bus priming" - depends on X86_PC && EISA + depends on X86 && EISA default n ---help--- Activate this option if your system contains a Vesa Local @@ -24,11 +24,11 @@ config EISA_PCI_EISA When in doubt, say Y. # Using EISA_VIRTUAL_ROOT on something other than an Alpha or -# an X86_PC may lead to crashes... +# an X86 may lead to crashes... config EISA_VIRTUAL_ROOT bool "EISA virtual root device" - depends on EISA && (ALPHA || X86_PC) + depends on EISA && (ALPHA || X86) default y ---help--- Activate this option if your system only have EISA bus diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 35561689ff3..ea2638b4198 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -13,11 +13,11 @@ menuconfig INPUT_KEYBOARD if INPUT_KEYBOARD config KEYBOARD_ATKBD - tristate "AT keyboard" if EMBEDDED || !X86_PC + tristate "AT keyboard" if EMBEDDED || !X86 default y select SERIO select SERIO_LIBPS2 - select SERIO_I8042 if X86_PC + select SERIO_I8042 if X86 select SERIO_GSCPS2 if GSC help Say Y here if you want to use a standard AT or PS/2 keyboard. Usually diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 093c8c1bca7..9bef935ef19 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -17,7 +17,7 @@ config MOUSE_PS2 default y select SERIO select SERIO_LIBPS2 - select SERIO_I8042 if X86_PC + select SERIO_I8042 if X86 select SERIO_GSCPS2 if GSC help Say Y here if you have a PS/2 mouse connected to your system. This diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 928923665f6..2ff88791ceb 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -273,7 +273,7 @@ config MTD_NAND_CAFE config MTD_NAND_CS553X tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)" - depends on X86_32 && (X86_PC || X86_32_NON_STANDARD) + depends on X86_32 help The CS553x companion chips for the AMD Geode processor include NAND flash controllers with built-in hardware ECC diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig index 0bcf14640fd..84714a65e5c 100644 --- a/sound/drivers/Kconfig +++ b/sound/drivers/Kconfig @@ -33,7 +33,7 @@ if SND_DRIVERS config SND_PCSP tristate "PC-Speaker support (READ HELP!)" - depends on PCSPKR_PLATFORM && X86_PC && HIGH_RES_TIMERS + depends on PCSPKR_PLATFORM && X86 && HIGH_RES_TIMERS depends on INPUT depends on EXPERIMENTAL select SND_PCM -- GitLab From 5d0d9be8ef456afc6c3fb5f8aad06ef19b704b05 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 29 Jan 2009 14:19:48 +0000 Subject: [PATCH 0998/4982] gro: Move common completion code into helpers Currently VLAN still has a bit of common code handling the aftermath of GRO that's shared with the common path. This patch moves them into shared helpers to reduce code duplication. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- include/linux/netdevice.h | 3 ++ net/8021q/vlan_core.c | 39 +++----------------- net/core/dev.c | 76 ++++++++++++++++++++++++++------------- 3 files changed, 59 insertions(+), 59 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index dd8a35b3e8b..20419508eec 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1375,12 +1375,15 @@ extern int netif_receive_skb(struct sk_buff *skb); extern void napi_gro_flush(struct napi_struct *napi); extern int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb); +extern int napi_skb_finish(int ret, struct sk_buff *skb); extern int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb); extern void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb); extern struct sk_buff * napi_fraginfo_skb(struct napi_struct *napi, struct napi_gro_fraginfo *info); +extern int napi_frags_finish(struct napi_struct *napi, + struct sk_buff *skb, int ret); extern int napi_gro_frags(struct napi_struct *napi, struct napi_gro_fraginfo *info); extern void netif_nit_deliver(struct sk_buff *skb); diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index e9db889d622..2eb057a7465 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -98,22 +98,7 @@ drop: int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, unsigned int vlan_tci, struct sk_buff *skb) { - int err = NET_RX_SUCCESS; - - switch (vlan_gro_common(napi, grp, vlan_tci, skb)) { - case -1: - return netif_receive_skb(skb); - - case 2: - err = NET_RX_DROP; - /* fall through */ - - case 1: - kfree_skb(skb); - break; - } - - return err; + return napi_skb_finish(vlan_gro_common(napi, grp, vlan_tci, skb), skb); } EXPORT_SYMBOL(vlan_gro_receive); @@ -121,27 +106,11 @@ int vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, unsigned int vlan_tci, struct napi_gro_fraginfo *info) { struct sk_buff *skb = napi_fraginfo_skb(napi, info); - int err = NET_RX_DROP; if (!skb) - goto out; - - err = NET_RX_SUCCESS; - - switch (vlan_gro_common(napi, grp, vlan_tci, skb)) { - case -1: - return netif_receive_skb(skb); - - case 2: - err = NET_RX_DROP; - /* fall through */ - - case 1: - napi_reuse_skb(napi, skb); - break; - } + return NET_RX_DROP; -out: - return err; + return napi_frags_finish(napi, skb, + vlan_gro_common(napi, grp, vlan_tci, skb)); } EXPORT_SYMBOL(vlan_gro_frags); diff --git a/net/core/dev.c b/net/core/dev.c index e61b95c11fc..cd23ae15a1d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -135,6 +135,14 @@ /* This should be increased if a protocol with a bigger head is added. */ #define GRO_MAX_HEAD (MAX_HEADER + 128) +enum { + GRO_MERGED, + GRO_MERGED_FREE, + GRO_HELD, + GRO_NORMAL, + GRO_DROP, +}; + /* * The list of packet types we will receive (as opposed to discard) * and the routines to invoke. @@ -2369,7 +2377,7 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) int count = 0; int same_flow; int mac_len; - int free; + int ret; if (!(skb->dev->features & NETIF_F_GRO)) goto normal; @@ -2412,7 +2420,7 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) goto normal; same_flow = NAPI_GRO_CB(skb)->same_flow; - free = NAPI_GRO_CB(skb)->free; + ret = NAPI_GRO_CB(skb)->free ? GRO_MERGED_FREE : GRO_MERGED; if (pp) { struct sk_buff *nskb = *pp; @@ -2435,12 +2443,13 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) skb_shinfo(skb)->gso_size = skb->len; skb->next = napi->gro_list; napi->gro_list = skb; + ret = GRO_HELD; ok: - return free; + return ret; normal: - return -1; + return GRO_NORMAL; } EXPORT_SYMBOL(dev_gro_receive); @@ -2456,18 +2465,30 @@ static int __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) return dev_gro_receive(napi, skb); } -int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) +int napi_skb_finish(int ret, struct sk_buff *skb) { - switch (__napi_gro_receive(napi, skb)) { - case -1: + int err = NET_RX_SUCCESS; + + switch (ret) { + case GRO_NORMAL: return netif_receive_skb(skb); - case 1: + case GRO_DROP: + err = NET_RX_DROP; + /* fall through */ + + case GRO_MERGED_FREE: kfree_skb(skb); break; } - return NET_RX_SUCCESS; + return err; +} +EXPORT_SYMBOL(napi_skb_finish); + +int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) +{ + return napi_skb_finish(__napi_gro_receive(napi, skb), skb); } EXPORT_SYMBOL(napi_gro_receive); @@ -2520,29 +2541,36 @@ out: } EXPORT_SYMBOL(napi_fraginfo_skb); -int napi_gro_frags(struct napi_struct *napi, struct napi_gro_fraginfo *info) +int napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb, int ret) { - struct sk_buff *skb = napi_fraginfo_skb(napi, info); - int err = NET_RX_DROP; - - if (!skb) - goto out; + int err = NET_RX_SUCCESS; - err = NET_RX_SUCCESS; - - switch (__napi_gro_receive(napi, skb)) { - case -1: + switch (ret) { + case GRO_NORMAL: return netif_receive_skb(skb); - case 0: - goto out; - } + case GRO_DROP: + err = NET_RX_DROP; + /* fall through */ - napi_reuse_skb(napi, skb); + case GRO_MERGED_FREE: + napi_reuse_skb(napi, skb); + break; + } -out: return err; } +EXPORT_SYMBOL(napi_frags_finish); + +int napi_gro_frags(struct napi_struct *napi, struct napi_gro_fraginfo *info) +{ + struct sk_buff *skb = napi_fraginfo_skb(napi, info); + + if (!skb) + return NET_RX_DROP; + + return napi_frags_finish(napi, skb, __napi_gro_receive(napi, skb)); +} EXPORT_SYMBOL(napi_gro_frags); static int process_backlog(struct napi_struct *napi, int quota) -- GitLab From 86911732d3996a9da07914b280621450111bb6da Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 29 Jan 2009 14:19:50 +0000 Subject: [PATCH 0999/4982] gro: Avoid copying headers of unmerged packets Unfortunately simplicity isn't always the best. The fraginfo interface turned out to be suboptimal. The problem was quite obvious. For every packet, we have to copy the headers from the frags structure into skb->head, even though for 99% of the packets this part is immediately thrown away after the merge. LRO didn't have this problem because it directly read the headers from the frags structure. This patch attempts to address this by creating an interface that allows GRO to access the headers in the first frag without having to copy it. Because all drivers that use frags place the headers in the first frag this optimisation should be enough. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- include/linux/netdevice.h | 26 +++++++++++++++ include/linux/skbuff.h | 2 -- net/8021q/vlan_core.c | 2 ++ net/core/dev.c | 70 +++++++++++++++++++++++++++++++++------ net/core/skbuff.c | 23 ++++++++----- net/ipv4/af_inet.c | 10 +++--- net/ipv4/tcp.c | 16 ++++----- net/ipv4/tcp_ipv4.c | 2 +- net/ipv6/af_inet6.c | 30 +++++++++++------ net/ipv6/tcp_ipv6.c | 2 +- 10 files changed, 137 insertions(+), 46 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 20419508eec..7a5057fbb7c 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -984,6 +984,9 @@ void netif_napi_add(struct net_device *dev, struct napi_struct *napi, void netif_napi_del(struct napi_struct *napi); struct napi_gro_cb { + /* This indicates where we are processing relative to skb->data. */ + int data_offset; + /* This is non-zero if the packet may be of the same flow. */ int same_flow; @@ -1087,6 +1090,29 @@ extern int dev_restart(struct net_device *dev); #ifdef CONFIG_NETPOLL_TRAP extern int netpoll_trap(void); #endif +extern void *skb_gro_header(struct sk_buff *skb, unsigned int hlen); +extern int skb_gro_receive(struct sk_buff **head, + struct sk_buff *skb); + +static inline unsigned int skb_gro_offset(const struct sk_buff *skb) +{ + return NAPI_GRO_CB(skb)->data_offset; +} + +static inline unsigned int skb_gro_len(const struct sk_buff *skb) +{ + return skb->len - NAPI_GRO_CB(skb)->data_offset; +} + +static inline void skb_gro_pull(struct sk_buff *skb, unsigned int len) +{ + NAPI_GRO_CB(skb)->data_offset += len; +} + +static inline void skb_gro_reset_offset(struct sk_buff *skb) +{ + NAPI_GRO_CB(skb)->data_offset = 0; +} static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index a2c2378a9c5..08670d01747 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1687,8 +1687,6 @@ extern int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen); extern struct sk_buff *skb_segment(struct sk_buff *skb, int features); -extern int skb_gro_receive(struct sk_buff **head, - struct sk_buff *skb); static inline void *skb_header_pointer(const struct sk_buff *skb, int offset, int len, void *buffer) diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 2eb057a7465..378fa69d625 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -98,6 +98,8 @@ drop: int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, unsigned int vlan_tci, struct sk_buff *skb) { + skb_gro_reset_offset(skb); + return napi_skb_finish(vlan_gro_common(napi, grp, vlan_tci, skb), skb); } EXPORT_SYMBOL(vlan_gro_receive); diff --git a/net/core/dev.c b/net/core/dev.c index cd23ae15a1d..df406dcf748 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -215,6 +215,13 @@ static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex) return &net->dev_index_head[ifindex & ((1 << NETDEV_HASHBITS) - 1)]; } +static inline void *skb_gro_mac_header(struct sk_buff *skb) +{ + return skb_headlen(skb) ? skb_mac_header(skb) : + page_address(skb_shinfo(skb)->frags[0].page) + + skb_shinfo(skb)->frags[0].page_offset; +} + /* Device list insertion */ static int list_netdevice(struct net_device *dev) { @@ -2350,7 +2357,6 @@ static int napi_gro_complete(struct sk_buff *skb) out: skb_shinfo(skb)->gso_size = 0; - __skb_push(skb, -skb_network_offset(skb)); return netif_receive_skb(skb); } @@ -2368,6 +2374,25 @@ void napi_gro_flush(struct napi_struct *napi) } EXPORT_SYMBOL(napi_gro_flush); +void *skb_gro_header(struct sk_buff *skb, unsigned int hlen) +{ + unsigned int offset = skb_gro_offset(skb); + + hlen += offset; + if (hlen <= skb_headlen(skb)) + return skb->data + offset; + + if (unlikely(!skb_shinfo(skb)->nr_frags || + skb_shinfo(skb)->frags[0].size <= + hlen - skb_headlen(skb) || + PageHighMem(skb_shinfo(skb)->frags[0].page))) + return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL; + + return page_address(skb_shinfo(skb)->frags[0].page) + + skb_shinfo(skb)->frags[0].page_offset + offset; +} +EXPORT_SYMBOL(skb_gro_header); + int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) { struct sk_buff **pp = NULL; @@ -2388,11 +2413,13 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) rcu_read_lock(); list_for_each_entry_rcu(ptype, head, list) { struct sk_buff *p; + void *mac; if (ptype->type != type || ptype->dev || !ptype->gro_receive) continue; - skb_reset_network_header(skb); + skb_set_network_header(skb, skb_gro_offset(skb)); + mac = skb_gro_mac_header(skb); mac_len = skb->network_header - skb->mac_header; skb->mac_len = mac_len; NAPI_GRO_CB(skb)->same_flow = 0; @@ -2406,8 +2433,7 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) continue; if (p->mac_len != mac_len || - memcmp(skb_mac_header(p), skb_mac_header(skb), - mac_len)) + memcmp(skb_mac_header(p), mac, mac_len)) NAPI_GRO_CB(p)->same_flow = 0; } @@ -2434,13 +2460,11 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) if (same_flow) goto ok; - if (NAPI_GRO_CB(skb)->flush || count >= MAX_GRO_SKBS) { - __skb_push(skb, -skb_network_offset(skb)); + if (NAPI_GRO_CB(skb)->flush || count >= MAX_GRO_SKBS) goto normal; - } NAPI_GRO_CB(skb)->count = 1; - skb_shinfo(skb)->gso_size = skb->len; + skb_shinfo(skb)->gso_size = skb_gro_len(skb); skb->next = napi->gro_list; napi->gro_list = skb; ret = GRO_HELD; @@ -2488,6 +2512,8 @@ EXPORT_SYMBOL(napi_skb_finish); int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) { + skb_gro_reset_offset(skb); + return napi_skb_finish(__napi_gro_receive(napi, skb), skb); } EXPORT_SYMBOL(napi_gro_receive); @@ -2506,6 +2532,7 @@ struct sk_buff *napi_fraginfo_skb(struct napi_struct *napi, { struct net_device *dev = napi->dev; struct sk_buff *skb = napi->skb; + struct ethhdr *eth; napi->skb = NULL; @@ -2525,13 +2552,23 @@ struct sk_buff *napi_fraginfo_skb(struct napi_struct *napi, skb->len += info->len; skb->truesize += info->len; - if (!pskb_may_pull(skb, ETH_HLEN)) { + skb_reset_mac_header(skb); + skb_gro_reset_offset(skb); + + eth = skb_gro_header(skb, sizeof(*eth)); + if (!eth) { napi_reuse_skb(napi, skb); skb = NULL; goto out; } - skb->protocol = eth_type_trans(skb, dev); + skb_gro_pull(skb, sizeof(*eth)); + + /* + * This works because the only protocols we care about don't require + * special handling. We'll fix it up properly at the end. + */ + skb->protocol = eth->h_proto; skb->ip_summed = info->ip_summed; skb->csum = info->csum; @@ -2544,10 +2581,21 @@ EXPORT_SYMBOL(napi_fraginfo_skb); int napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb, int ret) { int err = NET_RX_SUCCESS; + int may; switch (ret) { case GRO_NORMAL: - return netif_receive_skb(skb); + case GRO_HELD: + may = pskb_may_pull(skb, skb_gro_offset(skb)); + BUG_ON(!may); + + skb->protocol = eth_type_trans(skb, napi->dev); + + if (ret == GRO_NORMAL) + return netif_receive_skb(skb); + + skb_gro_pull(skb, -ETH_HLEN); + break; case GRO_DROP: err = NET_RX_DROP; diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 2e5f2ca3bdc..f9f4065a7e9 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2584,17 +2584,21 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) struct sk_buff *p = *head; struct sk_buff *nskb; unsigned int headroom; - unsigned int hlen = p->data - skb_mac_header(p); - unsigned int len = skb->len; + unsigned int len = skb_gro_len(skb); - if (hlen + p->len + len >= 65536) + if (p->len + len >= 65536) return -E2BIG; if (skb_shinfo(p)->frag_list) goto merge; - else if (!skb_headlen(p) && !skb_headlen(skb) && - skb_shinfo(p)->nr_frags + skb_shinfo(skb)->nr_frags < + else if (skb_headlen(skb) <= skb_gro_offset(skb) && + skb_shinfo(p)->nr_frags + skb_shinfo(skb)->nr_frags <= MAX_SKB_FRAGS) { + skb_shinfo(skb)->frags[0].page_offset += + skb_gro_offset(skb) - skb_headlen(skb); + skb_shinfo(skb)->frags[0].size -= + skb_gro_offset(skb) - skb_headlen(skb); + memcpy(skb_shinfo(p)->frags + skb_shinfo(p)->nr_frags, skb_shinfo(skb)->frags, skb_shinfo(skb)->nr_frags * sizeof(skb_frag_t)); @@ -2611,7 +2615,7 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) } headroom = skb_headroom(p); - nskb = netdev_alloc_skb(p->dev, headroom); + nskb = netdev_alloc_skb(p->dev, headroom + skb_gro_offset(p)); if (unlikely(!nskb)) return -ENOMEM; @@ -2619,12 +2623,15 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) nskb->mac_len = p->mac_len; skb_reserve(nskb, headroom); + __skb_put(nskb, skb_gro_offset(p)); - skb_set_mac_header(nskb, -hlen); + skb_set_mac_header(nskb, skb_mac_header(p) - p->data); skb_set_network_header(nskb, skb_network_offset(p)); skb_set_transport_header(nskb, skb_transport_offset(p)); - memcpy(skb_mac_header(nskb), skb_mac_header(p), hlen); + __skb_pull(p, skb_gro_offset(p)); + memcpy(skb_mac_header(nskb), skb_mac_header(p), + p->data - skb_mac_header(p)); *NAPI_GRO_CB(nskb) = *NAPI_GRO_CB(p); skb_shinfo(nskb)->frag_list = p; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 743f5542d65..d6770f295d5 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1253,10 +1253,10 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, int proto; int id; - if (unlikely(!pskb_may_pull(skb, sizeof(*iph)))) + iph = skb_gro_header(skb, sizeof(*iph)); + if (unlikely(!iph)) goto out; - iph = ip_hdr(skb); proto = iph->protocol & (MAX_INET_PROTOS - 1); rcu_read_lock(); @@ -1270,7 +1270,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) goto out_unlock; - flush = ntohs(iph->tot_len) != skb->len || + flush = ntohs(iph->tot_len) != skb_gro_len(skb) || iph->frag_off != htons(IP_DF); id = ntohs(iph->id); @@ -1298,8 +1298,8 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, } NAPI_GRO_CB(skb)->flush |= flush; - __skb_pull(skb, sizeof(*iph)); - skb_reset_transport_header(skb); + skb_gro_pull(skb, sizeof(*iph)); + skb_set_transport_header(skb, skb_gro_offset(skb)); pp = ops->gro_receive(head, skb); diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 0cd71b84e48..1cd60825394 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2481,19 +2481,19 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) unsigned int mss = 1; int flush = 1; - if (!pskb_may_pull(skb, sizeof(*th))) + th = skb_gro_header(skb, sizeof(*th)); + if (unlikely(!th)) goto out; - th = tcp_hdr(skb); thlen = th->doff * 4; if (thlen < sizeof(*th)) goto out; - if (!pskb_may_pull(skb, thlen)) + th = skb_gro_header(skb, thlen); + if (unlikely(!th)) goto out; - th = tcp_hdr(skb); - __skb_pull(skb, thlen); + skb_gro_pull(skb, thlen); flags = tcp_flag_word(th); @@ -2521,10 +2521,10 @@ found: flush |= th->ack_seq != th2->ack_seq || th->window != th2->window; flush |= memcmp(th + 1, th2 + 1, thlen - sizeof(*th)); - total = p->len; + total = skb_gro_len(p); mss = skb_shinfo(p)->gso_size; - flush |= skb->len > mss || skb->len <= 0; + flush |= skb_gro_len(skb) > mss || !skb_gro_len(skb); flush |= ntohl(th2->seq) + total != ntohl(th->seq); if (flush || skb_gro_receive(head, skb)) { @@ -2537,7 +2537,7 @@ found: tcp_flag_word(th2) |= flags & (TCP_FLAG_FIN | TCP_FLAG_PSH); out_check_final: - flush = skb->len < mss; + flush = skb_gro_len(skb) < mss; flush |= flags & (TCP_FLAG_URG | TCP_FLAG_PSH | TCP_FLAG_RST | TCP_FLAG_SYN | TCP_FLAG_FIN); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 19d7b429a26..f6b962f56ab 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2355,7 +2355,7 @@ struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb) switch (skb->ip_summed) { case CHECKSUM_COMPLETE: - if (!tcp_v4_check(skb->len, iph->saddr, iph->daddr, + if (!tcp_v4_check(skb_gro_len(skb), iph->saddr, iph->daddr, skb->csum)) { skb->ip_summed = CHECKSUM_UNNECESSARY; break; diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index c802bc1658a..bd91eadcbe3 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -799,24 +799,34 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, int proto; __wsum csum; - if (unlikely(!pskb_may_pull(skb, sizeof(*iph)))) + iph = skb_gro_header(skb, sizeof(*iph)); + if (unlikely(!iph)) goto out; - iph = ipv6_hdr(skb); - __skb_pull(skb, sizeof(*iph)); + skb_gro_pull(skb, sizeof(*iph)); + skb_set_transport_header(skb, skb_gro_offset(skb)); - flush += ntohs(iph->payload_len) != skb->len; + flush += ntohs(iph->payload_len) != skb_gro_len(skb); rcu_read_lock(); - proto = ipv6_gso_pull_exthdrs(skb, iph->nexthdr); - iph = ipv6_hdr(skb); - IPV6_GRO_CB(skb)->proto = proto; + proto = iph->nexthdr; ops = rcu_dereference(inet6_protos[proto]); - if (!ops || !ops->gro_receive) - goto out_unlock; + if (!ops || !ops->gro_receive) { + __pskb_pull(skb, skb_gro_offset(skb)); + proto = ipv6_gso_pull_exthdrs(skb, proto); + skb_gro_pull(skb, -skb_transport_offset(skb)); + skb_reset_transport_header(skb); + __skb_push(skb, skb_gro_offset(skb)); + + if (!ops || !ops->gro_receive) + goto out_unlock; + + iph = ipv6_hdr(skb); + } + + IPV6_GRO_CB(skb)->proto = proto; flush--; - skb_reset_transport_header(skb); nlen = skb_network_header_len(skb); for (p = *head; p; p = p->next) { diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index e5b85d45bee..00f1269e11e 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -948,7 +948,7 @@ struct sk_buff **tcp6_gro_receive(struct sk_buff **head, struct sk_buff *skb) switch (skb->ip_summed) { case CHECKSUM_COMPLETE: - if (!tcp_v6_check(skb->len, &iph->saddr, &iph->daddr, + if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr, skb->csum)) { skb->ip_summed = CHECKSUM_UNNECESSARY; break; -- GitLab From 81705ad1b2f926d2ef15ed95074a9c1fa9fb4dc4 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 29 Jan 2009 14:19:51 +0000 Subject: [PATCH 1000/4982] gro: Do not merge paged packets into frag_list gro: Do not merge paged packets into frag_list Bigger is not always better :) It was easy to continue to merged packets into frag_list after the page array is full. However, this turns out to be worse than LRO because frag_list is a much less efficient form of storage than the page array. So we're better off stopping the merge and starting a new entry with an empty page array. In future we can optimise this further by doing frag_list merging but making sure that we continue to fill in the page array. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/core/skbuff.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index f9f4065a7e9..d386f1082eb 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2591,9 +2591,11 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) if (skb_shinfo(p)->frag_list) goto merge; - else if (skb_headlen(skb) <= skb_gro_offset(skb) && - skb_shinfo(p)->nr_frags + skb_shinfo(skb)->nr_frags <= - MAX_SKB_FRAGS) { + else if (skb_headlen(skb) <= skb_gro_offset(skb)) { + if (skb_shinfo(p)->nr_frags + skb_shinfo(skb)->nr_frags > + MAX_SKB_FRAGS) + return -E2BIG; + skb_shinfo(skb)->frags[0].page_offset += skb_gro_offset(skb) - skb_headlen(skb); skb_shinfo(skb)->frags[0].size -= -- GitLab From 80595d59ba9917227856e663da249c2276a8628d Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 29 Jan 2009 14:19:52 +0000 Subject: [PATCH 1001/4982] gro: Open-code memcpy in napi_fraginfo_skb This patch optimises napi_fraginfo_skb to only copy the bits necessary. We also open-code the memcpy so that the alignment information is always available to gcc. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/core/dev.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index df406dcf748..ec5be1c7f2f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2533,6 +2533,8 @@ struct sk_buff *napi_fraginfo_skb(struct napi_struct *napi, struct net_device *dev = napi->dev; struct sk_buff *skb = napi->skb; struct ethhdr *eth; + skb_frag_t *frag; + int i; napi->skb = NULL; @@ -2545,8 +2547,14 @@ struct sk_buff *napi_fraginfo_skb(struct napi_struct *napi, } BUG_ON(info->nr_frags > MAX_SKB_FRAGS); + frag = &info->frags[info->nr_frags - 1]; + + for (i = skb_shinfo(skb)->nr_frags; i < info->nr_frags; i++) { + skb_fill_page_desc(skb, i, frag->page, frag->page_offset, + frag->size); + frag++; + } skb_shinfo(skb)->nr_frags = info->nr_frags; - memcpy(skb_shinfo(skb)->frags, info->frags, sizeof(info->frags)); skb->data_len = info->len; skb->len += info->len; -- GitLab From 754ef0cd65faac4840ada4362bda322d9a811fbf Mon Sep 17 00:00:00 2001 From: Yasuaki Ishimatsu Date: Wed, 28 Jan 2009 12:51:09 +0900 Subject: [PATCH 1002/4982] x86: fix debug message of CPU clock speed Impact: Fixes incorrect printk LOCAL APIC is corrected by PM-Timer, when SMI occurred while LOCAL APIC is calibrated. In this case, LOCAL APIC debug message(Boot with apic=debug) is displayed correctly, however, CPU clock speed debug message is displayed wrongly . When SMI occured on my machine, which has 1.6GHz CPU, CPU clock speed is displayed 3622.0205 MHz as follow. CPU0: Intel(R) Xeon(R) CPU 5110 @ 1.60GHz stepping 06 Using local APIC timer interrupts. calibrating APIC timer ... ... lapic delta = 3773130 ... PM timer delta = 812434 APIC calibration not consistent with PM Timer: 226ms instead of 100ms APIC delta adjusted to PM-Timer: 1662420 (3773130) ..... delta 1662420 ..... mult: 71411249 ..... calibration result: 265987 ..... CPU clock speed is 3622.0205 MHz. =====> here ..... host bus clock speed is 265.0987 MHz. This patch fixes to displaying CPU clock speed correctly as follow. CPU0: Intel(R) Xeon(R) CPU 5110 @ 1.60GHz stepping 06 Using local APIC timer interrupts. calibrating APIC timer ... ... lapic delta = 3773131 ... PM timer delta = 812434 APIC calibration not consistent with PM Timer: 226ms instead of 100ms APIC delta adjusted to PM-Timer: 1662420 (3773131) TSC delta adjusted to PM-Timer: 159592409 (362220564) ..... delta 1662420 ..... mult: 71411249 ..... calibration result: 265987 ..... CPU clock speed is 1595.0924 MHz. ..... host bus clock speed is 265.0987 MHz. Signed-off-by: Yasuaki Ishimatsu Signed-off-by: H. Peter Anvin --- arch/x86/kernel/apic.c | 47 +++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 4b6df2469fe..7bcd746d704 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -535,7 +535,8 @@ static void __init lapic_cal_handler(struct clock_event_device *dev) } } -static int __init calibrate_by_pmtimer(long deltapm, long *delta) +static int __init +calibrate_by_pmtimer(long deltapm, long *delta, long *deltatsc) { const long pm_100ms = PMTMR_TICKS_PER_SEC / 10; const long pm_thresh = pm_100ms / 100; @@ -557,18 +558,29 @@ static int __init calibrate_by_pmtimer(long deltapm, long *delta) if (deltapm > (pm_100ms - pm_thresh) && deltapm < (pm_100ms + pm_thresh)) { apic_printk(APIC_VERBOSE, "... PM timer result ok\n"); - } else { - res = (((u64)deltapm) * mult) >> 22; - do_div(res, 1000000); - pr_warning("APIC calibration not consistent " - "with PM Timer: %ldms instead of 100ms\n", - (long)res); - /* Correct the lapic counter value */ - res = (((u64)(*delta)) * pm_100ms); + return 0; + } + + res = (((u64)deltapm) * mult) >> 22; + do_div(res, 1000000); + pr_warning("APIC calibration not consistent " + "with PM Timer: %ldms instead of 100ms\n",(long)res); + + /* Correct the lapic counter value */ + res = (((u64)(*delta)) * pm_100ms); + do_div(res, deltapm); + pr_info("APIC delta adjusted to PM-Timer: " + "%lu (%ld)\n", (unsigned long)res, *delta); + *delta = (long)res; + + /* Correct the tsc counter value */ + if (cpu_has_tsc) { + res = (((u64)(*deltatsc)) * pm_100ms); do_div(res, deltapm); - pr_info("APIC delta adjusted to PM-Timer: " - "%lu (%ld)\n", (unsigned long)res, *delta); - *delta = (long)res; + apic_printk(APIC_VERBOSE, "TSC delta adjusted to " + "PM-Timer: %lu (%ld) \n", + (unsigned long)res, *deltatsc); + *deltatsc = (long)res; } return 0; @@ -579,7 +591,7 @@ static int __init calibrate_APIC_clock(void) struct clock_event_device *levt = &__get_cpu_var(lapic_events); void (*real_handler)(struct clock_event_device *dev); unsigned long deltaj; - long delta; + long delta, deltatsc; int pm_referenced = 0; local_irq_disable(); @@ -609,9 +621,11 @@ static int __init calibrate_APIC_clock(void) delta = lapic_cal_t1 - lapic_cal_t2; apic_printk(APIC_VERBOSE, "... lapic delta = %ld\n", delta); + deltatsc = (long)(lapic_cal_tsc2 - lapic_cal_tsc1); + /* we trust the PM based calibration if possible */ pm_referenced = !calibrate_by_pmtimer(lapic_cal_pm2 - lapic_cal_pm1, - &delta); + &delta, &deltatsc); /* Calculate the scaled math multiplication factor */ lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS, @@ -629,11 +643,10 @@ static int __init calibrate_APIC_clock(void) calibration_result); if (cpu_has_tsc) { - delta = (long)(lapic_cal_tsc2 - lapic_cal_tsc1); apic_printk(APIC_VERBOSE, "..... CPU clock speed is " "%ld.%04ld MHz.\n", - (delta / LAPIC_CAL_LOOPS) / (1000000 / HZ), - (delta / LAPIC_CAL_LOOPS) % (1000000 / HZ)); + (deltatsc / LAPIC_CAL_LOOPS) / (1000000 / HZ), + (deltatsc / LAPIC_CAL_LOOPS) % (1000000 / HZ)); } apic_printk(APIC_VERBOSE, "..... host bus clock speed is " -- GitLab From 39ba5d43fc9133696240fc8b6b13e7a41fea87cd Mon Sep 17 00:00:00 2001 From: Yasuaki Ishimatsu Date: Wed, 28 Jan 2009 12:52:24 +0900 Subject: [PATCH 1003/4982] x86: unify PM-Timer messages Impact: Cleans up printk formatting When LOCAL APIC was calibrated, the debug message is displayed as follows. CPU0: Intel(R) Xeon(R) CPU 5110 @ 1.60GHz stepping 06 Using local APIC timer interrupts. calibrating APIC timer ... ... lapic delta = 3773131 ... PM timer delta = 812434 APIC calibration not consistent with PM Timer: 226ms instead of 100ms APIC delta adjusted to PM-Timer: 1662420 (3773131) TSC delta adjusted to PM-Timer: 159592409 (362220564) ..... delta 1662420 ..... mult: 71411249 ..... calibration result: 265987 ..... CPU clock speed is 1595.0924 MHz. ..... host bus clock speed is 265.0987 MHz. There are three type of PM-Timer (PM-Timer, PM Timer, and PM timer), in this message. This patch unifies those messages to PM-Timer. Signed-off-by: Yasuaki Ishimatsu Signed-off-by: H. Peter Anvin --- arch/x86/kernel/apic.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 7bcd746d704..0d935d218d0 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -547,7 +547,7 @@ calibrate_by_pmtimer(long deltapm, long *delta, long *deltatsc) return -1; #endif - apic_printk(APIC_VERBOSE, "... PM timer delta = %ld\n", deltapm); + apic_printk(APIC_VERBOSE, "... PM-Timer delta = %ld\n", deltapm); /* Check, if the PM timer is available */ if (!deltapm) @@ -557,14 +557,14 @@ calibrate_by_pmtimer(long deltapm, long *delta, long *deltatsc) if (deltapm > (pm_100ms - pm_thresh) && deltapm < (pm_100ms + pm_thresh)) { - apic_printk(APIC_VERBOSE, "... PM timer result ok\n"); + apic_printk(APIC_VERBOSE, "... PM-Timer result ok\n"); return 0; } res = (((u64)deltapm) * mult) >> 22; do_div(res, 1000000); pr_warning("APIC calibration not consistent " - "with PM Timer: %ldms instead of 100ms\n",(long)res); + "with PM-Timer: %ldms instead of 100ms\n",(long)res); /* Correct the lapic counter value */ res = (((u64)(*delta)) * pm_100ms); -- GitLab From cc3657e1f6d552a88307af62f53380503ba0130b Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 30 Jan 2009 14:23:22 +1100 Subject: [PATCH 1004/4982] solos: Add 'reset' module parameter to reset the DSL chips on load Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 21c73b17d5f..c54ecebc9a7 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -70,6 +70,7 @@ #define RX_DMA_SIZE 2048 +static int reset = 0; static int atmdebug = 0; static int firmware_upgrade = 0; static int fpga_upgrade = 0; @@ -131,9 +132,11 @@ MODULE_AUTHOR("Traverse Technologies "); MODULE_DESCRIPTION("Solos PCI driver"); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); +MODULE_PARM_DESC(reset, "Reset Solos chips on startup"); MODULE_PARM_DESC(atmdebug, "Print ATM data"); MODULE_PARM_DESC(firmware_upgrade, "Initiate Solos firmware upgrade"); MODULE_PARM_DESC(fpga_upgrade, "Initiate FPGA upgrade"); +module_param(reset, int, 0444); module_param(atmdebug, int, 0644); module_param(firmware_upgrade, int, 0444); module_param(fpga_upgrade, int, 0444); @@ -1071,6 +1074,13 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) goto out_unmap_config; } + if (reset) { + iowrite32(1, card->config_regs + FPGA_MODE); + data32 = ioread32(card->config_regs + FPGA_MODE); + + iowrite32(0, card->config_regs + FPGA_MODE); + data32 = ioread32(card->config_regs + FPGA_MODE); + } //Fill Config Mem with zeros for(i = 0; i < 128; i += 4) iowrite32(0, card->config_regs + i); -- GitLab From 95852f48c2b78ee6b211a38039ccca2c889a7010 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 30 Jan 2009 14:23:52 +1100 Subject: [PATCH 1005/4982] solos: Tidy up status interrupt handling, cope with 'ERROR' status Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index c54ecebc9a7..f27bd922574 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -340,6 +340,12 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb str = next_string(skb); if (!str) return -EIO; + if (!strcmp(str, "ERROR")) { + dev_dbg(&card->dev->dev, "Status packet indicated Solos error on port %d (starting up?)\n", + port); + return 0; + } + rate_up = simple_strtol(str, &end, 10); if (*end) return -EIO; @@ -362,8 +368,7 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb } if (state == ATM_PHY_SIG_LOST) { - dev_info(&card->dev->dev, "Port %d ATM state: %s\n", - port, state_str); + dev_info(&card->dev->dev, "Port %d: %s\n", port, state_str); } else { char *snr, *attn; @@ -374,7 +379,7 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb if (!attn) return -EIO; - dev_info(&card->dev->dev, "Port %d: %s (%d/%d kb/s%s%s%s%s)\n", + dev_info(&card->dev->dev, "Port %d: %s @%d/%d kb/s%s%s%s%s\n", port, state_str, rate_down/1000, rate_up/1000, snr[0]?", SNR ":"", snr, attn[0]?", Attn ":"", attn); } @@ -663,7 +668,11 @@ void solos_bh(unsigned long card_arg) break; case PKT_STATUS: - process_status(card, port, skb); + if (process_status(card, port, skb) && + net_ratelimit()) { + dev_warn(&card->dev->dev, "Bad status packet of %d bytes on port %d:\n", skb->len, port); + print_buffer(skb); + } dev_kfree_skb_any(skb); break; -- GitLab From cd5549e0f4b5129cdb7b02fbb6a559f78eda7f4c Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 30 Jan 2009 14:26:37 +1100 Subject: [PATCH 1006/4982] solos: Don't clear config registers at startup Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index f27bd922574..df016825519 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -1040,7 +1040,7 @@ static struct atmdev_ops fpga_ops = { static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) { - int err, i; + int err; uint16_t fpga_ver; uint8_t major_ver, minor_ver; uint32_t data32; @@ -1090,10 +1090,6 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) iowrite32(0, card->config_regs + FPGA_MODE); data32 = ioread32(card->config_regs + FPGA_MODE); } - //Fill Config Mem with zeros - for(i = 0; i < 128; i += 4) - iowrite32(0, card->config_regs + i); - //Set RX empty flags iowrite32(0xF0, card->config_regs + FLAGS_ADDR); -- GitLab From eab50f73ca51384d8f17886edc7bbc9969b91c0e Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 30 Jan 2009 14:27:26 +1100 Subject: [PATCH 1007/4982] solos: Set RX empty flag at startup only for !dma mode Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index df016825519..7c26bd2ac11 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -1090,8 +1090,6 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) iowrite32(0, card->config_regs + FPGA_MODE); data32 = ioread32(card->config_regs + FPGA_MODE); } - //Set RX empty flags - iowrite32(0xF0, card->config_regs + FLAGS_ADDR); data32 = ioread32(card->config_regs + FPGA_VER); fpga_ver = (data32 & 0x0000FFFF); @@ -1102,6 +1100,10 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) if (fpga_ver > 27) card->using_dma = 1; + else { + /* Set RX empty flag for all ports */ + iowrite32(0xF0, card->config_regs + FLAGS_ADDR); + } card->nr_ports = 2; /* FIXME: Detect daughterboard */ -- GitLab From f87b2ed225c002ea1b1b9994c6608d8b202f865e Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 30 Jan 2009 14:31:36 +1100 Subject: [PATCH 1008/4982] solos: Swap upstream/downstream rates in status packet, clean up some more Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 51 ++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 7c26bd2ac11..eef920a9c44 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -314,14 +314,16 @@ static char *next_string(struct sk_buff *skb) * for the information therein. Fields are.... * * packet version - * TxBitRate (version >= 1) * RxBitRate (version >= 1) + * TxBitRate (version >= 1) * State (version >= 1) + * LocalSNRMargin (version >= 1) + * LocalLineAttn (version >= 1) */ static int process_status(struct solos_card *card, int port, struct sk_buff *skb) { - char *str, *end, *state_str; - int ver, rate_up, rate_down, state; + char *str, *end, *state_str, *snr, *attn; + int ver, rate_up, rate_down; if (!card->atmdev[port]) return -ENODEV; @@ -346,45 +348,42 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb return 0; } - rate_up = simple_strtol(str, &end, 10); + rate_down = simple_strtol(str, &end, 10); if (*end) return -EIO; str = next_string(skb); if (!str) return -EIO; - rate_down = simple_strtol(str, &end, 10); + rate_up = simple_strtol(str, &end, 10); if (*end) return -EIO; state_str = next_string(skb); if (!state_str) return -EIO; - if (!strcmp(state_str, "Showtime")) - state = ATM_PHY_SIG_FOUND; - else { - state = ATM_PHY_SIG_LOST; + + /* Anything but 'Showtime' is down */ + if (strcmp(state_str, "Showtime")) { + card->atmdev[port]->signal = ATM_PHY_SIG_LOST; release_vccs(card->atmdev[port]); + dev_info(&card->dev->dev, "Port %d: %s\n", port, state_str); + return 0; } - if (state == ATM_PHY_SIG_LOST) { - dev_info(&card->dev->dev, "Port %d: %s\n", port, state_str); - } else { - char *snr, *attn; - - snr = next_string(skb); - if (!str) - return -EIO; - attn = next_string(skb); - if (!attn) - return -EIO; - - dev_info(&card->dev->dev, "Port %d: %s @%d/%d kb/s%s%s%s%s\n", - port, state_str, rate_down/1000, rate_up/1000, - snr[0]?", SNR ":"", snr, attn[0]?", Attn ":"", attn); - } + snr = next_string(skb); + if (!str) + return -EIO; + attn = next_string(skb); + if (!attn) + return -EIO; + + dev_info(&card->dev->dev, "Port %d: %s @%d/%d kb/s%s%s%s%s\n", + port, state_str, rate_down/1000, rate_up/1000, + snr[0]?", SNR ":"", snr, attn[0]?", Attn ":"", attn); + card->atmdev[port]->link_rate = rate_down / 424; - card->atmdev[port]->signal = state; + card->atmdev[port]->signal = ATM_PHY_SIG_FOUND; return 0; } -- GitLab From 04eb093c7c81d118efeb96228f69bc0179f71897 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Thu, 29 Jan 2009 14:28:37 -0600 Subject: [PATCH 1009/4982] ASoC: fix initialization order of the CS4270 codec driver ASoC codec drivers typically serve two masters: the I2C bus and ASoC itself. When a codec driver registers with ASoC, a probe function is called. Most codec drivers call ASoC first, and then register with the I2C bus in the ASoC probe function. However, in order to support multiple codecs on one board, it's easier if the codec driver is probed via the I2C bus first. This is because the call to i2c_add_driver() can result in the I2C probe function being called multiple times - once for each codec. In the current design, the driver registers once with ASoC, and in the ASoC probe function, it calls i2c_add_driver(). The results in the I2C probe function being called multiple times before the driver can register with ASoC again. The new design has the driver call i2c_add_driver() first. In the I2C probe function, the driver registers with ASoC. This allows the ASoC probe function to be called once per I2C device. Also add code to check if the I2C probe function is called more than once, since that is not supported with the current ASoC design. Signed-off-by: Timur Tabi Signed-off-by: Mark Brown --- sound/soc/codecs/cs4270.c | 177 +++++++++++++++++++++----------------- 1 file changed, 97 insertions(+), 80 deletions(-) diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 21253b48289..adc1150ddb0 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -490,21 +490,17 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = { }; /* - * Global variable to store socdev for i2c probe function. + * Global variable to store codec for the ASoC probe function. * * If struct i2c_driver had a private_data field, we wouldn't need to use - * cs4270_socdec. This is the only way to pass the socdev structure to - * cs4270_i2c_probe(). - * - * The real solution to cs4270_socdev is to create a mechanism - * that maps I2C addresses to snd_soc_device structures. Perhaps the - * creation of the snd_soc_device object should be moved out of - * cs4270_probe() and into cs4270_i2c_probe(), but that would make this - * driver dependent on I2C. The CS4270 supports "stand-alone" mode, whereby - * the chip is *not* connected to the I2C bus, but is instead configured via - * input pins. + * cs4270_codec. This is the only way to pass the codec structure from + * cs4270_i2c_probe() to cs4270_probe(). Unfortunately, there is no good + * way to synchronize these two functions. cs4270_i2c_probe() can be called + * multiple times before cs4270_probe() is called even once. So for now, we + * also only allow cs4270_i2c_probe() to be run once. That means that we do + * not support more than one cs4270 device in the system, at least for now. */ -static struct snd_soc_device *cs4270_socdev; +static struct snd_soc_codec *cs4270_codec; struct snd_soc_dai cs4270_dai = { .name = "cs4270", @@ -531,6 +527,70 @@ struct snd_soc_dai cs4270_dai = { }; EXPORT_SYMBOL_GPL(cs4270_dai); +/* + * ASoC probe function + */ +static int cs4270_probe(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = cs4270_codec; + unsigned int i; + int ret; + + /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */ + socdev->card->codec = codec; + + /* Register PCMs */ + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + if (ret < 0) { + printk(KERN_ERR "cs4270: failed to create PCMs\n"); + return ret; + } + + /* Add the non-DAPM controls */ + for (i = 0; i < ARRAY_SIZE(cs4270_snd_controls); i++) { + struct snd_kcontrol *kctrl; + + kctrl = snd_soc_cnew(&cs4270_snd_controls[i], codec, NULL); + if (!kctrl) { + printk(KERN_ERR "cs4270: error creating control '%s'\n", + cs4270_snd_controls[i].name); + ret = -ENOMEM; + goto error_free_pcms; + } + + ret = snd_ctl_add(codec->card, kctrl); + if (ret < 0) { + printk(KERN_ERR "cs4270: error adding control '%s'\n", + cs4270_snd_controls[i].name); + goto error_free_pcms; + } + } + + /* And finally, register the socdev */ + ret = snd_soc_init_card(socdev); + if (ret < 0) { + printk(KERN_ERR "cs4270: failed to register card\n"); + goto error_free_pcms; + } + + return 0; + +error_free_pcms: + snd_soc_free_pcms(socdev); + + return ret; +} + +static int cs4270_remove(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + + snd_soc_free_pcms(socdev); + + return 0; +}; + /* * Initialize the I2C interface of the CS4270 * @@ -543,17 +603,27 @@ EXPORT_SYMBOL_GPL(cs4270_dai); static int cs4270_i2c_probe(struct i2c_client *i2c_client, const struct i2c_device_id *id) { - struct snd_soc_device *socdev = cs4270_socdev; struct snd_soc_codec *codec; struct cs4270_private *cs4270; - int i; - int ret = 0; + int ret; + + /* For now, we only support one cs4270 device in the system. See the + * comment for cs4270_codec. + */ + if (cs4270_codec) { + printk(KERN_ERR "cs4270: ignoring CS4270 at addr %X\n", + i2c_client->addr); + printk(KERN_ERR "cs4270: only one CS4270 per board allowed\n"); + /* Should we return something other than ENODEV here? */ + return -ENODEV; + } /* Verify that we have a CS4270 */ ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); if (ret < 0) { - printk(KERN_ERR "cs4270: failed to read I2C\n"); + printk(KERN_ERR "cs4270: failed to read I2C at addr %X\n", + i2c_client->addr); return ret; } /* The top four bits of the chip ID should be 1100. */ @@ -575,7 +645,7 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, return -ENOMEM; } codec = &cs4270->codec; - socdev->card->codec = codec; + cs4270_codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); @@ -600,50 +670,20 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, goto error_free_codec; } - /* Register PCMs */ - - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + /* Register the DAI. If all the other ASoC driver have already + * registered, then this will call our probe function, so + * cs4270_codec needs to be ready. + */ + ret = snd_soc_register_dai(&cs4270_dai); if (ret < 0) { - printk(KERN_ERR "cs4270: failed to create PCMs\n"); + printk(KERN_ERR "cs4270: failed to register DAIe\n"); goto error_free_codec; } - /* Add the non-DAPM controls */ - - for (i = 0; i < ARRAY_SIZE(cs4270_snd_controls); i++) { - struct snd_kcontrol *kctrl; - - kctrl = snd_soc_cnew(&cs4270_snd_controls[i], codec, NULL); - if (!kctrl) { - printk(KERN_ERR "cs4270: error creating control '%s'\n", - cs4270_snd_controls[i].name); - ret = -ENOMEM; - goto error_free_pcms; - } - - ret = snd_ctl_add(codec->card, kctrl); - if (ret < 0) { - printk(KERN_ERR "cs4270: error adding control '%s'\n", - cs4270_snd_controls[i].name); - goto error_free_pcms; - } - } - - /* Initialize the SOC device */ - - ret = snd_soc_init_card(socdev); - if (ret < 0) { - printk(KERN_ERR "cs4270: failed to register card\n"); - goto error_free_pcms;; - } - - i2c_set_clientdata(i2c_client, socdev); + i2c_set_clientdata(i2c_client, cs4270); return 0; -error_free_pcms: - snd_soc_free_pcms(socdev); - error_free_codec: kfree(cs4270); @@ -652,11 +692,8 @@ error_free_codec: static int cs4270_i2c_remove(struct i2c_client *i2c_client) { - struct snd_soc_device *socdev = i2c_get_clientdata(i2c_client); - struct snd_soc_codec *codec = socdev->card->codec; - struct cs4270_private *cs4270 = codec->private_data; + struct cs4270_private *cs4270 = i2c_get_clientdata(i2c_client); - snd_soc_free_pcms(socdev); kfree(cs4270); return 0; @@ -678,26 +715,6 @@ static struct i2c_driver cs4270_i2c_driver = { .remove = cs4270_i2c_remove, }; -/* - * ASoC probe function - * - * This function is called when the machine driver calls - * platform_device_add(). - */ -static int cs4270_probe(struct platform_device *pdev) -{ - cs4270_socdev = platform_get_drvdata(pdev);; - - return i2c_add_driver(&cs4270_i2c_driver); -} - -static int cs4270_remove(struct platform_device *pdev) -{ - i2c_del_driver(&cs4270_i2c_driver); - - return 0; -} - /* * ASoC codec device structure * @@ -714,13 +731,13 @@ static int __init cs4270_init(void) { printk(KERN_INFO "Cirrus Logic CS4270 ALSA SoC Codec Driver\n"); - return snd_soc_register_dai(&cs4270_dai); + return i2c_add_driver(&cs4270_i2c_driver); } module_init(cs4270_init); static void __exit cs4270_exit(void) { - snd_soc_unregister_dai(&cs4270_dai); + i2c_del_driver(&cs4270_i2c_driver); } module_exit(cs4270_exit); -- GitLab From 36ef4944ee8118491631e317e406f9bd15e20e97 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 29 Jan 2009 19:29:24 -0800 Subject: [PATCH 1010/4982] x86, apic unification: remove left over files Impact: cleanup remove unused files Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/include/asm/bigsmp/apic.h | 138 -------------------------- arch/x86/include/asm/bigsmp/apicdef.h | 9 -- arch/x86/include/asm/bigsmp/ipi.h | 22 ---- arch/x86/mach-default/Makefile | 5 - 4 files changed, 174 deletions(-) delete mode 100644 arch/x86/include/asm/bigsmp/apic.h delete mode 100644 arch/x86/include/asm/bigsmp/apicdef.h delete mode 100644 arch/x86/include/asm/bigsmp/ipi.h delete mode 100644 arch/x86/mach-default/Makefile diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h deleted file mode 100644 index ee29d66cd30..00000000000 --- a/arch/x86/include/asm/bigsmp/apic.h +++ /dev/null @@ -1,138 +0,0 @@ -#ifndef __ASM_MACH_APIC_H -#define __ASM_MACH_APIC_H - -#define xapic_phys_to_log_apicid(cpu) (per_cpu(x86_bios_cpu_apicid, cpu)) - -static inline int bigsmp_apic_id_registered(void) -{ - return 1; -} - -static inline const cpumask_t *bigsmp_target_cpus(void) -{ -#ifdef CONFIG_SMP - return &cpu_online_map; -#else - return &cpumask_of_cpu(0); -#endif -} - -#define APIC_DFR_VALUE (APIC_DFR_FLAT) - -static inline unsigned long -bigsmp_check_apicid_used(physid_mask_t bitmap, int apicid) -{ - return 0; -} - -static inline unsigned long bigsmp_check_apicid_present(int bit) -{ - return 1; -} - -static inline unsigned long calculate_ldr(int cpu) -{ - unsigned long val, id; - val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; - id = xapic_phys_to_log_apicid(cpu); - val |= SET_APIC_LOGICAL_ID(id); - return val; -} - -/* - * Set up the logical destination ID. - * - * Intel recommends to set DFR, LDR and TPR before enabling - * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel - * document number 292116). So here it goes... - */ -static inline void bigsmp_init_apic_ldr(void) -{ - unsigned long val; - int cpu = smp_processor_id(); - - apic_write(APIC_DFR, APIC_DFR_VALUE); - val = calculate_ldr(cpu); - apic_write(APIC_LDR, val); -} - -static inline void bigsmp_setup_apic_routing(void) -{ - printk("Enabling APIC mode: %s. Using %d I/O APICs\n", - "Physflat", nr_ioapics); -} - -static inline int bigsmp_apicid_to_node(int logical_apicid) -{ - return apicid_2_node[hard_smp_processor_id()]; -} - -static inline int bigsmp_cpu_present_to_apicid(int mps_cpu) -{ - if (mps_cpu < nr_cpu_ids) - return (int) per_cpu(x86_bios_cpu_apicid, mps_cpu); - - return BAD_APICID; -} - -static inline physid_mask_t bigsmp_apicid_to_cpu_present(int phys_apicid) -{ - return physid_mask_of_physid(phys_apicid); -} - -extern u8 cpu_2_logical_apicid[]; -/* Mapping from cpu number to logical apicid */ -static inline int bigsmp_cpu_to_logical_apicid(int cpu) -{ - if (cpu >= nr_cpu_ids) - return BAD_APICID; - return cpu_physical_id(cpu); -} - -static inline physid_mask_t bigsmp_ioapic_phys_id_map(physid_mask_t phys_map) -{ - /* For clustered we don't have a good way to do this yet - hack */ - return physids_promote(0xFFL); -} - -static inline void bigsmp_setup_portio_remap(void) -{ -} - -static inline int bigsmp_check_phys_apicid_present(int boot_cpu_physical_apicid) -{ - return 1; -} - -/* As we are using single CPU as destination, pick only one CPU here */ -static inline unsigned int bigsmp_cpu_mask_to_apicid(const cpumask_t *cpumask) -{ - return bigsmp_cpu_to_logical_apicid(first_cpu(*cpumask)); -} - -static inline unsigned int -bigsmp_cpu_mask_to_apicid_and(const struct cpumask *cpumask, - const struct cpumask *andmask) -{ - int cpu; - - /* - * We're using fixed IRQ delivery, can only return one phys APIC ID. - * May as well be the first. - */ - for_each_cpu_and(cpu, cpumask, andmask) { - if (cpumask_test_cpu(cpu, cpu_online_mask)) - break; - } - if (cpu < nr_cpu_ids) - return bigsmp_cpu_to_logical_apicid(cpu); - - return BAD_APICID; -} - -static inline int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb) -{ - return cpuid_apic >> index_msb; -} - -#endif /* __ASM_MACH_APIC_H */ diff --git a/arch/x86/include/asm/bigsmp/apicdef.h b/arch/x86/include/asm/bigsmp/apicdef.h deleted file mode 100644 index e58dee84757..00000000000 --- a/arch/x86/include/asm/bigsmp/apicdef.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __ASM_MACH_APICDEF_H -#define __ASM_MACH_APICDEF_H - -static inline unsigned bigsmp_get_apic_id(unsigned long x) -{ - return (x >> 24) & 0xFF; -} - -#endif diff --git a/arch/x86/include/asm/bigsmp/ipi.h b/arch/x86/include/asm/bigsmp/ipi.h deleted file mode 100644 index a91db69cda6..00000000000 --- a/arch/x86/include/asm/bigsmp/ipi.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef __ASM_MACH_IPI_H -#define __ASM_MACH_IPI_H - -void default_send_IPI_mask_sequence(const struct cpumask *mask, int vector); -void default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector); - -static inline void default_send_IPI_mask(const struct cpumask *mask, int vector) -{ - default_send_IPI_mask_sequence(mask, vector); -} - -static inline void bigsmp_send_IPI_allbutself(int vector) -{ - default_send_IPI_mask_allbutself(cpu_online_mask, vector); -} - -static inline void bigsmp_send_IPI_all(int vector) -{ - default_send_IPI_mask(cpu_online_mask, vector); -} - -#endif /* __ASM_MACH_IPI_H */ diff --git a/arch/x86/mach-default/Makefile b/arch/x86/mach-default/Makefile deleted file mode 100644 index 012fe34459e..00000000000 --- a/arch/x86/mach-default/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for the linux kernel. -# - -obj-y := setup.o -- GitLab From 1ff2f20de354a621ef4b56b9cfe6f9139a7e493b Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 29 Jan 2009 19:30:04 -0800 Subject: [PATCH 1011/4982] x86: fix compiling with 64bit with def_to_bigsmp only need to do cut off with 32bit Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/smpboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 2912fa3a8ef..4c3cff57494 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1000,7 +1000,7 @@ static int __init smp_sanity_check(unsigned max_cpus) { preempt_disable(); -#ifndef CONFIG_X86_BIGSMP +#if !defined(CONFIG_X86_BIGSMP) && defined(CONFIG_X86_32) if (def_to_bigsmp && nr_cpu_ids > 8) { unsigned int cpu; unsigned nr; -- GitLab From 43f39890db2959b10891cf7bbf3f53fffc8ce3bd Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 29 Jan 2009 19:31:49 -0800 Subject: [PATCH 1012/4982] x86: seperate default_send_IPI_mask_sequence/allbutself from logical Impact: 32-bit should use logical version there are two version: for default_send_IPI_mask_sequence/allbutself one in ipi.h and one in ipi.c for 32bit it seems .h version overwrote ipi.c for a while. restore it so 32 bit could use its old logical version. also remove dupicated functions in .c Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/include/asm/ipi.h | 71 ++++++++++++--- arch/x86/kernel/bigsmp_32.c | 8 +- arch/x86/kernel/es7000_32.c | 4 +- arch/x86/kernel/genapic_flat_64.c | 6 +- arch/x86/kernel/ipi.c | 139 +----------------------------- arch/x86/kernel/numaq_32.c | 8 +- arch/x86/kernel/probe_32.c | 4 +- arch/x86/kernel/summit_32.c | 6 +- 8 files changed, 77 insertions(+), 169 deletions(-) diff --git a/arch/x86/include/asm/ipi.h b/arch/x86/include/asm/ipi.h index e2e8e4e0a65..aa79945445b 100644 --- a/arch/x86/include/asm/ipi.h +++ b/arch/x86/include/asm/ipi.h @@ -120,7 +120,7 @@ static inline void } static inline void -default_send_IPI_mask_sequence(const struct cpumask *mask, int vector) +default_send_IPI_mask_sequence_phys(const struct cpumask *mask, int vector) { unsigned long query_cpu; unsigned long flags; @@ -139,7 +139,7 @@ default_send_IPI_mask_sequence(const struct cpumask *mask, int vector) } static inline void -default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector) +default_send_IPI_mask_allbutself_phys(const struct cpumask *mask, int vector) { unsigned int this_cpu = smp_processor_id(); unsigned int query_cpu; @@ -157,23 +157,72 @@ default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector) local_irq_restore(flags); } +#include + +static inline void +default_send_IPI_mask_sequence_logical(const struct cpumask *mask, int vector) +{ + unsigned long flags; + unsigned int query_cpu; + + /* + * Hack. The clustered APIC addressing mode doesn't allow us to send + * to an arbitrary mask, so I do a unicasts to each CPU instead. This + * should be modified to do 1 message per cluster ID - mbligh + */ + + local_irq_save(flags); + for_each_cpu(query_cpu, mask) + __default_send_IPI_dest_field( + apic->cpu_to_logical_apicid(query_cpu), vector, + apic->dest_logical); + local_irq_restore(flags); +} + +static inline void +default_send_IPI_mask_allbutself_logical(const struct cpumask *mask, int vector) +{ + unsigned long flags; + unsigned int query_cpu; + unsigned int this_cpu = smp_processor_id(); + + /* See Hack comment above */ + + local_irq_save(flags); + for_each_cpu(query_cpu, mask) { + if (query_cpu == this_cpu) + continue; + __default_send_IPI_dest_field( + apic->cpu_to_logical_apicid(query_cpu), vector, + apic->dest_logical); + } + local_irq_restore(flags); +} /* Avoid include hell */ #define NMI_VECTOR 0x02 -void default_send_IPI_mask_bitmask(const struct cpumask *mask, int vector); -void default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector); - extern int no_broadcast; -#ifdef CONFIG_X86_64 -#include -#else -static inline void default_send_IPI_mask(const struct cpumask *mask, int vector) +#ifndef CONFIG_X86_64 +/* + * This is only used on smaller machines. + */ +static inline void default_send_IPI_mask_bitmask_logical(const struct cpumask *cpumask, int vector) +{ + unsigned long mask = cpumask_bits(cpumask)[0]; + unsigned long flags; + + local_irq_save(flags); + WARN_ON(mask & ~cpumask_bits(cpu_online_mask)[0]); + __default_send_IPI_dest_field(mask, vector, apic->dest_logical); + local_irq_restore(flags); +} + +static inline void default_send_IPI_mask_logical(const struct cpumask *mask, int vector) { - default_send_IPI_mask_bitmask(mask, vector); + default_send_IPI_mask_bitmask_logical(mask, vector); } -void default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector); #endif static inline void __default_local_send_IPI_allbutself(int vector) diff --git a/arch/x86/kernel/bigsmp_32.c b/arch/x86/kernel/bigsmp_32.c index b1f91931003..ab645c93a6e 100644 --- a/arch/x86/kernel/bigsmp_32.c +++ b/arch/x86/kernel/bigsmp_32.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -154,17 +155,14 @@ static inline int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb) return cpuid_apic >> index_msb; } -void default_send_IPI_mask_sequence(const struct cpumask *mask, int vector); -void default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector); - static inline void bigsmp_send_IPI_mask(const struct cpumask *mask, int vector) { - default_send_IPI_mask_sequence(mask, vector); + default_send_IPI_mask_sequence_phys(mask, vector); } static inline void bigsmp_send_IPI_allbutself(int vector) { - default_send_IPI_mask_allbutself(cpu_online_mask, vector); + default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector); } static inline void bigsmp_send_IPI_all(int vector) diff --git a/arch/x86/kernel/es7000_32.c b/arch/x86/kernel/es7000_32.c index 078364ccfa0..b5b50e8b94a 100644 --- a/arch/x86/kernel/es7000_32.c +++ b/arch/x86/kernel/es7000_32.c @@ -451,12 +451,12 @@ static int es7000_check_dsdt(void) static void es7000_send_IPI_mask(const struct cpumask *mask, int vector) { - default_send_IPI_mask_sequence(mask, vector); + default_send_IPI_mask_sequence_phys(mask, vector); } static void es7000_send_IPI_allbutself(int vector) { - default_send_IPI_mask_allbutself(cpu_online_mask, vector); + default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector); } static void es7000_send_IPI_all(int vector) diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c index 19bffb3f732..249d2d3c034 100644 --- a/arch/x86/kernel/genapic_flat_64.c +++ b/arch/x86/kernel/genapic_flat_64.c @@ -267,18 +267,18 @@ static void physflat_vector_allocation_domain(int cpu, struct cpumask *retmask) static void physflat_send_IPI_mask(const struct cpumask *cpumask, int vector) { - default_send_IPI_mask_sequence(cpumask, vector); + default_send_IPI_mask_sequence_phys(cpumask, vector); } static void physflat_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector) { - default_send_IPI_mask_allbutself(cpumask, vector); + default_send_IPI_mask_allbutself_phys(cpumask, vector); } static void physflat_send_IPI_allbutself(int vector) { - default_send_IPI_mask_allbutself(cpu_online_mask, vector); + default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector); } static void physflat_send_IPI_all(int vector) diff --git a/arch/x86/kernel/ipi.c b/arch/x86/kernel/ipi.c index 0893fa14458..339f4f3feee 100644 --- a/arch/x86/kernel/ipi.c +++ b/arch/x86/kernel/ipi.c @@ -17,148 +17,13 @@ #include #include #include +#include #ifdef CONFIG_X86_32 -#include - -/* - * the following functions deal with sending IPIs between CPUs. - * - * We use 'broadcast', CPU->CPU IPIs and self-IPIs too. - */ - -static inline int __prepare_ICR(unsigned int shortcut, int vector) -{ - unsigned int icr = shortcut | apic->dest_logical; - - switch (vector) { - default: - icr |= APIC_DM_FIXED | vector; - break; - case NMI_VECTOR: - icr |= APIC_DM_NMI; - break; - } - return icr; -} - -static inline int __prepare_ICR2(unsigned int mask) -{ - return SET_APIC_DEST_FIELD(mask); -} - -void __default_send_IPI_shortcut(unsigned int shortcut, int vector) -{ - /* - * Subtle. In the case of the 'never do double writes' workaround - * we have to lock out interrupts to be safe. As we don't care - * of the value read we use an atomic rmw access to avoid costly - * cli/sti. Otherwise we use an even cheaper single atomic write - * to the APIC. - */ - unsigned int cfg; - - /* - * Wait for idle. - */ - apic_wait_icr_idle(); - - /* - * No need to touch the target chip field - */ - cfg = __prepare_ICR(shortcut, vector); - - /* - * Send the IPI. The write to APIC_ICR fires this off. - */ - apic_write(APIC_ICR, cfg); -} void default_send_IPI_self(int vector) { - __default_send_IPI_shortcut(APIC_DEST_SELF, vector); -} - -/* - * This is used to send an IPI with no shorthand notation (the destination is - * specified in bits 56 to 63 of the ICR). - */ -static inline void __default_send_IPI_dest_field(unsigned long mask, int vector) -{ - unsigned long cfg; - - /* - * Wait for idle. - */ - if (unlikely(vector == NMI_VECTOR)) - safe_apic_wait_icr_idle(); - else - apic_wait_icr_idle(); - - /* - * prepare target chip field - */ - cfg = __prepare_ICR2(mask); - apic_write(APIC_ICR2, cfg); - - /* - * program the ICR - */ - cfg = __prepare_ICR(0, vector); - - /* - * Send the IPI. The write to APIC_ICR fires this off. - */ - apic_write(APIC_ICR, cfg); -} - -/* - * This is only used on smaller machines. - */ -void default_send_IPI_mask_bitmask(const struct cpumask *cpumask, int vector) -{ - unsigned long mask = cpumask_bits(cpumask)[0]; - unsigned long flags; - - local_irq_save(flags); - WARN_ON(mask & ~cpumask_bits(cpu_online_mask)[0]); - __default_send_IPI_dest_field(mask, vector); - local_irq_restore(flags); -} - -void default_send_IPI_mask_sequence(const struct cpumask *mask, int vector) -{ - unsigned long flags; - unsigned int query_cpu; - - /* - * Hack. The clustered APIC addressing mode doesn't allow us to send - * to an arbitrary mask, so I do a unicasts to each CPU instead. This - * should be modified to do 1 message per cluster ID - mbligh - */ - - local_irq_save(flags); - for_each_cpu(query_cpu, mask) - __default_send_IPI_dest_field(apic->cpu_to_logical_apicid(query_cpu), vector); - local_irq_restore(flags); -} - -void default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector) -{ - unsigned long flags; - unsigned int query_cpu; - unsigned int this_cpu = smp_processor_id(); - - /* See Hack comment above */ - - local_irq_save(flags); - for_each_cpu(query_cpu, mask) { - if (query_cpu == this_cpu) - continue; - __default_send_IPI_dest_field( - apic->cpu_to_logical_apicid(query_cpu), vector); - } - local_irq_restore(flags); + __default_send_IPI_shortcut(APIC_DEST_SELF, vector, apic->dest_logical); } /* must come after the send_IPI functions above for inlining */ diff --git a/arch/x86/kernel/numaq_32.c b/arch/x86/kernel/numaq_32.c index 83bb05524f4..c143b329216 100644 --- a/arch/x86/kernel/numaq_32.c +++ b/arch/x86/kernel/numaq_32.c @@ -302,6 +302,7 @@ int __init get_memcfg_numaq(void) #include #include #include +#include #include #include #include @@ -319,17 +320,14 @@ static inline unsigned int numaq_get_apic_id(unsigned long x) return (x >> 24) & 0x0F; } -void default_send_IPI_mask_sequence(const struct cpumask *mask, int vector); -void default_send_IPI_mask_allbutself(const struct cpumask *mask, int vector); - static inline void numaq_send_IPI_mask(const struct cpumask *mask, int vector) { - default_send_IPI_mask_sequence(mask, vector); + default_send_IPI_mask_sequence_logical(mask, vector); } static inline void numaq_send_IPI_allbutself(int vector) { - default_send_IPI_mask_allbutself(cpu_online_mask, vector); + default_send_IPI_mask_allbutself_logical(cpu_online_mask, vector); } static inline void numaq_send_IPI_all(int vector) diff --git a/arch/x86/kernel/probe_32.c b/arch/x86/kernel/probe_32.c index b5db26f8e06..3f12a401182 100644 --- a/arch/x86/kernel/probe_32.c +++ b/arch/x86/kernel/probe_32.c @@ -112,8 +112,8 @@ struct genapic apic_default = { .cpu_mask_to_apicid = default_cpu_mask_to_apicid, .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, - .send_IPI_mask = default_send_IPI_mask, - .send_IPI_mask_allbutself = default_send_IPI_mask_allbutself, + .send_IPI_mask = default_send_IPI_mask_logical, + .send_IPI_mask_allbutself = default_send_IPI_mask_allbutself_logical, .send_IPI_allbutself = default_send_IPI_allbutself, .send_IPI_all = default_send_IPI_all, .send_IPI_self = NULL, diff --git a/arch/x86/kernel/summit_32.c b/arch/x86/kernel/summit_32.c index 84ff9ebbcc9..ecb41b9d7aa 100644 --- a/arch/x86/kernel/summit_32.c +++ b/arch/x86/kernel/summit_32.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -54,12 +55,9 @@ static inline unsigned summit_get_apic_id(unsigned long x) return (x >> 24) & 0xFF; } -void default_send_IPI_mask_sequence(const cpumask_t *mask, int vector); -void default_send_IPI_mask_allbutself(const cpumask_t *mask, int vector); - static inline void summit_send_IPI_mask(const cpumask_t *mask, int vector) { - default_send_IPI_mask_sequence(mask, vector); + default_send_IPI_mask_sequence_logical(mask, vector); } static inline void summit_send_IPI_allbutself(int vector) -- GitLab From 26f7ef14a76b0e590a3797fd7b2f3cee868d9664 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 29 Jan 2009 14:19:22 -0800 Subject: [PATCH 1013/4982] x86: don't treat bigsmp as non-standard just like 64 bit switch from flat logical APIC messages to flat physical mode automatically. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 15 +++++++-------- arch/x86/kernel/acpi/boot.c | 2 +- arch/x86/kernel/mpparse.c | 4 ++-- arch/x86/kernel/setup.c | 2 +- arch/x86/kernel/smpboot.c | 2 +- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index afaf2cb7c1a..c6e567bb649 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -262,6 +262,12 @@ config X86_MPPARSE For old smp systems that do not have proper acpi support. Newer systems (esp with 64bit cpus) with acpi support, MADT and DSDT will override it +config X86_BIGSMP + bool "Support for big SMP systems with more than 8 CPUs" + depends on X86_32 && SMP + help + This option is needed for the systems that have more than 8 CPUs + config X86_NON_STANDARD bool "Support for non-standard x86 platforms" help @@ -338,13 +344,6 @@ config X86_32_NON_STANDARD if you select them all, kernel will probe it one by one. and will fallback to default. -config X86_BIGSMP - bool "Support for big SMP systems with more than 8 CPUs" - depends on X86_32_NON_STANDARD - help - This option is needed for the systems that have more than 8 CPUs - and if the system is not of any sub-arch type above. - config X86_NUMAQ bool "NUMAQ (IBM/Sequent)" depends on X86_32_NON_STANDARD @@ -366,7 +365,7 @@ config X86_SUMMIT config X86_ES7000 bool "Support for Unisys ES7000 IA32 series" - depends on X86_32_NON_STANDARD + depends on X86_32_NON_STANDARD && X86_BIGSMP help Support for Unisys ES7000 systems. Say 'Y' here if this kernel is supposed to run on an IA32-based Unisys ES7000 system. diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 7352c60f29d..3efa996b036 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -1335,7 +1335,7 @@ static void __init acpi_process_madt(void) if (!error) { acpi_lapic = 1; -#ifdef CONFIG_X86_32_NON_STANDARD +#ifdef CONFIG_X86_BIGSMP generic_bigsmp_probe(); #endif /* diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 89aaced51bd..b46ca7d31fe 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -372,8 +372,8 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) (*x86_quirks->mpc_record)++; } -#ifdef CONFIG_X86_32_NON_STANDARD - generic_bigsmp_probe(); +#ifdef CONFIG_X86_BIGSMP + generic_bigsmp_probe(); #endif if (apic->setup_apic_routing) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index f64e1a487c9..df64afff580 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -936,7 +936,7 @@ void __init setup_arch(char **cmdline_p) map_vsyscall(); #endif -#ifdef CONFIG_X86_32_NON_STANDARD +#if defined(CONFIG_X86_32_NON_STANDARD) || defined(CONFIG_X86_BIGSMP) generic_apic_probe(); #endif diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 4c3cff57494..1268a862abb 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1007,7 +1007,7 @@ static int __init smp_sanity_check(unsigned max_cpus) printk(KERN_WARNING "More than 8 CPUs detected - skipping them.\n" - "Use CONFIG_X86_32_NON_STANDARD and CONFIG_X86_BIGSMP.\n"); + "Use CONFIG_X86_BIGSMP.\n"); nr = 0; for_each_present_cpu(cpu) { -- GitLab From 4d87c5bec5389625d80b71108795aecf82cd670d Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 29 Jan 2009 14:29:10 -0800 Subject: [PATCH 1014/4982] fix "sparseirq: use kstat_irqs_cpu on non-x86 architectures too" Repair 0b0f0b1c2c87de299df6f92a8ffc0a73bd1bb960 arch/alpha/kernel/irq.c: In function 'show_interrupts': arch/alpha/kernel/irq.c:93: error: 'i' undeclared (first use in this function) arch/alpha/kernel/irq.c:93: error: (Each undeclared identifier is reported only once arch/alpha/kernel/irq.c:93: error: for each function it appears in.) Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar --- arch/alpha/kernel/irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c index 430550bd1eb..d3812eb8401 100644 --- a/arch/alpha/kernel/irq.c +++ b/arch/alpha/kernel/irq.c @@ -90,7 +90,7 @@ show_interrupts(struct seq_file *p, void *v) seq_printf(p, "%10u ", kstat_irqs(irq)); #else for_each_online_cpu(j) - seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); + seq_printf(p, "%10u ", kstat_irqs_cpu(irq, j)); #endif seq_printf(p, " %14s", irq_desc[irq].chip->typename); seq_printf(p, " %c%s", -- GitLab From 3c4572657656117c1f9cf1df42e681ea71abb2db Mon Sep 17 00:00:00 2001 From: Sujith Date: Tue, 27 Jan 2009 10:55:31 +0530 Subject: [PATCH 1015/4982] ath9k: Handle chainmask for A9280 The default chainmask for AR9280 is 3, so handle that when setting the supported MCS rates. Also, check for the HW supported chainmask when choosing single/dual stream. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 1 + drivers/net/wireless/ath9k/rc.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index ede8980be96..04a60510371 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -876,6 +876,7 @@ static void setup_ht_cap(struct ath_softc *sc, case 1: ht_info->mcs.rx_mask[0] = 0xff; break; + case 3: case 5: case 7: default: diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 8e1528d487b..eb557add656 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -1359,7 +1359,7 @@ static void ath_rc_init(struct ath_softc *sc, if (sta->ht_cap.ht_supported) { ath_rc_priv->ht_cap = WLAN_RC_HT_FLAG; - if (sc->sc_tx_chainmask != 1) + if (sc->sc_ah->ah_caps.tx_chainmask != 1) ath_rc_priv->ht_cap |= WLAN_RC_DS_FLAG; if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ath_rc_priv->ht_cap |= WLAN_RC_40_FLAG; -- GitLab From 1f7d6cbfa2a993ea0d714e8552c784eea75a046b Mon Sep 17 00:00:00 2001 From: Sujith Date: Tue, 27 Jan 2009 10:55:54 +0530 Subject: [PATCH 1016/4982] ath9k: Reconfigure beacons on getting a notification from mac80211 Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 35 +++++++++++++++++-------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 04a60510371..e9b0684ea70 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -2253,24 +2253,27 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, } } - if ((conf->changed & IEEE80211_IFCC_BEACON) && - ((vif->type == NL80211_IFTYPE_ADHOC) || - (vif->type == NL80211_IFTYPE_AP))) { - /* - * Allocate and setup the beacon frame. - * - * Stop any previous beacon DMA. This may be - * necessary, for example, when an ibss merge - * causes reconfiguration; we may be called - * with beacon transmission active. - */ - ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); + if ((vif->type == NL80211_IFTYPE_ADHOC) || + (vif->type == NL80211_IFTYPE_AP)) { + if ((conf->changed & IEEE80211_IFCC_BEACON) || + (conf->changed & IEEE80211_IFCC_BEACON_ENABLED && + conf->enable_beacon)) { + /* + * Allocate and setup the beacon frame. + * + * Stop any previous beacon DMA. This may be + * necessary, for example, when an ibss merge + * causes reconfiguration; we may be called + * with beacon transmission active. + */ + ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); - error = ath_beacon_alloc(sc, 0); - if (error != 0) - return error; + error = ath_beacon_alloc(sc, 0); + if (error != 0) + return error; - ath_beacon_sync(sc, 0); + ath_beacon_sync(sc, 0); + } } /* Check for WLAN_CAPABILITY_PRIVACY ? */ -- GitLab From 1286ec6d63c557aa203ab5af56962a3d37181771 Mon Sep 17 00:00:00 2001 From: Sujith Date: Tue, 27 Jan 2009 13:30:37 +0530 Subject: [PATCH 1017/4982] ath9k: Fix station access in aggregation completion The ieee80211_sta pointer in the SKB's TX control info area is not guaranteed to be valid after returning from the tx() callback. Use ieee80211_find_sta() instead and return early if the station is no longer present. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/xmit.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 1b83673c3df..007ca91188d 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -268,7 +268,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, { struct ath_node *an = NULL; struct sk_buff *skb; - struct ieee80211_tx_info *tx_info; + struct ieee80211_sta *sta; + struct ieee80211_hdr *hdr; struct ath_atx_tid *tid = NULL; struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; struct ath_desc *ds = bf_last->bf_desc; @@ -278,13 +279,19 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, int isaggr, txfail, txpending, sendbar = 0, needreset = 0; skb = (struct sk_buff *)bf->bf_mpdu; - tx_info = IEEE80211_SKB_CB(skb); + hdr = (struct ieee80211_hdr *)skb->data; - if (tx_info->control.sta) { - an = (struct ath_node *)tx_info->control.sta->drv_priv; - tid = ATH_AN_2_TID(an, bf->bf_tidno); + rcu_read_lock(); + + sta = ieee80211_find_sta(sc->hw, hdr->addr1); + if (!sta) { + rcu_read_unlock(); + return; } + an = (struct ath_node *)sta->drv_priv; + tid = ATH_AN_2_TID(an, bf->bf_tidno); + isaggr = bf_isaggr(bf); memset(ba, 0, WME_BA_BMP_SIZE >> 3); @@ -391,6 +398,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, /* send buffered frames as singles */ ath_tx_flush_tid(sc, tid); } + rcu_read_unlock(); return; } @@ -402,6 +410,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, spin_unlock_bh(&txq->axq_lock); } + rcu_read_unlock(); + if (needreset) ath_reset(sc, false); } -- GitLab From f46730d13f23b4578dca1c0f7663ea3093ff4f0e Mon Sep 17 00:00:00 2001 From: Sujith Date: Tue, 27 Jan 2009 13:51:03 +0530 Subject: [PATCH 1018/4982] ath9k: Setup short preamble properly in rate registration This patch fixes an issue where hw_value_short was not being filled with the proper ratecode during rate registration, but was being used in the RX path for decoding the packet rate. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index e9b0684ea70..d8e826659c1 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -217,7 +217,13 @@ static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band) for (i = 0; i < maxrates; i++) { rate[i].bitrate = rate_table->info[i].ratekbps / 100; rate[i].hw_value = rate_table->info[i].ratecode; + if (rate_table->info[i].short_preamble) { + rate[i].hw_value_short = rate_table->info[i].ratecode | + rate_table->info[i].short_preamble; + rate[i].flags = IEEE80211_RATE_SHORT_PREAMBLE; + } sband->n_bitrates++; + DPRINTF(sc, ATH_DBG_CONFIG, "Rate: %2dMbps, ratecode: %2d\n", rate[i].bitrate / 10, rate[i].hw_value); } -- GitLab From 94ff91d4afd8ae14e8bb7012ba17cf6984130e44 Mon Sep 17 00:00:00 2001 From: Sujith Date: Tue, 27 Jan 2009 15:06:38 +0530 Subject: [PATCH 1019/4982] ath9k: Fix bug in TX DMA termination Removing the module was slow because ath9k_hw_stopdma() was looping for a long time quantum. Use reasonable values now to fix this issue. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/mac.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath9k/mac.c b/drivers/net/wireless/ath9k/mac.c index af32d091dc3..ef832a5ebbd 100644 --- a/drivers/net/wireless/ath9k/mac.c +++ b/drivers/net/wireless/ath9k/mac.c @@ -107,14 +107,32 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hal *ah, bool bIncTrigLevel) bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q) { +#define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */ +#define ATH9K_TIME_QUANTUM 100 /* usec */ + + struct ath_hal_5416 *ahp = AH5416(ah); + struct ath9k_hw_capabilities *pCap = &ah->ah_caps; + struct ath9k_tx_queue_info *qi; u32 tsfLow, j, wait; + u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM; + + if (q >= pCap->total_queues) { + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q); + return false; + } + + qi = &ahp->ah_txq[q]; + if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n"); + return false; + } REG_WRITE(ah, AR_Q_TXD, 1 << q); - for (wait = 1000; wait != 0; wait--) { + for (wait = wait_time; wait != 0; wait--) { if (ath9k_hw_numtxpending(ah, q) == 0) break; - udelay(100); + udelay(ATH9K_TIME_QUANTUM); } if (ath9k_hw_numtxpending(ah, q)) { @@ -144,8 +162,7 @@ bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q) udelay(200); REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); - wait = 1000; - + wait = wait_time; while (ath9k_hw_numtxpending(ah, q)) { if ((--wait) == 0) { DPRINTF(ah->ah_sc, ATH_DBG_XMIT, @@ -153,15 +170,17 @@ bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q) "msec after killing last frame\n"); break; } - udelay(100); + udelay(ATH9K_TIME_QUANTUM); } REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); } REG_WRITE(ah, AR_Q_TXD, 0); - return wait != 0; + +#undef ATH9K_TX_STOP_DMA_TIMEOUT +#undef ATH9K_TIME_QUANTUM } bool ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds, -- GitLab From b8abde45d7d6ab9e8ceced9b5990eeb1149d0b97 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Tue, 27 Jan 2009 19:26:28 +0530 Subject: [PATCH 1020/4982] mac80211: Cancel the dynamic ps timer in ioctl_siwpower. If the dynamic power save timer has been started before the power save is disabled using iwconfig, we fail to cancel the timer. Hence cancel it while disabling power save. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- net/mac80211/wext.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 70a29b657b6..5c88b8246bb 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -906,6 +906,8 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev, IEEE80211_CONF_CHANGE_PS); if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) ieee80211_send_nullfunc(local, sdata, 0); + del_timer_sync(&local->dynamic_ps_timer); + cancel_work_sync(&local->dynamic_ps_enable_work); } } -- GitLab From 880abd42d0891635e988b0a2cfb0942cf79fa2c3 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Fri, 30 Jan 2009 19:20:29 +0100 Subject: [PATCH 1021/4982] ALSA: ess1688: fix OPL3 port setting The ess1688 driver uses the same port for PCM audio (SB compatible) and OPL3 synthesis. It is not always right so allow to choose a different port for OPL3 synthesis. Signed-off-by: Krzysztof Helt Signed-off-by: Takashi Iwai --- sound/isa/es1688/es1688.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c index b46377139cf..b0eb0cf6050 100644 --- a/sound/isa/es1688/es1688.c +++ b/sound/isa/es1688/es1688.c @@ -49,6 +49,7 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260 */ +static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* Usually 0x388 */ static long mpu_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1}; static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */ static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */ @@ -65,6 +66,8 @@ MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); module_param_array(mpu_port, long, NULL, 0444); MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver."); module_param_array(irq, int, NULL, 0444); +module_param_array(fm_port, long, NULL, 0444); +MODULE_PARM_DESC(fm_port, "FM port # for ES1688 driver."); MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver."); module_param_array(mpu_irq, int, NULL, 0444); MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver."); @@ -143,13 +146,19 @@ static int __devinit snd_es1688_probe(struct device *dev, unsigned int n) sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i", pcm->name, chip->port, chip->irq, chip->dma8); - if (snd_opl3_create(card, chip->port, chip->port + 2, - OPL3_HW_OPL3, 0, &opl3) < 0) - dev_warn(dev, "opl3 not detected at 0x%lx\n", chip->port); - else { - error = snd_opl3_hwdep_new(opl3, 0, 1, NULL); - if (error < 0) - goto out; + if (fm_port[n] == SNDRV_AUTO_PORT) + fm_port[n] = port[n]; /* share the same port */ + + if (fm_port[n] > 0) { + if (snd_opl3_create(card, fm_port[n], fm_port[n] + 2, + OPL3_HW_OPL3, 0, &opl3) < 0) + dev_warn(dev, + "opl3 not detected at 0x%lx\n", fm_port[n]); + else { + error = snd_opl3_hwdep_new(opl3, 0, 1, NULL); + if (error < 0) + goto out; + } } if (mpu_irq[n] >= 0 && mpu_irq[n] != SNDRV_AUTO_IRQ && -- GitLab From 504a06d8b05cb5b214c9b97752d8451e88d9ef81 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 30 Jan 2009 19:59:10 +0100 Subject: [PATCH 1022/4982] ALSA: Add description of new fm_port option for snd-es1688 driver Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 7134a8f7044..a763b76afe5 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -609,6 +609,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. Module for ESS AudioDrive ES-1688 and ES-688 sound cards. port - port # for ES-1688 chip (0x220,0x240,0x260) + fm_port - port # for OPL3 (option; share the same port as default) mpu_port - port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default) irq - IRQ # for ES-1688 chip (5,7,9,10) mpu_irq - IRQ # for MPU-401 port (5,7,9,10) -- GitLab From 3ac6cffea4aa18007a454a7442da2855882f403d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 30 Jan 2009 16:32:22 +0900 Subject: [PATCH 1023/4982] linker script: use separate simpler definition for PERCPU() Impact: fix linker screwup on x86_32 Recent x86_64 zerobased patches introduced PERCPU_VADDR() to put .data.percpu to a predefined address and re-defined PERCPU() in terms of it. The new macro defined one extra symbol, __per_cpu_load, for LMA of the section so that the init data could be accessed. This new symbol introduced the following problems to x86_32. 1. If __per_cpu_load is defined outside of .data.percpu as an absolute symbol, relocation generation for relocatable kernel fails due to absolute relocation. 2. If __per_cpu_load is put inside .data.percpu with absolute address assignment to work around #1, linker gets confused and under certain configurations ends up relocating the symbol against .data.percpu such that the load address gets added on top of already set load address. As x86_32 doesn't use predefined address for .data.percpu, there's no need for it to care about the possibility of __per_cpu_load being different from __per_cpu_start. This patch defines PERCPU() separately so that __per_cpu_load is defined inside .data.percpu so that everything is ordinary linking-wise. Signed-off-by: Tejun Heo Signed-off-by: Ingo Molnar --- include/asm-generic/vmlinux.lds.h | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 53e21f36a80..5406e70aba8 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -445,10 +445,9 @@ * section in the linker script will go there too. @phdr should have * a leading colon. * - * This macro defines three symbols, __per_cpu_load, __per_cpu_start - * and __per_cpu_end. The first one is the vaddr of loaded percpu - * init data. __per_cpu_start equals @vaddr and __per_cpu_end is the - * end offset. + * Note that this macros defines __per_cpu_load as an absolute symbol. + * If there is no need to put the percpu section at a predetermined + * address, use PERCPU(). */ #define PERCPU_VADDR(vaddr, phdr) \ VMLINUX_SYMBOL(__per_cpu_load) = .; \ @@ -470,7 +469,20 @@ * Align to @align and outputs output section for percpu area. This * macro doesn't maniuplate @vaddr or @phdr and __per_cpu_load and * __per_cpu_start will be identical. + * + * This macro is equivalent to ALIGN(align); PERCPU_VADDR( , ) except + * that __per_cpu_load is defined as a relative symbol against + * .data.percpu which is required for relocatable x86_32 + * configuration. */ #define PERCPU(align) \ . = ALIGN(align); \ - PERCPU_VADDR( , ) + .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { \ + VMLINUX_SYMBOL(__per_cpu_load) = .; \ + VMLINUX_SYMBOL(__per_cpu_start) = .; \ + *(.data.percpu.first) \ + *(.data.percpu.page_aligned) \ + *(.data.percpu) \ + *(.data.percpu.shared_aligned) \ + VMLINUX_SYMBOL(__per_cpu_end) = .; \ + } -- GitLab From 6b64ee02da20d6c0d97115e0b1ab47f9fa2f0d8f Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 30 Jan 2009 23:42:18 +0100 Subject: [PATCH 1024/4982] x86, apic, 32-bit: add self-IPI methods Impact: fix rare crash on 32-bit The 32-bit APIC drivers had their send_IPI_self vectors set to NULL, but ioapic_retrigger_irq() depends on it being always set. Fix it. Signed-off-by: Ingo Molnar --- arch/x86/kernel/bigsmp_32.c | 2 +- arch/x86/kernel/es7000_32.c | 2 +- arch/x86/kernel/numaq_32.c | 2 +- arch/x86/kernel/probe_32.c | 2 +- arch/x86/kernel/summit_32.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/bigsmp_32.c b/arch/x86/kernel/bigsmp_32.c index ab645c93a6e..47a62f46afd 100644 --- a/arch/x86/kernel/bigsmp_32.c +++ b/arch/x86/kernel/bigsmp_32.c @@ -252,7 +252,7 @@ struct genapic apic_bigsmp = { .send_IPI_mask_allbutself = NULL, .send_IPI_allbutself = bigsmp_send_IPI_allbutself, .send_IPI_all = bigsmp_send_IPI_all, - .send_IPI_self = NULL, + .send_IPI_self = default_send_IPI_self, .wakeup_cpu = NULL, .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, diff --git a/arch/x86/kernel/es7000_32.c b/arch/x86/kernel/es7000_32.c index b5b50e8b94a..d6184c12a18 100644 --- a/arch/x86/kernel/es7000_32.c +++ b/arch/x86/kernel/es7000_32.c @@ -786,7 +786,7 @@ struct genapic apic_es7000 = { .send_IPI_mask_allbutself = NULL, .send_IPI_allbutself = es7000_send_IPI_allbutself, .send_IPI_all = es7000_send_IPI_all, - .send_IPI_self = NULL, + .send_IPI_self = default_send_IPI_self, .wakeup_cpu = NULL, diff --git a/arch/x86/kernel/numaq_32.c b/arch/x86/kernel/numaq_32.c index c143b329216..947748e1721 100644 --- a/arch/x86/kernel/numaq_32.c +++ b/arch/x86/kernel/numaq_32.c @@ -554,7 +554,7 @@ struct genapic apic_numaq = { .send_IPI_mask_allbutself = NULL, .send_IPI_allbutself = numaq_send_IPI_allbutself, .send_IPI_all = numaq_send_IPI_all, - .send_IPI_self = NULL, + .send_IPI_self = default_send_IPI_self, .wakeup_cpu = NULL, .trampoline_phys_low = NUMAQ_TRAMPOLINE_PHYS_LOW, diff --git a/arch/x86/kernel/probe_32.c b/arch/x86/kernel/probe_32.c index 3f12a401182..22337b75de6 100644 --- a/arch/x86/kernel/probe_32.c +++ b/arch/x86/kernel/probe_32.c @@ -116,7 +116,7 @@ struct genapic apic_default = { .send_IPI_mask_allbutself = default_send_IPI_mask_allbutself_logical, .send_IPI_allbutself = default_send_IPI_allbutself, .send_IPI_all = default_send_IPI_all, - .send_IPI_self = NULL, + .send_IPI_self = default_send_IPI_self, .wakeup_cpu = NULL, .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, diff --git a/arch/x86/kernel/summit_32.c b/arch/x86/kernel/summit_32.c index ecb41b9d7aa..1e733eff9b3 100644 --- a/arch/x86/kernel/summit_32.c +++ b/arch/x86/kernel/summit_32.c @@ -588,7 +588,7 @@ struct genapic apic_summit = { .send_IPI_mask_allbutself = NULL, .send_IPI_allbutself = summit_send_IPI_allbutself, .send_IPI_all = summit_send_IPI_all, - .send_IPI_self = NULL, + .send_IPI_self = default_send_IPI_self, .wakeup_cpu = NULL, .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, -- GitLab From 319f3ba52c71630865b10ac3b99dd020440d681d Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 28 Jan 2009 14:35:01 -0800 Subject: [PATCH 1025/4982] xen: move remaining mmu-related stuff into mmu.c Impact: Cleanup Move remaining mmu-related stuff into mmu.c. A general cleanup, and lay the groundwork for later patches. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: H. Peter Anvin --- arch/x86/xen/enlighten.c | 731 +-------------------------------------- arch/x86/xen/mmu.c | 700 +++++++++++++++++++++++++++++++++++++ arch/x86/xen/mmu.h | 3 + arch/x86/xen/xen-ops.h | 8 + 4 files changed, 712 insertions(+), 730 deletions(-) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 6b3f7eef57e..0cd2a165f17 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -61,35 +61,6 @@ DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info); enum xen_domain_type xen_domain_type = XEN_NATIVE; EXPORT_SYMBOL_GPL(xen_domain_type); -/* - * Identity map, in addition to plain kernel map. This needs to be - * large enough to allocate page table pages to allocate the rest. - * Each page can map 2MB. - */ -static pte_t level1_ident_pgt[PTRS_PER_PTE * 4] __page_aligned_bss; - -#ifdef CONFIG_X86_64 -/* l3 pud for userspace vsyscall mapping */ -static pud_t level3_user_vsyscall[PTRS_PER_PUD] __page_aligned_bss; -#endif /* CONFIG_X86_64 */ - -/* - * Note about cr3 (pagetable base) values: - * - * xen_cr3 contains the current logical cr3 value; it contains the - * last set cr3. This may not be the current effective cr3, because - * its update may be being lazily deferred. However, a vcpu looking - * at its own cr3 can use this value knowing that it everything will - * be self-consistent. - * - * xen_current_cr3 contains the actual vcpu cr3; it is set once the - * hypercall to set the vcpu cr3 is complete (so it may be a little - * out of date, but it will never be set early). If one vcpu is - * looking at another vcpu's cr3 value, it should use this variable. - */ -DEFINE_PER_CPU(unsigned long, xen_cr3); /* cr3 stored as physaddr */ -DEFINE_PER_CPU(unsigned long, xen_current_cr3); /* actual vcpu cr3 */ - struct start_info *xen_start_info; EXPORT_SYMBOL_GPL(xen_start_info); @@ -237,7 +208,7 @@ static unsigned long xen_get_debugreg(int reg) return HYPERVISOR_get_debugreg(reg); } -static void xen_leave_lazy(void) +void xen_leave_lazy(void) { paravirt_leave_lazy(paravirt_get_lazy_mode()); xen_mc_flush(); @@ -598,76 +569,6 @@ static struct apic_ops xen_basic_apic_ops = { #endif -static void xen_flush_tlb(void) -{ - struct mmuext_op *op; - struct multicall_space mcs; - - preempt_disable(); - - mcs = xen_mc_entry(sizeof(*op)); - - op = mcs.args; - op->cmd = MMUEXT_TLB_FLUSH_LOCAL; - MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); - - xen_mc_issue(PARAVIRT_LAZY_MMU); - - preempt_enable(); -} - -static void xen_flush_tlb_single(unsigned long addr) -{ - struct mmuext_op *op; - struct multicall_space mcs; - - preempt_disable(); - - mcs = xen_mc_entry(sizeof(*op)); - op = mcs.args; - op->cmd = MMUEXT_INVLPG_LOCAL; - op->arg1.linear_addr = addr & PAGE_MASK; - MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); - - xen_mc_issue(PARAVIRT_LAZY_MMU); - - preempt_enable(); -} - -static void xen_flush_tlb_others(const struct cpumask *cpus, - struct mm_struct *mm, unsigned long va) -{ - struct { - struct mmuext_op op; - DECLARE_BITMAP(mask, NR_CPUS); - } *args; - struct multicall_space mcs; - - BUG_ON(cpumask_empty(cpus)); - BUG_ON(!mm); - - mcs = xen_mc_entry(sizeof(*args)); - args = mcs.args; - args->op.arg2.vcpumask = to_cpumask(args->mask); - - /* Remove us, and any offline CPUS. */ - cpumask_and(to_cpumask(args->mask), cpus, cpu_online_mask); - cpumask_clear_cpu(smp_processor_id(), to_cpumask(args->mask)); - if (unlikely(cpumask_empty(to_cpumask(args->mask)))) - goto issue; - - if (va == TLB_FLUSH_ALL) { - args->op.cmd = MMUEXT_TLB_FLUSH_MULTI; - } else { - args->op.cmd = MMUEXT_INVLPG_MULTI; - args->op.arg1.linear_addr = va; - } - - MULTI_mmuext_op(mcs.mc, &args->op, 1, NULL, DOMID_SELF); - -issue: - xen_mc_issue(PARAVIRT_LAZY_MMU); -} static void xen_clts(void) { @@ -693,21 +594,6 @@ static void xen_write_cr0(unsigned long cr0) xen_mc_issue(PARAVIRT_LAZY_CPU); } -static void xen_write_cr2(unsigned long cr2) -{ - percpu_read(xen_vcpu)->arch.cr2 = cr2; -} - -static unsigned long xen_read_cr2(void) -{ - return percpu_read(xen_vcpu)->arch.cr2; -} - -static unsigned long xen_read_cr2_direct(void) -{ - return percpu_read(xen_vcpu_info.arch.cr2); -} - static void xen_write_cr4(unsigned long cr4) { cr4 &= ~X86_CR4_PGE; @@ -716,71 +602,6 @@ static void xen_write_cr4(unsigned long cr4) native_write_cr4(cr4); } -static unsigned long xen_read_cr3(void) -{ - return percpu_read(xen_cr3); -} - -static void set_current_cr3(void *v) -{ - percpu_write(xen_current_cr3, (unsigned long)v); -} - -static void __xen_write_cr3(bool kernel, unsigned long cr3) -{ - struct mmuext_op *op; - struct multicall_space mcs; - unsigned long mfn; - - if (cr3) - mfn = pfn_to_mfn(PFN_DOWN(cr3)); - else - mfn = 0; - - WARN_ON(mfn == 0 && kernel); - - mcs = __xen_mc_entry(sizeof(*op)); - - op = mcs.args; - op->cmd = kernel ? MMUEXT_NEW_BASEPTR : MMUEXT_NEW_USER_BASEPTR; - op->arg1.mfn = mfn; - - MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); - - if (kernel) { - percpu_write(xen_cr3, cr3); - - /* Update xen_current_cr3 once the batch has actually - been submitted. */ - xen_mc_callback(set_current_cr3, (void *)cr3); - } -} - -static void xen_write_cr3(unsigned long cr3) -{ - BUG_ON(preemptible()); - - xen_mc_batch(); /* disables interrupts */ - - /* Update while interrupts are disabled, so its atomic with - respect to ipis */ - percpu_write(xen_cr3, cr3); - - __xen_write_cr3(true, cr3); - -#ifdef CONFIG_X86_64 - { - pgd_t *user_pgd = xen_get_user_pgd(__va(cr3)); - if (user_pgd) - __xen_write_cr3(false, __pa(user_pgd)); - else - __xen_write_cr3(false, 0); - } -#endif - - xen_mc_issue(PARAVIRT_LAZY_CPU); /* interrupts restored */ -} - static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high) { int ret; @@ -822,185 +643,6 @@ static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high) return ret; } -/* Early in boot, while setting up the initial pagetable, assume - everything is pinned. */ -static __init void xen_alloc_pte_init(struct mm_struct *mm, unsigned long pfn) -{ -#ifdef CONFIG_FLATMEM - BUG_ON(mem_map); /* should only be used early */ -#endif - make_lowmem_page_readonly(__va(PFN_PHYS(pfn))); -} - -/* Early release_pte assumes that all pts are pinned, since there's - only init_mm and anything attached to that is pinned. */ -static void xen_release_pte_init(unsigned long pfn) -{ - make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); -} - -static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn) -{ - struct mmuext_op op; - op.cmd = cmd; - op.arg1.mfn = pfn_to_mfn(pfn); - if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF)) - BUG(); -} - -/* This needs to make sure the new pte page is pinned iff its being - attached to a pinned pagetable. */ -static void xen_alloc_ptpage(struct mm_struct *mm, unsigned long pfn, unsigned level) -{ - struct page *page = pfn_to_page(pfn); - - if (PagePinned(virt_to_page(mm->pgd))) { - SetPagePinned(page); - - vm_unmap_aliases(); - if (!PageHighMem(page)) { - make_lowmem_page_readonly(__va(PFN_PHYS((unsigned long)pfn))); - if (level == PT_PTE && USE_SPLIT_PTLOCKS) - pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn); - } else { - /* make sure there are no stray mappings of - this page */ - kmap_flush_unused(); - } - } -} - -static void xen_alloc_pte(struct mm_struct *mm, unsigned long pfn) -{ - xen_alloc_ptpage(mm, pfn, PT_PTE); -} - -static void xen_alloc_pmd(struct mm_struct *mm, unsigned long pfn) -{ - xen_alloc_ptpage(mm, pfn, PT_PMD); -} - -static int xen_pgd_alloc(struct mm_struct *mm) -{ - pgd_t *pgd = mm->pgd; - int ret = 0; - - BUG_ON(PagePinned(virt_to_page(pgd))); - -#ifdef CONFIG_X86_64 - { - struct page *page = virt_to_page(pgd); - pgd_t *user_pgd; - - BUG_ON(page->private != 0); - - ret = -ENOMEM; - - user_pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO); - page->private = (unsigned long)user_pgd; - - if (user_pgd != NULL) { - user_pgd[pgd_index(VSYSCALL_START)] = - __pgd(__pa(level3_user_vsyscall) | _PAGE_TABLE); - ret = 0; - } - - BUG_ON(PagePinned(virt_to_page(xen_get_user_pgd(pgd)))); - } -#endif - - return ret; -} - -static void xen_pgd_free(struct mm_struct *mm, pgd_t *pgd) -{ -#ifdef CONFIG_X86_64 - pgd_t *user_pgd = xen_get_user_pgd(pgd); - - if (user_pgd) - free_page((unsigned long)user_pgd); -#endif -} - -/* This should never happen until we're OK to use struct page */ -static void xen_release_ptpage(unsigned long pfn, unsigned level) -{ - struct page *page = pfn_to_page(pfn); - - if (PagePinned(page)) { - if (!PageHighMem(page)) { - if (level == PT_PTE && USE_SPLIT_PTLOCKS) - pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn); - make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); - } - ClearPagePinned(page); - } -} - -static void xen_release_pte(unsigned long pfn) -{ - xen_release_ptpage(pfn, PT_PTE); -} - -static void xen_release_pmd(unsigned long pfn) -{ - xen_release_ptpage(pfn, PT_PMD); -} - -#if PAGETABLE_LEVELS == 4 -static void xen_alloc_pud(struct mm_struct *mm, unsigned long pfn) -{ - xen_alloc_ptpage(mm, pfn, PT_PUD); -} - -static void xen_release_pud(unsigned long pfn) -{ - xen_release_ptpage(pfn, PT_PUD); -} -#endif - -#ifdef CONFIG_HIGHPTE -static void *xen_kmap_atomic_pte(struct page *page, enum km_type type) -{ - pgprot_t prot = PAGE_KERNEL; - - if (PagePinned(page)) - prot = PAGE_KERNEL_RO; - - if (0 && PageHighMem(page)) - printk("mapping highpte %lx type %d prot %s\n", - page_to_pfn(page), type, - (unsigned long)pgprot_val(prot) & _PAGE_RW ? "WRITE" : "READ"); - - return kmap_atomic_prot(page, type, prot); -} -#endif - -#ifdef CONFIG_X86_32 -static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte) -{ - /* If there's an existing pte, then don't allow _PAGE_RW to be set */ - if (pte_val_ma(*ptep) & _PAGE_PRESENT) - pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) & - pte_val_ma(pte)); - - return pte; -} - -/* Init-time set_pte while constructing initial pagetables, which - doesn't allow RO pagetable pages to be remapped RW */ -static __init void xen_set_pte_init(pte_t *ptep, pte_t pte) -{ - pte = mask_rw_pte(ptep, pte); - - xen_set_pte(ptep, pte); -} -#endif - -static __init void xen_pagetable_setup_start(pgd_t *base) -{ -} - void xen_setup_shared_info(void) { if (!xen_feature(XENFEAT_auto_translated_physmap)) { @@ -1021,37 +663,6 @@ void xen_setup_shared_info(void) xen_setup_mfn_list_list(); } -static __init void xen_pagetable_setup_done(pgd_t *base) -{ - xen_setup_shared_info(); -} - -static __init void xen_post_allocator_init(void) -{ - pv_mmu_ops.set_pte = xen_set_pte; - pv_mmu_ops.set_pmd = xen_set_pmd; - pv_mmu_ops.set_pud = xen_set_pud; -#if PAGETABLE_LEVELS == 4 - pv_mmu_ops.set_pgd = xen_set_pgd; -#endif - - /* This will work as long as patching hasn't happened yet - (which it hasn't) */ - pv_mmu_ops.alloc_pte = xen_alloc_pte; - pv_mmu_ops.alloc_pmd = xen_alloc_pmd; - pv_mmu_ops.release_pte = xen_release_pte; - pv_mmu_ops.release_pmd = xen_release_pmd; -#if PAGETABLE_LEVELS == 4 - pv_mmu_ops.alloc_pud = xen_alloc_pud; - pv_mmu_ops.release_pud = xen_release_pud; -#endif - -#ifdef CONFIG_X86_64 - SetPagePinned(virt_to_page(level3_user_vsyscall)); -#endif - xen_mark_init_mm_pinned(); -} - /* This is called once we have the cpu_possible_map */ void xen_setup_vcpu_info_placement(void) { @@ -1126,49 +737,6 @@ static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf, return ret; } -static void xen_set_fixmap(unsigned idx, unsigned long phys, pgprot_t prot) -{ - pte_t pte; - - phys >>= PAGE_SHIFT; - - switch (idx) { - case FIX_BTMAP_END ... FIX_BTMAP_BEGIN: -#ifdef CONFIG_X86_F00F_BUG - case FIX_F00F_IDT: -#endif -#ifdef CONFIG_X86_32 - case FIX_WP_TEST: - case FIX_VDSO: -# ifdef CONFIG_HIGHMEM - case FIX_KMAP_BEGIN ... FIX_KMAP_END: -# endif -#else - case VSYSCALL_LAST_PAGE ... VSYSCALL_FIRST_PAGE: -#endif -#ifdef CONFIG_X86_LOCAL_APIC - case FIX_APIC_BASE: /* maps dummy local APIC */ -#endif - pte = pfn_pte(phys, prot); - break; - - default: - pte = mfn_pte(phys, prot); - break; - } - - __native_set_fixmap(idx, pte); - -#ifdef CONFIG_X86_64 - /* Replicate changes to map the vsyscall page into the user - pagetable vsyscall mapping. */ - if (idx >= VSYSCALL_LAST_PAGE && idx <= VSYSCALL_FIRST_PAGE) { - unsigned long vaddr = __fix_to_virt(idx); - set_pte_vaddr_pud(level3_user_vsyscall, vaddr, pte); - } -#endif -} - static const struct pv_info xen_info __initdata = { .paravirt_enabled = 1, .shared_kernel_pmd = 0, @@ -1264,86 +832,6 @@ static const struct pv_apic_ops xen_apic_ops __initdata = { #endif }; -static const struct pv_mmu_ops xen_mmu_ops __initdata = { - .pagetable_setup_start = xen_pagetable_setup_start, - .pagetable_setup_done = xen_pagetable_setup_done, - - .read_cr2 = xen_read_cr2, - .write_cr2 = xen_write_cr2, - - .read_cr3 = xen_read_cr3, - .write_cr3 = xen_write_cr3, - - .flush_tlb_user = xen_flush_tlb, - .flush_tlb_kernel = xen_flush_tlb, - .flush_tlb_single = xen_flush_tlb_single, - .flush_tlb_others = xen_flush_tlb_others, - - .pte_update = paravirt_nop, - .pte_update_defer = paravirt_nop, - - .pgd_alloc = xen_pgd_alloc, - .pgd_free = xen_pgd_free, - - .alloc_pte = xen_alloc_pte_init, - .release_pte = xen_release_pte_init, - .alloc_pmd = xen_alloc_pte_init, - .alloc_pmd_clone = paravirt_nop, - .release_pmd = xen_release_pte_init, - -#ifdef CONFIG_HIGHPTE - .kmap_atomic_pte = xen_kmap_atomic_pte, -#endif - -#ifdef CONFIG_X86_64 - .set_pte = xen_set_pte, -#else - .set_pte = xen_set_pte_init, -#endif - .set_pte_at = xen_set_pte_at, - .set_pmd = xen_set_pmd_hyper, - - .ptep_modify_prot_start = __ptep_modify_prot_start, - .ptep_modify_prot_commit = __ptep_modify_prot_commit, - - .pte_val = xen_pte_val, - .pgd_val = xen_pgd_val, - - .make_pte = xen_make_pte, - .make_pgd = xen_make_pgd, - -#ifdef CONFIG_X86_PAE - .set_pte_atomic = xen_set_pte_atomic, - .set_pte_present = xen_set_pte_at, - .pte_clear = xen_pte_clear, - .pmd_clear = xen_pmd_clear, -#endif /* CONFIG_X86_PAE */ - .set_pud = xen_set_pud_hyper, - - .make_pmd = xen_make_pmd, - .pmd_val = xen_pmd_val, - -#if PAGETABLE_LEVELS == 4 - .pud_val = xen_pud_val, - .make_pud = xen_make_pud, - .set_pgd = xen_set_pgd_hyper, - - .alloc_pud = xen_alloc_pte_init, - .release_pud = xen_release_pte_init, -#endif /* PAGETABLE_LEVELS == 4 */ - - .activate_mm = xen_activate_mm, - .dup_mmap = xen_dup_mmap, - .exit_mmap = xen_exit_mmap, - - .lazy_mode = { - .enter = paravirt_enter_lazy_mmu, - .leave = xen_leave_lazy, - }, - - .set_fixmap = xen_set_fixmap, -}; - static void xen_reboot(int reason) { struct sched_shutdown r = { .reason = reason }; @@ -1386,223 +874,6 @@ static const struct machine_ops __initdata xen_machine_ops = { }; -static void __init xen_reserve_top(void) -{ -#ifdef CONFIG_X86_32 - unsigned long top = HYPERVISOR_VIRT_START; - struct xen_platform_parameters pp; - - if (HYPERVISOR_xen_version(XENVER_platform_parameters, &pp) == 0) - top = pp.virt_start; - - reserve_top_address(-top); -#endif /* CONFIG_X86_32 */ -} - -/* - * Like __va(), but returns address in the kernel mapping (which is - * all we have until the physical memory mapping has been set up. - */ -static void *__ka(phys_addr_t paddr) -{ -#ifdef CONFIG_X86_64 - return (void *)(paddr + __START_KERNEL_map); -#else - return __va(paddr); -#endif -} - -/* Convert a machine address to physical address */ -static unsigned long m2p(phys_addr_t maddr) -{ - phys_addr_t paddr; - - maddr &= PTE_PFN_MASK; - paddr = mfn_to_pfn(maddr >> PAGE_SHIFT) << PAGE_SHIFT; - - return paddr; -} - -/* Convert a machine address to kernel virtual */ -static void *m2v(phys_addr_t maddr) -{ - return __ka(m2p(maddr)); -} - -static void set_page_prot(void *addr, pgprot_t prot) -{ - unsigned long pfn = __pa(addr) >> PAGE_SHIFT; - pte_t pte = pfn_pte(pfn, prot); - - if (HYPERVISOR_update_va_mapping((unsigned long)addr, pte, 0)) - BUG(); -} - -static __init void xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn) -{ - unsigned pmdidx, pteidx; - unsigned ident_pte; - unsigned long pfn; - - ident_pte = 0; - pfn = 0; - for (pmdidx = 0; pmdidx < PTRS_PER_PMD && pfn < max_pfn; pmdidx++) { - pte_t *pte_page; - - /* Reuse or allocate a page of ptes */ - if (pmd_present(pmd[pmdidx])) - pte_page = m2v(pmd[pmdidx].pmd); - else { - /* Check for free pte pages */ - if (ident_pte == ARRAY_SIZE(level1_ident_pgt)) - break; - - pte_page = &level1_ident_pgt[ident_pte]; - ident_pte += PTRS_PER_PTE; - - pmd[pmdidx] = __pmd(__pa(pte_page) | _PAGE_TABLE); - } - - /* Install mappings */ - for (pteidx = 0; pteidx < PTRS_PER_PTE; pteidx++, pfn++) { - pte_t pte; - - if (pfn > max_pfn_mapped) - max_pfn_mapped = pfn; - - if (!pte_none(pte_page[pteidx])) - continue; - - pte = pfn_pte(pfn, PAGE_KERNEL_EXEC); - pte_page[pteidx] = pte; - } - } - - for (pteidx = 0; pteidx < ident_pte; pteidx += PTRS_PER_PTE) - set_page_prot(&level1_ident_pgt[pteidx], PAGE_KERNEL_RO); - - set_page_prot(pmd, PAGE_KERNEL_RO); -} - -#ifdef CONFIG_X86_64 -static void convert_pfn_mfn(void *v) -{ - pte_t *pte = v; - int i; - - /* All levels are converted the same way, so just treat them - as ptes. */ - for (i = 0; i < PTRS_PER_PTE; i++) - pte[i] = xen_make_pte(pte[i].pte); -} - -/* - * Set up the inital kernel pagetable. - * - * We can construct this by grafting the Xen provided pagetable into - * head_64.S's preconstructed pagetables. We copy the Xen L2's into - * level2_ident_pgt, level2_kernel_pgt and level2_fixmap_pgt. This - * means that only the kernel has a physical mapping to start with - - * but that's enough to get __va working. We need to fill in the rest - * of the physical mapping once some sort of allocator has been set - * up. - */ -static __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, - unsigned long max_pfn) -{ - pud_t *l3; - pmd_t *l2; - - /* Zap identity mapping */ - init_level4_pgt[0] = __pgd(0); - - /* Pre-constructed entries are in pfn, so convert to mfn */ - convert_pfn_mfn(init_level4_pgt); - convert_pfn_mfn(level3_ident_pgt); - convert_pfn_mfn(level3_kernel_pgt); - - l3 = m2v(pgd[pgd_index(__START_KERNEL_map)].pgd); - l2 = m2v(l3[pud_index(__START_KERNEL_map)].pud); - - memcpy(level2_ident_pgt, l2, sizeof(pmd_t) * PTRS_PER_PMD); - memcpy(level2_kernel_pgt, l2, sizeof(pmd_t) * PTRS_PER_PMD); - - l3 = m2v(pgd[pgd_index(__START_KERNEL_map + PMD_SIZE)].pgd); - l2 = m2v(l3[pud_index(__START_KERNEL_map + PMD_SIZE)].pud); - memcpy(level2_fixmap_pgt, l2, sizeof(pmd_t) * PTRS_PER_PMD); - - /* Set up identity map */ - xen_map_identity_early(level2_ident_pgt, max_pfn); - - /* Make pagetable pieces RO */ - set_page_prot(init_level4_pgt, PAGE_KERNEL_RO); - set_page_prot(level3_ident_pgt, PAGE_KERNEL_RO); - set_page_prot(level3_kernel_pgt, PAGE_KERNEL_RO); - set_page_prot(level3_user_vsyscall, PAGE_KERNEL_RO); - set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO); - set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO); - - /* Pin down new L4 */ - pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE, - PFN_DOWN(__pa_symbol(init_level4_pgt))); - - /* Unpin Xen-provided one */ - pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd))); - - /* Switch over */ - pgd = init_level4_pgt; - - /* - * At this stage there can be no user pgd, and no page - * structure to attach it to, so make sure we just set kernel - * pgd. - */ - xen_mc_batch(); - __xen_write_cr3(true, __pa(pgd)); - xen_mc_issue(PARAVIRT_LAZY_CPU); - - reserve_early(__pa(xen_start_info->pt_base), - __pa(xen_start_info->pt_base + - xen_start_info->nr_pt_frames * PAGE_SIZE), - "XEN PAGETABLES"); - - return pgd; -} -#else /* !CONFIG_X86_64 */ -static pmd_t level2_kernel_pgt[PTRS_PER_PMD] __page_aligned_bss; - -static __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, - unsigned long max_pfn) -{ - pmd_t *kernel_pmd; - - init_pg_tables_start = __pa(pgd); - init_pg_tables_end = __pa(pgd) + xen_start_info->nr_pt_frames*PAGE_SIZE; - max_pfn_mapped = PFN_DOWN(init_pg_tables_end + 512*1024); - - kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd); - memcpy(level2_kernel_pgt, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD); - - xen_map_identity_early(level2_kernel_pgt, max_pfn); - - memcpy(swapper_pg_dir, pgd, sizeof(pgd_t) * PTRS_PER_PGD); - set_pgd(&swapper_pg_dir[KERNEL_PGD_BOUNDARY], - __pgd(__pa(level2_kernel_pgt) | _PAGE_PRESENT)); - - set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO); - set_page_prot(swapper_pg_dir, PAGE_KERNEL_RO); - set_page_prot(empty_zero_page, PAGE_KERNEL_RO); - - pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd))); - - xen_write_cr3(__pa(swapper_pg_dir)); - - pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(swapper_pg_dir))); - - return swapper_pg_dir; -} -#endif /* CONFIG_X86_64 */ - /* First C function to be called on Xen boot */ asmlinkage void __init xen_start_kernel(void) { diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 98cb9869eb2..94e452c0b00 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -55,6 +56,8 @@ #include #include +#include +#include #include "multicalls.h" #include "mmu.h" @@ -114,6 +117,37 @@ static inline void check_zero(void) #endif /* CONFIG_XEN_DEBUG_FS */ + +/* + * Identity map, in addition to plain kernel map. This needs to be + * large enough to allocate page table pages to allocate the rest. + * Each page can map 2MB. + */ +static pte_t level1_ident_pgt[PTRS_PER_PTE * 4] __page_aligned_bss; + +#ifdef CONFIG_X86_64 +/* l3 pud for userspace vsyscall mapping */ +static pud_t level3_user_vsyscall[PTRS_PER_PUD] __page_aligned_bss; +#endif /* CONFIG_X86_64 */ + +/* + * Note about cr3 (pagetable base) values: + * + * xen_cr3 contains the current logical cr3 value; it contains the + * last set cr3. This may not be the current effective cr3, because + * its update may be being lazily deferred. However, a vcpu looking + * at its own cr3 can use this value knowing that it everything will + * be self-consistent. + * + * xen_current_cr3 contains the actual vcpu cr3; it is set once the + * hypercall to set the vcpu cr3 is complete (so it may be a little + * out of date, but it will never be set early). If one vcpu is + * looking at another vcpu's cr3 value, it should use this variable. + */ +DEFINE_PER_CPU(unsigned long, xen_cr3); /* cr3 stored as physaddr */ +DEFINE_PER_CPU(unsigned long, xen_current_cr3); /* actual vcpu cr3 */ + + /* * Just beyond the highest usermode address. STACK_TOP_MAX has a * redzone above it, so round it up to a PGD boundary. @@ -1152,6 +1186,672 @@ void xen_exit_mmap(struct mm_struct *mm) spin_unlock(&mm->page_table_lock); } +static __init void xen_pagetable_setup_start(pgd_t *base) +{ +} + +static __init void xen_pagetable_setup_done(pgd_t *base) +{ + xen_setup_shared_info(); +} + +static void xen_write_cr2(unsigned long cr2) +{ + percpu_read(xen_vcpu)->arch.cr2 = cr2; +} + +static unsigned long xen_read_cr2(void) +{ + return percpu_read(xen_vcpu)->arch.cr2; +} + +unsigned long xen_read_cr2_direct(void) +{ + return percpu_read(xen_vcpu_info.arch.cr2); +} + +static void xen_flush_tlb(void) +{ + struct mmuext_op *op; + struct multicall_space mcs; + + preempt_disable(); + + mcs = xen_mc_entry(sizeof(*op)); + + op = mcs.args; + op->cmd = MMUEXT_TLB_FLUSH_LOCAL; + MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); + + xen_mc_issue(PARAVIRT_LAZY_MMU); + + preempt_enable(); +} + +static void xen_flush_tlb_single(unsigned long addr) +{ + struct mmuext_op *op; + struct multicall_space mcs; + + preempt_disable(); + + mcs = xen_mc_entry(sizeof(*op)); + op = mcs.args; + op->cmd = MMUEXT_INVLPG_LOCAL; + op->arg1.linear_addr = addr & PAGE_MASK; + MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); + + xen_mc_issue(PARAVIRT_LAZY_MMU); + + preempt_enable(); +} + +static void xen_flush_tlb_others(const struct cpumask *cpus, + struct mm_struct *mm, unsigned long va) +{ + struct { + struct mmuext_op op; + DECLARE_BITMAP(mask, NR_CPUS); + } *args; + struct multicall_space mcs; + + BUG_ON(cpumask_empty(cpus)); + BUG_ON(!mm); + + mcs = xen_mc_entry(sizeof(*args)); + args = mcs.args; + args->op.arg2.vcpumask = to_cpumask(args->mask); + + /* Remove us, and any offline CPUS. */ + cpumask_and(to_cpumask(args->mask), cpus, cpu_online_mask); + cpumask_clear_cpu(smp_processor_id(), to_cpumask(args->mask)); + if (unlikely(cpumask_empty(to_cpumask(args->mask)))) + goto issue; + + if (va == TLB_FLUSH_ALL) { + args->op.cmd = MMUEXT_TLB_FLUSH_MULTI; + } else { + args->op.cmd = MMUEXT_INVLPG_MULTI; + args->op.arg1.linear_addr = va; + } + + MULTI_mmuext_op(mcs.mc, &args->op, 1, NULL, DOMID_SELF); + +issue: + xen_mc_issue(PARAVIRT_LAZY_MMU); +} + +static unsigned long xen_read_cr3(void) +{ + return percpu_read(xen_cr3); +} + +static void set_current_cr3(void *v) +{ + percpu_write(xen_current_cr3, (unsigned long)v); +} + +static void __xen_write_cr3(bool kernel, unsigned long cr3) +{ + struct mmuext_op *op; + struct multicall_space mcs; + unsigned long mfn; + + if (cr3) + mfn = pfn_to_mfn(PFN_DOWN(cr3)); + else + mfn = 0; + + WARN_ON(mfn == 0 && kernel); + + mcs = __xen_mc_entry(sizeof(*op)); + + op = mcs.args; + op->cmd = kernel ? MMUEXT_NEW_BASEPTR : MMUEXT_NEW_USER_BASEPTR; + op->arg1.mfn = mfn; + + MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); + + if (kernel) { + percpu_write(xen_cr3, cr3); + + /* Update xen_current_cr3 once the batch has actually + been submitted. */ + xen_mc_callback(set_current_cr3, (void *)cr3); + } +} + +static void xen_write_cr3(unsigned long cr3) +{ + BUG_ON(preemptible()); + + xen_mc_batch(); /* disables interrupts */ + + /* Update while interrupts are disabled, so its atomic with + respect to ipis */ + percpu_write(xen_cr3, cr3); + + __xen_write_cr3(true, cr3); + +#ifdef CONFIG_X86_64 + { + pgd_t *user_pgd = xen_get_user_pgd(__va(cr3)); + if (user_pgd) + __xen_write_cr3(false, __pa(user_pgd)); + else + __xen_write_cr3(false, 0); + } +#endif + + xen_mc_issue(PARAVIRT_LAZY_CPU); /* interrupts restored */ +} + +static int xen_pgd_alloc(struct mm_struct *mm) +{ + pgd_t *pgd = mm->pgd; + int ret = 0; + + BUG_ON(PagePinned(virt_to_page(pgd))); + +#ifdef CONFIG_X86_64 + { + struct page *page = virt_to_page(pgd); + pgd_t *user_pgd; + + BUG_ON(page->private != 0); + + ret = -ENOMEM; + + user_pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO); + page->private = (unsigned long)user_pgd; + + if (user_pgd != NULL) { + user_pgd[pgd_index(VSYSCALL_START)] = + __pgd(__pa(level3_user_vsyscall) | _PAGE_TABLE); + ret = 0; + } + + BUG_ON(PagePinned(virt_to_page(xen_get_user_pgd(pgd)))); + } +#endif + + return ret; +} + +static void xen_pgd_free(struct mm_struct *mm, pgd_t *pgd) +{ +#ifdef CONFIG_X86_64 + pgd_t *user_pgd = xen_get_user_pgd(pgd); + + if (user_pgd) + free_page((unsigned long)user_pgd); +#endif +} + + +/* Early in boot, while setting up the initial pagetable, assume + everything is pinned. */ +static __init void xen_alloc_pte_init(struct mm_struct *mm, unsigned long pfn) +{ +#ifdef CONFIG_FLATMEM + BUG_ON(mem_map); /* should only be used early */ +#endif + make_lowmem_page_readonly(__va(PFN_PHYS(pfn))); +} + +/* Early release_pte assumes that all pts are pinned, since there's + only init_mm and anything attached to that is pinned. */ +static void xen_release_pte_init(unsigned long pfn) +{ + make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); +} + +static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn) +{ + struct mmuext_op op; + op.cmd = cmd; + op.arg1.mfn = pfn_to_mfn(pfn); + if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF)) + BUG(); +} + +/* This needs to make sure the new pte page is pinned iff its being + attached to a pinned pagetable. */ +static void xen_alloc_ptpage(struct mm_struct *mm, unsigned long pfn, unsigned level) +{ + struct page *page = pfn_to_page(pfn); + + if (PagePinned(virt_to_page(mm->pgd))) { + SetPagePinned(page); + + vm_unmap_aliases(); + if (!PageHighMem(page)) { + make_lowmem_page_readonly(__va(PFN_PHYS((unsigned long)pfn))); + if (level == PT_PTE && USE_SPLIT_PTLOCKS) + pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn); + } else { + /* make sure there are no stray mappings of + this page */ + kmap_flush_unused(); + } + } +} + +static void xen_alloc_pte(struct mm_struct *mm, unsigned long pfn) +{ + xen_alloc_ptpage(mm, pfn, PT_PTE); +} + +static void xen_alloc_pmd(struct mm_struct *mm, unsigned long pfn) +{ + xen_alloc_ptpage(mm, pfn, PT_PMD); +} + +/* This should never happen until we're OK to use struct page */ +static void xen_release_ptpage(unsigned long pfn, unsigned level) +{ + struct page *page = pfn_to_page(pfn); + + if (PagePinned(page)) { + if (!PageHighMem(page)) { + if (level == PT_PTE && USE_SPLIT_PTLOCKS) + pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn); + make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); + } + ClearPagePinned(page); + } +} + +static void xen_release_pte(unsigned long pfn) +{ + xen_release_ptpage(pfn, PT_PTE); +} + +static void xen_release_pmd(unsigned long pfn) +{ + xen_release_ptpage(pfn, PT_PMD); +} + +#if PAGETABLE_LEVELS == 4 +static void xen_alloc_pud(struct mm_struct *mm, unsigned long pfn) +{ + xen_alloc_ptpage(mm, pfn, PT_PUD); +} + +static void xen_release_pud(unsigned long pfn) +{ + xen_release_ptpage(pfn, PT_PUD); +} +#endif + +void __init xen_reserve_top(void) +{ +#ifdef CONFIG_X86_32 + unsigned long top = HYPERVISOR_VIRT_START; + struct xen_platform_parameters pp; + + if (HYPERVISOR_xen_version(XENVER_platform_parameters, &pp) == 0) + top = pp.virt_start; + + reserve_top_address(-top); +#endif /* CONFIG_X86_32 */ +} + +/* + * Like __va(), but returns address in the kernel mapping (which is + * all we have until the physical memory mapping has been set up. + */ +static void *__ka(phys_addr_t paddr) +{ +#ifdef CONFIG_X86_64 + return (void *)(paddr + __START_KERNEL_map); +#else + return __va(paddr); +#endif +} + +/* Convert a machine address to physical address */ +static unsigned long m2p(phys_addr_t maddr) +{ + phys_addr_t paddr; + + maddr &= PTE_PFN_MASK; + paddr = mfn_to_pfn(maddr >> PAGE_SHIFT) << PAGE_SHIFT; + + return paddr; +} + +/* Convert a machine address to kernel virtual */ +static void *m2v(phys_addr_t maddr) +{ + return __ka(m2p(maddr)); +} + +static void set_page_prot(void *addr, pgprot_t prot) +{ + unsigned long pfn = __pa(addr) >> PAGE_SHIFT; + pte_t pte = pfn_pte(pfn, prot); + + if (HYPERVISOR_update_va_mapping((unsigned long)addr, pte, 0)) + BUG(); +} + +static __init void xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn) +{ + unsigned pmdidx, pteidx; + unsigned ident_pte; + unsigned long pfn; + + ident_pte = 0; + pfn = 0; + for (pmdidx = 0; pmdidx < PTRS_PER_PMD && pfn < max_pfn; pmdidx++) { + pte_t *pte_page; + + /* Reuse or allocate a page of ptes */ + if (pmd_present(pmd[pmdidx])) + pte_page = m2v(pmd[pmdidx].pmd); + else { + /* Check for free pte pages */ + if (ident_pte == ARRAY_SIZE(level1_ident_pgt)) + break; + + pte_page = &level1_ident_pgt[ident_pte]; + ident_pte += PTRS_PER_PTE; + + pmd[pmdidx] = __pmd(__pa(pte_page) | _PAGE_TABLE); + } + + /* Install mappings */ + for (pteidx = 0; pteidx < PTRS_PER_PTE; pteidx++, pfn++) { + pte_t pte; + + if (pfn > max_pfn_mapped) + max_pfn_mapped = pfn; + + if (!pte_none(pte_page[pteidx])) + continue; + + pte = pfn_pte(pfn, PAGE_KERNEL_EXEC); + pte_page[pteidx] = pte; + } + } + + for (pteidx = 0; pteidx < ident_pte; pteidx += PTRS_PER_PTE) + set_page_prot(&level1_ident_pgt[pteidx], PAGE_KERNEL_RO); + + set_page_prot(pmd, PAGE_KERNEL_RO); +} + +#ifdef CONFIG_X86_64 +static void convert_pfn_mfn(void *v) +{ + pte_t *pte = v; + int i; + + /* All levels are converted the same way, so just treat them + as ptes. */ + for (i = 0; i < PTRS_PER_PTE; i++) + pte[i] = xen_make_pte(pte[i].pte); +} + +/* + * Set up the inital kernel pagetable. + * + * We can construct this by grafting the Xen provided pagetable into + * head_64.S's preconstructed pagetables. We copy the Xen L2's into + * level2_ident_pgt, level2_kernel_pgt and level2_fixmap_pgt. This + * means that only the kernel has a physical mapping to start with - + * but that's enough to get __va working. We need to fill in the rest + * of the physical mapping once some sort of allocator has been set + * up. + */ +__init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, + unsigned long max_pfn) +{ + pud_t *l3; + pmd_t *l2; + + /* Zap identity mapping */ + init_level4_pgt[0] = __pgd(0); + + /* Pre-constructed entries are in pfn, so convert to mfn */ + convert_pfn_mfn(init_level4_pgt); + convert_pfn_mfn(level3_ident_pgt); + convert_pfn_mfn(level3_kernel_pgt); + + l3 = m2v(pgd[pgd_index(__START_KERNEL_map)].pgd); + l2 = m2v(l3[pud_index(__START_KERNEL_map)].pud); + + memcpy(level2_ident_pgt, l2, sizeof(pmd_t) * PTRS_PER_PMD); + memcpy(level2_kernel_pgt, l2, sizeof(pmd_t) * PTRS_PER_PMD); + + l3 = m2v(pgd[pgd_index(__START_KERNEL_map + PMD_SIZE)].pgd); + l2 = m2v(l3[pud_index(__START_KERNEL_map + PMD_SIZE)].pud); + memcpy(level2_fixmap_pgt, l2, sizeof(pmd_t) * PTRS_PER_PMD); + + /* Set up identity map */ + xen_map_identity_early(level2_ident_pgt, max_pfn); + + /* Make pagetable pieces RO */ + set_page_prot(init_level4_pgt, PAGE_KERNEL_RO); + set_page_prot(level3_ident_pgt, PAGE_KERNEL_RO); + set_page_prot(level3_kernel_pgt, PAGE_KERNEL_RO); + set_page_prot(level3_user_vsyscall, PAGE_KERNEL_RO); + set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO); + set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO); + + /* Pin down new L4 */ + pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE, + PFN_DOWN(__pa_symbol(init_level4_pgt))); + + /* Unpin Xen-provided one */ + pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd))); + + /* Switch over */ + pgd = init_level4_pgt; + + /* + * At this stage there can be no user pgd, and no page + * structure to attach it to, so make sure we just set kernel + * pgd. + */ + xen_mc_batch(); + __xen_write_cr3(true, __pa(pgd)); + xen_mc_issue(PARAVIRT_LAZY_CPU); + + reserve_early(__pa(xen_start_info->pt_base), + __pa(xen_start_info->pt_base + + xen_start_info->nr_pt_frames * PAGE_SIZE), + "XEN PAGETABLES"); + + return pgd; +} +#else /* !CONFIG_X86_64 */ +static pmd_t level2_kernel_pgt[PTRS_PER_PMD] __page_aligned_bss; + +__init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, + unsigned long max_pfn) +{ + pmd_t *kernel_pmd; + + init_pg_tables_start = __pa(pgd); + init_pg_tables_end = __pa(pgd) + xen_start_info->nr_pt_frames*PAGE_SIZE; + max_pfn_mapped = PFN_DOWN(init_pg_tables_end + 512*1024); + + kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd); + memcpy(level2_kernel_pgt, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD); + + xen_map_identity_early(level2_kernel_pgt, max_pfn); + + memcpy(swapper_pg_dir, pgd, sizeof(pgd_t) * PTRS_PER_PGD); + set_pgd(&swapper_pg_dir[KERNEL_PGD_BOUNDARY], + __pgd(__pa(level2_kernel_pgt) | _PAGE_PRESENT)); + + set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO); + set_page_prot(swapper_pg_dir, PAGE_KERNEL_RO); + set_page_prot(empty_zero_page, PAGE_KERNEL_RO); + + pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd))); + + xen_write_cr3(__pa(swapper_pg_dir)); + + pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(swapper_pg_dir))); + + return swapper_pg_dir; +} +#endif /* CONFIG_X86_64 */ + +static void xen_set_fixmap(unsigned idx, unsigned long phys, pgprot_t prot) +{ + pte_t pte; + + phys >>= PAGE_SHIFT; + + switch (idx) { + case FIX_BTMAP_END ... FIX_BTMAP_BEGIN: +#ifdef CONFIG_X86_F00F_BUG + case FIX_F00F_IDT: +#endif +#ifdef CONFIG_X86_32 + case FIX_WP_TEST: + case FIX_VDSO: +# ifdef CONFIG_HIGHMEM + case FIX_KMAP_BEGIN ... FIX_KMAP_END: +# endif +#else + case VSYSCALL_LAST_PAGE ... VSYSCALL_FIRST_PAGE: +#endif +#ifdef CONFIG_X86_LOCAL_APIC + case FIX_APIC_BASE: /* maps dummy local APIC */ +#endif + pte = pfn_pte(phys, prot); + break; + + default: + pte = mfn_pte(phys, prot); + break; + } + + __native_set_fixmap(idx, pte); + +#ifdef CONFIG_X86_64 + /* Replicate changes to map the vsyscall page into the user + pagetable vsyscall mapping. */ + if (idx >= VSYSCALL_LAST_PAGE && idx <= VSYSCALL_FIRST_PAGE) { + unsigned long vaddr = __fix_to_virt(idx); + set_pte_vaddr_pud(level3_user_vsyscall, vaddr, pte); + } +#endif +} + +__init void xen_post_allocator_init(void) +{ + pv_mmu_ops.set_pte = xen_set_pte; + pv_mmu_ops.set_pmd = xen_set_pmd; + pv_mmu_ops.set_pud = xen_set_pud; +#if PAGETABLE_LEVELS == 4 + pv_mmu_ops.set_pgd = xen_set_pgd; +#endif + + /* This will work as long as patching hasn't happened yet + (which it hasn't) */ + pv_mmu_ops.alloc_pte = xen_alloc_pte; + pv_mmu_ops.alloc_pmd = xen_alloc_pmd; + pv_mmu_ops.release_pte = xen_release_pte; + pv_mmu_ops.release_pmd = xen_release_pmd; +#if PAGETABLE_LEVELS == 4 + pv_mmu_ops.alloc_pud = xen_alloc_pud; + pv_mmu_ops.release_pud = xen_release_pud; +#endif + +#ifdef CONFIG_X86_64 + SetPagePinned(virt_to_page(level3_user_vsyscall)); +#endif + xen_mark_init_mm_pinned(); +} + + +const struct pv_mmu_ops xen_mmu_ops __initdata = { + .pagetable_setup_start = xen_pagetable_setup_start, + .pagetable_setup_done = xen_pagetable_setup_done, + + .read_cr2 = xen_read_cr2, + .write_cr2 = xen_write_cr2, + + .read_cr3 = xen_read_cr3, + .write_cr3 = xen_write_cr3, + + .flush_tlb_user = xen_flush_tlb, + .flush_tlb_kernel = xen_flush_tlb, + .flush_tlb_single = xen_flush_tlb_single, + .flush_tlb_others = xen_flush_tlb_others, + + .pte_update = paravirt_nop, + .pte_update_defer = paravirt_nop, + + .pgd_alloc = xen_pgd_alloc, + .pgd_free = xen_pgd_free, + + .alloc_pte = xen_alloc_pte_init, + .release_pte = xen_release_pte_init, + .alloc_pmd = xen_alloc_pte_init, + .alloc_pmd_clone = paravirt_nop, + .release_pmd = xen_release_pte_init, + +#ifdef CONFIG_HIGHPTE + .kmap_atomic_pte = xen_kmap_atomic_pte, +#endif + +#ifdef CONFIG_X86_64 + .set_pte = xen_set_pte, +#else + .set_pte = xen_set_pte_init, +#endif + .set_pte_at = xen_set_pte_at, + .set_pmd = xen_set_pmd_hyper, + + .ptep_modify_prot_start = __ptep_modify_prot_start, + .ptep_modify_prot_commit = __ptep_modify_prot_commit, + + .pte_val = xen_pte_val, + .pgd_val = xen_pgd_val, + + .make_pte = xen_make_pte, + .make_pgd = xen_make_pgd, + +#ifdef CONFIG_X86_PAE + .set_pte_atomic = xen_set_pte_atomic, + .set_pte_present = xen_set_pte_at, + .pte_clear = xen_pte_clear, + .pmd_clear = xen_pmd_clear, +#endif /* CONFIG_X86_PAE */ + .set_pud = xen_set_pud_hyper, + + .make_pmd = xen_make_pmd, + .pmd_val = xen_pmd_val, + +#if PAGETABLE_LEVELS == 4 + .pud_val = xen_pud_val, + .make_pud = xen_make_pud, + .set_pgd = xen_set_pgd_hyper, + + .alloc_pud = xen_alloc_pte_init, + .release_pud = xen_release_pte_init, +#endif /* PAGETABLE_LEVELS == 4 */ + + .activate_mm = xen_activate_mm, + .dup_mmap = xen_dup_mmap, + .exit_mmap = xen_exit_mmap, + + .lazy_mode = { + .enter = paravirt_enter_lazy_mmu, + .leave = xen_leave_lazy, + }, + + .set_fixmap = xen_set_fixmap, +}; + + #ifdef CONFIG_XEN_DEBUG_FS static struct dentry *d_mmu_debug; diff --git a/arch/x86/xen/mmu.h b/arch/x86/xen/mmu.h index 98d71659da5..24d1b44a337 100644 --- a/arch/x86/xen/mmu.h +++ b/arch/x86/xen/mmu.h @@ -54,4 +54,7 @@ pte_t xen_ptep_modify_prot_start(struct mm_struct *mm, unsigned long addr, pte_t void xen_ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte); +unsigned long xen_read_cr2_direct(void); + +extern const struct pv_mmu_ops xen_mmu_ops; #endif /* _XEN_MMU_H */ diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index c1f8faf0a2c..11913fc94c1 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -13,6 +13,7 @@ extern const char xen_failsafe_callback[]; struct trap_info; void xen_copy_trap_info(struct trap_info *traps); +DECLARE_PER_CPU(struct vcpu_info, xen_vcpu_info); DECLARE_PER_CPU(unsigned long, xen_cr3); DECLARE_PER_CPU(unsigned long, xen_current_cr3); @@ -22,6 +23,13 @@ extern struct shared_info *HYPERVISOR_shared_info; void xen_setup_mfn_list_list(void); void xen_setup_shared_info(void); +void xen_setup_machphys_mapping(void); +pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn); +void xen_ident_map_ISA(void); +void xen_reserve_top(void); + +void xen_leave_lazy(void); +void xen_post_allocator_init(void); char * __init xen_memory_setup(void); void __init xen_arch_setup(void); -- GitLab From 41edafdb78feac1d1f8823846209975fde990633 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 28 Jan 2009 14:35:02 -0800 Subject: [PATCH 1026/4982] x86/pvops: add a paravirt_ident functions to allow special patching Impact: Optimization Several paravirt ops implementations simply return their arguments, the most obvious being the make_pte/pte_val class of operations on native. On 32-bit, the identity function is literally a no-op, as the calling convention uses the same registers for the first argument and return. On 64-bit, it can be implemented with a single "mov". This patch adds special identity functions for 32 and 64 bit argument, and machinery to recognize them and replace them with either nops or a mov as appropriate. At the moment, the only users for the identity functions are the pagetable entry conversion functions. The result is a measureable improvement on pagetable-heavy benchmarks (2-3%, reducing the pvops overhead from 5 to 2%). Signed-off-by: Jeremy Fitzhardinge Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/paravirt.h | 5 ++ arch/x86/kernel/paravirt.c | 75 +++++++++++++++++++++++++---- arch/x86/kernel/paravirt_patch_32.c | 12 +++++ arch/x86/kernel/paravirt_patch_64.c | 15 ++++++ 4 files changed, 98 insertions(+), 9 deletions(-) diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 17577888709..961d10c12f1 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -388,6 +388,8 @@ extern struct pv_lock_ops pv_lock_ops; asm("start_" #ops "_" #name ": " code "; end_" #ops "_" #name ":") unsigned paravirt_patch_nop(void); +unsigned paravirt_patch_ident_32(void *insnbuf, unsigned len); +unsigned paravirt_patch_ident_64(void *insnbuf, unsigned len); unsigned paravirt_patch_ignore(unsigned len); unsigned paravirt_patch_call(void *insnbuf, const void *target, u16 tgt_clobbers, @@ -1371,6 +1373,9 @@ static inline void __set_fixmap(unsigned /* enum fixed_addresses */ idx, } void _paravirt_nop(void); +u32 _paravirt_ident_32(u32); +u64 _paravirt_ident_64(u64); + #define paravirt_nop ((void *)_paravirt_nop) void paravirt_use_bytelocks(void); diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index 202514be592..dd25e2b1593 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -44,6 +44,17 @@ void _paravirt_nop(void) { } +/* identity function, which can be inlined */ +u32 _paravirt_ident_32(u32 x) +{ + return x; +} + +u64 _paravirt_ident_64(u64 x) +{ + return x; +} + static void __init default_banner(void) { printk(KERN_INFO "Booting paravirtualized kernel on %s\n", @@ -138,9 +149,16 @@ unsigned paravirt_patch_default(u8 type, u16 clobbers, void *insnbuf, if (opfunc == NULL) /* If there's no function, patch it with a ud2a (BUG) */ ret = paravirt_patch_insns(insnbuf, len, ud2a, ud2a+sizeof(ud2a)); - else if (opfunc == paravirt_nop) + else if (opfunc == _paravirt_nop) /* If the operation is a nop, then nop the callsite */ ret = paravirt_patch_nop(); + + /* identity functions just return their single argument */ + else if (opfunc == _paravirt_ident_32) + ret = paravirt_patch_ident_32(insnbuf, len); + else if (opfunc == _paravirt_ident_64) + ret = paravirt_patch_ident_64(insnbuf, len); + else if (type == PARAVIRT_PATCH(pv_cpu_ops.iret) || type == PARAVIRT_PATCH(pv_cpu_ops.irq_enable_sysexit) || type == PARAVIRT_PATCH(pv_cpu_ops.usergs_sysret32) || @@ -373,6 +391,45 @@ struct pv_apic_ops pv_apic_ops = { #endif }; +typedef pte_t make_pte_t(pteval_t); +typedef pmd_t make_pmd_t(pmdval_t); +typedef pud_t make_pud_t(pudval_t); +typedef pgd_t make_pgd_t(pgdval_t); + +typedef pteval_t pte_val_t(pte_t); +typedef pmdval_t pmd_val_t(pmd_t); +typedef pudval_t pud_val_t(pud_t); +typedef pgdval_t pgd_val_t(pgd_t); + + +#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_PAE) +/* 32-bit pagetable entries */ +#define paravirt_native_make_pte (make_pte_t *)_paravirt_ident_32 +#define paravirt_native_pte_val (pte_val_t *)_paravirt_ident_32 + +#define paravirt_native_make_pmd (make_pmd_t *)_paravirt_ident_32 +#define paravirt_native_pmd_val (pmd_val_t *)_paravirt_ident_32 + +#define paravirt_native_make_pud (make_pud_t *)_paravirt_ident_32 +#define paravirt_native_pud_val (pud_val_t *)_paravirt_ident_32 + +#define paravirt_native_make_pgd (make_pgd_t *)_paravirt_ident_32 +#define paravirt_native_pgd_val (pgd_val_t *)_paravirt_ident_32 +#else +/* 64-bit pagetable entries */ +#define paravirt_native_make_pte (make_pte_t *)_paravirt_ident_64 +#define paravirt_native_pte_val (pte_val_t *)_paravirt_ident_64 + +#define paravirt_native_make_pmd (make_pmd_t *)_paravirt_ident_64 +#define paravirt_native_pmd_val (pmd_val_t *)_paravirt_ident_64 + +#define paravirt_native_make_pud (make_pud_t *)_paravirt_ident_64 +#define paravirt_native_pud_val (pud_val_t *)_paravirt_ident_64 + +#define paravirt_native_make_pgd (make_pgd_t *)_paravirt_ident_64 +#define paravirt_native_pgd_val (pgd_val_t *)_paravirt_ident_64 +#endif + struct pv_mmu_ops pv_mmu_ops = { #ifndef CONFIG_X86_64 .pagetable_setup_start = native_pagetable_setup_start, @@ -424,21 +481,21 @@ struct pv_mmu_ops pv_mmu_ops = { .pmd_clear = native_pmd_clear, #endif .set_pud = native_set_pud, - .pmd_val = native_pmd_val, - .make_pmd = native_make_pmd, + .pmd_val = paravirt_native_pmd_val, + .make_pmd = paravirt_native_make_pmd, #if PAGETABLE_LEVELS == 4 - .pud_val = native_pud_val, - .make_pud = native_make_pud, + .pud_val = paravirt_native_pud_val, + .make_pud = paravirt_native_make_pud, .set_pgd = native_set_pgd, #endif #endif /* PAGETABLE_LEVELS >= 3 */ - .pte_val = native_pte_val, - .pgd_val = native_pgd_val, + .pte_val = paravirt_native_pte_val, + .pgd_val = paravirt_native_pgd_val, - .make_pte = native_make_pte, - .make_pgd = native_make_pgd, + .make_pte = paravirt_native_make_pte, + .make_pgd = paravirt_native_make_pgd, .dup_mmap = paravirt_nop, .exit_mmap = paravirt_nop, diff --git a/arch/x86/kernel/paravirt_patch_32.c b/arch/x86/kernel/paravirt_patch_32.c index 9fe644f4861..d9f32e6d6ab 100644 --- a/arch/x86/kernel/paravirt_patch_32.c +++ b/arch/x86/kernel/paravirt_patch_32.c @@ -12,6 +12,18 @@ DEF_NATIVE(pv_mmu_ops, read_cr3, "mov %cr3, %eax"); DEF_NATIVE(pv_cpu_ops, clts, "clts"); DEF_NATIVE(pv_cpu_ops, read_tsc, "rdtsc"); +unsigned paravirt_patch_ident_32(void *insnbuf, unsigned len) +{ + /* arg in %eax, return in %eax */ + return 0; +} + +unsigned paravirt_patch_ident_64(void *insnbuf, unsigned len) +{ + /* arg in %edx:%eax, return in %edx:%eax */ + return 0; +} + unsigned native_patch(u8 type, u16 clobbers, void *ibuf, unsigned long addr, unsigned len) { diff --git a/arch/x86/kernel/paravirt_patch_64.c b/arch/x86/kernel/paravirt_patch_64.c index 061d01df9ae..3f08f34f93e 100644 --- a/arch/x86/kernel/paravirt_patch_64.c +++ b/arch/x86/kernel/paravirt_patch_64.c @@ -19,6 +19,21 @@ DEF_NATIVE(pv_cpu_ops, usergs_sysret64, "swapgs; sysretq"); DEF_NATIVE(pv_cpu_ops, usergs_sysret32, "swapgs; sysretl"); DEF_NATIVE(pv_cpu_ops, swapgs, "swapgs"); +DEF_NATIVE(, mov32, "mov %edi, %eax"); +DEF_NATIVE(, mov64, "mov %rdi, %rax"); + +unsigned paravirt_patch_ident_32(void *insnbuf, unsigned len) +{ + return paravirt_patch_insns(insnbuf, len, + start__mov32, end__mov32); +} + +unsigned paravirt_patch_ident_64(void *insnbuf, unsigned len) +{ + return paravirt_patch_insns(insnbuf, len, + start__mov64, end__mov64); +} + unsigned native_patch(u8 type, u16 clobbers, void *ibuf, unsigned long addr, unsigned len) { -- GitLab From b8aa287f77be943e37a84fa4657e27df95269bfb Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 28 Jan 2009 14:35:03 -0800 Subject: [PATCH 1027/4982] x86: fix paravirt clobber in entry_64.S Impact: Fix latent bug The clobber is trying to say that anything except RDI is available for clobbering, but actually clobbers everything. This hasn't mattered because the clobbers were basically ignored, but subsequent patches will rely on them. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: H. Peter Anvin --- arch/x86/kernel/entry_64.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index a52703864a1..e4c9710cae5 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -1140,7 +1140,7 @@ ENTRY(native_load_gs_index) CFI_STARTPROC pushf CFI_ADJUST_CFA_OFFSET 8 - DISABLE_INTERRUPTS(CLBR_ANY | ~(CLBR_RDI)) + DISABLE_INTERRUPTS(CLBR_ANY & ~CLBR_RDI) SWAPGS gs_change: movl %edi,%gs -- GitLab From 9104a18dcdd8dfefdddca8ce44988563f13ed3c4 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 28 Jan 2009 14:35:04 -0800 Subject: [PATCH 1028/4982] x86/paravirt: selectively save/restore regs around pvops calls Impact: Optimization Each asm paravirt-ops call says what registers are available for clobbering. This patch makes use of this to selectively save/restore registers around each pvops call. In many cases this significantly shrinks code size. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/paravirt.h | 100 +++++++++++++++++++++----------- 1 file changed, 65 insertions(+), 35 deletions(-) diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 961d10c12f1..dcce961262b 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -12,19 +12,29 @@ #define CLBR_EAX (1 << 0) #define CLBR_ECX (1 << 1) #define CLBR_EDX (1 << 2) +#define CLBR_EDI (1 << 3) -#ifdef CONFIG_X86_64 -#define CLBR_RSI (1 << 3) -#define CLBR_RDI (1 << 4) +#ifdef CONFIG_X86_32 +/* CLBR_ANY should match all regs platform has. For i386, that's just it */ +#define CLBR_ANY ((1 << 4) - 1) +#else +#define CLBR_RAX CLBR_EAX +#define CLBR_RCX CLBR_ECX +#define CLBR_RDX CLBR_EDX +#define CLBR_RDI CLBR_EDI +#define CLBR_RSI (1 << 4) #define CLBR_R8 (1 << 5) #define CLBR_R9 (1 << 6) #define CLBR_R10 (1 << 7) #define CLBR_R11 (1 << 8) #define CLBR_ANY ((1 << 9) - 1) + +#define CLBR_ARG_REGS (CLBR_RDI | CLBR_RSI | CLBR_RDX | \ + CLBR_RCX | CLBR_R8 | CLBR_R9) +#define CLBR_RET_REG (CLBR_RAX | CLBR_RDX) +#define CLBR_SCRATCH (CLBR_R10 | CLBR_R11) + #include -#else -/* CLBR_ANY should match all regs platform has. For i386, that's just it */ -#define CLBR_ANY ((1 << 3) - 1) #endif /* X86_64 */ #ifndef __ASSEMBLY__ @@ -1530,33 +1540,49 @@ static inline unsigned long __raw_local_irq_save(void) .popsection +#define COND_PUSH(set, mask, reg) \ + .if ((~set) & mask); push %reg; .endif +#define COND_POP(set, mask, reg) \ + .if ((~set) & mask); pop %reg; .endif + #ifdef CONFIG_X86_64 -#define PV_SAVE_REGS \ - push %rax; \ - push %rcx; \ - push %rdx; \ - push %rsi; \ - push %rdi; \ - push %r8; \ - push %r9; \ - push %r10; \ - push %r11 -#define PV_RESTORE_REGS \ - pop %r11; \ - pop %r10; \ - pop %r9; \ - pop %r8; \ - pop %rdi; \ - pop %rsi; \ - pop %rdx; \ - pop %rcx; \ - pop %rax + +#define PV_SAVE_REGS(set) \ + COND_PUSH(set, CLBR_RAX, rax); \ + COND_PUSH(set, CLBR_RCX, rcx); \ + COND_PUSH(set, CLBR_RDX, rdx); \ + COND_PUSH(set, CLBR_RSI, rsi); \ + COND_PUSH(set, CLBR_RDI, rdi); \ + COND_PUSH(set, CLBR_R8, r8); \ + COND_PUSH(set, CLBR_R9, r9); \ + COND_PUSH(set, CLBR_R10, r10); \ + COND_PUSH(set, CLBR_R11, r11) +#define PV_RESTORE_REGS(set) \ + COND_POP(set, CLBR_R11, r11); \ + COND_POP(set, CLBR_R10, r10); \ + COND_POP(set, CLBR_R9, r9); \ + COND_POP(set, CLBR_R8, r8); \ + COND_POP(set, CLBR_RDI, rdi); \ + COND_POP(set, CLBR_RSI, rsi); \ + COND_POP(set, CLBR_RDX, rdx); \ + COND_POP(set, CLBR_RCX, rcx); \ + COND_POP(set, CLBR_RAX, rax) + #define PARA_PATCH(struct, off) ((PARAVIRT_PATCH_##struct + (off)) / 8) #define PARA_SITE(ptype, clobbers, ops) _PVSITE(ptype, clobbers, ops, .quad, 8) #define PARA_INDIRECT(addr) *addr(%rip) #else -#define PV_SAVE_REGS pushl %eax; pushl %edi; pushl %ecx; pushl %edx -#define PV_RESTORE_REGS popl %edx; popl %ecx; popl %edi; popl %eax +#define PV_SAVE_REGS(set) \ + COND_PUSH(set, CLBR_EAX, eax); \ + COND_PUSH(set, CLBR_EDI, edi); \ + COND_PUSH(set, CLBR_ECX, ecx); \ + COND_PUSH(set, CLBR_EDX, edx) +#define PV_RESTORE_REGS(set) \ + COND_POP(set, CLBR_EDX, edx); \ + COND_POP(set, CLBR_ECX, ecx); \ + COND_POP(set, CLBR_EDI, edi); \ + COND_POP(set, CLBR_EAX, eax) + #define PARA_PATCH(struct, off) ((PARAVIRT_PATCH_##struct + (off)) / 4) #define PARA_SITE(ptype, clobbers, ops) _PVSITE(ptype, clobbers, ops, .long, 4) #define PARA_INDIRECT(addr) *%cs:addr @@ -1568,15 +1594,15 @@ static inline unsigned long __raw_local_irq_save(void) #define DISABLE_INTERRUPTS(clobbers) \ PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_disable), clobbers, \ - PV_SAVE_REGS; \ + PV_SAVE_REGS(clobbers); \ call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_disable); \ - PV_RESTORE_REGS;) \ + PV_RESTORE_REGS(clobbers);) #define ENABLE_INTERRUPTS(clobbers) \ PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_enable), clobbers, \ - PV_SAVE_REGS; \ + PV_SAVE_REGS(clobbers); \ call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_enable); \ - PV_RESTORE_REGS;) + PV_RESTORE_REGS(clobbers);) #define USERGS_SYSRET32 \ PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret32), \ @@ -1606,11 +1632,15 @@ static inline unsigned long __raw_local_irq_save(void) PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_swapgs), CLBR_NONE, \ swapgs) +/* + * Note: swapgs is very special, and in practise is either going to be + * implemented with a single "swapgs" instruction or something very + * special. Either way, we don't need to save any registers for + * it. + */ #define SWAPGS \ PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_swapgs), CLBR_NONE, \ - PV_SAVE_REGS; \ - call PARA_INDIRECT(pv_cpu_ops+PV_CPU_swapgs); \ - PV_RESTORE_REGS \ + call PARA_INDIRECT(pv_cpu_ops+PV_CPU_swapgs) \ ) #define GET_CR2_INTO_RCX \ -- GitLab From ecb93d1ccd0aac63f03be2db3cac3fa974716f4c Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 28 Jan 2009 14:35:05 -0800 Subject: [PATCH 1029/4982] x86/paravirt: add register-saving thunks to reduce caller register pressure Impact: Optimization One of the problems with inserting a pile of C calls where previously there were none is that the register pressure is greatly increased. The C calling convention says that the caller must expect a certain set of registers may be trashed by the callee, and that the callee can use those registers without restriction. This includes the function argument registers, and several others. This patch seeks to alleviate this pressure by introducing wrapper thunks that will do the register saving/restoring, so that the callsite doesn't need to worry about it, but the callee function can be conventional compiler-generated code. In many cases (particularly performance-sensitive cases) the callee will be in assembler anyway, and need not use the compiler's calling convention. Standard calling convention is: arguments return scratch x86-32 eax edx ecx eax ? x86-64 rdi rsi rdx rcx rax r8 r9 r10 r11 The thunk preserves all argument and scratch registers. The return register is not preserved, and is available as a scratch register for unwrapped callee code (and of course the return value). Wrapped function pointers are themselves wrapped in a struct paravirt_callee_save structure, in order to get some warning from the compiler when functions with mismatched calling conventions are used. The most common paravirt ops, both statically and dynamically, are interrupt enable/disable/save/restore, so handle them first. This is particularly easy since their calls are handled specially anyway. XXX Deal with VMI. What's their calling convention? Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/paravirt.h | 126 ++++++++++++++++++++++++-------- arch/x86/kernel/paravirt.c | 8 +- arch/x86/kernel/vsmp_64.c | 12 ++- arch/x86/lguest/boot.c | 13 +++- arch/x86/xen/enlighten.c | 8 +- arch/x86/xen/irq.c | 14 +++- 6 files changed, 132 insertions(+), 49 deletions(-) diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index dcce961262b..f9107b88631 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -17,6 +17,10 @@ #ifdef CONFIG_X86_32 /* CLBR_ANY should match all regs platform has. For i386, that's just it */ #define CLBR_ANY ((1 << 4) - 1) + +#define CLBR_ARG_REGS (CLBR_EAX | CLBR_EDX | CLBR_ECX) +#define CLBR_RET_REG (CLBR_EAX) +#define CLBR_SCRATCH (0) #else #define CLBR_RAX CLBR_EAX #define CLBR_RCX CLBR_ECX @@ -27,16 +31,19 @@ #define CLBR_R9 (1 << 6) #define CLBR_R10 (1 << 7) #define CLBR_R11 (1 << 8) + #define CLBR_ANY ((1 << 9) - 1) #define CLBR_ARG_REGS (CLBR_RDI | CLBR_RSI | CLBR_RDX | \ CLBR_RCX | CLBR_R8 | CLBR_R9) -#define CLBR_RET_REG (CLBR_RAX | CLBR_RDX) +#define CLBR_RET_REG (CLBR_RAX) #define CLBR_SCRATCH (CLBR_R10 | CLBR_R11) #include #endif /* X86_64 */ +#define CLBR_CALLEE_SAVE ((CLBR_ARG_REGS | CLBR_SCRATCH) & ~CLBR_RET_REG) + #ifndef __ASSEMBLY__ #include #include @@ -50,6 +57,14 @@ struct tss_struct; struct mm_struct; struct desc_struct; +/* + * Wrapper type for pointers to code which uses the non-standard + * calling convention. See PV_CALL_SAVE_REGS_THUNK below. + */ +struct paravirt_callee_save { + void *func; +}; + /* general info */ struct pv_info { unsigned int kernel_rpl; @@ -199,11 +214,15 @@ struct pv_irq_ops { * expected to use X86_EFLAGS_IF; all other bits * returned from save_fl are undefined, and may be ignored by * restore_fl. + * + * NOTE: These functions callers expect the callee to preserve + * more registers than the standard C calling convention. */ - unsigned long (*save_fl)(void); - void (*restore_fl)(unsigned long); - void (*irq_disable)(void); - void (*irq_enable)(void); + struct paravirt_callee_save save_fl; + struct paravirt_callee_save restore_fl; + struct paravirt_callee_save irq_disable; + struct paravirt_callee_save irq_enable; + void (*safe_halt)(void); void (*halt)(void); @@ -1437,12 +1456,37 @@ extern struct paravirt_patch_site __parainstructions[], __parainstructions_end[]; #ifdef CONFIG_X86_32 -#define PV_SAVE_REGS "pushl %%ecx; pushl %%edx;" -#define PV_RESTORE_REGS "popl %%edx; popl %%ecx" +#define PV_SAVE_REGS "pushl %ecx; pushl %edx;" +#define PV_RESTORE_REGS "popl %edx; popl %ecx;" + +/* save and restore all caller-save registers, except return value */ +#define PV_SAVE_ALL_CALLER_REGS PV_SAVE_REGS +#define PV_RESTORE_ALL_CALLER_REGS PV_RESTORE_REGS + #define PV_FLAGS_ARG "0" #define PV_EXTRA_CLOBBERS #define PV_VEXTRA_CLOBBERS #else +/* save and restore all caller-save registers, except return value */ +#define PV_SAVE_ALL_CALLER_REGS \ + "push %rcx;" \ + "push %rdx;" \ + "push %rsi;" \ + "push %rdi;" \ + "push %r8;" \ + "push %r9;" \ + "push %r10;" \ + "push %r11;" +#define PV_RESTORE_ALL_CALLER_REGS \ + "pop %r11;" \ + "pop %r10;" \ + "pop %r9;" \ + "pop %r8;" \ + "pop %rdi;" \ + "pop %rsi;" \ + "pop %rdx;" \ + "pop %rcx;" + /* We save some registers, but all of them, that's too much. We clobber all * caller saved registers but the argument parameter */ #define PV_SAVE_REGS "pushq %%rdi;" @@ -1452,52 +1496,76 @@ extern struct paravirt_patch_site __parainstructions[], #define PV_FLAGS_ARG "D" #endif +/* + * Generate a thunk around a function which saves all caller-save + * registers except for the return value. This allows C functions to + * be called from assembler code where fewer than normal registers are + * available. It may also help code generation around calls from C + * code if the common case doesn't use many registers. + * + * When a callee is wrapped in a thunk, the caller can assume that all + * arg regs and all scratch registers are preserved across the + * call. The return value in rax/eax will not be saved, even for void + * functions. + */ +#define PV_CALLEE_SAVE_REGS_THUNK(func) \ + extern typeof(func) __raw_callee_save_##func; \ + static void *__##func##__ __used = func; \ + \ + asm(".pushsection .text;" \ + "__raw_callee_save_" #func ": " \ + PV_SAVE_ALL_CALLER_REGS \ + "call " #func ";" \ + PV_RESTORE_ALL_CALLER_REGS \ + "ret;" \ + ".popsection") + +/* Get a reference to a callee-save function */ +#define PV_CALLEE_SAVE(func) \ + ((struct paravirt_callee_save) { __raw_callee_save_##func }) + +/* Promise that "func" already uses the right calling convention */ +#define __PV_IS_CALLEE_SAVE(func) \ + ((struct paravirt_callee_save) { func }) + static inline unsigned long __raw_local_save_flags(void) { unsigned long f; - asm volatile(paravirt_alt(PV_SAVE_REGS - PARAVIRT_CALL - PV_RESTORE_REGS) + asm volatile(paravirt_alt(PARAVIRT_CALL) : "=a"(f) : paravirt_type(pv_irq_ops.save_fl), paravirt_clobber(CLBR_EAX) - : "memory", "cc" PV_VEXTRA_CLOBBERS); + : "memory", "cc"); return f; } static inline void raw_local_irq_restore(unsigned long f) { - asm volatile(paravirt_alt(PV_SAVE_REGS - PARAVIRT_CALL - PV_RESTORE_REGS) + asm volatile(paravirt_alt(PARAVIRT_CALL) : "=a"(f) : PV_FLAGS_ARG(f), paravirt_type(pv_irq_ops.restore_fl), paravirt_clobber(CLBR_EAX) - : "memory", "cc" PV_EXTRA_CLOBBERS); + : "memory", "cc"); } static inline void raw_local_irq_disable(void) { - asm volatile(paravirt_alt(PV_SAVE_REGS - PARAVIRT_CALL - PV_RESTORE_REGS) + asm volatile(paravirt_alt(PARAVIRT_CALL) : : paravirt_type(pv_irq_ops.irq_disable), paravirt_clobber(CLBR_EAX) - : "memory", "eax", "cc" PV_EXTRA_CLOBBERS); + : "memory", "eax", "cc"); } static inline void raw_local_irq_enable(void) { - asm volatile(paravirt_alt(PV_SAVE_REGS - PARAVIRT_CALL - PV_RESTORE_REGS) + asm volatile(paravirt_alt(PARAVIRT_CALL) : : paravirt_type(pv_irq_ops.irq_enable), paravirt_clobber(CLBR_EAX) - : "memory", "eax", "cc" PV_EXTRA_CLOBBERS); + : "memory", "eax", "cc"); } static inline unsigned long __raw_local_irq_save(void) @@ -1541,9 +1609,9 @@ static inline unsigned long __raw_local_irq_save(void) #define COND_PUSH(set, mask, reg) \ - .if ((~set) & mask); push %reg; .endif + .if ((~(set)) & mask); push %reg; .endif #define COND_POP(set, mask, reg) \ - .if ((~set) & mask); pop %reg; .endif + .if ((~(set)) & mask); pop %reg; .endif #ifdef CONFIG_X86_64 @@ -1594,15 +1662,15 @@ static inline unsigned long __raw_local_irq_save(void) #define DISABLE_INTERRUPTS(clobbers) \ PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_disable), clobbers, \ - PV_SAVE_REGS(clobbers); \ + PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \ call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_disable); \ - PV_RESTORE_REGS(clobbers);) + PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);) #define ENABLE_INTERRUPTS(clobbers) \ PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_enable), clobbers, \ - PV_SAVE_REGS(clobbers); \ + PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \ call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_enable); \ - PV_RESTORE_REGS(clobbers);) + PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);) #define USERGS_SYSRET32 \ PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret32), \ diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index dd25e2b1593..8adb6b5aa42 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -310,10 +310,10 @@ struct pv_time_ops pv_time_ops = { struct pv_irq_ops pv_irq_ops = { .init_IRQ = native_init_IRQ, - .save_fl = native_save_fl, - .restore_fl = native_restore_fl, - .irq_disable = native_irq_disable, - .irq_enable = native_irq_enable, + .save_fl = __PV_IS_CALLEE_SAVE(native_save_fl), + .restore_fl = __PV_IS_CALLEE_SAVE(native_restore_fl), + .irq_disable = __PV_IS_CALLEE_SAVE(native_irq_disable), + .irq_enable = __PV_IS_CALLEE_SAVE(native_irq_enable), .safe_halt = native_safe_halt, .halt = native_halt, #ifdef CONFIG_X86_64 diff --git a/arch/x86/kernel/vsmp_64.c b/arch/x86/kernel/vsmp_64.c index a688f3bfaec..c609205df59 100644 --- a/arch/x86/kernel/vsmp_64.c +++ b/arch/x86/kernel/vsmp_64.c @@ -37,6 +37,7 @@ static unsigned long vsmp_save_fl(void) flags &= ~X86_EFLAGS_IF; return flags; } +PV_CALLEE_SAVE_REGS_THUNK(vsmp_save_fl); static void vsmp_restore_fl(unsigned long flags) { @@ -46,6 +47,7 @@ static void vsmp_restore_fl(unsigned long flags) flags |= X86_EFLAGS_AC; native_restore_fl(flags); } +PV_CALLEE_SAVE_REGS_THUNK(vsmp_restore_fl); static void vsmp_irq_disable(void) { @@ -53,6 +55,7 @@ static void vsmp_irq_disable(void) native_restore_fl((flags & ~X86_EFLAGS_IF) | X86_EFLAGS_AC); } +PV_CALLEE_SAVE_REGS_THUNK(vsmp_irq_disable); static void vsmp_irq_enable(void) { @@ -60,6 +63,7 @@ static void vsmp_irq_enable(void) native_restore_fl((flags | X86_EFLAGS_IF) & (~X86_EFLAGS_AC)); } +PV_CALLEE_SAVE_REGS_THUNK(vsmp_irq_enable); static unsigned __init_or_module vsmp_patch(u8 type, u16 clobbers, void *ibuf, unsigned long addr, unsigned len) @@ -90,10 +94,10 @@ static void __init set_vsmp_pv_ops(void) cap, ctl); if (cap & ctl & (1 << 4)) { /* Setup irq ops and turn on vSMP IRQ fastpath handling */ - pv_irq_ops.irq_disable = vsmp_irq_disable; - pv_irq_ops.irq_enable = vsmp_irq_enable; - pv_irq_ops.save_fl = vsmp_save_fl; - pv_irq_ops.restore_fl = vsmp_restore_fl; + pv_irq_ops.irq_disable = PV_CALLEE_SAVE(vsmp_irq_disable); + pv_irq_ops.irq_enable = PV_CALLEE_SAVE(vsmp_irq_enable); + pv_irq_ops.save_fl = PV_CALLEE_SAVE(vsmp_save_fl); + pv_irq_ops.restore_fl = PV_CALLEE_SAVE(vsmp_restore_fl); pv_init_ops.patch = vsmp_patch; ctl &= ~(1 << 4); diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 92f1c6f3e19..19e33b6cd59 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -173,24 +173,29 @@ static unsigned long save_fl(void) { return lguest_data.irq_enabled; } +PV_CALLEE_SAVE_REGS_THUNK(save_fl); /* restore_flags() just sets the flags back to the value given. */ static void restore_fl(unsigned long flags) { lguest_data.irq_enabled = flags; } +PV_CALLEE_SAVE_REGS_THUNK(restore_fl); /* Interrupts go off... */ static void irq_disable(void) { lguest_data.irq_enabled = 0; } +PV_CALLEE_SAVE_REGS_THUNK(irq_disable); /* Interrupts go on... */ static void irq_enable(void) { lguest_data.irq_enabled = X86_EFLAGS_IF; } +PV_CALLEE_SAVE_REGS_THUNK(irq_enable); + /*:*/ /*M:003 Note that we don't check for outstanding interrupts when we re-enable * them (or when we unmask an interrupt). This seems to work for the moment, @@ -984,10 +989,10 @@ __init void lguest_init(void) /* interrupt-related operations */ pv_irq_ops.init_IRQ = lguest_init_IRQ; - pv_irq_ops.save_fl = save_fl; - pv_irq_ops.restore_fl = restore_fl; - pv_irq_ops.irq_disable = irq_disable; - pv_irq_ops.irq_enable = irq_enable; + pv_irq_ops.save_fl = PV_CALLEE_SAVE(save_fl); + pv_irq_ops.restore_fl = PV_CALLEE_SAVE(restore_fl); + pv_irq_ops.irq_disable = PV_CALLEE_SAVE(irq_disable); + pv_irq_ops.irq_enable = PV_CALLEE_SAVE(irq_enable); pv_irq_ops.safe_halt = lguest_safe_halt; /* init-time operations */ diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 0cd2a165f17..ff6d530ccc7 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -676,10 +676,10 @@ void xen_setup_vcpu_info_placement(void) if (have_vcpu_info_placement) { printk(KERN_INFO "Xen: using vcpu_info placement\n"); - pv_irq_ops.save_fl = xen_save_fl_direct; - pv_irq_ops.restore_fl = xen_restore_fl_direct; - pv_irq_ops.irq_disable = xen_irq_disable_direct; - pv_irq_ops.irq_enable = xen_irq_enable_direct; + pv_irq_ops.save_fl = __PV_IS_CALLEE_SAVE(xen_save_fl_direct); + pv_irq_ops.restore_fl = __PV_IS_CALLEE_SAVE(xen_restore_fl_direct); + pv_irq_ops.irq_disable = __PV_IS_CALLEE_SAVE(xen_irq_disable_direct); + pv_irq_ops.irq_enable = __PV_IS_CALLEE_SAVE(xen_irq_enable_direct); pv_mmu_ops.read_cr2 = xen_read_cr2_direct; } } diff --git a/arch/x86/xen/irq.c b/arch/x86/xen/irq.c index 2e8271431e1..5a070900ad3 100644 --- a/arch/x86/xen/irq.c +++ b/arch/x86/xen/irq.c @@ -50,6 +50,7 @@ static unsigned long xen_save_fl(void) */ return (-flags) & X86_EFLAGS_IF; } +PV_CALLEE_SAVE_REGS_THUNK(xen_save_fl); static void xen_restore_fl(unsigned long flags) { @@ -76,6 +77,7 @@ static void xen_restore_fl(unsigned long flags) xen_force_evtchn_callback(); } } +PV_CALLEE_SAVE_REGS_THUNK(xen_restore_fl); static void xen_irq_disable(void) { @@ -86,6 +88,7 @@ static void xen_irq_disable(void) percpu_read(xen_vcpu)->evtchn_upcall_mask = 1; preempt_enable_no_resched(); } +PV_CALLEE_SAVE_REGS_THUNK(xen_irq_disable); static void xen_irq_enable(void) { @@ -106,6 +109,7 @@ static void xen_irq_enable(void) if (unlikely(vcpu->evtchn_upcall_pending)) xen_force_evtchn_callback(); } +PV_CALLEE_SAVE_REGS_THUNK(xen_irq_enable); static void xen_safe_halt(void) { @@ -124,10 +128,12 @@ static void xen_halt(void) static const struct pv_irq_ops xen_irq_ops __initdata = { .init_IRQ = __xen_init_IRQ, - .save_fl = xen_save_fl, - .restore_fl = xen_restore_fl, - .irq_disable = xen_irq_disable, - .irq_enable = xen_irq_enable, + + .save_fl = PV_CALLEE_SAVE(xen_save_fl), + .restore_fl = PV_CALLEE_SAVE(xen_restore_fl), + .irq_disable = PV_CALLEE_SAVE(xen_irq_disable), + .irq_enable = PV_CALLEE_SAVE(xen_irq_enable), + .safe_halt = xen_safe_halt, .halt = xen_halt, #ifdef CONFIG_X86_64 -- GitLab From 791bad9d28d405d9397ea0c370ffb7c7bdd2aa6e Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 28 Jan 2009 14:35:06 -0800 Subject: [PATCH 1030/4982] x86/paravirt: implement PVOP_CALL macros for callee-save functions Impact: Optimization Functions with the callee save calling convention clobber many fewer registers than the normal C calling convention. Implement variants of PVOP_V?CALL* accordingly. This only bothers with functions up to 3 args, since functions with more args may as well use the normal calling convention. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/paravirt.h | 134 +++++++++++++++++++++++--------- 1 file changed, 99 insertions(+), 35 deletions(-) diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index f9107b88631..beb10ecdbe6 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -510,25 +510,45 @@ int paravirt_disable_iospace(void); * makes sure the incoming and outgoing types are always correct. */ #ifdef CONFIG_X86_32 -#define PVOP_VCALL_ARGS unsigned long __eax, __edx, __ecx +#define PVOP_VCALL_ARGS \ + unsigned long __eax = __eax, __edx = __edx, __ecx = __ecx #define PVOP_CALL_ARGS PVOP_VCALL_ARGS + +#define PVOP_CALL_ARG1(x) "a" ((unsigned long)(x)) +#define PVOP_CALL_ARG2(x) "d" ((unsigned long)(x)) +#define PVOP_CALL_ARG3(x) "c" ((unsigned long)(x)) + #define PVOP_VCALL_CLOBBERS "=a" (__eax), "=d" (__edx), \ "=c" (__ecx) #define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS + +#define PVOP_VCALLEE_CLOBBERS "=a" (__eax) +#define PVOP_CALLEE_CLOBBERS PVOP_VCALLEE_CLOBBERS + #define EXTRA_CLOBBERS #define VEXTRA_CLOBBERS -#else -#define PVOP_VCALL_ARGS unsigned long __edi, __esi, __edx, __ecx +#else /* CONFIG_X86_64 */ +#define PVOP_VCALL_ARGS \ + unsigned long __edi = __edi, __esi = __esi, \ + __edx = __edx, __ecx = __ecx #define PVOP_CALL_ARGS PVOP_VCALL_ARGS, __eax + +#define PVOP_CALL_ARG1(x) "D" ((unsigned long)(x)) +#define PVOP_CALL_ARG2(x) "S" ((unsigned long)(x)) +#define PVOP_CALL_ARG3(x) "d" ((unsigned long)(x)) +#define PVOP_CALL_ARG4(x) "c" ((unsigned long)(x)) + #define PVOP_VCALL_CLOBBERS "=D" (__edi), \ "=S" (__esi), "=d" (__edx), \ "=c" (__ecx) - #define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS, "=a" (__eax) +#define PVOP_VCALLEE_CLOBBERS "=a" (__eax) +#define PVOP_CALLEE_CLOBBERS PVOP_VCALLEE_CLOBBERS + #define EXTRA_CLOBBERS , "r8", "r9", "r10", "r11" #define VEXTRA_CLOBBERS , "rax", "r8", "r9", "r10", "r11" -#endif +#endif /* CONFIG_X86_32 */ #ifdef CONFIG_PARAVIRT_DEBUG #define PVOP_TEST_NULL(op) BUG_ON(op == NULL) @@ -536,10 +556,11 @@ int paravirt_disable_iospace(void); #define PVOP_TEST_NULL(op) ((void)op) #endif -#define __PVOP_CALL(rettype, op, pre, post, ...) \ +#define ____PVOP_CALL(rettype, op, clbr, call_clbr, extra_clbr, \ + pre, post, ...) \ ({ \ rettype __ret; \ - PVOP_CALL_ARGS; \ + PVOP_CALL_ARGS; \ PVOP_TEST_NULL(op); \ /* This is 32-bit specific, but is okay in 64-bit */ \ /* since this condition will never hold */ \ @@ -547,70 +568,113 @@ int paravirt_disable_iospace(void); asm volatile(pre \ paravirt_alt(PARAVIRT_CALL) \ post \ - : PVOP_CALL_CLOBBERS \ + : call_clbr \ : paravirt_type(op), \ - paravirt_clobber(CLBR_ANY), \ + paravirt_clobber(clbr), \ ##__VA_ARGS__ \ - : "memory", "cc" EXTRA_CLOBBERS); \ + : "memory", "cc" extra_clbr); \ __ret = (rettype)((((u64)__edx) << 32) | __eax); \ } else { \ asm volatile(pre \ paravirt_alt(PARAVIRT_CALL) \ post \ - : PVOP_CALL_CLOBBERS \ + : call_clbr \ : paravirt_type(op), \ - paravirt_clobber(CLBR_ANY), \ + paravirt_clobber(clbr), \ ##__VA_ARGS__ \ - : "memory", "cc" EXTRA_CLOBBERS); \ + : "memory", "cc" extra_clbr); \ __ret = (rettype)__eax; \ } \ __ret; \ }) -#define __PVOP_VCALL(op, pre, post, ...) \ + +#define __PVOP_CALL(rettype, op, pre, post, ...) \ + ____PVOP_CALL(rettype, op, CLBR_ANY, PVOP_CALL_CLOBBERS, \ + EXTRA_CLOBBERS, pre, post, ##__VA_ARGS__) + +#define __PVOP_CALLEESAVE(rettype, op, pre, post, ...) \ + ____PVOP_CALL(rettype, op.func, CLBR_RET_REG, \ + PVOP_CALLEE_CLOBBERS, , \ + pre, post, ##__VA_ARGS__) + + +#define ____PVOP_VCALL(op, clbr, call_clbr, extra_clbr, pre, post, ...) \ ({ \ PVOP_VCALL_ARGS; \ PVOP_TEST_NULL(op); \ asm volatile(pre \ paravirt_alt(PARAVIRT_CALL) \ post \ - : PVOP_VCALL_CLOBBERS \ + : call_clbr \ : paravirt_type(op), \ - paravirt_clobber(CLBR_ANY), \ + paravirt_clobber(clbr), \ ##__VA_ARGS__ \ - : "memory", "cc" VEXTRA_CLOBBERS); \ + : "memory", "cc" extra_clbr); \ }) +#define __PVOP_VCALL(op, pre, post, ...) \ + ____PVOP_VCALL(op, CLBR_ANY, PVOP_VCALL_CLOBBERS, \ + VEXTRA_CLOBBERS, \ + pre, post, ##__VA_ARGS__) + +#define __PVOP_VCALLEESAVE(rettype, op, pre, post, ...) \ + ____PVOP_CALL(rettype, op.func, CLBR_RET_REG, \ + PVOP_VCALLEE_CLOBBERS, , \ + pre, post, ##__VA_ARGS__) + + + #define PVOP_CALL0(rettype, op) \ __PVOP_CALL(rettype, op, "", "") #define PVOP_VCALL0(op) \ __PVOP_VCALL(op, "", "") +#define PVOP_CALLEE0(rettype, op) \ + __PVOP_CALLEESAVE(rettype, op, "", "") +#define PVOP_VCALLEE0(op) \ + __PVOP_VCALLEESAVE(op, "", "") + + #define PVOP_CALL1(rettype, op, arg1) \ - __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1))) + __PVOP_CALL(rettype, op, "", "", PVOP_CALL_ARG1(arg1)) #define PVOP_VCALL1(op, arg1) \ - __PVOP_VCALL(op, "", "", "0" ((unsigned long)(arg1))) + __PVOP_VCALL(op, "", "", PVOP_CALL_ARG1(arg1)) + +#define PVOP_CALLEE1(rettype, op, arg1) \ + __PVOP_CALLEESAVE(rettype, op, "", "", PVOP_CALL_ARG1(arg1)) +#define PVOP_VCALLEE1(op, arg1) \ + __PVOP_VCALLEESAVE(op, "", "", PVOP_CALL_ARG1(arg1)) + #define PVOP_CALL2(rettype, op, arg1, arg2) \ - __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1)), \ - "1" ((unsigned long)(arg2))) + __PVOP_CALL(rettype, op, "", "", PVOP_CALL_ARG1(arg1), \ + PVOP_CALL_ARG2(arg2)) #define PVOP_VCALL2(op, arg1, arg2) \ - __PVOP_VCALL(op, "", "", "0" ((unsigned long)(arg1)), \ - "1" ((unsigned long)(arg2))) + __PVOP_VCALL(op, "", "", PVOP_CALL_ARG1(arg1), \ + PVOP_CALL_ARG2(arg2)) + +#define PVOP_CALLEE2(rettype, op, arg1, arg2) \ + __PVOP_CALLEESAVE(rettype, op, "", "", PVOP_CALL_ARG1(arg1), \ + PVOP_CALL_ARG2(arg2)) +#define PVOP_VCALLEE2(op, arg1, arg2) \ + __PVOP_VCALLEESAVE(op, "", "", PVOP_CALL_ARG1(arg1), \ + PVOP_CALL_ARG2(arg2)) + #define PVOP_CALL3(rettype, op, arg1, arg2, arg3) \ - __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1)), \ - "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3))) + __PVOP_CALL(rettype, op, "", "", PVOP_CALL_ARG1(arg1), \ + PVOP_CALL_ARG2(arg2), PVOP_CALL_ARG3(arg3)) #define PVOP_VCALL3(op, arg1, arg2, arg3) \ - __PVOP_VCALL(op, "", "", "0" ((unsigned long)(arg1)), \ - "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3))) + __PVOP_VCALL(op, "", "", PVOP_CALL_ARG1(arg1), \ + PVOP_CALL_ARG2(arg2), PVOP_CALL_ARG3(arg3)) /* This is the only difference in x86_64. We can make it much simpler */ #ifdef CONFIG_X86_32 #define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \ __PVOP_CALL(rettype, op, \ "push %[_arg4];", "lea 4(%%esp),%%esp;", \ - "0" ((u32)(arg1)), "1" ((u32)(arg2)), \ - "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4))) + PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2), \ + PVOP_CALL_ARG3(arg3), [_arg4] "mr" ((u32)(arg4))) #define PVOP_VCALL4(op, arg1, arg2, arg3, arg4) \ __PVOP_VCALL(op, \ "push %[_arg4];", "lea 4(%%esp),%%esp;", \ @@ -618,13 +682,13 @@ int paravirt_disable_iospace(void); "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4))) #else #define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \ - __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1)), \ - "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3)), \ - "3"((unsigned long)(arg4))) + __PVOP_CALL(rettype, op, "", "", \ + PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2), \ + PVOP_CALL_ARG3(arg3), PVOP_CALL_ARG4(arg4)) #define PVOP_VCALL4(op, arg1, arg2, arg3, arg4) \ - __PVOP_VCALL(op, "", "", "0" ((unsigned long)(arg1)), \ - "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3)), \ - "3"((unsigned long)(arg4))) + __PVOP_VCALL(op, "", "", \ + PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2), \ + PVOP_CALL_ARG3(arg3), PVOP_CALL_ARG4(arg4)) #endif static inline int paravirt_enabled(void) -- GitLab From da5de7c22eb705be709a57e486e7475a6969b994 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 28 Jan 2009 14:35:07 -0800 Subject: [PATCH 1031/4982] x86/paravirt: use callee-saved convention for pte_val/make_pte/etc Impact: Optimization In the native case, pte_val, make_pte, etc are all just identity functions, so there's no need to clobber a lot of registers over them. (This changes the 32-bit callee-save calling convention to return both EAX and EDX so functions can return 64-bit values.) Signed-off-by: Jeremy Fitzhardinge Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/paravirt.h | 78 ++++++++++++++++----------------- arch/x86/kernel/paravirt.c | 53 +++++----------------- arch/x86/xen/mmu.c | 24 ++++++---- 3 files changed, 67 insertions(+), 88 deletions(-) diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index beb10ecdbe6..2d098b78bc1 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -19,7 +19,7 @@ #define CLBR_ANY ((1 << 4) - 1) #define CLBR_ARG_REGS (CLBR_EAX | CLBR_EDX | CLBR_ECX) -#define CLBR_RET_REG (CLBR_EAX) +#define CLBR_RET_REG (CLBR_EAX | CLBR_EDX) #define CLBR_SCRATCH (0) #else #define CLBR_RAX CLBR_EAX @@ -308,11 +308,11 @@ struct pv_mmu_ops { void (*ptep_modify_prot_commit)(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte); - pteval_t (*pte_val)(pte_t); - pte_t (*make_pte)(pteval_t pte); + struct paravirt_callee_save pte_val; + struct paravirt_callee_save make_pte; - pgdval_t (*pgd_val)(pgd_t); - pgd_t (*make_pgd)(pgdval_t pgd); + struct paravirt_callee_save pgd_val; + struct paravirt_callee_save make_pgd; #if PAGETABLE_LEVELS >= 3 #ifdef CONFIG_X86_PAE @@ -327,12 +327,12 @@ struct pv_mmu_ops { void (*set_pud)(pud_t *pudp, pud_t pudval); - pmdval_t (*pmd_val)(pmd_t); - pmd_t (*make_pmd)(pmdval_t pmd); + struct paravirt_callee_save pmd_val; + struct paravirt_callee_save make_pmd; #if PAGETABLE_LEVELS == 4 - pudval_t (*pud_val)(pud_t); - pud_t (*make_pud)(pudval_t pud); + struct paravirt_callee_save pud_val; + struct paravirt_callee_save make_pud; void (*set_pgd)(pgd_t *pudp, pgd_t pgdval); #endif /* PAGETABLE_LEVELS == 4 */ @@ -1155,13 +1155,13 @@ static inline pte_t __pte(pteval_t val) pteval_t ret; if (sizeof(pteval_t) > sizeof(long)) - ret = PVOP_CALL2(pteval_t, - pv_mmu_ops.make_pte, - val, (u64)val >> 32); + ret = PVOP_CALLEE2(pteval_t, + pv_mmu_ops.make_pte, + val, (u64)val >> 32); else - ret = PVOP_CALL1(pteval_t, - pv_mmu_ops.make_pte, - val); + ret = PVOP_CALLEE1(pteval_t, + pv_mmu_ops.make_pte, + val); return (pte_t) { .pte = ret }; } @@ -1171,11 +1171,11 @@ static inline pteval_t pte_val(pte_t pte) pteval_t ret; if (sizeof(pteval_t) > sizeof(long)) - ret = PVOP_CALL2(pteval_t, pv_mmu_ops.pte_val, - pte.pte, (u64)pte.pte >> 32); + ret = PVOP_CALLEE2(pteval_t, pv_mmu_ops.pte_val, + pte.pte, (u64)pte.pte >> 32); else - ret = PVOP_CALL1(pteval_t, pv_mmu_ops.pte_val, - pte.pte); + ret = PVOP_CALLEE1(pteval_t, pv_mmu_ops.pte_val, + pte.pte); return ret; } @@ -1185,11 +1185,11 @@ static inline pgd_t __pgd(pgdval_t val) pgdval_t ret; if (sizeof(pgdval_t) > sizeof(long)) - ret = PVOP_CALL2(pgdval_t, pv_mmu_ops.make_pgd, - val, (u64)val >> 32); + ret = PVOP_CALLEE2(pgdval_t, pv_mmu_ops.make_pgd, + val, (u64)val >> 32); else - ret = PVOP_CALL1(pgdval_t, pv_mmu_ops.make_pgd, - val); + ret = PVOP_CALLEE1(pgdval_t, pv_mmu_ops.make_pgd, + val); return (pgd_t) { ret }; } @@ -1199,11 +1199,11 @@ static inline pgdval_t pgd_val(pgd_t pgd) pgdval_t ret; if (sizeof(pgdval_t) > sizeof(long)) - ret = PVOP_CALL2(pgdval_t, pv_mmu_ops.pgd_val, - pgd.pgd, (u64)pgd.pgd >> 32); + ret = PVOP_CALLEE2(pgdval_t, pv_mmu_ops.pgd_val, + pgd.pgd, (u64)pgd.pgd >> 32); else - ret = PVOP_CALL1(pgdval_t, pv_mmu_ops.pgd_val, - pgd.pgd); + ret = PVOP_CALLEE1(pgdval_t, pv_mmu_ops.pgd_val, + pgd.pgd); return ret; } @@ -1267,11 +1267,11 @@ static inline pmd_t __pmd(pmdval_t val) pmdval_t ret; if (sizeof(pmdval_t) > sizeof(long)) - ret = PVOP_CALL2(pmdval_t, pv_mmu_ops.make_pmd, - val, (u64)val >> 32); + ret = PVOP_CALLEE2(pmdval_t, pv_mmu_ops.make_pmd, + val, (u64)val >> 32); else - ret = PVOP_CALL1(pmdval_t, pv_mmu_ops.make_pmd, - val); + ret = PVOP_CALLEE1(pmdval_t, pv_mmu_ops.make_pmd, + val); return (pmd_t) { ret }; } @@ -1281,11 +1281,11 @@ static inline pmdval_t pmd_val(pmd_t pmd) pmdval_t ret; if (sizeof(pmdval_t) > sizeof(long)) - ret = PVOP_CALL2(pmdval_t, pv_mmu_ops.pmd_val, - pmd.pmd, (u64)pmd.pmd >> 32); + ret = PVOP_CALLEE2(pmdval_t, pv_mmu_ops.pmd_val, + pmd.pmd, (u64)pmd.pmd >> 32); else - ret = PVOP_CALL1(pmdval_t, pv_mmu_ops.pmd_val, - pmd.pmd); + ret = PVOP_CALLEE1(pmdval_t, pv_mmu_ops.pmd_val, + pmd.pmd); return ret; } @@ -1307,11 +1307,11 @@ static inline pud_t __pud(pudval_t val) pudval_t ret; if (sizeof(pudval_t) > sizeof(long)) - ret = PVOP_CALL2(pudval_t, pv_mmu_ops.make_pud, - val, (u64)val >> 32); + ret = PVOP_CALLEE2(pudval_t, pv_mmu_ops.make_pud, + val, (u64)val >> 32); else - ret = PVOP_CALL1(pudval_t, pv_mmu_ops.make_pud, - val); + ret = PVOP_CALLEE1(pudval_t, pv_mmu_ops.make_pud, + val); return (pud_t) { ret }; } diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index 8adb6b5aa42..cea11c8e304 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -391,43 +391,12 @@ struct pv_apic_ops pv_apic_ops = { #endif }; -typedef pte_t make_pte_t(pteval_t); -typedef pmd_t make_pmd_t(pmdval_t); -typedef pud_t make_pud_t(pudval_t); -typedef pgd_t make_pgd_t(pgdval_t); - -typedef pteval_t pte_val_t(pte_t); -typedef pmdval_t pmd_val_t(pmd_t); -typedef pudval_t pud_val_t(pud_t); -typedef pgdval_t pgd_val_t(pgd_t); - - #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_PAE) /* 32-bit pagetable entries */ -#define paravirt_native_make_pte (make_pte_t *)_paravirt_ident_32 -#define paravirt_native_pte_val (pte_val_t *)_paravirt_ident_32 - -#define paravirt_native_make_pmd (make_pmd_t *)_paravirt_ident_32 -#define paravirt_native_pmd_val (pmd_val_t *)_paravirt_ident_32 - -#define paravirt_native_make_pud (make_pud_t *)_paravirt_ident_32 -#define paravirt_native_pud_val (pud_val_t *)_paravirt_ident_32 - -#define paravirt_native_make_pgd (make_pgd_t *)_paravirt_ident_32 -#define paravirt_native_pgd_val (pgd_val_t *)_paravirt_ident_32 +#define PTE_IDENT __PV_IS_CALLEE_SAVE(_paravirt_ident_32) #else /* 64-bit pagetable entries */ -#define paravirt_native_make_pte (make_pte_t *)_paravirt_ident_64 -#define paravirt_native_pte_val (pte_val_t *)_paravirt_ident_64 - -#define paravirt_native_make_pmd (make_pmd_t *)_paravirt_ident_64 -#define paravirt_native_pmd_val (pmd_val_t *)_paravirt_ident_64 - -#define paravirt_native_make_pud (make_pud_t *)_paravirt_ident_64 -#define paravirt_native_pud_val (pud_val_t *)_paravirt_ident_64 - -#define paravirt_native_make_pgd (make_pgd_t *)_paravirt_ident_64 -#define paravirt_native_pgd_val (pgd_val_t *)_paravirt_ident_64 +#define PTE_IDENT __PV_IS_CALLEE_SAVE(_paravirt_ident_64) #endif struct pv_mmu_ops pv_mmu_ops = { @@ -481,21 +450,23 @@ struct pv_mmu_ops pv_mmu_ops = { .pmd_clear = native_pmd_clear, #endif .set_pud = native_set_pud, - .pmd_val = paravirt_native_pmd_val, - .make_pmd = paravirt_native_make_pmd, + + .pmd_val = PTE_IDENT, + .make_pmd = PTE_IDENT, #if PAGETABLE_LEVELS == 4 - .pud_val = paravirt_native_pud_val, - .make_pud = paravirt_native_make_pud, + .pud_val = PTE_IDENT, + .make_pud = PTE_IDENT, + .set_pgd = native_set_pgd, #endif #endif /* PAGETABLE_LEVELS >= 3 */ - .pte_val = paravirt_native_pte_val, - .pgd_val = paravirt_native_pgd_val, + .pte_val = PTE_IDENT, + .pgd_val = PTE_IDENT, - .make_pte = paravirt_native_make_pte, - .make_pgd = paravirt_native_make_pgd, + .make_pte = PTE_IDENT, + .make_pgd = PTE_IDENT, .dup_mmap = paravirt_nop, .exit_mmap = paravirt_nop, diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 94e452c0b00..5e41f7fc6cf 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -492,28 +492,33 @@ pteval_t xen_pte_val(pte_t pte) { return pte_mfn_to_pfn(pte.pte); } +PV_CALLEE_SAVE_REGS_THUNK(xen_pte_val); pgdval_t xen_pgd_val(pgd_t pgd) { return pte_mfn_to_pfn(pgd.pgd); } +PV_CALLEE_SAVE_REGS_THUNK(xen_pgd_val); pte_t xen_make_pte(pteval_t pte) { pte = pte_pfn_to_mfn(pte); return native_make_pte(pte); } +PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte); pgd_t xen_make_pgd(pgdval_t pgd) { pgd = pte_pfn_to_mfn(pgd); return native_make_pgd(pgd); } +PV_CALLEE_SAVE_REGS_THUNK(xen_make_pgd); pmdval_t xen_pmd_val(pmd_t pmd) { return pte_mfn_to_pfn(pmd.pmd); } +PV_CALLEE_SAVE_REGS_THUNK(xen_pmd_val); void xen_set_pud_hyper(pud_t *ptr, pud_t val) { @@ -590,12 +595,14 @@ pmd_t xen_make_pmd(pmdval_t pmd) pmd = pte_pfn_to_mfn(pmd); return native_make_pmd(pmd); } +PV_CALLEE_SAVE_REGS_THUNK(xen_make_pmd); #if PAGETABLE_LEVELS == 4 pudval_t xen_pud_val(pud_t pud) { return pte_mfn_to_pfn(pud.pud); } +PV_CALLEE_SAVE_REGS_THUNK(xen_pud_val); pud_t xen_make_pud(pudval_t pud) { @@ -603,6 +610,7 @@ pud_t xen_make_pud(pudval_t pud) return native_make_pud(pud); } +PV_CALLEE_SAVE_REGS_THUNK(xen_make_pud); pgd_t *xen_get_user_pgd(pgd_t *pgd) { @@ -1813,11 +1821,11 @@ const struct pv_mmu_ops xen_mmu_ops __initdata = { .ptep_modify_prot_start = __ptep_modify_prot_start, .ptep_modify_prot_commit = __ptep_modify_prot_commit, - .pte_val = xen_pte_val, - .pgd_val = xen_pgd_val, + .pte_val = PV_CALLEE_SAVE(xen_pte_val), + .pgd_val = PV_CALLEE_SAVE(xen_pgd_val), - .make_pte = xen_make_pte, - .make_pgd = xen_make_pgd, + .make_pte = PV_CALLEE_SAVE(xen_make_pte), + .make_pgd = PV_CALLEE_SAVE(xen_make_pgd), #ifdef CONFIG_X86_PAE .set_pte_atomic = xen_set_pte_atomic, @@ -1827,12 +1835,12 @@ const struct pv_mmu_ops xen_mmu_ops __initdata = { #endif /* CONFIG_X86_PAE */ .set_pud = xen_set_pud_hyper, - .make_pmd = xen_make_pmd, - .pmd_val = xen_pmd_val, + .make_pmd = PV_CALLEE_SAVE(xen_make_pmd), + .pmd_val = PV_CALLEE_SAVE(xen_pmd_val), #if PAGETABLE_LEVELS == 4 - .pud_val = xen_pud_val, - .make_pud = xen_make_pud, + .pud_val = PV_CALLEE_SAVE(xen_pud_val), + .make_pud = PV_CALLEE_SAVE(xen_make_pud), .set_pgd = xen_set_pgd_hyper, .alloc_pud = xen_alloc_pte_init, -- GitLab From 4767afbf1f60f73997a7eb69a86d380f1fb27a92 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 29 Jan 2009 01:51:34 -0800 Subject: [PATCH 1032/4982] x86/paravirt: fix missing callee-save call on pud_val Impact: Fix build when CONFIG_PARAVIRT_DEBUG is enabled Fix missed convertion to using callee-saved calls for pud_val, which causes a compile error when CONFIG_PARAVIRT_DEBUG is enabled. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/paravirt.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 2d098b78bc1..b17365c3974 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -1321,11 +1321,11 @@ static inline pudval_t pud_val(pud_t pud) pudval_t ret; if (sizeof(pudval_t) > sizeof(long)) - ret = PVOP_CALL2(pudval_t, pv_mmu_ops.pud_val, - pud.pud, (u64)pud.pud >> 32); + ret = PVOP_CALLEE2(pudval_t, pv_mmu_ops.pud_val, + pud.pud, (u64)pud.pud >> 32); else - ret = PVOP_CALL1(pudval_t, pv_mmu_ops.pud_val, - pud.pud); + ret = PVOP_CALLEE1(pudval_t, pv_mmu_ops.pud_val, + pud.pud); return ret; } -- GitLab From 7e3fa56141175026136b392fd026d5d07c49720e Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Fri, 30 Jan 2009 23:56:42 +0100 Subject: [PATCH 1033/4982] kbuild: drop check for CONFIG_ in headers_check The check for references to CONFIG_ symbols in exported headers turned out to be too agressive with the current state of affairs. After the work of Jaswinder to clean up all relevant cases we are down to almost pure noise. So lets drop the check for now - we can always add it back later should our headers be ready for that. Signed-off-by: Sam Ravnborg Signed-off-by: Ingo Molnar --- scripts/headers_check.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/headers_check.pl b/scripts/headers_check.pl index db30fac3083..56f90a48089 100644 --- a/scripts/headers_check.pl +++ b/scripts/headers_check.pl @@ -38,7 +38,7 @@ foreach my $file (@files) { &check_asm_types(); &check_sizetypes(); &check_prototypes(); - &check_config(); + # Dropped for now. Too much noise &check_config(); } close FH; } -- GitLab From 193c81b979adbc4a540bf89e75b9039fae75bf82 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 31 Jan 2009 02:23:27 +0100 Subject: [PATCH 1034/4982] x86, irq: add LOCAL_PERF_VECTOR Add a slot for the performance monitoring interrupt. Not yet used by any subsystem - but the hardware has it. (This eases integration with performance monitoring code.) Signed-off-by: Ingo Molnar --- arch/x86/include/asm/irq_vectors.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index 9a83a10a5d5..0e2220bb314 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h @@ -88,6 +88,11 @@ */ #define LOCAL_TIMER_VECTOR 0xef +/* + * Performance monitoring interrupt vector: + */ +#define LOCAL_PERF_VECTOR 0xee + /* * First APIC vector available to drivers: (vectors 0x30-0xee) we * start at 0x31(0x41) to spread out vectors evenly between priority -- GitLab From d1de36f5b5a30b8f9dae7142516fb122ce1e0661 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 31 Jan 2009 01:59:14 +0100 Subject: [PATCH 1035/4982] x86, apic: clean up header section Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic.c | 46 ++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 968c817762a..29e7186b0e8 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -14,43 +14,41 @@ * Mikael Pettersson : PM converted to driver model. */ -#include - -#include -#include -#include -#include -#include #include -#include -#include -#include -#include +#include #include +#include +#include +#include +#include +#include #include -#include +#include +#include +#include #include -#include -#include +#include +#include +#include #include -#include +#include +#include -#include -#include -#include -#include #include -#include #include +#include +#include +#include #include -#include +#include #include #include -#include +#include +#include +#include +#include #include -#include - /* * Sanity check */ -- GitLab From 8f47e16348e8e25eedf639092a8a2f10a66aba34 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 31 Jan 2009 02:03:42 +0100 Subject: [PATCH 1036/4982] x86: update copyrights Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic.c | 2 +- arch/x86/kernel/io_apic.c | 2 +- arch/x86/kernel/mpparse.c | 2 +- arch/x86/kernel/smp.c | 2 +- arch/x86/kernel/smpboot.c | 2 +- arch/x86/kernel/stacktrace.c | 2 +- arch/x86/mm/mmap.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 29e7186b0e8..d6da6dd2f60 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -1,7 +1,7 @@ /* * Local APIC handling, local APIC timers * - * (c) 1999, 2000 Ingo Molnar + * (c) 1999, 2000, 2009 Ingo Molnar * * Fixes * Maciej W. Rozycki : Bits for genuine 82489DX APICs; diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 3378ffb2140..57d60c741e3 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -1,7 +1,7 @@ /* * Intel IO-APIC support for multi-Pentium hosts. * - * Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar, Hajnalka Szabo + * Copyright (C) 1997, 1998, 1999, 2000, 2009 Ingo Molnar, Hajnalka Szabo * * Many thanks to Stig Venaas for trying out countless experimental * patches and reporting/debugging problems patiently! diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index b46ca7d31fe..66ebb823f39 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -3,7 +3,7 @@ * compliant MP-table parsing routines. * * (c) 1995 Alan Cox, Building #3 - * (c) 1998, 1999, 2000 Ingo Molnar + * (c) 1998, 1999, 2000, 2009 Ingo Molnar * (c) 2008 Alexey Starikovskiy */ diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index 0eb32ae9bf1..eaaffae31cc 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c @@ -2,7 +2,7 @@ * Intel SMP support routines. * * (c) 1995 Alan Cox, Building #3 - * (c) 1998-99, 2000 Ingo Molnar + * (c) 1998-99, 2000, 2009 Ingo Molnar * (c) 2002,2003 Andi Kleen, SuSE Labs. * * i386 and x86_64 integration by Glauber Costa diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 1268a862abb..f40f86fec2f 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -2,7 +2,7 @@ * x86 SMP booting functions * * (c) 1995 Alan Cox, Building #3 - * (c) 1998, 1999, 2000 Ingo Molnar + * (c) 1998, 1999, 2000, 2009 Ingo Molnar * Copyright 2001 Andi Kleen, SuSE Labs. * * Much of the core SMP work is based on previous work by Thomas Radke, to diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c index 10786af9554..f7bddc2e37d 100644 --- a/arch/x86/kernel/stacktrace.c +++ b/arch/x86/kernel/stacktrace.c @@ -1,7 +1,7 @@ /* * Stack trace management functions * - * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar + * Copyright (C) 2006-2009 Red Hat, Inc., Ingo Molnar */ #include #include diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c index 56fe7124fbe..16582960056 100644 --- a/arch/x86/mm/mmap.c +++ b/arch/x86/mm/mmap.c @@ -4,7 +4,7 @@ * Based on code by Ingo Molnar and Andi Kleen, copyrighted * as follows: * - * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. + * Copyright 2003-2009 Red Hat Inc. * All Rights Reserved. * Copyright 2005 Andi Kleen, SUSE Labs. * Copyright 2007 Jiri Kosina, SUSE Labs. -- GitLab From 5da690d29f0de17cc1835dd3eb8f8bd0945521f0 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 31 Jan 2009 02:10:03 +0100 Subject: [PATCH 1037/4982] x86, apic: unify the APIC vector enumeration Most of the vector layout on 32-bit and 64-bit is identical now, so eliminate the duplicated enumeration of the vectors. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/irq_vectors.h | 35 ++++++++++-------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index 0e2220bb314..393f85ecdd8 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h @@ -50,37 +50,26 @@ * into a single vector (CALL_FUNCTION_VECTOR) to save vector space. * TLB, reschedule and local APIC vectors are performance-critical. */ -#ifdef CONFIG_X86_32 - -# define SPURIOUS_APIC_VECTOR 0xff -# define ERROR_APIC_VECTOR 0xfe -# define RESCHEDULE_VECTOR 0xfd -# define CALL_FUNCTION_VECTOR 0xfc -# define CALL_FUNCTION_SINGLE_VECTOR 0xfb -# define THERMAL_APIC_VECTOR 0xfa -/* 0xf8 - 0xf9 : free */ -# define INVALIDATE_TLB_VECTOR_END 0xf7 -# define INVALIDATE_TLB_VECTOR_START 0xf0 /* f0-f7 used for TLB flush */ -# define NUM_INVALIDATE_TLB_VECTORS 8 +#define SPURIOUS_APIC_VECTOR 0xff +#define ERROR_APIC_VECTOR 0xfe +#define RESCHEDULE_VECTOR 0xfd +#define CALL_FUNCTION_VECTOR 0xfc +#define CALL_FUNCTION_SINGLE_VECTOR 0xfb +#define THERMAL_APIC_VECTOR 0xfa +#ifdef CONFIG_X86_32 +/* 0xf8 - 0xf9 : free */ #else - -# define SPURIOUS_APIC_VECTOR 0xff -# define ERROR_APIC_VECTOR 0xfe -# define RESCHEDULE_VECTOR 0xfd -# define CALL_FUNCTION_VECTOR 0xfc -# define CALL_FUNCTION_SINGLE_VECTOR 0xfb -# define THERMAL_APIC_VECTOR 0xfa # define THRESHOLD_APIC_VECTOR 0xf9 # define UV_BAU_MESSAGE 0xf8 -# define INVALIDATE_TLB_VECTOR_END 0xf7 -# define INVALIDATE_TLB_VECTOR_START 0xf0 /* f0-f7 used for TLB flush */ +#endif +/* f0-f7 used for spreading out TLB flushes: */ +#define INVALIDATE_TLB_VECTOR_END 0xf7 +#define INVALIDATE_TLB_VECTOR_START 0xf0 #define NUM_INVALIDATE_TLB_VECTORS 8 -#endif - /* * Local APIC timer IRQ vector is on a different priority level, * to work around the 'lost local interrupt if more than 2 IRQ -- GitLab From 647ad94fc0479e33958cb4d0e20e241c0bcf599c Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 31 Jan 2009 02:06:50 +0100 Subject: [PATCH 1038/4982] x86, apic: clean up spurious vector sanity check Move the spurious vector sanity check to the place where it's defined - out of a .c file. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/irq_vectors.h | 7 +++++++ arch/x86/kernel/apic.c | 7 ------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index 393f85ecdd8..2601fd108c7 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h @@ -52,6 +52,13 @@ */ #define SPURIOUS_APIC_VECTOR 0xff +/* + * Sanity check + */ +#if ((SPURIOUS_APIC_VECTOR & 0x0F) != 0x0F) +# error SPURIOUS_APIC_VECTOR definition error +#endif + #define ERROR_APIC_VECTOR 0xfe #define RESCHEDULE_VECTOR 0xfd #define CALL_FUNCTION_VECTOR 0xfc diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index d6da6dd2f60..85d8b50d1af 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -49,13 +49,6 @@ #include #include -/* - * Sanity check - */ -#if ((SPURIOUS_APIC_VECTOR & 0x0F) != 0x0F) -# error SPURIOUS_APIC_VECTOR definition error -#endif - unsigned int num_processors; unsigned disabled_cpus __cpuinitdata; /* Processor that is doing the boot up */ -- GitLab From ed74ca6d5a3e57eb0969d4e14e46cf9f88d25d3f Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 31 Jan 2009 02:16:04 +0100 Subject: [PATCH 1039/4982] x86, voyager: move Voyager-specific defines to voyager.h They dont belong into the generic headers. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/hw_irq.h | 10 ------- arch/x86/include/asm/irq_vectors.h | 35 ------------------------- arch/x86/include/asm/voyager.h | 42 ++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 45 deletions(-) diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index 41550797396..3ef2bded97a 100644 --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h @@ -84,16 +84,6 @@ extern atomic_t irq_mis_count; /* EISA */ extern void eisa_set_level_irq(unsigned int irq); -/* Voyager functions */ -extern asmlinkage void vic_cpi_interrupt(void); -extern asmlinkage void vic_sys_interrupt(void); -extern asmlinkage void vic_cmn_interrupt(void); -extern asmlinkage void qic_timer_interrupt(void); -extern asmlinkage void qic_invalidate_interrupt(void); -extern asmlinkage void qic_reschedule_interrupt(void); -extern asmlinkage void qic_enable_irq_interrupt(void); -extern asmlinkage void qic_call_function_interrupt(void); - /* SMP */ extern void smp_apic_timer_interrupt(struct pt_regs *); extern void smp_spurious_interrupt(struct pt_regs *); diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index 2601fd108c7..067d22ffb3e 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h @@ -135,39 +135,4 @@ #endif -/* Voyager specific defines */ -/* These define the CPIs we use in linux */ -#define VIC_CPI_LEVEL0 0 -#define VIC_CPI_LEVEL1 1 -/* now the fake CPIs */ -#define VIC_TIMER_CPI 2 -#define VIC_INVALIDATE_CPI 3 -#define VIC_RESCHEDULE_CPI 4 -#define VIC_ENABLE_IRQ_CPI 5 -#define VIC_CALL_FUNCTION_CPI 6 -#define VIC_CALL_FUNCTION_SINGLE_CPI 7 - -/* Now the QIC CPIs: Since we don't need the two initial levels, - * these are 2 less than the VIC CPIs */ -#define QIC_CPI_OFFSET 1 -#define QIC_TIMER_CPI (VIC_TIMER_CPI - QIC_CPI_OFFSET) -#define QIC_INVALIDATE_CPI (VIC_INVALIDATE_CPI - QIC_CPI_OFFSET) -#define QIC_RESCHEDULE_CPI (VIC_RESCHEDULE_CPI - QIC_CPI_OFFSET) -#define QIC_ENABLE_IRQ_CPI (VIC_ENABLE_IRQ_CPI - QIC_CPI_OFFSET) -#define QIC_CALL_FUNCTION_CPI (VIC_CALL_FUNCTION_CPI - QIC_CPI_OFFSET) -#define QIC_CALL_FUNCTION_SINGLE_CPI (VIC_CALL_FUNCTION_SINGLE_CPI - QIC_CPI_OFFSET) - -#define VIC_START_FAKE_CPI VIC_TIMER_CPI -#define VIC_END_FAKE_CPI VIC_CALL_FUNCTION_SINGLE_CPI - -/* this is the SYS_INT CPI. */ -#define VIC_SYS_INT 8 -#define VIC_CMN_INT 15 - -/* This is the boot CPI for alternate processors. It gets overwritten - * by the above once the system has activated all available processors */ -#define VIC_CPU_BOOT_CPI VIC_CPI_LEVEL0 -#define VIC_CPU_BOOT_ERRATA_CPI (VIC_CPI_LEVEL0 + 8) - - #endif /* _ASM_X86_IRQ_VECTORS_H */ diff --git a/arch/x86/include/asm/voyager.h b/arch/x86/include/asm/voyager.h index b3e64730762..c1635d43616 100644 --- a/arch/x86/include/asm/voyager.h +++ b/arch/x86/include/asm/voyager.h @@ -527,3 +527,45 @@ extern void voyager_smp_intr_init(void); #define VOYAGER_PSI_SUBREAD 2 #define VOYAGER_PSI_SUBWRITE 3 extern void voyager_cat_psi(__u8, __u16, __u8 *); + +/* These define the CPIs we use in linux */ +#define VIC_CPI_LEVEL0 0 +#define VIC_CPI_LEVEL1 1 +/* now the fake CPIs */ +#define VIC_TIMER_CPI 2 +#define VIC_INVALIDATE_CPI 3 +#define VIC_RESCHEDULE_CPI 4 +#define VIC_ENABLE_IRQ_CPI 5 +#define VIC_CALL_FUNCTION_CPI 6 +#define VIC_CALL_FUNCTION_SINGLE_CPI 7 + +/* Now the QIC CPIs: Since we don't need the two initial levels, + * these are 2 less than the VIC CPIs */ +#define QIC_CPI_OFFSET 1 +#define QIC_TIMER_CPI (VIC_TIMER_CPI - QIC_CPI_OFFSET) +#define QIC_INVALIDATE_CPI (VIC_INVALIDATE_CPI - QIC_CPI_OFFSET) +#define QIC_RESCHEDULE_CPI (VIC_RESCHEDULE_CPI - QIC_CPI_OFFSET) +#define QIC_ENABLE_IRQ_CPI (VIC_ENABLE_IRQ_CPI - QIC_CPI_OFFSET) +#define QIC_CALL_FUNCTION_CPI (VIC_CALL_FUNCTION_CPI - QIC_CPI_OFFSET) +#define QIC_CALL_FUNCTION_SINGLE_CPI (VIC_CALL_FUNCTION_SINGLE_CPI - QIC_CPI_OFFSET) + +#define VIC_START_FAKE_CPI VIC_TIMER_CPI +#define VIC_END_FAKE_CPI VIC_CALL_FUNCTION_SINGLE_CPI + +/* this is the SYS_INT CPI. */ +#define VIC_SYS_INT 8 +#define VIC_CMN_INT 15 + +/* This is the boot CPI for alternate processors. It gets overwritten + * by the above once the system has activated all available processors */ +#define VIC_CPU_BOOT_CPI VIC_CPI_LEVEL0 +#define VIC_CPU_BOOT_ERRATA_CPI (VIC_CPI_LEVEL0 + 8) + +extern asmlinkage void vic_cpi_interrupt(void); +extern asmlinkage void vic_sys_interrupt(void); +extern asmlinkage void vic_cmn_interrupt(void); +extern asmlinkage void qic_timer_interrupt(void); +extern asmlinkage void qic_invalidate_interrupt(void); +extern asmlinkage void qic_reschedule_interrupt(void); +extern asmlinkage void qic_enable_irq_interrupt(void); +extern asmlinkage void qic_call_function_interrupt(void); -- GitLab From 3e92ab3d7e2edef5dccd8b0db21528699c81d2c0 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 31 Jan 2009 02:21:42 +0100 Subject: [PATCH 1040/4982] x86, irqs, voyager: remove Voyager quirk Remove a Voyager complication from the generic irq_vectors.h header. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/irq_vectors.h | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index 067d22ffb3e..81fc883b3c0 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h @@ -106,7 +106,7 @@ #define NR_IRQS_LEGACY 16 -#if defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_VOYAGER) +#ifdef CONFIG_X86_IO_APIC #include /* need MAX_IO_APICS */ @@ -117,22 +117,14 @@ # define NR_IRQS (NR_VECTORS + (32 * MAX_IO_APICS)) # endif #else - # define NR_IRQS \ ((8 * NR_CPUS) > (32 * MAX_IO_APICS) ? \ (NR_VECTORS + (8 * NR_CPUS)) : \ - (NR_VECTORS + (32 * MAX_IO_APICS))) \ - + (NR_VECTORS + (32 * MAX_IO_APICS))) #endif -#elif defined(CONFIG_X86_VOYAGER) - -# define NR_IRQS 224 - -#else /* IO_APIC || VOYAGER */ - +#else /* !CONFIG_X86_IO_APIC: */ # define NR_IRQS 16 - #endif #endif /* _ASM_X86_IRQ_VECTORS_H */ -- GitLab From 9fc2e79d4f239c1c1dfdab7b10854c7588b39d9a Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 31 Jan 2009 02:48:17 +0100 Subject: [PATCH 1041/4982] x86, irq: add IRQ layout comments Describe the layout of x86 trap/exception/IRQ vectors and clean up indentation and other small details. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/irq_vectors.h | 92 +++++++++++++++++++----------- 1 file changed, 58 insertions(+), 34 deletions(-) diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index 81fc883b3c0..5f7d6a1e3d2 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h @@ -3,45 +3,69 @@ #include -#define NMI_VECTOR 0x02 +/* + * Linux IRQ vector layout. + * + * There are 256 IDT entries (per CPU - each entry is 8 bytes) which can + * be defined by Linux. They are used as a jump table by the CPU when a + * given vector is triggered - by a CPU-external, CPU-internal or + * software-triggered event. + * + * Linux sets the kernel code address each entry jumps to early during + * bootup, and never changes them. This is the general layout of the + * IDT entries: + * + * Vectors 0 ... 31 : system traps and exceptions - hardcoded events + * Vectors 32 ... 127 : device interrupts + * Vector 128 : legacy int80 syscall interface + * Vectors 129 ... 237 : device interrupts + * Vectors 238 ... 255 : special interrupts + * + * 64-bit x86 has per CPU IDT tables, 32-bit has one shared IDT table. + * + * This file enumerates the exact layout of them: + */ + +#define NMI_VECTOR 0x02 /* * IDT vectors usable for external interrupt sources start * at 0x20: */ -#define FIRST_EXTERNAL_VECTOR 0x20 +#define FIRST_EXTERNAL_VECTOR 0x20 #ifdef CONFIG_X86_32 -# define SYSCALL_VECTOR 0x80 +# define SYSCALL_VECTOR 0x80 #else -# define IA32_SYSCALL_VECTOR 0x80 +# define IA32_SYSCALL_VECTOR 0x80 #endif /* * Reserve the lowest usable priority level 0x20 - 0x2f for triggering * cleanup after irq migration. */ -#define IRQ_MOVE_CLEANUP_VECTOR FIRST_EXTERNAL_VECTOR +#define IRQ_MOVE_CLEANUP_VECTOR FIRST_EXTERNAL_VECTOR /* * Vectors 0x30-0x3f are used for ISA interrupts. */ -#define IRQ0_VECTOR (FIRST_EXTERNAL_VECTOR + 0x10) -#define IRQ1_VECTOR (IRQ0_VECTOR + 1) -#define IRQ2_VECTOR (IRQ0_VECTOR + 2) -#define IRQ3_VECTOR (IRQ0_VECTOR + 3) -#define IRQ4_VECTOR (IRQ0_VECTOR + 4) -#define IRQ5_VECTOR (IRQ0_VECTOR + 5) -#define IRQ6_VECTOR (IRQ0_VECTOR + 6) -#define IRQ7_VECTOR (IRQ0_VECTOR + 7) -#define IRQ8_VECTOR (IRQ0_VECTOR + 8) -#define IRQ9_VECTOR (IRQ0_VECTOR + 9) -#define IRQ10_VECTOR (IRQ0_VECTOR + 10) -#define IRQ11_VECTOR (IRQ0_VECTOR + 11) -#define IRQ12_VECTOR (IRQ0_VECTOR + 12) -#define IRQ13_VECTOR (IRQ0_VECTOR + 13) -#define IRQ14_VECTOR (IRQ0_VECTOR + 14) -#define IRQ15_VECTOR (IRQ0_VECTOR + 15) +#define IRQ0_VECTOR (FIRST_EXTERNAL_VECTOR + 0x10) + +#define IRQ1_VECTOR (IRQ0_VECTOR + 1) +#define IRQ2_VECTOR (IRQ0_VECTOR + 2) +#define IRQ3_VECTOR (IRQ0_VECTOR + 3) +#define IRQ4_VECTOR (IRQ0_VECTOR + 4) +#define IRQ5_VECTOR (IRQ0_VECTOR + 5) +#define IRQ6_VECTOR (IRQ0_VECTOR + 6) +#define IRQ7_VECTOR (IRQ0_VECTOR + 7) +#define IRQ8_VECTOR (IRQ0_VECTOR + 8) +#define IRQ9_VECTOR (IRQ0_VECTOR + 9) +#define IRQ10_VECTOR (IRQ0_VECTOR + 10) +#define IRQ11_VECTOR (IRQ0_VECTOR + 11) +#define IRQ12_VECTOR (IRQ0_VECTOR + 12) +#define IRQ13_VECTOR (IRQ0_VECTOR + 13) +#define IRQ14_VECTOR (IRQ0_VECTOR + 14) +#define IRQ15_VECTOR (IRQ0_VECTOR + 15) /* * Special IRQ vectors used by the SMP architecture, 0xf0-0xff @@ -75,36 +99,36 @@ /* f0-f7 used for spreading out TLB flushes: */ #define INVALIDATE_TLB_VECTOR_END 0xf7 #define INVALIDATE_TLB_VECTOR_START 0xf0 -#define NUM_INVALIDATE_TLB_VECTORS 8 +#define NUM_INVALIDATE_TLB_VECTORS 8 /* * Local APIC timer IRQ vector is on a different priority level, * to work around the 'lost local interrupt if more than 2 IRQ * sources per level' errata. */ -#define LOCAL_TIMER_VECTOR 0xef +#define LOCAL_TIMER_VECTOR 0xef /* * Performance monitoring interrupt vector: */ -#define LOCAL_PERF_VECTOR 0xee +#define LOCAL_PERF_VECTOR 0xee /* * First APIC vector available to drivers: (vectors 0x30-0xee) we * start at 0x31(0x41) to spread out vectors evenly between priority * levels. (0x80 is the syscall vector) */ -#define FIRST_DEVICE_VECTOR (IRQ15_VECTOR + 2) +#define FIRST_DEVICE_VECTOR (IRQ15_VECTOR + 2) -#define NR_VECTORS 256 +#define NR_VECTORS 256 -#define FPU_IRQ 13 +#define FPU_IRQ 13 -#define FIRST_VM86_IRQ 3 -#define LAST_VM86_IRQ 15 -#define invalid_vm86_irq(irq) ((irq) < 3 || (irq) > 15) +#define FIRST_VM86_IRQ 3 +#define LAST_VM86_IRQ 15 +#define invalid_vm86_irq(irq) ((irq) < 3 || (irq) > 15) -#define NR_IRQS_LEGACY 16 +#define NR_IRQS_LEGACY 16 #ifdef CONFIG_X86_IO_APIC @@ -112,9 +136,9 @@ #ifndef CONFIG_SPARSE_IRQ # if NR_CPUS < MAX_IO_APICS -# define NR_IRQS (NR_VECTORS + (32 * NR_CPUS)) +# define NR_IRQS (NR_VECTORS + (32 * NR_CPUS)) # else -# define NR_IRQS (NR_VECTORS + (32 * MAX_IO_APICS)) +# define NR_IRQS (NR_VECTORS + (32 * MAX_IO_APICS)) # endif #else # define NR_IRQS \ @@ -124,7 +148,7 @@ #endif #else /* !CONFIG_X86_IO_APIC: */ -# define NR_IRQS 16 +# define NR_IRQS 16 #endif #endif /* _ASM_X86_IRQ_VECTORS_H */ -- GitLab From c379698fdac7cb65c96dec549850ce606dd6ceba Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 31 Jan 2009 02:50:46 +0100 Subject: [PATCH 1042/4982] x86, irq_vectors.h: remove needless includes Reduce include file dependencies a bit - remove the two headers that are included in irq_vectors.h. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/irq_vectors.h | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index 5f7d6a1e3d2..ec87910025d 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h @@ -1,8 +1,6 @@ #ifndef _ASM_X86_IRQ_VECTORS_H #define _ASM_X86_IRQ_VECTORS_H -#include - /* * Linux IRQ vector layout. * @@ -131,22 +129,18 @@ #define NR_IRQS_LEGACY 16 #ifdef CONFIG_X86_IO_APIC - -#include /* need MAX_IO_APICS */ - -#ifndef CONFIG_SPARSE_IRQ -# if NR_CPUS < MAX_IO_APICS -# define NR_IRQS (NR_VECTORS + (32 * NR_CPUS)) +# ifndef CONFIG_SPARSE_IRQ +# if NR_CPUS < MAX_IO_APICS +# define NR_IRQS (NR_VECTORS + (32 * NR_CPUS)) +# else +# define NR_IRQS (NR_VECTORS + (32 * MAX_IO_APICS)) +# endif # else -# define NR_IRQS (NR_VECTORS + (32 * MAX_IO_APICS)) -# endif -#else -# define NR_IRQS \ +# define NR_IRQS \ ((8 * NR_CPUS) > (32 * MAX_IO_APICS) ? \ (NR_VECTORS + (8 * NR_CPUS)) : \ (NR_VECTORS + (32 * MAX_IO_APICS))) -#endif - +# endif #else /* !CONFIG_X86_IO_APIC: */ # define NR_IRQS 16 #endif -- GitLab From 009eb3fe146aa6f1951f3c5235851bb8d1330dfb Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 31 Jan 2009 02:56:44 +0100 Subject: [PATCH 1043/4982] x86, irq: describe NR_IRQ sizing details, clean up Impact: cleanup Signed-off-by: Ingo Molnar --- arch/x86/include/asm/irq_vectors.h | 32 +++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index ec87910025d..41e2450e13b 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h @@ -126,23 +126,37 @@ #define LAST_VM86_IRQ 15 #define invalid_vm86_irq(irq) ((irq) < 3 || (irq) > 15) +/* + * Size the maximum number of interrupts. + * + * If the irq_desc[] array has a sparse layout, we can size things + * generously - it scales up linearly with the maximum number of CPUs, + * and the maximum number of IO-APICs, whichever is higher. + * + * In other cases we size more conservatively, to not create too large + * static arrays. + */ + #define NR_IRQS_LEGACY 16 +#define CPU_VECTOR_LIMIT ( 8 * NR_CPUS ) +#define IO_APIC_VECTOR_LIMIT ( 32 * MAX_IO_APICS ) + #ifdef CONFIG_X86_IO_APIC -# ifndef CONFIG_SPARSE_IRQ +# ifdef CONFIG_SPARSE_IRQ +# define NR_IRQS \ + (CPU_VECTOR_LIMIT > IO_APIC_VECTOR_LIMIT ? \ + (NR_VECTORS + CPU_VECTOR_LIMIT) : \ + (NR_VECTORS + IO_APIC_VECTOR_LIMIT)) +# else # if NR_CPUS < MAX_IO_APICS -# define NR_IRQS (NR_VECTORS + (32 * NR_CPUS)) +# define NR_IRQS (NR_VECTORS + 4*CPU_VECTOR_LIMIT) # else -# define NR_IRQS (NR_VECTORS + (32 * MAX_IO_APICS)) +# define NR_IRQS (NR_VECTORS + IO_APIC_VECTOR_LIMIT) # endif -# else -# define NR_IRQS \ - ((8 * NR_CPUS) > (32 * MAX_IO_APICS) ? \ - (NR_VECTORS + (8 * NR_CPUS)) : \ - (NR_VECTORS + (32 * MAX_IO_APICS))) # endif #else /* !CONFIG_X86_IO_APIC: */ -# define NR_IRQS 16 +# define NR_IRQS NR_IRQS_LEGACY #endif #endif /* _ASM_X86_IRQ_VECTORS_H */ -- GitLab From d8106d2e24d54497233ca9cd97fa9bec807de458 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 31 Jan 2009 03:06:17 +0100 Subject: [PATCH 1044/4982] x86, vm86: clean up invalid_vm86_irq() Signed-off-by: Ingo Molnar --- arch/x86/include/asm/irq_vectors.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index 41e2450e13b..b07278c55e9 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h @@ -124,7 +124,13 @@ #define FIRST_VM86_IRQ 3 #define LAST_VM86_IRQ 15 -#define invalid_vm86_irq(irq) ((irq) < 3 || (irq) > 15) + +#ifndef __ASSEMBLY__ +static inline int invalid_vm86_irq(int irq) +{ + return irq < 3 || irq > 15; +} +#endif /* * Size the maximum number of interrupts. -- GitLab From 2749ebe320ff9f77548d10fcc0a3464ac21c8e58 Mon Sep 17 00:00:00 2001 From: Cliff Wickman Date: Thu, 29 Jan 2009 15:35:26 -0600 Subject: [PATCH 1045/4982] x86: UV fix uv_flush_send_and_wait() Impact: fix possible tlb mis-flushing on UV uv_flush_send_and_wait() should return a pointer if the broadcast remote tlb shootdown requests fail. That causes the conventional IPI method of shootdown to be used. Signed-off-by: Cliff Wickman Signed-off-by: Tejun Heo --- arch/x86/kernel/tlb_uv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c index 89fce1b6d01..f4b2f27d19b 100644 --- a/arch/x86/kernel/tlb_uv.c +++ b/arch/x86/kernel/tlb_uv.c @@ -259,7 +259,7 @@ const struct cpumask *uv_flush_send_and_wait(int cpu, int this_blade, * the cpu's, all of which are still in the mask. */ __get_cpu_var(ptcstats).ptc_i++; - return 0; + return flush_mask; } /* -- GitLab From 552be871e67ff577ed36beb2f53d078b42304739 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Fri, 30 Jan 2009 17:47:53 +0900 Subject: [PATCH 1046/4982] x86: pass in cpu number to switch_to_new_gdt() Impact: cleanup, prepare for xen boot fix. Xen needs to call this function very early to setup the GDT and per-cpu segments. Remove the call to smp_processor_id() and just pass in the cpu number. Signed-off-by: Brian Gerst Signed-off-by: Tejun Heo --- arch/x86/include/asm/processor.h | 2 +- arch/x86/kernel/cpu/common.c | 7 +++---- arch/x86/kernel/setup_percpu.c | 2 +- arch/x86/kernel/smpboot.c | 2 +- arch/x86/mach-voyager/voyager_smp.c | 11 ++++++----- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index befa20b4a68..1c25eb69ea8 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -768,7 +768,7 @@ extern int sysenter_setup(void); extern struct desc_ptr early_gdt_descr; extern void cpu_set_gdt(int); -extern void switch_to_new_gdt(void); +extern void switch_to_new_gdt(int); extern void cpu_init(void); static inline unsigned long get_debugctlmsr(void) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 652fdc9a757..6eacd64b602 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -255,10 +255,9 @@ __u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata; /* Current gdt points %fs at the "master" per-cpu area: after this, * it's on the real one. */ -void switch_to_new_gdt(void) +void switch_to_new_gdt(int cpu) { struct desc_ptr gdt_descr; - int cpu = smp_processor_id(); gdt_descr.address = (long)get_cpu_gdt_table(cpu); gdt_descr.size = GDT_SIZE - 1; @@ -993,7 +992,7 @@ void __cpuinit cpu_init(void) * and set up the GDT descriptor: */ - switch_to_new_gdt(); + switch_to_new_gdt(cpu); loadsegment(fs, 0); load_idt((const struct desc_ptr *)&idt_descr); @@ -1098,7 +1097,7 @@ void __cpuinit cpu_init(void) clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); load_idt(&idt_descr); - switch_to_new_gdt(); + switch_to_new_gdt(cpu); /* * Set up and load the per-CPU TSS and LDT diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 0d1e7ac439f..ef91747bbed 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -122,7 +122,7 @@ void __init setup_per_cpu_areas(void) * area. Reload any changed state for the boot CPU. */ if (cpu == boot_cpu_id) - switch_to_new_gdt(); + switch_to_new_gdt(cpu); DBG("PERCPU: cpu %4d %p\n", cpu, ptr); } diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index f9dbcff4354..612d3c74f6a 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1185,7 +1185,7 @@ out: void __init native_smp_prepare_boot_cpu(void) { int me = smp_processor_id(); - switch_to_new_gdt(); + switch_to_new_gdt(me); /* already set me in cpu_online_mask in boot_cpu_init() */ cpumask_set_cpu(me, cpu_callout_mask); per_cpu(cpu_state, me) = CPU_ONLINE; diff --git a/arch/x86/mach-voyager/voyager_smp.c b/arch/x86/mach-voyager/voyager_smp.c index 331cd6d5648..58c7cac3440 100644 --- a/arch/x86/mach-voyager/voyager_smp.c +++ b/arch/x86/mach-voyager/voyager_smp.c @@ -1746,12 +1746,13 @@ static void __init voyager_smp_prepare_cpus(unsigned int max_cpus) static void __cpuinit voyager_smp_prepare_boot_cpu(void) { - switch_to_new_gdt(); + int cpu = smp_processor_id(); + switch_to_new_gdt(cpu); - cpu_set(smp_processor_id(), cpu_online_map); - cpu_set(smp_processor_id(), cpu_callout_map); - cpu_set(smp_processor_id(), cpu_possible_map); - cpu_set(smp_processor_id(), cpu_present_map); + cpu_set(cpu, cpu_online_map); + cpu_set(cpu, cpu_callout_map); + cpu_set(cpu, cpu_possible_map); + cpu_set(cpu, cpu_present_map); } static int __cpuinit voyager_cpu_up(unsigned int cpu) -- GitLab From 11e3a840cd5b731cdd8f6f956dfae78a8046d09c Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Fri, 30 Jan 2009 17:47:54 +0900 Subject: [PATCH 1047/4982] x86: split loading percpu segments from loading gdt Impact: split out a function, no functional change Xen needs to be able to access percpu data from very early on. For various reasons, it cannot also load the gdt at that time. It does, however, have a pefectly functional gdt at that point, so there's no pressing need to reload the gdt. Split the function to load the segment registers off, so Xen can call it directly. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Tejun Heo --- arch/x86/include/asm/processor.h | 1 + arch/x86/kernel/cpu/common.c | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 1c25eb69ea8..656d02ea509 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -769,6 +769,7 @@ extern struct desc_ptr early_gdt_descr; extern void cpu_set_gdt(int); extern void switch_to_new_gdt(int); +extern void load_percpu_segment(int); extern void cpu_init(void); static inline unsigned long get_debugctlmsr(void) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 6eacd64b602..0f73ea42308 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -253,6 +253,16 @@ static char __cpuinit *table_lookup_model(struct cpuinfo_x86 *c) __u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata; +void load_percpu_segment(int cpu) +{ +#ifdef CONFIG_X86_32 + loadsegment(fs, __KERNEL_PERCPU); +#else + loadsegment(gs, 0); + wrmsrl(MSR_GS_BASE, (unsigned long)per_cpu(irq_stack_union.gs_base, cpu)); +#endif +} + /* Current gdt points %fs at the "master" per-cpu area: after this, * it's on the real one. */ void switch_to_new_gdt(int cpu) @@ -263,12 +273,8 @@ void switch_to_new_gdt(int cpu) gdt_descr.size = GDT_SIZE - 1; load_gdt(&gdt_descr); /* Reload the per-cpu base */ -#ifdef CONFIG_X86_32 - loadsegment(fs, __KERNEL_PERCPU); -#else - loadsegment(gs, 0); - wrmsrl(MSR_GS_BASE, (unsigned long)per_cpu(irq_stack_union.gs_base, cpu)); -#endif + + load_percpu_segment(cpu); } static struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {}; -- GitLab From 795f99b61d20c34cb04d17d8906b32f745a635ec Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Fri, 30 Jan 2009 17:47:54 +0900 Subject: [PATCH 1048/4982] xen: setup percpu data pointers Impact: fix xen booting We need to access percpu data fairly early, so set up the percpu registers as soon as possible. We only need to load the appropriate segment register. We already have a GDT, but its hard to change it early because we need to manipulate the pagetable to do so, and that hasn't been set up yet. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Tejun Heo --- arch/x86/xen/enlighten.c | 3 +++ arch/x86/xen/smp.c | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index bef941f6145..fe19c88a502 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1647,6 +1647,9 @@ asmlinkage void __init xen_start_kernel(void) have_vcpu_info_placement = 0; #endif + /* setup percpu state */ + load_percpu_segment(0); + xen_smp_init(); /* Get mfn list */ diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 7735e3dd359..88d5d5ec6be 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -170,7 +170,8 @@ static void __init xen_smp_prepare_boot_cpu(void) /* We've switched to the "real" per-cpu gdt, so make sure the old memory can be recycled */ - make_lowmem_page_readwrite(&per_cpu_var(gdt_page)); + make_lowmem_page_readwrite(__per_cpu_load + + (unsigned long)&per_cpu_var(gdt_page)); xen_setup_vcpu_info_placement(); } @@ -235,6 +236,8 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle) ctxt->user_regs.ss = __KERNEL_DS; #ifdef CONFIG_X86_32 ctxt->user_regs.fs = __KERNEL_PERCPU; +#else + ctxt->gs_base_kernel = per_cpu_offset(cpu); #endif ctxt->user_regs.eip = (unsigned long)cpu_bringup_and_idle; ctxt->user_regs.eflags = 0x1000; /* IOPL_RING1 */ -- GitLab From ff7bf02f630ae93cad4feda0f6a5a19b25a5019a Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Fri, 30 Jan 2009 11:14:49 -0600 Subject: [PATCH 1049/4982] ASoC: fix documentation in CS4270 codec driver Spruce up the documentation in the CS4270 codec. Use kerneldoc where appropriate. Fix incorrect comments. Signed-off-by: Timur Tabi Signed-off-by: Mark Brown --- sound/soc/codecs/cs4270.c | 163 ++++++++++++++++++++++++-------------- 1 file changed, 105 insertions(+), 58 deletions(-) diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index adc1150ddb0..e5f5afdd342 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -3,10 +3,10 @@ * * Author: Timur Tabi * - * Copyright 2007 Freescale Semiconductor, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. + * Copyright 2007-2009 Freescale Semiconductor, Inc. This file is licensed + * under the terms of the GNU General Public License version 2. This + * program is licensed "as is" without any warranty of any kind, whether + * express or implied. * * This is an ASoC device driver for the Cirrus Logic CS4270 codec. * @@ -111,8 +111,13 @@ struct cs4270_private { unsigned int mode; /* The mode (I2S or left-justified) */ }; -/* - * Clock Ratio Selection for Master Mode with I2C enabled +/** + * struct cs4270_mode_ratios - clock ratio tables + * @ratio: the ratio of MCLK to the sample rate + * @speed_mode: the Speed Mode bits to set in the Mode Control register for + * this ratio + * @mclk: the Ratio Select bits to set in the Mode Control register for this + * ratio * * The data for this chart is taken from Table 5 of the CS4270 reference * manual. @@ -121,31 +126,30 @@ struct cs4270_private { * It is also used by cs4270_set_dai_sysclk() to tell ALSA which sampling * rates the CS4270 currently supports. * - * Each element in this array corresponds to the ratios in mclk_ratios[]. - * These two arrays need to be in sync. - * - * 'speed_mode' is the corresponding bit pattern to be written to the + * @speed_mode is the corresponding bit pattern to be written to the * MODE bits of the Mode Control Register * - * 'mclk' is the corresponding bit pattern to be wirten to the MCLK bits of + * @mclk is the corresponding bit pattern to be wirten to the MCLK bits of * the Mode Control Register. * * In situations where a single ratio is represented by multiple speed * modes, we favor the slowest speed. E.g, for a ratio of 128, we pick * double-speed instead of quad-speed. However, the CS4270 errata states - * that Divide-By-1.5 can cause failures, so we avoid that mode where + * that divide-By-1.5 can cause failures, so we avoid that mode where * possible. * - * ERRATA: There is an errata for the CS4270 where divide-by-1.5 does not - * work if VD = 3.3V. If this effects you, select the + * Errata: There is an errata for the CS4270 where divide-by-1.5 does not + * work if Vd is 3.3V. If this effects you, select the * CONFIG_SND_SOC_CS4270_VD33_ERRATA Kconfig option, and the driver will * never select any sample rates that require divide-by-1.5. */ -static struct { +struct cs4270_mode_ratios { unsigned int ratio; u8 speed_mode; u8 mclk; -} cs4270_mode_ratios[] = { +}; + +static struct cs4270_mode_ratios[] = { {64, CS4270_MODE_4X, CS4270_MODE_DIV1}, #ifndef CONFIG_SND_SOC_CS4270_VD33_ERRATA {96, CS4270_MODE_4X, CS4270_MODE_DIV15}, @@ -162,34 +166,27 @@ static struct { /* The number of MCLK/LRCK ratios supported by the CS4270 */ #define NUM_MCLK_RATIOS ARRAY_SIZE(cs4270_mode_ratios) -/* - * Determine the CS4270 samples rates. +/** + * cs4270_set_dai_sysclk - determine the CS4270 samples rates. + * @codec_dai: the codec DAI + * @clk_id: the clock ID (ignored) + * @freq: the MCLK input frequency + * @dir: the clock direction (ignored) * - * 'freq' is the input frequency to MCLK. The other parameters are ignored. + * This function is used to tell the codec driver what the input MCLK + * frequency is. * * The value of MCLK is used to determine which sample rates are supported * by the CS4270. The ratio of MCLK / Fs must be equal to one of nine - * support values: 64, 96, 128, 192, 256, 384, 512, 768, and 1024. + * supported values - 64, 96, 128, 192, 256, 384, 512, 768, and 1024. * * This function calculates the nine ratios and determines which ones match * a standard sample rate. If there's a match, then it is added to the list - * of support sample rates. + * of supported sample rates. * * This function must be called by the machine driver's 'startup' function, * otherwise the list of supported sample rates will not be available in * time for ALSA. - * - * Note that in stand-alone mode, the sample rate is determined by input - * pins M0, M1, MDIV1, and MDIV2. Also in stand-alone mode, divide-by-3 - * is not a programmable option. However, divide-by-3 is not an available - * option in stand-alone mode. This cases two problems: a ratio of 768 is - * not available (it requires divide-by-3) and B) ratios 192 and 384 can - * only be selected with divide-by-1.5, but there is an errate that make - * this selection difficult. - * - * In addition, there is no mechanism for communicating with the machine - * driver what the input settings can be. This would need to be implemented - * for stand-alone mode to work. */ static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id, unsigned int freq, int dir) @@ -230,8 +227,10 @@ static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai, return 0; } -/* - * Configure the codec for the selected audio format +/** + * cs4270_set_dai_fmt - configure the codec for the selected audio format + * @codec_dai: the codec DAI + * @format: a SND_SOC_DAIFMT_x value indicating the data format * * This function takes a bitmask of SND_SOC_DAIFMT_x bits and programs the * codec accordingly. @@ -261,8 +260,16 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai, return ret; } -/* - * Pre-fill the CS4270 register cache. +/** + * cs4270_fill_cache - pre-fill the CS4270 register cache. + * @codec: the codec for this CS4270 + * + * This function fills in the CS4270 register cache by reading the register + * values from the hardware. + * + * This CS4270 registers are cached to avoid excessive I2C I/O operations. + * After the initial read to pre-fill the cache, the CS4270 never updates + * the register values, so we won't have a cache coherency problem. * * We use the auto-increment feature of the CS4270 to read all registers in * one shot. @@ -285,12 +292,17 @@ static int cs4270_fill_cache(struct snd_soc_codec *codec) return 0; } -/* - * Read from the CS4270 register cache. +/** + * cs4270_read_reg_cache - read from the CS4270 register cache. + * @codec: the codec for this CS4270 + * @reg: the register to read + * + * This function returns the value for a given register. It reads only from + * the register cache, not the hardware itself. * * This CS4270 registers are cached to avoid excessive I2C I/O operations. * After the initial read to pre-fill the cache, the CS4270 never updates - * the register values, so we won't have a cache coherncy problem. + * the register values, so we won't have a cache coherency problem. */ static unsigned int cs4270_read_reg_cache(struct snd_soc_codec *codec, unsigned int reg) @@ -303,8 +315,11 @@ static unsigned int cs4270_read_reg_cache(struct snd_soc_codec *codec, return cache[reg - CS4270_FIRSTREG]; } -/* - * Write to a CS4270 register via the I2C bus. +/** + * cs4270_i2c_write - write to a CS4270 register via the I2C bus. + * @codec: the codec for this CS4270 + * @reg: the register to write + * @value: the value to write to the register * * This function writes the given value to the given CS4270 register, and * also updates the register cache. @@ -336,11 +351,17 @@ static int cs4270_i2c_write(struct snd_soc_codec *codec, unsigned int reg, return 0; } -/* - * Program the CS4270 with the given hardware parameters. +/** + * cs4270_hw_params - program the CS4270 with the given hardware parameters. + * @substream: the audio stream + * @params: the hardware parameters to set + * @dai: the SOC DAI (ignored) * - * The .ops functions are used to provide board-specific data, like - * input frequencies, to this driver. This function takes that information, + * This function programs the hardware with the values provided. + * Specifically, the sample rate and the data format. + * + * The .ops functions are used to provide board-specific data, like input + * frequencies, to this driver. This function takes that information, * combines it with the hardware parameters provided, and programs the * hardware accordingly. */ @@ -455,8 +476,10 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, } #ifdef CONFIG_SND_SOC_CS4270_HWMUTE -/* - * Set the CS4270 external mute +/** + * cs4270_mute - enable/disable the CS4270 external mute + * @dai: the SOC DAI + * @mute: 0 = disable mute, 1 = enable mute * * This function toggles the mute bits in the MUTE register. The CS4270's * mute capability is intended for external muting circuitry, so if the @@ -490,7 +513,7 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = { }; /* - * Global variable to store codec for the ASoC probe function. + * cs4270_codec - global variable to store codec for the ASoC probe function * * If struct i2c_driver had a private_data field, we wouldn't need to use * cs4270_codec. This is the only way to pass the codec structure from @@ -527,8 +550,12 @@ struct snd_soc_dai cs4270_dai = { }; EXPORT_SYMBOL_GPL(cs4270_dai); -/* - * ASoC probe function +/** + * cs4270_probe - ASoC probe function + * @pdev: platform device + * + * This function is called when ASoC has all the pieces it needs to + * instantiate a sound driver. */ static int cs4270_probe(struct platform_device *pdev) { @@ -582,6 +609,12 @@ error_free_pcms: return ret; } +/** + * cs4270_remove - ASoC remove function + * @pdev: platform device + * + * This function is the counterpart to cs4270_probe(). + */ static int cs4270_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); @@ -591,14 +624,13 @@ static int cs4270_remove(struct platform_device *pdev) return 0; }; -/* - * Initialize the I2C interface of the CS4270 - * - * This function is called for whenever the I2C subsystem finds a device - * at a particular address. +/** + * cs4270_i2c_probe - initialize the I2C interface of the CS4270 + * @i2c_client: the I2C client object + * @id: the I2C device ID (ignored) * - * Note: snd_soc_new_pcms() must be called before this function can be called, - * because of snd_ctl_add(). + * This function is called whenever the I2C subsystem finds a device that + * matches the device ID given via a prior call to i2c_add_driver(). */ static int cs4270_i2c_probe(struct i2c_client *i2c_client, const struct i2c_device_id *id) @@ -690,6 +722,12 @@ error_free_codec: return ret; } +/** + * cs4270_i2c_remove - remove an I2C device + * @i2c_client: the I2C client object + * + * This function is the counterpart to cs4270_i2c_probe(). + */ static int cs4270_i2c_remove(struct i2c_client *i2c_client) { struct cs4270_private *cs4270 = i2c_get_clientdata(i2c_client); @@ -699,12 +737,21 @@ static int cs4270_i2c_remove(struct i2c_client *i2c_client) return 0; } +/* + * cs4270_id - I2C device IDs supported by this driver + */ static struct i2c_device_id cs4270_id[] = { {"cs4270", 0}, {} }; MODULE_DEVICE_TABLE(i2c, cs4270_id); +/* + * cs4270_i2c_driver - I2C device identification + * + * This structure tells the I2C subsystem how to identify and support a + * given I2C device type. + */ static struct i2c_driver cs4270_i2c_driver = { .driver = { .name = "cs4270", -- GitLab From 8f008062943c8565e855dda8a6681f641d7e71f9 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Sat, 31 Jan 2009 16:29:24 +0200 Subject: [PATCH 1050/4982] ASoC: Update OMAP3 pandora board file Update pandora board file for recent TWL4030 codec changes. Also move output related snd_soc_dapm_nc_pin() calls to omap3pandora_out_init(), where they belong. Signed-off-by: Grazvydas Ignotas Signed-off-by: Mark Brown --- sound/soc/omap/omap3pandora.c | 49 +++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c index fcc2f5d9a87..fe282d4ef42 100644 --- a/sound/soc/omap/omap3pandora.c +++ b/sound/soc/omap/omap3pandora.c @@ -143,7 +143,7 @@ static const struct snd_soc_dapm_widget omap3pandora_out_dapm_widgets[] = { }; static const struct snd_soc_dapm_widget omap3pandora_in_dapm_widgets[] = { - SND_SOC_DAPM_MIC("Mic (Internal)", NULL), + SND_SOC_DAPM_MIC("Mic (internal)", NULL), SND_SOC_DAPM_MIC("Mic (external)", NULL), SND_SOC_DAPM_LINE("Line In", NULL), }; @@ -155,16 +155,33 @@ static const struct snd_soc_dapm_route omap3pandora_out_map[] = { }; static const struct snd_soc_dapm_route omap3pandora_in_map[] = { - {"INL", NULL, "Line In"}, - {"INR", NULL, "Line In"}, - {"INL", NULL, "Mic (Internal)"}, - {"INR", NULL, "Mic (external)"}, + {"AUXL", NULL, "Line In"}, + {"AUXR", NULL, "Line In"}, + + {"MAINMIC", NULL, "Mic Bias 1"}, + {"Mic Bias 1", NULL, "Mic (internal)"}, + + {"SUBMIC", NULL, "Mic Bias 2"}, + {"Mic Bias 2", NULL, "Mic (external)"}, }; static int omap3pandora_out_init(struct snd_soc_codec *codec) { int ret; + /* All TWL4030 output pins are floating */ + snd_soc_dapm_nc_pin(codec, "OUTL"); + snd_soc_dapm_nc_pin(codec, "OUTR"); + snd_soc_dapm_nc_pin(codec, "EARPIECE"); + snd_soc_dapm_nc_pin(codec, "PREDRIVEL"); + snd_soc_dapm_nc_pin(codec, "PREDRIVER"); + snd_soc_dapm_nc_pin(codec, "HSOL"); + snd_soc_dapm_nc_pin(codec, "HSOR"); + snd_soc_dapm_nc_pin(codec, "CARKITL"); + snd_soc_dapm_nc_pin(codec, "CARKITR"); + snd_soc_dapm_nc_pin(codec, "HFL"); + snd_soc_dapm_nc_pin(codec, "HFR"); + ret = snd_soc_dapm_new_controls(codec, omap3pandora_out_dapm_widgets, ARRAY_SIZE(omap3pandora_out_dapm_widgets)); if (ret < 0) @@ -180,18 +197,11 @@ static int omap3pandora_in_init(struct snd_soc_codec *codec) { int ret; - /* All TWL4030 output pins are floating */ - snd_soc_dapm_nc_pin(codec, "OUTL"), - snd_soc_dapm_nc_pin(codec, "OUTR"), - snd_soc_dapm_nc_pin(codec, "EARPIECE"), - snd_soc_dapm_nc_pin(codec, "PREDRIVEL"), - snd_soc_dapm_nc_pin(codec, "PREDRIVER"), - snd_soc_dapm_nc_pin(codec, "HSOL"), - snd_soc_dapm_nc_pin(codec, "HSOR"), - snd_soc_dapm_nc_pin(codec, "CARKITL"), - snd_soc_dapm_nc_pin(codec, "CARKITR"), - snd_soc_dapm_nc_pin(codec, "HFL"), - snd_soc_dapm_nc_pin(codec, "HFR"), + /* Not comnnected */ + snd_soc_dapm_nc_pin(codec, "HSMIC"); + snd_soc_dapm_nc_pin(codec, "CARKITMIC"); + snd_soc_dapm_nc_pin(codec, "DIGIMIC0"); + snd_soc_dapm_nc_pin(codec, "DIGIMIC1"); ret = snd_soc_dapm_new_controls(codec, omap3pandora_in_dapm_widgets, ARRAY_SIZE(omap3pandora_in_dapm_widgets)); @@ -251,10 +261,9 @@ static int __init omap3pandora_soc_init(void) { int ret; - if (!machine_is_omap3_pandora()) { - pr_debug(PREFIX "Not OMAP3 Pandora\n"); + if (!machine_is_omap3_pandora()) return -ENODEV; - } + pr_info("OMAP3 Pandora SoC init\n"); ret = gpio_request(OMAP3_PANDORA_DAC_POWER_GPIO, "dac_power"); -- GitLab From d563ffa6b319a4e401d096db9014a947590ca081 Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Sat, 31 Jan 2009 18:01:13 +0100 Subject: [PATCH 1051/4982] ALSA: pcxhr: fix trivial typo Signed-off-by: Tim Blechmann Signed-off-by: Takashi Iwai --- sound/pci/pcxhr/pcxhr_core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/pcxhr/pcxhr_core.h b/sound/pci/pcxhr/pcxhr_core.h index bbbd66d13a6..be0173796cd 100644 --- a/sound/pci/pcxhr/pcxhr_core.h +++ b/sound/pci/pcxhr/pcxhr_core.h @@ -1,7 +1,7 @@ /* * Driver for Digigram pcxhr compatible soundcards * - * low level interface with interrupt ans message handling + * low level interface with interrupt and message handling * * Copyright (c) 2004 by Digigram * -- GitLab From 0fc2eb3bade59365ed0b28b8ea3b5c448b2f4a26 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 10:34:04 +0530 Subject: [PATCH 1052/4982] headers_check fix: alpha, statfs.h fix the following 'make headers_check' warning: usr/include/asm-alpha/statfs.h:6: found __[us]{8,16,32,64} type without #include Signed-off-by: Jaswinder Singh Rajput --- arch/alpha/include/asm/statfs.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/alpha/include/asm/statfs.h b/arch/alpha/include/asm/statfs.h index de35cd438a1..ccd2e186bfd 100644 --- a/arch/alpha/include/asm/statfs.h +++ b/arch/alpha/include/asm/statfs.h @@ -1,6 +1,8 @@ #ifndef _ALPHA_STATFS_H #define _ALPHA_STATFS_H +#include + /* Alpha is the only 64-bit platform with 32-bit statfs. And doesn't even seem to implement statfs64 */ #define __statfs_word __u32 -- GitLab From 3fd59061b7b16dd0bb7bf779ba297daa5f0bf0f5 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 10:36:04 +0530 Subject: [PATCH 1053/4982] headers_check fix: alpha, swab.h fix the following 'make headers_check' warnings: usr/include/asm-alpha/swab.h:4: include of is preferred over usr/include/asm-alpha/swab.h:10: found __[us]{8,16,32,64} type without #include Signed-off-by: Jaswinder Singh Rajput --- arch/alpha/include/asm/swab.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/alpha/include/asm/swab.h b/arch/alpha/include/asm/swab.h index 68e7089e02d..4d682b16c7c 100644 --- a/arch/alpha/include/asm/swab.h +++ b/arch/alpha/include/asm/swab.h @@ -1,7 +1,7 @@ #ifndef _ALPHA_SWAB_H #define _ALPHA_SWAB_H -#include +#include #include #include -- GitLab From f100e6d0368742ddb8b6b9be986536e63117c05a Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 10:38:16 +0530 Subject: [PATCH 1054/4982] headers_check fix: arm, a.out.h fix the following 'make headers_check' warnings: usr/include/asm-arm/a.out.h:5: include of is preferred over usr/include/asm-arm/a.out.h:9: found __[us]{8,16,32,64} type without #include Signed-off-by: Jaswinder Singh Rajput --- arch/arm/include/asm/a.out.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/include/asm/a.out.h b/arch/arm/include/asm/a.out.h index 79489fdcc8b..083894b2e3b 100644 --- a/arch/arm/include/asm/a.out.h +++ b/arch/arm/include/asm/a.out.h @@ -2,7 +2,7 @@ #define __ARM_A_OUT_H__ #include -#include +#include struct exec { -- GitLab From 4af3bf6b393a2cec947cd42cc10fc03f5b782484 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 10:41:59 +0530 Subject: [PATCH 1055/4982] headers_check fix: arm, setup.h fix the following 'make headers_check' warnings: usr/include/asm-arm/setup.h:17: include of is preferred over usr/include/asm-arm/setup.h:25: found __[us]{8,16,32,64} type without #include Signed-off-by: Jaswinder Singh Rajput --- arch/arm/include/asm/setup.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h index f2cd18a0932..ee1304f22f9 100644 --- a/arch/arm/include/asm/setup.h +++ b/arch/arm/include/asm/setup.h @@ -14,7 +14,7 @@ #ifndef __ASMARM_SETUP_H #define __ASMARM_SETUP_H -#include +#include #define COMMAND_LINE_SIZE 1024 -- GitLab From e42ec2418fa96f98ed8d4e6d8a572a7200156df6 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 10:43:44 +0530 Subject: [PATCH 1056/4982] headers_check fix: arm, swab.h fix the following 'make headers_check' warnings: usr/include/asm-arm/swab.h:19: include of is preferred over usr/include/asm-arm/swab.h:25: found __[us]{8,16,32,64} type without #include Signed-off-by: Jaswinder Singh Rajput --- arch/arm/include/asm/swab.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/include/asm/swab.h b/arch/arm/include/asm/swab.h index 27a689be085..ca2bf2f6d6e 100644 --- a/arch/arm/include/asm/swab.h +++ b/arch/arm/include/asm/swab.h @@ -16,7 +16,7 @@ #define __ASM_ARM_SWAB_H #include -#include +#include #if !defined(__STRICT_ANSI__) || defined(__KERNEL__) # define __SWAB_64_THRU_32__ -- GitLab From 1c6ce704f1e965f64ad0b017842854ceec5b9cc7 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 10:46:26 +0530 Subject: [PATCH 1057/4982] headers_check fix: avr32, swab.h fix the following 'make headers_check' warnings: usr/include/asm-avr32/swab.h:7: include of is preferred over usr/include/asm-avr32/swab.h:22: found __[us]{8,16,32,64} type without #include Signed-off-by: Jaswinder Singh Rajput --- arch/avr32/include/asm/swab.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/avr32/include/asm/swab.h b/arch/avr32/include/asm/swab.h index a14aa5b46d9..14cc737bbca 100644 --- a/arch/avr32/include/asm/swab.h +++ b/arch/avr32/include/asm/swab.h @@ -4,7 +4,7 @@ #ifndef __ASM_AVR32_SWAB_H #define __ASM_AVR32_SWAB_H -#include +#include #include #define __SWAB_64_THRU_32__ -- GitLab From 350eb8b3cb5e4860a4c8352f2cca00e6eb4a16b2 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 10:48:44 +0530 Subject: [PATCH 1058/4982] headers_check fix: blackfin, swab.h fix the following 'make headers_check' warnings: usr/include/asm-blackfin/swab.h:4: include of is preferred over usr/include/asm-blackfin/swab.h:13: found __[us]{8,16,32,64} type without #include Signed-off-by: Jaswinder Singh Rajput --- arch/blackfin/include/asm/swab.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/blackfin/include/asm/swab.h b/arch/blackfin/include/asm/swab.h index 69a051b612b..6403ad2932e 100644 --- a/arch/blackfin/include/asm/swab.h +++ b/arch/blackfin/include/asm/swab.h @@ -1,7 +1,7 @@ #ifndef _BLACKFIN_SWAB_H #define _BLACKFIN_SWAB_H -#include +#include #include #if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__) -- GitLab From dacd762eabf69e32f0e9181f99fd19b6f96ea5c5 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 10:53:32 +0530 Subject: [PATCH 1059/4982] headers_check fix: frv, swab.h fix the following 'make headers_check' warning: usr/include/asm-frv/swab.h:4: include of is preferred over Signed-off-by: Jaswinder Singh Rajput --- include/asm-frv/swab.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-frv/swab.h b/include/asm-frv/swab.h index afb3396ba5e..f305834b479 100644 --- a/include/asm-frv/swab.h +++ b/include/asm-frv/swab.h @@ -1,7 +1,7 @@ #ifndef _ASM_SWAB_H #define _ASM_SWAB_H -#include +#include #if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__) # define __SWAB_64_THRU_32__ -- GitLab From 295803eea178d777cf3813b16696c54b0b2bcd23 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 10:55:12 +0530 Subject: [PATCH 1060/4982] headers_check fix: h8300, swab.h fix the following 'make headers_check' warning: usr/include/asm-h8300/swab.h:4: include of is preferred over Signed-off-by: Jaswinder Singh Rajput --- arch/h8300/include/asm/swab.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/h8300/include/asm/swab.h b/arch/h8300/include/asm/swab.h index c108f39b8bc..39abbf52807 100644 --- a/arch/h8300/include/asm/swab.h +++ b/arch/h8300/include/asm/swab.h @@ -1,7 +1,7 @@ #ifndef _H8300_SWAB_H #define _H8300_SWAB_H -#include +#include #if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__) # define __SWAB_64_THRU_32__ -- GitLab From fa9ea6c7abd94482ecd84e130676b6a1b3e61c2c Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 10:59:12 +0530 Subject: [PATCH 1061/4982] headers_check fix: ia64, fpu.h fix the following 'make headers_check' warning: usr/include/asm-ia64/fpu.h:9: include of is preferred over Signed-off-by: Jaswinder Singh Rajput --- arch/ia64/include/asm/fpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ia64/include/asm/fpu.h b/arch/ia64/include/asm/fpu.h index 3859558ff0a..b6395ad1500 100644 --- a/arch/ia64/include/asm/fpu.h +++ b/arch/ia64/include/asm/fpu.h @@ -6,7 +6,7 @@ * David Mosberger-Tang */ -#include +#include /* floating point status register: */ #define FPSR_TRAP_VD (1 << 0) /* invalid op trap disabled */ -- GitLab From a812a9170c5db5390280eb4fa075f1555e6ae53c Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 11:03:28 +0530 Subject: [PATCH 1062/4982] headers_check fix: ia64, gcc_intrin.h fix the following 'make headers_check' warning: usr/include/asm-ia64/gcc_intrin.h:63: found __[us]{8,16,32,64} type without #include Signed-off-by: Jaswinder Singh Rajput --- arch/ia64/include/asm/gcc_intrin.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/ia64/include/asm/gcc_intrin.h b/arch/ia64/include/asm/gcc_intrin.h index 0f5b5592175..c2c5fd8fcac 100644 --- a/arch/ia64/include/asm/gcc_intrin.h +++ b/arch/ia64/include/asm/gcc_intrin.h @@ -6,6 +6,7 @@ * Copyright (C) 2002,2003 Suresh Siddha */ +#include #include /* define this macro to get some asm stmts included in 'c' files */ -- GitLab From 1ecbb7fcfd20803bdd403de0c9c514da7d6c8843 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 11:07:06 +0530 Subject: [PATCH 1063/4982] headers_check fix: ia64, intrinsics.h fix the following 'make headers_check' warning: usr/include/asm-ia64/intrinsics.h:57: found __[us]{8,16,32,64} type without #include Signed-off-by: Jaswinder Singh Rajput --- arch/ia64/include/asm/intrinsics.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/ia64/include/asm/intrinsics.h b/arch/ia64/include/asm/intrinsics.h index a3e44a5ed49..c47830e26cb 100644 --- a/arch/ia64/include/asm/intrinsics.h +++ b/arch/ia64/include/asm/intrinsics.h @@ -10,6 +10,7 @@ #ifndef __ASSEMBLY__ +#include /* include compiler specific intrinsics */ #include #ifdef __INTEL_COMPILER -- GitLab From 6ce795065bdd2bfeebd97fa91a95918dcff7d0ec Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 11:10:22 +0530 Subject: [PATCH 1064/4982] headers_check fix: ia64, kvm.h fix the following 'make headers_check' warnings: usr/include/asm-ia64/kvm.h:24: include of is preferred over usr/include/asm-ia64/kvm.h:34: found __[us]{8,16,32,64} type without #include --- arch/ia64/include/asm/kvm.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/ia64/include/asm/kvm.h b/arch/ia64/include/asm/kvm.h index 68aa6da807c..116761ca462 100644 --- a/arch/ia64/include/asm/kvm.h +++ b/arch/ia64/include/asm/kvm.h @@ -21,8 +21,7 @@ * */ -#include - +#include #include /* Architectural interrupt line count. */ -- GitLab From 040c92b8e5f080e1f5a610bf0e10c683328dce75 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 11:12:29 +0530 Subject: [PATCH 1065/4982] headers_check fix: ia64, swab.h fix the following 'make headers_check' warnings: usr/include/asm-ia64/swab.h:9: include of is preferred over usr/include/asm-ia64/swab.h:13: found __[us]{8,16,32,64} type without #include Signed-off-by: Jaswinder Singh Rajput --- arch/ia64/include/asm/swab.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ia64/include/asm/swab.h b/arch/ia64/include/asm/swab.h index 6aa58b699ee..c89a8cb5d8a 100644 --- a/arch/ia64/include/asm/swab.h +++ b/arch/ia64/include/asm/swab.h @@ -6,7 +6,7 @@ * David Mosberger-Tang , Hewlett-Packard Co. */ -#include +#include #include #include -- GitLab From d8cbec15af88e067f33cb78efad15d581fa79b12 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 11:18:19 +0530 Subject: [PATCH 1066/4982] headers_check fix: m32r, swab.h fix the following 'make headers_check' warning: usr/include/asm-m32r/swab.h:4: include of is preferred over Signed-off-by: Jaswinder Singh Rajput --- include/asm-m32r/swab.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-m32r/swab.h b/include/asm-m32r/swab.h index 97973e10182..54dab001d6d 100644 --- a/include/asm-m32r/swab.h +++ b/include/asm-m32r/swab.h @@ -1,7 +1,7 @@ #ifndef _ASM_M32R_SWAB_H #define _ASM_M32R_SWAB_H -#include +#include #if !defined(__STRICT_ANSI__) || defined(__KERNEL__) # define __SWAB_64_THRU_32__ -- GitLab From ae612fb05b0f60ff58e2a86eea46dc99532d62c5 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 11:22:18 +0530 Subject: [PATCH 1067/4982] headers_check fix: mips, sigcontext.h fix the following 'make headers_check' warning: usr/include/asm-mips/sigcontext.h:57: found __[us]{8,16,32,64} type without #include Signed-off-by: Jaswinder Singh Rajput --- arch/mips/include/asm/sigcontext.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/mips/include/asm/sigcontext.h b/arch/mips/include/asm/sigcontext.h index 9ce0607d7a4..9e89cf99d4e 100644 --- a/arch/mips/include/asm/sigcontext.h +++ b/arch/mips/include/asm/sigcontext.h @@ -9,6 +9,7 @@ #ifndef _ASM_SIGCONTEXT_H #define _ASM_SIGCONTEXT_H +#include #include #if _MIPS_SIM == _MIPS_SIM_ABI32 -- GitLab From a9f6acc5ab36c7533c9b3e224f7c209d8da4048d Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 11:23:37 +0530 Subject: [PATCH 1068/4982] headers_check fix: mips, swab.h fix the following 'make headers_check' warnings: usr/include/asm-mips/swab.h:12: include of is preferred over usr/include/asm-mips/swab.h:18: found __[us]{8,16,32,64} type without #include Signed-off-by: Jaswinder Singh Rajput --- arch/mips/include/asm/swab.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/include/asm/swab.h b/arch/mips/include/asm/swab.h index 88f1f7d555c..99993c0d6c1 100644 --- a/arch/mips/include/asm/swab.h +++ b/arch/mips/include/asm/swab.h @@ -9,7 +9,7 @@ #define _ASM_SWAB_H #include -#include +#include #define __SWAB_64_THRU_32__ -- GitLab From bef53ca086e069a3fb8e6bf4ecf06221de9b445f Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 11:29:28 +0530 Subject: [PATCH 1069/4982] headers_check fix: mn10300, swab.h fix the following 'make headers_check' warnings: usr/include/asm-mn10300/swab.h:14: include of is preferred over usr/include/asm-mn10300/swab.h:19: found __[us]{8,16,32,64} type without #include Signed-off-by: Jaswinder Singh Rajput --- include/asm-mn10300/swab.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-mn10300/swab.h b/include/asm-mn10300/swab.h index 4504d1b4b47..bd818a820ca 100644 --- a/include/asm-mn10300/swab.h +++ b/include/asm-mn10300/swab.h @@ -11,7 +11,7 @@ #ifndef _ASM_SWAB_H #define _ASM_SWAB_H -#include +#include #ifdef __GNUC__ -- GitLab From 79f95ac2412c993e52f02cfde1f71d141b2e530d Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 11:36:07 +0530 Subject: [PATCH 1070/4982] headers_check fix: parisc, pdc.h fix the following 'make headers_check' warning: usr/include/asm-parisc/pdc.h:420: found __[us]{8,16,32,64} type without #include Signed-off-by: Jaswinder Singh Rajput --- arch/parisc/include/asm/pdc.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/parisc/include/asm/pdc.h b/arch/parisc/include/asm/pdc.h index c584b00c607..430f1aeea0b 100644 --- a/arch/parisc/include/asm/pdc.h +++ b/arch/parisc/include/asm/pdc.h @@ -336,10 +336,11 @@ #define NUM_PDC_RESULT 32 #if !defined(__ASSEMBLY__) -#ifdef __KERNEL__ #include +#ifdef __KERNEL__ + extern int pdc_type; /* Values for pdc_type */ -- GitLab From 726da1e3408caae6af8372f93380f18986f1003b Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 11:39:01 +0530 Subject: [PATCH 1071/4982] headers_check fix: parisc, swab.h fix the following 'make headers_check' warnings: usr/include/asm-parisc/swab.h:4: include of is preferred over usr/include/asm-parisc/swab.h:9: found __[us]{8,16,32,64} type without #include Signed-off-by: Jaswinder Singh Rajput --- arch/parisc/include/asm/swab.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/parisc/include/asm/swab.h b/arch/parisc/include/asm/swab.h index 3ff16c5a335..e78403b129e 100644 --- a/arch/parisc/include/asm/swab.h +++ b/arch/parisc/include/asm/swab.h @@ -1,7 +1,7 @@ #ifndef _PARISC_SWAB_H #define _PARISC_SWAB_H -#include +#include #include #define __SWAB_64_THRU_32__ -- GitLab From 4be2c7ff4f362e41706e84a3d6726bdcda9ab65f Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 11:41:04 +0530 Subject: [PATCH 1072/4982] headers_check fix: powerpc, bootx.h fix the following 'make headers_check' warnings: usr/include/asm-powerpc/bootx.h:12: include of is preferred over usr/include/asm-powerpc/bootx.h:57: found __[us]{8,16,32,64} type without #include Signed-off-by: Jaswinder Singh Rajput --- arch/powerpc/include/asm/bootx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/bootx.h b/arch/powerpc/include/asm/bootx.h index 57b82e3f89c..60a3c9ef301 100644 --- a/arch/powerpc/include/asm/bootx.h +++ b/arch/powerpc/include/asm/bootx.h @@ -9,7 +9,7 @@ #ifndef __ASM_BOOTX_H__ #define __ASM_BOOTX_H__ -#include +#include #ifdef macintosh #include -- GitLab From 785857f5f0b7fbeed934e39af24edec471637375 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 11:42:29 +0530 Subject: [PATCH 1073/4982] headers_check fix: powerpc, elf.h fix the following 'make headers_check' warning: usr/include/asm-powerpc/elf.h:5: include of is preferred over Signed-off-by: Jaswinder Singh Rajput --- arch/powerpc/include/asm/elf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h index cd46f023ec6..b5600ce6055 100644 --- a/arch/powerpc/include/asm/elf.h +++ b/arch/powerpc/include/asm/elf.h @@ -7,7 +7,7 @@ #include #endif -#include +#include #include #include #include -- GitLab From 9f2cd967b7f029ebe2c74969709ff9c745344dba Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 11:44:45 +0530 Subject: [PATCH 1074/4982] headers_check fix: powerpc, kvm.h fix the following 'make headers_check' warnings: usr/include/asm-powerpc/kvm.h:23: include of is preferred over usr/include/asm-powerpc/kvm.h:26: found __[us]{8,16,32,64} type without #include Signed-off-by: Jaswinder Singh Rajput --- arch/powerpc/include/asm/kvm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/kvm.h b/arch/powerpc/include/asm/kvm.h index f993e4198d5..4e0cf65f7f5 100644 --- a/arch/powerpc/include/asm/kvm.h +++ b/arch/powerpc/include/asm/kvm.h @@ -20,7 +20,7 @@ #ifndef __LINUX_KVM_POWERPC_H #define __LINUX_KVM_POWERPC_H -#include +#include struct kvm_regs { __u64 pc; -- GitLab From 122bb2207b8107ce117d10fcfd3a2f6c3804a362 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 11:46:23 +0530 Subject: [PATCH 1075/4982] headers_check fix: powerpc, ps3fb.h fix the following 'make headers_check' warning: usr/include/asm-powerpc/ps3fb.h:33: found __[us]{8,16,32,64} type without #include Signed-off-by: Jaswinder Singh Rajput --- arch/powerpc/include/asm/ps3fb.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/include/asm/ps3fb.h b/arch/powerpc/include/asm/ps3fb.h index 3f121fe4010..e7233a84968 100644 --- a/arch/powerpc/include/asm/ps3fb.h +++ b/arch/powerpc/include/asm/ps3fb.h @@ -19,6 +19,7 @@ #ifndef _ASM_POWERPC_PS3FB_H_ #define _ASM_POWERPC_PS3FB_H_ +#include #include /* ioctl */ -- GitLab From 1a16bc4590fcc94630571c541c8fef7a0845c2c0 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 11:52:05 +0530 Subject: [PATCH 1076/4982] headers_check fix: powerpc, spu_info.h fix the following 'make headers_check' warning: usr/include/asm-powerpc/spu_info.h:27: found __[us]{8,16,32,64} type without #include Signed-off-by: Jaswinder Singh Rajput --- arch/powerpc/include/asm/spu_info.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/spu_info.h b/arch/powerpc/include/asm/spu_info.h index 3545efbf989..1286c823f0d 100644 --- a/arch/powerpc/include/asm/spu_info.h +++ b/arch/powerpc/include/asm/spu_info.h @@ -23,9 +23,10 @@ #ifndef _SPU_INFO_H #define _SPU_INFO_H +#include + #ifdef __KERNEL__ #include -#include #else struct mfc_cq_sr { __u64 mfc_cq_data0_RW; -- GitLab From 48109870bab7e66f30f933cd218258368024cd9f Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 11:54:05 +0530 Subject: [PATCH 1077/4982] headers_check fix: powerpc, swab.h fix the following 'make headers_check' warning: usr/include/asm-powerpc/swab.h:11: include of is preferred over Signed-off-by: Jaswinder Singh Rajput --- arch/powerpc/include/asm/swab.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/swab.h b/arch/powerpc/include/asm/swab.h index ef824ae4b79..c581e3ef73e 100644 --- a/arch/powerpc/include/asm/swab.h +++ b/arch/powerpc/include/asm/swab.h @@ -8,7 +8,7 @@ * 2 of the License, or (at your option) any later version. */ -#include +#include #include #ifdef __GNUC__ -- GitLab From 1ff8f739c7cc4eaa89b6ba986494f458ff7bdbef Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 31 Jan 2009 12:02:14 +0530 Subject: [PATCH 1078/4982] headers_check fix: xtensa, swab.h fix the following 'make headers_check' warnings: usr/include/asm-xtensa/swab.h:14: include of is preferred over usr/include/asm-xtensa/swab.h:19: found __[us]{8,16,32,64} type without #include Signed-off-by: Jaswinder Singh Rajput --- arch/xtensa/include/asm/swab.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/xtensa/include/asm/swab.h b/arch/xtensa/include/asm/swab.h index f50b697eb60..226a3916231 100644 --- a/arch/xtensa/include/asm/swab.h +++ b/arch/xtensa/include/asm/swab.h @@ -11,7 +11,7 @@ #ifndef _XTENSA_SWAB_H #define _XTENSA_SWAB_H -#include +#include #include #define __SWAB_64_THRU_32__ -- GitLab From 61307ed85dbf0ee232e354721a5a0a2011da7996 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Tue, 27 Jan 2009 06:51:09 +0000 Subject: [PATCH 1079/4982] smsc911x: add support for platform-specific irq flags this patch adds support for the platform_device's resources to indicate additional flags to use when registering the irq, for example IORESOURCE_IRQ_LOWLEVEL (which corresponds to IRQF_TRIGGER_LOW). These should be set in the irq resource flags field. Signed-off-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/smsc911x.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index ae4c74b5182..d273a0720ef 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1886,9 +1886,9 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) struct net_device *dev; struct smsc911x_data *pdata; struct smsc911x_platform_config *config = pdev->dev.platform_data; - struct resource *res; + struct resource *res, *irq_res; unsigned int intcfg = 0; - int res_size; + int res_size, irq_flags; int retval; DECLARE_MAC_BUF(mac); @@ -1913,6 +1913,14 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) } res_size = res->end - res->start; + irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!irq_res) { + pr_warning("%s: Could not allocate irq resource.\n", + SMSC_CHIPNAME); + retval = -ENODEV; + goto out_0; + } + if (!request_mem_region(res->start, res_size, SMSC_CHIPNAME)) { retval = -EBUSY; goto out_0; @@ -1929,7 +1937,8 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) pdata = netdev_priv(dev); - dev->irq = platform_get_irq(pdev, 0); + dev->irq = irq_res->start; + irq_flags = irq_res->flags & IRQF_TRIGGER_MASK; pdata->ioaddr = ioremap_nocache(res->start, res_size); /* copy config parameters across to pdata */ @@ -1962,8 +1971,8 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) smsc911x_reg_write(pdata, INT_EN, 0); smsc911x_reg_write(pdata, INT_STS, 0xFFFFFFFF); - retval = request_irq(dev->irq, smsc911x_irqhandler, IRQF_DISABLED, - dev->name, dev); + retval = request_irq(dev->irq, smsc911x_irqhandler, + irq_flags | IRQF_DISABLED, dev->name, dev); if (retval) { SMSC_WARNING(PROBE, "Unable to claim requested irq: %d", dev->irq); -- GitLab From e81259b4f7c69a71d92216ba551731fb7027bcbe Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Tue, 27 Jan 2009 06:51:10 +0000 Subject: [PATCH 1080/4982] smsc911x: register isr as IRQF_SHARED The isr supports shared operation, so register it with the IRQF_SHARED flag to indicate this. This patch also removes the IRQF_DISABLED flag. This driver doesn't need it, and IRQF_DISABLED isn't guaranteed when using shared interrupts. Signed-off-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/smsc911x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index d273a0720ef..6aa2b165de6 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1972,7 +1972,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) smsc911x_reg_write(pdata, INT_STS, 0xFFFFFFFF); retval = request_irq(dev->irq, smsc911x_irqhandler, - irq_flags | IRQF_DISABLED, dev->name, dev); + irq_flags | IRQF_SHARED, dev->name, dev); if (retval) { SMSC_WARNING(PROBE, "Unable to claim requested irq: %d", dev->irq); -- GitLab From d23f028a4ddce8b783c212bfe911d1d307ff3617 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Tue, 27 Jan 2009 06:51:11 +0000 Subject: [PATCH 1081/4982] smsc911x: add external phy detection overrides On LAN9115/LAN9117/LAN9215/LAN9217, external phys are supported. These are usually indicated by a hardware strap which sets an "external PHY detected" bit in the HW_CFG register. In some cases it is desirable to override this hardware strap and force use of either the internal phy or an external PHY. This patch adds SMSC911X_FORCE_INTERNAL_PHY and SMSC911X_FORCE_EXTERNAL_PHY flags so a platform can indicate this preference via its platform_data. Signed-off-by: Steve Glendinning Acked-by: Sascha Hauer Tested-by: Sascha Hauer Signed-off-by: David S. Miller --- drivers/net/smsc911x.c | 75 ++++++++++++++++++++-------------------- include/linux/smsc911x.h | 2 ++ 2 files changed, 40 insertions(+), 37 deletions(-) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 6aa2b165de6..27d2d7c4551 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -368,48 +368,53 @@ out: return reg; } -/* Autodetects and initialises external phy for SMSC9115 and SMSC9117 flavors. - * If something goes wrong, returns -ENODEV to revert back to internal phy. - * Performed at initialisation only, so interrupts are enabled */ -static int smsc911x_phy_initialise_external(struct smsc911x_data *pdata) +/* Switch to external phy. Assumes tx and rx are stopped. */ +static void smsc911x_phy_enable_external(struct smsc911x_data *pdata) { unsigned int hwcfg = smsc911x_reg_read(pdata, HW_CFG); - /* External phy is requested, supported, and detected */ - if (hwcfg & HW_CFG_EXT_PHY_DET_) { + /* Disable phy clocks to the MAC */ + hwcfg &= (~HW_CFG_PHY_CLK_SEL_); + hwcfg |= HW_CFG_PHY_CLK_SEL_CLK_DIS_; + smsc911x_reg_write(pdata, HW_CFG, hwcfg); + udelay(10); /* Enough time for clocks to stop */ - /* Switch to external phy. Assuming tx and rx are stopped - * because smsc911x_phy_initialise is called before - * smsc911x_rx_initialise and tx_initialise. */ + /* Switch to external phy */ + hwcfg |= HW_CFG_EXT_PHY_EN_; + smsc911x_reg_write(pdata, HW_CFG, hwcfg); - /* Disable phy clocks to the MAC */ - hwcfg &= (~HW_CFG_PHY_CLK_SEL_); - hwcfg |= HW_CFG_PHY_CLK_SEL_CLK_DIS_; - smsc911x_reg_write(pdata, HW_CFG, hwcfg); - udelay(10); /* Enough time for clocks to stop */ + /* Enable phy clocks to the MAC */ + hwcfg &= (~HW_CFG_PHY_CLK_SEL_); + hwcfg |= HW_CFG_PHY_CLK_SEL_EXT_PHY_; + smsc911x_reg_write(pdata, HW_CFG, hwcfg); + udelay(10); /* Enough time for clocks to restart */ - /* Switch to external phy */ - hwcfg |= HW_CFG_EXT_PHY_EN_; - smsc911x_reg_write(pdata, HW_CFG, hwcfg); - - /* Enable phy clocks to the MAC */ - hwcfg &= (~HW_CFG_PHY_CLK_SEL_); - hwcfg |= HW_CFG_PHY_CLK_SEL_EXT_PHY_; - smsc911x_reg_write(pdata, HW_CFG, hwcfg); - udelay(10); /* Enough time for clocks to restart */ + hwcfg |= HW_CFG_SMI_SEL_; + smsc911x_reg_write(pdata, HW_CFG, hwcfg); +} - hwcfg |= HW_CFG_SMI_SEL_; - smsc911x_reg_write(pdata, HW_CFG, hwcfg); +/* Autodetects and enables external phy if present on supported chips. + * autodetection can be overridden by specifying SMSC911X_FORCE_INTERNAL_PHY + * or SMSC911X_FORCE_EXTERNAL_PHY in the platform_data flags. */ +static void smsc911x_phy_initialise_external(struct smsc911x_data *pdata) +{ + unsigned int hwcfg = smsc911x_reg_read(pdata, HW_CFG); - SMSC_TRACE(HW, "Successfully switched to external PHY"); + if (pdata->config.flags & SMSC911X_FORCE_INTERNAL_PHY) { + SMSC_TRACE(HW, "Forcing internal PHY"); + pdata->using_extphy = 0; + } else if (pdata->config.flags & SMSC911X_FORCE_EXTERNAL_PHY) { + SMSC_TRACE(HW, "Forcing external PHY"); + smsc911x_phy_enable_external(pdata); + pdata->using_extphy = 1; + } else if (hwcfg & HW_CFG_EXT_PHY_DET_) { + SMSC_TRACE(HW, "HW_CFG EXT_PHY_DET set, using external PHY"); + smsc911x_phy_enable_external(pdata); pdata->using_extphy = 1; } else { - SMSC_WARNING(HW, "No external PHY detected, " - "Using internal PHY instead."); - /* Use internal phy */ - return -ENODEV; + SMSC_TRACE(HW, "HW_CFG EXT_PHY_DET clear, using internal PHY"); + pdata->using_extphy = 0; } - return 0; } /* Fetches a tx status out of the status fifo */ @@ -825,22 +830,18 @@ static int __devinit smsc911x_mii_init(struct platform_device *pdev, pdata->mii_bus->parent = &pdev->dev; - pdata->using_extphy = 0; - switch (pdata->idrev & 0xFFFF0000) { case 0x01170000: case 0x01150000: case 0x117A0000: case 0x115A0000: /* External PHY supported, try to autodetect */ - if (smsc911x_phy_initialise_external(pdata) < 0) { - SMSC_TRACE(HW, "No external PHY detected, " - "using internal PHY"); - } + smsc911x_phy_initialise_external(pdata); break; default: SMSC_TRACE(HW, "External PHY is not supported, " "using internal PHY"); + pdata->using_extphy = 0; break; } diff --git a/include/linux/smsc911x.h b/include/linux/smsc911x.h index 1cbf0313add..170c76b8f7a 100644 --- a/include/linux/smsc911x.h +++ b/include/linux/smsc911x.h @@ -43,5 +43,7 @@ struct smsc911x_platform_config { /* Constants for flags */ #define SMSC911X_USE_16BIT (BIT(0)) #define SMSC911X_USE_32BIT (BIT(1)) +#define SMSC911X_FORCE_INTERNAL_PHY (BIT(2)) +#define SMSC911X_FORCE_EXTERNAL_PHY (BIT(3)) #endif /* __LINUX_SMSC911X_H__ */ -- GitLab From 31f4574774e98aa275aeeee94f41ce042285ed8e Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Tue, 27 Jan 2009 06:51:12 +0000 Subject: [PATCH 1082/4982] smsc911x: allow mac address to be saved before device reset Some platforms (for example pcm037) do not have an EEPROM fitted, instead storing their mac address somewhere else. The bootloader fetches this and configures the ethernet adapter before the kernel is started. This patch allows a platform to indicate to the driver via the SMSC911X_SAVE_MAC_ADDRESS flag that the mac address has already been configured via such a mechanism, and should be saved before resetting the chip. Signed-off-by: Steve Glendinning Acked-by: Sascha Hauer Tested-by: Sascha Hauer Signed-off-by: David S. Miller --- drivers/net/smsc911x.c | 30 ++++++++++++++++++++++-------- include/linux/smsc911x.h | 1 + 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 27d2d7c4551..6e175e5555a 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1742,6 +1742,21 @@ static const struct net_device_ops smsc911x_netdev_ops = { #endif }; +/* copies the current mac address from hardware to dev->dev_addr */ +static void __devinit smsc911x_read_mac_address(struct net_device *dev) +{ + struct smsc911x_data *pdata = netdev_priv(dev); + u32 mac_high16 = smsc911x_mac_read(pdata, ADDRH); + u32 mac_low32 = smsc911x_mac_read(pdata, ADDRL); + + dev->dev_addr[0] = (u8)(mac_low32); + dev->dev_addr[1] = (u8)(mac_low32 >> 8); + dev->dev_addr[2] = (u8)(mac_low32 >> 16); + dev->dev_addr[3] = (u8)(mac_low32 >> 24); + dev->dev_addr[4] = (u8)(mac_high16); + dev->dev_addr[5] = (u8)(mac_high16 >> 8); +} + /* Initializing private device structures, only called from probe */ static int __devinit smsc911x_init(struct net_device *dev) { @@ -1829,6 +1844,12 @@ static int __devinit smsc911x_init(struct net_device *dev) SMSC_WARNING(PROBE, "This driver is not intended for this chip revision"); + /* workaround for platforms without an eeprom, where the mac address + * is stored elsewhere and set by the bootloader. This saves the + * mac address before resetting the device */ + if (pdata->config.flags & SMSC911X_SAVE_MAC_ADDRESS) + smsc911x_read_mac_address(dev); + /* Reset the LAN911x */ if (smsc911x_soft_reset(pdata)) return -ENODEV; @@ -2009,14 +2030,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) } else { /* Try reading mac address from device. if EEPROM is present * it will already have been set */ - u32 mac_high16 = smsc911x_mac_read(pdata, ADDRH); - u32 mac_low32 = smsc911x_mac_read(pdata, ADDRL); - dev->dev_addr[0] = (u8)(mac_low32); - dev->dev_addr[1] = (u8)(mac_low32 >> 8); - dev->dev_addr[2] = (u8)(mac_low32 >> 16); - dev->dev_addr[3] = (u8)(mac_low32 >> 24); - dev->dev_addr[4] = (u8)(mac_high16); - dev->dev_addr[5] = (u8)(mac_high16 >> 8); + smsc911x_read_mac_address(dev); if (is_valid_ether_addr(dev->dev_addr)) { /* eeprom values are valid so use them */ diff --git a/include/linux/smsc911x.h b/include/linux/smsc911x.h index 170c76b8f7a..b32725075d7 100644 --- a/include/linux/smsc911x.h +++ b/include/linux/smsc911x.h @@ -45,5 +45,6 @@ struct smsc911x_platform_config { #define SMSC911X_USE_32BIT (BIT(1)) #define SMSC911X_FORCE_INTERNAL_PHY (BIT(2)) #define SMSC911X_FORCE_EXTERNAL_PHY (BIT(3)) +#define SMSC911X_SAVE_MAC_ADDRESS (BIT(4)) #endif /* __LINUX_SMSC911X_H__ */ -- GitLab From 4fb669948116d928ae44262ab7743732c574630d Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Sun, 1 Feb 2009 00:41:42 -0800 Subject: [PATCH 1083/4982] net: Optimize memory usage when splicing from sockets. The recent fix of data corruption when splicing from sockets uses memory very inefficiently allocating a new page to copy each chunk of linear part of skb. This patch uses the same page until it's full (almost) by caching the page in sk_sndmsg_page field. With changes from David S. Miller Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- net/core/skbuff.c | 47 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index f20e758fe46..e55d1ef5690 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1333,14 +1333,39 @@ static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i) put_page(spd->pages[i]); } -static inline struct page *linear_to_page(struct page *page, unsigned int len, - unsigned int offset) -{ - struct page *p = alloc_pages(GFP_KERNEL, 0); +static inline struct page *linear_to_page(struct page *page, unsigned int *len, + unsigned int *offset, + struct sk_buff *skb) +{ + struct sock *sk = skb->sk; + struct page *p = sk->sk_sndmsg_page; + unsigned int off; + + if (!p) { +new_page: + p = sk->sk_sndmsg_page = alloc_pages(sk->sk_allocation, 0); + if (!p) + return NULL; - if (!p) - return NULL; - memcpy(page_address(p) + offset, page_address(page) + offset, len); + off = sk->sk_sndmsg_off = 0; + /* hold one ref to this page until it's full */ + } else { + unsigned int mlen; + + off = sk->sk_sndmsg_off; + mlen = PAGE_SIZE - off; + if (mlen < 64 && mlen < *len) { + put_page(p); + goto new_page; + } + + *len = min_t(unsigned int, *len, mlen); + } + + memcpy(page_address(p) + off, page_address(page) + *offset, *len); + sk->sk_sndmsg_off += *len; + *offset = off; + get_page(p); return p; } @@ -1349,21 +1374,21 @@ static inline struct page *linear_to_page(struct page *page, unsigned int len, * Fill page/offset/length into spd, if it can hold more pages. */ static inline int spd_fill_page(struct splice_pipe_desc *spd, struct page *page, - unsigned int len, unsigned int offset, + unsigned int *len, unsigned int offset, struct sk_buff *skb, int linear) { if (unlikely(spd->nr_pages == PIPE_BUFFERS)) return 1; if (linear) { - page = linear_to_page(page, len, offset); + page = linear_to_page(page, len, &offset, skb); if (!page) return 1; } else get_page(page); spd->pages[spd->nr_pages] = page; - spd->partial[spd->nr_pages].len = len; + spd->partial[spd->nr_pages].len = *len; spd->partial[spd->nr_pages].offset = offset; spd->nr_pages++; @@ -1405,7 +1430,7 @@ static inline int __splice_segment(struct page *page, unsigned int poff, /* the linear region may spread across several pages */ flen = min_t(unsigned int, flen, PAGE_SIZE - poff); - if (spd_fill_page(spd, page, flen, poff, skb, linear)) + if (spd_fill_page(spd, page, &flen, poff, skb, linear)) return 1; __segment_seek(&page, &poff, &plen, flen); -- GitLab From ee437770c42088b9b653e8b3bf28a61fa647f84e Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Sun, 1 Feb 2009 00:43:54 -0800 Subject: [PATCH 1084/4982] wimax: replace uses of __constant_{endian} Base versions handle constant folding now. Signed-off-by: Harvey Harrison Acked-by: Inaky Perez-Gonzalez Signed-off-by: David S. Miller --- drivers/net/wimax/i2400m/fw.c | 12 ++++++------ drivers/net/wimax/i2400m/i2400m.h | 16 ++++++++-------- drivers/net/wimax/i2400m/netdev.c | 2 +- drivers/net/wimax/i2400m/sdio.c | 16 ++++++++-------- drivers/net/wimax/i2400m/usb.c | 16 ++++++++-------- 5 files changed, 31 insertions(+), 31 deletions(-) diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c index 1d8271f34c3..ecd0cfaefdc 100644 --- a/drivers/net/wimax/i2400m/fw.c +++ b/drivers/net/wimax/i2400m/fw.c @@ -140,10 +140,10 @@ static const __le32 i2400m_ACK_BARKER[4] = { - __constant_cpu_to_le32(I2400M_ACK_BARKER), - __constant_cpu_to_le32(I2400M_ACK_BARKER), - __constant_cpu_to_le32(I2400M_ACK_BARKER), - __constant_cpu_to_le32(I2400M_ACK_BARKER) + cpu_to_le32(I2400M_ACK_BARKER), + cpu_to_le32(I2400M_ACK_BARKER), + cpu_to_le32(I2400M_ACK_BARKER), + cpu_to_le32(I2400M_ACK_BARKER) }; @@ -771,8 +771,8 @@ static int i2400m_dnload_init_nonsigned(struct i2400m *i2400m) { #define POKE(a, d) { \ - .address = __constant_cpu_to_le32(a), \ - .data = __constant_cpu_to_le32(d) \ + .address = cpu_to_le32(a), \ + .data = cpu_to_le32(d) \ } static const struct { __le32 address; diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h index 067c871cc22..236f19ea4c8 100644 --- a/drivers/net/wimax/i2400m/i2400m.h +++ b/drivers/net/wimax/i2400m/i2400m.h @@ -664,17 +664,17 @@ extern struct i2400m_msg_hdr *i2400m_tx_msg_get(struct i2400m *, size_t *); extern void i2400m_tx_msg_sent(struct i2400m *); static const __le32 i2400m_NBOOT_BARKER[4] = { - __constant_cpu_to_le32(I2400M_NBOOT_BARKER), - __constant_cpu_to_le32(I2400M_NBOOT_BARKER), - __constant_cpu_to_le32(I2400M_NBOOT_BARKER), - __constant_cpu_to_le32(I2400M_NBOOT_BARKER) + cpu_to_le32(I2400M_NBOOT_BARKER), + cpu_to_le32(I2400M_NBOOT_BARKER), + cpu_to_le32(I2400M_NBOOT_BARKER), + cpu_to_le32(I2400M_NBOOT_BARKER) }; static const __le32 i2400m_SBOOT_BARKER[4] = { - __constant_cpu_to_le32(I2400M_SBOOT_BARKER), - __constant_cpu_to_le32(I2400M_SBOOT_BARKER), - __constant_cpu_to_le32(I2400M_SBOOT_BARKER), - __constant_cpu_to_le32(I2400M_SBOOT_BARKER) + cpu_to_le32(I2400M_SBOOT_BARKER), + cpu_to_le32(I2400M_SBOOT_BARKER), + cpu_to_le32(I2400M_SBOOT_BARKER), + cpu_to_le32(I2400M_SBOOT_BARKER) }; diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c index 57159e4bbfe..be8be4d0709 100644 --- a/drivers/net/wimax/i2400m/netdev.c +++ b/drivers/net/wimax/i2400m/netdev.c @@ -419,7 +419,7 @@ void i2400m_rx_fake_eth_header(struct net_device *net_dev, memcpy(eth_hdr->h_dest, net_dev->dev_addr, sizeof(eth_hdr->h_dest)); memset(eth_hdr->h_source, 0, sizeof(eth_hdr->h_dest)); - eth_hdr->h_proto = __constant_cpu_to_be16(ETH_P_IP); + eth_hdr->h_proto = cpu_to_be16(ETH_P_IP); } diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c index 1bfa283bbd8..123a5f8db6a 100644 --- a/drivers/net/wimax/i2400m/sdio.c +++ b/drivers/net/wimax/i2400m/sdio.c @@ -255,16 +255,16 @@ int i2400ms_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) container_of(i2400m, struct i2400ms, i2400m); struct device *dev = i2400m_dev(i2400m); static const __le32 i2400m_WARM_BOOT_BARKER[4] = { - __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER), - __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER), - __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER), - __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER), + cpu_to_le32(I2400M_WARM_RESET_BARKER), + cpu_to_le32(I2400M_WARM_RESET_BARKER), + cpu_to_le32(I2400M_WARM_RESET_BARKER), + cpu_to_le32(I2400M_WARM_RESET_BARKER), }; static const __le32 i2400m_COLD_BOOT_BARKER[4] = { - __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER), - __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER), - __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER), - __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER), + cpu_to_le32(I2400M_COLD_RESET_BARKER), + cpu_to_le32(I2400M_COLD_RESET_BARKER), + cpu_to_le32(I2400M_COLD_RESET_BARKER), + cpu_to_le32(I2400M_COLD_RESET_BARKER), }; if (rt == I2400M_RT_WARM) diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c index c6d93465c7e..7c28610da6f 100644 --- a/drivers/net/wimax/i2400m/usb.c +++ b/drivers/net/wimax/i2400m/usb.c @@ -211,16 +211,16 @@ int i2400mu_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) container_of(i2400m, struct i2400mu, i2400m); struct device *dev = i2400m_dev(i2400m); static const __le32 i2400m_WARM_BOOT_BARKER[4] = { - __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER), - __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER), - __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER), - __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER), + cpu_to_le32(I2400M_WARM_RESET_BARKER), + cpu_to_le32(I2400M_WARM_RESET_BARKER), + cpu_to_le32(I2400M_WARM_RESET_BARKER), + cpu_to_le32(I2400M_WARM_RESET_BARKER), }; static const __le32 i2400m_COLD_BOOT_BARKER[4] = { - __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER), - __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER), - __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER), - __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER), + cpu_to_le32(I2400M_COLD_RESET_BARKER), + cpu_to_le32(I2400M_COLD_RESET_BARKER), + cpu_to_le32(I2400M_COLD_RESET_BARKER), + cpu_to_le32(I2400M_COLD_RESET_BARKER), }; d_fnstart(3, dev, "(i2400m %p rt %u)\n", i2400m, rt); -- GitLab From 09640e6365c679b5642b1c41b6d7078f51689ddf Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Sun, 1 Feb 2009 00:45:17 -0800 Subject: [PATCH 1085/4982] net: replace uses of __constant_{endian} Base versions handle constant folding now. Signed-off-by: Harvey Harrison Signed-off-by: David S. Miller --- drivers/net/arcnet/arc-rawmode.c | 2 +- drivers/net/arcnet/capmode.c | 4 ++-- drivers/net/bonding/bond_3ad.h | 2 +- drivers/net/bonding/bond_alb.c | 4 ++-- drivers/net/e1000/e1000_main.c | 4 ++-- drivers/net/e1000e/netdev.c | 4 ++-- drivers/net/enic/enic_main.c | 4 ++-- drivers/net/hamachi.c | 8 ++++---- drivers/net/hamradio/bpqether.c | 2 +- drivers/net/igb/igb_main.c | 4 ++-- drivers/net/ixgbe/ixgbe_main.c | 4 ++-- drivers/net/myri_sbus.c | 2 +- drivers/net/netxen/netxen_nic_main.c | 8 ++++---- drivers/net/niu.c | 4 ++-- drivers/net/pppoe.c | 8 ++++---- drivers/net/ps3_gelic_net.c | 2 +- drivers/net/sfc/bitfield.h | 4 ++-- drivers/net/tun.c | 2 +- drivers/net/usb/hso.c | 3 +-- drivers/net/via-velocity.h | 6 +++--- drivers/net/wan/hdlc.c | 2 +- drivers/net/wan/hdlc_cisco.c | 16 ++++++++-------- drivers/net/wan/hdlc_fr.c | 16 ++++++++-------- drivers/net/wan/hdlc_ppp.c | 4 ++-- drivers/net/wan/hdlc_raw.c | 2 +- drivers/net/wan/lapbether.c | 2 +- net/802/psnap.c | 2 +- net/8021q/vlan.c | 2 +- net/appletalk/ddp.c | 4 ++-- net/ax25/af_ax25.c | 2 +- net/bridge/br_netfilter.c | 2 +- net/can/af_can.c | 2 +- net/decnet/af_decnet.c | 2 +- net/decnet/dn_route.c | 2 +- net/dsa/mv88e6123_61_65.c | 2 +- net/dsa/mv88e6131.c | 2 +- net/dsa/tag_dsa.c | 2 +- net/dsa/tag_edsa.c | 2 +- net/dsa/tag_trailer.c | 2 +- net/econet/af_econet.c | 2 +- net/ipv4/af_inet.c | 2 +- net/ipv4/arp.c | 2 +- net/ipv4/ipconfig.c | 8 ++++---- net/ipv4/netfilter/nf_nat_snmp_basic.c | 4 ++-- net/ipv4/route.c | 4 ++-- net/ipv4/xfrm4_policy.c | 2 +- net/ipv6/af_inet6.c | 2 +- net/ipv6/route.c | 4 ++-- net/ipv6/xfrm6_policy.c | 2 +- net/ipx/af_ipx.c | 4 ++-- net/irda/irmod.c | 2 +- net/llc/llc_core.c | 4 ++-- net/netfilter/ipvs/ip_vs_sync.c | 4 ++-- net/netfilter/nf_conntrack_amanda.c | 4 ++-- net/netfilter/nf_conntrack_h323_main.c | 8 ++++---- net/netfilter/nf_conntrack_netbios_ns.c | 2 +- net/netfilter/nf_conntrack_pptp.c | 2 +- net/phonet/af_phonet.c | 2 +- net/sctp/output.c | 2 +- net/sctp/sm_make_chunk.c | 4 ++-- net/x25/af_x25.c | 2 +- 61 files changed, 111 insertions(+), 112 deletions(-) diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c index da017cbb5f6..646dfc5f50c 100644 --- a/drivers/net/arcnet/arc-rawmode.c +++ b/drivers/net/arcnet/arc-rawmode.c @@ -122,7 +122,7 @@ static void rx(struct net_device *dev, int bufnum, BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); - skb->protocol = __constant_htons(ETH_P_ARCNET); + skb->protocol = cpu_to_be16(ETH_P_ARCNET); ; netif_rx(skb); } diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index 1613929ff30..083e21094b2 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -148,7 +148,7 @@ static void rx(struct net_device *dev, int bufnum, BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); - skb->protocol = __constant_htons(ETH_P_ARCNET); + skb->protocol = cpu_to_be16(ETH_P_ARCNET); ; netif_rx(skb); } @@ -282,7 +282,7 @@ static int ack_tx(struct net_device *dev, int acked) BUGMSG(D_PROTO, "Ackknowledge for cap packet %x.\n", *((int*)&ackpkt->soft.cap.cookie[0])); - ackskb->protocol = __constant_htons(ETH_P_ARCNET); + ackskb->protocol = cpu_to_be16(ETH_P_ARCNET); BUGLVL(D_SKB) arcnet_dump_skb(dev, ackskb, "ack_tx_recv"); netif_rx(ackskb); diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h index 8a83eb283c2..a306230381c 100644 --- a/drivers/net/bonding/bond_3ad.h +++ b/drivers/net/bonding/bond_3ad.h @@ -29,7 +29,7 @@ // General definitions #define BOND_ETH_P_LACPDU 0x8809 -#define PKT_TYPE_LACPDU __constant_htons(BOND_ETH_P_LACPDU) +#define PKT_TYPE_LACPDU cpu_to_be16(BOND_ETH_P_LACPDU) #define AD_TIMER_INTERVAL 100 /*msec*/ #define MULTICAST_LACPDU_ADDR {0x01, 0x80, 0xC2, 0x00, 0x00, 0x02} diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 27fb7f5c21c..409b1407427 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -822,7 +822,7 @@ static int rlb_initialize(struct bonding *bond) _unlock_rx_hashtbl(bond); /*initialize packet type*/ - pk_type->type = __constant_htons(ETH_P_ARP); + pk_type->type = cpu_to_be16(ETH_P_ARP); pk_type->dev = NULL; pk_type->func = rlb_arp_recv; @@ -892,7 +892,7 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[]) memset(&pkt, 0, size); memcpy(pkt.mac_dst, mac_addr, ETH_ALEN); memcpy(pkt.mac_src, mac_addr, ETH_ALEN); - pkt.type = __constant_htons(ETH_P_LOOP); + pkt.type = cpu_to_be16(ETH_P_LOOP); for (i = 0; i < MAX_LP_BURST; i++) { struct sk_buff *skb; diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index c4a303023b3..40db34deebd 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2860,11 +2860,11 @@ static bool e1000_tx_csum(struct e1000_adapter *adapter, return false; switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case cpu_to_be16(ETH_P_IP): if (ip_hdr(skb)->protocol == IPPROTO_TCP) cmd_len |= E1000_TXD_CMD_TCP; break; - case __constant_htons(ETH_P_IPV6): + case cpu_to_be16(ETH_P_IPV6): /* XXX not handling all IPV6 headers */ if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) cmd_len |= E1000_TXD_CMD_TCP; diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index e04b392c9a5..c425b19e336 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -3770,11 +3770,11 @@ static bool e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb) return 0; switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case cpu_to_be16(ETH_P_IP): if (ip_hdr(skb)->protocol == IPPROTO_TCP) cmd_len |= E1000_TXD_CMD_TCP; break; - case __constant_htons(ETH_P_IPV6): + case cpu_to_be16(ETH_P_IPV6): /* XXX not handling all IPV6 headers */ if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) cmd_len |= E1000_TXD_CMD_TCP; diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 4617956821c..5dd11563553 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -570,11 +570,11 @@ static inline void enic_queue_wq_skb_tso(struct enic *enic, * to each TCP segment resulting from the TSO. */ - if (skb->protocol == __constant_htons(ETH_P_IP)) { + if (skb->protocol == cpu_to_be16(ETH_P_IP)) { ip_hdr(skb)->check = 0; tcp_hdr(skb)->check = ~csum_tcpudp_magic(ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, 0, IPPROTO_TCP, 0); - } else if (skb->protocol == __constant_htons(ETH_P_IPV6)) { + } else if (skb->protocol == cpu_to_be16(ETH_P_IPV6)) { tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, 0, IPPROTO_TCP, 0); } diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index 7e8b3c59a7d..455641f8677 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -1244,7 +1244,7 @@ do { \ csum_add(sum, (ih)->saddr & 0xffff); \ csum_add(sum, (ih)->daddr >> 16); \ csum_add(sum, (ih)->daddr & 0xffff); \ - csum_add(sum, __constant_htons(IPPROTO_UDP)); \ + csum_add(sum, cpu_to_be16(IPPROTO_UDP)); \ csum_add(sum, (uh)->len); \ } while (0) @@ -1255,7 +1255,7 @@ do { \ csum_add(sum, (ih)->saddr & 0xffff); \ csum_add(sum, (ih)->daddr >> 16); \ csum_add(sum, (ih)->daddr & 0xffff); \ - csum_add(sum, __constant_htons(IPPROTO_TCP)); \ + csum_add(sum, cpu_to_be16(IPPROTO_TCP)); \ csum_add(sum, htons(len)); \ } while (0) #endif @@ -1296,7 +1296,7 @@ static int hamachi_start_xmit(struct sk_buff *skb, struct net_device *dev) /* tack on checksum tag */ u32 tagval = 0; struct ethhdr *eh = (struct ethhdr *)skb->data; - if (eh->h_proto == __constant_htons(ETH_P_IP)) { + if (eh->h_proto == cpu_to_be16(ETH_P_IP)) { struct iphdr *ih = (struct iphdr *)((char *)eh + ETH_HLEN); if (ih->protocol == IPPROTO_UDP) { struct udphdr *uh @@ -1605,7 +1605,7 @@ static int hamachi_rx(struct net_device *dev) */ if (ntohs(ih->tot_len) >= 46){ /* don't worry about frags */ - if (!(ih->frag_off & __constant_htons(IP_MF|IP_OFFSET))) { + if (!(ih->frag_off & cpu_to_be16(IP_MF|IP_OFFSET))) { u32 inv = *(u32 *) &buf_addr[data_size - 16]; u32 *p = (u32 *) &buf_addr[data_size - 20]; register u32 crc, p_r, p_r1; diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index 1f65d1edf13..2c619bc99ae 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c @@ -97,7 +97,7 @@ static int bpq_rcv(struct sk_buff *, struct net_device *, struct packet_type *, static int bpq_device_event(struct notifier_block *, unsigned long, void *); static struct packet_type bpq_packet_type = { - .type = __constant_htons(ETH_P_BPQ), + .type = cpu_to_be16(ETH_P_BPQ), .func = bpq_rcv, }; diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index bd166803671..cd794bac8b8 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2749,12 +2749,12 @@ static inline bool igb_tx_csum_adv(struct igb_adapter *adapter, if (skb->ip_summed == CHECKSUM_PARTIAL) { switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case cpu_to_be16(ETH_P_IP): tu_cmd |= E1000_ADVTXD_TUCMD_IPV4; if (ip_hdr(skb)->protocol == IPPROTO_TCP) tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP; break; - case __constant_htons(ETH_P_IPV6): + case cpu_to_be16(ETH_P_IPV6): /* XXX what about other V6 headers?? */ if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP; diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index fe4a4d17c4b..88615f69976 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3567,13 +3567,13 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter, if (skb->ip_summed == CHECKSUM_PARTIAL) { switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case cpu_to_be16(ETH_P_IP): type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4; if (ip_hdr(skb)->protocol == IPPROTO_TCP) type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP; break; - case __constant_htons(ETH_P_IPV6): + case cpu_to_be16(ETH_P_IPV6): /* XXX what about other V6 headers?? */ if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) type_tucmd_mlhl |= diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index 899ed065a14..88b52883ace 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c @@ -748,7 +748,7 @@ static int myri_rebuild_header(struct sk_buff *skb) switch (eth->h_proto) { #ifdef CONFIG_INET - case __constant_htons(ETH_P_IP): + case cpu_to_be16(ETH_P_IP): return arp_find(eth->h_dest, skb); #endif diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index cc06cc5429f..ada462e94c9 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -1170,7 +1170,7 @@ static bool netxen_tso_check(struct net_device *netdev, __be16 protocol = skb->protocol; u16 flags = 0; - if (protocol == __constant_htons(ETH_P_8021Q)) { + if (protocol == cpu_to_be16(ETH_P_8021Q)) { struct vlan_ethhdr *vh = (struct vlan_ethhdr *)skb->data; protocol = vh->h_vlan_encapsulated_proto; flags = FLAGS_VLAN_TAGGED; @@ -1183,21 +1183,21 @@ static bool netxen_tso_check(struct net_device *netdev, desc->total_hdr_length = skb_transport_offset(skb) + tcp_hdrlen(skb); - opcode = (protocol == __constant_htons(ETH_P_IPV6)) ? + opcode = (protocol == cpu_to_be16(ETH_P_IPV6)) ? TX_TCP_LSO6 : TX_TCP_LSO; tso = true; } else if (skb->ip_summed == CHECKSUM_PARTIAL) { u8 l4proto; - if (protocol == __constant_htons(ETH_P_IP)) { + if (protocol == cpu_to_be16(ETH_P_IP)) { l4proto = ip_hdr(skb)->protocol; if (l4proto == IPPROTO_TCP) opcode = TX_TCP_PKT; else if(l4proto == IPPROTO_UDP) opcode = TX_UDP_PKT; - } else if (protocol == __constant_htons(ETH_P_IPV6)) { + } else if (protocol == cpu_to_be16(ETH_P_IPV6)) { l4proto = ipv6_hdr(skb)->nexthdr; if (l4proto == IPPROTO_TCP) diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 2346ca6bf5b..c26325ded20 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -6447,11 +6447,11 @@ static u64 niu_compute_tx_flags(struct sk_buff *skb, struct ethhdr *ehdr, ipv6 = ihl = 0; switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case cpu_to_be16(ETH_P_IP): ip_proto = ip_hdr(skb)->protocol; ihl = ip_hdr(skb)->ihl; break; - case __constant_htons(ETH_P_IPV6): + case cpu_to_be16(ETH_P_IPV6): ip_proto = ipv6_hdr(skb)->nexthdr; ihl = (40 >> 2); ipv6 = 1; diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 074803a78fc..1011fd64108 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -514,12 +514,12 @@ out: } static struct packet_type pppoes_ptype = { - .type = __constant_htons(ETH_P_PPP_SES), + .type = cpu_to_be16(ETH_P_PPP_SES), .func = pppoe_rcv, }; static struct packet_type pppoed_ptype = { - .type = __constant_htons(ETH_P_PPP_DISC), + .type = cpu_to_be16(ETH_P_PPP_DISC), .func = pppoe_disc_rcv, }; @@ -877,7 +877,7 @@ static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock, skb->dev = dev; skb->priority = sk->sk_priority; - skb->protocol = __constant_htons(ETH_P_PPP_SES); + skb->protocol = cpu_to_be16(ETH_P_PPP_SES); ph = (struct pppoe_hdr *)skb_put(skb, total_len + sizeof(struct pppoe_hdr)); start = (char *)&ph->tag[0]; @@ -937,7 +937,7 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb) ph->sid = po->num; ph->length = htons(data_len); - skb->protocol = __constant_htons(ETH_P_PPP_SES); + skb->protocol = cpu_to_be16(ETH_P_PPP_SES); skb->dev = dev; dev_hard_header(skb, dev, ETH_P_PPP_SES, diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c index 06649d0c209..30900b30d53 100644 --- a/drivers/net/ps3_gelic_net.c +++ b/drivers/net/ps3_gelic_net.c @@ -745,7 +745,7 @@ static inline struct sk_buff *gelic_put_vlan_tag(struct sk_buff *skb, /* Move the mac addresses to the top of buffer */ memmove(skb->data, skb->data + VLAN_HLEN, 2 * ETH_ALEN); - veth->h_vlan_proto = __constant_htons(ETH_P_8021Q); + veth->h_vlan_proto = cpu_to_be16(ETH_P_8021Q); veth->h_vlan_TCI = htons(tag); return skb; diff --git a/drivers/net/sfc/bitfield.h b/drivers/net/sfc/bitfield.h index d95c2182801..d54d84c267b 100644 --- a/drivers/net/sfc/bitfield.h +++ b/drivers/net/sfc/bitfield.h @@ -543,7 +543,7 @@ typedef union efx_oword { /* Static initialiser */ #define EFX_OWORD32(a, b, c, d) \ - { .u32 = { __constant_cpu_to_le32(a), __constant_cpu_to_le32(b), \ - __constant_cpu_to_le32(c), __constant_cpu_to_le32(d) } } + { .u32 = { cpu_to_le32(a), cpu_to_le32(b), \ + cpu_to_le32(c), cpu_to_le32(d) } } #endif /* EFX_BITFIELD_H */ diff --git a/drivers/net/tun.c b/drivers/net/tun.c index e9bcbdfe015..457f2d7430c 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -543,7 +543,7 @@ static struct sk_buff *tun_alloc_skb(size_t prepad, size_t len, size_t linear, /* Get packet from user space buffer */ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv, size_t count) { - struct tun_pi pi = { 0, __constant_htons(ETH_P_IP) }; + struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) }; struct sk_buff *skb; size_t len = count, align = 0; struct virtio_net_hdr gso = { 0 }; diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 0d0fa91c025..806cc5da56c 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -934,8 +934,7 @@ static void packetizeRx(struct hso_net *odev, unsigned char *ip_pkt, if (!odev->rx_buf_missing) { /* Packet is complete. Inject into stack. */ /* We have IP packet here */ - odev->skb_rx_buf->protocol = - __constant_htons(ETH_P_IP); + odev->skb_rx_buf->protocol = cpu_to_be16(ETH_P_IP); /* don't check it */ odev->skb_rx_buf->ip_summed = CHECKSUM_UNNECESSARY; diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h index 29a33090d3d..ea43e1832af 100644 --- a/drivers/net/via-velocity.h +++ b/drivers/net/via-velocity.h @@ -183,7 +183,7 @@ struct rdesc1 { }; enum { - RX_INTEN = __constant_cpu_to_le16(0x8000) + RX_INTEN = cpu_to_le16(0x8000) }; struct rx_desc { @@ -210,7 +210,7 @@ struct tdesc1 { } __attribute__ ((__packed__)); enum { - TD_QUEUE = __constant_cpu_to_le16(0x8000) + TD_QUEUE = cpu_to_le16(0x8000) }; struct td_buf { @@ -242,7 +242,7 @@ struct velocity_td_info { enum velocity_owner { OWNED_BY_HOST = 0, - OWNED_BY_NIC = __constant_cpu_to_le16(0x8000) + OWNED_BY_NIC = cpu_to_le16(0x8000) }; diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c index 43da8bd7297..5ce43720555 100644 --- a/drivers/net/wan/hdlc.c +++ b/drivers/net/wan/hdlc.c @@ -349,7 +349,7 @@ EXPORT_SYMBOL(attach_hdlc_protocol); EXPORT_SYMBOL(detach_hdlc_protocol); static struct packet_type hdlc_packet_type = { - .type = __constant_htons(ETH_P_HDLC), + .type = cpu_to_be16(ETH_P_HDLC), .func = hdlc_rcv, }; diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c index af3fd4fead8..cf5fd17ad70 100644 --- a/drivers/net/wan/hdlc_cisco.c +++ b/drivers/net/wan/hdlc_cisco.c @@ -117,7 +117,7 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type, data->type = htonl(type); data->par1 = par1; data->par2 = par2; - data->rel = __constant_htons(0xFFFF); + data->rel = cpu_to_be16(0xFFFF); /* we will need do_div here if 1000 % HZ != 0 */ data->time = htonl((jiffies - INITIAL_JIFFIES) * (1000 / HZ)); @@ -136,20 +136,20 @@ static __be16 cisco_type_trans(struct sk_buff *skb, struct net_device *dev) struct hdlc_header *data = (struct hdlc_header*)skb->data; if (skb->len < sizeof(struct hdlc_header)) - return __constant_htons(ETH_P_HDLC); + return cpu_to_be16(ETH_P_HDLC); if (data->address != CISCO_MULTICAST && data->address != CISCO_UNICAST) - return __constant_htons(ETH_P_HDLC); + return cpu_to_be16(ETH_P_HDLC); switch(data->protocol) { - case __constant_htons(ETH_P_IP): - case __constant_htons(ETH_P_IPX): - case __constant_htons(ETH_P_IPV6): + case cpu_to_be16(ETH_P_IP): + case cpu_to_be16(ETH_P_IPX): + case cpu_to_be16(ETH_P_IPV6): skb_pull(skb, sizeof(struct hdlc_header)); return data->protocol; default: - return __constant_htons(ETH_P_HDLC); + return cpu_to_be16(ETH_P_HDLC); } } @@ -194,7 +194,7 @@ static int cisco_rx(struct sk_buff *skb) case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */ in_dev = dev->ip_ptr; addr = 0; - mask = __constant_htonl(~0); /* is the mask correct? */ + mask = ~cpu_to_be32(0); /* is the mask correct? */ if (in_dev != NULL) { struct in_ifaddr **ifap = &in_dev->ifa_list; diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index 70e57cebc95..80053010109 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c @@ -278,31 +278,31 @@ static int fr_hard_header(struct sk_buff **skb_p, u16 dlci) struct sk_buff *skb = *skb_p; switch (skb->protocol) { - case __constant_htons(NLPID_CCITT_ANSI_LMI): + case cpu_to_be16(NLPID_CCITT_ANSI_LMI): head_len = 4; skb_push(skb, head_len); skb->data[3] = NLPID_CCITT_ANSI_LMI; break; - case __constant_htons(NLPID_CISCO_LMI): + case cpu_to_be16(NLPID_CISCO_LMI): head_len = 4; skb_push(skb, head_len); skb->data[3] = NLPID_CISCO_LMI; break; - case __constant_htons(ETH_P_IP): + case cpu_to_be16(ETH_P_IP): head_len = 4; skb_push(skb, head_len); skb->data[3] = NLPID_IP; break; - case __constant_htons(ETH_P_IPV6): + case cpu_to_be16(ETH_P_IPV6): head_len = 4; skb_push(skb, head_len); skb->data[3] = NLPID_IPV6; break; - case __constant_htons(ETH_P_802_3): + case cpu_to_be16(ETH_P_802_3): head_len = 10; if (skb_headroom(skb) < head_len) { struct sk_buff *skb2 = skb_realloc_headroom(skb, @@ -426,7 +426,7 @@ static int pvc_xmit(struct sk_buff *skb, struct net_device *dev) skb_put(skb, pad); memset(skb->data + len, 0, pad); } - skb->protocol = __constant_htons(ETH_P_802_3); + skb->protocol = cpu_to_be16(ETH_P_802_3); } if (!fr_hard_header(&skb, pvc->dlci)) { dev->stats.tx_bytes += skb->len; @@ -496,10 +496,10 @@ static void fr_lmi_send(struct net_device *dev, int fullrep) memset(skb->data, 0, len); skb_reserve(skb, 4); if (lmi == LMI_CISCO) { - skb->protocol = __constant_htons(NLPID_CISCO_LMI); + skb->protocol = cpu_to_be16(NLPID_CISCO_LMI); fr_hard_header(&skb, LMI_CISCO_DLCI); } else { - skb->protocol = __constant_htons(NLPID_CCITT_ANSI_LMI); + skb->protocol = cpu_to_be16(NLPID_CCITT_ANSI_LMI); fr_hard_header(&skb, LMI_CCITT_ANSI_DLCI); } data = skb_tail_pointer(skb); diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c index 7b8a5eae201..72a7cdab424 100644 --- a/drivers/net/wan/hdlc_ppp.c +++ b/drivers/net/wan/hdlc_ppp.c @@ -150,11 +150,11 @@ static __be16 ppp_type_trans(struct sk_buff *skb, struct net_device *dev) return htons(ETH_P_HDLC); switch (data->protocol) { - case __constant_htons(PID_IP): + case cpu_to_be16(PID_IP): skb_pull(skb, sizeof(struct hdlc_header)); return htons(ETH_P_IP); - case __constant_htons(PID_IPV6): + case cpu_to_be16(PID_IPV6): skb_pull(skb, sizeof(struct hdlc_header)); return htons(ETH_P_IPV6); diff --git a/drivers/net/wan/hdlc_raw.c b/drivers/net/wan/hdlc_raw.c index 6e92c64ebd0..19f51fdd552 100644 --- a/drivers/net/wan/hdlc_raw.c +++ b/drivers/net/wan/hdlc_raw.c @@ -27,7 +27,7 @@ static int raw_ioctl(struct net_device *dev, struct ifreq *ifr); static __be16 raw_type_trans(struct sk_buff *skb, struct net_device *dev) { - return __constant_htons(ETH_P_IP); + return cpu_to_be16(ETH_P_IP); } static struct hdlc_proto proto = { diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c index 5b61b3eef45..da9dcf59de2 100644 --- a/drivers/net/wan/lapbether.c +++ b/drivers/net/wan/lapbether.c @@ -422,7 +422,7 @@ static int lapbeth_device_event(struct notifier_block *this, /* ------------------------------------------------------------------------ */ static struct packet_type lapbeth_packet_type = { - .type = __constant_htons(ETH_P_DEC), + .type = cpu_to_be16(ETH_P_DEC), .func = lapbeth_rcv, }; diff --git a/net/802/psnap.c b/net/802/psnap.c index 70980baeb68..6ed711748f2 100644 --- a/net/802/psnap.c +++ b/net/802/psnap.c @@ -51,7 +51,7 @@ static int snap_rcv(struct sk_buff *skb, struct net_device *dev, int rc = 1; struct datalink_proto *proto; static struct packet_type snap_packet_type = { - .type = __constant_htons(ETH_P_SNAP), + .type = cpu_to_be16(ETH_P_SNAP), }; if (unlikely(!pskb_may_pull(skb, 5))) diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 41e8f65bd3f..4163ea65bf4 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -52,7 +52,7 @@ static const char vlan_copyright[] = "Ben Greear "; static const char vlan_buggyright[] = "David S. Miller "; static struct packet_type vlan_packet_type = { - .type = __constant_htons(ETH_P_8021Q), + .type = cpu_to_be16(ETH_P_8021Q), .func = vlan_skb_recv, /* VLAN receive method */ }; diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 5abce07fb50..510a6782da8 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -1861,12 +1861,12 @@ static struct notifier_block ddp_notifier = { }; static struct packet_type ltalk_packet_type = { - .type = __constant_htons(ETH_P_LOCALTALK), + .type = cpu_to_be16(ETH_P_LOCALTALK), .func = ltalk_rcv, }; static struct packet_type ppptalk_packet_type = { - .type = __constant_htons(ETH_P_PPPTALK), + .type = cpu_to_be16(ETH_P_PPPTALK), .func = atalk_rcv, }; diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 00d9e5e1315..d127fd3ba5c 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1986,7 +1986,7 @@ static const struct proto_ops ax25_proto_ops = { * Called by socket.c on kernel start up */ static struct packet_type ax25_packet_type = { - .type = __constant_htons(ETH_P_AX25), + .type = cpu_to_be16(ETH_P_AX25), .dev = NULL, /* All devices */ .func = ax25_kiss_rcv, }; diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index cf754ace0b7..3953ac4214c 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -107,7 +107,7 @@ static void fake_update_pmtu(struct dst_entry *dst, u32 mtu) static struct dst_ops fake_dst_ops = { .family = AF_INET, - .protocol = __constant_htons(ETH_P_IP), + .protocol = cpu_to_be16(ETH_P_IP), .update_pmtu = fake_update_pmtu, .entries = ATOMIC_INIT(0), }; diff --git a/net/can/af_can.c b/net/can/af_can.c index fa417ca6cbe..d90e8dd975f 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -828,7 +828,7 @@ static int can_notifier(struct notifier_block *nb, unsigned long msg, */ static struct packet_type can_packet __read_mostly = { - .type = __constant_htons(ETH_P_CAN), + .type = cpu_to_be16(ETH_P_CAN), .dev = NULL, .func = can_rcv, }; diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index cf0e1849929..12bf7d4c16c 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -2113,7 +2113,7 @@ static struct notifier_block dn_dev_notifier = { extern int dn_route_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *); static struct packet_type dn_dix_packet_type = { - .type = __constant_htons(ETH_P_DNA_RT), + .type = cpu_to_be16(ETH_P_DNA_RT), .dev = NULL, /* All devices */ .func = dn_route_rcv, }; diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index c754670b7fc..5130dee0b38 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -124,7 +124,7 @@ int decnet_dst_gc_interval = 2; static struct dst_ops dn_dst_ops = { .family = PF_DECnet, - .protocol = __constant_htons(ETH_P_DNA_RT), + .protocol = cpu_to_be16(ETH_P_DNA_RT), .gc_thresh = 128, .gc = dn_dst_gc, .check = dn_dst_check, diff --git a/net/dsa/mv88e6123_61_65.c b/net/dsa/mv88e6123_61_65.c index ec8c6a0482d..10031872221 100644 --- a/net/dsa/mv88e6123_61_65.c +++ b/net/dsa/mv88e6123_61_65.c @@ -394,7 +394,7 @@ static int mv88e6123_61_65_get_sset_count(struct dsa_switch *ds) } static struct dsa_switch_driver mv88e6123_61_65_switch_driver = { - .tag_protocol = __constant_htons(ETH_P_EDSA), + .tag_protocol = cpu_to_be16(ETH_P_EDSA), .priv_size = sizeof(struct mv88e6xxx_priv_state), .probe = mv88e6123_61_65_probe, .setup = mv88e6123_61_65_setup, diff --git a/net/dsa/mv88e6131.c b/net/dsa/mv88e6131.c index 374d46a0126..70fae2444cb 100644 --- a/net/dsa/mv88e6131.c +++ b/net/dsa/mv88e6131.c @@ -353,7 +353,7 @@ static int mv88e6131_get_sset_count(struct dsa_switch *ds) } static struct dsa_switch_driver mv88e6131_switch_driver = { - .tag_protocol = __constant_htons(ETH_P_DSA), + .tag_protocol = cpu_to_be16(ETH_P_DSA), .priv_size = sizeof(struct mv88e6xxx_priv_state), .probe = mv88e6131_probe, .setup = mv88e6131_setup, diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c index f99a019b939..63e532a69fd 100644 --- a/net/dsa/tag_dsa.c +++ b/net/dsa/tag_dsa.c @@ -176,7 +176,7 @@ out: } static struct packet_type dsa_packet_type = { - .type = __constant_htons(ETH_P_DSA), + .type = cpu_to_be16(ETH_P_DSA), .func = dsa_rcv, }; diff --git a/net/dsa/tag_edsa.c b/net/dsa/tag_edsa.c index 328ec957f78..6197f9a7ef4 100644 --- a/net/dsa/tag_edsa.c +++ b/net/dsa/tag_edsa.c @@ -195,7 +195,7 @@ out: } static struct packet_type edsa_packet_type = { - .type = __constant_htons(ETH_P_EDSA), + .type = cpu_to_be16(ETH_P_EDSA), .func = edsa_rcv, }; diff --git a/net/dsa/tag_trailer.c b/net/dsa/tag_trailer.c index b59132878ad..d7e7f424ff0 100644 --- a/net/dsa/tag_trailer.c +++ b/net/dsa/tag_trailer.c @@ -112,7 +112,7 @@ out: } static struct packet_type trailer_packet_type = { - .type = __constant_htons(ETH_P_TRAILER), + .type = cpu_to_be16(ETH_P_TRAILER), .func = trailer_rcv, }; diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index 8789d2bb1b0..7bf35582f65 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c @@ -1103,7 +1103,7 @@ drop: } static struct packet_type econet_packet_type = { - .type = __constant_htons(ETH_P_ECONET), + .type = cpu_to_be16(ETH_P_ECONET), .func = econet_rcv, }; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index d6770f295d5..957cd054732 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1501,7 +1501,7 @@ static int ipv4_proc_init(void); */ static struct packet_type ip_packet_type = { - .type = __constant_htons(ETH_P_IP), + .type = cpu_to_be16(ETH_P_IP), .func = ip_rcv, .gso_send_check = inet_gso_send_check, .gso_segment = inet_gso_segment, diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 29a74c01d8d..3f6b7354699 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -1226,7 +1226,7 @@ void arp_ifdown(struct net_device *dev) */ static struct packet_type arp_packet_type = { - .type = __constant_htons(ETH_P_ARP), + .type = cpu_to_be16(ETH_P_ARP), .func = arp_rcv, }; diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index d722013c1ca..90d22ae0a41 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -100,8 +100,8 @@ #define CONF_NAMESERVERS_MAX 3 /* Maximum number of nameservers - '3' from resolv.h */ -#define NONE __constant_htonl(INADDR_NONE) -#define ANY __constant_htonl(INADDR_ANY) +#define NONE cpu_to_be32(INADDR_NONE) +#define ANY cpu_to_be32(INADDR_ANY) /* * Public IP configuration @@ -406,7 +406,7 @@ static int __init ic_defaults(void) static int ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev); static struct packet_type rarp_packet_type __initdata = { - .type = __constant_htons(ETH_P_RARP), + .type = cpu_to_be16(ETH_P_RARP), .func = ic_rarp_recv, }; @@ -568,7 +568,7 @@ struct bootp_pkt { /* BOOTP packet format */ static int ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev); static struct packet_type bootp_packet_type __initdata = { - .type = __constant_htons(ETH_P_IP), + .type = cpu_to_be16(ETH_P_IP), .func = ic_bootp_recv, }; diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c index 182f845de92..d9521f6f9ed 100644 --- a/net/ipv4/netfilter/nf_nat_snmp_basic.c +++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c @@ -1292,7 +1292,7 @@ static struct nf_conntrack_helper snmp_helper __read_mostly = { .expect_policy = &snmp_exp_policy, .name = "snmp", .tuple.src.l3num = AF_INET, - .tuple.src.u.udp.port = __constant_htons(SNMP_PORT), + .tuple.src.u.udp.port = cpu_to_be16(SNMP_PORT), .tuple.dst.protonum = IPPROTO_UDP, }; @@ -1302,7 +1302,7 @@ static struct nf_conntrack_helper snmp_trap_helper __read_mostly = { .expect_policy = &snmp_exp_policy, .name = "snmp_trap", .tuple.src.l3num = AF_INET, - .tuple.src.u.udp.port = __constant_htons(SNMP_TRAP_PORT), + .tuple.src.u.udp.port = cpu_to_be16(SNMP_TRAP_PORT), .tuple.dst.protonum = IPPROTO_UDP, }; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 6a9e204c802..5caee609be0 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -151,7 +151,7 @@ static void rt_emergency_hash_rebuild(struct net *net); static struct dst_ops ipv4_dst_ops = { .family = AF_INET, - .protocol = __constant_htons(ETH_P_IP), + .protocol = cpu_to_be16(ETH_P_IP), .gc = rt_garbage_collect, .check = ipv4_dst_check, .destroy = ipv4_dst_destroy, @@ -2696,7 +2696,7 @@ static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) static struct dst_ops ipv4_dst_blackhole_ops = { .family = AF_INET, - .protocol = __constant_htons(ETH_P_IP), + .protocol = cpu_to_be16(ETH_P_IP), .destroy = ipv4_dst_destroy, .check = ipv4_dst_check, .update_pmtu = ipv4_rt_blackhole_update_pmtu, diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 2ad24ba31f9..60d918c96a4 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -241,7 +241,7 @@ static void xfrm4_dst_ifdown(struct dst_entry *dst, struct net_device *dev, static struct dst_ops xfrm4_dst_ops = { .family = AF_INET, - .protocol = __constant_htons(ETH_P_IP), + .protocol = cpu_to_be16(ETH_P_IP), .gc = xfrm4_garbage_collect, .update_pmtu = xfrm4_update_pmtu, .destroy = xfrm4_dst_destroy, diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index bd91eadcbe3..fa2ac7ee662 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -890,7 +890,7 @@ out_unlock: } static struct packet_type ipv6_packet_type = { - .type = __constant_htons(ETH_P_IPV6), + .type = cpu_to_be16(ETH_P_IPV6), .func = ipv6_rcv, .gso_send_check = ipv6_gso_send_check, .gso_segment = ipv6_gso_segment, diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 9c574235c90..c3d486a3eda 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -98,7 +98,7 @@ static struct rt6_info *rt6_get_route_info(struct net *net, static struct dst_ops ip6_dst_ops_template = { .family = AF_INET6, - .protocol = __constant_htons(ETH_P_IPV6), + .protocol = cpu_to_be16(ETH_P_IPV6), .gc = ip6_dst_gc, .gc_thresh = 1024, .check = ip6_dst_check, @@ -117,7 +117,7 @@ static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) static struct dst_ops ip6_dst_blackhole_ops = { .family = AF_INET6, - .protocol = __constant_htons(ETH_P_IPV6), + .protocol = cpu_to_be16(ETH_P_IPV6), .destroy = ip6_dst_destroy, .check = ip6_dst_check, .update_pmtu = ip6_rt_blackhole_update_pmtu, diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 97ab068e8cc..b4b16a43f27 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -272,7 +272,7 @@ static void xfrm6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, static struct dst_ops xfrm6_dst_ops = { .family = AF_INET6, - .protocol = __constant_htons(ETH_P_IPV6), + .protocol = cpu_to_be16(ETH_P_IPV6), .gc = xfrm6_garbage_collect, .update_pmtu = xfrm6_update_pmtu, .destroy = xfrm6_dst_destroy, diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index b6e70f92e7f..43d0ffc6d56 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -1959,12 +1959,12 @@ static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = { SOCKOPS_WRAP(ipx_dgram, PF_IPX); static struct packet_type ipx_8023_packet_type = { - .type = __constant_htons(ETH_P_802_3), + .type = cpu_to_be16(ETH_P_802_3), .func = ipx_rcv, }; static struct packet_type ipx_dix_packet_type = { - .type = __constant_htons(ETH_P_IPX), + .type = cpu_to_be16(ETH_P_IPX), .func = ipx_rcv, }; diff --git a/net/irda/irmod.c b/net/irda/irmod.c index 4c487a88372..1bb607f2f5c 100644 --- a/net/irda/irmod.c +++ b/net/irda/irmod.c @@ -56,7 +56,7 @@ EXPORT_SYMBOL(irda_debug); * Tell the kernel how IrDA packets should be handled. */ static struct packet_type irda_packet_type = { - .type = __constant_htons(ETH_P_IRDA), + .type = cpu_to_be16(ETH_P_IRDA), .func = irlap_driver_rcv, /* Packet type handler irlap_frame.c */ }; diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c index 50d5b10e23a..a7fe1adc378 100644 --- a/net/llc/llc_core.c +++ b/net/llc/llc_core.c @@ -148,12 +148,12 @@ void llc_sap_close(struct llc_sap *sap) } static struct packet_type llc_packet_type = { - .type = __constant_htons(ETH_P_802_2), + .type = cpu_to_be16(ETH_P_802_2), .func = llc_rcv, }; static struct packet_type llc_tr_packet_type = { - .type = __constant_htons(ETH_P_TR_802_2), + .type = cpu_to_be16(ETH_P_TR_802_2), .func = llc_rcv, }; diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index 6be5d4efa51..5c48378a852 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c @@ -149,8 +149,8 @@ static struct task_struct *sync_backup_thread; /* multicast addr */ static struct sockaddr_in mcast_addr = { .sin_family = AF_INET, - .sin_port = __constant_htons(IP_VS_SYNC_PORT), - .sin_addr.s_addr = __constant_htonl(IP_VS_SYNC_GROUP), + .sin_port = cpu_to_be16(IP_VS_SYNC_PORT), + .sin_addr.s_addr = cpu_to_be32(IP_VS_SYNC_GROUP), }; diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c index 4f8fcf49854..07d9d8857e5 100644 --- a/net/netfilter/nf_conntrack_amanda.c +++ b/net/netfilter/nf_conntrack_amanda.c @@ -177,7 +177,7 @@ static struct nf_conntrack_helper amanda_helper[2] __read_mostly = { .me = THIS_MODULE, .help = amanda_help, .tuple.src.l3num = AF_INET, - .tuple.src.u.udp.port = __constant_htons(10080), + .tuple.src.u.udp.port = cpu_to_be16(10080), .tuple.dst.protonum = IPPROTO_UDP, .expect_policy = &amanda_exp_policy, }, @@ -186,7 +186,7 @@ static struct nf_conntrack_helper amanda_helper[2] __read_mostly = { .me = THIS_MODULE, .help = amanda_help, .tuple.src.l3num = AF_INET6, - .tuple.src.u.udp.port = __constant_htons(10080), + .tuple.src.u.udp.port = cpu_to_be16(10080), .tuple.dst.protonum = IPPROTO_UDP, .expect_policy = &amanda_exp_policy, }, diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 687bd633c3d..66369490230 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -1167,7 +1167,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = { .name = "Q.931", .me = THIS_MODULE, .tuple.src.l3num = AF_INET, - .tuple.src.u.tcp.port = __constant_htons(Q931_PORT), + .tuple.src.u.tcp.port = cpu_to_be16(Q931_PORT), .tuple.dst.protonum = IPPROTO_TCP, .help = q931_help, .expect_policy = &q931_exp_policy, @@ -1176,7 +1176,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = { .name = "Q.931", .me = THIS_MODULE, .tuple.src.l3num = AF_INET6, - .tuple.src.u.tcp.port = __constant_htons(Q931_PORT), + .tuple.src.u.tcp.port = cpu_to_be16(Q931_PORT), .tuple.dst.protonum = IPPROTO_TCP, .help = q931_help, .expect_policy = &q931_exp_policy, @@ -1741,7 +1741,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = { .name = "RAS", .me = THIS_MODULE, .tuple.src.l3num = AF_INET, - .tuple.src.u.udp.port = __constant_htons(RAS_PORT), + .tuple.src.u.udp.port = cpu_to_be16(RAS_PORT), .tuple.dst.protonum = IPPROTO_UDP, .help = ras_help, .expect_policy = &ras_exp_policy, @@ -1750,7 +1750,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = { .name = "RAS", .me = THIS_MODULE, .tuple.src.l3num = AF_INET6, - .tuple.src.u.udp.port = __constant_htons(RAS_PORT), + .tuple.src.u.udp.port = cpu_to_be16(RAS_PORT), .tuple.dst.protonum = IPPROTO_UDP, .help = ras_help, .expect_policy = &ras_exp_policy, diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c index 5af4273b466..8a3875e36ec 100644 --- a/net/netfilter/nf_conntrack_netbios_ns.c +++ b/net/netfilter/nf_conntrack_netbios_ns.c @@ -105,7 +105,7 @@ static struct nf_conntrack_expect_policy exp_policy = { static struct nf_conntrack_helper helper __read_mostly = { .name = "netbios-ns", .tuple.src.l3num = AF_INET, - .tuple.src.u.udp.port = __constant_htons(NMBD_PORT), + .tuple.src.u.udp.port = cpu_to_be16(NMBD_PORT), .tuple.dst.protonum = IPPROTO_UDP, .me = THIS_MODULE, .help = help, diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c index 9e169ef2e85..72cca638a82 100644 --- a/net/netfilter/nf_conntrack_pptp.c +++ b/net/netfilter/nf_conntrack_pptp.c @@ -591,7 +591,7 @@ static struct nf_conntrack_helper pptp __read_mostly = { .name = "pptp", .me = THIS_MODULE, .tuple.src.l3num = AF_INET, - .tuple.src.u.tcp.port = __constant_htons(PPTP_CONTROL_PORT), + .tuple.src.u.tcp.port = cpu_to_be16(PPTP_CONTROL_PORT), .tuple.dst.protonum = IPPROTO_TCP, .help = conntrack_pptp_help, .destroy = pptp_destroy_siblings, diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index 95bc49ddb8b..81795ea8779 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c @@ -383,7 +383,7 @@ out: } static struct packet_type phonet_packet_type = { - .type = __constant_htons(ETH_P_PHONET), + .type = cpu_to_be16(ETH_P_PHONET), .dev = NULL, .func = phonet_rcv, }; diff --git a/net/sctp/output.c b/net/sctp/output.c index 73639355157..47bfba6c03e 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -367,7 +367,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) struct sctp_transport *tp = packet->transport; struct sctp_association *asoc = tp->asoc; struct sctphdr *sh; - __be32 crc32 = __constant_cpu_to_be32(0); + __be32 crc32 = cpu_to_be32(0); struct sk_buff *nskb; struct sctp_chunk *chunk, *tmp; struct sock *sk; diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index fd8acb48c3f..b40e95f9851 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -100,11 +100,11 @@ int sctp_chunk_iif(const struct sctp_chunk *chunk) */ static const struct sctp_paramhdr ecap_param = { SCTP_PARAM_ECN_CAPABLE, - __constant_htons(sizeof(struct sctp_paramhdr)), + cpu_to_be16(sizeof(struct sctp_paramhdr)), }; static const struct sctp_paramhdr prsctp_param = { SCTP_PARAM_FWD_TSN_SUPPORT, - __constant_htons(sizeof(struct sctp_paramhdr)), + cpu_to_be16(sizeof(struct sctp_paramhdr)), }; /* A helper to initialize to initialize an op error inside a diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 9fc5b023d11..8f76f4009c2 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -1609,7 +1609,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { SOCKOPS_WRAP(x25_proto, AF_X25); static struct packet_type x25_packet_type = { - .type = __constant_htons(ETH_P_X25), + .type = cpu_to_be16(ETH_P_X25), .func = x25_lapb_receive_frame, }; -- GitLab From 2884e5cc9283d541977bdf5dc344849af94cd639 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sun, 1 Feb 2009 00:52:34 -0800 Subject: [PATCH 1086/4982] gianfar: Implement proper, per netdevice wakeup management This patch implements wakeup management for the gianfar driver. The driver should set wakeup enable if WOL is enabled, so that phylib won't power off an attached PHY. Signed-off-by: Anton Vorontsov Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 5 +++++ drivers/net/gianfar_ethtool.c | 1 + 2 files changed, 6 insertions(+) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index f5e6068f9b0..4d2ca490d76 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -463,6 +463,9 @@ static int gfar_probe(struct of_device *ofdev, goto register_fail; } + device_init_wakeup(&dev->dev, + priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); + /* fill out IRQ number and name fields */ len_devname = strlen(dev->name); strncpy(&priv->int_name_tx[0], dev->name, len_devname); @@ -1200,6 +1203,8 @@ static int gfar_enet_open(struct net_device *dev) netif_start_queue(dev); + device_set_wakeup_enable(&dev->dev, priv->wol_en); + return err; } diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 59b3b5d98ef..dbf06e9313c 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c @@ -600,6 +600,7 @@ static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) spin_lock_irqsave(&priv->bflock, flags); priv->wol_en = wol->wolopts & WAKE_MAGIC ? 1 : 0; + device_set_wakeup_enable(&dev->dev, priv->wol_en); spin_unlock_irqrestore(&priv->bflock, flags); return 0; -- GitLab From 3d1e4db2b0698785f4e4dd139d88257e855e53b8 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sun, 1 Feb 2009 00:53:34 -0800 Subject: [PATCH 1087/4982] phylib: Rework suspend/resume code to check netdev wakeup capability In most cases (e.g. PCI drivers) MDIO and MAC controllers are represented by the same device. But for SOC ethernets we have separate devices. So, in SOC case, checking whether MDIO controller may wakeup is not only makes little sense, but also prevents us from doing per-netdevice wakeup management. This patch reworks suspend/resume code so that now it checks for net device's wakeup flags, not MDIO controller's ones. Each netdevice should manage its wakeup flags, and phylib will decide whether suspend an attached PHY or not. Signed-off-by: Anton Vorontsov Signed-off-by: David S. Miller --- drivers/net/phy/mdio_bus.c | 54 ++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 811a637695c..bb29ae3ff17 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -286,33 +287,58 @@ static int mdio_bus_match(struct device *dev, struct device_driver *drv) (phydev->phy_id & phydrv->phy_id_mask)); } +static bool mdio_bus_phy_may_suspend(struct phy_device *phydev) +{ + struct device_driver *drv = phydev->dev.driver; + struct phy_driver *phydrv = to_phy_driver(drv); + struct net_device *netdev = phydev->attached_dev; + + if (!drv || !phydrv->suspend) + return false; + + /* PHY not attached? May suspend. */ + if (!netdev) + return true; + + /* + * Don't suspend PHY if the attched netdev parent may wakeup. + * The parent may point to a PCI device, as in tg3 driver. + */ + if (netdev->dev.parent && device_may_wakeup(netdev->dev.parent)) + return false; + + /* + * Also don't suspend PHY if the netdev itself may wakeup. This + * is the case for devices w/o underlaying pwr. mgmt. aware bus, + * e.g. SoC devices. + */ + if (device_may_wakeup(&netdev->dev)) + return false; + + return true; +} + /* Suspend and resume. Copied from platform_suspend and * platform_resume */ static int mdio_bus_suspend(struct device * dev, pm_message_t state) { - int ret = 0; - struct device_driver *drv = dev->driver; - struct phy_driver *phydrv = to_phy_driver(drv); + struct phy_driver *phydrv = to_phy_driver(dev->driver); struct phy_device *phydev = to_phy_device(dev); - if (drv && phydrv->suspend && !device_may_wakeup(phydev->dev.parent)) - ret = phydrv->suspend(phydev); - - return ret; + if (!mdio_bus_phy_may_suspend(phydev)) + return 0; + return phydrv->suspend(phydev); } static int mdio_bus_resume(struct device * dev) { - int ret = 0; - struct device_driver *drv = dev->driver; - struct phy_driver *phydrv = to_phy_driver(drv); + struct phy_driver *phydrv = to_phy_driver(dev->driver); struct phy_device *phydev = to_phy_device(dev); - if (drv && phydrv->resume && !device_may_wakeup(phydev->dev.parent)) - ret = phydrv->resume(phydev); - - return ret; + if (!mdio_bus_phy_may_suspend(phydev)) + return 0; + return phydrv->resume(phydev); } struct bus_type mdio_bus_type = { -- GitLab From b2f66d183966114fcc91591191ec9af14a252ac5 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sun, 1 Feb 2009 00:54:16 -0800 Subject: [PATCH 1088/4982] gianfar: Fix sparse warnings This patch fixes following sparse warnings: CHECK gianfar_ethtool.c gianfar_ethtool.c:610:26: warning: symbol 'gfar_ethtool_ops' was not declared. Should it be static? CHECK gianfar_mii.c gianfar_mii.c:108:35: warning: cast adds address space to expression () gianfar_mii.c:119:35: warning: cast adds address space to expression () gianfar_mii.c:128:35: warning: cast adds address space to expression () gianfar_mii.c:272:5: warning: cast removes address space of expression gianfar_mii.c:271:15: warning: cast adds address space to expression () gianfar_mii.c:340:11: warning: cast adds address space to expression () CHECK gianfar_sysfs.c gianfar_sysfs.c:84:1: warning: symbol 'dev_attr_bd_stash' was not declared. Should it be static? gianfar_sysfs.c:133:1: warning: symbol 'dev_attr_rx_stash_size' was not declared. Should it be static? gianfar_sysfs.c:175:1: warning: symbol 'dev_attr_rx_stash_index' was not declared. Should it be static? gianfar_sysfs.c:213:1: warning: symbol 'dev_attr_fifo_threshold' was not declared. Should it be static? gianfar_sysfs.c:250:1: warning: symbol 'dev_attr_fifo_starve' was not declared. Should it be static? gianfar_sysfs.c:287:1: warning: symbol 'dev_attr_fifo_starve_off' was not declared. Should it be static? Signed-off-by: Anton Vorontsov Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 2 -- drivers/net/gianfar.h | 2 ++ drivers/net/gianfar_mii.c | 12 ++++++------ drivers/net/gianfar_sysfs.c | 21 +++++++++++---------- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 4d2ca490d76..eb8302c5ba8 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -141,8 +141,6 @@ void gfar_start(struct net_device *dev); static void gfar_clear_exact_match(struct net_device *dev); static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr); -extern const struct ethtool_ops gfar_ethtool_ops; - MODULE_AUTHOR("Freescale Semiconductor, Inc"); MODULE_DESCRIPTION("Gianfar Ethernet Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index b1a83344acc..7820720ceee 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -830,4 +830,6 @@ int gfar_local_mdio_write(struct gfar_mii __iomem *regs, int mii_id, int regnum, u16 value); int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum); +extern const struct ethtool_ops gfar_ethtool_ops; + #endif /* __GIANFAR_H */ diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c index f49a426ad68..64e4679b327 100644 --- a/drivers/net/gianfar_mii.c +++ b/drivers/net/gianfar_mii.c @@ -105,7 +105,7 @@ int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum) * All PHY configuration is done through the TSEC1 MIIM regs */ int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) { - struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; + struct gfar_mii __iomem *regs = (void __force __iomem *)bus->priv; /* Write to the local MII regs */ return(gfar_local_mdio_write(regs, mii_id, regnum, value)); @@ -116,7 +116,7 @@ int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) * configuration has to be done through the TSEC1 MIIM regs */ int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum) { - struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; + struct gfar_mii __iomem *regs = (void __force __iomem *)bus->priv; /* Read the local MII regs */ return(gfar_local_mdio_read(regs, mii_id, regnum)); @@ -125,7 +125,7 @@ int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum) /* Reset the MIIM registers, and wait for the bus to free */ static int gfar_mdio_reset(struct mii_bus *bus) { - struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; + struct gfar_mii __iomem *regs = (void __force __iomem *)bus->priv; unsigned int timeout = PHY_INIT_TIMEOUT; mutex_lock(&bus->mdio_lock); @@ -268,8 +268,8 @@ static int gfar_mdio_probe(struct of_device *ofdev, * Also, we have to cast back to struct gfar_mii because of * definition weirdness done in gianfar.h. */ - enet_regs = (struct gfar __iomem *) - ((char *)regs - offsetof(struct gfar, gfar_mii_regs)); + enet_regs = (struct gfar __force __iomem *) + ((char __force *)regs - offsetof(struct gfar, gfar_mii_regs)); for_each_child_of_node(np, tbi) { if (!strncmp(tbi->type, "tbi-phy", 8)) @@ -337,7 +337,7 @@ static int gfar_mdio_remove(struct of_device *ofdev) dev_set_drvdata(&ofdev->dev, NULL); - iounmap((void __iomem *)bus->priv); + iounmap((void __force __iomem *)bus->priv); bus->priv = NULL; kfree(bus->irq); mdiobus_free(bus); diff --git a/drivers/net/gianfar_sysfs.c b/drivers/net/gianfar_sysfs.c index 782c2017008..74e0b4d4258 100644 --- a/drivers/net/gianfar_sysfs.c +++ b/drivers/net/gianfar_sysfs.c @@ -81,7 +81,7 @@ static ssize_t gfar_set_bd_stash(struct device *dev, return count; } -DEVICE_ATTR(bd_stash, 0644, gfar_show_bd_stash, gfar_set_bd_stash); +static DEVICE_ATTR(bd_stash, 0644, gfar_show_bd_stash, gfar_set_bd_stash); static ssize_t gfar_show_rx_stash_size(struct device *dev, struct device_attribute *attr, char *buf) @@ -130,8 +130,8 @@ out: return count; } -DEVICE_ATTR(rx_stash_size, 0644, gfar_show_rx_stash_size, - gfar_set_rx_stash_size); +static DEVICE_ATTR(rx_stash_size, 0644, gfar_show_rx_stash_size, + gfar_set_rx_stash_size); /* Stashing will only be enabled when rx_stash_size != 0 */ static ssize_t gfar_show_rx_stash_index(struct device *dev, @@ -172,8 +172,8 @@ out: return count; } -DEVICE_ATTR(rx_stash_index, 0644, gfar_show_rx_stash_index, - gfar_set_rx_stash_index); +static DEVICE_ATTR(rx_stash_index, 0644, gfar_show_rx_stash_index, + gfar_set_rx_stash_index); static ssize_t gfar_show_fifo_threshold(struct device *dev, struct device_attribute *attr, @@ -210,8 +210,8 @@ static ssize_t gfar_set_fifo_threshold(struct device *dev, return count; } -DEVICE_ATTR(fifo_threshold, 0644, gfar_show_fifo_threshold, - gfar_set_fifo_threshold); +static DEVICE_ATTR(fifo_threshold, 0644, gfar_show_fifo_threshold, + gfar_set_fifo_threshold); static ssize_t gfar_show_fifo_starve(struct device *dev, struct device_attribute *attr, char *buf) @@ -247,7 +247,8 @@ static ssize_t gfar_set_fifo_starve(struct device *dev, return count; } -DEVICE_ATTR(fifo_starve, 0644, gfar_show_fifo_starve, gfar_set_fifo_starve); +static DEVICE_ATTR(fifo_starve, 0644, gfar_show_fifo_starve, + gfar_set_fifo_starve); static ssize_t gfar_show_fifo_starve_off(struct device *dev, struct device_attribute *attr, @@ -284,8 +285,8 @@ static ssize_t gfar_set_fifo_starve_off(struct device *dev, return count; } -DEVICE_ATTR(fifo_starve_off, 0644, gfar_show_fifo_starve_off, - gfar_set_fifo_starve_off); +static DEVICE_ATTR(fifo_starve_off, 0644, gfar_show_fifo_starve_off, + gfar_set_fifo_starve_off); void gfar_init_sysfs(struct net_device *dev) { -- GitLab From 51bbc3e31cb59d94b0c9c1ca3f1851b7f1787169 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 28 Jan 2009 23:03:03 +0000 Subject: [PATCH 1089/4982] fec: remove unused #else branches The #else branches throughout this driver belong to a PowerPC 8xx for which this driver is not used. Signed-off-by: Sascha Hauer Acked-by: Greg Ungerer Signed-off-by: David S. Miller --- drivers/net/fec.c | 92 ----------------------------------------------- 1 file changed, 92 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 7e33c129d51..b754f600e44 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -72,8 +72,6 @@ static unsigned int fec_hw[] = { (MCF_MBAR+0x30000), #elif defined(CONFIG_M532x) (MCF_MBAR+0xfc030000), -#else - &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec), #endif }; @@ -1760,96 +1758,6 @@ static void __inline__ fec_uncache(unsigned long addr) { } -/* ------------------------------------------------------------------------- */ - - -#else - -/* - * Code specific to the MPC860T setup. - */ -static void __inline__ fec_request_intrs(struct net_device *dev) -{ - volatile immap_t *immap; - - immap = (immap_t *)IMAP_ADDR; /* pointer to internal registers */ - - if (request_8xxirq(FEC_INTERRUPT, fec_enet_interrupt, 0, "fec", dev) != 0) - panic("Could not allocate FEC IRQ!"); -} - -static void __inline__ fec_get_mac(struct net_device *dev) -{ - bd_t *bd; - - bd = (bd_t *)__res; - memcpy(dev->dev_addr, bd->bi_enetaddr, ETH_ALEN); -} - -static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep) -{ - extern uint _get_IMMR(void); - volatile immap_t *immap; - volatile fec_t *fecp; - - fecp = fep->hwp; - immap = (immap_t *)IMAP_ADDR; /* pointer to internal registers */ - - /* Configure all of port D for MII. - */ - immap->im_ioport.iop_pdpar = 0x1fff; - - /* Bits moved from Rev. D onward. - */ - if ((_get_IMMR() & 0xffff) < 0x0501) - immap->im_ioport.iop_pddir = 0x1c58; /* Pre rev. D */ - else - immap->im_ioport.iop_pddir = 0x1fff; /* Rev. D and later */ - - /* Set MII speed to 2.5 MHz - */ - fecp->fec_mii_speed = fep->phy_speed = - ((bd->bi_busfreq * 1000000) / 2500000) & 0x7e; -} - -static void __inline__ fec_enable_phy_intr(void) -{ - volatile fec_t *fecp; - - fecp = fep->hwp; - - /* Enable MII command finished interrupt - */ - fecp->fec_ivec = (FEC_INTERRUPT/2) << 29; -} - -static void __inline__ fec_disable_phy_intr(void) -{ -} - -static void __inline__ fec_phy_ack_intr(void) -{ -} - -static void __inline__ fec_localhw_setup(void) -{ - volatile fec_t *fecp; - - fecp = fep->hwp; - fecp->fec_r_hash = PKT_MAXBUF_SIZE; - /* Enable big endian and don't care about SDMA FC. - */ - fecp->fec_fun_code = 0x78000000; -} - -static void __inline__ fec_uncache(unsigned long addr) -{ - pte_t *pte; - pte = va_to_pte(mem_addr); - pte_val(*pte) |= _PAGE_NO_CACHE; - flush_tlb_page(init_mm.mmap, mem_addr); -} - #endif /* ------------------------------------------------------------------------- */ -- GitLab From 6a8ea2c6f5521096b9972c75f7ad7b5303bce29c Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 28 Jan 2009 23:03:04 +0000 Subject: [PATCH 1090/4982] fec: remove empty functions There are some architecture specific functions which are all empty. Remove them. Signed-off-by: Sascha Hauer Acked-by: Greg Ungerer Signed-off-by: David S. Miller --- drivers/net/fec.c | 65 ----------------------------------------------- 1 file changed, 65 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index b754f600e44..f913c97bb81 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1306,10 +1306,6 @@ static void __inline__ fec_get_mac(struct net_device *dev) dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index; } -static void __inline__ fec_enable_phy_intr(void) -{ -} - static void __inline__ fec_disable_phy_intr(void) { volatile unsigned long *icrp; @@ -1325,17 +1321,6 @@ static void __inline__ fec_phy_ack_intr(void) *icrp = 0x0d000000; } -static void __inline__ fec_localhw_setup(void) -{ -} - -/* - * Do not need to make region uncached on 5272. - */ -static void __inline__ fec_uncache(unsigned long addr) -{ -} - /* ------------------------------------------------------------------------- */ #elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) @@ -1475,10 +1460,6 @@ static void __inline__ fec_get_mac(struct net_device *dev) dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index; } -static void __inline__ fec_enable_phy_intr(void) -{ -} - static void __inline__ fec_disable_phy_intr(void) { } @@ -1487,17 +1468,6 @@ static void __inline__ fec_phy_ack_intr(void) { } -static void __inline__ fec_localhw_setup(void) -{ -} - -/* - * Do not need to make region uncached on 5272. - */ -static void __inline__ fec_uncache(unsigned long addr) -{ -} - /* ------------------------------------------------------------------------- */ #elif defined(CONFIG_M520x) @@ -1596,10 +1566,6 @@ static void __inline__ fec_get_mac(struct net_device *dev) dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index; } -static void __inline__ fec_enable_phy_intr(void) -{ -} - static void __inline__ fec_disable_phy_intr(void) { } @@ -1608,14 +1574,6 @@ static void __inline__ fec_phy_ack_intr(void) { } -static void __inline__ fec_localhw_setup(void) -{ -} - -static void __inline__ fec_uncache(unsigned long addr) -{ -} - /* ------------------------------------------------------------------------- */ #elif defined(CONFIG_M532x) @@ -1735,10 +1693,6 @@ static void __inline__ fec_get_mac(struct net_device *dev) dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index; } -static void __inline__ fec_enable_phy_intr(void) -{ -} - static void __inline__ fec_disable_phy_intr(void) { } @@ -1747,17 +1701,6 @@ static void __inline__ fec_phy_ack_intr(void) { } -static void __inline__ fec_localhw_setup(void) -{ -} - -/* - * Do not need to make region uncached on 532x. - */ -static void __inline__ fec_uncache(unsigned long addr) -{ -} - #endif /* ------------------------------------------------------------------------- */ @@ -2199,8 +2142,6 @@ int __init fec_enet_init(struct net_device *dev) cbd_base = (cbd_t *)mem_addr; /* XXX: missing check for allocation failure */ - fec_uncache(mem_addr); - /* Set receive and transmit descriptor base. */ fep->rx_bd_base = cbd_base; @@ -2221,8 +2162,6 @@ int __init fec_enet_init(struct net_device *dev) mem_addr = __get_free_page(GFP_KERNEL); /* XXX: missing check for allocation failure */ - fec_uncache(mem_addr); - /* Initialize the BD for every fragment in the page. */ for (j=0; jfec_ievent = 0xffc00000; - fec_enable_phy_intr(); /* Set station address. */ @@ -2353,8 +2291,6 @@ fec_restart(struct net_device *dev, int duplex) */ fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; - fec_localhw_setup(); - /* Set receive and transmit descriptor base. */ fecp->fec_r_des_start = __pa((uint)(fep->rx_bd_base)); @@ -2460,7 +2396,6 @@ fec_stop(struct net_device *dev) /* Clear outstanding MII command interrupts. */ fecp->fec_ievent = FEC_ENET_MII; - fec_enable_phy_intr(); fecp->fec_imask = FEC_ENET_MII; fecp->fec_mii_speed = fep->phy_speed; -- GitLab From 6f501b173f2d69973497599f5358fb4c30922d67 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 28 Jan 2009 23:03:05 +0000 Subject: [PATCH 1091/4982] fec: use linux/*.h instead of asm/*.h Signed-off-by: Sascha Hauer Acked-by: Greg Ungerer Signed-off-by: David S. Miller --- drivers/net/fec.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index f913c97bb81..a44b4eef180 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -36,15 +36,13 @@ #include #include #include +#include +#include -#include -#include -#include -#include #include - #include #include + #include "fec.h" #if defined(CONFIG_FEC2) -- GitLab From 6989f5122f84046ba286efe8ce8be2fec42a1b7c Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 28 Jan 2009 23:03:06 +0000 Subject: [PATCH 1092/4982] fec: do not use memcpy on physical addresses Signed-off-by: Sascha Hauer Acked-by: Greg Ungerer Signed-off-by: David S. Miller --- drivers/net/fec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index a44b4eef180..1087c4da84a 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -341,7 +341,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) if (bdp->cbd_bufaddr & 0x3) { unsigned int index; index = bdp - fep->tx_bd_base; - memcpy(fep->tx_bounce[index], (void *) bdp->cbd_bufaddr, bdp->cbd_datlen); + memcpy(fep->tx_bounce[index], (void *)skb->data, skb->len); bdp->cbd_bufaddr = __pa(fep->tx_bounce[index]); } -- GitLab From 4661e75b9d7bb12bcbe9be8bbf40ebf0845879a9 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 28 Jan 2009 23:03:07 +0000 Subject: [PATCH 1093/4982] fec: use dma_alloc_coherent for descriptor ring Signed-off-by: Sascha Hauer Acked-by: Greg Ungerer Signed-off-by: David S. Miller --- drivers/net/fec.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 1087c4da84a..46a441a9c64 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -186,6 +186,7 @@ struct fec_enet_private { /* CPM dual port RAM relative addresses. */ + dma_addr_t bd_dma; cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */ cbd_t *tx_bd_base; cbd_t *cur_rx, *cur_tx; /* The next free ring entry */ @@ -2107,7 +2108,8 @@ int __init fec_enet_init(struct net_device *dev) /* Allocate memory for buffer descriptors. */ - mem_addr = __get_free_page(GFP_KERNEL); + mem_addr = (unsigned long)dma_alloc_coherent(NULL, PAGE_SIZE, + &fep->bd_dma, GFP_KERNEL); if (mem_addr == 0) { printk("FEC: allocate descriptor memory failed?\n"); return -ENOMEM; @@ -2202,8 +2204,9 @@ int __init fec_enet_init(struct net_device *dev) /* Set receive and transmit descriptor base. */ - fecp->fec_r_des_start = __pa((uint)(fep->rx_bd_base)); - fecp->fec_x_des_start = __pa((uint)(fep->tx_bd_base)); + fecp->fec_r_des_start = fep->bd_dma; + fecp->fec_x_des_start = (unsigned long)fep->bd_dma + sizeof(cbd_t) + * RX_RING_SIZE; /* Install our interrupt handlers. This varies depending on * the architecture. @@ -2291,8 +2294,9 @@ fec_restart(struct net_device *dev, int duplex) /* Set receive and transmit descriptor base. */ - fecp->fec_r_des_start = __pa((uint)(fep->rx_bd_base)); - fecp->fec_x_des_start = __pa((uint)(fep->tx_bd_base)); + fecp->fec_r_des_start = fep->bd_dma; + fecp->fec_x_des_start = (unsigned long)fep->bd_dma + sizeof(cbd_t) + * RX_RING_SIZE; fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; fep->cur_rx = fep->rx_bd_base; -- GitLab From 43268dcea7512cc10bc2542f20ce37971ecfeb48 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 28 Jan 2009 23:03:08 +0000 Subject: [PATCH 1094/4982] fec: Fix KS8721BL_ICSR phy register offset According to the datasheet the ICSR register is at offset 27, not 22. Signed-off-by: Sascha Hauer Acked-by: Greg Ungerer Signed-off-by: David S. Miller --- drivers/net/fec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 46a441a9c64..cab07eced06 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1111,7 +1111,7 @@ static phy_info_t const phy_info_am79c874 = { /* register definitions for the 8721 */ #define MII_KS8721BL_RXERCR 21 -#define MII_KS8721BL_ICSR 22 +#define MII_KS8721BL_ICSR 27 #define MII_KS8721BL_PHYCR 31 static phy_cmd_t const phy_cmd_ks8721bl_config[] = { -- GitLab From ccdc4f198193eb4956b8dbc00745270525c4cd6e Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 28 Jan 2009 23:03:09 +0000 Subject: [PATCH 1095/4982] fec: replace flush_dcache_range with dma_sync_single flush_dcache_range is not portable across architectures. Use dma_sync_single instead. Also, the memory must be synchronised in the receive path aswell. Signed-off-by: Sascha Hauer Acked-by: Greg Ungerer Signed-off-by: David S. Miller --- drivers/net/fec.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index cab07eced06..a17dc6af30c 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -356,8 +356,8 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Push the data cache so the CPM does not get stale memory * data. */ - flush_dcache_range((unsigned long)skb->data, - (unsigned long)skb->data + skb->len); + dma_sync_single(NULL, bdp->cbd_bufaddr, + bdp->cbd_datlen, DMA_TO_DEVICE); /* Send it on its way. Tell FEC it's ready, interrupt when done, * it's the last BD of the frame, and to put the CRC on the end. @@ -630,6 +630,9 @@ while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) { dev->stats.rx_bytes += pkt_len; data = (__u8*)__va(bdp->cbd_bufaddr); + dma_sync_single(NULL, (unsigned long)__pa(data), + pkt_len - 4, DMA_FROM_DEVICE); + /* This does 16 byte alignment, exactly what we need. * The packet length includes FCS, but we don't want to * include that when passing upstream as it messes up -- GitLab From 196719ecec0c526de273dcb902f0be956a193232 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 28 Jan 2009 23:03:10 +0000 Subject: [PATCH 1096/4982] fec: Add support for Freescale MX27 Signed-off-by: Sascha Hauer Acked-by: Greg Ungerer Signed-off-by: David S. Miller --- drivers/net/Kconfig | 6 +++--- drivers/net/fec.c | 15 +++++++++++++-- drivers/net/fec.h | 11 +++++++++-- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index c4776a2adf0..0ec01e42e9b 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1828,11 +1828,11 @@ config 68360_ENET the Motorola 68360 processor. config FEC - bool "FEC ethernet controller (of ColdFire CPUs)" - depends on M523x || M527x || M5272 || M528x || M520x + bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)" + depends on M523x || M527x || M5272 || M528x || M520x || MACH_MX27 help Say Y here if you want to use the built-in 10/100 Fast ethernet - controller on some Motorola ColdFire processors. + controller on some Motorola ColdFire and Freescale i.MX processors. config FEC2 bool "Second FEC ethernet controller (on some ColdFire CPUs)" diff --git a/drivers/net/fec.c b/drivers/net/fec.c index a17dc6af30c..7631062cd44 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -38,10 +38,14 @@ #include #include #include +#include #include + +#ifndef CONFIG_ARCH_MXC #include #include +#endif #include "fec.h" @@ -51,6 +55,13 @@ #define FEC_MAX_PORTS 1 #endif +#ifdef CONFIG_ARCH_MXC +#include +#define FEC_ALIGNMENT 0xf +#else +#define FEC_ALIGNMENT 0x3 +#endif + #if defined(CONFIG_M5272) #define HAVE_mii_link_interrupt #endif @@ -158,7 +169,7 @@ typedef struct { * account when setting it. */ #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ - defined(CONFIG_M520x) || defined(CONFIG_M532x) + defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARCH_MXC) #define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16) #else #define OPT_FRAME_SIZE 0 @@ -339,7 +350,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) * 4-byte boundaries. Use bounce buffers to copy data * and get it aligned. Ugh. */ - if (bdp->cbd_bufaddr & 0x3) { + if (bdp->cbd_bufaddr & FEC_ALIGNMENT) { unsigned int index; index = bdp - fep->tx_bd_base; memcpy(fep->tx_bounce[index], (void *)skb->data, skb->len); diff --git a/drivers/net/fec.h b/drivers/net/fec.h index 292719dacef..76c64c92e19 100644 --- a/drivers/net/fec.h +++ b/drivers/net/fec.h @@ -14,7 +14,7 @@ /****************************************************************************/ #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ - defined(CONFIG_M520x) || defined(CONFIG_M532x) + defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARCH_MXC) /* * Just figures, Motorola would have to change the offsets for * registers in the same peripheral device on different models @@ -103,12 +103,19 @@ typedef struct fec { /* * Define the buffer descriptor structure. */ +#ifdef CONFIG_ARCH_MXC +typedef struct bufdesc { + unsigned short cbd_datlen; /* Data length */ + unsigned short cbd_sc; /* Control and status info */ + unsigned long cbd_bufaddr; /* Buffer address */ +} cbd_t; +#else typedef struct bufdesc { unsigned short cbd_sc; /* Control and status info */ unsigned short cbd_datlen; /* Data length */ unsigned long cbd_bufaddr; /* Buffer address */ } cbd_t; - +#endif /* * The following definitions courtesy of commproc.h, which where -- GitLab From ead731837d142b103eab9870105f50bc40b69255 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 28 Jan 2009 23:03:11 +0000 Subject: [PATCH 1097/4982] FEC: Turn FEC driver into platform device driver This turns the fec driver into a platform device driver for new platforms. Old platforms are still supported through a FEC_LEGACY define till they are also ported. Signed-off-by: Sascha Hauer Acked-by: Greg Ungerer Signed-off-by: David S. Miller --- drivers/net/fec.c | 249 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 220 insertions(+), 29 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 7631062cd44..ea23baaf025 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -39,6 +39,7 @@ #include #include #include +#include #include @@ -49,12 +50,6 @@ #include "fec.h" -#if defined(CONFIG_FEC2) -#define FEC_MAX_PORTS 2 -#else -#define FEC_MAX_PORTS 1 -#endif - #ifdef CONFIG_ARCH_MXC #include #define FEC_ALIGNMENT 0xf @@ -62,13 +57,22 @@ #define FEC_ALIGNMENT 0x3 #endif +#if defined CONFIG_M5272 || defined CONFIG_M527x || defined CONFIG_M523x \ + || defined CONFIG_M528x || defined CONFIG_M532x || defined CONFIG_M520x +#define FEC_LEGACY +/* + * Define the fixed address of the FEC hardware. + */ #if defined(CONFIG_M5272) #define HAVE_mii_link_interrupt #endif -/* - * Define the fixed address of the FEC hardware. - */ +#if defined(CONFIG_FEC2) +#define FEC_MAX_PORTS 2 +#else +#define FEC_MAX_PORTS 1 +#endif + static unsigned int fec_hw[] = { #if defined(CONFIG_M5272) (MCF_MBAR + 0x840), @@ -106,6 +110,8 @@ static unsigned char fec_mac_default[] = { #define FEC_FLASHMAC 0 #endif +#endif /* FEC_LEGACY */ + /* Forward declarations of some structures to support different PHYs */ @@ -189,6 +195,8 @@ struct fec_enet_private { struct net_device *netdev; + struct clk *clk; + /* The saved address of a sent-in-place packet/buffer, for skfree(). */ unsigned char *tx_bounce[TX_RING_SIZE]; struct sk_buff* tx_skbuff[TX_RING_SIZE]; @@ -1919,7 +1927,9 @@ mii_discover_phy(uint mii_reg, struct net_device *dev) printk("FEC: No PHY device found.\n"); /* Disable external MII interface */ fecp->fec_mii_speed = fep->phy_speed = 0; +#ifdef FREC_LEGACY fec_disable_phy_intr(); +#endif } } @@ -2101,12 +2111,12 @@ fec_set_mac_address(struct net_device *dev) } -/* Initialize the FEC Ethernet on 860T (or ColdFire 5272). - */ /* * XXX: We need to clean up on failure exits here. + * + * index is only used in legacy code */ -int __init fec_enet_init(struct net_device *dev) +int __init fec_enet_init(struct net_device *dev, int index) { struct fec_enet_private *fep = netdev_priv(dev); unsigned long mem_addr; @@ -2114,11 +2124,6 @@ int __init fec_enet_init(struct net_device *dev) cbd_t *cbd_base; volatile fec_t *fecp; int i, j; - static int index = 0; - - /* Only allow us to be probed once. */ - if (index >= FEC_MAX_PORTS) - return -ENXIO; /* Allocate memory for buffer descriptors. */ @@ -2134,7 +2139,7 @@ int __init fec_enet_init(struct net_device *dev) /* Create an Ethernet device instance. */ - fecp = (volatile fec_t *) fec_hw[index]; + fecp = (volatile fec_t *)dev->base_addr; fep->index = index; fep->hwp = fecp; @@ -2145,16 +2150,24 @@ int __init fec_enet_init(struct net_device *dev) fecp->fec_ecntrl = 1; udelay(10); - /* Set the Ethernet address. If using multiple Enets on the 8xx, - * this needs some work to get unique addresses. - * - * This is our default MAC address unless the user changes - * it via eth_mac_addr (our dev->set_mac_addr handler). - */ + /* Set the Ethernet address */ +#ifdef FEC_LEGACY fec_get_mac(dev); +#else + { + unsigned long l; + l = fecp->fec_addr_low; + dev->dev_addr[0] = (unsigned char)((l & 0xFF000000) >> 24); + dev->dev_addr[1] = (unsigned char)((l & 0x00FF0000) >> 16); + dev->dev_addr[2] = (unsigned char)((l & 0x0000FF00) >> 8); + dev->dev_addr[3] = (unsigned char)((l & 0x000000FF) >> 0); + l = fecp->fec_addr_high; + dev->dev_addr[4] = (unsigned char)((l & 0xFF000000) >> 24); + dev->dev_addr[5] = (unsigned char)((l & 0x00FF0000) >> 16); + } +#endif cbd_base = (cbd_t *)mem_addr; - /* XXX: missing check for allocation failure */ /* Set receive and transmit descriptor base. */ @@ -2222,10 +2235,12 @@ int __init fec_enet_init(struct net_device *dev) fecp->fec_x_des_start = (unsigned long)fep->bd_dma + sizeof(cbd_t) * RX_RING_SIZE; +#ifdef FEC_LEGACY /* Install our interrupt handlers. This varies depending on * the architecture. */ fec_request_intrs(dev); +#endif fecp->fec_grp_hash_table_high = 0; fecp->fec_grp_hash_table_low = 0; @@ -2237,8 +2252,6 @@ int __init fec_enet_init(struct net_device *dev) fecp->fec_hash_table_low = 0; #endif - dev->base_addr = (unsigned long)fecp; - /* The FEC Ethernet specific entries in the device structure. */ dev->open = fec_enet_open; dev->hard_start_xmit = fec_enet_start_xmit; @@ -2252,7 +2265,20 @@ int __init fec_enet_init(struct net_device *dev) mii_free = mii_cmds; /* setup MII interface */ +#ifdef FEC_LEGACY fec_set_mii(dev, fep); +#else + fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04; + fecp->fec_x_cntrl = 0x00; + + /* + * Set MII speed to 2.5 MHz + */ + fep->phy_speed = ((((clk_get_rate(fep->clk) / 2 + 4999999) + / 2500000) / 2) & 0x3F) << 1; + fecp->fec_mii_speed = fep->phy_speed; + fec_restart(dev, 0); +#endif /* Clear and enable interrupts */ fecp->fec_ievent = 0xffc00000; @@ -2265,7 +2291,6 @@ int __init fec_enet_init(struct net_device *dev) fep->phy_addr = 0; mii_queue(dev, mk_mii_read(MII_REG_PHYIR1), mii_discover_phy); - index++; return 0; } @@ -2417,6 +2442,7 @@ fec_stop(struct net_device *dev) fecp->fec_mii_speed = fep->phy_speed; } +#ifdef FEC_LEGACY static int __init fec_enet_module_init(void) { struct net_device *dev; @@ -2428,7 +2454,8 @@ static int __init fec_enet_module_init(void) dev = alloc_etherdev(sizeof(struct fec_enet_private)); if (!dev) return -ENOMEM; - err = fec_enet_init(dev); + dev->base_addr = (unsigned long)fec_hw[i]; + err = fec_enet_init(dev, i); if (err) { free_netdev(dev); continue; @@ -2443,6 +2470,170 @@ static int __init fec_enet_module_init(void) } return 0; } +#else + +static int __devinit +fec_probe(struct platform_device *pdev) +{ + struct fec_enet_private *fep; + struct net_device *ndev; + int i, irq, ret = 0; + struct resource *r; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) + return -ENXIO; + + r = request_mem_region(r->start, resource_size(r), pdev->name); + if (!r) + return -EBUSY; + + /* Init network device */ + ndev = alloc_etherdev(sizeof(struct fec_enet_private)); + if (!ndev) + return -ENOMEM; + + SET_NETDEV_DEV(ndev, &pdev->dev); + + /* setup board info structure */ + fep = netdev_priv(ndev); + memset(fep, 0, sizeof(*fep)); + + ndev->base_addr = (unsigned long)ioremap(r->start, resource_size(r)); + + if (!ndev->base_addr) { + ret = -ENOMEM; + goto failed_ioremap; + } + + platform_set_drvdata(pdev, ndev); + + /* This device has up to three irqs on some platforms */ + for (i = 0; i < 3; i++) { + irq = platform_get_irq(pdev, i); + if (i && irq < 0) + break; + ret = request_irq(irq, fec_enet_interrupt, IRQF_DISABLED, pdev->name, ndev); + if (ret) { + while (i >= 0) { + irq = platform_get_irq(pdev, i); + free_irq(irq, ndev); + i--; + } + goto failed_irq; + } + } + + fep->clk = clk_get(&pdev->dev, "fec_clk"); + if (IS_ERR(fep->clk)) { + ret = PTR_ERR(fep->clk); + goto failed_clk; + } + clk_enable(fep->clk); + + ret = fec_enet_init(ndev, 0); + if (ret) + goto failed_init; + + ret = register_netdev(ndev); + if (ret) + goto failed_register; + + return 0; + +failed_register: +failed_init: + clk_disable(fep->clk); + clk_put(fep->clk); +failed_clk: + for (i = 0; i < 3; i++) { + irq = platform_get_irq(pdev, i); + if (irq > 0) + free_irq(irq, ndev); + } +failed_irq: + iounmap((void __iomem *)ndev->base_addr); +failed_ioremap: + free_netdev(ndev); + + return ret; +} + +static int __devexit +fec_drv_remove(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct fec_enet_private *fep = netdev_priv(ndev); + + platform_set_drvdata(pdev, NULL); + + fec_stop(ndev); + clk_disable(fep->clk); + clk_put(fep->clk); + iounmap((void __iomem *)ndev->base_addr); + unregister_netdev(ndev); + free_netdev(ndev); + return 0; +} + +static int +fec_suspend(struct platform_device *dev, pm_message_t state) +{ + struct net_device *ndev = platform_get_drvdata(dev); + struct fec_enet_private *fep; + + if (ndev) { + fep = netdev_priv(ndev); + if (netif_running(ndev)) { + netif_device_detach(ndev); + fec_stop(ndev); + } + } + return 0; +} + +static int +fec_resume(struct platform_device *dev) +{ + struct net_device *ndev = platform_get_drvdata(dev); + + if (ndev) { + if (netif_running(ndev)) { + fec_enet_init(ndev, 0); + netif_device_attach(ndev); + } + } + return 0; +} + +static struct platform_driver fec_driver = { + .driver = { + .name = "fec", + .owner = THIS_MODULE, + }, + .probe = fec_probe, + .remove = __devexit_p(fec_drv_remove), + .suspend = fec_suspend, + .resume = fec_resume, +}; + +static int __init +fec_enet_module_init(void) +{ + printk(KERN_INFO "FEC Ethernet Driver\n"); + + return platform_driver_register(&fec_driver); +} + +static void __exit +fec_enet_cleanup(void) +{ + platform_driver_unregister(&fec_driver); +} + +module_exit(fec_enet_cleanup); + +#endif /* FEC_LEGACY */ module_init(fec_enet_module_init); -- GitLab From eefef1cf7653cd4e0aaf743c00ae8345086cdc01 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 1 Feb 2009 01:04:33 -0800 Subject: [PATCH 1098/4982] net: add ARP notify option for devices This adds another inet device option to enable gratuitous ARP when device is brought up or address change. This is handy for clusters or virtualization. Signed-off-by: Stephen Hemminger Signed-off-by: Jeremy Fitzhardinge Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 6 ++++++ include/linux/inetdevice.h | 1 + include/linux/sysctl.h | 1 + kernel/sysctl_check.c | 1 + net/ipv4/devinet.c | 9 +++++++++ 5 files changed, 18 insertions(+) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index c7712787933..ff3f219ee4d 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -782,6 +782,12 @@ arp_ignore - INTEGER The max value from conf/{all,interface}/arp_ignore is used when ARP request is received on the {interface} +arp_notify - BOOLEAN + Define mode for notification of address and device changes. + 0 - (default): do nothing + 1 - Generate gratuitous arp replies when device is brought up + or hardware address changes. + arp_accept - BOOLEAN Define behavior when gratuitous arp replies are received: 0 - drop gratuitous arp frames diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index 06fcdb45106..acef2a770b6 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h @@ -108,6 +108,7 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev) #define IN_DEV_ARPFILTER(in_dev) IN_DEV_ORCONF((in_dev), ARPFILTER) #define IN_DEV_ARP_ANNOUNCE(in_dev) IN_DEV_MAXCONF((in_dev), ARP_ANNOUNCE) #define IN_DEV_ARP_IGNORE(in_dev) IN_DEV_MAXCONF((in_dev), ARP_IGNORE) +#define IN_DEV_ARP_NOTIFY(in_dev) IN_DEV_MAXCONF((in_dev), ARP_NOTIFY) struct in_ifaddr { diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 39d471d1163..e76d3b22a46 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -490,6 +490,7 @@ enum NET_IPV4_CONF_ARP_IGNORE=19, NET_IPV4_CONF_PROMOTE_SECONDARIES=20, NET_IPV4_CONF_ARP_ACCEPT=21, + NET_IPV4_CONF_ARP_NOTIFY=22, __NET_IPV4_CONF_MAX }; diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c index fafeb48f27c..b38423ca711 100644 --- a/kernel/sysctl_check.c +++ b/kernel/sysctl_check.c @@ -219,6 +219,7 @@ static const struct trans_ctl_table trans_net_ipv4_conf_vars_table[] = { { NET_IPV4_CONF_ARP_IGNORE, "arp_ignore" }, { NET_IPV4_CONF_PROMOTE_SECONDARIES, "promote_secondaries" }, { NET_IPV4_CONF_ARP_ACCEPT, "arp_accept" }, + { NET_IPV4_CONF_ARP_NOTIFY, "arp_notify" }, {} }; diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 309997edc8a..d519a6a6672 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1075,6 +1075,14 @@ static int inetdev_event(struct notifier_block *this, unsigned long event, } } ip_mc_up(in_dev); + /* fall through */ + case NETDEV_CHANGEADDR: + if (IN_DEV_ARP_NOTIFY(in_dev)) + arp_send(ARPOP_REQUEST, ETH_P_ARP, + in_dev->ifa_list->ifa_address, + dev, + in_dev->ifa_list->ifa_address, + NULL, dev->dev_addr, NULL); break; case NETDEV_DOWN: ip_mc_down(in_dev); @@ -1439,6 +1447,7 @@ static struct devinet_sysctl_table { DEVINET_SYSCTL_RW_ENTRY(ARP_ANNOUNCE, "arp_announce"), DEVINET_SYSCTL_RW_ENTRY(ARP_IGNORE, "arp_ignore"), DEVINET_SYSCTL_RW_ENTRY(ARP_ACCEPT, "arp_accept"), + DEVINET_SYSCTL_RW_ENTRY(ARP_NOTIFY, "arp_notify"), DEVINET_SYSCTL_FLUSHING_ENTRY(NOXFRM, "disable_xfrm"), DEVINET_SYSCTL_FLUSHING_ENTRY(NOPOLICY, "disable_policy"), -- GitLab From b00355db3f88d96810a60011a30cfb2c3469409d Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Sun, 1 Feb 2009 01:12:42 -0800 Subject: [PATCH 1099/4982] pkt_sched: sch_hfsc: sch_htb: Add non-work-conserving warning handler. Patrick McHardy suggested: > How about making this flag and the warning message (in a out-of-line > function) globally available? Other qdiscs (f.i. HFSC) can't deal with > inner non-work-conserving qdiscs as well. This patch uses qdisc->flags field of "suspected" child qdisc. Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- include/net/pkt_sched.h | 1 + include/net/sch_generic.h | 7 ++++--- net/sched/sch_api.c | 11 +++++++++++ net/sched/sch_hfsc.c | 6 ++---- net/sched/sch_htb.c | 9 +-------- 5 files changed, 19 insertions(+), 15 deletions(-) diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index 4082f39f507..e37fe3129c1 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -85,6 +85,7 @@ extern struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct nlattr *tab); extern void qdisc_put_rtab(struct qdisc_rate_table *tab); extern void qdisc_put_stab(struct qdisc_size_table *tab); +extern void qdisc_warn_nonwc(char *txt, struct Qdisc *qdisc); extern void __qdisc_run(struct Qdisc *q); diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index f8c47429044..3d78a4d2246 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -42,9 +42,10 @@ struct Qdisc int (*enqueue)(struct sk_buff *skb, struct Qdisc *dev); struct sk_buff * (*dequeue)(struct Qdisc *dev); unsigned flags; -#define TCQ_F_BUILTIN 1 -#define TCQ_F_THROTTLED 2 -#define TCQ_F_INGRESS 4 +#define TCQ_F_BUILTIN 1 +#define TCQ_F_THROTTLED 2 +#define TCQ_F_INGRESS 4 +#define TCQ_F_WARN_NONWC (1 << 16) int padded; struct Qdisc_ops *ops; struct qdisc_size_table *stab; diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 0fc4a18fd96..32009793307 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -444,6 +444,17 @@ out: } EXPORT_SYMBOL(qdisc_calculate_pkt_len); +void qdisc_warn_nonwc(char *txt, struct Qdisc *qdisc) +{ + if (!(qdisc->flags & TCQ_F_WARN_NONWC)) { + printk(KERN_WARNING + "%s: %s qdisc %X: is non-work-conserving?\n", + txt, qdisc->ops->id, qdisc->handle >> 16); + qdisc->flags |= TCQ_F_WARN_NONWC; + } +} +EXPORT_SYMBOL(qdisc_warn_nonwc); + static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer) { struct qdisc_watchdog *wd = container_of(timer, struct qdisc_watchdog, diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 45c31b1a4e1..74226b26552 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -887,8 +887,7 @@ qdisc_peek_len(struct Qdisc *sch) skb = sch->ops->peek(sch); if (skb == NULL) { - if (net_ratelimit()) - printk("qdisc_peek_len: non work-conserving qdisc ?\n"); + qdisc_warn_nonwc("qdisc_peek_len", sch); return 0; } len = qdisc_pkt_len(skb); @@ -1642,8 +1641,7 @@ hfsc_dequeue(struct Qdisc *sch) skb = qdisc_dequeue_peeked(cl->qdisc); if (skb == NULL) { - if (net_ratelimit()) - printk("HFSC: Non-work-conserving qdisc ?\n"); + qdisc_warn_nonwc("HFSC", cl->qdisc); return NULL; } diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 2f0f0b04d3f..77ff510ef8a 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -114,8 +114,6 @@ struct htb_class { struct tcf_proto *filter_list; int filter_cnt; - int warned; /* only one warning about non work conserving .. */ - /* token bucket parameters */ struct qdisc_rate_table *rate; /* rate table of the class itself */ struct qdisc_rate_table *ceil; /* ceiling rate (limits borrows too) */ @@ -809,13 +807,8 @@ next: skb = cl->un.leaf.q->dequeue(cl->un.leaf.q); if (likely(skb != NULL)) break; - if (!cl->warned) { - printk(KERN_WARNING - "htb: class %X isn't work conserving ?!\n", - cl->common.classid); - cl->warned = 1; - } + qdisc_warn_nonwc("htb", cl->un.leaf.q); htb_next_rb_node((level ? cl->parent->un.inner.ptr : q-> ptr[0]) + prio); cl = htb_lookup_leaf(q->row[level] + prio, prio, -- GitLab From e82181de5ef4648074765912d2d82d6bd60115eb Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Sun, 1 Feb 2009 01:13:05 -0800 Subject: [PATCH 1100/4982] pkt_sched: sch_htb: Warn on too many events. Let's get some info on possible config problems. This patch brings back an old warning, but is printed only once now. With feedback from Patrick McHardy Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- net/sched/sch_htb.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 77ff510ef8a..826f9214526 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -153,6 +153,9 @@ struct htb_sched { int direct_qlen; /* max qlen of above */ long direct_pkts; + +#define HTB_WARN_TOOMANYEVENTS 0x1 + unsigned int warned; /* only one warning */ }; /* find class in global hash table using given handle */ @@ -685,6 +688,10 @@ static psched_time_t htb_do_events(struct htb_sched *q, int level, htb_add_to_wait_tree(q, cl, diff); } /* too much load - let's continue on next jiffie (including above) */ + if (!(q->warned & HTB_WARN_TOOMANYEVENTS)) { + printk(KERN_WARNING "htb: too many events!\n"); + q->warned |= HTB_WARN_TOOMANYEVENTS; + } return q->now + 2 * PSCHED_TICKS_PER_SEC / HZ; } -- GitLab From 1224736d97e83367bb66e29c2bee0f570f09db3e Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Sun, 1 Feb 2009 01:13:22 -0800 Subject: [PATCH 1101/4982] pkt_sched: sch_htb: Use workqueue to schedule after too many events. Patrick McHardy suggested using a workqueue instead of hrtimers to trigger netif_schedule() when there is a problem with setting exact time of this event: 'The differnce - yeah, it shouldn't make much, mainly wake up the qdisc earlier (but not too early) after "too many events" occured _and_ no further enqueue events wake up the qdisc anyways.' Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- net/sched/sch_htb.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 826f9214526..355974f610c 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -156,6 +157,7 @@ struct htb_sched { #define HTB_WARN_TOOMANYEVENTS 0x1 unsigned int warned; /* only one warning */ + struct work_struct work; }; /* find class in global hash table using given handle */ @@ -659,7 +661,7 @@ static void htb_charge_class(struct htb_sched *q, struct htb_class *cl, * htb_do_events - make mode changes to classes at the level * * Scans event queue for pending events and applies them. Returns time of - * next pending event (0 for no event in pq). + * next pending event (0 for no event in pq, q->now for too many events). * Note: Applied are events whose have cl->pq_key <= q->now. */ static psched_time_t htb_do_events(struct htb_sched *q, int level, @@ -687,12 +689,14 @@ static psched_time_t htb_do_events(struct htb_sched *q, int level, if (cl->cmode != HTB_CAN_SEND) htb_add_to_wait_tree(q, cl, diff); } - /* too much load - let's continue on next jiffie (including above) */ + + /* too much load - let's continue after a break for scheduling */ if (!(q->warned & HTB_WARN_TOOMANYEVENTS)) { printk(KERN_WARNING "htb: too many events!\n"); q->warned |= HTB_WARN_TOOMANYEVENTS; } - return q->now + 2 * PSCHED_TICKS_PER_SEC / HZ; + + return q->now; } /* Returns class->node+prio from id-tree where classe's id is >= id. NULL @@ -892,7 +896,10 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch) } } sch->qstats.overlimits++; - qdisc_watchdog_schedule(&q->watchdog, next_event); + if (likely(next_event > q->now)) + qdisc_watchdog_schedule(&q->watchdog, next_event); + else + schedule_work(&q->work); fin: return skb; } @@ -962,6 +969,14 @@ static const struct nla_policy htb_policy[TCA_HTB_MAX + 1] = { [TCA_HTB_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, }; +static void htb_work_func(struct work_struct *work) +{ + struct htb_sched *q = container_of(work, struct htb_sched, work); + struct Qdisc *sch = q->watchdog.qdisc; + + __netif_schedule(qdisc_root(sch)); +} + static int htb_init(struct Qdisc *sch, struct nlattr *opt) { struct htb_sched *q = qdisc_priv(sch); @@ -996,6 +1011,7 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt) INIT_LIST_HEAD(q->drops + i); qdisc_watchdog_init(&q->watchdog, sch); + INIT_WORK(&q->work, htb_work_func); skb_queue_head_init(&q->direct_queue); q->direct_qlen = qdisc_dev(sch)->tx_queue_len; @@ -1188,7 +1204,6 @@ static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl) kfree(cl); } -/* always caled under BH & queue lock */ static void htb_destroy(struct Qdisc *sch) { struct htb_sched *q = qdisc_priv(sch); @@ -1196,6 +1211,7 @@ static void htb_destroy(struct Qdisc *sch) struct htb_class *cl; unsigned int i; + cancel_work_sync(&q->work); qdisc_watchdog_cancel(&q->watchdog); /* This line used to be after htb_destroy_class call below and surprisingly it worked in 2.4. But it must precede it -- GitLab From 2f21bdd3542838dc5513a585a32aa13f01b019e7 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Sun, 1 Feb 2009 01:18:23 -0800 Subject: [PATCH 1102/4982] ixgbe: Add 82598 support for BX mezzanine devices Add the device ID for BX devices using the 82598 MAC. Signed-off-by: Don Skidmore Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_82598.c | 4 +++- drivers/net/ixgbe/ixgbe_ethtool.c | 8 ++++++++ drivers/net/ixgbe/ixgbe_main.c | 2 ++ drivers/net/ixgbe/ixgbe_type.h | 1 + 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 6c7ddb96ed0..dffe7f062c8 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -214,7 +214,7 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw) /* Media type for I82598 is based on device ID */ switch (hw->device_id) { case IXGBE_DEV_ID_82598: - /* Default device ID is mezzanine card KX/KX4 */ + case IXGBE_DEV_ID_82598_BX: media_type = ixgbe_media_type_backplane; break; case IXGBE_DEV_ID_82598AF_DUAL_PORT: @@ -1011,6 +1011,8 @@ static s32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw) physical_layer = (IXGBE_PHYSICAL_LAYER_10GBASE_KX4 | IXGBE_PHYSICAL_LAYER_1000BASE_KX); break; + case IXGBE_DEV_ID_82598_BX: + physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_BX; case IXGBE_DEV_ID_82598EB_CX4: case IXGBE_DEV_ID_82598_CX4_DUAL_PORT: physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4; diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 444200fa31e..69eda891f59 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -141,6 +141,14 @@ static int ixgbe_get_settings(struct net_device *netdev, ADVERTISED_FIBRE); ecmd->port = PORT_FIBRE; break; + case IXGBE_DEV_ID_82598_BX: + ecmd->supported = (SUPPORTED_1000baseT_Full | + SUPPORTED_FIBRE); + ecmd->advertising = (ADVERTISED_1000baseT_Full | + ADVERTISED_FIBRE); + ecmd->port = PORT_FIBRE; + ecmd->autoneg = AUTONEG_DISABLE; + break; } } else { ecmd->supported |= SUPPORTED_FIBRE; diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 88615f69976..82afc606c23 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -84,6 +84,8 @@ static struct pci_device_id ixgbe_pci_tbl[] = { board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_SFP_LOM), board_82598 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_BX), + board_82598 }, /* required last entry */ {0, } diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index e43f0c7c341..883ff821153 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -35,6 +35,7 @@ /* Device IDs */ #define IXGBE_DEV_ID_82598 0x10B6 +#define IXGBE_DEV_ID_82598_BX 0x1508 #define IXGBE_DEV_ID_82598AF_DUAL_PORT 0x10C6 #define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7 #define IXGBE_DEV_ID_82598EB_SFP_LOM 0x10DB -- GitLab From eb7f139ce523bfe03b1628c66d3e1d50f3c07196 Mon Sep 17 00:00:00 2001 From: Peter P Waskiewicz Jr Date: Sun, 1 Feb 2009 01:18:58 -0800 Subject: [PATCH 1103/4982] ixgbe: Refactor MSI-X allocation mechanism Our current MSI-X allocation mechanism does not support new hardware at all. It also isn't getting the actual number of supported MSI-X vectors from the device. This patch allows the number of MSI-X vectors to be specific to a device, plus it gets the number of MSI-X vectors available from PCIe configuration space. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe.h | 9 +++++++-- drivers/net/ixgbe/ixgbe_82598.c | 22 ++++++++++++++++++++++ drivers/net/ixgbe/ixgbe_main.c | 9 ++++++++- drivers/net/ixgbe/ixgbe_type.h | 5 +++++ 4 files changed, 42 insertions(+), 3 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 6ac361a4b8a..341d8b555f1 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -204,9 +204,13 @@ struct ixgbe_q_vector { #define OTHER_VECTOR 1 #define NON_Q_VECTORS (OTHER_VECTOR) -#define MAX_MSIX_Q_VECTORS 16 +#define MAX_MSIX_VECTORS_82598 18 +#define MAX_MSIX_Q_VECTORS_82598 16 + +#define MAX_MSIX_Q_VECTORS MAX_MSIX_Q_VECTORS_82598 +#define MAX_MSIX_COUNT MAX_MSIX_VECTORS_82598 + #define MIN_MSIX_Q_VECTORS 2 -#define MAX_MSIX_COUNT (MAX_MSIX_Q_VECTORS + NON_Q_VECTORS) #define MIN_MSIX_COUNT (MIN_MSIX_Q_VECTORS + NON_Q_VECTORS) /* board specific private data structure */ @@ -244,6 +248,7 @@ struct ixgbe_adapter { u64 hw_csum_rx_good; u64 non_eop_descs; int num_msix_vectors; + int max_msix_q_vectors; /* true count of q_vectors for device */ struct ixgbe_ring_feature ring_feature[3]; struct msix_entry *msix_entries; diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index dffe7f062c8..7fb4b86f869 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -49,6 +49,27 @@ static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw, static s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset, u8 *eeprom_data); +/** + * ixgbe_get_pcie_msix_count_82598 - Gets MSI-X vector count + * @hw: pointer to hardware structure + * + * Read PCIe configuration space, and get the MSI-X vector count from + * the capabilities table. + **/ +u16 ixgbe_get_pcie_msix_count_82598(struct ixgbe_hw *hw) +{ + struct ixgbe_adapter *adapter = hw->back; + u16 msix_count; + pci_read_config_word(adapter->pdev, IXGBE_PCIE_MSIX_82598_CAPS, + &msix_count); + msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK; + + /* MSI-X count is zero-based in HW, so increment to give proper value */ + msix_count++; + + return msix_count; +} + /** */ static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw) @@ -106,6 +127,7 @@ static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw) mac->num_rar_entries = IXGBE_82598_RAR_ENTRIES; mac->max_rx_queues = IXGBE_82598_MAX_RX_QUEUES; mac->max_tx_queues = IXGBE_82598_MAX_TX_QUEUES; + mac->max_msix_vectors = ixgbe_get_pcie_msix_count_82598(hw); out: return ret_val; diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 82afc606c23..7bbafa3ebbe 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2421,7 +2421,13 @@ static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter, ixgbe_set_num_queues(adapter); } else { adapter->flags |= IXGBE_FLAG_MSIX_ENABLED; /* Woot! */ - adapter->num_msix_vectors = vectors; + /* + * Adjust for only the vectors we'll use, which is minimum + * of max_msix_q_vectors + NON_Q_VECTORS, or the number of + * vectors we were allocated. + */ + adapter->num_msix_vectors = min(vectors, + adapter->max_msix_q_vectors + NON_Q_VECTORS); } } @@ -2746,6 +2752,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) adapter->ring_feature[RING_F_RSS].indices = rss; adapter->flags |= IXGBE_FLAG_RSS_ENABLED; adapter->ring_feature[RING_F_DCB].indices = IXGBE_MAX_DCB_INDICES; + adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82598; #ifdef CONFIG_IXGBE_DCB /* Configure DCB traffic classes */ diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 883ff821153..0d1d1d20aff 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -821,6 +821,10 @@ #define IXGBE_FW_PTR 0x0F #define IXGBE_PBANUM0_PTR 0x15 #define IXGBE_PBANUM1_PTR 0x16 +#define IXGBE_PCIE_MSIX_82598_CAPS 0x62 + +/* MSI-X capability fields masks */ +#define IXGBE_PCIE_MSIX_TBL_SZ_MASK 0x7FF /* Legacy EEPROM word offsets */ #define IXGBE_ISCSI_BOOT_CAPS 0x0033 @@ -1451,6 +1455,7 @@ struct ixgbe_mac_info { u32 num_rar_entries; u32 max_tx_queues; u32 max_rx_queues; + u32 max_msix_vectors; u32 link_attach_type; u32 link_mode_select; bool link_settings_loaded; -- GitLab From 3efac5a0012979ae236fe1247b773317ef5f1c88 Mon Sep 17 00:00:00 2001 From: Peter P Waskiewicz Jr Date: Sun, 1 Feb 2009 01:19:20 -0800 Subject: [PATCH 1104/4982] ixgbe: Update copyright dates, bump the driver version number New year, new copyright date ranges. Also bump the driver version number to reflect many of the recent changes. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/Makefile | 2 +- drivers/net/ixgbe/ixgbe.h | 2 +- drivers/net/ixgbe/ixgbe_82598.c | 2 +- drivers/net/ixgbe/ixgbe_common.c | 2 +- drivers/net/ixgbe/ixgbe_common.h | 2 +- drivers/net/ixgbe/ixgbe_dcb.c | 2 +- drivers/net/ixgbe/ixgbe_dcb.h | 2 +- drivers/net/ixgbe/ixgbe_dcb_82598.c | 2 +- drivers/net/ixgbe/ixgbe_dcb_82598.h | 2 +- drivers/net/ixgbe/ixgbe_dcb_nl.c | 2 +- drivers/net/ixgbe/ixgbe_ethtool.c | 2 +- drivers/net/ixgbe/ixgbe_main.c | 6 +++--- drivers/net/ixgbe/ixgbe_phy.c | 2 +- drivers/net/ixgbe/ixgbe_phy.h | 2 +- drivers/net/ixgbe/ixgbe_type.h | 2 +- 15 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/net/ixgbe/Makefile b/drivers/net/ixgbe/Makefile index 6e7ef765bcd..f6061950f5d 100644 --- a/drivers/net/ixgbe/Makefile +++ b/drivers/net/ixgbe/Makefile @@ -1,7 +1,7 @@ ################################################################################ # # Intel 10 Gigabit PCI Express Linux driver -# Copyright(c) 1999 - 2007 Intel Corporation. +# Copyright(c) 1999 - 2009 Intel Corporation. # # This program is free software; you can redistribute it and/or modify it # under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 341d8b555f1..0ea791ae0d1 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2008 Intel Corporation. + Copyright(c) 1999 - 2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 7fb4b86f869..8e7315e0a7f 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2008 Intel Corporation. + Copyright(c) 1999 - 2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index f67c68404bb..05f0e872947 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2008 Intel Corporation. + Copyright(c) 1999 - 2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ixgbe/ixgbe_common.h index 192f8d01291..0b5ba575580 100644 --- a/drivers/net/ixgbe/ixgbe_common.h +++ b/drivers/net/ixgbe/ixgbe_common.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2008 Intel Corporation. + Copyright(c) 1999 - 2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_dcb.c b/drivers/net/ixgbe/ixgbe_dcb.c index e2e28ac63de..2a60c89ab34 100644 --- a/drivers/net/ixgbe/ixgbe_dcb.c +++ b/drivers/net/ixgbe/ixgbe_dcb.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2007 Intel Corporation. + Copyright(c) 1999 - 2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_dcb.h b/drivers/net/ixgbe/ixgbe_dcb.h index 75f6efe1e36..0da5c6d5bca 100644 --- a/drivers/net/ixgbe/ixgbe_dcb.h +++ b/drivers/net/ixgbe/ixgbe_dcb.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2007 Intel Corporation. + Copyright(c) 1999 - 2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ixgbe/ixgbe_dcb_82598.c index 2c046b0b5d2..56032114893 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82598.c +++ b/drivers/net/ixgbe/ixgbe_dcb_82598.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2007 Intel Corporation. + Copyright(c) 1999 - 2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.h b/drivers/net/ixgbe/ixgbe_dcb_82598.h index 1e6a313719d..ebbe53c352a 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82598.h +++ b/drivers/net/ixgbe/ixgbe_dcb_82598.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2007 Intel Corporation. + Copyright(c) 1999 - 2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index 4129976953f..dd9d1d63a59 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2008 Intel Corporation. + Copyright(c) 1999 - 2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 69eda891f59..14e661e0a25 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2008 Intel Corporation. + Copyright(c) 1999 - 2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 7bbafa3ebbe..ed8d14163c1 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2008 Intel Corporation. + Copyright(c) 1999 - 2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -47,9 +47,9 @@ char ixgbe_driver_name[] = "ixgbe"; static const char ixgbe_driver_string[] = "Intel(R) 10 Gigabit PCI Express Network Driver"; -#define DRV_VERSION "1.3.30-k2" +#define DRV_VERSION "1.3.56-k2" const char ixgbe_driver_version[] = DRV_VERSION; -static char ixgbe_copyright[] = "Copyright (c) 1999-2007 Intel Corporation."; +static char ixgbe_copyright[] = "Copyright (c) 1999-2009 Intel Corporation."; static const struct ixgbe_info *ixgbe_info_tbl[] = { [board_82598] = &ixgbe_82598_info, diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index 5a8669aedf6..77ec26f5650 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2008 Intel Corporation. + Copyright(c) 1999 - 2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_phy.h b/drivers/net/ixgbe/ixgbe_phy.h index 43a97bc420f..539a3061eb2 100644 --- a/drivers/net/ixgbe/ixgbe_phy.h +++ b/drivers/net/ixgbe/ixgbe_phy.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2008 Intel Corporation. + Copyright(c) 1999 - 2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 0d1d1d20aff..c49ba8a17f1 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2008 Intel Corporation. + Copyright(c) 1999 - 2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, -- GitLab From ad0f9904444de1309dedd2b9e365cae8af77d9b1 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 1 Feb 2009 01:24:55 -0800 Subject: [PATCH 1105/4982] gro: Fix handling of imprecisely split packets The commit 89a1b249edcf9be884e71f92df84d48355c576aa (gro: Avoid copying headers of unmerged packets) only worked for packets which are either completely linear, completely non-linear, or packets which exactly split at the boundary between headers and payload. Anything else would cause bits in the header to go missing if the packet is held by GRO. This may have broken drivers such as ixgbe. This patch fixes the places that assumed or only worked with the above cases. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/core/dev.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index ec5be1c7f2f..220f52a1001 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -217,7 +217,7 @@ static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex) static inline void *skb_gro_mac_header(struct sk_buff *skb) { - return skb_headlen(skb) ? skb_mac_header(skb) : + return skb_mac_header(skb) < skb->data ? skb_mac_header(skb) : page_address(skb_shinfo(skb)->frags[0].page) + skb_shinfo(skb)->frags[0].page_offset; } @@ -2469,11 +2469,19 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) napi->gro_list = skb; ret = GRO_HELD; +pull: + if (unlikely(!pskb_may_pull(skb, skb_gro_offset(skb)))) { + if (napi->gro_list == skb) + napi->gro_list = skb->next; + ret = GRO_DROP; + } + ok: return ret; normal: - return GRO_NORMAL; + ret = GRO_NORMAL; + goto pull; } EXPORT_SYMBOL(dev_gro_receive); @@ -2589,14 +2597,10 @@ EXPORT_SYMBOL(napi_fraginfo_skb); int napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb, int ret) { int err = NET_RX_SUCCESS; - int may; switch (ret) { case GRO_NORMAL: case GRO_HELD: - may = pskb_may_pull(skb, skb_gro_offset(skb)); - BUG_ON(!may); - skb->protocol = eth_type_trans(skb, napi->dev); if (ret == GRO_NORMAL) -- GitLab From 5add300975cf36b1bd30c461105bb938da260f14 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 1 Feb 2009 01:40:17 -0800 Subject: [PATCH 1106/4982] inet: Fix virt-manager regression due to bind(0) changes. From: Stephen Hemminger Fix regression introduced by a9d8f9110d7e953c2f2b521087a4179677843c2a ("inet: Allowing more than 64k connections and heavily optimize bind(0) time.") Based upon initial patches and feedback from Evegniy Polyakov and Eric Dumazet. From Eric Dumazet: -------------------- Also there might be a problem at line 175 if (sk->sk_reuse && sk->sk_state != TCP_LISTEN && --attempts >= 0) { spin_unlock(&head->lock); goto again; If we entered inet_csk_get_port() with a non null snum, we can "goto again" while it was not expected. -------------------- Signed-off-by: David S. Miller --- net/ipv4/inet_connection_sock.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index df8e72f0747..9bc6a187bdc 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -172,7 +172,8 @@ tb_found: } else { ret = 1; if (inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb)) { - if (sk->sk_reuse && sk->sk_state != TCP_LISTEN && --attempts >= 0) { + if (sk->sk_reuse && sk->sk_state != TCP_LISTEN && + smallest_size != -1 && --attempts >= 0) { spin_unlock(&head->lock); goto again; } -- GitLab From 24dd1fa184595ff095a92de807fdf029b2632673 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 1 Feb 2009 12:31:33 -0800 Subject: [PATCH 1107/4982] net: move bsockets outside of read only beginning of struct inet_hashinfo And switch bsockets to atomic_t since it might be changed in parallel. Signed-off-by: Eric Dumazet Acked-by: Evgeniy Polyakov Signed-off-by: David S. Miller --- include/net/inet_hashtables.h | 3 ++- net/ipv4/inet_connection_sock.c | 2 +- net/ipv4/inet_hashtables.c | 5 +++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index 8d98dc76bd7..a44e2248b2e 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h @@ -134,7 +134,7 @@ struct inet_hashinfo { struct inet_bind_hashbucket *bhash; unsigned int bhash_size; - int bsockets; + /* 4 bytes hole on 64 bit */ struct kmem_cache *bind_bucket_cachep; @@ -151,6 +151,7 @@ struct inet_hashinfo { struct inet_listen_hashbucket listening_hash[INET_LHTABLE_SIZE] ____cacheline_aligned_in_smp; + atomic_t bsockets; }; static inline struct inet_ehash_bucket *inet_ehash_bucket( diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 9bc6a187bdc..22cd19ee44e 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -119,7 +119,7 @@ again: (tb->num_owners < smallest_size || smallest_size == -1)) { smallest_size = tb->num_owners; smallest_rover = rover; - if (hashinfo->bsockets > (high - low) + 1) { + if (atomic_read(&hashinfo->bsockets) > (high - low) + 1) { spin_unlock(&head->lock); snum = smallest_rover; goto have_snum; diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index d7b6178bf48..625cc5f64c9 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -62,7 +62,7 @@ void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb, { struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; - hashinfo->bsockets++; + atomic_inc(&hashinfo->bsockets); inet_sk(sk)->num = snum; sk_add_bind_node(sk, &tb->owners); @@ -81,7 +81,7 @@ static void __inet_put_port(struct sock *sk) struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash]; struct inet_bind_bucket *tb; - hashinfo->bsockets--; + atomic_dec(&hashinfo->bsockets); spin_lock(&head->lock); tb = inet_csk(sk)->icsk_bind_hash; @@ -532,6 +532,7 @@ void inet_hashinfo_init(struct inet_hashinfo *h) { int i; + atomic_set(&h->bsockets, 0); for (i = 0; i < INET_LHTABLE_SIZE; i++) { spin_lock_init(&h->listening_hash[i].lock); INIT_HLIST_NULLS_HEAD(&h->listening_hash[i].head, -- GitLab From 5626d3e86141390c8efc7bcb929b6a4b58b00480 Mon Sep 17 00:00:00 2001 From: James Morris Date: Fri, 30 Jan 2009 10:05:06 +1100 Subject: [PATCH 1108/4982] selinux: remove hooks which simply defer to capabilities Remove SELinux hooks which do nothing except defer to the capabilites hooks (or in one case, replicates the function). Signed-off-by: James Morris Acked-by: Stephen Smalley --- security/selinux/hooks.c | 68 ++++++---------------------------------- 1 file changed, 10 insertions(+), 58 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index d9604794a4d..a69d6f8970c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1892,6 +1892,16 @@ static int selinux_capset(struct cred *new, const struct cred *old, return cred_has_perm(old, new, PROCESS__SETCAP); } +/* + * (This comment used to live with the selinux_task_setuid hook, + * which was removed). + * + * Since setuid only affects the current process, and since the SELinux + * controls are not based on the Linux identity attributes, SELinux does not + * need to control this operation. However, SELinux does control the use of + * the CAP_SETUID and CAP_SETGID capabilities using the capable hook. + */ + static int selinux_capable(struct task_struct *tsk, const struct cred *cred, int cap, int audit) { @@ -2909,16 +2919,6 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t return len; } -static int selinux_inode_need_killpriv(struct dentry *dentry) -{ - return secondary_ops->inode_need_killpriv(dentry); -} - -static int selinux_inode_killpriv(struct dentry *dentry) -{ - return secondary_ops->inode_killpriv(dentry); -} - static void selinux_inode_getsecid(const struct inode *inode, u32 *secid) { struct inode_security_struct *isec = inode->i_security; @@ -3288,29 +3288,6 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) return 0; } -static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) -{ - /* Since setuid only affects the current process, and - since the SELinux controls are not based on the Linux - identity attributes, SELinux does not need to control - this operation. However, SELinux does control the use - of the CAP_SETUID and CAP_SETGID capabilities using the - capable hook. */ - return 0; -} - -static int selinux_task_fix_setuid(struct cred *new, const struct cred *old, - int flags) -{ - return secondary_ops->task_fix_setuid(new, old, flags); -} - -static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags) -{ - /* See the comment for setuid above. */ - return 0; -} - static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) { return current_has_perm(p, PROCESS__SETPGID); @@ -3331,12 +3308,6 @@ static void selinux_task_getsecid(struct task_struct *p, u32 *secid) *secid = task_sid(p); } -static int selinux_task_setgroups(struct group_info *group_info) -{ - /* See the comment for setuid above. */ - return 0; -} - static int selinux_task_setnice(struct task_struct *p, int nice) { int rc; @@ -3417,18 +3388,6 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info, return rc; } -static int selinux_task_prctl(int option, - unsigned long arg2, - unsigned long arg3, - unsigned long arg4, - unsigned long arg5) -{ - /* The current prctl operations do not appear to require - any SELinux controls since they merely observe or modify - the state of the current process. */ - return secondary_ops->task_prctl(option, arg2, arg3, arg4, arg5); -} - static int selinux_task_wait(struct task_struct *p) { return task_has_perm(p, current, PROCESS__SIGCHLD); @@ -5563,8 +5522,6 @@ static struct security_operations selinux_ops = { .inode_getsecurity = selinux_inode_getsecurity, .inode_setsecurity = selinux_inode_setsecurity, .inode_listsecurity = selinux_inode_listsecurity, - .inode_need_killpriv = selinux_inode_need_killpriv, - .inode_killpriv = selinux_inode_killpriv, .inode_getsecid = selinux_inode_getsecid, .file_permission = selinux_file_permission, @@ -5586,14 +5543,10 @@ static struct security_operations selinux_ops = { .cred_prepare = selinux_cred_prepare, .kernel_act_as = selinux_kernel_act_as, .kernel_create_files_as = selinux_kernel_create_files_as, - .task_setuid = selinux_task_setuid, - .task_fix_setuid = selinux_task_fix_setuid, - .task_setgid = selinux_task_setgid, .task_setpgid = selinux_task_setpgid, .task_getpgid = selinux_task_getpgid, .task_getsid = selinux_task_getsid, .task_getsecid = selinux_task_getsecid, - .task_setgroups = selinux_task_setgroups, .task_setnice = selinux_task_setnice, .task_setioprio = selinux_task_setioprio, .task_getioprio = selinux_task_getioprio, @@ -5603,7 +5556,6 @@ static struct security_operations selinux_ops = { .task_movememory = selinux_task_movememory, .task_kill = selinux_task_kill, .task_wait = selinux_task_wait, - .task_prctl = selinux_task_prctl, .task_to_inode = selinux_task_to_inode, .ipc_permission = selinux_ipc_permission, -- GitLab From f15fbcd7d857ca2ea20b57ba6dfe63aab89d0b8b Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 1 Feb 2009 22:24:43 -0800 Subject: [PATCH 1109/4982] ipv4: Delete redundant sk_family assignment sk_alloc now sets sk_family so this is redundant. In fact it caught my eye because sock_init_data already uses sk_family so this is too late anyway. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv4/af_inet.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 957cd054732..c79087719df 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -369,7 +369,6 @@ lookup_protocol: sock_init_data(sock, sk); sk->sk_destruct = inet_sock_destruct; - sk->sk_family = PF_INET; sk->sk_protocol = protocol; sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; -- GitLab From 5aa13a94098ef5fc1bb0a7f531fdda8864ae67ff Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Sun, 1 Feb 2009 21:13:15 +0100 Subject: [PATCH 1110/4982] ALSA: msnd: add module description and license for the snd-msnd-lib The missing module license generates warning during module loading. Signed-off-by: Krzysztof Helt Signed-off-by: Takashi Iwai --- sound/isa/msnd/msnd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/isa/msnd/msnd.c b/sound/isa/msnd/msnd.c index 264e08212c6..906454413ed 100644 --- a/sound/isa/msnd/msnd.c +++ b/sound/isa/msnd/msnd.c @@ -700,3 +700,6 @@ int snd_msnd_pcm(struct snd_card *card, int device, } EXPORT_SYMBOL(snd_msnd_pcm); +MODULE_DESCRIPTION("Common routines for Turtle Beach Multisound drivers"); +MODULE_LICENSE("GPL"); + -- GitLab From 6489c611db095356645ca1a2689e93c63caeb310 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Sun, 1 Feb 2009 11:20:30 +0100 Subject: [PATCH 1111/4982] [ARM] pxa/magician: Enable pxa27x_udc and gpio_vbus This patch depends on otg_transceiver support in pxa27x_udc (which is queued via linux-usb) to work. It compiles also without it. Signed-off-by: Philipp Zabel Signed-off-by: Eric Miao --- arch/arm/configs/magician_defconfig | 56 +++++++++++++++++++---- arch/arm/mach-pxa/include/mach/magician.h | 2 +- arch/arm/mach-pxa/magician.c | 35 ++++++++++++-- 3 files changed, 79 insertions(+), 14 deletions(-) diff --git a/arch/arm/configs/magician_defconfig b/arch/arm/configs/magician_defconfig index dde50df09bc..4154d61af66 100644 --- a/arch/arm/configs/magician_defconfig +++ b/arch/arm/configs/magician_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.29-rc2 -# Sat Jan 17 17:47:17 2009 +# Linux kernel version: 2.6.29-rc3 +# Fri Jan 30 12:42:03 2009 # CONFIG_ARM=y CONFIG_HAVE_PWM=y @@ -44,6 +44,15 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=16 @@ -114,11 +123,6 @@ CONFIG_IOSCHED_NOOP=y # CONFIG_DEFAULT_CFQ is not set CONFIG_DEFAULT_NOOP=y CONFIG_DEFAULT_IOSCHED="noop" -CONFIG_CLASSIC_RCU=y -# CONFIG_TREE_RCU is not set -# CONFIG_PREEMPT_RCU is not set -# CONFIG_TREE_RCU_TRACE is not set -# CONFIG_PREEMPT_RCU_TRACE is not set CONFIG_FREEZER=y # @@ -993,6 +997,7 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_R8A66597_HCD is not set # CONFIG_USB_HWA_HCD is not set # CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_GADGET_MUSB_HDRC is not set # # USB Device Class drivers @@ -1044,12 +1049,45 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_ISIGHTFW is not set # CONFIG_USB_VST is not set -# CONFIG_USB_GADGET is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_PXA25X is not set +CONFIG_USB_GADGET_PXA27X=y +CONFIG_USB_PXA27X=y +# CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_IMX is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_FSL_QE is not set +# CONFIG_USB_GADGET_CI13XXX is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +# CONFIG_USB_ZERO is not set +CONFIG_USB_ETH=m +# CONFIG_USB_ETH_RNDIS is not set +CONFIG_USB_GADGETFS=m +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +CONFIG_USB_G_SERIAL=m +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +CONFIG_USB_CDC_COMPOSITE=m # # OTG and related infrastructure # -# CONFIG_USB_GPIO_VBUS is not set +CONFIG_USB_OTG_UTILS=y +CONFIG_USB_GPIO_VBUS=y CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_UNSAFE_RESUME is not set diff --git a/arch/arm/mach-pxa/include/mach/magician.h b/arch/arm/mach-pxa/include/mach/magician.h index 38d68d99f58..82a399f3f9f 100644 --- a/arch/arm/mach-pxa/include/mach/magician.h +++ b/arch/arm/mach-pxa/include/mach/magician.h @@ -69,7 +69,7 @@ #define IRQ_MAGICIAN_SD (IRQ_BOARD_START + 0) #define IRQ_MAGICIAN_EP (IRQ_BOARD_START + 1) #define IRQ_MAGICIAN_BT (IRQ_BOARD_START + 2) -#define IRQ_MAGICIAN_AC (IRQ_BOARD_START + 3) +#define IRQ_MAGICIAN_VBUS (IRQ_BOARD_START + 3) /* * CPLD EGPIOs diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c index b7aafe6823f..af464870c12 100644 --- a/arch/arm/mach-pxa/magician.c +++ b/arch/arm/mach-pxa/magician.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -524,6 +525,31 @@ static struct platform_device pasic3 = { }, }; +/* + * USB "Transceiver" + */ + +static struct resource gpio_vbus_resource = { + .flags = IORESOURCE_IRQ, + .start = IRQ_MAGICIAN_VBUS, + .end = IRQ_MAGICIAN_VBUS, +}; + +static struct gpio_vbus_mach_info gpio_vbus_info = { + .gpio_pullup = GPIO27_MAGICIAN_USBC_PUEN, + .gpio_vbus = EGPIO_MAGICIAN_CABLE_STATE_USB, +}; + +static struct platform_device gpio_vbus = { + .name = "gpio-vbus", + .id = -1, + .num_resources = 1, + .resource = &gpio_vbus_resource, + .dev = { + .platform_data = &gpio_vbus_info, + }, +}; + /* * External power */ @@ -601,14 +627,14 @@ static struct resource power_supply_resources[] = { [0] = { .name = "ac", .flags = IORESOURCE_IRQ, - .start = IRQ_MAGICIAN_AC, - .end = IRQ_MAGICIAN_AC, + .start = IRQ_MAGICIAN_VBUS, + .end = IRQ_MAGICIAN_VBUS, }, [1] = { .name = "usb", .flags = IORESOURCE_IRQ, - .start = IRQ_MAGICIAN_AC, - .end = IRQ_MAGICIAN_AC, + .start = IRQ_MAGICIAN_VBUS, + .end = IRQ_MAGICIAN_VBUS, }, }; @@ -732,6 +758,7 @@ static struct platform_device *devices[] __initdata = { &egpio, &backlight, &pasic3, + &gpio_vbus, &power_supply, &strataflash, &leds_gpio, -- GitLab From 6432f46c4ffd0a85cab5313bc989a6db32bc0eb4 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Mon, 2 Feb 2009 08:57:51 +0200 Subject: [PATCH 1112/4982] [ARM] pxa/em-x270: update MMC/SDIO implementation Signed-off-by: Mike Rapoport Signed-off-by: Eric Miao --- arch/arm/mach-pxa/em-x270.c | 97 +++++++++++++++++++++++++++++++------ 1 file changed, 81 insertions(+), 16 deletions(-) diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c index 1aaae97de7d..05f9e9e1224 100644 --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c @@ -43,12 +43,12 @@ #include #include "generic.h" +#include "devices.h" /* GPIO IRQ usage */ #define GPIO41_ETHIRQ (41) #define GPIO13_MMC_CD (13) #define EM_X270_ETHIRQ IRQ_GPIO(GPIO41_ETHIRQ) -#define EM_X270_MMC_CD IRQ_GPIO(GPIO13_MMC_CD) /* NAND control GPIOs */ #define GPIO11_NAND_CS (11) @@ -56,6 +56,7 @@ /* Miscelaneous GPIOs */ #define GPIO93_CAM_RESET (93) +#define GPIO95_MMC_WP (95) static unsigned long em_x270_pin_config[] = { /* AC'97 */ @@ -163,7 +164,8 @@ static unsigned long em_x270_pin_config[] = { GPIO18_RDY, /* GPIO */ - GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH, + GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH, /* sleep/resume button */ + GPIO95_GPIO, /* MMC Write protect */ /* power controls */ GPIO20_GPIO | MFP_LPM_DRIVE_LOW, /* GPRS_PWEN */ @@ -464,47 +466,86 @@ static inline void em_x270_init_ohci(void) {} /* MCI controller setup */ #if defined(CONFIG_MMC) || defined(CONFIG_MMC_MODULE) +static struct regulator *em_x270_sdio_ldo; + static int em_x270_mci_init(struct device *dev, irq_handler_t em_x270_detect_int, void *data) { - int err = request_irq(EM_X270_MMC_CD, em_x270_detect_int, - IRQF_DISABLED | IRQF_TRIGGER_FALLING, + int err; + + em_x270_sdio_ldo = regulator_get(dev, "vcc sdio"); + if (IS_ERR(em_x270_sdio_ldo)) { + dev_err(dev, "can't request SDIO power supply: %ld\n", + PTR_ERR(em_x270_sdio_ldo)); + return PTR_ERR(em_x270_sdio_ldo); + } + + err = request_irq(gpio_to_irq(GPIO13_MMC_CD), em_x270_detect_int, + IRQF_DISABLED | IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING, "MMC card detect", data); if (err) { - printk(KERN_ERR "%s: can't request MMC card detect IRQ: %d\n", - __func__, err); - return err; + dev_err(dev, "can't request MMC card detect IRQ: %d\n", err); + goto err_irq; + } + + err = gpio_request(GPIO95_MMC_WP, "MMC WP"); + if (err) { + dev_err(dev, "can't request MMC write protect: %d\n", err); + goto err_gpio_wp; } + gpio_direction_input(GPIO95_MMC_WP); + return 0; + +err_gpio_wp: + free_irq(gpio_to_irq(GPIO13_MMC_CD), data); +err_irq: + regulator_put(em_x270_sdio_ldo); + + return err; } static void em_x270_mci_setpower(struct device *dev, unsigned int vdd) { - /* - FIXME: current hardware implementation does not allow to - enable/disable MMC power. This will be fixed in next HW releases, - and we'll need to add implmentation here. - */ - return; + struct pxamci_platform_data* p_d = dev->platform_data; + + if ((1 << vdd) & p_d->ocr_mask) { + int vdd_uV = (2000 + (vdd - __ffs(MMC_VDD_20_21)) * 100) * 1000; + + regulator_set_voltage(em_x270_sdio_ldo, vdd_uV, vdd_uV); + regulator_enable(em_x270_sdio_ldo); + } else { + regulator_disable(em_x270_sdio_ldo); + } } static void em_x270_mci_exit(struct device *dev, void *data) { - int irq = gpio_to_irq(GPIO13_MMC_CD); - free_irq(irq, data); + free_irq(gpio_to_irq(GPIO13_MMC_CD), data); +} + +static int em_x270_mci_get_ro(struct device *dev) +{ + return gpio_get_value(GPIO95_MMC_WP); } static struct pxamci_platform_data em_x270_mci_platform_data = { - .ocr_mask = MMC_VDD_28_29|MMC_VDD_29_30|MMC_VDD_30_31, + .ocr_mask = MMC_VDD_20_21|MMC_VDD_21_22|MMC_VDD_22_23| + MMC_VDD_24_25|MMC_VDD_25_26|MMC_VDD_26_27| + MMC_VDD_27_28|MMC_VDD_28_29|MMC_VDD_29_30| + MMC_VDD_30_31|MMC_VDD_31_32, .init = em_x270_mci_init, .setpower = em_x270_mci_setpower, + .get_ro = em_x270_mci_get_ro, .exit = em_x270_mci_exit, }; static void __init em_x270_init_mmc(void) { + em_x270_mci_platform_data.detect_delay = msecs_to_jiffies(250); pxa_set_mci_info(&em_x270_mci_platform_data); } #else @@ -757,6 +798,13 @@ static struct regulator_consumer_supply ldo5_consumers[] = { }, }; +static struct regulator_consumer_supply ldo10_consumers[] = { + { + .dev = &pxa_device_mci.dev, + .supply = "vcc sdio", + }, +}; + static struct regulator_consumer_supply ldo12_consumers[] = { { .dev = NULL, @@ -795,6 +843,19 @@ static struct regulator_init_data ldo5_data = { .consumer_supplies = ldo5_consumers, }; +static struct regulator_init_data ldo10_data = { + .constraints = { + .min_uV = 2000000, + .max_uV = 3200000, + .state_mem = { + .enabled = 0, + }, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(ldo10_consumers), + .consumer_supplies = ldo10_consumers, +}; + static struct regulator_init_data ldo12_data = { .constraints = { .min_uV = 3000000, @@ -833,6 +894,10 @@ struct da903x_subdev_info em_x270_da9030_subdevs[] = { .name = "da903x-regulator", .id = DA9030_ID_LDO5, .platform_data = &ldo5_data, + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO10, + .platform_data = &ldo10_data, }, { .name = "da903x-regulator", .id = DA9030_ID_LDO12, -- GitLab From 432adf1898381bac5a9ef90262d8a91e16823b11 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Mon, 2 Feb 2009 08:57:52 +0200 Subject: [PATCH 1113/4982] [ARM] pxa/em-x270: introduce macors to to simplify da9030 subdev initialization Signed-off-by: Mike Rapoport Signed-off-by: Eric Miao --- arch/arm/mach-pxa/em-x270.c | 172 +++++++++++------------------------- 1 file changed, 50 insertions(+), 122 deletions(-) diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c index 05f9e9e1224..7d056cb2334 100644 --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c @@ -784,136 +784,64 @@ static inline void em_x270_init_camera(void) {} #endif /* DA9030 related initializations */ -static struct regulator_consumer_supply ldo3_consumers[] = { - { - .dev = NULL, - .supply = "vcc gps", - }, -}; - -static struct regulator_consumer_supply ldo5_consumers[] = { - { - .dev = NULL, - .supply = "vcc cam", - }, -}; - -static struct regulator_consumer_supply ldo10_consumers[] = { - { - .dev = &pxa_device_mci.dev, - .supply = "vcc sdio", - }, -}; - -static struct regulator_consumer_supply ldo12_consumers[] = { - { - .dev = NULL, - .supply = "vcc usb", - }, -}; - -static struct regulator_consumer_supply ldo19_consumers[] = { - { - .dev = NULL, - .supply = "vcc gprs", - }, -}; - -static struct regulator_init_data ldo3_data = { - .constraints = { - .min_uV = 3200000, - .max_uV = 3200000, - .state_mem = { - .enabled = 0, - }, - }, - .num_consumer_supplies = ARRAY_SIZE(ldo3_consumers), - .consumer_supplies = ldo3_consumers, -}; - -static struct regulator_init_data ldo5_data = { - .constraints = { - .min_uV = 3000000, - .max_uV = 3000000, - .state_mem = { - .enabled = 0, - }, - }, - .num_consumer_supplies = ARRAY_SIZE(ldo5_consumers), - .consumer_supplies = ldo5_consumers, -}; - -static struct regulator_init_data ldo10_data = { - .constraints = { - .min_uV = 2000000, - .max_uV = 3200000, - .state_mem = { - .enabled = 0, - }, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(ldo10_consumers), - .consumer_supplies = ldo10_consumers, -}; - -static struct regulator_init_data ldo12_data = { - .constraints = { - .min_uV = 3000000, - .max_uV = 3000000, - .state_mem = { - .enabled = 0, - }, - }, - .num_consumer_supplies = ARRAY_SIZE(ldo12_consumers), - .consumer_supplies = ldo12_consumers, -}; +#define REGULATOR_CONSUMER(_name, _dev, _supply) \ + static struct regulator_consumer_supply _name##_consumers[] = { \ + { \ + .dev = _dev, \ + .supply = _supply, \ + }, \ + } -static struct regulator_init_data ldo19_data = { - .constraints = { - .min_uV = 3200000, - .max_uV = 3200000, - .state_mem = { - .enabled = 0, - }, - }, - .num_consumer_supplies = ARRAY_SIZE(ldo19_consumers), - .consumer_supplies = ldo19_consumers, -}; +REGULATOR_CONSUMER(ldo3, NULL, "vcc gps"); +REGULATOR_CONSUMER(ldo5, NULL, "vcc cam"); +REGULATOR_CONSUMER(ldo10, &pxa_device_mci.dev, "vcc sdio"); +REGULATOR_CONSUMER(ldo12, NULL, "vcc usb"); +REGULATOR_CONSUMER(ldo19, NULL, "vcc gprs"); + +#define REGULATOR_INIT(_ldo, _min_uV, _max_uV, _ops_mask) \ + static struct regulator_init_data _ldo##_data = { \ + .constraints = { \ + .min_uV = _min_uV, \ + .max_uV = _max_uV, \ + .state_mem = { \ + .enabled = 0, \ + }, \ + .valid_ops_mask = _ops_mask, \ + }, \ + .num_consumer_supplies = ARRAY_SIZE(_ldo##_consumers), \ + .consumer_supplies = _ldo##_consumers, \ + }; + +REGULATOR_INIT(ldo3, 3200000, 3200000, REGULATOR_CHANGE_STATUS); +REGULATOR_INIT(ldo5, 3000000, 3000000, REGULATOR_CHANGE_STATUS); +REGULATOR_INIT(ldo10, 2000000, 3200000, + REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE); +REGULATOR_INIT(ldo12, 3000000, 3000000, REGULATOR_CHANGE_STATUS); +REGULATOR_INIT(ldo19, 3200000, 3200000, REGULATOR_CHANGE_STATUS); struct led_info em_x270_led_info = { .name = "em-x270:orange", .default_trigger = "battery-charging-or-full", }; -struct da903x_subdev_info em_x270_da9030_subdevs[] = { - { - .name = "da903x-regulator", - .id = DA9030_ID_LDO3, - .platform_data = &ldo3_data, - }, { - .name = "da903x-regulator", - .id = DA9030_ID_LDO5, - .platform_data = &ldo5_data, - }, { - .name = "da903x-regulator", - .id = DA9030_ID_LDO10, - .platform_data = &ldo10_data, - }, { - .name = "da903x-regulator", - .id = DA9030_ID_LDO12, - .platform_data = &ldo12_data, - }, { - .name = "da903x-regulator", - .id = DA9030_ID_LDO19, - .platform_data = &ldo19_data, - }, { - .name = "da903x-led", - .id = DA9030_ID_LED_PC, - .platform_data = &em_x270_led_info, - }, { - .name = "da903x-backlight", - .id = DA9030_ID_WLED, +#define DA9030_SUBDEV(_name, _id, _pdata) \ + { \ + .name = "da903x-" #_name, \ + .id = DA9030_ID_##_id, \ + .platform_data = _pdata, \ } + +#define DA9030_LDO(num) DA9030_SUBDEV(regulator, LDO##num, &ldo##num##_data) + +struct da903x_subdev_info em_x270_da9030_subdevs[] = { + DA9030_LDO(3), + DA9030_LDO(5), + DA9030_LDO(10), + DA9030_LDO(12), + DA9030_LDO(19), + + DA9030_SUBDEV(led, LED_PC, &em_x270_led_info), + DA9030_SUBDEV(backlight, WLED, &em_x270_led_info), }; static struct da903x_platform_data em_x270_da9030_info = { -- GitLab From 9f055c49c6a1afe6e8b75a2622ac29f3a4290b9d Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Mon, 2 Feb 2009 08:57:53 +0200 Subject: [PATCH 1114/4982] [ARM] pxa/em-x270: add battery charger Signed-off-by: Mike Rapoport Signed-off-by: Eric Miao --- arch/arm/mach-pxa/em-x270.c | 46 +++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c index 7d056cb2334..20ed10c67c6 100644 --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include @@ -824,6 +826,49 @@ struct led_info em_x270_led_info = { .default_trigger = "battery-charging-or-full", }; +struct power_supply_info em_x270_psy_info = { + .name = "LP555597P6H-FPS", + .technology = POWER_SUPPLY_TECHNOLOGY_LIPO, + .voltage_max_design = 4200000, + .voltage_min_design = 3000000, + .use_for_apm = 1, +}; + +static void em_x270_battery_low(void) +{ + apm_queue_event(APM_LOW_BATTERY); +} + +static void em_x270_battery_critical(void) +{ + apm_queue_event(APM_CRITICAL_SUSPEND); +} + +struct da9030_battery_info em_x270_batterty_info = { + .battery_info = &em_x270_psy_info, + + .charge_milliamp = 1000, + .charge_millivolt = 4200, + + .vbat_low = 3600, + .vbat_crit = 3400, + .vbat_charge_start = 4100, + .vbat_charge_stop = 4200, + .vbat_charge_restart = 4000, + + .vcharge_min = 3200, + .vcharge_max = 5500, + + .tbat_low = 197, + .tbat_high = 78, + .tbat_restart = 100, + + .batmon_interval = 0, + + .battery_low = em_x270_battery_low, + .battery_critical = em_x270_battery_critical, +}; + #define DA9030_SUBDEV(_name, _id, _pdata) \ { \ .name = "da903x-" #_name, \ @@ -842,6 +887,7 @@ struct da903x_subdev_info em_x270_da9030_subdevs[] = { DA9030_SUBDEV(led, LED_PC, &em_x270_led_info), DA9030_SUBDEV(backlight, WLED, &em_x270_led_info), + DA9030_SUBDEV(battery, BAT, &em_x270_batterty_info), }; static struct da903x_platform_data em_x270_da9030_info = { -- GitLab From 4a697e83cf8b20b35942c93b873fe17e54d7e6c5 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Mon, 2 Feb 2009 08:57:54 +0200 Subject: [PATCH 1115/4982] [ARM] pxa/em-x270: prepare addition of eXeda machine to em-x270.c Change several GPIO assignment from static to run-time Split MFP table to common and EM-X270 specific parts Introduce em_x270_module_init Signed-off-by: Mike Rapoport Signed-off-by: Eric Miao --- arch/arm/mach-pxa/em-x270.c | 43 ++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c index 20ed10c67c6..ea099183773 100644 --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c @@ -60,7 +60,11 @@ #define GPIO93_CAM_RESET (93) #define GPIO95_MMC_WP (95) -static unsigned long em_x270_pin_config[] = { +static int mmc_cd; +static int nand_rb; +static int dm9000_flags; + +static unsigned long common_pin_config[] = { /* AC'97 */ GPIO28_AC97_BITCLK, GPIO29_AC97_SDATA_IN_0, @@ -167,7 +171,6 @@ static unsigned long em_x270_pin_config[] = { /* GPIO */ GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH, /* sleep/resume button */ - GPIO95_GPIO, /* MMC Write protect */ /* power controls */ GPIO20_GPIO | MFP_LPM_DRIVE_LOW, /* GPRS_PWEN */ @@ -176,13 +179,17 @@ static unsigned long em_x270_pin_config[] = { /* NAND controls */ GPIO11_GPIO | MFP_LPM_DRIVE_HIGH, /* NAND CE# */ - GPIO56_GPIO, /* NAND Ready/Busy */ /* interrupts */ - GPIO13_GPIO, /* MMC card detect */ GPIO41_GPIO, /* DM9000 interrupt */ }; +static unsigned long em_x270_pin_config[] = { + GPIO13_GPIO, /* MMC card detect */ + GPIO56_GPIO, /* NAND Ready/Busy */ + GPIO95_GPIO, /* MMC Write protect */ +}; + #if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE) static struct resource em_x270_dm9000_resource[] = { [0] = { @@ -203,7 +210,7 @@ static struct resource em_x270_dm9000_resource[] = { }; static struct dm9000_plat_data em_x270_dm9000_platdata = { - .flags = DM9000_PLATF_32BITONLY, + .flags = DM9000_PLATF_NO_EEPROM, }; static struct platform_device em_x270_dm9000 = { @@ -218,6 +225,7 @@ static struct platform_device em_x270_dm9000 = { static void __init em_x270_init_dm9000(void) { + em_x270_dm9000_platdata.flags |= dm9000_flags; platform_device_register(&em_x270_dm9000); } #else @@ -307,7 +315,7 @@ static int em_x270_nand_device_ready(struct mtd_info *mtd) { dsb(); - return gpio_get_value(GPIO56_NAND_RB); + return gpio_get_value(nand_rb); } static struct mtd_partition em_x270_partition_info[] = { @@ -372,14 +380,14 @@ static void __init em_x270_init_nand(void) gpio_direction_output(GPIO11_NAND_CS, 1); - err = gpio_request(GPIO56_NAND_RB, "NAND R/B"); + err = gpio_request(nand_rb, "NAND R/B"); if (err) { pr_warning("EM-X270: failed to request NAND R/B gpio\n"); gpio_free(GPIO11_NAND_CS); return; } - gpio_direction_input(GPIO56_NAND_RB); + gpio_direction_input(nand_rb); platform_device_register(&em_x270_nand); } @@ -483,7 +491,7 @@ static int em_x270_mci_init(struct device *dev, return PTR_ERR(em_x270_sdio_ldo); } - err = request_irq(gpio_to_irq(GPIO13_MMC_CD), em_x270_detect_int, + err = request_irq(gpio_to_irq(mmc_cd), em_x270_detect_int, IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "MMC card detect", data); @@ -503,7 +511,7 @@ static int em_x270_mci_init(struct device *dev, return 0; err_gpio_wp: - free_irq(gpio_to_irq(GPIO13_MMC_CD), data); + free_irq(gpio_to_irq(mmc_cd), data); err_irq: regulator_put(em_x270_sdio_ldo); @@ -526,7 +534,7 @@ static void em_x270_mci_setpower(struct device *dev, unsigned int vdd) static void em_x270_mci_exit(struct device *dev, void *data) { - free_irq(gpio_to_irq(GPIO13_MMC_CD), data); + free_irq(gpio_to_irq(mmc_cd), data); } static int em_x270_mci_get_ro(struct device *dev) @@ -911,10 +919,21 @@ static void __init em_x270_init_da9030(void) i2c_register_board_info(1, &em_x270_i2c_pmic_info, 1); } -static void __init em_x270_init(void) +static void __init em_x270_module_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(em_x270_pin_config)); + mmc_cd = GPIO13_MMC_CD; + nand_rb = GPIO56_NAND_RB; + dm9000_flags = DM9000_PLATF_32BITONLY; +} + +static void __init em_x270_init(void) +{ + pxa2xx_mfp_config(ARRAY_AND_SIZE(common_pin_config)); + + em_x270_module_init(); + em_x270_init_da9030(); em_x270_init_dm9000(); em_x270_init_rtc(); -- GitLab From 7f14a78713e0b4517f785402accaccca22df93c1 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Mon, 2 Feb 2009 08:57:55 +0200 Subject: [PATCH 1116/4982] [ARM] pxa: add eXeda platform support Signed-off-by: Mike Rapoport Signed-off-by: Eric Miao --- arch/arm/mach-pxa/Kconfig | 4 + arch/arm/mach-pxa/em-x270.c | 149 +++++++++++++++++++++++++++++++----- 2 files changed, 132 insertions(+), 21 deletions(-) diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index a2ed2aa731b..ffd28e48d75 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -254,6 +254,10 @@ config MACH_EM_X270 bool "CompuLab EM-x270 platform" select PXA27x +config MACH_EXEDA + bool "CompuLab eXeda platform" + select PXA27x + config MACH_COLIBRI bool "Toradex Colibri PX27x" select PXA27x diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c index ea099183773..9f15a7c9cc5 100644 --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -47,18 +48,21 @@ #include "generic.h" #include "devices.h" -/* GPIO IRQ usage */ -#define GPIO41_ETHIRQ (41) +/* EM-X270 specific GPIOs */ #define GPIO13_MMC_CD (13) -#define EM_X270_ETHIRQ IRQ_GPIO(GPIO41_ETHIRQ) +#define GPIO95_MMC_WP (95) +#define GPIO56_NAND_RB (56) -/* NAND control GPIOs */ -#define GPIO11_NAND_CS (11) -#define GPIO56_NAND_RB (56) +/* eXeda specific GPIOs */ +#define GPIO114_MMC_CD (114) +#define GPIO20_NAND_RB (20) +#define GPIO38_SD_PWEN (38) -/* Miscelaneous GPIOs */ +/* common GPIOs */ +#define GPIO11_NAND_CS (11) #define GPIO93_CAM_RESET (93) -#define GPIO95_MMC_WP (95) +#define GPIO41_ETHIRQ (41) +#define EM_X270_ETHIRQ IRQ_GPIO(GPIO41_ETHIRQ) static int mmc_cd; static int nand_rb; @@ -190,6 +194,12 @@ static unsigned long em_x270_pin_config[] = { GPIO95_GPIO, /* MMC Write protect */ }; +static unsigned long exeda_pin_config[] = { + GPIO20_GPIO, /* NAND Ready/Busy */ + GPIO38_GPIO | MFP_LPM_DRIVE_LOW, /* SD slot power */ + GPIO114_GPIO, /* MMC card detect */ +}; + #if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE) static struct resource em_x270_dm9000_resource[] = { [0] = { @@ -500,14 +510,24 @@ static int em_x270_mci_init(struct device *dev, goto err_irq; } - err = gpio_request(GPIO95_MMC_WP, "MMC WP"); - if (err) { - dev_err(dev, "can't request MMC write protect: %d\n", err); - goto err_gpio_wp; + if (machine_is_em_x270()) { + err = gpio_request(GPIO95_MMC_WP, "MMC WP"); + if (err) { + dev_err(dev, "can't request MMC write protect: %d\n", + err); + goto err_gpio_wp; + } + gpio_direction_input(GPIO95_MMC_WP); + } else { + err = gpio_request(GPIO38_SD_PWEN, "sdio power"); + if (err) { + dev_err(dev, "can't request MMC power control : %d\n", + err); + goto err_gpio_wp; + } + gpio_direction_output(GPIO38_SD_PWEN, 1); } - gpio_direction_input(GPIO95_MMC_WP); - return 0; err_gpio_wp: @@ -535,6 +555,12 @@ static void em_x270_mci_setpower(struct device *dev, unsigned int vdd) static void em_x270_mci_exit(struct device *dev, void *data) { free_irq(gpio_to_irq(mmc_cd), data); + regulator_put(em_x270_sdio_ldo); + + if (machine_is_em_x270()) + gpio_free(GPIO95_MMC_WP); + else + gpio_free(GPIO38_SD_PWEN); } static int em_x270_mci_get_ro(struct device *dev) @@ -549,12 +575,14 @@ static struct pxamci_platform_data em_x270_mci_platform_data = { MMC_VDD_30_31|MMC_VDD_31_32, .init = em_x270_mci_init, .setpower = em_x270_mci_setpower, - .get_ro = em_x270_mci_get_ro, .exit = em_x270_mci_exit, }; static void __init em_x270_init_mmc(void) { + if (machine_is_em_x270()) + em_x270_mci_platform_data.get_ro = em_x270_mci_get_ro; + em_x270_mci_platform_data.detect_delay = msecs_to_jiffies(250); pxa_set_mci_info(&em_x270_mci_platform_data); } @@ -651,23 +679,76 @@ static inline void em_x270_init_ac97(void) {} #endif #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) -static unsigned int em_x270_matrix_keys[] = { +static unsigned int em_x270_module_matrix_keys[] = { KEY(0, 0, KEY_A), KEY(1, 0, KEY_UP), KEY(2, 1, KEY_B), KEY(0, 2, KEY_LEFT), KEY(1, 1, KEY_ENTER), KEY(2, 0, KEY_RIGHT), KEY(0, 1, KEY_C), KEY(1, 2, KEY_DOWN), KEY(2, 2, KEY_D), }; -struct pxa27x_keypad_platform_data em_x270_keypad_info = { +struct pxa27x_keypad_platform_data em_x270_module_keypad_info = { /* code map for the matrix keys */ .matrix_key_rows = 3, .matrix_key_cols = 3, - .matrix_key_map = em_x270_matrix_keys, - .matrix_key_map_size = ARRAY_SIZE(em_x270_matrix_keys), + .matrix_key_map = em_x270_module_matrix_keys, + .matrix_key_map_size = ARRAY_SIZE(em_x270_module_matrix_keys), +}; + +static unsigned int em_x270_exeda_matrix_keys[] = { + KEY(0, 0, KEY_RIGHTSHIFT), KEY(0, 1, KEY_RIGHTCTRL), + KEY(0, 2, KEY_RIGHTALT), KEY(0, 3, KEY_SPACE), + KEY(0, 4, KEY_LEFTALT), KEY(0, 5, KEY_LEFTCTRL), + KEY(0, 6, KEY_ENTER), KEY(0, 7, KEY_SLASH), + + KEY(1, 0, KEY_DOT), KEY(1, 1, KEY_M), + KEY(1, 2, KEY_N), KEY(1, 3, KEY_B), + KEY(1, 4, KEY_V), KEY(1, 5, KEY_C), + KEY(1, 6, KEY_X), KEY(1, 7, KEY_Z), + + KEY(2, 0, KEY_LEFTSHIFT), KEY(2, 1, KEY_SEMICOLON), + KEY(2, 2, KEY_L), KEY(2, 3, KEY_K), + KEY(2, 4, KEY_J), KEY(2, 5, KEY_H), + KEY(2, 6, KEY_G), KEY(2, 7, KEY_F), + + KEY(3, 0, KEY_D), KEY(3, 1, KEY_S), + KEY(3, 2, KEY_A), KEY(3, 3, KEY_TAB), + KEY(3, 4, KEY_BACKSPACE), KEY(3, 5, KEY_P), + KEY(3, 6, KEY_O), KEY(3, 7, KEY_I), + + KEY(4, 0, KEY_U), KEY(4, 1, KEY_Y), + KEY(4, 2, KEY_T), KEY(4, 3, KEY_R), + KEY(4, 4, KEY_E), KEY(4, 5, KEY_W), + KEY(4, 6, KEY_Q), KEY(4, 7, KEY_MINUS), + + KEY(5, 0, KEY_0), KEY(5, 1, KEY_9), + KEY(5, 2, KEY_8), KEY(5, 3, KEY_7), + KEY(5, 4, KEY_6), KEY(5, 5, KEY_5), + KEY(5, 6, KEY_4), KEY(5, 7, KEY_3), + + KEY(6, 0, KEY_2), KEY(6, 1, KEY_1), + KEY(6, 2, KEY_ENTER), KEY(6, 3, KEY_END), + KEY(6, 4, KEY_DOWN), KEY(6, 5, KEY_UP), + KEY(6, 6, KEY_MENU), KEY(6, 7, KEY_F1), + + KEY(7, 0, KEY_LEFT), KEY(7, 1, KEY_RIGHT), + KEY(7, 2, KEY_BACK), KEY(7, 3, KEY_HOME), + KEY(7, 4, 0), KEY(7, 5, 0), + KEY(7, 6, 0), KEY(7, 7, 0), +}; + +struct pxa27x_keypad_platform_data em_x270_exeda_keypad_info = { + /* code map for the matrix keys */ + .matrix_key_rows = 8, + .matrix_key_cols = 8, + .matrix_key_map = em_x270_exeda_matrix_keys, + .matrix_key_map_size = ARRAY_SIZE(em_x270_exeda_matrix_keys), }; static void __init em_x270_init_keypad(void) { - pxa_set_keypad_info(&em_x270_keypad_info); + if (machine_is_em_x270()) + pxa_set_keypad_info(&em_x270_module_keypad_info); + else + pxa_set_keypad_info(&em_x270_exeda_keypad_info); } #else static inline void em_x270_init_keypad(void) {} @@ -921,6 +1002,7 @@ static void __init em_x270_init_da9030(void) static void __init em_x270_module_init(void) { + pr_info("%s\n", __func__); pxa2xx_mfp_config(ARRAY_AND_SIZE(em_x270_pin_config)); mmc_cd = GPIO13_MMC_CD; @@ -928,11 +1010,26 @@ static void __init em_x270_module_init(void) dm9000_flags = DM9000_PLATF_32BITONLY; } +static void __init em_x270_exeda_init(void) +{ + pr_info("%s\n", __func__); + pxa2xx_mfp_config(ARRAY_AND_SIZE(exeda_pin_config)); + + mmc_cd = GPIO114_MMC_CD; + nand_rb = GPIO20_NAND_RB; + dm9000_flags = DM9000_PLATF_16BITONLY; +} + static void __init em_x270_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(common_pin_config)); - em_x270_module_init(); + if (machine_is_em_x270()) + em_x270_module_init(); + else if (machine_is_exeda()) + em_x270_exeda_init(); + else + panic("Unsupported machine: %d\n", machine_arch_type); em_x270_init_da9030(); em_x270_init_dm9000(); @@ -958,3 +1055,13 @@ MACHINE_START(EM_X270, "Compulab EM-X270") .timer = &pxa_timer, .init_machine = em_x270_init, MACHINE_END + +MACHINE_START(EXEDA, "Compulab eXeda") + .boot_params = 0xa0000100, + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .map_io = pxa_map_io, + .init_irq = pxa27x_init_irq, + .timer = &pxa_timer, + .init_machine = em_x270_init, +MACHINE_END -- GitLab From 6e39759d456e502f91c6a7ff669f28d6e50437f1 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Mon, 2 Feb 2009 08:57:57 +0200 Subject: [PATCH 1117/4982] [ARM] pxa: prepare xm_x2xx_defconfig for split xm_x2xx_defconfig currently supports 3 platforms: CM-X255, CM-X270 and EM-X270. Although EM-X270 is similar to CM-X2XX, it has a lot of unique features. Keeping these features in the same _defconfig increases the kernel size in the way it does not fit into CM-X2XX NOR flash. Rename xm_x2xx_defconfig to cm_x2xx_defconfig and remove EM-X270 specifc parts from it. Signed-off-by: Mike Rapoport Signed-off-by: Eric Miao --- .../{xm_x2xx_defconfig => cm_x2xx_defconfig} | 140 ++++++++++-------- 1 file changed, 75 insertions(+), 65 deletions(-) rename arch/arm/configs/{xm_x2xx_defconfig => cm_x2xx_defconfig} (95%) diff --git a/arch/arm/configs/xm_x2xx_defconfig b/arch/arm/configs/cm_x2xx_defconfig similarity index 95% rename from arch/arm/configs/xm_x2xx_defconfig rename to arch/arm/configs/cm_x2xx_defconfig index 07c3c93754b..797b790cba7 100644 --- a/arch/arm/configs/xm_x2xx_defconfig +++ b/arch/arm/configs/cm_x2xx_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.28-rc6 -# Wed Dec 3 09:26:16 2008 +# Linux kernel version: 2.6.29-rc2 +# Sun Feb 1 16:31:36 2009 # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y @@ -46,12 +46,12 @@ CONFIG_SYSVIPC_SYSCTL=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CGROUPS is not set CONFIG_GROUP_SCHED=y CONFIG_FAIR_GROUP_SCHED=y # CONFIG_RT_GROUP_SCHED is not set CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set +# CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set @@ -87,7 +87,6 @@ CONFIG_PCI_QUIRKS=y CONFIG_SLUB=y # CONFIG_SLOB is not set # CONFIG_PROFILING is not set -# CONFIG_MARKERS is not set CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set CONFIG_HAVE_KPROBES=y @@ -95,7 +94,6 @@ CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_CLK=y CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 CONFIG_MODULES=y # CONFIG_MODULE_FORCE_LOAD is not set @@ -103,11 +101,9 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y CONFIG_BLOCK=y # CONFIG_LBD is not set # CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_INTEGRITY is not set @@ -124,6 +120,10 @@ CONFIG_DEFAULT_CFQ=y # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="cfq" CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set CONFIG_FREEZER=y # @@ -134,7 +134,6 @@ CONFIG_FREEZER=y # CONFIG_ARCH_REALVIEW is not set # CONFIG_ARCH_VERSATILE is not set # CONFIG_ARCH_AT91 is not set -# CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_EP93XX is not set @@ -161,16 +160,19 @@ CONFIG_ARCH_PXA=y # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set # CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set # CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP is not set # CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_W90X900 is not set # # Intel PXA2xx/PXA3xx Implementations # # CONFIG_ARCH_GUMSTIX is not set +# CONFIG_MACH_INTELMOTE2 is not set # CONFIG_ARCH_LUBBOCK is not set # CONFIG_MACH_LOGICPD_PXA270 is not set # CONFIG_MACH_MAINSTONE is not set @@ -180,7 +182,9 @@ CONFIG_ARCH_PXA=y # CONFIG_ARCH_VIPER is not set # CONFIG_ARCH_PXA_ESERIES is not set # CONFIG_TRIZEPS_PXA is not set -CONFIG_MACH_EM_X270=y +# CONFIG_MACH_H5000 is not set +# CONFIG_MACH_EM_X270 is not set +# CONFIG_MACH_EXEDA is not set # CONFIG_MACH_COLIBRI is not set # CONFIG_MACH_ZYLONITE is not set # CONFIG_MACH_LITTLETON is not set @@ -198,14 +202,6 @@ CONFIG_PXA27x=y CONFIG_PXA_SSP=y # CONFIG_PXA_PWM is not set -# -# Boot options -# - -# -# Power management -# - # # Processor Type # @@ -228,6 +224,7 @@ CONFIG_ARM_THUMB=y CONFIG_IWMMXT=y CONFIG_XSCALE_PMU=y CONFIG_DMABOUNCE=y +CONFIG_COMMON_CLKDEV=y # # Bus support @@ -238,6 +235,7 @@ CONFIG_PCI_HOST_ITE8152=y # CONFIG_ARCH_SUPPORTS_MSI is not set CONFIG_PCI_LEGACY=y # CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_STUB is not set CONFIG_PCCARD=m # CONFIG_PCMCIA_DEBUG is not set CONFIG_PCMCIA=m @@ -285,7 +283,6 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4096 -# CONFIG_RESOURCES_64BIT is not set # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y @@ -343,6 +340,7 @@ CONFIG_NET=y # # Networking options # +CONFIG_COMPAT_NET_DEV_OPS=y CONFIG_PACKET=y CONFIG_PACKET_MMAP=y CONFIG_UNIX=y @@ -398,6 +396,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set # # Network testing @@ -419,8 +418,6 @@ CONFIG_BT_HIDP=m # # Bluetooth device drivers # -CONFIG_BT_HCIUSB=m -CONFIG_BT_HCIUSB_SCO=y # CONFIG_BT_HCIBTUSB is not set # CONFIG_BT_HCIBTSDIO is not set # CONFIG_BT_HCIUART is not set @@ -439,8 +436,9 @@ CONFIG_WIRELESS=y CONFIG_WIRELESS_OLD_REGULATORY=y CONFIG_WIRELESS_EXT=y CONFIG_WIRELESS_EXT_SYSFS=y +CONFIG_LIB80211=m # CONFIG_MAC80211 is not set -# CONFIG_IEEE80211 is not set +# CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set @@ -465,6 +463,7 @@ CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set # CONFIG_MTD_CONCAT is not set CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set # CONFIG_MTD_REDBOOT_PARTS is not set CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_AFS_PARTS is not set @@ -519,9 +518,7 @@ CONFIG_MTD_CFI_UTIL=y # # CONFIG_MTD_COMPLEX_MAPPINGS is not set CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_PHYSMAP_START=0x0 -CONFIG_MTD_PHYSMAP_LEN=0x0 -CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +# CONFIG_MTD_PHYSMAP_COMPAT is not set CONFIG_MTD_PXA2XX=y # CONFIG_MTD_ARM_INTEGRATOR is not set # CONFIG_MTD_IMPA7 is not set @@ -562,6 +559,12 @@ CONFIG_MTD_NAND_PLATFORM=y # CONFIG_MTD_ALAUDA is not set # CONFIG_MTD_ONENAND is not set +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_QINFO_PROBE is not set + # # UBI - Unsorted block images # @@ -642,6 +645,8 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set # CONFIG_SCSI_HPTIOP is not set +# CONFIG_LIBFC is not set +# CONFIG_FCOE is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_IPS is not set @@ -758,6 +763,7 @@ CONFIG_DM9000_DEBUGLEVEL=1 # CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL is not set # CONFIG_ENC28J60 is not set # CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set # CONFIG_IBM_NEW_EMAC_ZMII is not set @@ -773,7 +779,6 @@ CONFIG_NET_PCI=y # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set -# CONFIG_EEPRO100 is not set # CONFIG_E100 is not set # CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set @@ -787,6 +792,7 @@ CONFIG_8139TOO=m # CONFIG_R6040 is not set # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set +# CONFIG_SMSC9420 is not set # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set @@ -802,8 +808,6 @@ CONFIG_8139TOO=m # CONFIG_WLAN_PRE80211 is not set CONFIG_WLAN_80211=y # CONFIG_PCMCIA_RAYCS is not set -# CONFIG_IPW2100 is not set -# CONFIG_IPW2200 is not set CONFIG_LIBERTAS=m # CONFIG_LIBERTAS_USB is not set # CONFIG_LIBERTAS_CS is not set @@ -816,9 +820,15 @@ CONFIG_LIBERTAS_SDIO=m # CONFIG_PRISM54 is not set # CONFIG_USB_ZD1201 is not set # CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_IPW2100 is not set +# CONFIG_IPW2200 is not set # CONFIG_IWLWIFI_LEDS is not set # CONFIG_HOSTAP is not set +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + # # USB Network Adapters # @@ -888,19 +898,18 @@ CONFIG_INPUT_TOUCHSCREEN=y # CONFIG_TOUCHSCREEN_FUJITSU is not set # CONFIG_TOUCHSCREEN_GUNZE is not set # CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set # CONFIG_TOUCHSCREEN_MTOUCH is not set # CONFIG_TOUCHSCREEN_INEXIO is not set # CONFIG_TOUCHSCREEN_MK712 is not set # CONFIG_TOUCHSCREEN_PENMOUNT is not set # CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set # CONFIG_TOUCHSCREEN_TOUCHWIN is not set -CONFIG_TOUCHSCREEN_WM97XX=m -# CONFIG_TOUCHSCREEN_WM9705 is not set -CONFIG_TOUCHSCREEN_WM9712=y -# CONFIG_TOUCHSCREEN_WM9713 is not set -# CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE is not set +CONFIG_TOUCHSCREEN_UCB1400=m +# CONFIG_TOUCHSCREEN_WM97XX is not set # CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set # CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set # CONFIG_INPUT_MISC is not set # @@ -939,6 +948,7 @@ CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=16 # CONFIG_IPMI_HANDLER is not set @@ -1021,7 +1031,6 @@ CONFIG_I2C_PXA=y # CONFIG_PCF8575 is not set # CONFIG_SENSORS_PCA9539 is not set # CONFIG_SENSORS_PCF8591 is not set -# CONFIG_TPS65010 is not set # CONFIG_SENSORS_MAX6875 is not set # CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set @@ -1036,6 +1045,7 @@ CONFIG_SPI_MASTER=y # SPI Master Controller Drivers # # CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_GPIO is not set CONFIG_SPI_PXA2XX=m # @@ -1091,14 +1101,17 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_ASIC3 is not set # CONFIG_HTC_EGPIO is not set # CONFIG_HTC_PASIC3 is not set -# CONFIG_UCB1400_CORE is not set +CONFIG_UCB1400_CORE=m +# CONFIG_TPS65010 is not set +# CONFIG_TWL4030_CORE is not set # CONFIG_MFD_TMIO is not set # CONFIG_MFD_T7L66XB is not set # CONFIG_MFD_TC6387XB is not set # CONFIG_MFD_TC6393XB is not set -CONFIG_PMIC_DA903X=y +# CONFIG_PMIC_DA903X is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set # # Multimedia devices @@ -1173,6 +1186,7 @@ CONFIG_VIDEO_CAPTURE_DRIVERS=y # CONFIG_VIDEO_TCM825X is not set # CONFIG_VIDEO_SAA711X is not set # CONFIG_VIDEO_SAA717X is not set +# CONFIG_VIDEO_TVP514X is not set # CONFIG_VIDEO_TVP5150 is not set # @@ -1208,8 +1222,11 @@ CONFIG_VIDEO_CAPTURE_DRIVERS=y CONFIG_SOC_CAMERA=m # CONFIG_SOC_CAMERA_MT9M001 is not set CONFIG_SOC_CAMERA_MT9M111=m +# CONFIG_SOC_CAMERA_MT9T031 is not set # CONFIG_SOC_CAMERA_MT9V022 is not set +# CONFIG_SOC_CAMERA_TW9910 is not set # CONFIG_SOC_CAMERA_PLATFORM is not set +# CONFIG_SOC_CAMERA_OV772X is not set CONFIG_VIDEO_PXA27x=m # CONFIG_VIDEO_SH_MOBILE_CEU is not set # CONFIG_V4L_USB_DRIVERS is not set @@ -1270,6 +1287,7 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_PM3 is not set # CONFIG_FB_CARMINE is not set CONFIG_FB_PXA=y +# CONFIG_FB_PXA_OVERLAY is not set # CONFIG_FB_PXA_SMARTPANEL is not set CONFIG_FB_PXA_PARAMETERS=y CONFIG_FB_MBX=m @@ -1278,15 +1296,8 @@ CONFIG_FB_MBX=m # CONFIG_FB_METRONOME is not set # CONFIG_FB_MB862XX is not set CONFIG_BACKLIGHT_LCD_SUPPORT=y -CONFIG_LCD_CLASS_DEVICE=m -# CONFIG_LCD_LTV350QV is not set -# CONFIG_LCD_ILI9320 is not set -CONFIG_LCD_TDO24M=m -# CONFIG_LCD_VGG2432A4 is not set -# CONFIG_LCD_PLATFORM is not set -CONFIG_BACKLIGHT_CLASS_DEVICE=m -# CONFIG_BACKLIGHT_CORGI is not set -CONFIG_BACKLIGHT_DA903X=m +# CONFIG_LCD_CLASS_DEVICE is not set +# CONFIG_BACKLIGHT_CLASS_DEVICE is not set # # Display device support @@ -1335,13 +1346,7 @@ CONFIG_SND_PXA2XX_AC97=m # CONFIG_SND_SPI is not set # CONFIG_SND_USB is not set # CONFIG_SND_PCMCIA is not set -CONFIG_SND_SOC=m -CONFIG_SND_SOC_AC97_BUS=y -CONFIG_SND_PXA2XX_SOC=m -CONFIG_SND_PXA2XX_SOC_AC97=m -CONFIG_SND_PXA2XX_SOC_EM_X270=m -# CONFIG_SND_SOC_ALL_CODECS is not set -CONFIG_SND_SOC_WM9712=m +# CONFIG_SND_SOC is not set # CONFIG_SOUND_PRIME is not set CONFIG_AC97_BUS=m CONFIG_HID_SUPPORT=y @@ -1363,11 +1368,9 @@ CONFIG_HID_COMPAT=y CONFIG_HID_A4TECH=y CONFIG_HID_APPLE=y CONFIG_HID_BELKIN=y -CONFIG_HID_BRIGHT=y CONFIG_HID_CHERRY=y CONFIG_HID_CHICONY=y CONFIG_HID_CYPRESS=y -CONFIG_HID_DELL=y CONFIG_HID_EZKEY=y CONFIG_HID_GYRATION=y CONFIG_HID_LOGITECH=y @@ -1375,12 +1378,15 @@ CONFIG_HID_LOGITECH=y # CONFIG_LOGIRUMBLEPAD2_FF is not set CONFIG_HID_MICROSOFT=y CONFIG_HID_MONTEREY=y +# CONFIG_HID_NTRIG is not set CONFIG_HID_PANTHERLORD=y # CONFIG_PANTHERLORD_FF is not set CONFIG_HID_PETALYNX=y CONFIG_HID_SAMSUNG=y CONFIG_HID_SONY=y CONFIG_HID_SUNPLUS=y +# CONFIG_GREENASIA_FF is not set +# CONFIG_HID_TOPSEED is not set # CONFIG_THRUSTMASTER_FF is not set # CONFIG_ZEROPLUS_FF is not set CONFIG_USB_SUPPORT=y @@ -1410,6 +1416,7 @@ CONFIG_USB_MON=y # # CONFIG_USB_C67X00_HCD is not set # CONFIG_USB_EHCI_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set CONFIG_USB_OHCI_HCD=y @@ -1443,7 +1450,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DATAFAB is not set # CONFIG_USB_STORAGE_FREECOM is not set # CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set # CONFIG_USB_STORAGE_USBAT is not set # CONFIG_USB_STORAGE_SDDR09 is not set # CONFIG_USB_STORAGE_SDDR55 is not set @@ -1490,6 +1496,11 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_ISIGHTFW is not set # CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_USB_GPIO_VBUS is not set # CONFIG_UWB is not set CONFIG_MMC=m # CONFIG_MMC_DEBUG is not set @@ -1522,7 +1533,6 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_PCA9532 is not set CONFIG_LEDS_GPIO=m # CONFIG_LEDS_PCA955X is not set -CONFIG_LEDS_DA903X=m # # LED Triggers @@ -1594,14 +1604,11 @@ CONFIG_RTC_DRV_V3020=y # on-CPU RTC drivers # CONFIG_RTC_DRV_SA1100=y +# CONFIG_RTC_DRV_PXA is not set # CONFIG_DMADEVICES is not set -CONFIG_REGULATOR=y -# CONFIG_REGULATOR_DEBUG is not set -# CONFIG_REGULATOR_FIXED_VOLTAGE is not set -# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set -# CONFIG_REGULATOR_BQ24022 is not set -CONFIG_REGULATOR_DA903X=m +# CONFIG_REGULATOR is not set # CONFIG_UIO is not set +# CONFIG_STAGING is not set # # File systems @@ -1622,6 +1629,7 @@ CONFIG_FS_MBCACHE=y CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set # CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y @@ -1657,10 +1665,7 @@ CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set # CONFIG_CONFIGFS_FS is not set - -# -# Miscellaneous filesystems -# +CONFIG_MISC_FILESYSTEMS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set @@ -1680,6 +1685,7 @@ CONFIG_JFFS2_ZLIB=y CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set # CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_OMFS_FS is not set @@ -1811,6 +1817,7 @@ CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set CONFIG_FRAME_POINTER=y # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set @@ -1830,6 +1837,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y # CONFIG_SCHED_TRACER is not set # CONFIG_CONTEXT_SWITCH_TRACER is not set # CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set # CONFIG_STACK_TRACER is not set # CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set @@ -1855,6 +1863,7 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_FIPS is not set # CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_CRYPTD is not set @@ -1937,6 +1946,7 @@ CONFIG_CRYPTO=y # Library routines # CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y CONFIG_CRC_CCITT=m # CONFIG_CRC16 is not set # CONFIG_CRC_T10DIF is not set -- GitLab From 432dc14fa40dea427d9ed476965001a816ff833b Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Mon, 2 Feb 2009 08:57:58 +0200 Subject: [PATCH 1118/4982] [ARM] pxa: add em_x270_defconfig for EM-X270 and eXeda machines Signed-off-by: Mike Rapoport Signed-off-by: Eric Miao --- arch/arm/configs/em_x270_defconfig | 1741 ++++++++++++++++++++++++++++ 1 file changed, 1741 insertions(+) create mode 100644 arch/arm/configs/em_x270_defconfig diff --git a/arch/arm/configs/em_x270_defconfig b/arch/arm/configs/em_x270_defconfig new file mode 100644 index 00000000000..1f759601e3b --- /dev/null +++ b/arch/arm/configs/em_x270_defconfig @@ -0,0 +1,1741 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.29-rc2 +# Sun Feb 1 16:43:31 2009 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_MTD_XIP=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set +# CONFIG_CGROUPS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +# CONFIG_COMPAT_BRK is not set +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +# CONFIG_VM_EVENT_COUNTERS is not set +# CONFIG_SLUB_DEBUG is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +CONFIG_FREEZER=y + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +CONFIG_ARCH_PXA=y +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_W90X900 is not set + +# +# Intel PXA2xx/PXA3xx Implementations +# +# CONFIG_ARCH_GUMSTIX is not set +# CONFIG_MACH_INTELMOTE2 is not set +# CONFIG_ARCH_LUBBOCK is not set +# CONFIG_MACH_LOGICPD_PXA270 is not set +# CONFIG_MACH_MAINSTONE is not set +# CONFIG_MACH_MP900C is not set +# CONFIG_ARCH_PXA_IDP is not set +# CONFIG_PXA_SHARPSL is not set +# CONFIG_ARCH_VIPER is not set +# CONFIG_ARCH_PXA_ESERIES is not set +# CONFIG_TRIZEPS_PXA is not set +# CONFIG_MACH_H5000 is not set +CONFIG_MACH_EM_X270=y +CONFIG_MACH_EXEDA=y +# CONFIG_MACH_COLIBRI is not set +# CONFIG_MACH_ZYLONITE is not set +# CONFIG_MACH_LITTLETON is not set +# CONFIG_MACH_TAVOREVB is not set +# CONFIG_MACH_SAAR is not set +# CONFIG_MACH_ARMCORE is not set +# CONFIG_MACH_CM_X300 is not set +# CONFIG_MACH_MAGICIAN is not set +# CONFIG_MACH_MIOA701 is not set +# CONFIG_MACH_PCM027 is not set +# CONFIG_ARCH_PXA_PALM is not set +# CONFIG_PXA_EZX is not set +CONFIG_PXA27x=y +CONFIG_PXA_SSP=y +# CONFIG_PXA_PWM is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_XSCALE=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_OUTER_CACHE is not set +CONFIG_IWMMXT=y +CONFIG_XSCALE_PMU=y +CONFIG_COMMON_CLKDEV=y + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="root=1f03 mem=32M" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +# CONFIG_CPU_FREQ_DEBUG is not set +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +CONFIG_CPU_FREQ_GOV_USERSPACE=m +# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +CONFIG_PM_SLEEP=y +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_APM_EMULATION=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_COMPAT_NET_DEV_OPS=y +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +# CONFIG_BT_RFCOMM_TTY is not set +CONFIG_BT_BNEP=m +# CONFIG_BT_BNEP_MC_FILTER is not set +# CONFIG_BT_BNEP_PROTO_FILTER is not set +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIBTUSB=m +# CONFIG_BT_HCIBTSDIO is not set +# CONFIG_BT_HCIUART is not set +# CONFIG_BT_HCIBCM203X is not set +# CONFIG_BT_HCIBPA10X is not set +# CONFIG_BT_HCIBFUSB is not set +# CONFIG_BT_HCIVHCI is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +CONFIG_WIRELESS_OLD_REGULATORY=y +CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +CONFIG_LIB80211=m +# CONFIG_MAC80211 is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=m +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_XIP is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +CONFIG_MTD_PXA2XX=y +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_SHARP_SL is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_H1900 is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_SHARPSL is not set +# CONFIG_MTD_NAND_NANDSIM is not set +CONFIG_MTD_NAND_PLATFORM=y +# CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_QINFO_PROBE is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_DH is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_PHYLIB is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +CONFIG_DM9000=y +CONFIG_DM9000_DEBUGLEVEL=1 +# CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL is not set +# CONFIG_ENC28J60 is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +CONFIG_WLAN_80211=y +CONFIG_LIBERTAS=m +# CONFIG_LIBERTAS_USB is not set +CONFIG_LIBERTAS_SDIO=m +# CONFIG_LIBERTAS_DEBUG is not set +# CONFIG_USB_ZD1201 is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_IWLWIFI_LEDS is not set +# CONFIG_HOSTAP is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_WAN is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +# CONFIG_PPP_MPPE is not set +# CONFIG_PPPOE is not set +# CONFIG_PPPOL2TP is not set +# CONFIG_SLIP is not set +CONFIG_SLHC=m +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set +CONFIG_INPUT_APMPOWER=y + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +CONFIG_KEYBOARD_PXA27x=y +CONFIG_KEYBOARD_GPIO=y +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_DA9034 is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +CONFIG_TOUCHSCREEN_WM97XX=m +# CONFIG_TOUCHSCREEN_WM9705 is not set +CONFIG_TOUCHSCREEN_WM9712=y +# CONFIG_TOUCHSCREEN_WM9713 is not set +# CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +# CONFIG_SERIO_SERPORT is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_PXA=y +CONFIG_SERIAL_PXA_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_NVRAM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=m +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_PXA=y +# CONFIG_I2C_PXA_SLAVE is not set +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_AT24 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_GPIO is not set +CONFIG_SPI_PXA2XX=y + +# +# SPI Protocol Masters +# +# CONFIG_SPI_AT25 is not set +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_GPIO_SYSFS is not set + +# +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_W1 is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_APM_POWER is not set +# CONFIG_BATTERY_DS2760 is not set +# CONFIG_BATTERY_BQ27x00 is not set +CONFIG_BATTERY_DA9030=y +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_UCB1400_CORE is not set +# CONFIG_TPS65010 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +CONFIG_PMIC_DA903X=y +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L2_COMMON=m +# CONFIG_VIDEO_ALLOW_V4L1 is not set +CONFIG_VIDEO_V4L1_COMPAT=y +# CONFIG_DVB_CORE is not set +CONFIG_VIDEO_MEDIA=m + +# +# Multimedia drivers +# +# CONFIG_MEDIA_ATTACH is not set +CONFIG_MEDIA_TUNER=m +CONFIG_MEDIA_TUNER_CUSTOMIZE=y +# CONFIG_MEDIA_TUNER_SIMPLE is not set +# CONFIG_MEDIA_TUNER_TDA8290 is not set +# CONFIG_MEDIA_TUNER_TDA827X is not set +# CONFIG_MEDIA_TUNER_TDA18271 is not set +# CONFIG_MEDIA_TUNER_TDA9887 is not set +# CONFIG_MEDIA_TUNER_TEA5761 is not set +# CONFIG_MEDIA_TUNER_TEA5767 is not set +# CONFIG_MEDIA_TUNER_MT20XX is not set +# CONFIG_MEDIA_TUNER_MT2060 is not set +# CONFIG_MEDIA_TUNER_MT2266 is not set +# CONFIG_MEDIA_TUNER_MT2131 is not set +# CONFIG_MEDIA_TUNER_QT1010 is not set +# CONFIG_MEDIA_TUNER_XC2028 is not set +# CONFIG_MEDIA_TUNER_XC5000 is not set +# CONFIG_MEDIA_TUNER_MXL5005S is not set +# CONFIG_MEDIA_TUNER_MXL5007T is not set +CONFIG_VIDEO_V4L2=m +CONFIG_VIDEOBUF_GEN=m +CONFIG_VIDEOBUF_DMA_SG=m +CONFIG_VIDEO_CAPTURE_DRIVERS=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set + +# +# Encoders/decoders and other helper chips +# + +# +# Audio decoders +# +# CONFIG_VIDEO_TVAUDIO is not set +# CONFIG_VIDEO_TDA7432 is not set +# CONFIG_VIDEO_TDA9840 is not set +# CONFIG_VIDEO_TDA9875 is not set +# CONFIG_VIDEO_TEA6415C is not set +# CONFIG_VIDEO_TEA6420 is not set +# CONFIG_VIDEO_MSP3400 is not set +# CONFIG_VIDEO_CS5345 is not set +# CONFIG_VIDEO_CS53L32A is not set +# CONFIG_VIDEO_M52790 is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_WM8775 is not set +# CONFIG_VIDEO_WM8739 is not set +# CONFIG_VIDEO_VP27SMPX is not set + +# +# Video decoders +# +# CONFIG_VIDEO_OV7670 is not set +# CONFIG_VIDEO_TCM825X is not set +# CONFIG_VIDEO_SAA711X is not set +# CONFIG_VIDEO_SAA717X is not set +# CONFIG_VIDEO_TVP514X is not set +# CONFIG_VIDEO_TVP5150 is not set + +# +# Video and audio decoders +# +# CONFIG_VIDEO_CX25840 is not set + +# +# MPEG video encoders +# +# CONFIG_VIDEO_CX2341X is not set + +# +# Video encoders +# +# CONFIG_VIDEO_SAA7127 is not set + +# +# Video improvement chips +# +# CONFIG_VIDEO_UPD64031A is not set +# CONFIG_VIDEO_UPD64083 is not set +# CONFIG_VIDEO_VIVI is not set +# CONFIG_VIDEO_SAA5246A is not set +# CONFIG_VIDEO_SAA5249 is not set +CONFIG_SOC_CAMERA=m +# CONFIG_SOC_CAMERA_MT9M001 is not set +CONFIG_SOC_CAMERA_MT9M111=m +# CONFIG_SOC_CAMERA_MT9T031 is not set +# CONFIG_SOC_CAMERA_MT9V022 is not set +# CONFIG_SOC_CAMERA_TW9910 is not set +# CONFIG_SOC_CAMERA_PLATFORM is not set +# CONFIG_SOC_CAMERA_OV772X is not set +CONFIG_VIDEO_PXA27x=m +# CONFIG_VIDEO_SH_MOBILE_CEU is not set +# CONFIG_V4L_USB_DRIVERS is not set +# CONFIG_RADIO_ADAPTERS is not set +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_PXA=y +# CONFIG_FB_PXA_OVERLAY is not set +# CONFIG_FB_PXA_SMARTPANEL is not set +CONFIG_FB_PXA_PARAMETERS=y +CONFIG_FB_MBX=m +# CONFIG_FB_MBX_DEBUG is not set +# CONFIG_FB_W100 is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=y +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_ILI9320 is not set +CONFIG_LCD_TDO24M=y +# CONFIG_LCD_VGG2432A4 is not set +# CONFIG_LCD_PLATFORM is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=m +# CONFIG_BACKLIGHT_GENERIC is not set +CONFIG_BACKLIGHT_DA903X=m + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_SOUND=m +CONFIG_SOUND_OSS_CORE=y +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +# CONFIG_SND_SEQUENCER is not set +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +CONFIG_SND_VMASTER=y +CONFIG_SND_AC97_CODEC=m +# CONFIG_SND_DRIVERS is not set +CONFIG_SND_ARM=y +CONFIG_SND_PXA2XX_LIB=m +CONFIG_SND_PXA2XX_LIB_AC97=y +# CONFIG_SND_PXA2XX_AC97 is not set +# CONFIG_SND_SPI is not set +# CONFIG_SND_USB is not set +CONFIG_SND_SOC=m +CONFIG_SND_SOC_AC97_BUS=y +CONFIG_SND_PXA2XX_SOC=m +CONFIG_SND_PXA2XX_SOC_AC97=m +CONFIG_SND_PXA2XX_SOC_EM_X270=m +CONFIG_SND_SOC_I2C_AND_SPI=m +# CONFIG_SND_SOC_ALL_CODECS is not set +CONFIG_SND_SOC_WM9712=m +# CONFIG_SOUND_PRIME is not set +CONFIG_AC97_BUS=m +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +CONFIG_HID_DEBUG=y +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV is not set + +# +# Special HID drivers +# +CONFIG_HID_COMPAT=y +CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_EZKEY=y +CONFIG_HID_GYRATION=y +CONFIG_HID_LOGITECH=y +# CONFIG_LOGITECH_FF is not set +# CONFIG_LOGIRUMBLEPAD2_FF is not set +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +# CONFIG_HID_NTRIG is not set +CONFIG_HID_PANTHERLORD=y +# CONFIG_PANTHERLORD_FF is not set +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SONY=y +CONFIG_HID_SUNPLUS=y +# CONFIG_GREENASIA_FF is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_THRUSTMASTER_FF is not set +# CONFIG_ZEROPLUS_FF is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_DEVICE_CLASS is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +CONFIG_USB_MON=y +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +# CONFIG_USB_MUSB_HDRC is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; +# + +# +# see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set +# CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_USB_GPIO_VBUS is not set +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=m +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +CONFIG_MMC_PXA=m +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_SPI is not set +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_PCA955X is not set +CONFIG_LEDS_DA903X=y + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +# CONFIG_LEDS_TRIGGER_TIMER is not set +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +CONFIG_RTC_DRV_V3020=y + +# +# on-CPU RTC drivers +# +CONFIG_RTC_DRV_SA1100=y +# CONFIG_RTC_DRV_PXA is not set +# CONFIG_DMADEVICES is not set +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_BQ24022 is not set +CONFIG_REGULATOR_DA903X=y +# CONFIG_UIO is not set +# CONFIG_STAGING is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +# CONFIG_PROC_PAGE_MONITOR is not set +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_REGISTER_V4 is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set +# CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=m +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=m +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=m +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=0 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_DETECT_SOFTLOCKUP is not set +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_HAVE_FUNCTION_TRACER=y + +# +# Tracers +# +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=m +CONFIG_CRYPTO_ALGAPI2=m +CONFIG_CRYPTO_AEAD2=m +CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_BLKCIPHER2=m +CONFIG_CRYPTO_HASH=m +CONFIG_CRYPTO_HASH2=m +CONFIG_CRYPTO_RNG2=m +CONFIG_CRYPTO_MANAGER=m +CONFIG_CRYPTO_MANAGER2=m +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=m +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +CONFIG_CRYPTO_MICHAEL_MIC=m +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y -- GitLab From db8ac47cfccaafd3fa4c5c15320809d44f4fcef9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 4 Nov 2008 15:10:54 +0000 Subject: [PATCH 1119/4982] [ARM] omap: remove VIRTUAL_CLOCK Nothing tests the clock flags for this bit, so it serves no purpose. Remove it. Signed-off-by: Russell King --- arch/arm/mach-omap1/clock.h | 8 +++----- arch/arm/mach-omap2/clock24xx.h | 2 +- arch/arm/plat-omap/include/mach/clock.h | 1 - 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h index c1dcdf18d8d..d4ccba464b4 100644 --- a/arch/arm/mach-omap1/clock.h +++ b/arch/arm/mach-omap1/clock.h @@ -734,7 +734,7 @@ static struct clk mmc2_ck = { static struct clk virtual_ck_mpu = { .name = "mpu", .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP310 | VIRTUAL_CLOCK | ALWAYS_ENABLED, + CLOCK_IN_OMAP310 | ALWAYS_ENABLED, .parent = &arm_ck, /* Is smarter alias for */ .recalc = &followparent_recalc, .set_rate = &omap1_select_table_rate, @@ -749,8 +749,7 @@ static struct clk i2c_fck = { .name = "i2c_fck", .id = 1, .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - VIRTUAL_CLOCK | CLOCK_NO_IDLE_PARENT | - ALWAYS_ENABLED, + CLOCK_NO_IDLE_PARENT | ALWAYS_ENABLED, .parent = &armxor_ck.clk, .recalc = &followparent_recalc, .enable = &omap1_clk_enable_generic, @@ -760,8 +759,7 @@ static struct clk i2c_fck = { static struct clk i2c_ick = { .name = "i2c_ick", .id = 1, - .flags = CLOCK_IN_OMAP16XX | - VIRTUAL_CLOCK | CLOCK_NO_IDLE_PARENT | + .flags = CLOCK_IN_OMAP16XX | CLOCK_NO_IDLE_PARENT | ALWAYS_ENABLED, .parent = &armper_ck.clk, .recalc = &followparent_recalc, diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h index ad6d98d177c..8c57a2e180f 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock24xx.h @@ -2629,7 +2629,7 @@ static struct clk mmchsdb2_fck = { static struct clk virt_prcm_set = { .name = "virt_prcm_set", .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - VIRTUAL_CLOCK | ALWAYS_ENABLED | DELAYED_APP, + ALWAYS_ENABLED | DELAYED_APP, .parent = &mpu_ck, /* Indexed by mpu speed, no parent */ .recalc = &omap2_table_mpu_recalc, /* sets are keyed on mpu rate */ .set_rate = &omap2_select_table_rate, diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index 719298554ed..4e8f59df30b 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -125,7 +125,6 @@ extern void clk_enable_init_clocks(void); #define RATE_CKCTL (1 << 0) /* Main fixed ratio clocks */ #define RATE_FIXED (1 << 1) /* Fixed clock rate */ #define RATE_PROPAGATES (1 << 2) /* Program children too */ -#define VIRTUAL_CLOCK (1 << 3) /* Composite clock from table */ #define ALWAYS_ENABLED (1 << 4) /* Clock cannot be disabled */ #define ENABLE_REG_32BIT (1 << 5) /* Use 32-bit access */ #define VIRTUAL_IO_ADDRESS (1 << 6) /* Clock in virtual address */ -- GitLab From 548d849574847b788fe846fe21a41386063be161 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 4 Nov 2008 14:02:46 +0000 Subject: [PATCH 1120/4982] [ARM] omap: introduce clock operations structure Collect up all the common enable/disable clock operation functions into a separate operations structure. Signed-off-by: Russell King --- arch/arm/mach-omap1/clock.c | 30 ++++- arch/arm/mach-omap1/clock.h | 152 ++++++++---------------- arch/arm/mach-omap2/clock.c | 8 +- arch/arm/mach-omap2/clock24xx.c | 16 ++- arch/arm/mach-omap2/clock24xx.h | 13 +- arch/arm/mach-omap2/clock34xx.c | 10 +- arch/arm/mach-omap2/clock34xx.h | 11 +- arch/arm/plat-omap/include/mach/clock.h | 8 +- 8 files changed, 115 insertions(+), 133 deletions(-) diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index 5fba2073171..25ef04da6b0 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -26,8 +26,17 @@ #include #include +static const struct clkops clkops_generic; +static const struct clkops clkops_uart; +static const struct clkops clkops_dspck; + #include "clock.h" +static int omap1_clk_enable_generic(struct clk * clk); +static int omap1_clk_enable(struct clk *clk); +static void omap1_clk_disable_generic(struct clk * clk); +static void omap1_clk_disable(struct clk *clk); + __u32 arm_idlect1_mask; /*------------------------------------------------------------------------- @@ -78,6 +87,11 @@ static void omap1_clk_disable_dsp_domain(struct clk *clk) } } +static const struct clkops clkops_dspck = { + .enable = &omap1_clk_enable_dsp_domain, + .disable = &omap1_clk_disable_dsp_domain, +}; + static int omap1_clk_enable_uart_functional(struct clk *clk) { int ret; @@ -105,6 +119,11 @@ static void omap1_clk_disable_uart_functional(struct clk *clk) omap1_clk_disable_generic(clk); } +static const struct clkops clkops_uart = { + .enable = &omap1_clk_enable_uart_functional, + .disable = &omap1_clk_disable_uart_functional, +}; + static void omap1_clk_allow_idle(struct clk *clk) { struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk; @@ -468,7 +487,7 @@ static int omap1_clk_enable(struct clk *clk) omap1_clk_deny_idle(clk->parent); } - ret = clk->enable(clk); + ret = clk->ops->enable(clk); if (unlikely(ret != 0) && clk->parent) { omap1_clk_disable(clk->parent); @@ -482,7 +501,7 @@ static int omap1_clk_enable(struct clk *clk) static void omap1_clk_disable(struct clk *clk) { if (clk->usecount > 0 && !(--clk->usecount)) { - clk->disable(clk); + clk->ops->disable(clk); if (likely(clk->parent)) { omap1_clk_disable(clk->parent); if (clk->flags & CLOCK_NO_IDLE_PARENT) @@ -561,6 +580,11 @@ static void omap1_clk_disable_generic(struct clk *clk) } } +static const struct clkops clkops_generic = { + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, +}; + static long omap1_clk_round_rate(struct clk *clk, unsigned long rate) { int dsor_exp; @@ -659,7 +683,7 @@ static void __init omap1_clk_disable_unused(struct clk *clk) } printk(KERN_INFO "Disabling unused clock \"%s\"... ", clk->name); - clk->disable(clk); + clk->ops->disable(clk); printk(" done\n"); } diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h index d4ccba464b4..5b93a2a897a 100644 --- a/arch/arm/mach-omap1/clock.h +++ b/arch/arm/mach-omap1/clock.h @@ -13,27 +13,19 @@ #ifndef __ARCH_ARM_MACH_OMAP1_CLOCK_H #define __ARCH_ARM_MACH_OMAP1_CLOCK_H -static int omap1_clk_enable_generic(struct clk * clk); -static void omap1_clk_disable_generic(struct clk * clk); static void omap1_ckctl_recalc(struct clk * clk); static void omap1_watchdog_recalc(struct clk * clk); static int omap1_set_sossi_rate(struct clk *clk, unsigned long rate); static void omap1_sossi_recalc(struct clk *clk); static void omap1_ckctl_recalc_dsp_domain(struct clk * clk); -static int omap1_clk_enable_dsp_domain(struct clk * clk); static int omap1_clk_set_rate_dsp_domain(struct clk * clk, unsigned long rate); -static void omap1_clk_disable_dsp_domain(struct clk * clk); static int omap1_set_uart_rate(struct clk * clk, unsigned long rate); static void omap1_uart_recalc(struct clk * clk); -static int omap1_clk_enable_uart_functional(struct clk * clk); -static void omap1_clk_disable_uart_functional(struct clk * clk); static int omap1_set_ext_clk_rate(struct clk * clk, unsigned long rate); static long omap1_round_ext_clk_rate(struct clk * clk, unsigned long rate); static void omap1_init_ext_clk(struct clk * clk); static int omap1_select_table_rate(struct clk * clk, unsigned long rate); static long omap1_round_to_table_rate(struct clk * clk, unsigned long rate); -static int omap1_clk_enable(struct clk *clk); -static void omap1_clk_disable(struct clk *clk); struct mpu_rate { unsigned long rate; @@ -152,39 +144,37 @@ static struct mpu_rate rate_table[] = { static struct clk ck_ref = { .name = "ck_ref", + .ops = &clkops_generic, .rate = 12000000, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | ALWAYS_ENABLED, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk ck_dpll1 = { .name = "ck_dpll1", + .ops = &clkops_generic, .parent = &ck_ref, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | RATE_PROPAGATES | ALWAYS_ENABLED, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct arm_idlect1_clk ck_dpll1out = { .clk = { .name = "ck_dpll1out", + .ops = &clkops_generic, .parent = &ck_dpll1, .flags = CLOCK_IN_OMAP16XX | CLOCK_IDLE_CONTROL | ENABLE_REG_32BIT | RATE_PROPAGATES, .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_CKOUT_ARM, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }, .idlect_shift = 12, }; static struct clk sossi_ck = { .name = "ck_sossi", + .ops = &clkops_generic, .parent = &ck_dpll1out.clk, .flags = CLOCK_IN_OMAP16XX | CLOCK_NO_IDLE_PARENT | ENABLE_REG_32BIT, @@ -192,25 +182,23 @@ static struct clk sossi_ck = { .enable_bit = 16, .recalc = &omap1_sossi_recalc, .set_rate = &omap1_set_sossi_rate, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk arm_ck = { .name = "arm_ck", + .ops = &clkops_generic, .parent = &ck_dpll1, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED, .rate_offset = CKCTL_ARMDIV_OFFSET, .recalc = &omap1_ckctl_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct arm_idlect1_clk armper_ck = { .clk = { .name = "armper_ck", + .ops = &clkops_generic, .parent = &ck_dpll1, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | RATE_CKCTL | @@ -219,34 +207,30 @@ static struct arm_idlect1_clk armper_ck = { .enable_bit = EN_PERCK, .rate_offset = CKCTL_PERDIV_OFFSET, .recalc = &omap1_ckctl_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }, .idlect_shift = 2, }; static struct clk arm_gpio_ck = { .name = "arm_gpio_ck", + .ops = &clkops_generic, .parent = &ck_dpll1, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_GPIOCK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct arm_idlect1_clk armxor_ck = { .clk = { .name = "armxor_ck", + .ops = &clkops_generic, .parent = &ck_ref, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL, .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_XORPCK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }, .idlect_shift = 1, }; @@ -254,14 +238,13 @@ static struct arm_idlect1_clk armxor_ck = { static struct arm_idlect1_clk armtim_ck = { .clk = { .name = "armtim_ck", + .ops = &clkops_generic, .parent = &ck_ref, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL, .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_TIMCK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }, .idlect_shift = 9, }; @@ -269,20 +252,20 @@ static struct arm_idlect1_clk armtim_ck = { static struct arm_idlect1_clk armwdt_ck = { .clk = { .name = "armwdt_ck", + .ops = &clkops_generic, .parent = &ck_ref, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL, .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_WDTCK, .recalc = &omap1_watchdog_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }, .idlect_shift = 0, }; static struct clk arminth_ck16xx = { .name = "arminth_ck", + .ops = &clkops_generic, .parent = &arm_ck, .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, .recalc = &followparent_recalc, @@ -291,12 +274,11 @@ static struct clk arminth_ck16xx = { * * 1510 version is in TC clocks. */ - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk dsp_ck = { .name = "dsp_ck", + .ops = &clkops_generic, .parent = &ck_dpll1, .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | RATE_CKCTL, @@ -304,23 +286,21 @@ static struct clk dsp_ck = { .enable_bit = EN_DSPCK, .rate_offset = CKCTL_DSPDIV_OFFSET, .recalc = &omap1_ckctl_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk dspmmu_ck = { .name = "dspmmu_ck", + .ops = &clkops_generic, .parent = &ck_dpll1, .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | RATE_CKCTL | ALWAYS_ENABLED, .rate_offset = CKCTL_DSPMMUDIV_OFFSET, .recalc = &omap1_ckctl_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk dspper_ck = { .name = "dspper_ck", + .ops = &clkops_dspck, .parent = &ck_dpll1, .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | RATE_CKCTL | VIRTUAL_IO_ADDRESS, @@ -329,38 +309,35 @@ static struct clk dspper_ck = { .rate_offset = CKCTL_PERDIV_OFFSET, .recalc = &omap1_ckctl_recalc_dsp_domain, .set_rate = &omap1_clk_set_rate_dsp_domain, - .enable = &omap1_clk_enable_dsp_domain, - .disable = &omap1_clk_disable_dsp_domain, }; static struct clk dspxor_ck = { .name = "dspxor_ck", + .ops = &clkops_dspck, .parent = &ck_ref, .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | VIRTUAL_IO_ADDRESS, .enable_reg = DSP_IDLECT2, .enable_bit = EN_XORPCK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable_dsp_domain, - .disable = &omap1_clk_disable_dsp_domain, }; static struct clk dsptim_ck = { .name = "dsptim_ck", + .ops = &clkops_dspck, .parent = &ck_ref, .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | VIRTUAL_IO_ADDRESS, .enable_reg = DSP_IDLECT2, .enable_bit = EN_DSPTIMCK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable_dsp_domain, - .disable = &omap1_clk_disable_dsp_domain, }; /* Tie ARM_IDLECT1:IDLIF_ARM to this logical clock structure */ static struct arm_idlect1_clk tc_ck = { .clk = { .name = "tc_ck", + .ops = &clkops_generic, .parent = &ck_dpll1, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP730 | CLOCK_IN_OMAP310 | @@ -368,14 +345,13 @@ static struct arm_idlect1_clk tc_ck = { ALWAYS_ENABLED | CLOCK_IDLE_CONTROL, .rate_offset = CKCTL_TCDIV_OFFSET, .recalc = &omap1_ckctl_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }, .idlect_shift = 6, }; static struct clk arminth_ck1510 = { .name = "arminth_ck", + .ops = &clkops_generic, .parent = &tc_ck.clk, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | ALWAYS_ENABLED, @@ -384,86 +360,77 @@ static struct clk arminth_ck1510 = { * * 16xx version is in MPU clocks. */ - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk tipb_ck = { /* No-idle controlled by "tc_ck" */ .name = "tipb_ck", + .ops = &clkops_generic, .parent = &tc_ck.clk, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | ALWAYS_ENABLED, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk l3_ocpi_ck = { /* No-idle controlled by "tc_ck" */ .name = "l3_ocpi_ck", + .ops = &clkops_generic, .parent = &tc_ck.clk, .flags = CLOCK_IN_OMAP16XX, .enable_reg = (void __iomem *)ARM_IDLECT3, .enable_bit = EN_OCPI_CK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk tc1_ck = { .name = "tc1_ck", + .ops = &clkops_generic, .parent = &tc_ck.clk, .flags = CLOCK_IN_OMAP16XX, .enable_reg = (void __iomem *)ARM_IDLECT3, .enable_bit = EN_TC1_CK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk tc2_ck = { .name = "tc2_ck", + .ops = &clkops_generic, .parent = &tc_ck.clk, .flags = CLOCK_IN_OMAP16XX, .enable_reg = (void __iomem *)ARM_IDLECT3, .enable_bit = EN_TC2_CK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk dma_ck = { /* No-idle controlled by "tc_ck" */ .name = "dma_ck", + .ops = &clkops_generic, .parent = &tc_ck.clk, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | ALWAYS_ENABLED, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk dma_lcdfree_ck = { .name = "dma_lcdfree_ck", + .ops = &clkops_generic, .parent = &tc_ck.clk, .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct arm_idlect1_clk api_ck = { .clk = { .name = "api_ck", + .ops = &clkops_generic, .parent = &tc_ck.clk, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL, .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_APICK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }, .idlect_shift = 8, }; @@ -471,51 +438,48 @@ static struct arm_idlect1_clk api_ck = { static struct arm_idlect1_clk lb_ck = { .clk = { .name = "lb_ck", + .ops = &clkops_generic, .parent = &tc_ck.clk, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL, .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_LBCK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }, .idlect_shift = 4, }; static struct clk rhea1_ck = { .name = "rhea1_ck", + .ops = &clkops_generic, .parent = &tc_ck.clk, .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk rhea2_ck = { .name = "rhea2_ck", + .ops = &clkops_generic, .parent = &tc_ck.clk, .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk lcd_ck_16xx = { .name = "lcd_ck", + .ops = &clkops_generic, .parent = &ck_dpll1, .flags = CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP730 | RATE_CKCTL, .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_LCDCK, .rate_offset = CKCTL_LCDDIV_OFFSET, .recalc = &omap1_ckctl_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct arm_idlect1_clk lcd_ck_1510 = { .clk = { .name = "lcd_ck", + .ops = &clkops_generic, .parent = &ck_dpll1, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | RATE_CKCTL | CLOCK_IDLE_CONTROL, @@ -523,14 +487,13 @@ static struct arm_idlect1_clk lcd_ck_1510 = { .enable_bit = EN_LCDCK, .rate_offset = CKCTL_LCDDIV_OFFSET, .recalc = &omap1_ckctl_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }, .idlect_shift = 3, }; static struct clk uart1_1510 = { .name = "uart1_ck", + .ops = &clkops_generic, /* Direct from ULPD, no real parent */ .parent = &armper_ck.clk, .rate = 12000000, @@ -541,13 +504,12 @@ static struct clk uart1_1510 = { .enable_bit = 29, /* Chooses between 12MHz and 48MHz */ .set_rate = &omap1_set_uart_rate, .recalc = &omap1_uart_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct uart_clk uart1_16xx = { .clk = { .name = "uart1_ck", + .ops = &clkops_uart, /* Direct from ULPD, no real parent */ .parent = &armper_ck.clk, .rate = 48000000, @@ -555,14 +517,13 @@ static struct uart_clk uart1_16xx = { ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, .enable_bit = 29, - .enable = &omap1_clk_enable_uart_functional, - .disable = &omap1_clk_disable_uart_functional, }, .sysc_addr = 0xfffb0054, }; static struct clk uart2_ck = { .name = "uart2_ck", + .ops = &clkops_generic, /* Direct from ULPD, no real parent */ .parent = &armper_ck.clk, .rate = 12000000, @@ -573,12 +534,11 @@ static struct clk uart2_ck = { .enable_bit = 30, /* Chooses between 12MHz and 48MHz */ .set_rate = &omap1_set_uart_rate, .recalc = &omap1_uart_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk uart3_1510 = { .name = "uart3_ck", + .ops = &clkops_generic, /* Direct from ULPD, no real parent */ .parent = &armper_ck.clk, .rate = 12000000, @@ -589,13 +549,12 @@ static struct clk uart3_1510 = { .enable_bit = 31, /* Chooses between 12MHz and 48MHz */ .set_rate = &omap1_set_uart_rate, .recalc = &omap1_uart_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct uart_clk uart3_16xx = { .clk = { .name = "uart3_ck", + .ops = &clkops_uart, /* Direct from ULPD, no real parent */ .parent = &armper_ck.clk, .rate = 48000000, @@ -603,38 +562,35 @@ static struct uart_clk uart3_16xx = { ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, .enable_bit = 31, - .enable = &omap1_clk_enable_uart_functional, - .disable = &omap1_clk_disable_uart_functional, }, .sysc_addr = 0xfffb9854, }; static struct clk usb_clko = { /* 6 MHz output on W4_USB_CLKO */ .name = "usb_clko", + .ops = &clkops_generic, /* Direct from ULPD, no parent */ .rate = 6000000, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | RATE_FIXED | ENABLE_REG_32BIT, .enable_reg = (void __iomem *)ULPD_CLOCK_CTRL, .enable_bit = USB_MCLK_EN_BIT, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk usb_hhc_ck1510 = { .name = "usb_hhc_ck", + .ops = &clkops_generic, /* Direct from ULPD, no parent */ .rate = 48000000, /* Actually 2 clocks, 12MHz and 48MHz */ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | RATE_FIXED | ENABLE_REG_32BIT, .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, .enable_bit = USB_HOST_HHC_UHOST_EN, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk usb_hhc_ck16xx = { .name = "usb_hhc_ck", + .ops = &clkops_generic, /* Direct from ULPD, no parent */ .rate = 48000000, /* OTG_SYSCON_2.OTG_PADEN == 0 (not 1510-compatible) */ @@ -642,34 +598,31 @@ static struct clk usb_hhc_ck16xx = { RATE_FIXED | ENABLE_REG_32BIT, .enable_reg = (void __iomem *)OTG_BASE + 0x08 /* OTG_SYSCON_2 */, .enable_bit = 8 /* UHOST_EN */, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk usb_dc_ck = { .name = "usb_dc_ck", + .ops = &clkops_generic, /* Direct from ULPD, no parent */ .rate = 48000000, .flags = CLOCK_IN_OMAP16XX | RATE_FIXED, .enable_reg = (void __iomem *)SOFT_REQ_REG, .enable_bit = 4, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk mclk_1510 = { .name = "mclk", + .ops = &clkops_generic, /* Direct from ULPD, no parent. May be enabled by ext hardware. */ .rate = 12000000, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | RATE_FIXED, .enable_reg = (void __iomem *)SOFT_REQ_REG, .enable_bit = 6, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk mclk_16xx = { .name = "mclk", + .ops = &clkops_generic, /* Direct from ULPD, no parent. May be enabled by ext hardware. */ .flags = CLOCK_IN_OMAP16XX, .enable_reg = (void __iomem *)COM_CLK_DIV_CTRL_SEL, @@ -677,21 +630,19 @@ static struct clk mclk_16xx = { .set_rate = &omap1_set_ext_clk_rate, .round_rate = &omap1_round_ext_clk_rate, .init = &omap1_init_ext_clk, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk bclk_1510 = { .name = "bclk", + .ops = &clkops_generic, /* Direct from ULPD, no parent. May be enabled by ext hardware. */ .rate = 12000000, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | RATE_FIXED, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk bclk_16xx = { .name = "bclk", + .ops = &clkops_generic, /* Direct from ULPD, no parent. May be enabled by ext hardware. */ .flags = CLOCK_IN_OMAP16XX, .enable_reg = (void __iomem *)SWD_CLK_DIV_CTRL_SEL, @@ -699,12 +650,11 @@ static struct clk bclk_16xx = { .set_rate = &omap1_set_ext_clk_rate, .round_rate = &omap1_round_ext_clk_rate, .init = &omap1_init_ext_clk, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk mmc1_ck = { .name = "mmc_ck", + .ops = &clkops_generic, /* Functional clock is direct from ULPD, interface clock is ARMPER */ .parent = &armper_ck.clk, .rate = 48000000, @@ -713,13 +663,12 @@ static struct clk mmc1_ck = { CLOCK_NO_IDLE_PARENT, .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, .enable_bit = 23, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk mmc2_ck = { .name = "mmc_ck", .id = 1, + .ops = &clkops_generic, /* Functional clock is direct from ULPD, interface clock is ARMPER */ .parent = &armper_ck.clk, .rate = 48000000, @@ -727,20 +676,17 @@ static struct clk mmc2_ck = { RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, .enable_bit = 20, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk virtual_ck_mpu = { .name = "mpu", + .ops = &clkops_generic, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | ALWAYS_ENABLED, .parent = &arm_ck, /* Is smarter alias for */ .recalc = &followparent_recalc, .set_rate = &omap1_select_table_rate, .round_rate = &omap1_round_to_table_rate, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; /* virtual functional clock domain for I2C. Just for making sure that ARMXOR_CK @@ -748,23 +694,21 @@ remains active during MPU idle whenever this is enabled */ static struct clk i2c_fck = { .name = "i2c_fck", .id = 1, + .ops = &clkops_generic, .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_NO_IDLE_PARENT | ALWAYS_ENABLED, .parent = &armxor_ck.clk, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk i2c_ick = { .name = "i2c_ick", .id = 1, + .ops = &clkops_generic, .flags = CLOCK_IN_OMAP16XX | CLOCK_NO_IDLE_PARENT | ALWAYS_ENABLED, .parent = &armper_ck.clk, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable_generic, - .disable = &omap1_clk_disable_generic, }; static struct clk * onchip_clks[] = { diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index ad721e0cbf7..d3213f565d5 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -274,8 +274,8 @@ int _omap2_clk_enable(struct clk *clk) if (clk->flags & (ALWAYS_ENABLED | PARENT_CONTROLS_CLOCK)) return 0; - if (clk->enable) - return clk->enable(clk); + if (clk->ops && clk->ops->enable) + return clk->ops->enable(clk); if (unlikely(clk->enable_reg == NULL)) { printk(KERN_ERR "clock.c: Enable for %s without enable code\n", @@ -304,8 +304,8 @@ void _omap2_clk_disable(struct clk *clk) if (clk->flags & (ALWAYS_ENABLED | PARENT_CONTROLS_CLOCK)) return; - if (clk->disable) { - clk->disable(clk); + if (clk->ops && clk->ops->disable) { + clk->ops->disable(clk); return; } diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index d382eb0184a..866a618c4d8 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -34,12 +34,16 @@ #include "memory.h" #include "clock.h" -#include "clock24xx.h" #include "prm.h" #include "prm-regbits-24xx.h" #include "cm.h" #include "cm-regbits-24xx.h" +static const struct clkops clkops_oscck; +static const struct clkops clkops_fixed; + +#include "clock24xx.h" + /* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */ #define EN_APLL_STOPPED 0 #define EN_APLL_LOCKED 3 @@ -96,6 +100,11 @@ static void omap2_disable_osc_ck(struct clk *clk) OMAP24XX_PRCM_CLKSRC_CTRL); } +static const struct clkops clkops_oscck = { + .enable = &omap2_enable_osc_ck, + .disable = &omap2_disable_osc_ck, +}; + #ifdef OLD_CK /* Recalculate SYST_CLK */ static void omap2_sys_clk_recalc(struct clk * clk) @@ -149,6 +158,11 @@ static void omap2_clk_fixed_disable(struct clk *clk) cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN); } +static const struct clkops clkops_fixed = { + .enable = &omap2_clk_fixed_enable, + .disable = &omap2_clk_fixed_disable, +}; + /* * Uses the current prcm set to tell if a rate is valid. * You can go slower, but not faster within a given rate set. diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h index 8c57a2e180f..2aa0b5e6560 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock24xx.h @@ -31,10 +31,6 @@ static void omap2_sys_clk_recalc(struct clk *clk); static void omap2_osc_clk_recalc(struct clk *clk); static void omap2_sys_clk_recalc(struct clk *clk); static void omap2_dpllcore_recalc(struct clk *clk); -static int omap2_clk_fixed_enable(struct clk *clk); -static void omap2_clk_fixed_disable(struct clk *clk); -static int omap2_enable_osc_ck(struct clk *clk); -static void omap2_disable_osc_ck(struct clk *clk); static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate); /* Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated. @@ -633,11 +629,10 @@ static struct clk func_32k_ck = { /* Typical 12/13MHz in standalone mode, will be 26Mhz in chassis mode */ static struct clk osc_ck = { /* (*12, *13, 19.2, *26, 38.4)MHz */ .name = "osc_ck", + .ops = &clkops_oscck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", - .enable = &omap2_enable_osc_ck, - .disable = &omap2_disable_osc_ck, .recalc = &omap2_osc_clk_recalc, }; @@ -695,6 +690,7 @@ static struct clk dpll_ck = { static struct clk apll96_ck = { .name = "apll96_ck", + .ops = &clkops_fixed, .parent = &sys_ck, .rate = 96000000, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | @@ -702,13 +698,12 @@ static struct clk apll96_ck = { .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP24XX_EN_96M_PLL_SHIFT, - .enable = &omap2_clk_fixed_enable, - .disable = &omap2_clk_fixed_disable, .recalc = &propagate_rate, }; static struct clk apll54_ck = { .name = "apll54_ck", + .ops = &clkops_fixed, .parent = &sys_ck, .rate = 54000000, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | @@ -716,8 +711,6 @@ static struct clk apll54_ck = { .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP24XX_EN_54M_PLL_SHIFT, - .enable = &omap2_clk_fixed_enable, - .disable = &omap2_clk_fixed_disable, .recalc = &propagate_rate, }; diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 31bb7010bd4..2f2d43db2dd 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -33,12 +33,15 @@ #include "memory.h" #include "clock.h" -#include "clock34xx.h" #include "prm.h" #include "prm-regbits-34xx.h" #include "cm.h" #include "cm-regbits-34xx.h" +static const struct clkops clkops_noncore_dpll_ops; + +#include "clock34xx.h" + /* CM_AUTOIDLE_PLL*.AUTO_* bit values */ #define DPLL_AUTOIDLE_DISABLE 0x0 #define DPLL_AUTOIDLE_LOW_POWER_STOP 0x1 @@ -270,6 +273,11 @@ static void omap3_noncore_dpll_disable(struct clk *clk) _omap3_noncore_dpll_stop(clk); } +static const struct clkops clkops_noncore_dpll_ops = { + .enable = &omap3_noncore_dpll_enable, + .disable = &omap3_noncore_dpll_disable, +}; + /** * omap3_dpll_autoidle_read - read a DPLL's autoidle bits * @clk: struct clk * of the DPLL to read diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index a826094d89b..8b188fb9bea 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -32,8 +32,6 @@ static void omap3_clkoutx2_recalc(struct clk *clk); static void omap3_dpll_allow_idle(struct clk *clk); static void omap3_dpll_deny_idle(struct clk *clk); static u32 omap3_dpll_autoidle_read(struct clk *clk); -static int omap3_noncore_dpll_enable(struct clk *clk); -static void omap3_noncore_dpll_disable(struct clk *clk); /* Maximum DPLL multiplier, divider values for OMAP3 */ #define OMAP3_MAX_DPLL_MULT 2048 @@ -347,11 +345,10 @@ static struct dpll_data dpll2_dd = { static struct clk dpll2_ck = { .name = "dpll2_ck", + .ops = &clkops_noncore_dpll_ops, .parent = &sys_ck, .dpll_data = &dpll2_dd, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, - .enable = &omap3_noncore_dpll_enable, - .disable = &omap3_noncore_dpll_disable, .round_rate = &omap2_dpll_round_rate, .recalc = &omap3_dpll_recalc, }; @@ -582,11 +579,10 @@ static struct dpll_data dpll4_dd = { static struct clk dpll4_ck = { .name = "dpll4_ck", + .ops = &clkops_noncore_dpll_ops, .parent = &sys_ck, .dpll_data = &dpll4_dd, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, - .enable = &omap3_noncore_dpll_enable, - .disable = &omap3_noncore_dpll_disable, .round_rate = &omap2_dpll_round_rate, .recalc = &omap3_dpll_recalc, }; @@ -884,11 +880,10 @@ static struct dpll_data dpll5_dd = { static struct clk dpll5_ck = { .name = "dpll5_ck", + .ops = &clkops_noncore_dpll_ops, .parent = &sys_ck, .dpll_data = &dpll5_dd, .flags = CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES, - .enable = &omap3_noncore_dpll_enable, - .disable = &omap3_noncore_dpll_disable, .round_rate = &omap2_dpll_round_rate, .recalc = &omap3_dpll_recalc, }; diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index 4e8f59df30b..4fe5084e8cc 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -17,6 +17,11 @@ struct module; struct clk; struct clockdomain; +struct clkops { + int (*enable)(struct clk *); + void (*disable)(struct clk *); +}; + #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) struct clksel_rate { @@ -59,6 +64,7 @@ struct dpll_data { struct clk { struct list_head node; + const struct clkops *ops; struct module *owner; const char *name; int id; @@ -72,8 +78,6 @@ struct clk { int (*set_rate)(struct clk *, unsigned long); long (*round_rate)(struct clk *, unsigned long); void (*init)(struct clk *); - int (*enable)(struct clk *); - void (*disable)(struct clk *); #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) u8 fixed_div; void __iomem *clksel_reg; -- GitLab From e584f559c7b8711cccdf319400acd6294b2c074e Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Fri, 30 Jan 2009 23:17:23 -0800 Subject: [PATCH 1121/4982] x86/paravirt: don't restore second return reg Impact: bugfix In the 32-bit calling convention, %eax:%edx is used to return 64-bit values. Don't save and restore %edx around wrapped functions, or they can't return a full 64-bit result. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/paravirt.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index b17365c3974..016dce31130 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -1524,8 +1524,8 @@ extern struct paravirt_patch_site __parainstructions[], #define PV_RESTORE_REGS "popl %edx; popl %ecx;" /* save and restore all caller-save registers, except return value */ -#define PV_SAVE_ALL_CALLER_REGS PV_SAVE_REGS -#define PV_RESTORE_ALL_CALLER_REGS PV_RESTORE_REGS +#define PV_SAVE_ALL_CALLER_REGS "pushl %ecx;" +#define PV_RESTORE_ALL_CALLER_REGS "popl %ecx;" #define PV_FLAGS_ARG "0" #define PV_EXTRA_CLOBBERS -- GitLab From 664c7954721adfc9bd61de6ec78f89f482f1a802 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Fri, 30 Jan 2009 23:18:41 -0800 Subject: [PATCH 1122/4982] x86/vmi: fix interrupt enable/disable/save/restore calling convention. Zach says: > Enable/Disable have no clobbers at all. > Save clobbers only return value, %eax > Restore also clobbers nothing. This is precisely compatible with the calling convention, so we can just call them directly without wrapping. (Compile tested only.) Signed-off-by: Jeremy Fitzhardinge Signed-off-by: H. Peter Anvin --- arch/x86/kernel/vmi_32.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c index 1d3302cc2dd..eb9e7347928 100644 --- a/arch/x86/kernel/vmi_32.c +++ b/arch/x86/kernel/vmi_32.c @@ -670,10 +670,11 @@ static inline int __init activate_vmi(void) para_fill(pv_mmu_ops.write_cr2, SetCR2); para_fill(pv_mmu_ops.write_cr3, SetCR3); para_fill(pv_cpu_ops.write_cr4, SetCR4); - para_fill(pv_irq_ops.save_fl, GetInterruptMask); - para_fill(pv_irq_ops.restore_fl, SetInterruptMask); - para_fill(pv_irq_ops.irq_disable, DisableInterrupts); - para_fill(pv_irq_ops.irq_enable, EnableInterrupts); + + para_fill(pv_irq_ops.save_fl.func, GetInterruptMask); + para_fill(pv_irq_ops.restore_fl.func, SetInterruptMask); + para_fill(pv_irq_ops.irq_disable.func, DisableInterrupts); + para_fill(pv_irq_ops.irq_enable.func, EnableInterrupts); para_fill(pv_cpu_ops.wbinvd, WBINVD); para_fill(pv_cpu_ops.read_tsc, RDTSC); -- GitLab From 7e7f4eae28711fbb7f4d5e4b0aa3195776194bc1 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Mon, 2 Feb 2009 21:40:10 +0530 Subject: [PATCH 1123/4982] headers_check fix: linux/coda_psdev.h fix the following 'make headers_check' warning: usr/include/linux/coda_psdev.h:90: extern's make no sense in userspace Signed-off-by: Jaswinder Singh Rajput --- include/linux/coda_psdev.h | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/include/linux/coda_psdev.h b/include/linux/coda_psdev.h index 07ae8f84605..6f06352cf55 100644 --- a/include/linux/coda_psdev.h +++ b/include/linux/coda_psdev.h @@ -24,7 +24,7 @@ static inline struct venus_comm *coda_vcp(struct super_block *sb) return (struct venus_comm *)((sb)->s_fs_info); } - +#ifdef __KERNEL__ /* upcalls */ int venus_rootfid(struct super_block *sb, struct CodaFid *fidp); int venus_getattr(struct super_block *sb, struct CodaFid *fid, @@ -64,6 +64,12 @@ int coda_downcall(int opcode, union outputArgs *out, struct super_block *sb); int venus_fsync(struct super_block *sb, struct CodaFid *fid); int venus_statfs(struct dentry *dentry, struct kstatfs *sfs); +/* + * Statistics + */ + +extern struct venus_comm coda_comms[]; +#endif /* __KERNEL__ */ /* messages between coda filesystem in kernel and Venus */ struct upc_req { @@ -82,11 +88,4 @@ struct upc_req { #define REQ_WRITE 0x4 #define REQ_ABORT 0x8 - -/* - * Statistics - */ - -extern struct venus_comm coda_comms[]; - #endif -- GitLab From 25d00fddf8d23234da2d45c051a14450939496d6 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Mon, 2 Feb 2009 21:40:58 +0530 Subject: [PATCH 1124/4982] headers_check fix: linux/in6.h fix the following 'make headers_check' warnings: usr/include/linux/in6.h:47: extern's make no sense in userspace usr/include/linux/in6.h:49: extern's make no sense in userspace Signed-off-by: Jaswinder Singh Rajput --- include/linux/in6.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/in6.h b/include/linux/in6.h index bc492048c34..718bf21c575 100644 --- a/include/linux/in6.h +++ b/include/linux/in6.h @@ -44,11 +44,11 @@ struct in6_addr * NOTE: Be aware the IN6ADDR_* constants and in6addr_* externals are defined * in network byte order, not in host byte order as are the IPv4 equivalents */ +#ifdef __KERNEL__ extern const struct in6_addr in6addr_any; #define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } } extern const struct in6_addr in6addr_loopback; #define IN6ADDR_LOOPBACK_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } } -#ifdef __KERNEL__ extern const struct in6_addr in6addr_linklocal_allnodes; #define IN6ADDR_LINKLOCAL_ALLNODES_INIT \ { { { 0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } } -- GitLab From 9fe03bc3139503fbad66016bf714f4575babf651 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Mon, 2 Feb 2009 21:41:41 +0530 Subject: [PATCH 1125/4982] headers_check fix: linux/nubus.h fix the following 'make headers_check' warnings: usr/include/linux/nubus.h:297: extern's make no sense in userspace usr/include/linux/nubus.h:299: extern's make no sense in userspace usr/include/linux/nubus.h:303: extern's make no sense in userspace Signed-off-by: Jaswinder Singh Rajput --- include/linux/nubus.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/nubus.h b/include/linux/nubus.h index 7382af37473..9be57d99269 100644 --- a/include/linux/nubus.h +++ b/include/linux/nubus.h @@ -296,6 +296,7 @@ struct nubus_dev { struct nubus_board* board; }; +#ifdef __KERNEL__ /* This is all NuBus devices (used to find devices later on) */ extern struct nubus_dev* nubus_devices; /* This is all NuBus cards */ @@ -351,6 +352,7 @@ void nubus_get_rsrc_mem(void* dest, void nubus_get_rsrc_str(void* dest, const struct nubus_dirent *dirent, int maxlen); +#endif /* __KERNEL__ */ /* We'd like to get rid of this eventually. Only daynaport.c uses it now. */ static inline void *nubus_slot_addr(int slot) -- GitLab From 7d7dc0d6b0565484e0623cb08b5dcdd56424697b Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Mon, 2 Feb 2009 21:44:09 +0530 Subject: [PATCH 1126/4982] headers_check fix: linux/socket.h fix the following 'make headers_check' warning: usr/include/linux/socket.h:29: extern's make no sense in userspace Signed-off-by: Jaswinder Singh Rajput --- include/linux/socket.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/linux/socket.h b/include/linux/socket.h index 20fc4bbfca4..afc01909a42 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -24,10 +24,12 @@ struct __kernel_sockaddr_storage { #include /* pid_t */ #include /* __user */ -#ifdef CONFIG_PROC_FS +#ifdef __KERNEL__ +# ifdef CONFIG_PROC_FS struct seq_file; extern void socket_seq_show(struct seq_file *seq); -#endif +# endif +#endif /* __KERNEL__ */ typedef unsigned short sa_family_t; -- GitLab From 11d9f653aff1d445b4300ae1d2e2d675a0e9172f Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Mon, 2 Feb 2009 21:45:41 +0530 Subject: [PATCH 1127/4982] headers_check fix: linux/reinserfs_fs.h fix the following 'make headers_check' warnings: usr/include/linux/reiserfs_fs.h:687: extern's make no sense in userspace usr/include/linux/reiserfs_fs.h:995: extern's make no sense in userspace usr/include/linux/reiserfs_fs.h:997: extern's make no sense in userspace usr/include/linux/reiserfs_fs.h:1467: extern's make no sense in userspace usr/include/linux/reiserfs_fs.h:1760: extern's make no sense in userspace usr/include/linux/reiserfs_fs.h:1764: extern's make no sense in userspace usr/include/linux/reiserfs_fs.h:1766: extern's make no sense in userspace usr/include/linux/reiserfs_fs.h:1769: extern's make no sense in userspace usr/include/linux/reiserfs_fs.h:1771: extern's make no sense in userspace usr/include/linux/reiserfs_fs.h:1805: extern's make no sense in userspace usr/include/linux/reiserfs_fs.h:1948: extern's make no sense in userspace usr/include/linux/reiserfs_fs.h:1949: extern's make no sense in userspace usr/include/linux/reiserfs_fs.h:1950: extern's make no sense in userspace usr/include/linux/reiserfs_fs.h:1951: extern's make no sense in userspace usr/include/linux/reiserfs_fs.h:1962: extern's make no sense in userspace usr/include/linux/reiserfs_fs.h:1963: extern's make no sense in userspace usr/include/linux/reiserfs_fs.h:1964: extern's make no sense in userspace Signed-off-by: Jaswinder Singh Rajput --- include/linux/reiserfs_fs.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index bc5114d35e9..a4db55fd1f6 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -698,7 +698,9 @@ static inline void cpu_key_k_offset_dec(struct cpu_key *key) /* object identifier for root dir */ #define REISERFS_ROOT_OBJECTID 2 #define REISERFS_ROOT_PARENT_OBJECTID 1 +#ifdef __KERNEL__ extern struct reiserfs_key root_key; +#endif /* __KERNEL__ */ /* * Picture represents a leaf of the S+tree @@ -1006,10 +1008,12 @@ struct reiserfs_de_head { #define de_visible(deh) test_bit_unaligned (DEH_Visible, &((deh)->deh_state)) #define de_hidden(deh) !test_bit_unaligned (DEH_Visible, &((deh)->deh_state)) +#ifdef __KERNEL__ extern void make_empty_dir_item_v1(char *body, __le32 dirid, __le32 objid, __le32 par_dirid, __le32 par_objid); extern void make_empty_dir_item(char *body, __le32 dirid, __le32 objid, __le32 par_dirid, __le32 par_objid); +#endif /* __KERNEL__ */ /* array of the entry headers */ /* get item body */ @@ -1478,7 +1482,9 @@ struct item_operations { void (*print_vi) (struct virtual_item * vi); }; +#ifdef __KERNEL__ extern struct item_operations *item_ops[TYPE_ANY + 1]; +#endif /* __KERNEL__ */ #define op_bytes_number(ih,bsize) item_ops[le_ih_k_type (ih)]->bytes_number (ih, bsize) #define op_is_left_mergeable(key,bsize) item_ops[le_key_k_type (le_key_version (key), key)]->is_left_mergeable (key, bsize) @@ -1679,6 +1685,7 @@ struct reiserfs_transaction_handle { struct list_head t_list; }; +#ifdef __KERNEL__ /* used to keep track of ordered and tail writes, attached to the buffer * head through b_journal_head. */ @@ -2203,4 +2210,5 @@ int reiserfs_unpack(struct inode *inode, struct file *filp); /* xattr stuff */ #define REISERFS_XATTR_DIR_SEM(s) (REISERFS_SB(s)->xattr_dir_sem) +#endif /* __KERNEL__ */ #endif /* _LINUX_REISER_FS_H */ -- GitLab From e683ec4697c74c7d04ff8e90ec625ac34e25a7d8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 12 Nov 2008 16:42:44 +0100 Subject: [PATCH 1128/4982] ALSA: ice1724 - Dynamic MIDI TX irq control MIDI_TX IRQ seems always pending when any bytes on FIFO is available. Thus, it's better to enable MPU_TX only when any bytres are really stored in the substream, and disables immediately when the queue becomes empty. Signed-off-by: Takashi Iwai --- sound/pci/ice1712/ice1724.c | 43 +++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index bb8d8c766b9..eb7872dec5a 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -241,6 +241,8 @@ get_rawmidi_substream(struct snd_ice1712 *ice, unsigned int stream) struct snd_rawmidi_substream, list); } +static void enable_midi_irq(struct snd_ice1712 *ice, u8 flag, int enable); + static void vt1724_midi_write(struct snd_ice1712 *ice) { struct snd_rawmidi_substream *s; @@ -254,6 +256,11 @@ static void vt1724_midi_write(struct snd_ice1712 *ice) for (i = 0; i < count; ++i) outb(buffer[i], ICEREG1724(ice, MPU_DATA)); } + /* mask irq when all bytes have been transmitted. + * enabled again in output_trigger when the new data comes in. + */ + enable_midi_irq(ice, VT1724_IRQ_MPU_TX, + !snd_rawmidi_transmit_empty(s)); } static void vt1724_midi_read(struct snd_ice1712 *ice) @@ -272,31 +279,34 @@ static void vt1724_midi_read(struct snd_ice1712 *ice) } } -static void vt1724_enable_midi_irq(struct snd_rawmidi_substream *substream, - u8 flag, int enable) +/* call with ice->reg_lock */ +static void enable_midi_irq(struct snd_ice1712 *ice, u8 flag, int enable) { - struct snd_ice1712 *ice = substream->rmidi->private_data; - u8 mask; - - spin_lock_irq(&ice->reg_lock); - mask = inb(ICEREG1724(ice, IRQMASK)); + u8 mask = inb(ICEREG1724(ice, IRQMASK)); if (enable) mask &= ~flag; else mask |= flag; outb(mask, ICEREG1724(ice, IRQMASK)); +} + +static void vt1724_enable_midi_irq(struct snd_rawmidi_substream *substream, + u8 flag, int enable) +{ + struct snd_ice1712 *ice = substream->rmidi->private_data; + + spin_lock_irq(&ice->reg_lock); + enable_midi_irq(ice, flag, enable); spin_unlock_irq(&ice->reg_lock); } static int vt1724_midi_output_open(struct snd_rawmidi_substream *s) { - vt1724_enable_midi_irq(s, VT1724_IRQ_MPU_TX, 1); return 0; } static int vt1724_midi_output_close(struct snd_rawmidi_substream *s) { - vt1724_enable_midi_irq(s, VT1724_IRQ_MPU_TX, 0); return 0; } @@ -311,6 +321,7 @@ static void vt1724_midi_output_trigger(struct snd_rawmidi_substream *s, int up) vt1724_midi_write(ice); } else { ice->midi_output = 0; + enable_midi_irq(ice, VT1724_IRQ_MPU_TX, 0); } spin_unlock_irqrestore(&ice->reg_lock, flags); } @@ -320,6 +331,7 @@ static void vt1724_midi_output_drain(struct snd_rawmidi_substream *s) struct snd_ice1712 *ice = s->rmidi->private_data; unsigned long timeout; + vt1724_enable_midi_irq(s, VT1724_IRQ_MPU_TX, 0); /* 32 bytes should be transmitted in less than about 12 ms */ timeout = jiffies + msecs_to_jiffies(15); do { @@ -389,24 +401,24 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id) status &= status_mask; if (status == 0) break; + spin_lock(&ice->reg_lock); if (++timeout > 10) { status = inb(ICEREG1724(ice, IRQSTAT)); printk(KERN_ERR "ice1724: Too long irq loop, " "status = 0x%x\n", status); if (status & VT1724_IRQ_MPU_TX) { printk(KERN_ERR "ice1724: Disabling MPU_TX\n"); - outb(inb(ICEREG1724(ice, IRQMASK)) | - VT1724_IRQ_MPU_TX, - ICEREG1724(ice, IRQMASK)); + enable_midi_irq(ice, VT1724_IRQ_MPU_TX, 0); } + spin_unlock(&ice->reg_lock); break; } handled = 1; if (status & VT1724_IRQ_MPU_TX) { - spin_lock(&ice->reg_lock); if (ice->midi_output) vt1724_midi_write(ice); - spin_unlock(&ice->reg_lock); + else + enable_midi_irq(ice, VT1724_IRQ_MPU_TX, 0); /* Due to mysterical reasons, MPU_TX is always * generated (and can't be cleared) when a PCM * playback is going. So let's ignore at the @@ -415,15 +427,14 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id) status_mask &= ~VT1724_IRQ_MPU_TX; } if (status & VT1724_IRQ_MPU_RX) { - spin_lock(&ice->reg_lock); if (ice->midi_input) vt1724_midi_read(ice); else vt1724_midi_clear_rx(ice); - spin_unlock(&ice->reg_lock); } /* ack MPU irq */ outb(status, ICEREG1724(ice, IRQSTAT)); + spin_unlock(&ice->reg_lock); if (status & VT1724_IRQ_MTPCM) { /* * Multi-track PCM -- GitLab From 8d4b4981195849dd50ed94be33ede926c6f41dcd Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Mon, 2 Feb 2009 21:48:33 +0530 Subject: [PATCH 1129/4982] headers_check fix: x86, prctl.h fix the following 'make headers_check' warning: usr/include/asm/prctl.h:10: extern's make no sense in userspace Signed-off-by: Jaswinder Singh Rajput --- arch/x86/include/asm/prctl.h | 4 ---- arch/x86/include/asm/syscalls.h | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/arch/x86/include/asm/prctl.h b/arch/x86/include/asm/prctl.h index a8894647dd9..3ac5032fae0 100644 --- a/arch/x86/include/asm/prctl.h +++ b/arch/x86/include/asm/prctl.h @@ -6,8 +6,4 @@ #define ARCH_GET_FS 0x1003 #define ARCH_GET_GS 0x1004 -#ifdef CONFIG_X86_64 -extern long sys_arch_prctl(int, unsigned long); -#endif /* CONFIG_X86_64 */ - #endif /* _ASM_X86_PRCTL_H */ diff --git a/arch/x86/include/asm/syscalls.h b/arch/x86/include/asm/syscalls.h index c0b0bda754e..e26d34b0bc7 100644 --- a/arch/x86/include/asm/syscalls.h +++ b/arch/x86/include/asm/syscalls.h @@ -74,6 +74,7 @@ asmlinkage long sys_vfork(struct pt_regs *); asmlinkage long sys_execve(char __user *, char __user * __user *, char __user * __user *, struct pt_regs *); +long sys_arch_prctl(int, unsigned long); /* kernel/ioport.c */ asmlinkage long sys_iopl(unsigned int, struct pt_regs *); -- GitLab From 15c554439faedfa490389b31db893dc764245e88 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Mon, 2 Feb 2009 21:59:19 +0530 Subject: [PATCH 1130/4982] headers_check fix: x86, setup.h fix the following 'make headers_check' warning: usr/include/asm/setup.h:16: extern's make no sense in userspace usr/include/asm/setup.h:17: extern's make no sense in userspace usr/include/asm/setup.h:23: extern's make no sense in userspace usr/include/asm/setup.h:24: extern's make no sense in userspace usr/include/asm/setup.h:51: extern's make no sense in userspace usr/include/asm/setup.h:52: extern's make no sense in userspace Signed-off-by: Jaswinder Singh Rajput --- arch/x86/include/asm/setup.h | 45 ++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h index ebe858cdc8a..5a3a1371575 100644 --- a/arch/x86/include/asm/setup.h +++ b/arch/x86/include/asm/setup.h @@ -5,23 +5,6 @@ #ifndef __ASSEMBLY__ -/* Interrupt control for vSMPowered x86_64 systems */ -void vsmp_init(void); - - -void setup_bios_corruption_check(void); - - -#ifdef CONFIG_X86_VISWS -extern void visws_early_detect(void); -extern int is_visws_box(void); -#else -static inline void visws_early_detect(void) { } -static inline int is_visws_box(void) { return 0; } -#endif - -extern int wakeup_secondary_cpu_via_nmi(int apicid, unsigned long start_eip); -extern int wakeup_secondary_cpu_via_init(int apicid, unsigned long start_eip); /* * Any setup quirks to be performed? */ @@ -48,12 +31,6 @@ struct x86_quirks { int (*update_genapic)(void); }; -extern struct x86_quirks *x86_quirks; -extern unsigned long saved_video_mode; - -#ifndef CONFIG_PARAVIRT -#define paravirt_post_allocator_init() do {} while (0) -#endif #endif /* __ASSEMBLY__ */ #ifdef __KERNEL__ @@ -78,6 +55,28 @@ extern unsigned long saved_video_mode; #ifndef __ASSEMBLY__ #include +/* Interrupt control for vSMPowered x86_64 systems */ +void vsmp_init(void); + +void setup_bios_corruption_check(void); + +#ifdef CONFIG_X86_VISWS +extern void visws_early_detect(void); +extern int is_visws_box(void); +#else +static inline void visws_early_detect(void) { } +static inline int is_visws_box(void) { return 0; } +#endif + +extern int wakeup_secondary_cpu_via_nmi(int apicid, unsigned long start_eip); +extern int wakeup_secondary_cpu_via_init(int apicid, unsigned long start_eip); +extern struct x86_quirks *x86_quirks; +extern unsigned long saved_video_mode; + +#ifndef CONFIG_PARAVIRT +#define paravirt_post_allocator_init() do {} while (0) +#endif + #ifndef _SETUP /* -- GitLab From d9fb7fbddc9a14569aad517984c1a5b0b07002ea Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Mon, 2 Feb 2009 14:50:45 -0600 Subject: [PATCH 1131/4982] ASoC: fix build break in CS4270 codec driver Fix a oversight in the CS4270 codec driver that caused a build break. Signed-off-by: Timur Tabi Signed-off-by: Mark Brown --- sound/soc/codecs/cs4270.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index e5f5afdd342..7962874258f 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -149,7 +149,7 @@ struct cs4270_mode_ratios { u8 mclk; }; -static struct cs4270_mode_ratios[] = { +static struct cs4270_mode_ratios cs4270_mode_ratios[] = { {64, CS4270_MODE_4X, CS4270_MODE_DIV1}, #ifndef CONFIG_SND_SOC_CS4270_VD33_ERRATA {96, CS4270_MODE_4X, CS4270_MODE_DIV15}, -- GitLab From a6c255e0945160b76eabe983f59e2129e0c66246 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Mon, 2 Feb 2009 15:08:29 -0600 Subject: [PATCH 1132/4982] ASoC: fix message display in CS4270 codec driver Replace printk calls with dev_xxx calls. Set the 'dev' field of the codec and codec_dai structures so that these calls work. Signed-off-by: Timur Tabi Signed-off-by: Mark Brown --- sound/soc/codecs/cs4270.c | 66 +++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 7962874258f..2c79a24186f 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -212,7 +212,7 @@ static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai, rates &= ~SNDRV_PCM_RATE_KNOT; if (!rates) { - printk(KERN_ERR "cs4270: could not find a valid sample rate\n"); + dev_err(codec->dev, "could not find a valid sample rate\n"); return -EINVAL; } @@ -253,7 +253,7 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai, cs4270->mode = format & SND_SOC_DAIFMT_FORMAT_MASK; break; default: - printk(KERN_ERR "cs4270: invalid DAI format\n"); + dev_err(codec->dev, "invalid dai format\n"); ret = -EINVAL; } @@ -284,7 +284,7 @@ static int cs4270_fill_cache(struct snd_soc_codec *codec) CS4270_FIRSTREG | 0x80, CS4270_NUMREGS, cache); if (length != CS4270_NUMREGS) { - printk(KERN_ERR "cs4270: I2C read failure, addr=0x%x\n", + dev_err(codec->dev, "i2c read failure, addr=0x%x\n", i2c_client->addr); return -EIO; } @@ -340,7 +340,7 @@ static int cs4270_i2c_write(struct snd_soc_codec *codec, unsigned int reg, if (cache[reg - CS4270_FIRSTREG] != value) { struct i2c_client *client = codec->control_data; if (i2c_smbus_write_byte_data(client, reg, value)) { - printk(KERN_ERR "cs4270: I2C write failed\n"); + dev_err(codec->dev, "i2c write failed\n"); return -EIO; } @@ -391,7 +391,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, if (i == NUM_MCLK_RATIOS) { /* We did not find a matching ratio */ - printk(KERN_ERR "cs4270: could not find matching ratio\n"); + dev_err(codec->dev, "could not find matching ratio\n"); return -EINVAL; } @@ -401,7 +401,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, CS4270_PWRCTL_PDN_ADC | CS4270_PWRCTL_PDN_DAC | CS4270_PWRCTL_PDN); if (ret < 0) { - printk(KERN_ERR "cs4270: I2C write failed\n"); + dev_err(codec->dev, "i2c write failed\n"); return ret; } @@ -413,7 +413,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, ret = snd_soc_write(codec, CS4270_MODE, reg); if (ret < 0) { - printk(KERN_ERR "cs4270: I2C write failed\n"); + dev_err(codec->dev, "i2c write failed\n"); return ret; } @@ -430,13 +430,13 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, reg |= CS4270_FORMAT_DAC_LJ | CS4270_FORMAT_ADC_LJ; break; default: - printk(KERN_ERR "cs4270: unknown format\n"); + dev_err(codec->dev, "unknown dai format\n"); return -EINVAL; } ret = snd_soc_write(codec, CS4270_FORMAT, reg); if (ret < 0) { - printk(KERN_ERR "cs4270: I2C write failed\n"); + dev_err(codec->dev, "i2c write failed\n"); return ret; } @@ -447,7 +447,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, reg &= ~CS4270_MUTE_AUTO; ret = snd_soc_write(codec, CS4270_MUTE, reg); if (ret < 0) { - printk(KERN_ERR "cs4270: I2C write failed\n"); + dev_err(codec->dev, "i2c write failed\n"); return ret; } @@ -460,7 +460,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO); ret = cs4270_i2c_write(codec, CS4270_TRANS, reg); if (ret < 0) { - printk(KERN_ERR "I2C write failed\n"); + dev_err(codec->dev, "i2c write failed\n"); return ret; } @@ -468,7 +468,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, ret = snd_soc_write(codec, CS4270_PWRCTL, 0); if (ret < 0) { - printk(KERN_ERR "cs4270: I2C write failed\n"); + dev_err(codec->dev, "i2c write failed\n"); return ret; } @@ -570,7 +570,7 @@ static int cs4270_probe(struct platform_device *pdev) /* Register PCMs */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) { - printk(KERN_ERR "cs4270: failed to create PCMs\n"); + dev_err(codec->dev, "failed to create pcms\n"); return ret; } @@ -580,7 +580,7 @@ static int cs4270_probe(struct platform_device *pdev) kctrl = snd_soc_cnew(&cs4270_snd_controls[i], codec, NULL); if (!kctrl) { - printk(KERN_ERR "cs4270: error creating control '%s'\n", + dev_err(codec->dev, "error creating control '%s'\n", cs4270_snd_controls[i].name); ret = -ENOMEM; goto error_free_pcms; @@ -588,7 +588,7 @@ static int cs4270_probe(struct platform_device *pdev) ret = snd_ctl_add(codec->card, kctrl); if (ret < 0) { - printk(KERN_ERR "cs4270: error adding control '%s'\n", + dev_err(codec->dev, "error adding control '%s'\n", cs4270_snd_controls[i].name); goto error_free_pcms; } @@ -597,7 +597,7 @@ static int cs4270_probe(struct platform_device *pdev) /* And finally, register the socdev */ ret = snd_soc_init_card(socdev); if (ret < 0) { - printk(KERN_ERR "cs4270: failed to register card\n"); + dev_err(codec->dev, "failed to register card\n"); goto error_free_pcms; } @@ -643,9 +643,9 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, * comment for cs4270_codec. */ if (cs4270_codec) { - printk(KERN_ERR "cs4270: ignoring CS4270 at addr %X\n", + dev_err(&i2c_client->dev, "ignoring CS4270 at addr %X\n", i2c_client->addr); - printk(KERN_ERR "cs4270: only one CS4270 per board allowed\n"); + dev_err(&i2c_client->dev, "only one per board allowed\n"); /* Should we return something other than ENODEV here? */ return -ENODEV; } @@ -654,35 +654,35 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); if (ret < 0) { - printk(KERN_ERR "cs4270: failed to read I2C at addr %X\n", + dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n", i2c_client->addr); return ret; } /* The top four bits of the chip ID should be 1100. */ if ((ret & 0xF0) != 0xC0) { - printk(KERN_ERR "cs4270: device at addr %X is not a CS4270\n", + dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n", i2c_client->addr); return -ENODEV; } - printk(KERN_INFO "cs4270: found device at I2C address %X\n", + dev_info(&i2c_client->dev, "found device at i2c address %X\n", i2c_client->addr); - printk(KERN_INFO "cs4270: hardware revision %X\n", ret & 0xF); + dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF); /* Allocate enough space for the snd_soc_codec structure and our private data together. */ cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL); if (!cs4270) { - printk(KERN_ERR "cs4270: Could not allocate codec structure\n"); + dev_err(&i2c_client->dev, "could not allocate codec\n"); return -ENOMEM; } codec = &cs4270->codec; - cs4270_codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); + codec->dev = &i2c_client->dev; codec->name = "CS4270"; codec->owner = THIS_MODULE; codec->dai = &cs4270_dai; @@ -698,17 +698,25 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, ret = cs4270_fill_cache(codec); if (ret < 0) { - printk(KERN_ERR "cs4270: failed to fill register cache\n"); + dev_err(&i2c_client->dev, "failed to fill register cache\n"); goto error_free_codec; } + /* Initialize the DAI. Normally, we'd prefer to have a kmalloc'd DAI + * structure for each CS4270 device, but the machine driver needs to + * have a pointer to the DAI structure, so for now it must be a global + * variable. + */ + cs4270_dai.dev = &i2c_client->dev; + /* Register the DAI. If all the other ASoC driver have already * registered, then this will call our probe function, so * cs4270_codec needs to be ready. */ + cs4270_codec = codec; ret = snd_soc_register_dai(&cs4270_dai); if (ret < 0) { - printk(KERN_ERR "cs4270: failed to register DAIe\n"); + dev_err(&i2c_client->dev, "failed to register DAIe\n"); goto error_free_codec; } @@ -718,6 +726,8 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, error_free_codec: kfree(cs4270); + cs4270_codec = NULL; + cs4270_dai.dev = NULL; return ret; } @@ -733,6 +743,8 @@ static int cs4270_i2c_remove(struct i2c_client *i2c_client) struct cs4270_private *cs4270 = i2c_get_clientdata(i2c_client); kfree(cs4270); + cs4270_codec = NULL; + cs4270_dai.dev = NULL; return 0; } @@ -776,7 +788,7 @@ EXPORT_SYMBOL_GPL(soc_codec_device_cs4270); static int __init cs4270_init(void) { - printk(KERN_INFO "Cirrus Logic CS4270 ALSA SoC Codec Driver\n"); + pr_info("Cirrus Logic CS4270 ALSA SoC Codec Driver\n"); return i2c_add_driver(&cs4270_i2c_driver); } -- GitLab From 3bd323a1da42525317e2ce6c93b97b5ba653bc9d Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 2 Feb 2009 14:52:00 -0800 Subject: [PATCH 1133/4982] x86 setup: a20: early timeout for a nonexistent keyboard controller When probing the keyboard controller to enable A20, if we get FF back (which is *possible* as a valid status word, but is extremely unlikely) then bail after much fewer iterations than we otherwise would, and abort the attempt to access the KBC. This hopefully should make it work a lot better for embedded platforms which don't have a KBC and where the BIOS doesn't implement INT 15h AX=2401h (and doesn't boot with A20 already enabled.) If this works, it will be the one remaining use of CONFIG_X86_ELAN as anything other than a processor type optimization option. Signed-off-by: H. Peter Anvin --- arch/x86/boot/a20.c | 75 +++++++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/arch/x86/boot/a20.c b/arch/x86/boot/a20.c index 4063d630def..fba8e9c6a50 100644 --- a/arch/x86/boot/a20.c +++ b/arch/x86/boot/a20.c @@ -2,6 +2,7 @@ * * Copyright (C) 1991, 1992 Linus Torvalds * Copyright 2007-2008 rPath, Inc. - All Rights Reserved + * Copyright 2009 Intel Corporation * * This file is part of the Linux kernel, and is made available under * the terms of the GNU General Public License version 2. @@ -15,16 +16,23 @@ #include "boot.h" #define MAX_8042_LOOPS 100000 +#define MAX_8042_FF 32 static int empty_8042(void) { u8 status; int loops = MAX_8042_LOOPS; + int ffs = MAX_8042_FF; while (loops--) { io_delay(); status = inb(0x64); + if (status == 0xff) { + /* FF is a plausible, but very unlikely status */ + if (!--ffs) + return -1; /* Assume no KBC present */ + } if (status & 1) { /* Read and discard input data */ io_delay(); @@ -118,44 +126,43 @@ static void enable_a20_fast(void) int enable_a20(void) { -#if defined(CONFIG_X86_ELAN) - /* Elan croaks if we try to touch the KBC */ - enable_a20_fast(); - while (!a20_test_long()) - ; - return 0; -#elif defined(CONFIG_X86_VOYAGER) +#ifdef CONFIG_X86_VOYAGER /* On Voyager, a20_test() is unsafe? */ enable_a20_kbc(); return 0; #else int loops = A20_ENABLE_LOOPS; - while (loops--) { - /* First, check to see if A20 is already enabled - (legacy free, etc.) */ - if (a20_test_short()) - return 0; - - /* Next, try the BIOS (INT 0x15, AX=0x2401) */ - enable_a20_bios(); - if (a20_test_short()) - return 0; - - /* Try enabling A20 through the keyboard controller */ - empty_8042(); - if (a20_test_short()) - return 0; /* BIOS worked, but with delayed reaction */ - - enable_a20_kbc(); - if (a20_test_long()) - return 0; - - /* Finally, try enabling the "fast A20 gate" */ - enable_a20_fast(); - if (a20_test_long()) - return 0; - } - - return -1; + int kbc_err; + + while (loops--) { + /* First, check to see if A20 is already enabled + (legacy free, etc.) */ + if (a20_test_short()) + return 0; + + /* Next, try the BIOS (INT 0x15, AX=0x2401) */ + enable_a20_bios(); + if (a20_test_short()) + return 0; + + /* Try enabling A20 through the keyboard controller */ + kbc_err = empty_8042(); + + if (a20_test_short()) + return 0; /* BIOS worked, but with delayed reaction */ + + if (!kbc_err) { + enable_a20_kbc(); + if (a20_test_long()) + return 0; + } + + /* Finally, try enabling the "fast A20 gate" */ + enable_a20_fast(); + if (a20_test_long()) + return 0; + } + + return -1; #endif } -- GitLab From faa3aad75a959f55e7783f4dc7840253c7506571 Mon Sep 17 00:00:00 2001 From: "Serge E. Hallyn" Date: Mon, 2 Feb 2009 15:07:33 -0800 Subject: [PATCH 1134/4982] securityfs: fix long-broken securityfs_create_file comment If there is an error creating a file through securityfs_create_file, NULL is not returned, rather the error is propagated. Signed-off-by: Serge E. Hallyn Signed-off-by: James Morris --- security/inode.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/security/inode.c b/security/inode.c index efea5a60546..b41e708147a 100644 --- a/security/inode.c +++ b/security/inode.c @@ -205,12 +205,11 @@ static int create_by_name(const char *name, mode_t mode, * This function returns a pointer to a dentry if it succeeds. This * pointer must be passed to the securityfs_remove() function when the file is * to be removed (no automatic cleanup happens if your module is unloaded, - * you are responsible here). If an error occurs, %NULL is returned. + * you are responsible here). If an error occurs, the function will return + * the erorr value (via ERR_PTR). * * If securityfs is not enabled in the kernel, the value %-ENODEV is - * returned. It is not wise to check for this value, but rather, check for - * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling - * code. + * returned. */ struct dentry *securityfs_create_file(const char *name, mode_t mode, struct dentry *parent, void *data, -- GitLab From 0883743825e34b81f3ff78aaee3a97cba57586c5 Mon Sep 17 00:00:00 2001 From: Rajiv Andrade Date: Mon, 2 Feb 2009 15:23:43 -0200 Subject: [PATCH 1135/4982] TPM: sysfs functions consolidation According to Dave Hansen's comments on the tpm_show_*, some of these functions present a pattern when allocating data[] memory space and also when setting its content. A new function was created so that this pattern could be consolidated. Also, replaced the data[] command vectors and its indexes by meaningful structures as pointed out by Matt Helsley too. Signed-off-by: Rajiv Andrade Signed-off-by: James Morris --- drivers/char/tpm/tpm.c | 411 ++++++++++++++--------------------------- drivers/char/tpm/tpm.h | 124 +++++++++++++ 2 files changed, 266 insertions(+), 269 deletions(-) diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 9c47dc48c9f..9b9eb761cba 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -429,134 +429,148 @@ out: #define TPM_DIGEST_SIZE 20 #define TPM_ERROR_SIZE 10 #define TPM_RET_CODE_IDX 6 -#define TPM_GET_CAP_RET_SIZE_IDX 10 -#define TPM_GET_CAP_RET_UINT32_1_IDX 14 -#define TPM_GET_CAP_RET_UINT32_2_IDX 18 -#define TPM_GET_CAP_RET_UINT32_3_IDX 22 -#define TPM_GET_CAP_RET_UINT32_4_IDX 26 -#define TPM_GET_CAP_PERM_DISABLE_IDX 16 -#define TPM_GET_CAP_PERM_INACTIVE_IDX 18 -#define TPM_GET_CAP_RET_BOOL_1_IDX 14 -#define TPM_GET_CAP_TEMP_INACTIVE_IDX 16 - -#define TPM_CAP_IDX 13 -#define TPM_CAP_SUBCAP_IDX 21 enum tpm_capabilities { - TPM_CAP_FLAG = 4, - TPM_CAP_PROP = 5, + TPM_CAP_FLAG = cpu_to_be32(4), + TPM_CAP_PROP = cpu_to_be32(5), + CAP_VERSION_1_1 = cpu_to_be32(0x06), + CAP_VERSION_1_2 = cpu_to_be32(0x1A) }; enum tpm_sub_capabilities { - TPM_CAP_PROP_PCR = 0x1, - TPM_CAP_PROP_MANUFACTURER = 0x3, - TPM_CAP_FLAG_PERM = 0x8, - TPM_CAP_FLAG_VOL = 0x9, - TPM_CAP_PROP_OWNER = 0x11, - TPM_CAP_PROP_TIS_TIMEOUT = 0x15, - TPM_CAP_PROP_TIS_DURATION = 0x20, -}; + TPM_CAP_PROP_PCR = cpu_to_be32(0x101), + TPM_CAP_PROP_MANUFACTURER = cpu_to_be32(0x103), + TPM_CAP_FLAG_PERM = cpu_to_be32(0x108), + TPM_CAP_FLAG_VOL = cpu_to_be32(0x109), + TPM_CAP_PROP_OWNER = cpu_to_be32(0x111), + TPM_CAP_PROP_TIS_TIMEOUT = cpu_to_be32(0x115), + TPM_CAP_PROP_TIS_DURATION = cpu_to_be32(0x120), -/* - * This is a semi generic GetCapability command for use - * with the capability type TPM_CAP_PROP or TPM_CAP_FLAG - * and their associated sub_capabilities. - */ - -static const u8 tpm_cap[] = { - 0, 193, /* TPM_TAG_RQU_COMMAND */ - 0, 0, 0, 22, /* length */ - 0, 0, 0, 101, /* TPM_ORD_GetCapability */ - 0, 0, 0, 0, /* TPM_CAP_ */ - 0, 0, 0, 4, /* TPM_CAP_SUB_ size */ - 0, 0, 1, 0 /* TPM_CAP_SUB_ */ }; -static ssize_t transmit_cmd(struct tpm_chip *chip, u8 *data, int len, - char *desc) +static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd, + int len, const char *desc) { int err; - len = tpm_transmit(chip, data, len); + len = tpm_transmit(chip,(u8 *) cmd, len); if (len < 0) return len; if (len == TPM_ERROR_SIZE) { - err = be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))); + err = be32_to_cpu(cmd->header.out.return_code); dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); return err; } return 0; } +#define TPM_INTERNAL_RESULT_SIZE 200 +#define TPM_TAG_RQU_COMMAND cpu_to_be16(193) +#define TPM_ORD_GET_CAP cpu_to_be32(101) + +static const struct tpm_input_header tpm_getcap_header = { + .tag = TPM_TAG_RQU_COMMAND, + .length = cpu_to_be32(22), + .ordinal = TPM_ORD_GET_CAP +}; + +ssize_t tpm_getcap(struct device *dev, __be32 subcap_id, cap_t *cap, + const char *desc) +{ + struct tpm_cmd_t tpm_cmd; + int rc; + struct tpm_chip *chip = dev_get_drvdata(dev); + + tpm_cmd.header.in = tpm_getcap_header; + if (subcap_id == CAP_VERSION_1_1 || subcap_id == CAP_VERSION_1_2) { + tpm_cmd.params.getcap_in.cap = subcap_id; + /*subcap field not necessary */ + tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(0); + tpm_cmd.header.in.length -= cpu_to_be32(sizeof(__be32)); + } else { + if (subcap_id == TPM_CAP_FLAG_PERM || + subcap_id == TPM_CAP_FLAG_VOL) + tpm_cmd.params.getcap_in.cap = TPM_CAP_FLAG; + else + tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; + tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); + tpm_cmd.params.getcap_in.subcap = subcap_id; + } + rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, desc); + if (!rc) + *cap = tpm_cmd.params.getcap_out.cap; + return rc; +} + void tpm_gen_interrupt(struct tpm_chip *chip) { - u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)]; + struct tpm_cmd_t tpm_cmd; ssize_t rc; - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_PROP; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT; + tpm_cmd.header.in = tpm_getcap_header; + tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; + tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); + tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; - rc = transmit_cmd(chip, data, sizeof(data), + rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, "attempting to determine the timeouts"); } EXPORT_SYMBOL_GPL(tpm_gen_interrupt); void tpm_get_timeouts(struct tpm_chip *chip) { - u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)]; + struct tpm_cmd_t tpm_cmd; + struct timeout_t *timeout_cap; + struct duration_t *duration_cap; ssize_t rc; u32 timeout; - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_PROP; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT; + tpm_cmd.header.in = tpm_getcap_header; + tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; + tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); + tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; - rc = transmit_cmd(chip, data, sizeof(data), + rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, "attempting to determine the timeouts"); if (rc) goto duration; - if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX))) + if (be32_to_cpu(tpm_cmd.header.out.length) != 4 * sizeof(u32)) goto duration; + timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout; /* Don't overwrite default if value is 0 */ - timeout = - be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))); + timeout = be32_to_cpu(timeout_cap->a); if (timeout) chip->vendor.timeout_a = usecs_to_jiffies(timeout); - timeout = - be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX))); + timeout = be32_to_cpu(timeout_cap->b); if (timeout) chip->vendor.timeout_b = usecs_to_jiffies(timeout); - timeout = - be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX))); + timeout = be32_to_cpu(timeout_cap->c); if (timeout) chip->vendor.timeout_c = usecs_to_jiffies(timeout); - timeout = - be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_4_IDX))); + timeout = be32_to_cpu(timeout_cap->d); if (timeout) chip->vendor.timeout_d = usecs_to_jiffies(timeout); duration: - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_PROP; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_DURATION; + tpm_cmd.header.in = tpm_getcap_header; + tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; + tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); + tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_DURATION; - rc = transmit_cmd(chip, data, sizeof(data), + rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, "attempting to determine the durations"); if (rc) return; - if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX))) + if (be32_to_cpu(tpm_cmd.header.out.return_code) != 3 * sizeof(u32)) return; - + duration_cap = &tpm_cmd.params.getcap_out.cap.duration; chip->vendor.duration[TPM_SHORT] = - usecs_to_jiffies(be32_to_cpu - (*((__be32 *) (data + - TPM_GET_CAP_RET_UINT32_1_IDX)))); + usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short)); /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above * value wrong and apparently reports msecs rather than usecs. So we * fix up the resulting too-small TPM_SHORT value to make things work. @@ -565,13 +579,9 @@ duration: chip->vendor.duration[TPM_SHORT] = HZ; chip->vendor.duration[TPM_MEDIUM] = - usecs_to_jiffies(be32_to_cpu - (*((__be32 *) (data + - TPM_GET_CAP_RET_UINT32_2_IDX)))); + usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium)); chip->vendor.duration[TPM_LONG] = - usecs_to_jiffies(be32_to_cpu - (*((__be32 *) (data + - TPM_GET_CAP_RET_UINT32_3_IDX)))); + usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long)); } EXPORT_SYMBOL_GPL(tpm_get_timeouts); @@ -587,36 +597,18 @@ void tpm_continue_selftest(struct tpm_chip *chip) } EXPORT_SYMBOL_GPL(tpm_continue_selftest); -#define TPM_INTERNAL_RESULT_SIZE 200 - ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, char *buf) { - u8 *data; + cap_t cap; ssize_t rc; - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; - - data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); - if (!data) - return -ENOMEM; - - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_FLAG; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; - - rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, - "attemtping to determine the permanent enabled state"); - if (rc) { - kfree(data); + rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap, + "attempting to determine the permanent enabled state"); + if (rc) return 0; - } - - rc = sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]); - kfree(data); + rc = sprintf(buf, "%d\n", !cap.perm_flags.disable); return rc; } EXPORT_SYMBOL_GPL(tpm_show_enabled); @@ -624,31 +616,15 @@ EXPORT_SYMBOL_GPL(tpm_show_enabled); ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr, char *buf) { - u8 *data; + cap_t cap; ssize_t rc; - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; - - data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); - if (!data) - return -ENOMEM; - - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_FLAG; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; - - rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, - "attemtping to determine the permanent active state"); - if (rc) { - kfree(data); + rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap, + "attempting to determine the permanent active state"); + if (rc) return 0; - } - rc = sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]); - - kfree(data); + rc = sprintf(buf, "%d\n", !cap.perm_flags.deactivated); return rc; } EXPORT_SYMBOL_GPL(tpm_show_active); @@ -656,31 +632,15 @@ EXPORT_SYMBOL_GPL(tpm_show_active); ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr, char *buf) { - u8 *data; + cap_t cap; ssize_t rc; - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; - - data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); - if (!data) - return -ENOMEM; - - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_PROP; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER; - - rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, - "attempting to determine the owner state"); - if (rc) { - kfree(data); + rc = tpm_getcap(dev, TPM_CAP_PROP_OWNER, &cap, + "attempting to determine the owner state"); + if (rc) return 0; - } - - rc = sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]); - kfree(data); + rc = sprintf(buf, "%d\n", cap.owned); return rc; } EXPORT_SYMBOL_GPL(tpm_show_owned); @@ -688,31 +648,15 @@ EXPORT_SYMBOL_GPL(tpm_show_owned); ssize_t tpm_show_temp_deactivated(struct device * dev, struct device_attribute * attr, char *buf) { - u8 *data; + cap_t cap; ssize_t rc; - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; - - data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); - if (!data) - return -ENOMEM; - - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_FLAG; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL; - - rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, - "attempting to determine the temporary state"); - if (rc) { - kfree(data); + rc = tpm_getcap(dev, TPM_CAP_FLAG_VOL, &cap, + "attempting to determine the temporary state"); + if (rc) return 0; - } - rc = sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]); - - kfree(data); + rc = sprintf(buf, "%d\n", cap.stclear_flags.deactivated); return rc; } EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated); @@ -727,77 +671,64 @@ static const u8 pcrread[] = { ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, char *buf) { + cap_t cap; u8 *data; ssize_t rc; int i, j, num_pcrs; __be32 index; char *str = buf; - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); if (!data) return -ENOMEM; - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_PROP; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR; - - rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, + rc = tpm_getcap(dev, TPM_CAP_PROP_PCR, &cap, "attempting to determine the number of PCRS"); - if (rc) { - kfree(data); + if (rc) return 0; - } - num_pcrs = be32_to_cpu(*((__be32 *) (data + 14))); + num_pcrs = be32_to_cpu(cap.num_pcrs); for (i = 0; i < num_pcrs; i++) { memcpy(data, pcrread, sizeof(pcrread)); index = cpu_to_be32(i); memcpy(data + 10, &index, 4); - rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, - "attempting to read a PCR"); + rc = transmit_cmd(chip, (struct tpm_cmd_t *)data, + TPM_INTERNAL_RESULT_SIZE, + "attempting to read a PCR"); if (rc) - goto out; + break; str += sprintf(str, "PCR-%02d: ", i); for (j = 0; j < TPM_DIGEST_SIZE; j++) str += sprintf(str, "%02X ", *(data + 10 + j)); str += sprintf(str, "\n"); } -out: kfree(data); return str - buf; } EXPORT_SYMBOL_GPL(tpm_show_pcrs); #define READ_PUBEK_RESULT_SIZE 314 -static const u8 readpubek[] = { - 0, 193, /* TPM_TAG_RQU_COMMAND */ - 0, 0, 0, 30, /* length */ - 0, 0, 0, 124, /* TPM_ORD_ReadPubek */ +#define TPM_ORD_READPUBEK cpu_to_be32(124) +struct tpm_input_header tpm_readpubek_header = { + .tag = TPM_TAG_RQU_COMMAND, + .length = cpu_to_be32(30), + .ordinal = TPM_ORD_READPUBEK }; ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, char *buf) { u8 *data; + struct tpm_cmd_t tpm_cmd; ssize_t err; int i, rc; char *str = buf; struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; - data = kzalloc(READ_PUBEK_RESULT_SIZE, GFP_KERNEL); - if (!data) - return -ENOMEM; - - memcpy(data, readpubek, sizeof(readpubek)); - - err = transmit_cmd(chip, data, READ_PUBEK_RESULT_SIZE, + tpm_cmd.header.in = tpm_readpubek_header; + err = transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE, "attempting to read the PUBEK"); if (err) goto out; @@ -812,7 +743,7 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, 256 byte modulus ignore checksum 20 bytes */ - + data = tpm_cmd.params.readpubek_out_buffer; str += sprintf(str, "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n" @@ -832,65 +763,33 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, } out: rc = str - buf; - kfree(data); return rc; } EXPORT_SYMBOL_GPL(tpm_show_pubek); -#define CAP_VERSION_1_1 6 -#define CAP_VERSION_1_2 0x1A -#define CAP_VERSION_IDX 13 -static const u8 cap_version[] = { - 0, 193, /* TPM_TAG_RQU_COMMAND */ - 0, 0, 0, 18, /* length */ - 0, 0, 0, 101, /* TPM_ORD_GetCapability */ - 0, 0, 0, 0, - 0, 0, 0, 0 -}; ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, char *buf) { - u8 *data; + cap_t cap; ssize_t rc; char *str = buf; - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; - - data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); - if (!data) - return -ENOMEM; - - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_PROP; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; - - rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, + rc = tpm_getcap(dev, TPM_CAP_PROP_MANUFACTURER, &cap, "attempting to determine the manufacturer"); - if (rc) { - kfree(data); + if (rc) return 0; - } - str += sprintf(str, "Manufacturer: 0x%x\n", - be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); + be32_to_cpu(cap.manufacturer_id)); - memcpy(data, cap_version, sizeof(cap_version)); - data[CAP_VERSION_IDX] = CAP_VERSION_1_1; - rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, - "attempting to determine the 1.1 version"); + rc = tpm_getcap(dev, CAP_VERSION_1_1, &cap, + "attempting to determine the 1.1 version"); if (rc) - goto out; - + return 0; str += sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n", - (int) data[14], (int) data[15], (int) data[16], - (int) data[17]); - -out: - kfree(data); + cap.tpm_version.Major, cap.tpm_version.Minor, + cap.tpm_version.revMajor, cap.tpm_version.revMinor); return str - buf; } EXPORT_SYMBOL_GPL(tpm_show_caps); @@ -898,51 +797,25 @@ EXPORT_SYMBOL_GPL(tpm_show_caps); ssize_t tpm_show_caps_1_2(struct device * dev, struct device_attribute * attr, char *buf) { - u8 *data; - ssize_t len; + cap_t cap; + ssize_t rc; char *str = buf; - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; - - data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); - if (!data) - return -ENOMEM; - - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_PROP; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; - - len = tpm_transmit(chip, data, TPM_INTERNAL_RESULT_SIZE); - if (len <= TPM_ERROR_SIZE) { - dev_dbg(chip->dev, "A TPM error (%d) occurred " - "attempting to determine the manufacturer\n", - be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); - kfree(data); + rc = tpm_getcap(dev, TPM_CAP_PROP_MANUFACTURER, &cap, + "attempting to determine the manufacturer"); + if (rc) return 0; - } - str += sprintf(str, "Manufacturer: 0x%x\n", - be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); - - memcpy(data, cap_version, sizeof(cap_version)); - data[CAP_VERSION_IDX] = CAP_VERSION_1_2; - - len = tpm_transmit(chip, data, TPM_INTERNAL_RESULT_SIZE); - if (len <= TPM_ERROR_SIZE) { - dev_err(chip->dev, "A TPM error (%d) occurred " - "attempting to determine the 1.2 version\n", - be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); - goto out; - } + be32_to_cpu(cap.manufacturer_id)); + rc = tpm_getcap(dev, CAP_VERSION_1_2, &cap, + "attempting to determine the 1.2 version"); + if (rc) + return 0; str += sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n", - (int) data[16], (int) data[17], (int) data[18], - (int) data[19]); - -out: - kfree(data); + cap.tpm_version_1_2.Major, cap.tpm_version_1_2.Minor, + cap.tpm_version_1_2.revMajor, + cap.tpm_version_1_2.revMinor); return str - buf; } EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 8e30df4a438..d64f6b7e5b8 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -123,6 +123,130 @@ static inline void tpm_write_index(int base, int index, int value) outb(index, base); outb(value & 0xFF, base+1); } +struct tpm_input_header { + __be16 tag; + __be32 length; + __be32 ordinal; +}__attribute__((packed)); + +struct tpm_output_header { + __be16 tag; + __be32 length; + __be32 return_code; +}__attribute__((packed)); + +struct stclear_flags_t { + __be16 tag; + u8 deactivated; + u8 disableForceClear; + u8 physicalPresence; + u8 physicalPresenceLock; + u8 bGlobalLock; +}__attribute__((packed)); + +struct tpm_version_t { + u8 Major; + u8 Minor; + u8 revMajor; + u8 revMinor; +}__attribute__((packed)); + +struct tpm_version_1_2_t { + __be16 tag; + u8 Major; + u8 Minor; + u8 revMajor; + u8 revMinor; +}__attribute__((packed)); + +struct timeout_t { + __be32 a; + __be32 b; + __be32 c; + __be32 d; +}__attribute__((packed)); + +struct duration_t { + __be32 tpm_short; + __be32 tpm_medium; + __be32 tpm_long; +}__attribute__((packed)); + +struct permanent_flags_t { + __be16 tag; + u8 disable; + u8 ownership; + u8 deactivated; + u8 readPubek; + u8 disableOwnerClear; + u8 allowMaintenance; + u8 physicalPresenceLifetimeLock; + u8 physicalPresenceHWEnable; + u8 physicalPresenceCMDEnable; + u8 CEKPUsed; + u8 TPMpost; + u8 TPMpostLock; + u8 FIPS; + u8 operator; + u8 enableRevokeEK; + u8 nvLocked; + u8 readSRKPub; + u8 tpmEstablished; + u8 maintenanceDone; + u8 disableFullDALogicInfo; +}__attribute__((packed)); + +typedef union { + struct permanent_flags_t perm_flags; + struct stclear_flags_t stclear_flags; + bool owned; + __be32 num_pcrs; + struct tpm_version_t tpm_version; + struct tpm_version_1_2_t tpm_version_1_2; + __be32 manufacturer_id; + struct timeout_t timeout; + struct duration_t duration; +} cap_t; + +struct tpm_getcap_params_in { + __be32 cap; + __be32 subcap_size; + __be32 subcap; +}__attribute__((packed)); + +struct tpm_getcap_params_out { + __be32 cap_size; + cap_t cap; +}__attribute__((packed)); + +struct tpm_readpubek_params_out { + u8 algorithm[4]; + u8 encscheme[2]; + u8 sigscheme[2]; + u8 parameters[12]; /*assuming RSA*/ + __be32 keysize; + u8 modulus[256]; + u8 checksum[20]; +}__attribute__((packed)); + +typedef union { + struct tpm_input_header in; + struct tpm_output_header out; +} tpm_cmd_header; + +typedef union { + struct tpm_getcap_params_out getcap_out; + struct tpm_readpubek_params_out readpubek_out; + u8 readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)]; + struct tpm_getcap_params_in getcap_in; +} tpm_cmd_params; + +struct tpm_cmd_t { + tpm_cmd_header header; + tpm_cmd_params params; +}__attribute__((packed)); + +ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); extern void tpm_get_timeouts(struct tpm_chip *); extern void tpm_gen_interrupt(struct tpm_chip *); -- GitLab From 659aaf2bb5496a425ba14036b5b5900f593e4484 Mon Sep 17 00:00:00 2001 From: Rajiv Andrade Date: Mon, 2 Feb 2009 15:23:44 -0200 Subject: [PATCH 1136/4982] TPM: integrity interface This patch adds internal kernel support for: - reading/extending a pcr value - looking up the tpm_chip for a given chip number Signed-off-by: Rajiv Andrade Signed-off-by: Mimi Zohar Signed-off-by: James Morris --- drivers/char/tpm/tpm.c | 129 +++++++++++++++++++++++++++++++++++------ drivers/char/tpm/tpm.h | 18 ++++++ include/linux/tpm.h | 35 +++++++++++ 3 files changed, 163 insertions(+), 19 deletions(-) create mode 100644 include/linux/tpm.h diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 9b9eb761cba..62a5682578c 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -661,28 +661,125 @@ ssize_t tpm_show_temp_deactivated(struct device * dev, } EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated); -static const u8 pcrread[] = { - 0, 193, /* TPM_TAG_RQU_COMMAND */ - 0, 0, 0, 14, /* length */ - 0, 0, 0, 21, /* TPM_ORD_PcrRead */ - 0, 0, 0, 0 /* PCR index */ +/* + * tpm_chip_find_get - return tpm_chip for given chip number + */ +static struct tpm_chip *tpm_chip_find_get(int chip_num) +{ + struct tpm_chip *pos; + + rcu_read_lock(); + list_for_each_entry_rcu(pos, &tpm_chip_list, list) { + if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num) + continue; + + if (try_module_get(pos->dev->driver->owner)) + break; + } + rcu_read_unlock(); + return pos; +} + +#define TPM_ORDINAL_PCRREAD cpu_to_be32(21) +#define READ_PCR_RESULT_SIZE 30 +static struct tpm_input_header pcrread_header = { + .tag = TPM_TAG_RQU_COMMAND, + .length = cpu_to_be32(14), + .ordinal = TPM_ORDINAL_PCRREAD +}; + +int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) +{ + int rc; + struct tpm_cmd_t cmd; + + cmd.header.in = pcrread_header; + cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx); + BUILD_BUG_ON(cmd.header.in.length > READ_PCR_RESULT_SIZE); + rc = transmit_cmd(chip, &cmd, cmd.header.in.length, + "attempting to read a pcr value"); + + if (rc == 0) + memcpy(res_buf, cmd.params.pcrread_out.pcr_result, + TPM_DIGEST_SIZE); + return rc; +} + +/** + * tpm_pcr_read - read a pcr value + * @chip_num: tpm idx # or ANY + * @pcr_idx: pcr idx to retrieve + * @res_buf: TPM_PCR value + * size of res_buf is 20 bytes (or NULL if you don't care) + * + * The TPM driver should be built-in, but for whatever reason it + * isn't, protect against the chip disappearing, by incrementing + * the module usage count. + */ +int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) +{ + struct tpm_chip *chip; + int rc; + + chip = tpm_chip_find_get(chip_num); + if (chip == NULL) + return -ENODEV; + rc = __tpm_pcr_read(chip, pcr_idx, res_buf); + module_put(chip->dev->driver->owner); + return rc; +} +EXPORT_SYMBOL_GPL(tpm_pcr_read); + +/** + * tpm_pcr_extend - extend pcr value with hash + * @chip_num: tpm idx # or AN& + * @pcr_idx: pcr idx to extend + * @hash: hash value used to extend pcr value + * + * The TPM driver should be built-in, but for whatever reason it + * isn't, protect against the chip disappearing, by incrementing + * the module usage count. + */ +#define TPM_ORD_PCR_EXTEND cpu_to_be32(20) +#define EXTEND_PCR_SIZE 34 +static struct tpm_input_header pcrextend_header = { + .tag = TPM_TAG_RQU_COMMAND, + .length = cpu_to_be32(34), + .ordinal = TPM_ORD_PCR_EXTEND }; +int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) +{ + struct tpm_cmd_t cmd; + int rc; + struct tpm_chip *chip; + + chip = tpm_chip_find_get(chip_num); + if (chip == NULL) + return -ENODEV; + + cmd.header.in = pcrextend_header; + BUILD_BUG_ON(be32_to_cpu(cmd.header.in.length) > EXTEND_PCR_SIZE); + cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx); + memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE); + rc = transmit_cmd(chip, &cmd, cmd.header.in.length, + "attempting extend a PCR value"); + + module_put(chip->dev->driver->owner); + return rc; +} +EXPORT_SYMBOL_GPL(tpm_pcr_extend); + ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, char *buf) { cap_t cap; - u8 *data; + u8 digest[TPM_DIGEST_SIZE]; ssize_t rc; int i, j, num_pcrs; - __be32 index; char *str = buf; struct tpm_chip *chip = dev_get_drvdata(dev); - data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); - if (!data) - return -ENOMEM; - rc = tpm_getcap(dev, TPM_CAP_PROP_PCR, &cap, "attempting to determine the number of PCRS"); if (rc) @@ -690,20 +787,14 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, num_pcrs = be32_to_cpu(cap.num_pcrs); for (i = 0; i < num_pcrs; i++) { - memcpy(data, pcrread, sizeof(pcrread)); - index = cpu_to_be32(i); - memcpy(data + 10, &index, 4); - rc = transmit_cmd(chip, (struct tpm_cmd_t *)data, - TPM_INTERNAL_RESULT_SIZE, - "attempting to read a PCR"); + rc = __tpm_pcr_read(chip, i, digest); if (rc) break; str += sprintf(str, "PCR-%02d: ", i); for (j = 0; j < TPM_DIGEST_SIZE; j++) - str += sprintf(str, "%02X ", *(data + 10 + j)); + str += sprintf(str, "%02X ", digest[j]); str += sprintf(str, "\n"); } - kfree(data); return str - buf; } EXPORT_SYMBOL_GPL(tpm_show_pcrs); diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index d64f6b7e5b8..8e00b4ddd08 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -26,6 +26,7 @@ #include #include #include +#include enum tpm_timeout { TPM_TIMEOUT = 5, /* msecs */ @@ -234,11 +235,28 @@ typedef union { struct tpm_output_header out; } tpm_cmd_header; +#define TPM_DIGEST_SIZE 20 +struct tpm_pcrread_out { + u8 pcr_result[TPM_DIGEST_SIZE]; +}__attribute__((packed)); + +struct tpm_pcrread_in { + __be32 pcr_idx; +}__attribute__((packed)); + +struct tpm_pcrextend_in { + __be32 pcr_idx; + u8 hash[TPM_DIGEST_SIZE]; +}__attribute__((packed)); + typedef union { struct tpm_getcap_params_out getcap_out; struct tpm_readpubek_params_out readpubek_out; u8 readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)]; struct tpm_getcap_params_in getcap_in; + struct tpm_pcrread_in pcrread_in; + struct tpm_pcrread_out pcrread_out; + struct tpm_pcrextend_in pcrextend_in; } tpm_cmd_params; struct tpm_cmd_t { diff --git a/include/linux/tpm.h b/include/linux/tpm.h new file mode 100644 index 00000000000..3338b3f5c21 --- /dev/null +++ b/include/linux/tpm.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2004,2007,2008 IBM Corporation + * + * Authors: + * Leendert van Doorn + * Dave Safford + * Reiner Sailer + * Kylene Hall + * Debora Velarde + * + * Maintained by: + * + * Device driver for TCG/TCPA TPM (trusted platform module). + * Specifications at www.trustedcomputinggroup.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + */ +#ifndef __LINUX_TPM_H__ +#define __LINUX_TPM_H__ + +/* + * Chip num is this value or a valid tpm idx + */ +#define TPM_ANY_NUM 0xFFFF + +#if defined(CONFIG_TCG_TPM) + +extern int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf); +extern int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash); +#endif +#endif -- GitLab From ef3892bd63420380d115f755d351d2071f1f805f Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 2 Feb 2009 18:16:19 -0800 Subject: [PATCH 1137/4982] x86, percpu: fix kexec with vmlinux Impact: fix regression with kexec with vmlinux Split data.init into data.init, percpu, data.init2 sections instead of let data.init wrap percpu secion. Thus kexec loading will be happy, because sections will not overlap. Before the patch we have: Elf file type is EXEC (Executable file) Entry point 0x200000 There are 6 program headers, starting at offset 64 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align LOAD 0x0000000000200000 0xffffffff80200000 0x0000000000200000 0x0000000000ca6000 0x0000000000ca6000 R E 200000 LOAD 0x0000000000ea6000 0xffffffff80ea6000 0x0000000000ea6000 0x000000000014dfe0 0x000000000014dfe0 RWE 200000 LOAD 0x0000000001000000 0xffffffffff600000 0x0000000000ff4000 0x0000000000000888 0x0000000000000888 RWE 200000 LOAD 0x00000000011f6000 0xffffffff80ff6000 0x0000000000ff6000 0x0000000000073086 0x0000000000a2d938 RWE 200000 LOAD 0x0000000001400000 0x0000000000000000 0x000000000106a000 0x00000000001d2ce0 0x00000000001d2ce0 RWE 200000 NOTE 0x00000000009e2c1c 0xffffffff809e2c1c 0x00000000009e2c1c 0x0000000000000024 0x0000000000000024 4 Section to Segment mapping: Segment Sections... 00 .text .notes __ex_table .rodata __bug_table .pci_fixup .builtin_fw __ksymtab __ksymtab_gpl __ksymtab_strings __init_rodata __param 01 .data .init.rodata .data.cacheline_aligned .data.read_mostly 02 .vsyscall_0 .vsyscall_fn .vsyscall_gtod_data .vsyscall_1 .vsyscall_2 .vgetcpu_mode .jiffies 03 .data.init_task .smp_locks .init.text .init.data .init.setup .initcall.init .con_initcall.init .x86_cpu_dev.init .altinstructions .altinstr_replacement .exit.text .init.ramfs .bss 04 .data.percpu 05 .notes After patch we've got: Elf file type is EXEC (Executable file) Entry point 0x200000 There are 7 program headers, starting at offset 64 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align LOAD 0x0000000000200000 0xffffffff80200000 0x0000000000200000 0x0000000000ca6000 0x0000000000ca6000 R E 200000 LOAD 0x0000000000ea6000 0xffffffff80ea6000 0x0000000000ea6000 0x000000000014dfe0 0x000000000014dfe0 RWE 200000 LOAD 0x0000000001000000 0xffffffffff600000 0x0000000000ff4000 0x0000000000000888 0x0000000000000888 RWE 200000 LOAD 0x00000000011f6000 0xffffffff80ff6000 0x0000000000ff6000 0x0000000000073086 0x0000000000073086 RWE 200000 LOAD 0x0000000001400000 0x0000000000000000 0x000000000106a000 0x00000000001d2ce0 0x00000000001d2ce0 RWE 200000 LOAD 0x000000000163d000 0xffffffff8123d000 0x000000000123d000 0x0000000000000000 0x00000000007e6938 RWE 200000 NOTE 0x00000000009e2c1c 0xffffffff809e2c1c 0x00000000009e2c1c 0x0000000000000024 0x0000000000000024 4 Section to Segment mapping: Segment Sections... 00 .text .notes __ex_table .rodata __bug_table .pci_fixup .builtin_fw __ksymtab __ksymtab_gpl __ksymtab_strings __init_rodata __param 01 .data .init.rodata .data.cacheline_aligned .data.read_mostly 02 .vsyscall_0 .vsyscall_fn .vsyscall_gtod_data .vsyscall_1 .vsyscall_2 .vgetcpu_mode .jiffies 03 .data.init_task .smp_locks .init.text .init.data .init.setup .initcall.init .con_initcall.init .x86_cpu_dev.init .altinstructions .altinstr_replacement .exit.text .init.ramfs 04 .data.percpu 05 .bss 06 .notes Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/vmlinux_64.lds.S | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S index c9740996430..07f62d287ff 100644 --- a/arch/x86/kernel/vmlinux_64.lds.S +++ b/arch/x86/kernel/vmlinux_64.lds.S @@ -22,6 +22,7 @@ PHDRS { #ifdef CONFIG_SMP percpu PT_LOAD FLAGS(7); /* RWE */ #endif + data.init2 PT_LOAD FLAGS(7); /* RWE */ note PT_NOTE FLAGS(0); /* ___ */ } SECTIONS @@ -215,7 +216,7 @@ SECTIONS /* * percpu offsets are zero-based on SMP. PERCPU_VADDR() changes the * output PHDR, so the next output section - __data_nosave - should - * switch it back to data.init. Also, pda should be at the head of + * start another section data.init2. Also, pda should be at the head of * percpu area. Preallocate it and define the percpu offset symbol * so that it can be accessed as a percpu variable. */ @@ -232,7 +233,7 @@ SECTIONS __nosave_begin = .; .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.data.nosave) - } :data.init /* switch back to data.init, see PERCPU_VADDR() above */ + } :data.init2 /* use another section data.init2, see PERCPU_VADDR() above */ . = ALIGN(PAGE_SIZE); __nosave_end = .; -- GitLab From 1a5645bc901aea6f3f446888061b2b084bbf1ba6 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Mon, 2 Feb 2009 23:22:04 -0800 Subject: [PATCH 1138/4982] connector: create connector workqueue only while needed once The netlink connector uses its own workqueue to relay the datas sent from userspace to the appropriate callback. If you launch the test from Documentation/connector and change it a bit to send a high flow of data, you will see thousands of events coming to the "cqueue" workqueue by looking at the workqueue tracer. This flow of events can be sent very quickly. So, to not encumber the kevent workqueue and delay other jobs, the "cqueue" workqueue should remain. But this workqueue is pointless most of the time, it will always be created (assuming you have built it of course) although only developpers with specific needs will use it. So avoid this "most of the time useless task", this patch proposes to create this workqueue only when needed once. The first jobs to be sent to connector callbacks will be sent to kevent while the "cqueue" thread creation will be scheduled to kevent too. The following jobs will continue to be scheduled to keventd until the cqueue workqueue is created, and then the rest of the jobs will continue to perform as usual, through this dedicated workqueue. Each time I tested this patch, only the first event was sent to keventd, the rest has been sent to cqueue which have been created quickly. Also, this patch fixes some trailing whitespaces on the connector files. Signed-off-by: Frederic Weisbecker Acked-by: Evgeniy Polyakov Signed-off-by: David S. Miller --- drivers/connector/cn_queue.c | 80 ++++++++++++++++++++++++++++++----- drivers/connector/connector.c | 19 +++++---- include/linux/connector.h | 8 ++++ 3 files changed, 87 insertions(+), 20 deletions(-) diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c index b6fe7e7a2c2..c769ef269fb 100644 --- a/drivers/connector/cn_queue.c +++ b/drivers/connector/cn_queue.c @@ -1,9 +1,9 @@ /* * cn_queue.c - * + * * 2004-2005 Copyright (c) Evgeniy Polyakov * All rights reserved. - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -31,6 +31,48 @@ #include #include + +/* + * This job is sent to the kevent workqueue. + * While no event is once sent to any callback, the connector workqueue + * is not created to avoid a useless waiting kernel task. + * Once the first event is received, we create this dedicated workqueue which + * is necessary because the flow of data can be high and we don't want + * to encumber keventd with that. + */ +static void cn_queue_create(struct work_struct *work) +{ + struct cn_queue_dev *dev; + + dev = container_of(work, struct cn_queue_dev, wq_creation); + + dev->cn_queue = create_singlethread_workqueue(dev->name); + /* If we fail, we will use keventd for all following connector jobs */ + WARN_ON(!dev->cn_queue); +} + +/* + * Queue a data sent to a callback. + * If the connector workqueue is already created, we queue the job on it. + * Otherwise, we queue the job to kevent and queue the connector workqueue + * creation too. + */ +int queue_cn_work(struct cn_callback_entry *cbq, struct work_struct *work) +{ + struct cn_queue_dev *pdev = cbq->pdev; + + if (likely(pdev->cn_queue)) + return queue_work(pdev->cn_queue, work); + + /* Don't create the connector workqueue twice */ + if (atomic_inc_return(&pdev->wq_requested) == 1) + schedule_work(&pdev->wq_creation); + else + atomic_dec(&pdev->wq_requested); + + return schedule_work(work); +} + void cn_queue_wrapper(struct work_struct *work) { struct cn_callback_entry *cbq = @@ -58,14 +100,17 @@ static struct cn_callback_entry *cn_queue_alloc_callback_entry(char *name, struc snprintf(cbq->id.name, sizeof(cbq->id.name), "%s", name); memcpy(&cbq->id.id, id, sizeof(struct cb_id)); cbq->data.callback = callback; - + INIT_WORK(&cbq->work, &cn_queue_wrapper); return cbq; } static void cn_queue_free_callback(struct cn_callback_entry *cbq) { - flush_workqueue(cbq->pdev->cn_queue); + /* The first jobs have been sent to kevent, flush them too */ + flush_scheduled_work(); + if (cbq->pdev->cn_queue) + flush_workqueue(cbq->pdev->cn_queue); kfree(cbq); } @@ -143,14 +188,11 @@ struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *nls) atomic_set(&dev->refcnt, 0); INIT_LIST_HEAD(&dev->queue_list); spin_lock_init(&dev->queue_lock); + init_waitqueue_head(&dev->wq_created); dev->nls = nls; - dev->cn_queue = create_singlethread_workqueue(dev->name); - if (!dev->cn_queue) { - kfree(dev); - return NULL; - } + INIT_WORK(&dev->wq_creation, cn_queue_create); return dev; } @@ -158,9 +200,25 @@ struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *nls) void cn_queue_free_dev(struct cn_queue_dev *dev) { struct cn_callback_entry *cbq, *n; + long timeout; + DEFINE_WAIT(wait); + + /* Flush the first pending jobs queued on kevent */ + flush_scheduled_work(); + + /* If the connector workqueue creation is still pending, wait for it */ + prepare_to_wait(&dev->wq_created, &wait, TASK_UNINTERRUPTIBLE); + if (atomic_read(&dev->wq_requested) && !dev->cn_queue) { + timeout = schedule_timeout(HZ * 2); + if (!timeout && !dev->cn_queue) + WARN_ON(1); + } + finish_wait(&dev->wq_created, &wait); - flush_workqueue(dev->cn_queue); - destroy_workqueue(dev->cn_queue); + if (dev->cn_queue) { + flush_workqueue(dev->cn_queue); + destroy_workqueue(dev->cn_queue); + } spin_lock_bh(&dev->queue_lock); list_for_each_entry_safe(cbq, n, &dev->queue_list, callback_entry) diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index bf4830082a1..fd336c5a905 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -1,9 +1,9 @@ /* * connector.c - * + * * 2004-2005 Copyright (c) Evgeniy Polyakov * All rights reserved. - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -145,14 +145,13 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v __cbq->data.ddata = data; __cbq->data.destruct_data = destruct_data; - if (queue_work(dev->cbdev->cn_queue, - &__cbq->work)) + if (queue_cn_work(__cbq, &__cbq->work)) err = 0; else err = -EINVAL; } else { struct cn_callback_data *d; - + err = -ENOMEM; __new_cbq = kzalloc(sizeof(struct cn_callback_entry), GFP_ATOMIC); if (__new_cbq) { @@ -163,10 +162,12 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v d->destruct_data = destruct_data; d->free = __new_cbq; + __new_cbq->pdev = __cbq->pdev; + INIT_WORK(&__new_cbq->work, &cn_queue_wrapper); - if (queue_work(dev->cbdev->cn_queue, + if (queue_cn_work(__new_cbq, &__new_cbq->work)) err = 0; else { @@ -237,7 +238,7 @@ static void cn_notify(struct cb_id *id, u32 notify_event) req = (struct cn_notify_req *)ctl->data; for (i = 0; i < ctl->idx_notify_num; ++i, ++req) { - if (id->idx >= req->first && + if (id->idx >= req->first && id->idx < req->first + req->range) { idx_found = 1; break; @@ -245,7 +246,7 @@ static void cn_notify(struct cb_id *id, u32 notify_event) } for (i = 0; i < ctl->val_notify_num; ++i, ++req) { - if (id->val >= req->first && + if (id->val >= req->first && id->val < req->first + req->range) { val_found = 1; break; @@ -459,7 +460,7 @@ static int __devinit cn_init(void) netlink_kernel_release(dev->nls); return -EINVAL; } - + cn_already_initialized = 1; err = cn_add_callback(&dev->id, "connector", &cn_callback); diff --git a/include/linux/connector.h b/include/linux/connector.h index 34f2789d9b9..fc65d219d88 100644 --- a/include/linux/connector.h +++ b/include/linux/connector.h @@ -109,6 +109,12 @@ struct cn_queue_dev { unsigned char name[CN_CBQ_NAMELEN]; struct workqueue_struct *cn_queue; + /* Sent to kevent to create cn_queue only when needed */ + struct work_struct wq_creation; + /* Tell if the wq_creation job is pending/completed */ + atomic_t wq_requested; + /* Wait for cn_queue to be created */ + wait_queue_head_t wq_created; struct list_head queue_list; spinlock_t queue_lock; @@ -164,6 +170,8 @@ int cn_netlink_send(struct cn_msg *, u32, gfp_t); int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(void *)); void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id); +int queue_cn_work(struct cn_callback_entry *cbq, struct work_struct *work); + struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *); void cn_queue_free_dev(struct cn_queue_dev *dev); -- GitLab From 1bded710a574f20d41bc9e7fb531301db282d623 Mon Sep 17 00:00:00 2001 From: Michael Tokarev Date: Mon, 2 Feb 2009 23:34:56 -0800 Subject: [PATCH 1139/4982] tun: Check supplemental groups in TUN/TAP driver. Michael Tokarev wrote: [] > 2, and this is the main one: How about supplementary groups? > > Here I have a valid usage case: a group of testers running various > versions of windows using KVM (kernel virtual machine), 1 at a time, > to test some software. kvm is set up to use bridge with a tap device > (there should be a way to connect to the machine). Anyone on that group > has to be able to start/stop the virtual machines. > > My first attempt - pretty obvious when I saw -g option of tunctl - is > to add group ownership for the tun device and add a supplementary group > to each user (their primary group should be different). But that fails, > since kernel only checks for egid, not any other group ids. > > What's the reasoning to not allow supplementary groups and to only check > for egid? Signed-off-by: Michael Tokarev Signed-off-by: David S. Miller --- drivers/net/tun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 457f2d7430c..15d67635bb1 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -123,7 +123,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file) /* Check permissions */ if (((tun->owner != -1 && cred->euid != tun->owner) || - (tun->group != -1 && cred->egid != tun->group)) && + (tun->group != -1 && !in_egroup_p(tun->group))) && !capable(CAP_NET_ADMIN)) return -EPERM; -- GitLab From ba340e825f4b892782779abd0f93bcff7e763567 Mon Sep 17 00:00:00 2001 From: Tony Vroon Date: Mon, 2 Feb 2009 19:01:30 +0000 Subject: [PATCH 1140/4982] ALSA: hda - Add tyan model for Realtek ALC262 The Realtek ALC262 on the Tyan Thunder n6650W (S2915-E) mainboard has a rather odd configuration template. As a result, the white AUX connector can not be used. This rewrites the default config to more accurately reflect the connector layout, colour and function. Unfortunately the black CD_IN connector, which is suspected to be widget 0x1c refuses to switch into input (0x20), instead opting to remain on 0x0. As such, no mixer controls are exposed for it. Autoswitching is implemented between the front headphone output and back line output. Signed-off-by: Tony Vroon Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 77 +++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 0c81d92c3d7..bd9ef336389 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -103,6 +103,7 @@ enum { ALC262_NEC, ALC262_TOSHIBA_S06, ALC262_TOSHIBA_RX1, + ALC262_TYAN, ALC262_AUTO, ALC262_MODEL_LAST /* last tag */ }; @@ -9509,6 +9510,67 @@ static struct snd_kcontrol_new alc262_benq_t31_mixer[] = { { } /* end */ }; +static struct snd_kcontrol_new alc262_tyan_mixer[] = { + HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT), + HDA_CODEC_VOLUME("Aux Playback Volume", 0x0b, 0x06, HDA_INPUT), + HDA_CODEC_MUTE("Aux Playback Switch", 0x0b, 0x06, HDA_INPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), + HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), + HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), + HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), + { } /* end */ +}; + +static struct hda_verb alc262_tyan_verbs[] = { + /* Headphone automute */ + {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, + {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, + + /* P11 AUX_IN, white 4-pin connector */ + {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, 0xe1}, + {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, 0x93}, + {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0x19}, + + {} +}; + +/* unsolicited event for HP jack sensing */ +static void alc262_tyan_automute(struct hda_codec *codec) +{ + unsigned int mute; + unsigned int present; + + snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0); + present = snd_hda_codec_read(codec, 0x1b, 0, + AC_VERB_GET_PIN_SENSE, 0); + present = (present & 0x80000000) != 0; + if (present) { + /* mute line output on ATX panel */ + snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, + HDA_AMP_MUTE, HDA_AMP_MUTE); + } else { + /* unmute line output if necessary */ + mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0); + snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, + HDA_AMP_MUTE, mute); + } +} + +static void alc262_tyan_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + if ((res >> 26) != ALC880_HP_EVENT) + return; + alc262_tyan_automute(codec); +} + #define alc262_capture_mixer alc882_capture_mixer #define alc262_capture_alt_mixer alc882_capture_alt_mixer @@ -10626,6 +10688,7 @@ static const char *alc262_models[ALC262_MODEL_LAST] = { [ALC262_ULTRA] = "ultra", [ALC262_LENOVO_3000] = "lenovo-3000", [ALC262_NEC] = "nec", + [ALC262_TYAN] = "tyan", [ALC262_AUTO] = "auto", }; @@ -10666,6 +10729,7 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = { SND_PCI_QUIRK(0x1179, 0xff7b, "Toshiba S06", ALC262_TOSHIBA_S06), SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU), SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU), + SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_TYAN), SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA), SND_PCI_QUIRK(0x144d, 0xc039, "Samsung Q1U EL", ALC262_ULTRA), SND_PCI_QUIRK(0x144d, 0xc510, "Samsung Q45", ALC262_HIPPO), @@ -10884,6 +10948,19 @@ static struct alc_config_preset alc262_presets[] = { .unsol_event = alc262_hippo_unsol_event, .init_hook = alc262_hippo_automute, }, + [ALC262_TYAN] = { + .mixers = { alc262_tyan_mixer }, + .init_verbs = { alc262_init_verbs, alc262_tyan_verbs}, + .num_dacs = ARRAY_SIZE(alc262_dac_nids), + .dac_nids = alc262_dac_nids, + .hp_nid = 0x02, + .dig_out_nid = ALC262_DIGOUT_NID, + .num_channel_mode = ARRAY_SIZE(alc262_modes), + .channel_mode = alc262_modes, + .input_mux = &alc262_capture_source, + .unsol_event = alc262_tyan_unsol_event, + .init_hook = alc262_tyan_automute, + }, }; static int patch_alc262(struct hda_codec *codec) -- GitLab From 123848e77623b9996288e85433985439c157fcd0 Mon Sep 17 00:00:00 2001 From: Tony Vroon Date: Tue, 3 Feb 2009 11:13:34 +0000 Subject: [PATCH 1141/4982] ALSA: Document tyan model for Realtek ALC262 As just pointed out to me, the new tyan model for ALC262 was implemented but not documented. This adds the board to the list, using both its marketing name (Thunder n6650W) and its model number (S2915-E). Signed-off-by: Tony Vroon Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index c9df9db5835..8f40999a456 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -56,6 +56,7 @@ ALC262 sony-assamd Sony ASSAMD toshiba-s06 Toshiba S06 toshiba-rx1 Toshiba RX1 + tyan Tyan Thunder n6650W (S2915-E) ultra Samsung Q1 Ultra Vista model lenovo-3000 Lenovo 3000 y410 nec NEC Versa S9100 -- GitLab From f2cddb29ebfc02dfd2c4b439aa0433393ad15575 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Tue, 3 Feb 2009 19:21:38 +0530 Subject: [PATCH 1142/4982] headers_check fix cleanup: linux/coda_psdev.h These are only for kernel internals as pointed by Arnd Bergmann: struct kstatfs struct venus_comm coda_vcp() Signed-off-by: Jaswinder Singh Rajput --- include/linux/coda_psdev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/coda_psdev.h b/include/linux/coda_psdev.h index 6f06352cf55..5b5d4731f95 100644 --- a/include/linux/coda_psdev.h +++ b/include/linux/coda_psdev.h @@ -6,6 +6,7 @@ #define CODA_PSDEV_MAJOR 67 #define MAX_CODADEVS 5 /* how many do we allow */ +#ifdef __KERNEL__ struct kstatfs; /* communication pending/processing queues */ @@ -24,7 +25,6 @@ static inline struct venus_comm *coda_vcp(struct super_block *sb) return (struct venus_comm *)((sb)->s_fs_info); } -#ifdef __KERNEL__ /* upcalls */ int venus_rootfid(struct super_block *sb, struct CodaFid *fidp); int venus_getattr(struct super_block *sb, struct CodaFid *fid, -- GitLab From 5007b1fc4ef2c1b496536b2f026353c1d44d92ef Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Tue, 3 Feb 2009 19:28:24 +0530 Subject: [PATCH 1143/4982] headers_check fix cleanup: linux/nubus.h These are only for kernel internals as pointed by Arnd Bergmann: struct nubus_board struct nubus_dev Signed-off-by: Jaswinder Singh Rajput --- include/linux/nubus.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/nubus.h b/include/linux/nubus.h index 9be57d99269..e137b3c486a 100644 --- a/include/linux/nubus.h +++ b/include/linux/nubus.h @@ -237,6 +237,7 @@ struct nubus_dirent int mask; }; +#ifdef __KERNEL__ struct nubus_board { struct nubus_board* next; struct nubus_dev* first_dev; @@ -296,7 +297,6 @@ struct nubus_dev { struct nubus_board* board; }; -#ifdef __KERNEL__ /* This is all NuBus devices (used to find devices later on) */ extern struct nubus_dev* nubus_devices; /* This is all NuBus cards */ -- GitLab From 750e1c18251345e662bb7e7062b5fd5c1ade36de Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Tue, 3 Feb 2009 19:40:03 +0530 Subject: [PATCH 1144/4982] headers_check fix cleanup: linux/reiserfs_fs.h Only REISERFS_IOC_* definitions are required for user space rest should be in #ifdef __KERNEL__ as pointed by Arnd Bergmann. Signed-off-by: Jaswinder Singh Rajput --- include/linux/reiserfs_fs.h | 62 +++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index a4db55fd1f6..e356c99f065 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -28,8 +28,6 @@ #include #endif -struct fid; - /* * include/linux/reiser_fs.h * @@ -37,6 +35,33 @@ struct fid; * */ +/* ioctl's command */ +#define REISERFS_IOC_UNPACK _IOW(0xCD,1,long) +/* define following flags to be the same as in ext2, so that chattr(1), + lsattr(1) will work with us. */ +#define REISERFS_IOC_GETFLAGS FS_IOC_GETFLAGS +#define REISERFS_IOC_SETFLAGS FS_IOC_SETFLAGS +#define REISERFS_IOC_GETVERSION FS_IOC_GETVERSION +#define REISERFS_IOC_SETVERSION FS_IOC_SETVERSION + +#ifdef __KERNEL__ +/* the 32 bit compat definitions with int argument */ +#define REISERFS_IOC32_UNPACK _IOW(0xCD, 1, int) +#define REISERFS_IOC32_GETFLAGS FS_IOC32_GETFLAGS +#define REISERFS_IOC32_SETFLAGS FS_IOC32_SETFLAGS +#define REISERFS_IOC32_GETVERSION FS_IOC32_GETVERSION +#define REISERFS_IOC32_SETVERSION FS_IOC32_SETVERSION + +/* Locking primitives */ +/* Right now we are still falling back to (un)lock_kernel, but eventually that + would evolve into real per-fs locks */ +#define reiserfs_write_lock( sb ) lock_kernel() +#define reiserfs_write_unlock( sb ) unlock_kernel() + +/* xattr stuff */ +#define REISERFS_XATTR_DIR_SEM(s) (REISERFS_SB(s)->xattr_dir_sem) +struct fid; + /* in reading the #defines, it may help to understand that they employ the following abbreviations: @@ -698,9 +723,8 @@ static inline void cpu_key_k_offset_dec(struct cpu_key *key) /* object identifier for root dir */ #define REISERFS_ROOT_OBJECTID 2 #define REISERFS_ROOT_PARENT_OBJECTID 1 -#ifdef __KERNEL__ + extern struct reiserfs_key root_key; -#endif /* __KERNEL__ */ /* * Picture represents a leaf of the S+tree @@ -1008,12 +1032,10 @@ struct reiserfs_de_head { #define de_visible(deh) test_bit_unaligned (DEH_Visible, &((deh)->deh_state)) #define de_hidden(deh) !test_bit_unaligned (DEH_Visible, &((deh)->deh_state)) -#ifdef __KERNEL__ extern void make_empty_dir_item_v1(char *body, __le32 dirid, __le32 objid, __le32 par_dirid, __le32 par_objid); extern void make_empty_dir_item(char *body, __le32 dirid, __le32 objid, __le32 par_dirid, __le32 par_objid); -#endif /* __KERNEL__ */ /* array of the entry headers */ /* get item body */ @@ -1482,9 +1504,7 @@ struct item_operations { void (*print_vi) (struct virtual_item * vi); }; -#ifdef __KERNEL__ extern struct item_operations *item_ops[TYPE_ANY + 1]; -#endif /* __KERNEL__ */ #define op_bytes_number(ih,bsize) item_ops[le_ih_k_type (ih)]->bytes_number (ih, bsize) #define op_is_left_mergeable(key,bsize) item_ops[le_key_k_type (le_key_version (key), key)]->is_left_mergeable (key, bsize) @@ -1546,7 +1566,6 @@ struct reiserfs_iget_args { /* FUNCTION DECLARATIONS */ /***************************************************************************/ -/*#ifdef __KERNEL__*/ #define get_journal_desc_magic(bh) (bh->b_data + bh->b_size - 12) #define journal_trans_half(blocksize) \ @@ -1685,7 +1704,6 @@ struct reiserfs_transaction_handle { struct list_head t_list; }; -#ifdef __KERNEL__ /* used to keep track of ordered and tail writes, attached to the buffer * head through b_journal_head. */ @@ -2185,30 +2203,6 @@ long reiserfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); int reiserfs_unpack(struct inode *inode, struct file *filp); -/* ioctl's command */ -#define REISERFS_IOC_UNPACK _IOW(0xCD,1,long) -/* define following flags to be the same as in ext2, so that chattr(1), - lsattr(1) will work with us. */ -#define REISERFS_IOC_GETFLAGS FS_IOC_GETFLAGS -#define REISERFS_IOC_SETFLAGS FS_IOC_SETFLAGS -#define REISERFS_IOC_GETVERSION FS_IOC_GETVERSION -#define REISERFS_IOC_SETVERSION FS_IOC_SETVERSION - -/* the 32 bit compat definitions with int argument */ -#define REISERFS_IOC32_UNPACK _IOW(0xCD, 1, int) -#define REISERFS_IOC32_GETFLAGS FS_IOC32_GETFLAGS -#define REISERFS_IOC32_SETFLAGS FS_IOC32_SETFLAGS -#define REISERFS_IOC32_GETVERSION FS_IOC32_GETVERSION -#define REISERFS_IOC32_SETVERSION FS_IOC32_SETVERSION - -/* Locking primitives */ -/* Right now we are still falling back to (un)lock_kernel, but eventually that - would evolve into real per-fs locks */ -#define reiserfs_write_lock( sb ) lock_kernel() -#define reiserfs_write_unlock( sb ) unlock_kernel() - -/* xattr stuff */ -#define REISERFS_XATTR_DIR_SEM(s) (REISERFS_SB(s)->xattr_dir_sem) #endif /* __KERNEL__ */ #endif /* _LINUX_REISER_FS_H */ -- GitLab From 111f6fbeb73fc350fe3a08c4ecd0ccdf3e13bef0 Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Tue, 3 Feb 2009 15:52:56 +0200 Subject: [PATCH 1145/4982] ASoC: Don't unconditionally use the PLL in UDA1380 Without this fix driver switches to WSPLL in uda1380_pcm_prepare even if SYSCLK was chosen (uda1380_pcm_prepare modifies UDA1380_CLK register to disable R00_DAC_CLK before flushing reg cache) Signed-off-by: Vasily Khoruzhick Signed-off-by: Mark Brown --- sound/soc/codecs/uda1380.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 98e4a6560f0..6e4a1770ce8 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -418,8 +418,8 @@ static int uda1380_pcm_prepare(struct snd_pcm_substream *substream, uda1380_write(codec, reg, uda1380_read_reg_cache(codec, reg)); } - /* FIXME enable DAC_CLK */ - uda1380_write(codec, UDA1380_CLK, clk | R00_DAC_CLK); + /* FIXME restore DAC_CLK */ + uda1380_write(codec, UDA1380_CLK, clk); return 0; } -- GitLab From 063f8913afb48842b9329e195d90d2c28e58aacc Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 3 Feb 2009 18:02:36 +0100 Subject: [PATCH 1146/4982] x86: document 64-bit and 32-bit function call convention ABI - also clean up the calling.h file a tiny bit Signed-off-by: Ingo Molnar --- arch/x86/include/asm/calling.h | 56 ++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/calling.h b/arch/x86/include/asm/calling.h index 2bc162e0ec6..0e63c9a2a8d 100644 --- a/arch/x86/include/asm/calling.h +++ b/arch/x86/include/asm/calling.h @@ -1,5 +1,55 @@ /* - * Some macros to handle stack frames in assembly. + + x86 function call convention, 64-bit: + ------------------------------------- + arguments | callee-saved | extra caller-saved | return + [callee-clobbered] | | [callee-clobbered] | + --------------------------------------------------------------------------- + rdi rsi rdx rcx r8-9 | rbx rbp [*] r12-15 | r10-11 | rax, rdx [**] + + ( rsp is obviously invariant across normal function calls. (gcc can 'merge' + functions when it sees tail-call optimization possibilities) rflags is + clobbered. Leftover arguments are passed over the stack frame.) + + [*] In the frame-pointers case rbp is fixed to the stack frame. + + [**] for struct return values wider than 64 bits the return convention is a + bit more complex: up to 128 bits width we return small structures + straight in rax, rdx. For structures larger than that (3 words or + larger) the caller puts a pointer to an on-stack return struct + [allocated in the caller's stack frame] into the first argument - i.e. + into rdi. All other arguments shift up by one in this case. + Fortunately this case is rare in the kernel. + +For 32-bit we have the following conventions - kernel is built with +-mregparm=3 and -freg-struct-return: + + x86 function calling convention, 32-bit: + ---------------------------------------- + arguments | callee-saved | extra caller-saved | return + [callee-clobbered] | | [callee-clobbered] | + ------------------------------------------------------------------------- + eax edx ecx | ebx edi esi ebp [*] | | eax, edx [**] + + ( here too esp is obviously invariant across normal function calls. eflags + is clobbered. Leftover arguments are passed over the stack frame. ) + + [*] In the frame-pointers case ebp is fixed to the stack frame. + + [**] We build with -freg-struct-return, which on 32-bit means similar + semantics as on 64-bit: edx can be used for a second return value + (i.e. covering integer and structure sizes up to 64 bits) - after that + it gets more complex and more expensive: 3-word or larger struct returns + get done in the caller's frame and the pointer to the return struct goes + into regparm0, i.e. eax - the other arguments shift up and the + function's register parameters degenerate to regparm=2 in essence. + +*/ + + +/* + * 64-bit system call stack frame layout defines and helpers, + * for assembly code: */ #define R15 0 @@ -9,7 +59,7 @@ #define RBP 32 #define RBX 40 -/* arguments: interrupts/non tracing syscalls only save upto here*/ +/* arguments: interrupts/non tracing syscalls only save up to here: */ #define R11 48 #define R10 56 #define R9 64 @@ -22,7 +72,7 @@ #define ORIG_RAX 120 /* + error_code */ /* end of arguments */ -/* cpu exception frame or undefined in case of fast syscall. */ +/* cpu exception frame or undefined in case of fast syscall: */ #define RIP 128 #define CS 136 #define EFLAGS 144 -- GitLab From 1bd68c04850b9e73f1c7022b9a8c38cd14ceb37d Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 3 Feb 2009 11:27:27 +0000 Subject: [PATCH 1147/4982] sky2: remove unneede workaround This workaround is not needed. It was inherited from sk98lin driver but only applies to an early development version of the chip that is not supported by sky2. The workaround required an unnecessary pci read which hurts performance Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 994703cc0db..db925085c18 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2687,13 +2687,6 @@ static int sky2_poll(struct napi_struct *napi, int work_limit) goto done; } - /* Bug/Errata workaround? - * Need to kick the TX irq moderation timer. - */ - if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) { - sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); - sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); - } napi_complete(napi); sky2_read32(hw, B0_Y2_SP_LISR); done: -- GitLab From 454e6cb6868dd5c88d8bcdab407caa3738d30c2b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 3 Feb 2009 11:27:28 +0000 Subject: [PATCH 1148/4982] sky2: handle dma mapping errors On non-x86 platforms it is possible to run out of DMA mapping resources. The driver was ignoring this and could cause corruptions. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.c | 64 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 8 deletions(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index db925085c18..8b9b8845726 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1068,13 +1068,16 @@ static void sky2_rx_submit(struct sky2_port *sky2, } -static void sky2_rx_map_skb(struct pci_dev *pdev, struct rx_ring_info *re, +static int sky2_rx_map_skb(struct pci_dev *pdev, struct rx_ring_info *re, unsigned size) { struct sk_buff *skb = re->skb; int i; re->data_addr = pci_map_single(pdev, skb->data, size, PCI_DMA_FROMDEVICE); + if (unlikely(pci_dma_mapping_error(pdev, re->data_addr))) + return -EIO; + pci_unmap_len_set(re, data_size, size); for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) @@ -1083,6 +1086,7 @@ static void sky2_rx_map_skb(struct pci_dev *pdev, struct rx_ring_info *re, skb_shinfo(skb)->frags[i].page_offset, skb_shinfo(skb)->frags[i].size, PCI_DMA_FROMDEVICE); + return 0; } static void sky2_rx_unmap_skb(struct pci_dev *pdev, struct rx_ring_info *re) @@ -1354,7 +1358,12 @@ static int sky2_rx_start(struct sky2_port *sky2) if (!re->skb) goto nomem; - sky2_rx_map_skb(hw->pdev, re, sky2->rx_data_size); + if (sky2_rx_map_skb(hw->pdev, re, sky2->rx_data_size)) { + dev_kfree_skb(re->skb); + re->skb = NULL; + goto nomem; + } + sky2_rx_submit(sky2, re); } @@ -1547,7 +1556,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) struct sky2_hw *hw = sky2->hw; struct sky2_tx_le *le = NULL; struct tx_ring_info *re; - unsigned i, len; + unsigned i, len, first_slot; dma_addr_t mapping; u16 mss; u8 ctrl; @@ -1555,13 +1564,17 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) if (unlikely(tx_avail(sky2) < tx_le_req(skb))) return NETDEV_TX_BUSY; - if (unlikely(netif_msg_tx_queued(sky2))) - printk(KERN_DEBUG "%s: tx queued, slot %u, len %d\n", - dev->name, sky2->tx_prod, skb->len); - len = skb_headlen(skb); mapping = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(hw->pdev, mapping)) + goto mapping_error; + + first_slot = sky2->tx_prod; + if (unlikely(netif_msg_tx_queued(sky2))) + printk(KERN_DEBUG "%s: tx queued, slot %u, len %d\n", + dev->name, first_slot, skb->len); + /* Send high bits if needed */ if (sizeof(dma_addr_t) > sizeof(u32)) { le = get_tx_le(sky2); @@ -1648,6 +1661,9 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) mapping = pci_map_page(hw->pdev, frag->page, frag->page_offset, frag->size, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(hw->pdev, mapping)) + goto mapping_unwind; + if (sizeof(dma_addr_t) > sizeof(u32)) { le = get_tx_le(sky2); le->addr = cpu_to_le32(upper_32_bits(mapping)); @@ -1676,6 +1692,34 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) dev->trans_start = jiffies; return NETDEV_TX_OK; + +mapping_unwind: + for (i = first_slot; i != sky2->tx_prod; i = RING_NEXT(i, TX_RING_SIZE)) { + le = sky2->tx_le + i; + re = sky2->tx_ring + i; + + switch(le->opcode & ~HW_OWNER) { + case OP_LARGESEND: + case OP_PACKET: + pci_unmap_single(hw->pdev, + pci_unmap_addr(re, mapaddr), + pci_unmap_len(re, maplen), + PCI_DMA_TODEVICE); + break; + case OP_BUFFER: + pci_unmap_page(hw->pdev, pci_unmap_addr(re, mapaddr), + pci_unmap_len(re, maplen), + PCI_DMA_TODEVICE); + break; + } + } + + sky2->tx_prod = first_slot; +mapping_error: + if (net_ratelimit()) + dev_warn(&hw->pdev->dev, "%s: tx mapping error\n", dev->name); + dev_kfree_skb(skb); + return NETDEV_TX_OK; } /* @@ -2191,7 +2235,11 @@ static struct sk_buff *receive_new(struct sky2_port *sky2, prefetch(skb->data); re->skb = nskb; - sky2_rx_map_skb(sky2->hw->pdev, re, hdr_space); + if (sky2_rx_map_skb(sky2->hw->pdev, re, hdr_space)) { + dev_kfree_skb(nskb); + re->skb = skb; + return NULL; + } if (skb_shinfo(skb)->nr_frags) skb_put_frags(skb, hdr_space, length); -- GitLab From e4c2abe29e1ec5d68908848ffa77b39f61a83f7c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 3 Feb 2009 11:27:29 +0000 Subject: [PATCH 1149/4982] sky2: move VPD display into debug interface The VPD stuff has more data and isn't generally that useful, so move it into the existing debugfs display and use the new PCI VPD accessor routines. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.c | 155 +++++++++++++++++++++++++-------------------- 1 file changed, 87 insertions(+), 68 deletions(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 8b9b8845726..d3c090dae87 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -3905,6 +3905,86 @@ static const struct ethtool_ops sky2_ethtool_ops = { static struct dentry *sky2_debug; + +/* + * Read and parse the first part of Vital Product Data + */ +#define VPD_SIZE 128 +#define VPD_MAGIC 0x82 + +static const struct vpd_tag { + char tag[2]; + char *label; +} vpd_tags[] = { + { "PN", "Part Number" }, + { "EC", "Engineering Level" }, + { "MN", "Manufacturer" }, + { "SN", "Serial Number" }, + { "YA", "Asset Tag" }, + { "VL", "First Error Log Message" }, + { "VF", "Second Error Log Message" }, + { "VB", "Boot Agent ROM Configuration" }, + { "VE", "EFI UNDI Configuration" }, +}; + +static void sky2_show_vpd(struct seq_file *seq, struct sky2_hw *hw) +{ + size_t vpd_size; + loff_t offs; + u8 len; + unsigned char *buf; + u16 reg2; + + reg2 = sky2_pci_read16(hw, PCI_DEV_REG2); + vpd_size = 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8); + + seq_printf(seq, "%s Product Data\n", pci_name(hw->pdev)); + buf = kmalloc(vpd_size, GFP_KERNEL); + if (!buf) { + seq_puts(seq, "no memory!\n"); + return; + } + + if (pci_read_vpd(hw->pdev, 0, vpd_size, buf) < 0) { + seq_puts(seq, "VPD read failed\n"); + goto out; + } + + if (buf[0] != VPD_MAGIC) { + seq_printf(seq, "VPD tag mismatch: %#x\n", buf[0]); + goto out; + } + len = buf[1]; + if (len == 0 || len > vpd_size - 4) { + seq_printf(seq, "Invalid id length: %d\n", len); + goto out; + } + + seq_printf(seq, "%.*s\n", len, buf + 3); + offs = len + 3; + + while (offs < vpd_size - 4) { + int i; + + if (!memcmp("RW", buf + offs, 2)) /* end marker */ + break; + len = buf[offs + 2]; + if (offs + len + 3 >= vpd_size) + break; + + for (i = 0; i < ARRAY_SIZE(vpd_tags); i++) { + if (!memcmp(vpd_tags[i].tag, buf + offs, 2)) { + seq_printf(seq, " %s: %.*s\n", + vpd_tags[i].label, len, buf + offs + 3); + break; + } + } + offs += len + 3; + } +out: + kfree(buf); +} + static int sky2_debug_show(struct seq_file *seq, void *v) { struct net_device *dev = seq->private; @@ -3914,14 +3994,18 @@ static int sky2_debug_show(struct seq_file *seq, void *v) unsigned idx, last; int sop; - if (!netif_running(dev)) - return -ENETDOWN; + sky2_show_vpd(seq, hw); - seq_printf(seq, "IRQ src=%x mask=%x control=%x\n", + seq_printf(seq, "\nIRQ src=%x mask=%x control=%x\n", sky2_read32(hw, B0_ISRC), sky2_read32(hw, B0_IMSK), sky2_read32(hw, B0_Y2_SP_ICR)); + if (!netif_running(dev)) { + seq_printf(seq, "network not running\n"); + return 0; + } + napi_disable(&hw->napi); last = sky2_read16(hw, STAT_PUT_IDX); @@ -4245,69 +4329,6 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw) return err; } -/* - * Read and parse the first part of Vital Product Data - */ -#define VPD_SIZE 128 -#define VPD_MAGIC 0x82 - -static void __devinit sky2_vpd_info(struct sky2_hw *hw) -{ - int cap = pci_find_capability(hw->pdev, PCI_CAP_ID_VPD); - const u8 *p; - u8 *vpd_buf = NULL; - u16 len; - static struct vpd_tag { - char tag[2]; - char *label; - } vpd_tags[] = { - { "PN", "Part Number" }, - { "EC", "Engineering Level" }, - { "MN", "Manufacturer" }, - }; - - if (!cap) - goto out; - - vpd_buf = kmalloc(VPD_SIZE, GFP_KERNEL); - if (!vpd_buf) - goto out; - - if (sky2_vpd_read(hw, cap, vpd_buf, 0, VPD_SIZE)) - goto out; - - if (vpd_buf[0] != VPD_MAGIC) - goto out; - len = vpd_buf[1]; - if (len == 0 || len > VPD_SIZE - 4) - goto out; - p = vpd_buf + 3; - dev_info(&hw->pdev->dev, "%.*s\n", len, p); - p += len; - - while (p < vpd_buf + VPD_SIZE - 4) { - int i; - - if (!memcmp("RW", p, 2)) /* end marker */ - break; - - len = p[2]; - if (len > (p - vpd_buf) - 4) - break; - - for (i = 0; i < ARRAY_SIZE(vpd_tags); i++) { - if (!memcmp(vpd_tags[i].tag, p, 2)) { - printk(KERN_DEBUG " %s: %.*s\n", - vpd_tags[i].label, len, p + 3); - break; - } - } - p += len + 3; - } -out: - kfree(vpd_buf); -} - /* This driver supports yukon2 chipset only */ static const char *sky2_name(u8 chipid, char *buf, int sz) { @@ -4411,8 +4432,6 @@ static int __devinit sky2_probe(struct pci_dev *pdev, sky2_reset(hw); - sky2_vpd_info(hw); - dev = sky2_init_netdev(hw, 0, using_dac, wol_default); if (!dev) { err = -ENOMEM; -- GitLab From 3834507d0c5480a0f05486c2fb57ed18fd179a83 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 3 Feb 2009 11:27:30 +0000 Subject: [PATCH 1150/4982] sky2: set VPD size Read configuration register during probe and use it to size the available VPD. Move existing code using same register slightly earlier in probe handling. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.c | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index d3c090dae87..d01c56eb962 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -4356,6 +4356,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev, struct net_device *dev; struct sky2_hw *hw; int err, using_dac = 0, wol_default; + u32 reg; char buf1[16]; err = pci_enable_device(pdev); @@ -4389,6 +4390,34 @@ static int __devinit sky2_probe(struct pci_dev *pdev, } } + /* Get configuration information + * Note: only regular PCI config access once to test for HW issues + * other PCI access through shared memory for speed and to + * avoid MMCONFIG problems. + */ + err = pci_read_config_dword(pdev, PCI_DEV_REG2, ®); + if (err) { + dev_err(&pdev->dev, "PCI read config failed\n"); + goto err_out_free_regions; + } + + /* size of available VPD, only impact sysfs */ + err = pci_vpd_truncate(pdev, 1ul << (((reg & PCI_VPD_ROM_SZ) >> 14) + 8)); + if (err) + dev_warn(&pdev->dev, "Can't set VPD size\n"); + +#ifdef __BIG_ENDIAN + /* The sk98lin vendor driver uses hardware byte swapping but + * this driver uses software swapping. + */ + reg &= ~PCI_REV_DESC; + err = pci_write_config_dword(pdev,PCI_DEV_REG2, reg); + if (err) { + dev_err(&pdev->dev, "PCI write config failed\n"); + goto err_out_free_regions; + } +#endif + wol_default = device_may_wakeup(&pdev->dev) ? WAKE_MAGIC : 0; err = -ENOMEM; @@ -4406,18 +4435,6 @@ static int __devinit sky2_probe(struct pci_dev *pdev, goto err_out_free_hw; } -#ifdef __BIG_ENDIAN - /* The sk98lin vendor driver uses hardware byte swapping but - * this driver uses software swapping. - */ - { - u32 reg; - reg = sky2_pci_read32(hw, PCI_DEV_REG2); - reg &= ~PCI_REV_DESC; - sky2_pci_write32(hw, PCI_DEV_REG2, reg); - } -#endif - /* ring for status responses */ hw->st_le = pci_alloc_consistent(pdev, STATUS_LE_BYTES, &hw->st_dma); if (!hw->st_le) -- GitLab From 073a24364fe6de7eef0a3dec0ec7d48e56624092 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Tue, 3 Feb 2009 15:15:15 -0800 Subject: [PATCH 1151/4982] s2io: Formatting log message S2IO driver is printing dev->name before the name being allocated, which display eth%d instead of eth0, eth1, etc. Example: eth%d: Enabling MSIX failed eth%d: MSI-X requested but failed to enable This patch just change eth%d to s2io. Signed-off-by: Breno Leitao Signed-off-by: David S. Miller --- drivers/net/s2io.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index e0a353f4ec9..5cd2291bc0b 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -3862,7 +3862,7 @@ static int s2io_enable_msi_x(struct s2io_nic *nic) ret = pci_enable_msix(nic->pdev, nic->entries, nic->num_entries); /* We fail init if error or we get less vectors than min required */ if (ret) { - DBG_PRINT(ERR_DBG, "%s: Enabling MSIX failed\n", nic->dev->name); + DBG_PRINT(ERR_DBG, "s2io: Enabling MSI-X failed\n"); kfree(nic->entries); nic->mac_control.stats_info->sw_stat.mem_freed += (nic->num_entries * sizeof(struct msix_entry)); @@ -8010,8 +8010,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) if (ret) { DBG_PRINT(ERR_DBG, - "%s: MSI-X requested but failed to enable\n", - dev->name); + "s2io: MSI-X requested but failed to enable\n"); sp->config.intr_type = INTA; } } -- GitLab From 0eb592dbba40baebec9cdde3ff4574185de6cbcc Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 3 Feb 2009 16:00:38 -0800 Subject: [PATCH 1152/4982] x86/paravirt: return full 64-bit result Impact: Bug fix A hunk went missing in the original patch, and callee-save callsites were not marked as returning the upper 32-bit of result, causing Badness. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/paravirt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 016dce31130..c85e7475e17 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -522,7 +522,7 @@ int paravirt_disable_iospace(void); "=c" (__ecx) #define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS -#define PVOP_VCALLEE_CLOBBERS "=a" (__eax) +#define PVOP_VCALLEE_CLOBBERS "=a" (__eax), "=d" (__edx) #define PVOP_CALLEE_CLOBBERS PVOP_VCALLEE_CLOBBERS #define EXTRA_CLOBBERS -- GitLab From f5deb79679af6eb41b61112fadcda28b2a4cfb0d Mon Sep 17 00:00:00 2001 From: Huang Ying Date: Tue, 3 Feb 2009 14:22:48 +0800 Subject: [PATCH 1153/4982] x86: kexec: Use one page table in x86_64 machine_kexec Impact: reduce kernel BSS size by 7 pages, improve code readability Two page tables are used in current x86_64 kexec implementation. One is used to jump from kernel virtual address to identity map address, the other is used to map all physical memory. In fact, on x86_64, there is no conflict between kernel virtual address space and physical memory space, so just one page table is sufficient. The page table pages used to map control page are dynamically allocated to save memory if kexec image is not loaded. ASM code used to map control page is replaced by C code too. Signed-off-by: Huang Ying Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/kexec.h | 27 ++---- arch/x86/kernel/machine_kexec_64.c | 82 ++++++++++++------ arch/x86/kernel/relocate_kernel_64.S | 125 +-------------------------- 3 files changed, 67 insertions(+), 167 deletions(-) diff --git a/arch/x86/include/asm/kexec.h b/arch/x86/include/asm/kexec.h index c61d8b2ab8b..0ceb6d19ed3 100644 --- a/arch/x86/include/asm/kexec.h +++ b/arch/x86/include/asm/kexec.h @@ -9,23 +9,8 @@ # define PAGES_NR 4 #else # define PA_CONTROL_PAGE 0 -# define VA_CONTROL_PAGE 1 -# define PA_PGD 2 -# define VA_PGD 3 -# define PA_PUD_0 4 -# define VA_PUD_0 5 -# define PA_PMD_0 6 -# define VA_PMD_0 7 -# define PA_PTE_0 8 -# define VA_PTE_0 9 -# define PA_PUD_1 10 -# define VA_PUD_1 11 -# define PA_PMD_1 12 -# define VA_PMD_1 13 -# define PA_PTE_1 14 -# define VA_PTE_1 15 -# define PA_TABLE_PAGE 16 -# define PAGES_NR 17 +# define PA_TABLE_PAGE 1 +# define PAGES_NR 2 #endif #ifdef CONFIG_X86_32 @@ -157,9 +142,9 @@ relocate_kernel(unsigned long indirection_page, unsigned long start_address) ATTRIB_NORET; #endif -#ifdef CONFIG_X86_32 #define ARCH_HAS_KIMAGE_ARCH +#ifdef CONFIG_X86_32 struct kimage_arch { pgd_t *pgd; #ifdef CONFIG_X86_PAE @@ -169,6 +154,12 @@ struct kimage_arch { pte_t *pte0; pte_t *pte1; }; +#else +struct kimage_arch { + pud_t *pud; + pmd_t *pmd; + pte_t *pte; +}; #endif #endif /* __ASSEMBLY__ */ diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c index c43caa3a91f..6993d51b7fd 100644 --- a/arch/x86/kernel/machine_kexec_64.c +++ b/arch/x86/kernel/machine_kexec_64.c @@ -18,15 +18,6 @@ #include #include -#define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE))) -static u64 kexec_pgd[512] PAGE_ALIGNED; -static u64 kexec_pud0[512] PAGE_ALIGNED; -static u64 kexec_pmd0[512] PAGE_ALIGNED; -static u64 kexec_pte0[512] PAGE_ALIGNED; -static u64 kexec_pud1[512] PAGE_ALIGNED; -static u64 kexec_pmd1[512] PAGE_ALIGNED; -static u64 kexec_pte1[512] PAGE_ALIGNED; - static void init_level2_page(pmd_t *level2p, unsigned long addr) { unsigned long end_addr; @@ -107,12 +98,65 @@ out: return result; } +static void free_transition_pgtable(struct kimage *image) +{ + free_page((unsigned long)image->arch.pud); + free_page((unsigned long)image->arch.pmd); + free_page((unsigned long)image->arch.pte); +} + +static int init_transition_pgtable(struct kimage *image, pgd_t *pgd) +{ + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + unsigned long vaddr, paddr; + int result = -ENOMEM; + + vaddr = (unsigned long)relocate_kernel; + paddr = __pa(page_address(image->control_code_page)+PAGE_SIZE); + pgd += pgd_index(vaddr); + if (!pgd_present(*pgd)) { + pud = (pud_t *)get_zeroed_page(GFP_KERNEL); + if (!pud) + goto err; + image->arch.pud = pud; + set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE)); + } + pud = pud_offset(pgd, vaddr); + if (!pud_present(*pud)) { + pmd = (pmd_t *)get_zeroed_page(GFP_KERNEL); + if (!pmd) + goto err; + image->arch.pmd = pmd; + set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE)); + } + pmd = pmd_offset(pud, vaddr); + if (!pmd_present(*pmd)) { + pte = (pte_t *)get_zeroed_page(GFP_KERNEL); + if (!pte) + goto err; + image->arch.pte = pte; + set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE)); + } + pte = pte_offset_kernel(pmd, vaddr); + set_pte(pte, pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL_EXEC)); + return 0; +err: + free_transition_pgtable(image); + return result; +} + static int init_pgtable(struct kimage *image, unsigned long start_pgtable) { pgd_t *level4p; + int result; level4p = (pgd_t *)__va(start_pgtable); - return init_level4_page(image, level4p, 0, max_pfn << PAGE_SHIFT); + result = init_level4_page(image, level4p, 0, max_pfn << PAGE_SHIFT); + if (result) + return result; + return init_transition_pgtable(image, level4p); } static void set_idt(void *newidt, u16 limit) @@ -174,7 +218,7 @@ int machine_kexec_prepare(struct kimage *image) void machine_kexec_cleanup(struct kimage *image) { - return; + free_transition_pgtable(image); } /* @@ -195,22 +239,6 @@ void machine_kexec(struct kimage *image) memcpy(control_page, relocate_kernel, PAGE_SIZE); page_list[PA_CONTROL_PAGE] = virt_to_phys(control_page); - page_list[VA_CONTROL_PAGE] = (unsigned long)relocate_kernel; - page_list[PA_PGD] = virt_to_phys(&kexec_pgd); - page_list[VA_PGD] = (unsigned long)kexec_pgd; - page_list[PA_PUD_0] = virt_to_phys(&kexec_pud0); - page_list[VA_PUD_0] = (unsigned long)kexec_pud0; - page_list[PA_PMD_0] = virt_to_phys(&kexec_pmd0); - page_list[VA_PMD_0] = (unsigned long)kexec_pmd0; - page_list[PA_PTE_0] = virt_to_phys(&kexec_pte0); - page_list[VA_PTE_0] = (unsigned long)kexec_pte0; - page_list[PA_PUD_1] = virt_to_phys(&kexec_pud1); - page_list[VA_PUD_1] = (unsigned long)kexec_pud1; - page_list[PA_PMD_1] = virt_to_phys(&kexec_pmd1); - page_list[VA_PMD_1] = (unsigned long)kexec_pmd1; - page_list[PA_PTE_1] = virt_to_phys(&kexec_pte1); - page_list[VA_PTE_1] = (unsigned long)kexec_pte1; - page_list[PA_TABLE_PAGE] = (unsigned long)__pa(page_address(image->control_code_page)); diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S index f5afe665a82..b0bbdd4829c 100644 --- a/arch/x86/kernel/relocate_kernel_64.S +++ b/arch/x86/kernel/relocate_kernel_64.S @@ -29,122 +29,6 @@ relocate_kernel: * %rdx start address */ - /* map the control page at its virtual address */ - - movq $0x0000ff8000000000, %r10 /* mask */ - mov $(39 - 3), %cl /* bits to shift */ - movq PTR(VA_CONTROL_PAGE)(%rsi), %r11 /* address to map */ - - movq %r11, %r9 - andq %r10, %r9 - shrq %cl, %r9 - - movq PTR(VA_PGD)(%rsi), %r8 - addq %r8, %r9 - movq PTR(PA_PUD_0)(%rsi), %r8 - orq $PAGE_ATTR, %r8 - movq %r8, (%r9) - - shrq $9, %r10 - sub $9, %cl - - movq %r11, %r9 - andq %r10, %r9 - shrq %cl, %r9 - - movq PTR(VA_PUD_0)(%rsi), %r8 - addq %r8, %r9 - movq PTR(PA_PMD_0)(%rsi), %r8 - orq $PAGE_ATTR, %r8 - movq %r8, (%r9) - - shrq $9, %r10 - sub $9, %cl - - movq %r11, %r9 - andq %r10, %r9 - shrq %cl, %r9 - - movq PTR(VA_PMD_0)(%rsi), %r8 - addq %r8, %r9 - movq PTR(PA_PTE_0)(%rsi), %r8 - orq $PAGE_ATTR, %r8 - movq %r8, (%r9) - - shrq $9, %r10 - sub $9, %cl - - movq %r11, %r9 - andq %r10, %r9 - shrq %cl, %r9 - - movq PTR(VA_PTE_0)(%rsi), %r8 - addq %r8, %r9 - movq PTR(PA_CONTROL_PAGE)(%rsi), %r8 - orq $PAGE_ATTR, %r8 - movq %r8, (%r9) - - /* identity map the control page at its physical address */ - - movq $0x0000ff8000000000, %r10 /* mask */ - mov $(39 - 3), %cl /* bits to shift */ - movq PTR(PA_CONTROL_PAGE)(%rsi), %r11 /* address to map */ - - movq %r11, %r9 - andq %r10, %r9 - shrq %cl, %r9 - - movq PTR(VA_PGD)(%rsi), %r8 - addq %r8, %r9 - movq PTR(PA_PUD_1)(%rsi), %r8 - orq $PAGE_ATTR, %r8 - movq %r8, (%r9) - - shrq $9, %r10 - sub $9, %cl - - movq %r11, %r9 - andq %r10, %r9 - shrq %cl, %r9 - - movq PTR(VA_PUD_1)(%rsi), %r8 - addq %r8, %r9 - movq PTR(PA_PMD_1)(%rsi), %r8 - orq $PAGE_ATTR, %r8 - movq %r8, (%r9) - - shrq $9, %r10 - sub $9, %cl - - movq %r11, %r9 - andq %r10, %r9 - shrq %cl, %r9 - - movq PTR(VA_PMD_1)(%rsi), %r8 - addq %r8, %r9 - movq PTR(PA_PTE_1)(%rsi), %r8 - orq $PAGE_ATTR, %r8 - movq %r8, (%r9) - - shrq $9, %r10 - sub $9, %cl - - movq %r11, %r9 - andq %r10, %r9 - shrq %cl, %r9 - - movq PTR(VA_PTE_1)(%rsi), %r8 - addq %r8, %r9 - movq PTR(PA_CONTROL_PAGE)(%rsi), %r8 - orq $PAGE_ATTR, %r8 - movq %r8, (%r9) - -relocate_new_kernel: - /* %rdi indirection_page - * %rsi page_list - * %rdx start address - */ - /* zero out flags, and disable interrupts */ pushq $0 popfq @@ -156,9 +40,8 @@ relocate_new_kernel: /* get physical address of page table now too */ movq PTR(PA_TABLE_PAGE)(%rsi), %rcx - /* switch to new set of page tables */ - movq PTR(PA_PGD)(%rsi), %r9 - movq %r9, %cr3 + /* Switch to the identity mapped page tables */ + movq %rcx, %cr3 /* setup a new stack at the end of the physical control page */ lea PAGE_SIZE(%r8), %rsp @@ -194,9 +77,7 @@ identity_mapped: jmp 1f 1: - /* Switch to the identity mapped page tables, - * and flush the TLB. - */ + /* Flush the TLB (needed?) */ movq %rcx, %cr3 /* Do the copies */ -- GitLab From 508eb2ce222053e51e2243b7add8eeac85b1d250 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 4 Feb 2009 15:28:06 +0900 Subject: [PATCH 1154/4982] sh: Restrict old CMT timer code to SH-2/SH-2A. None of the other platforms use this, and need individual porting. Restrict it back to the supported set of CPU subtypes. Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 50c992444e5..78a01d7d37e 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -419,7 +419,7 @@ config SH_TMU config SH_CMT bool "CMT timer support" - depends on SYS_SUPPORTS_CMT + depends on SYS_SUPPORTS_CMT && CPU_SH2 default y help This enables the use of the CMT as the system timer. -- GitLab From 5b2474425ed2a625b75dcd8d648701e473b7d764 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 3 Feb 2009 17:19:40 +0100 Subject: [PATCH 1155/4982] ASoC: uda1380: split set_dai_fmt into _both, _playback and _capture variants This patch splits set_dai_fmt into three variants (single interface, dual interface playback only, dual interface capture only) so that data input and output formats can be configured separately for dual interface setups. Signed-off-by: Philipp Zabel Tested-by: Vasily Khoruzhick Signed-off-by: Mark Brown --- sound/soc/codecs/uda1380.c | 68 ++++++++++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 6e4a1770ce8..5242b8156b3 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -356,7 +356,7 @@ static int uda1380_add_widgets(struct snd_soc_codec *codec) return 0; } -static int uda1380_set_dai_fmt(struct snd_soc_dai *codec_dai, +static int uda1380_set_dai_fmt_both(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; @@ -366,16 +366,70 @@ static int uda1380_set_dai_fmt(struct snd_soc_dai *codec_dai, iface = uda1380_read_reg_cache(codec, UDA1380_IFACE); iface &= ~(R01_SFORI_MASK | R01_SIM | R01_SFORO_MASK); - /* FIXME: how to select I2S for DATAO and MSB for DATAI correctly? */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: iface |= R01_SFORI_I2S | R01_SFORO_I2S; break; case SND_SOC_DAIFMT_LSB: - iface |= R01_SFORI_LSB16 | R01_SFORO_I2S; + iface |= R01_SFORI_LSB16 | R01_SFORO_LSB16; break; case SND_SOC_DAIFMT_MSB: - iface |= R01_SFORI_MSB | R01_SFORO_I2S; + iface |= R01_SFORI_MSB | R01_SFORO_MSB; + } + + if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBM_CFM) + iface |= R01_SIM; + + uda1380_write(codec, UDA1380_IFACE, iface); + + return 0; +} + +static int uda1380_set_dai_fmt_playback(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + int iface; + + /* set up DAI based upon fmt */ + iface = uda1380_read_reg_cache(codec, UDA1380_IFACE); + iface &= ~R01_SFORI_MASK; + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + iface |= R01_SFORI_I2S; + break; + case SND_SOC_DAIFMT_LSB: + iface |= R01_SFORI_LSB16; + break; + case SND_SOC_DAIFMT_MSB: + iface |= R01_SFORI_MSB; + } + + uda1380_write(codec, UDA1380_IFACE, iface); + + return 0; +} + +static int uda1380_set_dai_fmt_capture(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + int iface; + + /* set up DAI based upon fmt */ + iface = uda1380_read_reg_cache(codec, UDA1380_IFACE); + iface &= ~(R01_SIM | R01_SFORO_MASK); + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + iface |= R01_SFORO_I2S; + break; + case SND_SOC_DAIFMT_LSB: + iface |= R01_SFORO_LSB16; + break; + case SND_SOC_DAIFMT_MSB: + iface |= R01_SFORO_MSB; } if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBM_CFM) @@ -549,7 +603,7 @@ struct snd_soc_dai uda1380_dai[] = { .shutdown = uda1380_pcm_shutdown, .prepare = uda1380_pcm_prepare, .digital_mute = uda1380_mute, - .set_fmt = uda1380_set_dai_fmt, + .set_fmt = uda1380_set_dai_fmt_both, }, }, { /* playback only - dual interface */ @@ -566,7 +620,7 @@ struct snd_soc_dai uda1380_dai[] = { .shutdown = uda1380_pcm_shutdown, .prepare = uda1380_pcm_prepare, .digital_mute = uda1380_mute, - .set_fmt = uda1380_set_dai_fmt, + .set_fmt = uda1380_set_dai_fmt_playback, }, }, { /* capture only - dual interface*/ @@ -582,7 +636,7 @@ struct snd_soc_dai uda1380_dai[] = { .hw_params = uda1380_pcm_hw_params, .shutdown = uda1380_pcm_shutdown, .prepare = uda1380_pcm_prepare, - .set_fmt = uda1380_set_dai_fmt, + .set_fmt = uda1380_set_dai_fmt_capture, }, }, }; -- GitLab From 0664678a84c653bde844c7d91646259a25c6188b Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 3 Feb 2009 21:18:26 +0100 Subject: [PATCH 1156/4982] ASoC: pxa-ssp: fix SSP port request PXA2xx/3xx SSP ports start from 1, not 0. Thus, the probe function requested the wrong SSP port. Correcting this unveiled another bug where ssp_init tries to request the already-requested SSP port again. So this patch replaces the ssp_init/exit calls with their internals from mach-pxa/ssp.c, leaving out the redundant ssp_request and the unneeded IRQ request. Effectively, that leaves us with not much more than enabling/disabling the SSP clock. Signed-off-by: Philipp Zabel Signed-off-by: Mark Brown --- sound/soc/pxa/pxa-ssp.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 73cb6b4c2f2..4a973ab710b 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -21,6 +21,8 @@ #include #include +#include + #include #include #include @@ -221,9 +223,9 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream, int ret = 0; if (!cpu_dai->active) { - ret = ssp_init(&priv->dev, cpu_dai->id + 1, SSP_NO_IRQ); - if (ret < 0) - return ret; + priv->dev.port = cpu_dai->id + 1; + priv->dev.irq = NO_IRQ; + clk_enable(priv->dev.ssp->clk); ssp_disable(&priv->dev); } return ret; @@ -238,7 +240,7 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream, if (!cpu_dai->active) { ssp_disable(&priv->dev); - ssp_exit(&priv->dev); + clk_disable(priv->dev.ssp->clk); } } @@ -751,7 +753,7 @@ static int pxa_ssp_probe(struct platform_device *pdev, if (!priv) return -ENOMEM; - priv->dev.ssp = ssp_request(dai->id, "SoC audio"); + priv->dev.ssp = ssp_request(dai->id + 1, "SoC audio"); if (priv->dev.ssp == NULL) { ret = -ENODEV; goto err_priv; -- GitLab From 680cd53652d8bfb2b97d8c0248d1afb82de6b61d Mon Sep 17 00:00:00 2001 From: Kusanagi Kouichi Date: Thu, 5 Feb 2009 00:00:58 +0900 Subject: [PATCH 1157/4982] ALSA: hda: Add digital beep generator support for Realtek codecs. A digital beep generator can be used via input layer. Signed-off-by: Kusanagi Kouichi Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_beep.h | 2 +- sound/pci/hda/patch_realtek.c | 62 +++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h index b9679f081ca..51bf6a5daf3 100644 --- a/sound/pci/hda/hda_beep.h +++ b/sound/pci/hda/hda_beep.h @@ -39,7 +39,7 @@ struct hda_beep { int snd_hda_attach_beep_device(struct hda_codec *codec, int nid); void snd_hda_detach_beep_device(struct hda_codec *codec); #else -#define snd_hda_attach_beep_device(...) +#define snd_hda_attach_beep_device(...) 0 #define snd_hda_detach_beep_device(...) #endif #endif diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index bd9ef336389..0faa41bfc8b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -30,6 +30,7 @@ #include #include "hda_codec.h" #include "hda_local.h" +#include "hda_beep.h" #define ALC880_FRONT_EVENT 0x01 #define ALC880_DCVOL_EVENT 0x02 @@ -3187,6 +3188,7 @@ static void alc_free(struct hda_codec *codec) alc_free_kctls(codec); kfree(spec); + snd_hda_detach_beep_device(codec); codec->spec = NULL; /* to be sure */ } @@ -4355,6 +4357,12 @@ static int patch_alc880(struct hda_codec *codec) } } + err = snd_hda_attach_beep_device(codec, 0x1); + if (err < 0) { + alc_free(codec); + return err; + } + if (board_config != ALC880_AUTO) setup_preset(spec, &alc880_presets[board_config]); @@ -5882,6 +5890,12 @@ static int patch_alc260(struct hda_codec *codec) } } + err = snd_hda_attach_beep_device(codec, 0x1); + if (err < 0) { + alc_free(codec); + return err; + } + if (board_config != ALC260_AUTO) setup_preset(spec, &alc260_presets[board_config]); @@ -7093,6 +7107,12 @@ static int patch_alc882(struct hda_codec *codec) } } + err = snd_hda_attach_beep_device(codec, 0x1); + if (err < 0) { + alc_free(codec); + return err; + } + if (board_config != ALC882_AUTO) setup_preset(spec, &alc882_presets[board_config]); @@ -9093,6 +9113,12 @@ static int patch_alc883(struct hda_codec *codec) } } + err = snd_hda_attach_beep_device(codec, 0x1); + if (err < 0) { + alc_free(codec); + return err; + } + if (board_config != ALC883_AUTO) setup_preset(spec, &alc883_presets[board_config]); @@ -11013,6 +11039,12 @@ static int patch_alc262(struct hda_codec *codec) } } + err = snd_hda_attach_beep_device(codec, 0x1); + if (err < 0) { + alc_free(codec); + return err; + } + if (board_config != ALC262_AUTO) setup_preset(spec, &alc262_presets[board_config]); @@ -12051,6 +12083,12 @@ static int patch_alc268(struct hda_codec *codec) } } + err = snd_hda_attach_beep_device(codec, 0x1); + if (err < 0) { + alc_free(codec); + return err; + } + if (board_config != ALC268_AUTO) setup_preset(spec, &alc268_presets[board_config]); @@ -12885,6 +12923,12 @@ static int patch_alc269(struct hda_codec *codec) } } + err = snd_hda_attach_beep_device(codec, 0x1); + if (err < 0) { + alc_free(codec); + return err; + } + if (board_config != ALC269_AUTO) setup_preset(spec, &alc269_presets[board_config]); @@ -13978,6 +14022,12 @@ static int patch_alc861(struct hda_codec *codec) } } + err = snd_hda_attach_beep_device(codec, 0x23); + if (err < 0) { + alc_free(codec); + return err; + } + if (board_config != ALC861_AUTO) setup_preset(spec, &alc861_presets[board_config]); @@ -14924,6 +14974,12 @@ static int patch_alc861vd(struct hda_codec *codec) } } + err = snd_hda_attach_beep_device(codec, 0x23); + if (err < 0) { + alc_free(codec); + return err; + } + if (board_config != ALC861VD_AUTO) setup_preset(spec, &alc861vd_presets[board_config]); @@ -16733,6 +16789,12 @@ static int patch_alc662(struct hda_codec *codec) } } + err = snd_hda_attach_beep_device(codec, 0x1); + if (err < 0) { + alc_free(codec); + return err; + } + if (board_config != ALC662_AUTO) setup_preset(spec, &alc662_presets[board_config]); -- GitLab From 453e37b37521b613f0927fcf53ccd93ad3a8b3ae Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Wed, 4 Feb 2009 17:41:32 +0100 Subject: [PATCH 1158/4982] ALSA: sscape: drop redundant fields from soundscape struct The wss_base is disuised parameter for one function. It is converted to function parameter. The code_type is only set but never read. It is removed. The midi_vol is set only to 0 so it does not work as detection of change in midi volume. It is fixed. The xport variable is alias to the port[dev]. Use the port[dev] directly to increase readability. Signed-off-by: Krzysztof Helt Signed-off-by: Takashi Iwai --- sound/isa/sscape.c | 44 ++++++++++++++++---------------------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 681e2237acb..33c1258029f 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -135,8 +135,6 @@ enum card_type { struct soundscape { spinlock_t lock; unsigned io_base; - unsigned wss_base; - int codec_type; int ic_type; enum card_type type; struct resource *io_res; @@ -726,13 +724,7 @@ static int sscape_midi_get(struct snd_kcontrol *kctl, unsigned long flags; spin_lock_irqsave(&s->lock, flags); - set_host_mode_unsafe(s->io_base); - - if (host_write_ctrl_unsafe(s->io_base, CMD_GET_MIDI_VOL, 100)) { - uctl->value.integer.value[0] = host_read_ctrl_unsafe(s->io_base, 100); - } - - set_midi_mode_unsafe(s->io_base); + uctl->value.integer.value[0] = s->midi_vol; spin_unlock_irqrestore(&s->lock, flags); return 0; } @@ -767,6 +759,7 @@ static int sscape_midi_put(struct snd_kcontrol *kctl, change = (host_write_ctrl_unsafe(s->io_base, CMD_SET_MIDI_VOL, 100) && host_write_ctrl_unsafe(s->io_base, ((unsigned char) uctl->value.integer. value[0]) & 127, 100) && host_write_ctrl_unsafe(s->io_base, CMD_XXX_MIDI_VOL, 100)); + s->midi_vol = (unsigned char) uctl->value.integer.value[0] & 127; __skip_change: /* @@ -809,12 +802,11 @@ static unsigned __devinit get_irq_config(int irq) * Perform certain arcane port-checks to see whether there * is a SoundScape board lurking behind the given ports. */ -static int __devinit detect_sscape(struct soundscape *s) +static int __devinit detect_sscape(struct soundscape *s, long wss_io) { unsigned long flags; unsigned d; int retval = 0; - int codec = s->wss_base; spin_lock_irqsave(&s->lock, flags); @@ -830,13 +822,11 @@ static int __devinit detect_sscape(struct soundscape *s) if ((d & 0x80) != 0) goto _done; - if (d == 0) { - s->codec_type = 1; + if (d == 0) s->ic_type = IC_ODIE; - } else if ((d & 0x60) != 0) { - s->codec_type = 2; + else if ((d & 0x60) != 0) s->ic_type = IC_OPUS; - } else + else goto _done; outb(0xfa, ODIE_ADDR_IO(s->io_base)); @@ -856,10 +846,10 @@ static int __devinit detect_sscape(struct soundscape *s) sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0); if (s->type == SSCAPE_VIVO) - codec += 4; + wss_io += 4; /* wait for WSS codec */ for (d = 0; d < 500; d++) { - if ((inb(codec) & 0x80) == 0) + if ((inb(wss_io) & 0x80) == 0) break; spin_unlock_irqrestore(&s->lock, flags); msleep(1); @@ -1057,7 +1047,6 @@ static int __devinit create_sscape(int dev, struct snd_card *card) unsigned dma_cfg; unsigned irq_cfg; unsigned mpu_irq_cfg; - unsigned xport; struct resource *io_res; struct resource *wss_res; unsigned long flags; @@ -1077,15 +1066,15 @@ static int __devinit create_sscape(int dev, struct snd_card *card) printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]); return -ENXIO; } - xport = port[dev]; /* * Grab IO ports that we will need to probe so that we * can detect and control this hardware ... */ - io_res = request_region(xport, 8, "SoundScape"); + io_res = request_region(port[dev], 8, "SoundScape"); if (!io_res) { - snd_printk(KERN_ERR "sscape: can't grab port 0x%x\n", xport); + snd_printk(KERN_ERR + "sscape: can't grab port 0x%lx\n", port[dev]); return -EBUSY; } wss_res = NULL; @@ -1112,10 +1101,9 @@ static int __devinit create_sscape(int dev, struct snd_card *card) spin_lock_init(&sscape->fwlock); sscape->io_res = io_res; sscape->wss_res = wss_res; - sscape->io_base = xport; - sscape->wss_base = wss_port[dev]; + sscape->io_base = port[dev]; - if (!detect_sscape(sscape)) { + if (!detect_sscape(sscape, wss_port[dev])) { printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", sscape->io_base); err = -ENODEV; goto _release_dma; @@ -1188,11 +1176,11 @@ static int __devinit create_sscape(int dev, struct snd_card *card) } #define MIDI_DEVNUM 0 if (sscape->type != SSCAPE_VIVO) { - err = create_mpu401(card, MIDI_DEVNUM, xport, mpu_irq[dev]); + err = create_mpu401(card, MIDI_DEVNUM, port[dev], mpu_irq[dev]); if (err < 0) { printk(KERN_ERR "sscape: Failed to create " - "MPU-401 device at 0x%x\n", - xport); + "MPU-401 device at 0x%lx\n", + port[dev]); goto _release_dma; } -- GitLab From 5e7476243ad755fa1d8be2b1774d0aeb16bb48df Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 4 Feb 2009 18:28:42 +0100 Subject: [PATCH 1159/4982] ALSA: msnd - Fix build error with CONFIG_PNP=n sound/isa/msnd/msnd_pinnacle.c:891: error: 'isapnp' undeclared (first use in this function) Signed-off-by: Takashi Iwai --- sound/isa/msnd/msnd_pinnacle.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c index 70559223e8f..60b6abd7161 100644 --- a/sound/isa/msnd/msnd_pinnacle.c +++ b/sound/isa/msnd/msnd_pinnacle.c @@ -785,6 +785,9 @@ static int calibrate_signal; static int isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; module_param_array(isapnp, bool, NULL, 0444); MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard."); +#define has_isapnp(x) isapnp[x] +#else +#define has_isapnp(x) 0 #endif MODULE_AUTHOR("Karsten Wiese "); @@ -888,7 +891,7 @@ static int __devinit snd_msnd_isa_probe(struct device *pdev, unsigned int idx) struct snd_card *card; struct snd_msnd *chip; - if (isapnp[idx] || cfg[idx] == SNDRV_AUTO_PORT) { + if (has_isapnp(idx) || cfg[idx] == SNDRV_AUTO_PORT) { printk(KERN_INFO LOGNAME ": Assuming PnP mode\n"); return -ENODEV; } @@ -1082,7 +1085,7 @@ static int __devinit snd_msnd_pnp_detect(struct pnp_card_link *pcard, int ret; for ( ; idx < SNDRV_CARDS; idx++) { - if (isapnp[idx]) + if (has_isapnp(idx)) break; } if (idx >= SNDRV_CARDS) -- GitLab From 0973a06cde8cc1522fbcf2baacb926f1ee3f4c79 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Wed, 4 Feb 2009 15:24:09 -0800 Subject: [PATCH 1160/4982] x86: mm: introduce helper function in fault.c Impact: cleanup Introduce helper function fault_in_kernel_address() to make editors happy. Signed-off-by: Hiroshi Shimamoto Signed-off-by: H. Peter Anvin --- arch/x86/mm/fault.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index eb4d7fe0593..8e9b0f1fd87 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -775,6 +775,15 @@ static inline int access_error(unsigned long error_code, int write, return 0; } +static int fault_in_kernel_space(unsigned long address) +{ +#ifdef CONFIG_X86_32 + return address >= TASK_SIZE; +#else /* !CONFIG_X86_32 */ + return address >= TASK_SIZE64; +#endif /* CONFIG_X86_32 */ +} + /* * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate @@ -817,11 +826,7 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) * (error_code & 4) == 0, and that the fault was not a * protection error (error_code & 9) == 0. */ -#ifdef CONFIG_X86_32 - if (unlikely(address >= TASK_SIZE)) { -#else - if (unlikely(address >= TASK_SIZE64)) { -#endif + if (unlikely(fault_in_kernel_space(address))) { if (!(error_code & (PF_RSVD|PF_USER|PF_PROT)) && vmalloc_fault(address) >= 0) return; -- GitLab From 2a41f71d3bd97dde3305b4e1c43ab0eca46e7c71 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 4 Feb 2009 09:02:34 +0000 Subject: [PATCH 1161/4982] virtio_net: Add a virtqueue for outbound control commands This will be used for RX mode, MAC filter table, VLAN filtering, etc... The control transaction consists of one or more "out" sg entries and one or more "in" sg entries. The first out entry contains a header defining the class and command. Additional out entries may provide data for the command. The last in entry provides a status response back from the command. Virtqueues typically run asynchronous, running a callback function when there's data in the channel. We can't readily make use of this in the command paths where we need to use this. Instead, we kick the virtqueue and spin. The kick causes an I/O write, triggering an immediate trap into the hypervisor. Signed-off-by: Alex Williamson Acked-by: Rusty Russell Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 68 ++++++++++++++++++++++++++++++++++++-- include/linux/virtio_net.h | 18 ++++++++++ 2 files changed, 83 insertions(+), 3 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index fe576e75a53..67bb583b7fc 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -37,10 +37,12 @@ module_param(gso, bool, 0444); #define MAX_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN) #define GOOD_COPY_LEN 128 +#define VIRTNET_SEND_COMMAND_SG_MAX 0 + struct virtnet_info { struct virtio_device *vdev; - struct virtqueue *rvq, *svq; + struct virtqueue *rvq, *svq, *cvq; struct net_device *dev; struct napi_struct napi; unsigned int status; @@ -589,6 +591,53 @@ static int virtnet_open(struct net_device *dev) return 0; } +/* + * Send command via the control virtqueue and check status. Commands + * supported by the hypervisor, as indicated by feature bits, should + * never fail unless improperly formated. + */ +static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, + struct scatterlist *data, int out, int in) +{ + struct scatterlist sg[VIRTNET_SEND_COMMAND_SG_MAX + 2]; + struct virtio_net_ctrl_hdr ctrl; + virtio_net_ctrl_ack status = ~0; + unsigned int tmp; + + if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) { + BUG(); /* Caller should know better */ + return false; + } + + BUG_ON(out + in > VIRTNET_SEND_COMMAND_SG_MAX); + + out++; /* Add header */ + in++; /* Add return status */ + + ctrl.class = class; + ctrl.cmd = cmd; + + sg_init_table(sg, out + in); + + sg_set_buf(&sg[0], &ctrl, sizeof(ctrl)); + memcpy(&sg[1], data, sizeof(struct scatterlist) * (out + in - 2)); + sg_set_buf(&sg[out + in - 1], &status, sizeof(status)); + + if (vi->cvq->vq_ops->add_buf(vi->cvq, sg, out, in, vi) != 0) + BUG(); + + vi->cvq->vq_ops->kick(vi->cvq); + + /* + * Spin for a response, the kick causes an ioport write, trapping + * into the hypervisor, so the request should be handled immediately. + */ + while (!vi->cvq->vq_ops->get_buf(vi->cvq, &tmp)) + cpu_relax(); + + return status == VIRTIO_NET_OK; +} + static int virtnet_close(struct net_device *dev) { struct virtnet_info *vi = netdev_priv(dev); @@ -752,6 +801,14 @@ static int virtnet_probe(struct virtio_device *vdev) goto free_recv; } + if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) { + vi->cvq = vdev->config->find_vq(vdev, 2, NULL); + if (IS_ERR(vi->cvq)) { + err = PTR_ERR(vi->svq); + goto free_send; + } + } + /* Initialize our empty receive and send queues. */ skb_queue_head_init(&vi->recv); skb_queue_head_init(&vi->send); @@ -764,7 +821,7 @@ static int virtnet_probe(struct virtio_device *vdev) err = register_netdev(dev); if (err) { pr_debug("virtio_net: registering device failed\n"); - goto free_send; + goto free_ctrl; } /* Last of all, set up some receive buffers. */ @@ -784,6 +841,9 @@ static int virtnet_probe(struct virtio_device *vdev) unregister: unregister_netdev(dev); +free_ctrl: + if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) + vdev->config->del_vq(vi->cvq); free_send: vdev->config->del_vq(vi->svq); free_recv: @@ -815,6 +875,8 @@ static void virtnet_remove(struct virtio_device *vdev) vdev->config->del_vq(vi->svq); vdev->config->del_vq(vi->rvq); + if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) + vdev->config->del_vq(vi->cvq); unregister_netdev(vi->dev); while (vi->pages) @@ -834,7 +896,7 @@ static unsigned int features[] = { VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6, VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */ - VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, + VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ, VIRTIO_F_NOTIFY_ON_EMPTY, }; diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index d8e362d52fd..245eda829aa 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -23,6 +23,7 @@ #define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */ #define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */ #define VIRTIO_NET_F_STATUS 16 /* virtio_net_config.status available */ +#define VIRTIO_NET_F_CTRL_VQ 17 /* Control channel available */ #define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ @@ -59,4 +60,21 @@ struct virtio_net_hdr_mrg_rxbuf { __u16 num_buffers; /* Number of merged rx buffers */ }; +/* + * Control virtqueue data structures + * + * The control virtqueue expects a header in the first sg entry + * and an ack/status response in the last entry. Data for the + * command goes in between. + */ +struct virtio_net_ctrl_hdr { + __u8 class; + __u8 cmd; +} __attribute__((packed)); + +typedef __u8 virtio_net_ctrl_ack; + +#define VIRTIO_NET_OK 0 +#define VIRTIO_NET_ERR 1 + #endif /* _LINUX_VIRTIO_NET_H */ -- GitLab From 2af7698e2dd698d452ab9d63a9ca5956bbe8fc3b Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 4 Feb 2009 09:02:40 +0000 Subject: [PATCH 1162/4982] virtio_net: Add a set_rx_mode interface Make use of the RX_MODE control virtqueue class to enable the set_rx_mode netdev interface. This allows us to selectively enable/disable promiscuous and allmulti mode so we don't see packets we don't want. For now, we automatically enable these as needed if additional unicast or multicast addresses are requested. Signed-off-by: Alex Williamson Acked-by: Rusty Russell Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 34 +++++++++++++++++++++++++++++++++- include/linux/virtio_net.h | 11 +++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 67bb583b7fc..1abea9dc6f0 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -37,7 +37,7 @@ module_param(gso, bool, 0444); #define MAX_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN) #define GOOD_COPY_LEN 128 -#define VIRTNET_SEND_COMMAND_SG_MAX 0 +#define VIRTNET_SEND_COMMAND_SG_MAX 1 struct virtnet_info { @@ -658,6 +658,36 @@ static int virtnet_set_tx_csum(struct net_device *dev, u32 data) return ethtool_op_set_tx_hw_csum(dev, data); } +static void virtnet_set_rx_mode(struct net_device *dev) +{ + struct virtnet_info *vi = netdev_priv(dev); + struct scatterlist sg; + u8 promisc, allmulti; + + /* We can't dynamicaly set ndo_set_rx_mode, so return gracefully */ + if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_RX)) + return; + + promisc = ((dev->flags & IFF_PROMISC) != 0 || dev->uc_count > 0); + allmulti = ((dev->flags & IFF_ALLMULTI) != 0 || dev->mc_count > 0); + + sg_set_buf(&sg, &promisc, sizeof(promisc)); + + if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, + VIRTIO_NET_CTRL_RX_PROMISC, + &sg, 1, 0)) + dev_warn(&dev->dev, "Failed to %sable promisc mode.\n", + promisc ? "en" : "dis"); + + sg_set_buf(&sg, &allmulti, sizeof(allmulti)); + + if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, + VIRTIO_NET_CTRL_RX_ALLMULTI, + &sg, 1, 0)) + dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n", + allmulti ? "en" : "dis"); +} + static struct ethtool_ops virtnet_ethtool_ops = { .set_tx_csum = virtnet_set_tx_csum, .set_sg = ethtool_op_set_sg, @@ -682,6 +712,7 @@ static const struct net_device_ops virtnet_netdev = { .ndo_start_xmit = start_xmit, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, + .ndo_set_rx_mode = virtnet_set_rx_mode, .ndo_change_mtu = virtnet_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = virtnet_netpoll, @@ -897,6 +928,7 @@ static unsigned int features[] = { VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */ VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ, + VIRTIO_NET_F_CTRL_RX, VIRTIO_F_NOTIFY_ON_EMPTY, }; diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index 245eda829aa..63b2461a40f 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -24,6 +24,7 @@ #define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */ #define VIRTIO_NET_F_STATUS 16 /* virtio_net_config.status available */ #define VIRTIO_NET_F_CTRL_VQ 17 /* Control channel available */ +#define VIRTIO_NET_F_CTRL_RX 18 /* Control channel RX mode support */ #define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ @@ -77,4 +78,14 @@ typedef __u8 virtio_net_ctrl_ack; #define VIRTIO_NET_OK 0 #define VIRTIO_NET_ERR 1 +/* + * Control the RX mode, ie. promisucous and allmulti. PROMISC and + * ALLMULTI commands require an "out" sg entry containing a 1 byte + * state value, zero = disable, non-zero = enable. These commands + * are supported with the VIRTIO_NET_F_CTRL_RX feature. + */ +#define VIRTIO_NET_CTRL_RX 0 + #define VIRTIO_NET_CTRL_RX_PROMISC 0 + #define VIRTIO_NET_CTRL_RX_ALLMULTI 1 + #endif /* _LINUX_VIRTIO_NET_H */ -- GitLab From f565a7c259d71cc186753653d978c646d2354b36 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 4 Feb 2009 09:02:45 +0000 Subject: [PATCH 1163/4982] virtio_net: Add a MAC filter table Make use of the MAC control virtqueue class to support a MAC filter table. The filter table is managed by the hypervisor. We consider the table to be available if the CTRL_RX feature bit is set. We leave it to the hypervisor to manage the table and enable promiscuous or all-multi mode as necessary depending on the resources available to it. Signed-off-by: Alex Williamson Acked-by: Rusty Russell Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 55 ++++++++++++++++++++++++++++++++------ include/linux/virtio_net.h | 23 ++++++++++++++++ 2 files changed, 70 insertions(+), 8 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 1abea9dc6f0..daab9c9b0a4 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -37,7 +37,7 @@ module_param(gso, bool, 0444); #define MAX_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN) #define GOOD_COPY_LEN 128 -#define VIRTNET_SEND_COMMAND_SG_MAX 1 +#define VIRTNET_SEND_COMMAND_SG_MAX 2 struct virtnet_info { @@ -661,31 +661,70 @@ static int virtnet_set_tx_csum(struct net_device *dev, u32 data) static void virtnet_set_rx_mode(struct net_device *dev) { struct virtnet_info *vi = netdev_priv(dev); - struct scatterlist sg; + struct scatterlist sg[2]; u8 promisc, allmulti; + struct virtio_net_ctrl_mac *mac_data; + struct dev_addr_list *addr; + void *buf; + int i; /* We can't dynamicaly set ndo_set_rx_mode, so return gracefully */ if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_RX)) return; - promisc = ((dev->flags & IFF_PROMISC) != 0 || dev->uc_count > 0); - allmulti = ((dev->flags & IFF_ALLMULTI) != 0 || dev->mc_count > 0); + promisc = ((dev->flags & IFF_PROMISC) != 0); + allmulti = ((dev->flags & IFF_ALLMULTI) != 0); - sg_set_buf(&sg, &promisc, sizeof(promisc)); + sg_set_buf(sg, &promisc, sizeof(promisc)); if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, VIRTIO_NET_CTRL_RX_PROMISC, - &sg, 1, 0)) + sg, 1, 0)) dev_warn(&dev->dev, "Failed to %sable promisc mode.\n", promisc ? "en" : "dis"); - sg_set_buf(&sg, &allmulti, sizeof(allmulti)); + sg_set_buf(sg, &allmulti, sizeof(allmulti)); if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, VIRTIO_NET_CTRL_RX_ALLMULTI, - &sg, 1, 0)) + sg, 1, 0)) dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n", allmulti ? "en" : "dis"); + + /* MAC filter - use one buffer for both lists */ + mac_data = buf = kzalloc(((dev->uc_count + dev->mc_count) * ETH_ALEN) + + (2 * sizeof(mac_data->entries)), GFP_ATOMIC); + if (!buf) { + dev_warn(&dev->dev, "No memory for MAC address buffer\n"); + return; + } + + /* Store the unicast list and count in the front of the buffer */ + mac_data->entries = dev->uc_count; + addr = dev->uc_list; + for (i = 0; i < dev->uc_count; i++, addr = addr->next) + memcpy(&mac_data->macs[i][0], addr->da_addr, ETH_ALEN); + + sg_set_buf(&sg[0], mac_data, + sizeof(mac_data->entries) + (dev->uc_count * ETH_ALEN)); + + /* multicast list and count fill the end */ + mac_data = (void *)&mac_data->macs[dev->uc_count][0]; + + mac_data->entries = dev->mc_count; + addr = dev->mc_list; + for (i = 0; i < dev->mc_count; i++, addr = addr->next) + memcpy(&mac_data->macs[i][0], addr->da_addr, ETH_ALEN); + + sg_set_buf(&sg[1], mac_data, + sizeof(mac_data->entries) + (dev->mc_count * ETH_ALEN)); + + if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MAC, + VIRTIO_NET_CTRL_MAC_TABLE_SET, + sg, 2, 0)) + dev_warn(&dev->dev, "Failed to set MAC fitler table.\n"); + + kfree(buf); } static struct ethtool_ops virtnet_ethtool_ops = { diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index 63b2461a40f..ba82b653cac 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -88,4 +88,27 @@ typedef __u8 virtio_net_ctrl_ack; #define VIRTIO_NET_CTRL_RX_PROMISC 0 #define VIRTIO_NET_CTRL_RX_ALLMULTI 1 +/* + * Control the MAC filter table. + * + * The MAC filter table is managed by the hypervisor, the guest should + * assume the size is infinite. Filtering should be considered + * non-perfect, ie. based on hypervisor resources, the guest may + * received packets from sources not specified in the filter list. + * + * In addition to the class/cmd header, the TABLE_SET command requires + * two out scatterlists. Each contains a 4 byte count of entries followed + * by a concatenated byte stream of the ETH_ALEN MAC addresses. The + * first sg list contains unicast addresses, the second is for multicast. + * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature + * is available. + */ +struct virtio_net_ctrl_mac { + __u32 entries; + __u8 macs[][ETH_ALEN]; +} __attribute__((packed)); + +#define VIRTIO_NET_CTRL_MAC 1 + #define VIRTIO_NET_CTRL_MAC_TABLE_SET 0 + #endif /* _LINUX_VIRTIO_NET_H */ -- GitLab From 0bde95690d65653e420d04856c5d5783155c747c Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 4 Feb 2009 09:02:50 +0000 Subject: [PATCH 1164/4982] virtio_net: Add support for VLAN filtering in the hypervisor VLAN filtering allows the hypervisor to drop packets from VLANs that we're not a part of, further reducing the number of extraneous packets recieved. This makes use of the VLAN virtqueue command class. The CTRL_VLAN feature bit tells us whether the backend supports VLAN filtering. Signed-off-by: Alex Williamson Acked-by: Rusty Russell Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 31 ++++++++++++++++++++++++++++++- include/linux/virtio_net.h | 14 ++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index daab9c9b0a4..e68813a246d 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -727,6 +727,30 @@ static void virtnet_set_rx_mode(struct net_device *dev) kfree(buf); } +static void virnet_vlan_rx_add_vid(struct net_device *dev, u16 vid) +{ + struct virtnet_info *vi = netdev_priv(dev); + struct scatterlist sg; + + sg_set_buf(&sg, &vid, sizeof(vid)); + + if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN, + VIRTIO_NET_CTRL_VLAN_ADD, &sg, 1, 0)) + dev_warn(&dev->dev, "Failed to add VLAN ID %d.\n", vid); +} + +static void virnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid) +{ + struct virtnet_info *vi = netdev_priv(dev); + struct scatterlist sg; + + sg_set_buf(&sg, &vid, sizeof(vid)); + + if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN, + VIRTIO_NET_CTRL_VLAN_DEL, &sg, 1, 0)) + dev_warn(&dev->dev, "Failed to kill VLAN ID %d.\n", vid); +} + static struct ethtool_ops virtnet_ethtool_ops = { .set_tx_csum = virtnet_set_tx_csum, .set_sg = ethtool_op_set_sg, @@ -753,6 +777,8 @@ static const struct net_device_ops virtnet_netdev = { .ndo_set_mac_address = eth_mac_addr, .ndo_set_rx_mode = virtnet_set_rx_mode, .ndo_change_mtu = virtnet_change_mtu, + .ndo_vlan_rx_add_vid = virnet_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = virnet_vlan_rx_kill_vid, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = virtnet_netpoll, #endif @@ -877,6 +903,9 @@ static int virtnet_probe(struct virtio_device *vdev) err = PTR_ERR(vi->svq); goto free_send; } + + if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VLAN)) + dev->features |= NETIF_F_HW_VLAN_FILTER; } /* Initialize our empty receive and send queues. */ @@ -967,7 +996,7 @@ static unsigned int features[] = { VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */ VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ, - VIRTIO_NET_F_CTRL_RX, + VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN, VIRTIO_F_NOTIFY_ON_EMPTY, }; diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index ba82b653cac..242348bb376 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -25,6 +25,7 @@ #define VIRTIO_NET_F_STATUS 16 /* virtio_net_config.status available */ #define VIRTIO_NET_F_CTRL_VQ 17 /* Control channel available */ #define VIRTIO_NET_F_CTRL_RX 18 /* Control channel RX mode support */ +#define VIRTIO_NET_F_CTRL_VLAN 19 /* Control channel VLAN filtering */ #define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ @@ -111,4 +112,17 @@ struct virtio_net_ctrl_mac { #define VIRTIO_NET_CTRL_MAC 1 #define VIRTIO_NET_CTRL_MAC_TABLE_SET 0 +/* + * Control VLAN filtering + * + * The VLAN filter table is controlled via a simple ADD/DEL interface. + * VLAN IDs not added may be filterd by the hypervisor. Del is the + * opposite of add. Both commands expect an out entry containing a 2 + * byte VLAN ID. VLAN filterting is available with the + * VIRTIO_NET_F_CTRL_VLAN feature bit. + */ +#define VIRTIO_NET_CTRL_VLAN 2 + #define VIRTIO_NET_CTRL_VLAN_ADD 0 + #define VIRTIO_NET_CTRL_VLAN_DEL 1 + #endif /* _LINUX_VIRTIO_NET_H */ -- GitLab From 9c46f6d42f1b5627c49a5906cb5b315ad8716ff0 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 4 Feb 2009 16:36:34 -0800 Subject: [PATCH 1165/4982] virtio_net: Allow setting the MAC address of the NIC Many physical NICs let the OS re-program the "hardware" MAC address. Virtual NICs should allow this too. Signed-off-by: Alex Williamson Acked-by: Mark McLoughlin Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index e68813a246d..3d003392022 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -565,6 +565,22 @@ stop_queue: goto done; } +static int virtnet_set_mac_address(struct net_device *dev, void *p) +{ + struct virtnet_info *vi = netdev_priv(dev); + struct virtio_device *vdev = vi->vdev; + int ret; + + ret = eth_mac_addr(dev, p); + if (ret) + return ret; + + vdev->config->set(vdev, offsetof(struct virtio_net_config, mac), + dev->dev_addr, dev->addr_len); + + return 0; +} + #ifdef CONFIG_NET_POLL_CONTROLLER static void virtnet_netpoll(struct net_device *dev) { @@ -774,7 +790,7 @@ static const struct net_device_ops virtnet_netdev = { .ndo_stop = virtnet_close, .ndo_start_xmit = start_xmit, .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, + .ndo_set_mac_address = virtnet_set_mac_address, .ndo_set_rx_mode = virtnet_set_rx_mode, .ndo_change_mtu = virtnet_change_mtu, .ndo_vlan_rx_add_vid = virnet_vlan_rx_add_vid, @@ -860,8 +876,11 @@ static int virtnet_probe(struct virtio_device *vdev) vdev->config->get(vdev, offsetof(struct virtio_net_config, mac), dev->dev_addr, dev->addr_len); - } else + } else { random_ether_addr(dev->dev_addr); + vdev->config->set(vdev, offsetof(struct virtio_net_config, mac), + dev->dev_addr, dev->addr_len); + } /* Set up our device-specific information */ vi = netdev_priv(dev); -- GitLab From 1577ecef766650a57fceb171acee2b13cbfaf1d3 Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Wed, 4 Feb 2009 16:42:12 -0800 Subject: [PATCH 1166/4982] netdev: Merge UCC and gianfar MDIO bus drivers The MDIO bus drivers for the UCC and gianfar ethernet controllers are essentially the same. There's no reason to duplicate that much code. Signed-off-by: Andy Fleming Signed-off-by: David S. Miller --- drivers/net/Kconfig | 9 + drivers/net/Makefile | 5 +- drivers/net/fsl_pq_mdio.c | 463 +++++++++++++++++++++++++++++++++ drivers/net/fsl_pq_mdio.h | 45 ++++ drivers/net/gianfar.c | 23 +- drivers/net/gianfar.h | 13 +- drivers/net/gianfar_mii.h | 54 ---- drivers/net/ucc_geth.c | 16 +- drivers/net/ucc_geth.h | 14 +- drivers/net/ucc_geth_ethtool.c | 1 - drivers/net/ucc_geth_mii.c | 295 --------------------- drivers/net/ucc_geth_mii.h | 101 ------- 12 files changed, 549 insertions(+), 490 deletions(-) create mode 100644 drivers/net/fsl_pq_mdio.c create mode 100644 drivers/net/fsl_pq_mdio.h delete mode 100644 drivers/net/gianfar_mii.h delete mode 100644 drivers/net/ucc_geth_mii.c delete mode 100644 drivers/net/ucc_geth_mii.h diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 49f4d50abc5..62bc0223a8e 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2272,9 +2272,17 @@ config GELIC_WIRELESS_OLD_PSK_INTERFACE If unsure, say N. +config FSL_PQ_MDIO + tristate "Freescale PQ MDIO" + depends on FSL_SOC + select PHYLIB + help + This driver supports the MDIO bus used by the gianfar and UCC drivers. + config GIANFAR tristate "Gianfar Ethernet" depends on FSL_SOC + select FSL_PQ_MDIO select PHYLIB select CRC32 help @@ -2284,6 +2292,7 @@ config GIANFAR config UCC_GETH tristate "Freescale QE Gigabit Ethernet" depends on QUICC_ENGINE + select FSL_PQ_MDIO select PHYLIB help This driver supports the Gigabit Ethernet mode of the QUICC Engine, diff --git a/drivers/net/Makefile b/drivers/net/Makefile index a3c5c002f22..ad87ba72cf1 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -24,11 +24,12 @@ obj-$(CONFIG_JME) += jme.o gianfar_driver-objs := gianfar.o \ gianfar_ethtool.o \ - gianfar_mii.o \ gianfar_sysfs.o obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o -ucc_geth_driver-objs := ucc_geth.o ucc_geth_mii.o ucc_geth_ethtool.o +ucc_geth_driver-objs := ucc_geth.o ucc_geth_ethtool.o + +obj-$(CONFIG_FSL_PQ_MDIO) += fsl_pq_mdio.o # # link order important here diff --git a/drivers/net/fsl_pq_mdio.c b/drivers/net/fsl_pq_mdio.c new file mode 100644 index 00000000000..c434a156d7a --- /dev/null +++ b/drivers/net/fsl_pq_mdio.c @@ -0,0 +1,463 @@ +/* + * Freescale PowerQUICC Ethernet Driver -- MIIM bus implementation + * Provides Bus interface for MIIM regs + * + * Author: Andy Fleming + * + * Copyright (c) 2002-2004,2008 Freescale Semiconductor, Inc. + * + * Based on gianfar_mii.c and ucc_geth_mii.c (Li Yang, Kim Phillips) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "gianfar.h" +#include "fsl_pq_mdio.h" + +/* + * Write value to the PHY at mii_id at register regnum, + * on the bus attached to the local interface, which may be different from the + * generic mdio bus (tied to a single interface), waiting until the write is + * done before returning. This is helpful in programming interfaces like + * the TBI which control interfaces like onchip SERDES and are always tied to + * the local mdio pins, which may not be the same as system mdio bus, used for + * controlling the external PHYs, for example. + */ +int fsl_pq_local_mdio_write(struct fsl_pq_mdio __iomem *regs, int mii_id, + int regnum, u16 value) +{ + /* Set the PHY address and the register address we want to write */ + out_be32(®s->miimadd, (mii_id << 8) | regnum); + + /* Write out the value we want */ + out_be32(®s->miimcon, value); + + /* Wait for the transaction to finish */ + while (in_be32(®s->miimind) & MIIMIND_BUSY) + cpu_relax(); + + return 0; +} + +/* + * Read the bus for PHY at addr mii_id, register regnum, and + * return the value. Clears miimcom first. All PHY operation + * done on the bus attached to the local interface, + * which may be different from the generic mdio bus + * This is helpful in programming interfaces like + * the TBI which, in turn, control interfaces like onchip SERDES + * and are always tied to the local mdio pins, which may not be the + * same as system mdio bus, used for controlling the external PHYs, for eg. + */ +int fsl_pq_local_mdio_read(struct fsl_pq_mdio __iomem *regs, + int mii_id, int regnum) +{ + u16 value; + + /* Set the PHY address and the register address we want to read */ + out_be32(®s->miimadd, (mii_id << 8) | regnum); + + /* Clear miimcom, and then initiate a read */ + out_be32(®s->miimcom, 0); + out_be32(®s->miimcom, MII_READ_COMMAND); + + /* Wait for the transaction to finish */ + while (in_be32(®s->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY)) + cpu_relax(); + + /* Grab the value of the register from miimstat */ + value = in_be32(®s->miimstat); + + return value; +} + +/* + * Write value to the PHY at mii_id at register regnum, + * on the bus, waiting until the write is done before returning. + */ +int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) +{ + struct fsl_pq_mdio __iomem *regs = (void __iomem *)bus->priv; + + /* Write to the local MII regs */ + return(fsl_pq_local_mdio_write(regs, mii_id, regnum, value)); +} + +/* + * Read the bus for PHY at addr mii_id, register regnum, and + * return the value. Clears miimcom first. + */ +int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum) +{ + struct fsl_pq_mdio __iomem *regs = (void __iomem *)bus->priv; + + /* Read the local MII regs */ + return(fsl_pq_local_mdio_read(regs, mii_id, regnum)); +} + +/* Reset the MIIM registers, and wait for the bus to free */ +static int fsl_pq_mdio_reset(struct mii_bus *bus) +{ + struct fsl_pq_mdio __iomem *regs = (void __iomem *)bus->priv; + unsigned int timeout = PHY_INIT_TIMEOUT; + + mutex_lock(&bus->mdio_lock); + + /* Reset the management interface */ + out_be32(®s->miimcfg, MIIMCFG_RESET); + + /* Setup the MII Mgmt clock speed */ + out_be32(®s->miimcfg, MIIMCFG_INIT_VALUE); + + /* Wait until the bus is free */ + while ((in_be32(®s->miimind) & MIIMIND_BUSY) && timeout--) + cpu_relax(); + + mutex_unlock(&bus->mdio_lock); + + if(timeout == 0) { + printk(KERN_ERR "%s: The MII Bus is stuck!\n", + bus->name); + return -EBUSY; + } + + return 0; +} + +/* Allocate an array which provides irq #s for each PHY on the given bus */ +static int *create_irq_map(struct device_node *np) +{ + int *irqs; + int i; + struct device_node *child = NULL; + + irqs = kcalloc(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL); + + if (!irqs) + return NULL; + + for (i = 0; i < PHY_MAX_ADDR; i++) + irqs[i] = PHY_POLL; + + while ((child = of_get_next_child(np, child)) != NULL) { + int irq = irq_of_parse_and_map(child, 0); + const u32 *id; + + if (irq == NO_IRQ) + continue; + + id = of_get_property(child, "reg", NULL); + + if (!id) + continue; + + if (*id < PHY_MAX_ADDR && *id >= 0) + irqs[*id] = irq; + else + printk(KERN_WARNING "%s: " + "%d is not a valid PHY address\n", + np->full_name, *id); + } + + return irqs; +} + +void fsl_pq_mdio_bus_name(char *name, struct device_node *np) +{ + const u32 *reg; + + reg = of_get_property(np, "reg", NULL); + + snprintf(name, MII_BUS_ID_SIZE, "%s@%x", np->name, reg ? *reg : 0); +} + +/* Scan the bus in reverse, looking for an empty spot */ +static int fsl_pq_mdio_find_free(struct mii_bus *new_bus) +{ + int i; + + for (i = PHY_MAX_ADDR; i > 0; i--) { + u32 phy_id; + + if (get_phy_id(new_bus, i, &phy_id)) + return -1; + + if (phy_id == 0xffffffff) + break; + } + + return i; +} + + +#ifdef CONFIG_GIANFAR +static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs) +{ + struct gfar __iomem *enet_regs; + + /* + * This is mildly evil, but so is our hardware for doing this. + * Also, we have to cast back to struct gfar because of + * definition weirdness done in gianfar.h. + */ + enet_regs = (struct gfar __iomem *) + ((char __iomem *)regs - offsetof(struct gfar, gfar_mii_regs)); + + return &enet_regs->tbipa; +} +#endif + + +#ifdef CONFIG_UCC_GETH +static int get_ucc_id_for_range(u64 start, u64 end, u32 *ucc_id) +{ + struct device_node *np = NULL; + int err = 0; + + for_each_compatible_node(np, NULL, "ucc_geth") { + struct resource tempres; + + err = of_address_to_resource(np, 0, &tempres); + if (err) + continue; + + /* if our mdio regs fall within this UCC regs range */ + if ((start >= tempres.start) && (end <= tempres.end)) { + /* Find the id of the UCC */ + const u32 *id; + + id = of_get_property(np, "cell-index", NULL); + if (!id) { + id = of_get_property(np, "device-id", NULL); + if (!id) + continue; + } + + *ucc_id = *id; + + return 0; + } + } + + if (err) + return err; + else + return -EINVAL; +} +#endif + + +static int fsl_pq_mdio_probe(struct of_device *ofdev, + const struct of_device_id *match) +{ + struct device_node *np = ofdev->node; + struct device_node *tbi; + struct fsl_pq_mdio __iomem *regs; + u32 __iomem *tbipa; + struct mii_bus *new_bus; + int tbiaddr = -1; + u64 addr, size; + int err = 0; + + new_bus = mdiobus_alloc(); + if (NULL == new_bus) + return -ENOMEM; + + new_bus->name = "Freescale PowerQUICC MII Bus", + new_bus->read = &fsl_pq_mdio_read, + new_bus->write = &fsl_pq_mdio_write, + new_bus->reset = &fsl_pq_mdio_reset, + fsl_pq_mdio_bus_name(new_bus->id, np); + + /* Set the PHY base address */ + addr = of_translate_address(np, of_get_address(np, 0, &size, NULL)); + regs = ioremap(addr, size); + + if (NULL == regs) { + err = -ENOMEM; + goto err_free_bus; + } + + new_bus->priv = (void __force *)regs; + + new_bus->irq = create_irq_map(np); + + if (NULL == new_bus->irq) { + err = -ENOMEM; + goto err_unmap_regs; + } + + new_bus->parent = &ofdev->dev; + dev_set_drvdata(&ofdev->dev, new_bus); + + if (of_device_is_compatible(np, "fsl,gianfar-mdio") || + of_device_is_compatible(np, "gianfar")) { +#ifdef CONFIG_GIANFAR + tbipa = get_gfar_tbipa(regs); +#else + err = -ENODEV; + goto err_free_irqs; +#endif + } else if (of_device_is_compatible(np, "fsl,ucc-mdio") || + of_device_is_compatible(np, "ucc_geth_phy")) { +#ifdef CONFIG_UCC_GETH + u32 id; + + tbipa = ®s->utbipar; + + if ((err = get_ucc_id_for_range(addr, addr + size, &id))) + goto err_free_irqs; + + ucc_set_qe_mux_mii_mng(id - 1); +#else + err = -ENODEV; + goto err_free_irqs; +#endif + } else { + err = -ENODEV; + goto err_free_irqs; + } + + for_each_child_of_node(np, tbi) { + if (!strncmp(tbi->type, "tbi-phy", 8)) + break; + } + + if (tbi) { + const u32 *prop = of_get_property(tbi, "reg", NULL); + + if (prop) + tbiaddr = *prop; + } + + if (tbiaddr == -1) { + out_be32(tbipa, 0); + + tbiaddr = fsl_pq_mdio_find_free(new_bus); + } + + /* + * We define TBIPA at 0 to be illegal, opting to fail for boards that + * have PHYs at 1-31, rather than change tbipa and rescan. + */ + if (tbiaddr == 0) { + err = -EBUSY; + + goto err_free_irqs; + } + + out_be32(tbipa, tbiaddr); + + /* + * The TBIPHY-only buses will find PHYs at every address, + * so we mask them all but the TBI + */ + if (!of_device_is_compatible(np, "fsl,gianfar-mdio")) + new_bus->phy_mask = ~(1 << tbiaddr); + + err = mdiobus_register(new_bus); + + if (err) { + printk (KERN_ERR "%s: Cannot register as MDIO bus\n", + new_bus->name); + goto err_free_irqs; + } + + return 0; + +err_free_irqs: + kfree(new_bus->irq); +err_unmap_regs: + iounmap(regs); +err_free_bus: + kfree(new_bus); + + return err; +} + + +static int fsl_pq_mdio_remove(struct of_device *ofdev) +{ + struct device *device = &ofdev->dev; + struct mii_bus *bus = dev_get_drvdata(device); + + mdiobus_unregister(bus); + + dev_set_drvdata(device, NULL); + + iounmap((void __iomem *)bus->priv); + bus->priv = NULL; + mdiobus_free(bus); + + return 0; +} + +static struct of_device_id fsl_pq_mdio_match[] = { + { + .type = "mdio", + .compatible = "ucc_geth_phy", + }, + { + .type = "mdio", + .compatible = "gianfar", + }, + { + .compatible = "fsl,ucc-mdio", + }, + { + .compatible = "fsl,gianfar-tbi", + }, + { + .compatible = "fsl,gianfar-mdio", + }, + {}, +}; + +static struct of_platform_driver fsl_pq_mdio_driver = { + .name = "fsl-pq_mdio", + .probe = fsl_pq_mdio_probe, + .remove = fsl_pq_mdio_remove, + .match_table = fsl_pq_mdio_match, +}; + +int __init fsl_pq_mdio_init(void) +{ + return of_register_platform_driver(&fsl_pq_mdio_driver); +} + +void fsl_pq_mdio_exit(void) +{ + of_unregister_platform_driver(&fsl_pq_mdio_driver); +} +subsys_initcall_sync(fsl_pq_mdio_init); +module_exit(fsl_pq_mdio_exit); diff --git a/drivers/net/fsl_pq_mdio.h b/drivers/net/fsl_pq_mdio.h new file mode 100644 index 00000000000..36dad527410 --- /dev/null +++ b/drivers/net/fsl_pq_mdio.h @@ -0,0 +1,45 @@ +/* + * Freescale PowerQUICC MDIO Driver -- MII Management Bus Implementation + * Driver for the MDIO bus controller on Freescale PowerQUICC processors + * + * Author: Andy Fleming + * + * Copyright (c) 2002-2004,2008 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ +#ifndef __FSL_PQ_MDIO_H +#define __FSL_PQ_MDIO_H + +#define MIIMIND_BUSY 0x00000001 +#define MIIMIND_NOTVALID 0x00000004 +#define MIIMCFG_INIT_VALUE 0x00000007 +#define MIIMCFG_RESET 0x80000000 + +#define MII_READ_COMMAND 0x00000001 + +struct fsl_pq_mdio { + u32 miimcfg; /* MII management configuration reg */ + u32 miimcom; /* MII management command reg */ + u32 miimadd; /* MII management address reg */ + u32 miimcon; /* MII management control reg */ + u32 miimstat; /* MII management status reg */ + u32 miimind; /* MII management indication reg */ + u8 reserved[28]; /* Space holder */ + u32 utbipar; /* TBI phy address reg (only on UCC) */ +} __attribute__ ((packed)); + + +int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum); +int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value); +int fsl_pq_local_mdio_write(struct fsl_pq_mdio __iomem *regs, int mii_id, + int regnum, u16 value); +int fsl_pq_local_mdio_read(struct fsl_pq_mdio __iomem *regs, int mii_id, int regnum); +int __init fsl_pq_mdio_init(void); +void fsl_pq_mdio_exit(void); +void fsl_pq_mdio_bus_name(char *name, struct device_node *np); +#endif /* FSL_PQ_MDIO_H */ diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index eb8302c5ba8..bd21b6d5f13 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -93,7 +93,7 @@ #include #include "gianfar.h" -#include "gianfar_mii.h" +#include "fsl_pq_mdio.h" #define TX_TIMEOUT (1*HZ) #undef BRIEF_GFAR_ERRORS @@ -253,7 +253,7 @@ static int gfar_of_init(struct net_device *dev) of_node_put(phy); of_node_put(mdio); - gfar_mdio_bus_name(bus_name, mdio); + fsl_pq_mdio_bus_name(bus_name, mdio); snprintf(priv->phy_bus_id, sizeof(priv->phy_bus_id), "%s:%02x", bus_name, *id); } @@ -420,7 +420,7 @@ static int gfar_probe(struct of_device *ofdev, priv->hash_width = 8; priv->hash_regs[0] = &priv->regs->gaddr0; - priv->hash_regs[1] = &priv->regs->gaddr1; + priv->hash_regs[1] = &priv->regs->gaddr1; priv->hash_regs[2] = &priv->regs->gaddr2; priv->hash_regs[3] = &priv->regs->gaddr3; priv->hash_regs[4] = &priv->regs->gaddr4; @@ -836,7 +836,7 @@ void stop_gfar(struct net_device *dev) free_irq(priv->interruptTransmit, dev); free_irq(priv->interruptReceive, dev); } else { - free_irq(priv->interruptTransmit, dev); + free_irq(priv->interruptTransmit, dev); } free_skb_resources(priv); @@ -1829,6 +1829,8 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) skb_put(skb, pkt_len); dev->stats.rx_bytes += pkt_len; + if (in_irq() || irqs_disabled()) + printk("Interrupt problem!\n"); gfar_process_frame(dev, skb, amount_pull); } else { @@ -2302,23 +2304,12 @@ static struct of_platform_driver gfar_driver = { static int __init gfar_init(void) { - int err = gfar_mdio_init(); - - if (err) - return err; - - err = of_register_platform_driver(&gfar_driver); - - if (err) - gfar_mdio_exit(); - - return err; + return of_register_platform_driver(&gfar_driver); } static void __exit gfar_exit(void) { of_unregister_platform_driver(&gfar_driver); - gfar_mdio_exit(); } module_init(gfar_init); diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 7820720ceee..3cb901b2e24 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -46,7 +46,6 @@ #include #include #include -#include "gianfar_mii.h" /* The maximum number of packets to be handled in one call of gfar_poll */ #define GFAR_DEV_WEIGHT 64 @@ -126,9 +125,12 @@ extern const char gfar_driver_version[]; #define DEFAULT_RX_COALESCE 0 #define DEFAULT_RXCOUNT 0 -#define MIIMCFG_INIT_VALUE 0x00000007 -#define MIIMCFG_RESET 0x80000000 -#define MIIMIND_BUSY 0x00000001 +#define GFAR_SUPPORTED (SUPPORTED_10baseT_Half \ + | SUPPORTED_10baseT_Full \ + | SUPPORTED_100baseT_Half \ + | SUPPORTED_100baseT_Full \ + | SUPPORTED_Autoneg \ + | SUPPORTED_MII) /* TBI register addresses */ #define MII_TBICON 0x11 @@ -826,9 +828,6 @@ extern void gfar_halt(struct net_device *dev); extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev, int enable, u32 regnum, u32 read); void gfar_init_sysfs(struct net_device *dev); -int gfar_local_mdio_write(struct gfar_mii __iomem *regs, int mii_id, - int regnum, u16 value); -int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum); extern const struct ethtool_ops gfar_ethtool_ops; diff --git a/drivers/net/gianfar_mii.h b/drivers/net/gianfar_mii.h deleted file mode 100644 index 65c242cd468..00000000000 --- a/drivers/net/gianfar_mii.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * drivers/net/gianfar_mii.h - * - * Gianfar Ethernet Driver -- MII Management Bus Implementation - * Driver for the MDIO bus controller in the Gianfar register space - * - * Author: Andy Fleming - * Maintainer: Kumar Gala - * - * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ -#ifndef __GIANFAR_MII_H -#define __GIANFAR_MII_H - -struct gfar_private; /* forward ref */ - -#define MIIMIND_BUSY 0x00000001 -#define MIIMIND_NOTVALID 0x00000004 - -#define MII_READ_COMMAND 0x00000001 - -#define GFAR_SUPPORTED (SUPPORTED_10baseT_Half \ - | SUPPORTED_10baseT_Full \ - | SUPPORTED_100baseT_Half \ - | SUPPORTED_100baseT_Full \ - | SUPPORTED_Autoneg \ - | SUPPORTED_MII) - -struct gfar_mii { - u32 miimcfg; /* 0x.520 - MII Management Config Register */ - u32 miimcom; /* 0x.524 - MII Management Command Register */ - u32 miimadd; /* 0x.528 - MII Management Address Register */ - u32 miimcon; /* 0x.52c - MII Management Control Register */ - u32 miimstat; /* 0x.530 - MII Management Status Register */ - u32 miimind; /* 0x.534 - MII Management Indicator Register */ -}; - -int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum); -int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value); -int gfar_local_mdio_write(struct gfar_mii __iomem *regs, int mii_id, - int regnum, u16 value); -int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum); -struct mii_bus *gfar_get_miibus(const struct gfar_private *priv); -int __init gfar_mdio_init(void); -void gfar_mdio_exit(void); - -void gfar_mdio_bus_name(char *name, struct device_node *np); -#endif /* GIANFAR_PHY_H */ diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 4a8d5747204..1c095c63f98 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -39,7 +39,7 @@ #include #include "ucc_geth.h" -#include "ucc_geth_mii.h" +#include "fsl_pq_mdio.h" #undef DEBUG @@ -1557,7 +1557,7 @@ static int init_phy(struct net_device *dev) of_node_put(phy); of_node_put(mdio); - uec_mdio_bus_name(bus_name, mdio); + fsl_pq_mdio_bus_name(bus_name, mdio); snprintf(phy_id, sizeof(phy_id), "%s:%02x", bus_name, *id); @@ -3657,7 +3657,8 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma if (err) return -1; - snprintf(ug_info->mdio_bus, MII_BUS_ID_SIZE, "%x", res.start); + snprintf(ug_info->mdio_bus, MII_BUS_ID_SIZE, "%x", + res.start&0xfffff); } /* get the phy interface type, or default to MII */ @@ -3803,11 +3804,6 @@ static int __init ucc_geth_init(void) { int i, ret; - ret = uec_mdio_init(); - - if (ret) - return ret; - if (netif_msg_drv(&debug)) printk(KERN_INFO "ucc_geth: " DRV_DESC "\n"); for (i = 0; i < 8; i++) @@ -3816,16 +3812,12 @@ static int __init ucc_geth_init(void) ret = of_register_platform_driver(&ucc_geth_driver); - if (ret) - uec_mdio_exit(); - return ret; } static void __exit ucc_geth_exit(void) { of_unregister_platform_driver(&ucc_geth_driver); - uec_mdio_exit(); } module_init(ucc_geth_init); diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h index 16cbe42ba43..66d18971fa0 100644 --- a/drivers/net/ucc_geth.h +++ b/drivers/net/ucc_geth.h @@ -28,8 +28,6 @@ #include #include -#include "ucc_geth_mii.h" - #define DRV_DESC "QE UCC Gigabit Ethernet Controller" #define DRV_NAME "ucc_geth" #define DRV_VERSION "1.1" @@ -184,6 +182,18 @@ struct ucc_geth { #define UCCE_RX_EVENTS (UCCE_RXF | UCC_GETH_UCCE_BSY) #define UCCE_TX_EVENTS (UCCE_TXB | UCC_GETH_UCCE_TXE) +/* TBI defines */ +#define ENET_TBI_MII_CR 0x00 /* Control */ +#define ENET_TBI_MII_SR 0x01 /* Status */ +#define ENET_TBI_MII_ANA 0x04 /* AN advertisement */ +#define ENET_TBI_MII_ANLPBPA 0x05 /* AN link partner base page ability */ +#define ENET_TBI_MII_ANEX 0x06 /* AN expansion */ +#define ENET_TBI_MII_ANNPT 0x07 /* AN next page transmit */ +#define ENET_TBI_MII_ANLPANP 0x08 /* AN link partner ability next page */ +#define ENET_TBI_MII_EXST 0x0F /* Extended status */ +#define ENET_TBI_MII_JD 0x10 /* Jitter diagnostics */ +#define ENET_TBI_MII_TBICON 0x11 /* TBI control */ + /* UCC GETH MACCFG1 (MAC Configuration 1 Register) */ #define MACCFG1_FLOW_RX 0x00000020 /* Flow Control Rx */ diff --git a/drivers/net/ucc_geth_ethtool.c b/drivers/net/ucc_geth_ethtool.c index 68a7f541413..a755bea559b 100644 --- a/drivers/net/ucc_geth_ethtool.c +++ b/drivers/net/ucc_geth_ethtool.c @@ -39,7 +39,6 @@ #include #include "ucc_geth.h" -#include "ucc_geth_mii.h" static char hw_stat_gstrings[][ETH_GSTRING_LEN] = { "tx-64-frames", diff --git a/drivers/net/ucc_geth_mii.c b/drivers/net/ucc_geth_mii.c deleted file mode 100644 index 54635911305..00000000000 --- a/drivers/net/ucc_geth_mii.c +++ /dev/null @@ -1,295 +0,0 @@ -/* - * drivers/net/ucc_geth_mii.c - * - * QE UCC Gigabit Ethernet Driver -- MII Management Bus Implementation - * Provides Bus interface for MII Management regs in the UCC register space - * - * Copyright (C) 2007 Freescale Semiconductor, Inc. - * - * Authors: Li Yang - * Kim Phillips - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "ucc_geth_mii.h" -#include "ucc_geth.h" - -#define DEBUG -#ifdef DEBUG -#define vdbg(format, arg...) printk(KERN_DEBUG , format "\n" , ## arg) -#else -#define vdbg(format, arg...) do {} while(0) -#endif - -#define MII_DRV_DESC "QE UCC Ethernet Controller MII Bus" -#define MII_DRV_NAME "fsl-uec_mdio" - -/* Write value to the PHY for this device to the register at regnum, */ -/* waiting until the write is done before it returns. All PHY */ -/* configuration has to be done through the master UEC MIIM regs */ -int uec_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) -{ - struct ucc_mii_mng __iomem *regs = (void __iomem *)bus->priv; - - /* Setting up the MII Mangement Address Register */ - out_be32(®s->miimadd, - (mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | regnum); - - /* Setting up the MII Mangement Control Register with the value */ - out_be32(®s->miimcon, value); - - /* Wait till MII management write is complete */ - while ((in_be32(®s->miimind)) & MIIMIND_BUSY) - cpu_relax(); - - return 0; -} - -/* Reads from register regnum in the PHY for device dev, */ -/* returning the value. Clears miimcom first. All PHY */ -/* configuration has to be done through the TSEC1 MIIM regs */ -int uec_mdio_read(struct mii_bus *bus, int mii_id, int regnum) -{ - struct ucc_mii_mng __iomem *regs = (void __iomem *)bus->priv; - u16 value; - - /* Setting up the MII Mangement Address Register */ - out_be32(®s->miimadd, - (mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | regnum); - - /* Clear miimcom, perform an MII management read cycle */ - out_be32(®s->miimcom, 0); - out_be32(®s->miimcom, MIIMCOM_READ_CYCLE); - - /* Wait till MII management write is complete */ - while ((in_be32(®s->miimind)) & (MIIMIND_BUSY | MIIMIND_NOT_VALID)) - cpu_relax(); - - /* Read MII management status */ - value = in_be32(®s->miimstat); - - return value; -} - -/* Reset the MIIM registers, and wait for the bus to free */ -static int uec_mdio_reset(struct mii_bus *bus) -{ - struct ucc_mii_mng __iomem *regs = (void __iomem *)bus->priv; - unsigned int timeout = PHY_INIT_TIMEOUT; - - mutex_lock(&bus->mdio_lock); - - /* Reset the management interface */ - out_be32(®s->miimcfg, MIIMCFG_RESET_MANAGEMENT); - - /* Setup the MII Mgmt clock speed */ - out_be32(®s->miimcfg, MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_112); - - /* Wait until the bus is free */ - while ((in_be32(®s->miimind) & MIIMIND_BUSY) && timeout--) - cpu_relax(); - - mutex_unlock(&bus->mdio_lock); - - if (timeout <= 0) { - printk(KERN_ERR "%s: The MII Bus is stuck!\n", bus->name); - return -EBUSY; - } - - return 0; -} - -static int uec_mdio_probe(struct of_device *ofdev, const struct of_device_id *match) -{ - struct device *device = &ofdev->dev; - struct device_node *np = ofdev->node, *tempnp = NULL; - struct device_node *child = NULL; - struct ucc_mii_mng __iomem *regs; - struct mii_bus *new_bus; - struct resource res; - int k, err = 0; - - new_bus = mdiobus_alloc(); - if (NULL == new_bus) - return -ENOMEM; - - new_bus->name = "UCC Ethernet Controller MII Bus"; - new_bus->read = &uec_mdio_read; - new_bus->write = &uec_mdio_write; - new_bus->reset = &uec_mdio_reset; - - memset(&res, 0, sizeof(res)); - - err = of_address_to_resource(np, 0, &res); - if (err) - goto reg_map_fail; - - uec_mdio_bus_name(new_bus->id, np); - - new_bus->irq = kmalloc(32 * sizeof(int), GFP_KERNEL); - - if (NULL == new_bus->irq) { - err = -ENOMEM; - goto reg_map_fail; - } - - for (k = 0; k < 32; k++) - new_bus->irq[k] = PHY_POLL; - - while ((child = of_get_next_child(np, child)) != NULL) { - int irq = irq_of_parse_and_map(child, 0); - if (irq != NO_IRQ) { - const u32 *id = of_get_property(child, "reg", NULL); - new_bus->irq[*id] = irq; - } - } - - /* Set the base address */ - regs = ioremap(res.start, sizeof(struct ucc_mii_mng)); - - if (NULL == regs) { - err = -ENOMEM; - goto ioremap_fail; - } - - new_bus->priv = (void __force *)regs; - - new_bus->parent = device; - dev_set_drvdata(device, new_bus); - - /* Read MII management master from device tree */ - while ((tempnp = of_find_compatible_node(tempnp, "network", "ucc_geth")) - != NULL) { - struct resource tempres; - - err = of_address_to_resource(tempnp, 0, &tempres); - if (err) - goto bus_register_fail; - - /* if our mdio regs fall within this UCC regs range */ - if ((res.start >= tempres.start) && - (res.end <= tempres.end)) { - /* set this UCC to be the MII master */ - const u32 *id; - - id = of_get_property(tempnp, "cell-index", NULL); - if (!id) { - id = of_get_property(tempnp, "device-id", NULL); - if (!id) - goto bus_register_fail; - } - - ucc_set_qe_mux_mii_mng(*id - 1); - - /* assign the TBI an address which won't - * conflict with the PHYs */ - out_be32(®s->utbipar, UTBIPAR_INIT_TBIPA); - break; - } - } - - err = mdiobus_register(new_bus); - if (0 != err) { - printk(KERN_ERR "%s: Cannot register as MDIO bus\n", - new_bus->name); - goto bus_register_fail; - } - - return 0; - -bus_register_fail: - iounmap(regs); -ioremap_fail: - kfree(new_bus->irq); -reg_map_fail: - mdiobus_free(new_bus); - - return err; -} - -static int uec_mdio_remove(struct of_device *ofdev) -{ - struct device *device = &ofdev->dev; - struct mii_bus *bus = dev_get_drvdata(device); - - mdiobus_unregister(bus); - - dev_set_drvdata(device, NULL); - - iounmap((void __iomem *)bus->priv); - bus->priv = NULL; - mdiobus_free(bus); - - return 0; -} - -static struct of_device_id uec_mdio_match[] = { - { - .type = "mdio", - .compatible = "ucc_geth_phy", - }, - { - .compatible = "fsl,ucc-mdio", - }, - {}, -}; - -static struct of_platform_driver uec_mdio_driver = { - .name = MII_DRV_NAME, - .probe = uec_mdio_probe, - .remove = uec_mdio_remove, - .match_table = uec_mdio_match, -}; - -int __init uec_mdio_init(void) -{ - return of_register_platform_driver(&uec_mdio_driver); -} - -/* called from __init ucc_geth_init, therefore can not be __exit */ -void uec_mdio_exit(void) -{ - of_unregister_platform_driver(&uec_mdio_driver); -} - -void uec_mdio_bus_name(char *name, struct device_node *np) -{ - const u32 *reg; - - reg = of_get_property(np, "reg", NULL); - - snprintf(name, MII_BUS_ID_SIZE, "%s@%x", np->name, reg ? *reg : 0); -} - diff --git a/drivers/net/ucc_geth_mii.h b/drivers/net/ucc_geth_mii.h deleted file mode 100644 index 840cf80235b..00000000000 --- a/drivers/net/ucc_geth_mii.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * drivers/net/ucc_geth_mii.h - * - * QE UCC Gigabit Ethernet Driver -- MII Management Bus Implementation - * Provides Bus interface for MII Management regs in the UCC register space - * - * Copyright (C) 2007 Freescale Semiconductor, Inc. - * - * Authors: Li Yang - * Kim Phillips - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ -#ifndef __UEC_MII_H -#define __UEC_MII_H - -/* UCC GETH MIIMCFG (MII Management Configuration Register) */ -#define MIIMCFG_RESET_MANAGEMENT 0x80000000 /* Reset - management */ -#define MIIMCFG_NO_PREAMBLE 0x00000010 /* Preamble - suppress */ -#define MIIMCFG_CLOCK_DIVIDE_SHIFT (31 - 31) /* clock divide - << shift */ -#define MIIMCFG_CLOCK_DIVIDE_MAX 0xf /* max clock divide */ -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_2 0x00000000 -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_4 0x00000001 -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_6 0x00000002 -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_8 0x00000003 -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_10 0x00000004 -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_14 0x00000005 -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_16 0x00000008 -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_20 0x00000006 -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_28 0x00000007 -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_32 0x00000009 -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_48 0x0000000a -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_64 0x0000000b -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_80 0x0000000c -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_112 0x0000000d -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_160 0x0000000e -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_224 0x0000000f - -/* UCC GETH MIIMCOM (MII Management Command Register) */ -#define MIIMCOM_SCAN_CYCLE 0x00000002 /* Scan cycle */ -#define MIIMCOM_READ_CYCLE 0x00000001 /* Read cycle */ - -/* UCC GETH MIIMADD (MII Management Address Register) */ -#define MIIMADD_PHY_ADDRESS_SHIFT (31 - 23) /* PHY Address - << shift */ -#define MIIMADD_PHY_REGISTER_SHIFT (31 - 31) /* PHY Register - << shift */ - -/* UCC GETH MIIMCON (MII Management Control Register) */ -#define MIIMCON_PHY_CONTROL_SHIFT (31 - 31) /* PHY Control - << shift */ -#define MIIMCON_PHY_STATUS_SHIFT (31 - 31) /* PHY Status - << shift */ - -/* UCC GETH MIIMIND (MII Management Indicator Register) */ -#define MIIMIND_NOT_VALID 0x00000004 /* Not valid */ -#define MIIMIND_SCAN 0x00000002 /* Scan in - progress */ -#define MIIMIND_BUSY 0x00000001 - -/* Initial TBI Physical Address */ -#define UTBIPAR_INIT_TBIPA 0x1f - -struct ucc_mii_mng { - u32 miimcfg; /* MII management configuration reg */ - u32 miimcom; /* MII management command reg */ - u32 miimadd; /* MII management address reg */ - u32 miimcon; /* MII management control reg */ - u32 miimstat; /* MII management status reg */ - u32 miimind; /* MII management indication reg */ - u8 notcare[28]; /* Space holder */ - u32 utbipar; /* TBI phy address reg */ -} __attribute__ ((packed)); - -/* TBI / MII Set Register */ -enum enet_tbi_mii_reg { - ENET_TBI_MII_CR = 0x00, /* Control */ - ENET_TBI_MII_SR = 0x01, /* Status */ - ENET_TBI_MII_ANA = 0x04, /* AN advertisement */ - ENET_TBI_MII_ANLPBPA = 0x05, /* AN link partner base page ability */ - ENET_TBI_MII_ANEX = 0x06, /* AN expansion */ - ENET_TBI_MII_ANNPT = 0x07, /* AN next page transmit */ - ENET_TBI_MII_ANLPANP = 0x08, /* AN link partner ability next page */ - ENET_TBI_MII_EXST = 0x0F, /* Extended status */ - ENET_TBI_MII_JD = 0x10, /* Jitter diagnostics */ - ENET_TBI_MII_TBICON = 0x11 /* TBI control */ -}; - -int uec_mdio_read(struct mii_bus *bus, int mii_id, int regnum); -int uec_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value); -int __init uec_mdio_init(void); -void uec_mdio_exit(void); -void uec_mdio_bus_name(char *name, struct device_node *np); -#endif /* __UEC_MII_H */ -- GitLab From 0fd56bb5be6455d0d42241e65aed057244665e5e Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Wed, 4 Feb 2009 16:43:16 -0800 Subject: [PATCH 1167/4982] gianfar: Add support for skb recycling Signed-off-by: Andy Fleming Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 23 +++++++++++++++++++---- drivers/net/gianfar.h | 2 ++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index bd21b6d5f13..33de25602b3 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -1181,6 +1181,8 @@ static int gfar_enet_open(struct net_device *dev) napi_enable(&priv->napi); + skb_queue_head_init(&priv->rx_recycle); + /* Initialize a bunch of registers */ init_registers(dev); @@ -1399,6 +1401,7 @@ static int gfar_close(struct net_device *dev) napi_disable(&priv->napi); + skb_queue_purge(&priv->rx_recycle); cancel_work_sync(&priv->reset_task); stop_gfar(dev); @@ -1595,7 +1598,17 @@ static int gfar_clean_tx_ring(struct net_device *dev) bdp = next_txbd(bdp, base, tx_ring_size); } - dev_kfree_skb_any(skb); + /* + * If there's room in the queue (limit it to rx_buffer_size) + * we add this skb back into the pool, if it's the right size + */ + if (skb_queue_len(&priv->rx_recycle) < priv->rx_ring_size && + skb_recycle_check(skb, priv->rx_buffer_size + + RXBUF_ALIGNMENT)) + __skb_queue_head(&priv->rx_recycle, skb); + else + dev_kfree_skb_any(skb); + priv->tx_skbuff[skb_dirtytx] = NULL; skb_dirtytx = (skb_dirtytx + 1) & @@ -1668,8 +1681,10 @@ struct sk_buff * gfar_new_skb(struct net_device *dev) struct gfar_private *priv = netdev_priv(dev); struct sk_buff *skb = NULL; - /* We have to allocate the skb, so keep trying till we succeed */ - skb = netdev_alloc_skb(dev, priv->rx_buffer_size + RXBUF_ALIGNMENT); + skb = __skb_dequeue(&priv->rx_recycle); + if (!skb) + skb = netdev_alloc_skb(dev, + priv->rx_buffer_size + RXBUF_ALIGNMENT); if (!skb) return NULL; @@ -1817,7 +1832,7 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) if (unlikely(!newskb)) newskb = skb; else if (skb) - dev_kfree_skb_any(skb); + __skb_queue_head(&priv->rx_recycle, skb); } else { /* Increment the number of packets */ dev->stats.rx_packets++; diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 3cb901b2e24..811855bc423 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -758,6 +758,8 @@ struct gfar_private { unsigned int rx_stash_size; unsigned int rx_stash_index; + struct sk_buff_head rx_recycle; + struct vlan_group *vlgrp; /* Unprotected fields */ -- GitLab From 4d7902f22b0804730b80f7a4147f676430248a3a Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Wed, 4 Feb 2009 16:43:44 -0800 Subject: [PATCH 1168/4982] gianfar: Fix stashing support Stashing is only supported on the 85xx (e500-based) SoCs. The 83xx and 86xx chips don't have a proper cache for this. U-Boot has been updated to add stashing properties to the device tree nodes of gianfar devices on 85xx. So now we modify Linux to keep stashing off unless those properties are there. Signed-off-by: Andy Fleming Signed-off-by: David S. Miller --- .../powerpc/dts-bindings/fsl/tsec.txt | 6 +++++ drivers/net/gianfar.c | 23 +++++++++++++++++++ drivers/net/gianfar_sysfs.c | 12 +++++++--- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/Documentation/powerpc/dts-bindings/fsl/tsec.txt b/Documentation/powerpc/dts-bindings/fsl/tsec.txt index 7fa4b27574b..edb7ae19e86 100644 --- a/Documentation/powerpc/dts-bindings/fsl/tsec.txt +++ b/Documentation/powerpc/dts-bindings/fsl/tsec.txt @@ -56,6 +56,12 @@ Properties: hardware. - fsl,magic-packet : If present, indicates that the hardware supports waking up via magic packet. + - bd-stash : If present, indicates that the hardware supports stashing + buffer descriptors in the L2. + - rx-stash-len : Denotes the number of bytes of a received buffer to stash + in the L2. + - rx-stash-idx : Denotes the index of the first byte from the received + buffer to stash in the L2. Example: ethernet@24000 { diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 33de25602b3..dadd08cd801 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -164,6 +164,9 @@ static int gfar_of_init(struct net_device *dev) struct gfar_private *priv = netdev_priv(dev); struct device_node *np = priv->node; char bus_name[MII_BUS_ID_SIZE]; + const u32 *stash; + const u32 *stash_len; + const u32 *stash_idx; if (!np || !of_device_is_available(np)) return -ENODEV; @@ -193,6 +196,26 @@ static int gfar_of_init(struct net_device *dev) } } + stash = of_get_property(np, "bd-stash", NULL); + + if(stash) { + priv->device_flags |= FSL_GIANFAR_DEV_HAS_BD_STASHING; + priv->bd_stash_en = 1; + } + + stash_len = of_get_property(np, "rx-stash-len", NULL); + + if (stash_len) + priv->rx_stash_size = *stash_len; + + stash_idx = of_get_property(np, "rx-stash-idx", NULL); + + if (stash_idx) + priv->rx_stash_index = *stash_idx; + + if (stash_len || stash_idx) + priv->device_flags |= FSL_GIANFAR_DEV_HAS_BUF_STASHING; + mac_addr = of_get_mac_address(np); if (mac_addr) memcpy(dev->dev_addr, mac_addr, MAC_ADDR_LEN); diff --git a/drivers/net/gianfar_sysfs.c b/drivers/net/gianfar_sysfs.c index 74e0b4d4258..dd26da74f27 100644 --- a/drivers/net/gianfar_sysfs.c +++ b/drivers/net/gianfar_sysfs.c @@ -53,6 +53,9 @@ static ssize_t gfar_set_bd_stash(struct device *dev, u32 temp; unsigned long flags; + if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BD_STASHING)) + return count; + /* Find out the new setting */ if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1)) new_setting = 1; @@ -100,6 +103,9 @@ static ssize_t gfar_set_rx_stash_size(struct device *dev, u32 temp; unsigned long flags; + if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING)) + return count; + spin_lock_irqsave(&priv->rxlock, flags); if (length > priv->rx_buffer_size) goto out; @@ -152,6 +158,9 @@ static ssize_t gfar_set_rx_stash_index(struct device *dev, u32 temp; unsigned long flags; + if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING)) + return count; + spin_lock_irqsave(&priv->rxlock, flags); if (index > priv->rx_stash_size) goto out; @@ -294,12 +303,9 @@ void gfar_init_sysfs(struct net_device *dev) int rc; /* Initialize the default values */ - priv->rx_stash_size = DEFAULT_STASH_LENGTH; - priv->rx_stash_index = DEFAULT_STASH_INDEX; priv->fifo_threshold = DEFAULT_FIFO_TX_THR; priv->fifo_starve = DEFAULT_FIFO_TX_STARVE; priv->fifo_starve_off = DEFAULT_FIFO_TX_STARVE_OFF; - priv->bd_stash_en = DEFAULT_BD_STASH; /* Create our sysfs files */ rc = device_create_file(&dev->dev, &dev_attr_bd_stash); -- GitLab From 1f4f931501e9270c156d05ee76b7b872de486304 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 2 Feb 2009 13:58:06 -0800 Subject: [PATCH 1169/4982] xen: fix 32-bit build resulting from mmu move Moving the mmu code from enlighten.c to mmu.c inadvertently broke the 32-bit build. Fix it. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: H. Peter Anvin --- arch/x86/xen/mmu.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 5e41f7fc6cf..d2e8ed1aff3 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1396,6 +1396,43 @@ static void xen_pgd_free(struct mm_struct *mm, pgd_t *pgd) #endif } +#ifdef CONFIG_HIGHPTE +static void *xen_kmap_atomic_pte(struct page *page, enum km_type type) +{ + pgprot_t prot = PAGE_KERNEL; + + if (PagePinned(page)) + prot = PAGE_KERNEL_RO; + + if (0 && PageHighMem(page)) + printk("mapping highpte %lx type %d prot %s\n", + page_to_pfn(page), type, + (unsigned long)pgprot_val(prot) & _PAGE_RW ? "WRITE" : "READ"); + + return kmap_atomic_prot(page, type, prot); +} +#endif + +#ifdef CONFIG_X86_32 +static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte) +{ + /* If there's an existing pte, then don't allow _PAGE_RW to be set */ + if (pte_val_ma(*ptep) & _PAGE_PRESENT) + pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) & + pte_val_ma(pte)); + + return pte; +} + +/* Init-time set_pte while constructing initial pagetables, which + doesn't allow RO pagetable pages to be remapped RW */ +static __init void xen_set_pte_init(pte_t *ptep, pte_t pte) +{ + pte = mask_rw_pte(ptep, pte); + + xen_set_pte(ptep, pte); +} +#endif /* Early in boot, while setting up the initial pagetable, assume everything is pinned. */ -- GitLab From 9a279bcbe347496799711155ed41a89bc40f79c5 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 4 Feb 2009 16:55:27 -0800 Subject: [PATCH 1170/4982] net: Partially allow skb destructors to be used on receive path As it currently stands, skb destructors are forbidden on the receive path because the protocol end-points will overwrite any existing destructor with their own. This is the reason why we have to call skb_orphan in the loopback driver before we reinject the packet back into the stack, thus creating a period during which loopback traffic isn't charged to any socket. With virtualisation, we have a similar problem in that traffic is reinjected into the stack without being associated with any socket entity, thus providing no natural congestion push-back for those poor folks still stuck with UDP. Now had we been consistent in telling them that UDP simply has no congestion feedback, I could just fob them off. Unfortunately, we appear to have gone to some length in catering for this on the standard UDP path, with skb/socket accounting so that has created a very unhealthy dependency. Alas habits are difficult to break out of, so we may just have to allow skb destructors on the receive path. It turns out that making skb destructors useable on the receive path isn't as easy as it seems. For instance, simply adding skb_orphan to skb_set_owner_r isn't enough. This is because we assume all over the IP stack that skb->sk is an IP socket if present. The new transparent proxy code goes one step further and assumes that skb->sk is the receiving socket if present. Now all of this can be dealt with by adding simple checks such as only treating skb->sk as an IP socket if skb->sk->sk_family matches. However, it turns out that for bridging at least we don't need to do all of this work. This is of interest because most virtualisation setups use bridging so we don't actually go through the IP stack on the host (with the exception of our old nemesis the bridge netfilter, but that's easily taken care of). So this patch simply adds skb_orphan to the point just before we enter the IP stack, but after we've gone through the bridge on the receive path. It also adds an skb_orphan to the one place in netfilter that touches skb->sk/skb->destructor, that is, tproxy. One word of caution, because of the internal code structure, anyone wishing to deploy this must use skb_set_owner_w as opposed to skb_set_owner_r since many functions that create a new skb from an existing one will invoke skb_set_owner_w on the new skb. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/core/dev.c | 2 ++ net/netfilter/nf_tproxy_core.c | 1 + 2 files changed, 3 insertions(+) diff --git a/net/core/dev.c b/net/core/dev.c index 220f52a1001..3337cf98f23 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2288,6 +2288,8 @@ ncls: if (!skb) goto out; + skb_orphan(skb); + type = skb->protocol; list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) { diff --git a/net/netfilter/nf_tproxy_core.c b/net/netfilter/nf_tproxy_core.c index cdc97f3105a..5490fc37c92 100644 --- a/net/netfilter/nf_tproxy_core.c +++ b/net/netfilter/nf_tproxy_core.c @@ -71,6 +71,7 @@ int nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk) { if (inet_sk(sk)->transparent) { + skb_orphan(skb); skb->sk = sk; skb->destructor = nf_tproxy_destructor; return 1; -- GitLab From 4cc7f68d65558f683c702d4fe3a5aac4c5227b97 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 4 Feb 2009 16:55:54 -0800 Subject: [PATCH 1171/4982] net: Reexport sock_alloc_send_pskb The function sock_alloc_send_pskb is completely useless if not exported since most of the code in it won't be used as is. In fact, this code has already been duplicated in the tun driver. Now that we need accounting in the tun driver, we can in fact use this function as is. So this patch marks it for export again. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- include/net/sock.h | 5 +++++ net/core/sock.c | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index 5a3a151bd73..c047def9cf1 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -945,6 +945,11 @@ extern struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, int noblock, int *errcode); +extern struct sk_buff *sock_alloc_send_pskb(struct sock *sk, + unsigned long header_len, + unsigned long data_len, + int noblock, + int *errcode); extern void *sock_kmalloc(struct sock *sk, int size, gfp_t priority); extern void sock_kfree_s(struct sock *sk, void *mem, int size); diff --git a/net/core/sock.c b/net/core/sock.c index f3a0d08cbb4..c64996f8a27 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1254,10 +1254,9 @@ static long sock_wait_for_wmem(struct sock * sk, long timeo) * Generic send/receive buffer handlers */ -static struct sk_buff *sock_alloc_send_pskb(struct sock *sk, - unsigned long header_len, - unsigned long data_len, - int noblock, int *errcode) +struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len, + unsigned long data_len, int noblock, + int *errcode) { struct sk_buff *skb; gfp_t gfp_mask; @@ -1337,6 +1336,7 @@ failure: *errcode = err; return NULL; } +EXPORT_SYMBOL(sock_alloc_send_pskb); struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, int noblock, int *errcode) -- GitLab From 383414322b3b3ced0cbc146801e0cc6c60a6c5f4 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 2 Feb 2009 13:55:31 -0800 Subject: [PATCH 1172/4982] xen: setup percpu data pointers We need to access percpu data fairly early, so set up the percpu registers as soon as possible. We only need to load the appropriate segment register. We already have a GDT, but its hard to change it early because we need to manipulate the pagetable to do so, and that hasn't been set up yet. Also, set the kernel stack when bringing up secondary CPUs. If we don't they all end up sharing the same stack... Signed-off-by: Jeremy Fitzhardinge Signed-off-by: H. Peter Anvin --- arch/x86/xen/enlighten.c | 15 ++++++++++++++- arch/x86/xen/smp.c | 6 ++++-- arch/x86/xen/xen-ops.h | 2 ++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index cd022c43dfb..aed7ceeb4b6 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -66,6 +66,8 @@ EXPORT_SYMBOL_GPL(xen_start_info); struct shared_info xen_dummy_shared_info; +void *xen_initial_gdt; + /* * Point at some empty memory to start with. We map the real shared_info * page as soon as fixmap is up and running. @@ -917,8 +919,19 @@ asmlinkage void __init xen_start_kernel(void) have_vcpu_info_placement = 0; #endif - /* setup percpu state */ +#ifdef CONFIG_X86_64 + /* + * Setup percpu state. We only need to do this for 64-bit + * because 32-bit already has %fs set properly. + */ load_percpu_segment(0); +#endif + /* + * The only reliable way to retain the initial address of the + * percpu gdt_page is to remember it here, so we can go and + * mark it RW later, when the initial percpu area is freed. + */ + xen_initial_gdt = &per_cpu(gdt_page, 0); xen_smp_init(); diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 88d5d5ec6be..035582ae815 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -170,8 +170,7 @@ static void __init xen_smp_prepare_boot_cpu(void) /* We've switched to the "real" per-cpu gdt, so make sure the old memory can be recycled */ - make_lowmem_page_readwrite(__per_cpu_load + - (unsigned long)&per_cpu_var(gdt_page)); + make_lowmem_page_readwrite(xen_initial_gdt); xen_setup_vcpu_info_placement(); } @@ -287,6 +286,9 @@ static int __cpuinit xen_cpu_up(unsigned int cpu) irq_ctx_init(cpu); #else clear_tsk_thread_flag(idle, TIF_FORK); + per_cpu(kernel_stack, cpu) = + (unsigned long)task_stack_page(idle) - + KERNEL_STACK_OFFSET + THREAD_SIZE; #endif xen_setup_timer(cpu); xen_init_lock_cpu(cpu); diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 11913fc94c1..2f5ef2632ea 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -10,6 +10,8 @@ extern const char xen_hypervisor_callback[]; extern const char xen_failsafe_callback[]; +extern void *xen_initial_gdt; + struct trap_info; void xen_copy_trap_info(struct trap_info *traps); -- GitLab From 5393744b71ce797f1b1546fafaed127fc50c2b61 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 2 Feb 2009 13:55:42 -0800 Subject: [PATCH 1173/4982] xen: make direct versions of irq_enable/disable/save/restore to common code Now that x86-64 has directly accessible percpu variables, it can also implement the direct versions of these operations, which operate on a vcpu_info structure directly embedded in the percpu area. In fact, the 64-bit versions are more or less identical, and so can be shared. The only two differences are: 1. xen_restore_fl_direct takes its argument in eax on 32-bit, and rdi on 64-bit. Unfortunately it isn't possible to directly refer to the 2nd lsb of rdi directly (as you can with %ah), so the code isn't quite as dense. 2. check_events needs to variants to save different registers. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: H. Peter Anvin --- arch/x86/xen/Makefile | 3 +- arch/x86/xen/xen-asm.S | 140 ++++++++++++++++++++++++++++++++++++++ arch/x86/xen/xen-asm.h | 12 ++++ arch/x86/xen/xen-asm_32.S | 111 ++++-------------------------- arch/x86/xen/xen-asm_64.S | 134 +----------------------------------- 5 files changed, 169 insertions(+), 231 deletions(-) create mode 100644 arch/x86/xen/xen-asm.S create mode 100644 arch/x86/xen/xen-asm.h diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile index 6dcefba7836..3b767d03fd6 100644 --- a/arch/x86/xen/Makefile +++ b/arch/x86/xen/Makefile @@ -6,7 +6,8 @@ CFLAGS_REMOVE_irq.o = -pg endif obj-y := enlighten.o setup.o multicalls.o mmu.o irq.o \ - time.o xen-asm_$(BITS).o grant-table.o suspend.o + time.o xen-asm.o xen-asm_$(BITS).o \ + grant-table.o suspend.o obj-$(CONFIG_SMP) += smp.o spinlock.o obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o \ No newline at end of file diff --git a/arch/x86/xen/xen-asm.S b/arch/x86/xen/xen-asm.S new file mode 100644 index 00000000000..4c6f9679913 --- /dev/null +++ b/arch/x86/xen/xen-asm.S @@ -0,0 +1,140 @@ +/* + Asm versions of Xen pv-ops, suitable for either direct use or inlining. + The inline versions are the same as the direct-use versions, with the + pre- and post-amble chopped off. + + This code is encoded for size rather than absolute efficiency, + with a view to being able to inline as much as possible. + + We only bother with direct forms (ie, vcpu in percpu data) of + the operations here; the indirect forms are better handled in + C, since they're generally too large to inline anyway. + */ + +#include +#include +#include + +#include "xen-asm.h" + +/* + Enable events. This clears the event mask and tests the pending + event status with one and operation. If there are pending + events, then enter the hypervisor to get them handled. + */ +ENTRY(xen_irq_enable_direct) + /* Unmask events */ + movb $0, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask + + /* Preempt here doesn't matter because that will deal with + any pending interrupts. The pending check may end up being + run on the wrong CPU, but that doesn't hurt. */ + + /* Test for pending */ + testb $0xff, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_pending + jz 1f + +2: call check_events +1: +ENDPATCH(xen_irq_enable_direct) + ret + ENDPROC(xen_irq_enable_direct) + RELOC(xen_irq_enable_direct, 2b+1) + + +/* + Disabling events is simply a matter of making the event mask + non-zero. + */ +ENTRY(xen_irq_disable_direct) + movb $1, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask +ENDPATCH(xen_irq_disable_direct) + ret + ENDPROC(xen_irq_disable_direct) + RELOC(xen_irq_disable_direct, 0) + +/* + (xen_)save_fl is used to get the current interrupt enable status. + Callers expect the status to be in X86_EFLAGS_IF, and other bits + may be set in the return value. We take advantage of this by + making sure that X86_EFLAGS_IF has the right value (and other bits + in that byte are 0), but other bits in the return value are + undefined. We need to toggle the state of the bit, because + Xen and x86 use opposite senses (mask vs enable). + */ +ENTRY(xen_save_fl_direct) + testb $0xff, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask + setz %ah + addb %ah,%ah +ENDPATCH(xen_save_fl_direct) + ret + ENDPROC(xen_save_fl_direct) + RELOC(xen_save_fl_direct, 0) + + +/* + In principle the caller should be passing us a value return + from xen_save_fl_direct, but for robustness sake we test only + the X86_EFLAGS_IF flag rather than the whole byte. After + setting the interrupt mask state, it checks for unmasked + pending events and enters the hypervisor to get them delivered + if so. + */ +ENTRY(xen_restore_fl_direct) +#ifdef CONFIG_X86_64 + testw $X86_EFLAGS_IF, %di +#else + testb $X86_EFLAGS_IF>>8, %ah +#endif + setz PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask + /* Preempt here doesn't matter because that will deal with + any pending interrupts. The pending check may end up being + run on the wrong CPU, but that doesn't hurt. */ + + /* check for unmasked and pending */ + cmpw $0x0001, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_pending + jz 1f +2: call check_events +1: +ENDPATCH(xen_restore_fl_direct) + ret + ENDPROC(xen_restore_fl_direct) + RELOC(xen_restore_fl_direct, 2b+1) + + +/* + Force an event check by making a hypercall, + but preserve regs before making the call. + */ +check_events: +#ifdef CONFIG_X86_32 + push %eax + push %ecx + push %edx + call xen_force_evtchn_callback + pop %edx + pop %ecx + pop %eax +#else + push %rax + push %rcx + push %rdx + push %rsi + push %rdi + push %r8 + push %r9 + push %r10 + push %r11 + call xen_force_evtchn_callback + pop %r11 + pop %r10 + pop %r9 + pop %r8 + pop %rdi + pop %rsi + pop %rdx + pop %rcx + pop %rax +#endif + ret + diff --git a/arch/x86/xen/xen-asm.h b/arch/x86/xen/xen-asm.h new file mode 100644 index 00000000000..465276467a4 --- /dev/null +++ b/arch/x86/xen/xen-asm.h @@ -0,0 +1,12 @@ +#ifndef _XEN_XEN_ASM_H +#define _XEN_XEN_ASM_H + +#include + +#define RELOC(x, v) .globl x##_reloc; x##_reloc=v +#define ENDPATCH(x) .globl x##_end; x##_end=. + +/* Pseudo-flag used for virtual NMI, which we don't implement yet */ +#define XEN_EFLAGS_NMI 0x80000000 + +#endif diff --git a/arch/x86/xen/xen-asm_32.S b/arch/x86/xen/xen-asm_32.S index 42786f59d9c..082d173caaf 100644 --- a/arch/x86/xen/xen-asm_32.S +++ b/arch/x86/xen/xen-asm_32.S @@ -11,101 +11,28 @@ generally too large to inline anyway. */ -#include - -#include +//#include #include -#include #include #include #include -#define RELOC(x, v) .globl x##_reloc; x##_reloc=v -#define ENDPATCH(x) .globl x##_end; x##_end=. - -/* Pseudo-flag used for virtual NMI, which we don't implement yet */ -#define XEN_EFLAGS_NMI 0x80000000 - -/* - Enable events. This clears the event mask and tests the pending - event status with one and operation. If there are pending - events, then enter the hypervisor to get them handled. - */ -ENTRY(xen_irq_enable_direct) - /* Unmask events */ - movb $0, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_mask - - /* Preempt here doesn't matter because that will deal with - any pending interrupts. The pending check may end up being - run on the wrong CPU, but that doesn't hurt. */ - - /* Test for pending */ - testb $0xff, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_pending - jz 1f - -2: call check_events -1: -ENDPATCH(xen_irq_enable_direct) - ret - ENDPROC(xen_irq_enable_direct) - RELOC(xen_irq_enable_direct, 2b+1) - +#include "xen-asm.h" /* - Disabling events is simply a matter of making the event mask - non-zero. - */ -ENTRY(xen_irq_disable_direct) - movb $1, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_mask -ENDPATCH(xen_irq_disable_direct) - ret - ENDPROC(xen_irq_disable_direct) - RELOC(xen_irq_disable_direct, 0) - -/* - (xen_)save_fl is used to get the current interrupt enable status. - Callers expect the status to be in X86_EFLAGS_IF, and other bits - may be set in the return value. We take advantage of this by - making sure that X86_EFLAGS_IF has the right value (and other bits - in that byte are 0), but other bits in the return value are - undefined. We need to toggle the state of the bit, because - Xen and x86 use opposite senses (mask vs enable). - */ -ENTRY(xen_save_fl_direct) - testb $0xff, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_mask - setz %ah - addb %ah,%ah -ENDPATCH(xen_save_fl_direct) - ret - ENDPROC(xen_save_fl_direct) - RELOC(xen_save_fl_direct, 0) - - -/* - In principle the caller should be passing us a value return - from xen_save_fl_direct, but for robustness sake we test only - the X86_EFLAGS_IF flag rather than the whole byte. After - setting the interrupt mask state, it checks for unmasked - pending events and enters the hypervisor to get them delivered - if so. + Force an event check by making a hypercall, + but preserve regs before making the call. */ -ENTRY(xen_restore_fl_direct) - testb $X86_EFLAGS_IF>>8, %ah - setz PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_mask - /* Preempt here doesn't matter because that will deal with - any pending interrupts. The pending check may end up being - run on the wrong CPU, but that doesn't hurt. */ - - /* check for unmasked and pending */ - cmpw $0x0001, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_pending - jz 1f -2: call check_events -1: -ENDPATCH(xen_restore_fl_direct) +check_events: + push %eax + push %ecx + push %edx + call xen_force_evtchn_callback + pop %edx + pop %ecx + pop %eax ret - ENDPROC(xen_restore_fl_direct) - RELOC(xen_restore_fl_direct, 2b+1) /* We can't use sysexit directly, because we're not running in ring0. @@ -289,17 +216,3 @@ ENTRY(xen_iret_crit_fixup) lea 4(%edi),%esp /* point esp to new frame */ 2: jmp xen_do_upcall - -/* - Force an event check by making a hypercall, - but preserve regs before making the call. - */ -check_events: - push %eax - push %ecx - push %edx - call xen_force_evtchn_callback - pop %edx - pop %ecx - pop %eax - ret diff --git a/arch/x86/xen/xen-asm_64.S b/arch/x86/xen/xen-asm_64.S index d6fc51f4ce8..d205a283efe 100644 --- a/arch/x86/xen/xen-asm_64.S +++ b/arch/x86/xen/xen-asm_64.S @@ -11,142 +11,14 @@ generally too large to inline anyway. */ -#include - -#include -#include #include -#include #include +#include +#include #include -#define RELOC(x, v) .globl x##_reloc; x##_reloc=v -#define ENDPATCH(x) .globl x##_end; x##_end=. - -/* Pseudo-flag used for virtual NMI, which we don't implement yet */ -#define XEN_EFLAGS_NMI 0x80000000 - -#if 1 -/* - FIXME: x86_64 now can support direct access to percpu variables - via a segment override. Update xen accordingly. - */ -#define BUG ud2a -#endif - -/* - Enable events. This clears the event mask and tests the pending - event status with one and operation. If there are pending - events, then enter the hypervisor to get them handled. - */ -ENTRY(xen_irq_enable_direct) - BUG - - /* Unmask events */ - movb $0, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask - - /* Preempt here doesn't matter because that will deal with - any pending interrupts. The pending check may end up being - run on the wrong CPU, but that doesn't hurt. */ - - /* Test for pending */ - testb $0xff, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_pending - jz 1f - -2: call check_events -1: -ENDPATCH(xen_irq_enable_direct) - ret - ENDPROC(xen_irq_enable_direct) - RELOC(xen_irq_enable_direct, 2b+1) - -/* - Disabling events is simply a matter of making the event mask - non-zero. - */ -ENTRY(xen_irq_disable_direct) - BUG - - movb $1, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask -ENDPATCH(xen_irq_disable_direct) - ret - ENDPROC(xen_irq_disable_direct) - RELOC(xen_irq_disable_direct, 0) - -/* - (xen_)save_fl is used to get the current interrupt enable status. - Callers expect the status to be in X86_EFLAGS_IF, and other bits - may be set in the return value. We take advantage of this by - making sure that X86_EFLAGS_IF has the right value (and other bits - in that byte are 0), but other bits in the return value are - undefined. We need to toggle the state of the bit, because - Xen and x86 use opposite senses (mask vs enable). - */ -ENTRY(xen_save_fl_direct) - BUG - - testb $0xff, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask - setz %ah - addb %ah,%ah -ENDPATCH(xen_save_fl_direct) - ret - ENDPROC(xen_save_fl_direct) - RELOC(xen_save_fl_direct, 0) - -/* - In principle the caller should be passing us a value return - from xen_save_fl_direct, but for robustness sake we test only - the X86_EFLAGS_IF flag rather than the whole byte. After - setting the interrupt mask state, it checks for unmasked - pending events and enters the hypervisor to get them delivered - if so. - */ -ENTRY(xen_restore_fl_direct) - BUG - - testb $X86_EFLAGS_IF>>8, %ah - setz PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask - /* Preempt here doesn't matter because that will deal with - any pending interrupts. The pending check may end up being - run on the wrong CPU, but that doesn't hurt. */ - - /* check for unmasked and pending */ - cmpw $0x0001, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_pending - jz 1f -2: call check_events -1: -ENDPATCH(xen_restore_fl_direct) - ret - ENDPROC(xen_restore_fl_direct) - RELOC(xen_restore_fl_direct, 2b+1) - - -/* - Force an event check by making a hypercall, - but preserve regs before making the call. - */ -check_events: - push %rax - push %rcx - push %rdx - push %rsi - push %rdi - push %r8 - push %r9 - push %r10 - push %r11 - call xen_force_evtchn_callback - pop %r11 - pop %r10 - pop %r9 - pop %r8 - pop %rdi - pop %rsi - pop %rdx - pop %rcx - pop %rax - ret +#include "xen-asm.h" ENTRY(xen_adjust_exception_frame) mov 8+0(%rsp),%rcx -- GitLab From e4d0407185cdbdcfd99fc23bde2e5454bbc46329 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 2 Feb 2009 13:55:54 -0800 Subject: [PATCH 1174/4982] xen: use direct ops on 64-bit Enable the use of the direct vcpu-access operations on 64-bit. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: H. Peter Anvin --- arch/x86/xen/enlighten.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index aed7ceeb4b6..37230342c2c 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -87,14 +87,7 @@ struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info; * * 0: not available, 1: available */ -static int have_vcpu_info_placement = -#ifdef CONFIG_X86_32 - 1 -#else - 0 -#endif - ; - +static int have_vcpu_info_placement = 1; static void xen_vcpu_setup(int cpu) { @@ -914,11 +907,6 @@ asmlinkage void __init xen_start_kernel(void) machine_ops = xen_machine_ops; -#ifdef CONFIG_X86_64 - /* Disable until direct per-cpu data access. */ - have_vcpu_info_placement = 0; -#endif - #ifdef CONFIG_X86_64 /* * Setup percpu state. We only need to do this for 64-bit -- GitLab From 18114f61359ac05e3aa797d53d63f40db41f798d Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Fri, 30 Jan 2009 18:16:46 -0800 Subject: [PATCH 1175/4982] x86: uaccess: use errret as error value in __put_user_size() Impact: cleanup In __put_user_size() macro errret is used for error value. But if size is 8, errret isn't passed to__put_user_asm_u64(). This behavior is inconsistent. Signed-off-by: Hiroshi Shimamoto Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/uaccess.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index b9a24155f7a..b685ece89d5 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -186,7 +186,7 @@ extern int __get_user_bad(void); #ifdef CONFIG_X86_32 -#define __put_user_asm_u64(x, addr, err) \ +#define __put_user_asm_u64(x, addr, err, errret) \ asm volatile("1: movl %%eax,0(%2)\n" \ "2: movl %%edx,4(%2)\n" \ "3:\n" \ @@ -197,7 +197,7 @@ extern int __get_user_bad(void); _ASM_EXTABLE(1b, 4b) \ _ASM_EXTABLE(2b, 4b) \ : "=r" (err) \ - : "A" (x), "r" (addr), "i" (-EFAULT), "0" (err)) + : "A" (x), "r" (addr), "i" (errret), "0" (err)) #define __put_user_asm_ex_u64(x, addr) \ asm volatile("1: movl %%eax,0(%1)\n" \ @@ -211,8 +211,8 @@ extern int __get_user_bad(void); asm volatile("call __put_user_8" : "=a" (__ret_pu) \ : "A" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx") #else -#define __put_user_asm_u64(x, ptr, retval) \ - __put_user_asm(x, ptr, retval, "q", "", "Zr", -EFAULT) +#define __put_user_asm_u64(x, ptr, retval, errret) \ + __put_user_asm(x, ptr, retval, "q", "", "Zr", errret) #define __put_user_asm_ex_u64(x, addr) \ __put_user_asm_ex(x, addr, "q", "", "Zr") #define __put_user_x8(x, ptr, __ret_pu) __put_user_x(8, x, ptr, __ret_pu) @@ -289,7 +289,8 @@ do { \ __put_user_asm(x, ptr, retval, "l", "k", "ir", errret); \ break; \ case 8: \ - __put_user_asm_u64((__typeof__(*ptr))(x), ptr, retval); \ + __put_user_asm_u64((__typeof__(*ptr))(x), ptr, retval, \ + errret); \ break; \ default: \ __put_user_bad(); \ -- GitLab From 616f89e74cd954e04ae4f8bad6a3dc8730a4a47a Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Wed, 4 Feb 2009 11:23:19 -0500 Subject: [PATCH 1176/4982] ALSA: hda - Additional pin nids for STAC92HD71Bx and STAC92HD75Bx codecs Current code for STAC92HD71Bx and STAC92HD75Bx doesn't consider pin complexes 0x20 and 0x27. Also for 4 port models, nids 0x0e and 0x0f are vendor reserved. This commit changes code so it'll consider the additional pin complexes for models that have it, and avoid reserved nids to be touched on 4 port models. Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 59 +++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index a7df81efed2..58c9ff9d27f 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -481,10 +481,17 @@ static hda_nid_t stac92hd83xxx_pin_nids[14] = { 0x0f, 0x10, 0x11, 0x12, 0x13, 0x1d, 0x1e, 0x1f, 0x20 }; -static hda_nid_t stac92hd71bxx_pin_nids[11] = { + +#define STAC92HD71BXX_NUM_PINS 13 +static hda_nid_t stac92hd71bxx_pin_nids_4port[STAC92HD71BXX_NUM_PINS] = { + 0x0a, 0x0b, 0x0c, 0x0d, 0x00, + 0x00, 0x14, 0x18, 0x19, 0x1e, + 0x1f, 0x20, 0x27 +}; +static hda_nid_t stac92hd71bxx_pin_nids_6port[STAC92HD71BXX_NUM_PINS] = { 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x14, 0x18, 0x19, 0x1e, - 0x1f, + 0x1f, 0x20, 0x27 }; static hda_nid_t stac927x_pin_nids[14] = { @@ -1745,28 +1752,32 @@ static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { {} /* terminator */ }; -static unsigned int ref92hd71bxx_pin_configs[11] = { +static unsigned int ref92hd71bxx_pin_configs[STAC92HD71BXX_NUM_PINS] = { 0x02214030, 0x02a19040, 0x01a19020, 0x01014010, 0x0181302e, 0x01014010, 0x01019020, 0x90a000f0, - 0x90a000f0, 0x01452050, 0x01452050, + 0x90a000f0, 0x01452050, 0x01452050, 0x00000000, + 0x00000000 }; -static unsigned int dell_m4_1_pin_configs[11] = { +static unsigned int dell_m4_1_pin_configs[STAC92HD71BXX_NUM_PINS] = { 0x0421101f, 0x04a11221, 0x40f000f0, 0x90170110, 0x23a1902e, 0x23014250, 0x40f000f0, 0x90a000f0, - 0x40f000f0, 0x4f0000f0, 0x4f0000f0, + 0x40f000f0, 0x4f0000f0, 0x4f0000f0, 0x00000000, + 0x00000000 }; -static unsigned int dell_m4_2_pin_configs[11] = { +static unsigned int dell_m4_2_pin_configs[STAC92HD71BXX_NUM_PINS] = { 0x0421101f, 0x04a11221, 0x90a70330, 0x90170110, 0x23a1902e, 0x23014250, 0x40f000f0, 0x40f000f0, - 0x40f000f0, 0x044413b0, 0x044413b0, + 0x40f000f0, 0x044413b0, 0x044413b0, 0x00000000, + 0x00000000 }; -static unsigned int dell_m4_3_pin_configs[11] = { +static unsigned int dell_m4_3_pin_configs[STAC92HD71BXX_NUM_PINS] = { 0x0421101f, 0x04a11221, 0x90a70330, 0x90170110, 0x40f000f0, 0x40f000f0, 0x40f000f0, 0x90a000f0, - 0x40f000f0, 0x044413b0, 0x044413b0, + 0x40f000f0, 0x044413b0, 0x044413b0, 0x00000000, + 0x00000000 }; static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = { @@ -2311,7 +2322,9 @@ static int stac92xx_save_bios_config_regs(struct hda_codec *codec) for (i = 0; i < spec->num_pins; i++) { hda_nid_t nid = spec->pin_nids[i]; unsigned int pin_cfg; - + + if (!nid) + continue; pin_cfg = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0x00); snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x bios pin config %8.8x\n", @@ -2354,8 +2367,9 @@ static void stac92xx_set_config_regs(struct hda_codec *codec) return; for (i = 0; i < spec->num_pins; i++) - stac92xx_set_config_reg(codec, spec->pin_nids[i], - spec->pin_configs[i]); + if (spec->pin_nids[i] && spec->pin_configs[i]) + stac92xx_set_config_reg(codec, spec->pin_nids[i], + spec->pin_configs[i]); } static int stac_save_pin_cfgs(struct hda_codec *codec, unsigned int *pins) @@ -4952,9 +4966,21 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) codec->spec = spec; codec->patch_ops = stac92xx_patch_ops; - spec->num_pins = ARRAY_SIZE(stac92hd71bxx_pin_nids); + spec->num_pins = STAC92HD71BXX_NUM_PINS; + switch (codec->vendor_id) { + case 0x111d76b6: + case 0x111d76b7: + spec->pin_nids = stac92hd71bxx_pin_nids_4port; + break; + case 0x111d7603: + case 0x111d7608: + /* On 92HD75Bx 0x27 isn't a pin nid */ + spec->num_pins--; + /* fallthrough */ + default: + spec->pin_nids = stac92hd71bxx_pin_nids_6port; + } spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids); - spec->pin_nids = stac92hd71bxx_pin_nids; memcpy(&spec->private_dimux, &stac92hd71bxx_dmux, sizeof(stac92hd71bxx_dmux)); spec->board_config = snd_hda_check_board_config(codec, @@ -5018,7 +5044,8 @@ again: /* disable VSW */ spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF]; unmute_init++; - stac_change_pin_config(codec, 0xf, 0x40f000f0); + stac_change_pin_config(codec, 0x0f, 0x40f000f0); + stac_change_pin_config(codec, 0x19, 0x40f000f3); break; case 0x111d7603: /* 6 Port with Analog Mixer */ if ((codec->revision_id & 0xf) == 1) -- GitLab From 6df703aefc81252447c69d24d2863007de2338e9 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Wed, 4 Feb 2009 11:34:22 -0500 Subject: [PATCH 1177/4982] ALSA: hda - Dynamic detection of dmics/dmuxes/smuxes in stac92hd71bxx Detect the number of connected ports and number of smuxes dynamically, looking at pin configs, using new introduced functions stac92hd71bxx_connected_ports and stac92hd71bxx_connected_smuxes. Also use proper input mux configuration for 4port and 5port models. Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 99 +++++++++++++++++++++++++++++----- 1 file changed, 87 insertions(+), 12 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 58c9ff9d27f..c36c1c0f957 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -4944,7 +4944,16 @@ again: return 0; } -static struct hda_input_mux stac92hd71bxx_dmux = { +static struct hda_input_mux stac92hd71bxx_dmux_nomixer = { + .num_items = 3, + .items = { + { "Analog Inputs", 0x00 }, + { "Digital Mic 1", 0x02 }, + { "Digital Mic 2", 0x03 }, + } +}; + +static struct hda_input_mux stac92hd71bxx_dmux_amixer = { .num_items = 4, .items = { { "Analog Inputs", 0x00 }, @@ -4954,11 +4963,57 @@ static struct hda_input_mux stac92hd71bxx_dmux = { } }; +static int stac92hd71bxx_connected_ports(struct hda_codec *codec, + hda_nid_t *nids, int num_nids) +{ + struct sigmatel_spec *spec = codec->spec; + int idx, num; + unsigned int def_conf; + + for (num = 0; num < num_nids; num++) { + for (idx = 0; idx < spec->num_pins; idx++) + if (spec->pin_nids[idx] == nids[num]) + break; + if (idx >= spec->num_pins) + break; + def_conf = get_defcfg_connect(spec->pin_configs[idx]); + if (def_conf == AC_JACK_PORT_NONE) + break; + } + return num; +} + +static int stac92hd71bxx_connected_smuxes(struct hda_codec *codec, + hda_nid_t dig0pin) +{ + struct sigmatel_spec *spec = codec->spec; + int idx; + + for (idx = 0; idx < spec->num_pins; idx++) + if (spec->pin_nids[idx] == dig0pin) + break; + if ((idx + 2) >= spec->num_pins) + return 0; + + /* dig1pin case */ + if (get_defcfg_connect(spec->pin_configs[idx+1]) != AC_JACK_PORT_NONE) + return 2; + + /* dig0pin + dig2pin case */ + if (get_defcfg_connect(spec->pin_configs[idx+2]) != AC_JACK_PORT_NONE) + return 2; + if (get_defcfg_connect(spec->pin_configs[idx]) != AC_JACK_PORT_NONE) + return 1; + else + return 0; +} + static int patch_stac92hd71bxx(struct hda_codec *codec) { struct sigmatel_spec *spec; struct hda_verb *unmute_init = stac92hd71bxx_unmute_core_init; int err = 0; + unsigned int ndmic_nids = 0; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) @@ -4981,8 +5036,6 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) spec->pin_nids = stac92hd71bxx_pin_nids_6port; } spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids); - memcpy(&spec->private_dimux, &stac92hd71bxx_dmux, - sizeof(stac92hd71bxx_dmux)); spec->board_config = snd_hda_check_board_config(codec, STAC_92HD71BXX_MODELS, stac92hd71bxx_models, @@ -5007,16 +5060,32 @@ again: spec->gpio_data = 0x01; } + spec->dmic_nids = stac92hd71bxx_dmic_nids; + spec->dmux_nids = stac92hd71bxx_dmux_nids; + switch (codec->vendor_id) { case 0x111d76b6: /* 4 Port without Analog Mixer */ case 0x111d76b7: case 0x111d76b4: /* 6 Port without Analog Mixer */ case 0x111d76b5: + memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_nomixer, + sizeof(stac92hd71bxx_dmux_nomixer)); spec->mixer = stac92hd71bxx_mixer; spec->init = stac92hd71bxx_core_init; codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; + spec->num_dmics = stac92hd71bxx_connected_ports(codec, + stac92hd71bxx_dmic_nids, + STAC92HD71BXX_NUM_DMICS); + if (spec->num_dmics) { + spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); + spec->dinput_mux = &spec->private_dimux; + ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1; + } break; case 0x111d7608: /* 5 Port with Analog Mixer */ + memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer, + sizeof(stac92hd71bxx_dmux_amixer)); + spec->private_dimux.num_items--; switch (spec->board_config) { case STAC_HP_M4: /* Enable VREF power saving on GPIO1 detect */ @@ -5046,6 +5115,12 @@ again: unmute_init++; stac_change_pin_config(codec, 0x0f, 0x40f000f0); stac_change_pin_config(codec, 0x19, 0x40f000f3); + stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS - 1] = 0; + spec->num_dmics = stac92hd71bxx_connected_ports(codec, + stac92hd71bxx_dmic_nids, + STAC92HD71BXX_NUM_DMICS - 1); + spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); + ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 2; break; case 0x111d7603: /* 6 Port with Analog Mixer */ if ((codec->revision_id & 0xf) == 1) @@ -5055,10 +5130,17 @@ again: spec->num_pwrs = 0; /* fallthru */ default: + memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer, + sizeof(stac92hd71bxx_dmux_amixer)); spec->dinput_mux = &spec->private_dimux; spec->mixer = stac92hd71bxx_analog_mixer; spec->init = stac92hd71bxx_analog_core_init; codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; + spec->num_dmics = stac92hd71bxx_connected_ports(codec, + stac92hd71bxx_dmic_nids, + STAC92HD71BXX_NUM_DMICS); + spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); + ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1; } if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP) @@ -5071,13 +5153,12 @@ again: spec->digbeep_nid = 0x26; spec->mux_nids = stac92hd71bxx_mux_nids; spec->adc_nids = stac92hd71bxx_adc_nids; - spec->dmic_nids = stac92hd71bxx_dmic_nids; - spec->dmux_nids = stac92hd71bxx_dmux_nids; spec->smux_nids = stac92hd71bxx_smux_nids; spec->pwr_nids = stac92hd71bxx_pwr_nids; spec->num_muxes = ARRAY_SIZE(stac92hd71bxx_mux_nids); spec->num_adcs = ARRAY_SIZE(stac92hd71bxx_adc_nids); + spec->num_smuxes = stac92hd71bxx_connected_smuxes(codec, 0x1e); switch (spec->board_config) { case STAC_HP_M4: @@ -5097,17 +5178,11 @@ again: spec->num_smuxes = 0; spec->num_dmuxes = 0; break; - default: - spec->num_dmics = STAC92HD71BXX_NUM_DMICS; - spec->num_smuxes = ARRAY_SIZE(stac92hd71bxx_smux_nids); - spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); }; spec->multiout.dac_nids = spec->dac_nids; if (spec->dinput_mux) - spec->private_dimux.num_items += - spec->num_dmics - - (ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1); + spec->private_dimux.num_items += spec->num_dmics - ndmic_nids; err = stac92xx_parse_auto_config(codec, 0x21, 0x23); if (!err) { -- GitLab From 29d4ab4d6e996ef4c71910c915611151c34f1c75 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Wed, 4 Feb 2009 11:37:27 -0500 Subject: [PATCH 1178/4982] ALSA: hda - Don't call stac92xx_parse_auto_config with wrong dig_in Don't use uneeded/wrong third parameter for stac92xx_parse_auto_config in patch_stac92hd71bxx (no SPDIF in). Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index c36c1c0f957..0b00110a5a0 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -5184,7 +5184,7 @@ again: if (spec->dinput_mux) spec->private_dimux.num_items += spec->num_dmics - ndmic_nids; - err = stac92xx_parse_auto_config(codec, 0x21, 0x23); + err = stac92xx_parse_auto_config(codec, 0x21, 0); if (!err) { if (spec->board_config < 0) { printk(KERN_WARNING "hda_codec: No auto-config is " -- GitLab From 45c1d85bcc6438454d104966c30fd2497ae1cdd7 Mon Sep 17 00:00:00 2001 From: Matthew Ranostay Date: Wed, 4 Feb 2009 17:49:41 -0500 Subject: [PATCH 1179/4982] ALSA: hda: Added stac378x digital slave out struct Added the ADATOut nid to a slave digital outs struct to allow output via the DigOut pin. Signed-off-by: Matthew Ranostay Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 0b00110a5a0..85dc642d113 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -404,6 +404,10 @@ static hda_nid_t stac922x_mux_nids[2] = { 0x12, 0x13, }; +static hda_nid_t stac927x_slave_dig_outs[2] = { + 0x1f, 0, +}; + static hda_nid_t stac927x_adc_nids[3] = { 0x07, 0x08, 0x09 }; @@ -5320,6 +5324,7 @@ static int patch_stac927x(struct hda_codec *codec) return -ENOMEM; codec->spec = spec; + codec->slave_dig_outs = stac927x_slave_dig_outs; spec->num_pins = ARRAY_SIZE(stac927x_pin_nids); spec->pin_nids = stac927x_pin_nids; spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS, -- GitLab From 345d0b1964df83a6c3fff815fabd34e37265581f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 5 Feb 2009 09:10:20 +0100 Subject: [PATCH 1180/4982] ALSA: hwdep - Make open callback optional Don't require the open callback as mandatory. Now all hwdeps ops can be optional. Signed-off-by: Takashi Iwai --- sound/core/hwdep.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 195cafc5a55..a70ee7f1ed9 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c @@ -99,9 +99,6 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) if (hw == NULL) return -ENODEV; - if (!hw->ops.open) - return -ENXIO; - if (!try_module_get(hw->card->module)) return -EFAULT; @@ -113,6 +110,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) err = -EBUSY; break; } + if (!hw->ops.open) { + err = 0; + break; + } err = hw->ops.open(hw, file); if (err >= 0) break; @@ -151,7 +152,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) static int snd_hwdep_release(struct inode *inode, struct file * file) { - int err = -ENXIO; + int err = 0; struct snd_hwdep *hw = file->private_data; struct module *mod = hw->card->module; -- GitLab From e0d80648c0037b8b815317a52b782d4ea0c287f0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 5 Feb 2009 09:17:50 +0100 Subject: [PATCH 1181/4982] ALSA: hwdep - Fix coding style Fix misc coding style issues in hwdep.h and add some comments. Signed-off-by: Takashi Iwai --- include/sound/hwdep.h | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/include/sound/hwdep.h b/include/sound/hwdep.h index d9eea013c75..8c05e47a409 100644 --- a/include/sound/hwdep.h +++ b/include/sound/hwdep.h @@ -27,18 +27,28 @@ struct snd_hwdep; +/* hwdep file ops; all ops can be NULL */ struct snd_hwdep_ops { - long long (*llseek) (struct snd_hwdep *hw, struct file * file, long long offset, int orig); - long (*read) (struct snd_hwdep *hw, char __user *buf, long count, loff_t *offset); - long (*write) (struct snd_hwdep *hw, const char __user *buf, long count, loff_t *offset); - int (*open) (struct snd_hwdep * hw, struct file * file); - int (*release) (struct snd_hwdep *hw, struct file * file); - unsigned int (*poll) (struct snd_hwdep *hw, struct file * file, poll_table * wait); - int (*ioctl) (struct snd_hwdep *hw, struct file * file, unsigned int cmd, unsigned long arg); - int (*ioctl_compat) (struct snd_hwdep *hw, struct file * file, unsigned int cmd, unsigned long arg); - int (*mmap) (struct snd_hwdep *hw, struct file * file, struct vm_area_struct * vma); - int (*dsp_status) (struct snd_hwdep *hw, struct snd_hwdep_dsp_status *status); - int (*dsp_load) (struct snd_hwdep *hw, struct snd_hwdep_dsp_image *image); + long long (*llseek)(struct snd_hwdep *hw, struct file *file, + long long offset, int orig); + long (*read)(struct snd_hwdep *hw, char __user *buf, + long count, loff_t *offset); + long (*write)(struct snd_hwdep *hw, const char __user *buf, + long count, loff_t *offset); + int (*open)(struct snd_hwdep *hw, struct file * file); + int (*release)(struct snd_hwdep *hw, struct file * file); + unsigned int (*poll)(struct snd_hwdep *hw, struct file *file, + poll_table *wait); + int (*ioctl)(struct snd_hwdep *hw, struct file *file, + unsigned int cmd, unsigned long arg); + int (*ioctl_compat)(struct snd_hwdep *hw, struct file *file, + unsigned int cmd, unsigned long arg); + int (*mmap)(struct snd_hwdep *hw, struct file *file, + struct vm_area_struct *vma); + int (*dsp_status)(struct snd_hwdep *hw, + struct snd_hwdep_dsp_status *status); + int (*dsp_load)(struct snd_hwdep *hw, + struct snd_hwdep_dsp_image *image); }; struct snd_hwdep { @@ -61,9 +71,9 @@ struct snd_hwdep { void (*private_free) (struct snd_hwdep *hwdep); struct mutex open_mutex; - int used; - unsigned int dsp_loaded; - unsigned int exclusive: 1; + int used; /* reference counter */ + unsigned int dsp_loaded; /* bit fields of loaded dsp indices */ + unsigned int exclusive:1; /* exclusive access mode */ }; extern int snd_hwdep_new(struct snd_card *card, char *id, int device, -- GitLab From 28b7e343ee63454d563a71d2d5f769fc297fd5ad Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 5 Feb 2009 09:28:08 +0100 Subject: [PATCH 1182/4982] ALSA: Remove superfluous hwdep ops Remove NOP hwdep ops in sound drivers. Signed-off-by: Takashi Iwai --- sound/drivers/vx/vx_hwdep.c | 12 ------------ sound/pci/mixart/mixart_hwdep.c | 12 ------------ sound/pci/pcxhr/pcxhr_hwdep.c | 12 ------------ sound/pci/rme9652/hdsp.c | 9 --------- sound/pci/rme9652/hdspm.c | 9 --------- sound/synth/emux/emux_hwdep.c | 21 --------------------- sound/usb/usbmixer.c | 22 +--------------------- sound/usb/usx2y/usX2Yhwdep.c | 12 ------------ 8 files changed, 1 insertion(+), 108 deletions(-) diff --git a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c index 8d6362e2d4c..46df8817c18 100644 --- a/sound/drivers/vx/vx_hwdep.c +++ b/sound/drivers/vx/vx_hwdep.c @@ -119,16 +119,6 @@ void snd_vx_free_firmware(struct vx_core *chip) #else /* old style firmware loading */ -static int vx_hwdep_open(struct snd_hwdep *hw, struct file *file) -{ - return 0; -} - -static int vx_hwdep_release(struct snd_hwdep *hw, struct file *file) -{ - return 0; -} - static int vx_hwdep_dsp_status(struct snd_hwdep *hw, struct snd_hwdep_dsp_status *info) { @@ -243,8 +233,6 @@ int snd_vx_setup_firmware(struct vx_core *chip) hw->iface = SNDRV_HWDEP_IFACE_VX; hw->private_data = chip; - hw->ops.open = vx_hwdep_open; - hw->ops.release = vx_hwdep_release; hw->ops.dsp_status = vx_hwdep_dsp_status; hw->ops.dsp_load = vx_hwdep_dsp_load; hw->exclusive = 1; diff --git a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c index 3782b52bc0e..fa4de985fc4 100644 --- a/sound/pci/mixart/mixart_hwdep.c +++ b/sound/pci/mixart/mixart_hwdep.c @@ -581,16 +581,6 @@ MODULE_FIRMWARE("mixart/miXart8AES.xlx"); /* miXart hwdep interface id string */ #define SND_MIXART_HWDEP_ID "miXart Loader" -static int mixart_hwdep_open(struct snd_hwdep *hw, struct file *file) -{ - return 0; -} - -static int mixart_hwdep_release(struct snd_hwdep *hw, struct file *file) -{ - return 0; -} - static int mixart_hwdep_dsp_status(struct snd_hwdep *hw, struct snd_hwdep_dsp_status *info) { @@ -643,8 +633,6 @@ int snd_mixart_setup_firmware(struct mixart_mgr *mgr) hw->iface = SNDRV_HWDEP_IFACE_MIXART; hw->private_data = mgr; - hw->ops.open = mixart_hwdep_open; - hw->ops.release = mixart_hwdep_release; hw->ops.dsp_status = mixart_hwdep_dsp_status; hw->ops.dsp_load = mixart_hwdep_dsp_load; hw->exclusive = 1; diff --git a/sound/pci/pcxhr/pcxhr_hwdep.c b/sound/pci/pcxhr/pcxhr_hwdep.c index 592743a298b..17cb1233a90 100644 --- a/sound/pci/pcxhr/pcxhr_hwdep.c +++ b/sound/pci/pcxhr/pcxhr_hwdep.c @@ -471,16 +471,6 @@ static int pcxhr_hwdep_dsp_load(struct snd_hwdep *hw, return 0; } -static int pcxhr_hwdep_open(struct snd_hwdep *hw, struct file *file) -{ - return 0; -} - -static int pcxhr_hwdep_release(struct snd_hwdep *hw, struct file *file) -{ - return 0; -} - int pcxhr_setup_firmware(struct pcxhr_mgr *mgr) { int err; @@ -495,8 +485,6 @@ int pcxhr_setup_firmware(struct pcxhr_mgr *mgr) hw->iface = SNDRV_HWDEP_IFACE_PCXHR; hw->private_data = mgr; - hw->ops.open = pcxhr_hwdep_open; - hw->ops.release = pcxhr_hwdep_release; hw->ops.dsp_status = pcxhr_hwdep_dsp_status; hw->ops.dsp_load = pcxhr_hwdep_dsp_load; hw->exclusive = 1; diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 44d0c15e2b7..2434609b2d3 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -4413,13 +4413,6 @@ static int snd_hdsp_capture_release(struct snd_pcm_substream *substream) return 0; } -static int snd_hdsp_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file) -{ - /* we have nothing to initialize but the call is required */ - return 0; -} - - /* helper functions for copying meter values */ static inline int copy_u32_le(void __user *dest, void __iomem *src) { @@ -4738,9 +4731,7 @@ static int snd_hdsp_create_hwdep(struct snd_card *card, struct hdsp *hdsp) hw->private_data = hdsp; strcpy(hw->name, "HDSP hwdep interface"); - hw->ops.open = snd_hdsp_hwdep_dummy_op; hw->ops.ioctl = snd_hdsp_hwdep_ioctl; - hw->ops.release = snd_hdsp_hwdep_dummy_op; return 0; } diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 71231cf1b2b..df2034eb235 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -4100,13 +4100,6 @@ static int snd_hdspm_capture_release(struct snd_pcm_substream *substream) return 0; } -static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep * hw, struct file *file) -{ - /* we have nothing to initialize but the call is required */ - return 0; -} - - static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file, unsigned int cmd, unsigned long arg) { @@ -4213,9 +4206,7 @@ static int __devinit snd_hdspm_create_hwdep(struct snd_card *card, hw->private_data = hdspm; strcpy(hw->name, "HDSPM hwdep interface"); - hw->ops.open = snd_hdspm_hwdep_dummy_op; hw->ops.ioctl = snd_hdspm_hwdep_ioctl; - hw->ops.release = snd_hdspm_hwdep_dummy_op; return 0; } diff --git a/sound/synth/emux/emux_hwdep.c b/sound/synth/emux/emux_hwdep.c index 0a5391436ad..ff0b2a8fd25 100644 --- a/sound/synth/emux/emux_hwdep.c +++ b/sound/synth/emux/emux_hwdep.c @@ -24,25 +24,6 @@ #include #include "emux_voice.h" -/* - * open the hwdep device - */ -static int -snd_emux_hwdep_open(struct snd_hwdep *hw, struct file *file) -{ - return 0; -} - - -/* - * close the device - */ -static int -snd_emux_hwdep_release(struct snd_hwdep *hw, struct file *file) -{ - return 0; -} - #define TMP_CLIENT_ID 0x1001 @@ -146,8 +127,6 @@ snd_emux_init_hwdep(struct snd_emux *emu) emu->hwdep = hw; strcpy(hw->name, SNDRV_EMUX_HWDEP_NAME); hw->iface = SNDRV_HWDEP_IFACE_EMUX_WAVETABLE; - hw->ops.open = snd_emux_hwdep_open; - hw->ops.release = snd_emux_hwdep_release; hw->ops.ioctl = snd_emux_hwdep_ioctl; hw->exclusive = 1; hw->private_data = emu; diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index 00397c8a765..2bde79216fa 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c @@ -78,7 +78,6 @@ struct usb_mixer_interface { /* Sound Blaster remote control stuff */ const struct rc_config *rc_cfg; - unsigned long rc_hwdep_open; u32 rc_code; wait_queue_head_t rc_waitq; struct urb *rc_urb; @@ -1797,24 +1796,6 @@ static void snd_usb_soundblaster_remote_complete(struct urb *urb) wake_up(&mixer->rc_waitq); } -static int snd_usb_sbrc_hwdep_open(struct snd_hwdep *hw, struct file *file) -{ - struct usb_mixer_interface *mixer = hw->private_data; - - if (test_and_set_bit(0, &mixer->rc_hwdep_open)) - return -EBUSY; - return 0; -} - -static int snd_usb_sbrc_hwdep_release(struct snd_hwdep *hw, struct file *file) -{ - struct usb_mixer_interface *mixer = hw->private_data; - - clear_bit(0, &mixer->rc_hwdep_open); - smp_mb__after_clear_bit(); - return 0; -} - static long snd_usb_sbrc_hwdep_read(struct snd_hwdep *hw, char __user *buf, long count, loff_t *offset) { @@ -1867,9 +1848,8 @@ static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer) hwdep->iface = SNDRV_HWDEP_IFACE_SB_RC; hwdep->private_data = mixer; hwdep->ops.read = snd_usb_sbrc_hwdep_read; - hwdep->ops.open = snd_usb_sbrc_hwdep_open; - hwdep->ops.release = snd_usb_sbrc_hwdep_release; hwdep->ops.poll = snd_usb_sbrc_hwdep_poll; + hwdep->exclusive = 1; mixer->rc_urb = usb_alloc_urb(0, GFP_KERNEL); if (!mixer->rc_urb) diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c index 1558a5c4094..a26d8d83d3e 100644 --- a/sound/usb/usx2y/usX2Yhwdep.c +++ b/sound/usb/usx2y/usX2Yhwdep.c @@ -106,16 +106,6 @@ static unsigned int snd_us428ctls_poll(struct snd_hwdep *hw, struct file *file, } -static int snd_usX2Y_hwdep_open(struct snd_hwdep *hw, struct file *file) -{ - return 0; -} - -static int snd_usX2Y_hwdep_release(struct snd_hwdep *hw, struct file *file) -{ - return 0; -} - static int snd_usX2Y_hwdep_dsp_status(struct snd_hwdep *hw, struct snd_hwdep_dsp_status *info) { @@ -267,8 +257,6 @@ int usX2Y_hwdep_new(struct snd_card *card, struct usb_device* device) hw->iface = SNDRV_HWDEP_IFACE_USX2Y; hw->private_data = usX2Y(card); - hw->ops.open = snd_usX2Y_hwdep_open; - hw->ops.release = snd_usX2Y_hwdep_release; hw->ops.dsp_status = snd_usX2Y_hwdep_dsp_status; hw->ops.dsp_load = snd_usX2Y_hwdep_dsp_load; hw->ops.mmap = snd_us428ctls_mmap; -- GitLab From 705350f8bd6b44fda3f0dcc3e6f4b453da4378dd Mon Sep 17 00:00:00 2001 From: Mark Hills Date: Wed, 4 Feb 2009 22:34:30 +0000 Subject: [PATCH 1183/4982] ALSA: snd-usb-caiaq: Send the correct command when setting controls Fixes a bug where an incorrect command was sent which had no effect on the device. Signed-off-by: Mark Hills Acked-by: Daniel Mack Signed-off-by: Takashi Iwai --- sound/usb/caiaq/caiaq-control.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/caiaq/caiaq-control.c b/sound/usb/caiaq/caiaq-control.c index 6ac5489a0f2..1f9531d0fce 100644 --- a/sound/usb/caiaq/caiaq-control.c +++ b/sound/usb/caiaq/caiaq-control.c @@ -94,7 +94,7 @@ static int control_put(struct snd_kcontrol *kcontrol, if (pos & CNT_INTVAL) { dev->control_state[pos & ~CNT_INTVAL] = ucontrol->value.integer.value[0]; - snd_usb_caiaq_send_command(dev, EP1_CMD_DIMM_LEDS, + snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, dev->control_state, sizeof(dev->control_state)); } else { if (ucontrol->value.integer.value[0]) -- GitLab From e3ca4c9982e3b84da859ca20a3ca0a9d5bda8c30 Mon Sep 17 00:00:00 2001 From: Mark Hills Date: Wed, 4 Feb 2009 22:34:31 +0000 Subject: [PATCH 1184/4982] ALSA: snd-usb-caiaq: Set default input mode of A4DJ Do not start the device with input mode undefined. Mimic the behaviour of the Audio 8 DJ and start in phono input mode. Signed-off-by: Mark Hills Acked-by: Daniel Mack Signed-off-by: Takashi Iwai --- sound/usb/caiaq/caiaq-device.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c index d09fc2a88cf..94610dda8ab 100644 --- a/sound/usb/caiaq/caiaq-device.c +++ b/sound/usb/caiaq/caiaq-device.c @@ -312,6 +312,12 @@ static void __devinit setup_card(struct snd_usb_caiaqdev *dev) } break; + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): + /* Audio 4 DJ - default input mode to phono */ + dev->control_state[0] = 2; + snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, + dev->control_state, 1); + break; } if (dev->spec.num_analog_audio_out + -- GitLab From 9a9527ed49f45e75a5b005592a261ab2bd7c1b1d Mon Sep 17 00:00:00 2001 From: Mark Hills Date: Wed, 4 Feb 2009 22:34:32 +0000 Subject: [PATCH 1185/4982] ALSA: snd-usb-caiaq: Do not expose hardware input mode 0 of A4DJ In the context of the Audio 4 DJ (when compared to Audio 8 DJ), hardware input mode 0 is not used. Expose modes 1 (line) and 2 (phono) to the user as modes 0 and 1 respectively. Signed-off-by: Mark Hills Acked-by: Daniel Mack Signed-off-by: Takashi Iwai --- sound/usb/caiaq/caiaq-control.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/sound/usb/caiaq/caiaq-control.c b/sound/usb/caiaq/caiaq-control.c index 1f9531d0fce..136ef34300d 100644 --- a/sound/usb/caiaq/caiaq-control.c +++ b/sound/usb/caiaq/caiaq-control.c @@ -44,16 +44,24 @@ static int control_info(struct snd_kcontrol *kcontrol, uinfo->count = 1; pos &= ~CNT_INTVAL; - if (((id == USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ)) || - (id == USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ))) + if (id == USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ) && (pos == 0)) { - /* current input mode of A8DJ and A4DJ */ + /* current input mode of A8DJ */ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->value.integer.min = 0; uinfo->value.integer.max = 2; return 0; } + if (id == USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ) + && (pos == 0)) { + /* current input mode of A4DJ */ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; + } + if (is_intval) { uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->value.integer.min = 0; @@ -74,6 +82,14 @@ static int control_get(struct snd_kcontrol *kcontrol, struct snd_usb_caiaqdev *dev = caiaqdev(chip->card); int pos = kcontrol->private_value; + if (dev->chip.usb_id == + USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ)) { + /* A4DJ has only one control */ + /* do not expose hardware input mode 0 */ + ucontrol->value.integer.value[0] = dev->control_state[0] - 1; + return 0; + } + if (pos & CNT_INTVAL) ucontrol->value.integer.value[0] = dev->control_state[pos & ~CNT_INTVAL]; @@ -91,6 +107,16 @@ static int control_put(struct snd_kcontrol *kcontrol, struct snd_usb_caiaqdev *dev = caiaqdev(chip->card); int pos = kcontrol->private_value; + if (dev->chip.usb_id == + USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ)) { + /* A4DJ has only one control */ + /* do not expose hardware input mode 0 */ + dev->control_state[0] = ucontrol->value.integer.value[0] + 1; + snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, + dev->control_state, sizeof(dev->control_state)); + return 1; + } + if (pos & CNT_INTVAL) { dev->control_state[pos & ~CNT_INTVAL] = ucontrol->value.integer.value[0]; -- GitLab From a8564155a9cb3b5c4a18afc451679a1f02c647b5 Mon Sep 17 00:00:00 2001 From: Mark Hills Date: Wed, 4 Feb 2009 22:34:33 +0000 Subject: [PATCH 1186/4982] ALSA: snd-usb-caiaq: Remove duplicate A8DJ control Remove a duplicate control which causes an error when it is registered, and causes later controls to not be registered. The device does not have a fourth ground lift control. Signed-off-by: Mark Hills Acked-by: Daniel Mack Signed-off-by: Takashi Iwai --- sound/usb/caiaq/caiaq-control.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/usb/caiaq/caiaq-control.c b/sound/usb/caiaq/caiaq-control.c index 136ef34300d..e92c2bbf4fe 100644 --- a/sound/usb/caiaq/caiaq-control.c +++ b/sound/usb/caiaq/caiaq-control.c @@ -270,7 +270,6 @@ static struct caiaq_controller a8dj_controller[] = { { "GND lift for TC Vinyl mode", 24 + 0 }, { "GND lift for TC CD/Line mode", 24 + 1 }, { "GND lift for phono mode", 24 + 2 }, - { "GND lift for TC Vinyl mode", 24 + 3 }, { "Software lock", 40 } }; -- GitLab From 238c0270baade3a542c1497712dd8e66cc9cc476 Mon Sep 17 00:00:00 2001 From: Mark Hills Date: Wed, 4 Feb 2009 22:34:34 +0000 Subject: [PATCH 1187/4982] ALSA: snd-usb-caiaq: Increase version number to 1.3.12 Indicates fixes affecting control messages and switching of input mode on Audio 8 DJ and Audio 4 DJ. Signed-off-by: Mark Hills Acked-by: Daniel Mack Signed-off-by: Takashi Iwai --- sound/usb/caiaq/caiaq-device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c index 94610dda8ab..5736669df2d 100644 --- a/sound/usb/caiaq/caiaq-device.c +++ b/sound/usb/caiaq/caiaq-device.c @@ -42,7 +42,7 @@ #endif MODULE_AUTHOR("Daniel Mack "); -MODULE_DESCRIPTION("caiaq USB audio, version 1.3.11"); +MODULE_DESCRIPTION("caiaq USB audio, version 1.3.12"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," "{Native Instruments, RigKontrol3}," -- GitLab From 67f7857ab12e9f8005ef988f0b667396e07622c2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 5 Feb 2009 12:14:52 +0100 Subject: [PATCH 1188/4982] ALSA: hda - Add quirk for HP zenith laptop Added model=laptop for another HP laptop (103c:3072) with AD1984A codec. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_analog.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index e934e2c187d..6e348d03b71 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -3890,6 +3890,7 @@ static struct snd_pci_quirk ad1884a_cfg_tbl[] = { SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE), SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP), SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE), + SND_PCI_QUIRK(0x103c, 0x3072, "HP", AD1884A_LAPTOP), SND_PCI_QUIRK(0x103c, 0x30e6, "HP 6730b", AD1884A_LAPTOP), SND_PCI_QUIRK(0x103c, 0x30e7, "HP EliteBook 8530p", AD1884A_LAPTOP), SND_PCI_QUIRK(0x103c, 0x3614, "HP 6730s", AD1884A_LAPTOP), -- GitLab From 632da7321b7e9fa5375956280f8a0f380836c22d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 5 Feb 2009 15:02:06 +0100 Subject: [PATCH 1189/4982] ALSA: hda - Add quirk for another HP laptop Add model=laptop entry for another HP laptop (103c:3077) with AD1984A. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_analog.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 6e348d03b71..30399cbf819 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -3891,6 +3891,7 @@ static struct snd_pci_quirk ad1884a_cfg_tbl[] = { SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP), SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE), SND_PCI_QUIRK(0x103c, 0x3072, "HP", AD1884A_LAPTOP), + SND_PCI_QUIRK(0x103c, 0x3077, "HP", AD1884A_LAPTOP), SND_PCI_QUIRK(0x103c, 0x30e6, "HP 6730b", AD1884A_LAPTOP), SND_PCI_QUIRK(0x103c, 0x30e7, "HP EliteBook 8530p", AD1884A_LAPTOP), SND_PCI_QUIRK(0x103c, 0x3614, "HP 6730s", AD1884A_LAPTOP), -- GitLab From e6161653094f14b1add10efe3493a2e526fe9538 Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Thu, 5 Feb 2009 13:01:54 +0100 Subject: [PATCH 1190/4982] ALSA: snd_pcm_new api cleanup Impact: cleanup snd_pcm_new takes a char *id argument, although it is not modifying the string. it can therefore be declared as const char *id. Signed-off-by: Tim Blechmann Signed-off-by: Takashi Iwai --- include/sound/pcm.h | 2 +- sound/core/pcm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 40c5a6fa6bc..ee0e887e49d 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -451,7 +451,7 @@ struct snd_pcm_notify { extern const struct file_operations snd_pcm_f_ops[2]; -int snd_pcm_new(struct snd_card *card, char *id, int device, +int snd_pcm_new(struct snd_card *card, const char *id, int device, int playback_count, int capture_count, struct snd_pcm **rpcm); int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count); diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 192a433a240..583453e2355 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -692,7 +692,7 @@ EXPORT_SYMBOL(snd_pcm_new_stream); * * Returns zero if successful, or a negative error code on failure. */ -int snd_pcm_new(struct snd_card *card, char *id, int device, +int snd_pcm_new(struct snd_card *card, const char *id, int device, int playback_count, int capture_count, struct snd_pcm ** rpcm) { -- GitLab From e4967d6016b7785edafdb871e6d3e4426cb4bd1f Mon Sep 17 00:00:00 2001 From: Hans-Christian Egtvedt Date: Thu, 5 Feb 2009 13:10:59 +0100 Subject: [PATCH 1191/4982] ALSA: Add ALSA driver for Atmel Audio Bitstream DAC This patch adds ALSA support for the Audio Bistream DAC found on Atmel AVR32 devices. The ABDAC is an Atmel IP which might show up on AT91 devices in the future, hence making a generic driver which can be utilized by AT91 arch if needed. Datasheet describing the ABDAC peripheral is available in the AT32AP7000 datasheet, http://www.atmel.com/dyn/products/datasheets.asp?family_id=682 Tested on ATSTK1006 + ATSTK1000 with a class D amplifier stage. Signed-off-by: Hans-Christian Egtvedt Signed-off-by: Takashi Iwai --- include/sound/atmel-abdac.h | 23 ++ sound/atmel/Kconfig | 11 + sound/atmel/Makefile | 3 + sound/atmel/abdac.c | 602 ++++++++++++++++++++++++++++++++++++ 4 files changed, 639 insertions(+) create mode 100644 include/sound/atmel-abdac.h create mode 100644 sound/atmel/Kconfig create mode 100644 sound/atmel/Makefile create mode 100644 sound/atmel/abdac.c diff --git a/include/sound/atmel-abdac.h b/include/sound/atmel-abdac.h new file mode 100644 index 00000000000..edff6a8ba1b --- /dev/null +++ b/include/sound/atmel-abdac.h @@ -0,0 +1,23 @@ +/* + * Driver for the Atmel Audio Bitstream DAC (ABDAC) + * + * Copyright (C) 2009 Atmel Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ +#ifndef __INCLUDE_SOUND_ATMEL_ABDAC_H +#define __INCLUDE_SOUND_ATMEL_ABDAC_H + +#include + +/** + * struct atmel_abdac_pdata - board specific ABDAC configuration + * @dws: DMA slave interface to use for sound playback. + */ +struct atmel_abdac_pdata { + struct dw_dma_slave dws; +}; + +#endif /* __INCLUDE_SOUND_ATMEL_ABDAC_H */ diff --git a/sound/atmel/Kconfig b/sound/atmel/Kconfig new file mode 100644 index 00000000000..715318e3670 --- /dev/null +++ b/sound/atmel/Kconfig @@ -0,0 +1,11 @@ +menu "Atmel devices (AVR32 and AT91)" + depends on AVR32 || ARCH_AT91 + +config SND_ATMEL_ABDAC + tristate "Atmel Audio Bitstream DAC (ABDAC) driver" + select SND_PCM + depends on DW_DMAC && AVR32 + help + ALSA sound driver for the Atmel Audio Bitstream DAC (ABDAC). + +endmenu diff --git a/sound/atmel/Makefile b/sound/atmel/Makefile new file mode 100644 index 00000000000..c5a8213f9cb --- /dev/null +++ b/sound/atmel/Makefile @@ -0,0 +1,3 @@ +snd-atmel-abdac-objs := abdac.o + +obj-$(CONFIG_SND_ATMEL_ABDAC) += snd-atmel-abdac.o diff --git a/sound/atmel/abdac.c b/sound/atmel/abdac.c new file mode 100644 index 00000000000..28b3c7f7cfe --- /dev/null +++ b/sound/atmel/abdac.c @@ -0,0 +1,602 @@ +/* + * Driver for the Atmel on-chip Audio Bitstream DAC (ABDAC) + * + * Copyright (C) 2006-2009 Atmel Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* DAC register offsets */ +#define DAC_DATA 0x0000 +#define DAC_CTRL 0x0008 +#define DAC_INT_MASK 0x000c +#define DAC_INT_EN 0x0010 +#define DAC_INT_DIS 0x0014 +#define DAC_INT_CLR 0x0018 +#define DAC_INT_STATUS 0x001c + +/* Bitfields in CTRL */ +#define DAC_SWAP_OFFSET 30 +#define DAC_SWAP_SIZE 1 +#define DAC_EN_OFFSET 31 +#define DAC_EN_SIZE 1 + +/* Bitfields in INT_MASK/INT_EN/INT_DIS/INT_STATUS/INT_CLR */ +#define DAC_UNDERRUN_OFFSET 28 +#define DAC_UNDERRUN_SIZE 1 +#define DAC_TX_READY_OFFSET 29 +#define DAC_TX_READY_SIZE 1 + +/* Bit manipulation macros */ +#define DAC_BIT(name) \ + (1 << DAC_##name##_OFFSET) +#define DAC_BF(name, value) \ + (((value) & ((1 << DAC_##name##_SIZE) - 1)) \ + << DAC_##name##_OFFSET) +#define DAC_BFEXT(name, value) \ + (((value) >> DAC_##name##_OFFSET) \ + & ((1 << DAC_##name##_SIZE) - 1)) +#define DAC_BFINS(name, value, old) \ + (((old) & ~(((1 << DAC_##name##_SIZE) - 1) \ + << DAC_##name##_OFFSET)) \ + | DAC_BF(name, value)) + +/* Register access macros */ +#define dac_readl(port, reg) \ + __raw_readl((port)->regs + DAC_##reg) +#define dac_writel(port, reg, value) \ + __raw_writel((value), (port)->regs + DAC_##reg) + +/* + * ABDAC supports a maximum of 6 different rates from a generic clock. The + * generic clock has a power of two divider, which gives 6 steps from 192 kHz + * to 5112 Hz. + */ +#define MAX_NUM_RATES 6 +/* ALSA seems to use rates between 192000 Hz and 5112 Hz. */ +#define RATE_MAX 192000 +#define RATE_MIN 5112 + +enum { + DMA_READY = 0, +}; + +struct atmel_abdac_dma { + struct dma_chan *chan; + struct dw_cyclic_desc *cdesc; +}; + +struct atmel_abdac { + struct clk *pclk; + struct clk *sample_clk; + struct platform_device *pdev; + struct atmel_abdac_dma dma; + + struct snd_pcm_hw_constraint_list constraints_rates; + struct snd_pcm_substream *substream; + struct snd_card *card; + struct snd_pcm *pcm; + + void __iomem *regs; + unsigned long flags; + unsigned int rates[MAX_NUM_RATES]; + unsigned int rates_num; + int irq; +}; + +#define get_dac(card) ((struct atmel_abdac *)(card)->private_data) + +/* This function is called by the DMA driver. */ +static void atmel_abdac_dma_period_done(void *arg) +{ + struct atmel_abdac *dac = arg; + snd_pcm_period_elapsed(dac->substream); +} + +static int atmel_abdac_prepare_dma(struct atmel_abdac *dac, + struct snd_pcm_substream *substream, + enum dma_data_direction direction) +{ + struct dma_chan *chan = dac->dma.chan; + struct dw_cyclic_desc *cdesc; + struct snd_pcm_runtime *runtime = substream->runtime; + unsigned long buffer_len, period_len; + + /* + * We don't do DMA on "complex" transfers, i.e. with + * non-halfword-aligned buffers or lengths. + */ + if (runtime->dma_addr & 1 || runtime->buffer_size & 1) { + dev_dbg(&dac->pdev->dev, "too complex transfer\n"); + return -EINVAL; + } + + buffer_len = frames_to_bytes(runtime, runtime->buffer_size); + period_len = frames_to_bytes(runtime, runtime->period_size); + + cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len, + period_len, DMA_TO_DEVICE); + if (IS_ERR(cdesc)) { + dev_dbg(&dac->pdev->dev, "could not prepare cyclic DMA\n"); + return PTR_ERR(cdesc); + } + + cdesc->period_callback = atmel_abdac_dma_period_done; + cdesc->period_callback_param = dac; + + dac->dma.cdesc = cdesc; + + set_bit(DMA_READY, &dac->flags); + + return 0; +} + +static struct snd_pcm_hardware atmel_abdac_hw = { + .info = (SNDRV_PCM_INFO_MMAP + | SNDRV_PCM_INFO_MMAP_VALID + | SNDRV_PCM_INFO_INTERLEAVED + | SNDRV_PCM_INFO_BLOCK_TRANSFER + | SNDRV_PCM_INFO_RESUME + | SNDRV_PCM_INFO_PAUSE), + .formats = (SNDRV_PCM_FMTBIT_S16_BE), + .rates = (SNDRV_PCM_RATE_KNOT), + .rate_min = RATE_MIN, + .rate_max = RATE_MAX, + .channels_min = 2, + .channels_max = 2, + .buffer_bytes_max = 64 * 4096, + .period_bytes_min = 4096, + .period_bytes_max = 4096, + .periods_min = 4, + .periods_max = 64, +}; + +static int atmel_abdac_open(struct snd_pcm_substream *substream) +{ + struct atmel_abdac *dac = snd_pcm_substream_chip(substream); + + dac->substream = substream; + atmel_abdac_hw.rate_max = dac->rates[dac->rates_num - 1]; + atmel_abdac_hw.rate_min = dac->rates[0]; + substream->runtime->hw = atmel_abdac_hw; + + return snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, &dac->constraints_rates); +} + +static int atmel_abdac_close(struct snd_pcm_substream *substream) +{ + struct atmel_abdac *dac = snd_pcm_substream_chip(substream); + dac->substream = NULL; + return 0; +} + +static int atmel_abdac_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + struct atmel_abdac *dac = snd_pcm_substream_chip(substream); + int retval; + + retval = snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); + if (retval < 0) + return retval; + /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ + if (retval == 1) + if (test_and_clear_bit(DMA_READY, &dac->flags)) + dw_dma_cyclic_free(dac->dma.chan); + + return retval; +} + +static int atmel_abdac_hw_free(struct snd_pcm_substream *substream) +{ + struct atmel_abdac *dac = snd_pcm_substream_chip(substream); + if (test_and_clear_bit(DMA_READY, &dac->flags)) + dw_dma_cyclic_free(dac->dma.chan); + return snd_pcm_lib_free_pages(substream); +} + +static int atmel_abdac_prepare(struct snd_pcm_substream *substream) +{ + struct atmel_abdac *dac = snd_pcm_substream_chip(substream); + int retval; + + retval = clk_set_rate(dac->sample_clk, 256 * substream->runtime->rate); + if (retval) + return retval; + + if (!test_bit(DMA_READY, &dac->flags)) + retval = atmel_abdac_prepare_dma(dac, substream, DMA_TO_DEVICE); + + return retval; +} + +static int atmel_abdac_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct atmel_abdac *dac = snd_pcm_substream_chip(substream); + int retval = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ + case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ + case SNDRV_PCM_TRIGGER_START: + clk_enable(dac->sample_clk); + retval = dw_dma_cyclic_start(dac->dma.chan); + if (retval) + goto out; + dac_writel(dac, CTRL, DAC_BIT(EN)); + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ + case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ + case SNDRV_PCM_TRIGGER_STOP: + dw_dma_cyclic_stop(dac->dma.chan); + dac_writel(dac, DATA, 0); + dac_writel(dac, CTRL, 0); + clk_disable(dac->sample_clk); + break; + default: + retval = -EINVAL; + break; + } +out: + return retval; +} + +static snd_pcm_uframes_t +atmel_abdac_pointer(struct snd_pcm_substream *substream) +{ + struct atmel_abdac *dac = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + snd_pcm_uframes_t frames; + unsigned long bytes; + + bytes = dw_dma_get_src_addr(dac->dma.chan); + bytes -= runtime->dma_addr; + + frames = bytes_to_frames(runtime, bytes); + if (frames >= runtime->buffer_size) + frames -= runtime->buffer_size; + + return frames; +} + +static irqreturn_t abdac_interrupt(int irq, void *dev_id) +{ + struct atmel_abdac *dac = dev_id; + u32 status; + + status = dac_readl(dac, INT_STATUS); + if (status & DAC_BIT(UNDERRUN)) { + dev_err(&dac->pdev->dev, "underrun detected\n"); + dac_writel(dac, INT_CLR, DAC_BIT(UNDERRUN)); + } else { + dev_err(&dac->pdev->dev, "spurious interrupt (status=0x%x)\n", + status); + dac_writel(dac, INT_CLR, status); + } + + return IRQ_HANDLED; +} + +static struct snd_pcm_ops atmel_abdac_ops = { + .open = atmel_abdac_open, + .close = atmel_abdac_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = atmel_abdac_hw_params, + .hw_free = atmel_abdac_hw_free, + .prepare = atmel_abdac_prepare, + .trigger = atmel_abdac_trigger, + .pointer = atmel_abdac_pointer, +}; + +static int __devinit atmel_abdac_pcm_new(struct atmel_abdac *dac) +{ + struct snd_pcm_hardware hw = atmel_abdac_hw; + struct snd_pcm *pcm; + int retval; + + retval = snd_pcm_new(dac->card, dac->card->shortname, + dac->pdev->id, 1, 0, &pcm); + if (retval) + return retval; + + strcpy(pcm->name, dac->card->shortname); + pcm->private_data = dac; + pcm->info_flags = 0; + dac->pcm = pcm; + + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &atmel_abdac_ops); + + retval = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, + &dac->pdev->dev, hw.periods_min * hw.period_bytes_min, + hw.buffer_bytes_max); + + return retval; +} + +static bool filter(struct dma_chan *chan, void *slave) +{ + struct dw_dma_slave *dws = slave; + + if (dws->dma_dev == chan->device->dev) { + chan->private = dws; + return true; + } else + return false; +} + +static int set_sample_rates(struct atmel_abdac *dac) +{ + long new_rate = RATE_MAX; + int retval = -EINVAL; + int index = 0; + + /* we start at 192 kHz and work our way down to 5112 Hz */ + while (new_rate >= RATE_MIN && index < (MAX_NUM_RATES + 1)) { + new_rate = clk_round_rate(dac->sample_clk, 256 * new_rate); + if (new_rate < 0) + break; + /* make sure we are below the ABDAC clock */ + if (new_rate <= clk_get_rate(dac->pclk)) { + dac->rates[index] = new_rate / 256; + index++; + } + /* divide by 256 and then by two to get next rate */ + new_rate /= 256 * 2; + } + + if (index) { + int i; + + /* reverse array, smallest go first */ + for (i = 0; i < (index / 2); i++) { + unsigned int tmp = dac->rates[index - 1 - i]; + dac->rates[index - 1 - i] = dac->rates[i]; + dac->rates[i] = tmp; + } + + dac->constraints_rates.count = index; + dac->constraints_rates.list = dac->rates; + dac->constraints_rates.mask = 0; + dac->rates_num = index; + + retval = 0; + } + + return retval; +} + +static int __devinit atmel_abdac_probe(struct platform_device *pdev) +{ + struct snd_card *card; + struct atmel_abdac *dac; + struct resource *regs; + struct atmel_abdac_pdata *pdata; + struct clk *pclk; + struct clk *sample_clk; + int retval; + int irq; + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) { + dev_dbg(&pdev->dev, "no memory resource\n"); + return -ENXIO; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_dbg(&pdev->dev, "could not get IRQ number\n"); + return irq; + } + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_dbg(&pdev->dev, "no platform data\n"); + return -ENXIO; + } + + pclk = clk_get(&pdev->dev, "pclk"); + if (IS_ERR(pclk)) { + dev_dbg(&pdev->dev, "no peripheral clock\n"); + return PTR_ERR(pclk); + } + sample_clk = clk_get(&pdev->dev, "sample_clk"); + if (IS_ERR(pclk)) { + dev_dbg(&pdev->dev, "no sample clock\n"); + retval = PTR_ERR(pclk); + goto out_put_pclk; + } + clk_enable(pclk); + + retval = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, + THIS_MODULE, sizeof(struct atmel_abdac), &card); + if (retval) { + dev_dbg(&pdev->dev, "could not create sound card device\n"); + goto out_put_sample_clk; + } + + dac = get_dac(card); + + dac->irq = irq; + dac->card = card; + dac->pclk = pclk; + dac->sample_clk = sample_clk; + dac->pdev = pdev; + + retval = set_sample_rates(dac); + if (retval < 0) { + dev_dbg(&pdev->dev, "could not set supported rates\n"); + goto out_free_card; + } + + dac->regs = ioremap(regs->start, regs->end - regs->start + 1); + if (!dac->regs) { + dev_dbg(&pdev->dev, "could not remap register memory\n"); + goto out_free_card; + } + + /* make sure the DAC is silent and disabled */ + dac_writel(dac, DATA, 0); + dac_writel(dac, CTRL, 0); + + retval = request_irq(irq, abdac_interrupt, 0, "abdac", dac); + if (retval) { + dev_dbg(&pdev->dev, "could not request irq\n"); + goto out_unmap_regs; + } + + snd_card_set_dev(card, &pdev->dev); + + if (pdata->dws.dma_dev) { + struct dw_dma_slave *dws = &pdata->dws; + dma_cap_mask_t mask; + + dws->tx_reg = regs->start + DAC_DATA; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + dac->dma.chan = dma_request_channel(mask, filter, dws); + } + if (!pdata->dws.dma_dev || !dac->dma.chan) { + dev_dbg(&pdev->dev, "DMA not available\n"); + retval = -ENODEV; + goto out_unset_card_dev; + } + + strcpy(card->driver, "Atmel ABDAC"); + strcpy(card->shortname, "Atmel ABDAC"); + sprintf(card->longname, "Atmel Audio Bitstream DAC"); + + retval = atmel_abdac_pcm_new(dac); + if (retval) { + dev_dbg(&pdev->dev, "could not register ABDAC pcm device\n"); + goto out_release_dma; + } + + retval = snd_card_register(card); + if (retval) { + dev_dbg(&pdev->dev, "could not register sound card\n"); + goto out_release_dma; + } + + platform_set_drvdata(pdev, card); + + dev_info(&pdev->dev, "Atmel ABDAC at 0x%p using %s\n", + dac->regs, dac->dma.chan->dev->device.bus_id); + + return retval; + +out_release_dma: + dma_release_channel(dac->dma.chan); + dac->dma.chan = NULL; +out_unset_card_dev: + snd_card_set_dev(card, NULL); + free_irq(irq, dac); +out_unmap_regs: + iounmap(dac->regs); +out_free_card: + snd_card_free(card); +out_put_sample_clk: + clk_put(sample_clk); + clk_disable(pclk); +out_put_pclk: + clk_put(pclk); + return retval; +} + +#ifdef CONFIG_PM +static int atmel_abdac_suspend(struct platform_device *pdev, pm_message_t msg) +{ + struct snd_card *card = platform_get_drvdata(pdev); + struct atmel_abdac *dac = card->private_data; + + dw_dma_cyclic_stop(dac->dma.chan); + clk_disable(dac->sample_clk); + clk_disable(dac->pclk); + + return 0; +} + +static int atmel_abdac_resume(struct platform_device *pdev) +{ + struct snd_card *card = platform_get_drvdata(pdev); + struct atmel_abdac *dac = card->private_data; + + clk_enable(dac->pclk); + clk_enable(dac->sample_clk); + if (test_bit(DMA_READY, &dac->flags)) + dw_dma_cyclic_start(dac->dma.chan); + + return 0; +} +#else +#define atmel_abdac_suspend NULL +#define atmel_abdac_resume NULL +#endif + +static int __devexit atmel_abdac_remove(struct platform_device *pdev) +{ + struct snd_card *card = platform_get_drvdata(pdev); + struct atmel_abdac *dac = get_dac(card); + + clk_put(dac->sample_clk); + clk_disable(dac->pclk); + clk_put(dac->pclk); + + dma_release_channel(dac->dma.chan); + dac->dma.chan = NULL; + snd_card_set_dev(card, NULL); + iounmap(dac->regs); + free_irq(dac->irq, dac); + snd_card_free(card); + + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver atmel_abdac_driver = { + .remove = __devexit_p(atmel_abdac_remove), + .driver = { + .name = "atmel_abdac", + }, + .suspend = atmel_abdac_suspend, + .resume = atmel_abdac_resume, +}; + +static int __init atmel_abdac_init(void) +{ + return platform_driver_probe(&atmel_abdac_driver, + atmel_abdac_probe); +} +module_init(atmel_abdac_init); + +static void __exit atmel_abdac_exit(void) +{ + platform_driver_unregister(&atmel_abdac_driver); +} +module_exit(atmel_abdac_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Driver for Atmel Audio Bitstream DAC (ABDAC)"); +MODULE_AUTHOR("Hans-Christian Egtvedt "); -- GitLab From 4ede028f8716523fc31e0d3d01b81405613dfb8f Mon Sep 17 00:00:00 2001 From: Hans-Christian Egtvedt Date: Thu, 5 Feb 2009 13:11:00 +0100 Subject: [PATCH 1192/4982] ALSA: Add ALSA driver for Atmel AC97 controller This patch adds ALSA support for the AC97 controller found on Atmel AVR32 devices. Tested on ATSTK1006 + ATSTK1000 with a development board with a AC97 codec. Signed-off-by: Hans-Christian Egtvedt Signed-off-by: Takashi Iwai --- include/sound/atmel-ac97c.h | 40 ++ sound/atmel/Kconfig | 8 + sound/atmel/Makefile | 2 + sound/atmel/ac97c.c | 932 ++++++++++++++++++++++++++++++++++++ sound/atmel/ac97c.h | 71 +++ 5 files changed, 1053 insertions(+) create mode 100644 include/sound/atmel-ac97c.h create mode 100644 sound/atmel/ac97c.c create mode 100644 sound/atmel/ac97c.h diff --git a/include/sound/atmel-ac97c.h b/include/sound/atmel-ac97c.h new file mode 100644 index 00000000000..e6aabdb4586 --- /dev/null +++ b/include/sound/atmel-ac97c.h @@ -0,0 +1,40 @@ +/* + * Driver for the Atmel AC97C controller + * + * Copyright (C) 2005-2009 Atmel Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ +#ifndef __INCLUDE_SOUND_ATMEL_AC97C_H +#define __INCLUDE_SOUND_ATMEL_AC97C_H + +#include + +#define AC97C_CAPTURE 0x01 +#define AC97C_PLAYBACK 0x02 +#define AC97C_BOTH (AC97C_CAPTURE | AC97C_PLAYBACK) + +/** + * struct atmel_ac97c_pdata - board specific AC97C configuration + * @rx_dws: DMA slave interface to use for sound capture. + * @tx_dws: DMA slave interface to use for sound playback. + * @reset_pin: GPIO pin wired to the reset input on the external AC97 codec, + * optional to use, set to -ENODEV if not in use. AC97 layer will + * try to do a software reset of the external codec anyway. + * @flags: Flags for which directions should be enabled. + * + * If the user do not want to use a DMA channel for playback or capture, i.e. + * only one feature is required on the board. The slave for playback or capture + * can be set to NULL. The AC97C driver will take use of this when setting up + * the sound streams. + */ +struct ac97c_platform_data { + struct dw_dma_slave rx_dws; + struct dw_dma_slave tx_dws; + unsigned int flags; + int reset_pin; +}; + +#endif /* __INCLUDE_SOUND_ATMEL_AC97C_H */ diff --git a/sound/atmel/Kconfig b/sound/atmel/Kconfig index 715318e3670..6c228a91940 100644 --- a/sound/atmel/Kconfig +++ b/sound/atmel/Kconfig @@ -8,4 +8,12 @@ config SND_ATMEL_ABDAC help ALSA sound driver for the Atmel Audio Bitstream DAC (ABDAC). +config SND_ATMEL_AC97C + tristate "Atmel AC97 Controller (AC97C) driver" + select SND_PCM + select SND_AC97_CODEC + depends on DW_DMAC && AVR32 + help + ALSA sound driver for the Atmel AC97 controller. + endmenu diff --git a/sound/atmel/Makefile b/sound/atmel/Makefile index c5a8213f9cb..219dcfac608 100644 --- a/sound/atmel/Makefile +++ b/sound/atmel/Makefile @@ -1,3 +1,5 @@ snd-atmel-abdac-objs := abdac.o +snd-atmel-ac97c-objs := ac97c.o obj-$(CONFIG_SND_ATMEL_ABDAC) += snd-atmel-abdac.o +obj-$(CONFIG_SND_ATMEL_AC97C) += snd-atmel-ac97c.o diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c new file mode 100644 index 00000000000..dd72e00e5ae --- /dev/null +++ b/sound/atmel/ac97c.c @@ -0,0 +1,932 @@ +/* + * Driver for the Atmel AC97C controller + * + * Copyright (C) 2005-2009 Atmel Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ac97c.h" + +enum { + DMA_TX_READY = 0, + DMA_RX_READY, + DMA_TX_CHAN_PRESENT, + DMA_RX_CHAN_PRESENT, +}; + +/* Serialize access to opened variable */ +static DEFINE_MUTEX(opened_mutex); + +struct atmel_ac97c_dma { + struct dma_chan *rx_chan; + struct dma_chan *tx_chan; +}; + +struct atmel_ac97c { + struct clk *pclk; + struct platform_device *pdev; + struct atmel_ac97c_dma dma; + + struct snd_pcm_substream *playback_substream; + struct snd_pcm_substream *capture_substream; + struct snd_card *card; + struct snd_pcm *pcm; + struct snd_ac97 *ac97; + struct snd_ac97_bus *ac97_bus; + + u64 cur_format; + unsigned int cur_rate; + unsigned long flags; + /* Serialize access to opened variable */ + spinlock_t lock; + void __iomem *regs; + int opened; + int reset_pin; +}; + +#define get_chip(card) ((struct atmel_ac97c *)(card)->private_data) + +#define ac97c_writel(chip, reg, val) \ + __raw_writel((val), (chip)->regs + AC97C_##reg) +#define ac97c_readl(chip, reg) \ + __raw_readl((chip)->regs + AC97C_##reg) + +/* This function is called by the DMA driver. */ +static void atmel_ac97c_dma_playback_period_done(void *arg) +{ + struct atmel_ac97c *chip = arg; + snd_pcm_period_elapsed(chip->playback_substream); +} + +static void atmel_ac97c_dma_capture_period_done(void *arg) +{ + struct atmel_ac97c *chip = arg; + snd_pcm_period_elapsed(chip->capture_substream); +} + +static int atmel_ac97c_prepare_dma(struct atmel_ac97c *chip, + struct snd_pcm_substream *substream, + enum dma_data_direction direction) +{ + struct dma_chan *chan; + struct dw_cyclic_desc *cdesc; + struct snd_pcm_runtime *runtime = substream->runtime; + unsigned long buffer_len, period_len; + + /* + * We don't do DMA on "complex" transfers, i.e. with + * non-halfword-aligned buffers or lengths. + */ + if (runtime->dma_addr & 1 || runtime->buffer_size & 1) { + dev_dbg(&chip->pdev->dev, "too complex transfer\n"); + return -EINVAL; + } + + if (direction == DMA_TO_DEVICE) + chan = chip->dma.tx_chan; + else + chan = chip->dma.rx_chan; + + buffer_len = frames_to_bytes(runtime, runtime->buffer_size); + period_len = frames_to_bytes(runtime, runtime->period_size); + + cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len, + period_len, direction); + if (IS_ERR(cdesc)) { + dev_dbg(&chip->pdev->dev, "could not prepare cyclic DMA\n"); + return PTR_ERR(cdesc); + } + + if (direction == DMA_TO_DEVICE) { + cdesc->period_callback = atmel_ac97c_dma_playback_period_done; + set_bit(DMA_TX_READY, &chip->flags); + } else { + cdesc->period_callback = atmel_ac97c_dma_capture_period_done; + set_bit(DMA_RX_READY, &chip->flags); + } + + cdesc->period_callback_param = chip; + + return 0; +} + +static struct snd_pcm_hardware atmel_ac97c_hw = { + .info = (SNDRV_PCM_INFO_MMAP + | SNDRV_PCM_INFO_MMAP_VALID + | SNDRV_PCM_INFO_INTERLEAVED + | SNDRV_PCM_INFO_BLOCK_TRANSFER + | SNDRV_PCM_INFO_JOINT_DUPLEX + | SNDRV_PCM_INFO_RESUME + | SNDRV_PCM_INFO_PAUSE), + .formats = (SNDRV_PCM_FMTBIT_S16_BE + | SNDRV_PCM_FMTBIT_S16_LE), + .rates = (SNDRV_PCM_RATE_CONTINUOUS), + .rate_min = 4000, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 2, + .buffer_bytes_max = 64 * 4096, + .period_bytes_min = 4096, + .period_bytes_max = 4096, + .periods_min = 4, + .periods_max = 64, +}; + +static int atmel_ac97c_playback_open(struct snd_pcm_substream *substream) +{ + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + + mutex_lock(&opened_mutex); + chip->opened++; + runtime->hw = atmel_ac97c_hw; + if (chip->cur_rate) { + runtime->hw.rate_min = chip->cur_rate; + runtime->hw.rate_max = chip->cur_rate; + } + if (chip->cur_format) + runtime->hw.formats = (1ULL << chip->cur_format); + mutex_unlock(&opened_mutex); + chip->playback_substream = substream; + return 0; +} + +static int atmel_ac97c_capture_open(struct snd_pcm_substream *substream) +{ + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + + mutex_lock(&opened_mutex); + chip->opened++; + runtime->hw = atmel_ac97c_hw; + if (chip->cur_rate) { + runtime->hw.rate_min = chip->cur_rate; + runtime->hw.rate_max = chip->cur_rate; + } + if (chip->cur_format) + runtime->hw.formats = (1ULL << chip->cur_format); + mutex_unlock(&opened_mutex); + chip->capture_substream = substream; + return 0; +} + +static int atmel_ac97c_playback_close(struct snd_pcm_substream *substream) +{ + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); + + mutex_lock(&opened_mutex); + chip->opened--; + if (!chip->opened) { + chip->cur_rate = 0; + chip->cur_format = 0; + } + mutex_unlock(&opened_mutex); + + chip->playback_substream = NULL; + + return 0; +} + +static int atmel_ac97c_capture_close(struct snd_pcm_substream *substream) +{ + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); + + mutex_lock(&opened_mutex); + chip->opened--; + if (!chip->opened) { + chip->cur_rate = 0; + chip->cur_format = 0; + } + mutex_unlock(&opened_mutex); + + chip->capture_substream = NULL; + + return 0; +} + +static int atmel_ac97c_playback_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); + int retval; + + retval = snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); + if (retval < 0) + return retval; + /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ + if (retval == 1) + if (test_and_clear_bit(DMA_TX_READY, &chip->flags)) + dw_dma_cyclic_free(chip->dma.tx_chan); + + /* Set restrictions to params. */ + mutex_lock(&opened_mutex); + chip->cur_rate = params_rate(hw_params); + chip->cur_format = params_format(hw_params); + mutex_unlock(&opened_mutex); + + return retval; +} + +static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); + int retval; + + retval = snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); + if (retval < 0) + return retval; + /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ + if (retval == 1) + if (test_and_clear_bit(DMA_RX_READY, &chip->flags)) + dw_dma_cyclic_free(chip->dma.rx_chan); + + /* Set restrictions to params. */ + mutex_lock(&opened_mutex); + chip->cur_rate = params_rate(hw_params); + chip->cur_format = params_format(hw_params); + mutex_unlock(&opened_mutex); + + return retval; +} + +static int atmel_ac97c_playback_hw_free(struct snd_pcm_substream *substream) +{ + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); + if (test_and_clear_bit(DMA_TX_READY, &chip->flags)) + dw_dma_cyclic_free(chip->dma.tx_chan); + return snd_pcm_lib_free_pages(substream); +} + +static int atmel_ac97c_capture_hw_free(struct snd_pcm_substream *substream) +{ + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); + if (test_and_clear_bit(DMA_RX_READY, &chip->flags)) + dw_dma_cyclic_free(chip->dma.rx_chan); + return snd_pcm_lib_free_pages(substream); +} + +static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) +{ + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + unsigned long word = 0; + int retval; + + /* assign channels to AC97C channel A */ + switch (runtime->channels) { + case 1: + word |= AC97C_CH_ASSIGN(PCM_LEFT, A); + break; + case 2: + word |= AC97C_CH_ASSIGN(PCM_LEFT, A) + | AC97C_CH_ASSIGN(PCM_RIGHT, A); + break; + default: + /* TODO: support more than two channels */ + return -EINVAL; + break; + } + ac97c_writel(chip, OCA, word); + + /* configure sample format and size */ + word = AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16; + + switch (runtime->format) { + case SNDRV_PCM_FORMAT_S16_LE: + word |= AC97C_CMR_CEM_LITTLE; + break; + case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ + default: + word &= ~(AC97C_CMR_CEM_LITTLE); + break; + } + + ac97c_writel(chip, CAMR, word); + + /* set variable rate if needed */ + if (runtime->rate != 48000) { + word = ac97c_readl(chip, MR); + word |= AC97C_MR_VRA; + ac97c_writel(chip, MR, word); + } else { + word = ac97c_readl(chip, MR); + word &= ~(AC97C_MR_VRA); + ac97c_writel(chip, MR, word); + } + + retval = snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE, + runtime->rate); + if (retval) + dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n", + runtime->rate); + + if (!test_bit(DMA_TX_READY, &chip->flags)) + retval = atmel_ac97c_prepare_dma(chip, substream, + DMA_TO_DEVICE); + + return retval; +} + +static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream) +{ + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + unsigned long word = 0; + int retval; + + /* assign channels to AC97C channel A */ + switch (runtime->channels) { + case 1: + word |= AC97C_CH_ASSIGN(PCM_LEFT, A); + break; + case 2: + word |= AC97C_CH_ASSIGN(PCM_LEFT, A) + | AC97C_CH_ASSIGN(PCM_RIGHT, A); + break; + default: + /* TODO: support more than two channels */ + return -EINVAL; + break; + } + ac97c_writel(chip, ICA, word); + + /* configure sample format and size */ + word = AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16; + + switch (runtime->format) { + case SNDRV_PCM_FORMAT_S16_LE: + word |= AC97C_CMR_CEM_LITTLE; + break; + case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ + default: + word &= ~(AC97C_CMR_CEM_LITTLE); + break; + } + + ac97c_writel(chip, CAMR, word); + + /* set variable rate if needed */ + if (runtime->rate != 48000) { + word = ac97c_readl(chip, MR); + word |= AC97C_MR_VRA; + ac97c_writel(chip, MR, word); + } else { + word = ac97c_readl(chip, MR); + word &= ~(AC97C_MR_VRA); + ac97c_writel(chip, MR, word); + } + + retval = snd_ac97_set_rate(chip->ac97, AC97_PCM_LR_ADC_RATE, + runtime->rate); + if (retval) + dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n", + runtime->rate); + + if (!test_bit(DMA_RX_READY, &chip->flags)) + retval = atmel_ac97c_prepare_dma(chip, substream, + DMA_FROM_DEVICE); + + return retval; +} + +static int +atmel_ac97c_playback_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); + unsigned long camr; + int retval = 0; + + camr = ac97c_readl(chip, CAMR); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ + case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ + case SNDRV_PCM_TRIGGER_START: + retval = dw_dma_cyclic_start(chip->dma.tx_chan); + if (retval) + goto out; + camr |= AC97C_CMR_CENA; + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ + case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ + case SNDRV_PCM_TRIGGER_STOP: + dw_dma_cyclic_stop(chip->dma.tx_chan); + if (chip->opened <= 1) + camr &= ~AC97C_CMR_CENA; + break; + default: + retval = -EINVAL; + goto out; + } + + ac97c_writel(chip, CAMR, camr); +out: + return retval; +} + +static int +atmel_ac97c_capture_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); + unsigned long camr; + int retval = 0; + + camr = ac97c_readl(chip, CAMR); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ + case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ + case SNDRV_PCM_TRIGGER_START: + retval = dw_dma_cyclic_start(chip->dma.rx_chan); + if (retval) + goto out; + camr |= AC97C_CMR_CENA; + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ + case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ + case SNDRV_PCM_TRIGGER_STOP: + dw_dma_cyclic_stop(chip->dma.rx_chan); + if (chip->opened <= 1) + camr &= ~AC97C_CMR_CENA; + break; + default: + retval = -EINVAL; + break; + } + + ac97c_writel(chip, CAMR, camr); +out: + return retval; +} + +static snd_pcm_uframes_t +atmel_ac97c_playback_pointer(struct snd_pcm_substream *substream) +{ + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + snd_pcm_uframes_t frames; + unsigned long bytes; + + bytes = dw_dma_get_src_addr(chip->dma.tx_chan); + bytes -= runtime->dma_addr; + + frames = bytes_to_frames(runtime, bytes); + if (frames >= runtime->buffer_size) + frames -= runtime->buffer_size; + return frames; +} + +static snd_pcm_uframes_t +atmel_ac97c_capture_pointer(struct snd_pcm_substream *substream) +{ + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + snd_pcm_uframes_t frames; + unsigned long bytes; + + bytes = dw_dma_get_dst_addr(chip->dma.rx_chan); + bytes -= runtime->dma_addr; + + frames = bytes_to_frames(runtime, bytes); + if (frames >= runtime->buffer_size) + frames -= runtime->buffer_size; + return frames; +} + +static struct snd_pcm_ops atmel_ac97_playback_ops = { + .open = atmel_ac97c_playback_open, + .close = atmel_ac97c_playback_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = atmel_ac97c_playback_hw_params, + .hw_free = atmel_ac97c_playback_hw_free, + .prepare = atmel_ac97c_playback_prepare, + .trigger = atmel_ac97c_playback_trigger, + .pointer = atmel_ac97c_playback_pointer, +}; + +static struct snd_pcm_ops atmel_ac97_capture_ops = { + .open = atmel_ac97c_capture_open, + .close = atmel_ac97c_capture_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = atmel_ac97c_capture_hw_params, + .hw_free = atmel_ac97c_capture_hw_free, + .prepare = atmel_ac97c_capture_prepare, + .trigger = atmel_ac97c_capture_trigger, + .pointer = atmel_ac97c_capture_pointer, +}; + +static int __devinit atmel_ac97c_pcm_new(struct atmel_ac97c *chip) +{ + struct snd_pcm *pcm; + struct snd_pcm_hardware hw = atmel_ac97c_hw; + int capture, playback, retval; + + capture = test_bit(DMA_RX_CHAN_PRESENT, &chip->flags); + playback = test_bit(DMA_TX_CHAN_PRESENT, &chip->flags); + + retval = snd_pcm_new(chip->card, chip->card->shortname, + chip->pdev->id, playback, capture, &pcm); + if (retval) + return retval; + + if (capture) + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, + &atmel_ac97_capture_ops); + if (playback) + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, + &atmel_ac97_playback_ops); + + retval = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, + &chip->pdev->dev, hw.periods_min * hw.period_bytes_min, + hw.buffer_bytes_max); + if (retval) + return retval; + + pcm->private_data = chip; + pcm->info_flags = 0; + strcpy(pcm->name, chip->card->shortname); + chip->pcm = pcm; + + return 0; +} + +static int atmel_ac97c_mixer_new(struct atmel_ac97c *chip) +{ + struct snd_ac97_template template; + memset(&template, 0, sizeof(template)); + template.private_data = chip; + return snd_ac97_mixer(chip->ac97_bus, &template, &chip->ac97); +} + +static void atmel_ac97c_write(struct snd_ac97 *ac97, unsigned short reg, + unsigned short val) +{ + struct atmel_ac97c *chip = get_chip(ac97); + unsigned long word; + int timeout = 40; + + word = (reg & 0x7f) << 16 | val; + + do { + if (ac97c_readl(chip, COSR) & AC97C_CSR_TXRDY) { + ac97c_writel(chip, COTHR, word); + return; + } + udelay(1); + } while (--timeout); + + dev_dbg(&chip->pdev->dev, "codec write timeout\n"); +} + +static unsigned short atmel_ac97c_read(struct snd_ac97 *ac97, + unsigned short reg) +{ + struct atmel_ac97c *chip = get_chip(ac97); + unsigned long word; + int timeout = 40; + int write = 10; + + word = (0x80 | (reg & 0x7f)) << 16; + + if ((ac97c_readl(chip, COSR) & AC97C_CSR_RXRDY) != 0) + ac97c_readl(chip, CORHR); + +retry_write: + timeout = 40; + + do { + if ((ac97c_readl(chip, COSR) & AC97C_CSR_TXRDY) != 0) { + ac97c_writel(chip, COTHR, word); + goto read_reg; + } + udelay(10); + } while (--timeout); + + if (!--write) + goto timed_out; + goto retry_write; + +read_reg: + do { + if ((ac97c_readl(chip, COSR) & AC97C_CSR_RXRDY) != 0) { + unsigned short val = ac97c_readl(chip, CORHR); + return val; + } + udelay(10); + } while (--timeout); + + if (!--write) + goto timed_out; + goto retry_write; + +timed_out: + dev_dbg(&chip->pdev->dev, "codec read timeout\n"); + return 0xffff; +} + +static bool filter(struct dma_chan *chan, void *slave) +{ + struct dw_dma_slave *dws = slave; + + if (dws->dma_dev == chan->device->dev) { + chan->private = dws; + return true; + } else + return false; +} + +static void atmel_ac97c_reset(struct atmel_ac97c *chip) +{ + ac97c_writel(chip, MR, AC97C_MR_WRST); + + if (gpio_is_valid(chip->reset_pin)) { + gpio_set_value(chip->reset_pin, 0); + /* AC97 v2.2 specifications says minimum 1 us. */ + udelay(10); + gpio_set_value(chip->reset_pin, 1); + } + + udelay(1); + ac97c_writel(chip, MR, AC97C_MR_ENA); +} + +static int __devinit atmel_ac97c_probe(struct platform_device *pdev) +{ + struct snd_card *card; + struct atmel_ac97c *chip; + struct resource *regs; + struct ac97c_platform_data *pdata; + struct clk *pclk; + static struct snd_ac97_bus_ops ops = { + .write = atmel_ac97c_write, + .read = atmel_ac97c_read, + }; + int retval; + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) { + dev_dbg(&pdev->dev, "no memory resource\n"); + return -ENXIO; + } + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_dbg(&pdev->dev, "no platform data\n"); + return -ENXIO; + } + + pclk = clk_get(&pdev->dev, "pclk"); + if (IS_ERR(pclk)) { + dev_dbg(&pdev->dev, "no peripheral clock\n"); + return PTR_ERR(pclk); + } + clk_enable(pclk); + + retval = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, + THIS_MODULE, sizeof(struct atmel_ac97c), &card); + if (retval) { + dev_dbg(&pdev->dev, "could not create sound card device\n"); + goto err_snd_card_new; + } + + chip = get_chip(card); + + spin_lock_init(&chip->lock); + + strcpy(card->driver, "Atmel AC97C"); + strcpy(card->shortname, "Atmel AC97C"); + sprintf(card->longname, "Atmel AC97 controller"); + + chip->card = card; + chip->pclk = pclk; + chip->pdev = pdev; + chip->regs = ioremap(regs->start, regs->end - regs->start + 1); + + if (!chip->regs) { + dev_dbg(&pdev->dev, "could not remap register memory\n"); + goto err_ioremap; + } + + if (gpio_is_valid(pdata->reset_pin)) { + if (gpio_request(pdata->reset_pin, "reset_pin")) { + dev_dbg(&pdev->dev, "reset pin not available\n"); + chip->reset_pin = -ENODEV; + } else { + gpio_direction_output(pdata->reset_pin, 1); + chip->reset_pin = pdata->reset_pin; + } + } + + snd_card_set_dev(card, &pdev->dev); + + retval = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus); + if (retval) { + dev_dbg(&pdev->dev, "could not register on ac97 bus\n"); + goto err_ac97_bus; + } + + atmel_ac97c_reset(chip); + + retval = atmel_ac97c_mixer_new(chip); + if (retval) { + dev_dbg(&pdev->dev, "could not register ac97 mixer\n"); + goto err_ac97_bus; + } + + if (pdata->rx_dws.dma_dev) { + struct dw_dma_slave *dws = &pdata->rx_dws; + dma_cap_mask_t mask; + + dws->rx_reg = regs->start + AC97C_CARHR + 2; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + chip->dma.rx_chan = dma_request_channel(mask, filter, dws); + + dev_info(&chip->pdev->dev, "using %s for DMA RX\n", + chip->dma.rx_chan->dev->device.bus_id); + set_bit(DMA_RX_CHAN_PRESENT, &chip->flags); + } + + if (pdata->tx_dws.dma_dev) { + struct dw_dma_slave *dws = &pdata->tx_dws; + dma_cap_mask_t mask; + + dws->tx_reg = regs->start + AC97C_CATHR + 2; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + chip->dma.tx_chan = dma_request_channel(mask, filter, dws); + + dev_info(&chip->pdev->dev, "using %s for DMA TX\n", + chip->dma.tx_chan->dev->device.bus_id); + set_bit(DMA_TX_CHAN_PRESENT, &chip->flags); + } + + if (!test_bit(DMA_RX_CHAN_PRESENT, &chip->flags) && + !test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) { + dev_dbg(&pdev->dev, "DMA not available\n"); + retval = -ENODEV; + goto err_dma; + } + + retval = atmel_ac97c_pcm_new(chip); + if (retval) { + dev_dbg(&pdev->dev, "could not register ac97 pcm device\n"); + goto err_dma; + } + + retval = snd_card_register(card); + if (retval) { + dev_dbg(&pdev->dev, "could not register sound card\n"); + goto err_ac97_bus; + } + + platform_set_drvdata(pdev, card); + + dev_info(&pdev->dev, "Atmel AC97 controller at 0x%p\n", + chip->regs); + + return 0; + +err_dma: + if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags)) + dma_release_channel(chip->dma.rx_chan); + if (test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) + dma_release_channel(chip->dma.tx_chan); + clear_bit(DMA_RX_CHAN_PRESENT, &chip->flags); + clear_bit(DMA_TX_CHAN_PRESENT, &chip->flags); + chip->dma.rx_chan = NULL; + chip->dma.tx_chan = NULL; +err_ac97_bus: + snd_card_set_dev(card, NULL); + + if (gpio_is_valid(chip->reset_pin)) + gpio_free(chip->reset_pin); + + iounmap(chip->regs); +err_ioremap: + snd_card_free(card); +err_snd_card_new: + clk_disable(pclk); + clk_put(pclk); + return retval; +} + +#ifdef CONFIG_PM +static int atmel_ac97c_suspend(struct platform_device *pdev, pm_message_t msg) +{ + struct snd_card *card = platform_get_drvdata(pdev); + struct atmel_ac97c *chip = card->private_data; + + if (test_bit(DMA_RX_READY, &chip->flags)) + dw_dma_cyclic_stop(chip->dma.rx_chan); + if (test_bit(DMA_TX_READY, &chip->flags)) + dw_dma_cyclic_stop(chip->dma.tx_chan); + clk_disable(chip->pclk); + + return 0; +} + +static int atmel_ac97c_resume(struct platform_device *pdev) +{ + struct snd_card *card = platform_get_drvdata(pdev); + struct atmel_ac97c *chip = card->private_data; + + clk_enable(chip->pclk); + if (test_bit(DMA_RX_READY, &chip->flags)) + dw_dma_cyclic_start(chip->dma.rx_chan); + if (test_bit(DMA_TX_READY, &chip->flags)) + dw_dma_cyclic_start(chip->dma.tx_chan); + + return 0; +} +#else +#define atmel_ac97c_suspend NULL +#define atmel_ac97c_resume NULL +#endif + +static int __devexit atmel_ac97c_remove(struct platform_device *pdev) +{ + struct snd_card *card = platform_get_drvdata(pdev); + struct atmel_ac97c *chip = get_chip(card); + + if (gpio_is_valid(chip->reset_pin)) + gpio_free(chip->reset_pin); + + clk_disable(chip->pclk); + clk_put(chip->pclk); + iounmap(chip->regs); + + if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags)) + dma_release_channel(chip->dma.rx_chan); + if (test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) + dma_release_channel(chip->dma.tx_chan); + clear_bit(DMA_RX_CHAN_PRESENT, &chip->flags); + clear_bit(DMA_TX_CHAN_PRESENT, &chip->flags); + chip->dma.rx_chan = NULL; + chip->dma.tx_chan = NULL; + + snd_card_set_dev(card, NULL); + snd_card_free(card); + + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver atmel_ac97c_driver = { + .remove = __devexit_p(atmel_ac97c_remove), + .driver = { + .name = "atmel_ac97c", + }, + .suspend = atmel_ac97c_suspend, + .resume = atmel_ac97c_resume, +}; + +static int __init atmel_ac97c_init(void) +{ + return platform_driver_probe(&atmel_ac97c_driver, + atmel_ac97c_probe); +} +module_init(atmel_ac97c_init); + +static void __exit atmel_ac97c_exit(void) +{ + platform_driver_unregister(&atmel_ac97c_driver); +} +module_exit(atmel_ac97c_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Driver for Atmel AC97 controller"); +MODULE_AUTHOR("Hans-Christian Egtvedt "); diff --git a/sound/atmel/ac97c.h b/sound/atmel/ac97c.h new file mode 100644 index 00000000000..c17bd582598 --- /dev/null +++ b/sound/atmel/ac97c.h @@ -0,0 +1,71 @@ +/* + * Register definitions for the Atmel AC97C controller + * + * Copyright (C) 2005-2009 Atmel Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ +#ifndef __SOUND_ATMEL_AC97C_H +#define __SOUND_ATMEL_AC97C_H + +#define AC97C_MR 0x08 +#define AC97C_ICA 0x10 +#define AC97C_OCA 0x14 +#define AC97C_CARHR 0x20 +#define AC97C_CATHR 0x24 +#define AC97C_CASR 0x28 +#define AC97C_CAMR 0x2c +#define AC97C_CBRHR 0x30 +#define AC97C_CBTHR 0x34 +#define AC97C_CBSR 0x38 +#define AC97C_CBMR 0x3c +#define AC97C_CORHR 0x40 +#define AC97C_COTHR 0x44 +#define AC97C_COSR 0x48 +#define AC97C_COMR 0x4c +#define AC97C_SR 0x50 +#define AC97C_IER 0x54 +#define AC97C_IDR 0x58 +#define AC97C_IMR 0x5c +#define AC97C_VERSION 0xfc + +#define AC97C_CATPR PDC_TPR +#define AC97C_CATCR PDC_TCR +#define AC97C_CATNPR PDC_TNPR +#define AC97C_CATNCR PDC_TNCR +#define AC97C_CARPR PDC_RPR +#define AC97C_CARCR PDC_RCR +#define AC97C_CARNPR PDC_RNPR +#define AC97C_CARNCR PDC_RNCR +#define AC97C_PTCR PDC_PTCR + +#define AC97C_MR_ENA (1 << 0) +#define AC97C_MR_WRST (1 << 1) +#define AC97C_MR_VRA (1 << 2) + +#define AC97C_CSR_TXRDY (1 << 0) +#define AC97C_CSR_UNRUN (1 << 2) +#define AC97C_CSR_RXRDY (1 << 4) +#define AC97C_CSR_ENDTX (1 << 10) +#define AC97C_CSR_ENDRX (1 << 14) + +#define AC97C_CMR_SIZE_20 (0 << 16) +#define AC97C_CMR_SIZE_18 (1 << 16) +#define AC97C_CMR_SIZE_16 (2 << 16) +#define AC97C_CMR_SIZE_10 (3 << 16) +#define AC97C_CMR_CEM_LITTLE (1 << 18) +#define AC97C_CMR_CEM_BIG (0 << 18) +#define AC97C_CMR_CENA (1 << 21) +#define AC97C_CMR_DMAEN (1 << 22) + +#define AC97C_SR_CAEVT (1 << 3) + +#define AC97C_CH_ASSIGN(slot, channel) \ + (AC97C_CHANNEL_##channel << (3 * (AC97_SLOT_##slot - 3))) +#define AC97C_CHANNEL_NONE 0x0 +#define AC97C_CHANNEL_A 0x1 +#define AC97C_CHANNEL_B 0x2 + +#endif /* __SOUND_ATMEL_AC97C_H */ -- GitLab From 6c7578bb0a631d018a68e5f90554f29fbd928055 Mon Sep 17 00:00:00 2001 From: Hans-Christian Egtvedt Date: Thu, 5 Feb 2009 13:11:01 +0100 Subject: [PATCH 1193/4982] ALSA: Add Atmel ALSA drivers directory Signed-off-by: Hans-Christian Egtvedt Signed-off-by: Haavard Skinnemoen Signed-off-by: Takashi Iwai --- sound/Kconfig | 2 ++ sound/Makefile | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/Kconfig b/sound/Kconfig index 200aca1faa7..1eceb85287c 100644 --- a/sound/Kconfig +++ b/sound/Kconfig @@ -60,6 +60,8 @@ source "sound/aoa/Kconfig" source "sound/arm/Kconfig" +source "sound/atmel/Kconfig" + source "sound/spi/Kconfig" source "sound/mips/Kconfig" diff --git a/sound/Makefile b/sound/Makefile index c76d70716fa..ec467decfa7 100644 --- a/sound/Makefile +++ b/sound/Makefile @@ -6,7 +6,7 @@ obj-$(CONFIG_SOUND_PRIME) += sound_firmware.o obj-$(CONFIG_SOUND_PRIME) += oss/ obj-$(CONFIG_DMASOUND) += oss/ obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \ - sparc/ spi/ parisc/ pcmcia/ mips/ soc/ + sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ obj-$(CONFIG_SND_AOA) += aoa/ # This one must be compilable even if sound is configured out -- GitLab From 76d498e43fa5f9f0a148dca8915cc7e9d9b9a643 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 5 Feb 2009 15:45:05 +0100 Subject: [PATCH 1194/4982] ALSA: wss - Add missing KERN_* prefix to printk Signed-off-by: Takashi Iwai --- sound/isa/wss/wss_lib.c | 76 ++++++++++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 23 deletions(-) diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index 3d6c5f2838a..8de5deda7ad 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c @@ -219,7 +219,8 @@ void snd_wss_out(struct snd_wss *chip, unsigned char reg, unsigned char value) snd_wss_wait(chip); #ifdef CONFIG_SND_DEBUG if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); + snd_printk(KERN_DEBUG "out: auto calibration time out " + "- reg = 0x%x, value = 0x%x\n", reg, value); #endif wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); wss_outb(chip, CS4231P(REG), value); @@ -235,7 +236,8 @@ unsigned char snd_wss_in(struct snd_wss *chip, unsigned char reg) snd_wss_wait(chip); #ifdef CONFIG_SND_DEBUG if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - snd_printk("in: auto calibration time out - reg = 0x%x\n", reg); + snd_printk(KERN_DEBUG "in: auto calibration time out " + "- reg = 0x%x\n", reg); #endif wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); mb(); @@ -252,7 +254,7 @@ void snd_cs4236_ext_out(struct snd_wss *chip, unsigned char reg, wss_outb(chip, CS4231P(REG), val); chip->eimage[CS4236_REG(reg)] = val; #if 0 - printk("ext out : reg = 0x%x, val = 0x%x\n", reg, val); + printk(KERN_DEBUG "ext out : reg = 0x%x, val = 0x%x\n", reg, val); #endif } EXPORT_SYMBOL(snd_cs4236_ext_out); @@ -268,7 +270,8 @@ unsigned char snd_cs4236_ext_in(struct snd_wss *chip, unsigned char reg) { unsigned char res; res = wss_inb(chip, CS4231P(REG)); - printk("ext in : reg = 0x%x, val = 0x%x\n", reg, res); + printk(KERN_DEBUG "ext in : reg = 0x%x, val = 0x%x\n", + reg, res); return res; } #endif @@ -394,13 +397,16 @@ void snd_wss_mce_up(struct snd_wss *chip) snd_wss_wait(chip); #ifdef CONFIG_SND_DEBUG if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - snd_printk("mce_up - auto calibration time out (0)\n"); + snd_printk(KERN_DEBUG + "mce_up - auto calibration time out (0)\n"); #endif spin_lock_irqsave(&chip->reg_lock, flags); chip->mce_bit |= CS4231_MCE; timeout = wss_inb(chip, CS4231P(REGSEL)); if (timeout == 0x80) - snd_printk("mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port); + snd_printk(KERN_DEBUG "mce_up [0x%lx]: " + "serious init problem - codec still busy\n", + chip->port); if (!(timeout & CS4231_MCE)) wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); @@ -419,7 +425,9 @@ void snd_wss_mce_down(struct snd_wss *chip) #ifdef CONFIG_SND_DEBUG if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - snd_printk("mce_down [0x%lx] - auto calibration time out (0)\n", (long)CS4231P(REGSEL)); + snd_printk(KERN_DEBUG "mce_down [0x%lx] - " + "auto calibration time out (0)\n", + (long)CS4231P(REGSEL)); #endif spin_lock_irqsave(&chip->reg_lock, flags); chip->mce_bit &= ~CS4231_MCE; @@ -427,7 +435,9 @@ void snd_wss_mce_down(struct snd_wss *chip) wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); spin_unlock_irqrestore(&chip->reg_lock, flags); if (timeout == 0x80) - snd_printk("mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port); + snd_printk(KERN_DEBUG "mce_down [0x%lx]: " + "serious init problem - codec still busy\n", + chip->port); if ((timeout & CS4231_MCE) == 0 || !(chip->hardware & hw_mask)) return; @@ -565,7 +575,7 @@ static unsigned char snd_wss_get_format(struct snd_wss *chip, if (channels > 1) rformat |= CS4231_STEREO; #if 0 - snd_printk("get_format: 0x%x (mode=0x%x)\n", format, mode); + snd_printk(KERN_DEBUG "get_format: 0x%x (mode=0x%x)\n", format, mode); #endif return rformat; } @@ -774,7 +784,7 @@ static void snd_wss_init(struct snd_wss *chip) snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printk("init: (1)\n"); + snd_printk(KERN_DEBUG "init: (1)\n"); #endif snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); @@ -789,7 +799,7 @@ static void snd_wss_init(struct snd_wss *chip) snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printk("init: (2)\n"); + snd_printk(KERN_DEBUG "init: (2)\n"); #endif snd_wss_mce_up(chip); @@ -800,7 +810,7 @@ static void snd_wss_init(struct snd_wss *chip) snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printk("init: (3) - afei = 0x%x\n", + snd_printk(KERN_DEBUG "init: (3) - afei = 0x%x\n", chip->image[CS4231_ALT_FEATURE_1]); #endif @@ -817,7 +827,7 @@ static void snd_wss_init(struct snd_wss *chip) snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printk("init: (4)\n"); + snd_printk(KERN_DEBUG "init: (4)\n"); #endif snd_wss_mce_up(chip); @@ -829,7 +839,7 @@ static void snd_wss_init(struct snd_wss *chip) snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printk("init: (5)\n"); + snd_printk(KERN_DEBUG "init: (5)\n"); #endif } @@ -1278,7 +1288,8 @@ static int snd_wss_probe(struct snd_wss *chip) } else if (rev == 0x03) { chip->hardware = WSS_HW_CS4236B; } else { - snd_printk("unknown CS chip with version 0x%x\n", rev); + snd_printk(KERN_ERR + "unknown CS chip with version 0x%x\n", rev); return -ENODEV; /* unknown CS4231 chip? */ } } @@ -1342,7 +1353,10 @@ static int snd_wss_probe(struct snd_wss *chip) case 6: break; default: - snd_printk("unknown CS4235 chip (enhanced version = 0x%x)\n", id); + snd_printk(KERN_WARNING + "unknown CS4235 chip " + "(enhanced version = 0x%x)\n", + id); } } else if ((id & 0x1f) == 0x0b) { /* CS4236/B */ switch (id >> 5) { @@ -1353,7 +1367,10 @@ static int snd_wss_probe(struct snd_wss *chip) chip->hardware = WSS_HW_CS4236B; break; default: - snd_printk("unknown CS4236 chip (enhanced version = 0x%x)\n", id); + snd_printk(KERN_WARNING + "unknown CS4236 chip " + "(enhanced version = 0x%x)\n", + id); } } else if ((id & 0x1f) == 0x08) { /* CS4237B */ chip->hardware = WSS_HW_CS4237B; @@ -1364,7 +1381,10 @@ static int snd_wss_probe(struct snd_wss *chip) case 7: break; default: - snd_printk("unknown CS4237B chip (enhanced version = 0x%x)\n", id); + snd_printk(KERN_WARNING + "unknown CS4237B chip " + "(enhanced version = 0x%x)\n", + id); } } else if ((id & 0x1f) == 0x09) { /* CS4238B */ chip->hardware = WSS_HW_CS4238B; @@ -1374,7 +1394,10 @@ static int snd_wss_probe(struct snd_wss *chip) case 7: break; default: - snd_printk("unknown CS4238B chip (enhanced version = 0x%x)\n", id); + snd_printk(KERN_WARNING + "unknown CS4238B chip " + "(enhanced version = 0x%x)\n", + id); } } else if ((id & 0x1f) == 0x1e) { /* CS4239 */ chip->hardware = WSS_HW_CS4239; @@ -1384,10 +1407,15 @@ static int snd_wss_probe(struct snd_wss *chip) case 6: break; default: - snd_printk("unknown CS4239 chip (enhanced version = 0x%x)\n", id); + snd_printk(KERN_WARNING + "unknown CS4239 chip " + "(enhanced version = 0x%x)\n", + id); } } else { - snd_printk("unknown CS4236/CS423xB chip (enhanced version = 0x%x)\n", id); + snd_printk(KERN_WARNING + "unknown CS4236/CS423xB chip " + "(enhanced version = 0x%x)\n", id); } } } @@ -1618,7 +1646,8 @@ static void snd_wss_resume(struct snd_wss *chip) wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); spin_unlock_irqrestore(&chip->reg_lock, flags); if (timeout == 0x80) - snd_printk("down [0x%lx]: serious init problem - codec still busy\n", chip->port); + snd_printk(KERN_ERR "down [0x%lx]: serious init problem " + "- codec still busy\n", chip->port); if ((timeout & CS4231_MCE) == 0 || !(chip->hardware & (WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK))) { return; @@ -1820,7 +1849,8 @@ int snd_wss_create(struct snd_card *card, #if 0 if (chip->hardware & WSS_HW_CS4232_MASK) { if (chip->res_cport == NULL) - snd_printk("CS4232 control port features are not accessible\n"); + snd_printk(KERN_ERR "CS4232 control port features are " + "not accessible\n"); } #endif -- GitLab From 91f050604cc045a0b7aa0460d36eb6e0f0cb301a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 5 Feb 2009 15:46:48 +0100 Subject: [PATCH 1195/4982] ALSA: gus - Add missing KERN_* prefix to printk Signed-off-by: Takashi Iwai --- sound/isa/gus/gus_dma.c | 3 ++- sound/isa/gus/gus_irq.c | 6 ++++-- sound/isa/gus/gus_pcm.c | 26 ++++++++++++++++++++------ sound/isa/gus/gus_uart.c | 10 ++++++++-- sound/isa/gus/interwave.c | 16 +++++++++------- 5 files changed, 43 insertions(+), 18 deletions(-) diff --git a/sound/isa/gus/gus_dma.c b/sound/isa/gus/gus_dma.c index cf8cd3c26a5..36c27c83236 100644 --- a/sound/isa/gus/gus_dma.c +++ b/sound/isa/gus/gus_dma.c @@ -78,7 +78,8 @@ static void snd_gf1_dma_program(struct snd_gus_card * gus, snd_gf1_dma_ack(gus); snd_dma_program(gus->gf1.dma1, buf_addr, count, dma_cmd & SNDRV_GF1_DMA_READ ? DMA_MODE_READ : DMA_MODE_WRITE); #if 0 - snd_printk("address = 0x%x, count = 0x%x, dma_cmd = 0x%x\n", address << 1, count, dma_cmd); + snd_printk(KERN_DEBUG "address = 0x%x, count = 0x%x, dma_cmd = 0x%x\n", + address << 1, count, dma_cmd); #endif spin_lock_irqsave(&gus->reg_lock, flags); if (gus->gf1.enh_mode) { diff --git a/sound/isa/gus/gus_irq.c b/sound/isa/gus/gus_irq.c index 041894ddd01..2055aff71b5 100644 --- a/sound/isa/gus/gus_irq.c +++ b/sound/isa/gus/gus_irq.c @@ -41,7 +41,7 @@ __again: if (status == 0) return IRQ_RETVAL(handled); handled = 1; - // snd_printk("IRQ: status = 0x%x\n", status); + /* snd_printk(KERN_DEBUG "IRQ: status = 0x%x\n", status); */ if (status & 0x02) { STAT_ADD(gus->gf1.interrupt_stat_midi_in); if (gus->gf1.interrupt_handler_midi_in) @@ -65,7 +65,9 @@ __again: continue; /* multi request */ already |= _current_; /* mark request */ #if 0 - printk("voice = %i, voice_status = 0x%x, voice_verify = %i\n", voice, voice_status, inb(GUSP(gus, GF1PAGE))); + printk(KERN_DEBUG "voice = %i, voice_status = 0x%x, " + "voice_verify = %i\n", + voice, voice_status, inb(GUSP(gus, GF1PAGE))); #endif pvoice = &gus->gf1.voices[voice]; if (pvoice->use) { diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c index 38510aeb21c..edb11eefdfe 100644 --- a/sound/isa/gus/gus_pcm.c +++ b/sound/isa/gus/gus_pcm.c @@ -82,7 +82,10 @@ static int snd_gf1_pcm_block_change(struct snd_pcm_substream *substream, count += offset & 31; offset &= ~31; - // snd_printk("block change - offset = 0x%x, count = 0x%x\n", offset, count); + /* + snd_printk(KERN_DEBUG "block change - offset = 0x%x, count = 0x%x\n", + offset, count); + */ memset(&block, 0, sizeof(block)); block.cmd = SNDRV_GF1_DMA_IRQ; if (snd_pcm_format_unsigned(runtime->format)) @@ -135,7 +138,11 @@ static void snd_gf1_pcm_trigger_up(struct snd_pcm_substream *substream) curr = begin + (pcmp->bpos * pcmp->block_size) / runtime->channels; end = curr + (pcmp->block_size / runtime->channels); end -= snd_pcm_format_width(runtime->format) == 16 ? 2 : 1; - // snd_printk("init: curr=0x%x, begin=0x%x, end=0x%x, ctrl=0x%x, ramp=0x%x, rate=0x%x\n", curr, begin, end, voice_ctrl, ramp_ctrl, rate); + /* + snd_printk(KERN_DEBUG "init: curr=0x%x, begin=0x%x, end=0x%x, " + "ctrl=0x%x, ramp=0x%x, rate=0x%x\n", + curr, begin, end, voice_ctrl, ramp_ctrl, rate); + */ pan = runtime->channels == 2 ? (!voice ? 1 : 14) : 8; vol = !voice ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right; spin_lock_irqsave(&gus->reg_lock, flags); @@ -205,9 +212,11 @@ static void snd_gf1_pcm_interrupt_wave(struct snd_gus_card * gus, ramp_ctrl = (snd_gf1_read8(gus, SNDRV_GF1_VB_VOLUME_CONTROL) & ~0xa4) | 0x03; #if 0 snd_gf1_select_voice(gus, pvoice->number); - printk("position = 0x%x\n", (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4)); + printk(KERN_DEBUG "position = 0x%x\n", + (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4)); snd_gf1_select_voice(gus, pcmp->pvoices[1]->number); - printk("position = 0x%x\n", (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4)); + printk(KERN_DEBUG "position = 0x%x\n", + (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4)); snd_gf1_select_voice(gus, pvoice->number); #endif pcmp->bpos++; @@ -299,7 +308,11 @@ static int snd_gf1_pcm_poke_block(struct snd_gus_card *gus, unsigned char *buf, unsigned int len; unsigned long flags; - // printk("poke block; buf = 0x%x, pos = %i, count = %i, port = 0x%x\n", (int)buf, pos, count, gus->gf1.port); + /* + printk(KERN_DEBUG + "poke block; buf = 0x%x, pos = %i, count = %i, port = 0x%x\n", + (int)buf, pos, count, gus->gf1.port); + */ while (count > 0) { len = count; if (len > 512) /* limit, to allow IRQ */ @@ -680,7 +693,8 @@ static int snd_gf1_pcm_playback_open(struct snd_pcm_substream *substream) runtime->private_free = snd_gf1_pcm_playback_free; #if 0 - printk("playback.buffer = 0x%lx, gf1.pcm_buffer = 0x%lx\n", (long) pcm->playback.buffer, (long) gus->gf1.pcm_buffer); + printk(KERN_DEBUG "playback.buffer = 0x%lx, gf1.pcm_buffer = 0x%lx\n", + (long) pcm->playback.buffer, (long) gus->gf1.pcm_buffer); #endif if ((err = snd_gf1_dma_init(gus)) < 0) return err; diff --git a/sound/isa/gus/gus_uart.c b/sound/isa/gus/gus_uart.c index f0af3f79b08..21cc42e4c4b 100644 --- a/sound/isa/gus/gus_uart.c +++ b/sound/isa/gus/gus_uart.c @@ -129,8 +129,14 @@ static int snd_gf1_uart_input_open(struct snd_rawmidi_substream *substream) } spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); #if 0 - snd_printk("read init - enable = %i, cmd = 0x%x, stat = 0x%x\n", gus->uart_enable, gus->gf1.uart_cmd, snd_gf1_uart_stat(gus)); - snd_printk("[0x%x] reg (ctrl/status) = 0x%x, reg (data) = 0x%x (page = 0x%x)\n", gus->gf1.port + 0x100, inb(gus->gf1.port + 0x100), inb(gus->gf1.port + 0x101), inb(gus->gf1.port + 0x102)); + snd_printk(KERN_DEBUG + "read init - enable = %i, cmd = 0x%x, stat = 0x%x\n", + gus->uart_enable, gus->gf1.uart_cmd, snd_gf1_uart_stat(gus)); + snd_printk(KERN_DEBUG + "[0x%x] reg (ctrl/status) = 0x%x, reg (data) = 0x%x " + "(page = 0x%x)\n", + gus->gf1.port + 0x100, inb(gus->gf1.port + 0x100), + inb(gus->gf1.port + 0x101), inb(gus->gf1.port + 0x102)); #endif return 0; } diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index 5faecfb602d..418d49eef92 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c @@ -170,7 +170,7 @@ static void snd_interwave_i2c_setlines(struct snd_i2c_bus *bus, int ctrl, int da unsigned long port = bus->private_value; #if 0 - printk("i2c_setlines - 0x%lx <- %i,%i\n", port, ctrl, data); + printk(KERN_DEBUG "i2c_setlines - 0x%lx <- %i,%i\n", port, ctrl, data); #endif outb((data << 1) | ctrl, port); udelay(10); @@ -183,7 +183,7 @@ static int snd_interwave_i2c_getclockline(struct snd_i2c_bus *bus) res = inb(port) & 1; #if 0 - printk("i2c_getclockline - 0x%lx -> %i\n", port, res); + printk(KERN_DEBUG "i2c_getclockline - 0x%lx -> %i\n", port, res); #endif return res; } @@ -197,7 +197,7 @@ static int snd_interwave_i2c_getdataline(struct snd_i2c_bus *bus, int ack) udelay(10); res = (inb(port) & 2) >> 1; #if 0 - printk("i2c_getdataline - 0x%lx -> %i\n", port, res); + printk(KERN_DEBUG "i2c_getdataline - 0x%lx -> %i\n", port, res); #endif return res; } @@ -342,7 +342,8 @@ static void __devinit snd_interwave_bank_sizes(struct snd_gus_card * gus, int *s snd_gf1_poke(gus, local, d); snd_gf1_poke(gus, local + 1, d + 1); #if 0 - printk("d = 0x%x, local = 0x%x, local + 1 = 0x%x, idx << 22 = 0x%x\n", + printk(KERN_DEBUG "d = 0x%x, local = 0x%x, " + "local + 1 = 0x%x, idx << 22 = 0x%x\n", d, snd_gf1_peek(gus, local), snd_gf1_peek(gus, local + 1), @@ -356,7 +357,8 @@ static void __devinit snd_interwave_bank_sizes(struct snd_gus_card * gus, int *s } } #if 0 - printk("sizes: %i %i %i %i\n", sizes[0], sizes[1], sizes[2], sizes[3]); + printk(KERN_DEBUG "sizes: %i %i %i %i\n", + sizes[0], sizes[1], sizes[2], sizes[3]); #endif } @@ -410,12 +412,12 @@ static void __devinit snd_interwave_detect_memory(struct snd_gus_card * gus) lmct = (psizes[3] << 24) | (psizes[2] << 16) | (psizes[1] << 8) | psizes[0]; #if 0 - printk("lmct = 0x%08x\n", lmct); + printk(KERN_DEBUG "lmct = 0x%08x\n", lmct); #endif for (i = 0; i < ARRAY_SIZE(lmc); i++) if (lmct == lmc[i]) { #if 0 - printk("found !!! %i\n", i); + printk(KERN_DEBUG "found !!! %i\n", i); #endif snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xfff0) | i); snd_interwave_bank_sizes(gus, psizes); -- GitLab From 4c9f1d3ed7e5f910b66dc4d1456cfac17e58cf0e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 5 Feb 2009 15:47:51 +0100 Subject: [PATCH 1196/4982] ALSA: isa/*: Add missing KERN_* prefix to printk Signed-off-by: Takashi Iwai --- sound/isa/ad1816a/ad1816a_lib.c | 6 +++--- sound/isa/cs423x/cs4236_lib.c | 21 ++++++++++++------- sound/isa/es1688/es1688_lib.c | 23 +++++++++++++------- sound/isa/opl3sa2.c | 10 ++++++--- sound/isa/opti9xx/opti92x-ad1848.c | 30 +++++++++++++++------------ sound/isa/wavefront/wavefront.c | 4 ++-- sound/isa/wavefront/wavefront_synth.c | 2 +- 7 files changed, 59 insertions(+), 37 deletions(-) diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c index 1c9e01ecac0..05aef8b97e9 100644 --- a/sound/isa/ad1816a/ad1816a_lib.c +++ b/sound/isa/ad1816a/ad1816a_lib.c @@ -37,7 +37,7 @@ static inline int snd_ad1816a_busy_wait(struct snd_ad1816a *chip) if (inb(AD1816A_REG(AD1816A_CHIP_STATUS)) & AD1816A_READY) return 0; - snd_printk("chip busy.\n"); + snd_printk(KERN_WARNING "chip busy.\n"); return -EBUSY; } @@ -196,7 +196,7 @@ static int snd_ad1816a_trigger(struct snd_ad1816a *chip, unsigned char what, spin_unlock(&chip->lock); break; default: - snd_printk("invalid trigger mode 0x%x.\n", what); + snd_printk(KERN_WARNING "invalid trigger mode 0x%x.\n", what); error = -EINVAL; } @@ -565,7 +565,7 @@ static const char __devinit *snd_ad1816a_chip_id(struct snd_ad1816a *chip) case AD1816A_HW_AD1815: return "AD1815"; case AD1816A_HW_AD18MAX10: return "AD18max10"; default: - snd_printk("Unknown chip version %d:%d.\n", + snd_printk(KERN_WARNING "Unknown chip version %d:%d.\n", chip->version, chip->hardware); return "AD1816A - unknown"; } diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c index 6a85fdc53b6..2406efdfd8d 100644 --- a/sound/isa/cs423x/cs4236_lib.c +++ b/sound/isa/cs423x/cs4236_lib.c @@ -286,7 +286,8 @@ int snd_cs4236_create(struct snd_card *card, if (hardware == WSS_HW_DETECT) hardware = WSS_HW_DETECT3; if (cport < 0x100) { - snd_printk("please, specify control port for CS4236+ chips\n"); + snd_printk(KERN_ERR "please, specify control port " + "for CS4236+ chips\n"); return -ENODEV; } err = snd_wss_create(card, port, cport, @@ -295,7 +296,8 @@ int snd_cs4236_create(struct snd_card *card, return err; if (!(chip->hardware & WSS_HW_CS4236B_MASK)) { - snd_printk("CS4236+: MODE3 and extended registers not available, hardware=0x%x\n",chip->hardware); + snd_printk(KERN_ERR "CS4236+: MODE3 and extended registers " + "not available, hardware=0x%x\n", chip->hardware); snd_device_free(card, chip); return -ENODEV; } @@ -303,16 +305,19 @@ int snd_cs4236_create(struct snd_card *card, { int idx; for (idx = 0; idx < 8; idx++) - snd_printk("CD%i = 0x%x\n", idx, inb(chip->cport + idx)); + snd_printk(KERN_DEBUG "CD%i = 0x%x\n", + idx, inb(chip->cport + idx)); for (idx = 0; idx < 9; idx++) - snd_printk("C%i = 0x%x\n", idx, snd_cs4236_ctrl_in(chip, idx)); + snd_printk(KERN_DEBUG "C%i = 0x%x\n", + idx, snd_cs4236_ctrl_in(chip, idx)); } #endif ver1 = snd_cs4236_ctrl_in(chip, 1); ver2 = snd_cs4236_ext_in(chip, CS4236_VERSION); snd_printdd("CS4236: [0x%lx] C1 (version) = 0x%x, ext = 0x%x\n", cport, ver1, ver2); if (ver1 != ver2) { - snd_printk("CS4236+ chip detected, but control port 0x%lx is not valid\n", cport); + snd_printk(KERN_ERR "CS4236+ chip detected, but " + "control port 0x%lx is not valid\n", cport); snd_device_free(card, chip); return -ENODEV; } @@ -883,7 +888,8 @@ static int snd_cs4236_get_iec958_switch(struct snd_kcontrol *kcontrol, struct sn spin_lock_irqsave(&chip->reg_lock, flags); ucontrol->value.integer.value[0] = chip->image[CS4231_ALT_FEATURE_1] & 0x02 ? 1 : 0; #if 0 - printk("get valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n", + printk(KERN_DEBUG "get valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, " + "C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n", snd_wss_in(chip, CS4231_ALT_FEATURE_1), snd_cs4236_ctrl_in(chip, 3), snd_cs4236_ctrl_in(chip, 4), @@ -920,7 +926,8 @@ static int snd_cs4236_put_iec958_switch(struct snd_kcontrol *kcontrol, struct sn mutex_unlock(&chip->mce_mutex); #if 0 - printk("set valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n", + printk(KERN_DEBUG "set valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, " + "C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n", snd_wss_in(chip, CS4231_ALT_FEATURE_1), snd_cs4236_ctrl_in(chip, 3), snd_cs4236_ctrl_in(chip, 4), diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c index 4fbb508a817..4c6e14f87f2 100644 --- a/sound/isa/es1688/es1688_lib.c +++ b/sound/isa/es1688/es1688_lib.c @@ -45,7 +45,7 @@ static int snd_es1688_dsp_command(struct snd_es1688 *chip, unsigned char val) return 1; } #ifdef CONFIG_SND_DEBUG - printk("snd_es1688_dsp_command: timeout (0x%x)\n", val); + printk(KERN_DEBUG "snd_es1688_dsp_command: timeout (0x%x)\n", val); #endif return 0; } @@ -167,13 +167,16 @@ static int snd_es1688_probe(struct snd_es1688 *chip) hw = ES1688_HW_AUTO; switch (chip->version & 0xfff0) { case 0x4880: - snd_printk("[0x%lx] ESS: AudioDrive ES488 detected, but driver is in another place\n", chip->port); + snd_printk(KERN_ERR "[0x%lx] ESS: AudioDrive ES488 detected, " + "but driver is in another place\n", chip->port); return -ENODEV; case 0x6880: hw = (chip->version & 0x0f) >= 8 ? ES1688_HW_1688 : ES1688_HW_688; break; default: - snd_printk("[0x%lx] ESS: unknown AudioDrive chip with version 0x%x (Jazz16 soundcard?)\n", chip->port, chip->version); + snd_printk(KERN_ERR "[0x%lx] ESS: unknown AudioDrive chip " + "with version 0x%x (Jazz16 soundcard?)\n", + chip->port, chip->version); return -ENODEV; } @@ -223,7 +226,7 @@ static int snd_es1688_init(struct snd_es1688 * chip, int enable) } } #if 0 - snd_printk("mpu cfg = 0x%x\n", cfg); + snd_printk(KERN_DEBUG "mpu cfg = 0x%x\n", cfg); #endif spin_lock_irqsave(&chip->reg_lock, flags); snd_es1688_mixer_write(chip, 0x40, cfg); @@ -237,7 +240,9 @@ static int snd_es1688_init(struct snd_es1688 * chip, int enable) cfg = 0xf0; /* enable only DMA counter interrupt */ irq_bits = irqs[chip->irq & 0x0f]; if (irq_bits < 0) { - snd_printk("[0x%lx] ESS: bad IRQ %d for ES1688 chip!!\n", chip->port, chip->irq); + snd_printk(KERN_ERR "[0x%lx] ESS: bad IRQ %d " + "for ES1688 chip!!\n", + chip->port, chip->irq); #if 0 irq_bits = 0; cfg = 0x10; @@ -250,7 +255,8 @@ static int snd_es1688_init(struct snd_es1688 * chip, int enable) cfg = 0xf0; /* extended mode DMA enable */ dma = chip->dma8; if (dma > 3 || dma == 2) { - snd_printk("[0x%lx] ESS: bad DMA channel %d for ES1688 chip!!\n", chip->port, dma); + snd_printk(KERN_ERR "[0x%lx] ESS: bad DMA channel %d " + "for ES1688 chip!!\n", chip->port, dma); #if 0 dma_bits = 0; cfg = 0x00; /* disable all DMA */ @@ -341,8 +347,9 @@ static int snd_es1688_trigger(struct snd_es1688 *chip, int cmd, unsigned char va return -EINVAL; /* something is wrong */ } #if 0 - printk("trigger: val = 0x%x, value = 0x%x\n", val, value); - printk("trigger: pointer = 0x%x\n", snd_dma_pointer(chip->dma8, chip->dma_size)); + printk(KERN_DEBUG "trigger: val = 0x%x, value = 0x%x\n", val, value); + printk(KERN_DEBUG "trigger: pointer = 0x%x\n", + snd_dma_pointer(chip->dma8, chip->dma_size)); #endif snd_es1688_write(chip, 0xb8, (val & 0xf0) | value); spin_unlock(&chip->reg_lock); diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index 58c972b2af0..06810dfb9d9 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c @@ -179,12 +179,13 @@ static unsigned char __snd_opl3sa2_read(struct snd_opl3sa2 *chip, unsigned char unsigned char result; #if 0 outb(0x1d, port); /* password */ - printk("read [0x%lx] = 0x%x\n", port, inb(port)); + printk(KERN_DEBUG "read [0x%lx] = 0x%x\n", port, inb(port)); #endif outb(reg, chip->port); /* register */ result = inb(chip->port + 1); #if 0 - printk("read [0x%lx] = 0x%x [0x%x]\n", port, result, inb(port)); + printk(KERN_DEBUG "read [0x%lx] = 0x%x [0x%x]\n", + port, result, inb(port)); #endif return result; } @@ -233,7 +234,10 @@ static int __devinit snd_opl3sa2_detect(struct snd_card *card) snd_printk(KERN_ERR PFX "can't grab port 0x%lx\n", port); return -EBUSY; } - // snd_printk("REG 0A = 0x%x\n", snd_opl3sa2_read(chip, 0x0a)); + /* + snd_printk(KERN_DEBUG "REG 0A = 0x%x\n", + snd_opl3sa2_read(chip, 0x0a)); + */ chip->version = 0; tmp = snd_opl3sa2_read(chip, OPL3SA2_MISC); if (tmp == 0xff) { diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 5deb7e69a02..d5bc0e03132 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -252,7 +252,7 @@ static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip, #endif /* OPTi93X */ default: - snd_printk("chip %d not supported\n", hardware); + snd_printk(KERN_ERR "chip %d not supported\n", hardware); return -ENODEV; } return 0; @@ -294,7 +294,7 @@ static unsigned char snd_opti9xx_read(struct snd_opti9xx *chip, #endif /* OPTi93X */ default: - snd_printk("chip %d not supported\n", chip->hardware); + snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware); } spin_unlock_irqrestore(&chip->lock, flags); @@ -336,7 +336,7 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, #endif /* OPTi93X */ default: - snd_printk("chip %d not supported\n", chip->hardware); + snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware); } spin_unlock_irqrestore(&chip->lock, flags); @@ -412,7 +412,7 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip) #endif /* OPTi93X */ default: - snd_printk("chip %d not supported\n", chip->hardware); + snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware); return -EINVAL; } @@ -430,7 +430,8 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip) wss_base_bits = 0x02; break; default: - snd_printk("WSS port 0x%lx not valid\n", chip->wss_base); + snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", + chip->wss_base); goto __skip_base; } snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30); @@ -455,7 +456,7 @@ __skip_base: irq_bits = 0x04; break; default: - snd_printk("WSS irq # %d not valid\n", chip->irq); + snd_printk(KERN_WARNING "WSS irq # %d not valid\n", chip->irq); goto __skip_resources; } @@ -470,13 +471,14 @@ __skip_base: dma_bits = 0x03; break; default: - snd_printk("WSS dma1 # %d not valid\n", chip->dma1); + snd_printk(KERN_WARNING "WSS dma1 # %d not valid\n", + chip->dma1); goto __skip_resources; } #if defined(CS4231) || defined(OPTi93X) if (chip->dma1 == chip->dma2) { - snd_printk("don't want to share dmas\n"); + snd_printk(KERN_ERR "don't want to share dmas\n"); return -EBUSY; } @@ -485,7 +487,8 @@ __skip_base: case 1: break; default: - snd_printk("WSS dma2 # %d not valid\n", chip->dma2); + snd_printk(KERN_WARNING "WSS dma2 # %d not valid\n", + chip->dma2); goto __skip_resources; } dma_bits |= 0x04; @@ -516,7 +519,8 @@ __skip_resources: mpu_port_bits = 0x00; break; default: - snd_printk("MPU-401 port 0x%lx not valid\n", + snd_printk(KERN_WARNING + "MPU-401 port 0x%lx not valid\n", chip->mpu_port); goto __skip_mpu; } @@ -535,7 +539,7 @@ __skip_resources: mpu_irq_bits = 0x01; break; default: - snd_printk("MPU-401 irq # %d not valid\n", + snd_printk(KERN_WARNING "MPU-401 irq # %d not valid\n", chip->mpu_irq); goto __skip_mpu; } @@ -726,7 +730,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) if (chip->wss_base == SNDRV_AUTO_PORT) { chip->wss_base = snd_legacy_find_free_ioport(possible_ports, 4); if (chip->wss_base < 0) { - snd_printk("unable to find a free WSS port\n"); + snd_printk(KERN_ERR "unable to find a free WSS port\n"); return -EBUSY; } } @@ -891,7 +895,7 @@ static int __devinit snd_opti9xx_isa_probe(struct device *devptr, #if defined(CS4231) || defined(OPTi93X) if (dma2 == SNDRV_AUTO_DMA) { if ((dma2 = snd_legacy_find_free_dma(possible_dma2s[dma1 % 4])) < 0) { - snd_printk("unable to find a free DMA2\n"); + snd_printk(KERN_ERR "unable to find a free DMA2\n"); return -EBUSY; } } diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index 4c095bc7c72..c280e6220ae 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c @@ -551,11 +551,11 @@ static int __devinit snd_wavefront_isa_match(struct device *pdev, return 0; #endif if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) { - snd_printk("specify CS4232 port\n"); + snd_printk(KERN_ERR "specify CS4232 port\n"); return 0; } if (ics2115_port[dev] == SNDRV_AUTO_PORT) { - snd_printk("specify ICS2115 port\n"); + snd_printk(KERN_ERR "specify ICS2115 port\n"); return 0; } return 1; diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index 4c410820a99..beb312cca75 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c @@ -633,7 +633,7 @@ wavefront_get_sample_status (snd_wavefront_t *dev, int assume_rom) wbuf[1] = i >> 7; if (snd_wavefront_cmd (dev, WFC_IDENTIFY_SAMPLE_TYPE, rbuf, wbuf)) { - snd_printk("cannot identify sample " + snd_printk(KERN_WARNING "cannot identify sample " "type of slot %d\n", i); dev->sample_status[i] = WF_ST_EMPTY; continue; -- GitLab From 54530bded6ecf22d683423b66fc3cd6dddb249aa Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 5 Feb 2009 15:55:18 +0100 Subject: [PATCH 1197/4982] ALSA: usb - Add missing KERN_* prefix to printk Signed-off-by: Takashi Iwai --- sound/usb/usbaudio.c | 6 ++++-- sound/usb/usbmixer.c | 5 ++++- sound/usb/usx2y/usb_stream.c | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 4636926d12d..c69cc6e4f54 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -1419,9 +1419,11 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) subs->cur_audiofmt = fmt; #if 0 - printk("setting done: format = %d, rate = %d..%d, channels = %d\n", + printk(KERN_DEBUG + "setting done: format = %d, rate = %d..%d, channels = %d\n", fmt->format, fmt->rate_min, fmt->rate_max, fmt->channels); - printk(" datapipe = 0x%0x, syncpipe = 0x%0x\n", + printk(KERN_DEBUG + " datapipe = 0x%0x, syncpipe = 0x%0x\n", subs->datapipe, subs->syncpipe); #endif diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index 330f2fbff2d..6615cd3b407 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c @@ -222,7 +222,10 @@ static int check_ignored_ctl(struct mixer_build *state, int unitid, int control) for (p = state->map; p->id; p++) { if (p->id == unitid && ! p->name && (! control || ! p->control || control == p->control)) { - // printk("ignored control %d:%d\n", unitid, control); + /* + printk(KERN_DEBUG "ignored control %d:%d\n", + unitid, control); + */ return 1; } } diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c index 70b96355ca4..24393dafcb6 100644 --- a/sound/usb/usx2y/usb_stream.c +++ b/sound/usb/usx2y/usb_stream.c @@ -557,7 +557,7 @@ static void stream_start(struct usb_stream_kernel *sk, s->idle_insize -= max_diff - max_diff_0; s->idle_insize += urb_size - s->period_size; if (s->idle_insize < 0) { - snd_printk("%i %i %i\n", + snd_printk(KERN_WARNING "%i %i %i\n", s->idle_insize, urb_size, s->period_size); return; } else if (s->idle_insize == 0) { -- GitLab From 939778aedd9386e13051a9e1d57c14cba2b6ae13 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 5 Feb 2009 15:57:55 +0100 Subject: [PATCH 1198/4982] ALSA: hda - Add missing KERN_* prefix to printk ... and disable the annoying debug message. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 5218118f01b..d2812ab729c 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -8265,7 +8265,7 @@ static void alc888_6st_dell_unsol_event(struct hda_codec *codec, { switch (res >> 26) { case ALC880_HP_EVENT: - printk("hp_event\n"); + /* printk(KERN_DEBUG "hp_event\n"); */ alc888_6st_dell_front_automute(codec); break; } @@ -16564,7 +16564,7 @@ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, if (alc880_is_fixed_pin(pin)) { nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); - /* printk("DAC nid=%x\n",nid); */ + /* printk(KERN_DEBUG "DAC nid=%x\n",nid); */ /* specify the DAC as the extra output */ if (!spec->multiout.hp_nid) spec->multiout.hp_nid = nid; -- GitLab From 006de267351aa3d836f3307370eae7ec16eac09d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 5 Feb 2009 15:51:04 +0100 Subject: [PATCH 1199/4982] ALSA: Add missing KERN_* prefix to printk in sound/core Signed-off-by: Takashi Iwai --- sound/core/oss/pcm_oss.c | 49 ++++++++++++++++++----------- sound/core/oss/pcm_plugin.h | 4 +-- sound/core/pcm_native.c | 6 ++-- sound/core/seq/oss/seq_oss_device.h | 2 +- sound/core/seq/seq_prioq.c | 3 +- 5 files changed, 39 insertions(+), 25 deletions(-) diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index e17836680f4..4b883595a85 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -1160,9 +1160,11 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG if (runtime->status->state == SNDRV_PCM_STATE_XRUN) - printk("pcm_oss: write: recovering from XRUN\n"); + printk(KERN_DEBUG "pcm_oss: write: " + "recovering from XRUN\n"); else - printk("pcm_oss: write: recovering from SUSPEND\n"); + printk(KERN_DEBUG "pcm_oss: write: " + "recovering from SUSPEND\n"); #endif ret = snd_pcm_oss_prepare(substream); if (ret < 0) @@ -1196,9 +1198,11 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG if (runtime->status->state == SNDRV_PCM_STATE_XRUN) - printk("pcm_oss: read: recovering from XRUN\n"); + printk(KERN_DEBUG "pcm_oss: read: " + "recovering from XRUN\n"); else - printk("pcm_oss: read: recovering from SUSPEND\n"); + printk(KERN_DEBUG "pcm_oss: read: " + "recovering from SUSPEND\n"); #endif ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); if (ret < 0) @@ -1242,9 +1246,11 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG if (runtime->status->state == SNDRV_PCM_STATE_XRUN) - printk("pcm_oss: writev: recovering from XRUN\n"); + printk(KERN_DEBUG "pcm_oss: writev: " + "recovering from XRUN\n"); else - printk("pcm_oss: writev: recovering from SUSPEND\n"); + printk(KERN_DEBUG "pcm_oss: writev: " + "recovering from SUSPEND\n"); #endif ret = snd_pcm_oss_prepare(substream); if (ret < 0) @@ -1278,9 +1284,11 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void * runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG if (runtime->status->state == SNDRV_PCM_STATE_XRUN) - printk("pcm_oss: readv: recovering from XRUN\n"); + printk(KERN_DEBUG "pcm_oss: readv: " + "recovering from XRUN\n"); else - printk("pcm_oss: readv: recovering from SUSPEND\n"); + printk(KERN_DEBUG "pcm_oss: readv: " + "recovering from SUSPEND\n"); #endif ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); if (ret < 0) @@ -1533,7 +1541,7 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size) init_waitqueue_entry(&wait, current); add_wait_queue(&runtime->sleep, &wait); #ifdef OSS_DEBUG - printk("sync1: size = %li\n", size); + printk(KERN_DEBUG "sync1: size = %li\n", size); #endif while (1) { result = snd_pcm_oss_write2(substream, runtime->oss.buffer, size, 1); @@ -1590,7 +1598,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) mutex_lock(&runtime->oss.params_lock); if (runtime->oss.buffer_used > 0) { #ifdef OSS_DEBUG - printk("sync: buffer_used\n"); + printk(KERN_DEBUG "sync: buffer_used\n"); #endif size = (8 * (runtime->oss.period_bytes - runtime->oss.buffer_used) + 7) / width; snd_pcm_format_set_silence(format, @@ -1603,7 +1611,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) } } else if (runtime->oss.period_ptr > 0) { #ifdef OSS_DEBUG - printk("sync: period_ptr\n"); + printk(KERN_DEBUG "sync: period_ptr\n"); #endif size = runtime->oss.period_bytes - runtime->oss.period_ptr; snd_pcm_format_set_silence(format, @@ -1952,7 +1960,7 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr int err, cmd; #ifdef OSS_DEBUG - printk("pcm_oss: trigger = 0x%x\n", trigger); + printk(KERN_DEBUG "pcm_oss: trigger = 0x%x\n", trigger); #endif psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; @@ -2170,7 +2178,9 @@ static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stre } #ifdef OSS_DEBUG - printk("pcm_oss: space: bytes = %i, fragments = %i, fragstotal = %i, fragsize = %i\n", info.bytes, info.fragments, info.fragstotal, info.fragsize); + printk(KERN_DEBUG "pcm_oss: space: bytes = %i, fragments = %i, " + "fragstotal = %i, fragsize = %i\n", + info.bytes, info.fragments, info.fragstotal, info.fragsize); #endif if (copy_to_user(_info, &info, sizeof(info))) return -EFAULT; @@ -2473,7 +2483,7 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long if (((cmd >> 8) & 0xff) != 'P') return -EINVAL; #ifdef OSS_DEBUG - printk("pcm_oss: ioctl = 0x%x\n", cmd); + printk(KERN_DEBUG "pcm_oss: ioctl = 0x%x\n", cmd); #endif switch (cmd) { case SNDCTL_DSP_RESET: @@ -2627,7 +2637,8 @@ static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t coun #else { ssize_t res = snd_pcm_oss_read1(substream, buf, count); - printk("pcm_oss: read %li bytes (returned %li bytes)\n", (long)count, (long)res); + printk(KERN_DEBUG "pcm_oss: read %li bytes " + "(returned %li bytes)\n", (long)count, (long)res); return res; } #endif @@ -2646,7 +2657,8 @@ static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size substream->f_flags = file->f_flags & O_NONBLOCK; result = snd_pcm_oss_write1(substream, buf, count); #ifdef OSS_DEBUG - printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result); + printk(KERN_DEBUG "pcm_oss: write %li bytes (wrote %li bytes)\n", + (long)count, (long)result); #endif return result; } @@ -2720,7 +2732,7 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area) int err; #ifdef OSS_DEBUG - printk("pcm_oss: mmap begin\n"); + printk(KERN_DEBUG "pcm_oss: mmap begin\n"); #endif pcm_oss_file = file->private_data; switch ((area->vm_flags & (VM_READ | VM_WRITE))) { @@ -2770,7 +2782,8 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area) runtime->silence_threshold = 0; runtime->silence_size = 0; #ifdef OSS_DEBUG - printk("pcm_oss: mmap ok, bytes = 0x%x\n", runtime->oss.mmap_bytes); + printk(KERN_DEBUG "pcm_oss: mmap ok, bytes = 0x%x\n", + runtime->oss.mmap_bytes); #endif /* In mmap mode we never stop */ runtime->stop_threshold = runtime->boundary; diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h index ca2f4c39be4..b9afab60371 100644 --- a/sound/core/oss/pcm_plugin.h +++ b/sound/core/oss/pcm_plugin.h @@ -176,9 +176,9 @@ static inline int snd_pcm_plug_slave_format(int format, struct snd_mask *format_ #endif #ifdef PLUGIN_DEBUG -#define pdprintf( fmt, args... ) printk( "plugin: " fmt, ##args) +#define pdprintf(fmt, args...) printk(KERN_DEBUG "plugin: " fmt, ##args) #else -#define pdprintf( fmt, args... ) +#define pdprintf(fmt, args...) #endif #endif /* __PCM_PLUGIN_H */ diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index a789efc9df3..d9b8f537942 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -186,7 +186,7 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream, if (!(params->rmask & (1 << k))) continue; #ifdef RULES_DEBUG - printk("%s = ", snd_pcm_hw_param_names[k]); + printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]); printk("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]); #endif changed = snd_mask_refine(m, constrs_mask(constrs, k)); @@ -206,7 +206,7 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream, if (!(params->rmask & (1 << k))) continue; #ifdef RULES_DEBUG - printk("%s = ", snd_pcm_hw_param_names[k]); + printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]); if (i->empty) printk("empty"); else @@ -251,7 +251,7 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream, if (!doit) continue; #ifdef RULES_DEBUG - printk("Rule %d [%p]: ", k, r->func); + printk(KERN_DEBUG "Rule %d [%p]: ", k, r->func); if (r->var >= 0) { printk("%s = ", snd_pcm_hw_param_names[r->var]); if (hw_is_mask(r->var)) { diff --git a/sound/core/seq/oss/seq_oss_device.h b/sound/core/seq/oss/seq_oss_device.h index bf8d2b4cb15..c0154a959d5 100644 --- a/sound/core/seq/oss/seq_oss_device.h +++ b/sound/core/seq/oss/seq_oss_device.h @@ -181,7 +181,7 @@ char *enabled_str(int bool); /* for debug */ #ifdef SNDRV_SEQ_OSS_DEBUG extern int seq_oss_debug; -#define debug_printk(x) do { if (seq_oss_debug > 0) snd_printk x; } while (0) +#define debug_printk(x) do { if (seq_oss_debug > 0) snd_printd x; } while (0) #else #define debug_printk(x) /**/ #endif diff --git a/sound/core/seq/seq_prioq.c b/sound/core/seq/seq_prioq.c index 0101a8b99b7..29896ab2340 100644 --- a/sound/core/seq/seq_prioq.c +++ b/sound/core/seq/seq_prioq.c @@ -321,7 +321,8 @@ void snd_seq_prioq_leave(struct snd_seq_prioq * f, int client, int timestamp) freeprev = cell; } else { #if 0 - printk("type = %i, source = %i, dest = %i, client = %i\n", + printk(KERN_DEBUG "type = %i, source = %i, dest = %i, " + "client = %i\n", cell->event.type, cell->event.source.client, cell->event.dest.client, -- GitLab From 45203832df2fa9e94ca0a249ddb20d2b077e58cc Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 5 Feb 2009 15:51:50 +0100 Subject: [PATCH 1200/4982] ALSA: Add missing KERN_* prefix to printk in sound/drivers Signed-off-by: Takashi Iwai --- sound/drivers/mtpav.c | 12 +++++++----- sound/drivers/mts64.c | 2 +- sound/drivers/opl3/opl3_lib.c | 2 +- sound/drivers/opl3/opl3_midi.c | 30 +++++++++++++++--------------- sound/drivers/opl3/opl3_oss.c | 8 +++++--- sound/drivers/opl3/opl3_synth.c | 2 +- sound/drivers/pcsp/pcsp.c | 2 +- sound/drivers/serial-u16550.c | 18 ++++++++++++------ sound/drivers/virmidi.c | 4 +++- sound/drivers/vx/vx_core.c | 3 ++- 10 files changed, 48 insertions(+), 35 deletions(-) diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c index 5b89c0883d6..6b26305ff0e 100644 --- a/sound/drivers/mtpav.c +++ b/sound/drivers/mtpav.c @@ -303,8 +303,10 @@ static void snd_mtpav_output_port_write(struct mtpav *mtp_card, snd_mtpav_send_byte(mtp_card, 0xf5); snd_mtpav_send_byte(mtp_card, portp->hwport); - //snd_printk("new outport: 0x%x\n", (unsigned int) portp->hwport); - + /* + snd_printk(KERN_DEBUG "new outport: 0x%x\n", + (unsigned int) portp->hwport); + */ if (!(outbyte & 0x80) && portp->running_status) snd_mtpav_send_byte(mtp_card, portp->running_status); } @@ -540,7 +542,7 @@ static void snd_mtpav_read_bytes(struct mtpav *mcrd) u8 sbyt = snd_mtpav_getreg(mcrd, SREG); - //printk("snd_mtpav_read_bytes() sbyt: 0x%x\n", sbyt); + /* printk(KERN_DEBUG "snd_mtpav_read_bytes() sbyt: 0x%x\n", sbyt); */ if (!(sbyt & SIGS_BYTE)) return; @@ -585,12 +587,12 @@ static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id) static int __devinit snd_mtpav_get_ISA(struct mtpav * mcard) { if ((mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI")) == NULL) { - snd_printk("MTVAP port 0x%lx is busy\n", port); + snd_printk(KERN_ERR "MTVAP port 0x%lx is busy\n", port); return -EBUSY; } mcard->port = port; if (request_irq(irq, snd_mtpav_irqh, IRQF_DISABLED, "MOTU MTPAV", mcard)) { - snd_printk("MTVAP IRQ %d busy\n", irq); + snd_printk(KERN_ERR "MTVAP IRQ %d busy\n", irq); return -EBUSY; } mcard->irq = irq; diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c index 87ba1ddc011..1a05b2d64c9 100644 --- a/sound/drivers/mts64.c +++ b/sound/drivers/mts64.c @@ -1015,7 +1015,7 @@ static int __devinit snd_mts64_probe(struct platform_device *pdev) goto __err; } - snd_printk("ESI Miditerminal 4140 on 0x%lx\n", p->base); + snd_printk(KERN_INFO "ESI Miditerminal 4140 on 0x%lx\n", p->base); return 0; __err: diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c index 780582340fe..6e31e46ca39 100644 --- a/sound/drivers/opl3/opl3_lib.c +++ b/sound/drivers/opl3/opl3_lib.c @@ -302,7 +302,7 @@ void snd_opl3_interrupt(struct snd_hwdep * hw) opl3 = hw->private_data; status = inb(opl3->l_port); #if 0 - snd_printk("AdLib IRQ status = 0x%x\n", status); + snd_printk(KERN_DEBUG "AdLib IRQ status = 0x%x\n", status); #endif if (!(status & 0x80)) return; diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c index 16feafa2c51..6e7d09ae0e8 100644 --- a/sound/drivers/opl3/opl3_midi.c +++ b/sound/drivers/opl3/opl3_midi.c @@ -125,7 +125,7 @@ static void debug_alloc(struct snd_opl3 *opl3, char *s, int voice) { int i; char *str = "x.24"; - printk("time %.5i: %s [%.2i]: ", opl3->use_time, s, voice); + printk(KERN_DEBUG "time %.5i: %s [%.2i]: ", opl3->use_time, s, voice); for (i = 0; i < opl3->max_voices; i++) printk("%c", *(str + opl3->voices[i].state + 1)); printk("\n"); @@ -218,7 +218,7 @@ static int opl3_get_voice(struct snd_opl3 *opl3, int instr_4op, for (i = 0; i < END; i++) { if (best[i].voice >= 0) { #ifdef DEBUG_ALLOC - printk("%s %iop allocation on voice %i\n", + printk(KERN_DEBUG "%s %iop allocation on voice %i\n", alloc_type[i], instr_4op ? 4 : 2, best[i].voice); #endif @@ -317,7 +317,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) opl3 = p; #ifdef DEBUG_MIDI - snd_printk("Note on, ch %i, inst %i, note %i, vel %i\n", + snd_printk(KERN_DEBUG "Note on, ch %i, inst %i, note %i, vel %i\n", chan->number, chan->midi_program, note, vel); #endif @@ -372,7 +372,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) return; } #ifdef DEBUG_MIDI - snd_printk(" --> OPL%i instrument: %s\n", + snd_printk(KERN_DEBUG " --> OPL%i instrument: %s\n", instr_4op ? 3 : 2, patch->name); #endif /* in SYNTH mode, application takes care of voices */ @@ -431,7 +431,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) } #ifdef DEBUG_MIDI - snd_printk(" --> setting OPL3 connection: 0x%x\n", + snd_printk(KERN_DEBUG " --> setting OPL3 connection: 0x%x\n", opl3->connection_reg); #endif /* @@ -466,7 +466,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) /* Program the FM voice characteristics */ for (i = 0; i < (instr_4op ? 4 : 2); i++) { #ifdef DEBUG_MIDI - snd_printk(" --> programming operator %i\n", i); + snd_printk(KERN_DEBUG " --> programming operator %i\n", i); #endif op_offset = snd_opl3_regmap[voice_offset][i]; @@ -546,7 +546,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) blocknum |= OPL3_KEYON_BIT; #ifdef DEBUG_MIDI - snd_printk(" --> trigger voice %i\n", voice); + snd_printk(KERN_DEBUG " --> trigger voice %i\n", voice); #endif /* Set OPL3 KEYON_BLOCK register of requested voice */ opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); @@ -602,7 +602,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) prg = extra_prg - 1; } #ifdef DEBUG_MIDI - snd_printk(" *** allocating extra program\n"); + snd_printk(KERN_DEBUG " *** allocating extra program\n"); #endif goto __extra_prg; } @@ -633,7 +633,7 @@ static void snd_opl3_kill_voice(struct snd_opl3 *opl3, int voice) /* kill voice */ #ifdef DEBUG_MIDI - snd_printk(" --> kill voice %i\n", voice); + snd_printk(KERN_DEBUG " --> kill voice %i\n", voice); #endif opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); /* clear Key ON bit */ @@ -670,7 +670,7 @@ void snd_opl3_note_off(void *p, int note, int vel, struct snd_midi_channel *chan opl3 = p; #ifdef DEBUG_MIDI - snd_printk("Note off, ch %i, inst %i, note %i\n", + snd_printk(KERN_DEBUG "Note off, ch %i, inst %i, note %i\n", chan->number, chan->midi_program, note); #endif @@ -709,7 +709,7 @@ void snd_opl3_key_press(void *p, int note, int vel, struct snd_midi_channel *cha opl3 = p; #ifdef DEBUG_MIDI - snd_printk("Key pressure, ch#: %i, inst#: %i\n", + snd_printk(KERN_DEBUG "Key pressure, ch#: %i, inst#: %i\n", chan->number, chan->midi_program); #endif } @@ -723,7 +723,7 @@ void snd_opl3_terminate_note(void *p, int note, struct snd_midi_channel *chan) opl3 = p; #ifdef DEBUG_MIDI - snd_printk("Terminate note, ch#: %i, inst#: %i\n", + snd_printk(KERN_DEBUG "Terminate note, ch#: %i, inst#: %i\n", chan->number, chan->midi_program); #endif } @@ -812,7 +812,7 @@ void snd_opl3_control(void *p, int type, struct snd_midi_channel *chan) opl3 = p; #ifdef DEBUG_MIDI - snd_printk("Controller, TYPE = %i, ch#: %i, inst#: %i\n", + snd_printk(KERN_DEBUG "Controller, TYPE = %i, ch#: %i, inst#: %i\n", type, chan->number, chan->midi_program); #endif @@ -849,7 +849,7 @@ void snd_opl3_nrpn(void *p, struct snd_midi_channel *chan, opl3 = p; #ifdef DEBUG_MIDI - snd_printk("NRPN, ch#: %i, inst#: %i\n", + snd_printk(KERN_DEBUG "NRPN, ch#: %i, inst#: %i\n", chan->number, chan->midi_program); #endif } @@ -864,6 +864,6 @@ void snd_opl3_sysex(void *p, unsigned char *buf, int len, opl3 = p; #ifdef DEBUG_MIDI - snd_printk("SYSEX\n"); + snd_printk(KERN_DEBUG "SYSEX\n"); #endif } diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c index 9a2271dc046..a54b1dc5cc7 100644 --- a/sound/drivers/opl3/opl3_oss.c +++ b/sound/drivers/opl3/opl3_oss.c @@ -220,14 +220,14 @@ static int snd_opl3_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, return -EINVAL; if (count < (int)sizeof(sbi)) { - snd_printk("FM Error: Patch record too short\n"); + snd_printk(KERN_ERR "FM Error: Patch record too short\n"); return -EINVAL; } if (copy_from_user(&sbi, buf, sizeof(sbi))) return -EFAULT; if (sbi.channel < 0 || sbi.channel >= SBFM_MAXINSTR) { - snd_printk("FM Error: Invalid instrument number %d\n", + snd_printk(KERN_ERR "FM Error: Invalid instrument number %d\n", sbi.channel); return -EINVAL; } @@ -254,7 +254,9 @@ static int snd_opl3_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd, opl3 = arg->private_data; switch (cmd) { case SNDCTL_FM_LOAD_INSTR: - snd_printk("OPL3: Obsolete ioctl(SNDCTL_FM_LOAD_INSTR) used. Fix the program.\n"); + snd_printk(KERN_ERR "OPL3: " + "Obsolete ioctl(SNDCTL_FM_LOAD_INSTR) used. " + "Fix the program.\n"); return -EINVAL; case SNDCTL_SYNTH_MEMAVL: diff --git a/sound/drivers/opl3/opl3_synth.c b/sound/drivers/opl3/opl3_synth.c index 962bb9c8b9c..6d57b6441de 100644 --- a/sound/drivers/opl3/opl3_synth.c +++ b/sound/drivers/opl3/opl3_synth.c @@ -168,7 +168,7 @@ int snd_opl3_ioctl(struct snd_hwdep * hw, struct file *file, #ifdef CONFIG_SND_DEBUG default: - snd_printk("unknown IOCTL: 0x%x\n", cmd); + snd_printk(KERN_WARNING "unknown IOCTL: 0x%x\n", cmd); #endif } return -ENOTTY; diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c index a4049eb94d3..c7c744c6fc0 100644 --- a/sound/drivers/pcsp/pcsp.c +++ b/sound/drivers/pcsp/pcsp.c @@ -57,7 +57,7 @@ static int __devinit snd_pcsp_create(struct snd_card *card) else min_div = MAX_DIV; #if PCSP_DEBUG - printk("PCSP: lpj=%li, min_div=%i, res=%li\n", + printk(KERN_DEBUG "PCSP: lpj=%li, min_div=%i, res=%li\n", loops_per_jiffy, min_div, tp.tv_nsec); #endif diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index d8aab9da97c..ff0a4151094 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c @@ -241,7 +241,8 @@ static void snd_uart16550_io_loop(struct snd_uart16550 * uart) snd_rawmidi_receive(uart->midi_input[substream], &c, 1); if (status & UART_LSR_OE) - snd_printk("%s: Overrun on device at 0x%lx\n", + snd_printk(KERN_WARNING + "%s: Overrun on device at 0x%lx\n", uart->rmidi->name, uart->base); } @@ -636,7 +637,8 @@ static int snd_uart16550_output_byte(struct snd_uart16550 *uart, } } else { if (!snd_uart16550_write_buffer(uart, midi_byte)) { - snd_printk("%s: Buffer overrun on device at 0x%lx\n", + snd_printk(KERN_WARNING + "%s: Buffer overrun on device at 0x%lx\n", uart->rmidi->name, uart->base); return 0; } @@ -815,7 +817,8 @@ static int __devinit snd_uart16550_create(struct snd_card *card, if (irq >= 0 && irq != SNDRV_AUTO_IRQ) { if (request_irq(irq, snd_uart16550_interrupt, IRQF_DISABLED, "Serial MIDI", uart)) { - snd_printk("irq %d busy. Using Polling.\n", irq); + snd_printk(KERN_WARNING + "irq %d busy. Using Polling.\n", irq); } else { uart->irq = irq; } @@ -919,19 +922,22 @@ static int __devinit snd_serial_probe(struct platform_device *devptr) case SNDRV_SERIAL_GENERIC: break; default: - snd_printk("Adaptor type is out of range 0-%d (%d)\n", + snd_printk(KERN_ERR + "Adaptor type is out of range 0-%d (%d)\n", SNDRV_SERIAL_MAX_ADAPTOR, adaptor[dev]); return -ENODEV; } if (outs[dev] < 1 || outs[dev] > SNDRV_SERIAL_MAX_OUTS) { - snd_printk("Count of outputs is out of range 1-%d (%d)\n", + snd_printk(KERN_ERR + "Count of outputs is out of range 1-%d (%d)\n", SNDRV_SERIAL_MAX_OUTS, outs[dev]); return -ENODEV; } if (ins[dev] < 1 || ins[dev] > SNDRV_SERIAL_MAX_INS) { - snd_printk("Count of inputs is out of range 1-%d (%d)\n", + snd_printk(KERN_ERR + "Count of inputs is out of range 1-%d (%d)\n", SNDRV_SERIAL_MAX_INS, ins[dev]); return -ENODEV; } diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c index f79e3614079..1022e365606 100644 --- a/sound/drivers/virmidi.c +++ b/sound/drivers/virmidi.c @@ -98,7 +98,9 @@ static int __devinit snd_virmidi_probe(struct platform_device *devptr) vmidi->card = card; if (midi_devs[dev] > MAX_MIDI_DEVICES) { - snd_printk("too much midi devices for virmidi %d: force to use %d\n", dev, MAX_MIDI_DEVICES); + snd_printk(KERN_WARNING + "too much midi devices for virmidi %d: " + "force to use %d\n", dev, MAX_MIDI_DEVICES); midi_devs[dev] = MAX_MIDI_DEVICES; } for (idx = 0; idx < midi_devs[dev]; idx++) { diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c index 14e3354be43..19c6e376c7c 100644 --- a/sound/drivers/vx/vx_core.c +++ b/sound/drivers/vx/vx_core.c @@ -688,7 +688,8 @@ int snd_vx_dsp_load(struct vx_core *chip, const struct firmware *dsp) image = dsp->data + i; /* Wait DSP ready for a new read */ if ((err = vx_wait_isr_bit(chip, ISR_TX_EMPTY)) < 0) { - printk("dsp loading error at position %d\n", i); + printk(KERN_ERR + "dsp loading error at position %d\n", i); return err; } cptr = image; -- GitLab From 42b0158bdb1344b05cc1e98c363fba9e97137565 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 5 Feb 2009 16:01:46 +0100 Subject: [PATCH 1201/4982] ALSA: emux - Add missing KERN_* prefix to printk Signed-off-by: Takashi Iwai --- sound/synth/emux/emux_oss.c | 2 +- sound/synth/emux/emux_seq.c | 16 ++++++++-------- sound/synth/emux/emux_synth.c | 6 ++++-- sound/synth/emux/soundfont.c | 28 +++++++++++++++++----------- 4 files changed, 30 insertions(+), 22 deletions(-) diff --git a/sound/synth/emux/emux_oss.c b/sound/synth/emux/emux_oss.c index 5c47b6c0926..87e42206c4e 100644 --- a/sound/synth/emux/emux_oss.c +++ b/sound/synth/emux/emux_oss.c @@ -132,7 +132,7 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) p = snd_emux_create_port(emu, tmpname, 32, 1, &callback); if (p == NULL) { - snd_printk("can't create port\n"); + snd_printk(KERN_ERR "can't create port\n"); snd_emux_dec_count(emu); mutex_unlock(&emu->register_mutex); return -ENOMEM; diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c index 335aa2ce257..ca5f7effb4d 100644 --- a/sound/synth/emux/emux_seq.c +++ b/sound/synth/emux/emux_seq.c @@ -74,15 +74,15 @@ snd_emux_init_seq(struct snd_emux *emu, struct snd_card *card, int index) emu->client = snd_seq_create_kernel_client(card, index, "%s WaveTable", emu->name); if (emu->client < 0) { - snd_printk("can't create client\n"); + snd_printk(KERN_ERR "can't create client\n"); return -ENODEV; } if (emu->num_ports < 0) { - snd_printk("seqports must be greater than zero\n"); + snd_printk(KERN_WARNING "seqports must be greater than zero\n"); emu->num_ports = 1; } else if (emu->num_ports >= SNDRV_EMUX_MAX_PORTS) { - snd_printk("too many ports." + snd_printk(KERN_WARNING "too many ports." "limited max. ports %d\n", SNDRV_EMUX_MAX_PORTS); emu->num_ports = SNDRV_EMUX_MAX_PORTS; } @@ -100,7 +100,7 @@ snd_emux_init_seq(struct snd_emux *emu, struct snd_card *card, int index) p = snd_emux_create_port(emu, tmpname, MIDI_CHANNELS, 0, &pinfo); if (p == NULL) { - snd_printk("can't create port\n"); + snd_printk(KERN_ERR "can't create port\n"); return -ENOMEM; } @@ -147,12 +147,12 @@ snd_emux_create_port(struct snd_emux *emu, char *name, /* Allocate structures for this channel */ if ((p = kzalloc(sizeof(*p), GFP_KERNEL)) == NULL) { - snd_printk("no memory\n"); + snd_printk(KERN_ERR "no memory\n"); return NULL; } p->chset.channels = kcalloc(max_channels, sizeof(struct snd_midi_channel), GFP_KERNEL); if (p->chset.channels == NULL) { - snd_printk("no memory\n"); + snd_printk(KERN_ERR "no memory\n"); kfree(p); return NULL; } @@ -376,12 +376,12 @@ int snd_emux_init_virmidi(struct snd_emux *emu, struct snd_card *card) goto __error; } emu->vmidi[i] = rmidi; - //snd_printk("virmidi %d ok\n", i); + /* snd_printk(KERN_DEBUG "virmidi %d ok\n", i); */ } return 0; __error: - //snd_printk("error init..\n"); + /* snd_printk(KERN_DEBUG "error init..\n"); */ snd_emux_delete_virmidi(emu); return -ENOMEM; } diff --git a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c index 2cc6f6f7906..3e921b386fd 100644 --- a/sound/synth/emux/emux_synth.c +++ b/sound/synth/emux/emux_synth.c @@ -956,7 +956,8 @@ void snd_emux_lock_voice(struct snd_emux *emu, int voice) if (emu->voices[voice].state == SNDRV_EMUX_ST_OFF) emu->voices[voice].state = SNDRV_EMUX_ST_LOCKED; else - snd_printk("invalid voice for lock %d (state = %x)\n", + snd_printk(KERN_WARNING + "invalid voice for lock %d (state = %x)\n", voice, emu->voices[voice].state); spin_unlock_irqrestore(&emu->voice_lock, flags); } @@ -973,7 +974,8 @@ void snd_emux_unlock_voice(struct snd_emux *emu, int voice) if (emu->voices[voice].state == SNDRV_EMUX_ST_LOCKED) emu->voices[voice].state = SNDRV_EMUX_ST_OFF; else - snd_printk("invalid voice for unlock %d (state = %x)\n", + snd_printk(KERN_WARNING + "invalid voice for unlock %d (state = %x)\n", voice, emu->voices[voice].state); spin_unlock_irqrestore(&emu->voice_lock, flags); } diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c index 36d53bd317e..63c8f45c0c2 100644 --- a/sound/synth/emux/soundfont.c +++ b/sound/synth/emux/soundfont.c @@ -133,7 +133,7 @@ snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data, int rc; if (count < (long)sizeof(patch)) { - snd_printk("patch record too small %ld\n", count); + snd_printk(KERN_ERR "patch record too small %ld\n", count); return -EINVAL; } if (copy_from_user(&patch, data, sizeof(patch))) @@ -143,15 +143,16 @@ snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data, data += sizeof(patch); if (patch.key != SNDRV_OSS_SOUNDFONT_PATCH) { - snd_printk("'The wrong kind of patch' %x\n", patch.key); + snd_printk(KERN_ERR "The wrong kind of patch %x\n", patch.key); return -EINVAL; } if (count < patch.len) { - snd_printk("Patch too short %ld, need %d\n", count, patch.len); + snd_printk(KERN_ERR "Patch too short %ld, need %d\n", + count, patch.len); return -EINVAL; } if (patch.len < 0) { - snd_printk("poor length %d\n", patch.len); + snd_printk(KERN_ERR "poor length %d\n", patch.len); return -EINVAL; } @@ -195,7 +196,8 @@ snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data, case SNDRV_SFNT_REMOVE_INFO: /* patch must be opened */ if (!sflist->currsf) { - snd_printk("soundfont: remove_info: patch not opened\n"); + snd_printk(KERN_ERR "soundfont: remove_info: " + "patch not opened\n"); rc = -EINVAL; } else { int bank, instr; @@ -531,7 +533,7 @@ load_info(struct snd_sf_list *sflist, const void __user *data, long count) return -EINVAL; if (count < (long)sizeof(hdr)) { - printk("Soundfont error: invalid patch zone length\n"); + printk(KERN_ERR "Soundfont error: invalid patch zone length\n"); return -EINVAL; } if (copy_from_user((char*)&hdr, data, sizeof(hdr))) @@ -541,12 +543,14 @@ load_info(struct snd_sf_list *sflist, const void __user *data, long count) count -= sizeof(hdr); if (hdr.nvoices <= 0 || hdr.nvoices >= 100) { - printk("Soundfont error: Illegal voice number %d\n", hdr.nvoices); + printk(KERN_ERR "Soundfont error: Illegal voice number %d\n", + hdr.nvoices); return -EINVAL; } if (count < (long)sizeof(struct soundfont_voice_info) * hdr.nvoices) { - printk("Soundfont Error: patch length(%ld) is smaller than nvoices(%d)\n", + printk(KERN_ERR "Soundfont Error: " + "patch length(%ld) is smaller than nvoices(%d)\n", count, hdr.nvoices); return -EINVAL; } @@ -952,7 +956,7 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data, int rc; if (count < (long)sizeof(patch)) { - snd_printk("patch record too small %ld\n", count); + snd_printk(KERN_ERR "patch record too small %ld\n", count); return -EINVAL; } if (copy_from_user(&patch, data, sizeof(patch))) @@ -1034,7 +1038,8 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data, /* panning position; -128 - 127 => 0-127 */ zone->v.pan = (patch.panning + 128) / 2; #if 0 - snd_printk("gus: basefrq=%d (ofs=%d) root=%d,tune=%d, range:%d-%d\n", + snd_printk(KERN_DEBUG + "gus: basefrq=%d (ofs=%d) root=%d,tune=%d, range:%d-%d\n", (int)patch.base_freq, zone->v.rate_offset, zone->v.root, zone->v.tune, zone->v.low, zone->v.high); #endif @@ -1068,7 +1073,8 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data, zone->v.parm.volrelease = 0x8000 | snd_sf_calc_parm_decay(release); zone->v.attenuation = calc_gus_attenuation(patch.env_offset[0]); #if 0 - snd_printk("gus: atkhld=%x, dcysus=%x, volrel=%x, att=%d\n", + snd_printk(KERN_DEBUG + "gus: atkhld=%x, dcysus=%x, volrel=%x, att=%d\n", zone->v.parm.volatkhld, zone->v.parm.voldcysus, zone->v.parm.volrelease, -- GitLab From e2ea7cfc703cba3299d22db728516a0fc1a9717c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 5 Feb 2009 16:07:02 +0100 Subject: [PATCH 1202/4982] ALSA: Add missing KERN_* prefix to printk in sound/pci/ice1712 Signed-off-by: Takashi Iwai --- sound/pci/ice1712/ice1712.c | 2 +- sound/pci/ice1712/ice1724.c | 17 ++++++++++++++--- sound/pci/ice1712/juli.c | 5 +++-- sound/pci/ice1712/prodigy192.c | 13 +++++++++---- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 58d7cda03de..dcd3f4f89b4 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -458,7 +458,7 @@ static irqreturn_t snd_ice1712_interrupt(int irq, void *dev_id) u16 pbkstatus; struct snd_pcm_substream *substream; pbkstatus = inw(ICEDS(ice, INTSTAT)); - /* printk("pbkstatus = 0x%x\n", pbkstatus); */ + /* printk(KERN_DEBUG "pbkstatus = 0x%x\n", pbkstatus); */ for (idx = 0; idx < 6; idx++) { if ((pbkstatus & (3 << (idx * 2))) == 0) continue; diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index eb7872dec5a..da8c111e9e3 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -756,7 +756,14 @@ static int snd_vt1724_playback_pro_prepare(struct snd_pcm_substream *substream) spin_unlock_irq(&ice->reg_lock); - /* printk("pro prepare: ch = %d, addr = 0x%x, buffer = 0x%x, period = 0x%x\n", substream->runtime->channels, (unsigned int)substream->runtime->dma_addr, snd_pcm_lib_buffer_bytes(substream), snd_pcm_lib_period_bytes(substream)); */ + /* + printk(KERN_DEBUG "pro prepare: ch = %d, addr = 0x%x, " + "buffer = 0x%x, period = 0x%x\n", + substream->runtime->channels, + (unsigned int)substream->runtime->dma_addr, + snd_pcm_lib_buffer_bytes(substream), + snd_pcm_lib_period_bytes(substream)); + */ return 0; } @@ -2133,7 +2140,9 @@ unsigned char snd_vt1724_read_i2c(struct snd_ice1712 *ice, wait_i2c_busy(ice); val = inb(ICEREG1724(ice, I2C_DATA)); mutex_unlock(&ice->i2c_mutex); - /* printk("i2c_read: [0x%x,0x%x] = 0x%x\n", dev, addr, val); */ + /* + printk(KERN_DEBUG "i2c_read: [0x%x,0x%x] = 0x%x\n", dev, addr, val); + */ return val; } @@ -2142,7 +2151,9 @@ void snd_vt1724_write_i2c(struct snd_ice1712 *ice, { mutex_lock(&ice->i2c_mutex); wait_i2c_busy(ice); - /* printk("i2c_write: [0x%x,0x%x] = 0x%x\n", dev, addr, data); */ + /* + printk(KERN_DEBUG "i2c_write: [0x%x,0x%x] = 0x%x\n", dev, addr, data); + */ outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR)); outb(data, ICEREG1724(ice, I2C_DATA)); outb(dev | VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR)); diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c index c51659b9caf..fd948bfd9ae 100644 --- a/sound/pci/ice1712/juli.c +++ b/sound/pci/ice1712/juli.c @@ -345,8 +345,9 @@ static int juli_mute_put(struct snd_kcontrol *kcontrol, new_gpio = old_gpio & ~((unsigned int) kcontrol->private_value); } - /* printk("JULI - mute/unmute: control_value: 0x%x, old_gpio: 0x%x, \ - new_gpio 0x%x\n", + /* printk(KERN_DEBUG + "JULI - mute/unmute: control_value: 0x%x, old_gpio: 0x%x, " + "new_gpio 0x%x\n", (unsigned int)ucontrol->value.integer.value[0], old_gpio, new_gpio); */ if (old_gpio != new_gpio) { diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c index 48d3679292a..2a8e5cd8f2d 100644 --- a/sound/pci/ice1712/prodigy192.c +++ b/sound/pci/ice1712/prodigy192.c @@ -133,8 +133,10 @@ static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME; /* due to possible conflicts with stac9460_set_rate_val, mutexing */ mutex_lock(&spec->mute_mutex); - /*printk("Mute put: reg 0x%02x, ctrl value: 0x%02x\n", idx, - ucontrol->value.integer.value[0]);*/ + /* + printk(KERN_DEBUG "Mute put: reg 0x%02x, ctrl value: 0x%02x\n", idx, + ucontrol->value.integer.value[0]); + */ change = stac9460_dac_mute(ice, idx, ucontrol->value.integer.value[0]); mutex_unlock(&spec->mute_mutex); return change; @@ -185,7 +187,10 @@ static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el change = (ovol != nvol); if (change) { ovol = (0x7f - nvol) | (tmp & 0x80); - /*printk("DAC Volume: reg 0x%02x: 0x%02x\n", idx, ovol);*/ + /* + printk(KERN_DEBUG "DAC Volume: reg 0x%02x: 0x%02x\n", + idx, ovol); + */ stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80)); } return change; @@ -344,7 +349,7 @@ static void stac9460_set_rate_val(struct snd_ice1712 *ice, unsigned int rate) for (idx = 0; idx < 7 ; ++idx) changed[idx] = stac9460_dac_mute(ice, STAC946X_MASTER_VOLUME + idx, 0); - /*printk("Rate change: %d, new MC: 0x%02x\n", rate, new);*/ + /*printk(KERN_DEBUG "Rate change: %d, new MC: 0x%02x\n", rate, new);*/ stac9460_put(ice, STAC946X_MASTER_CLOCKING, new); udelay(10); /* unmuting - only originally unmuted dacs - -- GitLab From 28a97c194cec477073ae341f15b836437d8ef8e5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 5 Feb 2009 16:08:14 +0100 Subject: [PATCH 1203/4982] ALSA: emu10k1 - Add missing KERN_* prefix to printk Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/emu10k1_callback.c | 7 +- sound/pci/emu10k1/emu10k1_main.c | 5 +- sound/pci/emu10k1/emufx.c | 11 +-- sound/pci/emu10k1/emupcm.c | 37 ++++++++-- sound/pci/emu10k1/io.c | 4 +- sound/pci/emu10k1/p16v.c | 100 +++++++++++++++++++-------- sound/pci/emu10k1/voice.c | 12 +++- 7 files changed, 130 insertions(+), 46 deletions(-) diff --git a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c index 0e649dcdbf6..7ef949d99a5 100644 --- a/sound/pci/emu10k1/emu10k1_callback.c +++ b/sound/pci/emu10k1/emu10k1_callback.c @@ -103,7 +103,10 @@ snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw) int ch; vp = &emu->voices[best[i].voice]; if ((ch = vp->ch) < 0) { - //printk("synth_get_voice: ch < 0 (%d) ??", i); + /* + printk(KERN_WARNING + "synth_get_voice: ch < 0 (%d) ??", i); + */ continue; } vp->emu->num_voices--; @@ -335,7 +338,7 @@ start_voice(struct snd_emux_voice *vp) return -EINVAL; emem->map_locked++; if (snd_emu10k1_memblk_map(hw, emem) < 0) { - // printk("emu: cannot map!\n"); + /* printk(KERN_ERR "emu: cannot map!\n"); */ return -ENOMEM; } mapped_offset = snd_emu10k1_memblk_offset(emem) >> 1; diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 7958006a1d6..8343aecbd25 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -758,7 +758,8 @@ static int emu1010_firmware_thread(void *data) snd_printk(KERN_INFO "emu1010: Audio Dock Firmware loaded\n"); snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp); snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2); - snd_printk("Audio Dock ver:%d.%d\n", tmp, tmp2); + snd_printk(KERN_INFO "Audio Dock ver:%d.%d\n", + tmp, tmp2); /* Sync clocking between 1010 and Dock */ /* Allow DLL to settle */ msleep(10); @@ -887,7 +888,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) snd_printk(KERN_INFO "emu1010: Hana Firmware loaded\n"); snd_emu1010_fpga_read(emu, EMU_HANA_MAJOR_REV, &tmp); snd_emu1010_fpga_read(emu, EMU_HANA_MINOR_REV, &tmp2); - snd_printk("emu1010: Hana version: %d.%d\n", tmp, tmp2); + snd_printk(KERN_INFO "emu1010: Hana version: %d.%d\n", tmp, tmp2); /* Enable 48Volt power to Audio Dock */ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, EMU_HANA_DOCK_PWR_ON); diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 7dba08f0ab8..191e1cd9997 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c @@ -1519,7 +1519,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) /* A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); */ if (emu->card_capabilities->emu_model) { /* EMU1010 Outputs from PCM Front, Rear, Center, LFE, Side */ - snd_printk("EMU outputs on\n"); + snd_printk(KERN_INFO "EMU outputs on\n"); for (z = 0; z < 8; z++) { if (emu->card_capabilities->ca0108_chip) { A_OP(icode, &ptr, iACC3, A3_EMU32OUT(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000); @@ -1567,7 +1567,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) if (emu->card_capabilities->emu_model) { if (emu->card_capabilities->ca0108_chip) { - snd_printk("EMU2 inputs on\n"); + snd_printk(KERN_INFO "EMU2 inputs on\n"); for (z = 0; z < 0x10; z++) { snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, @@ -1575,10 +1575,13 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) A_FXBUS2(z*2) ); } } else { - snd_printk("EMU inputs on\n"); + snd_printk(KERN_INFO "EMU inputs on\n"); /* Capture 16 (originally 8) channels of S32_LE sound */ - /* printk("emufx.c: gpr=0x%x, tmp=0x%x\n",gpr, tmp); */ + /* + printk(KERN_DEBUG "emufx.c: gpr=0x%x, tmp=0x%x\n", + gpr, tmp); + */ /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */ /* A_P16VIN(0) is delayed by one sample, * so all other A_P16VIN channels will need to also be delayed diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index cf9276ddad4..78f62fd404c 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c @@ -44,7 +44,7 @@ static void snd_emu10k1_pcm_interrupt(struct snd_emu10k1 *emu, if (epcm->substream == NULL) return; #if 0 - printk("IRQ: position = 0x%x, period = 0x%x, size = 0x%x\n", + printk(KERN_DEBUG "IRQ: position = 0x%x, period = 0x%x, size = 0x%x\n", epcm->substream->runtime->hw->pointer(emu, epcm->substream), snd_pcm_lib_period_bytes(epcm->substream), snd_pcm_lib_buffer_bytes(epcm->substream)); @@ -146,7 +146,11 @@ static int snd_emu10k1_pcm_channel_alloc(struct snd_emu10k1_pcm * epcm, int voic 1, &epcm->extra); if (err < 0) { - /* printk("pcm_channel_alloc: failed extra: voices=%d, frame=%d\n", voices, frame); */ + /* + printk(KERN_DEBUG "pcm_channel_alloc: " + "failed extra: voices=%d, frame=%d\n", + voices, frame); + */ for (i = 0; i < voices; i++) { snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]); epcm->voices[i] = NULL; @@ -737,7 +741,10 @@ static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream, struct snd_emu10k1_pcm_mixer *mix; int result = 0; - /* printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream)); */ + /* + printk(KERN_DEBUG "trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", + (int)emu, cmd, substream->ops->pointer(substream)) + */ spin_lock(&emu->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -786,7 +793,10 @@ static int snd_emu10k1_capture_trigger(struct snd_pcm_substream *substream, /* hmm this should cause full and half full interrupt to be raised? */ outl(epcm->capture_ipr, emu->port + IPR); snd_emu10k1_intr_enable(emu, epcm->capture_inte); - /* printk("adccr = 0x%x, adcbs = 0x%x\n", epcm->adccr, epcm->adcbs); */ + /* + printk(KERN_DEBUG "adccr = 0x%x, adcbs = 0x%x\n", + epcm->adccr, epcm->adcbs); + */ switch (epcm->type) { case CAPTURE_AC97ADC: snd_emu10k1_ptr_write(emu, ADCCR, 0, epcm->capture_cr_val); @@ -857,7 +867,11 @@ static snd_pcm_uframes_t snd_emu10k1_playback_pointer(struct snd_pcm_substream * ptr -= runtime->buffer_size; } #endif - /* printk("ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n", ptr, runtime->buffer_size, runtime->period_size); */ + /* + printk(KERN_DEBUG + "ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n", + ptr, runtime->buffer_size, runtime->period_size); + */ return ptr; } @@ -1546,7 +1560,11 @@ static void snd_emu10k1_fx8010_playback_tram_poke1(unsigned short *dst_left, unsigned int count, unsigned int tram_shift) { - /* printk("tram_poke1: dst_left = 0x%p, dst_right = 0x%p, src = 0x%p, count = 0x%x\n", dst_left, dst_right, src, count); */ + /* + printk(KERN_DEBUG "tram_poke1: dst_left = 0x%p, dst_right = 0x%p, " + "src = 0x%p, count = 0x%x\n", + dst_left, dst_right, src, count); + */ if ((tram_shift & 1) == 0) { while (count--) { *dst_left-- = *src++; @@ -1623,7 +1641,12 @@ static int snd_emu10k1_fx8010_playback_prepare(struct snd_pcm_substream *substre struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; unsigned int i; - /* printk("prepare: etram_pages = 0x%p, dma_area = 0x%x, buffer_size = 0x%x (0x%x)\n", emu->fx8010.etram_pages, runtime->dma_area, runtime->buffer_size, runtime->buffer_size << 2); */ + /* + printk(KERN_DEBUG "prepare: etram_pages = 0x%p, dma_area = 0x%x, " + "buffer_size = 0x%x (0x%x)\n", + emu->fx8010.etram_pages, runtime->dma_area, + runtime->buffer_size, runtime->buffer_size << 2); + */ memset(&pcm->pcm_rec, 0, sizeof(pcm->pcm_rec)); pcm->pcm_rec.hw_buffer_size = pcm->buffer_size * 2; /* byte size */ pcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c index b5a802bdeb7..4bfc31d1b28 100644 --- a/sound/pci/emu10k1/io.c +++ b/sound/pci/emu10k1/io.c @@ -226,7 +226,9 @@ int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, break; if (timeout > 1000) { - snd_printk("emu10k1:I2C:timeout status=0x%x\n", status); + snd_printk(KERN_WARNING + "emu10k1:I2C:timeout status=0x%x\n", + status); break; } } diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index 749a21b6bd0..e617acaf10e 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c @@ -168,7 +168,7 @@ static void snd_p16v_pcm_free_substream(struct snd_pcm_runtime *runtime) struct snd_emu10k1_pcm *epcm = runtime->private_data; if (epcm) { - //snd_printk("epcm free: %p\n", epcm); + /* snd_printk(KERN_DEBUG "epcm free: %p\n", epcm); */ kfree(epcm); } } @@ -183,14 +183,16 @@ static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substrea int err; epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - //snd_printk("epcm kcalloc: %p\n", epcm); + /* snd_printk(KERN_DEBUG "epcm kcalloc: %p\n", epcm); */ if (epcm == NULL) return -ENOMEM; epcm->emu = emu; epcm->substream = substream; - //snd_printk("epcm device=%d, channel_id=%d\n", substream->pcm->device, channel_id); - + /* + snd_printk(KERN_DEBUG "epcm device=%d, channel_id=%d\n", + substream->pcm->device, channel_id); + */ runtime->private_data = epcm; runtime->private_free = snd_p16v_pcm_free_substream; @@ -200,10 +202,15 @@ static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substrea channel->number = channel_id; channel->use=1; - //snd_printk("p16v: open channel_id=%d, channel=%p, use=0x%x\n", channel_id, channel, channel->use); - //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel); - //channel->interrupt = snd_p16v_pcm_channel_interrupt; - channel->epcm=epcm; +#if 0 /* debug */ + snd_printk(KERN_DEBUG + "p16v: open channel_id=%d, channel=%p, use=0x%x\n", + channel_id, channel, channel->use); + printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n", + channel_id, chip, channel); +#endif /* debug */ + /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */ + channel->epcm = epcm; if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) return err; @@ -224,14 +231,16 @@ static int snd_p16v_pcm_open_capture_channel(struct snd_pcm_substream *substream int err; epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - //snd_printk("epcm kcalloc: %p\n", epcm); + /* snd_printk(KERN_DEBUG "epcm kcalloc: %p\n", epcm); */ if (epcm == NULL) return -ENOMEM; epcm->emu = emu; epcm->substream = substream; - //snd_printk("epcm device=%d, channel_id=%d\n", substream->pcm->device, channel_id); - + /* + snd_printk(KERN_DEBUG "epcm device=%d, channel_id=%d\n", + substream->pcm->device, channel_id); + */ runtime->private_data = epcm; runtime->private_free = snd_p16v_pcm_free_substream; @@ -241,10 +250,15 @@ static int snd_p16v_pcm_open_capture_channel(struct snd_pcm_substream *substream channel->number = channel_id; channel->use=1; - //snd_printk("p16v: open channel_id=%d, channel=%p, use=0x%x\n", channel_id, channel, channel->use); - //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel); - //channel->interrupt = snd_p16v_pcm_channel_interrupt; - channel->epcm=epcm; +#if 0 /* debug */ + snd_printk(KERN_DEBUG + "p16v: open channel_id=%d, channel=%p, use=0x%x\n", + channel_id, channel, channel->use); + printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n", + channel_id, chip, channel); +#endif /* debug */ + /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */ + channel->epcm = epcm; if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) return err; @@ -334,9 +348,19 @@ static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream) int i; u32 tmp; - //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1)); - //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base); - //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->p16v_buffer.addr, emu->p16v_buffer.area, emu->p16v_buffer.bytes); +#if 0 /* debug */ + snd_printk(KERN_DEBUG "prepare:channel_number=%d, rate=%d, " + "format=0x%x, channels=%d, buffer_size=%ld, " + "period_size=%ld, periods=%u, frames_to_bytes=%d\n", + channel, runtime->rate, runtime->format, runtime->channels, + runtime->buffer_size, runtime->period_size, + runtime->periods, frames_to_bytes(runtime, 1)); + snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, table_base=%p\n", + runtime->dma_addr, runtime->dma_area, table_base); + snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n", + emu->p16v_buffer.addr, emu->p16v_buffer.area, + emu->p16v_buffer.bytes); +#endif /* debug */ tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel); switch (runtime->rate) { case 44100: @@ -379,7 +403,15 @@ static int snd_p16v_pcm_prepare_capture(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; int channel = substream->pcm->device - emu->p16v_device_offset; u32 tmp; - //printk("prepare capture:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, frames_to_bytes(runtime, 1)); + + /* + printk(KERN_DEBUG "prepare capture:channel_number=%d, rate=%d, " + "format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, " + "frames_to_bytes=%d\n", + channel, runtime->rate, runtime->format, runtime->channels, + runtime->buffer_size, runtime->period_size, + frames_to_bytes(runtime, 1)); + */ tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel); switch (runtime->rate) { case 44100: @@ -459,13 +491,13 @@ static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream, runtime = s->runtime; epcm = runtime->private_data; channel = substream->pcm->device-emu->p16v_device_offset; - //snd_printk("p16v channel=%d\n",channel); + /* snd_printk(KERN_DEBUG "p16v channel=%d\n", channel); */ epcm->running = running; basic |= (0x1<buffer_size; printk(KERN_WARNING "buffer capture limited!\n"); } - //printk("ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", ptr1, ptr2, ptr, (int)runtime->buffer_size, (int)runtime->period_size, (int)runtime->frame_bits, (int)runtime->rate); - + /* + printk(KERN_DEBUG "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, " + "buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", + ptr1, ptr2, ptr, (int)runtime->buffer_size, + (int)runtime->period_size, (int)runtime->frame_bits, + (int)runtime->rate); + */ return ptr; } @@ -592,7 +629,10 @@ int snd_p16v_free(struct snd_emu10k1 *chip) // release the data if (chip->p16v_buffer.area) { snd_dma_free_pages(&chip->p16v_buffer); - //snd_printk("period lables free: %p\n", &chip->p16v_buffer); + /* + snd_printk(KERN_DEBUG "period lables free: %p\n", + &chip->p16v_buffer); + */ } return 0; } @@ -604,7 +644,7 @@ int __devinit snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm * int err; int capture=1; - //snd_printk("snd_p16v_pcm called. device=%d\n", device); + /* snd_printk("KERN_DEBUG snd_p16v_pcm called. device=%d\n", device); */ emu->p16v_device_offset = device; if (rpcm) *rpcm = NULL; @@ -631,7 +671,10 @@ int __devinit snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm * snd_dma_pci_data(emu->pci), ((65536 - 64) * 8), ((65536 - 64) * 8))) < 0) return err; - //snd_printk("preallocate playback substream: err=%d\n", err); + /* + snd_printk(KERN_DEBUG + "preallocate playback substream: err=%d\n", err); + */ } for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; @@ -642,7 +685,10 @@ int __devinit snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm * snd_dma_pci_data(emu->pci), 65536 - 64, 65536 - 64)) < 0) return err; - //snd_printk("preallocate capture substream: err=%d\n", err); + /* + snd_printk(KERN_DEBUG + "preallocate capture substream: err=%d\n", err); + */ } if (rpcm) diff --git a/sound/pci/emu10k1/voice.c b/sound/pci/emu10k1/voice.c index d7300a1aa26..20b8da250bd 100644 --- a/sound/pci/emu10k1/voice.c +++ b/sound/pci/emu10k1/voice.c @@ -53,7 +53,10 @@ static int voice_alloc(struct snd_emu10k1 *emu, int type, int number, *rvoice = NULL; first_voice = last_voice = 0; for (i = emu->next_free_voice, j = 0; j < NUM_G ; i += number, j += number) { - // printk("i %d j %d next free %d!\n", i, j, emu->next_free_voice); + /* + printk(KERN_DEBUG "i %d j %d next free %d!\n", + i, j, emu->next_free_voice); + */ i %= NUM_G; /* stereo voices must be even/odd */ @@ -71,7 +74,7 @@ static int voice_alloc(struct snd_emu10k1 *emu, int type, int number, } } if (!skip) { - // printk("allocated voice %d\n", i); + /* printk(KERN_DEBUG "allocated voice %d\n", i); */ first_voice = i; last_voice = (i + number) % NUM_G; emu->next_free_voice = last_voice; @@ -84,7 +87,10 @@ static int voice_alloc(struct snd_emu10k1 *emu, int type, int number, for (i = 0; i < number; i++) { voice = &emu->voices[(first_voice + i) % NUM_G]; - // printk("voice alloc - %i, %i of %i\n", voice->number, idx-first_voice+1, number); + /* + printk(kERN_DEBUG "voice alloc - %i, %i of %i\n", + voice->number, idx-first_voice+1, number); + */ voice->use = 1; switch (type) { case EMU10K1_PCM: -- GitLab From 14ab08610971eb1db572ad8ca63acd13bc4d4caf Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 5 Feb 2009 16:09:57 +0100 Subject: [PATCH 1204/4982] ALSA: intel8x0 - Add missing KERN_* prefix to printk Signed-off-by: Takashi Iwai --- sound/pci/intel8x0.c | 11 +++++++---- sound/pci/intel8x0m.c | 14 ++++++++++---- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index b13ef1e2a4a..0f7d1291190 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -689,7 +689,7 @@ static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ich bdbar[idx + 1] = cpu_to_le32(0x80000000 | /* interrupt on completion */ ichdev->fragsize >> ichdev->pos_shift); #if 0 - printk("bdbar[%i] = 0x%x [0x%x]\n", + printk(KERN_DEBUG "bdbar[%i] = 0x%x [0x%x]\n", idx + 0, bdbar[idx + 0], bdbar[idx + 1]); #endif } @@ -701,8 +701,10 @@ static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ich ichdev->lvi_frag = ICH_REG_LVI_MASK % ichdev->frags; ichdev->position = 0; #if 0 - printk("lvi_frag = %i, frags = %i, period_size = 0x%x, period_size1 = 0x%x\n", - ichdev->lvi_frag, ichdev->frags, ichdev->fragsize, ichdev->fragsize1); + printk(KERN_DEBUG "lvi_frag = %i, frags = %i, period_size = 0x%x, " + "period_size1 = 0x%x\n", + ichdev->lvi_frag, ichdev->frags, ichdev->fragsize, + ichdev->fragsize1); #endif /* clear interrupts */ iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI); @@ -768,7 +770,8 @@ static inline void snd_intel8x0_update(struct intel8x0 *chip, struct ichdev *ich ichdev->lvi_frag %= ichdev->frags; ichdev->bdbar[ichdev->lvi * 2] = cpu_to_le32(ichdev->physbuf + ichdev->lvi_frag * ichdev->fragsize1); #if 0 - printk("new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, all = 0x%x, 0x%x\n", + printk(KERN_DEBUG "new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, " + "all = 0x%x, 0x%x\n", ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2], ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port), inl(port + 4), inb(port + ICH_REG_OFF_CR)); diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 93449e46456..7c819fd824a 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -411,7 +411,10 @@ static void snd_intel8x0_setup_periods(struct intel8x0m *chip, struct ichdev *ic bdbar[idx + 0] = cpu_to_le32(ichdev->physbuf + (((idx >> 1) * ichdev->fragsize) % ichdev->size)); bdbar[idx + 1] = cpu_to_le32(0x80000000 | /* interrupt on completion */ ichdev->fragsize >> chip->pcm_pos_shift); - // printk("bdbar[%i] = 0x%x [0x%x]\n", idx + 0, bdbar[idx + 0], bdbar[idx + 1]); + /* + printk(KERN_DEBUG "bdbar[%i] = 0x%x [0x%x]\n", + idx + 0, bdbar[idx + 0], bdbar[idx + 1]); + */ } ichdev->frags = ichdev->size / ichdev->fragsize; } @@ -421,8 +424,10 @@ static void snd_intel8x0_setup_periods(struct intel8x0m *chip, struct ichdev *ic ichdev->lvi_frag = ICH_REG_LVI_MASK % ichdev->frags; ichdev->position = 0; #if 0 - printk("lvi_frag = %i, frags = %i, period_size = 0x%x, period_size1 = 0x%x\n", - ichdev->lvi_frag, ichdev->frags, ichdev->fragsize, ichdev->fragsize1); + printk(KERN_DEBUG "lvi_frag = %i, frags = %i, period_size = 0x%x, " + "period_size1 = 0x%x\n", + ichdev->lvi_frag, ichdev->frags, ichdev->fragsize, + ichdev->fragsize1); #endif /* clear interrupts */ iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI); @@ -465,7 +470,8 @@ static inline void snd_intel8x0_update(struct intel8x0m *chip, struct ichdev *ic ichdev->lvi_frag * ichdev->fragsize1); #if 0 - printk("new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, all = 0x%x, 0x%x\n", + printk(KERN_DEBUG "new: bdbar[%i] = 0x%x [0x%x], " + "prefetch = %i, all = 0x%x, 0x%x\n", ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2], ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port), inl(port + 4), inb(port + ICH_REG_OFF_CR)); -- GitLab From ee419653a38de93b75a577851d9e4003cf0bbe07 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 5 Feb 2009 16:11:31 +0100 Subject: [PATCH 1205/4982] ALSA: Fix missing KERN_* prefix to printk in sound/pci Signed-off-by: Takashi Iwai --- sound/pci/ac97/ac97_codec.c | 5 +- sound/pci/ak4531_codec.c | 3 +- sound/pci/als300.c | 2 +- sound/pci/au88x0/au88x0_a3d.c | 7 +- sound/pci/au88x0/au88x0_core.c | 19 ++++- sound/pci/au88x0/au88x0_synth.c | 39 ++++++++-- sound/pci/azt3328.c | 8 +- sound/pci/ca0106/ca0106_main.c | 91 ++++++++++++++++++----- sound/pci/cs4281.c | 6 +- sound/pci/cs46xx/cs46xx_lib.c | 6 +- sound/pci/cs46xx/cs46xx_lib.h | 6 +- sound/pci/cs5535audio/cs5535audio.c | 2 +- sound/pci/ens1370.c | 3 +- sound/pci/es1938.c | 23 ++++-- sound/pci/mixart/mixart_hwdep.c | 46 +++++++----- sound/pci/sonicvibes.c | 109 ++++++++++++++++++---------- sound/pci/trident/trident_main.c | 57 ++++++++------- sound/pci/via82xx.c | 5 +- sound/pci/via82xx_modem.c | 5 +- sound/pci/vx222/vx222_ops.c | 8 +- sound/pci/ymfpci/ymfpci_main.c | 14 +++- 21 files changed, 318 insertions(+), 146 deletions(-) diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index e2b843b4f9d..bc707b60385 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -1643,7 +1643,10 @@ static int snd_ac97_modem_build(struct snd_card *card, struct snd_ac97 * ac97) { int err, idx; - //printk("AC97_GPIO_CFG = %x\n",snd_ac97_read(ac97,AC97_GPIO_CFG)); + /* + printk(KERN_DEBUG "AC97_GPIO_CFG = %x\n", + snd_ac97_read(ac97,AC97_GPIO_CFG)); + */ snd_ac97_write(ac97, AC97_GPIO_CFG, 0xffff & ~(AC97_GPIO_LINE1_OH)); snd_ac97_write(ac97, AC97_GPIO_POLARITY, 0xffff & ~(AC97_GPIO_LINE1_OH)); snd_ac97_write(ac97, AC97_GPIO_STICKY, 0xffff); diff --git a/sound/pci/ak4531_codec.c b/sound/pci/ak4531_codec.c index 0f819ddb3eb..fd135e3d8a8 100644 --- a/sound/pci/ak4531_codec.c +++ b/sound/pci/ak4531_codec.c @@ -51,7 +51,8 @@ static void snd_ak4531_dump(struct snd_ak4531 *ak4531) int idx; for (idx = 0; idx < 0x19; idx++) - printk("ak4531 0x%x: 0x%x\n", idx, ak4531->regs[idx]); + printk(KERN_DEBUG "ak4531 0x%x: 0x%x\n", + idx, ak4531->regs[idx]); } #endif diff --git a/sound/pci/als300.c b/sound/pci/als300.c index 8df6824b51c..a2c35c1081c 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c @@ -91,7 +91,7 @@ #define DEBUG_PLAY_REC 0 #if DEBUG_CALLS -#define snd_als300_dbgcalls(format, args...) printk(format, ##args) +#define snd_als300_dbgcalls(format, args...) printk(KERN_DEBUG format, ##args) #define snd_als300_dbgcallenter() printk(KERN_ERR "--> %s\n", __func__) #define snd_als300_dbgcallleave() printk(KERN_ERR "<-- %s\n", __func__) #else diff --git a/sound/pci/au88x0/au88x0_a3d.c b/sound/pci/au88x0/au88x0_a3d.c index 649849e540d..f4aa8ff6f5f 100644 --- a/sound/pci/au88x0/au88x0_a3d.c +++ b/sound/pci/au88x0/au88x0_a3d.c @@ -462,9 +462,10 @@ static void a3dsrc_ZeroSliceIO(a3dsrc_t * a) /* Reset Single A3D source. */ static void a3dsrc_ZeroState(a3dsrc_t * a) { - - //printk("vortex: ZeroState slice: %d, source %d\n", a->slice, a->source); - + /* + printk(KERN_DEBUG "vortex: ZeroState slice: %d, source %d\n", + a->slice, a->source); + */ a3dsrc_SetAtmosState(a, 0, 0, 0, 0); a3dsrc_SetHrtfState(a, A3dHrirZeros, A3dHrirZeros); a3dsrc_SetItdDline(a, A3dItdDlineZeros); diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c index b070e571451..e6a04d037c1 100644 --- a/sound/pci/au88x0/au88x0_core.c +++ b/sound/pci/au88x0/au88x0_core.c @@ -1135,7 +1135,10 @@ vortex_adbdma_setbuffers(vortex_t * vortex, int adbdma, snd_pcm_sgbuf_get_addr(dma->substream, 0)); break; } - //printk("vortex: cfg0 = 0x%x\nvortex: cfg1=0x%x\n", dma->cfg0, dma->cfg1); + /* + printk(KERN_DEBUG "vortex: cfg0 = 0x%x\nvortex: cfg1=0x%x\n", + dma->cfg0, dma->cfg1); + */ hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFCFG0 + (adbdma << 3), dma->cfg0); hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFCFG1 + (adbdma << 3), dma->cfg1); @@ -1959,7 +1962,7 @@ vortex_connect_codecplay(vortex_t * vortex, int en, unsigned char mixers[]) ADB_CODECOUT(0 + 4)); vortex_connection_mix_adb(vortex, en, 0x11, mixers[3], ADB_CODECOUT(1 + 4)); - //printk("SDAC detected "); + /* printk(KERN_DEBUG "SDAC detected "); */ } #else // Use plain direct output to codec. @@ -2013,7 +2016,11 @@ vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, int restype) resmap[restype] |= (1 << i); else vortex->dma_adb[i].resources[restype] |= (1 << i); - //printk("vortex: ResManager: type %d out %d\n", restype, i); + /* + printk(KERN_DEBUG + "vortex: ResManager: type %d out %d\n", + restype, i); + */ return i; } } @@ -2024,7 +2031,11 @@ vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, int restype) for (i = 0; i < qty; i++) { if (resmap[restype] & (1 << i)) { resmap[restype] &= ~(1 << i); - //printk("vortex: ResManager: type %d in %d\n",restype, i); + /* + printk(KERN_DEBUG + "vortex: ResManager: type %d in %d\n", + restype, i); + */ return i; } } diff --git a/sound/pci/au88x0/au88x0_synth.c b/sound/pci/au88x0/au88x0_synth.c index 978b856f562..2805e34bd41 100644 --- a/sound/pci/au88x0/au88x0_synth.c +++ b/sound/pci/au88x0/au88x0_synth.c @@ -213,38 +213,59 @@ vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt, switch (reg) { /* Voice specific parameters */ case 0: /* running */ - //printk("vortex: WT SetReg(0x%x) = 0x%08x\n", WT_RUN(wt), (int)val); + /* + printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", + WT_RUN(wt), (int)val); + */ hwwrite(vortex->mmio, WT_RUN(wt), val); return 0xc; break; case 1: /* param 0 */ - //printk("vortex: WT SetReg(0x%x) = 0x%08x\n", WT_PARM(wt,0), (int)val); + /* + printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", + WT_PARM(wt,0), (int)val); + */ hwwrite(vortex->mmio, WT_PARM(wt, 0), val); return 0xc; break; case 2: /* param 1 */ - //printk("vortex: WT SetReg(0x%x) = 0x%08x\n", WT_PARM(wt,1), (int)val); + /* + printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", + WT_PARM(wt,1), (int)val); + */ hwwrite(vortex->mmio, WT_PARM(wt, 1), val); return 0xc; break; case 3: /* param 2 */ - //printk("vortex: WT SetReg(0x%x) = 0x%08x\n", WT_PARM(wt,2), (int)val); + /* + printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", + WT_PARM(wt,2), (int)val); + */ hwwrite(vortex->mmio, WT_PARM(wt, 2), val); return 0xc; break; case 4: /* param 3 */ - //printk("vortex: WT SetReg(0x%x) = 0x%08x\n", WT_PARM(wt,3), (int)val); + /* + printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", + WT_PARM(wt,3), (int)val); + */ hwwrite(vortex->mmio, WT_PARM(wt, 3), val); return 0xc; break; case 6: /* mute */ - //printk("vortex: WT SetReg(0x%x) = 0x%08x\n", WT_MUTE(wt), (int)val); + /* + printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", + WT_MUTE(wt), (int)val); + */ hwwrite(vortex->mmio, WT_MUTE(wt), val); return 0xc; break; case 0xb: { /* delay */ - //printk("vortex: WT SetReg(0x%x) = 0x%08x\n", WT_DELAY(wt,0), (int)val); + /* + printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", + WT_DELAY(wt,0), (int)val); + */ hwwrite(vortex->mmio, WT_DELAY(wt, 3), val); hwwrite(vortex->mmio, WT_DELAY(wt, 2), val); hwwrite(vortex->mmio, WT_DELAY(wt, 1), val); @@ -272,7 +293,9 @@ vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt, return 0; break; } - //printk("vortex: WT SetReg(0x%x) = 0x%08x\n", ecx, (int)val); + /* + printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", ecx, (int)val); + */ hwwrite(vortex->mmio, ecx, val); return 1; } diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 333007c523a..8121763b0c1 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -211,25 +211,25 @@ MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}"); #endif #if DEBUG_MIXER -#define snd_azf3328_dbgmixer(format, args...) printk(format, ##args) +#define snd_azf3328_dbgmixer(format, args...) printk(KERN_DEBUG format, ##args) #else #define snd_azf3328_dbgmixer(format, args...) #endif #if DEBUG_PLAY_REC -#define snd_azf3328_dbgplay(format, args...) printk(KERN_ERR format, ##args) +#define snd_azf3328_dbgplay(format, args...) printk(KERN_DEBUG format, ##args) #else #define snd_azf3328_dbgplay(format, args...) #endif #if DEBUG_MISC -#define snd_azf3328_dbgtimer(format, args...) printk(KERN_ERR format, ##args) +#define snd_azf3328_dbgtimer(format, args...) printk(KERN_DEBUG format, ##args) #else #define snd_azf3328_dbgtimer(format, args...) #endif #if DEBUG_GAME -#define snd_azf3328_dbggame(format, args...) printk(KERN_ERR format, ##args) +#define snd_azf3328_dbggame(format, args...) printk(KERN_DEBUG format, ##args) #else #define snd_azf3328_dbggame(format, args...) #endif diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 0e62205d408..f2f8fd17ea4 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -404,7 +404,9 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, } tmp = reg << 25 | value << 16; - // snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value); + /* + snd_printk(KERN_DEBUG "I2C-write:reg=0x%x, value=0x%x\n", reg, value); + */ /* Not sure what this I2C channel controls. */ /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */ @@ -422,7 +424,7 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, /* Wait till the transaction ends */ while (1) { status = snd_ca0106_ptr_read(emu, I2C_A, 0); - //snd_printk("I2C:status=0x%x\n", status); + /*snd_printk(KERN_DEBUG "I2C:status=0x%x\n", status);*/ timeout++; if ((status & I2C_A_ADC_START) == 0) break; @@ -521,7 +523,10 @@ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substr channel->number = channel_id; channel->use = 1; - //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel); + /* + printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n", + channel_id, chip, channel); + */ //channel->interrupt = snd_ca0106_pcm_channel_interrupt; channel->epcm = epcm; if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) @@ -614,7 +619,10 @@ static int snd_ca0106_pcm_open_capture_channel(struct snd_pcm_substream *substre channel->number = channel_id; channel->use = 1; - //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel); + /* + printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n", + channel_id, chip, channel); + */ //channel->interrupt = snd_ca0106_pcm_channel_interrupt; channel->epcm = epcm; if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) @@ -705,9 +713,20 @@ static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream) u32 reg71; int i; - //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1)); - //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base); - //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes); +#if 0 /* debug */ + snd_printk(KERN_DEBUG + "prepare:channel_number=%d, rate=%d, format=0x%x, " + "channels=%d, buffer_size=%ld, period_size=%ld, " + "periods=%u, frames_to_bytes=%d\n", + channel, runtime->rate, runtime->format, + runtime->channels, runtime->buffer_size, + runtime->period_size, runtime->periods, + frames_to_bytes(runtime, 1)); + snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, table_base=%p\n", + runtime->dma_addr, runtime->dma_area, table_base); + snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n", + emu->buffer.addr, emu->buffer.area, emu->buffer.bytes); +#endif /* debug */ /* Rate can be set per channel. */ /* reg40 control host to fifo */ /* reg71 controls DAC rate. */ @@ -799,9 +818,20 @@ static int snd_ca0106_pcm_prepare_capture(struct snd_pcm_substream *substream) u32 reg71_set = 0; u32 reg71; - //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1)); - //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base); - //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes); +#if 0 /* debug */ + snd_printk(KERN_DEBUG + "prepare:channel_number=%d, rate=%d, format=0x%x, " + "channels=%d, buffer_size=%ld, period_size=%ld, " + "periods=%u, frames_to_bytes=%d\n", + channel, runtime->rate, runtime->format, + runtime->channels, runtime->buffer_size, + runtime->period_size, runtime->periods, + frames_to_bytes(runtime, 1)); + snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, table_base=%p\n", + runtime->dma_addr, runtime->dma_area, table_base); + snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n", + emu->buffer.addr, emu->buffer.area, emu->buffer.bytes); +#endif /* debug */ /* reg71 controls ADC rate. */ switch (runtime->rate) { case 44100: @@ -846,7 +876,14 @@ static int snd_ca0106_pcm_prepare_capture(struct snd_pcm_substream *substream) } - //printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, frames_to_bytes(runtime, 1)); + /* + printk(KERN_DEBUG + "prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, " + "buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n", + channel, runtime->rate, runtime->format, runtime->channels, + runtime->buffer_size, runtime->period_size, + frames_to_bytes(runtime, 1)); + */ snd_ca0106_ptr_write(emu, 0x13, channel, 0); snd_ca0106_ptr_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr); snd_ca0106_ptr_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes @@ -888,13 +925,13 @@ static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream, runtime = s->runtime; epcm = runtime->private_data; channel = epcm->channel_id; - /* snd_printk("channel=%d\n",channel); */ + /* snd_printk(KERN_DEBUG "channel=%d\n", channel); */ epcm->running = running; basic |= (0x1 << channel); extended |= (0x10 << channel); snd_pcm_trigger_done(s, substream); } - /* snd_printk("basic=0x%x, extended=0x%x\n",basic, extended); */ + /* snd_printk(KERN_DEBUG "basic=0x%x, extended=0x%x\n",basic, extended); */ switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -972,8 +1009,13 @@ snd_ca0106_pcm_pointer_playback(struct snd_pcm_substream *substream) ptr=ptr2; if (ptr >= runtime->buffer_size) ptr -= runtime->buffer_size; - //printk("ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", ptr1, ptr2, ptr, (int)runtime->buffer_size, (int)runtime->period_size, (int)runtime->frame_bits, (int)runtime->rate); - + /* + printk(KERN_DEBUG "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, " + "buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", + ptr1, ptr2, ptr, (int)runtime->buffer_size, + (int)runtime->period_size, (int)runtime->frame_bits, + (int)runtime->rate); + */ return ptr; } @@ -995,8 +1037,13 @@ snd_ca0106_pcm_pointer_capture(struct snd_pcm_substream *substream) ptr=ptr2; if (ptr >= runtime->buffer_size) ptr -= runtime->buffer_size; - //printk("ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", ptr1, ptr2, ptr, (int)runtime->buffer_size, (int)runtime->period_size, (int)runtime->frame_bits, (int)runtime->rate); - + /* + printk(KERN_DEBUG "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, " + "buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", + ptr1, ptr2, ptr, (int)runtime->buffer_size, + (int)runtime->period_size, (int)runtime->frame_bits, + (int)runtime->rate); + */ return ptr; } @@ -1181,8 +1228,12 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id) return IRQ_NONE; stat76 = snd_ca0106_ptr_read(chip, EXTENDED_INT, 0); - //snd_printk("interrupt status = 0x%08x, stat76=0x%08x\n", status, stat76); - //snd_printk("ptr=0x%08x\n",snd_ca0106_ptr_read(chip, PLAYBACK_POINTER, 0)); + /* + snd_printk(KERN_DEBUG "interrupt status = 0x%08x, stat76=0x%08x\n", + status, stat76); + snd_printk(KERN_DEBUG "ptr=0x%08x\n", + snd_ca0106_ptr_read(chip, PLAYBACK_POINTER, 0)); + */ mask = 0x11; /* 0x1 for one half, 0x10 for the other half period. */ for(i = 0; i < 4; i++) { pchannel = &(chip->playback_channels[i]); @@ -1470,7 +1521,7 @@ static void ca0106_init_chip(struct snd_ca0106 *chip, int resume) int size, n; size = ARRAY_SIZE(i2c_adc_init); - /* snd_printk("I2C:array size=0x%x\n", size); */ + /* snd_printk(KERN_DEBUG "I2C:array size=0x%x\n", size); */ for (n = 0; n < size; n++) snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], i2c_adc_init[n][1]); diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index 192e7842e18..415e88f2c62 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -834,7 +834,11 @@ static snd_pcm_uframes_t snd_cs4281_pointer(struct snd_pcm_substream *substream) struct cs4281_dma *dma = runtime->private_data; struct cs4281 *chip = snd_pcm_substream_chip(substream); - // printk("DCC = 0x%x, buffer_size = 0x%x, jiffies = %li\n", snd_cs4281_peekBA0(chip, dma->regDCC), runtime->buffer_size, jiffies); + /* + printk(KERN_DEBUG "DCC = 0x%x, buffer_size = 0x%x, jiffies = %li\n", + snd_cs4281_peekBA0(chip, dma->regDCC), runtime->buffer_size, + jiffies); + */ return runtime->buffer_size - snd_cs4281_peekBA0(chip, dma->regDCC) - 1; } diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 8ab07aa6365..1be96ead424 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -194,7 +194,7 @@ static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip, * ACSDA = Status Data Register = 474h */ #if 0 - printk("e) reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n", reg, + printk(KERN_DEBUG "e) reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n", reg, snd_cs46xx_peekBA0(chip, BA0_ACSDA), snd_cs46xx_peekBA0(chip, BA0_ACCAD)); #endif @@ -428,8 +428,8 @@ static int cs46xx_wait_for_fifo(struct snd_cs46xx * chip,int retry_timeout) } if(status & SERBST_WBSY) { - snd_printk( KERN_ERR "cs46xx: failure waiting for FIFO command to complete\n"); - + snd_printk(KERN_ERR "cs46xx: failure waiting for " + "FIFO command to complete\n"); return -EINVAL; } diff --git a/sound/pci/cs46xx/cs46xx_lib.h b/sound/pci/cs46xx/cs46xx_lib.h index 018a7de5601..4eb55aa3361 100644 --- a/sound/pci/cs46xx/cs46xx_lib.h +++ b/sound/pci/cs46xx/cs46xx_lib.h @@ -62,7 +62,11 @@ static inline void snd_cs46xx_poke(struct snd_cs46xx *chip, unsigned long reg, u unsigned int bank = reg >> 16; unsigned int offset = reg & 0xffff; - /*if (bank == 0) printk("snd_cs46xx_poke: %04X - %08X\n",reg >> 2,val); */ + /* + if (bank == 0) + printk(KERN_DEBUG "snd_cs46xx_poke: %04X - %08X\n", + reg >> 2,val); + */ writel(val, chip->region.idx[bank+1].remap_addr + offset); } diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index 826e6dec2e9..6506201d56f 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c @@ -312,7 +312,7 @@ static int __devinit snd_cs5535audio_create(struct snd_card *card, if (request_irq(pci->irq, snd_cs5535audio_interrupt, IRQF_SHARED, "CS5535 Audio", cs5535au)) { - snd_printk("unable to grab IRQ %d\n", pci->irq); + snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); err = -EBUSY; goto sndfail; } diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 9bf95367c88..17674b3406b 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -584,7 +584,8 @@ static void snd_es1370_codec_write(struct snd_ak4531 *ak4531, unsigned long end_time = jiffies + HZ / 10; #if 0 - printk("CODEC WRITE: reg = 0x%x, val = 0x%x (0x%x), creg = 0x%x\n", + printk(KERN_DEBUG + "CODEC WRITE: reg = 0x%x, val = 0x%x (0x%x), creg = 0x%x\n", reg, val, ES_1370_CODEC_WRITE(reg, val), ES_REG(ensoniq, 1370_CODEC)); #endif do { diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 4cd9a1faaec..e4ba84bed4a 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -1673,18 +1673,22 @@ static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id) status = inb(SLIO_REG(chip, IRQCONTROL)); #if 0 - printk("Es1938debug - interrupt status: =0x%x\n", status); + printk(KERN_DEBUG "Es1938debug - interrupt status: =0x%x\n", status); #endif /* AUDIO 1 */ if (status & 0x10) { #if 0 - printk("Es1938debug - AUDIO channel 1 interrupt\n"); - printk("Es1938debug - AUDIO channel 1 DMAC DMA count: %u\n", + printk(KERN_DEBUG + "Es1938debug - AUDIO channel 1 interrupt\n"); + printk(KERN_DEBUG + "Es1938debug - AUDIO channel 1 DMAC DMA count: %u\n", inw(SLDM_REG(chip, DMACOUNT))); - printk("Es1938debug - AUDIO channel 1 DMAC DMA base: %u\n", + printk(KERN_DEBUG + "Es1938debug - AUDIO channel 1 DMAC DMA base: %u\n", inl(SLDM_REG(chip, DMAADDR))); - printk("Es1938debug - AUDIO channel 1 DMAC DMA status: 0x%x\n", + printk(KERN_DEBUG + "Es1938debug - AUDIO channel 1 DMAC DMA status: 0x%x\n", inl(SLDM_REG(chip, DMASTATUS))); #endif /* clear irq */ @@ -1699,10 +1703,13 @@ static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id) /* AUDIO 2 */ if (status & 0x20) { #if 0 - printk("Es1938debug - AUDIO channel 2 interrupt\n"); - printk("Es1938debug - AUDIO channel 2 DMAC DMA count: %u\n", + printk(KERN_DEBUG + "Es1938debug - AUDIO channel 2 interrupt\n"); + printk(KERN_DEBUG + "Es1938debug - AUDIO channel 2 DMAC DMA count: %u\n", inw(SLIO_REG(chip, AUDIO2DMACOUNT))); - printk("Es1938debug - AUDIO channel 2 DMAC DMA base: %u\n", + printk(KERN_DEBUG + "Es1938debug - AUDIO channel 2 DMAC DMA base: %u\n", inl(SLIO_REG(chip, AUDIO2DMAADDR))); #endif diff --git a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c index 3782b52bc0e..dda562081d7 100644 --- a/sound/pci/mixart/mixart_hwdep.c +++ b/sound/pci/mixart/mixart_hwdep.c @@ -345,8 +345,8 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw status_daught = readl_be( MIXART_MEM( mgr,MIXART_PSEUDOREG_DXLX_STATUS_OFFSET )); /* motherboard xilinx status 5 will say that the board is performing a reset */ - if( status_xilinx == 5 ) { - snd_printk( KERN_ERR "miXart is resetting !\n"); + if (status_xilinx == 5) { + snd_printk(KERN_ERR "miXart is resetting !\n"); return -EAGAIN; /* try again later */ } @@ -354,13 +354,14 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw case MIXART_MOTHERBOARD_XLX_INDEX: /* xilinx already loaded ? */ - if( status_xilinx == 4 ) { - snd_printk( KERN_DEBUG "xilinx is already loaded !\n"); + if (status_xilinx == 4) { + snd_printk(KERN_DEBUG "xilinx is already loaded !\n"); return 0; } /* the status should be 0 == "idle" */ - if( status_xilinx != 0 ) { - snd_printk( KERN_ERR "xilinx load error ! status = %d\n", status_xilinx); + if (status_xilinx != 0) { + snd_printk(KERN_ERR "xilinx load error ! status = %d\n", + status_xilinx); return -EIO; /* modprob -r may help ? */ } @@ -389,21 +390,23 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw case MIXART_MOTHERBOARD_ELF_INDEX: - if( status_elf == 4 ) { - snd_printk( KERN_DEBUG "elf file already loaded !\n"); + if (status_elf == 4) { + snd_printk(KERN_DEBUG "elf file already loaded !\n"); return 0; } /* the status should be 0 == "idle" */ - if( status_elf != 0 ) { - snd_printk( KERN_ERR "elf load error ! status = %d\n", status_elf); + if (status_elf != 0) { + snd_printk(KERN_ERR "elf load error ! status = %d\n", + status_elf); return -EIO; /* modprob -r may help ? */ } /* wait for xilinx status == 4 */ err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_MXLX_STATUS_OFFSET, 1, 4, 500); /* 5sec */ if (err < 0) { - snd_printk( KERN_ERR "xilinx was not loaded or could not be started\n"); + snd_printk(KERN_ERR "xilinx was not loaded or " + "could not be started\n"); return err; } @@ -424,7 +427,7 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw /* wait for elf status == 4 */ err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_ELF_STATUS_OFFSET, 1, 4, 300); /* 3sec */ if (err < 0) { - snd_printk( KERN_ERR "elf could not be started\n"); + snd_printk(KERN_ERR "elf could not be started\n"); return err; } @@ -437,15 +440,16 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw default: /* elf and xilinx should be loaded */ - if( (status_elf != 4) || (status_xilinx != 4) ) { - printk( KERN_ERR "xilinx or elf not successfully loaded\n"); + if (status_elf != 4 || status_xilinx != 4) { + printk(KERN_ERR "xilinx or elf not " + "successfully loaded\n"); return -EIO; /* modprob -r may help ? */ } /* wait for daughter detection != 0 */ err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DBRD_PRESENCE_OFFSET, 0, 0, 30); /* 300msec */ if (err < 0) { - snd_printk( KERN_ERR "error starting elf file\n"); + snd_printk(KERN_ERR "error starting elf file\n"); return err; } @@ -460,8 +464,9 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw return -EINVAL; /* daughter should be idle */ - if( status_daught != 0 ) { - printk( KERN_ERR "daughter load error ! status = %d\n", status_daught); + if (status_daught != 0) { + printk(KERN_ERR "daughter load error ! status = %d\n", + status_daught); return -EIO; /* modprob -r may help ? */ } @@ -480,7 +485,7 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw /* wait for status == 2 */ err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET, 1, 2, 30); /* 300msec */ if (err < 0) { - snd_printk( KERN_ERR "daughter board load error\n"); + snd_printk(KERN_ERR "daughter board load error\n"); return err; } @@ -502,7 +507,8 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw /* wait for daughter status == 3 */ err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET, 1, 3, 300); /* 3sec */ if (err < 0) { - snd_printk( KERN_ERR "daughter board could not be initialised\n"); + snd_printk(KERN_ERR + "daughter board could not be initialised\n"); return err; } @@ -512,7 +518,7 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw /* first communication with embedded */ err = mixart_first_init(mgr); if (err < 0) { - snd_printk( KERN_ERR "miXart could not be set up\n"); + snd_printk(KERN_ERR "miXart could not be set up\n"); return err; } diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index cd408b86c83..e922b1887b1 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -273,7 +273,8 @@ static inline void snd_sonicvibes_setdmaa(struct sonicvibes * sonic, outl(count, sonic->dmaa_port + SV_DMA_COUNT0); outb(0x18, sonic->dmaa_port + SV_DMA_MODE); #if 0 - printk("program dmaa: addr = 0x%x, paddr = 0x%x\n", addr, inl(sonic->dmaa_port + SV_DMA_ADDR0)); + printk(KERN_DEBUG "program dmaa: addr = 0x%x, paddr = 0x%x\n", + addr, inl(sonic->dmaa_port + SV_DMA_ADDR0)); #endif } @@ -288,7 +289,8 @@ static inline void snd_sonicvibes_setdmac(struct sonicvibes * sonic, outl(count, sonic->dmac_port + SV_DMA_COUNT0); outb(0x14, sonic->dmac_port + SV_DMA_MODE); #if 0 - printk("program dmac: addr = 0x%x, paddr = 0x%x\n", addr, inl(sonic->dmac_port + SV_DMA_ADDR0)); + printk(KERN_DEBUG "program dmac: addr = 0x%x, paddr = 0x%x\n", + addr, inl(sonic->dmac_port + SV_DMA_ADDR0)); #endif } @@ -355,71 +357,104 @@ static unsigned char snd_sonicvibes_in(struct sonicvibes * sonic, unsigned char #if 0 static void snd_sonicvibes_debug(struct sonicvibes * sonic) { - printk("SV REGS: INDEX = 0x%02x ", inb(SV_REG(sonic, INDEX))); + printk(KERN_DEBUG + "SV REGS: INDEX = 0x%02x ", inb(SV_REG(sonic, INDEX))); printk(" STATUS = 0x%02x\n", inb(SV_REG(sonic, STATUS))); - printk(" 0x00: left input = 0x%02x ", snd_sonicvibes_in(sonic, 0x00)); + printk(KERN_DEBUG + " 0x00: left input = 0x%02x ", snd_sonicvibes_in(sonic, 0x00)); printk(" 0x20: synth rate low = 0x%02x\n", snd_sonicvibes_in(sonic, 0x20)); - printk(" 0x01: right input = 0x%02x ", snd_sonicvibes_in(sonic, 0x01)); + printk(KERN_DEBUG + " 0x01: right input = 0x%02x ", snd_sonicvibes_in(sonic, 0x01)); printk(" 0x21: synth rate high = 0x%02x\n", snd_sonicvibes_in(sonic, 0x21)); - printk(" 0x02: left AUX1 = 0x%02x ", snd_sonicvibes_in(sonic, 0x02)); + printk(KERN_DEBUG + " 0x02: left AUX1 = 0x%02x ", snd_sonicvibes_in(sonic, 0x02)); printk(" 0x22: ADC clock = 0x%02x\n", snd_sonicvibes_in(sonic, 0x22)); - printk(" 0x03: right AUX1 = 0x%02x ", snd_sonicvibes_in(sonic, 0x03)); + printk(KERN_DEBUG + " 0x03: right AUX1 = 0x%02x ", snd_sonicvibes_in(sonic, 0x03)); printk(" 0x23: ADC alt rate = 0x%02x\n", snd_sonicvibes_in(sonic, 0x23)); - printk(" 0x04: left CD = 0x%02x ", snd_sonicvibes_in(sonic, 0x04)); + printk(KERN_DEBUG + " 0x04: left CD = 0x%02x ", snd_sonicvibes_in(sonic, 0x04)); printk(" 0x24: ADC pll M = 0x%02x\n", snd_sonicvibes_in(sonic, 0x24)); - printk(" 0x05: right CD = 0x%02x ", snd_sonicvibes_in(sonic, 0x05)); + printk(KERN_DEBUG + " 0x05: right CD = 0x%02x ", snd_sonicvibes_in(sonic, 0x05)); printk(" 0x25: ADC pll N = 0x%02x\n", snd_sonicvibes_in(sonic, 0x25)); - printk(" 0x06: left line = 0x%02x ", snd_sonicvibes_in(sonic, 0x06)); + printk(KERN_DEBUG + " 0x06: left line = 0x%02x ", snd_sonicvibes_in(sonic, 0x06)); printk(" 0x26: Synth pll M = 0x%02x\n", snd_sonicvibes_in(sonic, 0x26)); - printk(" 0x07: right line = 0x%02x ", snd_sonicvibes_in(sonic, 0x07)); + printk(KERN_DEBUG + " 0x07: right line = 0x%02x ", snd_sonicvibes_in(sonic, 0x07)); printk(" 0x27: Synth pll N = 0x%02x\n", snd_sonicvibes_in(sonic, 0x27)); - printk(" 0x08: MIC = 0x%02x ", snd_sonicvibes_in(sonic, 0x08)); + printk(KERN_DEBUG + " 0x08: MIC = 0x%02x ", snd_sonicvibes_in(sonic, 0x08)); printk(" 0x28: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x28)); - printk(" 0x09: Game port = 0x%02x ", snd_sonicvibes_in(sonic, 0x09)); + printk(KERN_DEBUG + " 0x09: Game port = 0x%02x ", snd_sonicvibes_in(sonic, 0x09)); printk(" 0x29: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x29)); - printk(" 0x0a: left synth = 0x%02x ", snd_sonicvibes_in(sonic, 0x0a)); + printk(KERN_DEBUG + " 0x0a: left synth = 0x%02x ", snd_sonicvibes_in(sonic, 0x0a)); printk(" 0x2a: MPU401 = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2a)); - printk(" 0x0b: right synth = 0x%02x ", snd_sonicvibes_in(sonic, 0x0b)); + printk(KERN_DEBUG + " 0x0b: right synth = 0x%02x ", snd_sonicvibes_in(sonic, 0x0b)); printk(" 0x2b: drive ctrl = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2b)); - printk(" 0x0c: left AUX2 = 0x%02x ", snd_sonicvibes_in(sonic, 0x0c)); + printk(KERN_DEBUG + " 0x0c: left AUX2 = 0x%02x ", snd_sonicvibes_in(sonic, 0x0c)); printk(" 0x2c: SRS space = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2c)); - printk(" 0x0d: right AUX2 = 0x%02x ", snd_sonicvibes_in(sonic, 0x0d)); + printk(KERN_DEBUG + " 0x0d: right AUX2 = 0x%02x ", snd_sonicvibes_in(sonic, 0x0d)); printk(" 0x2d: SRS center = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2d)); - printk(" 0x0e: left analog = 0x%02x ", snd_sonicvibes_in(sonic, 0x0e)); + printk(KERN_DEBUG + " 0x0e: left analog = 0x%02x ", snd_sonicvibes_in(sonic, 0x0e)); printk(" 0x2e: wave source = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2e)); - printk(" 0x0f: right analog = 0x%02x ", snd_sonicvibes_in(sonic, 0x0f)); + printk(KERN_DEBUG + " 0x0f: right analog = 0x%02x ", snd_sonicvibes_in(sonic, 0x0f)); printk(" 0x2f: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2f)); - printk(" 0x10: left PCM = 0x%02x ", snd_sonicvibes_in(sonic, 0x10)); + printk(KERN_DEBUG + " 0x10: left PCM = 0x%02x ", snd_sonicvibes_in(sonic, 0x10)); printk(" 0x30: analog power = 0x%02x\n", snd_sonicvibes_in(sonic, 0x30)); - printk(" 0x11: right PCM = 0x%02x ", snd_sonicvibes_in(sonic, 0x11)); + printk(KERN_DEBUG + " 0x11: right PCM = 0x%02x ", snd_sonicvibes_in(sonic, 0x11)); printk(" 0x31: analog power = 0x%02x\n", snd_sonicvibes_in(sonic, 0x31)); - printk(" 0x12: DMA data format = 0x%02x ", snd_sonicvibes_in(sonic, 0x12)); + printk(KERN_DEBUG + " 0x12: DMA data format = 0x%02x ", snd_sonicvibes_in(sonic, 0x12)); printk(" 0x32: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x32)); - printk(" 0x13: P/C enable = 0x%02x ", snd_sonicvibes_in(sonic, 0x13)); + printk(KERN_DEBUG + " 0x13: P/C enable = 0x%02x ", snd_sonicvibes_in(sonic, 0x13)); printk(" 0x33: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x33)); - printk(" 0x14: U/D button = 0x%02x ", snd_sonicvibes_in(sonic, 0x14)); + printk(KERN_DEBUG + " 0x14: U/D button = 0x%02x ", snd_sonicvibes_in(sonic, 0x14)); printk(" 0x34: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x34)); - printk(" 0x15: revision = 0x%02x ", snd_sonicvibes_in(sonic, 0x15)); + printk(KERN_DEBUG + " 0x15: revision = 0x%02x ", snd_sonicvibes_in(sonic, 0x15)); printk(" 0x35: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x35)); - printk(" 0x16: ADC output ctrl = 0x%02x ", snd_sonicvibes_in(sonic, 0x16)); + printk(KERN_DEBUG + " 0x16: ADC output ctrl = 0x%02x ", snd_sonicvibes_in(sonic, 0x16)); printk(" 0x36: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x36)); - printk(" 0x17: --- = 0x%02x ", snd_sonicvibes_in(sonic, 0x17)); + printk(KERN_DEBUG + " 0x17: --- = 0x%02x ", snd_sonicvibes_in(sonic, 0x17)); printk(" 0x37: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x37)); - printk(" 0x18: DMA A upper cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x18)); + printk(KERN_DEBUG + " 0x18: DMA A upper cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x18)); printk(" 0x38: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x38)); - printk(" 0x19: DMA A lower cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x19)); + printk(KERN_DEBUG + " 0x19: DMA A lower cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x19)); printk(" 0x39: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x39)); - printk(" 0x1a: --- = 0x%02x ", snd_sonicvibes_in(sonic, 0x1a)); + printk(KERN_DEBUG + " 0x1a: --- = 0x%02x ", snd_sonicvibes_in(sonic, 0x1a)); printk(" 0x3a: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3a)); - printk(" 0x1b: --- = 0x%02x ", snd_sonicvibes_in(sonic, 0x1b)); + printk(KERN_DEBUG + " 0x1b: --- = 0x%02x ", snd_sonicvibes_in(sonic, 0x1b)); printk(" 0x3b: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3b)); - printk(" 0x1c: DMA C upper cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x1c)); + printk(KERN_DEBUG + " 0x1c: DMA C upper cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x1c)); printk(" 0x3c: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3c)); - printk(" 0x1d: DMA C upper cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x1d)); + printk(KERN_DEBUG + " 0x1d: DMA C upper cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x1d)); printk(" 0x3d: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3d)); - printk(" 0x1e: PCM rate low = 0x%02x ", snd_sonicvibes_in(sonic, 0x1e)); + printk(KERN_DEBUG + " 0x1e: PCM rate low = 0x%02x ", snd_sonicvibes_in(sonic, 0x1e)); printk(" 0x3e: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3e)); - printk(" 0x1f: PCM rate high = 0x%02x ", snd_sonicvibes_in(sonic, 0x1f)); + printk(KERN_DEBUG + " 0x1f: PCM rate high = 0x%02x ", snd_sonicvibes_in(sonic, 0x1f)); printk(" 0x3f: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3f)); } @@ -476,8 +511,8 @@ static void snd_sonicvibes_pll(unsigned int rate, *res_m = m; *res_n = n; #if 0 - printk("metric = %i, xm = %i, xn = %i\n", metric, xm, xn); - printk("pll: m = 0x%x, r = 0x%x, n = 0x%x\n", reg, m, r, n); + printk(KERN_DEBUG "metric = %i, xm = %i, xn = %i\n", metric, xm, xn); + printk(KERN_DEBUG "pll: m = 0x%x, r = 0x%x, n = 0x%x\n", reg, m, r, n); #endif } diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index c612b435ca2..a9da9c18466 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -68,40 +68,40 @@ static void snd_trident_print_voice_regs(struct snd_trident *trident, int voice) { unsigned int val, tmp; - printk("Trident voice %i:\n", voice); + printk(KERN_DEBUG "Trident voice %i:\n", voice); outb(voice, TRID_REG(trident, T4D_LFO_GC_CIR)); val = inl(TRID_REG(trident, CH_LBA)); - printk("LBA: 0x%x\n", val); + printk(KERN_DEBUG "LBA: 0x%x\n", val); val = inl(TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC)); - printk("GVSel: %i\n", val >> 31); - printk("Pan: 0x%x\n", (val >> 24) & 0x7f); - printk("Vol: 0x%x\n", (val >> 16) & 0xff); - printk("CTRL: 0x%x\n", (val >> 12) & 0x0f); - printk("EC: 0x%x\n", val & 0x0fff); + printk(KERN_DEBUG "GVSel: %i\n", val >> 31); + printk(KERN_DEBUG "Pan: 0x%x\n", (val >> 24) & 0x7f); + printk(KERN_DEBUG "Vol: 0x%x\n", (val >> 16) & 0xff); + printk(KERN_DEBUG "CTRL: 0x%x\n", (val >> 12) & 0x0f); + printk(KERN_DEBUG "EC: 0x%x\n", val & 0x0fff); if (trident->device != TRIDENT_DEVICE_ID_NX) { val = inl(TRID_REG(trident, CH_DX_CSO_ALPHA_FMS)); - printk("CSO: 0x%x\n", val >> 16); + printk(KERN_DEBUG "CSO: 0x%x\n", val >> 16); printk("Alpha: 0x%x\n", (val >> 4) & 0x0fff); - printk("FMS: 0x%x\n", val & 0x0f); + printk(KERN_DEBUG "FMS: 0x%x\n", val & 0x0f); val = inl(TRID_REG(trident, CH_DX_ESO_DELTA)); - printk("ESO: 0x%x\n", val >> 16); - printk("Delta: 0x%x\n", val & 0xffff); + printk(KERN_DEBUG "ESO: 0x%x\n", val >> 16); + printk(KERN_DEBUG "Delta: 0x%x\n", val & 0xffff); val = inl(TRID_REG(trident, CH_DX_FMC_RVOL_CVOL)); } else { // TRIDENT_DEVICE_ID_NX val = inl(TRID_REG(trident, CH_NX_DELTA_CSO)); tmp = (val >> 24) & 0xff; - printk("CSO: 0x%x\n", val & 0x00ffffff); + printk(KERN_DEBUG "CSO: 0x%x\n", val & 0x00ffffff); val = inl(TRID_REG(trident, CH_NX_DELTA_ESO)); tmp |= (val >> 16) & 0xff00; - printk("Delta: 0x%x\n", tmp); - printk("ESO: 0x%x\n", val & 0x00ffffff); + printk(KERN_DEBUG "Delta: 0x%x\n", tmp); + printk(KERN_DEBUG "ESO: 0x%x\n", val & 0x00ffffff); val = inl(TRID_REG(trident, CH_NX_ALPHA_FMS_FMC_RVOL_CVOL)); - printk("Alpha: 0x%x\n", val >> 20); - printk("FMS: 0x%x\n", (val >> 16) & 0x0f); + printk(KERN_DEBUG "Alpha: 0x%x\n", val >> 20); + printk(KERN_DEBUG "FMS: 0x%x\n", (val >> 16) & 0x0f); } - printk("FMC: 0x%x\n", (val >> 14) & 3); - printk("RVol: 0x%x\n", (val >> 7) & 0x7f); - printk("CVol: 0x%x\n", val & 0x7f); + printk(KERN_DEBUG "FMC: 0x%x\n", (val >> 14) & 3); + printk(KERN_DEBUG "RVol: 0x%x\n", (val >> 7) & 0x7f); + printk(KERN_DEBUG "CVol: 0x%x\n", val & 0x7f); } #endif @@ -496,12 +496,17 @@ void snd_trident_write_voice_regs(struct snd_trident * trident, outl(regs[4], TRID_REG(trident, CH_START + 16)); #if 0 - printk("written %i channel:\n", voice->number); - printk(" regs[0] = 0x%x/0x%x\n", regs[0], inl(TRID_REG(trident, CH_START + 0))); - printk(" regs[1] = 0x%x/0x%x\n", regs[1], inl(TRID_REG(trident, CH_START + 4))); - printk(" regs[2] = 0x%x/0x%x\n", regs[2], inl(TRID_REG(trident, CH_START + 8))); - printk(" regs[3] = 0x%x/0x%x\n", regs[3], inl(TRID_REG(trident, CH_START + 12))); - printk(" regs[4] = 0x%x/0x%x\n", regs[4], inl(TRID_REG(trident, CH_START + 16))); + printk(KERN_DEBUG "written %i channel:\n", voice->number); + printk(KERN_DEBUG " regs[0] = 0x%x/0x%x\n", + regs[0], inl(TRID_REG(trident, CH_START + 0))); + printk(KERN_DEBUG " regs[1] = 0x%x/0x%x\n", + regs[1], inl(TRID_REG(trident, CH_START + 4))); + printk(KERN_DEBUG " regs[2] = 0x%x/0x%x\n", + regs[2], inl(TRID_REG(trident, CH_START + 8))); + printk(KERN_DEBUG " regs[3] = 0x%x/0x%x\n", + regs[3], inl(TRID_REG(trident, CH_START + 12))); + printk(KERN_DEBUG " regs[4] = 0x%x/0x%x\n", + regs[4], inl(TRID_REG(trident, CH_START + 16))); #endif } @@ -583,7 +588,7 @@ static void snd_trident_write_vol_reg(struct snd_trident * trident, outb(voice->Vol >> 2, TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC + 2)); break; case TRIDENT_DEVICE_ID_SI7018: - // printk("voice->Vol = 0x%x\n", voice->Vol); + /* printk(KERN_DEBUG "voice->Vol = 0x%x\n", voice->Vol); */ outw((voice->CTRL << 12) | voice->Vol, TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC)); break; diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 1aafe956ee2..fc62d6380f8 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -466,7 +466,10 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre flag = VIA_TBL_BIT_FLAG; /* period boundary */ } else flag = 0; /* period continues to the next */ - // printk("via: tbl %d: at %d size %d (rest %d)\n", idx, ofs, r, rest); + /* + printk(KERN_DEBUG "via: tbl %d: at %d size %d " + "(rest %d)\n", idx, ofs, r, rest); + */ ((u32 *)dev->table.area)[(idx<<1) + 1] = cpu_to_le32(r | flag); dev->idx_table[idx].offset = ofs; dev->idx_table[idx].size = r; diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 5bd79d2a5a1..c0d9cc9dad4 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -328,7 +328,10 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre flag = VIA_TBL_BIT_FLAG; /* period boundary */ } else flag = 0; /* period continues to the next */ - // printk("via: tbl %d: at %d size %d (rest %d)\n", idx, ofs, r, rest); + /* + printk(KERN_DEBUG "via: tbl %d: at %d size %d " + "(rest %d)\n", idx, ofs, r, rest); + */ ((u32 *)dev->table.area)[(idx<<1) + 1] = cpu_to_le32(r | flag); dev->idx_table[idx].offset = ofs; dev->idx_table[idx].size = r; diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c index 7e87f398ff0..c0efe449111 100644 --- a/sound/pci/vx222/vx222_ops.c +++ b/sound/pci/vx222/vx222_ops.c @@ -107,7 +107,9 @@ static unsigned char vx2_inb(struct vx_core *chip, int offset) static void vx2_outb(struct vx_core *chip, int offset, unsigned char val) { outb(val, vx2_reg_addr(chip, offset)); - //printk("outb: %x -> %x\n", val, vx2_reg_addr(chip, offset)); + /* + printk(KERN_DEBUG "outb: %x -> %x\n", val, vx2_reg_addr(chip, offset)); + */ } /** @@ -126,7 +128,9 @@ static unsigned int vx2_inl(struct vx_core *chip, int offset) */ static void vx2_outl(struct vx_core *chip, int offset, unsigned int val) { - // printk("outl: %x -> %x\n", val, vx2_reg_addr(chip, offset)); + /* + printk(KERN_DEBUG "outl: %x -> %x\n", val, vx2_reg_addr(chip, offset)); + */ outl(val, vx2_reg_addr(chip, offset)); } diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 90d0d62bd0b..2f0925236a1 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -318,7 +318,12 @@ static void snd_ymfpci_pcm_interrupt(struct snd_ymfpci *chip, struct snd_ymfpci_ ypcm->period_pos += delta; ypcm->last_pos = pos; if (ypcm->period_pos >= ypcm->period_size) { - // printk("done - active_bank = 0x%x, start = 0x%x\n", chip->active_bank, voice->bank[chip->active_bank].start); + /* + printk(KERN_DEBUG + "done - active_bank = 0x%x, start = 0x%x\n", + chip->active_bank, + voice->bank[chip->active_bank].start); + */ ypcm->period_pos %= ypcm->period_size; spin_unlock(&chip->reg_lock); snd_pcm_period_elapsed(ypcm->substream); @@ -366,7 +371,12 @@ static void snd_ymfpci_pcm_capture_interrupt(struct snd_pcm_substream *substream ypcm->last_pos = pos; if (ypcm->period_pos >= ypcm->period_size) { ypcm->period_pos %= ypcm->period_size; - // printk("done - active_bank = 0x%x, start = 0x%x\n", chip->active_bank, voice->bank[chip->active_bank].start); + /* + printk(KERN_DEBUG + "done - active_bank = 0x%x, start = 0x%x\n", + chip->active_bank, + voice->bank[chip->active_bank].start); + */ spin_unlock(&chip->reg_lock); snd_pcm_period_elapsed(substream); spin_lock(&chip->reg_lock); -- GitLab From 2ebfb8eeb8f244f9d25937d31a947895cf819e26 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 5 Feb 2009 16:11:58 +0100 Subject: [PATCH 1206/4982] ALSA: Add missing KERN_* prefix to printk in other sound/* Signed-off-by: Takashi Iwai --- sound/arm/sa11xx-uda1341.c | 2 +- sound/mips/au1x00.c | 2 +- sound/pcmcia/pdaudiocf/pdaudiocf_core.c | 23 +++++++++++++++-------- sound/pcmcia/pdaudiocf/pdaudiocf_irq.c | 4 ++-- sound/sparc/amd7930.c | 5 +++-- 5 files changed, 22 insertions(+), 14 deletions(-) diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c index 1dcd51d81d1..ed481a866a3 100644 --- a/sound/arm/sa11xx-uda1341.c +++ b/sound/arm/sa11xx-uda1341.c @@ -914,7 +914,7 @@ static int __devinit sa11xx_uda1341_probe(struct platform_device *devptr) snd_card_set_dev(card, &devptr->dev); if ((err = snd_card_register(card)) == 0) { - printk( KERN_INFO "iPAQ audio support initialized\n" ); + printk(KERN_INFO "iPAQ audio support initialized\n"); platform_set_drvdata(devptr, card); return 0; } diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c index 1881cec11e7..7c1afc96ab8 100644 --- a/sound/mips/au1x00.c +++ b/sound/mips/au1x00.c @@ -678,7 +678,7 @@ au1000_init(void) return err; } - printk( KERN_INFO "ALSA AC97: Driver Initialized\n" ); + printk(KERN_INFO "ALSA AC97: Driver Initialized\n"); au1000_card = card; return 0; } diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c index dfa40b0ed86..5d2afa0b0ce 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c @@ -82,14 +82,21 @@ static void pdacf_ak4117_write(void *private_data, unsigned char reg, unsigned c #if 0 void pdacf_dump(struct snd_pdacf *chip) { - printk("PDAUDIOCF DUMP (0x%lx):\n", chip->port); - printk("WPD : 0x%x\n", inw(chip->port + PDAUDIOCF_REG_WDP)); - printk("RDP : 0x%x\n", inw(chip->port + PDAUDIOCF_REG_RDP)); - printk("TCR : 0x%x\n", inw(chip->port + PDAUDIOCF_REG_TCR)); - printk("SCR : 0x%x\n", inw(chip->port + PDAUDIOCF_REG_SCR)); - printk("ISR : 0x%x\n", inw(chip->port + PDAUDIOCF_REG_ISR)); - printk("IER : 0x%x\n", inw(chip->port + PDAUDIOCF_REG_IER)); - printk("AK_IFR : 0x%x\n", inw(chip->port + PDAUDIOCF_REG_AK_IFR)); + printk(KERN_DEBUG "PDAUDIOCF DUMP (0x%lx):\n", chip->port); + printk(KERN_DEBUG "WPD : 0x%x\n", + inw(chip->port + PDAUDIOCF_REG_WDP)); + printk(KERN_DEBUG "RDP : 0x%x\n", + inw(chip->port + PDAUDIOCF_REG_RDP)); + printk(KERN_DEBUG "TCR : 0x%x\n", + inw(chip->port + PDAUDIOCF_REG_TCR)); + printk(KERN_DEBUG "SCR : 0x%x\n", + inw(chip->port + PDAUDIOCF_REG_SCR)); + printk(KERN_DEBUG "ISR : 0x%x\n", + inw(chip->port + PDAUDIOCF_REG_ISR)); + printk(KERN_DEBUG "IER : 0x%x\n", + inw(chip->port + PDAUDIOCF_REG_IER)); + printk(KERN_DEBUG "AK_IFR : 0x%x\n", + inw(chip->port + PDAUDIOCF_REG_AK_IFR)); } #endif diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c index ea903c8e90d..dcd32201bc8 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c @@ -269,7 +269,7 @@ void pdacf_tasklet(unsigned long private_data) rdp = inw(chip->port + PDAUDIOCF_REG_RDP); wdp = inw(chip->port + PDAUDIOCF_REG_WDP); - // printk("TASKLET: rdp = %x, wdp = %x\n", rdp, wdp); + /* printk(KERN_DEBUG "TASKLET: rdp = %x, wdp = %x\n", rdp, wdp); */ size = wdp - rdp; if (size < 0) size += 0x10000; @@ -321,5 +321,5 @@ void pdacf_tasklet(unsigned long private_data) spin_lock(&chip->reg_lock); } spin_unlock(&chip->reg_lock); - // printk("TASKLET: end\n"); + /* printk(KERN_DEBUG "TASKLET: end\n"); */ } diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index f87933e4881..7cbc725934e 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c @@ -954,7 +954,8 @@ static int __devinit snd_amd7930_create(struct snd_card *card, amd->regs = of_ioremap(&op->resource[0], 0, resource_size(&op->resource[0]), "amd7930"); if (!amd->regs) { - snd_printk("amd7930-%d: Unable to map chip registers.\n", dev); + snd_printk(KERN_ERR + "amd7930-%d: Unable to map chip registers.\n", dev); return -EIO; } @@ -962,7 +963,7 @@ static int __devinit snd_amd7930_create(struct snd_card *card, if (request_irq(irq, snd_amd7930_interrupt, IRQF_DISABLED | IRQF_SHARED, "amd7930", amd)) { - snd_printk("amd7930-%d: Unable to grab IRQ %d\n", + snd_printk(KERN_ERR "amd7930-%d: Unable to grab IRQ %d\n", dev, irq); snd_amd7930_free(amd); return -EBUSY; -- GitLab From dd542f169aaa35f4ac0d063e04b41c648a93887c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 5 Feb 2009 16:15:39 +0100 Subject: [PATCH 1207/4982] ALSA: ca0106 - Add missing KERN_* prefix to printk Signed-off-by: Takashi Iwai --- sound/pci/ca0106/ca0106_main.c | 91 ++++++++++++++++++++++++++-------- 1 file changed, 71 insertions(+), 20 deletions(-) diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 3aac7e6489c..dac8a5f040e 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -412,7 +412,9 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, } tmp = reg << 25 | value << 16; - // snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value); + /* + snd_printk(KERN_DEBUG "I2C-write:reg=0x%x, value=0x%x\n", reg, value); + */ /* Not sure what this I2C channel controls. */ /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */ @@ -430,7 +432,7 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, /* Wait till the transaction ends */ while (1) { status = snd_ca0106_ptr_read(emu, I2C_A, 0); - //snd_printk("I2C:status=0x%x\n", status); + /*snd_printk(KERN_DEBUG "I2C:status=0x%x\n", status);*/ timeout++; if ((status & I2C_A_ADC_START) == 0) break; @@ -529,7 +531,10 @@ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substr channel->number = channel_id; channel->use = 1; - //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel); + /* + printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n", + channel_id, chip, channel); + */ //channel->interrupt = snd_ca0106_pcm_channel_interrupt; channel->epcm = epcm; if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) @@ -622,7 +627,10 @@ static int snd_ca0106_pcm_open_capture_channel(struct snd_pcm_substream *substre channel->number = channel_id; channel->use = 1; - //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel); + /* + printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n", + channel_id, chip, channel); + */ //channel->interrupt = snd_ca0106_pcm_channel_interrupt; channel->epcm = epcm; if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) @@ -713,9 +721,20 @@ static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream) u32 reg71; int i; - //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1)); - //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base); - //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes); +#if 0 /* debug */ + snd_printk(KERN_DEBUG + "prepare:channel_number=%d, rate=%d, format=0x%x, " + "channels=%d, buffer_size=%ld, period_size=%ld, " + "periods=%u, frames_to_bytes=%d\n", + channel, runtime->rate, runtime->format, + runtime->channels, runtime->buffer_size, + runtime->period_size, runtime->periods, + frames_to_bytes(runtime, 1)); + snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, table_base=%p\n", + runtime->dma_addr, runtime->dma_area, table_base); + snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n", + emu->buffer.addr, emu->buffer.area, emu->buffer.bytes); +#endif /* debug */ /* Rate can be set per channel. */ /* reg40 control host to fifo */ /* reg71 controls DAC rate. */ @@ -807,9 +826,20 @@ static int snd_ca0106_pcm_prepare_capture(struct snd_pcm_substream *substream) u32 reg71_set = 0; u32 reg71; - //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1)); - //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base); - //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes); +#if 0 /* debug */ + snd_printk(KERN_DEBUG + "prepare:channel_number=%d, rate=%d, format=0x%x, " + "channels=%d, buffer_size=%ld, period_size=%ld, " + "periods=%u, frames_to_bytes=%d\n", + channel, runtime->rate, runtime->format, + runtime->channels, runtime->buffer_size, + runtime->period_size, runtime->periods, + frames_to_bytes(runtime, 1)); + snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, table_base=%p\n", + runtime->dma_addr, runtime->dma_area, table_base); + snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n", + emu->buffer.addr, emu->buffer.area, emu->buffer.bytes); +#endif /* debug */ /* reg71 controls ADC rate. */ switch (runtime->rate) { case 44100: @@ -854,7 +884,14 @@ static int snd_ca0106_pcm_prepare_capture(struct snd_pcm_substream *substream) } - //printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, frames_to_bytes(runtime, 1)); + /* + printk(KERN_DEBUG + "prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, " + "buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n", + channel, runtime->rate, runtime->format, runtime->channels, + runtime->buffer_size, runtime->period_size, + frames_to_bytes(runtime, 1)); + */ snd_ca0106_ptr_write(emu, 0x13, channel, 0); snd_ca0106_ptr_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr); snd_ca0106_ptr_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes @@ -896,13 +933,13 @@ static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream, runtime = s->runtime; epcm = runtime->private_data; channel = epcm->channel_id; - /* snd_printk("channel=%d\n",channel); */ + /* snd_printk(KERN_DEBUG "channel=%d\n", channel); */ epcm->running = running; basic |= (0x1 << channel); extended |= (0x10 << channel); snd_pcm_trigger_done(s, substream); } - /* snd_printk("basic=0x%x, extended=0x%x\n",basic, extended); */ + /* snd_printk(KERN_DEBUG "basic=0x%x, extended=0x%x\n",basic, extended); */ switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -980,8 +1017,13 @@ snd_ca0106_pcm_pointer_playback(struct snd_pcm_substream *substream) ptr=ptr2; if (ptr >= runtime->buffer_size) ptr -= runtime->buffer_size; - //printk("ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", ptr1, ptr2, ptr, (int)runtime->buffer_size, (int)runtime->period_size, (int)runtime->frame_bits, (int)runtime->rate); - + /* + printk(KERN_DEBUG "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, " + "buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", + ptr1, ptr2, ptr, (int)runtime->buffer_size, + (int)runtime->period_size, (int)runtime->frame_bits, + (int)runtime->rate); + */ return ptr; } @@ -1003,8 +1045,13 @@ snd_ca0106_pcm_pointer_capture(struct snd_pcm_substream *substream) ptr=ptr2; if (ptr >= runtime->buffer_size) ptr -= runtime->buffer_size; - //printk("ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", ptr1, ptr2, ptr, (int)runtime->buffer_size, (int)runtime->period_size, (int)runtime->frame_bits, (int)runtime->rate); - + /* + printk(KERN_DEBUG "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, " + "buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", + ptr1, ptr2, ptr, (int)runtime->buffer_size, + (int)runtime->period_size, (int)runtime->frame_bits, + (int)runtime->rate); + */ return ptr; } @@ -1189,8 +1236,12 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id) return IRQ_NONE; stat76 = snd_ca0106_ptr_read(chip, EXTENDED_INT, 0); - //snd_printk("interrupt status = 0x%08x, stat76=0x%08x\n", status, stat76); - //snd_printk("ptr=0x%08x\n",snd_ca0106_ptr_read(chip, PLAYBACK_POINTER, 0)); + /* + snd_printk(KERN_DEBUG "interrupt status = 0x%08x, stat76=0x%08x\n", + status, stat76); + snd_printk(KERN_DEBUG "ptr=0x%08x\n", + snd_ca0106_ptr_read(chip, PLAYBACK_POINTER, 0)); + */ mask = 0x11; /* 0x1 for one half, 0x10 for the other half period. */ for(i = 0; i < 4; i++) { pchannel = &(chip->playback_channels[i]); @@ -1478,7 +1529,7 @@ static void ca0106_init_chip(struct snd_ca0106 *chip, int resume) int size, n; size = ARRAY_SIZE(i2c_adc_init); - /* snd_printk("I2C:array size=0x%x\n", size); */ + /* snd_printk(KERN_DEBUG "I2C:array size=0x%x\n", size); */ for (n = 0; n < size; n++) snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], i2c_adc_init[n][1]); -- GitLab From 130ace11a9dc682541336d1fe5cb3bc7771a149e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 6 Feb 2009 00:57:48 +0900 Subject: [PATCH 1208/4982] x86: style cleanups for xen assemblies Make the following style cleanups: * drop unnecessary //#include from xen-asm_32.S * compulsive adding of space after comma * reformat multiline comments Signed-off-by: Tejun Heo Signed-off-by: Ingo Molnar --- arch/x86/xen/xen-asm.S | 78 +++++++------ arch/x86/xen/xen-asm_32.S | 238 ++++++++++++++++++++------------------ arch/x86/xen/xen-asm_64.S | 107 ++++++++--------- 3 files changed, 219 insertions(+), 204 deletions(-) diff --git a/arch/x86/xen/xen-asm.S b/arch/x86/xen/xen-asm.S index 4c6f9679913..79d7362ad6d 100644 --- a/arch/x86/xen/xen-asm.S +++ b/arch/x86/xen/xen-asm.S @@ -1,14 +1,14 @@ /* - Asm versions of Xen pv-ops, suitable for either direct use or inlining. - The inline versions are the same as the direct-use versions, with the - pre- and post-amble chopped off. - - This code is encoded for size rather than absolute efficiency, - with a view to being able to inline as much as possible. - - We only bother with direct forms (ie, vcpu in percpu data) of - the operations here; the indirect forms are better handled in - C, since they're generally too large to inline anyway. + * Asm versions of Xen pv-ops, suitable for either direct use or + * inlining. The inline versions are the same as the direct-use + * versions, with the pre- and post-amble chopped off. + * + * This code is encoded for size rather than absolute efficiency, with + * a view to being able to inline as much as possible. + * + * We only bother with direct forms (ie, vcpu in percpu data) of the + * operations here; the indirect forms are better handled in C, since + * they're generally too large to inline anyway. */ #include @@ -18,17 +18,19 @@ #include "xen-asm.h" /* - Enable events. This clears the event mask and tests the pending - event status with one and operation. If there are pending - events, then enter the hypervisor to get them handled. + * Enable events. This clears the event mask and tests the pending + * event status with one and operation. If there are pending events, + * then enter the hypervisor to get them handled. */ ENTRY(xen_irq_enable_direct) /* Unmask events */ movb $0, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask - /* Preempt here doesn't matter because that will deal with - any pending interrupts. The pending check may end up being - run on the wrong CPU, but that doesn't hurt. */ + /* + * Preempt here doesn't matter because that will deal with any + * pending interrupts. The pending check may end up being run + * on the wrong CPU, but that doesn't hurt. + */ /* Test for pending */ testb $0xff, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_pending @@ -43,8 +45,8 @@ ENDPATCH(xen_irq_enable_direct) /* - Disabling events is simply a matter of making the event mask - non-zero. + * Disabling events is simply a matter of making the event mask + * non-zero. */ ENTRY(xen_irq_disable_direct) movb $1, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask @@ -54,18 +56,18 @@ ENDPATCH(xen_irq_disable_direct) RELOC(xen_irq_disable_direct, 0) /* - (xen_)save_fl is used to get the current interrupt enable status. - Callers expect the status to be in X86_EFLAGS_IF, and other bits - may be set in the return value. We take advantage of this by - making sure that X86_EFLAGS_IF has the right value (and other bits - in that byte are 0), but other bits in the return value are - undefined. We need to toggle the state of the bit, because - Xen and x86 use opposite senses (mask vs enable). + * (xen_)save_fl is used to get the current interrupt enable status. + * Callers expect the status to be in X86_EFLAGS_IF, and other bits + * may be set in the return value. We take advantage of this by + * making sure that X86_EFLAGS_IF has the right value (and other bits + * in that byte are 0), but other bits in the return value are + * undefined. We need to toggle the state of the bit, because Xen and + * x86 use opposite senses (mask vs enable). */ ENTRY(xen_save_fl_direct) testb $0xff, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask setz %ah - addb %ah,%ah + addb %ah, %ah ENDPATCH(xen_save_fl_direct) ret ENDPROC(xen_save_fl_direct) @@ -73,12 +75,11 @@ ENDPATCH(xen_save_fl_direct) /* - In principle the caller should be passing us a value return - from xen_save_fl_direct, but for robustness sake we test only - the X86_EFLAGS_IF flag rather than the whole byte. After - setting the interrupt mask state, it checks for unmasked - pending events and enters the hypervisor to get them delivered - if so. + * In principle the caller should be passing us a value return from + * xen_save_fl_direct, but for robustness sake we test only the + * X86_EFLAGS_IF flag rather than the whole byte. After setting the + * interrupt mask state, it checks for unmasked pending events and + * enters the hypervisor to get them delivered if so. */ ENTRY(xen_restore_fl_direct) #ifdef CONFIG_X86_64 @@ -87,9 +88,11 @@ ENTRY(xen_restore_fl_direct) testb $X86_EFLAGS_IF>>8, %ah #endif setz PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask - /* Preempt here doesn't matter because that will deal with - any pending interrupts. The pending check may end up being - run on the wrong CPU, but that doesn't hurt. */ + /* + * Preempt here doesn't matter because that will deal with any + * pending interrupts. The pending check may end up being run + * on the wrong CPU, but that doesn't hurt. + */ /* check for unmasked and pending */ cmpw $0x0001, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_pending @@ -103,8 +106,8 @@ ENDPATCH(xen_restore_fl_direct) /* - Force an event check by making a hypercall, - but preserve regs before making the call. + * Force an event check by making a hypercall, but preserve regs + * before making the call. */ check_events: #ifdef CONFIG_X86_32 @@ -137,4 +140,3 @@ check_events: pop %rax #endif ret - diff --git a/arch/x86/xen/xen-asm_32.S b/arch/x86/xen/xen-asm_32.S index 082d173caaf..88e15deb8b8 100644 --- a/arch/x86/xen/xen-asm_32.S +++ b/arch/x86/xen/xen-asm_32.S @@ -1,17 +1,16 @@ /* - Asm versions of Xen pv-ops, suitable for either direct use or inlining. - The inline versions are the same as the direct-use versions, with the - pre- and post-amble chopped off. - - This code is encoded for size rather than absolute efficiency, - with a view to being able to inline as much as possible. - - We only bother with direct forms (ie, vcpu in pda) of the operations - here; the indirect forms are better handled in C, since they're - generally too large to inline anyway. + * Asm versions of Xen pv-ops, suitable for either direct use or + * inlining. The inline versions are the same as the direct-use + * versions, with the pre- and post-amble chopped off. + * + * This code is encoded for size rather than absolute efficiency, with + * a view to being able to inline as much as possible. + * + * We only bother with direct forms (ie, vcpu in pda) of the + * operations here; the indirect forms are better handled in C, since + * they're generally too large to inline anyway. */ -//#include #include #include #include @@ -21,8 +20,8 @@ #include "xen-asm.h" /* - Force an event check by making a hypercall, - but preserve regs before making the call. + * Force an event check by making a hypercall, but preserve regs + * before making the call. */ check_events: push %eax @@ -35,10 +34,10 @@ check_events: ret /* - We can't use sysexit directly, because we're not running in ring0. - But we can easily fake it up using iret. Assuming xen_sysexit - is jumped to with a standard stack frame, we can just strip it - back to a standard iret frame and use iret. + * We can't use sysexit directly, because we're not running in ring0. + * But we can easily fake it up using iret. Assuming xen_sysexit is + * jumped to with a standard stack frame, we can just strip it back to + * a standard iret frame and use iret. */ ENTRY(xen_sysexit) movl PT_EAX(%esp), %eax /* Shouldn't be necessary? */ @@ -49,33 +48,31 @@ ENTRY(xen_sysexit) ENDPROC(xen_sysexit) /* - This is run where a normal iret would be run, with the same stack setup: - 8: eflags - 4: cs - esp-> 0: eip - - This attempts to make sure that any pending events are dealt - with on return to usermode, but there is a small window in - which an event can happen just before entering usermode. If - the nested interrupt ends up setting one of the TIF_WORK_MASK - pending work flags, they will not be tested again before - returning to usermode. This means that a process can end up - with pending work, which will be unprocessed until the process - enters and leaves the kernel again, which could be an - unbounded amount of time. This means that a pending signal or - reschedule event could be indefinitely delayed. - - The fix is to notice a nested interrupt in the critical - window, and if one occurs, then fold the nested interrupt into - the current interrupt stack frame, and re-process it - iteratively rather than recursively. This means that it will - exit via the normal path, and all pending work will be dealt - with appropriately. - - Because the nested interrupt handler needs to deal with the - current stack state in whatever form its in, we keep things - simple by only using a single register which is pushed/popped - on the stack. + * This is run where a normal iret would be run, with the same stack setup: + * 8: eflags + * 4: cs + * esp-> 0: eip + * + * This attempts to make sure that any pending events are dealt with + * on return to usermode, but there is a small window in which an + * event can happen just before entering usermode. If the nested + * interrupt ends up setting one of the TIF_WORK_MASK pending work + * flags, they will not be tested again before returning to + * usermode. This means that a process can end up with pending work, + * which will be unprocessed until the process enters and leaves the + * kernel again, which could be an unbounded amount of time. This + * means that a pending signal or reschedule event could be + * indefinitely delayed. + * + * The fix is to notice a nested interrupt in the critical window, and + * if one occurs, then fold the nested interrupt into the current + * interrupt stack frame, and re-process it iteratively rather than + * recursively. This means that it will exit via the normal path, and + * all pending work will be dealt with appropriately. + * + * Because the nested interrupt handler needs to deal with the current + * stack state in whatever form its in, we keep things simple by only + * using a single register which is pushed/popped on the stack. */ ENTRY(xen_iret) /* test eflags for special cases */ @@ -85,13 +82,15 @@ ENTRY(xen_iret) push %eax ESP_OFFSET=4 # bytes pushed onto stack - /* Store vcpu_info pointer for easy access. Do it this - way to avoid having to reload %fs */ + /* + * Store vcpu_info pointer for easy access. Do it this way to + * avoid having to reload %fs + */ #ifdef CONFIG_SMP GET_THREAD_INFO(%eax) - movl TI_cpu(%eax),%eax - movl __per_cpu_offset(,%eax,4),%eax - mov per_cpu__xen_vcpu(%eax),%eax + movl TI_cpu(%eax), %eax + movl __per_cpu_offset(,%eax,4), %eax + mov per_cpu__xen_vcpu(%eax), %eax #else movl per_cpu__xen_vcpu, %eax #endif @@ -99,37 +98,46 @@ ENTRY(xen_iret) /* check IF state we're restoring */ testb $X86_EFLAGS_IF>>8, 8+1+ESP_OFFSET(%esp) - /* Maybe enable events. Once this happens we could get a - recursive event, so the critical region starts immediately - afterwards. However, if that happens we don't end up - resuming the code, so we don't have to be worried about - being preempted to another CPU. */ + /* + * Maybe enable events. Once this happens we could get a + * recursive event, so the critical region starts immediately + * afterwards. However, if that happens we don't end up + * resuming the code, so we don't have to be worried about + * being preempted to another CPU. + */ setz XEN_vcpu_info_mask(%eax) xen_iret_start_crit: /* check for unmasked and pending */ cmpw $0x0001, XEN_vcpu_info_pending(%eax) - /* If there's something pending, mask events again so we - can jump back into xen_hypervisor_callback */ + /* + * If there's something pending, mask events again so we can + * jump back into xen_hypervisor_callback + */ sete XEN_vcpu_info_mask(%eax) popl %eax - /* From this point on the registers are restored and the stack - updated, so we don't need to worry about it if we're preempted */ + /* + * From this point on the registers are restored and the stack + * updated, so we don't need to worry about it if we're + * preempted + */ iret_restore_end: - /* Jump to hypervisor_callback after fixing up the stack. - Events are masked, so jumping out of the critical - region is OK. */ + /* + * Jump to hypervisor_callback after fixing up the stack. + * Events are masked, so jumping out of the critical region is + * OK. + */ je xen_hypervisor_callback 1: iret xen_iret_end_crit: -.section __ex_table,"a" +.section __ex_table, "a" .align 4 - .long 1b,iret_exc + .long 1b, iret_exc .previous hyper_iret: @@ -139,55 +147,55 @@ hyper_iret: .globl xen_iret_start_crit, xen_iret_end_crit /* - This is called by xen_hypervisor_callback in entry.S when it sees - that the EIP at the time of interrupt was between xen_iret_start_crit - and xen_iret_end_crit. We're passed the EIP in %eax so we can do - a more refined determination of what to do. - - The stack format at this point is: - ---------------- - ss : (ss/esp may be present if we came from usermode) - esp : - eflags } outer exception info - cs } - eip } - ---------------- <- edi (copy dest) - eax : outer eax if it hasn't been restored - ---------------- - eflags } nested exception info - cs } (no ss/esp because we're nested - eip } from the same ring) - orig_eax }<- esi (copy src) - - - - - - - - - - fs } - es } - ds } SAVE_ALL state - eax } - : : - ebx }<- esp - ---------------- - - In order to deliver the nested exception properly, we need to shift - everything from the return addr up to the error code so it - sits just under the outer exception info. This means that when we - handle the exception, we do it in the context of the outer exception - rather than starting a new one. - - The only caveat is that if the outer eax hasn't been - restored yet (ie, it's still on stack), we need to insert - its value into the SAVE_ALL state before going on, since - it's usermode state which we eventually need to restore. + * This is called by xen_hypervisor_callback in entry.S when it sees + * that the EIP at the time of interrupt was between + * xen_iret_start_crit and xen_iret_end_crit. We're passed the EIP in + * %eax so we can do a more refined determination of what to do. + * + * The stack format at this point is: + * ---------------- + * ss : (ss/esp may be present if we came from usermode) + * esp : + * eflags } outer exception info + * cs } + * eip } + * ---------------- <- edi (copy dest) + * eax : outer eax if it hasn't been restored + * ---------------- + * eflags } nested exception info + * cs } (no ss/esp because we're nested + * eip } from the same ring) + * orig_eax }<- esi (copy src) + * - - - - - - - - + * fs } + * es } + * ds } SAVE_ALL state + * eax } + * : : + * ebx }<- esp + * ---------------- + * + * In order to deliver the nested exception properly, we need to shift + * everything from the return addr up to the error code so it sits + * just under the outer exception info. This means that when we + * handle the exception, we do it in the context of the outer + * exception rather than starting a new one. + * + * The only caveat is that if the outer eax hasn't been restored yet + * (ie, it's still on stack), we need to insert its value into the + * SAVE_ALL state before going on, since it's usermode state which we + * eventually need to restore. */ ENTRY(xen_iret_crit_fixup) /* - Paranoia: Make sure we're really coming from kernel space. - One could imagine a case where userspace jumps into the - critical range address, but just before the CPU delivers a GP, - it decides to deliver an interrupt instead. Unlikely? - Definitely. Easy to avoid? Yes. The Intel documents - explicitly say that the reported EIP for a bad jump is the - jump instruction itself, not the destination, but some virtual - environments get this wrong. + * Paranoia: Make sure we're really coming from kernel space. + * One could imagine a case where userspace jumps into the + * critical range address, but just before the CPU delivers a + * GP, it decides to deliver an interrupt instead. Unlikely? + * Definitely. Easy to avoid? Yes. The Intel documents + * explicitly say that the reported EIP for a bad jump is the + * jump instruction itself, not the destination, but some + * virtual environments get this wrong. */ movl PT_CS(%esp), %ecx andl $SEGMENT_RPL_MASK, %ecx @@ -197,15 +205,17 @@ ENTRY(xen_iret_crit_fixup) lea PT_ORIG_EAX(%esp), %esi lea PT_EFLAGS(%esp), %edi - /* If eip is before iret_restore_end then stack - hasn't been restored yet. */ + /* + * If eip is before iret_restore_end then stack + * hasn't been restored yet. + */ cmp $iret_restore_end, %eax jae 1f - movl 0+4(%edi),%eax /* copy EAX (just above top of frame) */ + movl 0+4(%edi), %eax /* copy EAX (just above top of frame) */ movl %eax, PT_EAX(%esp) - lea ESP_OFFSET(%edi),%edi /* move dest up over saved regs */ + lea ESP_OFFSET(%edi), %edi /* move dest up over saved regs */ /* set up the copy */ 1: std @@ -213,6 +223,6 @@ ENTRY(xen_iret_crit_fixup) rep movsl cld - lea 4(%edi),%esp /* point esp to new frame */ + lea 4(%edi), %esp /* point esp to new frame */ 2: jmp xen_do_upcall diff --git a/arch/x86/xen/xen-asm_64.S b/arch/x86/xen/xen-asm_64.S index d205a283efe..02f496a8dba 100644 --- a/arch/x86/xen/xen-asm_64.S +++ b/arch/x86/xen/xen-asm_64.S @@ -1,14 +1,14 @@ /* - Asm versions of Xen pv-ops, suitable for either direct use or inlining. - The inline versions are the same as the direct-use versions, with the - pre- and post-amble chopped off. - - This code is encoded for size rather than absolute efficiency, - with a view to being able to inline as much as possible. - - We only bother with direct forms (ie, vcpu in pda) of the operations - here; the indirect forms are better handled in C, since they're - generally too large to inline anyway. + * Asm versions of Xen pv-ops, suitable for either direct use or + * inlining. The inline versions are the same as the direct-use + * versions, with the pre- and post-amble chopped off. + * + * This code is encoded for size rather than absolute efficiency, with + * a view to being able to inline as much as possible. + * + * We only bother with direct forms (ie, vcpu in pda) of the + * operations here; the indirect forms are better handled in C, since + * they're generally too large to inline anyway. */ #include @@ -21,25 +21,25 @@ #include "xen-asm.h" ENTRY(xen_adjust_exception_frame) - mov 8+0(%rsp),%rcx - mov 8+8(%rsp),%r11 + mov 8+0(%rsp), %rcx + mov 8+8(%rsp), %r11 ret $16 hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32 /* - Xen64 iret frame: - - ss - rsp - rflags - cs - rip <-- standard iret frame - - flags - - rcx } - r11 }<-- pushed by hypercall page -rsp -> rax } + * Xen64 iret frame: + * + * ss + * rsp + * rflags + * cs + * rip <-- standard iret frame + * + * flags + * + * rcx } + * r11 }<-- pushed by hypercall page + * rsp->rax } */ ENTRY(xen_iret) pushq $0 @@ -48,8 +48,8 @@ ENDPATCH(xen_iret) RELOC(xen_iret, 1b+1) /* - sysexit is not used for 64-bit processes, so it's - only ever used to return to 32-bit compat userspace. + * sysexit is not used for 64-bit processes, so it's only ever used to + * return to 32-bit compat userspace. */ ENTRY(xen_sysexit) pushq $__USER32_DS @@ -64,10 +64,12 @@ ENDPATCH(xen_sysexit) RELOC(xen_sysexit, 1b+1) ENTRY(xen_sysret64) - /* We're already on the usermode stack at this point, but still - with the kernel gs, so we can easily switch back */ + /* + * We're already on the usermode stack at this point, but + * still with the kernel gs, so we can easily switch back + */ movq %rsp, PER_CPU_VAR(old_rsp) - movq PER_CPU_VAR(kernel_stack),%rsp + movq PER_CPU_VAR(kernel_stack), %rsp pushq $__USER_DS pushq PER_CPU_VAR(old_rsp) @@ -81,8 +83,10 @@ ENDPATCH(xen_sysret64) RELOC(xen_sysret64, 1b+1) ENTRY(xen_sysret32) - /* We're already on the usermode stack at this point, but still - with the kernel gs, so we can easily switch back */ + /* + * We're already on the usermode stack at this point, but + * still with the kernel gs, so we can easily switch back + */ movq %rsp, PER_CPU_VAR(old_rsp) movq PER_CPU_VAR(kernel_stack), %rsp @@ -98,28 +102,27 @@ ENDPATCH(xen_sysret32) RELOC(xen_sysret32, 1b+1) /* - Xen handles syscall callbacks much like ordinary exceptions, - which means we have: - - kernel gs - - kernel rsp - - an iret-like stack frame on the stack (including rcx and r11): - ss - rsp - rflags - cs - rip - r11 - rsp-> rcx - - In all the entrypoints, we undo all that to make it look - like a CPU-generated syscall/sysenter and jump to the normal - entrypoint. + * Xen handles syscall callbacks much like ordinary exceptions, which + * means we have: + * - kernel gs + * - kernel rsp + * - an iret-like stack frame on the stack (including rcx and r11): + * ss + * rsp + * rflags + * cs + * rip + * r11 + * rsp->rcx + * + * In all the entrypoints, we undo all that to make it look like a + * CPU-generated syscall/sysenter and jump to the normal entrypoint. */ .macro undo_xen_syscall - mov 0*8(%rsp),%rcx - mov 1*8(%rsp),%r11 - mov 5*8(%rsp),%rsp + mov 0*8(%rsp), %rcx + mov 1*8(%rsp), %r11 + mov 5*8(%rsp), %rsp .endm /* Normal 64-bit system call target */ @@ -146,7 +149,7 @@ ENDPROC(xen_sysenter_target) ENTRY(xen_syscall32_target) ENTRY(xen_sysenter_target) - lea 16(%rsp), %rsp /* strip %rcx,%r11 */ + lea 16(%rsp), %rsp /* strip %rcx, %r11 */ mov $-ENOSYS, %rax pushq $VGCF_in_syscall jmp hypercall_iret -- GitLab From 56fc82c5360cdf0b250b5eb74f38657b0402faa5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 6 Feb 2009 00:48:02 +0900 Subject: [PATCH 1209/4982] modpost: NOBITS sections may point beyond the end of the file Impact: fix link failure on certain toolchains with specific configs Recent percpu change made x86_64 split .data.init section into three separate segments - data.init, percpu and data.init2. data.init2 gets .data.nosave and .bss.* and is followed by .notes segment. Depending on configuration both segments might contain no data, in which case the tool chain makes the section header to contain offset beyond the end of the file. modpost isn't too happy about it and fails build - as reported by Pawel Dziekonski: Building modules, stage 2. MODPOST 416 modules FATAL: vmlinux is truncated. sechdrs[i].sh_offset=10354688 > sizeof(*hrd)=64 make[1]: *** [__modpost] Error 1 Teach modpost that NOBITS section may point beyond the end of the file and that .modinfo can't be NOBITS. Reported-by: Pawel Dziekonski Signed-off-by: Tejun Heo Signed-off-by: Ingo Molnar --- scripts/mod/modpost.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 88921611b22..7e62303133d 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -415,8 +415,9 @@ static int parse_elf(struct elf_info *info, const char *filename) const char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; const char *secname; + int nobits = sechdrs[i].sh_type == SHT_NOBITS; - if (sechdrs[i].sh_offset > info->size) { + if (!nobits && sechdrs[i].sh_offset > info->size) { fatal("%s is truncated. sechdrs[i].sh_offset=%lu > " "sizeof(*hrd)=%zu\n", filename, (unsigned long)sechdrs[i].sh_offset, @@ -425,6 +426,8 @@ static int parse_elf(struct elf_info *info, const char *filename) } secname = secstrings + sechdrs[i].sh_name; if (strcmp(secname, ".modinfo") == 0) { + if (nobits) + fatal("%s has NOBITS .modinfo\n", filename); info->modinfo = (void *)hdr + sechdrs[i].sh_offset; info->modinfo_len = sechdrs[i].sh_size; } else if (strcmp(secname, "__ksymtab") == 0) -- GitLab From 65a4e574d2382d83f71b30ea92f86d2e40a6ef8d Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 31 Jan 2009 03:36:17 +0100 Subject: [PATCH 1210/4982] smp, generic: introduce arch_disable_smp_support() instead of disable_ioapic_setup() Impact: cleanup disable_ioapic_setup() in init/main.c is ugly as the function is x86-specific. The #ifdef inline prototype there is ugly too. Replace it with a generic arch_disable_smp_support() function - which has a weak alias for non-x86 architectures and for non-ioapic x86 builds. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/io_apic.h | 9 --------- arch/x86/kernel/apic.c | 4 +--- arch/x86/kernel/io_apic.c | 11 ++++++++++- arch/x86/kernel/smpboot.c | 2 +- include/linux/smp.h | 6 ++++++ init/main.c | 12 ++++++------ 6 files changed, 24 insertions(+), 20 deletions(-) diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index 08ec793aa04..309d0e23193 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h @@ -143,15 +143,6 @@ extern int noioapicreroute; /* 1 if the timer IRQ uses the '8259A Virtual Wire' mode */ extern int timer_through_8259; -static inline void disable_ioapic_setup(void) -{ -#ifdef CONFIG_PCI - noioapicquirk = 1; - noioapicreroute = -1; -#endif - skip_ioapic_setup = 1; -} - /* * If we use the IO-APIC for IRQ routing, disable automatic * assignment of PCI IRQ's. diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 85d8b50d1af..a04a73a51d2 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -1138,9 +1138,7 @@ void __cpuinit setup_local_APIC(void) int i, j; if (disable_apic) { -#ifdef CONFIG_X86_IO_APIC - disable_ioapic_setup(); -#endif + arch_disable_smp_support(); return; } diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 57d60c741e3..84bccac4619 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -98,10 +98,19 @@ DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES); int skip_ioapic_setup; +void arch_disable_smp_support(void) +{ +#ifdef CONFIG_PCI + noioapicquirk = 1; + noioapicreroute = -1; +#endif + skip_ioapic_setup = 1; +} + static int __init parse_noapic(char *str) { /* disable IO-APIC */ - disable_ioapic_setup(); + arch_disable_smp_support(); return 0; } early_param("noapic", parse_noapic); diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index f40f86fec2f..96f7d304f5c 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1071,7 +1071,7 @@ static int __init smp_sanity_check(unsigned max_cpus) printk(KERN_ERR "... forcing use of dummy APIC emulation." "(tell your hw vendor)\n"); smpboot_clear_io_apic(); - disable_ioapic_setup(); + arch_disable_smp_support(); return -1; } diff --git a/include/linux/smp.h b/include/linux/smp.h index 715196b09d6..d41a3a865fe 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -66,6 +66,12 @@ extern int __cpu_up(unsigned int cpunum); */ extern void smp_cpus_done(unsigned int max_cpus); +/* + * Callback to arch code if there's nosmp or maxcpus=0 on the + * boot command line: + */ +extern void arch_disable_smp_support(void); + /* * Call a function on all other processors */ diff --git a/init/main.c b/init/main.c index bfe4fb0c984..6441083f827 100644 --- a/init/main.c +++ b/init/main.c @@ -136,14 +136,14 @@ unsigned int __initdata setup_max_cpus = NR_CPUS; * greater than 0, limits the maximum number of CPUs activated in * SMP mode to . */ -#ifndef CONFIG_X86_IO_APIC -static inline void disable_ioapic_setup(void) {}; -#endif + +void __weak arch_disable_smp_support(void) { } static int __init nosmp(char *str) { setup_max_cpus = 0; - disable_ioapic_setup(); + arch_disable_smp_support(); + return 0; } @@ -153,14 +153,14 @@ static int __init maxcpus(char *str) { get_option(&str, &setup_max_cpus); if (setup_max_cpus == 0) - disable_ioapic_setup(); + arch_disable_smp_support(); return 0; } early_param("maxcpus", maxcpus); #else -#define setup_max_cpus NR_CPUS +const unsigned int setup_max_cpus = NR_CPUS; #endif /* -- GitLab From fdbecd9fd14198853bec4cbae8bc7af93f2e3de3 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 31 Jan 2009 03:57:12 +0100 Subject: [PATCH 1211/4982] x86, apic: explain the purpose of max_physical_apicid Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index a04a73a51d2..5475e1c3180 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -50,13 +50,26 @@ #include unsigned int num_processors; + unsigned disabled_cpus __cpuinitdata; + /* Processor that is doing the boot up */ unsigned int boot_cpu_physical_apicid = -1U; -EXPORT_SYMBOL(boot_cpu_physical_apicid); + +/* + * The highest APIC ID seen during enumeration. + * + * This determines the messaging protocol we can use: if all APIC IDs + * are in the 0 ... 7 range, then we can use logical addressing which + * has some performance advantages (better broadcasting). + * + * If there's an APIC ID above 8, we use physical addressing. + */ unsigned int max_physical_apicid; -/* Bitmask of physically existing CPUs */ +/* + * Bitmask of physically existing CPUs: + */ physid_mask_t phys_cpu_present_map; /* -- GitLab From c5e954820335ef5aed1662b70aaf5deb9de16735 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 30 Jan 2009 17:29:27 -0800 Subject: [PATCH 1212/4982] x86: move default_ipi_xx back to ipi.c Impact: cleanup only leave _default_ipi_xx etc in .h Beyond the cleanup factor, this saves a bit of code size as well: text data bss dec hex filename 7281931 1630144 1463304 10375379 9e50d3 vmlinux.before 7281753 1630144 1463304 10375201 9e5021 vmlinux.after Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/include/asm/hw_irq.h | 6 -- arch/x86/include/asm/ipi.h | 127 ++++------------------------------ arch/x86/kernel/ipi.c | 108 +++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+), 120 deletions(-) diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index 3ef2bded97a..1a20e3d1200 100644 --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h @@ -71,12 +71,6 @@ extern void setup_ioapic_dest(void); extern void enable_IO_APIC(void); #endif -/* IPI functions */ -#ifdef CONFIG_X86_32 -extern void default_send_IPI_self(int vector); -#endif -extern void default_send_IPI(int dest, int vector); - /* Statistics */ extern atomic_t irq_err_count; extern atomic_t irq_mis_count; diff --git a/arch/x86/include/asm/ipi.h b/arch/x86/include/asm/ipi.h index aa79945445b..5f2efc5d992 100644 --- a/arch/x86/include/asm/ipi.h +++ b/arch/x86/include/asm/ipi.h @@ -119,112 +119,22 @@ static inline void native_apic_mem_write(APIC_ICR, cfg); } -static inline void -default_send_IPI_mask_sequence_phys(const struct cpumask *mask, int vector) -{ - unsigned long query_cpu; - unsigned long flags; - - /* - * Hack. The clustered APIC addressing mode doesn't allow us to send - * to an arbitrary mask, so I do a unicast to each CPU instead. - * - mbligh - */ - local_irq_save(flags); - for_each_cpu(query_cpu, mask) { - __default_send_IPI_dest_field(per_cpu(x86_cpu_to_apicid, - query_cpu), vector, APIC_DEST_PHYSICAL); - } - local_irq_restore(flags); -} - -static inline void -default_send_IPI_mask_allbutself_phys(const struct cpumask *mask, int vector) -{ - unsigned int this_cpu = smp_processor_id(); - unsigned int query_cpu; - unsigned long flags; - - /* See Hack comment above */ - - local_irq_save(flags); - for_each_cpu(query_cpu, mask) { - if (query_cpu == this_cpu) - continue; - __default_send_IPI_dest_field(per_cpu(x86_cpu_to_apicid, - query_cpu), vector, APIC_DEST_PHYSICAL); - } - local_irq_restore(flags); -} - +extern void default_send_IPI_mask_sequence_phys(const struct cpumask *mask, + int vector); +extern void default_send_IPI_mask_allbutself_phys(const struct cpumask *mask, + int vector); #include -static inline void -default_send_IPI_mask_sequence_logical(const struct cpumask *mask, int vector) -{ - unsigned long flags; - unsigned int query_cpu; - - /* - * Hack. The clustered APIC addressing mode doesn't allow us to send - * to an arbitrary mask, so I do a unicasts to each CPU instead. This - * should be modified to do 1 message per cluster ID - mbligh - */ - - local_irq_save(flags); - for_each_cpu(query_cpu, mask) - __default_send_IPI_dest_field( - apic->cpu_to_logical_apicid(query_cpu), vector, - apic->dest_logical); - local_irq_restore(flags); -} - -static inline void -default_send_IPI_mask_allbutself_logical(const struct cpumask *mask, int vector) -{ - unsigned long flags; - unsigned int query_cpu; - unsigned int this_cpu = smp_processor_id(); - - /* See Hack comment above */ - - local_irq_save(flags); - for_each_cpu(query_cpu, mask) { - if (query_cpu == this_cpu) - continue; - __default_send_IPI_dest_field( - apic->cpu_to_logical_apicid(query_cpu), vector, - apic->dest_logical); - } - local_irq_restore(flags); -} +extern void default_send_IPI_mask_sequence_logical(const struct cpumask *mask, + int vector); +extern void default_send_IPI_mask_allbutself_logical(const struct cpumask *mask, + int vector); /* Avoid include hell */ #define NMI_VECTOR 0x02 extern int no_broadcast; -#ifndef CONFIG_X86_64 -/* - * This is only used on smaller machines. - */ -static inline void default_send_IPI_mask_bitmask_logical(const struct cpumask *cpumask, int vector) -{ - unsigned long mask = cpumask_bits(cpumask)[0]; - unsigned long flags; - - local_irq_save(flags); - WARN_ON(mask & ~cpumask_bits(cpu_online_mask)[0]); - __default_send_IPI_dest_field(mask, vector, apic->dest_logical); - local_irq_restore(flags); -} - -static inline void default_send_IPI_mask_logical(const struct cpumask *mask, int vector) -{ - default_send_IPI_mask_bitmask_logical(mask, vector); -} -#endif - static inline void __default_local_send_IPI_allbutself(int vector) { if (no_broadcast || vector == NMI_VECTOR) @@ -242,22 +152,11 @@ static inline void __default_local_send_IPI_all(int vector) } #ifdef CONFIG_X86_32 -static inline void default_send_IPI_allbutself(int vector) -{ - /* - * if there are no other CPUs in the system then we get an APIC send - * error if we try to broadcast, thus avoid sending IPIs in this case. - */ - if (!(num_online_cpus() > 1)) - return; - - __default_local_send_IPI_allbutself(vector); -} - -static inline void default_send_IPI_all(int vector) -{ - __default_local_send_IPI_all(vector); -} +extern void default_send_IPI_mask_logical(const struct cpumask *mask, + int vector); +extern void default_send_IPI_allbutself(int vector); +extern void default_send_IPI_all(int vector); +extern void default_send_IPI_self(int vector); #endif #endif diff --git a/arch/x86/kernel/ipi.c b/arch/x86/kernel/ipi.c index 339f4f3feee..dbf5445727a 100644 --- a/arch/x86/kernel/ipi.c +++ b/arch/x86/kernel/ipi.c @@ -19,8 +19,116 @@ #include #include +void default_send_IPI_mask_sequence_phys(const struct cpumask *mask, int vector) +{ + unsigned long query_cpu; + unsigned long flags; + + /* + * Hack. The clustered APIC addressing mode doesn't allow us to send + * to an arbitrary mask, so I do a unicast to each CPU instead. + * - mbligh + */ + local_irq_save(flags); + for_each_cpu(query_cpu, mask) { + __default_send_IPI_dest_field(per_cpu(x86_cpu_to_apicid, + query_cpu), vector, APIC_DEST_PHYSICAL); + } + local_irq_restore(flags); +} + +void default_send_IPI_mask_allbutself_phys(const struct cpumask *mask, + int vector) +{ + unsigned int this_cpu = smp_processor_id(); + unsigned int query_cpu; + unsigned long flags; + + /* See Hack comment above */ + + local_irq_save(flags); + for_each_cpu(query_cpu, mask) { + if (query_cpu == this_cpu) + continue; + __default_send_IPI_dest_field(per_cpu(x86_cpu_to_apicid, + query_cpu), vector, APIC_DEST_PHYSICAL); + } + local_irq_restore(flags); +} + +void default_send_IPI_mask_sequence_logical(const struct cpumask *mask, + int vector) +{ + unsigned long flags; + unsigned int query_cpu; + + /* + * Hack. The clustered APIC addressing mode doesn't allow us to send + * to an arbitrary mask, so I do a unicasts to each CPU instead. This + * should be modified to do 1 message per cluster ID - mbligh + */ + + local_irq_save(flags); + for_each_cpu(query_cpu, mask) + __default_send_IPI_dest_field( + apic->cpu_to_logical_apicid(query_cpu), vector, + apic->dest_logical); + local_irq_restore(flags); +} + +void default_send_IPI_mask_allbutself_logical(const struct cpumask *mask, + int vector) +{ + unsigned long flags; + unsigned int query_cpu; + unsigned int this_cpu = smp_processor_id(); + + /* See Hack comment above */ + + local_irq_save(flags); + for_each_cpu(query_cpu, mask) { + if (query_cpu == this_cpu) + continue; + __default_send_IPI_dest_field( + apic->cpu_to_logical_apicid(query_cpu), vector, + apic->dest_logical); + } + local_irq_restore(flags); +} + #ifdef CONFIG_X86_32 +/* + * This is only used on smaller machines. + */ +void default_send_IPI_mask_logical(const struct cpumask *cpumask, int vector) +{ + unsigned long mask = cpumask_bits(cpumask)[0]; + unsigned long flags; + + local_irq_save(flags); + WARN_ON(mask & ~cpumask_bits(cpu_online_mask)[0]); + __default_send_IPI_dest_field(mask, vector, apic->dest_logical); + local_irq_restore(flags); +} + +void default_send_IPI_allbutself(int vector) +{ + /* + * if there are no other CPUs in the system then we get an APIC send + * error if we try to broadcast, thus avoid sending IPIs in this case. + */ + if (!(num_online_cpus() > 1)) + return; + + __default_local_send_IPI_allbutself(vector); +} + +void default_send_IPI_all(int vector) +{ + __default_local_send_IPI_all(vector); +} + void default_send_IPI_self(int vector) { __default_send_IPI_shortcut(APIC_DEST_SELF, vector, apic->dest_logical); -- GitLab From a146649bc19d5eba4f5bfac6720c5f252d517a71 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 31 Jan 2009 14:09:06 +0100 Subject: [PATCH 1213/4982] smp, generic: introduce arch_disable_smp_support(), build fix This function should be provided on UP too. Signed-off-by: Ingo Molnar --- include/linux/smp.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/linux/smp.h b/include/linux/smp.h index d41a3a865fe..bbacb7baa44 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -66,12 +66,6 @@ extern int __cpu_up(unsigned int cpunum); */ extern void smp_cpus_done(unsigned int max_cpus); -/* - * Callback to arch code if there's nosmp or maxcpus=0 on the - * boot command line: - */ -extern void arch_disable_smp_support(void); - /* * Call a function on all other processors */ @@ -182,6 +176,12 @@ static inline void init_call_single_data(void) #define put_cpu() preempt_enable() #define put_cpu_no_resched() preempt_enable_no_resched() +/* + * Callback to arch code if there's nosmp or maxcpus=0 on the + * boot command line: + */ +extern void arch_disable_smp_support(void); + void smp_setup_processor_id(void); #endif /* __LINUX_SMP_H */ -- GitLab From 4f179d121885142fb907b64956228b369d495958 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 1 Feb 2009 11:25:57 +0100 Subject: [PATCH 1214/4982] x86, numaq: cleanups Also move xquad_portio over to where it's allocated. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/numaq.h | 2 ++ arch/x86/kernel/numaq_32.c | 33 ++++++++++++++++++--------------- arch/x86/pci/numaq_32.c | 4 ---- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/arch/x86/include/asm/numaq.h b/arch/x86/include/asm/numaq.h index 1e8bd30b4c1..9f0a5f5d29e 100644 --- a/arch/x86/include/asm/numaq.h +++ b/arch/x86/include/asm/numaq.h @@ -31,6 +31,8 @@ extern int found_numaq; extern int get_memcfg_numaq(void); +extern void *xquad_portio; + /* * SYS_CFG_DATA_PRIV_ADDR, struct eachquadmem, and struct sys_cfg_data are the */ diff --git a/arch/x86/kernel/numaq_32.c b/arch/x86/kernel/numaq_32.c index 947748e1721..0cc41a1d255 100644 --- a/arch/x86/kernel/numaq_32.c +++ b/arch/x86/kernel/numaq_32.c @@ -3,7 +3,7 @@ * * Copyright (C) 2002, IBM Corp. * - * All rights reserved. + * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,17 +23,18 @@ * Send feedback to */ -#include +#include #include #include #include -#include -#include -#include +#include + #include +#include #include -#include +#include #include +#include #define MB_TO_PAGES(addr) ((addr) << (20 - PAGE_SHIFT)) @@ -91,19 +92,20 @@ static int __init numaq_pre_time_init(void) } int found_numaq; + /* * Have to match translation table entries to main table entries by counter * hence the mpc_record variable .... can't see a less disgusting way of * doing this .... */ struct mpc_config_translation { - unsigned char mpc_type; - unsigned char trans_len; - unsigned char trans_type; - unsigned char trans_quad; - unsigned char trans_global; - unsigned char trans_local; - unsigned short trans_reserved; + unsigned char mpc_type; + unsigned char trans_len; + unsigned char trans_type; + unsigned char trans_quad; + unsigned char trans_global; + unsigned char trans_local; + unsigned short trans_reserved; }; /* x86_quirks member */ @@ -444,7 +446,8 @@ static inline physid_mask_t numaq_apicid_to_cpu_present(int logical_apicid) return physid_mask_of_physid(cpu + 4*node); } -extern void *xquad_portio; +/* Where the IO area was mapped on multiquad, always 0 otherwise */ +void *xquad_portio; static inline int numaq_check_phys_apicid_present(int boot_cpu_physical_apicid) { @@ -502,7 +505,7 @@ static void numaq_setup_portio_remap(void) int num_quads = num_online_nodes(); if (num_quads <= 1) - return; + return; printk("Remapping cross-quad port I/O for %d quads\n", num_quads); xquad_portio = ioremap(XQUAD_PORTIO_BASE, num_quads*XQUAD_PORTIO_QUAD); diff --git a/arch/x86/pci/numaq_32.c b/arch/x86/pci/numaq_32.c index 1b2d773612e..5601e829c38 100644 --- a/arch/x86/pci/numaq_32.c +++ b/arch/x86/pci/numaq_32.c @@ -18,10 +18,6 @@ #define QUADLOCAL2BUS(quad,local) (quad_local_to_mp_bus_id[quad][local]) -/* Where the IO area was mapped on multiquad, always 0 otherwise */ -void *xquad_portio; -EXPORT_SYMBOL(xquad_portio); - #define XQUAD_PORT_ADDR(port, quad) (xquad_portio + (XQUAD_PORTIO_QUAD*quad) + port) #define PCI_CONF1_MQ_ADDRESS(bus, devfn, reg) \ -- GitLab From 8f9ca475c994e4d32f405183d07e8c7eedbdbdb4 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 5 Feb 2009 16:21:53 +0100 Subject: [PATCH 1215/4982] x86: clean up arch/x86/Kconfig* - Consistent alignment of help text - Use the ---help--- keyword everywhere consistently as a visual separator - fix whitespace mismatches Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 404 ++++++++++++++++++++--------------------- arch/x86/Kconfig.cpu | 70 +++---- arch/x86/Kconfig.debug | 47 +++-- 3 files changed, 260 insertions(+), 261 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 80291f749b6..270ecf90bdb 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -5,7 +5,7 @@ mainmenu "Linux Kernel Configuration for x86" config 64BIT bool "64-bit kernel" if ARCH = "x86" default ARCH = "x86_64" - help + ---help--- Say yes to build a 64-bit kernel - formerly known as x86_64 Say no to build a 32-bit kernel - formerly known as i386 @@ -235,7 +235,7 @@ config SMP config SPARSE_IRQ bool "Support sparse irq numbering" depends on PCI_MSI || HT_IRQ - help + ---help--- This enables support for sparse irqs. This is useful for distro kernels that want to define a high CONFIG_NR_CPUS value but still want to have low kernel memory footprint on smaller machines. @@ -249,7 +249,7 @@ config NUMA_MIGRATE_IRQ_DESC bool "Move irq desc when changing irq smp_affinity" depends on SPARSE_IRQ && NUMA default n - help + ---help--- This enables moving irq_desc to cpu/node that irq will use handled. If you don't know what to do here, say N. @@ -258,19 +258,19 @@ config X86_MPPARSE bool "Enable MPS table" if ACPI default y depends on X86_LOCAL_APIC - help + ---help--- For old smp systems that do not have proper acpi support. Newer systems (esp with 64bit cpus) with acpi support, MADT and DSDT will override it config X86_BIGSMP bool "Support for big SMP systems with more than 8 CPUs" depends on X86_32 && SMP - help + ---help--- This option is needed for the systems that have more than 8 CPUs config X86_NON_STANDARD bool "Support for non-standard x86 platforms" - help + ---help--- If you disable this option then the kernel will only support standard PC platforms. (which covers the vast majority of systems out there.) @@ -285,7 +285,7 @@ config X86_VISWS bool "SGI 320/540 (Visual Workstation)" depends on X86_32 && PCI && X86_MPPARSE && PCI_GODIRECT depends on X86_NON_STANDARD - help + ---help--- The SGI Visual Workstation series is an IA32-based workstation based on SGI systems chips with some legacy PC hardware attached. @@ -300,7 +300,7 @@ config X86_RDC321X depends on X86_NON_STANDARD select M486 select X86_REBOOTFIXUPS - help + ---help--- This option is needed for RDC R-321x system-on-chip, also known as R-8610-(G). If you don't have one of these chips, you should say N here. @@ -309,7 +309,7 @@ config X86_UV bool "SGI Ultraviolet" depends on X86_64 depends on X86_NON_STANDARD - help + ---help--- This option is needed in order to support SGI Ultraviolet systems. If you don't have one of these, you should say N here. @@ -318,7 +318,7 @@ config X86_VSMP select PARAVIRT depends on X86_64 && PCI depends on X86_NON_STANDARD - help + ---help--- Support for ScaleMP vSMP systems. Say 'Y' here if this kernel is supposed to run on these EM64T-based machines. Only choose this option if you have one of these machines. @@ -327,7 +327,7 @@ config X86_ELAN bool "AMD Elan" depends on X86_32 depends on X86_NON_STANDARD - help + ---help--- Select this for an AMD Elan processor. Do not use this option for K6/Athlon/Opteron processors! @@ -338,8 +338,8 @@ config X86_32_NON_STANDARD bool "Support non-standard 32-bit SMP architectures" depends on X86_32 && SMP depends on X86_NON_STANDARD - help - This option compiles in the NUMAQ, Summit, bigsmp, ES7000, default + ---help--- + This option compiles in the NUMAQ, Summit, bigsmp, ES7000, default subarchitectures. It is intended for a generic binary kernel. if you select them all, kernel will probe it one by one. and will fallback to default. @@ -349,7 +349,7 @@ config X86_NUMAQ depends on X86_32_NON_STANDARD select NUMA select X86_MPPARSE - help + ---help--- This option is used for getting Linux to run on a NUMAQ (IBM/Sequent) NUMA multiquad box. This changes the way that processors are bootstrapped, and uses Clustered Logical APIC addressing mode instead @@ -359,14 +359,14 @@ config X86_NUMAQ config X86_SUMMIT bool "Summit/EXA (IBM x440)" depends on X86_32_NON_STANDARD - help + ---help--- This option is needed for IBM systems that use the Summit/EXA chipset. In particular, it is needed for the x440. config X86_ES7000 bool "Support for Unisys ES7000 IA32 series" depends on X86_32_NON_STANDARD && X86_BIGSMP - help + ---help--- Support for Unisys ES7000 systems. Say 'Y' here if this kernel is supposed to run on an IA32-based Unisys ES7000 system. @@ -374,7 +374,7 @@ config X86_VOYAGER bool "Voyager (NCR)" depends on SMP && !PCI && BROKEN depends on X86_32_NON_STANDARD - help + ---help--- Voyager is an MCA-based 32-way capable SMP architecture proprietary to NCR Corp. Machine classes 345x/35xx/4100/51xx are Voyager-based. @@ -387,7 +387,7 @@ config SCHED_OMIT_FRAME_POINTER def_bool y prompt "Single-depth WCHAN output" depends on X86 - help + ---help--- Calculate simpler /proc//wchan values. If this option is disabled then wchan values will recurse back to the caller function. This provides more accurate wchan values, @@ -397,7 +397,7 @@ config SCHED_OMIT_FRAME_POINTER menuconfig PARAVIRT_GUEST bool "Paravirtualized guest support" - help + ---help--- Say Y here to get to see options related to running Linux under various hypervisors. This option alone does not add any kernel code. @@ -411,7 +411,7 @@ config VMI bool "VMI Guest support" select PARAVIRT depends on X86_32 - help + ---help--- VMI provides a paravirtualized interface to the VMware ESX server (it could be used by other hypervisors in theory too, but is not at the moment), by linking the kernel to a GPL-ed ROM module @@ -421,7 +421,7 @@ config KVM_CLOCK bool "KVM paravirtualized clock" select PARAVIRT select PARAVIRT_CLOCK - help + ---help--- Turning on this option will allow you to run a paravirtualized clock when running over the KVM hypervisor. Instead of relying on a PIT (or probably other) emulation by the underlying device model, the host @@ -431,15 +431,15 @@ config KVM_CLOCK config KVM_GUEST bool "KVM Guest support" select PARAVIRT - help - This option enables various optimizations for running under the KVM - hypervisor. + ---help--- + This option enables various optimizations for running under the KVM + hypervisor. source "arch/x86/lguest/Kconfig" config PARAVIRT bool "Enable paravirtualization code" - help + ---help--- This changes the kernel so it can modify itself when it is run under a hypervisor, potentially improving performance significantly over full virtualization. However, when run without a hypervisor @@ -452,21 +452,21 @@ config PARAVIRT_CLOCK endif config PARAVIRT_DEBUG - bool "paravirt-ops debugging" - depends on PARAVIRT && DEBUG_KERNEL - help - Enable to debug paravirt_ops internals. Specifically, BUG if - a paravirt_op is missing when it is called. + bool "paravirt-ops debugging" + depends on PARAVIRT && DEBUG_KERNEL + ---help--- + Enable to debug paravirt_ops internals. Specifically, BUG if + a paravirt_op is missing when it is called. config MEMTEST bool "Memtest" - help + ---help--- This option adds a kernel parameter 'memtest', which allows memtest to be set. - memtest=0, mean disabled; -- default - memtest=1, mean do 1 test pattern; - ... - memtest=4, mean do 4 test patterns. + memtest=0, mean disabled; -- default + memtest=1, mean do 1 test pattern; + ... + memtest=4, mean do 4 test patterns. If you are unsure how to answer this question, answer N. config X86_SUMMIT_NUMA @@ -482,21 +482,21 @@ source "arch/x86/Kconfig.cpu" config HPET_TIMER def_bool X86_64 prompt "HPET Timer Support" if X86_32 - help - Use the IA-PC HPET (High Precision Event Timer) to manage - time in preference to the PIT and RTC, if a HPET is - present. - HPET is the next generation timer replacing legacy 8254s. - The HPET provides a stable time base on SMP - systems, unlike the TSC, but it is more expensive to access, - as it is off-chip. You can find the HPET spec at - . + ---help--- + Use the IA-PC HPET (High Precision Event Timer) to manage + time in preference to the PIT and RTC, if a HPET is + present. + HPET is the next generation timer replacing legacy 8254s. + The HPET provides a stable time base on SMP + systems, unlike the TSC, but it is more expensive to access, + as it is off-chip. You can find the HPET spec at + . - You can safely choose Y here. However, HPET will only be - activated if the platform and the BIOS support this feature. - Otherwise the 8254 will be used for timing services. + You can safely choose Y here. However, HPET will only be + activated if the platform and the BIOS support this feature. + Otherwise the 8254 will be used for timing services. - Choose N to continue using the legacy 8254 timer. + Choose N to continue using the legacy 8254 timer. config HPET_EMULATE_RTC def_bool y @@ -507,7 +507,7 @@ config HPET_EMULATE_RTC config DMI default y bool "Enable DMI scanning" if EMBEDDED - help + ---help--- Enabled scanning of DMI to identify machine quirks. Say Y here unless you have verified that your setup is not affected by entries in the DMI blacklist. Required by PNP @@ -519,7 +519,7 @@ config GART_IOMMU select SWIOTLB select AGP depends on X86_64 && PCI - help + ---help--- Support for full DMA access of devices with 32bit memory access only on systems with more than 3GB. This is usually needed for USB, sound, many IDE/SATA chipsets and some other devices. @@ -534,7 +534,7 @@ config CALGARY_IOMMU bool "IBM Calgary IOMMU support" select SWIOTLB depends on X86_64 && PCI && EXPERIMENTAL - help + ---help--- Support for hardware IOMMUs in IBM's xSeries x366 and x460 systems. Needed to run systems with more than 3GB of memory properly with 32-bit PCI devices that do not support DAC @@ -552,7 +552,7 @@ config CALGARY_IOMMU_ENABLED_BY_DEFAULT def_bool y prompt "Should Calgary be enabled by default?" depends on CALGARY_IOMMU - help + ---help--- Should Calgary be enabled by default? if you choose 'y', Calgary will be used (if it exists). If you choose 'n', Calgary will not be used even if it exists. If you choose 'n' and would like to use @@ -564,7 +564,7 @@ config AMD_IOMMU select SWIOTLB select PCI_MSI depends on X86_64 && PCI && ACPI - help + ---help--- With this option you can enable support for AMD IOMMU hardware in your system. An IOMMU is a hardware component which provides remapping of DMA memory accesses from devices. With an AMD IOMMU you @@ -579,7 +579,7 @@ config AMD_IOMMU_STATS bool "Export AMD IOMMU statistics to debugfs" depends on AMD_IOMMU select DEBUG_FS - help + ---help--- This option enables code in the AMD IOMMU driver to collect various statistics about whats happening in the driver and exports that information to userspace via debugfs. @@ -588,7 +588,7 @@ config AMD_IOMMU_STATS # need this always selected by IOMMU for the VIA workaround config SWIOTLB def_bool y if X86_64 - help + ---help--- Support for software bounce buffers used on x86-64 systems which don't have a hardware IOMMU (e.g. the current generation of Intel's x86-64 CPUs). Using this PCI devices which can only @@ -606,7 +606,7 @@ config MAXSMP depends on X86_64 && SMP && DEBUG_KERNEL && EXPERIMENTAL select CPUMASK_OFFSTACK default n - help + ---help--- Configure maximum number of CPUS and NUMA Nodes for this architecture. If unsure, say N. @@ -617,7 +617,7 @@ config NR_CPUS default "4096" if MAXSMP default "32" if SMP && (X86_NUMAQ || X86_SUMMIT || X86_BIGSMP || X86_ES7000) default "8" if SMP - help + ---help--- This allows you to specify the maximum number of CPUs which this kernel will support. The maximum supported value is 512 and the minimum value which makes sense is 2. @@ -628,7 +628,7 @@ config NR_CPUS config SCHED_SMT bool "SMT (Hyperthreading) scheduler support" depends on X86_HT - help + ---help--- SMT scheduler support improves the CPU scheduler's decision making when dealing with Intel Pentium 4 chips with HyperThreading at a cost of slightly increased overhead in some places. If unsure say @@ -638,7 +638,7 @@ config SCHED_MC def_bool y prompt "Multi-core scheduler support" depends on X86_HT - help + ---help--- Multi-core scheduler support improves the CPU scheduler's decision making when dealing with multi-core CPU chips at a cost of slightly increased overhead in some places. If unsure say N here. @@ -648,7 +648,7 @@ source "kernel/Kconfig.preempt" config X86_UP_APIC bool "Local APIC support on uniprocessors" depends on X86_32 && !SMP && !X86_32_NON_STANDARD - help + ---help--- A local APIC (Advanced Programmable Interrupt Controller) is an integrated interrupt controller in the CPU. If you have a single-CPU system which has a processor with a local APIC, you can say Y here to @@ -661,7 +661,7 @@ config X86_UP_APIC config X86_UP_IOAPIC bool "IO-APIC support on uniprocessors" depends on X86_UP_APIC - help + ---help--- An IO-APIC (I/O Advanced Programmable Interrupt Controller) is an SMP-capable replacement for PC-style interrupt controllers. Most SMP systems and many recent uniprocessor systems have one. @@ -686,7 +686,7 @@ config X86_REROUTE_FOR_BROKEN_BOOT_IRQS bool "Reroute for broken boot IRQs" default n depends on X86_IO_APIC - help + ---help--- This option enables a workaround that fixes a source of spurious interrupts. This is recommended when threaded interrupt handling is used on systems where the generation of @@ -726,7 +726,7 @@ config X86_MCE_INTEL def_bool y prompt "Intel MCE features" depends on X86_64 && X86_MCE && X86_LOCAL_APIC - help + ---help--- Additional support for intel specific MCE features such as the thermal monitor. @@ -734,14 +734,14 @@ config X86_MCE_AMD def_bool y prompt "AMD MCE features" depends on X86_64 && X86_MCE && X86_LOCAL_APIC - help + ---help--- Additional support for AMD specific MCE features such as the DRAM Error Threshold. config X86_MCE_NONFATAL tristate "Check for non-fatal errors on AMD Athlon/Duron / Intel Pentium 4" depends on X86_32 && X86_MCE - help + ---help--- Enabling this feature starts a timer that triggers every 5 seconds which will look at the machine check registers to see if anything happened. Non-fatal problems automatically get corrected (but still logged). @@ -754,7 +754,7 @@ config X86_MCE_NONFATAL config X86_MCE_P4THERMAL bool "check for P4 thermal throttling interrupt." depends on X86_32 && X86_MCE && (X86_UP_APIC || SMP) - help + ---help--- Enabling this feature will cause a message to be printed when the P4 enters thermal throttling. @@ -762,11 +762,11 @@ config VM86 bool "Enable VM86 support" if EMBEDDED default y depends on X86_32 - help - This option is required by programs like DOSEMU to run 16-bit legacy + ---help--- + This option is required by programs like DOSEMU to run 16-bit legacy code on X86 processors. It also may be needed by software like - XFree86 to initialize some video cards via BIOS. Disabling this - option saves about 6k. + XFree86 to initialize some video cards via BIOS. Disabling this + option saves about 6k. config TOSHIBA tristate "Toshiba Laptop support" @@ -840,33 +840,33 @@ config MICROCODE module will be called microcode. config MICROCODE_INTEL - bool "Intel microcode patch loading support" - depends on MICROCODE - default MICROCODE - select FW_LOADER - --help--- - This options enables microcode patch loading support for Intel - processors. - - For latest news and information on obtaining all the required - Intel ingredients for this driver, check: - . + bool "Intel microcode patch loading support" + depends on MICROCODE + default MICROCODE + select FW_LOADER + ---help--- + This options enables microcode patch loading support for Intel + processors. + + For latest news and information on obtaining all the required + Intel ingredients for this driver, check: + . config MICROCODE_AMD - bool "AMD microcode patch loading support" - depends on MICROCODE - select FW_LOADER - --help--- - If you select this option, microcode patch loading support for AMD - processors will be enabled. + bool "AMD microcode patch loading support" + depends on MICROCODE + select FW_LOADER + ---help--- + If you select this option, microcode patch loading support for AMD + processors will be enabled. - config MICROCODE_OLD_INTERFACE +config MICROCODE_OLD_INTERFACE def_bool y depends on MICROCODE config X86_MSR tristate "/dev/cpu/*/msr - Model-specific register support" - help + ---help--- This device gives privileged processes access to the x86 Model-Specific Registers (MSRs). It is a character device with major 202 and minors 0 to 31 for /dev/cpu/0/msr to /dev/cpu/31/msr. @@ -875,7 +875,7 @@ config X86_MSR config X86_CPUID tristate "/dev/cpu/*/cpuid - CPU information support" - help + ---help--- This device gives processes access to the x86 CPUID instruction to be executed on a specific processor. It is a character device with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to @@ -927,7 +927,7 @@ config NOHIGHMEM config HIGHMEM4G bool "4GB" depends on !X86_NUMAQ - help + ---help--- Select this if you have a 32-bit processor and between 1 and 4 gigabytes of physical RAM. @@ -935,7 +935,7 @@ config HIGHMEM64G bool "64GB" depends on !M386 && !M486 select X86_PAE - help + ---help--- Select this if you have a 32-bit processor and more than 4 gigabytes of physical RAM. @@ -946,7 +946,7 @@ choice prompt "Memory split" if EMBEDDED default VMSPLIT_3G depends on X86_32 - help + ---help--- Select the desired split between kernel and user memory. If the address range available to the kernel is less than the @@ -992,20 +992,20 @@ config HIGHMEM config X86_PAE bool "PAE (Physical Address Extension) Support" depends on X86_32 && !HIGHMEM4G - help + ---help--- PAE is required for NX support, and furthermore enables larger swapspace support for non-overcommit purposes. It has the cost of more pagetable lookup overhead, and also consumes more pagetable space per process. config ARCH_PHYS_ADDR_T_64BIT - def_bool X86_64 || X86_PAE + def_bool X86_64 || X86_PAE config DIRECT_GBPAGES bool "Enable 1GB pages for kernel pagetables" if EMBEDDED default y depends on X86_64 - help + ---help--- Allow the kernel linear mapping to use 1GB pages on CPUs that support it. This can improve the kernel's performance a tiny bit by reducing TLB pressure. If in doubt, say "Y". @@ -1016,7 +1016,7 @@ config NUMA depends on SMP depends on X86_64 || (X86_32 && HIGHMEM64G && (X86_NUMAQ || X86_BIGSMP || X86_SUMMIT && ACPI) && EXPERIMENTAL) default y if (X86_NUMAQ || X86_SUMMIT || X86_BIGSMP) - help + ---help--- Enable NUMA (Non Uniform Memory Access) support. The kernel will try to allocate memory used by a CPU on the @@ -1039,19 +1039,19 @@ config K8_NUMA def_bool y prompt "Old style AMD Opteron NUMA detection" depends on X86_64 && NUMA && PCI - help - Enable K8 NUMA node topology detection. You should say Y here if - you have a multi processor AMD K8 system. This uses an old - method to read the NUMA configuration directly from the builtin - Northbridge of Opteron. It is recommended to use X86_64_ACPI_NUMA - instead, which also takes priority if both are compiled in. + ---help--- + Enable K8 NUMA node topology detection. You should say Y here if + you have a multi processor AMD K8 system. This uses an old + method to read the NUMA configuration directly from the builtin + Northbridge of Opteron. It is recommended to use X86_64_ACPI_NUMA + instead, which also takes priority if both are compiled in. config X86_64_ACPI_NUMA def_bool y prompt "ACPI NUMA detection" depends on X86_64 && NUMA && ACPI && PCI select ACPI_NUMA - help + ---help--- Enable ACPI SRAT based node topology detection. # Some NUMA nodes have memory ranges that span @@ -1066,7 +1066,7 @@ config NODES_SPAN_OTHER_NODES config NUMA_EMU bool "NUMA emulation" depends on X86_64 && NUMA - help + ---help--- Enable NUMA emulation. A flat machine will be split into virtual nodes when booted with "numa=fake=N", where N is the number of nodes. This is only useful for debugging. @@ -1079,7 +1079,7 @@ config NODES_SHIFT default "4" if X86_NUMAQ default "3" depends on NEED_MULTIPLE_NODES - help + ---help--- Specify the maximum number of NUMA Nodes available on the target system. Increases memory reserved to accomodate various tables. @@ -1134,61 +1134,61 @@ source "mm/Kconfig" config HIGHPTE bool "Allocate 3rd-level pagetables from highmem" depends on X86_32 && (HIGHMEM4G || HIGHMEM64G) - help + ---help--- The VM uses one page table entry for each page of physical memory. For systems with a lot of RAM, this can be wasteful of precious low memory. Setting this option will put user-space page table entries in high memory. config X86_CHECK_BIOS_CORRUPTION - bool "Check for low memory corruption" - help - Periodically check for memory corruption in low memory, which - is suspected to be caused by BIOS. Even when enabled in the - configuration, it is disabled at runtime. Enable it by - setting "memory_corruption_check=1" on the kernel command - line. By default it scans the low 64k of memory every 60 - seconds; see the memory_corruption_check_size and - memory_corruption_check_period parameters in - Documentation/kernel-parameters.txt to adjust this. - - When enabled with the default parameters, this option has - almost no overhead, as it reserves a relatively small amount - of memory and scans it infrequently. It both detects corruption - and prevents it from affecting the running system. - - It is, however, intended as a diagnostic tool; if repeatable - BIOS-originated corruption always affects the same memory, - you can use memmap= to prevent the kernel from using that - memory. + bool "Check for low memory corruption" + ---help--- + Periodically check for memory corruption in low memory, which + is suspected to be caused by BIOS. Even when enabled in the + configuration, it is disabled at runtime. Enable it by + setting "memory_corruption_check=1" on the kernel command + line. By default it scans the low 64k of memory every 60 + seconds; see the memory_corruption_check_size and + memory_corruption_check_period parameters in + Documentation/kernel-parameters.txt to adjust this. + + When enabled with the default parameters, this option has + almost no overhead, as it reserves a relatively small amount + of memory and scans it infrequently. It both detects corruption + and prevents it from affecting the running system. + + It is, however, intended as a diagnostic tool; if repeatable + BIOS-originated corruption always affects the same memory, + you can use memmap= to prevent the kernel from using that + memory. config X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK - bool "Set the default setting of memory_corruption_check" + bool "Set the default setting of memory_corruption_check" depends on X86_CHECK_BIOS_CORRUPTION default y - help - Set whether the default state of memory_corruption_check is - on or off. + ---help--- + Set whether the default state of memory_corruption_check is + on or off. config X86_RESERVE_LOW_64K - bool "Reserve low 64K of RAM on AMI/Phoenix BIOSen" + bool "Reserve low 64K of RAM on AMI/Phoenix BIOSen" default y - help - Reserve the first 64K of physical RAM on BIOSes that are known - to potentially corrupt that memory range. A numbers of BIOSes are - known to utilize this area during suspend/resume, so it must not - be used by the kernel. + ---help--- + Reserve the first 64K of physical RAM on BIOSes that are known + to potentially corrupt that memory range. A numbers of BIOSes are + known to utilize this area during suspend/resume, so it must not + be used by the kernel. - Set this to N if you are absolutely sure that you trust the BIOS - to get all its memory reservations and usages right. + Set this to N if you are absolutely sure that you trust the BIOS + to get all its memory reservations and usages right. - If you have doubts about the BIOS (e.g. suspend/resume does not - work or there's kernel crashes after certain hardware hotplug - events) and it's not AMI or Phoenix, then you might want to enable - X86_CHECK_BIOS_CORRUPTION=y to allow the kernel to check typical - corruption patterns. + If you have doubts about the BIOS (e.g. suspend/resume does not + work or there's kernel crashes after certain hardware hotplug + events) and it's not AMI or Phoenix, then you might want to enable + X86_CHECK_BIOS_CORRUPTION=y to allow the kernel to check typical + corruption patterns. - Say Y if unsure. + Say Y if unsure. config MATH_EMULATION bool @@ -1254,7 +1254,7 @@ config MTRR_SANITIZER def_bool y prompt "MTRR cleanup support" depends on MTRR - help + ---help--- Convert MTRR layout from continuous to discrete, so X drivers can add writeback entries. @@ -1269,7 +1269,7 @@ config MTRR_SANITIZER_ENABLE_DEFAULT range 0 1 default "0" depends on MTRR_SANITIZER - help + ---help--- Enable mtrr cleanup default value config MTRR_SANITIZER_SPARE_REG_NR_DEFAULT @@ -1277,7 +1277,7 @@ config MTRR_SANITIZER_SPARE_REG_NR_DEFAULT range 0 7 default "1" depends on MTRR_SANITIZER - help + ---help--- mtrr cleanup spare entries default, it can be changed via mtrr_spare_reg_nr=N on the kernel command line. @@ -1285,7 +1285,7 @@ config X86_PAT bool prompt "x86 PAT support" depends on MTRR - help + ---help--- Use PAT attributes to setup page level cache control. PATs are the modern equivalents of MTRRs and are much more @@ -1300,20 +1300,20 @@ config EFI bool "EFI runtime service support" depends on ACPI ---help--- - This enables the kernel to use EFI runtime services that are - available (such as the EFI variable services). + This enables the kernel to use EFI runtime services that are + available (such as the EFI variable services). - This option is only useful on systems that have EFI firmware. - In addition, you should use the latest ELILO loader available - at in order to take advantage - of EFI runtime services. However, even with this option, the - resultant kernel should continue to boot on existing non-EFI - platforms. + This option is only useful on systems that have EFI firmware. + In addition, you should use the latest ELILO loader available + at in order to take advantage + of EFI runtime services. However, even with this option, the + resultant kernel should continue to boot on existing non-EFI + platforms. config SECCOMP def_bool y prompt "Enable seccomp to safely compute untrusted bytecode" - help + ---help--- This kernel feature is useful for number crunching applications that may need to compute untrusted bytecode during their execution. By using pipes or other transports made available to @@ -1333,8 +1333,8 @@ config CC_STACKPROTECTOR bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" depends on X86_64 select CC_STACKPROTECTOR_ALL - help - This option turns on the -fstack-protector GCC feature. This + ---help--- + This option turns on the -fstack-protector GCC feature. This feature puts, at the beginning of functions, a canary value on the stack just before the return address, and validates the value just before actually returning. Stack based buffer @@ -1351,7 +1351,7 @@ source kernel/Kconfig.hz config KEXEC bool "kexec system call" - help + ---help--- kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot but it is independent of the system firmware. And like a reboot @@ -1368,7 +1368,7 @@ config KEXEC config CRASH_DUMP bool "kernel crash dumps" depends on X86_64 || (X86_32 && HIGHMEM) - help + ---help--- Generate crash dump after being started by kexec. This should be normally only set in special crash dump kernels which are loaded in the main kernel with kexec-tools into @@ -1383,7 +1383,7 @@ config KEXEC_JUMP bool "kexec jump (EXPERIMENTAL)" depends on EXPERIMENTAL depends on KEXEC && HIBERNATION && X86_32 - help + ---help--- Jump between original kernel and kexeced kernel and invoke code in physical address mode via KEXEC @@ -1392,7 +1392,7 @@ config PHYSICAL_START default "0x1000000" if X86_NUMAQ default "0x200000" if X86_64 default "0x100000" - help + ---help--- This gives the physical address where the kernel is loaded. If kernel is a not relocatable (CONFIG_RELOCATABLE=n) then @@ -1433,7 +1433,7 @@ config PHYSICAL_START config RELOCATABLE bool "Build a relocatable kernel (EXPERIMENTAL)" depends on EXPERIMENTAL - help + ---help--- This builds a kernel image that retains relocation information so it can be loaded someplace besides the default 1MB. The relocations tend to make the kernel binary about 10% larger, @@ -1453,7 +1453,7 @@ config PHYSICAL_ALIGN default "0x100000" if X86_32 default "0x200000" if X86_64 range 0x2000 0x400000 - help + ---help--- This value puts the alignment restrictions on physical address where kernel is loaded and run from. Kernel is compiled for an address which meets above alignment restriction. @@ -1486,7 +1486,7 @@ config COMPAT_VDSO def_bool y prompt "Compat VDSO support" depends on X86_32 || IA32_EMULATION - help + ---help--- Map the 32-bit VDSO to the predictable old-style address too. ---help--- Say N here if you are running a sufficiently recent glibc @@ -1498,7 +1498,7 @@ config COMPAT_VDSO config CMDLINE_BOOL bool "Built-in kernel command line" default n - help + ---help--- Allow for specifying boot arguments to the kernel at build time. On some systems (e.g. embedded ones), it is necessary or convenient to provide some or all of the @@ -1516,7 +1516,7 @@ config CMDLINE string "Built-in kernel command string" depends on CMDLINE_BOOL default "" - help + ---help--- Enter arguments here that should be compiled into the kernel image and used at boot time. If the boot loader provides a command line at boot time, it is appended to this string to @@ -1533,7 +1533,7 @@ config CMDLINE_OVERRIDE bool "Built-in command line overrides boot loader arguments" default n depends on CMDLINE_BOOL - help + ---help--- Set this option to 'Y' to have the kernel ignore the boot loader command line, and use ONLY the built-in command line. @@ -1632,7 +1632,7 @@ if APM config APM_IGNORE_USER_SUSPEND bool "Ignore USER SUSPEND" - help + ---help--- This option will ignore USER SUSPEND requests. On machines with a compliant APM BIOS, you want to say N. However, on the NEC Versa M series notebooks, it is necessary to say Y because of a BIOS bug. @@ -1656,7 +1656,7 @@ config APM_DO_ENABLE config APM_CPU_IDLE bool "Make CPU Idle calls when idle" - help + ---help--- Enable calls to APM CPU Idle/CPU Busy inside the kernel's idle loop. On some machines, this can activate improved power savings, such as a slowed CPU clock rate, when the machine is idle. These idle calls @@ -1667,7 +1667,7 @@ config APM_CPU_IDLE config APM_DISPLAY_BLANK bool "Enable console blanking using APM" - help + ---help--- Enable console blanking using the APM. Some laptops can use this to turn off the LCD backlight when the screen blanker of the Linux virtual console blanks the screen. Note that this is only used by @@ -1680,7 +1680,7 @@ config APM_DISPLAY_BLANK config APM_ALLOW_INTS bool "Allow interrupts during APM BIOS calls" - help + ---help--- Normally we disable external interrupts while we are making calls to the APM BIOS as a measure to lessen the effects of a badly behaving BIOS implementation. The BIOS should reenable interrupts if it @@ -1705,7 +1705,7 @@ config PCI bool "PCI support" default y select ARCH_SUPPORTS_MSI if (X86_LOCAL_APIC && X86_IO_APIC) - help + ---help--- Find out whether you have a PCI motherboard. PCI is the name of a bus system, i.e. the way the CPU talks to the other stuff inside your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or @@ -1776,7 +1776,7 @@ config PCI_MMCONFIG config DMAR bool "Support for DMA Remapping Devices (EXPERIMENTAL)" depends on X86_64 && PCI_MSI && ACPI && EXPERIMENTAL - help + ---help--- DMA remapping (DMAR) devices support enables independent address translations for Direct Memory Access (DMA) from devices. These DMA remapping devices are reported via ACPI tables @@ -1798,29 +1798,29 @@ config DMAR_GFX_WA def_bool y prompt "Support for Graphics workaround" depends on DMAR - help - Current Graphics drivers tend to use physical address - for DMA and avoid using DMA APIs. Setting this config - option permits the IOMMU driver to set a unity map for - all the OS-visible memory. Hence the driver can continue - to use physical addresses for DMA. + ---help--- + Current Graphics drivers tend to use physical address + for DMA and avoid using DMA APIs. Setting this config + option permits the IOMMU driver to set a unity map for + all the OS-visible memory. Hence the driver can continue + to use physical addresses for DMA. config DMAR_FLOPPY_WA def_bool y depends on DMAR - help - Floppy disk drivers are know to bypass DMA API calls - thereby failing to work when IOMMU is enabled. This - workaround will setup a 1:1 mapping for the first - 16M to make floppy (an ISA device) work. + ---help--- + Floppy disk drivers are know to bypass DMA API calls + thereby failing to work when IOMMU is enabled. This + workaround will setup a 1:1 mapping for the first + 16M to make floppy (an ISA device) work. config INTR_REMAP bool "Support for Interrupt Remapping (EXPERIMENTAL)" depends on X86_64 && X86_IO_APIC && PCI_MSI && ACPI && EXPERIMENTAL - help - Supports Interrupt remapping for IO-APIC and MSI devices. - To use x2apic mode in the CPU's which support x2APIC enhancements or - to support platforms with CPU's having > 8 bit APIC ID, say Y. + ---help--- + Supports Interrupt remapping for IO-APIC and MSI devices. + To use x2apic mode in the CPU's which support x2APIC enhancements or + to support platforms with CPU's having > 8 bit APIC ID, say Y. source "drivers/pci/pcie/Kconfig" @@ -1834,7 +1834,7 @@ if X86_32 config ISA bool "ISA support" - help + ---help--- Find out whether you have ISA slots on your motherboard. ISA is the name of a bus system, i.e. the way the CPU talks to the other stuff inside your box. Other bus systems are PCI, EISA, MicroChannel @@ -1861,7 +1861,7 @@ source "drivers/eisa/Kconfig" config MCA bool "MCA support" - help + ---help--- MicroChannel Architecture is found in some IBM PS/2 machines and laptops. It is a bus system similar to PCI or ISA. See (and especially the web page given @@ -1871,7 +1871,7 @@ source "drivers/mca/Kconfig" config SCx200 tristate "NatSemi SCx200 support" - help + ---help--- This provides basic support for National Semiconductor's (now AMD's) Geode processors. The driver probes for the PCI-IDs of several on-chip devices, so its a good dependency @@ -1883,7 +1883,7 @@ config SCx200HR_TIMER tristate "NatSemi SCx200 27MHz High-Resolution Timer Support" depends on SCx200 && GENERIC_TIME default y - help + ---help--- This driver provides a clocksource built upon the on-chip 27MHz high-resolution timer. Its also a workaround for NSC Geode SC-1100's buggy TSC, which loses time when the @@ -1894,7 +1894,7 @@ config GEODE_MFGPT_TIMER def_bool y prompt "Geode Multi-Function General Purpose Timer (MFGPT) events" depends on MGEODE_LX && GENERIC_TIME && GENERIC_CLOCKEVENTS - help + ---help--- This driver provides a clock event source based on the MFGPT timer(s) in the CS5535 and CS5536 companion chip for the geode. MFGPTs have a better resolution and max interval than the @@ -1903,7 +1903,7 @@ config GEODE_MFGPT_TIMER config OLPC bool "One Laptop Per Child support" default n - help + ---help--- Add support for detecting the unique features of the OLPC XO hardware. @@ -1928,16 +1928,16 @@ config IA32_EMULATION bool "IA32 Emulation" depends on X86_64 select COMPAT_BINFMT_ELF - help + ---help--- Include code to run 32-bit programs under a 64-bit kernel. You should likely turn this on, unless you're 100% sure that you don't have any 32-bit programs left. config IA32_AOUT - tristate "IA32 a.out support" - depends on IA32_EMULATION - help - Support old a.out binaries in the 32bit emulation. + tristate "IA32 a.out support" + depends on IA32_EMULATION + ---help--- + Support old a.out binaries in the 32bit emulation. config COMPAT def_bool y diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index 085fef4d866..a95eaf0e582 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -50,7 +50,7 @@ config M386 config M486 bool "486" depends on X86_32 - help + ---help--- Select this for a 486 series processor, either Intel or one of the compatible processors from AMD, Cyrix, IBM, or Intel. Includes DX, DX2, and DX4 variants; also SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or @@ -59,7 +59,7 @@ config M486 config M586 bool "586/K5/5x86/6x86/6x86MX" depends on X86_32 - help + ---help--- Select this for an 586 or 686 series processor such as the AMD K5, the Cyrix 5x86, 6x86 and 6x86MX. This choice does not assume the RDTSC (Read Time Stamp Counter) instruction. @@ -67,21 +67,21 @@ config M586 config M586TSC bool "Pentium-Classic" depends on X86_32 - help + ---help--- Select this for a Pentium Classic processor with the RDTSC (Read Time Stamp Counter) instruction for benchmarking. config M586MMX bool "Pentium-MMX" depends on X86_32 - help + ---help--- Select this for a Pentium with the MMX graphics/multimedia extended instructions. config M686 bool "Pentium-Pro" depends on X86_32 - help + ---help--- Select this for Intel Pentium Pro chips. This enables the use of Pentium Pro extended instructions, and disables the init-time guard against the f00f bug found in earlier Pentiums. @@ -89,7 +89,7 @@ config M686 config MPENTIUMII bool "Pentium-II/Celeron(pre-Coppermine)" depends on X86_32 - help + ---help--- Select this for Intel chips based on the Pentium-II and pre-Coppermine Celeron core. This option enables an unaligned copy optimization, compiles the kernel with optimization flags @@ -99,7 +99,7 @@ config MPENTIUMII config MPENTIUMIII bool "Pentium-III/Celeron(Coppermine)/Pentium-III Xeon" depends on X86_32 - help + ---help--- Select this for Intel chips based on the Pentium-III and Celeron-Coppermine core. This option enables use of some extended prefetch instructions in addition to the Pentium II @@ -108,14 +108,14 @@ config MPENTIUMIII config MPENTIUMM bool "Pentium M" depends on X86_32 - help + ---help--- Select this for Intel Pentium M (not Pentium-4 M) notebook chips. config MPENTIUM4 bool "Pentium-4/Celeron(P4-based)/Pentium-4 M/older Xeon" depends on X86_32 - help + ---help--- Select this for Intel Pentium 4 chips. This includes the Pentium 4, Pentium D, P4-based Celeron and Xeon, and Pentium-4 M (not Pentium M) chips. This option enables compile @@ -151,7 +151,7 @@ config MPENTIUM4 config MK6 bool "K6/K6-II/K6-III" depends on X86_32 - help + ---help--- Select this for an AMD K6-family processor. Enables use of some extended instructions, and passes appropriate optimization flags to GCC. @@ -159,14 +159,14 @@ config MK6 config MK7 bool "Athlon/Duron/K7" depends on X86_32 - help + ---help--- Select this for an AMD Athlon K7-family processor. Enables use of some extended instructions, and passes appropriate optimization flags to GCC. config MK8 bool "Opteron/Athlon64/Hammer/K8" - help + ---help--- Select this for an AMD Opteron or Athlon64 Hammer-family processor. Enables use of some extended instructions, and passes appropriate optimization flags to GCC. @@ -174,7 +174,7 @@ config MK8 config MCRUSOE bool "Crusoe" depends on X86_32 - help + ---help--- Select this for a Transmeta Crusoe processor. Treats the processor like a 586 with TSC, and sets some GCC optimization flags (like a Pentium Pro with no alignment requirements). @@ -182,13 +182,13 @@ config MCRUSOE config MEFFICEON bool "Efficeon" depends on X86_32 - help + ---help--- Select this for a Transmeta Efficeon processor. config MWINCHIPC6 bool "Winchip-C6" depends on X86_32 - help + ---help--- Select this for an IDT Winchip C6 chip. Linux and GCC treat this chip as a 586TSC with some extended instructions and alignment requirements. @@ -196,7 +196,7 @@ config MWINCHIPC6 config MWINCHIP3D bool "Winchip-2/Winchip-2A/Winchip-3" depends on X86_32 - help + ---help--- Select this for an IDT Winchip-2, 2A or 3. Linux and GCC treat this chip as a 586TSC with some extended instructions and alignment requirements. Also enable out of order memory @@ -206,19 +206,19 @@ config MWINCHIP3D config MGEODEGX1 bool "GeodeGX1" depends on X86_32 - help + ---help--- Select this for a Geode GX1 (Cyrix MediaGX) chip. config MGEODE_LX bool "Geode GX/LX" depends on X86_32 - help + ---help--- Select this for AMD Geode GX and LX processors. config MCYRIXIII bool "CyrixIII/VIA-C3" depends on X86_32 - help + ---help--- Select this for a Cyrix III or C3 chip. Presently Linux and GCC treat this chip as a generic 586. Whilst the CPU is 686 class, it lacks the cmov extension which gcc assumes is present when @@ -230,7 +230,7 @@ config MCYRIXIII config MVIAC3_2 bool "VIA C3-2 (Nehemiah)" depends on X86_32 - help + ---help--- Select this for a VIA C3 "Nehemiah". Selecting this enables usage of SSE and tells gcc to treat the CPU as a 686. Note, this kernel will not boot on older (pre model 9) C3s. @@ -238,14 +238,14 @@ config MVIAC3_2 config MVIAC7 bool "VIA C7" depends on X86_32 - help + ---help--- Select this for a VIA C7. Selecting this uses the correct cache shift and tells gcc to treat the CPU as a 686. config MPSC bool "Intel P4 / older Netburst based Xeon" depends on X86_64 - help + ---help--- Optimize for Intel Pentium 4, Pentium D and older Nocona/Dempsey Xeon CPUs with Intel 64bit which is compatible with x86-64. Note that the latest Xeons (Xeon 51xx and 53xx) are not based on the @@ -255,7 +255,7 @@ config MPSC config MCORE2 bool "Core 2/newer Xeon" - help + ---help--- Select this for Intel Core 2 and newer Core 2 Xeons (Xeon 51xx and 53xx) CPUs. You can distinguish newer from older Xeons by the CPU @@ -265,7 +265,7 @@ config MCORE2 config GENERIC_CPU bool "Generic-x86-64" depends on X86_64 - help + ---help--- Generic x86-64 CPU. Run equally well on all x86-64 CPUs. @@ -274,7 +274,7 @@ endchoice config X86_GENERIC bool "Generic x86 support" depends on X86_32 - help + ---help--- Instead of just including optimizations for the selected x86 variant (e.g. PII, Crusoe or Athlon), include some more generic optimizations as well. This will make the kernel @@ -319,7 +319,7 @@ config X86_XADD config X86_PPRO_FENCE bool "PentiumPro memory ordering errata workaround" depends on M686 || M586MMX || M586TSC || M586 || M486 || M386 || MGEODEGX1 - help + ---help--- Old PentiumPro multiprocessor systems had errata that could cause memory operations to violate the x86 ordering standard in rare cases. Enabling this option will attempt to work around some (but not all) @@ -412,14 +412,14 @@ config X86_DEBUGCTLMSR menuconfig PROCESSOR_SELECT bool "Supported processor vendors" if EMBEDDED - help + ---help--- This lets you choose what x86 vendor support code your kernel will include. config CPU_SUP_INTEL default y bool "Support Intel processors" if PROCESSOR_SELECT - help + ---help--- This enables detection, tunings and quirks for Intel processors You need this enabled if you want your kernel to run on an @@ -433,7 +433,7 @@ config CPU_SUP_CYRIX_32 default y bool "Support Cyrix processors" if PROCESSOR_SELECT depends on !64BIT - help + ---help--- This enables detection, tunings and quirks for Cyrix processors You need this enabled if you want your kernel to run on a @@ -446,7 +446,7 @@ config CPU_SUP_CYRIX_32 config CPU_SUP_AMD default y bool "Support AMD processors" if PROCESSOR_SELECT - help + ---help--- This enables detection, tunings and quirks for AMD processors You need this enabled if you want your kernel to run on an @@ -460,7 +460,7 @@ config CPU_SUP_CENTAUR_32 default y bool "Support Centaur processors" if PROCESSOR_SELECT depends on !64BIT - help + ---help--- This enables detection, tunings and quirks for Centaur processors You need this enabled if you want your kernel to run on a @@ -474,7 +474,7 @@ config CPU_SUP_CENTAUR_64 default y bool "Support Centaur processors" if PROCESSOR_SELECT depends on 64BIT - help + ---help--- This enables detection, tunings and quirks for Centaur processors You need this enabled if you want your kernel to run on a @@ -488,7 +488,7 @@ config CPU_SUP_TRANSMETA_32 default y bool "Support Transmeta processors" if PROCESSOR_SELECT depends on !64BIT - help + ---help--- This enables detection, tunings and quirks for Transmeta processors You need this enabled if you want your kernel to run on a @@ -502,7 +502,7 @@ config CPU_SUP_UMC_32 default y bool "Support UMC processors" if PROCESSOR_SELECT depends on !64BIT - help + ---help--- This enables detection, tunings and quirks for UMC processors You need this enabled if you want your kernel to run on a @@ -521,7 +521,7 @@ config X86_PTRACE_BTS bool "Branch Trace Store" default y depends on X86_DEBUGCTLMSR - help + ---help--- This adds a ptrace interface to the hardware's branch trace store. Debuggers may use it to collect an execution trace of the debugged diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index a38dd6064f1..ba4781b9389 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -7,7 +7,7 @@ source "lib/Kconfig.debug" config STRICT_DEVMEM bool "Filter access to /dev/mem" - help + ---help--- If this option is disabled, you allow userspace (root) access to all of memory, including kernel and userspace memory. Accidental access to this is obviously disastrous, but specific access can @@ -25,7 +25,7 @@ config STRICT_DEVMEM config X86_VERBOSE_BOOTUP bool "Enable verbose x86 bootup info messages" default y - help + ---help--- Enables the informational output from the decompression stage (e.g. bzImage) of the boot. If you disable this you will still see errors. Disable this if you want silent bootup. @@ -33,7 +33,7 @@ config X86_VERBOSE_BOOTUP config EARLY_PRINTK bool "Early printk" if EMBEDDED default y - help + ---help--- Write kernel log output directly into the VGA buffer or to a serial port. @@ -47,7 +47,7 @@ config EARLY_PRINTK_DBGP bool "Early printk via EHCI debug port" default n depends on EARLY_PRINTK && PCI - help + ---help--- Write kernel log output directly into the EHCI debug port. This is useful for kernel debugging when your machine crashes very @@ -59,14 +59,14 @@ config EARLY_PRINTK_DBGP config DEBUG_STACKOVERFLOW bool "Check for stack overflows" depends on DEBUG_KERNEL - help + ---help--- This option will cause messages to be printed if free stack space drops below a certain limit. config DEBUG_STACK_USAGE bool "Stack utilization instrumentation" depends on DEBUG_KERNEL - help + ---help--- Enables the display of the minimum amount of free stack which each task has ever had available in the sysrq-T and sysrq-P debug output. @@ -75,7 +75,7 @@ config DEBUG_STACK_USAGE config DEBUG_PAGEALLOC bool "Debug page memory allocations" depends on DEBUG_KERNEL - help + ---help--- Unmap pages from the kernel linear mapping after free_pages(). This results in a large slowdown, but helps to find certain types of memory corruptions. @@ -85,7 +85,7 @@ config DEBUG_PER_CPU_MAPS depends on DEBUG_KERNEL depends on SMP default n - help + ---help--- Say Y to verify that the per_cpu map being accessed has been setup. Adds a fair amount of code to kernel memory and decreases performance. @@ -96,7 +96,7 @@ config X86_PTDUMP bool "Export kernel pagetable layout to userspace via debugfs" depends on DEBUG_KERNEL select DEBUG_FS - help + ---help--- Say Y here if you want to show the kernel pagetable layout in a debugfs file. This information is only useful for kernel developers who are working in architecture specific areas of the kernel. @@ -108,7 +108,7 @@ config DEBUG_RODATA bool "Write protect kernel read-only data structures" default y depends on DEBUG_KERNEL - help + ---help--- Mark the kernel read-only data as write-protected in the pagetables, in order to catch accidental (and incorrect) writes to such const data. This is recommended so that we can catch kernel bugs sooner. @@ -118,7 +118,7 @@ config DEBUG_RODATA_TEST bool "Testcase for the DEBUG_RODATA feature" depends on DEBUG_RODATA default y - help + ---help--- This option enables a testcase for the DEBUG_RODATA feature as well as for the change_page_attr() infrastructure. If in doubt, say "N" @@ -126,7 +126,7 @@ config DEBUG_RODATA_TEST config DEBUG_NX_TEST tristate "Testcase for the NX non-executable stack feature" depends on DEBUG_KERNEL && m - help + ---help--- This option enables a testcase for the CPU NX capability and the software setup of this feature. If in doubt, say "N" @@ -134,7 +134,7 @@ config DEBUG_NX_TEST config 4KSTACKS bool "Use 4Kb for kernel stacks instead of 8Kb" depends on X86_32 - help + ---help--- If you say Y here the kernel will use a 4Kb stacksize for the kernel stack attached to each process/thread. This facilitates running more threads on a system and also reduces the pressure @@ -145,7 +145,7 @@ config DOUBLEFAULT default y bool "Enable doublefault exception handler" if EMBEDDED depends on X86_32 - help + ---help--- This option allows trapping of rare doublefault exceptions that would otherwise cause a system to silently reboot. Disabling this option saves about 4k and might cause you much additional grey @@ -155,7 +155,7 @@ config IOMMU_DEBUG bool "Enable IOMMU debugging" depends on GART_IOMMU && DEBUG_KERNEL depends on X86_64 - help + ---help--- Force the IOMMU to on even when you have less than 4GB of memory and add debugging code. On overflow always panic. And allow to enable IOMMU leak tracing. Can be disabled at boot @@ -171,7 +171,7 @@ config IOMMU_LEAK bool "IOMMU leak tracing" depends on DEBUG_KERNEL depends on IOMMU_DEBUG - help + ---help--- Add a simple leak tracer to the IOMMU code. This is useful when you are debugging a buggy device driver that leaks IOMMU mappings. @@ -224,25 +224,25 @@ choice config IO_DELAY_0X80 bool "port 0x80 based port-IO delay [recommended]" - help + ---help--- This is the traditional Linux IO delay used for in/out_p. It is the most tested hence safest selection here. config IO_DELAY_0XED bool "port 0xed based port-IO delay" - help + ---help--- Use port 0xed as the IO delay. This frees up port 0x80 which is often used as a hardware-debug port. config IO_DELAY_UDELAY bool "udelay based port-IO delay" - help + ---help--- Use udelay(2) as the IO delay method. This provides the delay while not having any side-effect on the IO port space. config IO_DELAY_NONE bool "no port-IO delay" - help + ---help--- No port-IO delay. Will break on old boxes that require port-IO delay for certain operations. Should work on most new machines. @@ -276,18 +276,18 @@ config DEBUG_BOOT_PARAMS bool "Debug boot parameters" depends on DEBUG_KERNEL depends on DEBUG_FS - help + ---help--- This option will cause struct boot_params to be exported via debugfs. config CPA_DEBUG bool "CPA self-test code" depends on DEBUG_KERNEL - help + ---help--- Do change_page_attr() self-tests every 30 seconds. config OPTIMIZE_INLINING bool "Allow gcc to uninline functions marked 'inline'" - help + ---help--- This option determines if the kernel forces gcc to inline the functions developers have marked 'inline'. Doing so takes away freedom from gcc to do what it thinks is best, which is desirable for the gcc 3.x series of @@ -300,4 +300,3 @@ config OPTIMIZE_INLINING If unsure, say N. endmenu - -- GitLab From 6146f0d5e47ca4047ffded0fb79b6c25359b386c Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Wed, 4 Feb 2009 09:06:57 -0500 Subject: [PATCH 1216/4982] integrity: IMA hooks This patch replaces the generic integrity hooks, for which IMA registered itself, with IMA integrity hooks in the appropriate places directly in the fs directory. Signed-off-by: Mimi Zohar Acked-by: Serge Hallyn Signed-off-by: James Morris --- Documentation/kernel-parameters.txt | 1 + fs/exec.c | 10 +++++++ fs/file_table.c | 2 ++ fs/inode.c | 24 +++++++++++----- fs/namei.c | 8 ++++++ include/linux/ima.h | 44 +++++++++++++++++++++++++++++ mm/mmap.c | 4 +++ 7 files changed, 86 insertions(+), 7 deletions(-) create mode 100644 include/linux/ima.h diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index a2d8805c03d..7c67b94d182 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -44,6 +44,7 @@ parameter is applicable: FB The frame buffer device is enabled. HW Appropriate hardware is enabled. IA-64 IA-64 architecture is enabled. + IMA Integrity measurement architecture is enabled. IOSCHED More than one I/O scheduler is enabled. IP_PNP IP DHCP, BOOTP, or RARP is enabled. ISAPNP ISA PnP code is enabled. diff --git a/fs/exec.c b/fs/exec.c index 02d2e120542..9c789a525cc 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -128,6 +129,9 @@ asmlinkage long sys_uselib(const char __user * library) goto exit; error = vfs_permission(&nd, MAY_READ | MAY_EXEC | MAY_OPEN); + if (error) + goto exit; + error = ima_path_check(&nd.path, MAY_READ | MAY_EXEC | MAY_OPEN); if (error) goto exit; @@ -681,6 +685,9 @@ struct file *open_exec(const char *name) goto out_path_put; err = vfs_permission(&nd, MAY_EXEC | MAY_OPEN); + if (err) + goto out_path_put; + err = ima_path_check(&nd.path, MAY_EXEC | MAY_OPEN); if (err) goto out_path_put; @@ -1207,6 +1214,9 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) } #endif retval = security_bprm_check(bprm); + if (retval) + return retval; + retval = ima_bprm_check(bprm); if (retval) return retval; diff --git a/fs/file_table.c b/fs/file_table.c index 0fbcacc3ea7..55895ccc08c 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -276,6 +277,7 @@ void __fput(struct file *file) if (file->f_op && file->f_op->release) file->f_op->release(inode, file); security_file_free(file); + ima_file_free(file); if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL)) cdev_put(inode->i_cdev); fops_put(file->f_op); diff --git a/fs/inode.c b/fs/inode.c index 098a2443196..ed22b14f220 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -144,13 +145,13 @@ struct inode *inode_init_always(struct super_block *sb, struct inode *inode) inode->i_cdev = NULL; inode->i_rdev = 0; inode->dirtied_when = 0; - if (security_inode_alloc(inode)) { - if (inode->i_sb->s_op->destroy_inode) - inode->i_sb->s_op->destroy_inode(inode); - else - kmem_cache_free(inode_cachep, (inode)); - return NULL; - } + + if (security_inode_alloc(inode)) + goto out_free_inode; + + /* allocate and initialize an i_integrity */ + if (ima_inode_alloc(inode)) + goto out_free_security; spin_lock_init(&inode->i_lock); lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key); @@ -186,6 +187,15 @@ struct inode *inode_init_always(struct super_block *sb, struct inode *inode) inode->i_mapping = mapping; return inode; + +out_free_security: + security_inode_free(inode); +out_free_inode: + if (inode->i_sb->s_op->destroy_inode) + inode->i_sb->s_op->destroy_inode(inode); + else + kmem_cache_free(inode_cachep, (inode)); + return NULL; } EXPORT_SYMBOL(inode_init_always); diff --git a/fs/namei.c b/fs/namei.c index af3783fff1d..734f2b5591b 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -860,6 +861,8 @@ static int __link_path_walk(const char *name, struct nameidata *nd) err = exec_permission_lite(inode); if (err == -EAGAIN) err = vfs_permission(nd, MAY_EXEC); + if (!err) + err = ima_path_check(&nd->path, MAY_EXEC); if (err) break; @@ -1525,6 +1528,11 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) error = vfs_permission(nd, acc_mode); if (error) return error; + + error = ima_path_check(&nd->path, + acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC)); + if (error) + return error; /* * An append-only file must be opened in append mode for writing. */ diff --git a/include/linux/ima.h b/include/linux/ima.h new file mode 100644 index 00000000000..4ed1e4d962e --- /dev/null +++ b/include/linux/ima.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2008 IBM Corporation + * Author: Mimi Zohar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + */ + +#include + +#ifndef _LINUX_IMA_H +#define _LINUX_IMA_H + +static inline int ima_bprm_check(struct linux_binprm *bprm) +{ + return 0; +} + +static inline int ima_inode_alloc(struct inode *inode) +{ + return 0; +} + +static inline void ima_inode_free(struct inode *inode) +{ + return; +} + +static inline int ima_path_check(struct path *path, int mask) +{ + return 0; +} + +static inline void ima_file_free(struct file *file) +{ + return; +} + +static inline int ima_file_mmap(struct file *file, unsigned long prot) +{ + return 0; +} +#endif /* _LINUX_IMA_H */ diff --git a/mm/mmap.c b/mm/mmap.c index d4855a682ab..c3647f3b062 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -1048,6 +1049,9 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, } error = security_file_mmap(file, reqprot, prot, flags, addr, 0); + if (error) + return error; + error = ima_file_mmap(file, prot); if (error) return error; -- GitLab From 3323eec921efd815178a23107ab63588c605c0b2 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Wed, 4 Feb 2009 09:06:58 -0500 Subject: [PATCH 1217/4982] integrity: IMA as an integrity service provider IMA provides hardware (TPM) based measurement and attestation for file measurements. As the Trusted Computing (TPM) model requires, IMA measures all files before they are accessed in any way (on the integrity_bprm_check, integrity_path_check and integrity_file_mmap hooks), and commits the measurements to the TPM. Once added to the TPM, measurements can not be removed. In addition, IMA maintains a list of these file measurements, which can be used to validate the aggregate value stored in the TPM. The TPM can sign these measurements, and thus the system can prove, to itself and to a third party, the system's integrity in a way that cannot be circumvented by malicious or compromised software. - alloc ima_template_entry before calling ima_store_template() - log ima_add_boot_aggregate() failure - removed unused IMA_TEMPLATE_NAME_LEN - replaced hard coded string length with #define name Signed-off-by: Mimi Zohar Signed-off-by: James Morris --- Documentation/kernel-parameters.txt | 9 + include/linux/audit.h | 5 + include/linux/ima.h | 10 + security/Kconfig | 5 +- security/Makefile | 4 + security/integrity/ima/Kconfig | 49 +++++ security/integrity/ima/Makefile | 9 + security/integrity/ima/ima.h | 135 ++++++++++++++ security/integrity/ima/ima_api.c | 190 +++++++++++++++++++ security/integrity/ima/ima_audit.c | 78 ++++++++ security/integrity/ima/ima_crypto.c | 140 ++++++++++++++ security/integrity/ima/ima_iint.c | 185 ++++++++++++++++++ security/integrity/ima/ima_init.c | 90 +++++++++ security/integrity/ima/ima_main.c | 280 ++++++++++++++++++++++++++++ security/integrity/ima/ima_policy.c | 126 +++++++++++++ security/integrity/ima/ima_queue.c | 140 ++++++++++++++ 16 files changed, 1454 insertions(+), 1 deletion(-) create mode 100644 security/integrity/ima/Kconfig create mode 100644 security/integrity/ima/Makefile create mode 100644 security/integrity/ima/ima.h create mode 100644 security/integrity/ima/ima_api.c create mode 100644 security/integrity/ima/ima_audit.c create mode 100644 security/integrity/ima/ima_crypto.c create mode 100644 security/integrity/ima/ima_iint.c create mode 100644 security/integrity/ima/ima_init.c create mode 100644 security/integrity/ima/ima_main.c create mode 100644 security/integrity/ima/ima_policy.c create mode 100644 security/integrity/ima/ima_queue.c diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 7c67b94d182..31e0c2c3c6e 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -895,6 +895,15 @@ and is between 256 and 4096 characters. It is defined in the file ihash_entries= [KNL] Set number of hash buckets for inode cache. + ima_audit= [IMA] + Format: { "0" | "1" } + 0 -- integrity auditing messages. (Default) + 1 -- enable informational integrity auditing messages. + + ima_hash= [IMA] + Formt: { "sha1" | "md5" } + default: "sha1" + in2000= [HW,SCSI] See header of drivers/scsi/in2000.c. diff --git a/include/linux/audit.h b/include/linux/audit.h index 26c4f6f65a4..8d1f67789b5 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -125,6 +125,11 @@ #define AUDIT_LAST_KERN_ANOM_MSG 1799 #define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */ #define AUDIT_ANOM_ABEND 1701 /* Process ended abnormally */ +#define AUDIT_INTEGRITY_DATA 1800 /* Data integrity verification */ +#define AUDIT_INTEGRITY_METADATA 1801 /* Metadata integrity verification */ +#define AUDIT_INTEGRITY_STATUS 1802 /* Integrity enable status */ +#define AUDIT_INTEGRITY_HASH 1803 /* Integrity HASH type */ +#define AUDIT_INTEGRITY_PCR 1804 /* PCR invalidation msgs */ #define AUDIT_KERNEL 2000 /* Asynchronous audit record. NOT A REQUEST. */ diff --git a/include/linux/ima.h b/include/linux/ima.h index 4ed1e4d962e..dcc3664feee 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -12,6 +12,15 @@ #ifndef _LINUX_IMA_H #define _LINUX_IMA_H +#ifdef CONFIG_IMA +extern int ima_bprm_check(struct linux_binprm *bprm); +extern int ima_inode_alloc(struct inode *inode); +extern void ima_inode_free(struct inode *inode); +extern int ima_path_check(struct path *path, int mask); +extern void ima_file_free(struct file *file); +extern int ima_file_mmap(struct file *file, unsigned long prot); + +#else static inline int ima_bprm_check(struct linux_binprm *bprm) { return 0; @@ -41,4 +50,5 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot) { return 0; } +#endif /* CONFIG_IMA_H */ #endif /* _LINUX_IMA_H */ diff --git a/security/Kconfig b/security/Kconfig index d9f47ce7e20..a79b23f73d0 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -55,7 +55,8 @@ config SECURITYFS bool "Enable the securityfs filesystem" help This will build the securityfs filesystem. It is currently used by - the TPM bios character driver. It is not used by SELinux or SMACK. + the TPM bios character driver and IMA, an integrity provider. It is + not used by SELinux or SMACK. If you are unsure how to answer this question, answer N. @@ -126,5 +127,7 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR source security/selinux/Kconfig source security/smack/Kconfig +source security/integrity/ima/Kconfig + endmenu diff --git a/security/Makefile b/security/Makefile index c05c127fff9..595536cbffb 100644 --- a/security/Makefile +++ b/security/Makefile @@ -17,3 +17,7 @@ obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o + +# Object integrity file lists +subdir-$(CONFIG_IMA) += integrity/ima +obj-$(CONFIG_IMA) += integrity/ima/built-in.o diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig new file mode 100644 index 00000000000..2a761c8ac99 --- /dev/null +++ b/security/integrity/ima/Kconfig @@ -0,0 +1,49 @@ +# IBM Integrity Measurement Architecture +# +config IMA + bool "Integrity Measurement Architecture(IMA)" + depends on ACPI + select SECURITYFS + select CRYPTO + select CRYPTO_HMAC + select CRYPTO_MD5 + select CRYPTO_SHA1 + select TCG_TPM + select TCG_TIS + help + The Trusted Computing Group(TCG) runtime Integrity + Measurement Architecture(IMA) maintains a list of hash + values of executables and other sensitive system files, + as they are read or executed. If an attacker manages + to change the contents of an important system file + being measured, we can tell. + + If your system has a TPM chip, then IMA also maintains + an aggregate integrity value over this list inside the + TPM hardware, so that the TPM can prove to a third party + whether or not critical system files have been modified. + Read + to learn more about IMA. + If unsure, say N. + +config IMA_MEASURE_PCR_IDX + int + depends on IMA + range 8 14 + default 10 + help + IMA_MEASURE_PCR_IDX determines the TPM PCR register index + that IMA uses to maintain the integrity aggregate of the + measurement list. If unsure, use the default 10. + +config IMA_AUDIT + bool + depends on IMA + default y + help + This option adds a kernel parameter 'ima_audit', which + allows informational auditing messages to be enabled + at boot. If this option is selected, informational integrity + auditing messages can be enabled with 'ima_audit=1' on + the kernel command line. + diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile new file mode 100644 index 00000000000..9d6bf973b9b --- /dev/null +++ b/security/integrity/ima/Makefile @@ -0,0 +1,9 @@ +# +# Makefile for building Trusted Computing Group's(TCG) runtime Integrity +# Measurement Architecture(IMA). +# + +obj-$(CONFIG_IMA) += ima.o + +ima-y := ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \ + ima_policy.o ima_iint.o ima_audit.o diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h new file mode 100644 index 00000000000..bfa72ed41b9 --- /dev/null +++ b/security/integrity/ima/ima.h @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2005,2006,2007,2008 IBM Corporation + * + * Authors: + * Reiner Sailer + * Mimi Zohar + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * File: ima.h + * internal Integrity Measurement Architecture (IMA) definitions + */ + +#ifndef __LINUX_IMA_H +#define __LINUX_IMA_H + +#include +#include +#include +#include +#include +#include + +enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_ASCII }; +enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 }; + +/* digest size for IMA, fits SHA1 or MD5 */ +#define IMA_DIGEST_SIZE 20 +#define IMA_EVENT_NAME_LEN_MAX 255 + +#define IMA_HASH_BITS 9 +#define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS) + +/* set during initialization */ +extern int ima_initialized; +extern int ima_used_chip; +extern char *ima_hash; + +/* IMA inode template definition */ +struct ima_template_data { + u8 digest[IMA_DIGEST_SIZE]; /* sha1/md5 measurement hash */ + char file_name[IMA_EVENT_NAME_LEN_MAX + 1]; /* name + \0 */ +}; + +struct ima_template_entry { + u8 digest[IMA_DIGEST_SIZE]; /* sha1 or md5 measurement hash */ + char *template_name; + int template_len; + struct ima_template_data template; +}; + +struct ima_queue_entry { + struct hlist_node hnext; /* place in hash collision list */ + struct list_head later; /* place in ima_measurements list */ + struct ima_template_entry *entry; +}; +extern struct list_head ima_measurements; /* list of all measurements */ + +/* declarations */ +void integrity_audit_msg(int audit_msgno, struct inode *inode, + const unsigned char *fname, const char *op, + const char *cause, int result, int info); + +/* Internal IMA function definitions */ +void ima_iintcache_init(void); +int ima_init(void); +int ima_add_template_entry(struct ima_template_entry *entry, int violation, + const char *op, struct inode *inode); +int ima_calc_hash(struct file *file, char *digest); +int ima_calc_template_hash(int template_len, void *template, char *digest); +int ima_calc_boot_aggregate(char *digest); +void ima_add_violation(struct inode *inode, const unsigned char *filename, + const char *op, const char *cause); + +/* + * used to protect h_table and sha_table + */ +extern spinlock_t ima_queue_lock; + +struct ima_h_table { + atomic_long_t len; /* number of stored measurements in the list */ + atomic_long_t violations; + struct hlist_head queue[IMA_MEASURE_HTABLE_SIZE]; +}; +extern struct ima_h_table ima_htable; + +static inline unsigned long ima_hash_key(u8 *digest) +{ + return hash_long(*digest, IMA_HASH_BITS); +} + +/* iint cache flags */ +#define IMA_MEASURED 1 + +/* integrity data associated with an inode */ +struct ima_iint_cache { + u64 version; /* track inode changes */ + unsigned long flags; + u8 digest[IMA_DIGEST_SIZE]; + struct mutex mutex; /* protects: version, flags, digest */ + long readcount; /* measured files readcount */ + long writecount; /* measured files writecount */ + struct kref refcount; /* ima_iint_cache reference count */ + struct rcu_head rcu; +}; + +/* LIM API function definitions */ +int ima_must_measure(struct ima_iint_cache *iint, struct inode *inode, + int mask, int function); +int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file); +void ima_store_measurement(struct ima_iint_cache *iint, struct file *file, + const unsigned char *filename); +int ima_store_template(struct ima_template_entry *entry, int violation, + struct inode *inode); + +/* radix tree calls to lookup, insert, delete + * integrity data associated with an inode. + */ +struct ima_iint_cache *ima_iint_insert(struct inode *inode); +struct ima_iint_cache *ima_iint_find_get(struct inode *inode); +struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode); +void ima_iint_delete(struct inode *inode); +void iint_free(struct kref *kref); +void iint_rcu_free(struct rcu_head *rcu); + +/* IMA policy related functions */ +enum ima_hooks { PATH_CHECK = 1, FILE_MMAP, BPRM_CHECK }; + +int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask); +void ima_init_policy(void); +void ima_update_policy(void); +#endif diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c new file mode 100644 index 00000000000..a148a25804f --- /dev/null +++ b/security/integrity/ima/ima_api.c @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2008 IBM Corporation + * + * Author: Mimi Zohar + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * File: ima_api.c + * Implements must_measure, collect_measurement, store_measurement, + * and store_template. + */ +#include + +#include "ima.h" +static char *IMA_TEMPLATE_NAME = "ima"; + +/* + * ima_store_template - store ima template measurements + * + * Calculate the hash of a template entry, add the template entry + * to an ordered list of measurement entries maintained inside the kernel, + * and also update the aggregate integrity value (maintained inside the + * configured TPM PCR) over the hashes of the current list of measurement + * entries. + * + * Applications retrieve the current kernel-held measurement list through + * the securityfs entries in /sys/kernel/security/ima. The signed aggregate + * TPM PCR (called quote) can be retrieved using a TPM user space library + * and is used to validate the measurement list. + * + * Returns 0 on success, error code otherwise + */ +int ima_store_template(struct ima_template_entry *entry, + int violation, struct inode *inode) +{ + const char *op = "add_template_measure"; + const char *audit_cause = "hashing_error"; + int result; + + memset(entry->digest, 0, sizeof(entry->digest)); + entry->template_name = IMA_TEMPLATE_NAME; + entry->template_len = sizeof(entry->template); + + if (!violation) { + result = ima_calc_template_hash(entry->template_len, + &entry->template, + entry->digest); + if (result < 0) { + integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, + entry->template_name, op, + audit_cause, result, 0); + return result; + } + } + result = ima_add_template_entry(entry, violation, op, inode); + return result; +} + +/* + * ima_add_violation - add violation to measurement list. + * + * Violations are flagged in the measurement list with zero hash values. + * By extending the PCR with 0xFF's instead of with zeroes, the PCR + * value is invalidated. + */ +void ima_add_violation(struct inode *inode, const unsigned char *filename, + const char *op, const char *cause) +{ + struct ima_template_entry *entry; + int violation = 1; + int result; + + /* can overflow, only indicator */ + atomic_long_inc(&ima_htable.violations); + + entry = kmalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) { + result = -ENOMEM; + goto err_out; + } + memset(&entry->template, 0, sizeof(entry->template)); + strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX); + result = ima_store_template(entry, violation, inode); + if (result < 0) + kfree(entry); +err_out: + integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename, + op, cause, result, 0); +} + +/** + * ima_must_measure - measure decision based on policy. + * @inode: pointer to inode to measure + * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE) + * @function: calling function (PATH_CHECK, BPRM_CHECK, FILE_MMAP) + * + * The policy is defined in terms of keypairs: + * subj=, obj=, type=, func=, mask=, fsmagic= + * subj,obj, and type: are LSM specific. + * func: PATH_CHECK | BPRM_CHECK | FILE_MMAP + * mask: contains the permission mask + * fsmagic: hex value + * + * Must be called with iint->mutex held. + * + * Return 0 to measure. Return 1 if already measured. + * For matching a DONT_MEASURE policy, no policy, or other + * error, return an error code. +*/ +int ima_must_measure(struct ima_iint_cache *iint, struct inode *inode, + int mask, int function) +{ + int must_measure; + + if (iint->flags & IMA_MEASURED) + return 1; + + must_measure = ima_match_policy(inode, function, mask); + return must_measure ? 0 : -EACCES; +} + +/* + * ima_collect_measurement - collect file measurement + * + * Calculate the file hash, if it doesn't already exist, + * storing the measurement and i_version in the iint. + * + * Must be called with iint->mutex held. + * + * Return 0 on success, error code otherwise + */ +int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file) +{ + int result = -EEXIST; + + if (!(iint->flags & IMA_MEASURED)) { + u64 i_version = file->f_dentry->d_inode->i_version; + + memset(iint->digest, 0, IMA_DIGEST_SIZE); + result = ima_calc_hash(file, iint->digest); + if (!result) + iint->version = i_version; + } + return result; +} + +/* + * ima_store_measurement - store file measurement + * + * Create an "ima" template and then store the template by calling + * ima_store_template. + * + * We only get here if the inode has not already been measured, + * but the measurement could already exist: + * - multiple copies of the same file on either the same or + * different filesystems. + * - the inode was previously flushed as well as the iint info, + * containing the hashing info. + * + * Must be called with iint->mutex held. + */ +void ima_store_measurement(struct ima_iint_cache *iint, struct file *file, + const unsigned char *filename) +{ + const char *op = "add_template_measure"; + const char *audit_cause = "ENOMEM"; + int result = -ENOMEM; + struct inode *inode = file->f_dentry->d_inode; + struct ima_template_entry *entry; + int violation = 0; + + entry = kmalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) { + integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename, + op, audit_cause, result, 0); + return; + } + memset(&entry->template, 0, sizeof(entry->template)); + memcpy(entry->template.digest, iint->digest, IMA_DIGEST_SIZE); + strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX); + + result = ima_store_template(entry, violation, inode); + if (!result) + iint->flags |= IMA_MEASURED; + else + kfree(entry); +} diff --git a/security/integrity/ima/ima_audit.c b/security/integrity/ima/ima_audit.c new file mode 100644 index 00000000000..8a0f1e23ccf --- /dev/null +++ b/security/integrity/ima/ima_audit.c @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2008 IBM Corporation + * Author: Mimi Zohar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * File: integrity_audit.c + * Audit calls for the integrity subsystem + */ + +#include +#include +#include "ima.h" + +static int ima_audit; + +#ifdef CONFIG_IMA_AUDIT + +/* ima_audit_setup - enable informational auditing messages */ +static int __init ima_audit_setup(char *str) +{ + unsigned long audit; + int rc; + char *op; + + rc = strict_strtoul(str, 0, &audit); + if (rc || audit > 1) + printk(KERN_INFO "ima: invalid ima_audit value\n"); + else + ima_audit = audit; + op = ima_audit ? "ima_audit_enabled" : "ima_audit_not_enabled"; + integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL, NULL, op, 0, 0); + return 1; +} +__setup("ima_audit=", ima_audit_setup); +#endif + +void integrity_audit_msg(int audit_msgno, struct inode *inode, + const unsigned char *fname, const char *op, + const char *cause, int result, int audit_info) +{ + struct audit_buffer *ab; + + if (!ima_audit && audit_info == 1) /* Skip informational messages */ + return; + + ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno); + audit_log_format(ab, "integrity: pid=%d uid=%u auid=%u", + current->pid, current->cred->uid, + audit_get_loginuid(current)); + audit_log_task_context(ab); + switch (audit_msgno) { + case AUDIT_INTEGRITY_DATA: + case AUDIT_INTEGRITY_METADATA: + case AUDIT_INTEGRITY_PCR: + audit_log_format(ab, " op=%s cause=%s", op, cause); + break; + case AUDIT_INTEGRITY_HASH: + audit_log_format(ab, " op=%s hash=%s", op, cause); + break; + case AUDIT_INTEGRITY_STATUS: + default: + audit_log_format(ab, " op=%s", op); + } + audit_log_format(ab, " comm="); + audit_log_untrustedstring(ab, current->comm); + if (fname) { + audit_log_format(ab, " name="); + audit_log_untrustedstring(ab, fname); + } + if (inode) + audit_log_format(ab, " dev=%s ino=%lu", + inode->i_sb->s_id, inode->i_ino); + audit_log_format(ab, " res=%d", result); + audit_log_end(ab); +} diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c new file mode 100644 index 00000000000..c2a46e40999 --- /dev/null +++ b/security/integrity/ima/ima_crypto.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2005,2006,2007,2008 IBM Corporation + * + * Authors: + * Mimi Zohar + * Kylene Hall + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * File: ima_crypto.c + * Calculates md5/sha1 file hash, template hash, boot-aggreate hash + */ + +#include +#include +#include +#include +#include +#include "ima.h" + +static int init_desc(struct hash_desc *desc) +{ + int rc; + + desc->tfm = crypto_alloc_hash(ima_hash, 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(desc->tfm)) { + pr_info("failed to load %s transform: %ld\n", + ima_hash, PTR_ERR(desc->tfm)); + rc = PTR_ERR(desc->tfm); + return rc; + } + desc->flags = 0; + rc = crypto_hash_init(desc); + if (rc) + crypto_free_hash(desc->tfm); + return rc; +} + +/* + * Calculate the MD5/SHA1 file digest + */ +int ima_calc_hash(struct file *file, char *digest) +{ + struct hash_desc desc; + struct scatterlist sg[1]; + loff_t i_size; + char *rbuf; + int rc, offset = 0; + + rc = init_desc(&desc); + if (rc != 0) + return rc; + + rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (!rbuf) { + rc = -ENOMEM; + goto out; + } + i_size = i_size_read(file->f_dentry->d_inode); + while (offset < i_size) { + int rbuf_len; + + rbuf_len = kernel_read(file, offset, rbuf, PAGE_SIZE); + if (rbuf_len < 0) { + rc = rbuf_len; + break; + } + offset += rbuf_len; + sg_set_buf(sg, rbuf, rbuf_len); + + rc = crypto_hash_update(&desc, sg, rbuf_len); + if (rc) + break; + } + kfree(rbuf); + if (!rc) + rc = crypto_hash_final(&desc, digest); +out: + crypto_free_hash(desc.tfm); + return rc; +} + +/* + * Calculate the hash of a given template + */ +int ima_calc_template_hash(int template_len, void *template, char *digest) +{ + struct hash_desc desc; + struct scatterlist sg[1]; + int rc; + + rc = init_desc(&desc); + if (rc != 0) + return rc; + + sg_set_buf(sg, template, template_len); + rc = crypto_hash_update(&desc, sg, template_len); + if (!rc) + rc = crypto_hash_final(&desc, digest); + crypto_free_hash(desc.tfm); + return rc; +} + +static void ima_pcrread(int idx, u8 *pcr) +{ + if (!ima_used_chip) + return; + + if (tpm_pcr_read(TPM_ANY_NUM, idx, pcr) != 0) + pr_err("Error Communicating to TPM chip\n"); +} + +/* + * Calculate the boot aggregate hash + */ +int ima_calc_boot_aggregate(char *digest) +{ + struct hash_desc desc; + struct scatterlist sg; + u8 pcr_i[IMA_DIGEST_SIZE]; + int rc, i; + + rc = init_desc(&desc); + if (rc != 0) + return rc; + + /* cumulative sha1 over tpm registers 0-7 */ + for (i = TPM_PCR0; i < TPM_PCR8; i++) { + ima_pcrread(i, pcr_i); + /* now accumulate with current aggregate */ + sg_init_one(&sg, pcr_i, IMA_DIGEST_SIZE); + rc = crypto_hash_update(&desc, &sg, IMA_DIGEST_SIZE); + } + if (!rc) + crypto_hash_final(&desc, digest); + crypto_free_hash(desc.tfm); + return rc; +} diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c new file mode 100644 index 00000000000..750db3c993a --- /dev/null +++ b/security/integrity/ima/ima_iint.c @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2008 IBM Corporation + * + * Authors: + * Mimi Zohar + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * File: ima_iint.c + * - implements the IMA hooks: ima_inode_alloc, ima_inode_free + * - cache integrity information associated with an inode + * using a radix tree. + */ +#include +#include +#include +#include "ima.h" + +#define ima_iint_delete ima_inode_free + +RADIX_TREE(ima_iint_store, GFP_ATOMIC); +DEFINE_SPINLOCK(ima_iint_lock); + +static struct kmem_cache *iint_cache __read_mostly; + +/* ima_iint_find_get - return the iint associated with an inode + * + * ima_iint_find_get gets a reference to the iint. Caller must + * remember to put the iint reference. + */ +struct ima_iint_cache *ima_iint_find_get(struct inode *inode) +{ + struct ima_iint_cache *iint; + + rcu_read_lock(); + iint = radix_tree_lookup(&ima_iint_store, (unsigned long)inode); + if (!iint) + goto out; + kref_get(&iint->refcount); +out: + rcu_read_unlock(); + return iint; +} + +/* Allocate memory for the iint associated with the inode + * from the iint_cache slab, initialize the iint, and + * insert it into the radix tree. + * + * On success return a pointer to the iint; on failure return NULL. + */ +struct ima_iint_cache *ima_iint_insert(struct inode *inode) +{ + struct ima_iint_cache *iint = NULL; + int rc = 0; + + if (!ima_initialized) + return iint; + iint = kmem_cache_alloc(iint_cache, GFP_KERNEL); + if (!iint) + return iint; + + rc = radix_tree_preload(GFP_KERNEL); + if (rc < 0) + goto out; + + spin_lock(&ima_iint_lock); + rc = radix_tree_insert(&ima_iint_store, (unsigned long)inode, iint); + spin_unlock(&ima_iint_lock); +out: + if (rc < 0) { + kmem_cache_free(iint_cache, iint); + if (rc == -EEXIST) { + iint = radix_tree_lookup(&ima_iint_store, + (unsigned long)inode); + } else + iint = NULL; + } + radix_tree_preload_end(); + return iint; +} + +/** + * ima_inode_alloc - allocate an iint associated with an inode + * @inode: pointer to the inode + * + * Return 0 on success, 1 on failure. + */ +int ima_inode_alloc(struct inode *inode) +{ + struct ima_iint_cache *iint; + + if (!ima_initialized) + return 0; + + iint = ima_iint_insert(inode); + if (!iint) + return 1; + return 0; +} + +/* ima_iint_find_insert_get - get the iint associated with an inode + * + * Most insertions are done at inode_alloc, except those allocated + * before late_initcall. When the iint does not exist, allocate it, + * initialize and insert it, and increment the iint refcount. + * + * (Can't initialize at security_initcall before any inodes are + * allocated, got to wait at least until proc_init.) + * + * Return the iint. + */ +struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode) +{ + struct ima_iint_cache *iint = NULL; + + iint = ima_iint_find_get(inode); + if (iint) + return iint; + + iint = ima_iint_insert(inode); + if (iint) + kref_get(&iint->refcount); + + return iint; +} + +/* iint_free - called when the iint refcount goes to zero */ +void iint_free(struct kref *kref) +{ + struct ima_iint_cache *iint = container_of(kref, struct ima_iint_cache, + refcount); + iint->version = 0; + iint->flags = 0UL; + kref_set(&iint->refcount, 1); + kmem_cache_free(iint_cache, iint); +} + +void iint_rcu_free(struct rcu_head *rcu_head) +{ + struct ima_iint_cache *iint = container_of(rcu_head, + struct ima_iint_cache, rcu); + kref_put(&iint->refcount, iint_free); +} + +/** + * ima_iint_delete - called on integrity_inode_free + * @inode: pointer to the inode + * + * Free the integrity information(iint) associated with an inode. + */ +void ima_iint_delete(struct inode *inode) +{ + struct ima_iint_cache *iint; + + if (!ima_initialized) + return; + spin_lock(&ima_iint_lock); + iint = radix_tree_delete(&ima_iint_store, (unsigned long)inode); + spin_unlock(&ima_iint_lock); + if (iint) + call_rcu(&iint->rcu, iint_rcu_free); +} + +static void init_once(void *foo) +{ + struct ima_iint_cache *iint = foo; + + memset(iint, 0, sizeof *iint); + iint->version = 0; + iint->flags = 0UL; + mutex_init(&iint->mutex); + iint->readcount = 0; + iint->writecount = 0; + kref_set(&iint->refcount, 1); +} + +void ima_iintcache_init(void) +{ + iint_cache = + kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0, + SLAB_PANIC, init_once); +} diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c new file mode 100644 index 00000000000..e0f02e328d7 --- /dev/null +++ b/security/integrity/ima/ima_init.c @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2005,2006,2007,2008 IBM Corporation + * + * Authors: + * Reiner Sailer + * Leendert van Doorn + * Mimi Zohar + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * File: ima_init.c + * initialization and cleanup functions + */ +#include +#include +#include +#include "ima.h" + +/* name for boot aggregate entry */ +static char *boot_aggregate_name = "boot_aggregate"; +int ima_used_chip; + +/* Add the boot aggregate to the IMA measurement list and extend + * the PCR register. + * + * Calculate the boot aggregate, a SHA1 over tpm registers 0-7, + * assuming a TPM chip exists, and zeroes if the TPM chip does not + * exist. Add the boot aggregate measurement to the measurement + * list and extend the PCR register. + * + * If a tpm chip does not exist, indicate the core root of trust is + * not hardware based by invalidating the aggregate PCR value. + * (The aggregate PCR value is invalidated by adding one value to + * the measurement list and extending the aggregate PCR value with + * a different value.) Violations add a zero entry to the measurement + * list and extend the aggregate PCR value with ff...ff's. + */ +static void ima_add_boot_aggregate(void) +{ + struct ima_template_entry *entry; + const char *op = "add_boot_aggregate"; + const char *audit_cause = "ENOMEM"; + int result = -ENOMEM; + int violation = 1; + + entry = kmalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + goto err_out; + + memset(&entry->template, 0, sizeof(entry->template)); + strncpy(entry->template.file_name, boot_aggregate_name, + IMA_EVENT_NAME_LEN_MAX); + if (ima_used_chip) { + violation = 0; + result = ima_calc_boot_aggregate(entry->template.digest); + if (result < 0) { + audit_cause = "hashing_error"; + kfree(entry); + goto err_out; + } + } + result = ima_store_template(entry, violation, NULL); + if (result < 0) + kfree(entry); + return; +err_out: + integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL, boot_aggregate_name, op, + audit_cause, result, 0); +} + +int ima_init(void) +{ + u8 pcr_i[IMA_DIGEST_SIZE]; + int rc; + + ima_used_chip = 0; + rc = tpm_pcr_read(TPM_ANY_NUM, 0, pcr_i); + if (rc == 0) + ima_used_chip = 1; + + if (!ima_used_chip) + pr_info("No TPM chip found, activating TPM-bypass!\n"); + + ima_add_boot_aggregate(); /* boot aggregate must be first entry */ + ima_init_policy(); + return 0; +} diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c new file mode 100644 index 00000000000..53cee4c512c --- /dev/null +++ b/security/integrity/ima/ima_main.c @@ -0,0 +1,280 @@ +/* + * Copyright (C) 2005,2006,2007,2008 IBM Corporation + * + * Authors: + * Reiner Sailer + * Serge Hallyn + * Kylene Hall + * Mimi Zohar + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * File: ima_main.c + * implements the IMA hooks: ima_bprm_check, ima_file_mmap, + * and ima_path_check. + */ +#include +#include +#include +#include +#include + +#include "ima.h" + +int ima_initialized; + +char *ima_hash = "sha1"; +static int __init hash_setup(char *str) +{ + const char *op = "hash_setup"; + const char *hash = "sha1"; + int result = 0; + int audit_info = 0; + + if (strncmp(str, "md5", 3) == 0) { + hash = "md5"; + ima_hash = str; + } else if (strncmp(str, "sha1", 4) != 0) { + hash = "invalid_hash_type"; + result = 1; + } + integrity_audit_msg(AUDIT_INTEGRITY_HASH, NULL, NULL, op, hash, + result, audit_info); + return 1; +} +__setup("ima_hash=", hash_setup); + +/** + * ima_file_free - called on __fput() + * @file: pointer to file structure being freed + * + * Flag files that changed, based on i_version; + * and decrement the iint readcount/writecount. + */ +void ima_file_free(struct file *file) +{ + struct inode *inode = file->f_dentry->d_inode; + struct ima_iint_cache *iint; + + if (!ima_initialized || !S_ISREG(inode->i_mode)) + return; + iint = ima_iint_find_get(inode); + if (!iint) + return; + + mutex_lock(&iint->mutex); + if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) + iint->readcount--; + + if (file->f_mode & FMODE_WRITE) { + iint->writecount--; + if (iint->writecount == 0) { + if (iint->version != inode->i_version) + iint->flags &= ~IMA_MEASURED; + } + } + mutex_unlock(&iint->mutex); + kref_put(&iint->refcount, iint_free); +} + +/* ima_read_write_check - reflect possible reading/writing errors in the PCR. + * + * When opening a file for read, if the file is already open for write, + * the file could change, resulting in a file measurement error. + * + * Opening a file for write, if the file is already open for read, results + * in a time of measure, time of use (ToMToU) error. + * + * In either case invalidate the PCR. + */ +enum iint_pcr_error { TOMTOU, OPEN_WRITERS }; +static void ima_read_write_check(enum iint_pcr_error error, + struct ima_iint_cache *iint, + struct inode *inode, + const unsigned char *filename) +{ + switch (error) { + case TOMTOU: + if (iint->readcount > 0) + ima_add_violation(inode, filename, "invalid_pcr", + "ToMToU"); + break; + case OPEN_WRITERS: + if (iint->writecount > 0) + ima_add_violation(inode, filename, "invalid_pcr", + "open_writers"); + break; + } +} + +static int get_path_measurement(struct ima_iint_cache *iint, struct file *file, + const unsigned char *filename) +{ + int rc = 0; + + if (IS_ERR(file)) { + pr_info("%s dentry_open failed\n", filename); + return rc; + } + iint->readcount++; + + rc = ima_collect_measurement(iint, file); + if (!rc) + ima_store_measurement(iint, file, filename); + return rc; +} + +/** + * ima_path_check - based on policy, collect/store measurement. + * @path: contains a pointer to the path to be measured + * @mask: contains MAY_READ, MAY_WRITE or MAY_EXECUTE + * + * Measure the file being open for readonly, based on the + * ima_must_measure() policy decision. + * + * Keep read/write counters for all files, but only + * invalidate the PCR for measured files: + * - Opening a file for write when already open for read, + * results in a time of measure, time of use (ToMToU) error. + * - Opening a file for read when already open for write, + * could result in a file measurement error. + * + * Return 0 on success, an error code on failure. + * (Based on the results of appraise_measurement().) + */ +int ima_path_check(struct path *path, int mask) +{ + struct inode *inode = path->dentry->d_inode; + struct ima_iint_cache *iint; + struct file *file = NULL; + int rc; + + if (!ima_initialized || !S_ISREG(inode->i_mode)) + return 0; + iint = ima_iint_find_insert_get(inode); + if (!iint) + return 0; + + mutex_lock(&iint->mutex); + if ((mask & MAY_WRITE) || (mask == 0)) + iint->writecount++; + else if (mask & (MAY_READ | MAY_EXEC)) + iint->readcount++; + + rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK); + if (rc < 0) + goto out; + + if ((mask & MAY_WRITE) || (mask == 0)) + ima_read_write_check(TOMTOU, iint, inode, + path->dentry->d_name.name); + + if ((mask & (MAY_WRITE | MAY_READ | MAY_EXEC)) != MAY_READ) + goto out; + + ima_read_write_check(OPEN_WRITERS, iint, inode, + path->dentry->d_name.name); + if (!(iint->flags & IMA_MEASURED)) { + struct dentry *dentry = dget(path->dentry); + struct vfsmount *mnt = mntget(path->mnt); + + file = dentry_open(dentry, mnt, O_RDONLY, current->cred); + rc = get_path_measurement(iint, file, dentry->d_name.name); + } +out: + mutex_unlock(&iint->mutex); + if (file) + fput(file); + kref_put(&iint->refcount, iint_free); + return 0; +} + +static int process_measurement(struct file *file, const unsigned char *filename, + int mask, int function) +{ + struct inode *inode = file->f_dentry->d_inode; + struct ima_iint_cache *iint; + int rc; + + if (!ima_initialized || !S_ISREG(inode->i_mode)) + return 0; + iint = ima_iint_find_insert_get(inode); + if (!iint) + return -ENOMEM; + + mutex_lock(&iint->mutex); + rc = ima_must_measure(iint, inode, mask, function); + if (rc != 0) + goto out; + + rc = ima_collect_measurement(iint, file); + if (!rc) + ima_store_measurement(iint, file, filename); +out: + mutex_unlock(&iint->mutex); + kref_put(&iint->refcount, iint_free); + return rc; +} + +/** + * ima_file_mmap - based on policy, collect/store measurement. + * @file: pointer to the file to be measured (May be NULL) + * @prot: contains the protection that will be applied by the kernel. + * + * Measure files being mmapped executable based on the ima_must_measure() + * policy decision. + * + * Return 0 on success, an error code on failure. + * (Based on the results of appraise_measurement().) + */ +int ima_file_mmap(struct file *file, unsigned long prot) +{ + int rc; + + if (!file) + return 0; + if (prot & PROT_EXEC) + rc = process_measurement(file, file->f_dentry->d_name.name, + MAY_EXEC, FILE_MMAP); + return 0; +} + +/** + * ima_bprm_check - based on policy, collect/store measurement. + * @bprm: contains the linux_binprm structure + * + * The OS protects against an executable file, already open for write, + * from being executed in deny_write_access() and an executable file, + * already open for execute, from being modified in get_write_access(). + * So we can be certain that what we verify and measure here is actually + * what is being executed. + * + * Return 0 on success, an error code on failure. + * (Based on the results of appraise_measurement().) + */ +int ima_bprm_check(struct linux_binprm *bprm) +{ + int rc; + + rc = process_measurement(bprm->file, bprm->filename, + MAY_EXEC, BPRM_CHECK); + return 0; +} + +static int __init init_ima(void) +{ + int error; + + ima_iintcache_init(); + error = ima_init(); + ima_initialized = 1; + return error; +} + +late_initcall(init_ima); /* Start IMA after the TPM is available */ + +MODULE_DESCRIPTION("Integrity Measurement Architecture"); +MODULE_LICENSE("GPL"); diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c new file mode 100644 index 00000000000..7c3d1ffb147 --- /dev/null +++ b/security/integrity/ima/ima_policy.c @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2008 IBM Corporation + * Author: Mimi Zohar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * ima_policy.c + * - initialize default measure policy rules + * + */ +#include +#include +#include +#include +#include + +#include "ima.h" + +/* flags definitions */ +#define IMA_FUNC 0x0001 +#define IMA_MASK 0x0002 +#define IMA_FSMAGIC 0x0004 +#define IMA_UID 0x0008 + +enum ima_action { DONT_MEASURE, MEASURE }; + +struct ima_measure_rule_entry { + struct list_head list; + enum ima_action action; + unsigned int flags; + enum ima_hooks func; + int mask; + unsigned long fsmagic; + uid_t uid; +}; + +static struct ima_measure_rule_entry default_rules[] = { + {.action = DONT_MEASURE,.fsmagic = PROC_SUPER_MAGIC, + .flags = IMA_FSMAGIC}, + {.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC}, + {.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC}, + {.action = DONT_MEASURE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC}, + {.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC, + .flags = IMA_FSMAGIC}, + {.action = DONT_MEASURE,.fsmagic = 0xF97CFF8C,.flags = IMA_FSMAGIC}, + {.action = MEASURE,.func = FILE_MMAP,.mask = MAY_EXEC, + .flags = IMA_FUNC | IMA_MASK}, + {.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC, + .flags = IMA_FUNC | IMA_MASK}, + {.action = MEASURE,.func = PATH_CHECK,.mask = MAY_READ,.uid = 0, + .flags = IMA_FUNC | IMA_MASK | IMA_UID} +}; + +static LIST_HEAD(measure_default_rules); +static struct list_head *ima_measure; + +/** + * ima_match_rules - determine whether an inode matches the measure rule. + * @rule: a pointer to a rule + * @inode: a pointer to an inode + * @func: LIM hook identifier + * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC) + * + * Returns true on rule match, false on failure. + */ +static bool ima_match_rules(struct ima_measure_rule_entry *rule, + struct inode *inode, enum ima_hooks func, int mask) +{ + struct task_struct *tsk = current; + + if ((rule->flags & IMA_FUNC) && rule->func != func) + return false; + if ((rule->flags & IMA_MASK) && rule->mask != mask) + return false; + if ((rule->flags & IMA_FSMAGIC) + && rule->fsmagic != inode->i_sb->s_magic) + return false; + if ((rule->flags & IMA_UID) && rule->uid != tsk->cred->uid) + return false; + return true; +} + +/** + * ima_match_policy - decision based on LSM and other conditions + * @inode: pointer to an inode for which the policy decision is being made + * @func: IMA hook identifier + * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC) + * + * Measure decision based on func/mask/fsmagic and LSM(subj/obj/type) + * conditions. + * + * (There is no need for locking when walking the policy list, + * as elements in the list are never deleted, nor does the list + * change.) + */ +int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask) +{ + struct ima_measure_rule_entry *entry; + + list_for_each_entry(entry, ima_measure, list) { + bool rc; + + rc = ima_match_rules(entry, inode, func, mask); + if (rc) + return entry->action; + } + return 0; +} + +/** + * ima_init_policy - initialize the default measure rules. + * + * (Could use the default_rules directly, but in policy patch + * ima_measure points to either the measure_default_rules or the + * the new measure_policy_rules.) + */ +void ima_init_policy(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(default_rules); i++) + list_add_tail(&default_rules[i].list, &measure_default_rules); + ima_measure = &measure_default_rules; +} diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c new file mode 100644 index 00000000000..7ec94314ac0 --- /dev/null +++ b/security/integrity/ima/ima_queue.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2005,2006,2007,2008 IBM Corporation + * + * Authors: + * Serge Hallyn + * Reiner Sailer + * Mimi Zohar + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * File: ima_queue.c + * Implements queues that store template measurements and + * maintains aggregate over the stored measurements + * in the pre-configured TPM PCR (if available). + * The measurement list is append-only. No entry is + * ever removed or changed during the boot-cycle. + */ +#include +#include +#include "ima.h" + +LIST_HEAD(ima_measurements); /* list of all measurements */ + +/* key: inode (before secure-hashing a file) */ +struct ima_h_table ima_htable = { + .len = ATOMIC_LONG_INIT(0), + .violations = ATOMIC_LONG_INIT(0), + .queue[0 ... IMA_MEASURE_HTABLE_SIZE - 1] = HLIST_HEAD_INIT +}; + +/* mutex protects atomicity of extending measurement list + * and extending the TPM PCR aggregate. Since tpm_extend can take + * long (and the tpm driver uses a mutex), we can't use the spinlock. + */ +static DEFINE_MUTEX(ima_extend_list_mutex); + +/* lookup up the digest value in the hash table, and return the entry */ +static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value) +{ + struct ima_queue_entry *qe, *ret = NULL; + unsigned int key; + struct hlist_node *pos; + int rc; + + key = ima_hash_key(digest_value); + rcu_read_lock(); + hlist_for_each_entry_rcu(qe, pos, &ima_htable.queue[key], hnext) { + rc = memcmp(qe->entry->digest, digest_value, IMA_DIGEST_SIZE); + if (rc == 0) { + ret = qe; + break; + } + } + rcu_read_unlock(); + return ret; +} + +/* ima_add_template_entry helper function: + * - Add template entry to measurement list and hash table. + * + * (Called with ima_extend_list_mutex held.) + */ +static int ima_add_digest_entry(struct ima_template_entry *entry) +{ + struct ima_queue_entry *qe; + unsigned int key; + + qe = kmalloc(sizeof(*qe), GFP_KERNEL); + if (qe == NULL) { + pr_err("OUT OF MEMORY ERROR creating queue entry.\n"); + return -ENOMEM; + } + qe->entry = entry; + + INIT_LIST_HEAD(&qe->later); + list_add_tail_rcu(&qe->later, &ima_measurements); + + atomic_long_inc(&ima_htable.len); + key = ima_hash_key(entry->digest); + hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]); + return 0; +} + +static int ima_pcr_extend(const u8 *hash) +{ + int result = 0; + + if (!ima_used_chip) + return result; + + result = tpm_pcr_extend(TPM_ANY_NUM, CONFIG_IMA_MEASURE_PCR_IDX, hash); + if (result != 0) + pr_err("Error Communicating to TPM chip\n"); + return result; +} + +/* Add template entry to the measurement list and hash table, + * and extend the pcr. + */ +int ima_add_template_entry(struct ima_template_entry *entry, int violation, + const char *op, struct inode *inode) +{ + u8 digest[IMA_DIGEST_SIZE]; + const char *audit_cause = "hash_added"; + int audit_info = 1; + int result = 0; + + mutex_lock(&ima_extend_list_mutex); + if (!violation) { + memcpy(digest, entry->digest, sizeof digest); + if (ima_lookup_digest_entry(digest)) { + audit_cause = "hash_exists"; + goto out; + } + } + + result = ima_add_digest_entry(entry); + if (result < 0) { + audit_cause = "ENOMEM"; + audit_info = 0; + goto out; + } + + if (violation) /* invalidate pcr */ + memset(digest, 0xff, sizeof digest); + + result = ima_pcr_extend(digest); + if (result != 0) { + audit_cause = "TPM error"; + audit_info = 0; + } +out: + mutex_unlock(&ima_extend_list_mutex); + integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, entry->template_name, + op, audit_cause, result, audit_info); + return result; +} -- GitLab From bab739378758a1e2b2d7ddcee7bc06cf4c591c3c Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Wed, 4 Feb 2009 09:06:59 -0500 Subject: [PATCH 1218/4982] integrity: IMA display Make the measurement lists available through securityfs. - removed test for NULL return code from securityfs_create_file/dir Signed-off-by: Mimi Zohar Acked-by: Serge Hallyn Signed-off-by: James Morris --- security/integrity/ima/Makefile | 2 +- security/integrity/ima/ima.h | 5 + security/integrity/ima/ima_fs.c | 296 ++++++++++++++++++++++++++++++ security/integrity/ima/ima_init.c | 8 +- security/integrity/ima/ima_main.c | 5 + 5 files changed, 314 insertions(+), 2 deletions(-) create mode 100644 security/integrity/ima/ima_fs.c diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile index 9d6bf973b9b..787c4cb916c 100644 --- a/security/integrity/ima/Makefile +++ b/security/integrity/ima/Makefile @@ -5,5 +5,5 @@ obj-$(CONFIG_IMA) += ima.o -ima-y := ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \ +ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \ ima_policy.o ima_iint.o ima_audit.o diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index bfa72ed41b9..9c280cc7300 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -67,6 +67,9 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode, /* Internal IMA function definitions */ void ima_iintcache_init(void); int ima_init(void); +void ima_cleanup(void); +int ima_fs_init(void); +void ima_fs_cleanup(void); int ima_add_template_entry(struct ima_template_entry *entry, int violation, const char *op, struct inode *inode); int ima_calc_hash(struct file *file, char *digest); @@ -115,6 +118,8 @@ void ima_store_measurement(struct ima_iint_cache *iint, struct file *file, const unsigned char *filename); int ima_store_template(struct ima_template_entry *entry, int violation, struct inode *inode); +void ima_template_show(struct seq_file *m, void *e, + enum ima_show_type show); /* radix tree calls to lookup, insert, delete * integrity data associated with an inode. diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c new file mode 100644 index 00000000000..4f25be768b5 --- /dev/null +++ b/security/integrity/ima/ima_fs.c @@ -0,0 +1,296 @@ +/* + * Copyright (C) 2005,2006,2007,2008 IBM Corporation + * + * Authors: + * Kylene Hall + * Reiner Sailer + * Mimi Zohar + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * File: ima_fs.c + * implemenents security file system for reporting + * current measurement list and IMA statistics + */ +#include +#include +#include +#include + +#include "ima.h" + +#define TMPBUFLEN 12 +static ssize_t ima_show_htable_value(char __user *buf, size_t count, + loff_t *ppos, atomic_long_t *val) +{ + char tmpbuf[TMPBUFLEN]; + ssize_t len; + + len = scnprintf(tmpbuf, TMPBUFLEN, "%li\n", atomic_long_read(val)); + return simple_read_from_buffer(buf, count, ppos, tmpbuf, len); +} + +static ssize_t ima_show_htable_violations(struct file *filp, + char __user *buf, + size_t count, loff_t *ppos) +{ + return ima_show_htable_value(buf, count, ppos, &ima_htable.violations); +} + +static struct file_operations ima_htable_violations_ops = { + .read = ima_show_htable_violations +}; + +static ssize_t ima_show_measurements_count(struct file *filp, + char __user *buf, + size_t count, loff_t *ppos) +{ + return ima_show_htable_value(buf, count, ppos, &ima_htable.len); + +} + +static struct file_operations ima_measurements_count_ops = { + .read = ima_show_measurements_count +}; + +/* returns pointer to hlist_node */ +static void *ima_measurements_start(struct seq_file *m, loff_t *pos) +{ + loff_t l = *pos; + struct ima_queue_entry *qe; + + /* we need a lock since pos could point beyond last element */ + rcu_read_lock(); + list_for_each_entry_rcu(qe, &ima_measurements, later) { + if (!l--) { + rcu_read_unlock(); + return qe; + } + } + rcu_read_unlock(); + return NULL; +} + +static void *ima_measurements_next(struct seq_file *m, void *v, loff_t *pos) +{ + struct ima_queue_entry *qe = v; + + /* lock protects when reading beyond last element + * against concurrent list-extension + */ + rcu_read_lock(); + qe = list_entry(rcu_dereference(qe->later.next), + struct ima_queue_entry, later); + rcu_read_unlock(); + (*pos)++; + + return (&qe->later == &ima_measurements) ? NULL : qe; +} + +static void ima_measurements_stop(struct seq_file *m, void *v) +{ +} + +static void ima_putc(struct seq_file *m, void *data, int datalen) +{ + while (datalen--) + seq_putc(m, *(char *)data++); +} + +/* print format: + * 32bit-le=pcr# + * char[20]=template digest + * 32bit-le=template name size + * char[n]=template name + * eventdata[n]=template specific data + */ +static int ima_measurements_show(struct seq_file *m, void *v) +{ + /* the list never shrinks, so we don't need a lock here */ + struct ima_queue_entry *qe = v; + struct ima_template_entry *e; + int namelen; + u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX; + + /* get entry */ + e = qe->entry; + if (e == NULL) + return -1; + + /* + * 1st: PCRIndex + * PCR used is always the same (config option) in + * little-endian format + */ + ima_putc(m, &pcr, sizeof pcr); + + /* 2nd: template digest */ + ima_putc(m, e->digest, IMA_DIGEST_SIZE); + + /* 3rd: template name size */ + namelen = strlen(e->template_name); + ima_putc(m, &namelen, sizeof namelen); + + /* 4th: template name */ + ima_putc(m, e->template_name, namelen); + + /* 5th: template specific data */ + ima_template_show(m, (struct ima_template_data *)&e->template, + IMA_SHOW_BINARY); + return 0; +} + +static struct seq_operations ima_measurments_seqops = { + .start = ima_measurements_start, + .next = ima_measurements_next, + .stop = ima_measurements_stop, + .show = ima_measurements_show +}; + +static int ima_measurements_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &ima_measurments_seqops); +} + +static struct file_operations ima_measurements_ops = { + .open = ima_measurements_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static void ima_print_digest(struct seq_file *m, u8 *digest) +{ + int i; + + for (i = 0; i < IMA_DIGEST_SIZE; i++) + seq_printf(m, "%02x", *(digest + i)); +} + +void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show) +{ + struct ima_template_data *entry = e; + int namelen; + + switch (show) { + case IMA_SHOW_ASCII: + ima_print_digest(m, entry->digest); + seq_printf(m, " %s\n", entry->file_name); + break; + case IMA_SHOW_BINARY: + ima_putc(m, entry->digest, IMA_DIGEST_SIZE); + + namelen = strlen(entry->file_name); + ima_putc(m, &namelen, sizeof namelen); + ima_putc(m, entry->file_name, namelen); + default: + break; + } +} + +/* print in ascii */ +static int ima_ascii_measurements_show(struct seq_file *m, void *v) +{ + /* the list never shrinks, so we don't need a lock here */ + struct ima_queue_entry *qe = v; + struct ima_template_entry *e; + + /* get entry */ + e = qe->entry; + if (e == NULL) + return -1; + + /* 1st: PCR used (config option) */ + seq_printf(m, "%2d ", CONFIG_IMA_MEASURE_PCR_IDX); + + /* 2nd: SHA1 template hash */ + ima_print_digest(m, e->digest); + + /* 3th: template name */ + seq_printf(m, " %s ", e->template_name); + + /* 4th: template specific data */ + ima_template_show(m, (struct ima_template_data *)&e->template, + IMA_SHOW_ASCII); + return 0; +} + +static struct seq_operations ima_ascii_measurements_seqops = { + .start = ima_measurements_start, + .next = ima_measurements_next, + .stop = ima_measurements_stop, + .show = ima_ascii_measurements_show +}; + +static int ima_ascii_measurements_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &ima_ascii_measurements_seqops); +} + +static struct file_operations ima_ascii_measurements_ops = { + .open = ima_ascii_measurements_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static struct dentry *ima_dir; +static struct dentry *binary_runtime_measurements; +static struct dentry *ascii_runtime_measurements; +static struct dentry *runtime_measurements_count; +static struct dentry *violations; + +int ima_fs_init(void) +{ + ima_dir = securityfs_create_dir("ima", NULL); + if (IS_ERR(ima_dir)) + return -1; + + binary_runtime_measurements = + securityfs_create_file("binary_runtime_measurements", + S_IRUSR | S_IRGRP, ima_dir, NULL, + &ima_measurements_ops); + if (IS_ERR(binary_runtime_measurements)) + goto out; + + ascii_runtime_measurements = + securityfs_create_file("ascii_runtime_measurements", + S_IRUSR | S_IRGRP, ima_dir, NULL, + &ima_ascii_measurements_ops); + if (IS_ERR(ascii_runtime_measurements)) + goto out; + + runtime_measurements_count = + securityfs_create_file("runtime_measurements_count", + S_IRUSR | S_IRGRP, ima_dir, NULL, + &ima_measurements_count_ops); + if (IS_ERR(runtime_measurements_count)) + goto out; + + violations = + securityfs_create_file("violations", S_IRUSR | S_IRGRP, + ima_dir, NULL, &ima_htable_violations_ops); + if (IS_ERR(violations)) + goto out; + + return 0; + +out: + securityfs_remove(runtime_measurements_count); + securityfs_remove(ascii_runtime_measurements); + securityfs_remove(binary_runtime_measurements); + securityfs_remove(ima_dir); + return -1; +} + +void __exit ima_fs_cleanup(void) +{ + securityfs_remove(violations); + securityfs_remove(runtime_measurements_count); + securityfs_remove(ascii_runtime_measurements); + securityfs_remove(binary_runtime_measurements); + securityfs_remove(ima_dir); +} diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index e0f02e328d7..cf227dbfac2 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -86,5 +86,11 @@ int ima_init(void) ima_add_boot_aggregate(); /* boot aggregate must be first entry */ ima_init_policy(); - return 0; + + return ima_fs_init(); +} + +void __exit ima_cleanup(void) +{ + ima_fs_cleanup(); } diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 53cee4c512c..871e356e8d6 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -274,6 +274,11 @@ static int __init init_ima(void) return error; } +static void __exit cleanup_ima(void) +{ + ima_cleanup(); +} + late_initcall(init_ima); /* Start IMA after the TPM is available */ MODULE_DESCRIPTION("Integrity Measurement Architecture"); -- GitLab From 4af4662fa4a9dc62289c580337ae2506339c4729 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Wed, 4 Feb 2009 09:07:00 -0500 Subject: [PATCH 1219/4982] integrity: IMA policy Support for a user loadable policy through securityfs with support for LSM specific policy data. - free invalid rule in ima_parse_add_rule() Signed-off-by: Mimi Zohar Acked-by: Serge Hallyn Signed-off-by: James Morris --- Documentation/ABI/testing/ima_policy | 61 ++++++ security/integrity/ima/Kconfig | 6 + security/integrity/ima/ima.h | 24 +++ security/integrity/ima/ima_fs.c | 67 +++++- security/integrity/ima/ima_policy.c | 293 ++++++++++++++++++++++++++- 5 files changed, 447 insertions(+), 4 deletions(-) create mode 100644 Documentation/ABI/testing/ima_policy diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy new file mode 100644 index 00000000000..6434f0df012 --- /dev/null +++ b/Documentation/ABI/testing/ima_policy @@ -0,0 +1,61 @@ +What: security/ima/policy +Date: May 2008 +Contact: Mimi Zohar +Description: + The Trusted Computing Group(TCG) runtime Integrity + Measurement Architecture(IMA) maintains a list of hash + values of executables and other sensitive system files + loaded into the run-time of this system. At runtime, + the policy can be constrained based on LSM specific data. + Policies are loaded into the securityfs file ima/policy + by opening the file, writing the rules one at a time and + then closing the file. The new policy takes effect after + the file ima/policy is closed. + + rule format: action [condition ...] + + action: measure | dont_measure + condition:= base | lsm + base: [[func=] [mask=] [fsmagic=] [uid=]] + lsm: [[subj_user=] [subj_role=] [subj_type=] + [obj_user=] [obj_role=] [obj_type=]] + + base: func:= [BPRM_CHECK][FILE_MMAP][INODE_PERMISSION] + mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC] + fsmagic:= hex value + uid:= decimal value + lsm: are LSM specific + + default policy: + # PROC_SUPER_MAGIC + dont_measure fsmagic=0x9fa0 + # SYSFS_MAGIC + dont_measure fsmagic=0x62656572 + # DEBUGFS_MAGIC + dont_measure fsmagic=0x64626720 + # TMPFS_MAGIC + dont_measure fsmagic=0x01021994 + # SECURITYFS_MAGIC + dont_measure fsmagic=0x73636673 + + measure func=BPRM_CHECK + measure func=FILE_MMAP mask=MAY_EXEC + measure func=INODE_PERM mask=MAY_READ uid=0 + + The default policy measures all executables in bprm_check, + all files mmapped executable in file_mmap, and all files + open for read by root in inode_permission. + + Examples of LSM specific definitions: + + SELinux: + # SELINUX_MAGIC + dont_measure fsmagic=0xF97CFF8C + + dont_measure obj_type=var_log_t + dont_measure obj_type=auditd_log_t + measure subj_user=system_u func=INODE_PERM mask=MAY_READ + measure subj_role=system_r func=INODE_PERM mask=MAY_READ + + Smack: + measure subj_user=_ func=INODE_PERM mask=MAY_READ diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 2a761c8ac99..3d2b6ee778a 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -47,3 +47,9 @@ config IMA_AUDIT auditing messages can be enabled with 'ima_audit=1' on the kernel command line. +config IMA_LSM_RULES + bool + depends on IMA && (SECURITY_SELINUX || SECURITY_SMACK) + default y + help + Disabling this option will disregard LSM based policy rules diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 9c280cc7300..42706b55492 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -137,4 +137,28 @@ enum ima_hooks { PATH_CHECK = 1, FILE_MMAP, BPRM_CHECK }; int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask); void ima_init_policy(void); void ima_update_policy(void); +int ima_parse_add_rule(char *); +void ima_delete_rules(void); + +/* LSM based policy rules require audit */ +#ifdef CONFIG_IMA_LSM_RULES + +#define security_filter_rule_init security_audit_rule_init +#define security_filter_rule_match security_audit_rule_match + +#else + +static inline int security_filter_rule_init(u32 field, u32 op, char *rulestr, + void **lsmrule) +{ + return -EINVAL; +} + +static inline int security_filter_rule_match(u32 secid, u32 field, u32 op, + void *lsmrule, + struct audit_context *actx) +{ + return -EINVAL; +} +#endif /* CONFIG_IMA_LSM_RULES */ #endif diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 4f25be768b5..95ef1caa64b 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -19,9 +19,11 @@ #include #include #include +#include #include "ima.h" +static int valid_policy = 1; #define TMPBUFLEN 12 static ssize_t ima_show_htable_value(char __user *buf, size_t count, loff_t *ppos, atomic_long_t *val) @@ -237,11 +239,66 @@ static struct file_operations ima_ascii_measurements_ops = { .release = seq_release, }; +static ssize_t ima_write_policy(struct file *file, const char __user *buf, + size_t datalen, loff_t *ppos) +{ + char *data; + int rc; + + if (datalen >= PAGE_SIZE) + return -ENOMEM; + if (*ppos != 0) { + /* No partial writes. */ + return -EINVAL; + } + data = kmalloc(datalen + 1, GFP_KERNEL); + if (!data) + return -ENOMEM; + + if (copy_from_user(data, buf, datalen)) { + kfree(data); + return -EFAULT; + } + *(data + datalen) = '\0'; + rc = ima_parse_add_rule(data); + if (rc < 0) { + datalen = -EINVAL; + valid_policy = 0; + } + + kfree(data); + return datalen; +} + static struct dentry *ima_dir; static struct dentry *binary_runtime_measurements; static struct dentry *ascii_runtime_measurements; static struct dentry *runtime_measurements_count; static struct dentry *violations; +static struct dentry *ima_policy; + +/* + * ima_release_policy - start using the new measure policy rules. + * + * Initially, ima_measure points to the default policy rules, now + * point to the new policy rules, and remove the securityfs policy file. + */ +static int ima_release_policy(struct inode *inode, struct file *file) +{ + if (!valid_policy) { + ima_delete_rules(); + return 0; + } + ima_update_policy(); + securityfs_remove(ima_policy); + ima_policy = NULL; + return 0; +} + +static struct file_operations ima_measure_policy_ops = { + .write = ima_write_policy, + .release = ima_release_policy +}; int ima_fs_init(void) { @@ -276,13 +333,20 @@ int ima_fs_init(void) if (IS_ERR(violations)) goto out; - return 0; + ima_policy = securityfs_create_file("policy", + S_IRUSR | S_IRGRP | S_IWUSR, + ima_dir, NULL, + &ima_measure_policy_ops); + if (IS_ERR(ima_policy)) + goto out; + return 0; out: securityfs_remove(runtime_measurements_count); securityfs_remove(ascii_runtime_measurements); securityfs_remove(binary_runtime_measurements); securityfs_remove(ima_dir); + securityfs_remove(ima_policy); return -1; } @@ -293,4 +357,5 @@ void __exit ima_fs_cleanup(void) securityfs_remove(ascii_runtime_measurements); securityfs_remove(binary_runtime_measurements); securityfs_remove(ima_dir); + securityfs_remove(ima_policy); } diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 7c3d1ffb147..bd453603e2c 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "ima.h" @@ -24,7 +25,12 @@ #define IMA_FSMAGIC 0x0004 #define IMA_UID 0x0008 -enum ima_action { DONT_MEASURE, MEASURE }; +enum ima_action { UNKNOWN = -1, DONT_MEASURE = 0, MEASURE }; + +#define MAX_LSM_RULES 6 +enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE, + LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE +}; struct ima_measure_rule_entry { struct list_head list; @@ -34,8 +40,15 @@ struct ima_measure_rule_entry { int mask; unsigned long fsmagic; uid_t uid; + struct { + void *rule; /* LSM file metadata specific */ + int type; /* audit type */ + } lsm[MAX_LSM_RULES]; }; +/* Without LSM specific knowledge, the default policy can only be + * written in terms of .action, .func, .mask, .fsmagic, and .uid + */ static struct ima_measure_rule_entry default_rules[] = { {.action = DONT_MEASURE,.fsmagic = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC}, @@ -54,8 +67,11 @@ static struct ima_measure_rule_entry default_rules[] = { }; static LIST_HEAD(measure_default_rules); +static LIST_HEAD(measure_policy_rules); static struct list_head *ima_measure; +static DEFINE_MUTEX(ima_measure_mutex); + /** * ima_match_rules - determine whether an inode matches the measure rule. * @rule: a pointer to a rule @@ -69,6 +85,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule, struct inode *inode, enum ima_hooks func, int mask) { struct task_struct *tsk = current; + int i; if ((rule->flags & IMA_FUNC) && rule->func != func) return false; @@ -79,6 +96,39 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule, return false; if ((rule->flags & IMA_UID) && rule->uid != tsk->cred->uid) return false; + for (i = 0; i < MAX_LSM_RULES; i++) { + int rc; + u32 osid, sid; + + if (!rule->lsm[i].rule) + continue; + + switch (i) { + case LSM_OBJ_USER: + case LSM_OBJ_ROLE: + case LSM_OBJ_TYPE: + security_inode_getsecid(inode, &osid); + rc = security_filter_rule_match(osid, + rule->lsm[i].type, + AUDIT_EQUAL, + rule->lsm[i].rule, + NULL); + break; + case LSM_SUBJ_USER: + case LSM_SUBJ_ROLE: + case LSM_SUBJ_TYPE: + security_task_getsecid(tsk, &sid); + rc = security_filter_rule_match(sid, + rule->lsm[i].type, + AUDIT_EQUAL, + rule->lsm[i].rule, + NULL); + default: + break; + } + if (!rc) + return false; + } return true; } @@ -112,9 +162,8 @@ int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask) /** * ima_init_policy - initialize the default measure rules. * - * (Could use the default_rules directly, but in policy patch * ima_measure points to either the measure_default_rules or the - * the new measure_policy_rules.) + * the new measure_policy_rules. */ void ima_init_policy(void) { @@ -124,3 +173,241 @@ void ima_init_policy(void) list_add_tail(&default_rules[i].list, &measure_default_rules); ima_measure = &measure_default_rules; } + +/** + * ima_update_policy - update default_rules with new measure rules + * + * Called on file .release to update the default rules with a complete new + * policy. Once updated, the policy is locked, no additional rules can be + * added to the policy. + */ +void ima_update_policy(void) +{ + const char *op = "policy_update"; + const char *cause = "already exists"; + int result = 1; + int audit_info = 0; + + if (ima_measure == &measure_default_rules) { + ima_measure = &measure_policy_rules; + cause = "complete"; + result = 0; + } + integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, + NULL, op, cause, result, audit_info); +} + +enum { + Opt_err = -1, + Opt_measure = 1, Opt_dont_measure, + Opt_obj_user, Opt_obj_role, Opt_obj_type, + Opt_subj_user, Opt_subj_role, Opt_subj_type, + Opt_func, Opt_mask, Opt_fsmagic, Opt_uid +}; + +static match_table_t policy_tokens = { + {Opt_measure, "measure"}, + {Opt_dont_measure, "dont_measure"}, + {Opt_obj_user, "obj_user=%s"}, + {Opt_obj_role, "obj_role=%s"}, + {Opt_obj_type, "obj_type=%s"}, + {Opt_subj_user, "subj_user=%s"}, + {Opt_subj_role, "subj_role=%s"}, + {Opt_subj_type, "subj_type=%s"}, + {Opt_func, "func=%s"}, + {Opt_mask, "mask=%s"}, + {Opt_fsmagic, "fsmagic=%s"}, + {Opt_uid, "uid=%s"}, + {Opt_err, NULL} +}; + +static int ima_lsm_rule_init(struct ima_measure_rule_entry *entry, + char *args, int lsm_rule, int audit_type) +{ + int result; + + entry->lsm[lsm_rule].type = audit_type; + result = security_filter_rule_init(entry->lsm[lsm_rule].type, + AUDIT_EQUAL, args, + &entry->lsm[lsm_rule].rule); + return result; +} + +static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) +{ + struct audit_buffer *ab; + char *p; + int result = 0; + + ab = audit_log_start(current->audit_context, GFP_KERNEL, + AUDIT_INTEGRITY_STATUS); + + entry->action = -1; + while ((p = strsep(&rule, " \n")) != NULL) { + substring_t args[MAX_OPT_ARGS]; + int token; + unsigned long lnum; + + if (result < 0) + break; + if (!*p) + continue; + token = match_token(p, policy_tokens, args); + switch (token) { + case Opt_measure: + audit_log_format(ab, "%s ", "measure"); + entry->action = MEASURE; + break; + case Opt_dont_measure: + audit_log_format(ab, "%s ", "dont_measure"); + entry->action = DONT_MEASURE; + break; + case Opt_func: + audit_log_format(ab, "func=%s ", args[0].from); + if (strcmp(args[0].from, "PATH_CHECK") == 0) + entry->func = PATH_CHECK; + else if (strcmp(args[0].from, "FILE_MMAP") == 0) + entry->func = FILE_MMAP; + else if (strcmp(args[0].from, "BPRM_CHECK") == 0) + entry->func = BPRM_CHECK; + else + result = -EINVAL; + if (!result) + entry->flags |= IMA_FUNC; + break; + case Opt_mask: + audit_log_format(ab, "mask=%s ", args[0].from); + if ((strcmp(args[0].from, "MAY_EXEC")) == 0) + entry->mask = MAY_EXEC; + else if (strcmp(args[0].from, "MAY_WRITE") == 0) + entry->mask = MAY_WRITE; + else if (strcmp(args[0].from, "MAY_READ") == 0) + entry->mask = MAY_READ; + else if (strcmp(args[0].from, "MAY_APPEND") == 0) + entry->mask = MAY_APPEND; + else + result = -EINVAL; + if (!result) + entry->flags |= IMA_MASK; + break; + case Opt_fsmagic: + audit_log_format(ab, "fsmagic=%s ", args[0].from); + result = strict_strtoul(args[0].from, 16, + &entry->fsmagic); + if (!result) + entry->flags |= IMA_FSMAGIC; + break; + case Opt_uid: + audit_log_format(ab, "uid=%s ", args[0].from); + result = strict_strtoul(args[0].from, 10, &lnum); + if (!result) { + entry->uid = (uid_t) lnum; + if (entry->uid != lnum) + result = -EINVAL; + else + entry->flags |= IMA_UID; + } + break; + case Opt_obj_user: + audit_log_format(ab, "obj_user=%s ", args[0].from); + result = ima_lsm_rule_init(entry, args[0].from, + LSM_OBJ_USER, + AUDIT_OBJ_USER); + break; + case Opt_obj_role: + audit_log_format(ab, "obj_role=%s ", args[0].from); + result = ima_lsm_rule_init(entry, args[0].from, + LSM_OBJ_ROLE, + AUDIT_OBJ_ROLE); + break; + case Opt_obj_type: + audit_log_format(ab, "obj_type=%s ", args[0].from); + result = ima_lsm_rule_init(entry, args[0].from, + LSM_OBJ_TYPE, + AUDIT_OBJ_TYPE); + break; + case Opt_subj_user: + audit_log_format(ab, "subj_user=%s ", args[0].from); + result = ima_lsm_rule_init(entry, args[0].from, + LSM_SUBJ_USER, + AUDIT_SUBJ_USER); + break; + case Opt_subj_role: + audit_log_format(ab, "subj_role=%s ", args[0].from); + result = ima_lsm_rule_init(entry, args[0].from, + LSM_SUBJ_ROLE, + AUDIT_SUBJ_ROLE); + break; + case Opt_subj_type: + audit_log_format(ab, "subj_type=%s ", args[0].from); + result = ima_lsm_rule_init(entry, args[0].from, + LSM_SUBJ_TYPE, + AUDIT_SUBJ_TYPE); + break; + case Opt_err: + printk(KERN_INFO "%s: unknown token: %s\n", + __FUNCTION__, p); + break; + } + } + if (entry->action == UNKNOWN) + result = -EINVAL; + + audit_log_format(ab, "res=%d", result); + audit_log_end(ab); + return result; +} + +/** + * ima_parse_add_rule - add a rule to measure_policy_rules + * @rule - ima measurement policy rule + * + * Uses a mutex to protect the policy list from multiple concurrent writers. + * Returns 0 on success, an error code on failure. + */ +int ima_parse_add_rule(char *rule) +{ + const char *op = "add_rule"; + struct ima_measure_rule_entry *entry; + int result = 0; + int audit_info = 0; + + /* Prevent installed policy from changing */ + if (ima_measure != &measure_default_rules) { + integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, + NULL, op, "already exists", + -EACCES, audit_info); + return -EACCES; + } + + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) { + integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, + NULL, op, "-ENOMEM", -ENOMEM, audit_info); + return -ENOMEM; + } + + INIT_LIST_HEAD(&entry->list); + + result = ima_parse_rule(rule, entry); + if (!result) { + mutex_lock(&ima_measure_mutex); + list_add_tail(&entry->list, &measure_policy_rules); + mutex_unlock(&ima_measure_mutex); + } else + kfree(entry); + return result; +} + +/* ima_delete_rules called to cleanup invalid policy */ +void ima_delete_rules() +{ + struct ima_measure_rule_entry *entry, *tmp; + + mutex_lock(&ima_measure_mutex); + list_for_each_entry_safe(entry, tmp, &measure_policy_rules, list) { + list_del(&entry->list); + kfree(entry); + } + mutex_unlock(&ima_measure_mutex); +} -- GitLab From f4bd857bc8ed997c25ec06b56ef8064aafa6d4f3 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Wed, 4 Feb 2009 09:07:01 -0500 Subject: [PATCH 1220/4982] integrity: IMA policy open Sequentialize access to the policy file - permit multiple attempts to replace default policy with a valid policy Signed-off-by: Mimi Zohar Acked-by: Serge Hallyn Signed-off-by: James Morris --- security/integrity/ima/ima_fs.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 95ef1caa64b..573780c76f1 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -277,16 +277,30 @@ static struct dentry *runtime_measurements_count; static struct dentry *violations; static struct dentry *ima_policy; +static atomic_t policy_opencount = ATOMIC_INIT(1); +/* + * ima_open_policy: sequentialize access to the policy file + */ +int ima_open_policy(struct inode * inode, struct file * filp) +{ + if (atomic_dec_and_test(&policy_opencount)) + return 0; + return -EBUSY; +} + /* * ima_release_policy - start using the new measure policy rules. * * Initially, ima_measure points to the default policy rules, now - * point to the new policy rules, and remove the securityfs policy file. + * point to the new policy rules, and remove the securityfs policy file, + * assuming a valid policy. */ static int ima_release_policy(struct inode *inode, struct file *file) { if (!valid_policy) { ima_delete_rules(); + valid_policy = 1; + atomic_set(&policy_opencount, 1); return 0; } ima_update_policy(); @@ -296,6 +310,7 @@ static int ima_release_policy(struct inode *inode, struct file *file) } static struct file_operations ima_measure_policy_ops = { + .open = ima_open_policy, .write = ima_write_policy, .release = ima_release_policy }; -- GitLab From 1df9f0a73178718969ae47d813b8e7aab2cf073c Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Wed, 4 Feb 2009 09:07:02 -0500 Subject: [PATCH 1221/4982] Integrity: IMA file free imbalance The number of calls to ima_path_check()/ima_file_free() should be balanced. An extra call to fput(), indicates the file could have been accessed without first being measured. Although f_count is incremented/decremented in places other than fget/fput, like fget_light/fput_light and get_file, the current task must already hold a file refcnt. The call to __fput() is delayed until the refcnt becomes 0, resulting in ima_file_free() flagging any changes. - add hook to increment opencount for IPC shared memory(SYSV), shmat files, and /dev/zero - moved NULL iint test in opencount_get() Signed-off-by: Mimi Zohar Acked-by: Serge Hallyn Signed-off-by: James Morris --- include/linux/ima.h | 6 +++++ ipc/shm.c | 3 +++ mm/shmem.c | 2 ++ security/integrity/ima/ima.h | 2 ++ security/integrity/ima/ima_iint.c | 17 +++++++++++++ security/integrity/ima/ima_main.c | 42 +++++++++++++++++++++++++++++++ 6 files changed, 72 insertions(+) diff --git a/include/linux/ima.h b/include/linux/ima.h index dcc3664feee..6db30a328d9 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -19,6 +19,7 @@ extern void ima_inode_free(struct inode *inode); extern int ima_path_check(struct path *path, int mask); extern void ima_file_free(struct file *file); extern int ima_file_mmap(struct file *file, unsigned long prot); +extern void ima_shm_check(struct file *file); #else static inline int ima_bprm_check(struct linux_binprm *bprm) @@ -50,5 +51,10 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot) { return 0; } + +static inline void ima_shm_check(struct file *file) +{ + return; +} #endif /* CONFIG_IMA_H */ #endif /* _LINUX_IMA_H */ diff --git a/ipc/shm.c b/ipc/shm.c index 38a055758a9..d39bd7637b1 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -39,6 +39,7 @@ #include #include #include +#include #include @@ -381,6 +382,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) error = PTR_ERR(file); if (IS_ERR(file)) goto no_file; + ima_shm_check(file); id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni); if (id < 0) { @@ -888,6 +890,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) file = alloc_file(path.mnt, path.dentry, f_mode, &shm_file_operations); if (!file) goto out_free; + ima_shm_check(file); file->private_data = sfd; file->f_mapping = shp->shm_file->f_mapping; diff --git a/mm/shmem.c b/mm/shmem.c index f1b0d4871f3..dd5588f5d93 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -2600,6 +2601,7 @@ int shmem_zero_setup(struct vm_area_struct *vma) if (IS_ERR(file)) return PTR_ERR(file); + ima_shm_check(file); if (vma->vm_file) fput(vma->vm_file); vma->vm_file = file; diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 42706b55492..e3c16a21a38 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -97,6 +97,7 @@ static inline unsigned long ima_hash_key(u8 *digest) /* iint cache flags */ #define IMA_MEASURED 1 +#define IMA_IINT_DUMP_STACK 512 /* integrity data associated with an inode */ struct ima_iint_cache { @@ -106,6 +107,7 @@ struct ima_iint_cache { struct mutex mutex; /* protects: version, flags, digest */ long readcount; /* measured files readcount */ long writecount; /* measured files writecount */ + long opencount; /* opens reference count */ struct kref refcount; /* ima_iint_cache reference count */ struct rcu_head rcu; }; diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c index 750db3c993a..1f035e8d29c 100644 --- a/security/integrity/ima/ima_iint.c +++ b/security/integrity/ima/ima_iint.c @@ -126,6 +126,7 @@ struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode) return iint; } +EXPORT_SYMBOL_GPL(ima_iint_find_insert_get); /* iint_free - called when the iint refcount goes to zero */ void iint_free(struct kref *kref) @@ -134,6 +135,21 @@ void iint_free(struct kref *kref) refcount); iint->version = 0; iint->flags = 0UL; + if (iint->readcount != 0) { + printk(KERN_INFO "%s: readcount: %ld\n", __FUNCTION__, + iint->readcount); + iint->readcount = 0; + } + if (iint->writecount != 0) { + printk(KERN_INFO "%s: writecount: %ld\n", __FUNCTION__, + iint->writecount); + iint->writecount = 0; + } + if (iint->opencount != 0) { + printk(KERN_INFO "%s: opencount: %ld\n", __FUNCTION__, + iint->opencount); + iint->opencount = 0; + } kref_set(&iint->refcount, 1); kmem_cache_free(iint_cache, iint); } @@ -174,6 +190,7 @@ static void init_once(void *foo) mutex_init(&iint->mutex); iint->readcount = 0; iint->writecount = 0; + iint->opencount = 0; kref_set(&iint->refcount, 1); } diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 871e356e8d6..f4e7266f5ae 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -66,6 +66,19 @@ void ima_file_free(struct file *file) return; mutex_lock(&iint->mutex); + if (iint->opencount <= 0) { + printk(KERN_INFO + "%s: %s open/free imbalance (r:%ld w:%ld o:%ld f:%ld)\n", + __FUNCTION__, file->f_dentry->d_name.name, + iint->readcount, iint->writecount, + iint->opencount, atomic_long_read(&file->f_count)); + if (!(iint->flags & IMA_IINT_DUMP_STACK)) { + dump_stack(); + iint->flags |= IMA_IINT_DUMP_STACK; + } + } + iint->opencount--; + if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) iint->readcount--; @@ -119,6 +132,7 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file, pr_info("%s dentry_open failed\n", filename); return rc; } + iint->opencount++; iint->readcount++; rc = ima_collect_measurement(iint, file); @@ -159,6 +173,7 @@ int ima_path_check(struct path *path, int mask) return 0; mutex_lock(&iint->mutex); + iint->opencount++; if ((mask & MAY_WRITE) || (mask == 0)) iint->writecount++; else if (mask & (MAY_READ | MAY_EXEC)) @@ -219,6 +234,21 @@ out: return rc; } +static void opencount_get(struct file *file) +{ + struct inode *inode = file->f_dentry->d_inode; + struct ima_iint_cache *iint; + + if (!ima_initialized || !S_ISREG(inode->i_mode)) + return; + iint = ima_iint_find_insert_get(inode); + if (!iint) + return; + mutex_lock(&iint->mutex); + iint->opencount++; + mutex_unlock(&iint->mutex); +} + /** * ima_file_mmap - based on policy, collect/store measurement. * @file: pointer to the file to be measured (May be NULL) @@ -242,6 +272,18 @@ int ima_file_mmap(struct file *file, unsigned long prot) return 0; } +/* + * ima_shm_check - IPC shm and shmat create/fput a file + * + * Maintain the opencount for these files to prevent unnecessary + * imbalance messages. + */ +void ima_shm_check(struct file *file) +{ + opencount_get(file); + return; +} + /** * ima_bprm_check - based on policy, collect/store measurement. * @bprm: contains the linux_binprm structure -- GitLab From aa7168f47d912459a99a01c93714f447b44bfa72 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Wed, 4 Feb 2009 09:07:03 -0500 Subject: [PATCH 1222/4982] Integrity: IMA update maintainers Signed-off-by: Mimi Zohar Signed-off-by: James Morris --- MAINTAINERS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 6bd7d47ab9d..12fc2805ab4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2175,6 +2175,11 @@ M: stefanr@s5r6.in-berlin.de L: linux1394-devel@lists.sourceforge.net S: Maintained +INTEGRITY MEASUREMENT ARCHITECTURE (IMA) +P: Mimi Zohar +M: zohar@us.ibm.com +S: Supported + IMS TWINTURBO FRAMEBUFFER DRIVER L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) S: Orphan -- GitLab From 64c61d80a6e4c935a09ac5ff1d952967ca1268f8 Mon Sep 17 00:00:00 2001 From: James Morris Date: Thu, 5 Feb 2009 09:28:26 +1100 Subject: [PATCH 1223/4982] IMA: fix ima_delete_rules() definition Fix ima_delete_rules() definition so sparse doesn't complain. Signed-off-by: James Morris --- security/integrity/ima/ima_policy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index bd453603e2c..23810e0bfc6 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -400,7 +400,7 @@ int ima_parse_add_rule(char *rule) } /* ima_delete_rules called to cleanup invalid policy */ -void ima_delete_rules() +void ima_delete_rules(void) { struct ima_measure_rule_entry *entry, *tmp; -- GitLab From 8920d5ad6ba74ae8ab020e90cc4d976980e68701 Mon Sep 17 00:00:00 2001 From: Rajiv Andrade Date: Thu, 5 Feb 2009 13:06:30 -0200 Subject: [PATCH 1224/4982] TPM: integrity fix Fix to function which is called by IMA, now tpm_chip_find_get() considers the case in which the machine doesn't have a TPM or, if it has, its TPM isn't enabled. Signed-off-by: Mimi Zohar Signed-off-by: Rajiv Andrade Acked-by: Serge Hallyn Signed-off-by: James Morris --- drivers/char/tpm/tpm.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 62a5682578c..ccdd828adce 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -666,18 +666,20 @@ EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated); */ static struct tpm_chip *tpm_chip_find_get(int chip_num) { - struct tpm_chip *pos; + struct tpm_chip *pos, *chip = NULL; rcu_read_lock(); list_for_each_entry_rcu(pos, &tpm_chip_list, list) { if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num) continue; - if (try_module_get(pos->dev->driver->owner)) + if (try_module_get(pos->dev->driver->owner)) { + chip = pos; break; + } } rcu_read_unlock(); - return pos; + return chip; } #define TPM_ORDINAL_PCRREAD cpu_to_be32(21) -- GitLab From 33dccbb050bbe35b88ca8cf1228dcf3e4d4b3554 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 5 Feb 2009 21:25:32 -0800 Subject: [PATCH 1225/4982] tun: Limit amount of queued packets per device Unlike a normal socket path, the tuntap device send path does not have any accounting. This means that the user-space sender may be able to pin down arbitrary amounts of kernel memory by continuing to send data to an end-point that is congested. Even when this isn't an issue because of limited queueing at most end points, this can also be a problem because its only response to congestion is packet loss. That is, when those local queues at the end-point fills up, the tuntap device will start wasting system time because it will continue to send data there which simply gets dropped straight away. Of course one could argue that everybody should do congestion control end-to-end, unfortunately there are people in this world still hooked on UDP, and they don't appear to be going away anywhere fast. In fact, we've always helped them by performing accounting in our UDP code, the sole purpose of which is to provide congestion feedback other than through packet loss. This patch attempts to apply the same bandaid to the tuntap device. It creates a pseudo-socket object which is used to account our packets just as a normal socket does for UDP. Of course things are a little complex because we're actually reinjecting traffic back into the stack rather than out of the stack. The stack complexities however should have been resolved by preceding patches. So this one can simply start using skb_set_owner_w. For now the accounting is essentially disabled by default for backwards compatibility. In particular, we set the cap to INT_MAX. This is so that existing applications don't get confused by the sudden arrival EAGAIN errors. In future we may wish (or be forced to) do this by default. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- drivers/net/tun.c | 167 ++++++++++++++++++++++++++++------------- fs/compat_ioctl.c | 2 + include/linux/if_tun.h | 2 + 3 files changed, 118 insertions(+), 53 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 15d67635bb1..0476549841a 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -64,6 +64,7 @@ #include #include #include +#include #include #include @@ -95,6 +96,8 @@ struct tun_file { wait_queue_head_t read_wait; }; +struct tun_sock; + struct tun_struct { struct tun_file *tfile; unsigned int flags; @@ -107,12 +110,24 @@ struct tun_struct { struct fasync_struct *fasync; struct tap_filter txflt; + struct sock *sk; + struct socket socket; #ifdef TUN_DEBUG int debug; #endif }; +struct tun_sock { + struct sock sk; + struct tun_struct *tun; +}; + +static inline struct tun_sock *tun_sk(struct sock *sk) +{ + return container_of(sk, struct tun_sock, sk); +} + static int tun_attach(struct tun_struct *tun, struct file *file) { struct tun_file *tfile = file->private_data; @@ -461,7 +476,8 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait) { struct tun_file *tfile = file->private_data; struct tun_struct *tun = __tun_get(tfile); - unsigned int mask = POLLOUT | POLLWRNORM; + struct sock *sk = tun->sk; + unsigned int mask = 0; if (!tun) return POLLERR; @@ -473,6 +489,11 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait) if (!skb_queue_empty(&tun->readq)) mask |= POLLIN | POLLRDNORM; + if (sock_writeable(sk) || + (!test_and_set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags) && + sock_writeable(sk))) + mask |= POLLOUT | POLLWRNORM; + if (tun->dev->reg_state != NETREG_REGISTERED) mask = POLLERR; @@ -482,66 +503,35 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait) /* prepad is the amount to reserve at front. len is length after that. * linear is a hint as to how much to copy (usually headers). */ -static struct sk_buff *tun_alloc_skb(size_t prepad, size_t len, size_t linear, - gfp_t gfp) +static inline struct sk_buff *tun_alloc_skb(struct tun_struct *tun, + size_t prepad, size_t len, + size_t linear, int noblock) { + struct sock *sk = tun->sk; struct sk_buff *skb; - unsigned int i; - - skb = alloc_skb(prepad + len, gfp|__GFP_NOWARN); - if (skb) { - skb_reserve(skb, prepad); - skb_put(skb, len); - return skb; - } + int err; /* Under a page? Don't bother with paged skb. */ if (prepad + len < PAGE_SIZE) - return NULL; + linear = len; - /* Start with a normal skb, and add pages. */ - skb = alloc_skb(prepad + linear, gfp); + skb = sock_alloc_send_pskb(sk, prepad + linear, len - linear, noblock, + &err); if (!skb) - return NULL; + return ERR_PTR(err); skb_reserve(skb, prepad); skb_put(skb, linear); - - len -= linear; - - for (i = 0; i < MAX_SKB_FRAGS; i++) { - skb_frag_t *f = &skb_shinfo(skb)->frags[i]; - - f->page = alloc_page(gfp|__GFP_ZERO); - if (!f->page) - break; - - f->page_offset = 0; - f->size = PAGE_SIZE; - - skb->data_len += PAGE_SIZE; - skb->len += PAGE_SIZE; - skb->truesize += PAGE_SIZE; - skb_shinfo(skb)->nr_frags++; - - if (len < PAGE_SIZE) { - len = 0; - break; - } - len -= PAGE_SIZE; - } - - /* Too large, or alloc fail? */ - if (unlikely(len)) { - kfree_skb(skb); - skb = NULL; - } + skb->data_len = len - linear; + skb->len += len - linear; return skb; } /* Get packet from user space buffer */ -static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv, size_t count) +static __inline__ ssize_t tun_get_user(struct tun_struct *tun, + struct iovec *iv, size_t count, + int noblock) { struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) }; struct sk_buff *skb; @@ -573,9 +563,11 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv, return -EINVAL; } - if (!(skb = tun_alloc_skb(align, len, gso.hdr_len, GFP_KERNEL))) { - tun->dev->stats.rx_dropped++; - return -ENOMEM; + skb = tun_alloc_skb(tun, align, len, gso.hdr_len, noblock); + if (IS_ERR(skb)) { + if (PTR_ERR(skb) != -EAGAIN) + tun->dev->stats.rx_dropped++; + return PTR_ERR(skb); } if (skb_copy_datagram_from_iovec(skb, 0, iv, len)) { @@ -661,7 +653,8 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv, static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv, unsigned long count, loff_t pos) { - struct tun_struct *tun = tun_get(iocb->ki_filp); + struct file *file = iocb->ki_filp; + struct tun_struct *tun = file->private_data; ssize_t result; if (!tun) @@ -669,7 +662,8 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv, DBG(KERN_INFO "%s: tun_chr_write %ld\n", tun->dev->name, count); - result = tun_get_user(tun, (struct iovec *) iv, iov_length(iv, count)); + result = tun_get_user(tun, (struct iovec *)iv, iov_length(iv, count), + file->f_flags & O_NONBLOCK); tun_put(tun); return result; @@ -828,11 +822,40 @@ static struct rtnl_link_ops tun_link_ops __read_mostly = { .validate = tun_validate, }; +static void tun_sock_write_space(struct sock *sk) +{ + struct tun_struct *tun; + + if (!sock_writeable(sk)) + return; + + if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + wake_up_interruptible_sync(sk->sk_sleep); + + if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags)) + return; + + tun = container_of(sk, struct tun_sock, sk)->tun; + kill_fasync(&tun->fasync, SIGIO, POLL_OUT); +} + +static void tun_sock_destruct(struct sock *sk) +{ + dev_put(container_of(sk, struct tun_sock, sk)->tun->dev); +} + +static struct proto tun_proto = { + .name = "tun", + .owner = THIS_MODULE, + .obj_size = sizeof(struct tun_sock), +}; static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) { + struct sock *sk; struct tun_struct *tun; struct net_device *dev; + struct tun_file *tfile = file->private_data; int err; dev = __dev_get_by_name(net, ifr->ifr_name); @@ -885,14 +908,31 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) tun->flags = flags; tun->txflt.count = 0; + err = -ENOMEM; + sk = sk_alloc(net, AF_UNSPEC, GFP_KERNEL, &tun_proto); + if (!sk) + goto err_free_dev; + + /* This ref count is for tun->sk. */ + dev_hold(dev); + sock_init_data(&tun->socket, sk); + sk->sk_write_space = tun_sock_write_space; + sk->sk_destruct = tun_sock_destruct; + sk->sk_sndbuf = INT_MAX; + sk->sk_sleep = &tfile->read_wait; + + tun->sk = sk; + container_of(sk, struct tun_sock, sk)->tun = tun; + tun_net_init(dev); if (strchr(dev->name, '%')) { err = dev_alloc_name(dev, dev->name); if (err < 0) - goto err_free_dev; + goto err_free_sk; } + err = -EINVAL; err = register_netdevice(tun->dev); if (err < 0) goto err_free_dev; @@ -928,6 +968,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) strcpy(ifr->ifr_name, tun->dev->name); return 0; + err_free_sk: + sock_put(sk); err_free_dev: free_netdev(dev); failed: @@ -1012,6 +1054,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, struct tun_struct *tun; void __user* argp = (void __user*)arg; struct ifreq ifr; + int sndbuf; int ret; if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) @@ -1151,6 +1194,22 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr); rtnl_unlock(); break; + + case TUNGETSNDBUF: + sndbuf = tun->sk->sk_sndbuf; + if (copy_to_user(argp, &sndbuf, sizeof(sndbuf))) + ret = -EFAULT; + break; + + case TUNSETSNDBUF: + if (copy_from_user(&sndbuf, argp, sizeof(sndbuf))) { + ret = -EFAULT; + break; + } + + tun->sk->sk_sndbuf = sndbuf; + break; + default: ret = -EINVAL; break; @@ -1218,8 +1277,10 @@ static int tun_chr_close(struct inode *inode, struct file *file) __tun_detach(tun); /* If desireable, unregister the netdevice. */ - if (!(tun->flags & TUN_PERSIST)) + if (!(tun->flags & TUN_PERSIST)) { + sock_put(tun->sk); unregister_netdevice(tun->dev); + } rtnl_unlock(); } diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index c8f8d5904f5..c03c10d7fb6 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -1988,6 +1988,8 @@ COMPATIBLE_IOCTL(TUNSETGROUP) COMPATIBLE_IOCTL(TUNGETFEATURES) COMPATIBLE_IOCTL(TUNSETOFFLOAD) COMPATIBLE_IOCTL(TUNSETTXFILTER) +COMPATIBLE_IOCTL(TUNGETSNDBUF) +COMPATIBLE_IOCTL(TUNSETSNDBUF) /* Big V */ COMPATIBLE_IOCTL(VT_SETMODE) COMPATIBLE_IOCTL(VT_GETMODE) diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h index 8529f57ba26..049d6c9428d 100644 --- a/include/linux/if_tun.h +++ b/include/linux/if_tun.h @@ -46,6 +46,8 @@ #define TUNSETOFFLOAD _IOW('T', 208, unsigned int) #define TUNSETTXFILTER _IOW('T', 209, unsigned int) #define TUNGETIFF _IOR('T', 210, unsigned int) +#define TUNGETSNDBUF _IOR('T', 211, int) +#define TUNSETSNDBUF _IOW('T', 212, int) /* TUNSETIFF ifr flags */ #define IFF_TUN 0x0001 -- GitLab From fe2918b098cdbf55b69ba8762bd3de0ae64f33ff Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Thu, 5 Feb 2009 21:26:19 -0800 Subject: [PATCH 1226/4982] net: fix some trailing whitespaces Signed-off-by: Graf Yang Signed-off-by: Bryan Wu Signed-off-by: David S. Miller --- include/linux/if_ether.h | 8 ++++---- include/linux/netdevice.h | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index 7f3c735f422..0216e1bdbc5 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -17,7 +17,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ - + #ifndef _LINUX_IF_ETHER_H #define _LINUX_IF_ETHER_H @@ -25,7 +25,7 @@ /* * IEEE 802.3 Ethernet magic constants. The frame sizes omit the preamble - * and FCS/CRC (frame check sequence). + * and FCS/CRC (frame check sequence). */ #define ETH_ALEN 6 /* Octets in one ethernet addr */ @@ -83,7 +83,7 @@ /* * Non DIX types. Won't clash for 1500 types. */ - + #define ETH_P_802_3 0x0001 /* Dummy type for 802.3 frames */ #define ETH_P_AX25 0x0002 /* Dummy protocol id for AX.25 */ #define ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */ @@ -109,7 +109,7 @@ /* * This is an Ethernet frame header. */ - + struct ethhdr { unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ unsigned char h_source[ETH_ALEN]; /* source ether addr */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 7a5057fbb7c..864519e585f 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -96,7 +96,7 @@ struct wireless_dev; * Compute the worst case header length according to the protocols * used. */ - + #if defined(CONFIG_WLAN_80211) || defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) # if defined(CONFIG_MAC80211_MESH) # define LL_MAX_HEADER 128 @@ -124,7 +124,7 @@ struct wireless_dev; * Network device statistics. Akin to the 2.0 ether stats but * with byte counters. */ - + struct net_device_stats { unsigned long rx_packets; /* total packets received */ @@ -285,7 +285,7 @@ enum netdev_state_t /* * This structure holds at boot time configured netdevice settings. They - * are then used in the device probing. + * are then used in the device probing. */ struct netdev_boot_setup { char name[IFNAMSIZ]; @@ -740,7 +740,7 @@ struct net_device void *dsa_ptr; /* dsa specific data */ #endif void *atalk_ptr; /* AppleTalk link */ - void *ip_ptr; /* IPv4 specific data */ + void *ip_ptr; /* IPv4 specific data */ void *dn_ptr; /* DECnet specific data */ void *ip6_ptr; /* IPv6 specific data */ void *ec_ptr; /* Econet specific data */ @@ -753,7 +753,7 @@ struct net_device */ unsigned long last_rx; /* Time of last Rx */ /* Interface address info used in eth_type_trans() */ - unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address, (before bcast + unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address, (before bcast because most packets are unicast) */ unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */ -- GitLab From 56035022d86fff45299288cb372a42f752ba23fa Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 5 Feb 2009 21:26:52 -0800 Subject: [PATCH 1227/4982] gro: Fix frag_list merging on imprecisely split packets The previous fix ad0f9904444de1309dedd2b9e365cae8af77d9b1 (gro: Fix handling of imprecisely split packets) only fixed the case of frags merging, frag_list merging in the same circumstances were still broken. In particular, the packet headers end up in the data stream. This patch fixes this plus another issue where an imprecisely split packet header may be read incorrectly (this is mostly harmless since it'll simply cause the packet to not match and be rejected for GRO). Thanks to Emil Tantilov and Jeff Kirsher for helping to track this down. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/core/dev.c | 3 ++- net/core/skbuff.c | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index 3337cf98f23..247f1614a79 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2391,7 +2391,8 @@ void *skb_gro_header(struct sk_buff *skb, unsigned int hlen) return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL; return page_address(skb_shinfo(skb)->frags[0].page) + - skb_shinfo(skb)->frags[0].page_offset + offset; + skb_shinfo(skb)->frags[0].page_offset + + offset - skb_headlen(skb); } EXPORT_SYMBOL(skb_gro_header); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index e55d1ef5690..67f2a2f8582 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2678,6 +2678,17 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) p = nskb; merge: + if (skb_gro_offset(skb) > skb_headlen(skb)) { + skb_shinfo(skb)->frags[0].page_offset += + skb_gro_offset(skb) - skb_headlen(skb); + skb_shinfo(skb)->frags[0].size -= + skb_gro_offset(skb) - skb_headlen(skb); + skb_gro_reset_offset(skb); + skb_gro_pull(skb, skb_headlen(skb)); + } + + __skb_pull(skb, skb_gro_offset(skb)); + p->prev->next = skb; p->prev = skb; skb_header_release(skb); -- GitLab From b25c9da19889e33bb4ee2dff369fc46caa4543b0 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Fri, 6 Feb 2009 15:02:27 +0800 Subject: [PATCH 1228/4982] ALSA: enable concurrent digital outputs for ALC1200 Add the SPDIF pin as slave digital out to enable concurrent HDMI/SPDIF outputs for ASUS M3A-H/HDMI with ALC1200 codec. Tested-by: Thomas Schneider Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_local.h | 1 + sound/pci/hda/patch_realtek.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index ec687b206c0..4086491ed33 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -229,6 +229,7 @@ struct hda_multi_out { hda_nid_t hp_nid; /* optional DAC for HP, 0 when not exists */ hda_nid_t extra_out_nid[3]; /* optional DACs, 0 when not exists */ hda_nid_t dig_out_nid; /* digital out audio widget */ + hda_nid_t *slave_dig_outs; int max_channels; /* currently supported analog channels */ int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ int no_share_stream; /* don't share a stream with multiple pins */ diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index d2812ab729c..5194a58fafa 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -349,6 +349,7 @@ struct alc_config_preset { hda_nid_t *dac_nids; hda_nid_t dig_out_nid; /* optional */ hda_nid_t hp_nid; /* optional */ + hda_nid_t *slave_dig_outs; unsigned int num_adc_nids; hda_nid_t *adc_nids; hda_nid_t *capsrc_nids; @@ -824,6 +825,7 @@ static void setup_preset(struct alc_spec *spec, spec->multiout.num_dacs = preset->num_dacs; spec->multiout.dac_nids = preset->dac_nids; spec->multiout.dig_out_nid = preset->dig_out_nid; + spec->multiout.slave_dig_outs = preset->slave_dig_outs; spec->multiout.hp_nid = preset->hp_nid; spec->num_mux_defs = preset->num_mux_defs; @@ -3107,6 +3109,7 @@ static int alc_build_pcms(struct hda_codec *codec) /* SPDIF for stream index #1 */ if (spec->multiout.dig_out_nid || spec->dig_in_nid) { codec->num_pcms = 2; + codec->slave_dig_outs = spec->multiout.slave_dig_outs; info = spec->pcm_rec + 1; info->name = spec->stream_name_digital; if (spec->dig_out_type) @@ -8603,6 +8606,10 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { {} }; +static hda_nid_t alc1200_slave_dig_outs[] = { + ALC883_DIGOUT_NID, 0, +}; + static struct alc_config_preset alc883_presets[] = { [ALC883_3ST_2ch_DIG] = { .mixers = { alc883_3ST_2ch_mixer }, @@ -8943,6 +8950,7 @@ static struct alc_config_preset alc883_presets[] = { .dac_nids = alc883_dac_nids, .dig_out_nid = ALC1200_DIGOUT_NID, .dig_in_nid = ALC883_DIGIN_NID, + .slave_dig_outs = alc1200_slave_dig_outs, .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), .channel_mode = alc883_sixstack_modes, .input_mux = &alc883_capture_source, -- GitLab From bc97114d3f998a040876695a9b2b5be0b1a5320b Mon Sep 17 00:00:00 2001 From: Peter P Waskiewicz Jr Date: Thu, 5 Feb 2009 23:53:59 -0800 Subject: [PATCH 1229/4982] ixgbe: Refactor set_num_queues() and cache_ring_register() The current code to determine the number of queues the device will want on driver initialization is ugly and difficult to maintain. It also doesn't allow for easy expansion for future features or future hardware. This patch refactors these routines, and make them easier to deal with. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 222 ++++++++++++++++++--------------- 1 file changed, 118 insertions(+), 104 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index ed8d14163c1..d396c6e01fb 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2314,68 +2314,61 @@ static void ixgbe_reset_task(struct work_struct *work) ixgbe_reinit_locked(adapter); } -static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter) +#ifdef CONFIG_IXGBE_DCB +static inline bool ixgbe_set_dcb_queues(struct ixgbe_adapter *adapter) { - int nrq = 1, ntq = 1; - int feature_mask = 0, rss_i, rss_m; - int dcb_i, dcb_m; + bool ret = false; - /* Number of supported queues */ - switch (adapter->hw.mac.type) { - case ixgbe_mac_82598EB: - dcb_i = adapter->ring_feature[RING_F_DCB].indices; - dcb_m = 0; - rss_i = adapter->ring_feature[RING_F_RSS].indices; - rss_m = 0; - feature_mask |= IXGBE_FLAG_RSS_ENABLED; - feature_mask |= IXGBE_FLAG_DCB_ENABLED; - - switch (adapter->flags & feature_mask) { - case (IXGBE_FLAG_RSS_ENABLED | IXGBE_FLAG_DCB_ENABLED): - dcb_m = 0x7 << 3; - rss_i = min(8, rss_i); - rss_m = 0x7; - nrq = dcb_i * rss_i; - ntq = min(MAX_TX_QUEUES, dcb_i * rss_i); - break; - case (IXGBE_FLAG_DCB_ENABLED): - dcb_m = 0x7 << 3; - nrq = dcb_i; - ntq = dcb_i; - break; - case (IXGBE_FLAG_RSS_ENABLED): - rss_m = 0xF; - nrq = rss_i; - ntq = rss_i; - break; - case 0: - default: - dcb_i = 0; - dcb_m = 0; - rss_i = 0; - rss_m = 0; - nrq = 1; - ntq = 1; - break; - } + if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { + adapter->ring_feature[RING_F_DCB].mask = 0x7 << 3; + adapter->num_rx_queues = + adapter->ring_feature[RING_F_DCB].indices; + adapter->num_tx_queues = + adapter->ring_feature[RING_F_DCB].indices; + ret = true; + } else { + adapter->ring_feature[RING_F_DCB].mask = 0; + adapter->ring_feature[RING_F_DCB].indices = 0; + ret = false; + } - /* Sanity check, we should never have zero queues */ - nrq = (nrq ?:1); - ntq = (ntq ?:1); + return ret; +} +#endif - adapter->ring_feature[RING_F_DCB].indices = dcb_i; - adapter->ring_feature[RING_F_DCB].mask = dcb_m; - adapter->ring_feature[RING_F_RSS].indices = rss_i; - adapter->ring_feature[RING_F_RSS].mask = rss_m; - break; - default: - nrq = 1; - ntq = 1; - break; +static inline bool ixgbe_set_rss_queues(struct ixgbe_adapter *adapter) +{ + bool ret = false; + + if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { + adapter->ring_feature[RING_F_RSS].mask = 0xF; + adapter->num_rx_queues = + adapter->ring_feature[RING_F_RSS].indices; + adapter->num_tx_queues = + adapter->ring_feature[RING_F_RSS].indices; + ret = true; + } else { + adapter->ring_feature[RING_F_RSS].mask = 0; + adapter->ring_feature[RING_F_RSS].indices = 0; + ret = false; } - adapter->num_rx_queues = nrq; - adapter->num_tx_queues = ntq; + return ret; +} + +static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter) +{ + /* Start with base case */ + adapter->num_rx_queues = 1; + adapter->num_tx_queues = 1; + +#ifdef CONFIG_IXGBE_DCB + if (ixgbe_set_dcb_queues(adapter)) + return; + +#endif + if (ixgbe_set_rss_queues(adapter)) + return; } static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter, @@ -2432,66 +2425,87 @@ static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter, } /** - * ixgbe_cache_ring_register - Descriptor ring to register mapping + * ixgbe_cache_ring_rss - Descriptor ring to register mapping for RSS * @adapter: board private structure to initialize * - * Once we know the feature-set enabled for the device, we'll cache - * the register offset the descriptor ring is assigned to. + * Cache the descriptor ring offsets for RSS to the assigned rings. + * **/ -static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter) +static inline bool ixgbe_cache_ring_rss(struct ixgbe_adapter *adapter) { - int feature_mask = 0, rss_i; - int i, txr_idx, rxr_idx; - int dcb_i; + int i; + bool ret = false; - /* Number of supported queues */ - switch (adapter->hw.mac.type) { - case ixgbe_mac_82598EB: - dcb_i = adapter->ring_feature[RING_F_DCB].indices; - rss_i = adapter->ring_feature[RING_F_RSS].indices; - txr_idx = 0; - rxr_idx = 0; - feature_mask |= IXGBE_FLAG_DCB_ENABLED; - feature_mask |= IXGBE_FLAG_RSS_ENABLED; - switch (adapter->flags & feature_mask) { - case (IXGBE_FLAG_RSS_ENABLED | IXGBE_FLAG_DCB_ENABLED): - for (i = 0; i < dcb_i; i++) { - int j; - /* Rx first */ - for (j = 0; j < adapter->num_rx_queues; j++) { - adapter->rx_ring[rxr_idx].reg_idx = - i << 3 | j; - rxr_idx++; - } - /* Tx now */ - for (j = 0; j < adapter->num_tx_queues; j++) { - adapter->tx_ring[txr_idx].reg_idx = - i << 2 | (j >> 1); - if (j & 1) - txr_idx++; - } - } - case (IXGBE_FLAG_DCB_ENABLED): + if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { + for (i = 0; i < adapter->num_rx_queues; i++) + adapter->rx_ring[i].reg_idx = i; + for (i = 0; i < adapter->num_tx_queues; i++) + adapter->tx_ring[i].reg_idx = i; + ret = true; + } else { + ret = false; + } + + return ret; +} + +#ifdef CONFIG_IXGBE_DCB +/** + * ixgbe_cache_ring_dcb - Descriptor ring to register mapping for DCB + * @adapter: board private structure to initialize + * + * Cache the descriptor ring offsets for DCB to the assigned rings. + * + **/ +static inline bool ixgbe_cache_ring_dcb(struct ixgbe_adapter *adapter) +{ + int i; + bool ret = false; + int dcb_i = adapter->ring_feature[RING_F_DCB].indices; + + if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { + if (adapter->hw.mac.type == ixgbe_mac_82598EB) { /* the number of queues is assumed to be symmetric */ for (i = 0; i < dcb_i; i++) { adapter->rx_ring[i].reg_idx = i << 3; adapter->tx_ring[i].reg_idx = i << 2; } - break; - case (IXGBE_FLAG_RSS_ENABLED): - for (i = 0; i < adapter->num_rx_queues; i++) - adapter->rx_ring[i].reg_idx = i; - for (i = 0; i < adapter->num_tx_queues; i++) - adapter->tx_ring[i].reg_idx = i; - break; - case 0: - default: - break; + ret = true; + } else { + ret = false; } - break; - default: - break; + } else { + ret = false; } + + return ret; +} +#endif + +/** + * ixgbe_cache_ring_register - Descriptor ring to register mapping + * @adapter: board private structure to initialize + * + * Once we know the feature-set enabled for the device, we'll cache + * the register offset the descriptor ring is assigned to. + * + * Note, the order the various feature calls is important. It must start with + * the "most" features enabled at the same time, then trickle down to the + * least amount of features turned on at once. + **/ +static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter) +{ + /* start with default case */ + adapter->rx_ring[0].reg_idx = 0; + adapter->tx_ring[0].reg_idx = 0; + +#ifdef CONFIG_IXGBE_DCB + if (ixgbe_cache_ring_dcb(adapter)) + return; + +#endif + if (ixgbe_cache_ring_rss(adapter)) + return; } /** -- GitLab From 3201d3130ee3eb49ed0e905654568f02736afdcb Mon Sep 17 00:00:00 2001 From: Peter P Waskiewicz Jr Date: Thu, 5 Feb 2009 23:54:21 -0800 Subject: [PATCH 1230/4982] ixgbe: Update link setup code to better support autonegotiation of speed The current code has some flaws in it when performing autonegotiation, especially on KX/KX4 links. This patch updates the code to better handle the autonegotiation states on link setup. The patch also removes a redundant link configuration call on driver load, and moves link configuration to the ->open() path. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_82598.c | 114 ++++++++++++------------------- drivers/net/ixgbe/ixgbe_common.c | 3 - drivers/net/ixgbe/ixgbe_main.c | 3 - drivers/net/ixgbe/ixgbe_type.h | 9 +-- 4 files changed, 49 insertions(+), 80 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 8e7315e0a7f..f726a14d1a7 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -146,18 +146,12 @@ static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw, bool *autoneg) { s32 status = 0; - s32 autoc_reg; - autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); - - if (hw->mac.link_settings_loaded) { - autoc_reg &= ~IXGBE_AUTOC_LMS_ATTACH_TYPE; - autoc_reg &= ~IXGBE_AUTOC_LMS_MASK; - autoc_reg |= hw->mac.link_attach_type; - autoc_reg |= hw->mac.link_mode_select; - } - - switch (autoc_reg & IXGBE_AUTOC_LMS_MASK) { + /* + * Determine link capabilities based on the stored value of AUTOC, + * which represents EEPROM defaults. + */ + switch (hw->mac.orig_autoc & IXGBE_AUTOC_LMS_MASK) { case IXGBE_AUTOC_LMS_1G_LINK_NO_AN: *speed = IXGBE_LINK_SPEED_1GB_FULL; *autoneg = false; @@ -176,9 +170,9 @@ static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw, case IXGBE_AUTOC_LMS_KX4_AN: case IXGBE_AUTOC_LMS_KX4_AN_1G_AN: *speed = IXGBE_LINK_SPEED_UNKNOWN; - if (autoc_reg & IXGBE_AUTOC_KX4_SUPP) + if (hw->mac.orig_autoc & IXGBE_AUTOC_KX4_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; - if (autoc_reg & IXGBE_AUTOC_KX_SUPP) + if (hw->mac.orig_autoc & IXGBE_AUTOC_KX_SUPP) *speed |= IXGBE_LINK_SPEED_1GB_FULL; *autoneg = true; break; @@ -390,27 +384,17 @@ static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw) u32 i; s32 status = 0; - autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); - - if (hw->mac.link_settings_loaded) { - autoc_reg &= ~IXGBE_AUTOC_LMS_ATTACH_TYPE; - autoc_reg &= ~IXGBE_AUTOC_LMS_MASK; - autoc_reg |= hw->mac.link_attach_type; - autoc_reg |= hw->mac.link_mode_select; - - IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); - IXGBE_WRITE_FLUSH(hw); - msleep(50); - } - /* Restart link */ + autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); autoc_reg |= IXGBE_AUTOC_AN_RESTART; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); /* Only poll for autoneg to complete if specified to do so */ if (hw->phy.autoneg_wait_to_complete) { - if (hw->mac.link_mode_select == IXGBE_AUTOC_LMS_KX4_AN || - hw->mac.link_mode_select == IXGBE_AUTOC_LMS_KX4_AN_1G_AN) { + if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) == + IXGBE_AUTOC_LMS_KX4_AN || + (autoc_reg & IXGBE_AUTOC_LMS_MASK) == + IXGBE_AUTOC_LMS_KX4_AN_1G_AN) { links_reg = 0; /* Just in case Autoneg time = 0 */ for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) { links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); @@ -534,37 +518,43 @@ out: * Set the link speed in the AUTOC register and restarts link. **/ static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw, - ixgbe_link_speed speed, bool autoneg, - bool autoneg_wait_to_complete) + ixgbe_link_speed speed, bool autoneg, + bool autoneg_wait_to_complete) { - s32 status = 0; + s32 status = 0; + ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN; + u32 curr_autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); + u32 autoc = curr_autoc; + u32 link_mode = autoc & IXGBE_AUTOC_LMS_MASK; - /* If speed is 10G, then check for CX4 or XAUI. */ - if ((speed == IXGBE_LINK_SPEED_10GB_FULL) && - (!(hw->mac.link_attach_type & IXGBE_AUTOC_10G_KX4))) { - hw->mac.link_mode_select = IXGBE_AUTOC_LMS_10G_LINK_NO_AN; - } else if ((speed == IXGBE_LINK_SPEED_1GB_FULL) && (!autoneg)) { - hw->mac.link_mode_select = IXGBE_AUTOC_LMS_1G_LINK_NO_AN; - } else if (autoneg) { - /* BX mode - Autonegotiate 1G */ - if (!(hw->mac.link_attach_type & IXGBE_AUTOC_1G_PMA_PMD)) - hw->mac.link_mode_select = IXGBE_AUTOC_LMS_1G_AN; - else /* KX/KX4 mode */ - hw->mac.link_mode_select = IXGBE_AUTOC_LMS_KX4_AN_1G_AN; - } else { + /* Check to see if speed passed in is supported. */ + ixgbe_get_link_capabilities_82598(hw, &link_capabilities, &autoneg); + speed &= link_capabilities; + + if (speed == IXGBE_LINK_SPEED_UNKNOWN) status = IXGBE_ERR_LINK_SETUP; + + /* Set KX4/KX support according to speed requested */ + else if (link_mode == IXGBE_AUTOC_LMS_KX4_AN || + link_mode == IXGBE_AUTOC_LMS_KX4_AN_1G_AN) { + autoc &= ~IXGBE_AUTOC_KX4_KX_SUPP_MASK; + if (speed & IXGBE_LINK_SPEED_10GB_FULL) + autoc |= IXGBE_AUTOC_KX4_SUPP; + if (speed & IXGBE_LINK_SPEED_1GB_FULL) + autoc |= IXGBE_AUTOC_KX_SUPP; + if (autoc != curr_autoc) + IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc); } if (status == 0) { hw->phy.autoneg_wait_to_complete = autoneg_wait_to_complete; - hw->mac.link_settings_loaded = true; /* * Setup and restart the link based on the new values in * ixgbe_hw This will write the AUTOC register based on the new * stored values */ - ixgbe_setup_mac_link_82598(hw); + status = ixgbe_setup_mac_link_82598(hw); } return status; @@ -587,10 +577,6 @@ static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw) /* Restart autonegotiation on PHY */ status = hw->phy.ops.setup_link(hw); - /* Set MAC to KX/KX4 autoneg, which defaults to Parallel detection */ - hw->mac.link_attach_type = (IXGBE_AUTOC_10G_KX4 | IXGBE_AUTOC_1G_KX); - hw->mac.link_mode_select = IXGBE_AUTOC_LMS_KX4_AN; - /* Set up MAC */ ixgbe_setup_mac_link_82598(hw); @@ -617,10 +603,6 @@ static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw, status = hw->phy.ops.setup_link_speed(hw, speed, autoneg, autoneg_wait_to_complete); - /* Set MAC to KX/KX4 autoneg, which defaults to Parallel detection */ - hw->mac.link_attach_type = (IXGBE_AUTOC_10G_KX4 | IXGBE_AUTOC_1G_KX); - hw->mac.link_mode_select = IXGBE_AUTOC_LMS_KX4_AN; - /* Set up MAC */ ixgbe_setup_mac_link_82598(hw); @@ -720,24 +702,16 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw) IXGBE_WRITE_REG(hw, IXGBE_GHECCR, gheccr); /* - * AUTOC register which stores link settings gets cleared - * and reloaded from EEPROM after reset. We need to restore - * our stored value from init in case SW changed the attach - * type or speed. If this is the first time and link settings - * have not been stored, store default settings from AUTOC. + * Store the original AUTOC value if it has not been + * stored off yet. Otherwise restore the stored original + * AUTOC value since the reset operation sets back to deaults. */ autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); - if (hw->mac.link_settings_loaded) { - autoc &= ~(IXGBE_AUTOC_LMS_ATTACH_TYPE); - autoc &= ~(IXGBE_AUTOC_LMS_MASK); - autoc |= hw->mac.link_attach_type; - autoc |= hw->mac.link_mode_select; - IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc); - } else { - hw->mac.link_attach_type = - (autoc & IXGBE_AUTOC_LMS_ATTACH_TYPE); - hw->mac.link_mode_select = (autoc & IXGBE_AUTOC_LMS_MASK); - hw->mac.link_settings_loaded = true; + if (hw->mac.orig_link_settings_stored == false) { + hw->mac.orig_autoc = autoc; + hw->mac.orig_link_settings_stored = true; + } else if (autoc != hw->mac.orig_autoc) { + IXGBE_WRITE_REG(hw, IXGBE_AUTOC, hw->mac.orig_autoc); } /* Store the permanent mac address */ diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index 05f0e872947..13ad5ba66b6 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -80,9 +80,6 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) /* Clear the VLAN filter table */ hw->mac.ops.clear_vfta(hw); - /* Set up link */ - hw->mac.ops.setup_link(hw); - /* Clear statistics registers */ hw->mac.ops.clear_hw_cntrs(hw); diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index d396c6e01fb..5db82b5fa9b 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2799,9 +2799,6 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE; hw->fc.send_xon = true; - /* select 10G link by default */ - hw->mac.link_mode_select = IXGBE_AUTOC_LMS_10G_LINK_NO_AN; - /* enable itr by default in dynamic mode */ adapter->itr_setting = 1; adapter->eitr_param = 20000; diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index c49ba8a17f1..984b4ed372f 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -721,6 +721,7 @@ #define IXGBE_LED_OFF 0xF /* AUTOC Bit Masks */ +#define IXGBE_AUTOC_KX4_KX_SUPP_MASK 0xC0000000 #define IXGBE_AUTOC_KX4_SUPP 0x80000000 #define IXGBE_AUTOC_KX_SUPP 0x40000000 #define IXGBE_AUTOC_PAUSE 0x30000000 @@ -1456,11 +1457,11 @@ struct ixgbe_mac_info { u32 max_tx_queues; u32 max_rx_queues; u32 max_msix_vectors; - u32 link_attach_type; - u32 link_mode_select; - bool link_settings_loaded; + u32 orig_autoc; + u32 orig_autoc2; + bool orig_link_settings_stored; bool autoneg; - bool autoneg_failed; + bool autoneg_succeeded; }; struct ixgbe_phy_info { -- GitLab From 34b0368c6864321c7020ddc8cbaec9a63b4e3de8 Mon Sep 17 00:00:00 2001 From: Peter P Waskiewicz Jr Date: Thu, 5 Feb 2009 23:54:42 -0800 Subject: [PATCH 1231/4982] ixgbe: Display EEPROM version in ethtool -i queries Currently ixgbe does not display the EEPROM version in ethtool -i, where other drivers do. The EEPROM version is located at offset 0x29. This patch adds support to display it. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe.h | 2 ++ drivers/net/ixgbe/ixgbe_ethtool.c | 9 ++++++++- drivers/net/ixgbe/ixgbe_main.c | 3 +++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 0ea791ae0d1..e98ace8c578 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -310,6 +310,8 @@ struct ixgbe_adapter { struct work_struct watchdog_task; struct work_struct sfp_task; struct timer_list sfp_timer; + + u16 eeprom_version; }; enum ixbge_state_t { diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 14e661e0a25..54d96cb05b4 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -679,10 +679,17 @@ static void ixgbe_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { struct ixgbe_adapter *adapter = netdev_priv(netdev); + char firmware_version[32]; strncpy(drvinfo->driver, ixgbe_driver_name, 32); strncpy(drvinfo->version, ixgbe_driver_version, 32); - strncpy(drvinfo->fw_version, "N/A", 32); + + sprintf(firmware_version, "%d.%d-%d", + (adapter->eeprom_version & 0xF000) >> 12, + (adapter->eeprom_version & 0x0FF0) >> 4, + adapter->eeprom_version & 0x000F); + + strncpy(drvinfo->fw_version, firmware_version, 32); strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); drvinfo->n_stats = IXGBE_STATS_LEN; drvinfo->regdump_len = ixgbe_get_regs_len(netdev); diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 5db82b5fa9b..dceae37fd57 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -4191,6 +4191,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, "PCI-Express slot is required.\n"); } + /* save off EEPROM version number */ + hw->eeprom.ops.read(hw, 0x29, &adapter->eeprom_version); + /* reset the hardware with the new settings */ hw->mac.ops.start_hw(hw); -- GitLab From 612e244c12215f6f74973ea3b89bff96450dc530 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Thu, 5 Feb 2009 23:55:45 -0800 Subject: [PATCH 1232/4982] e1000e: normalize usage of serdes_has_link Cosmetic change to use struct e1000_mac_info.serdes_has_link consistently as the 'bool' that it's declared as. No functional change. Signed-off-by: Alex Chiang Acked-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/ethtool.c | 2 +- drivers/net/e1000e/lib.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index e48956d924b..2557aeef65e 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -1589,7 +1589,7 @@ static int e1000_link_test(struct e1000_adapter *adapter, u64 *data) *data = 0; if (hw->phy.media_type == e1000_media_type_internal_serdes) { int i = 0; - hw->mac.serdes_has_link = 0; + hw->mac.serdes_has_link = false; /* * On some blade server designs, link establishment diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index 66741104ffd..ac2f34e1836 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c @@ -501,7 +501,7 @@ s32 e1000e_check_for_fiber_link(struct e1000_hw *hw) ew32(TXCW, mac->txcw); ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); - mac->serdes_has_link = 1; + mac->serdes_has_link = true; } return 0; @@ -566,7 +566,7 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw) ew32(TXCW, mac->txcw); ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); - mac->serdes_has_link = 1; + mac->serdes_has_link = true; } else if (!(E1000_TXCW_ANE & er32(TXCW))) { /* * If we force link for non-auto-negotiation switch, check -- GitLab From ff491a7334acfd74e515c896632e37e401f52676 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 5 Feb 2009 23:56:36 -0800 Subject: [PATCH 1233/4982] netlink: change return-value logic of netlink_broadcast() Currently, netlink_broadcast() reports errors to the caller if no messages at all were delivered: 1) If, at least, one message has been delivered correctly, returns 0. 2) Otherwise, if no messages at all were delivered due to skb_clone() failure, return -ENOBUFS. 3) Otherwise, if there are no listeners, return -ESRCH. With this patch, the caller knows if the delivery of any of the messages to the listeners have failed: 1) If it fails to deliver any message (for whatever reason), return -ENOBUFS. 2) Otherwise, if all messages were delivered OK, returns 0. 3) Otherwise, if no listeners, return -ESRCH. In the current ctnetlink code and in Netfilter in general, we can add reliable logging and connection tracking event delivery by dropping the packets whose events were not successfully delivered over Netlink. Of course, this option would be settable via /proc as this approach reduces performance (in terms of filtered connections per seconds by a stateful firewall) but providing reliable logging and event delivery (for conntrackd) in return. This patch also changes some clients of netlink_broadcast() that may report ENOBUFS errors via printk. This error handling is not of any help. Instead, the userspace daemons that are listening to those netlink messages should resync themselves with the kernel-side if they hit ENOBUFS. BTW, netlink_broadcast() clients include those that call cn_netlink_send(), nlmsg_multicast() and genlmsg_multicast() since they internally call netlink_broadcast() and return its error value. Signed-off-by: Pablo Neira Ayuso Signed-off-by: David S. Miller --- drivers/acpi/event.c | 6 +----- drivers/scsi/scsi_transport_fc.c | 16 ++++------------ drivers/scsi/scsi_transport_iscsi.c | 12 ++---------- drivers/video/uvesafb.c | 5 ++++- fs/dquot.c | 5 +---- lib/kobject_uevent.c | 3 +++ net/netlink/af_netlink.c | 8 ++++++-- net/wimax/op-msg.c | 9 +++------ net/wimax/stack.c | 12 ++++-------- 9 files changed, 28 insertions(+), 48 deletions(-) diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index 0c24bd4d656..aeb7e5fb4a0 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c @@ -235,11 +235,7 @@ int acpi_bus_generate_netlink_event(const char *device_class, return result; } - result = - genlmsg_multicast(skb, 0, acpi_event_mcgrp.id, GFP_ATOMIC); - if (result) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Failed to send a Genetlink message!\n")); + genlmsg_multicast(skb, 0, acpi_event_mcgrp.id, GFP_ATOMIC); return 0; } diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 5f77417ed58..3ee4eb40abc 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -533,12 +533,8 @@ fc_host_post_event(struct Scsi_Host *shost, u32 event_number, event->event_code = event_code; event->event_data = event_data; - err = nlmsg_multicast(scsi_nl_sock, skb, 0, SCSI_NL_GRP_FC_EVENTS, - GFP_KERNEL); - if (err && (err != -ESRCH)) /* filter no recipient errors */ - /* nlmsg_multicast already kfree_skb'd */ - goto send_fail; - + nlmsg_multicast(scsi_nl_sock, skb, 0, SCSI_NL_GRP_FC_EVENTS, + GFP_KERNEL); return; send_fail_skb: @@ -607,12 +603,8 @@ fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number, event->event_code = FCH_EVT_VENDOR_UNIQUE; memcpy(&event->event_data, data_buf, data_len); - err = nlmsg_multicast(scsi_nl_sock, skb, 0, SCSI_NL_GRP_FC_EVENTS, - GFP_KERNEL); - if (err && (err != -ESRCH)) /* filter no recipient errors */ - /* nlmsg_multicast already kfree_skb'd */ - goto send_vendor_fail; - + nlmsg_multicast(scsi_nl_sock, skb, 0, SCSI_NL_GRP_FC_EVENTS, + GFP_KERNEL); return; send_vendor_fail_skb: diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 75c9297694c..2adfab8c11c 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -966,15 +966,7 @@ iscsi_if_transport_lookup(struct iscsi_transport *tt) static int iscsi_broadcast_skb(struct sk_buff *skb, gfp_t gfp) { - int rc; - - rc = netlink_broadcast(nls, skb, 0, 1, gfp); - if (rc < 0) { - printk(KERN_ERR "iscsi: can not broadcast skb (%d)\n", rc); - return rc; - } - - return 0; + return netlink_broadcast(nls, skb, 0, 1, gfp); } static int @@ -1207,7 +1199,7 @@ int iscsi_session_event(struct iscsi_cls_session *session, * the user and when the daemon is restarted it will handle it */ rc = iscsi_broadcast_skb(skb, GFP_KERNEL); - if (rc < 0) + if (rc == -ESRCH) iscsi_cls_session_printk(KERN_ERR, session, "Cannot notify userspace of session " "event %u. Check iscsi daemon\n", diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index 6c2d37fdd3b..74ae7589900 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c @@ -204,8 +204,11 @@ static int uvesafb_exec(struct uvesafb_ktask *task) } else { v86d_started = 1; err = cn_netlink_send(m, 0, gfp_any()); + if (err == -ENOBUFS) + err = 0; } - } + } else if (err == -ENOBUFS) + err = 0; if (!err && !(task->t.flags & TF_EXIT)) err = !wait_for_completion_timeout(task->done, diff --git a/fs/dquot.c b/fs/dquot.c index bca3cac4bee..d6add0bf5ad 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -1057,10 +1057,7 @@ static void send_warning(const struct dquot *dquot, const char warntype) goto attr_err_out; genlmsg_end(skb, msg_head); - ret = genlmsg_multicast(skb, 0, quota_genl_family.id, GFP_NOFS); - if (ret < 0 && ret != -ESRCH) - printk(KERN_ERR - "VFS: Failed to send notification message: %d\n", ret); + genlmsg_multicast(skb, 0, quota_genl_family.id, GFP_NOFS); return; attr_err_out: printk(KERN_ERR "VFS: Not enough space to compose quota message!\n"); diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index 318328ddbd1..38131028d16 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c @@ -227,6 +227,9 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, NETLINK_CB(skb).dst_group = 1; retval = netlink_broadcast(uevent_sock, skb, 0, 1, GFP_KERNEL); + /* ENOBUFS should be handled in userspace */ + if (retval == -ENOBUFS) + retval = 0; } else retval = -ENOMEM; } diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 9eb895c7a2a..6ee69c27f80 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -950,6 +950,7 @@ struct netlink_broadcast_data { u32 pid; u32 group; int failure; + int delivery_failure; int congested; int delivered; gfp_t allocation; @@ -999,6 +1000,7 @@ static inline int do_one_broadcast(struct sock *sk, p->skb2 = NULL; } else if ((val = netlink_broadcast_deliver(sk, p->skb2)) < 0) { netlink_overrun(sk); + p->delivery_failure = 1; } else { p->congested |= val; p->delivered = 1; @@ -1025,6 +1027,7 @@ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, info.pid = pid; info.group = group; info.failure = 0; + info.delivery_failure = 0; info.congested = 0; info.delivered = 0; info.allocation = allocation; @@ -1045,13 +1048,14 @@ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, if (info.skb2) kfree_skb(info.skb2); + if (info.delivery_failure || info.failure) + return -ENOBUFS; + if (info.delivered) { if (info.congested && (allocation & __GFP_WAIT)) yield(); return 0; } - if (info.failure) - return -ENOBUFS; return -ESRCH; } EXPORT_SYMBOL(netlink_broadcast); diff --git a/net/wimax/op-msg.c b/net/wimax/op-msg.c index cb3b4ad5368..5d149c1b5f0 100644 --- a/net/wimax/op-msg.c +++ b/net/wimax/op-msg.c @@ -258,7 +258,6 @@ EXPORT_SYMBOL_GPL(wimax_msg_len); */ int wimax_msg_send(struct wimax_dev *wimax_dev, struct sk_buff *skb) { - int result; struct device *dev = wimax_dev->net_dev->dev.parent; void *msg = skb->data; size_t size = skb->len; @@ -266,11 +265,9 @@ int wimax_msg_send(struct wimax_dev *wimax_dev, struct sk_buff *skb) d_printf(1, dev, "CTX: wimax msg, %zu bytes\n", size); d_dump(2, dev, msg, size); - result = genlmsg_multicast(skb, 0, wimax_gnl_mcg.id, GFP_KERNEL); - d_printf(1, dev, "CTX: genl multicast result %d\n", result); - if (result == -ESRCH) /* Nobody connected, ignore it */ - result = 0; /* btw, the skb is freed already */ - return result; + genlmsg_multicast(skb, 0, wimax_gnl_mcg.id, GFP_KERNEL); + d_printf(1, dev, "CTX: genl multicast done\n"); + return 0; } EXPORT_SYMBOL_GPL(wimax_msg_send); diff --git a/net/wimax/stack.c b/net/wimax/stack.c index 3869c032788..a0ee76b5251 100644 --- a/net/wimax/stack.c +++ b/net/wimax/stack.c @@ -163,16 +163,12 @@ int wimax_gnl_re_state_change_send( struct device *dev = wimax_dev_to_dev(wimax_dev); d_fnstart(3, dev, "(wimax_dev %p report_skb %p)\n", wimax_dev, report_skb); - if (report_skb == NULL) + if (report_skb == NULL) { + result = -ENOMEM; goto out; - genlmsg_end(report_skb, header); - result = genlmsg_multicast(report_skb, 0, wimax_gnl_mcg.id, GFP_KERNEL); - if (result == -ESRCH) /* Nobody connected, ignore it */ - result = 0; /* btw, the skb is freed already */ - if (result < 0) { - dev_err(dev, "RE_STCH: Error sending: %d\n", result); - nlmsg_free(report_skb); } + genlmsg_end(report_skb, header); + genlmsg_multicast(report_skb, 0, wimax_gnl_mcg.id, GFP_KERNEL); out: d_fnend(3, dev, "(wimax_dev %p report_skb %p) = %d\n", wimax_dev, report_skb, result); -- GitLab From ddb213f0768dc8b10cab37a21b85b567f1966d4a Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 6 Feb 2009 01:29:23 -0800 Subject: [PATCH 1234/4982] forcedeth: make msi-x different name for rx-tx Impact: make /proc/interrupts could show more info which irq is rx or other for msi-x add three name fields for rx, tx, other Signed-off-by: Yinghai Lu Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 875509d7d86..3a733a58456 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -812,6 +812,11 @@ struct fe_priv { /* power saved state */ u32 saved_config_space[NV_PCI_REGSZ_MAX/4]; + + /* for different msi-x irq type */ + char name_rx[IFNAMSIZ + 3]; /* -rx */ + char name_tx[IFNAMSIZ + 3]; /* -tx */ + char name_other[IFNAMSIZ + 6]; /* -other */ }; /* @@ -3918,21 +3923,27 @@ static int nv_request_irq(struct net_device *dev, int intr_test) np->msi_flags |= NV_MSI_X_ENABLED; if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT && !intr_test) { /* Request irq for rx handling */ - if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, &nv_nic_irq_rx, IRQF_SHARED, dev->name, dev) != 0) { + sprintf(np->name_rx, "%s-rx", dev->name); + if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, + &nv_nic_irq_rx, IRQF_SHARED, np->name_rx, dev) != 0) { printk(KERN_INFO "forcedeth: request_irq failed for rx %d\n", ret); pci_disable_msix(np->pci_dev); np->msi_flags &= ~NV_MSI_X_ENABLED; goto out_err; } /* Request irq for tx handling */ - if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, &nv_nic_irq_tx, IRQF_SHARED, dev->name, dev) != 0) { + sprintf(np->name_tx, "%s-tx", dev->name); + if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, + &nv_nic_irq_tx, IRQF_SHARED, np->name_tx, dev) != 0) { printk(KERN_INFO "forcedeth: request_irq failed for tx %d\n", ret); pci_disable_msix(np->pci_dev); np->msi_flags &= ~NV_MSI_X_ENABLED; goto out_free_rx; } /* Request irq for link and timer handling */ - if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector, &nv_nic_irq_other, IRQF_SHARED, dev->name, dev) != 0) { + sprintf(np->name_other, "%s-other", dev->name); + if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector, + &nv_nic_irq_other, IRQF_SHARED, np->name_other, dev) != 0) { printk(KERN_INFO "forcedeth: request_irq failed for link %d\n", ret); pci_disable_msix(np->pci_dev); np->msi_flags &= ~NV_MSI_X_ENABLED; -- GitLab From 79d30a581fc405fc63322622cb1517d95ed8f5ce Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 6 Feb 2009 01:30:01 -0800 Subject: [PATCH 1235/4982] forcedeth: don't clear nic_poll_irq too early Impact: fix bug for msix, we still need that flag to enable irq respectively Signed-off-by: Yinghai Lu Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 3a733a58456..2d5f7d42e92 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -4057,8 +4057,6 @@ static void nv_do_nic_poll(unsigned long data) mask |= NVREG_IRQ_OTHER; } } - np->nic_poll_irq = 0; - /* disable_irq() contains synchronize_irq, thus no irq handler can run now */ if (np->recover_error) { @@ -4096,11 +4094,11 @@ static void nv_do_nic_poll(unsigned long data) } } - writel(mask, base + NvRegIrqMask); pci_push(base); if (!using_multi_irqs(dev)) { + np->nic_poll_irq = 0; if (nv_optimized(np)) nv_nic_irq_optimized(0, dev); else @@ -4111,18 +4109,22 @@ static void nv_do_nic_poll(unsigned long data) enable_irq_lockdep(np->pci_dev->irq); } else { if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) { + np->nic_poll_irq &= ~NVREG_IRQ_RX_ALL; nv_nic_irq_rx(0, dev); enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); } if (np->nic_poll_irq & NVREG_IRQ_TX_ALL) { + np->nic_poll_irq &= ~NVREG_IRQ_TX_ALL; nv_nic_irq_tx(0, dev); enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); } if (np->nic_poll_irq & NVREG_IRQ_OTHER) { + np->nic_poll_irq &= ~NVREG_IRQ_OTHER; nv_nic_irq_other(0, dev); enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector); } } + } #ifdef CONFIG_NET_POLL_CONTROLLER -- GitLab From 0335ef5d59f40931e1b8f0a8be6a09dbc623081b Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 6 Feb 2009 01:30:36 -0800 Subject: [PATCH 1236/4982] forcedeth: disable irq at first before schedule rx Impact: clean up schedule it later after disable it. Signed-off-by: Yinghai Lu Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 2d5f7d42e92..a7c15715cd8 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -3708,13 +3708,13 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data) u32 events; events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_RX_ALL; - writel(NVREG_IRQ_RX_ALL, base + NvRegMSIXIrqStatus); if (events) { - napi_schedule(&np->napi); /* disable receive interrupts on the nic */ writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); pci_push(base); + writel(NVREG_IRQ_RX_ALL, base + NvRegMSIXIrqStatus); + napi_schedule(&np->napi); } return IRQ_HANDLED; } -- GitLab From 033e97b24ad6aaeddbb0180bbd87844513171430 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 6 Feb 2009 01:30:56 -0800 Subject: [PATCH 1237/4982] forcedeth: ck804 and mcp55 doesn't need timerirq Impact: cleanup so get less irq. Signed-off-by: Yinghai Lu Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index a7c15715cd8..f89ea35e448 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -6070,11 +6070,11 @@ static struct pci_device_id pci_tbl[] = { }, { /* CK804 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_8), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1|DEV_NEED_TX_LIMIT, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1|DEV_NEED_TX_LIMIT, }, { /* CK804 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_9), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1|DEV_NEED_TX_LIMIT, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1|DEV_NEED_TX_LIMIT, }, { /* MCP04 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_10), @@ -6094,11 +6094,11 @@ static struct pci_device_id pci_tbl[] = { }, { /* MCP55 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_NEED_TX_LIMIT, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_NEED_TX_LIMIT, }, { /* MCP55 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_NEED_TX_LIMIT, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_NEED_TX_LIMIT, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_16), -- GitLab From 394827913e371b058849349c6fc9d52c59c31a3d Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 6 Feb 2009 01:31:12 -0800 Subject: [PATCH 1238/4982] forcedeth: enable msix to default Impact: change default msix and napic can work again Signed-off-by: Yinghai Lu Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index f89ea35e448..7825be7586f 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -862,7 +862,7 @@ enum { NV_MSIX_INT_DISABLED, NV_MSIX_INT_ENABLED }; -static int msix = NV_MSIX_INT_DISABLED; +static int msix = NV_MSIX_INT_ENABLED; /* * DMA 64bit -- GitLab From 92a950ff2b7091a735c32a6e57b8136650bc7812 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 6 Feb 2009 18:12:34 +0800 Subject: [PATCH 1239/4982] ASoC: Blackfin: cleanup sport handling in ASoC Blackfin AC97 code - make sport number handling more dynamic as not all Blackfins have a linear sport map starting at 0 - indexes can be macroed away too Signed-off-by: Mike Frysinger Signed-off-by: Cliff Cai Signed-off-by: Bryan Wu Signed-off-by: Mark Brown --- sound/soc/blackfin/bf5xx-ac97.c | 92 ++++++++++++--------------------- 1 file changed, 33 insertions(+), 59 deletions(-) diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c index 3be2be60576..5885702c78f 100644 --- a/sound/soc/blackfin/bf5xx-ac97.c +++ b/sound/soc/blackfin/bf5xx-ac97.c @@ -31,72 +31,46 @@ #include "bf5xx-sport.h" #include "bf5xx-ac97.h" -#if defined(CONFIG_BF54x) -#define PIN_REQ_SPORT_0 {P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, \ - P_SPORT0_RFS, P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0} - -#define PIN_REQ_SPORT_1 {P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, \ - P_SPORT1_RFS, P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0} - -#define PIN_REQ_SPORT_2 {P_SPORT2_TFS, P_SPORT2_DTPRI, P_SPORT2_TSCLK, \ - P_SPORT2_RFS, P_SPORT2_DRPRI, P_SPORT2_RSCLK, 0} - -#define PIN_REQ_SPORT_3 {P_SPORT3_TFS, P_SPORT3_DTPRI, P_SPORT3_TSCLK, \ - P_SPORT3_RFS, P_SPORT3_DRPRI, P_SPORT3_RSCLK, 0} -#else -#define PIN_REQ_SPORT_0 {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, \ - P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0} - -#define PIN_REQ_SPORT_1 {P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, \ - P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0} -#endif - static int *cmd_count; static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM; +#define SPORT_REQ(x) \ + [x] = {P_SPORT##x##_TFS, P_SPORT##x##_DTPRI, P_SPORT##x##_TSCLK, \ + P_SPORT##x##_RFS, P_SPORT##x##_DRPRI, P_SPORT##x##_RSCLK, 0} static u16 sport_req[][7] = { - PIN_REQ_SPORT_0, -#ifdef PIN_REQ_SPORT_1 - PIN_REQ_SPORT_1, +#ifdef SPORT0_TCR1 + SPORT_REQ(0), #endif -#ifdef PIN_REQ_SPORT_2 - PIN_REQ_SPORT_2, +#ifdef SPORT1_TCR1 + SPORT_REQ(1), #endif -#ifdef PIN_REQ_SPORT_3 - PIN_REQ_SPORT_3, +#ifdef SPORT2_TCR1 + SPORT_REQ(2), #endif - }; +#ifdef SPORT3_TCR1 + SPORT_REQ(3), +#endif +}; +#define SPORT_PARAMS(x) \ + [x] = { \ + .dma_rx_chan = CH_SPORT##x##_RX, \ + .dma_tx_chan = CH_SPORT##x##_TX, \ + .err_irq = IRQ_SPORT##x##_ERROR, \ + .regs = (struct sport_register *)SPORT##x##_TCR1, \ + } static struct sport_param sport_params[4] = { - { - .dma_rx_chan = CH_SPORT0_RX, - .dma_tx_chan = CH_SPORT0_TX, - .err_irq = IRQ_SPORT0_ERROR, - .regs = (struct sport_register *)SPORT0_TCR1, - }, -#ifdef PIN_REQ_SPORT_1 - { - .dma_rx_chan = CH_SPORT1_RX, - .dma_tx_chan = CH_SPORT1_TX, - .err_irq = IRQ_SPORT1_ERROR, - .regs = (struct sport_register *)SPORT1_TCR1, - }, +#ifdef SPORT0_TCR1 + SPORT_PARAMS(0), #endif -#ifdef PIN_REQ_SPORT_2 - { - .dma_rx_chan = CH_SPORT2_RX, - .dma_tx_chan = CH_SPORT2_TX, - .err_irq = IRQ_SPORT2_ERROR, - .regs = (struct sport_register *)SPORT2_TCR1, - }, +#ifdef SPORT1_TCR1 + SPORT_PARAMS(1), #endif -#ifdef PIN_REQ_SPORT_3 - { - .dma_rx_chan = CH_SPORT3_RX, - .dma_tx_chan = CH_SPORT3_TX, - .err_irq = IRQ_SPORT3_ERROR, - .regs = (struct sport_register *)SPORT3_TCR1, - } +#ifdef SPORT2_TCR1 + SPORT_PARAMS(2), +#endif +#ifdef SPORT3_TCR1 + SPORT_PARAMS(3), #endif }; @@ -332,11 +306,11 @@ static int bf5xx_ac97_probe(struct platform_device *pdev, if (cmd_count == NULL) return -ENOMEM; - if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { + if (peripheral_request_list(sport_req[sport_num], "soc-audio")) { pr_err("Requesting Peripherals failed\n"); ret = -EFAULT; goto peripheral_err; - } + } #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET /* Request PB3 as reset pin */ @@ -385,7 +359,7 @@ sport_err: gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); #endif gpio_err: - peripheral_free_list(&sport_req[sport_num][0]); + peripheral_free_list(sport_req[sport_num]); peripheral_err: free_page((unsigned long)cmd_count); cmd_count = NULL; @@ -398,7 +372,7 @@ static void bf5xx_ac97_remove(struct platform_device *pdev, { free_page((unsigned long)cmd_count); cmd_count = NULL; - peripheral_free_list(&sport_req[sport_num][0]); + peripheral_free_list(sport_req[sport_num]); #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); #endif -- GitLab From 8836c273e4d44d088157b7ccbd2c108cefe70565 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 6 Feb 2009 18:12:35 +0800 Subject: [PATCH 1240/4982] ASoC: Blackfin: drop unnecessary dma casts Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu Signed-off-by: Mark Brown --- sound/soc/blackfin/bf5xx-sport.c | 104 +++++++++++++------------------ 1 file changed, 43 insertions(+), 61 deletions(-) diff --git a/sound/soc/blackfin/bf5xx-sport.c b/sound/soc/blackfin/bf5xx-sport.c index 3b99e484d55..b7953c8cf83 100644 --- a/sound/soc/blackfin/bf5xx-sport.c +++ b/sound/soc/blackfin/bf5xx-sport.c @@ -133,7 +133,7 @@ static void setup_desc(struct dmasg *desc, void *buf, int fragcount, int i; for (i = 0; i < fragcount; ++i) { - desc[i].next_desc_addr = (unsigned long)&(desc[i + 1]); + desc[i].next_desc_addr = &(desc[i + 1]); desc[i].start_addr = (unsigned long)buf + i*fragsize; desc[i].cfg = cfg; desc[i].x_count = x_count; @@ -143,12 +143,12 @@ static void setup_desc(struct dmasg *desc, void *buf, int fragcount, } /* make circular */ - desc[fragcount-1].next_desc_addr = (unsigned long)desc; + desc[fragcount-1].next_desc_addr = desc; - pr_debug("setup desc: desc0=%p, next0=%lx, desc1=%p," - "next1=%lx\nx_count=%x,y_count=%x,addr=0x%lx,cfs=0x%x\n", - &(desc[0]), desc[0].next_desc_addr, - &(desc[1]), desc[1].next_desc_addr, + pr_debug("setup desc: desc0=%p, next0=%p, desc1=%p," + "next1=%p\nx_count=%x,y_count=%x,addr=0x%lx,cfs=0x%x\n", + desc, desc[0].next_desc_addr, + desc+1, desc[1].next_desc_addr, desc[0].x_count, desc[0].y_count, desc[0].start_addr, desc[0].cfg); } @@ -184,22 +184,20 @@ static inline int sport_hook_rx_dummy(struct sport_device *sport) BUG_ON(sport->curr_rx_desc == sport->dummy_rx_desc); /* Maybe the dummy buffer descriptor ring is damaged */ - sport->dummy_rx_desc->next_desc_addr = \ - (unsigned long)(sport->dummy_rx_desc+1); + sport->dummy_rx_desc->next_desc_addr = sport->dummy_rx_desc + 1; local_irq_save(flags); - desc = (struct dmasg *)get_dma_next_desc_ptr(sport->dma_rx_chan); + desc = get_dma_next_desc_ptr(sport->dma_rx_chan); /* Copy the descriptor which will be damaged to backup */ temp_desc = *desc; desc->x_count = 0xa; desc->y_count = 0; - desc->next_desc_addr = (unsigned long)(sport->dummy_rx_desc); + desc->next_desc_addr = sport->dummy_rx_desc; local_irq_restore(flags); /* Waiting for dummy buffer descriptor is already hooked*/ while ((get_dma_curr_desc_ptr(sport->dma_rx_chan) - - sizeof(struct dmasg)) != - (unsigned long)sport->dummy_rx_desc) - ; + sizeof(struct dmasg)) != sport->dummy_rx_desc) + continue; sport->curr_rx_desc = sport->dummy_rx_desc; /* Restore the damaged descriptor */ *desc = temp_desc; @@ -210,14 +208,12 @@ static inline int sport_hook_rx_dummy(struct sport_device *sport) static inline int sport_rx_dma_start(struct sport_device *sport, int dummy) { if (dummy) { - sport->dummy_rx_desc->next_desc_addr = \ - (unsigned long) sport->dummy_rx_desc; + sport->dummy_rx_desc->next_desc_addr = sport->dummy_rx_desc; sport->curr_rx_desc = sport->dummy_rx_desc; } else sport->curr_rx_desc = sport->dma_rx_desc; - set_dma_next_desc_addr(sport->dma_rx_chan, \ - (unsigned long)(sport->curr_rx_desc)); + set_dma_next_desc_addr(sport->dma_rx_chan, sport->curr_rx_desc); set_dma_x_count(sport->dma_rx_chan, 0); set_dma_x_modify(sport->dma_rx_chan, 0); set_dma_config(sport->dma_rx_chan, (DMAFLOW_LARGE | NDSIZE_9 | \ @@ -231,14 +227,12 @@ static inline int sport_rx_dma_start(struct sport_device *sport, int dummy) static inline int sport_tx_dma_start(struct sport_device *sport, int dummy) { if (dummy) { - sport->dummy_tx_desc->next_desc_addr = \ - (unsigned long) sport->dummy_tx_desc; + sport->dummy_tx_desc->next_desc_addr = sport->dummy_tx_desc; sport->curr_tx_desc = sport->dummy_tx_desc; } else sport->curr_tx_desc = sport->dma_tx_desc; - set_dma_next_desc_addr(sport->dma_tx_chan, \ - (unsigned long)(sport->curr_tx_desc)); + set_dma_next_desc_addr(sport->dma_tx_chan, sport->curr_tx_desc); set_dma_x_count(sport->dma_tx_chan, 0); set_dma_x_modify(sport->dma_tx_chan, 0); set_dma_config(sport->dma_tx_chan, @@ -261,11 +255,9 @@ int sport_rx_start(struct sport_device *sport) BUG_ON(sport->curr_rx_desc != sport->dummy_rx_desc); local_irq_save(flags); while ((get_dma_curr_desc_ptr(sport->dma_rx_chan) - - sizeof(struct dmasg)) != - (unsigned long)sport->dummy_rx_desc) - ; - sport->dummy_rx_desc->next_desc_addr = - (unsigned long)(sport->dma_rx_desc); + sizeof(struct dmasg)) != sport->dummy_rx_desc) + continue; + sport->dummy_rx_desc->next_desc_addr = sport->dma_rx_desc; local_irq_restore(flags); sport->curr_rx_desc = sport->dma_rx_desc; } else { @@ -310,23 +302,21 @@ static inline int sport_hook_tx_dummy(struct sport_device *sport) BUG_ON(sport->dummy_tx_desc == NULL); BUG_ON(sport->curr_tx_desc == sport->dummy_tx_desc); - sport->dummy_tx_desc->next_desc_addr = \ - (unsigned long)(sport->dummy_tx_desc+1); + sport->dummy_tx_desc->next_desc_addr = sport->dummy_tx_desc + 1; /* Shorten the time on last normal descriptor */ local_irq_save(flags); - desc = (struct dmasg *)get_dma_next_desc_ptr(sport->dma_tx_chan); + desc = get_dma_next_desc_ptr(sport->dma_tx_chan); /* Store the descriptor which will be damaged */ temp_desc = *desc; desc->x_count = 0xa; desc->y_count = 0; - desc->next_desc_addr = (unsigned long)(sport->dummy_tx_desc); + desc->next_desc_addr = sport->dummy_tx_desc; local_irq_restore(flags); /* Waiting for dummy buffer descriptor is already hooked*/ while ((get_dma_curr_desc_ptr(sport->dma_tx_chan) - \ - sizeof(struct dmasg)) != \ - (unsigned long)sport->dummy_tx_desc) - ; + sizeof(struct dmasg)) != sport->dummy_tx_desc) + continue; sport->curr_tx_desc = sport->dummy_tx_desc; /* Restore the damaged descriptor */ *desc = temp_desc; @@ -347,11 +337,9 @@ int sport_tx_start(struct sport_device *sport) /* Hook the normal buffer descriptor */ local_irq_save(flags); while ((get_dma_curr_desc_ptr(sport->dma_tx_chan) - - sizeof(struct dmasg)) != - (unsigned long)sport->dummy_tx_desc) - ; - sport->dummy_tx_desc->next_desc_addr = - (unsigned long)(sport->dma_tx_desc); + sizeof(struct dmasg)) != sport->dummy_tx_desc) + continue; + sport->dummy_tx_desc->next_desc_addr = sport->dma_tx_desc; local_irq_restore(flags); sport->curr_tx_desc = sport->dma_tx_desc; } else { @@ -536,19 +524,17 @@ static int sport_config_rx_dummy(struct sport_device *sport) unsigned config; pr_debug("%s entered\n", __func__); -#if L1_DATA_A_LENGTH != 0 - desc = (struct dmasg *) l1_data_sram_alloc(2 * sizeof(*desc)); -#else - { + if (L1_DATA_A_LENGTH) + desc = l1_data_sram_zalloc(2 * sizeof(*desc)); + else { dma_addr_t addr; desc = dma_alloc_coherent(NULL, 2 * sizeof(*desc), &addr, 0); + memset(desc, 0, 2 * sizeof(*desc)); } -#endif if (desc == NULL) { pr_err("Failed to allocate memory for dummy rx desc\n"); return -ENOMEM; } - memset(desc, 0, 2 * sizeof(*desc)); sport->dummy_rx_desc = desc; desc->start_addr = (unsigned long)sport->dummy_buf; config = DMAFLOW_LARGE | NDSIZE_9 | compute_wdsize(sport->wdsize) @@ -559,8 +545,8 @@ static int sport_config_rx_dummy(struct sport_device *sport) desc->y_count = 0; desc->y_modify = 0; memcpy(desc+1, desc, sizeof(*desc)); - desc->next_desc_addr = (unsigned long)(desc+1); - desc[1].next_desc_addr = (unsigned long)desc; + desc->next_desc_addr = desc + 1; + desc[1].next_desc_addr = desc; return 0; } @@ -571,19 +557,17 @@ static int sport_config_tx_dummy(struct sport_device *sport) pr_debug("%s entered\n", __func__); -#if L1_DATA_A_LENGTH != 0 - desc = (struct dmasg *) l1_data_sram_alloc(2 * sizeof(*desc)); -#else - { + if (L1_DATA_A_LENGTH) + desc = l1_data_sram_zalloc(2 * sizeof(*desc)); + else { dma_addr_t addr; desc = dma_alloc_coherent(NULL, 2 * sizeof(*desc), &addr, 0); + memset(desc, 0, 2 * sizeof(*desc)); } -#endif if (!desc) { pr_err("Failed to allocate memory for dummy tx desc\n"); return -ENOMEM; } - memset(desc, 0, 2 * sizeof(*desc)); sport->dummy_tx_desc = desc; desc->start_addr = (unsigned long)sport->dummy_buf + \ sport->dummy_count; @@ -595,8 +579,8 @@ static int sport_config_tx_dummy(struct sport_device *sport) desc->y_count = 0; desc->y_modify = 0; memcpy(desc+1, desc, sizeof(*desc)); - desc->next_desc_addr = (unsigned long)(desc+1); - desc[1].next_desc_addr = (unsigned long)desc; + desc->next_desc_addr = desc + 1; + desc[1].next_desc_addr = desc; return 0; } @@ -872,17 +856,15 @@ struct sport_device *sport_init(struct sport_param *param, unsigned wdsize, sport->wdsize = wdsize; sport->dummy_count = dummy_count; -#if L1_DATA_A_LENGTH != 0 - sport->dummy_buf = l1_data_sram_alloc(dummy_count * 2); -#else - sport->dummy_buf = kmalloc(dummy_count * 2, GFP_KERNEL); -#endif + if (L1_DATA_A_LENGTH) + sport->dummy_buf = l1_data_sram_zalloc(dummy_count * 2); + else + sport->dummy_buf = kzalloc(dummy_count * 2, GFP_KERNEL); if (sport->dummy_buf == NULL) { pr_err("Failed to allocate dummy buffer\n"); goto __error; } - memset(sport->dummy_buf, 0, dummy_count * 2); ret = sport_config_rx_dummy(sport); if (ret) { pr_err("Failed to config rx dummy ring\n"); @@ -939,6 +921,7 @@ void sport_done(struct sport_device *sport) sport = NULL; } EXPORT_SYMBOL(sport_done); + /* * It is only used to send several bytes when dma is not enabled * sport controller is configured but not enabled. @@ -1029,4 +1012,3 @@ EXPORT_SYMBOL(sport_send_and_recv); MODULE_AUTHOR("Roy Huang"); MODULE_DESCRIPTION("SPORT driver for ADI Blackfin"); MODULE_LICENSE("GPL"); - -- GitLab From 85ef2375ef2ebbb2bf660ad3a27c644d0ebf1b1a Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Thu, 5 Feb 2009 17:56:02 -0600 Subject: [PATCH 1241/4982] ASoC: optimize init sequence of Freescale MPC8610 sound drivers In the Freescale MPC8610 sound drivers, relocate all code from the _prepare functions into the corresponding _hw_params functions. These drivers assumed that the sample size is known in the _prepare function and not in the _hw_params function, but this is not true. Move the code in fsl_dma_prepare() into fsl_dma_hw_param(). Create fsl_ssi_hw_params() and move the code from fsl_ssi_prepare() into it. Turn off snooping for DMA operations to/from I/O registers, since that's not necessary. Signed-off-by: Timur Tabi Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_dma.c | 178 +++++++++++++++++++--------------------- sound/soc/fsl/fsl_ssi.c | 19 ++--- 2 files changed, 94 insertions(+), 103 deletions(-) diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 64993eda567..58a3fa49750 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c @@ -464,11 +464,7 @@ static int fsl_dma_open(struct snd_pcm_substream *substream) sizeof(struct fsl_dma_link_descriptor); for (i = 0; i < NUM_DMA_LINKS; i++) { - struct fsl_dma_link_descriptor *link = &dma_private->link[i]; - - link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP); - link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP); - link->next = cpu_to_be64(temp_link); + dma_private->link[i].next = cpu_to_be64(temp_link); temp_link += sizeof(struct fsl_dma_link_descriptor); } @@ -525,79 +521,9 @@ static int fsl_dma_open(struct snd_pcm_substream *substream) * This function obtains hardware parameters about the opened stream and * programs the DMA controller accordingly. * - * Note that due to a quirk of the SSI's STX register, the target address - * for the DMA operations depends on the sample size. So we don't program - * the dest_addr (for playback -- source_addr for capture) fields in the - * link descriptors here. We do that in fsl_dma_prepare() - */ -static int fsl_dma_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct fsl_dma_private *dma_private = runtime->private_data; - - dma_addr_t temp_addr; /* Pointer to next period */ - - unsigned int i; - - /* Get all the parameters we need */ - size_t buffer_size = params_buffer_bytes(hw_params); - size_t period_size = params_period_bytes(hw_params); - - /* Initialize our DMA tracking variables */ - dma_private->period_size = period_size; - dma_private->num_periods = params_periods(hw_params); - dma_private->dma_buf_end = dma_private->dma_buf_phys + buffer_size; - dma_private->dma_buf_next = dma_private->dma_buf_phys + - (NUM_DMA_LINKS * period_size); - if (dma_private->dma_buf_next >= dma_private->dma_buf_end) - dma_private->dma_buf_next = dma_private->dma_buf_phys; - - /* - * The actual address in STX0 (destination for playback, source for - * capture) is based on the sample size, but we don't know the sample - * size in this function, so we'll have to adjust that later. See - * comments in fsl_dma_prepare(). - * - * The DMA controller does not have a cache, so the CPU does not - * need to tell it to flush its cache. However, the DMA - * controller does need to tell the CPU to flush its cache. - * That's what the SNOOP bit does. - * - * Also, even though the DMA controller supports 36-bit addressing, for - * simplicity we currently support only 32-bit addresses for the audio - * buffer itself. - */ - temp_addr = substream->dma_buffer.addr; - - for (i = 0; i < NUM_DMA_LINKS; i++) { - struct fsl_dma_link_descriptor *link = &dma_private->link[i]; - - link->count = cpu_to_be32(period_size); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - link->source_addr = cpu_to_be32(temp_addr); - else - link->dest_addr = cpu_to_be32(temp_addr); - - temp_addr += period_size; - } - - return 0; -} - -/** - * fsl_dma_prepare - prepare the DMA registers for playback. - * - * This function is called after the specifics of the audio data are known, - * i.e. snd_pcm_runtime is initialized. - * - * In this function, we finish programming the registers of the DMA - * controller that are dependent on the sample size. - * - * One of the drawbacks with big-endian is that when copying integers of - * different sizes to a fixed-sized register, the address to which the - * integer must be copied is dependent on the size of the integer. + * One drawback of big-endian is that when copying integers of different + * sizes to a fixed-sized register, the address to which the integer must be + * copied is dependent on the size of the integer. * * For example, if P is the address of a 32-bit register, and X is a 32-bit * integer, then X should be copied to address P. However, if X is a 16-bit @@ -613,22 +539,58 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream, * and 8 bytes at a time). So we do not support packed 24-bit samples. * 24-bit data must be padded to 32 bits. */ -static int fsl_dma_prepare(struct snd_pcm_substream *substream) +static int fsl_dma_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) { struct snd_pcm_runtime *runtime = substream->runtime; struct fsl_dma_private *dma_private = runtime->private_data; + + /* Number of bits per sample */ + unsigned int sample_size = + snd_pcm_format_physical_width(params_format(hw_params)); + + /* Number of bytes per frame */ + unsigned int frame_size = 2 * (sample_size / 8); + + /* Bus address of SSI STX register */ + dma_addr_t ssi_sxx_phys = dma_private->ssi_sxx_phys; + + /* Size of the DMA buffer, in bytes */ + size_t buffer_size = params_buffer_bytes(hw_params); + + /* Number of bytes per period */ + size_t period_size = params_period_bytes(hw_params); + + /* Pointer to next period */ + dma_addr_t temp_addr = substream->dma_buffer.addr; + + /* Pointer to DMA controller */ struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel; - u32 mr; + + u32 mr; /* DMA Mode Register */ + unsigned int i; - dma_addr_t ssi_sxx_phys; /* Bus address of SSI STX register */ - unsigned int frame_size; /* Number of bytes per frame */ - ssi_sxx_phys = dma_private->ssi_sxx_phys; + /* Initialize our DMA tracking variables */ + dma_private->period_size = period_size; + dma_private->num_periods = params_periods(hw_params); + dma_private->dma_buf_end = dma_private->dma_buf_phys + buffer_size; + dma_private->dma_buf_next = dma_private->dma_buf_phys + + (NUM_DMA_LINKS * period_size); + + if (dma_private->dma_buf_next >= dma_private->dma_buf_end) + /* This happens if the number of periods == NUM_DMA_LINKS */ + dma_private->dma_buf_next = dma_private->dma_buf_phys; mr = in_be32(&dma_channel->mr) & ~(CCSR_DMA_MR_BWC_MASK | CCSR_DMA_MR_SAHTS_MASK | CCSR_DMA_MR_DAHTS_MASK); - switch (runtime->sample_bits) { + /* Due to a quirk of the SSI's STX register, the target address + * for the DMA operations depends on the sample size. So we calculate + * that offset here. While we're at it, also tell the DMA controller + * how much data to transfer per sample. + */ + switch (sample_size) { case 8: mr |= CCSR_DMA_MR_DAHTS_1 | CCSR_DMA_MR_SAHTS_1; ssi_sxx_phys += 3; @@ -641,12 +603,12 @@ static int fsl_dma_prepare(struct snd_pcm_substream *substream) mr |= CCSR_DMA_MR_DAHTS_4 | CCSR_DMA_MR_SAHTS_4; break; default: + /* We should never get here */ dev_err(substream->pcm->card->dev, - "unsupported sample size %u\n", runtime->sample_bits); + "unsupported sample size %u\n", sample_size); return -EINVAL; } - frame_size = runtime->frame_bits / 8; /* * BWC should always be a multiple of the frame size. BWC determines * how many bytes are sent/received before the DMA controller checks the @@ -655,7 +617,6 @@ static int fsl_dma_prepare(struct snd_pcm_substream *substream) * capture, the receive FIFO is triggered when it contains one frame, so * we want to receive one frame at a time. */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) mr |= CCSR_DMA_MR_BWC(2 * frame_size); else @@ -663,16 +624,48 @@ static int fsl_dma_prepare(struct snd_pcm_substream *substream) out_be32(&dma_channel->mr, mr); - /* - * Program the address of the DMA transfer to/from the SSI. - */ for (i = 0; i < NUM_DMA_LINKS; i++) { struct fsl_dma_link_descriptor *link = &dma_private->link[i]; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + link->count = cpu_to_be32(period_size); + + /* Even though the DMA controller supports 36-bit addressing, + * for simplicity we allow only 32-bit addresses for the audio + * buffer itself. This was enforced in fsl_dma_new() with the + * DMA mask. + * + * The snoop bit tells the DMA controller whether it should tell + * the ECM to snoop during a read or write to an address. For + * audio, we use DMA to transfer data between memory and an I/O + * device (the SSI's STX0 or SRX0 register). Snooping is only + * needed if there is a cache, so we need to snoop memory + * addresses only. For playback, that means we snoop the source + * but not the destination. For capture, we snoop the + * destination but not the source. + * + * Note that failing to snoop properly is unlikely to cause + * cache incoherency if the period size is larger than the + * size of L1 cache. This is because filling in one period will + * flush out the data for the previous period. So if you + * increased period_bytes_min to a large enough size, you might + * get more performance by not snooping, and you'll still be + * okay. + */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + link->source_addr = cpu_to_be32(temp_addr); + link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP); + link->dest_addr = cpu_to_be32(ssi_sxx_phys); - else + link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP); + } else { link->source_addr = cpu_to_be32(ssi_sxx_phys); + link->source_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP); + + link->dest_addr = cpu_to_be32(temp_addr); + link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP); + } + + temp_addr += period_size; } return 0; @@ -808,7 +801,6 @@ static struct snd_pcm_ops fsl_dma_ops = { .ioctl = snd_pcm_lib_ioctl, .hw_params = fsl_dma_hw_params, .hw_free = fsl_dma_hw_free, - .prepare = fsl_dma_prepare, .pointer = fsl_dma_pointer, }; diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index c6d6eb71dc1..6844009833d 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -400,7 +400,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, } /** - * fsl_ssi_prepare: prepare the SSI. + * fsl_ssi_hw_params - program the sample size * * Most of the SSI registers have been programmed in the startup function, * but the word length must be programmed here. Unfortunately, programming @@ -412,20 +412,19 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, * Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the * clock master. */ -static int fsl_ssi_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) +static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai) { - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; - - struct ccsr_ssi __iomem *ssi = ssi_private->ssi; + struct fsl_ssi_private *ssi_private = cpu_dai->private_data; if (substream == ssi_private->first_stream) { + struct ccsr_ssi __iomem *ssi = ssi_private->ssi; + unsigned int sample_size = + snd_pcm_format_width(params_format(hw_params)); u32 wl; /* The SSI should always be disabled at this points (SSIEN=0) */ - wl = CCSR_SSI_SxCCR_WL(snd_pcm_format_width(runtime->format)); + wl = CCSR_SSI_SxCCR_WL(sample_size); /* In synchronous mode, the SSI uses STCCR for capture */ clrsetbits_be32(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl); @@ -579,7 +578,7 @@ static struct snd_soc_dai fsl_ssi_dai_template = { }, .ops = { .startup = fsl_ssi_startup, - .prepare = fsl_ssi_prepare, + .hw_params = fsl_ssi_hw_params, .shutdown = fsl_ssi_shutdown, .trigger = fsl_ssi_trigger, .set_sysclk = fsl_ssi_set_sysclk, -- GitLab From 45bdd1c1bbac56876cb9c71649300013281e4b22 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 6 Feb 2009 16:11:25 +0100 Subject: [PATCH 1242/4982] ALSA: hda - Create beep mixer controls dynamically for Realtek codecs Create beep mixer controls dynamically for Realtek codecs instead of static arrays. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 147 +++++++++++----------------------- 1 file changed, 47 insertions(+), 100 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 5194a58fafa..3b3b483e2a9 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -255,6 +255,7 @@ struct alc_spec { struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ unsigned int num_mixers; struct snd_kcontrol_new *cap_mixer; /* capture mixer */ + unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */ const struct hda_verb *init_verbs[5]; /* initialization verbs * don't forget NULL @@ -937,7 +938,7 @@ static void alc_mic_automute(struct hda_codec *codec) HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); } #else -#define alc_mic_automute(codec) /* NOP */ +#define alc_mic_automute(codec) do {} while(0) /* NOP */ #endif /* disabled */ /* unsolicited event for HP jack sensing */ @@ -1389,8 +1390,6 @@ static struct snd_kcontrol_new alc888_base_mixer[] = { HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), { } /* end */ }; @@ -1497,8 +1496,6 @@ static struct snd_kcontrol_new alc880_three_stack_mixer[] = { HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT), HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT), - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1720,8 +1717,6 @@ static struct snd_kcontrol_new alc880_six_stack_mixer[] = { HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Channel Mode", @@ -1898,13 +1893,6 @@ static struct snd_kcontrol_new alc880_asus_w1v_mixer[] = { { } /* end */ }; -/* additional mixers to alc880_asus_mixer */ -static struct snd_kcontrol_new alc880_pcbeep_mixer[] = { - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), - { } /* end */ -}; - /* TCL S700 */ static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = { HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), @@ -1937,8 +1925,6 @@ static struct snd_kcontrol_new alc880_uniwill_mixer[] = { HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Channel Mode", @@ -2013,6 +1999,13 @@ static const char *alc_slave_sws[] = { static void alc_free_kctls(struct hda_codec *codec); +/* additional beep mixers; the actual parameters are overwritten at build */ +static struct snd_kcontrol_new alc_beep_mixer[] = { + HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT), + HDA_CODEC_MUTE("Beep Playback Switch", 0, 0, HDA_INPUT), + { } /* end */ +}; + static int alc_build_controls(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; @@ -2048,6 +2041,21 @@ static int alc_build_controls(struct hda_codec *codec) return err; } + /* create beep controls if needed */ + if (spec->beep_amp) { + struct snd_kcontrol_new *knew; + for (knew = alc_beep_mixer; knew->name; knew++) { + struct snd_kcontrol *kctl; + kctl = snd_ctl_new1(knew, codec); + if (!kctl) + return -ENOMEM; + kctl->private_value = spec->beep_amp; + err = snd_hda_ctl_add(codec, kctl); + if (err < 0) + return err; + } + } + /* if we have no master control, let's create it */ if (!spec->no_analog && !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { @@ -3812,7 +3820,7 @@ static struct alc_config_preset alc880_presets[] = { .input_mux = &alc880_capture_source, }, [ALC880_UNIWILL_DIG] = { - .mixers = { alc880_asus_mixer, alc880_pcbeep_mixer }, + .mixers = { alc880_asus_mixer }, .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs }, .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), @@ -3850,8 +3858,7 @@ static struct alc_config_preset alc880_presets[] = { .init_hook = alc880_uniwill_p53_hp_automute, }, [ALC880_FUJITSU] = { - .mixers = { alc880_fujitsu_mixer, - alc880_pcbeep_mixer, }, + .mixers = { alc880_fujitsu_mixer }, .init_verbs = { alc880_volume_init_verbs, alc880_uniwill_p53_init_verbs, alc880_beep_init_verbs }, @@ -4310,10 +4317,6 @@ static void alc880_auto_init(struct hda_codec *codec) alc_inithook(codec); } -/* - * OK, here we have finally the patch for ALC880 - */ - static void set_capture_mixer(struct alc_spec *spec) { static struct snd_kcontrol_new *caps[3] = { @@ -4325,6 +4328,13 @@ static void set_capture_mixer(struct alc_spec *spec) spec->cap_mixer = caps[spec->num_adc_nids - 1]; } +#define set_beep_amp(spec, nid, idx, dir) \ + ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir)) + +/* + * OK, here we have finally the patch for ALC880 + */ + static int patch_alc880(struct hda_codec *codec) { struct alc_spec *spec; @@ -4392,6 +4402,7 @@ static int patch_alc880(struct hda_codec *codec) } } set_capture_mixer(spec); + set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); spec->vmaster_nid = 0x0c; @@ -4541,12 +4552,6 @@ static struct snd_kcontrol_new alc260_input_mixer[] = { { } /* end */ }; -static struct snd_kcontrol_new alc260_pc_beep_mixer[] = { - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT), - { } /* end */ -}; - /* update HP, line and mono out pins according to the master switch */ static void alc260_hp_master_update(struct hda_codec *codec, hda_nid_t hp, hda_nid_t line, @@ -4738,8 +4743,6 @@ static struct snd_kcontrol_new alc260_fujitsu_mixer[] = { HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT), ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN), - HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), HDA_CODEC_VOLUME("Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT), HDA_BIND_MUTE("Speaker Playback Switch", 0x09, 2, HDA_INPUT), { } /* end */ @@ -4784,8 +4787,6 @@ static struct snd_kcontrol_new alc260_acer_mixer[] = { HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), - HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), { } /* end */ }; @@ -4803,8 +4804,6 @@ static struct snd_kcontrol_new alc260_will_mixer[] = { ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), { } /* end */ }; @@ -5308,8 +5307,6 @@ static struct snd_kcontrol_new alc260_test_mixer[] = { HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT), HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT), HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT), @@ -5737,8 +5734,7 @@ static struct snd_pci_quirk alc260_cfg_tbl[] = { static struct alc_config_preset alc260_presets[] = { [ALC260_BASIC] = { .mixers = { alc260_base_output_mixer, - alc260_input_mixer, - alc260_pc_beep_mixer }, + alc260_input_mixer }, .init_verbs = { alc260_init_verbs }, .num_dacs = ARRAY_SIZE(alc260_dac_nids), .dac_nids = alc260_dac_nids, @@ -5924,6 +5920,7 @@ static int patch_alc260(struct hda_codec *codec) } } set_capture_mixer(spec); + set_beep_amp(spec, 0x07, 0x05, HDA_INPUT); spec->vmaster_nid = 0x08; @@ -6095,8 +6092,6 @@ static struct snd_kcontrol_new alc882_base_mixer[] = { HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), { } /* end */ }; @@ -6123,8 +6118,6 @@ static struct snd_kcontrol_new alc882_w2jc_mixer[] = { HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), { } /* end */ }; @@ -6176,8 +6169,6 @@ static struct snd_kcontrol_new alc882_asus_a7m_mixer[] = { HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), { } /* end */ }; @@ -6286,8 +6277,10 @@ static struct snd_kcontrol_new alc882_macpro_mixer[] = { HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT), HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT), + /* FIXME: this looks suspicious... HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x02, HDA_INPUT), HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x02, HDA_INPUT), + */ { } /* end */ }; @@ -7153,6 +7146,7 @@ static int patch_alc882(struct hda_codec *codec) } } set_capture_mixer(spec); + set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); spec->vmaster_nid = 0x0c; @@ -7429,8 +7423,6 @@ static struct snd_kcontrol_new alc883_base_mixer[] = { HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), { } /* end */ }; @@ -7493,8 +7485,6 @@ static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = { HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), { } /* end */ }; @@ -7518,8 +7508,6 @@ static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = { HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), { } /* end */ }; @@ -7544,8 +7532,6 @@ static struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = { HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Front Mic Boost", 0x18, 0, HDA_INPUT), HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), { } /* end */ }; @@ -7569,8 +7555,6 @@ static struct snd_kcontrol_new alc883_fivestack_mixer[] = { HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), { } /* end */ }; @@ -9183,6 +9167,7 @@ static int patch_alc883(struct hda_codec *codec) if (!spec->cap_mixer) set_capture_mixer(spec); + set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); spec->vmaster_nid = 0x0c; @@ -9235,8 +9220,6 @@ static struct snd_kcontrol_new alc262_base_mixer[] = { HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), - /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), */ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), @@ -9257,8 +9240,6 @@ static struct snd_kcontrol_new alc262_hippo1_mixer[] = { HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), - /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), */ /*HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),*/ HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), { } /* end */ @@ -9367,8 +9348,6 @@ static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = { HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT), HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT), { } /* end */ @@ -9397,8 +9376,6 @@ static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = { HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), { } /* end */ }; @@ -10073,8 +10050,6 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { }, HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("PC Speaker Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Switch", 0x0b, 0x05, HDA_INPUT), HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), @@ -11085,6 +11060,7 @@ static int patch_alc262(struct hda_codec *codec) } if (!spec->cap_mixer && !spec->no_analog) set_capture_mixer(spec); + set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); spec->vmaster_nid = 0x0c; @@ -12205,8 +12181,6 @@ static struct snd_kcontrol_new alc269_base_mixer[] = { HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Beep Playback Volume", 0x0b, 0x4, HDA_INPUT), - HDA_CODEC_MUTE("Beep Playback Switch", 0x0b, 0x4, HDA_INPUT), HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), @@ -12233,8 +12207,6 @@ static struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = { HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT), - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x04, HDA_INPUT), { } }; @@ -12258,8 +12230,6 @@ static struct snd_kcontrol_new alc269_lifebook_mixer[] = { HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x0b, 0x03, HDA_INPUT), HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x0b, 0x03, HDA_INPUT), HDA_CODEC_VOLUME("Dock Mic Boost", 0x1b, 0, HDA_INPUT), - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x04, HDA_INPUT), { } }; @@ -12296,13 +12266,6 @@ static struct snd_kcontrol_new alc269_fujitsu_mixer[] = { { } /* end */ }; -/* beep control */ -static struct snd_kcontrol_new alc269_beep_mixer[] = { - HDA_CODEC_VOLUME("Beep Playback Volume", 0x0b, 0x4, HDA_INPUT), - HDA_CODEC_MUTE("Beep Playback Switch", 0x0b, 0x4, HDA_INPUT), - { } /* end */ -}; - static struct hda_verb alc269_quanta_fl1_verbs[] = { {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, @@ -12749,13 +12712,6 @@ static int alc269_parse_auto_config(struct hda_codec *codec) if (spec->kctls.list) add_mixer(spec, spec->kctls.list); - /* create a beep mixer control if the pin 0x1d isn't assigned */ - for (i = 0; i < ARRAY_SIZE(spec->autocfg.input_pins); i++) - if (spec->autocfg.input_pins[i] == 0x1d) - break; - if (i >= ARRAY_SIZE(spec->autocfg.input_pins)) - add_mixer(spec, alc269_beep_mixer); - add_verb(spec, alc269_init_verbs); spec->num_mux_defs = 1; spec->input_mux = &spec->private_imux[0]; @@ -12868,7 +12824,7 @@ static struct alc_config_preset alc269_presets[] = { .init_hook = alc269_eeepc_dmic_inithook, }, [ALC269_FUJITSU] = { - .mixers = { alc269_fujitsu_mixer, alc269_beep_mixer }, + .mixers = { alc269_fujitsu_mixer }, .cap_mixer = alc269_epc_capture_mixer, .init_verbs = { alc269_init_verbs, alc269_eeepc_dmic_init_verbs }, @@ -12955,6 +12911,7 @@ static int patch_alc269(struct hda_codec *codec) spec->capsrc_nids = alc269_capsrc_nids; if (!spec->cap_mixer) set_capture_mixer(spec); + set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); codec->patch_ops = alc_patch_ops; if (board_config == ALC269_AUTO) @@ -13205,8 +13162,6 @@ static struct snd_kcontrol_new alc861_asus_mixer[] = { static struct snd_kcontrol_new alc861_asus_laptop_mixer[] = { HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x23, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("PC Beep Playback Switch", 0x23, 0x0, HDA_OUTPUT), { } }; @@ -14049,6 +14004,8 @@ static int patch_alc861(struct hda_codec *codec) spec->stream_digital_playback = &alc861_pcm_digital_playback; spec->stream_digital_capture = &alc861_pcm_digital_capture; + set_beep_amp(spec, 0x23, 0, HDA_OUTPUT); + spec->vmaster_nid = 0x03; codec->patch_ops = alc_patch_ops; @@ -14205,9 +14162,6 @@ static struct snd_kcontrol_new alc861vd_6st_mixer[] = { HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), - { } /* end */ }; @@ -14231,9 +14185,6 @@ static struct snd_kcontrol_new alc861vd_3st_mixer[] = { HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), - { } /* end */ }; @@ -14272,8 +14223,6 @@ static struct snd_kcontrol_new alc861vd_dallas_mixer[] = { HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("PC Beep Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Beep Switch", 0x0b, 0x05, HDA_INPUT), { } /* end */ }; @@ -15015,6 +14964,7 @@ static int patch_alc861vd(struct hda_codec *codec) spec->capture_style = CAPT_MIX; set_capture_mixer(spec); + set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); spec->vmaster_nid = 0x02; @@ -15203,8 +15153,6 @@ static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = { HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), { } /* end */ }; @@ -15226,8 +15174,6 @@ static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = { HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), { } /* end */ }; @@ -16832,6 +16778,7 @@ static int patch_alc662(struct hda_codec *codec) if (!spec->cap_mixer) set_capture_mixer(spec); + set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); spec->vmaster_nid = 0x02; -- GitLab From 2678c07b07ac2076675e5d57653bdf02e9af1950 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Fri, 6 Feb 2009 20:46:06 +0530 Subject: [PATCH 1243/4982] Neither asm/types.h nor linux/types.h is required for arch/ia64/include/asm/fpu.h Signed-off-by: Jaswinder Singh Rajput --- arch/ia64/include/asm/fpu.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/ia64/include/asm/fpu.h b/arch/ia64/include/asm/fpu.h index b6395ad1500..0c26157cffa 100644 --- a/arch/ia64/include/asm/fpu.h +++ b/arch/ia64/include/asm/fpu.h @@ -6,8 +6,6 @@ * David Mosberger-Tang */ -#include - /* floating point status register: */ #define FPSR_TRAP_VD (1 << 0) /* invalid op trap disabled */ #define FPSR_TRAP_DD (1 << 1) /* denormal trap disabled */ -- GitLab From 527bdfee18ac6a4c026060c2c2b1144df9a5bf1f Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Fri, 6 Feb 2009 20:47:58 +0530 Subject: [PATCH 1244/4982] make linux/types.h as assembly safe Signed-off-by: Jaswinder Singh Rajput --- include/linux/types.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/types.h b/include/linux/types.h index 712ca53bc34..c30973ace89 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -1,6 +1,7 @@ #ifndef _LINUX_TYPES_H #define _LINUX_TYPES_H +#ifndef __ASSEMBLY__ #ifdef __KERNEL__ #define DECLARE_BITMAP(name,bits) \ @@ -212,5 +213,5 @@ struct ustat { }; #endif /* __KERNEL__ */ - +#endif /* __ASSEMBLY__ */ #endif /* _LINUX_TYPES_H */ -- GitLab From c8dcdf829ca1827a802eae841dd04de8c9d6653f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 6 Feb 2009 16:21:20 +0100 Subject: [PATCH 1245/4982] ALSA: hda - Add missing NULL check in snd_hda_create_spdif_in_ctls() Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index c9158799ccb..93412f335dc 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1984,6 +1984,8 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) } for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) { kctl = snd_ctl_new1(dig_mix, codec); + if (!kctl) + return -ENOMEM; kctl->private_value = nid; err = snd_hda_ctl_add(codec, kctl); if (err < 0) -- GitLab From c44765b8c8bfc883c9868ab7aef37d27b5b14be8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 6 Feb 2009 16:48:10 +0100 Subject: [PATCH 1246/4982] ALSA: hda - Clear codec->beep at release Clear codec->beep field in snd_hda_detach_beep_device() to be sure. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_beep.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 960fd797038..4de5bacd392 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c @@ -138,6 +138,7 @@ void snd_hda_detach_beep_device(struct hda_codec *codec) input_unregister_device(beep->dev); kfree(beep); + codec->beep = NULL; } } EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device); -- GitLab From a4ddeba9c8896cba8c6ce7a98c0b5c755c15a746 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 6 Feb 2009 17:21:09 +0100 Subject: [PATCH 1247/4982] ALSA: hda - Remove superfluous code in patch_realtek.c codec->spec is reset in the caller side. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 76934bc8b48..3d933e307b1 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3202,7 +3202,6 @@ static void alc_free(struct hda_codec *codec) alc_free_kctls(codec); kfree(spec); snd_hda_detach_beep_device(codec); - codec->spec = NULL; /* to be sure */ } #ifdef SND_HDA_NEEDS_RESUME -- GitLab From c5a4bcd0cac546c5d776af881c5e913ba4a9922d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 6 Feb 2009 17:22:05 +0100 Subject: [PATCH 1248/4982] ALSA: hda - Use digital beep for AD codecs Use digital beep instead of analog pc-beep for AD codecs. Create the beep mixer controls dynamically on demand. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_analog.c | 140 ++++++++++++++++++++++------------- 1 file changed, 88 insertions(+), 52 deletions(-) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 30399cbf819..cc02f2df251 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -27,11 +27,12 @@ #include #include "hda_codec.h" #include "hda_local.h" +#include "hda_beep.h" struct ad198x_spec { struct snd_kcontrol_new *mixers[5]; int num_mixers; - + unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */ const struct hda_verb *init_verbs[5]; /* initialization verbs * don't forget NULL termination! */ @@ -154,6 +155,16 @@ static const char *ad_slave_sws[] = { static void ad198x_free_kctls(struct hda_codec *codec); +/* additional beep mixers; the actual parameters are overwritten at build */ +static struct snd_kcontrol_new ad_beep_mixer[] = { + HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT), + HDA_CODEC_MUTE("Beep Playback Switch", 0, 0, HDA_OUTPUT), + { } /* end */ +}; + +#define set_beep_amp(spec, nid, idx, dir) \ + ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */ + static int ad198x_build_controls(struct hda_codec *codec) { struct ad198x_spec *spec = codec->spec; @@ -181,6 +192,21 @@ static int ad198x_build_controls(struct hda_codec *codec) return err; } + /* create beep controls if needed */ + if (spec->beep_amp) { + struct snd_kcontrol_new *knew; + for (knew = ad_beep_mixer; knew->name; knew++) { + struct snd_kcontrol *kctl; + kctl = snd_ctl_new1(knew, codec); + if (!kctl) + return -ENOMEM; + kctl->private_value = spec->beep_amp; + err = snd_hda_ctl_add(codec, kctl); + if (err < 0) + return err; + } + } + /* if we have no master control, let's create it */ if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { unsigned int vmaster_tlv[4]; @@ -397,7 +423,8 @@ static void ad198x_free(struct hda_codec *codec) return; ad198x_free_kctls(codec); - kfree(codec->spec); + kfree(spec); + snd_hda_detach_beep_device(codec); } static struct hda_codec_ops ad198x_patch_ops = { @@ -536,8 +563,6 @@ static struct snd_kcontrol_new ad1986a_mixers[] = { HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), @@ -601,8 +626,7 @@ static struct snd_kcontrol_new ad1986a_laptop_mixers[] = { HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), - /* HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT), + /* HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */ HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), @@ -800,8 +824,6 @@ static struct snd_kcontrol_new ad1986a_laptop_automute_mixers[] = { HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Beep Playback Volume", 0x18, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Beep Playback Switch", 0x18, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), { @@ -1026,7 +1048,7 @@ static int is_jack_available(struct hda_codec *codec, hda_nid_t nid) static int patch_ad1986a(struct hda_codec *codec) { struct ad198x_spec *spec; - int board_config; + int err, board_config; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) @@ -1034,6 +1056,13 @@ static int patch_ad1986a(struct hda_codec *codec) codec->spec = spec; + err = snd_hda_attach_beep_device(codec, 0x19); + if (err < 0) { + ad198x_free(codec); + return err; + } + set_beep_amp(spec, 0x18, 0, HDA_OUTPUT); + spec->multiout.max_channels = 6; spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids); spec->multiout.dac_nids = ad1986a_dac_nids; @@ -1213,8 +1242,6 @@ static struct snd_kcontrol_new ad1983_mixers[] = { HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x10, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x10, 1, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), @@ -1285,6 +1312,7 @@ static struct hda_amp_list ad1983_loopbacks[] = { static int patch_ad1983(struct hda_codec *codec) { struct ad198x_spec *spec; + int err; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) @@ -1292,6 +1320,13 @@ static int patch_ad1983(struct hda_codec *codec) codec->spec = spec; + err = snd_hda_attach_beep_device(codec, 0x10); + if (err < 0) { + ad198x_free(codec); + return err; + } + set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); + spec->multiout.max_channels = 2; spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids); spec->multiout.dac_nids = ad1983_dac_nids; @@ -1361,8 +1396,6 @@ static struct snd_kcontrol_new ad1981_mixers[] = { HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x0d, 1, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), @@ -1685,7 +1718,7 @@ static struct snd_pci_quirk ad1981_cfg_tbl[] = { static int patch_ad1981(struct hda_codec *codec) { struct ad198x_spec *spec; - int board_config; + int err, board_config; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) @@ -1693,6 +1726,13 @@ static int patch_ad1981(struct hda_codec *codec) codec->spec = spec; + err = snd_hda_attach_beep_device(codec, 0x10); + if (err < 0) { + ad198x_free(codec); + return err; + } + set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT); + spec->multiout.max_channels = 2; spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids); spec->multiout.dac_nids = ad1981_dac_nids; @@ -1979,9 +2019,6 @@ static struct snd_kcontrol_new ad1988_6stack_mixers2[] = { HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT), HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT), - HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), @@ -2025,9 +2062,6 @@ static struct snd_kcontrol_new ad1988_3stack_mixers2[] = { HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT), HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT), - HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), @@ -2057,9 +2091,6 @@ static struct snd_kcontrol_new ad1988_laptop_mixers[] = { HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT), HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), @@ -2919,7 +2950,7 @@ static struct snd_pci_quirk ad1988_cfg_tbl[] = { static int patch_ad1988(struct hda_codec *codec) { struct ad198x_spec *spec; - int board_config; + int err, board_config; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) @@ -2939,7 +2970,7 @@ static int patch_ad1988(struct hda_codec *codec) if (board_config == AD1988_AUTO) { /* automatic parse from the BIOS config */ - int err = ad1988_parse_auto_config(codec); + err = ad1988_parse_auto_config(codec); if (err < 0) { ad198x_free(codec); return err; @@ -2949,6 +2980,13 @@ static int patch_ad1988(struct hda_codec *codec) } } + err = snd_hda_attach_beep_device(codec, 0x10); + if (err < 0) { + ad198x_free(codec); + return err; + } + set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); + switch (board_config) { case AD1988_6STACK: case AD1988_6STACK_DIG: @@ -3105,12 +3143,6 @@ static struct snd_kcontrol_new ad1884_base_mixers[] = { HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), - /* - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x20, 0x03, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x20, 0x03, HDA_INPUT), - HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Digital Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT), - */ HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), @@ -3219,7 +3251,7 @@ static const char *ad1884_slave_vols[] = { "CD Playback Volume", "Internal Mic Playback Volume", "Docking Mic Playback Volume" - "Beep Playback Volume", + /* "Beep Playback Volume", */ "IEC958 Playback Volume", NULL }; @@ -3227,6 +3259,7 @@ static const char *ad1884_slave_vols[] = { static int patch_ad1884(struct hda_codec *codec) { struct ad198x_spec *spec; + int err; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) @@ -3234,6 +3267,13 @@ static int patch_ad1884(struct hda_codec *codec) codec->spec = spec; + err = snd_hda_attach_beep_device(codec, 0x10); + if (err < 0) { + ad198x_free(codec); + return err; + } + set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); + spec->multiout.max_channels = 2; spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids); spec->multiout.dac_nids = ad1884_dac_nids; @@ -3300,8 +3340,6 @@ static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = { HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), - HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), @@ -3358,10 +3396,6 @@ static struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = { HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT), HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT), - /* - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x20, 0x03, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x20, 0x03, HDA_INPUT), - */ HDA_CODEC_VOLUME("Line-In Boost", 0x15, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), @@ -3540,8 +3574,6 @@ static struct snd_kcontrol_new ad1884a_base_mixers[] = { HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), - HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT), @@ -3674,8 +3706,6 @@ static struct snd_kcontrol_new ad1884a_laptop_mixers[] = { HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT), HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT), HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), - HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT), @@ -3703,8 +3733,6 @@ static struct snd_kcontrol_new ad1884a_mobile_mixers[] = { HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), - HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), - HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), @@ -3815,8 +3843,6 @@ static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = { HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), - HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), - HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), @@ -3902,7 +3928,7 @@ static struct snd_pci_quirk ad1884a_cfg_tbl[] = { static int patch_ad1884a(struct hda_codec *codec) { struct ad198x_spec *spec; - int board_config; + int err, board_config; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) @@ -3910,6 +3936,13 @@ static int patch_ad1884a(struct hda_codec *codec) codec->spec = spec; + err = snd_hda_attach_beep_device(codec, 0x10); + if (err < 0) { + ad198x_free(codec); + return err; + } + set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); + spec->multiout.max_channels = 2; spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids); spec->multiout.dac_nids = ad1884a_dac_nids; @@ -4064,8 +4097,6 @@ static struct snd_kcontrol_new ad1882_loopback_mixers[] = { HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), - HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x07, HDA_INPUT), - HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x07, HDA_INPUT), { } /* end */ }; @@ -4078,8 +4109,6 @@ static struct snd_kcontrol_new ad1882a_loopback_mixers[] = { HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), - HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x07, HDA_INPUT), - HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x07, HDA_INPUT), HDA_CODEC_VOLUME("Digital Mic Boost", 0x1f, 0x0, HDA_INPUT), { } /* end */ }; @@ -4238,7 +4267,7 @@ static const char *ad1882_models[AD1986A_MODELS] = { static int patch_ad1882(struct hda_codec *codec) { struct ad198x_spec *spec; - int board_config; + int err, board_config; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) @@ -4246,6 +4275,13 @@ static int patch_ad1882(struct hda_codec *codec) codec->spec = spec; + err = snd_hda_attach_beep_device(codec, 0x10); + if (err < 0) { + ad198x_free(codec); + return err; + } + set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); + spec->multiout.max_channels = 6; spec->multiout.num_dacs = 3; spec->multiout.dac_nids = ad1882_dac_nids; -- GitLab From cfb9fb5517faa9e61c7e874fc89ef9c9253a0902 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 6 Feb 2009 17:34:03 +0100 Subject: [PATCH 1249/4982] ALSA: hda - Fix unused variable compile warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sound/pci/hda/patch_realtek.c:12693: warning: unused variable ‘i’ Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 3d933e307b1..f594a096029 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -12690,7 +12690,7 @@ static int alc269_auto_create_analog_input_ctls(struct alc_spec *spec, static int alc269_parse_auto_config(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - int i, err; + int err; static hda_nid_t alc269_ignore[] = { 0x1d, 0 }; err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, -- GitLab From a034a010f48bf49efe25098c16c16b9708ccbba5 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:30:43 -0800 Subject: [PATCH 1250/4982] x86: unify pte_none Impact: cleanup Unify and demacro pte_none. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable-2level.h | 2 -- arch/x86/include/asm/pgtable-3level.h | 5 ----- arch/x86/include/asm/pgtable.h | 5 +++++ arch/x86/include/asm/pgtable_64.h | 1 - 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/asm/pgtable-2level.h b/arch/x86/include/asm/pgtable-2level.h index e0d199fe1d8..c1774ac9da7 100644 --- a/arch/x86/include/asm/pgtable-2level.h +++ b/arch/x86/include/asm/pgtable-2level.h @@ -53,8 +53,6 @@ static inline pte_t native_ptep_get_and_clear(pte_t *xp) #define native_ptep_get_and_clear(xp) native_local_ptep_get_and_clear(xp) #endif -#define pte_none(x) (!(x).pte_low) - /* * Bits _PAGE_BIT_PRESENT, _PAGE_BIT_FILE and _PAGE_BIT_PROTNONE are taken, * split up the 29 bits of offset into this range: diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h index 447da43cddb..07e0734f620 100644 --- a/arch/x86/include/asm/pgtable-3level.h +++ b/arch/x86/include/asm/pgtable-3level.h @@ -151,11 +151,6 @@ static inline int pte_same(pte_t a, pte_t b) return a.pte_low == b.pte_low && a.pte_high == b.pte_high; } -static inline int pte_none(pte_t pte) -{ - return !pte.pte_low && !pte.pte_high; -} - /* * Bits 0, 6 and 7 are taken in the low part of the pte, * put the 32 bits of offset into the high part. diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 06bbcbd66e9..841e573b27f 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -429,6 +429,11 @@ static inline void __init paravirt_pagetable_setup_done(pgd_t *base) } #endif /* CONFIG_PARAVIRT */ +static inline int pte_none(pte_t pte) +{ + return !pte.pte; +} + #endif /* __ASSEMBLY__ */ #ifdef CONFIG_X86_32 diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index ba09289acca..5906a41e849 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -171,7 +171,6 @@ static inline int pmd_bad(pmd_t pmd) return (pmd_val(pmd) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE; } -#define pte_none(x) (!pte_val((x))) #define pte_present(x) (pte_val((x)) & (_PAGE_PRESENT | _PAGE_PROTNONE)) #define pages_to_mb(x) ((x) >> (20 - PAGE_SHIFT)) /* FIXME: is this right? */ -- GitLab From 8de01da35e9dbbb4a9d1e9d5a37df98395dfa558 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:30:44 -0800 Subject: [PATCH 1251/4982] x86: unify pte_same Impact: cleanup Unify and demacro pte_same. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable-3level.h | 6 ------ arch/x86/include/asm/pgtable.h | 6 ++++++ arch/x86/include/asm/pgtable_64.h | 2 -- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h index 07e0734f620..51832fa0474 100644 --- a/arch/x86/include/asm/pgtable-3level.h +++ b/arch/x86/include/asm/pgtable-3level.h @@ -145,12 +145,6 @@ static inline pte_t native_ptep_get_and_clear(pte_t *ptep) #define native_ptep_get_and_clear(xp) native_local_ptep_get_and_clear(xp) #endif -#define __HAVE_ARCH_PTE_SAME -static inline int pte_same(pte_t a, pte_t b) -{ - return a.pte_low == b.pte_low && a.pte_high == b.pte_high; -} - /* * Bits 0, 6 and 7 are taken in the low part of the pte, * put the 32 bits of offset into the high part. diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 841e573b27f..e929d43753c 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -434,6 +434,12 @@ static inline int pte_none(pte_t pte) return !pte.pte; } +#define __HAVE_ARCH_PTE_SAME +static inline int pte_same(pte_t a, pte_t b) +{ + return a.pte == b.pte; +} + #endif /* __ASSEMBLY__ */ #ifdef CONFIG_X86_32 diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 5906a41e849..ff2571865bf 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -134,8 +134,6 @@ static inline void native_pgd_clear(pgd_t *pgd) native_set_pgd(pgd, native_make_pgd(0)); } -#define pte_same(a, b) ((a).pte == (b).pte) - #endif /* !__ASSEMBLY__ */ #define PMD_SIZE (_AC(1, UL) << PMD_SHIFT) -- GitLab From 7c683851d96c8313586c0695b25ca41bde9f0f73 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:30:45 -0800 Subject: [PATCH 1252/4982] x86: unify pte_present Impact: cleanup Unify and demacro pte_present. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable.h | 5 +++++ arch/x86/include/asm/pgtable_32.h | 2 -- arch/x86/include/asm/pgtable_64.h | 2 -- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index e929d43753c..17fcc17d6b4 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -440,6 +440,11 @@ static inline int pte_same(pte_t a, pte_t b) return a.pte == b.pte; } +static inline int pte_present(pte_t a) +{ + return pte_flags(a) & (_PAGE_PRESENT | _PAGE_PROTNONE); +} + #endif /* __ASSEMBLY__ */ #ifdef CONFIG_X86_32 diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h index 72b020deb46..188073713fe 100644 --- a/arch/x86/include/asm/pgtable_32.h +++ b/arch/x86/include/asm/pgtable_32.h @@ -85,8 +85,6 @@ extern void set_pmd_pfn(unsigned long, unsigned long, pgprot_t); /* The boot page tables (all created as a single array) */ extern unsigned long pg0[]; -#define pte_present(x) ((x).pte_low & (_PAGE_PRESENT | _PAGE_PROTNONE)) - /* To avoid harmful races, pmd_none(x) should check only the lower when PAE */ #define pmd_none(x) (!(unsigned long)pmd_val((x))) #define pmd_present(x) (pmd_val((x)) & _PAGE_PRESENT) diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index ff2571865bf..35b8dbc068e 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -169,8 +169,6 @@ static inline int pmd_bad(pmd_t pmd) return (pmd_val(pmd) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE; } -#define pte_present(x) (pte_val((x)) & (_PAGE_PRESENT | _PAGE_PROTNONE)) - #define pages_to_mb(x) ((x) >> (20 - PAGE_SHIFT)) /* FIXME: is this right? */ /* -- GitLab From 5ba7c91341be61e0942f792c237ac067d9f32f51 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:30:48 -0800 Subject: [PATCH 1253/4982] x86: unify pud_present Impact: cleanup Unify and demacro pud_present. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable-3level.h | 5 ----- arch/x86/include/asm/pgtable.h | 7 +++++++ arch/x86/include/asm/pgtable_64.h | 1 - 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h index 51832fa0474..524bd91b995 100644 --- a/arch/x86/include/asm/pgtable-3level.h +++ b/arch/x86/include/asm/pgtable-3level.h @@ -28,11 +28,6 @@ static inline int pud_bad(pud_t pud) return (pud_val(pud) & ~(PTE_PFN_MASK | _KERNPG_TABLE | _PAGE_USER)) != 0; } -static inline int pud_present(pud_t pud) -{ - return pud_val(pud) & _PAGE_PRESENT; -} - /* Rules for using set_pte: the pte being assigned *must* be * either not present or in a state where the hardware will * not attempt to update the pte. In places where this is diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 17fcc17d6b4..c117b28df15 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -445,6 +445,13 @@ static inline int pte_present(pte_t a) return pte_flags(a) & (_PAGE_PRESENT | _PAGE_PROTNONE); } +#if PAGETABLE_LEVELS > 2 +static inline int pud_present(pud_t pud) +{ + return pud_val(pud) & _PAGE_PRESENT; +} +#endif /* PAGETABLE_LEVELS > 2 */ + #endif /* __ASSEMBLY__ */ #ifdef CONFIG_X86_32 diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 35b8dbc068e..acdc27b202c 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -194,7 +194,6 @@ static inline int pgd_large(pgd_t pgd) { return 0; } #define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)) #define pud_offset(pgd, address) \ ((pud_t *)pgd_page_vaddr(*(pgd)) + pud_index((address))) -#define pud_present(pud) (pud_val((pud)) & _PAGE_PRESENT) static inline int pud_large(pud_t pte) { -- GitLab From 9f38d7e85e914f10a875f65d283432d55a12fc27 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:30:49 -0800 Subject: [PATCH 1254/4982] x86: unify pgd_present Impact: cleanup Unify and demacro pgd_present. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable.h | 7 +++++++ arch/x86/include/asm/pgtable_64.h | 1 - 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index c117b28df15..339e49a9bb6 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -452,6 +452,13 @@ static inline int pud_present(pud_t pud) } #endif /* PAGETABLE_LEVELS > 2 */ +#if PAGETABLE_LEVELS > 3 +static inline int pgd_present(pgd_t pgd) +{ + return pgd_val(pgd) & _PAGE_PRESENT; +} +#endif /* PAGETABLE_LEVELS > 3 */ + #endif /* __ASSEMBLY__ */ #ifdef CONFIG_X86_32 diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index acdc27b202c..447634698f5 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -182,7 +182,6 @@ static inline int pmd_bad(pmd_t pmd) #define pgd_page_vaddr(pgd) \ ((unsigned long)__va((unsigned long)pgd_val((pgd)) & PTE_PFN_MASK)) #define pgd_page(pgd) (pfn_to_page(pgd_val((pgd)) >> PAGE_SHIFT)) -#define pgd_present(pgd) (pgd_val(pgd) & _PAGE_PRESENT) static inline int pgd_large(pgd_t pgd) { return 0; } #define mk_kernel_pgd(address) __pgd((address) | _KERNPG_TABLE) -- GitLab From 649e8ef60fac0a2f6960cdb090d73e78717ac065 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:30:50 -0800 Subject: [PATCH 1255/4982] x86: unify pmd_present Impact: cleanup Unify and demacro pmd_present. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable.h | 5 +++++ arch/x86/include/asm/pgtable_32.h | 1 - arch/x86/include/asm/pgtable_64.h | 1 - 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 339e49a9bb6..147d3f097ab 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -445,6 +445,11 @@ static inline int pte_present(pte_t a) return pte_flags(a) & (_PAGE_PRESENT | _PAGE_PROTNONE); } +static inline int pmd_present(pmd_t pmd) +{ + return pmd_val(pmd) & _PAGE_PRESENT; +} + #if PAGETABLE_LEVELS > 2 static inline int pud_present(pud_t pud) { diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h index 188073713fe..f35160730b6 100644 --- a/arch/x86/include/asm/pgtable_32.h +++ b/arch/x86/include/asm/pgtable_32.h @@ -87,7 +87,6 @@ extern unsigned long pg0[]; /* To avoid harmful races, pmd_none(x) should check only the lower when PAE */ #define pmd_none(x) (!(unsigned long)pmd_val((x))) -#define pmd_present(x) (pmd_val((x)) & _PAGE_PRESENT) #define pmd_bad(x) ((pmd_val(x) & (PTE_FLAGS_MASK & ~_PAGE_USER)) != _KERNPG_TABLE) #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 447634698f5..471b3058f3d 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -208,7 +208,6 @@ static inline int pud_large(pud_t pte) #define pmd_offset(dir, address) ((pmd_t *)pud_page_vaddr(*(dir)) + \ pmd_index(address)) #define pmd_none(x) (!pmd_val((x))) -#define pmd_present(x) (pmd_val((x)) & _PAGE_PRESENT) #define pfn_pmd(nr, prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val((prot)))) #define pmd_pfn(x) ((pmd_val((x)) & __PHYSICAL_MASK) >> PAGE_SHIFT) -- GitLab From 4fea801ac95d6534a93aa01d3ac62be163d845af Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:30:51 -0800 Subject: [PATCH 1256/4982] x86: unify pmd_none Impact: cleanup Unify and demacro pmd_none. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable.h | 7 +++++++ arch/x86/include/asm/pgtable_32.h | 2 -- arch/x86/include/asm/pgtable_64.h | 1 - 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 147d3f097ab..2f38bbee77e 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -450,6 +450,13 @@ static inline int pmd_present(pmd_t pmd) return pmd_val(pmd) & _PAGE_PRESENT; } +static inline int pmd_none(pmd_t pmd) +{ + /* Only check low word on 32-bit platforms, since it might be + out of sync with upper half. */ + return !(unsigned long)native_pmd_val(pmd); +} + #if PAGETABLE_LEVELS > 2 static inline int pud_present(pud_t pud) { diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h index f35160730b6..26e73569223 100644 --- a/arch/x86/include/asm/pgtable_32.h +++ b/arch/x86/include/asm/pgtable_32.h @@ -85,8 +85,6 @@ extern void set_pmd_pfn(unsigned long, unsigned long, pgprot_t); /* The boot page tables (all created as a single array) */ extern unsigned long pg0[]; -/* To avoid harmful races, pmd_none(x) should check only the lower when PAE */ -#define pmd_none(x) (!(unsigned long)pmd_val((x))) #define pmd_bad(x) ((pmd_val(x) & (PTE_FLAGS_MASK & ~_PAGE_USER)) != _KERNPG_TABLE) #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 471b3058f3d..f3ad8943324 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -207,7 +207,6 @@ static inline int pud_large(pud_t pte) #define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) #define pmd_offset(dir, address) ((pmd_t *)pud_page_vaddr(*(dir)) + \ pmd_index(address)) -#define pmd_none(x) (!pmd_val((x))) #define pfn_pmd(nr, prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val((prot)))) #define pmd_pfn(x) ((pmd_val((x)) & __PHYSICAL_MASK) >> PAGE_SHIFT) -- GitLab From c5f040b12b2381591932a007432e7ed86b3f2796 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:30:52 -0800 Subject: [PATCH 1257/4982] x86: unify pgd_page_vaddr Impact: cleanup Unify and demacro pgd_page_vaddr. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable.h | 5 +++++ arch/x86/include/asm/pgtable_64.h | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 2f38bbee77e..cca4321e076 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -469,6 +469,11 @@ static inline int pgd_present(pgd_t pgd) { return pgd_val(pgd) & _PAGE_PRESENT; } + +static inline unsigned long pgd_page_vaddr(pgd_t pgd) +{ + return (unsigned long)__va((unsigned long)pgd_val(pgd) & PTE_PFN_MASK); +} #endif /* PAGETABLE_LEVELS > 3 */ #endif /* __ASSEMBLY__ */ diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index f3ad8943324..4f8dbb99b69 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -179,8 +179,6 @@ static inline int pmd_bad(pmd_t pmd) /* * Level 4 access. */ -#define pgd_page_vaddr(pgd) \ - ((unsigned long)__va((unsigned long)pgd_val((pgd)) & PTE_PFN_MASK)) #define pgd_page(pgd) (pfn_to_page(pgd_val((pgd)) >> PAGE_SHIFT)) static inline int pgd_large(pgd_t pgd) { return 0; } #define mk_kernel_pgd(address) __pgd((address) | _KERNPG_TABLE) -- GitLab From 6fff47e3ac5e17f7e164ac4ff9ea29aba3c54d73 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:30:53 -0800 Subject: [PATCH 1258/4982] x86: unify pud_page_vaddr Impact: cleanup Unify and demacro pud_page_vaddr. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable-3level.h | 3 --- arch/x86/include/asm/pgtable.h | 5 +++++ arch/x86/include/asm/pgtable_64.h | 2 -- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h index 524bd91b995..542616ac192 100644 --- a/arch/x86/include/asm/pgtable-3level.h +++ b/arch/x86/include/asm/pgtable-3level.h @@ -117,9 +117,6 @@ static inline void pud_clear(pud_t *pudp) #define pud_page(pud) pfn_to_page(pud_val(pud) >> PAGE_SHIFT) -#define pud_page_vaddr(pud) ((unsigned long) __va(pud_val(pud) & PTE_PFN_MASK)) - - /* Find an entry in the second-level page table.. */ #define pmd_offset(pud, address) ((pmd_t *)pud_page_vaddr(*(pud)) + \ pmd_index(address)) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index cca4321e076..4638b4af675 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -462,6 +462,11 @@ static inline int pud_present(pud_t pud) { return pud_val(pud) & _PAGE_PRESENT; } + +static inline unsigned long pud_page_vaddr(pud_t pud) +{ + return (unsigned long)__va((unsigned long)pud_val(pud) & PTE_PFN_MASK); +} #endif /* PAGETABLE_LEVELS > 2 */ #if PAGETABLE_LEVELS > 3 diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 4f8dbb99b69..9875e40c058 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -185,8 +185,6 @@ static inline int pgd_large(pgd_t pgd) { return 0; } /* PUD - Level3 access */ /* to find an entry in a page-table-directory. */ -#define pud_page_vaddr(pud) \ - ((unsigned long)__va(pud_val((pud)) & PHYSICAL_PAGE_MASK)) #define pud_page(pud) (pfn_to_page(pud_val((pud)) >> PAGE_SHIFT)) #define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)) #define pud_offset(pgd, address) \ -- GitLab From aca159dbb13a5221819d5b3849b8c013f4829e9e Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:30:54 -0800 Subject: [PATCH 1259/4982] x86: include pgtable_SIZE.h earlier We'll need the definitions sooner. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable.h | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 4638b4af675..bd38feb3492 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -429,6 +429,16 @@ static inline void __init paravirt_pagetable_setup_done(pgd_t *base) } #endif /* CONFIG_PARAVIRT */ +#endif /* __ASSEMBLY__ */ + +#ifdef CONFIG_X86_32 +# include "pgtable_32.h" +#else +# include "pgtable_64.h" +#endif + +#ifndef __ASSEMBLY__ + static inline int pte_none(pte_t pte) { return !pte.pte; @@ -483,12 +493,6 @@ static inline unsigned long pgd_page_vaddr(pgd_t pgd) #endif /* __ASSEMBLY__ */ -#ifdef CONFIG_X86_32 -# include "pgtable_32.h" -#else -# include "pgtable_64.h" -#endif - /* * the pgd page can be thought of an array like this: pgd_t[PTRS_PER_PGD] * -- GitLab From f476961cb16312fe4cb80b2b457ef9acf220a7fc Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:30:55 -0800 Subject: [PATCH 1260/4982] x86: unify pud_page Impact: cleanup Unify and demacro pud_page. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable-3level.h | 2 -- arch/x86/include/asm/pgtable.h | 6 ++++++ arch/x86/include/asm/pgtable_64.h | 1 - 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h index 542616ac192..28ba09ac230 100644 --- a/arch/x86/include/asm/pgtable-3level.h +++ b/arch/x86/include/asm/pgtable-3level.h @@ -115,8 +115,6 @@ static inline void pud_clear(pud_t *pudp) write_cr3(pgd); } -#define pud_page(pud) pfn_to_page(pud_val(pud) >> PAGE_SHIFT) - /* Find an entry in the second-level page table.. */ #define pmd_offset(pud, address) ((pmd_t *)pud_page_vaddr(*(pud)) + \ pmd_index(address)) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index bd38feb3492..a871ae55a5c 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -438,6 +438,7 @@ static inline void __init paravirt_pagetable_setup_done(pgd_t *base) #endif #ifndef __ASSEMBLY__ +#include static inline int pte_none(pte_t pte) { @@ -477,6 +478,11 @@ static inline unsigned long pud_page_vaddr(pud_t pud) { return (unsigned long)__va((unsigned long)pud_val(pud) & PTE_PFN_MASK); } + +static inline struct page *pud_page(pud_t pud) +{ + return pfn_to_page(pud_val(pud) >> PAGE_SHIFT); +} #endif /* PAGETABLE_LEVELS > 2 */ #if PAGETABLE_LEVELS > 3 diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 9875e40c058..7edacc7ec89 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -185,7 +185,6 @@ static inline int pgd_large(pgd_t pgd) { return 0; } /* PUD - Level3 access */ /* to find an entry in a page-table-directory. */ -#define pud_page(pud) (pfn_to_page(pud_val((pud)) >> PAGE_SHIFT)) #define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)) #define pud_offset(pgd, address) \ ((pud_t *)pgd_page_vaddr(*(pgd)) + pud_index((address))) -- GitLab From 777cba16aac5a1096db0b936912eb7fd06fb0cc5 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:30:56 -0800 Subject: [PATCH 1261/4982] x86: unify pgd_page Impact: cleanup Unify and demacro pgd_page. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable.h | 5 +++++ arch/x86/include/asm/pgtable_64.h | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index a871ae55a5c..c1a36dd1e59 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -495,6 +495,11 @@ static inline unsigned long pgd_page_vaddr(pgd_t pgd) { return (unsigned long)__va((unsigned long)pgd_val(pgd) & PTE_PFN_MASK); } + +static inline struct page *pgd_page(pgd_t pgd) +{ + return pfn_to_page(pgd_val(pgd) >> PAGE_SHIFT); +} #endif /* PAGETABLE_LEVELS > 3 */ #endif /* __ASSEMBLY__ */ diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 7edacc7ec89..02477ad40fc 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -179,7 +179,6 @@ static inline int pmd_bad(pmd_t pmd) /* * Level 4 access. */ -#define pgd_page(pgd) (pfn_to_page(pgd_val((pgd)) >> PAGE_SHIFT)) static inline int pgd_large(pgd_t pgd) { return 0; } #define mk_kernel_pgd(address) __pgd((address) | _KERNPG_TABLE) -- GitLab From 7cfb81024bc1dbe8ad2bf5affd58a6a7ad4172ba Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:30:57 -0800 Subject: [PATCH 1262/4982] x86: unify pud_index Impact: cleanup Unify and demacro pud_index. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable.h | 6 ++++++ arch/x86/include/asm/pgtable_64.h | 2 -- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index c1a36dd1e59..a51a97ade63 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -500,6 +500,12 @@ static inline struct page *pgd_page(pgd_t pgd) { return pfn_to_page(pgd_val(pgd) >> PAGE_SHIFT); } + +/* to find an entry in a page-table-directory. */ +static inline unsigned pud_index(unsigned long address) +{ + return (address >> PUD_SHIFT) & (PTRS_PER_PUD - 1); +} #endif /* PAGETABLE_LEVELS > 3 */ #endif /* __ASSEMBLY__ */ diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 02477ad40fc..c17c30f5751 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -183,8 +183,6 @@ static inline int pgd_large(pgd_t pgd) { return 0; } #define mk_kernel_pgd(address) __pgd((address) | _KERNPG_TABLE) /* PUD - Level3 access */ -/* to find an entry in a page-table-directory. */ -#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)) #define pud_offset(pgd, address) \ ((pud_t *)pgd_page_vaddr(*(pgd)) + pud_index((address))) -- GitLab From 3d081b1812bd4de2bbef58c6d598ddf45493010e Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:30:58 -0800 Subject: [PATCH 1263/4982] x86: unify pud_offset Impact: cleanup Unify and demacro pud_offset. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable.h | 5 +++++ arch/x86/include/asm/pgtable_64.h | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index a51a97ade63..decccb0a641 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -506,6 +506,11 @@ static inline unsigned pud_index(unsigned long address) { return (address >> PUD_SHIFT) & (PTRS_PER_PUD - 1); } + +static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address) +{ + return (pud_t *)pgd_page_vaddr(*pgd) + pud_index(address); +} #endif /* PAGETABLE_LEVELS > 3 */ #endif /* __ASSEMBLY__ */ diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index c17c30f5751..958dc1e7335 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -183,8 +183,6 @@ static inline int pgd_large(pgd_t pgd) { return 0; } #define mk_kernel_pgd(address) __pgd((address) | _KERNPG_TABLE) /* PUD - Level3 access */ -#define pud_offset(pgd, address) \ - ((pud_t *)pgd_page_vaddr(*(pgd)) + pud_index((address))) static inline int pud_large(pud_t pte) { -- GitLab From 3ffb3564cd3cd59de8a0d74430ffe2d43ae11f19 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:30:59 -0800 Subject: [PATCH 1264/4982] x86: unify pmd_page_vaddr Impact: cleanup Unify and demacro pmd_page_vaddr. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable.h | 5 +++++ arch/x86/include/asm/pgtable_32.h | 3 --- arch/x86/include/asm/pgtable_64.h | 1 - 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index decccb0a641..3789c05bf30 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -468,6 +468,11 @@ static inline int pmd_none(pmd_t pmd) return !(unsigned long)native_pmd_val(pmd); } +static inline unsigned long pmd_page_vaddr(pmd_t pmd) +{ + return (unsigned long)__va(pmd_val(pmd) & PTE_PFN_MASK); +} + #if PAGETABLE_LEVELS > 2 static inline int pud_present(pud_t pud) { diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h index 26e73569223..f7f7e297a0a 100644 --- a/arch/x86/include/asm/pgtable_32.h +++ b/arch/x86/include/asm/pgtable_32.h @@ -126,9 +126,6 @@ static inline int pud_large(pud_t pud) { return 0; } #define pmd_page(pmd) (pfn_to_page(pmd_val((pmd)) >> PAGE_SHIFT)) -#define pmd_page_vaddr(pmd) \ - ((unsigned long)__va(pmd_val((pmd)) & PTE_PFN_MASK)) - #if defined(CONFIG_HIGHPTE) #define pte_offset_map(dir, address) \ ((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), KM_PTE0) + \ diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 958dc1e7335..7a510e8a878 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -191,7 +191,6 @@ static inline int pud_large(pud_t pte) } /* PMD - Level 2 access */ -#define pmd_page_vaddr(pmd) ((unsigned long) __va(pmd_val((pmd)) & PTE_PFN_MASK)) #define pmd_page(pmd) (pfn_to_page(pmd_val((pmd)) >> PAGE_SHIFT)) #define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) -- GitLab From 20063ca4eb26d4b10f01d59925deea4aeee415e8 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:31:00 -0800 Subject: [PATCH 1265/4982] x86: unify pmd_page Impact: cleanup Unify and demacro pmd_page. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable.h | 5 +++++ arch/x86/include/asm/pgtable_32.h | 2 -- arch/x86/include/asm/pgtable_64.h | 2 -- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 3789c05bf30..38330d6288f 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -473,6 +473,11 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd) return (unsigned long)__va(pmd_val(pmd) & PTE_PFN_MASK); } +static inline struct page *pmd_page(pmd_t pmd) +{ + return pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT); +} + #if PAGETABLE_LEVELS > 2 static inline int pud_present(pud_t pud) { diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h index f7f7e297a0a..8714110b4a7 100644 --- a/arch/x86/include/asm/pgtable_32.h +++ b/arch/x86/include/asm/pgtable_32.h @@ -124,8 +124,6 @@ static inline int pud_large(pud_t pud) { return 0; } #define pte_offset_kernel(dir, address) \ ((pte_t *)pmd_page_vaddr(*(dir)) + pte_index((address))) -#define pmd_page(pmd) (pfn_to_page(pmd_val((pmd)) >> PAGE_SHIFT)) - #if defined(CONFIG_HIGHPTE) #define pte_offset_map(dir, address) \ ((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), KM_PTE0) + \ diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 7a510e8a878..97f24d2d60d 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -191,8 +191,6 @@ static inline int pud_large(pud_t pte) } /* PMD - Level 2 access */ -#define pmd_page(pmd) (pfn_to_page(pmd_val((pmd)) >> PAGE_SHIFT)) - #define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) #define pmd_offset(dir, address) ((pmd_t *)pud_page_vaddr(*(dir)) + \ pmd_index(address)) -- GitLab From e24d7eee0beda24504bf6a4aa03be68328557475 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:31:01 -0800 Subject: [PATCH 1266/4982] x86: unify pmd_index Impact: cleanup Unify and demacro pmd_index. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable.h | 11 +++++++++++ arch/x86/include/asm/pgtable_32.h | 9 --------- arch/x86/include/asm/pgtable_64.h | 1 - 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 38330d6288f..4ec24b6d099 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -478,6 +478,17 @@ static inline struct page *pmd_page(pmd_t pmd) return pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT); } +/* + * the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD] + * + * this macro returns the index of the entry in the pmd page which would + * control the given virtual address + */ +static inline unsigned pmd_index(unsigned long address) +{ + return (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1); +} + #if PAGETABLE_LEVELS > 2 static inline int pud_present(pud_t pud) { diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h index 8714110b4a7..40b066215bb 100644 --- a/arch/x86/include/asm/pgtable_32.h +++ b/arch/x86/include/asm/pgtable_32.h @@ -104,15 +104,6 @@ extern unsigned long pg0[]; static inline int pud_large(pud_t pud) { return 0; } -/* - * the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD] - * - * this macro returns the index of the entry in the pmd page which would - * control the given virtual address - */ -#define pmd_index(address) \ - (((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) - /* * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE] * diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 97f24d2d60d..15f42d6ee2f 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -191,7 +191,6 @@ static inline int pud_large(pud_t pte) } /* PMD - Level 2 access */ -#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) #define pmd_offset(dir, address) ((pmd_t *)pud_page_vaddr(*(dir)) + \ pmd_index(address)) #define pfn_pmd(nr, prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val((prot)))) -- GitLab From 01ade20d5a22e6ef002cbb751dddc3a01a78f998 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:31:02 -0800 Subject: [PATCH 1267/4982] x86: unify pmd_offset Impact: cleanup Unify and demacro pmd_offset. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable-3level.h | 4 ---- arch/x86/include/asm/pgtable.h | 6 ++++++ arch/x86/include/asm/pgtable_64.h | 2 -- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h index 28ba09ac230..7ad9d05710b 100644 --- a/arch/x86/include/asm/pgtable-3level.h +++ b/arch/x86/include/asm/pgtable-3level.h @@ -115,10 +115,6 @@ static inline void pud_clear(pud_t *pudp) write_cr3(pgd); } -/* Find an entry in the second-level page table.. */ -#define pmd_offset(pud, address) ((pmd_t *)pud_page_vaddr(*(pud)) + \ - pmd_index(address)) - #ifdef CONFIG_SMP static inline pte_t native_ptep_get_and_clear(pte_t *ptep) { diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 4ec24b6d099..a7dbb05075d 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -504,6 +504,12 @@ static inline struct page *pud_page(pud_t pud) { return pfn_to_page(pud_val(pud) >> PAGE_SHIFT); } + +/* Find an entry in the second-level page table.. */ +static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address) +{ + return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(address); +} #endif /* PAGETABLE_LEVELS > 2 */ #if PAGETABLE_LEVELS > 3 diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 15f42d6ee2f..78269656cf0 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -191,8 +191,6 @@ static inline int pud_large(pud_t pte) } /* PMD - Level 2 access */ -#define pmd_offset(dir, address) ((pmd_t *)pud_page_vaddr(*(dir)) + \ - pmd_index(address)) #define pfn_pmd(nr, prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val((prot)))) #define pmd_pfn(x) ((pmd_val((x)) & __PHYSICAL_MASK) >> PAGE_SHIFT) -- GitLab From bd44d64db1db6acf2dea9ba130b8cb0a54e1dabd Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:31:03 -0800 Subject: [PATCH 1268/4982] x86: remove redundant pfn_pmd definition Impact: cleanup It's already defined in pgtable.h Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable_64.h | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 78269656cf0..6cc4133705b 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -191,7 +191,6 @@ static inline int pud_large(pud_t pte) } /* PMD - Level 2 access */ -#define pfn_pmd(nr, prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val((prot)))) #define pmd_pfn(x) ((pmd_val((x)) & __PHYSICAL_MASK) >> PAGE_SHIFT) #define pte_to_pgoff(pte) ((pte_val((pte)) & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT) -- GitLab From 3180fba0eec0d14e4ac8183a90d643d0d3383c75 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:31:04 -0800 Subject: [PATCH 1269/4982] x86: unify pmd_pfn Impact: cleanup Unify and demacro pmd_pfn. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable.h | 5 +++++ arch/x86/include/asm/pgtable_64.h | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index a7dbb05075d..532144c2f1c 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -510,6 +510,11 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address) { return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(address); } + +static inline unsigned long pmd_pfn(pmd_t pmd) +{ + return (pmd_val(pmd) & PTE_PFN_MASK) >> PAGE_SHIFT; +} #endif /* PAGETABLE_LEVELS > 2 */ #if PAGETABLE_LEVELS > 3 diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 6cc4133705b..279ddc6a4eb 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -191,8 +191,6 @@ static inline int pud_large(pud_t pte) } /* PMD - Level 2 access */ -#define pmd_pfn(x) ((pmd_val((x)) & __PHYSICAL_MASK) >> PAGE_SHIFT) - #define pte_to_pgoff(pte) ((pte_val((pte)) & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT) #define pgoff_to_pte(off) ((pte_t) { .pte = ((off) << PAGE_SHIFT) | \ _PAGE_FILE }) -- GitLab From 97e2817d3423d753fd2f80ea936a370032846382 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:31:05 -0800 Subject: [PATCH 1270/4982] x86: unify pmd_pfn Impact: cleanup Unify pmd_pfn. Unfortunately it can't be demacroed because it has a cyclic dependency on linux/mm.h:page_to_nid(). Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable.h | 9 +++++++++ arch/x86/include/asm/pgtable_32.h | 7 ------- arch/x86/include/asm/pgtable_64.h | 3 --- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 532144c2f1c..49b5cff78c2 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -489,6 +489,15 @@ static inline unsigned pmd_index(unsigned long address) return (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1); } +/* + * Conversion functions: convert a page and protection to a page entry, + * and a page entry and page directory to the page they refer to. + * + * (Currently stuck as a macro because of indirect forward reference + * to linux/mm.h:page_to_nid()) + */ +#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) + #if PAGETABLE_LEVELS > 2 static inline int pud_present(pud_t pud) { diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h index 40b066215bb..6335be843c1 100644 --- a/arch/x86/include/asm/pgtable_32.h +++ b/arch/x86/include/asm/pgtable_32.h @@ -95,13 +95,6 @@ extern unsigned long pg0[]; # include #endif -/* - * Conversion functions: convert a page and protection to a page entry, - * and a page entry and page directory to the page they refer to. - */ -#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) - - static inline int pud_large(pud_t pud) { return 0; } /* diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 279ddc6a4eb..adce05628a0 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -198,9 +198,6 @@ static inline int pud_large(pud_t pte) /* PTE - Level 1 access. */ -/* page, protection -> pte */ -#define mk_pte(page, pgprot) pfn_pte(page_to_pfn((page)), (pgprot)) - #define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) #define pte_offset_kernel(dir, address) ((pte_t *) pmd_page_vaddr(*(dir)) + \ pte_index((address))) -- GitLab From 346309cff6127a38731cf102de3413a562700b84 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:31:06 -0800 Subject: [PATCH 1271/4982] x86: unify pte_index Impact: cleanup Unify and demacro pte_index. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable.h | 11 +++++++++++ arch/x86/include/asm/pgtable_32.h | 8 -------- arch/x86/include/asm/pgtable_64.h | 1 - 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 49b5cff78c2..10a8c2e5178 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -498,6 +498,17 @@ static inline unsigned pmd_index(unsigned long address) */ #define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) +/* + * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE] + * + * this function returns the index of the entry in the pte page which would + * control the given virtual address + */ +static inline unsigned pte_index(unsigned long address) +{ + return (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); +} + #if PAGETABLE_LEVELS > 2 static inline int pud_present(pud_t pud) { diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h index 6335be843c1..00d298e14a8 100644 --- a/arch/x86/include/asm/pgtable_32.h +++ b/arch/x86/include/asm/pgtable_32.h @@ -97,14 +97,6 @@ extern unsigned long pg0[]; static inline int pud_large(pud_t pud) { return 0; } -/* - * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE] - * - * this macro returns the index of the entry in the pte page which would - * control the given virtual address - */ -#define pte_index(address) \ - (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) #define pte_offset_kernel(dir, address) \ ((pte_t *)pmd_page_vaddr(*(dir)) + pte_index((address))) diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index adce05628a0..e7321bc8aa8 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -198,7 +198,6 @@ static inline int pud_large(pud_t pte) /* PTE - Level 1 access. */ -#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) #define pte_offset_kernel(dir, address) ((pte_t *) pmd_page_vaddr(*(dir)) + \ pte_index((address))) -- GitLab From 3fbc2444f465710cdf0c832461a6a14338437453 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:31:07 -0800 Subject: [PATCH 1272/4982] x86: unify pte_offset_kernel Impact: cleanup Unify and demacro pte_offset_kernel. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable.h | 5 +++++ arch/x86/include/asm/pgtable_32.h | 3 --- arch/x86/include/asm/pgtable_64.h | 3 --- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 10a8c2e5178..c61b37af1f2 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -509,6 +509,11 @@ static inline unsigned pte_index(unsigned long address) return (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); } +static inline pte_t *pte_offset_kernel(pmd_t *pmd, unsigned long address) +{ + return (pte_t *)pmd_page_vaddr(*pmd) + pte_index(address); +} + #if PAGETABLE_LEVELS > 2 static inline int pud_present(pud_t pud) { diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h index 00d298e14a8..133fc4e4529 100644 --- a/arch/x86/include/asm/pgtable_32.h +++ b/arch/x86/include/asm/pgtable_32.h @@ -97,9 +97,6 @@ extern unsigned long pg0[]; static inline int pud_large(pud_t pud) { return 0; } -#define pte_offset_kernel(dir, address) \ - ((pte_t *)pmd_page_vaddr(*(dir)) + pte_index((address))) - #if defined(CONFIG_HIGHPTE) #define pte_offset_map(dir, address) \ ((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), KM_PTE0) + \ diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index e7321bc8aa8..a8bfb75c76a 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -198,9 +198,6 @@ static inline int pud_large(pud_t pte) /* PTE - Level 1 access. */ -#define pte_offset_kernel(dir, address) ((pte_t *) pmd_page_vaddr(*(dir)) + \ - pte_index((address))) - /* x86-64 always has all page tables mapped. */ #define pte_offset_map(dir, address) pte_offset_kernel((dir), (address)) #define pte_offset_map_nested(dir, address) pte_offset_kernel((dir), (address)) -- GitLab From 3f6cbef1d7f474d16f3a824c6d2910d930778fbd Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:31:08 -0800 Subject: [PATCH 1273/4982] x86: unify pud_large Impact: cleanup Unify and demacro pud_large. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable.h | 6 ++++++ arch/x86/include/asm/pgtable_32.h | 2 -- arch/x86/include/asm/pgtable_64.h | 6 ------ 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index c61b37af1f2..0c734e2a90c 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -540,6 +540,12 @@ static inline unsigned long pmd_pfn(pmd_t pmd) { return (pmd_val(pmd) & PTE_PFN_MASK) >> PAGE_SHIFT; } + +static inline int pud_large(pud_t pud) +{ + return (pud_val(pud) & (_PAGE_PSE | _PAGE_PRESENT)) == + (_PAGE_PSE | _PAGE_PRESENT); +} #endif /* PAGETABLE_LEVELS > 2 */ #if PAGETABLE_LEVELS > 3 diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h index 133fc4e4529..ad7830bdc9a 100644 --- a/arch/x86/include/asm/pgtable_32.h +++ b/arch/x86/include/asm/pgtable_32.h @@ -95,8 +95,6 @@ extern unsigned long pg0[]; # include #endif -static inline int pud_large(pud_t pud) { return 0; } - #if defined(CONFIG_HIGHPTE) #define pte_offset_map(dir, address) \ ((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), KM_PTE0) + \ diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index a8bfb75c76a..a85ac14df35 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -184,12 +184,6 @@ static inline int pgd_large(pgd_t pgd) { return 0; } /* PUD - Level3 access */ -static inline int pud_large(pud_t pte) -{ - return (pud_val(pte) & (_PAGE_PSE | _PAGE_PRESENT)) == - (_PAGE_PSE | _PAGE_PRESENT); -} - /* PMD - Level 2 access */ #define pte_to_pgoff(pte) ((pte_val((pte)) & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT) #define pgoff_to_pte(off) ((pte_t) { .pte = ((off) << PAGE_SHIFT) | \ -- GitLab From 30f103167fcf2b08de64f5f37ece6bfff7392290 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:31:09 -0800 Subject: [PATCH 1274/4982] x86: unify pgd_bad Impact: cleanup Unify and demacro pgd_bad. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable.h | 5 +++++ arch/x86/include/asm/pgtable_64.h | 5 ----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 0c734e2a90c..ebcb60e6a96 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -574,6 +574,11 @@ static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address) { return (pud_t *)pgd_page_vaddr(*pgd) + pud_index(address); } + +static inline int pgd_bad(pgd_t pgd) +{ + return (pgd_val(pgd) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE; +} #endif /* PAGETABLE_LEVELS > 3 */ #endif /* __ASSEMBLY__ */ diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index a85ac14df35..1dfc44932f6 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -154,11 +154,6 @@ static inline void native_pgd_clear(pgd_t *pgd) #ifndef __ASSEMBLY__ -static inline int pgd_bad(pgd_t pgd) -{ - return (pgd_val(pgd) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE; -} - static inline int pud_bad(pud_t pud) { return (pud_val(pud) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE; -- GitLab From a61bb29af47b0e4052566d25f3391894306a23fd Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:31:10 -0800 Subject: [PATCH 1275/4982] x86: unify pgd_bad Impact: cleanup Unify and demacro pgd_bad. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable-3level.h | 5 ----- arch/x86/include/asm/pgtable.h | 5 +++++ arch/x86/include/asm/pgtable_64.h | 5 ----- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h index 7ad9d05710b..b92524eec20 100644 --- a/arch/x86/include/asm/pgtable-3level.h +++ b/arch/x86/include/asm/pgtable-3level.h @@ -23,11 +23,6 @@ static inline int pud_none(pud_t pud) return pud_val(pud) == 0; } -static inline int pud_bad(pud_t pud) -{ - return (pud_val(pud) & ~(PTE_PFN_MASK | _KERNPG_TABLE | _PAGE_USER)) != 0; -} - /* Rules for using set_pte: the pte being assigned *must* be * either not present or in a state where the hardware will * not attempt to update the pte. In places where this is diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index ebcb60e6a96..38882f6cc82 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -546,6 +546,11 @@ static inline int pud_large(pud_t pud) return (pud_val(pud) & (_PAGE_PSE | _PAGE_PRESENT)) == (_PAGE_PSE | _PAGE_PRESENT); } + +static inline int pud_bad(pud_t pud) +{ + return (pud_val(pud) & ~(PTE_PFN_MASK | _KERNPG_TABLE | _PAGE_USER)) != 0; +} #endif /* PAGETABLE_LEVELS > 2 */ #if PAGETABLE_LEVELS > 3 diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 1dfc44932f6..fe8be33df3d 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -154,11 +154,6 @@ static inline void native_pgd_clear(pgd_t *pgd) #ifndef __ASSEMBLY__ -static inline int pud_bad(pud_t pud) -{ - return (pud_val(pud) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE; -} - static inline int pmd_bad(pmd_t pmd) { return (pmd_val(pmd) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE; -- GitLab From 99510238bb428091e7caba020bc5e18b5f30b619 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:31:11 -0800 Subject: [PATCH 1276/4982] x86: unify pmd_bad Impact: cleanup Unify and demacro pmd_bad. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable.h | 5 +++++ arch/x86/include/asm/pgtable_32.h | 2 -- arch/x86/include/asm/pgtable_64.h | 5 ----- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 38882f6cc82..72bf53ef60b 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -514,6 +514,11 @@ static inline pte_t *pte_offset_kernel(pmd_t *pmd, unsigned long address) return (pte_t *)pmd_page_vaddr(*pmd) + pte_index(address); } +static inline int pmd_bad(pmd_t pmd) +{ + return (pmd_val(pmd) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE; +} + #if PAGETABLE_LEVELS > 2 static inline int pud_present(pud_t pud) { diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h index ad7830bdc9a..5362632df75 100644 --- a/arch/x86/include/asm/pgtable_32.h +++ b/arch/x86/include/asm/pgtable_32.h @@ -85,8 +85,6 @@ extern void set_pmd_pfn(unsigned long, unsigned long, pgprot_t); /* The boot page tables (all created as a single array) */ extern unsigned long pg0[]; -#define pmd_bad(x) ((pmd_val(x) & (PTE_FLAGS_MASK & ~_PAGE_USER)) != _KERNPG_TABLE) - #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) #ifdef CONFIG_X86_PAE diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index fe8be33df3d..d230e28a5f3 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -154,11 +154,6 @@ static inline void native_pgd_clear(pgd_t *pgd) #ifndef __ASSEMBLY__ -static inline int pmd_bad(pmd_t pmd) -{ - return (pmd_val(pmd) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE; -} - #define pages_to_mb(x) ((x) >> (20 - PAGE_SHIFT)) /* FIXME: is this right? */ /* -- GitLab From cc290ca38cc4c78b0d6175633232f05b8d8732ab Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:31:12 -0800 Subject: [PATCH 1277/4982] x86: unify pages_to_mb Impact: cleanup Unify and demacro pages_to_mb. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable.h | 5 +++++ arch/x86/include/asm/pgtable_32.h | 2 -- arch/x86/include/asm/pgtable_64.h | 2 -- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 72bf53ef60b..d4cbc8188c8 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -519,6 +519,11 @@ static inline int pmd_bad(pmd_t pmd) return (pmd_val(pmd) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE; } +static inline unsigned long pages_to_mb(unsigned long npg) +{ + return npg >> (20 - PAGE_SHIFT); +} + #if PAGETABLE_LEVELS > 2 static inline int pud_present(pud_t pud) { diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h index 5362632df75..10c71abae07 100644 --- a/arch/x86/include/asm/pgtable_32.h +++ b/arch/x86/include/asm/pgtable_32.h @@ -85,8 +85,6 @@ extern void set_pmd_pfn(unsigned long, unsigned long, pgprot_t); /* The boot page tables (all created as a single array) */ extern unsigned long pg0[]; -#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) - #ifdef CONFIG_X86_PAE # include #else diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index d230e28a5f3..6c6c3c34bc5 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -154,8 +154,6 @@ static inline void native_pgd_clear(pgd_t *pgd) #ifndef __ASSEMBLY__ -#define pages_to_mb(x) ((x) >> (20 - PAGE_SHIFT)) /* FIXME: is this right? */ - /* * Conversion functions: convert a page and protection to a page entry, * and a page entry and page directory to the page they refer to. -- GitLab From deb79cfb365c96ff960570d1bcf2c205424b6195 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:31:13 -0800 Subject: [PATCH 1278/4982] x86: unify pud_none Impact: cleanup Unify and demacro pud_none. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable-3level.h | 5 ----- arch/x86/include/asm/pgtable.h | 5 +++++ arch/x86/include/asm/pgtable_64.h | 1 - 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h index b92524eec20..3f13cdf6115 100644 --- a/arch/x86/include/asm/pgtable-3level.h +++ b/arch/x86/include/asm/pgtable-3level.h @@ -18,11 +18,6 @@ printk("%s:%d: bad pgd %p(%016Lx).\n", \ __FILE__, __LINE__, &(e), pgd_val(e)) -static inline int pud_none(pud_t pud) -{ - return pud_val(pud) == 0; -} - /* Rules for using set_pte: the pte being assigned *must* be * either not present or in a state where the hardware will * not attempt to update the pte. In places where this is diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index d4cbc8188c8..0ef49f3ebc8 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -525,6 +525,11 @@ static inline unsigned long pages_to_mb(unsigned long npg) } #if PAGETABLE_LEVELS > 2 +static inline int pud_none(pud_t pud) +{ + return pud_val(pud) == 0; +} + static inline int pud_present(pud_t pud) { return pud_val(pud) & _PAGE_PRESENT; diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 6c6c3c34bc5..d58c2ee15c3 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -68,7 +68,6 @@ extern void paging_init(void); __FILE__, __LINE__, &(e), pgd_val(e)) #define pgd_none(x) (!pgd_val(x)) -#define pud_none(x) (!pud_val(x)) struct mm_struct; -- GitLab From 7325cc2e333cdaaabd2103552458876ea85adb33 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:31:14 -0800 Subject: [PATCH 1279/4982] x86: unify pgd_none Impact: cleanup Unify and demacro pgd_none. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable.h | 5 +++++ arch/x86/include/asm/pgtable_64.h | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 0ef49f3ebc8..18afcd31e76 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -599,6 +599,11 @@ static inline int pgd_bad(pgd_t pgd) { return (pgd_val(pgd) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE; } + +static inline int pgd_none(pgd_t pgd) +{ + return !pgd_val(pgd); +} #endif /* PAGETABLE_LEVELS > 3 */ #endif /* __ASSEMBLY__ */ diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index d58c2ee15c3..3b92a4ca403 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -67,8 +67,6 @@ extern void paging_init(void); printk("%s:%d: bad pgd %p(%016lx).\n", \ __FILE__, __LINE__, &(e), pgd_val(e)) -#define pgd_none(x) (!pgd_val(x)) - struct mm_struct; void set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte); -- GitLab From 6cf7150084500962b8e225e2409ec01ed06a2c71 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:31:15 -0800 Subject: [PATCH 1280/4982] x86: unify io_remap_pfn_range Impact: cleanup Unify io_remap_pfn_range. Don't demacro yet. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable.h | 3 +++ arch/x86/include/asm/pgtable_32.h | 3 --- arch/x86/include/asm/pgtable_64.h | 3 --- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 18afcd31e76..9754d06ffe6 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -524,6 +524,9 @@ static inline unsigned long pages_to_mb(unsigned long npg) return npg >> (20 - PAGE_SHIFT); } +#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ + remap_pfn_range(vma, vaddr, pfn, size, prot) + #if PAGETABLE_LEVELS > 2 static inline int pud_none(pud_t pud) { diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h index 10c71abae07..1952bb762aa 100644 --- a/arch/x86/include/asm/pgtable_32.h +++ b/arch/x86/include/asm/pgtable_32.h @@ -133,7 +133,4 @@ do { \ #define kern_addr_valid(kaddr) (0) #endif -#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ - remap_pfn_range(vma, vaddr, pfn, size, prot) - #endif /* _ASM_X86_PGTABLE_32_H */ diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 3b92a4ca403..100ac483a0b 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -205,9 +205,6 @@ extern int direct_gbpages; extern int kern_addr_valid(unsigned long addr); extern void cleanup_highmap(void); -#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ - remap_pfn_range(vma, vaddr, pfn, size, prot) - #define HAVE_ARCH_UNMAPPED_AREA #define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN -- GitLab From 18a7a199f97a7509fb987722e543f1aac3d7ada5 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:31:16 -0800 Subject: [PATCH 1281/4982] x86: add and use pgd/pud/pmd_flags Add pgd/pud/pmd_flags which are analogous to pte_flags, and use them where-ever we only care about testing the flags portions of the respective entries. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/page.h | 15 +++++++++++++++ arch/x86/include/asm/pgtable.h | 16 ++++++++-------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h index e9873a2e869..0b16b64a8fe 100644 --- a/arch/x86/include/asm/page.h +++ b/arch/x86/include/asm/page.h @@ -95,6 +95,11 @@ static inline pgdval_t native_pgd_val(pgd_t pgd) return pgd.pgd; } +static inline pgdval_t pgd_flags(pgd_t pgd) +{ + return native_pgd_val(pgd) & PTE_FLAGS_MASK; +} + #if PAGETABLE_LEVELS >= 3 #if PAGETABLE_LEVELS == 4 typedef struct { pudval_t pud; } pud_t; @@ -117,6 +122,11 @@ static inline pudval_t native_pud_val(pud_t pud) } #endif /* PAGETABLE_LEVELS == 4 */ +static inline pudval_t pud_flags(pud_t pud) +{ + return native_pud_val(pud) & PTE_FLAGS_MASK; +} + typedef struct { pmdval_t pmd; } pmd_t; static inline pmd_t native_make_pmd(pmdval_t val) @@ -128,6 +138,11 @@ static inline pmdval_t native_pmd_val(pmd_t pmd) { return pmd.pmd; } + +static inline pmdval_t pmd_flags(pmd_t pmd) +{ + return native_pmd_val(pmd) & PTE_FLAGS_MASK; +} #else /* PAGETABLE_LEVELS == 2 */ #include diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 9754d06ffe6..c811d76d6fd 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -236,7 +236,7 @@ static inline unsigned long pte_pfn(pte_t pte) static inline int pmd_large(pmd_t pte) { - return (pmd_val(pte) & (_PAGE_PSE | _PAGE_PRESENT)) == + return (pmd_flags(pte) & (_PAGE_PSE | _PAGE_PRESENT)) == (_PAGE_PSE | _PAGE_PRESENT); } @@ -458,7 +458,7 @@ static inline int pte_present(pte_t a) static inline int pmd_present(pmd_t pmd) { - return pmd_val(pmd) & _PAGE_PRESENT; + return pmd_flags(pmd) & _PAGE_PRESENT; } static inline int pmd_none(pmd_t pmd) @@ -516,7 +516,7 @@ static inline pte_t *pte_offset_kernel(pmd_t *pmd, unsigned long address) static inline int pmd_bad(pmd_t pmd) { - return (pmd_val(pmd) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE; + return (pmd_flags(pmd) & ~_PAGE_USER) != _KERNPG_TABLE; } static inline unsigned long pages_to_mb(unsigned long npg) @@ -535,7 +535,7 @@ static inline int pud_none(pud_t pud) static inline int pud_present(pud_t pud) { - return pud_val(pud) & _PAGE_PRESENT; + return pud_flags(pud) & _PAGE_PRESENT; } static inline unsigned long pud_page_vaddr(pud_t pud) @@ -561,20 +561,20 @@ static inline unsigned long pmd_pfn(pmd_t pmd) static inline int pud_large(pud_t pud) { - return (pud_val(pud) & (_PAGE_PSE | _PAGE_PRESENT)) == + return (pud_flags(pud) & (_PAGE_PSE | _PAGE_PRESENT)) == (_PAGE_PSE | _PAGE_PRESENT); } static inline int pud_bad(pud_t pud) { - return (pud_val(pud) & ~(PTE_PFN_MASK | _KERNPG_TABLE | _PAGE_USER)) != 0; + return (pud_flags(pud) & ~(_KERNPG_TABLE | _PAGE_USER)) != 0; } #endif /* PAGETABLE_LEVELS > 2 */ #if PAGETABLE_LEVELS > 3 static inline int pgd_present(pgd_t pgd) { - return pgd_val(pgd) & _PAGE_PRESENT; + return pgd_flags(pgd) & _PAGE_PRESENT; } static inline unsigned long pgd_page_vaddr(pgd_t pgd) @@ -600,7 +600,7 @@ static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address) static inline int pgd_bad(pgd_t pgd) { - return (pgd_val(pgd) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE; + return (pgd_flags(pgd) & ~_PAGE_USER) != _KERNPG_TABLE; } static inline int pgd_none(pgd_t pgd) -- GitLab From 26c8e3179933c5c9071b16db76ab6de58a787d06 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 5 Feb 2009 11:31:17 -0800 Subject: [PATCH 1282/4982] x86: make pgd/pud/pmd/pte_none consistent The _none test is done differently for every level of the pagetable. Standardize them by: 1: Use the native_X_val to extract the raw entry, with no need to go via paravirt_ops, diff -r 1d0646d0d319 arch/x86/include/asm/pgtable.h, and 2: Compare with 0 rather than using a boolean !, since they are actually values and not booleans. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/pgtable.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index c811d76d6fd..a80a956ae65 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -465,7 +465,7 @@ static inline int pmd_none(pmd_t pmd) { /* Only check low word on 32-bit platforms, since it might be out of sync with upper half. */ - return !(unsigned long)native_pmd_val(pmd); + return (unsigned long)native_pmd_val(pmd) == 0; } static inline unsigned long pmd_page_vaddr(pmd_t pmd) @@ -530,7 +530,7 @@ static inline unsigned long pages_to_mb(unsigned long npg) #if PAGETABLE_LEVELS > 2 static inline int pud_none(pud_t pud) { - return pud_val(pud) == 0; + return native_pud_val(pud) == 0; } static inline int pud_present(pud_t pud) @@ -605,7 +605,7 @@ static inline int pgd_bad(pgd_t pgd) static inline int pgd_none(pgd_t pgd) { - return !pgd_val(pgd); + return !native_pgd_val(pgd); } #endif /* PAGETABLE_LEVELS > 3 */ -- GitLab From 976e8f677e42757e5586ea04a9ac8bb8ddaa037e Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Fri, 6 Feb 2009 13:29:44 -0800 Subject: [PATCH 1283/4982] x86: asm/io.h: unify virt_to_phys/phys_to_virt Impact: unify identical code asm/io_32.h and _64.h has functionally identical definitions for virt_to_phys, phys_to_virt, page_to_phys, and the isa_* variants, so just unify them. The only slightly functional change is using phys_addr_t for the physical address argument and return val. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/io.h | 59 ++++++++++++++++++++++++++++++++++++ arch/x86/include/asm/io_32.h | 57 ---------------------------------- arch/x86/include/asm/io_64.h | 37 ---------------------- 3 files changed, 59 insertions(+), 94 deletions(-) diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index 1dbbdf4be9b..919e3b19f3c 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h @@ -5,6 +5,7 @@ #include #include +#include #define build_mmio_read(name, size, type, reg, barrier) \ static inline type name(const volatile void __iomem *addr) \ @@ -80,6 +81,64 @@ static inline void writeq(__u64 val, volatile void __iomem *addr) #define readq readq #define writeq writeq +/** + * virt_to_phys - map virtual addresses to physical + * @address: address to remap + * + * The returned physical address is the physical (CPU) mapping for + * the memory address given. It is only valid to use this function on + * addresses directly mapped or allocated via kmalloc. + * + * This function does not give bus mappings for DMA transfers. In + * almost all conceivable cases a device driver should not be using + * this function + */ + +static inline phys_addr_t virt_to_phys(volatile void *address) +{ + return __pa(address); +} + +/** + * phys_to_virt - map physical address to virtual + * @address: address to remap + * + * The returned virtual address is a current CPU mapping for + * the memory address given. It is only valid to use this function on + * addresses that have a kernel mapping + * + * This function does not handle bus mappings for DMA transfers. In + * almost all conceivable cases a device driver should not be using + * this function + */ + +static inline void *phys_to_virt(phys_addr_t address) +{ + return __va(address); +} + +/* + * Change "struct page" to physical address. + */ +#define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT) + +/* + * ISA I/O bus memory addresses are 1:1 with the physical address. + */ +#define isa_virt_to_bus virt_to_phys +#define isa_page_to_bus page_to_phys +#define isa_bus_to_virt phys_to_virt + +/* + * However PCI ones are not necessarily 1:1 and therefore these interfaces + * are forbidden in portable PCI drivers. + * + * Allow them on x86 for legacy drivers, though. + */ +#define virt_to_bus virt_to_phys +#define bus_to_virt phys_to_virt + + #ifdef CONFIG_X86_32 # include "io_32.h" #else diff --git a/arch/x86/include/asm/io_32.h b/arch/x86/include/asm/io_32.h index d8e242e1b39..2b687cb8609 100644 --- a/arch/x86/include/asm/io_32.h +++ b/arch/x86/include/asm/io_32.h @@ -53,47 +53,6 @@ */ #define xlate_dev_kmem_ptr(p) p -/** - * virt_to_phys - map virtual addresses to physical - * @address: address to remap - * - * The returned physical address is the physical (CPU) mapping for - * the memory address given. It is only valid to use this function on - * addresses directly mapped or allocated via kmalloc. - * - * This function does not give bus mappings for DMA transfers. In - * almost all conceivable cases a device driver should not be using - * this function - */ - -static inline unsigned long virt_to_phys(volatile void *address) -{ - return __pa(address); -} - -/** - * phys_to_virt - map physical address to virtual - * @address: address to remap - * - * The returned virtual address is a current CPU mapping for - * the memory address given. It is only valid to use this function on - * addresses that have a kernel mapping - * - * This function does not handle bus mappings for DMA transfers. In - * almost all conceivable cases a device driver should not be using - * this function - */ - -static inline void *phys_to_virt(unsigned long address) -{ - return __va(address); -} - -/* - * Change "struct page" to physical address. - */ -#define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT) - /** * ioremap - map bus memory into CPU space * @offset: bus address of the memory @@ -123,22 +82,6 @@ static inline void __iomem *ioremap(resource_size_t offset, unsigned long size) extern void iounmap(volatile void __iomem *addr); -/* - * ISA I/O bus memory addresses are 1:1 with the physical address. - */ -#define isa_virt_to_bus virt_to_phys -#define isa_page_to_bus page_to_phys -#define isa_bus_to_virt phys_to_virt - -/* - * However PCI ones are not necessarily 1:1 and therefore these interfaces - * are forbidden in portable PCI drivers. - * - * Allow them on x86 for legacy drivers, though. - */ -#define virt_to_bus virt_to_phys -#define bus_to_virt phys_to_virt - static inline void memset_io(volatile void __iomem *addr, unsigned char val, int count) { diff --git a/arch/x86/include/asm/io_64.h b/arch/x86/include/asm/io_64.h index 563c16270ba..e71b5550877 100644 --- a/arch/x86/include/asm/io_64.h +++ b/arch/x86/include/asm/io_64.h @@ -142,27 +142,6 @@ __OUTS(l) #include -#ifndef __i386__ -/* - * Change virtual addresses to physical addresses and vv. - * These are pretty trivial - */ -static inline unsigned long virt_to_phys(volatile void *address) -{ - return __pa(address); -} - -static inline void *phys_to_virt(unsigned long address) -{ - return __va(address); -} -#endif - -/* - * Change "struct page" to physical address. - */ -#define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT) - #include /* @@ -187,22 +166,6 @@ extern void iounmap(volatile void __iomem *addr); extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys); -/* - * ISA I/O bus memory addresses are 1:1 with the physical address. - */ -#define isa_virt_to_bus virt_to_phys -#define isa_page_to_bus page_to_phys -#define isa_bus_to_virt phys_to_virt - -/* - * However PCI ones are not necessarily 1:1 and therefore these interfaces - * are forbidden in portable PCI drivers. - * - * Allow them on x86 for legacy drivers, though. - */ -#define virt_to_bus virt_to_phys -#define bus_to_virt phys_to_virt - void __memcpy_fromio(void *, unsigned long, unsigned); void __memcpy_toio(unsigned long, const void *, unsigned); -- GitLab From 133822c5c038b265ddb6545cda3a4c88815c7d3d Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Fri, 6 Feb 2009 13:29:52 -0800 Subject: [PATCH 1284/4982] x86: asm/io.h: unify ioremap prototypes Impact: unify identical code asm/io_32.h and _64.h have identical prototypes for the ioremap family of functions. The 32-bit header had a more descriptive comment. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/io.h | 31 +++++++++++++++++++++++++++++++ arch/x86/include/asm/io_32.h | 29 ----------------------------- arch/x86/include/asm/io_64.h | 22 ---------------------- 3 files changed, 31 insertions(+), 51 deletions(-) diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index 919e3b19f3c..f150b1ecf92 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h @@ -138,6 +138,37 @@ static inline void *phys_to_virt(phys_addr_t address) #define virt_to_bus virt_to_phys #define bus_to_virt phys_to_virt +/** + * ioremap - map bus memory into CPU space + * @offset: bus address of the memory + * @size: size of the resource to map + * + * ioremap performs a platform specific sequence of operations to + * make bus memory CPU accessible via the readb/readw/readl/writeb/ + * writew/writel functions and the other mmio helpers. The returned + * address is not guaranteed to be usable directly as a virtual + * address. + * + * If the area you are trying to map is a PCI BAR you should have a + * look at pci_iomap(). + */ +extern void __iomem *ioremap_nocache(resource_size_t offset, unsigned long size); +extern void __iomem *ioremap_cache(resource_size_t offset, unsigned long size); +extern void __iomem *ioremap_prot(resource_size_t offset, unsigned long size, + unsigned long prot_val); + +/* + * The default ioremap() behavior is non-cached: + */ +static inline void __iomem *ioremap(resource_size_t offset, unsigned long size) +{ + return ioremap_nocache(offset, size); +} + +extern void iounmap(volatile void __iomem *addr); + +extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys); + #ifdef CONFIG_X86_32 # include "io_32.h" diff --git a/arch/x86/include/asm/io_32.h b/arch/x86/include/asm/io_32.h index 2b687cb8609..2fbe7dd26bb 100644 --- a/arch/x86/include/asm/io_32.h +++ b/arch/x86/include/asm/io_32.h @@ -53,35 +53,6 @@ */ #define xlate_dev_kmem_ptr(p) p -/** - * ioremap - map bus memory into CPU space - * @offset: bus address of the memory - * @size: size of the resource to map - * - * ioremap performs a platform specific sequence of operations to - * make bus memory CPU accessible via the readb/readw/readl/writeb/ - * writew/writel functions and the other mmio helpers. The returned - * address is not guaranteed to be usable directly as a virtual - * address. - * - * If the area you are trying to map is a PCI BAR you should have a - * look at pci_iomap(). - */ -extern void __iomem *ioremap_nocache(resource_size_t offset, unsigned long size); -extern void __iomem *ioremap_cache(resource_size_t offset, unsigned long size); -extern void __iomem *ioremap_prot(resource_size_t offset, unsigned long size, - unsigned long prot_val); - -/* - * The default ioremap() behavior is non-cached: - */ -static inline void __iomem *ioremap(resource_size_t offset, unsigned long size) -{ - return ioremap_nocache(offset, size); -} - -extern void iounmap(volatile void __iomem *addr); - static inline void memset_io(volatile void __iomem *addr, unsigned char val, int count) { diff --git a/arch/x86/include/asm/io_64.h b/arch/x86/include/asm/io_64.h index e71b5550877..0424c07246f 100644 --- a/arch/x86/include/asm/io_64.h +++ b/arch/x86/include/asm/io_64.h @@ -144,28 +144,6 @@ __OUTS(l) #include -/* - * This one maps high address device memory and turns off caching for that area. - * it's useful if some control registers are in such an area and write combining - * or read caching is not desirable: - */ -extern void __iomem *ioremap_nocache(resource_size_t offset, unsigned long size); -extern void __iomem *ioremap_cache(resource_size_t offset, unsigned long size); -extern void __iomem *ioremap_prot(resource_size_t offset, unsigned long size, - unsigned long prot_val); - -/* - * The default ioremap() behavior is non-cached: - */ -static inline void __iomem *ioremap(resource_size_t offset, unsigned long size) -{ - return ioremap_nocache(offset, size); -} - -extern void iounmap(volatile void __iomem *addr); - -extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys); - void __memcpy_fromio(void *, unsigned long, unsigned); void __memcpy_toio(unsigned long, const void *, unsigned); -- GitLab From 88800b2f2ffd3e436266e4dff9586d48b5b54500 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Fri, 6 Feb 2009 21:56:04 +0000 Subject: [PATCH 1285/4982] [ARM] orion5x: add rtc-m48t86 to orion5x_defconfig The TS-7800 can have a M48T86 RTC onboard Signed-off-by: Alexander Clouter --- arch/arm/configs/orion5x_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/orion5x_defconfig b/arch/arm/configs/orion5x_defconfig index b2456ca544c..45dcd086fee 100644 --- a/arch/arm/configs/orion5x_defconfig +++ b/arch/arm/configs/orion5x_defconfig @@ -1177,7 +1177,7 @@ CONFIG_RTC_DRV_S35390A=y # CONFIG_RTC_DRV_DS1553 is not set # CONFIG_RTC_DRV_DS1742 is not set # CONFIG_RTC_DRV_STK17TA8 is not set -# CONFIG_RTC_DRV_M48T86 is not set +CONFIG_RTC_DRV_M48T86=y # CONFIG_RTC_DRV_M48T59 is not set # CONFIG_RTC_DRV_V3020 is not set -- GitLab From c3dfdb0823213c81f60987c8a3770b89ea95cad6 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Fri, 6 Feb 2009 21:57:13 +0000 Subject: [PATCH 1286/4982] [ARM] orion5x: remove TS-78xx NOR support as it does not exist The TS-7800's M25P40 is not available to the kernel, it's used to load the initial bitstream onto the FPGA and so these hooks point to nothing and need to be removed. Signed-off-by: Alexander Clouter --- arch/arm/mach-orion5x/ts78xx-setup.c | 46 ---------------------------- 1 file changed, 46 deletions(-) diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c index 1368e9fd1a0..0cb34b9a6d8 100644 --- a/arch/arm/mach-orion5x/ts78xx-setup.c +++ b/arch/arm/mach-orion5x/ts78xx-setup.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -40,12 +39,6 @@ #define TS78XX_FPGA_REGS_RTC_CTRL (TS78XX_FPGA_REGS_VIRT_BASE | 0x808) #define TS78XX_FPGA_REGS_RTC_DATA (TS78XX_FPGA_REGS_VIRT_BASE | 0x80c) -/* - * 512kB NOR flash Device - */ -#define TS78XX_NOR_BOOT_BASE 0xff800000 -#define TS78XX_NOR_BOOT_SIZE SZ_512K - /***************************************************************************** * I/O Address Mapping ****************************************************************************/ @@ -64,41 +57,6 @@ void __init ts78xx_map_io(void) iotable_init(ts78xx_io_desc, ARRAY_SIZE(ts78xx_io_desc)); } -/***************************************************************************** - * 512kB NOR Boot Flash - the chip is a M25P40 - ****************************************************************************/ -static struct mtd_partition ts78xx_nor_boot_flash_resources[] = { - { - .name = "ts-bootrom", - .offset = 0, - /* only the first 256kB is used */ - .size = SZ_256K, - .mask_flags = MTD_WRITEABLE, - }, -}; - -static struct physmap_flash_data ts78xx_nor_boot_flash_data = { - .width = 1, - .parts = ts78xx_nor_boot_flash_resources, - .nr_parts = ARRAY_SIZE(ts78xx_nor_boot_flash_resources), -}; - -static struct resource ts78xx_nor_boot_flash_resource = { - .flags = IORESOURCE_MEM, - .start = TS78XX_NOR_BOOT_BASE, - .end = TS78XX_NOR_BOOT_BASE + TS78XX_NOR_BOOT_SIZE - 1, -}; - -static struct platform_device ts78xx_nor_boot_flash = { - .name = "physmap-flash", - .id = -1, - .dev = { - .platform_data = &ts78xx_nor_boot_flash_data, - }, - .num_resources = 1, - .resource = &ts78xx_nor_boot_flash_resource, -}; - /***************************************************************************** * Ethernet ****************************************************************************/ @@ -257,10 +215,6 @@ static void __init ts78xx_init(void) orion5x_uart1_init(); orion5x_xor_init(); - orion5x_setup_dev_boot_win(TS78XX_NOR_BOOT_BASE, - TS78XX_NOR_BOOT_SIZE); - platform_device_register(&ts78xx_nor_boot_flash); - if (!ts78xx_rtc_init()) printk(KERN_INFO "TS-78xx RTC not detected or enabled\n"); } -- GitLab From f54128609c4e7792fb52b03c3db0da78627ce607 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Fri, 6 Feb 2009 21:59:15 +0000 Subject: [PATCH 1287/4982] [ARM] orion5x: TS-78xx comment shifting moved the MPP comments to the mpp area of the platform code Signed-off-by: Alexander Clouter --- arch/arm/mach-orion5x/ts78xx-setup.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c index 0cb34b9a6d8..b194956518a 100644 --- a/arch/arm/mach-orion5x/ts78xx-setup.c +++ b/arch/arm/mach-orion5x/ts78xx-setup.c @@ -181,6 +181,14 @@ static struct orion5x_mpp_mode ts78xx_mpp_modes[] __initdata = { { 17, MPP_UART }, { 18, MPP_UART }, { 19, MPP_UART }, + /* + * MPP[20] PCI Clock Out 1 + * MPP[21] PCI Clock Out 0 + * MPP[22] Unused + * MPP[23] Unused + * MPP[24] Unused + * MPP[25] Unused + */ { -1 }, }; @@ -195,15 +203,6 @@ static void __init ts78xx_init(void) orion5x_mpp_conf(ts78xx_mpp_modes); - /* - * MPP[20] PCI Clock Out 1 - * MPP[21] PCI Clock Out 0 - * MPP[22] Unused - * MPP[23] Unused - * MPP[24] Unused - * MPP[25] Unused - */ - /* * Configure peripherals. */ -- GitLab From fb08b20fe7c8491a35a4369cce60fcb886d7609d Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Fri, 6 Feb 2009 14:05:28 -0800 Subject: [PATCH 1288/4982] x86: Fix compile error in arch/x86/kernel/early_printk.c Fix compile problem: CC arch/x86/kernel/early_printk.o In file included from /home/jeremy/hg/xen/paravirt/linux/arch/x86/kernel/early_printk.c:17: /home/jeremy/hg/xen/paravirt/linux/arch/x86/include/asm/pgtable.h: In function 'pmd_page': /home/jeremy/hg/xen/paravirt/linux/arch/x86/include/asm/pgtable.h:516: error: implicit declaration of function '__pfn_to_section' /home/jeremy/hg/xen/paravirt/linux/arch/x86/include/asm/pgtable.h:516: warning: initialization makes pointer from integer without a cast /home/jeremy/hg/xen/paravirt/linux/arch/x86/include/asm/pgtable.h:516: error: implicit declaration of function '__section_mem_map_addr' /home/jeremy/hg/xen/paravirt/linux/arch/x86/include/asm/pgtable.h:516: warning: return makes pointer from integer without a cast /home/jeremy/hg/xen/paravirt/linux/arch/x86/include/asm/pgtable.h: In function 'pud_page': /home/jeremy/hg/xen/paravirt/linux/arch/x86/include/asm/pgtable.h:586: warning: initialization makes pointer from integer without a cast /home/jeremy/hg/xen/paravirt/linux/arch/x86/include/asm/pgtable.h:586: warning: return makes pointer from integer without a cast /home/jeremy/hg/xen/paravirt/linux/arch/x86/include/asm/pgtable.h: In function 'pgd_page': /home/jeremy/hg/xen/paravirt/linux/arch/x86/include/asm/pgtable.h:625: warning: initialization makes pointer from integer without a cast /home/jeremy/hg/xen/paravirt/linux/arch/x86/include/asm/pgtable.h:625: warning: return makes pointer from integer without a cast This is a cycling dependency between asm/pgtable.h and linux/mmzone.h when using CONFIG_SPARSEMEM. Rather than hacking up the headers some more, remove asm/pgtable.h, since early_printk.c doesn't actually need it. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/kernel/early_printk.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index 504ad198e4a..6a36dd228b6 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include -- GitLab From 39008f959f4f3b60eecc5cec0ca077146c1f366b Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Fri, 6 Feb 2009 22:16:55 +0000 Subject: [PATCH 1289/4982] [ARM] orion5x: TS-78xx support for 'hotplug' of FPGA devices the FPGA on the TS-7800 provides access to a number of devices and so we have to be careful when reprogramming it. As we are effectively turning a bus off/on we have to inform the kernel that it should stop using anything provided by the FPGA (currently only the RTC however the NAND, LCD, etc is to come) before it's reprogrammed. Once reprogramed, we can tell the kernel to (re)enable things by checking the FPGA ID against a lookup table for what a particular FPGA bitstream can provide. Signed-off-by: Alexander Clouter --- arch/arm/mach-orion5x/Kconfig | 1 + arch/arm/mach-orion5x/ts78xx-fpga.h | 27 +++ arch/arm/mach-orion5x/ts78xx-setup.c | 251 +++++++++++++++++++++------ 3 files changed, 224 insertions(+), 55 deletions(-) create mode 100644 arch/arm/mach-orion5x/ts78xx-fpga.h diff --git a/arch/arm/mach-orion5x/Kconfig b/arch/arm/mach-orion5x/Kconfig index f59a8d0e082..2c7035d8dcb 100644 --- a/arch/arm/mach-orion5x/Kconfig +++ b/arch/arm/mach-orion5x/Kconfig @@ -71,6 +71,7 @@ config MACH_WRT350N_V2 config MACH_TS78XX bool "Technologic Systems TS-78xx" + select PM help Say 'Y' here if you want your kernel to support the Technologic Systems TS-78xx platform. diff --git a/arch/arm/mach-orion5x/ts78xx-fpga.h b/arch/arm/mach-orion5x/ts78xx-fpga.h new file mode 100644 index 00000000000..0b8e30faff1 --- /dev/null +++ b/arch/arm/mach-orion5x/ts78xx-fpga.h @@ -0,0 +1,27 @@ +#define FPGAID(_magic, _rev) ((_magic << 8) + _rev) + +/* + * get yer id's from http://ts78xx.digriz.org.uk/ + * do *not* make up your own or 'borrow' any! + */ +enum fpga_ids { + /* Technologic Systems */ + TS7800_REV_B = FPGAID(0x00b480, 0x03), +}; + +struct fpga_device { + unsigned present:1; + unsigned init:1; +}; + +struct fpga_devices { + /* Technologic Systems */ + struct fpga_device ts_rtc; +}; + +struct ts78xx_fpga_data { + unsigned int id; + int state; + + struct fpga_devices supports; +}; diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c index b194956518a..baa25d0fd5c 100644 --- a/arch/arm/mach-orion5x/ts78xx-setup.c +++ b/arch/arm/mach-orion5x/ts78xx-setup.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -20,6 +21,7 @@ #include #include "common.h" #include "mpp.h" +#include "ts78xx-fpga.h" /***************************************************************************** * TS-78xx Info @@ -32,12 +34,11 @@ #define TS78XX_FPGA_REGS_VIRT_BASE 0xff900000 #define TS78XX_FPGA_REGS_SIZE SZ_1M -#define TS78XX_FPGA_REGS_SYSCON_ID (TS78XX_FPGA_REGS_VIRT_BASE | 0x000) -#define TS78XX_FPGA_REGS_SYSCON_LCDI (TS78XX_FPGA_REGS_VIRT_BASE | 0x004) -#define TS78XX_FPGA_REGS_SYSCON_LCDO (TS78XX_FPGA_REGS_VIRT_BASE | 0x008) - -#define TS78XX_FPGA_REGS_RTC_CTRL (TS78XX_FPGA_REGS_VIRT_BASE | 0x808) -#define TS78XX_FPGA_REGS_RTC_DATA (TS78XX_FPGA_REGS_VIRT_BASE | 0x80c) +static struct ts78xx_fpga_data ts78xx_fpga = { + .id = 0, + .state = 1, +/* .supports = ... - populated by ts78xx_fpga_supports() */ +}; /***************************************************************************** * I/O Address Mapping @@ -64,32 +65,42 @@ static struct mv643xx_eth_platform_data ts78xx_eth_data = { .phy_addr = MV643XX_ETH_PHY_ADDR(0), }; +/***************************************************************************** + * SATA + ****************************************************************************/ +static struct mv_sata_platform_data ts78xx_sata_data = { + .n_ports = 2, +}; + /***************************************************************************** * RTC M48T86 - nicked^Wborrowed from arch/arm/mach-ep93xx/ts72xx.c ****************************************************************************/ #ifdef CONFIG_RTC_DRV_M48T86 -static unsigned char ts78xx_rtc_readbyte(unsigned long addr) +#define TS_RTC_CTRL (TS78XX_FPGA_REGS_VIRT_BASE | 0x808) +#define TS_RTC_DATA (TS78XX_FPGA_REGS_VIRT_BASE | 0x80c) + +static unsigned char ts78xx_ts_rtc_readbyte(unsigned long addr) { - writeb(addr, TS78XX_FPGA_REGS_RTC_CTRL); - return readb(TS78XX_FPGA_REGS_RTC_DATA); + writeb(addr, TS_RTC_CTRL); + return readb(TS_RTC_DATA); } -static void ts78xx_rtc_writebyte(unsigned char value, unsigned long addr) +static void ts78xx_ts_rtc_writebyte(unsigned char value, unsigned long addr) { - writeb(addr, TS78XX_FPGA_REGS_RTC_CTRL); - writeb(value, TS78XX_FPGA_REGS_RTC_DATA); + writeb(addr, TS_RTC_CTRL); + writeb(value, TS_RTC_DATA); } -static struct m48t86_ops ts78xx_rtc_ops = { - .readbyte = ts78xx_rtc_readbyte, - .writebyte = ts78xx_rtc_writebyte, +static struct m48t86_ops ts78xx_ts_rtc_ops = { + .readbyte = ts78xx_ts_rtc_readbyte, + .writebyte = ts78xx_ts_rtc_writebyte, }; -static struct platform_device ts78xx_rtc_device = { +static struct platform_device ts78xx_ts_rtc_device = { .name = "rtc-m48t86", .id = -1, .dev = { - .platform_data = &ts78xx_rtc_ops, + .platform_data = &ts78xx_ts_rtc_ops, }, .num_resources = 0, }; @@ -104,59 +115,185 @@ static struct platform_device ts78xx_rtc_device = { * TODO: track down a guinea pig without an RTC to see if we can work out a * better RTC detection routine */ -static int __init ts78xx_rtc_init(void) +static int ts78xx_ts_rtc_load(void) { unsigned char tmp_rtc0, tmp_rtc1; - tmp_rtc0 = ts78xx_rtc_readbyte(126); - tmp_rtc1 = ts78xx_rtc_readbyte(127); - - ts78xx_rtc_writebyte(0x00, 126); - ts78xx_rtc_writebyte(0x55, 127); - if (ts78xx_rtc_readbyte(127) == 0x55) { - ts78xx_rtc_writebyte(0xaa, 127); - if (ts78xx_rtc_readbyte(127) == 0xaa - && ts78xx_rtc_readbyte(126) == 0x00) { - ts78xx_rtc_writebyte(tmp_rtc0, 126); - ts78xx_rtc_writebyte(tmp_rtc1, 127); - platform_device_register(&ts78xx_rtc_device); - return 1; + tmp_rtc0 = ts78xx_ts_rtc_readbyte(126); + tmp_rtc1 = ts78xx_ts_rtc_readbyte(127); + + ts78xx_ts_rtc_writebyte(0x00, 126); + ts78xx_ts_rtc_writebyte(0x55, 127); + if (ts78xx_ts_rtc_readbyte(127) == 0x55) { + ts78xx_ts_rtc_writebyte(0xaa, 127); + if (ts78xx_ts_rtc_readbyte(127) == 0xaa + && ts78xx_ts_rtc_readbyte(126) == 0x00) { + ts78xx_ts_rtc_writebyte(tmp_rtc0, 126); + ts78xx_ts_rtc_writebyte(tmp_rtc1, 127); + if (ts78xx_fpga.supports.ts_rtc.init == 0) { + ts78xx_fpga.supports.ts_rtc.init = 1; + platform_device_register(&ts78xx_ts_rtc_device); + } else + platform_device_add(&ts78xx_ts_rtc_device); + return 0; } } - return 0; + ts78xx_fpga.supports.ts_rtc.present = 0; + return -ENODEV; }; + +static void ts78xx_ts_rtc_unload(void) +{ + platform_device_del(&ts78xx_ts_rtc_device); +} #else -static int __init ts78xx_rtc_init(void) +static int ts78xx_ts_rtc_load(void) { return 0; } + +static void ts78xx_ts_rtc_unload(void) +{ +} #endif /***************************************************************************** - * SATA + * FPGA 'hotplug' support code ****************************************************************************/ -static struct mv_sata_platform_data ts78xx_sata_data = { - .n_ports = 2, +static void ts78xx_fpga_devices_zero_init(void) +{ + ts78xx_fpga.supports.ts_rtc.init = 0; +} + +static void ts78xx_fpga_supports(void) +{ + /* TODO: put this 'table' into ts78xx-fpga.h */ + switch (ts78xx_fpga.id) { + case TS7800_REV_B: + ts78xx_fpga.supports.ts_rtc.present = 1; + break; + default: + ts78xx_fpga.supports.ts_rtc.present = 0; + } +} + +static int ts78xx_fpga_load_devices(void) +{ + int tmp, ret = 0; + + if (ts78xx_fpga.supports.ts_rtc.present == 1) { + tmp = ts78xx_ts_rtc_load(); + if (tmp) + printk(KERN_INFO "TS-78xx RTC not detected or enabled\n"); + ret |= tmp; + } + + return ret; +} + +static int ts78xx_fpga_unload_devices(void) +{ + int ret = 0; + + if (ts78xx_fpga.supports.ts_rtc.present == 1) + ts78xx_ts_rtc_unload(); + + return ret; +} + +static int ts78xx_fpga_load(void) +{ + ts78xx_fpga.id = readl(TS78XX_FPGA_REGS_VIRT_BASE); + + printk(KERN_INFO "TS-78xx FPGA: magic=0x%.6x, rev=0x%.2x\n", + (ts78xx_fpga.id >> 8) & 0xffffff, + ts78xx_fpga.id & 0xff); + + ts78xx_fpga_supports(); + + if (ts78xx_fpga_load_devices()) { + ts78xx_fpga.state = -1; + return -EBUSY; + } + + return 0; }; -/***************************************************************************** - * print some information regarding the board - ****************************************************************************/ -static void __init ts78xx_print_board_id(void) -{ - unsigned int board_info; - - board_info = readl(TS78XX_FPGA_REGS_SYSCON_ID); - printk(KERN_INFO "TS-78xx Info: FPGA rev=%.2x, Board Magic=%.6x, ", - board_info & 0xff, - (board_info >> 8) & 0xffffff); - board_info = readl(TS78XX_FPGA_REGS_SYSCON_LCDI); - printk("JP1=%d, JP2=%d\n", - (board_info >> 30) & 0x1, - (board_info >> 31) & 0x1); +static int ts78xx_fpga_unload(void) +{ + unsigned int fpga_id; + + fpga_id = readl(TS78XX_FPGA_REGS_VIRT_BASE); + + /* + * There does not seem to be a feasible way to block access to the GPIO + * pins from userspace (/dev/mem). This if clause should hopefully warn + * those foolish enough not to follow 'policy' :) + * + * UrJTAG SVN since r1381 can be used to reprogram the FPGA + */ + if (ts78xx_fpga.id != fpga_id) { + printk(KERN_ERR "TS-78xx FPGA: magic/rev mismatch\n" + "TS-78xx FPGA: was 0x%.6x/%.2x but now 0x%.6x/%.2x\n", + (ts78xx_fpga.id >> 8) & 0xffffff, ts78xx_fpga.id & 0xff, + (fpga_id >> 8) & 0xffffff, fpga_id & 0xff); + ts78xx_fpga.state = -1; + return -EBUSY; + } + + if (ts78xx_fpga_unload_devices()) { + ts78xx_fpga.state = -1; + return -EBUSY; + } + + return 0; }; +static ssize_t ts78xx_fpga_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + if (ts78xx_fpga.state < 0) + return sprintf(buf, "borked\n"); + + return sprintf(buf, "%s\n", (ts78xx_fpga.state) ? "online" : "offline"); +} + +static ssize_t ts78xx_fpga_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t n) +{ + int value, ret; + + if (ts78xx_fpga.state < 0) { + printk(KERN_ERR "TS-78xx FPGA: borked, you must powercycle asap\n"); + return -EBUSY; + } + + if (strncmp(buf, "online", sizeof("online") - 1) == 0) + value = 1; + else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0) + value = 0; + else { + printk(KERN_ERR "ts78xx_fpga_store: Invalid value\n"); + return -EINVAL; + } + + if (ts78xx_fpga.state == value) + return n; + + ret = (ts78xx_fpga.state == 0) + ? ts78xx_fpga_load() + : ts78xx_fpga_unload(); + + if (!(ret < 0)) + ts78xx_fpga.state = value; + + return n; +} + +static struct kobj_attribute ts78xx_fpga_attr = + __ATTR(ts78xx_fpga, 0644, ts78xx_fpga_show, ts78xx_fpga_store); + /***************************************************************************** * General Setup ****************************************************************************/ @@ -194,13 +331,13 @@ static struct orion5x_mpp_mode ts78xx_mpp_modes[] __initdata = { static void __init ts78xx_init(void) { + int ret; + /* * Setup basic Orion functions. Need to be called early. */ orion5x_init(); - ts78xx_print_board_id(); - orion5x_mpp_conf(ts78xx_mpp_modes); /* @@ -214,8 +351,12 @@ static void __init ts78xx_init(void) orion5x_uart1_init(); orion5x_xor_init(); - if (!ts78xx_rtc_init()) - printk(KERN_INFO "TS-78xx RTC not detected or enabled\n"); + /* FPGA init */ + ts78xx_fpga_devices_zero_init(); + ret = ts78xx_fpga_load(); + ret = sysfs_create_file(power_kobj, &ts78xx_fpga_attr.attr); + if (ret) + printk(KERN_ERR "sysfs_create_file failed: %d\n", ret); } MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC") -- GitLab From 0ecc061d1967e9f2694502079e00d9d6e1e39072 Mon Sep 17 00:00:00 2001 From: Peter P Waskiewicz Jr Date: Fri, 6 Feb 2009 21:46:54 -0800 Subject: [PATCH 1290/4982] ixgbe: Update flow control state machine in link setup The flow control handling is overly complicated and difficult to maintain. This patch cleans up the flow control handling and makes it much more explicit. It also adds 1G flow control autonegotiation, for 1G copper links, 1G KX links, and 1G fiber links. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_82598.c | 177 ++++++++++++++++++---------- drivers/net/ixgbe/ixgbe_common.c | 138 ++++++++++++++++++++++ drivers/net/ixgbe/ixgbe_common.h | 3 + drivers/net/ixgbe/ixgbe_dcb_82598.c | 2 +- drivers/net/ixgbe/ixgbe_ethtool.c | 23 ++-- drivers/net/ixgbe/ixgbe_main.c | 77 ++++++------ drivers/net/ixgbe/ixgbe_type.h | 29 ++++- 7 files changed, 327 insertions(+), 122 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index f726a14d1a7..525bd87fea5 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -255,104 +255,75 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw) } /** - * ixgbe_setup_fc_82598 - Configure flow control settings + * ixgbe_fc_enable_82598 - Enable flow control * @hw: pointer to hardware structure * @packetbuf_num: packet buffer number (0-7) * - * Configures the flow control settings based on SW configuration. This - * function is used for 802.3x flow control configuration only. + * Enable flow control according to the current settings. **/ -static s32 ixgbe_setup_fc_82598(struct ixgbe_hw *hw, s32 packetbuf_num) +static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num) { - u32 frctl_reg; + s32 ret_val = 0; + u32 fctrl_reg; u32 rmcs_reg; + u32 reg; - if (packetbuf_num < 0 || packetbuf_num > 7) { - hw_dbg(hw, "Invalid packet buffer number [%d], expected range is" - " 0-7\n", packetbuf_num); - } - - frctl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL); - frctl_reg &= ~(IXGBE_FCTRL_RFCE | IXGBE_FCTRL_RPFCE); + fctrl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL); + fctrl_reg &= ~(IXGBE_FCTRL_RFCE | IXGBE_FCTRL_RPFCE); rmcs_reg = IXGBE_READ_REG(hw, IXGBE_RMCS); rmcs_reg &= ~(IXGBE_RMCS_TFCE_PRIORITY | IXGBE_RMCS_TFCE_802_3X); /* - * 10 gig parts do not have a word in the EEPROM to determine the - * default flow control setting, so we explicitly set it to full. - */ - if (hw->fc.type == ixgbe_fc_default) - hw->fc.type = ixgbe_fc_full; - - /* - * We want to save off the original Flow Control configuration just in - * case we get disconnected and then reconnected into a different hub - * or switch with different Flow Control capabilities. - */ - hw->fc.original_type = hw->fc.type; - - /* - * The possible values of the "flow_control" parameter are: + * The possible values of fc.current_mode are: * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause frames but not - * send pause frames). - * 2: Tx flow control is enabled (we can send pause frames but we do not - * support receiving pause frames) + * 1: Rx flow control is enabled (we can receive pause frames, + * but not send pause frames). + * 2: Tx flow control is enabled (we can send pause frames but + * we do not support receiving pause frames). * 3: Both Rx and Tx flow control (symmetric) are enabled. * other: Invalid. */ - switch (hw->fc.type) { + switch (hw->fc.current_mode) { case ixgbe_fc_none: + /* Flow control completely disabled by software override. */ break; case ixgbe_fc_rx_pause: /* - * Rx Flow control is enabled, - * and Tx Flow control is disabled. + * Rx Flow control is enabled and Tx Flow control is + * disabled by software override. Since there really + * isn't a way to advertise that we are capable of RX + * Pause ONLY, we will advertise that we support both + * symmetric and asymmetric Rx PAUSE. Later, we will + * disable the adapter's ability to send PAUSE frames. */ - frctl_reg |= IXGBE_FCTRL_RFCE; + fctrl_reg |= IXGBE_FCTRL_RFCE; break; case ixgbe_fc_tx_pause: /* - * Tx Flow control is enabled, and Rx Flow control is disabled, - * by a software over-ride. + * Tx Flow control is enabled, and Rx Flow control is + * disabled by software override. */ rmcs_reg |= IXGBE_RMCS_TFCE_802_3X; break; case ixgbe_fc_full: - /* - * Flow control (both Rx and Tx) is enabled by a software - * over-ride. - */ - frctl_reg |= IXGBE_FCTRL_RFCE; + /* Flow control (both Rx and Tx) is enabled by SW override. */ + fctrl_reg |= IXGBE_FCTRL_RFCE; rmcs_reg |= IXGBE_RMCS_TFCE_802_3X; break; default: - /* We should never get here. The value should be 0-3. */ hw_dbg(hw, "Flow control param set incorrectly\n"); + ret_val = -IXGBE_ERR_CONFIG; + goto out; break; } /* Enable 802.3x based flow control settings. */ - IXGBE_WRITE_REG(hw, IXGBE_FCTRL, frctl_reg); + IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl_reg); IXGBE_WRITE_REG(hw, IXGBE_RMCS, rmcs_reg); - /* - * Check for invalid software configuration, zeros are completely - * invalid for all parameters used past this point, and if we enable - * flow control with zero water marks, we blast flow control packets. - */ - if (!hw->fc.low_water || !hw->fc.high_water || !hw->fc.pause_time) { - hw_dbg(hw, "Flow control structure initialized incorrectly\n"); - return IXGBE_ERR_INVALID_LINK_SETTINGS; - } - - /* - * We need to set up the Receive Threshold high and low water - * marks as well as (optionally) enabling the transmission of - * XON frames. - */ - if (hw->fc.type & ixgbe_fc_tx_pause) { + /* Set up and enable Rx high/low water mark thresholds, enable XON. */ + if (hw->fc.current_mode & ixgbe_fc_tx_pause) { if (hw->fc.send_xon) { IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), (hw->fc.low_water | IXGBE_FCRTL_XONE)); @@ -360,14 +331,93 @@ static s32 ixgbe_setup_fc_82598(struct ixgbe_hw *hw, s32 packetbuf_num) IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), hw->fc.low_water); } + IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num), - (hw->fc.high_water)|IXGBE_FCRTH_FCEN); + (hw->fc.high_water | IXGBE_FCRTH_FCEN)); } - IXGBE_WRITE_REG(hw, IXGBE_FCTTV(0), hw->fc.pause_time); + /* Configure pause time (2 TCs per register) */ + reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num)); + if ((packetbuf_num & 1) == 0) + reg = (reg & 0xFFFF0000) | hw->fc.pause_time; + else + reg = (reg & 0x0000FFFF) | (hw->fc.pause_time << 16); + IXGBE_WRITE_REG(hw, IXGBE_FCTTV(packetbuf_num / 2), reg); + IXGBE_WRITE_REG(hw, IXGBE_FCRTV, (hw->fc.pause_time >> 1)); - return 0; +out: + return ret_val; +} + +/** + * ixgbe_setup_fc_82598 - Configure flow control settings + * @hw: pointer to hardware structure + * @packetbuf_num: packet buffer number (0-7) + * + * Configures the flow control settings based on SW configuration. This + * function is used for 802.3x flow control configuration only. + **/ +static s32 ixgbe_setup_fc_82598(struct ixgbe_hw *hw, s32 packetbuf_num) +{ + s32 ret_val = 0; + ixgbe_link_speed speed; + bool link_up; + + /* Validate the packetbuf configuration */ + if (packetbuf_num < 0 || packetbuf_num > 7) { + hw_dbg(hw, "Invalid packet buffer number [%d], expected range is" + " 0-7\n", packetbuf_num); + ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; + goto out; + } + + /* + * Validate the water mark configuration. Zero water marks are invalid + * because it causes the controller to just blast out fc packets. + */ + if (!hw->fc.low_water || !hw->fc.high_water || !hw->fc.pause_time) { + hw_dbg(hw, "Invalid water mark configuration\n"); + ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; + goto out; + } + + /* + * Validate the requested mode. Strict IEEE mode does not allow + * ixgbe_fc_rx_pause because it will cause testing anomalies. + */ + if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { + hw_dbg(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); + ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; + goto out; + } + + /* + * 10gig parts do not have a word in the EEPROM to determine the + * default flow control setting, so we explicitly set it to full. + */ + if (hw->fc.requested_mode == ixgbe_fc_default) + hw->fc.requested_mode = ixgbe_fc_full; + + /* + * Save off the requested flow control mode for use later. Depending + * on the link partner's capabilities, we may or may not use this mode. + */ + + hw->fc.current_mode = hw->fc.requested_mode; + + /* Decide whether to use autoneg or not. */ + hw->mac.ops.check_link(hw, &speed, &link_up, false); + if (hw->phy.multispeed_fiber && (speed == IXGBE_LINK_SPEED_1GB_FULL)) + ret_val = ixgbe_fc_autoneg(hw); + + if (ret_val) + goto out; + + ret_val = ixgbe_fc_enable_82598(hw, packetbuf_num); + +out: + return ret_val; } /** @@ -414,7 +464,6 @@ static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw) * case we get disconnected and then reconnected into a different hub * or switch with different Flow Control capabilities. */ - hw->fc.original_type = hw->fc.type; ixgbe_setup_fc_82598(hw, 0); /* Add delay to filter out noises during initial link setup */ diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index 13ad5ba66b6..5ae93989784 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -1486,6 +1486,144 @@ s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw) return 0; } +/** + * ixgbe_fc_autoneg - Configure flow control + * @hw: pointer to hardware structure + * + * Negotiates flow control capabilities with link partner using autoneg and + * applies the results. + **/ +s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw) +{ + s32 ret_val = 0; + u32 i, reg, pcs_anadv_reg, pcs_lpab_reg; + + reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); + + /* + * The possible values of fc.current_mode are: + * 0: Flow control is completely disabled + * 1: Rx flow control is enabled (we can receive pause frames, + * but not send pause frames). + * 2: Tx flow control is enabled (we can send pause frames but + * we do not support receiving pause frames). + * 3: Both Rx and Tx flow control (symmetric) are enabled. + * other: Invalid. + */ + switch (hw->fc.current_mode) { + case ixgbe_fc_none: + /* Flow control completely disabled by software override. */ + reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); + break; + case ixgbe_fc_rx_pause: + /* + * Rx Flow control is enabled and Tx Flow control is + * disabled by software override. Since there really + * isn't a way to advertise that we are capable of RX + * Pause ONLY, we will advertise that we support both + * symmetric and asymmetric Rx PAUSE. Later, we will + * disable the adapter's ability to send PAUSE frames. + */ + reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); + break; + case ixgbe_fc_tx_pause: + /* + * Tx Flow control is enabled, and Rx Flow control is + * disabled by software override. + */ + reg |= (IXGBE_PCS1GANA_ASM_PAUSE); + reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE); + break; + case ixgbe_fc_full: + /* Flow control (both Rx and Tx) is enabled by SW override. */ + reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); + break; + default: + hw_dbg(hw, "Flow control param set incorrectly\n"); + ret_val = -IXGBE_ERR_CONFIG; + goto out; + break; + } + + IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg); + reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL); + + /* Set PCS register for autoneg */ + /* Enable and restart autoneg */ + reg |= IXGBE_PCS1GLCTL_AN_ENABLE | IXGBE_PCS1GLCTL_AN_RESTART; + + /* Disable AN timeout */ + if (hw->fc.strict_ieee) + reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN; + + hw_dbg(hw, "Configuring Autoneg; PCS_LCTL = 0x%08X\n", reg); + IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg); + + /* See if autonegotiation has succeeded */ + hw->mac.autoneg_succeeded = 0; + for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) { + msleep(10); + reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA); + if ((reg & (IXGBE_PCS1GLSTA_LINK_OK | + IXGBE_PCS1GLSTA_AN_COMPLETE)) == + (IXGBE_PCS1GLSTA_LINK_OK | + IXGBE_PCS1GLSTA_AN_COMPLETE)) { + if (!(reg & IXGBE_PCS1GLSTA_AN_TIMED_OUT)) + hw->mac.autoneg_succeeded = 1; + break; + } + } + + if (!hw->mac.autoneg_succeeded) { + /* Autoneg failed to achieve a link, so we turn fc off */ + hw->fc.current_mode = ixgbe_fc_none; + hw_dbg(hw, "Flow Control = NONE.\n"); + goto out; + } + + /* + * Read the AN advertisement and LP ability registers and resolve + * local flow control settings accordingly + */ + pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); + pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP); + if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && + (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE)) { + /* + * Now we need to check if the user selected Rx ONLY + * of pause frames. In this case, we had to advertise + * FULL flow control because we could not advertise RX + * ONLY. Hence, we must now check to see if we need to + * turn OFF the TRANSMISSION of PAUSE frames. + */ + if (hw->fc.requested_mode == ixgbe_fc_full) { + hw->fc.current_mode = ixgbe_fc_full; + hw_dbg(hw, "Flow Control = FULL.\n"); + } else { + hw->fc.current_mode = ixgbe_fc_rx_pause; + hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n"); + } + } else if (!(pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && + (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) && + (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) && + (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) { + hw->fc.current_mode = ixgbe_fc_tx_pause; + hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n"); + } else if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && + (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) && + !(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) && + (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) { + hw->fc.current_mode = ixgbe_fc_rx_pause; + hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n"); + } else { + hw->fc.current_mode = ixgbe_fc_none; + hw_dbg(hw, "Flow Control = NONE.\n"); + } + +out: + return ret_val; +} + /** * ixgbe_disable_pcie_master - Disable PCI-express master access * @hw: pointer to hardware structure diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ixgbe/ixgbe_common.h index 0b5ba575580..c63021261e5 100644 --- a/drivers/net/ixgbe/ixgbe_common.h +++ b/drivers/net/ixgbe/ixgbe_common.h @@ -61,6 +61,9 @@ s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, u32 addr_count, ixgbe_mc_addr_itr func); s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw); s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw); +s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw, s32 packetbuf_num); +s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packtetbuf_num); +s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw); s32 ixgbe_validate_mac_addr(u8 *mac_addr); s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask); diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ixgbe/ixgbe_dcb_82598.c index 56032114893..df359554d49 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82598.c +++ b/drivers/net/ixgbe/ixgbe_dcb_82598.c @@ -298,7 +298,7 @@ s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, reg = IXGBE_READ_REG(hw, IXGBE_RMCS); reg &= ~IXGBE_RMCS_TFCE_802_3X; /* correct the reporting of our flow control status */ - hw->fc.type = ixgbe_fc_none; + hw->fc.current_mode = ixgbe_fc_none; reg |= IXGBE_RMCS_TFCE_PRIORITY; IXGBE_WRITE_REG(hw, IXGBE_RMCS, reg); diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 54d96cb05b4..cec2f4e8c61 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -224,13 +224,13 @@ static void ixgbe_get_pauseparam(struct net_device *netdev, struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; - pause->autoneg = (hw->fc.type == ixgbe_fc_full ? 1 : 0); + pause->autoneg = (hw->fc.current_mode == ixgbe_fc_full ? 1 : 0); - if (hw->fc.type == ixgbe_fc_rx_pause) { + if (hw->fc.current_mode == ixgbe_fc_rx_pause) { pause->rx_pause = 1; - } else if (hw->fc.type == ixgbe_fc_tx_pause) { + } else if (hw->fc.current_mode == ixgbe_fc_tx_pause) { pause->tx_pause = 1; - } else if (hw->fc.type == ixgbe_fc_full) { + } else if (hw->fc.current_mode == ixgbe_fc_full) { pause->rx_pause = 1; pause->tx_pause = 1; } @@ -244,22 +244,17 @@ static int ixgbe_set_pauseparam(struct net_device *netdev, if ((pause->autoneg == AUTONEG_ENABLE) || (pause->rx_pause && pause->tx_pause)) - hw->fc.type = ixgbe_fc_full; + hw->fc.requested_mode = ixgbe_fc_full; else if (pause->rx_pause && !pause->tx_pause) - hw->fc.type = ixgbe_fc_rx_pause; + hw->fc.requested_mode = ixgbe_fc_rx_pause; else if (!pause->rx_pause && pause->tx_pause) - hw->fc.type = ixgbe_fc_tx_pause; + hw->fc.requested_mode = ixgbe_fc_tx_pause; else if (!pause->rx_pause && !pause->tx_pause) - hw->fc.type = ixgbe_fc_none; + hw->fc.requested_mode = ixgbe_fc_none; else return -EINVAL; - hw->fc.original_type = hw->fc.type; - - if (netif_running(netdev)) - ixgbe_reinit_locked(adapter); - else - ixgbe_reset(adapter); + hw->mac.ops.setup_fc(hw, 0); return 0; } diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index dceae37fd57..850361a4c38 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1954,11 +1954,43 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter) (adapter->rx_ring[i].count - 1)); } +/** + * ixgbe_link_config - set up initial link with default speed and duplex + * @hw: pointer to private hardware struct + * + * Returns 0 on success, negative on failure + **/ +static int ixgbe_link_config(struct ixgbe_hw *hw) +{ + u32 autoneg; + bool link_up = false; + u32 ret = IXGBE_ERR_LINK_SETUP; + + if (hw->mac.ops.check_link) + ret = hw->mac.ops.check_link(hw, &autoneg, &link_up, false); + + if (ret) + goto link_cfg_out; + + if (hw->mac.ops.get_link_capabilities) + ret = hw->mac.ops.get_link_capabilities(hw, &autoneg, + &hw->mac.autoneg); + if (ret) + goto link_cfg_out; + + if (hw->mac.ops.setup_link_speed) + ret = hw->mac.ops.setup_link_speed(hw, autoneg, true, link_up); + +link_cfg_out: + return ret; +} + static int ixgbe_up_complete(struct ixgbe_adapter *adapter) { struct net_device *netdev = adapter->netdev; struct ixgbe_hw *hw = &adapter->hw; int i, j = 0; + int err; int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; u32 txdctl, rxdctl, mhadd; u32 gpie; @@ -2039,6 +2071,10 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) ixgbe_irq_enable(adapter); + err = ixgbe_link_config(hw); + if (err) + dev_err(&adapter->pdev->dev, "link_config FAILED %d\n", err); + /* enable transmits */ netif_tx_start_all_queues(netdev); @@ -2792,8 +2828,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) adapter->flags |= IXGBE_FLAG_FAN_FAIL_CAPABLE; /* default flow control settings */ - hw->fc.original_type = ixgbe_fc_none; - hw->fc.type = ixgbe_fc_none; + hw->fc.requested_mode = ixgbe_fc_none; hw->fc.high_water = IXGBE_DEFAULT_FCRTH; hw->fc.low_water = IXGBE_DEFAULT_FCRTL; hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE; @@ -3916,37 +3951,6 @@ static void ixgbe_netpoll(struct net_device *netdev) } #endif -/** - * ixgbe_link_config - set up initial link with default speed and duplex - * @hw: pointer to private hardware struct - * - * Returns 0 on success, negative on failure - **/ -static int ixgbe_link_config(struct ixgbe_hw *hw) -{ - u32 autoneg; - bool link_up = false; - u32 ret = IXGBE_ERR_LINK_SETUP; - - if (hw->mac.ops.check_link) - ret = hw->mac.ops.check_link(hw, &autoneg, &link_up, false); - - if (ret || !link_up) - goto link_cfg_out; - - if (hw->mac.ops.get_link_capabilities) - ret = hw->mac.ops.get_link_capabilities(hw, &autoneg, - &hw->mac.autoneg); - if (ret) - goto link_cfg_out; - - if (hw->mac.ops.setup_link_speed) - ret = hw->mac.ops.setup_link_speed(hw, autoneg, true, true); - -link_cfg_out: - return ret; -} - static const struct net_device_ops ixgbe_netdev_ops = { .ndo_open = ixgbe_open, .ndo_stop = ixgbe_close, @@ -4197,13 +4201,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, /* reset the hardware with the new settings */ hw->mac.ops.start_hw(hw); - /* link_config depends on start_hw being called at least once */ - err = ixgbe_link_config(hw); - if (err) { - dev_err(&pdev->dev, "setup_link_speed FAILED %d\n", err); - goto err_register; - } - netif_carrier_off(netdev); strcpy(netdev->name, "eth%d"); diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 984b4ed372f..237c688f8b6 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -771,6 +771,28 @@ #define IXGBE_LINK_UP_TIME 90 /* 9.0 Seconds */ #define IXGBE_AUTO_NEG_TIME 45 /* 4.5 Seconds */ +#define FIBER_LINK_UP_LIMIT 50 + +/* PCS1GLSTA Bit Masks */ +#define IXGBE_PCS1GLSTA_LINK_OK 1 +#define IXGBE_PCS1GLSTA_SYNK_OK 0x10 +#define IXGBE_PCS1GLSTA_AN_COMPLETE 0x10000 +#define IXGBE_PCS1GLSTA_AN_PAGE_RX 0x20000 +#define IXGBE_PCS1GLSTA_AN_TIMED_OUT 0x40000 +#define IXGBE_PCS1GLSTA_AN_REMOTE_FAULT 0x80000 +#define IXGBE_PCS1GLSTA_AN_ERROR_RWS 0x100000 + +#define IXGBE_PCS1GANA_SYM_PAUSE 0x80 +#define IXGBE_PCS1GANA_ASM_PAUSE 0x100 + +/* PCS1GLCTL Bit Masks */ +#define IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN 0x00040000 /* PCS 1G autoneg to en */ +#define IXGBE_PCS1GLCTL_FLV_LINK_UP 1 +#define IXGBE_PCS1GLCTL_FORCE_LINK 0x20 +#define IXGBE_PCS1GLCTL_LOW_LINK_LATCH 0x40 +#define IXGBE_PCS1GLCTL_AN_ENABLE 0x10000 +#define IXGBE_PCS1GLCTL_AN_RESTART 0x20000 + /* SW Semaphore Register bitmasks */ #define IXGBE_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ #define IXGBE_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ @@ -1270,7 +1292,7 @@ enum ixgbe_media_type { }; /* Flow Control Settings */ -enum ixgbe_fc_type { +enum ixgbe_fc_mode { ixgbe_fc_none = 0, ixgbe_fc_rx_pause, ixgbe_fc_tx_pause, @@ -1294,8 +1316,8 @@ struct ixgbe_fc_info { u16 pause_time; /* Flow Control Pause timer */ bool send_xon; /* Flow control send XON */ bool strict_ieee; /* Strict IEEE mode */ - enum ixgbe_fc_type type; /* Type of flow control */ - enum ixgbe_fc_type original_type; + enum ixgbe_fc_mode current_mode; /* FC mode in effect */ + enum ixgbe_fc_mode requested_mode; /* FC mode requested by caller */ }; /* Statistics counters collected by the MAC */ @@ -1475,6 +1497,7 @@ struct ixgbe_phy_info { bool reset_disable; ixgbe_autoneg_advertised autoneg_advertised; bool autoneg_wait_to_complete; + bool multispeed_fiber; }; struct ixgbe_hw { -- GitLab From 12207e498b9b8f9f0c946db079ad17c7ca16cdf3 Mon Sep 17 00:00:00 2001 From: Peter P Waskiewicz Jr Date: Fri, 6 Feb 2009 21:47:24 -0800 Subject: [PATCH 1291/4982] ixgbe: Defeature Tx Head writeback Tx Head writeback is causing multi-microsecond stalls on PCIe chipsets, due to partial cacheline writebacks. Removing this feature removes these issues. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 60 +++++++++++++--------------------- 1 file changed, 23 insertions(+), 37 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 850361a4c38..8e270b63e80 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -204,9 +204,6 @@ static inline bool ixgbe_check_tx_hang(struct ixgbe_adapter *adapter, #define DESC_NEEDED (TXD_USE_COUNT(IXGBE_MAX_DATA_PER_TXD) /* skb->data */ + \ MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1) /* for context */ -#define GET_TX_HEAD_FROM_RING(ring) (\ - *(volatile u32 *) \ - ((union ixgbe_adv_tx_desc *)(ring)->desc + (ring)->count)) static void ixgbe_tx_timeout(struct net_device *netdev); /** @@ -217,26 +214,27 @@ static void ixgbe_tx_timeout(struct net_device *netdev); static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter, struct ixgbe_ring *tx_ring) { - union ixgbe_adv_tx_desc *tx_desc; - struct ixgbe_tx_buffer *tx_buffer_info; struct net_device *netdev = adapter->netdev; - struct sk_buff *skb; - unsigned int i; - u32 head, oldhead; - unsigned int count = 0; + union ixgbe_adv_tx_desc *tx_desc, *eop_desc; + struct ixgbe_tx_buffer *tx_buffer_info; + unsigned int i, eop, count = 0; unsigned int total_bytes = 0, total_packets = 0; - rmb(); - head = GET_TX_HEAD_FROM_RING(tx_ring); - head = le32_to_cpu(head); i = tx_ring->next_to_clean; - while (1) { - while (i != head) { + eop = tx_ring->tx_buffer_info[i].next_to_watch; + eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); + + while ((eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) && + (count < tx_ring->count)) { + bool cleaned = false; + for ( ; !cleaned; count++) { + struct sk_buff *skb; tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i); tx_buffer_info = &tx_ring->tx_buffer_info[i]; + cleaned = (i == eop); skb = tx_buffer_info->skb; - if (skb) { + if (cleaned && skb) { unsigned int segs, bytecount; /* gso_segs is currently only valid for tcp */ @@ -251,23 +249,17 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter, ixgbe_unmap_and_free_tx_resource(adapter, tx_buffer_info); + tx_desc->wb.status = 0; + i++; if (i == tx_ring->count) i = 0; - - count++; - if (count == tx_ring->count) - goto done_cleaning; } - oldhead = head; - rmb(); - head = GET_TX_HEAD_FROM_RING(tx_ring); - head = le32_to_cpu(head); - if (head == oldhead) - goto done_cleaning; - } /* while (1) */ - -done_cleaning: + + eop = tx_ring->tx_buffer_info[i].next_to_watch; + eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); + } + tx_ring->next_to_clean = i; #define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) @@ -301,8 +293,8 @@ done_cleaning: tx_ring->total_bytes += total_bytes; tx_ring->total_packets += total_packets; - tx_ring->stats.bytes += total_bytes; tx_ring->stats.packets += total_packets; + tx_ring->stats.bytes += total_bytes; adapter->net_stats.tx_bytes += total_bytes; adapter->net_stats.tx_packets += total_packets; return (total_packets ? true : false); @@ -1484,7 +1476,7 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter) **/ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter) { - u64 tdba, tdwba; + u64 tdba; struct ixgbe_hw *hw = &adapter->hw; u32 i, j, tdlen, txctrl; @@ -1497,11 +1489,6 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j), (tdba & DMA_32BIT_MASK)); IXGBE_WRITE_REG(hw, IXGBE_TDBAH(j), (tdba >> 32)); - tdwba = ring->dma + - (ring->count * sizeof(union ixgbe_adv_tx_desc)); - tdwba |= IXGBE_TDWBAL_HEAD_WB_ENABLE; - IXGBE_WRITE_REG(hw, IXGBE_TDWBAL(j), tdwba & DMA_32BIT_MASK); - IXGBE_WRITE_REG(hw, IXGBE_TDWBAH(j), (tdwba >> 32)); IXGBE_WRITE_REG(hw, IXGBE_TDLEN(j), tdlen); IXGBE_WRITE_REG(hw, IXGBE_TDH(j), 0); IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0); @@ -2880,8 +2867,7 @@ int ixgbe_setup_tx_resources(struct ixgbe_adapter *adapter, memset(tx_ring->tx_buffer_info, 0, size); /* round up to nearest 4K */ - tx_ring->size = tx_ring->count * sizeof(union ixgbe_adv_tx_desc) + - sizeof(u32); + tx_ring->size = tx_ring->count * sizeof(union ixgbe_adv_tx_desc); tx_ring->size = ALIGN(tx_ring->size, 4096); tx_ring->desc = pci_alloc_consistent(pdev, tx_ring->size, -- GitLab From 69ebbf58f3dff9fb4e5240e472b5869fa869dae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Fri, 6 Feb 2009 23:46:51 -0800 Subject: [PATCH 1292/4982] ipmr: use goto to common label instead of opencoding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/ipmr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 21a6dc710f2..13e9dd3012b 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1243,8 +1243,7 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) vif->dev->stats.tx_bytes += skb->len; vif->dev->stats.tx_packets++; ipmr_cache_report(net, skb, vifi, IGMPMSG_WHOLEPKT); - kfree_skb(skb); - return; + goto out_free; } #endif -- GitLab From 910d30b704542b49f83881a4832d8414c6c3d9c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Fri, 6 Feb 2009 23:47:14 -0800 Subject: [PATCH 1293/4982] ax25: more common return path joining MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ilpo Järvinen Acked-by: Ralf Baechle Signed-off-by: David S. Miller --- net/ax25/ax25_iface.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/net/ax25/ax25_iface.c b/net/ax25/ax25_iface.c index 8443af57a37..71338f11210 100644 --- a/net/ax25/ax25_iface.c +++ b/net/ax25/ax25_iface.c @@ -61,27 +61,24 @@ void ax25_protocol_release(unsigned int pid) write_lock_bh(&protocol_list_lock); protocol = protocol_list; - if (protocol == NULL) { - write_unlock_bh(&protocol_list_lock); - return; - } + if (protocol == NULL) + goto out; if (protocol->pid == pid) { protocol_list = protocol->next; - write_unlock_bh(&protocol_list_lock); - return; + goto out; } while (protocol != NULL && protocol->next != NULL) { if (protocol->next->pid == pid) { s = protocol->next; protocol->next = protocol->next->next; - write_unlock_bh(&protocol_list_lock); - return; + goto out; } protocol = protocol->next; } +out: write_unlock_bh(&protocol_list_lock); } -- GitLab From d73f08011bc30c03a2bcb1ccd880e4be84aea269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Fri, 6 Feb 2009 23:47:37 -0800 Subject: [PATCH 1294/4982] ipv6/ndisc: join error paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv6/ndisc.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 3e2970841bd..3cd83b85e9e 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1538,13 +1538,10 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, if (rt->rt6i_flags & RTF_GATEWAY) { ND_PRINTK2(KERN_WARNING "ICMPv6 Redirect: destination is not a neighbour.\n"); - dst_release(dst); - return; - } - if (!xrlim_allow(dst, 1*HZ)) { - dst_release(dst); - return; + goto release; } + if (!xrlim_allow(dst, 1*HZ)) + goto release; if (dev->addr_len) { read_lock_bh(&neigh->lock); @@ -1570,8 +1567,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, ND_PRINTK0(KERN_ERR "ICMPv6 Redirect: %s() failed to allocate an skb.\n", __func__); - dst_release(dst); - return; + goto release; } skb_reserve(buff, LL_RESERVED_SPACE(dev)); @@ -1631,6 +1627,10 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, if (likely(idev != NULL)) in6_dev_put(idev); + return; + +release: + dst_release(dst); } static void pndisc_redo(struct sk_buff *skb) -- GitLab From b5f348e5a41b39543c1c5efd661d7fd296dd5281 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Fri, 6 Feb 2009 23:48:01 -0800 Subject: [PATCH 1295/4982] ipv6/addrconf: common code located MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit $ codiff net/ipv6/addrconf.o net/ipv6/addrconf.o.new net/ipv6/addrconf.c: addrconf_notify | -267 1 function changed, 267 bytes removed net/ipv6/addrconf.c: add_addr | +86 1 function changed, 86 bytes added net/ipv6/addrconf.o.new: 2 functions changed, 86 bytes added, 267 bytes removed, diff: -181 Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 45 ++++++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index f9afb452249..03e2a1ad71e 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2224,10 +2224,24 @@ int addrconf_del_ifaddr(struct net *net, void __user *arg) return err; } +static void add_addr(struct inet6_dev *idev, const struct in6_addr *addr, + int plen, int scope) +{ + struct inet6_ifaddr *ifp; + + ifp = ipv6_add_addr(idev, addr, plen, scope, IFA_F_PERMANENT); + if (!IS_ERR(ifp)) { + spin_lock_bh(&ifp->lock); + ifp->flags &= ~IFA_F_TENTATIVE; + spin_unlock_bh(&ifp->lock); + ipv6_ifa_notify(RTM_NEWADDR, ifp); + in6_ifa_put(ifp); + } +} + #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) static void sit_add_v4_addrs(struct inet6_dev *idev) { - struct inet6_ifaddr * ifp; struct in6_addr addr; struct net_device *dev; struct net *net = dev_net(idev->dev); @@ -2246,14 +2260,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) } if (addr.s6_addr32[3]) { - ifp = ipv6_add_addr(idev, &addr, 128, scope, IFA_F_PERMANENT); - if (!IS_ERR(ifp)) { - spin_lock_bh(&ifp->lock); - ifp->flags &= ~IFA_F_TENTATIVE; - spin_unlock_bh(&ifp->lock); - ipv6_ifa_notify(RTM_NEWADDR, ifp); - in6_ifa_put(ifp); - } + add_addr(idev, &addr, 128, scope); return; } @@ -2281,15 +2288,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) else plen = 96; - ifp = ipv6_add_addr(idev, &addr, plen, flag, - IFA_F_PERMANENT); - if (!IS_ERR(ifp)) { - spin_lock_bh(&ifp->lock); - ifp->flags &= ~IFA_F_TENTATIVE; - spin_unlock_bh(&ifp->lock); - ipv6_ifa_notify(RTM_NEWADDR, ifp); - in6_ifa_put(ifp); - } + add_addr(idev, &addr, plen, flag); } } } @@ -2299,7 +2298,6 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) static void init_loopback(struct net_device *dev) { struct inet6_dev *idev; - struct inet6_ifaddr * ifp; /* ::1 */ @@ -2310,14 +2308,7 @@ static void init_loopback(struct net_device *dev) return; } - ifp = ipv6_add_addr(idev, &in6addr_loopback, 128, IFA_HOST, IFA_F_PERMANENT); - if (!IS_ERR(ifp)) { - spin_lock_bh(&ifp->lock); - ifp->flags &= ~IFA_F_TENTATIVE; - spin_unlock_bh(&ifp->lock); - ipv6_ifa_notify(RTM_NEWADDR, ifp); - in6_ifa_put(ifp); - } + add_addr(idev, &in6addr_loopback, 128, IFA_HOST); } static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr) -- GitLab From 1f0fa15432e49547c3fa915644c7e0c0975809e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Fri, 6 Feb 2009 23:48:33 -0800 Subject: [PATCH 1296/4982] net/sunrpc/xprtsock.c: some common code found MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit $ diff-funcs xs_udp_write_space net/sunrpc/xprtsock.c net/sunrpc/xprtsock.c xs_tcp_write_space --- net/sunrpc/xprtsock.c:xs_udp_write_space() +++ net/sunrpc/xprtsock.c:xs_tcp_write_space() @@ -1,4 +1,4 @@ - * xs_udp_write_space - callback invoked when socket buffer space + * xs_tcp_write_space - callback invoked when socket buffer space * becomes available * @sk: socket whose state has changed * @@ -7,12 +7,12 @@ * progress, otherwise we'll waste resources thrashing kernel_sendmsg * with a bunch of small requests. */ -static void xs_udp_write_space(struct sock *sk) +static void xs_tcp_write_space(struct sock *sk) { read_lock(&sk->sk_callback_lock); - /* from net/core/sock.c:sock_def_write_space */ - if (sock_writeable(sk)) { + /* from net/core/stream.c:sk_stream_write_space */ + if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) { struct socket *sock; struct rpc_xprt *xprt; $ codiff net/sunrpc/xprtsock.o net/sunrpc/xprtsock.o.new net/sunrpc/xprtsock.c: xs_tcp_write_space | -163 xs_udp_write_space | -163 2 functions changed, 326 bytes removed net/sunrpc/xprtsock.c: xs_write_space | +179 1 function changed, 179 bytes added net/sunrpc/xprtsock.o.new: 3 functions changed, 179 bytes added, 326 bytes removed, diff: -147 Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/sunrpc/xprtsock.c | 53 +++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 5cbb404c4cd..b49e434c094 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1215,6 +1215,23 @@ out: read_unlock(&sk->sk_callback_lock); } +static void xs_write_space(struct sock *sk) +{ + struct socket *sock; + struct rpc_xprt *xprt; + + if (unlikely(!(sock = sk->sk_socket))) + return; + clear_bit(SOCK_NOSPACE, &sock->flags); + + if (unlikely(!(xprt = xprt_from_sock(sk)))) + return; + if (test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags) == 0) + return; + + xprt_write_space(xprt); +} + /** * xs_udp_write_space - callback invoked when socket buffer space * becomes available @@ -1230,23 +1247,9 @@ static void xs_udp_write_space(struct sock *sk) read_lock(&sk->sk_callback_lock); /* from net/core/sock.c:sock_def_write_space */ - if (sock_writeable(sk)) { - struct socket *sock; - struct rpc_xprt *xprt; - - if (unlikely(!(sock = sk->sk_socket))) - goto out; - clear_bit(SOCK_NOSPACE, &sock->flags); - - if (unlikely(!(xprt = xprt_from_sock(sk)))) - goto out; - if (test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags) == 0) - goto out; - - xprt_write_space(xprt); - } + if (sock_writeable(sk)) + xs_write_space(sk); - out: read_unlock(&sk->sk_callback_lock); } @@ -1265,23 +1268,9 @@ static void xs_tcp_write_space(struct sock *sk) read_lock(&sk->sk_callback_lock); /* from net/core/stream.c:sk_stream_write_space */ - if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) { - struct socket *sock; - struct rpc_xprt *xprt; - - if (unlikely(!(sock = sk->sk_socket))) - goto out; - clear_bit(SOCK_NOSPACE, &sock->flags); + if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) + xs_write_space(sk); - if (unlikely(!(xprt = xprt_from_sock(sk)))) - goto out; - if (test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags) == 0) - goto out; - - xprt_write_space(xprt); - } - - out: read_unlock(&sk->sk_callback_lock); } -- GitLab From cac1c52c3621b46e3be49cf7887a7cfa393890de Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Sat, 7 Feb 2009 00:23:57 -0800 Subject: [PATCH 1297/4982] forcedeth: mgmt unit interface This patch updates the logic used to communicate with the mgmt unit. It also adds a version check for a newer mgmt unit firmware. * Fixed udelay to schedule_timeout_uninterruptible Signed-off-by: Ayaz Abdulla Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 98 ++++++++++++++++++++++++++++++++++------- 1 file changed, 82 insertions(+), 16 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 7825be7586f..da7c9ee069b 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -157,6 +157,9 @@ enum { #define NVREG_XMITCTL_HOST_SEMA_ACQ 0x0000f000 #define NVREG_XMITCTL_HOST_LOADED 0x00004000 #define NVREG_XMITCTL_TX_PATH_EN 0x01000000 +#define NVREG_XMITCTL_DATA_START 0x00100000 +#define NVREG_XMITCTL_DATA_READY 0x00010000 +#define NVREG_XMITCTL_DATA_ERROR 0x00020000 NvRegTransmitterStatus = 0x088, #define NVREG_XMITSTAT_BUSY 0x01 @@ -289,8 +292,10 @@ enum { #define NVREG_WAKEUPFLAGS_ACCEPT_LINKCHANGE 0x04 #define NVREG_WAKEUPFLAGS_ENABLE 0x1111 - NvRegPatternCRC = 0x204, - NvRegPatternMask = 0x208, + NvRegMgmtUnitGetVersion = 0x204, +#define NVREG_MGMTUNITGETVERSION 0x01 + NvRegMgmtUnitVersion = 0x208, +#define NVREG_MGMTUNITVERSION 0x08 NvRegPowerCap = 0x268, #define NVREG_POWERCAP_D3SUPP (1<<30) #define NVREG_POWERCAP_D2SUPP (1<<26) @@ -303,6 +308,8 @@ enum { #define NVREG_POWERSTATE_D1 0x0001 #define NVREG_POWERSTATE_D2 0x0002 #define NVREG_POWERSTATE_D3 0x0003 + NvRegMgmtUnitControl = 0x278, +#define NVREG_MGMTUNITCONTROL_INUSE 0x20000 NvRegTxCnt = 0x280, NvRegTxZeroReXmt = 0x284, NvRegTxOneReXmt = 0x288, @@ -758,6 +765,8 @@ struct fe_priv { u32 register_size; int rx_csum; u32 mac_in_use; + int mgmt_version; + int mgmt_sema; void __iomem *base; @@ -5182,6 +5191,7 @@ static void nv_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) /* The mgmt unit and driver use a semaphore to access the phy during init */ static int nv_mgmt_acquire_sema(struct net_device *dev) { + struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); int i; u32 tx_ctrl, mgmt_sema; @@ -5204,8 +5214,10 @@ static int nv_mgmt_acquire_sema(struct net_device *dev) /* verify that semaphore was acquired */ tx_ctrl = readl(base + NvRegTransmitterControl); if (((tx_ctrl & NVREG_XMITCTL_HOST_SEMA_MASK) == NVREG_XMITCTL_HOST_SEMA_ACQ) && - ((tx_ctrl & NVREG_XMITCTL_MGMT_SEMA_MASK) == NVREG_XMITCTL_MGMT_SEMA_FREE)) + ((tx_ctrl & NVREG_XMITCTL_MGMT_SEMA_MASK) == NVREG_XMITCTL_MGMT_SEMA_FREE)) { + np->mgmt_sema = 1; return 1; + } else udelay(50); } @@ -5213,6 +5225,51 @@ static int nv_mgmt_acquire_sema(struct net_device *dev) return 0; } +static void nv_mgmt_release_sema(struct net_device *dev) +{ + struct fe_priv *np = netdev_priv(dev); + u8 __iomem *base = get_hwbase(dev); + u32 tx_ctrl; + + if (np->driver_data & DEV_HAS_MGMT_UNIT) { + if (np->mgmt_sema) { + tx_ctrl = readl(base + NvRegTransmitterControl); + tx_ctrl &= ~NVREG_XMITCTL_HOST_SEMA_ACQ; + writel(tx_ctrl, base + NvRegTransmitterControl); + } + } +} + + +static int nv_mgmt_get_version(struct net_device *dev) +{ + struct fe_priv *np = netdev_priv(dev); + u8 __iomem *base = get_hwbase(dev); + u32 data_ready = readl(base + NvRegTransmitterControl); + u32 data_ready2 = 0; + unsigned long start; + int ready = 0; + + writel(NVREG_MGMTUNITGETVERSION, base + NvRegMgmtUnitGetVersion); + writel(data_ready ^ NVREG_XMITCTL_DATA_START, base + NvRegTransmitterControl); + start = jiffies; + while (time_before(jiffies, start + 5*HZ)) { + data_ready2 = readl(base + NvRegTransmitterControl); + if ((data_ready & NVREG_XMITCTL_DATA_READY) != (data_ready2 & NVREG_XMITCTL_DATA_READY)) { + ready = 1; + break; + } + schedule_timeout_uninterruptible(1); + } + + if (!ready || (data_ready2 & NVREG_XMITCTL_DATA_ERROR)) + return 0; + + np->mgmt_version = readl(base + NvRegMgmtUnitVersion) & NVREG_MGMTUNITVERSION; + + return 1; +} + static int nv_open(struct net_device *dev) { struct fe_priv *np = netdev_priv(dev); @@ -5784,19 +5841,26 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i if (id->driver_data & DEV_HAS_MGMT_UNIT) { /* management unit running on the mac? */ - if (readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_PHY_INIT) { - np->mac_in_use = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_ST; - dprintk(KERN_INFO "%s: mgmt unit is running. mac in use %x.\n", pci_name(pci_dev), np->mac_in_use); - if (nv_mgmt_acquire_sema(dev)) { - /* management unit setup the phy already? */ - if ((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK) == - NVREG_XMITCTL_SYNC_PHY_INIT) { - /* phy is inited by mgmt unit */ - phyinitialized = 1; - dprintk(KERN_INFO "%s: Phy already initialized by mgmt unit.\n", pci_name(pci_dev)); - } else { - /* we need to init the phy */ - } + if ((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_ST) && + (readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_PHY_INIT) && + nv_mgmt_acquire_sema(dev) && + nv_mgmt_get_version(dev)) { + np->mac_in_use = 1; + if (np->mgmt_version > 0) { + np->mac_in_use = readl(base + NvRegMgmtUnitControl) & NVREG_MGMTUNITCONTROL_INUSE; + } + dprintk(KERN_INFO "%s: mgmt unit is running. mac in use %x.\n", + pci_name(pci_dev), np->mac_in_use); + /* management unit setup the phy already? */ + if (np->mac_in_use && + ((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK) == + NVREG_XMITCTL_SYNC_PHY_INIT)) { + /* phy is inited by mgmt unit */ + phyinitialized = 1; + dprintk(KERN_INFO "%s: Phy already initialized by mgmt unit.\n", + pci_name(pci_dev)); + } else { + /* we need to init the phy */ } } } @@ -5958,6 +6022,8 @@ static void __devexit nv_remove(struct pci_dev *pci_dev) /* restore any phy related changes */ nv_restore_phy(dev); + nv_mgmt_release_sema(dev); + /* free all structures */ free_rings(dev); iounmap(get_hwbase(dev)); -- GitLab From b6e4405bf7241ae91c497e021370066fcfb196c8 Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Sat, 7 Feb 2009 00:24:15 -0800 Subject: [PATCH 1298/4982] forcedeth: msi interrupt fix This patch fixes an issue with the suspend/resume cycle with msi interrupts. See bugzilla number 10487 for more details. The fix is to re-setup a private msi pci config offset field. Signed-off-by: Ayaz Abdulla Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index da7c9ee069b..47962ed4b04 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -589,6 +589,9 @@ union ring_type { #define NV_MSI_X_VECTOR_TX 0x1 #define NV_MSI_X_VECTOR_OTHER 0x2 +#define NV_MSI_PRIV_OFFSET 0x68 +#define NV_MSI_PRIV_VALUE 0xffffffff + #define NV_RESTART_TX 0x1 #define NV_RESTART_RX 0x2 @@ -6074,6 +6077,8 @@ static int nv_resume(struct pci_dev *pdev) for (i = 0;i <= np->register_size/sizeof(u32); i++) writel(np->saved_config_space[i], base+i*sizeof(u32)); + pci_write_config_dword(pdev, NV_MSI_PRIV_OFFSET, NV_MSI_PRIV_VALUE); + netif_device_attach(dev); if (netif_running(dev)) { rc = nv_open(dev); -- GitLab From c1086cda7d46885d672d282af04d1273b001442f Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Sat, 7 Feb 2009 00:24:39 -0800 Subject: [PATCH 1299/4982] forcedeth: ethtool tx csum fix This patch fixes the ethtool tx csum "set" command. A recent patch was submitted to remove HW_CSUM and use IP_CSUM instead. Therefore, the corresponding ethtool command should also be modified. Signed-off-by: Ayaz Abdulla Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 47962ed4b04..cb41897f286 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -4763,7 +4763,7 @@ static int nv_set_tx_csum(struct net_device *dev, u32 data) struct fe_priv *np = netdev_priv(dev); if (np->driver_data & DEV_HAS_CHECKSUM) - return ethtool_op_set_tx_hw_csum(dev, data); + return ethtool_op_set_tx_csum(dev, data); else return -EOPNOTSUPP; } -- GitLab From daa91a9d2402d33b70b8685dee6fd3e517bf34a9 Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Sat, 7 Feb 2009 00:25:00 -0800 Subject: [PATCH 1300/4982] forcedeth: recover error support This patch adds another type of recoverable error to the driver. It also modifies the sequence for recovery to include a mac reset and clearing of interrupts. Signed-off-by: Ayaz Abdulla Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index cb41897f286..e32b8e481b3 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -102,7 +102,7 @@ enum { NvRegIrqStatus = 0x000, #define NVREG_IRQSTAT_MIIEVENT 0x040 -#define NVREG_IRQSTAT_MASK 0x81ff +#define NVREG_IRQSTAT_MASK 0x83ff NvRegIrqMask = 0x004, #define NVREG_IRQ_RX_ERROR 0x0001 #define NVREG_IRQ_RX 0x0002 @@ -113,7 +113,7 @@ enum { #define NVREG_IRQ_LINK 0x0040 #define NVREG_IRQ_RX_FORCED 0x0080 #define NVREG_IRQ_TX_FORCED 0x0100 -#define NVREG_IRQ_RECOVER_ERROR 0x8000 +#define NVREG_IRQ_RECOVER_ERROR 0x8200 #define NVREG_IRQMASK_THROUGHPUT 0x00df #define NVREG_IRQMASK_CPU 0x0060 #define NVREG_IRQ_TX_ALL (NVREG_IRQ_TX_ERR|NVREG_IRQ_TX_OK|NVREG_IRQ_TX_FORCED) @@ -4073,13 +4073,15 @@ static void nv_do_nic_poll(unsigned long data) if (np->recover_error) { np->recover_error = 0; - printk(KERN_INFO "forcedeth: MAC in recoverable error state\n"); + printk(KERN_INFO "%s: MAC in recoverable error state\n", dev->name); if (netif_running(dev)) { netif_tx_lock_bh(dev); netif_addr_lock(dev); spin_lock(&np->lock); /* stop engines */ nv_stop_rxtx(dev); + if (np->driver_data & DEV_HAS_POWER_CNTRL) + nv_mac_reset(dev); nv_txrx_reset(dev); /* drain rx queue */ nv_drain_rxtx(dev); @@ -4097,6 +4099,11 @@ static void nv_do_nic_poll(unsigned long data) pci_push(base); writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl); pci_push(base); + /* clear interrupts */ + if (!(np->msi_flags & NV_MSI_X_ENABLED)) + writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); + else + writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus); /* restart rx engine */ nv_start_rxtx(dev); -- GitLab From 2813ddd1bfd681a2fcc1d95530b399a92da89556 Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Sat, 7 Feb 2009 00:25:18 -0800 Subject: [PATCH 1301/4982] forcedeth: bump version to 63 This patch bumps the version up to 63 Signed-off-by: Ayaz Abdulla Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index e32b8e481b3..021308f9f0c 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -39,7 +39,7 @@ * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few * superfluous timer interrupts from the nic. */ -#define FORCEDETH_VERSION "0.62" +#define FORCEDETH_VERSION "0.63" #define DRV_NAME "forcedeth" #include -- GitLab From 3e450669cc7060d56d886f53e31182f5fef103c7 Mon Sep 17 00:00:00 2001 From: Peter P Waskiewicz Jr Date: Sat, 7 Feb 2009 02:16:59 -0800 Subject: [PATCH 1302/4982] ixgbe: Fix a set_num_queues() bug that can result in num_(r|t)x_queues = 0 Now that our set_num_queues() routines for each feature are re-entrant, and can be called at any point, they shouldn't zero out the feature's indices or mask bits. Subsequent calls into those routines for those features can result in zero Rx and Tx queues being assigned, causing a panic later in driver reinitialization. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 8e270b63e80..a3572d1e0a9 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2350,8 +2350,6 @@ static inline bool ixgbe_set_dcb_queues(struct ixgbe_adapter *adapter) adapter->ring_feature[RING_F_DCB].indices; ret = true; } else { - adapter->ring_feature[RING_F_DCB].mask = 0; - adapter->ring_feature[RING_F_DCB].indices = 0; ret = false; } @@ -2371,8 +2369,6 @@ static inline bool ixgbe_set_rss_queues(struct ixgbe_adapter *adapter) adapter->ring_feature[RING_F_RSS].indices; ret = true; } else { - adapter->ring_feature[RING_F_RSS].mask = 0; - adapter->ring_feature[RING_F_RSS].indices = 0; ret = false; } -- GitLab From 69d3ca5357bb93bb3a139c5d90077407f8828bd1 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:15:04 +0000 Subject: [PATCH 1303/4982] igb: optimize/refactor receive path While cleaning up the skb_over panic with small frames I found there was room for improvement in the ordering of operations within the rx receive flow. These changes will place the prefetch for the next descriptor to a point earlier in the rx path. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 44 +++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 8b80fe34343..21f0c229b64 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3803,6 +3803,7 @@ static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring, unsigned int total_bytes = 0, total_packets = 0; i = rx_ring->next_to_clean; + buffer_info = &rx_ring->buffer_info[i]; rx_desc = E1000_RX_DESC_ADV(*rx_ring, i); staterr = le32_to_cpu(rx_desc->wb.upper.status_error); @@ -3810,25 +3811,22 @@ static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring, if (*work_done >= budget) break; (*work_done)++; - buffer_info = &rx_ring->buffer_info[i]; - /* HW will not DMA in data larger than the given buffer, even - * if it parses the (NFS, of course) header to be larger. In - * that case, it fills the header buffer and spills the rest - * into the page. - */ - hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hdr_info) & - E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT; - if (hlen > adapter->rx_ps_hdr_size) - hlen = adapter->rx_ps_hdr_size; + skb = buffer_info->skb; + prefetch(skb->data - NET_IP_ALIGN); + buffer_info->skb = NULL; + + i++; + if (i == rx_ring->count) + i = 0; + next_rxd = E1000_RX_DESC_ADV(*rx_ring, i); + prefetch(next_rxd); + next_buffer = &rx_ring->buffer_info[i]; length = le16_to_cpu(rx_desc->wb.upper.length); cleaned = true; cleaned_count++; - skb = buffer_info->skb; - prefetch(skb->data - NET_IP_ALIGN); - buffer_info->skb = NULL; if (!adapter->rx_ps_hdr_size) { pci_unmap_single(pdev, buffer_info->dma, adapter->rx_buffer_len + @@ -3838,6 +3836,16 @@ static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring, goto send_up; } + /* HW will not DMA in data larger than the given buffer, even + * if it parses the (NFS, of course) header to be larger. In + * that case, it fills the header buffer and spills the rest + * into the page. + */ + hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hdr_info) & + E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT; + if (hlen > adapter->rx_ps_hdr_size) + hlen = adapter->rx_ps_hdr_size; + if (!skb_shinfo(skb)->nr_frags) { pci_unmap_single(pdev, buffer_info->dma, adapter->rx_ps_hdr_size + @@ -3867,13 +3875,6 @@ static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring, skb->truesize += length; } -send_up: - i++; - if (i == rx_ring->count) - i = 0; - next_rxd = E1000_RX_DESC_ADV(*rx_ring, i); - prefetch(next_rxd); - next_buffer = &rx_ring->buffer_info[i]; if (!(staterr & E1000_RXD_STAT_EOP)) { buffer_info->skb = next_buffer->skb; @@ -3882,7 +3883,7 @@ send_up: next_buffer->dma = 0; goto next_desc; } - +send_up: if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) { dev_kfree_skb_irq(skb); goto next_desc; @@ -3909,7 +3910,6 @@ next_desc: /* use prefetched values */ rx_desc = next_rxd; buffer_info = next_buffer; - staterr = le32_to_cpu(rx_desc->wb.upper.status_error); } -- GitLab From db76176215ec5af7a67386e0eacb5ea53e040f10 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:15:25 +0000 Subject: [PATCH 1304/4982] igb: move setting of buffsz out of repeated path in alloc_rx_buffers buffsz is being repeatedly set when allocaing buffers. Since this value should only need to be set once in the function I am moving it out of the looped portion of the path. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 21f0c229b64..ec5855a10ff 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3943,10 +3943,17 @@ static void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, struct igb_buffer *buffer_info; struct sk_buff *skb; unsigned int i; + int bufsz; i = rx_ring->next_to_use; buffer_info = &rx_ring->buffer_info[i]; + if (adapter->rx_ps_hdr_size) + bufsz = adapter->rx_ps_hdr_size; + else + bufsz = adapter->rx_buffer_len; + bufsz += NET_IP_ALIGN; + while (cleaned_count--) { rx_desc = E1000_RX_DESC_ADV(*rx_ring, i); @@ -3962,23 +3969,14 @@ static void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, buffer_info->page_offset ^= PAGE_SIZE / 2; } buffer_info->page_dma = - pci_map_page(pdev, - buffer_info->page, + pci_map_page(pdev, buffer_info->page, buffer_info->page_offset, PAGE_SIZE / 2, PCI_DMA_FROMDEVICE); } if (!buffer_info->skb) { - int bufsz; - - if (adapter->rx_ps_hdr_size) - bufsz = adapter->rx_ps_hdr_size; - else - bufsz = adapter->rx_buffer_len; - bufsz += NET_IP_ALIGN; skb = netdev_alloc_skb(netdev, bufsz); - if (!skb) { adapter->alloc_rx_buff_failed++; goto no_buffers; @@ -3994,7 +3992,6 @@ static void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, buffer_info->dma = pci_map_single(pdev, skb->data, bufsz, PCI_DMA_FROMDEVICE); - } /* Refresh the desc even if buffer_addrs didn't change because * each write-back erases this info. */ -- GitLab From 83b7180d0da2a8ff92baa6a35f6871aeb74d9bec Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:15:45 +0000 Subject: [PATCH 1305/4982] igb: move initialization of number of queues into set_interrupt_capability This patch moves the initialization of the number of queues into set_interrupt_capability. This allows the number of queues to increase in the unlikely event that the system initially fails to allocate enough msi-x interrupts, does a suspend/resume, and then can allocate enough interrupts on resume. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index ec5855a10ff..6ef0adb7a06 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -543,6 +543,11 @@ static void igb_set_interrupt_capability(struct igb_adapter *adapter) int err; int numvecs, i; + /* Number of supported queues. */ + /* Having more queues than CPUs doesn't make sense. */ + adapter->num_rx_queues = min_t(u32, IGB_MAX_RX_QUEUES, num_online_cpus()); + adapter->num_tx_queues = min_t(u32, IGB_MAX_TX_QUEUES, num_online_cpus()); + numvecs = adapter->num_tx_queues + adapter->num_rx_queues + 1; adapter->msix_entries = kcalloc(numvecs, sizeof(struct msix_entry), GFP_KERNEL); @@ -1450,11 +1455,6 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter) adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; - /* Number of supported queues. */ - /* Having more queues than CPUs doesn't make sense. */ - adapter->num_rx_queues = min_t(u32, IGB_MAX_RX_QUEUES, num_online_cpus()); - adapter->num_tx_queues = min_t(u32, IGB_MAX_TX_QUEUES, num_online_cpus()); - /* This call may decrease the number of queues depending on * interrupt mode. */ igb_set_interrupt_capability(adapter); -- GitLab From aed5dec370e294233d647251ce1e5f74d70b09c9 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:16:04 +0000 Subject: [PATCH 1306/4982] igb: remove check for needing an io port Since igb supports only pci-e nics and there is no plan to support any legacy pci parts in the driver there isn't really much need for checking to see if an io port is needed. In the unlikely event that we do begin supporting legacy pci parts then we can see about adding this code back to the driver. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb.h | 4 --- drivers/net/igb/igb_main.c | 50 ++++++++------------------------------ 2 files changed, 10 insertions(+), 44 deletions(-) diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 30657ddf484..530d7aa4cb8 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -273,10 +273,6 @@ struct igb_adapter { unsigned int flags; u32 eeprom_wol; - /* for ioport free */ - int bars; - int need_ioport; - struct igb_ring *multi_tx_table[IGB_MAX_TX_QUEUES]; unsigned int tx_ring_count; unsigned int rx_ring_count; diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 6ef0adb7a06..13b10ba8a3c 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -974,21 +974,6 @@ void igb_reset(struct igb_adapter *adapter) igb_get_phy_info(&adapter->hw); } -/** - * igb_is_need_ioport - determine if an adapter needs ioport resources or not - * @pdev: PCI device information struct - * - * Returns true if an adapter needs ioport resources - **/ -static int igb_is_need_ioport(struct pci_dev *pdev) -{ - switch (pdev->device) { - /* Currently there are no adapters that need ioport resources */ - default: - return false; - } -} - static const struct net_device_ops igb_netdev_ops = { .ndo_open = igb_open, .ndo_stop = igb_close, @@ -1032,17 +1017,8 @@ static int __devinit igb_probe(struct pci_dev *pdev, u16 eeprom_data = 0, state = 0; u16 eeprom_apme_mask = IGB_EEPROM_APME; u32 part_num; - int bars, need_ioport; - /* do not allocate ioport bars when not needed */ - need_ioport = igb_is_need_ioport(pdev); - if (need_ioport) { - bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO); - err = pci_enable_device(pdev); - } else { - bars = pci_select_bars(pdev, IORESOURCE_MEM); - err = pci_enable_device_mem(pdev); - } + err = pci_enable_device_mem(pdev); if (err) return err; @@ -1085,7 +1061,9 @@ static int __devinit igb_probe(struct pci_dev *pdev, break; } - err = pci_request_selected_regions(pdev, bars, igb_driver_name); + err = pci_request_selected_regions(pdev, pci_select_bars(pdev, + IORESOURCE_MEM), + igb_driver_name); if (err) goto err_pci_reg; @@ -1113,8 +1091,6 @@ static int __devinit igb_probe(struct pci_dev *pdev, hw = &adapter->hw; hw->back = adapter; adapter->msg_enable = NETIF_MSG_DRV | NETIF_MSG_PROBE; - adapter->bars = bars; - adapter->need_ioport = need_ioport; mmio_start = pci_resource_start(pdev, 0); mmio_len = pci_resource_len(pdev, 0); @@ -1361,7 +1337,8 @@ err_hw_init: err_ioremap: free_netdev(netdev); err_alloc_etherdev: - pci_release_selected_regions(pdev, bars); + pci_release_selected_regions(pdev, pci_select_bars(pdev, + IORESOURCE_MEM)); err_pci_reg: err_dma: pci_disable_device(pdev); @@ -1420,7 +1397,8 @@ static void __devexit igb_remove(struct pci_dev *pdev) iounmap(adapter->hw.hw_addr); if (adapter->hw.flash_address) iounmap(adapter->hw.flash_address); - pci_release_selected_regions(pdev, adapter->bars); + pci_release_selected_regions(pdev, pci_select_bars(pdev, + IORESOURCE_MEM)); free_netdev(netdev); @@ -4309,10 +4287,7 @@ static int igb_resume(struct pci_dev *pdev) pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); - if (adapter->need_ioport) - err = pci_enable_device(pdev); - else - err = pci_enable_device_mem(pdev); + err = pci_enable_device_mem(pdev); if (err) { dev_err(&pdev->dev, "igb: Cannot enable PCI device from suspend\n"); @@ -4423,12 +4398,7 @@ static pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev) pci_ers_result_t result; int err; - if (adapter->need_ioport) - err = pci_enable_device(pdev); - else - err = pci_enable_device_mem(pdev); - - if (err) { + if (pci_enable_device_mem(pdev)) { dev_err(&pdev->dev, "Cannot re-enable PCI device after reset.\n"); result = PCI_ERS_RESULT_DISCONNECT; -- GitLab From 4d6b725e4d8e499fad012a25381c8d9bf53fbf4b Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:16:24 +0000 Subject: [PATCH 1307/4982] igb: add link check function Add a link check function to contain all activities related to verifying that the link is present. The current approach is a bit cludgy and needs to be cleaned up. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 59 +++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 13b10ba8a3c..b59088eace1 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2260,6 +2260,46 @@ static void igb_update_phy_info(unsigned long data) igb_get_phy_info(&adapter->hw); } +/** + * igb_has_link - check shared code for link and determine up/down + * @adapter: pointer to driver private info + **/ +static bool igb_has_link(struct igb_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + bool link_active = false; + s32 ret_val = 0; + + /* get_link_status is set on LSC (link status) interrupt or + * rx sequence error interrupt. get_link_status will stay + * false until the e1000_check_for_link establishes link + * for copper adapters ONLY + */ + switch (hw->phy.media_type) { + case e1000_media_type_copper: + if (hw->mac.get_link_status) { + ret_val = hw->mac.ops.check_for_link(hw); + link_active = !hw->mac.get_link_status; + } else { + link_active = true; + } + break; + case e1000_media_type_fiber: + ret_val = hw->mac.ops.check_for_link(hw); + link_active = !!(rd32(E1000_STATUS) & E1000_STATUS_LU); + break; + case e1000_media_type_internal_serdes: + ret_val = hw->mac.ops.check_for_link(hw); + link_active = hw->mac.serdes_has_link; + break; + default: + case e1000_media_type_unknown: + break; + } + + return link_active; +} + /** * igb_watchdog - Timer Call-back * @data: pointer to adapter cast into an unsigned long @@ -2285,25 +2325,10 @@ static void igb_watchdog_task(struct work_struct *work) s32 ret_val; int i; - if ((netif_carrier_ok(netdev)) && - (rd32(E1000_STATUS) & E1000_STATUS_LU)) + link = igb_has_link(adapter); + if ((netif_carrier_ok(netdev)) && link) goto link_up; - ret_val = hw->mac.ops.check_for_link(&adapter->hw); - if ((ret_val == E1000_ERR_PHY) && - (hw->phy.type == e1000_phy_igp_3) && - (rd32(E1000_CTRL) & - E1000_PHY_CTRL_GBE_DISABLE)) - dev_info(&adapter->pdev->dev, - "Gigabit has been disabled, downgrading speed\n"); - - if ((hw->phy.media_type == e1000_media_type_internal_serdes) && - !(rd32(E1000_TXCW) & E1000_TXCW_ANE)) - link = mac->serdes_has_link; - else - link = rd32(E1000_STATUS) & - E1000_STATUS_LU; - if (link) { if (!netif_carrier_ok(netdev)) { u32 ctrl; -- GitLab From c1889bfe687c22f74d1333913ffe8f8da173d601 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:16:45 +0000 Subject: [PATCH 1308/4982] igb: make dev_spec a union and remove dynamic allocation This patch makes dev_spec a union and simplifies it so that it does not require dynamic allocation and freeing in the driver. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_82575.c | 34 +++++----------------------------- drivers/net/igb/e1000_hw.h | 9 +++++++-- drivers/net/igb/e1000_mac.c | 13 ------------- drivers/net/igb/e1000_mac.h | 1 - drivers/net/igb/igb_main.c | 2 -- 5 files changed, 12 insertions(+), 47 deletions(-) diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index f5e4cad7971..ed9e8c0333a 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -62,17 +62,12 @@ static bool igb_sgmii_active_82575(struct e1000_hw *); static s32 igb_reset_init_script_82575(struct e1000_hw *); static s32 igb_read_mac_addr_82575(struct e1000_hw *); - -struct e1000_dev_spec_82575 { - bool sgmii_active; -}; - static s32 igb_get_invariants_82575(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; struct e1000_nvm_info *nvm = &hw->nvm; struct e1000_mac_info *mac = &hw->mac; - struct e1000_dev_spec_82575 *dev_spec; + struct e1000_dev_spec_82575 * dev_spec = &hw->dev_spec._82575; u32 eecd; s32 ret_val; u16 size; @@ -94,17 +89,6 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) break; } - /* MAC initialization */ - hw->dev_spec_size = sizeof(struct e1000_dev_spec_82575); - - /* Device-specific structure allocation */ - hw->dev_spec = kzalloc(hw->dev_spec_size, GFP_KERNEL); - - if (!hw->dev_spec) - return -ENOMEM; - - dev_spec = (struct e1000_dev_spec_82575 *)hw->dev_spec; - /* Set media type */ /* * The 82575 uses bits 22:23 for link mode. The mode can be changed @@ -1234,20 +1218,12 @@ out: **/ static bool igb_sgmii_active_82575(struct e1000_hw *hw) { - struct e1000_dev_spec_82575 *dev_spec; - bool ret_val; + struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; - if (hw->mac.type != e1000_82575) { - ret_val = false; - goto out; - } - - dev_spec = (struct e1000_dev_spec_82575 *)hw->dev_spec; + if (hw->mac.type != e1000_82575 && hw->mac.type != e1000_82576) + return false; - ret_val = dev_spec->sgmii_active; - -out: - return ret_val; + return dev_spec->sgmii_active; } /** diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h index 99504a600a8..06f72ae6a2c 100644 --- a/drivers/net/igb/e1000_hw.h +++ b/drivers/net/igb/e1000_hw.h @@ -565,9 +565,12 @@ struct e1000_fc_info { enum e1000_fc_type original_type; }; +struct e1000_dev_spec_82575 { + bool sgmii_active; +}; + struct e1000_hw { void *back; - void *dev_spec; u8 __iomem *hw_addr; u8 __iomem *flash_address; @@ -580,7 +583,9 @@ struct e1000_hw { struct e1000_bus_info bus; struct e1000_host_mng_dhcp_cookie mng_cookie; - u32 dev_spec_size; + union { + struct e1000_dev_spec_82575 _82575; + } dev_spec; u16 device_id; u16 subsystem_vendor_id; diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c index 97f0049a5d6..16fa0833368 100644 --- a/drivers/net/igb/e1000_mac.c +++ b/drivers/net/igb/e1000_mac.c @@ -37,19 +37,6 @@ static s32 igb_set_default_fc(struct e1000_hw *hw); static s32 igb_set_fc_watermarks(struct e1000_hw *hw); -/** - * igb_remove_device - Free device specific structure - * @hw: pointer to the HW structure - * - * If a device specific structure was allocated, this function will - * free it. - **/ -void igb_remove_device(struct e1000_hw *hw) -{ - /* Freeing the dev_spec member of e1000_hw structure */ - kfree(hw->dev_spec); -} - static s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) { struct igb_adapter *adapter = hw->back; diff --git a/drivers/net/igb/e1000_mac.h b/drivers/net/igb/e1000_mac.h index cbee6af7d91..4ef40d5629d 100644 --- a/drivers/net/igb/e1000_mac.h +++ b/drivers/net/igb/e1000_mac.h @@ -63,7 +63,6 @@ void igb_mta_set(struct e1000_hw *hw, u32 hash_value); void igb_put_hw_semaphore(struct e1000_hw *hw); void igb_rar_set(struct e1000_hw *hw, u8 *addr, u32 index); s32 igb_check_alt_mac_addr(struct e1000_hw *hw); -void igb_remove_device(struct e1000_hw *hw); void igb_reset_adaptive(struct e1000_hw *hw); void igb_update_adaptive(struct e1000_hw *hw); void igb_write_vfta(struct e1000_hw *hw, u32 offset, u32 value); diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index b59088eace1..cb3ac349f3b 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1329,7 +1329,6 @@ err_eeprom: if (hw->flash_address) iounmap(hw->flash_address); - igb_remove_device(hw); igb_free_queues(adapter); err_sw_init: err_hw_init: @@ -1389,7 +1388,6 @@ static void __devexit igb_remove(struct pci_dev *pdev) if (!igb_check_reset_block(&adapter->hw)) igb_reset_phy(&adapter->hw); - igb_remove_device(&adapter->hw); igb_reset_interrupt_capability(adapter); igb_free_queues(adapter); -- GitLab From 40a70b3889ea50daa10a7f3468920c1f5483155d Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:17:06 +0000 Subject: [PATCH 1309/4982] igb: read address from RAH/RAL instead of from EEPROM Instead of pulling the mac address from EEPROM it is easier to pull it from the RAL/RAH registers and then just copy it into the address structures. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_defines.h | 2 ++ drivers/net/igb/e1000_nvm.c | 28 +++++++++++----------------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index 40d03426c12..54a14892338 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -481,6 +481,8 @@ * manageability enabled, allowing us room for 15 multicast addresses. */ #define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */ +#define E1000_RAL_MAC_ADDR_LEN 4 +#define E1000_RAH_MAC_ADDR_LEN 2 /* Error Codes */ #define E1000_ERR_NVM 1 diff --git a/drivers/net/igb/e1000_nvm.c b/drivers/net/igb/e1000_nvm.c index a84e4e429fa..5942da107a9 100644 --- a/drivers/net/igb/e1000_nvm.c +++ b/drivers/net/igb/e1000_nvm.c @@ -515,29 +515,23 @@ out: **/ s32 igb_read_mac_addr(struct e1000_hw *hw) { - s32 ret_val = 0; - u16 offset, nvm_data, i; + u32 rar_high; + u32 rar_low; + u16 i; - for (i = 0; i < ETH_ALEN; i += 2) { - offset = i >> 1; - ret_val = hw->nvm.ops.read_nvm(hw, offset, 1, &nvm_data); - if (ret_val) { - hw_dbg("NVM Read Error\n"); - goto out; - } - hw->mac.perm_addr[i] = (u8)(nvm_data & 0xFF); - hw->mac.perm_addr[i+1] = (u8)(nvm_data >> 8); - } + rar_high = rd32(E1000_RAH(0)); + rar_low = rd32(E1000_RAL(0)); + + for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++) + hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8)); - /* Flip last bit of mac address if we're on second port */ - if (hw->bus.func == E1000_FUNC_1) - hw->mac.perm_addr[5] ^= 1; + for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++) + hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8)); for (i = 0; i < ETH_ALEN; i++) hw->mac.addr[i] = hw->mac.perm_addr[i]; -out: - return ret_val; + return 0; } /** -- GitLab From a8d2a0c27f84bdbf54b7e1c1a52ef7b8b7196dbc Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:17:26 +0000 Subject: [PATCH 1310/4982] igb: rename phy ops This patch renames write_phy_reg to write_reg and read_phy_reg to read_reg. It seems redundant to call out phy in an operation that is part of the phy_ops struct. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_82575.c | 38 ++-- drivers/net/igb/e1000_hw.h | 10 +- drivers/net/igb/e1000_mac.c | 8 +- drivers/net/igb/e1000_phy.c | 347 +++++++++++++--------------------- drivers/net/igb/e1000_phy.h | 1 - drivers/net/igb/igb.h | 12 +- 6 files changed, 162 insertions(+), 254 deletions(-) diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index ed9e8c0333a..9a66e345729 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -179,13 +179,13 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) /* PHY function pointers */ if (igb_sgmii_active_82575(hw)) { - phy->ops.reset_phy = igb_phy_hw_reset_sgmii_82575; - phy->ops.read_phy_reg = igb_read_phy_reg_sgmii_82575; - phy->ops.write_phy_reg = igb_write_phy_reg_sgmii_82575; + phy->ops.reset = igb_phy_hw_reset_sgmii_82575; + phy->ops.read_reg = igb_read_phy_reg_sgmii_82575; + phy->ops.write_reg = igb_write_phy_reg_sgmii_82575; } else { - phy->ops.reset_phy = igb_phy_hw_reset; - phy->ops.read_phy_reg = igb_read_phy_reg_igp; - phy->ops.write_phy_reg = igb_write_phy_reg_igp; + phy->ops.reset = igb_phy_hw_reset; + phy->ops.read_reg = igb_read_phy_reg_igp; + phy->ops.write_reg = igb_write_phy_reg_igp; } /* Set phy->phy_addr and phy->id. */ @@ -435,7 +435,7 @@ static s32 igb_phy_hw_reset_sgmii_82575(struct e1000_hw *hw) * SFP documentation requires the following to configure the SPF module * to work on SGMII. No further documentation is given. */ - ret_val = hw->phy.ops.write_phy_reg(hw, 0x1B, 0x8084); + ret_val = hw->phy.ops.write_reg(hw, 0x1B, 0x8084); if (ret_val) goto out; @@ -464,28 +464,28 @@ static s32 igb_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active) s32 ret_val; u16 data; - ret_val = phy->ops.read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); + ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); if (ret_val) goto out; if (active) { data |= IGP02E1000_PM_D0_LPLU; - ret_val = phy->ops.write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, + ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); if (ret_val) goto out; /* When LPLU is enabled, we should disable SmartSpeed */ - ret_val = phy->ops.read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = phy->ops.write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) goto out; } else { data &= ~IGP02E1000_PM_D0_LPLU; - ret_val = phy->ops.write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, + ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); /* * LPLU and SmartSpeed are mutually exclusive. LPLU is used @@ -494,24 +494,24 @@ static s32 igb_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active) * SmartSpeed, so performance is maintained. */ if (phy->smart_speed == e1000_smart_speed_on) { - ret_val = phy->ops.read_phy_reg(hw, + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = phy->ops.write_phy_reg(hw, + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) goto out; } else if (phy->smart_speed == e1000_smart_speed_off) { - ret_val = phy->ops.read_phy_reg(hw, + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = phy->ops.write_phy_reg(hw, + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) goto out; @@ -1035,7 +1035,7 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw) * depending on user settings. */ hw_dbg("Forcing Speed and Duplex\n"); - ret_val = igb_phy_force_speed_duplex(hw); + ret_val = hw->phy.ops.force_speed_duplex(hw); if (ret_val) { hw_dbg("Error Forcing Speed and Duplex\n"); goto out; @@ -1423,9 +1423,9 @@ static struct e1000_mac_operations e1000_mac_ops_82575 = { }; static struct e1000_phy_operations e1000_phy_ops_82575 = { - .acquire_phy = igb_acquire_phy_82575, + .acquire = igb_acquire_phy_82575, .get_cfg_done = igb_get_cfg_done_82575, - .release_phy = igb_release_phy_82575, + .release = igb_release_phy_82575, }; static struct e1000_nvm_operations e1000_nvm_ops_82575 = { diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h index 06f72ae6a2c..5acb8497cd6 100644 --- a/drivers/net/igb/e1000_hw.h +++ b/drivers/net/igb/e1000_hw.h @@ -422,18 +422,18 @@ struct e1000_mac_operations { }; struct e1000_phy_operations { - s32 (*acquire_phy)(struct e1000_hw *); + s32 (*acquire)(struct e1000_hw *); s32 (*check_reset_block)(struct e1000_hw *); s32 (*force_speed_duplex)(struct e1000_hw *); s32 (*get_cfg_done)(struct e1000_hw *hw); s32 (*get_cable_length)(struct e1000_hw *); s32 (*get_phy_info)(struct e1000_hw *); - s32 (*read_phy_reg)(struct e1000_hw *, u32, u16 *); - void (*release_phy)(struct e1000_hw *); - s32 (*reset_phy)(struct e1000_hw *); + s32 (*read_reg)(struct e1000_hw *, u32, u16 *); + void (*release)(struct e1000_hw *); + s32 (*reset)(struct e1000_hw *); s32 (*set_d0_lplu_state)(struct e1000_hw *, bool); s32 (*set_d3_lplu_state)(struct e1000_hw *, bool); - s32 (*write_phy_reg)(struct e1000_hw *, u32, u16); + s32 (*write_reg)(struct e1000_hw *, u32, u16); }; struct e1000_nvm_operations { diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c index 16fa0833368..d0b695cf956 100644 --- a/drivers/net/igb/e1000_mac.c +++ b/drivers/net/igb/e1000_mac.c @@ -707,11 +707,11 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) * has completed. We read this twice because this reg has * some "sticky" (latched) bits. */ - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_STATUS, + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg); if (ret_val) goto out; - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_STATUS, + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg); if (ret_val) goto out; @@ -729,11 +729,11 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) * Page Ability Register (Address 5) to determine how * flow control was negotiated. */ - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_AUTONEG_ADV, + ret_val = hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_nway_adv_reg); if (ret_val) goto out; - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_LP_ABILITY, + ret_val = hw->phy.ops.read_reg(hw, PHY_LP_ABILITY, &mii_nway_lp_ability_reg); if (ret_val) goto out; diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c index 17fddb91c9f..d73ea71d741 100644 --- a/drivers/net/igb/e1000_phy.c +++ b/drivers/net/igb/e1000_phy.c @@ -31,10 +31,6 @@ #include "e1000_mac.h" #include "e1000_phy.h" -static s32 igb_get_phy_cfg_done(struct e1000_hw *hw); -static void igb_release_phy(struct e1000_hw *hw); -static s32 igb_acquire_phy(struct e1000_hw *hw); -static s32 igb_phy_reset_dsp(struct e1000_hw *hw); static s32 igb_phy_setup_autoneg(struct e1000_hw *hw); static void igb_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl); @@ -91,13 +87,13 @@ s32 igb_get_phy_id(struct e1000_hw *hw) s32 ret_val = 0; u16 phy_id; - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_ID1, &phy_id); + ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id); if (ret_val) goto out; phy->id = (u32)(phy_id << 16); udelay(20); - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_ID2, &phy_id); + ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id); if (ret_val) goto out; @@ -118,11 +114,11 @@ static s32 igb_phy_reset_dsp(struct e1000_hw *hw) { s32 ret_val; - ret_val = hw->phy.ops.write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1); + ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1); if (ret_val) goto out; - ret_val = hw->phy.ops.write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0); + ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0); out: return ret_val; @@ -257,9 +253,12 @@ out: **/ s32 igb_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) { - s32 ret_val; + s32 ret_val = 0; + + if (!(hw->phy.ops.acquire)) + goto out; - ret_val = igb_acquire_phy(hw); + ret_val = hw->phy.ops.acquire(hw); if (ret_val) goto out; @@ -268,16 +267,15 @@ s32 igb_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) IGP01E1000_PHY_PAGE_SELECT, (u16)offset); if (ret_val) { - igb_release_phy(hw); + hw->phy.ops.release(hw); goto out; } } - ret_val = igb_read_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, - data); + ret_val = igb_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, + data); - igb_release_phy(hw); + hw->phy.ops.release(hw); out: return ret_val; @@ -294,9 +292,12 @@ out: **/ s32 igb_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) { - s32 ret_val; + s32 ret_val = 0; - ret_val = igb_acquire_phy(hw); + if (!(hw->phy.ops.acquire)) + goto out; + + ret_val = hw->phy.ops.acquire(hw); if (ret_val) goto out; @@ -305,16 +306,15 @@ s32 igb_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) IGP01E1000_PHY_PAGE_SELECT, (u16)offset); if (ret_val) { - igb_release_phy(hw); + hw->phy.ops.release(hw); goto out; } } - ret_val = igb_write_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, + ret_val = igb_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); - igb_release_phy(hw); + hw->phy.ops.release(hw); out: return ret_val; @@ -339,8 +339,7 @@ s32 igb_copper_link_setup_m88(struct e1000_hw *hw) } /* Enable CRS on TX. This must be set for half-duplex operation. */ - ret_val = hw->phy.ops.read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, - &phy_data); + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) goto out; @@ -383,8 +382,7 @@ s32 igb_copper_link_setup_m88(struct e1000_hw *hw) if (phy->disable_polarity_correction == 1) phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; - ret_val = hw->phy.ops.write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, - phy_data); + ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); if (ret_val) goto out; @@ -393,8 +391,7 @@ s32 igb_copper_link_setup_m88(struct e1000_hw *hw) * Force TX_CLK in the Extended PHY Specific Control Register * to 25MHz clock. */ - ret_val = hw->phy.ops.read_phy_reg(hw, - M88E1000_EXT_PHY_SPEC_CTRL, + ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); if (ret_val) goto out; @@ -413,8 +410,7 @@ s32 igb_copper_link_setup_m88(struct e1000_hw *hw) phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); } - ret_val = hw->phy.ops.write_phy_reg(hw, - M88E1000_EXT_PHY_SPEC_CTRL, + ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); if (ret_val) goto out; @@ -449,7 +445,7 @@ s32 igb_copper_link_setup_igp(struct e1000_hw *hw) goto out; } - ret_val = hw->phy.ops.reset_phy(hw); + ret_val = phy->ops.reset(hw); if (ret_val) { hw_dbg("Error resetting the PHY.\n"); goto out; @@ -464,8 +460,8 @@ s32 igb_copper_link_setup_igp(struct e1000_hw *hw) */ if (phy->type == e1000_phy_igp) { /* disable lplu d3 during driver init */ - if (hw->phy.ops.set_d3_lplu_state) - ret_val = hw->phy.ops.set_d3_lplu_state(hw, false); + if (phy->ops.set_d3_lplu_state) + ret_val = phy->ops.set_d3_lplu_state(hw, false); if (ret_val) { hw_dbg("Error Disabling LPLU D3\n"); goto out; @@ -473,13 +469,13 @@ s32 igb_copper_link_setup_igp(struct e1000_hw *hw) } /* disable lplu d0 during driver init */ - ret_val = hw->phy.ops.set_d0_lplu_state(hw, false); + ret_val = phy->ops.set_d0_lplu_state(hw, false); if (ret_val) { hw_dbg("Error Disabling LPLU D0\n"); goto out; } /* Configure mdi-mdix settings */ - ret_val = hw->phy.ops.read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data); + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data); if (ret_val) goto out; @@ -497,7 +493,7 @@ s32 igb_copper_link_setup_igp(struct e1000_hw *hw) data |= IGP01E1000_PSCR_AUTO_MDIX; break; } - ret_val = hw->phy.ops.write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, data); + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, data); if (ret_val) goto out; @@ -510,33 +506,31 @@ s32 igb_copper_link_setup_igp(struct e1000_hw *hw) */ if (phy->autoneg_advertised == ADVERTISE_1000_FULL) { /* Disable SmartSpeed */ - ret_val = hw->phy.ops.read_phy_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); + ret_val = phy->ops.read_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + &data); if (ret_val) goto out; data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = hw->phy.ops.write_phy_reg(hw, + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) goto out; /* Set auto Master/Slave resolution process */ - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_1000T_CTRL, - &data); + ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data); if (ret_val) goto out; data &= ~CR_1000T_MS_ENABLE; - ret_val = hw->phy.ops.write_phy_reg(hw, PHY_1000T_CTRL, - data); + ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data); if (ret_val) goto out; } - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_1000T_CTRL, &data); + ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data); if (ret_val) goto out; @@ -560,7 +554,7 @@ s32 igb_copper_link_setup_igp(struct e1000_hw *hw) default: break; } - ret_val = hw->phy.ops.write_phy_reg(hw, PHY_1000T_CTRL, data); + ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data); if (ret_val) goto out; } @@ -609,12 +603,12 @@ s32 igb_copper_link_autoneg(struct e1000_hw *hw) * Restart auto-negotiation by setting the Auto Neg Enable bit and * the Auto Neg Restart bit in the PHY control register. */ - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_CONTROL, &phy_ctrl); + ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); if (ret_val) goto out; phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); - ret_val = hw->phy.ops.write_phy_reg(hw, PHY_CONTROL, phy_ctrl); + ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl); if (ret_val) goto out; @@ -656,15 +650,13 @@ static s32 igb_phy_setup_autoneg(struct e1000_hw *hw) phy->autoneg_advertised &= phy->autoneg_mask; /* Read the MII Auto-Neg Advertisement Register (Address 4). */ - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_AUTONEG_ADV, - &mii_autoneg_adv_reg); + ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); if (ret_val) goto out; if (phy->autoneg_mask & ADVERTISE_1000_FULL) { /* Read the MII 1000Base-T Control Register (Address 9). */ - ret_val = hw->phy.ops.read_phy_reg(hw, - PHY_1000T_CTRL, + ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg); if (ret_val) goto out; @@ -785,17 +777,16 @@ static s32 igb_phy_setup_autoneg(struct e1000_hw *hw) goto out; } - ret_val = hw->phy.ops.write_phy_reg(hw, PHY_AUTONEG_ADV, - mii_autoneg_adv_reg); + ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg); if (ret_val) goto out; hw_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); if (phy->autoneg_mask & ADVERTISE_1000_FULL) { - ret_val = hw->phy.ops.write_phy_reg(hw, - PHY_1000T_CTRL, - mii_1000t_ctrl_reg); + ret_val = phy->ops.write_reg(hw, + PHY_1000T_CTRL, + mii_1000t_ctrl_reg); if (ret_val) goto out; } @@ -819,13 +810,13 @@ s32 igb_phy_force_speed_duplex_igp(struct e1000_hw *hw) u16 phy_data; bool link; - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_CONTROL, &phy_data); + ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); if (ret_val) goto out; igb_phy_force_speed_duplex_setup(hw, &phy_data); - ret_val = hw->phy.ops.write_phy_reg(hw, PHY_CONTROL, phy_data); + ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); if (ret_val) goto out; @@ -833,16 +824,14 @@ s32 igb_phy_force_speed_duplex_igp(struct e1000_hw *hw) * Clear Auto-Crossover to force MDI manually. IGP requires MDI * forced whenever speed and duplex are forced. */ - ret_val = hw->phy.ops.read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, - &phy_data); + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); if (ret_val) goto out; phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - ret_val = hw->phy.ops.write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, - phy_data); + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); if (ret_val) goto out; @@ -897,20 +886,18 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI * forced whenever speed and duplex are forced. */ - ret_val = hw->phy.ops.read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, - &phy_data); + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) goto out; phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - ret_val = hw->phy.ops.write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, - phy_data); + ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); if (ret_val) goto out; hw_dbg("M88E1000 PSCR: %X\n", phy_data); - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_CONTROL, &phy_data); + ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); if (ret_val) goto out; @@ -919,7 +906,7 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) /* Reset the phy to commit changes. */ phy_data |= MII_CR_RESET; - ret_val = hw->phy.ops.write_phy_reg(hw, PHY_CONTROL, phy_data); + ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); if (ret_val) goto out; @@ -940,7 +927,7 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) * We didn't get link. * Reset the DSP and cross our fingers. */ - ret_val = hw->phy.ops.write_phy_reg(hw, + ret_val = phy->ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x001d); if (ret_val) @@ -957,8 +944,7 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) goto out; } - ret_val = hw->phy.ops.read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, - &phy_data); + ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); if (ret_val) goto out; @@ -968,8 +954,7 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) * the reset value of 2.5MHz. */ phy_data |= M88E1000_EPSCR_TX_CLK_25; - ret_val = hw->phy.ops.write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, - phy_data); + ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); if (ret_val) goto out; @@ -977,14 +962,12 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) * In addition, we must re-enable CRS on Tx for both half and full * duplex. */ - ret_val = hw->phy.ops.read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, - &phy_data); + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) goto out; phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - ret_val = hw->phy.ops.write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, - phy_data); + ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); out: return ret_val; @@ -1071,15 +1054,13 @@ s32 igb_set_d3_lplu_state(struct e1000_hw *hw, bool active) s32 ret_val; u16 data; - ret_val = hw->phy.ops.read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, - &data); + ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); if (ret_val) goto out; if (!active) { data &= ~IGP02E1000_PM_D3_LPLU; - ret_val = hw->phy.ops.write_phy_reg(hw, - IGP02E1000_PHY_POWER_MGMT, + ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); if (ret_val) goto out; @@ -1090,27 +1071,27 @@ s32 igb_set_d3_lplu_state(struct e1000_hw *hw, bool active) * SmartSpeed, so performance is maintained. */ if (phy->smart_speed == e1000_smart_speed_on) { - ret_val = hw->phy.ops.read_phy_reg(hw, + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = hw->phy.ops.write_phy_reg(hw, + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) goto out; } else if (phy->smart_speed == e1000_smart_speed_off) { - ret_val = hw->phy.ops.read_phy_reg(hw, + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = hw->phy.ops.write_phy_reg(hw, + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) @@ -1120,22 +1101,19 @@ s32 igb_set_d3_lplu_state(struct e1000_hw *hw, bool active) (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { data |= IGP02E1000_PM_D3_LPLU; - ret_val = hw->phy.ops.write_phy_reg(hw, - IGP02E1000_PHY_POWER_MGMT, + ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); if (ret_val) goto out; /* When LPLU is enabled, we should disable SmartSpeed */ - ret_val = hw->phy.ops.read_phy_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = hw->phy.ops.write_phy_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, + ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); } @@ -1176,7 +1154,7 @@ s32 igb_check_downshift(struct e1000_hw *hw) goto out; } - ret_val = hw->phy.ops.read_phy_reg(hw, offset, &phy_data); + ret_val = phy->ops.read_reg(hw, offset, &phy_data); if (!ret_val) phy->speed_downgraded = (phy_data & mask) ? true : false; @@ -1199,7 +1177,7 @@ static s32 igb_check_polarity_m88(struct e1000_hw *hw) s32 ret_val; u16 data; - ret_val = hw->phy.ops.read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &data); + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &data); if (!ret_val) phy->cable_polarity = (data & M88E1000_PSSR_REV_POLARITY) @@ -1228,8 +1206,7 @@ static s32 igb_check_polarity_igp(struct e1000_hw *hw) * Polarity is determined based on the speed of * our connection. */ - ret_val = hw->phy.ops.read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, - &data); + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); if (ret_val) goto out; @@ -1246,7 +1223,7 @@ static s32 igb_check_polarity_igp(struct e1000_hw *hw) mask = IGP01E1000_PSSR_POLARITY_REVERSED; } - ret_val = hw->phy.ops.read_phy_reg(hw, offset, &data); + ret_val = phy->ops.read_reg(hw, offset, &data); if (!ret_val) phy->cable_polarity = (data & mask) @@ -1271,10 +1248,10 @@ static s32 igb_wait_autoneg(struct e1000_hw *hw) /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */ for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) { - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_STATUS, &phy_status); + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) break; - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_STATUS, &phy_status); + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) break; if (phy_status & MII_SR_AUTONEG_COMPLETE) @@ -1310,10 +1287,10 @@ s32 igb_phy_has_link(struct e1000_hw *hw, u32 iterations, * twice due to the link bit being sticky. No harm doing * it across the board. */ - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_STATUS, &phy_status); + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) break; - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_STATUS, &phy_status); + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) break; if (phy_status & MII_SR_LINK_STATUS) @@ -1350,8 +1327,7 @@ s32 igb_get_cable_length_m88(struct e1000_hw *hw) s32 ret_val; u16 phy_data, index; - ret_val = hw->phy.ops.read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, - &phy_data); + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); if (ret_val) goto out; @@ -1372,8 +1348,8 @@ out: * * The automatic gain control (agc) normalizes the amplitude of the * received signal, adjusting for the attenuation produced by the - * cable. By reading the AGC registers, which reperesent the - * cobination of course and fine gain value, the value can be put + * cable. By reading the AGC registers, which represent the + * combination of coarse and fine gain value, the value can be put * into a lookup table to obtain the approximate cable length * for each channel. **/ @@ -1392,14 +1368,13 @@ s32 igb_get_cable_length_igp_2(struct e1000_hw *hw) /* Read the AGC registers for all channels */ for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) { - ret_val = hw->phy.ops.read_phy_reg(hw, agc_reg_array[i], - &phy_data); + ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &phy_data); if (ret_val) goto out; /* * Getting bits 15:9, which represent the combination of - * course and fine gain values. The result is a number + * coarse and fine gain values. The result is a number * that can be put into the lookup table to obtain the * approximate cable length. */ @@ -1456,7 +1431,7 @@ s32 igb_get_phy_info_m88(struct e1000_hw *hw) u16 phy_data; bool link; - if (hw->phy.media_type != e1000_media_type_copper) { + if (phy->media_type != e1000_media_type_copper) { hw_dbg("Phy info is only valid for copper media\n"); ret_val = -E1000_ERR_CONFIG; goto out; @@ -1472,33 +1447,29 @@ s32 igb_get_phy_info_m88(struct e1000_hw *hw) goto out; } - ret_val = hw->phy.ops.read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, - &phy_data); + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) goto out; phy->polarity_correction = (phy_data & M88E1000_PSCR_POLARITY_REVERSAL) - ? true - : false; + ? true : false; ret_val = igb_check_polarity_m88(hw); if (ret_val) goto out; - ret_val = hw->phy.ops.read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, - &phy_data); + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); if (ret_val) goto out; phy->is_mdix = (phy_data & M88E1000_PSSR_MDIX) ? true : false; if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { - ret_val = hw->phy.ops.get_cable_length(hw); + ret_val = phy->ops.get_cable_length(hw); if (ret_val) goto out; - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_1000T_STATUS, - &phy_data); + ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data); if (ret_val) goto out; @@ -1552,8 +1523,7 @@ s32 igb_get_phy_info_igp(struct e1000_hw *hw) if (ret_val) goto out; - ret_val = hw->phy.ops.read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, - &data); + ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); if (ret_val) goto out; @@ -1561,12 +1531,11 @@ s32 igb_get_phy_info_igp(struct e1000_hw *hw) if ((data & IGP01E1000_PSSR_SPEED_MASK) == IGP01E1000_PSSR_SPEED_1000MBPS) { - ret_val = hw->phy.ops.get_cable_length(hw); + ret_val = phy->ops.get_cable_length(hw); if (ret_val) goto out; - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_1000T_STATUS, - &data); + ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data); if (ret_val) goto out; @@ -1599,12 +1568,12 @@ s32 igb_phy_sw_reset(struct e1000_hw *hw) s32 ret_val; u16 phy_ctrl; - ret_val = hw->phy.ops.read_phy_reg(hw, PHY_CONTROL, &phy_ctrl); + ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); if (ret_val) goto out; phy_ctrl |= MII_CR_RESET; - ret_val = hw->phy.ops.write_phy_reg(hw, PHY_CONTROL, phy_ctrl); + ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_ctrl); if (ret_val) goto out; @@ -1635,7 +1604,7 @@ s32 igb_phy_hw_reset(struct e1000_hw *hw) goto out; } - ret_val = igb_acquire_phy(hw); + ret_val = phy->ops.acquire(hw); if (ret_val) goto out; @@ -1650,74 +1619,14 @@ s32 igb_phy_hw_reset(struct e1000_hw *hw) udelay(150); - igb_release_phy(hw); + phy->ops.release(hw); - ret_val = igb_get_phy_cfg_done(hw); + ret_val = phy->ops.get_cfg_done(hw); out: return ret_val; } -/* Internal function pointers */ - -/** - * igb_get_phy_cfg_done - Generic PHY configuration done - * @hw: pointer to the HW structure - * - * Return success if silicon family did not implement a family specific - * get_cfg_done function. - **/ -static s32 igb_get_phy_cfg_done(struct e1000_hw *hw) -{ - if (hw->phy.ops.get_cfg_done) - return hw->phy.ops.get_cfg_done(hw); - - return 0; -} - -/** - * igb_release_phy - Generic release PHY - * @hw: pointer to the HW structure - * - * Return if silicon family does not require a semaphore when accessing the - * PHY. - **/ -static void igb_release_phy(struct e1000_hw *hw) -{ - if (hw->phy.ops.release_phy) - hw->phy.ops.release_phy(hw); -} - -/** - * igb_acquire_phy - Generic acquire PHY - * @hw: pointer to the HW structure - * - * Return success if silicon family does not require a semaphore when - * accessing the PHY. - **/ -static s32 igb_acquire_phy(struct e1000_hw *hw) -{ - if (hw->phy.ops.acquire_phy) - return hw->phy.ops.acquire_phy(hw); - - return 0; -} - -/** - * igb_phy_force_speed_duplex - Generic force PHY speed/duplex - * @hw: pointer to the HW structure - * - * When the silicon family has not implemented a forced speed/duplex - * function for the PHY, simply return 0. - **/ -s32 igb_phy_force_speed_duplex(struct e1000_hw *hw) -{ - if (hw->phy.ops.force_speed_duplex) - return hw->phy.ops.force_speed_duplex(hw); - - return 0; -} - /** * igb_phy_init_script_igp3 - Inits the IGP3 PHY * @hw: pointer to the HW structure @@ -1730,75 +1639,75 @@ s32 igb_phy_init_script_igp3(struct e1000_hw *hw) /* PHY init IGP 3 */ /* Enable rise/fall, 10-mode work in class-A */ - hw->phy.ops.write_phy_reg(hw, 0x2F5B, 0x9018); + hw->phy.ops.write_reg(hw, 0x2F5B, 0x9018); /* Remove all caps from Replica path filter */ - hw->phy.ops.write_phy_reg(hw, 0x2F52, 0x0000); + hw->phy.ops.write_reg(hw, 0x2F52, 0x0000); /* Bias trimming for ADC, AFE and Driver (Default) */ - hw->phy.ops.write_phy_reg(hw, 0x2FB1, 0x8B24); + hw->phy.ops.write_reg(hw, 0x2FB1, 0x8B24); /* Increase Hybrid poly bias */ - hw->phy.ops.write_phy_reg(hw, 0x2FB2, 0xF8F0); + hw->phy.ops.write_reg(hw, 0x2FB2, 0xF8F0); /* Add 4% to TX amplitude in Giga mode */ - hw->phy.ops.write_phy_reg(hw, 0x2010, 0x10B0); + hw->phy.ops.write_reg(hw, 0x2010, 0x10B0); /* Disable trimming (TTT) */ - hw->phy.ops.write_phy_reg(hw, 0x2011, 0x0000); + hw->phy.ops.write_reg(hw, 0x2011, 0x0000); /* Poly DC correction to 94.6% + 2% for all channels */ - hw->phy.ops.write_phy_reg(hw, 0x20DD, 0x249A); + hw->phy.ops.write_reg(hw, 0x20DD, 0x249A); /* ABS DC correction to 95.9% */ - hw->phy.ops.write_phy_reg(hw, 0x20DE, 0x00D3); + hw->phy.ops.write_reg(hw, 0x20DE, 0x00D3); /* BG temp curve trim */ - hw->phy.ops.write_phy_reg(hw, 0x28B4, 0x04CE); + hw->phy.ops.write_reg(hw, 0x28B4, 0x04CE); /* Increasing ADC OPAMP stage 1 currents to max */ - hw->phy.ops.write_phy_reg(hw, 0x2F70, 0x29E4); + hw->phy.ops.write_reg(hw, 0x2F70, 0x29E4); /* Force 1000 ( required for enabling PHY regs configuration) */ - hw->phy.ops.write_phy_reg(hw, 0x0000, 0x0140); + hw->phy.ops.write_reg(hw, 0x0000, 0x0140); /* Set upd_freq to 6 */ - hw->phy.ops.write_phy_reg(hw, 0x1F30, 0x1606); + hw->phy.ops.write_reg(hw, 0x1F30, 0x1606); /* Disable NPDFE */ - hw->phy.ops.write_phy_reg(hw, 0x1F31, 0xB814); + hw->phy.ops.write_reg(hw, 0x1F31, 0xB814); /* Disable adaptive fixed FFE (Default) */ - hw->phy.ops.write_phy_reg(hw, 0x1F35, 0x002A); + hw->phy.ops.write_reg(hw, 0x1F35, 0x002A); /* Enable FFE hysteresis */ - hw->phy.ops.write_phy_reg(hw, 0x1F3E, 0x0067); + hw->phy.ops.write_reg(hw, 0x1F3E, 0x0067); /* Fixed FFE for short cable lengths */ - hw->phy.ops.write_phy_reg(hw, 0x1F54, 0x0065); + hw->phy.ops.write_reg(hw, 0x1F54, 0x0065); /* Fixed FFE for medium cable lengths */ - hw->phy.ops.write_phy_reg(hw, 0x1F55, 0x002A); + hw->phy.ops.write_reg(hw, 0x1F55, 0x002A); /* Fixed FFE for long cable lengths */ - hw->phy.ops.write_phy_reg(hw, 0x1F56, 0x002A); + hw->phy.ops.write_reg(hw, 0x1F56, 0x002A); /* Enable Adaptive Clip Threshold */ - hw->phy.ops.write_phy_reg(hw, 0x1F72, 0x3FB0); + hw->phy.ops.write_reg(hw, 0x1F72, 0x3FB0); /* AHT reset limit to 1 */ - hw->phy.ops.write_phy_reg(hw, 0x1F76, 0xC0FF); + hw->phy.ops.write_reg(hw, 0x1F76, 0xC0FF); /* Set AHT master delay to 127 msec */ - hw->phy.ops.write_phy_reg(hw, 0x1F77, 0x1DEC); + hw->phy.ops.write_reg(hw, 0x1F77, 0x1DEC); /* Set scan bits for AHT */ - hw->phy.ops.write_phy_reg(hw, 0x1F78, 0xF9EF); + hw->phy.ops.write_reg(hw, 0x1F78, 0xF9EF); /* Set AHT Preset bits */ - hw->phy.ops.write_phy_reg(hw, 0x1F79, 0x0210); + hw->phy.ops.write_reg(hw, 0x1F79, 0x0210); /* Change integ_factor of channel A to 3 */ - hw->phy.ops.write_phy_reg(hw, 0x1895, 0x0003); + hw->phy.ops.write_reg(hw, 0x1895, 0x0003); /* Change prop_factor of channels BCD to 8 */ - hw->phy.ops.write_phy_reg(hw, 0x1796, 0x0008); + hw->phy.ops.write_reg(hw, 0x1796, 0x0008); /* Change cg_icount + enable integbp for channels BCD */ - hw->phy.ops.write_phy_reg(hw, 0x1798, 0xD008); + hw->phy.ops.write_reg(hw, 0x1798, 0xD008); /* * Change cg_icount + enable integbp + change prop_factor_master * to 8 for channel A */ - hw->phy.ops.write_phy_reg(hw, 0x1898, 0xD918); + hw->phy.ops.write_reg(hw, 0x1898, 0xD918); /* Disable AHT in Slave mode on channel A */ - hw->phy.ops.write_phy_reg(hw, 0x187A, 0x0800); + hw->phy.ops.write_reg(hw, 0x187A, 0x0800); /* * Enable LPLU and disable AN to 1000 in non-D0a states, * Enable SPD+B2B */ - hw->phy.ops.write_phy_reg(hw, 0x0019, 0x008D); + hw->phy.ops.write_reg(hw, 0x0019, 0x008D); /* Enable restart AN on an1000_dis change */ - hw->phy.ops.write_phy_reg(hw, 0x001B, 0x2080); + hw->phy.ops.write_reg(hw, 0x001B, 0x2080); /* Enable wh_fifo read clock in 10/100 modes */ - hw->phy.ops.write_phy_reg(hw, 0x0014, 0x0045); + hw->phy.ops.write_reg(hw, 0x0014, 0x0045); /* Restart AN, Speed selection is 1000 */ - hw->phy.ops.write_phy_reg(hw, 0x0000, 0x1340); + hw->phy.ops.write_reg(hw, 0x0000, 0x1340); return 0; } diff --git a/drivers/net/igb/e1000_phy.h b/drivers/net/igb/e1000_phy.h index 8f8fe0a780d..7499e5deec4 100644 --- a/drivers/net/igb/e1000_phy.h +++ b/drivers/net/igb/e1000_phy.h @@ -44,7 +44,6 @@ enum e1000_smart_speed { s32 igb_check_downshift(struct e1000_hw *hw); s32 igb_check_reset_block(struct e1000_hw *hw); s32 igb_copper_link_autoneg(struct e1000_hw *hw); -s32 igb_phy_force_speed_duplex(struct e1000_hw *hw); s32 igb_copper_link_setup_igp(struct e1000_hw *hw); s32 igb_copper_link_setup_m88(struct e1000_hw *hw); s32 igb_phy_force_speed_duplex_igp(struct e1000_hw *hw); diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 530d7aa4cb8..a2a812deb6b 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -313,24 +313,24 @@ extern void igb_set_ethtool_ops(struct net_device *); static inline s32 igb_reset_phy(struct e1000_hw *hw) { - if (hw->phy.ops.reset_phy) - return hw->phy.ops.reset_phy(hw); + if (hw->phy.ops.reset) + return hw->phy.ops.reset(hw); return 0; } static inline s32 igb_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data) { - if (hw->phy.ops.read_phy_reg) - return hw->phy.ops.read_phy_reg(hw, offset, data); + if (hw->phy.ops.read_reg) + return hw->phy.ops.read_reg(hw, offset, data); return 0; } static inline s32 igb_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data) { - if (hw->phy.ops.write_phy_reg) - return hw->phy.ops.write_phy_reg(hw, offset, data); + if (hw->phy.ops.write_reg) + return hw->phy.ops.write_reg(hw, offset, data); return 0; } -- GitLab From 312c75aee7606e886d91c810bc491c9f40ff5837 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:17:47 +0000 Subject: [PATCH 1311/4982] igb: rename nvm ops All of the nvm ops have the tag _nvm added to the end which is redundant since all of the calls to the ops have to go through the nvm ops struct anyway. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_82575.c | 8 ++++---- drivers/net/igb/e1000_hw.h | 8 ++++---- drivers/net/igb/e1000_mac.c | 9 ++++----- drivers/net/igb/e1000_nvm.c | 14 +++++++------- drivers/net/igb/igb_ethtool.c | 14 +++++++------- drivers/net/igb/igb_main.c | 3 +-- 6 files changed, 27 insertions(+), 29 deletions(-) diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index 9a66e345729..527d4c8e53f 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -1429,10 +1429,10 @@ static struct e1000_phy_operations e1000_phy_ops_82575 = { }; static struct e1000_nvm_operations e1000_nvm_ops_82575 = { - .acquire_nvm = igb_acquire_nvm_82575, - .read_nvm = igb_read_nvm_eerd, - .release_nvm = igb_release_nvm_82575, - .write_nvm = igb_write_nvm_spi, + .acquire = igb_acquire_nvm_82575, + .read = igb_read_nvm_eerd, + .release = igb_release_nvm_82575, + .write = igb_write_nvm_spi, }; const struct e1000_info e1000_82575_info = { diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h index 5acb8497cd6..acb42a21e95 100644 --- a/drivers/net/igb/e1000_hw.h +++ b/drivers/net/igb/e1000_hw.h @@ -437,10 +437,10 @@ struct e1000_phy_operations { }; struct e1000_nvm_operations { - s32 (*acquire_nvm)(struct e1000_hw *); - s32 (*read_nvm)(struct e1000_hw *, u16, u16, u16 *); - void (*release_nvm)(struct e1000_hw *); - s32 (*write_nvm)(struct e1000_hw *, u16, u16, u16 *); + s32 (*acquire)(struct e1000_hw *); + s32 (*read)(struct e1000_hw *, u16, u16, u16 *); + void (*release)(struct e1000_hw *); + s32 (*write)(struct e1000_hw *, u16, u16, u16 *); }; struct e1000_info { diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c index d0b695cf956..6682206750d 100644 --- a/drivers/net/igb/e1000_mac.c +++ b/drivers/net/igb/e1000_mac.c @@ -135,7 +135,7 @@ s32 igb_check_alt_mac_addr(struct e1000_hw *hw) u16 offset, nvm_alt_mac_addr_offset, nvm_data; u8 alt_mac_addr[ETH_ALEN]; - ret_val = hw->nvm.ops.read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1, + ret_val = hw->nvm.ops.read(hw, NVM_ALT_MAC_ADDR_PTR, 1, &nvm_alt_mac_addr_offset); if (ret_val) { hw_dbg("NVM Read Error\n"); @@ -152,7 +152,7 @@ s32 igb_check_alt_mac_addr(struct e1000_hw *hw) for (i = 0; i < ETH_ALEN; i += 2) { offset = nvm_alt_mac_addr_offset + (i >> 1); - ret_val = hw->nvm.ops.read_nvm(hw, offset, 1, &nvm_data); + ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data); if (ret_val) { hw_dbg("NVM Read Error\n"); goto out; @@ -575,8 +575,7 @@ static s32 igb_set_default_fc(struct e1000_hw *hw) * control setting, then the variable hw->fc will * be initialized based on a value in the EEPROM. */ - ret_val = hw->nvm.ops.read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, - &nvm_data); + ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data); if (ret_val) { hw_dbg("NVM Read Error\n"); @@ -1028,7 +1027,7 @@ static s32 igb_valid_led_default(struct e1000_hw *hw, u16 *data) { s32 ret_val; - ret_val = hw->nvm.ops.read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data); + ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); if (ret_val) { hw_dbg("NVM Read Error\n"); goto out; diff --git a/drivers/net/igb/e1000_nvm.c b/drivers/net/igb/e1000_nvm.c index 5942da107a9..33798642208 100644 --- a/drivers/net/igb/e1000_nvm.c +++ b/drivers/net/igb/e1000_nvm.c @@ -419,7 +419,7 @@ s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) goto out; } - ret_val = hw->nvm.ops.acquire_nvm(hw); + ret_val = hw->nvm.ops.acquire(hw); if (ret_val) goto out; @@ -468,7 +468,7 @@ s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) msleep(10); release: - hw->nvm.ops.release_nvm(hw); + hw->nvm.ops.release(hw); out: return ret_val; @@ -487,14 +487,14 @@ s32 igb_read_part_num(struct e1000_hw *hw, u32 *part_num) s32 ret_val; u16 nvm_data; - ret_val = hw->nvm.ops.read_nvm(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); + ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); if (ret_val) { hw_dbg("NVM Read Error\n"); goto out; } *part_num = (u32)(nvm_data << 16); - ret_val = hw->nvm.ops.read_nvm(hw, NVM_PBA_OFFSET_1, 1, &nvm_data); + ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data); if (ret_val) { hw_dbg("NVM Read Error\n"); goto out; @@ -548,7 +548,7 @@ s32 igb_validate_nvm_checksum(struct e1000_hw *hw) u16 i, nvm_data; for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { - ret_val = hw->nvm.ops.read_nvm(hw, i, 1, &nvm_data); + ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); if (ret_val) { hw_dbg("NVM Read Error\n"); goto out; @@ -581,7 +581,7 @@ s32 igb_update_nvm_checksum(struct e1000_hw *hw) u16 i, nvm_data; for (i = 0; i < NVM_CHECKSUM_REG; i++) { - ret_val = hw->nvm.ops.read_nvm(hw, i, 1, &nvm_data); + ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); if (ret_val) { hw_dbg("NVM Read Error while updating checksum.\n"); goto out; @@ -589,7 +589,7 @@ s32 igb_update_nvm_checksum(struct e1000_hw *hw) checksum += nvm_data; } checksum = (u16) NVM_SUM - checksum; - ret_val = hw->nvm.ops.write_nvm(hw, NVM_CHECKSUM_REG, 1, &checksum); + ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum); if (ret_val) hw_dbg("NVM Write Error while updating checksum.\n"); diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 4606e63fc6f..a5bf8ef2848 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -593,12 +593,12 @@ static int igb_get_eeprom(struct net_device *netdev, return -ENOMEM; if (hw->nvm.type == e1000_nvm_eeprom_spi) - ret_val = hw->nvm.ops.read_nvm(hw, first_word, + ret_val = hw->nvm.ops.read(hw, first_word, last_word - first_word + 1, eeprom_buff); else { for (i = 0; i < last_word - first_word + 1; i++) { - ret_val = hw->nvm.ops.read_nvm(hw, first_word + i, 1, + ret_val = hw->nvm.ops.read(hw, first_word + i, 1, &eeprom_buff[i]); if (ret_val) break; @@ -645,14 +645,14 @@ static int igb_set_eeprom(struct net_device *netdev, if (eeprom->offset & 1) { /* need read/modify/write of first changed EEPROM word */ /* only the second byte of the word is being modified */ - ret_val = hw->nvm.ops.read_nvm(hw, first_word, 1, + ret_val = hw->nvm.ops.read(hw, first_word, 1, &eeprom_buff[0]); ptr++; } if (((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) { /* need read/modify/write of last changed EEPROM word */ /* only the first byte of the word is being modified */ - ret_val = hw->nvm.ops.read_nvm(hw, last_word, 1, + ret_val = hw->nvm.ops.read(hw, last_word, 1, &eeprom_buff[last_word - first_word]); } @@ -665,7 +665,7 @@ static int igb_set_eeprom(struct net_device *netdev, for (i = 0; i < last_word - first_word + 1; i++) eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]); - ret_val = hw->nvm.ops.write_nvm(hw, first_word, + ret_val = hw->nvm.ops.write(hw, first_word, last_word - first_word + 1, eeprom_buff); /* Update the checksum over the first part of the EEPROM if needed @@ -689,7 +689,7 @@ static void igb_get_drvinfo(struct net_device *netdev, /* EEPROM image version # is reported as firmware version # for * 82575 controllers */ - adapter->hw.nvm.ops.read_nvm(&adapter->hw, 5, 1, &eeprom_data); + adapter->hw.nvm.ops.read(&adapter->hw, 5, 1, &eeprom_data); sprintf(firmware_version, "%d.%d-%d", (eeprom_data & 0xF000) >> 12, (eeprom_data & 0x0FF0) >> 4, @@ -1056,7 +1056,7 @@ static int igb_eeprom_test(struct igb_adapter *adapter, u64 *data) *data = 0; /* Read and add up the contents of the EEPROM */ for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { - if ((adapter->hw.nvm.ops.read_nvm(&adapter->hw, i, 1, &temp)) + if ((adapter->hw.nvm.ops.read(&adapter->hw, i, 1, &temp)) < 0) { *data = 1; break; diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index cb3ac349f3b..e3a3582fec9 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1243,8 +1243,7 @@ static int __devinit igb_probe(struct pci_dev *pdev, if (hw->bus.func == 0 || hw->device_id == E1000_DEV_ID_82575EB_COPPER) - hw->nvm.ops.read_nvm(hw, NVM_INIT_CONTROL3_PORT_A, 1, - &eeprom_data); + hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); if (eeprom_data & eeprom_apme_mask) adapter->eeprom_wol |= E1000_WUFC_MAG; -- GitLab From 0fbe67af3ee1928f7eae273133b7112d1665d4d3 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:18:06 +0000 Subject: [PATCH 1312/4982] igb: remove unused rx_hdr_split statistic This statistic is not used and so it is safe to remove Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb.h | 1 - drivers/net/igb/igb_ethtool.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index a2a812deb6b..88fdfe4961d 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -238,7 +238,6 @@ struct igb_adapter { u64 hw_csum_err; u64 hw_csum_good; - u64 rx_hdr_split; u32 alloc_rx_buff_failed; bool rx_csum; u32 gorc; diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index a5bf8ef2848..84be46c2a0f 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -88,7 +88,6 @@ static const struct igb_stats igb_gstrings_stats[] = { { "rx_long_byte_count", IGB_STAT(stats.gorc) }, { "rx_csum_offload_good", IGB_STAT(hw_csum_good) }, { "rx_csum_offload_errors", IGB_STAT(hw_csum_err) }, - { "rx_header_split", IGB_STAT(rx_hdr_split) }, { "alloc_rx_buff_failed", IGB_STAT(alloc_rx_buff_failed) }, { "tx_smbus", IGB_STAT(stats.mgptc) }, { "rx_smbus", IGB_STAT(stats.mgprc) }, -- GitLab From 7d8eb29e6eae9cc13e1975daf28d2ae789c1f110 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:18:27 +0000 Subject: [PATCH 1313/4982] igb: update feature flags supported in ethtool This driver is currently using HW_CSUM which is not correct. Update this to use the IP_CSUM and IPV6_CSUM flags. In addition consolidate the TSO flag setting. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_ethtool.c | 16 +++++++--------- drivers/net/igb/igb_main.c | 5 +++-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 84be46c2a0f..d7bdc6c16d0 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -287,15 +287,15 @@ static int igb_set_rx_csum(struct net_device *netdev, u32 data) static u32 igb_get_tx_csum(struct net_device *netdev) { - return (netdev->features & NETIF_F_HW_CSUM) != 0; + return (netdev->features & NETIF_F_IP_CSUM) != 0; } static int igb_set_tx_csum(struct net_device *netdev, u32 data) { if (data) - netdev->features |= NETIF_F_HW_CSUM; + netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); else - netdev->features &= ~NETIF_F_HW_CSUM; + netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); return 0; } @@ -304,15 +304,13 @@ static int igb_set_tso(struct net_device *netdev, u32 data) { struct igb_adapter *adapter = netdev_priv(netdev); - if (data) + if (data) { netdev->features |= NETIF_F_TSO; - else - netdev->features &= ~NETIF_F_TSO; - - if (data) netdev->features |= NETIF_F_TSO6; - else + } else { + netdev->features &= ~NETIF_F_TSO; netdev->features &= ~NETIF_F_TSO6; + } dev_info(&adapter->pdev->dev, "TSO is %s\n", data ? "Enabled" : "Disabled"); diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index e3a3582fec9..8c27e0a23df 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1158,11 +1158,12 @@ static int __devinit igb_probe(struct pci_dev *pdev, "PHY reset is blocked due to SOL/IDER session.\n"); netdev->features = NETIF_F_SG | - NETIF_F_HW_CSUM | + NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; + netdev->features |= NETIF_F_IPV6_CSUM; netdev->features |= NETIF_F_TSO; netdev->features |= NETIF_F_TSO6; @@ -1172,7 +1173,7 @@ static int __devinit igb_probe(struct pci_dev *pdev, netdev->vlan_features |= NETIF_F_TSO; netdev->vlan_features |= NETIF_F_TSO6; - netdev->vlan_features |= NETIF_F_HW_CSUM; + netdev->vlan_features |= NETIF_F_IP_CSUM; netdev->vlan_features |= NETIF_F_SG; if (pci_using_dac) -- GitLab From 2753f4cebf034a53f87b24679f394854275dcacb Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:18:48 +0000 Subject: [PATCH 1314/4982] igb: update testing done by ethtool Most of the code for the testing has pretty much become stale at this point and is need of update. This update just streamlines most of the code, widens the range of interrupt testing. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_ethtool.c | 87 ++++++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 26 deletions(-) diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index d7bdc6c16d0..33c23a117fe 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -855,23 +855,26 @@ static struct igb_reg_test reg_test_82576[] = { { E1000_RDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, { E1000_RDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_RDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, - { E1000_RDBAL(4), 0x40, 8, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, - { E1000_RDBAH(4), 0x40, 8, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, - { E1000_RDLEN(4), 0x40, 8, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, - /* Enable all four RX queues before testing. */ - { E1000_RXDCTL(0), 0x100, 1, WRITE_NO_TEST, 0, E1000_RXDCTL_QUEUE_ENABLE }, + { E1000_RDBAL(4), 0x40, 12, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, + { E1000_RDBAH(4), 0x40, 12, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, + { E1000_RDLEN(4), 0x40, 12, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, + /* Enable all RX queues before testing. */ + { E1000_RXDCTL(0), 0x100, 4, WRITE_NO_TEST, 0, E1000_RXDCTL_QUEUE_ENABLE }, + { E1000_RXDCTL(4), 0x40, 12, WRITE_NO_TEST, 0, E1000_RXDCTL_QUEUE_ENABLE }, /* RDH is read-only for 82576, only test RDT. */ { E1000_RDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, + { E1000_RDT(4), 0x40, 12, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, { E1000_RXDCTL(0), 0x100, 4, WRITE_NO_TEST, 0, 0 }, + { E1000_RXDCTL(4), 0x40, 12, WRITE_NO_TEST, 0, 0 }, { E1000_FCRTH, 0x100, 1, PATTERN_TEST, 0x0000FFF0, 0x0000FFF0 }, { E1000_FCTTV, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, { E1000_TIPG, 0x100, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF }, { E1000_TDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, { E1000_TDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_TDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, - { E1000_TDBAL(4), 0x40, 8, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, - { E1000_TDBAH(4), 0x40, 8, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, - { E1000_TDLEN(4), 0x40, 8, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, + { E1000_TDBAL(4), 0x40, 12, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, + { E1000_TDBAH(4), 0x40, 12, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, + { E1000_TDLEN(4), 0x40, 12, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 }, { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0x003FFFFB }, { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0xFFFFFFFF }, @@ -918,12 +921,13 @@ static struct igb_reg_test reg_test_82575[] = { static bool reg_pattern_test(struct igb_adapter *adapter, u64 *data, int reg, u32 mask, u32 write) { + struct e1000_hw *hw = &adapter->hw; u32 pat, val; u32 _test[] = {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; for (pat = 0; pat < ARRAY_SIZE(_test); pat++) { - writel((_test[pat] & write), (adapter->hw.hw_addr + reg)); - val = readl(adapter->hw.hw_addr + reg); + wr32(reg, (_test[pat] & write)); + val = rd32(reg); if (val != (_test[pat] & write & mask)) { dev_err(&adapter->pdev->dev, "pattern test reg %04X " "failed: got 0x%08X expected 0x%08X\n", @@ -938,9 +942,10 @@ static bool reg_pattern_test(struct igb_adapter *adapter, u64 *data, static bool reg_set_and_check(struct igb_adapter *adapter, u64 *data, int reg, u32 mask, u32 write) { + struct e1000_hw *hw = &adapter->hw; u32 val; - writel((write & mask), (adapter->hw.hw_addr + reg)); - val = readl(adapter->hw.hw_addr + reg); + wr32(reg, write & mask); + val = rd32(reg); if ((write & mask) != (val & mask)) { dev_err(&adapter->pdev->dev, "set/check reg %04X test failed:" " got 0x%08X expected 0x%08X\n", reg, @@ -1006,12 +1011,14 @@ static int igb_reg_test(struct igb_adapter *adapter, u64 *data) for (i = 0; i < test->array_len; i++) { switch (test->test_type) { case PATTERN_TEST: - REG_PATTERN_TEST(test->reg + (i * test->reg_offset), + REG_PATTERN_TEST(test->reg + + (i * test->reg_offset), test->mask, test->write); break; case SET_READ_TEST: - REG_SET_AND_CHECK(test->reg + (i * test->reg_offset), + REG_SET_AND_CHECK(test->reg + + (i * test->reg_offset), test->mask, test->write); break; @@ -1083,16 +1090,17 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data) { struct e1000_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; - u32 mask, i = 0, shared_int = true; + u32 mask, ics_mask, i = 0, shared_int = true; u32 irq = adapter->pdev->irq; *data = 0; /* Hook up test interrupt handler just for this test */ - if (adapter->msix_entries) { + if (adapter->msix_entries) /* NOTE: we don't test MSI-X interrupts here, yet */ return 0; - } else if (adapter->flags & IGB_FLAG_HAS_MSI) { + + if (adapter->flags & IGB_FLAG_HAS_MSI) { shared_int = false; if (request_irq(irq, &igb_test_intr, 0, netdev->name, netdev)) { *data = 1; @@ -1108,16 +1116,31 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data) } dev_info(&adapter->pdev->dev, "testing %s interrupt\n", (shared_int ? "shared" : "unshared")); - /* Disable all the interrupts */ wr32(E1000_IMC, 0xFFFFFFFF); msleep(10); + /* Define all writable bits for ICS */ + switch(hw->mac.type) { + case e1000_82575: + ics_mask = 0x37F47EDD; + break; + case e1000_82576: + ics_mask = 0x77D4FBFD; + break; + default: + ics_mask = 0x7FFFFFFF; + break; + } + /* Test each interrupt */ - for (; i < 10; i++) { + for (; i < 31; i++) { /* Interrupt to test */ mask = 1 << i; + if (!(mask & ics_mask)) + continue; + if (!shared_int) { /* Disable the interrupt to be reported in * the cause register and then force the same @@ -1126,8 +1149,12 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data) * test failed. */ adapter->test_icr = 0; - wr32(E1000_IMC, ~mask & 0x00007FFF); - wr32(E1000_ICS, ~mask & 0x00007FFF); + + /* Flush any pending interrupts */ + wr32(E1000_ICR, ~0); + + wr32(E1000_IMC, mask); + wr32(E1000_ICS, mask); msleep(10); if (adapter->test_icr & mask) { @@ -1143,6 +1170,10 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data) * test failed. */ adapter->test_icr = 0; + + /* Flush any pending interrupts */ + wr32(E1000_ICR, ~0); + wr32(E1000_IMS, mask); wr32(E1000_ICS, mask); msleep(10); @@ -1160,11 +1191,15 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data) * test failed. */ adapter->test_icr = 0; - wr32(E1000_IMC, ~mask & 0x00007FFF); - wr32(E1000_ICS, ~mask & 0x00007FFF); + + /* Flush any pending interrupts */ + wr32(E1000_ICR, ~0); + + wr32(E1000_IMC, ~mask); + wr32(E1000_ICS, ~mask); msleep(10); - if (adapter->test_icr) { + if (adapter->test_icr & mask) { *data = 5; break; } @@ -1172,7 +1207,7 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data) } /* Disable all the interrupts */ - wr32(E1000_IMC, 0xFFFFFFFF); + wr32(E1000_IMC, ~0); msleep(10); /* Unhook test interrupt handler */ @@ -1450,7 +1485,7 @@ static int igb_setup_loopback_test(struct igb_adapter *adapter) E1000_CTRL_TFCE | E1000_CTRL_LRST); reg |= E1000_CTRL_SLU | - E1000_CTRL_FD; + E1000_CTRL_FD; wr32(E1000_CTRL, reg); /* Unset switch control to serdes energy detect */ -- GitLab From dda0e0834c839c0e4b1717cbe9c22c35ca935809 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:19:08 +0000 Subject: [PATCH 1315/4982] igb: add counter for dma out of sync errors Add a counter for dma out of sync errors reported via interrupt. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_defines.h | 6 +++++- drivers/net/igb/e1000_hw.h | 1 + drivers/net/igb/igb_ethtool.c | 1 + drivers/net/igb/igb_main.c | 19 +++++++++++++++++-- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index 54a14892338..bff62dd8431 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -413,6 +413,7 @@ /* LAN connected device generates an interrupt */ #define E1000_ICR_PHYINT 0x00001000 #define E1000_ICR_EPRST 0x00100000 /* ME handware reset occurs */ +#define E1000_ICR_DOUTSYNC 0x10000000 /* NIC DMA out of sync */ /* Extended Interrupt Cause Read */ #define E1000_EICR_RX_QUEUE0 0x00000001 /* Rx Queue 0 Interrupt */ @@ -441,7 +442,8 @@ E1000_IMS_TXDW | \ E1000_IMS_RXDMT0 | \ E1000_IMS_RXSEQ | \ - E1000_IMS_LSC) + E1000_IMS_LSC | \ + E1000_IMS_DOUTSYNC) /* Interrupt Mask Set */ #define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ @@ -449,6 +451,7 @@ #define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ #define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ #define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ +#define E1000_IMS_DOUTSYNC E1000_ICR_DOUTSYNC /* NIC DMA out of sync */ /* Extended Interrupt Mask Set */ #define E1000_EIMS_TCP_TIMER E1000_EICR_TCP_TIMER /* TCP Timer */ @@ -457,6 +460,7 @@ /* Interrupt Cause Set */ #define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */ #define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ +#define E1000_ICS_DOUTSYNC E1000_ICR_DOUTSYNC /* NIC DMA out of sync */ /* Extended Interrupt Cause Set */ diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h index acb42a21e95..62ccd495356 100644 --- a/drivers/net/igb/e1000_hw.h +++ b/drivers/net/igb/e1000_hw.h @@ -359,6 +359,7 @@ struct e1000_hw_stats { u64 lenerrs; u64 scvpc; u64 hrmpc; + u64 doosync; }; struct e1000_phy_stats { diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 33c23a117fe..de09430ce7f 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -88,6 +88,7 @@ static const struct igb_stats igb_gstrings_stats[] = { { "rx_long_byte_count", IGB_STAT(stats.gorc) }, { "rx_csum_offload_good", IGB_STAT(hw_csum_good) }, { "rx_csum_offload_errors", IGB_STAT(hw_csum_err) }, + { "tx_dma_out_of_sync", IGB_STAT(stats.doosync) }, { "alloc_rx_buff_failed", IGB_STAT(alloc_rx_buff_failed) }, { "tx_smbus", IGB_STAT(stats.mgptc) }, { "rx_smbus", IGB_STAT(stats.mgprc) }, diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 8c27e0a23df..c05ca3461f6 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -689,7 +689,7 @@ static void igb_irq_enable(struct igb_adapter *adapter) wr32(E1000_EIAC, adapter->eims_enable_mask); wr32(E1000_EIAM, adapter->eims_enable_mask); wr32(E1000_EIMS, adapter->eims_enable_mask); - wr32(E1000_IMS, E1000_IMS_LSC); + wr32(E1000_IMS, E1000_IMS_LSC | E1000_IMS_DOUTSYNC); } else { wr32(E1000_IMS, IMS_ENABLE_MASK); wr32(E1000_IAM, IMS_ENABLE_MASK); @@ -3287,6 +3287,11 @@ static irqreturn_t igb_msix_other(int irq, void *data) u32 icr = rd32(E1000_ICR); /* reading ICR causes bit 31 of EICR to be cleared */ + + if(icr & E1000_ICR_DOUTSYNC) { + /* HW is reporting DMA is out of sync */ + adapter->stats.doosync++; + } if (!(icr & E1000_ICR_LSC)) goto no_link_interrupt; hw->mac.get_link_status = 1; @@ -3295,7 +3300,7 @@ static irqreturn_t igb_msix_other(int irq, void *data) mod_timer(&adapter->watchdog_timer, jiffies + 1); no_link_interrupt: - wr32(E1000_IMS, E1000_IMS_LSC); + wr32(E1000_IMS, E1000_IMS_LSC | E1000_IMS_DOUTSYNC); wr32(E1000_EIMS, adapter->eims_other); return IRQ_HANDLED; @@ -3499,6 +3504,11 @@ static irqreturn_t igb_intr_msi(int irq, void *data) igb_write_itr(adapter->rx_ring); + if(icr & E1000_ICR_DOUTSYNC) { + /* HW is reporting DMA is out of sync */ + adapter->stats.doosync++; + } + if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { hw->mac.get_link_status = 1; if (!test_bit(__IGB_DOWN, &adapter->state)) @@ -3534,6 +3544,11 @@ static irqreturn_t igb_intr(int irq, void *data) if (!(icr & E1000_ICR_INT_ASSERTED)) return IRQ_NONE; + if(icr & E1000_ICR_DOUTSYNC) { + /* HW is reporting DMA is out of sync */ + adapter->stats.doosync++; + } + eicr = rd32(E1000_EICR); if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { -- GitLab From eebbbdba5eb44406061e4dff130257b654773d3f Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:19:29 +0000 Subject: [PATCH 1316/4982] igb: cleanup igb_netpoll to be more friendly with napi & GRO This patch cleans up igb_netpoll so that it is more friendly with both the current napi and newly introduced GRO features. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb.h | 5 ++--- drivers/net/igb/igb_main.c | 37 +++++++++++++++++++++---------------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 88fdfe4961d..0519ae408af 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -280,9 +280,8 @@ struct igb_adapter { #define IGB_FLAG_HAS_MSI (1 << 0) #define IGB_FLAG_MSI_ENABLE (1 << 1) #define IGB_FLAG_DCA_ENABLED (1 << 2) -#define IGB_FLAG_IN_NETPOLL (1 << 3) -#define IGB_FLAG_QUAD_PORT_A (1 << 4) -#define IGB_FLAG_NEED_CTX_IDX (1 << 5) +#define IGB_FLAG_QUAD_PORT_A (1 << 3) +#define IGB_FLAG_NEED_CTX_IDX (1 << 4) enum e1000_state_t { __IGB_TESTING, diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index c05ca3461f6..3bf560f0fde 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -404,7 +404,7 @@ static void igb_configure_msix(struct igb_adapter *adapter) /* Turn on MSI-X capability first, or our settings * won't stick. And it will take days to debug. */ wr32(E1000_GPIE, E1000_GPIE_MSIX_MODE | - E1000_GPIE_PBA | E1000_GPIE_EIAME | + E1000_GPIE_PBA | E1000_GPIE_EIAME | E1000_GPIE_NSICR); for (i = 0; i < adapter->num_tx_queues; i++) { @@ -1629,7 +1629,7 @@ static int igb_setup_all_tx_resources(struct igb_adapter *adapter) for (i = 0; i < IGB_MAX_TX_QUEUES; i++) { r_idx = i % adapter->num_tx_queues; adapter->multi_tx_table[i] = &adapter->tx_ring[r_idx]; - } + } return err; } @@ -3298,7 +3298,7 @@ static irqreturn_t igb_msix_other(int irq, void *data) /* guard against interrupt when we're going down */ if (!test_bit(__IGB_DOWN, &adapter->state)) mod_timer(&adapter->watchdog_timer, jiffies + 1); - + no_link_interrupt: wr32(E1000_IMS, E1000_IMS_LSC | E1000_IMS_DOUTSYNC); wr32(E1000_EIMS, adapter->eims_other); @@ -3751,7 +3751,7 @@ static bool igb_clean_tx_irq(struct igb_ring *tx_ring) /** * igb_receive_skb - helper function to handle rx indications - * @ring: pointer to receive ring receving this packet + * @ring: pointer to receive ring receving this packet * @status: descriptor status field as written by hardware * @vlan: descriptor vlan field as written by hardware (no le/be conversion) * @skb: pointer to sk_buff to be indicated to stack @@ -4378,22 +4378,27 @@ static void igb_shutdown(struct pci_dev *pdev) static void igb_netpoll(struct net_device *netdev) { struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; int i; - int work_done = 0; - igb_irq_disable(adapter); - adapter->flags |= IGB_FLAG_IN_NETPOLL; - - for (i = 0; i < adapter->num_tx_queues; i++) - igb_clean_tx_irq(&adapter->tx_ring[i]); + if (!adapter->msix_entries) { + igb_irq_disable(adapter); + napi_schedule(&adapter->rx_ring[0].napi); + return; + } - for (i = 0; i < adapter->num_rx_queues; i++) - igb_clean_rx_irq_adv(&adapter->rx_ring[i], - &work_done, - adapter->rx_ring[i].napi.weight); + for (i = 0; i < adapter->num_tx_queues; i++) { + struct igb_ring *tx_ring = &adapter->tx_ring[i]; + wr32(E1000_EIMC, tx_ring->eims_value); + igb_clean_tx_irq(tx_ring); + wr32(E1000_EIMS, tx_ring->eims_value); + } - adapter->flags &= ~IGB_FLAG_IN_NETPOLL; - igb_irq_enable(adapter); + for (i = 0; i < adapter->num_rx_queues; i++) { + struct igb_ring *rx_ring = &adapter->rx_ring[i]; + wr32(E1000_EIMC, rx_ring->eims_value); + napi_schedule(&rx_ring->napi); + } } #endif /* CONFIG_NET_POLL_CONTROLLER */ -- GitLab From 4b1a9877364599fe57f263597821dab6bd86f3b9 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:19:50 +0000 Subject: [PATCH 1317/4982] igb: remove redundant timer updates and cleanup watchdog_task The igb watchdog task is modifying the watchdog timer twice duing a single run. It only needs to be called once to reschedule itself for 2 seconds from the last time it ran. In addition I removed the allocation of the mac_info structure since it is only called twice and is easier to access via the e1000_hw struct. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 3bf560f0fde..cbb38585633 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2314,13 +2314,10 @@ static void igb_watchdog_task(struct work_struct *work) struct igb_adapter *adapter = container_of(work, struct igb_adapter, watchdog_task); struct e1000_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; struct igb_ring *tx_ring = adapter->tx_ring; - struct e1000_mac_info *mac = &adapter->hw.mac; u32 link; u32 eics = 0; - s32 ret_val; int i; link = igb_has_link(adapter); @@ -2365,6 +2362,7 @@ static void igb_watchdog_task(struct work_struct *work) netif_carrier_on(netdev); netif_tx_wake_all_queues(netdev); + /* link state has changed, schedule phy info update */ if (!test_bit(__IGB_DOWN, &adapter->state)) mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ)); @@ -2378,6 +2376,8 @@ static void igb_watchdog_task(struct work_struct *work) netdev->name); netif_carrier_off(netdev); netif_tx_stop_all_queues(netdev); + + /* link state has changed, schedule phy info update */ if (!test_bit(__IGB_DOWN, &adapter->state)) mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ)); @@ -2387,9 +2387,9 @@ static void igb_watchdog_task(struct work_struct *work) link_up: igb_update_stats(adapter); - mac->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old; + hw->mac.tx_packet_delta = adapter->stats.tpt - adapter->tpt_old; adapter->tpt_old = adapter->stats.tpt; - mac->collision_delta = adapter->stats.colc - adapter->colc_old; + hw->mac.collision_delta = adapter->stats.colc - adapter->colc_old; adapter->colc_old = adapter->stats.colc; adapter->gorc = adapter->stats.gorc - adapter->gorc_old; -- GitLab From 8a900862a2402565564ddcc3c6ecefb1c239d7e1 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:20:10 +0000 Subject: [PATCH 1318/4982] igb: rename igb_update_mc_addr_list_82575 to not include the 82575 There isn't much point in having the _82575 hanging off the end of this function since there aren't any other version of this function running around within this driver. This also allows for a bit of whitespace cleanup due to a shorter function name. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_82575.c | 8 ++++---- drivers/net/igb/e1000_82575.h | 2 +- drivers/net/igb/igb_main.c | 7 +++---- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index 527d4c8e53f..68a9822f405 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -787,7 +787,7 @@ static void igb_init_rx_addrs_82575(struct e1000_hw *hw, u16 rar_count) } /** - * igb_update_mc_addr_list_82575 - Update Multicast addresses + * igb_update_mc_addr_list - Update Multicast addresses * @hw: pointer to the HW structure * @mc_addr_list: array of multicast addresses to program * @mc_addr_count: number of multicast addresses to program @@ -799,9 +799,9 @@ static void igb_init_rx_addrs_82575(struct e1000_hw *hw, u16 rar_count) * The parameter rar_count will usually be hw->mac.rar_entry_count * unless there are workarounds that change this. **/ -void igb_update_mc_addr_list_82575(struct e1000_hw *hw, - u8 *mc_addr_list, u32 mc_addr_count, - u32 rar_used_count, u32 rar_count) +void igb_update_mc_addr_list(struct e1000_hw *hw, + u8 *mc_addr_list, u32 mc_addr_count, + u32 rar_used_count, u32 rar_count) { u32 hash_value; u32 i; diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h index c1928b5efe1..e0a376fa28a 100644 --- a/drivers/net/igb/e1000_82575.h +++ b/drivers/net/igb/e1000_82575.h @@ -28,7 +28,7 @@ #ifndef _E1000_82575_H_ #define _E1000_82575_H_ -void igb_update_mc_addr_list_82575(struct e1000_hw*, u8*, u32, u32, u32); +void igb_update_mc_addr_list(struct e1000_hw*, u8*, u32, u32, u32); extern void igb_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw); extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw); diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index cbb38585633..2d169a45c42 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2227,8 +2227,8 @@ static void igb_set_multi(struct net_device *netdev) if (!netdev->mc_count) { /* nothing to program, so clear mc list */ - igb_update_mc_addr_list_82575(hw, NULL, 0, 1, - mac->rar_entry_count); + igb_update_mc_addr_list(hw, NULL, 0, 1, + mac->rar_entry_count); return; } @@ -2245,8 +2245,7 @@ static void igb_set_multi(struct net_device *netdev) memcpy(mta_list + (i*ETH_ALEN), mc_ptr->dmi_addr, ETH_ALEN); mc_ptr = mc_ptr->next; } - igb_update_mc_addr_list_82575(hw, mta_list, i, 1, - mac->rar_entry_count); + igb_update_mc_addr_list(hw, mta_list, i, 1, mac->rar_entry_count); kfree(mta_list); } -- GitLab From 28b0759c224cad4ae8f5ed47f5af862dd2d1e1ed Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:20:31 +0000 Subject: [PATCH 1319/4982] igb: remove unnecessary adapter->hw calls when just hw-> will do. There were several spots in the code making calls to adapter->hw when they could have just been accessing hw-> directly. I cleaned up the spots where this was visibly apparent. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 2d169a45c42..e3f521ccf9d 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1096,8 +1096,8 @@ static int __devinit igb_probe(struct pci_dev *pdev, mmio_len = pci_resource_len(pdev, 0); err = -EIO; - adapter->hw.hw_addr = ioremap(mmio_start, mmio_len); - if (!adapter->hw.hw_addr) + hw->hw_addr = ioremap(mmio_start, mmio_len); + if (!hw->hw_addr) goto err_ioremap; netdev->netdev_ops = &igb_netdev_ops; @@ -1357,9 +1357,7 @@ static void __devexit igb_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct igb_adapter *adapter = netdev_priv(netdev); -#ifdef CONFIG_IGB_DCA struct e1000_hw *hw = &adapter->hw; -#endif int err; /* flush_scheduled work may reschedule our watchdog task, so @@ -1392,9 +1390,9 @@ static void __devexit igb_remove(struct pci_dev *pdev) igb_free_queues(adapter); - iounmap(adapter->hw.hw_addr); - if (adapter->hw.flash_address) - iounmap(adapter->hw.flash_address); + iounmap(hw->hw_addr); + if (hw->flash_address) + iounmap(hw->flash_address); pci_release_selected_regions(pdev, pci_select_bars(pdev, IORESOURCE_MEM)); @@ -1784,7 +1782,7 @@ static void igb_setup_rctl(struct igb_adapter *adapter) rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC); rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_RDMTS_HALF | - (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT); + (hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT); /* * enable stripping of CRC. It's unlikely this will break BMC @@ -2176,15 +2174,16 @@ static void igb_clean_all_rx_rings(struct igb_adapter *adapter) static int igb_set_mac(struct net_device *netdev, void *p) { struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; struct sockaddr *addr = p; if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - memcpy(adapter->hw.mac.addr, addr->sa_data, netdev->addr_len); + memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len); - adapter->hw.mac.ops.rar_set(&adapter->hw, adapter->hw.mac.addr, 0); + hw->mac.ops.rar_set(hw, hw->mac.addr, 0); return 0; } @@ -4140,7 +4139,7 @@ static void igb_vlan_rx_add_vid(struct net_device *netdev, u16 vid) struct e1000_hw *hw = &adapter->hw; u32 vfta, index; - if ((adapter->hw.mng_cookie.status & + if ((hw->mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN) && (vid == adapter->mng_vlan_id)) return; -- GitLab From 4a3c6433e48592f260278966742a99e0d77de3cc Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:20:49 +0000 Subject: [PATCH 1320/4982] igb: don't read eicr when responding to legacy interrupts The interrupt handler was reading eicr and then doing nothing with the result. I have removed the variable and the register read since they provide no value to the legacy interrupt handler. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index e3f521ccf9d..56c14557cea 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3519,7 +3519,7 @@ static irqreturn_t igb_intr_msi(int irq, void *data) } /** - * igb_intr - Interrupt Handler + * igb_intr - Legacy Interrupt Handler * @irq: interrupt number * @data: pointer to a network interface device structure **/ @@ -3531,7 +3531,6 @@ static irqreturn_t igb_intr(int irq, void *data) /* Interrupt Auto-Mask...upon reading ICR, interrupts are masked. No * need for the IMC write */ u32 icr = rd32(E1000_ICR); - u32 eicr = 0; if (!icr) return IRQ_NONE; /* Not our interrupt */ @@ -3547,8 +3546,6 @@ static irqreturn_t igb_intr(int irq, void *data) adapter->stats.doosync++; } - eicr = rd32(E1000_EICR); - if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { hw->mac.get_link_status = 1; /* guard against interrupt when we're going down */ -- GitLab From a8564f033efade1b6f027c4bb807cdf8cf5c9570 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:21:10 +0000 Subject: [PATCH 1321/4982] igb: move get_hw_control within igb_resume. Move igb_get_hw_control up so that it is called just after the reset in igb_resume. This notifies the HW sooner that the driver is reassuming control of the device. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 56c14557cea..accab3f7357 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -4341,6 +4341,11 @@ static int igb_resume(struct pci_dev *pdev) /* e1000_power_up_phy(adapter); */ igb_reset(adapter); + + /* let the f/w know that the h/w is now under the control of the + * driver. */ + igb_get_hw_control(adapter); + wr32(E1000_WUS, ~0); if (netif_running(netdev)) { @@ -4351,10 +4356,6 @@ static int igb_resume(struct pci_dev *pdev) netif_device_attach(netdev); - /* let the f/w know that the h/w is now under the control of the - * driver. */ - igb_get_hw_control(adapter); - return 0; } #endif -- GitLab From fa4dfae0ce703976578015902025137d5e268501 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:21:31 +0000 Subject: [PATCH 1322/4982] igb: change pba size determination from if to switch statement As additional hardware is added to the igb driver it is easier to support the expansion via switch statements instead of using nested ifs. For this reason I am changing this to a switch statement. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index accab3f7357..d27e502097e 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -888,11 +888,14 @@ void igb_reset(struct igb_adapter *adapter) /* Repartition Pba for greater than 9k mtu * To take effect CTRL.RST is required. */ - if (mac->type != e1000_82576) { - pba = E1000_PBA_34K; - } - else { + switch (mac->type) { + case e1000_82576: pba = E1000_PBA_64K; + break; + case e1000_82575: + default: + pba = E1000_PBA_34K; + break; } if ((adapter->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN) && -- GitLab From 8675737a9c1bf6c295461efc64898359398e1c82 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:21:51 +0000 Subject: [PATCH 1323/4982] igb: remove disable_av variable from mac_info struct The disable_av variable is never used by the driver and provides no value as it is likely a leftover debugging variable. I have removed it and replaced the one spot that checked for it with a check for a valid address. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_hw.h | 1 - drivers/net/igb/e1000_mac.c | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h index 62ccd495356..6d1564f4383 100644 --- a/drivers/net/igb/e1000_hw.h +++ b/drivers/net/igb/e1000_hw.h @@ -484,7 +484,6 @@ struct e1000_mac_info { bool asf_firmware_present; bool autoneg; bool autoneg_failed; - bool disable_av; bool disable_hw_init_bits; bool get_link_status; bool ifs_params_forced; diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c index 6682206750d..e5d23e08650 100644 --- a/drivers/net/igb/e1000_mac.c +++ b/drivers/net/igb/e1000_mac.c @@ -200,7 +200,8 @@ void igb_rar_set(struct e1000_hw *hw, u8 *addr, u32 index) rar_high = ((u32) addr[4] | ((u32) addr[5] << 8)); - if (!hw->mac.disable_av) + /* If MAC address zero, no need to set the AV bit */ + if (rar_low || rar_high) rar_high |= E1000_RAH_AV; wr32(E1000_RAL(index), rar_low); -- GitLab From 450c87c8d28aeaf83889389ceeb01457c1a6f3e9 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:22:11 +0000 Subject: [PATCH 1324/4982] igb: remove redundant count set and err_hw_init Remove the setting of ring->count variables from igb_probe as they are duplicating the same configuration that is done igb_alloc_queues. Remove the err_hw_init tag as it can be replaced by err_sw_init. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index d27e502097e..3b79ad8be53 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1016,7 +1016,7 @@ static int __devinit igb_probe(struct pci_dev *pdev, struct pci_dev *us_dev; const struct e1000_info *ei = igb_info_tbl[ent->driver_data]; unsigned long mmio_start, mmio_len; - int i, err, pci_using_dac, pos; + int err, pci_using_dac, pos; u16 eeprom_data = 0, state = 0; u16 eeprom_apme_mask = IGB_EEPROM_APME; u32 part_num; @@ -1128,8 +1128,9 @@ static int __devinit igb_probe(struct pci_dev *pdev, /* Initialize skew-specific constants */ err = ei->get_invariants(hw); if (err) - goto err_hw_init; + goto err_sw_init; + /* setup the private structure */ err = igb_sw_init(adapter); if (err) goto err_sw_init; @@ -1219,14 +1220,7 @@ static int __devinit igb_probe(struct pci_dev *pdev, INIT_WORK(&adapter->reset_task, igb_reset_task); INIT_WORK(&adapter->watchdog_task, igb_watchdog_task); - /* Initialize link & ring properties that are user-changeable */ - adapter->tx_ring->count = 256; - for (i = 0; i < adapter->num_tx_queues; i++) - adapter->tx_ring[i].count = adapter->tx_ring->count; - adapter->rx_ring->count = 256; - for (i = 0; i < adapter->num_rx_queues; i++) - adapter->rx_ring[i].count = adapter->rx_ring->count; - + /* Initialize link properties that are user-changeable */ adapter->fc_autoneg = true; hw->mac.autoneg = true; hw->phy.autoneg_advertised = 0x2f; @@ -1334,7 +1328,6 @@ err_eeprom: igb_free_queues(adapter); err_sw_init: -err_hw_init: iounmap(hw->hw_addr); err_ioremap: free_netdev(netdev); -- GitLab From 04fe63583d4648c0378a58afc0de89b640d822ef Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:22:32 +0000 Subject: [PATCH 1325/4982] igb: update stats before doing reset in igb_down It was seen with repeated interface up/down testing that there was a large stray between the stats reported by the queues and the stats reported by the HW. It was found to be an issue in that hw stats were being reset without first being recorded. This change records the stats before wiping them from the system via the reset. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 3b79ad8be53..88f135f4b27 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -858,6 +858,10 @@ void igb_down(struct igb_adapter *adapter) netdev->tx_queue_len = adapter->tx_queue_len; netif_carrier_off(netdev); + + /* record the stats before reset*/ + igb_update_stats(adapter); + adapter->link_speed = 0; adapter->link_duplex = 0; -- GitLab From 265de4090853e56fb152e4cb0d21e4ec568d561a Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:22:52 +0000 Subject: [PATCH 1326/4982] igb: fix two minor items found during code review This patch addresses two minor items I found while cleaning up the igb driver for our sourceforge version. The first clears the context index if we don't flag that we need it. The second item is that eims_other should be used instead of bit defines when setting all of the EICS bits prior to reset. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 88f135f4b27..67138400af8 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2771,6 +2771,8 @@ static inline bool igb_tx_csum_adv(struct igb_adapter *adapter, if (adapter->flags & IGB_FLAG_NEED_CTX_IDX) context_desc->mss_l4len_idx = cpu_to_le32(tx_ring->queue_index << 4); + else + context_desc->mss_l4len_idx = 0; buffer_info->time_stamp = jiffies; buffer_info->next_to_watch = i; @@ -3040,8 +3042,8 @@ static void igb_tx_timeout(struct net_device *netdev) /* Do the reset outside of interrupt context */ adapter->tx_timeout_count++; schedule_work(&adapter->reset_task); - wr32(E1000_EICS, adapter->eims_enable_mask & - ~(E1000_EIMS_TCP_TIMER | E1000_EIMS_OTHER)); + wr32(E1000_EICS, + (adapter->eims_enable_mask & ~adapter->eims_other)); } static void igb_reset_task(struct work_struct *work) -- GitLab From 86d5d38fa1afe2c96f184482d6c6d1a59ee7e2dc Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Feb 2009 23:23:12 +0000 Subject: [PATCH 1327/4982] igb: update version number and copyright dates Update the version number to 1.3.16 and update copyright dates for 2009. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/Makefile | 2 +- drivers/net/igb/e1000_82575.c | 2 +- drivers/net/igb/e1000_82575.h | 2 +- drivers/net/igb/e1000_defines.h | 2 +- drivers/net/igb/e1000_hw.h | 2 +- drivers/net/igb/e1000_mac.c | 2 +- drivers/net/igb/e1000_mac.h | 2 +- drivers/net/igb/e1000_nvm.c | 2 +- drivers/net/igb/e1000_phy.c | 2 +- drivers/net/igb/e1000_phy.h | 2 +- drivers/net/igb/e1000_regs.h | 2 +- drivers/net/igb/igb.h | 2 +- drivers/net/igb/igb_ethtool.c | 2 +- drivers/net/igb/igb_main.c | 6 +++--- 14 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/net/igb/Makefile b/drivers/net/igb/Makefile index 1927b3fd6f0..cda3ad51baf 100644 --- a/drivers/net/igb/Makefile +++ b/drivers/net/igb/Makefile @@ -1,7 +1,7 @@ ################################################################################ # # Intel 82575 PCI-Express Ethernet Linux driver -# Copyright(c) 1999 - 2007 Intel Corporation. +# Copyright(c) 1999 - 2009 Intel Corporation. # # This program is free software; you can redistribute it and/or modify it # under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index 68a9822f405..7f43e253c56 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 - 2008 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h index e0a376fa28a..dd50237c8cb 100644 --- a/drivers/net/igb/e1000_82575.h +++ b/drivers/net/igb/e1000_82575.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 - 2008 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index bff62dd8431..5342e231c1d 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 - 2008 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h index 6d1564f4383..bd86cebed37 100644 --- a/drivers/net/igb/e1000_hw.h +++ b/drivers/net/igb/e1000_hw.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c index e5d23e08650..5c249e2ce93 100644 --- a/drivers/net/igb/e1000_mac.c +++ b/drivers/net/igb/e1000_mac.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_mac.h b/drivers/net/igb/e1000_mac.h index 4ef40d5629d..91461de083f 100644 --- a/drivers/net/igb/e1000_mac.h +++ b/drivers/net/igb/e1000_mac.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_nvm.c b/drivers/net/igb/e1000_nvm.c index 33798642208..a88bfe2f1e8 100644 --- a/drivers/net/igb/e1000_nvm.c +++ b/drivers/net/igb/e1000_nvm.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c index d73ea71d741..ff0050e5d0b 100644 --- a/drivers/net/igb/e1000_phy.c +++ b/drivers/net/igb/e1000_phy.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_phy.h b/drivers/net/igb/e1000_phy.h index 7499e5deec4..3228a862031 100644 --- a/drivers/net/igb/e1000_phy.h +++ b/drivers/net/igb/e1000_phy.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h index bdf5d839c4b..5038b73c78e 100644 --- a/drivers/net/igb/e1000_regs.h +++ b/drivers/net/igb/e1000_regs.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 0519ae408af..e507449b3cc 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index de09430ce7f..bd050b1dab7 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 67138400af8..8bc1ffa04ec 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 Intel Corporation. + Copyright(c) 2007-2009 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -48,12 +48,12 @@ #endif #include "igb.h" -#define DRV_VERSION "1.2.45-k2" +#define DRV_VERSION "1.3.16-k2" char igb_driver_name[] = "igb"; char igb_driver_version[] = DRV_VERSION; static const char igb_driver_string[] = "Intel(R) Gigabit Ethernet Network Driver"; -static const char igb_copyright[] = "Copyright (c) 2008 Intel Corporation."; +static const char igb_copyright[] = "Copyright (c) 2007-2009 Intel Corporation."; static const struct e1000_info *igb_info_tbl[] = { [board_82575] = &e1000_82575_info, -- GitLab From 593721833d2a3987736467144ad062a709d3a72c Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 6 Feb 2009 23:23:32 +0000 Subject: [PATCH 1328/4982] igb: remove dead code in transmit routine Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 8bc1ffa04ec..f8c2919bcec 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2951,12 +2951,9 @@ static int igb_xmit_frame_ring_adv(struct sk_buff *skb, struct igb_adapter *adapter = netdev_priv(netdev); unsigned int first; unsigned int tx_flags = 0; - unsigned int len; u8 hdr_len = 0; int tso = 0; - len = skb_headlen(skb); - if (test_bit(__IGB_DOWN, &adapter->state)) { dev_kfree_skb_any(skb); return NETDEV_TX_OK; -- GitLab From 0fb807c3e573ff9de2965ca38c907605d4735d16 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sun, 8 Feb 2009 11:00:25 +0530 Subject: [PATCH 1329/4982] unconditionally include asm/types.h from linux/types.h Reported-by: Sam Ravnborg Signed-off-by: Jaswinder Singh Rajput --- include/linux/types.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/types.h b/include/linux/types.h index c30973ace89..fca82ed55f4 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -1,6 +1,8 @@ #ifndef _LINUX_TYPES_H #define _LINUX_TYPES_H +#include + #ifndef __ASSEMBLY__ #ifdef __KERNEL__ @@ -10,7 +12,6 @@ #endif #include -#include #ifndef __KERNEL_STRICT_NAMES -- GitLab From 897dcded6fb6565f4d1c22a55d21f135403db132 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 4 Nov 2008 16:35:03 +0000 Subject: [PATCH 1330/4982] [ARM] omap: provide a NULL clock operations structure ... and use it for clocks which are ALWAYS_ENABLED. These clocks use a non-NULL enable_reg pointer for other purposes (such as selecting clock rates.) Signed-off-by: Russell King --- arch/arm/mach-omap1/clock.c | 3 - arch/arm/mach-omap1/clock.h | 78 +++++++++++------------ arch/arm/mach-omap2/clock.c | 4 +- arch/arm/mach-omap2/clock24xx.h | 31 ++++++--- arch/arm/mach-omap2/clock34xx.h | 85 +++++++++++++++---------- arch/arm/plat-omap/clock.c | 23 ++++++- arch/arm/plat-omap/include/mach/clock.h | 4 +- 7 files changed, 135 insertions(+), 93 deletions(-) diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index 25ef04da6b0..ff408105ffb 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -515,9 +515,6 @@ static int omap1_clk_enable_generic(struct clk *clk) __u16 regval16; __u32 regval32; - if (clk->flags & ALWAYS_ENABLED) - return 0; - if (unlikely(clk->enable_reg == NULL)) { printk(KERN_ERR "clock.c: Enable for %s without enable code\n", clk->name); diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h index 5b93a2a897a..8673832d829 100644 --- a/arch/arm/mach-omap1/clock.h +++ b/arch/arm/mach-omap1/clock.h @@ -144,18 +144,18 @@ static struct mpu_rate rate_table[] = { static struct clk ck_ref = { .name = "ck_ref", - .ops = &clkops_generic, + .ops = &clkops_null, .rate = 12000000, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP310 | ALWAYS_ENABLED, + CLOCK_IN_OMAP310, }; static struct clk ck_dpll1 = { .name = "ck_dpll1", - .ops = &clkops_generic, + .ops = &clkops_null, .parent = &ck_ref, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP310 | RATE_PROPAGATES | ALWAYS_ENABLED, + CLOCK_IN_OMAP310 | RATE_PROPAGATES, }; static struct arm_idlect1_clk ck_dpll1out = { @@ -186,11 +186,10 @@ static struct clk sossi_ck = { static struct clk arm_ck = { .name = "arm_ck", - .ops = &clkops_generic, + .ops = &clkops_null, .parent = &ck_dpll1, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP310 | RATE_CKCTL | RATE_PROPAGATES | - ALWAYS_ENABLED, + CLOCK_IN_OMAP310 | RATE_CKCTL | RATE_PROPAGATES, .rate_offset = CKCTL_ARMDIV_OFFSET, .recalc = &omap1_ckctl_recalc, }; @@ -265,9 +264,9 @@ static struct arm_idlect1_clk armwdt_ck = { static struct clk arminth_ck16xx = { .name = "arminth_ck", - .ops = &clkops_generic, + .ops = &clkops_null, .parent = &arm_ck, - .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP16XX, .recalc = &followparent_recalc, /* Note: On 16xx the frequency can be divided by 2 by programming * ARM_CKCTL:ARM_INTHCK_SEL(14) to 1 @@ -290,10 +289,10 @@ static struct clk dsp_ck = { static struct clk dspmmu_ck = { .name = "dspmmu_ck", - .ops = &clkops_generic, + .ops = &clkops_null, .parent = &ck_dpll1, .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - RATE_CKCTL | ALWAYS_ENABLED, + RATE_CKCTL, .rate_offset = CKCTL_DSPMMUDIV_OFFSET, .recalc = &omap1_ckctl_recalc, }; @@ -337,12 +336,12 @@ static struct clk dsptim_ck = { static struct arm_idlect1_clk tc_ck = { .clk = { .name = "tc_ck", - .ops = &clkops_generic, + .ops = &clkops_null, .parent = &ck_dpll1, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP730 | CLOCK_IN_OMAP310 | RATE_CKCTL | RATE_PROPAGATES | - ALWAYS_ENABLED | CLOCK_IDLE_CONTROL, + CLOCK_IDLE_CONTROL, .rate_offset = CKCTL_TCDIV_OFFSET, .recalc = &omap1_ckctl_recalc, }, @@ -351,10 +350,9 @@ static struct arm_idlect1_clk tc_ck = { static struct clk arminth_ck1510 = { .name = "arminth_ck", - .ops = &clkops_generic, + .ops = &clkops_null, .parent = &tc_ck.clk, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | - ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, .recalc = &followparent_recalc, /* Note: On 1510 the frequency follows TC_CK * @@ -365,10 +363,9 @@ static struct clk arminth_ck1510 = { static struct clk tipb_ck = { /* No-idle controlled by "tc_ck" */ .name = "tipb_ck", - .ops = &clkops_generic, + .ops = &clkops_null, .parent = &tc_ck.clk, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | - ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, .recalc = &followparent_recalc, }; @@ -406,18 +403,18 @@ static struct clk tc2_ck = { static struct clk dma_ck = { /* No-idle controlled by "tc_ck" */ .name = "dma_ck", - .ops = &clkops_generic, + .ops = &clkops_null, .parent = &tc_ck.clk, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP310 | ALWAYS_ENABLED, + CLOCK_IN_OMAP310, .recalc = &followparent_recalc, }; static struct clk dma_lcdfree_ck = { .name = "dma_lcdfree_ck", - .ops = &clkops_generic, + .ops = &clkops_null, .parent = &tc_ck.clk, - .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP16XX, .recalc = &followparent_recalc, }; @@ -451,17 +448,17 @@ static struct arm_idlect1_clk lb_ck = { static struct clk rhea1_ck = { .name = "rhea1_ck", - .ops = &clkops_generic, + .ops = &clkops_null, .parent = &tc_ck.clk, - .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP16XX, .recalc = &followparent_recalc, }; static struct clk rhea2_ck = { .name = "rhea2_ck", - .ops = &clkops_generic, + .ops = &clkops_null, .parent = &tc_ck.clk, - .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP16XX, .recalc = &followparent_recalc, }; @@ -493,13 +490,12 @@ static struct arm_idlect1_clk lcd_ck_1510 = { static struct clk uart1_1510 = { .name = "uart1_ck", - .ops = &clkops_generic, + .ops = &clkops_null, /* Direct from ULPD, no real parent */ .parent = &armper_ck.clk, .rate = 12000000, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | - ENABLE_REG_32BIT | ALWAYS_ENABLED | - CLOCK_NO_IDLE_PARENT, + ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, .enable_bit = 29, /* Chooses between 12MHz and 48MHz */ .set_rate = &omap1_set_uart_rate, @@ -523,13 +519,13 @@ static struct uart_clk uart1_16xx = { static struct clk uart2_ck = { .name = "uart2_ck", - .ops = &clkops_generic, + .ops = &clkops_null, /* Direct from ULPD, no real parent */ .parent = &armper_ck.clk, .rate = 12000000, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 | ENABLE_REG_32BIT | - ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT, + CLOCK_NO_IDLE_PARENT, .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, .enable_bit = 30, /* Chooses between 12MHz and 48MHz */ .set_rate = &omap1_set_uart_rate, @@ -538,13 +534,12 @@ static struct clk uart2_ck = { static struct clk uart3_1510 = { .name = "uart3_ck", - .ops = &clkops_generic, + .ops = &clkops_null, /* Direct from ULPD, no real parent */ .parent = &armper_ck.clk, .rate = 12000000, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | - ENABLE_REG_32BIT | ALWAYS_ENABLED | - CLOCK_NO_IDLE_PARENT, + ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, .enable_bit = 31, /* Chooses between 12MHz and 48MHz */ .set_rate = &omap1_set_uart_rate, @@ -680,9 +675,9 @@ static struct clk mmc2_ck = { static struct clk virtual_ck_mpu = { .name = "mpu", - .ops = &clkops_generic, + .ops = &clkops_null, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP310 | ALWAYS_ENABLED, + CLOCK_IN_OMAP310, .parent = &arm_ck, /* Is smarter alias for */ .recalc = &followparent_recalc, .set_rate = &omap1_select_table_rate, @@ -694,9 +689,9 @@ remains active during MPU idle whenever this is enabled */ static struct clk i2c_fck = { .name = "i2c_fck", .id = 1, - .ops = &clkops_generic, + .ops = &clkops_null, .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_NO_IDLE_PARENT | ALWAYS_ENABLED, + CLOCK_NO_IDLE_PARENT, .parent = &armxor_ck.clk, .recalc = &followparent_recalc, }; @@ -704,9 +699,8 @@ static struct clk i2c_fck = { static struct clk i2c_ick = { .name = "i2c_ick", .id = 1, - .ops = &clkops_generic, - .flags = CLOCK_IN_OMAP16XX | CLOCK_NO_IDLE_PARENT | - ALWAYS_ENABLED, + .ops = &clkops_null, + .flags = CLOCK_IN_OMAP16XX | CLOCK_NO_IDLE_PARENT, .parent = &armper_ck.clk, .recalc = &followparent_recalc, }; diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index d3213f565d5..fa99c0b71d3 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -271,7 +271,7 @@ int _omap2_clk_enable(struct clk *clk) { u32 regval32; - if (clk->flags & (ALWAYS_ENABLED | PARENT_CONTROLS_CLOCK)) + if (clk->flags & PARENT_CONTROLS_CLOCK) return 0; if (clk->ops && clk->ops->enable) @@ -301,7 +301,7 @@ void _omap2_clk_disable(struct clk *clk) { u32 regval32; - if (clk->flags & (ALWAYS_ENABLED | PARENT_CONTROLS_CLOCK)) + if (clk->flags & PARENT_CONTROLS_CLOCK) return; if (clk->ops && clk->ops->disable) { diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h index 2aa0b5e6560..d4869377307 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock24xx.h @@ -619,9 +619,10 @@ static struct prcm_config rate_table[] = { /* Base external input clocks */ static struct clk func_32k_ck = { .name = "func_32k_ck", + .ops = &clkops_null, .rate = 32000, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES, + RATE_FIXED | RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .recalc = &propagate_rate, }; @@ -639,18 +640,20 @@ static struct clk osc_ck = { /* (*12, *13, 19.2, *26, 38.4)MHz */ /* Without modem likely 12MHz, with modem likely 13MHz */ static struct clk sys_ck = { /* (*12, *13, 19.2, 26, 38.4)MHz */ .name = "sys_ck", /* ~ ref_clk also */ + .ops = &clkops_null, .parent = &osc_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - ALWAYS_ENABLED | RATE_PROPAGATES, + RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .recalc = &omap2_sys_clk_recalc, }; static struct clk alt_ck = { /* Typical 54M or 48M, may not exist */ .name = "alt_ck", + .ops = &clkops_null, .rate = 54000000, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES, + RATE_FIXED | RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .recalc = &propagate_rate, }; @@ -679,10 +682,11 @@ static struct dpll_data dpll_dd = { */ static struct clk dpll_ck = { .name = "dpll_ck", + .ops = &clkops_null, .parent = &sys_ck, /* Can be func_32k also */ .dpll_data = &dpll_dd, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - RATE_PROPAGATES | ALWAYS_ENABLED, + RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .recalc = &omap2_dpllcore_recalc, .set_rate = &omap2_reprogram_dpllcore, @@ -751,9 +755,10 @@ static struct clk func_54m_ck = { static struct clk core_ck = { .name = "core_ck", + .ops = &clkops_null, .parent = &dpll_ck, /* can also be 32k */ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - ALWAYS_ENABLED | RATE_PROPAGATES, + RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -837,6 +842,7 @@ static struct clk func_12m_ck = { /* Secure timer, only available in secure mode */ static struct clk wdt1_osc_ck = { .name = "ck_wdt1_osc", + .ops = &clkops_null, /* RMK: missing? */ .parent = &osc_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .recalc = &followparent_recalc, @@ -996,9 +1002,10 @@ static const struct clksel mpu_clksel[] = { static struct clk mpu_ck = { /* Control cpu */ .name = "mpu_ck", + .ops = &clkops_null, .parent = &core_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - ALWAYS_ENABLED | DELAYED_APP | + DELAYED_APP | CONFIG_PARTICIPANT | RATE_PROPAGATES, .clkdm_name = "mpu_clkdm", .init = &omap2_init_clksel_parent, @@ -1168,9 +1175,10 @@ static const struct clksel core_l3_clksel[] = { static struct clk core_l3_ck = { /* Used for ick and fck, interconnect */ .name = "core_l3_ck", + .ops = &clkops_null, .parent = &core_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - ALWAYS_ENABLED | DELAYED_APP | + DELAYED_APP | CONFIG_PARTICIPANT | RATE_PROPAGATES, .clkdm_name = "core_l3_clkdm", .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1), @@ -1231,9 +1239,10 @@ static const struct clksel l4_clksel[] = { static struct clk l4_ck = { /* used both as an ick and fck */ .name = "l4_ck", + .ops = &clkops_null, .parent = &core_l3_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - ALWAYS_ENABLED | DELAYED_APP | RATE_PROPAGATES, + DELAYED_APP | RATE_PROPAGATES, .clkdm_name = "core_l4_clkdm", .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1), .clksel_mask = OMAP24XX_CLKSEL_L4_MASK, @@ -2359,6 +2368,7 @@ static struct clk i2chs1_fck = { static struct clk gpmc_fck = { .name = "gpmc_fck", + .ops = &clkops_null, /* RMK: missing? */ .parent = &core_l3_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ENABLE_ON_INIT, @@ -2368,6 +2378,7 @@ static struct clk gpmc_fck = { static struct clk sdma_fck = { .name = "sdma_fck", + .ops = &clkops_null, /* RMK: missing? */ .parent = &core_l3_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l3_clkdm", @@ -2376,6 +2387,7 @@ static struct clk sdma_fck = { static struct clk sdma_ick = { .name = "sdma_ick", + .ops = &clkops_null, /* RMK: missing? */ .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l3_clkdm", @@ -2621,8 +2633,9 @@ static struct clk mmchsdb2_fck = { */ static struct clk virt_prcm_set = { .name = "virt_prcm_set", + .ops = &clkops_null, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - ALWAYS_ENABLED | DELAYED_APP, + DELAYED_APP, .parent = &mpu_ck, /* Indexed by mpu speed, no parent */ .recalc = &omap2_table_mpu_recalc, /* sets are keyed on mpu rate */ .set_rate = &omap2_select_table_rate, diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index 8b188fb9bea..b56fd289762 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -55,66 +55,66 @@ static u32 omap3_dpll_autoidle_read(struct clk *clk); /* According to timer32k.c, this is a 32768Hz clock, not a 32000Hz clock. */ static struct clk omap_32k_fck = { .name = "omap_32k_fck", + .ops = &clkops_null, .rate = 32768, - .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES | - ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES, .recalc = &propagate_rate, }; static struct clk secure_32k_fck = { .name = "secure_32k_fck", + .ops = &clkops_null, .rate = 32768, - .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES | - ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES, .recalc = &propagate_rate, }; /* Virtual source clocks for osc_sys_ck */ static struct clk virt_12m_ck = { .name = "virt_12m_ck", + .ops = &clkops_null, .rate = 12000000, - .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES | - ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES, .recalc = &propagate_rate, }; static struct clk virt_13m_ck = { .name = "virt_13m_ck", + .ops = &clkops_null, .rate = 13000000, - .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES | - ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES, .recalc = &propagate_rate, }; static struct clk virt_16_8m_ck = { .name = "virt_16_8m_ck", + .ops = &clkops_null, .rate = 16800000, - .flags = CLOCK_IN_OMAP3430ES2 | RATE_FIXED | RATE_PROPAGATES | - ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP3430ES2 | RATE_FIXED | RATE_PROPAGATES, .recalc = &propagate_rate, }; static struct clk virt_19_2m_ck = { .name = "virt_19_2m_ck", + .ops = &clkops_null, .rate = 19200000, - .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES | - ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES, .recalc = &propagate_rate, }; static struct clk virt_26m_ck = { .name = "virt_26m_ck", + .ops = &clkops_null, .rate = 26000000, - .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES | - ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES, .recalc = &propagate_rate, }; static struct clk virt_38_4m_ck = { .name = "virt_38_4m_ck", + .ops = &clkops_null, .rate = 38400000, - .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES | - ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES, .recalc = &propagate_rate, }; @@ -162,13 +162,13 @@ static const struct clksel osc_sys_clksel[] = { /* 12, 13, 16.8, 19.2, 26, or 38.4 MHz */ static struct clk osc_sys_ck = { .name = "osc_sys_ck", + .ops = &clkops_null, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP3430_PRM_CLKSEL, .clksel_mask = OMAP3430_SYS_CLKIN_SEL_MASK, .clksel = osc_sys_clksel, /* REVISIT: deal with autoextclkmode? */ - .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES | - ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -187,25 +187,28 @@ static const struct clksel sys_clksel[] = { /* Feeds DPLLs - divided first by PRM_CLKSRC_CTRL.SYSCLKDIV? */ static struct clk sys_ck = { .name = "sys_ck", + .ops = &clkops_null, .parent = &osc_sys_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP3430_PRM_CLKSRC_CTRL, .clksel_mask = OMAP_SYSCLKDIV_MASK, .clksel = sys_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; static struct clk sys_altclk = { .name = "sys_altclk", - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, + .ops = &clkops_null, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &propagate_rate, }; /* Optional external clock input for some McBSPs */ static struct clk mcbsp_clks = { .name = "mcbsp_clks", - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, + .ops = &clkops_null, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &propagate_rate, }; @@ -278,9 +281,10 @@ static struct dpll_data dpll1_dd = { static struct clk dpll1_ck = { .name = "dpll1_ck", + .ops = &clkops_null, .parent = &sys_ck, .dpll_data = &dpll1_dd, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .round_rate = &omap2_dpll_round_rate, .recalc = &omap3_dpll_recalc, }; @@ -398,9 +402,10 @@ static struct dpll_data dpll3_dd = { static struct clk dpll3_ck = { .name = "dpll3_ck", + .ops = &clkops_null, .parent = &sys_ck, .dpll_data = &dpll3_dd, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .round_rate = &omap2_dpll_round_rate, .recalc = &omap3_dpll_recalc, }; @@ -2266,9 +2271,10 @@ static struct clk gpt1_fck = { static struct clk wkup_32k_fck = { .name = "wkup_32k_fck", + .ops = &clkops_null, .init = &omap2_init_clk_clkdm, .parent = &omap_32k_fck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2295,8 +2301,9 @@ static struct clk wdt2_fck = { static struct clk wkup_l4_ick = { .name = "wkup_l4_ick", + .ops = &clkops_null, .parent = &sys_ck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2514,9 +2521,10 @@ static struct clk gpt9_fck = { static struct clk per_32k_alwon_fck = { .name = "per_32k_alwon_fck", + .ops = &clkops_null, .parent = &omap_32k_fck, .clkdm_name = "per_clkdm", - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &followparent_recalc, }; @@ -2859,11 +2867,12 @@ static const struct clksel emu_src_clksel[] = { */ static struct clk emu_src_ck = { .name = "emu_src_ck", + .ops = &clkops_null, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_MUX_CTRL_MASK, .clksel = emu_src_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .clkdm_name = "emu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2883,11 +2892,12 @@ static const struct clksel pclk_emu_clksel[] = { static struct clk pclk_fck = { .name = "pclk_fck", + .ops = &clkops_null, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_CLKSEL_PCLK_MASK, .clksel = pclk_emu_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .clkdm_name = "emu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2906,11 +2916,12 @@ static const struct clksel pclkx2_emu_clksel[] = { static struct clk pclkx2_fck = { .name = "pclkx2_fck", + .ops = &clkops_null, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_CLKSEL_PCLKX2_MASK, .clksel = pclkx2_emu_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .clkdm_name = "emu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2922,22 +2933,24 @@ static const struct clksel atclk_emu_clksel[] = { static struct clk atclk_fck = { .name = "atclk_fck", + .ops = &clkops_null, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_CLKSEL_ATCLK_MASK, .clksel = atclk_emu_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .clkdm_name = "emu_clkdm", .recalc = &omap2_clksel_recalc, }; static struct clk traceclk_src_fck = { .name = "traceclk_src_fck", + .ops = &clkops_null, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_TRACE_MUX_CTRL_MASK, .clksel = emu_src_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .clkdm_name = "emu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2956,11 +2969,12 @@ static const struct clksel traceclk_clksel[] = { static struct clk traceclk_fck = { .name = "traceclk_fck", + .ops = &clkops_null, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_CLKSEL_TRACECLK_MASK, .clksel = traceclk_clksel, - .flags = CLOCK_IN_OMAP343X | ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP343X, .clkdm_name = "emu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2989,6 +3003,7 @@ static struct clk sr2_fck = { static struct clk sr_l4_ick = { .name = "sr_l4_ick", + .ops = &clkops_null, /* RMK: missing? */ .parent = &l4_ick, .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", @@ -3000,15 +3015,17 @@ static struct clk sr_l4_ick = { /* XXX This clock no longer exists in 3430 TRM rev F */ static struct clk gpt12_fck = { .name = "gpt12_fck", + .ops = &clkops_null, .parent = &secure_32k_fck, - .flags = CLOCK_IN_OMAP343X | ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP343X, .recalc = &followparent_recalc, }; static struct clk wdt1_fck = { .name = "wdt1_fck", + .ops = &clkops_null, .parent = &secure_32k_fck, - .flags = CLOCK_IN_OMAP343X | ALWAYS_ENABLED, + .flags = CLOCK_IN_OMAP343X, .recalc = &followparent_recalc, }; diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index be6aab9c683..529c4a9f012 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -358,6 +358,23 @@ void clk_enable_init_clocks(void) } EXPORT_SYMBOL(clk_enable_init_clocks); +/* + * Low level helpers + */ +static int clkll_enable_null(struct clk *clk) +{ + return 0; +} + +static void clkll_disable_null(struct clk *clk) +{ +} + +const struct clkops clkops_null = { + .enable = clkll_enable_null, + .disable = clkll_disable_null, +}; + #ifdef CONFIG_CPU_FREQ void clk_init_cpufreq_table(struct cpufreq_frequency_table **table) { @@ -383,8 +400,10 @@ static int __init clk_disable_unused(void) unsigned long flags; list_for_each_entry(ck, &clocks, node) { - if (ck->usecount > 0 || (ck->flags & ALWAYS_ENABLED) || - ck->enable_reg == 0) + if (ck->ops == &clkops_null) + continue; + + if (ck->usecount > 0 || ck->enable_reg == 0) continue; spin_lock_irqsave(&clockfw_lock, flags); diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index 4fe5084e8cc..c1e484463ed 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -125,11 +125,13 @@ extern void clk_deny_idle(struct clk *clk); extern int clk_get_usecount(struct clk *clk); extern void clk_enable_init_clocks(void); +extern const struct clkops clkops_null; + /* Clock flags */ #define RATE_CKCTL (1 << 0) /* Main fixed ratio clocks */ #define RATE_FIXED (1 << 1) /* Fixed clock rate */ #define RATE_PROPAGATES (1 << 2) /* Program children too */ -#define ALWAYS_ENABLED (1 << 4) /* Clock cannot be disabled */ +/* bits 3-4 are free */ #define ENABLE_REG_32BIT (1 << 5) /* Use 32-bit access */ #define VIRTUAL_IO_ADDRESS (1 << 6) /* Clock in virtual address */ #define CLOCK_IDLE_CONTROL (1 << 7) -- GitLab From 57137181e3136d4c7b20b4b95b9817efd38f8f07 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 4 Nov 2008 16:48:35 +0000 Subject: [PATCH 1331/4982] [ARM] omap: kill PARENT_CONTROLS_CLOCK PARENT_CONTROLS_CLOCK just makes enable/disable no-op, and is functionally an alias for ALWAYS_ENABLED. This can be handled in the same way, using clkops_null. Signed-off-by: Russell King --- arch/arm/mach-omap2/clock.c | 6 - arch/arm/mach-omap2/clock24xx.h | 22 ++- arch/arm/mach-omap2/clock34xx.h | 196 ++++++++++++------------ arch/arm/plat-omap/include/mach/clock.h | 1 - 4 files changed, 114 insertions(+), 111 deletions(-) diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index fa99c0b71d3..21fbe29810a 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -271,9 +271,6 @@ int _omap2_clk_enable(struct clk *clk) { u32 regval32; - if (clk->flags & PARENT_CONTROLS_CLOCK) - return 0; - if (clk->ops && clk->ops->enable) return clk->ops->enable(clk); @@ -301,9 +298,6 @@ void _omap2_clk_disable(struct clk *clk) { u32 regval32; - if (clk->flags & PARENT_CONTROLS_CLOCK) - return; - if (clk->ops && clk->ops->disable) { clk->ops->disable(clk); return; diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h index d4869377307..adc00e1064a 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock24xx.h @@ -742,9 +742,10 @@ static const struct clksel func_54m_clksel[] = { static struct clk func_54m_ck = { .name = "func_54m_ck", + .ops = &clkops_null, .parent = &apll54_ck, /* can also be alt_clk */ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - RATE_PROPAGATES | PARENT_CONTROLS_CLOCK, + RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), @@ -783,9 +784,10 @@ static const struct clksel func_96m_clksel[] = { /* The parent of this clock is not selectable on 2420. */ static struct clk func_96m_ck = { .name = "func_96m_ck", + .ops = &clkops_null, .parent = &apll96_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - RATE_PROPAGATES | PARENT_CONTROLS_CLOCK, + RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), @@ -816,9 +818,10 @@ static const struct clksel func_48m_clksel[] = { static struct clk func_48m_ck = { .name = "func_48m_ck", + .ops = &clkops_null, .parent = &apll96_ck, /* 96M or Alt */ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - RATE_PROPAGATES | PARENT_CONTROLS_CLOCK, + RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), @@ -831,10 +834,11 @@ static struct clk func_48m_ck = { static struct clk func_12m_ck = { .name = "func_12m_ck", + .ops = &clkops_null, .parent = &func_48m_ck, .fixed_div = 4, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - RATE_PROPAGATES | PARENT_CONTROLS_CLOCK, + RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .recalc = &omap2_fixed_divisor_recalc, }; @@ -917,9 +921,9 @@ static const struct clksel sys_clkout_clksel[] = { static struct clk sys_clkout = { .name = "sys_clkout", + .ops = &clkops_null, .parent = &sys_clkout_src, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "wkup_clkdm", .clksel_reg = OMAP24XX_PRCM_CLKOUT_CTRL, .clksel_mask = OMAP24XX_CLKOUT_DIV_MASK, @@ -954,8 +958,9 @@ static const struct clksel sys_clkout2_clksel[] = { /* In 2430, new in 2420 ES2 */ static struct clk sys_clkout2 = { .name = "sys_clkout2", + .ops = &clkops_null, .parent = &sys_clkout2_src, - .flags = CLOCK_IN_OMAP242X | PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP242X, .clkdm_name = "wkup_clkdm", .clksel_reg = OMAP24XX_PRCM_CLKOUT_CTRL, .clksel_mask = OMAP2420_CLKOUT2_DIV_MASK, @@ -1076,9 +1081,10 @@ static const struct clksel dsp_irate_ick_clksel[] = { /* This clock does not exist as such in the TRM. */ static struct clk dsp_irate_ick = { .name = "dsp_irate_ick", + .ops = &clkops_null, .parent = &dsp_fck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP | - CONFIG_PARTICIPANT | PARENT_CONTROLS_CLOCK, + CONFIG_PARTICIPANT, .clksel_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL), .clksel_mask = OMAP24XX_CLKSEL_DSP_IF_MASK, .clksel = dsp_irate_ick_clksel, diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index b56fd289762..203e2bd3b3b 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -295,9 +295,9 @@ static struct clk dpll1_ck = { */ static struct clk dpll1_x2_ck = { .name = "dpll1_x2_ck", + .ops = &clkops_null, .parent = &dpll1_ck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap3_clkoutx2_recalc, }; @@ -313,13 +313,13 @@ static const struct clksel div16_dpll1_x2m2_clksel[] = { */ static struct clk dpll1_x2m2_ck = { .name = "dpll1_x2m2_ck", + .ops = &clkops_null, .parent = &dpll1_x2_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL), .clksel_mask = OMAP3430_MPU_DPLL_CLKOUT_DIV_MASK, .clksel = div16_dpll1_x2m2_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -368,14 +368,14 @@ static const struct clksel div16_dpll2_m2x2_clksel[] = { */ static struct clk dpll2_m2_ck = { .name = "dpll2_m2_ck", + .ops = &clkops_null, .parent = &dpll2_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL2_PLL), .clksel_mask = OMAP3430_IVA2_DPLL_CLKOUT_DIV_MASK, .clksel = div16_dpll2_m2x2_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -416,9 +416,9 @@ static struct clk dpll3_ck = { */ static struct clk dpll3_x2_ck = { .name = "dpll3_x2_ck", + .ops = &clkops_null, .parent = &dpll3_ck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap3_clkoutx2_recalc, }; @@ -469,13 +469,13 @@ static const struct clksel div31_dpll3m2_clksel[] = { */ static struct clk dpll3_m2_ck = { .name = "dpll3_m2_ck", + .ops = &clkops_null, .parent = &dpll3_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK, .clksel = div31_dpll3m2_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -487,12 +487,12 @@ static const struct clksel core_ck_clksel[] = { static struct clk core_ck = { .name = "core_ck", + .ops = &clkops_null, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), .clksel_mask = OMAP3430_ST_CORE_CLK_MASK, .clksel = core_ck_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -504,12 +504,12 @@ static const struct clksel dpll3_m2x2_ck_clksel[] = { static struct clk dpll3_m2x2_ck = { .name = "dpll3_m2x2_ck", + .ops = &clkops_null, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), .clksel_mask = OMAP3430_ST_CORE_CLK_MASK, .clksel = dpll3_m2x2_ck_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -522,13 +522,13 @@ static const struct clksel div16_dpll3_clksel[] = { /* This virtual clock is the source for dpll3_m3x2_ck */ static struct clk dpll3_m3_ck = { .name = "dpll3_m3_ck", + .ops = &clkops_null, .parent = &dpll3_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_DIV_DPLL3_MASK, .clksel = div16_dpll3_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -550,13 +550,13 @@ static const struct clksel emu_core_alwon_ck_clksel[] = { static struct clk emu_core_alwon_ck = { .name = "emu_core_alwon_ck", + .ops = &clkops_null, .parent = &dpll3_m3x2_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), .clksel_mask = OMAP3430_ST_CORE_CLK_MASK, .clksel = emu_core_alwon_ck_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -599,9 +599,9 @@ static struct clk dpll4_ck = { */ static struct clk dpll4_x2_ck = { .name = "dpll4_x2_ck", + .ops = &clkops_null, .parent = &dpll4_ck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap3_clkoutx2_recalc, }; @@ -613,13 +613,13 @@ static const struct clksel div16_dpll4_clksel[] = { /* This virtual clock is the source for dpll4_m2x2_ck */ static struct clk dpll4_m2_ck = { .name = "dpll4_m2_ck", + .ops = &clkops_null, .parent = &dpll4_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430_CM_CLKSEL3), .clksel_mask = OMAP3430_DIV_96M_MASK, .clksel = div16_dpll4_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -641,21 +641,21 @@ static const struct clksel omap_96m_alwon_fck_clksel[] = { static struct clk omap_96m_alwon_fck = { .name = "omap_96m_alwon_fck", + .ops = &clkops_null, .parent = &dpll4_m2x2_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), .clksel_mask = OMAP3430_ST_PERIPH_CLK_MASK, .clksel = omap_96m_alwon_fck_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; static struct clk omap_96m_fck = { .name = "omap_96m_fck", + .ops = &clkops_null, .parent = &omap_96m_alwon_fck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &followparent_recalc, }; @@ -667,26 +667,26 @@ static const struct clksel cm_96m_fck_clksel[] = { static struct clk cm_96m_fck = { .name = "cm_96m_fck", + .ops = &clkops_null, .parent = &dpll4_m2x2_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), .clksel_mask = OMAP3430_ST_PERIPH_CLK_MASK, .clksel = cm_96m_fck_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; /* This virtual clock is the source for dpll4_m3x2_ck */ static struct clk dpll4_m3_ck = { .name = "dpll4_m3_ck", + .ops = &clkops_null, .parent = &dpll4_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_TV_MASK, .clksel = div16_dpll4_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -709,13 +709,13 @@ static const struct clksel virt_omap_54m_fck_clksel[] = { static struct clk virt_omap_54m_fck = { .name = "virt_omap_54m_fck", + .ops = &clkops_null, .parent = &dpll4_m3x2_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), .clksel_mask = OMAP3430_ST_PERIPH_CLK_MASK, .clksel = virt_omap_54m_fck_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -737,12 +737,12 @@ static const struct clksel omap_54m_clksel[] = { static struct clk omap_54m_fck = { .name = "omap_54m_fck", + .ops = &clkops_null, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_SOURCE_54M, .clksel = omap_54m_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -764,34 +764,34 @@ static const struct clksel omap_48m_clksel[] = { static struct clk omap_48m_fck = { .name = "omap_48m_fck", + .ops = &clkops_null, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_SOURCE_48M, .clksel = omap_48m_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; static struct clk omap_12m_fck = { .name = "omap_12m_fck", + .ops = &clkops_null, .parent = &omap_48m_fck, .fixed_div = 4, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap2_fixed_divisor_recalc, }; /* This virstual clock is the source for dpll4_m4x2_ck */ static struct clk dpll4_m4_ck = { .name = "dpll4_m4_ck", + .ops = &clkops_null, .parent = &dpll4_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_DSS1_MASK, .clksel = div16_dpll4_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -808,13 +808,13 @@ static struct clk dpll4_m4x2_ck = { /* This virtual clock is the source for dpll4_m5x2_ck */ static struct clk dpll4_m5_ck = { .name = "dpll4_m5_ck", + .ops = &clkops_null, .parent = &dpll4_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_CAM_MASK, .clksel = div16_dpll4_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -831,13 +831,13 @@ static struct clk dpll4_m5x2_ck = { /* This virtual clock is the source for dpll4_m6x2_ck */ static struct clk dpll4_m6_ck = { .name = "dpll4_m6_ck", + .ops = &clkops_null, .parent = &dpll4_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_DIV_DPLL4_MASK, .clksel = div16_dpll4_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -854,9 +854,9 @@ static struct clk dpll4_m6x2_ck = { static struct clk emu_per_alwon_ck = { .name = "emu_per_alwon_ck", + .ops = &clkops_null, .parent = &dpll4_m6x2_ck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &followparent_recalc, }; @@ -900,13 +900,13 @@ static const struct clksel div16_dpll5_clksel[] = { static struct clk dpll5_m2_ck = { .name = "dpll5_m2_ck", + .ops = &clkops_null, .parent = &dpll5_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL5), .clksel_mask = OMAP3430ES2_DIV_120M_MASK, .clksel = div16_dpll5_clksel, - .flags = CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -918,13 +918,13 @@ static const struct clksel omap_120m_fck_clksel[] = { static struct clk omap_120m_fck = { .name = "omap_120m_fck", + .ops = &clkops_null, .parent = &dpll5_m2_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2), .clksel_mask = OMAP3430ES2_ST_PERIPH2_CLK_MASK, .clksel = omap_120m_fck_clksel, - .flags = CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -986,11 +986,12 @@ static const struct clksel sys_clkout2_clksel[] = { static struct clk sys_clkout2 = { .name = "sys_clkout2", + .ops = &clkops_null, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP3430_CM_CLKOUT_CTRL, .clksel_mask = OMAP3430_CLKOUT2_DIV_MASK, .clksel = sys_clkout2_clksel, - .flags = CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X, .recalc = &omap2_clksel_recalc, }; @@ -998,9 +999,9 @@ static struct clk sys_clkout2 = { static struct clk corex2_fck = { .name = "corex2_fck", + .ops = &clkops_null, .parent = &dpll3_m2x2_ck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &followparent_recalc, }; @@ -1017,13 +1018,13 @@ static const struct clksel div2_core_clksel[] = { */ static struct clk dpll1_fck = { .name = "dpll1_fck", + .ops = &clkops_null, .parent = &core_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL), .clksel_mask = OMAP3430_MPU_CLK_SRC_MASK, .clksel = div2_core_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -1041,13 +1042,13 @@ static const struct clksel mpu_clksel[] = { static struct clk mpu_ck = { .name = "mpu_ck", + .ops = &clkops_null, .parent = &dpll1_x2m2_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), .clksel_mask = OMAP3430_ST_MPU_CLK_MASK, .clksel = mpu_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .clkdm_name = "mpu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1066,13 +1067,13 @@ static const struct clksel arm_fck_clksel[] = { static struct clk arm_fck = { .name = "arm_fck", + .ops = &clkops_null, .parent = &mpu_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), .clksel_mask = OMAP3430_ST_MPU_CLK_MASK, .clksel = arm_fck_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -1084,21 +1085,21 @@ static struct clk arm_fck = { */ static struct clk emu_mpu_alwon_ck = { .name = "emu_mpu_alwon_ck", + .ops = &clkops_null, .parent = &mpu_ck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &followparent_recalc, }; static struct clk dpll2_fck = { .name = "dpll2_fck", + .ops = &clkops_null, .parent = &core_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL), .clksel_mask = OMAP3430_IVA2_CLK_SRC_MASK, .clksel = div2_core_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -1134,13 +1135,13 @@ static struct clk iva2_ck = { static struct clk l3_ick = { .name = "l3_ick", + .ops = &clkops_null, .parent = &core_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_L3_MASK, .clksel = div2_core_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .clkdm_name = "core_l3_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1152,13 +1153,13 @@ static const struct clksel div2_l3_clksel[] = { static struct clk l4_ick = { .name = "l4_ick", + .ops = &clkops_null, .parent = &l3_ick, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_L4_MASK, .clksel = div2_l3_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .clkdm_name = "core_l4_clkdm", .recalc = &omap2_clksel_recalc, @@ -1171,12 +1172,13 @@ static const struct clksel div2_l4_clksel[] = { static struct clk rm_ick = { .name = "rm_ick", + .ops = &clkops_null, .parent = &l4_ick, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_RM_MASK, .clksel = div2_l4_clksel, - .flags = CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X, .recalc = &omap2_clksel_recalc, }; @@ -1202,21 +1204,22 @@ static struct clk gfx_l3_ck = { static struct clk gfx_l3_fck = { .name = "gfx_l3_fck", + .ops = &clkops_null, .parent = &gfx_l3_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL), .clksel_mask = OMAP_CLKSEL_GFX_MASK, .clksel = gfx_l3_clksel, - .flags = CLOCK_IN_OMAP3430ES1 | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP3430ES1 | RATE_PROPAGATES, .clkdm_name = "gfx_3430es1_clkdm", .recalc = &omap2_clksel_recalc, }; static struct clk gfx_l3_ick = { .name = "gfx_l3_ick", + .ops = &clkops_null, .parent = &gfx_l3_ck, - .flags = CLOCK_IN_OMAP3430ES1 | PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP3430ES1, .clkdm_name = "gfx_3430es1_clkdm", .recalc = &followparent_recalc, }; @@ -1365,9 +1368,9 @@ static struct clk usbtll_fck = { static struct clk core_96m_fck = { .name = "core_96m_fck", + .ops = &clkops_null, .parent = &omap_96m_fck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1499,9 +1502,9 @@ static struct clk mcbsp1_fck = { static struct clk core_48m_fck = { .name = "core_48m_fck", + .ops = &clkops_null, .parent = &omap_48m_fck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1577,9 +1580,9 @@ static struct clk fshostusb_fck = { static struct clk core_12m_fck = { .name = "core_12m_fck", + .ops = &clkops_null, .parent = &omap_12m_fck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1625,9 +1628,10 @@ static struct clk ssi_ssr_fck = { static struct clk ssi_sst_fck = { .name = "ssi_sst_fck", + .ops = &clkops_null, .parent = &ssi_ssr_fck, .fixed_div = 2, - .flags = CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X, .recalc = &omap2_fixed_divisor_recalc, }; @@ -1641,10 +1645,10 @@ static struct clk ssi_sst_fck = { */ static struct clk core_l3_ick = { .name = "core_l3_ick", + .ops = &clkops_null, .parent = &l3_ick, .init = &omap2_init_clk_clkdm, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .clkdm_name = "core_l3_clkdm", .recalc = &followparent_recalc, }; @@ -1671,9 +1675,9 @@ static struct clk sdrc_ick = { static struct clk gpmc_fck = { .name = "gpmc_fck", + .ops = &clkops_null, .parent = &core_l3_ick, - .flags = CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK | - ENABLE_ON_INIT, + .flags = CLOCK_IN_OMAP343X | ENABLE_ON_INIT, /* huh? */ .clkdm_name = "core_l3_clkdm", .recalc = &followparent_recalc, }; @@ -1682,9 +1686,9 @@ static struct clk gpmc_fck = { static struct clk security_l3_ick = { .name = "security_l3_ick", + .ops = &clkops_null, .parent = &l3_ick, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &followparent_recalc, }; @@ -1701,10 +1705,10 @@ static struct clk pka_ick = { static struct clk core_l4_ick = { .name = "core_l4_ick", + .ops = &clkops_null, .parent = &l4_ick, .init = &omap2_init_clk_clkdm, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1984,9 +1988,9 @@ static struct clk omapctrl_ick = { static struct clk ssi_l4_ick = { .name = "ssi_l4_ick", + .ops = &clkops_null, .parent = &l4_ick, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -2028,9 +2032,9 @@ static struct clk usb_l4_ick = { static struct clk security_l4_ick2 = { .name = "security_l4_ick2", + .ops = &clkops_null, .parent = &l4_ick, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .recalc = &followparent_recalc, }; @@ -2387,20 +2391,20 @@ static struct clk gpt1_ick = { static struct clk per_96m_fck = { .name = "per_96m_fck", + .ops = &clkops_null, .parent = &omap_96m_alwon_fck, .init = &omap2_init_clk_clkdm, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; static struct clk per_48m_fck = { .name = "per_48m_fck", + .ops = &clkops_null, .parent = &omap_48m_fck, .init = &omap2_init_clk_clkdm, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2590,9 +2594,9 @@ static struct clk wdt3_fck = { static struct clk per_l4_ick = { .name = "per_l4_ick", + .ops = &clkops_null, .parent = &l4_ick, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | - PARENT_CONTROLS_CLOCK, + .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index c1e484463ed..40a2ac353de 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -148,7 +148,6 @@ extern const struct clkops clkops_null; #define CLOCK_IN_OMAP242X (1 << 25) #define CLOCK_IN_OMAP243X (1 << 26) #define CLOCK_IN_OMAP343X (1 << 27) /* clocks common to all 343X */ -#define PARENT_CONTROLS_CLOCK (1 << 28) #define CLOCK_IN_OMAP3430ES1 (1 << 29) /* 3430ES1 clocks only */ #define CLOCK_IN_OMAP3430ES2 (1 << 30) /* 3430ES2 clocks only */ -- GitLab From b36ee724208358bd892ad279efce629740517149 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 4 Nov 2008 17:59:52 +0000 Subject: [PATCH 1332/4982] [ARM] omap: add default .ops to all remaining OMAP2 clocks Signed-off-by: Russell King --- arch/arm/mach-omap2/clock.c | 35 +++++---- arch/arm/mach-omap2/clock.h | 2 + arch/arm/mach-omap2/clock24xx.h | 115 +++++++++++++++++++++++++++ arch/arm/mach-omap2/clock34xx.h | 133 ++++++++++++++++++++++++++++++++ 4 files changed, 271 insertions(+), 14 deletions(-) diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 21fbe29810a..8c09711d2ea 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -264,16 +264,10 @@ static void omap2_clk_wait_ready(struct clk *clk) omap2_wait_clock_ready(st_reg, bit, clk->name); } -/* Enables clock without considering parent dependencies or use count - * REVISIT: Maybe change this to use clk->enable like on omap1? - */ -int _omap2_clk_enable(struct clk *clk) +static int omap2_dflt_clk_enable_wait(struct clk *clk) { u32 regval32; - if (clk->ops && clk->ops->enable) - return clk->ops->enable(clk); - if (unlikely(clk->enable_reg == NULL)) { printk(KERN_ERR "clock.c: Enable for %s without enable code\n", clk->name); @@ -293,16 +287,10 @@ int _omap2_clk_enable(struct clk *clk) return 0; } -/* Disables clock without considering parent dependencies or use count */ -void _omap2_clk_disable(struct clk *clk) +static void omap2_dflt_clk_disable(struct clk *clk) { u32 regval32; - if (clk->ops && clk->ops->disable) { - clk->ops->disable(clk); - return; - } - if (clk->enable_reg == NULL) { /* * 'Independent' here refers to a clock which is not @@ -322,6 +310,25 @@ void _omap2_clk_disable(struct clk *clk) wmb(); } +const struct clkops clkops_omap2_dflt_wait = { + .enable = omap2_dflt_clk_enable_wait, + .disable = omap2_dflt_clk_disable, +}; + +/* Enables clock without considering parent dependencies or use count + * REVISIT: Maybe change this to use clk->enable like on omap1? + */ +static int _omap2_clk_enable(struct clk *clk) +{ + return clk->ops->enable(clk); +} + +/* Disables clock without considering parent dependencies or use count */ +static void _omap2_clk_disable(struct clk *clk) +{ + clk->ops->disable(clk); +} + void omap2_clk_disable(struct clk *clk) { if (clk->usecount > 0 && !(--clk->usecount)) { diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 1fb330e0847..d4bdb59b300 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -51,6 +51,8 @@ u32 omap2_get_dpll_rate(struct clk *clk); int omap2_wait_clock_ready(void __iomem *reg, u32 cval, const char *name); void omap2_clk_prepare_for_reboot(void); +extern const struct clkops clkops_omap2_dflt_wait; + extern u8 cpu_mask; /* clksel_rate data common to 24xx/343x */ diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h index adc00e1064a..b59bf902ce7 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock24xx.h @@ -890,6 +890,7 @@ static const struct clksel common_clkout_src_clksel[] = { static struct clk sys_clkout_src = { .name = "sys_clkout_src", + .ops = &clkops_omap2_dflt_wait, .parent = &func_54m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_PROPAGATES, @@ -936,6 +937,7 @@ static struct clk sys_clkout = { /* In 2430, new in 2420 ES2 */ static struct clk sys_clkout2_src = { .name = "sys_clkout2_src", + .ops = &clkops_omap2_dflt_wait, .parent = &func_54m_ck, .flags = CLOCK_IN_OMAP242X | RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", @@ -972,6 +974,7 @@ static struct clk sys_clkout2 = { static struct clk emul_ck = { .name = "emul_ck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_54m_ck, .flags = CLOCK_IN_OMAP242X, .clkdm_name = "wkup_clkdm", @@ -1051,6 +1054,7 @@ static const struct clksel dsp_fck_clksel[] = { static struct clk dsp_fck = { .name = "dsp_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &core_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP | CONFIG_PARTICIPANT | RATE_PROPAGATES, @@ -1096,6 +1100,7 @@ static struct clk dsp_irate_ick = { /* 2420 only */ static struct clk dsp_ick = { .name = "dsp_ick", /* apparently ipi and isp */ + .ops = &clkops_omap2_dflt_wait, .parent = &dsp_irate_ick, .flags = CLOCK_IN_OMAP242X | DELAYED_APP | CONFIG_PARTICIPANT, .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_ICLKEN), @@ -1105,6 +1110,7 @@ static struct clk dsp_ick = { /* 2430 only - EN_DSP controls both dsp fclk and iclk on 2430 */ static struct clk iva2_1_ick = { .name = "iva2_1_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &dsp_irate_ick, .flags = CLOCK_IN_OMAP243X | DELAYED_APP | CONFIG_PARTICIPANT, .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN), @@ -1118,6 +1124,7 @@ static struct clk iva2_1_ick = { */ static struct clk iva1_ifck = { .name = "iva1_ifck", + .ops = &clkops_omap2_dflt_wait, .parent = &core_ck, .flags = CLOCK_IN_OMAP242X | CONFIG_PARTICIPANT | RATE_PROPAGATES | DELAYED_APP, @@ -1135,6 +1142,7 @@ static struct clk iva1_ifck = { /* IVA1 mpu/int/i/f clocks are /2 of parent */ static struct clk iva1_mpu_int_ifck = { .name = "iva1_mpu_int_ifck", + .ops = &clkops_omap2_dflt_wait, .parent = &iva1_ifck, .flags = CLOCK_IN_OMAP242X, .clkdm_name = "iva1_clkdm", @@ -1211,6 +1219,7 @@ static const struct clksel usb_l4_ick_clksel[] = { /* It is unclear from TRM whether usb_l4_ick is really in L3 or L4 clkdm */ static struct clk usb_l4_ick = { /* FS-USB interface clock */ .name = "usb_l4_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &core_l3_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP | CONFIG_PARTICIPANT, @@ -1284,6 +1293,7 @@ static const struct clksel ssi_ssr_sst_fck_clksel[] = { static struct clk ssi_ssr_sst_fck = { .name = "ssi_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &core_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP, @@ -1320,6 +1330,7 @@ static const struct clksel gfx_fck_clksel[] = { static struct clk gfx_3d_fck = { .name = "gfx_3d_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &core_l3_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "gfx_clkdm", @@ -1335,6 +1346,7 @@ static struct clk gfx_3d_fck = { static struct clk gfx_2d_fck = { .name = "gfx_2d_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &core_l3_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "gfx_clkdm", @@ -1350,6 +1362,7 @@ static struct clk gfx_2d_fck = { static struct clk gfx_ick = { .name = "gfx_ick", /* From l3 */ + .ops = &clkops_omap2_dflt_wait, .parent = &core_l3_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "gfx_clkdm", @@ -1380,6 +1393,7 @@ static const struct clksel mdm_ick_clksel[] = { static struct clk mdm_ick = { /* used both as a ick and fck */ .name = "mdm_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &core_ck, .flags = CLOCK_IN_OMAP243X | DELAYED_APP | CONFIG_PARTICIPANT, .clkdm_name = "mdm_clkdm", @@ -1395,6 +1409,7 @@ static struct clk mdm_ick = { /* used both as a ick and fck */ static struct clk mdm_osc_ck = { .name = "mdm_osc_ck", + .ops = &clkops_omap2_dflt_wait, .parent = &osc_ck, .flags = CLOCK_IN_OMAP243X, .clkdm_name = "mdm_clkdm", @@ -1440,6 +1455,7 @@ static const struct clksel dss1_fck_clksel[] = { static struct clk dss_ick = { /* Enables both L3,L4 ICLK's */ .name = "dss_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, /* really both l3 and l4 */ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "dss_clkdm", @@ -1450,6 +1466,7 @@ static struct clk dss_ick = { /* Enables both L3,L4 ICLK's */ static struct clk dss1_fck = { .name = "dss1_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &core_ck, /* Core or sys */ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP, @@ -1483,6 +1500,7 @@ static const struct clksel dss2_fck_clksel[] = { static struct clk dss2_fck = { /* Alt clk used in power management */ .name = "dss2_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &sys_ck, /* fixed at sys_ck or 48MHz */ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP, @@ -1498,6 +1516,7 @@ static struct clk dss2_fck = { /* Alt clk used in power management */ static struct clk dss_54m_fck = { /* Alt clk used in power management */ .name = "dss_54m_fck", /* 54m tv clk */ + .ops = &clkops_omap2_dflt_wait, .parent = &func_54m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "dss_clkdm", @@ -1526,6 +1545,7 @@ static const struct clksel omap24xx_gpt_clksel[] = { static struct clk gpt1_ick = { .name = "gpt1_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -1536,6 +1556,7 @@ static struct clk gpt1_ick = { static struct clk gpt1_fck = { .name = "gpt1_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -1552,6 +1573,7 @@ static struct clk gpt1_fck = { static struct clk gpt2_ick = { .name = "gpt2_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -1562,6 +1584,7 @@ static struct clk gpt2_ick = { static struct clk gpt2_fck = { .name = "gpt2_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -1576,6 +1599,7 @@ static struct clk gpt2_fck = { static struct clk gpt3_ick = { .name = "gpt3_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -1586,6 +1610,7 @@ static struct clk gpt3_ick = { static struct clk gpt3_fck = { .name = "gpt3_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -1600,6 +1625,7 @@ static struct clk gpt3_fck = { static struct clk gpt4_ick = { .name = "gpt4_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -1610,6 +1636,7 @@ static struct clk gpt4_ick = { static struct clk gpt4_fck = { .name = "gpt4_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -1624,6 +1651,7 @@ static struct clk gpt4_fck = { static struct clk gpt5_ick = { .name = "gpt5_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -1634,6 +1662,7 @@ static struct clk gpt5_ick = { static struct clk gpt5_fck = { .name = "gpt5_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -1648,6 +1677,7 @@ static struct clk gpt5_fck = { static struct clk gpt6_ick = { .name = "gpt6_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -1658,6 +1688,7 @@ static struct clk gpt6_ick = { static struct clk gpt6_fck = { .name = "gpt6_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -1672,6 +1703,7 @@ static struct clk gpt6_fck = { static struct clk gpt7_ick = { .name = "gpt7_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1681,6 +1713,7 @@ static struct clk gpt7_ick = { static struct clk gpt7_fck = { .name = "gpt7_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -1695,6 +1728,7 @@ static struct clk gpt7_fck = { static struct clk gpt8_ick = { .name = "gpt8_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -1705,6 +1739,7 @@ static struct clk gpt8_ick = { static struct clk gpt8_fck = { .name = "gpt8_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -1719,6 +1754,7 @@ static struct clk gpt8_fck = { static struct clk gpt9_ick = { .name = "gpt9_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -1729,6 +1765,7 @@ static struct clk gpt9_ick = { static struct clk gpt9_fck = { .name = "gpt9_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -1743,6 +1780,7 @@ static struct clk gpt9_fck = { static struct clk gpt10_ick = { .name = "gpt10_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -1753,6 +1791,7 @@ static struct clk gpt10_ick = { static struct clk gpt10_fck = { .name = "gpt10_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -1767,6 +1806,7 @@ static struct clk gpt10_fck = { static struct clk gpt11_ick = { .name = "gpt11_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -1777,6 +1817,7 @@ static struct clk gpt11_ick = { static struct clk gpt11_fck = { .name = "gpt11_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -1791,6 +1832,7 @@ static struct clk gpt11_fck = { static struct clk gpt12_ick = { .name = "gpt12_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -1801,6 +1843,7 @@ static struct clk gpt12_ick = { static struct clk gpt12_fck = { .name = "gpt12_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -1815,6 +1858,7 @@ static struct clk gpt12_fck = { static struct clk mcbsp1_ick = { .name = "mcbsp_ick", + .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, @@ -1826,6 +1870,7 @@ static struct clk mcbsp1_ick = { static struct clk mcbsp1_fck = { .name = "mcbsp_fck", + .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, @@ -1837,6 +1882,7 @@ static struct clk mcbsp1_fck = { static struct clk mcbsp2_ick = { .name = "mcbsp_ick", + .ops = &clkops_omap2_dflt_wait, .id = 2, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, @@ -1848,6 +1894,7 @@ static struct clk mcbsp2_ick = { static struct clk mcbsp2_fck = { .name = "mcbsp_fck", + .ops = &clkops_omap2_dflt_wait, .id = 2, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, @@ -1859,6 +1906,7 @@ static struct clk mcbsp2_fck = { static struct clk mcbsp3_ick = { .name = "mcbsp_ick", + .ops = &clkops_omap2_dflt_wait, .id = 3, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X, @@ -1870,6 +1918,7 @@ static struct clk mcbsp3_ick = { static struct clk mcbsp3_fck = { .name = "mcbsp_fck", + .ops = &clkops_omap2_dflt_wait, .id = 3, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP243X, @@ -1881,6 +1930,7 @@ static struct clk mcbsp3_fck = { static struct clk mcbsp4_ick = { .name = "mcbsp_ick", + .ops = &clkops_omap2_dflt_wait, .id = 4, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X, @@ -1892,6 +1942,7 @@ static struct clk mcbsp4_ick = { static struct clk mcbsp4_fck = { .name = "mcbsp_fck", + .ops = &clkops_omap2_dflt_wait, .id = 4, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP243X, @@ -1903,6 +1954,7 @@ static struct clk mcbsp4_fck = { static struct clk mcbsp5_ick = { .name = "mcbsp_ick", + .ops = &clkops_omap2_dflt_wait, .id = 5, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X, @@ -1914,6 +1966,7 @@ static struct clk mcbsp5_ick = { static struct clk mcbsp5_fck = { .name = "mcbsp_fck", + .ops = &clkops_omap2_dflt_wait, .id = 5, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP243X, @@ -1925,6 +1978,7 @@ static struct clk mcbsp5_fck = { static struct clk mcspi1_ick = { .name = "mcspi_ick", + .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", @@ -1936,6 +1990,7 @@ static struct clk mcspi1_ick = { static struct clk mcspi1_fck = { .name = "mcspi_fck", + .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &func_48m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, @@ -1947,6 +2002,7 @@ static struct clk mcspi1_fck = { static struct clk mcspi2_ick = { .name = "mcspi_ick", + .ops = &clkops_omap2_dflt_wait, .id = 2, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, @@ -1958,6 +2014,7 @@ static struct clk mcspi2_ick = { static struct clk mcspi2_fck = { .name = "mcspi_fck", + .ops = &clkops_omap2_dflt_wait, .id = 2, .parent = &func_48m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, @@ -1969,6 +2026,7 @@ static struct clk mcspi2_fck = { static struct clk mcspi3_ick = { .name = "mcspi_ick", + .ops = &clkops_omap2_dflt_wait, .id = 3, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X, @@ -1980,6 +2038,7 @@ static struct clk mcspi3_ick = { static struct clk mcspi3_fck = { .name = "mcspi_fck", + .ops = &clkops_omap2_dflt_wait, .id = 3, .parent = &func_48m_ck, .flags = CLOCK_IN_OMAP243X, @@ -1991,6 +2050,7 @@ static struct clk mcspi3_fck = { static struct clk uart1_ick = { .name = "uart1_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2001,6 +2061,7 @@ static struct clk uart1_ick = { static struct clk uart1_fck = { .name = "uart1_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_48m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2011,6 +2072,7 @@ static struct clk uart1_fck = { static struct clk uart2_ick = { .name = "uart2_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2021,6 +2083,7 @@ static struct clk uart2_ick = { static struct clk uart2_fck = { .name = "uart2_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_48m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2031,6 +2094,7 @@ static struct clk uart2_fck = { static struct clk uart3_ick = { .name = "uart3_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2041,6 +2105,7 @@ static struct clk uart3_ick = { static struct clk uart3_fck = { .name = "uart3_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_48m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2051,6 +2116,7 @@ static struct clk uart3_fck = { static struct clk gpios_ick = { .name = "gpios_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2061,6 +2127,7 @@ static struct clk gpios_ick = { static struct clk gpios_fck = { .name = "gpios_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "wkup_clkdm", @@ -2071,6 +2138,7 @@ static struct clk gpios_fck = { static struct clk mpu_wdt_ick = { .name = "mpu_wdt_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2081,6 +2149,7 @@ static struct clk mpu_wdt_ick = { static struct clk mpu_wdt_fck = { .name = "mpu_wdt_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "wkup_clkdm", @@ -2091,6 +2160,7 @@ static struct clk mpu_wdt_fck = { static struct clk sync_32k_ick = { .name = "sync_32k_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ENABLE_ON_INIT, @@ -2102,6 +2172,7 @@ static struct clk sync_32k_ick = { static struct clk wdt1_ick = { .name = "wdt1_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2112,6 +2183,7 @@ static struct clk wdt1_ick = { static struct clk omapctrl_ick = { .name = "omapctrl_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ENABLE_ON_INIT, @@ -2123,6 +2195,7 @@ static struct clk omapctrl_ick = { static struct clk icr_ick = { .name = "icr_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2133,6 +2206,7 @@ static struct clk icr_ick = { static struct clk cam_ick = { .name = "cam_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2148,6 +2222,7 @@ static struct clk cam_ick = { */ static struct clk cam_fck = { .name = "cam_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l3_clkdm", @@ -2158,6 +2233,7 @@ static struct clk cam_fck = { static struct clk mailboxes_ick = { .name = "mailboxes_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2168,6 +2244,7 @@ static struct clk mailboxes_ick = { static struct clk wdt4_ick = { .name = "wdt4_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2178,6 +2255,7 @@ static struct clk wdt4_ick = { static struct clk wdt4_fck = { .name = "wdt4_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2188,6 +2266,7 @@ static struct clk wdt4_fck = { static struct clk wdt3_ick = { .name = "wdt3_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", @@ -2198,6 +2277,7 @@ static struct clk wdt3_ick = { static struct clk wdt3_fck = { .name = "wdt3_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", @@ -2208,6 +2288,7 @@ static struct clk wdt3_fck = { static struct clk mspro_ick = { .name = "mspro_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2218,6 +2299,7 @@ static struct clk mspro_ick = { static struct clk mspro_fck = { .name = "mspro_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2228,6 +2310,7 @@ static struct clk mspro_fck = { static struct clk mmc_ick = { .name = "mmc_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", @@ -2238,6 +2321,7 @@ static struct clk mmc_ick = { static struct clk mmc_fck = { .name = "mmc_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", @@ -2248,6 +2332,7 @@ static struct clk mmc_fck = { static struct clk fac_ick = { .name = "fac_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2258,6 +2343,7 @@ static struct clk fac_ick = { static struct clk fac_fck = { .name = "fac_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_12m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2268,6 +2354,7 @@ static struct clk fac_fck = { static struct clk eac_ick = { .name = "eac_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", @@ -2278,6 +2365,7 @@ static struct clk eac_ick = { static struct clk eac_fck = { .name = "eac_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", @@ -2288,6 +2376,7 @@ static struct clk eac_fck = { static struct clk hdq_ick = { .name = "hdq_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2298,6 +2387,7 @@ static struct clk hdq_ick = { static struct clk hdq_fck = { .name = "hdq_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_12m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2308,6 +2398,7 @@ static struct clk hdq_fck = { static struct clk i2c2_ick = { .name = "i2c_ick", + .ops = &clkops_omap2_dflt_wait, .id = 2, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, @@ -2319,6 +2410,7 @@ static struct clk i2c2_ick = { static struct clk i2c2_fck = { .name = "i2c_fck", + .ops = &clkops_omap2_dflt_wait, .id = 2, .parent = &func_12m_ck, .flags = CLOCK_IN_OMAP242X, @@ -2330,6 +2422,7 @@ static struct clk i2c2_fck = { static struct clk i2chs2_fck = { .name = "i2c_fck", + .ops = &clkops_omap2_dflt_wait, .id = 2, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP243X, @@ -2341,6 +2434,7 @@ static struct clk i2chs2_fck = { static struct clk i2c1_ick = { .name = "i2c_ick", + .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, @@ -2352,6 +2446,7 @@ static struct clk i2c1_ick = { static struct clk i2c1_fck = { .name = "i2c_fck", + .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &func_12m_ck, .flags = CLOCK_IN_OMAP242X, @@ -2363,6 +2458,7 @@ static struct clk i2c1_fck = { static struct clk i2chs1_fck = { .name = "i2c_fck", + .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP243X, @@ -2402,6 +2498,7 @@ static struct clk sdma_ick = { static struct clk vlynq_ick = { .name = "vlynq_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &core_l3_ck, .flags = CLOCK_IN_OMAP242X, .clkdm_name = "core_l3_clkdm", @@ -2437,6 +2534,7 @@ static const struct clksel vlynq_fck_clksel[] = { static struct clk vlynq_fck = { .name = "vlynq_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP242X | DELAYED_APP, .clkdm_name = "core_l3_clkdm", @@ -2453,6 +2551,7 @@ static struct clk vlynq_fck = { static struct clk sdrc_ick = { .name = "sdrc_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X | ENABLE_ON_INIT, .clkdm_name = "core_l4_clkdm", @@ -2463,6 +2562,7 @@ static struct clk sdrc_ick = { static struct clk des_ick = { .name = "des_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", @@ -2473,6 +2573,7 @@ static struct clk des_ick = { static struct clk sha_ick = { .name = "sha_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", @@ -2483,6 +2584,7 @@ static struct clk sha_ick = { static struct clk rng_ick = { .name = "rng_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", @@ -2493,6 +2595,7 @@ static struct clk rng_ick = { static struct clk aes_ick = { .name = "aes_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", @@ -2503,6 +2606,7 @@ static struct clk aes_ick = { static struct clk pka_ick = { .name = "pka_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", @@ -2513,6 +2617,7 @@ static struct clk pka_ick = { static struct clk usb_fck = { .name = "usb_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_48m_ck, .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, .clkdm_name = "core_l3_clkdm", @@ -2523,6 +2628,7 @@ static struct clk usb_fck = { static struct clk usbhs_ick = { .name = "usbhs_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &core_l3_ck, .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l3_clkdm", @@ -2533,6 +2639,7 @@ static struct clk usbhs_ick = { static struct clk mmchs1_ick = { .name = "mmchs_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2543,6 +2650,7 @@ static struct clk mmchs1_ick = { static struct clk mmchs1_fck = { .name = "mmchs_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l3_clkdm", @@ -2553,6 +2661,7 @@ static struct clk mmchs1_fck = { static struct clk mmchs2_ick = { .name = "mmchs_ick", + .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X, @@ -2564,6 +2673,7 @@ static struct clk mmchs2_ick = { static struct clk mmchs2_fck = { .name = "mmchs_fck", + .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP243X, @@ -2574,6 +2684,7 @@ static struct clk mmchs2_fck = { static struct clk gpio5_ick = { .name = "gpio5_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2584,6 +2695,7 @@ static struct clk gpio5_ick = { static struct clk gpio5_fck = { .name = "gpio5_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2594,6 +2706,7 @@ static struct clk gpio5_fck = { static struct clk mdm_intc_ick = { .name = "mdm_intc_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2604,6 +2717,7 @@ static struct clk mdm_intc_ick = { static struct clk mmchsdb1_fck = { .name = "mmchsdb_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2614,6 +2728,7 @@ static struct clk mmchsdb1_fck = { static struct clk mmchsdb2_fck = { .name = "mmchsdb_fck", + .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP243X, diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index 203e2bd3b3b..0d6a11ca132 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -216,6 +216,7 @@ static struct clk mcbsp_clks = { static struct clk sys_clkout1 = { .name = "sys_clkout1", + .ops = &clkops_omap2_dflt_wait, .parent = &osc_sys_ck, .enable_reg = OMAP3430_PRM_CLKOUT_CTRL, .enable_bit = OMAP3430_CLKOUT_EN_SHIFT, @@ -535,6 +536,7 @@ static struct clk dpll3_m3_ck = { /* The PWRDN bit is apparently only available on 3430ES2 and above */ static struct clk dpll3_m3x2_ck = { .name = "dpll3_m3x2_ck", + .ops = &clkops_omap2_dflt_wait, .parent = &dpll3_m3_ck, .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP3430_PWRDN_EMU_CORE_SHIFT, @@ -626,6 +628,7 @@ static struct clk dpll4_m2_ck = { /* The PWRDN bit is apparently only available on 3430ES2 and above */ static struct clk dpll4_m2x2_ck = { .name = "dpll4_m2x2_ck", + .ops = &clkops_omap2_dflt_wait, .parent = &dpll4_m2_ck, .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP3430_PWRDN_96M_SHIFT, @@ -693,6 +696,7 @@ static struct clk dpll4_m3_ck = { /* The PWRDN bit is apparently only available on 3430ES2 and above */ static struct clk dpll4_m3x2_ck = { .name = "dpll4_m3x2_ck", + .ops = &clkops_omap2_dflt_wait, .parent = &dpll4_m3_ck, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), @@ -798,6 +802,7 @@ static struct clk dpll4_m4_ck = { /* The PWRDN bit is apparently only available on 3430ES2 and above */ static struct clk dpll4_m4x2_ck = { .name = "dpll4_m4x2_ck", + .ops = &clkops_omap2_dflt_wait, .parent = &dpll4_m4_ck, .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP3430_PWRDN_CAM_SHIFT, @@ -821,6 +826,7 @@ static struct clk dpll4_m5_ck = { /* The PWRDN bit is apparently only available on 3430ES2 and above */ static struct clk dpll4_m5x2_ck = { .name = "dpll4_m5x2_ck", + .ops = &clkops_omap2_dflt_wait, .parent = &dpll4_m5_ck, .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP3430_PWRDN_CAM_SHIFT, @@ -844,6 +850,7 @@ static struct clk dpll4_m6_ck = { /* The PWRDN bit is apparently only available on 3430ES2 and above */ static struct clk dpll4_m6x2_ck = { .name = "dpll4_m6x2_ck", + .ops = &clkops_omap2_dflt_wait, .parent = &dpll4_m6_ck, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), @@ -960,6 +967,7 @@ static const struct clksel clkout2_src_clksel[] = { static struct clk clkout2_src_ck = { .name = "clkout2_src_ck", + .ops = &clkops_omap2_dflt_wait, .init = &omap2_init_clksel_parent, .enable_reg = OMAP3430_CM_CLKOUT_CTRL, .enable_bit = OMAP3430_CLKOUT2_EN_SHIFT, @@ -1118,6 +1126,7 @@ static const struct clksel iva2_clksel[] = { static struct clk iva2_ck = { .name = "iva2_ck", + .ops = &clkops_omap2_dflt_wait, .parent = &dpll2_m2_ck, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, CM_FCLKEN), @@ -1194,6 +1203,7 @@ static const struct clksel gfx_l3_clksel[] = { /* Virtual parent clock for gfx_l3_ick and gfx_l3_fck */ static struct clk gfx_l3_ck = { .name = "gfx_l3_ck", + .ops = &clkops_omap2_dflt_wait, .parent = &l3_ick, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN), @@ -1226,6 +1236,7 @@ static struct clk gfx_l3_ick = { static struct clk gfx_cg1_ck = { .name = "gfx_cg1_ck", + .ops = &clkops_omap2_dflt_wait, .parent = &gfx_l3_fck, /* REVISIT: correct? */ .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN), @@ -1237,6 +1248,7 @@ static struct clk gfx_cg1_ck = { static struct clk gfx_cg2_ck = { .name = "gfx_cg2_ck", + .ops = &clkops_omap2_dflt_wait, .parent = &gfx_l3_fck, /* REVISIT: correct? */ .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN), @@ -1268,6 +1280,7 @@ static const struct clksel sgx_clksel[] = { static struct clk sgx_fck = { .name = "sgx_fck", + .ops = &clkops_omap2_dflt_wait, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_FCLKEN), .enable_bit = OMAP3430ES2_EN_SGX_SHIFT, @@ -1281,6 +1294,7 @@ static struct clk sgx_fck = { static struct clk sgx_ick = { .name = "sgx_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l3_ick, .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_ICLKEN), @@ -1294,6 +1308,7 @@ static struct clk sgx_ick = { static struct clk d2d_26m_fck = { .name = "d2d_26m_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &sys_ck, .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), @@ -1311,6 +1326,7 @@ static const struct clksel omap343x_gpt_clksel[] = { static struct clk gpt10_fck = { .name = "gpt10_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &sys_ck, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), @@ -1325,6 +1341,7 @@ static struct clk gpt10_fck = { static struct clk gpt11_fck = { .name = "gpt11_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &sys_ck, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), @@ -1339,6 +1356,7 @@ static struct clk gpt11_fck = { static struct clk cpefuse_fck = { .name = "cpefuse_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &sys_ck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3), .enable_bit = OMAP3430ES2_EN_CPEFUSE_SHIFT, @@ -1348,6 +1366,7 @@ static struct clk cpefuse_fck = { static struct clk ts_fck = { .name = "ts_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &omap_32k_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3), .enable_bit = OMAP3430ES2_EN_TS_SHIFT, @@ -1357,6 +1376,7 @@ static struct clk ts_fck = { static struct clk usbtll_fck = { .name = "usbtll_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &omap_120m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3), .enable_bit = OMAP3430ES2_EN_USBTLL_SHIFT, @@ -1377,6 +1397,7 @@ static struct clk core_96m_fck = { static struct clk mmchs3_fck = { .name = "mmchs_fck", + .ops = &clkops_omap2_dflt_wait, .id = 2, .parent = &core_96m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), @@ -1388,6 +1409,7 @@ static struct clk mmchs3_fck = { static struct clk mmchs2_fck = { .name = "mmchs_fck", + .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &core_96m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), @@ -1399,6 +1421,7 @@ static struct clk mmchs2_fck = { static struct clk mspro_fck = { .name = "mspro_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &core_96m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_MSPRO_SHIFT, @@ -1409,6 +1432,7 @@ static struct clk mspro_fck = { static struct clk mmchs1_fck = { .name = "mmchs_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &core_96m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_MMC1_SHIFT, @@ -1419,6 +1443,7 @@ static struct clk mmchs1_fck = { static struct clk i2c3_fck = { .name = "i2c_fck", + .ops = &clkops_omap2_dflt_wait, .id = 3, .parent = &core_96m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), @@ -1430,6 +1455,7 @@ static struct clk i2c3_fck = { static struct clk i2c2_fck = { .name = "i2c_fck", + .ops = &clkops_omap2_dflt_wait, .id = 2, .parent = &core_96m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), @@ -1441,6 +1467,7 @@ static struct clk i2c2_fck = { static struct clk i2c1_fck = { .name = "i2c_fck", + .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &core_96m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), @@ -1472,6 +1499,7 @@ static const struct clksel mcbsp_15_clksel[] = { static struct clk mcbsp5_fck = { .name = "mcbsp_fck", + .ops = &clkops_omap2_dflt_wait, .id = 5, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), @@ -1486,6 +1514,7 @@ static struct clk mcbsp5_fck = { static struct clk mcbsp1_fck = { .name = "mcbsp_fck", + .ops = &clkops_omap2_dflt_wait, .id = 1, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), @@ -1511,6 +1540,7 @@ static struct clk core_48m_fck = { static struct clk mcspi4_fck = { .name = "mcspi_fck", + .ops = &clkops_omap2_dflt_wait, .id = 4, .parent = &core_48m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), @@ -1521,6 +1551,7 @@ static struct clk mcspi4_fck = { static struct clk mcspi3_fck = { .name = "mcspi_fck", + .ops = &clkops_omap2_dflt_wait, .id = 3, .parent = &core_48m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), @@ -1531,6 +1562,7 @@ static struct clk mcspi3_fck = { static struct clk mcspi2_fck = { .name = "mcspi_fck", + .ops = &clkops_omap2_dflt_wait, .id = 2, .parent = &core_48m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), @@ -1541,6 +1573,7 @@ static struct clk mcspi2_fck = { static struct clk mcspi1_fck = { .name = "mcspi_fck", + .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &core_48m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), @@ -1551,6 +1584,7 @@ static struct clk mcspi1_fck = { static struct clk uart2_fck = { .name = "uart2_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &core_48m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_UART2_SHIFT, @@ -1560,6 +1594,7 @@ static struct clk uart2_fck = { static struct clk uart1_fck = { .name = "uart1_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &core_48m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_UART1_SHIFT, @@ -1569,6 +1604,7 @@ static struct clk uart1_fck = { static struct clk fshostusb_fck = { .name = "fshostusb_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &core_48m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430ES1_EN_FSHOSTUSB_SHIFT, @@ -1589,6 +1625,7 @@ static struct clk core_12m_fck = { static struct clk hdq_fck = { .name = "hdq_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &core_12m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_HDQ_SHIFT, @@ -1615,6 +1652,7 @@ static const struct clksel ssi_ssr_clksel[] = { static struct clk ssi_ssr_fck = { .name = "ssi_ssr_fck", + .ops = &clkops_omap2_dflt_wait, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_SSI_SHIFT, @@ -1655,6 +1693,7 @@ static struct clk core_l3_ick = { static struct clk hsotgusb_ick = { .name = "hsotgusb_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &core_l3_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_HSOTGUSB_SHIFT, @@ -1665,6 +1704,7 @@ static struct clk hsotgusb_ick = { static struct clk sdrc_ick = { .name = "sdrc_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &core_l3_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_SDRC_SHIFT, @@ -1694,6 +1734,7 @@ static struct clk security_l3_ick = { static struct clk pka_ick = { .name = "pka_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &security_l3_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP3430_EN_PKA_SHIFT, @@ -1715,6 +1756,7 @@ static struct clk core_l4_ick = { static struct clk usbtll_ick = { .name = "usbtll_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3), .enable_bit = OMAP3430ES2_EN_USBTLL_SHIFT, @@ -1725,6 +1767,7 @@ static struct clk usbtll_ick = { static struct clk mmchs3_ick = { .name = "mmchs_ick", + .ops = &clkops_omap2_dflt_wait, .id = 2, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1737,6 +1780,7 @@ static struct clk mmchs3_ick = { /* Intersystem Communication Registers - chassis mode only */ static struct clk icr_ick = { .name = "icr_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_ICR_SHIFT, @@ -1747,6 +1791,7 @@ static struct clk icr_ick = { static struct clk aes2_ick = { .name = "aes2_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_AES2_SHIFT, @@ -1757,6 +1802,7 @@ static struct clk aes2_ick = { static struct clk sha12_ick = { .name = "sha12_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_SHA12_SHIFT, @@ -1767,6 +1813,7 @@ static struct clk sha12_ick = { static struct clk des2_ick = { .name = "des2_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_DES2_SHIFT, @@ -1777,6 +1824,7 @@ static struct clk des2_ick = { static struct clk mmchs2_ick = { .name = "mmchs_ick", + .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1788,6 +1836,7 @@ static struct clk mmchs2_ick = { static struct clk mmchs1_ick = { .name = "mmchs_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MMC1_SHIFT, @@ -1798,6 +1847,7 @@ static struct clk mmchs1_ick = { static struct clk mspro_ick = { .name = "mspro_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MSPRO_SHIFT, @@ -1808,6 +1858,7 @@ static struct clk mspro_ick = { static struct clk hdq_ick = { .name = "hdq_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_HDQ_SHIFT, @@ -1818,6 +1869,7 @@ static struct clk hdq_ick = { static struct clk mcspi4_ick = { .name = "mcspi_ick", + .ops = &clkops_omap2_dflt_wait, .id = 4, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1829,6 +1881,7 @@ static struct clk mcspi4_ick = { static struct clk mcspi3_ick = { .name = "mcspi_ick", + .ops = &clkops_omap2_dflt_wait, .id = 3, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1840,6 +1893,7 @@ static struct clk mcspi3_ick = { static struct clk mcspi2_ick = { .name = "mcspi_ick", + .ops = &clkops_omap2_dflt_wait, .id = 2, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1851,6 +1905,7 @@ static struct clk mcspi2_ick = { static struct clk mcspi1_ick = { .name = "mcspi_ick", + .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1862,6 +1917,7 @@ static struct clk mcspi1_ick = { static struct clk i2c3_ick = { .name = "i2c_ick", + .ops = &clkops_omap2_dflt_wait, .id = 3, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1873,6 +1929,7 @@ static struct clk i2c3_ick = { static struct clk i2c2_ick = { .name = "i2c_ick", + .ops = &clkops_omap2_dflt_wait, .id = 2, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1884,6 +1941,7 @@ static struct clk i2c2_ick = { static struct clk i2c1_ick = { .name = "i2c_ick", + .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1895,6 +1953,7 @@ static struct clk i2c1_ick = { static struct clk uart2_ick = { .name = "uart2_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_UART2_SHIFT, @@ -1905,6 +1964,7 @@ static struct clk uart2_ick = { static struct clk uart1_ick = { .name = "uart1_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_UART1_SHIFT, @@ -1915,6 +1975,7 @@ static struct clk uart1_ick = { static struct clk gpt11_ick = { .name = "gpt11_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_GPT11_SHIFT, @@ -1925,6 +1986,7 @@ static struct clk gpt11_ick = { static struct clk gpt10_ick = { .name = "gpt10_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_GPT10_SHIFT, @@ -1935,6 +1997,7 @@ static struct clk gpt10_ick = { static struct clk mcbsp5_ick = { .name = "mcbsp_ick", + .ops = &clkops_omap2_dflt_wait, .id = 5, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1946,6 +2009,7 @@ static struct clk mcbsp5_ick = { static struct clk mcbsp1_ick = { .name = "mcbsp_ick", + .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1957,6 +2021,7 @@ static struct clk mcbsp1_ick = { static struct clk fac_ick = { .name = "fac_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430ES1_EN_FAC_SHIFT, @@ -1967,6 +2032,7 @@ static struct clk fac_ick = { static struct clk mailboxes_ick = { .name = "mailboxes_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MAILBOXES_SHIFT, @@ -1977,6 +2043,7 @@ static struct clk mailboxes_ick = { static struct clk omapctrl_ick = { .name = "omapctrl_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_OMAPCTRL_SHIFT, @@ -1997,6 +2064,7 @@ static struct clk ssi_l4_ick = { static struct clk ssi_ick = { .name = "ssi_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &ssi_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_SSI_SHIFT, @@ -2015,6 +2083,7 @@ static const struct clksel usb_l4_clksel[] = { static struct clk usb_l4_ick = { .name = "usb_l4_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ick, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -2040,6 +2109,7 @@ static struct clk security_l4_ick2 = { static struct clk aes1_ick = { .name = "aes1_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &security_l4_ick2, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP3430_EN_AES1_SHIFT, @@ -2049,6 +2119,7 @@ static struct clk aes1_ick = { static struct clk rng_ick = { .name = "rng_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &security_l4_ick2, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP3430_EN_RNG_SHIFT, @@ -2058,6 +2129,7 @@ static struct clk rng_ick = { static struct clk sha11_ick = { .name = "sha11_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &security_l4_ick2, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP3430_EN_SHA11_SHIFT, @@ -2067,6 +2139,7 @@ static struct clk sha11_ick = { static struct clk des1_ick = { .name = "des1_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &security_l4_ick2, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP3430_EN_DES1_SHIFT, @@ -2083,6 +2156,7 @@ static const struct clksel dss1_alwon_fck_clksel[] = { static struct clk dss1_alwon_fck = { .name = "dss1_alwon_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &dpll4_m4x2_ck, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), @@ -2097,6 +2171,7 @@ static struct clk dss1_alwon_fck = { static struct clk dss_tv_fck = { .name = "dss_tv_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &omap_54m_fck, .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), @@ -2108,6 +2183,7 @@ static struct clk dss_tv_fck = { static struct clk dss_96m_fck = { .name = "dss_96m_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &omap_96m_fck, .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), @@ -2119,6 +2195,7 @@ static struct clk dss_96m_fck = { static struct clk dss2_alwon_fck = { .name = "dss2_alwon_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &sys_ck, .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), @@ -2131,6 +2208,7 @@ static struct clk dss2_alwon_fck = { static struct clk dss_ick = { /* Handles both L3 and L4 clocks */ .name = "dss_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ick, .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN), @@ -2150,6 +2228,7 @@ static const struct clksel cam_mclk_clksel[] = { static struct clk cam_mclk = { .name = "cam_mclk", + .ops = &clkops_omap2_dflt_wait, .parent = &dpll4_m5x2_ck, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), @@ -2165,6 +2244,7 @@ static struct clk cam_mclk = { static struct clk cam_ick = { /* Handles both L3 and L4 clocks */ .name = "cam_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ick, .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN), @@ -2178,6 +2258,7 @@ static struct clk cam_ick = { static struct clk usbhost_120m_fck = { .name = "usbhost_120m_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &omap_120m_fck, .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN), @@ -2189,6 +2270,7 @@ static struct clk usbhost_120m_fck = { static struct clk usbhost_48m_fck = { .name = "usbhost_48m_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &omap_48m_fck, .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN), @@ -2201,6 +2283,7 @@ static struct clk usbhost_48m_fck = { static struct clk usbhost_ick = { /* Handles both L3 and L4 clocks */ .name = "usbhost_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &l4_ick, .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN), @@ -2212,6 +2295,7 @@ static struct clk usbhost_ick = { static struct clk usbhost_sar_fck = { .name = "usbhost_sar_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &osc_sys_ck, .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_PRM_REGADDR(OMAP3430ES2_USBHOST_MOD, PM_PWSTCTRL), @@ -2249,6 +2333,7 @@ static const struct clksel usim_clksel[] = { /* 3430ES2 only */ static struct clk usim_fck = { .name = "usim_fck", + .ops = &clkops_omap2_dflt_wait, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), .enable_bit = OMAP3430ES2_EN_USIMOCP_SHIFT, @@ -2262,6 +2347,7 @@ static struct clk usim_fck = { /* XXX should gpt1's clksel have wkup_32k_fck as the 32k opt? */ static struct clk gpt1_fck = { .name = "gpt1_fck", + .ops = &clkops_omap2_dflt_wait, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPT1_SHIFT, @@ -2285,6 +2371,7 @@ static struct clk wkup_32k_fck = { static struct clk gpio1_dbck = { .name = "gpio1_dbck", + .ops = &clkops_omap2_dflt_wait, .parent = &wkup_32k_fck, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO1_SHIFT, @@ -2295,6 +2382,7 @@ static struct clk gpio1_dbck = { static struct clk wdt2_fck = { .name = "wdt2_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &wkup_32k_fck, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_WDT2_SHIFT, @@ -2316,6 +2404,7 @@ static struct clk wkup_l4_ick = { /* Never specifically named in the TRM, so we have to infer a likely name */ static struct clk usim_ick = { .name = "usim_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &wkup_l4_ick, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430ES2_EN_USIMOCP_SHIFT, @@ -2326,6 +2415,7 @@ static struct clk usim_ick = { static struct clk wdt2_ick = { .name = "wdt2_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &wkup_l4_ick, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_WDT2_SHIFT, @@ -2336,6 +2426,7 @@ static struct clk wdt2_ick = { static struct clk wdt1_ick = { .name = "wdt1_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &wkup_l4_ick, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_WDT1_SHIFT, @@ -2346,6 +2437,7 @@ static struct clk wdt1_ick = { static struct clk gpio1_ick = { .name = "gpio1_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &wkup_l4_ick, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO1_SHIFT, @@ -2356,6 +2448,7 @@ static struct clk gpio1_ick = { static struct clk omap_32ksync_ick = { .name = "omap_32ksync_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &wkup_l4_ick, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_32KSYNC_SHIFT, @@ -2367,6 +2460,7 @@ static struct clk omap_32ksync_ick = { /* XXX This clock no longer exists in 3430 TRM rev F */ static struct clk gpt12_ick = { .name = "gpt12_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &wkup_l4_ick, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT12_SHIFT, @@ -2377,6 +2471,7 @@ static struct clk gpt12_ick = { static struct clk gpt1_ick = { .name = "gpt1_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &wkup_l4_ick, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT1_SHIFT, @@ -2411,6 +2506,7 @@ static struct clk per_48m_fck = { static struct clk uart3_fck = { .name = "uart3_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &per_48m_fck, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_UART3_SHIFT, @@ -2421,6 +2517,7 @@ static struct clk uart3_fck = { static struct clk gpt2_fck = { .name = "gpt2_fck", + .ops = &clkops_omap2_dflt_wait, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPT2_SHIFT, @@ -2434,6 +2531,7 @@ static struct clk gpt2_fck = { static struct clk gpt3_fck = { .name = "gpt3_fck", + .ops = &clkops_omap2_dflt_wait, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPT3_SHIFT, @@ -2447,6 +2545,7 @@ static struct clk gpt3_fck = { static struct clk gpt4_fck = { .name = "gpt4_fck", + .ops = &clkops_omap2_dflt_wait, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPT4_SHIFT, @@ -2460,6 +2559,7 @@ static struct clk gpt4_fck = { static struct clk gpt5_fck = { .name = "gpt5_fck", + .ops = &clkops_omap2_dflt_wait, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPT5_SHIFT, @@ -2473,6 +2573,7 @@ static struct clk gpt5_fck = { static struct clk gpt6_fck = { .name = "gpt6_fck", + .ops = &clkops_omap2_dflt_wait, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPT6_SHIFT, @@ -2486,6 +2587,7 @@ static struct clk gpt6_fck = { static struct clk gpt7_fck = { .name = "gpt7_fck", + .ops = &clkops_omap2_dflt_wait, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPT7_SHIFT, @@ -2499,6 +2601,7 @@ static struct clk gpt7_fck = { static struct clk gpt8_fck = { .name = "gpt8_fck", + .ops = &clkops_omap2_dflt_wait, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPT8_SHIFT, @@ -2512,6 +2615,7 @@ static struct clk gpt8_fck = { static struct clk gpt9_fck = { .name = "gpt9_fck", + .ops = &clkops_omap2_dflt_wait, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPT9_SHIFT, @@ -2534,6 +2638,7 @@ static struct clk per_32k_alwon_fck = { static struct clk gpio6_dbck = { .name = "gpio6_dbck", + .ops = &clkops_omap2_dflt_wait, .parent = &per_32k_alwon_fck, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO6_SHIFT, @@ -2544,6 +2649,7 @@ static struct clk gpio6_dbck = { static struct clk gpio5_dbck = { .name = "gpio5_dbck", + .ops = &clkops_omap2_dflt_wait, .parent = &per_32k_alwon_fck, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO5_SHIFT, @@ -2554,6 +2660,7 @@ static struct clk gpio5_dbck = { static struct clk gpio4_dbck = { .name = "gpio4_dbck", + .ops = &clkops_omap2_dflt_wait, .parent = &per_32k_alwon_fck, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO4_SHIFT, @@ -2564,6 +2671,7 @@ static struct clk gpio4_dbck = { static struct clk gpio3_dbck = { .name = "gpio3_dbck", + .ops = &clkops_omap2_dflt_wait, .parent = &per_32k_alwon_fck, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO3_SHIFT, @@ -2574,6 +2682,7 @@ static struct clk gpio3_dbck = { static struct clk gpio2_dbck = { .name = "gpio2_dbck", + .ops = &clkops_omap2_dflt_wait, .parent = &per_32k_alwon_fck, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO2_SHIFT, @@ -2584,6 +2693,7 @@ static struct clk gpio2_dbck = { static struct clk wdt3_fck = { .name = "wdt3_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &per_32k_alwon_fck, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_WDT3_SHIFT, @@ -2603,6 +2713,7 @@ static struct clk per_l4_ick = { static struct clk gpio6_ick = { .name = "gpio6_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO6_SHIFT, @@ -2613,6 +2724,7 @@ static struct clk gpio6_ick = { static struct clk gpio5_ick = { .name = "gpio5_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO5_SHIFT, @@ -2623,6 +2735,7 @@ static struct clk gpio5_ick = { static struct clk gpio4_ick = { .name = "gpio4_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO4_SHIFT, @@ -2633,6 +2746,7 @@ static struct clk gpio4_ick = { static struct clk gpio3_ick = { .name = "gpio3_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO3_SHIFT, @@ -2643,6 +2757,7 @@ static struct clk gpio3_ick = { static struct clk gpio2_ick = { .name = "gpio2_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO2_SHIFT, @@ -2653,6 +2768,7 @@ static struct clk gpio2_ick = { static struct clk wdt3_ick = { .name = "wdt3_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_WDT3_SHIFT, @@ -2663,6 +2779,7 @@ static struct clk wdt3_ick = { static struct clk uart3_ick = { .name = "uart3_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_UART3_SHIFT, @@ -2673,6 +2790,7 @@ static struct clk uart3_ick = { static struct clk gpt9_ick = { .name = "gpt9_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT9_SHIFT, @@ -2683,6 +2801,7 @@ static struct clk gpt9_ick = { static struct clk gpt8_ick = { .name = "gpt8_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT8_SHIFT, @@ -2693,6 +2812,7 @@ static struct clk gpt8_ick = { static struct clk gpt7_ick = { .name = "gpt7_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT7_SHIFT, @@ -2703,6 +2823,7 @@ static struct clk gpt7_ick = { static struct clk gpt6_ick = { .name = "gpt6_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT6_SHIFT, @@ -2713,6 +2834,7 @@ static struct clk gpt6_ick = { static struct clk gpt5_ick = { .name = "gpt5_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT5_SHIFT, @@ -2723,6 +2845,7 @@ static struct clk gpt5_ick = { static struct clk gpt4_ick = { .name = "gpt4_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT4_SHIFT, @@ -2733,6 +2856,7 @@ static struct clk gpt4_ick = { static struct clk gpt3_ick = { .name = "gpt3_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT3_SHIFT, @@ -2743,6 +2867,7 @@ static struct clk gpt3_ick = { static struct clk gpt2_ick = { .name = "gpt2_ick", + .ops = &clkops_omap2_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT2_SHIFT, @@ -2753,6 +2878,7 @@ static struct clk gpt2_ick = { static struct clk mcbsp2_ick = { .name = "mcbsp_ick", + .ops = &clkops_omap2_dflt_wait, .id = 2, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), @@ -2764,6 +2890,7 @@ static struct clk mcbsp2_ick = { static struct clk mcbsp3_ick = { .name = "mcbsp_ick", + .ops = &clkops_omap2_dflt_wait, .id = 3, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), @@ -2775,6 +2902,7 @@ static struct clk mcbsp3_ick = { static struct clk mcbsp4_ick = { .name = "mcbsp_ick", + .ops = &clkops_omap2_dflt_wait, .id = 4, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), @@ -2792,6 +2920,7 @@ static const struct clksel mcbsp_234_clksel[] = { static struct clk mcbsp2_fck = { .name = "mcbsp_fck", + .ops = &clkops_omap2_dflt_wait, .id = 2, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), @@ -2806,6 +2935,7 @@ static struct clk mcbsp2_fck = { static struct clk mcbsp3_fck = { .name = "mcbsp_fck", + .ops = &clkops_omap2_dflt_wait, .id = 3, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), @@ -2820,6 +2950,7 @@ static struct clk mcbsp3_fck = { static struct clk mcbsp4_fck = { .name = "mcbsp_fck", + .ops = &clkops_omap2_dflt_wait, .id = 4, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), @@ -2988,6 +3119,7 @@ static struct clk traceclk_fck = { /* SmartReflex fclk (VDD1) */ static struct clk sr1_fck = { .name = "sr1_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &sys_ck, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_SR1_SHIFT, @@ -2998,6 +3130,7 @@ static struct clk sr1_fck = { /* SmartReflex fclk (VDD2) */ static struct clk sr2_fck = { .name = "sr2_fck", + .ops = &clkops_omap2_dflt_wait, .parent = &sys_ck, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_SR2_SHIFT, -- GitLab From bc51da4ee46d481dc3fbc57ec407594b80e92705 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 4 Nov 2008 18:59:32 +0000 Subject: [PATCH 1333/4982] [ARM] omap: eliminate unnecessary conditionals in omap2_clk_wait_ready Rather than employing run-time tests in omap2_clk_wait_ready() to decide whether we need to wait for the clock to become ready, we can set the .ops appropriately. This change deals with the OMAP24xx and OMAP34xx conditionals only. Signed-off-by: Russell King --- arch/arm/mach-omap2/clock.c | 42 +++++++++++++++++---------------- arch/arm/mach-omap2/clock.h | 1 + arch/arm/mach-omap2/clock24xx.h | 10 ++++---- arch/arm/mach-omap2/clock34xx.h | 14 +++++------ 4 files changed, 35 insertions(+), 32 deletions(-) diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 8c09711d2ea..986c9f58275 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -237,23 +237,6 @@ static void omap2_clk_wait_ready(struct clk *clk) else return; - /* REVISIT: What are the appropriate exclusions for 34XX? */ - /* No check for DSS or cam clocks */ - if (cpu_is_omap24xx() && ((u32)reg & 0x0f) == 0) { /* CM_{F,I}CLKEN1 */ - if (clk->enable_bit == OMAP24XX_EN_DSS2_SHIFT || - clk->enable_bit == OMAP24XX_EN_DSS1_SHIFT || - clk->enable_bit == OMAP24XX_EN_CAM_SHIFT) - return; - } - - /* REVISIT: What are the appropriate exclusions for 34XX? */ - /* OMAP3: ignore DSS-mod clocks */ - if (cpu_is_omap34xx() && - (((u32)reg & ~0xff) == (u32)OMAP_CM_REGADDR(OMAP3430_DSS_MOD, 0) || - ((((u32)reg & ~0xff) == (u32)OMAP_CM_REGADDR(CORE_MOD, 0)) && - clk->enable_bit == OMAP3430_EN_SSI_SHIFT))) - return; - /* Check if both functional and interface clocks * are running. */ bit = 1 << clk->enable_bit; @@ -264,7 +247,7 @@ static void omap2_clk_wait_ready(struct clk *clk) omap2_wait_clock_ready(st_reg, bit, clk->name); } -static int omap2_dflt_clk_enable_wait(struct clk *clk) +static int omap2_dflt_clk_enable(struct clk *clk) { u32 regval32; @@ -282,11 +265,25 @@ static int omap2_dflt_clk_enable_wait(struct clk *clk) __raw_writel(regval32, clk->enable_reg); wmb(); - omap2_clk_wait_ready(clk); - return 0; } +static int omap2_dflt_clk_enable_wait(struct clk *clk) +{ + int ret; + + if (unlikely(clk->enable_reg == NULL)) { + printk(KERN_ERR "clock.c: Enable for %s without enable code\n", + clk->name); + return 0; /* REVISIT: -EINVAL */ + } + + ret = omap2_dflt_clk_enable(clk); + if (ret == 0) + omap2_clk_wait_ready(clk); + return ret; +} + static void omap2_dflt_clk_disable(struct clk *clk) { u32 regval32; @@ -315,6 +312,11 @@ const struct clkops clkops_omap2_dflt_wait = { .disable = omap2_dflt_clk_disable, }; +const struct clkops clkops_omap2_dflt = { + .enable = omap2_dflt_clk_enable, + .disable = omap2_dflt_clk_disable, +}; + /* Enables clock without considering parent dependencies or use count * REVISIT: Maybe change this to use clk->enable like on omap1? */ diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index d4bdb59b300..b0358b659b4 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -52,6 +52,7 @@ int omap2_wait_clock_ready(void __iomem *reg, u32 cval, const char *name); void omap2_clk_prepare_for_reboot(void); extern const struct clkops clkops_omap2_dflt_wait; +extern const struct clkops clkops_omap2_dflt; extern u8 cpu_mask; diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h index b59bf902ce7..d386b3dfaba 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock24xx.h @@ -1455,7 +1455,7 @@ static const struct clksel dss1_fck_clksel[] = { static struct clk dss_ick = { /* Enables both L3,L4 ICLK's */ .name = "dss_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .parent = &l4_ck, /* really both l3 and l4 */ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "dss_clkdm", @@ -1466,7 +1466,7 @@ static struct clk dss_ick = { /* Enables both L3,L4 ICLK's */ static struct clk dss1_fck = { .name = "dss1_fck", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .parent = &core_ck, /* Core or sys */ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP, @@ -1500,7 +1500,7 @@ static const struct clksel dss2_fck_clksel[] = { static struct clk dss2_fck = { /* Alt clk used in power management */ .name = "dss2_fck", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .parent = &sys_ck, /* fixed at sys_ck or 48MHz */ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP, @@ -2206,7 +2206,7 @@ static struct clk icr_ick = { static struct clk cam_ick = { .name = "cam_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", @@ -2222,7 +2222,7 @@ static struct clk cam_ick = { */ static struct clk cam_fck = { .name = "cam_fck", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .parent = &func_96m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l3_clkdm", diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index 0d6a11ca132..1ff05d351b3 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -1652,7 +1652,7 @@ static const struct clksel ssi_ssr_clksel[] = { static struct clk ssi_ssr_fck = { .name = "ssi_ssr_fck", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_SSI_SHIFT, @@ -2064,7 +2064,7 @@ static struct clk ssi_l4_ick = { static struct clk ssi_ick = { .name = "ssi_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .parent = &ssi_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_SSI_SHIFT, @@ -2156,7 +2156,7 @@ static const struct clksel dss1_alwon_fck_clksel[] = { static struct clk dss1_alwon_fck = { .name = "dss1_alwon_fck", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .parent = &dpll4_m4x2_ck, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), @@ -2171,7 +2171,7 @@ static struct clk dss1_alwon_fck = { static struct clk dss_tv_fck = { .name = "dss_tv_fck", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .parent = &omap_54m_fck, .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), @@ -2183,7 +2183,7 @@ static struct clk dss_tv_fck = { static struct clk dss_96m_fck = { .name = "dss_96m_fck", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .parent = &omap_96m_fck, .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), @@ -2195,7 +2195,7 @@ static struct clk dss_96m_fck = { static struct clk dss2_alwon_fck = { .name = "dss2_alwon_fck", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .parent = &sys_ck, .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), @@ -2208,7 +2208,7 @@ static struct clk dss2_alwon_fck = { static struct clk dss_ick = { /* Handles both L3 and L4 clocks */ .name = "dss_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .parent = &l4_ick, .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN), -- GitLab From c1168dc31d8e0688168030ac66341897ed7ca32a Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 4 Nov 2008 21:24:00 +0000 Subject: [PATCH 1334/4982] [ARM] omap: don't use clkops_omap2_dflt_wait for non-ICLK/FCLK clocks The original code in omap2_clk_wait_ready() used to check the low 8 bits to determine whether they were within the FCLKEN or ICLKEN registers. Specifically, the test is satisfied when these offsets are used: CM_FCLKEN, CM_FCLKEN1, CM_CLKEN, OMAP24XX_CM_FCLKEN2, CM_ICLKEN, CM_ICLKEN1, CM_ICLKEN2, CM_ICLKEN3, OMAP24XX_CM_ICLKEN4 OMAP3430_CM_CLKEN_PLL, OMAP3430ES2_CM_CLKEN2 If one of these offsets isn't used, omap2_clk_wait_ready() merely returns without doing anything. So we should use the non-wait clkops version instead and eliminate that conditional. Signed-off-by: Russell King --- arch/arm/mach-omap2/clock.c | 14 ++++++-------- arch/arm/mach-omap2/clock24xx.h | 6 +++--- arch/arm/mach-omap2/clock34xx.h | 12 ++++++------ 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 986c9f58275..76afb7b4482 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -228,14 +228,12 @@ static void omap2_clk_wait_ready(struct clk *clk) * it and pull it into struct clk itself somehow. */ reg = clk->enable_reg; - if ((((u32)reg & 0xff) >= CM_FCLKEN1) && - (((u32)reg & 0xff) <= OMAP24XX_CM_FCLKEN2)) - other_reg = (void __iomem *)(((u32)reg & ~0xf0) | 0x10); /* CM_ICLKEN* */ - else if ((((u32)reg & 0xff) >= CM_ICLKEN1) && - (((u32)reg & 0xff) <= OMAP24XX_CM_ICLKEN4)) - other_reg = (void __iomem *)(((u32)reg & ~0xf0) | 0x00); /* CM_FCLKEN* */ - else - return; + + /* + * Convert CM_ICLKEN* <-> CM_FCLKEN*. This conversion assumes + * it's just a matter of XORing the bits. + */ + other_reg = (void __iomem *)((u32)reg ^ (CM_FCLKEN ^ CM_ICLKEN)); /* Check if both functional and interface clocks * are running. */ diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h index d386b3dfaba..486fd80143e 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock24xx.h @@ -890,7 +890,7 @@ static const struct clksel common_clkout_src_clksel[] = { static struct clk sys_clkout_src = { .name = "sys_clkout_src", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .parent = &func_54m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_PROPAGATES, @@ -937,7 +937,7 @@ static struct clk sys_clkout = { /* In 2430, new in 2420 ES2 */ static struct clk sys_clkout2_src = { .name = "sys_clkout2_src", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .parent = &func_54m_ck, .flags = CLOCK_IN_OMAP242X | RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", @@ -974,7 +974,7 @@ static struct clk sys_clkout2 = { static struct clk emul_ck = { .name = "emul_ck", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .parent = &func_54m_ck, .flags = CLOCK_IN_OMAP242X, .clkdm_name = "wkup_clkdm", diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index 1ff05d351b3..335ef88ada5 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -216,7 +216,7 @@ static struct clk mcbsp_clks = { static struct clk sys_clkout1 = { .name = "sys_clkout1", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .parent = &osc_sys_ck, .enable_reg = OMAP3430_PRM_CLKOUT_CTRL, .enable_bit = OMAP3430_CLKOUT_EN_SHIFT, @@ -967,7 +967,7 @@ static const struct clksel clkout2_src_clksel[] = { static struct clk clkout2_src_ck = { .name = "clkout2_src_ck", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .init = &omap2_init_clksel_parent, .enable_reg = OMAP3430_CM_CLKOUT_CTRL, .enable_bit = OMAP3430_CLKOUT2_EN_SHIFT, @@ -1356,7 +1356,7 @@ static struct clk gpt11_fck = { static struct clk cpefuse_fck = { .name = "cpefuse_fck", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .parent = &sys_ck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3), .enable_bit = OMAP3430ES2_EN_CPEFUSE_SHIFT, @@ -1366,7 +1366,7 @@ static struct clk cpefuse_fck = { static struct clk ts_fck = { .name = "ts_fck", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .parent = &omap_32k_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3), .enable_bit = OMAP3430ES2_EN_TS_SHIFT, @@ -1376,7 +1376,7 @@ static struct clk ts_fck = { static struct clk usbtll_fck = { .name = "usbtll_fck", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .parent = &omap_120m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3), .enable_bit = OMAP3430ES2_EN_USBTLL_SHIFT, @@ -2295,7 +2295,7 @@ static struct clk usbhost_ick = { static struct clk usbhost_sar_fck = { .name = "usbhost_sar_fck", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .parent = &osc_sys_ck, .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_PRM_REGADDR(OMAP3430ES2_USBHOST_MOD, PM_PWSTCTRL), -- GitLab From eee5b19119458cd399ce4deaabea07c8d07159ae Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 4 Nov 2008 21:42:54 +0000 Subject: [PATCH 1335/4982] [ARM] omap: remove clk->owner clk->owner is always NULL, so its existence doesn't serve any useful function other than bloating the kernel by 992 bytes. Remove it. Signed-off-by: Russell King --- arch/arm/plat-omap/clock.c | 7 ++----- arch/arm/plat-omap/include/mach/clock.h | 1 - 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 529c4a9f012..c53205c574d 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -53,15 +53,14 @@ struct clk * clk_get(struct device *dev, const char *id) mutex_lock(&clocks_mutex); list_for_each_entry(p, &clocks, node) { - if (p->id == idno && - strcmp(id, p->name) == 0 && try_module_get(p->owner)) { + if (p->id == idno && strcmp(id, p->name) == 0) { clk = p; goto found; } } list_for_each_entry(p, &clocks, node) { - if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { + if (strcmp(id, p->name) == 0) { clk = p; break; } @@ -148,8 +147,6 @@ EXPORT_SYMBOL(clk_get_rate); void clk_put(struct clk *clk) { - if (clk && !IS_ERR(clk)) - module_put(clk->owner); } EXPORT_SYMBOL(clk_put); diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index 40a2ac353de..547619f8356 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -65,7 +65,6 @@ struct dpll_data { struct clk { struct list_head node; const struct clkops *ops; - struct module *owner; const char *name; int id; struct clk *parent; -- GitLab From ebb8dca2957f3bb79eea8eec0c7d1c8c3fa9a5be Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 4 Nov 2008 21:50:46 +0000 Subject: [PATCH 1336/4982] [ARM] omap: rearrange clock.h structure order ... to eliminate unnecessary padding. We have rather a lot of these structures, so eliminating unnecessary padding results in a saving of 1488 bytes. Signed-off-by: Russell King --- arch/arm/plat-omap/include/mach/clock.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index 547619f8356..6c24835e174 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -25,8 +25,8 @@ struct clkops { #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) struct clksel_rate { - u8 div; u32 val; + u8 div; u8 flags; }; @@ -39,23 +39,23 @@ struct dpll_data { void __iomem *mult_div1_reg; u32 mult_mask; u32 div1_mask; + unsigned int rate_tolerance; + unsigned long last_rounded_rate; u16 last_rounded_m; u8 last_rounded_n; - unsigned long last_rounded_rate; - unsigned int rate_tolerance; - u16 max_multiplier; u8 max_divider; u32 max_tolerance; + u16 max_multiplier; # if defined(CONFIG_ARCH_OMAP3) u8 modes; void __iomem *control_reg; + void __iomem *autoidle_reg; + void __iomem *idlest_reg; u32 enable_mask; + u32 autoidle_mask; u8 auto_recal_bit; u8 recal_en_bit; u8 recal_st_bit; - void __iomem *autoidle_reg; - u32 autoidle_mask; - void __iomem *idlest_reg; u8 idlest_bit; # endif }; @@ -71,12 +71,12 @@ struct clk { unsigned long rate; __u32 flags; void __iomem *enable_reg; - __u8 enable_bit; - __s8 usecount; void (*recalc)(struct clk *); int (*set_rate)(struct clk *, unsigned long); long (*round_rate)(struct clk *, unsigned long); void (*init)(struct clk *); + __u8 enable_bit; + __s8 usecount; #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) u8 fixed_div; void __iomem *clksel_reg; -- GitLab From ae8fce5c3baf84e319269e67823cf337ed9d359a Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 5 Nov 2008 12:54:04 +0000 Subject: [PATCH 1337/4982] [ARM] omap: remove clk_deny_idle and clk_allow_idle Nothing makes any use of these functions, so there's little point in providing them. Signed-off-by: Russell King --- arch/arm/plat-omap/clock.c | 28 ------------------------- arch/arm/plat-omap/include/mach/clock.h | 2 -- arch/arm/plat-omap/include/mach/pm.h | 12 ----------- 3 files changed, 42 deletions(-) diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index c53205c574d..7b040072859 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -316,34 +316,6 @@ void clk_unregister(struct clk *clk) } EXPORT_SYMBOL(clk_unregister); -void clk_deny_idle(struct clk *clk) -{ - unsigned long flags; - - if (clk == NULL || IS_ERR(clk)) - return; - - spin_lock_irqsave(&clockfw_lock, flags); - if (arch_clock->clk_deny_idle) - arch_clock->clk_deny_idle(clk); - spin_unlock_irqrestore(&clockfw_lock, flags); -} -EXPORT_SYMBOL(clk_deny_idle); - -void clk_allow_idle(struct clk *clk) -{ - unsigned long flags; - - if (clk == NULL || IS_ERR(clk)) - return; - - spin_lock_irqsave(&clockfw_lock, flags); - if (arch_clock->clk_allow_idle) - arch_clock->clk_allow_idle(clk); - spin_unlock_irqrestore(&clockfw_lock, flags); -} -EXPORT_SYMBOL(clk_allow_idle); - void clk_enable_init_clocks(void) { struct clk *clkp; diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index 6c24835e174..4831bbdaf01 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -119,8 +119,6 @@ extern void clk_unregister(struct clk *clk); extern void propagate_rate(struct clk *clk); extern void recalculate_root_clocks(void); extern void followparent_recalc(struct clk * clk); -extern void clk_allow_idle(struct clk *clk); -extern void clk_deny_idle(struct clk *clk); extern int clk_get_usecount(struct clk *clk); extern void clk_enable_init_clocks(void); diff --git a/arch/arm/plat-omap/include/mach/pm.h b/arch/arm/plat-omap/include/mach/pm.h index 2a9c27ad4c3..ca81830b4f8 100644 --- a/arch/arm/plat-omap/include/mach/pm.h +++ b/arch/arm/plat-omap/include/mach/pm.h @@ -118,18 +118,6 @@ extern void prevent_idle_sleep(void); extern void allow_idle_sleep(void); -/** - * clk_deny_idle - Prevents the clock from being idled during MPU idle - * @clk: clock signal handle - */ -void clk_deny_idle(struct clk *clk); - -/** - * clk_allow_idle - Counters previous clk_deny_idle - * @clk: clock signal handle - */ -void clk_allow_idle(struct clk *clk); - extern void omap_pm_idle(void); extern void omap_pm_suspend(void); extern void omap730_cpu_suspend(unsigned short, unsigned short); -- GitLab From 2e777bf1f2482be13c2b678744d3497a4f0a0ec2 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 8 Feb 2009 17:49:22 +0000 Subject: [PATCH 1338/4982] [ARM] omap: provide a standard clk_get_parent() implementation which only has to return clk->parent. Signed-off-by: Russell King --- arch/arm/plat-omap/clock.c | 13 +------------ arch/arm/plat-omap/include/mach/clock.h | 1 - 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 7b040072859..ae77e10719f 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -207,18 +207,7 @@ EXPORT_SYMBOL(clk_set_parent); struct clk *clk_get_parent(struct clk *clk) { - unsigned long flags; - struct clk * ret = NULL; - - if (clk == NULL || IS_ERR(clk)) - return ret; - - spin_lock_irqsave(&clockfw_lock, flags); - if (arch_clock->clk_get_parent) - ret = arch_clock->clk_get_parent(clk); - spin_unlock_irqrestore(&clockfw_lock, flags); - - return ret; + return clk->parent; } EXPORT_SYMBOL(clk_get_parent); diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index 4831bbdaf01..06dd38a8a0c 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -102,7 +102,6 @@ struct clk_functions { long (*clk_round_rate)(struct clk *clk, unsigned long rate); int (*clk_set_rate)(struct clk *clk, unsigned long rate); int (*clk_set_parent)(struct clk *clk, struct clk *parent); - struct clk * (*clk_get_parent)(struct clk *clk); void (*clk_allow_idle)(struct clk *clk); void (*clk_deny_idle)(struct clk *clk); void (*clk_disable_unused)(struct clk *clk); -- GitLab From c6af45085211db8720d6b94b3985ce7198d764e3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 13 Nov 2008 13:01:32 +0000 Subject: [PATCH 1339/4982] [ARM] omap: move clock propagation into core omap clock code Move the clock propagation calls for set_parent and set_rate into the core omap clock code, rather than having these calls scattered throughout the OMAP1 and OMAP2 implementations. Signed-off-by: Russell King --- arch/arm/mach-omap1/clock.c | 3 --- arch/arm/mach-omap2/clock.c | 6 ------ arch/arm/plat-omap/clock.c | 6 +++++- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index ff408105ffb..ee1b9f20544 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -628,9 +628,6 @@ static int omap1_clk_set_rate(struct clk *clk, unsigned long rate) ret = 0; } - if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES))) - propagate_rate(clk); - return ret; } diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 76afb7b4482..7a1d56af9e4 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -684,9 +684,6 @@ int omap2_clk_set_rate(struct clk *clk, unsigned long rate) if (clk->set_rate != NULL) ret = clk->set_rate(clk, rate); - if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES))) - propagate_rate(clk); - return ret; } @@ -774,9 +771,6 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) pr_debug("clock: set parent of %s to %s (new rate %ld)\n", clk->name, clk->parent->name, clk->rate); - if (unlikely(clk->flags & RATE_PROPAGATES)) - propagate_rate(clk); - return 0; } diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index ae77e10719f..b7137c560db 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -182,6 +182,8 @@ int clk_set_rate(struct clk *clk, unsigned long rate) spin_lock_irqsave(&clockfw_lock, flags); if (arch_clock->clk_set_rate) ret = arch_clock->clk_set_rate(clk, rate); + if (ret == 0 && (clk->flags & RATE_PROPAGATES)) + propagate_rate(clk); spin_unlock_irqrestore(&clockfw_lock, flags); return ret; @@ -198,7 +200,9 @@ int clk_set_parent(struct clk *clk, struct clk *parent) spin_lock_irqsave(&clockfw_lock, flags); if (arch_clock->clk_set_parent) - ret = arch_clock->clk_set_parent(clk, parent); + ret = arch_clock->clk_set_parent(clk, parent); + if (ret == 0 && (clk->flags & RATE_PROPAGATES)) + propagate_rate(clk); spin_unlock_irqrestore(&clockfw_lock, flags); return ret; -- GitLab From a9e882096317a088087b608d272da7029a6cc8c8 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 13 Nov 2008 13:07:00 +0000 Subject: [PATCH 1340/4982] [ARM] omap: remove unnecessary calls to propagate_rate() We've always called propagate_rate() in the parent function to the .set_rate methods, so there's no point having the .set_rate methods also call this heavy-weight function - it's mere duplication of what's happening elsewhere. Signed-off-by: Russell King --- arch/arm/mach-omap1/clock.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index ee1b9f20544..80a58e9dbba 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -308,7 +308,6 @@ static int omap1_select_table_rate(struct clk * clk, unsigned long rate) omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val); ck_dpll1.rate = ptr->pll_rate; - propagate_rate(&ck_dpll1); return 0; } @@ -333,9 +332,6 @@ static int omap1_clk_set_rate_dsp_domain(struct clk *clk, unsigned long rate) ret = 0; } - if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES))) - propagate_rate(clk); - return ret; } @@ -442,8 +438,6 @@ static int omap1_set_sossi_rate(struct clk *clk, unsigned long rate) omap_writel(l, MOD_CONF_CTRL_1); clk->rate = p_rate / (div + 1); - if (unlikely(clk->flags & RATE_PROPAGATES)) - propagate_rate(clk); return 0; } @@ -787,7 +781,6 @@ int __init omap1_clk_init(void) } } } - propagate_rate(&ck_dpll1); #else /* Find the highest supported frequency and enable it */ if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) { @@ -796,9 +789,9 @@ int __init omap1_clk_init(void) omap_writew(0x2290, DPLL_CTL); omap_writew(cpu_is_omap730() ? 0x3005 : 0x1005, ARM_CKCTL); ck_dpll1.rate = 60000000; - propagate_rate(&ck_dpll1); } #endif + propagate_rate(&ck_dpll1); /* Cache rates for clocks connected to ck_ref (not dpll1) */ propagate_rate(&ck_ref); printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): " -- GitLab From 9a5fedac187f30116013a8420149d4ca11a44f0d Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 13 Nov 2008 13:44:15 +0000 Subject: [PATCH 1341/4982] [ARM] omap: move propagate_rate() calls into generic omap clock code propagate_rate() is recursive, so it makes sense to minimise the amount of stack which is used for each recursion. So, rather than recursing back into it from the ->recalc functions if RATE_PROPAGATES is set, do that test at the higher level. Signed-off-by: Russell King --- arch/arm/mach-omap1/clock.c | 6 ------ arch/arm/mach-omap2/clock.c | 6 ------ arch/arm/mach-omap2/clock24xx.c | 6 ++---- arch/arm/mach-omap2/clock24xx.h | 4 ---- arch/arm/mach-omap2/clock34xx.c | 5 ----- arch/arm/mach-omap2/clock34xx.h | 10 ---------- arch/arm/plat-omap/clock.c | 14 +++++++++----- 7 files changed, 11 insertions(+), 40 deletions(-) diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index 80a58e9dbba..be500014dcb 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -244,9 +244,6 @@ static void omap1_ckctl_recalc(struct clk * clk) if (unlikely(clk->rate == clk->parent->rate / dsor)) return; /* No change, quick exit */ clk->rate = clk->parent->rate / dsor; - - if (unlikely(clk->flags & RATE_PROPAGATES)) - propagate_rate(clk); } static void omap1_ckctl_recalc_dsp_domain(struct clk * clk) @@ -267,9 +264,6 @@ static void omap1_ckctl_recalc_dsp_domain(struct clk * clk) if (unlikely(clk->rate == clk->parent->rate / dsor)) return; /* No change, quick exit */ clk->rate = clk->parent->rate / dsor; - - if (unlikely(clk->flags & RATE_PROPAGATES)) - propagate_rate(clk); } /* MPU virtual clock functions */ diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 7a1d56af9e4..53fda9977d5 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -167,9 +167,6 @@ void omap2_fixed_divisor_recalc(struct clk *clk) WARN_ON(!clk->fixed_div); clk->rate = clk->parent->rate / clk->fixed_div; - - if (clk->flags & RATE_PROPAGATES) - propagate_rate(clk); } /** @@ -392,9 +389,6 @@ void omap2_clksel_recalc(struct clk *clk) clk->rate = clk->parent->rate / div; pr_debug("clock: new clock rate is %ld (div %d)\n", clk->rate, div); - - if (unlikely(clk->flags & RATE_PROPAGATES)) - propagate_rate(clk); } /** diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index 866a618c4d8..3a0a1b8aa0b 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -199,8 +199,6 @@ long omap2_dpllcore_round_rate(unsigned long target_rate) static void omap2_dpllcore_recalc(struct clk *clk) { clk->rate = omap2_get_dpll_rate_24xx(clk); - - propagate_rate(clk); } static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate) @@ -442,13 +440,11 @@ static u32 omap2_get_sysclkdiv(void) static void omap2_osc_clk_recalc(struct clk *clk) { clk->rate = omap2_get_apll_clkin() * omap2_get_sysclkdiv(); - propagate_rate(clk); } static void omap2_sys_clk_recalc(struct clk *clk) { clk->rate = clk->parent->rate / omap2_get_sysclkdiv(); - propagate_rate(clk); } /* @@ -502,7 +498,9 @@ int __init omap2_clk_init(void) clk_init(&omap2_clk_functions); omap2_osc_clk_recalc(&osc_ck); + propagate_rate(&osc_ck); omap2_sys_clk_recalc(&sys_ck); + propagate_rate(&sys_ck); for (clkp = onchip_24xx_clks; clkp < onchip_24xx_clks + ARRAY_SIZE(onchip_24xx_clks); diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h index 486fd80143e..e07dcba4b3e 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock24xx.h @@ -624,7 +624,6 @@ static struct clk func_32k_ck = { .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_FIXED | RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", - .recalc = &propagate_rate, }; /* Typical 12/13MHz in standalone mode, will be 26Mhz in chassis mode */ @@ -655,7 +654,6 @@ static struct clk alt_ck = { /* Typical 54M or 48M, may not exist */ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_FIXED | RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", - .recalc = &propagate_rate, }; /* @@ -702,7 +700,6 @@ static struct clk apll96_ck = { .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP24XX_EN_96M_PLL_SHIFT, - .recalc = &propagate_rate, }; static struct clk apll54_ck = { @@ -715,7 +712,6 @@ static struct clk apll54_ck = { .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP24XX_EN_54M_PLL_SHIFT, - .recalc = &propagate_rate, }; /* diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 2f2d43db2dd..52698fb4fd0 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -57,8 +57,6 @@ static const struct clkops clkops_noncore_dpll_ops; static void omap3_dpll_recalc(struct clk *clk) { clk->rate = omap2_get_dpll_rate(clk); - - propagate_rate(clk); } /* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */ @@ -388,9 +386,6 @@ static void omap3_clkoutx2_recalc(struct clk *clk) clk->rate = clk->parent->rate; else clk->rate = clk->parent->rate * 2; - - if (clk->flags & RATE_PROPAGATES) - propagate_rate(clk); } /* Common clock code */ diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index 335ef88ada5..dcacec84f8c 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -58,7 +58,6 @@ static struct clk omap_32k_fck = { .ops = &clkops_null, .rate = 32768, .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES, - .recalc = &propagate_rate, }; static struct clk secure_32k_fck = { @@ -66,7 +65,6 @@ static struct clk secure_32k_fck = { .ops = &clkops_null, .rate = 32768, .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES, - .recalc = &propagate_rate, }; /* Virtual source clocks for osc_sys_ck */ @@ -75,7 +73,6 @@ static struct clk virt_12m_ck = { .ops = &clkops_null, .rate = 12000000, .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES, - .recalc = &propagate_rate, }; static struct clk virt_13m_ck = { @@ -83,7 +80,6 @@ static struct clk virt_13m_ck = { .ops = &clkops_null, .rate = 13000000, .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES, - .recalc = &propagate_rate, }; static struct clk virt_16_8m_ck = { @@ -91,7 +87,6 @@ static struct clk virt_16_8m_ck = { .ops = &clkops_null, .rate = 16800000, .flags = CLOCK_IN_OMAP3430ES2 | RATE_FIXED | RATE_PROPAGATES, - .recalc = &propagate_rate, }; static struct clk virt_19_2m_ck = { @@ -99,7 +94,6 @@ static struct clk virt_19_2m_ck = { .ops = &clkops_null, .rate = 19200000, .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES, - .recalc = &propagate_rate, }; static struct clk virt_26m_ck = { @@ -107,7 +101,6 @@ static struct clk virt_26m_ck = { .ops = &clkops_null, .rate = 26000000, .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES, - .recalc = &propagate_rate, }; static struct clk virt_38_4m_ck = { @@ -115,7 +108,6 @@ static struct clk virt_38_4m_ck = { .ops = &clkops_null, .rate = 38400000, .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES, - .recalc = &propagate_rate, }; static const struct clksel_rate osc_sys_12m_rates[] = { @@ -201,7 +193,6 @@ static struct clk sys_altclk = { .name = "sys_altclk", .ops = &clkops_null, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, - .recalc = &propagate_rate, }; /* Optional external clock input for some McBSPs */ @@ -209,7 +200,6 @@ static struct clk mcbsp_clks = { .name = "mcbsp_clks", .ops = &clkops_null, .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, - .recalc = &propagate_rate, }; /* PRM EXTERNAL CLOCK OUTPUT */ diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index b7137c560db..df58f5d9a5a 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -246,8 +246,6 @@ void followparent_recalc(struct clk *clk) return; clk->rate = clk->parent->rate; - if (unlikely(clk->flags & RATE_PROPAGATES)) - propagate_rate(clk); } /* Propagate rate to children */ @@ -261,8 +259,10 @@ void propagate_rate(struct clk * tclk) list_for_each_entry(clkp, &clocks, node) { if (likely(clkp->parent != tclk)) continue; - if (likely((u32)clkp->recalc)) + if (clkp->recalc) clkp->recalc(clkp); + if (clkp->flags & RATE_PROPAGATES) + propagate_rate(clkp); } } @@ -278,8 +278,12 @@ void recalculate_root_clocks(void) struct clk *clkp; list_for_each_entry(clkp, &clocks, node) { - if (unlikely(!clkp->parent) && likely((u32)clkp->recalc)) - clkp->recalc(clkp); + if (!clkp->parent) { + if (clkp->recalc) + clkp->recalc(clkp); + if (clkp->flags & RATE_PROPAGATES) + propagate_rate(clkp); + } } } -- GitLab From d5e6072b753041b56236b014ccfd72a0d3177e08 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 8 Feb 2009 16:07:46 +0000 Subject: [PATCH 1342/4982] [ARM] omap: handle RATE_CKCTL via .set_rate/.round_rate methods It makes no sense to have the CKCTL rate selection implemented as a flag and a special exception in the top level set_rate/round_rate methods. Provide CKCTL set_rate/round_rate methods, and use these for where ever RATE_CKCTL is used and they're not already overridden. This allows us to remove the RATE_CKCTL flag. Signed-off-by: Russell King --- arch/arm/mach-omap1/clock.c | 96 ++++++++++++------------- arch/arm/mach-omap1/clock.h | 38 ++++++---- arch/arm/plat-omap/include/mach/clock.h | 2 +- 3 files changed, 72 insertions(+), 64 deletions(-) diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index be500014dcb..6b17da120e5 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -216,9 +216,6 @@ static int calc_dsor_exp(struct clk *clk, unsigned long rate) struct clk * parent; unsigned dsor_exp; - if (unlikely(!(clk->flags & RATE_CKCTL))) - return -EINVAL; - parent = clk->parent; if (unlikely(parent == NULL)) return -EIO; @@ -307,26 +304,52 @@ static int omap1_select_table_rate(struct clk * clk, unsigned long rate) static int omap1_clk_set_rate_dsp_domain(struct clk *clk, unsigned long rate) { - int ret = -EINVAL; - int dsor_exp; - __u16 regval; - - if (clk->flags & RATE_CKCTL) { - dsor_exp = calc_dsor_exp(clk, rate); - if (dsor_exp > 3) - dsor_exp = -EINVAL; - if (dsor_exp < 0) - return dsor_exp; - - regval = __raw_readw(DSP_CKCTL); - regval &= ~(3 << clk->rate_offset); - regval |= dsor_exp << clk->rate_offset; - __raw_writew(regval, DSP_CKCTL); - clk->rate = clk->parent->rate / (1 << dsor_exp); - ret = 0; - } + int dsor_exp; + u16 regval; - return ret; + dsor_exp = calc_dsor_exp(clk, rate); + if (dsor_exp > 3) + dsor_exp = -EINVAL; + if (dsor_exp < 0) + return dsor_exp; + + regval = __raw_readw(DSP_CKCTL); + regval &= ~(3 << clk->rate_offset); + regval |= dsor_exp << clk->rate_offset; + __raw_writew(regval, DSP_CKCTL); + clk->rate = clk->parent->rate / (1 << dsor_exp); + + return 0; +} + +static long omap1_clk_round_rate_ckctl_arm(struct clk *clk, unsigned long rate) +{ + int dsor_exp = calc_dsor_exp(clk, rate); + if (dsor_exp < 0) + return dsor_exp; + if (dsor_exp > 3) + dsor_exp = 3; + return clk->parent->rate / (1 << dsor_exp); +} + +static int omap1_clk_set_rate_ckctl_arm(struct clk *clk, unsigned long rate) +{ + int dsor_exp; + u16 regval; + + dsor_exp = calc_dsor_exp(clk, rate); + if (dsor_exp > 3) + dsor_exp = -EINVAL; + if (dsor_exp < 0) + return dsor_exp; + + regval = omap_readw(ARM_CKCTL); + regval &= ~(3 << clk->rate_offset); + regval |= dsor_exp << clk->rate_offset; + regval = verify_ckctl_value(regval); + omap_writew(regval, ARM_CKCTL); + clk->rate = clk->parent->rate / (1 << dsor_exp); + return 0; } static long omap1_round_to_table_rate(struct clk * clk, unsigned long rate) @@ -572,20 +595,9 @@ static const struct clkops clkops_generic = { static long omap1_clk_round_rate(struct clk *clk, unsigned long rate) { - int dsor_exp; - if (clk->flags & RATE_FIXED) return clk->rate; - if (clk->flags & RATE_CKCTL) { - dsor_exp = calc_dsor_exp(clk, rate); - if (dsor_exp < 0) - return dsor_exp; - if (dsor_exp > 3) - dsor_exp = 3; - return clk->parent->rate / (1 << dsor_exp); - } - if (clk->round_rate != NULL) return clk->round_rate(clk, rate); @@ -595,27 +607,9 @@ static long omap1_clk_round_rate(struct clk *clk, unsigned long rate) static int omap1_clk_set_rate(struct clk *clk, unsigned long rate) { int ret = -EINVAL; - int dsor_exp; - __u16 regval; if (clk->set_rate) ret = clk->set_rate(clk, rate); - else if (clk->flags & RATE_CKCTL) { - dsor_exp = calc_dsor_exp(clk, rate); - if (dsor_exp > 3) - dsor_exp = -EINVAL; - if (dsor_exp < 0) - return dsor_exp; - - regval = omap_readw(ARM_CKCTL); - regval &= ~(3 << clk->rate_offset); - regval |= dsor_exp << clk->rate_offset; - regval = verify_ckctl_value(regval); - omap_writew(regval, ARM_CKCTL); - clk->rate = clk->parent->rate / (1 << dsor_exp); - ret = 0; - } - return ret; } diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h index 8673832d829..aa7b3d604ee 100644 --- a/arch/arm/mach-omap1/clock.h +++ b/arch/arm/mach-omap1/clock.h @@ -27,6 +27,9 @@ static void omap1_init_ext_clk(struct clk * clk); static int omap1_select_table_rate(struct clk * clk, unsigned long rate); static long omap1_round_to_table_rate(struct clk * clk, unsigned long rate); +static int omap1_clk_set_rate_ckctl_arm(struct clk *clk, unsigned long rate); +static long omap1_clk_round_rate_ckctl_arm(struct clk *clk, unsigned long rate); + struct mpu_rate { unsigned long rate; unsigned long xtal; @@ -189,9 +192,11 @@ static struct clk arm_ck = { .ops = &clkops_null, .parent = &ck_dpll1, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP310 | RATE_CKCTL | RATE_PROPAGATES, + CLOCK_IN_OMAP310 | RATE_PROPAGATES, .rate_offset = CKCTL_ARMDIV_OFFSET, .recalc = &omap1_ckctl_recalc, + .round_rate = omap1_clk_round_rate_ckctl_arm, + .set_rate = omap1_clk_set_rate_ckctl_arm, }; static struct arm_idlect1_clk armper_ck = { @@ -200,12 +205,13 @@ static struct arm_idlect1_clk armper_ck = { .ops = &clkops_generic, .parent = &ck_dpll1, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP310 | RATE_CKCTL | - CLOCK_IDLE_CONTROL, + CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL, .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_PERCK, .rate_offset = CKCTL_PERDIV_OFFSET, .recalc = &omap1_ckctl_recalc, + .round_rate = omap1_clk_round_rate_ckctl_arm, + .set_rate = omap1_clk_set_rate_ckctl_arm, }, .idlect_shift = 2, }; @@ -279,22 +285,24 @@ static struct clk dsp_ck = { .name = "dsp_ck", .ops = &clkops_generic, .parent = &ck_dpll1, - .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - RATE_CKCTL, + .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, .enable_reg = (void __iomem *)ARM_CKCTL, .enable_bit = EN_DSPCK, .rate_offset = CKCTL_DSPDIV_OFFSET, .recalc = &omap1_ckctl_recalc, + .round_rate = omap1_clk_round_rate_ckctl_arm, + .set_rate = omap1_clk_set_rate_ckctl_arm, }; static struct clk dspmmu_ck = { .name = "dspmmu_ck", .ops = &clkops_null, .parent = &ck_dpll1, - .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - RATE_CKCTL, + .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, .rate_offset = CKCTL_DSPMMUDIV_OFFSET, .recalc = &omap1_ckctl_recalc, + .round_rate = omap1_clk_round_rate_ckctl_arm, + .set_rate = omap1_clk_set_rate_ckctl_arm, }; static struct clk dspper_ck = { @@ -302,11 +310,12 @@ static struct clk dspper_ck = { .ops = &clkops_dspck, .parent = &ck_dpll1, .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - RATE_CKCTL | VIRTUAL_IO_ADDRESS, + VIRTUAL_IO_ADDRESS, .enable_reg = DSP_IDLECT2, .enable_bit = EN_PERCK, .rate_offset = CKCTL_PERDIV_OFFSET, .recalc = &omap1_ckctl_recalc_dsp_domain, + .round_rate = omap1_clk_round_rate_ckctl_arm, .set_rate = &omap1_clk_set_rate_dsp_domain, }; @@ -340,10 +349,11 @@ static struct arm_idlect1_clk tc_ck = { .parent = &ck_dpll1, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP730 | CLOCK_IN_OMAP310 | - RATE_CKCTL | RATE_PROPAGATES | - CLOCK_IDLE_CONTROL, + RATE_PROPAGATES | CLOCK_IDLE_CONTROL, .rate_offset = CKCTL_TCDIV_OFFSET, .recalc = &omap1_ckctl_recalc, + .round_rate = omap1_clk_round_rate_ckctl_arm, + .set_rate = omap1_clk_set_rate_ckctl_arm, }, .idlect_shift = 6, }; @@ -466,11 +476,13 @@ static struct clk lcd_ck_16xx = { .name = "lcd_ck", .ops = &clkops_generic, .parent = &ck_dpll1, - .flags = CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP730 | RATE_CKCTL, + .flags = CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP730, .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_LCDCK, .rate_offset = CKCTL_LCDDIV_OFFSET, .recalc = &omap1_ckctl_recalc, + .round_rate = omap1_clk_round_rate_ckctl_arm, + .set_rate = omap1_clk_set_rate_ckctl_arm, }; static struct arm_idlect1_clk lcd_ck_1510 = { @@ -479,11 +491,13 @@ static struct arm_idlect1_clk lcd_ck_1510 = { .ops = &clkops_generic, .parent = &ck_dpll1, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | - RATE_CKCTL | CLOCK_IDLE_CONTROL, + CLOCK_IDLE_CONTROL, .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_LCDCK, .rate_offset = CKCTL_LCDDIV_OFFSET, .recalc = &omap1_ckctl_recalc, + .round_rate = omap1_clk_round_rate_ckctl_arm, + .set_rate = omap1_clk_set_rate_ckctl_arm, }, .idlect_shift = 3, }; diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index 06dd38a8a0c..5a7411e71f2 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -124,7 +124,7 @@ extern void clk_enable_init_clocks(void); extern const struct clkops clkops_null; /* Clock flags */ -#define RATE_CKCTL (1 << 0) /* Main fixed ratio clocks */ +/* bit 0 is free */ #define RATE_FIXED (1 << 1) /* Fixed clock rate */ #define RATE_PROPAGATES (1 << 2) /* Program children too */ /* bits 3-4 are free */ -- GitLab From 1e98ffa85e70f423e2e41156cc3d549c353cd897 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 19 Jan 2009 18:56:17 +0000 Subject: [PATCH 1343/4982] [ARM] omap: ensure devname is set for dummy devices This is needed to use these with the clkdev helpers. Signed-off-by: Russell King --- arch/arm/mach-omap2/devices.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index ce03fa75077..97304044152 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -348,6 +348,7 @@ static void __init omap_hsmmc_reset(void) } dummy_pdev.id = i; + dev_set_name(&dummy_pdev.dev, "mmci-omap-hs.%d", i); iclk = clk_get(dev, "mmchs_ick"); if (iclk && clk_enable(iclk)) iclk = NULL; -- GitLab From dbb674d57b5851a4fe3122ff4280e4cf87209198 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 22 Jan 2009 16:08:04 +0000 Subject: [PATCH 1344/4982] [ARM] omap: allow double-registering of clocks This stops things blowing up if a 'struct clk' to be passed more than once to clk_register(), which will be required when we decouple struct clk's from their names. Signed-off-by: Russell King --- arch/arm/plat-omap/clock.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index df58f5d9a5a..6b3ef2a0b04 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -292,6 +292,12 @@ int clk_register(struct clk *clk) if (clk == NULL || IS_ERR(clk)) return -EINVAL; + /* + * trap out already registered clocks + */ + if (clk->node.next || clk->node.prev) + return 0; + mutex_lock(&clocks_mutex); list_add(&clk->node, &clocks); if (clk->init) -- GitLab From d7e8f1f9d655af2c7ea90738bf567aa6990159b3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 18 Jan 2009 23:03:15 +0000 Subject: [PATCH 1345/4982] [ARM] omap: convert OMAP1 to use clkdev Signed-off-by: Russell King --- arch/arm/mach-omap1/clock.c | 117 ++++++++++++---- arch/arm/mach-omap1/clock.h | 164 +++++------------------ arch/arm/plat-omap/Kconfig | 1 + arch/arm/plat-omap/clock.c | 4 + arch/arm/plat-omap/include/mach/clkdev.h | 13 ++ arch/arm/plat-omap/include/mach/clock.h | 6 +- 6 files changed, 145 insertions(+), 160 deletions(-) create mode 100644 arch/arm/plat-omap/include/mach/clkdev.h diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index 6b17da120e5..829b9b845b8 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -32,6 +33,83 @@ static const struct clkops clkops_dspck; #include "clock.h" +struct omap_clk { + u32 cpu; + struct clk_lookup lk; +}; + +#define CLK(dev, con, ck, cp) \ + { \ + .cpu = cp, \ + .lk = { \ + .dev_id = dev, \ + .con_id = con, \ + .clk = ck, \ + }, \ + } + +#define CK_310 (1 << 0) +#define CK_730 (1 << 1) +#define CK_1510 (1 << 2) +#define CK_16XX (1 << 3) + +static struct omap_clk omap_clks[] = { + /* non-ULPD clocks */ + CLK(NULL, "ck_ref", &ck_ref, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "ck_dpll1", &ck_dpll1, CK_16XX | CK_1510 | CK_310), + /* CK_GEN1 clocks */ + CLK(NULL, "ck_dpll1out", &ck_dpll1out.clk, CK_16XX), + CLK(NULL, "ck_sossi", &sossi_ck, CK_16XX), + CLK(NULL, "arm_ck", &arm_ck, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "armper_ck", &armper_ck.clk, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "arm_gpio_ck", &arm_gpio_ck, CK_1510 | CK_310), + CLK(NULL, "armxor_ck", &armxor_ck.clk, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "armtim_ck", &armtim_ck.clk, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "armwdt_ck", &armwdt_ck.clk, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "arminth_ck", &arminth_ck1510, CK_1510 | CK_310), + CLK(NULL, "arminth_ck", &arminth_ck16xx, CK_16XX), + /* CK_GEN2 clocks */ + CLK(NULL, "dsp_ck", &dsp_ck, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "dspmmu_ck", &dspmmu_ck, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "dspper_ck", &dspper_ck, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "dspxor_ck", &dspxor_ck, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "dsptim_ck", &dsptim_ck, CK_16XX | CK_1510 | CK_310), + /* CK_GEN3 clocks */ + CLK(NULL, "tc_ck", &tc_ck.clk, CK_16XX | CK_1510 | CK_310 | CK_730), + CLK(NULL, "tipb_ck", &tipb_ck, CK_1510 | CK_310), + CLK(NULL, "l3_ocpi_ck", &l3_ocpi_ck, CK_16XX), + CLK(NULL, "tc1_ck", &tc1_ck, CK_16XX), + CLK(NULL, "tc2_ck", &tc2_ck, CK_16XX), + CLK(NULL, "dma_ck", &dma_ck, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "dma_lcdfree_ck", &dma_lcdfree_ck, CK_16XX), + CLK(NULL, "api_ck", &api_ck.clk, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "lb_ck", &lb_ck.clk, CK_1510 | CK_310), + CLK(NULL, "rhea1_ck", &rhea1_ck, CK_16XX), + CLK(NULL, "rhea2_ck", &rhea2_ck, CK_16XX), + CLK(NULL, "lcd_ck", &lcd_ck_16xx, CK_16XX | CK_730), + CLK(NULL, "lcd_ck", &lcd_ck_1510.clk, CK_1510 | CK_310), + /* ULPD clocks */ + CLK(NULL, "uart1_ck", &uart1_1510, CK_1510 | CK_310), + CLK(NULL, "uart1_ck", &uart1_16xx.clk, CK_16XX), + CLK(NULL, "uart2_ck", &uart2_ck, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "uart3_ck", &uart3_1510, CK_1510 | CK_310), + CLK(NULL, "uart3_ck", &uart3_16xx.clk, CK_16XX), + CLK(NULL, "usb_clko", &usb_clko, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "usb_hhc_ck", &usb_hhc_ck1510, CK_1510 | CK_310), + CLK(NULL, "usb_hhc_ck", &usb_hhc_ck16xx, CK_16XX), + CLK(NULL, "usb_dc_ck", &usb_dc_ck, CK_16XX), + CLK(NULL, "mclk", &mclk_1510, CK_1510 | CK_310), + CLK(NULL, "mclk", &mclk_16xx, CK_16XX), + CLK(NULL, "bclk", &bclk_1510, CK_1510 | CK_310), + CLK(NULL, "bclk", &bclk_16xx, CK_16XX), + CLK("mmci-omap.0", "mmc_ck", &mmc1_ck, CK_16XX | CK_1510 | CK_310), + CLK("mmci-omap.1", "mmc_ck", &mmc2_ck, CK_16XX), + /* Virtual clocks */ + CLK(NULL, "mpu", &virtual_ck_mpu, CK_16XX | CK_1510 | CK_310), + CLK("i2c_omap.1", "i2c_fck", &i2c_fck, CK_16XX | CK_1510 | CK_310), + CLK("i2c_omap.1", "i2c_ick", &i2c_ick, CK_16XX), +}; + static int omap1_clk_enable_generic(struct clk * clk); static int omap1_clk_enable(struct clk *clk); static void omap1_clk_disable_generic(struct clk * clk); @@ -677,10 +755,10 @@ static struct clk_functions omap1_clk_functions = { int __init omap1_clk_init(void) { - struct clk ** clkp; + struct omap_clk *c; const struct omap_clock_config *info; int crystal_type = 0; /* Default 12 MHz */ - u32 reg; + u32 reg, cpu_mask; #ifdef CONFIG_DEBUG_LL /* Resets some clocks that may be left on from bootloader, @@ -700,27 +778,21 @@ int __init omap1_clk_init(void) /* By default all idlect1 clocks are allowed to idle */ arm_idlect1_mask = ~0; - for (clkp = onchip_clks; clkp < onchip_clks+ARRAY_SIZE(onchip_clks); clkp++) { - if (((*clkp)->flags &CLOCK_IN_OMAP1510) && cpu_is_omap1510()) { - clk_register(*clkp); - continue; - } - - if (((*clkp)->flags &CLOCK_IN_OMAP16XX) && cpu_is_omap16xx()) { - clk_register(*clkp); - continue; - } - - if (((*clkp)->flags &CLOCK_IN_OMAP730) && cpu_is_omap730()) { - clk_register(*clkp); - continue; - } - - if (((*clkp)->flags &CLOCK_IN_OMAP310) && cpu_is_omap310()) { - clk_register(*clkp); - continue; + cpu_mask = 0; + if (cpu_is_omap16xx()) + cpu_mask |= CK_16XX; + if (cpu_is_omap1510()) + cpu_mask |= CK_1510; + if (cpu_is_omap730()) + cpu_mask |= CK_730; + if (cpu_is_omap310()) + cpu_mask |= CK_310; + + for (c = omap_clks; c < omap_clks + ARRAY_SIZE(omap_clks); c++) + if (c->cpu & cpu_mask) { + clkdev_add(&c->lk); + clk_register(c->lk.clk); } - } info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config); if (info != NULL) { @@ -831,4 +903,3 @@ int __init omap1_clk_init(void) return 0; } - diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h index aa7b3d604ee..ed343af5f12 100644 --- a/arch/arm/mach-omap1/clock.h +++ b/arch/arm/mach-omap1/clock.h @@ -149,16 +149,13 @@ static struct clk ck_ref = { .name = "ck_ref", .ops = &clkops_null, .rate = 12000000, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP310, }; static struct clk ck_dpll1 = { .name = "ck_dpll1", .ops = &clkops_null, .parent = &ck_ref, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP310 | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, }; static struct arm_idlect1_clk ck_dpll1out = { @@ -166,7 +163,7 @@ static struct arm_idlect1_clk ck_dpll1out = { .name = "ck_dpll1out", .ops = &clkops_generic, .parent = &ck_dpll1, - .flags = CLOCK_IN_OMAP16XX | CLOCK_IDLE_CONTROL | + .flags = CLOCK_IDLE_CONTROL | ENABLE_REG_32BIT | RATE_PROPAGATES, .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_CKOUT_ARM, @@ -179,8 +176,7 @@ static struct clk sossi_ck = { .name = "ck_sossi", .ops = &clkops_generic, .parent = &ck_dpll1out.clk, - .flags = CLOCK_IN_OMAP16XX | CLOCK_NO_IDLE_PARENT | - ENABLE_REG_32BIT, + .flags = CLOCK_NO_IDLE_PARENT | ENABLE_REG_32BIT, .enable_reg = (void __iomem *)MOD_CONF_CTRL_1, .enable_bit = 16, .recalc = &omap1_sossi_recalc, @@ -191,8 +187,7 @@ static struct clk arm_ck = { .name = "arm_ck", .ops = &clkops_null, .parent = &ck_dpll1, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP310 | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .rate_offset = CKCTL_ARMDIV_OFFSET, .recalc = &omap1_ckctl_recalc, .round_rate = omap1_clk_round_rate_ckctl_arm, @@ -204,8 +199,7 @@ static struct arm_idlect1_clk armper_ck = { .name = "armper_ck", .ops = &clkops_generic, .parent = &ck_dpll1, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL, + .flags = CLOCK_IDLE_CONTROL, .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_PERCK, .rate_offset = CKCTL_PERDIV_OFFSET, @@ -220,7 +214,6 @@ static struct clk arm_gpio_ck = { .name = "arm_gpio_ck", .ops = &clkops_generic, .parent = &ck_dpll1, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_GPIOCK, .recalc = &followparent_recalc, @@ -231,8 +224,7 @@ static struct arm_idlect1_clk armxor_ck = { .name = "armxor_ck", .ops = &clkops_generic, .parent = &ck_ref, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL, + .flags = CLOCK_IDLE_CONTROL, .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_XORPCK, .recalc = &followparent_recalc, @@ -245,8 +237,7 @@ static struct arm_idlect1_clk armtim_ck = { .name = "armtim_ck", .ops = &clkops_generic, .parent = &ck_ref, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL, + .flags = CLOCK_IDLE_CONTROL, .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_TIMCK, .recalc = &followparent_recalc, @@ -259,8 +250,7 @@ static struct arm_idlect1_clk armwdt_ck = { .name = "armwdt_ck", .ops = &clkops_generic, .parent = &ck_ref, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL, + .flags = CLOCK_IDLE_CONTROL, .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_WDTCK, .recalc = &omap1_watchdog_recalc, @@ -272,7 +262,6 @@ static struct clk arminth_ck16xx = { .name = "arminth_ck", .ops = &clkops_null, .parent = &arm_ck, - .flags = CLOCK_IN_OMAP16XX, .recalc = &followparent_recalc, /* Note: On 16xx the frequency can be divided by 2 by programming * ARM_CKCTL:ARM_INTHCK_SEL(14) to 1 @@ -285,7 +274,6 @@ static struct clk dsp_ck = { .name = "dsp_ck", .ops = &clkops_generic, .parent = &ck_dpll1, - .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, .enable_reg = (void __iomem *)ARM_CKCTL, .enable_bit = EN_DSPCK, .rate_offset = CKCTL_DSPDIV_OFFSET, @@ -298,7 +286,6 @@ static struct clk dspmmu_ck = { .name = "dspmmu_ck", .ops = &clkops_null, .parent = &ck_dpll1, - .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX, .rate_offset = CKCTL_DSPMMUDIV_OFFSET, .recalc = &omap1_ckctl_recalc, .round_rate = omap1_clk_round_rate_ckctl_arm, @@ -309,8 +296,7 @@ static struct clk dspper_ck = { .name = "dspper_ck", .ops = &clkops_dspck, .parent = &ck_dpll1, - .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - VIRTUAL_IO_ADDRESS, + .flags = VIRTUAL_IO_ADDRESS, .enable_reg = DSP_IDLECT2, .enable_bit = EN_PERCK, .rate_offset = CKCTL_PERDIV_OFFSET, @@ -323,8 +309,7 @@ static struct clk dspxor_ck = { .name = "dspxor_ck", .ops = &clkops_dspck, .parent = &ck_ref, - .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - VIRTUAL_IO_ADDRESS, + .flags = VIRTUAL_IO_ADDRESS, .enable_reg = DSP_IDLECT2, .enable_bit = EN_XORPCK, .recalc = &followparent_recalc, @@ -334,8 +319,7 @@ static struct clk dsptim_ck = { .name = "dsptim_ck", .ops = &clkops_dspck, .parent = &ck_ref, - .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - VIRTUAL_IO_ADDRESS, + .flags = VIRTUAL_IO_ADDRESS, .enable_reg = DSP_IDLECT2, .enable_bit = EN_DSPTIMCK, .recalc = &followparent_recalc, @@ -347,9 +331,7 @@ static struct arm_idlect1_clk tc_ck = { .name = "tc_ck", .ops = &clkops_null, .parent = &ck_dpll1, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP730 | CLOCK_IN_OMAP310 | - RATE_PROPAGATES | CLOCK_IDLE_CONTROL, + .flags = RATE_PROPAGATES | CLOCK_IDLE_CONTROL, .rate_offset = CKCTL_TCDIV_OFFSET, .recalc = &omap1_ckctl_recalc, .round_rate = omap1_clk_round_rate_ckctl_arm, @@ -362,7 +344,6 @@ static struct clk arminth_ck1510 = { .name = "arminth_ck", .ops = &clkops_null, .parent = &tc_ck.clk, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, .recalc = &followparent_recalc, /* Note: On 1510 the frequency follows TC_CK * @@ -375,7 +356,6 @@ static struct clk tipb_ck = { .name = "tipb_ck", .ops = &clkops_null, .parent = &tc_ck.clk, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, .recalc = &followparent_recalc, }; @@ -384,7 +364,6 @@ static struct clk l3_ocpi_ck = { .name = "l3_ocpi_ck", .ops = &clkops_generic, .parent = &tc_ck.clk, - .flags = CLOCK_IN_OMAP16XX, .enable_reg = (void __iomem *)ARM_IDLECT3, .enable_bit = EN_OCPI_CK, .recalc = &followparent_recalc, @@ -394,7 +373,6 @@ static struct clk tc1_ck = { .name = "tc1_ck", .ops = &clkops_generic, .parent = &tc_ck.clk, - .flags = CLOCK_IN_OMAP16XX, .enable_reg = (void __iomem *)ARM_IDLECT3, .enable_bit = EN_TC1_CK, .recalc = &followparent_recalc, @@ -404,7 +382,6 @@ static struct clk tc2_ck = { .name = "tc2_ck", .ops = &clkops_generic, .parent = &tc_ck.clk, - .flags = CLOCK_IN_OMAP16XX, .enable_reg = (void __iomem *)ARM_IDLECT3, .enable_bit = EN_TC2_CK, .recalc = &followparent_recalc, @@ -415,8 +392,6 @@ static struct clk dma_ck = { .name = "dma_ck", .ops = &clkops_null, .parent = &tc_ck.clk, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP310, .recalc = &followparent_recalc, }; @@ -424,7 +399,6 @@ static struct clk dma_lcdfree_ck = { .name = "dma_lcdfree_ck", .ops = &clkops_null, .parent = &tc_ck.clk, - .flags = CLOCK_IN_OMAP16XX, .recalc = &followparent_recalc, }; @@ -433,8 +407,7 @@ static struct arm_idlect1_clk api_ck = { .name = "api_ck", .ops = &clkops_generic, .parent = &tc_ck.clk, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL, + .flags = CLOCK_IDLE_CONTROL, .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_APICK, .recalc = &followparent_recalc, @@ -447,8 +420,7 @@ static struct arm_idlect1_clk lb_ck = { .name = "lb_ck", .ops = &clkops_generic, .parent = &tc_ck.clk, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | - CLOCK_IDLE_CONTROL, + .flags = CLOCK_IDLE_CONTROL, .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_LBCK, .recalc = &followparent_recalc, @@ -460,7 +432,6 @@ static struct clk rhea1_ck = { .name = "rhea1_ck", .ops = &clkops_null, .parent = &tc_ck.clk, - .flags = CLOCK_IN_OMAP16XX, .recalc = &followparent_recalc, }; @@ -468,7 +439,6 @@ static struct clk rhea2_ck = { .name = "rhea2_ck", .ops = &clkops_null, .parent = &tc_ck.clk, - .flags = CLOCK_IN_OMAP16XX, .recalc = &followparent_recalc, }; @@ -476,7 +446,6 @@ static struct clk lcd_ck_16xx = { .name = "lcd_ck", .ops = &clkops_generic, .parent = &ck_dpll1, - .flags = CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP730, .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_LCDCK, .rate_offset = CKCTL_LCDDIV_OFFSET, @@ -490,8 +459,7 @@ static struct arm_idlect1_clk lcd_ck_1510 = { .name = "lcd_ck", .ops = &clkops_generic, .parent = &ck_dpll1, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | - CLOCK_IDLE_CONTROL, + .flags = CLOCK_IDLE_CONTROL, .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_LCDCK, .rate_offset = CKCTL_LCDDIV_OFFSET, @@ -508,8 +476,7 @@ static struct clk uart1_1510 = { /* Direct from ULPD, no real parent */ .parent = &armper_ck.clk, .rate = 12000000, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | - ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, + .flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, .enable_bit = 29, /* Chooses between 12MHz and 48MHz */ .set_rate = &omap1_set_uart_rate, @@ -523,8 +490,8 @@ static struct uart_clk uart1_16xx = { /* Direct from ULPD, no real parent */ .parent = &armper_ck.clk, .rate = 48000000, - .flags = CLOCK_IN_OMAP16XX | RATE_FIXED | - ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, + .flags = RATE_FIXED | ENABLE_REG_32BIT | + CLOCK_NO_IDLE_PARENT, .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, .enable_bit = 29, }, @@ -537,9 +504,7 @@ static struct clk uart2_ck = { /* Direct from ULPD, no real parent */ .parent = &armper_ck.clk, .rate = 12000000, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP310 | ENABLE_REG_32BIT | - CLOCK_NO_IDLE_PARENT, + .flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, .enable_bit = 30, /* Chooses between 12MHz and 48MHz */ .set_rate = &omap1_set_uart_rate, @@ -552,8 +517,7 @@ static struct clk uart3_1510 = { /* Direct from ULPD, no real parent */ .parent = &armper_ck.clk, .rate = 12000000, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | - ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, + .flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, .enable_bit = 31, /* Chooses between 12MHz and 48MHz */ .set_rate = &omap1_set_uart_rate, @@ -567,8 +531,8 @@ static struct uart_clk uart3_16xx = { /* Direct from ULPD, no real parent */ .parent = &armper_ck.clk, .rate = 48000000, - .flags = CLOCK_IN_OMAP16XX | RATE_FIXED | - ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, + .flags = RATE_FIXED | ENABLE_REG_32BIT | + CLOCK_NO_IDLE_PARENT, .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, .enable_bit = 31, }, @@ -580,8 +544,7 @@ static struct clk usb_clko = { /* 6 MHz output on W4_USB_CLKO */ .ops = &clkops_generic, /* Direct from ULPD, no parent */ .rate = 6000000, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP310 | RATE_FIXED | ENABLE_REG_32BIT, + .flags = RATE_FIXED | ENABLE_REG_32BIT, .enable_reg = (void __iomem *)ULPD_CLOCK_CTRL, .enable_bit = USB_MCLK_EN_BIT, }; @@ -591,8 +554,7 @@ static struct clk usb_hhc_ck1510 = { .ops = &clkops_generic, /* Direct from ULPD, no parent */ .rate = 48000000, /* Actually 2 clocks, 12MHz and 48MHz */ - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | - RATE_FIXED | ENABLE_REG_32BIT, + .flags = RATE_FIXED | ENABLE_REG_32BIT, .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, .enable_bit = USB_HOST_HHC_UHOST_EN, }; @@ -603,8 +565,7 @@ static struct clk usb_hhc_ck16xx = { /* Direct from ULPD, no parent */ .rate = 48000000, /* OTG_SYSCON_2.OTG_PADEN == 0 (not 1510-compatible) */ - .flags = CLOCK_IN_OMAP16XX | - RATE_FIXED | ENABLE_REG_32BIT, + .flags = RATE_FIXED | ENABLE_REG_32BIT, .enable_reg = (void __iomem *)OTG_BASE + 0x08 /* OTG_SYSCON_2 */, .enable_bit = 8 /* UHOST_EN */, }; @@ -614,7 +575,7 @@ static struct clk usb_dc_ck = { .ops = &clkops_generic, /* Direct from ULPD, no parent */ .rate = 48000000, - .flags = CLOCK_IN_OMAP16XX | RATE_FIXED, + .flags = RATE_FIXED, .enable_reg = (void __iomem *)SOFT_REQ_REG, .enable_bit = 4, }; @@ -624,7 +585,7 @@ static struct clk mclk_1510 = { .ops = &clkops_generic, /* Direct from ULPD, no parent. May be enabled by ext hardware. */ .rate = 12000000, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | RATE_FIXED, + .flags = RATE_FIXED, .enable_reg = (void __iomem *)SOFT_REQ_REG, .enable_bit = 6, }; @@ -633,7 +594,6 @@ static struct clk mclk_16xx = { .name = "mclk", .ops = &clkops_generic, /* Direct from ULPD, no parent. May be enabled by ext hardware. */ - .flags = CLOCK_IN_OMAP16XX, .enable_reg = (void __iomem *)COM_CLK_DIV_CTRL_SEL, .enable_bit = COM_ULPD_PLL_CLK_REQ, .set_rate = &omap1_set_ext_clk_rate, @@ -646,14 +606,13 @@ static struct clk bclk_1510 = { .ops = &clkops_generic, /* Direct from ULPD, no parent. May be enabled by ext hardware. */ .rate = 12000000, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | RATE_FIXED, + .flags = RATE_FIXED, }; static struct clk bclk_16xx = { .name = "bclk", .ops = &clkops_generic, /* Direct from ULPD, no parent. May be enabled by ext hardware. */ - .flags = CLOCK_IN_OMAP16XX, .enable_reg = (void __iomem *)SWD_CLK_DIV_CTRL_SEL, .enable_bit = SWD_ULPD_PLL_CLK_REQ, .set_rate = &omap1_set_ext_clk_rate, @@ -667,9 +626,7 @@ static struct clk mmc1_ck = { /* Functional clock is direct from ULPD, interface clock is ARMPER */ .parent = &armper_ck.clk, .rate = 48000000, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP310 | RATE_FIXED | ENABLE_REG_32BIT | - CLOCK_NO_IDLE_PARENT, + .flags = RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, .enable_bit = 23, }; @@ -681,8 +638,7 @@ static struct clk mmc2_ck = { /* Functional clock is direct from ULPD, interface clock is ARMPER */ .parent = &armper_ck.clk, .rate = 48000000, - .flags = CLOCK_IN_OMAP16XX | - RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, + .flags = RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, .enable_bit = 20, }; @@ -690,8 +646,6 @@ static struct clk mmc2_ck = { static struct clk virtual_ck_mpu = { .name = "mpu", .ops = &clkops_null, - .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_IN_OMAP310, .parent = &arm_ck, /* Is smarter alias for */ .recalc = &followparent_recalc, .set_rate = &omap1_select_table_rate, @@ -704,8 +658,7 @@ static struct clk i2c_fck = { .name = "i2c_fck", .id = 1, .ops = &clkops_null, - .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | - CLOCK_NO_IDLE_PARENT, + .flags = CLOCK_NO_IDLE_PARENT, .parent = &armxor_ck.clk, .recalc = &followparent_recalc, }; @@ -714,62 +667,9 @@ static struct clk i2c_ick = { .name = "i2c_ick", .id = 1, .ops = &clkops_null, - .flags = CLOCK_IN_OMAP16XX | CLOCK_NO_IDLE_PARENT, + .flags = CLOCK_NO_IDLE_PARENT, .parent = &armper_ck.clk, .recalc = &followparent_recalc, }; -static struct clk * onchip_clks[] = { - /* non-ULPD clocks */ - &ck_ref, - &ck_dpll1, - /* CK_GEN1 clocks */ - &ck_dpll1out.clk, - &sossi_ck, - &arm_ck, - &armper_ck.clk, - &arm_gpio_ck, - &armxor_ck.clk, - &armtim_ck.clk, - &armwdt_ck.clk, - &arminth_ck1510, &arminth_ck16xx, - /* CK_GEN2 clocks */ - &dsp_ck, - &dspmmu_ck, - &dspper_ck, - &dspxor_ck, - &dsptim_ck, - /* CK_GEN3 clocks */ - &tc_ck.clk, - &tipb_ck, - &l3_ocpi_ck, - &tc1_ck, - &tc2_ck, - &dma_ck, - &dma_lcdfree_ck, - &api_ck.clk, - &lb_ck.clk, - &rhea1_ck, - &rhea2_ck, - &lcd_ck_16xx, - &lcd_ck_1510.clk, - /* ULPD clocks */ - &uart1_1510, - &uart1_16xx.clk, - &uart2_ck, - &uart3_1510, - &uart3_16xx.clk, - &usb_clko, - &usb_hhc_ck1510, &usb_hhc_ck16xx, - &usb_dc_ck, - &mclk_1510, &mclk_16xx, - &bclk_1510, &bclk_16xx, - &mmc1_ck, - &mmc2_ck, - /* Virtual clocks */ - &virtual_ck_mpu, - &i2c_fck, - &i2c_ick, -}; - #endif diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 46d3b0b9ce6..fc7b6831f3e 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -11,6 +11,7 @@ choice config ARCH_OMAP1 bool "TI OMAP1" + select COMMON_CLKDEV config ARCH_OMAP2 bool "TI OMAP2" diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 6b3ef2a0b04..6b88f7878a5 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -36,6 +36,7 @@ static struct clk_functions *arch_clock; * Standard clock functions defined in include/linux/clk.h *-------------------------------------------------------------------------*/ +#ifndef CONFIG_COMMON_CLKDEV /* * Returns a clock. Note that we first try to use device id on the bus * and clock name. If this fails, we try to use clock name only. @@ -72,6 +73,7 @@ found: return clk; } EXPORT_SYMBOL(clk_get); +#endif int clk_enable(struct clk *clk) { @@ -145,10 +147,12 @@ unsigned long clk_get_rate(struct clk *clk) } EXPORT_SYMBOL(clk_get_rate); +#ifndef CONFIG_COMMON_CLKDEV void clk_put(struct clk *clk) { } EXPORT_SYMBOL(clk_put); +#endif /*------------------------------------------------------------------------- * Optional clock functions defined in include/linux/clk.h diff --git a/arch/arm/plat-omap/include/mach/clkdev.h b/arch/arm/plat-omap/include/mach/clkdev.h new file mode 100644 index 00000000000..730c49d1ebd --- /dev/null +++ b/arch/arm/plat-omap/include/mach/clkdev.h @@ -0,0 +1,13 @@ +#ifndef __MACH_CLKDEV_H +#define __MACH_CLKDEV_H + +static inline int __clk_get(struct clk *clk) +{ + return 1; +} + +static inline void __clk_put(struct clk *clk) +{ +} + +#endif diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index 5a7411e71f2..2af4bc24cfe 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -136,11 +136,7 @@ extern const struct clkops clkops_null; #define CONFIG_PARTICIPANT (1 << 10) /* Fundamental clock */ #define ENABLE_ON_INIT (1 << 11) /* Enable upon framework init */ #define INVERT_ENABLE (1 << 12) /* 0 enables, 1 disables */ -/* bits 13-20 are currently free */ -#define CLOCK_IN_OMAP310 (1 << 21) -#define CLOCK_IN_OMAP730 (1 << 22) -#define CLOCK_IN_OMAP1510 (1 << 23) -#define CLOCK_IN_OMAP16XX (1 << 24) +/* bits 13-24 are currently free */ #define CLOCK_IN_OMAP242X (1 << 25) #define CLOCK_IN_OMAP243X (1 << 26) #define CLOCK_IN_OMAP343X (1 << 27) /* clocks common to all 343X */ -- GitLab From 8ad8ff6548f1c0bcbeaa02f274b3927c5015a921 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 19 Jan 2009 15:27:29 +0000 Subject: [PATCH 1346/4982] [ARM] omap: convert OMAP2 to use clkdev Signed-off-by: Russell King --- arch/arm/mach-omap2/clock24xx.c | 197 ++++++++++++- arch/arm/mach-omap2/clock24xx.h | 353 +++--------------------- arch/arm/plat-omap/Kconfig | 1 + arch/arm/plat-omap/include/mach/clock.h | 4 +- 4 files changed, 218 insertions(+), 337 deletions(-) diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index 3a0a1b8aa0b..36093ea878a 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "memory.h" #include "clock.h" @@ -44,6 +45,177 @@ static const struct clkops clkops_fixed; #include "clock24xx.h" +struct omap_clk { + u32 cpu; + struct clk_lookup lk; +}; + +#define CLK(dev, con, ck, cp) \ + { \ + .cpu = cp, \ + .lk = { \ + .dev_id = dev, \ + .con_id = con, \ + .clk = ck, \ + }, \ + } + +#define CK_243X (1 << 0) +#define CK_242X (1 << 1) + +static struct omap_clk omap24xx_clks[] = { + /* external root sources */ + CLK(NULL, "func_32k_ck", &func_32k_ck, CK_243X | CK_242X), + CLK(NULL, "osc_ck", &osc_ck, CK_243X | CK_242X), + CLK(NULL, "sys_ck", &sys_ck, CK_243X | CK_242X), + CLK(NULL, "alt_ck", &alt_ck, CK_243X | CK_242X), + /* internal analog sources */ + CLK(NULL, "dpll_ck", &dpll_ck, CK_243X | CK_242X), + CLK(NULL, "apll96_ck", &apll96_ck, CK_243X | CK_242X), + CLK(NULL, "apll54_ck", &apll54_ck, CK_243X | CK_242X), + /* internal prcm root sources */ + CLK(NULL, "func_54m_ck", &func_54m_ck, CK_243X | CK_242X), + CLK(NULL, "core_ck", &core_ck, CK_243X | CK_242X), + CLK(NULL, "func_96m_ck", &func_96m_ck, CK_243X | CK_242X), + CLK(NULL, "func_48m_ck", &func_48m_ck, CK_243X | CK_242X), + CLK(NULL, "func_12m_ck", &func_12m_ck, CK_243X | CK_242X), + CLK(NULL, "ck_wdt1_osc", &wdt1_osc_ck, CK_243X | CK_242X), + CLK(NULL, "sys_clkout_src", &sys_clkout_src, CK_243X | CK_242X), + CLK(NULL, "sys_clkout", &sys_clkout, CK_243X | CK_242X), + CLK(NULL, "sys_clkout2_src", &sys_clkout2_src, CK_242X), + CLK(NULL, "sys_clkout2", &sys_clkout2, CK_242X), + CLK(NULL, "emul_ck", &emul_ck, CK_242X), + /* mpu domain clocks */ + CLK(NULL, "mpu_ck", &mpu_ck, CK_243X | CK_242X), + /* dsp domain clocks */ + CLK(NULL, "dsp_fck", &dsp_fck, CK_243X | CK_242X), + CLK(NULL, "dsp_irate_ick", &dsp_irate_ick, CK_243X | CK_242X), + CLK(NULL, "dsp_ick", &dsp_ick, CK_242X), + CLK(NULL, "iva2_1_ick", &iva2_1_ick, CK_243X), + CLK(NULL, "iva1_ifck", &iva1_ifck, CK_242X), + CLK(NULL, "iva1_mpu_int_ifck", &iva1_mpu_int_ifck, CK_242X), + /* GFX domain clocks */ + CLK(NULL, "gfx_3d_fck", &gfx_3d_fck, CK_243X | CK_242X), + CLK(NULL, "gfx_2d_fck", &gfx_2d_fck, CK_243X | CK_242X), + CLK(NULL, "gfx_ick", &gfx_ick, CK_243X | CK_242X), + /* Modem domain clocks */ + CLK(NULL, "mdm_ick", &mdm_ick, CK_243X), + CLK(NULL, "mdm_osc_ck", &mdm_osc_ck, CK_243X), + /* DSS domain clocks */ + CLK(NULL, "dss_ick", &dss_ick, CK_243X | CK_242X), + CLK(NULL, "dss1_fck", &dss1_fck, CK_243X | CK_242X), + CLK(NULL, "dss2_fck", &dss2_fck, CK_243X | CK_242X), + CLK(NULL, "dss_54m_fck", &dss_54m_fck, CK_243X | CK_242X), + /* L3 domain clocks */ + CLK(NULL, "core_l3_ck", &core_l3_ck, CK_243X | CK_242X), + CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_243X | CK_242X), + CLK(NULL, "usb_l4_ick", &usb_l4_ick, CK_243X | CK_242X), + /* L4 domain clocks */ + CLK(NULL, "l4_ck", &l4_ck, CK_243X | CK_242X), + /* virtual meta-group clock */ + CLK(NULL, "virt_prcm_set", &virt_prcm_set, CK_243X | CK_242X), + /* general l4 interface ck, multi-parent functional clk */ + CLK(NULL, "gpt1_ick", &gpt1_ick, CK_243X | CK_242X), + CLK(NULL, "gpt1_fck", &gpt1_fck, CK_243X | CK_242X), + CLK(NULL, "gpt2_ick", &gpt2_ick, CK_243X | CK_242X), + CLK(NULL, "gpt2_fck", &gpt2_fck, CK_243X | CK_242X), + CLK(NULL, "gpt3_ick", &gpt3_ick, CK_243X | CK_242X), + CLK(NULL, "gpt3_fck", &gpt3_fck, CK_243X | CK_242X), + CLK(NULL, "gpt4_ick", &gpt4_ick, CK_243X | CK_242X), + CLK(NULL, "gpt4_fck", &gpt4_fck, CK_243X | CK_242X), + CLK(NULL, "gpt5_ick", &gpt5_ick, CK_243X | CK_242X), + CLK(NULL, "gpt5_fck", &gpt5_fck, CK_243X | CK_242X), + CLK(NULL, "gpt6_ick", &gpt6_ick, CK_243X | CK_242X), + CLK(NULL, "gpt6_fck", &gpt6_fck, CK_243X | CK_242X), + CLK(NULL, "gpt7_ick", &gpt7_ick, CK_243X | CK_242X), + CLK(NULL, "gpt7_fck", &gpt7_fck, CK_243X | CK_242X), + CLK(NULL, "gpt8_ick", &gpt8_ick, CK_243X | CK_242X), + CLK(NULL, "gpt8_fck", &gpt8_fck, CK_243X | CK_242X), + CLK(NULL, "gpt9_ick", &gpt9_ick, CK_243X | CK_242X), + CLK(NULL, "gpt9_fck", &gpt9_fck, CK_243X | CK_242X), + CLK(NULL, "gpt10_ick", &gpt10_ick, CK_243X | CK_242X), + CLK(NULL, "gpt10_fck", &gpt10_fck, CK_243X | CK_242X), + CLK(NULL, "gpt11_ick", &gpt11_ick, CK_243X | CK_242X), + CLK(NULL, "gpt11_fck", &gpt11_fck, CK_243X | CK_242X), + CLK(NULL, "gpt12_ick", &gpt12_ick, CK_243X | CK_242X), + CLK(NULL, "gpt12_fck", &gpt12_fck, CK_243X | CK_242X), + CLK("omap-mcbsp.1", "mcbsp_ick", &mcbsp1_ick, CK_243X | CK_242X), + CLK("omap-mcbsp.1", "mcbsp_fck", &mcbsp1_fck, CK_243X | CK_242X), + CLK("omap-mcbsp.2", "mcbsp_ick", &mcbsp2_ick, CK_243X | CK_242X), + CLK("omap-mcbsp.2", "mcbsp_fck", &mcbsp2_fck, CK_243X | CK_242X), + CLK("omap-mcbsp.3", "mcbsp_ick", &mcbsp3_ick, CK_243X), + CLK("omap-mcbsp.3", "mcbsp_fck", &mcbsp3_fck, CK_243X), + CLK("omap-mcbsp.4", "mcbsp_ick", &mcbsp4_ick, CK_243X), + CLK("omap-mcbsp.4", "mcbsp_fck", &mcbsp4_fck, CK_243X), + CLK("omap-mcbsp.5", "mcbsp_ick", &mcbsp5_ick, CK_243X), + CLK("omap-mcbsp.5", "mcbsp_fck", &mcbsp5_fck, CK_243X), + CLK("omap2_mcspi.1", "mcspi_ick", &mcspi1_ick, CK_243X | CK_242X), + CLK("omap2_mcspi.1", "mcspi_fck", &mcspi1_fck, CK_243X | CK_242X), + CLK("omap2_mcspi.2", "mcspi_ick", &mcspi2_ick, CK_243X | CK_242X), + CLK("omap2_mcspi.2", "mcspi_fck", &mcspi2_fck, CK_243X | CK_242X), + CLK("omap2_mcspi.3", "mcspi_ick", &mcspi3_ick, CK_243X), + CLK("omap2_mcspi.3", "mcspi_fck", &mcspi3_fck, CK_243X), + CLK(NULL, "uart1_ick", &uart1_ick, CK_243X | CK_242X), + CLK(NULL, "uart1_fck", &uart1_fck, CK_243X | CK_242X), + CLK(NULL, "uart2_ick", &uart2_ick, CK_243X | CK_242X), + CLK(NULL, "uart2_fck", &uart2_fck, CK_243X | CK_242X), + CLK(NULL, "uart3_ick", &uart3_ick, CK_243X | CK_242X), + CLK(NULL, "uart3_fck", &uart3_fck, CK_243X | CK_242X), + CLK(NULL, "gpios_ick", &gpios_ick, CK_243X | CK_242X), + CLK(NULL, "gpios_fck", &gpios_fck, CK_243X | CK_242X), + CLK(NULL, "mpu_wdt_ick", &mpu_wdt_ick, CK_243X | CK_242X), + CLK(NULL, "mpu_wdt_fck", &mpu_wdt_fck, CK_243X | CK_242X), + CLK(NULL, "sync_32k_ick", &sync_32k_ick, CK_243X | CK_242X), + CLK(NULL, "wdt1_ick", &wdt1_ick, CK_243X | CK_242X), + CLK(NULL, "omapctrl_ick", &omapctrl_ick, CK_243X | CK_242X), + CLK(NULL, "icr_ick", &icr_ick, CK_243X), + CLK(NULL, "cam_fck", &cam_fck, CK_243X | CK_242X), + CLK(NULL, "cam_ick", &cam_ick, CK_243X | CK_242X), + CLK(NULL, "mailboxes_ick", &mailboxes_ick, CK_243X | CK_242X), + CLK(NULL, "wdt4_ick", &wdt4_ick, CK_243X | CK_242X), + CLK(NULL, "wdt4_fck", &wdt4_fck, CK_243X | CK_242X), + CLK(NULL, "wdt3_ick", &wdt3_ick, CK_242X), + CLK(NULL, "wdt3_fck", &wdt3_fck, CK_242X), + CLK(NULL, "mspro_ick", &mspro_ick, CK_243X | CK_242X), + CLK(NULL, "mspro_fck", &mspro_fck, CK_243X | CK_242X), + CLK(NULL, "mmc_ick", &mmc_ick, CK_242X), + CLK(NULL, "mmc_fck", &mmc_fck, CK_242X), + CLK(NULL, "fac_ick", &fac_ick, CK_243X | CK_242X), + CLK(NULL, "fac_fck", &fac_fck, CK_243X | CK_242X), + CLK(NULL, "eac_ick", &eac_ick, CK_242X), + CLK(NULL, "eac_fck", &eac_fck, CK_242X), + CLK(NULL, "hdq_ick", &hdq_ick, CK_243X | CK_242X), + CLK(NULL, "hdq_fck", &hdq_fck, CK_243X | CK_242X), + CLK("i2c_omap.1", "i2c_ick", &i2c1_ick, CK_243X | CK_242X), + CLK("i2c_omap.1", "i2c_fck", &i2c1_fck, CK_242X), + CLK("i2c_omap.1", "i2c_fck", &i2chs1_fck, CK_243X), + CLK("i2c_omap.2", "i2c_ick", &i2c2_ick, CK_243X | CK_242X), + CLK("i2c_omap.2", "i2c_fck", &i2c2_fck, CK_242X), + CLK("i2c_omap.2", "i2c_fck", &i2chs2_fck, CK_243X), + CLK(NULL, "gpmc_fck", &gpmc_fck, CK_243X | CK_242X), + CLK(NULL, "sdma_fck", &sdma_fck, CK_243X | CK_242X), + CLK(NULL, "sdma_ick", &sdma_ick, CK_243X | CK_242X), + CLK(NULL, "vlynq_ick", &vlynq_ick, CK_242X), + CLK(NULL, "vlynq_fck", &vlynq_fck, CK_242X), + CLK(NULL, "sdrc_ick", &sdrc_ick, CK_243X), + CLK(NULL, "des_ick", &des_ick, CK_243X | CK_242X), + CLK(NULL, "sha_ick", &sha_ick, CK_243X | CK_242X), + CLK(NULL, "rng_ick", &rng_ick, CK_243X | CK_242X), + CLK(NULL, "aes_ick", &aes_ick, CK_243X | CK_242X), + CLK(NULL, "pka_ick", &pka_ick, CK_243X | CK_242X), + CLK(NULL, "usb_fck", &usb_fck, CK_243X | CK_242X), + CLK(NULL, "usbhs_ick", &usbhs_ick, CK_243X), + CLK("mmci-omap-hs.0", "mmchs_ick", &mmchs1_ick, CK_243X), + CLK("mmci-omap-hs.0", "mmchs_fck", &mmchs1_fck, CK_243X), + CLK("mmci-omap-hs.1", "mmchs_ick", &mmchs2_ick, CK_243X), + CLK("mmci-omap-hs.1", "mmchs_fck", &mmchs2_fck, CK_243X), + CLK(NULL, "gpio5_ick", &gpio5_ick, CK_243X), + CLK(NULL, "gpio5_fck", &gpio5_fck, CK_243X), + CLK(NULL, "mdm_intc_ick", &mdm_intc_ick, CK_243X), + CLK("mmci-omap-hs.0", "mmchsdb_fck", &mmchsdb1_fck, CK_243X), + CLK("mmci-omap-hs.1", "mmchsdb_fck", &mmchsdb2_fck, CK_243X), +}; + /* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */ #define EN_APLL_STOPPED 0 #define EN_APLL_LOCKED 3 @@ -487,8 +659,8 @@ arch_initcall(omap2_clk_arch_init); int __init omap2_clk_init(void) { struct prcm_config *prcm; - struct clk **clkp; - u32 clkrate; + struct omap_clk *c; + u32 clkrate, cpu_mask; if (cpu_is_omap242x()) cpu_mask = RATE_IN_242X; @@ -502,21 +674,18 @@ int __init omap2_clk_init(void) omap2_sys_clk_recalc(&sys_ck); propagate_rate(&sys_ck); - for (clkp = onchip_24xx_clks; - clkp < onchip_24xx_clks + ARRAY_SIZE(onchip_24xx_clks); - clkp++) { + cpu_mask = 0; + if (cpu_is_omap2420()) + cpu_mask |= CK_242X; + if (cpu_is_omap2430()) + cpu_mask |= CK_243X; - if ((*clkp)->flags & CLOCK_IN_OMAP242X && cpu_is_omap2420()) { - clk_register(*clkp); - continue; + for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++) + if (c->cpu & cpu_mask) { + clkdev_add(&c->lk); + clk_register(c->lk.clk); } - if ((*clkp)->flags & CLOCK_IN_OMAP243X && cpu_is_omap2430()) { - clk_register(*clkp); - continue; - } - } - /* Check the MPU rate set by bootloader */ clkrate = omap2_get_dpll_rate_24xx(&dpll_ck); for (prcm = rate_table; prcm->mpu_speed; prcm++) { diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h index e07dcba4b3e..b2442475fb4 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock24xx.h @@ -621,8 +621,7 @@ static struct clk func_32k_ck = { .name = "func_32k_ck", .ops = &clkops_null, .rate = 32000, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - RATE_FIXED | RATE_PROPAGATES, + .flags = RATE_FIXED | RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", }; @@ -630,8 +629,7 @@ static struct clk func_32k_ck = { static struct clk osc_ck = { /* (*12, *13, 19.2, *26, 38.4)MHz */ .name = "osc_ck", .ops = &clkops_oscck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .recalc = &omap2_osc_clk_recalc, }; @@ -641,8 +639,7 @@ static struct clk sys_ck = { /* (*12, *13, 19.2, 26, 38.4)MHz */ .name = "sys_ck", /* ~ ref_clk also */ .ops = &clkops_null, .parent = &osc_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .recalc = &omap2_sys_clk_recalc, }; @@ -651,8 +648,7 @@ static struct clk alt_ck = { /* Typical 54M or 48M, may not exist */ .name = "alt_ck", .ops = &clkops_null, .rate = 54000000, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - RATE_FIXED | RATE_PROPAGATES, + .flags = RATE_FIXED | RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", }; @@ -683,8 +679,7 @@ static struct clk dpll_ck = { .ops = &clkops_null, .parent = &sys_ck, /* Can be func_32k also */ .dpll_data = &dpll_dd, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .recalc = &omap2_dpllcore_recalc, .set_rate = &omap2_reprogram_dpllcore, @@ -695,8 +690,7 @@ static struct clk apll96_ck = { .ops = &clkops_fixed, .parent = &sys_ck, .rate = 96000000, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - RATE_FIXED | RATE_PROPAGATES | ENABLE_ON_INIT, + .flags = RATE_FIXED | RATE_PROPAGATES | ENABLE_ON_INIT, .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP24XX_EN_96M_PLL_SHIFT, @@ -707,8 +701,7 @@ static struct clk apll54_ck = { .ops = &clkops_fixed, .parent = &sys_ck, .rate = 54000000, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - RATE_FIXED | RATE_PROPAGATES | ENABLE_ON_INIT, + .flags = RATE_FIXED | RATE_PROPAGATES | ENABLE_ON_INIT, .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP24XX_EN_54M_PLL_SHIFT, @@ -740,8 +733,7 @@ static struct clk func_54m_ck = { .name = "func_54m_ck", .ops = &clkops_null, .parent = &apll54_ck, /* can also be alt_clk */ - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), @@ -754,8 +746,7 @@ static struct clk core_ck = { .name = "core_ck", .ops = &clkops_null, .parent = &dpll_ck, /* can also be 32k */ - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -782,8 +773,7 @@ static struct clk func_96m_ck = { .name = "func_96m_ck", .ops = &clkops_null, .parent = &apll96_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), @@ -816,8 +806,7 @@ static struct clk func_48m_ck = { .name = "func_48m_ck", .ops = &clkops_null, .parent = &apll96_ck, /* 96M or Alt */ - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), @@ -833,8 +822,7 @@ static struct clk func_12m_ck = { .ops = &clkops_null, .parent = &func_48m_ck, .fixed_div = 4, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .recalc = &omap2_fixed_divisor_recalc, }; @@ -844,7 +832,6 @@ static struct clk wdt1_osc_ck = { .name = "ck_wdt1_osc", .ops = &clkops_null, /* RMK: missing? */ .parent = &osc_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .recalc = &followparent_recalc, }; @@ -888,8 +875,7 @@ static struct clk sys_clkout_src = { .name = "sys_clkout_src", .ops = &clkops_omap2_dflt, .parent = &func_54m_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .enable_reg = OMAP24XX_PRCM_CLKOUT_CTRL, .enable_bit = OMAP24XX_CLKOUT_EN_SHIFT, @@ -920,7 +906,6 @@ static struct clk sys_clkout = { .name = "sys_clkout", .ops = &clkops_null, .parent = &sys_clkout_src, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "wkup_clkdm", .clksel_reg = OMAP24XX_PRCM_CLKOUT_CTRL, .clksel_mask = OMAP24XX_CLKOUT_DIV_MASK, @@ -935,7 +920,7 @@ static struct clk sys_clkout2_src = { .name = "sys_clkout2_src", .ops = &clkops_omap2_dflt, .parent = &func_54m_ck, - .flags = CLOCK_IN_OMAP242X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .enable_reg = OMAP24XX_PRCM_CLKOUT_CTRL, .enable_bit = OMAP2420_CLKOUT2_EN_SHIFT, @@ -958,7 +943,6 @@ static struct clk sys_clkout2 = { .name = "sys_clkout2", .ops = &clkops_null, .parent = &sys_clkout2_src, - .flags = CLOCK_IN_OMAP242X, .clkdm_name = "wkup_clkdm", .clksel_reg = OMAP24XX_PRCM_CLKOUT_CTRL, .clksel_mask = OMAP2420_CLKOUT2_DIV_MASK, @@ -972,7 +956,6 @@ static struct clk emul_ck = { .name = "emul_ck", .ops = &clkops_omap2_dflt, .parent = &func_54m_ck, - .flags = CLOCK_IN_OMAP242X, .clkdm_name = "wkup_clkdm", .enable_reg = OMAP24XX_PRCM_CLKEMUL_CTRL, .enable_bit = OMAP24XX_EMULATION_EN_SHIFT, @@ -1008,9 +991,7 @@ static struct clk mpu_ck = { /* Control cpu */ .name = "mpu_ck", .ops = &clkops_null, .parent = &core_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - DELAYED_APP | - CONFIG_PARTICIPANT | RATE_PROPAGATES, + .flags = DELAYED_APP | CONFIG_PARTICIPANT | RATE_PROPAGATES, .clkdm_name = "mpu_clkdm", .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL), @@ -1052,8 +1033,7 @@ static struct clk dsp_fck = { .name = "dsp_fck", .ops = &clkops_omap2_dflt_wait, .parent = &core_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP | - CONFIG_PARTICIPANT | RATE_PROPAGATES, + .flags = DELAYED_APP | CONFIG_PARTICIPANT | RATE_PROPAGATES, .clkdm_name = "dsp_clkdm", .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN), .enable_bit = OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT, @@ -1083,8 +1063,7 @@ static struct clk dsp_irate_ick = { .name = "dsp_irate_ick", .ops = &clkops_null, .parent = &dsp_fck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP | - CONFIG_PARTICIPANT, + .flags = DELAYED_APP | CONFIG_PARTICIPANT, .clksel_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL), .clksel_mask = OMAP24XX_CLKSEL_DSP_IF_MASK, .clksel = dsp_irate_ick_clksel, @@ -1098,7 +1077,7 @@ static struct clk dsp_ick = { .name = "dsp_ick", /* apparently ipi and isp */ .ops = &clkops_omap2_dflt_wait, .parent = &dsp_irate_ick, - .flags = CLOCK_IN_OMAP242X | DELAYED_APP | CONFIG_PARTICIPANT, + .flags = DELAYED_APP | CONFIG_PARTICIPANT, .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_ICLKEN), .enable_bit = OMAP2420_EN_DSP_IPI_SHIFT, /* for ipi */ }; @@ -1108,7 +1087,7 @@ static struct clk iva2_1_ick = { .name = "iva2_1_ick", .ops = &clkops_omap2_dflt_wait, .parent = &dsp_irate_ick, - .flags = CLOCK_IN_OMAP243X | DELAYED_APP | CONFIG_PARTICIPANT, + .flags = DELAYED_APP | CONFIG_PARTICIPANT, .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN), .enable_bit = OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT, }; @@ -1122,8 +1101,7 @@ static struct clk iva1_ifck = { .name = "iva1_ifck", .ops = &clkops_omap2_dflt_wait, .parent = &core_ck, - .flags = CLOCK_IN_OMAP242X | CONFIG_PARTICIPANT | - RATE_PROPAGATES | DELAYED_APP, + .flags = CONFIG_PARTICIPANT | RATE_PROPAGATES | DELAYED_APP, .clkdm_name = "iva1_clkdm", .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN), .enable_bit = OMAP2420_EN_IVA_COP_SHIFT, @@ -1140,7 +1118,6 @@ static struct clk iva1_mpu_int_ifck = { .name = "iva1_mpu_int_ifck", .ops = &clkops_omap2_dflt_wait, .parent = &iva1_ifck, - .flags = CLOCK_IN_OMAP242X, .clkdm_name = "iva1_clkdm", .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN), .enable_bit = OMAP2420_EN_IVA_MPU_SHIFT, @@ -1187,9 +1164,7 @@ static struct clk core_l3_ck = { /* Used for ick and fck, interconnect */ .name = "core_l3_ck", .ops = &clkops_null, .parent = &core_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - DELAYED_APP | - CONFIG_PARTICIPANT | RATE_PROPAGATES, + .flags = DELAYED_APP | CONFIG_PARTICIPANT | RATE_PROPAGATES, .clkdm_name = "core_l3_clkdm", .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1), .clksel_mask = OMAP24XX_CLKSEL_L3_MASK, @@ -1217,8 +1192,7 @@ static struct clk usb_l4_ick = { /* FS-USB interface clock */ .name = "usb_l4_ick", .ops = &clkops_omap2_dflt_wait, .parent = &core_l3_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - DELAYED_APP | CONFIG_PARTICIPANT, + .flags = DELAYED_APP | CONFIG_PARTICIPANT, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP24XX_EN_USB_SHIFT, @@ -1252,8 +1226,7 @@ static struct clk l4_ck = { /* used both as an ick and fck */ .name = "l4_ck", .ops = &clkops_null, .parent = &core_l3_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - DELAYED_APP | RATE_PROPAGATES, + .flags = DELAYED_APP | RATE_PROPAGATES, .clkdm_name = "core_l4_clkdm", .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1), .clksel_mask = OMAP24XX_CLKSEL_L4_MASK, @@ -1291,8 +1264,7 @@ static struct clk ssi_ssr_sst_fck = { .name = "ssi_fck", .ops = &clkops_omap2_dflt_wait, .parent = &core_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - DELAYED_APP, + .flags = DELAYED_APP, .clkdm_name = "core_l3_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP24XX_EN_SSI_SHIFT, @@ -1328,7 +1300,6 @@ static struct clk gfx_3d_fck = { .name = "gfx_3d_fck", .ops = &clkops_omap2_dflt_wait, .parent = &core_l3_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "gfx_clkdm", .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN), .enable_bit = OMAP24XX_EN_3D_SHIFT, @@ -1344,7 +1315,6 @@ static struct clk gfx_2d_fck = { .name = "gfx_2d_fck", .ops = &clkops_omap2_dflt_wait, .parent = &core_l3_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "gfx_clkdm", .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN), .enable_bit = OMAP24XX_EN_2D_SHIFT, @@ -1360,7 +1330,6 @@ static struct clk gfx_ick = { .name = "gfx_ick", /* From l3 */ .ops = &clkops_omap2_dflt_wait, .parent = &core_l3_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "gfx_clkdm", .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN), .enable_bit = OMAP_EN_GFX_SHIFT, @@ -1391,7 +1360,7 @@ static struct clk mdm_ick = { /* used both as a ick and fck */ .name = "mdm_ick", .ops = &clkops_omap2_dflt_wait, .parent = &core_ck, - .flags = CLOCK_IN_OMAP243X | DELAYED_APP | CONFIG_PARTICIPANT, + .flags = DELAYED_APP | CONFIG_PARTICIPANT, .clkdm_name = "mdm_clkdm", .enable_reg = OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_ICLKEN), .enable_bit = OMAP2430_CM_ICLKEN_MDM_EN_MDM_SHIFT, @@ -1407,7 +1376,6 @@ static struct clk mdm_osc_ck = { .name = "mdm_osc_ck", .ops = &clkops_omap2_dflt_wait, .parent = &osc_ck, - .flags = CLOCK_IN_OMAP243X, .clkdm_name = "mdm_clkdm", .enable_reg = OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_FCLKEN), .enable_bit = OMAP2430_EN_OSC_SHIFT, @@ -1453,7 +1421,6 @@ static struct clk dss_ick = { /* Enables both L3,L4 ICLK's */ .name = "dss_ick", .ops = &clkops_omap2_dflt, .parent = &l4_ck, /* really both l3 and l4 */ - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "dss_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_DSS1_SHIFT, @@ -1464,8 +1431,7 @@ static struct clk dss1_fck = { .name = "dss1_fck", .ops = &clkops_omap2_dflt, .parent = &core_ck, /* Core or sys */ - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - DELAYED_APP, + .flags = DELAYED_APP, .clkdm_name = "dss_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_DSS1_SHIFT, @@ -1498,8 +1464,7 @@ static struct clk dss2_fck = { /* Alt clk used in power management */ .name = "dss2_fck", .ops = &clkops_omap2_dflt, .parent = &sys_ck, /* fixed at sys_ck or 48MHz */ - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - DELAYED_APP, + .flags = DELAYED_APP, .clkdm_name = "dss_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_DSS2_SHIFT, @@ -1514,7 +1479,6 @@ static struct clk dss_54m_fck = { /* Alt clk used in power management */ .name = "dss_54m_fck", /* 54m tv clk */ .ops = &clkops_omap2_dflt_wait, .parent = &func_54m_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "dss_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_TV_SHIFT, @@ -1543,7 +1507,6 @@ static struct clk gpt1_ick = { .name = "gpt1_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_GPT1_SHIFT, @@ -1554,7 +1517,6 @@ static struct clk gpt1_fck = { .name = "gpt1_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), .enable_bit = OMAP24XX_EN_GPT1_SHIFT, @@ -1571,7 +1533,6 @@ static struct clk gpt2_ick = { .name = "gpt2_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT2_SHIFT, @@ -1582,7 +1543,6 @@ static struct clk gpt2_fck = { .name = "gpt2_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_GPT2_SHIFT, @@ -1597,7 +1557,6 @@ static struct clk gpt3_ick = { .name = "gpt3_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT3_SHIFT, @@ -1608,7 +1567,6 @@ static struct clk gpt3_fck = { .name = "gpt3_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_GPT3_SHIFT, @@ -1623,7 +1581,6 @@ static struct clk gpt4_ick = { .name = "gpt4_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT4_SHIFT, @@ -1634,7 +1591,6 @@ static struct clk gpt4_fck = { .name = "gpt4_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_GPT4_SHIFT, @@ -1649,7 +1605,6 @@ static struct clk gpt5_ick = { .name = "gpt5_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT5_SHIFT, @@ -1660,7 +1615,6 @@ static struct clk gpt5_fck = { .name = "gpt5_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_GPT5_SHIFT, @@ -1675,7 +1629,6 @@ static struct clk gpt6_ick = { .name = "gpt6_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT6_SHIFT, @@ -1686,7 +1639,6 @@ static struct clk gpt6_fck = { .name = "gpt6_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_GPT6_SHIFT, @@ -1701,7 +1653,6 @@ static struct clk gpt7_ick = { .name = "gpt7_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT7_SHIFT, .recalc = &followparent_recalc, @@ -1711,7 +1662,6 @@ static struct clk gpt7_fck = { .name = "gpt7_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_GPT7_SHIFT, @@ -1726,7 +1676,6 @@ static struct clk gpt8_ick = { .name = "gpt8_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT8_SHIFT, @@ -1737,7 +1686,6 @@ static struct clk gpt8_fck = { .name = "gpt8_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_GPT8_SHIFT, @@ -1752,7 +1700,6 @@ static struct clk gpt9_ick = { .name = "gpt9_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT9_SHIFT, @@ -1763,7 +1710,6 @@ static struct clk gpt9_fck = { .name = "gpt9_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_GPT9_SHIFT, @@ -1778,7 +1724,6 @@ static struct clk gpt10_ick = { .name = "gpt10_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT10_SHIFT, @@ -1789,7 +1734,6 @@ static struct clk gpt10_fck = { .name = "gpt10_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_GPT10_SHIFT, @@ -1804,7 +1748,6 @@ static struct clk gpt11_ick = { .name = "gpt11_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT11_SHIFT, @@ -1815,7 +1758,6 @@ static struct clk gpt11_fck = { .name = "gpt11_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_GPT11_SHIFT, @@ -1830,7 +1772,6 @@ static struct clk gpt12_ick = { .name = "gpt12_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT12_SHIFT, @@ -1841,7 +1782,6 @@ static struct clk gpt12_fck = { .name = "gpt12_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_GPT12_SHIFT, @@ -1857,7 +1797,6 @@ static struct clk mcbsp1_ick = { .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_MCBSP1_SHIFT, @@ -1869,7 +1808,6 @@ static struct clk mcbsp1_fck = { .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &func_96m_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_MCBSP1_SHIFT, @@ -1881,7 +1819,6 @@ static struct clk mcbsp2_ick = { .ops = &clkops_omap2_dflt_wait, .id = 2, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_MCBSP2_SHIFT, @@ -1893,7 +1830,6 @@ static struct clk mcbsp2_fck = { .ops = &clkops_omap2_dflt_wait, .id = 2, .parent = &func_96m_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_MCBSP2_SHIFT, @@ -1905,7 +1841,6 @@ static struct clk mcbsp3_ick = { .ops = &clkops_omap2_dflt_wait, .id = 3, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP2430_EN_MCBSP3_SHIFT, @@ -1917,7 +1852,6 @@ static struct clk mcbsp3_fck = { .ops = &clkops_omap2_dflt_wait, .id = 3, .parent = &func_96m_ck, - .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP2430_EN_MCBSP3_SHIFT, @@ -1929,7 +1863,6 @@ static struct clk mcbsp4_ick = { .ops = &clkops_omap2_dflt_wait, .id = 4, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP2430_EN_MCBSP4_SHIFT, @@ -1941,7 +1874,6 @@ static struct clk mcbsp4_fck = { .ops = &clkops_omap2_dflt_wait, .id = 4, .parent = &func_96m_ck, - .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP2430_EN_MCBSP4_SHIFT, @@ -1953,7 +1885,6 @@ static struct clk mcbsp5_ick = { .ops = &clkops_omap2_dflt_wait, .id = 5, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP2430_EN_MCBSP5_SHIFT, @@ -1965,7 +1896,6 @@ static struct clk mcbsp5_fck = { .ops = &clkops_omap2_dflt_wait, .id = 5, .parent = &func_96m_ck, - .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP2430_EN_MCBSP5_SHIFT, @@ -1978,7 +1908,6 @@ static struct clk mcspi1_ick = { .id = 1, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_MCSPI1_SHIFT, .recalc = &followparent_recalc, @@ -1989,7 +1918,6 @@ static struct clk mcspi1_fck = { .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &func_48m_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_MCSPI1_SHIFT, @@ -2001,7 +1929,6 @@ static struct clk mcspi2_ick = { .ops = &clkops_omap2_dflt_wait, .id = 2, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_MCSPI2_SHIFT, @@ -2013,7 +1940,6 @@ static struct clk mcspi2_fck = { .ops = &clkops_omap2_dflt_wait, .id = 2, .parent = &func_48m_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_MCSPI2_SHIFT, @@ -2025,7 +1951,6 @@ static struct clk mcspi3_ick = { .ops = &clkops_omap2_dflt_wait, .id = 3, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP2430_EN_MCSPI3_SHIFT, @@ -2037,7 +1962,6 @@ static struct clk mcspi3_fck = { .ops = &clkops_omap2_dflt_wait, .id = 3, .parent = &func_48m_ck, - .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP2430_EN_MCSPI3_SHIFT, @@ -2048,7 +1972,6 @@ static struct clk uart1_ick = { .name = "uart1_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_UART1_SHIFT, @@ -2059,7 +1982,6 @@ static struct clk uart1_fck = { .name = "uart1_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_48m_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_UART1_SHIFT, @@ -2070,7 +1992,6 @@ static struct clk uart2_ick = { .name = "uart2_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_UART2_SHIFT, @@ -2081,7 +2002,6 @@ static struct clk uart2_fck = { .name = "uart2_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_48m_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_UART2_SHIFT, @@ -2092,7 +2012,6 @@ static struct clk uart3_ick = { .name = "uart3_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP24XX_EN_UART3_SHIFT, @@ -2103,7 +2022,6 @@ static struct clk uart3_fck = { .name = "uart3_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_48m_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP24XX_EN_UART3_SHIFT, @@ -2114,7 +2032,6 @@ static struct clk gpios_ick = { .name = "gpios_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_GPIOS_SHIFT, @@ -2125,7 +2042,6 @@ static struct clk gpios_fck = { .name = "gpios_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), .enable_bit = OMAP24XX_EN_GPIOS_SHIFT, @@ -2136,7 +2052,6 @@ static struct clk mpu_wdt_ick = { .name = "mpu_wdt_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_MPU_WDT_SHIFT, @@ -2147,7 +2062,6 @@ static struct clk mpu_wdt_fck = { .name = "mpu_wdt_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), .enable_bit = OMAP24XX_EN_MPU_WDT_SHIFT, @@ -2158,8 +2072,7 @@ static struct clk sync_32k_ick = { .name = "sync_32k_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - ENABLE_ON_INIT, + .flags = ENABLE_ON_INIT, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_32KSYNC_SHIFT, @@ -2170,7 +2083,6 @@ static struct clk wdt1_ick = { .name = "wdt1_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_WDT1_SHIFT, @@ -2181,8 +2093,7 @@ static struct clk omapctrl_ick = { .name = "omapctrl_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - ENABLE_ON_INIT, + .flags = ENABLE_ON_INIT, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_OMAPCTRL_SHIFT, @@ -2193,7 +2104,6 @@ static struct clk icr_ick = { .name = "icr_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP2430_EN_ICR_SHIFT, @@ -2204,7 +2114,6 @@ static struct clk cam_ick = { .name = "cam_ick", .ops = &clkops_omap2_dflt, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_CAM_SHIFT, @@ -2220,7 +2129,6 @@ static struct clk cam_fck = { .name = "cam_fck", .ops = &clkops_omap2_dflt, .parent = &func_96m_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l3_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_CAM_SHIFT, @@ -2231,7 +2139,6 @@ static struct clk mailboxes_ick = { .name = "mailboxes_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_MAILBOXES_SHIFT, @@ -2242,7 +2149,6 @@ static struct clk wdt4_ick = { .name = "wdt4_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_WDT4_SHIFT, @@ -2253,7 +2159,6 @@ static struct clk wdt4_fck = { .name = "wdt4_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_WDT4_SHIFT, @@ -2264,7 +2169,6 @@ static struct clk wdt3_ick = { .name = "wdt3_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP2420_EN_WDT3_SHIFT, @@ -2275,7 +2179,6 @@ static struct clk wdt3_fck = { .name = "wdt3_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, - .flags = CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP2420_EN_WDT3_SHIFT, @@ -2286,7 +2189,6 @@ static struct clk mspro_ick = { .name = "mspro_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_MSPRO_SHIFT, @@ -2297,7 +2199,6 @@ static struct clk mspro_fck = { .name = "mspro_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_96m_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_MSPRO_SHIFT, @@ -2308,7 +2209,6 @@ static struct clk mmc_ick = { .name = "mmc_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP2420_EN_MMC_SHIFT, @@ -2319,7 +2219,6 @@ static struct clk mmc_fck = { .name = "mmc_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_96m_ck, - .flags = CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP2420_EN_MMC_SHIFT, @@ -2330,7 +2229,6 @@ static struct clk fac_ick = { .name = "fac_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_FAC_SHIFT, @@ -2341,7 +2239,6 @@ static struct clk fac_fck = { .name = "fac_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_12m_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_FAC_SHIFT, @@ -2352,7 +2249,6 @@ static struct clk eac_ick = { .name = "eac_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP2420_EN_EAC_SHIFT, @@ -2363,7 +2259,6 @@ static struct clk eac_fck = { .name = "eac_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_96m_ck, - .flags = CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP2420_EN_EAC_SHIFT, @@ -2374,7 +2269,6 @@ static struct clk hdq_ick = { .name = "hdq_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_HDQ_SHIFT, @@ -2385,7 +2279,6 @@ static struct clk hdq_fck = { .name = "hdq_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_12m_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_HDQ_SHIFT, @@ -2397,7 +2290,6 @@ static struct clk i2c2_ick = { .ops = &clkops_omap2_dflt_wait, .id = 2, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP2420_EN_I2C2_SHIFT, @@ -2409,7 +2301,6 @@ static struct clk i2c2_fck = { .ops = &clkops_omap2_dflt_wait, .id = 2, .parent = &func_12m_ck, - .flags = CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP2420_EN_I2C2_SHIFT, @@ -2421,7 +2312,6 @@ static struct clk i2chs2_fck = { .ops = &clkops_omap2_dflt_wait, .id = 2, .parent = &func_96m_ck, - .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP2430_EN_I2CHS2_SHIFT, @@ -2433,7 +2323,6 @@ static struct clk i2c1_ick = { .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP2420_EN_I2C1_SHIFT, @@ -2445,7 +2334,6 @@ static struct clk i2c1_fck = { .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &func_12m_ck, - .flags = CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP2420_EN_I2C1_SHIFT, @@ -2457,7 +2345,6 @@ static struct clk i2chs1_fck = { .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &func_96m_ck, - .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP2430_EN_I2CHS1_SHIFT, @@ -2468,8 +2355,7 @@ static struct clk gpmc_fck = { .name = "gpmc_fck", .ops = &clkops_null, /* RMK: missing? */ .parent = &core_l3_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - ENABLE_ON_INIT, + .flags = ENABLE_ON_INIT, .clkdm_name = "core_l3_clkdm", .recalc = &followparent_recalc, }; @@ -2478,7 +2364,6 @@ static struct clk sdma_fck = { .name = "sdma_fck", .ops = &clkops_null, /* RMK: missing? */ .parent = &core_l3_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l3_clkdm", .recalc = &followparent_recalc, }; @@ -2487,7 +2372,6 @@ static struct clk sdma_ick = { .name = "sdma_ick", .ops = &clkops_null, /* RMK: missing? */ .parent = &l4_ck, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .clkdm_name = "core_l3_clkdm", .recalc = &followparent_recalc, }; @@ -2496,7 +2380,6 @@ static struct clk vlynq_ick = { .name = "vlynq_ick", .ops = &clkops_omap2_dflt_wait, .parent = &core_l3_ck, - .flags = CLOCK_IN_OMAP242X, .clkdm_name = "core_l3_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP2420_EN_VLYNQ_SHIFT, @@ -2532,7 +2415,7 @@ static struct clk vlynq_fck = { .name = "vlynq_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_96m_ck, - .flags = CLOCK_IN_OMAP242X | DELAYED_APP, + .flags = DELAYED_APP, .clkdm_name = "core_l3_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP2420_EN_VLYNQ_SHIFT, @@ -2549,7 +2432,7 @@ static struct clk sdrc_ick = { .name = "sdrc_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP243X | ENABLE_ON_INIT, + .flags = ENABLE_ON_INIT, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3), .enable_bit = OMAP2430_EN_SDRC_SHIFT, @@ -2560,7 +2443,6 @@ static struct clk des_ick = { .name = "des_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4), .enable_bit = OMAP24XX_EN_DES_SHIFT, @@ -2571,7 +2453,6 @@ static struct clk sha_ick = { .name = "sha_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4), .enable_bit = OMAP24XX_EN_SHA_SHIFT, @@ -2582,7 +2463,6 @@ static struct clk rng_ick = { .name = "rng_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4), .enable_bit = OMAP24XX_EN_RNG_SHIFT, @@ -2593,7 +2473,6 @@ static struct clk aes_ick = { .name = "aes_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4), .enable_bit = OMAP24XX_EN_AES_SHIFT, @@ -2604,7 +2483,6 @@ static struct clk pka_ick = { .name = "pka_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4), .enable_bit = OMAP24XX_EN_PKA_SHIFT, @@ -2615,7 +2493,6 @@ static struct clk usb_fck = { .name = "usb_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_48m_ck, - .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X, .clkdm_name = "core_l3_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP24XX_EN_USB_SHIFT, @@ -2626,7 +2503,6 @@ static struct clk usbhs_ick = { .name = "usbhs_ick", .ops = &clkops_omap2_dflt_wait, .parent = &core_l3_ck, - .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l3_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP2430_EN_USBHS_SHIFT, @@ -2637,7 +2513,6 @@ static struct clk mmchs1_ick = { .name = "mmchs_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP2430_EN_MMCHS1_SHIFT, @@ -2648,7 +2523,6 @@ static struct clk mmchs1_fck = { .name = "mmchs_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_96m_ck, - .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l3_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP2430_EN_MMCHS1_SHIFT, @@ -2660,7 +2534,6 @@ static struct clk mmchs2_ick = { .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP2430_EN_MMCHS2_SHIFT, @@ -2672,7 +2545,6 @@ static struct clk mmchs2_fck = { .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &func_96m_ck, - .flags = CLOCK_IN_OMAP243X, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP2430_EN_MMCHS2_SHIFT, .recalc = &followparent_recalc, @@ -2682,7 +2554,6 @@ static struct clk gpio5_ick = { .name = "gpio5_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP2430_EN_GPIO5_SHIFT, @@ -2693,7 +2564,6 @@ static struct clk gpio5_fck = { .name = "gpio5_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, - .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP2430_EN_GPIO5_SHIFT, @@ -2704,7 +2574,6 @@ static struct clk mdm_intc_ick = { .name = "mdm_intc_ick", .ops = &clkops_omap2_dflt_wait, .parent = &l4_ck, - .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP2430_EN_MDM_INTC_SHIFT, @@ -2715,7 +2584,6 @@ static struct clk mmchsdb1_fck = { .name = "mmchsdb_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_32k_ck, - .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP2430_EN_MMCHSDB1_SHIFT, @@ -2727,7 +2595,6 @@ static struct clk mmchsdb2_fck = { .ops = &clkops_omap2_dflt_wait, .id = 1, .parent = &func_32k_ck, - .flags = CLOCK_IN_OMAP243X, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP2430_EN_MMCHSDB2_SHIFT, @@ -2751,166 +2618,12 @@ static struct clk mmchsdb2_fck = { static struct clk virt_prcm_set = { .name = "virt_prcm_set", .ops = &clkops_null, - .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - DELAYED_APP, + .flags = DELAYED_APP, .parent = &mpu_ck, /* Indexed by mpu speed, no parent */ .recalc = &omap2_table_mpu_recalc, /* sets are keyed on mpu rate */ .set_rate = &omap2_select_table_rate, .round_rate = &omap2_round_to_table_rate, }; -static struct clk *onchip_24xx_clks[] __initdata = { - /* external root sources */ - &func_32k_ck, - &osc_ck, - &sys_ck, - &alt_ck, - /* internal analog sources */ - &dpll_ck, - &apll96_ck, - &apll54_ck, - /* internal prcm root sources */ - &func_54m_ck, - &core_ck, - &func_96m_ck, - &func_48m_ck, - &func_12m_ck, - &wdt1_osc_ck, - &sys_clkout_src, - &sys_clkout, - &sys_clkout2_src, - &sys_clkout2, - &emul_ck, - /* mpu domain clocks */ - &mpu_ck, - /* dsp domain clocks */ - &dsp_fck, - &dsp_irate_ick, - &dsp_ick, /* 242x */ - &iva2_1_ick, /* 243x */ - &iva1_ifck, /* 242x */ - &iva1_mpu_int_ifck, /* 242x */ - /* GFX domain clocks */ - &gfx_3d_fck, - &gfx_2d_fck, - &gfx_ick, - /* Modem domain clocks */ - &mdm_ick, - &mdm_osc_ck, - /* DSS domain clocks */ - &dss_ick, - &dss1_fck, - &dss2_fck, - &dss_54m_fck, - /* L3 domain clocks */ - &core_l3_ck, - &ssi_ssr_sst_fck, - &usb_l4_ick, - /* L4 domain clocks */ - &l4_ck, /* used as both core_l4 and wu_l4 */ - /* virtual meta-group clock */ - &virt_prcm_set, - /* general l4 interface ck, multi-parent functional clk */ - &gpt1_ick, - &gpt1_fck, - &gpt2_ick, - &gpt2_fck, - &gpt3_ick, - &gpt3_fck, - &gpt4_ick, - &gpt4_fck, - &gpt5_ick, - &gpt5_fck, - &gpt6_ick, - &gpt6_fck, - &gpt7_ick, - &gpt7_fck, - &gpt8_ick, - &gpt8_fck, - &gpt9_ick, - &gpt9_fck, - &gpt10_ick, - &gpt10_fck, - &gpt11_ick, - &gpt11_fck, - &gpt12_ick, - &gpt12_fck, - &mcbsp1_ick, - &mcbsp1_fck, - &mcbsp2_ick, - &mcbsp2_fck, - &mcbsp3_ick, - &mcbsp3_fck, - &mcbsp4_ick, - &mcbsp4_fck, - &mcbsp5_ick, - &mcbsp5_fck, - &mcspi1_ick, - &mcspi1_fck, - &mcspi2_ick, - &mcspi2_fck, - &mcspi3_ick, - &mcspi3_fck, - &uart1_ick, - &uart1_fck, - &uart2_ick, - &uart2_fck, - &uart3_ick, - &uart3_fck, - &gpios_ick, - &gpios_fck, - &mpu_wdt_ick, - &mpu_wdt_fck, - &sync_32k_ick, - &wdt1_ick, - &omapctrl_ick, - &icr_ick, - &cam_fck, - &cam_ick, - &mailboxes_ick, - &wdt4_ick, - &wdt4_fck, - &wdt3_ick, - &wdt3_fck, - &mspro_ick, - &mspro_fck, - &mmc_ick, - &mmc_fck, - &fac_ick, - &fac_fck, - &eac_ick, - &eac_fck, - &hdq_ick, - &hdq_fck, - &i2c1_ick, - &i2c1_fck, - &i2chs1_fck, - &i2c2_ick, - &i2c2_fck, - &i2chs2_fck, - &gpmc_fck, - &sdma_fck, - &sdma_ick, - &vlynq_ick, - &vlynq_fck, - &sdrc_ick, - &des_ick, - &sha_ick, - &rng_ick, - &aes_ick, - &pka_ick, - &usb_fck, - &usbhs_ick, - &mmchs1_ick, - &mmchs1_fck, - &mmchs2_ick, - &mmchs2_fck, - &gpio5_ick, - &gpio5_fck, - &mdm_intc_ick, - &mmchsdb1_fck, - &mmchsdb2_fck, -}; - #endif diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index fc7b6831f3e..90372131055 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -16,6 +16,7 @@ config ARCH_OMAP1 config ARCH_OMAP2 bool "TI OMAP2" select CPU_V6 + select COMMON_CLKDEV config ARCH_OMAP3 bool "TI OMAP3" diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index 2af4bc24cfe..214dc46d6ad 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -136,9 +136,7 @@ extern const struct clkops clkops_null; #define CONFIG_PARTICIPANT (1 << 10) /* Fundamental clock */ #define ENABLE_ON_INIT (1 << 11) /* Enable upon framework init */ #define INVERT_ENABLE (1 << 12) /* 0 enables, 1 disables */ -/* bits 13-24 are currently free */ -#define CLOCK_IN_OMAP242X (1 << 25) -#define CLOCK_IN_OMAP243X (1 << 26) +/* bits 13-26 are currently free */ #define CLOCK_IN_OMAP343X (1 << 27) /* clocks common to all 343X */ #define CLOCK_IN_OMAP3430ES1 (1 << 29) /* 3430ES1 clocks only */ #define CLOCK_IN_OMAP3430ES2 (1 << 30) /* 3430ES2 clocks only */ -- GitLab From 44dc9d027f1cb56625b1011d8725d2ab614c04e6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 19 Jan 2009 15:51:11 +0000 Subject: [PATCH 1347/4982] [ARM] omap: convert OMAP3 to use clkdev Signed-off-by: Russell King --- arch/arm/mach-omap2/clock34xx.c | 268 +++++++++++-- arch/arm/mach-omap2/clock34xx.h | 513 ++++-------------------- arch/arm/plat-omap/Kconfig | 1 + arch/arm/plat-omap/include/mach/clock.h | 5 +- 4 files changed, 331 insertions(+), 456 deletions(-) diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 52698fb4fd0..2c22750016c 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "memory.h" #include "clock.h" @@ -42,6 +43,240 @@ static const struct clkops clkops_noncore_dpll_ops; #include "clock34xx.h" +struct omap_clk { + u32 cpu; + struct clk_lookup lk; +}; + +#define CLK(dev, con, ck, cp) \ + { \ + .cpu = cp, \ + .lk = { \ + .dev_id = dev, \ + .con_id = con, \ + .clk = ck, \ + }, \ + } + +#define CK_343X (1 << 0) +#define CK_3430ES1 (1 << 1) +#define CK_3430ES2 (1 << 2) + +static struct omap_clk omap34xx_clks[] = { + CLK(NULL, "omap_32k_fck", &omap_32k_fck, CK_343X), + CLK(NULL, "virt_12m_ck", &virt_12m_ck, CK_343X), + CLK(NULL, "virt_13m_ck", &virt_13m_ck, CK_343X), + CLK(NULL, "virt_16_8m_ck", &virt_16_8m_ck, CK_3430ES2), + CLK(NULL, "virt_19_2m_ck", &virt_19_2m_ck, CK_343X), + CLK(NULL, "virt_26m_ck", &virt_26m_ck, CK_343X), + CLK(NULL, "virt_38_4m_ck", &virt_38_4m_ck, CK_343X), + CLK(NULL, "osc_sys_ck", &osc_sys_ck, CK_343X), + CLK(NULL, "sys_ck", &sys_ck, CK_343X), + CLK(NULL, "sys_altclk", &sys_altclk, CK_343X), + CLK(NULL, "mcbsp_clks", &mcbsp_clks, CK_343X), + CLK(NULL, "sys_clkout1", &sys_clkout1, CK_343X), + CLK(NULL, "dpll1_ck", &dpll1_ck, CK_343X), + CLK(NULL, "dpll1_x2_ck", &dpll1_x2_ck, CK_343X), + CLK(NULL, "dpll1_x2m2_ck", &dpll1_x2m2_ck, CK_343X), + CLK(NULL, "dpll2_ck", &dpll2_ck, CK_343X), + CLK(NULL, "dpll2_m2_ck", &dpll2_m2_ck, CK_343X), + CLK(NULL, "dpll3_ck", &dpll3_ck, CK_343X), + CLK(NULL, "core_ck", &core_ck, CK_343X), + CLK(NULL, "dpll3_x2_ck", &dpll3_x2_ck, CK_343X), + CLK(NULL, "dpll3_m2_ck", &dpll3_m2_ck, CK_343X), + CLK(NULL, "dpll3_m2x2_ck", &dpll3_m2x2_ck, CK_343X), + CLK(NULL, "dpll3_m3_ck", &dpll3_m3_ck, CK_343X), + CLK(NULL, "dpll3_m3x2_ck", &dpll3_m3x2_ck, CK_343X), + CLK(NULL, "emu_core_alwon_ck", &emu_core_alwon_ck, CK_343X), + CLK(NULL, "dpll4_ck", &dpll4_ck, CK_343X), + CLK(NULL, "dpll4_x2_ck", &dpll4_x2_ck, CK_343X), + CLK(NULL, "omap_96m_alwon_fck", &omap_96m_alwon_fck, CK_343X), + CLK(NULL, "omap_96m_fck", &omap_96m_fck, CK_343X), + CLK(NULL, "cm_96m_fck", &cm_96m_fck, CK_343X), + CLK(NULL, "virt_omap_54m_fck", &virt_omap_54m_fck, CK_343X), + CLK(NULL, "omap_54m_fck", &omap_54m_fck, CK_343X), + CLK(NULL, "omap_48m_fck", &omap_48m_fck, CK_343X), + CLK(NULL, "omap_12m_fck", &omap_12m_fck, CK_343X), + CLK(NULL, "dpll4_m2_ck", &dpll4_m2_ck, CK_343X), + CLK(NULL, "dpll4_m2x2_ck", &dpll4_m2x2_ck, CK_343X), + CLK(NULL, "dpll4_m3_ck", &dpll4_m3_ck, CK_343X), + CLK(NULL, "dpll4_m3x2_ck", &dpll4_m3x2_ck, CK_343X), + CLK(NULL, "dpll4_m4_ck", &dpll4_m4_ck, CK_343X), + CLK(NULL, "dpll4_m4x2_ck", &dpll4_m4x2_ck, CK_343X), + CLK(NULL, "dpll4_m5_ck", &dpll4_m5_ck, CK_343X), + CLK(NULL, "dpll4_m5x2_ck", &dpll4_m5x2_ck, CK_343X), + CLK(NULL, "dpll4_m6_ck", &dpll4_m6_ck, CK_343X), + CLK(NULL, "dpll4_m6x2_ck", &dpll4_m6x2_ck, CK_343X), + CLK(NULL, "emu_per_alwon_ck", &emu_per_alwon_ck, CK_343X), + CLK(NULL, "dpll5_ck", &dpll5_ck, CK_3430ES2), + CLK(NULL, "dpll5_m2_ck", &dpll5_m2_ck, CK_3430ES2), + CLK(NULL, "omap_120m_fck", &omap_120m_fck, CK_3430ES2), + CLK(NULL, "clkout2_src_ck", &clkout2_src_ck, CK_343X), + CLK(NULL, "sys_clkout2", &sys_clkout2, CK_343X), + CLK(NULL, "corex2_fck", &corex2_fck, CK_343X), + CLK(NULL, "dpll1_fck", &dpll1_fck, CK_343X), + CLK(NULL, "mpu_ck", &mpu_ck, CK_343X), + CLK(NULL, "arm_fck", &arm_fck, CK_343X), + CLK(NULL, "emu_mpu_alwon_ck", &emu_mpu_alwon_ck, CK_343X), + CLK(NULL, "dpll2_fck", &dpll2_fck, CK_343X), + CLK(NULL, "iva2_ck", &iva2_ck, CK_343X), + CLK(NULL, "l3_ick", &l3_ick, CK_343X), + CLK(NULL, "l4_ick", &l4_ick, CK_343X), + CLK(NULL, "rm_ick", &rm_ick, CK_343X), + CLK(NULL, "gfx_l3_ck", &gfx_l3_ck, CK_3430ES1), + CLK(NULL, "gfx_l3_fck", &gfx_l3_fck, CK_3430ES1), + CLK(NULL, "gfx_l3_ick", &gfx_l3_ick, CK_3430ES1), + CLK(NULL, "gfx_cg1_ck", &gfx_cg1_ck, CK_3430ES1), + CLK(NULL, "gfx_cg2_ck", &gfx_cg2_ck, CK_3430ES1), + CLK(NULL, "sgx_fck", &sgx_fck, CK_3430ES2), + CLK(NULL, "sgx_ick", &sgx_ick, CK_3430ES2), + CLK(NULL, "d2d_26m_fck", &d2d_26m_fck, CK_3430ES1), + CLK(NULL, "gpt10_fck", &gpt10_fck, CK_343X), + CLK(NULL, "gpt11_fck", &gpt11_fck, CK_343X), + CLK(NULL, "cpefuse_fck", &cpefuse_fck, CK_3430ES2), + CLK(NULL, "ts_fck", &ts_fck, CK_3430ES2), + CLK(NULL, "usbtll_fck", &usbtll_fck, CK_3430ES2), + CLK(NULL, "core_96m_fck", &core_96m_fck, CK_343X), + CLK("mmci-omap-hs.2", "mmchs_fck", &mmchs3_fck, CK_3430ES2), + CLK("mmci-omap-hs.1", "mmchs_fck", &mmchs2_fck, CK_343X), + CLK(NULL, "mspro_fck", &mspro_fck, CK_343X), + CLK("mmci-omap-hs.0", "mmchs_fck", &mmchs1_fck, CK_343X), + CLK("i2c_omap.3", "i2c_fck", &i2c3_fck, CK_343X), + CLK("i2c_omap.2", "i2c_fck", &i2c2_fck, CK_343X), + CLK("i2c_omap.1", "i2c_fck", &i2c1_fck, CK_343X), + CLK("omap-mcbsp.5", "mcbsp_fck", &mcbsp5_fck, CK_343X), + CLK("omap-mcbsp.1", "mcbsp_fck", &mcbsp1_fck, CK_343X), + CLK(NULL, "core_48m_fck", &core_48m_fck, CK_343X), + CLK("omap2_mcspi.4", "mcspi_fck", &mcspi4_fck, CK_343X), + CLK("omap2_mcspi.3", "mcspi_fck", &mcspi3_fck, CK_343X), + CLK("omap2_mcspi.2", "mcspi_fck", &mcspi2_fck, CK_343X), + CLK("omap2_mcspi.1", "mcspi_fck", &mcspi1_fck, CK_343X), + CLK(NULL, "uart2_fck", &uart2_fck, CK_343X), + CLK(NULL, "uart1_fck", &uart1_fck, CK_343X), + CLK(NULL, "fshostusb_fck", &fshostusb_fck, CK_3430ES1), + CLK(NULL, "core_12m_fck", &core_12m_fck, CK_343X), + CLK(NULL, "hdq_fck", &hdq_fck, CK_343X), + CLK(NULL, "ssi_ssr_fck", &ssi_ssr_fck, CK_343X), + CLK(NULL, "ssi_sst_fck", &ssi_sst_fck, CK_343X), + CLK(NULL, "core_l3_ick", &core_l3_ick, CK_343X), + CLK(NULL, "hsotgusb_ick", &hsotgusb_ick, CK_343X), + CLK(NULL, "sdrc_ick", &sdrc_ick, CK_343X), + CLK(NULL, "gpmc_fck", &gpmc_fck, CK_343X), + CLK(NULL, "security_l3_ick", &security_l3_ick, CK_343X), + CLK(NULL, "pka_ick", &pka_ick, CK_343X), + CLK(NULL, "core_l4_ick", &core_l4_ick, CK_343X), + CLK(NULL, "usbtll_ick", &usbtll_ick, CK_3430ES2), + CLK("mmci-omap-hs.2", "mmchs_ick", &mmchs3_ick, CK_3430ES2), + CLK(NULL, "icr_ick", &icr_ick, CK_343X), + CLK(NULL, "aes2_ick", &aes2_ick, CK_343X), + CLK(NULL, "sha12_ick", &sha12_ick, CK_343X), + CLK(NULL, "des2_ick", &des2_ick, CK_343X), + CLK("mmci-omap-hs.1", "mmchs_ick", &mmchs2_ick, CK_343X), + CLK("mmci-omap-hs.0", "mmchs_ick", &mmchs1_ick, CK_343X), + CLK(NULL, "mspro_ick", &mspro_ick, CK_343X), + CLK(NULL, "hdq_ick", &hdq_ick, CK_343X), + CLK("omap2_mcspi.4", "mcspi_ick", &mcspi4_ick, CK_343X), + CLK("omap2_mcspi.3", "mcspi_ick", &mcspi3_ick, CK_343X), + CLK("omap2_mcspi.2", "mcspi_ick", &mcspi2_ick, CK_343X), + CLK("omap2_mcspi.1", "mcspi_ick", &mcspi1_ick, CK_343X), + CLK("i2c_omap.3", "i2c_ick", &i2c3_ick, CK_343X), + CLK("i2c_omap.2", "i2c_ick", &i2c2_ick, CK_343X), + CLK("i2c_omap.1", "i2c_ick", &i2c1_ick, CK_343X), + CLK(NULL, "uart2_ick", &uart2_ick, CK_343X), + CLK(NULL, "uart1_ick", &uart1_ick, CK_343X), + CLK(NULL, "gpt11_ick", &gpt11_ick, CK_343X), + CLK(NULL, "gpt10_ick", &gpt10_ick, CK_343X), + CLK("omap-mcbsp.5", "mcbsp_ick", &mcbsp5_ick, CK_343X), + CLK("omap-mcbsp.1", "mcbsp_ick", &mcbsp1_ick, CK_343X), + CLK(NULL, "fac_ick", &fac_ick, CK_3430ES1), + CLK(NULL, "mailboxes_ick", &mailboxes_ick, CK_343X), + CLK(NULL, "omapctrl_ick", &omapctrl_ick, CK_343X), + CLK(NULL, "ssi_l4_ick", &ssi_l4_ick, CK_343X), + CLK(NULL, "ssi_ick", &ssi_ick, CK_343X), + CLK(NULL, "usb_l4_ick", &usb_l4_ick, CK_3430ES1), + CLK(NULL, "security_l4_ick2", &security_l4_ick2, CK_343X), + CLK(NULL, "aes1_ick", &aes1_ick, CK_343X), + CLK(NULL, "rng_ick", &rng_ick, CK_343X), + CLK(NULL, "sha11_ick", &sha11_ick, CK_343X), + CLK(NULL, "des1_ick", &des1_ick, CK_343X), + CLK(NULL, "dss1_alwon_fck", &dss1_alwon_fck, CK_343X), + CLK(NULL, "dss_tv_fck", &dss_tv_fck, CK_343X), + CLK(NULL, "dss_96m_fck", &dss_96m_fck, CK_343X), + CLK(NULL, "dss2_alwon_fck", &dss2_alwon_fck, CK_343X), + CLK(NULL, "dss_ick", &dss_ick, CK_343X), + CLK(NULL, "cam_mclk", &cam_mclk, CK_343X), + CLK(NULL, "cam_ick", &cam_ick, CK_343X), + CLK(NULL, "usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2), + CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2), + CLK(NULL, "usbhost_ick", &usbhost_ick, CK_3430ES2), + CLK(NULL, "usbhost_sar_fck", &usbhost_sar_fck, CK_3430ES2), + CLK(NULL, "usim_fck", &usim_fck, CK_3430ES2), + CLK(NULL, "gpt1_fck", &gpt1_fck, CK_343X), + CLK(NULL, "wkup_32k_fck", &wkup_32k_fck, CK_343X), + CLK(NULL, "gpio1_dbck", &gpio1_dbck, CK_343X), + CLK(NULL, "wdt2_fck", &wdt2_fck, CK_343X), + CLK(NULL, "wkup_l4_ick", &wkup_l4_ick, CK_343X), + CLK(NULL, "usim_ick", &usim_ick, CK_3430ES2), + CLK(NULL, "wdt2_ick", &wdt2_ick, CK_343X), + CLK(NULL, "wdt1_ick", &wdt1_ick, CK_343X), + CLK(NULL, "gpio1_ick", &gpio1_ick, CK_343X), + CLK(NULL, "omap_32ksync_ick", &omap_32ksync_ick, CK_343X), + CLK(NULL, "gpt12_ick", &gpt12_ick, CK_343X), + CLK(NULL, "gpt1_ick", &gpt1_ick, CK_343X), + CLK(NULL, "per_96m_fck", &per_96m_fck, CK_343X), + CLK(NULL, "per_48m_fck", &per_48m_fck, CK_343X), + CLK(NULL, "uart3_fck", &uart3_fck, CK_343X), + CLK(NULL, "gpt2_fck", &gpt2_fck, CK_343X), + CLK(NULL, "gpt3_fck", &gpt3_fck, CK_343X), + CLK(NULL, "gpt4_fck", &gpt4_fck, CK_343X), + CLK(NULL, "gpt5_fck", &gpt5_fck, CK_343X), + CLK(NULL, "gpt6_fck", &gpt6_fck, CK_343X), + CLK(NULL, "gpt7_fck", &gpt7_fck, CK_343X), + CLK(NULL, "gpt8_fck", &gpt8_fck, CK_343X), + CLK(NULL, "gpt9_fck", &gpt9_fck, CK_343X), + CLK(NULL, "per_32k_alwon_fck", &per_32k_alwon_fck, CK_343X), + CLK(NULL, "gpio6_dbck", &gpio6_dbck, CK_343X), + CLK(NULL, "gpio5_dbck", &gpio5_dbck, CK_343X), + CLK(NULL, "gpio4_dbck", &gpio4_dbck, CK_343X), + CLK(NULL, "gpio3_dbck", &gpio3_dbck, CK_343X), + CLK(NULL, "gpio2_dbck", &gpio2_dbck, CK_343X), + CLK(NULL, "wdt3_fck", &wdt3_fck, CK_343X), + CLK(NULL, "per_l4_ick", &per_l4_ick, CK_343X), + CLK(NULL, "gpio6_ick", &gpio6_ick, CK_343X), + CLK(NULL, "gpio5_ick", &gpio5_ick, CK_343X), + CLK(NULL, "gpio4_ick", &gpio4_ick, CK_343X), + CLK(NULL, "gpio3_ick", &gpio3_ick, CK_343X), + CLK(NULL, "gpio2_ick", &gpio2_ick, CK_343X), + CLK(NULL, "wdt3_ick", &wdt3_ick, CK_343X), + CLK(NULL, "uart3_ick", &uart3_ick, CK_343X), + CLK(NULL, "gpt9_ick", &gpt9_ick, CK_343X), + CLK(NULL, "gpt8_ick", &gpt8_ick, CK_343X), + CLK(NULL, "gpt7_ick", &gpt7_ick, CK_343X), + CLK(NULL, "gpt6_ick", &gpt6_ick, CK_343X), + CLK(NULL, "gpt5_ick", &gpt5_ick, CK_343X), + CLK(NULL, "gpt4_ick", &gpt4_ick, CK_343X), + CLK(NULL, "gpt3_ick", &gpt3_ick, CK_343X), + CLK(NULL, "gpt2_ick", &gpt2_ick, CK_343X), + CLK("omap-mcbsp.2", "mcbsp_ick", &mcbsp2_ick, CK_343X), + CLK("omap-mcbsp.3", "mcbsp_ick", &mcbsp3_ick, CK_343X), + CLK("omap-mcbsp.4", "mcbsp_ick", &mcbsp4_ick, CK_343X), + CLK("omap-mcbsp.2", "mcbsp_fck", &mcbsp2_fck, CK_343X), + CLK("omap-mcbsp.3", "mcbsp_fck", &mcbsp3_fck, CK_343X), + CLK("omap-mcbsp.4", "mcbsp_fck", &mcbsp4_fck, CK_343X), + CLK(NULL, "emu_src_ck", &emu_src_ck, CK_343X), + CLK(NULL, "pclk_fck", &pclk_fck, CK_343X), + CLK(NULL, "pclkx2_fck", &pclkx2_fck, CK_343X), + CLK(NULL, "atclk_fck", &atclk_fck, CK_343X), + CLK(NULL, "traceclk_src_fck", &traceclk_src_fck, CK_343X), + CLK(NULL, "traceclk_fck", &traceclk_fck, CK_343X), + CLK(NULL, "sr1_fck", &sr1_fck, CK_343X), + CLK(NULL, "sr2_fck", &sr2_fck, CK_343X), + CLK(NULL, "sr_l4_ick", &sr_l4_ick, CK_343X), + CLK(NULL, "secure_32k_fck", &secure_32k_fck, CK_343X), + CLK(NULL, "gpt12_fck", &gpt12_fck, CK_343X), + CLK(NULL, "wdt1_fck", &wdt1_fck, CK_343X), +}; + /* CM_AUTOIDLE_PLL*.AUTO_* bit values */ #define DPLL_AUTOIDLE_DISABLE 0x0 #define DPLL_AUTOIDLE_LOW_POWER_STOP 0x1 @@ -453,26 +688,13 @@ arch_initcall(omap2_clk_arch_init); int __init omap2_clk_init(void) { /* struct prcm_config *prcm; */ - struct clk **clkp; + struct omap_clk *c; /* u32 clkrate; */ u32 cpu_clkflg; - /* REVISIT: Ultimately this will be used for multiboot */ -#if 0 - if (cpu_is_omap242x()) { - cpu_mask = RATE_IN_242X; - cpu_clkflg = CLOCK_IN_OMAP242X; - clkp = onchip_24xx_clks; - } else if (cpu_is_omap2430()) { - cpu_mask = RATE_IN_243X; - cpu_clkflg = CLOCK_IN_OMAP243X; - clkp = onchip_24xx_clks; - } -#endif if (cpu_is_omap34xx()) { cpu_mask = RATE_IN_343X; - cpu_clkflg = CLOCK_IN_OMAP343X; - clkp = onchip_34xx_clks; + cpu_clkflg = CK_343X; /* * Update this if there are further clock changes between ES2 @@ -480,23 +702,21 @@ int __init omap2_clk_init(void) */ if (omap_rev() == OMAP3430_REV_ES1_0) { /* No 3430ES1-only rates exist, so no RATE_IN_3430ES1 */ - cpu_clkflg |= CLOCK_IN_OMAP3430ES1; + cpu_clkflg |= CK_3430ES1; } else { cpu_mask |= RATE_IN_3430ES2; - cpu_clkflg |= CLOCK_IN_OMAP3430ES2; + cpu_clkflg |= CK_3430ES2; } } clk_init(&omap2_clk_functions); - for (clkp = onchip_34xx_clks; - clkp < onchip_34xx_clks + ARRAY_SIZE(onchip_34xx_clks); - clkp++) { - if ((*clkp)->flags & cpu_clkflg) { - clk_register(*clkp); - omap2_init_clk_clkdm(*clkp); + for (c = omap34xx_clks; c < omap34xx_clks + ARRAY_SIZE(omap34xx_clks); c++) + if (c->cpu & cpu_clkflg) { + clkdev_add(&c->lk); + clk_register(c->lk.clk); + omap2_init_clk_clkdm(c->lk.clk); } - } /* REVISIT: Not yet ready for OMAP3 */ #if 0 diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index dcacec84f8c..6bd8c6d5a4e 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -57,14 +57,14 @@ static struct clk omap_32k_fck = { .name = "omap_32k_fck", .ops = &clkops_null, .rate = 32768, - .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES, + .flags = RATE_FIXED | RATE_PROPAGATES, }; static struct clk secure_32k_fck = { .name = "secure_32k_fck", .ops = &clkops_null, .rate = 32768, - .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES, + .flags = RATE_FIXED | RATE_PROPAGATES, }; /* Virtual source clocks for osc_sys_ck */ @@ -72,42 +72,42 @@ static struct clk virt_12m_ck = { .name = "virt_12m_ck", .ops = &clkops_null, .rate = 12000000, - .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES, + .flags = RATE_FIXED | RATE_PROPAGATES, }; static struct clk virt_13m_ck = { .name = "virt_13m_ck", .ops = &clkops_null, .rate = 13000000, - .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES, + .flags = RATE_FIXED | RATE_PROPAGATES, }; static struct clk virt_16_8m_ck = { .name = "virt_16_8m_ck", .ops = &clkops_null, .rate = 16800000, - .flags = CLOCK_IN_OMAP3430ES2 | RATE_FIXED | RATE_PROPAGATES, + .flags = RATE_FIXED | RATE_PROPAGATES, }; static struct clk virt_19_2m_ck = { .name = "virt_19_2m_ck", .ops = &clkops_null, .rate = 19200000, - .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES, + .flags = RATE_FIXED | RATE_PROPAGATES, }; static struct clk virt_26m_ck = { .name = "virt_26m_ck", .ops = &clkops_null, .rate = 26000000, - .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES, + .flags = RATE_FIXED | RATE_PROPAGATES, }; static struct clk virt_38_4m_ck = { .name = "virt_38_4m_ck", .ops = &clkops_null, .rate = 38400000, - .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES, + .flags = RATE_FIXED | RATE_PROPAGATES, }; static const struct clksel_rate osc_sys_12m_rates[] = { @@ -160,7 +160,7 @@ static struct clk osc_sys_ck = { .clksel_mask = OMAP3430_SYS_CLKIN_SEL_MASK, .clksel = osc_sys_clksel, /* REVISIT: deal with autoextclkmode? */ - .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES, + .flags = RATE_FIXED | RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -185,21 +185,21 @@ static struct clk sys_ck = { .clksel_reg = OMAP3430_PRM_CLKSRC_CTRL, .clksel_mask = OMAP_SYSCLKDIV_MASK, .clksel = sys_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; static struct clk sys_altclk = { .name = "sys_altclk", .ops = &clkops_null, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, }; /* Optional external clock input for some McBSPs */ static struct clk mcbsp_clks = { .name = "mcbsp_clks", .ops = &clkops_null, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, }; /* PRM EXTERNAL CLOCK OUTPUT */ @@ -210,7 +210,6 @@ static struct clk sys_clkout1 = { .parent = &osc_sys_ck, .enable_reg = OMAP3430_PRM_CLKOUT_CTRL, .enable_bit = OMAP3430_CLKOUT_EN_SHIFT, - .flags = CLOCK_IN_OMAP343X, .recalc = &followparent_recalc, }; @@ -275,7 +274,7 @@ static struct clk dpll1_ck = { .ops = &clkops_null, .parent = &sys_ck, .dpll_data = &dpll1_dd, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .round_rate = &omap2_dpll_round_rate, .recalc = &omap3_dpll_recalc, }; @@ -288,7 +287,7 @@ static struct clk dpll1_x2_ck = { .name = "dpll1_x2_ck", .ops = &clkops_null, .parent = &dpll1_ck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap3_clkoutx2_recalc, }; @@ -310,7 +309,7 @@ static struct clk dpll1_x2m2_ck = { .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL), .clksel_mask = OMAP3430_MPU_DPLL_CLKOUT_DIV_MASK, .clksel = div16_dpll1_x2m2_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -343,7 +342,7 @@ static struct clk dpll2_ck = { .ops = &clkops_noncore_dpll_ops, .parent = &sys_ck, .dpll_data = &dpll2_dd, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .round_rate = &omap2_dpll_round_rate, .recalc = &omap3_dpll_recalc, }; @@ -366,7 +365,7 @@ static struct clk dpll2_m2_ck = { OMAP3430_CM_CLKSEL2_PLL), .clksel_mask = OMAP3430_IVA2_DPLL_CLKOUT_DIV_MASK, .clksel = div16_dpll2_m2x2_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -396,7 +395,7 @@ static struct clk dpll3_ck = { .ops = &clkops_null, .parent = &sys_ck, .dpll_data = &dpll3_dd, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .round_rate = &omap2_dpll_round_rate, .recalc = &omap3_dpll_recalc, }; @@ -409,7 +408,7 @@ static struct clk dpll3_x2_ck = { .name = "dpll3_x2_ck", .ops = &clkops_null, .parent = &dpll3_ck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap3_clkoutx2_recalc, }; @@ -466,7 +465,7 @@ static struct clk dpll3_m2_ck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK, .clksel = div31_dpll3m2_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -483,7 +482,7 @@ static struct clk core_ck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), .clksel_mask = OMAP3430_ST_CORE_CLK_MASK, .clksel = core_ck_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -500,7 +499,7 @@ static struct clk dpll3_m2x2_ck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), .clksel_mask = OMAP3430_ST_CORE_CLK_MASK, .clksel = dpll3_m2x2_ck_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -519,7 +518,7 @@ static struct clk dpll3_m3_ck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_DIV_DPLL3_MASK, .clksel = div16_dpll3_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -530,7 +529,7 @@ static struct clk dpll3_m3x2_ck = { .parent = &dpll3_m3_ck, .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP3430_PWRDN_EMU_CORE_SHIFT, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE, + .flags = RATE_PROPAGATES | INVERT_ENABLE, .recalc = &omap3_clkoutx2_recalc, }; @@ -548,7 +547,7 @@ static struct clk emu_core_alwon_ck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), .clksel_mask = OMAP3430_ST_CORE_CLK_MASK, .clksel = emu_core_alwon_ck_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -579,7 +578,7 @@ static struct clk dpll4_ck = { .ops = &clkops_noncore_dpll_ops, .parent = &sys_ck, .dpll_data = &dpll4_dd, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .round_rate = &omap2_dpll_round_rate, .recalc = &omap3_dpll_recalc, }; @@ -593,7 +592,7 @@ static struct clk dpll4_x2_ck = { .name = "dpll4_x2_ck", .ops = &clkops_null, .parent = &dpll4_ck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap3_clkoutx2_recalc, }; @@ -611,7 +610,7 @@ static struct clk dpll4_m2_ck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430_CM_CLKSEL3), .clksel_mask = OMAP3430_DIV_96M_MASK, .clksel = div16_dpll4_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -622,7 +621,7 @@ static struct clk dpll4_m2x2_ck = { .parent = &dpll4_m2_ck, .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP3430_PWRDN_96M_SHIFT, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE, + .flags = RATE_PROPAGATES | INVERT_ENABLE, .recalc = &omap3_clkoutx2_recalc, }; @@ -640,7 +639,7 @@ static struct clk omap_96m_alwon_fck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), .clksel_mask = OMAP3430_ST_PERIPH_CLK_MASK, .clksel = omap_96m_alwon_fck_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -648,7 +647,7 @@ static struct clk omap_96m_fck = { .name = "omap_96m_fck", .ops = &clkops_null, .parent = &omap_96m_alwon_fck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &followparent_recalc, }; @@ -666,7 +665,7 @@ static struct clk cm_96m_fck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), .clksel_mask = OMAP3430_ST_PERIPH_CLK_MASK, .clksel = cm_96m_fck_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -679,7 +678,7 @@ static struct clk dpll4_m3_ck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_TV_MASK, .clksel = div16_dpll4_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -691,7 +690,7 @@ static struct clk dpll4_m3x2_ck = { .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP3430_PWRDN_TV_SHIFT, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE, + .flags = RATE_PROPAGATES | INVERT_ENABLE, .recalc = &omap3_clkoutx2_recalc, }; @@ -709,7 +708,7 @@ static struct clk virt_omap_54m_fck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), .clksel_mask = OMAP3430_ST_PERIPH_CLK_MASK, .clksel = virt_omap_54m_fck_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -736,7 +735,7 @@ static struct clk omap_54m_fck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_SOURCE_54M, .clksel = omap_54m_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -763,7 +762,7 @@ static struct clk omap_48m_fck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_SOURCE_48M, .clksel = omap_48m_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -772,7 +771,7 @@ static struct clk omap_12m_fck = { .ops = &clkops_null, .parent = &omap_48m_fck, .fixed_div = 4, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_fixed_divisor_recalc, }; @@ -785,7 +784,7 @@ static struct clk dpll4_m4_ck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_DSS1_MASK, .clksel = div16_dpll4_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -796,7 +795,7 @@ static struct clk dpll4_m4x2_ck = { .parent = &dpll4_m4_ck, .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP3430_PWRDN_CAM_SHIFT, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE, + .flags = RATE_PROPAGATES | INVERT_ENABLE, .recalc = &omap3_clkoutx2_recalc, }; @@ -809,7 +808,7 @@ static struct clk dpll4_m5_ck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_CAM_MASK, .clksel = div16_dpll4_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -820,7 +819,7 @@ static struct clk dpll4_m5x2_ck = { .parent = &dpll4_m5_ck, .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP3430_PWRDN_CAM_SHIFT, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE, + .flags = RATE_PROPAGATES | INVERT_ENABLE, .recalc = &omap3_clkoutx2_recalc, }; @@ -833,7 +832,7 @@ static struct clk dpll4_m6_ck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_DIV_DPLL4_MASK, .clksel = div16_dpll4_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -845,7 +844,7 @@ static struct clk dpll4_m6x2_ck = { .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP3430_PWRDN_EMU_PERIPH_SHIFT, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE, + .flags = RATE_PROPAGATES | INVERT_ENABLE, .recalc = &omap3_clkoutx2_recalc, }; @@ -853,7 +852,7 @@ static struct clk emu_per_alwon_ck = { .name = "emu_per_alwon_ck", .ops = &clkops_null, .parent = &dpll4_m6x2_ck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &followparent_recalc, }; @@ -885,7 +884,7 @@ static struct clk dpll5_ck = { .ops = &clkops_noncore_dpll_ops, .parent = &sys_ck, .dpll_data = &dpll5_dd, - .flags = CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .round_rate = &omap2_dpll_round_rate, .recalc = &omap3_dpll_recalc, }; @@ -903,7 +902,7 @@ static struct clk dpll5_m2_ck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL5), .clksel_mask = OMAP3430ES2_DIV_120M_MASK, .clksel = div16_dpll5_clksel, - .flags = CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -921,7 +920,7 @@ static struct clk omap_120m_fck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2), .clksel_mask = OMAP3430ES2_ST_PERIPH2_CLK_MASK, .clksel = omap_120m_fck_clksel, - .flags = CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -964,7 +963,7 @@ static struct clk clkout2_src_ck = { .clksel_reg = OMAP3430_CM_CLKOUT_CTRL, .clksel_mask = OMAP3430_CLKOUT2SOURCE_MASK, .clksel = clkout2_src_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -989,7 +988,6 @@ static struct clk sys_clkout2 = { .clksel_reg = OMAP3430_CM_CLKOUT_CTRL, .clksel_mask = OMAP3430_CLKOUT2_DIV_MASK, .clksel = sys_clkout2_clksel, - .flags = CLOCK_IN_OMAP343X, .recalc = &omap2_clksel_recalc, }; @@ -999,7 +997,7 @@ static struct clk corex2_fck = { .name = "corex2_fck", .ops = &clkops_null, .parent = &dpll3_m2x2_ck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &followparent_recalc, }; @@ -1022,7 +1020,7 @@ static struct clk dpll1_fck = { .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL), .clksel_mask = OMAP3430_MPU_CLK_SRC_MASK, .clksel = div2_core_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -1046,7 +1044,7 @@ static struct clk mpu_ck = { .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), .clksel_mask = OMAP3430_ST_MPU_CLK_MASK, .clksel = mpu_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "mpu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1071,7 +1069,7 @@ static struct clk arm_fck = { .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), .clksel_mask = OMAP3430_ST_MPU_CLK_MASK, .clksel = arm_fck_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -1085,7 +1083,7 @@ static struct clk emu_mpu_alwon_ck = { .name = "emu_mpu_alwon_ck", .ops = &clkops_null, .parent = &mpu_ck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &followparent_recalc, }; @@ -1097,7 +1095,7 @@ static struct clk dpll2_fck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL), .clksel_mask = OMAP3430_IVA2_CLK_SRC_MASK, .clksel = div2_core_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -1125,7 +1123,7 @@ static struct clk iva2_ck = { OMAP3430_CM_IDLEST_PLL), .clksel_mask = OMAP3430_ST_IVA2_CLK_MASK, .clksel = iva2_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "iva2_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1140,7 +1138,7 @@ static struct clk l3_ick = { .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_L3_MASK, .clksel = div2_core_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "core_l3_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1158,7 +1156,7 @@ static struct clk l4_ick = { .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_L4_MASK, .clksel = div2_l3_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "core_l4_clkdm", .recalc = &omap2_clksel_recalc, @@ -1177,7 +1175,6 @@ static struct clk rm_ick = { .clksel_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_RM_MASK, .clksel = div2_l4_clksel, - .flags = CLOCK_IN_OMAP343X, .recalc = &omap2_clksel_recalc, }; @@ -1198,7 +1195,6 @@ static struct clk gfx_l3_ck = { .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN), .enable_bit = OMAP_EN_GFX_SHIFT, - .flags = CLOCK_IN_OMAP3430ES1, .recalc = &followparent_recalc, }; @@ -1210,7 +1206,7 @@ static struct clk gfx_l3_fck = { .clksel_reg = OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL), .clksel_mask = OMAP_CLKSEL_GFX_MASK, .clksel = gfx_l3_clksel, - .flags = CLOCK_IN_OMAP3430ES1 | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "gfx_3430es1_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1219,7 +1215,6 @@ static struct clk gfx_l3_ick = { .name = "gfx_l3_ick", .ops = &clkops_null, .parent = &gfx_l3_ck, - .flags = CLOCK_IN_OMAP3430ES1, .clkdm_name = "gfx_3430es1_clkdm", .recalc = &followparent_recalc, }; @@ -1231,7 +1226,6 @@ static struct clk gfx_cg1_ck = { .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN), .enable_bit = OMAP3430ES1_EN_2D_SHIFT, - .flags = CLOCK_IN_OMAP3430ES1, .clkdm_name = "gfx_3430es1_clkdm", .recalc = &followparent_recalc, }; @@ -1243,7 +1237,6 @@ static struct clk gfx_cg2_ck = { .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN), .enable_bit = OMAP3430ES1_EN_3D_SHIFT, - .flags = CLOCK_IN_OMAP3430ES1, .clkdm_name = "gfx_3430es1_clkdm", .recalc = &followparent_recalc, }; @@ -1277,7 +1270,6 @@ static struct clk sgx_fck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_CLKSEL), .clksel_mask = OMAP3430ES2_CLKSEL_SGX_MASK, .clksel = sgx_clksel, - .flags = CLOCK_IN_OMAP3430ES2, .clkdm_name = "sgx_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1289,7 +1281,6 @@ static struct clk sgx_ick = { .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_ICLKEN), .enable_bit = OMAP3430ES2_EN_SGX_SHIFT, - .flags = CLOCK_IN_OMAP3430ES2, .clkdm_name = "sgx_clkdm", .recalc = &followparent_recalc, }; @@ -1303,7 +1294,6 @@ static struct clk d2d_26m_fck = { .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430ES1_EN_D2D_SHIFT, - .flags = CLOCK_IN_OMAP3430ES1, .clkdm_name = "d2d_clkdm", .recalc = &followparent_recalc, }; @@ -1324,7 +1314,6 @@ static struct clk gpt10_fck = { .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_GPT10_MASK, .clksel = omap343x_gpt_clksel, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1339,7 +1328,6 @@ static struct clk gpt11_fck = { .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_GPT11_MASK, .clksel = omap343x_gpt_clksel, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1350,7 +1338,6 @@ static struct clk cpefuse_fck = { .parent = &sys_ck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3), .enable_bit = OMAP3430ES2_EN_CPEFUSE_SHIFT, - .flags = CLOCK_IN_OMAP3430ES2, .recalc = &followparent_recalc, }; @@ -1360,7 +1347,6 @@ static struct clk ts_fck = { .parent = &omap_32k_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3), .enable_bit = OMAP3430ES2_EN_TS_SHIFT, - .flags = CLOCK_IN_OMAP3430ES2, .recalc = &followparent_recalc, }; @@ -1370,7 +1356,6 @@ static struct clk usbtll_fck = { .parent = &omap_120m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3), .enable_bit = OMAP3430ES2_EN_USBTLL_SHIFT, - .flags = CLOCK_IN_OMAP3430ES2, .recalc = &followparent_recalc, }; @@ -1380,7 +1365,7 @@ static struct clk core_96m_fck = { .name = "core_96m_fck", .ops = &clkops_null, .parent = &omap_96m_fck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1392,7 +1377,6 @@ static struct clk mmchs3_fck = { .parent = &core_96m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430ES2_EN_MMC3_SHIFT, - .flags = CLOCK_IN_OMAP3430ES2, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1404,7 +1388,6 @@ static struct clk mmchs2_fck = { .parent = &core_96m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_MMC2_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1415,7 +1398,6 @@ static struct clk mspro_fck = { .parent = &core_96m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_MSPRO_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1426,7 +1408,6 @@ static struct clk mmchs1_fck = { .parent = &core_96m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_MMC1_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1438,7 +1419,6 @@ static struct clk i2c3_fck = { .parent = &core_96m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_I2C3_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1450,7 +1430,6 @@ static struct clk i2c2_fck = { .parent = &core_96m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_I2C2_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1462,7 +1441,6 @@ static struct clk i2c1_fck = { .parent = &core_96m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_I2C1_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1497,7 +1475,6 @@ static struct clk mcbsp5_fck = { .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1), .clksel_mask = OMAP2_MCBSP5_CLKS_MASK, .clksel = mcbsp_15_clksel, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1512,7 +1489,6 @@ static struct clk mcbsp1_fck = { .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0), .clksel_mask = OMAP2_MCBSP1_CLKS_MASK, .clksel = mcbsp_15_clksel, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1523,7 +1499,7 @@ static struct clk core_48m_fck = { .name = "core_48m_fck", .ops = &clkops_null, .parent = &omap_48m_fck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1535,7 +1511,6 @@ static struct clk mcspi4_fck = { .parent = &core_48m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_MCSPI4_SHIFT, - .flags = CLOCK_IN_OMAP343X, .recalc = &followparent_recalc, }; @@ -1546,7 +1521,6 @@ static struct clk mcspi3_fck = { .parent = &core_48m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_MCSPI3_SHIFT, - .flags = CLOCK_IN_OMAP343X, .recalc = &followparent_recalc, }; @@ -1557,7 +1531,6 @@ static struct clk mcspi2_fck = { .parent = &core_48m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_MCSPI2_SHIFT, - .flags = CLOCK_IN_OMAP343X, .recalc = &followparent_recalc, }; @@ -1568,7 +1541,6 @@ static struct clk mcspi1_fck = { .parent = &core_48m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_MCSPI1_SHIFT, - .flags = CLOCK_IN_OMAP343X, .recalc = &followparent_recalc, }; @@ -1578,7 +1550,6 @@ static struct clk uart2_fck = { .parent = &core_48m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_UART2_SHIFT, - .flags = CLOCK_IN_OMAP343X, .recalc = &followparent_recalc, }; @@ -1588,7 +1559,6 @@ static struct clk uart1_fck = { .parent = &core_48m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_UART1_SHIFT, - .flags = CLOCK_IN_OMAP343X, .recalc = &followparent_recalc, }; @@ -1598,7 +1568,6 @@ static struct clk fshostusb_fck = { .parent = &core_48m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430ES1_EN_FSHOSTUSB_SHIFT, - .flags = CLOCK_IN_OMAP3430ES1, .recalc = &followparent_recalc, }; @@ -1608,7 +1577,7 @@ static struct clk core_12m_fck = { .name = "core_12m_fck", .ops = &clkops_null, .parent = &omap_12m_fck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1619,7 +1588,6 @@ static struct clk hdq_fck = { .parent = &core_12m_fck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_HDQ_SHIFT, - .flags = CLOCK_IN_OMAP343X, .recalc = &followparent_recalc, }; @@ -1649,7 +1617,7 @@ static struct clk ssi_ssr_fck = { .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_SSI_MASK, .clksel = ssi_ssr_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "core_l4_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1659,7 +1627,6 @@ static struct clk ssi_sst_fck = { .ops = &clkops_null, .parent = &ssi_ssr_fck, .fixed_div = 2, - .flags = CLOCK_IN_OMAP343X, .recalc = &omap2_fixed_divisor_recalc, }; @@ -1676,7 +1643,7 @@ static struct clk core_l3_ick = { .ops = &clkops_null, .parent = &l3_ick, .init = &omap2_init_clk_clkdm, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "core_l3_clkdm", .recalc = &followparent_recalc, }; @@ -1687,7 +1654,6 @@ static struct clk hsotgusb_ick = { .parent = &core_l3_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_HSOTGUSB_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l3_clkdm", .recalc = &followparent_recalc, }; @@ -1698,7 +1664,7 @@ static struct clk sdrc_ick = { .parent = &core_l3_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_SDRC_SHIFT, - .flags = CLOCK_IN_OMAP343X | ENABLE_ON_INIT, + .flags = ENABLE_ON_INIT, .clkdm_name = "core_l3_clkdm", .recalc = &followparent_recalc, }; @@ -1707,7 +1673,7 @@ static struct clk gpmc_fck = { .name = "gpmc_fck", .ops = &clkops_null, .parent = &core_l3_ick, - .flags = CLOCK_IN_OMAP343X | ENABLE_ON_INIT, /* huh? */ + .flags = ENABLE_ON_INIT, /* huh? */ .clkdm_name = "core_l3_clkdm", .recalc = &followparent_recalc, }; @@ -1718,7 +1684,7 @@ static struct clk security_l3_ick = { .name = "security_l3_ick", .ops = &clkops_null, .parent = &l3_ick, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &followparent_recalc, }; @@ -1728,7 +1694,6 @@ static struct clk pka_ick = { .parent = &security_l3_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP3430_EN_PKA_SHIFT, - .flags = CLOCK_IN_OMAP343X, .recalc = &followparent_recalc, }; @@ -1739,7 +1704,7 @@ static struct clk core_l4_ick = { .ops = &clkops_null, .parent = &l4_ick, .init = &omap2_init_clk_clkdm, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1750,7 +1715,6 @@ static struct clk usbtll_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3), .enable_bit = OMAP3430ES2_EN_USBTLL_SHIFT, - .flags = CLOCK_IN_OMAP3430ES2, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1762,7 +1726,6 @@ static struct clk mmchs3_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430ES2_EN_MMC3_SHIFT, - .flags = CLOCK_IN_OMAP3430ES2, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1774,7 +1737,6 @@ static struct clk icr_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_ICR_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1785,7 +1747,6 @@ static struct clk aes2_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_AES2_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1796,7 +1757,6 @@ static struct clk sha12_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_SHA12_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1807,7 +1767,6 @@ static struct clk des2_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_DES2_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1819,7 +1778,6 @@ static struct clk mmchs2_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MMC2_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1830,7 +1788,6 @@ static struct clk mmchs1_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MMC1_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1841,7 +1798,6 @@ static struct clk mspro_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MSPRO_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1852,7 +1808,6 @@ static struct clk hdq_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_HDQ_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1864,7 +1819,6 @@ static struct clk mcspi4_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MCSPI4_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1876,7 +1830,6 @@ static struct clk mcspi3_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MCSPI3_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1888,7 +1841,6 @@ static struct clk mcspi2_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MCSPI2_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1900,7 +1852,6 @@ static struct clk mcspi1_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MCSPI1_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1912,7 +1863,6 @@ static struct clk i2c3_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_I2C3_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1924,7 +1874,6 @@ static struct clk i2c2_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_I2C2_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1936,7 +1885,6 @@ static struct clk i2c1_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_I2C1_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1947,7 +1895,6 @@ static struct clk uart2_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_UART2_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1958,7 +1905,6 @@ static struct clk uart1_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_UART1_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1969,7 +1915,6 @@ static struct clk gpt11_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_GPT11_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1980,7 +1925,6 @@ static struct clk gpt10_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_GPT10_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1992,7 +1936,6 @@ static struct clk mcbsp5_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MCBSP5_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -2004,7 +1947,6 @@ static struct clk mcbsp1_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MCBSP1_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -2015,7 +1957,6 @@ static struct clk fac_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430ES1_EN_FAC_SHIFT, - .flags = CLOCK_IN_OMAP3430ES1, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -2026,7 +1967,6 @@ static struct clk mailboxes_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MAILBOXES_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -2037,7 +1977,7 @@ static struct clk omapctrl_ick = { .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_OMAPCTRL_SHIFT, - .flags = CLOCK_IN_OMAP343X | ENABLE_ON_INIT, + .flags = ENABLE_ON_INIT, .recalc = &followparent_recalc, }; @@ -2047,7 +1987,7 @@ static struct clk ssi_l4_ick = { .name = "ssi_l4_ick", .ops = &clkops_null, .parent = &l4_ick, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -2058,7 +1998,6 @@ static struct clk ssi_ick = { .parent = &ssi_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_SSI_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -2081,7 +2020,6 @@ static struct clk usb_l4_ick = { .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), .clksel_mask = OMAP3430ES1_CLKSEL_FSHOSTUSB_MASK, .clksel = usb_l4_clksel, - .flags = CLOCK_IN_OMAP3430ES1, .recalc = &omap2_clksel_recalc, }; @@ -2093,7 +2031,7 @@ static struct clk security_l4_ick2 = { .name = "security_l4_ick2", .ops = &clkops_null, .parent = &l4_ick, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &followparent_recalc, }; @@ -2103,7 +2041,6 @@ static struct clk aes1_ick = { .parent = &security_l4_ick2, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP3430_EN_AES1_SHIFT, - .flags = CLOCK_IN_OMAP343X, .recalc = &followparent_recalc, }; @@ -2113,7 +2050,6 @@ static struct clk rng_ick = { .parent = &security_l4_ick2, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP3430_EN_RNG_SHIFT, - .flags = CLOCK_IN_OMAP343X, .recalc = &followparent_recalc, }; @@ -2123,7 +2059,6 @@ static struct clk sha11_ick = { .parent = &security_l4_ick2, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP3430_EN_SHA11_SHIFT, - .flags = CLOCK_IN_OMAP343X, .recalc = &followparent_recalc, }; @@ -2133,7 +2068,6 @@ static struct clk des1_ick = { .parent = &security_l4_ick2, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP3430_EN_DES1_SHIFT, - .flags = CLOCK_IN_OMAP343X, .recalc = &followparent_recalc, }; @@ -2154,7 +2088,6 @@ static struct clk dss1_alwon_fck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), .clksel_mask = OMAP3430_ST_PERIPH_CLK_MASK, .clksel = dss1_alwon_fck_clksel, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "dss_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2166,7 +2099,6 @@ static struct clk dss_tv_fck = { .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_TV_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "dss_clkdm", .recalc = &followparent_recalc, }; @@ -2178,7 +2110,6 @@ static struct clk dss_96m_fck = { .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_TV_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "dss_clkdm", .recalc = &followparent_recalc, }; @@ -2190,7 +2121,6 @@ static struct clk dss2_alwon_fck = { .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_DSS2_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "dss_clkdm", .recalc = &followparent_recalc, }; @@ -2203,7 +2133,6 @@ static struct clk dss_ick = { .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN), .enable_bit = OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "dss_clkdm", .recalc = &followparent_recalc, }; @@ -2226,7 +2155,6 @@ static struct clk cam_mclk = { .clksel = cam_mclk_clksel, .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_CAM_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "cam_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2239,7 +2167,6 @@ static struct clk cam_ick = { .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_CAM_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "cam_clkdm", .recalc = &followparent_recalc, }; @@ -2253,7 +2180,6 @@ static struct clk usbhost_120m_fck = { .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN), .enable_bit = OMAP3430ES2_EN_USBHOST2_SHIFT, - .flags = CLOCK_IN_OMAP3430ES2, .clkdm_name = "usbhost_clkdm", .recalc = &followparent_recalc, }; @@ -2265,7 +2191,6 @@ static struct clk usbhost_48m_fck = { .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN), .enable_bit = OMAP3430ES2_EN_USBHOST1_SHIFT, - .flags = CLOCK_IN_OMAP3430ES2, .clkdm_name = "usbhost_clkdm", .recalc = &followparent_recalc, }; @@ -2278,7 +2203,6 @@ static struct clk usbhost_ick = { .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN), .enable_bit = OMAP3430ES2_EN_USBHOST_SHIFT, - .flags = CLOCK_IN_OMAP3430ES2, .clkdm_name = "usbhost_clkdm", .recalc = &followparent_recalc, }; @@ -2290,7 +2214,6 @@ static struct clk usbhost_sar_fck = { .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_PRM_REGADDR(OMAP3430ES2_USBHOST_MOD, PM_PWSTCTRL), .enable_bit = OMAP3430ES2_SAVEANDRESTORE_SHIFT, - .flags = CLOCK_IN_OMAP3430ES2, .clkdm_name = "usbhost_clkdm", .recalc = &followparent_recalc, }; @@ -2330,7 +2253,6 @@ static struct clk usim_fck = { .clksel_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL), .clksel_mask = OMAP3430ES2_CLKSEL_USIMOCP_MASK, .clksel = usim_clksel, - .flags = CLOCK_IN_OMAP3430ES2, .recalc = &omap2_clksel_recalc, }; @@ -2344,7 +2266,6 @@ static struct clk gpt1_fck = { .clksel_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_GPT1_MASK, .clksel = omap343x_gpt_clksel, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "wkup_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2354,7 +2275,7 @@ static struct clk wkup_32k_fck = { .ops = &clkops_null, .init = &omap2_init_clk_clkdm, .parent = &omap_32k_fck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2365,7 +2286,6 @@ static struct clk gpio1_dbck = { .parent = &wkup_32k_fck, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO1_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2376,7 +2296,6 @@ static struct clk wdt2_fck = { .parent = &wkup_32k_fck, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_WDT2_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2385,7 +2304,7 @@ static struct clk wkup_l4_ick = { .name = "wkup_l4_ick", .ops = &clkops_null, .parent = &sys_ck, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2398,7 +2317,6 @@ static struct clk usim_ick = { .parent = &wkup_l4_ick, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430ES2_EN_USIMOCP_SHIFT, - .flags = CLOCK_IN_OMAP3430ES2, .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2409,7 +2327,6 @@ static struct clk wdt2_ick = { .parent = &wkup_l4_ick, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_WDT2_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2420,7 +2337,6 @@ static struct clk wdt1_ick = { .parent = &wkup_l4_ick, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_WDT1_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2431,7 +2347,6 @@ static struct clk gpio1_ick = { .parent = &wkup_l4_ick, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO1_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2442,7 +2357,6 @@ static struct clk omap_32ksync_ick = { .parent = &wkup_l4_ick, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_32KSYNC_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2454,7 +2368,6 @@ static struct clk gpt12_ick = { .parent = &wkup_l4_ick, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT12_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2465,7 +2378,6 @@ static struct clk gpt1_ick = { .parent = &wkup_l4_ick, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT1_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2479,7 +2391,7 @@ static struct clk per_96m_fck = { .ops = &clkops_null, .parent = &omap_96m_alwon_fck, .init = &omap2_init_clk_clkdm, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2489,7 +2401,7 @@ static struct clk per_48m_fck = { .ops = &clkops_null, .parent = &omap_48m_fck, .init = &omap2_init_clk_clkdm, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2500,7 +2412,6 @@ static struct clk uart3_fck = { .parent = &per_48m_fck, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_UART3_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2514,7 +2425,6 @@ static struct clk gpt2_fck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_GPT2_MASK, .clksel = omap343x_gpt_clksel, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2528,7 +2438,6 @@ static struct clk gpt3_fck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_GPT3_MASK, .clksel = omap343x_gpt_clksel, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2542,7 +2451,6 @@ static struct clk gpt4_fck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_GPT4_MASK, .clksel = omap343x_gpt_clksel, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2556,7 +2464,6 @@ static struct clk gpt5_fck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_GPT5_MASK, .clksel = omap343x_gpt_clksel, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2570,7 +2477,6 @@ static struct clk gpt6_fck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_GPT6_MASK, .clksel = omap343x_gpt_clksel, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2584,7 +2490,6 @@ static struct clk gpt7_fck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_GPT7_MASK, .clksel = omap343x_gpt_clksel, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2598,7 +2503,6 @@ static struct clk gpt8_fck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_GPT8_MASK, .clksel = omap343x_gpt_clksel, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2612,7 +2516,6 @@ static struct clk gpt9_fck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_GPT9_MASK, .clksel = omap343x_gpt_clksel, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2622,7 +2525,7 @@ static struct clk per_32k_alwon_fck = { .ops = &clkops_null, .parent = &omap_32k_fck, .clkdm_name = "per_clkdm", - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &followparent_recalc, }; @@ -2632,7 +2535,6 @@ static struct clk gpio6_dbck = { .parent = &per_32k_alwon_fck, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO6_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2643,7 +2545,6 @@ static struct clk gpio5_dbck = { .parent = &per_32k_alwon_fck, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO5_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2654,7 +2555,6 @@ static struct clk gpio4_dbck = { .parent = &per_32k_alwon_fck, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO4_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2665,7 +2565,6 @@ static struct clk gpio3_dbck = { .parent = &per_32k_alwon_fck, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO3_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2676,7 +2575,6 @@ static struct clk gpio2_dbck = { .parent = &per_32k_alwon_fck, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_GPIO2_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2687,7 +2585,6 @@ static struct clk wdt3_fck = { .parent = &per_32k_alwon_fck, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_WDT3_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2696,7 +2593,7 @@ static struct clk per_l4_ick = { .name = "per_l4_ick", .ops = &clkops_null, .parent = &l4_ick, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2707,7 +2604,6 @@ static struct clk gpio6_ick = { .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO6_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2718,7 +2614,6 @@ static struct clk gpio5_ick = { .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO5_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2729,7 +2624,6 @@ static struct clk gpio4_ick = { .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO4_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2740,7 +2634,6 @@ static struct clk gpio3_ick = { .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO3_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2751,7 +2644,6 @@ static struct clk gpio2_ick = { .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO2_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2762,7 +2654,6 @@ static struct clk wdt3_ick = { .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_WDT3_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2773,7 +2664,6 @@ static struct clk uart3_ick = { .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_UART3_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2784,7 +2674,6 @@ static struct clk gpt9_ick = { .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT9_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2795,7 +2684,6 @@ static struct clk gpt8_ick = { .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT8_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2806,7 +2694,6 @@ static struct clk gpt7_ick = { .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT7_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2817,7 +2704,6 @@ static struct clk gpt6_ick = { .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT6_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2828,7 +2714,6 @@ static struct clk gpt5_ick = { .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT5_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2839,7 +2724,6 @@ static struct clk gpt4_ick = { .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT4_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2850,7 +2734,6 @@ static struct clk gpt3_ick = { .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT3_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2861,7 +2744,6 @@ static struct clk gpt2_ick = { .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT2_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2873,7 +2755,6 @@ static struct clk mcbsp2_ick = { .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_MCBSP2_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2885,7 +2766,6 @@ static struct clk mcbsp3_ick = { .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_MCBSP3_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2897,7 +2777,6 @@ static struct clk mcbsp4_ick = { .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_MCBSP4_SHIFT, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2918,7 +2797,6 @@ static struct clk mcbsp2_fck = { .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0), .clksel_mask = OMAP2_MCBSP2_CLKS_MASK, .clksel = mcbsp_234_clksel, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2933,7 +2811,6 @@ static struct clk mcbsp3_fck = { .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1), .clksel_mask = OMAP2_MCBSP3_CLKS_MASK, .clksel = mcbsp_234_clksel, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2948,7 +2825,6 @@ static struct clk mcbsp4_fck = { .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1), .clksel_mask = OMAP2_MCBSP4_CLKS_MASK, .clksel = mcbsp_234_clksel, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "per_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2997,7 +2873,7 @@ static struct clk emu_src_ck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_MUX_CTRL_MASK, .clksel = emu_src_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "emu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -3022,7 +2898,7 @@ static struct clk pclk_fck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_CLKSEL_PCLK_MASK, .clksel = pclk_emu_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "emu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -3046,7 +2922,7 @@ static struct clk pclkx2_fck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_CLKSEL_PCLKX2_MASK, .clksel = pclkx2_emu_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "emu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -3063,7 +2939,7 @@ static struct clk atclk_fck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_CLKSEL_ATCLK_MASK, .clksel = atclk_emu_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "emu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -3075,7 +2951,7 @@ static struct clk traceclk_src_fck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_TRACE_MUX_CTRL_MASK, .clksel = emu_src_clksel, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .clkdm_name = "emu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -3099,7 +2975,6 @@ static struct clk traceclk_fck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_CLKSEL_TRACECLK_MASK, .clksel = traceclk_clksel, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "emu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -3113,7 +2988,7 @@ static struct clk sr1_fck = { .parent = &sys_ck, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_SR1_SHIFT, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &followparent_recalc, }; @@ -3124,7 +2999,7 @@ static struct clk sr2_fck = { .parent = &sys_ck, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_SR2_SHIFT, - .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, + .flags = RATE_PROPAGATES, .recalc = &followparent_recalc, }; @@ -3132,7 +3007,6 @@ static struct clk sr_l4_ick = { .name = "sr_l4_ick", .ops = &clkops_null, /* RMK: missing? */ .parent = &l4_ick, - .flags = CLOCK_IN_OMAP343X, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -3144,7 +3018,6 @@ static struct clk gpt12_fck = { .name = "gpt12_fck", .ops = &clkops_null, .parent = &secure_32k_fck, - .flags = CLOCK_IN_OMAP343X, .recalc = &followparent_recalc, }; @@ -3152,223 +3025,7 @@ static struct clk wdt1_fck = { .name = "wdt1_fck", .ops = &clkops_null, .parent = &secure_32k_fck, - .flags = CLOCK_IN_OMAP343X, - .recalc = &followparent_recalc, -}; - -static struct clk *onchip_34xx_clks[] __initdata = { - &omap_32k_fck, - &virt_12m_ck, - &virt_13m_ck, - &virt_16_8m_ck, - &virt_19_2m_ck, - &virt_26m_ck, - &virt_38_4m_ck, - &osc_sys_ck, - &sys_ck, - &sys_altclk, - &mcbsp_clks, - &sys_clkout1, - &dpll1_ck, - &dpll1_x2_ck, - &dpll1_x2m2_ck, - &dpll2_ck, - &dpll2_m2_ck, - &dpll3_ck, - &core_ck, - &dpll3_x2_ck, - &dpll3_m2_ck, - &dpll3_m2x2_ck, - &dpll3_m3_ck, - &dpll3_m3x2_ck, - &emu_core_alwon_ck, - &dpll4_ck, - &dpll4_x2_ck, - &omap_96m_alwon_fck, - &omap_96m_fck, - &cm_96m_fck, - &virt_omap_54m_fck, - &omap_54m_fck, - &omap_48m_fck, - &omap_12m_fck, - &dpll4_m2_ck, - &dpll4_m2x2_ck, - &dpll4_m3_ck, - &dpll4_m3x2_ck, - &dpll4_m4_ck, - &dpll4_m4x2_ck, - &dpll4_m5_ck, - &dpll4_m5x2_ck, - &dpll4_m6_ck, - &dpll4_m6x2_ck, - &emu_per_alwon_ck, - &dpll5_ck, - &dpll5_m2_ck, - &omap_120m_fck, - &clkout2_src_ck, - &sys_clkout2, - &corex2_fck, - &dpll1_fck, - &mpu_ck, - &arm_fck, - &emu_mpu_alwon_ck, - &dpll2_fck, - &iva2_ck, - &l3_ick, - &l4_ick, - &rm_ick, - &gfx_l3_ck, - &gfx_l3_fck, - &gfx_l3_ick, - &gfx_cg1_ck, - &gfx_cg2_ck, - &sgx_fck, - &sgx_ick, - &d2d_26m_fck, - &gpt10_fck, - &gpt11_fck, - &cpefuse_fck, - &ts_fck, - &usbtll_fck, - &core_96m_fck, - &mmchs3_fck, - &mmchs2_fck, - &mspro_fck, - &mmchs1_fck, - &i2c3_fck, - &i2c2_fck, - &i2c1_fck, - &mcbsp5_fck, - &mcbsp1_fck, - &core_48m_fck, - &mcspi4_fck, - &mcspi3_fck, - &mcspi2_fck, - &mcspi1_fck, - &uart2_fck, - &uart1_fck, - &fshostusb_fck, - &core_12m_fck, - &hdq_fck, - &ssi_ssr_fck, - &ssi_sst_fck, - &core_l3_ick, - &hsotgusb_ick, - &sdrc_ick, - &gpmc_fck, - &security_l3_ick, - &pka_ick, - &core_l4_ick, - &usbtll_ick, - &mmchs3_ick, - &icr_ick, - &aes2_ick, - &sha12_ick, - &des2_ick, - &mmchs2_ick, - &mmchs1_ick, - &mspro_ick, - &hdq_ick, - &mcspi4_ick, - &mcspi3_ick, - &mcspi2_ick, - &mcspi1_ick, - &i2c3_ick, - &i2c2_ick, - &i2c1_ick, - &uart2_ick, - &uart1_ick, - &gpt11_ick, - &gpt10_ick, - &mcbsp5_ick, - &mcbsp1_ick, - &fac_ick, - &mailboxes_ick, - &omapctrl_ick, - &ssi_l4_ick, - &ssi_ick, - &usb_l4_ick, - &security_l4_ick2, - &aes1_ick, - &rng_ick, - &sha11_ick, - &des1_ick, - &dss1_alwon_fck, - &dss_tv_fck, - &dss_96m_fck, - &dss2_alwon_fck, - &dss_ick, - &cam_mclk, - &cam_ick, - &usbhost_120m_fck, - &usbhost_48m_fck, - &usbhost_ick, - &usbhost_sar_fck, - &usim_fck, - &gpt1_fck, - &wkup_32k_fck, - &gpio1_dbck, - &wdt2_fck, - &wkup_l4_ick, - &usim_ick, - &wdt2_ick, - &wdt1_ick, - &gpio1_ick, - &omap_32ksync_ick, - &gpt12_ick, - &gpt1_ick, - &per_96m_fck, - &per_48m_fck, - &uart3_fck, - &gpt2_fck, - &gpt3_fck, - &gpt4_fck, - &gpt5_fck, - &gpt6_fck, - &gpt7_fck, - &gpt8_fck, - &gpt9_fck, - &per_32k_alwon_fck, - &gpio6_dbck, - &gpio5_dbck, - &gpio4_dbck, - &gpio3_dbck, - &gpio2_dbck, - &wdt3_fck, - &per_l4_ick, - &gpio6_ick, - &gpio5_ick, - &gpio4_ick, - &gpio3_ick, - &gpio2_ick, - &wdt3_ick, - &uart3_ick, - &gpt9_ick, - &gpt8_ick, - &gpt7_ick, - &gpt6_ick, - &gpt5_ick, - &gpt4_ick, - &gpt3_ick, - &gpt2_ick, - &mcbsp2_ick, - &mcbsp3_ick, - &mcbsp4_ick, - &mcbsp2_fck, - &mcbsp3_fck, - &mcbsp4_fck, - &emu_src_ck, - &pclk_fck, - &pclkx2_fck, - &atclk_fck, - &traceclk_src_fck, - &traceclk_fck, - &sr1_fck, - &sr2_fck, - &sr_l4_ick, - &secure_32k_fck, - &gpt12_fck, - &wdt1_fck, + .recalc = &followparent_recalc, }; #endif diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 90372131055..e25e1ac64fc 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -21,6 +21,7 @@ config ARCH_OMAP2 config ARCH_OMAP3 bool "TI OMAP3" select CPU_V7 + select COMMON_CLKDEV endchoice diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index 214dc46d6ad..3895ba72979 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -136,10 +136,7 @@ extern const struct clkops clkops_null; #define CONFIG_PARTICIPANT (1 << 10) /* Fundamental clock */ #define ENABLE_ON_INIT (1 << 11) /* Enable upon framework init */ #define INVERT_ENABLE (1 << 12) /* 0 enables, 1 disables */ -/* bits 13-26 are currently free */ -#define CLOCK_IN_OMAP343X (1 << 27) /* clocks common to all 343X */ -#define CLOCK_IN_OMAP3430ES1 (1 << 29) /* 3430ES1 clocks only */ -#define CLOCK_IN_OMAP3430ES2 (1 << 30) /* 3430ES2 clocks only */ +/* bits 13-31 are currently free */ /* Clksel_rate flags */ #define DEFAULT_RATE (1 << 0) -- GitLab From 2b811bb56a008f0f669a1bd82e4d077e75aa059a Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 19 Jan 2009 16:28:32 +0000 Subject: [PATCH 1348/4982] [ARM] omap: remove pre-CLKDEV clk_get/clk_put Signed-off-by: Russell King --- arch/arm/plat-omap/clock.c | 46 -------------------------------------- 1 file changed, 46 deletions(-) diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 6b88f7878a5..5272a2212ab 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -36,45 +36,6 @@ static struct clk_functions *arch_clock; * Standard clock functions defined in include/linux/clk.h *-------------------------------------------------------------------------*/ -#ifndef CONFIG_COMMON_CLKDEV -/* - * Returns a clock. Note that we first try to use device id on the bus - * and clock name. If this fails, we try to use clock name only. - */ -struct clk * clk_get(struct device *dev, const char *id) -{ - struct clk *p, *clk = ERR_PTR(-ENOENT); - int idno; - - if (dev == NULL || dev->bus != &platform_bus_type) - idno = -1; - else - idno = to_platform_device(dev)->id; - - mutex_lock(&clocks_mutex); - - list_for_each_entry(p, &clocks, node) { - if (p->id == idno && strcmp(id, p->name) == 0) { - clk = p; - goto found; - } - } - - list_for_each_entry(p, &clocks, node) { - if (strcmp(id, p->name) == 0) { - clk = p; - break; - } - } - -found: - mutex_unlock(&clocks_mutex); - - return clk; -} -EXPORT_SYMBOL(clk_get); -#endif - int clk_enable(struct clk *clk) { unsigned long flags; @@ -147,13 +108,6 @@ unsigned long clk_get_rate(struct clk *clk) } EXPORT_SYMBOL(clk_get_rate); -#ifndef CONFIG_COMMON_CLKDEV -void clk_put(struct clk *clk) -{ -} -EXPORT_SYMBOL(clk_put); -#endif - /*------------------------------------------------------------------------- * Optional clock functions defined in include/linux/clk.h *-------------------------------------------------------------------------*/ -- GitLab From f1c2543738d18e4398e3d6e27abff6676667975a Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 23 Jan 2009 22:34:09 +0000 Subject: [PATCH 1349/4982] [ARM] omap: provide a dummy clock node By providing a dummy clock node, we can eliminate the SoC conditional clock handing in the OMAP drivers, moving this knowledge out of the driver and into the machine clock support code. Signed-off-by: Russell King --- arch/arm/mach-omap1/clock.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index 829b9b845b8..88c716331ee 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -33,6 +33,26 @@ static const struct clkops clkops_dspck; #include "clock.h" +static int clk_omap1_dummy_enable(struct clk *clk) +{ + return 0; +} + +static void clk_omap1_dummy_disable(struct clk *clk) +{ +} + +static const struct clkops clkops_dummy = { + .enable = clk_omap1_dummy_enable, + .disable = clk_omap1_dummy_disable, +}; + +static struct clk dummy_ck = { + .name = "dummy", + .ops = &clkops_dummy, + .flags = RATE_FIXED, +}; + struct omap_clk { u32 cpu; struct clk_lookup lk; -- GitLab From 39a80c7f379e1c1d3e63b204b8353b7381d0a3d5 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 19 Jan 2009 20:44:33 +0000 Subject: [PATCH 1350/4982] [ARM] omap: watchdog: convert clocks to match by devid and conid This eliminates the need for separate OMAP24xx and OMAP34xx clock requesting code sections. Signed-off-by: Russell King --- arch/arm/mach-omap1/clock.c | 2 +- arch/arm/mach-omap2/clock24xx.c | 4 +- arch/arm/mach-omap2/clock34xx.c | 4 +- drivers/watchdog/omap_wdt.c | 93 +++++++++------------------------ 4 files changed, 30 insertions(+), 73 deletions(-) diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index 88c716331ee..8ae7827bb8b 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -85,7 +85,7 @@ static struct omap_clk omap_clks[] = { CLK(NULL, "arm_gpio_ck", &arm_gpio_ck, CK_1510 | CK_310), CLK(NULL, "armxor_ck", &armxor_ck.clk, CK_16XX | CK_1510 | CK_310), CLK(NULL, "armtim_ck", &armtim_ck.clk, CK_16XX | CK_1510 | CK_310), - CLK(NULL, "armwdt_ck", &armwdt_ck.clk, CK_16XX | CK_1510 | CK_310), + CLK("omap_wdt", "fck", &armwdt_ck.clk, CK_16XX | CK_1510 | CK_310), CLK(NULL, "arminth_ck", &arminth_ck1510, CK_1510 | CK_310), CLK(NULL, "arminth_ck", &arminth_ck16xx, CK_16XX), /* CK_GEN2 clocks */ diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index 36093ea878a..6a6278e5bbc 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -163,8 +163,8 @@ static struct omap_clk omap24xx_clks[] = { CLK(NULL, "uart3_fck", &uart3_fck, CK_243X | CK_242X), CLK(NULL, "gpios_ick", &gpios_ick, CK_243X | CK_242X), CLK(NULL, "gpios_fck", &gpios_fck, CK_243X | CK_242X), - CLK(NULL, "mpu_wdt_ick", &mpu_wdt_ick, CK_243X | CK_242X), - CLK(NULL, "mpu_wdt_fck", &mpu_wdt_fck, CK_243X | CK_242X), + CLK("omap_wdt", "ick", &mpu_wdt_ick, CK_243X | CK_242X), + CLK("omap_wdt", "fck", &mpu_wdt_fck, CK_243X | CK_242X), CLK(NULL, "sync_32k_ick", &sync_32k_ick, CK_243X | CK_242X), CLK(NULL, "wdt1_ick", &wdt1_ick, CK_243X | CK_242X), CLK(NULL, "omapctrl_ick", &omapctrl_ick, CK_243X | CK_242X), diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 2c22750016c..b3334b355cb 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -214,10 +214,10 @@ static struct omap_clk omap34xx_clks[] = { CLK(NULL, "gpt1_fck", &gpt1_fck, CK_343X), CLK(NULL, "wkup_32k_fck", &wkup_32k_fck, CK_343X), CLK(NULL, "gpio1_dbck", &gpio1_dbck, CK_343X), - CLK(NULL, "wdt2_fck", &wdt2_fck, CK_343X), + CLK("omap_wdt", "fck", &wdt2_fck, CK_343X), CLK(NULL, "wkup_l4_ick", &wkup_l4_ick, CK_343X), CLK(NULL, "usim_ick", &usim_ick, CK_3430ES2), - CLK(NULL, "wdt2_ick", &wdt2_ick, CK_343X), + CLK("omap_wdt", "ick", &wdt2_ick, CK_343X), CLK(NULL, "wdt1_ick", &wdt1_ick, CK_343X), CLK(NULL, "gpio1_ick", &gpio1_ick, CK_343X), CLK(NULL, "omap_32ksync_ick", &omap_32ksync_ick, CK_343X), diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 2f2ce7429f5..1a4c699762e 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -60,9 +60,8 @@ struct omap_wdt_dev { void __iomem *base; /* physical */ struct device *dev; int omap_wdt_users; - struct clk *armwdt_ck; - struct clk *mpu_wdt_ick; - struct clk *mpu_wdt_fck; + struct clk *ick; + struct clk *fck; struct resource *mem; struct miscdevice omap_wdt_miscdev; }; @@ -146,13 +145,9 @@ static int omap_wdt_open(struct inode *inode, struct file *file) if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users))) return -EBUSY; - if (cpu_is_omap16xx()) - clk_enable(wdev->armwdt_ck); /* Enable the clock */ - - if (cpu_is_omap24xx() || cpu_is_omap34xx()) { - clk_enable(wdev->mpu_wdt_ick); /* Enable the interface clock */ - clk_enable(wdev->mpu_wdt_fck); /* Enable the functional clock */ - } + if (wdev->ick) + clk_enable(wdev->ick); /* Enable the interface clock */ + clk_enable(wdev->fck); /* Enable the functional clock */ /* initialize prescaler */ while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01) @@ -181,13 +176,9 @@ static int omap_wdt_release(struct inode *inode, struct file *file) omap_wdt_disable(wdev); - if (cpu_is_omap16xx()) - clk_disable(wdev->armwdt_ck); /* Disable the clock */ - - if (cpu_is_omap24xx() || cpu_is_omap34xx()) { - clk_disable(wdev->mpu_wdt_ick); /* Disable the clock */ - clk_disable(wdev->mpu_wdt_fck); /* Disable the clock */ - } + if (wdev->ick) + clk_disable(wdev->ick); + clk_disable(wdev->fck); #else printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n"); #endif @@ -303,44 +294,21 @@ static int __init omap_wdt_probe(struct platform_device *pdev) wdev->omap_wdt_users = 0; wdev->mem = mem; - if (cpu_is_omap16xx()) { - wdev->armwdt_ck = clk_get(&pdev->dev, "armwdt_ck"); - if (IS_ERR(wdev->armwdt_ck)) { - ret = PTR_ERR(wdev->armwdt_ck); - wdev->armwdt_ck = NULL; + if (cpu_is_omap24xx() || cpu_is_omap34xx()) { + wdev->ick = clk_get(&pdev->dev, "ick"); + if (IS_ERR(wdev->ick)) { + ret = PTR_ERR(wdev->ick); + wdev->ick = NULL; goto err_clk; } } - - if (cpu_is_omap24xx()) { - wdev->mpu_wdt_ick = clk_get(&pdev->dev, "mpu_wdt_ick"); - if (IS_ERR(wdev->mpu_wdt_ick)) { - ret = PTR_ERR(wdev->mpu_wdt_ick); - wdev->mpu_wdt_ick = NULL; - goto err_clk; - } - wdev->mpu_wdt_fck = clk_get(&pdev->dev, "mpu_wdt_fck"); - if (IS_ERR(wdev->mpu_wdt_fck)) { - ret = PTR_ERR(wdev->mpu_wdt_fck); - wdev->mpu_wdt_fck = NULL; - goto err_clk; - } + wdev->fck = clk_get(&pdev->dev, "fck"); + if (IS_ERR(wdev->fck)) { + ret = PTR_ERR(wdev->fck); + wdev->fck = NULL; + goto err_clk; } - if (cpu_is_omap34xx()) { - wdev->mpu_wdt_ick = clk_get(&pdev->dev, "wdt2_ick"); - if (IS_ERR(wdev->mpu_wdt_ick)) { - ret = PTR_ERR(wdev->mpu_wdt_ick); - wdev->mpu_wdt_ick = NULL; - goto err_clk; - } - wdev->mpu_wdt_fck = clk_get(&pdev->dev, "wdt2_fck"); - if (IS_ERR(wdev->mpu_wdt_fck)) { - ret = PTR_ERR(wdev->mpu_wdt_fck); - wdev->mpu_wdt_fck = NULL; - goto err_clk; - } - } wdev->base = ioremap(res->start, res->end - res->start + 1); if (!wdev->base) { ret = -ENOMEM; @@ -380,12 +348,10 @@ err_ioremap: wdev->base = NULL; err_clk: - if (wdev->armwdt_ck) - clk_put(wdev->armwdt_ck); - if (wdev->mpu_wdt_ick) - clk_put(wdev->mpu_wdt_ick); - if (wdev->mpu_wdt_fck) - clk_put(wdev->mpu_wdt_fck); + if (wdev->ick) + clk_put(wdev->ick); + if (wdev->fck) + clk_put(wdev->fck); kfree(wdev); err_kzalloc: @@ -417,20 +383,11 @@ static int omap_wdt_remove(struct platform_device *pdev) release_mem_region(res->start, res->end - res->start + 1); platform_set_drvdata(pdev, NULL); - if (wdev->armwdt_ck) { - clk_put(wdev->armwdt_ck); - wdev->armwdt_ck = NULL; + if (wdev->ick) { + clk_put(wdev->ick); } - if (wdev->mpu_wdt_ick) { - clk_put(wdev->mpu_wdt_ick); - wdev->mpu_wdt_ick = NULL; - } - - if (wdev->mpu_wdt_fck) { - clk_put(wdev->mpu_wdt_fck); - wdev->mpu_wdt_fck = NULL; - } + clk_put(wdev->fck); iounmap(wdev->base); kfree(wdev); -- GitLab From 4c5e1946b5f89c33e3bc8ed73fa7ba8f31e37cc5 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 23 Jan 2009 12:48:37 +0000 Subject: [PATCH 1351/4982] [ARM] omap: watchdog: provide a dummy ick for OMAP1 Eliminate the OMAP1 vs OMAP2 clock knowledge in the watchdog driver. Signed-off-by: Russell King --- arch/arm/mach-omap1/clock.c | 2 ++ drivers/watchdog/omap_wdt.c | 23 ++++++++--------------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index 8ae7827bb8b..758abaadaf3 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -86,6 +86,8 @@ static struct omap_clk omap_clks[] = { CLK(NULL, "armxor_ck", &armxor_ck.clk, CK_16XX | CK_1510 | CK_310), CLK(NULL, "armtim_ck", &armtim_ck.clk, CK_16XX | CK_1510 | CK_310), CLK("omap_wdt", "fck", &armwdt_ck.clk, CK_16XX | CK_1510 | CK_310), + CLK("omap_wdt", "ick", &armper_ck.clk, CK_16XX), + CLK("omap_wdt", "ick", &dummy_ck, CK_1510 | CK_310), CLK(NULL, "arminth_ck", &arminth_ck1510, CK_1510 | CK_310), CLK(NULL, "arminth_ck", &arminth_ck16xx, CK_16XX), /* CK_GEN2 clocks */ diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 1a4c699762e..aa5ad6e33f0 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -145,8 +145,7 @@ static int omap_wdt_open(struct inode *inode, struct file *file) if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users))) return -EBUSY; - if (wdev->ick) - clk_enable(wdev->ick); /* Enable the interface clock */ + clk_enable(wdev->ick); /* Enable the interface clock */ clk_enable(wdev->fck); /* Enable the functional clock */ /* initialize prescaler */ @@ -176,8 +175,7 @@ static int omap_wdt_release(struct inode *inode, struct file *file) omap_wdt_disable(wdev); - if (wdev->ick) - clk_disable(wdev->ick); + clk_disable(wdev->ick); clk_disable(wdev->fck); #else printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n"); @@ -294,13 +292,11 @@ static int __init omap_wdt_probe(struct platform_device *pdev) wdev->omap_wdt_users = 0; wdev->mem = mem; - if (cpu_is_omap24xx() || cpu_is_omap34xx()) { - wdev->ick = clk_get(&pdev->dev, "ick"); - if (IS_ERR(wdev->ick)) { - ret = PTR_ERR(wdev->ick); - wdev->ick = NULL; - goto err_clk; - } + wdev->ick = clk_get(&pdev->dev, "ick"); + if (IS_ERR(wdev->ick)) { + ret = PTR_ERR(wdev->ick); + wdev->ick = NULL; + goto err_clk; } wdev->fck = clk_get(&pdev->dev, "fck"); if (IS_ERR(wdev->fck)) { @@ -383,10 +379,7 @@ static int omap_wdt_remove(struct platform_device *pdev) release_mem_region(res->start, res->end - res->start + 1); platform_set_drvdata(pdev, NULL); - if (wdev->ick) { - clk_put(wdev->ick); - } - + clk_put(wdev->ick); clk_put(wdev->fck); iounmap(wdev->base); -- GitLab From 5c9e02b1abcb227f47529ad72cc4a3234cddae49 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 19 Jan 2009 20:53:30 +0000 Subject: [PATCH 1352/4982] [ARM] omap: MMC: convert clocks to match by devid and conid Convert OMAP MMC driver to match clocks using the device ID and a connection ID rather than a clock name. This allows us to eliminate the OMAP1/OMAP2 differences for the function clock. Signed-off-by: Russell King --- arch/arm/mach-omap1/clock.c | 4 ++-- arch/arm/mach-omap2/clock24xx.c | 4 ++-- drivers/mmc/host/omap.c | 7 ++----- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index 758abaadaf3..3015e852965 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -124,8 +124,8 @@ static struct omap_clk omap_clks[] = { CLK(NULL, "mclk", &mclk_16xx, CK_16XX), CLK(NULL, "bclk", &bclk_1510, CK_1510 | CK_310), CLK(NULL, "bclk", &bclk_16xx, CK_16XX), - CLK("mmci-omap.0", "mmc_ck", &mmc1_ck, CK_16XX | CK_1510 | CK_310), - CLK("mmci-omap.1", "mmc_ck", &mmc2_ck, CK_16XX), + CLK("mmci-omap.0", "fck", &mmc1_ck, CK_16XX | CK_1510 | CK_310), + CLK("mmci-omap.1", "fck", &mmc2_ck, CK_16XX), /* Virtual clocks */ CLK(NULL, "mpu", &virtual_ck_mpu, CK_16XX | CK_1510 | CK_310), CLK("i2c_omap.1", "i2c_fck", &i2c_fck, CK_16XX | CK_1510 | CK_310), diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index 6a6278e5bbc..aca4ca42bf4 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -178,8 +178,8 @@ static struct omap_clk omap24xx_clks[] = { CLK(NULL, "wdt3_fck", &wdt3_fck, CK_242X), CLK(NULL, "mspro_ick", &mspro_ick, CK_243X | CK_242X), CLK(NULL, "mspro_fck", &mspro_fck, CK_243X | CK_242X), - CLK(NULL, "mmc_ick", &mmc_ick, CK_242X), - CLK(NULL, "mmc_fck", &mmc_fck, CK_242X), + CLK("mmci-omap.0", "ick", &mmc_ick, CK_242X), + CLK("mmci-omap.0", "fck", &mmc_fck, CK_242X), CLK(NULL, "fac_ick", &fac_ick, CK_243X | CK_242X), CLK(NULL, "fac_fck", &fac_fck, CK_243X | CK_242X), CLK(NULL, "eac_ick", &eac_ick, CK_242X), diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 67d7b7fef08..15eb8834376 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -1461,16 +1461,13 @@ static int __init mmc_omap_probe(struct platform_device *pdev) goto err_ioremap; if (cpu_is_omap24xx()) { - host->iclk = clk_get(&pdev->dev, "mmc_ick"); + host->iclk = clk_get(&pdev->dev, "ick"); if (IS_ERR(host->iclk)) goto err_free_mmc_host; clk_enable(host->iclk); } - if (!cpu_is_omap24xx()) - host->fclk = clk_get(&pdev->dev, "mmc_ck"); - else - host->fclk = clk_get(&pdev->dev, "mmc_fck"); + host->fclk = clk_get(&pdev->dev, "fck"); if (IS_ERR(host->fclk)) { ret = PTR_ERR(host->fclk); -- GitLab From d4a36645a1a76e5294c1b00682fb849fc53ccd80 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 23 Jan 2009 19:03:37 +0000 Subject: [PATCH 1353/4982] [ARM] omap: MMC: provide a dummy ick for OMAP1 Eliminate the OMAP1 vs OMAP2 clock knowledge in the MMC driver. Signed-off-by: Russell King --- arch/arm/mach-omap1/clock.c | 2 ++ drivers/mmc/host/omap.c | 19 ++++++++----------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index 3015e852965..61ace02e7dd 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -125,7 +125,9 @@ static struct omap_clk omap_clks[] = { CLK(NULL, "bclk", &bclk_1510, CK_1510 | CK_310), CLK(NULL, "bclk", &bclk_16xx, CK_16XX), CLK("mmci-omap.0", "fck", &mmc1_ck, CK_16XX | CK_1510 | CK_310), + CLK("mmci-omap.0", "ick", &armper_ck.clk, CK_16XX | CK_1510 | CK_310), CLK("mmci-omap.1", "fck", &mmc2_ck, CK_16XX), + CLK("mmci-omap.1", "ick", &armper_ck.clk, CK_16XX), /* Virtual clocks */ CLK(NULL, "mpu", &virtual_ck_mpu, CK_16XX | CK_1510 | CK_310), CLK("i2c_omap.1", "i2c_fck", &i2c_fck, CK_16XX | CK_1510 | CK_310), diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 15eb8834376..5570849188c 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -1460,15 +1460,12 @@ static int __init mmc_omap_probe(struct platform_device *pdev) if (!host->virt_base) goto err_ioremap; - if (cpu_is_omap24xx()) { - host->iclk = clk_get(&pdev->dev, "ick"); - if (IS_ERR(host->iclk)) - goto err_free_mmc_host; - clk_enable(host->iclk); - } + host->iclk = clk_get(&pdev->dev, "ick"); + if (IS_ERR(host->iclk)) + goto err_free_mmc_host; + clk_enable(host->iclk); host->fclk = clk_get(&pdev->dev, "fck"); - if (IS_ERR(host->fclk)) { ret = PTR_ERR(host->fclk); goto err_free_iclk; @@ -1533,10 +1530,10 @@ static int mmc_omap_remove(struct platform_device *pdev) if (host->pdata->cleanup) host->pdata->cleanup(&pdev->dev); - if (host->iclk && !IS_ERR(host->iclk)) - clk_put(host->iclk); - if (host->fclk && !IS_ERR(host->fclk)) - clk_put(host->fclk); + mmc_omap_fclk_enable(host, 0); + clk_put(host->fclk); + clk_disable(host->iclk); + clk_put(host->iclk); iounmap(host->virt_base); release_mem_region(pdev->resource[0].start, -- GitLab From 1b5715ec471d1def9722e22b6cb1d24841b5e290 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 19 Jan 2009 20:49:37 +0000 Subject: [PATCH 1354/4982] [ARM] omap: mcspi: new short connection id names ... rather than the clock names themselves. Signed-off-by: Russell King --- arch/arm/mach-omap2/clock24xx.c | 12 ++++++------ arch/arm/mach-omap2/clock34xx.c | 16 ++++++++-------- drivers/spi/omap2_mcspi.c | 4 ++-- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index aca4ca42bf4..ac038035c1c 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -149,12 +149,12 @@ static struct omap_clk omap24xx_clks[] = { CLK("omap-mcbsp.4", "mcbsp_fck", &mcbsp4_fck, CK_243X), CLK("omap-mcbsp.5", "mcbsp_ick", &mcbsp5_ick, CK_243X), CLK("omap-mcbsp.5", "mcbsp_fck", &mcbsp5_fck, CK_243X), - CLK("omap2_mcspi.1", "mcspi_ick", &mcspi1_ick, CK_243X | CK_242X), - CLK("omap2_mcspi.1", "mcspi_fck", &mcspi1_fck, CK_243X | CK_242X), - CLK("omap2_mcspi.2", "mcspi_ick", &mcspi2_ick, CK_243X | CK_242X), - CLK("omap2_mcspi.2", "mcspi_fck", &mcspi2_fck, CK_243X | CK_242X), - CLK("omap2_mcspi.3", "mcspi_ick", &mcspi3_ick, CK_243X), - CLK("omap2_mcspi.3", "mcspi_fck", &mcspi3_fck, CK_243X), + CLK("omap2_mcspi.1", "ick", &mcspi1_ick, CK_243X | CK_242X), + CLK("omap2_mcspi.1", "fck", &mcspi1_fck, CK_243X | CK_242X), + CLK("omap2_mcspi.2", "ick", &mcspi2_ick, CK_243X | CK_242X), + CLK("omap2_mcspi.2", "fck", &mcspi2_fck, CK_243X | CK_242X), + CLK("omap2_mcspi.3", "ick", &mcspi3_ick, CK_243X), + CLK("omap2_mcspi.3", "fck", &mcspi3_fck, CK_243X), CLK(NULL, "uart1_ick", &uart1_ick, CK_243X | CK_242X), CLK(NULL, "uart1_fck", &uart1_fck, CK_243X | CK_242X), CLK(NULL, "uart2_ick", &uart2_ick, CK_243X | CK_242X), diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index b3334b355cb..d0bfae5a2f4 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -147,10 +147,10 @@ static struct omap_clk omap34xx_clks[] = { CLK("omap-mcbsp.5", "mcbsp_fck", &mcbsp5_fck, CK_343X), CLK("omap-mcbsp.1", "mcbsp_fck", &mcbsp1_fck, CK_343X), CLK(NULL, "core_48m_fck", &core_48m_fck, CK_343X), - CLK("omap2_mcspi.4", "mcspi_fck", &mcspi4_fck, CK_343X), - CLK("omap2_mcspi.3", "mcspi_fck", &mcspi3_fck, CK_343X), - CLK("omap2_mcspi.2", "mcspi_fck", &mcspi2_fck, CK_343X), - CLK("omap2_mcspi.1", "mcspi_fck", &mcspi1_fck, CK_343X), + CLK("omap2_mcspi.4", "fck", &mcspi4_fck, CK_343X), + CLK("omap2_mcspi.3", "fck", &mcspi3_fck, CK_343X), + CLK("omap2_mcspi.2", "fck", &mcspi2_fck, CK_343X), + CLK("omap2_mcspi.1", "fck", &mcspi1_fck, CK_343X), CLK(NULL, "uart2_fck", &uart2_fck, CK_343X), CLK(NULL, "uart1_fck", &uart1_fck, CK_343X), CLK(NULL, "fshostusb_fck", &fshostusb_fck, CK_3430ES1), @@ -175,10 +175,10 @@ static struct omap_clk omap34xx_clks[] = { CLK("mmci-omap-hs.0", "mmchs_ick", &mmchs1_ick, CK_343X), CLK(NULL, "mspro_ick", &mspro_ick, CK_343X), CLK(NULL, "hdq_ick", &hdq_ick, CK_343X), - CLK("omap2_mcspi.4", "mcspi_ick", &mcspi4_ick, CK_343X), - CLK("omap2_mcspi.3", "mcspi_ick", &mcspi3_ick, CK_343X), - CLK("omap2_mcspi.2", "mcspi_ick", &mcspi2_ick, CK_343X), - CLK("omap2_mcspi.1", "mcspi_ick", &mcspi1_ick, CK_343X), + CLK("omap2_mcspi.4", "ick", &mcspi4_ick, CK_343X), + CLK("omap2_mcspi.3", "ick", &mcspi3_ick, CK_343X), + CLK("omap2_mcspi.2", "ick", &mcspi2_ick, CK_343X), + CLK("omap2_mcspi.1", "ick", &mcspi1_ick, CK_343X), CLK("i2c_omap.3", "i2c_ick", &i2c3_ick, CK_343X), CLK("i2c_omap.2", "i2c_ick", &i2c2_ick, CK_343X), CLK("i2c_omap.1", "i2c_ick", &i2c1_ick, CK_343X), diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c index 454a2712e62..b91ee1ae975 100644 --- a/drivers/spi/omap2_mcspi.c +++ b/drivers/spi/omap2_mcspi.c @@ -1021,13 +1021,13 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev) spin_lock_init(&mcspi->lock); INIT_LIST_HEAD(&mcspi->msg_queue); - mcspi->ick = clk_get(&pdev->dev, "mcspi_ick"); + mcspi->ick = clk_get(&pdev->dev, "ick"); if (IS_ERR(mcspi->ick)) { dev_dbg(&pdev->dev, "can't get mcspi_ick\n"); status = PTR_ERR(mcspi->ick); goto err1a; } - mcspi->fck = clk_get(&pdev->dev, "mcspi_fck"); + mcspi->fck = clk_get(&pdev->dev, "fck"); if (IS_ERR(mcspi->fck)) { dev_dbg(&pdev->dev, "can't get mcspi_fck\n"); status = PTR_ERR(mcspi->fck); -- GitLab From b820ce4e6736ddad7ccda528e10aaf37ad3f13f9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 23 Jan 2009 10:26:46 +0000 Subject: [PATCH 1355/4982] [ARM] omap: mcbsp: convert to use fck/ick clocks directly Rather than introducing a special 'mcbsp_clk' with code behind it in mach-omap*/mcbsp.c to handle the SoC specifics, arrange for the mcbsp driver to be like any other driver. mcbsp requests its fck and ick clocks directly, and the SoC specific code deals with selecting the correct clock. There is one oddity to deal with - OMAP1 fiddles with the DSP clocks and DSP reset, so we move this to the two callback functions. Signed-off-by: Russell King --- arch/arm/mach-omap1/clock.c | 9 +++ arch/arm/mach-omap1/mcbsp.c | 52 ++++++++------ arch/arm/mach-omap2/clock24xx.c | 20 +++--- arch/arm/mach-omap2/clock34xx.c | 20 +++--- arch/arm/mach-omap2/mcbsp.c | 26 ------- arch/arm/plat-omap/include/mach/mcbsp.h | 6 +- arch/arm/plat-omap/mcbsp.c | 90 ++++++++++--------------- 7 files changed, 100 insertions(+), 123 deletions(-) diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index 61ace02e7dd..b62da4c9563 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -132,6 +132,15 @@ static struct omap_clk omap_clks[] = { CLK(NULL, "mpu", &virtual_ck_mpu, CK_16XX | CK_1510 | CK_310), CLK("i2c_omap.1", "i2c_fck", &i2c_fck, CK_16XX | CK_1510 | CK_310), CLK("i2c_omap.1", "i2c_ick", &i2c_ick, CK_16XX), + CLK("omap-mcbsp.1", "ick", &dspper_ck, CK_16XX), + CLK("omap-mcbsp.1", "ick", &dummy_ck, CK_1510 | CK_310), + CLK("omap-mcbsp.2", "ick", &armper_ck.clk, CK_16XX), + CLK("omap-mcbsp.2", "ick", &dummy_ck, CK_1510 | CK_310), + CLK("omap-mcbsp.3", "ick", &dspper_ck, CK_16XX), + CLK("omap-mcbsp.3", "ick", &dummy_ck, CK_1510 | CK_310), + CLK("omap-mcbsp.1", "fck", &dspxor_ck, CK_16XX | CK_1510 | CK_310), + CLK("omap-mcbsp.2", "fck", &armper_ck.clk, CK_16XX | CK_1510 | CK_310), + CLK("omap-mcbsp.3", "fck", &dspxor_ck, CK_16XX | CK_1510 | CK_310), }; static int omap1_clk_enable_generic(struct clk * clk); diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c index 575ba31295c..d040c3f1027 100644 --- a/arch/arm/mach-omap1/mcbsp.c +++ b/arch/arm/mach-omap1/mcbsp.c @@ -28,9 +28,9 @@ #define DPS_RSTCT2_PER_EN (1 << 0) #define DSP_RSTCT2_WD_PER_EN (1 << 1) -#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) -const char *clk_names[] = { "dsp_ck", "api_ck", "dspxor_ck" }; -#endif +static int dsp_use; +static struct clk *api_clk; +static struct clk *dsp_clk; static void omap1_mcbsp_request(unsigned int id) { @@ -39,20 +39,40 @@ static void omap1_mcbsp_request(unsigned int id) * are DSP public peripherals. */ if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) { - omap_dsp_request_mem(); - /* - * DSP external peripheral reset - * FIXME: This should be moved to dsp code - */ - __raw_writew(__raw_readw(DSP_RSTCT2) | DPS_RSTCT2_PER_EN | - DSP_RSTCT2_WD_PER_EN, DSP_RSTCT2); + if (dsp_use++ == 0) { + api_clk = clk_get(NULL, "api_clk"); + dsp_clk = clk_get(NULL, "dsp_clk"); + if (!IS_ERR(api_clk) && !IS_ERR(dsp_clk)) { + clk_enable(api_clk); + clk_enable(dsp_clk); + + omap_dsp_request_mem(); + /* + * DSP external peripheral reset + * FIXME: This should be moved to dsp code + */ + __raw_writew(__raw_readw(DSP_RSTCT2) | DPS_RSTCT2_PER_EN | + DSP_RSTCT2_WD_PER_EN, DSP_RSTCT2); + } + } } } static void omap1_mcbsp_free(unsigned int id) { - if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) - omap_dsp_release_mem(); + if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) { + if (--dsp_use == 0) { + omap_dsp_release_mem(); + if (!IS_ERR(api_clk)) { + clk_disable(api_clk); + clk_put(api_clk); + } + if (!IS_ERR(dsp_clk)) { + clk_disable(dsp_clk); + clk_put(dsp_clk); + } + } + } } static struct omap_mcbsp_ops omap1_mcbsp_ops = { @@ -94,8 +114,6 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = { .rx_irq = INT_McBSP1RX, .tx_irq = INT_McBSP1TX, .ops = &omap1_mcbsp_ops, - .clk_names = clk_names, - .num_clks = 3, }, { .phys_base = OMAP1510_MCBSP2_BASE, @@ -112,8 +130,6 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = { .rx_irq = INT_McBSP3RX, .tx_irq = INT_McBSP3TX, .ops = &omap1_mcbsp_ops, - .clk_names = clk_names, - .num_clks = 3, }, }; #define OMAP15XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap15xx_mcbsp_pdata) @@ -131,8 +147,6 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = { .rx_irq = INT_McBSP1RX, .tx_irq = INT_McBSP1TX, .ops = &omap1_mcbsp_ops, - .clk_names = clk_names, - .num_clks = 3, }, { .phys_base = OMAP1610_MCBSP2_BASE, @@ -149,8 +163,6 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = { .rx_irq = INT_McBSP3RX, .tx_irq = INT_McBSP3TX, .ops = &omap1_mcbsp_ops, - .clk_names = clk_names, - .num_clks = 3, }, }; #define OMAP16XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap16xx_mcbsp_pdata) diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index ac038035c1c..ea21d55a207 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -139,16 +139,16 @@ static struct omap_clk omap24xx_clks[] = { CLK(NULL, "gpt11_fck", &gpt11_fck, CK_243X | CK_242X), CLK(NULL, "gpt12_ick", &gpt12_ick, CK_243X | CK_242X), CLK(NULL, "gpt12_fck", &gpt12_fck, CK_243X | CK_242X), - CLK("omap-mcbsp.1", "mcbsp_ick", &mcbsp1_ick, CK_243X | CK_242X), - CLK("omap-mcbsp.1", "mcbsp_fck", &mcbsp1_fck, CK_243X | CK_242X), - CLK("omap-mcbsp.2", "mcbsp_ick", &mcbsp2_ick, CK_243X | CK_242X), - CLK("omap-mcbsp.2", "mcbsp_fck", &mcbsp2_fck, CK_243X | CK_242X), - CLK("omap-mcbsp.3", "mcbsp_ick", &mcbsp3_ick, CK_243X), - CLK("omap-mcbsp.3", "mcbsp_fck", &mcbsp3_fck, CK_243X), - CLK("omap-mcbsp.4", "mcbsp_ick", &mcbsp4_ick, CK_243X), - CLK("omap-mcbsp.4", "mcbsp_fck", &mcbsp4_fck, CK_243X), - CLK("omap-mcbsp.5", "mcbsp_ick", &mcbsp5_ick, CK_243X), - CLK("omap-mcbsp.5", "mcbsp_fck", &mcbsp5_fck, CK_243X), + CLK("omap-mcbsp.1", "ick", &mcbsp1_ick, CK_243X | CK_242X), + CLK("omap-mcbsp.1", "fck", &mcbsp1_fck, CK_243X | CK_242X), + CLK("omap-mcbsp.2", "ick", &mcbsp2_ick, CK_243X | CK_242X), + CLK("omap-mcbsp.2", "fck", &mcbsp2_fck, CK_243X | CK_242X), + CLK("omap-mcbsp.3", "ick", &mcbsp3_ick, CK_243X), + CLK("omap-mcbsp.3", "fck", &mcbsp3_fck, CK_243X), + CLK("omap-mcbsp.4", "ick", &mcbsp4_ick, CK_243X), + CLK("omap-mcbsp.4", "fck", &mcbsp4_fck, CK_243X), + CLK("omap-mcbsp.5", "ick", &mcbsp5_ick, CK_243X), + CLK("omap-mcbsp.5", "fck", &mcbsp5_fck, CK_243X), CLK("omap2_mcspi.1", "ick", &mcspi1_ick, CK_243X | CK_242X), CLK("omap2_mcspi.1", "fck", &mcspi1_fck, CK_243X | CK_242X), CLK("omap2_mcspi.2", "ick", &mcspi2_ick, CK_243X | CK_242X), diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index d0bfae5a2f4..a70aa2eaf05 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -144,8 +144,8 @@ static struct omap_clk omap34xx_clks[] = { CLK("i2c_omap.3", "i2c_fck", &i2c3_fck, CK_343X), CLK("i2c_omap.2", "i2c_fck", &i2c2_fck, CK_343X), CLK("i2c_omap.1", "i2c_fck", &i2c1_fck, CK_343X), - CLK("omap-mcbsp.5", "mcbsp_fck", &mcbsp5_fck, CK_343X), - CLK("omap-mcbsp.1", "mcbsp_fck", &mcbsp1_fck, CK_343X), + CLK("omap-mcbsp.5", "fck", &mcbsp5_fck, CK_343X), + CLK("omap-mcbsp.1", "fck", &mcbsp1_fck, CK_343X), CLK(NULL, "core_48m_fck", &core_48m_fck, CK_343X), CLK("omap2_mcspi.4", "fck", &mcspi4_fck, CK_343X), CLK("omap2_mcspi.3", "fck", &mcspi3_fck, CK_343X), @@ -186,8 +186,8 @@ static struct omap_clk omap34xx_clks[] = { CLK(NULL, "uart1_ick", &uart1_ick, CK_343X), CLK(NULL, "gpt11_ick", &gpt11_ick, CK_343X), CLK(NULL, "gpt10_ick", &gpt10_ick, CK_343X), - CLK("omap-mcbsp.5", "mcbsp_ick", &mcbsp5_ick, CK_343X), - CLK("omap-mcbsp.1", "mcbsp_ick", &mcbsp1_ick, CK_343X), + CLK("omap-mcbsp.5", "ick", &mcbsp5_ick, CK_343X), + CLK("omap-mcbsp.1", "ick", &mcbsp1_ick, CK_343X), CLK(NULL, "fac_ick", &fac_ick, CK_3430ES1), CLK(NULL, "mailboxes_ick", &mailboxes_ick, CK_343X), CLK(NULL, "omapctrl_ick", &omapctrl_ick, CK_343X), @@ -257,12 +257,12 @@ static struct omap_clk omap34xx_clks[] = { CLK(NULL, "gpt4_ick", &gpt4_ick, CK_343X), CLK(NULL, "gpt3_ick", &gpt3_ick, CK_343X), CLK(NULL, "gpt2_ick", &gpt2_ick, CK_343X), - CLK("omap-mcbsp.2", "mcbsp_ick", &mcbsp2_ick, CK_343X), - CLK("omap-mcbsp.3", "mcbsp_ick", &mcbsp3_ick, CK_343X), - CLK("omap-mcbsp.4", "mcbsp_ick", &mcbsp4_ick, CK_343X), - CLK("omap-mcbsp.2", "mcbsp_fck", &mcbsp2_fck, CK_343X), - CLK("omap-mcbsp.3", "mcbsp_fck", &mcbsp3_fck, CK_343X), - CLK("omap-mcbsp.4", "mcbsp_fck", &mcbsp4_fck, CK_343X), + CLK("omap-mcbsp.2", "ick", &mcbsp2_ick, CK_343X), + CLK("omap-mcbsp.3", "ick", &mcbsp3_ick, CK_343X), + CLK("omap-mcbsp.4", "ick", &mcbsp4_ick, CK_343X), + CLK("omap-mcbsp.2", "fck", &mcbsp2_fck, CK_343X), + CLK("omap-mcbsp.3", "fck", &mcbsp3_fck, CK_343X), + CLK("omap-mcbsp.4", "fck", &mcbsp4_fck, CK_343X), CLK(NULL, "emu_src_ck", &emu_src_ck, CK_343X), CLK(NULL, "pclk_fck", &pclk_fck, CK_343X), CLK(NULL, "pclkx2_fck", &pclkx2_fck, CK_343X), diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index a9e631fc113..a5c0f0435cd 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -24,8 +24,6 @@ #include #include -const char *clk_names[] = { "mcbsp_ick", "mcbsp_fck" }; - static void omap2_mcbsp2_mux_setup(void) { omap_cfg_reg(Y15_24XX_MCBSP2_CLKX); @@ -57,8 +55,6 @@ static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP1_IRQ_RX, .tx_irq = INT_24XX_MCBSP1_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_names = clk_names, - .num_clks = 2, }, { .phys_base = OMAP24XX_MCBSP2_BASE, @@ -67,8 +63,6 @@ static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP2_IRQ_RX, .tx_irq = INT_24XX_MCBSP2_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_names = clk_names, - .num_clks = 2, }, }; #define OMAP2420_MCBSP_PDATA_SZ ARRAY_SIZE(omap2420_mcbsp_pdata) @@ -86,8 +80,6 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP1_IRQ_RX, .tx_irq = INT_24XX_MCBSP1_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_names = clk_names, - .num_clks = 2, }, { .phys_base = OMAP24XX_MCBSP2_BASE, @@ -96,8 +88,6 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP2_IRQ_RX, .tx_irq = INT_24XX_MCBSP2_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_names = clk_names, - .num_clks = 2, }, { .phys_base = OMAP2430_MCBSP3_BASE, @@ -106,8 +96,6 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP3_IRQ_RX, .tx_irq = INT_24XX_MCBSP3_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_names = clk_names, - .num_clks = 2, }, { .phys_base = OMAP2430_MCBSP4_BASE, @@ -116,8 +104,6 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP4_IRQ_RX, .tx_irq = INT_24XX_MCBSP4_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_names = clk_names, - .num_clks = 2, }, { .phys_base = OMAP2430_MCBSP5_BASE, @@ -126,8 +112,6 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP5_IRQ_RX, .tx_irq = INT_24XX_MCBSP5_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_names = clk_names, - .num_clks = 2, }, }; #define OMAP2430_MCBSP_PDATA_SZ ARRAY_SIZE(omap2430_mcbsp_pdata) @@ -145,8 +129,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP1_IRQ_RX, .tx_irq = INT_24XX_MCBSP1_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_names = clk_names, - .num_clks = 2, }, { .phys_base = OMAP34XX_MCBSP2_BASE, @@ -155,8 +137,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP2_IRQ_RX, .tx_irq = INT_24XX_MCBSP2_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_names = clk_names, - .num_clks = 2, }, { .phys_base = OMAP34XX_MCBSP3_BASE, @@ -165,8 +145,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP3_IRQ_RX, .tx_irq = INT_24XX_MCBSP3_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_names = clk_names, - .num_clks = 2, }, { .phys_base = OMAP34XX_MCBSP4_BASE, @@ -175,8 +153,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP4_IRQ_RX, .tx_irq = INT_24XX_MCBSP4_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_names = clk_names, - .num_clks = 2, }, { .phys_base = OMAP34XX_MCBSP5_BASE, @@ -185,8 +161,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP5_IRQ_RX, .tx_irq = INT_24XX_MCBSP5_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_names = clk_names, - .num_clks = 2, }, }; #define OMAP34XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap34xx_mcbsp_pdata) diff --git a/arch/arm/plat-omap/include/mach/mcbsp.h b/arch/arm/plat-omap/include/mach/mcbsp.h index 113c2466c86..bb154ea7676 100644 --- a/arch/arm/plat-omap/include/mach/mcbsp.h +++ b/arch/arm/plat-omap/include/mach/mcbsp.h @@ -344,8 +344,6 @@ struct omap_mcbsp_platform_data { u8 dma_rx_sync, dma_tx_sync; u16 rx_irq, tx_irq; struct omap_mcbsp_ops *ops; - char const **clk_names; - int num_clks; }; struct omap_mcbsp { @@ -377,8 +375,8 @@ struct omap_mcbsp { /* Protect the field .free, while checking if the mcbsp is in use */ spinlock_t lock; struct omap_mcbsp_platform_data *pdata; - struct clk **clks; - int num_clks; + struct clk *iclk; + struct clk *fclk; }; extern struct omap_mcbsp **mcbsp_ptr; extern int omap_mcbsp_count; diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index e5842e30e53..28b0a824b8c 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -214,7 +214,6 @@ EXPORT_SYMBOL(omap_mcbsp_set_io_type); int omap_mcbsp_request(unsigned int id) { struct omap_mcbsp *mcbsp; - int i; int err; if (!omap_mcbsp_check_valid_id(id)) { @@ -223,23 +222,23 @@ int omap_mcbsp_request(unsigned int id) } mcbsp = id_to_mcbsp_ptr(id); - if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request) - mcbsp->pdata->ops->request(id); - - for (i = 0; i < mcbsp->num_clks; i++) - clk_enable(mcbsp->clks[i]); - spin_lock(&mcbsp->lock); if (!mcbsp->free) { dev_err(mcbsp->dev, "McBSP%d is currently in use\n", mcbsp->id); spin_unlock(&mcbsp->lock); - return -1; + return -EBUSY; } mcbsp->free = 0; spin_unlock(&mcbsp->lock); + if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request) + mcbsp->pdata->ops->request(id); + + clk_enable(mcbsp->iclk); + clk_enable(mcbsp->fclk); + /* * Make sure that transmitter, receiver and sample-rate generator are * not running before activating IRQs. @@ -278,7 +277,6 @@ EXPORT_SYMBOL(omap_mcbsp_request); void omap_mcbsp_free(unsigned int id) { struct omap_mcbsp *mcbsp; - int i; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); @@ -289,8 +287,14 @@ void omap_mcbsp_free(unsigned int id) if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free) mcbsp->pdata->ops->free(id); - for (i = mcbsp->num_clks - 1; i >= 0; i--) - clk_disable(mcbsp->clks[i]); + clk_disable(mcbsp->fclk); + clk_disable(mcbsp->iclk); + + if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) { + /* Free IRQs */ + free_irq(mcbsp->rx_irq, (void *)mcbsp); + free_irq(mcbsp->tx_irq, (void *)mcbsp); + } spin_lock(&mcbsp->lock); if (mcbsp->free) { @@ -302,12 +306,6 @@ void omap_mcbsp_free(unsigned int id) mcbsp->free = 1; spin_unlock(&mcbsp->lock); - - if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) { - /* Free IRQs */ - free_irq(mcbsp->rx_irq, (void *)mcbsp); - free_irq(mcbsp->tx_irq, (void *)mcbsp); - } } EXPORT_SYMBOL(omap_mcbsp_free); @@ -876,7 +874,6 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) struct omap_mcbsp_platform_data *pdata = pdev->dev.platform_data; struct omap_mcbsp *mcbsp; int id = pdev->id - 1; - int i; int ret = 0; if (!pdata) { @@ -899,7 +896,6 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) ret = -ENOMEM; goto exit; } - mcbsp_ptr[id] = mcbsp; spin_lock_init(&mcbsp->lock); mcbsp->id = id + 1; @@ -921,39 +917,32 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) mcbsp->dma_rx_sync = pdata->dma_rx_sync; mcbsp->dma_tx_sync = pdata->dma_tx_sync; - if (pdata->num_clks) { - mcbsp->num_clks = pdata->num_clks; - mcbsp->clks = kzalloc(mcbsp->num_clks * sizeof(struct clk *), - GFP_KERNEL); - if (!mcbsp->clks) { - ret = -ENOMEM; - goto exit; - } - for (i = 0; i < mcbsp->num_clks; i++) { - mcbsp->clks[i] = clk_get(&pdev->dev, pdata->clk_names[i]); - if (IS_ERR(mcbsp->clks[i])) { - dev_err(&pdev->dev, - "Invalid %s configuration for McBSP%d.\n", - pdata->clk_names[i], mcbsp->id); - ret = PTR_ERR(mcbsp->clks[i]); - goto err_clk; - } - } + mcbsp->iclk = clk_get(&pdev->dev, "ick"); + if (IS_ERR(mcbsp->iclk)) { + ret = PTR_ERR(mcbsp->iclk); + dev_err(&pdev->dev, "unable to get ick: %d\n", ret); + goto err_iclk; + } + mcbsp->fclk = clk_get(&pdev->dev, "fck"); + if (IS_ERR(mcbsp->fclk)) { + ret = PTR_ERR(mcbsp->fclk); + dev_err(&pdev->dev, "unable to get fck: %d\n", ret); + goto err_fclk; } mcbsp->pdata = pdata; mcbsp->dev = &pdev->dev; + mcbsp_ptr[id] = mcbsp; platform_set_drvdata(pdev, mcbsp); return 0; -err_clk: - while (i--) - clk_put(mcbsp->clks[i]); - kfree(mcbsp->clks); +err_fclk: + clk_put(mcbsp->iclk); +err_iclk: iounmap(mcbsp->io_base); err_ioremap: - mcbsp->free = 0; + kfree(mcbsp); exit: return ret; } @@ -961,7 +950,6 @@ exit: static int __devexit omap_mcbsp_remove(struct platform_device *pdev) { struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev); - int i; platform_set_drvdata(pdev, NULL); if (mcbsp) { @@ -970,18 +958,15 @@ static int __devexit omap_mcbsp_remove(struct platform_device *pdev) mcbsp->pdata->ops->free) mcbsp->pdata->ops->free(mcbsp->id); - for (i = mcbsp->num_clks - 1; i >= 0; i--) { - clk_disable(mcbsp->clks[i]); - clk_put(mcbsp->clks[i]); - } + clk_disable(mcbsp->fclk); + clk_disable(mcbsp->iclk); + clk_put(mcbsp->fclk); + clk_put(mcbsp->iclk); iounmap(mcbsp->io_base); - if (mcbsp->num_clks) { - kfree(mcbsp->clks); - mcbsp->clks = NULL; - mcbsp->num_clks = 0; - } + mcbsp->fclk = NULL; + mcbsp->iclk = NULL; mcbsp->free = 0; mcbsp->dev = NULL; } @@ -1002,4 +987,3 @@ int __init omap_mcbsp_init(void) /* Register the McBSP driver */ return platform_driver_register(&omap_mcbsp_driver); } - -- GitLab From 1d14de087dd1cab0436fb7c9d5e38d852f33df69 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 19 Jan 2009 21:02:29 +0000 Subject: [PATCH 1356/4982] [ARM] omap: i2c: use short connection ids Signed-off-by: Russell King --- arch/arm/mach-omap1/clock.c | 4 ++-- arch/arm/mach-omap2/clock24xx.c | 12 ++++++------ arch/arm/mach-omap2/clock34xx.c | 12 ++++++------ drivers/i2c/busses/i2c-omap.c | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index b62da4c9563..382e09a1cec 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -130,8 +130,8 @@ static struct omap_clk omap_clks[] = { CLK("mmci-omap.1", "ick", &armper_ck.clk, CK_16XX), /* Virtual clocks */ CLK(NULL, "mpu", &virtual_ck_mpu, CK_16XX | CK_1510 | CK_310), - CLK("i2c_omap.1", "i2c_fck", &i2c_fck, CK_16XX | CK_1510 | CK_310), - CLK("i2c_omap.1", "i2c_ick", &i2c_ick, CK_16XX), + CLK("i2c_omap.1", "fck", &i2c_fck, CK_16XX | CK_1510 | CK_310), + CLK("i2c_omap.1", "ick", &i2c_ick, CK_16XX), CLK("omap-mcbsp.1", "ick", &dspper_ck, CK_16XX), CLK("omap-mcbsp.1", "ick", &dummy_ck, CK_1510 | CK_310), CLK("omap-mcbsp.2", "ick", &armper_ck.clk, CK_16XX), diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index ea21d55a207..81c7b705114 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -186,12 +186,12 @@ static struct omap_clk omap24xx_clks[] = { CLK(NULL, "eac_fck", &eac_fck, CK_242X), CLK(NULL, "hdq_ick", &hdq_ick, CK_243X | CK_242X), CLK(NULL, "hdq_fck", &hdq_fck, CK_243X | CK_242X), - CLK("i2c_omap.1", "i2c_ick", &i2c1_ick, CK_243X | CK_242X), - CLK("i2c_omap.1", "i2c_fck", &i2c1_fck, CK_242X), - CLK("i2c_omap.1", "i2c_fck", &i2chs1_fck, CK_243X), - CLK("i2c_omap.2", "i2c_ick", &i2c2_ick, CK_243X | CK_242X), - CLK("i2c_omap.2", "i2c_fck", &i2c2_fck, CK_242X), - CLK("i2c_omap.2", "i2c_fck", &i2chs2_fck, CK_243X), + CLK("i2c_omap.1", "ick", &i2c1_ick, CK_243X | CK_242X), + CLK("i2c_omap.1", "fck", &i2c1_fck, CK_242X), + CLK("i2c_omap.1", "fck", &i2chs1_fck, CK_243X), + CLK("i2c_omap.2", "ick", &i2c2_ick, CK_243X | CK_242X), + CLK("i2c_omap.2", "fck", &i2c2_fck, CK_242X), + CLK("i2c_omap.2", "fck", &i2chs2_fck, CK_243X), CLK(NULL, "gpmc_fck", &gpmc_fck, CK_243X | CK_242X), CLK(NULL, "sdma_fck", &sdma_fck, CK_243X | CK_242X), CLK(NULL, "sdma_ick", &sdma_ick, CK_243X | CK_242X), diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index a70aa2eaf05..859ad1d4062 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -141,9 +141,9 @@ static struct omap_clk omap34xx_clks[] = { CLK("mmci-omap-hs.1", "mmchs_fck", &mmchs2_fck, CK_343X), CLK(NULL, "mspro_fck", &mspro_fck, CK_343X), CLK("mmci-omap-hs.0", "mmchs_fck", &mmchs1_fck, CK_343X), - CLK("i2c_omap.3", "i2c_fck", &i2c3_fck, CK_343X), - CLK("i2c_omap.2", "i2c_fck", &i2c2_fck, CK_343X), - CLK("i2c_omap.1", "i2c_fck", &i2c1_fck, CK_343X), + CLK("i2c_omap.3", "fck", &i2c3_fck, CK_343X), + CLK("i2c_omap.2", "fck", &i2c2_fck, CK_343X), + CLK("i2c_omap.1", "fck", &i2c1_fck, CK_343X), CLK("omap-mcbsp.5", "fck", &mcbsp5_fck, CK_343X), CLK("omap-mcbsp.1", "fck", &mcbsp1_fck, CK_343X), CLK(NULL, "core_48m_fck", &core_48m_fck, CK_343X), @@ -179,9 +179,9 @@ static struct omap_clk omap34xx_clks[] = { CLK("omap2_mcspi.3", "ick", &mcspi3_ick, CK_343X), CLK("omap2_mcspi.2", "ick", &mcspi2_ick, CK_343X), CLK("omap2_mcspi.1", "ick", &mcspi1_ick, CK_343X), - CLK("i2c_omap.3", "i2c_ick", &i2c3_ick, CK_343X), - CLK("i2c_omap.2", "i2c_ick", &i2c2_ick, CK_343X), - CLK("i2c_omap.1", "i2c_ick", &i2c1_ick, CK_343X), + CLK("i2c_omap.3", "ick", &i2c3_ick, CK_343X), + CLK("i2c_omap.2", "ick", &i2c2_ick, CK_343X), + CLK("i2c_omap.1", "ick", &i2c1_ick, CK_343X), CLK(NULL, "uart2_ick", &uart2_ick, CK_343X), CLK(NULL, "uart1_ick", &uart1_ick, CK_343X), CLK(NULL, "gpt11_ick", &gpt11_ick, CK_343X), diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index be8ee2cac8b..19f86e1eefa 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -194,14 +194,14 @@ static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg) static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev) { if (cpu_is_omap16xx() || cpu_class_is_omap2()) { - dev->iclk = clk_get(dev->dev, "i2c_ick"); + dev->iclk = clk_get(dev->dev, "ick"); if (IS_ERR(dev->iclk)) { dev->iclk = NULL; return -ENODEV; } } - dev->fclk = clk_get(dev->dev, "i2c_fck"); + dev->fclk = clk_get(dev->dev, "fck"); if (IS_ERR(dev->fclk)) { if (dev->iclk != NULL) { clk_put(dev->iclk); -- GitLab From 0e9ae109e4eece027ede4f3f0edc8e659f8298c9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 22 Jan 2009 19:31:46 +0000 Subject: [PATCH 1357/4982] [ARM] omap: i2c: remove armxor_ck On OMAP1, the I2C functional clock (fck) is the armxor_ck, so there's no need to get "armxor_ck" separately. Signed-off-by: Russell King --- drivers/i2c/busses/i2c-omap.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 19f86e1eefa..96814fb6715 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -312,15 +312,14 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); if (cpu_class_is_omap1()) { - struct clk *armxor_ck; - - armxor_ck = clk_get(NULL, "armxor_ck"); - if (IS_ERR(armxor_ck)) - dev_warn(dev->dev, "Could not get armxor_ck\n"); - else { - fclk_rate = clk_get_rate(armxor_ck); - clk_put(armxor_ck); - } + /* + * The I2C functional clock is the armxor_ck, so there's + * no need to get "armxor_ck" separately. Now, if OMAP2420 + * always returns 12MHz for the functional clock, we can + * do this bit unconditionally. + */ + fclk_rate = clk_get_rate(dev->fclk); + /* TRM for 5912 says the I2C clock must be prescaled to be * between 7 - 12 MHz. The XOR input clock is typically * 12, 13 or 19.2 MHz. So we should have code that produces: -- GitLab From 5fe23380405d3a65ce6f46d270c4d3a31027430b Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 23 Jan 2009 22:57:12 +0000 Subject: [PATCH 1358/4982] [ARM] omap: i2c: remove conditional ick clocks By providing a dummy ick for OMAP1510 and OMAP310, we avoid having SoC conditional clock information in i2c-omap.c. Also, fix the error handling by making sure we propagate the error returned via clk_get(). Signed-off-by: Russell King --- arch/arm/mach-omap1/clock.c | 1 + drivers/i2c/busses/i2c-omap.c | 28 +++++++++++++--------------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index 382e09a1cec..d2c61390346 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -132,6 +132,7 @@ static struct omap_clk omap_clks[] = { CLK(NULL, "mpu", &virtual_ck_mpu, CK_16XX | CK_1510 | CK_310), CLK("i2c_omap.1", "fck", &i2c_fck, CK_16XX | CK_1510 | CK_310), CLK("i2c_omap.1", "ick", &i2c_ick, CK_16XX), + CLK("i2c_omap.1", "ick", &dummy_ck, CK_1510 | CK_310), CLK("omap-mcbsp.1", "ick", &dspper_ck, CK_16XX), CLK("omap-mcbsp.1", "ick", &dummy_ck, CK_1510 | CK_310), CLK("omap-mcbsp.2", "ick", &armper_ck.clk, CK_16XX), diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 96814fb6715..ece0125a1ee 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -193,22 +193,24 @@ static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg) static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev) { - if (cpu_is_omap16xx() || cpu_class_is_omap2()) { - dev->iclk = clk_get(dev->dev, "ick"); - if (IS_ERR(dev->iclk)) { - dev->iclk = NULL; - return -ENODEV; - } + int ret; + + dev->iclk = clk_get(dev->dev, "ick"); + if (IS_ERR(dev->iclk)) { + ret = PTR_ERR(dev->iclk); + dev->iclk = NULL; + return ret; } dev->fclk = clk_get(dev->dev, "fck"); if (IS_ERR(dev->fclk)) { + ret = PTR_ERR(dev->fclk); if (dev->iclk != NULL) { clk_put(dev->iclk); dev->iclk = NULL; } dev->fclk = NULL; - return -ENODEV; + return ret; } return 0; @@ -218,18 +220,15 @@ static void omap_i2c_put_clocks(struct omap_i2c_dev *dev) { clk_put(dev->fclk); dev->fclk = NULL; - if (dev->iclk != NULL) { - clk_put(dev->iclk); - dev->iclk = NULL; - } + clk_put(dev->iclk); + dev->iclk = NULL; } static void omap_i2c_unidle(struct omap_i2c_dev *dev) { WARN_ON(!dev->idle); - if (dev->iclk != NULL) - clk_enable(dev->iclk); + clk_enable(dev->iclk); clk_enable(dev->fclk); dev->idle = 0; if (dev->iestate) @@ -254,8 +253,7 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev) } dev->idle = 1; clk_disable(dev->fclk); - if (dev->iclk != NULL) - clk_disable(dev->iclk); + clk_disable(dev->iclk); } static int omap_i2c_init(struct omap_i2c_dev *dev) -- GitLab From cc51c9d444ae1532be6a600c65ac0d3d22472c53 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 22 Jan 2009 10:12:04 +0000 Subject: [PATCH 1359/4982] [ARM] omap: w1: convert omap HDQ clocks to match by devid and conid Signed-off-by: Russell King --- arch/arm/mach-omap2/clock24xx.c | 4 ++-- arch/arm/mach-omap2/clock34xx.c | 4 ++-- drivers/w1/masters/omap_hdq.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index 81c7b705114..f83588002f6 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -184,8 +184,8 @@ static struct omap_clk omap24xx_clks[] = { CLK(NULL, "fac_fck", &fac_fck, CK_243X | CK_242X), CLK(NULL, "eac_ick", &eac_ick, CK_242X), CLK(NULL, "eac_fck", &eac_fck, CK_242X), - CLK(NULL, "hdq_ick", &hdq_ick, CK_243X | CK_242X), - CLK(NULL, "hdq_fck", &hdq_fck, CK_243X | CK_242X), + CLK("omap_hdq.0", "ick", &hdq_ick, CK_243X | CK_242X), + CLK("omap_hdq.1", "fck", &hdq_fck, CK_243X | CK_242X), CLK("i2c_omap.1", "ick", &i2c1_ick, CK_243X | CK_242X), CLK("i2c_omap.1", "fck", &i2c1_fck, CK_242X), CLK("i2c_omap.1", "fck", &i2chs1_fck, CK_243X), diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 859ad1d4062..1a4bc336c8a 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -155,7 +155,7 @@ static struct omap_clk omap34xx_clks[] = { CLK(NULL, "uart1_fck", &uart1_fck, CK_343X), CLK(NULL, "fshostusb_fck", &fshostusb_fck, CK_3430ES1), CLK(NULL, "core_12m_fck", &core_12m_fck, CK_343X), - CLK(NULL, "hdq_fck", &hdq_fck, CK_343X), + CLK("omap_hdq.0", "fck", &hdq_fck, CK_343X), CLK(NULL, "ssi_ssr_fck", &ssi_ssr_fck, CK_343X), CLK(NULL, "ssi_sst_fck", &ssi_sst_fck, CK_343X), CLK(NULL, "core_l3_ick", &core_l3_ick, CK_343X), @@ -174,7 +174,7 @@ static struct omap_clk omap34xx_clks[] = { CLK("mmci-omap-hs.1", "mmchs_ick", &mmchs2_ick, CK_343X), CLK("mmci-omap-hs.0", "mmchs_ick", &mmchs1_ick, CK_343X), CLK(NULL, "mspro_ick", &mspro_ick, CK_343X), - CLK(NULL, "hdq_ick", &hdq_ick, CK_343X), + CLK("omap_hdq.0", "ick", &hdq_ick, CK_343X), CLK("omap2_mcspi.4", "ick", &mcspi4_ick, CK_343X), CLK("omap2_mcspi.3", "ick", &mcspi3_ick, CK_343X), CLK("omap2_mcspi.2", "ick", &mcspi2_ick, CK_343X), diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c index c973889110c..a7e3b706b9d 100644 --- a/drivers/w1/masters/omap_hdq.c +++ b/drivers/w1/masters/omap_hdq.c @@ -590,8 +590,8 @@ static int __init omap_hdq_probe(struct platform_device *pdev) } /* get interface & functional clock objects */ - hdq_data->hdq_ick = clk_get(&pdev->dev, "hdq_ick"); - hdq_data->hdq_fck = clk_get(&pdev->dev, "hdq_fck"); + hdq_data->hdq_ick = clk_get(&pdev->dev, "ick"); + hdq_data->hdq_fck = clk_get(&pdev->dev, "fck"); if (IS_ERR(hdq_data->hdq_ick) || IS_ERR(hdq_data->hdq_fck)) { dev_dbg(&pdev->dev, "Can't get HDQ clock objects\n"); -- GitLab From b1ad379632327c0722c5c92275c326971da3b948 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 22 Jan 2009 19:41:20 +0000 Subject: [PATCH 1360/4982] [ARM] omap: spi: arrange for omap_uwire to use connection ID ... which now means no driver requests the "armxor_ck" clock directly. Also, fix the error handling for clk_get(), ensuring that we propagate the error returned from clk_get(). Signed-off-by: Russell King --- arch/arm/mach-omap1/clock.c | 1 + drivers/spi/omap_uwire.c | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index d2c61390346..7c455431790 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -133,6 +133,7 @@ static struct omap_clk omap_clks[] = { CLK("i2c_omap.1", "fck", &i2c_fck, CK_16XX | CK_1510 | CK_310), CLK("i2c_omap.1", "ick", &i2c_ick, CK_16XX), CLK("i2c_omap.1", "ick", &dummy_ck, CK_1510 | CK_310), + CLK("omap_uwire", "fck", &armxor_ck.clk, CK_16XX | CK_1510 | CK_310), CLK("omap-mcbsp.1", "ick", &dspper_ck, CK_16XX), CLK("omap-mcbsp.1", "ick", &dummy_ck, CK_1510 | CK_310), CLK("omap-mcbsp.2", "ick", &armper_ck.clk, CK_16XX), diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/omap_uwire.c index bab6ff061e9..394b616eafe 100644 --- a/drivers/spi/omap_uwire.c +++ b/drivers/spi/omap_uwire.c @@ -506,11 +506,12 @@ static int __init uwire_probe(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, uwire); - uwire->ck = clk_get(&pdev->dev, "armxor_ck"); - if (!uwire->ck || IS_ERR(uwire->ck)) { - dev_dbg(&pdev->dev, "no mpu_xor_clk ?\n"); + uwire->ck = clk_get(&pdev->dev, "fck"); + if (IS_ERR(uwire->ck)) { + status = PTR_ERR(uwire->ck); + dev_dbg(&pdev->dev, "no functional clock?\n"); spi_master_put(master); - return -ENODEV; + return status; } clk_enable(uwire->ck); -- GitLab From eeec7c8d18465a85c212230bdb715e3f029dbf4e Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 19 Jan 2009 20:58:56 +0000 Subject: [PATCH 1361/4982] [ARM] omap: convert omap RNG clocks to match by devid and conid Signed-off-by: Russell King --- arch/arm/mach-omap2/clock24xx.c | 2 +- arch/arm/mach-omap2/clock34xx.c | 2 +- drivers/char/hw_random/omap-rng.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index f83588002f6..1e9ac83dca5 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -200,7 +200,7 @@ static struct omap_clk omap24xx_clks[] = { CLK(NULL, "sdrc_ick", &sdrc_ick, CK_243X), CLK(NULL, "des_ick", &des_ick, CK_243X | CK_242X), CLK(NULL, "sha_ick", &sha_ick, CK_243X | CK_242X), - CLK(NULL, "rng_ick", &rng_ick, CK_243X | CK_242X), + CLK("omap_rng", "ick", &rng_ick, CK_243X | CK_242X), CLK(NULL, "aes_ick", &aes_ick, CK_243X | CK_242X), CLK(NULL, "pka_ick", &pka_ick, CK_243X | CK_242X), CLK(NULL, "usb_fck", &usb_fck, CK_243X | CK_242X), diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 1a4bc336c8a..07e3308da65 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -196,7 +196,7 @@ static struct omap_clk omap34xx_clks[] = { CLK(NULL, "usb_l4_ick", &usb_l4_ick, CK_3430ES1), CLK(NULL, "security_l4_ick2", &security_l4_ick2, CK_343X), CLK(NULL, "aes1_ick", &aes1_ick, CK_343X), - CLK(NULL, "rng_ick", &rng_ick, CK_343X), + CLK("omap_rng", "ick", &rng_ick, CK_343X), CLK(NULL, "sha11_ick", &sha11_ick, CK_343X), CLK(NULL, "des1_ick", &des1_ick, CK_343X), CLK(NULL, "dss1_alwon_fck", &dss1_alwon_fck, CK_343X), diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index ba68a4671cb..538313f9e7a 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c @@ -102,7 +102,7 @@ static int __init omap_rng_probe(struct platform_device *pdev) return -EBUSY; if (cpu_is_omap24xx()) { - rng_ick = clk_get(&pdev->dev, "rng_ick"); + rng_ick = clk_get(&pdev->dev, "ick"); if (IS_ERR(rng_ick)) { dev_err(&pdev->dev, "Could not get rng_ick\n"); ret = PTR_ERR(rng_ick); -- GitLab From 6c5dbb40f4795f3fdbf3e5aab7eda4e2f838d08b Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 24 Jan 2009 16:27:06 +0000 Subject: [PATCH 1362/4982] [ARM] omap: omap24xxcam: use short connection IDs for omap2 clocks Signed-off-by: Russell King --- arch/arm/mach-omap2/clock24xx.c | 4 ++-- drivers/media/video/omap24xxcam.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index 1e9ac83dca5..d190b6a7493 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -169,8 +169,8 @@ static struct omap_clk omap24xx_clks[] = { CLK(NULL, "wdt1_ick", &wdt1_ick, CK_243X | CK_242X), CLK(NULL, "omapctrl_ick", &omapctrl_ick, CK_243X | CK_242X), CLK(NULL, "icr_ick", &icr_ick, CK_243X), - CLK(NULL, "cam_fck", &cam_fck, CK_243X | CK_242X), - CLK(NULL, "cam_ick", &cam_ick, CK_243X | CK_242X), + CLK("omap24xxcam", "fck", &cam_fck, CK_243X | CK_242X), + CLK("omap24xxcam", "ick", &cam_ick, CK_243X | CK_242X), CLK(NULL, "mailboxes_ick", &mailboxes_ick, CK_243X | CK_242X), CLK(NULL, "wdt4_ick", &wdt4_ick, CK_243X | CK_242X), CLK(NULL, "wdt4_fck", &wdt4_fck, CK_243X | CK_242X), diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c index 73eb656acfe..805faaea644 100644 --- a/drivers/media/video/omap24xxcam.c +++ b/drivers/media/video/omap24xxcam.c @@ -80,17 +80,17 @@ static int omap24xxcam_clock_get(struct omap24xxcam_device *cam) { int rval = 0; - cam->fck = clk_get(cam->dev, "cam_fck"); + cam->fck = clk_get(cam->dev, "fck"); if (IS_ERR(cam->fck)) { - dev_err(cam->dev, "can't get cam_fck"); + dev_err(cam->dev, "can't get camera fck"); rval = PTR_ERR(cam->fck); omap24xxcam_clock_put(cam); return rval; } - cam->ick = clk_get(cam->dev, "cam_ick"); + cam->ick = clk_get(cam->dev, "ick"); if (IS_ERR(cam->ick)) { - dev_err(cam->dev, "can't get cam_ick"); + dev_err(cam->dev, "can't get camera ick"); rval = PTR_ERR(cam->ick); omap24xxcam_clock_put(cam); } -- GitLab From 6f7607ccd175518a3ee7dccc1620f3a086689668 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 28 Jan 2009 10:22:50 +0000 Subject: [PATCH 1363/4982] [ARM] omap: hsmmc: new short connection id names ... rather than the clock names themselves. Signed-off-by: Russell King --- arch/arm/mach-omap2/clock24xx.c | 8 ++++---- arch/arm/mach-omap2/clock34xx.c | 12 ++++++------ arch/arm/mach-omap2/devices.c | 4 ++-- drivers/mmc/host/omap_hsmmc.c | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index d190b6a7493..bd77ef2d5ae 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -205,10 +205,10 @@ static struct omap_clk omap24xx_clks[] = { CLK(NULL, "pka_ick", &pka_ick, CK_243X | CK_242X), CLK(NULL, "usb_fck", &usb_fck, CK_243X | CK_242X), CLK(NULL, "usbhs_ick", &usbhs_ick, CK_243X), - CLK("mmci-omap-hs.0", "mmchs_ick", &mmchs1_ick, CK_243X), - CLK("mmci-omap-hs.0", "mmchs_fck", &mmchs1_fck, CK_243X), - CLK("mmci-omap-hs.1", "mmchs_ick", &mmchs2_ick, CK_243X), - CLK("mmci-omap-hs.1", "mmchs_fck", &mmchs2_fck, CK_243X), + CLK("mmci-omap-hs.0", "ick", &mmchs1_ick, CK_243X), + CLK("mmci-omap-hs.0", "fck", &mmchs1_fck, CK_243X), + CLK("mmci-omap-hs.1", "ick", &mmchs2_ick, CK_243X), + CLK("mmci-omap-hs.1", "fck", &mmchs2_fck, CK_243X), CLK(NULL, "gpio5_ick", &gpio5_ick, CK_243X), CLK(NULL, "gpio5_fck", &gpio5_fck, CK_243X), CLK(NULL, "mdm_intc_ick", &mdm_intc_ick, CK_243X), diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 07e3308da65..245a7b9b560 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -137,10 +137,10 @@ static struct omap_clk omap34xx_clks[] = { CLK(NULL, "ts_fck", &ts_fck, CK_3430ES2), CLK(NULL, "usbtll_fck", &usbtll_fck, CK_3430ES2), CLK(NULL, "core_96m_fck", &core_96m_fck, CK_343X), - CLK("mmci-omap-hs.2", "mmchs_fck", &mmchs3_fck, CK_3430ES2), - CLK("mmci-omap-hs.1", "mmchs_fck", &mmchs2_fck, CK_343X), + CLK("mmci-omap-hs.2", "fck", &mmchs3_fck, CK_3430ES2), + CLK("mmci-omap-hs.1", "fck", &mmchs2_fck, CK_343X), CLK(NULL, "mspro_fck", &mspro_fck, CK_343X), - CLK("mmci-omap-hs.0", "mmchs_fck", &mmchs1_fck, CK_343X), + CLK("mmci-omap-hs.0", "fck", &mmchs1_fck, CK_343X), CLK("i2c_omap.3", "fck", &i2c3_fck, CK_343X), CLK("i2c_omap.2", "fck", &i2c2_fck, CK_343X), CLK("i2c_omap.1", "fck", &i2c1_fck, CK_343X), @@ -166,13 +166,13 @@ static struct omap_clk omap34xx_clks[] = { CLK(NULL, "pka_ick", &pka_ick, CK_343X), CLK(NULL, "core_l4_ick", &core_l4_ick, CK_343X), CLK(NULL, "usbtll_ick", &usbtll_ick, CK_3430ES2), - CLK("mmci-omap-hs.2", "mmchs_ick", &mmchs3_ick, CK_3430ES2), + CLK("mmci-omap-hs.2", "ick", &mmchs3_ick, CK_3430ES2), CLK(NULL, "icr_ick", &icr_ick, CK_343X), CLK(NULL, "aes2_ick", &aes2_ick, CK_343X), CLK(NULL, "sha12_ick", &sha12_ick, CK_343X), CLK(NULL, "des2_ick", &des2_ick, CK_343X), - CLK("mmci-omap-hs.1", "mmchs_ick", &mmchs2_ick, CK_343X), - CLK("mmci-omap-hs.0", "mmchs_ick", &mmchs1_ick, CK_343X), + CLK("mmci-omap-hs.1", "ick", &mmchs2_ick, CK_343X), + CLK("mmci-omap-hs.0", "ick", &mmchs1_ick, CK_343X), CLK(NULL, "mspro_ick", &mspro_ick, CK_343X), CLK("omap_hdq.0", "ick", &hdq_ick, CK_343X), CLK("omap2_mcspi.4", "ick", &mcspi4_ick, CK_343X), diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 97304044152..8075f5868c3 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -349,11 +349,11 @@ static void __init omap_hsmmc_reset(void) dummy_pdev.id = i; dev_set_name(&dummy_pdev.dev, "mmci-omap-hs.%d", i); - iclk = clk_get(dev, "mmchs_ick"); + iclk = clk_get(dev, "ick"); if (iclk && clk_enable(iclk)) iclk = NULL; - fclk = clk_get(dev, "mmchs_fck"); + fclk = clk_get(dev, "fck"); if (fclk && clk_enable(fclk)) fclk = NULL; diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index db37490f67e..65e0743dbdd 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -920,13 +920,13 @@ static int __init omap_mmc_probe(struct platform_device *pdev) sema_init(&host->sem, 1); - host->iclk = clk_get(&pdev->dev, "mmchs_ick"); + host->iclk = clk_get(&pdev->dev, "ick"); if (IS_ERR(host->iclk)) { ret = PTR_ERR(host->iclk); host->iclk = NULL; goto err1; } - host->fclk = clk_get(&pdev->dev, "mmchs_fck"); + host->fclk = clk_get(&pdev->dev, "fck"); if (IS_ERR(host->fclk)) { ret = PTR_ERR(host->fclk); host->fclk = NULL; -- GitLab From 16c90f020034d3cd38b3dab280001e728e6b19e5 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 27 Jan 2009 19:12:47 -0700 Subject: [PATCH 1364/4982] [ARM] OMAP2/3: Add non-CORE DPLL rate set code and M, N programming Add non-CORE DPLL rate set code and M,N programming for OMAP3. Connect it to OMAP34xx DPLLs 1, 2, 4, 5 via the clock framework. You may see some warnings on rate sets from the freqsel code. The table that TI presented in the 3430 TRM Rev F does not cover Fint < 750000, which definitely occurs in practice. However, the lack of this freqsel case does not appear to impair the DPLL rate change. linux-omap source commit is 689fe67c6d1ad8f52f7f7b139a3274b79bf3e784. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock34xx.c | 137 +++++++++++++++++++++++- arch/arm/mach-omap2/clock34xx.h | 11 ++ arch/arm/plat-omap/include/mach/clock.h | 1 + 3 files changed, 148 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 245a7b9b560..943ac63fc6f 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -340,6 +340,42 @@ static int _omap3_wait_dpll_status(struct clk *clk, u8 state) return ret; } +/* From 3430 TRM ES2 4.7.6.2 */ +static u16 _omap3_dpll_compute_freqsel(struct clk *clk, u8 n) +{ + unsigned long fint; + u16 f = 0; + + fint = clk->parent->rate / (n + 1); + + pr_debug("clock: fint is %lu\n", fint); + + if (fint >= 750000 && fint <= 1000000) + f = 0x3; + else if (fint > 1000000 && fint <= 1250000) + f = 0x4; + else if (fint > 1250000 && fint <= 1500000) + f = 0x5; + else if (fint > 1500000 && fint <= 1750000) + f = 0x6; + else if (fint > 1750000 && fint <= 2100000) + f = 0x7; + else if (fint > 7500000 && fint <= 10000000) + f = 0xB; + else if (fint > 10000000 && fint <= 12500000) + f = 0xC; + else if (fint > 12500000 && fint <= 15000000) + f = 0xD; + else if (fint > 15000000 && fint <= 17500000) + f = 0xE; + else if (fint > 17500000 && fint <= 21000000) + f = 0xF; + else + pr_debug("clock: unknown freqsel setting for %d\n", n); + + return f; +} + /* Non-CORE DPLL (e.g., DPLLs that do not control SDRC) clock functions */ /* @@ -476,7 +512,7 @@ static int omap3_noncore_dpll_enable(struct clk *clk) if (clk == &dpll3_ck) return -EINVAL; - if (clk->parent->rate == clk_get_rate(clk)) + if (clk->parent->rate == omap2_get_dpll_rate(clk)) r = _omap3_noncore_dpll_bypass(clk); else r = _omap3_noncore_dpll_lock(clk); @@ -506,11 +542,110 @@ static void omap3_noncore_dpll_disable(struct clk *clk) _omap3_noncore_dpll_stop(clk); } + +/* Non-CORE DPLL rate set code */ + +/* + * omap3_noncore_dpll_program - set non-core DPLL M,N values directly + * @clk: struct clk * of DPLL to set + * @m: DPLL multiplier to set + * @n: DPLL divider to set + * @freqsel: FREQSEL value to set + * + * Program the DPLL with the supplied M, N values, and wait for the DPLL to + * lock.. Returns -EINVAL upon error, or 0 upon success. + */ +static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel) +{ + struct dpll_data *dd = clk->dpll_data; + u32 v; + + /* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */ + _omap3_noncore_dpll_bypass(clk); + + v = __raw_readl(dd->mult_div1_reg); + v &= ~(dd->mult_mask | dd->div1_mask); + + /* Set mult (M), div1 (N), freqsel */ + v |= m << __ffs(dd->mult_mask); + v |= n << __ffs(dd->div1_mask); + v |= freqsel << __ffs(dd->freqsel_mask); + + __raw_writel(v, dd->mult_div1_reg); + + /* We let the clock framework set the other output dividers later */ + + /* REVISIT: Set ramp-up delay? */ + + _omap3_noncore_dpll_lock(clk); + + return 0; +} + +/** + * omap3_noncore_dpll_set_rate - set non-core DPLL rate + * @clk: struct clk * of DPLL to set + * @rate: rounded target rate + * + * Program the DPLL with the rounded target rate. Returns -EINVAL upon + * error, or 0 upon success. + */ +static int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate) +{ + u16 freqsel; + struct dpll_data *dd; + + if (!clk || !rate) + return -EINVAL; + + dd = clk->dpll_data; + if (!dd) + return -EINVAL; + + if (rate == omap2_get_dpll_rate(clk)) + return 0; + + if (dd->last_rounded_rate != rate) + omap2_dpll_round_rate(clk, rate); + + if (dd->last_rounded_rate == 0) + return -EINVAL; + + freqsel = _omap3_dpll_compute_freqsel(clk, dd->last_rounded_n); + if (!freqsel) + WARN_ON(1); + + omap3_noncore_dpll_program(clk, dd->last_rounded_m, dd->last_rounded_n, + freqsel); + + omap3_dpll_recalc(clk); + + return 0; +} + +static int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate) +{ + /* + * According to the 12-5 CDP code from TI, "Limitation 2.5" + * on 3430ES1 prevents us from changing DPLL multipliers or dividers + * on DPLL4. + */ + if (omap_rev() == OMAP3430_REV_ES1_0) { + printk(KERN_ERR "clock: DPLL4 cannot change rate due to " + "silicon 'Limitation 2.5' on 3430ES1.\n"); + return -EINVAL; + } + return omap3_noncore_dpll_set_rate(clk, rate); +} + static const struct clkops clkops_noncore_dpll_ops = { .enable = &omap3_noncore_dpll_enable, .disable = &omap3_noncore_dpll_disable, }; +/* DPLL autoidle read/set code */ + + /** * omap3_dpll_autoidle_read - read a DPLL's autoidle bits * @clk: struct clk * of the DPLL to read diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index 6bd8c6d5a4e..f811a097851 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -32,6 +32,8 @@ static void omap3_clkoutx2_recalc(struct clk *clk); static void omap3_dpll_allow_idle(struct clk *clk); static void omap3_dpll_deny_idle(struct clk *clk); static u32 omap3_dpll_autoidle_read(struct clk *clk); +static int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate); +static int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate); /* Maximum DPLL multiplier, divider values for OMAP3 */ #define OMAP3_MAX_DPLL_MULT 2048 @@ -254,6 +256,7 @@ static struct dpll_data dpll1_dd = { .mult_div1_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL), .mult_mask = OMAP3430_MPU_DPLL_MULT_MASK, .div1_mask = OMAP3430_MPU_DPLL_DIV_MASK, + .freqsel_mask = OMAP3430_MPU_DPLL_FREQSEL_MASK, .control_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKEN_PLL), .enable_mask = OMAP3430_EN_MPU_DPLL_MASK, .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), @@ -276,6 +279,7 @@ static struct clk dpll1_ck = { .dpll_data = &dpll1_dd, .flags = RATE_PROPAGATES, .round_rate = &omap2_dpll_round_rate, + .set_rate = &omap3_noncore_dpll_set_rate, .recalc = &omap3_dpll_recalc, }; @@ -321,6 +325,7 @@ static struct dpll_data dpll2_dd = { .mult_div1_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL), .mult_mask = OMAP3430_IVA2_DPLL_MULT_MASK, .div1_mask = OMAP3430_IVA2_DPLL_DIV_MASK, + .freqsel_mask = OMAP3430_IVA2_DPLL_FREQSEL_MASK, .control_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL), .enable_mask = OMAP3430_EN_IVA2_DPLL_MASK, .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED) | @@ -344,6 +349,7 @@ static struct clk dpll2_ck = { .dpll_data = &dpll2_dd, .flags = RATE_PROPAGATES, .round_rate = &omap2_dpll_round_rate, + .set_rate = &omap3_noncore_dpll_set_rate, .recalc = &omap3_dpll_recalc, }; @@ -378,6 +384,7 @@ static struct dpll_data dpll3_dd = { .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), .mult_mask = OMAP3430_CORE_DPLL_MULT_MASK, .div1_mask = OMAP3430_CORE_DPLL_DIV_MASK, + .freqsel_mask = OMAP3430_CORE_DPLL_FREQSEL_MASK, .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_mask = OMAP3430_EN_CORE_DPLL_MASK, .auto_recal_bit = OMAP3430_EN_CORE_DPLL_DRIFTGUARD_SHIFT, @@ -558,6 +565,7 @@ static struct dpll_data dpll4_dd = { .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2), .mult_mask = OMAP3430_PERIPH_DPLL_MULT_MASK, .div1_mask = OMAP3430_PERIPH_DPLL_DIV_MASK, + .freqsel_mask = OMAP3430_PERIPH_DPLL_FREQSEL_MASK, .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_mask = OMAP3430_EN_PERIPH_DPLL_MASK, .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED), @@ -580,6 +588,7 @@ static struct clk dpll4_ck = { .dpll_data = &dpll4_dd, .flags = RATE_PROPAGATES, .round_rate = &omap2_dpll_round_rate, + .set_rate = &omap3_dpll4_set_rate, .recalc = &omap3_dpll_recalc, }; @@ -864,6 +873,7 @@ static struct dpll_data dpll5_dd = { .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL4), .mult_mask = OMAP3430ES2_PERIPH2_DPLL_MULT_MASK, .div1_mask = OMAP3430ES2_PERIPH2_DPLL_DIV_MASK, + .freqsel_mask = OMAP3430ES2_PERIPH2_DPLL_FREQSEL_MASK, .control_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKEN2), .enable_mask = OMAP3430ES2_EN_PERIPH2_DPLL_MASK, .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED), @@ -886,6 +896,7 @@ static struct clk dpll5_ck = { .dpll_data = &dpll5_dd, .flags = RATE_PROPAGATES, .round_rate = &omap2_dpll_round_rate, + .set_rate = &omap3_noncore_dpll_set_rate, .recalc = &omap3_dpll_recalc, }; diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index 3895ba72979..f147aec91f1 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -53,6 +53,7 @@ struct dpll_data { void __iomem *idlest_reg; u32 enable_mask; u32 autoidle_mask; + u32 freqsel_mask; u8 auto_recal_bit; u8 recal_en_bit; u8 recal_st_bit; -- GitLab From fecb494beef09e4caaa80313834af26f57091195 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 27 Jan 2009 19:12:50 -0700 Subject: [PATCH 1365/4982] [ARM] OMAP: Fix sparse, checkpatch warnings in OMAP2/3 PRCM/PM code Fix sparse & checkpatch warnings in OMAP2/3 PRCM & PM code. This mostly consists of: - converting pointer comparisons to integers in form similar to (ptr == 0) to the standard idiom (!ptr) - labeling a few non-static private functions as static - adding prototypes for *_init() functions in the appropriate header files, and getting rid of the corresponding open-coded extern prototypes in other C files - renaming the variable 'sclk' in mach-omap2/clock.c:omap2_get_apll_clkin to avoid shadowing an earlier declaration Clean up checkpatch issues. This mostly involves: - converting some asm/ includes to linux/ includes - cleaning up some whitespace - getting rid of braces for conditionals with single following statements Also take care of a few odds and ends, including: - getting rid of unlikely() and likely() - none of this code is particularly fast-path code, so the performance impact seems slim; and some of those likely() and unlikely() indicators are probably not as accurate as the ARM's branch predictor - removing some superfluous casts linux-omap source commit is 347df59f5d20fdf905afbc26b1328b0e28a8a01b. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock.c | 51 +++++++++---------- arch/arm/mach-omap2/clock.h | 2 +- arch/arm/mach-omap2/clock24xx.c | 16 +++--- arch/arm/mach-omap2/pm.c | 2 +- arch/arm/plat-omap/include/mach/clock.h | 4 +- arch/arm/plat-omap/include/mach/powerdomain.h | 1 + arch/arm/plat-omap/include/mach/prcm.h | 5 +- arch/arm/plat-omap/include/mach/system.h | 4 +- 8 files changed, 44 insertions(+), 41 deletions(-) diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 53fda9977d5..886f73f3933 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -26,7 +26,6 @@ #include #include -#include #include #include @@ -187,11 +186,10 @@ int omap2_wait_clock_ready(void __iomem *reg, u32 mask, const char *name) * 24xx uses 0 to indicate not ready, and 1 to indicate ready. * 34xx reverses this, just to keep us on our toes */ - if (cpu_mask & (RATE_IN_242X | RATE_IN_243X)) { + if (cpu_mask & (RATE_IN_242X | RATE_IN_243X)) ena = mask; - } else if (cpu_mask & RATE_IN_343X) { + else if (cpu_mask & RATE_IN_343X) ena = 0; - } /* Wait for lock */ while (((__raw_readl(reg) & mask) != ena) && @@ -267,7 +265,7 @@ static int omap2_dflt_clk_enable_wait(struct clk *clk) { int ret; - if (unlikely(clk->enable_reg == NULL)) { + if (!clk->enable_reg) { printk(KERN_ERR "clock.c: Enable for %s without enable code\n", clk->name); return 0; /* REVISIT: -EINVAL */ @@ -283,7 +281,7 @@ static void omap2_dflt_clk_disable(struct clk *clk) { u32 regval32; - if (clk->enable_reg == NULL) { + if (!clk->enable_reg) { /* * 'Independent' here refers to a clock which is not * controlled by its parent. @@ -330,7 +328,7 @@ void omap2_clk_disable(struct clk *clk) { if (clk->usecount > 0 && !(--clk->usecount)) { _omap2_clk_disable(clk); - if (likely((u32)clk->parent)) + if (clk->parent) omap2_clk_disable(clk->parent); if (clk->clkdm) omap2_clkdm_clk_disable(clk->clkdm, clk); @@ -343,10 +341,10 @@ int omap2_clk_enable(struct clk *clk) int ret = 0; if (clk->usecount++ == 0) { - if (likely((u32)clk->parent)) + if (clk->parent) ret = omap2_clk_enable(clk->parent); - if (unlikely(ret != 0)) { + if (ret != 0) { clk->usecount--; return ret; } @@ -356,7 +354,7 @@ int omap2_clk_enable(struct clk *clk) ret = _omap2_clk_enable(clk); - if (unlikely(ret != 0)) { + if (ret != 0) { if (clk->clkdm) omap2_clkdm_clk_disable(clk->clkdm, clk); @@ -384,7 +382,7 @@ void omap2_clksel_recalc(struct clk *clk) if (div == 0) return; - if (unlikely(clk->rate == clk->parent->rate / div)) + if (clk->rate == (clk->parent->rate / div)) return; clk->rate = clk->parent->rate / div; @@ -400,8 +398,8 @@ void omap2_clksel_recalc(struct clk *clk) * the element associated with the supplied parent clock address. * Returns a pointer to the struct clksel on success or NULL on error. */ -const struct clksel *omap2_get_clksel_by_parent(struct clk *clk, - struct clk *src_clk) +static const struct clksel *omap2_get_clksel_by_parent(struct clk *clk, + struct clk *src_clk) { const struct clksel *clks; @@ -450,7 +448,7 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate, *new_div = 1; clks = omap2_get_clksel_by_parent(clk, clk->parent); - if (clks == NULL) + if (!clks) return ~0; for (clkr = clks->rates; clkr->div; clkr++) { @@ -509,7 +507,7 @@ long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate) /* Given a clock and a rate apply a clock specific rounding function */ long omap2_clk_round_rate(struct clk *clk, unsigned long rate) { - if (clk->round_rate != NULL) + if (clk->round_rate) return clk->round_rate(clk, rate); if (clk->flags & RATE_FIXED) @@ -535,7 +533,7 @@ u32 omap2_clksel_to_divisor(struct clk *clk, u32 field_val) const struct clksel_rate *clkr; clks = omap2_get_clksel_by_parent(clk, clk->parent); - if (clks == NULL) + if (!clks) return 0; for (clkr = clks->rates; clkr->div; clkr++) { @@ -571,7 +569,7 @@ u32 omap2_divisor_to_clksel(struct clk *clk, u32 div) WARN_ON(div == 0); clks = omap2_get_clksel_by_parent(clk, clk->parent); - if (clks == NULL) + if (!clks) return 0; for (clkr = clks->rates; clkr->div; clkr++) { @@ -596,9 +594,9 @@ u32 omap2_divisor_to_clksel(struct clk *clk, u32 div) * * Returns the address of the clksel register upon success or NULL on error. */ -void __iomem *omap2_get_clksel(struct clk *clk, u32 *field_mask) +static void __iomem *omap2_get_clksel(struct clk *clk, u32 *field_mask) { - if (unlikely((clk->clksel_reg == NULL) || (clk->clksel_mask == NULL))) + if (!clk->clksel_reg || (clk->clksel_mask == 0)) return NULL; *field_mask = clk->clksel_mask; @@ -618,7 +616,7 @@ u32 omap2_clksel_get_divisor(struct clk *clk) void __iomem *div_addr; div_addr = omap2_get_clksel(clk, &field_mask); - if (div_addr == NULL) + if (!div_addr) return 0; field_val = __raw_readl(div_addr) & field_mask; @@ -637,7 +635,7 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate) return -EINVAL; div_addr = omap2_get_clksel(clk, &field_mask); - if (div_addr == NULL) + if (!div_addr) return -EINVAL; field_val = omap2_divisor_to_clksel(clk, new_div); @@ -675,7 +673,7 @@ int omap2_clk_set_rate(struct clk *clk, unsigned long rate) return -EINVAL; /* dpll_ck, core_ck, virt_prcm_set; plus all clksel clocks */ - if (clk->set_rate != NULL) + if (clk->set_rate) ret = clk->set_rate(clk, rate); return ret; @@ -696,7 +694,7 @@ static u32 omap2_clksel_get_src_field(void __iomem **src_addr, *src_addr = NULL; clks = omap2_get_clksel_by_parent(clk, src_clk); - if (clks == NULL) + if (!clks) return 0; for (clkr = clks->rates; clkr->div; clkr++) { @@ -726,7 +724,7 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) void __iomem *src_addr; u32 field_val, field_mask, reg_val, parent_div; - if (unlikely(clk->flags & CONFIG_PARTICIPANT)) + if (clk->flags & CONFIG_PARTICIPANT) return -EINVAL; if (!clk->clksel) @@ -734,7 +732,7 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) field_val = omap2_clksel_get_src_field(&src_addr, new_parent, &field_mask, clk, &parent_div); - if (src_addr == NULL) + if (!src_addr) return -EINVAL; if (clk->usecount > 0) @@ -794,7 +792,8 @@ int omap2_dpll_set_rate_tolerance(struct clk *clk, unsigned int tolerance) return 0; } -static unsigned long _dpll_compute_new_rate(unsigned long parent_rate, unsigned int m, unsigned int n) +static unsigned long _dpll_compute_new_rate(unsigned long parent_rate, + unsigned int m, unsigned int n) { unsigned long long num; diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index b0358b659b4..90077f0df78 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -27,7 +27,7 @@ void omap2_clk_disable(struct clk *clk); long omap2_clk_round_rate(struct clk *clk, unsigned long rate); int omap2_clk_set_rate(struct clk *clk, unsigned long rate); int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent); -int omap2_dpll_rate_tolerance_set(struct clk *clk, unsigned int tolerance); +int omap2_dpll_set_rate_tolerance(struct clk *clk, unsigned int tolerance); long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate); #ifdef CONFIG_OMAP_RESET_CLOCKS diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index bd77ef2d5ae..91ad2070264 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -339,7 +339,7 @@ static const struct clkops clkops_fixed = { * Uses the current prcm set to tell if a rate is valid. * You can go slower, but not faster within a given rate set. */ -long omap2_dpllcore_round_rate(unsigned long target_rate) +static long omap2_dpllcore_round_rate(unsigned long target_rate) { u32 high, low, core_clk_src; @@ -550,7 +550,9 @@ static int omap2_select_table_rate(struct clk *clk, unsigned long rate) /* Major subsystem dividers */ tmp = cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK; - cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD, CM_CLKSEL1); + cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD, + CM_CLKSEL1); + if (cpu_is_omap2430()) cm_write_mod_reg(prcm->cm_clksel_mdm, OMAP2430_MDM_MOD, CM_CLKSEL); @@ -582,20 +584,20 @@ static struct clk_functions omap2_clk_functions = { static u32 omap2_get_apll_clkin(void) { - u32 aplls, sclk = 0; + u32 aplls, srate = 0; aplls = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1); aplls &= OMAP24XX_APLLS_CLKIN_MASK; aplls >>= OMAP24XX_APLLS_CLKIN_SHIFT; if (aplls == APLLS_CLKIN_19_2MHZ) - sclk = 19200000; + srate = 19200000; else if (aplls == APLLS_CLKIN_13MHZ) - sclk = 13000000; + srate = 13000000; else if (aplls == APLLS_CLKIN_12MHZ) - sclk = 12000000; + srate = 12000000; - return sclk; + return srate; } static u32 omap2_get_sysclkdiv(void) diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 55361c16c9d..ea8ceaed09c 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -103,7 +103,7 @@ static struct platform_suspend_ops omap_pm_ops = { .valid = suspend_valid_only_mem, }; -int __init omap2_pm_init(void) +static int __init omap2_pm_init(void) { return 0; } diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index f147aec91f1..6f49a333289 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -113,12 +113,12 @@ struct clk_functions { extern unsigned int mpurate; -extern int clk_init(struct clk_functions * custom_clocks); +extern int clk_init(struct clk_functions *custom_clocks); extern int clk_register(struct clk *clk); extern void clk_unregister(struct clk *clk); extern void propagate_rate(struct clk *clk); extern void recalculate_root_clocks(void); -extern void followparent_recalc(struct clk * clk); +extern void followparent_recalc(struct clk *clk); extern int clk_get_usecount(struct clk *clk); extern void clk_enable_init_clocks(void); diff --git a/arch/arm/plat-omap/include/mach/powerdomain.h b/arch/arm/plat-omap/include/mach/powerdomain.h index 2806a9c8e4d..4948cb7af5b 100644 --- a/arch/arm/plat-omap/include/mach/powerdomain.h +++ b/arch/arm/plat-omap/include/mach/powerdomain.h @@ -145,6 +145,7 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm); int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst); int pwrdm_read_next_pwrst(struct powerdomain *pwrdm); +int pwrdm_read_pwrst(struct powerdomain *pwrdm); int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm); int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm); diff --git a/arch/arm/plat-omap/include/mach/prcm.h b/arch/arm/plat-omap/include/mach/prcm.h index 56eba0fd6f6..24ac3c71591 100644 --- a/arch/arm/plat-omap/include/mach/prcm.h +++ b/arch/arm/plat-omap/include/mach/prcm.h @@ -20,10 +20,11 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __ASM_ARM_ARCH_DPM_PRCM_H -#define __ASM_ARM_ARCH_DPM_PRCM_H +#ifndef __ASM_ARM_ARCH_OMAP_PRCM_H +#define __ASM_ARM_ARCH_OMAP_PRCM_H u32 omap_prcm_get_reset_sources(void); +void omap_prcm_arch_reset(char mode); #endif diff --git a/arch/arm/plat-omap/include/mach/system.h b/arch/arm/plat-omap/include/mach/system.h index 06923f26154..e9b95637f7f 100644 --- a/arch/arm/plat-omap/include/mach/system.h +++ b/arch/arm/plat-omap/include/mach/system.h @@ -9,12 +9,12 @@ #include #include +#include + #ifndef CONFIG_MACH_VOICEBLUE #define voiceblue_reset() do {} while (0) #endif -extern void omap_prcm_arch_reset(char mode); - static inline void arch_idle(void) { cpu_do_idle(); -- GitLab From 9299fd85a00a52b7c575fa02b3031ad407a15344 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 27 Jan 2009 19:12:54 -0700 Subject: [PATCH 1366/4982] [ARM] OMAP24xx clock: add missing SSI L4 interface clock This patch adds a missing OMAP24xx clock, the SSI L4 interface clock, as "ssi_l4_ick". linux-omap source commit is ace129d39b3107d330d4cf6934385d13521f2fec. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock24xx.c | 1 + arch/arm/mach-omap2/clock24xx.h | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index 91ad2070264..421728a7f90 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -112,6 +112,7 @@ static struct omap_clk omap24xx_clks[] = { CLK(NULL, "usb_l4_ick", &usb_l4_ick, CK_243X | CK_242X), /* L4 domain clocks */ CLK(NULL, "l4_ck", &l4_ck, CK_243X | CK_242X), + CLK(NULL, "ssi_l4_ick", &ssi_l4_ick, CK_243X | CK_242X), /* virtual meta-group clock */ CLK(NULL, "virt_prcm_set", &virt_prcm_set, CK_243X | CK_242X), /* general l4 interface ck, multi-parent functional clk */ diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h index b2442475fb4..32dd8573e56 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock24xx.h @@ -1276,6 +1276,20 @@ static struct clk ssi_ssr_sst_fck = { .set_rate = &omap2_clksel_set_rate }; +/* + * Presumably this is the same as SSI_ICLK. + * TRM contradicts itself on what clockdomain SSI_ICLK is in + */ +static struct clk ssi_l4_ick = { + .name = "ssi_l4_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &l4_ck, + .clkdm_name = "core_l4_clkdm", + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), + .enable_bit = OMAP24XX_EN_SSI_SHIFT, + .recalc = &followparent_recalc, +}; + /* * GFX clock domain -- GitLab From 207233533dd197457634810c6dc1b5d65ab6b8c7 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 27 Jan 2009 19:12:57 -0700 Subject: [PATCH 1367/4982] [ARM] OMAP3: move USBHOST SAR handling from clock framework to powerdomain layer Remove usbhost_sar_fclk from the OMAP3 clock framework. The bit that the clock was tweaking doesn't actually enable or disable a clock; it controls whether the hardware will save and restore USBHOST state when the powerdomain changes state. (That happens to coincidentally enable a clock for the duration of the operation, hence the earlier confusion.) In place of the clock, mark the USBHOST powerdomain as supporting hardware save-and-restore functionality. linux-omap source commit is f3ceac86a9d425d101d606d87a5af44afef27179. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock34xx.c | 1 - arch/arm/mach-omap2/clock34xx.h | 11 ----------- arch/arm/mach-omap2/powerdomains34xx.h | 1 + 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 943ac63fc6f..439a66918d3 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -209,7 +209,6 @@ static struct omap_clk omap34xx_clks[] = { CLK(NULL, "usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2), CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2), CLK(NULL, "usbhost_ick", &usbhost_ick, CK_3430ES2), - CLK(NULL, "usbhost_sar_fck", &usbhost_sar_fck, CK_3430ES2), CLK(NULL, "usim_fck", &usim_fck, CK_3430ES2), CLK(NULL, "gpt1_fck", &gpt1_fck, CK_343X), CLK(NULL, "wkup_32k_fck", &wkup_32k_fck, CK_343X), diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index f811a097851..a2dcf574d98 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -2218,17 +2218,6 @@ static struct clk usbhost_ick = { .recalc = &followparent_recalc, }; -static struct clk usbhost_sar_fck = { - .name = "usbhost_sar_fck", - .ops = &clkops_omap2_dflt, - .parent = &osc_sys_ck, - .init = &omap2_init_clk_clkdm, - .enable_reg = OMAP_PRM_REGADDR(OMAP3430ES2_USBHOST_MOD, PM_PWSTCTRL), - .enable_bit = OMAP3430ES2_SAVEANDRESTORE_SHIFT, - .clkdm_name = "usbhost_clkdm", - .recalc = &followparent_recalc, -}; - /* WKUP */ static const struct clksel_rate usim_96m_rates[] = { diff --git a/arch/arm/mach-omap2/powerdomains34xx.h b/arch/arm/mach-omap2/powerdomains34xx.h index f573f710839..3a8e4fbea5f 100644 --- a/arch/arm/mach-omap2/powerdomains34xx.h +++ b/arch/arm/mach-omap2/powerdomains34xx.h @@ -312,6 +312,7 @@ static struct powerdomain usbhost_pwrdm = { .sleepdep_srcs = dss_per_usbhost_sleepdeps, .pwrsts = PWRSTS_OFF_RET_ON, .pwrsts_logic_ret = PWRDM_POWER_RET, + .flags = PWRDM_HAS_HDWR_SAR, /* for USBHOST ctrlr only */ .banks = 1, .pwrsts_mem_ret = { [0] = PWRDM_POWER_RET, /* MEMRETSTATE */ -- GitLab From 9cfd985e27bfdf1e120aecaf595db265f4b5eb27 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 27 Jan 2009 19:13:02 -0700 Subject: [PATCH 1368/4982] [ARM] OMAP3 clock: fix 96MHz clocks Fix some bugs in the OMAP3 clock tree pertaining to the 96MHz clocks. The 96MHz portion of the clock tree should now have reasonable fidelity to the 34xx TRM Rev I. One remaining question mark: it's not clear exactly which 96MHz source clock the USIM uses. This patch sticks with the previous setting, which seems reasonable. linux-omap source commit is 15c706e8179ce238c3ba70a25846a36b73bd2359. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock34xx.h | 58 +++++++++++++++++---------- arch/arm/mach-omap2/cm-regbits-34xx.h | 8 +++- 2 files changed, 43 insertions(+), 23 deletions(-) diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index a2dcf574d98..2c84717f952 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -640,6 +640,12 @@ static const struct clksel omap_96m_alwon_fck_clksel[] = { { .parent = NULL } }; +/* + * DPLL4 generates DPLL4_M2X2_CLK which is then routed into the PRM as + * PRM_96M_ALWON_(F)CLK. Two clocks then emerge from the PRM: + * 96M_ALWON_FCLK (called "omap_96m_alwon_fck" below) and + * CM_96K_(F)CLK. + */ static struct clk omap_96m_alwon_fck = { .name = "omap_96m_alwon_fck", .ops = &clkops_null, @@ -652,28 +658,38 @@ static struct clk omap_96m_alwon_fck = { .recalc = &omap2_clksel_recalc, }; -static struct clk omap_96m_fck = { - .name = "omap_96m_fck", +static struct clk cm_96m_fck = { + .name = "cm_96m_fck", .ops = &clkops_null, .parent = &omap_96m_alwon_fck, .flags = RATE_PROPAGATES, .recalc = &followparent_recalc, }; -static const struct clksel cm_96m_fck_clksel[] = { - { .parent = &sys_ck, .rates = dpll_bypass_rates }, - { .parent = &dpll4_m2x2_ck, .rates = dpll_locked_rates }, +static const struct clksel_rate omap_96m_dpll_rates[] = { + { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 } +}; + +static const struct clksel_rate omap_96m_sys_rates[] = { + { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 0 } +}; + +static const struct clksel omap_96m_fck_clksel[] = { + { .parent = &cm_96m_fck, .rates = omap_96m_dpll_rates }, + { .parent = &sys_ck, .rates = omap_96m_sys_rates }, { .parent = NULL } }; -static struct clk cm_96m_fck = { - .name = "cm_96m_fck", +static struct clk omap_96m_fck = { + .name = "omap_96m_fck", .ops = &clkops_null, - .parent = &dpll4_m2x2_ck, + .parent = &sys_ck, .init = &omap2_init_clksel_parent, - .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), - .clksel_mask = OMAP3430_ST_PERIPH_CLK_MASK, - .clksel = cm_96m_fck_clksel, + .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), + .clksel_mask = OMAP3430_SOURCE_96M_MASK, + .clksel = omap_96m_fck_clksel, .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -742,13 +758,13 @@ static struct clk omap_54m_fck = { .ops = &clkops_null, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), - .clksel_mask = OMAP3430_SOURCE_54M, + .clksel_mask = OMAP3430_SOURCE_54M_MASK, .clksel = omap_54m_clksel, .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; -static const struct clksel_rate omap_48m_96md2_rates[] = { +static const struct clksel_rate omap_48m_cm96m_rates[] = { { .div = 2, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE }, { .div = 0 } }; @@ -759,7 +775,7 @@ static const struct clksel_rate omap_48m_alt_rates[] = { }; static const struct clksel omap_48m_clksel[] = { - { .parent = &cm_96m_fck, .rates = omap_48m_96md2_rates }, + { .parent = &cm_96m_fck, .rates = omap_48m_cm96m_rates }, { .parent = &sys_altclk, .rates = omap_48m_alt_rates }, { .parent = NULL } }; @@ -769,7 +785,7 @@ static struct clk omap_48m_fck = { .ops = &clkops_null, .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), - .clksel_mask = OMAP3430_SOURCE_48M, + .clksel_mask = OMAP3430_SOURCE_48M_MASK, .clksel = omap_48m_clksel, .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, @@ -958,10 +974,10 @@ static const struct clksel_rate clkout2_src_54m_rates[] = { }; static const struct clksel clkout2_src_clksel[] = { - { .parent = &core_ck, .rates = clkout2_src_core_rates }, - { .parent = &sys_ck, .rates = clkout2_src_sys_rates }, - { .parent = &omap_96m_alwon_fck, .rates = clkout2_src_96m_rates }, - { .parent = &omap_54m_fck, .rates = clkout2_src_54m_rates }, + { .parent = &core_ck, .rates = clkout2_src_core_rates }, + { .parent = &sys_ck, .rates = clkout2_src_sys_rates }, + { .parent = &cm_96m_fck, .rates = clkout2_src_96m_rates }, + { .parent = &omap_54m_fck, .rates = clkout2_src_54m_rates }, { .parent = NULL } }; @@ -2782,8 +2798,8 @@ static struct clk mcbsp4_ick = { }; static const struct clksel mcbsp_234_clksel[] = { - { .parent = &per_96m_fck, .rates = common_mcbsp_96m_rates }, - { .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates }, + { .parent = &core_96m_fck, .rates = common_mcbsp_96m_rates }, + { .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates }, { .parent = NULL } }; diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h b/arch/arm/mach-omap2/cm-regbits-34xx.h index 219f5c8d965..a46f93c399d 100644 --- a/arch/arm/mach-omap2/cm-regbits-34xx.h +++ b/arch/arm/mach-omap2/cm-regbits-34xx.h @@ -449,8 +449,12 @@ #define OMAP3430_CORE_DPLL_MULT_MASK (0x7ff << 16) #define OMAP3430_CORE_DPLL_DIV_SHIFT 8 #define OMAP3430_CORE_DPLL_DIV_MASK (0x7f << 8) -#define OMAP3430_SOURCE_54M (1 << 5) -#define OMAP3430_SOURCE_48M (1 << 3) +#define OMAP3430_SOURCE_96M_SHIFT 6 +#define OMAP3430_SOURCE_96M_MASK (1 << 6) +#define OMAP3430_SOURCE_54M_SHIFT 5 +#define OMAP3430_SOURCE_54M_MASK (1 << 5) +#define OMAP3430_SOURCE_48M_SHIFT 3 +#define OMAP3430_SOURCE_48M_MASK (1 << 3) /* CM_CLKSEL2_PLL */ #define OMAP3430_PERIPH_DPLL_MULT_SHIFT 8 -- GitLab From 712d7c860269018fc92169e0f6b42218fd82a6d1 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Tue, 27 Jan 2009 19:13:05 -0700 Subject: [PATCH 1369/4982] [ARM] OMAP2: Fix definition of SGX clock register bits The GFX/SGX functional and interface clocks have different masks, for some unknown reason, so split EN_SGX_SHIFT into one each for fclk and iclk. Correct according to the TRM and the far more important 'does this actually work at all?' metric. linux-omap source commit is de1121fdb899f762b9e717f44eaf3fae7c00cd3e. Signed-off-by: Daniel Stone Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock34xx.h | 4 ++-- arch/arm/mach-omap2/cm-regbits-34xx.h | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index 2c84717f952..6b39ad47633 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -1293,7 +1293,7 @@ static struct clk sgx_fck = { .ops = &clkops_omap2_dflt_wait, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_FCLKEN), - .enable_bit = OMAP3430ES2_EN_SGX_SHIFT, + .enable_bit = OMAP3430ES2_CM_FCLKEN_SGX_EN_SGX_SHIFT, .clksel_reg = OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_CLKSEL), .clksel_mask = OMAP3430ES2_CLKSEL_SGX_MASK, .clksel = sgx_clksel, @@ -1307,7 +1307,7 @@ static struct clk sgx_ick = { .parent = &l3_ick, .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_ICLKEN), - .enable_bit = OMAP3430ES2_EN_SGX_SHIFT, + .enable_bit = OMAP3430ES2_CM_ICLKEN_SGX_EN_SGX_SHIFT, .clkdm_name = "sgx_clkdm", .recalc = &followparent_recalc, }; diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h b/arch/arm/mach-omap2/cm-regbits-34xx.h index a46f93c399d..f3c327bac1c 100644 --- a/arch/arm/mach-omap2/cm-regbits-34xx.h +++ b/arch/arm/mach-omap2/cm-regbits-34xx.h @@ -332,8 +332,12 @@ #define OMAP3430ES1_CLKACTIVITY_GFX_MASK (1 << 0) /* CM_FCLKEN_SGX */ -#define OMAP3430ES2_EN_SGX_SHIFT 1 -#define OMAP3430ES2_EN_SGX_MASK (1 << 1) +#define OMAP3430ES2_CM_FCLKEN_SGX_EN_SGX_SHIFT 1 +#define OMAP3430ES2_CM_FCLKEN_SGX_EN_SGX_MASK (1 << 1) + +/* CM_ICLKEN_SGX */ +#define OMAP3430ES2_CM_ICLKEN_SGX_EN_SGX_SHIFT 0 +#define OMAP3430ES2_CM_ICLKEN_SGX_EN_SGX_MASK (1 << 0) /* CM_CLKSEL_SGX */ #define OMAP3430ES2_CLKSEL_SGX_SHIFT 0 -- GitLab From 6c8fe0b954b198d8e9116b824f7998c00f47c46c Mon Sep 17 00:00:00 2001 From: Sergio Aguirre Date: Tue, 27 Jan 2009 19:13:09 -0700 Subject: [PATCH 1370/4982] [ARM] OMAP: Add CSI2 clock struct for handling it with clock API Add CSI2 clock struct for handling it with clock API when TI PM is disabled. linux-omap source commit is 8b20f4498928459276bd3366e3381ad595d23432. Signed-off-by: Sergio Aguirre Acked-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock34xx.c | 1 + arch/arm/mach-omap2/clock34xx.h | 11 +++++++++++ arch/arm/mach-omap2/cm-regbits-34xx.h | 2 ++ 3 files changed, 14 insertions(+) diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 439a66918d3..cb5e068feb5 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -206,6 +206,7 @@ static struct omap_clk omap34xx_clks[] = { CLK(NULL, "dss_ick", &dss_ick, CK_343X), CLK(NULL, "cam_mclk", &cam_mclk, CK_343X), CLK(NULL, "cam_ick", &cam_ick, CK_343X), + CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_343X), CLK(NULL, "usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2), CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2), CLK(NULL, "usbhost_ick", &usbhost_ick, CK_3430ES2), diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index 6b39ad47633..c265cdcc86a 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -2198,6 +2198,17 @@ static struct clk cam_ick = { .recalc = &followparent_recalc, }; +static struct clk csi2_96m_fck = { + .name = "csi2_96m_fck", + .ops = &clkops_omap2_dflt_wait, + .parent = &core_96m_fck, + .init = &omap2_init_clk_clkdm, + .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN), + .enable_bit = OMAP3430_EN_CSI2_SHIFT, + .clkdm_name = "cam_clkdm", + .recalc = &followparent_recalc, +}; + /* USBHOST - 3430ES2 only */ static struct clk usbhost_120m_fck = { diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h b/arch/arm/mach-omap2/cm-regbits-34xx.h index f3c327bac1c..aaf68a59800 100644 --- a/arch/arm/mach-omap2/cm-regbits-34xx.h +++ b/arch/arm/mach-omap2/cm-regbits-34xx.h @@ -524,6 +524,8 @@ #define OMAP3430_CLKACTIVITY_DSS_MASK (1 << 0) /* CM_FCLKEN_CAM specific bits */ +#define OMAP3430_EN_CSI2 (1 << 1) +#define OMAP3430_EN_CSI2_SHIFT 1 /* CM_ICLKEN_CAM specific bits */ -- GitLab From ae8578c0194695bd37435249dfed720769a6bbf3 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 27 Jan 2009 19:13:12 -0700 Subject: [PATCH 1371/4982] [ARM] OMAP: Make dpll4_m4_ck programmable with clk_set_rate() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Filling the set_rate and round_rate fields of dpll4_m4_ck makes this clock programmable through clk_set_rate(). This is needed to give omapfb control over the dss1_alwon_fck rate. This patch includes a fix from Tomi Valkeinen . linux-omap source commits are e42218d45afbc3e654e289e021e6b80c657b16c2 and 9d211b761b3cdf7736602ecf7e68f8a298c13278. Signed-off-by: MÃ¥ns RullgÃ¥rd Signed-off-by: Tomi Valkeinen Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock34xx.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index c265cdcc86a..65929cc3740 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -811,6 +811,8 @@ static struct clk dpll4_m4_ck = { .clksel = div16_dpll4_clksel, .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, + .set_rate = &omap2_clksel_set_rate, + .round_rate = &omap2_clksel_round_rate, }; /* The PWRDN bit is apparently only available on 3430ES2 and above */ -- GitLab From aeec299011da8c3f07a47fe5d988f0eafda53906 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Tue, 27 Jan 2009 19:13:38 -0700 Subject: [PATCH 1372/4982] [ARM] OMAP2: Implement CPUfreq frequency table based on PRCM table This patch adds a CPUfreq frequency-table implementation for OMAP2 by walking the PRCM rate-table for available entries and adding them to a CPUfreq table. CPUfreq can then be used to manage switching between all the available entries in the PRCM rate table. Either use the CPUfreq sysfs interface directly, (see Section 3 of Documentation/cpu-freq/user-guide.txt) or use the cpufrequtils package: http://www.kernel.org/pub/linux/utils/kernel/cpufreq/cpufrequtils.html Signed-off-by: Kevin Hilman Updated to try to use cpufreq_table if it exists. linux-omap source commit is 77ce544fa48deb7a2003f454624e3ca10d37ab87. Signed-off-by: Tony Lindgren Signed-off-by: Paul Walmsley Signed-off-by: Russell King --- arch/arm/mach-omap2/clock24xx.c | 42 ++++++++++++++++++ arch/arm/plat-omap/cpu-omap.c | 57 +++++++++++++++++++++++-- arch/arm/plat-omap/include/mach/clock.h | 3 ++ 3 files changed, 98 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index 421728a7f90..b9902666e4b 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -574,6 +574,45 @@ static int omap2_select_table_rate(struct clk *clk, unsigned long rate) return 0; } +#ifdef CONFIG_CPU_FREQ +/* + * Walk PRCM rate table and fillout cpufreq freq_table + */ +static struct cpufreq_frequency_table freq_table[ARRAY_SIZE(rate_table)]; + +void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table) +{ + struct prcm_config *prcm; + int i = 0; + + for (prcm = rate_table; prcm->mpu_speed; prcm++) { + if (!(prcm->flags & cpu_mask)) + continue; + if (prcm->xtal_speed != sys_ck.rate) + continue; + + /* don't put bypass rates in table */ + if (prcm->dpll_speed == prcm->xtal_speed) + continue; + + freq_table[i].index = i; + freq_table[i].frequency = prcm->mpu_speed / 1000; + i++; + } + + if (i == 0) { + printk(KERN_WARNING "%s: failed to initialize frequency " + "table\n", __func__); + return; + } + + freq_table[i].index = i; + freq_table[i].frequency = CPUFREQ_TABLE_END; + + *table = &freq_table[0]; +} +#endif + static struct clk_functions omap2_clk_functions = { .clk_enable = omap2_clk_enable, .clk_disable = omap2_clk_disable, @@ -581,6 +620,9 @@ static struct clk_functions omap2_clk_functions = { .clk_set_rate = omap2_clk_set_rate, .clk_set_parent = omap2_clk_set_parent, .clk_disable_unused = omap2_clk_disable_unused, +#ifdef CONFIG_CPU_FREQ + .clk_init_cpufreq_table = omap2_clk_init_cpufreq_table, +#endif }; static u32 omap2_get_apll_clkin(void) diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c index b2690242a39..843e8af6406 100644 --- a/arch/arm/plat-omap/cpu-omap.c +++ b/arch/arm/plat-omap/cpu-omap.c @@ -23,10 +23,13 @@ #include #include +#include #include #define VERY_HI_RATE 900000000 +static struct cpufreq_frequency_table *freq_table; + #ifdef CONFIG_ARCH_OMAP1 #define MPU_CLK "mpu" #else @@ -39,6 +42,9 @@ static struct clk *mpu_clk; int omap_verify_speed(struct cpufreq_policy *policy) { + if (freq_table) + return cpufreq_frequency_table_verify(policy, freq_table); + if (policy->cpu) return -EINVAL; @@ -70,12 +76,26 @@ static int omap_target(struct cpufreq_policy *policy, struct cpufreq_freqs freqs; int ret = 0; + /* Ensure desired rate is within allowed range. Some govenors + * (ondemand) will just pass target_freq=0 to get the minimum. */ + if (target_freq < policy->cpuinfo.min_freq) + target_freq = policy->cpuinfo.min_freq; + if (target_freq > policy->cpuinfo.max_freq) + target_freq = policy->cpuinfo.max_freq; + freqs.old = omap_getspeed(0); freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; freqs.cpu = 0; + if (freqs.old == freqs.new) + return ret; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - ret = clk_set_rate(mpu_clk, target_freq * 1000); +#ifdef CONFIG_CPU_FREQ_DEBUG + printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n", + freqs.old, freqs.new); +#endif + ret = clk_set_rate(mpu_clk, freqs.new * 1000); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); return ret; @@ -83,16 +103,31 @@ static int omap_target(struct cpufreq_policy *policy, static int __init omap_cpu_init(struct cpufreq_policy *policy) { + int result = 0; + mpu_clk = clk_get(NULL, MPU_CLK); if (IS_ERR(mpu_clk)) return PTR_ERR(mpu_clk); if (policy->cpu != 0) return -EINVAL; + policy->cur = policy->min = policy->max = omap_getspeed(0); - policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; - policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, VERY_HI_RATE) / 1000; - policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + + clk_init_cpufreq_table(&freq_table); + if (freq_table) { + result = cpufreq_frequency_table_cpuinfo(policy, freq_table); + if (!result) + cpufreq_frequency_table_get_attr(freq_table, + policy->cpu); + } else { + policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; + policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, + VERY_HI_RATE) / 1000; + } + + /* FIXME: what's the actual transition time? */ + policy->cpuinfo.transition_latency = 10 * 1000 * 1000; return 0; } @@ -103,6 +138,11 @@ static int omap_cpu_exit(struct cpufreq_policy *policy) return 0; } +static struct freq_attr *omap_cpufreq_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + static struct cpufreq_driver omap_driver = { .flags = CPUFREQ_STICKY, .verify = omap_verify_speed, @@ -111,6 +151,7 @@ static struct cpufreq_driver omap_driver = { .init = omap_cpu_init, .exit = omap_cpu_exit, .name = "omap", + .attr = omap_cpufreq_attr, }; static int __init omap_cpufreq_init(void) @@ -119,3 +160,11 @@ static int __init omap_cpufreq_init(void) } arch_initcall(omap_cpufreq_init); + +/* + * if ever we want to remove this, upon cleanup call: + * + * cpufreq_unregister_driver() + * cpufreq_frequency_table_put_attr() + */ + diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index 6f49a333289..681c65105e2 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -121,6 +121,9 @@ extern void recalculate_root_clocks(void); extern void followparent_recalc(struct clk *clk); extern int clk_get_usecount(struct clk *clk); extern void clk_enable_init_clocks(void); +#ifdef CONFIG_CPU_FREQ +extern void clk_init_cpufreq_table(struct cpufreq_frequency_table **table); +#endif extern const struct clkops clkops_null; -- GitLab From 5b74c67660dbd536a4f4e8cea12d10683ad2e432 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 3 Feb 2009 02:10:03 -0700 Subject: [PATCH 1373/4982] [ARM] OMAP2/3 clockdomains: combine pwrdm, pwrdm_name into union in struct clockdomain struct clockdomain contains a struct powerdomain *pwrdm and const char *pwrdm_name. The pwrdm_name is only used at initialization to look up the appropriate pwrdm pointer. Combining these into a union saves about 100 bytes on 3430SDP. This patch should not cause any change in kernel function. Updated to gracefully handle autodeps that contain invalid powerdomains, per Russell King's review comments. Boot-tested on BeagleBoard ES2.1. linux-omap source commit is 718fc6cd4db902aa2242a736cc3feb8744a4c71a. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clockdomain.c | 59 ++++++++++--------- arch/arm/mach-omap2/clockdomains.h | 54 +++++++++-------- arch/arm/plat-omap/include/mach/clockdomain.h | 24 ++++---- 3 files changed, 72 insertions(+), 65 deletions(-) diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 4c3ce9cfd94..e9b4f6c564e 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -71,14 +72,14 @@ static void _autodep_lookup(struct clkdm_pwrdm_autodep *autodep) if (!omap_chip_is(autodep->omap_chip)) return; - pwrdm = pwrdm_lookup(autodep->pwrdm_name); + pwrdm = pwrdm_lookup(autodep->pwrdm.name); if (!pwrdm) { pr_debug("clockdomain: _autodep_lookup: powerdomain %s " - "does not exist\n", autodep->pwrdm_name); + "does not exist\n", autodep->pwrdm.name); WARN_ON(1); - return; + pwrdm = ERR_PTR(-ENOENT); } - autodep->pwrdm = pwrdm; + autodep->pwrdm.ptr = pwrdm; return; } @@ -95,16 +96,16 @@ static void _clkdm_add_autodeps(struct clockdomain *clkdm) { struct clkdm_pwrdm_autodep *autodep; - for (autodep = autodeps; autodep->pwrdm_name; autodep++) { - if (!autodep->pwrdm) + for (autodep = autodeps; autodep->pwrdm.ptr; autodep++) { + if (IS_ERR(autodep->pwrdm.ptr)) continue; pr_debug("clockdomain: adding %s sleepdep/wkdep for " - "pwrdm %s\n", autodep->pwrdm_name, - clkdm->pwrdm->name); + "pwrdm %s\n", autodep->pwrdm.ptr->name, + clkdm->pwrdm.ptr->name); - pwrdm_add_sleepdep(clkdm->pwrdm, autodep->pwrdm); - pwrdm_add_wkdep(clkdm->pwrdm, autodep->pwrdm); + pwrdm_add_sleepdep(clkdm->pwrdm.ptr, autodep->pwrdm.ptr); + pwrdm_add_wkdep(clkdm->pwrdm.ptr, autodep->pwrdm.ptr); } } @@ -120,16 +121,16 @@ static void _clkdm_del_autodeps(struct clockdomain *clkdm) { struct clkdm_pwrdm_autodep *autodep; - for (autodep = autodeps; autodep->pwrdm_name; autodep++) { - if (!autodep->pwrdm) + for (autodep = autodeps; autodep->pwrdm.ptr; autodep++) { + if (IS_ERR(autodep->pwrdm.ptr)) continue; pr_debug("clockdomain: removing %s sleepdep/wkdep for " - "pwrdm %s\n", autodep->pwrdm_name, - clkdm->pwrdm->name); + "pwrdm %s\n", autodep->pwrdm.ptr->name, + clkdm->pwrdm.ptr->name); - pwrdm_del_sleepdep(clkdm->pwrdm, autodep->pwrdm); - pwrdm_del_wkdep(clkdm->pwrdm, autodep->pwrdm); + pwrdm_del_sleepdep(clkdm->pwrdm.ptr, autodep->pwrdm.ptr); + pwrdm_del_wkdep(clkdm->pwrdm.ptr, autodep->pwrdm.ptr); } } @@ -179,7 +180,7 @@ void clkdm_init(struct clockdomain **clkdms, autodeps = init_autodeps; if (autodeps) - for (autodep = autodeps; autodep->pwrdm_name; autodep++) + for (autodep = autodeps; autodep->pwrdm.ptr; autodep++) _autodep_lookup(autodep); } @@ -202,13 +203,13 @@ int clkdm_register(struct clockdomain *clkdm) if (!omap_chip_is(clkdm->omap_chip)) return -EINVAL; - pwrdm = pwrdm_lookup(clkdm->pwrdm_name); + pwrdm = pwrdm_lookup(clkdm->pwrdm.name); if (!pwrdm) { pr_debug("clockdomain: clkdm_register %s: powerdomain %s " - "does not exist\n", clkdm->name, clkdm->pwrdm_name); + "does not exist\n", clkdm->name, clkdm->pwrdm.name); return -EINVAL; } - clkdm->pwrdm = pwrdm; + clkdm->pwrdm.ptr = pwrdm; mutex_lock(&clkdm_mutex); /* Verify that the clockdomain is not already registered */ @@ -242,7 +243,7 @@ int clkdm_unregister(struct clockdomain *clkdm) if (!clkdm) return -EINVAL; - pwrdm_del_clkdm(clkdm->pwrdm, clkdm); + pwrdm_del_clkdm(clkdm->pwrdm.ptr, clkdm); mutex_lock(&clkdm_mutex); list_del(&clkdm->node); @@ -327,7 +328,7 @@ struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm) if (!clkdm) return NULL; - return clkdm->pwrdm; + return clkdm->pwrdm.ptr; } @@ -348,7 +349,7 @@ static int omap2_clkdm_clktrctrl_read(struct clockdomain *clkdm) if (!clkdm) return -EINVAL; - v = cm_read_mod_reg(clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL); + v = cm_read_mod_reg(clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL); v &= clkdm->clktrctrl_mask; v >>= __ffs(clkdm->clktrctrl_mask); @@ -380,7 +381,7 @@ int omap2_clkdm_sleep(struct clockdomain *clkdm) if (cpu_is_omap24xx()) { cm_set_mod_reg_bits(OMAP24XX_FORCESTATE, - clkdm->pwrdm->prcm_offs, PM_PWSTCTRL); + clkdm->pwrdm.ptr->prcm_offs, PM_PWSTCTRL); } else if (cpu_is_omap34xx()) { @@ -388,7 +389,7 @@ int omap2_clkdm_sleep(struct clockdomain *clkdm) __ffs(clkdm->clktrctrl_mask)); cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, v, - clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL); + clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL); } else { BUG(); @@ -422,7 +423,7 @@ int omap2_clkdm_wakeup(struct clockdomain *clkdm) if (cpu_is_omap24xx()) { cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE, - clkdm->pwrdm->prcm_offs, PM_PWSTCTRL); + clkdm->pwrdm.ptr->prcm_offs, PM_PWSTCTRL); } else if (cpu_is_omap34xx()) { @@ -430,7 +431,7 @@ int omap2_clkdm_wakeup(struct clockdomain *clkdm) __ffs(clkdm->clktrctrl_mask)); cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, v, - clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL); + clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL); } else { BUG(); @@ -478,7 +479,7 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm) cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, v << __ffs(clkdm->clktrctrl_mask), - clkdm->pwrdm->prcm_offs, + clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL); } @@ -516,7 +517,7 @@ void omap2_clkdm_deny_idle(struct clockdomain *clkdm) cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, v << __ffs(clkdm->clktrctrl_mask), - clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL); + clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL); if (atomic_read(&clkdm->usecount) > 0) _clkdm_del_autodeps(clkdm); diff --git a/arch/arm/mach-omap2/clockdomains.h b/arch/arm/mach-omap2/clockdomains.h index cd86dcc7b42..e17c3693542 100644 --- a/arch/arm/mach-omap2/clockdomains.h +++ b/arch/arm/mach-omap2/clockdomains.h @@ -19,7 +19,7 @@ /* This is an implicit clockdomain - it is never defined as such in TRM */ static struct clockdomain wkup_clkdm = { .name = "wkup_clkdm", - .pwrdm_name = "wkup_pwrdm", + .pwrdm = { .name = "wkup_pwrdm" }, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430), }; @@ -31,7 +31,7 @@ static struct clockdomain wkup_clkdm = { static struct clockdomain mpu_2420_clkdm = { .name = "mpu_clkdm", - .pwrdm_name = "mpu_pwrdm", + .pwrdm = { .name = "mpu_pwrdm" }, .flags = CLKDM_CAN_HWSUP, .clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420), @@ -39,7 +39,7 @@ static struct clockdomain mpu_2420_clkdm = { static struct clockdomain iva1_2420_clkdm = { .name = "iva1_clkdm", - .pwrdm_name = "dsp_pwrdm", + .pwrdm = { .name = "dsp_pwrdm" }, .flags = CLKDM_CAN_HWSUP_SWSUP, .clktrctrl_mask = OMAP2420_AUTOSTATE_IVA_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420), @@ -56,7 +56,7 @@ static struct clockdomain iva1_2420_clkdm = { static struct clockdomain mpu_2430_clkdm = { .name = "mpu_clkdm", - .pwrdm_name = "mpu_pwrdm", + .pwrdm = { .name = "mpu_pwrdm" }, .flags = CLKDM_CAN_HWSUP_SWSUP, .clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430), @@ -64,7 +64,7 @@ static struct clockdomain mpu_2430_clkdm = { static struct clockdomain mdm_clkdm = { .name = "mdm_clkdm", - .pwrdm_name = "mdm_pwrdm", + .pwrdm = { .name = "mdm_pwrdm" }, .flags = CLKDM_CAN_HWSUP_SWSUP, .clktrctrl_mask = OMAP2430_AUTOSTATE_MDM_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430), @@ -81,7 +81,7 @@ static struct clockdomain mdm_clkdm = { static struct clockdomain dsp_clkdm = { .name = "dsp_clkdm", - .pwrdm_name = "dsp_pwrdm", + .pwrdm = { .name = "dsp_pwrdm" }, .flags = CLKDM_CAN_HWSUP_SWSUP, .clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX), @@ -89,7 +89,7 @@ static struct clockdomain dsp_clkdm = { static struct clockdomain gfx_24xx_clkdm = { .name = "gfx_clkdm", - .pwrdm_name = "gfx_pwrdm", + .pwrdm = { .name = "gfx_pwrdm" }, .flags = CLKDM_CAN_HWSUP_SWSUP, .clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX), @@ -97,7 +97,7 @@ static struct clockdomain gfx_24xx_clkdm = { static struct clockdomain core_l3_24xx_clkdm = { .name = "core_l3_clkdm", - .pwrdm_name = "core_pwrdm", + .pwrdm = { .name = "core_pwrdm" }, .flags = CLKDM_CAN_HWSUP, .clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX), @@ -105,7 +105,7 @@ static struct clockdomain core_l3_24xx_clkdm = { static struct clockdomain core_l4_24xx_clkdm = { .name = "core_l4_clkdm", - .pwrdm_name = "core_pwrdm", + .pwrdm = { .name = "core_pwrdm" }, .flags = CLKDM_CAN_HWSUP, .clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX), @@ -113,7 +113,7 @@ static struct clockdomain core_l4_24xx_clkdm = { static struct clockdomain dss_24xx_clkdm = { .name = "dss_clkdm", - .pwrdm_name = "core_pwrdm", + .pwrdm = { .name = "core_pwrdm" }, .flags = CLKDM_CAN_HWSUP, .clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX), @@ -130,7 +130,7 @@ static struct clockdomain dss_24xx_clkdm = { static struct clockdomain mpu_34xx_clkdm = { .name = "mpu_clkdm", - .pwrdm_name = "mpu_pwrdm", + .pwrdm = { .name = "mpu_pwrdm" }, .flags = CLKDM_CAN_HWSUP | CLKDM_CAN_FORCE_WAKEUP, .clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), @@ -138,7 +138,7 @@ static struct clockdomain mpu_34xx_clkdm = { static struct clockdomain neon_clkdm = { .name = "neon_clkdm", - .pwrdm_name = "neon_pwrdm", + .pwrdm = { .name = "neon_pwrdm" }, .flags = CLKDM_CAN_HWSUP_SWSUP, .clktrctrl_mask = OMAP3430_CLKTRCTRL_NEON_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), @@ -146,7 +146,7 @@ static struct clockdomain neon_clkdm = { static struct clockdomain iva2_clkdm = { .name = "iva2_clkdm", - .pwrdm_name = "iva2_pwrdm", + .pwrdm = { .name = "iva2_pwrdm" }, .flags = CLKDM_CAN_HWSUP_SWSUP, .clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), @@ -154,7 +154,7 @@ static struct clockdomain iva2_clkdm = { static struct clockdomain gfx_3430es1_clkdm = { .name = "gfx_clkdm", - .pwrdm_name = "gfx_pwrdm", + .pwrdm = { .name = "gfx_pwrdm" }, .flags = CLKDM_CAN_HWSUP_SWSUP, .clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_GFX_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1), @@ -162,7 +162,7 @@ static struct clockdomain gfx_3430es1_clkdm = { static struct clockdomain sgx_clkdm = { .name = "sgx_clkdm", - .pwrdm_name = "sgx_pwrdm", + .pwrdm = { .name = "sgx_pwrdm" }, .flags = CLKDM_CAN_HWSUP_SWSUP, .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2), @@ -177,7 +177,7 @@ static struct clockdomain sgx_clkdm = { */ static struct clockdomain d2d_clkdm = { .name = "d2d_clkdm", - .pwrdm_name = "core_pwrdm", + .pwrdm = { .name = "core_pwrdm" }, .flags = CLKDM_CAN_HWSUP, .clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_D2D_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), @@ -185,7 +185,7 @@ static struct clockdomain d2d_clkdm = { static struct clockdomain core_l3_34xx_clkdm = { .name = "core_l3_clkdm", - .pwrdm_name = "core_pwrdm", + .pwrdm = { .name = "core_pwrdm" }, .flags = CLKDM_CAN_HWSUP, .clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), @@ -193,7 +193,7 @@ static struct clockdomain core_l3_34xx_clkdm = { static struct clockdomain core_l4_34xx_clkdm = { .name = "core_l4_clkdm", - .pwrdm_name = "core_pwrdm", + .pwrdm = { .name = "core_pwrdm" }, .flags = CLKDM_CAN_HWSUP, .clktrctrl_mask = OMAP3430_CLKTRCTRL_L4_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), @@ -201,7 +201,7 @@ static struct clockdomain core_l4_34xx_clkdm = { static struct clockdomain dss_34xx_clkdm = { .name = "dss_clkdm", - .pwrdm_name = "dss_pwrdm", + .pwrdm = { .name = "dss_pwrdm" }, .flags = CLKDM_CAN_HWSUP_SWSUP, .clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), @@ -209,7 +209,7 @@ static struct clockdomain dss_34xx_clkdm = { static struct clockdomain cam_clkdm = { .name = "cam_clkdm", - .pwrdm_name = "cam_pwrdm", + .pwrdm = { .name = "cam_pwrdm" }, .flags = CLKDM_CAN_HWSUP_SWSUP, .clktrctrl_mask = OMAP3430_CLKTRCTRL_CAM_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), @@ -217,7 +217,7 @@ static struct clockdomain cam_clkdm = { static struct clockdomain usbhost_clkdm = { .name = "usbhost_clkdm", - .pwrdm_name = "usbhost_pwrdm", + .pwrdm = { .name = "usbhost_pwrdm" }, .flags = CLKDM_CAN_HWSUP_SWSUP, .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2), @@ -225,7 +225,7 @@ static struct clockdomain usbhost_clkdm = { static struct clockdomain per_clkdm = { .name = "per_clkdm", - .pwrdm_name = "per_pwrdm", + .pwrdm = { .name = "per_pwrdm" }, .flags = CLKDM_CAN_HWSUP_SWSUP, .clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), @@ -233,7 +233,7 @@ static struct clockdomain per_clkdm = { static struct clockdomain emu_clkdm = { .name = "emu_clkdm", - .pwrdm_name = "emu_pwrdm", + .pwrdm = { .name = "emu_pwrdm" }, .flags = CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_SWSUP, .clktrctrl_mask = OMAP3430_CLKTRCTRL_EMU_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), @@ -247,14 +247,16 @@ static struct clockdomain emu_clkdm = { static struct clkdm_pwrdm_autodep clkdm_pwrdm_autodeps[] = { { - .pwrdm_name = "mpu_pwrdm", + .pwrdm = { .name = "mpu_pwrdm" }, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) }, { - .pwrdm_name = "iva2_pwrdm", + .pwrdm = { .name = "iva2_pwrdm" }, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) }, - { NULL } + { + .pwrdm = { .name = NULL }, + } }; /* diff --git a/arch/arm/plat-omap/include/mach/clockdomain.h b/arch/arm/plat-omap/include/mach/clockdomain.h index 1f51f017378..b9d0dd2da89 100644 --- a/arch/arm/plat-omap/include/mach/clockdomain.h +++ b/arch/arm/plat-omap/include/mach/clockdomain.h @@ -1,5 +1,5 @@ /* - * linux/include/asm-arm/arch-omap/clockdomain.h + * arch/arm/plat-omap/include/mach/clockdomain.h * * OMAP2/3 clockdomain framework functions * @@ -48,11 +48,13 @@ */ struct clkdm_pwrdm_autodep { - /* Name of the powerdomain to add a wkdep/sleepdep on */ - const char *pwrdm_name; + union { + /* Name of the powerdomain to add a wkdep/sleepdep on */ + const char *name; - /* Powerdomain pointer (looked up at clkdm_init() time) */ - struct powerdomain *pwrdm; + /* Powerdomain pointer (looked up at clkdm_init() time) */ + struct powerdomain *ptr; + } pwrdm; /* OMAP chip types that this clockdomain dep is valid on */ const struct omap_chip_id omap_chip; @@ -64,8 +66,13 @@ struct clockdomain { /* Clockdomain name */ const char *name; - /* Powerdomain enclosing this clockdomain */ - const char *pwrdm_name; + union { + /* Powerdomain enclosing this clockdomain */ + const char *name; + + /* Powerdomain pointer assigned at clkdm_register() */ + struct powerdomain *ptr; + } pwrdm; /* CLKTRCTRL/AUTOSTATE field mask in CM_CLKSTCTRL reg */ const u16 clktrctrl_mask; @@ -79,9 +86,6 @@ struct clockdomain { /* Usecount tracking */ atomic_t usecount; - /* Powerdomain pointer assigned at clkdm_register() */ - struct powerdomain *pwrdm; - struct list_head node; }; -- GitLab From d37f1a136783aa9c9b1a6cd832a60cb2bbd2453a Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 10 Sep 2008 10:47:36 -0600 Subject: [PATCH 1374/4982] [ARM] OMAP2/3 clockdomains: add CM and PRM clkdms Add clockdomains for the CM and PRM. These will ultimately replace the "wkup_clkdm", which appears to not actually exist on the hardware. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clockdomains.h | 19 +++++++++++++++++++ arch/arm/plat-omap/include/mach/powerdomain.h | 4 ++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/clockdomains.h b/arch/arm/mach-omap2/clockdomains.h index e17c3693542..ec5a7209099 100644 --- a/arch/arm/mach-omap2/clockdomains.h +++ b/arch/arm/mach-omap2/clockdomains.h @@ -14,6 +14,11 @@ /* * OMAP2/3-common clockdomains + * + * Even though the 2420 has a single PRCM module from the + * interconnect's perspective, internally it does appear to have + * separate PRM and CM clockdomains. The usual test case is + * sys_clkout/sys_clkout2. */ /* This is an implicit clockdomain - it is never defined as such in TRM */ @@ -23,6 +28,18 @@ static struct clockdomain wkup_clkdm = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430), }; +static struct clockdomain prm_clkdm = { + .name = "prm_clkdm", + .pwrdm = { .name = "wkup_pwrdm" }, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430), +}; + +static struct clockdomain cm_clkdm = { + .name = "cm_clkdm", + .pwrdm = { .name = "core_pwrdm" }, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430), +}; + /* * 2420-only clockdomains */ @@ -266,6 +283,8 @@ static struct clkdm_pwrdm_autodep clkdm_pwrdm_autodeps[] = { static struct clockdomain *clockdomains_omap[] = { &wkup_clkdm, + &cm_clkdm, + &prm_clkdm, #ifdef CONFIG_ARCH_OMAP2420 &mpu_2420_clkdm, diff --git a/arch/arm/plat-omap/include/mach/powerdomain.h b/arch/arm/plat-omap/include/mach/powerdomain.h index 4948cb7af5b..69c9e675d8e 100644 --- a/arch/arm/plat-omap/include/mach/powerdomain.h +++ b/arch/arm/plat-omap/include/mach/powerdomain.h @@ -50,9 +50,9 @@ /* * Maximum number of clockdomains that can be associated with a powerdomain. - * CORE powerdomain is probably the worst case. + * CORE powerdomain on OMAP3 is the worst case */ -#define PWRDM_MAX_CLKDMS 3 +#define PWRDM_MAX_CLKDMS 4 /* XXX A completely arbitrary number. What is reasonable here? */ #define PWRDM_TRANSITION_BAILOUT 100000 -- GitLab From 15b52bc4cb2b4cc93047b957a6c7b9dbd910a6fa Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 7 May 2008 19:19:07 -0600 Subject: [PATCH 1375/4982] [ARM] OMAP3 clock: move sys_clkout2 clk to core_clkdm sys_clkout2 belongs in the core_clkdm (3430 TRM section 4.7.2.2). It's not clear whether it actually is in the CORE clockdomain, or whether it is technically in a different clockdomain; but this is closer to reality than the present configuration. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock34xx.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index 65929cc3740..baed53f6952 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -993,6 +993,7 @@ static struct clk clkout2_src_ck = { .clksel_mask = OMAP3430_CLKOUT2SOURCE_MASK, .clksel = clkout2_src_clksel, .flags = RATE_PROPAGATES, + .clkdm_name = "core_clkdm", .recalc = &omap2_clksel_recalc, }; -- GitLab From 46e0ccf8ae32e53dc34a274977e2c6256b2deddc Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 27 Jan 2009 19:44:18 -0700 Subject: [PATCH 1376/4982] [ARM] OMAP3 PRCM: add DPLL1-5 powerdomains, clockdomains; mark clocks Each DPLL exists in its own powerdomain (cf 34xx TRM figure 4-18) and clockdomain; so, create powerdomain and clockdomain structures for them. Mark each DPLL clock as belonging to their respective DPLL clockdomain. cf. 34xx TRM Table 4-27 (among other references). linux-omap source commits are acdb615850b9b4f7d1ab68133a16be8c8c0e7419 and a8798a48f33e9268dcc7f30a4b4a3ce4220fe0c9. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock34xx.h | 27 ++++++++++++++++++++ arch/arm/mach-omap2/clockdomains.h | 35 ++++++++++++++++++++++++++ arch/arm/mach-omap2/powerdomains.h | 5 ++++ arch/arm/mach-omap2/powerdomains34xx.h | 31 +++++++++++++++++++++++ 4 files changed, 98 insertions(+) diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index baed53f6952..9dec69860ba 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -280,6 +280,7 @@ static struct clk dpll1_ck = { .flags = RATE_PROPAGATES, .round_rate = &omap2_dpll_round_rate, .set_rate = &omap3_noncore_dpll_set_rate, + .clkdm_name = "dpll1_clkdm", .recalc = &omap3_dpll_recalc, }; @@ -292,6 +293,7 @@ static struct clk dpll1_x2_ck = { .ops = &clkops_null, .parent = &dpll1_ck, .flags = RATE_PROPAGATES, + .clkdm_name = "dpll1_clkdm", .recalc = &omap3_clkoutx2_recalc, }; @@ -314,6 +316,7 @@ static struct clk dpll1_x2m2_ck = { .clksel_mask = OMAP3430_MPU_DPLL_CLKOUT_DIV_MASK, .clksel = div16_dpll1_x2m2_clksel, .flags = RATE_PROPAGATES, + .clkdm_name = "dpll1_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -350,6 +353,7 @@ static struct clk dpll2_ck = { .flags = RATE_PROPAGATES, .round_rate = &omap2_dpll_round_rate, .set_rate = &omap3_noncore_dpll_set_rate, + .clkdm_name = "dpll2_clkdm", .recalc = &omap3_dpll_recalc, }; @@ -372,6 +376,7 @@ static struct clk dpll2_m2_ck = { .clksel_mask = OMAP3430_IVA2_DPLL_CLKOUT_DIV_MASK, .clksel = div16_dpll2_m2x2_clksel, .flags = RATE_PROPAGATES, + .clkdm_name = "dpll2_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -404,6 +409,7 @@ static struct clk dpll3_ck = { .dpll_data = &dpll3_dd, .flags = RATE_PROPAGATES, .round_rate = &omap2_dpll_round_rate, + .clkdm_name = "dpll3_clkdm", .recalc = &omap3_dpll_recalc, }; @@ -416,6 +422,7 @@ static struct clk dpll3_x2_ck = { .ops = &clkops_null, .parent = &dpll3_ck, .flags = RATE_PROPAGATES, + .clkdm_name = "dpll3_clkdm", .recalc = &omap3_clkoutx2_recalc, }; @@ -473,6 +480,7 @@ static struct clk dpll3_m2_ck = { .clksel_mask = OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK, .clksel = div31_dpll3m2_clksel, .flags = RATE_PROPAGATES, + .clkdm_name = "dpll3_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -507,6 +515,7 @@ static struct clk dpll3_m2x2_ck = { .clksel_mask = OMAP3430_ST_CORE_CLK_MASK, .clksel = dpll3_m2x2_ck_clksel, .flags = RATE_PROPAGATES, + .clkdm_name = "dpll3_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -526,6 +535,7 @@ static struct clk dpll3_m3_ck = { .clksel_mask = OMAP3430_DIV_DPLL3_MASK, .clksel = div16_dpll3_clksel, .flags = RATE_PROPAGATES, + .clkdm_name = "dpll3_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -537,6 +547,7 @@ static struct clk dpll3_m3x2_ck = { .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP3430_PWRDN_EMU_CORE_SHIFT, .flags = RATE_PROPAGATES | INVERT_ENABLE, + .clkdm_name = "dpll3_clkdm", .recalc = &omap3_clkoutx2_recalc, }; @@ -555,6 +566,7 @@ static struct clk emu_core_alwon_ck = { .clksel_mask = OMAP3430_ST_CORE_CLK_MASK, .clksel = emu_core_alwon_ck_clksel, .flags = RATE_PROPAGATES, + .clkdm_name = "dpll3_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -589,6 +601,7 @@ static struct clk dpll4_ck = { .flags = RATE_PROPAGATES, .round_rate = &omap2_dpll_round_rate, .set_rate = &omap3_dpll4_set_rate, + .clkdm_name = "dpll4_clkdm", .recalc = &omap3_dpll_recalc, }; @@ -602,6 +615,7 @@ static struct clk dpll4_x2_ck = { .ops = &clkops_null, .parent = &dpll4_ck, .flags = RATE_PROPAGATES, + .clkdm_name = "dpll4_clkdm", .recalc = &omap3_clkoutx2_recalc, }; @@ -620,6 +634,7 @@ static struct clk dpll4_m2_ck = { .clksel_mask = OMAP3430_DIV_96M_MASK, .clksel = div16_dpll4_clksel, .flags = RATE_PROPAGATES, + .clkdm_name = "dpll4_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -631,6 +646,7 @@ static struct clk dpll4_m2x2_ck = { .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP3430_PWRDN_96M_SHIFT, .flags = RATE_PROPAGATES | INVERT_ENABLE, + .clkdm_name = "dpll4_clkdm", .recalc = &omap3_clkoutx2_recalc, }; @@ -704,6 +720,7 @@ static struct clk dpll4_m3_ck = { .clksel_mask = OMAP3430_CLKSEL_TV_MASK, .clksel = div16_dpll4_clksel, .flags = RATE_PROPAGATES, + .clkdm_name = "dpll4_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -716,6 +733,7 @@ static struct clk dpll4_m3x2_ck = { .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP3430_PWRDN_TV_SHIFT, .flags = RATE_PROPAGATES | INVERT_ENABLE, + .clkdm_name = "dpll4_clkdm", .recalc = &omap3_clkoutx2_recalc, }; @@ -810,6 +828,7 @@ static struct clk dpll4_m4_ck = { .clksel_mask = OMAP3430_CLKSEL_DSS1_MASK, .clksel = div16_dpll4_clksel, .flags = RATE_PROPAGATES, + .clkdm_name = "dpll4_clkdm", .recalc = &omap2_clksel_recalc, .set_rate = &omap2_clksel_set_rate, .round_rate = &omap2_clksel_round_rate, @@ -823,6 +842,7 @@ static struct clk dpll4_m4x2_ck = { .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP3430_PWRDN_CAM_SHIFT, .flags = RATE_PROPAGATES | INVERT_ENABLE, + .clkdm_name = "dpll4_clkdm", .recalc = &omap3_clkoutx2_recalc, }; @@ -836,6 +856,7 @@ static struct clk dpll4_m5_ck = { .clksel_mask = OMAP3430_CLKSEL_CAM_MASK, .clksel = div16_dpll4_clksel, .flags = RATE_PROPAGATES, + .clkdm_name = "dpll4_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -847,6 +868,7 @@ static struct clk dpll4_m5x2_ck = { .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP3430_PWRDN_CAM_SHIFT, .flags = RATE_PROPAGATES | INVERT_ENABLE, + .clkdm_name = "dpll4_clkdm", .recalc = &omap3_clkoutx2_recalc, }; @@ -860,6 +882,7 @@ static struct clk dpll4_m6_ck = { .clksel_mask = OMAP3430_DIV_DPLL4_MASK, .clksel = div16_dpll4_clksel, .flags = RATE_PROPAGATES, + .clkdm_name = "dpll4_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -872,6 +895,7 @@ static struct clk dpll4_m6x2_ck = { .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP3430_PWRDN_EMU_PERIPH_SHIFT, .flags = RATE_PROPAGATES | INVERT_ENABLE, + .clkdm_name = "dpll4_clkdm", .recalc = &omap3_clkoutx2_recalc, }; @@ -880,6 +904,7 @@ static struct clk emu_per_alwon_ck = { .ops = &clkops_null, .parent = &dpll4_m6x2_ck, .flags = RATE_PROPAGATES, + .clkdm_name = "dpll4_clkdm", .recalc = &followparent_recalc, }; @@ -915,6 +940,7 @@ static struct clk dpll5_ck = { .flags = RATE_PROPAGATES, .round_rate = &omap2_dpll_round_rate, .set_rate = &omap3_noncore_dpll_set_rate, + .clkdm_name = "dpll5_clkdm", .recalc = &omap3_dpll_recalc, }; @@ -932,6 +958,7 @@ static struct clk dpll5_m2_ck = { .clksel_mask = OMAP3430ES2_DIV_120M_MASK, .clksel = div16_dpll5_clksel, .flags = RATE_PROPAGATES, + .clkdm_name = "dpll5_clkdm", .recalc = &omap2_clksel_recalc, }; diff --git a/arch/arm/mach-omap2/clockdomains.h b/arch/arm/mach-omap2/clockdomains.h index ec5a7209099..9eb73432810 100644 --- a/arch/arm/mach-omap2/clockdomains.h +++ b/arch/arm/mach-omap2/clockdomains.h @@ -256,6 +256,36 @@ static struct clockdomain emu_clkdm = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), }; +static struct clockdomain dpll1_clkdm = { + .name = "dpll1_clkdm", + .pwrdm = { .name = "dpll1_pwrdm" }, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +}; + +static struct clockdomain dpll2_clkdm = { + .name = "dpll2_clkdm", + .pwrdm = { .name = "dpll2_pwrdm" }, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +}; + +static struct clockdomain dpll3_clkdm = { + .name = "dpll3_clkdm", + .pwrdm = { .name = "dpll3_pwrdm" }, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +}; + +static struct clockdomain dpll4_clkdm = { + .name = "dpll4_clkdm", + .pwrdm = { .name = "dpll4_pwrdm" }, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +}; + +static struct clockdomain dpll5_clkdm = { + .name = "dpll5_clkdm", + .pwrdm = { .name = "dpll5_pwrdm" }, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2), +}; + #endif /* CONFIG_ARCH_OMAP34XX */ /* @@ -318,6 +348,11 @@ static struct clockdomain *clockdomains_omap[] = { &usbhost_clkdm, &per_clkdm, &emu_clkdm, + &dpll1_clkdm, + &dpll2_clkdm, + &dpll3_clkdm, + &dpll4_clkdm, + &dpll5_clkdm, #endif NULL, diff --git a/arch/arm/mach-omap2/powerdomains.h b/arch/arm/mach-omap2/powerdomains.h index 1e151faebbd..1329443f2cd 100644 --- a/arch/arm/mach-omap2/powerdomains.h +++ b/arch/arm/mach-omap2/powerdomains.h @@ -178,6 +178,11 @@ static struct powerdomain *powerdomains_omap[] __initdata = { &emu_pwrdm, &sgx_pwrdm, &usbhost_pwrdm, + &dpll1_pwrdm, + &dpll2_pwrdm, + &dpll3_pwrdm, + &dpll4_pwrdm, + &dpll5_pwrdm, #endif NULL diff --git a/arch/arm/mach-omap2/powerdomains34xx.h b/arch/arm/mach-omap2/powerdomains34xx.h index 3a8e4fbea5f..7b63fa074b7 100644 --- a/arch/arm/mach-omap2/powerdomains34xx.h +++ b/arch/arm/mach-omap2/powerdomains34xx.h @@ -322,6 +322,37 @@ static struct powerdomain usbhost_pwrdm = { }, }; +static struct powerdomain dpll1_pwrdm = { + .name = "dpll1_pwrdm", + .prcm_offs = MPU_MOD, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +}; + +static struct powerdomain dpll2_pwrdm = { + .name = "dpll2_pwrdm", + .prcm_offs = OMAP3430_IVA2_MOD, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +}; + +static struct powerdomain dpll3_pwrdm = { + .name = "dpll3_pwrdm", + .prcm_offs = PLL_MOD, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +}; + +static struct powerdomain dpll4_pwrdm = { + .name = "dpll4_pwrdm", + .prcm_offs = PLL_MOD, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +}; + +static struct powerdomain dpll5_pwrdm = { + .name = "dpll5_pwrdm", + .prcm_offs = PLL_MOD, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2), +}; + + #endif /* CONFIG_ARCH_OMAP34XX */ -- GitLab From be48ea74d49408c5c4f999c730d35eaf0034f273 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 27 Jan 2009 19:44:28 -0700 Subject: [PATCH 1377/4982] [ARM] OMAP3 powerdomains: remove RET from SGX power states list The SGX device on OMAP3 does not support retention, so remove RET from the list of possible SGX power states. Problem debugged by Richard Woodruff . Signed-off-by: Richard Woodruff Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/powerdomains34xx.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/powerdomains34xx.h b/arch/arm/mach-omap2/powerdomains34xx.h index 7b63fa074b7..15c346c627d 100644 --- a/arch/arm/mach-omap2/powerdomains34xx.h +++ b/arch/arm/mach-omap2/powerdomains34xx.h @@ -236,6 +236,11 @@ static struct powerdomain dss_pwrdm = { }, }; +/* + * Although the 34XX TRM Rev K Table 4-371 notes that retention is a + * possible SGX powerstate, the SGX device itself does not support + * retention. + */ static struct powerdomain sgx_pwrdm = { .name = "sgx_pwrdm", .prcm_offs = OMAP3430ES2_SGX_MOD, @@ -243,7 +248,7 @@ static struct powerdomain sgx_pwrdm = { .wkdep_srcs = gfx_sgx_wkdeps, .sleepdep_srcs = cam_gfx_sleepdeps, /* XXX This is accurate for 3430 SGX, but what about GFX? */ - .pwrsts = PWRSTS_OFF_RET_ON, + .pwrsts = PWRSTS_OFF_ON, .pwrsts_logic_ret = PWRDM_POWER_RET, .banks = 1, .pwrsts_mem_ret = { -- GitLab From 054ce503ae335dbc8610ef5aa0852c0c090023fe Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 27 Jan 2009 19:44:31 -0700 Subject: [PATCH 1378/4982] [ARM] OMAP: wait for pwrdm transition after clk_enable() Enabling clock in a disabled power domain causes the power domain to be turned on. However, the power transition is not always finished when clk_enable() returns and this randomly crashes the kernel when an interrupt happens right after the clk_enable, and the kernel tries to read the irq status register for that domain. Why the irq status register is inaccessible, I don't know. Also it doesn't seem to be related to the module being not powered up, but to the transition itself. The same could perhaps happen after clk_disable also, but I have not witnessed that. The problem affects at least dss, cam and sgx clocks. This change waits for the transition to be finished before returning from omap2_clkdm_clk_enable(). Signed-off-by: Tomi Valkeinen Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clockdomain.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index e9b4f6c564e..c9c367c3967 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -568,6 +568,8 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) else omap2_clkdm_wakeup(clkdm); + pwrdm_wait_transition(clkdm->pwrdm.ptr); + return 0; } -- GitLab From d96df00d6dfd2482fb23ef7aabcaa36e6dce4d1c Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 27 Jan 2009 19:44:35 -0700 Subject: [PATCH 1379/4982] [ARM] OMAP2/3 clockdomains: autodeps should respect platform flags Fix the clockdomain autodep code to respect omap_chip platform flags. Resolves "Unable to handle kernel paging request at virtual address 5f75706d" panic during power management initialization on OMAP2. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clockdomain.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index c9c367c3967..ae0c53abb55 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -100,6 +100,9 @@ static void _clkdm_add_autodeps(struct clockdomain *clkdm) if (IS_ERR(autodep->pwrdm.ptr)) continue; + if (!omap_chip_is(autodep->omap_chip)) + continue; + pr_debug("clockdomain: adding %s sleepdep/wkdep for " "pwrdm %s\n", autodep->pwrdm.ptr->name, clkdm->pwrdm.ptr->name); @@ -125,6 +128,9 @@ static void _clkdm_del_autodeps(struct clockdomain *clkdm) if (IS_ERR(autodep->pwrdm.ptr)) continue; + if (!omap_chip_is(autodep->omap_chip)) + continue; + pr_debug("clockdomain: removing %s sleepdep/wkdep for " "pwrdm %s\n", autodep->pwrdm.ptr->name, clkdm->pwrdm.ptr->name); -- GitLab From f266950d0234599cc6d4a5602e43d0fb782de1d2 Mon Sep 17 00:00:00 2001 From: Jouni Hogander Date: Tue, 27 Jan 2009 19:44:38 -0700 Subject: [PATCH 1380/4982] [ARM] OMAP3: PM: Emu_pwrdm is switched off by hardware even when sdti is in use Using sdti doesn't keep emu_pwrdm on if hardware supervised pwrdm transitions are used. This causes sdti stop to work when power management is initialized and hardware supervised pwrdm control is enabled. This patch disables hardware supervised pwrdm control for emu_pwrdm. Now emu_pwrdm is switched off on boot by software when it is not used. Signed-off-by: Jouni Hogander Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clockdomains.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/clockdomains.h b/arch/arm/mach-omap2/clockdomains.h index 9eb73432810..d7db796403d 100644 --- a/arch/arm/mach-omap2/clockdomains.h +++ b/arch/arm/mach-omap2/clockdomains.h @@ -248,10 +248,14 @@ static struct clockdomain per_clkdm = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), }; +/* + * Disable hw supervised mode for emu_clkdm, because emu_pwrdm is + * switched of even if sdti is in use + */ static struct clockdomain emu_clkdm = { .name = "emu_clkdm", .pwrdm = { .name = "emu_pwrdm" }, - .flags = CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_SWSUP, + .flags = /* CLKDM_CAN_ENABLE_AUTO | */CLKDM_CAN_SWSUP, .clktrctrl_mask = OMAP3430_CLKTRCTRL_EMU_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), }; -- GitLab From f0587b63c24e0c7539c6e77f1bfc68e6053608c7 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 28 Jan 2009 12:08:11 -0700 Subject: [PATCH 1381/4982] [ARM] OMAP3 clock: fix DPLL jitter correction and rate programming Fix DPLL jitter correction programming. Previously, omap3_noncore_dpll_program() stored the FREQSEL jitter correction parameter to the wrong register. This caused jitter correction to be set incorrectly and also caused the DPLL divider to be programmed incorrectly. Also, fix DPLL divider programming. An off-by-one error existed in omap3_noncore_dpll_program(), causing DPLLs to be programmed with a higher divider than intended. linux-omap source commit is 5c0ec88a2145cdf2f2c9cc5fae49635c4c2476c7. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock34xx.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index cb5e068feb5..fdfc7d58291 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -563,14 +563,17 @@ static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel) /* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */ _omap3_noncore_dpll_bypass(clk); + /* Set jitter correction */ + v = __raw_readl(dd->control_reg); + v &= ~dd->freqsel_mask; + v |= freqsel << __ffs(dd->freqsel_mask); + __raw_writel(v, dd->control_reg); + + /* Set DPLL multiplier, divider */ v = __raw_readl(dd->mult_div1_reg); v &= ~(dd->mult_mask | dd->div1_mask); - - /* Set mult (M), div1 (N), freqsel */ v |= m << __ffs(dd->mult_mask); - v |= n << __ffs(dd->div1_mask); - v |= freqsel << __ffs(dd->freqsel_mask); - + v |= (n - 1) << __ffs(dd->div1_mask); __raw_writel(v, dd->mult_div1_reg); /* We let the clock framework set the other output dividers later */ -- GitLab From b8168d1e3989bc141da6bba87ad49e218ff04658 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 28 Jan 2009 12:08:14 -0700 Subject: [PATCH 1382/4982] [ARM] OMAP3 clock: DPLL{1,2}_FCLK clksel can divide by 4 OMAP34xx ES2 TRM Delta G to H states that the divider for DPLL1_FCLK and DPLL2_FCLK can divide by 4 in addition to dividing by 1 and 2. Encode this into the OMAP3 clock framework. linux-omap source commit is 050684c18f2ea0b08fdd5233a0cd3c7f96e00a0e. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock34xx.h | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index 9dec69860ba..f8088c0ec01 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -1060,8 +1060,15 @@ static struct clk corex2_fck = { /* DPLL power domain clock controls */ -static const struct clksel div2_core_clksel[] = { - { .parent = &core_ck, .rates = div2_rates }, +static const struct clksel_rate div4_rates[] = { + { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE }, + { .div = 2, .val = 2, .flags = RATE_IN_343X }, + { .div = 4, .val = 4, .flags = RATE_IN_343X }, + { .div = 0 } +}; + +static const struct clksel div4_core_clksel[] = { + { .parent = &core_ck, .rates = div4_rates }, { .parent = NULL } }; @@ -1076,7 +1083,7 @@ static struct clk dpll1_fck = { .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL), .clksel_mask = OMAP3430_MPU_CLK_SRC_MASK, - .clksel = div2_core_clksel, + .clksel = div4_core_clksel, .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -1151,7 +1158,7 @@ static struct clk dpll2_fck = { .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL), .clksel_mask = OMAP3430_IVA2_CLK_SRC_MASK, - .clksel = div2_core_clksel, + .clksel = div4_core_clksel, .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -1187,6 +1194,11 @@ static struct clk iva2_ck = { /* Common interface clocks */ +static const struct clksel div2_core_clksel[] = { + { .parent = &core_ck, .rates = div2_rates }, + { .parent = NULL } +}; + static struct clk l3_ick = { .name = "l3_ick", .ops = &clkops_null, -- GitLab From c1bd7aaf678a7e35086520e284d5b44bc69b6599 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 28 Jan 2009 12:08:17 -0700 Subject: [PATCH 1383/4982] [ARM] OMAP3 clock: convert dpll_data.idlest_bit to idlest_mask Convert struct dpll_data.idlest_bit field to idlest_mask. Needed since OMAP2 uses two bits for DPLL IDLEST rather than one. While here, add the missing idlest_* fields for DPLL3. linux-omap source commits are 25bab0f176b0a97be18a1b38153f266c3a155784 and b0f7fd17db2aaf8e6e9a2732ae3f4de0874db01c. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock34xx.c | 6 ++---- arch/arm/mach-omap2/clock34xx.h | 10 ++++++---- arch/arm/plat-omap/include/mach/clock.h | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index fdfc7d58291..aad77e0d43c 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -314,14 +314,12 @@ static int _omap3_wait_dpll_status(struct clk *clk, u8 state) const struct dpll_data *dd; int i = 0; int ret = -EINVAL; - u32 idlest_mask; dd = clk->dpll_data; - state <<= dd->idlest_bit; - idlest_mask = 1 << dd->idlest_bit; + state <<= __ffs(dd->idlest_mask); - while (((__raw_readl(dd->idlest_reg) & idlest_mask) != state) && + while (((__raw_readl(dd->idlest_reg) & dd->idlest_mask) != state) && i < MAX_DPLL_WAIT_TRIES) { i++; udelay(1); diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index f8088c0ec01..7ee13120262 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -266,7 +266,7 @@ static struct dpll_data dpll1_dd = { .autoidle_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_AUTOIDLE_PLL), .autoidle_mask = OMAP3430_AUTO_MPU_DPLL_MASK, .idlest_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), - .idlest_bit = OMAP3430_ST_MPU_CLK_SHIFT, + .idlest_mask = OMAP3430_ST_MPU_CLK_MASK, .max_multiplier = OMAP3_MAX_DPLL_MULT, .max_divider = OMAP3_MAX_DPLL_DIV, .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE @@ -339,7 +339,7 @@ static struct dpll_data dpll2_dd = { .autoidle_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_AUTOIDLE_PLL), .autoidle_mask = OMAP3430_AUTO_IVA2_DPLL_MASK, .idlest_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_IDLEST_PLL), - .idlest_bit = OMAP3430_ST_IVA2_CLK_SHIFT, + .idlest_mask = OMAP3430_ST_IVA2_CLK_MASK, .max_multiplier = OMAP3_MAX_DPLL_MULT, .max_divider = OMAP3_MAX_DPLL_DIV, .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE @@ -397,6 +397,8 @@ static struct dpll_data dpll3_dd = { .recal_st_bit = OMAP3430_CORE_DPLL_ST_SHIFT, .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE), .autoidle_mask = OMAP3430_AUTO_CORE_DPLL_MASK, + .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), + .idlest_mask = OMAP3430_ST_CORE_CLK_MASK, .max_multiplier = OMAP3_MAX_DPLL_MULT, .max_divider = OMAP3_MAX_DPLL_DIV, .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE @@ -587,7 +589,7 @@ static struct dpll_data dpll4_dd = { .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE), .autoidle_mask = OMAP3430_AUTO_PERIPH_DPLL_MASK, .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), - .idlest_bit = OMAP3430_ST_PERIPH_CLK_SHIFT, + .idlest_mask = OMAP3430_ST_PERIPH_CLK_MASK, .max_multiplier = OMAP3_MAX_DPLL_MULT, .max_divider = OMAP3_MAX_DPLL_DIV, .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE @@ -926,7 +928,7 @@ static struct dpll_data dpll5_dd = { .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_AUTOIDLE2_PLL), .autoidle_mask = OMAP3430ES2_AUTO_PERIPH2_DPLL_MASK, .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2), - .idlest_bit = OMAP3430ES2_ST_PERIPH2_CLK_SHIFT, + .idlest_mask = OMAP3430ES2_ST_PERIPH2_CLK_MASK, .max_multiplier = OMAP3_MAX_DPLL_MULT, .max_divider = OMAP3_MAX_DPLL_DIV, .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index 681c65105e2..611df52a324 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -54,10 +54,10 @@ struct dpll_data { u32 enable_mask; u32 autoidle_mask; u32 freqsel_mask; + u32 idlest_mask; u8 auto_recal_bit; u8 recal_en_bit; u8 recal_st_bit; - u8 idlest_bit; # endif }; -- GitLab From b32450409847dddf060a468707212d3493df4f63 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 28 Jan 2009 12:08:38 -0700 Subject: [PATCH 1384/4982] [ARM] OMAP3 clock: remove unnecessary dpll_data dereferences Remove some clutter from omap2_dpll_round_rate(). linux-omap source commit is 4625dceb8583c02a6d67ededc9f6a8347b6b8cb7. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 886f73f3933..2f0eaaad481 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -877,19 +877,22 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate) int m, n, r, e, scaled_max_m; unsigned long scaled_rt_rp, new_rate; int min_e = -1, min_e_m = -1, min_e_n = -1; + struct dpll_data *dd; if (!clk || !clk->dpll_data) return ~0; + dd = clk->dpll_data; + pr_debug("clock: starting DPLL round_rate for clock %s, target rate " "%ld\n", clk->name, target_rate); scaled_rt_rp = target_rate / (clk->parent->rate / DPLL_SCALE_FACTOR); - scaled_max_m = clk->dpll_data->max_multiplier * DPLL_SCALE_FACTOR; + scaled_max_m = dd->max_multiplier * DPLL_SCALE_FACTOR; - clk->dpll_data->last_rounded_rate = 0; + dd->last_rounded_rate = 0; - for (n = clk->dpll_data->max_divider; n >= DPLL_MIN_DIVIDER; n--) { + for (n = dd->max_divider; n >= DPLL_MIN_DIVIDER; n--) { /* Compute the scaled DPLL multiplier, based on the divider */ m = scaled_rt_rp * n; @@ -909,7 +912,7 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate) "(new_rate = %ld)\n", n, m, e, new_rate); if (min_e == -1 || - min_e >= (int)(abs(e) - clk->dpll_data->rate_tolerance)) { + min_e >= (int)(abs(e) - dd->rate_tolerance)) { min_e = e; min_e_m = m; min_e_n = n; @@ -932,17 +935,17 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate) return ~0; } - clk->dpll_data->last_rounded_m = min_e_m; - clk->dpll_data->last_rounded_n = min_e_n; - clk->dpll_data->last_rounded_rate = - _dpll_compute_new_rate(clk->parent->rate, min_e_m, min_e_n); + dd->last_rounded_m = min_e_m; + dd->last_rounded_n = min_e_n; + dd->last_rounded_rate = _dpll_compute_new_rate(clk->parent->rate, + min_e_m, min_e_n); pr_debug("clock: final least error: e = %d, m = %d, n = %d\n", min_e, min_e_m, min_e_n); pr_debug("clock: final rate: %ld (target rate: %ld)\n", - clk->dpll_data->last_rounded_rate, target_rate); + dd->last_rounded_rate, target_rate); - return clk->dpll_data->last_rounded_rate; + return dd->last_rounded_rate; } /*------------------------------------------------------------------------- -- GitLab From 85a5f78d2b15a2e73b6486a24b77bb3ab67d5bbc Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 28 Jan 2009 12:08:41 -0700 Subject: [PATCH 1385/4982] [ARM] OMAP3 clock: optimize DPLL rate rounding algorithm The previous DPLL rate rounding algorithm counted the divider (N) down from the maximum to 1. Since we currently use a broad DPLL rate tolerance, and lower N values are more power-efficient, we can often bypass several iterations through the loop by counting N upwards from 1. Peter de Schrijver put up with several test cycles of this patch - thanks Peter. linux-omap source commit is 6f6d82bb2f80fa20a841ac3e95a6f44a5a156188. Signed-off-by: Paul Walmsley Cc: Peter de Schrijver Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 2f0eaaad481..76e20bcc4e8 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -45,7 +45,7 @@ #define DPLL_MIN_DIVIDER 1 /* Possible error results from _dpll_test_mult */ -#define DPLL_MULT_UNDERFLOW (1 << 0) +#define DPLL_MULT_UNDERFLOW -1 /* * Scale factor to mitigate roundoff errors in DPLL rate rounding. @@ -826,7 +826,7 @@ static int _dpll_test_mult(int *m, int n, unsigned long *new_rate, unsigned long target_rate, unsigned long parent_rate) { - int flags = 0, carry = 0; + int r = 0, carry = 0; /* Unscale m and round if necessary */ if (*m % DPLL_SCALE_FACTOR >= DPLL_ROUNDING_VAL) @@ -847,13 +847,13 @@ static int _dpll_test_mult(int *m, int n, unsigned long *new_rate, if (*m < DPLL_MIN_MULTIPLIER) { *m = DPLL_MIN_MULTIPLIER; *new_rate = 0; - flags = DPLL_MULT_UNDERFLOW; + r = DPLL_MULT_UNDERFLOW; } if (*new_rate == 0) *new_rate = _dpll_compute_new_rate(parent_rate, *m, n); - return flags; + return r; } /** @@ -892,21 +892,27 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate) dd->last_rounded_rate = 0; - for (n = dd->max_divider; n >= DPLL_MIN_DIVIDER; n--) { + for (n = DPLL_MIN_DIVIDER; n <= dd->max_divider; n++) { /* Compute the scaled DPLL multiplier, based on the divider */ m = scaled_rt_rp * n; /* - * Since we're counting n down, a m overflow means we can - * can immediately skip to the next n + * Since we're counting n up, a m overflow means we + * can bail out completely (since as n increases in + * the next iteration, there's no way that m can + * increase beyond the current m) */ if (m > scaled_max_m) - continue; + break; r = _dpll_test_mult(&m, n, &new_rate, target_rate, clk->parent->rate); + /* m can't be set low enough for this n - try with a larger n */ + if (r == DPLL_MULT_UNDERFLOW) + continue; + e = target_rate - new_rate; pr_debug("clock: n = %d: m = %d: rate error is %d " "(new_rate = %ld)\n", n, m, e, new_rate); @@ -918,16 +924,11 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate) min_e_n = n; pr_debug("clock: found new least error %d\n", min_e); - } - /* - * Since we're counting n down, a m underflow means we - * can bail out completely (since as n decreases in - * the next iteration, there's no way that m can - * increase beyond the current m) - */ - if (r & DPLL_MULT_UNDERFLOW) - break; + /* We found good settings -- bail out now */ + if (min_e <= clk->dpll_data->rate_tolerance) + break; + } } if (min_e < 0) { -- GitLab From 95f538ac370d9625457ba00ef7c3bb91e2b92f89 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 28 Jan 2009 12:08:44 -0700 Subject: [PATCH 1386/4982] [ARM] OMAP3 clock: avoid invalid FREQSEL values during DPLL rate rounding The DPLL FREQSEL jitter correction bits are set based on a table in the 34xx TRM, Table 4-38, according to the DPLL's internal clock frequency "Fint." Several Fint frequency ranges are missing from this table. Previously, we allowed these Fint frequency ranges to be selected in the rate rounding code, but did not change the FREQSEL bits. Correspondence with the OMAP hardware team indicates that Fint values not in the table should not be used. So, prevent them from being selected during DPLL rate rounding. This removes warnings and also can prevent the chip from locking up. The first pass through the rate rounding code will update the DPLL max and min dividers appropriately, so later rate rounding passes will run faster than the first. Peter de Schrijver put up with several test cycles of this patch - thanks Peter. linux-omap source commit is f9c1b82f55b60fc39eaa6e7aa1fbe380c0ffe2e9. Signed-off-by: Paul Walmsley Cc: Peter de Schrijver Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock.c | 67 ++++++++++++++++++++++++- arch/arm/mach-omap2/clock24xx.h | 1 + arch/arm/mach-omap2/clock34xx.h | 5 ++ arch/arm/plat-omap/include/mach/clock.h | 1 + 4 files changed, 72 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 76e20bcc4e8..752e34787f2 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -58,12 +58,68 @@ #define DPLL_ROUNDING_VAL ((DPLL_SCALE_BASE / 2) * \ (DPLL_SCALE_FACTOR / DPLL_SCALE_BASE)) +/* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */ +#define DPLL_FINT_BAND1_MIN 750000 +#define DPLL_FINT_BAND1_MAX 2100000 +#define DPLL_FINT_BAND2_MIN 7500000 +#define DPLL_FINT_BAND2_MAX 21000000 + +/* _dpll_test_fint() return codes */ +#define DPLL_FINT_UNDERFLOW -1 +#define DPLL_FINT_INVALID -2 + u8 cpu_mask; /*------------------------------------------------------------------------- * OMAP2/3 specific clock functions *-------------------------------------------------------------------------*/ +/* + * _dpll_test_fint - test whether an Fint value is valid for the DPLL + * @clk: DPLL struct clk to test + * @n: divider value (N) to test + * + * Tests whether a particular divider @n will result in a valid DPLL + * internal clock frequency Fint. See the 34xx TRM 4.7.6.2 "DPLL Jitter + * Correction". Returns 0 if OK, -1 if the enclosing loop can terminate + * (assuming that it is counting N upwards), or -2 if the enclosing loop + * should skip to the next iteration (again assuming N is increasing). + */ +static int _dpll_test_fint(struct clk *clk, u8 n) +{ + struct dpll_data *dd; + long fint; + int ret = 0; + + dd = clk->dpll_data; + + /* DPLL divider must result in a valid jitter correction val */ + fint = clk->parent->rate / (n + 1); + if (fint < DPLL_FINT_BAND1_MIN) { + + pr_debug("rejecting n=%d due to Fint failure, " + "lowering max_divider\n", n); + dd->max_divider = n; + ret = DPLL_FINT_UNDERFLOW; + + } else if (fint > DPLL_FINT_BAND1_MAX && + fint < DPLL_FINT_BAND2_MIN) { + + pr_debug("rejecting n=%d due to Fint failure\n", n); + ret = DPLL_FINT_INVALID; + + } else if (fint > DPLL_FINT_BAND2_MAX) { + + pr_debug("rejecting n=%d due to Fint failure, " + "boosting min_divider\n", n); + dd->min_divider = n; + ret = DPLL_FINT_INVALID; + + } + + return ret; +} + /** * omap2_init_clk_clkdm - look up a clockdomain name, store pointer in clk * @clk: OMAP clock struct ptr to use @@ -892,7 +948,14 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate) dd->last_rounded_rate = 0; - for (n = DPLL_MIN_DIVIDER; n <= dd->max_divider; n++) { + for (n = dd->min_divider; n <= dd->max_divider; n++) { + + /* Is the (input clk, divider) pair valid for the DPLL? */ + r = _dpll_test_fint(clk, n); + if (r == DPLL_FINT_UNDERFLOW) + break; + else if (r == DPLL_FINT_INVALID) + continue; /* Compute the scaled DPLL multiplier, based on the divider */ m = scaled_rt_rp * n; @@ -926,7 +989,7 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate) pr_debug("clock: found new least error %d\n", min_e); /* We found good settings -- bail out now */ - if (min_e <= clk->dpll_data->rate_tolerance) + if (min_e <= dd->rate_tolerance) break; } } diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h index 32dd8573e56..7731ab6acd1 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock24xx.h @@ -666,6 +666,7 @@ static struct dpll_data dpll_dd = { .mult_mask = OMAP24XX_DPLL_MULT_MASK, .div1_mask = OMAP24XX_DPLL_DIV_MASK, .max_multiplier = 1024, + .min_divider = 1, .max_divider = 16, .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE }; diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index 7ee13120262..aadd296c05a 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -268,6 +268,7 @@ static struct dpll_data dpll1_dd = { .idlest_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), .idlest_mask = OMAP3430_ST_MPU_CLK_MASK, .max_multiplier = OMAP3_MAX_DPLL_MULT, + .min_divider = 1, .max_divider = OMAP3_MAX_DPLL_DIV, .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE }; @@ -341,6 +342,7 @@ static struct dpll_data dpll2_dd = { .idlest_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_IDLEST_PLL), .idlest_mask = OMAP3430_ST_IVA2_CLK_MASK, .max_multiplier = OMAP3_MAX_DPLL_MULT, + .min_divider = 1, .max_divider = OMAP3_MAX_DPLL_DIV, .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE }; @@ -400,6 +402,7 @@ static struct dpll_data dpll3_dd = { .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), .idlest_mask = OMAP3430_ST_CORE_CLK_MASK, .max_multiplier = OMAP3_MAX_DPLL_MULT, + .min_divider = 1, .max_divider = OMAP3_MAX_DPLL_DIV, .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE }; @@ -591,6 +594,7 @@ static struct dpll_data dpll4_dd = { .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), .idlest_mask = OMAP3430_ST_PERIPH_CLK_MASK, .max_multiplier = OMAP3_MAX_DPLL_MULT, + .min_divider = 1, .max_divider = OMAP3_MAX_DPLL_DIV, .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE }; @@ -930,6 +934,7 @@ static struct dpll_data dpll5_dd = { .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2), .idlest_mask = OMAP3430ES2_ST_PERIPH2_CLK_MASK, .max_multiplier = OMAP3_MAX_DPLL_MULT, + .min_divider = 1, .max_divider = OMAP3_MAX_DPLL_DIV, .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE }; diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index 611df52a324..cd69111cd33 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -43,6 +43,7 @@ struct dpll_data { unsigned long last_rounded_rate; u16 last_rounded_m; u8 last_rounded_n; + u8 min_divider; u8 max_divider; u32 max_tolerance; u16 max_multiplier; -- GitLab From 416db864c18343c6dcc5e9768c902460c8f8777c Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 28 Jan 2009 12:08:46 -0700 Subject: [PATCH 1387/4982] [ARM] OMAP3 clock: disable DPLL autoidle while waiting for DPLL to lock During _omap3_noncore_dpll_lock(), if a DPLL has no active downstream clocks and DPLL autoidle is enabled, the DPLL may never lock, since it will enter autoidle immediately. To resolve this, disable DPLL autoidle while locking the DPLL, and unconditionally wait for the DPLL to lock. This fixes some bugs where the kernel would hang when returning from retention or return the wrong rate for the DPLL. This patch is a collaboration with Peter de Schrijver and Kevin Hilman . linux-omap source commit is 3b7de4be879f1f4f55ae59882a5cbd80f6dcf0f0. Signed-off-by: Paul Walmsley Cc: Peter de Schrijver Cc: Kevin Hilman Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock34xx.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index aad77e0d43c..3d756babb2f 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -398,19 +398,14 @@ static int _omap3_noncore_dpll_lock(struct clk *clk) ai = omap3_dpll_autoidle_read(clk); + omap3_dpll_deny_idle(clk); + _omap3_dpll_write_clken(clk, DPLL_LOCKED); - if (ai) { - /* - * If no downstream clocks are enabled, CM_IDLEST bit - * may never become active, so don't wait for DPLL to lock. - */ - r = 0; + r = _omap3_wait_dpll_status(clk, 1); + + if (ai) omap3_dpll_allow_idle(clk); - } else { - r = _omap3_wait_dpll_status(clk, 1); - omap3_dpll_deny_idle(clk); - }; return r; } -- GitLab From ee1eec36345871955730e36232937c9d814a6e20 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 28 Jan 2009 12:18:19 -0700 Subject: [PATCH 1388/4982] [ARM] OMAP2/3 clock: clean up mach-omap2/clock.c This patch rolls up several cleanup patches. 1. Some unnecessarily verbose variable names are used in several clock.c functions; clean these up per CodingStyle. 2. Remove omap2_get_clksel() and just use clk->clksel_reg and clk->clksel_mask directly. 3. Get rid of void __iomem * usage in omap2_clksel_get_src_field. Prepend the function name with an underscore to highlight that it is a static function. linux-omap source commits are 7fa95e007ea2f3c4d0ecd2779d809756e7775894, af0ea23f1ee4a5bea3b026e38761b47089f9048a, and 91c0c979b47c44b08f80e4f8d4c990fb158d82c4. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock.c | 98 +++++++++++++------------------------ 1 file changed, 35 insertions(+), 63 deletions(-) diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 752e34787f2..5d7d4c52f37 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -298,7 +298,7 @@ static void omap2_clk_wait_ready(struct clk *clk) static int omap2_dflt_clk_enable(struct clk *clk) { - u32 regval32; + u32 v; if (unlikely(clk->enable_reg == NULL)) { printk(KERN_ERR "clock.c: Enable for %s without enable code\n", @@ -306,12 +306,12 @@ static int omap2_dflt_clk_enable(struct clk *clk) return 0; /* REVISIT: -EINVAL */ } - regval32 = __raw_readl(clk->enable_reg); + v = __raw_readl(clk->enable_reg); if (clk->flags & INVERT_ENABLE) - regval32 &= ~(1 << clk->enable_bit); + v &= ~(1 << clk->enable_bit); else - regval32 |= (1 << clk->enable_bit); - __raw_writel(regval32, clk->enable_reg); + v |= (1 << clk->enable_bit); + __raw_writel(v, clk->enable_reg); wmb(); return 0; @@ -335,7 +335,7 @@ static int omap2_dflt_clk_enable_wait(struct clk *clk) static void omap2_dflt_clk_disable(struct clk *clk) { - u32 regval32; + u32 v; if (!clk->enable_reg) { /* @@ -347,12 +347,12 @@ static void omap2_dflt_clk_disable(struct clk *clk) return; } - regval32 = __raw_readl(clk->enable_reg); + v = __raw_readl(clk->enable_reg); if (clk->flags & INVERT_ENABLE) - regval32 |= (1 << clk->enable_bit); + v |= (1 << clk->enable_bit); else - regval32 &= ~(1 << clk->enable_bit); - __raw_writel(regval32, clk->enable_reg); + v &= ~(1 << clk->enable_bit); + __raw_writel(v, clk->enable_reg); wmb(); } @@ -643,23 +643,6 @@ u32 omap2_divisor_to_clksel(struct clk *clk, u32 div) return clkr->val; } -/** - * omap2_get_clksel - find clksel register addr & field mask for a clk - * @clk: struct clk to use - * @field_mask: ptr to u32 to store the register field mask - * - * Returns the address of the clksel register upon success or NULL on error. - */ -static void __iomem *omap2_get_clksel(struct clk *clk, u32 *field_mask) -{ - if (!clk->clksel_reg || (clk->clksel_mask == 0)) - return NULL; - - *field_mask = clk->clksel_mask; - - return clk->clksel_reg; -} - /** * omap2_clksel_get_divisor - get current divider applied to parent clock. * @clk: OMAP struct clk to use. @@ -668,40 +651,36 @@ static void __iomem *omap2_get_clksel(struct clk *clk, u32 *field_mask) */ u32 omap2_clksel_get_divisor(struct clk *clk) { - u32 field_mask, field_val; - void __iomem *div_addr; + u32 v; - div_addr = omap2_get_clksel(clk, &field_mask); - if (!div_addr) + if (!clk->clksel_mask) return 0; - field_val = __raw_readl(div_addr) & field_mask; - field_val >>= __ffs(field_mask); + v = __raw_readl(clk->clksel_reg) & clk->clksel_mask; + v >>= __ffs(clk->clksel_mask); - return omap2_clksel_to_divisor(clk, field_val); + return omap2_clksel_to_divisor(clk, v); } int omap2_clksel_set_rate(struct clk *clk, unsigned long rate) { - u32 field_mask, field_val, reg_val, validrate, new_div = 0; - void __iomem *div_addr; + u32 v, field_val, validrate, new_div = 0; - validrate = omap2_clksel_round_rate_div(clk, rate, &new_div); - if (validrate != rate) + if (!clk->clksel_mask) return -EINVAL; - div_addr = omap2_get_clksel(clk, &field_mask); - if (!div_addr) + validrate = omap2_clksel_round_rate_div(clk, rate, &new_div); + if (validrate != rate) return -EINVAL; field_val = omap2_divisor_to_clksel(clk, new_div); if (field_val == ~0) return -EINVAL; - reg_val = __raw_readl(div_addr); - reg_val &= ~field_mask; - reg_val |= (field_val << __ffs(field_mask)); - __raw_writel(reg_val, div_addr); + v = __raw_readl(clk->clksel_reg); + v &= ~clk->clksel_mask; + v |= field_val << __ffs(clk->clksel_mask); + __raw_writel(v, clk->clksel_reg); wmb(); clk->rate = clk->parent->rate / new_div; @@ -737,18 +716,14 @@ int omap2_clk_set_rate(struct clk *clk, unsigned long rate) /* * Converts encoded control register address into a full address - * On error, *src_addr will be returned as 0. + * On error, the return value (parent_div) will be 0. */ -static u32 omap2_clksel_get_src_field(void __iomem **src_addr, - struct clk *src_clk, u32 *field_mask, - struct clk *clk, u32 *parent_div) +static u32 _omap2_clksel_get_src_field(struct clk *src_clk, struct clk *clk, + u32 *field_val) { const struct clksel *clks; const struct clksel_rate *clkr; - *parent_div = 0; - *src_addr = NULL; - clks = omap2_get_clksel_by_parent(clk, src_clk); if (!clks) return 0; @@ -768,17 +743,14 @@ static u32 omap2_clksel_get_src_field(void __iomem **src_addr, /* Should never happen. Add a clksel mask to the struct clk. */ WARN_ON(clk->clksel_mask == 0); - *field_mask = clk->clksel_mask; - *src_addr = clk->clksel_reg; - *parent_div = clkr->div; + *field_val = clkr->val; - return clkr->val; + return clkr->div; } int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) { - void __iomem *src_addr; - u32 field_val, field_mask, reg_val, parent_div; + u32 field_val, v, parent_div; if (clk->flags & CONFIG_PARTICIPANT) return -EINVAL; @@ -786,18 +758,18 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) if (!clk->clksel) return -EINVAL; - field_val = omap2_clksel_get_src_field(&src_addr, new_parent, - &field_mask, clk, &parent_div); - if (!src_addr) + parent_div = _omap2_clksel_get_src_field(new_parent, clk, &field_val); + if (!parent_div) return -EINVAL; if (clk->usecount > 0) _omap2_clk_disable(clk); /* Set new source value (previous dividers if any in effect) */ - reg_val = __raw_readl(src_addr) & ~field_mask; - reg_val |= (field_val << __ffs(field_mask)); - __raw_writel(reg_val, src_addr); + v = __raw_readl(clk->clksel_reg); + v &= ~clk->clksel_mask; + v |= field_val << __ffs(clk->clksel_mask); + __raw_writel(v, clk->clksel_reg); wmb(); if (clk->flags & DELAYED_APP && cpu_is_omap24xx()) { -- GitLab From 027d8ded5d1c142eb120caff7a395c0637467ac9 Mon Sep 17 00:00:00 2001 From: Jouni Hogander Date: Fri, 16 May 2008 13:58:18 +0300 Subject: [PATCH 1389/4982] [ARM] OMAP34XX: Add miscellaneous definitions related to 34xx Signed-off-by: Jouni Hogander Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/cm-regbits-34xx.h | 7 +++++++ arch/arm/mach-omap2/prm-regbits-34xx.h | 9 +++++++++ arch/arm/mach-omap2/prm.h | 24 +++++++++++++----------- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h b/arch/arm/mach-omap2/cm-regbits-34xx.h index aaf68a59800..844356cc75b 100644 --- a/arch/arm/mach-omap2/cm-regbits-34xx.h +++ b/arch/arm/mach-omap2/cm-regbits-34xx.h @@ -208,6 +208,10 @@ #define OMAP3430ES2_ST_USBTLL_MASK (1 << 2) /* CM_AUTOIDLE1_CORE */ +#define OMAP3430ES2_AUTO_MMC3 (1 << 30) +#define OMAP3430ES2_AUTO_MMC3_SHIFT 30 +#define OMAP3430ES2_AUTO_ICR (1 << 29) +#define OMAP3430ES2_AUTO_ICR_SHIFT 29 #define OMAP3430_AUTO_AES2 (1 << 28) #define OMAP3430_AUTO_AES2_SHIFT 28 #define OMAP3430_AUTO_SHA12 (1 << 27) @@ -276,6 +280,9 @@ #define OMAP3430_AUTO_DES1_SHIFT 0 /* CM_AUTOIDLE3_CORE */ +#define OMAP3430ES2_AUTO_USBHOST (1 << 0) +#define OMAP3430ES2_AUTO_USBHOST_SHIFT 0 +#define OMAP3430ES2_AUTO_USBTLL (1 << 2) #define OMAP3430ES2_AUTO_USBTLL_SHIFT 2 #define OMAP3430ES2_AUTO_USBTLL_MASK (1 << 2) diff --git a/arch/arm/mach-omap2/prm-regbits-34xx.h b/arch/arm/mach-omap2/prm-regbits-34xx.h index 5b5ecfe6c99..c6a7940f428 100644 --- a/arch/arm/mach-omap2/prm-regbits-34xx.h +++ b/arch/arm/mach-omap2/prm-regbits-34xx.h @@ -366,6 +366,7 @@ /* PM_WKEN_WKUP specific bits */ #define OMAP3430_EN_IO (1 << 8) +#define OMAP3430_EN_GPIO1 (1 << 3) /* PM_MPUGRPSEL_WKUP specific bits */ @@ -452,6 +453,14 @@ #define OMAP3430_CMDRA0_MASK (0xff << 0) /* PRM_VC_CMD_VAL_0 specific bits */ +#define OMAP3430_VC_CMD_ON_SHIFT 24 +#define OMAP3430_VC_CMD_ON_MASK (0xFF << 24) +#define OMAP3430_VC_CMD_ONLP_SHIFT 16 +#define OMAP3430_VC_CMD_ONLP_MASK (0xFF << 16) +#define OMAP3430_VC_CMD_RET_SHIFT 8 +#define OMAP3430_VC_CMD_RET_MASK (0xFF << 8) +#define OMAP3430_VC_CMD_OFF_SHIFT 0 +#define OMAP3430_VC_CMD_OFF_MASK (0xFF << 0) /* PRM_VC_CMD_VAL_1 specific bits */ diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h index e4dc4b17881..826d326b806 100644 --- a/arch/arm/mach-omap2/prm.h +++ b/arch/arm/mach-omap2/prm.h @@ -141,6 +141,19 @@ #define PM_PWSTCTRL 0x00e0 #define PM_PWSTST 0x00e4 +/* Omap2 specific registers */ +#define OMAP24XX_PM_WKEN2 0x00a4 +#define OMAP24XX_PM_WKST2 0x00b4 + +#define OMAP24XX_PRCM_IRQSTATUS_DSP 0x00f0 /* IVA mod */ +#define OMAP24XX_PRCM_IRQENABLE_DSP 0x00f4 /* IVA mod */ +#define OMAP24XX_PRCM_IRQSTATUS_IVA 0x00f8 +#define OMAP24XX_PRCM_IRQENABLE_IVA 0x00fc + +/* Omap3 specific registers */ +#define OMAP3430ES2_PM_WKEN3 0x00f0 +#define OMAP3430ES2_PM_WKST3 0x00b8 + #define OMAP3430_PM_MPUGRPSEL 0x00a4 #define OMAP3430_PM_MPUGRPSEL1 OMAP3430_PM_MPUGRPSEL @@ -153,16 +166,6 @@ #define OMAP3430_PRM_IRQENABLE_IVA2 0x00fc -/* Architecture-specific registers */ - -#define OMAP24XX_PM_WKEN2 0x00a4 -#define OMAP24XX_PM_WKST2 0x00b4 - -#define OMAP24XX_PRCM_IRQSTATUS_DSP 0x00f0 /* IVA mod */ -#define OMAP24XX_PRCM_IRQENABLE_DSP 0x00f4 /* IVA mod */ -#define OMAP24XX_PRCM_IRQSTATUS_IVA 0x00f8 -#define OMAP24XX_PRCM_IRQENABLE_IVA 0x00fc - #ifndef __ASSEMBLER__ /* Power/reset management domain register get/set */ @@ -228,7 +231,6 @@ static inline u32 prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx) #define OMAP_RSTTIME1_SHIFT 0 #define OMAP_RSTTIME1_MASK (0xff << 0) - /* PRM_RSTCTRL */ /* Named RM_RSTCTRL_WKUP on the 24xx */ /* 2420 calls RST_DPLL3 'RST_DPLL' */ -- GitLab From da0747d4faf55320f0f6cbcd8525e2a8e4619925 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 28 Jan 2009 12:18:22 -0700 Subject: [PATCH 1390/4982] [ARM] OMAP2 PRCM: clean up CM_IDLEST bits This patch fixes a few OMAP2xxx CM_IDLEST bits that were incorrectly marked as being OMAP2xxx-wide, when they were actually 2420-specific. Also, originally when the PRCM register macros were defined, bit shift macros used a "_SHIFT" suffix, and mask macros used none. This became a source of bugs and confusion, as the mask macros were mistakenly used for shift values. Gradually, the mask macros have been updated, piece by piece, to add a "_MASK" suffix on the end to clarify. This patch applies this change to the CM_IDLEST_* register bits. The patch also adds a few bits that were missing, mostly from the 3430ES1 to ES2 revisions. linux-omap source commits are d18eff5b5fa15e170794397a6a94486d1f774f77, e1f1a5cc24615fb790cc763c96d1c5cfe6296f5b, and part of 9fe6b6cf8d9e0cbb429fd64553a4b3160a9e99e1 Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/cm-regbits-24xx.h | 80 +++++++---- arch/arm/mach-omap2/cm-regbits-34xx.h | 96 +++++++++---- arch/arm/mach-omap2/prcm-common.h | 198 +++++++++++++++++--------- 3 files changed, 257 insertions(+), 117 deletions(-) diff --git a/arch/arm/mach-omap2/cm-regbits-24xx.h b/arch/arm/mach-omap2/cm-regbits-24xx.h index 1098ecfab86..297a2fe634e 100644 --- a/arch/arm/mach-omap2/cm-regbits-24xx.h +++ b/arch/arm/mach-omap2/cm-regbits-24xx.h @@ -110,35 +110,56 @@ #define OMAP24XX_EN_DES (1 << 0) /* CM_IDLEST1_CORE specific bits */ -#define OMAP24XX_ST_MAILBOXES (1 << 30) -#define OMAP24XX_ST_WDT4 (1 << 29) -#define OMAP2420_ST_WDT3 (1 << 28) -#define OMAP24XX_ST_MSPRO (1 << 27) -#define OMAP24XX_ST_FAC (1 << 25) -#define OMAP2420_ST_EAC (1 << 24) -#define OMAP24XX_ST_HDQ (1 << 23) -#define OMAP24XX_ST_I2C2 (1 << 20) -#define OMAP24XX_ST_I2C1 (1 << 19) -#define OMAP24XX_ST_MCBSP2 (1 << 16) -#define OMAP24XX_ST_MCBSP1 (1 << 15) -#define OMAP24XX_ST_DSS (1 << 0) +#define OMAP24XX_ST_MAILBOXES_SHIFT 30 +#define OMAP24XX_ST_MAILBOXES_MASK (1 << 30) +#define OMAP24XX_ST_WDT4_SHIFT 29 +#define OMAP24XX_ST_WDT4_MASK (1 << 29) +#define OMAP2420_ST_WDT3_SHIFT 28 +#define OMAP2420_ST_WDT3_MASK (1 << 28) +#define OMAP24XX_ST_MSPRO_SHIFT 27 +#define OMAP24XX_ST_MSPRO_MASK (1 << 27) +#define OMAP24XX_ST_FAC_SHIFT 25 +#define OMAP24XX_ST_FAC_MASK (1 << 25) +#define OMAP2420_ST_EAC_SHIFT 24 +#define OMAP2420_ST_EAC_MASK (1 << 24) +#define OMAP24XX_ST_HDQ_SHIFT 23 +#define OMAP24XX_ST_HDQ_MASK (1 << 23) +#define OMAP2420_ST_I2C2_SHIFT 20 +#define OMAP2420_ST_I2C2_MASK (1 << 20) +#define OMAP2420_ST_I2C1_SHIFT 19 +#define OMAP2420_ST_I2C1_MASK (1 << 19) +#define OMAP24XX_ST_MCBSP2_SHIFT 16 +#define OMAP24XX_ST_MCBSP2_MASK (1 << 16) +#define OMAP24XX_ST_MCBSP1_SHIFT 15 +#define OMAP24XX_ST_MCBSP1_MASK (1 << 15) +#define OMAP24XX_ST_DSS_SHIFT 0 +#define OMAP24XX_ST_DSS_MASK (1 << 0) /* CM_IDLEST2_CORE */ -#define OMAP2430_ST_MCBSP5 (1 << 5) -#define OMAP2430_ST_MCBSP4 (1 << 4) -#define OMAP2430_ST_MCBSP3 (1 << 3) -#define OMAP24XX_ST_SSI (1 << 1) +#define OMAP2430_ST_MCBSP5_SHIFT 5 +#define OMAP2430_ST_MCBSP5_MASK (1 << 5) +#define OMAP2430_ST_MCBSP4_SHIFT 4 +#define OMAP2430_ST_MCBSP4_MASK (1 << 4) +#define OMAP2430_ST_MCBSP3_SHIFT 3 +#define OMAP2430_ST_MCBSP3_MASK (1 << 3) +#define OMAP24XX_ST_SSI_SHIFT 1 +#define OMAP24XX_ST_SSI_MASK (1 << 1) /* CM_IDLEST3_CORE */ /* 2430 only */ -#define OMAP2430_ST_SDRC (1 << 2) +#define OMAP2430_ST_SDRC_MASK (1 << 2) /* CM_IDLEST4_CORE */ -#define OMAP24XX_ST_PKA (1 << 4) -#define OMAP24XX_ST_AES (1 << 3) -#define OMAP24XX_ST_RNG (1 << 2) -#define OMAP24XX_ST_SHA (1 << 1) -#define OMAP24XX_ST_DES (1 << 0) +#define OMAP24XX_ST_PKA_SHIFT 4 +#define OMAP24XX_ST_PKA_MASK (1 << 4) +#define OMAP24XX_ST_AES_SHIFT 3 +#define OMAP24XX_ST_AES_MASK (1 << 3) +#define OMAP24XX_ST_RNG_SHIFT 2 +#define OMAP24XX_ST_RNG_MASK (1 << 2) +#define OMAP24XX_ST_SHA_SHIFT 1 +#define OMAP24XX_ST_SHA_MASK (1 << 1) +#define OMAP24XX_ST_DES_SHIFT 0 +#define OMAP24XX_ST_DES_MASK (1 << 0) /* CM_AUTOIDLE1_CORE */ #define OMAP24XX_AUTO_CAM (1 << 31) @@ -275,11 +296,16 @@ #define OMAP24XX_EN_32KSYNC (1 << 1) /* CM_IDLEST_WKUP specific bits */ -#define OMAP2430_ST_ICR (1 << 6) -#define OMAP24XX_ST_OMAPCTRL (1 << 5) -#define OMAP24XX_ST_WDT1 (1 << 4) -#define OMAP24XX_ST_MPU_WDT (1 << 3) -#define OMAP24XX_ST_32KSYNC (1 << 1) +#define OMAP2430_ST_ICR_SHIFT 6 +#define OMAP2430_ST_ICR_MASK (1 << 6) +#define OMAP24XX_ST_OMAPCTRL_SHIFT 5 +#define OMAP24XX_ST_OMAPCTRL_MASK (1 << 5) +#define OMAP24XX_ST_WDT1_SHIFT 4 +#define OMAP24XX_ST_WDT1_MASK (1 << 4) +#define OMAP24XX_ST_MPU_WDT_SHIFT 3 +#define OMAP24XX_ST_MPU_WDT_MASK (1 << 3) +#define OMAP24XX_ST_32KSYNC_SHIFT 1 +#define OMAP24XX_ST_32KSYNC_MASK (1 << 1) /* CM_AUTOIDLE_WKUP */ #define OMAP24XX_AUTO_OMAPCTRL (1 << 5) diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h b/arch/arm/mach-omap2/cm-regbits-34xx.h index 844356cc75b..6f3f5a36aae 100644 --- a/arch/arm/mach-omap2/cm-regbits-34xx.h +++ b/arch/arm/mach-omap2/cm-regbits-34xx.h @@ -183,29 +183,52 @@ #define OMAP3430ES2_EN_CPEFUSE_MASK (1 << 0) /* CM_IDLEST1_CORE specific bits */ -#define OMAP3430_ST_ICR (1 << 29) -#define OMAP3430_ST_AES2 (1 << 28) -#define OMAP3430_ST_SHA12 (1 << 27) -#define OMAP3430_ST_DES2 (1 << 26) -#define OMAP3430_ST_MSPRO (1 << 23) -#define OMAP3430_ST_HDQ (1 << 22) -#define OMAP3430ES1_ST_FAC (1 << 8) -#define OMAP3430ES1_ST_MAILBOXES (1 << 7) -#define OMAP3430_ST_OMAPCTRL (1 << 6) -#define OMAP3430_ST_SDMA (1 << 2) -#define OMAP3430_ST_SDRC (1 << 1) -#define OMAP3430_ST_SSI (1 << 0) +#define OMAP3430ES2_ST_MMC3_SHIFT 30 +#define OMAP3430ES2_ST_MMC3_MASK (1 << 30) +#define OMAP3430_ST_ICR_SHIFT 29 +#define OMAP3430_ST_ICR_MASK (1 << 29) +#define OMAP3430_ST_AES2_SHIFT 28 +#define OMAP3430_ST_AES2_MASK (1 << 28) +#define OMAP3430_ST_SHA12_SHIFT 27 +#define OMAP3430_ST_SHA12_MASK (1 << 27) +#define OMAP3430_ST_DES2_SHIFT 26 +#define OMAP3430_ST_DES2_MASK (1 << 26) +#define OMAP3430_ST_MSPRO_SHIFT 23 +#define OMAP3430_ST_MSPRO_MASK (1 << 23) +#define OMAP3430_ST_HDQ_SHIFT 22 +#define OMAP3430_ST_HDQ_MASK (1 << 22) +#define OMAP3430ES1_ST_FAC_SHIFT 8 +#define OMAP3430ES1_ST_FAC_MASK (1 << 8) +#define OMAP3430ES2_ST_SSI_IDLE_SHIFT 8 +#define OMAP3430ES2_ST_SSI_IDLE_MASK (1 << 8) +#define OMAP3430_ST_MAILBOXES_SHIFT 7 +#define OMAP3430_ST_MAILBOXES_MASK (1 << 7) +#define OMAP3430_ST_OMAPCTRL_SHIFT 6 +#define OMAP3430_ST_OMAPCTRL_MASK (1 << 6) +#define OMAP3430_ST_SDMA_SHIFT 2 +#define OMAP3430_ST_SDMA_MASK (1 << 2) +#define OMAP3430_ST_SDRC_SHIFT 1 +#define OMAP3430_ST_SDRC_MASK (1 << 1) +#define OMAP3430_ST_SSI_STDBY_SHIFT 0 +#define OMAP3430_ST_SSI_STDBY_MASK (1 << 0) /* CM_IDLEST2_CORE */ -#define OMAP3430_ST_PKA (1 << 4) -#define OMAP3430_ST_AES1 (1 << 3) -#define OMAP3430_ST_RNG (1 << 2) -#define OMAP3430_ST_SHA11 (1 << 1) -#define OMAP3430_ST_DES1 (1 << 0) +#define OMAP3430_ST_PKA_SHIFT 4 +#define OMAP3430_ST_PKA_MASK (1 << 4) +#define OMAP3430_ST_AES1_SHIFT 3 +#define OMAP3430_ST_AES1_MASK (1 << 3) +#define OMAP3430_ST_RNG_SHIFT 2 +#define OMAP3430_ST_RNG_MASK (1 << 2) +#define OMAP3430_ST_SHA11_SHIFT 1 +#define OMAP3430_ST_SHA11_MASK (1 << 1) +#define OMAP3430_ST_DES1_SHIFT 0 +#define OMAP3430_ST_DES1_MASK (1 << 0) /* CM_IDLEST3_CORE */ #define OMAP3430ES2_ST_USBTLL_SHIFT 2 #define OMAP3430ES2_ST_USBTLL_MASK (1 << 2) +#define OMAP3430ES2_ST_CPEFUSE_SHIFT 0 +#define OMAP3430ES2_ST_CPEFUSE_MASK (1 << 0) /* CM_AUTOIDLE1_CORE */ #define OMAP3430ES2_AUTO_MMC3 (1 << 30) @@ -360,6 +383,7 @@ /* CM_FCLKEN_WKUP specific bits */ #define OMAP3430ES2_EN_USIMOCP_SHIFT 9 +#define OMAP3430ES2_EN_USIMOCP_MASK (1 << 9) /* CM_ICLKEN_WKUP specific bits */ #define OMAP3430_EN_WDT1 (1 << 4) @@ -368,11 +392,18 @@ #define OMAP3430_EN_32KSYNC_SHIFT 2 /* CM_IDLEST_WKUP specific bits */ -#define OMAP3430_ST_WDT2 (1 << 5) -#define OMAP3430_ST_WDT1 (1 << 4) -#define OMAP3430_ST_32KSYNC (1 << 2) +#define OMAP3430ES2_ST_USIMOCP_SHIFT 9 +#define OMAP3430ES2_ST_USIMOCP_MASK (1 << 9) +#define OMAP3430_ST_WDT2_SHIFT 5 +#define OMAP3430_ST_WDT2_MASK (1 << 5) +#define OMAP3430_ST_WDT1_SHIFT 4 +#define OMAP3430_ST_WDT1_MASK (1 << 4) +#define OMAP3430_ST_32KSYNC_SHIFT 2 +#define OMAP3430_ST_32KSYNC_MASK (1 << 2) /* CM_AUTOIDLE_WKUP */ +#define OMAP3430ES2_AUTO_USIMOCP (1 << 9) +#define OMAP3430ES2_AUTO_USIMOCP_SHIFT 9 #define OMAP3430_AUTO_WDT2 (1 << 5) #define OMAP3430_AUTO_WDT2_SHIFT 5 #define OMAP3430_AUTO_WDT1 (1 << 4) @@ -437,6 +468,8 @@ #define OMAP3430_ST_CORE_CLK_MASK (1 << 0) /* CM_IDLEST2_CKGEN */ +#define OMAP3430ES2_ST_USIM_CLK_SHIFT 2 +#define OMAP3430ES2_ST_USIM_CLK_MASK (1 << 2) #define OMAP3430ES2_ST_120M_CLK_SHIFT 1 #define OMAP3430ES2_ST_120M_CLK_MASK (1 << 1) #define OMAP3430ES2_ST_PERIPH2_CLK_SHIFT 0 @@ -508,7 +541,12 @@ #define OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT 0 /* CM_IDLEST_DSS */ -#define OMAP3430_ST_DSS (1 << 0) +#define OMAP3430ES2_ST_DSS_IDLE_SHIFT 1 +#define OMAP3430ES2_ST_DSS_IDLE_MASK (1 << 1) +#define OMAP3430ES2_ST_DSS_STDBY_SHIFT 0 +#define OMAP3430ES2_ST_DSS_STDBY_MASK (1 << 0) +#define OMAP3430ES1_ST_DSS_SHIFT 0 +#define OMAP3430ES1_ST_DSS_MASK (1 << 0) /* CM_AUTOIDLE_DSS */ #define OMAP3430_AUTO_DSS (1 << 0) @@ -562,10 +600,14 @@ /* CM_ICLKEN_PER specific bits */ /* CM_IDLEST_PER */ -#define OMAP3430_ST_WDT3 (1 << 12) -#define OMAP3430_ST_MCBSP4 (1 << 2) -#define OMAP3430_ST_MCBSP3 (1 << 1) -#define OMAP3430_ST_MCBSP2 (1 << 0) +#define OMAP3430_ST_WDT3_SHIFT 12 +#define OMAP3430_ST_WDT3_MASK (1 << 12) +#define OMAP3430_ST_MCBSP4_SHIFT 2 +#define OMAP3430_ST_MCBSP4_MASK (1 << 2) +#define OMAP3430_ST_MCBSP3_SHIFT 1 +#define OMAP3430_ST_MCBSP3_MASK (1 << 1) +#define OMAP3430_ST_MCBSP2_SHIFT 0 +#define OMAP3430_ST_MCBSP2_MASK (1 << 0) /* CM_AUTOIDLE_PER */ #define OMAP3430_AUTO_GPIO6 (1 << 17) @@ -693,6 +735,10 @@ #define OMAP3430ES2_EN_USBHOST_MASK (1 << 0) /* CM_IDLEST_USBHOST */ +#define OMAP3430ES2_ST_USBHOST_IDLE_SHIFT 1 +#define OMAP3430ES2_ST_USBHOST_IDLE_MASK (1 << 1) +#define OMAP3430ES2_ST_USBHOST_STDBY_SHIFT 0 +#define OMAP3430ES2_ST_USBHOST_STDBY_MASK (1 << 0) /* CM_AUTOIDLE_USBHOST */ #define OMAP3430ES2_AUTO_USBHOST_SHIFT 0 diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h index 4a32822ff3f..812d50ee495 100644 --- a/arch/arm/mach-omap2/prcm-common.h +++ b/arch/arm/mach-omap2/prcm-common.h @@ -113,33 +113,58 @@ #define OMAP2430_EN_USBHS (1 << 6) /* CM_IDLEST1_CORE, PM_WKST1_CORE shared bits */ -#define OMAP2420_ST_MMC (1 << 26) -#define OMAP24XX_ST_UART2 (1 << 22) -#define OMAP24XX_ST_UART1 (1 << 21) -#define OMAP24XX_ST_MCSPI2 (1 << 18) -#define OMAP24XX_ST_MCSPI1 (1 << 17) -#define OMAP24XX_ST_GPT12 (1 << 14) -#define OMAP24XX_ST_GPT11 (1 << 13) -#define OMAP24XX_ST_GPT10 (1 << 12) -#define OMAP24XX_ST_GPT9 (1 << 11) -#define OMAP24XX_ST_GPT8 (1 << 10) -#define OMAP24XX_ST_GPT7 (1 << 9) -#define OMAP24XX_ST_GPT6 (1 << 8) -#define OMAP24XX_ST_GPT5 (1 << 7) -#define OMAP24XX_ST_GPT4 (1 << 6) -#define OMAP24XX_ST_GPT3 (1 << 5) -#define OMAP24XX_ST_GPT2 (1 << 4) -#define OMAP2420_ST_VLYNQ (1 << 3) +#define OMAP2420_ST_MMC_SHIFT 26 +#define OMAP2420_ST_MMC_MASK (1 << 26) +#define OMAP24XX_ST_UART2_SHIFT 22 +#define OMAP24XX_ST_UART2_MASK (1 << 22) +#define OMAP24XX_ST_UART1_SHIFT 21 +#define OMAP24XX_ST_UART1_MASK (1 << 21) +#define OMAP24XX_ST_MCSPI2_SHIFT 18 +#define OMAP24XX_ST_MCSPI2_MASK (1 << 18) +#define OMAP24XX_ST_MCSPI1_SHIFT 17 +#define OMAP24XX_ST_MCSPI1_MASK (1 << 17) +#define OMAP24XX_ST_GPT12_SHIFT 14 +#define OMAP24XX_ST_GPT12_MASK (1 << 14) +#define OMAP24XX_ST_GPT11_SHIFT 13 +#define OMAP24XX_ST_GPT11_MASK (1 << 13) +#define OMAP24XX_ST_GPT10_SHIFT 12 +#define OMAP24XX_ST_GPT10_MASK (1 << 12) +#define OMAP24XX_ST_GPT9_SHIFT 11 +#define OMAP24XX_ST_GPT9_MASK (1 << 11) +#define OMAP24XX_ST_GPT8_SHIFT 10 +#define OMAP24XX_ST_GPT8_MASK (1 << 10) +#define OMAP24XX_ST_GPT7_SHIFT 9 +#define OMAP24XX_ST_GPT7_MASK (1 << 9) +#define OMAP24XX_ST_GPT6_SHIFT 8 +#define OMAP24XX_ST_GPT6_MASK (1 << 8) +#define OMAP24XX_ST_GPT5_SHIFT 7 +#define OMAP24XX_ST_GPT5_MASK (1 << 7) +#define OMAP24XX_ST_GPT4_SHIFT 6 +#define OMAP24XX_ST_GPT4_MASK (1 << 6) +#define OMAP24XX_ST_GPT3_SHIFT 5 +#define OMAP24XX_ST_GPT3_MASK (1 << 5) +#define OMAP24XX_ST_GPT2_SHIFT 4 +#define OMAP24XX_ST_GPT2_MASK (1 << 4) +#define OMAP2420_ST_VLYNQ_SHIFT 3 +#define OMAP2420_ST_VLYNQ_MASK (1 << 3) /* CM_IDLEST2_CORE, PM_WKST2_CORE shared bits */ -#define OMAP2430_ST_MDM_INTC (1 << 11) -#define OMAP2430_ST_GPIO5 (1 << 10) -#define OMAP2430_ST_MCSPI3 (1 << 9) -#define OMAP2430_ST_MMCHS2 (1 << 8) -#define OMAP2430_ST_MMCHS1 (1 << 7) -#define OMAP2430_ST_USBHS (1 << 6) -#define OMAP24XX_ST_UART3 (1 << 2) -#define OMAP24XX_ST_USB (1 << 0) +#define OMAP2430_ST_MDM_INTC_SHIFT 11 +#define OMAP2430_ST_MDM_INTC_MASK (1 << 11) +#define OMAP2430_ST_GPIO5_SHIFT 10 +#define OMAP2430_ST_GPIO5_MASK (1 << 10) +#define OMAP2430_ST_MCSPI3_SHIFT 9 +#define OMAP2430_ST_MCSPI3_MASK (1 << 9) +#define OMAP2430_ST_MMCHS2_SHIFT 8 +#define OMAP2430_ST_MMCHS2_MASK (1 << 8) +#define OMAP2430_ST_MMCHS1_SHIFT 7 +#define OMAP2430_ST_MMCHS1_MASK (1 << 7) +#define OMAP2430_ST_USBHS_SHIFT 6 +#define OMAP2430_ST_USBHS_MASK (1 << 6) +#define OMAP24XX_ST_UART3_SHIFT 2 +#define OMAP24XX_ST_UART3_MASK (1 << 2) +#define OMAP24XX_ST_USB_SHIFT 0 +#define OMAP24XX_ST_USB_MASK (1 << 0) /* CM_FCLKEN_WKUP, CM_ICLKEN_WKUP, PM_WKEN_WKUP shared bits */ #define OMAP24XX_EN_GPIOS_SHIFT 2 @@ -148,11 +173,13 @@ #define OMAP24XX_EN_GPT1 (1 << 0) /* PM_WKST_WKUP, CM_IDLEST_WKUP shared bits */ -#define OMAP24XX_ST_GPIOS (1 << 2) -#define OMAP24XX_ST_GPT1 (1 << 0) +#define OMAP24XX_ST_GPIOS_SHIFT (1 << 2) +#define OMAP24XX_ST_GPIOS_MASK 2 +#define OMAP24XX_ST_GPT1_SHIFT (1 << 0) +#define OMAP24XX_ST_GPT1_MASK 0 /* CM_IDLEST_MDM and PM_WKST_MDM shared bits */ -#define OMAP2430_ST_MDM (1 << 0) +#define OMAP2430_ST_MDM_SHIFT (1 << 0) /* 3430 register bits shared between CM & PRM registers */ @@ -205,24 +232,46 @@ #define OMAP3430_EN_HSOTGUSB_SHIFT 4 /* PM_WKST1_CORE, CM_IDLEST1_CORE shared bits */ -#define OMAP3430_ST_MMC2 (1 << 25) -#define OMAP3430_ST_MMC1 (1 << 24) -#define OMAP3430_ST_MCSPI4 (1 << 21) -#define OMAP3430_ST_MCSPI3 (1 << 20) -#define OMAP3430_ST_MCSPI2 (1 << 19) -#define OMAP3430_ST_MCSPI1 (1 << 18) -#define OMAP3430_ST_I2C3 (1 << 17) -#define OMAP3430_ST_I2C2 (1 << 16) -#define OMAP3430_ST_I2C1 (1 << 15) -#define OMAP3430_ST_UART2 (1 << 14) -#define OMAP3430_ST_UART1 (1 << 13) -#define OMAP3430_ST_GPT11 (1 << 12) -#define OMAP3430_ST_GPT10 (1 << 11) -#define OMAP3430_ST_MCBSP5 (1 << 10) -#define OMAP3430_ST_MCBSP1 (1 << 9) -#define OMAP3430_ST_FSHOSTUSB (1 << 5) -#define OMAP3430_ST_HSOTGUSB (1 << 4) -#define OMAP3430_ST_D2D (1 << 3) +#define OMAP3430_ST_MMC2_SHIFT 25 +#define OMAP3430_ST_MMC2_MASK (1 << 25) +#define OMAP3430_ST_MMC1_SHIFT 24 +#define OMAP3430_ST_MMC1_MASK (1 << 24) +#define OMAP3430_ST_MCSPI4_SHIFT 21 +#define OMAP3430_ST_MCSPI4_MASK (1 << 21) +#define OMAP3430_ST_MCSPI3_SHIFT 20 +#define OMAP3430_ST_MCSPI3_MASK (1 << 20) +#define OMAP3430_ST_MCSPI2_SHIFT 19 +#define OMAP3430_ST_MCSPI2_MASK (1 << 19) +#define OMAP3430_ST_MCSPI1_SHIFT 18 +#define OMAP3430_ST_MCSPI1_MASK (1 << 18) +#define OMAP3430_ST_I2C3_SHIFT 17 +#define OMAP3430_ST_I2C3_MASK (1 << 17) +#define OMAP3430_ST_I2C2_SHIFT 16 +#define OMAP3430_ST_I2C2_MASK (1 << 16) +#define OMAP3430_ST_I2C1_SHIFT 15 +#define OMAP3430_ST_I2C1_MASK (1 << 15) +#define OMAP3430_ST_UART2_SHIFT 14 +#define OMAP3430_ST_UART2_MASK (1 << 14) +#define OMAP3430_ST_UART1_SHIFT 13 +#define OMAP3430_ST_UART1_MASK (1 << 13) +#define OMAP3430_ST_GPT11_SHIFT 12 +#define OMAP3430_ST_GPT11_MASK (1 << 12) +#define OMAP3430_ST_GPT10_SHIFT 11 +#define OMAP3430_ST_GPT10_MASK (1 << 11) +#define OMAP3430_ST_MCBSP5_SHIFT 10 +#define OMAP3430_ST_MCBSP5_MASK (1 << 10) +#define OMAP3430_ST_MCBSP1_SHIFT 9 +#define OMAP3430_ST_MCBSP1_MASK (1 << 9) +#define OMAP3430ES1_ST_FSHOSTUSB_SHIFT 5 +#define OMAP3430ES1_ST_FSHOSTUSB_MASK (1 << 5) +#define OMAP3430ES1_ST_HSOTGUSB_SHIFT 4 +#define OMAP3430ES1_ST_HSOTGUSB_MASK (1 << 4) +#define OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT 5 +#define OMAP3430ES2_ST_HSOTGUSB_IDLE_MASK (1 << 5) +#define OMAP3430ES2_ST_HSOTGUSB_STDBY_SHIFT 4 +#define OMAP3430ES2_ST_HSOTGUSB_STDBY_MASK (1 << 4) +#define OMAP3430_ST_D2D_SHIFT 3 +#define OMAP3430_ST_D2D_MASK (1 << 3) /* CM_FCLKEN_WKUP, CM_ICLKEN_WKUP, PM_WKEN_WKUP shared bits */ #define OMAP3430_EN_GPIO1 (1 << 3) @@ -241,11 +290,16 @@ #define OMAP3430_EN_GPT12_SHIFT 1 /* CM_IDLEST_WKUP, PM_WKST_WKUP shared bits */ -#define OMAP3430_ST_SR2 (1 << 7) -#define OMAP3430_ST_SR1 (1 << 6) -#define OMAP3430_ST_GPIO1 (1 << 3) -#define OMAP3430_ST_GPT12 (1 << 1) -#define OMAP3430_ST_GPT1 (1 << 0) +#define OMAP3430_ST_SR2_SHIFT 7 +#define OMAP3430_ST_SR2_MASK (1 << 7) +#define OMAP3430_ST_SR1_SHIFT 6 +#define OMAP3430_ST_SR1_MASK (1 << 6) +#define OMAP3430_ST_GPIO1_SHIFT 3 +#define OMAP3430_ST_GPIO1_MASK (1 << 3) +#define OMAP3430_ST_GPT12_SHIFT 1 +#define OMAP3430_ST_GPT12_MASK (1 << 1) +#define OMAP3430_ST_GPT1_SHIFT 0 +#define OMAP3430_ST_GPT1_MASK (1 << 0) /* * CM_SLEEPDEP_GFX, CM_SLEEPDEP_DSS, CM_SLEEPDEP_CAM, @@ -296,20 +350,34 @@ #define OMAP3430_EN_MCBSP2_SHIFT 0 /* CM_IDLEST_PER, PM_WKST_PER shared bits */ -#define OMAP3430_ST_GPIO6 (1 << 17) -#define OMAP3430_ST_GPIO5 (1 << 16) -#define OMAP3430_ST_GPIO4 (1 << 15) -#define OMAP3430_ST_GPIO3 (1 << 14) -#define OMAP3430_ST_GPIO2 (1 << 13) -#define OMAP3430_ST_UART3 (1 << 11) -#define OMAP3430_ST_GPT9 (1 << 10) -#define OMAP3430_ST_GPT8 (1 << 9) -#define OMAP3430_ST_GPT7 (1 << 8) -#define OMAP3430_ST_GPT6 (1 << 7) -#define OMAP3430_ST_GPT5 (1 << 6) -#define OMAP3430_ST_GPT4 (1 << 5) -#define OMAP3430_ST_GPT3 (1 << 4) -#define OMAP3430_ST_GPT2 (1 << 3) +#define OMAP3430_ST_GPIO6_SHIFT 17 +#define OMAP3430_ST_GPIO6_MASK (1 << 17) +#define OMAP3430_ST_GPIO5_SHIFT 16 +#define OMAP3430_ST_GPIO5_MASK (1 << 16) +#define OMAP3430_ST_GPIO4_SHIFT 15 +#define OMAP3430_ST_GPIO4_MASK (1 << 15) +#define OMAP3430_ST_GPIO3_SHIFT 14 +#define OMAP3430_ST_GPIO3_MASK (1 << 14) +#define OMAP3430_ST_GPIO2_SHIFT 13 +#define OMAP3430_ST_GPIO2_MASK (1 << 13) +#define OMAP3430_ST_UART3_SHIFT 11 +#define OMAP3430_ST_UART3_MASK (1 << 11) +#define OMAP3430_ST_GPT9_SHIFT 10 +#define OMAP3430_ST_GPT9_MASK (1 << 10) +#define OMAP3430_ST_GPT8_SHIFT 9 +#define OMAP3430_ST_GPT8_MASK (1 << 9) +#define OMAP3430_ST_GPT7_SHIFT 8 +#define OMAP3430_ST_GPT7_MASK (1 << 8) +#define OMAP3430_ST_GPT6_SHIFT 7 +#define OMAP3430_ST_GPT6_MASK (1 << 7) +#define OMAP3430_ST_GPT5_SHIFT 6 +#define OMAP3430_ST_GPT5_MASK (1 << 6) +#define OMAP3430_ST_GPT4_SHIFT 5 +#define OMAP3430_ST_GPT4_MASK (1 << 5) +#define OMAP3430_ST_GPT3_SHIFT 4 +#define OMAP3430_ST_GPT3_MASK (1 << 4) +#define OMAP3430_ST_GPT2_SHIFT 3 +#define OMAP3430_ST_GPT2_MASK (1 << 3) /* CM_SLEEPDEP_PER, PM_WKDEP_IVA2, PM_WKDEP_MPU, PM_WKDEP_PER shared bits */ #define OMAP3430_EN_CORE_SHIFT 0 -- GitLab From fed415e48f07799b278cd4353385fee1464d4aca Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 28 Jan 2009 12:18:48 -0700 Subject: [PATCH 1391/4982] [ARM] omap: Fix omap1 clock issues This fixes booting, and is a step toward fixing things properly: - Make enable_reg u32 instead of u16 [rmk: virtual addresses are void __iomem *, not u32] - Get rid of VIRTUAL_IO_ADDRESS for clocks - Use __raw_read/write instead of omap_read/write for clock registers This patch adds a bunch of compile warnings until omap1 clock also uses offsets. linux-omap source commit is 9d1dff8638c9e96a401e1885f9948662e9ff9636. Signed-off-by: Tony Lindgren Signed-off-by: Paul Walmsley Signed-off-by: Russell King --- arch/arm/mach-omap1/clock.c | 77 ++++++++----------------- arch/arm/mach-omap1/clock.h | 63 ++++++++++---------- arch/arm/plat-omap/include/mach/clock.h | 1 - 3 files changed, 53 insertions(+), 88 deletions(-) diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index 7c455431790..1e477af666e 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -163,7 +163,7 @@ static void omap1_watchdog_recalc(struct clk * clk) static void omap1_uart_recalc(struct clk * clk) { - unsigned int val = omap_readl(clk->enable_reg); + unsigned int val = __raw_readl(clk->enable_reg); if (val & clk->enable_bit) clk->rate = 48000000; else @@ -517,14 +517,14 @@ static int omap1_set_uart_rate(struct clk * clk, unsigned long rate) { unsigned int val; - val = omap_readl(clk->enable_reg); + val = __raw_readl(clk->enable_reg); if (rate == 12000000) val &= ~(1 << clk->enable_bit); else if (rate == 48000000) val |= (1 << clk->enable_bit); else return -EINVAL; - omap_writel(val, clk->enable_reg); + __raw_writel(val, clk->enable_reg); clk->rate = rate; return 0; @@ -543,8 +543,8 @@ static int omap1_set_ext_clk_rate(struct clk * clk, unsigned long rate) else ratio_bits = (dsor - 2) << 2; - ratio_bits |= omap_readw(clk->enable_reg) & ~0xfd; - omap_writew(ratio_bits, clk->enable_reg); + ratio_bits |= __raw_readw(clk->enable_reg) & ~0xfd; + __raw_writew(ratio_bits, clk->enable_reg); return 0; } @@ -583,8 +583,8 @@ static void omap1_init_ext_clk(struct clk * clk) __u16 ratio_bits; /* Determine current rate and ensure clock is based on 96MHz APLL */ - ratio_bits = omap_readw(clk->enable_reg) & ~1; - omap_writew(ratio_bits, clk->enable_reg); + ratio_bits = __raw_readw(clk->enable_reg) & ~1; + __raw_writew(ratio_bits, clk->enable_reg); ratio_bits = (ratio_bits & 0xfc) >> 2; if (ratio_bits > 6) @@ -646,25 +646,13 @@ static int omap1_clk_enable_generic(struct clk *clk) } if (clk->flags & ENABLE_REG_32BIT) { - if (clk->flags & VIRTUAL_IO_ADDRESS) { - regval32 = __raw_readl(clk->enable_reg); - regval32 |= (1 << clk->enable_bit); - __raw_writel(regval32, clk->enable_reg); - } else { - regval32 = omap_readl(clk->enable_reg); - regval32 |= (1 << clk->enable_bit); - omap_writel(regval32, clk->enable_reg); - } + regval32 = __raw_readl(clk->enable_reg); + regval32 |= (1 << clk->enable_bit); + __raw_writel(regval32, clk->enable_reg); } else { - if (clk->flags & VIRTUAL_IO_ADDRESS) { - regval16 = __raw_readw(clk->enable_reg); - regval16 |= (1 << clk->enable_bit); - __raw_writew(regval16, clk->enable_reg); - } else { - regval16 = omap_readw(clk->enable_reg); - regval16 |= (1 << clk->enable_bit); - omap_writew(regval16, clk->enable_reg); - } + regval16 = __raw_readw(clk->enable_reg); + regval16 |= (1 << clk->enable_bit); + __raw_writew(regval16, clk->enable_reg); } return 0; @@ -679,25 +667,13 @@ static void omap1_clk_disable_generic(struct clk *clk) return; if (clk->flags & ENABLE_REG_32BIT) { - if (clk->flags & VIRTUAL_IO_ADDRESS) { - regval32 = __raw_readl(clk->enable_reg); - regval32 &= ~(1 << clk->enable_bit); - __raw_writel(regval32, clk->enable_reg); - } else { - regval32 = omap_readl(clk->enable_reg); - regval32 &= ~(1 << clk->enable_bit); - omap_writel(regval32, clk->enable_reg); - } + regval32 = __raw_readl(clk->enable_reg); + regval32 &= ~(1 << clk->enable_bit); + __raw_writel(regval32, clk->enable_reg); } else { - if (clk->flags & VIRTUAL_IO_ADDRESS) { - regval16 = __raw_readw(clk->enable_reg); - regval16 &= ~(1 << clk->enable_bit); - __raw_writew(regval16, clk->enable_reg); - } else { - regval16 = omap_readw(clk->enable_reg); - regval16 &= ~(1 << clk->enable_bit); - omap_writew(regval16, clk->enable_reg); - } + regval16 = __raw_readw(clk->enable_reg); + regval16 &= ~(1 << clk->enable_bit); + __raw_writew(regval16, clk->enable_reg); } } @@ -745,17 +721,10 @@ static void __init omap1_clk_disable_unused(struct clk *clk) } /* Is the clock already disabled? */ - if (clk->flags & ENABLE_REG_32BIT) { - if (clk->flags & VIRTUAL_IO_ADDRESS) - regval32 = __raw_readl(clk->enable_reg); - else - regval32 = omap_readl(clk->enable_reg); - } else { - if (clk->flags & VIRTUAL_IO_ADDRESS) - regval32 = __raw_readw(clk->enable_reg); - else - regval32 = omap_readw(clk->enable_reg); - } + if (clk->flags & ENABLE_REG_32BIT) + regval32 = __raw_readl(clk->enable_reg); + else + regval32 = __raw_readw(clk->enable_reg); if ((regval32 & (1 << clk->enable_bit)) == 0) return; diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h index ed343af5f12..1b4dd056d9b 100644 --- a/arch/arm/mach-omap1/clock.h +++ b/arch/arm/mach-omap1/clock.h @@ -165,7 +165,7 @@ static struct arm_idlect1_clk ck_dpll1out = { .parent = &ck_dpll1, .flags = CLOCK_IDLE_CONTROL | ENABLE_REG_32BIT | RATE_PROPAGATES, - .enable_reg = (void __iomem *)ARM_IDLECT2, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), .enable_bit = EN_CKOUT_ARM, .recalc = &followparent_recalc, }, @@ -177,7 +177,7 @@ static struct clk sossi_ck = { .ops = &clkops_generic, .parent = &ck_dpll1out.clk, .flags = CLOCK_NO_IDLE_PARENT | ENABLE_REG_32BIT, - .enable_reg = (void __iomem *)MOD_CONF_CTRL_1, + .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1), .enable_bit = 16, .recalc = &omap1_sossi_recalc, .set_rate = &omap1_set_sossi_rate, @@ -200,7 +200,7 @@ static struct arm_idlect1_clk armper_ck = { .ops = &clkops_generic, .parent = &ck_dpll1, .flags = CLOCK_IDLE_CONTROL, - .enable_reg = (void __iomem *)ARM_IDLECT2, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), .enable_bit = EN_PERCK, .rate_offset = CKCTL_PERDIV_OFFSET, .recalc = &omap1_ckctl_recalc, @@ -214,7 +214,7 @@ static struct clk arm_gpio_ck = { .name = "arm_gpio_ck", .ops = &clkops_generic, .parent = &ck_dpll1, - .enable_reg = (void __iomem *)ARM_IDLECT2, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), .enable_bit = EN_GPIOCK, .recalc = &followparent_recalc, }; @@ -225,7 +225,7 @@ static struct arm_idlect1_clk armxor_ck = { .ops = &clkops_generic, .parent = &ck_ref, .flags = CLOCK_IDLE_CONTROL, - .enable_reg = (void __iomem *)ARM_IDLECT2, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), .enable_bit = EN_XORPCK, .recalc = &followparent_recalc, }, @@ -238,7 +238,7 @@ static struct arm_idlect1_clk armtim_ck = { .ops = &clkops_generic, .parent = &ck_ref, .flags = CLOCK_IDLE_CONTROL, - .enable_reg = (void __iomem *)ARM_IDLECT2, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), .enable_bit = EN_TIMCK, .recalc = &followparent_recalc, }, @@ -251,7 +251,7 @@ static struct arm_idlect1_clk armwdt_ck = { .ops = &clkops_generic, .parent = &ck_ref, .flags = CLOCK_IDLE_CONTROL, - .enable_reg = (void __iomem *)ARM_IDLECT2, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), .enable_bit = EN_WDTCK, .recalc = &omap1_watchdog_recalc, }, @@ -274,7 +274,7 @@ static struct clk dsp_ck = { .name = "dsp_ck", .ops = &clkops_generic, .parent = &ck_dpll1, - .enable_reg = (void __iomem *)ARM_CKCTL, + .enable_reg = OMAP1_IO_ADDRESS(ARM_CKCTL), .enable_bit = EN_DSPCK, .rate_offset = CKCTL_DSPDIV_OFFSET, .recalc = &omap1_ckctl_recalc, @@ -296,7 +296,6 @@ static struct clk dspper_ck = { .name = "dspper_ck", .ops = &clkops_dspck, .parent = &ck_dpll1, - .flags = VIRTUAL_IO_ADDRESS, .enable_reg = DSP_IDLECT2, .enable_bit = EN_PERCK, .rate_offset = CKCTL_PERDIV_OFFSET, @@ -309,7 +308,6 @@ static struct clk dspxor_ck = { .name = "dspxor_ck", .ops = &clkops_dspck, .parent = &ck_ref, - .flags = VIRTUAL_IO_ADDRESS, .enable_reg = DSP_IDLECT2, .enable_bit = EN_XORPCK, .recalc = &followparent_recalc, @@ -319,7 +317,6 @@ static struct clk dsptim_ck = { .name = "dsptim_ck", .ops = &clkops_dspck, .parent = &ck_ref, - .flags = VIRTUAL_IO_ADDRESS, .enable_reg = DSP_IDLECT2, .enable_bit = EN_DSPTIMCK, .recalc = &followparent_recalc, @@ -364,7 +361,7 @@ static struct clk l3_ocpi_ck = { .name = "l3_ocpi_ck", .ops = &clkops_generic, .parent = &tc_ck.clk, - .enable_reg = (void __iomem *)ARM_IDLECT3, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT3), .enable_bit = EN_OCPI_CK, .recalc = &followparent_recalc, }; @@ -373,7 +370,7 @@ static struct clk tc1_ck = { .name = "tc1_ck", .ops = &clkops_generic, .parent = &tc_ck.clk, - .enable_reg = (void __iomem *)ARM_IDLECT3, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT3), .enable_bit = EN_TC1_CK, .recalc = &followparent_recalc, }; @@ -382,7 +379,7 @@ static struct clk tc2_ck = { .name = "tc2_ck", .ops = &clkops_generic, .parent = &tc_ck.clk, - .enable_reg = (void __iomem *)ARM_IDLECT3, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT3), .enable_bit = EN_TC2_CK, .recalc = &followparent_recalc, }; @@ -408,7 +405,7 @@ static struct arm_idlect1_clk api_ck = { .ops = &clkops_generic, .parent = &tc_ck.clk, .flags = CLOCK_IDLE_CONTROL, - .enable_reg = (void __iomem *)ARM_IDLECT2, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), .enable_bit = EN_APICK, .recalc = &followparent_recalc, }, @@ -421,7 +418,7 @@ static struct arm_idlect1_clk lb_ck = { .ops = &clkops_generic, .parent = &tc_ck.clk, .flags = CLOCK_IDLE_CONTROL, - .enable_reg = (void __iomem *)ARM_IDLECT2, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), .enable_bit = EN_LBCK, .recalc = &followparent_recalc, }, @@ -446,7 +443,7 @@ static struct clk lcd_ck_16xx = { .name = "lcd_ck", .ops = &clkops_generic, .parent = &ck_dpll1, - .enable_reg = (void __iomem *)ARM_IDLECT2, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), .enable_bit = EN_LCDCK, .rate_offset = CKCTL_LCDDIV_OFFSET, .recalc = &omap1_ckctl_recalc, @@ -460,7 +457,7 @@ static struct arm_idlect1_clk lcd_ck_1510 = { .ops = &clkops_generic, .parent = &ck_dpll1, .flags = CLOCK_IDLE_CONTROL, - .enable_reg = (void __iomem *)ARM_IDLECT2, + .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), .enable_bit = EN_LCDCK, .rate_offset = CKCTL_LCDDIV_OFFSET, .recalc = &omap1_ckctl_recalc, @@ -477,7 +474,7 @@ static struct clk uart1_1510 = { .parent = &armper_ck.clk, .rate = 12000000, .flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, - .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, + .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), .enable_bit = 29, /* Chooses between 12MHz and 48MHz */ .set_rate = &omap1_set_uart_rate, .recalc = &omap1_uart_recalc, @@ -492,7 +489,7 @@ static struct uart_clk uart1_16xx = { .rate = 48000000, .flags = RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, - .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, + .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), .enable_bit = 29, }, .sysc_addr = 0xfffb0054, @@ -505,7 +502,7 @@ static struct clk uart2_ck = { .parent = &armper_ck.clk, .rate = 12000000, .flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, - .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, + .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), .enable_bit = 30, /* Chooses between 12MHz and 48MHz */ .set_rate = &omap1_set_uart_rate, .recalc = &omap1_uart_recalc, @@ -518,7 +515,7 @@ static struct clk uart3_1510 = { .parent = &armper_ck.clk, .rate = 12000000, .flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, - .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, + .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), .enable_bit = 31, /* Chooses between 12MHz and 48MHz */ .set_rate = &omap1_set_uart_rate, .recalc = &omap1_uart_recalc, @@ -533,7 +530,7 @@ static struct uart_clk uart3_16xx = { .rate = 48000000, .flags = RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, - .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, + .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), .enable_bit = 31, }, .sysc_addr = 0xfffb9854, @@ -545,7 +542,7 @@ static struct clk usb_clko = { /* 6 MHz output on W4_USB_CLKO */ /* Direct from ULPD, no parent */ .rate = 6000000, .flags = RATE_FIXED | ENABLE_REG_32BIT, - .enable_reg = (void __iomem *)ULPD_CLOCK_CTRL, + .enable_reg = OMAP1_IO_ADDRESS(ULPD_CLOCK_CTRL), .enable_bit = USB_MCLK_EN_BIT, }; @@ -555,7 +552,7 @@ static struct clk usb_hhc_ck1510 = { /* Direct from ULPD, no parent */ .rate = 48000000, /* Actually 2 clocks, 12MHz and 48MHz */ .flags = RATE_FIXED | ENABLE_REG_32BIT, - .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, + .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), .enable_bit = USB_HOST_HHC_UHOST_EN, }; @@ -566,7 +563,7 @@ static struct clk usb_hhc_ck16xx = { .rate = 48000000, /* OTG_SYSCON_2.OTG_PADEN == 0 (not 1510-compatible) */ .flags = RATE_FIXED | ENABLE_REG_32BIT, - .enable_reg = (void __iomem *)OTG_BASE + 0x08 /* OTG_SYSCON_2 */, + .enable_reg = OMAP1_IO_ADDRESS(OTG_BASE + 0x08), /* OTG_SYSCON_2 */ .enable_bit = 8 /* UHOST_EN */, }; @@ -576,7 +573,7 @@ static struct clk usb_dc_ck = { /* Direct from ULPD, no parent */ .rate = 48000000, .flags = RATE_FIXED, - .enable_reg = (void __iomem *)SOFT_REQ_REG, + .enable_reg = OMAP1_IO_ADDRESS(SOFT_REQ_REG), .enable_bit = 4, }; @@ -586,15 +583,15 @@ static struct clk mclk_1510 = { /* Direct from ULPD, no parent. May be enabled by ext hardware. */ .rate = 12000000, .flags = RATE_FIXED, - .enable_reg = (void __iomem *)SOFT_REQ_REG, - .enable_bit = 6, + .enable_reg = OMAP1_IO_ADDRESS(SOFT_REQ_REG), + .enable_bit = 6, }; static struct clk mclk_16xx = { .name = "mclk", .ops = &clkops_generic, /* Direct from ULPD, no parent. May be enabled by ext hardware. */ - .enable_reg = (void __iomem *)COM_CLK_DIV_CTRL_SEL, + .enable_reg = OMAP1_IO_ADDRESS(COM_CLK_DIV_CTRL_SEL), .enable_bit = COM_ULPD_PLL_CLK_REQ, .set_rate = &omap1_set_ext_clk_rate, .round_rate = &omap1_round_ext_clk_rate, @@ -613,7 +610,7 @@ static struct clk bclk_16xx = { .name = "bclk", .ops = &clkops_generic, /* Direct from ULPD, no parent. May be enabled by ext hardware. */ - .enable_reg = (void __iomem *)SWD_CLK_DIV_CTRL_SEL, + .enable_reg = OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL), .enable_bit = SWD_ULPD_PLL_CLK_REQ, .set_rate = &omap1_set_ext_clk_rate, .round_rate = &omap1_round_ext_clk_rate, @@ -627,7 +624,7 @@ static struct clk mmc1_ck = { .parent = &armper_ck.clk, .rate = 48000000, .flags = RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, - .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, + .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), .enable_bit = 23, }; @@ -639,7 +636,7 @@ static struct clk mmc2_ck = { .parent = &armper_ck.clk, .rate = 48000000, .flags = RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, - .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, + .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), .enable_bit = 20, }; diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index cd69111cd33..8705902de1d 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -134,7 +134,6 @@ extern const struct clkops clkops_null; #define RATE_PROPAGATES (1 << 2) /* Program children too */ /* bits 3-4 are free */ #define ENABLE_REG_32BIT (1 << 5) /* Use 32-bit access */ -#define VIRTUAL_IO_ADDRESS (1 << 6) /* Clock in virtual address */ #define CLOCK_IDLE_CONTROL (1 << 7) #define CLOCK_NO_IDLE_PARENT (1 << 8) #define DELAYED_APP (1 << 9) /* Delay application of clock */ -- GitLab From f8de9b2c45c4506702da4bd3a5bc7630754077f9 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 28 Jan 2009 12:27:31 -0700 Subject: [PATCH 1392/4982] [ARM] OMAP2 SDRC: move mach-omap2/memory.h into mach/sdrc.h Move the contents of the arch/arm/mach-omap2/memory.h file to the existing mach/sdrc.h file, and remove memory.h. Modify files which include memory.h to include asm/arch/sdrc.h instead. linux-omap source commit is e7ae2d89921372fc4b9712a32cc401d645597807. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock.c | 2 +- arch/arm/mach-omap2/clock24xx.c | 2 +- arch/arm/mach-omap2/clock34xx.c | 2 +- arch/arm/mach-omap2/io.c | 4 +-- arch/arm/mach-omap2/memory.c | 9 +++++- arch/arm/mach-omap2/memory.h | 43 -------------------------- arch/arm/plat-omap/include/mach/gpmc.h | 2 +- arch/arm/plat-omap/include/mach/sdrc.h | 21 +++++++++++++ 8 files changed, 35 insertions(+), 50 deletions(-) delete mode 100644 arch/arm/mach-omap2/memory.h diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 5d7d4c52f37..18fddb660ff 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -29,7 +29,7 @@ #include #include -#include "memory.h" +#include #include "sdrc.h" #include "clock.h" #include "prm.h" diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index b9902666e4b..83911ad4873 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -33,7 +33,7 @@ #include #include -#include "memory.h" +#include #include "clock.h" #include "prm.h" #include "prm-regbits-24xx.h" diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 3d756babb2f..52385b1506e 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -32,7 +32,7 @@ #include #include -#include "memory.h" +#include #include "clock.h" #include "prm.h" #include "prm-regbits-34xx.h" diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 5ea64f926ed..2b5f28a3c4b 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -27,8 +27,8 @@ #include #include #include - -#include "memory.h" +#include +#include #include "clock.h" diff --git a/arch/arm/mach-omap2/memory.c b/arch/arm/mach-omap2/memory.c index 882c7022429..93cb25715ba 100644 --- a/arch/arm/mach-omap2/memory.c +++ b/arch/arm/mach-omap2/memory.c @@ -29,9 +29,16 @@ #include "prm.h" -#include "memory.h" +#include #include "sdrc.h" +/* Memory timing, DLL mode flags */ +#define M_DDR 1 +#define M_LOCK_CTRL (1 << 2) +#define M_UNLOCK 0 +#define M_LOCK 1 + + void __iomem *omap2_sdrc_base; void __iomem *omap2_sms_base; diff --git a/arch/arm/mach-omap2/memory.h b/arch/arm/mach-omap2/memory.h deleted file mode 100644 index bb3db80a7c4..00000000000 --- a/arch/arm/mach-omap2/memory.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * linux/arch/arm/mach-omap2/memory.h - * - * Interface for memory timing related functions for OMAP24XX - * - * Copyright (C) 2005 Texas Instruments Inc. - * Richard Woodruff - * - * Copyright (C) 2005 Nokia Corporation - * Tony Lindgren - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef ARCH_ARM_MACH_OMAP2_MEMORY_H -#define ARCH_ARM_MACH_OMAP2_MEMORY_H - -/* Memory timings */ -#define M_DDR 1 -#define M_LOCK_CTRL (1 << 2) -#define M_UNLOCK 0 -#define M_LOCK 1 - -struct memory_timings { - u32 m_type; /* ddr = 1, sdr = 0 */ - u32 dll_mode; /* use lock mode = 1, unlock mode = 0 */ - u32 slow_dll_ctrl; /* unlock mode, dll value for slow speed */ - u32 fast_dll_ctrl; /* unlock mode, dll value for fast speed */ - u32 base_cs; /* base chip select to use for calculations */ -}; - -extern void omap2_init_memory_params(u32 force_lock_to_unlock_mode); -extern u32 omap2_memory_get_slow_dll_ctrl(void); -extern u32 omap2_memory_get_fast_dll_ctrl(void); -extern u32 omap2_memory_get_type(void); -u32 omap2_dll_force_needed(void); -u32 omap2_reprogram_sdrc(u32 level, u32 force); -void __init omap2_init_memory(void); -void __init gpmc_init(void); - -#endif diff --git a/arch/arm/plat-omap/include/mach/gpmc.h b/arch/arm/plat-omap/include/mach/gpmc.h index 45b678439bb..921b16532ff 100644 --- a/arch/arm/plat-omap/include/mach/gpmc.h +++ b/arch/arm/plat-omap/include/mach/gpmc.h @@ -103,6 +103,6 @@ extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base); extern void gpmc_cs_free(int cs); extern int gpmc_cs_set_reserved(int cs, int reserved); extern int gpmc_cs_reserved(int cs); -extern void gpmc_init(void); +extern void __init gpmc_init(void); #endif diff --git a/arch/arm/plat-omap/include/mach/sdrc.h b/arch/arm/plat-omap/include/mach/sdrc.h index a98c6c3beb2..c905b5268e5 100644 --- a/arch/arm/plat-omap/include/mach/sdrc.h +++ b/arch/arm/plat-omap/include/mach/sdrc.h @@ -74,4 +74,25 @@ #define SMS_SYSCONFIG 0x010 /* REVISIT: fill in other SMS registers here */ +#ifndef __ASSEMBLER__ + +struct memory_timings { + u32 m_type; /* ddr = 1, sdr = 0 */ + u32 dll_mode; /* use lock mode = 1, unlock mode = 0 */ + u32 slow_dll_ctrl; /* unlock mode, dll value for slow speed */ + u32 fast_dll_ctrl; /* unlock mode, dll value for fast speed */ + u32 base_cs; /* base chip select to use for calculations */ +}; + +extern void omap2_init_memory_params(u32 force_lock_to_unlock_mode); +extern u32 omap2_memory_get_slow_dll_ctrl(void); +extern u32 omap2_memory_get_fast_dll_ctrl(void); +extern u32 omap2_memory_get_type(void); +u32 omap2_dll_force_needed(void); +u32 omap2_reprogram_sdrc(u32 level, u32 force); +void __init omap2_init_memory(void); + +#endif + + #endif -- GitLab From 96609ef4009515f0667a52b7776c21418df19bd8 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 28 Jan 2009 12:27:34 -0700 Subject: [PATCH 1393/4982] [ARM] OMAP2 SDRC: rename memory.c to sdrc2xxx.c Rename arch/arm/mach-omap2/memory.c to arch/arm/mach-omap2/sdrc2xxx.c, since it contains exclusively SDRAM-related functions. Most of the functions are also OMAP2xxx-specific - those which are common will be separated out in a following patch. linux-omap source commit is fe212f797e2efef9dc88bcb5db7cf9db3f9f562e. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/Makefile | 2 +- arch/arm/mach-omap2/{memory.c => sdrc2xxx.c} | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) rename arch/arm/mach-omap2/{memory.c => sdrc2xxx.c} (95%) diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index bbd12bc10fd..bb47d43af39 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -3,7 +3,7 @@ # # Common support -obj-y := irq.o id.o io.o memory.o control.o prcm.o clock.o mux.o \ +obj-y := irq.o id.o io.o sdrc2xxx.o control.o prcm.o clock.o mux.o \ devices.o serial.o gpmc.o timer-gp.o powerdomain.o \ clockdomain.o diff --git a/arch/arm/mach-omap2/memory.c b/arch/arm/mach-omap2/sdrc2xxx.c similarity index 95% rename from arch/arm/mach-omap2/memory.c rename to arch/arm/mach-omap2/sdrc2xxx.c index 93cb25715ba..3e38aa4ea45 100644 --- a/arch/arm/mach-omap2/memory.c +++ b/arch/arm/mach-omap2/sdrc2xxx.c @@ -1,7 +1,7 @@ /* - * linux/arch/arm/mach-omap2/memory.c + * linux/arch/arm/mach-omap2/sdrc2xxx.c * - * Memory timing related functions for OMAP24XX + * SDRAM timing related functions for OMAP2xxx * * Copyright (C) 2005 Texas Instruments Inc. * Richard Woodruff @@ -89,13 +89,12 @@ u32 omap2_reprogram_sdrc(u32 level, u32 force) if ((curr_perf_level == level) && !force) return prev; - if (level == CORE_CLK_SRC_DPLL) { + if (level == CORE_CLK_SRC_DPLL) dll_ctrl = omap2_memory_get_slow_dll_ctrl(); - } else if (level == CORE_CLK_SRC_DPLL_X2) { + else if (level == CORE_CLK_SRC_DPLL_X2) dll_ctrl = omap2_memory_get_fast_dll_ctrl(); - } else { + else return prev; - } m_type = omap2_memory_get_type(); @@ -124,7 +123,8 @@ void omap2_init_memory_params(u32 force_lock_to_unlock_mode) unsigned long dll_cnt; u32 fast_dll = 0; - mem_timings.m_type = !((sdrc_read_reg(SDRC_MR_0) & 0x3) == 0x1); /* DDR = 1, SDR = 0 */ + /* DDR = 1, SDR = 0 */ + mem_timings.m_type = !((sdrc_read_reg(SDRC_MR_0) & 0x3) == 0x1); /* 2422 es2.05 and beyond has a single SIP DDR instead of 2 like others. * In the case of 2422, its ok to use CS1 instead of CS0. -- GitLab From f2ab99778a1a04ddbae38f4de4ef40f2edb92080 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 28 Jan 2009 12:27:37 -0700 Subject: [PATCH 1394/4982] [ARM] OMAP2 SDRC: separate common OMAP2/3 code from OMAP2xxx code Separate SDRC code common to OMAP2/3 from mach-omap2/sdrc2xxx.c to mach-omap2/sdrc.c. Rename the OMAP2xxx-specific functions to use an 'omap2xxx' prefix rather than an 'omap2' prefix, and use "sdrc" in the function names rather than "memory." Mark several functions as static that should not be used outside the sdrc2xxx.c file. linux-omap source commit is bf1612b9d8d29379558500cd5de9ae0367c41fc4. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/Makefile | 6 ++- arch/arm/mach-omap2/clock24xx.c | 23 ++++---- arch/arm/mach-omap2/io.c | 2 +- arch/arm/mach-omap2/sdrc.c | 57 ++++++++++++++++++++ arch/arm/mach-omap2/sdrc2xxx.c | 67 ++++++------------------ arch/arm/plat-omap/common.c | 2 +- arch/arm/plat-omap/include/mach/common.h | 2 +- arch/arm/plat-omap/include/mach/sdrc.h | 37 +++++++------ 8 files changed, 115 insertions(+), 81 deletions(-) create mode 100644 arch/arm/mach-omap2/sdrc.c diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index bb47d43af39..9717afcdbda 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -3,7 +3,7 @@ # # Common support -obj-y := irq.o id.o io.o sdrc2xxx.o control.o prcm.o clock.o mux.o \ +obj-y := irq.o id.o io.o sdrc.o control.o prcm.o clock.o mux.o \ devices.o serial.o gpmc.o timer-gp.o powerdomain.o \ clockdomain.o @@ -14,6 +14,10 @@ obj-$(CONFIG_ARCH_OMAP2420) += sram242x.o obj-$(CONFIG_ARCH_OMAP2430) += sram243x.o obj-$(CONFIG_ARCH_OMAP3) += sram34xx.o +# SMS/SDRC +obj-$(CONFIG_ARCH_OMAP2) += sdrc2xxx.o +# obj-$(CONFIG_ARCH_OMAP3) += sdrc3xxx.o + # Power Management ifeq ($(CONFIG_PM),y) obj-y += pm.o diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index 83911ad4873..a11e7c71177 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -389,9 +389,9 @@ static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate) mult &= OMAP24XX_CORE_CLK_SRC_MASK; if ((rate == (cur_rate / 2)) && (mult == 2)) { - omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1); + omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1); } else if ((rate == (cur_rate * 2)) && (mult == 1)) { - omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1); + omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1); } else if (rate != cur_rate) { valid_rate = omap2_dpllcore_round_rate(rate); if (valid_rate != rate) @@ -430,15 +430,16 @@ static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate) if (rate == curr_prcm_set->xtal_speed) /* If asking for 1-1 */ bypass = 1; - omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1); /* For init_mem */ + /* For omap2xxx_sdrc_init_params() */ + omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1); /* Force dll lock mode */ omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr, bypass); /* Errata: ret dll entry state */ - omap2_init_memory_params(omap2_dll_force_needed()); - omap2_reprogram_sdrc(done_rate, 0); + omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked()); + omap2xxx_sdrc_reprogram(done_rate, 0); } omap2_dpllcore_recalc(&dpll_ck); ret = 0; @@ -525,9 +526,9 @@ static int omap2_select_table_rate(struct clk *clk, unsigned long rate) cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck); if (prcm->dpll_speed == cur_rate / 2) { - omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1); + omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1); } else if (prcm->dpll_speed == cur_rate * 2) { - omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1); + omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1); } else if (prcm->dpll_speed != cur_rate) { local_irq_save(flags); @@ -558,14 +559,14 @@ static int omap2_select_table_rate(struct clk *clk, unsigned long rate) cm_write_mod_reg(prcm->cm_clksel_mdm, OMAP2430_MDM_MOD, CM_CLKSEL); - /* x2 to enter init_mem */ - omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1); + /* x2 to enter omap2xxx_sdrc_init_params() */ + omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1); omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr, bypass); - omap2_init_memory_params(omap2_dll_force_needed()); - omap2_reprogram_sdrc(done_rate, 0); + omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked()); + omap2xxx_sdrc_reprogram(done_rate, 0); local_irq_restore(flags); } diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 2b5f28a3c4b..3c1de3615eb 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -201,6 +201,6 @@ void __init omap2_init_common_hw(void) pwrdm_init(powerdomains_omap); clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps); omap2_clk_init(); - omap2_init_memory(); + omap2_sdrc_init(); gpmc_init(); } diff --git a/arch/arm/mach-omap2/sdrc.c b/arch/arm/mach-omap2/sdrc.c new file mode 100644 index 00000000000..24b54d50b89 --- /dev/null +++ b/arch/arm/mach-omap2/sdrc.c @@ -0,0 +1,57 @@ +/* + * SMS/SDRC (SDRAM controller) common code for OMAP2/3 + * + * Copyright (C) 2005, 2008 Texas Instruments Inc. + * Copyright (C) 2005, 2008 Nokia Corporation + * + * Tony Lindgren + * Paul Walmsley + * Richard Woodruff + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "prm.h" + +#include +#include "sdrc.h" + +void __iomem *omap2_sdrc_base; +void __iomem *omap2_sms_base; + +void __init omap2_set_globals_sdrc(struct omap_globals *omap2_globals) +{ + omap2_sdrc_base = omap2_globals->sdrc; + omap2_sms_base = omap2_globals->sms; +} + +/* turn on smart idle modes for SDRAM scheduler and controller */ +void __init omap2_sdrc_init(void) +{ + u32 l; + + l = sms_read_reg(SMS_SYSCONFIG); + l &= ~(0x3 << 3); + l |= (0x2 << 3); + sms_write_reg(l, SMS_SYSCONFIG); + + l = sdrc_read_reg(SDRC_SYSCONFIG); + l &= ~(0x3 << 3); + l |= (0x2 << 3); + sdrc_write_reg(l, SDRC_SYSCONFIG); +} diff --git a/arch/arm/mach-omap2/sdrc2xxx.c b/arch/arm/mach-omap2/sdrc2xxx.c index 3e38aa4ea45..3a47aba2903 100644 --- a/arch/arm/mach-omap2/sdrc2xxx.c +++ b/arch/arm/mach-omap2/sdrc2xxx.c @@ -3,11 +3,12 @@ * * SDRAM timing related functions for OMAP2xxx * - * Copyright (C) 2005 Texas Instruments Inc. - * Richard Woodruff + * Copyright (C) 2005, 2008 Texas Instruments Inc. + * Copyright (C) 2005, 2008 Nokia Corporation * - * Copyright (C) 2005 Nokia Corporation * Tony Lindgren + * Paul Walmsley + * Richard Woodruff * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -39,23 +40,20 @@ #define M_LOCK 1 -void __iomem *omap2_sdrc_base; -void __iomem *omap2_sms_base; - static struct memory_timings mem_timings; static u32 curr_perf_level = CORE_CLK_SRC_DPLL_X2; -u32 omap2_memory_get_slow_dll_ctrl(void) +static u32 omap2xxx_sdrc_get_slow_dll_ctrl(void) { return mem_timings.slow_dll_ctrl; } -u32 omap2_memory_get_fast_dll_ctrl(void) +static u32 omap2xxx_sdrc_get_fast_dll_ctrl(void) { return mem_timings.fast_dll_ctrl; } -u32 omap2_memory_get_type(void) +static u32 omap2xxx_sdrc_get_type(void) { return mem_timings.m_type; } @@ -64,7 +62,7 @@ u32 omap2_memory_get_type(void) * Check the DLL lock state, and return tue if running in unlock mode. * This is needed to compensate for the shifted DLL value in unlock mode. */ -u32 omap2_dll_force_needed(void) +u32 omap2xxx_sdrc_dll_is_unlocked(void) { /* dlla and dllb are a set */ u32 dll_state = sdrc_read_reg(SDRC_DLLA_CTRL); @@ -79,8 +77,10 @@ u32 omap2_dll_force_needed(void) * 'level' is the value to store to CM_CLKSEL2_PLL.CORE_CLK_SRC. * Practical values are CORE_CLK_SRC_DPLL (for CORE_CLK = DPLL_CLK) or * CORE_CLK_SRC_DPLL_X2 (for CORE_CLK = * DPLL_CLK * 2) + * + * Used by the clock framework during CORE DPLL changes */ -u32 omap2_reprogram_sdrc(u32 level, u32 force) +u32 omap2xxx_sdrc_reprogram(u32 level, u32 force) { u32 dll_ctrl, m_type; u32 prev = curr_perf_level; @@ -90,13 +90,13 @@ u32 omap2_reprogram_sdrc(u32 level, u32 force) return prev; if (level == CORE_CLK_SRC_DPLL) - dll_ctrl = omap2_memory_get_slow_dll_ctrl(); + dll_ctrl = omap2xxx_sdrc_get_slow_dll_ctrl(); else if (level == CORE_CLK_SRC_DPLL_X2) - dll_ctrl = omap2_memory_get_fast_dll_ctrl(); + dll_ctrl = omap2xxx_sdrc_get_fast_dll_ctrl(); else return prev; - m_type = omap2_memory_get_type(); + m_type = omap2xxx_sdrc_get_type(); local_irq_save(flags); __raw_writel(0xffff, OMAP24XX_PRCM_VOLTSETUP); @@ -107,18 +107,8 @@ u32 omap2_reprogram_sdrc(u32 level, u32 force) return prev; } -#if !defined(CONFIG_ARCH_OMAP2) -void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl, - u32 base_cs, u32 force_unlock) -{ -} -void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val, - u32 mem_type) -{ -} -#endif - -void omap2_init_memory_params(u32 force_lock_to_unlock_mode) +/* Used by the clock framework during CORE DPLL changes */ +void omap2xxx_sdrc_init_params(u32 force_lock_to_unlock_mode) { unsigned long dll_cnt; u32 fast_dll = 0; @@ -171,28 +161,3 @@ void omap2_init_memory_params(u32 force_lock_to_unlock_mode) /* 90 degree phase for anything below 133Mhz + disable DLL filter */ mem_timings.slow_dll_ctrl |= ((1 << 1) | (3 << 8)); } - -void __init omap2_set_globals_memory(struct omap_globals *omap2_globals) -{ - omap2_sdrc_base = omap2_globals->sdrc; - omap2_sms_base = omap2_globals->sms; -} - -/* turn on smart idle modes for SDRAM scheduler and controller */ -void __init omap2_init_memory(void) -{ - u32 l; - - if (!cpu_is_omap2420()) - return; - - l = sms_read_reg(SMS_SYSCONFIG); - l &= ~(0x3 << 3); - l |= (0x2 << 3); - sms_write_reg(l, SMS_SYSCONFIG); - - l = sdrc_read_reg(SDRC_SYSCONFIG); - l &= ~(0x3 << 3); - l |= (0x2 << 3); - sdrc_write_reg(l, SDRC_SYSCONFIG); -} diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c index 0843b8882f9..187239c054c 100644 --- a/arch/arm/plat-omap/common.c +++ b/arch/arm/plat-omap/common.c @@ -249,7 +249,7 @@ static struct omap_globals *omap2_globals; static void __init __omap2_set_globals(void) { omap2_set_globals_tap(omap2_globals); - omap2_set_globals_memory(omap2_globals); + omap2_set_globals_sdrc(omap2_globals); omap2_set_globals_control(omap2_globals); omap2_set_globals_prcm(omap2_globals); } diff --git a/arch/arm/plat-omap/include/mach/common.h b/arch/arm/plat-omap/include/mach/common.h index ef70e2b0f05..f3444a66a57 100644 --- a/arch/arm/plat-omap/include/mach/common.h +++ b/arch/arm/plat-omap/include/mach/common.h @@ -65,7 +65,7 @@ void omap2_set_globals_343x(void); /* These get called from omap2_set_globals_xxxx(), do not call these */ void omap2_set_globals_tap(struct omap_globals *); -void omap2_set_globals_memory(struct omap_globals *); +void omap2_set_globals_sdrc(struct omap_globals *); void omap2_set_globals_control(struct omap_globals *); void omap2_set_globals_prcm(struct omap_globals *); diff --git a/arch/arm/plat-omap/include/mach/sdrc.h b/arch/arm/plat-omap/include/mach/sdrc.h index c905b5268e5..8e0740eb83f 100644 --- a/arch/arm/plat-omap/include/mach/sdrc.h +++ b/arch/arm/plat-omap/include/mach/sdrc.h @@ -4,10 +4,12 @@ /* * OMAP2/3 SDRC/SMS register definitions * - * Copyright (C) 2007 Texas Instruments, Inc. - * Copyright (C) 2007 Nokia Corporation + * Copyright (C) 2007-2008 Texas Instruments, Inc. + * Copyright (C) 2007-2008 Nokia Corporation * - * Written by Paul Walmsley + * Tony Lindgren + * Paul Walmsley + * Richard Woodruff * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -64,18 +66,25 @@ * SMS register access */ - -#define OMAP242X_SMS_REGADDR(reg) IO_ADDRESS(OMAP2420_SMS_BASE + reg) -#define OMAP243X_SMS_REGADDR(reg) IO_ADDRESS(OMAP243X_SMS_BASE + reg) -#define OMAP343X_SMS_REGADDR(reg) IO_ADDRESS(OMAP343X_SMS_BASE + reg) +#define OMAP242X_SMS_REGADDR(reg) \ + (void __iomem *)IO_ADDRESS(OMAP2420_SMS_BASE + reg) +#define OMAP243X_SMS_REGADDR(reg) \ + (void __iomem *)IO_ADDRESS(OMAP243X_SMS_BASE + reg) +#define OMAP343X_SMS_REGADDR(reg) \ + (void __iomem *)IO_ADDRESS(OMAP343X_SMS_BASE + reg) /* SMS register offsets - read/write with sms_{read,write}_reg() */ #define SMS_SYSCONFIG 0x010 /* REVISIT: fill in other SMS registers here */ + #ifndef __ASSEMBLER__ +void __init omap2_sdrc_init(void); + +#ifdef CONFIG_ARCH_OMAP2 + struct memory_timings { u32 m_type; /* ddr = 1, sdr = 0 */ u32 dll_mode; /* use lock mode = 1, unlock mode = 0 */ @@ -84,15 +93,13 @@ struct memory_timings { u32 base_cs; /* base chip select to use for calculations */ }; -extern void omap2_init_memory_params(u32 force_lock_to_unlock_mode); -extern u32 omap2_memory_get_slow_dll_ctrl(void); -extern u32 omap2_memory_get_fast_dll_ctrl(void); -extern u32 omap2_memory_get_type(void); -u32 omap2_dll_force_needed(void); -u32 omap2_reprogram_sdrc(u32 level, u32 force); -void __init omap2_init_memory(void); +extern void omap2xxx_sdrc_init_params(u32 force_lock_to_unlock_mode); -#endif +u32 omap2xxx_sdrc_dll_is_unlocked(void); +u32 omap2xxx_sdrc_reprogram(u32 level, u32 force); + +#endif /* CONFIG_ARCH_OMAP2 */ +#endif /* __ASSEMBLER__ */ #endif -- GitLab From 87246b7567f7d1951bfcea29875523ef435c0ebf Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 28 Jan 2009 12:27:39 -0700 Subject: [PATCH 1395/4982] [ARM] OMAP2 SDRC: add SDRAM timing parameter infrastructure For a given SDRAM clock rate, SDRAM chips require memory controllers to use a specific set of timing minimums and maximums to transfer data reliably. These parameters can be different for different memory chips and can also potentially vary by board. This patch adds the infrastructure for board-*.c files to pass this timing data to the SDRAM controller init function. The timing data is specified in an 'omap_sdrc_params' structure, in terms of SDRC controller register values. An array of these structs, one per SDRC target clock rate, is passed by the board-*.c file to omap2_init_common_hw(). This patch does not define the values for different memory chips, nor does it use the values for anything; those will come in subsequent patches. linux-omap source commit is bc84ecfc795c2d1c5cda8da4127cf972f488a696. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/board-2430sdp.c | 2 +- arch/arm/mach-omap2/board-apollon.c | 2 +- arch/arm/mach-omap2/board-generic.c | 2 +- arch/arm/mach-omap2/board-h4.c | 2 +- arch/arm/mach-omap2/board-ldp.c | 2 +- arch/arm/mach-omap2/board-omap3beagle.c | 2 +- arch/arm/mach-omap2/io.c | 4 +-- arch/arm/mach-omap2/sdrc.c | 38 ++++++++++++++++++++++++- arch/arm/plat-omap/include/mach/io.h | 4 ++- arch/arm/plat-omap/include/mach/sdrc.h | 24 +++++++++++++++- 10 files changed, 71 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index 83fa37211d7..7b29e1d00f2 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -185,7 +185,7 @@ out: static void __init omap_2430sdp_init_irq(void) { - omap2_init_common_hw(); + omap2_init_common_hw(NULL); omap_init_irq(); omap_gpio_init(); sdp2430_init_smc91x(); diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c index 0a7b24ba165..0c911f414d8 100644 --- a/arch/arm/mach-omap2/board-apollon.c +++ b/arch/arm/mach-omap2/board-apollon.c @@ -249,7 +249,7 @@ out: static void __init omap_apollon_init_irq(void) { - omap2_init_common_hw(); + omap2_init_common_hw(NULL); omap_init_irq(); omap_gpio_init(); apollon_init_smc91x(); diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c index 3b34c20d1df..3492162a65c 100644 --- a/arch/arm/mach-omap2/board-generic.c +++ b/arch/arm/mach-omap2/board-generic.c @@ -33,7 +33,7 @@ static void __init omap_generic_init_irq(void) { - omap2_init_common_hw(); + omap2_init_common_hw(NULL); omap_init_irq(); } diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c index 5e9b14675b1..ef55b45ab76 100644 --- a/arch/arm/mach-omap2/board-h4.c +++ b/arch/arm/mach-omap2/board-h4.c @@ -363,7 +363,7 @@ static void __init h4_init_flash(void) static void __init omap_h4_init_irq(void) { - omap2_init_common_hw(); + omap2_init_common_hw(NULL); omap_init_irq(); omap_gpio_init(); h4_init_flash(); diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index f6a13451d1f..61f7c365a28 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c @@ -98,7 +98,7 @@ static inline void __init ldp_init_smc911x(void) static void __init omap_ldp_init_irq(void) { - omap2_init_common_hw(); + omap2_init_common_hw(NULL); omap_init_irq(); omap_gpio_init(); ldp_init_smc911x(); diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 38c88fbe658..ad312ccf2ec 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -184,7 +184,7 @@ static int __init omap3_beagle_i2c_init(void) static void __init omap3_beagle_init_irq(void) { - omap2_init_common_hw(); + omap2_init_common_hw(NULL); omap_init_irq(); omap_gpio_init(); } diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 3c1de3615eb..916fcd3a232 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -195,12 +195,12 @@ void __init omap2_map_common_io(void) omapfb_reserve_sdram(); } -void __init omap2_init_common_hw(void) +void __init omap2_init_common_hw(struct omap_sdrc_params *sp) { omap2_mux_init(); pwrdm_init(powerdomains_omap); clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps); omap2_clk_init(); - omap2_sdrc_init(); + omap2_sdrc_init(sp); gpmc_init(); } diff --git a/arch/arm/mach-omap2/sdrc.c b/arch/arm/mach-omap2/sdrc.c index 24b54d50b89..2a30060cb4b 100644 --- a/arch/arm/mach-omap2/sdrc.c +++ b/arch/arm/mach-omap2/sdrc.c @@ -12,6 +12,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#undef DEBUG #include #include @@ -31,9 +32,42 @@ #include #include "sdrc.h" +static struct omap_sdrc_params *sdrc_init_params; + void __iomem *omap2_sdrc_base; void __iomem *omap2_sms_base; + +/** + * omap2_sdrc_get_params - return SDRC register values for a given clock rate + * @r: SDRC clock rate (in Hz) + * + * Return pre-calculated values for the SDRC_ACTIM_CTRLA, + * SDRC_ACTIM_CTRLB, SDRC_RFR_CTRL, and SDRC_MR registers, for a given + * SDRC clock rate 'r'. These parameters control various timing + * delays in the SDRAM controller that are expressed in terms of the + * number of SDRC clock cycles to wait; hence the clock rate + * dependency. Note that sdrc_init_params must be sorted rate + * descending. Also assumes that both chip-selects use the same + * timing parameters. Returns a struct omap_sdrc_params * upon + * success, or NULL upon failure. + */ +struct omap_sdrc_params *omap2_sdrc_get_params(unsigned long r) +{ + struct omap_sdrc_params *sp; + + sp = sdrc_init_params; + + while (sp->rate != r) + sp++; + + if (!sp->rate) + return NULL; + + return sp; +} + + void __init omap2_set_globals_sdrc(struct omap_globals *omap2_globals) { omap2_sdrc_base = omap2_globals->sdrc; @@ -41,7 +75,7 @@ void __init omap2_set_globals_sdrc(struct omap_globals *omap2_globals) } /* turn on smart idle modes for SDRAM scheduler and controller */ -void __init omap2_sdrc_init(void) +void __init omap2_sdrc_init(struct omap_sdrc_params *sp) { u32 l; @@ -54,4 +88,6 @@ void __init omap2_sdrc_init(void) l &= ~(0x3 << 3); l |= (0x2 << 3); sdrc_write_reg(l, SDRC_SYSCONFIG); + + sdrc_init_params = sp; } diff --git a/arch/arm/plat-omap/include/mach/io.h b/arch/arm/plat-omap/include/mach/io.h index d92bf796448..0610d7e2b3d 100644 --- a/arch/arm/plat-omap/include/mach/io.h +++ b/arch/arm/plat-omap/include/mach/io.h @@ -185,11 +185,13 @@ #define omap_writew(v,a) __raw_writew(v, IO_ADDRESS(a)) #define omap_writel(v,a) __raw_writel(v, IO_ADDRESS(a)) +struct omap_sdrc_params; + extern void omap1_map_common_io(void); extern void omap1_init_common_hw(void); extern void omap2_map_common_io(void); -extern void omap2_init_common_hw(void); +extern void omap2_init_common_hw(struct omap_sdrc_params *sp); #define __arch_ioremap(p,s,t) omap_ioremap(p,s,t) #define __arch_iounmap(v) omap_iounmap(v) diff --git a/arch/arm/plat-omap/include/mach/sdrc.h b/arch/arm/plat-omap/include/mach/sdrc.h index 8e0740eb83f..adc73522491 100644 --- a/arch/arm/plat-omap/include/mach/sdrc.h +++ b/arch/arm/plat-omap/include/mach/sdrc.h @@ -81,7 +81,29 @@ #ifndef __ASSEMBLER__ -void __init omap2_sdrc_init(void); +/** + * struct omap_sdrc_params - SDRC parameters for a given SDRC clock rate + * @rate: SDRC clock rate (in Hz) + * @actim_ctrla: Value to program to SDRC_ACTIM_CTRLA for this rate + * @actim_ctrlb: Value to program to SDRC_ACTIM_CTRLB for this rate + * @rfr_ctrl: Value to program to SDRC_RFR_CTRL for this rate + * @mr: Value to program to SDRC_MR for this rate + * + * This structure holds a pre-computed set of register values for the + * SDRC for a given SDRC clock rate and SDRAM chip. These are + * intended to be pre-computed and specified in an array in the board-*.c + * files. The structure is keyed off the 'rate' field. + */ +struct omap_sdrc_params { + unsigned long rate; + u32 actim_ctrla; + u32 actim_ctrlb; + u32 rfr_ctrl; + u32 mr; +}; + +void __init omap2_sdrc_init(struct omap_sdrc_params *sp); +struct omap_sdrc_params *omap2_sdrc_get_params(unsigned long r); #ifdef CONFIG_ARCH_OMAP2 -- GitLab From 0eafd4725cf5d828e76e474b8991a228bbdd3f2b Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 28 Jan 2009 12:27:42 -0700 Subject: [PATCH 1396/4982] [ARM] OMAP3 clock: add omap3_core_dpll_m2_set_rate() Add the omap3_core_dpll_m2_set_rate() function to the OMAP3 clock code, which calls into the SRAM function omap3_sram_configure_core_dpll() to change the CORE DPLL M2 divider. (SRAM code is necessary since rate changes on clocks upstream from the SDRC can glitch SDRAM accesses.) Use this function for the set_rate function pointer in the dpll3_m2_ck struct clk. With this function in place, PM/OPP code should be able to alter SDRAM speed via code similar to: clk_set_rate(&dpll3_m2_ck, target_rate). linux-omap source commit is 7f8b2b0f4fe52238c67d79dedcd2794dcef4dddd. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock34xx.c | 65 +++++++++++++++++++++++++++++++++ arch/arm/mach-omap2/clock34xx.h | 9 ++--- 2 files changed, 69 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 52385b1506e..1ad0a1359cb 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -634,6 +634,71 @@ static int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate) return omap3_noncore_dpll_set_rate(clk, rate); } + +/* + * CORE DPLL (DPLL3) rate programming functions + * + * These call into SRAM code to do the actual CM writes, since the SDRAM + * is clocked from DPLL3. + */ + +/** + * omap3_core_dpll_m2_set_rate - set CORE DPLL M2 divider + * @clk: struct clk * of DPLL to set + * @rate: rounded target rate + * + * Program the DPLL M2 divider with the rounded target rate. Returns + * -EINVAL upon error, or 0 upon success. + */ +static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate) +{ + u32 new_div = 0; + unsigned long validrate, sdrcrate; + struct omap_sdrc_params *sp; + + if (!clk || !rate) + return -EINVAL; + + if (clk != &dpll3_m2_ck) + return -EINVAL; + + if (rate == clk->rate) + return 0; + + validrate = omap2_clksel_round_rate_div(clk, rate, &new_div); + if (validrate != rate) + return -EINVAL; + + sdrcrate = sdrc_ick.rate; + if (rate > clk->rate) + sdrcrate <<= ((rate / clk->rate) - 1); + else + sdrcrate >>= ((clk->rate / rate) - 1); + + sp = omap2_sdrc_get_params(sdrcrate); + if (!sp) + return -EINVAL; + + pr_info("clock: changing CORE DPLL rate from %lu to %lu\n", clk->rate, + validrate); + pr_info("clock: SDRC timing params used: %08x %08x %08x\n", + sp->rfr_ctrl, sp->actim_ctrla, sp->actim_ctrlb); + + /* REVISIT: SRAM code doesn't support other M2 divisors yet */ + WARN_ON(new_div != 1 && new_div != 2); + + /* REVISIT: Add SDRC_MR changing to this code also */ + local_irq_disable(); + omap3_configure_core_dpll(sp->rfr_ctrl, sp->actim_ctrla, + sp->actim_ctrlb, new_div); + local_irq_enable(); + + omap2_clksel_recalc(clk); + + return 0; +} + + static const struct clkops clkops_noncore_dpll_ops = { .enable = &omap3_noncore_dpll_enable, .disable = &omap3_noncore_dpll_disable, diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index aadd296c05a..681acf0427c 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -34,6 +34,7 @@ static void omap3_dpll_deny_idle(struct clk *clk); static u32 omap3_dpll_autoidle_read(struct clk *clk); static int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate); static int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate); +static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate); /* Maximum DPLL multiplier, divider values for OMAP3 */ #define OMAP3_MAX_DPLL_MULT 2048 @@ -471,11 +472,7 @@ static const struct clksel div31_dpll3m2_clksel[] = { { .parent = NULL } }; -/* - * DPLL3 output M2 - * REVISIT: This DPLL output divider must be changed in SRAM, so until - * that code is ready, this should remain a 'read-only' clksel clock. - */ +/* DPLL3 output M2 - primary control point for CORE speed */ static struct clk dpll3_m2_ck = { .name = "dpll3_m2_ck", .ops = &clkops_null, @@ -486,6 +483,8 @@ static struct clk dpll3_m2_ck = { .clksel = div31_dpll3m2_clksel, .flags = RATE_PROPAGATES, .clkdm_name = "dpll3_clkdm", + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap3_core_dpll_m2_set_rate, .recalc = &omap2_clksel_recalc, }; -- GitLab From 8463e20a58e8b8c88fab948b8610504cbf604294 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Wed, 28 Jan 2009 12:27:45 -0700 Subject: [PATCH 1397/4982] [ARM] OMAP3: PM: Make sure clk_disable_unused() order is correct Current implementation will disable clocks in the order defined in clock34xx.h, at least DPLL4_M2X2 will hang in certain cases (and prevent retention / off) if clocks are not disabled in correct order. This patch makes sure the parent clocks will be active when disabling a clock. linux-omap source commit is 672680063420ef8c8c4e7271984bb9cc08171d29. Signed-off-by: Tero Kristo Signed-off-by: Kevin Hilman Signed-off-by: Russell King --- arch/arm/mach-omap2/clock.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 18fddb660ff..478ca660fff 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -1000,6 +1000,10 @@ void omap2_clk_disable_unused(struct clk *clk) return; printk(KERN_INFO "Disabling unused clock \"%s\"\n", clk->name); - _omap2_clk_disable(clk); + if (cpu_is_omap34xx()) { + omap2_clk_enable(clk); + omap2_clk_disable(clk); + } else + _omap2_clk_disable(clk); } #endif -- GitLab From 7b0f89d7bba946345fd597110388da5a913e9744 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 28 Jan 2009 12:27:48 -0700 Subject: [PATCH 1398/4982] [ARM] OMAP2/3 clock: use standard set_rate fn in omap2_clk_arch_init() Use the standard clk_set_rate() function in omap2_clk_arch_init() rather than omap2_select_table_rate() -- this will ensure that clock rates are recalculated and propagated correctly after those operations are consolidated into clk_set_rate(). linux-omap source commit is 03c03330017eeb445b01957608ff5db49a7151b6. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock24xx.c | 2 +- arch/arm/mach-omap2/clock34xx.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index a11e7c71177..2ce8c0296e8 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -688,7 +688,7 @@ static int __init omap2_clk_arch_init(void) if (!mpurate) return -EINVAL; - if (omap2_select_table_rate(&virt_prcm_set, mpurate)) + if (clk_set_rate(&virt_prcm_set, mpurate)) printk(KERN_ERR "Could not find matching MPU rate\n"); recalculate_root_clocks(); diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 1ad0a1359cb..06a81febe45 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -866,7 +866,7 @@ static int __init omap2_clk_arch_init(void) /* REVISIT: not yet ready for 343x */ #if 0 - if (omap2_select_table_rate(&virt_prcm_set, mpurate)) + if (clk_set_rate(&virt_prcm_set, mpurate)) printk(KERN_ERR "Could not find matching MPU rate\n"); #endif -- GitLab From b5088c0d90b898802318c62caf2320a53df6ce57 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 29 Jan 2009 19:33:19 +0000 Subject: [PATCH 1399/4982] [ARM] omap: clks: call recalc after any rate change This implements the remainder of: OMAP clock: move rate recalc, propagation code up to plat-omap/clock.c from Paul Walmsley which is not covered by the previous: [ARM] omap: move clock propagation into core omap clock code [ARM] omap: remove unnecessary calls to propagate_rate() [ARM] omap: move propagate_rate() calls into generic omap clock code commits. Signed-off-by: Russell King --- arch/arm/mach-omap2/clock24xx.c | 2 -- arch/arm/mach-omap2/clock34xx.c | 4 ---- arch/arm/plat-omap/clock.c | 16 ++++++++++++---- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index 2ce8c0296e8..4564ae32ae0 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -441,7 +441,6 @@ static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate) omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked()); omap2xxx_sdrc_reprogram(done_rate, 0); } - omap2_dpllcore_recalc(&dpll_ck); ret = 0; dpll_exit: @@ -570,7 +569,6 @@ static int omap2_select_table_rate(struct clk *clk, unsigned long rate) local_irq_restore(flags); } - omap2_dpllcore_recalc(&dpll_ck); return 0; } diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 06a81febe45..75eb2546bb0 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -614,8 +614,6 @@ static int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate) omap3_noncore_dpll_program(clk, dd->last_rounded_m, dd->last_rounded_n, freqsel); - omap3_dpll_recalc(clk); - return 0; } @@ -693,8 +691,6 @@ static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate) sp->actim_ctrlb, new_div); local_irq_enable(); - omap2_clksel_recalc(clk); - return 0; } diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 5272a2212ab..54da27af0bd 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -140,8 +140,12 @@ int clk_set_rate(struct clk *clk, unsigned long rate) spin_lock_irqsave(&clockfw_lock, flags); if (arch_clock->clk_set_rate) ret = arch_clock->clk_set_rate(clk, rate); - if (ret == 0 && (clk->flags & RATE_PROPAGATES)) - propagate_rate(clk); + if (ret == 0) { + if (clk->recalc) + clk->recalc(clk); + if (clk->flags & RATE_PROPAGATES) + propagate_rate(clk); + } spin_unlock_irqrestore(&clockfw_lock, flags); return ret; @@ -159,8 +163,12 @@ int clk_set_parent(struct clk *clk, struct clk *parent) spin_lock_irqsave(&clockfw_lock, flags); if (arch_clock->clk_set_parent) ret = arch_clock->clk_set_parent(clk, parent); - if (ret == 0 && (clk->flags & RATE_PROPAGATES)) - propagate_rate(clk); + if (ret == 0) { + if (clk->recalc) + clk->recalc(clk); + if (clk->flags & RATE_PROPAGATES) + propagate_rate(clk); + } spin_unlock_irqrestore(&clockfw_lock, flags); return ret; -- GitLab From 3f0a820c4c0b4670fb5f164baa5582e23c2ef118 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 31 Jan 2009 10:05:51 +0000 Subject: [PATCH 1400/4982] [ARM] omap: create a proper tree of clocks Traditionally, we've tracked the parent/child relationships between clk structures by setting the child's parent member to point at the upstream clock. As a result, when decending the tree, we have had to scan all clocks to find the children. Avoid this wasteful scanning by keeping a list of the clock's children. Signed-off-by: Russell King --- arch/arm/mach-omap1/clock.c | 3 + arch/arm/mach-omap1/clock.h | 7 +- arch/arm/mach-omap2/clock.c | 4 +- arch/arm/mach-omap2/clock24xx.c | 3 + arch/arm/mach-omap2/clock24xx.h | 28 +++----- arch/arm/mach-omap2/clock34xx.c | 3 + arch/arm/mach-omap2/clock34xx.h | 96 ++++--------------------- arch/arm/plat-omap/clock.c | 51 ++++++++----- arch/arm/plat-omap/include/mach/clock.h | 7 +- 9 files changed, 74 insertions(+), 128 deletions(-) diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index 1e477af666e..ccf989f4aa7 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -782,6 +782,9 @@ int __init omap1_clk_init(void) /* By default all idlect1 clocks are allowed to idle */ arm_idlect1_mask = ~0; + for (c = omap_clks; c < omap_clks + ARRAY_SIZE(omap_clks); c++) + clk_init_one(c->lk.clk); + cpu_mask = 0; if (cpu_is_omap16xx()) cpu_mask |= CK_16XX; diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h index 1b4dd056d9b..28bc74e93e8 100644 --- a/arch/arm/mach-omap1/clock.h +++ b/arch/arm/mach-omap1/clock.h @@ -155,7 +155,6 @@ static struct clk ck_dpll1 = { .name = "ck_dpll1", .ops = &clkops_null, .parent = &ck_ref, - .flags = RATE_PROPAGATES, }; static struct arm_idlect1_clk ck_dpll1out = { @@ -163,8 +162,7 @@ static struct arm_idlect1_clk ck_dpll1out = { .name = "ck_dpll1out", .ops = &clkops_generic, .parent = &ck_dpll1, - .flags = CLOCK_IDLE_CONTROL | - ENABLE_REG_32BIT | RATE_PROPAGATES, + .flags = CLOCK_IDLE_CONTROL | ENABLE_REG_32BIT, .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), .enable_bit = EN_CKOUT_ARM, .recalc = &followparent_recalc, @@ -187,7 +185,6 @@ static struct clk arm_ck = { .name = "arm_ck", .ops = &clkops_null, .parent = &ck_dpll1, - .flags = RATE_PROPAGATES, .rate_offset = CKCTL_ARMDIV_OFFSET, .recalc = &omap1_ckctl_recalc, .round_rate = omap1_clk_round_rate_ckctl_arm, @@ -328,7 +325,7 @@ static struct arm_idlect1_clk tc_ck = { .name = "tc_ck", .ops = &clkops_null, .parent = &ck_dpll1, - .flags = RATE_PROPAGATES | CLOCK_IDLE_CONTROL, + .flags = CLOCK_IDLE_CONTROL, .rate_offset = CKCTL_TCDIV_OFFSET, .recalc = &omap1_ckctl_recalc, .round_rate = omap1_clk_round_rate_ckctl_arm, diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 478ca660fff..38a7898d0ce 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -175,7 +175,7 @@ void omap2_init_clksel_parent(struct clk *clk) clk->name, clks->parent->name, ((clk->parent) ? clk->parent->name : "NULL")); - clk->parent = clks->parent; + clk_reparent(clk, clks->parent); }; found = 1; } @@ -780,7 +780,7 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) if (clk->usecount > 0) _omap2_clk_enable(clk); - clk->parent = new_parent; + clk_reparent(clk, new_parent); /* CLKSEL clocks follow their parents' rates, divided by a divisor */ clk->rate = new_parent->rate; diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index 4564ae32ae0..1a885976c25 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -718,6 +718,9 @@ int __init omap2_clk_init(void) omap2_sys_clk_recalc(&sys_ck); propagate_rate(&sys_ck); + for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++) + clk_init_one(c->lk.clk); + cpu_mask = 0; if (cpu_is_omap2420()) cpu_mask |= CK_242X; diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h index 7731ab6acd1..759489822ee 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock24xx.h @@ -621,7 +621,7 @@ static struct clk func_32k_ck = { .name = "func_32k_ck", .ops = &clkops_null, .rate = 32000, - .flags = RATE_FIXED | RATE_PROPAGATES, + .flags = RATE_FIXED, .clkdm_name = "wkup_clkdm", }; @@ -629,7 +629,6 @@ static struct clk func_32k_ck = { static struct clk osc_ck = { /* (*12, *13, 19.2, *26, 38.4)MHz */ .name = "osc_ck", .ops = &clkops_oscck, - .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .recalc = &omap2_osc_clk_recalc, }; @@ -639,7 +638,6 @@ static struct clk sys_ck = { /* (*12, *13, 19.2, 26, 38.4)MHz */ .name = "sys_ck", /* ~ ref_clk also */ .ops = &clkops_null, .parent = &osc_ck, - .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .recalc = &omap2_sys_clk_recalc, }; @@ -648,7 +646,7 @@ static struct clk alt_ck = { /* Typical 54M or 48M, may not exist */ .name = "alt_ck", .ops = &clkops_null, .rate = 54000000, - .flags = RATE_FIXED | RATE_PROPAGATES, + .flags = RATE_FIXED, .clkdm_name = "wkup_clkdm", }; @@ -680,7 +678,6 @@ static struct clk dpll_ck = { .ops = &clkops_null, .parent = &sys_ck, /* Can be func_32k also */ .dpll_data = &dpll_dd, - .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .recalc = &omap2_dpllcore_recalc, .set_rate = &omap2_reprogram_dpllcore, @@ -691,7 +688,7 @@ static struct clk apll96_ck = { .ops = &clkops_fixed, .parent = &sys_ck, .rate = 96000000, - .flags = RATE_FIXED | RATE_PROPAGATES | ENABLE_ON_INIT, + .flags = RATE_FIXED | ENABLE_ON_INIT, .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP24XX_EN_96M_PLL_SHIFT, @@ -702,7 +699,7 @@ static struct clk apll54_ck = { .ops = &clkops_fixed, .parent = &sys_ck, .rate = 54000000, - .flags = RATE_FIXED | RATE_PROPAGATES | ENABLE_ON_INIT, + .flags = RATE_FIXED | ENABLE_ON_INIT, .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP24XX_EN_54M_PLL_SHIFT, @@ -734,7 +731,6 @@ static struct clk func_54m_ck = { .name = "func_54m_ck", .ops = &clkops_null, .parent = &apll54_ck, /* can also be alt_clk */ - .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), @@ -747,7 +743,6 @@ static struct clk core_ck = { .name = "core_ck", .ops = &clkops_null, .parent = &dpll_ck, /* can also be 32k */ - .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -774,7 +769,6 @@ static struct clk func_96m_ck = { .name = "func_96m_ck", .ops = &clkops_null, .parent = &apll96_ck, - .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), @@ -807,7 +801,6 @@ static struct clk func_48m_ck = { .name = "func_48m_ck", .ops = &clkops_null, .parent = &apll96_ck, /* 96M or Alt */ - .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), @@ -823,7 +816,6 @@ static struct clk func_12m_ck = { .ops = &clkops_null, .parent = &func_48m_ck, .fixed_div = 4, - .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .recalc = &omap2_fixed_divisor_recalc, }; @@ -876,7 +868,6 @@ static struct clk sys_clkout_src = { .name = "sys_clkout_src", .ops = &clkops_omap2_dflt, .parent = &func_54m_ck, - .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .enable_reg = OMAP24XX_PRCM_CLKOUT_CTRL, .enable_bit = OMAP24XX_CLKOUT_EN_SHIFT, @@ -921,7 +912,6 @@ static struct clk sys_clkout2_src = { .name = "sys_clkout2_src", .ops = &clkops_omap2_dflt, .parent = &func_54m_ck, - .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .enable_reg = OMAP24XX_PRCM_CLKOUT_CTRL, .enable_bit = OMAP2420_CLKOUT2_EN_SHIFT, @@ -992,7 +982,7 @@ static struct clk mpu_ck = { /* Control cpu */ .name = "mpu_ck", .ops = &clkops_null, .parent = &core_ck, - .flags = DELAYED_APP | CONFIG_PARTICIPANT | RATE_PROPAGATES, + .flags = DELAYED_APP | CONFIG_PARTICIPANT, .clkdm_name = "mpu_clkdm", .init = &omap2_init_clksel_parent, .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL), @@ -1034,7 +1024,7 @@ static struct clk dsp_fck = { .name = "dsp_fck", .ops = &clkops_omap2_dflt_wait, .parent = &core_ck, - .flags = DELAYED_APP | CONFIG_PARTICIPANT | RATE_PROPAGATES, + .flags = DELAYED_APP | CONFIG_PARTICIPANT, .clkdm_name = "dsp_clkdm", .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN), .enable_bit = OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT, @@ -1102,7 +1092,7 @@ static struct clk iva1_ifck = { .name = "iva1_ifck", .ops = &clkops_omap2_dflt_wait, .parent = &core_ck, - .flags = CONFIG_PARTICIPANT | RATE_PROPAGATES | DELAYED_APP, + .flags = CONFIG_PARTICIPANT | DELAYED_APP, .clkdm_name = "iva1_clkdm", .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN), .enable_bit = OMAP2420_EN_IVA_COP_SHIFT, @@ -1165,7 +1155,7 @@ static struct clk core_l3_ck = { /* Used for ick and fck, interconnect */ .name = "core_l3_ck", .ops = &clkops_null, .parent = &core_ck, - .flags = DELAYED_APP | CONFIG_PARTICIPANT | RATE_PROPAGATES, + .flags = DELAYED_APP | CONFIG_PARTICIPANT, .clkdm_name = "core_l3_clkdm", .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1), .clksel_mask = OMAP24XX_CLKSEL_L3_MASK, @@ -1227,7 +1217,7 @@ static struct clk l4_ck = { /* used both as an ick and fck */ .name = "l4_ck", .ops = &clkops_null, .parent = &core_l3_ck, - .flags = DELAYED_APP | RATE_PROPAGATES, + .flags = DELAYED_APP, .clkdm_name = "core_l4_clkdm", .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1), .clksel_mask = OMAP24XX_CLKSEL_L4_MASK, diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 75eb2546bb0..a853b1e149e 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -903,6 +903,9 @@ int __init omap2_clk_init(void) clk_init(&omap2_clk_functions); + for (c = omap34xx_clks; c < omap34xx_clks + ARRAY_SIZE(omap34xx_clks); c++) + clk_init_one(c->lk.clk); + for (c = omap34xx_clks; c < omap34xx_clks + ARRAY_SIZE(omap34xx_clks); c++) if (c->cpu & cpu_clkflg) { clkdev_add(&c->lk); diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index 681acf0427c..2138a58f634 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -60,14 +60,14 @@ static struct clk omap_32k_fck = { .name = "omap_32k_fck", .ops = &clkops_null, .rate = 32768, - .flags = RATE_FIXED | RATE_PROPAGATES, + .flags = RATE_FIXED, }; static struct clk secure_32k_fck = { .name = "secure_32k_fck", .ops = &clkops_null, .rate = 32768, - .flags = RATE_FIXED | RATE_PROPAGATES, + .flags = RATE_FIXED, }; /* Virtual source clocks for osc_sys_ck */ @@ -75,42 +75,42 @@ static struct clk virt_12m_ck = { .name = "virt_12m_ck", .ops = &clkops_null, .rate = 12000000, - .flags = RATE_FIXED | RATE_PROPAGATES, + .flags = RATE_FIXED, }; static struct clk virt_13m_ck = { .name = "virt_13m_ck", .ops = &clkops_null, .rate = 13000000, - .flags = RATE_FIXED | RATE_PROPAGATES, + .flags = RATE_FIXED, }; static struct clk virt_16_8m_ck = { .name = "virt_16_8m_ck", .ops = &clkops_null, .rate = 16800000, - .flags = RATE_FIXED | RATE_PROPAGATES, + .flags = RATE_FIXED, }; static struct clk virt_19_2m_ck = { .name = "virt_19_2m_ck", .ops = &clkops_null, .rate = 19200000, - .flags = RATE_FIXED | RATE_PROPAGATES, + .flags = RATE_FIXED, }; static struct clk virt_26m_ck = { .name = "virt_26m_ck", .ops = &clkops_null, .rate = 26000000, - .flags = RATE_FIXED | RATE_PROPAGATES, + .flags = RATE_FIXED, }; static struct clk virt_38_4m_ck = { .name = "virt_38_4m_ck", .ops = &clkops_null, .rate = 38400000, - .flags = RATE_FIXED | RATE_PROPAGATES, + .flags = RATE_FIXED, }; static const struct clksel_rate osc_sys_12m_rates[] = { @@ -163,7 +163,7 @@ static struct clk osc_sys_ck = { .clksel_mask = OMAP3430_SYS_CLKIN_SEL_MASK, .clksel = osc_sys_clksel, /* REVISIT: deal with autoextclkmode? */ - .flags = RATE_FIXED | RATE_PROPAGATES, + .flags = RATE_FIXED, .recalc = &omap2_clksel_recalc, }; @@ -188,21 +188,18 @@ static struct clk sys_ck = { .clksel_reg = OMAP3430_PRM_CLKSRC_CTRL, .clksel_mask = OMAP_SYSCLKDIV_MASK, .clksel = sys_clksel, - .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; static struct clk sys_altclk = { .name = "sys_altclk", .ops = &clkops_null, - .flags = RATE_PROPAGATES, }; /* Optional external clock input for some McBSPs */ static struct clk mcbsp_clks = { .name = "mcbsp_clks", .ops = &clkops_null, - .flags = RATE_PROPAGATES, }; /* PRM EXTERNAL CLOCK OUTPUT */ @@ -279,7 +276,6 @@ static struct clk dpll1_ck = { .ops = &clkops_null, .parent = &sys_ck, .dpll_data = &dpll1_dd, - .flags = RATE_PROPAGATES, .round_rate = &omap2_dpll_round_rate, .set_rate = &omap3_noncore_dpll_set_rate, .clkdm_name = "dpll1_clkdm", @@ -294,7 +290,6 @@ static struct clk dpll1_x2_ck = { .name = "dpll1_x2_ck", .ops = &clkops_null, .parent = &dpll1_ck, - .flags = RATE_PROPAGATES, .clkdm_name = "dpll1_clkdm", .recalc = &omap3_clkoutx2_recalc, }; @@ -317,7 +312,6 @@ static struct clk dpll1_x2m2_ck = { .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL), .clksel_mask = OMAP3430_MPU_DPLL_CLKOUT_DIV_MASK, .clksel = div16_dpll1_x2m2_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "dpll1_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -353,7 +347,6 @@ static struct clk dpll2_ck = { .ops = &clkops_noncore_dpll_ops, .parent = &sys_ck, .dpll_data = &dpll2_dd, - .flags = RATE_PROPAGATES, .round_rate = &omap2_dpll_round_rate, .set_rate = &omap3_noncore_dpll_set_rate, .clkdm_name = "dpll2_clkdm", @@ -378,7 +371,6 @@ static struct clk dpll2_m2_ck = { OMAP3430_CM_CLKSEL2_PLL), .clksel_mask = OMAP3430_IVA2_DPLL_CLKOUT_DIV_MASK, .clksel = div16_dpll2_m2x2_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "dpll2_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -413,7 +405,6 @@ static struct clk dpll3_ck = { .ops = &clkops_null, .parent = &sys_ck, .dpll_data = &dpll3_dd, - .flags = RATE_PROPAGATES, .round_rate = &omap2_dpll_round_rate, .clkdm_name = "dpll3_clkdm", .recalc = &omap3_dpll_recalc, @@ -427,7 +418,6 @@ static struct clk dpll3_x2_ck = { .name = "dpll3_x2_ck", .ops = &clkops_null, .parent = &dpll3_ck, - .flags = RATE_PROPAGATES, .clkdm_name = "dpll3_clkdm", .recalc = &omap3_clkoutx2_recalc, }; @@ -481,7 +471,6 @@ static struct clk dpll3_m2_ck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK, .clksel = div31_dpll3m2_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "dpll3_clkdm", .round_rate = &omap2_clksel_round_rate, .set_rate = &omap3_core_dpll_m2_set_rate, @@ -501,7 +490,6 @@ static struct clk core_ck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), .clksel_mask = OMAP3430_ST_CORE_CLK_MASK, .clksel = core_ck_clksel, - .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -518,7 +506,6 @@ static struct clk dpll3_m2x2_ck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), .clksel_mask = OMAP3430_ST_CORE_CLK_MASK, .clksel = dpll3_m2x2_ck_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "dpll3_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -538,7 +525,6 @@ static struct clk dpll3_m3_ck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_DIV_DPLL3_MASK, .clksel = div16_dpll3_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "dpll3_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -550,7 +536,7 @@ static struct clk dpll3_m3x2_ck = { .parent = &dpll3_m3_ck, .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP3430_PWRDN_EMU_CORE_SHIFT, - .flags = RATE_PROPAGATES | INVERT_ENABLE, + .flags = INVERT_ENABLE, .clkdm_name = "dpll3_clkdm", .recalc = &omap3_clkoutx2_recalc, }; @@ -569,7 +555,6 @@ static struct clk emu_core_alwon_ck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), .clksel_mask = OMAP3430_ST_CORE_CLK_MASK, .clksel = emu_core_alwon_ck_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "dpll3_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -603,7 +588,6 @@ static struct clk dpll4_ck = { .ops = &clkops_noncore_dpll_ops, .parent = &sys_ck, .dpll_data = &dpll4_dd, - .flags = RATE_PROPAGATES, .round_rate = &omap2_dpll_round_rate, .set_rate = &omap3_dpll4_set_rate, .clkdm_name = "dpll4_clkdm", @@ -619,7 +603,6 @@ static struct clk dpll4_x2_ck = { .name = "dpll4_x2_ck", .ops = &clkops_null, .parent = &dpll4_ck, - .flags = RATE_PROPAGATES, .clkdm_name = "dpll4_clkdm", .recalc = &omap3_clkoutx2_recalc, }; @@ -638,7 +621,6 @@ static struct clk dpll4_m2_ck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430_CM_CLKSEL3), .clksel_mask = OMAP3430_DIV_96M_MASK, .clksel = div16_dpll4_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "dpll4_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -650,7 +632,7 @@ static struct clk dpll4_m2x2_ck = { .parent = &dpll4_m2_ck, .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP3430_PWRDN_96M_SHIFT, - .flags = RATE_PROPAGATES | INVERT_ENABLE, + .flags = INVERT_ENABLE, .clkdm_name = "dpll4_clkdm", .recalc = &omap3_clkoutx2_recalc, }; @@ -675,7 +657,6 @@ static struct clk omap_96m_alwon_fck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), .clksel_mask = OMAP3430_ST_PERIPH_CLK_MASK, .clksel = omap_96m_alwon_fck_clksel, - .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -683,7 +664,6 @@ static struct clk cm_96m_fck = { .name = "cm_96m_fck", .ops = &clkops_null, .parent = &omap_96m_alwon_fck, - .flags = RATE_PROPAGATES, .recalc = &followparent_recalc, }; @@ -711,7 +691,6 @@ static struct clk omap_96m_fck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_SOURCE_96M_MASK, .clksel = omap_96m_fck_clksel, - .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -724,7 +703,6 @@ static struct clk dpll4_m3_ck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_TV_MASK, .clksel = div16_dpll4_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "dpll4_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -737,7 +715,7 @@ static struct clk dpll4_m3x2_ck = { .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP3430_PWRDN_TV_SHIFT, - .flags = RATE_PROPAGATES | INVERT_ENABLE, + .flags = INVERT_ENABLE, .clkdm_name = "dpll4_clkdm", .recalc = &omap3_clkoutx2_recalc, }; @@ -756,7 +734,6 @@ static struct clk virt_omap_54m_fck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), .clksel_mask = OMAP3430_ST_PERIPH_CLK_MASK, .clksel = virt_omap_54m_fck_clksel, - .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -783,7 +760,6 @@ static struct clk omap_54m_fck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_SOURCE_54M_MASK, .clksel = omap_54m_clksel, - .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -810,7 +786,6 @@ static struct clk omap_48m_fck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_SOURCE_48M_MASK, .clksel = omap_48m_clksel, - .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -819,7 +794,6 @@ static struct clk omap_12m_fck = { .ops = &clkops_null, .parent = &omap_48m_fck, .fixed_div = 4, - .flags = RATE_PROPAGATES, .recalc = &omap2_fixed_divisor_recalc, }; @@ -832,7 +806,6 @@ static struct clk dpll4_m4_ck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_DSS1_MASK, .clksel = div16_dpll4_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "dpll4_clkdm", .recalc = &omap2_clksel_recalc, .set_rate = &omap2_clksel_set_rate, @@ -846,7 +819,7 @@ static struct clk dpll4_m4x2_ck = { .parent = &dpll4_m4_ck, .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP3430_PWRDN_CAM_SHIFT, - .flags = RATE_PROPAGATES | INVERT_ENABLE, + .flags = INVERT_ENABLE, .clkdm_name = "dpll4_clkdm", .recalc = &omap3_clkoutx2_recalc, }; @@ -860,7 +833,6 @@ static struct clk dpll4_m5_ck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_CAM_MASK, .clksel = div16_dpll4_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "dpll4_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -872,7 +844,7 @@ static struct clk dpll4_m5x2_ck = { .parent = &dpll4_m5_ck, .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP3430_PWRDN_CAM_SHIFT, - .flags = RATE_PROPAGATES | INVERT_ENABLE, + .flags = INVERT_ENABLE, .clkdm_name = "dpll4_clkdm", .recalc = &omap3_clkoutx2_recalc, }; @@ -886,7 +858,6 @@ static struct clk dpll4_m6_ck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_DIV_DPLL4_MASK, .clksel = div16_dpll4_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "dpll4_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -899,7 +870,7 @@ static struct clk dpll4_m6x2_ck = { .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN), .enable_bit = OMAP3430_PWRDN_EMU_PERIPH_SHIFT, - .flags = RATE_PROPAGATES | INVERT_ENABLE, + .flags = INVERT_ENABLE, .clkdm_name = "dpll4_clkdm", .recalc = &omap3_clkoutx2_recalc, }; @@ -908,7 +879,6 @@ static struct clk emu_per_alwon_ck = { .name = "emu_per_alwon_ck", .ops = &clkops_null, .parent = &dpll4_m6x2_ck, - .flags = RATE_PROPAGATES, .clkdm_name = "dpll4_clkdm", .recalc = &followparent_recalc, }; @@ -943,7 +913,6 @@ static struct clk dpll5_ck = { .ops = &clkops_noncore_dpll_ops, .parent = &sys_ck, .dpll_data = &dpll5_dd, - .flags = RATE_PROPAGATES, .round_rate = &omap2_dpll_round_rate, .set_rate = &omap3_noncore_dpll_set_rate, .clkdm_name = "dpll5_clkdm", @@ -963,7 +932,6 @@ static struct clk dpll5_m2_ck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL5), .clksel_mask = OMAP3430ES2_DIV_120M_MASK, .clksel = div16_dpll5_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "dpll5_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -982,7 +950,6 @@ static struct clk omap_120m_fck = { .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2), .clksel_mask = OMAP3430ES2_ST_PERIPH2_CLK_MASK, .clksel = omap_120m_fck_clksel, - .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -1025,7 +992,6 @@ static struct clk clkout2_src_ck = { .clksel_reg = OMAP3430_CM_CLKOUT_CTRL, .clksel_mask = OMAP3430_CLKOUT2SOURCE_MASK, .clksel = clkout2_src_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "core_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1060,7 +1026,6 @@ static struct clk corex2_fck = { .name = "corex2_fck", .ops = &clkops_null, .parent = &dpll3_m2x2_ck, - .flags = RATE_PROPAGATES, .recalc = &followparent_recalc, }; @@ -1090,7 +1055,6 @@ static struct clk dpll1_fck = { .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL), .clksel_mask = OMAP3430_MPU_CLK_SRC_MASK, .clksel = div4_core_clksel, - .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -1114,7 +1078,6 @@ static struct clk mpu_ck = { .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), .clksel_mask = OMAP3430_ST_MPU_CLK_MASK, .clksel = mpu_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "mpu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1139,7 +1102,6 @@ static struct clk arm_fck = { .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), .clksel_mask = OMAP3430_ST_MPU_CLK_MASK, .clksel = arm_fck_clksel, - .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -1153,7 +1115,6 @@ static struct clk emu_mpu_alwon_ck = { .name = "emu_mpu_alwon_ck", .ops = &clkops_null, .parent = &mpu_ck, - .flags = RATE_PROPAGATES, .recalc = &followparent_recalc, }; @@ -1165,7 +1126,6 @@ static struct clk dpll2_fck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL), .clksel_mask = OMAP3430_IVA2_CLK_SRC_MASK, .clksel = div4_core_clksel, - .flags = RATE_PROPAGATES, .recalc = &omap2_clksel_recalc, }; @@ -1193,7 +1153,6 @@ static struct clk iva2_ck = { OMAP3430_CM_IDLEST_PLL), .clksel_mask = OMAP3430_ST_IVA2_CLK_MASK, .clksel = iva2_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "iva2_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1213,7 +1172,6 @@ static struct clk l3_ick = { .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_L3_MASK, .clksel = div2_core_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "core_l3_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1231,7 +1189,6 @@ static struct clk l4_ick = { .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_L4_MASK, .clksel = div2_l3_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "core_l4_clkdm", .recalc = &omap2_clksel_recalc, @@ -1281,7 +1238,6 @@ static struct clk gfx_l3_fck = { .clksel_reg = OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL), .clksel_mask = OMAP_CLKSEL_GFX_MASK, .clksel = gfx_l3_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "gfx_3430es1_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1440,7 +1396,6 @@ static struct clk core_96m_fck = { .name = "core_96m_fck", .ops = &clkops_null, .parent = &omap_96m_fck, - .flags = RATE_PROPAGATES, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1574,7 +1529,6 @@ static struct clk core_48m_fck = { .name = "core_48m_fck", .ops = &clkops_null, .parent = &omap_48m_fck, - .flags = RATE_PROPAGATES, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1652,7 +1606,6 @@ static struct clk core_12m_fck = { .name = "core_12m_fck", .ops = &clkops_null, .parent = &omap_12m_fck, - .flags = RATE_PROPAGATES, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -1692,7 +1645,6 @@ static struct clk ssi_ssr_fck = { .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), .clksel_mask = OMAP3430_CLKSEL_SSI_MASK, .clksel = ssi_ssr_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "core_l4_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -1718,7 +1670,6 @@ static struct clk core_l3_ick = { .ops = &clkops_null, .parent = &l3_ick, .init = &omap2_init_clk_clkdm, - .flags = RATE_PROPAGATES, .clkdm_name = "core_l3_clkdm", .recalc = &followparent_recalc, }; @@ -1759,7 +1710,6 @@ static struct clk security_l3_ick = { .name = "security_l3_ick", .ops = &clkops_null, .parent = &l3_ick, - .flags = RATE_PROPAGATES, .recalc = &followparent_recalc, }; @@ -1779,7 +1729,6 @@ static struct clk core_l4_ick = { .ops = &clkops_null, .parent = &l4_ick, .init = &omap2_init_clk_clkdm, - .flags = RATE_PROPAGATES, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -2062,7 +2011,6 @@ static struct clk ssi_l4_ick = { .name = "ssi_l4_ick", .ops = &clkops_null, .parent = &l4_ick, - .flags = RATE_PROPAGATES, .clkdm_name = "core_l4_clkdm", .recalc = &followparent_recalc, }; @@ -2106,7 +2054,6 @@ static struct clk security_l4_ick2 = { .name = "security_l4_ick2", .ops = &clkops_null, .parent = &l4_ick, - .flags = RATE_PROPAGATES, .recalc = &followparent_recalc, }; @@ -2350,7 +2297,6 @@ static struct clk wkup_32k_fck = { .ops = &clkops_null, .init = &omap2_init_clk_clkdm, .parent = &omap_32k_fck, - .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2379,7 +2325,6 @@ static struct clk wkup_l4_ick = { .name = "wkup_l4_ick", .ops = &clkops_null, .parent = &sys_ck, - .flags = RATE_PROPAGATES, .clkdm_name = "wkup_clkdm", .recalc = &followparent_recalc, }; @@ -2466,7 +2411,6 @@ static struct clk per_96m_fck = { .ops = &clkops_null, .parent = &omap_96m_alwon_fck, .init = &omap2_init_clk_clkdm, - .flags = RATE_PROPAGATES, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2476,7 +2420,6 @@ static struct clk per_48m_fck = { .ops = &clkops_null, .parent = &omap_48m_fck, .init = &omap2_init_clk_clkdm, - .flags = RATE_PROPAGATES, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2600,7 +2543,6 @@ static struct clk per_32k_alwon_fck = { .ops = &clkops_null, .parent = &omap_32k_fck, .clkdm_name = "per_clkdm", - .flags = RATE_PROPAGATES, .recalc = &followparent_recalc, }; @@ -2668,7 +2610,6 @@ static struct clk per_l4_ick = { .name = "per_l4_ick", .ops = &clkops_null, .parent = &l4_ick, - .flags = RATE_PROPAGATES, .clkdm_name = "per_clkdm", .recalc = &followparent_recalc, }; @@ -2948,7 +2889,6 @@ static struct clk emu_src_ck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_MUX_CTRL_MASK, .clksel = emu_src_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "emu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2973,7 +2913,6 @@ static struct clk pclk_fck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_CLKSEL_PCLK_MASK, .clksel = pclk_emu_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "emu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -2997,7 +2936,6 @@ static struct clk pclkx2_fck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_CLKSEL_PCLKX2_MASK, .clksel = pclkx2_emu_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "emu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -3014,7 +2952,6 @@ static struct clk atclk_fck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_CLKSEL_ATCLK_MASK, .clksel = atclk_emu_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "emu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -3026,7 +2963,6 @@ static struct clk traceclk_src_fck = { .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1), .clksel_mask = OMAP3430_TRACE_MUX_CTRL_MASK, .clksel = emu_src_clksel, - .flags = RATE_PROPAGATES, .clkdm_name = "emu_clkdm", .recalc = &omap2_clksel_recalc, }; @@ -3063,7 +2999,6 @@ static struct clk sr1_fck = { .parent = &sys_ck, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_SR1_SHIFT, - .flags = RATE_PROPAGATES, .recalc = &followparent_recalc, }; @@ -3074,7 +3009,6 @@ static struct clk sr2_fck = { .parent = &sys_ck, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_SR2_SHIFT, - .flags = RATE_PROPAGATES, .recalc = &followparent_recalc, }; diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 54da27af0bd..6a1737a7447 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -143,8 +143,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate) if (ret == 0) { if (clk->recalc) clk->recalc(clk); - if (clk->flags & RATE_PROPAGATES) - propagate_rate(clk); + propagate_rate(clk); } spin_unlock_irqrestore(&clockfw_lock, flags); @@ -166,8 +165,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent) if (ret == 0) { if (clk->recalc) clk->recalc(clk); - if (clk->flags & RATE_PROPAGATES) - propagate_rate(clk); + propagate_rate(clk); } spin_unlock_irqrestore(&clockfw_lock, flags); @@ -214,24 +212,31 @@ void followparent_recalc(struct clk *clk) clk->rate = clk->parent->rate; } +void clk_reparent(struct clk *child, struct clk *parent) +{ + list_del_init(&child->sibling); + if (parent) + list_add(&child->sibling, &parent->children); + child->parent = parent; + + /* now do the debugfs renaming to reattach the child + to the proper parent */ +} + /* Propagate rate to children */ void propagate_rate(struct clk * tclk) { struct clk *clkp; - if (tclk == NULL || IS_ERR(tclk)) - return; - - list_for_each_entry(clkp, &clocks, node) { - if (likely(clkp->parent != tclk)) - continue; + list_for_each_entry(clkp, &tclk->children, sibling) { if (clkp->recalc) clkp->recalc(clkp); - if (clkp->flags & RATE_PROPAGATES) - propagate_rate(clkp); + propagate_rate(clkp); } } +static LIST_HEAD(root_clks); + /** * recalculate_root_clocks - recalculate and propagate all root clocks * @@ -243,16 +248,18 @@ void recalculate_root_clocks(void) { struct clk *clkp; - list_for_each_entry(clkp, &clocks, node) { - if (!clkp->parent) { - if (clkp->recalc) - clkp->recalc(clkp); - if (clkp->flags & RATE_PROPAGATES) - propagate_rate(clkp); - } + list_for_each_entry(clkp, &root_clks, sibling) { + if (clkp->recalc) + clkp->recalc(clkp); + propagate_rate(clkp); } } +void clk_init_one(struct clk *clk) +{ + INIT_LIST_HEAD(&clk->children); +} + int clk_register(struct clk *clk) { if (clk == NULL || IS_ERR(clk)) @@ -265,6 +272,11 @@ int clk_register(struct clk *clk) return 0; mutex_lock(&clocks_mutex); + if (clk->parent) + list_add(&clk->sibling, &clk->parent->children); + else + list_add(&clk->sibling, &root_clks); + list_add(&clk->node, &clocks); if (clk->init) clk->init(clk); @@ -280,6 +292,7 @@ void clk_unregister(struct clk *clk) return; mutex_lock(&clocks_mutex); + list_del(&clk->sibling); list_del(&clk->node); mutex_unlock(&clocks_mutex); } diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index 8705902de1d..af6ae4fa46d 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -70,6 +70,8 @@ struct clk { const char *name; int id; struct clk *parent; + struct list_head children; + struct list_head sibling; /* node for children */ unsigned long rate; __u32 flags; void __iomem *enable_reg; @@ -115,7 +117,9 @@ struct clk_functions { extern unsigned int mpurate; extern int clk_init(struct clk_functions *custom_clocks); +extern void clk_init_one(struct clk *clk); extern int clk_register(struct clk *clk); +extern void clk_reparent(struct clk *child, struct clk *parent); extern void clk_unregister(struct clk *clk); extern void propagate_rate(struct clk *clk); extern void recalculate_root_clocks(void); @@ -131,8 +135,7 @@ extern const struct clkops clkops_null; /* Clock flags */ /* bit 0 is free */ #define RATE_FIXED (1 << 1) /* Fixed clock rate */ -#define RATE_PROPAGATES (1 << 2) /* Program children too */ -/* bits 3-4 are free */ +/* bits 2-4 are free */ #define ENABLE_REG_32BIT (1 << 5) /* Use 32-bit access */ #define CLOCK_IDLE_CONTROL (1 << 7) #define CLOCK_NO_IDLE_PARENT (1 << 8) -- GitLab From de07fedd79999668c4c112a2ba3eaf3d7434235c Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 28 Jan 2009 12:35:01 -0700 Subject: [PATCH 1401/4982] [ARM] OMAP2/3 clock: don't use a barrier after clk_disable() clk_disable() previously used an ARM barrier, wmb(), to try to ensure that the hardware write completed before continuing. There are some problems with this approach. The first problem is that wmb() only ensures that the write leaves the ARM -- not that it actually reaches the endpoint device. In this case, the endpoint device - either the PRM, CM, or SCM - is three interconnects away from the ARM, and the final interconnect is low-speed. And the OCP interconnects will post the write, who knows how long that will take to complete. So the wmb() is not really what we want. Worse, the wmb() is indiscriminate; it will cause the ARM to flush any other unrelated buffered writes and wait for the local interconnect to acknowledge them - potentially very expensive. This first problem could be fixed by doing a readback of the same PRM/CM/SCM register. Since these devices use a single OCP thread, this will cause the MPU to wait for the write to complete. But the primary problem is a conceptual one: clk_disable() should not need any kind of barrier. clk_enable() needs one since device driver code must not access a device until its clocks are known to be enabled. But clk_disable() has no such restriction. Since blocking the MPU on a PRM/CM/SCM write can be a very high-latency operation - several hundred MPU cycles - it's worth avoiding this barrier if possible. linux-omap source commit is f4aacad2c0ed1055622d5c1e910befece24ef0e2. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 38a7898d0ce..0803c8c811f 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -353,7 +353,7 @@ static void omap2_dflt_clk_disable(struct clk *clk) else v &= ~(1 << clk->enable_bit); __raw_writel(v, clk->enable_reg); - wmb(); + /* No OCP barrier needed here since it is a disable operation */ } const struct clkops clkops_omap2_dflt_wait = { -- GitLab From 439764cc18beb20ef409991e75e29b460db71d33 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 28 Jan 2009 12:35:03 -0700 Subject: [PATCH 1402/4982] [ARM] OMAP2xxx clock: consolidate DELAYED_APP clock commits; fix barrier Consolidate the commit code for DELAYED_APP clocks into a subroutine, _omap2xxx_clk_commit(). Also convert the MPU barrier wmb() into an OCP barrier, since with an MPU barrier, we have no guarantee that the write actually reached the endpoint device. linux-omap source commit is 0f5bdb736515801b296125d16937a21ff7b3cfdc. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 0803c8c811f..7f12230fef7 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -74,6 +74,28 @@ u8 cpu_mask; * OMAP2/3 specific clock functions *-------------------------------------------------------------------------*/ +/** + * _omap2xxx_clk_commit - commit clock parent/rate changes in hardware + * @clk: struct clk * + * + * If @clk has the DELAYED_APP flag set, meaning that parent/rate changes + * don't take effect until the VALID_CONFIG bit is written, write the + * VALID_CONFIG bit and wait for the write to complete. No return value. + */ +static void _omap2xxx_clk_commit(struct clk *clk) +{ + if (!cpu_is_omap24xx()) + return; + + if (!(clk->flags & DELAYED_APP)) + return; + + prm_write_mod_reg(OMAP24XX_VALID_CONFIG, OMAP24XX_GR_MOD, + OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET); + /* OCP barrier */ + prm_read_mod_reg(OMAP24XX_GR_MOD, OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET); +} + /* * _dpll_test_fint - test whether an Fint value is valid for the DPLL * @clk: DPLL struct clk to test @@ -685,11 +707,7 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate) clk->rate = clk->parent->rate / new_div; - if (clk->flags & DELAYED_APP && cpu_is_omap24xx()) { - prm_write_mod_reg(OMAP24XX_VALID_CONFIG, - OMAP24XX_GR_MOD, OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET); - wmb(); - } + _omap2xxx_clk_commit(clk); return 0; } @@ -772,10 +790,7 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) __raw_writel(v, clk->clksel_reg); wmb(); - if (clk->flags & DELAYED_APP && cpu_is_omap24xx()) { - __raw_writel(OMAP24XX_VALID_CONFIG, OMAP24XX_PRCM_CLKCFG_CTRL); - wmb(); - } + _omap2xxx_clk_commit(clk); if (clk->usecount > 0) _omap2_clk_enable(clk); -- GitLab From f11fda6a9173e8e6b152ba5cb26fa20095a4c60f Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 28 Jan 2009 12:35:06 -0700 Subject: [PATCH 1403/4982] [ARM] OMAP2/3 clock: convert remaining MPU barriers into OCP barriers Several parts of the OMAP2/3 clock code use wmb() to try to ensure that the hardware write completes before continuing. This approach is problematic: wmb() only ensures that the write leaves the ARM. It does not ensure that the write actually reaches the endpoint device. The endpoint device in this case - either the PRM, CM, or SCM - is three interconnects away from the ARM - and the final interconnect is low-speed. And the OCP interconnects will post the write, and who knows how long that will take to complete. So the wmb() is not what we want. Worse, the wmb() is indiscriminate; it causes the ARM to flush any other unrelated buffered writes and wait for the local interconnect to acknowledge them - potentially very expensive. Fix this by converting the wmb()s into readbacks of the same PRM/CM/SCM register. Since the PRM/CM/SCM devices use a single OCP thread, this will cause the MPU to block while waiting for posted writes to that device to complete. linux-omap source commit is 260f5487848681b4d8ea7430a709a601bbcb21d1. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 7f12230fef7..666274a8b10 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -334,7 +334,7 @@ static int omap2_dflt_clk_enable(struct clk *clk) else v |= (1 << clk->enable_bit); __raw_writel(v, clk->enable_reg); - wmb(); + v = __raw_readl(clk->enable_reg); /* OCP barrier */ return 0; } @@ -703,7 +703,7 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate) v &= ~clk->clksel_mask; v |= field_val << __ffs(clk->clksel_mask); __raw_writel(v, clk->clksel_reg); - wmb(); + v = __raw_readl(clk->clksel_reg); /* OCP barrier */ clk->rate = clk->parent->rate / new_div; @@ -788,7 +788,7 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) v &= ~clk->clksel_mask; v |= field_val << __ffs(clk->clksel_mask); __raw_writel(v, clk->clksel_reg); - wmb(); + v = __raw_readl(clk->clksel_reg); /* OCP barrier */ _omap2xxx_clk_commit(clk); -- GitLab From be5f34b77355b9b1720a88390e51441ef578720b Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 28 Jan 2009 12:35:09 -0700 Subject: [PATCH 1404/4982] [ARM] OMAP clock: drop clk_get_usecount() This function is race-prone and mistakenly conveys the impression to drivers that it is part of the clock interface. Get rid of it: core code that absolutely needs this can just check clk->usecount. Drivers should not use it at all. linux-omap source commit is 5df9e4adc2f6a6d55aca53ee27b8baad18897c05. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/plat-omap/clock.c | 16 ---------------- arch/arm/plat-omap/include/mach/clock.h | 1 - 2 files changed, 17 deletions(-) diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 6a1737a7447..9833d73511a 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -76,22 +76,6 @@ out: } EXPORT_SYMBOL(clk_disable); -int clk_get_usecount(struct clk *clk) -{ - unsigned long flags; - int ret = 0; - - if (clk == NULL || IS_ERR(clk)) - return 0; - - spin_lock_irqsave(&clockfw_lock, flags); - ret = clk->usecount; - spin_unlock_irqrestore(&clockfw_lock, flags); - - return ret; -} -EXPORT_SYMBOL(clk_get_usecount); - unsigned long clk_get_rate(struct clk *clk) { unsigned long flags; diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index af6ae4fa46d..0ba28462a49 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -124,7 +124,6 @@ extern void clk_unregister(struct clk *clk); extern void propagate_rate(struct clk *clk); extern void recalculate_root_clocks(void); extern void followparent_recalc(struct clk *clk); -extern int clk_get_usecount(struct clk *clk); extern void clk_enable_init_clocks(void); #ifdef CONFIG_CPU_FREQ extern void clk_init_cpufreq_table(struct cpufreq_frequency_table **table); -- GitLab From a7f8c599c570fc0e2396e8fdccaeeeaefc41dac8 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 31 Jan 2009 11:00:17 +0000 Subject: [PATCH 1405/4982] [ARM] omap: fix usecount decrement bug Based upon a patch from Paul Walmsley : If _omap2_clk_enable() fails, the clock's usecount must be decremented by one no matter whether the clock has a parent or not. but reorganised a bit. Signed-off-by: Russell King --- arch/arm/mach-omap2/clock.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 666274a8b10..222c2c0d4a6 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -419,30 +419,30 @@ int omap2_clk_enable(struct clk *clk) int ret = 0; if (clk->usecount++ == 0) { - if (clk->parent) + if (clk->parent) { ret = omap2_clk_enable(clk->parent); - - if (ret != 0) { - clk->usecount--; - return ret; + if (ret) + goto err; } if (clk->clkdm) omap2_clkdm_clk_enable(clk->clkdm, clk); ret = _omap2_clk_enable(clk); - - if (ret != 0) { + if (ret) { if (clk->clkdm) omap2_clkdm_clk_disable(clk->clkdm, clk); - if (clk->parent) { + if (clk->parent) omap2_clk_disable(clk->parent); - clk->usecount--; - } + + goto err; } } + return ret; +err: + clk->usecount--; return ret; } -- GitLab From 8263e5b31eae2bbf689ff08a7da334329c9f353b Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 31 Jan 2009 11:02:37 +0000 Subject: [PATCH 1406/4982] [ARM] omap: fix clockdomain enable/disable ordering Based on a patch from Paul Walmsley : omap2_clk_enable() should enable a clock's clockdomain before attempting to enable its parent clock's clockdomain. Similarly, in the unlikely event that the parent clock enable fails, the clockdomain should be disabled. linux-omap source commit is 6d6e285e5a7912b1ea68fadac387304c914aaba8. Signed-off-by: Russell King --- arch/arm/mach-omap2/clock.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 222c2c0d4a6..1b40d757500 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -419,20 +419,17 @@ int omap2_clk_enable(struct clk *clk) int ret = 0; if (clk->usecount++ == 0) { + if (clk->clkdm) + omap2_clkdm_clk_enable(clk->clkdm, clk); + if (clk->parent) { ret = omap2_clk_enable(clk->parent); if (ret) goto err; } - if (clk->clkdm) - omap2_clkdm_clk_enable(clk->clkdm, clk); - ret = _omap2_clk_enable(clk); if (ret) { - if (clk->clkdm) - omap2_clkdm_clk_disable(clk->clkdm, clk); - if (clk->parent) omap2_clk_disable(clk->parent); @@ -442,6 +439,8 @@ int omap2_clk_enable(struct clk *clk) return ret; err: + if (clk->clkdm) + omap2_clkdm_clk_disable(clk->clkdm, clk); clk->usecount--; return ret; } -- GitLab From 883992bd8f6924c9aa849f2dac381075e2e55a9d Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 28 Jan 2009 12:35:31 -0700 Subject: [PATCH 1407/4982] [ARM] OMAP2/3 clock: don't tinker with hardirqs when they are supposed to be disabled Clock rate change code executes inside a spinlock with hardirqs disabled. The only code that should be messing around with the hardirq state should be the plat-omap/clock.c code. In the omap2_reprogram_dpllcore() case, this probably just wastes cycles, but in the omap3_core_dpll_m2_set_rate() case, this is a nasty bug. linux-omap source commit is b9b6208dadb5e0d8b290900a3ffa911673ca97ed. Signed-off-by: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/clock24xx.c | 12 +++--------- arch/arm/mach-omap2/clock34xx.c | 2 -- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index 1a885976c25..069f3e1827a 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -380,10 +380,7 @@ static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate) u32 bypass = 0; struct prcm_config tmpset; const struct dpll_data *dd; - unsigned long flags; - int ret = -EINVAL; - local_irq_save(flags); cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck); mult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2); mult &= OMAP24XX_CORE_CLK_SRC_MASK; @@ -395,7 +392,7 @@ static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate) } else if (rate != cur_rate) { valid_rate = omap2_dpllcore_round_rate(rate); if (valid_rate != rate) - goto dpll_exit; + return -EINVAL; if (mult == 1) low = curr_prcm_set->dpll_speed; @@ -404,7 +401,7 @@ static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate) dd = clk->dpll_data; if (!dd) - goto dpll_exit; + return -EINVAL; tmpset.cm_clksel1_pll = __raw_readl(dd->mult_div1_reg); tmpset.cm_clksel1_pll &= ~(dd->mult_mask | @@ -441,11 +438,8 @@ static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate) omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked()); omap2xxx_sdrc_reprogram(done_rate, 0); } - ret = 0; -dpll_exit: - local_irq_restore(flags); - return(ret); + return 0; } /** diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index a853b1e149e..3b6e27bc9fe 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -686,10 +686,8 @@ static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate) WARN_ON(new_div != 1 && new_div != 2); /* REVISIT: Add SDRC_MR changing to this code also */ - local_irq_disable(); omap3_configure_core_dpll(sp->rfr_ctrl, sp->actim_ctrla, sp->actim_ctrlb, new_div); - local_irq_enable(); return 0; } -- GitLab From 8f0dc655f9efa3fc81b8cdaf5aa1f2779f8db46d Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 7 Feb 2009 14:01:58 +0100 Subject: [PATCH 1408/4982] ASoC: Add initial support of Mitac mioa701 device SoC. This machine driver enables sound functions on Mitac mio a701 smartphone. Build upon ASoC v1, it handles : - rear speaker - front speaker - microphone - GSM A global "Mio Mode" switch is not yet provided to cope with audio path setup. As balance on audio chip line is no more assured, an incorrect setup can produce a lot of heat and even fry the battery behind the wm9713 and the speaker amplifier. It doesn't cope with : - headset jack - mio master mode - master volume control This driver is backported from ASoc v2, and amputated from scenario setups and master volume control. [Minor mods for terminology in comments -- broonie] Signed-off-by: Robert Jarzmik Signed-off-by: Mark Brown --- sound/soc/pxa/Kconfig | 9 ++ sound/soc/pxa/Makefile | 2 + sound/soc/pxa/mioa701_wm9713.c | 250 +++++++++++++++++++++++++++++++++ 3 files changed, 261 insertions(+) create mode 100644 sound/soc/pxa/mioa701_wm9713.c diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index 958ac3fe15d..5998ab366e8 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -115,3 +115,12 @@ config SND_SOC_ZYLONITE help Say Y if you want to add support for SoC audio on the Marvell Zylonite reference platform. + +config SND_PXA2XX_SOC_MIOA701 + tristate "SoC Audio support for MIO A701" + depends on SND_PXA2XX_SOC && MACH_MIOA701 + select SND_PXA2XX_SOC_AC97 + select SND_SOC_WM9713 + help + Say Y if you want to add support for SoC audio on the + MIO A701. diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile index 97a51a8c936..8ed881c5e5c 100644 --- a/sound/soc/pxa/Makefile +++ b/sound/soc/pxa/Makefile @@ -20,6 +20,7 @@ snd-soc-spitz-objs := spitz.o snd-soc-em-x270-objs := em-x270.o snd-soc-palm27x-objs := palm27x.o snd-soc-zylonite-objs := zylonite.o +snd-soc-mioa701-objs := mioa701_wm9713.o obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o @@ -30,4 +31,5 @@ obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o +obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c new file mode 100644 index 00000000000..19eda8bbfda --- /dev/null +++ b/sound/soc/pxa/mioa701_wm9713.c @@ -0,0 +1,250 @@ +/* + * Handles the Mitac mioa701 SoC system + * + * Copyright (C) 2008 Robert Jarzmik + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation in version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This is a little schema of the sound interconnections : + * + * Sagem X200 Wolfson WM9713 + * +--------+ +-------------------+ Rear Speaker + * | | | | /-+ + * | +--->----->---+MONOIN SPKL+--->----+-+ | + * | GSM | | | | | | + * | +--->----->---+PCBEEP SPKR+--->----+-+ | + * | CHIP | | | \-+ + * | +---<-----<---+MONO | + * | | | | Front Speaker + * +--------+ | | /-+ + * | HPL+--->----+-+ | + * | | | | | + * | OUT3+--->----+-+ | + * | | \-+ + * | | + * | | Front Micro + * | | + + * | MIC1+-----<--+o+ + * | | + + * +-------------------+ --- + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "pxa2xx-pcm.h" +#include "pxa2xx-ac97.h" +#include "../codecs/wm9713.h" + +#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x) + +#define AC97_GPIO_PULL 0x58 + +/* Use GPIO8 for rear speaker amplifier */ +static int rear_amp_power(struct snd_soc_codec *codec, int power) +{ + unsigned short reg; + + if (power) { + reg = snd_soc_read(codec, AC97_GPIO_CFG); + snd_soc_write(codec, AC97_GPIO_CFG, reg | 0x0100); + reg = snd_soc_read(codec, AC97_GPIO_PULL); + snd_soc_write(codec, AC97_GPIO_PULL, reg | (1<<15)); + } else { + reg = snd_soc_read(codec, AC97_GPIO_CFG); + snd_soc_write(codec, AC97_GPIO_CFG, reg & ~0x0100); + reg = snd_soc_read(codec, AC97_GPIO_PULL); + snd_soc_write(codec, AC97_GPIO_PULL, reg & ~(1<<15)); + } + + return 0; +} + +static int rear_amp_event(struct snd_soc_dapm_widget *widget, + struct snd_kcontrol *kctl, int event) +{ + struct snd_soc_codec *codec = widget->codec; + + return rear_amp_power(codec, SND_SOC_DAPM_EVENT_ON(event)); +} + +/* mioa701 machine dapm widgets */ +static const struct snd_soc_dapm_widget mioa701_dapm_widgets[] = { + SND_SOC_DAPM_SPK("Front Speaker", NULL), + SND_SOC_DAPM_SPK("Rear Speaker", rear_amp_event), + SND_SOC_DAPM_MIC("Headset", NULL), + SND_SOC_DAPM_LINE("GSM Line Out", NULL), + SND_SOC_DAPM_LINE("GSM Line In", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Front Mic", NULL), +}; + +static const struct snd_soc_dapm_route audio_map[] = { + /* Call Mic */ + {"Mic Bias", NULL, "Front Mic"}, + {"MIC1", NULL, "Mic Bias"}, + + /* Headset Mic */ + {"LINEL", NULL, "Headset Mic"}, + {"LINER", NULL, "Headset Mic"}, + + /* GSM Module */ + {"MONOIN", NULL, "GSM Line Out"}, + {"PCBEEP", NULL, "GSM Line Out"}, + {"GSM Line In", NULL, "MONO"}, + + /* headphone connected to HPL, HPR */ + {"Headset", NULL, "HPL"}, + {"Headset", NULL, "HPR"}, + + /* front speaker connected to HPL, OUT3 */ + {"Front Speaker", NULL, "HPL"}, + {"Front Speaker", NULL, "OUT3"}, + + /* rear speaker connected to SPKL, SPKR */ + {"Rear Speaker", NULL, "SPKL"}, + {"Rear Speaker", NULL, "SPKR"}, +}; + +static int mioa701_wm9713_init(struct snd_soc_codec *codec) +{ + unsigned short reg; + + /* Add mioa701 specific widgets */ + snd_soc_dapm_new_controls(codec, ARRAY_AND_SIZE(mioa701_dapm_widgets)); + + /* Set up mioa701 specific audio path audio_mapnects */ + snd_soc_dapm_add_routes(codec, ARRAY_AND_SIZE(audio_map)); + + /* Prepare GPIO8 for rear speaker amplifier */ + reg = codec->read(codec, AC97_GPIO_CFG); + codec->write(codec, AC97_GPIO_CFG, reg | 0x0100); + + /* Prepare MIC input */ + reg = codec->read(codec, AC97_3D_CONTROL); + codec->write(codec, AC97_3D_CONTROL, reg | 0xc000); + + snd_soc_dapm_enable_pin(codec, "Front Speaker"); + snd_soc_dapm_enable_pin(codec, "Rear Speaker"); + snd_soc_dapm_enable_pin(codec, "Front Mic"); + snd_soc_dapm_enable_pin(codec, "GSM Line In"); + snd_soc_dapm_enable_pin(codec, "GSM Line Out"); + snd_soc_dapm_sync(codec); + + return 0; +} + +static struct snd_soc_ops mioa701_ops; + +static struct snd_soc_dai_link mioa701_dai[] = { + { + .name = "AC97", + .stream_name = "AC97 HiFi", + .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], + .codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI], + .init = mioa701_wm9713_init, + .ops = &mioa701_ops, + }, + { + .name = "AC97 Aux", + .stream_name = "AC97 Aux", + .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], + .codec_dai = &wm9713_dai[WM9713_DAI_AC97_AUX], + .ops = &mioa701_ops, + }, +}; + +static struct snd_soc_card mioa701 = { + .name = "MioA701", + .platform = &pxa2xx_soc_platform, + .dai_link = mioa701_dai, + .num_links = ARRAY_SIZE(mioa701_dai), +}; + +static struct snd_soc_device mioa701_snd_devdata = { + .card = &mioa701, + .codec_dev = &soc_codec_dev_wm9713, +}; + +static struct platform_device *mioa701_snd_device; + +static int mioa701_wm9713_probe(struct platform_device *pdev) +{ + int ret; + + if (!machine_is_mioa701()) + return -ENODEV; + + dev_warn(&pdev->dev, "Be warned that incorrect mixers/muxes setup will" + "lead to overheating and possible destruction of your device." + "Do not use without a good knowledge of mio's board design!\n"); + + mioa701_snd_device = platform_device_alloc("soc-audio", -1); + if (!mioa701_snd_device) + return -ENOMEM; + + platform_set_drvdata(mioa701_snd_device, &mioa701_snd_devdata); + mioa701_snd_devdata.dev = &mioa701_snd_device->dev; + + ret = platform_device_add(mioa701_snd_device); + if (!ret) + return 0; + + platform_device_put(mioa701_snd_device); + return ret; +} + +static int __devexit mioa701_wm9713_remove(struct platform_device *pdev) +{ + platform_device_unregister(mioa701_snd_device); + return 0; +} + +static struct platform_driver mioa701_wm9713_driver = { + .probe = mioa701_wm9713_probe, + .remove = __devexit_p(mioa701_wm9713_remove), + .driver = { + .name = "mioa701-wm9713", + .owner = THIS_MODULE, + }, +}; + +static int __init mioa701_asoc_init(void) +{ + return platform_driver_register(&mioa701_wm9713_driver); +} + +static void __exit mioa701_asoc_exit(void) +{ + platform_driver_unregister(&mioa701_wm9713_driver); +} + +module_init(mioa701_asoc_init); +module_exit(mioa701_asoc_exit); + +/* Module information */ +MODULE_AUTHOR("Robert Jarzmik (rjarzmik@free.fr)"); +MODULE_DESCRIPTION("ALSA SoC WM9713 MIO A701"); +MODULE_LICENSE("GPL"); -- GitLab From 67137a5d46d5a7c4cbdc66f03d1e2f397fe14b2b Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Sun, 8 Feb 2009 18:17:37 +0100 Subject: [PATCH 1409/4982] ASoC: count reaches 10001, not 10000. With a postfix increment count reaches 10001, not 10000. Signed-off-by: Mark Brown --- sound/soc/blackfin/bf5xx-ad73311.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c index 7f2a5e19907..edfbdc024e6 100644 --- a/sound/soc/blackfin/bf5xx-ad73311.c +++ b/sound/soc/blackfin/bf5xx-ad73311.c @@ -114,7 +114,7 @@ static int snd_ad73311_configure(void) SSYNC(); /* When TUVF is set, the data is already send out */ - while (!(status & TUVF) && count++ < 10000) { + while (!(status & TUVF) && ++count < 10000) { udelay(1); status = bfin_read_SPORT_STAT(); SSYNC(); @@ -123,7 +123,7 @@ static int snd_ad73311_configure(void) SSYNC(); local_irq_enable(); - if (count == 10000) { + if (count >= 10000) { printk(KERN_ERR "ad73311: failed to configure codec\n"); return -1; } -- GitLab From 4e7f78f815412fd25b207b8c63a698b637c9621d Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 5 Feb 2009 17:48:19 +0100 Subject: [PATCH 1410/4982] pxa/h5000: Setup I2S pins for pxa2xx-i2s The iPAQ h5000 has an AK4535 codec connected as I2S slave, PXA I2S providing SYSCLK. Signed-off-by: Philipp Zabel Acked-by: Eric Miao Signed-off-by: Mark Brown --- arch/arm/mach-pxa/h5000.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/mach-pxa/h5000.c b/arch/arm/mach-pxa/h5000.c index da6e4422c0f..295ec413d80 100644 --- a/arch/arm/mach-pxa/h5000.c +++ b/arch/arm/mach-pxa/h5000.c @@ -153,6 +153,13 @@ static unsigned long h5000_pin_config[] __initdata = { GPIO23_SSP1_SCLK, GPIO25_SSP1_TXD, GPIO26_SSP1_RXD, + + /* I2S */ + GPIO28_I2S_BITCLK_OUT, + GPIO29_I2S_SDATA_IN, + GPIO30_I2S_SDATA_OUT, + GPIO31_I2S_SYNC, + GPIO32_I2S_SYSCLK, }; /* -- GitLab From 772885c1dc42f1992ac4fc937f1ed4ae9d42a31e Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 5 Feb 2009 17:48:20 +0100 Subject: [PATCH 1411/4982] pxa/spitz: Setup I2S pins for pxa2xx-i2s The spitz has a WM8750 codec connected as I2S slave but doesn't use the PXA I2S system clock. Signed-off-by: Philipp Zabel Acked-by: Eric Miao Signed-off-by: Mark Brown --- arch/arm/mach-pxa/spitz.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 6d447c9ce8a..0d62d311d41 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -105,6 +105,12 @@ static unsigned long spitz_pin_config[] __initdata = { GPIO57_nIOIS16, GPIO104_PSKTSEL, + /* I2S */ + GPIO28_I2S_BITCLK_OUT, + GPIO29_I2S_SDATA_IN, + GPIO30_I2S_SDATA_OUT, + GPIO31_I2S_SYNC, + /* MMC */ GPIO32_MMC_CLK, GPIO112_MMC_CMD, -- GitLab From 44dd2b9168350b82a671ce71666b99208ab2d973 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 5 Feb 2009 17:48:21 +0100 Subject: [PATCH 1412/4982] ASoC: pxa2xx-i2s: remove I2S pin setup This removes the calls to pxa_gpio_mode from the pxa2xx-i2s driver. Pin setup should be done during board init via pxa2xx_mfp_config instead. Signed-off-by: Philipp Zabel Acked-by: Eric Miao Signed-off-by: Mark Brown --- sound/soc/pxa/pxa2xx-i2s.c | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index 517991fb109..83b59d7fe96 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c @@ -25,20 +25,11 @@ #include #include -#include #include #include "pxa2xx-pcm.h" #include "pxa2xx-i2s.h" -struct pxa2xx_gpio { - u32 sys; - u32 rx; - u32 tx; - u32 clk; - u32 frm; -}; - /* * I2S Controller Register and Bit Definitions */ @@ -106,21 +97,6 @@ static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_in = { DCMD_BURST32 | DCMD_WIDTH4, }; -static struct pxa2xx_gpio gpio_bus[] = { - { /* I2S SoC Slave */ - .rx = GPIO29_SDATA_IN_I2S_MD, - .tx = GPIO30_SDATA_OUT_I2S_MD, - .clk = GPIO28_BITCLK_IN_I2S_MD, - .frm = GPIO31_SYNC_I2S_MD, - }, - { /* I2S SoC Master */ - .rx = GPIO29_SDATA_IN_I2S_MD, - .tx = GPIO30_SDATA_OUT_I2S_MD, - .clk = GPIO28_BITCLK_OUT_I2S_MD, - .frm = GPIO31_SYNC_I2S_MD, - }, -}; - static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { @@ -181,9 +157,6 @@ static int pxa2xx_i2s_set_dai_sysclk(struct snd_soc_dai *cpu_dai, if (clk_id != PXA2XX_I2S_SYSCLK) return -ENODEV; - if (pxa_i2s.master && dir == SND_SOC_CLOCK_OUT) - pxa_gpio_mode(gpio_bus[pxa_i2s.master].sys); - return 0; } @@ -194,10 +167,6 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - pxa_gpio_mode(gpio_bus[pxa_i2s.master].rx); - pxa_gpio_mode(gpio_bus[pxa_i2s.master].tx); - pxa_gpio_mode(gpio_bus[pxa_i2s.master].frm); - pxa_gpio_mode(gpio_bus[pxa_i2s.master].clk); BUG_ON(IS_ERR(clk_i2s)); clk_enable(clk_i2s); pxa_i2s_wait(); @@ -398,11 +367,6 @@ static struct platform_driver pxa2xx_i2s_driver = { static int __init pxa2xx_i2s_init(void) { - if (cpu_is_pxa27x()) - gpio_bus[1].sys = GPIO113_I2S_SYSCLK_MD; - else - gpio_bus[1].sys = GPIO32_SYSCLK_I2S_MD; - clk_i2s = ERR_PTR(-ENOENT); return platform_driver_register(&pxa2xx_i2s_driver); } -- GitLab From d6301d3dd1c287b32132dda15272a50c11e92a14 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 8 Feb 2009 19:24:13 -0800 Subject: [PATCH 1413/4982] net: Increase default NET_SKB_PAD to 32. Several devices need to insert some "pre headers" in front of the main packet data when they transmit a packet. Currently we allocate only 16 bytes of pad room and this ends up not being enough for some types of hardware (NIU, usb-net, s390 qeth, etc.) So increase this to 32. Note that drivers still need to check in their transmit routine whether enough headroom exists, and if not use skb_realloc_headroom(). Tunneling, IPSEC, and other encapsulation methods can cause the padding area to be used up. Signed-off-by: David S. Miller --- include/linux/skbuff.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 08670d01747..5eba4007e07 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1287,7 +1287,7 @@ static inline int skb_network_offset(const struct sk_buff *skb) * The networking layer reserves some headroom in skb data (via * dev_alloc_skb). This is used to avoid having to reallocate skb data when * the header has to grow. In the default case, if the header has to grow - * 16 bytes or less we avoid the reallocation. + * 32 bytes or less we avoid the reallocation. * * Unfortunately this headroom changes the DMA alignment of the resulting * network packet. As for NET_IP_ALIGN, this unaligned DMA is expensive @@ -1295,11 +1295,11 @@ static inline int skb_network_offset(const struct sk_buff *skb) * perhaps setting it to a cacheline in size (since that will maintain * cacheline alignment of the DMA). It must be a power of 2. * - * Various parts of the networking layer expect at least 16 bytes of + * Various parts of the networking layer expect at least 32 bytes of * headroom, you should not reduce this. */ #ifndef NET_SKB_PAD -#define NET_SKB_PAD 16 +#define NET_SKB_PAD 32 #endif extern int ___pskb_trim(struct sk_buff *skb, unsigned int len); -- GitLab From 4ae5544f9a33e4ae306e337f96951eb3ff2df6d9 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 8 Feb 2009 18:00:36 +0000 Subject: [PATCH 1414/4982] gro: Remember number of held packets instead of counting every time This patch prepares for the move of the same_flow checks out of dev_gro_receive. As such we need to remember the number of held packets since doing a loop just to count them every time is silly. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- include/linux/netdevice.h | 3 +++ net/core/dev.c | 12 +++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 864519e585f..9ee344bc6c1 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -314,6 +314,9 @@ struct napi_struct { spinlock_t poll_lock; int poll_owner; #endif + + unsigned int gro_count; + struct net_device *dev; struct list_head dev_list; struct sk_buff *gro_list; diff --git a/net/core/dev.c b/net/core/dev.c index 709a9a92225..ae0b66936ab 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2372,6 +2372,7 @@ void napi_gro_flush(struct napi_struct *napi) napi_gro_complete(skb); } + napi->gro_count = 0; napi->gro_list = NULL; } EXPORT_SYMBOL(napi_gro_flush); @@ -2402,7 +2403,6 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) struct packet_type *ptype; __be16 type = skb->protocol; struct list_head *head = &ptype_base[ntohs(type) & PTYPE_HASH_MASK]; - int count = 0; int same_flow; int mac_len; int ret; @@ -2430,8 +2430,6 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) NAPI_GRO_CB(skb)->free = 0; for (p = napi->gro_list; p; p = p->next) { - count++; - if (!NAPI_GRO_CB(p)->same_flow) continue; @@ -2457,15 +2455,16 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) *pp = nskb->next; nskb->next = NULL; napi_gro_complete(nskb); - count--; + napi->gro_count--; } if (same_flow) goto ok; - if (NAPI_GRO_CB(skb)->flush || count >= MAX_GRO_SKBS) + if (NAPI_GRO_CB(skb)->flush || napi->gro_count >= MAX_GRO_SKBS) goto normal; + napi->gro_count++; NAPI_GRO_CB(skb)->count = 1; skb_shinfo(skb)->gso_size = skb_gro_len(skb); skb->next = napi->gro_list; @@ -2713,6 +2712,7 @@ void netif_napi_add(struct net_device *dev, struct napi_struct *napi, int (*poll)(struct napi_struct *, int), int weight) { INIT_LIST_HEAD(&napi->poll_list); + napi->gro_count = 0; napi->gro_list = NULL; napi->skb = NULL; napi->poll = poll; @@ -2741,6 +2741,7 @@ void netif_napi_del(struct napi_struct *napi) } napi->gro_list = NULL; + napi->gro_count = 0; } EXPORT_SYMBOL(netif_napi_del); @@ -5246,6 +5247,7 @@ static int __init net_dev_init(void) queue->backlog.poll = process_backlog; queue->backlog.weight = weight_p; queue->backlog.gro_list = NULL; + queue->backlog.gro_count = 0; } dev_boot_phase = 0; -- GitLab From aa4b9f533ed5a22952e038b9fac2447ccc682124 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 8 Feb 2009 18:00:37 +0000 Subject: [PATCH 1415/4982] gro: Optimise Ethernet header comparison This patch optimises the Ethernet header comparison to use 2-byte and 4-byte xors instead of memcmp. In order to facilitate this, the actual comparison is now carried out by the callers of the shared dev_gro_receive function. This has a significant impact when receiving 1500B packets through 10GbE. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- include/linux/etherdevice.h | 21 +++++++++++++++++++++ include/linux/netdevice.h | 7 +++++++ net/8021q/vlan_core.c | 4 +++- net/core/dev.c | 23 ++--------------------- 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h index 1cb0f0b9092..a1f17abba7d 100644 --- a/include/linux/etherdevice.h +++ b/include/linux/etherdevice.h @@ -184,4 +184,25 @@ static inline unsigned compare_ether_addr_64bits(const u8 addr1[6+2], } #endif /* __KERNEL__ */ +/** + * compare_ether_header - Compare two Ethernet headers + * @a: Pointer to Ethernet header + * @b: Pointer to Ethernet header + * + * Compare two ethernet headers, returns 0 if equal. + * This assumes that the network header (i.e., IP header) is 4-byte + * aligned OR the platform can handle unaligned access. This is the + * case for all packets coming into netif_receive_skb or similar + * entry points. + */ + +static inline int compare_ether_header(const void *a, const void *b) +{ + u32 *a32 = (u32 *)((u8 *)a + 2); + u32 *b32 = (u32 *)((u8 *)b + 2); + + return (*(u16 *)a ^ *(u16 *)b) | (a32[0] ^ b32[0]) | + (a32[1] ^ b32[1]) | (a32[2] ^ b32[2]); +} + #endif /* _LINUX_ETHERDEVICE_H */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 9ee344bc6c1..355662aac94 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1117,6 +1117,13 @@ static inline void skb_gro_reset_offset(struct sk_buff *skb) NAPI_GRO_CB(skb)->data_offset = 0; } +static inline void *skb_gro_mac_header(struct sk_buff *skb) +{ + return skb_mac_header(skb) < skb->data ? skb_mac_header(skb) : + page_address(skb_shinfo(skb)->frags[0].page) + + skb_shinfo(skb)->frags[0].page_offset; +} + static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, const void *daddr, const void *saddr, diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 378fa69d625..70435af153f 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -85,7 +85,9 @@ static int vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp, goto drop; for (p = napi->gro_list; p; p = p->next) { - NAPI_GRO_CB(p)->same_flow = p->dev == skb->dev; + NAPI_GRO_CB(p)->same_flow = + p->dev == skb->dev && !compare_ether_header( + skb_mac_header(p), skb_gro_mac_header(skb)); NAPI_GRO_CB(p)->flush = 0; } diff --git a/net/core/dev.c b/net/core/dev.c index ae0b66936ab..1e27a67df24 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -215,13 +215,6 @@ static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex) return &net->dev_index_head[ifindex & ((1 << NETDEV_HASHBITS) - 1)]; } -static inline void *skb_gro_mac_header(struct sk_buff *skb) -{ - return skb_mac_header(skb) < skb->data ? skb_mac_header(skb) : - page_address(skb_shinfo(skb)->frags[0].page) + - skb_shinfo(skb)->frags[0].page_offset; -} - /* Device list insertion */ static int list_netdevice(struct net_device *dev) { @@ -2415,29 +2408,16 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) rcu_read_lock(); list_for_each_entry_rcu(ptype, head, list) { - struct sk_buff *p; - void *mac; - if (ptype->type != type || ptype->dev || !ptype->gro_receive) continue; skb_set_network_header(skb, skb_gro_offset(skb)); - mac = skb_gro_mac_header(skb); mac_len = skb->network_header - skb->mac_header; skb->mac_len = mac_len; NAPI_GRO_CB(skb)->same_flow = 0; NAPI_GRO_CB(skb)->flush = 0; NAPI_GRO_CB(skb)->free = 0; - for (p = napi->gro_list; p; p = p->next) { - if (!NAPI_GRO_CB(p)->same_flow) - continue; - - if (p->mac_len != mac_len || - memcmp(skb_mac_header(p), mac, mac_len)) - NAPI_GRO_CB(p)->same_flow = 0; - } - pp = ptype->gro_receive(&napi->gro_list, skb); break; } @@ -2492,7 +2472,8 @@ static int __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) struct sk_buff *p; for (p = napi->gro_list; p; p = p->next) { - NAPI_GRO_CB(p)->same_flow = 1; + NAPI_GRO_CB(p)->same_flow = !compare_ether_header( + skb_mac_header(p), skb_gro_mac_header(skb)); NAPI_GRO_CB(p)->flush = 0; } -- GitLab From a5ad24be728d4352b71a81fba471aa41eb71f83a Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 8 Feb 2009 18:00:39 +0000 Subject: [PATCH 1416/4982] gro: Optimise IPv4 packet reception As this function can be called more than half a million times for 10GbE, it's important to optimise it as much as we can. This patch does some obvious changes to use 2-byte and 4-byte operations instead of byte-oriented ones where possible. Bit ops are also used to replace logical ops to reduce branching. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv4/af_inet.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index c79087719df..627be4dc7fb 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1263,7 +1263,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, if (!ops || !ops->gro_receive) goto out_unlock; - if (iph->version != 4 || iph->ihl != 5) + if (*(u8 *)iph != 0x45) goto out_unlock; if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) @@ -1281,17 +1281,18 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, iph2 = ip_hdr(p); - if (iph->protocol != iph2->protocol || - iph->tos != iph2->tos || - memcmp(&iph->saddr, &iph2->saddr, 8)) { + if ((iph->protocol ^ iph2->protocol) | + (iph->tos ^ iph2->tos) | + (iph->saddr ^ iph2->saddr) | + (iph->daddr ^ iph2->daddr)) { NAPI_GRO_CB(p)->same_flow = 0; continue; } /* All fields must match except length and checksum. */ NAPI_GRO_CB(p)->flush |= - memcmp(&iph->frag_off, &iph2->frag_off, 4) || - (u16)(ntohs(iph2->id) + NAPI_GRO_CB(p)->count) != id; + (iph->ttl ^ iph2->ttl) | + ((u16)(ntohs(iph2->id) + NAPI_GRO_CB(p)->count) ^ id); NAPI_GRO_CB(p)->flush |= flush; } -- GitLab From aa6320d336971171df1d13c1c284facf10804881 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 8 Feb 2009 18:00:40 +0000 Subject: [PATCH 1417/4982] gro: Optimise TCP packet reception gro: Optimise TCP packet reception As this function can be called more than half a million times for 10GbE, it's important to optimise it as much as we can. This patch uses bit ops to logical ops, as well as open coding memcmp to exploit alignment properties. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv4/tcp.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 73266b79c19..90b2f3c192f 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2478,9 +2478,9 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) struct tcphdr *th2; unsigned int thlen; unsigned int flags; - unsigned int total; unsigned int mss = 1; int flush = 1; + int i; th = skb_gro_header(skb, sizeof(*th)); if (unlikely(!th)) @@ -2504,7 +2504,7 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) th2 = tcp_hdr(p); - if (th->source != th2->source || th->dest != th2->dest) { + if ((th->source ^ th2->source) | (th->dest ^ th2->dest)) { NAPI_GRO_CB(p)->same_flow = 0; continue; } @@ -2519,14 +2519,15 @@ found: flush |= flags & TCP_FLAG_CWR; flush |= (flags ^ tcp_flag_word(th2)) & ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH); - flush |= th->ack_seq != th2->ack_seq || th->window != th2->window; - flush |= memcmp(th + 1, th2 + 1, thlen - sizeof(*th)); + flush |= (th->ack_seq ^ th2->ack_seq) | (th->window ^ th2->window); + for (i = sizeof(*th); !flush && i < thlen; i += 4) + flush |= *(u32 *)((u8 *)th + i) ^ + *(u32 *)((u8 *)th2 + i); - total = skb_gro_len(p); mss = skb_shinfo(p)->gso_size; - flush |= skb_gro_len(skb) > mss || !skb_gro_len(skb); - flush |= ntohl(th2->seq) + total != ntohl(th->seq); + flush |= (skb_gro_len(skb) > mss) | !skb_gro_len(skb); + flush |= (ntohl(th2->seq) + skb_gro_len(p)) ^ ntohl(th->seq); if (flush || skb_gro_receive(head, skb)) { mss = 1; -- GitLab From 8663ae55f39e99c25242adb6242a191258a4eca1 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Sun, 8 Feb 2009 19:50:34 -0200 Subject: [PATCH 1418/4982] ALSA: hda - Bind new ecs mobo id (1019:2950) to model=ecs202 This adds a new sound quirk entry (model=ecs202) for an ecs motherboard with IDT STAC9221 codec (1019:2950). Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 85dc642d113..d16d5c60eec 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -2108,6 +2108,8 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = { "ECS/PC chips", STAC_ECS_202), SND_PCI_QUIRK(0x1019, 0x2820, "ECS/PC chips", STAC_ECS_202), + SND_PCI_QUIRK(0x1019, 0x2950, + "ECS/PC chips", STAC_ECS_202), {} /* terminator */ }; -- GitLab From 23c7b521c250b261dd97a7a06d5a2e74b56233d5 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Sun, 8 Feb 2009 19:51:28 -0200 Subject: [PATCH 1419/4982] ALSA: hda - Don't touch non-existent port f on 4-port 92hd71bxx codecs When checking for input amps on pins 0x0a, 0x0d and 0x0f, and initializing them for 92hd71xxx codec models, we must skip nid 0x0f for 4-port models too like with 5-port models, as it is unused (nid 0x0f is vendor reserved in 4-port models). Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index d16d5c60eec..2f4e090b055 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -5072,6 +5072,8 @@ again: switch (codec->vendor_id) { case 0x111d76b6: /* 4 Port without Analog Mixer */ case 0x111d76b7: + unmute_init++; + /* fallthru */ case 0x111d76b4: /* 6 Port without Analog Mixer */ case 0x111d76b5: memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_nomixer, -- GitLab From 0f3c2a89c1451cdf6328f99977bd9decd4f708e1 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 8 Feb 2009 16:18:03 -0800 Subject: [PATCH 1420/4982] irq: clear kstat_irqs Impact: get correct kstat_irqs [/proc/interrupts] for msi/msi-x etc need to call clear_kstat_irqs(), so when we reuse that irq_desc, we get correct kstat in /proc/interrupts. This makes /proc/interrupts not have entries. Don't need to worry about arch that doesn't support genirq, because they will not call dynamic_irq_cleanup(). v2: simplify and make clear_kstat_irqs more robust Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- kernel/irq/chip.c | 1 + kernel/irq/handle.c | 5 +++++ kernel/irq/internals.h | 1 + 3 files changed, 7 insertions(+) diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index f63c706d25e..1310856cb22 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -78,6 +78,7 @@ void dynamic_irq_cleanup(unsigned int irq) desc->handle_irq = handle_bad_irq; desc->chip = &no_irq_chip; desc->name = NULL; + clear_kstat_irqs(desc); spin_unlock_irqrestore(&desc->lock, flags); } diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 48299a8a22f..1b473e7569a 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -242,6 +242,11 @@ struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu) } #endif /* !CONFIG_SPARSE_IRQ */ +void clear_kstat_irqs(struct irq_desc *desc) +{ + memset(desc->kstat_irqs, 0, nr_cpu_ids * sizeof(*(desc->kstat_irqs))); +} + /* * What should we do if we get a hw irq event on an illegal vector? * Each architecture has to answer this themself. diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index e6d0a43cc12..b60950bf5a1 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h @@ -15,6 +15,7 @@ extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, extern struct lock_class_key irq_desc_lock_class; extern void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr); +extern void clear_kstat_irqs(struct irq_desc *desc); extern spinlock_t sparse_irq_lock; extern struct irq_desc *irq_desc_ptrs[NR_IRQS]; -- GitLab From 005bf0e6fa0e9543933fe2e36322af649df7cacb Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 8 Feb 2009 16:18:03 -0800 Subject: [PATCH 1421/4982] irq: optimize init_kstat_irqs/init_copy_kstat_irqs Simplify and make init_kstat_irqs etc more type proof, suggested by Andrew. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- kernel/irq/handle.c | 20 +++++++++++--------- kernel/irq/numa_migrate.c | 11 +++-------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 1b473e7569a..49d642b62c6 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -71,19 +71,21 @@ static struct irq_desc irq_desc_init = { void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr) { - unsigned long bytes; - char *ptr; int node; - - /* Compute how many bytes we need per irq and allocate them */ - bytes = nr * sizeof(unsigned int); + void *ptr; node = cpu_to_node(cpu); - ptr = kzalloc_node(bytes, GFP_ATOMIC, node); - printk(KERN_DEBUG " alloc kstat_irqs on cpu %d node %d\n", cpu, node); + ptr = kzalloc_node(nr * sizeof(*desc->kstat_irqs), GFP_ATOMIC, node); - if (ptr) - desc->kstat_irqs = (unsigned int *)ptr; + /* + * don't overwite if can not get new one + * init_copy_kstat_irqs() could still use old one + */ + if (ptr) { + printk(KERN_DEBUG " alloc kstat_irqs on cpu %d node %d\n", + cpu, node); + desc->kstat_irqs = ptr; + } } static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu) diff --git a/kernel/irq/numa_migrate.c b/kernel/irq/numa_migrate.c index ecf765c6a77..c500cfe422b 100644 --- a/kernel/irq/numa_migrate.c +++ b/kernel/irq/numa_migrate.c @@ -17,16 +17,11 @@ static void init_copy_kstat_irqs(struct irq_desc *old_desc, struct irq_desc *desc, int cpu, int nr) { - unsigned long bytes; - init_kstat_irqs(desc, cpu, nr); - if (desc->kstat_irqs != old_desc->kstat_irqs) { - /* Compute how many bytes we need per irq and allocate them */ - bytes = nr * sizeof(unsigned int); - - memcpy(desc->kstat_irqs, old_desc->kstat_irqs, bytes); - } + if (desc->kstat_irqs != old_desc->kstat_irqs) + memcpy(desc->kstat_irqs, old_desc->kstat_irqs, + nr * sizeof(*desc->kstat_irqs)); } static void free_kstat_irqs(struct irq_desc *old_desc, struct irq_desc *desc) -- GitLab From f1ee5548a6507d2b4293635c61ddbf12e2c00e94 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 8 Feb 2009 16:18:03 -0800 Subject: [PATCH 1422/4982] x86/irq: optimize nr_irqs Impact: make nr_irqs depend more on cards used in a system depend on nr_irq_gsi more, and have a ratio for MSI. v2: make nr_irqs less than NR_VECTORS * nr_cpu_ids aka if only one cpu, we only can support nr_irqs = NR_VECTORS Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/io_apic.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 9578d33f20a..43f95d7b13a 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -3479,9 +3479,9 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) sub_handle = 0; list_for_each_entry(msidesc, &dev->msi_list, list) { irq = create_irq_nr(irq_want); - irq_want++; if (irq == 0) return -1; + irq_want = irq + 1; #ifdef CONFIG_INTR_REMAP if (!intr_remapping_enabled) goto no_ir; @@ -3825,11 +3825,17 @@ int __init arch_probe_nr_irqs(void) { int nr; - nr = ((8 * nr_cpu_ids) > (32 * nr_ioapics) ? - (NR_VECTORS + (8 * nr_cpu_ids)) : - (NR_VECTORS + (32 * nr_ioapics))); + if (nr_irqs > (NR_VECTORS * nr_cpu_ids)) + nr_irqs = NR_VECTORS * nr_cpu_ids; - if (nr < nr_irqs && nr > nr_irqs_gsi) + nr = nr_irqs_gsi + 8 * nr_cpu_ids; +#if defined(CONFIG_PCI_MSI) || defined(CONFIG_HT_IRQ) + /* + * for MSI and HT dyn irq + */ + nr += nr_irqs_gsi * 16; +#endif + if (nr < nr_irqs) nr_irqs = nr; return 0; -- GitLab From abcaa2b8319a7673e76c2391cb5de3045ab1b401 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 8 Feb 2009 16:18:03 -0800 Subject: [PATCH 1423/4982] x86: use NR_IRQS_LEGACY to replace 16 Impact: cleanup also could kill platform_legacy_irq Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/include/asm/hw_irq.h | 4 +--- arch/x86/kernel/io_apic.c | 8 ++++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index 1a20e3d1200..1b82781b898 100644 --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h @@ -25,8 +25,6 @@ #include #include -#define platform_legacy_irq(irq) ((irq) < 16) - /* Interrupt handlers registered during init_IRQ */ extern void apic_timer_interrupt(void); extern void error_interrupt(void); @@ -58,7 +56,7 @@ extern void make_8259A_irq(unsigned int irq); extern void init_8259A(int aeoi); /* IOAPIC */ -#define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs)) +#define IO_APIC_IRQ(x) (((x) >= NR_IRQS_LEGACY) || ((1<<(x)) & io_apic_irqs)) extern unsigned long io_apic_irqs; extern void init_VISWS_APIC_irqs(void); diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 43f95d7b13a..e5be9f35ea5 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -3165,6 +3165,7 @@ static int __init ioapic_init_sysfs(void) device_initcall(ioapic_init_sysfs); +static int nr_irqs_gsi = NR_IRQS_LEGACY; /* * Dynamic irq allocate and deallocation */ @@ -3179,11 +3180,11 @@ unsigned int create_irq_nr(unsigned int irq_want) struct irq_desc *desc_new = NULL; irq = 0; + if (irq_want < nr_irqs_gsi) + irq_want = nr_irqs_gsi; + spin_lock_irqsave(&vector_lock, flags); for (new = irq_want; new < nr_irqs; new++) { - if (platform_legacy_irq(new)) - continue; - desc_new = irq_to_desc_alloc_cpu(new, cpu); if (!desc_new) { printk(KERN_INFO "can not get irq_desc for %d\n", new); @@ -3208,7 +3209,6 @@ unsigned int create_irq_nr(unsigned int irq_want) return irq; } -static int nr_irqs_gsi = NR_IRQS_LEGACY; int create_irq(void) { unsigned int irq_want; -- GitLab From f72dccace737df74d04a96461785a3ad61724b9f Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 8 Feb 2009 16:18:03 -0800 Subject: [PATCH 1424/4982] x86: check_timer cleanup Impact: make check-timer more robust potentially solve boot fragility For edge trigger io-apic routing, we already unmasked the pin via setup_IO_APIC_irq(), so don't unmask it again. Also call local_irq_disable() between timer_irq_works(), because it calls local_irq_enable() inside. Also remove not needed apic version reading for 64-bit Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/io_apic.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index e5be9f35ea5..855209a1b17 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -1657,7 +1657,7 @@ static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin, * to the first CPU. */ entry.dest_mode = apic->irq_dest_mode; - entry.mask = 1; /* mask IRQ now */ + entry.mask = 0; /* don't mask IRQ for edge */ entry.dest = apic->cpu_mask_to_apicid(apic->target_cpus()); entry.delivery_mode = apic->irq_delivery_mode; entry.polarity = 0; @@ -2863,14 +2863,10 @@ static inline void __init check_timer(void) int cpu = boot_cpu_id; int apic1, pin1, apic2, pin2; unsigned long flags; - unsigned int ver; int no_pin1 = 0; local_irq_save(flags); - ver = apic_read(APIC_LVR); - ver = GET_APIC_VERSION(ver); - /* * get/set the timer IRQ vector: */ @@ -2889,7 +2885,13 @@ static inline void __init check_timer(void) apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); init_8259A(1); #ifdef CONFIG_X86_32 - timer_ack = (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver)); + { + unsigned int ver; + + ver = apic_read(APIC_LVR); + ver = GET_APIC_VERSION(ver); + timer_ack = (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver)); + } #endif pin1 = find_isa_irq_pin(0, mp_INT); @@ -2928,8 +2930,17 @@ static inline void __init check_timer(void) if (no_pin1) { add_pin_to_irq_cpu(cfg, cpu, apic1, pin1); setup_timer_IRQ0_pin(apic1, pin1, cfg->vector); + } else { + /* for edge trigger, setup_IO_APIC_irq already + * leave it unmasked. + * so only need to unmask if it is level-trigger + * do we really have level trigger timer? + */ + int idx; + idx = find_irq_entry(apic1, pin1, mp_INT); + if (idx != -1 && irq_trigger(idx)) + unmask_IO_APIC_irq_desc(desc); } - unmask_IO_APIC_irq_desc(desc); if (timer_irq_works()) { if (nmi_watchdog == NMI_IO_APIC) { setup_nmi(); @@ -2943,6 +2954,7 @@ static inline void __init check_timer(void) if (intr_remapping_enabled) panic("timer doesn't work through Interrupt-remapped IO-APIC"); #endif + local_irq_disable(); clear_IO_APIC_pin(apic1, pin1); if (!no_pin1) apic_printk(APIC_QUIET, KERN_ERR "..MP-BIOS bug: " @@ -2957,7 +2969,6 @@ static inline void __init check_timer(void) */ replace_pin_at_irq_cpu(cfg, cpu, apic1, pin1, apic2, pin2); setup_timer_IRQ0_pin(apic2, pin2, cfg->vector); - unmask_IO_APIC_irq_desc(desc); enable_8259A_irq(0); if (timer_irq_works()) { apic_printk(APIC_QUIET, KERN_INFO "....... works.\n"); @@ -2972,6 +2983,7 @@ static inline void __init check_timer(void) /* * Cleanup, just in case ... */ + local_irq_disable(); disable_8259A_irq(0); clear_IO_APIC_pin(apic2, pin2); apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n"); @@ -2997,6 +3009,7 @@ static inline void __init check_timer(void) apic_printk(APIC_QUIET, KERN_INFO "..... works.\n"); goto out; } + local_irq_disable(); disable_8259A_irq(0); apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector); apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n"); @@ -3014,6 +3027,7 @@ static inline void __init check_timer(void) apic_printk(APIC_QUIET, KERN_INFO "..... works.\n"); goto out; } + local_irq_disable(); apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n"); panic("IO-APIC + timer doesn't work! Boot with apic=debug and send a " "report. Then try booting with the 'noapic' option.\n"); -- GitLab From cc6c50066ec1ac98bef97117e2f078bb89bbccc7 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 8 Feb 2009 16:18:03 -0800 Subject: [PATCH 1425/4982] x86: find nr_irqs_gsi with mp_ioapic_routing Impact: find right nr_irqs_gsi on some systems. One test-system has gap between gsi's: [ 0.000000] ACPI: IOAPIC (id[0x04] address[0xfec00000] gsi_base[0]) [ 0.000000] IOAPIC[0]: apic_id 4, version 0, address 0xfec00000, GSI 0-23 [ 0.000000] ACPI: IOAPIC (id[0x05] address[0xfeafd000] gsi_base[48]) [ 0.000000] IOAPIC[1]: apic_id 5, version 0, address 0xfeafd000, GSI 48-54 [ 0.000000] ACPI: IOAPIC (id[0x06] address[0xfeafc000] gsi_base[56]) [ 0.000000] IOAPIC[2]: apic_id 6, version 0, address 0xfeafc000, GSI 56-62 ... [ 0.000000] nr_irqs_gsi: 38 So nr_irqs_gsi is not right. some irq for MSI will overwrite with io_apic. need to get that with acpi_probe_gsi when acpi io_apic is used Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/include/asm/mpspec.h | 6 ++++++ arch/x86/kernel/acpi/boot.c | 23 +++++++++++++++++++++++ arch/x86/kernel/io_apic.c | 20 +++++++++++++++----- 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h index d22f732eab8..8c5620147c4 100644 --- a/arch/x86/include/asm/mpspec.h +++ b/arch/x86/include/asm/mpspec.h @@ -73,6 +73,7 @@ extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi); extern void mp_config_acpi_legacy_irqs(void); extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low); +extern int acpi_probe_gsi(void); #ifdef CONFIG_X86_IO_APIC extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin, u32 gsi, int triggering, int polarity); @@ -84,6 +85,11 @@ mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin, return 0; } #endif +#else /* !CONFIG_ACPI: */ +static inline int acpi_probe_gsi(void) +{ + return 0; +} #endif /* CONFIG_ACPI */ #define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_APICS) diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 3efa996b036..c334fe75dcd 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -961,6 +961,29 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) nr_ioapics++; } +int __init acpi_probe_gsi(void) +{ + int idx; + int gsi; + int max_gsi = 0; + + if (acpi_disabled) + return 0; + + if (!acpi_ioapic) + return 0; + + max_gsi = 0; + for (idx = 0; idx < nr_ioapics; idx++) { + gsi = mp_ioapic_routing[idx].gsi_end; + + if (gsi > max_gsi) + max_gsi = gsi; + } + + return max_gsi + 1; +} + static void assign_to_mp_irq(struct mpc_intsrc *m, struct mpc_intsrc *mp_irq) { diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 855209a1b17..56e51eb551a 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -3824,14 +3824,24 @@ int __init io_apic_get_redir_entries (int ioapic) void __init probe_nr_irqs_gsi(void) { - int idx; int nr = 0; - for (idx = 0; idx < nr_ioapics; idx++) - nr += io_apic_get_redir_entries(idx) + 1; - - if (nr > nr_irqs_gsi) + nr = acpi_probe_gsi(); + if (nr > nr_irqs_gsi) { nr_irqs_gsi = nr; + } else { + /* for acpi=off or acpi is not compiled in */ + int idx; + + nr = 0; + for (idx = 0; idx < nr_ioapics; idx++) + nr += io_apic_get_redir_entries(idx) + 1; + + if (nr > nr_irqs_gsi) + nr_irqs_gsi = nr; + } + + printk(KERN_DEBUG "nr_irqs_gsi: %d\n", nr_irqs_gsi); } #ifdef CONFIG_SPARSE_IRQ -- GitLab From 2c344e9d6e1938fdf15e93c56d6fe42f8410e9d3 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sat, 7 Feb 2009 12:23:37 -0800 Subject: [PATCH 1426/4982] x86: don't pretend that non-framepointer stack traces are reliable Without frame pointers enabled, the x86 stack traces should not pretend to be reliable; instead they should just be what they are: unreliable. The effect of this is that they have a '?' printed in the stacktrace, to warn the reader that these entries are guesses rather than known based on more reliable information. Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar --- arch/x86/kernel/dumpstack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index 6b1f6f6f866..87d103ded1c 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c @@ -99,7 +99,7 @@ print_context_stack(struct thread_info *tinfo, frame = frame->next_frame; bp = (unsigned long) frame; } else { - ops->address(data, addr, bp == 0); + ops->address(data, addr, 0); } print_ftrace_graph_addr(addr, data, ops, tinfo, graph); } -- GitLab From 548c8933801c9ee347b6f1bad2491e4286a4f3a2 Mon Sep 17 00:00:00 2001 From: Hannes Eder Date: Sun, 8 Feb 2009 20:24:47 +0100 Subject: [PATCH 1427/4982] kernel/irq: fix sparse warning: make symbol static While being at it make every occurrence of 'do_irq_select_affinity' have the same signature in terms of signedness of the first argument. Fix this sparse warning: kernel/irq/manage.c:112:5: warning: symbol 'do_irq_select_affinity' was not declared. Should it be static? Also rename do_irq_select_affinity() to setup_affinity() - shorter name and clearer naming. Signed-off-by: Hannes Eder Acked-by: Matthew Wilcox Signed-off-by: Ingo Molnar --- kernel/irq/manage.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 291f0366455..38008b80bd5 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -109,7 +109,7 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask) /* * Generic version of the affinity autoselector. */ -int do_irq_select_affinity(unsigned int irq, struct irq_desc *desc) +static int setup_affinity(unsigned int irq, struct irq_desc *desc) { if (!irq_can_set_affinity(irq)) return 0; @@ -133,7 +133,7 @@ set_affinity: return 0; } #else -static inline int do_irq_select_affinity(unsigned int irq, struct irq_desc *d) +static inline int setup_affinity(unsigned int irq, struct irq_desc *d) { return irq_select_affinity(irq); } @@ -149,14 +149,14 @@ int irq_select_affinity_usr(unsigned int irq) int ret; spin_lock_irqsave(&desc->lock, flags); - ret = do_irq_select_affinity(irq, desc); + ret = setup_affinity(irq, desc); spin_unlock_irqrestore(&desc->lock, flags); return ret; } #else -static inline int do_irq_select_affinity(int irq, struct irq_desc *desc) +static inline int setup_affinity(unsigned int irq, struct irq_desc *desc) { return 0; } @@ -488,7 +488,7 @@ __setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new) desc->status |= IRQ_NO_BALANCING; /* Set default affinity mask once everything is setup */ - do_irq_select_affinity(irq, desc); + setup_affinity(irq, desc); } else if ((new->flags & IRQF_TRIGGER_MASK) && (new->flags & IRQF_TRIGGER_MASK) -- GitLab From d3770449d3cb058b94ca1d050d5ced4a66c75ce4 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Sun, 8 Feb 2009 09:58:38 -0500 Subject: [PATCH 1428/4982] percpu: make PER_CPU_BASE_SECTION overridable by arches Impact: bug fix IA-64 needs to put percpu data in the seperate section even on UP. Fixes regression caused by "percpu: refactor percpu.h" Signed-off-by: Brian Gerst Acked-by: Tony Luck Signed-off-by: Ingo Molnar --- arch/ia64/include/asm/percpu.h | 4 ++-- include/linux/percpu.h | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/arch/ia64/include/asm/percpu.h b/arch/ia64/include/asm/percpu.h index 77f30b664b4..30cf46534dd 100644 --- a/arch/ia64/include/asm/percpu.h +++ b/arch/ia64/include/asm/percpu.h @@ -27,12 +27,12 @@ extern void *per_cpu_init(void); #else /* ! SMP */ -#define PER_CPU_ATTRIBUTES __attribute__((__section__(".data.percpu"))) - #define per_cpu_init() (__phys_per_cpu_start) #endif /* SMP */ +#define PER_CPU_BASE_SECTION ".data.percpu" + /* * Be extremely careful when taking the address of this variable! Due to virtual * remapping, it is different from the canonical address returned by __get_cpu_var(var)! diff --git a/include/linux/percpu.h b/include/linux/percpu.h index 0e24202b5a4..3577ffd90d4 100644 --- a/include/linux/percpu.h +++ b/include/linux/percpu.h @@ -8,8 +8,15 @@ #include +#ifndef PER_CPU_BASE_SECTION #ifdef CONFIG_SMP #define PER_CPU_BASE_SECTION ".data.percpu" +#else +#define PER_CPU_BASE_SECTION ".data" +#endif +#endif + +#ifdef CONFIG_SMP #ifdef MODULE #define PER_CPU_SHARED_ALIGNED_SECTION "" @@ -20,7 +27,6 @@ #else -#define PER_CPU_BASE_SECTION ".data" #define PER_CPU_SHARED_ALIGNED_SECTION "" #define PER_CPU_FIRST_SECTION "" -- GitLab From 2add8e235cbe0dcd672c33fc322754e15500238c Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Sun, 8 Feb 2009 09:58:39 -0500 Subject: [PATCH 1429/4982] x86: use linker to offset symbols by __per_cpu_load Impact: cleanup and bug fix Use the linker to create symbols for certain per-cpu variables that are offset by __per_cpu_load. This allows the removal of the runtime fixup of the GDT pointer, which fixes a bug with resume reported by Jiri Slaby. Reported-by: Jiri Slaby Signed-off-by: Brian Gerst Acked-by: Jiri Slaby Signed-off-by: Ingo Molnar --- arch/x86/include/asm/percpu.h | 22 ++++++++++++++++++++++ arch/x86/include/asm/processor.h | 2 ++ arch/x86/kernel/cpu/common.c | 6 +----- arch/x86/kernel/head_64.S | 21 ++------------------- arch/x86/kernel/vmlinux_64.lds.S | 8 ++++++++ 5 files changed, 35 insertions(+), 24 deletions(-) diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index 0b64af4f13a..aee103b26d0 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h @@ -34,6 +34,12 @@ #define PER_CPU_VAR(var) per_cpu__##var #endif /* SMP */ +#ifdef CONFIG_X86_64_SMP +#define INIT_PER_CPU_VAR(var) init_per_cpu__##var +#else +#define INIT_PER_CPU_VAR(var) per_cpu__##var +#endif + #else /* ...!ASSEMBLY */ #include @@ -45,6 +51,22 @@ #define __percpu_arg(x) "%" #x #endif +/* + * Initialized pointers to per-cpu variables needed for the boot + * processor need to use these macros to get the proper address + * offset from __per_cpu_load on SMP. + * + * There also must be an entry in vmlinux_64.lds.S + */ +#define DECLARE_INIT_PER_CPU(var) \ + extern typeof(per_cpu_var(var)) init_per_cpu_var(var) + +#ifdef CONFIG_X86_64_SMP +#define init_per_cpu_var(var) init_per_cpu__##var +#else +#define init_per_cpu_var(var) per_cpu_var(var) +#endif + /* For arch-specific code, we can use direct single-insn ops (they * don't give an lvalue though). */ extern void __bad_percpu_size(void); diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 656d02ea509..373d3f628d2 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -393,6 +393,8 @@ union irq_stack_union { }; DECLARE_PER_CPU(union irq_stack_union, irq_stack_union); +DECLARE_INIT_PER_CPU(irq_stack_union); + DECLARE_PER_CPU(char *, irq_stack_ptr); #endif diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 0f73ea42308..41b0de6df87 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -902,12 +902,8 @@ struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table }; DEFINE_PER_CPU_FIRST(union irq_stack_union, irq_stack_union) __aligned(PAGE_SIZE); -#ifdef CONFIG_SMP -DEFINE_PER_CPU(char *, irq_stack_ptr); /* will be set during per cpu init */ -#else DEFINE_PER_CPU(char *, irq_stack_ptr) = - per_cpu_var(irq_stack_union.irq_stack) + IRQ_STACK_SIZE - 64; -#endif + init_per_cpu_var(irq_stack_union.irq_stack) + IRQ_STACK_SIZE - 64; DEFINE_PER_CPU(unsigned long, kernel_stack) = (unsigned long)&init_thread_union - KERNEL_STACK_OFFSET + THREAD_SIZE; diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index a0a2b5ca9b7..2e648e3a5ea 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -205,19 +205,6 @@ ENTRY(secondary_startup_64) pushq $0 popfq -#ifdef CONFIG_SMP - /* - * Fix up static pointers that need __per_cpu_load added. The assembler - * is unable to do this directly. This is only needed for the boot cpu. - * These values are set up with the correct base addresses by C code for - * secondary cpus. - */ - movq initial_gs(%rip), %rax - cmpl $0, per_cpu__cpu_number(%rax) - jne 1f - addq %rax, early_gdt_descr_base(%rip) -1: -#endif /* * We must switch to a new descriptor in kernel space for the GDT * because soon the kernel won't have access anymore to the userspace @@ -275,11 +262,7 @@ ENTRY(secondary_startup_64) ENTRY(initial_code) .quad x86_64_start_kernel ENTRY(initial_gs) -#ifdef CONFIG_SMP - .quad __per_cpu_load -#else - .quad PER_CPU_VAR(irq_stack_union) -#endif + .quad INIT_PER_CPU_VAR(irq_stack_union) __FINITDATA ENTRY(stack_start) @@ -425,7 +408,7 @@ NEXT_PAGE(level2_spare_pgt) early_gdt_descr: .word GDT_ENTRIES*8-1 early_gdt_descr_base: - .quad per_cpu__gdt_page + .quad INIT_PER_CPU_VAR(gdt_page) ENTRY(phys_base) /* This must match the first entry in level2_kernel_pgt */ diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S index 07f62d287ff..087a7f2c639 100644 --- a/arch/x86/kernel/vmlinux_64.lds.S +++ b/arch/x86/kernel/vmlinux_64.lds.S @@ -257,6 +257,14 @@ SECTIONS DWARF_DEBUG } + /* + * Per-cpu symbols which need to be offset from __per_cpu_load + * for the boot processor. + */ +#define INIT_PER_CPU(x) init_per_cpu__##x = per_cpu__##x + __per_cpu_load +INIT_PER_CPU(gdt_page); +INIT_PER_CPU(irq_stack_union); + /* * Build-time check on the image size: */ -- GitLab From 44581a28e805a31661469c4b466b9cd14b36e7b6 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Sun, 8 Feb 2009 09:58:40 -0500 Subject: [PATCH 1430/4982] x86: fix abuse of per_cpu_offset Impact: bug fix Don't use per_cpu_offset() to determine if it valid to access a per-cpu variable for a given cpu number. It is not a valid assumption on x86-64 anymore. Use cpu_possible() instead. Signed-off-by: Brian Gerst Signed-off-by: Ingo Molnar --- arch/x86/mm/numa_64.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c index 08d140fbc31..deb1c1ab786 100644 --- a/arch/x86/mm/numa_64.c +++ b/arch/x86/mm/numa_64.c @@ -702,7 +702,7 @@ void __cpuinit numa_set_node(int cpu, int node) } #ifdef CONFIG_DEBUG_PER_CPU_MAPS - if (cpu >= nr_cpu_ids || !per_cpu_offset(cpu)) { + if (cpu >= nr_cpu_ids || !cpu_possible(cpu)) { printk(KERN_ERR "numa_set_node: invalid cpu# (%d)\n", cpu); dump_stack(); return; @@ -790,7 +790,7 @@ int early_cpu_to_node(int cpu) if (early_per_cpu_ptr(x86_cpu_to_node_map)) return early_per_cpu_ptr(x86_cpu_to_node_map)[cpu]; - if (!per_cpu_offset(cpu)) { + if (!cpu_possible(cpu)) { printk(KERN_WARNING "early_cpu_to_node(%d): no per_cpu area!\n", cpu); dump_stack(); -- GitLab From 726c0d95b6bd06cb83efd36a76ccf03fa9a770f0 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 9 Feb 2009 11:32:17 +0100 Subject: [PATCH 1431/4982] x86: early_printk.c - fix pgtable.h unification fallout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit arch/x86/kernel/early_printk.c: In function ‘early_dbgp_init’: arch/x86/kernel/early_printk.c:827: error: ‘PAGE_KERNEL_NOCACHE’ undeclared (first use in this function) arch/x86/kernel/early_printk.c:827: error: (Each undeclared identifier is reported only once arch/x86/kernel/early_printk.c:827: error: for each function it appears in.) Signed-off-by: Ingo Molnar --- arch/x86/kernel/early_printk.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index 6a36dd228b6..639ad98238a 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c @@ -14,6 +14,7 @@ #include #include #include +#include #include /* Simple VGA output */ -- GitLab From e5f7f202f31fd05e9de7e1ba5a7b30de7855f5aa Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 9 Feb 2009 11:42:57 +0100 Subject: [PATCH 1432/4982] x86, pgtable.h: macro-ify *_page() methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The p?d_page() methods still rely on highlevel types and methods: In file included from arch/x86/kernel/early_printk.c:18: /home/mingo/tip/arch/x86/include/asm/pgtable.h: In function ‘pmd_page’: /home/mingo/tip/arch/x86/include/asm/pgtable.h:516: error: implicit declaration of function ‘__pfn_to_section’ /home/mingo/tip/arch/x86/include/asm/pgtable.h:516: error: initialization makes pointer from integer without a cast /home/mingo/tip/arch/x86/include/asm/pgtable.h:516: error: implicit declaration of function ‘__section_mem_map_addr’ /home/mingo/tip/arch/x86/include/asm/pgtable.h:516: error: return makes pointer from integer without a cast So convert them to macros and document the type dependency. Signed-off-by: Ingo Molnar --- arch/x86/include/asm/pgtable.h | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index a80a956ae65..76696e98f5b 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -473,10 +473,11 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd) return (unsigned long)__va(pmd_val(pmd) & PTE_PFN_MASK); } -static inline struct page *pmd_page(pmd_t pmd) -{ - return pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT); -} +/* + * Currently stuck as a macro due to indirect forward reference to + * linux/mmzone.h's __section_mem_map_addr() definition: + */ +#define pmd_page(pmd) pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT) /* * the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD] @@ -543,10 +544,11 @@ static inline unsigned long pud_page_vaddr(pud_t pud) return (unsigned long)__va((unsigned long)pud_val(pud) & PTE_PFN_MASK); } -static inline struct page *pud_page(pud_t pud) -{ - return pfn_to_page(pud_val(pud) >> PAGE_SHIFT); -} +/* + * Currently stuck as a macro due to indirect forward reference to + * linux/mmzone.h's __section_mem_map_addr() definition: + */ +#define pud_page(pud) pfn_to_page(pud_val(pud) >> PAGE_SHIFT) /* Find an entry in the second-level page table.. */ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address) @@ -582,10 +584,11 @@ static inline unsigned long pgd_page_vaddr(pgd_t pgd) return (unsigned long)__va((unsigned long)pgd_val(pgd) & PTE_PFN_MASK); } -static inline struct page *pgd_page(pgd_t pgd) -{ - return pfn_to_page(pgd_val(pgd) >> PAGE_SHIFT); -} +/* + * Currently stuck as a macro due to indirect forward reference to + * linux/mmzone.h's __section_mem_map_addr() definition: + */ +#define pgd_page(pgd) pfn_to_page(pgd_val(pgd) >> PAGE_SHIFT) /* to find an entry in a page-table-directory. */ static inline unsigned pud_index(unsigned long address) -- GitLab From c47c1b1f3a9d6973108020df1dcab7604f7774dd Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 9 Feb 2009 11:57:45 +0100 Subject: [PATCH 1433/4982] x86, pgtable.h: fix 2-level 32-bit build - pmd_flags() needs to be available on 2-levels too - provide pud_large() wrapper as well - include page.h - it provides basic types relied on by pgtable.h Signed-off-by: Ingo Molnar --- arch/x86/include/asm/page.h | 9 +++++---- arch/x86/include/asm/pgtable.h | 9 +++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h index 0b16b64a8fe..823cc931363 100644 --- a/arch/x86/include/asm/page.h +++ b/arch/x86/include/asm/page.h @@ -139,10 +139,6 @@ static inline pmdval_t native_pmd_val(pmd_t pmd) return pmd.pmd; } -static inline pmdval_t pmd_flags(pmd_t pmd) -{ - return native_pmd_val(pmd) & PTE_FLAGS_MASK; -} #else /* PAGETABLE_LEVELS == 2 */ #include @@ -152,6 +148,11 @@ static inline pmdval_t native_pmd_val(pmd_t pmd) } #endif /* PAGETABLE_LEVELS >= 3 */ +static inline pmdval_t pmd_flags(pmd_t pmd) +{ + return native_pmd_val(pmd) & PTE_FLAGS_MASK; +} + static inline pte_t native_make_pte(pteval_t val) { return (pte_t) { .pte = val }; diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 76696e98f5b..178205305ac 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -1,6 +1,8 @@ #ifndef _ASM_X86_PGTABLE_H #define _ASM_X86_PGTABLE_H +#include + #define FIRST_USER_ADDRESS 0 #define _PAGE_BIT_PRESENT 0 /* is present */ @@ -528,6 +530,13 @@ static inline unsigned long pages_to_mb(unsigned long npg) #define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ remap_pfn_range(vma, vaddr, pfn, size, prot) +#if PAGETABLE_LEVELS == 2 +static inline int pud_large(pud_t pud) +{ + return 0; +} +#endif + #if PAGETABLE_LEVELS > 2 static inline int pud_none(pud_t pud) { -- GitLab From 9b2b76a3344146c4d8d300874e73af8161204f87 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Fri, 6 Feb 2009 14:09:40 -0800 Subject: [PATCH 1434/4982] x86: add handle_irq() to allow interrupt injection Xen uses a different interrupt path, so introduce handle_irq() to allow interrupts to be inserted into the normal interrupt path. This is handled slightly differently on 32 and 64-bit. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/include/asm/irq.h | 1 + arch/x86/kernel/irq_32.c | 34 +++++++++++++++++++++------------- arch/x86/kernel/irq_64.c | 23 ++++++++++++++++------- 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index 592688ed04d..d0f6f7d1771 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h @@ -39,6 +39,7 @@ extern void fixup_irqs(void); extern unsigned int do_IRQ(struct pt_regs *regs); extern void init_IRQ(void); extern void native_init_IRQ(void); +extern bool handle_irq(unsigned irq, struct pt_regs *regs); /* Interrupt vector management */ extern DECLARE_BITMAP(used_vectors, NR_VECTORS); diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index d802c844991..61f09fb969e 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c @@ -191,6 +191,26 @@ static inline int execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) { return 0; } #endif +bool handle_irq(unsigned irq, struct pt_regs *regs) +{ + struct irq_desc *desc; + int overflow; + + overflow = check_stack_overflow(); + + desc = irq_to_desc(irq); + if (unlikely(!desc)) + return false; + + if (!execute_on_irq_stack(overflow, desc, irq)) { + if (unlikely(overflow)) + print_stack_overflow(); + desc->handle_irq(irq, desc); + } + + return true; +} + /* * do_IRQ handles all normal device IRQ's (the special * SMP cross-CPU interrupts have their own specific @@ -200,31 +220,19 @@ unsigned int do_IRQ(struct pt_regs *regs) { struct pt_regs *old_regs; /* high bit used in ret_from_ code */ - int overflow; unsigned vector = ~regs->orig_ax; - struct irq_desc *desc; unsigned irq; - old_regs = set_irq_regs(regs); irq_enter(); irq = __get_cpu_var(vector_irq)[vector]; - overflow = check_stack_overflow(); - - desc = irq_to_desc(irq); - if (unlikely(!desc)) { + if (!handle_irq(irq, regs)) { printk(KERN_EMERG "%s: cannot handle IRQ %d vector %#x cpu %d\n", __func__, irq, vector, smp_processor_id()); BUG(); } - if (!execute_on_irq_stack(overflow, desc, irq)) { - if (unlikely(overflow)) - print_stack_overflow(); - desc->handle_irq(irq, desc); - } - irq_exit(); set_irq_regs(old_regs); return 1; diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index 018963aa6ee..a93f3b0dc7f 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c @@ -48,6 +48,20 @@ static inline void stack_overflow_check(struct pt_regs *regs) #endif } +bool handle_irq(unsigned irq, struct pt_regs *regs) +{ + struct irq_desc *desc; + + stack_overflow_check(regs); + + desc = irq_to_desc(irq); + if (unlikely(!desc)) + return false; + + generic_handle_irq_desc(irq, desc); + return true; +} + /* * do_IRQ handles all normal device IRQ's (the special * SMP cross-CPU interrupts have their own specific @@ -56,7 +70,6 @@ static inline void stack_overflow_check(struct pt_regs *regs) asmlinkage unsigned int __irq_entry do_IRQ(struct pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs(regs); - struct irq_desc *desc; /* high bit used in ret_from_ code */ unsigned vector = ~regs->orig_ax; @@ -64,14 +77,10 @@ asmlinkage unsigned int __irq_entry do_IRQ(struct pt_regs *regs) exit_idle(); irq_enter(); - irq = __get_cpu_var(vector_irq)[vector]; - stack_overflow_check(regs); + irq = __get_cpu_var(vector_irq)[vector]; - desc = irq_to_desc(irq); - if (likely(desc)) - generic_handle_irq_desc(irq, desc); - else { + if (!handle_irq(irq, regs)) { if (!disable_apic) ack_APIC_irq(); -- GitLab From 7c1d7cdcef1b54f4a78892b6b99d19f12c4f398e Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Fri, 6 Feb 2009 14:09:41 -0800 Subject: [PATCH 1435/4982] x86: unify do_IRQ() With the differences in interrupt handling hoisted into handle_irq(), do_IRQ is more or less identical between 32 and 64 bit, so unify it. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/include/asm/irq.h | 3 ++- arch/x86/kernel/irq.c | 38 ++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/irq_32.c | 27 --------------------------- arch/x86/kernel/irq_64.c | 33 --------------------------------- 4 files changed, 40 insertions(+), 61 deletions(-) diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index d0f6f7d1771..107eb219669 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h @@ -36,11 +36,12 @@ static inline int irq_canonicalize(int irq) extern void fixup_irqs(void); #endif -extern unsigned int do_IRQ(struct pt_regs *regs); extern void init_IRQ(void); extern void native_init_IRQ(void); extern bool handle_irq(unsigned irq, struct pt_regs *regs); +extern unsigned int do_IRQ(struct pt_regs *regs); + /* Interrupt vector management */ extern DECLARE_BITMAP(used_vectors, NR_VECTORS); extern int vector_used_by_percpu_irq(unsigned int vector); diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 8b30d0c2512..f13ca1650aa 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -6,10 +6,12 @@ #include #include #include +#include #include #include #include +#include atomic_t irq_err_count; @@ -188,4 +190,40 @@ u64 arch_irq_stat(void) return sum; } + +/* + * do_IRQ handles all normal device IRQ's (the special + * SMP cross-CPU interrupts have their own specific + * handlers). + */ +unsigned int __irq_entry do_IRQ(struct pt_regs *regs) +{ + struct pt_regs *old_regs = set_irq_regs(regs); + + /* high bit used in ret_from_ code */ + unsigned vector = ~regs->orig_ax; + unsigned irq; + + exit_idle(); + irq_enter(); + + irq = __get_cpu_var(vector_irq)[vector]; + + if (!handle_irq(irq, regs)) { +#ifdef CONFIG_X86_64 + if (!disable_apic) + ack_APIC_irq(); +#endif + + if (printk_ratelimit()) + printk(KERN_EMERG "%s: %d.%d No irq handler for vector (irq %d)\n", + __func__, smp_processor_id(), vector, irq); + } + + irq_exit(); + + set_irq_regs(old_regs); + return 1; +} + EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq); diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index 61f09fb969e..4beb9a13873 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c @@ -211,33 +211,6 @@ bool handle_irq(unsigned irq, struct pt_regs *regs) return true; } -/* - * do_IRQ handles all normal device IRQ's (the special - * SMP cross-CPU interrupts have their own specific - * handlers). - */ -unsigned int do_IRQ(struct pt_regs *regs) -{ - struct pt_regs *old_regs; - /* high bit used in ret_from_ code */ - unsigned vector = ~regs->orig_ax; - unsigned irq; - - old_regs = set_irq_regs(regs); - irq_enter(); - irq = __get_cpu_var(vector_irq)[vector]; - - if (!handle_irq(irq, regs)) { - printk(KERN_EMERG "%s: cannot handle IRQ %d vector %#x cpu %d\n", - __func__, irq, vector, smp_processor_id()); - BUG(); - } - - irq_exit(); - set_irq_regs(old_regs); - return 1; -} - #ifdef CONFIG_HOTPLUG_CPU #include diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index a93f3b0dc7f..977d8b43a0d 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c @@ -62,39 +62,6 @@ bool handle_irq(unsigned irq, struct pt_regs *regs) return true; } -/* - * do_IRQ handles all normal device IRQ's (the special - * SMP cross-CPU interrupts have their own specific - * handlers). - */ -asmlinkage unsigned int __irq_entry do_IRQ(struct pt_regs *regs) -{ - struct pt_regs *old_regs = set_irq_regs(regs); - - /* high bit used in ret_from_ code */ - unsigned vector = ~regs->orig_ax; - unsigned irq; - - exit_idle(); - irq_enter(); - - irq = __get_cpu_var(vector_irq)[vector]; - - if (!handle_irq(irq, regs)) { - if (!disable_apic) - ack_APIC_irq(); - - if (printk_ratelimit()) - printk(KERN_EMERG "%s: %d.%d No irq handler for vector\n", - __func__, smp_processor_id(), vector); - } - - irq_exit(); - - set_irq_regs(old_regs); - return 1; -} - #ifdef CONFIG_HOTPLUG_CPU /* A cpu has been removed from cpu_online_mask. Reset irq affinities. */ void fixup_irqs(void) -- GitLab From 54a353a0f845c1dad5fc8183872e750d667838ac Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Fri, 6 Feb 2009 14:09:42 -0800 Subject: [PATCH 1436/4982] xen: set irq_chip disable By default, the irq_chip.disable operation is a no-op. Explicitly set it to disable the Xen event channel. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- drivers/xen/events.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 3141e149d59..7c3705479ea 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -820,8 +820,11 @@ void xen_irq_resume(void) static struct irq_chip xen_dynamic_chip __read_mostly = { .name = "xen-dyn", + + .disable = disable_dynirq, .mask = disable_dynirq, .unmask = enable_dynirq, + .ack = ack_dynirq, .set_affinity = set_affinity_irq, .retrigger = retrigger_dynirq, -- GitLab From 792dc4f6cdacf50d3f2b93756d282fc04ee34bd5 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Fri, 6 Feb 2009 14:09:43 -0800 Subject: [PATCH 1437/4982] xen: use our own eventchannel->irq path Rather than overloading vectors for event channels, take full responsibility for mapping an event channel to irq directly. With this patch Xen has its own irq allocator. When the kernel gets an event channel upcall, it maps the event channel number to an irq and injects it into the normal interrupt path. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/include/asm/xen/events.h | 6 ------ arch/x86/xen/irq.c | 17 +---------------- drivers/xen/events.c | 22 ++++++++++++++++++++-- 3 files changed, 21 insertions(+), 24 deletions(-) diff --git a/arch/x86/include/asm/xen/events.h b/arch/x86/include/asm/xen/events.h index 19144184983..1df35417c41 100644 --- a/arch/x86/include/asm/xen/events.h +++ b/arch/x86/include/asm/xen/events.h @@ -15,10 +15,4 @@ static inline int xen_irqs_disabled(struct pt_regs *regs) return raw_irqs_disabled_flags(regs->flags); } -static inline void xen_do_IRQ(int irq, struct pt_regs *regs) -{ - regs->orig_ax = ~irq; - do_IRQ(regs); -} - #endif /* _ASM_X86_XEN_EVENTS_H */ diff --git a/arch/x86/xen/irq.c b/arch/x86/xen/irq.c index 5a070900ad3..cfd17799bd6 100644 --- a/arch/x86/xen/irq.c +++ b/arch/x86/xen/irq.c @@ -19,21 +19,6 @@ void xen_force_evtchn_callback(void) (void)HYPERVISOR_xen_version(0, NULL); } -static void __init __xen_init_IRQ(void) -{ - int i; - - /* Create identity vector->irq map */ - for(i = 0; i < NR_VECTORS; i++) { - int cpu; - - for_each_possible_cpu(cpu) - per_cpu(vector_irq, cpu)[i] = i; - } - - xen_init_IRQ(); -} - static unsigned long xen_save_fl(void) { struct vcpu_info *vcpu; @@ -127,7 +112,7 @@ static void xen_halt(void) } static const struct pv_irq_ops xen_irq_ops __initdata = { - .init_IRQ = __xen_init_IRQ, + .init_IRQ = xen_init_IRQ, .save_fl = PV_CALLEE_SAVE(xen_save_fl), .restore_fl = PV_CALLEE_SAVE(xen_restore_fl), diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 7c3705479ea..2c8d710713f 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -517,6 +518,24 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id) } +static void xen_do_irq(unsigned irq, struct pt_regs *regs) +{ + struct pt_regs *old_regs = set_irq_regs(regs); + + if (WARN_ON(irq == -1)) + return; + + exit_idle(); + irq_enter(); + + //printk("cpu %d handling irq %d\n", smp_processor_id(), info->irq); + handle_irq(irq, regs); + + irq_exit(); + + set_irq_regs(old_regs); +} + /* * Search the CPUs pending events bitmasks. For each one found, map * the event number to an irq, and feed it into do_IRQ() for @@ -557,8 +576,7 @@ void xen_evtchn_do_upcall(struct pt_regs *regs) int port = (word_idx * BITS_PER_LONG) + bit_idx; int irq = evtchn_to_irq[port]; - if (irq != -1) - xen_do_IRQ(irq, regs); + xen_do_irq(irq, regs); } } -- GitLab From ced40d0f3e8833bb8d7d8e2cbfac7da0bf7008c4 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Fri, 6 Feb 2009 14:09:44 -0800 Subject: [PATCH 1438/4982] xen: pack all irq-related info together Put all irq info into one struct. Also, use a union to keep event channel type-specific information, rather than overloading the index field. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- drivers/xen/events.c | 184 +++++++++++++++++++++++++++++++------------ 1 file changed, 135 insertions(+), 49 deletions(-) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 2c8d710713f..0541e07d4f6 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -52,18 +52,8 @@ static DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS]) = {[0 ... NR_VIRQS-1] = -1}; /* IRQ <-> IPI mapping */ static DEFINE_PER_CPU(int, ipi_to_irq[XEN_NR_IPIS]) = {[0 ... XEN_NR_IPIS-1] = -1}; -/* Packed IRQ information: binding type, sub-type index, and event channel. */ -struct packed_irq -{ - unsigned short evtchn; - unsigned char index; - unsigned char type; -}; - -static struct packed_irq irq_info[NR_IRQS]; - -/* Binding types. */ -enum { +/* Interrupt types. */ +enum xen_irq_type { IRQT_UNBOUND, IRQT_PIRQ, IRQT_VIRQ, @@ -71,8 +61,34 @@ enum { IRQT_EVTCHN }; -/* Convenient shorthand for packed representation of an unbound IRQ. */ -#define IRQ_UNBOUND mk_irq_info(IRQT_UNBOUND, 0, 0) +/* + * Packed IRQ information: + * type - enum xen_irq_type + * event channel - irq->event channel mapping + * cpu - cpu this event channel is bound to + * index - type-specific information: + * PIRQ - vector, with MSB being "needs EIO" + * VIRQ - virq number + * IPI - IPI vector + * EVTCHN - + */ +struct irq_info +{ + enum xen_irq_type type; /* type */ + unsigned short evtchn; /* event channel */ + unsigned short cpu; /* cpu bound */ + + union { + unsigned short virq; + enum ipi_vector ipi; + struct { + unsigned short gsi; + unsigned short vector; + } pirq; + } u; +}; + +static struct irq_info irq_info[NR_IRQS]; static int evtchn_to_irq[NR_EVENT_CHANNELS] = { [0 ... NR_EVENT_CHANNELS-1] = -1 @@ -85,7 +101,6 @@ static inline unsigned long *cpu_evtchn_mask(int cpu) { return cpu_evtchn_mask_p[cpu].bits; } -static u8 cpu_evtchn[NR_EVENT_CHANNELS]; /* Reference counts for bindings to IRQs. */ static int irq_bindcount[NR_IRQS]; @@ -96,27 +111,107 @@ static int irq_bindcount[NR_IRQS]; static struct irq_chip xen_dynamic_chip; /* Constructor for packed IRQ information. */ -static inline struct packed_irq mk_irq_info(u32 type, u32 index, u32 evtchn) +static struct irq_info mk_unbound_info(void) +{ + return (struct irq_info) { .type = IRQT_UNBOUND }; +} + +static struct irq_info mk_evtchn_info(unsigned short evtchn) +{ + return (struct irq_info) { .type = IRQT_EVTCHN, .evtchn = evtchn }; +} + +static struct irq_info mk_ipi_info(unsigned short evtchn, enum ipi_vector ipi) { - return (struct packed_irq) { evtchn, index, type }; + return (struct irq_info) { .type = IRQT_IPI, .evtchn = evtchn, + .u.ipi = ipi }; +} + +static struct irq_info mk_virq_info(unsigned short evtchn, unsigned short virq) +{ + return (struct irq_info) { .type = IRQT_VIRQ, .evtchn = evtchn, + .u.virq = virq }; +} + +static struct irq_info mk_pirq_info(unsigned short evtchn, + unsigned short gsi, unsigned short vector) +{ + return (struct irq_info) { .type = IRQT_PIRQ, .evtchn = evtchn, + .u.pirq = { .gsi = gsi, .vector = vector } }; } /* * Accessors for packed IRQ information. */ -static inline unsigned int evtchn_from_irq(int irq) +static struct irq_info *info_for_irq(unsigned irq) { - return irq_info[irq].evtchn; + return &irq_info[irq]; } -static inline unsigned int index_from_irq(int irq) +static unsigned int evtchn_from_irq(unsigned irq) { - return irq_info[irq].index; + return info_for_irq(irq)->evtchn; } -static inline unsigned int type_from_irq(int irq) +static enum ipi_vector ipi_from_irq(unsigned irq) { - return irq_info[irq].type; + struct irq_info *info = info_for_irq(irq); + + BUG_ON(info == NULL); + BUG_ON(info->type != IRQT_IPI); + + return info->u.ipi; +} + +static unsigned virq_from_irq(unsigned irq) +{ + struct irq_info *info = info_for_irq(irq); + + BUG_ON(info == NULL); + BUG_ON(info->type != IRQT_VIRQ); + + return info->u.virq; +} + +static unsigned gsi_from_irq(unsigned irq) +{ + struct irq_info *info = info_for_irq(irq); + + BUG_ON(info == NULL); + BUG_ON(info->type != IRQT_PIRQ); + + return info->u.pirq.gsi; +} + +static unsigned vector_from_irq(unsigned irq) +{ + struct irq_info *info = info_for_irq(irq); + + BUG_ON(info == NULL); + BUG_ON(info->type != IRQT_PIRQ); + + return info->u.pirq.vector; +} + +static enum xen_irq_type type_from_irq(unsigned irq) +{ + return info_for_irq(irq)->type; +} + +static unsigned cpu_from_irq(unsigned irq) +{ + return info_for_irq(irq)->cpu; +} + +static unsigned int cpu_from_evtchn(unsigned int evtchn) +{ + int irq = evtchn_to_irq[evtchn]; + unsigned ret = 0; + + if (irq != -1) + ret = cpu_from_irq(irq); + + return ret; } static inline unsigned long active_evtchns(unsigned int cpu, @@ -137,10 +232,10 @@ static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu) cpumask_copy(irq_to_desc(irq)->affinity, cpumask_of(cpu)); #endif - __clear_bit(chn, cpu_evtchn_mask(cpu_evtchn[chn])); + __clear_bit(chn, cpu_evtchn_mask(cpu_from_irq(irq))); __set_bit(chn, cpu_evtchn_mask(cpu)); - cpu_evtchn[chn] = cpu; + irq_info[irq].cpu = cpu; } static void init_evtchn_cpu_bindings(void) @@ -155,15 +250,9 @@ static void init_evtchn_cpu_bindings(void) } #endif - memset(cpu_evtchn, 0, sizeof(cpu_evtchn)); memset(cpu_evtchn_mask(0), ~0, sizeof(cpu_evtchn_mask(0))); } -static inline unsigned int cpu_from_evtchn(unsigned int evtchn) -{ - return cpu_evtchn[evtchn]; -} - static inline void clear_evtchn(int port) { struct shared_info *s = HYPERVISOR_shared_info; @@ -253,6 +342,8 @@ static int find_unbound_irq(void) if (WARN_ON(desc == NULL)) return -1; + dynamic_irq_init(irq); + return irq; } @@ -267,12 +358,11 @@ int bind_evtchn_to_irq(unsigned int evtchn) if (irq == -1) { irq = find_unbound_irq(); - dynamic_irq_init(irq); set_irq_chip_and_handler_name(irq, &xen_dynamic_chip, handle_level_irq, "event"); evtchn_to_irq[evtchn] = irq; - irq_info[irq] = mk_irq_info(IRQT_EVTCHN, 0, evtchn); + irq_info[irq] = mk_evtchn_info(evtchn); } irq_bindcount[irq]++; @@ -296,7 +386,6 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) if (irq < 0) goto out; - dynamic_irq_init(irq); set_irq_chip_and_handler_name(irq, &xen_dynamic_chip, handle_level_irq, "ipi"); @@ -307,7 +396,7 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) evtchn = bind_ipi.port; evtchn_to_irq[evtchn] = irq; - irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn); + irq_info[irq] = mk_ipi_info(evtchn, ipi); per_cpu(ipi_to_irq, cpu)[ipi] = irq; @@ -341,12 +430,11 @@ static int bind_virq_to_irq(unsigned int virq, unsigned int cpu) irq = find_unbound_irq(); - dynamic_irq_init(irq); set_irq_chip_and_handler_name(irq, &xen_dynamic_chip, handle_level_irq, "virq"); evtchn_to_irq[evtchn] = irq; - irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn); + irq_info[irq] = mk_virq_info(evtchn, virq); per_cpu(virq_to_irq, cpu)[virq] = irq; @@ -375,11 +463,11 @@ static void unbind_from_irq(unsigned int irq) switch (type_from_irq(irq)) { case IRQT_VIRQ: per_cpu(virq_to_irq, cpu_from_evtchn(evtchn)) - [index_from_irq(irq)] = -1; + [virq_from_irq(irq)] = -1; break; case IRQT_IPI: per_cpu(ipi_to_irq, cpu_from_evtchn(evtchn)) - [index_from_irq(irq)] = -1; + [ipi_from_irq(irq)] = -1; break; default: break; @@ -389,7 +477,7 @@ static void unbind_from_irq(unsigned int irq) bind_evtchn_to_cpu(evtchn, 0); evtchn_to_irq[evtchn] = -1; - irq_info[irq] = IRQ_UNBOUND; + irq_info[irq] = mk_unbound_info(); dynamic_irq_cleanup(irq); } @@ -507,8 +595,8 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id) for(i = 0; i < NR_EVENT_CHANNELS; i++) { if (sync_test_bit(i, sh->evtchn_pending)) { printk(" %d: event %d -> irq %d\n", - cpu_evtchn[i], i, - evtchn_to_irq[i]); + cpu_from_evtchn(i), i, + evtchn_to_irq[i]); } } @@ -606,7 +694,7 @@ void rebind_evtchn_irq(int evtchn, int irq) BUG_ON(irq_bindcount[irq] == 0); evtchn_to_irq[evtchn] = irq; - irq_info[irq] = mk_irq_info(IRQT_EVTCHN, 0, evtchn); + irq_info[irq] = mk_evtchn_info(evtchn); spin_unlock(&irq_mapping_update_lock); @@ -716,8 +804,7 @@ static void restore_cpu_virqs(unsigned int cpu) if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) continue; - BUG_ON(irq_info[irq].type != IRQT_VIRQ); - BUG_ON(irq_info[irq].index != virq); + BUG_ON(virq_from_irq(irq) != virq); /* Get a new binding from Xen. */ bind_virq.virq = virq; @@ -729,7 +816,7 @@ static void restore_cpu_virqs(unsigned int cpu) /* Record the new mapping. */ evtchn_to_irq[evtchn] = irq; - irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn); + irq_info[irq] = mk_virq_info(evtchn, virq); bind_evtchn_to_cpu(evtchn, cpu); /* Ready for use. */ @@ -746,8 +833,7 @@ static void restore_cpu_ipis(unsigned int cpu) if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1) continue; - BUG_ON(irq_info[irq].type != IRQT_IPI); - BUG_ON(irq_info[irq].index != ipi); + BUG_ON(ipi_from_irq(irq) != ipi); /* Get a new binding from Xen. */ bind_ipi.vcpu = cpu; @@ -758,7 +844,7 @@ static void restore_cpu_ipis(unsigned int cpu) /* Record the new mapping. */ evtchn_to_irq[evtchn] = irq; - irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn); + irq_info[irq] = mk_ipi_info(evtchn, ipi); bind_evtchn_to_cpu(evtchn, cpu); /* Ready for use. */ -- GitLab From d77bbd4db475e2edc78edb7f94a258159c140b54 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Fri, 6 Feb 2009 14:09:45 -0800 Subject: [PATCH 1439/4982] xen: remove irq bindcount There should be no need for us to maintain our own bind count for irqs, since the surrounding irq system should keep track of shared irqs for us. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- drivers/xen/events.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 0541e07d4f6..459121c5325 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -54,7 +54,7 @@ static DEFINE_PER_CPU(int, ipi_to_irq[XEN_NR_IPIS]) = {[0 ... XEN_NR_IPIS-1] = - /* Interrupt types. */ enum xen_irq_type { - IRQT_UNBOUND, + IRQT_UNBOUND = 0, IRQT_PIRQ, IRQT_VIRQ, IRQT_IPI, @@ -102,9 +102,6 @@ static inline unsigned long *cpu_evtchn_mask(int cpu) return cpu_evtchn_mask_p[cpu].bits; } -/* Reference counts for bindings to IRQs. */ -static int irq_bindcount[NR_IRQS]; - /* Xen will never allocate port zero for any purpose. */ #define VALID_EVTCHN(chn) ((chn) != 0) @@ -330,9 +327,8 @@ static int find_unbound_irq(void) int irq; struct irq_desc *desc; - /* Only allocate from dynirq range */ for (irq = 0; irq < nr_irqs; irq++) - if (irq_bindcount[irq] == 0) + if (irq_info[irq].type == IRQT_UNBOUND) break; if (irq == nr_irqs) @@ -365,8 +361,6 @@ int bind_evtchn_to_irq(unsigned int evtchn) irq_info[irq] = mk_evtchn_info(evtchn); } - irq_bindcount[irq]++; - spin_unlock(&irq_mapping_update_lock); return irq; @@ -403,8 +397,6 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) bind_evtchn_to_cpu(evtchn, cpu); } - irq_bindcount[irq]++; - out: spin_unlock(&irq_mapping_update_lock); return irq; @@ -441,8 +433,6 @@ static int bind_virq_to_irq(unsigned int virq, unsigned int cpu) bind_evtchn_to_cpu(evtchn, cpu); } - irq_bindcount[irq]++; - spin_unlock(&irq_mapping_update_lock); return irq; @@ -455,7 +445,7 @@ static void unbind_from_irq(unsigned int irq) spin_lock(&irq_mapping_update_lock); - if ((--irq_bindcount[irq] == 0) && VALID_EVTCHN(evtchn)) { + if (VALID_EVTCHN(evtchn)) { close.port = evtchn; if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0) BUG(); @@ -681,6 +671,8 @@ out: /* Rebind a new event channel to an existing irq. */ void rebind_evtchn_irq(int evtchn, int irq) { + struct irq_info *info = info_for_irq(irq); + /* Make sure the irq is masked, since the new event channel will also be masked. */ disable_irq(irq); @@ -690,8 +682,8 @@ void rebind_evtchn_irq(int evtchn, int irq) /* After resume the irq<->evtchn mappings are all cleared out */ BUG_ON(evtchn_to_irq[evtchn] != -1); /* Expect irq to have been bound before, - so the bindcount should be non-0 */ - BUG_ON(irq_bindcount[irq] == 0); + so there should be a proper type */ + BUG_ON(info->type == IRQT_UNBOUND); evtchn_to_irq[evtchn] = irq; irq_info[irq] = mk_evtchn_info(evtchn); @@ -948,9 +940,5 @@ void __init xen_init_IRQ(void) for (i = 0; i < NR_EVENT_CHANNELS; i++) mask_evtchn(i); - /* Dynamic IRQ space is currently unbound. Zero the refcnts. */ - for (i = 0; i < nr_irqs; i++) - irq_bindcount[i] = 0; - irq_ctx_init(smp_processor_id()); } -- GitLab From 3445a8fd7c6868bd9db0d1bea7d6e89004552122 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Fri, 6 Feb 2009 14:09:46 -0800 Subject: [PATCH 1440/4982] xen: make sure that softirqs get handled at the end of event processing Make sure that irq_enter()/irq_exit() wrap the entire event processing loop, rather than each individual event invokation. This makes sure that softirq processing is deferred until the end of event processing, rather than in the middle with interrupts disabled. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- drivers/xen/events.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 459121c5325..e53fd60fe4b 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -595,25 +595,6 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } - -static void xen_do_irq(unsigned irq, struct pt_regs *regs) -{ - struct pt_regs *old_regs = set_irq_regs(regs); - - if (WARN_ON(irq == -1)) - return; - - exit_idle(); - irq_enter(); - - //printk("cpu %d handling irq %d\n", smp_processor_id(), info->irq); - handle_irq(irq, regs); - - irq_exit(); - - set_irq_regs(old_regs); -} - /* * Search the CPUs pending events bitmasks. For each one found, map * the event number to an irq, and feed it into do_IRQ() for @@ -626,11 +607,15 @@ static void xen_do_irq(unsigned irq, struct pt_regs *regs) void xen_evtchn_do_upcall(struct pt_regs *regs) { int cpu = get_cpu(); + struct pt_regs *old_regs = set_irq_regs(regs); struct shared_info *s = HYPERVISOR_shared_info; struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu); static DEFINE_PER_CPU(unsigned, nesting_count); unsigned count; + exit_idle(); + irq_enter(); + do { unsigned long pending_words; @@ -654,7 +639,8 @@ void xen_evtchn_do_upcall(struct pt_regs *regs) int port = (word_idx * BITS_PER_LONG) + bit_idx; int irq = evtchn_to_irq[port]; - xen_do_irq(irq, regs); + if (irq != -1) + handle_irq(irq, regs); } } @@ -665,6 +651,9 @@ void xen_evtchn_do_upcall(struct pt_regs *regs) } while(count != 1); out: + irq_exit(); + set_irq_regs(old_regs); + put_cpu(); } -- GitLab From 90af9514ac99f51e81682c7bec8f9fb88a17a95c Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 6 Feb 2009 16:55:58 -0800 Subject: [PATCH 1441/4982] xen: explicitly initialise the cpu field of irq_info I was seeing a very odd crash on 64 bit in bind_evtchn_to_cpu because cpu_from_irq(irq) was coming out as -1. I found this was coming direct from the mk_ipi_info call. It's not clear to me that this isn't a compiler bug (implicit initialisation to zero of unsigned shorts in a struct not handled correctly?). On the other hand is it true that all event channels start of bound to CPU 0? If not then -1 might be correct and the various other functions should cope with this. Signed-off-by: Ian Campbell Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- drivers/xen/events.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index e53fd60fe4b..30963af5dba 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -115,26 +115,27 @@ static struct irq_info mk_unbound_info(void) static struct irq_info mk_evtchn_info(unsigned short evtchn) { - return (struct irq_info) { .type = IRQT_EVTCHN, .evtchn = evtchn }; + return (struct irq_info) { .type = IRQT_EVTCHN, .evtchn = evtchn, + .cpu = 0 }; } static struct irq_info mk_ipi_info(unsigned short evtchn, enum ipi_vector ipi) { return (struct irq_info) { .type = IRQT_IPI, .evtchn = evtchn, - .u.ipi = ipi }; + .cpu = 0, .u.ipi = ipi }; } static struct irq_info mk_virq_info(unsigned short evtchn, unsigned short virq) { return (struct irq_info) { .type = IRQT_VIRQ, .evtchn = evtchn, - .u.virq = virq }; + .cpu = 0, .u.virq = virq }; } static struct irq_info mk_pirq_info(unsigned short evtchn, unsigned short gsi, unsigned short vector) { return (struct irq_info) { .type = IRQT_PIRQ, .evtchn = evtchn, - .u.pirq = { .gsi = gsi, .vector = vector } }; + .cpu = 0, .u.pirq = { .gsi = gsi, .vector = vector } }; } /* @@ -375,6 +376,7 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) spin_lock(&irq_mapping_update_lock); irq = per_cpu(ipi_to_irq, cpu)[ipi]; + if (irq == -1) { irq = find_unbound_irq(); if (irq < 0) @@ -391,7 +393,6 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) evtchn_to_irq[evtchn] = irq; irq_info[irq] = mk_ipi_info(evtchn, ipi); - per_cpu(ipi_to_irq, cpu)[ipi] = irq; bind_evtchn_to_cpu(evtchn, cpu); -- GitLab From 1c14fa4937eb73509e07ac12bf8db1fdf4c42a59 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Sat, 7 Feb 2009 15:39:38 -0800 Subject: [PATCH 1442/4982] x86: use early_ioremap in __acpi_map_table __acpi_map_table() effectively reimplements early_ioremap(). Rather than have that duplication, just implement it in terms of early_ioremap(). However, unlike early_ioremap(), __acpi_map_table() just maintains a single mapping which gets replaced each call, and has no corresponding unmap function. Implement this by just removing the previous mapping each time its called. Unfortunately, this will leave a stray mapping at the end. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/include/asm/acpi.h | 3 --- arch/x86/include/asm/fixmap_32.h | 4 ---- arch/x86/include/asm/fixmap_64.h | 4 ---- arch/x86/kernel/acpi/boot.c | 27 +++++++-------------------- 4 files changed, 7 insertions(+), 31 deletions(-) diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index 9830681446a..4518dc50090 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h @@ -102,9 +102,6 @@ static inline void disable_acpi(void) acpi_noirq = 1; } -/* Fixmap pages to reserve for ACPI boot-time tables (see fixmap.h) */ -#define FIX_ACPI_PAGES 4 - extern int acpi_gsi_to_irq(u32 gsi, unsigned int *irq); static inline void acpi_noirq_set(void) { acpi_noirq = 1; } diff --git a/arch/x86/include/asm/fixmap_32.h b/arch/x86/include/asm/fixmap_32.h index c7115c1d721..047d9bab2b3 100644 --- a/arch/x86/include/asm/fixmap_32.h +++ b/arch/x86/include/asm/fixmap_32.h @@ -95,10 +95,6 @@ enum fixed_addresses { (__end_of_permanent_fixed_addresses & 255), FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1, FIX_WP_TEST, -#ifdef CONFIG_ACPI - FIX_ACPI_BEGIN, - FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1, -#endif #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT FIX_OHCI1394_BASE, #endif diff --git a/arch/x86/include/asm/fixmap_64.h b/arch/x86/include/asm/fixmap_64.h index 00a30ab9b1a..298d9ba3fae 100644 --- a/arch/x86/include/asm/fixmap_64.h +++ b/arch/x86/include/asm/fixmap_64.h @@ -50,10 +50,6 @@ enum fixed_addresses { FIX_PARAVIRT_BOOTMAP, #endif __end_of_permanent_fixed_addresses, -#ifdef CONFIG_ACPI - FIX_ACPI_BEGIN, - FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1, -#endif #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT FIX_OHCI1394_BASE, #endif diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index d37593c2f43..c518599e426 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -121,8 +121,8 @@ enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC; */ char *__init __acpi_map_table(unsigned long phys, unsigned long size) { - unsigned long base, offset, mapped_size; - int idx; + static char *prev_map; + static unsigned long prev_size; if (!phys || !size) return NULL; @@ -130,26 +130,13 @@ char *__init __acpi_map_table(unsigned long phys, unsigned long size) if (phys+size <= (max_low_pfn_mapped << PAGE_SHIFT)) return __va(phys); - offset = phys & (PAGE_SIZE - 1); - mapped_size = PAGE_SIZE - offset; - clear_fixmap(FIX_ACPI_END); - set_fixmap(FIX_ACPI_END, phys); - base = fix_to_virt(FIX_ACPI_END); + if (prev_map) + early_iounmap(prev_map, prev_size); - /* - * Most cases can be covered by the below. - */ - idx = FIX_ACPI_END; - while (mapped_size < size) { - if (--idx < FIX_ACPI_BEGIN) - return NULL; /* cannot handle this */ - phys += PAGE_SIZE; - clear_fixmap(idx); - set_fixmap(idx, phys); - mapped_size += PAGE_SIZE; - } + prev_size = size; + prev_map = early_ioremap(phys, size); - return ((unsigned char *)base + offset); + return prev_map; } #ifdef CONFIG_PCI_MMCONFIG -- GitLab From eecb9a697f0b790e5840dae8a8b866bea49a86ee Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Sat, 7 Feb 2009 15:39:38 -0800 Subject: [PATCH 1443/4982] x86: always explicitly map acpi memory Always map acpi tables, rather than assuming we can use the normal linear mapping to access the acpi tables. This is necessary in a virtual environment where the linear mappings are to pseudo-physical memory, but the acpi tables exist at a real physical address. It doesn't hurt to map in the normal non-virtual case, so just do it unconditionally. Signed-off-by: Jeremy Fitzhardinge Acked-by: Len Brown Signed-off-by: Ingo Molnar --- arch/x86/kernel/acpi/boot.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index c518599e426..5424a18f2e4 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -127,9 +127,6 @@ char *__init __acpi_map_table(unsigned long phys, unsigned long size) if (!phys || !size) return NULL; - if (phys+size <= (max_low_pfn_mapped << PAGE_SHIFT)) - return __va(phys); - if (prev_map) early_iounmap(prev_map, prev_size); -- GitLab From 05876f88ed9a66b26af613e222795ae790616252 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Sat, 7 Feb 2009 15:39:40 -0800 Subject: [PATCH 1444/4982] acpi: remove final __acpi_map_table mapping before setting acpi_gbl_permanent_mmap On x86, __acpi_map_table uses early_ioremap() to create the mapping, replacing the previous mapping with a new one. Once enough of the kernel is up an running it switches to using normal ioremap(). At that point, we need to clean up the final mapping to avoid a warning from the early_ioremap subsystem. This can be removed after all the instances in the ACPI code are fixed that rely on early-ioremap's implicit overmapping of previously mapped tables. Signed-off-by: Jeremy Fitzhardinge Acked-by: Len Brown Signed-off-by: Ingo Molnar --- arch/x86/kernel/acpi/boot.c | 8 +++++--- drivers/acpi/bus.c | 6 ++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 5424a18f2e4..7217834f6b1 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -124,12 +124,14 @@ char *__init __acpi_map_table(unsigned long phys, unsigned long size) static char *prev_map; static unsigned long prev_size; + if (prev_map) { + early_iounmap(prev_map, prev_size); + prev_map = NULL; + } + if (!phys || !size) return NULL; - if (prev_map) - early_iounmap(prev_map, prev_size); - prev_size = size; prev_map = early_ioremap(phys, size); diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 765fd1c56cd..fb1be7b5dbc 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -694,6 +694,12 @@ void __init acpi_early_init(void) if (!acpi_strict) acpi_gbl_enable_interpreter_slack = TRUE; + /* + * Doing a zero-sized mapping will clear out the previous + * __acpi_map_table() mapping, if any. + */ + __acpi_map_table(0, 0); + acpi_gbl_permanent_mmap = 1; status = acpi_reallocate_root_table(); -- GitLab From 7d97277b754d3ee098a5ec69b6aaafb00c94e2f2 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 7 Feb 2009 15:39:41 -0800 Subject: [PATCH 1445/4982] acpi/x86: introduce __apci_map_table, v4 to prevent wrongly overwriting fixmap that still want to use. ACPI used to rely on low mappings being all linearly mapped and grew a habit: it never really unmapped certain kinds of tables after use. This can cause problems - for example the hypothetical case when some spurious access still references it. v2: remove prev_map and prev_size in __apci_map_table v3: let acpi_os_unmap_memory() call early_iounmap too, so remove extral calling to early_acpi_os_unmap_memory v4: fix typo in one acpi_get_table_with_size calling Signed-off-by: Yinghai Lu Acked-by: Len Brown Signed-off-by: Ingo Molnar --- arch/ia64/kernel/acpi.c | 4 ++++ arch/x86/kernel/acpi/boot.c | 17 +++++++---------- drivers/acpi/acpica/tbxface.c | 17 ++++++++++++++--- drivers/acpi/bus.c | 6 ------ drivers/acpi/osl.c | 11 +++++++++-- drivers/acpi/tables.c | 20 ++++++++++++++------ include/acpi/acpiosxf.h | 1 + include/acpi/acpixf.h | 4 ++++ include/linux/acpi.h | 1 + 9 files changed, 54 insertions(+), 27 deletions(-) diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index d541671caf4..2363ed17319 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -199,6 +199,10 @@ char *__init __acpi_map_table(unsigned long phys_addr, unsigned long size) return __va(phys_addr); } +char *__init __acpi_unmap_table(unsigned long virt_addr, unsigned long size) +{ +} + /* -------------------------------------------------------------------------- Boot-time Table Parsing -------------------------------------------------------------------------- */ diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 7217834f6b1..4c2aaea4293 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -121,21 +121,18 @@ enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC; */ char *__init __acpi_map_table(unsigned long phys, unsigned long size) { - static char *prev_map; - static unsigned long prev_size; - - if (prev_map) { - early_iounmap(prev_map, prev_size); - prev_map = NULL; - } if (!phys || !size) return NULL; - prev_size = size; - prev_map = early_ioremap(phys, size); + return early_ioremap(phys, size); +} +void __init __acpi_unmap_table(char *map, unsigned long size) +{ + if (!map || !size) + return; - return prev_map; + early_iounmap(map, size); } #ifdef CONFIG_PCI_MMCONFIG diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index c3e841f3cde..ab0aff3c7d6 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -365,7 +365,7 @@ ACPI_EXPORT_SYMBOL(acpi_unload_table_id) /******************************************************************************* * - * FUNCTION: acpi_get_table + * FUNCTION: acpi_get_table_with_size * * PARAMETERS: Signature - ACPI signature of needed table * Instance - Which instance (for SSDTs) @@ -377,8 +377,9 @@ ACPI_EXPORT_SYMBOL(acpi_unload_table_id) * *****************************************************************************/ acpi_status -acpi_get_table(char *signature, - u32 instance, struct acpi_table_header **out_table) +acpi_get_table_with_size(char *signature, + u32 instance, struct acpi_table_header **out_table, + acpi_size *tbl_size) { u32 i; u32 j; @@ -408,6 +409,7 @@ acpi_get_table(char *signature, acpi_tb_verify_table(&acpi_gbl_root_table_list.tables[i]); if (ACPI_SUCCESS(status)) { *out_table = acpi_gbl_root_table_list.tables[i].pointer; + *tbl_size = acpi_gbl_root_table_list.tables[i].length; } if (!acpi_gbl_permanent_mmap) { @@ -420,6 +422,15 @@ acpi_get_table(char *signature, return (AE_NOT_FOUND); } +acpi_status +acpi_get_table(char *signature, + u32 instance, struct acpi_table_header **out_table) +{ + acpi_size tbl_size; + + return acpi_get_table_with_size(signature, + instance, out_table, &tbl_size); +} ACPI_EXPORT_SYMBOL(acpi_get_table) /******************************************************************************* diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index fb1be7b5dbc..765fd1c56cd 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -694,12 +694,6 @@ void __init acpi_early_init(void) if (!acpi_strict) acpi_gbl_enable_interpreter_slack = TRUE; - /* - * Doing a zero-sized mapping will clear out the previous - * __acpi_map_table() mapping, if any. - */ - __acpi_map_table(0, 0); - acpi_gbl_permanent_mmap = 1; status = acpi_reallocate_root_table(); diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index b3193ec0a2e..d1dd5160daa 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -274,12 +274,19 @@ EXPORT_SYMBOL_GPL(acpi_os_map_memory); void acpi_os_unmap_memory(void __iomem * virt, acpi_size size) { - if (acpi_gbl_permanent_mmap) { + if (acpi_gbl_permanent_mmap) iounmap(virt); - } + else + __acpi_unmap_table(virt, size); } EXPORT_SYMBOL_GPL(acpi_os_unmap_memory); +void early_acpi_os_unmap_memory(void __iomem * virt, acpi_size size) +{ + if (!acpi_gbl_permanent_mmap) + __acpi_unmap_table(virt, size); +} + #ifdef ACPI_FUTURE_USAGE acpi_status acpi_os_get_physical_address(void *virt, acpi_physical_address * phys) diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index a8852952fac..fec1ae36d43 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -181,14 +181,15 @@ acpi_table_parse_entries(char *id, struct acpi_subtable_header *entry; unsigned int count = 0; unsigned long table_end; + acpi_size tbl_size; if (!handler) return -EINVAL; if (strncmp(id, ACPI_SIG_MADT, 4) == 0) - acpi_get_table(id, acpi_apic_instance, &table_header); + acpi_get_table_with_size(id, acpi_apic_instance, &table_header, &tbl_size); else - acpi_get_table(id, 0, &table_header); + acpi_get_table_with_size(id, 0, &table_header, &tbl_size); if (!table_header) { printk(KERN_WARNING PREFIX "%4.4s not present\n", id); @@ -206,8 +207,10 @@ acpi_table_parse_entries(char *id, table_end) { if (entry->type == entry_id && (!max_entries || count++ < max_entries)) - if (handler(entry, table_end)) + if (handler(entry, table_end)) { + early_acpi_os_unmap_memory((char *)table_header, tbl_size); return -EINVAL; + } entry = (struct acpi_subtable_header *) ((unsigned long)entry + entry->length); @@ -217,6 +220,7 @@ acpi_table_parse_entries(char *id, "%i found\n", id, entry_id, count - max_entries, count); } + early_acpi_os_unmap_memory((char *)table_header, tbl_size); return count; } @@ -241,17 +245,19 @@ acpi_table_parse_madt(enum acpi_madt_type id, int __init acpi_table_parse(char *id, acpi_table_handler handler) { struct acpi_table_header *table = NULL; + acpi_size tbl_size; if (!handler) return -EINVAL; if (strncmp(id, ACPI_SIG_MADT, 4) == 0) - acpi_get_table(id, acpi_apic_instance, &table); + acpi_get_table_with_size(id, acpi_apic_instance, &table, &tbl_size); else - acpi_get_table(id, 0, &table); + acpi_get_table_with_size(id, 0, &table, &tbl_size); if (table) { handler(table); + early_acpi_os_unmap_memory(table, tbl_size); return 0; } else return 1; @@ -265,8 +271,9 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler) static void __init check_multiple_madt(void) { struct acpi_table_header *table = NULL; + acpi_size tbl_size; - acpi_get_table(ACPI_SIG_MADT, 2, &table); + acpi_get_table_with_size(ACPI_SIG_MADT, 2, &table, &tbl_size); if (table) { printk(KERN_WARNING PREFIX "BIOS bug: multiple APIC/MADT found," @@ -275,6 +282,7 @@ static void __init check_multiple_madt(void) "If \"acpi_apic_instance=%d\" works better, " "notify linux-acpi@vger.kernel.org\n", acpi_apic_instance ? 0 : 2); + early_acpi_os_unmap_memory(table, tbl_size); } else acpi_apic_instance = 0; diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index a62720a7edc..ab0b85cf21f 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -144,6 +144,7 @@ void __iomem *acpi_os_map_memory(acpi_physical_address where, acpi_size length); void acpi_os_unmap_memory(void __iomem * logical_address, acpi_size size); +void early_acpi_os_unmap_memory(void __iomem * virt, acpi_size size); #ifdef ACPI_FUTURE_USAGE acpi_status diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index c8e8cf45830..cc40102fe2f 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -130,6 +130,10 @@ acpi_get_table_header(acpi_string signature, struct acpi_table_header *out_table_header); acpi_status +acpi_get_table_with_size(acpi_string signature, + u32 instance, struct acpi_table_header **out_table, + acpi_size *tbl_size); +acpi_status acpi_get_table(acpi_string signature, u32 instance, struct acpi_table_header **out_table); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 6fce2fc2d12..d59f0fa4d77 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -79,6 +79,7 @@ typedef int (*acpi_table_handler) (struct acpi_table_header *table); typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end); char * __acpi_map_table (unsigned long phys_addr, unsigned long size); +void __init __acpi_unmap_table(char *map, unsigned long size); int early_acpi_boot_init(void); int acpi_boot_init (void); int acpi_boot_table_init (void); -- GitLab From b825e6cc7b1401862531df497a4a4daff8102ed5 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 7 Feb 2009 15:39:41 -0800 Subject: [PATCH 1446/4982] x86, es7000: fix ACPI table mappings Signed-off-by: Ingo Molnar --- arch/x86/kernel/es7000_32.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/es7000_32.c b/arch/x86/kernel/es7000_32.c index 53699c931ad..71d7be624d4 100644 --- a/arch/x86/kernel/es7000_32.c +++ b/arch/x86/kernel/es7000_32.c @@ -292,24 +292,31 @@ int __init find_unisys_acpi_oem_table(unsigned long *oem_addr) { struct acpi_table_header *header = NULL; int i = 0; + acpi_size tbl_size; - while (ACPI_SUCCESS(acpi_get_table("OEM1", i++, &header))) { + while (ACPI_SUCCESS(acpi_get_table_with_size("OEM1", i++, &header, &tbl_size))) { if (!memcmp((char *) &header->oem_id, "UNISYS", 6)) { struct oem_table *t = (struct oem_table *)header; oem_addrX = t->OEMTableAddr; oem_size = t->OEMTableSize; + early_acpi_os_unmap_memory(header, tbl_size); *oem_addr = (unsigned long)__acpi_map_table(oem_addrX, oem_size); return 0; } + early_acpi_os_unmap_memory(header, tbl_size); } return -1; } void __init unmap_unisys_acpi_oem_table(unsigned long oem_addr) { + if (!oem_addr) + return; + + __acpi_unmap_table((char *)oem_addr, oem_size); } #endif -- GitLab From 8bd4bb7a35e8ebb015a531218614c48e10a3c4ee Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 30 Jan 2009 17:27:45 +0100 Subject: [PATCH 1447/4982] ALSA: Add subdevice_mask field to quirk entries Introduced a new field, subdevice_mask, which specifies the bitmask to match with the given subdevice ID. Signed-off-by: Takashi Iwai --- include/sound/core.h | 16 ++++++++++++++-- sound/core/misc.c | 10 ++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/include/sound/core.h b/include/sound/core.h index f632484bc74..f67952a61a2 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -446,21 +446,33 @@ static inline int __snd_bug_on(int cond) struct snd_pci_quirk { unsigned short subvendor; /* PCI subvendor ID */ unsigned short subdevice; /* PCI subdevice ID */ + unsigned short subdevice_mask; /* bitmask to match */ int value; /* value */ #ifdef CONFIG_SND_DEBUG_VERBOSE const char *name; /* name of the device (optional) */ #endif }; -#define _SND_PCI_QUIRK_ID(vend,dev) \ - .subvendor = (vend), .subdevice = (dev) +#define _SND_PCI_QUIRK_ID_MASK(vend, mask, dev) \ + .subvendor = (vend), .subdevice = (dev), .subdevice_mask = (mask) +#define _SND_PCI_QUIRK_ID(vend, dev) \ + _SND_PCI_QUIRK_ID_MASK(vend, 0xffff, dev) #define SND_PCI_QUIRK_ID(vend,dev) {_SND_PCI_QUIRK_ID(vend, dev)} #ifdef CONFIG_SND_DEBUG_VERBOSE #define SND_PCI_QUIRK(vend,dev,xname,val) \ {_SND_PCI_QUIRK_ID(vend, dev), .value = (val), .name = (xname)} +#define SND_PCI_QUIRK_VENDOR(vend, xname, val) \ + {_SND_PCI_QUIRK_ID_MASK(vend, 0, 0), .value = (val), .name = (xname)} +#define SND_PCI_QUIRK_MASK(vend, mask, dev, xname, val) \ + {_SND_PCI_QUIRK_ID_MASK(vend, mask, dev), \ + .value = (val), .name = (xname)} #else #define SND_PCI_QUIRK(vend,dev,xname,val) \ {_SND_PCI_QUIRK_ID(vend, dev), .value = (val)} +#define SND_PCI_QUIRK_MASK(vend, mask, dev, xname, val) \ + {_SND_PCI_QUIRK_ID_MASK(vend, mask, dev), .value = (val)} +#define SND_PCI_QUIRK_VENDOR(vend, xname, val) \ + {_SND_PCI_QUIRK_ID_MASK(vend, 0, 0), .value = (val)} #endif const struct snd_pci_quirk * diff --git a/sound/core/misc.c b/sound/core/misc.c index 38524f615d9..a9710e0c97a 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c @@ -95,12 +95,14 @@ snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list) { const struct snd_pci_quirk *q; - for (q = list; q->subvendor; q++) - if (q->subvendor == pci->subsystem_vendor && - (!q->subdevice || q->subdevice == pci->subsystem_device)) + for (q = list; q->subvendor; q++) { + if (q->subvendor != pci->subsystem_vendor) + continue; + if (!q->subdevice || + (pci->subsystem_device & q->subdevice_mask) == q->subdevice) return q; + } return NULL; } - EXPORT_SYMBOL(snd_pci_quirk_lookup); #endif -- GitLab From dea0a5095b5e21306a81c496567043798fac7815 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 9 Feb 2009 17:14:52 +0100 Subject: [PATCH 1448/4982] ALSA: hda - Clean up quirk lists Clean up quirk lists with bit masks. Also, sorted in numerical order for alc662_cfg_tbl[]. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_analog.c | 10 ++-- sound/pci/hda/patch_conexant.c | 20 +++---- sound/pci/hda/patch_realtek.c | 97 ++++++++++++++++------------------ sound/pci/hda/patch_sigmatel.c | 61 ++++----------------- 4 files changed, 65 insertions(+), 123 deletions(-) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index cc02f2df251..6106dfe8ec0 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -1015,10 +1015,8 @@ static struct snd_pci_quirk ad1986a_cfg_tbl[] = { SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD), SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK), SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP), - SND_PCI_QUIRK(0x144d, 0xc023, "Samsung X60", AD1986A_SAMSUNG), - SND_PCI_QUIRK(0x144d, 0xc024, "Samsung R65", AD1986A_SAMSUNG), - SND_PCI_QUIRK(0x144d, 0xc026, "Samsung X11", AD1986A_SAMSUNG), SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA), + SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG), SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK), SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP), SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK), @@ -1706,10 +1704,10 @@ static struct snd_pci_quirk ad1981_cfg_tbl[] = { SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD), SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD), /* All HP models */ - SND_PCI_QUIRK(0x103c, 0, "HP nx", AD1981_HP), + SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP), SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA), /* Lenovo Thinkpad T60/X60/Z6xx */ - SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1981_THINKPAD), + SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD), /* HP nx6320 (reversed SSID, H/W bug) */ SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP), {} @@ -3481,7 +3479,7 @@ static const char *ad1984_models[AD1984_MODELS] = { static struct snd_pci_quirk ad1984_cfg_tbl[] = { /* Lenovo Thinkpad T61/X61 */ - SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1984_THINKPAD), + SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD), SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP), {} }; diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 0177ef8f4c9..fdf876be712 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -1002,15 +1002,9 @@ static const char *cxt5045_models[CXT5045_MODELS] = { }; static struct snd_pci_quirk cxt5045_cfg_tbl[] = { - SND_PCI_QUIRK(0x103c, 0x30a5, "HP", CXT5045_LAPTOP_HPSENSE), - SND_PCI_QUIRK(0x103c, 0x30b2, "HP DV Series", CXT5045_LAPTOP_HPSENSE), - SND_PCI_QUIRK(0x103c, 0x30b5, "HP DV2120", CXT5045_LAPTOP_HPSENSE), - SND_PCI_QUIRK(0x103c, 0x30b7, "HP DV6000Z", CXT5045_LAPTOP_HPSENSE), - SND_PCI_QUIRK(0x103c, 0x30bb, "HP DV8000", CXT5045_LAPTOP_HPSENSE), - SND_PCI_QUIRK(0x103c, 0x30cd, "HP DV Series", CXT5045_LAPTOP_HPSENSE), - SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV9533EG", CXT5045_LAPTOP_HPSENSE), SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530), - SND_PCI_QUIRK(0x103c, 0x30d9, "HP Spartan", CXT5045_LAPTOP_HPSENSE), + SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series", + CXT5045_LAPTOP_HPSENSE), SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P105", CXT5045_LAPTOP_MICSENSE), SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ), SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE), @@ -1020,8 +1014,8 @@ static struct snd_pci_quirk cxt5045_cfg_tbl[] = { SND_PCI_QUIRK(0x1509, 0x1e40, "FIC", CXT5045_LAPTOP_HPMICSENSE), SND_PCI_QUIRK(0x1509, 0x2f05, "FIC", CXT5045_LAPTOP_HPMICSENSE), SND_PCI_QUIRK(0x1509, 0x2f06, "FIC", CXT5045_LAPTOP_HPMICSENSE), - SND_PCI_QUIRK(0x1631, 0xc106, "Packard Bell", CXT5045_LAPTOP_HPMICSENSE), - SND_PCI_QUIRK(0x1631, 0xc107, "Packard Bell", CXT5045_LAPTOP_HPMICSENSE), + SND_PCI_QUIRK_MASK(0x1631, 0xff00, 0xc100, "Packard Bell", + CXT5045_LAPTOP_HPMICSENSE), SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP_HPSENSE), {} }; @@ -1571,11 +1565,9 @@ static const char *cxt5047_models[CXT5047_MODELS] = { }; static struct snd_pci_quirk cxt5047_cfg_tbl[] = { - SND_PCI_QUIRK(0x103c, 0x30a0, "HP DV1000", CXT5047_LAPTOP), SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP), - SND_PCI_QUIRK(0x103c, 0x30b2, "HP DV2000T/DV3000T", CXT5047_LAPTOP), - SND_PCI_QUIRK(0x103c, 0x30b5, "HP DV2000Z", CXT5047_LAPTOP), - SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6700", CXT5047_LAPTOP), + SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series", + CXT5047_LAPTOP), SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P100", CXT5047_LAPTOP_EAPD), {} }; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f594a096029..7ae8fad0189 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3598,7 +3598,7 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = { SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG), SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST), SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST), - SND_PCI_QUIRK(0x1043, 0, "ASUS", ALC880_ASUS), /* default ASUS */ + SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_ASUS), /* default ASUS */ SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST), SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST), SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST), @@ -3641,7 +3641,8 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = { SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG), SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG), SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG), - SND_PCI_QUIRK(0x8086, 0, "Intel mobo", ALC880_3ST), /* default Intel */ + /* default Intel */ + SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_3ST), SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG), SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG), {} @@ -8521,7 +8522,8 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { ALC888_ACER_ASPIRE_4930G), SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G", ALC888_ACER_ASPIRE_4930G), - SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER), /* default Acer */ + /* default Acer */ + SND_PCI_QUIRK_VENDOR(0x1025, "Acer laptop", ALC883_ACER), SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL), SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG), SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP), @@ -8566,7 +8568,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG), SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720), SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720), - SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD), + SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC883_LAPTOP_EAPD), SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch), SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION), SND_PCI_QUIRK(0x1734, 0x1107, "FSC AMILO Xi2550", @@ -10707,14 +10709,10 @@ static const char *alc262_models[ALC262_MODEL_LAST] = { static struct snd_pci_quirk alc262_cfg_tbl[] = { SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO), SND_PCI_QUIRK(0x1033, 0x8895, "NEC Versa S9100", ALC262_NEC), - SND_PCI_QUIRK(0x103c, 0x12fe, "HP xw9400", ALC262_HP_BPC), - SND_PCI_QUIRK(0x103c, 0x12ff, "HP xw4550", ALC262_HP_BPC), - SND_PCI_QUIRK(0x103c, 0x1306, "HP xw8600", ALC262_HP_BPC), - SND_PCI_QUIRK(0x103c, 0x1307, "HP xw6600", ALC262_HP_BPC), - SND_PCI_QUIRK(0x103c, 0x1308, "HP xw4600", ALC262_HP_BPC), - SND_PCI_QUIRK(0x103c, 0x1309, "HP xw4*00", ALC262_HP_BPC), - SND_PCI_QUIRK(0x103c, 0x130a, "HP xw6*00", ALC262_HP_BPC), - SND_PCI_QUIRK(0x103c, 0x130b, "HP xw8*00", ALC262_HP_BPC), + SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1200, "HP xw series", + ALC262_HP_BPC), + SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1300, "HP xw series", + ALC262_HP_BPC), SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL), SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF), SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL), @@ -10742,8 +10740,8 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = { SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU), SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU), SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_TYAN), - SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA), - SND_PCI_QUIRK(0x144d, 0xc039, "Samsung Q1U EL", ALC262_ULTRA), + SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc032, "Samsung Q1", + ALC262_ULTRA), SND_PCI_QUIRK(0x144d, 0xc510, "Samsung Q45", ALC262_HIPPO), SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 y410", ALC262_LENOVO_3000), SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8), @@ -14534,9 +14532,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = { SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO), SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS), SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG), - SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO), - SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO), - SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 N200", ALC861VD_LENOVO), + SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", ALC861VD_LENOVO), SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG), {} }; @@ -16150,56 +16146,55 @@ static const char *alc662_models[ALC662_MODEL_LAST] = { }; static struct snd_pci_quirk alc662_cfg_tbl[] = { - SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA), - SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS G50V", ALC663_ASUS_G50V), - SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG), - SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701), - SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20), - SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M50Vr", ALC663_ASUS_MODE1), + SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_ECS), SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC663_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC663_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC663_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS NB", ALC663_ASUS_MODE1), + SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3), + SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3), SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1), + SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2), SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC663_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC663_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC663_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_ASUS_MODE2), SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_ASUS_MODE2), - SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_ASUS_MODE2), - SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_ASUS_MODE2), + SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_ASUS_MODE2), + SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_ASUS_MODE2), + SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6), + SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6), + SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_ASUS_MODE2), SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_ASUS_MODE2), - SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2), - SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_ASUS_MODE2), + SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC663_ASUS_MODE5), + SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC663_ASUS_MODE6), + SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_ASUS_MODE2), SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_ASUS_MODE2), - SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_ASUS_MODE2), - SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_ASUS_MODE2), - SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_ASUS_MODE2), - SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_ASUS_MODE2), + SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_ASUS_MODE2), + SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA), + /*SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M50Vr", ALC663_ASUS_MODE1),*/ SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC663_ASUS_MODE3), - SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3), - SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC663_ASUS_MODE3), SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC663_ASUS_MODE3), - SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3), + SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1), + SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_ASUS_MODE2), + SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_ASUS_MODE2), + SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC663_ASUS_MODE1), + SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC663_ASUS_MODE3), + SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC663_ASUS_MODE1), + SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS G50V", ALC663_ASUS_G50V), + /*SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS NB", ALC663_ASUS_MODE1),*/ + SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC663_ASUS_MODE1), + SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_ASUS_MODE2), + SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC663_ASUS_MODE4), - SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC663_ASUS_MODE5), - SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC663_ASUS_MODE6), - SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6), - SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6), + SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG), + SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701), + SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20), + SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS), SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K", ALC662_3ST_6ch_DIG), - SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), - SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_ECS), - SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS), SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L", ALC662_3ST_6ch_DIG), SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG), + SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), SND_PCI_QUIRK(0x1849, 0x3662, "ASROCK K10N78FullHD-hSLI R3.0", ALC662_3ST_6ch_DIG), - SND_PCI_QUIRK(0x1854, 0x2000, "ASUS H13-2000", ALC663_ASUS_H13), - SND_PCI_QUIRK(0x1854, 0x2001, "ASUS H13-2001", ALC663_ASUS_H13), - SND_PCI_QUIRK(0x1854, 0x2002, "ASUS H13-2002", ALC663_ASUS_H13), + SND_PCI_QUIRK_MASK(0x1854, 0xf000, 0x2000, "ASUS H13-200x", + ALC663_ASUS_H13), {} }; diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 2f4e090b055..12b30884843 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -2082,33 +2082,7 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = { SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d7, "Dell XPS M1210", STAC_922X_DELL_M82), /* ECS/PC Chips boards */ - SND_PCI_QUIRK(0x1019, 0x2144, - "ECS/PC chips", STAC_ECS_202), - SND_PCI_QUIRK(0x1019, 0x2608, - "ECS/PC chips", STAC_ECS_202), - SND_PCI_QUIRK(0x1019, 0x2633, - "ECS/PC chips P17G/1333", STAC_ECS_202), - SND_PCI_QUIRK(0x1019, 0x2811, - "ECS/PC chips", STAC_ECS_202), - SND_PCI_QUIRK(0x1019, 0x2812, - "ECS/PC chips", STAC_ECS_202), - SND_PCI_QUIRK(0x1019, 0x2813, - "ECS/PC chips", STAC_ECS_202), - SND_PCI_QUIRK(0x1019, 0x2814, - "ECS/PC chips", STAC_ECS_202), - SND_PCI_QUIRK(0x1019, 0x2815, - "ECS/PC chips", STAC_ECS_202), - SND_PCI_QUIRK(0x1019, 0x2816, - "ECS/PC chips", STAC_ECS_202), - SND_PCI_QUIRK(0x1019, 0x2817, - "ECS/PC chips", STAC_ECS_202), - SND_PCI_QUIRK(0x1019, 0x2818, - "ECS/PC chips", STAC_ECS_202), - SND_PCI_QUIRK(0x1019, 0x2819, - "ECS/PC chips", STAC_ECS_202), - SND_PCI_QUIRK(0x1019, 0x2820, - "ECS/PC chips", STAC_ECS_202), - SND_PCI_QUIRK(0x1019, 0x2950, + SND_PCI_QUIRK_MASK(0x1019, 0xf000, 0x2000, "ECS/PC chips", STAC_ECS_202), {} /* terminator */ }; @@ -2169,22 +2143,10 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = { SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x3d01, "Intel D946", STAC_D965_3ST), SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xa301, "Intel D946", STAC_D965_3ST), /* 965 based 3 stack systems */ - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2116, "Intel D965", STAC_D965_3ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2115, "Intel D965", STAC_D965_3ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2114, "Intel D965", STAC_D965_3ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2113, "Intel D965", STAC_D965_3ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2112, "Intel D965", STAC_D965_3ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2111, "Intel D965", STAC_D965_3ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2110, "Intel D965", STAC_D965_3ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2009, "Intel D965", STAC_D965_3ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2008, "Intel D965", STAC_D965_3ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2007, "Intel D965", STAC_D965_3ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2006, "Intel D965", STAC_D965_3ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2005, "Intel D965", STAC_D965_3ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2004, "Intel D965", STAC_D965_3ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2003, "Intel D965", STAC_D965_3ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2002, "Intel D965", STAC_D965_3ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2001, "Intel D965", STAC_D965_3ST), + SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2100, + "Intel D965", STAC_D965_3ST), + SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2000, + "Intel D965", STAC_D965_3ST), /* Dell 3 stack systems */ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f7, "Dell XPS M1730", STAC_DELL_3ST), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01dd, "Dell Dimension E520", STAC_DELL_3ST), @@ -2200,15 +2162,10 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = { SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ff, "Dell ", STAC_DELL_BIOS), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0209, "Dell XPS 1330", STAC_DELL_BIOS), /* 965 based 5 stack systems */ - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2301, "Intel D965", STAC_D965_5ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2302, "Intel D965", STAC_D965_5ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2303, "Intel D965", STAC_D965_5ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2304, "Intel D965", STAC_D965_5ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2305, "Intel D965", STAC_D965_5ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2501, "Intel D965", STAC_D965_5ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2502, "Intel D965", STAC_D965_5ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2503, "Intel D965", STAC_D965_5ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2504, "Intel D965", STAC_D965_5ST), + SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2300, + "Intel D965", STAC_D965_5ST), + SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2500, + "Intel D965", STAC_D965_5ST), {} /* terminator */ }; -- GitLab From a85165c66c5640c37b67a94aa4e00fe45273bca1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 9 Feb 2009 17:15:50 +0100 Subject: [PATCH 1449/4982] ALSA: via82xx - Clean up quirk list Use SND_PCI_QUIRK_VENDOR() macro. Signed-off-by: Takashi Iwai --- sound/pci/via82xx.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index fc62d6380f8..a027896a220 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -2363,14 +2363,14 @@ static struct snd_pci_quirk dxs_whitelist[] __devinitdata = { SND_PCI_QUIRK(0x1019, 0x0996, "ESC Mobo", VIA_DXS_48K), SND_PCI_QUIRK(0x1019, 0x0a81, "ECS K7VTA3 v8.0", VIA_DXS_NO_VRA), SND_PCI_QUIRK(0x1019, 0x0a85, "ECS L7VMM2", VIA_DXS_NO_VRA), - SND_PCI_QUIRK(0x1019, 0, "ESC K8", VIA_DXS_SRC), + SND_PCI_QUIRK_VENDOR(0x1019, "ESC K8", VIA_DXS_SRC), SND_PCI_QUIRK(0x1019, 0xaa01, "ESC K8T890-A", VIA_DXS_SRC), SND_PCI_QUIRK(0x1025, 0x0033, "Acer Inspire 1353LM", VIA_DXS_NO_VRA), SND_PCI_QUIRK(0x1025, 0x0046, "Acer Aspire 1524 WLMi", VIA_DXS_SRC), - SND_PCI_QUIRK(0x1043, 0, "ASUS A7/A8", VIA_DXS_NO_VRA), - SND_PCI_QUIRK(0x1071, 0, "Diverse Notebook", VIA_DXS_NO_VRA), + SND_PCI_QUIRK_VENDOR(0x1043, "ASUS A7/A8", VIA_DXS_NO_VRA), + SND_PCI_QUIRK_VENDOR(0x1071, "Diverse Notebook", VIA_DXS_NO_VRA), SND_PCI_QUIRK(0x10cf, 0x118e, "FSC Laptop", VIA_DXS_ENABLE), - SND_PCI_QUIRK(0x1106, 0, "ASRock", VIA_DXS_SRC), + SND_PCI_QUIRK_VENDOR(0x1106, "ASRock", VIA_DXS_SRC), SND_PCI_QUIRK(0x1297, 0xa231, "Shuttle AK31v2", VIA_DXS_SRC), SND_PCI_QUIRK(0x1297, 0xa232, "Shuttle", VIA_DXS_SRC), SND_PCI_QUIRK(0x1297, 0xc160, "Shuttle Sk41G", VIA_DXS_SRC), @@ -2378,7 +2378,7 @@ static struct snd_pci_quirk dxs_whitelist[] __devinitdata = { SND_PCI_QUIRK(0x1462, 0x3800, "MSI KT266", VIA_DXS_ENABLE), SND_PCI_QUIRK(0x1462, 0x7120, "MSI KT4V", VIA_DXS_ENABLE), SND_PCI_QUIRK(0x1462, 0x7142, "MSI K8MM-V", VIA_DXS_ENABLE), - SND_PCI_QUIRK(0x1462, 0, "MSI Mobo", VIA_DXS_SRC), + SND_PCI_QUIRK_VENDOR(0x1462, "MSI Mobo", VIA_DXS_SRC), SND_PCI_QUIRK(0x147b, 0x1401, "ABIT KD7(-RAID)", VIA_DXS_ENABLE), SND_PCI_QUIRK(0x147b, 0x1411, "ABIT VA-20", VIA_DXS_ENABLE), SND_PCI_QUIRK(0x147b, 0x1413, "ABIT KV8 Pro", VIA_DXS_ENABLE), @@ -2392,11 +2392,11 @@ static struct snd_pci_quirk dxs_whitelist[] __devinitdata = { SND_PCI_QUIRK(0x161f, 0x2032, "m680x machines", VIA_DXS_48K), SND_PCI_QUIRK(0x1631, 0xe004, "PB EasyNote 3174", VIA_DXS_ENABLE), SND_PCI_QUIRK(0x1695, 0x3005, "EPoX EP-8K9A", VIA_DXS_ENABLE), - SND_PCI_QUIRK(0x1695, 0, "EPoX mobo", VIA_DXS_SRC), - SND_PCI_QUIRK(0x16f3, 0, "Jetway K8", VIA_DXS_SRC), - SND_PCI_QUIRK(0x1734, 0, "FSC Laptop", VIA_DXS_SRC), + SND_PCI_QUIRK_VENDOR(0x1695, "EPoX mobo", VIA_DXS_SRC), + SND_PCI_QUIRK_VENDOR(0x16f3, "Jetway K8", VIA_DXS_SRC), + SND_PCI_QUIRK_VENDOR(0x1734, "FSC Laptop", VIA_DXS_SRC), SND_PCI_QUIRK(0x1849, 0x3059, "ASRock K7VM2", VIA_DXS_NO_VRA), - SND_PCI_QUIRK(0x1849, 0, "ASRock mobo", VIA_DXS_SRC), + SND_PCI_QUIRK_VENDOR(0x1849, "ASRock mobo", VIA_DXS_SRC), SND_PCI_QUIRK(0x1919, 0x200a, "Soltek SL-K8", VIA_DXS_NO_VRA), SND_PCI_QUIRK(0x4005, 0x4710, "MSI K7T266", VIA_DXS_SRC), { } /* terminator */ -- GitLab From b93f74f604c53b546fced33d11aee722560de249 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 9 Feb 2009 14:27:06 +0200 Subject: [PATCH 1450/4982] ASoC: TLV320AIC3X: Fix volume ranges This is a minor fix but helps to define dB ranges for volume controls. Only DAC digital volume has full register value range from 0 to 127 but ADC PGA gain and output stage volume controls don't. For ADC PGA, maximum value is 119 and then it saturates to the same gain value of 59.5 dB. For output stages, value 117 corresponds to -78.3 dB and is muted for values 118 and above. Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic3x.c | 38 +++++++++++++++++----------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index ac73e692a99..cdb6dec14e1 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -255,51 +255,51 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { SOC_DOUBLE_R("PCM Playback Volume", LDAC_VOL, RDAC_VOL, 0, 0x7f, 1), SOC_DOUBLE_R("Line DAC Playback Volume", DACL1_2_LLOPM_VOL, - DACR1_2_RLOPM_VOL, 0, 0x7f, 1), + DACR1_2_RLOPM_VOL, 0, 118, 1), SOC_SINGLE("LineL Playback Switch", LLOPM_CTRL, 3, 0x01, 0), SOC_SINGLE("LineR Playback Switch", RLOPM_CTRL, 3, 0x01, 0), SOC_DOUBLE_R("LineL DAC Playback Volume", DACL1_2_LLOPM_VOL, - DACR1_2_LLOPM_VOL, 0, 0x7f, 1), + DACR1_2_LLOPM_VOL, 0, 118, 1), SOC_SINGLE("LineL Left PGA Bypass Playback Volume", PGAL_2_LLOPM_VOL, - 0, 0x7f, 1), + 0, 118, 1), SOC_SINGLE("LineR Right PGA Bypass Playback Volume", PGAR_2_RLOPM_VOL, - 0, 0x7f, 1), + 0, 118, 1), SOC_DOUBLE_R("LineL Line2 Bypass Playback Volume", LINE2L_2_LLOPM_VOL, - LINE2R_2_LLOPM_VOL, 0, 0x7f, 1), + LINE2R_2_LLOPM_VOL, 0, 118, 1), SOC_DOUBLE_R("LineR Line2 Bypass Playback Volume", LINE2L_2_RLOPM_VOL, - LINE2R_2_RLOPM_VOL, 0, 0x7f, 1), + LINE2R_2_RLOPM_VOL, 0, 118, 1), SOC_DOUBLE_R("Mono DAC Playback Volume", DACL1_2_MONOLOPM_VOL, - DACR1_2_MONOLOPM_VOL, 0, 0x7f, 1), + DACR1_2_MONOLOPM_VOL, 0, 118, 1), SOC_SINGLE("Mono DAC Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0), SOC_DOUBLE_R("Mono PGA Bypass Playback Volume", PGAL_2_MONOLOPM_VOL, - PGAR_2_MONOLOPM_VOL, 0, 0x7f, 1), + PGAR_2_MONOLOPM_VOL, 0, 118, 1), SOC_DOUBLE_R("Mono Line2 Bypass Playback Volume", LINE2L_2_MONOLOPM_VOL, - LINE2R_2_MONOLOPM_VOL, 0, 0x7f, 1), + LINE2R_2_MONOLOPM_VOL, 0, 118, 1), SOC_DOUBLE_R("HP DAC Playback Volume", DACL1_2_HPLOUT_VOL, - DACR1_2_HPROUT_VOL, 0, 0x7f, 1), + DACR1_2_HPROUT_VOL, 0, 118, 1), SOC_DOUBLE_R("HP DAC Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3, 0x01, 0), SOC_DOUBLE_R("HP Right PGA Bypass Playback Volume", PGAR_2_HPLOUT_VOL, - PGAR_2_HPROUT_VOL, 0, 0x7f, 1), + PGAR_2_HPROUT_VOL, 0, 118, 1), SOC_SINGLE("HPL PGA Bypass Playback Volume", PGAL_2_HPLOUT_VOL, - 0, 0x7f, 1), + 0, 118, 1), SOC_SINGLE("HPR PGA Bypass Playback Volume", PGAL_2_HPROUT_VOL, - 0, 0x7f, 1), + 0, 118, 1), SOC_DOUBLE_R("HP Line2 Bypass Playback Volume", LINE2L_2_HPLOUT_VOL, - LINE2R_2_HPROUT_VOL, 0, 0x7f, 1), + LINE2R_2_HPROUT_VOL, 0, 118, 1), SOC_DOUBLE_R("HPCOM DAC Playback Volume", DACL1_2_HPLCOM_VOL, - DACR1_2_HPRCOM_VOL, 0, 0x7f, 1), + DACR1_2_HPRCOM_VOL, 0, 118, 1), SOC_DOUBLE_R("HPCOM DAC Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3, 0x01, 0), SOC_SINGLE("HPLCOM PGA Bypass Playback Volume", PGAL_2_HPLCOM_VOL, - 0, 0x7f, 1), + 0, 118, 1), SOC_SINGLE("HPRCOM PGA Bypass Playback Volume", PGAL_2_HPRCOM_VOL, - 0, 0x7f, 1), + 0, 118, 1), SOC_DOUBLE_R("HPCOM Line2 Bypass Playback Volume", LINE2L_2_HPLCOM_VOL, - LINE2R_2_HPRCOM_VOL, 0, 0x7f, 1), + LINE2R_2_HPRCOM_VOL, 0, 118, 1), /* * Note: enable Automatic input Gain Controller with care. It can @@ -308,7 +308,7 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { SOC_DOUBLE_R("AGC Switch", LAGC_CTRL_A, RAGC_CTRL_A, 7, 0x01, 0), /* Input */ - SOC_DOUBLE_R("PGA Capture Volume", LADC_VOL, RADC_VOL, 0, 0x7f, 0), + SOC_DOUBLE_R("PGA Capture Volume", LADC_VOL, RADC_VOL, 0, 119, 0), SOC_DOUBLE_R("PGA Capture Switch", LADC_VOL, RADC_VOL, 7, 0x01, 1), SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]), -- GitLab From 7565fc38cc8c3a2742d63e957199d70a82d2faf1 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 9 Feb 2009 14:27:07 +0200 Subject: [PATCH 1451/4982] ASoC: TLV320AIC3X: Add TLV information for volume controls TLV320AIC3X volume controls are logarithmic. Export their dB ranges. Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic3x.c | 114 +++++++++++++++++++++------------ 1 file changed, 73 insertions(+), 41 deletions(-) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index cdb6dec14e1..d638e3f0728 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -45,6 +45,7 @@ #include #include #include +#include #include "tlv320aic3x.h" @@ -250,56 +251,86 @@ static const struct soc_enum aic3x_enum[] = { SOC_ENUM_DOUBLE(AIC3X_CODEC_DFILT_CTRL, 6, 4, 4, aic3x_adc_hpf), }; +/* + * DAC digital volumes. From -63.5 to 0 dB in 0.5 dB steps + */ +static DECLARE_TLV_DB_SCALE(dac_tlv, -6350, 50, 0); +/* ADC PGA gain volumes. From 0 to 59.5 dB in 0.5 dB steps */ +static DECLARE_TLV_DB_SCALE(adc_tlv, 0, 50, 0); +/* + * Output stage volumes. From -78.3 to 0 dB. Muted below -78.3 dB. + * Step size is approximately 0.5 dB over most of the scale but increasing + * near the very low levels. + * Define dB scale so that it is mostly correct for range about -55 to 0 dB + * but having increasing dB difference below that (and where it doesn't count + * so much). This setting shows -50 dB (actual is -50.3 dB) for register + * value 100 and -58.5 dB (actual is -78.3 dB) for register value 117. + */ +static DECLARE_TLV_DB_SCALE(output_stage_tlv, -5900, 50, 1); + static const struct snd_kcontrol_new aic3x_snd_controls[] = { /* Output */ - SOC_DOUBLE_R("PCM Playback Volume", LDAC_VOL, RDAC_VOL, 0, 0x7f, 1), + SOC_DOUBLE_R_TLV("PCM Playback Volume", + LDAC_VOL, RDAC_VOL, 0, 0x7f, 1, dac_tlv), - SOC_DOUBLE_R("Line DAC Playback Volume", DACL1_2_LLOPM_VOL, - DACR1_2_RLOPM_VOL, 0, 118, 1), + SOC_DOUBLE_R_TLV("Line DAC Playback Volume", + DACL1_2_LLOPM_VOL, DACR1_2_RLOPM_VOL, + 0, 118, 1, output_stage_tlv), SOC_SINGLE("LineL Playback Switch", LLOPM_CTRL, 3, 0x01, 0), SOC_SINGLE("LineR Playback Switch", RLOPM_CTRL, 3, 0x01, 0), - SOC_DOUBLE_R("LineL DAC Playback Volume", DACL1_2_LLOPM_VOL, - DACR1_2_LLOPM_VOL, 0, 118, 1), - SOC_SINGLE("LineL Left PGA Bypass Playback Volume", PGAL_2_LLOPM_VOL, - 0, 118, 1), - SOC_SINGLE("LineR Right PGA Bypass Playback Volume", PGAR_2_RLOPM_VOL, - 0, 118, 1), - SOC_DOUBLE_R("LineL Line2 Bypass Playback Volume", LINE2L_2_LLOPM_VOL, - LINE2R_2_LLOPM_VOL, 0, 118, 1), - SOC_DOUBLE_R("LineR Line2 Bypass Playback Volume", LINE2L_2_RLOPM_VOL, - LINE2R_2_RLOPM_VOL, 0, 118, 1), - - SOC_DOUBLE_R("Mono DAC Playback Volume", DACL1_2_MONOLOPM_VOL, - DACR1_2_MONOLOPM_VOL, 0, 118, 1), + SOC_DOUBLE_R_TLV("LineL DAC Playback Volume", + DACL1_2_LLOPM_VOL, DACR1_2_LLOPM_VOL, + 0, 118, 1, output_stage_tlv), + SOC_SINGLE_TLV("LineL Left PGA Bypass Playback Volume", + PGAL_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv), + SOC_SINGLE_TLV("LineR Right PGA Bypass Playback Volume", + PGAR_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv), + SOC_DOUBLE_R_TLV("LineL Line2 Bypass Playback Volume", + LINE2L_2_LLOPM_VOL, LINE2R_2_LLOPM_VOL, + 0, 118, 1, output_stage_tlv), + SOC_DOUBLE_R_TLV("LineR Line2 Bypass Playback Volume", + LINE2L_2_RLOPM_VOL, LINE2R_2_RLOPM_VOL, + 0, 118, 1, output_stage_tlv), + + SOC_DOUBLE_R_TLV("Mono DAC Playback Volume", + DACL1_2_MONOLOPM_VOL, DACR1_2_MONOLOPM_VOL, + 0, 118, 1, output_stage_tlv), SOC_SINGLE("Mono DAC Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0), - SOC_DOUBLE_R("Mono PGA Bypass Playback Volume", PGAL_2_MONOLOPM_VOL, - PGAR_2_MONOLOPM_VOL, 0, 118, 1), - SOC_DOUBLE_R("Mono Line2 Bypass Playback Volume", LINE2L_2_MONOLOPM_VOL, - LINE2R_2_MONOLOPM_VOL, 0, 118, 1), - - SOC_DOUBLE_R("HP DAC Playback Volume", DACL1_2_HPLOUT_VOL, - DACR1_2_HPROUT_VOL, 0, 118, 1), + SOC_DOUBLE_R_TLV("Mono PGA Bypass Playback Volume", + PGAL_2_MONOLOPM_VOL, PGAR_2_MONOLOPM_VOL, + 0, 118, 1, output_stage_tlv), + SOC_DOUBLE_R_TLV("Mono Line2 Bypass Playback Volume", + LINE2L_2_MONOLOPM_VOL, LINE2R_2_MONOLOPM_VOL, + 0, 118, 1, output_stage_tlv), + + SOC_DOUBLE_R_TLV("HP DAC Playback Volume", + DACL1_2_HPLOUT_VOL, DACR1_2_HPROUT_VOL, + 0, 118, 1, output_stage_tlv), SOC_DOUBLE_R("HP DAC Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3, 0x01, 0), - SOC_DOUBLE_R("HP Right PGA Bypass Playback Volume", PGAR_2_HPLOUT_VOL, - PGAR_2_HPROUT_VOL, 0, 118, 1), - SOC_SINGLE("HPL PGA Bypass Playback Volume", PGAL_2_HPLOUT_VOL, - 0, 118, 1), - SOC_SINGLE("HPR PGA Bypass Playback Volume", PGAL_2_HPROUT_VOL, - 0, 118, 1), - SOC_DOUBLE_R("HP Line2 Bypass Playback Volume", LINE2L_2_HPLOUT_VOL, - LINE2R_2_HPROUT_VOL, 0, 118, 1), - - SOC_DOUBLE_R("HPCOM DAC Playback Volume", DACL1_2_HPLCOM_VOL, - DACR1_2_HPRCOM_VOL, 0, 118, 1), + SOC_DOUBLE_R_TLV("HP Right PGA Bypass Playback Volume", + PGAR_2_HPLOUT_VOL, PGAR_2_HPROUT_VOL, + 0, 118, 1, output_stage_tlv), + SOC_SINGLE_TLV("HPL PGA Bypass Playback Volume", + PGAL_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv), + SOC_SINGLE_TLV("HPR PGA Bypass Playback Volume", + PGAL_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv), + SOC_DOUBLE_R_TLV("HP Line2 Bypass Playback Volume", + LINE2L_2_HPLOUT_VOL, LINE2R_2_HPROUT_VOL, + 0, 118, 1, output_stage_tlv), + + SOC_DOUBLE_R_TLV("HPCOM DAC Playback Volume", + DACL1_2_HPLCOM_VOL, DACR1_2_HPRCOM_VOL, + 0, 118, 1, output_stage_tlv), SOC_DOUBLE_R("HPCOM DAC Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3, 0x01, 0), - SOC_SINGLE("HPLCOM PGA Bypass Playback Volume", PGAL_2_HPLCOM_VOL, - 0, 118, 1), - SOC_SINGLE("HPRCOM PGA Bypass Playback Volume", PGAL_2_HPRCOM_VOL, - 0, 118, 1), - SOC_DOUBLE_R("HPCOM Line2 Bypass Playback Volume", LINE2L_2_HPLCOM_VOL, - LINE2R_2_HPRCOM_VOL, 0, 118, 1), + SOC_SINGLE_TLV("HPLCOM PGA Bypass Playback Volume", + PGAL_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv), + SOC_SINGLE_TLV("HPRCOM PGA Bypass Playback Volume", + PGAL_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), + SOC_DOUBLE_R_TLV("HPCOM Line2 Bypass Playback Volume", + LINE2L_2_HPLCOM_VOL, LINE2R_2_HPRCOM_VOL, + 0, 118, 1, output_stage_tlv), /* * Note: enable Automatic input Gain Controller with care. It can @@ -308,7 +339,8 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { SOC_DOUBLE_R("AGC Switch", LAGC_CTRL_A, RAGC_CTRL_A, 7, 0x01, 0), /* Input */ - SOC_DOUBLE_R("PGA Capture Volume", LADC_VOL, RADC_VOL, 0, 119, 0), + SOC_DOUBLE_R_TLV("PGA Capture Volume", LADC_VOL, RADC_VOL, + 0, 119, 0, adc_tlv), SOC_DOUBLE_R("PGA Capture Switch", LADC_VOL, RADC_VOL, 7, 0x01, 1), SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]), -- GitLab From d14c7c1d6aef1175625ea72938b07cee072723dc Mon Sep 17 00:00:00 2001 From: Andrey Borzenkov Date: Sun, 25 Jan 2009 23:08:43 +0300 Subject: [PATCH 1452/4982] orinoco: checkpatch cleanup Fix errors and obvious warnings reported by checkpatch in all files except orinoco.c. Orinoco.c is part of different patch series of Dave. Signed-off-by: Andrey Borzenkov Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/airport.c | 35 +++--- drivers/net/wireless/orinoco/hermes.c | 102 ++++++++++-------- drivers/net/wireless/orinoco/hermes.h | 35 +++--- drivers/net/wireless/orinoco/orinoco.h | 17 +-- drivers/net/wireless/orinoco/orinoco_cs.c | 31 +++--- drivers/net/wireless/orinoco/orinoco_nortel.c | 7 +- drivers/net/wireless/orinoco/orinoco_pci.c | 5 +- drivers/net/wireless/orinoco/orinoco_pci.h | 10 +- drivers/net/wireless/orinoco/orinoco_plx.c | 3 +- drivers/net/wireless/orinoco/orinoco_tmd.c | 2 +- drivers/net/wireless/orinoco/spectrum_cs.c | 15 ++- 11 files changed, 143 insertions(+), 119 deletions(-) diff --git a/drivers/net/wireless/orinoco/airport.c b/drivers/net/wireless/orinoco/airport.c index 28f1cae4843..5582dca9f7f 100644 --- a/drivers/net/wireless/orinoco/airport.c +++ b/drivers/net/wireless/orinoco/airport.c @@ -4,9 +4,9 @@ * card. * * Copyright notice & release notes in file orinoco.c - * + * * Note specific to airport stub: - * + * * 0.05 : first version of the new split driver * 0.06 : fix possible hang on powerup, add sleep support */ @@ -60,7 +60,8 @@ airport_suspend(struct macio_dev *mdev, pm_message_t state) orinoco_unlock(priv, &flags); disable_irq(dev->irq); - pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 0); + pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, + macio_get_of_node(mdev), 0, 0); return 0; } @@ -75,7 +76,8 @@ airport_resume(struct macio_dev *mdev) printk(KERN_DEBUG "%s: Airport waking up\n", dev->name); - pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1); + pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, + macio_get_of_node(mdev), 0, 1); msleep(200); enable_irq(dev->irq); @@ -93,7 +95,7 @@ airport_resume(struct macio_dev *mdev) priv->hw_unavailable--; - if (priv->open && (! priv->hw_unavailable)) { + if (priv->open && (!priv->hw_unavailable)) { err = __orinoco_up(dev); if (err) printk(KERN_ERR "%s: Error %d restarting card on PBOOK_WAKE\n", @@ -127,7 +129,8 @@ airport_detach(struct macio_dev *mdev) macio_release_resource(mdev, 0); - pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 0); + pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, + macio_get_of_node(mdev), 0, 0); ssleep(1); macio_set_drvdata(mdev, NULL); @@ -153,9 +156,11 @@ static int airport_hard_reset(struct orinoco_private *priv) * off. */ disable_irq(dev->irq); - pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(card->mdev), 0, 0); + pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, + macio_get_of_node(card->mdev), 0, 0); ssleep(1); - pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(card->mdev), 0, 1); + pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, + macio_get_of_node(card->mdev), 0, 1); ssleep(1); enable_irq(dev->irq); @@ -182,7 +187,7 @@ airport_attach(struct macio_dev *mdev, const struct of_device_id *match) /* Allocate space for private device-specific data */ dev = alloc_orinocodev(sizeof(*card), &mdev->ofdev.dev, airport_hard_reset, NULL); - if (! dev) { + if (!dev) { printk(KERN_ERR PFX "Cannot allocate network device\n"); return -ENODEV; } @@ -214,9 +219,10 @@ airport_attach(struct macio_dev *mdev, const struct of_device_id *match) } hermes_struct_init(hw, card->vaddr, HERMES_16BIT_REGSPACING); - + /* Power up card */ - pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1); + pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, + macio_get_of_node(mdev), 0, 1); ssleep(1); /* Reset it before we get the interrupt */ @@ -248,7 +254,7 @@ MODULE_AUTHOR("Benjamin Herrenschmidt "); MODULE_DESCRIPTION("Driver for the Apple Airport wireless card."); MODULE_LICENSE("Dual MPL/GPL"); -static struct of_device_id airport_match[] = +static struct of_device_id airport_match[] = { { .name = "radio", @@ -256,10 +262,9 @@ static struct of_device_id airport_match[] = {}, }; -MODULE_DEVICE_TABLE (of, airport_match); +MODULE_DEVICE_TABLE(of, airport_match); -static struct macio_driver airport_driver = -{ +static struct macio_driver airport_driver = { .name = DRIVER_NAME, .match_table = airport_match, .probe = airport_attach, diff --git a/drivers/net/wireless/orinoco/hermes.c b/drivers/net/wireless/orinoco/hermes.c index bfa375369df..f48358fed9f 100644 --- a/drivers/net/wireless/orinoco/hermes.c +++ b/drivers/net/wireless/orinoco/hermes.c @@ -15,7 +15,7 @@ * * Copyright (C) 2000, David Gibson, Linuxcare Australia. * (C) Copyright David Gibson, IBM Corp. 2001-2003. - * + * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License @@ -45,7 +45,8 @@ #include "hermes.h" -MODULE_DESCRIPTION("Low-level driver helper for Lucent Hermes chipset and Prism II HFA384x wireless MAC controller"); +MODULE_DESCRIPTION("Low-level driver helper for Lucent Hermes chipset" + " and Prism II HFA384x wireless MAC controller"); MODULE_AUTHOR("Pavel Roskin " " & David Gibson "); MODULE_LICENSE("Dual MPL/GPL"); @@ -61,13 +62,13 @@ MODULE_LICENSE("Dual MPL/GPL"); */ #define DMSG(stuff...) do {printk(KERN_DEBUG "hermes @ %p: " , hw->iobase); \ - printk(stuff);} while (0) + printk(stuff); } while (0) #undef HERMES_DEBUG #ifdef HERMES_DEBUG #include -#define DEBUG(lvl, stuff...) if ( (lvl) <= HERMES_DEBUG) DMSG(stuff) +#define DEBUG(lvl, stuff...) if ((lvl) <= HERMES_DEBUG) DMSG(stuff) #else /* ! HERMES_DEBUG */ @@ -95,20 +96,19 @@ static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0, /* First wait for the command register to unbusy */ reg = hermes_read_regn(hw, CMD); - while ( (reg & HERMES_CMD_BUSY) && k ) { + while ((reg & HERMES_CMD_BUSY) && k) { k--; udelay(1); reg = hermes_read_regn(hw, CMD); } - if (reg & HERMES_CMD_BUSY) { + if (reg & HERMES_CMD_BUSY) return -EBUSY; - } hermes_write_regn(hw, PARAM2, param2); hermes_write_regn(hw, PARAM1, param1); hermes_write_regn(hw, PARAM0, param0); hermes_write_regn(hw, CMD, cmd); - + return 0; } @@ -191,23 +191,23 @@ int hermes_init(hermes_t *hw) hermes_write_regn(hw, EVACK, 0xffff); /* Normally it's a "can't happen" for the command register to - be busy when we go to issue a command because we are - serializing all commands. However we want to have some - chance of resetting the card even if it gets into a stupid - state, so we actually wait to see if the command register - will unbusy itself here. */ + be busy when we go to issue a command because we are + serializing all commands. However we want to have some + chance of resetting the card even if it gets into a stupid + state, so we actually wait to see if the command register + will unbusy itself here. */ k = CMD_BUSY_TIMEOUT; reg = hermes_read_regn(hw, CMD); while (k && (reg & HERMES_CMD_BUSY)) { - if (reg == 0xffff) /* Special case - the card has probably been removed, - so don't wait for the timeout */ + if (reg == 0xffff) /* Special case - the card has probably been + removed, so don't wait for the timeout */ return -ENODEV; k--; udelay(1); reg = hermes_read_regn(hw, CMD); } - + /* No need to explicitly handle the timeout - if we've timed out hermes_issue_cmd() will probably return -EBUSY below */ @@ -228,7 +228,10 @@ EXPORT_SYMBOL(hermes_init); /* Issue a command to the chip, and (busy!) wait for it to * complete. * - * Returns: < 0 on internal error, 0 on success, > 0 on error returned by the firmware + * Returns: + * < 0 on internal error + * 0 on success + * > 0 on error returned by the firmware * * Callable from any context, but locking is your problem. */ int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, @@ -241,13 +244,13 @@ int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, err = hermes_issue_cmd(hw, cmd, parm0, 0, 0); if (err) { - if (! hermes_present(hw)) { + if (!hermes_present(hw)) { if (net_ratelimit()) printk(KERN_WARNING "hermes @ %p: " "Card removed while issuing command " "0x%04x.\n", hw->iobase, cmd); err = -ENODEV; - } else + } else if (net_ratelimit()) printk(KERN_ERR "hermes @ %p: " "Error %d issuing command 0x%04x.\n", @@ -257,21 +260,21 @@ int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, reg = hermes_read_regn(hw, EVSTAT); k = CMD_COMPL_TIMEOUT; - while ( (! (reg & HERMES_EV_CMD)) && k) { + while ((!(reg & HERMES_EV_CMD)) && k) { k--; udelay(10); reg = hermes_read_regn(hw, EVSTAT); } - if (! hermes_present(hw)) { + if (!hermes_present(hw)) { printk(KERN_WARNING "hermes @ %p: Card removed " "while waiting for command 0x%04x completion.\n", hw->iobase, cmd); err = -ENODEV; goto out; } - - if (! (reg & HERMES_EV_CMD)) { + + if (!(reg & HERMES_EV_CMD)) { printk(KERN_ERR "hermes @ %p: Timeout waiting for " "command 0x%04x completion.\n", hw->iobase, cmd); err = -ETIMEDOUT; @@ -301,31 +304,30 @@ int hermes_allocate(hermes_t *hw, u16 size, u16 *fid) int err = 0; int k; u16 reg; - - if ( (size < HERMES_ALLOC_LEN_MIN) || (size > HERMES_ALLOC_LEN_MAX) ) + + if ((size < HERMES_ALLOC_LEN_MIN) || (size > HERMES_ALLOC_LEN_MAX)) return -EINVAL; err = hermes_docmd_wait(hw, HERMES_CMD_ALLOC, size, NULL); - if (err) { + if (err) return err; - } reg = hermes_read_regn(hw, EVSTAT); k = ALLOC_COMPL_TIMEOUT; - while ( (! (reg & HERMES_EV_ALLOC)) && k) { + while ((!(reg & HERMES_EV_ALLOC)) && k) { k--; udelay(10); reg = hermes_read_regn(hw, EVSTAT); } - - if (! hermes_present(hw)) { + + if (!hermes_present(hw)) { printk(KERN_WARNING "hermes @ %p: " "Card removed waiting for frame allocation.\n", hw->iobase); return -ENODEV; } - - if (! (reg & HERMES_EV_ALLOC)) { + + if (!(reg & HERMES_EV_ALLOC)) { printk(KERN_ERR "hermes @ %p: " "Timeout waiting for frame allocation\n", hw->iobase); @@ -334,14 +336,17 @@ int hermes_allocate(hermes_t *hw, u16 size, u16 *fid) *fid = hermes_read_regn(hw, ALLOCFID); hermes_write_regn(hw, EVACK, HERMES_EV_ALLOC); - + return 0; } EXPORT_SYMBOL(hermes_allocate); /* Set up a BAP to read a particular chunk of data from card's internal buffer. * - * Returns: < 0 on internal failure (errno), 0 on success, >0 on error + * Returns: + * < 0 on internal failure (errno) + * 0 on success + * > 0 on error * from firmware * * Callable from any context */ @@ -353,7 +358,7 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset) u16 reg; /* Paranoia.. */ - if ( (offset > HERMES_BAP_OFFSET_MAX) || (offset % 2) ) + if ((offset > HERMES_BAP_OFFSET_MAX) || (offset % 2)) return -EINVAL; k = HERMES_BAP_BUSY_TIMEOUT; @@ -374,7 +379,7 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset) /* Wait for the BAP to be ready */ k = HERMES_BAP_BUSY_TIMEOUT; reg = hermes_read_reg(hw, oreg); - while ( (reg & (HERMES_OFFSET_BUSY | HERMES_OFFSET_ERR)) && k) { + while ((reg & (HERMES_OFFSET_BUSY | HERMES_OFFSET_ERR)) && k) { k--; udelay(1); reg = hermes_read_reg(hw, oreg); @@ -386,9 +391,8 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset) (reg & HERMES_OFFSET_BUSY) ? "timeout" : "error", reg, id, offset); - if (reg & HERMES_OFFSET_BUSY) { + if (reg & HERMES_OFFSET_BUSY) return -ETIMEDOUT; - } return -EIO; /* error or wrong offset */ } @@ -400,7 +404,10 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset) * BAP. Synchronization/serialization is the caller's problem. len * must be even. * - * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware + * Returns: + * < 0 on internal failure (errno) + * 0 on success + * > 0 on error from firmware */ int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len, u16 id, u16 offset) @@ -408,7 +415,7 @@ int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len, int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; int err = 0; - if ( (len < 0) || (len % 2) ) + if ((len < 0) || (len % 2)) return -EINVAL; err = hermes_bap_seek(hw, bap, id, offset); @@ -426,7 +433,10 @@ EXPORT_SYMBOL(hermes_bap_pread); /* Write a block of data to the chip's buffer, via the * BAP. Synchronization/serialization is the caller's problem. * - * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware + * Returns: + * < 0 on internal failure (errno) + * 0 on success + * > 0 on error from firmware */ int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len, u16 id, u16 offset) @@ -440,11 +450,11 @@ int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len, err = hermes_bap_seek(hw, bap, id, offset); if (err) goto out; - + /* Actually do the transfer */ hermes_write_bytes(hw, dreg, buf, len); - out: + out: return err; } EXPORT_SYMBOL(hermes_bap_pwrite); @@ -465,7 +475,7 @@ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize, u16 rlength, rtype; unsigned nwords; - if ( (bufsize < 0) || (bufsize % 2) ) + if ((bufsize < 0) || (bufsize % 2)) return -EINVAL; err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS, rid, NULL); @@ -478,7 +488,7 @@ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize, rlength = hermes_read_reg(hw, dreg); - if (! rlength) + if (!rlength) return -ENODATA; rtype = hermes_read_reg(hw, dreg); @@ -503,7 +513,7 @@ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize, } EXPORT_SYMBOL(hermes_read_ltv); -int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, +int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, u16 length, const void *value) { int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; diff --git a/drivers/net/wireless/orinoco/hermes.h b/drivers/net/wireless/orinoco/hermes.h index 8b13c8fef3d..c78c442a02c 100644 --- a/drivers/net/wireless/orinoco/hermes.h +++ b/drivers/net/wireless/orinoco/hermes.h @@ -15,7 +15,8 @@ * Copyright (C) 2000, David Gibson, Linuxcare Australia. * (C) Copyright David Gibson, IBM Corp. 2001-2003. * - * Portions taken from hfa384x.h, Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + * Portions taken from hfa384x.h. + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. * * This file distributed under the GPL, version 2. */ @@ -31,7 +32,7 @@ */ #include -#include +#include /* * Limits and constants @@ -203,7 +204,7 @@ struct hermes_tx_descriptor { __le32 sw_support; u8 retry_count; u8 tx_rate; - __le16 tx_control; + __le16 tx_control; } __attribute__ ((packed)); #define HERMES_TXSTAT_RETRYERR (0x0001) @@ -298,7 +299,7 @@ struct symbol_scan_apinfo { /* bits: 0-ess, 1-ibss, 4-privacy [wep] */ __le16 essid_len; /* ESSID length */ u8 essid[32]; /* ESSID of the network */ - __le16 rates[5]; /* Bit rate supported */ + __le16 rates[5]; /* Bit rate supported */ __le16 basic_rates; /* Basic rates bitmask */ u8 unknown2[6]; /* Always FF:FF:FF:FF:00:00 */ u8 unknown3[8]; /* Always 0, appeared in f/w 3.91-68 */ @@ -344,14 +345,14 @@ struct agere_ext_scan_info { u8 data[316]; } __attribute__ ((packed)); -#define HERMES_LINKSTATUS_NOT_CONNECTED (0x0000) +#define HERMES_LINKSTATUS_NOT_CONNECTED (0x0000) #define HERMES_LINKSTATUS_CONNECTED (0x0001) #define HERMES_LINKSTATUS_DISCONNECTED (0x0002) #define HERMES_LINKSTATUS_AP_CHANGE (0x0003) #define HERMES_LINKSTATUS_AP_OUT_OF_RANGE (0x0004) #define HERMES_LINKSTATUS_AP_IN_RANGE (0x0005) #define HERMES_LINKSTATUS_ASSOC_FAILED (0x0006) - + struct hermes_linkstatus { __le16 linkstatus; /* Link status */ } __attribute__ ((packed)); @@ -384,11 +385,12 @@ typedef struct hermes { /* Register access convenience macros */ #define hermes_read_reg(hw, off) \ - (ioread16((hw)->iobase + ( (off) << (hw)->reg_spacing ))) + (ioread16((hw)->iobase + ((off) << (hw)->reg_spacing))) #define hermes_write_reg(hw, off, val) \ (iowrite16((val), (hw)->iobase + ((off) << (hw)->reg_spacing))) #define hermes_read_regn(hw, name) hermes_read_reg((hw), HERMES_##name) -#define hermes_write_regn(hw, name, val) hermes_write_reg((hw), HERMES_##name, (val)) +#define hermes_write_regn(hw, name, val) \ + hermes_write_reg((hw), HERMES_##name, (val)) /* Function prototypes */ void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing); @@ -430,7 +432,7 @@ static inline int hermes_enable_port(hermes_t *hw, int port) static inline int hermes_disable_port(hermes_t *hw, int port) { - return hermes_docmd_wait(hw, HERMES_CMD_DISABLE | (port << 8), + return hermes_docmd_wait(hw, HERMES_CMD_DISABLE | (port << 8), 0, NULL); } @@ -441,11 +443,12 @@ static inline int hermes_inquire(hermes_t *hw, u16 rid) return hermes_docmd_wait(hw, HERMES_CMD_INQUIRE, rid, NULL); } -#define HERMES_BYTES_TO_RECLEN(n) ( (((n)+1)/2) + 1 ) -#define HERMES_RECLEN_TO_BYTES(n) ( ((n)-1) * 2 ) +#define HERMES_BYTES_TO_RECLEN(n) ((((n)+1)/2) + 1) +#define HERMES_RECLEN_TO_BYTES(n) (((n)-1) * 2) /* Note that for the next two, the count is in 16-bit words, not bytes */ -static inline void hermes_read_words(struct hermes *hw, int off, void *buf, unsigned count) +static inline void hermes_read_words(struct hermes *hw, int off, + void *buf, unsigned count) { off = off << hw->reg_spacing; ioread16_rep(hw->iobase + off, buf, count); @@ -460,7 +463,8 @@ static inline void hermes_write_bytes(struct hermes *hw, int off, iowrite8(buf[count - 1], hw->iobase + off); } -static inline void hermes_clear_words(struct hermes *hw, int off, unsigned count) +static inline void hermes_clear_words(struct hermes *hw, int off, + unsigned count) { unsigned i; @@ -471,9 +475,10 @@ static inline void hermes_clear_words(struct hermes *hw, int off, unsigned count } #define HERMES_READ_RECORD(hw, bap, rid, buf) \ - (hermes_read_ltv((hw),(bap),(rid), sizeof(*buf), NULL, (buf))) + (hermes_read_ltv((hw), (bap), (rid), sizeof(*buf), NULL, (buf))) #define HERMES_WRITE_RECORD(hw, bap, rid, buf) \ - (hermes_write_ltv((hw),(bap),(rid),HERMES_BYTES_TO_RECLEN(sizeof(*buf)),(buf))) + (hermes_write_ltv((hw), (bap), (rid), \ + HERMES_BYTES_TO_RECLEN(sizeof(*buf)), (buf))) static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word) { diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h index c653816ef5f..f3f94b28ce6 100644 --- a/drivers/net/wireless/orinoco/orinoco.h +++ b/drivers/net/wireless/orinoco/orinoco.h @@ -1,5 +1,5 @@ /* orinoco.h - * + * * Common definitions to all pieces of the various orinoco * drivers */ @@ -18,9 +18,9 @@ #include "hermes.h" /* To enable debug messages */ -//#define ORINOCO_DEBUG 3 +/*#define ORINOCO_DEBUG 3*/ -#define WIRELESS_SPY // enable iwspy support +#define WIRELESS_SPY /* enable iwspy support */ #define MAX_SCAN_LEN 4096 @@ -121,7 +121,7 @@ struct orinoco_private { u16 encode_alg, wep_restrict, tx_key; struct orinoco_key keys[ORINOCO_MAX_KEYS]; int bitratemode; - char nick[IW_ESSID_MAX_SIZE+1]; + char nick[IW_ESSID_MAX_SIZE+1]; char desired_essid[IW_ESSID_MAX_SIZE+1]; char desired_bssid[ETH_ALEN]; int bssid_fixed; @@ -131,7 +131,7 @@ struct orinoco_private { u16 pm_on, pm_mcast, pm_period, pm_timeout; u16 preamble; #ifdef WIRELESS_SPY - struct iw_spy_data spy_data; /* iwspy support */ + struct iw_spy_data spy_data; /* iwspy support */ struct iw_public_data wireless_data; #endif @@ -168,7 +168,10 @@ struct orinoco_private { #ifdef ORINOCO_DEBUG extern int orinoco_debug; -#define DEBUG(n, args...) do { if (orinoco_debug>(n)) printk(KERN_DEBUG args); } while(0) +#define DEBUG(n, args...) do { \ + if (orinoco_debug > (n)) \ + printk(KERN_DEBUG args); \ +} while (0) #else #define DEBUG(n, args...) do { } while (0) #endif /* ORINOCO_DEBUG */ @@ -185,7 +188,7 @@ extern void free_orinocodev(struct net_device *dev); extern int __orinoco_up(struct net_device *dev); extern int __orinoco_down(struct net_device *dev); extern int orinoco_reinit_firmware(struct net_device *dev); -extern irqreturn_t orinoco_interrupt(int irq, void * dev_id); +extern irqreturn_t orinoco_interrupt(int irq, void *dev_id); /********************************************************************/ /* Locking and synchronization functions */ diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c index 0b32215d3f5..d194b3e0311 100644 --- a/drivers/net/wireless/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/orinoco/orinoco_cs.c @@ -6,7 +6,7 @@ * It should also be usable on various Prism II based cards such as the * Linksys, D-Link and Farallon Skyline. It should also work on Symbol * cards such as the 3Com AirConnect and Ericsson WLAN. - * + * * Copyright notice & release notes in file orinoco.c */ @@ -30,7 +30,8 @@ /********************************************************************/ MODULE_AUTHOR("David Gibson "); -MODULE_DESCRIPTION("Driver for PCMCIA Lucent Orinoco, Prism II based and similar wireless cards"); +MODULE_DESCRIPTION("Driver for PCMCIA Lucent Orinoco," + " Prism II based and similar wireless cards"); MODULE_LICENSE("Dual MPL/GPL"); /* Module parameters */ @@ -53,8 +54,8 @@ struct orinoco_pccard { /* Used to handle hard reset */ /* yuck, we need this hack to work around the insanity of the - * PCMCIA layer */ - unsigned long hard_reset_in_progress; + * PCMCIA layer */ + unsigned long hard_reset_in_progress; }; @@ -98,7 +99,7 @@ orinoco_cs_hard_reset(struct orinoco_private *priv) * This creates an "instance" of the driver, allocating local data * structures for one device. The device is registered with Card * Services. - * + * * The dev_link structure is initialized, but we don't actually * configure the card at this point -- we wait until we receive a card * insertion event. */ @@ -111,7 +112,7 @@ orinoco_cs_probe(struct pcmcia_device *link) dev = alloc_orinocodev(sizeof(*card), &handle_to_dev(link), orinoco_cs_hard_reset, NULL); - if (! dev) + if (!dev) return -ENOMEM; priv = netdev_priv(dev); card = priv->card; @@ -124,7 +125,7 @@ orinoco_cs_probe(struct pcmcia_device *link) link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = orinoco_interrupt; - link->irq.Instance = dev; + link->irq.Instance = dev; /* General socket configuration defaults can go here. In this * client, we assume very little, and rely on the CIS for @@ -162,8 +163,10 @@ static void orinoco_cs_detach(struct pcmcia_device *link) */ #define CS_CHECK(fn, ret) do { \ - last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \ - } while (0) + last_fn = (fn); \ + if ((last_ret = (ret)) != 0) \ + goto cs_failed; \ +} while (0) static int orinoco_cs_config_check(struct pcmcia_device *p_dev, cistpl_cftable_entry_t *cfg, @@ -307,8 +310,8 @@ orinoco_cs_config(struct pcmcia_device *link) * initialized and arranged in a linked list at link->dev_node. */ strcpy(card->node.dev_name, dev->name); link->dev_node = &card->node; /* link->dev_node being non-NULL is also - used to indicate that the - net_device has been registered */ + * used to indicate that the + * net_device has been registered */ /* Finally, report what we've done */ printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io " @@ -359,7 +362,7 @@ static int orinoco_cs_suspend(struct pcmcia_device *link) /* This is probably racy, but I can't think of a better way, short of rewriting the PCMCIA layer to not suck :-( */ - if (! test_bit(0, &card->hard_reset_in_progress)) { + if (!test_bit(0, &card->hard_reset_in_progress)) { spin_lock_irqsave(&priv->lock, flags); err = __orinoco_down(dev); @@ -384,7 +387,7 @@ static int orinoco_cs_resume(struct pcmcia_device *link) int err = 0; unsigned long flags; - if (! test_bit(0, &card->hard_reset_in_progress)) { + if (!test_bit(0, &card->hard_reset_in_progress)) { err = orinoco_reinit_firmware(dev); if (err) { printk(KERN_ERR "%s: Error %d re-initializing firmware\n", @@ -397,7 +400,7 @@ static int orinoco_cs_resume(struct pcmcia_device *link) netif_device_attach(dev); priv->hw_unavailable--; - if (priv->open && ! priv->hw_unavailable) { + if (priv->open && !priv->hw_unavailable) { err = __orinoco_up(dev); if (err) printk(KERN_ERR "%s: Error %d restarting card\n", diff --git a/drivers/net/wireless/orinoco/orinoco_nortel.c b/drivers/net/wireless/orinoco/orinoco_nortel.c index 2fc86596302..b01726255c6 100644 --- a/drivers/net/wireless/orinoco/orinoco_nortel.c +++ b/drivers/net/wireless/orinoco/orinoco_nortel.c @@ -9,12 +9,12 @@ * * Some of this code is borrowed from orinoco_plx.c * Copyright (C) 2001 Daniel Barlow - * Some of this code is borrowed from orinoco_pci.c + * Some of this code is borrowed from orinoco_pci.c * Copyright (C) 2001 Jean Tourrilhes * Some of this code is "inspired" by linux-wlan-ng-0.1.10, but nothing * has been copied from it. linux-wlan-ng-0.1.10 is originally : * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. - * + * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License @@ -103,9 +103,8 @@ static int orinoco_nortel_hw_init(struct orinoco_pci_card *card) iowrite16(0x8, card->bridge_io + 2); for (i = 0; i < 30; i++) { mdelay(30); - if (ioread16(card->bridge_io) & 0x10) { + if (ioread16(card->bridge_io) & 0x10) break; - } } if (i == 30) { printk(KERN_ERR PFX "brg1 timed out\n"); diff --git a/drivers/net/wireless/orinoco/orinoco_pci.c b/drivers/net/wireless/orinoco/orinoco_pci.c index 4ebd638a073..78cafff1fb2 100644 --- a/drivers/net/wireless/orinoco/orinoco_pci.c +++ b/drivers/net/wireless/orinoco/orinoco_pci.c @@ -1,5 +1,5 @@ /* orinoco_pci.c - * + * * Driver for Prism 2.5/3 devices that have a direct PCI interface * (i.e. these are not PCMCIA cards in a PCMCIA-to-PCI bridge). * The card contains only one PCI region, which contains all the usual @@ -237,7 +237,8 @@ static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION " (Pavel Roskin ," " David Gibson &" " Jean Tourrilhes )"; -MODULE_AUTHOR("Pavel Roskin & David Gibson "); +MODULE_AUTHOR("Pavel Roskin &" + " David Gibson "); MODULE_DESCRIPTION("Driver for wireless LAN cards using direct PCI interface"); MODULE_LICENSE("Dual MPL/GPL"); diff --git a/drivers/net/wireless/orinoco/orinoco_pci.h b/drivers/net/wireless/orinoco/orinoco_pci.h index f4e5e06760c..88df3ee9807 100644 --- a/drivers/net/wireless/orinoco/orinoco_pci.h +++ b/drivers/net/wireless/orinoco/orinoco_pci.h @@ -1,5 +1,5 @@ /* orinoco_pci.h - * + * * Common code for all Orinoco drivers for PCI devices, including * both native PCI and PCMCIA-to-PCI bridges. * @@ -37,11 +37,11 @@ static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state) if (err) printk(KERN_WARNING "%s: error %d bringing interface down " "for suspend\n", dev->name, err); - + netif_device_detach(dev); priv->hw_unavailable++; - + orinoco_unlock(priv, &flags); free_irq(pdev->irq, dev); @@ -90,13 +90,13 @@ static int orinoco_pci_resume(struct pci_dev *pdev) priv->hw_unavailable--; - if (priv->open && (! priv->hw_unavailable)) { + if (priv->open && (!priv->hw_unavailable)) { err = __orinoco_up(dev); if (err) printk(KERN_ERR "%s: Error %d restarting card on resume\n", dev->name, err); } - + spin_unlock_irqrestore(&priv->lock, flags); return 0; diff --git a/drivers/net/wireless/orinoco/orinoco_plx.c b/drivers/net/wireless/orinoco/orinoco_plx.c index ef761857bb3..a2a4471c033 100644 --- a/drivers/net/wireless/orinoco/orinoco_plx.c +++ b/drivers/net/wireless/orinoco/orinoco_plx.c @@ -146,9 +146,8 @@ static int orinoco_plx_hw_init(struct orinoco_pci_card *card) }; printk(KERN_DEBUG PFX "CIS: "); - for (i = 0; i < 16; i++) { + for (i = 0; i < 16; i++) printk("%02X:", ioread8(card->attr_io + (i << 1))); - } printk("\n"); /* Verify whether a supported PC card is present */ diff --git a/drivers/net/wireless/orinoco/orinoco_tmd.c b/drivers/net/wireless/orinoco/orinoco_tmd.c index ede24ec309c..e77c4042d43 100644 --- a/drivers/net/wireless/orinoco/orinoco_tmd.c +++ b/drivers/net/wireless/orinoco/orinoco_tmd.c @@ -1,7 +1,7 @@ /* orinoco_tmd.c * * Driver for Prism II devices which would usually be driven by orinoco_cs, - * but are connected to the PCI bus by a TMD7160. + * but are connected to the PCI bus by a TMD7160. * * Copyright (C) 2003 Joerg Dorchain * based heavily upon orinoco_plx.c Copyright (C) 2001 Daniel Barlow diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c index b2ca2e39c2c..9aefe19dbac 100644 --- a/drivers/net/wireless/orinoco/spectrum_cs.c +++ b/drivers/net/wireless/orinoco/spectrum_cs.c @@ -133,7 +133,7 @@ spectrum_reset(struct pcmcia_device *link, int idle) udelay(1000); return 0; - cs_failed: +cs_failed: cs_error(link, last_fn, last_ret); return -ENODEV; } @@ -171,7 +171,7 @@ spectrum_cs_stop_firmware(struct orinoco_private *priv, int idle) * This creates an "instance" of the driver, allocating local data * structures for one device. The device is registered with Card * Services. - * + * * The dev_link structure is initialized, but we don't actually * configure the card at this point -- we wait until we receive a card * insertion event. */ @@ -185,7 +185,7 @@ spectrum_cs_probe(struct pcmcia_device *link) dev = alloc_orinocodev(sizeof(*card), &handle_to_dev(link), spectrum_cs_hard_reset, spectrum_cs_stop_firmware); - if (! dev) + if (!dev) return -ENOMEM; priv = netdev_priv(dev); card = priv->card; @@ -198,7 +198,7 @@ spectrum_cs_probe(struct pcmcia_device *link) link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = orinoco_interrupt; - link->irq.Instance = dev; + link->irq.Instance = dev; /* General socket configuration defaults can go here. In this * client, we assume very little, and rely on the CIS for @@ -367,9 +367,8 @@ spectrum_cs_config(struct pcmcia_device *link) card->node.major = card->node.minor = 0; /* Reset card */ - if (spectrum_cs_hard_reset(priv) != 0) { + if (spectrum_cs_hard_reset(priv) != 0) goto failed; - } SET_NETDEV_DEV(dev, &handle_to_dev(link)); /* Tell the stack we exist */ @@ -382,8 +381,8 @@ spectrum_cs_config(struct pcmcia_device *link) * initialized and arranged in a linked list at link->dev_node. */ strcpy(card->node.dev_name, dev->name); link->dev_node = &card->node; /* link->dev_node being non-NULL is also - used to indicate that the - net_device has been registered */ + * used to indicate that the + * net_device has been registered */ /* Finally, report what we've done */ printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io " -- GitLab From 8ccde88a87a3dc906234b281a036fee9c7371949 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Tue, 27 Jan 2009 14:27:52 -0800 Subject: [PATCH 1453/4982] iwl3945: Getting rid of the *39_rxon iwl_priv fields The iwl_rxon_cmd is really just a iwl3945_rxon_cmd structure extension. So, we can use the *_rxon fields from iwl_priv instead of the 3945 specific ones (*39_rxon). We have to then be careful when submitting REPLY_RXON host commands, since the command length as to be set according to the HW. As another precaution the reserved4 and reserved5 fields are cleared before being sent to the 3945. With the *39_rxon removal, a lot of duplicated code can be removed from the 3945 code base. Signed-off-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Makefile | 2 +- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 13 +- drivers/net/wireless/iwlwifi/iwl-3945.h | 8 - .../net/wireless/iwlwifi/iwl-agn-hcmd-check.c | 109 --- drivers/net/wireless/iwlwifi/iwl-agn.c | 358 +-------- drivers/net/wireless/iwlwifi/iwl-core.c | 434 +++++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 19 + drivers/net/wireless/iwlwifi/iwl-dev.h | 7 - drivers/net/wireless/iwlwifi/iwl-rx.c | 9 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 711 +++--------------- 11 files changed, 585 insertions(+), 1087 deletions(-) delete mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index fec2fbf8dc0..ddc8b31b260 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -8,7 +8,7 @@ iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o iwlcore-$(CONFIG_IWLAGN_SPECTRUM_MEASUREMENT) += iwl-spectrum.o obj-$(CONFIG_IWLAGN) += iwlagn.o -iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-hcmd-check.o +iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwlagn-$(CONFIG_IWL4965) += iwl-4965.o iwlagn-$(CONFIG_IWL5000) += iwl-5000.o diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 044abf734eb..b93f5ba7719 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -934,7 +934,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) switch (priv->band) { case IEEE80211_BAND_2GHZ: /* TODO: this always does G, not a regression */ - if (priv->active39_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) { + if (priv->active_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) { rs_sta->tgg = 1; rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot; } else diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 12f93b6207d..610ee17c840 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -251,7 +251,7 @@ int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate) break; case IEEE80211_BAND_2GHZ: if (!(priv->sta_supp_rates & IWL_OFDM_RATES_MASK) && - iwl3945_is_associated(priv)) { + iwl_is_associated(priv)) { if (rate == IWL_RATE_11M_INDEX) next_rate = IWL_RATE_5M_INDEX; } @@ -579,7 +579,8 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, skb_put(rxb->skb, le16_to_cpu(rx_hdr->len)); if (!iwl3945_mod_params.sw_crypto) - iwl3945_set_decrypted_flag(priv, rxb->skb, + iwl_set_decrypted_flag(priv, + (struct ieee80211_hdr *)rxb->skb->data, le32_to_cpu(rx_end->status), stats); #ifdef CONFIG_IWL3945_LEDS @@ -1694,17 +1695,17 @@ int iwl3945_send_tx_power(struct iwl_priv *priv) int rate_idx, i; const struct iwl_channel_info *ch_info = NULL; struct iwl3945_txpowertable_cmd txpower = { - .channel = priv->active39_rxon.channel, + .channel = priv->active_rxon.channel, }; txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1; ch_info = iwl_get_channel_info(priv, priv->band, - le16_to_cpu(priv->active39_rxon.channel)); + le16_to_cpu(priv->active_rxon.channel)); if (!ch_info) { IWL_ERR(priv, "Failed to get channel info for channel %d [%d]\n", - le16_to_cpu(priv->active39_rxon.channel), priv->band); + le16_to_cpu(priv->active_rxon.channel), priv->band); return -EINVAL; } @@ -2432,7 +2433,7 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv) * 1M CCK rates */ if (!(priv->sta_supp_rates & IWL_OFDM_RATES_MASK) && - iwl3945_is_associated(priv)) { + iwl_is_associated(priv)) { index = IWL_FIRST_CCK_RATE; for (i = IWL_RATE_6M_INDEX_TABLE; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index fef54e9cf8a..ab7aaf6872c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -222,9 +222,6 @@ extern int __must_check iwl3945_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, struct ieee80211_hdr *hdr,int left); -extern void iwl3945_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb, - u32 decrypt_res, - struct ieee80211_rx_status *stats); /* * Currently used by iwl-3945-rs... look at restructuring so that it doesn't @@ -303,11 +300,6 @@ extern int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv); extern u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags); -static inline int iwl3945_is_associated(struct iwl_priv *priv) -{ - return (priv->active39_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0; -} - extern const struct iwl_channel_info *iwl3945_get_channel_info( const struct iwl_priv *priv, enum ieee80211_band band, u16 channel); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c deleted file mode 100644 index 1217a1da88f..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c +++ /dev/null @@ -1,109 +0,0 @@ -/****************************************************************************** - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *****************************************************************************/ - -#include -#include -#include "iwl-dev.h" -#include "iwl-debug.h" -#include "iwl-commands.h" - - -/** - * iwl_check_rxon_cmd - validate RXON structure is valid - * - * NOTE: This is really only useful during development and can eventually - * be #ifdef'd out once the driver is stable and folks aren't actively - * making changes - */ -int iwl_agn_check_rxon_cmd(struct iwl_priv *priv) -{ - int error = 0; - int counter = 1; - struct iwl_rxon_cmd *rxon = &priv->staging_rxon; - - if (rxon->flags & RXON_FLG_BAND_24G_MSK) { - error |= le32_to_cpu(rxon->flags & - (RXON_FLG_TGJ_NARROW_BAND_MSK | - RXON_FLG_RADAR_DETECT_MSK)); - if (error) - IWL_WARN(priv, "check 24G fields %d | %d\n", - counter++, error); - } else { - error |= (rxon->flags & RXON_FLG_SHORT_SLOT_MSK) ? - 0 : le32_to_cpu(RXON_FLG_SHORT_SLOT_MSK); - if (error) - IWL_WARN(priv, "check 52 fields %d | %d\n", - counter++, error); - error |= le32_to_cpu(rxon->flags & RXON_FLG_CCK_MSK); - if (error) - IWL_WARN(priv, "check 52 CCK %d | %d\n", - counter++, error); - } - error |= (rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1; - if (error) - IWL_WARN(priv, "check mac addr %d | %d\n", counter++, error); - - /* make sure basic rates 6Mbps and 1Mbps are supported */ - error |= (((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0) && - ((rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0)); - if (error) - IWL_WARN(priv, "check basic rate %d | %d\n", counter++, error); - - error |= (le16_to_cpu(rxon->assoc_id) > 2007); - if (error) - IWL_WARN(priv, "check assoc id %d | %d\n", counter++, error); - - error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) - == (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)); - if (error) - IWL_WARN(priv, "check CCK and short slot %d | %d\n", - counter++, error); - - error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) - == (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)); - if (error) - IWL_WARN(priv, "check CCK & auto detect %d | %d\n", - counter++, error); - - error |= ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK | - RXON_FLG_TGG_PROTECT_MSK)) == RXON_FLG_TGG_PROTECT_MSK); - if (error) - IWL_WARN(priv, "check TGG and auto detect %d | %d\n", - counter++, error); - - if (error) - IWL_WARN(priv, "Tuning to channel %d\n", - le16_to_cpu(rxon->channel)); - - if (error) { - IWL_ERR(priv, "Not a valid iwl_rxon_assoc_cmd field values\n"); - return -1; - } - return 0; -} - diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 6b7120a41ab..c54a9bcbb2e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -94,66 +94,6 @@ MODULE_ALIAS("iwl4965"); /**************************************************************/ - - -static void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) -{ - struct iwl_rxon_cmd *rxon = &priv->staging_rxon; - - if (hw_decrypt) - rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK; - else - rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK; - -} - -/** - * iwl_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed - * @priv: staging_rxon is compared to active_rxon - * - * If the RXON structure is changing enough to require a new tune, - * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that - * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. - */ -static int iwl_full_rxon_required(struct iwl_priv *priv) -{ - - /* These items are only settable from the full RXON command */ - if (!(iwl_is_associated(priv)) || - compare_ether_addr(priv->staging_rxon.bssid_addr, - priv->active_rxon.bssid_addr) || - compare_ether_addr(priv->staging_rxon.node_addr, - priv->active_rxon.node_addr) || - compare_ether_addr(priv->staging_rxon.wlap_bssid_addr, - priv->active_rxon.wlap_bssid_addr) || - (priv->staging_rxon.dev_type != priv->active_rxon.dev_type) || - (priv->staging_rxon.channel != priv->active_rxon.channel) || - (priv->staging_rxon.air_propagation != - priv->active_rxon.air_propagation) || - (priv->staging_rxon.ofdm_ht_single_stream_basic_rates != - priv->active_rxon.ofdm_ht_single_stream_basic_rates) || - (priv->staging_rxon.ofdm_ht_dual_stream_basic_rates != - priv->active_rxon.ofdm_ht_dual_stream_basic_rates) || - (priv->staging_rxon.assoc_id != priv->active_rxon.assoc_id)) - return 1; - - /* flags, filter_flags, ofdm_basic_rates, and cck_basic_rates can - * be updated with the RXON_ASSOC command -- however only some - * flag transitions are allowed using RXON_ASSOC */ - - /* Check if we are not switching bands */ - if ((priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) != - (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK)) - return 1; - - /* Check if we are switching association toggle */ - if ((priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) != - (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) - return 1; - - return 0; -} - /** * iwl_commit_rxon - commit staging_rxon to hardware * @@ -179,7 +119,7 @@ static int iwl_commit_rxon(struct iwl_priv *priv) * 5000, but will not damage 4965 */ priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN; - ret = iwl_agn_check_rxon_cmd(priv); + ret = iwl_check_rxon_cmd(priv); if (ret) { IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); return -EINVAL; @@ -374,31 +314,6 @@ static unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv, return priv->ibss_beacon->len; } -static u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv) -{ - int i; - int rate_mask; - - /* Set rate mask*/ - if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) - rate_mask = priv->active_rate_basic & IWL_CCK_RATES_MASK; - else - rate_mask = priv->active_rate_basic & IWL_OFDM_RATES_MASK; - - /* Find lowest valid rate */ - for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID; - i = iwl_rates[i].next_ieee) { - if (rate_mask & (1 << i)) - return iwl_rates[i].plcp; - } - - /* No valid rate was found. Assign the lowest one */ - if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) - return IWL_RATE_1M_PLCP; - else - return IWL_RATE_6M_PLCP; -} - static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, struct iwl_frame *frame, u8 rate) { @@ -771,111 +686,10 @@ static void iwl_setup_rxon_timing(struct iwl_priv *priv) le16_to_cpu(priv->rxon_timing.atim_window)); } -static void iwl_set_flags_for_band(struct iwl_priv *priv, - enum ieee80211_band band) -{ - if (band == IEEE80211_BAND_5GHZ) { - priv->staging_rxon.flags &= - ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK - | RXON_FLG_CCK_MSK); - priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; - } else { - /* Copied from iwl_post_associate() */ - if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) - priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; - else - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - - if (priv->iw_mode == NL80211_IFTYPE_ADHOC) - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - - priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; - priv->staging_rxon.flags |= RXON_FLG_AUTO_DETECT_MSK; - priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK; - } -} - -/* - * initialize rxon structure with default values from eeprom - */ -static void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode) -{ - const struct iwl_channel_info *ch_info; - - memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon)); - - switch (mode) { - case NL80211_IFTYPE_AP: - priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP; - break; - - case NL80211_IFTYPE_STATION: - priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS; - priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; - break; - - case NL80211_IFTYPE_ADHOC: - priv->staging_rxon.dev_type = RXON_DEV_TYPE_IBSS; - priv->staging_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK; - priv->staging_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK | - RXON_FILTER_ACCEPT_GRP_MSK; - break; - - case NL80211_IFTYPE_MONITOR: - priv->staging_rxon.dev_type = RXON_DEV_TYPE_SNIFFER; - priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK | - RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK; - break; - default: - IWL_ERR(priv, "Unsupported interface type %d\n", mode); - break; - } - -#if 0 - /* TODO: Figure out when short_preamble would be set and cache from - * that */ - if (!hw_to_local(priv->hw)->short_preamble) - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - else - priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; -#endif - - ch_info = iwl_get_channel_info(priv, priv->band, - le16_to_cpu(priv->active_rxon.channel)); - - if (!ch_info) - ch_info = &priv->channel_info[0]; - - /* - * in some case A channels are all non IBSS - * in this case force B/G channel - */ - if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && - !(is_channel_ibss(ch_info))) - ch_info = &priv->channel_info[0]; - - priv->staging_rxon.channel = cpu_to_le16(ch_info->channel); - priv->band = ch_info->band; - - iwl_set_flags_for_band(priv, priv->band); - - priv->staging_rxon.ofdm_basic_rates = - (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; - priv->staging_rxon.cck_basic_rates = - (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; - - priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK | - RXON_FLG_CHANNEL_MODE_PURE_40_MSK); - memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); - memcpy(priv->staging_rxon.wlap_bssid_addr, priv->mac_addr, ETH_ALEN); - priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff; - priv->staging_rxon.ofdm_ht_dual_stream_basic_rates = 0xff; - iwl_set_rxon_chain(priv); -} - static int iwl_set_mode(struct iwl_priv *priv, int mode) { iwl_connection_init_rx_config(priv, mode); + iwl_set_rxon_chain(priv); memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); iwl_clear_stations_table(priv); @@ -896,54 +710,6 @@ static int iwl_set_mode(struct iwl_priv *priv, int mode) return 0; } -static void iwl_set_rate(struct iwl_priv *priv) -{ - const struct ieee80211_supported_band *hw = NULL; - struct ieee80211_rate *rate; - int i; - - hw = iwl_get_hw_mode(priv, priv->band); - if (!hw) { - IWL_ERR(priv, "Failed to set rate: unable to get hw mode\n"); - return; - } - - priv->active_rate = 0; - priv->active_rate_basic = 0; - - for (i = 0; i < hw->n_bitrates; i++) { - rate = &(hw->bitrates[i]); - if (rate->hw_value < IWL_RATE_COUNT) - priv->active_rate |= (1 << rate->hw_value); - } - - IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n", - priv->active_rate, priv->active_rate_basic); - - /* - * If a basic rate is configured, then use it (adding IWL_RATE_1M_MASK) - * otherwise set it to the default of all CCK rates and 6, 12, 24 for - * OFDM - */ - if (priv->active_rate_basic & IWL_CCK_BASIC_RATES_MASK) - priv->staging_rxon.cck_basic_rates = - ((priv->active_rate_basic & - IWL_CCK_RATES_MASK) >> IWL_FIRST_CCK_RATE) & 0xF; - else - priv->staging_rxon.cck_basic_rates = - (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; - - if (priv->active_rate_basic & IWL_OFDM_BASIC_RATES_MASK) - priv->staging_rxon.ofdm_basic_rates = - ((priv->active_rate_basic & - (IWL_OFDM_BASIC_RATES_MASK | IWL_RATE_6M_MASK)) >> - IWL_FIRST_OFDM_RATE) & 0xFF; - else - priv->staging_rxon.ofdm_basic_rates = - (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; -} - - /****************************************************************************** * * Generic RX handler implementations @@ -999,19 +765,6 @@ static void iwl_rx_reply_error(struct iwl_priv *priv, le32_to_cpu(pkt->u.err_resp.error_info)); } -#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x - -static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon; - struct iwl_csa_notification *csa = &(pkt->u.csa_notif); - IWL_DEBUG_11H("CSA notif: channel %d, status %d\n", - le16_to_cpu(csa->channel), le32_to_cpu(csa->status)); - rxon->channel = csa->channel; - priv->staging_rxon.channel = csa->channel; -} - static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { @@ -1370,27 +1123,6 @@ void iwl_rx_handle(struct iwl_priv *priv) iwl_rx_queue_restock(priv); } -#ifdef CONFIG_IWLWIFI_DEBUG -static void iwl_print_rx_config_cmd(struct iwl_priv *priv) -{ - struct iwl_rxon_cmd *rxon = &priv->staging_rxon; - - IWL_DEBUG_RADIO("RX CONFIG:\n"); - iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon)); - IWL_DEBUG_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel)); - IWL_DEBUG_RADIO("u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags)); - IWL_DEBUG_RADIO("u32 filter_flags: 0x%08x\n", - le32_to_cpu(rxon->filter_flags)); - IWL_DEBUG_RADIO("u8 dev_type: 0x%x\n", rxon->dev_type); - IWL_DEBUG_RADIO("u8 ofdm_basic_rates: 0x%02x\n", - rxon->ofdm_basic_rates); - IWL_DEBUG_RADIO("u8 cck_basic_rates: 0x%02x\n", rxon->cck_basic_rates); - IWL_DEBUG_RADIO("u8[6] node_addr: %pM\n", rxon->node_addr); - IWL_DEBUG_RADIO("u8[6] bssid_addr: %pM\n", rxon->bssid_addr); - IWL_DEBUG_RADIO("u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id)); -} -#endif - /* call this function to flush any scheduled tasklet */ static inline void iwl_synchronize_irq(struct iwl_priv *priv) { @@ -1399,45 +1131,6 @@ static inline void iwl_synchronize_irq(struct iwl_priv *priv) tasklet_kill(&priv->irq_tasklet); } -/** - * iwl_irq_handle_error - called for HW or SW error interrupt from card - */ -static void iwl_irq_handle_error(struct iwl_priv *priv) -{ - /* Set the FW error flag -- cleared on iwl_down */ - set_bit(STATUS_FW_ERROR, &priv->status); - - /* Cancel currently queued command. */ - clear_bit(STATUS_HCMD_ACTIVE, &priv->status); - -#ifdef CONFIG_IWLWIFI_DEBUG - if (priv->debug_level & IWL_DL_FW_ERRORS) { - iwl_dump_nic_error_log(priv); - iwl_dump_nic_event_log(priv); - iwl_print_rx_config_cmd(priv); - } -#endif - - wake_up_interruptible(&priv->wait_command_queue); - - /* Keep the restart process from trying to send host - * commands by clearing the INIT status bit */ - clear_bit(STATUS_READY, &priv->status); - - if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { - IWL_DEBUG(IWL_DL_FW_ERRORS, - "Restarting adapter due to uCode error.\n"); - - if (iwl_is_associated(priv)) { - memcpy(&priv->recovery_rxon, &priv->active_rxon, - sizeof(priv->recovery_rxon)); - priv->error_recovering = 1; - } - if (priv->cfg->mod_params->restart_fw) - queue_work(priv->workqueue, &priv->restart); - } -} - static void iwl_error_recovery(struct iwl_priv *priv) { unsigned long flags; @@ -2010,6 +1703,7 @@ static void iwl_alive_start(struct iwl_priv *priv) } else { /* Initialize our rx_config data */ iwl_connection_init_rx_config(priv, priv->iw_mode); + iwl_set_rxon_chain(priv); memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); } @@ -2899,52 +2593,6 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, return 0; } -static void iwl_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - int mc_count, struct dev_addr_list *mc_list) -{ - struct iwl_priv *priv = hw->priv; - __le32 *filter_flags = &priv->staging_rxon.filter_flags; - - IWL_DEBUG_MAC80211("Enter: changed: 0x%x, total: 0x%x\n", - changed_flags, *total_flags); - - if (changed_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) { - if (*total_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) - *filter_flags |= RXON_FILTER_PROMISC_MSK; - else - *filter_flags &= ~RXON_FILTER_PROMISC_MSK; - } - if (changed_flags & FIF_ALLMULTI) { - if (*total_flags & FIF_ALLMULTI) - *filter_flags |= RXON_FILTER_ACCEPT_GRP_MSK; - else - *filter_flags &= ~RXON_FILTER_ACCEPT_GRP_MSK; - } - if (changed_flags & FIF_CONTROL) { - if (*total_flags & FIF_CONTROL) - *filter_flags |= RXON_FILTER_CTL2HOST_MSK; - else - *filter_flags &= ~RXON_FILTER_CTL2HOST_MSK; - } - if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { - if (*total_flags & FIF_BCN_PRBRESP_PROMISC) - *filter_flags |= RXON_FILTER_BCON_AWARE_MSK; - else - *filter_flags &= ~RXON_FILTER_BCON_AWARE_MSK; - } - - /* We avoid iwl_commit_rxon here to commit the new filter flags - * since mac80211 will call ieee80211_hw_config immediately. - * (mc_list is not supported at this time). Otherwise, we need to - * queue a background iwl_commit_rxon work. - */ - - *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | - FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; -} - static void iwl_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) { diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 21f386568c9..4f2b88c59c7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -28,6 +28,7 @@ #include #include +#include #include #include "iwl-eeprom.h" @@ -403,6 +404,7 @@ static void iwlcore_init_hw_rates(struct iwl_priv *priv, } } + /** * iwlcore_init_geos - Initialize mac80211's geo/channel info based from eeprom */ @@ -586,6 +588,167 @@ u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv, } EXPORT_SYMBOL(iwl_is_fat_tx_allowed); +void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) +{ + struct iwl_rxon_cmd *rxon = &priv->staging_rxon; + + if (hw_decrypt) + rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK; + else + rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK; + +} +EXPORT_SYMBOL(iwl_set_rxon_hwcrypto); + +/** + * iwl_check_rxon_cmd - validate RXON structure is valid + * + * NOTE: This is really only useful during development and can eventually + * be #ifdef'd out once the driver is stable and folks aren't actively + * making changes + */ +int iwl_check_rxon_cmd(struct iwl_priv *priv) +{ + int error = 0; + int counter = 1; + struct iwl_rxon_cmd *rxon = &priv->staging_rxon; + + if (rxon->flags & RXON_FLG_BAND_24G_MSK) { + error |= le32_to_cpu(rxon->flags & + (RXON_FLG_TGJ_NARROW_BAND_MSK | + RXON_FLG_RADAR_DETECT_MSK)); + if (error) + IWL_WARN(priv, "check 24G fields %d | %d\n", + counter++, error); + } else { + error |= (rxon->flags & RXON_FLG_SHORT_SLOT_MSK) ? + 0 : le32_to_cpu(RXON_FLG_SHORT_SLOT_MSK); + if (error) + IWL_WARN(priv, "check 52 fields %d | %d\n", + counter++, error); + error |= le32_to_cpu(rxon->flags & RXON_FLG_CCK_MSK); + if (error) + IWL_WARN(priv, "check 52 CCK %d | %d\n", + counter++, error); + } + error |= (rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1; + if (error) + IWL_WARN(priv, "check mac addr %d | %d\n", counter++, error); + + /* make sure basic rates 6Mbps and 1Mbps are supported */ + error |= (((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0) && + ((rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0)); + if (error) + IWL_WARN(priv, "check basic rate %d | %d\n", counter++, error); + + error |= (le16_to_cpu(rxon->assoc_id) > 2007); + if (error) + IWL_WARN(priv, "check assoc id %d | %d\n", counter++, error); + + error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) + == (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)); + if (error) + IWL_WARN(priv, "check CCK and short slot %d | %d\n", + counter++, error); + + error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) + == (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)); + if (error) + IWL_WARN(priv, "check CCK & auto detect %d | %d\n", + counter++, error); + + error |= ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK | + RXON_FLG_TGG_PROTECT_MSK)) == RXON_FLG_TGG_PROTECT_MSK); + if (error) + IWL_WARN(priv, "check TGG and auto detect %d | %d\n", + counter++, error); + + if (error) + IWL_WARN(priv, "Tuning to channel %d\n", + le16_to_cpu(rxon->channel)); + + if (error) { + IWL_ERR(priv, "Not a valid iwl_rxon_assoc_cmd field values\n"); + return -1; + } + return 0; +} +EXPORT_SYMBOL(iwl_check_rxon_cmd); + +/** + * iwl_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed + * @priv: staging_rxon is compared to active_rxon + * + * If the RXON structure is changing enough to require a new tune, + * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that + * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. + */ +int iwl_full_rxon_required(struct iwl_priv *priv) +{ + + /* These items are only settable from the full RXON command */ + if (!(iwl_is_associated(priv)) || + compare_ether_addr(priv->staging_rxon.bssid_addr, + priv->active_rxon.bssid_addr) || + compare_ether_addr(priv->staging_rxon.node_addr, + priv->active_rxon.node_addr) || + compare_ether_addr(priv->staging_rxon.wlap_bssid_addr, + priv->active_rxon.wlap_bssid_addr) || + (priv->staging_rxon.dev_type != priv->active_rxon.dev_type) || + (priv->staging_rxon.channel != priv->active_rxon.channel) || + (priv->staging_rxon.air_propagation != + priv->active_rxon.air_propagation) || + (priv->staging_rxon.ofdm_ht_single_stream_basic_rates != + priv->active_rxon.ofdm_ht_single_stream_basic_rates) || + (priv->staging_rxon.ofdm_ht_dual_stream_basic_rates != + priv->active_rxon.ofdm_ht_dual_stream_basic_rates) || + (priv->staging_rxon.assoc_id != priv->active_rxon.assoc_id)) + return 1; + + /* flags, filter_flags, ofdm_basic_rates, and cck_basic_rates can + * be updated with the RXON_ASSOC command -- however only some + * flag transitions are allowed using RXON_ASSOC */ + + /* Check if we are not switching bands */ + if ((priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) != + (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK)) + return 1; + + /* Check if we are switching association toggle */ + if ((priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) != + (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) + return 1; + + return 0; +} +EXPORT_SYMBOL(iwl_full_rxon_required); + +u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv) +{ + int i; + int rate_mask; + + /* Set rate mask*/ + if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) + rate_mask = priv->active_rate_basic & IWL_CCK_RATES_MASK; + else + rate_mask = priv->active_rate_basic & IWL_OFDM_RATES_MASK; + + /* Find lowest valid rate */ + for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID; + i = iwl_rates[i].next_ieee) { + if (rate_mask & (1 << i)) + return iwl_rates[i].plcp; + } + + /* No valid rate was found. Assign the lowest one */ + if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) + return IWL_RATE_1M_PLCP; + else + return IWL_RATE_6M_PLCP; +} +EXPORT_SYMBOL(iwl_rate_get_lowest_plcp); + void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) { struct iwl_rxon_cmd *rxon = &priv->staging_rxon; @@ -821,6 +984,277 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch) } EXPORT_SYMBOL(iwl_set_rxon_channel); +void iwl_set_flags_for_band(struct iwl_priv *priv, + enum ieee80211_band band) +{ + if (band == IEEE80211_BAND_5GHZ) { + priv->staging_rxon.flags &= + ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK + | RXON_FLG_CCK_MSK); + priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; + } else { + /* Copied from iwl_post_associate() */ + if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) + priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; + else + priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; + + if (priv->iw_mode == NL80211_IFTYPE_ADHOC) + priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; + + priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; + priv->staging_rxon.flags |= RXON_FLG_AUTO_DETECT_MSK; + priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK; + } +} +EXPORT_SYMBOL(iwl_set_flags_for_band); + +/* + * initialize rxon structure with default values from eeprom + */ +void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode) +{ + const struct iwl_channel_info *ch_info; + + memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon)); + + switch (mode) { + case NL80211_IFTYPE_AP: + priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP; + break; + + case NL80211_IFTYPE_STATION: + priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS; + priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; + break; + + case NL80211_IFTYPE_ADHOC: + priv->staging_rxon.dev_type = RXON_DEV_TYPE_IBSS; + priv->staging_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK; + priv->staging_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK | + RXON_FILTER_ACCEPT_GRP_MSK; + break; + + case NL80211_IFTYPE_MONITOR: + priv->staging_rxon.dev_type = RXON_DEV_TYPE_SNIFFER; + priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK | + RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK; + break; + default: + IWL_ERR(priv, "Unsupported interface type %d\n", mode); + break; + } + +#if 0 + /* TODO: Figure out when short_preamble would be set and cache from + * that */ + if (!hw_to_local(priv->hw)->short_preamble) + priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + else + priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; +#endif + + ch_info = iwl_get_channel_info(priv, priv->band, + le16_to_cpu(priv->active_rxon.channel)); + + if (!ch_info) + ch_info = &priv->channel_info[0]; + + /* + * in some case A channels are all non IBSS + * in this case force B/G channel + */ + if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && + !(is_channel_ibss(ch_info))) + ch_info = &priv->channel_info[0]; + + priv->staging_rxon.channel = cpu_to_le16(ch_info->channel); + priv->band = ch_info->band; + + iwl_set_flags_for_band(priv, priv->band); + + priv->staging_rxon.ofdm_basic_rates = + (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; + priv->staging_rxon.cck_basic_rates = + (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; + + priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK | + RXON_FLG_CHANNEL_MODE_PURE_40_MSK); + memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); + memcpy(priv->staging_rxon.wlap_bssid_addr, priv->mac_addr, ETH_ALEN); + priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff; + priv->staging_rxon.ofdm_ht_dual_stream_basic_rates = 0xff; +} +EXPORT_SYMBOL(iwl_connection_init_rx_config); + +void iwl_set_rate(struct iwl_priv *priv) +{ + const struct ieee80211_supported_band *hw = NULL; + struct ieee80211_rate *rate; + int i; + + hw = iwl_get_hw_mode(priv, priv->band); + if (!hw) { + IWL_ERR(priv, "Failed to set rate: unable to get hw mode\n"); + return; + } + + priv->active_rate = 0; + priv->active_rate_basic = 0; + + for (i = 0; i < hw->n_bitrates; i++) { + rate = &(hw->bitrates[i]); + if (rate->hw_value < IWL_RATE_COUNT) + priv->active_rate |= (1 << rate->hw_value); + } + + IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n", + priv->active_rate, priv->active_rate_basic); + + /* + * If a basic rate is configured, then use it (adding IWL_RATE_1M_MASK) + * otherwise set it to the default of all CCK rates and 6, 12, 24 for + * OFDM + */ + if (priv->active_rate_basic & IWL_CCK_BASIC_RATES_MASK) + priv->staging_rxon.cck_basic_rates = + ((priv->active_rate_basic & + IWL_CCK_RATES_MASK) >> IWL_FIRST_CCK_RATE) & 0xF; + else + priv->staging_rxon.cck_basic_rates = + (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; + + if (priv->active_rate_basic & IWL_OFDM_BASIC_RATES_MASK) + priv->staging_rxon.ofdm_basic_rates = + ((priv->active_rate_basic & + (IWL_OFDM_BASIC_RATES_MASK | IWL_RATE_6M_MASK)) >> + IWL_FIRST_OFDM_RATE) & 0xFF; + else + priv->staging_rxon.ofdm_basic_rates = + (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; +} +EXPORT_SYMBOL(iwl_set_rate); + +void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) +{ + struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; + struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon; + struct iwl_csa_notification *csa = &(pkt->u.csa_notif); + IWL_DEBUG_11H("CSA notif: channel %d, status %d\n", + le16_to_cpu(csa->channel), le32_to_cpu(csa->status)); + rxon->channel = csa->channel; + priv->staging_rxon.channel = csa->channel; +} +EXPORT_SYMBOL(iwl_rx_csa); + +#ifdef CONFIG_IWLWIFI_DEBUG +static void iwl_print_rx_config_cmd(struct iwl_priv *priv) +{ + struct iwl_rxon_cmd *rxon = &priv->staging_rxon; + + IWL_DEBUG_RADIO("RX CONFIG:\n"); + iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon)); + IWL_DEBUG_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel)); + IWL_DEBUG_RADIO("u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags)); + IWL_DEBUG_RADIO("u32 filter_flags: 0x%08x\n", + le32_to_cpu(rxon->filter_flags)); + IWL_DEBUG_RADIO("u8 dev_type: 0x%x\n", rxon->dev_type); + IWL_DEBUG_RADIO("u8 ofdm_basic_rates: 0x%02x\n", + rxon->ofdm_basic_rates); + IWL_DEBUG_RADIO("u8 cck_basic_rates: 0x%02x\n", rxon->cck_basic_rates); + IWL_DEBUG_RADIO("u8[6] node_addr: %pM\n", rxon->node_addr); + IWL_DEBUG_RADIO("u8[6] bssid_addr: %pM\n", rxon->bssid_addr); + IWL_DEBUG_RADIO("u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id)); +} +#endif + +/** + * iwl_irq_handle_error - called for HW or SW error interrupt from card + */ +void iwl_irq_handle_error(struct iwl_priv *priv) +{ + /* Set the FW error flag -- cleared on iwl_down */ + set_bit(STATUS_FW_ERROR, &priv->status); + + /* Cancel currently queued command. */ + clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + +#ifdef CONFIG_IWLWIFI_DEBUG + if (priv->debug_level & IWL_DL_FW_ERRORS) { + iwl_dump_nic_error_log(priv); + iwl_dump_nic_event_log(priv); + iwl_print_rx_config_cmd(priv); + } +#endif + + wake_up_interruptible(&priv->wait_command_queue); + + /* Keep the restart process from trying to send host + * commands by clearing the INIT status bit */ + clear_bit(STATUS_READY, &priv->status); + + if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { + IWL_DEBUG(IWL_DL_FW_ERRORS, + "Restarting adapter due to uCode error.\n"); + + if (iwl_is_associated(priv)) { + memcpy(&priv->recovery_rxon, &priv->active_rxon, + sizeof(priv->recovery_rxon)); + priv->error_recovering = 1; + } + if (priv->cfg->mod_params->restart_fw) + queue_work(priv->workqueue, &priv->restart); + } +} +EXPORT_SYMBOL(iwl_irq_handle_error); + +void iwl_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + int mc_count, struct dev_addr_list *mc_list) +{ + struct iwl_priv *priv = hw->priv; + __le32 *filter_flags = &priv->staging_rxon.filter_flags; + + IWL_DEBUG_MAC80211("Enter: changed: 0x%x, total: 0x%x\n", + changed_flags, *total_flags); + + if (changed_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) { + if (*total_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) + *filter_flags |= RXON_FILTER_PROMISC_MSK; + else + *filter_flags &= ~RXON_FILTER_PROMISC_MSK; + } + if (changed_flags & FIF_ALLMULTI) { + if (*total_flags & FIF_ALLMULTI) + *filter_flags |= RXON_FILTER_ACCEPT_GRP_MSK; + else + *filter_flags &= ~RXON_FILTER_ACCEPT_GRP_MSK; + } + if (changed_flags & FIF_CONTROL) { + if (*total_flags & FIF_CONTROL) + *filter_flags |= RXON_FILTER_CTL2HOST_MSK; + else + *filter_flags &= ~RXON_FILTER_CTL2HOST_MSK; + } + if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { + if (*total_flags & FIF_BCN_PRBRESP_PROMISC) + *filter_flags |= RXON_FILTER_BCON_AWARE_MSK; + else + *filter_flags &= ~RXON_FILTER_BCON_AWARE_MSK; + } + + /* We avoid iwl_commit_rxon here to commit the new filter flags + * since mac80211 will call ieee80211_hw_config immediately. + * (mc_list is not supported at this time). Otherwise, we need to + * queue a background iwl_commit_rxon work. + */ + + *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | + FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; +} +EXPORT_SYMBOL(iwl_configure_filter); + int iwl_setup_mac(struct iwl_priv *priv) { int ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 3c6a4b0c2c3..0a719aeb734 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -221,11 +221,25 @@ struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, struct ieee80211_ops *hw_ops); void iwl_hw_detect(struct iwl_priv *priv); void iwl_reset_qos(struct iwl_priv *priv); +void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt); +int iwl_check_rxon_cmd(struct iwl_priv *priv); +int iwl_full_rxon_required(struct iwl_priv *priv); void iwl_set_rxon_chain(struct iwl_priv *priv); int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info); u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv, struct ieee80211_sta_ht_cap *sta_ht_inf); +void iwl_set_flags_for_band(struct iwl_priv *priv, enum ieee80211_band band); +void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode); +int iwl_set_decrypted_flag(struct iwl_priv *priv, + struct ieee80211_hdr *hdr, + u32 decrypt_res, + struct ieee80211_rx_status *stats); +void iwl_irq_handle_error(struct iwl_priv *priv); +void iwl_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + int mc_count, struct dev_addr_list *mc_list); int iwl_hw_nic_init(struct iwl_priv *priv); int iwl_setup_mac(struct iwl_priv *priv); int iwl_set_hw_params(struct iwl_priv *priv); @@ -253,6 +267,7 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); void iwl_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); +void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); /* TX helpers */ @@ -296,6 +311,10 @@ void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, struct ieee80211_tx_info *info); int iwl_hwrate_to_plcp_idx(u32 rate_n_flags); +u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv); + +void iwl_set_rate(struct iwl_priv *priv); + u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx); static inline u32 iwl_ant_idx_to_flags(u8 ant_idx) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 437c05b9a33..b9954bc89cf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1078,13 +1078,6 @@ struct iwl_priv { /*For 3945*/ #define IWL_DEFAULT_TX_POWER 0x0F - /* We declare this const so it can only be - * changed via explicit cast within the - * routines that actually update the physical - * hardware */ - const struct iwl3945_rxon_cmd active39_rxon; - struct iwl3945_rxon_cmd staging39_rxon; - struct iwl3945_rxon_cmd recovery39_rxon; struct iwl3945_notif_statistics statistics_39; diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 33145207fc1..c8865d0b906 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -772,10 +772,10 @@ static void iwl_update_rx_stats(struct iwl_priv *priv, u16 fc, u16 len) /* * returns non-zero if packet should be dropped */ -static int iwl_set_decrypted_flag(struct iwl_priv *priv, - struct ieee80211_hdr *hdr, - u32 decrypt_res, - struct ieee80211_rx_status *stats) +int iwl_set_decrypted_flag(struct iwl_priv *priv, + struct ieee80211_hdr *hdr, + u32 decrypt_res, + struct ieee80211_rx_status *stats) { u16 fc = le16_to_cpu(hdr->frame_control); @@ -815,6 +815,7 @@ static int iwl_set_decrypted_flag(struct iwl_priv *priv, } return 0; } +EXPORT_SYMBOL(iwl_set_decrypted_flag); static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) { diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 25a350810a1..6a2c8a3a3d5 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -233,166 +233,6 @@ u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flag } -/** - * iwl3945_set_rxon_channel - Set the phymode and channel values in staging RXON - * @band: 2.4 or 5 GHz band - * @channel: Any channel valid for the requested band - - * In addition to setting the staging RXON, priv->band is also set. - * - * NOTE: Does not commit to the hardware; it sets appropriate bit fields - * in the staging RXON flag structure based on the band - */ -static int iwl3945_set_rxon_channel(struct iwl_priv *priv, - enum ieee80211_band band, - u16 channel) -{ - if (!iwl_get_channel_info(priv, band, channel)) { - IWL_DEBUG_INFO("Could not set channel to %d [%d]\n", - channel, band); - return -EINVAL; - } - - if ((le16_to_cpu(priv->staging39_rxon.channel) == channel) && - (priv->band == band)) - return 0; - - priv->staging39_rxon.channel = cpu_to_le16(channel); - if (band == IEEE80211_BAND_5GHZ) - priv->staging39_rxon.flags &= ~RXON_FLG_BAND_24G_MSK; - else - priv->staging39_rxon.flags |= RXON_FLG_BAND_24G_MSK; - - priv->band = band; - - IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, band); - - return 0; -} - -/** - * iwl3945_check_rxon_cmd - validate RXON structure is valid - * - * NOTE: This is really only useful during development and can eventually - * be #ifdef'd out once the driver is stable and folks aren't actively - * making changes - */ -static int iwl3945_check_rxon_cmd(struct iwl_priv *priv) -{ - int error = 0; - int counter = 1; - struct iwl3945_rxon_cmd *rxon = &priv->staging39_rxon; - - if (rxon->flags & RXON_FLG_BAND_24G_MSK) { - error |= le32_to_cpu(rxon->flags & - (RXON_FLG_TGJ_NARROW_BAND_MSK | - RXON_FLG_RADAR_DETECT_MSK)); - if (error) - IWL_WARN(priv, "check 24G fields %d | %d\n", - counter++, error); - } else { - error |= (rxon->flags & RXON_FLG_SHORT_SLOT_MSK) ? - 0 : le32_to_cpu(RXON_FLG_SHORT_SLOT_MSK); - if (error) - IWL_WARN(priv, "check 52 fields %d | %d\n", - counter++, error); - error |= le32_to_cpu(rxon->flags & RXON_FLG_CCK_MSK); - if (error) - IWL_WARN(priv, "check 52 CCK %d | %d\n", - counter++, error); - } - error |= (rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1; - if (error) - IWL_WARN(priv, "check mac addr %d | %d\n", counter++, error); - - /* make sure basic rates 6Mbps and 1Mbps are supported */ - error |= (((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0) && - ((rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0)); - if (error) - IWL_WARN(priv, "check basic rate %d | %d\n", counter++, error); - - error |= (le16_to_cpu(rxon->assoc_id) > 2007); - if (error) - IWL_WARN(priv, "check assoc id %d | %d\n", counter++, error); - - error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) - == (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)); - if (error) - IWL_WARN(priv, "check CCK and short slot %d | %d\n", - counter++, error); - - error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) - == (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)); - if (error) - IWL_WARN(priv, "check CCK & auto detect %d | %d\n", - counter++, error); - - error |= ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK | - RXON_FLG_TGG_PROTECT_MSK)) == RXON_FLG_TGG_PROTECT_MSK); - if (error) - IWL_WARN(priv, "check TGG and auto detect %d | %d\n", - counter++, error); - - if ((rxon->flags & RXON_FLG_DIS_DIV_MSK)) - error |= ((rxon->flags & (RXON_FLG_ANT_B_MSK | - RXON_FLG_ANT_A_MSK)) == 0); - if (error) - IWL_WARN(priv, "check antenna %d %d\n", counter++, error); - - if (error) - IWL_WARN(priv, "Tuning to channel %d\n", - le16_to_cpu(rxon->channel)); - - if (error) { - IWL_ERR(priv, "Not a valid rxon_assoc_cmd field values\n"); - return -1; - } - return 0; -} - -/** - * iwl3945_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed - * @priv: staging_rxon is compared to active_rxon - * - * If the RXON structure is changing enough to require a new tune, - * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that - * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. - */ -static int iwl3945_full_rxon_required(struct iwl_priv *priv) -{ - - /* These items are only settable from the full RXON command */ - if (!(iwl3945_is_associated(priv)) || - compare_ether_addr(priv->staging39_rxon.bssid_addr, - priv->active39_rxon.bssid_addr) || - compare_ether_addr(priv->staging39_rxon.node_addr, - priv->active39_rxon.node_addr) || - compare_ether_addr(priv->staging39_rxon.wlap_bssid_addr, - priv->active39_rxon.wlap_bssid_addr) || - (priv->staging39_rxon.dev_type != priv->active39_rxon.dev_type) || - (priv->staging39_rxon.channel != priv->active39_rxon.channel) || - (priv->staging39_rxon.air_propagation != - priv->active39_rxon.air_propagation) || - (priv->staging39_rxon.assoc_id != priv->active39_rxon.assoc_id)) - return 1; - - /* flags, filter_flags, ofdm_basic_rates, and cck_basic_rates can - * be updated with the RXON_ASSOC command -- however only some - * flag transitions are allowed using RXON_ASSOC */ - - /* Check if we are not switching bands */ - if ((priv->staging39_rxon.flags & RXON_FLG_BAND_24G_MSK) != - (priv->active39_rxon.flags & RXON_FLG_BAND_24G_MSK)) - return 1; - - /* Check if we are switching association toggle */ - if ((priv->staging39_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) != - (priv->active39_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) - return 1; - - return 0; -} - static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) { int rc = 0; @@ -404,8 +244,8 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) .meta.flags = CMD_WANT_SKB, .data = &rxon_assoc, }; - const struct iwl3945_rxon_cmd *rxon1 = &priv->staging39_rxon; - const struct iwl3945_rxon_cmd *rxon2 = &priv->active39_rxon; + const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; + const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; if ((rxon1->flags == rxon2->flags) && (rxon1->filter_flags == rxon2->filter_flags) && @@ -415,10 +255,10 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) return 0; } - rxon_assoc.flags = priv->staging39_rxon.flags; - rxon_assoc.filter_flags = priv->staging39_rxon.filter_flags; - rxon_assoc.ofdm_basic_rates = priv->staging39_rxon.ofdm_basic_rates; - rxon_assoc.cck_basic_rates = priv->staging39_rxon.cck_basic_rates; + rxon_assoc.flags = priv->staging_rxon.flags; + rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; + rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; + rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; rxon_assoc.reserved = 0; rc = iwl_send_cmd_sync(priv, &cmd); @@ -485,21 +325,22 @@ __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv) static int iwl3945_commit_rxon(struct iwl_priv *priv) { /* cast away the const for active_rxon in this function */ - struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active39_rxon; + struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon; + struct iwl3945_rxon_cmd *staging_rxon = (void *)&priv->staging_rxon; int rc = 0; if (!iwl_is_alive(priv)) return -1; /* always get timestamp with Rx frame */ - priv->staging39_rxon.flags |= RXON_FLG_TSF2HOST_MSK; + staging_rxon->flags |= RXON_FLG_TSF2HOST_MSK; /* select antenna */ - priv->staging39_rxon.flags &= + staging_rxon->flags &= ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK); - priv->staging39_rxon.flags |= iwl3945_get_antenna_flags(priv); + staging_rxon->flags |= iwl3945_get_antenna_flags(priv); - rc = iwl3945_check_rxon_cmd(priv); + rc = iwl_check_rxon_cmd(priv); if (rc) { IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); return -EINVAL; @@ -508,7 +349,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) /* If we don't need to send a full RXON, we can use * iwl3945_rxon_assoc_cmd which is used to reconfigure filter * and other flags for the current radio configuration. */ - if (!iwl3945_full_rxon_required(priv)) { + if (!iwl_full_rxon_required(priv)) { rc = iwl3945_send_rxon_assoc(priv); if (rc) { IWL_ERR(priv, "Error setting RXON_ASSOC " @@ -516,7 +357,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) return rc; } - memcpy(active_rxon, &priv->staging39_rxon, sizeof(*active_rxon)); + memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); return 0; } @@ -525,14 +366,20 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) * an RXON_ASSOC and the new config wants the associated mask enabled, * we must clear the associated from the active configuration * before we apply the new config */ - if (iwl3945_is_associated(priv) && - (priv->staging39_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) { + if (iwl_is_associated(priv) && + (staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK)) { IWL_DEBUG_INFO("Toggling associated bit on current RXON\n"); active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; + /* + * reserved4 and 5 could have been filled by the iwlcore code. + * Let's clear them before pushing to the 3945. + */ + active_rxon->reserved4 = 0; + active_rxon->reserved5 = 0; rc = iwl_send_cmd_pdu(priv, REPLY_RXON, sizeof(struct iwl3945_rxon_cmd), - &priv->active39_rxon); + &priv->active_rxon); /* If the mask clearing failed then we set * active_rxon back to what it was previously */ @@ -548,20 +395,28 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) "* with%s RXON_FILTER_ASSOC_MSK\n" "* channel = %d\n" "* bssid = %pM\n", - ((priv->staging39_rxon.filter_flags & + ((priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? "" : "out"), - le16_to_cpu(priv->staging39_rxon.channel), - priv->staging_rxon.bssid_addr); + le16_to_cpu(staging_rxon->channel), + staging_rxon->bssid_addr); + + /* + * reserved4 and 5 could have been filled by the iwlcore code. + * Let's clear them before pushing to the 3945. + */ + staging_rxon->reserved4 = 0; + staging_rxon->reserved5 = 0; /* Apply the new configuration */ rc = iwl_send_cmd_pdu(priv, REPLY_RXON, - sizeof(struct iwl3945_rxon_cmd), &priv->staging39_rxon); + sizeof(struct iwl3945_rxon_cmd), + staging_rxon); if (rc) { IWL_ERR(priv, "Error setting new configuration (%d).\n", rc); return rc; } - memcpy(active_rxon, &priv->staging39_rxon, sizeof(*active_rxon)); + memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); iwl3945_clear_stations_table(priv); @@ -582,9 +437,10 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) /* If we have set the ASSOC_MSK and we are in BSS mode then * add the IWL_AP_ID to the station rate table */ - if (iwl3945_is_associated(priv) && + if (iwl_is_associated(priv) && (priv->iw_mode == NL80211_IFTYPE_STATION)) - if (iwl3945_add_station(priv, priv->active39_rxon.bssid_addr, 1, 0) + if (iwl3945_add_station(priv, priv->active_rxon.bssid_addr, + 1, 0) == IWL_INVALID_STATION) { IWL_ERR(priv, "Error adding AP address for transmit\n"); return -EIO; @@ -710,7 +566,7 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, int left) { - if (!iwl3945_is_associated(priv) || !priv->ibss_beacon || + if (!iwl_is_associated(priv) || !priv->ibss_beacon || ((priv->iw_mode != NL80211_IFTYPE_ADHOC) && (priv->iw_mode != NL80211_IFTYPE_AP))) return 0; @@ -723,30 +579,6 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, return priv->ibss_beacon->len; } -static u8 iwl3945_rate_get_lowest_plcp(struct iwl_priv *priv) -{ - u8 i; - int rate_mask; - - /* Set rate mask*/ - if (priv->staging39_rxon.flags & RXON_FLG_BAND_24G_MSK) - rate_mask = priv->active_rate_basic & IWL_CCK_RATES_MASK; - else - rate_mask = priv->active_rate_basic & IWL_OFDM_RATES_MASK; - - for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID; - i = iwl3945_rates[i].next_ieee) { - if (rate_mask & (1 << i)) - return iwl3945_rates[i].plcp; - } - - /* No valid rate was found. Assign the lowest one */ - if (priv->staging39_rxon.flags & RXON_FLG_BAND_24G_MSK) - return IWL_RATE_1M_PLCP; - else - return IWL_RATE_6M_PLCP; -} - static int iwl3945_send_beacon_cmd(struct iwl_priv *priv) { struct iwl3945_frame *frame; @@ -762,7 +594,7 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv) return -ENOMEM; } - rate = iwl3945_rate_get_lowest_plcp(priv); + rate = iwl_rate_get_lowest_plcp(priv); frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate); @@ -815,7 +647,7 @@ static void iwl3945_activate_qos(struct iwl_priv *priv, u8 force) spin_unlock_irqrestore(&priv->lock, flags); - if (force || iwl3945_is_associated(priv)) { + if (force || iwl_is_associated(priv)) { IWL_DEBUG_QOS("send QoS cmd with QoS active %d \n", priv->qos_data.qos_active); @@ -1082,115 +914,6 @@ static int iwl3945_scan_initiate(struct iwl_priv *priv) return 0; } -static int iwl3945_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) -{ - struct iwl3945_rxon_cmd *rxon = &priv->staging39_rxon; - - if (hw_decrypt) - rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK; - else - rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK; - - return 0; -} - -static void iwl3945_set_flags_for_phymode(struct iwl_priv *priv, - enum ieee80211_band band) -{ - if (band == IEEE80211_BAND_5GHZ) { - priv->staging39_rxon.flags &= - ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK - | RXON_FLG_CCK_MSK); - priv->staging39_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; - } else { - /* Copied from iwl3945_bg_post_associate() */ - if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) - priv->staging39_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; - else - priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - - if (priv->iw_mode == NL80211_IFTYPE_ADHOC) - priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - - priv->staging39_rxon.flags |= RXON_FLG_BAND_24G_MSK; - priv->staging39_rxon.flags |= RXON_FLG_AUTO_DETECT_MSK; - priv->staging39_rxon.flags &= ~RXON_FLG_CCK_MSK; - } -} - -/* - * initialize rxon structure with default values from eeprom - */ -static void iwl3945_connection_init_rx_config(struct iwl_priv *priv, - int mode) -{ - const struct iwl_channel_info *ch_info; - - memset(&priv->staging39_rxon, 0, sizeof(priv->staging39_rxon)); - - switch (mode) { - case NL80211_IFTYPE_AP: - priv->staging39_rxon.dev_type = RXON_DEV_TYPE_AP; - break; - - case NL80211_IFTYPE_STATION: - priv->staging39_rxon.dev_type = RXON_DEV_TYPE_ESS; - priv->staging39_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; - break; - - case NL80211_IFTYPE_ADHOC: - priv->staging39_rxon.dev_type = RXON_DEV_TYPE_IBSS; - priv->staging39_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK; - priv->staging39_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK | - RXON_FILTER_ACCEPT_GRP_MSK; - break; - - case NL80211_IFTYPE_MONITOR: - priv->staging39_rxon.dev_type = RXON_DEV_TYPE_SNIFFER; - priv->staging39_rxon.filter_flags = RXON_FILTER_PROMISC_MSK | - RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK; - break; - default: - IWL_ERR(priv, "Unsupported interface type %d\n", mode); - break; - } - -#if 0 - /* TODO: Figure out when short_preamble would be set and cache from - * that */ - if (!hw_to_local(priv->hw)->short_preamble) - priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - else - priv->staging39_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; -#endif - - ch_info = iwl_get_channel_info(priv, priv->band, - le16_to_cpu(priv->active39_rxon.channel)); - - if (!ch_info) - ch_info = &priv->channel_info[0]; - - /* - * in some case A channels are all non IBSS - * in this case force B/G channel - */ - if ((mode == NL80211_IFTYPE_ADHOC) && !(is_channel_ibss(ch_info))) - ch_info = &priv->channel_info[0]; - - priv->staging39_rxon.channel = cpu_to_le16(ch_info->channel); - if (is_channel_a_band(ch_info)) - priv->band = IEEE80211_BAND_5GHZ; - else - priv->band = IEEE80211_BAND_2GHZ; - - iwl3945_set_flags_for_phymode(priv, priv->band); - - priv->staging39_rxon.ofdm_basic_rates = - (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; - priv->staging39_rxon.cck_basic_rates = - (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; -} - static int iwl3945_set_mode(struct iwl_priv *priv, int mode) { if (mode == NL80211_IFTYPE_ADHOC) { @@ -1198,17 +921,16 @@ static int iwl3945_set_mode(struct iwl_priv *priv, int mode) ch_info = iwl_get_channel_info(priv, priv->band, - le16_to_cpu(priv->staging39_rxon.channel)); + le16_to_cpu(priv->staging_rxon.channel)); if (!ch_info || !is_channel_ibss(ch_info)) { IWL_ERR(priv, "channel %d not IBSS channel\n", - le16_to_cpu(priv->staging39_rxon.channel)); + le16_to_cpu(priv->staging_rxon.channel)); return -EINVAL; } } - iwl3945_connection_init_rx_config(priv, mode); - memcpy(priv->staging39_rxon.node_addr, priv->mac_addr, ETH_ALEN); + iwl_connection_init_rx_config(priv, mode); iwl3945_clear_stations_table(priv); @@ -1455,9 +1177,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* drop all data frame if we are not associated */ if (ieee80211_is_data(fc) && (priv->iw_mode != NL80211_IFTYPE_MONITOR) && /* packet injection */ - (!iwl3945_is_associated(priv) || + (!iwl_is_associated(priv) || ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id))) { - IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n"); + IWL_DEBUG_DROP("Dropping - !iwl_is_associated\n"); goto drop_unlock; } @@ -1622,60 +1344,6 @@ drop: return -1; } -static void iwl3945_set_rate(struct iwl_priv *priv) -{ - const struct ieee80211_supported_band *sband = NULL; - struct ieee80211_rate *rate; - int i; - - sband = iwl_get_hw_mode(priv, priv->band); - if (!sband) { - IWL_ERR(priv, "Failed to set rate: unable to get hw mode\n"); - return; - } - - priv->active_rate = 0; - priv->active_rate_basic = 0; - - IWL_DEBUG_RATE("Setting rates for %s GHz\n", - sband->band == IEEE80211_BAND_2GHZ ? "2.4" : "5"); - - for (i = 0; i < sband->n_bitrates; i++) { - rate = &sband->bitrates[i]; - if ((rate->hw_value < IWL_RATE_COUNT) && - !(rate->flags & IEEE80211_CHAN_DISABLED)) { - IWL_DEBUG_RATE("Adding rate index %d (plcp %d)\n", - rate->hw_value, iwl3945_rates[rate->hw_value].plcp); - priv->active_rate |= (1 << rate->hw_value); - } - } - - IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n", - priv->active_rate, priv->active_rate_basic); - - /* - * If a basic rate is configured, then use it (adding IWL_RATE_1M_MASK) - * otherwise set it to the default of all CCK rates and 6, 12, 24 for - * OFDM - */ - if (priv->active_rate_basic & IWL_CCK_BASIC_RATES_MASK) - priv->staging39_rxon.cck_basic_rates = - ((priv->active_rate_basic & - IWL_CCK_RATES_MASK) >> IWL_FIRST_CCK_RATE) & 0xF; - else - priv->staging39_rxon.cck_basic_rates = - (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; - - if (priv->active_rate_basic & IWL_OFDM_BASIC_RATES_MASK) - priv->staging39_rxon.ofdm_basic_rates = - ((priv->active_rate_basic & - (IWL_OFDM_BASIC_RATES_MASK | IWL_RATE_6M_MASK)) >> - IWL_FIRST_OFDM_RATE) & 0xFF; - else - priv->staging39_rxon.ofdm_basic_rates = - (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; -} - static void iwl3945_radio_kill_sw(struct iwl_priv *priv, int disable_radio) { unsigned long flags; @@ -1726,38 +1394,6 @@ static void iwl3945_radio_kill_sw(struct iwl_priv *priv, int disable_radio) return; } -void iwl3945_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb, - u32 decrypt_res, struct ieee80211_rx_status *stats) -{ - u16 fc = - le16_to_cpu(((struct ieee80211_hdr *)skb->data)->frame_control); - - if (priv->active39_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK) - return; - - if (!(fc & IEEE80211_FCTL_PROTECTED)) - return; - - IWL_DEBUG_RX("decrypt_res:0x%x\n", decrypt_res); - switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) { - case RX_RES_STATUS_SEC_TYPE_TKIP: - if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == - RX_RES_STATUS_BAD_ICV_MIC) - stats->flag |= RX_FLAG_MMIC_ERROR; - case RX_RES_STATUS_SEC_TYPE_WEP: - case RX_RES_STATUS_SEC_TYPE_CCMP: - if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == - RX_RES_STATUS_DECRYPT_OK) { - IWL_DEBUG_RX("hw decrypt successfully!!!\n"); - stats->flag |= RX_FLAG_DECRYPTED; - } - break; - - default: - break; - } -} - #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT #include "iwl-spectrum.h" @@ -1827,7 +1463,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, int spectrum_resp_status; int duration = le16_to_cpu(params->duration); - if (iwl3945_is_associated(priv)) + if (iwl_is_associated(priv)) add_time = iwl3945_usecs_to_beacons( le64_to_cpu(params->start_time) - priv->last_tsf, @@ -1842,7 +1478,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, cmd.len = sizeof(spectrum); spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len)); - if (iwl3945_is_associated(priv)) + if (iwl_is_associated(priv)) spectrum.start_time = iwl3945_add_beacon_time(priv->last_beacon_time, add_time, @@ -1853,7 +1489,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT); spectrum.channels[0].channel = params->channel; spectrum.channels[0].type = type; - if (priv->active39_rxon.flags & RXON_FLG_BAND_24G_MSK) + if (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK) spectrum.flags |= RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK; @@ -1951,19 +1587,6 @@ static void iwl3945_rx_reply_error(struct iwl_priv *priv, le32_to_cpu(pkt->u.err_resp.error_info)); } -#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x - -static void iwl3945_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = (void *)rxb->skb->data; - struct iwl3945_rxon_cmd *rxon = (void *)&priv->active39_rxon; - struct iwl_csa_notification *csa = &(pkt->u.csa_notif); - IWL_DEBUG_11H("CSA notif: channel %d, status %d\n", - le16_to_cpu(csa->channel), le32_to_cpu(csa->status)); - rxon->channel = csa->channel; - priv->staging39_rxon.channel = csa->channel; -} - static void iwl3945_rx_spectrum_measure_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { @@ -2224,7 +1847,7 @@ static void iwl3945_setup_rx_handlers(struct iwl_priv *priv) priv->rx_handlers[REPLY_ALIVE] = iwl3945_rx_reply_alive; priv->rx_handlers[REPLY_ADD_STA] = iwl3945_rx_reply_add_sta; priv->rx_handlers[REPLY_ERROR] = iwl3945_rx_reply_error; - priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl3945_rx_csa; + priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa; priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] = iwl3945_rx_spectrum_measure_notif; priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl3945_rx_pm_sleep_notif; @@ -2728,26 +2351,6 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) iwl3945_rx_queue_restock(priv); } -#ifdef CONFIG_IWLWIFI_DEBUG -static void iwl3945_print_rx_config_cmd(struct iwl_priv *priv, - struct iwl3945_rxon_cmd *rxon) -{ - IWL_DEBUG_RADIO("RX CONFIG:\n"); - iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon)); - IWL_DEBUG_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel)); - IWL_DEBUG_RADIO("u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags)); - IWL_DEBUG_RADIO("u32 filter_flags: 0x%08x\n", - le32_to_cpu(rxon->filter_flags)); - IWL_DEBUG_RADIO("u8 dev_type: 0x%x\n", rxon->dev_type); - IWL_DEBUG_RADIO("u8 ofdm_basic_rates: 0x%02x\n", - rxon->ofdm_basic_rates); - IWL_DEBUG_RADIO("u8 cck_basic_rates: 0x%02x\n", rxon->cck_basic_rates); - IWL_DEBUG_RADIO("u8[6] node_addr: %pM\n", rxon->node_addr); - IWL_DEBUG_RADIO("u8[6] bssid_addr: %pM\n", rxon->bssid_addr); - IWL_DEBUG_RADIO("u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id)); -} -#endif - static void iwl3945_enable_interrupts(struct iwl_priv *priv) { IWL_DEBUG_ISR("Enabling interrupts\n"); @@ -2957,58 +2560,19 @@ static void iwl3945_dump_nic_event_log(struct iwl_priv *priv) iwl_release_nic_access(priv); } -/** - * iwl3945_irq_handle_error - called for HW or SW error interrupt from card - */ -static void iwl3945_irq_handle_error(struct iwl_priv *priv) -{ - /* Set the FW error flag -- cleared on iwl3945_down */ - set_bit(STATUS_FW_ERROR, &priv->status); - - /* Cancel currently queued command. */ - clear_bit(STATUS_HCMD_ACTIVE, &priv->status); - -#ifdef CONFIG_IWLWIFI_DEBUG - if (priv->debug_level & IWL_DL_FW_ERRORS) { - iwl3945_dump_nic_error_log(priv); - iwl3945_dump_nic_event_log(priv); - iwl3945_print_rx_config_cmd(priv, &priv->staging39_rxon); - } -#endif - - wake_up_interruptible(&priv->wait_command_queue); - - /* Keep the restart process from trying to send host - * commands by clearing the INIT status bit */ - clear_bit(STATUS_READY, &priv->status); - - if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { - IWL_DEBUG(IWL_DL_INFO | IWL_DL_FW_ERRORS, - "Restarting adapter due to uCode error.\n"); - - if (iwl3945_is_associated(priv)) { - memcpy(&priv->recovery39_rxon, &priv->active39_rxon, - sizeof(priv->recovery39_rxon)); - priv->error_recovering = 1; - } - if (priv->cfg->mod_params->restart_fw) - queue_work(priv->workqueue, &priv->restart); - } -} - static void iwl3945_error_recovery(struct iwl_priv *priv) { unsigned long flags; - memcpy(&priv->staging39_rxon, &priv->recovery39_rxon, - sizeof(priv->staging39_rxon)); - priv->staging39_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + memcpy(&priv->staging_rxon, &priv->recovery_rxon, + sizeof(priv->staging_rxon)); + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl3945_commit_rxon(priv); iwl3945_add_station(priv, priv->bssid, 1, 0); spin_lock_irqsave(&priv->lock, flags); - priv->assoc_id = le16_to_cpu(priv->staging39_rxon.assoc_id); + priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id); priv->error_recovering = 0; spin_unlock_irqrestore(&priv->lock, flags); } @@ -3061,7 +2625,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) /* Tell the device to stop sending interrupts */ iwl3945_disable_interrupts(priv); - iwl3945_irq_handle_error(priv); + iwl_irq_handle_error(priv); handled |= CSR_INT_BIT_HW_ERR; @@ -3089,7 +2653,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) if (inta & CSR_INT_BIT_SW_ERR) { IWL_ERR(priv, "Microcode SW error detected. " "Restarting 0x%X.\n", inta); - iwl3945_irq_handle_error(priv); + iwl_irq_handle_error(priv); handled |= CSR_INT_BIT_SW_ERR; } @@ -3893,17 +3457,16 @@ static void iwl3945_alive_start(struct iwl_priv *priv) iwl3945_send_power_mode(priv, IWL_POWER_LEVEL(priv->power_mode)); - if (iwl3945_is_associated(priv)) { + if (iwl_is_associated(priv)) { struct iwl3945_rxon_cmd *active_rxon = - (struct iwl3945_rxon_cmd *)(&priv->active39_rxon); + (struct iwl3945_rxon_cmd *)(&priv->active_rxon); - memcpy(&priv->staging39_rxon, &priv->active39_rxon, - sizeof(priv->staging39_rxon)); + memcpy(&priv->staging_rxon, &priv->active_rxon, + sizeof(priv->staging_rxon)); active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; } else { /* Initialize our rx_config data */ - iwl3945_connection_init_rx_config(priv, priv->iw_mode); - memcpy(priv->staging39_rxon.node_addr, priv->mac_addr, ETH_ALEN); + iwl_connection_init_rx_config(priv, priv->iw_mode); } /* Configure Bluetooth device coexistence support */ @@ -4278,7 +3841,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; scan->quiet_time = IWL_ACTIVE_QUIET_TIME; - if (iwl3945_is_associated(priv)) { + if (iwl_is_associated(priv)) { u16 interval = 0; u32 extra; u32 suspend_time = 100; @@ -4449,7 +4012,7 @@ static void iwl3945_post_associate(struct iwl_priv *priv) IWL_DEBUG_ASSOC("Associated as %d to: %pM\n", - priv->assoc_id, priv->active39_rxon.bssid_addr); + priv->assoc_id, priv->active_rxon.bssid_addr); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -4461,7 +4024,7 @@ static void iwl3945_post_associate(struct iwl_priv *priv) conf = ieee80211_get_hw_conf(priv->hw); - priv->staging39_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl3945_commit_rxon(priv); memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); @@ -4472,26 +4035,26 @@ static void iwl3945_post_associate(struct iwl_priv *priv) IWL_WARN(priv, "REPLY_RXON_TIMING failed - " "Attempting to continue.\n"); - priv->staging39_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; + priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; - priv->staging39_rxon.assoc_id = cpu_to_le16(priv->assoc_id); + priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); IWL_DEBUG_ASSOC("assoc id %d beacon interval %d\n", priv->assoc_id, priv->beacon_int); if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - priv->staging39_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else - priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - if (priv->staging39_rxon.flags & RXON_FLG_BAND_24G_MSK) { + if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) - priv->staging39_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; + priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; else - priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; + priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; if (priv->iw_mode == NL80211_IFTYPE_ADHOC) - priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; + priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } @@ -4547,7 +4110,7 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) /* we should be verifying the device is ready to be opened */ mutex_lock(&priv->mutex); - memset(&priv->staging39_rxon, 0, sizeof(struct iwl3945_rxon_cmd)); + memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon)); /* fetch ucode file from disk, alloc and copy to bus-master buffers ... * ucode filename and max sizes are card-specific. */ @@ -4732,14 +4295,14 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed) goto out; } - iwl3945_set_rxon_channel(priv, conf->channel->band, conf->channel->hw_value); + iwl_set_rxon_channel(priv, conf->channel); - iwl3945_set_flags_for_phymode(priv, conf->channel->band); + iwl_set_flags_for_band(priv, conf->channel->band); /* The list of supported rates and rate mask can be different * for each phymode; since the phymode may have changed, reset * the rate mask to what mac80211 lists */ - iwl3945_set_rate(priv); + iwl_set_rate(priv); spin_unlock_irqrestore(&priv->lock, flags); @@ -4763,10 +4326,10 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed) goto out; } - iwl3945_set_rate(priv); + iwl_set_rate(priv); - if (memcmp(&priv->active39_rxon, - &priv->staging39_rxon, sizeof(priv->staging39_rxon))) + if (memcmp(&priv->active_rxon, + &priv->staging_rxon, sizeof(priv->staging_rxon))) iwl3945_commit_rxon(priv); else IWL_DEBUG_INFO("No re-sending same RXON configuration.\n"); @@ -4787,10 +4350,10 @@ static void iwl3945_config_ap(struct iwl_priv *priv) return; /* The following should be done only at AP bring up */ - if (!(iwl3945_is_associated(priv))) { + if (!(iwl_is_associated(priv))) { /* RXON - unassoc (to set timing command) */ - priv->staging39_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl3945_commit_rxon(priv); /* RXON Timing */ @@ -4804,29 +4367,29 @@ static void iwl3945_config_ap(struct iwl_priv *priv) "Attempting to continue.\n"); /* FIXME: what should be the assoc_id for AP? */ - priv->staging39_rxon.assoc_id = cpu_to_le16(priv->assoc_id); + priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - priv->staging39_rxon.flags |= + priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else - priv->staging39_rxon.flags &= + priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - if (priv->staging39_rxon.flags & RXON_FLG_BAND_24G_MSK) { + if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) - priv->staging39_rxon.flags |= + priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; else - priv->staging39_rxon.flags &= + priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; if (priv->iw_mode == NL80211_IFTYPE_ADHOC) - priv->staging39_rxon.flags &= + priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } /* restore RXON assoc */ - priv->staging39_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; + priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; iwl3945_commit_rxon(priv); iwl3945_add_station(priv, iwl_bcast_addr, 0, 0); } @@ -4907,7 +4470,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, mutex_unlock(&priv->mutex); return -EAGAIN; } - memcpy(priv->staging39_rxon.bssid_addr, conf->bssid, ETH_ALEN); + memcpy(priv->staging_rxon.bssid_addr, conf->bssid, ETH_ALEN); /* TODO: Audit driver for usage of these members and see * if mac80211 deprecates them (priv->bssid looks like it @@ -4921,12 +4484,12 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, rc = iwl3945_commit_rxon(priv); if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc) iwl3945_add_station(priv, - priv->active39_rxon.bssid_addr, 1, 0); + priv->active_rxon.bssid_addr, 1, 0); } } else { iwl_scan_cancel_timeout(priv, 100); - priv->staging39_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl3945_commit_rxon(priv); } @@ -4937,52 +4500,6 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, return 0; } -static void iwl3945_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - int mc_count, struct dev_addr_list *mc_list) -{ - struct iwl_priv *priv = hw->priv; - __le32 *filter_flags = &priv->staging39_rxon.filter_flags; - - IWL_DEBUG_MAC80211("Enter: changed: 0x%x, total: 0x%x\n", - changed_flags, *total_flags); - - if (changed_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) { - if (*total_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) - *filter_flags |= RXON_FILTER_PROMISC_MSK; - else - *filter_flags &= ~RXON_FILTER_PROMISC_MSK; - } - if (changed_flags & FIF_ALLMULTI) { - if (*total_flags & FIF_ALLMULTI) - *filter_flags |= RXON_FILTER_ACCEPT_GRP_MSK; - else - *filter_flags &= ~RXON_FILTER_ACCEPT_GRP_MSK; - } - if (changed_flags & FIF_CONTROL) { - if (*total_flags & FIF_CONTROL) - *filter_flags |= RXON_FILTER_CTL2HOST_MSK; - else - *filter_flags &= ~RXON_FILTER_CTL2HOST_MSK; - } - if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { - if (*total_flags & FIF_BCN_PRBRESP_PROMISC) - *filter_flags |= RXON_FILTER_BCON_AWARE_MSK; - else - *filter_flags &= ~RXON_FILTER_BCON_AWARE_MSK; - } - - /* We avoid iwl_commit_rxon here to commit the new filter flags - * since mac80211 will call ieee80211_hw_config immediately. - * (mc_list is not supported at this time). Otherwise, we need to - * queue a background iwl_commit_rxon work. - */ - - *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | - FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; -} - static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) { @@ -4994,7 +4511,7 @@ static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw, if (iwl_is_ready_rf(priv)) { iwl_scan_cancel_timeout(priv, 100); - priv->staging39_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl3945_commit_rxon(priv); } if (priv->vif == conf->vif) { @@ -5021,17 +4538,18 @@ static void iwl3945_bss_info_changed(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211("ERP_PREAMBLE %d\n", bss_conf->use_short_preamble); if (bss_conf->use_short_preamble) - priv->staging39_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else - priv->staging39_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + priv->staging_rxon.flags &= + ~RXON_FLG_SHORT_PREAMBLE_MSK; } if (changes & BSS_CHANGED_ERP_CTS_PROT) { IWL_DEBUG_MAC80211("ERP_CTS %d\n", bss_conf->use_cts_prot); if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) - priv->staging39_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; + priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; else - priv->staging39_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; + priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; } if (changes & BSS_CHANGED_ASSOC) { @@ -5055,7 +4573,7 @@ static void iwl3945_bss_info_changed(struct ieee80211_hw *hw, priv->assoc_id = 0; IWL_DEBUG_MAC80211("DISASSOC %d\n", bss_conf->assoc); } - } else if (changes && iwl3945_is_associated(priv) && priv->assoc_id) { + } else if (changes && iwl_is_associated(priv) && priv->assoc_id) { IWL_DEBUG_MAC80211("Associated Changes %d\n", changes); iwl3945_send_rxon_assoc(priv); } @@ -5148,7 +4666,7 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, case SET_KEY: ret = iwl3945_update_sta_key_info(priv, key, sta_id); if (!ret) { - iwl3945_set_rxon_hwcrypto(priv, 1); + iwl_set_rxon_hwcrypto(priv, 1); iwl3945_commit_rxon(priv); key->hw_key_idx = sta_id; IWL_DEBUG_MAC80211("set_key success, using hwcrypto\n"); @@ -5158,7 +4676,7 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, case DISABLE_KEY: ret = iwl3945_clear_sta_key_info(priv, sta_id); if (!ret) { - iwl3945_set_rxon_hwcrypto(priv, 0); + iwl_set_rxon_hwcrypto(priv, 0); iwl3945_commit_rxon(priv); IWL_DEBUG_MAC80211("disable hwcrypto key\n"); } @@ -5210,7 +4728,7 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, mutex_lock(&priv->mutex); if (priv->iw_mode == NL80211_IFTYPE_AP) iwl3945_activate_qos(priv, 1); - else if (priv->assoc_id && iwl3945_is_associated(priv)) + else if (priv->assoc_id && iwl_is_associated(priv)) iwl3945_activate_qos(priv, 0); mutex_unlock(&priv->mutex); @@ -5292,7 +4810,7 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) */ if (priv->iw_mode != NL80211_IFTYPE_AP) { iwl_scan_cancel_timeout(priv, 100); - priv->staging39_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl3945_commit_rxon(priv); } @@ -5304,7 +4822,7 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) return; } - iwl3945_set_rate(priv); + iwl_set_rate(priv); mutex_unlock(&priv->mutex); @@ -5437,7 +4955,7 @@ static ssize_t show_flags(struct device *d, { struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; - return sprintf(buf, "0x%04X\n", priv->active39_rxon.flags); + return sprintf(buf, "0x%04X\n", priv->active_rxon.flags); } static ssize_t store_flags(struct device *d, @@ -5448,14 +4966,14 @@ static ssize_t store_flags(struct device *d, u32 flags = simple_strtoul(buf, NULL, 0); mutex_lock(&priv->mutex); - if (le32_to_cpu(priv->staging39_rxon.flags) != flags) { + if (le32_to_cpu(priv->staging_rxon.flags) != flags) { /* Cancel any currently running scans... */ if (iwl_scan_cancel_timeout(priv, 100)) IWL_WARN(priv, "Could not cancel scan.\n"); else { IWL_DEBUG_INFO("Committing rxon.flags = 0x%04X\n", flags); - priv->staging39_rxon.flags = cpu_to_le32(flags); + priv->staging_rxon.flags = cpu_to_le32(flags); iwl3945_commit_rxon(priv); } } @@ -5472,7 +4990,7 @@ static ssize_t show_filter_flags(struct device *d, struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; return sprintf(buf, "0x%04X\n", - le32_to_cpu(priv->active39_rxon.filter_flags)); + le32_to_cpu(priv->active_rxon.filter_flags)); } static ssize_t store_filter_flags(struct device *d, @@ -5483,14 +5001,14 @@ static ssize_t store_filter_flags(struct device *d, u32 filter_flags = simple_strtoul(buf, NULL, 0); mutex_lock(&priv->mutex); - if (le32_to_cpu(priv->staging39_rxon.filter_flags) != filter_flags) { + if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) { /* Cancel any currently running scans... */ if (iwl_scan_cancel_timeout(priv, 100)) IWL_WARN(priv, "Could not cancel scan.\n"); else { IWL_DEBUG_INFO("Committing rxon.filter_flags = " "0x%04X\n", filter_flags); - priv->staging39_rxon.filter_flags = + priv->staging_rxon.filter_flags = cpu_to_le32(filter_flags); iwl3945_commit_rxon(priv); } @@ -5543,7 +5061,7 @@ static ssize_t store_measurement(struct device *d, { struct iwl_priv *priv = dev_get_drvdata(d); struct ieee80211_measurement_params params = { - .channel = le16_to_cpu(priv->active39_rxon.channel), + .channel = le16_to_cpu(priv->active_rxon.channel), .start_time = cpu_to_le64(priv->last_tsf), .duration = cpu_to_le16(1), }; @@ -5890,7 +5408,7 @@ static struct ieee80211_ops iwl3945_hw_ops = { .remove_interface = iwl3945_mac_remove_interface, .config = iwl3945_mac_config, .config_interface = iwl3945_mac_config_interface, - .configure_filter = iwl3945_configure_filter, + .configure_filter = iwl_configure_filter, .set_key = iwl3945_mac_set_key, .get_tx_stats = iwl3945_mac_get_tx_stats, .conf_tx = iwl3945_mac_conf_tx, @@ -6163,7 +5681,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e goto out_release_irq; } - iwl3945_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6); + iwl_set_rxon_channel(priv, + &priv->bands[IEEE80211_BAND_2GHZ].channels[5]); iwl3945_setup_deferred_work(priv); iwl3945_setup_rx_handlers(priv); -- GitLab From 7530f85f086a5d58a5e43b1a98993801fe509c51 Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Tue, 27 Jan 2009 14:27:53 -0800 Subject: [PATCH 1454/4982] iwlwifi: suppress unused variable warning when compiling w/o IWLWIFI_DEBUG This patch adds __maybe_unused attribute to priv variables used in functions that used it solely for debug printouts Signed-off-by: Tomas Winkler Cc: Helmut Schaa Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 10 +++++----- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index b93f5ba7719..45ce3ff653a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -183,7 +183,7 @@ static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta) int unflushed = 0; int i; unsigned long flags; - struct iwl_priv *priv = rs_sta->priv; + struct iwl_priv *priv __maybe_unused = rs_sta->priv; /* * For each rate, if we have collected data on that rate @@ -216,7 +216,7 @@ static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta) static void iwl3945_bg_rate_scale_flush(unsigned long data) { struct iwl3945_rs_sta *rs_sta = (void *)data; - struct iwl_priv *priv = rs_sta->priv; + struct iwl_priv *priv __maybe_unused = rs_sta->priv; int unflushed = 0; unsigned long flags; u32 packet_count, duration, pps; @@ -290,7 +290,7 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, { unsigned long flags; s32 fail_count; - struct iwl_priv *priv = rs_sta->priv; + struct iwl_priv *priv __maybe_unused = rs_sta->priv; if (!retries) { IWL_DEBUG_RATE("leave: retries == 0 -- should be at least 1\n"); @@ -438,7 +438,7 @@ static void rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta, { struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; struct iwl3945_rs_sta *rs_sta = priv_sta; - struct iwl_priv *priv = rs_sta->priv; + struct iwl_priv *priv __maybe_unused = rs_sta->priv; psta->rs_sta = NULL; @@ -556,7 +556,7 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, { u8 high = IWL_RATE_INVALID; u8 low = IWL_RATE_INVALID; - struct iwl_priv *priv = rs_sta->priv; + struct iwl_priv *priv __maybe_unused = rs_sta->priv; /* 802.11A walks to the next literal adjacent rate in * the rate table */ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 6a2c8a3a3d5..72ff20e10aa 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -5270,8 +5270,8 @@ static ssize_t store_antenna(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { + struct iwl_priv *priv __maybe_unused = dev_get_drvdata(d); int ant; - struct iwl_priv *priv = dev_get_drvdata(d); if (count == 0) return 0; -- GitLab From dfb39e82957153c5748675b72bbe7eded2e2b069 Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Tue, 27 Jan 2009 14:27:54 -0800 Subject: [PATCH 1455/4982] iwlwifi: iwl3945_send_tx_power must be static iwl3945_send_tx_power must be static Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 610ee17c840..b4b186db0fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1690,7 +1690,7 @@ static void iwl3945_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_in * Configures power settings for all rates for the current channel, * using values from channel info struct, and send to NIC */ -int iwl3945_send_tx_power(struct iwl_priv *priv) +static int iwl3945_send_tx_power(struct iwl_priv *priv) { int rate_idx, i; const struct iwl_channel_info *ch_info = NULL; -- GitLab From 450154e4f471248e188d18e45c2409b37a133765 Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Tue, 27 Jan 2009 14:27:55 -0800 Subject: [PATCH 1456/4982] iwlwifi: check return value of pci_enable_device pci_enable_device is tagged with __must_check therefore don't ignore the return value in pci_resume handlers Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 5 ++++- drivers/net/wireless/iwlwifi/iwl3945-base.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c54a9bcbb2e..ad6403395e4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3767,9 +3767,12 @@ static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) static int iwl_pci_resume(struct pci_dev *pdev) { struct iwl_priv *priv = pci_get_drvdata(pdev); + int ret; pci_set_power_state(pdev, PCI_D0); - pci_enable_device(pdev); + ret = pci_enable_device(pdev); + if (ret) + return ret; pci_restore_state(pdev); iwl_enable_interrupts(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 72ff20e10aa..346a3018d8a 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -5824,9 +5824,12 @@ static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state) static int iwl3945_pci_resume(struct pci_dev *pdev) { struct iwl_priv *priv = pci_get_drvdata(pdev); + int ret; pci_set_power_state(pdev, PCI_D0); - pci_enable_device(pdev); + ret = pci_enable_device(pdev); + if (ret) + return ret; pci_restore_state(pdev); if (priv->is_open) -- GitLab From e1623446bb1de1834ff1c57b3e8ed341d5d4a927 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 27 Jan 2009 14:27:56 -0800 Subject: [PATCH 1457/4982] iwlwifi: don't use implicit priv in IWL_DEBUG Call IWL_DEBUG macro with explicit priv argument. Signed-off-by: Tomas Winkler Acked-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-led.c | 6 +- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 74 ++-- drivers/net/wireless/iwlwifi/iwl-3945.c | 109 +++-- drivers/net/wireless/iwlwifi/iwl-4965.c | 126 +++--- drivers/net/wireless/iwlwifi/iwl-5000.c | 54 +-- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 104 ++--- drivers/net/wireless/iwlwifi/iwl-agn.c | 281 +++++++------ drivers/net/wireless/iwlwifi/iwl-calib.c | 74 ++-- drivers/net/wireless/iwlwifi/iwl-core.c | 72 ++-- drivers/net/wireless/iwlwifi/iwl-debug.h | 103 ++--- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 14 +- drivers/net/wireless/iwlwifi/iwl-hcmd.c | 8 +- drivers/net/wireless/iwlwifi/iwl-io.h | 20 +- drivers/net/wireless/iwlwifi/iwl-led.c | 14 +- drivers/net/wireless/iwlwifi/iwl-power.c | 18 +- drivers/net/wireless/iwlwifi/iwl-rfkill.c | 8 +- drivers/net/wireless/iwlwifi/iwl-rx.c | 28 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 62 +-- drivers/net/wireless/iwlwifi/iwl-spectrum.c | 8 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 36 +- drivers/net/wireless/iwlwifi/iwl-tx.c | 52 +-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 427 ++++++++++---------- 22 files changed, 859 insertions(+), 839 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index fab13736500..2e507e912da 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -137,7 +137,7 @@ static int iwl3945_led_off(struct iwl_priv *priv, int led_id) .off = 0, .interval = IWL_DEF_LED_INTRVL }; - IWL_DEBUG_LED("led off %d\n", led_id); + IWL_DEBUG_LED(priv, "led off %d\n", led_id); return iwl_send_led_cmd(priv, &led_cmd); } @@ -174,7 +174,7 @@ static void iwl3945_led_brightness_set(struct led_classdev *led_cdev, case LED_FULL: if (led->type == IWL_LED_TRG_ASSOC) { priv->allow_blinking = 1; - IWL_DEBUG_LED("MAC is associated\n"); + IWL_DEBUG_LED(priv, "MAC is associated\n"); } if (led->led_on) led->led_on(priv, IWL_LED_LINK); @@ -182,7 +182,7 @@ static void iwl3945_led_brightness_set(struct led_classdev *led_cdev, case LED_OFF: if (led->type == IWL_LED_TRG_ASSOC) { priv->allow_blinking = 0; - IWL_DEBUG_LED("MAC is disassociated\n"); + IWL_DEBUG_LED(priv, "MAC is disassociated\n"); } if (led->led_off) led->led_off(priv, IWL_LED_LINK); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 45ce3ff653a..7db8198c625 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -197,7 +197,7 @@ static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta) spin_lock_irqsave(&rs_sta->lock, flags); if (time_after(jiffies, rs_sta->win[i].stamp + IWL_RATE_WIN_FLUSH)) { - IWL_DEBUG_RATE("flushing %d samples of rate " + IWL_DEBUG_RATE(priv, "flushing %d samples of rate " "index %d\n", rs_sta->win[i].counter, i); iwl3945_clear_window(&rs_sta->win[i]); @@ -221,7 +221,7 @@ static void iwl3945_bg_rate_scale_flush(unsigned long data) unsigned long flags; u32 packet_count, duration, pps; - IWL_DEBUG_RATE("enter\n"); + IWL_DEBUG_RATE(priv, "enter\n"); unflushed = iwl3945_rate_scale_flush_windows(rs_sta); @@ -236,7 +236,7 @@ static void iwl3945_bg_rate_scale_flush(unsigned long data) duration = jiffies_to_msecs(jiffies - rs_sta->last_partial_flush); - IWL_DEBUG_RATE("Tx'd %d packets in %dms\n", + IWL_DEBUG_RATE(priv, "Tx'd %d packets in %dms\n", packet_count, duration); /* Determine packets per second */ @@ -256,7 +256,7 @@ static void iwl3945_bg_rate_scale_flush(unsigned long data) rs_sta->flush_time = msecs_to_jiffies(duration); - IWL_DEBUG_RATE("new flush period: %d msec ave %d\n", + IWL_DEBUG_RATE(priv, "new flush period: %d msec ave %d\n", duration, packet_count); mod_timer(&rs_sta->rate_scale_flush, jiffies + @@ -274,7 +274,7 @@ static void iwl3945_bg_rate_scale_flush(unsigned long data) spin_unlock_irqrestore(&rs_sta->lock, flags); - IWL_DEBUG_RATE("leave\n"); + IWL_DEBUG_RATE(priv, "leave\n"); } /** @@ -293,7 +293,7 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, struct iwl_priv *priv __maybe_unused = rs_sta->priv; if (!retries) { - IWL_DEBUG_RATE("leave: retries == 0 -- should be at least 1\n"); + IWL_DEBUG_RATE(priv, "leave: retries == 0 -- should be at least 1\n"); return; } @@ -347,7 +347,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, struct iwl_priv *priv = (struct iwl_priv *)priv_r; int i; - IWL_DEBUG_RATE("enter\n"); + IWL_DEBUG_RATE(priv, "enter\n"); /* TODO: what is a good starting rate for STA? About middle? Maybe not * the lowest or the highest rate.. Could consider using RSSI from @@ -370,7 +370,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, } - IWL_DEBUG_RATE("leave\n"); + IWL_DEBUG_RATE(priv, "leave\n"); } static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) @@ -396,11 +396,11 @@ static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp) * as well just put all the information there. */ - IWL_DEBUG_RATE("enter\n"); + IWL_DEBUG_RATE(priv, "enter\n"); rs_sta = kzalloc(sizeof(struct iwl3945_rs_sta), gfp); if (!rs_sta) { - IWL_DEBUG_RATE("leave: ENOMEM\n"); + IWL_DEBUG_RATE(priv, "leave: ENOMEM\n"); return NULL; } @@ -428,7 +428,7 @@ static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp) for (i = 0; i < IWL_RATE_COUNT_3945; i++) iwl3945_clear_window(&rs_sta->win[i]); - IWL_DEBUG_RATE("leave\n"); + IWL_DEBUG_RATE(priv, "leave\n"); return rs_sta; } @@ -442,10 +442,10 @@ static void rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta, psta->rs_sta = NULL; - IWL_DEBUG_RATE("enter\n"); + IWL_DEBUG_RATE(priv, "enter\n"); del_timer_sync(&rs_sta->rate_scale_flush); kfree(rs_sta); - IWL_DEBUG_RATE("leave\n"); + IWL_DEBUG_RATE(priv, "leave\n"); } @@ -466,18 +466,18 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband struct iwl3945_rs_sta *rs_sta = priv_sta; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - IWL_DEBUG_RATE("enter\n"); + IWL_DEBUG_RATE(priv, "enter\n"); retries = info->status.rates[0].count; first_index = sband->bitrates[info->status.rates[0].idx].hw_value; if ((first_index < 0) || (first_index >= IWL_RATE_COUNT_3945)) { - IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index); + IWL_DEBUG_RATE(priv, "leave: Rate out of bounds: %d\n", first_index); return; } if (!priv_sta) { - IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); + IWL_DEBUG_RATE(priv, "leave: No STA priv data to update!\n"); return; } @@ -511,7 +511,7 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband iwl3945_collect_tx_data(rs_sta, &rs_sta->win[scale_rate_index], 0, current_count, scale_rate_index); - IWL_DEBUG_RATE("Update rate %d for %d retries.\n", + IWL_DEBUG_RATE(priv, "Update rate %d for %d retries.\n", scale_rate_index, current_count); retries -= current_count; @@ -521,7 +521,7 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband /* Update the last index window with success/failure based on ACK */ - IWL_DEBUG_RATE("Update rate %d with %s.\n", + IWL_DEBUG_RATE(priv, "Update rate %d with %s.\n", last_index, (info->flags & IEEE80211_TX_STAT_ACK) ? "success" : "failure"); @@ -546,7 +546,7 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband spin_unlock_irqrestore(&rs_sta->lock, flags); - IWL_DEBUG_RATE("leave\n"); + IWL_DEBUG_RATE(priv, "leave\n"); return; } @@ -596,7 +596,7 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, break; if (rate_mask & (1 << low)) break; - IWL_DEBUG_RATE("Skipping masked lower rate: %d\n", low); + IWL_DEBUG_RATE(priv, "Skipping masked lower rate: %d\n", low); } high = index; @@ -609,7 +609,7 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, break; if (rate_mask & (1 << high)) break; - IWL_DEBUG_RATE("Skipping masked higher rate: %d\n", high); + IWL_DEBUG_RATE(priv, "Skipping masked higher rate: %d\n", high); } return (high << 8) | low; @@ -655,7 +655,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, struct iwl_priv *priv = (struct iwl_priv *)priv_r; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - IWL_DEBUG_RATE("enter\n"); + IWL_DEBUG_RATE(priv, "enter\n"); if (sta) rate_mask = sta->supp_rates[sband->band]; @@ -666,7 +666,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || is_multicast_ether_addr(hdr->addr1) || !sta || !priv_sta) { - IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); + IWL_DEBUG_RATE(priv, "leave: No STA priv data to update!\n"); if (!rate_mask) info->control.rates[0].idx = rate_lowest_index(sband, NULL); @@ -693,7 +693,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, u8 sta_id = iwl3945_hw_find_station(priv, hdr->addr1); if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_RATE("LQ: ADD station %pm\n", + IWL_DEBUG_RATE(priv, "LQ: ADD station %pm\n", hdr->addr1); sta_id = iwl3945_add_station(priv, hdr->addr1, 0, CMD_ASYNC); @@ -728,7 +728,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) { spin_unlock_irqrestore(&rs_sta->lock, flags); - IWL_DEBUG_RATE("Invalid average_tpt on rate %d: " + IWL_DEBUG_RATE(priv, "Invalid average_tpt on rate %d: " "counter: %d, success_counter: %d, " "expected_tpt is %sNULL\n", index, @@ -761,7 +761,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, scale_action = 1; if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) { - IWL_DEBUG_RATE("decrease rate because of low success_ratio\n"); + IWL_DEBUG_RATE(priv, "decrease rate because of low success_ratio\n"); scale_action = -1; } else if ((low_tpt == IWL_INVALID_VALUE) && (high_tpt == IWL_INVALID_VALUE)) @@ -769,7 +769,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, else if ((low_tpt != IWL_INVALID_VALUE) && (high_tpt != IWL_INVALID_VALUE) && (low_tpt < current_tpt) && (high_tpt < current_tpt)) { - IWL_DEBUG_RATE("No action -- low [%d] & high [%d] < " + IWL_DEBUG_RATE(priv, "No action -- low [%d] & high [%d] < " "current_tpt [%d]\n", low_tpt, high_tpt, current_tpt); scale_action = 0; @@ -778,14 +778,14 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, if (high_tpt > current_tpt) scale_action = 1; else { - IWL_DEBUG_RATE - ("decrease rate because of high tpt\n"); + IWL_DEBUG_RATE(priv, + "decrease rate because of high tpt\n"); scale_action = -1; } } else if (low_tpt != IWL_INVALID_VALUE) { if (low_tpt > current_tpt) { - IWL_DEBUG_RATE - ("decrease rate because of low tpt\n"); + IWL_DEBUG_RATE(priv, + "decrease rate because of low tpt\n"); scale_action = -1; } else scale_action = 1; @@ -797,7 +797,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, scale_action = 0; } else if (scale_action == 1) { if (window->success_ratio < IWL_SUCCESS_UP_TH) { - IWL_DEBUG_RATE("No action -- success_ratio [%d] < " + IWL_DEBUG_RATE(priv, "No action -- success_ratio [%d] < " "SUCCESS UP\n", window->success_ratio); scale_action = 0; } @@ -820,7 +820,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, break; } - IWL_DEBUG_RATE("Selected %d (action %d) - low %d high %d\n", + IWL_DEBUG_RATE(priv, "Selected %d (action %d) - low %d high %d\n", index, scale_action, low, high); out: @@ -832,7 +832,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, else info->control.rates[0].idx = rs_sta->last_txrate_idx; - IWL_DEBUG_RATE("leave: %d\n", index); + IWL_DEBUG_RATE(priv, "leave: %d\n", index); } #ifdef CONFIG_MAC80211_DEBUGFS @@ -915,7 +915,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) struct ieee80211_sta *sta; struct iwl3945_sta_priv *psta; - IWL_DEBUG_RATE("enter\n"); + IWL_DEBUG_RATE(priv, "enter\n"); rcu_read_lock(); @@ -955,11 +955,11 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) if (rssi == 0) rssi = IWL_MIN_RSSI_VAL; - IWL_DEBUG(IWL_DL_INFO | IWL_DL_RATE, "Network RSSI: %d\n", rssi); + IWL_DEBUG_RATE(priv, "Network RSSI: %d\n", rssi); rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band); - IWL_DEBUG_RATE("leave: rssi %d assign rate index: " + IWL_DEBUG_RATE(priv, "leave: rssi %d assign rate index: " "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate, iwl3945_rates[rs_sta->start_rate].plcp); rcu_read_unlock(); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index b4b186db0fd..8ff5798ad64 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -170,7 +170,7 @@ void iwl3945_disable_events(struct iwl_priv *priv) iwl_release_nic_access(priv); if (IWL_EVT_DISABLE && (array_size == IWL_EVT_DISABLE_SIZE)) { - IWL_DEBUG_INFO("Disabling selected uCode log events at 0x%x\n", + IWL_DEBUG_INFO(priv, "Disabling selected uCode log events at 0x%x\n", disable_ptr); ret = iwl_grab_nic_access(priv); for (i = 0; i < IWL_EVT_DISABLE_SIZE; i++) @@ -180,9 +180,9 @@ void iwl3945_disable_events(struct iwl_priv *priv) iwl_release_nic_access(priv); } else { - IWL_DEBUG_INFO("Selected uCode log events may be disabled\n"); - IWL_DEBUG_INFO(" by writing \"1\"s into disable bitmap\n"); - IWL_DEBUG_INFO(" in SRAM at 0x%x, size %d u32s\n", + IWL_DEBUG_INFO(priv, "Selected uCode log events may be disabled\n"); + IWL_DEBUG_INFO(priv, " by writing \"1\"s into disable bitmap\n"); + IWL_DEBUG_INFO(priv, " in SRAM at 0x%x, size %d u32s\n", disable_ptr, array_size); } @@ -338,11 +338,11 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv, info->flags |= ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ? IEEE80211_TX_STAT_ACK : 0; - IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n", + IWL_DEBUG_TX(priv, "Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n", txq_id, iwl3945_get_tx_fail_reason(status), status, tx_resp->rate, tx_resp->failure_frame); - IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index); + IWL_DEBUG_TX_REPLY(priv, "Tx queue reclaim %d\n", index); iwl3945_tx_queue_reclaim(priv, txq_id, index); if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) @@ -362,7 +362,7 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv, void iwl3945_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; - IWL_DEBUG_RX("Statistics notification received (%d vs %d).\n", + IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", (int)sizeof(struct iwl3945_notif_statistics), le32_to_cpu(pkt->len)); @@ -496,13 +496,13 @@ static void _iwl3945_dbg_report_frame(struct iwl_priv *priv, * MAC addresses show just the last byte (for brevity), * but you can hack it to show more, if you'd like to. */ if (dataframe) - IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, " + IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " "len=%u, rssi=%d, chnl=%d, rate=%d, \n", title, le16_to_cpu(fc), header->addr1[5], length, rssi, channel, rate); else { /* src/dst addresses assume managed mode */ - IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, " + IWL_DEBUG_RX(priv, "%s: 0x%04x, dst=0x%02x, " "src=0x%02x, rssi=%u, tim=%lu usec, " "phy=0x%02x, chnl=%d\n", title, le16_to_cpu(fc), header->addr1[5], @@ -563,14 +563,14 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, /* We received data from the HW, so stop the watchdog */ if (unlikely((len + IWL39_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) { - IWL_DEBUG_DROP("Corruption detected!\n"); + IWL_DEBUG_DROP(priv, "Corruption detected!\n"); return; } /* We only process data packets if the interface is open */ if (unlikely(!priv->is_open)) { - IWL_DEBUG_DROP_LIMIT - ("Dropping packet while interface is not open.\n"); + IWL_DEBUG_DROP_LIMIT(priv, + "Dropping packet while interface is not open.\n"); return; } @@ -626,15 +626,14 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, rx_status.flag |= RX_FLAG_SHORTPRE; if ((unlikely(rx_stats->phy_count > 20))) { - IWL_DEBUG_DROP - ("dsp size out of range [0,20]: " - "%d/n", rx_stats->phy_count); + IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", + rx_stats->phy_count); return; } if (!(rx_end->status & RX_RES_STATUS_NO_CRC32_ERROR) || !(rx_end->status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { - IWL_DEBUG_RX("Bad CRC or FIFO: 0x%08X.\n", rx_end->status); + IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", rx_end->status); return; } @@ -673,7 +672,7 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, } - IWL_DEBUG_STATS("Rssi %d noise %d qual %d sig_avg %d noise_diff %d\n", + IWL_DEBUG_STATS(priv, "Rssi %d noise %d qual %d sig_avg %d noise_diff %d\n", rx_status.signal, rx_status.noise, rx_status.qual, rx_stats_sig_avg, rx_stats_noise_diff); @@ -681,7 +680,7 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, network_packet = iwl3945_is_network_packet(priv, header); - IWL_DEBUG_STATS_LIMIT("[%c] %d RSSI:%d Signal:%u, Noise:%u, Rate:%u\n", + IWL_DEBUG_STATS_LIMIT(priv, "[%c] %d RSSI:%d Signal:%u, Noise:%u, Rate:%u\n", network_packet ? '*' : ' ', le16_to_cpu(rx_hdr->channel), rx_status.signal, rx_status.signal, @@ -799,7 +798,7 @@ u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *addr) goto out; } - IWL_DEBUG_INFO("can not find STA %pM (total %d)\n", + IWL_DEBUG_INFO(priv, "can not find STA %pM (total %d)\n", addr, priv->num_stations); out: spin_unlock_irqrestore(&priv->sta_lock, flags); @@ -874,7 +873,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, struct iwl_cmd *cmd, /* CCK */ tx->supp_rates[1] = (rate_mask & 0xF); - IWL_DEBUG_RATE("Tx sta id: %d, rate: %d (plcp), flags: 0x%4X " + IWL_DEBUG_RATE(priv, "Tx sta id: %d, rate: %d (plcp), flags: 0x%4X " "cck/ofdm mask: 0x%x/0x%x\n", sta_id, tx->rate, le32_to_cpu(tx->tx_flags), tx->supp_rates[1], tx->supp_rates[0]); @@ -899,7 +898,7 @@ u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags) iwl_send_add_sta(priv, (struct iwl_addsta_cmd *)&station->sta, flags); - IWL_DEBUG_RATE("SCALE sync station %d to rate %d\n", + IWL_DEBUG_RATE(priv, "SCALE sync station %d to rate %d\n", sta_id, tx_rate); return sta_id; } @@ -1080,7 +1079,7 @@ static int iwl3945_apm_init(struct iwl_priv *priv) iwl_poll_direct_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); if (ret < 0) { - IWL_DEBUG_INFO("Failed to init the card\n"); + IWL_DEBUG_INFO(priv, "Failed to init the card\n"); goto out; } @@ -1112,31 +1111,31 @@ static void iwl3945_nic_config(struct iwl_priv *priv) spin_lock_irqsave(&priv->lock, flags); if (rev_id & PCI_CFG_REV_ID_BIT_RTP) - IWL_DEBUG_INFO("RTP type \n"); + IWL_DEBUG_INFO(priv, "RTP type \n"); else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) { - IWL_DEBUG_INFO("3945 RADIO-MB type\n"); + IWL_DEBUG_INFO(priv, "3945 RADIO-MB type\n"); iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BIT_3945_MB); } else { - IWL_DEBUG_INFO("3945 RADIO-MM type\n"); + IWL_DEBUG_INFO(priv, "3945 RADIO-MM type\n"); iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BIT_3945_MM); } if (EEPROM_SKU_CAP_OP_MODE_MRC == eeprom->sku_cap) { - IWL_DEBUG_INFO("SKU OP mode is mrc\n"); + IWL_DEBUG_INFO(priv, "SKU OP mode is mrc\n"); iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC); } else - IWL_DEBUG_INFO("SKU OP mode is basic\n"); + IWL_DEBUG_INFO(priv, "SKU OP mode is basic\n"); if ((eeprom->board_revision & 0xF0) == 0xD0) { - IWL_DEBUG_INFO("3945ABG revision is 0x%X\n", + IWL_DEBUG_INFO(priv, "3945ABG revision is 0x%X\n", eeprom->board_revision); iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE); } else { - IWL_DEBUG_INFO("3945ABG revision is 0x%X\n", + IWL_DEBUG_INFO(priv, "3945ABG revision is 0x%X\n", eeprom->board_revision); iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE); @@ -1145,10 +1144,10 @@ static void iwl3945_nic_config(struct iwl_priv *priv) if (eeprom->almgor_m_version <= 1) { iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A); - IWL_DEBUG_INFO("Card M type A version is 0x%X\n", + IWL_DEBUG_INFO(priv, "Card M type A version is 0x%X\n", eeprom->almgor_m_version); } else { - IWL_DEBUG_INFO("Card M type B version is 0x%X\n", + IWL_DEBUG_INFO(priv, "Card M type B version is 0x%X\n", eeprom->almgor_m_version); iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B); @@ -1156,10 +1155,10 @@ static void iwl3945_nic_config(struct iwl_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); if (eeprom->sku_cap & EEPROM_SKU_CAP_SW_RF_KILL_ENABLE) - IWL_DEBUG_RF_KILL("SW RF KILL supported in EEPROM.\n"); + IWL_DEBUG_RF_KILL(priv, "SW RF KILL supported in EEPROM.\n"); if (eeprom->sku_cap & EEPROM_SKU_CAP_HW_RF_KILL_ENABLE) - IWL_DEBUG_RF_KILL("HW RF KILL supported in EEPROM.\n"); + IWL_DEBUG_RF_KILL(priv, "HW RF KILL supported in EEPROM.\n"); } int iwl3945_hw_nic_init(struct iwl_priv *priv) @@ -1177,7 +1176,7 @@ int iwl3945_hw_nic_init(struct iwl_priv *priv) rc = pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id); if (rc) return rc; - IWL_DEBUG_INFO("HW Revision ID = 0x%X\n", rev_id); + IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id); rc = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); if(rc) @@ -1286,7 +1285,7 @@ static int iwl3945_apm_stop_master(struct iwl_priv *priv) out: spin_unlock_irqrestore(&priv->lock, flags); - IWL_DEBUG_INFO("stop master\n"); + IWL_DEBUG_INFO(priv, "stop master\n"); return ret; } @@ -1391,7 +1390,7 @@ static int iwl3945_hw_reg_txpower_get_temperature(struct iwl_priv *priv) /* driver's okay range is -260 to +25. * human readable okay range is 0 to +285 */ - IWL_DEBUG_INFO("Temperature: %d\n", temperature + IWL_TEMP_CONVERT); + IWL_DEBUG_INFO(priv, "Temperature: %d\n", temperature + IWL_TEMP_CONVERT); /* handle insane temp reading */ if (iwl3945_hw_reg_temp_out_of_range(temperature)) { @@ -1428,20 +1427,20 @@ static int is_temp_calib_needed(struct iwl_priv *priv) /* get absolute value */ if (temp_diff < 0) { - IWL_DEBUG_POWER("Getting cooler, delta %d,\n", temp_diff); + IWL_DEBUG_POWER(priv, "Getting cooler, delta %d,\n", temp_diff); temp_diff = -temp_diff; } else if (temp_diff == 0) - IWL_DEBUG_POWER("Same temp,\n"); + IWL_DEBUG_POWER(priv, "Same temp,\n"); else - IWL_DEBUG_POWER("Getting warmer, delta %d,\n", temp_diff); + IWL_DEBUG_POWER(priv, "Getting warmer, delta %d,\n", temp_diff); /* if we don't need calibration, *don't* update last_temperature */ if (temp_diff < IWL_TEMPERATURE_LIMIT_TIMER) { - IWL_DEBUG_POWER("Timed thermal calib not needed\n"); + IWL_DEBUG_POWER(priv, "Timed thermal calib not needed\n"); return 0; } - IWL_DEBUG_POWER("Timed thermal calib needed\n"); + IWL_DEBUG_POWER(priv, "Timed thermal calib needed\n"); /* assume that caller will actually do calib ... * update the "last temperature" value */ @@ -1710,7 +1709,7 @@ static int iwl3945_send_tx_power(struct iwl_priv *priv) } if (!is_channel_valid(ch_info)) { - IWL_DEBUG_POWER("Not calling TX_PWR_TABLE_CMD on " + IWL_DEBUG_POWER(priv, "Not calling TX_PWR_TABLE_CMD on " "non-Tx channel.\n"); return 0; } @@ -1723,7 +1722,7 @@ static int iwl3945_send_tx_power(struct iwl_priv *priv) txpower.power[i].tpc = ch_info->power_info[i].tpc; txpower.power[i].rate = iwl3945_rates[rate_idx].plcp; - IWL_DEBUG_POWER("ch %d:%d rf %d dsp %3d rate code 0x%02x\n", + IWL_DEBUG_POWER(priv, "ch %d:%d rf %d dsp %3d rate code 0x%02x\n", le16_to_cpu(txpower.channel), txpower.band, txpower.power[i].tpc.tx_gain, @@ -1736,7 +1735,7 @@ static int iwl3945_send_tx_power(struct iwl_priv *priv) txpower.power[i].tpc = ch_info->power_info[i].tpc; txpower.power[i].rate = iwl3945_rates[rate_idx].plcp; - IWL_DEBUG_POWER("ch %d:%d rf %d dsp %3d rate code 0x%02x\n", + IWL_DEBUG_POWER(priv, "ch %d:%d rf %d dsp %3d rate code 0x%02x\n", le16_to_cpu(txpower.channel), txpower.band, txpower.power[i].tpc.tx_gain, @@ -1927,12 +1926,12 @@ int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power) u8 i; if (priv->tx_power_user_lmt == power) { - IWL_DEBUG_POWER("Requested Tx power same as current " + IWL_DEBUG_POWER(priv, "Requested Tx power same as current " "limit: %ddBm.\n", power); return 0; } - IWL_DEBUG_POWER("Setting upper limit clamp to %ddBm.\n", power); + IWL_DEBUG_POWER(priv, "Setting upper limit clamp to %ddBm.\n", power); priv->tx_power_user_lmt = power; /* set up new Tx powers for each and every channel, 2.4 and 5.x */ @@ -2042,7 +2041,7 @@ static u16 iwl3945_hw_reg_get_ch_grp_index(struct iwl_priv *priv, } else group_index = 0; /* 2.4 GHz, group 0 */ - IWL_DEBUG_POWER("Chnl %d mapped to grp %d\n", ch_info->channel, + IWL_DEBUG_POWER(priv, "Chnl %d mapped to grp %d\n", ch_info->channel, group_index); return group_index; } @@ -2109,7 +2108,7 @@ static void iwl3945_hw_reg_init_channel_groups(struct iwl_priv *priv) struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; const struct iwl3945_eeprom_txpower_group *group; - IWL_DEBUG_POWER("Initializing factory calib info from EEPROM\n"); + IWL_DEBUG_POWER(priv, "Initializing factory calib info from EEPROM\n"); for (i = 0; i < IWL_NUM_TX_CALIB_GROUPS; i++) { s8 *clip_pwrs; /* table of power levels for each rate */ @@ -2225,7 +2224,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv) eeprom->groups[ch_info->group_index]. temperature); - IWL_DEBUG_POWER("Delta index for channel %d: %d [%d]\n", + IWL_DEBUG_POWER(priv, "Delta index for channel %d: %d [%d]\n", ch_info->channel, delta_index, temperature + IWL_TEMP_CONVERT); @@ -2410,7 +2409,7 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv) switch (priv->band) { case IEEE80211_BAND_5GHZ: - IWL_DEBUG_RATE("Select A mode rate scale\n"); + IWL_DEBUG_RATE(priv, "Select A mode rate scale\n"); /* If one of the following CCK rates is used, * have it fall back to the 6M OFDM rate */ for (i = IWL_RATE_1M_INDEX_TABLE; @@ -2428,7 +2427,7 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv) break; case IEEE80211_BAND_2GHZ: - IWL_DEBUG_RATE("Select B/G mode rate scale\n"); + IWL_DEBUG_RATE(priv, "Select B/G mode rate scale\n"); /* If an OFDM rate is used, have it fall back to the * 1M CCK rates */ @@ -2553,7 +2552,7 @@ static int iwl3945_verify_bsm(struct iwl_priv *priv) u32 reg; u32 val; - IWL_DEBUG_INFO("Begin verify bsm\n"); + IWL_DEBUG_INFO(priv, "Begin verify bsm\n"); /* verify BSM SRAM contents */ val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG); @@ -2571,7 +2570,7 @@ static int iwl3945_verify_bsm(struct iwl_priv *priv) } } - IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n"); + IWL_DEBUG_INFO(priv, "BSM bootstrap uCode image OK\n"); return 0; } @@ -2648,7 +2647,7 @@ static int iwl3945_load_bsm(struct iwl_priv *priv) u32 done; u32 reg_offset; - IWL_DEBUG_INFO("Begin load bsm\n"); + IWL_DEBUG_INFO(priv, "Begin load bsm\n"); /* make sure bootstrap program is no larger than BSM's SRAM size */ if (len > IWL39_MAX_BSM_SIZE) @@ -2705,7 +2704,7 @@ static int iwl3945_load_bsm(struct iwl_priv *priv) udelay(10); } if (i < 100) - IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i); + IWL_DEBUG_INFO(priv, "BSM write complete, poll %d iterations\n", i); else { IWL_ERR(priv, "BSM write did not complete!\n"); return -EIO; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index d7d956db19d..7e9c8cfaa61 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -76,7 +76,7 @@ static int iwl4965_verify_bsm(struct iwl_priv *priv) u32 reg; u32 val; - IWL_DEBUG_INFO("Begin verify bsm\n"); + IWL_DEBUG_INFO(priv, "Begin verify bsm\n"); /* verify BSM SRAM contents */ val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG); @@ -94,7 +94,7 @@ static int iwl4965_verify_bsm(struct iwl_priv *priv) } } - IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n"); + IWL_DEBUG_INFO(priv, "BSM bootstrap uCode image OK\n"); return 0; } @@ -144,7 +144,7 @@ static int iwl4965_load_bsm(struct iwl_priv *priv) u32 reg_offset; int ret; - IWL_DEBUG_INFO("Begin load bsm\n"); + IWL_DEBUG_INFO(priv, "Begin load bsm\n"); priv->ucode_type = UCODE_RT; @@ -201,7 +201,7 @@ static int iwl4965_load_bsm(struct iwl_priv *priv) udelay(10); } if (i < 100) - IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i); + IWL_DEBUG_INFO(priv, "BSM write complete, poll %d iterations\n", i); else { IWL_ERR(priv, "BSM write did not complete!\n"); return -EIO; @@ -257,7 +257,7 @@ static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); - IWL_DEBUG_INFO("Runtime uCode pointers are set.\n"); + IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n"); return ret; } @@ -279,7 +279,7 @@ static void iwl4965_init_alive_start(struct iwl_priv *priv) if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { /* We had an error bringing up the hardware, so take it * all the way back down so we can try again */ - IWL_DEBUG_INFO("Initialize Alive failed.\n"); + IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n"); goto restart; } @@ -289,7 +289,7 @@ static void iwl4965_init_alive_start(struct iwl_priv *priv) if (iwl_verify_ucode(priv)) { /* Runtime instruction load was bad; * take it all the way back down so we can try again */ - IWL_DEBUG_INFO("Bad \"initialize\" uCode load.\n"); + IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n"); goto restart; } @@ -299,11 +299,11 @@ static void iwl4965_init_alive_start(struct iwl_priv *priv) /* Send pointers to protocol/runtime uCode image ... init code will * load and launch runtime uCode, which will send us another "Alive" * notification. */ - IWL_DEBUG_INFO("Initialization Alive received.\n"); + IWL_DEBUG_INFO(priv, "Initialization Alive received.\n"); if (iwl4965_set_ucode_ptrs(priv)) { /* Runtime instruction load won't happen; * take it all the way back down so we can try again */ - IWL_DEBUG_INFO("Couldn't set up uCode pointers.\n"); + IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n"); goto restart; } return; @@ -354,7 +354,7 @@ static int iwl4965_apm_init(struct iwl_priv *priv) ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); if (ret < 0) { - IWL_DEBUG_INFO("Failed to init the card\n"); + IWL_DEBUG_INFO(priv, "Failed to init the card\n"); goto out; } @@ -437,7 +437,7 @@ static int iwl4965_apm_stop_master(struct iwl_priv *priv) CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); spin_unlock_irqrestore(&priv->lock, flags); - IWL_DEBUG_INFO("stop master\n"); + IWL_DEBUG_INFO(priv, "stop master\n"); return 0; } @@ -526,7 +526,7 @@ static void iwl4965_chain_noise_reset(struct iwl_priv *priv) IWL_ERR(priv, "Could not send REPLY_PHY_CALIBRATION_CMD\n"); data->state = IWL_CHAIN_NOISE_ACCUMULATE; - IWL_DEBUG_CALIB("Run chain_noise_calibrate\n"); + IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n"); } } @@ -558,7 +558,7 @@ static void iwl4965_gain_computation(struct iwl_priv *priv, data->delta_gain_code[i] = 0; } } - IWL_DEBUG_CALIB("delta_gain_codes: a %d b %d c %d\n", + IWL_DEBUG_CALIB(priv, "delta_gain_codes: a %d b %d c %d\n", data->delta_gain_code[0], data->delta_gain_code[1], data->delta_gain_code[2]); @@ -576,7 +576,7 @@ static void iwl4965_gain_computation(struct iwl_priv *priv, ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, sizeof(cmd), &cmd); if (ret) - IWL_DEBUG_CALIB("fail sending cmd " + IWL_DEBUG_CALIB(priv, "fail sending cmd " "REPLY_PHY_CALIBRATION_CMD \n"); /* TODO we might want recalculate @@ -669,7 +669,7 @@ static void iwl4965_tx_queue_set_status(struct iwl_priv *priv, txq->sched_retry = scd_retry; - IWL_DEBUG_INFO("%s %s Queue %d on AC %d\n", + IWL_DEBUG_INFO(priv, "%s %s Queue %d on AC %d\n", active ? "Activate" : "Deactivate", scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); } @@ -968,7 +968,7 @@ static int iwl4965_interpolate_chan(struct iwl_priv *priv, u32 channel, ch_i2 = priv->calib_info->band_info[s].ch2.ch_num; chan_info->ch_num = (u8) channel; - IWL_DEBUG_TXPOWER("channel %d subband %d factory cal ch %d & %d\n", + IWL_DEBUG_TXPOWER(priv, "channel %d subband %d factory cal ch %d & %d\n", channel, s, ch_i1, ch_i2); for (c = 0; c < EEPROM_TX_POWER_TX_CHAINS; c++) { @@ -998,19 +998,19 @@ static int iwl4965_interpolate_chan(struct iwl_priv *priv, u32 channel, m1->pa_det, ch_i2, m2->pa_det); - IWL_DEBUG_TXPOWER - ("chain %d meas %d AP1=%d AP2=%d AP=%d\n", c, m, - m1->actual_pow, m2->actual_pow, omeas->actual_pow); - IWL_DEBUG_TXPOWER - ("chain %d meas %d NI1=%d NI2=%d NI=%d\n", c, m, - m1->gain_idx, m2->gain_idx, omeas->gain_idx); - IWL_DEBUG_TXPOWER - ("chain %d meas %d PA1=%d PA2=%d PA=%d\n", c, m, - m1->pa_det, m2->pa_det, omeas->pa_det); - IWL_DEBUG_TXPOWER - ("chain %d meas %d T1=%d T2=%d T=%d\n", c, m, - m1->temperature, m2->temperature, - omeas->temperature); + IWL_DEBUG_TXPOWER(priv, + "chain %d meas %d AP1=%d AP2=%d AP=%d\n", c, m, + m1->actual_pow, m2->actual_pow, omeas->actual_pow); + IWL_DEBUG_TXPOWER(priv, + "chain %d meas %d NI1=%d NI2=%d NI=%d\n", c, m, + m1->gain_idx, m2->gain_idx, omeas->gain_idx); + IWL_DEBUG_TXPOWER(priv, + "chain %d meas %d PA1=%d PA2=%d PA=%d\n", c, m, + m1->pa_det, m2->pa_det, omeas->pa_det); + IWL_DEBUG_TXPOWER(priv, + "chain %d meas %d T1=%d T2=%d T=%d\n", c, m, + m1->temperature, m2->temperature, + omeas->temperature); } } @@ -1312,7 +1312,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, user_target_power = 2 * priv->tx_power_user_lmt; /* Get current (RXON) channel, band, width */ - IWL_DEBUG_TXPOWER("chan %d band %d is_fat %d\n", channel, band, + IWL_DEBUG_TXPOWER(priv, "chan %d band %d is_fat %d\n", channel, band, is_fat); ch_info = iwl_get_channel_info(priv, priv->band, channel); @@ -1329,7 +1329,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, return -EINVAL; } - IWL_DEBUG_TXPOWER("channel %d belongs to txatten group %d\n", + IWL_DEBUG_TXPOWER(priv, "channel %d belongs to txatten group %d\n", channel, txatten_grp); if (is_fat) { @@ -1379,7 +1379,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, voltage_compensation = iwl4965_get_voltage_compensation(voltage, init_voltage); - IWL_DEBUG_TXPOWER("curr volt %d eeprom volt %d volt comp %d\n", + IWL_DEBUG_TXPOWER(priv, "curr volt %d eeprom volt %d volt comp %d\n", init_voltage, voltage, voltage_compensation); @@ -1410,13 +1410,13 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, factory_gain_index[c] = measurement->gain_idx; factory_actual_pwr[c] = measurement->actual_pow; - IWL_DEBUG_TXPOWER("chain = %d\n", c); - IWL_DEBUG_TXPOWER("fctry tmp %d, " + IWL_DEBUG_TXPOWER(priv, "chain = %d\n", c); + IWL_DEBUG_TXPOWER(priv, "fctry tmp %d, " "curr tmp %d, comp %d steps\n", factory_temp, current_temp, temperature_comp[c]); - IWL_DEBUG_TXPOWER("fctry idx %d, fctry pwr %d\n", + IWL_DEBUG_TXPOWER(priv, "fctry idx %d, fctry pwr %d\n", factory_gain_index[c], factory_actual_pwr[c]); } @@ -1449,7 +1449,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, if (target_power > power_limit) target_power = power_limit; - IWL_DEBUG_TXPOWER("rate %d sat %d reg %d usr %d tgt %d\n", + IWL_DEBUG_TXPOWER(priv, "rate %d sat %d reg %d usr %d tgt %d\n", i, saturation_power - back_off_table[i], current_regulatory, user_target_power, target_power); @@ -1473,7 +1473,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, voltage_compensation + atten_value); -/* IWL_DEBUG_TXPOWER("calculated txpower index %d\n", +/* IWL_DEBUG_TXPOWER(priv, "calculated txpower index %d\n", power_index); */ if (power_index < get_min_power_index(i, band)) @@ -1506,7 +1506,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, tx_power.s.dsp_predis_atten[c] = gain_table[band][power_index].dsp; - IWL_DEBUG_TXPOWER("chain %d mimo %d index %d " + IWL_DEBUG_TXPOWER(priv, "chain %d mimo %d index %d " "gain 0x%02x dsp %d\n", c, atten_value, power_index, tx_power.s.radio_tx_gain[c], @@ -1581,7 +1581,7 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) rxon2->ofdm_ht_dual_stream_basic_rates) && (rxon1->rx_chain == rxon2->rx_chain) && (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { - IWL_DEBUG_INFO("Using current RXON_ASSOC. Not resending.\n"); + IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); return 0; } @@ -1638,7 +1638,7 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_fat, ctrl_chan_high, &cmd.tx_power); if (rc) { - IWL_DEBUG_11H("error:%d fill txpower_tbl\n", rc); + IWL_DEBUG_11H(priv, "error:%d fill txpower_tbl\n", rc); return rc; } @@ -1703,13 +1703,13 @@ static int iwl4965_hw_get_temperature(const struct iwl_priv *priv) if (test_bit(STATUS_TEMPERATURE, &priv->status) && (priv->statistics.flag & STATISTICS_REPLY_FLG_FAT_MODE_MSK)) { - IWL_DEBUG_TEMP("Running FAT temperature calibration\n"); + IWL_DEBUG_TEMP(priv, "Running FAT temperature calibration\n"); R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[1]); R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[1]); R3 = (s32)le32_to_cpu(priv->card_alive_init.therm_r3[1]); R4 = le32_to_cpu(priv->card_alive_init.therm_r4[1]); } else { - IWL_DEBUG_TEMP("Running temperature calibration\n"); + IWL_DEBUG_TEMP(priv, "Running temperature calibration\n"); R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[0]); R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[0]); R3 = (s32)le32_to_cpu(priv->card_alive_init.therm_r3[0]); @@ -1729,7 +1729,7 @@ static int iwl4965_hw_get_temperature(const struct iwl_priv *priv) vt = sign_extend( le32_to_cpu(priv->statistics.general.temperature), 23); - IWL_DEBUG_TEMP("Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt); + IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt); if (R3 == R1) { IWL_ERR(priv, "Calibration conflict R1 == R3\n"); @@ -1742,7 +1742,7 @@ static int iwl4965_hw_get_temperature(const struct iwl_priv *priv) temperature /= (R3 - R1); temperature = (temperature * 97) / 100 + TEMPERATURE_CALIB_KELVIN_OFFSET; - IWL_DEBUG_TEMP("Calibrated temperature: %dK, %dC\n", + IWL_DEBUG_TEMP(priv, "Calibrated temperature: %dK, %dC\n", temperature, KELVIN_TO_CELSIUS(temperature)); return temperature; @@ -1765,7 +1765,7 @@ static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv) int temp_diff; if (!test_bit(STATUS_STATISTICS, &priv->status)) { - IWL_DEBUG_TEMP("Temperature not updated -- no statistics.\n"); + IWL_DEBUG_TEMP(priv, "Temperature not updated -- no statistics.\n"); return 0; } @@ -1773,19 +1773,19 @@ static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv) /* get absolute value */ if (temp_diff < 0) { - IWL_DEBUG_POWER("Getting cooler, delta %d, \n", temp_diff); + IWL_DEBUG_POWER(priv, "Getting cooler, delta %d, \n", temp_diff); temp_diff = -temp_diff; } else if (temp_diff == 0) - IWL_DEBUG_POWER("Same temp, \n"); + IWL_DEBUG_POWER(priv, "Same temp, \n"); else - IWL_DEBUG_POWER("Getting warmer, delta %d, \n", temp_diff); + IWL_DEBUG_POWER(priv, "Getting warmer, delta %d, \n", temp_diff); if (temp_diff < IWL_TEMPERATURE_THRESHOLD) { - IWL_DEBUG_POWER("Thermal txpower calib not needed\n"); + IWL_DEBUG_POWER(priv, "Thermal txpower calib not needed\n"); return 0; } - IWL_DEBUG_POWER("Thermal txpower calib needed\n"); + IWL_DEBUG_POWER(priv, "Thermal txpower calib needed\n"); return 1; } @@ -1800,12 +1800,12 @@ static void iwl4965_temperature_calib(struct iwl_priv *priv) if (priv->temperature != temp) { if (priv->temperature) - IWL_DEBUG_TEMP("Temperature changed " + IWL_DEBUG_TEMP(priv, "Temperature changed " "from %dC to %dC\n", KELVIN_TO_CELSIUS(priv->temperature), KELVIN_TO_CELSIUS(temp)); else - IWL_DEBUG_TEMP("Temperature " + IWL_DEBUG_TEMP(priv, "Temperature " "initialized to %dC\n", KELVIN_TO_CELSIUS(temp)); } @@ -2022,7 +2022,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, int i, sh, idx; u16 seq; if (agg->wait_for_ba) - IWL_DEBUG_TX_REPLY("got tx response w/o block-ack\n"); + IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n"); agg->frame_count = tx_resp->frame_count; agg->start_idx = start_idx; @@ -2036,7 +2036,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, idx = start_idx; /* FIXME: code repetition */ - IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n", + IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", agg->frame_count, agg->start_idx, idx); info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); @@ -2047,9 +2047,9 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, iwl_hwrate_to_tx_control(priv, rate_n_flags, info); /* FIXME: code repetition end */ - IWL_DEBUG_TX_REPLY("1 Frame 0x%x failure :%d\n", + IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n", status & 0xff, tx_resp->failure_frame); - IWL_DEBUG_TX_REPLY("Rate Info rate_n_flags=%x\n", rate_n_flags); + IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags); agg->wait_for_ba = 0; } else { @@ -2069,7 +2069,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, AGG_TX_STATE_ABORT_MSK)) continue; - IWL_DEBUG_TX_REPLY("FrameCnt = %d, txq_id=%d idx=%d\n", + IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n", agg->frame_count, txq_id, idx); hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); @@ -2083,7 +2083,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, return -1; } - IWL_DEBUG_TX_REPLY("AGG Frame i=%d idx %d seq=%d\n", + IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n", i, idx, SEQ_TO_SN(sc)); sh = idx - start; @@ -2101,13 +2101,13 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, sh = 0; } bitmap |= 1ULL << sh; - IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%llx\n", + IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n", start, (unsigned long long)bitmap); } agg->bitmap = bitmap; agg->start_idx = start; - IWL_DEBUG_TX_REPLY("Frames %d start_idx=%d bitmap=0x%llx\n", + IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n", agg->frame_count, agg->start_idx, (unsigned long long)agg->bitmap); @@ -2176,7 +2176,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, if (txq->q.read_ptr != (scd_ssn & 0xff)) { index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); - IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn " + IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn " "%d index %d\n", scd_ssn , index); freed = iwl_tx_queue_reclaim(priv, txq_id, index); priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; @@ -2199,7 +2199,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, le32_to_cpu(tx_resp->rate_n_flags), info); - IWL_DEBUG_TX_REPLY("TXQ %d status %s (0x%08x) " + IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) " "rate_n_flags 0x%x retries %d\n", txq_id, iwl_get_tx_fail_reason(status), status, @@ -2247,7 +2247,7 @@ static int iwl4965_calc_rssi(struct iwl_priv *priv, if (valid_antennae & (1 << i)) max_rssi = max(ncphy->rssi_info[i << 1], max_rssi); - IWL_DEBUG_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n", + IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n", ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4], max_rssi, agc); diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 89d92a8ca15..c5e9a66e2f8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -84,7 +84,7 @@ static int iwl5000_apm_stop_master(struct iwl_priv *priv) CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); spin_unlock_irqrestore(&priv->lock, flags); - IWL_DEBUG_INFO("stop master\n"); + IWL_DEBUG_INFO(priv, "stop master\n"); return 0; } @@ -118,7 +118,7 @@ static int iwl5000_apm_init(struct iwl_priv *priv) ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); if (ret < 0) { - IWL_DEBUG_INFO("Failed to init the card\n"); + IWL_DEBUG_INFO(priv, "Failed to init the card\n"); return ret; } @@ -186,7 +186,7 @@ static int iwl5000_apm_reset(struct iwl_priv *priv) ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); if (ret < 0) { - IWL_DEBUG_INFO("Failed to init the card\n"); + IWL_DEBUG_INFO(priv, "Failed to init the card\n"); goto out; } @@ -338,7 +338,7 @@ static void iwl5000_gain_computation(struct iwl_priv *priv, data->delta_gain_code[i] |= (1 << 2); } - IWL_DEBUG_CALIB("Delta gains: ANT_B = %d ANT_C = %d\n", + IWL_DEBUG_CALIB(priv, "Delta gains: ANT_B = %d ANT_C = %d\n", data->delta_gain_code[1], data->delta_gain_code[2]); if (!data->radio_write) { @@ -387,7 +387,7 @@ static void iwl5000_chain_noise_reset(struct iwl_priv *priv) IWL_ERR(priv, "Could not send REPLY_PHY_CALIBRATION_CMD\n"); data->state = IWL_CHAIN_NOISE_ACCUMULATE; - IWL_DEBUG_CALIB("Run chain_noise_calibrate\n"); + IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n"); } } @@ -518,7 +518,7 @@ static void iwl5000_rx_calib_result(struct iwl_priv *priv, static void iwl5000_rx_calib_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { - IWL_DEBUG_INFO("Init. calibration is completed, restarting fw.\n"); + IWL_DEBUG_INFO(priv, "Init. calibration is completed, restarting fw.\n"); queue_work(priv->workqueue, &priv->restart); } @@ -586,7 +586,7 @@ static int iwl5000_load_given_ucode(struct iwl_priv *priv, if (ret) return ret; - IWL_DEBUG_INFO("INST uCode section being loaded...\n"); + IWL_DEBUG_INFO(priv, "INST uCode section being loaded...\n"); ret = wait_event_interruptible_timeout(priv->wait_command_queue, priv->ucode_write_complete, 5 * HZ); if (ret == -ERESTARTSYS) { @@ -606,7 +606,7 @@ static int iwl5000_load_given_ucode(struct iwl_priv *priv, if (ret) return ret; - IWL_DEBUG_INFO("DATA uCode section being loaded...\n"); + IWL_DEBUG_INFO(priv, "DATA uCode section being loaded...\n"); ret = wait_event_interruptible_timeout(priv->wait_command_queue, priv->ucode_write_complete, 5 * HZ); @@ -631,20 +631,20 @@ static int iwl5000_load_ucode(struct iwl_priv *priv) /* check whether init ucode should be loaded, or rather runtime ucode */ if (priv->ucode_init.len && (priv->ucode_type == UCODE_NONE)) { - IWL_DEBUG_INFO("Init ucode found. Loading init ucode...\n"); + IWL_DEBUG_INFO(priv, "Init ucode found. Loading init ucode...\n"); ret = iwl5000_load_given_ucode(priv, &priv->ucode_init, &priv->ucode_init_data); if (!ret) { - IWL_DEBUG_INFO("Init ucode load complete.\n"); + IWL_DEBUG_INFO(priv, "Init ucode load complete.\n"); priv->ucode_type = UCODE_INIT; } } else { - IWL_DEBUG_INFO("Init ucode not found, or already loaded. " + IWL_DEBUG_INFO(priv, "Init ucode not found, or already loaded. " "Loading runtime ucode...\n"); ret = iwl5000_load_given_ucode(priv, &priv->ucode_code, &priv->ucode_data); if (!ret) { - IWL_DEBUG_INFO("Runtime ucode load complete.\n"); + IWL_DEBUG_INFO(priv, "Runtime ucode load complete.\n"); priv->ucode_type = UCODE_RT; } } @@ -660,7 +660,7 @@ static void iwl5000_init_alive_start(struct iwl_priv *priv) if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { /* We had an error bringing up the hardware, so take it * all the way back down so we can try again */ - IWL_DEBUG_INFO("Initialize Alive failed.\n"); + IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n"); goto restart; } @@ -670,7 +670,7 @@ static void iwl5000_init_alive_start(struct iwl_priv *priv) if (iwl_verify_ucode(priv)) { /* Runtime instruction load was bad; * take it all the way back down so we can try again */ - IWL_DEBUG_INFO("Bad \"initialize\" uCode load.\n"); + IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n"); goto restart; } @@ -713,7 +713,7 @@ static void iwl5000_tx_queue_set_status(struct iwl_priv *priv, txq->sched_retry = scd_retry; - IWL_DEBUG_INFO("%s %s Queue %d on AC %d\n", + IWL_DEBUG_INFO(priv, "%s %s Queue %d on AC %d\n", active ? "Activate" : "Deactivate", scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); } @@ -1151,7 +1151,7 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, u16 seq; if (agg->wait_for_ba) - IWL_DEBUG_TX_REPLY("got tx response w/o block-ack\n"); + IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n"); agg->frame_count = tx_resp->frame_count; agg->start_idx = start_idx; @@ -1165,7 +1165,7 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, idx = start_idx; /* FIXME: code repetition */ - IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n", + IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", agg->frame_count, agg->start_idx, idx); info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); @@ -1177,9 +1177,9 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, /* FIXME: code repetition end */ - IWL_DEBUG_TX_REPLY("1 Frame 0x%x failure :%d\n", + IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n", status & 0xff, tx_resp->failure_frame); - IWL_DEBUG_TX_REPLY("Rate Info rate_n_flags=%x\n", rate_n_flags); + IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags); agg->wait_for_ba = 0; } else { @@ -1199,7 +1199,7 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, AGG_TX_STATE_ABORT_MSK)) continue; - IWL_DEBUG_TX_REPLY("FrameCnt = %d, txq_id=%d idx=%d\n", + IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n", agg->frame_count, txq_id, idx); hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); @@ -1214,7 +1214,7 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, return -1; } - IWL_DEBUG_TX_REPLY("AGG Frame i=%d idx %d seq=%d\n", + IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n", i, idx, SEQ_TO_SN(sc)); sh = idx - start; @@ -1232,13 +1232,13 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, sh = 0; } bitmap |= 1ULL << sh; - IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%llx\n", + IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n", start, (unsigned long long)bitmap); } agg->bitmap = bitmap; agg->start_idx = start; - IWL_DEBUG_TX_REPLY("Frames %d start_idx=%d bitmap=0x%llx\n", + IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n", agg->frame_count, agg->start_idx, (unsigned long long)agg->bitmap); @@ -1291,7 +1291,7 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, if (txq->q.read_ptr != (scd_ssn & 0xff)) { index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); - IWL_DEBUG_TX_REPLY("Retry scheduler reclaim " + IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim " "scd_ssn=%d idx=%d txq=%d swq=%d\n", scd_ssn , index, txq_id, txq->swq_id); @@ -1318,7 +1318,7 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, le32_to_cpu(tx_resp->rate_n_flags), info); - IWL_DEBUG_TX_REPLY("TXQ %d status %s (0x%08x) rate_n_flags " + IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags " "0x%x retries %d\n", txq_id, iwl_get_tx_fail_reason(status), status, @@ -1389,7 +1389,7 @@ static int iwl5000_send_rxon_assoc(struct iwl_priv *priv) (rxon1->acquisition_data == rxon2->acquisition_data) && (rxon1->rx_chain == rxon2->rx_chain) && (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { - IWL_DEBUG_INFO("Using current RXON_ASSOC. Not resending.\n"); + IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); return 0; } @@ -1465,7 +1465,7 @@ static int iwl5000_calc_rssi(struct iwl_priv *priv, max_rssi = max_t(u32, rssi_a, rssi_b); max_rssi = max_t(u32, max_rssi, rssi_c); - IWL_DEBUG_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n", + IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n", rssi_a, rssi_b, rssi_c, max_rssi, agc); /* dBm = max_rssi dB - agc dB - constant. diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 13039a02447..04b42c8a770 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -360,7 +360,7 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, struct ieee80211_sta *sta) { if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { - IWL_DEBUG_HT("Starting Tx agg: STA: %pM tid: %d\n", + IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", sta->addr, tid); ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid); } @@ -693,7 +693,7 @@ static u16 rs_get_adjacent_rate(struct iwl_priv *priv, u8 index, u16 rate_mask, break; if (rate_mask & (1 << low)) break; - IWL_DEBUG_RATE("Skipping masked lower rate: %d\n", low); + IWL_DEBUG_RATE(priv, "Skipping masked lower rate: %d\n", low); } high = index; @@ -703,7 +703,7 @@ static u16 rs_get_adjacent_rate(struct iwl_priv *priv, u8 index, u16 rate_mask, break; if (rate_mask & (1 << high)) break; - IWL_DEBUG_RATE("Skipping masked higher rate: %d\n", high); + IWL_DEBUG_RATE(priv, "Skipping masked higher rate: %d\n", high); } return (high << 8) | low; @@ -790,7 +790,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, u8 active_index = 0; s32 tpt = 0; - IWL_DEBUG_RATE_LIMIT("get frame ack response, update rate scale window\n"); + IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); if (!ieee80211_is_data(hdr->frame_control) || is_multicast_ether_addr(hdr->addr1)) @@ -840,7 +840,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, (!!(tx_rate & RATE_MCS_GF_MSK) != !!(info->status.rates[0].flags & IEEE80211_TX_RC_GREEN_FIELD)) || (hw->wiphy->bands[priv->band]->bitrates[rs_index].bitrate != hw->wiphy->bands[info->band]->bitrates[info->status.rates[0].idx].bitrate)) { - IWL_DEBUG_RATE("initial rate does not match 0x%x\n", tx_rate); + IWL_DEBUG_RATE(priv, "initial rate does not match 0x%x\n", tx_rate); /* the last LQ command could failed so the LQ in ucode not * the same in driver sync up */ @@ -971,7 +971,7 @@ out: static void rs_set_stay_in_table(struct iwl_priv *priv, u8 is_legacy, struct iwl_lq_sta *lq_sta) { - IWL_DEBUG_RATE("we are staying in the same table\n"); + IWL_DEBUG_RATE(priv, "we are staying in the same table\n"); lq_sta->stay_in_tbl = 1; /* only place this gets set */ if (is_legacy) { lq_sta->table_count_limit = IWL_LEGACY_TABLE_COUNT; @@ -1150,7 +1150,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, if (priv->hw_params.tx_chains_num < 2) return -1; - IWL_DEBUG_RATE("LQ: try to switch to MIMO2\n"); + IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO2\n"); tbl->lq_type = LQ_MIMO2; tbl->is_dup = lq_sta->is_dup; @@ -1179,16 +1179,16 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index); - IWL_DEBUG_RATE("LQ: MIMO2 best rate %d mask %X\n", rate, rate_mask); + IWL_DEBUG_RATE(priv, "LQ: MIMO2 best rate %d mask %X\n", rate, rate_mask); if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) { - IWL_DEBUG_RATE("Can't switch with index %d rate mask %x\n", + IWL_DEBUG_RATE(priv, "Can't switch with index %d rate mask %x\n", rate, rate_mask); return -1; } tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, rate, is_green); - IWL_DEBUG_RATE("LQ: Switch to new mcs %X index is green %X\n", + IWL_DEBUG_RATE(priv, "LQ: Switch to new mcs %X index is green %X\n", tbl->current_rate, is_green); return 0; } @@ -1209,7 +1209,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv, if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) return -1; - IWL_DEBUG_RATE("LQ: try to switch to SISO\n"); + IWL_DEBUG_RATE(priv, "LQ: try to switch to SISO\n"); tbl->is_dup = lq_sta->is_dup; tbl->lq_type = LQ_SISO; @@ -1240,14 +1240,14 @@ static int rs_switch_to_siso(struct iwl_priv *priv, rs_set_expected_tpt_table(lq_sta, tbl); rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index); - IWL_DEBUG_RATE("LQ: get best rate %d mask %X\n", rate, rate_mask); + IWL_DEBUG_RATE(priv, "LQ: get best rate %d mask %X\n", rate, rate_mask); if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) { - IWL_DEBUG_RATE("can not switch with index %d rate mask %x\n", + IWL_DEBUG_RATE(priv, "can not switch with index %d rate mask %x\n", rate, rate_mask); return -1; } tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, rate, is_green); - IWL_DEBUG_RATE("LQ: Switch to new mcs %X index is green %X\n", + IWL_DEBUG_RATE(priv, "LQ: Switch to new mcs %X index is green %X\n", tbl->current_rate, is_green); return 0; } @@ -1276,7 +1276,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, switch (tbl->action) { case IWL_LEGACY_SWITCH_ANTENNA1: case IWL_LEGACY_SWITCH_ANTENNA2: - IWL_DEBUG_RATE("LQ: Legacy toggle Antenna\n"); + IWL_DEBUG_RATE(priv, "LQ: Legacy toggle Antenna\n"); lq_sta->action_counter++; @@ -1300,7 +1300,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, } break; case IWL_LEGACY_SWITCH_SISO: - IWL_DEBUG_RATE("LQ: Legacy switch to SISO\n"); + IWL_DEBUG_RATE(priv, "LQ: Legacy switch to SISO\n"); /* Set up search table to try SISO */ memcpy(search_tbl, tbl, sz); @@ -1316,7 +1316,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, case IWL_LEGACY_SWITCH_MIMO2_AB: case IWL_LEGACY_SWITCH_MIMO2_AC: case IWL_LEGACY_SWITCH_MIMO2_BC: - IWL_DEBUG_RATE("LQ: Legacy switch to MIMO2\n"); + IWL_DEBUG_RATE(priv, "LQ: Legacy switch to MIMO2\n"); /* Set up search table to try MIMO */ memcpy(search_tbl, tbl, sz); @@ -1385,7 +1385,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, switch (tbl->action) { case IWL_SISO_SWITCH_ANTENNA1: case IWL_SISO_SWITCH_ANTENNA2: - IWL_DEBUG_RATE("LQ: SISO toggle Antenna\n"); + IWL_DEBUG_RATE(priv, "LQ: SISO toggle Antenna\n"); if ((tbl->action == IWL_SISO_SWITCH_ANTENNA1 && tx_chains_num <= 1) || @@ -1404,7 +1404,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, case IWL_SISO_SWITCH_MIMO2_AB: case IWL_SISO_SWITCH_MIMO2_AC: case IWL_SISO_SWITCH_MIMO2_BC: - IWL_DEBUG_RATE("LQ: SISO switch to MIMO2\n"); + IWL_DEBUG_RATE(priv, "LQ: SISO switch to MIMO2\n"); memcpy(search_tbl, tbl, sz); search_tbl->is_SGI = 0; @@ -1433,7 +1433,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, HT_SHORT_GI_40MHZ)) break; - IWL_DEBUG_RATE("LQ: SISO toggle SGI/NGI\n"); + IWL_DEBUG_RATE(priv, "LQ: SISO toggle SGI/NGI\n"); memcpy(search_tbl, tbl, sz); if (is_green) { @@ -1498,7 +1498,7 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv, switch (tbl->action) { case IWL_MIMO2_SWITCH_ANTENNA1: case IWL_MIMO2_SWITCH_ANTENNA2: - IWL_DEBUG_RATE("LQ: MIMO toggle Antennas\n"); + IWL_DEBUG_RATE(priv, "LQ: MIMO toggle Antennas\n"); if (tx_chains_num <= 2) break; @@ -1514,7 +1514,7 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv, case IWL_MIMO2_SWITCH_SISO_A: case IWL_MIMO2_SWITCH_SISO_B: case IWL_MIMO2_SWITCH_SISO_C: - IWL_DEBUG_RATE("LQ: MIMO2 switch to SISO\n"); + IWL_DEBUG_RATE(priv, "LQ: MIMO2 switch to SISO\n"); /* Set up new search table for SISO */ memcpy(search_tbl, tbl, sz); @@ -1546,7 +1546,7 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv, HT_SHORT_GI_40MHZ)) break; - IWL_DEBUG_RATE("LQ: MIMO toggle SGI/NGI\n"); + IWL_DEBUG_RATE(priv, "LQ: MIMO toggle SGI/NGI\n"); /* Set up new search table for MIMO */ memcpy(search_tbl, tbl, sz); @@ -1629,7 +1629,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta) (lq_sta->total_success > lq_sta->max_success_limit) || ((!lq_sta->search_better_tbl) && (lq_sta->flush_timer) && (flush_interval_passed))) { - IWL_DEBUG_RATE("LQ: stay is expired %d %d %d\n:", + IWL_DEBUG_RATE(priv, "LQ: stay is expired %d %d %d\n:", lq_sta->total_failed, lq_sta->total_success, flush_interval_passed); @@ -1652,7 +1652,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta) lq_sta->table_count_limit) { lq_sta->table_count = 0; - IWL_DEBUG_RATE("LQ: stay in table clear win\n"); + IWL_DEBUG_RATE(priv, "LQ: stay in table clear win\n"); for (i = 0; i < IWL_RATE_COUNT; i++) rs_rate_scale_clear_window( &(tbl->win[i])); @@ -1701,7 +1701,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, s32 sr; u8 tid = MAX_TID_COUNT; - IWL_DEBUG_RATE("rate scale calculate new rate for skb\n"); + IWL_DEBUG_RATE(priv, "rate scale calculate new rate for skb\n"); /* Send management frames and broadcast/multicast data using * lowest rate. */ @@ -1733,13 +1733,13 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, /* current tx rate */ index = lq_sta->last_txrate_idx; - IWL_DEBUG_RATE("Rate scale index %d for type %d\n", index, + IWL_DEBUG_RATE(priv, "Rate scale index %d for type %d\n", index, tbl->lq_type); /* rates available for this association, and for modulation mode */ rate_mask = rs_get_supported_rates(lq_sta, hdr, tbl->lq_type); - IWL_DEBUG_RATE("mask 0x%04X \n", rate_mask); + IWL_DEBUG_RATE(priv, "mask 0x%04X \n", rate_mask); /* mask with station rate restriction */ if (is_legacy(tbl->lq_type)) { @@ -1789,7 +1789,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, fail_count = window->counter - window->success_counter; if ((fail_count < IWL_RATE_MIN_FAILURE_TH) && (window->success_counter < IWL_RATE_MIN_SUCCESS_TH)) { - IWL_DEBUG_RATE("LQ: still below TH. succ=%d total=%d " + IWL_DEBUG_RATE(priv, "LQ: still below TH. succ=%d total=%d " "for index %d\n", window->success_counter, window->counter, index); @@ -1817,7 +1817,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, * continuing to use the setup that we've been trying. */ if (window->average_tpt > lq_sta->last_tpt) { - IWL_DEBUG_RATE("LQ: SWITCHING TO NEW TABLE " + IWL_DEBUG_RATE(priv, "LQ: SWITCHING TO NEW TABLE " "suc=%d cur-tpt=%d old-tpt=%d\n", window->success_ratio, window->average_tpt, @@ -1833,7 +1833,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, /* Else poor success; go back to mode in "active" table */ } else { - IWL_DEBUG_RATE("LQ: GOING BACK TO THE OLD TABLE " + IWL_DEBUG_RATE(priv, "LQ: GOING BACK TO THE OLD TABLE " "suc=%d cur-tpt=%d old-tpt=%d\n", window->success_ratio, window->average_tpt, @@ -1886,7 +1886,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, /* Too many failures, decrease rate */ if ((sr <= IWL_RATE_DECREASE_TH) || (current_tpt == 0)) { - IWL_DEBUG_RATE("decrease rate because of low success_ratio\n"); + IWL_DEBUG_RATE(priv, "decrease rate because of low success_ratio\n"); scale_action = -1; /* No throughput measured yet for adjacent rates; try increase. */ @@ -1917,8 +1917,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, sr >= IWL_RATE_INCREASE_TH) { scale_action = 1; } else { - IWL_DEBUG_RATE - ("decrease rate because of high tpt\n"); + IWL_DEBUG_RATE(priv, + "decrease rate because of high tpt\n"); scale_action = -1; } @@ -1926,8 +1926,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, } else if (low_tpt != IWL_INVALID_VALUE) { /* Lower rate has better throughput */ if (low_tpt > current_tpt) { - IWL_DEBUG_RATE - ("decrease rate because of low tpt\n"); + IWL_DEBUG_RATE(priv, + "decrease rate because of low tpt\n"); scale_action = -1; } else if (sr >= IWL_RATE_INCREASE_TH) { scale_action = 1; @@ -1964,7 +1964,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, break; } - IWL_DEBUG_RATE("choose rate scale index %d action %d low %d " + IWL_DEBUG_RATE(priv, "choose rate scale index %d action %d low %d " "high %d type %d\n", index, scale_action, low, high, tbl->lq_type); @@ -2008,7 +2008,7 @@ lq_update: /* Use new "search" start rate */ index = iwl_hwrate_to_plcp_idx(tbl->current_rate); - IWL_DEBUG_RATE("Switch current mcs: %X index: %d\n", + IWL_DEBUG_RATE(priv, "Switch current mcs: %X index: %d\n", tbl->current_rate, index); rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); @@ -2023,7 +2023,7 @@ lq_update: if (is_legacy(tbl1->lq_type) && !conf_is_ht(conf) && lq_sta->action_counter >= 1) { lq_sta->action_counter = 0; - IWL_DEBUG_RATE("LQ: STAY in legacy table\n"); + IWL_DEBUG_RATE(priv, "LQ: STAY in legacy table\n"); rs_set_stay_in_table(priv, 1, lq_sta); } @@ -2035,7 +2035,7 @@ lq_update: if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) && (lq_sta->tx_agg_tid_en & (1 << tid)) && (tid != MAX_TID_COUNT)) { - IWL_DEBUG_RATE("try to aggregate tid %d\n", tid); + IWL_DEBUG_RATE(priv, "try to aggregate tid %d\n", tid); rs_tl_turn_on_agg(priv, tid, lq_sta, sta); } lq_sta->action_counter = 0; @@ -2131,7 +2131,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, int rate_idx; u64 mask_bit = 0; - IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n"); + IWL_DEBUG_RATE_LIMIT(priv, "rate scale calculate new rate for skb\n"); /* Get max rate if user set max rate */ if (lq_sta) { @@ -2167,7 +2167,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, u8 sta_id = iwl_find_station(priv, hdr->addr1); if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_RATE("LQ: ADD station %pM\n", + IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", hdr->addr1); sta_id = iwl_add_station_flags(priv, hdr->addr1, 0, CMD_ASYNC, NULL); @@ -2196,7 +2196,7 @@ static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, int i, j; priv = (struct iwl_priv *)priv_rate; - IWL_DEBUG_RATE("create station rate scale window\n"); + IWL_DEBUG_RATE(priv, "create station rate scale window\n"); lq_sta = kzalloc(sizeof(struct iwl_lq_sta), gfp); @@ -2229,7 +2229,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, for (i = 0; i < IWL_RATE_COUNT; i++) rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); - IWL_DEBUG_RATE("LQ: *** rate scale station global init ***\n"); + IWL_DEBUG_RATE(priv, "LQ: *** rate scale station global init ***\n"); /* TODO: what is a good starting rate for STA? About middle? Maybe not * the lowest or the highest rate.. Could consider using RSSI from * previous packets? Need to have IEEE 802.1X auth succeed immediately @@ -2240,10 +2240,10 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, u8 sta_id = iwl_find_station(priv, sta->addr); /* for IBSS the call are from tasklet */ - IWL_DEBUG_RATE("LQ: ADD station %pM\n", sta->addr); + IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr); if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_RATE("LQ: ADD station %pM\n", sta->addr); + IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr); sta_id = iwl_add_station_flags(priv, sta->addr, 0, CMD_ASYNC, NULL); } @@ -2282,7 +2282,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, lq_sta->active_mimo3_rate &= ~((u16)0x2); lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE; - IWL_DEBUG_RATE("SISO-RATE=%X MIMO2-RATE=%X MIMO3-RATE=%X\n", + IWL_DEBUG_RATE(priv, "SISO-RATE=%X MIMO2-RATE=%X MIMO3-RATE=%X\n", lq_sta->active_siso_rate, lq_sta->active_mimo2_rate, lq_sta->active_mimo3_rate); @@ -2448,9 +2448,9 @@ static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta, struct iwl_lq_sta *lq_sta = priv_sta; struct iwl_priv *priv __maybe_unused = priv_r; - IWL_DEBUG_RATE("enter\n"); + IWL_DEBUG_RATE(priv, "enter\n"); kfree(lq_sta); - IWL_DEBUG_RATE("leave\n"); + IWL_DEBUG_RATE(priv, "leave\n"); } @@ -2475,9 +2475,9 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, else *rate_n_flags = 0x820A; } - IWL_DEBUG_RATE("Fixed rate ON\n"); + IWL_DEBUG_RATE(priv, "Fixed rate ON\n"); } else { - IWL_DEBUG_RATE("Fixed rate OFF\n"); + IWL_DEBUG_RATE(priv, "Fixed rate OFF\n"); } } @@ -2506,7 +2506,7 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ lq_sta->active_mimo3_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ - IWL_DEBUG_RATE("sta_id %d rate 0x%X\n", + IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n", lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate); if (lq_sta->dbg_fixed_rate) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index ad6403395e4..c196abc6db7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -147,7 +147,7 @@ static int iwl_commit_rxon(struct iwl_priv *priv) * we must clear the associated from the active configuration * before we apply the new config */ if (iwl_is_associated(priv) && new_assoc) { - IWL_DEBUG_INFO("Toggling associated bit on current RXON\n"); + IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n"); active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; ret = iwl_send_cmd_pdu(priv, REPLY_RXON, @@ -163,7 +163,7 @@ static int iwl_commit_rxon(struct iwl_priv *priv) } } - IWL_DEBUG_INFO("Sending RXON\n" + IWL_DEBUG_INFO(priv, "Sending RXON\n" "* with%s RXON_FILTER_ASSOC_MSK\n" "* channel = %d\n" "* bssid = %pM\n", @@ -254,7 +254,7 @@ static void iwl_clear_free_frames(struct iwl_priv *priv) { struct list_head *element; - IWL_DEBUG_INFO("%d frames on pre-allocated heap on clear.\n", + IWL_DEBUG_INFO(priv, "%d frames on pre-allocated heap on clear.\n", priv->frames_count); while (!list_empty(&priv->free_frames)) { @@ -538,7 +538,7 @@ static void iwl_ht_conf(struct iwl_priv *priv, struct iwl_ht_info *iwl_conf = &priv->current_ht_config; struct ieee80211_sta *sta; - IWL_DEBUG_MAC80211("enter: \n"); + IWL_DEBUG_MAC80211(priv, "enter: \n"); if (!iwl_conf->is_ht) return; @@ -598,7 +598,7 @@ static void iwl_ht_conf(struct iwl_priv *priv, rcu_read_unlock(); - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); } /* @@ -623,7 +623,7 @@ static void iwl_activate_qos(struct iwl_priv *priv, u8 force) priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; if (force || iwl_is_associated(priv)) { - IWL_DEBUG_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n", + IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n", priv->qos_data.qos_active, priv->qos_data.def_qos_parm.qos_flags); @@ -680,7 +680,7 @@ static void iwl_setup_rxon_timing(struct iwl_priv *priv) priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem); spin_unlock_irqrestore(&priv->lock, flags); - IWL_DEBUG_ASSOC("beacon interval %d beacon timer %d beacon tim %d\n", + IWL_DEBUG_ASSOC(priv, "beacon interval %d beacon timer %d beacon tim %d\n", le16_to_cpu(priv->rxon_timing.beacon_interval), le32_to_cpu(priv->rxon_timing.beacon_init_val), le16_to_cpu(priv->rxon_timing.atim_window)); @@ -701,7 +701,7 @@ static int iwl_set_mode(struct iwl_priv *priv, int mode) cancel_delayed_work(&priv->scan_check); if (iwl_scan_cancel_timeout(priv, 100)) { IWL_WARN(priv, "Aborted scan still in progress after 100ms\n"); - IWL_DEBUG_MAC80211("leaving - scan abort failed.\n"); + IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n"); return -EAGAIN; } @@ -724,19 +724,19 @@ static void iwl_rx_reply_alive(struct iwl_priv *priv, palive = &pkt->u.alive_frame; - IWL_DEBUG_INFO("Alive ucode status 0x%08X revision " + IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision " "0x%01X 0x%01X\n", palive->is_valid, palive->ver_type, palive->ver_subtype); if (palive->ver_subtype == INITIALIZE_SUBTYPE) { - IWL_DEBUG_INFO("Initialization Alive received.\n"); + IWL_DEBUG_INFO(priv, "Initialization Alive received.\n"); memcpy(&priv->card_alive_init, &pkt->u.alive_frame, sizeof(struct iwl_init_alive_resp)); pwork = &priv->init_alive_start; } else { - IWL_DEBUG_INFO("Runtime Alive received.\n"); + IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); memcpy(&priv->card_alive, &pkt->u.alive_frame, sizeof(struct iwl_alive_resp)); pwork = &priv->alive_start; @@ -771,7 +771,7 @@ static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, #ifdef CONFIG_IWLWIFI_DEBUG struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif); - IWL_DEBUG_RX("sleep mode: %d, src: %d\n", + IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n", sleep->pm_sleep_mode, sleep->pm_wakeup_src); #endif } @@ -780,7 +780,7 @@ static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - IWL_DEBUG_RADIO("Dumping %d bytes of unhandled " + IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " "notification for %s:\n", le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd)); iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len)); @@ -844,7 +844,7 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv, (struct iwl4965_beacon_notif *)pkt->u.raw; u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); - IWL_DEBUG_RX("beacon status %x retries %d iss %d " + IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d " "tsf %d %d rate %d\n", le32_to_cpu(beacon->beacon_notify_hdr.u.status) & TX_STATUS_MSK, beacon->beacon_notify_hdr.failure_frame, @@ -867,7 +867,7 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); unsigned long status = priv->status; - IWL_DEBUG_RF_KILL("Card state received: HW:%s SW:%s\n", + IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s\n", (flags & HW_CARD_DISABLED) ? "Kill" : "On", (flags & SW_CARD_DISABLED) ? "Kill" : "On"); @@ -1029,7 +1029,7 @@ void iwl_rx_handle(struct iwl_priv *priv) /* Rx interrupt, but nothing sent from uCode */ if (i == r) - IWL_DEBUG(IWL_DL_RX, "r = %d, i = %d\n", r, i); + IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i); if (iwl_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2)) fill_rx = 1; @@ -1069,12 +1069,12 @@ void iwl_rx_handle(struct iwl_priv *priv) * handle those that need handling via function in * rx_handlers table. See iwl_setup_rx_handlers() */ if (priv->rx_handlers[pkt->hdr.cmd]) { - IWL_DEBUG(IWL_DL_RX, "r = %d, i = %d, %s, 0x%02x\n", r, + IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); } else { /* No handling needed */ - IWL_DEBUG(IWL_DL_RX, + IWL_DEBUG_RX(priv, "r %d i %d No handler needed for %s, 0x%02x\n", r, i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); @@ -1175,7 +1175,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) if (priv->debug_level & IWL_DL_ISR) { /* just for debug */ inta_mask = iwl_read32(priv, CSR_INT_MASK); - IWL_DEBUG_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", + IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", inta, inta_mask, inta_fh); } #endif @@ -1209,12 +1209,12 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) if (priv->debug_level & (IWL_DL_ISR)) { /* NIC fires this, but we don't use it, redundant with WAKEUP */ if (inta & CSR_INT_BIT_SCD) - IWL_DEBUG_ISR("Scheduler finished to transmit " + IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " "the frame/frames.\n"); /* Alive notification via Rx interrupt will do the real work */ if (inta & CSR_INT_BIT_ALIVE) - IWL_DEBUG_ISR("Alive interrupt\n"); + IWL_DEBUG_ISR(priv, "Alive interrupt\n"); } #endif /* Safely ignore these bits for debug checks below */ @@ -1227,7 +1227,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) hw_rf_kill = 1; - IWL_DEBUG(IWL_DL_RF_KILL, "RF_KILL bit toggled to %s.\n", + IWL_DEBUG_RF_KILL(priv, "RF_KILL bit toggled to %s.\n", hw_rf_kill ? "disable radio" : "enable radio"); /* driver only loads ucode once setting the interface up. @@ -1262,7 +1262,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) /* uCode wakes up after power-down sleep */ if (inta & CSR_INT_BIT_WAKEUP) { - IWL_DEBUG_ISR("Wakeup interrupt\n"); + IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); iwl_rx_queue_update_write_ptr(priv, &priv->rxq); iwl_txq_update_write_ptr(priv, &priv->txq[0]); iwl_txq_update_write_ptr(priv, &priv->txq[1]); @@ -1283,7 +1283,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) } if (inta & CSR_INT_BIT_FH_TX) { - IWL_DEBUG_ISR("Tx interrupt\n"); + IWL_DEBUG_ISR(priv, "Tx interrupt\n"); handled |= CSR_INT_BIT_FH_TX; /* FH finished to write, send event */ priv->ucode_write_complete = 1; @@ -1309,7 +1309,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) inta = iwl_read32(priv, CSR_INT); inta_mask = iwl_read32(priv, CSR_INT_MASK); inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); - IWL_DEBUG_ISR("End inta 0x%08x, enabled 0x%08x, fh 0x%08x, " + IWL_DEBUG_ISR(priv, "End inta 0x%08x, enabled 0x%08x, fh 0x%08x, " "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags); } #endif @@ -1341,7 +1341,7 @@ static irqreturn_t iwl_isr(int irq, void *data) * This may be due to IRQ shared with another device, * or due to sporadic interrupts thrown from our NIC. */ if (!inta && !inta_fh) { - IWL_DEBUG_ISR("Ignore interrupt, inta == 0, inta_fh == 0\n"); + IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0, inta_fh == 0\n"); goto none; } @@ -1352,7 +1352,7 @@ static irqreturn_t iwl_isr(int irq, void *data) goto unplugged; } - IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", + IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", inta, inta_mask, inta_fh); inta &= ~CSR_INT_BIT_SCD; @@ -1434,7 +1434,7 @@ static int iwl_read_ucode(struct iwl_priv *priv) "Please use API v%u instead.\n", buf, api_max); - IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n", + IWL_DEBUG_INFO(priv, "Got firmware '%s' file (%zd bytes) from disk\n", buf, ucode_raw->size); break; } @@ -1485,17 +1485,17 @@ static int iwl_read_ucode(struct iwl_priv *priv) IWL_UCODE_API(priv->ucode_ver), IWL_UCODE_SERIAL(priv->ucode_ver)); - IWL_DEBUG_INFO("f/w package hdr ucode version raw = 0x%x\n", + IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", priv->ucode_ver); - IWL_DEBUG_INFO("f/w package hdr runtime inst size = %u\n", + IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n", inst_size); - IWL_DEBUG_INFO("f/w package hdr runtime data size = %u\n", + IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %u\n", data_size); - IWL_DEBUG_INFO("f/w package hdr init inst size = %u\n", + IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %u\n", init_size); - IWL_DEBUG_INFO("f/w package hdr init data size = %u\n", + IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %u\n", init_data_size); - IWL_DEBUG_INFO("f/w package hdr boot inst size = %u\n", + IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %u\n", boot_size); /* Verify size of file vs. image size info in file's header */ @@ -1503,7 +1503,7 @@ static int iwl_read_ucode(struct iwl_priv *priv) inst_size + data_size + init_size + init_data_size + boot_size) { - IWL_DEBUG_INFO("uCode file size %d too small\n", + IWL_DEBUG_INFO(priv, "uCode file size %d too small\n", (int)ucode_raw->size); ret = -EINVAL; goto err_release; @@ -1511,36 +1511,33 @@ static int iwl_read_ucode(struct iwl_priv *priv) /* Verify that uCode images will fit in card's SRAM */ if (inst_size > priv->hw_params.max_inst_size) { - IWL_DEBUG_INFO("uCode instr len %d too large to fit in\n", + IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n", inst_size); ret = -EINVAL; goto err_release; } if (data_size > priv->hw_params.max_data_size) { - IWL_DEBUG_INFO("uCode data len %d too large to fit in\n", + IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n", data_size); ret = -EINVAL; goto err_release; } if (init_size > priv->hw_params.max_inst_size) { - IWL_DEBUG_INFO - ("uCode init instr len %d too large to fit in\n", - init_size); + IWL_INFO(priv, "uCode init instr len %d too large to fit in\n", + init_size); ret = -EINVAL; goto err_release; } if (init_data_size > priv->hw_params.max_data_size) { - IWL_DEBUG_INFO - ("uCode init data len %d too large to fit in\n", + IWL_INFO(priv, "uCode init data len %d too large to fit in\n", init_data_size); ret = -EINVAL; goto err_release; } if (boot_size > priv->hw_params.max_bsm_size) { - IWL_DEBUG_INFO - ("uCode boot instr len %d too large to fit in\n", - boot_size); + IWL_INFO(priv, "uCode boot instr len %d too large to fit in\n", + boot_size); ret = -EINVAL; goto err_release; } @@ -1589,16 +1586,16 @@ static int iwl_read_ucode(struct iwl_priv *priv) /* Runtime instructions (first block of data in file) */ src = &ucode->data[0]; len = priv->ucode_code.len; - IWL_DEBUG_INFO("Copying (but not loading) uCode instr len %Zd\n", len); + IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n", len); memcpy(priv->ucode_code.v_addr, src, len); - IWL_DEBUG_INFO("uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", + IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); /* Runtime data (2nd block) * NOTE: Copy into backup buffer will be done in iwl_up() */ src = &ucode->data[inst_size]; len = priv->ucode_data.len; - IWL_DEBUG_INFO("Copying (but not loading) uCode data len %Zd\n", len); + IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", len); memcpy(priv->ucode_data.v_addr, src, len); memcpy(priv->ucode_data_backup.v_addr, src, len); @@ -1606,7 +1603,7 @@ static int iwl_read_ucode(struct iwl_priv *priv) if (init_size) { src = &ucode->data[inst_size + data_size]; len = priv->ucode_init.len; - IWL_DEBUG_INFO("Copying (but not loading) init instr len %Zd\n", + IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n", len); memcpy(priv->ucode_init.v_addr, src, len); } @@ -1615,7 +1612,7 @@ static int iwl_read_ucode(struct iwl_priv *priv) if (init_data_size) { src = &ucode->data[inst_size + data_size + init_size]; len = priv->ucode_init_data.len; - IWL_DEBUG_INFO("Copying (but not loading) init data len %Zd\n", + IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n", len); memcpy(priv->ucode_init_data.v_addr, src, len); } @@ -1623,7 +1620,7 @@ static int iwl_read_ucode(struct iwl_priv *priv) /* Bootstrap instructions (5th block) */ src = &ucode->data[inst_size + data_size + init_size + init_data_size]; len = priv->ucode_boot.len; - IWL_DEBUG_INFO("Copying (but not loading) boot instr len %Zd\n", len); + IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", len); memcpy(priv->ucode_boot.v_addr, src, len); /* We have our copies now, allow OS release its copies */ @@ -1655,12 +1652,12 @@ static void iwl_alive_start(struct iwl_priv *priv) { int ret = 0; - IWL_DEBUG_INFO("Runtime Alive received.\n"); + IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); if (priv->card_alive.is_valid != UCODE_VALID_OK) { /* We had an error bringing up the hardware, so take it * all the way back down so we can try again */ - IWL_DEBUG_INFO("Alive failed.\n"); + IWL_DEBUG_INFO(priv, "Alive failed.\n"); goto restart; } @@ -1670,7 +1667,7 @@ static void iwl_alive_start(struct iwl_priv *priv) if (iwl_verify_ucode(priv)) { /* Runtime instruction load was bad; * take it all the way back down so we can try again */ - IWL_DEBUG_INFO("Bad runtime uCode load.\n"); + IWL_DEBUG_INFO(priv, "Bad runtime uCode load.\n"); goto restart; } @@ -1720,7 +1717,7 @@ static void iwl_alive_start(struct iwl_priv *priv) iwl_leds_register(priv); - IWL_DEBUG_INFO("ALIVE processing complete.\n"); + IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); set_bit(STATUS_READY, &priv->status); wake_up_interruptible(&priv->wait_command_queue); @@ -1754,7 +1751,7 @@ static void __iwl_down(struct iwl_priv *priv) unsigned long flags; int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status); - IWL_DEBUG_INFO(DRV_NAME " is going down\n"); + IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n"); if (!exit_pending) set_bit(STATUS_EXIT_PENDING, &priv->status); @@ -1935,7 +1932,7 @@ static int __iwl_up(struct iwl_priv *priv) /* start card; "initialize" will load runtime ucode */ iwl_nic_start(priv); - IWL_DEBUG_INFO(DRV_NAME " is coming up\n"); + IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n"); return 0; } @@ -2056,7 +2053,7 @@ static void iwl_post_associate(struct iwl_priv *priv) return; } - IWL_DEBUG_ASSOC("Associated as %d to: %pM\n", + IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", priv->assoc_id, priv->active_rxon.bssid_addr); @@ -2089,7 +2086,7 @@ static void iwl_post_associate(struct iwl_priv *priv) iwl_set_rxon_chain(priv); priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); - IWL_DEBUG_ASSOC("assoc id %d beacon interval %d\n", + IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", priv->assoc_id, priv->beacon_int); if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) @@ -2162,7 +2159,7 @@ static int iwl_mac_start(struct ieee80211_hw *hw) struct iwl_priv *priv = hw->priv; int ret; - IWL_DEBUG_MAC80211("enter\n"); + IWL_DEBUG_MAC80211(priv, "enter\n"); /* we should be verifying the device is ready to be opened */ mutex_lock(&priv->mutex); @@ -2192,7 +2189,7 @@ static int iwl_mac_start(struct ieee80211_hw *hw) if (iwl_is_rfkill(priv)) goto out; - IWL_DEBUG_INFO("Start UP work done.\n"); + IWL_DEBUG_INFO(priv, "Start UP work done.\n"); if (test_bit(STATUS_IN_SUSPEND, &priv->status)) return 0; @@ -2212,7 +2209,7 @@ static int iwl_mac_start(struct ieee80211_hw *hw) out: priv->is_open = 1; - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); return 0; } @@ -2220,10 +2217,10 @@ static void iwl_mac_stop(struct ieee80211_hw *hw) { struct iwl_priv *priv = hw->priv; - IWL_DEBUG_MAC80211("enter\n"); + IWL_DEBUG_MAC80211(priv, "enter\n"); if (!priv->is_open) { - IWL_DEBUG_MAC80211("leave - skip\n"); + IWL_DEBUG_MAC80211(priv, "leave - skip\n"); return; } @@ -2246,22 +2243,22 @@ static void iwl_mac_stop(struct ieee80211_hw *hw) iwl_write32(priv, CSR_INT, 0xFFFFFFFF); iwl_enable_interrupts(priv); - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); } static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct iwl_priv *priv = hw->priv; - IWL_DEBUG_MACDUMP("enter\n"); + IWL_DEBUG_MACDUMP(priv, "enter\n"); - IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, + IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); if (iwl_tx_skb(priv, skb)) dev_kfree_skb_any(skb); - IWL_DEBUG_MACDUMP("leave\n"); + IWL_DEBUG_MACDUMP(priv, "leave\n"); return NETDEV_TX_OK; } @@ -2271,10 +2268,10 @@ static int iwl_mac_add_interface(struct ieee80211_hw *hw, struct iwl_priv *priv = hw->priv; unsigned long flags; - IWL_DEBUG_MAC80211("enter: type %d\n", conf->type); + IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type); if (priv->vif) { - IWL_DEBUG_MAC80211("leave - vif != NULL\n"); + IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); return -EOPNOTSUPP; } @@ -2287,7 +2284,7 @@ static int iwl_mac_add_interface(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); if (conf->mac_addr) { - IWL_DEBUG_MAC80211("Set %pM\n", conf->mac_addr); + IWL_DEBUG_MAC80211(priv, "Set %pM\n", conf->mac_addr); memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); } @@ -2297,7 +2294,7 @@ static int iwl_mac_add_interface(struct ieee80211_hw *hw, mutex_unlock(&priv->mutex); - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); return 0; } @@ -2318,12 +2315,12 @@ static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) u16 channel; mutex_lock(&priv->mutex); - IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value); + IWL_DEBUG_MAC80211(priv, "enter to channel %d\n", conf->channel->hw_value); priv->current_ht_config.is_ht = conf_is_ht(conf); if (conf->radio_enabled && iwl_radio_kill_sw_enable_radio(priv)) { - IWL_DEBUG_MAC80211("leave - RF-KILL - waiting for uCode\n"); + IWL_DEBUG_MAC80211(priv, "leave - RF-KILL - waiting for uCode\n"); goto out; } @@ -2331,14 +2328,14 @@ static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) iwl_radio_kill_sw_disable_radio(priv); if (!iwl_is_ready(priv)) { - IWL_DEBUG_MAC80211("leave - not ready\n"); + IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); ret = -EIO; goto out; } if (unlikely(!priv->cfg->mod_params->disable_hw_scan && test_bit(STATUS_SCANNING, &priv->status))) { - IWL_DEBUG_MAC80211("leave - scanning\n"); + IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); mutex_unlock(&priv->mutex); return 0; } @@ -2346,7 +2343,7 @@ static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) channel = ieee80211_frequency_to_channel(conf->channel->center_freq); ch_info = iwl_get_channel_info(priv, conf->channel->band, channel); if (!is_channel_valid(ch_info)) { - IWL_DEBUG_MAC80211("leave - invalid channel\n"); + IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); ret = -EINVAL; goto out; } @@ -2391,12 +2388,12 @@ static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) #endif if (!conf->radio_enabled) { - IWL_DEBUG_MAC80211("leave - radio disabled\n"); + IWL_DEBUG_MAC80211(priv, "leave - radio disabled\n"); goto out; } if (iwl_is_rfkill(priv)) { - IWL_DEBUG_MAC80211("leave - RF kill\n"); + IWL_DEBUG_MAC80211(priv, "leave - RF kill\n"); ret = -EIO; goto out; } @@ -2406,9 +2403,9 @@ static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) else ret = iwl_power_set_user_mode(priv, IWL_POWER_MODE_CAM); if (ret) - IWL_DEBUG_MAC80211("Error setting power level\n"); + IWL_DEBUG_MAC80211(priv, "Error setting power level\n"); - IWL_DEBUG_MAC80211("TX Power old=%d new=%d\n", + IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n", priv->tx_power_user_lmt, conf->power_level); iwl_set_tx_power(priv, conf->power_level, false); @@ -2422,9 +2419,9 @@ static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) &priv->staging_rxon, sizeof(priv->staging_rxon))) iwl_commit_rxon(priv); else - IWL_DEBUG_INFO("No re-sending same RXON configuration.\n"); + IWL_DEBUG_INFO(priv, "No re-sending same RXON configuration.\n"); - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); out: mutex_unlock(&priv->mutex); @@ -2505,7 +2502,7 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, return -EIO; if (priv->vif != vif) { - IWL_DEBUG_MAC80211("leave - priv->vif != vif\n"); + IWL_DEBUG_MAC80211(priv, "leave - priv->vif != vif\n"); return 0; } @@ -2527,7 +2524,7 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); if (conf->bssid) - IWL_DEBUG_MAC80211("bssid: %pM\n", conf->bssid); + IWL_DEBUG_MAC80211(priv, "bssid: %pM\n", conf->bssid); /* * very dubious code was here; the probe filtering flag is never set: @@ -2540,7 +2537,7 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, if (!conf->bssid) { conf->bssid = priv->mac_addr; memcpy(priv->bssid, priv->mac_addr, ETH_ALEN); - IWL_DEBUG_MAC80211("bssid was set to: %pM\n", + IWL_DEBUG_MAC80211(priv, "bssid was set to: %pM\n", conf->bssid); } if (priv->ibss_beacon) @@ -2559,7 +2556,7 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, if (iwl_scan_cancel_timeout(priv, 100)) { IWL_WARN(priv, "Aborted scan still in progress " "after 100ms\n"); - IWL_DEBUG_MAC80211("leaving - scan abort failed.\n"); + IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n"); mutex_unlock(&priv->mutex); return -EAGAIN; } @@ -2587,7 +2584,7 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, } done: - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); mutex_unlock(&priv->mutex); return 0; @@ -2598,7 +2595,7 @@ static void iwl_mac_remove_interface(struct ieee80211_hw *hw, { struct iwl_priv *priv = hw->priv; - IWL_DEBUG_MAC80211("enter\n"); + IWL_DEBUG_MAC80211(priv, "enter\n"); mutex_lock(&priv->mutex); @@ -2613,7 +2610,7 @@ static void iwl_mac_remove_interface(struct ieee80211_hw *hw, } mutex_unlock(&priv->mutex); - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); } @@ -2625,10 +2622,10 @@ static void iwl_bss_info_changed(struct ieee80211_hw *hw, { struct iwl_priv *priv = hw->priv; - IWL_DEBUG_MAC80211("changes = 0x%X\n", changes); + IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes); if (changes & BSS_CHANGED_ERP_PREAMBLE) { - IWL_DEBUG_MAC80211("ERP_PREAMBLE %d\n", + IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n", bss_conf->use_short_preamble); if (bss_conf->use_short_preamble) priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; @@ -2637,7 +2634,7 @@ static void iwl_bss_info_changed(struct ieee80211_hw *hw, } if (changes & BSS_CHANGED_ERP_CTS_PROT) { - IWL_DEBUG_MAC80211("ERP_CTS %d\n", bss_conf->use_cts_prot); + IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot); if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; else @@ -2650,7 +2647,7 @@ static void iwl_bss_info_changed(struct ieee80211_hw *hw, } if (changes & BSS_CHANGED_ASSOC) { - IWL_DEBUG_MAC80211("ASSOC %d\n", bss_conf->assoc); + IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc); /* This should never happen as this function should * never be called from interrupt context. */ if (WARN_ON_ONCE(in_interrupt())) @@ -2672,10 +2669,10 @@ static void iwl_bss_info_changed(struct ieee80211_hw *hw, mutex_unlock(&priv->mutex); } else { priv->assoc_id = 0; - IWL_DEBUG_MAC80211("DISASSOC %d\n", bss_conf->assoc); + IWL_DEBUG_MAC80211(priv, "DISASSOC %d\n", bss_conf->assoc); } } else if (changes && iwl_is_associated(priv) && priv->assoc_id) { - IWL_DEBUG_MAC80211("Associated Changes %d\n", changes); + IWL_DEBUG_MAC80211(priv, "Associated Changes %d\n", changes); iwl_send_rxon_assoc(priv); } @@ -2687,14 +2684,14 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t ssid_len) struct iwl_priv *priv = hw->priv; int ret; - IWL_DEBUG_MAC80211("enter\n"); + IWL_DEBUG_MAC80211(priv, "enter\n"); mutex_lock(&priv->mutex); spin_lock_irqsave(&priv->lock, flags); if (!iwl_is_ready_rf(priv)) { ret = -EIO; - IWL_DEBUG_MAC80211("leave - not ready or exit pending\n"); + IWL_DEBUG_MAC80211(priv, "leave - not ready or exit pending\n"); goto out_unlock; } @@ -2704,7 +2701,7 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t ssid_len) */ if (priv->next_scan_jiffies && time_after(priv->next_scan_jiffies, jiffies)) { - IWL_DEBUG_SCAN("scan rejected: within next scan period\n"); + IWL_DEBUG_SCAN(priv, "scan rejected: within next scan period\n"); queue_work(priv->workqueue, &priv->scan_completed); ret = 0; goto out_unlock; @@ -2713,7 +2710,7 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t ssid_len) /* if we just finished scan ask for delay */ if (iwl_is_associated(priv) && priv->last_scan_jiffies && time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN, jiffies)) { - IWL_DEBUG_SCAN("scan rejected: within previous scan period\n"); + IWL_DEBUG_SCAN(priv, "scan rejected: within previous scan period\n"); queue_work(priv->workqueue, &priv->scan_completed); ret = 0; goto out_unlock; @@ -2729,7 +2726,7 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t ssid_len) ret = iwl_scan_initiate(priv); - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); out_unlock: spin_unlock_irqrestore(&priv->lock, flags); @@ -2744,11 +2741,11 @@ static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, { struct iwl_priv *priv = hw->priv; - IWL_DEBUG_MAC80211("enter\n"); + IWL_DEBUG_MAC80211(priv, "enter\n"); iwl_update_tkip_key(priv, keyconf, addr, iv32, phase1key); - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); } static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, @@ -2762,16 +2759,16 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, u8 sta_id; bool is_default_wep_key = false; - IWL_DEBUG_MAC80211("enter\n"); + IWL_DEBUG_MAC80211(priv, "enter\n"); if (priv->hw_params.sw_crypto) { - IWL_DEBUG_MAC80211("leave - hwcrypto disabled\n"); + IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n"); return -EOPNOTSUPP; } addr = sta ? sta->addr : iwl_bcast_addr; sta_id = iwl_find_station(priv, addr); if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_MAC80211("leave - %pM not in station map.\n", + IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", addr); return -EINVAL; @@ -2801,7 +2798,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, else ret = iwl_set_dynamic_key(priv, key, sta_id); - IWL_DEBUG_MAC80211("enable hwcrypto key\n"); + IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n"); break; case DISABLE_KEY: if (is_default_wep_key) @@ -2809,13 +2806,13 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, else ret = iwl_remove_dynamic_key(priv, key, sta_id); - IWL_DEBUG_MAC80211("disable hwcrypto key\n"); + IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n"); break; default: ret = -EINVAL; } - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); return ret; } @@ -2827,15 +2824,15 @@ static int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, unsigned long flags; int q; - IWL_DEBUG_MAC80211("enter\n"); + IWL_DEBUG_MAC80211(priv, "enter\n"); if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211("leave - RF not ready\n"); + IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); return -EIO; } if (queue >= AC_NUM) { - IWL_DEBUG_MAC80211("leave - queue >= AC_NUM %d\n", queue); + IWL_DEBUG_MAC80211(priv, "leave - queue >= AC_NUM %d\n", queue); return 0; } @@ -2859,7 +2856,7 @@ static int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, spin_unlock_irqrestore(&priv->lock, flags); - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); return 0; } @@ -2869,7 +2866,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, { struct iwl_priv *priv = hw->priv; - IWL_DEBUG_HT("A-MPDU action on addr %pM tid %d\n", + IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", sta->addr, tid); if (!(priv->cfg->sku & IWL_SKU_N)) @@ -2877,19 +2874,19 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, switch (action) { case IEEE80211_AMPDU_RX_START: - IWL_DEBUG_HT("start Rx\n"); + IWL_DEBUG_HT(priv, "start Rx\n"); return iwl_sta_rx_agg_start(priv, sta->addr, tid, *ssn); case IEEE80211_AMPDU_RX_STOP: - IWL_DEBUG_HT("stop Rx\n"); + IWL_DEBUG_HT(priv, "stop Rx\n"); return iwl_sta_rx_agg_stop(priv, sta->addr, tid); case IEEE80211_AMPDU_TX_START: - IWL_DEBUG_HT("start Tx\n"); + IWL_DEBUG_HT(priv, "start Tx\n"); return iwl_tx_agg_start(priv, sta->addr, tid, ssn); case IEEE80211_AMPDU_TX_STOP: - IWL_DEBUG_HT("stop Tx\n"); + IWL_DEBUG_HT(priv, "stop Tx\n"); return iwl_tx_agg_stop(priv, sta->addr, tid); default: - IWL_DEBUG_HT("unknown\n"); + IWL_DEBUG_HT(priv, "unknown\n"); return -EINVAL; break; } @@ -2905,10 +2902,10 @@ static int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, struct iwl_queue *q; unsigned long flags; - IWL_DEBUG_MAC80211("enter\n"); + IWL_DEBUG_MAC80211(priv, "enter\n"); if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211("leave - RF not ready\n"); + IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); return -EIO; } @@ -2926,7 +2923,7 @@ static int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, } spin_unlock_irqrestore(&priv->lock, flags); - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); return 0; } @@ -2937,8 +2934,8 @@ static int iwl_mac_get_stats(struct ieee80211_hw *hw, struct iwl_priv *priv = hw->priv; priv = hw->priv; - IWL_DEBUG_MAC80211("enter\n"); - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "enter\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); return 0; } @@ -2949,7 +2946,7 @@ static void iwl_mac_reset_tsf(struct ieee80211_hw *hw) unsigned long flags; mutex_lock(&priv->mutex); - IWL_DEBUG_MAC80211("enter\n"); + IWL_DEBUG_MAC80211(priv, "enter\n"); spin_lock_irqsave(&priv->lock, flags); memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info)); @@ -2976,7 +2973,7 @@ static void iwl_mac_reset_tsf(struct ieee80211_hw *hw) spin_unlock_irqrestore(&priv->lock, flags); if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211("leave - not ready\n"); + IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); mutex_unlock(&priv->mutex); return; } @@ -3005,7 +3002,7 @@ static void iwl_mac_reset_tsf(struct ieee80211_hw *hw) IEEE80211_CHAN_RADAR)) iwl_power_disable_management(priv, 3000); - IWL_DEBUG_MAC80211("leave - not in IBSS\n"); + IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n"); mutex_unlock(&priv->mutex); return; } @@ -3014,7 +3011,7 @@ static void iwl_mac_reset_tsf(struct ieee80211_hw *hw) mutex_unlock(&priv->mutex); - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); } static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) @@ -3023,15 +3020,15 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) unsigned long flags; __le64 timestamp; - IWL_DEBUG_MAC80211("enter\n"); + IWL_DEBUG_MAC80211(priv, "enter\n"); if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211("leave - RF not ready\n"); + IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); return -EIO; } if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { - IWL_DEBUG_MAC80211("leave - not IBSS\n"); + IWL_DEBUG_MAC80211(priv, "leave - not IBSS\n"); return -EIO; } @@ -3046,7 +3043,7 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; priv->timestamp = le64_to_cpu(timestamp); - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); spin_unlock_irqrestore(&priv->lock, flags); iwl_reset_qos(priv); @@ -3204,7 +3201,7 @@ static ssize_t store_flags(struct device *d, if (iwl_scan_cancel_timeout(priv, 100)) IWL_WARN(priv, "Could not cancel scan.\n"); else { - IWL_DEBUG_INFO("Commit rxon.flags = 0x%04X\n", flags); + IWL_DEBUG_INFO(priv, "Commit rxon.flags = 0x%04X\n", flags); priv->staging_rxon.flags = cpu_to_le32(flags); iwl_commit_rxon(priv); } @@ -3243,7 +3240,7 @@ static ssize_t store_filter_flags(struct device *d, if (iwl_scan_cancel_timeout(priv, 100)) IWL_WARN(priv, "Could not cancel scan.\n"); else { - IWL_DEBUG_INFO("Committing rxon.filter_flags = " + IWL_DEBUG_INFO(priv, "Committing rxon.filter_flags = " "0x%04X\n", filter_flags); priv->staging_rxon.filter_flags = cpu_to_le32(filter_flags); @@ -3280,7 +3277,7 @@ static ssize_t store_power_level(struct device *d, ret = iwl_power_set_user_mode(priv, mode); if (ret) { - IWL_DEBUG_MAC80211("failed setting power mode.\n"); + IWL_DEBUG_MAC80211(priv, "failed setting power mode.\n"); goto out; } ret = count; @@ -3481,7 +3478,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) SET_IEEE80211_DEV(hw, &pdev->dev); - IWL_DEBUG_INFO("*** LOAD DRIVER ***\n"); + IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); priv->cfg = cfg; priv->pci_dev = pdev; @@ -3530,9 +3527,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_pci_release_regions; } - IWL_DEBUG_INFO("pci_resource_len = 0x%08llx\n", + IWL_DEBUG_INFO(priv, "pci_resource_len = 0x%08llx\n", (unsigned long long) pci_resource_len(pdev, 0)); - IWL_DEBUG_INFO("pci_resource_base = %p\n", priv->hw_base); + IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base); iwl_hw_detect(priv); IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n", @@ -3545,7 +3542,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* amp init */ err = priv->cfg->ops->lib->apm_ops.init(priv); if (err < 0) { - IWL_DEBUG_INFO("Failed to init APMG\n"); + IWL_DEBUG_INFO(priv, "Failed to init APMG\n"); goto out_iounmap; } /***************** @@ -3563,7 +3560,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* extract MAC Address */ iwl_eeprom_get_mac(priv, priv->mac_addr); - IWL_DEBUG_INFO("MAC address: %pM\n", priv->mac_addr); + IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->mac_addr); SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); /************************ @@ -3590,7 +3587,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Disable radio (SW RF KILL) via parameter when loading driver */ if (priv->cfg->mod_params->disable) { set_bit(STATUS_RF_KILL_SW, &priv->status); - IWL_DEBUG_INFO("Radio disabled.\n"); + IWL_DEBUG_INFO(priv, "Radio disabled.\n"); } /******************** @@ -3684,7 +3681,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) if (!priv) return; - IWL_DEBUG_INFO("*** UNLOAD DRIVER ***\n"); + IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); iwl_dbgfs_unregister(priv); sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group); diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index 8e5e6663be3..d06c57764e1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c @@ -202,7 +202,7 @@ static int iwl_sens_energy_cck(struct iwl_priv *priv, val = data->nrg_silence_rssi[i]; silence_ref = max(silence_ref, val); } - IWL_DEBUG_CALIB("silence a %u, b %u, c %u, 20-bcn max %u\n", + IWL_DEBUG_CALIB(priv, "silence a %u, b %u, c %u, 20-bcn max %u\n", silence_rssi_a, silence_rssi_b, silence_rssi_c, silence_ref); @@ -226,7 +226,7 @@ static int iwl_sens_energy_cck(struct iwl_priv *priv, max_nrg_cck = (u32) max(max_nrg_cck, (data->nrg_value[i])); max_nrg_cck += 6; - IWL_DEBUG_CALIB("rx energy a %u, b %u, c %u, 10-bcn max/min %u\n", + IWL_DEBUG_CALIB(priv, "rx energy a %u, b %u, c %u, 10-bcn max/min %u\n", rx_info->beacon_energy_a, rx_info->beacon_energy_b, rx_info->beacon_energy_c, max_nrg_cck - 6); @@ -236,15 +236,15 @@ static int iwl_sens_energy_cck(struct iwl_priv *priv, data->num_in_cck_no_fa++; else data->num_in_cck_no_fa = 0; - IWL_DEBUG_CALIB("consecutive bcns with few false alarms = %u\n", + IWL_DEBUG_CALIB(priv, "consecutive bcns with few false alarms = %u\n", data->num_in_cck_no_fa); /* If we got too many false alarms this time, reduce sensitivity */ if ((false_alarms > max_false_alarms) && (data->auto_corr_cck > AUTO_CORR_MAX_TH_CCK)) { - IWL_DEBUG_CALIB("norm FA %u > max FA %u\n", + IWL_DEBUG_CALIB(priv, "norm FA %u > max FA %u\n", false_alarms, max_false_alarms); - IWL_DEBUG_CALIB("... reducing sensitivity\n"); + IWL_DEBUG_CALIB(priv, "... reducing sensitivity\n"); data->nrg_curr_state = IWL_FA_TOO_MANY; /* Store for "fewer than desired" on later beacon */ data->nrg_silence_ref = silence_ref; @@ -266,7 +266,7 @@ static int iwl_sens_energy_cck(struct iwl_priv *priv, data->nrg_auto_corr_silence_diff = (s32)data->nrg_silence_ref - (s32)silence_ref; - IWL_DEBUG_CALIB("norm FA %u < min FA %u, silence diff %d\n", + IWL_DEBUG_CALIB(priv, "norm FA %u < min FA %u, silence diff %d\n", false_alarms, min_false_alarms, data->nrg_auto_corr_silence_diff); @@ -280,17 +280,17 @@ static int iwl_sens_energy_cck(struct iwl_priv *priv, ((data->nrg_auto_corr_silence_diff > NRG_DIFF) || (data->num_in_cck_no_fa > MAX_NUMBER_CCK_NO_FA))) { - IWL_DEBUG_CALIB("... increasing sensitivity\n"); + IWL_DEBUG_CALIB(priv, "... increasing sensitivity\n"); /* Increase nrg value to increase sensitivity */ val = data->nrg_th_cck + NRG_STEP_CCK; data->nrg_th_cck = min((u32)ranges->min_nrg_cck, val); } else { - IWL_DEBUG_CALIB("... but not changing sensitivity\n"); + IWL_DEBUG_CALIB(priv, "... but not changing sensitivity\n"); } /* Else we got a healthy number of false alarms, keep status quo */ } else { - IWL_DEBUG_CALIB(" FA in safe zone\n"); + IWL_DEBUG_CALIB(priv, " FA in safe zone\n"); data->nrg_curr_state = IWL_FA_GOOD_RANGE; /* Store for use in "fewer than desired" with later beacon */ @@ -300,7 +300,7 @@ static int iwl_sens_energy_cck(struct iwl_priv *priv, * give it some extra margin by reducing sensitivity again * (but don't go below measured energy of desired Rx) */ if (IWL_FA_TOO_MANY == data->nrg_prev_state) { - IWL_DEBUG_CALIB("... increasing margin\n"); + IWL_DEBUG_CALIB(priv, "... increasing margin\n"); if (data->nrg_th_cck > (max_nrg_cck + NRG_MARGIN)) data->nrg_th_cck -= NRG_MARGIN; else @@ -314,7 +314,7 @@ static int iwl_sens_energy_cck(struct iwl_priv *priv, * Lower value is higher energy, so we use max()! */ data->nrg_th_cck = max(max_nrg_cck, data->nrg_th_cck); - IWL_DEBUG_CALIB("new nrg_th_cck %u\n", data->nrg_th_cck); + IWL_DEBUG_CALIB(priv, "new nrg_th_cck %u\n", data->nrg_th_cck); data->nrg_prev_state = data->nrg_curr_state; @@ -367,7 +367,7 @@ static int iwl_sens_auto_corr_ofdm(struct iwl_priv *priv, /* If we got too many false alarms this time, reduce sensitivity */ if (false_alarms > max_false_alarms) { - IWL_DEBUG_CALIB("norm FA %u > max FA %u)\n", + IWL_DEBUG_CALIB(priv, "norm FA %u > max FA %u)\n", false_alarms, max_false_alarms); val = data->auto_corr_ofdm + AUTO_CORR_STEP_OFDM; @@ -390,7 +390,7 @@ static int iwl_sens_auto_corr_ofdm(struct iwl_priv *priv, /* Else if we got fewer than desired, increase sensitivity */ else if (false_alarms < min_false_alarms) { - IWL_DEBUG_CALIB("norm FA %u < min FA %u\n", + IWL_DEBUG_CALIB(priv, "norm FA %u < min FA %u\n", false_alarms, min_false_alarms); val = data->auto_corr_ofdm - AUTO_CORR_STEP_OFDM; @@ -409,7 +409,7 @@ static int iwl_sens_auto_corr_ofdm(struct iwl_priv *priv, data->auto_corr_ofdm_mrc_x1 = max((u32)ranges->auto_corr_min_ofdm_mrc_x1, val); } else { - IWL_DEBUG_CALIB("min FA %u < norm FA %u < max FA %u OK\n", + IWL_DEBUG_CALIB(priv, "min FA %u < norm FA %u < max FA %u OK\n", min_false_alarms, false_alarms, max_false_alarms); } return 0; @@ -458,12 +458,12 @@ static int iwl_sensitivity_write(struct iwl_priv *priv) cmd.table[HD_OFDM_ENERGY_TH_IN_INDEX] = __constant_cpu_to_le16(62); - IWL_DEBUG_CALIB("ofdm: ac %u mrc %u x1 %u mrc_x1 %u thresh %u\n", + IWL_DEBUG_CALIB(priv, "ofdm: ac %u mrc %u x1 %u mrc_x1 %u thresh %u\n", data->auto_corr_ofdm, data->auto_corr_ofdm_mrc, data->auto_corr_ofdm_x1, data->auto_corr_ofdm_mrc_x1, data->nrg_th_ofdm); - IWL_DEBUG_CALIB("cck: ac %u mrc %u thresh %u\n", + IWL_DEBUG_CALIB(priv, "cck: ac %u mrc %u thresh %u\n", data->auto_corr_cck, data->auto_corr_cck_mrc, data->nrg_th_cck); @@ -473,7 +473,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv) /* Don't send command to uCode if nothing has changed */ if (!memcmp(&cmd.table[0], &(priv->sensitivity_tbl[0]), sizeof(u16)*HD_TABLE_SIZE)) { - IWL_DEBUG_CALIB("No change in SENSITIVITY_CMD\n"); + IWL_DEBUG_CALIB(priv, "No change in SENSITIVITY_CMD\n"); return 0; } @@ -498,7 +498,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv) if (priv->disable_sens_cal) return; - IWL_DEBUG_CALIB("Start iwl_init_sensitivity\n"); + IWL_DEBUG_CALIB(priv, "Start iwl_init_sensitivity\n"); /* Clear driver's sensitivity algo data */ data = &(priv->sensitivity_data); @@ -536,7 +536,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv) data->last_fa_cnt_cck = 0; ret |= iwl_sensitivity_write(priv); - IWL_DEBUG_CALIB("<sensitivity_data); if (!iwl_is_associated(priv)) { - IWL_DEBUG_CALIB("<< - not associated\n"); + IWL_DEBUG_CALIB(priv, "<< - not associated\n"); return; } spin_lock_irqsave(&priv->lock, flags); if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { - IWL_DEBUG_CALIB("<< invalid data.\n"); + IWL_DEBUG_CALIB(priv, "<< invalid data.\n"); spin_unlock_irqrestore(&priv->lock, flags); return; } @@ -595,10 +595,10 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, spin_unlock_irqrestore(&priv->lock, flags); - IWL_DEBUG_CALIB("rx_enable_time = %u usecs\n", rx_enable_time); + IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time); if (!rx_enable_time) { - IWL_DEBUG_CALIB("<< RX Enable Time == 0! \n"); + IWL_DEBUG_CALIB(priv, "<< RX Enable Time == 0! \n"); return; } @@ -637,7 +637,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, norm_fa_ofdm = fa_ofdm + bad_plcp_ofdm; norm_fa_cck = fa_cck + bad_plcp_cck; - IWL_DEBUG_CALIB("cck: fa %u badp %u ofdm: fa %u badp %u\n", fa_cck, + IWL_DEBUG_CALIB(priv, "cck: fa %u badp %u ofdm: fa %u badp %u\n", fa_cck, bad_plcp_cck, fa_ofdm, bad_plcp_ofdm); iwl_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time); @@ -690,13 +690,13 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, * then we're done forever. */ if (data->state != IWL_CHAIN_NOISE_ACCUMULATE) { if (data->state == IWL_CHAIN_NOISE_ALIVE) - IWL_DEBUG_CALIB("Wait for noise calib reset\n"); + IWL_DEBUG_CALIB(priv, "Wait for noise calib reset\n"); return; } spin_lock_irqsave(&priv->lock, flags); if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { - IWL_DEBUG_CALIB(" << Interference data unavailable\n"); + IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n"); spin_unlock_irqrestore(&priv->lock, flags); return; } @@ -709,7 +709,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, /* Make sure we accumulate data for just the associated channel * (even if scanning). */ if ((rxon_chnum != stat_chnum) || (rxon_band24 != stat_band24)) { - IWL_DEBUG_CALIB("Stats not from chan=%d, band24=%d\n", + IWL_DEBUG_CALIB(priv, "Stats not from chan=%d, band24=%d\n", rxon_chnum, rxon_band24); spin_unlock_irqrestore(&priv->lock, flags); return; @@ -739,11 +739,11 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, data->chain_signal_b = (chain_sig_b + data->chain_signal_b); data->chain_signal_c = (chain_sig_c + data->chain_signal_c); - IWL_DEBUG_CALIB("chan=%d, band24=%d, beacon=%d\n", + IWL_DEBUG_CALIB(priv, "chan=%d, band24=%d, beacon=%d\n", rxon_chnum, rxon_band24, data->beacon_count); - IWL_DEBUG_CALIB("chain_sig: a %d b %d c %d\n", + IWL_DEBUG_CALIB(priv, "chain_sig: a %d b %d c %d\n", chain_sig_a, chain_sig_b, chain_sig_c); - IWL_DEBUG_CALIB("chain_noise: a %d b %d c %d\n", + IWL_DEBUG_CALIB(priv, "chain_noise: a %d b %d c %d\n", chain_noise_a, chain_noise_b, chain_noise_c); /* If this is the 20th beacon, determine: @@ -773,9 +773,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, active_chains = (1 << max_average_sig_antenna_i); } - IWL_DEBUG_CALIB("average_sig: a %d b %d c %d\n", + IWL_DEBUG_CALIB(priv, "average_sig: a %d b %d c %d\n", average_sig[0], average_sig[1], average_sig[2]); - IWL_DEBUG_CALIB("max_average_sig = %d, antenna %d\n", + IWL_DEBUG_CALIB(priv, "max_average_sig = %d, antenna %d\n", max_average_sig, max_average_sig_antenna_i); /* Compare signal strengths for all 3 receivers. */ @@ -789,7 +789,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, data->disconn_array[i] = 1; else active_chains |= (1 << i); - IWL_DEBUG_CALIB("i = %d rssiDelta = %d " + IWL_DEBUG_CALIB(priv, "i = %d rssiDelta = %d " "disconn_array[i] = %d\n", i, rssi_delta, data->disconn_array[i]); } @@ -813,7 +813,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, * disconnected connect it anyway */ data->disconn_array[i] = 0; active_chains |= ant_msk; - IWL_DEBUG_CALIB("All Tx chains are disconnected W/A - " + IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected W/A - " "declare %d as connected\n", i); break; } @@ -821,7 +821,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, /* Save for use within RXON, TX, SCAN commands, etc. */ priv->chain_noise_data.active_chains = active_chains; - IWL_DEBUG_CALIB("active_chains (bitwise) = 0x%x\n", + IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n", active_chains); /* Analyze noise for rx balance */ @@ -839,11 +839,11 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, } } - IWL_DEBUG_CALIB("average_noise: a %d b %d c %d\n", + IWL_DEBUG_CALIB(priv, "average_noise: a %d b %d c %d\n", average_noise[0], average_noise[1], average_noise[2]); - IWL_DEBUG_CALIB("min_average_noise = %d, antenna %d\n", + IWL_DEBUG_CALIB(priv, "min_average_noise = %d, antenna %d\n", min_average_noise, min_average_noise_antenna_i); priv->cfg->ops->utils->gain_computation(priv, average_noise, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 4f2b88c59c7..5f92cfbe926 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -323,7 +323,7 @@ void iwl_reset_qos(struct iwl_priv *priv) priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; } } - IWL_DEBUG_QOS("set QoS to default \n"); + IWL_DEBUG_QOS(priv, "set QoS to default \n"); spin_unlock_irqrestore(&priv->lock, flags); } @@ -419,7 +419,7 @@ int iwlcore_init_geos(struct iwl_priv *priv) if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { - IWL_DEBUG_INFO("Geography modes already initialized.\n"); + IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n"); set_bit(STATUS_GEO_CONFIGURED, &priv->status); return 0; } @@ -501,7 +501,7 @@ int iwlcore_init_geos(struct iwl_priv *priv) /* Save flags for reg domain usage */ geo_ch->orig_flags = geo_ch->flags; - IWL_DEBUG_INFO("Channel %d Freq=%d[%sGHz] %s flag=0x%X\n", + IWL_DEBUG_INFO(priv, "Channel %d Freq=%d[%sGHz] %s flag=0x%X\n", ch->channel, geo_ch->center_freq, is_channel_a_band(ch) ? "5.2" : "2.4", geo_ch->flags & IEEE80211_CHAN_DISABLED ? @@ -790,7 +790,7 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) iwl_set_rxon_chain(priv); - IWL_DEBUG_ASSOC("supported HT rate 0x%X 0x%X 0x%X " + IWL_DEBUG_ASSOC(priv, "supported HT rate 0x%X 0x%X 0x%X " "rxon flags 0x%X operation mode :0x%X " "extension channel offset 0x%x\n", ht_info->mcs.rx_mask[0], @@ -936,7 +936,7 @@ void iwl_set_rxon_chain(struct iwl_priv *priv) else priv->staging_rxon.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK; - IWL_DEBUG_ASSOC("rx_chain=0x%X active=%d idle=%d\n", + IWL_DEBUG_ASSOC(priv, "rx_chain=0x%X active=%d idle=%d\n", priv->staging_rxon.rx_chain, active_rx_cnt, idle_rx_cnt); @@ -961,7 +961,7 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch) u16 channel = ieee80211_frequency_to_channel(ch->center_freq); if (!iwl_get_channel_info(priv, band, channel)) { - IWL_DEBUG_INFO("Could not set channel to %d [%d]\n", + IWL_DEBUG_INFO(priv, "Could not set channel to %d [%d]\n", channel, band); return -EINVAL; } @@ -978,7 +978,7 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch) priv->band = band; - IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, band); + IWL_DEBUG_INFO(priv, "Staging channel set to %d [%d]\n", channel, band); return 0; } @@ -1108,7 +1108,7 @@ void iwl_set_rate(struct iwl_priv *priv) priv->active_rate |= (1 << rate->hw_value); } - IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n", + IWL_DEBUG_RATE(priv, "Set active_rate = %0x, active_rate_basic = %0x\n", priv->active_rate, priv->active_rate_basic); /* @@ -1140,7 +1140,7 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon; struct iwl_csa_notification *csa = &(pkt->u.csa_notif); - IWL_DEBUG_11H("CSA notif: channel %d, status %d\n", + IWL_DEBUG_11H(priv, "CSA notif: channel %d, status %d\n", le16_to_cpu(csa->channel), le32_to_cpu(csa->status)); rxon->channel = csa->channel; priv->staging_rxon.channel = csa->channel; @@ -1152,19 +1152,19 @@ static void iwl_print_rx_config_cmd(struct iwl_priv *priv) { struct iwl_rxon_cmd *rxon = &priv->staging_rxon; - IWL_DEBUG_RADIO("RX CONFIG:\n"); + IWL_DEBUG_RADIO(priv, "RX CONFIG:\n"); iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon)); - IWL_DEBUG_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel)); - IWL_DEBUG_RADIO("u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags)); - IWL_DEBUG_RADIO("u32 filter_flags: 0x%08x\n", + IWL_DEBUG_RADIO(priv, "u16 channel: 0x%x\n", le16_to_cpu(rxon->channel)); + IWL_DEBUG_RADIO(priv, "u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags)); + IWL_DEBUG_RADIO(priv, "u32 filter_flags: 0x%08x\n", le32_to_cpu(rxon->filter_flags)); - IWL_DEBUG_RADIO("u8 dev_type: 0x%x\n", rxon->dev_type); - IWL_DEBUG_RADIO("u8 ofdm_basic_rates: 0x%02x\n", + IWL_DEBUG_RADIO(priv, "u8 dev_type: 0x%x\n", rxon->dev_type); + IWL_DEBUG_RADIO(priv, "u8 ofdm_basic_rates: 0x%02x\n", rxon->ofdm_basic_rates); - IWL_DEBUG_RADIO("u8 cck_basic_rates: 0x%02x\n", rxon->cck_basic_rates); - IWL_DEBUG_RADIO("u8[6] node_addr: %pM\n", rxon->node_addr); - IWL_DEBUG_RADIO("u8[6] bssid_addr: %pM\n", rxon->bssid_addr); - IWL_DEBUG_RADIO("u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id)); + IWL_DEBUG_RADIO(priv, "u8 cck_basic_rates: 0x%02x\n", rxon->cck_basic_rates); + IWL_DEBUG_RADIO(priv, "u8[6] node_addr: %pM\n", rxon->node_addr); + IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr); + IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id)); } #endif @@ -1194,7 +1194,7 @@ void iwl_irq_handle_error(struct iwl_priv *priv) clear_bit(STATUS_READY, &priv->status); if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { - IWL_DEBUG(IWL_DL_FW_ERRORS, + IWL_DEBUG(priv, IWL_DL_FW_ERRORS, "Restarting adapter due to uCode error.\n"); if (iwl_is_associated(priv)) { @@ -1216,7 +1216,7 @@ void iwl_configure_filter(struct ieee80211_hw *hw, struct iwl_priv *priv = hw->priv; __le32 *filter_flags = &priv->staging_rxon.filter_flags; - IWL_DEBUG_MAC80211("Enter: changed: 0x%x, total: 0x%x\n", + IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n", changed_flags, *total_flags); if (changed_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) { @@ -1429,13 +1429,13 @@ void iwl_disable_interrupts(struct iwl_priv *priv) * from uCode or flow handler (Rx/Tx DMA) */ iwl_write32(priv, CSR_INT, 0xffffffff); iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff); - IWL_DEBUG_ISR("Disabled interrupts\n"); + IWL_DEBUG_ISR(priv, "Disabled interrupts\n"); } EXPORT_SYMBOL(iwl_disable_interrupts); void iwl_enable_interrupts(struct iwl_priv *priv) { - IWL_DEBUG_ISR("Enabling interrupts\n"); + IWL_DEBUG_ISR(priv, "Enabling interrupts\n"); set_bit(STATUS_INT_ENABLED, &priv->status); iwl_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK); } @@ -1481,7 +1481,7 @@ static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 u32 errcnt = 0; u32 i; - IWL_DEBUG_INFO("ucode inst image size is %u\n", len); + IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); ret = iwl_grab_nic_access(priv); if (ret) @@ -1519,7 +1519,7 @@ static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 *image, int ret = 0; u32 errcnt; - IWL_DEBUG_INFO("ucode inst image size is %u\n", len); + IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); ret = iwl_grab_nic_access(priv); if (ret) @@ -1548,8 +1548,8 @@ static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 *image, iwl_release_nic_access(priv); if (!errcnt) - IWL_DEBUG_INFO - ("ucode image in INSTRUCTION memory is good\n"); + IWL_DEBUG_INFO(priv, + "ucode image in INSTRUCTION memory is good\n"); return ret; } @@ -1569,7 +1569,7 @@ int iwl_verify_ucode(struct iwl_priv *priv) len = priv->ucode_boot.len; ret = iwlcore_verify_inst_sparse(priv, image, len); if (!ret) { - IWL_DEBUG_INFO("Bootstrap uCode is good in inst SRAM\n"); + IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n"); return 0; } @@ -1578,7 +1578,7 @@ int iwl_verify_ucode(struct iwl_priv *priv) len = priv->ucode_init.len; ret = iwlcore_verify_inst_sparse(priv, image, len); if (!ret) { - IWL_DEBUG_INFO("Initialize uCode is good in inst SRAM\n"); + IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n"); return 0; } @@ -1587,7 +1587,7 @@ int iwl_verify_ucode(struct iwl_priv *priv) len = priv->ucode_code.len; ret = iwlcore_verify_inst_sparse(priv, image, len); if (!ret) { - IWL_DEBUG_INFO("Runtime uCode is good in inst SRAM\n"); + IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n"); return 0; } @@ -1827,7 +1827,7 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv) if (ret) IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); else - IWL_DEBUG_INFO("REPLY_CT_KILL_CONFIG_CMD succeeded, " + IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD succeeded, " "critical temperature is %d\n", cmd.critical_temperature_R); } @@ -1864,7 +1864,7 @@ void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv) if (test_bit(STATUS_RF_KILL_SW, &priv->status)) return; - IWL_DEBUG_RF_KILL("Manual SW RF KILL set to: RADIO OFF\n"); + IWL_DEBUG_RF_KILL(priv, "Manual SW RF KILL set to: RADIO OFF\n"); iwl_scan_cancel(priv); /* FIXME: This is a workaround for AP */ @@ -1893,7 +1893,7 @@ int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv) if (!test_bit(STATUS_RF_KILL_SW, &priv->status)) return 0; - IWL_DEBUG_RF_KILL("Manual SW RF KILL set to: RADIO ON\n"); + IWL_DEBUG_RF_KILL(priv, "Manual SW RF KILL set to: RADIO ON\n"); spin_lock_irqsave(&priv->lock, flags); iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); @@ -1918,7 +1918,7 @@ int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { - IWL_DEBUG_RF_KILL("Can not turn radio back on - " + IWL_DEBUG_RF_KILL(priv, "Can not turn radio back on - " "disabled by HW switch\n"); return 0; } @@ -1953,7 +1953,7 @@ void iwl_bg_rf_kill(struct work_struct *work) mutex_lock(&priv->mutex); if (!iwl_is_rfkill(priv)) { - IWL_DEBUG(IWL_DL_RF_KILL, + IWL_DEBUG_RF_KILL(priv, "HW and/or SW RF Kill no longer active, restarting " "device\n"); if (!test_bit(STATUS_EXIT_PENDING, &priv->status) && @@ -1965,7 +1965,7 @@ void iwl_bg_rf_kill(struct work_struct *work) ieee80211_stop_queues(priv->hw); if (!test_bit(STATUS_RF_KILL_HW, &priv->status)) - IWL_DEBUG_RF_KILL("Can not turn radio back on - " + IWL_DEBUG_RF_KILL(priv, "Can not turn radio back on - " "disabled by SW switch\n"); else IWL_WARN(priv, "Radio Frequency Kill Switch is On:\n" diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 7192d3249ca..65d1a7f2db9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -37,18 +37,20 @@ struct iwl_priv; #define IWL_CRIT(p, f, a...) dev_crit(&((p)->pci_dev->dev), f, ## a) #ifdef CONFIG_IWLWIFI_DEBUG -#define IWL_DEBUG(level, fmt, args...) \ -do { \ - if (priv->debug_level & (level)) \ - dev_printk(KERN_ERR, &(priv->hw->wiphy->dev), "%c %s " fmt, \ - in_interrupt() ? 'I' : 'U', __func__ , ## args); \ +#define IWL_DEBUG(__priv, level, fmt, args...) \ +do { \ + if (__priv->debug_level & (level)) \ + dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \ + "%c %s " fmt, in_interrupt() ? 'I' : 'U', \ + __func__ , ## args); \ } while (0) -#define IWL_DEBUG_LIMIT(level, fmt, args...) \ -do { \ - if ((priv->debug_level & (level)) && net_ratelimit()) \ - dev_printk(KERN_ERR, &(priv->hw->wiphy->dev), "%c %s " fmt, \ - in_interrupt() ? 'I' : 'U', __func__ , ## args); \ +#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) \ +do { \ + if ((__priv->debug_level & (level)) && net_ratelimit()) \ + dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \ + "%c %s " fmt, in_interrupt() ? 'I' : 'U', \ + __func__ , ## args); \ } while (0) #define iwl_print_hex_dump(priv, level, p, len) \ @@ -88,8 +90,8 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv); #endif #else -#define IWL_DEBUG(level, fmt, args...) -#define IWL_DEBUG_LIMIT(level, fmt, args...) +#define IWL_DEBUG(__priv, level, fmt, args...) +#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level, void *p, u32 len) {} @@ -169,42 +171,45 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) #define IWL_DL_TX_REPLY (1 << 30) #define IWL_DL_QOS (1 << 31) -#define IWL_DEBUG_INFO(f, a...) IWL_DEBUG(IWL_DL_INFO, f, ## a) -#define IWL_DEBUG_MAC80211(f, a...) IWL_DEBUG(IWL_DL_MAC80211, f, ## a) -#define IWL_DEBUG_MACDUMP(f, a...) IWL_DEBUG(IWL_DL_MACDUMP, f, ## a) -#define IWL_DEBUG_TEMP(f, a...) IWL_DEBUG(IWL_DL_TEMP, f, ## a) -#define IWL_DEBUG_SCAN(f, a...) IWL_DEBUG(IWL_DL_SCAN, f, ## a) -#define IWL_DEBUG_RX(f, a...) IWL_DEBUG(IWL_DL_RX, f, ## a) -#define IWL_DEBUG_TX(f, a...) IWL_DEBUG(IWL_DL_TX, f, ## a) -#define IWL_DEBUG_ISR(f, a...) IWL_DEBUG(IWL_DL_ISR, f, ## a) -#define IWL_DEBUG_LED(f, a...) IWL_DEBUG(IWL_DL_LED, f, ## a) -#define IWL_DEBUG_WEP(f, a...) IWL_DEBUG(IWL_DL_WEP, f, ## a) -#define IWL_DEBUG_HC(f, a...) IWL_DEBUG(IWL_DL_HCMD, f, ## a) -#define IWL_DEBUG_HC_DUMP(f, a...) IWL_DEBUG(IWL_DL_HCMD_DUMP, f, ## a) -#define IWL_DEBUG_CALIB(f, a...) IWL_DEBUG(IWL_DL_CALIB, f, ## a) -#define IWL_DEBUG_FW(f, a...) IWL_DEBUG(IWL_DL_FW, f, ## a) -#define IWL_DEBUG_RF_KILL(f, a...) IWL_DEBUG(IWL_DL_RF_KILL, f, ## a) -#define IWL_DEBUG_DROP(f, a...) IWL_DEBUG(IWL_DL_DROP, f, ## a) -#define IWL_DEBUG_DROP_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_DROP, f, ## a) -#define IWL_DEBUG_AP(f, a...) IWL_DEBUG(IWL_DL_AP, f, ## a) -#define IWL_DEBUG_TXPOWER(f, a...) IWL_DEBUG(IWL_DL_TXPOWER, f, ## a) -#define IWL_DEBUG_IO(f, a...) IWL_DEBUG(IWL_DL_IO, f, ## a) -#define IWL_DEBUG_RATE(f, a...) IWL_DEBUG(IWL_DL_RATE, f, ## a) -#define IWL_DEBUG_RATE_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_RATE, f, ## a) -#define IWL_DEBUG_NOTIF(f, a...) IWL_DEBUG(IWL_DL_NOTIF, f, ## a) -#define IWL_DEBUG_ASSOC(f, a...) \ - IWL_DEBUG(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a) -#define IWL_DEBUG_ASSOC_LIMIT(f, a...) \ - IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a) -#define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a) -#define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a) -#define IWL_DEBUG_STATS_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_STATS, f, ## a) -#define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a) -#define IWL_DEBUG_TX_REPLY_LIMIT(f, a...) \ - IWL_DEBUG_LIMIT(IWL_DL_TX_REPLY, f, ## a) -#define IWL_DEBUG_QOS(f, a...) IWL_DEBUG(IWL_DL_QOS, f, ## a) -#define IWL_DEBUG_RADIO(f, a...) IWL_DEBUG(IWL_DL_RADIO, f, ## a) -#define IWL_DEBUG_POWER(f, a...) IWL_DEBUG(IWL_DL_POWER, f, ## a) -#define IWL_DEBUG_11H(f, a...) IWL_DEBUG(IWL_DL_11H, f, ## a) +#define IWL_DEBUG_INFO(p, f, a...) IWL_DEBUG(p, IWL_DL_INFO, f, ## a) +#define IWL_DEBUG_MAC80211(p, f, a...) IWL_DEBUG(p, IWL_DL_MAC80211, f, ## a) +#define IWL_DEBUG_MACDUMP(p, f, a...) IWL_DEBUG(p, IWL_DL_MACDUMP, f, ## a) +#define IWL_DEBUG_TEMP(p, f, a...) IWL_DEBUG(p, IWL_DL_TEMP, f, ## a) +#define IWL_DEBUG_SCAN(p, f, a...) IWL_DEBUG(p, IWL_DL_SCAN, f, ## a) +#define IWL_DEBUG_RX(p, f, a...) IWL_DEBUG(p, IWL_DL_RX, f, ## a) +#define IWL_DEBUG_TX(p, f, a...) IWL_DEBUG(p, IWL_DL_TX, f, ## a) +#define IWL_DEBUG_ISR(p, f, a...) IWL_DEBUG(p, IWL_DL_ISR, f, ## a) +#define IWL_DEBUG_LED(p, f, a...) IWL_DEBUG(p, IWL_DL_LED, f, ## a) +#define IWL_DEBUG_WEP(p, f, a...) IWL_DEBUG(p, IWL_DL_WEP, f, ## a) +#define IWL_DEBUG_HC(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD, f, ## a) +#define IWL_DEBUG_HC_DUMP(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD_DUMP, f, ## a) +#define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a) +#define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a) +#define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a) +#define IWL_DEBUG_DROP(p, f, a...) IWL_DEBUG(p, IWL_DL_DROP, f, ## a) +#define IWL_DEBUG_DROP_LIMIT(p, f, a...) \ + IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a) +#define IWL_DEBUG_AP(p, f, a...) IWL_DEBUG(p, IWL_DL_AP, f, ## a) +#define IWL_DEBUG_TXPOWER(p, f, a...) IWL_DEBUG(p, IWL_DL_TXPOWER, f, ## a) +#define IWL_DEBUG_IO(p, f, a...) IWL_DEBUG(p, IWL_DL_IO, f, ## a) +#define IWL_DEBUG_RATE(p, f, a...) IWL_DEBUG(p, IWL_DL_RATE, f, ## a) +#define IWL_DEBUG_RATE_LIMIT(p, f, a...) \ + IWL_DEBUG_LIMIT(p, IWL_DL_RATE, f, ## a) +#define IWL_DEBUG_NOTIF(p, f, a...) IWL_DEBUG(p, IWL_DL_NOTIF, f, ## a) +#define IWL_DEBUG_ASSOC(p, f, a...) \ + IWL_DEBUG(p, IWL_DL_ASSOC | IWL_DL_INFO, f, ## a) +#define IWL_DEBUG_ASSOC_LIMIT(p, f, a...) \ + IWL_DEBUG_LIMIT(p, IWL_DL_ASSOC | IWL_DL_INFO, f, ## a) +#define IWL_DEBUG_HT(p, f, a...) IWL_DEBUG(p, IWL_DL_HT, f, ## a) +#define IWL_DEBUG_STATS(p, f, a...) IWL_DEBUG(p, IWL_DL_STATS, f, ## a) +#define IWL_DEBUG_STATS_LIMIT(p, f, a...) \ + IWL_DEBUG_LIMIT(p, IWL_DL_STATS, f, ## a) +#define IWL_DEBUG_TX_REPLY(p, f, a...) IWL_DEBUG(p, IWL_DL_TX_REPLY, f, ## a) +#define IWL_DEBUG_TX_REPLY_LIMIT(p, f, a...) \ + IWL_DEBUG_LIMIT(p, IWL_DL_TX_REPLY, f, ## a) +#define IWL_DEBUG_QOS(p, f, a...) IWL_DEBUG(p, IWL_DL_QOS, f, ## a) +#define IWL_DEBUG_RADIO(p, f, a...) IWL_DEBUG(p, IWL_DL_RADIO, f, ## a) +#define IWL_DEBUG_POWER(p, f, a...) IWL_DEBUG(p, IWL_DL_POWER, f, ## a) +#define IWL_DEBUG_11H(p, f, a...) IWL_DEBUG(p, IWL_DL_11H, f, ## a) #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index eaa658f9e54..d1d1d9bcfea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -173,7 +173,7 @@ int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv) CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, EEPROM_SEM_TIMEOUT); if (ret >= 0) { - IWL_DEBUG_IO("Acquired semaphore after %d tries.\n", + IWL_DEBUG_IO(priv, "Acquired semaphore after %d tries.\n", count+1); return ret; } @@ -390,7 +390,7 @@ static int iwl_set_fat_chan_info(struct iwl_priv *priv, if (!is_channel_valid(ch_info)) return -1; - IWL_DEBUG_INFO("FAT Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm):" + IWL_DEBUG_INFO(priv, "FAT Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm):" " Ad-Hoc %ssupported\n", ch_info->channel, is_channel_a_band(ch_info) ? @@ -432,11 +432,11 @@ int iwl_init_channel_map(struct iwl_priv *priv) struct iwl_channel_info *ch_info; if (priv->channel_count) { - IWL_DEBUG_INFO("Channel map already initialized.\n"); + IWL_DEBUG_INFO(priv, "Channel map already initialized.\n"); return 0; } - IWL_DEBUG_INFO("Initializing regulatory info from EEPROM\n"); + IWL_DEBUG_INFO(priv, "Initializing regulatory info from EEPROM\n"); priv->channel_count = ARRAY_SIZE(iwl_eeprom_band_1) + @@ -445,7 +445,7 @@ int iwl_init_channel_map(struct iwl_priv *priv) ARRAY_SIZE(iwl_eeprom_band_4) + ARRAY_SIZE(iwl_eeprom_band_5); - IWL_DEBUG_INFO("Parsing data for %d channels.\n", priv->channel_count); + IWL_DEBUG_INFO(priv, "Parsing data for %d channels.\n", priv->channel_count); priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) * priv->channel_count, GFP_KERNEL); @@ -485,7 +485,7 @@ int iwl_init_channel_map(struct iwl_priv *priv) IEEE80211_CHAN_NO_FAT_BELOW); if (!(is_channel_valid(ch_info))) { - IWL_DEBUG_INFO("Ch. %d Flags %x [%sGHz] - " + IWL_DEBUG_INFO(priv, "Ch. %d Flags %x [%sGHz] - " "No traffic\n", ch_info->channel, ch_info->flags, @@ -501,7 +501,7 @@ int iwl_init_channel_map(struct iwl_priv *priv) ch_info->scan_power = eeprom_ch_info[ch].max_power_avg; ch_info->min_power = 0; - IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm):" + IWL_DEBUG_INFO(priv, "Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm):" " Ad-Hoc %ssupported\n", ch_info->channel, is_channel_a_band(ch_info) ? diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 65ae2af61c8..17d61ac8ed6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -125,11 +125,11 @@ static int iwl_generic_cmd_callback(struct iwl_priv *priv, switch (cmd->hdr.cmd) { case REPLY_TX_LINK_QUALITY_CMD: case SENSITIVITY_CMD: - IWL_DEBUG_HC_DUMP("back from %s (0x%08X)\n", + IWL_DEBUG_HC_DUMP(priv, "back from %s (0x%08X)\n", get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); break; default: - IWL_DEBUG_HC("back from %s (0x%08X)\n", + IWL_DEBUG_HC(priv, "back from %s (0x%08X)\n", get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); } #endif @@ -211,13 +211,13 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) } if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { - IWL_DEBUG_INFO("Command %s aborted: RF KILL Switch\n", + IWL_DEBUG_INFO(priv, "Command %s aborted: RF KILL Switch\n", get_cmd_string(cmd->id)); ret = -ECANCELED; goto fail; } if (test_bit(STATUS_FW_ERROR, &priv->status)) { - IWL_DEBUG_INFO("Command %s failed: FW Error\n", + IWL_DEBUG_INFO(priv, "Command %s failed: FW Error\n", get_cmd_string(cmd->id)); ret = -EIO; goto fail; diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 7341a2da843..c7b8e5bb4e4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -66,7 +66,7 @@ static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *priv, u32 ofs, u32 val) { - IWL_DEBUG_IO("write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l); + IWL_DEBUG_IO(priv, "write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l); _iwl_write32(priv, ofs, val); } #define iwl_write32(priv, ofs, val) \ @@ -79,7 +79,7 @@ static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *priv, #ifdef CONFIG_IWLWIFI_DEBUG static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs) { - IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l); + IWL_DEBUG_IO(priv, "read_direct32(0x%08X) - %s %d\n", ofs, f, l); return _iwl_read32(priv, ofs); } #define iwl_read32(priv, ofs) __iwl_read32(__FILE__, __LINE__, priv, ofs) @@ -108,7 +108,7 @@ static inline int __iwl_poll_bit(const char *f, u32 l, u32 bits, u32 mask, int timeout) { int ret = _iwl_poll_bit(priv, addr, bits, mask, timeout); - IWL_DEBUG_IO("poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n", + IWL_DEBUG_IO(priv, "poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n", addr, bits, mask, unlikely(ret == -ETIMEDOUT) ? "timeout" : "", f, l); return ret; @@ -128,7 +128,7 @@ static inline void __iwl_set_bit(const char *f, u32 l, struct iwl_priv *priv, u32 reg, u32 mask) { u32 val = _iwl_read32(priv, reg) | mask; - IWL_DEBUG_IO("set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); + IWL_DEBUG_IO(priv, "set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); _iwl_write32(priv, reg, val); } #define iwl_set_bit(p, r, m) __iwl_set_bit(__FILE__, __LINE__, p, r, m) @@ -145,7 +145,7 @@ static inline void __iwl_clear_bit(const char *f, u32 l, struct iwl_priv *priv, u32 reg, u32 mask) { u32 val = _iwl_read32(priv, reg) & ~mask; - IWL_DEBUG_IO("clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); + IWL_DEBUG_IO(priv, "clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); _iwl_write32(priv, reg, val); } #define iwl_clear_bit(p, r, m) __iwl_clear_bit(__FILE__, __LINE__, p, r, m) @@ -184,7 +184,7 @@ static inline int __iwl_grab_nic_access(const char *f, u32 l, if (atomic_read(&priv->restrict_refcnt)) IWL_ERR(priv, "Grabbing access while already held %s %d.\n", f, l); - IWL_DEBUG_IO("grabbing nic access - %s %d\n", f, l); + IWL_DEBUG_IO(priv, "grabbing nic access - %s %d\n", f, l); return _iwl_grab_nic_access(priv); } #define iwl_grab_nic_access(priv) \ @@ -209,7 +209,7 @@ static inline void __iwl_release_nic_access(const char *f, u32 l, if (atomic_read(&priv->restrict_refcnt) <= 0) IWL_ERR(priv, "Release unheld nic access at line %s %d.\n", f, l); - IWL_DEBUG_IO("releasing nic access - %s %d\n", f, l); + IWL_DEBUG_IO(priv, "releasing nic access - %s %d\n", f, l); _iwl_release_nic_access(priv); } #define iwl_release_nic_access(priv) \ @@ -230,7 +230,7 @@ static inline u32 __iwl_read_direct32(const char *f, u32 l, u32 value = _iwl_read_direct32(priv, reg); if (!atomic_read(&priv->restrict_refcnt)) IWL_ERR(priv, "Nic access not held from %s %d\n", f, l); - IWL_DEBUG_IO("read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value, + IWL_DEBUG_IO(priv, "read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value, f, l); return value; } @@ -284,10 +284,10 @@ static inline int __iwl_poll_direct_bit(const char *f, u32 l, int ret = _iwl_poll_direct_bit(priv, addr, mask, timeout); if (unlikely(ret == -ETIMEDOUT)) - IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) - " + IWL_DEBUG_IO(priv, "poll_direct_bit(0x%08X, 0x%08X) - " "timedout - %s %d\n", addr, mask, f, l); else - IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) = 0x%08X " + IWL_DEBUG_IO(priv, "poll_direct_bit(0x%08X, 0x%08X) = 0x%08X " "- %s %d\n", addr, mask, ret, f, l); return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 501cffeff5f..63d669ec20c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -123,7 +123,7 @@ static int iwl4965_led_pattern(struct iwl_priv *priv, int led_id, /* Set led register off */ static int iwl4965_led_on_reg(struct iwl_priv *priv, int led_id) { - IWL_DEBUG_LED("led on %d\n", led_id); + IWL_DEBUG_LED(priv, "led on %d\n", led_id); iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); return 0; } @@ -150,7 +150,7 @@ int iwl4965_led_off(struct iwl_priv *priv, int led_id) .off = 0, .interval = IWL_DEF_LED_INTRVL }; - IWL_DEBUG_LED("led off %d\n", led_id); + IWL_DEBUG_LED(priv, "led off %d\n", led_id); return iwl_send_led_cmd(priv, &led_cmd); } #endif @@ -159,7 +159,7 @@ int iwl4965_led_off(struct iwl_priv *priv, int led_id) /* Set led register off */ static int iwl4965_led_off_reg(struct iwl_priv *priv, int led_id) { - IWL_DEBUG_LED("LED Reg off\n"); + IWL_DEBUG_LED(priv, "LED Reg off\n"); iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF); return 0; } @@ -169,7 +169,7 @@ static int iwl4965_led_off_reg(struct iwl_priv *priv, int led_id) */ static int iwl_led_associate(struct iwl_priv *priv, int led_id) { - IWL_DEBUG_LED("Associated\n"); + IWL_DEBUG_LED(priv, "Associated\n"); priv->allow_blinking = 1; return iwl4965_led_on_reg(priv, led_id); } @@ -213,7 +213,7 @@ static void iwl_led_brightness_set(struct led_classdev *led_cdev, return; - IWL_DEBUG_LED("Led type = %s brightness = %d\n", + IWL_DEBUG_LED(priv, "Led type = %s brightness = %d\n", led_type_str[led->type], brightness); switch (brightness) { case LED_FULL: @@ -280,7 +280,7 @@ static int iwl_get_blink_rate(struct iwl_priv *priv) if (tpt < 0) /* wraparound */ tpt = -tpt; - IWL_DEBUG_LED("tpt %lld current_tpt %llu\n", + IWL_DEBUG_LED(priv, "tpt %lld current_tpt %llu\n", (long long)tpt, (unsigned long long)current_tpt); priv->led_tpt = current_tpt; @@ -292,7 +292,7 @@ static int iwl_get_blink_rate(struct iwl_priv *priv) if (tpt > (blink_tbl[i].tpt * IWL_1MB_RATE)) break; - IWL_DEBUG_LED("LED BLINK IDX=%d\n", i); + IWL_DEBUG_LED(priv, "LED BLINK IDX=%d\n", i); return i; } diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index a4634595c59..abe0d2966a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -149,7 +149,7 @@ static void iwl_power_init_handle(struct iwl_priv *priv) int i; u16 pci_pm; - IWL_DEBUG_POWER("Initialize power \n"); + IWL_DEBUG_POWER(priv, "Initialize power \n"); pow_data = &priv->power_data; @@ -161,7 +161,7 @@ static void iwl_power_init_handle(struct iwl_priv *priv) pci_read_config_word(priv->pci_dev, PCI_CFG_LINK_CTRL, &pci_pm); - IWL_DEBUG_POWER("adjust power command flags\n"); + IWL_DEBUG_POWER(priv, "adjust power command flags\n"); for (i = 0; i < IWL_POWER_MAX; i++) { cmd = &pow_data->pwr_range_0[i].cmd; @@ -185,7 +185,7 @@ static int iwl_update_power_cmd(struct iwl_priv *priv, bool skip; if (mode > IWL_POWER_INDEX_5) { - IWL_DEBUG_POWER("Error invalid power mode \n"); + IWL_DEBUG_POWER(priv, "Error invalid power mode \n"); return -EINVAL; } @@ -225,10 +225,10 @@ static int iwl_update_power_cmd(struct iwl_priv *priv, if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep) cmd->sleep_interval[i] = cpu_to_le32(max_sleep); - IWL_DEBUG_POWER("Flags value = 0x%08X\n", cmd->flags); - IWL_DEBUG_POWER("Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout)); - IWL_DEBUG_POWER("Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout)); - IWL_DEBUG_POWER("Sleep interval vector = { %d , %d , %d , %d , %d }\n", + IWL_DEBUG_POWER(priv, "Flags value = 0x%08X\n", cmd->flags); + IWL_DEBUG_POWER(priv, "Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout)); + IWL_DEBUG_POWER(priv, "Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout)); + IWL_DEBUG_POWER(priv, "Sleep interval vector = { %d , %d , %d , %d , %d }\n", le32_to_cpu(cmd->sleep_interval[0]), le32_to_cpu(cmd->sleep_interval[1]), le32_to_cpu(cmd->sleep_interval[2]), @@ -302,7 +302,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) if (priv->cfg->ops->lib->update_chain_flags && update_chains) priv->cfg->ops->lib->update_chain_flags(priv); else - IWL_DEBUG_POWER("Cannot update the power, chain noise " + IWL_DEBUG_POWER(priv, "Cannot update the power, chain noise " "calibration running: %d\n", priv->chain_noise_data.state); if (!ret) @@ -423,7 +423,7 @@ static void iwl_bg_set_power_save(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, set_power_save.work); - IWL_DEBUG(IWL_DL_STATE, "update power\n"); + IWL_DEBUG_POWER(priv, "update power\n"); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c index f67d7be1074..2ad9faf1508 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c @@ -47,7 +47,7 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return 0; - IWL_DEBUG_RF_KILL("we received soft RFKILL set to state %d\n", state); + IWL_DEBUG_RF_KILL(priv, "we received soft RFKILL set to state %d\n", state); mutex_lock(&priv->mutex); switch (state) { @@ -79,7 +79,7 @@ int iwl_rfkill_init(struct iwl_priv *priv) BUG_ON(device == NULL); - IWL_DEBUG_RF_KILL("Initializing RFKILL.\n"); + IWL_DEBUG_RF_KILL(priv, "Initializing RFKILL.\n"); priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); if (!priv->rfkill) { IWL_ERR(priv, "Unable to allocate RFKILL device.\n"); @@ -102,7 +102,7 @@ int iwl_rfkill_init(struct iwl_priv *priv) goto free_rfkill; } - IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); + IWL_DEBUG_RF_KILL(priv, "RFKILL initialization complete.\n"); return ret; free_rfkill: @@ -111,7 +111,7 @@ free_rfkill: priv->rfkill = NULL; error: - IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); + IWL_DEBUG_RF_KILL(priv, "RFKILL initialization complete.\n"); return ret; } EXPORT_SYMBOL(iwl_rfkill_init); diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index c8865d0b906..8f65908f66f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -494,7 +494,7 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, missed_beacon = &pkt->u.missed_beacon; if (le32_to_cpu(missed_beacon->consequtive_missed_beacons) > 5) { - IWL_DEBUG_CALIB("missed bcn cnsq %d totl %d rcd %d expctd %d\n", + IWL_DEBUG_CALIB(priv, "missed bcn cnsq %d totl %d rcd %d expctd %d\n", le32_to_cpu(missed_beacon->consequtive_missed_beacons), le32_to_cpu(missed_beacon->total_missed_becons), le32_to_cpu(missed_beacon->num_recvd_beacons), @@ -541,7 +541,7 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) else priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; - IWL_DEBUG_CALIB("inband silence a %u, b %u, c %u, dBm %d\n", + IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n", bcn_silence_a, bcn_silence_b, bcn_silence_c, priv->last_rx_noise); } @@ -554,7 +554,7 @@ void iwl_rx_statistics(struct iwl_priv *priv, int change; struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - IWL_DEBUG_RX("Statistics notification received (%d vs %d).\n", + IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", (int)sizeof(priv->statistics), pkt->len); change = ((priv->statistics.general.temperature != @@ -741,13 +741,13 @@ static void iwl_dbg_report_frame(struct iwl_priv *priv, * MAC addresses show just the last byte (for brevity), * but you can hack it to show more, if you'd like to. */ if (dataframe) - IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, " + IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " "len=%u, rssi=%d, chnl=%d, rate=%u, \n", title, le16_to_cpu(fc), header->addr1[5], length, rssi, channel, bitrate); else { /* src/dst addresses assume managed mode */ - IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, src=0x%02x, " + IWL_DEBUG_RX(priv, "%s: 0x%04x, dst=0x%02x, src=0x%02x, " "len=%u, rssi=%d, tim=%lu usec, " "phy=0x%02x, chnl=%d\n", title, le16_to_cpu(fc), header->addr1[5], @@ -785,7 +785,7 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv, if (!(fc & IEEE80211_FCTL_PROTECTED)) return 0; - IWL_DEBUG_RX("decrypt_res:0x%x\n", decrypt_res); + IWL_DEBUG_RX(priv, "decrypt_res:0x%x\n", decrypt_res); switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) { case RX_RES_STATUS_SEC_TYPE_TKIP: /* The uCode has got a bad phase 1 Key, pushes the packet. @@ -799,13 +799,13 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv, RX_RES_STATUS_BAD_ICV_MIC) { /* bad ICV, the packet is destroyed since the * decryption is inplace, drop it */ - IWL_DEBUG_RX("Packet destroyed\n"); + IWL_DEBUG_RX(priv, "Packet destroyed\n"); return -1; } case RX_RES_STATUS_SEC_TYPE_CCMP: if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == RX_RES_STATUS_DECRYPT_OK) { - IWL_DEBUG_RX("hw decrypt successfully!!!\n"); + IWL_DEBUG_RX(priv, "hw decrypt successfully!!!\n"); stats->flag |= RX_FLAG_DECRYPTED; } break; @@ -870,7 +870,7 @@ static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) break; }; - IWL_DEBUG_RX("decrypt_in:0x%x decrypt_out = 0x%x\n", + IWL_DEBUG_RX(priv, "decrypt_in:0x%x decrypt_out = 0x%x\n", decrypt_in, decrypt_out); return decrypt_out; @@ -934,8 +934,8 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, /* We only process data packets if the interface is open */ if (unlikely(!priv->is_open)) { - IWL_DEBUG_DROP_LIMIT - ("Dropping packet while interface is not open.\n"); + IWL_DEBUG_DROP_LIMIT(priv, + "Dropping packet while interface is not open.\n"); return; } @@ -1007,7 +1007,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, /*rx_status.flag |= RX_FLAG_TSFT;*/ if ((unlikely(rx_start->cfg_phy_cnt > 20))) { - IWL_DEBUG_DROP("dsp size out of range [0,20]: %d/n", + IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", rx_start->cfg_phy_cnt); return; } @@ -1045,7 +1045,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, if (!(*rx_end & RX_RES_STATUS_NO_CRC32_ERROR) || !(*rx_end & RX_RES_STATUS_NO_RXE_OVERFLOW)) { - IWL_DEBUG_RX("Bad CRC or FIFO: 0x%08X.\n", + IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", le32_to_cpu(*rx_end)); return; } @@ -1078,7 +1078,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, if (unlikely(priv->debug_level & IWL_DL_RX)) iwl_dbg_report_frame(priv, rx_start, len, header, 1); #endif - IWL_DEBUG_STATS_LIMIT("Rssi %d, noise %d, qual %d, TSF %llu\n", + IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n", rx_status.signal, rx_status.noise, rx_status.signal, (unsigned long long)rx_status.mactime); diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index c282d1d294e..22bad3ce7d6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -70,12 +70,12 @@ int iwl_scan_cancel(struct iwl_priv *priv) if (test_bit(STATUS_SCANNING, &priv->status)) { if (!test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_SCAN("Queuing scan abort.\n"); + IWL_DEBUG_SCAN(priv, "Queuing scan abort.\n"); set_bit(STATUS_SCAN_ABORTING, &priv->status); queue_work(priv->workqueue, &priv->abort_scan); } else - IWL_DEBUG_SCAN("Scan abort already in progress.\n"); + IWL_DEBUG_SCAN(priv, "Scan abort already in progress.\n"); return test_bit(STATUS_SCANNING, &priv->status); } @@ -140,7 +140,7 @@ int iwl_send_scan_abort(struct iwl_priv *priv) * can occur if we send the scan abort before we * the microcode has notified us that a scan is * completed. */ - IWL_DEBUG_INFO("SCAN_ABORT returned %d.\n", res->u.status); + IWL_DEBUG_INFO(priv, "SCAN_ABORT returned %d.\n", res->u.status); clear_bit(STATUS_SCAN_ABORTING, &priv->status); clear_bit(STATUS_SCAN_HW, &priv->status); } @@ -161,7 +161,7 @@ static void iwl_rx_reply_scan(struct iwl_priv *priv, struct iwl_scanreq_notification *notif = (struct iwl_scanreq_notification *)pkt->u.raw; - IWL_DEBUG_RX("Scan request status = 0x%x\n", notif->status); + IWL_DEBUG_RX(priv, "Scan request status = 0x%x\n", notif->status); #endif } @@ -173,7 +173,7 @@ static void iwl_rx_scan_start_notif(struct iwl_priv *priv, struct iwl_scanstart_notification *notif = (struct iwl_scanstart_notification *)pkt->u.raw; priv->scan_start_tsf = le32_to_cpu(notif->tsf_low); - IWL_DEBUG_SCAN("Scan start: " + IWL_DEBUG_SCAN(priv, "Scan start: " "%d [802.11%s] " "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n", notif->channel, @@ -192,7 +192,7 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv, struct iwl_scanresults_notification *notif = (struct iwl_scanresults_notification *)pkt->u.raw; - IWL_DEBUG_SCAN("Scan ch.res: " + IWL_DEBUG_SCAN(priv, "Scan ch.res: " "%d [802.11%s] " "(TSF: 0x%08X:%08X) - %d " "elapsed=%lu usec (%dms since last)\n", @@ -218,7 +218,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw; - IWL_DEBUG_SCAN("Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n", + IWL_DEBUG_SCAN(priv, "Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n", scan_notif->scanned_channels, scan_notif->tsf_low, scan_notif->tsf_high, scan_notif->status); @@ -230,7 +230,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, /* The scan completion notification came in, so kill that timer... */ cancel_delayed_work(&priv->scan_check); - IWL_DEBUG_INFO("Scan pass on %sGHz took %dms\n", + IWL_DEBUG_INFO(priv, "Scan pass on %sGHz took %dms\n", (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) ? "2.4" : "5.2", jiffies_to_msecs(elapsed_jiffies @@ -248,7 +248,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, * then we reset the scan state machine and terminate, * re-queuing another scan if one has been requested */ if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_INFO("Aborted scan completed.\n"); + IWL_DEBUG_INFO(priv, "Aborted scan completed.\n"); clear_bit(STATUS_SCAN_ABORTING, &priv->status); } else { /* If there are more bands on this scan pass reschedule */ @@ -258,11 +258,11 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, priv->last_scan_jiffies = jiffies; priv->next_scan_jiffies = 0; - IWL_DEBUG_INFO("Setting scan to off\n"); + IWL_DEBUG_INFO(priv, "Setting scan to off\n"); clear_bit(STATUS_SCANNING, &priv->status); - IWL_DEBUG_INFO("Scan took %dms\n", + IWL_DEBUG_INFO(priv, "Scan took %dms\n", jiffies_to_msecs(elapsed_jiffies(priv->scan_start, jiffies))); queue_work(priv->workqueue, &priv->scan_completed); @@ -355,7 +355,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, ch_info = iwl_get_channel_info(priv, band, channel); if (!is_channel_valid(ch_info)) { - IWL_DEBUG_SCAN("Channel %d is INVALID for this band.\n", + IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n", channel); continue; } @@ -384,7 +384,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, else scan_ch->tx_gain = ((1 << 5) | (5 << 3)); - IWL_DEBUG_SCAN("Scanning ch=%d prob=0x%X [%s %d]\n", + IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n", channel, le32_to_cpu(scan_ch->type), (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? "ACTIVE" : "PASSIVE", @@ -395,7 +395,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, added++; } - IWL_DEBUG_SCAN("total channels to scan %d \n", added); + IWL_DEBUG_SCAN(priv, "total channels to scan %d \n", added); return added; } @@ -411,21 +411,21 @@ void iwl_init_scan_params(struct iwl_priv *priv) int iwl_scan_initiate(struct iwl_priv *priv) { if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_SCAN("Aborting scan due to not ready.\n"); + IWL_DEBUG_SCAN(priv, "Aborting scan due to not ready.\n"); return -EIO; } if (test_bit(STATUS_SCANNING, &priv->status)) { - IWL_DEBUG_SCAN("Scan already in progress.\n"); + IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); return -EAGAIN; } if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_SCAN("Scan request while abort pending\n"); + IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); return -EAGAIN; } - IWL_DEBUG_INFO("Starting scan...\n"); + IWL_DEBUG_INFO(priv, "Starting scan...\n"); if (priv->cfg->sku & IWL_SKU_G) priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ); if (priv->cfg->sku & IWL_SKU_A) @@ -453,7 +453,7 @@ void iwl_bg_scan_check(struct work_struct *data) mutex_lock(&priv->mutex); if (test_bit(STATUS_SCANNING, &priv->status) || test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG(IWL_DL_SCAN, "Scan completion watchdog resetting " + IWL_DEBUG_SCAN(priv, "Scan completion watchdog resetting " "adapter (%dms)\n", jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG)); @@ -657,34 +657,34 @@ static void iwl_bg_request_scan(struct work_struct *data) /* This should never be called or scheduled if there is currently * a scan active in the hardware. */ if (test_bit(STATUS_SCAN_HW, &priv->status)) { - IWL_DEBUG_INFO("Multiple concurrent scan requests in parallel. " + IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests in parallel. " "Ignoring second request.\n"); ret = -EIO; goto done; } if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { - IWL_DEBUG_SCAN("Aborting scan due to device shutdown\n"); + IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n"); goto done; } if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_HC("Scan request while abort pending. Queuing.\n"); + IWL_DEBUG_HC(priv, "Scan request while abort pending. Queuing.\n"); goto done; } if (iwl_is_rfkill(priv)) { - IWL_DEBUG_HC("Aborting scan due to RF Kill activation\n"); + IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n"); goto done; } if (!test_bit(STATUS_READY, &priv->status)) { - IWL_DEBUG_HC("Scan request while uninitialized. Queuing.\n"); + IWL_DEBUG_HC(priv, "Scan request while uninitialized. Queuing.\n"); goto done; } if (!priv->scan_bands) { - IWL_DEBUG_HC("Aborting scan due to no requested bands\n"); + IWL_DEBUG_HC(priv, "Aborting scan due to no requested bands\n"); goto done; } @@ -709,7 +709,7 @@ static void iwl_bg_request_scan(struct work_struct *data) u32 scan_suspend_time = 100; unsigned long flags; - IWL_DEBUG_INFO("Scanning while associated...\n"); + IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); spin_lock_irqsave(&priv->lock, flags); interval = priv->beacon_int; @@ -724,13 +724,13 @@ static void iwl_bg_request_scan(struct work_struct *data) scan_suspend_time = (extra | ((suspend_time % interval) * 1024)); scan->suspend_time = cpu_to_le32(scan_suspend_time); - IWL_DEBUG_SCAN("suspend_time 0x%X beacon interval %d\n", + IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n", scan_suspend_time, interval); } /* We should add the ability for user to lock to PASSIVE ONLY */ if (priv->one_direct_scan) { - IWL_DEBUG_SCAN("Start direct scan for '%s'\n", + IWL_DEBUG_SCAN(priv, "Start direct scan for '%s'\n", print_ssid(ssid, priv->direct_ssid, priv->direct_ssid_len)); scan->direct_scan[0].id = WLAN_EID_SSID; @@ -739,7 +739,7 @@ static void iwl_bg_request_scan(struct work_struct *data) priv->direct_ssid, priv->direct_ssid_len); n_probes++; } else { - IWL_DEBUG_SCAN("Start indirect scan.\n"); + IWL_DEBUG_SCAN(priv, "Start indirect scan.\n"); } scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; @@ -801,7 +801,7 @@ static void iwl_bg_request_scan(struct work_struct *data) (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); if (scan->channel_count == 0) { - IWL_DEBUG_SCAN("channel count %d\n", scan->channel_count); + IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); goto done; } @@ -855,7 +855,7 @@ void iwl_bg_scan_completed(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, scan_completed); - IWL_DEBUG_SCAN("SCAN complete scan\n"); + IWL_DEBUG_SCAN(priv, "SCAN complete scan\n"); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.c b/drivers/net/wireless/iwlwifi/iwl-spectrum.c index aba1ef22fc6..022bcf11573 100644 --- a/drivers/net/wireless/iwlwifi/iwl-spectrum.c +++ b/drivers/net/wireless/iwlwifi/iwl-spectrum.c @@ -154,9 +154,9 @@ static int iwl_get_measurement(struct iwl_priv *priv, switch (spectrum_resp_status) { case 0: /* Command will be handled */ if (res->u.spectrum.id != 0xff) { - IWL_DEBUG_INFO - ("Replaced existing measurement: %d\n", - res->u.spectrum.id); + IWL_DEBUG_INFO(priv, + "Replaced existing measurement: %d\n", + res->u.spectrum.id); priv->measurement_status &= ~MEASUREMENT_READY; } priv->measurement_status |= MEASUREMENT_ACTIVE; @@ -181,7 +181,7 @@ static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif); if (!report->state) { - IWL_DEBUG(IWL_DL_11H, + IWL_DEBUG_11H(priv, "Spectrum Measure Notification: Start\n"); return; } diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 20dc84152d4..1fae3a6bd8d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -60,7 +60,7 @@ u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) goto out; } - IWL_DEBUG_ASSOC_LIMIT("can not find STA %pM total %d\n", + IWL_DEBUG_ASSOC_LIMIT(priv, "can not find STA %pM total %d\n", addr, priv->num_stations); out: @@ -92,7 +92,7 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) sta_id); priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE; - IWL_DEBUG_ASSOC("Added STA to Ucode: %pM\n", + IWL_DEBUG_ASSOC(priv, "Added STA to Ucode: %pM\n", priv->stations[sta_id].sta.sta.addr); spin_unlock_irqrestore(&priv->sta_lock, flags); @@ -123,7 +123,7 @@ static int iwl_add_sta_callback(struct iwl_priv *priv, iwl_sta_ucode_activate(priv, sta_id); /* fall through */ default: - IWL_DEBUG_HC("Received REPLY_ADD_STA:(0x%08X)\n", + IWL_DEBUG_HC(priv, "Received REPLY_ADD_STA:(0x%08X)\n", res->u.add_sta.status); break; } @@ -166,7 +166,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, switch (res->u.add_sta.status) { case ADD_STA_SUCCESS_MSK: iwl_sta_ucode_activate(priv, sta->sta.sta_id); - IWL_DEBUG_INFO("REPLY_ADD_STA PASSED\n"); + IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n"); break; default: ret = -EIO; @@ -272,7 +272,7 @@ u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap, station = &priv->stations[sta_id]; station->used = IWL_STA_DRIVER_ACTIVE; - IWL_DEBUG_ASSOC("Add STA to driver ID %d: %pM\n", + IWL_DEBUG_ASSOC(priv, "Add STA to driver ID %d: %pM\n", sta_id, addr); priv->num_stations++; @@ -304,7 +304,7 @@ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr) BUG_ON(sta_id == IWL_INVALID_STATION); - IWL_DEBUG_ASSOC("Removed STA from Ucode: %pM\n", addr); + IWL_DEBUG_ASSOC(priv, "Removed STA from Ucode: %pM\n", addr); spin_lock_irqsave(&priv->sta_lock, flags); @@ -390,7 +390,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, switch (res->u.rem_sta.status) { case REM_STA_SUCCESS_MSK: iwl_sta_ucode_deactivate(priv, addr); - IWL_DEBUG_ASSOC("REPLY_REMOVE_STA PASSED\n"); + IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); break; default: ret = -EIO; @@ -432,7 +432,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap) if (unlikely(sta_id == IWL_INVALID_STATION)) goto out; - IWL_DEBUG_ASSOC("Removing STA from driver:%d %pM\n", + IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d %pM\n", sta_id, addr); if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { @@ -560,7 +560,7 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, priv->default_wep_key--; memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0])); ret = iwl_send_static_wepkey_cmd(priv, 1); - IWL_DEBUG_WEP("Remove default WEP key: idx=%d ret=%d\n", + IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n", keyconf->keyidx, ret); spin_unlock_irqrestore(&priv->sta_lock, flags); @@ -576,7 +576,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, if (keyconf->keylen != WEP_KEY_LEN_128 && keyconf->keylen != WEP_KEY_LEN_64) { - IWL_DEBUG_WEP("Bad WEP key length %d\n", keyconf->keylen); + IWL_DEBUG_WEP(priv, "Bad WEP key length %d\n", keyconf->keylen); return -EINVAL; } @@ -596,7 +596,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, keyconf->keylen); ret = iwl_send_static_wepkey_cmd(priv, 0); - IWL_DEBUG_WEP("Set default WEP key: len=%d idx=%d ret=%d\n", + IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n", keyconf->keylen, keyconf->keyidx, ret); spin_unlock_irqrestore(&priv->sta_lock, flags); @@ -752,7 +752,7 @@ void iwl_update_tkip_key(struct iwl_priv *priv, sta_id = iwl_find_station(priv, addr); if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_MAC80211("leave - %pM not in station map.\n", + IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", addr); return; } @@ -804,7 +804,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags); keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3; - IWL_DEBUG_WEP("Remove dynamic key: idx=%d sta=%d\n", + IWL_DEBUG_WEP(priv, "Remove dynamic key: idx=%d sta=%d\n", keyconf->keyidx, sta_id); if (keyconf->keyidx != keyidx) { @@ -868,7 +868,7 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, ret = -EINVAL; } - IWL_DEBUG_WEP("Set dynamic key: alg= %d len=%d idx=%d sta=%d ret=%d\n", + IWL_DEBUG_WEP(priv, "Set dynamic key: alg= %d len=%d idx=%d sta=%d ret=%d\n", keyconf->alg, keyconf->keylen, keyconf->keyidx, sta_id, ret); @@ -881,13 +881,13 @@ static void iwl_dump_lq_cmd(struct iwl_priv *priv, struct iwl_link_quality_cmd *lq) { int i; - IWL_DEBUG_RATE("lq station id 0x%x\n", lq->sta_id); - IWL_DEBUG_RATE("lq ant 0x%X 0x%X\n", + IWL_DEBUG_RATE(priv, "lq station id 0x%x\n", lq->sta_id); + IWL_DEBUG_RATE(priv, "lq ant 0x%X 0x%X\n", lq->general_params.single_stream_ant_msk, lq->general_params.dual_stream_ant_msk); for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) - IWL_DEBUG_RATE("lq index %d 0x%X\n", + IWL_DEBUG_RATE(priv, "lq index %d 0x%X\n", i, lq->rs_table[i].rate_n_flags); } #else @@ -1064,7 +1064,7 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) if (sta_id != IWL_INVALID_STATION) return sta_id; - IWL_DEBUG_DROP("Station %pM not in station map. " + IWL_DEBUG_DROP(priv, "Station %pM not in station map. " "Defaulting to broadcast...\n", hdr->addr1); iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 7d2b6e11f73..7c74b259873 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -96,7 +96,7 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { - IWL_DEBUG_INFO("Requesting wakeup, GP1 = 0x%x\n", reg); + IWL_DEBUG_INFO(priv, "Requesting wakeup, GP1 = 0x%x\n", reg); iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); return ret; @@ -638,14 +638,14 @@ static void iwl_tx_cmd_build_hwcrypto(struct iwl_priv *priv, memcpy(tx_cmd->key, keyconf->key, keyconf->keylen); if (info->flags & IEEE80211_TX_CTL_AMPDU) tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK; - IWL_DEBUG_TX("tx_cmd with AES hwcrypto\n"); + IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); break; case ALG_TKIP: tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; ieee80211_get_tkip_key(keyconf, skb_frag, IEEE80211_TKIP_P2_KEY, tx_cmd->key); - IWL_DEBUG_TX("tx_cmd with tkip hwcrypto\n"); + IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n"); break; case ALG_WEP: @@ -657,7 +657,7 @@ static void iwl_tx_cmd_build_hwcrypto(struct iwl_priv *priv, memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen); - IWL_DEBUG_TX("Configuring packet for WEP encryption " + IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " "with key %d\n", keyconf->keyidx); break; @@ -703,7 +703,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) spin_lock_irqsave(&priv->lock, flags); if (iwl_is_rfkill(priv)) { - IWL_DEBUG_DROP("Dropping - RF KILL\n"); + IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); goto drop_unlock; } @@ -717,11 +717,11 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) #ifdef CONFIG_IWLWIFI_DEBUG if (ieee80211_is_auth(fc)) - IWL_DEBUG_TX("Sending AUTH frame\n"); + IWL_DEBUG_TX(priv, "Sending AUTH frame\n"); else if (ieee80211_is_assoc_req(fc)) - IWL_DEBUG_TX("Sending ASSOC frame\n"); + IWL_DEBUG_TX(priv, "Sending ASSOC frame\n"); else if (ieee80211_is_reassoc_req(fc)) - IWL_DEBUG_TX("Sending REASSOC frame\n"); + IWL_DEBUG_TX(priv, "Sending REASSOC frame\n"); #endif /* drop all data frame if we are not associated */ @@ -731,7 +731,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) (!iwl_is_associated(priv) || ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id) || !priv->assoc_station_added)) { - IWL_DEBUG_DROP("Dropping - !iwl_is_associated\n"); + IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n"); goto drop_unlock; } @@ -742,12 +742,12 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* Find (or create) index into station table for destination station */ sta_id = iwl_get_sta_id(priv, hdr); if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_DROP("Dropping - INVALID STATION: %pM\n", + IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", hdr->addr1); goto drop; } - IWL_DEBUG_TX("station Id %d\n", sta_id); + IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); swq_id = skb_get_queue_mapping(skb); txq_id = swq_id; @@ -938,7 +938,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) !(cmd->meta.flags & CMD_SIZE_HUGE)); if (iwl_is_rfkill(priv)) { - IWL_DEBUG_INFO("Not sending command - RF KILL"); + IWL_DEBUG_INFO(priv, "Not sending command - RF KILL"); return -EIO; } @@ -981,7 +981,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) switch (out_cmd->hdr.cmd) { case REPLY_TX_LINK_QUALITY_CMD: case SENSITIVITY_CMD: - IWL_DEBUG_HC_DUMP("Sending command %s (#%x), seq: 0x%04X, " + IWL_DEBUG_HC_DUMP(priv, "Sending command %s (#%x), seq: 0x%04X, " "%d bytes at %d[%d]:%d\n", get_cmd_string(out_cmd->hdr.cmd), out_cmd->hdr.cmd, @@ -989,7 +989,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) q->write_ptr, idx, IWL_CMD_QUEUE_NUM); break; default: - IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, " + IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, " "%d bytes at %d[%d]:%d\n", get_cmd_string(out_cmd->hdr.cmd), out_cmd->hdr.cmd, @@ -1194,7 +1194,7 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) tid_data->agg.state = IWL_AGG_ON; ieee80211_start_tx_ba_cb_irqsafe(priv->hw, ra, tid); } else { - IWL_DEBUG_HT("HW queue is NOT empty: %d packets in HW queue\n", + IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n", tid_data->tfds_in_queue); tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; } @@ -1235,13 +1235,13 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) /* The queue is not empty */ if (write_ptr != read_ptr) { - IWL_DEBUG_HT("Stopping a non empty AGG HW QUEUE\n"); + IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n"); priv->stations[sta_id].tid[tid].agg.state = IWL_EMPTYING_HW_QUEUE_DELBA; return 0; } - IWL_DEBUG_HT("HW queue is empty\n"); + IWL_DEBUG_HT(priv, "HW queue is empty\n"); priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; spin_lock_irqsave(&priv->lock, flags); @@ -1272,7 +1272,7 @@ int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id) (q->read_ptr == q->write_ptr)) { u16 ssn = SEQ_TO_SN(tid_data->seq_number); int tx_fifo = default_tid_to_tx_fifo[tid]; - IWL_DEBUG_HT("HW queue empty: continue DELBA flow\n"); + IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, tx_fifo); tid_data->agg.state = IWL_AGG_OFF; @@ -1282,7 +1282,7 @@ int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id) case IWL_EMPTYING_HW_QUEUE_ADDBA: /* We are reclaiming the last packet of the queue */ if (tid_data->tfds_in_queue == 0) { - IWL_DEBUG_HT("HW queue empty: continue ADDBA flow\n"); + IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); tid_data->agg.state = IWL_AGG_ON; ieee80211_start_tx_ba_cb_irqsafe(priv->hw, addr, tid); } @@ -1317,7 +1317,7 @@ static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv, /* Mark that the expected block-ack response arrived */ agg->wait_for_ba = 0; - IWL_DEBUG_TX_REPLY("BA %d %d\n", agg->start_idx, ba_resp->seq_ctl); + IWL_DEBUG_TX_REPLY(priv, "BA %d %d\n", agg->start_idx, ba_resp->seq_ctl); /* Calculate shift to align block-ack bits with our Tx window bits */ sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4); @@ -1328,7 +1328,7 @@ static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv, bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; if (agg->frame_count > (64 - sh)) { - IWL_DEBUG_TX_REPLY("more frames than bitmap size"); + IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size"); return -1; } @@ -1341,7 +1341,7 @@ static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv, for (i = 0; i < agg->frame_count ; i++) { ack = bitmap & (1ULL << i); successes += !!ack; - IWL_DEBUG_TX_REPLY("%s ON i=%d idx=%d raw=%d\n", + IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff, agg->start_idx + i); } @@ -1354,7 +1354,7 @@ static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv, info->status.ampdu_ack_len = agg->frame_count; iwl_hwrate_to_tx_control(priv, agg->rate_n_flags, info); - IWL_DEBUG_TX_REPLY("Bitmap %llx\n", (unsigned long long)bitmap); + IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", (unsigned long long)bitmap); return 0; } @@ -1399,19 +1399,19 @@ void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, /* TODO: Need to get this copy more safely - now good for debug */ - IWL_DEBUG_TX_REPLY("REPLY_COMPRESSED_BA [%d] Received from %pM, " + IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " "sta_id = %d\n", agg->wait_for_ba, (u8 *) &ba_resp->sta_addr_lo32, ba_resp->sta_id); - IWL_DEBUG_TX_REPLY("TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = " + IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = " "%d, scd_ssn = %d\n", ba_resp->tid, ba_resp->seq_ctl, (unsigned long long)le64_to_cpu(ba_resp->bitmap), ba_resp->scd_flow, ba_resp->scd_ssn); - IWL_DEBUG_TX_REPLY("DAT start_idx = %d, bitmap = 0x%llx \n", + IWL_DEBUG_TX_REPLY(priv, "DAT start_idx = %d, bitmap = 0x%llx \n", agg->start_idx, (unsigned long long)agg->bitmap); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 346a3018d8a..ac337177fdb 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -203,7 +203,7 @@ u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flag return index; } - IWL_DEBUG_ASSOC("Add STA ID %d: %pM\n", index, addr); + IWL_DEBUG_ASSOC(priv, "Add STA ID %d: %pM\n", index, addr); station = &priv->stations_39[index]; station->used = 1; priv->num_stations++; @@ -251,7 +251,7 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) (rxon1->filter_flags == rxon2->filter_flags) && (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { - IWL_DEBUG_INFO("Using current RXON_ASSOC. Not resending.\n"); + IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); return 0; } @@ -368,7 +368,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) * before we apply the new config */ if (iwl_is_associated(priv) && (staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK)) { - IWL_DEBUG_INFO("Toggling associated bit on current RXON\n"); + IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n"); active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; /* @@ -391,7 +391,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) } } - IWL_DEBUG_INFO("Sending RXON\n" + IWL_DEBUG_INFO(priv, "Sending RXON\n" "* with%s RXON_FILTER_ASSOC_MSK\n" "* channel = %d\n" "* bssid = %pM\n", @@ -489,7 +489,7 @@ static int iwl3945_update_sta_key_info(struct iwl_priv *priv, spin_unlock_irqrestore(&priv->sta_lock, flags); - IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n"); + IWL_DEBUG_INFO(priv, "hwcrypto: modify ucode station key info\n"); iwl_send_add_sta(priv, (struct iwl_addsta_cmd *)&priv->stations_39[sta_id].sta, 0); return 0; @@ -508,7 +508,7 @@ static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) priv->stations_39[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; spin_unlock_irqrestore(&priv->sta_lock, flags); - IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n"); + IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n"); iwl_send_add_sta(priv, (struct iwl_addsta_cmd *)&priv->stations_39[sta_id].sta, 0); return 0; @@ -518,7 +518,7 @@ static void iwl3945_clear_free_frames(struct iwl_priv *priv) { struct list_head *element; - IWL_DEBUG_INFO("%d frames on pre-allocated heap on clear.\n", + IWL_DEBUG_INFO(priv, "%d frames on pre-allocated heap on clear.\n", priv->frames_count); while (!list_empty(&priv->free_frames)) { @@ -648,7 +648,7 @@ static void iwl3945_activate_qos(struct iwl_priv *priv, u8 force) spin_unlock_irqrestore(&priv->lock, flags); if (force || iwl_is_associated(priv)) { - IWL_DEBUG_QOS("send QoS cmd with QoS active %d \n", + IWL_DEBUG_QOS(priv, "send QoS cmd with QoS active %d \n", priv->qos_data.qos_active); iwl3945_send_qos_params_command(priv, @@ -690,7 +690,7 @@ int iwl3945_power_init_handle(struct iwl_priv *priv) int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_MAX; u16 pci_pm; - IWL_DEBUG_POWER("Initialize power \n"); + IWL_DEBUG_POWER(priv, "Initialize power \n"); pow_data = &priv->power_data; @@ -707,7 +707,7 @@ int iwl3945_power_init_handle(struct iwl_priv *priv) else { struct iwl_powertable_cmd *cmd; - IWL_DEBUG_POWER("adjust power command flags\n"); + IWL_DEBUG_POWER(priv, "adjust power command flags\n"); for (i = 0; i < IWL_POWER_MAX; i++) { cmd = &pow_data->pwr_range_0[i].cmd; @@ -732,7 +732,7 @@ static int iwl3945_update_power_cmd(struct iwl_priv *priv, bool skip; if (mode > IWL_POWER_INDEX_5) { - IWL_DEBUG_POWER("Error invalid power mode \n"); + IWL_DEBUG_POWER(priv, "Error invalid power mode \n"); return -EINVAL; } pow_data = &priv->power_data; @@ -765,10 +765,10 @@ static int iwl3945_update_power_cmd(struct iwl_priv *priv, if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep) cmd->sleep_interval[i] = cpu_to_le32(max_sleep); - IWL_DEBUG_POWER("Flags value = 0x%08X\n", cmd->flags); - IWL_DEBUG_POWER("Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout)); - IWL_DEBUG_POWER("Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout)); - IWL_DEBUG_POWER("Sleep interval vector = { %d , %d , %d , %d , %d }\n", + IWL_DEBUG_POWER(priv, "Flags value = 0x%08X\n", cmd->flags); + IWL_DEBUG_POWER(priv, "Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout)); + IWL_DEBUG_POWER(priv, "Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout)); + IWL_DEBUG_POWER(priv, "Sleep interval vector = { %d , %d , %d , %d , %d }\n", le32_to_cpu(cmd->sleep_interval[0]), le32_to_cpu(cmd->sleep_interval[1]), le32_to_cpu(cmd->sleep_interval[2]), @@ -875,8 +875,8 @@ static void iwl3945_setup_rxon_timing(struct iwl_priv *priv) priv->rxon_timing.beacon_init_val = cpu_to_le32((u32) ((u64) interval_tm_unit - result)); - IWL_DEBUG_ASSOC - ("beacon interval %d beacon timer %d beacon tim %d\n", + IWL_DEBUG_ASSOC(priv, + "beacon interval %d beacon timer %d beacon tim %d\n", le16_to_cpu(priv->rxon_timing.beacon_interval), le32_to_cpu(priv->rxon_timing.beacon_init_val), le16_to_cpu(priv->rxon_timing.atim_window)); @@ -885,22 +885,22 @@ static void iwl3945_setup_rxon_timing(struct iwl_priv *priv) static int iwl3945_scan_initiate(struct iwl_priv *priv) { if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_SCAN("Aborting scan due to not ready.\n"); + IWL_DEBUG_SCAN(priv, "Aborting scan due to not ready.\n"); return -EIO; } if (test_bit(STATUS_SCANNING, &priv->status)) { - IWL_DEBUG_SCAN("Scan already in progress.\n"); + IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); return -EAGAIN; } if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_SCAN("Scan request while abort pending. " + IWL_DEBUG_SCAN(priv, "Scan request while abort pending. " "Queuing.\n"); return -EAGAIN; } - IWL_DEBUG_INFO("Starting scan...\n"); + IWL_DEBUG_INFO(priv, "Starting scan...\n"); if (priv->cfg->sku & IWL_SKU_G) priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ); if (priv->cfg->sku & IWL_SKU_A) @@ -941,7 +941,7 @@ static int iwl3945_set_mode(struct iwl_priv *priv, int mode) cancel_delayed_work(&priv->scan_check); if (iwl_scan_cancel_timeout(priv, 100)) { IWL_WARN(priv, "Aborted scan still in progress after 100ms\n"); - IWL_DEBUG_MAC80211("leaving - scan abort failed.\n"); + IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n"); return -EAGAIN; } @@ -964,7 +964,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, case ALG_CCMP: tx->sec_ctl = TX_CMD_SEC_CCM; memcpy(tx->key, keyinfo->key, keyinfo->keylen); - IWL_DEBUG_TX("tx_cmd with AES hwcrypto\n"); + IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); break; case ALG_TKIP: @@ -988,7 +988,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, memcpy(&tx->key[3], keyinfo->key, keyinfo->keylen); - IWL_DEBUG_TX("Configuring packet for WEP encryption " + IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " "with key %d\n", info->control.hw_key->hw_key_idx); break; @@ -1105,7 +1105,7 @@ static int iwl3945_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) if (sta_id != IWL_INVALID_STATION) return sta_id; - IWL_DEBUG_DROP("Station %pM not in station map. " + IWL_DEBUG_DROP(priv, "Station %pM not in station map. " "Defaulting to broadcast...\n", hdr->addr1); iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); @@ -1151,7 +1151,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) spin_lock_irqsave(&priv->lock, flags); if (iwl_is_rfkill(priv)) { - IWL_DEBUG_DROP("Dropping - RF KILL\n"); + IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); goto drop_unlock; } @@ -1167,11 +1167,11 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) #ifdef CONFIG_IWLWIFI_DEBUG if (ieee80211_is_auth(fc)) - IWL_DEBUG_TX("Sending AUTH frame\n"); + IWL_DEBUG_TX(priv, "Sending AUTH frame\n"); else if (ieee80211_is_assoc_req(fc)) - IWL_DEBUG_TX("Sending ASSOC frame\n"); + IWL_DEBUG_TX(priv, "Sending ASSOC frame\n"); else if (ieee80211_is_reassoc_req(fc)) - IWL_DEBUG_TX("Sending REASSOC frame\n"); + IWL_DEBUG_TX(priv, "Sending REASSOC frame\n"); #endif /* drop all data frame if we are not associated */ @@ -1179,7 +1179,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) (priv->iw_mode != NL80211_IFTYPE_MONITOR) && /* packet injection */ (!iwl_is_associated(priv) || ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id))) { - IWL_DEBUG_DROP("Dropping - !iwl_is_associated\n"); + IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n"); goto drop_unlock; } @@ -1190,12 +1190,12 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* Find (or create) index into station table for destination station */ sta_id = iwl3945_get_sta_id(priv, hdr); if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_DROP("Dropping - INVALID STATION: %pM\n", + IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", hdr->addr1); goto drop; } - IWL_DEBUG_RATE("station Id %d\n", sta_id); + IWL_DEBUG_RATE(priv, "station Id %d\n", sta_id); if (ieee80211_is_data_qos(fc)) { qc = ieee80211_get_qos_ctl(hdr); @@ -1351,7 +1351,7 @@ static void iwl3945_radio_kill_sw(struct iwl_priv *priv, int disable_radio) if (!!disable_radio == test_bit(STATUS_RF_KILL_SW, &priv->status)) return; - IWL_DEBUG_RF_KILL("Manual SW RF KILL set to: RADIO %s\n", + IWL_DEBUG_RF_KILL(priv, "Manual SW RF KILL set to: RADIO %s\n", disable_radio ? "OFF" : "ON"); if (disable_radio) { @@ -1384,7 +1384,7 @@ static void iwl3945_radio_kill_sw(struct iwl_priv *priv, int disable_radio) spin_unlock_irqrestore(&priv->lock, flags); if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { - IWL_DEBUG_RF_KILL("Can not turn radio back on - " + IWL_DEBUG_RF_KILL(priv, "Can not turn radio back on - " "disabled by HW switch\n"); return; } @@ -1507,7 +1507,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, switch (spectrum_resp_status) { case 0: /* Command will be handled */ if (res->u.spectrum.id != 0xff) { - IWL_DEBUG_INFO("Replaced existing measurement: %d\n", + IWL_DEBUG_INFO(priv, "Replaced existing measurement: %d\n", res->u.spectrum.id); priv->measurement_status &= ~MEASUREMENT_READY; } @@ -1535,18 +1535,18 @@ static void iwl3945_rx_reply_alive(struct iwl_priv *priv, palive = &pkt->u.alive_frame; - IWL_DEBUG_INFO("Alive ucode status 0x%08X revision " + IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision " "0x%01X 0x%01X\n", palive->is_valid, palive->ver_type, palive->ver_subtype); if (palive->ver_subtype == INITIALIZE_SUBTYPE) { - IWL_DEBUG_INFO("Initialization Alive received.\n"); + IWL_DEBUG_INFO(priv, "Initialization Alive received.\n"); memcpy(&priv->card_alive_init, &pkt->u.alive_frame, sizeof(struct iwl_alive_resp)); pwork = &priv->init_alive_start; } else { - IWL_DEBUG_INFO("Runtime Alive received.\n"); + IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); memcpy(&priv->card_alive, &pkt->u.alive_frame, sizeof(struct iwl_alive_resp)); pwork = &priv->alive_start; @@ -1569,7 +1569,7 @@ static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv, struct iwl_rx_packet *pkt = (void *)rxb->skb->data; #endif - IWL_DEBUG_RX("Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status); + IWL_DEBUG_RX(priv, "Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status); return; } @@ -1595,7 +1595,7 @@ static void iwl3945_rx_spectrum_measure_notif(struct iwl_priv *priv, struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif); if (!report->state) { - IWL_DEBUG(IWL_DL_11H | IWL_DL_INFO, + IWL_DEBUG(priv, IWL_DL_11H | IWL_DL_INFO, "Spectrum Measure Notification: Start\n"); return; } @@ -1611,7 +1611,7 @@ static void iwl3945_rx_pm_sleep_notif(struct iwl_priv *priv, #ifdef CONFIG_IWLWIFI_DEBUG struct iwl_rx_packet *pkt = (void *)rxb->skb->data; struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif); - IWL_DEBUG_RX("sleep mode: %d, src: %d\n", + IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n", sleep->pm_sleep_mode, sleep->pm_wakeup_src); #endif } @@ -1620,7 +1620,7 @@ static void iwl3945_rx_pm_debug_statistics_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = (void *)rxb->skb->data; - IWL_DEBUG_RADIO("Dumping %d bytes of unhandled " + IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " "notification for %s:\n", le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd)); iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, @@ -1660,7 +1660,7 @@ static void iwl3945_rx_beacon_notif(struct iwl_priv *priv, struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status); u8 rate = beacon->beacon_notify_hdr.rate; - IWL_DEBUG_RX("beacon status %x retries %d iss %d " + IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d " "tsf %d %d rate %d\n", le32_to_cpu(beacon->beacon_notify_hdr.status) & TX_STATUS_MSK, beacon->beacon_notify_hdr.failure_frame, @@ -1683,7 +1683,7 @@ static void iwl3945_rx_reply_scan(struct iwl_priv *priv, struct iwl_scanreq_notification *notif = (struct iwl_scanreq_notification *)pkt->u.raw; - IWL_DEBUG_RX("Scan request status = 0x%x\n", notif->status); + IWL_DEBUG_RX(priv, "Scan request status = 0x%x\n", notif->status); #endif } @@ -1695,7 +1695,7 @@ static void iwl3945_rx_scan_start_notif(struct iwl_priv *priv, struct iwl_scanstart_notification *notif = (struct iwl_scanstart_notification *)pkt->u.raw; priv->scan_start_tsf = le32_to_cpu(notif->tsf_low); - IWL_DEBUG_SCAN("Scan start: " + IWL_DEBUG_SCAN(priv, "Scan start: " "%d [802.11%s] " "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n", notif->channel, @@ -1714,7 +1714,7 @@ static void iwl3945_rx_scan_results_notif(struct iwl_priv *priv, (struct iwl_scanresults_notification *)pkt->u.raw; #endif - IWL_DEBUG_SCAN("Scan ch.res: " + IWL_DEBUG_SCAN(priv, "Scan ch.res: " "%d [802.11%s] " "(TSF: 0x%08X:%08X) - %d " "elapsed=%lu usec (%dms since last)\n", @@ -1740,7 +1740,7 @@ static void iwl3945_rx_scan_complete_notif(struct iwl_priv *priv, struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw; #endif - IWL_DEBUG_SCAN("Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n", + IWL_DEBUG_SCAN(priv, "Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n", scan_notif->scanned_channels, scan_notif->tsf_low, scan_notif->tsf_high, scan_notif->status); @@ -1751,7 +1751,7 @@ static void iwl3945_rx_scan_complete_notif(struct iwl_priv *priv, /* The scan completion notification came in, so kill that timer... */ cancel_delayed_work(&priv->scan_check); - IWL_DEBUG_INFO("Scan pass on %sGHz took %dms\n", + IWL_DEBUG_INFO(priv, "Scan pass on %sGHz took %dms\n", (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) ? "2.4" : "5.2", jiffies_to_msecs(elapsed_jiffies @@ -1769,7 +1769,7 @@ static void iwl3945_rx_scan_complete_notif(struct iwl_priv *priv, * then we reset the scan state machine and terminate, * re-queuing another scan if one has been requested */ if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_INFO("Aborted scan completed.\n"); + IWL_DEBUG_INFO(priv, "Aborted scan completed.\n"); clear_bit(STATUS_SCAN_ABORTING, &priv->status); } else { /* If there are more bands on this scan pass reschedule */ @@ -1779,11 +1779,11 @@ static void iwl3945_rx_scan_complete_notif(struct iwl_priv *priv, priv->last_scan_jiffies = jiffies; priv->next_scan_jiffies = 0; - IWL_DEBUG_INFO("Setting scan to off\n"); + IWL_DEBUG_INFO(priv, "Setting scan to off\n"); clear_bit(STATUS_SCANNING, &priv->status); - IWL_DEBUG_INFO("Scan took %dms\n", + IWL_DEBUG_INFO(priv, "Scan took %dms\n", jiffies_to_msecs(elapsed_jiffies(priv->scan_start, jiffies))); queue_work(priv->workqueue, &priv->scan_completed); @@ -1804,7 +1804,7 @@ static void iwl3945_rx_card_state_notif(struct iwl_priv *priv, u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); unsigned long status = priv->status; - IWL_DEBUG_RF_KILL("Card state received: HW:%s SW:%s\n", + IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s\n", (flags & HW_CARD_DISABLED) ? "Kill" : "On", (flags & SW_CARD_DISABLED) ? "Kill" : "On"); @@ -2265,7 +2265,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) fill_rx = 1; /* Rx interrupt, but nothing sent from uCode */ if (i == r) - IWL_DEBUG(IWL_DL_RX | IWL_DL_ISR, "r = %d, i = %d\n", r, i); + IWL_DEBUG(priv, IWL_DL_RX | IWL_DL_ISR, "r = %d, i = %d\n", r, i); while (i != r) { rxb = rxq->queue[i]; @@ -2296,13 +2296,13 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) * handle those that need handling via function in * rx_handlers table. See iwl3945_setup_rx_handlers() */ if (priv->rx_handlers[pkt->hdr.cmd]) { - IWL_DEBUG(IWL_DL_HCMD | IWL_DL_RX | IWL_DL_ISR, + IWL_DEBUG(priv, IWL_DL_HCMD | IWL_DL_RX | IWL_DL_ISR, "r = %d, i = %d, %s, 0x%02x\n", r, i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); } else { /* No handling needed */ - IWL_DEBUG(IWL_DL_HCMD | IWL_DL_RX | IWL_DL_ISR, + IWL_DEBUG(priv, IWL_DL_HCMD | IWL_DL_RX | IWL_DL_ISR, "r %d i %d No handler needed for %s, 0x%02x\n", r, i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); @@ -2353,7 +2353,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) static void iwl3945_enable_interrupts(struct iwl_priv *priv) { - IWL_DEBUG_ISR("Enabling interrupts\n"); + IWL_DEBUG_ISR(priv, "Enabling interrupts\n"); set_bit(STATUS_INT_ENABLED, &priv->status); iwl_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK); } @@ -2379,7 +2379,7 @@ static inline void iwl3945_disable_interrupts(struct iwl_priv *priv) * from uCode or flow handler (Rx/Tx DMA) */ iwl_write32(priv, CSR_INT, 0xffffffff); iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff); - IWL_DEBUG_ISR("Disabled interrupts\n"); + IWL_DEBUG_ISR(priv, "Disabled interrupts\n"); } static const char *desc_lookup(int i) @@ -2604,7 +2604,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) if (priv->debug_level & IWL_DL_ISR) { /* just for debug */ inta_mask = iwl_read32(priv, CSR_INT_MASK); - IWL_DEBUG_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", + IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", inta, inta_mask, inta_fh); } #endif @@ -2638,12 +2638,12 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) if (priv->debug_level & (IWL_DL_ISR)) { /* NIC fires this, but we don't use it, redundant with WAKEUP */ if (inta & CSR_INT_BIT_SCD) - IWL_DEBUG_ISR("Scheduler finished to transmit " + IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " "the frame/frames.\n"); /* Alive notification via Rx interrupt will do the real work */ if (inta & CSR_INT_BIT_ALIVE) - IWL_DEBUG_ISR("Alive interrupt\n"); + IWL_DEBUG_ISR(priv, "Alive interrupt\n"); } #endif /* Safely ignore these bits for debug checks below */ @@ -2659,7 +2659,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) /* uCode wakes up after power-down sleep */ if (inta & CSR_INT_BIT_WAKEUP) { - IWL_DEBUG_ISR("Wakeup interrupt\n"); + IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); iwl_rx_queue_update_write_ptr(priv, &priv->rxq); iwl_txq_update_write_ptr(priv, &priv->txq[0]); iwl_txq_update_write_ptr(priv, &priv->txq[1]); @@ -2680,7 +2680,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) } if (inta & CSR_INT_BIT_FH_TX) { - IWL_DEBUG_ISR("Tx interrupt\n"); + IWL_DEBUG_ISR(priv, "Tx interrupt\n"); iwl_write32(priv, CSR_FH_INT_STATUS, (1 << 6)); if (!iwl_grab_nic_access(priv)) { @@ -2710,7 +2710,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) inta = iwl_read32(priv, CSR_INT); inta_mask = iwl_read32(priv, CSR_INT_MASK); inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); - IWL_DEBUG_ISR("End inta 0x%08x, enabled 0x%08x, fh 0x%08x, " + IWL_DEBUG_ISR(priv, "End inta 0x%08x, enabled 0x%08x, fh 0x%08x, " "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags); } #endif @@ -2742,7 +2742,7 @@ static irqreturn_t iwl3945_isr(int irq, void *data) * This may be due to IRQ shared with another device, * or due to sporadic interrupts thrown from our NIC. */ if (!inta && !inta_fh) { - IWL_DEBUG_ISR("Ignore interrupt, inta == 0, inta_fh == 0\n"); + IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0, inta_fh == 0\n"); goto none; } @@ -2752,7 +2752,7 @@ static irqreturn_t iwl3945_isr(int irq, void *data) goto unplugged; } - IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", + IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", inta, inta_mask, inta_fh); inta &= ~CSR_INT_BIT_SCD; @@ -2806,7 +2806,7 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, ch_info = iwl_get_channel_info(priv, band, scan_ch->channel); if (!is_channel_valid(ch_info)) { - IWL_DEBUG_SCAN("Channel %d is INVALID for this band.\n", + IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n", scan_ch->channel); continue; } @@ -2854,7 +2854,7 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, */ } - IWL_DEBUG_SCAN("Scanning %d [%s %d]\n", + IWL_DEBUG_SCAN(priv, "Scanning %d [%s %d]\n", scan_ch->channel, (scan_ch->type & 1) ? "ACTIVE" : "PASSIVE", (scan_ch->type & 1) ? @@ -2864,7 +2864,7 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, added++; } - IWL_DEBUG_SCAN("total channels to scan %d \n", added); + IWL_DEBUG_SCAN(priv, "total channels to scan %d \n", added); return added; } @@ -2915,7 +2915,7 @@ static int iwl3945_verify_inst_full(struct iwl_priv *priv, __le32 *image, u32 le int rc = 0; u32 errcnt; - IWL_DEBUG_INFO("ucode inst image size is %u\n", len); + IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); rc = iwl_grab_nic_access(priv); if (rc) @@ -2944,7 +2944,8 @@ static int iwl3945_verify_inst_full(struct iwl_priv *priv, __le32 *image, u32 le iwl_release_nic_access(priv); if (!errcnt) - IWL_DEBUG_INFO("ucode image in INSTRUCTION memory is good\n"); + IWL_DEBUG_INFO(priv, + "ucode image in INSTRUCTION memory is good\n"); return rc; } @@ -2962,7 +2963,7 @@ static int iwl3945_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 u32 errcnt = 0; u32 i; - IWL_DEBUG_INFO("ucode inst image size is %u\n", len); + IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); rc = iwl_grab_nic_access(priv); if (rc) @@ -3009,7 +3010,7 @@ static int iwl3945_verify_ucode(struct iwl_priv *priv) len = priv->ucode_boot.len; rc = iwl3945_verify_inst_sparse(priv, image, len); if (rc == 0) { - IWL_DEBUG_INFO("Bootstrap uCode is good in inst SRAM\n"); + IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n"); return 0; } @@ -3018,7 +3019,7 @@ static int iwl3945_verify_ucode(struct iwl_priv *priv) len = priv->ucode_init.len; rc = iwl3945_verify_inst_sparse(priv, image, len); if (rc == 0) { - IWL_DEBUG_INFO("Initialize uCode is good in inst SRAM\n"); + IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n"); return 0; } @@ -3027,7 +3028,7 @@ static int iwl3945_verify_ucode(struct iwl_priv *priv) len = priv->ucode_code.len; rc = iwl3945_verify_inst_sparse(priv, image, len); if (rc == 0) { - IWL_DEBUG_INFO("Runtime uCode is good in inst SRAM\n"); + IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n"); return 0; } @@ -3086,7 +3087,8 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) "which is deprecated. " " Please use API v%u instead.\n", buf, api_max); - IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n", + IWL_DEBUG_INFO(priv, "Got firmware '%s' file " + "(%zd bytes) from disk\n", buf, ucode_raw->size); break; } @@ -3137,13 +3139,18 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) IWL_UCODE_API(priv->ucode_ver), IWL_UCODE_SERIAL(priv->ucode_ver)); - IWL_DEBUG_INFO("f/w package hdr ucode version raw = 0x%x\n", + IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", priv->ucode_ver); - IWL_DEBUG_INFO("f/w package hdr runtime inst size = %u\n", inst_size); - IWL_DEBUG_INFO("f/w package hdr runtime data size = %u\n", data_size); - IWL_DEBUG_INFO("f/w package hdr init inst size = %u\n", init_size); - IWL_DEBUG_INFO("f/w package hdr init data size = %u\n", init_data_size); - IWL_DEBUG_INFO("f/w package hdr boot inst size = %u\n", boot_size); + IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n", + inst_size); + IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %u\n", + data_size); + IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %u\n", + init_size); + IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %u\n", + init_data_size); + IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %u\n", + boot_size); /* Verify size of file vs. image size info in file's header */ @@ -3151,40 +3158,43 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) inst_size + data_size + init_size + init_data_size + boot_size) { - IWL_DEBUG_INFO("uCode file size %d too small\n", - (int)ucode_raw->size); + IWL_DEBUG_INFO(priv, "uCode file size %zd too small\n", + ucode_raw->size); ret = -EINVAL; goto err_release; } /* Verify that uCode images will fit in card's SRAM */ if (inst_size > IWL39_MAX_INST_SIZE) { - IWL_DEBUG_INFO("uCode instr len %d too large to fit in\n", + IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n", inst_size); ret = -EINVAL; goto err_release; } if (data_size > IWL39_MAX_DATA_SIZE) { - IWL_DEBUG_INFO("uCode data len %d too large to fit in\n", + IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n", data_size); ret = -EINVAL; goto err_release; } if (init_size > IWL39_MAX_INST_SIZE) { - IWL_DEBUG_INFO("uCode init instr len %d too large to fit in\n", + IWL_DEBUG_INFO(priv, + "uCode init instr len %d too large to fit in\n", init_size); ret = -EINVAL; goto err_release; } if (init_data_size > IWL39_MAX_DATA_SIZE) { - IWL_DEBUG_INFO("uCode init data len %d too large to fit in\n", + IWL_DEBUG_INFO(priv, + "uCode init data len %d too large to fit in\n", init_data_size); ret = -EINVAL; goto err_release; } if (boot_size > IWL39_MAX_BSM_SIZE) { - IWL_DEBUG_INFO("uCode boot instr len %d too large to fit in\n", + IWL_DEBUG_INFO(priv, + "uCode boot instr len %d too large to fit in\n", boot_size); ret = -EINVAL; goto err_release; @@ -3234,16 +3244,18 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) /* Runtime instructions (first block of data in file) */ src = &ucode->data[0]; len = priv->ucode_code.len; - IWL_DEBUG_INFO("Copying (but not loading) uCode instr len %Zd\n", len); + IWL_DEBUG_INFO(priv, + "Copying (but not loading) uCode instr len %zd\n", len); memcpy(priv->ucode_code.v_addr, src, len); - IWL_DEBUG_INFO("uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", + IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); /* Runtime data (2nd block) * NOTE: Copy into backup buffer will be done in iwl3945_up() */ src = &ucode->data[inst_size]; len = priv->ucode_data.len; - IWL_DEBUG_INFO("Copying (but not loading) uCode data len %Zd\n", len); + IWL_DEBUG_INFO(priv, + "Copying (but not loading) uCode data len %zd\n", len); memcpy(priv->ucode_data.v_addr, src, len); memcpy(priv->ucode_data_backup.v_addr, src, len); @@ -3251,8 +3263,8 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) if (init_size) { src = &ucode->data[inst_size + data_size]; len = priv->ucode_init.len; - IWL_DEBUG_INFO("Copying (but not loading) init instr len %Zd\n", - len); + IWL_DEBUG_INFO(priv, + "Copying (but not loading) init instr len %zd\n", len); memcpy(priv->ucode_init.v_addr, src, len); } @@ -3260,16 +3272,16 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) if (init_data_size) { src = &ucode->data[inst_size + data_size + init_size]; len = priv->ucode_init_data.len; - IWL_DEBUG_INFO("Copying (but not loading) init data len %d\n", - (int)len); + IWL_DEBUG_INFO(priv, + "Copying (but not loading) init data len %zd\n", len); memcpy(priv->ucode_init_data.v_addr, src, len); } /* Bootstrap instructions (5th block) */ src = &ucode->data[inst_size + data_size + init_size + init_data_size]; len = priv->ucode_boot.len; - IWL_DEBUG_INFO("Copying (but not loading) boot instr len %d\n", - (int)len); + IWL_DEBUG_INFO(priv, + "Copying (but not loading) boot instr len %zd\n", len); memcpy(priv->ucode_boot.v_addr, src, len); /* We have our copies now, allow OS release its copies */ @@ -3331,7 +3343,7 @@ static int iwl3945_set_ucode_ptrs(struct iwl_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); - IWL_DEBUG_INFO("Runtime uCode pointers are set.\n"); + IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n"); return rc; } @@ -3349,7 +3361,7 @@ static void iwl3945_init_alive_start(struct iwl_priv *priv) if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { /* We had an error bringing up the hardware, so take it * all the way back down so we can try again */ - IWL_DEBUG_INFO("Initialize Alive failed.\n"); + IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n"); goto restart; } @@ -3359,18 +3371,18 @@ static void iwl3945_init_alive_start(struct iwl_priv *priv) if (iwl3945_verify_ucode(priv)) { /* Runtime instruction load was bad; * take it all the way back down so we can try again */ - IWL_DEBUG_INFO("Bad \"initialize\" uCode load.\n"); + IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n"); goto restart; } /* Send pointers to protocol/runtime uCode image ... init code will * load and launch runtime uCode, which will send us another "Alive" * notification. */ - IWL_DEBUG_INFO("Initialization Alive received.\n"); + IWL_DEBUG_INFO(priv, "Initialization Alive received.\n"); if (iwl3945_set_ucode_ptrs(priv)) { /* Runtime instruction load won't happen; * take it all the way back down so we can try again */ - IWL_DEBUG_INFO("Couldn't set up uCode pointers.\n"); + IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n"); goto restart; } return; @@ -3395,12 +3407,12 @@ static void iwl3945_alive_start(struct iwl_priv *priv) int thermal_spin = 0; u32 rfkill; - IWL_DEBUG_INFO("Runtime Alive received.\n"); + IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); if (priv->card_alive.is_valid != UCODE_VALID_OK) { /* We had an error bringing up the hardware, so take it * all the way back down so we can try again */ - IWL_DEBUG_INFO("Alive failed.\n"); + IWL_DEBUG_INFO(priv, "Alive failed.\n"); goto restart; } @@ -3410,7 +3422,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) if (iwl3945_verify_ucode(priv)) { /* Runtime instruction load was bad; * take it all the way back down so we can try again */ - IWL_DEBUG_INFO("Bad runtime uCode load.\n"); + IWL_DEBUG_INFO(priv, "Bad runtime uCode load.\n"); goto restart; } @@ -3423,7 +3435,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) } rfkill = iwl_read_prph(priv, APMG_RFKILL_REG); - IWL_DEBUG_INFO("RFKILL status: 0x%x\n", rfkill); + IWL_DEBUG_INFO(priv, "RFKILL status: 0x%x\n", rfkill); iwl_release_nic_access(priv); if (rfkill & 0x1) { @@ -3436,7 +3448,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) } if (thermal_spin) - IWL_DEBUG_INFO("Thermal calibration took %dus\n", + IWL_DEBUG_INFO(priv, "Thermal calibration took %dus\n", thermal_spin * 10); } else set_bit(STATUS_RF_KILL_HW, &priv->status); @@ -3479,7 +3491,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) iwl3945_led_register(priv); - IWL_DEBUG_INFO("ALIVE processing complete.\n"); + IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); set_bit(STATUS_READY, &priv->status); wake_up_interruptible(&priv->wait_command_queue); @@ -3508,7 +3520,7 @@ static void __iwl3945_down(struct iwl_priv *priv) int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status); struct ieee80211_conf *conf = NULL; - IWL_DEBUG_INFO(DRV_NAME " is going down\n"); + IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n"); conf = ieee80211_get_hw_conf(priv->hw); @@ -3695,7 +3707,7 @@ static int __iwl3945_up(struct iwl_priv *priv) /* start card; "initialize" will load runtime ucode */ iwl3945_nic_start(priv); - IWL_DEBUG_INFO(DRV_NAME " is coming up\n"); + IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n"); return 0; } @@ -3796,34 +3808,36 @@ static void iwl3945_bg_request_scan(struct work_struct *data) /* This should never be called or scheduled if there is currently * a scan active in the hardware. */ if (test_bit(STATUS_SCAN_HW, &priv->status)) { - IWL_DEBUG_INFO("Multiple concurrent scan requests in parallel. " - "Ignoring second request.\n"); + IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests " + "Ignoring second request.\n"); rc = -EIO; goto done; } if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { - IWL_DEBUG_SCAN("Aborting scan due to device shutdown\n"); + IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n"); goto done; } if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_HC("Scan request while abort pending. Queuing.\n"); + IWL_DEBUG_HC(priv, + "Scan request while abort pending. Queuing.\n"); goto done; } if (iwl_is_rfkill(priv)) { - IWL_DEBUG_HC("Aborting scan due to RF Kill activation\n"); + IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n"); goto done; } if (!test_bit(STATUS_READY, &priv->status)) { - IWL_DEBUG_HC("Scan request while uninitialized. Queuing.\n"); + IWL_DEBUG_HC(priv, + "Scan request while uninitialized. Queuing.\n"); goto done; } if (!priv->scan_bands) { - IWL_DEBUG_HC("Aborting scan due to no requested bands\n"); + IWL_DEBUG_HC(priv, "Aborting scan due to no requested bands\n"); goto done; } @@ -3848,7 +3862,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) u32 scan_suspend_time = 100; unsigned long flags; - IWL_DEBUG_INFO("Scanning while associated...\n"); + IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); spin_lock_irqsave(&priv->lock, flags); interval = priv->beacon_int; @@ -3870,15 +3884,14 @@ static void iwl3945_bg_request_scan(struct work_struct *data) (extra | ((suspend_time % interval) * 1024)); scan->suspend_time = cpu_to_le32(scan_suspend_time); - IWL_DEBUG_SCAN("suspend_time 0x%X beacon interval %d\n", + IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n", scan_suspend_time, interval); } /* We should add the ability for user to lock to PASSIVE ONLY */ if (priv->one_direct_scan) { - IWL_DEBUG_SCAN - ("Kicking off one direct scan for '%s'\n", - print_ssid(ssid, priv->direct_ssid, + IWL_DEBUG_SCAN(priv, "Kicking off one direct scan for '%s'\n", + print_ssid(ssid, priv->direct_ssid, priv->direct_ssid_len)); scan->direct_scan[0].id = WLAN_EID_SSID; scan->direct_scan[0].len = priv->direct_ssid_len; @@ -3886,7 +3899,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) priv->direct_ssid, priv->direct_ssid_len); n_probes++; } else - IWL_DEBUG_SCAN("Kicking off one indirect scan.\n"); + IWL_DEBUG_SCAN(priv, "Kicking off one indirect scan.\n"); /* We don't build a direct scan probe request; the uCode will do * that based on the direct_mask added to each channel entry */ @@ -3927,7 +3940,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); if (scan->channel_count == 0) { - IWL_DEBUG_SCAN("channel count %d\n", scan->channel_count); + IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); goto done; } @@ -4011,7 +4024,7 @@ static void iwl3945_post_associate(struct iwl_priv *priv) } - IWL_DEBUG_ASSOC("Associated as %d to: %pM\n", + IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", priv->assoc_id, priv->active_rxon.bssid_addr); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) @@ -4039,7 +4052,7 @@ static void iwl3945_post_associate(struct iwl_priv *priv) priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); - IWL_DEBUG_ASSOC("assoc id %d beacon interval %d\n", + IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", priv->assoc_id, priv->beacon_int); if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) @@ -4105,7 +4118,7 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) struct iwl_priv *priv = hw->priv; int ret; - IWL_DEBUG_MAC80211("enter\n"); + IWL_DEBUG_MAC80211(priv, "enter\n"); /* we should be verifying the device is ready to be opened */ mutex_lock(&priv->mutex); @@ -4132,7 +4145,7 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) if (ret) goto out_release_irq; - IWL_DEBUG_INFO("Start UP work.\n"); + IWL_DEBUG_INFO(priv, "Start UP work.\n"); if (test_bit(STATUS_IN_SUSPEND, &priv->status)) return 0; @@ -4157,12 +4170,12 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) cancel_delayed_work(&priv->rfkill_poll); priv->is_open = 1; - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); return 0; out_release_irq: priv->is_open = 0; - IWL_DEBUG_MAC80211("leave - failed\n"); + IWL_DEBUG_MAC80211(priv, "leave - failed\n"); return ret; } @@ -4170,10 +4183,10 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw) { struct iwl_priv *priv = hw->priv; - IWL_DEBUG_MAC80211("enter\n"); + IWL_DEBUG_MAC80211(priv, "enter\n"); if (!priv->is_open) { - IWL_DEBUG_MAC80211("leave - skip\n"); + IWL_DEBUG_MAC80211(priv, "leave - skip\n"); return; } @@ -4196,22 +4209,22 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw) queue_delayed_work(priv->workqueue, &priv->rfkill_poll, round_jiffies_relative(2 * HZ)); - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); } static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct iwl_priv *priv = hw->priv; - IWL_DEBUG_MAC80211("enter\n"); + IWL_DEBUG_MAC80211(priv, "enter\n"); - IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, + IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); if (iwl3945_tx_skb(priv, skb)) dev_kfree_skb_any(skb); - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); return NETDEV_TX_OK; } @@ -4221,10 +4234,10 @@ static int iwl3945_mac_add_interface(struct ieee80211_hw *hw, struct iwl_priv *priv = hw->priv; unsigned long flags; - IWL_DEBUG_MAC80211("enter: type %d\n", conf->type); + IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type); if (priv->vif) { - IWL_DEBUG_MAC80211("leave - vif != NULL\n"); + IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); return -EOPNOTSUPP; } @@ -4237,7 +4250,7 @@ static int iwl3945_mac_add_interface(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); if (conf->mac_addr) { - IWL_DEBUG_MAC80211("Set: %pM\n", conf->mac_addr); + IWL_DEBUG_MAC80211(priv, "Set: %pM\n", conf->mac_addr); memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); } @@ -4246,7 +4259,7 @@ static int iwl3945_mac_add_interface(struct ieee80211_hw *hw, mutex_unlock(&priv->mutex); - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); return 0; } @@ -4266,17 +4279,18 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed) int ret = 0; mutex_lock(&priv->mutex); - IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value); + IWL_DEBUG_MAC80211(priv, "enter to channel %d\n", + conf->channel->hw_value); if (!iwl_is_ready(priv)) { - IWL_DEBUG_MAC80211("leave - not ready\n"); + IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); ret = -EIO; goto out; } if (unlikely(!iwl3945_mod_params.disable_hw_scan && test_bit(STATUS_SCANNING, &priv->status))) { - IWL_DEBUG_MAC80211("leave - scanning\n"); + IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); set_bit(STATUS_CONF_PENDING, &priv->status); mutex_unlock(&priv->mutex); return 0; @@ -4287,9 +4301,10 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed) ch_info = iwl_get_channel_info(priv, conf->channel->band, conf->channel->hw_value); if (!is_channel_valid(ch_info)) { - IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this band.\n", - conf->channel->hw_value, conf->channel->band); - IWL_DEBUG_MAC80211("leave - invalid channel\n"); + IWL_DEBUG_SCAN(priv, + "Channel %d [%d] is INVALID for this band.\n", + conf->channel->hw_value, conf->channel->band); + IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); spin_unlock_irqrestore(&priv->lock, flags); ret = -EINVAL; goto out; @@ -4316,12 +4331,12 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed) iwl3945_radio_kill_sw(priv, !conf->radio_enabled); if (!conf->radio_enabled) { - IWL_DEBUG_MAC80211("leave - radio disabled\n"); + IWL_DEBUG_MAC80211(priv, "leave - radio disabled\n"); goto out; } if (iwl_is_rfkill(priv)) { - IWL_DEBUG_MAC80211("leave - RF kill\n"); + IWL_DEBUG_MAC80211(priv, "leave - RF kill\n"); ret = -EIO; goto out; } @@ -4332,9 +4347,9 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed) &priv->staging_rxon, sizeof(priv->staging_rxon))) iwl3945_commit_rxon(priv); else - IWL_DEBUG_INFO("No re-sending same RXON configuration.\n"); + IWL_DEBUG_INFO(priv, "Not re-sending same RXON configuration\n"); - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); out: clear_bit(STATUS_CONF_PENDING, &priv->status); @@ -4411,7 +4426,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, return -EIO; if (priv->vif != vif) { - IWL_DEBUG_MAC80211("leave - priv->vif != vif\n"); + IWL_DEBUG_MAC80211(priv, "leave - priv->vif != vif\n"); return 0; } @@ -4434,7 +4449,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); if (conf->bssid) - IWL_DEBUG_MAC80211("bssid: %pM\n", conf->bssid); + IWL_DEBUG_MAC80211(priv, "bssid: %pM\n", conf->bssid); /* * very dubious code was here; the probe filtering flag is never set: @@ -4447,7 +4462,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, if (!conf->bssid) { conf->bssid = priv->mac_addr; memcpy(priv->bssid, priv->mac_addr, ETH_ALEN); - IWL_DEBUG_MAC80211("bssid was set to: %pM\n", + IWL_DEBUG_MAC80211(priv, "bssid was set to: %pM\n", conf->bssid); } if (priv->ibss_beacon) @@ -4466,7 +4481,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, if (iwl_scan_cancel_timeout(priv, 100)) { IWL_WARN(priv, "Aborted scan still in progress " "after 100ms\n"); - IWL_DEBUG_MAC80211("leaving - scan abort failed.\n"); + IWL_DEBUG_MAC80211(priv, "leaving:scan abort failed\n"); mutex_unlock(&priv->mutex); return -EAGAIN; } @@ -4494,7 +4509,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, } done: - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); mutex_unlock(&priv->mutex); return 0; @@ -4505,7 +4520,7 @@ static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw, { struct iwl_priv *priv = hw->priv; - IWL_DEBUG_MAC80211("enter\n"); + IWL_DEBUG_MAC80211(priv, "enter\n"); mutex_lock(&priv->mutex); @@ -4520,7 +4535,7 @@ static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw, } mutex_unlock(&priv->mutex); - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); } #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) @@ -4532,10 +4547,10 @@ static void iwl3945_bss_info_changed(struct ieee80211_hw *hw, { struct iwl_priv *priv = hw->priv; - IWL_DEBUG_MAC80211("changes = 0x%X\n", changes); + IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes); if (changes & BSS_CHANGED_ERP_PREAMBLE) { - IWL_DEBUG_MAC80211("ERP_PREAMBLE %d\n", + IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n", bss_conf->use_short_preamble); if (bss_conf->use_short_preamble) priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; @@ -4545,7 +4560,8 @@ static void iwl3945_bss_info_changed(struct ieee80211_hw *hw, } if (changes & BSS_CHANGED_ERP_CTS_PROT) { - IWL_DEBUG_MAC80211("ERP_CTS %d\n", bss_conf->use_cts_prot); + IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", + bss_conf->use_cts_prot); if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; else @@ -4553,7 +4569,7 @@ static void iwl3945_bss_info_changed(struct ieee80211_hw *hw, } if (changes & BSS_CHANGED_ASSOC) { - IWL_DEBUG_MAC80211("ASSOC %d\n", bss_conf->assoc); + IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc); /* This should never happen as this function should * never be called from interrupt context. */ if (WARN_ON_ONCE(in_interrupt())) @@ -4571,10 +4587,12 @@ static void iwl3945_bss_info_changed(struct ieee80211_hw *hw, mutex_unlock(&priv->mutex); } else { priv->assoc_id = 0; - IWL_DEBUG_MAC80211("DISASSOC %d\n", bss_conf->assoc); + IWL_DEBUG_MAC80211(priv, + "DISASSOC %d\n", bss_conf->assoc); } } else if (changes && iwl_is_associated(priv) && priv->assoc_id) { - IWL_DEBUG_MAC80211("Associated Changes %d\n", changes); + IWL_DEBUG_MAC80211(priv, + "Associated Changes %d\n", changes); iwl3945_send_rxon_assoc(priv); } @@ -4587,14 +4605,14 @@ static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) struct iwl_priv *priv = hw->priv; DECLARE_SSID_BUF(ssid_buf); - IWL_DEBUG_MAC80211("enter\n"); + IWL_DEBUG_MAC80211(priv, "enter\n"); mutex_lock(&priv->mutex); spin_lock_irqsave(&priv->lock, flags); if (!iwl_is_ready_rf(priv)) { rc = -EIO; - IWL_DEBUG_MAC80211("leave - not ready or exit pending\n"); + IWL_DEBUG_MAC80211(priv, "leave - not ready or exit pending\n"); goto out_unlock; } @@ -4612,8 +4630,8 @@ static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) goto out_unlock; } if (len) { - IWL_DEBUG_SCAN("direct scan for %s [%d]\n ", - print_ssid(ssid_buf, ssid, len), (int)len); + IWL_DEBUG_SCAN(priv, "direct scan for %s [%zd]\n ", + print_ssid(ssid_buf, ssid, len), len); priv->one_direct_scan = 1; priv->direct_ssid_len = (u8) @@ -4624,7 +4642,7 @@ static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) rc = iwl3945_scan_initiate(priv); - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); out_unlock: spin_unlock_irqrestore(&priv->lock, flags); @@ -4643,17 +4661,17 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, int ret; u8 sta_id; - IWL_DEBUG_MAC80211("enter\n"); + IWL_DEBUG_MAC80211(priv, "enter\n"); if (iwl3945_mod_params.sw_crypto) { - IWL_DEBUG_MAC80211("leave - hwcrypto disabled\n"); + IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n"); return -EOPNOTSUPP; } addr = sta ? sta->addr : iwl_bcast_addr; sta_id = iwl3945_hw_find_station(priv, addr); if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_MAC80211("leave - %pM not in station map.\n", + IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", addr); return -EINVAL; } @@ -4669,7 +4687,8 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, iwl_set_rxon_hwcrypto(priv, 1); iwl3945_commit_rxon(priv); key->hw_key_idx = sta_id; - IWL_DEBUG_MAC80211("set_key success, using hwcrypto\n"); + IWL_DEBUG_MAC80211(priv, + "set_key success, using hwcrypto\n"); key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; } break; @@ -4678,14 +4697,14 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (!ret) { iwl_set_rxon_hwcrypto(priv, 0); iwl3945_commit_rxon(priv); - IWL_DEBUG_MAC80211("disable hwcrypto key\n"); + IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n"); } break; default: ret = -EINVAL; } - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); mutex_unlock(&priv->mutex); return ret; @@ -4698,15 +4717,15 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, unsigned long flags; int q; - IWL_DEBUG_MAC80211("enter\n"); + IWL_DEBUG_MAC80211(priv, "enter\n"); if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211("leave - RF not ready\n"); + IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); return -EIO; } if (queue >= AC_NUM) { - IWL_DEBUG_MAC80211("leave - queue >= AC_NUM %d\n", queue); + IWL_DEBUG_MAC80211(priv, "leave - queue >= AC_NUM %d\n", queue); return 0; } @@ -4733,7 +4752,7 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, mutex_unlock(&priv->mutex); - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); return 0; } @@ -4746,10 +4765,10 @@ static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw, struct iwl_queue *q; unsigned long flags; - IWL_DEBUG_MAC80211("enter\n"); + IWL_DEBUG_MAC80211(priv, "enter\n"); if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211("leave - RF not ready\n"); + IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); return -EIO; } @@ -4767,7 +4786,7 @@ static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw, } spin_unlock_irqrestore(&priv->lock, flags); - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); return 0; } @@ -4778,7 +4797,7 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) unsigned long flags; mutex_lock(&priv->mutex); - IWL_DEBUG_MAC80211("enter\n"); + IWL_DEBUG_MAC80211(priv, "enter\n"); iwl_reset_qos(priv); @@ -4800,7 +4819,7 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) spin_unlock_irqrestore(&priv->lock, flags); if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211("leave - not ready\n"); + IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); mutex_unlock(&priv->mutex); return; } @@ -4817,7 +4836,7 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) /* Per mac80211.h: This is only used in IBSS mode... */ if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { - IWL_DEBUG_MAC80211("leave - not in IBSS\n"); + IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n"); mutex_unlock(&priv->mutex); return; } @@ -4826,7 +4845,7 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) mutex_unlock(&priv->mutex); - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); } @@ -4835,15 +4854,15 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk struct iwl_priv *priv = hw->priv; unsigned long flags; - IWL_DEBUG_MAC80211("enter\n"); + IWL_DEBUG_MAC80211(priv, "enter\n"); if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211("leave - RF not ready\n"); + IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); return -EIO; } if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { - IWL_DEBUG_MAC80211("leave - not IBSS\n"); + IWL_DEBUG_MAC80211(priv, "leave - not IBSS\n"); return -EIO; } @@ -4856,7 +4875,7 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk priv->assoc_id = 0; - IWL_DEBUG_MAC80211("leave\n"); + IWL_DEBUG_MAC80211(priv, "leave\n"); spin_unlock_irqrestore(&priv->lock, flags); iwl_reset_qos(priv); @@ -4971,7 +4990,7 @@ static ssize_t store_flags(struct device *d, if (iwl_scan_cancel_timeout(priv, 100)) IWL_WARN(priv, "Could not cancel scan.\n"); else { - IWL_DEBUG_INFO("Committing rxon.flags = 0x%04X\n", + IWL_DEBUG_INFO(priv, "Committing rxon.flags = 0x%04X\n", flags); priv->staging_rxon.flags = cpu_to_le32(flags); iwl3945_commit_rxon(priv); @@ -5006,7 +5025,7 @@ static ssize_t store_filter_flags(struct device *d, if (iwl_scan_cancel_timeout(priv, 100)) IWL_WARN(priv, "Could not cancel scan.\n"); else { - IWL_DEBUG_INFO("Committing rxon.filter_flags = " + IWL_DEBUG_INFO(priv, "Committing rxon.filter_flags = " "0x%04X\n", filter_flags); priv->staging_rxon.filter_flags = cpu_to_le32(filter_flags); @@ -5083,7 +5102,7 @@ static ssize_t store_measurement(struct device *d, type = simple_strtoul(p + 1, NULL, 0); } - IWL_DEBUG_INFO("Invoking measurement of type %d on " + IWL_DEBUG_INFO(priv, "Invoking measurement of type %d on " "channel %d (for '%s')\n", type, params.channel, buf); iwl3945_get_measurement(priv, ¶ms, type); @@ -5142,7 +5161,7 @@ static ssize_t store_power_level(struct device *d, if (mode != priv->power_mode) { rc = iwl3945_send_power_mode(priv, IWL_POWER_LEVEL(mode)); if (rc) { - IWL_DEBUG_MAC80211("failed setting power mode.\n"); + IWL_DEBUG_MAC80211(priv, "failed setting power mode\n"); goto out; } priv->power_mode = mode; @@ -5277,15 +5296,15 @@ static ssize_t store_antenna(struct device *d, return 0; if (sscanf(buf, "%1i", &ant) != 1) { - IWL_DEBUG_INFO("not in hex or decimal form.\n"); + IWL_DEBUG_INFO(priv, "not in hex or decimal form.\n"); return count; } if ((ant >= 0) && (ant <= 2)) { - IWL_DEBUG_INFO("Setting antenna select to %d.\n", ant); + IWL_DEBUG_INFO(priv, "Setting antenna select to %d.\n", ant); iwl3945_mod_params.antenna = (enum iwl3945_antenna)ant; } else - IWL_DEBUG_INFO("Bad antenna select value %d.\n", ant); + IWL_DEBUG_INFO(priv, "Bad antenna select value %d.\n", ant); return count; @@ -5532,12 +5551,12 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e * "the hard way", rather than using device's scan. */ if (iwl3945_mod_params.disable_hw_scan) { - IWL_DEBUG_INFO("Disabling hw_scan\n"); + IWL_DEBUG_INFO(priv, "Disabling hw_scan\n"); iwl3945_hw_ops.hw_scan = NULL; } - IWL_DEBUG_INFO("*** LOAD DRIVER ***\n"); + IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); priv->cfg = cfg; priv->pci_dev = pdev; @@ -5593,9 +5612,9 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e goto out_pci_release_regions; } - IWL_DEBUG_INFO("pci_resource_len = 0x%08llx\n", + IWL_DEBUG_INFO(priv, "pci_resource_len = 0x%08llx\n", (unsigned long long) pci_resource_len(pdev, 0)); - IWL_DEBUG_INFO("pci_resource_base = %p\n", priv->hw_base); + IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base); /* We disable the RETRY_TIMEOUT register (0x41) to keep * PCI Tx retries from interfering with C3 CPU state */ @@ -5604,7 +5623,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e /* amp init */ err = priv->cfg->ops->lib->apm_ops.init(priv); if (err < 0) { - IWL_DEBUG_INFO("Failed to init APMG\n"); + IWL_DEBUG_INFO(priv, "Failed to init APMG\n"); goto out_iounmap; } @@ -5621,7 +5640,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e /* MAC Address location in EEPROM same for 3945/4965 */ eeprom = (struct iwl3945_eeprom *)priv->eeprom; memcpy(priv->mac_addr, eeprom->mac_address, ETH_ALEN); - IWL_DEBUG_INFO("MAC address: %pM\n", priv->mac_addr); + IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->mac_addr); SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); /*********************** @@ -5654,7 +5673,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e /* Disable radio (SW RF KILL) via parameter when loading driver */ if (iwl3945_mod_params.disable) { set_bit(STATUS_RF_KILL_SW, &priv->status); - IWL_DEBUG_INFO("Radio disabled.\n"); + IWL_DEBUG_INFO(priv, "Radio disabled.\n"); } @@ -5743,7 +5762,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) if (!priv) return; - IWL_DEBUG_INFO("*** UNLOAD DRIVER ***\n"); + IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); set_bit(STATUS_EXIT_PENDING, &priv->status); -- GitLab From d25aabb0a1a2f659206ba21f6ac8ec28047e5595 Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Tue, 27 Jan 2009 14:27:58 -0800 Subject: [PATCH 1458/4982] iwlwifi: unify iwlagn and 3945 power save management This patch unifies 3945 and iwlagn power save management This patch also better separates system state from user setting. System state shall be removed later as this shall be shifted to user space Signed-off-by: Tomas Winkler Acked-by: Mohamed Abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 6 +- drivers/net/wireless/iwlwifi/iwl-core.c | 4 +- drivers/net/wireless/iwlwifi/iwl-power.c | 17 +- drivers/net/wireless/iwlwifi/iwl-power.h | 14 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 261 ++++---------------- 5 files changed, 60 insertions(+), 242 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 8ff5798ad64..cb6db4525dc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1063,7 +1063,7 @@ static int iwl3945_apm_init(struct iwl_priv *priv) { int ret = 0; - iwl3945_power_init_handle(priv); + iwl_power_initialize(priv); iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); @@ -2372,7 +2372,9 @@ static u16 iwl3945_get_hcmd_size(u8 cmd_id, u16 len) { switch (cmd_id) { case REPLY_RXON: - return (u16) sizeof(struct iwl3945_rxon_cmd); + return sizeof(struct iwl3945_rxon_cmd); + case POWER_TABLE_CMD: + return sizeof(struct iwl3945_powertable_cmd); default: return len; } diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 5f92cfbe926..e18c3f326f7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1355,8 +1355,8 @@ int iwl_init_drv(struct iwl_priv *priv) priv->qos_data.qos_cap.val = 0; priv->rates_mask = IWL_RATES_MASK; - /* If power management is turned on, default to AC mode */ - priv->power_mode = IWL_POWER_AC; + /* If power management is turned on, default to CAM mode */ + priv->power_mode = IWL_POWER_MODE_CAM; priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MAX; ret = iwl_init_channel_map(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index abe0d2966a5..4c5a775f48b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -102,6 +102,7 @@ static struct iwl_power_vec_entry range_2[IWL_POWER_MAX] = { {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0} }; + /* set card power command */ static int iwl_set_power(struct iwl_priv *priv, void *cmd) { @@ -126,13 +127,6 @@ static u16 iwl_get_auto_power_mode(struct iwl_priv *priv) else mode = IWL_POWER_ON_AC_DISASSOC; break; - /* FIXME: remove battery and ac from here */ - case IWL_POWER_BATTERY: - mode = IWL_POWER_INDEX_3; - break; - case IWL_POWER_AC: - mode = IWL_POWER_MODE_CAM; - break; default: mode = priv->power_data.user_power_setting; break; @@ -357,7 +351,7 @@ EXPORT_SYMBOL(iwl_power_enable_management); /* set user_power_setting */ int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode) { - if (mode > IWL_POWER_LIMIT) + if (mode > IWL_POWER_MAX) return -EINVAL; priv->power_data.user_power_setting = mode; @@ -371,11 +365,10 @@ EXPORT_SYMBOL(iwl_power_set_user_mode); */ int iwl_power_set_system_mode(struct iwl_priv *priv, u16 mode) { - if (mode > IWL_POWER_LIMIT) + if (mode < IWL_POWER_SYS_MAX) + priv->power_data.system_power_setting = mode; + else return -EINVAL; - - priv->power_data.system_power_setting = mode; - return iwl_power_update_mode(priv, 0); } EXPORT_SYMBOL(iwl_power_set_system_mode); diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h index 859b60b5335..879eafdd736 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/iwl-power.h @@ -42,27 +42,15 @@ enum { IWL_POWER_INDEX_5, IWL_POWER_AUTO, IWL_POWER_MAX = IWL_POWER_AUTO, - IWL39_POWER_AC = IWL_POWER_AUTO, /* 0x06 */ - IWL_POWER_AC, - IWL39_POWER_BATTERY = IWL_POWER_AC, /* 0x07 */ - IWL39_POWER_LIMIT = IWL_POWER_AC, - IWL_POWER_BATTERY, }; enum { IWL_POWER_SYS_AUTO, IWL_POWER_SYS_AC, IWL_POWER_SYS_BATTERY, + IWL_POWER_SYS_MAX, }; -#define IWL_POWER_LIMIT 0x08 -#define IWL_POWER_MASK 0x0F -#define IWL_POWER_ENABLED 0x10 - -#define IWL_POWER_RANGE_0 (0) -#define IWL_POWER_RANGE_1 (1) - -#define IWL_POWER_LEVEL(x) ((x) & IWL_POWER_MASK) /* Power management (not Tx power) structures */ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index ac337177fdb..800e46c9a68 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -656,162 +656,6 @@ static void iwl3945_activate_qos(struct iwl_priv *priv, u8 force) } } -/* - * Power management (not Tx power!) functions - */ -#define MSEC_TO_USEC 1024 - - -/* default power management (not Tx power) table values */ -/* for TIM 0-10 */ -static struct iwl_power_vec_entry range_0[IWL_POWER_MAX] = { - {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, - {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0}, - {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 7)}, 0}, - {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 6, 9, 9, 10)}, 0}, - {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 7, 9, 9, 10)}, 1}, - {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 10)}, 1} -}; - -/* for TIM > 10 */ -static struct iwl_power_vec_entry range_1[IWL_POWER_MAX] = { - {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, - {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0}, - {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0}, - {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 6, 9, 9, 0xFF)}, 0}, - {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0}, - {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0} -}; - -int iwl3945_power_init_handle(struct iwl_priv *priv) -{ - int rc = 0, i; - struct iwl_power_mgr *pow_data; - int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_MAX; - u16 pci_pm; - - IWL_DEBUG_POWER(priv, "Initialize power \n"); - - pow_data = &priv->power_data; - - memset(pow_data, 0, sizeof(*pow_data)); - - pow_data->dtim_period = 1; - - memcpy(&pow_data->pwr_range_0[0], &range_0[0], size); - memcpy(&pow_data->pwr_range_1[0], &range_1[0], size); - - rc = pci_read_config_word(priv->pci_dev, PCI_LINK_CTRL, &pci_pm); - if (rc != 0) - return 0; - else { - struct iwl_powertable_cmd *cmd; - - IWL_DEBUG_POWER(priv, "adjust power command flags\n"); - - for (i = 0; i < IWL_POWER_MAX; i++) { - cmd = &pow_data->pwr_range_0[i].cmd; - - if (pci_pm & 0x1) - cmd->flags &= ~IWL_POWER_PCI_PM_MSK; - else - cmd->flags |= IWL_POWER_PCI_PM_MSK; - } - } - return rc; -} - -static int iwl3945_update_power_cmd(struct iwl_priv *priv, - struct iwl_powertable_cmd *cmd, u32 mode) -{ - struct iwl_power_mgr *pow_data; - struct iwl_power_vec_entry *range; - u32 max_sleep = 0; - int i; - u8 period = 0; - bool skip; - - if (mode > IWL_POWER_INDEX_5) { - IWL_DEBUG_POWER(priv, "Error invalid power mode \n"); - return -EINVAL; - } - pow_data = &priv->power_data; - - if (pow_data->dtim_period < 10) - range = &pow_data->pwr_range_0[0]; - else - range = &pow_data->pwr_range_1[1]; - - memcpy(cmd, &range[mode].cmd, sizeof(struct iwl3945_powertable_cmd)); - - - if (period == 0) { - period = 1; - skip = false; - } else { - skip = !!range[mode].no_dtim; - } - - if (skip) { - __le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]; - max_sleep = (le32_to_cpu(slp_itrvl) / period) * period; - cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK; - } else { - max_sleep = period; - cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK; - } - - for (i = 0; i < IWL_POWER_VEC_SIZE; i++) - if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep) - cmd->sleep_interval[i] = cpu_to_le32(max_sleep); - - IWL_DEBUG_POWER(priv, "Flags value = 0x%08X\n", cmd->flags); - IWL_DEBUG_POWER(priv, "Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout)); - IWL_DEBUG_POWER(priv, "Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout)); - IWL_DEBUG_POWER(priv, "Sleep interval vector = { %d , %d , %d , %d , %d }\n", - le32_to_cpu(cmd->sleep_interval[0]), - le32_to_cpu(cmd->sleep_interval[1]), - le32_to_cpu(cmd->sleep_interval[2]), - le32_to_cpu(cmd->sleep_interval[3]), - le32_to_cpu(cmd->sleep_interval[4])); - - return 0; -} - -static int iwl3945_send_power_mode(struct iwl_priv *priv, u32 mode) -{ - u32 uninitialized_var(final_mode); - int rc; - struct iwl_powertable_cmd cmd; - - /* If on battery, set to 3, - * if plugged into AC power, set to CAM ("continuously aware mode"), - * else user level */ - switch (mode) { - case IWL39_POWER_BATTERY: - final_mode = IWL_POWER_INDEX_3; - break; - case IWL39_POWER_AC: - final_mode = IWL_POWER_MODE_CAM; - break; - default: - final_mode = mode; - break; - } - - iwl3945_update_power_cmd(priv, &cmd, final_mode); - - /* FIXME use get_hcmd_size 3945 command is 4 bytes shorter */ - rc = iwl_send_cmd_pdu(priv, POWER_TABLE_CMD, - sizeof(struct iwl3945_powertable_cmd), &cmd); - - if (final_mode == IWL_POWER_MODE_CAM) - clear_bit(STATUS_POWER_PMI, &priv->status); - else - set_bit(STATUS_POWER_PMI, &priv->status); - - return rc; -} #define MAX_UCODE_BEACON_INTERVAL 1024 #define INTEL_CONN_LISTEN_INTERVAL __constant_cpu_to_le16(0xA) @@ -3467,7 +3311,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) priv->active_rate = priv->rates_mask; priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; - iwl3945_send_power_mode(priv, IWL_POWER_LEVEL(priv->power_mode)); + iwl_power_update_mode(priv, false); if (iwl_is_associated(priv)) { struct iwl3945_rxon_cmd *active_rxon = @@ -5136,44 +4980,70 @@ static ssize_t show_retry_rate(struct device *d, static DEVICE_ATTR(retry_rate, S_IWUSR | S_IRUSR, show_retry_rate, store_retry_rate); + static ssize_t store_power_level(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { struct iwl_priv *priv = dev_get_drvdata(d); - int rc; - int mode; + int ret; + unsigned long mode; + - mode = simple_strtoul(buf, NULL, 0); mutex_lock(&priv->mutex); if (!iwl_is_ready(priv)) { - rc = -EAGAIN; + ret = -EAGAIN; goto out; } - if ((mode < 1) || (mode > IWL39_POWER_LIMIT) || - (mode == IWL39_POWER_AC)) - mode = IWL39_POWER_AC; - else - mode |= IWL_POWER_ENABLED; + ret = strict_strtoul(buf, 10, &mode); + if (ret) + goto out; - if (mode != priv->power_mode) { - rc = iwl3945_send_power_mode(priv, IWL_POWER_LEVEL(mode)); - if (rc) { - IWL_DEBUG_MAC80211(priv, "failed setting power mode\n"); - goto out; - } - priv->power_mode = mode; + ret = iwl_power_set_user_mode(priv, mode); + if (ret) { + IWL_DEBUG_MAC80211(priv, "failed setting power mode.\n"); + goto out; } - - rc = count; + ret = count; out: mutex_unlock(&priv->mutex); - return rc; + return ret; } +static ssize_t show_power_level(struct device *d, + struct device_attribute *attr, char *buf) +{ + struct iwl_priv *priv = dev_get_drvdata(d); + int mode = priv->power_data.user_power_setting; + int system = priv->power_data.system_power_setting; + int level = priv->power_data.power_mode; + char *p = buf; + + switch (system) { + case IWL_POWER_SYS_AUTO: + p += sprintf(p, "SYSTEM:auto"); + break; + case IWL_POWER_SYS_AC: + p += sprintf(p, "SYSTEM:ac"); + break; + case IWL_POWER_SYS_BATTERY: + p += sprintf(p, "SYSTEM:battery"); + break; + } + + p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO) ? + "fixed" : "auto"); + p += sprintf(p, "\tINDEX:%d", level); + p += sprintf(p, "\n"); + return p - buf + 1; +} + +static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, + show_power_level, store_power_level); + #define MAX_WX_STRING 80 /* Values are in microsecond */ @@ -5192,41 +5062,6 @@ static const s32 period_duration[] = { 1000000 }; -static ssize_t show_power_level(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - int level = IWL_POWER_LEVEL(priv->power_mode); - char *p = buf; - - p += sprintf(p, "%d ", level); - switch (level) { - case IWL_POWER_MODE_CAM: - case IWL39_POWER_AC: - p += sprintf(p, "(AC)"); - break; - case IWL39_POWER_BATTERY: - p += sprintf(p, "(BATTERY)"); - break; - default: - p += sprintf(p, - "(Timeout %dms, Period %dms)", - timeout_duration[level - 1] / 1000, - period_duration[level - 1] / 1000); - } - - if (!(priv->power_mode & IWL_POWER_ENABLED)) - p += sprintf(p, " OFF\n"); - else - p += sprintf(p, " \n"); - - return p - buf + 1; - -} - -static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level, - store_power_level); - static ssize_t show_channels(struct device *d, struct device_attribute *attr, char *buf) { @@ -5469,8 +5304,8 @@ static int iwl3945_init_drv(struct iwl_priv *priv) priv->qos_data.qos_cap.val = 0; priv->rates_mask = IWL_RATES_MASK; - /* If power management is turned on, default to AC mode */ - priv->power_mode = IWL39_POWER_AC; + /* If power management is turned on, default to CAM mode */ + priv->power_mode = IWL_POWER_MODE_CAM; priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER; if (eeprom->version < EEPROM_3945_EEPROM_VERSION) { -- GitLab From 382fe0f2da78db7833c6a7278e33e694e6e2a6f3 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Wed, 28 Jan 2009 00:32:13 +0100 Subject: [PATCH 1459/4982] rt2x00: Move intf_work to mac82011 workqueue ieee80211_iterate_active_interfaces() no longer acquires the RTNL lock which means the intf_work handler can be safely used from the mac80211 workqueue again. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index e1b40545a9b..e681d239d43 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -215,7 +215,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) rt2x00lib_beacondone_iter, rt2x00dev); - schedule_work(&rt2x00dev->intf_work); + queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); } EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); -- GitLab From a2c9b652a12a550d3d8509e9bae43bac396c5076 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Wed, 28 Jan 2009 00:32:33 +0100 Subject: [PATCH 1460/4982] rt2x00: Add kill_tx_queue callback function provide rt2x00lib the possibility to kill a particular TX queue. This can be useful when disabling the radio, but more importantly will allow beaconing to be disabled when mac80211 requests this (during scanning for example) Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 30 ++++++----- drivers/net/wireless/rt2x00/rt2500pci.c | 30 ++++++----- drivers/net/wireless/rt2x00/rt2500usb.c | 1 + drivers/net/wireless/rt2x00/rt2x00.h | 2 + drivers/net/wireless/rt2x00/rt2x00dev.c | 5 +- drivers/net/wireless/rt2x00/rt2x00lib.h | 13 ++++- drivers/net/wireless/rt2x00/rt2x00mac.c | 6 ++- drivers/net/wireless/rt2x00/rt2x00queue.c | 19 ++++++- drivers/net/wireless/rt2x00/rt2x00usb.c | 62 ++++++++++++++--------- drivers/net/wireless/rt2x00/rt2x00usb.h | 11 ++++ drivers/net/wireless/rt2x00/rt61pci.c | 37 ++++++++------ drivers/net/wireless/rt2x00/rt73usb.c | 1 + 12 files changed, 145 insertions(+), 72 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 4a2c0b971ca..b0848259b45 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -934,21 +934,10 @@ static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev) static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev) { - u32 reg; - - rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0); - /* - * Disable synchronisation. + * Disable power */ - rt2x00pci_register_write(rt2x00dev, CSR14, 0); - - /* - * Cancel RX and TX. - */ - rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); - rt2x00_set_field32(®, TXCSR0_ABORT, 1); - rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0); } static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev, @@ -1145,6 +1134,20 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); } +static void rt2400pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev, + const enum data_queue_qid qid) +{ + u32 reg; + + if (qid == QID_BEACON) { + rt2x00pci_register_write(rt2x00dev, CSR14, 0); + } else { + rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); + rt2x00_set_field32(®, TXCSR0_ABORT, 1); + rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + } +} + /* * RX control handlers */ @@ -1606,6 +1609,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .write_beacon = rt2400pci_write_beacon, .kick_tx_queue = rt2400pci_kick_tx_queue, + .kill_tx_queue = rt2400pci_kill_tx_queue, .fill_rxdone = rt2400pci_fill_rxdone, .config_filter = rt2400pci_config_filter, .config_intf = rt2400pci_config_intf, diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index b9104e28bc2..eb82860c54f 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1093,21 +1093,10 @@ static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev) static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev) { - u32 reg; - - rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0); - /* - * Disable synchronisation. + * Disable power */ - rt2x00pci_register_write(rt2x00dev, CSR14, 0); - - /* - * Cancel RX and TX. - */ - rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); - rt2x00_set_field32(®, TXCSR0_ABORT, 1); - rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0); } static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev, @@ -1303,6 +1292,20 @@ static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); } +static void rt2500pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev, + const enum data_queue_qid qid) +{ + u32 reg; + + if (qid == QID_BEACON) { + rt2x00pci_register_write(rt2x00dev, CSR14, 0); + } else { + rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); + rt2x00_set_field32(®, TXCSR0_ABORT, 1); + rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + } +} + /* * RX control handlers */ @@ -1905,6 +1908,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .write_beacon = rt2500pci_write_beacon, .kick_tx_queue = rt2500pci_kick_tx_queue, + .kill_tx_queue = rt2500pci_kill_tx_queue, .fill_rxdone = rt2500pci_fill_rxdone, .config_filter = rt2500pci_config_filter, .config_intf = rt2500pci_config_intf, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index c526e737fca..270691ac236 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1935,6 +1935,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .write_beacon = rt2500usb_write_beacon, .get_tx_data_len = rt2500usb_get_tx_data_len, .kick_tx_queue = rt2500usb_kick_tx_queue, + .kill_tx_queue = rt2x00usb_kill_tx_queue, .fill_rxdone = rt2500usb_fill_rxdone, .config_shared_key = rt2500usb_config_key, .config_pairwise_key = rt2500usb_config_key, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index d0a82563818..94fb571667f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -508,6 +508,8 @@ struct rt2x00lib_ops { int (*get_tx_data_len) (struct queue_entry *entry); void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev, const enum data_queue_qid queue); + void (*kill_tx_queue) (struct rt2x00_dev *rt2x00dev, + const enum data_queue_qid queue); /* * RX control handlers diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index e681d239d43..05f94e21b42 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -83,9 +83,10 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) return; /* - * Stop the TX queues. + * Stop the TX queues in mac80211. */ ieee80211_stop_queues(rt2x00dev->hw); + rt2x00queue_stop_queues(rt2x00dev); /* * Disable RX. @@ -157,7 +158,7 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, return; if (delayed_flags & DELAYED_UPDATE_BEACON) - rt2x00queue_update_beacon(rt2x00dev, vif); + rt2x00queue_update_beacon(rt2x00dev, vif, true); if (delayed_flags & DELAYED_CONFIG_ERP) rt2x00lib_config_erp(rt2x00dev, intf, &conf); diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 34efe465354..a631613177d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -123,9 +123,11 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb); * rt2x00queue_update_beacon - Send new beacon from mac80211 to hardware * @rt2x00dev: Pointer to &struct rt2x00_dev. * @vif: Interface for which the beacon should be updated. + * @enable_beacon: Enable beaconing */ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, - struct ieee80211_vif *vif); + struct ieee80211_vif *vif, + const bool enable_beacon); /** * rt2x00queue_index_inc - Index incrementation function @@ -138,6 +140,15 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, */ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index); +/** + * rt2x00queue_stop_queues - Halt all data queues + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * + * This function will loop through all available queues to stop + * any pending outgoing frames. + */ +void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev); + /** * rt2x00queue_init_queues - Initialize all data queues * @rt2x00dev: Pointer to &struct rt2x00_dev. diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 71de8a7144f..c41a0b9e473 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -431,8 +431,10 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, /* * Update the beacon. */ - if (conf->changed & IEEE80211_IFCC_BEACON) - status = rt2x00queue_update_beacon(rt2x00dev, vif); + if (conf->changed & (IEEE80211_IFCC_BEACON | + IEEE80211_IFCC_BEACON_ENABLED)) + status = rt2x00queue_update_beacon(rt2x00dev, vif, + conf->enable_beacon); return status; } diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index c86fb647175..a5664bd8493 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -443,7 +443,8 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) } int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, - struct ieee80211_vif *vif) + struct ieee80211_vif *vif, + const bool enable_beacon) { struct rt2x00_intf *intf = vif_to_intf(vif); struct skb_frame_desc *skbdesc; @@ -453,6 +454,11 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, if (unlikely(!intf->beacon)) return -ENOBUFS; + if (!enable_beacon) { + rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev, QID_BEACON); + return 0; + } + intf->beacon->skb = ieee80211_beacon_get(rt2x00dev->hw, vif); if (!intf->beacon->skb) return -ENOMEM; @@ -501,6 +507,9 @@ struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, { int atim = test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); + if (queue == QID_RX) + return rt2x00dev->rx; + if (queue < rt2x00dev->ops->tx_queues && rt2x00dev->tx) return &rt2x00dev->tx[queue]; @@ -577,6 +586,14 @@ static void rt2x00queue_reset(struct data_queue *queue) spin_unlock_irqrestore(&queue->lock, irqflags); } +void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev) +{ + struct data_queue *queue; + + txall_queue_for_each(rt2x00dev, queue) + rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev, queue->qid); +} + void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev) { struct data_queue *queue; diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index c89d1520838..7d50ca82375 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -296,6 +296,41 @@ void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, } EXPORT_SYMBOL_GPL(rt2x00usb_kick_tx_queue); +void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev, + const enum data_queue_qid qid) +{ + struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, qid); + struct queue_entry_priv_usb *entry_priv; + struct queue_entry_priv_usb_bcn *bcn_priv; + unsigned int i; + bool kill_guard; + + /* + * When killing the beacon queue, we must also kill + * the beacon guard byte. + */ + kill_guard = + (qid == QID_BEACON) && + (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)); + + /* + * Cancel all entries. + */ + for (i = 0; i < queue->limit; i++) { + entry_priv = queue->entries[i].priv_data; + usb_kill_urb(entry_priv->urb); + + /* + * Kill guardian urb (if required by driver). + */ + if (kill_guard) { + bcn_priv = queue->entries[i].priv_data; + usb_kill_urb(bcn_priv->guardian_urb); + } + } +} +EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue); + /* * RX data handlers. */ @@ -338,35 +373,14 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) */ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev) { - struct queue_entry_priv_usb *entry_priv; - struct queue_entry_priv_usb_bcn *bcn_priv; - struct data_queue *queue; - unsigned int i; - rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0, 0, REGISTER_TIMEOUT); /* - * Cancel all queues. + * The USB version of kill_tx_queue also works + * on the RX queue. */ - queue_for_each(rt2x00dev, queue) { - for (i = 0; i < queue->limit; i++) { - entry_priv = queue->entries[i].priv_data; - usb_kill_urb(entry_priv->urb); - } - } - - /* - * Kill guardian urb (if required by driver). - */ - if (!test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)) - return; - - for (i = 0; i < rt2x00dev->bcn->limit; i++) { - bcn_priv = rt2x00dev->bcn->entries[i].priv_data; - if (bcn_priv->guardian_urb) - usb_kill_urb(bcn_priv->guardian_urb); - } + rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev, QID_RX); } EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio); diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index fe4523887bd..bd2d59c85f1 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -419,6 +419,17 @@ struct queue_entry_priv_usb_bcn { void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, const enum data_queue_qid qid); +/** + * rt2x00usb_kill_tx_queue - Kill data queue + * @rt2x00dev: Pointer to &struct rt2x00_dev + * @qid: Data queue to kill + * + * This will walk through all entries of the queue and kill all + * previously kicked frames before they can be send. + */ +void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev, + const enum data_queue_qid qid); + /* * Device initialization handlers. */ diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index d81a8de9dc1..c7ad1b3d476 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1696,24 +1696,10 @@ static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev) static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev) { - u32 reg; - - rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x00001818); - - /* - * Disable synchronisation. - */ - rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0); - /* - * Cancel RX and TX. + * Disable power */ - rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC0, 1); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC1, 1); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC2, 1); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC3, 1); - rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); + rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x00001818); } static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) @@ -1936,6 +1922,24 @@ static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); } +static void rt61pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev, + const enum data_queue_qid qid) +{ + u32 reg; + + if (qid == QID_BEACON) { + rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0); + return; + } + + rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); + rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC0, (qid == QID_AC_BE)); + rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC1, (qid == QID_AC_BK)); + rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC2, (qid == QID_AC_VI)); + rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC3, (qid == QID_AC_VO)); + rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); +} + /* * RX control handlers */ @@ -2761,6 +2765,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .write_beacon = rt61pci_write_beacon, .kick_tx_queue = rt61pci_kick_tx_queue, + .kill_tx_queue = rt61pci_kill_tx_queue, .fill_rxdone = rt61pci_fill_rxdone, .config_shared_key = rt61pci_config_shared_key, .config_pairwise_key = rt61pci_config_pairwise_key, diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index f854551be75..24e97b341cf 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2293,6 +2293,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .write_beacon = rt73usb_write_beacon, .get_tx_data_len = rt73usb_get_tx_data_len, .kick_tx_queue = rt73usb_kick_tx_queue, + .kill_tx_queue = rt2x00usb_kill_tx_queue, .fill_rxdone = rt73usb_fill_rxdone, .config_shared_key = rt73usb_config_shared_key, .config_pairwise_key = rt73usb_config_pairwise_key, -- GitLab From 0cbe0064614ace61e08618948f82c6d525e75017 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Wed, 28 Jan 2009 00:33:47 +0100 Subject: [PATCH 1461/4982] rt2x00: Validate firmware in driver The get_firmware_crc() callback function isn't flexible enough when dealing with multiple firmware versions. It might in some cases be possible that the firmware file contains multiple CRC checksums. Create the check_firmware() callback function where the driver has complete freedom in how to validate the firmware. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 7 +++-- drivers/net/wireless/rt2x00/rt2x00firmware.c | 27 ++++++++++++------ drivers/net/wireless/rt2x00/rt2x00reg.h | 10 +++++++ drivers/net/wireless/rt2x00/rt61pci.c | 29 ++++++++++++-------- drivers/net/wireless/rt2x00/rt73usb.c | 29 ++++++++++++-------- 5 files changed, 68 insertions(+), 34 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 94fb571667f..84bd6f19acb 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -468,9 +468,10 @@ struct rt2x00lib_ops { */ int (*probe_hw) (struct rt2x00_dev *rt2x00dev); char *(*get_firmware_name) (struct rt2x00_dev *rt2x00dev); - u16 (*get_firmware_crc) (const void *data, const size_t len); - int (*load_firmware) (struct rt2x00_dev *rt2x00dev, const void *data, - const size_t len); + int (*check_firmware) (struct rt2x00_dev *rt2x00dev, + const u8 *data, const size_t len); + int (*load_firmware) (struct rt2x00_dev *rt2x00dev, + const u8 *data, const size_t len); /* * Device initialization/deinitialization handlers. diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c index 2a7e8bc0016..d2deea2f267 100644 --- a/drivers/net/wireless/rt2x00/rt2x00firmware.c +++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c @@ -35,7 +35,6 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev) const struct firmware *fw; char *fw_name; int retval; - u16 crc; /* * Read correct firmware from harddisk. @@ -61,16 +60,26 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev) return -ENOENT; } - crc = rt2x00dev->ops->lib->get_firmware_crc(fw->data, fw->size); - if (crc != (fw->data[fw->size - 2] << 8 | fw->data[fw->size - 1])) { - ERROR(rt2x00dev, "Firmware checksum error.\n"); - retval = -ENOENT; - goto exit; - } - INFO(rt2x00dev, "Firmware detected - version: %d.%d.\n", fw->data[fw->size - 4], fw->data[fw->size - 3]); + retval = rt2x00dev->ops->lib->check_firmware(rt2x00dev, fw->data, fw->size); + switch (retval) { + case FW_OK: + break; + case FW_BAD_CRC: + ERROR(rt2x00dev, "Firmware checksum error.\n"); + goto exit; + case FW_BAD_LENGTH: + ERROR(rt2x00dev, + "Invalid firmware file length (len=%zu)\n", fw->size); + goto exit; + case FW_BAD_VERSION: + ERROR(rt2x00dev, + "Current firmware does not support detected chipset.\n"); + goto exit; + }; + rt2x00dev->fw = fw; return 0; @@ -78,7 +87,7 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev) exit: release_firmware(fw); - return retval; + return -ENOENT; } int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev) diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index 9ddc2d07eef..861322d97fc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h @@ -134,6 +134,16 @@ enum rate_modulation { RATE_MODE_HT_GREENFIELD = 3, }; +/* + * Firmware validation error codes + */ +enum firmware_errors { + FW_OK, + FW_BAD_CRC, + FW_BAD_LENGTH, + FW_BAD_VERSION, +}; + /* * Register handlers. * We store the position of a register field inside a field structure, diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index c7ad1b3d476..0be147f364e 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1176,34 +1176,41 @@ static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev) return fw_name; } -static u16 rt61pci_get_firmware_crc(const void *data, const size_t len) +static int rt61pci_check_firmware(struct rt2x00_dev *rt2x00dev, + const u8 *data, const size_t len) { + u16 fw_crc; u16 crc; /* - * Use the crc itu-t algorithm. + * Only support 8kb firmware files. + */ + if (len != 8192) + return FW_BAD_LENGTH; + + /* * The last 2 bytes in the firmware array are the crc checksum itself, * this means that we should never pass those 2 bytes to the crc * algorithm. */ + fw_crc = (data[len - 2] << 8 | data[len - 1]); + + /* + * Use the crc itu-t algorithm. + */ crc = crc_itu_t(0, data, len - 2); crc = crc_itu_t_byte(crc, 0); crc = crc_itu_t_byte(crc, 0); - return crc; + return (fw_crc == crc) ? FW_OK : FW_BAD_CRC; } -static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, const void *data, - const size_t len) +static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, + const u8 *data, const size_t len) { int i; u32 reg; - if (len != 8192) { - ERROR(rt2x00dev, "Invalid firmware file length (len=%zu)\n", len); - return -ENOENT; - } - /* * Wait for stable hardware. */ @@ -2750,7 +2757,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .irq_handler = rt61pci_interrupt, .probe_hw = rt61pci_probe_hw, .get_firmware_name = rt61pci_get_firmware_name, - .get_firmware_crc = rt61pci_get_firmware_crc, + .check_firmware = rt61pci_check_firmware, .load_firmware = rt61pci_load_firmware, .initialize = rt2x00pci_initialize, .uninitialize = rt2x00pci_uninitialize, diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 24e97b341cf..be791a43c05 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1061,35 +1061,42 @@ static char *rt73usb_get_firmware_name(struct rt2x00_dev *rt2x00dev) return FIRMWARE_RT2571; } -static u16 rt73usb_get_firmware_crc(const void *data, const size_t len) +static int rt73usb_check_firmware(struct rt2x00_dev *rt2x00dev, + const u8 *data, const size_t len) { + u16 fw_crc; u16 crc; /* - * Use the crc itu-t algorithm. + * Only support 2kb firmware files. + */ + if (len != 2048) + return FW_BAD_LENGTH; + + /* * The last 2 bytes in the firmware array are the crc checksum itself, * this means that we should never pass those 2 bytes to the crc * algorithm. */ + fw_crc = (data[len - 2] << 8 | data[len - 1]); + + /* + * Use the crc itu-t algorithm. + */ crc = crc_itu_t(0, data, len - 2); crc = crc_itu_t_byte(crc, 0); crc = crc_itu_t_byte(crc, 0); - return crc; + return (fw_crc == crc) ? FW_OK : FW_BAD_CRC; } -static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, const void *data, - const size_t len) +static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, + const u8 *data, const size_t len) { unsigned int i; int status; u32 reg; - if (len != 2048) { - ERROR(rt2x00dev, "Invalid firmware file length (len=%zu)\n", len); - return -ENOENT; - } - /* * Wait for stable hardware. */ @@ -2278,7 +2285,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .probe_hw = rt73usb_probe_hw, .get_firmware_name = rt73usb_get_firmware_name, - .get_firmware_crc = rt73usb_get_firmware_crc, + .check_firmware = rt73usb_check_firmware, .load_firmware = rt73usb_load_firmware, .initialize = rt2x00usb_initialize, .uninitialize = rt2x00usb_uninitialize, -- GitLab From d22b0022e75b37e5c5a995754fcf9f61b39022d2 Mon Sep 17 00:00:00 2001 From: Sujith Date: Wed, 28 Jan 2009 11:55:45 +0530 Subject: [PATCH 1462/4982] ath9k: Fix lockdep warning This patch fixes the lockdep warning shown below, and also initializes the starting sequence number when starting a TX aggregation session. ============================================= [ INFO: possible recursive locking detected ] 2.6.29-rc2-wl #21 --------------------------------------------- swapper/0 is trying to acquire lock: (_xmit_IEEE80211#2){-+..}, at: [] __qdisc_run+0x221/0x290 but task is already holding lock: (_xmit_IEEE80211#2){-+..}, at: [] __qdisc_run+0x221/0x290 other info that might help us debug this: 7 locks held by swapper/0: #0: (rcu_read_lock){..--}, at: [] dev_queue_xmit+0x53/0x620 #1: (_xmit_ETHER#2){-+..}, at: [] __qdisc_run+0x221/0x290 #2: (rcu_read_lock){..--}, at: [] dev_queue_xmit+0x53/0x620 #3: (_xmit_IEEE80211#2){-+..}, at: [] __qdisc_run+0x221/0x290 #4: (rcu_read_lock){..--}, at: [] ieee80211_master_start_xmit+0x219/0x6c0 [mac80211] #5: (rcu_read_lock){..--}, at: [] ieee80211_start_tx_ba_session+0x66/0x4e0 [mac80211] #6: (rcu_read_lock){..--}, at: [] dev_queue_xmit+0x53/0x620 stack backtrace: Pid: 0, comm: swapper Not tainted 2.6.29-rc2-wl #21 Call Trace: [] __lock_acquire+0x1be9/0x1c40 [] dev_queue_xmit+0xe1/0x620 [] __lock_acquire+0x18c/0x1c40 [] lock_acquire+0x55/0x70 [] __qdisc_run+0x221/0x290 [] _spin_lock+0x39/0x50 [] __qdisc_run+0x221/0x290 [] _spin_unlock+0x1f/0x50 [] __qdisc_run+0x221/0x290 [] dev_queue_xmit+0x308/0x620 [] dev_queue_xmit+0x53/0x620 [] ieee80211_start_tx_ba_session+0x303/0x4e0 [mac80211] [] ieee80211_start_tx_ba_session+0x66/0x4e0 [mac80211] [] rate_control_get_rate+0xae/0xc0 [mac80211] [] invoke_tx_handlers+0x655/0x1000 [mac80211] [] mark_held_locks+0x4d/0x90 [] _spin_unlock_irqrestore+0x65/0x80 [] __ieee80211_tx_prepare+0x16a/0x310 [mac80211] [] __ieee80211_tx_prepare+0x19c/0x310 [mac80211] [] pskb_expand_head+0x112/0x190 [] ieee80211_master_start_xmit+0x286/0x6c0 [mac80211] [] ieee80211_master_start_xmit+0x219/0x6c0 [mac80211] [] __lock_acquire+0x18c/0x1c40 [] __qdisc_run+0x23e/0x290 [] dev_queue_xmit+0x308/0x620 [] dev_queue_xmit+0x53/0x620 [] ieee80211_subif_start_xmit+0x4a1/0x980 [mac80211] [] ieee80211_subif_start_xmit+0x198/0x980 [mac80211] [] __qdisc_run+0x23e/0x290 [] dev_queue_xmit+0x308/0x620 [] dev_queue_xmit+0x53/0x620 [] ip6_output+0x62d/0x1230 [ipv6] [] __mod_timer+0xb0/0xd0 [] mld_sendpack+0x3fa/0x4a0 [ipv6] [] mld_sendpack+0x0/0x4a0 [ipv6] [] mld_ifc_timer_expire+0x0/0x340 [ipv6] [] mld_ifc_timer_expire+0x289/0x340 [ipv6] [] mld_ifc_timer_expire+0x0/0x340 [ipv6] [] run_timer_softirq+0x147/0x220 [] __do_softirq+0x9b/0x180 [] tick_dev_program_event+0x36/0xb0 [] call_softirq+0x1c/0x30 [] do_softirq+0x65/0xb0 [] irq_exit+0x9d/0xc0 [] smp_apic_timer_interrupt+0x86/0xd0 [] apic_timer_interrupt+0x13/0x20 Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/rc.c | 30 ++++++++++++++---------------- drivers/net/wireless/ath9k/xmit.c | 1 + 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index eb557add656..61c86c4f9fc 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -1479,6 +1479,20 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, (is_underrun) ? ATH_11N_TXMAXTRY : tx_info_priv->tx.ts_longretry); + /* Check if aggregation has to be enabled for this tid */ + if (conf_is_ht(&sc->hw->conf)) { + if (ieee80211_is_data_qos(fc)) { + u8 *qc, tid; + struct ath_node *an; + + qc = ieee80211_get_qos_ctl(hdr); + tid = qc[0] & 0xf; + an = (struct ath_node *)sta->drv_priv; + + if(ath_tx_aggr_check(sc, an, tid)) + ieee80211_start_tx_ba_session(sc->hw, hdr->addr1, tid); + } + } exit: kfree(tx_info_priv); } @@ -1490,7 +1504,6 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb = txrc->skb; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ath_softc *sc = priv; - struct ieee80211_hw *hw = sc->hw; struct ath_rate_priv *ath_rc_priv = priv_sta; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); int is_probe = 0; @@ -1508,21 +1521,6 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, /* Find tx rate for unicast frames */ ath_rc_ratefind(sc, ath_rc_priv, ATH_11N_TXMAXTRY, 4, tx_info, &is_probe, false); - - /* Check if aggregation has to be enabled for this tid */ - if (conf_is_ht(&hw->conf)) { - if (ieee80211_is_data_qos(fc)) { - u8 *qc, tid; - struct ath_node *an; - - qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & 0xf; - an = (struct ath_node *)sta->drv_priv; - - if(ath_tx_aggr_check(sc, an, tid)) - ieee80211_start_tx_ba_session(hw, hdr->addr1, tid); - } - } } static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 007ca91188d..d483f3c1350 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -677,6 +677,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, txtid = ATH_AN_2_TID(an, tid); txtid->state |= AGGR_ADDBA_PROGRESS; ath_tx_pause_tid(sc, txtid); + *ssn = txtid->seq_start; } return 0; -- GitLab From 4e30ffa29c1388006e5d36d5ea8c5b46b38b36d5 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Wed, 28 Jan 2009 20:53:27 +0530 Subject: [PATCH 1463/4982] ath9k: Enable MIB and TIM interrupts for station mode. Enable operating mode specific interrupts in ath9k_add_interface instead of ath9k_start. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 40 ++++++++++++++++--------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index d8e826659c1..91f7a7b69a3 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1957,25 +1957,6 @@ static int ath9k_start(struct ieee80211_hw *hw) if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) sc->sc_imask |= ATH9K_INT_CST; - /* - * Enable MIB interrupts when there are hardware phy counters. - * Note we only do this (at the moment) for station mode. - */ - if (ath9k_hw_phycounters(sc->sc_ah) && - ((sc->sc_ah->ah_opmode == NL80211_IFTYPE_STATION) || - (sc->sc_ah->ah_opmode == NL80211_IFTYPE_ADHOC))) - sc->sc_imask |= ATH9K_INT_MIB; - /* - * Some hardware processes the TIM IE and fires an - * interrupt when the TIM bit is set. For hardware - * that does, if not overridden by configuration, - * enable the TIM interrupt when operating as station. - */ - if ((sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_ENHANCEDPM) && - (sc->sc_ah->ah_opmode == NL80211_IFTYPE_STATION) && - !sc->sc_config.swBeaconProcess) - sc->sc_imask |= ATH9K_INT_TIM; - ath_cache_conf_rate(sc, &hw->conf); sc->sc_flags &= ~SC_OP_INVALID; @@ -2124,6 +2105,27 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, /* Set the device opmode */ sc->sc_ah->ah_opmode = ic_opmode; + /* + * Enable MIB interrupts when there are hardware phy counters. + * Note we only do this (at the moment) for station mode. + */ + if (ath9k_hw_phycounters(sc->sc_ah) && + ((conf->type == NL80211_IFTYPE_STATION) || + (conf->type == NL80211_IFTYPE_ADHOC))) + sc->sc_imask |= ATH9K_INT_MIB; + /* + * Some hardware processes the TIM IE and fires an + * interrupt when the TIM bit is set. For hardware + * that does, if not overridden by configuration, + * enable the TIM interrupt when operating as station. + */ + if ((sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_ENHANCEDPM) && + (conf->type == NL80211_IFTYPE_STATION) && + !sc->sc_config.swBeaconProcess) + sc->sc_imask |= ATH9K_INT_TIM; + + ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask); + if (conf->type == NL80211_IFTYPE_AP) { /* TODO: is this a suitable place to start ANI for AP mode? */ /* Start ANI */ -- GitLab From 8c63c46d58c9dca6d0bfacfb41958c55d9b75ea0 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 28 Jan 2009 12:17:47 -0800 Subject: [PATCH 1464/4982] ath9k: replace usage of internal wireless_modes for conf No need to use our internal wireless mode variable when cfg80211 already has its own. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/regd.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath9k/regd.c b/drivers/net/wireless/ath9k/regd.c index ec88f78743e..b84fbe30109 100644 --- a/drivers/net/wireless/ath9k/regd.c +++ b/drivers/net/wireless/ath9k/regd.c @@ -158,8 +158,6 @@ const struct ieee80211_regdomain *ath9k_world_regdomain(struct ath_hal *ah) static void ath9k_reg_apply_5ghz_adhoc_flags(struct wiphy *wiphy, enum reg_set_by setby) { - struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct ath_softc *sc = hw->priv; struct ieee80211_supported_band *sband; const struct ieee80211_reg_rule *reg_rule; struct ieee80211_channel *ch; @@ -169,8 +167,7 @@ static void ath9k_reg_apply_5ghz_adhoc_flags(struct wiphy *wiphy, if (setby != REGDOM_SET_BY_COUNTRY_IE) return; - if (!test_bit(ATH9K_MODE_11A, - sc->sc_ah->ah_caps.wireless_modes)) + if (!wiphy->bands[IEEE80211_BAND_5GHZ]) return; sband = wiphy->bands[IEEE80211_BAND_5GHZ]; -- GitLab From 547e4c2e64d0be5e8491abb49ee6b0f0f8272de1 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 28 Jan 2009 12:17:48 -0800 Subject: [PATCH 1465/4982] ath9k: move check for radar freqs into a helper This will be used later. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/regd.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath9k/regd.c b/drivers/net/wireless/ath9k/regd.c index b84fbe30109..cccec40139c 100644 --- a/drivers/net/wireless/ath9k/regd.c +++ b/drivers/net/wireless/ath9k/regd.c @@ -154,6 +154,12 @@ const struct ieee80211_regdomain *ath9k_world_regdomain(struct ath_hal *ah) } } +/* Frequency is one where radar detection is required */ +static bool ath9k_is_radar_freq(u16 center_freq) +{ + return (center_freq >= 5260 && center_freq <= 5700); +} + /* Enable adhoc on 5 GHz if allowed by 11d */ static void ath9k_reg_apply_5ghz_adhoc_flags(struct wiphy *wiphy, enum reg_set_by setby) @@ -247,9 +253,7 @@ void ath9k_reg_apply_radar_flags(struct wiphy *wiphy) for (i = 0; i < sband->n_channels; i++) { ch = &sband->channels[i]; - if (ch->center_freq < 5260) - continue; - if (ch->center_freq > 5700) + if (!ath9k_is_radar_freq(ch->center_freq)) continue; /* We always enable radar detection/DFS on this * frequency range. Additionally we also apply on -- GitLab From 7519a8f0778bdb14f07cf685fa5fee6ab07e734c Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 28 Jan 2009 12:17:49 -0800 Subject: [PATCH 1466/4982] ath9k: remove passive scan on 5 GHz if country IE knows better If we have new found information about our location and the current country regulatory domain does not have passive scan flag requirements we should be able to actively scan now on those channels. Since AP functionality is not allowed where passive scan flags are set this means if you have a world regulatory domain and you get a country IE that allows that channel (with active scan) then we lift the passive-scan requirement so you can then use AP mode. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/regd.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath9k/regd.c b/drivers/net/wireless/ath9k/regd.c index cccec40139c..dfcc3b5274c 100644 --- a/drivers/net/wireless/ath9k/regd.c +++ b/drivers/net/wireless/ath9k/regd.c @@ -160,8 +160,12 @@ static bool ath9k_is_radar_freq(u16 center_freq) return (center_freq >= 5260 && center_freq <= 5700); } -/* Enable adhoc on 5 GHz if allowed by 11d */ -static void ath9k_reg_apply_5ghz_adhoc_flags(struct wiphy *wiphy, +/* + * Enable adhoc on 5 GHz if allowed by 11d. + * Remove passive scan if channel is allowed by 11d, + * except when on radar frequencies. + */ +static void ath9k_reg_apply_5ghz_beaconing_flags(struct wiphy *wiphy, enum reg_set_by setby) { struct ieee80211_supported_band *sband; @@ -189,6 +193,10 @@ static void ath9k_reg_apply_5ghz_adhoc_flags(struct wiphy *wiphy, * probe */ if (!(reg_rule->flags & NL80211_RRF_NO_IBSS)) ch->flags &= ~NL80211_RRF_NO_IBSS; + if (!ath9k_is_radar_freq(ch->center_freq)) + continue; + if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) + ch->flags &= ~NL80211_RRF_PASSIVE_SCAN; } } @@ -283,10 +291,10 @@ void ath9k_reg_apply_world_flags(struct wiphy *wiphy, enum reg_set_by setby) case 0x63: case 0x66: case 0x67: - ath9k_reg_apply_5ghz_adhoc_flags(wiphy, setby); + ath9k_reg_apply_5ghz_beaconing_flags(wiphy, setby); break; case 0x68: - ath9k_reg_apply_5ghz_adhoc_flags(wiphy, setby); + ath9k_reg_apply_5ghz_beaconing_flags(wiphy, setby); ath9k_reg_apply_active_scan_flags(wiphy, setby); break; } -- GitLab From e374055afbf92c8d128d8538aafc7e765838206e Mon Sep 17 00:00:00 2001 From: Sujith Date: Thu, 29 Jan 2009 09:34:22 +0530 Subject: [PATCH 1467/4982] mac80211: Reset assoc_scan_tries after an unsuccessful scan run Trying to associate with a non-existent SSID stops the state machine after the first run. Subsequent association requests fail to start the scan engine. Fix this by resetting assoc_scan_tries to zero after completing a scan run. Signed-off-by: Sujith Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 9d51e278c1e..a8755df0cf7 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2415,8 +2415,10 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, ifsta->ssid_len); ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); - } else + } else { + ifsta->assoc_scan_tries = 0; ifsta->state = IEEE80211_STA_MLME_DISABLED; + } } return -1; } -- GitLab From feed029cd63ee14df85afbe1583960c0e983a0ed Mon Sep 17 00:00:00 2001 From: Sujith Date: Thu, 29 Jan 2009 11:37:35 +0530 Subject: [PATCH 1468/4982] ath9k: Fix typo in checking for chip revision Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 77282345efc..00ed44a0c31 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -267,7 +267,7 @@ static int ath9k_hw_get_radiorev(struct ath_hal *ah) static void ath9k_hw_disablepcie(struct ath_hal *ah) { - if (!AR_SREV_9100(ah)) + if (AR_SREV_9100(ah)) return; REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); -- GitLab From 547c3763765654f9a796e628692d9e7d5c1039af Mon Sep 17 00:00:00 2001 From: Sujith Date: Thu, 29 Jan 2009 11:50:20 +0530 Subject: [PATCH 1469/4982] ath9k: Remove a bunch of unused macros RX filter masks are already defined in enum ath9k_rx_filter in ath9k.h Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/reg.h | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/net/wireless/ath9k/reg.h b/drivers/net/wireless/ath9k/reg.h index 150eda56055..c967b7926e3 100644 --- a/drivers/net/wireless/ath9k/reg.h +++ b/drivers/net/wireless/ath9k/reg.h @@ -1198,18 +1198,7 @@ enum { #define AR_CFP_VAL 0x0000FFFF #define AR_RX_FILTER 0x803C -#define AR_RX_FILTER_ALL 0x00000000 -#define AR_RX_UCAST 0x00000001 -#define AR_RX_MCAST 0x00000002 -#define AR_RX_BCAST 0x00000004 -#define AR_RX_CONTROL 0x00000008 -#define AR_RX_BEACON 0x00000010 -#define AR_RX_PROM 0x00000020 -#define AR_RX_PROBE_REQ 0x00000080 -#define AR_RX_MY_BEACON 0x00000200 #define AR_RX_COMPR_BAR 0x00000400 -#define AR_RX_COMPR_BA 0x00000800 -#define AR_RX_UNCOM_BA_BAR 0x00001000 #define AR_MCAST_FIL0 0x8040 #define AR_MCAST_FIL1 0x8044 -- GitLab From c0415b547d37e8065ad4adf289d11db2f3b16dfd Mon Sep 17 00:00:00 2001 From: Alina Friedrichsen Date: Thu, 29 Jan 2009 09:59:43 +0100 Subject: [PATCH 1470/4982] mac80211: Creating new IBSS with fixed BSSID This fixes a bug when creating a new IBSS network with a fixed BSSID. The fixed BSSID situation is now with one of my last patches handled in ieee80211_sta_find_ibss() function. It's more robust to test against (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET), because ifsta->state is not seted right in every situation and so the creating of the new IBSS network sometimes hangs after the first try to scan for a network to merge. Signed-off-by: Alina Friedrichsen Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a8755df0cf7..0ece151659c 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2722,9 +2722,8 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) if (sdata && sdata->vif.type == NL80211_IFTYPE_ADHOC) { ifsta = &sdata->u.sta; - if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) || - (!(ifsta->state == IEEE80211_STA_MLME_IBSS_JOINED) && - !ieee80211_sta_active_ibss(sdata))) + if ((!(ifsta->flags & IEEE80211_STA_PREV_BSSID_SET)) || + !ieee80211_sta_active_ibss(sdata)) ieee80211_sta_find_ibss(sdata, ifsta); } -- GitLab From f2bffa7ea012befc2230331f97bf9b002c0b62bb Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 29 Jan 2009 17:52:19 +0530 Subject: [PATCH 1471/4982] ath9k: Fix LED blink pattern Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/core.h | 10 ++++++ drivers/net/wireless/ath9k/main.c | 52 +++++++++++++++++++++++++++---- 2 files changed, 56 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index 29251f8dabb..9a7bb1b5cd5 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -600,6 +600,8 @@ struct ath_ani { /********************/ #define ATH_LED_PIN 1 +#define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */ +#define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */ enum ath_led_type { ATH_LED_RADIO, @@ -677,6 +679,7 @@ enum PROT_MODE { #define SC_OP_RFKILL_SW_BLOCKED BIT(12) #define SC_OP_RFKILL_HW_BLOCKED BIT(13) #define SC_OP_WAIT_FOR_BEACON BIT(14) +#define SC_OP_LED_ON BIT(15) struct ath_bus_ops { void (*read_cachesize)(struct ath_softc *sc, int *csz); @@ -725,10 +728,17 @@ struct ath_softc { struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX]; struct ath_rate_table *cur_rate_table; struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; + struct ath_led radio_led; struct ath_led assoc_led; struct ath_led tx_led; struct ath_led rx_led; + struct delayed_work ath_led_blink_work; + int led_on_duration; + int led_off_duration; + int led_on_cnt; + int led_off_cnt; + struct ath_rfkill rf_kill; struct ath_ani sc_ani; struct ath9k_node_stats sc_halstats; diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 91f7a7b69a3..e98f2d79af6 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -935,6 +935,32 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, /* LED functions */ /********************************/ +static void ath_led_blink_work(struct work_struct *work) +{ + struct ath_softc *sc = container_of(work, struct ath_softc, + ath_led_blink_work.work); + + if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED)) + return; + ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, + (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0); + + queue_delayed_work(sc->hw->workqueue, &sc->ath_led_blink_work, + (sc->sc_flags & SC_OP_LED_ON) ? + msecs_to_jiffies(sc->led_off_duration) : + msecs_to_jiffies(sc->led_on_duration)); + + sc->led_on_duration = + max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25); + sc->led_off_duration = + max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10); + sc->led_on_cnt = sc->led_off_cnt = 0; + if (sc->sc_flags & SC_OP_LED_ON) + sc->sc_flags &= ~SC_OP_LED_ON; + else + sc->sc_flags |= SC_OP_LED_ON; +} + static void ath_led_brightness(struct led_classdev *led_cdev, enum led_brightness brightness) { @@ -944,16 +970,27 @@ static void ath_led_brightness(struct led_classdev *led_cdev, switch (brightness) { case LED_OFF: if (led->led_type == ATH_LED_ASSOC || - led->led_type == ATH_LED_RADIO) + led->led_type == ATH_LED_RADIO) { + ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, + (led->led_type == ATH_LED_RADIO)); sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; - ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, - (led->led_type == ATH_LED_RADIO) ? 1 : - !!(sc->sc_flags & SC_OP_LED_ASSOCIATED)); + if (led->led_type == ATH_LED_RADIO) + sc->sc_flags &= ~SC_OP_LED_ON; + } else { + sc->led_off_cnt++; + } break; case LED_FULL: - if (led->led_type == ATH_LED_ASSOC) + if (led->led_type == ATH_LED_ASSOC) { sc->sc_flags |= SC_OP_LED_ASSOCIATED; - ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0); + queue_delayed_work(sc->hw->workqueue, + &sc->ath_led_blink_work, 0); + } else if (led->led_type == ATH_LED_RADIO) { + ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0); + sc->sc_flags |= SC_OP_LED_ON; + } else { + sc->led_on_cnt++; + } break; default: break; @@ -989,6 +1026,7 @@ static void ath_unregister_led(struct ath_led *led) static void ath_deinit_leds(struct ath_softc *sc) { + cancel_delayed_work_sync(&sc->ath_led_blink_work); ath_unregister_led(&sc->assoc_led); sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; ath_unregister_led(&sc->tx_led); @@ -1008,6 +1046,8 @@ static void ath_init_leds(struct ath_softc *sc) /* LED off, active low */ ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); + INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work); + trigger = ieee80211_get_radio_led_name(sc->hw); snprintf(sc->radio_led.name, sizeof(sc->radio_led.name), "ath9k-%s:radio", wiphy_name(sc->hw->wiphy)); -- GitLab From c4e3a5844812dd5bf03282e021175d55d608f594 Mon Sep 17 00:00:00 2001 From: Alina Friedrichsen Date: Thu, 29 Jan 2009 13:56:20 +0100 Subject: [PATCH 1472/4982] mac80211: IBSS join rework I hold back this patch for around a week to avoid confusion. This is the second step of "mac80211: Fixed BSSID handling revisited". With it, in the situation of a strange merge to the same BSSID (e.g. caused by a TSF overflow) only reset_tsf() is called. And sta_info_flush_delayed() is only called if you change the network manually, not on an automatic BSSID merge. Signed-off-by: Alina Friedrichsen Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 0ece151659c..73808780f53 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1503,13 +1503,22 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_bss *bss) { struct ieee80211_local *local = sdata->local; - int res, rates, i, j; + int res = 0, rates, i, j; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; u8 *pos; struct ieee80211_supported_band *sband; union iwreq_data wrqu; + if (local->ops->reset_tsf) { + /* Reset own TSF to allow time synchronization work. */ + local->ops->reset_tsf(local_to_hw(local)); + } + + if ((ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) && + memcmp(ifsta->bssid, bss->bssid, ETH_ALEN) == 0) + return res; + skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 + sdata->u.sta.ie_proberesp_len); if (!skb) { @@ -1520,13 +1529,11 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - /* Remove possible STA entries from other IBSS networks. */ - sta_info_flush_delayed(sdata); - - if (local->ops->reset_tsf) { - /* Reset own TSF to allow time synchronization work. */ - local->ops->reset_tsf(local_to_hw(local)); + if (!(ifsta->flags & IEEE80211_STA_PREV_BSSID_SET)) { + /* Remove possible STA entries from other IBSS networks. */ + sta_info_flush_delayed(sdata); } + memcpy(ifsta->bssid, bss->bssid, ETH_ALEN); res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); if (res) -- GitLab From 2264596d6d0a5c1e569af809625c11f8f2d89435 Mon Sep 17 00:00:00 2001 From: Jay Sternberg Date: Thu, 29 Jan 2009 11:09:11 -0800 Subject: [PATCH 1473/4982] iwlwifi: add new HW_REV_TYPEs for Intel WiFi Link 100, 6000 and 6050 Series simply add definitions for the HW_REV_TYPEs for the new devices. Signed-off-by: Jay Sternberg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-csr.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 74d3d43fa67..5028c781275 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -211,6 +211,9 @@ #define CSR_HW_REV_TYPE_5350 (0x0000030) #define CSR_HW_REV_TYPE_5100 (0x0000050) #define CSR_HW_REV_TYPE_5150 (0x0000040) +#define CSR_HW_REV_TYPE_100 (0x0000060) +#define CSR_HW_REV_TYPE_6x00 (0x0000070) +#define CSR_HW_REV_TYPE_6x50 (0x0000080) #define CSR_HW_REV_TYPE_NONE (0x00000F0) /* EEPROM REG */ -- GitLab From c0bac76a22c00d0b4622b2847e0b087befb9ff25 Mon Sep 17 00:00:00 2001 From: Jay Sternberg Date: Mon, 2 Feb 2009 16:21:14 -0800 Subject: [PATCH 1474/4982] iwlwifi: simplify parameter setting to allow support for 6000 series by parametrizing the set hw function, in addition to allowing for supporting the 6000 family significantly simplify the addition of new hardware. Signed-off-by: Jay Sternberg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-100.c | 2 + drivers/net/wireless/iwlwifi/iwl-5000.c | 76 +++++++++++++------------ drivers/net/wireless/iwlwifi/iwl-6000.c | 10 ++++ drivers/net/wireless/iwlwifi/iwl-core.h | 2 + 4 files changed, 53 insertions(+), 37 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-100.c b/drivers/net/wireless/iwlwifi/iwl-100.c index dbadaf44f57..4c4d16537e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-100.c +++ b/drivers/net/wireless/iwlwifi/iwl-100.c @@ -66,5 +66,7 @@ struct iwl_cfg iwl100_bgn_cfg = { .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .mod_params = &iwl50_mod_params, + .valid_tx_ant = ANT_A, + .valid_rx_ant = ANT_AB, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index c5e9a66e2f8..539fc0e234f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -43,6 +43,7 @@ #include "iwl-sta.h" #include "iwl-helpers.h" #include "iwl-5000-hw.h" +#include "iwl-6000-hw.h" /* Highest firmware API version supported */ #define IWL5000_UCODE_API_MAX 1 @@ -840,8 +841,18 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.tfd_size = sizeof(struct iwl_tfd); priv->hw_params.max_stations = IWL5000_STATION_COUNT; priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; - priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; - priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE; + + switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { + case CSR_HW_REV_TYPE_6x00: + case CSR_HW_REV_TYPE_6x50: + priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; + priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; + break; + default: + priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; + priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE; + } + priv->hw_params.max_bsm_size = 0; priv->hw_params.fat_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); @@ -849,61 +860,40 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.sens = &iwl5000_sensitivity; - switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { - case CSR_HW_REV_TYPE_5100: - priv->hw_params.tx_chains_num = 1; - priv->hw_params.rx_chains_num = 2; - priv->hw_params.valid_tx_ant = ANT_B; - priv->hw_params.valid_rx_ant = ANT_AB; - break; - case CSR_HW_REV_TYPE_5150: - priv->hw_params.tx_chains_num = 1; - priv->hw_params.rx_chains_num = 2; - priv->hw_params.valid_tx_ant = ANT_A; - priv->hw_params.valid_rx_ant = ANT_AB; - break; - case CSR_HW_REV_TYPE_5300: - case CSR_HW_REV_TYPE_5350: - priv->hw_params.tx_chains_num = 3; - priv->hw_params.rx_chains_num = 3; - priv->hw_params.valid_tx_ant = ANT_ABC; - priv->hw_params.valid_rx_ant = ANT_ABC; - break; - } + priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); + priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); + priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; + priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { - case CSR_HW_REV_TYPE_5100: - case CSR_HW_REV_TYPE_5300: - case CSR_HW_REV_TYPE_5350: - /* 5X00 and 5350 wants in Celsius */ - priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD; - break; case CSR_HW_REV_TYPE_5150: /* 5150 wants in Kelvin */ priv->hw_params.ct_kill_threshold = iwl5150_get_ct_threshold(priv); break; + default: + /* all others want Celsius */ + priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD; + break; } /* Set initial calibration set */ switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { - case CSR_HW_REV_TYPE_5100: - case CSR_HW_REV_TYPE_5300: - case CSR_HW_REV_TYPE_5350: + case CSR_HW_REV_TYPE_5150: priv->hw_params.calib_init_cfg = - BIT(IWL_CALIB_XTAL) | + BIT(IWL_CALIB_DC) | BIT(IWL_CALIB_LO) | BIT(IWL_CALIB_TX_IQ) | - BIT(IWL_CALIB_TX_IQ_PERD) | BIT(IWL_CALIB_BASE_BAND); + break; - case CSR_HW_REV_TYPE_5150: + default: priv->hw_params.calib_init_cfg = - BIT(IWL_CALIB_DC) | + BIT(IWL_CALIB_XTAL) | BIT(IWL_CALIB_LO) | BIT(IWL_CALIB_TX_IQ) | + BIT(IWL_CALIB_TX_IQ_PERD) | BIT(IWL_CALIB_BASE_BAND); - break; } @@ -1556,6 +1546,8 @@ struct iwl_cfg iwl5300_agn_cfg = { .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .mod_params = &iwl50_mod_params, + .valid_tx_ant = ANT_ABC, + .valid_rx_ant = ANT_ABC, }; struct iwl_cfg iwl5100_bg_cfg = { @@ -1569,6 +1561,8 @@ struct iwl_cfg iwl5100_bg_cfg = { .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .mod_params = &iwl50_mod_params, + .valid_tx_ant = ANT_B, + .valid_rx_ant = ANT_AB, }; struct iwl_cfg iwl5100_abg_cfg = { @@ -1582,6 +1576,8 @@ struct iwl_cfg iwl5100_abg_cfg = { .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .mod_params = &iwl50_mod_params, + .valid_tx_ant = ANT_B, + .valid_rx_ant = ANT_AB, }; struct iwl_cfg iwl5100_agn_cfg = { @@ -1595,6 +1591,8 @@ struct iwl_cfg iwl5100_agn_cfg = { .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .mod_params = &iwl50_mod_params, + .valid_tx_ant = ANT_B, + .valid_rx_ant = ANT_AB, }; struct iwl_cfg iwl5350_agn_cfg = { @@ -1608,6 +1606,8 @@ struct iwl_cfg iwl5350_agn_cfg = { .eeprom_ver = EEPROM_5050_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, .mod_params = &iwl50_mod_params, + .valid_tx_ant = ANT_ABC, + .valid_rx_ant = ANT_ABC, }; struct iwl_cfg iwl5150_agn_cfg = { @@ -1621,6 +1621,8 @@ struct iwl_cfg iwl5150_agn_cfg = { .eeprom_ver = EEPROM_5050_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, .mod_params = &iwl50_mod_params, + .valid_tx_ant = ANT_A, + .valid_rx_ant = ANT_AB, }; MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 4515a6053dd..b78d67633c2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -72,6 +72,8 @@ struct iwl_cfg iwl6000_2ag_cfg = { .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .mod_params = &iwl50_mod_params, + .valid_tx_ant = ANT_BC, + .valid_rx_ant = ANT_BC, }; struct iwl_cfg iwl6000_2agn_cfg = { @@ -85,6 +87,8 @@ struct iwl_cfg iwl6000_2agn_cfg = { .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .mod_params = &iwl50_mod_params, + .valid_tx_ant = ANT_BC, + .valid_rx_ant = ANT_BC, }; struct iwl_cfg iwl6050_2agn_cfg = { @@ -98,6 +102,8 @@ struct iwl_cfg iwl6050_2agn_cfg = { .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .mod_params = &iwl50_mod_params, + .valid_tx_ant = ANT_BC, + .valid_rx_ant = ANT_BC, }; struct iwl_cfg iwl6000_3agn_cfg = { @@ -111,6 +117,8 @@ struct iwl_cfg iwl6000_3agn_cfg = { .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .mod_params = &iwl50_mod_params, + .valid_tx_ant = ANT_ABC, + .valid_rx_ant = ANT_ABC, }; struct iwl_cfg iwl6050_3agn_cfg = { @@ -124,6 +132,8 @@ struct iwl_cfg iwl6050_3agn_cfg = { .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, .mod_params = &iwl50_mod_params, + .valid_tx_ant = ANT_ABC, + .valid_rx_ant = ANT_ABC, }; MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 0a719aeb734..02e92be7556 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -211,6 +211,8 @@ struct iwl_cfg { u16 eeprom_calib_ver; const struct iwl_ops *ops; const struct iwl_mod_params *mod_params; + u8 valid_tx_ant; + u8 valid_rx_ant; }; /*************************** -- GitLab From 050681b77d10ac81bf6be5b2c61aa6c5969947e4 Mon Sep 17 00:00:00 2001 From: Jay Sternberg Date: Thu, 29 Jan 2009 11:09:13 -0800 Subject: [PATCH 1475/4982] iwlwifi: parametrize configuration of the PLL for exclusion on 6000 added a config parameter to enable setting PLL_CFG. older hardware has this parameter set true. the 6000 family does not support this setting, so this parameter set false. Signed-off-by: Jay Sternberg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-100.c | 1 + drivers/net/wireless/iwlwifi/iwl-5000.c | 12 ++++++++++-- drivers/net/wireless/iwlwifi/iwl-6000.c | 5 +++++ drivers/net/wireless/iwlwifi/iwl-core.h | 1 + 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-100.c b/drivers/net/wireless/iwlwifi/iwl-100.c index 4c4d16537e3..a5df93154d2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-100.c +++ b/drivers/net/wireless/iwlwifi/iwl-100.c @@ -68,5 +68,6 @@ struct iwl_cfg iwl100_bgn_cfg = { .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_A, .valid_rx_ant = ANT_AB, + .need_pll_cfg = true, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 539fc0e234f..f8158edf6eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -109,7 +109,8 @@ static int iwl5000_apm_init(struct iwl_priv *priv) iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); - iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); + if (priv->cfg->need_pll_cfg) + iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); /* set "initialization complete" bit to move adapter * D0U* --> D0A* state */ @@ -177,7 +178,8 @@ static int iwl5000_apm_reset(struct iwl_priv *priv) /* FIXME: put here L1A -L0S w/a */ - iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); + if (priv->cfg->need_pll_cfg) + iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); /* set "initialization complete" bit to move adapter * D0U* --> D0A* state */ @@ -1548,6 +1550,7 @@ struct iwl_cfg iwl5300_agn_cfg = { .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_ABC, .valid_rx_ant = ANT_ABC, + .need_pll_cfg = true, }; struct iwl_cfg iwl5100_bg_cfg = { @@ -1563,6 +1566,7 @@ struct iwl_cfg iwl5100_bg_cfg = { .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_B, .valid_rx_ant = ANT_AB, + .need_pll_cfg = true, }; struct iwl_cfg iwl5100_abg_cfg = { @@ -1578,6 +1582,7 @@ struct iwl_cfg iwl5100_abg_cfg = { .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_B, .valid_rx_ant = ANT_AB, + .need_pll_cfg = true, }; struct iwl_cfg iwl5100_agn_cfg = { @@ -1593,6 +1598,7 @@ struct iwl_cfg iwl5100_agn_cfg = { .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_B, .valid_rx_ant = ANT_AB, + .need_pll_cfg = true, }; struct iwl_cfg iwl5350_agn_cfg = { @@ -1608,6 +1614,7 @@ struct iwl_cfg iwl5350_agn_cfg = { .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_ABC, .valid_rx_ant = ANT_ABC, + .need_pll_cfg = true, }; struct iwl_cfg iwl5150_agn_cfg = { @@ -1623,6 +1630,7 @@ struct iwl_cfg iwl5150_agn_cfg = { .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_A, .valid_rx_ant = ANT_AB, + .need_pll_cfg = true, }; MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index b78d67633c2..1672a988424 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -74,6 +74,7 @@ struct iwl_cfg iwl6000_2ag_cfg = { .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_BC, .valid_rx_ant = ANT_BC, + .need_pll_cfg = false, }; struct iwl_cfg iwl6000_2agn_cfg = { @@ -89,6 +90,7 @@ struct iwl_cfg iwl6000_2agn_cfg = { .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_BC, .valid_rx_ant = ANT_BC, + .need_pll_cfg = false, }; struct iwl_cfg iwl6050_2agn_cfg = { @@ -104,6 +106,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_BC, .valid_rx_ant = ANT_BC, + .need_pll_cfg = false, }; struct iwl_cfg iwl6000_3agn_cfg = { @@ -119,6 +122,7 @@ struct iwl_cfg iwl6000_3agn_cfg = { .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_ABC, .valid_rx_ant = ANT_ABC, + .need_pll_cfg = false, }; struct iwl_cfg iwl6050_3agn_cfg = { @@ -134,6 +138,7 @@ struct iwl_cfg iwl6050_3agn_cfg = { .mod_params = &iwl50_mod_params, .valid_tx_ant = ANT_ABC, .valid_rx_ant = ANT_ABC, + .need_pll_cfg = false, }; MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 02e92be7556..789fe6ee27a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -213,6 +213,7 @@ struct iwl_cfg { const struct iwl_mod_params *mod_params; u8 valid_tx_ant; u8 valid_rx_ant; + bool need_pll_cfg; }; /*************************** -- GitLab From 76a2407a5b043d0950d5657184118e89860d545c Mon Sep 17 00:00:00 2001 From: Jay Sternberg Date: Thu, 29 Jan 2009 11:09:14 -0800 Subject: [PATCH 1476/4982] iwlwifi: correct API command overlap Correct the API commands where same command id used for two different commands. Update max api versions for affected devices. TX_ANT_CONFIGURATION_CMD was already using id 0x98, so REPLY_TX_POWER_DBM_CMD moved to 0x95 Older API interfaces may used original value so V1 defines provided. Signed-off-by: Jay Sternberg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-100.c | 2 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 9 ++++++++- drivers/net/wireless/iwlwifi/iwl-6000.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-commands.h | 4 +++- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-100.c b/drivers/net/wireless/iwlwifi/iwl-100.c index a5df93154d2..11d206abb71 100644 --- a/drivers/net/wireless/iwlwifi/iwl-100.c +++ b/drivers/net/wireless/iwlwifi/iwl-100.c @@ -46,7 +46,7 @@ #include "iwl-5000-hw.h" /* Highest firmware API version supported */ -#define IWL100_UCODE_API_MAX 1 +#define IWL100_UCODE_API_MAX 2 /* Lowest firmware API version supported */ #define IWL100_UCODE_API_MIN 1 diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index f8158edf6eb..17aaca8dad1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1411,12 +1411,19 @@ static int iwl5000_send_rxon_assoc(struct iwl_priv *priv) static int iwl5000_send_tx_power(struct iwl_priv *priv) { struct iwl5000_tx_power_dbm_cmd tx_power_cmd; + u8 tx_ant_cfg_cmd; /* half dBm need to multiply */ tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); tx_power_cmd.flags = IWL50_TX_POWER_NO_CLOSED; tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO; - return iwl_send_cmd_pdu_async(priv, REPLY_TX_POWER_DBM_CMD, + + if (IWL_UCODE_API(priv->ucode_ver) == 1) + tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1; + else + tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; + + return iwl_send_cmd_pdu_async(priv, tx_ant_cfg_cmd, sizeof(tx_power_cmd), &tx_power_cmd, NULL); } diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 1672a988424..af700707cb7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -46,8 +46,8 @@ #include "iwl-5000-hw.h" /* Highest firmware API version supported */ -#define IWL6000_UCODE_API_MAX 1 -#define IWL6050_UCODE_API_MAX 1 +#define IWL6000_UCODE_API_MAX 2 +#define IWL6050_UCODE_API_MAX 2 /* Lowest firmware API version supported */ #define IWL6000_UCODE_API_MIN 1 diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index e49415c7fb2..77f32ad3de0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -144,9 +144,11 @@ enum { WHO_IS_AWAKE_NOTIFICATION = 0x94, /* not used */ /* Miscellaneous commands */ + REPLY_TX_POWER_DBM_CMD = 0x95, QUIET_NOTIFICATION = 0x96, /* not used */ REPLY_TX_PWR_TABLE_CMD = 0x97, - REPLY_TX_POWER_DBM_CMD = 0x98, + REPLY_TX_POWER_DBM_CMD_V1 = 0x98, /* old version of API */ + TX_ANT_CONFIGURATION_CMD = 0x98, /* not used */ MEASURE_ABORT_NOTIFICATION = 0x99, /* not used */ /* Bluetooth device coexistence config command */ -- GitLab From e8c00dcb028a1b702863c3a454315c7ae5f544e7 Mon Sep 17 00:00:00 2001 From: Jay Sternberg Date: Thu, 29 Jan 2009 11:09:15 -0800 Subject: [PATCH 1477/4982] iwlwifi: define structures and functions externally for customization defined the structures and functions as extern to alter behavior used by 5000 series for other products including 100 and 6000 series Signed-off-by: Jay Sternberg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-5000.c | 14 +++++++------- drivers/net/wireless/iwlwifi/iwl-dev.h | 12 ++++++++++++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 17aaca8dad1..e3cba61d154 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -394,7 +394,7 @@ static void iwl5000_chain_noise_reset(struct iwl_priv *priv) } } -static void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, +void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, __le32 *tx_flags) { if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || @@ -1105,7 +1105,7 @@ static int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, return 0; } -static u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) +u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) { u16 size = (u16)sizeof(struct iwl_addsta_cmd); memcpy(data, cmd, size); @@ -1334,7 +1334,7 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, } /* Currently 5000 is the superset of everything */ -static u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len) +u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len) { return len; } @@ -1435,7 +1435,7 @@ static void iwl5000_temperature(struct iwl_priv *priv) } /* Calc max signal level (dBm) among 3 possible receivers */ -static int iwl5000_calc_rssi(struct iwl_priv *priv, +int iwl5000_calc_rssi(struct iwl_priv *priv, struct iwl_rx_phy_res *rx_resp) { /* data from PHY/DSP regarding signal strength, etc., @@ -1472,11 +1472,11 @@ static int iwl5000_calc_rssi(struct iwl_priv *priv, return max_rssi - agc - IWL49_RSSI_OFFSET; } -static struct iwl_hcmd_ops iwl5000_hcmd = { +struct iwl_hcmd_ops iwl5000_hcmd = { .rxon_assoc = iwl5000_send_rxon_assoc, }; -static struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { +struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { .get_hcmd_size = iwl5000_get_hcmd_size, .build_addsta_hcmd = iwl5000_build_addsta_hcmd, .gain_computation = iwl5000_gain_computation, @@ -1485,7 +1485,7 @@ static struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { .calc_rssi = iwl5000_calc_rssi, }; -static struct iwl_lib_ops iwl5000_lib = { +struct iwl_lib_ops iwl5000_lib = { .set_hw_params = iwl5000_hw_set_hw_params, .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index b9954bc89cf..afde713c806 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -67,6 +67,18 @@ extern struct iwl_cfg iwl100_bgn_cfg; /* shared structures from iwl-5000.c */ extern struct iwl_mod_params iwl50_mod_params; extern struct iwl_ops iwl5000_ops; +extern struct iwl_lib_ops iwl5000_lib; +extern struct iwl_hcmd_ops iwl5000_hcmd; +extern struct iwl_hcmd_utils_ops iwl5000_hcmd_utils; + +/* shared functions from iwl-5000.c */ +extern u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len); +extern u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, + u8 *data); +extern void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, + __le32 *tx_flags); +extern int iwl5000_calc_rssi(struct iwl_priv *priv, + struct iwl_rx_phy_res *rx_resp); /* CT-KILL constants */ #define CT_KILL_THRESHOLD 110 /* in Celsius */ -- GitLab From 29f35c149e887960ccb5a7d31fb5d9f813193418 Mon Sep 17 00:00:00 2001 From: Jay Sternberg Date: Thu, 29 Jan 2009 11:09:16 -0800 Subject: [PATCH 1478/4982] iwlwifi: remove chain noise calibration functions from 6000 family redefine structures that contain function pointer for chain noise reset and chain noise gain for the 6000 family since these are not needed. Signed-off-by: Jay Sternberg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-6000.c | 23 ++++++++++++++++++----- drivers/net/wireless/iwlwifi/iwl-calib.c | 5 +++-- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index af700707cb7..edfa5e149f7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -61,13 +61,26 @@ #define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode" #define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api) +static struct iwl_hcmd_utils_ops iwl6000_hcmd_utils = { + .get_hcmd_size = iwl5000_get_hcmd_size, + .build_addsta_hcmd = iwl5000_build_addsta_hcmd, + .rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag, + .calc_rssi = iwl5000_calc_rssi, +}; + +static struct iwl_ops iwl6000_ops = { + .lib = &iwl5000_lib, + .hcmd = &iwl5000_hcmd, + .utils = &iwl6000_hcmd_utils, +}; + struct iwl_cfg iwl6000_2ag_cfg = { .name = "6000 Series 2x2 AG", .fw_name_pre = IWL6000_FW_PRE, .ucode_api_max = IWL6000_UCODE_API_MAX, .ucode_api_min = IWL6000_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G, - .ops = &iwl5000_ops, + .ops = &iwl6000_ops, .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, @@ -83,7 +96,7 @@ struct iwl_cfg iwl6000_2agn_cfg = { .ucode_api_max = IWL6000_UCODE_API_MAX, .ucode_api_min = IWL6000_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .ops = &iwl5000_ops, + .ops = &iwl6000_ops, .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, @@ -99,7 +112,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { .ucode_api_max = IWL6050_UCODE_API_MAX, .ucode_api_min = IWL6050_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .ops = &iwl5000_ops, + .ops = &iwl6000_ops, .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, @@ -115,7 +128,7 @@ struct iwl_cfg iwl6000_3agn_cfg = { .ucode_api_max = IWL6000_UCODE_API_MAX, .ucode_api_min = IWL6000_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .ops = &iwl5000_ops, + .ops = &iwl6000_ops, .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, @@ -131,7 +144,7 @@ struct iwl_cfg iwl6050_3agn_cfg = { .ucode_api_max = IWL6050_UCODE_API_MAX, .ucode_api_min = IWL6050_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .ops = &iwl5000_ops, + .ops = &iwl6000_ops, .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, .eeprom_ver = EEPROM_5000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index d06c57764e1..d95797ac02c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c @@ -846,8 +846,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, IWL_DEBUG_CALIB(priv, "min_average_noise = %d, antenna %d\n", min_average_noise, min_average_noise_antenna_i); - priv->cfg->ops->utils->gain_computation(priv, average_noise, - min_average_noise_antenna_i, min_average_noise); + if (priv->cfg->ops->utils->gain_computation) + priv->cfg->ops->utils->gain_computation(priv, average_noise, + min_average_noise_antenna_i, min_average_noise); /* Some power changes may have been made during the calibration. * Update and commit the RXON -- GitLab From 9a23e5a2268fc03a55c7e7112ce904629276d0b2 Mon Sep 17 00:00:00 2001 From: Jay Sternberg Date: Thu, 29 Jan 2009 11:09:17 -0800 Subject: [PATCH 1479/4982] ipw2x00: correct Kconfig to prevent following entries from not indenting not defining dependencies for LIBIPW caused the following entries to not be indented. changing this entry to depend on PCI && WLAN_80211 corrects this issue Signed-off-by: Jay Sternberg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ipw2x00/Kconfig b/drivers/net/wireless/ipw2x00/Kconfig index 3d5cc4463d4..1d5dc3e9c5f 100644 --- a/drivers/net/wireless/ipw2x00/Kconfig +++ b/drivers/net/wireless/ipw2x00/Kconfig @@ -150,6 +150,7 @@ config IPW2200_DEBUG config LIBIPW tristate + depends on PCI && WLAN_80211 select WIRELESS_EXT select CRYPTO select CRYPTO_ARC4 -- GitLab From e5d24efe529b26d782b41a61a5e958c72f36f295 Mon Sep 17 00:00:00 2001 From: Danny Kukawka Date: Thu, 29 Jan 2009 21:58:26 +0100 Subject: [PATCH 1480/4982] iwlwifi: fix led naming Fixed led device naming for the iwl driver. Due to the documentation of the led subsystem/class the naming should be "devicename:colour:function" while not applying sections should be left blank. This should lead to e.g. "iwl-phy0::RX" instead of "iwl-phy0:RX". Signed-off-by: Danny Kukawka Acked-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-led.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 63d669ec20c..19680f72087 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -352,7 +352,7 @@ int iwl_leds_register(struct iwl_priv *priv) trigger = ieee80211_get_radio_led_name(priv->hw); snprintf(priv->led[IWL_LED_TRG_RADIO].name, - sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s:radio", + sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s::radio", wiphy_name(priv->hw->wiphy)); priv->led[IWL_LED_TRG_RADIO].led_on = iwl4965_led_on_reg; @@ -366,7 +366,7 @@ int iwl_leds_register(struct iwl_priv *priv) trigger = ieee80211_get_assoc_led_name(priv->hw); snprintf(priv->led[IWL_LED_TRG_ASSOC].name, - sizeof(priv->led[IWL_LED_TRG_ASSOC].name), "iwl-%s:assoc", + sizeof(priv->led[IWL_LED_TRG_ASSOC].name), "iwl-%s::assoc", wiphy_name(priv->hw->wiphy)); ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_ASSOC], @@ -382,7 +382,7 @@ int iwl_leds_register(struct iwl_priv *priv) trigger = ieee80211_get_rx_led_name(priv->hw); snprintf(priv->led[IWL_LED_TRG_RX].name, - sizeof(priv->led[IWL_LED_TRG_RX].name), "iwl-%s:RX", + sizeof(priv->led[IWL_LED_TRG_RX].name), "iwl-%s::RX", wiphy_name(priv->hw->wiphy)); ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RX], @@ -397,7 +397,7 @@ int iwl_leds_register(struct iwl_priv *priv) trigger = ieee80211_get_tx_led_name(priv->hw); snprintf(priv->led[IWL_LED_TRG_TX].name, - sizeof(priv->led[IWL_LED_TRG_TX].name), "iwl-%s:TX", + sizeof(priv->led[IWL_LED_TRG_TX].name), "iwl-%s::TX", wiphy_name(priv->hw->wiphy)); ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_TX], -- GitLab From c1b4aa3fb619782213af2af6652663c8f9cef373 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Thu, 29 Jan 2009 13:26:44 -0800 Subject: [PATCH 1481/4982] wireless: replace uses of __constant_{endian} The base versions handle constant folding now. Signed-off-by: Harvey Harrison Signed-off-by: John W. Linville --- drivers/net/wireless/hostap/hostap_80211_rx.c | 4 ++-- drivers/net/wireless/hostap/hostap_ap.c | 8 ++++---- drivers/net/wireless/hostap/hostap_ioctl.c | 6 +++--- drivers/net/wireless/ipw2x00/ipw2200.c | 2 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-calib.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-commands.h | 2 +- drivers/net/wireless/iwlwifi/iwl-core.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-led.h | 2 +- drivers/net/wireless/iwlwifi/iwl-power.h | 14 +++++++------- drivers/net/wireless/iwlwifi/iwl-tx.c | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 ++-- drivers/net/wireless/orinoco/hermes_dld.c | 4 ++-- drivers/net/wireless/orinoco/orinoco.c | 2 +- net/mac80211/rx.c | 8 ++++---- 15 files changed, 36 insertions(+), 36 deletions(-) diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c index 19b1bf0478b..241756318da 100644 --- a/drivers/net/wireless/hostap/hostap_80211_rx.c +++ b/drivers/net/wireless/hostap/hostap_80211_rx.c @@ -193,7 +193,7 @@ hdr->f.status = s; hdr->f.len = l; hdr->f.data = d if (prism_header) skb_pull(skb, phdrlen); skb->pkt_type = PACKET_OTHERHOST; - skb->protocol = __constant_htons(ETH_P_802_2); + skb->protocol = cpu_to_be16(ETH_P_802_2); memset(skb->cb, 0, sizeof(skb->cb)); netif_rx(skb); @@ -1094,7 +1094,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb, if (skb2 != NULL) { /* send to wireless media */ skb2->dev = dev; - skb2->protocol = __constant_htons(ETH_P_802_3); + skb2->protocol = cpu_to_be16(ETH_P_802_3); skb_reset_mac_header(skb2); skb_reset_network_header(skb2); /* skb2->network_header += ETH_HLEN; */ diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index 0903db786d5..0a4bf94dddf 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c @@ -609,7 +609,7 @@ static void hostap_ap_tx_cb(struct sk_buff *skb, int ok, void *data) skb->dev = ap->local->apdev; skb_pull(skb, hostap_80211_get_hdrlen(fc)); skb->pkt_type = PACKET_OTHERHOST; - skb->protocol = __constant_htons(ETH_P_802_2); + skb->protocol = cpu_to_be16(ETH_P_802_2); memset(skb->cb, 0, sizeof(skb->cb)); netif_rx(skb); } @@ -2281,7 +2281,7 @@ void hostap_rx(struct net_device *dev, struct sk_buff *skb, WLAN_FC_GET_STYPE(fc) == IEEE80211_STYPE_BEACON) goto drop; - skb->protocol = __constant_htons(ETH_P_HOSTAP); + skb->protocol = cpu_to_be16(ETH_P_HOSTAP); handle_ap_item(local, skb, rx_stats); return; @@ -2310,7 +2310,7 @@ static void schedule_packet_send(local_info_t *local, struct sta_info *sta) hdr = (struct ieee80211_hdr_4addr *) skb_put(skb, 16); /* Generate a fake pspoll frame to start packet delivery */ - hdr->frame_ctl = __constant_cpu_to_le16( + hdr->frame_ctl = cpu_to_le16( IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); memcpy(hdr->addr1, local->dev->dev_addr, ETH_ALEN); memcpy(hdr->addr2, sta->addr, ETH_ALEN); @@ -2754,7 +2754,7 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx) if (meta->flags & HOSTAP_TX_FLAGS_ADD_MOREDATA) { /* indicate to STA that more frames follow */ hdr->frame_ctl |= - __constant_cpu_to_le16(IEEE80211_FCTL_MOREDATA); + cpu_to_le16(IEEE80211_FCTL_MOREDATA); } if (meta->flags & HOSTAP_TX_FLAGS_BUFFERED_FRAME) { diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c index c40fdf4c79d..8618b3355eb 100644 --- a/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/hostap/hostap_ioctl.c @@ -1638,7 +1638,7 @@ static int prism2_request_hostscan(struct net_device *dev, memset(&scan_req, 0, sizeof(scan_req)); scan_req.channel_list = cpu_to_le16(local->channel_mask & local->scan_channel_mask); - scan_req.txrate = __constant_cpu_to_le16(HFA384X_RATES_1MBPS); + scan_req.txrate = cpu_to_le16(HFA384X_RATES_1MBPS); if (ssid) { if (ssid_len > 32) return -EINVAL; @@ -1668,7 +1668,7 @@ static int prism2_request_scan(struct net_device *dev) memset(&scan_req, 0, sizeof(scan_req)); scan_req.channel_list = cpu_to_le16(local->channel_mask & local->scan_channel_mask); - scan_req.txrate = __constant_cpu_to_le16(HFA384X_RATES_1MBPS); + scan_req.txrate = cpu_to_le16(HFA384X_RATES_1MBPS); /* FIX: * It seems to be enough to set roaming mode for a short moment to @@ -2514,7 +2514,7 @@ static int prism2_ioctl_priv_prism2_param(struct net_device *dev, u16 rate; memset(&scan_req, 0, sizeof(scan_req)); - scan_req.channel_list = __constant_cpu_to_le16(0x3fff); + scan_req.channel_list = cpu_to_le16(0x3fff); switch (value) { case 1: rate = HFA384X_RATES_1MBPS; break; case 2: rate = HFA384X_RATES_2MBPS; break; diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 625f2cf99fa..0420d3d35dd 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -8272,7 +8272,7 @@ static void ipw_handle_mgmt_packet(struct ipw_priv *priv, skb_reset_mac_header(skb); skb->pkt_type = PACKET_OTHERHOST; - skb->protocol = __constant_htons(ETH_P_80211_STATS); + skb->protocol = cpu_to_be16(ETH_P_80211_STATS); memset(skb->cb, 0, sizeof(rxb->skb->cb)); netif_rx(skb); rxb->skb = NULL; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 7e9c8cfaa61..0638f3e3760 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1995,8 +1995,8 @@ static u16 iwl4965_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid; addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid; addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn; - addsta->reserved1 = __constant_cpu_to_le16(0); - addsta->reserved2 = __constant_cpu_to_le32(0); + addsta->reserved1 = cpu_to_le16(0); + addsta->reserved2 = cpu_to_le32(0); return (u16)sizeof(struct iwl4965_addsta_cmd); } diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index d95797ac02c..735f3f19928 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c @@ -452,11 +452,11 @@ static int iwl_sensitivity_write(struct iwl_priv *priv) cpu_to_le16((u16)data->nrg_th_ofdm); cmd.table[HD_BARKER_CORR_TH_ADD_MIN_INDEX] = - __constant_cpu_to_le16(190); + cpu_to_le16(190); cmd.table[HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX] = - __constant_cpu_to_le16(390); + cpu_to_le16(390); cmd.table[HD_OFDM_ENERGY_TH_IN_INDEX] = - __constant_cpu_to_le16(62); + cpu_to_le16(62); IWL_DEBUG_CALIB(priv, "ofdm: ac %u mrc %u x1 %u mrc_x1 %u thresh %u\n", data->auto_corr_ofdm, data->auto_corr_ofdm_mrc, diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 77f32ad3de0..29d40746da6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2848,7 +2848,7 @@ struct statistics_rx_ht_phy { __le32 reserved2; } __attribute__ ((packed)); -#define INTERFERENCE_DATA_AVAILABLE __constant_cpu_to_le32(1) +#define INTERFERENCE_DATA_AVAILABLE cpu_to_le32(1) struct statistics_rx_non_phy { __le32 bogus_cts; /* CTS received when not expecting CTS */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 789fe6ee27a..d79912ba6a2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -365,8 +365,8 @@ int iwl_send_scan_abort(struct iwl_priv *priv); * time if it's a quiet channel (nothing responded to our probe, and there's * no other traffic). * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */ -#define IWL_ACTIVE_QUIET_TIME __constant_cpu_to_le16(10) /* msec */ -#define IWL_PLCP_QUIET_THRESH __constant_cpu_to_le16(1) /* packets */ +#define IWL_ACTIVE_QUIET_TIME cpu_to_le16(10) /* msec */ +#define IWL_PLCP_QUIET_THRESH cpu_to_le16(1) /* packets */ /******************************************************************************* diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h index 1d798d08669..140fd8fa485 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-led.h @@ -35,7 +35,7 @@ struct iwl_priv; #define IWL_LED_SOLID 11 #define IWL_LED_NAME_LEN 31 -#define IWL_DEF_LED_INTRVL __constant_cpu_to_le32(1000) +#define IWL_DEF_LED_INTRVL cpu_to_le32(1000) #define IWL_LED_ACTIVITY (0<<1) #define IWL_LED_LINK (1<<1) diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h index 879eafdd736..18963392121 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/iwl-power.h @@ -54,14 +54,14 @@ enum { /* Power management (not Tx power) structures */ -#define NOSLP __constant_cpu_to_le16(0), 0, 0 +#define NOSLP cpu_to_le16(0), 0, 0 #define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0 -#define SLP_TOUT(T) __constant_cpu_to_le32((T) * MSEC_TO_USEC) -#define SLP_VEC(X0, X1, X2, X3, X4) {__constant_cpu_to_le32(X0), \ - __constant_cpu_to_le32(X1), \ - __constant_cpu_to_le32(X2), \ - __constant_cpu_to_le32(X3), \ - __constant_cpu_to_le32(X4)} +#define SLP_TOUT(T) cpu_to_le32((T) * MSEC_TO_USEC) +#define SLP_VEC(X0, X1, X2, X3, X4) {cpu_to_le32(X0), \ + cpu_to_le32(X1), \ + cpu_to_le32(X2), \ + cpu_to_le32(X3), \ + cpu_to_le32(X4)} struct iwl_power_vec_entry { struct iwl_powertable_cmd cmd; u8 no_dtim; diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 7c74b259873..ae04c2086f7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -757,7 +757,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) seq_number = priv->stations[sta_id].tid[tid].seq_number; seq_number &= IEEE80211_SCTL_SEQ; hdr->seq_ctrl = hdr->seq_ctrl & - __constant_cpu_to_le16(IEEE80211_SCTL_FRAG); + cpu_to_le16(IEEE80211_SCTL_FRAG); hdr->seq_ctrl |= cpu_to_le16(seq_number); seq_number += 0x10; /* aggregation is on for this */ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 800e46c9a68..42cc2884971 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -658,7 +658,7 @@ static void iwl3945_activate_qos(struct iwl_priv *priv, u8 force) #define MAX_UCODE_BEACON_INTERVAL 1024 -#define INTEL_CONN_LISTEN_INTERVAL __constant_cpu_to_le16(0xA) +#define INTEL_CONN_LISTEN_INTERVAL cpu_to_le16(0xA) static __le16 iwl3945_adjust_beacon_interval(u16 beacon_val) { @@ -1048,7 +1048,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) IEEE80211_SCTL_SEQ; hdr->seq_ctrl = cpu_to_le16(seq_number) | (hdr->seq_ctrl & - __constant_cpu_to_le16(IEEE80211_SCTL_FRAG)); + cpu_to_le16(IEEE80211_SCTL_FRAG)); seq_number += 0x10; } diff --git a/drivers/net/wireless/orinoco/hermes_dld.c b/drivers/net/wireless/orinoco/hermes_dld.c index d8c626e61a3..45aed14bf11 100644 --- a/drivers/net/wireless/orinoco/hermes_dld.c +++ b/drivers/net/wireless/orinoco/hermes_dld.c @@ -573,9 +573,9 @@ static const struct { \ __le16 id; \ u8 val[length]; \ } __attribute__ ((packed)) default_pdr_data_##pid = { \ - __constant_cpu_to_le16((sizeof(default_pdr_data_##pid)/ \ + cpu_to_le16((sizeof(default_pdr_data_##pid)/ \ sizeof(__le16)) - 1), \ - __constant_cpu_to_le16(pid), \ + cpu_to_le16(pid), \ data \ } diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c index 6514e4611b9..e082ef08511 100644 --- a/drivers/net/wireless/orinoco/orinoco.c +++ b/drivers/net/wireless/orinoco/orinoco.c @@ -1333,7 +1333,7 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid, skb->dev = dev; skb->ip_summed = CHECKSUM_NONE; skb->pkt_type = PACKET_OTHERHOST; - skb->protocol = __constant_htons(ETH_P_802_2); + skb->protocol = cpu_to_be16(ETH_P_802_2); stats->rx_packets++; stats->rx_bytes += skb->len; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 19ffc8ef1d1..1a59382976e 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1225,12 +1225,12 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) switch (hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { - case __constant_cpu_to_le16(IEEE80211_FCTL_TODS): + case cpu_to_le16(IEEE80211_FCTL_TODS): if (unlikely(sdata->vif.type != NL80211_IFTYPE_AP && sdata->vif.type != NL80211_IFTYPE_AP_VLAN)) return -1; break; - case __constant_cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): + case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS && sdata->vif.type != NL80211_IFTYPE_MESH_POINT)) return -1; @@ -1244,13 +1244,13 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) } } break; - case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS): + case cpu_to_le16(IEEE80211_FCTL_FROMDS): if (sdata->vif.type != NL80211_IFTYPE_STATION || (is_multicast_ether_addr(dst) && !compare_ether_addr(src, dev->dev_addr))) return -1; break; - case __constant_cpu_to_le16(0): + case cpu_to_le16(0): if (sdata->vif.type != NL80211_IFTYPE_ADHOC) return -1; break; -- GitLab From a6c8d375f539d450bf8d45e8ccbb7c9e26dffbef Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 30 Jan 2009 01:36:48 +0100 Subject: [PATCH 1482/4982] ath5k: properly free rx dma descriptors When freeing rx dma descriptors, use the right buffer size. Fixes kernel oopses on module unload on ixp4xx and most likely other platforms as well. Signed-off-by: Felix Fietkau Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index bd2c580d1f1..f9d486ff04f 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -310,6 +310,19 @@ static inline void ath5k_txbuf_free(struct ath5k_softc *sc, bf->skb = NULL; } +static inline void ath5k_rxbuf_free(struct ath5k_softc *sc, + struct ath5k_buf *bf) +{ + BUG_ON(!bf); + if (!bf->skb) + return; + pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, + PCI_DMA_FROMDEVICE); + dev_kfree_skb_any(bf->skb); + bf->skb = NULL; +} + + /* Queues setup */ static struct ath5k_txq *ath5k_txq_setup(struct ath5k_softc *sc, int qtype, int subtype); @@ -1343,7 +1356,7 @@ ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev) list_for_each_entry(bf, &sc->txbuf, list) ath5k_txbuf_free(sc, bf); list_for_each_entry(bf, &sc->rxbuf, list) - ath5k_txbuf_free(sc, bf); + ath5k_rxbuf_free(sc, bf); /* Free memory associated with all descriptors */ pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); -- GitLab From 3900898c7a3d563d14a1288f483f8a589bd38299 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 30 Jan 2009 14:29:15 +0530 Subject: [PATCH 1483/4982] ath9k: Cleanup get_rate() interface The interface to calculate the TX rate for a data frame was convoluted with lots of redundant arguments being passed around. Remove all of that and make it simple. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/rc.c | 67 ++++++++++++++------------------- 1 file changed, 28 insertions(+), 39 deletions(-) diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 61c86c4f9fc..8bc7bb50c7f 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -631,8 +631,7 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv, static u8 ath_rc_ratefind_ht(struct ath_softc *sc, struct ath_rate_priv *ath_rc_priv, struct ath_rate_table *rate_table, - int probe_allowed, int *is_probing, - int is_retry) + int *is_probing) { u32 dt, best_thruput, this_thruput, now_msec; u8 rate, next_rate, best_rate, maxindex, minindex; @@ -714,13 +713,6 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc, } rate = best_rate; - - /* if we are retrying for more than half the number - * of max retries, use the min rate for the next retry - */ - if (is_retry) - rate = ath_rc_priv->valid_rate_index[minindex]; - ath_rc_priv->rssi_last_lookup = rssi_last; /* @@ -728,13 +720,12 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc, * non-monoticity of 11g's rate table */ - if (rate >= ath_rc_priv->rate_max_phy && probe_allowed) { + if (rate >= ath_rc_priv->rate_max_phy) { rate = ath_rc_priv->rate_max_phy; /* Probe the next allowed phy state */ - /* FIXME:XXXX Check to make sure ratMax is checked properly */ if (ath_rc_get_nextvalid_txrate(rate_table, - ath_rc_priv, rate, &next_rate) && + ath_rc_priv, rate, &next_rate) && (now_msec - ath_rc_priv->probe_time > rate_table->probe_interval) && (ath_rc_priv->hw_maxretry_pktcnt >= 1)) { @@ -804,54 +795,54 @@ static u8 ath_rc_rate_getidx(struct ath_softc *sc, static void ath_rc_ratefind(struct ath_softc *sc, struct ath_rate_priv *ath_rc_priv, - int num_tries, int num_rates, - struct ieee80211_tx_info *tx_info, int *is_probe, - int is_retry) + struct ieee80211_tx_rate_control *txrc) { - u8 try_per_rate = 0, i = 0, rix, nrix; struct ath_rate_table *rate_table; + struct sk_buff *skb = txrc->skb; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_rate *rates = tx_info->control.rates; + u8 try_per_rate = 0, i = 0, rix, nrix; + int is_probe = 0; rate_table = sc->cur_rate_table; - rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table, 1, - is_probe, is_retry); + rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table, &is_probe); nrix = rix; - if (*is_probe) { + if (is_probe) { /* set one try for probe rates. For the * probes don't enable rts */ - ath_rc_rate_set_series(rate_table, - &rates[i++], 1, nrix, 0); + ath_rc_rate_set_series(rate_table, &rates[i++], + 1, nrix, 0); - try_per_rate = (num_tries/num_rates); + try_per_rate = (ATH_11N_TXMAXTRY/4); /* Get the next tried/allowed rate. No RTS for the next series * after the probe rate */ - nrix = ath_rc_rate_getidx(sc, - ath_rc_priv, rate_table, nrix, 1, 0); - ath_rc_rate_set_series(rate_table, - &rates[i++], try_per_rate, nrix, 0); + nrix = ath_rc_rate_getidx(sc, ath_rc_priv, + rate_table, nrix, 1, 0); + ath_rc_rate_set_series(rate_table, &rates[i++], + try_per_rate, nrix, 0); } else { - try_per_rate = (num_tries/num_rates); + try_per_rate = (ATH_11N_TXMAXTRY/4); /* Set the choosen rate. No RTS for first series entry. */ - ath_rc_rate_set_series(rate_table, - &rates[i++], try_per_rate, nrix, 0); + ath_rc_rate_set_series(rate_table, &rates[i++], + try_per_rate, nrix, 0); } /* Fill in the other rates for multirate retry */ - for ( ; i < num_rates; i++) { + for ( ; i < 4; i++) { u8 try_num; u8 min_rate; - try_num = ((i + 1) == num_rates) ? - num_tries - (try_per_rate * i) : try_per_rate ; - min_rate = (((i + 1) == num_rates) && 0); + try_num = ((i + 1) == 4) ? + ATH_11N_TXMAXTRY - (try_per_rate * i) : try_per_rate ; + min_rate = (((i + 1) == 4) && 0); nrix = ath_rc_rate_getidx(sc, ath_rc_priv, rate_table, nrix, 1, min_rate); /* All other rates in the series have RTS enabled */ - ath_rc_rate_set_series(rate_table, - &rates[i], try_num, nrix, 1); + ath_rc_rate_set_series(rate_table, &rates[i], + try_num, nrix, 1); } /* @@ -1503,10 +1494,9 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, struct ieee80211_supported_band *sband = txrc->sband; struct sk_buff *skb = txrc->skb; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ath_softc *sc = priv; struct ath_rate_priv *ath_rc_priv = priv_sta; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - int is_probe = 0; __le16 fc = hdr->frame_control; /* lowest rate for management and multicast/broadcast frames */ @@ -1519,8 +1509,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, } /* Find tx rate for unicast frames */ - ath_rc_ratefind(sc, ath_rc_priv, ATH_11N_TXMAXTRY, 4, - tx_info, &is_probe, false); + ath_rc_ratefind(sc, ath_rc_priv, txrc); } static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, -- GitLab From c89424df441ea8d794682b9c5620d8e8b0315438 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 30 Jan 2009 14:29:28 +0530 Subject: [PATCH 1484/4982] ath9k: Handle mac80211's RC flags for MCS rates mac80211 notifies the RC algorithm if RTS/CTS and short preamble are needed. The RC flags for MCS rates are currently not handled by mac80211, and ath9k's RC doesn't set the flags either. Fix this. Also, set the rts_cts_rate_idx inside the RC algorithm. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/core.h | 8 -- drivers/net/wireless/ath9k/mac.c | 3 - drivers/net/wireless/ath9k/rc.c | 82 +++++++++++++++--- drivers/net/wireless/ath9k/xmit.c | 135 +++++++++--------------------- 4 files changed, 111 insertions(+), 117 deletions(-) diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index 9a7bb1b5cd5..8683fc8ddb3 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -233,7 +233,6 @@ struct ath_buf_state { #define bf_isht(bf) (bf->bf_state.bf_type & BUF_HT) #define bf_isretried(bf) (bf->bf_state.bf_type & BUF_RETRY) #define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY) -#define bf_isshpreamble(bf) (bf->bf_state.bf_type & BUF_SHORT_PREAMBLE) #define bf_isbar(bf) (bf->bf_state.bf_type & BUF_BAR) #define bf_ispspoll(bf) (bf->bf_state.bf_type & BUF_PSPOLL) #define bf_isaggrburst(bf) (bf->bf_state.bf_type & BUF_AGGR_BURST) @@ -658,12 +657,6 @@ struct ath_rfkill { #define ATH_RSSI_DUMMY_MARKER 0x127 #define ATH_RATE_DUMMY_MARKER 0 -enum PROT_MODE { - PROT_M_NONE = 0, - PROT_M_RTSCTS, - PROT_M_CTSONLY -}; - #define SC_OP_INVALID BIT(0) #define SC_OP_BEACONS BIT(1) #define SC_OP_RXAGGR BIT(2) @@ -715,7 +708,6 @@ struct ath_softc { u8 sc_splitmic; atomic_t ps_usecount; enum ath9k_int sc_imask; - enum PROT_MODE sc_protmode; enum ath9k_ht_extprotspacing sc_ht_extprotspacing; enum ath9k_ht_macmode tx_chan_width; diff --git a/drivers/net/wireless/ath9k/mac.c b/drivers/net/wireless/ath9k/mac.c index ef832a5ebbd..2427c44a8c3 100644 --- a/drivers/net/wireless/ath9k/mac.c +++ b/drivers/net/wireless/ath9k/mac.c @@ -344,9 +344,6 @@ void ath9k_hw_set11n_ratescenario(struct ath_hal *ah, struct ath_desc *ds, struct ar5416_desc *last_ads = AR5416DESC(lastds); u32 ds_ctl0; - (void) nseries; - (void) rtsctsDuration; - if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) { ds_ctl0 = ads->ds_ctl0; diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 8bc7bb50c7f..a8c4f9757eb 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -747,14 +747,17 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc, return rate; } -static void ath_rc_rate_set_series(struct ath_rate_table *rate_table , +static void ath_rc_rate_set_series(struct ath_rate_table *rate_table, struct ieee80211_tx_rate *rate, + struct ieee80211_tx_rate_control *txrc, u8 tries, u8 rix, int rtsctsenable) { rate->count = tries; rate->idx = rix; - if (rtsctsenable) + if (txrc->short_preamble) + rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE; + if (txrc->rts || rtsctsenable) rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS; if (WLAN_RC_PHY_40(rate_table->info[rix].phy)) rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; @@ -764,6 +767,43 @@ static void ath_rc_rate_set_series(struct ath_rate_table *rate_table , rate->flags |= IEEE80211_TX_RC_MCS; } +static void ath_rc_rate_set_rtscts(struct ath_softc *sc, + struct ath_rate_table *rate_table, + struct ieee80211_tx_info *tx_info) +{ + struct ieee80211_tx_rate *rates = tx_info->control.rates; + int i = 0, rix = 0, cix, enable_g_protection = 0; + + /* get the cix for the lowest valid rix */ + for (i = 3; i >= 0; i--) { + if (rates[i].count && (rates[i].idx >= 0)) { + rix = rates[i].idx; + break; + } + } + cix = rate_table->info[rix].ctrl_rate; + + /* All protection frames are transmited at 2Mb/s for 802.11g, + * otherwise we transmit them at 1Mb/s */ + if (sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ && + !conf_is_ht(&sc->hw->conf)) + enable_g_protection = 1; + + /* + * If 802.11g protection is enabled, determine whether to use RTS/CTS or + * just CTS. Note that this is only done for OFDM/HT unicast frames. + */ + if ((sc->sc_flags & SC_OP_PROTECT_ENABLE) && + !(tx_info->flags & IEEE80211_TX_CTL_NO_ACK) && + (rate_table->info[rix].phy == WLAN_RC_PHY_OFDM || + WLAN_RC_PHY_HT(rate_table->info[rix].phy))) { + rates[0].flags |= IEEE80211_TX_RC_USE_CTS_PROTECT; + cix = rate_table->info[enable_g_protection].ctrl_rate; + } + + tx_info->control.rts_cts_rate_idx = cix; +} + static u8 ath_rc_rate_getidx(struct ath_softc *sc, struct ath_rate_priv *ath_rc_priv, struct ath_rate_table *rate_table, @@ -801,6 +841,8 @@ static void ath_rc_ratefind(struct ath_softc *sc, struct sk_buff *skb = txrc->skb; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_rate *rates = tx_info->control.rates; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + __le16 fc = hdr->frame_control; u8 try_per_rate = 0, i = 0, rix, nrix; int is_probe = 0; @@ -811,7 +853,7 @@ static void ath_rc_ratefind(struct ath_softc *sc, if (is_probe) { /* set one try for probe rates. For the * probes don't enable rts */ - ath_rc_rate_set_series(rate_table, &rates[i++], + ath_rc_rate_set_series(rate_table, &rates[i++], txrc, 1, nrix, 0); try_per_rate = (ATH_11N_TXMAXTRY/4); @@ -820,12 +862,12 @@ static void ath_rc_ratefind(struct ath_softc *sc, */ nrix = ath_rc_rate_getidx(sc, ath_rc_priv, rate_table, nrix, 1, 0); - ath_rc_rate_set_series(rate_table, &rates[i++], + ath_rc_rate_set_series(rate_table, &rates[i++], txrc, try_per_rate, nrix, 0); } else { try_per_rate = (ATH_11N_TXMAXTRY/4); /* Set the choosen rate. No RTS for first series entry. */ - ath_rc_rate_set_series(rate_table, &rates[i++], + ath_rc_rate_set_series(rate_table, &rates[i++], txrc, try_per_rate, nrix, 0); } @@ -841,7 +883,7 @@ static void ath_rc_ratefind(struct ath_softc *sc, nrix = ath_rc_rate_getidx(sc, ath_rc_priv, rate_table, nrix, 1, min_rate); /* All other rates in the series have RTS enabled */ - ath_rc_rate_set_series(rate_table, &rates[i], + ath_rc_rate_set_series(rate_table, &rates[i], txrc, try_num, nrix, 1); } @@ -871,6 +913,24 @@ static void ath_rc_ratefind(struct ath_softc *sc, rates[3].flags = rates[2].flags; } } + + /* + * Force hardware to use computed duration for next + * fragment by disabling multi-rate retry, which + * updates duration based on the multi-rate duration table. + * + * FIXME: Fix duration + */ + if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK) && + (ieee80211_has_morefrags(fc) || + (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG))) { + rates[1].count = rates[2].count = rates[3].count = 0; + rates[1].idx = rates[2].idx = rates[3].idx = 0; + rates[0].count = ATH_TXMAXTRY; + } + + /* Setup RTS/CTS */ + ath_rc_rate_set_rtscts(sc, rate_table, tx_info); } static bool ath_rc_update_per(struct ath_softc *sc, @@ -1385,16 +1445,16 @@ static void ath_rc_init(struct ath_softc *sc, if (!rateset->rs_nrates) { /* No working rate, just initialize valid rates */ hi = ath_rc_init_validrates(ath_rc_priv, rate_table, - ath_rc_priv->ht_cap); + ath_rc_priv->ht_cap); } else { /* Use intersection of working rates and valid rates */ hi = ath_rc_setvalid_rates(ath_rc_priv, rate_table, - rateset, ath_rc_priv->ht_cap); + rateset, ath_rc_priv->ht_cap); if (ath_rc_priv->ht_cap & WLAN_RC_HT_FLAG) { hthi = ath_rc_setvalid_htrates(ath_rc_priv, - rate_table, - ht_mcs, - ath_rc_priv->ht_cap); + rate_table, + ht_mcs, + ath_rc_priv->ht_cap); } hi = A_MAX(hi, hthi); } diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index d483f3c1350..e14bceaef12 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -1386,8 +1386,6 @@ static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb, if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) flags |= ATH9K_TXDESC_NOACK; - if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) - flags |= ATH9K_TXDESC_RTSENA; return flags; } @@ -1433,137 +1431,86 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) { - struct ath_hal *ah = sc->sc_ah; - struct ath_rate_table *rt; - struct ath_desc *ds = bf->bf_desc; - struct ath_desc *lastds = bf->bf_lastbf->bf_desc; + struct ath_rate_table *rt = sc->cur_rate_table; struct ath9k_11n_rate_series series[4]; struct sk_buff *skb; struct ieee80211_tx_info *tx_info; struct ieee80211_tx_rate *rates; - struct ieee80211_hdr *hdr; - struct ieee80211_hw *hw = sc->hw; - int i, flags, rtsctsena = 0, enable_g_protection = 0; - u32 ctsduration = 0; - u8 rix = 0, cix, ctsrate = 0; - __le16 fc; + int i, flags = 0; + u8 rix = 0, ctsrate = 0; memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); skb = (struct sk_buff *)bf->bf_mpdu; - hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; tx_info = IEEE80211_SKB_CB(skb); rates = tx_info->control.rates; - if (ieee80211_has_morefrags(fc) || - (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) { - rates[1].count = rates[2].count = rates[3].count = 0; - rates[1].idx = rates[2].idx = rates[3].idx = 0; - rates[0].count = ATH_TXMAXTRY; - } - - /* get the cix for the lowest valid rix */ - rt = sc->cur_rate_table; - for (i = 3; i >= 0; i--) { - if (rates[i].count && (rates[i].idx >= 0)) { - rix = rates[i].idx; - break; - } - } - - flags = (bf->bf_flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)); - cix = rt->info[rix].ctrl_rate; - - /* All protection frames are transmited at 2Mb/s for 802.11g, - * otherwise we transmit them at 1Mb/s */ - if (hw->conf.channel->band == IEEE80211_BAND_2GHZ && - !conf_is_ht(&hw->conf)) - enable_g_protection = 1; - /* - * If 802.11g protection is enabled, determine whether to use RTS/CTS or - * just CTS. Note that this is only done for OFDM/HT unicast frames. + * We check if Short Preamble is needed for the CTS rate by + * checking the BSS's global flag. + * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used. */ - if (sc->sc_protmode != PROT_M_NONE && !(bf->bf_flags & ATH9K_TXDESC_NOACK) - && (rt->info[rix].phy == WLAN_RC_PHY_OFDM || - WLAN_RC_PHY_HT(rt->info[rix].phy))) { - if (sc->sc_protmode == PROT_M_RTSCTS) - flags = ATH9K_TXDESC_RTSENA; - else if (sc->sc_protmode == PROT_M_CTSONLY) - flags = ATH9K_TXDESC_CTSENA; - - cix = rt->info[enable_g_protection].ctrl_rate; - rtsctsena = 1; - } + if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) + ctsrate = rt->info[tx_info->control.rts_cts_rate_idx].ratecode | + rt->info[tx_info->control.rts_cts_rate_idx].short_preamble; + else + ctsrate = rt->info[tx_info->control.rts_cts_rate_idx].ratecode; - /* For 11n, the default behavior is to enable RTS for hw retried frames. - * We enable the global flag here and let rate series flags determine - * which rates will actually use RTS. + /* + * ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. + * Check the first rate in the series to decide whether RTS/CTS + * or CTS-to-self has to be used. */ - if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) && bf_isdata(bf)) { - /* 802.11g protection not needed, use our default behavior */ - if (!rtsctsena) - flags = ATH9K_TXDESC_RTSENA; - } + if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) + flags = ATH9K_TXDESC_CTSENA; + else if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) + flags = ATH9K_TXDESC_RTSENA; - /* Set protection if aggregate protection on */ + /* FIXME: Handle aggregation protection */ if (sc->sc_config.ath_aggr_prot && (!bf_isaggr(bf) || (bf_isaggr(bf) && bf->bf_al < 8192))) { flags = ATH9K_TXDESC_RTSENA; - cix = rt->info[enable_g_protection].ctrl_rate; - rtsctsena = 1; } /* For AR5416 - RTS cannot be followed by a frame larger than 8K */ - if (bf_isaggr(bf) && (bf->bf_al > ah->ah_caps.rts_aggr_limit)) + if (bf_isaggr(bf) && (bf->bf_al > sc->sc_ah->ah_caps.rts_aggr_limit)) flags &= ~(ATH9K_TXDESC_RTSENA); - /* - * CTS transmit rate is derived from the transmit rate by looking in the - * h/w rate table. We must also factor in whether or not a short - * preamble is to be used. NB: cix is set above where RTS/CTS is enabled - */ - ctsrate = rt->info[cix].ratecode | - (bf_isshpreamble(bf) ? rt->info[cix].short_preamble : 0); - for (i = 0; i < 4; i++) { if (!rates[i].count || (rates[i].idx < 0)) continue; rix = rates[i].idx; - - series[i].Rate = rt->info[rix].ratecode | - (bf_isshpreamble(bf) ? rt->info[rix].short_preamble : 0); - series[i].Tries = rates[i].count; + series[i].ChSel = sc->sc_tx_chainmask; - series[i].RateFlags = ( - (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) ? - ATH9K_RATESERIES_RTS_CTS : 0) | - ((rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? - ATH9K_RATESERIES_2040 : 0) | - ((rates[i].flags & IEEE80211_TX_RC_SHORT_GI) ? - ATH9K_RATESERIES_HALFGI : 0); + if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) + series[i].Rate = rt->info[rix].ratecode | + rt->info[rix].short_preamble; + else + series[i].Rate = rt->info[rix].ratecode; + + if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) + series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; + if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) + series[i].RateFlags |= ATH9K_RATESERIES_2040; + if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI) + series[i].RateFlags |= ATH9K_RATESERIES_HALFGI; series[i].PktDuration = ath_pkt_duration(sc, rix, bf, (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) != 0, (rates[i].flags & IEEE80211_TX_RC_SHORT_GI), - bf_isshpreamble(bf)); - - series[i].ChSel = sc->sc_tx_chainmask; - - if (rtsctsena) - series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; + (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)); } /* set dur_update_en for l-sig computation except for PS-Poll frames */ - ath9k_hw_set11n_ratescenario(ah, ds, lastds, !bf_ispspoll(bf), - ctsrate, ctsduration, - series, 4, flags); + ath9k_hw_set11n_ratescenario(sc->sc_ah, bf->bf_desc, + bf->bf_lastbf->bf_desc, + !bf_ispspoll(bf), ctsrate, + 0, series, 4, flags); if (sc->sc_config.ath_aggr_prot && flags) - ath9k_hw_set11n_burstduration(ah, ds, 8192); + ath9k_hw_set11n_burstduration(sc->sc_ah, bf->bf_desc, 8192); } static int ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf, @@ -1593,8 +1540,6 @@ static int ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf, bf->bf_state.bf_type |= BUF_BAR; if (ieee80211_is_pspoll(fc)) bf->bf_state.bf_type |= BUF_PSPOLL; - if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) - bf->bf_state.bf_type |= BUF_SHORT_PREAMBLE; if ((conf_is_ht(&sc->hw->conf) && !is_pae(skb) && (tx_info->flags & IEEE80211_TX_CTL_AMPDU))) bf->bf_state.bf_type |= BUF_HT; -- GitLab From 7a7dec656252a5784218a22abf76ad1cdef115d0 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 30 Jan 2009 14:32:09 +0530 Subject: [PATCH 1485/4982] ath9k: Add debugfs files for printing TX rate details Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/core.h | 17 +++++ drivers/net/wireless/ath9k/debug.c | 100 +++++++++++++++++++++++++++++ drivers/net/wireless/ath9k/rc.c | 2 + 3 files changed, 119 insertions(+) diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index 8683fc8ddb3..791f1acc0bb 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -131,8 +131,18 @@ struct ath_interrupt_stats { u32 dtim; }; +struct ath_legacy_rc_stats { + u32 success; +}; + +struct ath_11n_rc_stats { + u32 success; +}; + struct ath_stats { struct ath_interrupt_stats istats; + struct ath_legacy_rc_stats legacy_rcstats[12]; /* max(11a,11b,11g) */ + struct ath_11n_rc_stats n_rcstats[16]; /* 0..15 MCS rates */ }; struct ath9k_debug { @@ -141,6 +151,7 @@ struct ath9k_debug { struct dentry *debugfs_phy; struct dentry *debugfs_dma; struct dentry *debugfs_interrupt; + struct dentry *debugfs_rcstat; struct ath_stats stats; }; @@ -148,6 +159,7 @@ void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...); int ath9k_init_debug(struct ath_softc *sc); void ath9k_exit_debug(struct ath_softc *sc); void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); +void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb); #else @@ -170,6 +182,11 @@ static inline void ath_debug_stat_interrupt(struct ath_softc *sc, { } +static inline void ath_debug_stat_rc(struct ath_softc *sc, + struct sk_buff *skb) +{ +} + #endif /* CONFIG_ATH9K_DEBUG */ struct ath_config { diff --git a/drivers/net/wireless/ath9k/debug.c b/drivers/net/wireless/ath9k/debug.c index 1680164b4ad..6181e49eecb 100644 --- a/drivers/net/wireless/ath9k/debug.c +++ b/drivers/net/wireless/ath9k/debug.c @@ -222,6 +222,98 @@ static const struct file_operations fops_interrupt = { .owner = THIS_MODULE }; +static void ath_debug_stat_11n_rc(struct ath_softc *sc, struct sk_buff *skb) +{ + struct ath_tx_info_priv *tx_info_priv = NULL; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_tx_rate *rates = tx_info->status.rates; + int final_ts_idx, idx; + + tx_info_priv = ATH_TX_INFO_PRIV(tx_info); + final_ts_idx = tx_info_priv->tx.ts_rateindex; + idx = sc->cur_rate_table->info[rates[final_ts_idx].idx].dot11rate; + + sc->sc_debug.stats.n_rcstats[idx].success++; +} + +static void ath_debug_stat_legacy_rc(struct ath_softc *sc, struct sk_buff *skb) +{ + struct ath_tx_info_priv *tx_info_priv = NULL; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_tx_rate *rates = tx_info->status.rates; + int final_ts_idx, idx; + + tx_info_priv = ATH_TX_INFO_PRIV(tx_info); + final_ts_idx = tx_info_priv->tx.ts_rateindex; + idx = rates[final_ts_idx].idx; + + sc->sc_debug.stats.legacy_rcstats[idx].success++; +} + +void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb) +{ + if (conf_is_ht(&sc->hw->conf)) + ath_debug_stat_11n_rc(sc, skb); + else + ath_debug_stat_legacy_rc(sc, skb); +} + +static ssize_t ath_read_file_stat_11n_rc(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + char buf[512]; + unsigned int len = 0; + int i = 0; + + len += sprintf(buf, "%7s %13s\n\n", "Rate", "Success"); + + for (i = 0; i <= 15; i++) { + len += snprintf(buf + len, sizeof(buf) - len, + "%5s%3d: %8u\n", "MCS", i, + sc->sc_debug.stats.n_rcstats[i].success); + } + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t ath_read_file_stat_legacy_rc(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + char buf[512]; + unsigned int len = 0; + int i = 0; + + len += sprintf(buf, "%7s %13s\n\n", "Rate", "Success"); + + for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) { + len += snprintf(buf + len, sizeof(buf) - len, "%5u: %12u\n", + sc->cur_rate_table->info[i].ratekbps / 1000, + sc->sc_debug.stats.legacy_rcstats[i].success); + } + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + + if (conf_is_ht(&sc->hw->conf)) + return ath_read_file_stat_11n_rc(file, user_buf, count, ppos); + else + return ath_read_file_stat_legacy_rc(file, user_buf, count ,ppos); +} + +static const struct file_operations fops_rcstat = { + .read = read_file_rcstat, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE +}; int ath9k_init_debug(struct ath_softc *sc) { @@ -248,6 +340,13 @@ int ath9k_init_debug(struct ath_softc *sc) if (!sc->sc_debug.debugfs_interrupt) goto err; + sc->sc_debug.debugfs_rcstat = debugfs_create_file("rcstat", + S_IRUGO, + sc->sc_debug.debugfs_phy, + sc, &fops_rcstat); + if (!sc->sc_debug.debugfs_rcstat) + goto err; + return 0; err: ath9k_exit_debug(sc); @@ -256,6 +355,7 @@ err: void ath9k_exit_debug(struct ath_softc *sc) { + debugfs_remove(sc->sc_debug.debugfs_rcstat); debugfs_remove(sc->sc_debug.debugfs_interrupt); debugfs_remove(sc->sc_debug.debugfs_dma); debugfs_remove(sc->sc_debug.debugfs_phy); diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index a8c4f9757eb..704b6277814 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -1544,6 +1544,8 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, ieee80211_start_tx_ba_session(sc->hw, hdr->addr1, tid); } } + + ath_debug_stat_rc(sc, skb); exit: kfree(tx_info_priv); } -- GitLab From 7fee5372d814c4be9546e5c28ac0058258d8df3e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 30 Jan 2009 11:13:06 +0100 Subject: [PATCH 1486/4982] mac80211: remove HW_SIGNAL_DB Giving the signal in dB isn't much more useful to userspace than giving the signal in unspecified units. This removes some radiotap information for zd1211 (the only driver using this flag), but it helps a lot for getting cfg80211-based scanning which won't support dB, and zd1211 being dB is a little fishy anyway. Signed-off-by: Johannes Berg Cc: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_mac.c | 2 +- include/net/mac80211.h | 22 ++++++++-------------- net/mac80211/main.c | 1 - net/mac80211/rx.c | 11 +---------- net/mac80211/wext.c | 3 +-- 5 files changed, 11 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index a611ad85798..651807dfb50 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -967,7 +967,7 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band; hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_SIGNAL_DB; + IEEE80211_HW_SIGNAL_UNSPEC; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_MESH_POINT) | diff --git a/include/net/mac80211.h b/include/net/mac80211.h index e2144f0e872..409e2c69269 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -860,11 +860,6 @@ enum ieee80211_tkip_key_type { * expect values between 0 and @max_signal. * If possible please provide dB or dBm instead. * - * @IEEE80211_HW_SIGNAL_DB: - * Hardware gives signal values in dB, decibel difference from an - * arbitrary, fixed reference. We expect values between 0 and @max_signal. - * If possible please provide dBm instead. - * * @IEEE80211_HW_SIGNAL_DBM: * Hardware gives signal values in dBm, decibel difference from * one milliwatt. This is the preferred method since it is standardized @@ -900,15 +895,14 @@ enum ieee80211_hw_flags { IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE = 1<<3, IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE = 1<<4, IEEE80211_HW_SIGNAL_UNSPEC = 1<<5, - IEEE80211_HW_SIGNAL_DB = 1<<6, - IEEE80211_HW_SIGNAL_DBM = 1<<7, - IEEE80211_HW_NOISE_DBM = 1<<8, - IEEE80211_HW_SPECTRUM_MGMT = 1<<9, - IEEE80211_HW_AMPDU_AGGREGATION = 1<<10, - IEEE80211_HW_SUPPORTS_PS = 1<<11, - IEEE80211_HW_PS_NULLFUNC_STACK = 1<<12, - IEEE80211_HW_SUPPORTS_DYNAMIC_PS = 1<<13, - IEEE80211_HW_MFP_CAPABLE = 1<<14, + IEEE80211_HW_SIGNAL_DBM = 1<<6, + IEEE80211_HW_NOISE_DBM = 1<<7, + IEEE80211_HW_SPECTRUM_MGMT = 1<<8, + IEEE80211_HW_AMPDU_AGGREGATION = 1<<9, + IEEE80211_HW_SUPPORTS_PS = 1<<10, + IEEE80211_HW_PS_NULLFUNC_STACK = 1<<11, + IEEE80211_HW_SUPPORTS_DYNAMIC_PS = 1<<12, + IEEE80211_HW_MFP_CAPABLE = 1<<13, }; /** diff --git a/net/mac80211/main.c b/net/mac80211/main.c index a109c06e8e4..7247b303e96 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -884,7 +884,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) local->hw.conf.listen_interval = local->hw.max_listen_interval; local->wstats_flags |= local->hw.flags & (IEEE80211_HW_SIGNAL_UNSPEC | - IEEE80211_HW_SIGNAL_DB | IEEE80211_HW_SIGNAL_DBM) ? IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID; local->wstats_flags |= local->hw.flags & IEEE80211_HW_NOISE_DBM ? diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 1a59382976e..8e8ddbfcd23 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -86,8 +86,7 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local, if (status->flag & RX_FLAG_TSFT) len += 8; - if (local->hw.flags & IEEE80211_HW_SIGNAL_DB || - local->hw.flags & IEEE80211_HW_SIGNAL_DBM) + if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) len += 1; if (local->hw.flags & IEEE80211_HW_NOISE_DBM) len += 1; @@ -199,14 +198,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, *pos = status->antenna; pos++; - /* IEEE80211_RADIOTAP_DB_ANTSIGNAL */ - if (local->hw.flags & IEEE80211_HW_SIGNAL_DB) { - *pos = status->signal; - rthdr->it_present |= - cpu_to_le32(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL); - pos++; - } - /* IEEE80211_RADIOTAP_DB_ANTNOISE is not used */ /* IEEE80211_RADIOTAP_RX_FLAGS */ diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 5c88b8246bb..bad1cfbfdf1 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -173,8 +173,7 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev, range->num_encoding_sizes = 2; range->max_encoding_tokens = NUM_DEFAULT_KEYS; - if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC || - local->hw.flags & IEEE80211_HW_SIGNAL_DB) + if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) range->max_qual.level = local->hw.max_signal; else if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) range->max_qual.level = -110; -- GitLab From 587e729ecff959482d25c73278a1fbadbc6a54fe Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 30 Jan 2009 13:35:22 +0100 Subject: [PATCH 1487/4982] mac80211: convert to net_device_ops Convert to new net_device_ops in 2.6.28 and later. Signed-off-by: Stephen Hemminger Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/iface.c | 47 ++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 00562a8b99c..915d04323a3 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -591,19 +591,6 @@ static void ieee80211_set_multicast_list(struct net_device *dev) dev_mc_sync(local->mdev, dev); } -static void ieee80211_if_setup(struct net_device *dev) -{ - ether_setup(dev); - dev->hard_start_xmit = ieee80211_subif_start_xmit; - dev->wireless_handlers = &ieee80211_iw_handler_def; - dev->set_multicast_list = ieee80211_set_multicast_list; - dev->change_mtu = ieee80211_change_mtu; - dev->open = ieee80211_open; - dev->stop = ieee80211_stop; - dev->destructor = free_netdev; - /* we will validate the address ourselves in ->open */ - dev->validate_addr = NULL; -} /* * Called when the netdev is removed or, by the code below, before * the interface type changes. @@ -671,6 +658,34 @@ static void ieee80211_teardown_sdata(struct net_device *dev) WARN_ON(flushed); } +static const struct net_device_ops ieee80211_dataif_ops = { + .ndo_open = ieee80211_open, + .ndo_stop = ieee80211_stop, + .ndo_uninit = ieee80211_teardown_sdata, + .ndo_start_xmit = ieee80211_subif_start_xmit, + .ndo_set_multicast_list = ieee80211_set_multicast_list, + .ndo_change_mtu = ieee80211_change_mtu, + .ndo_set_mac_address = eth_mac_addr, +}; + +static const struct net_device_ops ieee80211_monitorif_ops = { + .ndo_open = ieee80211_open, + .ndo_stop = ieee80211_stop, + .ndo_uninit = ieee80211_teardown_sdata, + .ndo_start_xmit = ieee80211_monitor_start_xmit, + .ndo_set_multicast_list = ieee80211_set_multicast_list, + .ndo_change_mtu = ieee80211_change_mtu, + .ndo_set_mac_address = eth_mac_addr, +}; + +static void ieee80211_if_setup(struct net_device *dev) +{ + ether_setup(dev); + dev->netdev_ops = &ieee80211_dataif_ops; + dev->wireless_handlers = &ieee80211_iw_handler_def; + dev->destructor = free_netdev; +} + /* * Helper function to initialise an interface to a specific type. */ @@ -682,7 +697,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, /* and set some type-dependent values */ sdata->vif.type = type; - sdata->dev->hard_start_xmit = ieee80211_subif_start_xmit; + sdata->dev->netdev_ops = &ieee80211_dataif_ops; sdata->wdev.iftype = type; /* only monitor differs */ @@ -703,7 +718,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, break; case NL80211_IFTYPE_MONITOR: sdata->dev->type = ARPHRD_IEEE80211_RADIOTAP; - sdata->dev->hard_start_xmit = ieee80211_monitor_start_xmit; + sdata->dev->netdev_ops = &ieee80211_monitorif_ops; sdata->u.mntr_flags = MONITOR_FLAG_CONTROL | MONITOR_FLAG_OTHER_BSS; break; @@ -809,8 +824,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, if (ret) goto fail; - ndev->uninit = ieee80211_teardown_sdata; - if (ieee80211_vif_is_mesh(&sdata->vif) && params && params->mesh_id_len) ieee80211_sdata_set_mesh_id(sdata, -- GitLab From 7230645e329b4a9c566fefa9327eb8734c7d392c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 30 Jan 2009 13:36:25 +0100 Subject: [PATCH 1488/4982] mac80211: convert master interface to netdev_ops Also call our own ieee80211_master_setup routine instead of overwriting almost all the values from ether_setup; this loses a few assignments that are pointless on the master interface anyway. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/main.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 7247b303e96..caf92424c76 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -791,6 +791,23 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, } EXPORT_SYMBOL(ieee80211_alloc_hw); +static const struct net_device_ops ieee80211_master_ops = { + .ndo_start_xmit = ieee80211_master_start_xmit, + .ndo_open = ieee80211_master_open, + .ndo_stop = ieee80211_master_stop, + .ndo_set_multicast_list = ieee80211_master_set_multicast_list, + .ndo_select_queue = ieee80211_select_queue, +}; + +static void ieee80211_master_setup(struct net_device *mdev) +{ + mdev->type = ARPHRD_IEEE80211; + mdev->netdev_ops = &ieee80211_master_ops; + mdev->header_ops = &ieee80211_header_ops; + mdev->tx_queue_len = 1000; + mdev->addr_len = ETH_ALEN; +} + int ieee80211_register_hw(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); @@ -840,7 +857,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) hw->ampdu_queues = 0; mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv), - "wmaster%d", ether_setup, + "wmaster%d", ieee80211_master_setup, ieee80211_num_queues(hw)); if (!mdev) goto fail_mdev_alloc; @@ -851,13 +868,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) ieee80211_rx_bss_list_init(local); - mdev->hard_start_xmit = ieee80211_master_start_xmit; - mdev->open = ieee80211_master_open; - mdev->stop = ieee80211_master_stop; - mdev->type = ARPHRD_IEEE80211; - mdev->header_ops = &ieee80211_header_ops; - mdev->set_multicast_list = ieee80211_master_set_multicast_list; - local->hw.workqueue = create_singlethread_workqueue(wiphy_name(local->hw.wiphy)); if (!local->hw.workqueue) { @@ -923,8 +933,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) goto fail_wep; } - local->mdev->select_queue = ieee80211_select_queue; - /* add one default STA interface if supported */ if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) { result = ieee80211_if_add(local, "wlan%d", NULL, -- GitLab From 47f4d8872ffc57ad92d0fb344e677d12acc34acd Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Fri, 30 Jan 2009 09:08:29 -0800 Subject: [PATCH 1489/4982] mac80211: do not TX injected frames when not allowed Monitor mode is able to TX by using injected frames. We should not allow injected frames to be sent unless allowed by regulatory rules. Since AP mode uses a monitor interfaces to transmit management frames we have to take care to not break AP mode as well while resolving this. We can deal with this by allowing compliant APs solutions to inform mac80211 if their monitor interface is intended to be used for an AP by setting a cfg80211 flag for the monitor interface. hostapd, for example, currently does its own checks to ensure AP mode is not used on channels which require radar detection. Once such solutions are available it can can add this flag for monitor interfaces. Acked-by: Johannes Berg Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/mac80211/tx.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 7b013fb0d27..f1c726d94f4 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1433,10 +1433,31 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_channel *chan = local->hw.conf.channel; struct ieee80211_radiotap_header *prthdr = (struct ieee80211_radiotap_header *)skb->data; u16 len_rthdr; + /* + * Frame injection is not allowed if beaconing is not allowed + * or if we need radar detection. Beaconing is usually not allowed when + * the mode or operation (Adhoc, AP, Mesh) does not support DFS. + * Passive scan is also used in world regulatory domains where + * your country is not known and as such it should be treated as + * NO TX unless the channel is explicitly allowed in which case + * your current regulatory domain would not have the passive scan + * flag. + * + * Since AP mode uses monitor interfaces to inject/TX management + * frames we can make AP mode the exception to this rule once it + * supports radar detection as its implementation can deal with + * radar detection by itself. We can do that later by adding a + * monitor flag interfaces used for AP support. + */ + if ((chan->flags & (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_RADAR | + IEEE80211_CHAN_PASSIVE_SCAN))) + goto fail; + /* check for not even having the fixed radiotap header part */ if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header))) goto fail; /* too short to be possibly valid */ -- GitLab From f130347c2dd8e7ce0757cd3cf80bedbc6ed63c4c Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Fri, 30 Jan 2009 09:26:42 -0800 Subject: [PATCH 1490/4982] cfg80211: add get reg command This lets userspace request to get the currently set regulatory domain. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- include/linux/nl80211.h | 4 ++ net/wireless/nl80211.c | 81 +++++++++++++++++++++++++++++++++++++++++ net/wireless/reg.c | 2 +- net/wireless/reg.h | 2 + 4 files changed, 88 insertions(+), 1 deletion(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 76aae3d8e97..4bc27049f4e 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -113,6 +113,8 @@ * @NL80211_CMD_SET_BSS: Set BSS attributes for BSS identified by * %NL80211_ATTR_IFINDEX. * + * @NL80211_CMD_GET_REG: ask the wireless core to send us its currently set + * regulatory domain. * @NL80211_CMD_SET_REG: Set current regulatory domain. CRDA sends this command * after being queried by the kernel. CRDA replies by sending a regulatory * domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our @@ -188,6 +190,8 @@ enum nl80211_commands { NL80211_CMD_SET_MGMT_EXTRA_IE, + NL80211_CMD_GET_REG, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index e69da8d2047..d452396006e 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2093,6 +2093,81 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info) #undef FILL_IN_MESH_PARAM_IF_SET +static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) +{ + struct sk_buff *msg; + void *hdr = NULL; + struct nlattr *nl_reg_rules; + unsigned int i; + int err = -EINVAL; + + mutex_lock(&cfg80211_drv_mutex); + + if (!cfg80211_regdomain) + goto out; + + msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!msg) { + err = -ENOBUFS; + goto out; + } + + hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, + NL80211_CMD_GET_REG); + if (!hdr) + goto nla_put_failure; + + NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, + cfg80211_regdomain->alpha2); + + nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES); + if (!nl_reg_rules) + goto nla_put_failure; + + for (i = 0; i < cfg80211_regdomain->n_reg_rules; i++) { + struct nlattr *nl_reg_rule; + const struct ieee80211_reg_rule *reg_rule; + const struct ieee80211_freq_range *freq_range; + const struct ieee80211_power_rule *power_rule; + + reg_rule = &cfg80211_regdomain->reg_rules[i]; + freq_range = ®_rule->freq_range; + power_rule = ®_rule->power_rule; + + nl_reg_rule = nla_nest_start(msg, i); + if (!nl_reg_rule) + goto nla_put_failure; + + NLA_PUT_U32(msg, NL80211_ATTR_REG_RULE_FLAGS, + reg_rule->flags); + NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_START, + freq_range->start_freq_khz); + NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_END, + freq_range->end_freq_khz); + NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW, + freq_range->max_bandwidth_khz); + NLA_PUT_U32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, + power_rule->max_antenna_gain); + NLA_PUT_U32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP, + power_rule->max_eirp); + + nla_nest_end(msg, nl_reg_rule); + } + + nla_nest_end(msg, nl_reg_rules); + + genlmsg_end(msg, hdr); + err = genlmsg_unicast(msg, info->snd_pid); + goto out; + +nla_put_failure: + genlmsg_cancel(msg, hdr); + err = -EMSGSIZE; +out: + mutex_unlock(&cfg80211_drv_mutex); + return err; +} + static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) { struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1]; @@ -2332,6 +2407,12 @@ static struct genl_ops nl80211_ops[] = { .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, }, + { + .cmd = NL80211_CMD_GET_REG, + .doit = nl80211_get_reg, + .policy = nl80211_policy, + /* can be retrieved by unprivileged users */ + }, { .cmd = NL80211_CMD_SET_REG, .doit = nl80211_set_reg, diff --git a/net/wireless/reg.c b/net/wireless/reg.c index f643d398110..2323644330c 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -57,7 +57,7 @@ static u32 supported_bandwidths[] = { /* Central wireless core regulatory domains, we only need two, * the current one and a world regulatory domain in case we have no * information to give us an alpha2 */ -static const struct ieee80211_regdomain *cfg80211_regdomain; +const struct ieee80211_regdomain *cfg80211_regdomain; /* We use this as a place for the rd structure built from the * last parsed country IE to rest until CRDA gets back to us with diff --git a/net/wireless/reg.h b/net/wireless/reg.h index eb1dd5bc9b2..fe8c83f34fb 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h @@ -1,6 +1,8 @@ #ifndef __NET_WIRELESS_REG_H #define __NET_WIRELESS_REG_H +extern const struct ieee80211_regdomain *cfg80211_regdomain; + bool is_world_regdom(const char *alpha2); bool reg_is_valid_request(const char *alpha2); -- GitLab From 964d6ad935d96a002fdbbdfcac38f02a084f75d9 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 31 Jan 2009 10:07:39 +0100 Subject: [PATCH 1491/4982] Add new rt73usb USB ID Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt73usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index be791a43c05..6521dac7ec4 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2368,6 +2368,7 @@ static struct usb_device_id rt73usb_device_table[] = { /* Billionton */ { USB_DEVICE(0x1631, 0xc019), USB_DEVICE_DATA(&rt73usb_ops) }, /* Buffalo */ + { USB_DEVICE(0x0411, 0x00d8), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) }, /* CNet */ { USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt73usb_ops) }, -- GitLab From a387cc7d380504bf64743789f47de35605e05596 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 31 Jan 2009 14:20:44 +0100 Subject: [PATCH 1492/4982] b43: Add LP-PHY register definitions This adds register definitions for the LP-PHY. This also adds a few minor empty function bodies for the LP-init. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_lp.c | 33 ++++ drivers/net/wireless/b43/phy_lp.h | 273 ++++++++++++++++++++++++++++++ 2 files changed, 306 insertions(+) diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index c5d9dc3667c..ec83b8cd2f2 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -57,8 +57,41 @@ static void b43_lpphy_op_free(struct b43_wldev *dev) dev->phy.lp = NULL; } +static void lpphy_table_init(struct b43_wldev *dev) +{ + //TODO +} + +static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) +{ + B43_WARN_ON(1);//TODO rev < 2 not supported, yet. +} + +static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) +{ + //TODO +} + +static void lpphy_baseband_init(struct b43_wldev *dev) +{ + lpphy_table_init(dev); + if (dev->phy.rev >= 2) + lpphy_baseband_rev2plus_init(dev); + else + lpphy_baseband_rev0_1_init(dev); +} + +static void lpphy_radio_init(struct b43_wldev *dev) +{ + //TODO +} + static int b43_lpphy_op_init(struct b43_wldev *dev) { + /* TODO: band SPROM */ + lpphy_baseband_init(dev); + lpphy_radio_init(dev); + //TODO return 0; diff --git a/drivers/net/wireless/b43/phy_lp.h b/drivers/net/wireless/b43/phy_lp.h index b0b5357abf9..c3f92f17259 100644 --- a/drivers/net/wireless/b43/phy_lp.h +++ b/drivers/net/wireless/b43/phy_lp.h @@ -4,8 +4,281 @@ /* Definitions for the LP-PHY */ +/* The CCK PHY register range. */ +#define B43_LPPHY_B_VERSION B43_PHY_CCK(0x00) /* B PHY version */ +#define B43_LPPHY_B_BBCONFIG B43_PHY_CCK(0x01) /* B PHY BBConfig */ +#define B43_LPPHY_B_RX_STAT0 B43_PHY_CCK(0x04) /* B PHY RX Status0 */ +#define B43_LPPHY_B_RX_STAT1 B43_PHY_CCK(0x05) /* B PHY RX Status1 */ +#define B43_LPPHY_B_CRS_THRESH B43_PHY_CCK(0x06) /* B PHY CRS Thresh */ +#define B43_LPPHY_B_TXERROR B43_PHY_CCK(0x07) /* B PHY TxError */ +#define B43_LPPHY_B_CHANNEL B43_PHY_CCK(0x08) /* B PHY Channel */ +#define B43_LPPHY_B_WORKAROUND B43_PHY_CCK(0x09) /* B PHY workaround */ +#define B43_LPPHY_B_TEST B43_PHY_CCK(0x0A) /* B PHY Test */ +#define B43_LPPHY_B_FOURWIRE_ADDR B43_PHY_CCK(0x0B) /* B PHY Fourwire Address */ +#define B43_LPPHY_B_FOURWIRE_DATA_HI B43_PHY_CCK(0x0C) /* B PHY Fourwire Data Hi */ +#define B43_LPPHY_B_FOURWIRE_DATA_LO B43_PHY_CCK(0x0D) /* B PHY Fourwire Data Lo */ +#define B43_LPPHY_B_BIST_STAT B43_PHY_CCK(0x0E) /* B PHY Bist Status */ +#define B43_LPPHY_PA_RAMP_TX_TO B43_PHY_CCK(0x10) /* PA Ramp TX Timeout */ +#define B43_LPPHY_RF_SYNTH_DC_TIMER B43_PHY_CCK(0x11) /* RF Synth DC Timer */ +#define B43_LPPHY_PA_RAMP_TX_TIME_IN B43_PHY_CCK(0x12) /* PA ramp TX Time in */ +#define B43_LPPHY_RX_FILTER_TIME_IN B43_PHY_CCK(0x13) /* RX Filter Time in */ +#define B43_LPPHY_PLL_COEFF_S B43_PHY_CCK(0x18) /* PLL Coefficient(s) */ +#define B43_LPPHY_PLL_OUT B43_PHY_CCK(0x19) /* PLL Out */ +#define B43_LPPHY_RSSI_THRES B43_PHY_CCK(0x20) /* RSSI Threshold */ +#define B43_LPPHY_IQ_THRES_HH B43_PHY_CCK(0x21) /* IQ Threshold HH */ +#define B43_LPPHY_IQ_THRES_H B43_PHY_CCK(0x22) /* IQ Threshold H */ +#define B43_LPPHY_IQ_THRES_L B43_PHY_CCK(0x23) /* IQ Threshold L */ +#define B43_LPPHY_IQ_THRES_LL B43_PHY_CCK(0x24) /* IQ Threshold LL */ +#define B43_LPPHY_AGC_GAIN B43_PHY_CCK(0x25) /* AGC Gain */ +#define B43_LPPHY_LNA_GAIN_RANGE B43_PHY_CCK(0x26) /* LNA Gain Range */ +#define B43_LPPHY_JSSI B43_PHY_CCK(0x27) /* JSSI */ +#define B43_LPPHY_TSSI_CTL B43_PHY_CCK(0x28) /* TSSI Control */ +#define B43_LPPHY_TSSI B43_PHY_CCK(0x29) /* TSSI */ +#define B43_LPPHY_TR_LOSS B43_PHY_CCK(0x2A) /* TR Loss */ +#define B43_LPPHY_LO_LEAKAGE B43_PHY_CCK(0x2B) /* LO Leakage */ +#define B43_LPPHY_LO_RSSIACC B43_PHY_CCK(0x2C) /* LO RSSIAcc */ +#define B43_LPPHY_LO_IQ_MAG_ACC B43_PHY_CCK(0x2D) /* LO IQ Mag Acc */ +#define B43_LPPHY_TX_DCOFFSET1 B43_PHY_CCK(0x2E) /* TX DCOffset1 */ +#define B43_LPPHY_TX_DCOFFSET2 B43_PHY_CCK(0x2F) /* TX DCOffset2 */ +#define B43_LPPHY_SYNCPEAKCNT B43_PHY_CCK(0x30) /* SyncPeakCnt */ +#define B43_LPPHY_SYNCFREQ B43_PHY_CCK(0x31) /* SyncFreq */ +#define B43_LPPHY_SYNCDIVERSITYCTL B43_PHY_CCK(0x32) /* SyncDiversityControl */ +#define B43_LPPHY_PEAKENERGYL B43_PHY_CCK(0x33) /* PeakEnergyL */ +#define B43_LPPHY_PEAKENERGYH B43_PHY_CCK(0x34) /* PeakEnergyH */ +#define B43_LPPHY_SYNCCTL B43_PHY_CCK(0x35) /* SyncControl */ +#define B43_LPPHY_DSSSSTEP B43_PHY_CCK(0x38) /* DsssStep */ +#define B43_LPPHY_DSSSWARMUP B43_PHY_CCK(0x39) /* DsssWarmup */ +#define B43_LPPHY_DSSSSIGPOW B43_PHY_CCK(0x3D) /* DsssSigPow */ +#define B43_LPPHY_SFDDETECTBLOCKTIME B43_PHY_CCK(0x40) /* SfdDetectBlockTIme */ +#define B43_LPPHY_SFDTO B43_PHY_CCK(0x41) /* SFDTimeOut */ +#define B43_LPPHY_SFDCTL B43_PHY_CCK(0x42) /* SFDControl */ +#define B43_LPPHY_RXDBG B43_PHY_CCK(0x43) /* rxDebug */ +#define B43_LPPHY_RX_DELAYCOMP B43_PHY_CCK(0x44) /* RX DelayComp */ +#define B43_LPPHY_CRSDROPOUTTO B43_PHY_CCK(0x45) /* CRSDropoutTimeout */ +#define B43_LPPHY_PSEUDOSHORTTO B43_PHY_CCK(0x46) /* PseudoShortTimeout */ +#define B43_LPPHY_PR3931 B43_PHY_CCK(0x47) /* PR3931 */ +#define B43_LPPHY_DSSSCOEFF1 B43_PHY_CCK(0x48) /* DSSSCoeff1 */ +#define B43_LPPHY_DSSSCOEFF2 B43_PHY_CCK(0x49) /* DSSSCoeff2 */ +#define B43_LPPHY_CCKCOEFF1 B43_PHY_CCK(0x4A) /* CCKCoeff1 */ +#define B43_LPPHY_CCKCOEFF2 B43_PHY_CCK(0x4B) /* CCKCoeff2 */ +#define B43_LPPHY_TRCORR B43_PHY_CCK(0x4C) /* TRCorr */ +#define B43_LPPHY_ANGLESCALE B43_PHY_CCK(0x4D) /* AngleScale */ +#define B43_LPPHY_OPTIONALMODES2 B43_PHY_CCK(0x4F) /* OptionalModes2 */ +#define B43_LPPHY_CCKLMSSTEPSIZE B43_PHY_CCK(0x50) /* CCKLMSStepSize */ +#define B43_LPPHY_DFEBYPASS B43_PHY_CCK(0x51) /* DFEBypass */ +#define B43_LPPHY_CCKSTARTDELAYLONG B43_PHY_CCK(0x52) /* CCKStartDelayLong */ +#define B43_LPPHY_CCKSTARTDELAYSHORT B43_PHY_CCK(0x53) /* CCKStartDelayShort */ +#define B43_LPPHY_PPROCCHDELAY B43_PHY_CCK(0x54) /* PprocChDelay */ +#define B43_LPPHY_PPROCONOFF B43_PHY_CCK(0x55) /* PProcOnOff */ +#define B43_LPPHY_LNAGAINTWOBIT10 B43_PHY_CCK(0x5B) /* LNAGainTwoBit10 */ +#define B43_LPPHY_LNAGAINTWOBIT32 B43_PHY_CCK(0x5C) /* LNAGainTwoBit32 */ +#define B43_LPPHY_OPTIONALMODES B43_PHY_CCK(0x5D) /* OptionalModes */ +#define B43_LPPHY_B_RX_STAT2 B43_PHY_CCK(0x5E) /* B PHY RX Status2 */ +#define B43_LPPHY_B_RX_STAT3 B43_PHY_CCK(0x5F) /* B PHY RX Status3 */ +#define B43_LPPHY_PWDNDACDELAY B43_PHY_CCK(0x63) /* pwdnDacDelay */ +#define B43_LPPHY_FINEDIGIGAIN_CTL B43_PHY_CCK(0x67) /* FineDigiGain Control */ +#define B43_LPPHY_LG2GAINTBLLNA8 B43_PHY_CCK(0x68) /* Lg2GainTblLNA8 */ +#define B43_LPPHY_LG2GAINTBLLNA28 B43_PHY_CCK(0x69) /* Lg2GainTblLNA28 */ +#define B43_LPPHY_GAINTBLLNATRSW B43_PHY_CCK(0x6A) /* GainTblLNATrSw */ +#define B43_LPPHY_PEAKENERGY B43_PHY_CCK(0x6B) /* PeakEnergy */ +#define B43_LPPHY_LG2INITGAIN B43_PHY_CCK(0x6C) /* lg2InitGain */ +#define B43_LPPHY_BLANKCOUNTLNAPGA B43_PHY_CCK(0x6D) /* BlankCountLnaPga */ +#define B43_LPPHY_LNAGAINTWOBIT54 B43_PHY_CCK(0x6E) /* LNAGainTwoBit54 */ +#define B43_LPPHY_LNAGAINTWOBIT76 B43_PHY_CCK(0x6F) /* LNAGainTwoBit76 */ +#define B43_LPPHY_JSSICTL B43_PHY_CCK(0x70) /* JSSIControl */ +#define B43_LPPHY_LG2GAINTBLLNA44 B43_PHY_CCK(0x71) /* Lg2GainTblLNA44 */ +#define B43_LPPHY_LG2GAINTBLLNA62 B43_PHY_CCK(0x72) /* Lg2GainTblLNA62 */ +/* The OFDM PHY register range. */ +#define B43_LPPHY_VERSION B43_PHY_OFDM(0x00) /* Version */ +#define B43_LPPHY_BBCONFIG B43_PHY_OFDM(0x01) /* BBConfig */ +#define B43_LPPHY_RX_STAT0 B43_PHY_OFDM(0x04) /* RX Status0 */ +#define B43_LPPHY_RX_STAT1 B43_PHY_OFDM(0x05) /* RX Status1 */ +#define B43_LPPHY_TX_ERROR B43_PHY_OFDM(0x07) /* TX Error */ +#define B43_LPPHY_CHANNEL B43_PHY_OFDM(0x08) /* Channel */ +#define B43_LPPHY_WORKAROUND B43_PHY_OFDM(0x09) /* workaround */ +#define B43_LPPHY_FOURWIRE_ADDR B43_PHY_OFDM(0x0B) /* Fourwire Address */ +#define B43_LPPHY_FOURWIREDATAHI B43_PHY_OFDM(0x0C) /* FourwireDataHi */ +#define B43_LPPHY_FOURWIREDATALO B43_PHY_OFDM(0x0D) /* FourwireDataLo */ +#define B43_LPPHY_BISTSTAT0 B43_PHY_OFDM(0x0E) /* BistStatus0 */ +#define B43_LPPHY_BISTSTAT1 B43_PHY_OFDM(0x0F) /* BistStatus1 */ +#define B43_LPPHY_CRSGAIN_CTL B43_PHY_OFDM(0x10) /* crsgain Control */ +#define B43_LPPHY_OFDMPWR_THRESH0 B43_PHY_OFDM(0x11) /* ofdmPower Thresh0 */ +#define B43_LPPHY_OFDMPWR_THRESH1 B43_PHY_OFDM(0x12) /* ofdmPower Thresh1 */ +#define B43_LPPHY_OFDMPWR_THRESH2 B43_PHY_OFDM(0x13) /* ofdmPower Thresh2 */ +#define B43_LPPHY_DSSSPWR_THRESH0 B43_PHY_OFDM(0x14) /* dsssPower Thresh0 */ +#define B43_LPPHY_DSSSPWR_THRESH1 B43_PHY_OFDM(0x15) /* dsssPower Thresh1 */ +#define B43_LPPHY_MINPWR_LEVEL B43_PHY_OFDM(0x16) /* MinPower Level */ +#define B43_LPPHY_OFDMSYNCTHRESH0 B43_PHY_OFDM(0x17) /* ofdmSyncThresh0 */ +#define B43_LPPHY_OFDMSYNCTHRESH1 B43_PHY_OFDM(0x18) /* ofdmSyncThresh1 */ +#define B43_LPPHY_FINEFREQEST B43_PHY_OFDM(0x19) /* FineFreqEst */ +#define B43_LPPHY_IDLEAFTERPKTRXTO B43_PHY_OFDM(0x1A) /* IDLEafterPktRXTimeout */ +#define B43_LPPHY_LTRN_CTL B43_PHY_OFDM(0x1B) /* LTRN Control */ +#define B43_LPPHY_DCOFFSETTRANSIENT B43_PHY_OFDM(0x1C) /* DCOffsetTransient */ +#define B43_LPPHY_PREAMBLEINTO B43_PHY_OFDM(0x1D) /* PreambleInTimeout */ +#define B43_LPPHY_PREAMBLECONFIRMTO B43_PHY_OFDM(0x1E) /* PreambleConfirmTimeout */ +#define B43_LPPHY_CLIPTHRESH B43_PHY_OFDM(0x1F) /* ClipThresh */ +#define B43_LPPHY_CLIPCTRTHRESH B43_PHY_OFDM(0x20) /* ClipCtrThresh */ +#define B43_LPPHY_OFDMSYNCTIMER_CTL B43_PHY_OFDM(0x21) /* ofdmSyncTimer Control */ +#define B43_LPPHY_WAITFORPHYSELTO B43_PHY_OFDM(0x22) /* WaitforPHYSelTimeout */ +#define B43_LPPHY_HIGAINDB B43_PHY_OFDM(0x23) /* HiGainDB */ +#define B43_LPPHY_LOWGAINDB B43_PHY_OFDM(0x24) /* LowGainDB */ +#define B43_LPPHY_VERYLOWGAINDB B43_PHY_OFDM(0x25) /* VeryLowGainDB */ +#define B43_LPPHY_GAINMISMATCH B43_PHY_OFDM(0x26) /* gainMismatch */ +#define B43_LPPHY_GAINDIRECTMISMATCH B43_PHY_OFDM(0x27) /* gaindirectMismatch */ +#define B43_LPPHY_PWR_THRESH0 B43_PHY_OFDM(0x28) /* Power Thresh0 */ +#define B43_LPPHY_PWR_THRESH1 B43_PHY_OFDM(0x29) /* Power Thresh1 */ +#define B43_LPPHY_DETECTOR_DELAY_ADJUST B43_PHY_OFDM(0x2A) /* Detector Delay Adjust */ +#define B43_LPPHY_REDUCED_DETECTOR_DELAY B43_PHY_OFDM(0x2B) /* Reduced Detector Delay */ +#define B43_LPPHY_DATA_TO B43_PHY_OFDM(0x2C) /* data Timeout */ +#define B43_LPPHY_CORRELATOR_DIS_DELAY B43_PHY_OFDM(0x2D) /* correlator Dis Delay */ +#define B43_LPPHY_DIVERSITY_GAINBACK B43_PHY_OFDM(0x2E) /* Diversity GainBack */ +#define B43_LPPHY_DSSS_CONFIRM_CNT B43_PHY_OFDM(0x2F) /* DSSS Confirm Cnt */ +#define B43_LPPHY_DC_BLANK_INT B43_PHY_OFDM(0x30) /* DC Blank Interval */ +#define B43_LPPHY_GAIN_MISMATCH_LIMIT B43_PHY_OFDM(0x31) /* gain Mismatch Limit */ +#define B43_LPPHY_CRS_ED_THRESH B43_PHY_OFDM(0x32) /* crs ed thresh */ +#define B43_LPPHY_PHASE_SHIFT_CTL B43_PHY_OFDM(0x33) /* phase shift Control */ +#define B43_LPPHY_INPUT_PWRDB B43_PHY_OFDM(0x34) /* Input PowerDB */ +#define B43_LPPHY_OFDM_SYNC_CTL B43_PHY_OFDM(0x35) /* ofdm sync Control */ +#define B43_LPPHY_AFE_ADC_CTL_0 B43_PHY_OFDM(0x36) /* Afe ADC Control 0 */ +#define B43_LPPHY_AFE_ADC_CTL_1 B43_PHY_OFDM(0x37) /* Afe ADC Control 1 */ +#define B43_LPPHY_AFE_ADC_CTL_2 B43_PHY_OFDM(0x38) /* Afe ADC Control 2 */ +#define B43_LPPHY_AFE_DAC_CTL B43_PHY_OFDM(0x39) /* Afe DAC Control */ +#define B43_LPPHY_AFE_CTL B43_PHY_OFDM(0x3A) /* Afe Control */ +#define B43_LPPHY_AFE_CTL_OVR B43_PHY_OFDM(0x3B) /* Afe Control Ovr */ +#define B43_LPPHY_AFE_CTL_OVRVAL B43_PHY_OFDM(0x3C) /* Afe Control OvrVal */ +#define B43_LPPHY_AFE_RSSI_CTL_0 B43_PHY_OFDM(0x3D) /* Afe RSSI Control 0 */ +#define B43_LPPHY_AFE_RSSI_CTL_1 B43_PHY_OFDM(0x3E) /* Afe RSSI Control 1 */ +#define B43_LPPHY_AFE_RSSI_SEL B43_PHY_OFDM(0x3F) /* Afe RSSI Sel */ +#define B43_LPPHY_RADAR_THRESH B43_PHY_OFDM(0x40) /* Radar Thresh */ +#define B43_LPPHY_RADAR_BLANK_INT B43_PHY_OFDM(0x41) /* Radar blank Interval */ +#define B43_LPPHY_RADAR_MIN_FM_INT B43_PHY_OFDM(0x42) /* Radar min fm Interval */ +#define B43_LPPHY_RADAR_GAIN_TO B43_PHY_OFDM(0x43) /* Radar gain timeout */ +#define B43_LPPHY_RADAR_PULSE_TO B43_PHY_OFDM(0x44) /* Radar pulse timeout */ +#define B43_LPPHY_RADAR_DETECT_FM_CTL B43_PHY_OFDM(0x45) /* Radar detect FM Control */ +#define B43_LPPHY_RADAR_DETECT_EN B43_PHY_OFDM(0x46) /* Radar detect En */ +#define B43_LPPHY_RADAR_RD_DATA_REG B43_PHY_OFDM(0x47) /* Radar Rd Data Reg */ +#define B43_LPPHY_LP_PHY_CTL B43_PHY_OFDM(0x48) /* LP PHY Control */ +#define B43_LPPHY_CLASSIFIER_CTL B43_PHY_OFDM(0x49) /* classifier Control */ +#define B43_LPPHY_RESET_CTL B43_PHY_OFDM(0x4A) /* reset Control */ +#define B43_LPPHY_CLKEN_CTL B43_PHY_OFDM(0x4B) /* ClkEn Control */ +#define B43_LPPHY_RF_OVERRIDE_0 B43_PHY_OFDM(0x4C) /* RF Override 0 */ +#define B43_LPPHY_RF_OVERRIDE_VAL_0 B43_PHY_OFDM(0x4D) /* RF Override Val 0 */ +#define B43_LPPHY_TR_LOOKUP_1 B43_PHY_OFDM(0x4E) /* TR Lookup 1 */ +#define B43_LPPHY_TR_LOOKUP_2 B43_PHY_OFDM(0x4F) /* TR Lookup 2 */ +#define B43_LPPHY_RSSISELLOOKUP1 B43_PHY_OFDM(0x50) /* RssiSelLookup1 */ +#define B43_LPPHY_IQLO_CAL_CMD B43_PHY_OFDM(0x51) /* iqlo Cal Cmd */ +#define B43_LPPHY_IQLO_CAL_CMD_N_NUM B43_PHY_OFDM(0x52) /* iqlo Cal Cmd N num */ +#define B43_LPPHY_IQLO_CAL_CMD_G_CTL B43_PHY_OFDM(0x53) /* iqlo Cal Cmd G control */ +#define B43_LPPHY_MACINT_DBG_REGISTER B43_PHY_OFDM(0x54) /* macint Debug Register */ +#define B43_LPPHY_TABLE_ADDR B43_PHY_OFDM(0x55) /* Table Address */ +#define B43_LPPHY_TABLEDATALO B43_PHY_OFDM(0x56) /* TabledataLo */ +#define B43_LPPHY_TABLEDATAHI B43_PHY_OFDM(0x57) /* TabledataHi */ +#define B43_LPPHY_PHY_CRS_ENABLE_ADDR B43_PHY_OFDM(0x58) /* phy CRS Enable Address */ +#define B43_LPPHY_IDLETIME_CTL B43_PHY_OFDM(0x59) /* Idletime Control */ +#define B43_LPPHY_IDLETIME_CRS_ON_LO B43_PHY_OFDM(0x5A) /* Idletime CRS On Lo */ +#define B43_LPPHY_IDLETIME_CRS_ON_HI B43_PHY_OFDM(0x5B) /* Idletime CRS On Hi */ +#define B43_LPPHY_IDLETIME_MEAS_TIME_LO B43_PHY_OFDM(0x5C) /* Idletime Meas Time Lo */ +#define B43_LPPHY_IDLETIME_MEAS_TIME_HI B43_PHY_OFDM(0x5D) /* Idletime Meas Time Hi */ +#define B43_LPPHY_RESET_LEN_OFDM_TX_ADDR B43_PHY_OFDM(0x5E) /* Reset len Ofdm TX Address */ +#define B43_LPPHY_RESET_LEN_OFDM_RX_ADDR B43_PHY_OFDM(0x5F) /* Reset len Ofdm RX Address */ +#define B43_LPPHY_REG_CRS_ENABLE B43_PHY_OFDM(0x60) /* reg crs enable */ +#define B43_LPPHY_PLCP_TMT_STR0_CTR_MIN B43_PHY_OFDM(0x61) /* PLCP Tmt Str0 Ctr Min */ +#define B43_LPPHY_PKT_FSM_RESET_LEN_VAL B43_PHY_OFDM(0x62) /* Pkt fsm Reset Len Value */ +#define B43_LPPHY_READSYM2RESET_CTL B43_PHY_OFDM(0x63) /* readsym2reset Control */ +#define B43_LPPHY_DC_FILTER_DELAY1 B43_PHY_OFDM(0x64) /* Dc filter delay1 */ +#define B43_LPPHY_PACKET_RX_ACTIVE_TO B43_PHY_OFDM(0x65) /* packet rx Active timeout */ +#define B43_LPPHY_ED_TOVAL B43_PHY_OFDM(0x66) /* ed timeoutValue */ +#define B43_LPPHY_HOLD_CRS_ON_VAL B43_PHY_OFDM(0x67) /* hold CRS On Value */ +#define B43_LPPHY_OFDM_TX_PHY_CRS_DELAY_VAL B43_PHY_OFDM(0x69) /* ofdm tx phy CRS Delay Value */ +#define B43_LPPHY_CCK_TX_PHY_CRS_DELAY_VAL B43_PHY_OFDM(0x6A) /* cck tx phy CRS Delay Value */ +#define B43_LPPHY_ED_ON_CONFIRM_TIMER_VAL B43_PHY_OFDM(0x6B) /* Ed on confirm Timer Value */ +#define B43_LPPHY_ED_OFFSET_CONFIRM_TIMER_VAL B43_PHY_OFDM(0x6C) /* Ed offset confirm Timer Value */ +#define B43_LPPHY_PHY_CRS_OFFSET_TIMER_VAL B43_PHY_OFDM(0x6D) /* phy CRS offset Timer Value */ +#define B43_LPPHY_ADC_COMPENSATION_CTL B43_PHY_OFDM(0x70) /* ADC Compensation Control */ +#define B43_LPPHY_LOG2_RBPSK_ADDR B43_PHY_OFDM(0x71) /* log2 RBPSK Address */ +#define B43_LPPHY_LOG2_RQPSK_ADDR B43_PHY_OFDM(0x72) /* log2 RQPSK Address */ +#define B43_LPPHY_LOG2_R16QAM_ADDR B43_PHY_OFDM(0x73) /* log2 R16QAM Address */ +#define B43_LPPHY_LOG2_R64QAM_ADDR B43_PHY_OFDM(0x74) /* log2 R64QAM Address */ +#define B43_LPPHY_OFFSET_BPSK_ADDR B43_PHY_OFDM(0x75) /* offset BPSK Address */ +#define B43_LPPHY_OFFSET_QPSK_ADDR B43_PHY_OFDM(0x76) /* offset QPSK Address */ +#define B43_LPPHY_OFFSET_16QAM_ADDR B43_PHY_OFDM(0x77) /* offset 16QAM Address */ +#define B43_LPPHY_OFFSET_64QAM_ADDR B43_PHY_OFDM(0x78) /* offset 64QAM Address */ +#define B43_LPPHY_ALPHA1 B43_PHY_OFDM(0x79) /* Alpha1 */ +#define B43_LPPHY_ALPHA2 B43_PHY_OFDM(0x7A) /* Alpha2 */ +#define B43_LPPHY_BETA1 B43_PHY_OFDM(0x7B) /* Beta1 */ +#define B43_LPPHY_BETA2 B43_PHY_OFDM(0x7C) /* Beta2 */ +#define B43_LPPHY_LOOP_NUM_ADDR B43_PHY_OFDM(0x7D) /* Loop Num Address */ +#define B43_LPPHY_STR_COLLMAX_SMPL_ADDR B43_PHY_OFDM(0x7E) /* Str Collmax Sample Address */ +#define B43_LPPHY_MAX_SMPL_COARSE_FINE_ADDR B43_PHY_OFDM(0x7F) /* Max Sample Coarse/Fine Address */ +#define B43_LPPHY_MAX_SMPL_COARSE_STR0CTR_ADDR B43_PHY_OFDM(0x80) /* Max Sample Coarse/Str0Ctr Address */ +#define B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR B43_PHY_OFDM(0x81) /* IQ Enable Wait Time Address */ +#define B43_LPPHY_IQ_NUM_SMPLS_ADDR B43_PHY_OFDM(0x82) /* IQ Num Samples Address */ +#define B43_LPPHY_IQ_ACC_HI_ADDR B43_PHY_OFDM(0x83) /* IQ Acc Hi Address */ +#define B43_LPPHY_IQ_ACC_LO_ADDR B43_PHY_OFDM(0x84) /* IQ Acc Lo Address */ +#define B43_LPPHY_IQ_I_PWR_ACC_HI_ADDR B43_PHY_OFDM(0x85) /* IQ I PWR Acc Hi Address */ +#define B43_LPPHY_IQ_I_PWR_ACC_LO_ADDR B43_PHY_OFDM(0x86) /* IQ I PWR Acc Lo Address */ +#define B43_LPPHY_IQ_Q_PWR_ACC_HI_ADDR B43_PHY_OFDM(0x87) /* IQ Q PWR Acc Hi Address */ +#define B43_LPPHY_IQ_Q_PWR_ACC_LO_ADDR B43_PHY_OFDM(0x88) /* IQ Q PWR Acc Lo Address */ +#define B43_LPPHY_MAXNUMSTEPS B43_PHY_OFDM(0x89) /* MaxNumsteps */ +#define B43_LPPHY_ROTORPHASE_ADDR B43_PHY_OFDM(0x8A) /* RotorPhase Address */ +#define B43_LPPHY_ADVANCEDRETARDROTOR_ADDR B43_PHY_OFDM(0x8B) /* AdvancedRetardRotor Address */ +#define B43_LPPHY_RSSIADCDELAY_CTL_ADDR B43_PHY_OFDM(0x8D) /* rssiAdcdelay Control Address */ +#define B43_LPPHY_TSSISTAT_ADDR B43_PHY_OFDM(0x8E) /* tssiStatus Address */ +#define B43_LPPHY_TEMPSENSESTAT_ADDR B43_PHY_OFDM(0x8F) /* tempsenseStatus Address */ +#define B43_LPPHY_TEMPSENSE_CTL_ADDR B43_PHY_OFDM(0x90) /* tempsense Control Address */ +#define B43_LPPHY_WRSSISTAT_ADDR B43_PHY_OFDM(0x91) /* wrssistatus Address */ +#define B43_LPPHY_MUFACTORADDR B43_PHY_OFDM(0x92) /* mufactoraddr */ +#define B43_LPPHY_SCRAMSTATE_ADDR B43_PHY_OFDM(0x93) /* scramstate Address */ +#define B43_LPPHY_TXHOLDOFFADDR B43_PHY_OFDM(0x94) /* txholdoffaddr */ +#define B43_LPPHY_PKTGAINVAL_ADDR B43_PHY_OFDM(0x95) /* pktgainval Address */ +#define B43_LPPHY_COARSEESTIM_ADDR B43_PHY_OFDM(0x96) /* Coarseestim Address */ +#define B43_LPPHY_STATE_TRANSITION_ADDR B43_PHY_OFDM(0x97) /* state Transition Address */ +#define B43_LPPHY_TRN_OFFSET_ADDR B43_PHY_OFDM(0x98) /* TRN offset Address */ +#define B43_LPPHY_NUM_ROTOR_ADDR B43_PHY_OFDM(0x99) /* Num Rotor Address */ +#define B43_LPPHY_VITERBI_OFFSET_ADDR B43_PHY_OFDM(0x9A) /* Viterbi Offset Address */ +#define B43_LPPHY_SMPL_COLLECT_WAIT_ADDR B43_PHY_OFDM(0x9B) /* Sample collect wait Address */ +#define B43_LPPHY_A_PHY_CTL_ADDR B43_PHY_OFDM(0x9C) /* A PHY Control Address */ +#define B43_LPPHY_NUM_PASS_THROUGH_ADDR B43_PHY_OFDM(0x9D) /* Num Pass Through Address */ +#define B43_LPPHY_RX_COMP_COEFF_S B43_PHY_OFDM(0x9E) /* RX Comp coefficient(s) */ +#define B43_LPPHY_CPAROTATEVAL B43_PHY_OFDM(0x9F) /* cpaRotateValue */ +#define B43_LPPHY_SMPL_PLAY_COUNT B43_PHY_OFDM(0xA0) /* Sample play count */ +#define B43_LPPHY_SMPL_PLAY_BUFFER_CTL B43_PHY_OFDM(0xA1) /* Sample play Buffer Control */ +#define B43_LPPHY_FOURWIRE_CTL B43_PHY_OFDM(0xA2) /* fourwire Control */ +#define B43_LPPHY_CPA_TAILCOUNT_VAL B43_PHY_OFDM(0xA3) /* CPA TailCount Value */ +#define B43_LPPHY_TX_PWR_CTL_CMD B43_PHY_OFDM(0xA4) /* TX Power Control Cmd */ +#define B43_LPPHY_TX_PWR_CTL_NNUM B43_PHY_OFDM(0xA5) /* TX Power Control Nnum */ +#define B43_LPPHY_TX_PWR_CTL_IDLETSSI B43_PHY_OFDM(0xA6) /* TX Power Control IdleTssi */ +#define B43_LPPHY_TX_PWR_CTL_TARGETPWR B43_PHY_OFDM(0xA7) /* TX Power Control TargetPower */ +#define B43_LPPHY_TX_PWR_CTL_DELTAPWR_LIMIT B43_PHY_OFDM(0xA8) /* TX Power Control DeltaPower Limit */ +#define B43_LPPHY_TX_PWR_CTL_BASEINDEX B43_PHY_OFDM(0xA9) /* TX Power Control BaseIndex */ +#define B43_LPPHY_TX_PWR_CTL_PWR_INDEX B43_PHY_OFDM(0xAA) /* TX Power Control Power Index */ +#define B43_LPPHY_TX_PWR_CTL_STAT B43_PHY_OFDM(0xAB) /* TX Power Control Status */ +#define B43_LPPHY_LP_RF_SIGNAL_LUT B43_PHY_OFDM(0xAC) /* LP RF signal LUT */ +#define B43_LPPHY_RX_RADIO_CTL_FILTER_STATE B43_PHY_OFDM(0xAD) /* RX Radio Control Filter State */ +#define B43_LPPHY_RX_RADIO_CTL B43_PHY_OFDM(0xAE) /* RX Radio Control */ +#define B43_LPPHY_NRSSI_STAT_ADDR B43_PHY_OFDM(0xAF) /* NRSSI status Address */ +#define B43_LPPHY_RF_OVERRIDE_2 B43_PHY_OFDM(0xB0) /* RF override 2 */ +#define B43_LPPHY_RF_OVERRIDE_2_VAL B43_PHY_OFDM(0xB1) /* RF override 2 val */ +#define B43_LPPHY_PS_CTL_OVERRIDE_VAL0 B43_PHY_OFDM(0xB2) /* PS Control override val0 */ +#define B43_LPPHY_PS_CTL_OVERRIDE_VAL1 B43_PHY_OFDM(0xB3) /* PS Control override val1 */ +#define B43_LPPHY_PS_CTL_OVERRIDE_VAL2 B43_PHY_OFDM(0xB4) /* PS Control override val2 */ +#define B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL B43_PHY_OFDM(0xB5) /* TX gain Control override val */ +#define B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL B43_PHY_OFDM(0xB6) /* RX gain Control override val */ +#define B43_LPPHY_AFE_DDFS B43_PHY_OFDM(0xB7) /* AFE DDFS */ +#define B43_LPPHY_AFE_DDFS_POINTER_INIT B43_PHY_OFDM(0xB8) /* AFE DDFS pointer init */ +#define B43_LPPHY_AFE_DDFS_INCR_INIT B43_PHY_OFDM(0xB9) /* AFE DDFS incr init */ +#define B43_LPPHY_MRCNOISEREDUCTION B43_PHY_OFDM(0xBA) /* mrcNoiseReduction */ +#define B43_LPPHY_TRLOOKUP3 B43_PHY_OFDM(0xBB) /* TRLookup3 */ +#define B43_LPPHY_TRLOOKUP4 B43_PHY_OFDM(0xBC) /* TRLookup4 */ +#define B43_LPPHY_RADAR_FIFO_STAT B43_PHY_OFDM(0xBD) /* Radar FIFO Status */ +#define B43_LPPHY_GPIO_OUTEN B43_PHY_OFDM(0xBE) /* GPIO Out enable */ +#define B43_LPPHY_GPOI_SELECT B43_PHY_OFDM(0xBF) /* GPOI Select */ +#define B43_LPPHY_GPIO_OUT B43_PHY_OFDM(0xC0) /* GPIO Out */ + + +/* Radio register access decorators. */ #define B43_LP_RADIO(radio_reg) (radio_reg) #define B43_LP_NORTH(radio_reg) B43_LP_RADIO(radio_reg) #define B43_LP_SOUTH(radio_reg) B43_LP_RADIO((radio_reg) | 0x4000) -- GitLab From 0818cb8adfedf3e5b48662056f0228576c666d9d Mon Sep 17 00:00:00 2001 From: Danny Kukawka Date: Sat, 31 Jan 2009 15:52:09 +0100 Subject: [PATCH 1493/4982] ath9k: fix led naming Fixed led device naming for the ath9k driver. Due to the documentation of the led subsystem/class the naming should be "devicename:colour:function" while not applying sections should be left blank. This should lead to e.g. "ath9k-%s::rx" instead of "ath9k-%s:rx". Signed-off-by: Danny Kukawka Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index e98f2d79af6..1c0f893e1c0 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1050,7 +1050,7 @@ static void ath_init_leds(struct ath_softc *sc) trigger = ieee80211_get_radio_led_name(sc->hw); snprintf(sc->radio_led.name, sizeof(sc->radio_led.name), - "ath9k-%s:radio", wiphy_name(sc->hw->wiphy)); + "ath9k-%s::radio", wiphy_name(sc->hw->wiphy)); ret = ath_register_led(sc, &sc->radio_led, trigger); sc->radio_led.led_type = ATH_LED_RADIO; if (ret) @@ -1058,7 +1058,7 @@ static void ath_init_leds(struct ath_softc *sc) trigger = ieee80211_get_assoc_led_name(sc->hw); snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name), - "ath9k-%s:assoc", wiphy_name(sc->hw->wiphy)); + "ath9k-%s::assoc", wiphy_name(sc->hw->wiphy)); ret = ath_register_led(sc, &sc->assoc_led, trigger); sc->assoc_led.led_type = ATH_LED_ASSOC; if (ret) @@ -1066,7 +1066,7 @@ static void ath_init_leds(struct ath_softc *sc) trigger = ieee80211_get_tx_led_name(sc->hw); snprintf(sc->tx_led.name, sizeof(sc->tx_led.name), - "ath9k-%s:tx", wiphy_name(sc->hw->wiphy)); + "ath9k-%s::tx", wiphy_name(sc->hw->wiphy)); ret = ath_register_led(sc, &sc->tx_led, trigger); sc->tx_led.led_type = ATH_LED_TX; if (ret) @@ -1074,7 +1074,7 @@ static void ath_init_leds(struct ath_softc *sc) trigger = ieee80211_get_rx_led_name(sc->hw); snprintf(sc->rx_led.name, sizeof(sc->rx_led.name), - "ath9k-%s:rx", wiphy_name(sc->hw->wiphy)); + "ath9k-%s::rx", wiphy_name(sc->hw->wiphy)); ret = ath_register_led(sc, &sc->rx_led, trigger); sc->rx_led.led_type = ATH_LED_RX; if (ret) @@ -1257,7 +1257,7 @@ static int ath_init_sw_rfkill(struct ath_softc *sc) } snprintf(sc->rf_kill.rfkill_name, sizeof(sc->rf_kill.rfkill_name), - "ath9k-%s:rfkill", wiphy_name(sc->hw->wiphy)); + "ath9k-%s::rfkill", wiphy_name(sc->hw->wiphy)); sc->rf_kill.rfkill->name = sc->rf_kill.rfkill_name; sc->rf_kill.rfkill->data = sc; sc->rf_kill.rfkill->toggle_radio = ath_sw_toggle_radio; -- GitLab From b157b5e60b2e4eefa8fb13936e0d2642ccc1d02c Mon Sep 17 00:00:00 2001 From: Danny Kukawka Date: Sat, 31 Jan 2009 15:52:16 +0100 Subject: [PATCH 1494/4982] b43legacy: fix led naming Fixed led device naming for the b43legacy driver. Due to the documentation of the led subsystem/class the naming should be "devicename:colour:function" while not applying sections should be left blank. This should lead to e.g. "b43legacy-%s::rx" instead of "b43legacy-%s:rx". Signed-off-by: Danny Kukawka Acked-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/leds.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/b43legacy/leds.c b/drivers/net/wireless/b43legacy/leds.c index cacb786d971..3ea55b18c70 100644 --- a/drivers/net/wireless/b43legacy/leds.c +++ b/drivers/net/wireless/b43legacy/leds.c @@ -146,12 +146,12 @@ static void b43legacy_map_led(struct b43legacy_wldev *dev, case B43legacy_LED_TRANSFER: case B43legacy_LED_APTRANSFER: snprintf(name, sizeof(name), - "b43legacy-%s:tx", wiphy_name(hw->wiphy)); + "b43legacy-%s::tx", wiphy_name(hw->wiphy)); b43legacy_register_led(dev, &dev->led_tx, name, ieee80211_get_tx_led_name(hw), led_index, activelow); snprintf(name, sizeof(name), - "b43legacy-%s:rx", wiphy_name(hw->wiphy)); + "b43legacy-%s::rx", wiphy_name(hw->wiphy)); b43legacy_register_led(dev, &dev->led_rx, name, ieee80211_get_rx_led_name(hw), led_index, activelow); @@ -161,7 +161,7 @@ static void b43legacy_map_led(struct b43legacy_wldev *dev, case B43legacy_LED_RADIO_B: case B43legacy_LED_MODE_BG: snprintf(name, sizeof(name), - "b43legacy-%s:radio", wiphy_name(hw->wiphy)); + "b43legacy-%s::radio", wiphy_name(hw->wiphy)); b43legacy_register_led(dev, &dev->led_radio, name, b43legacy_rfkill_led_name(dev), led_index, activelow); @@ -172,7 +172,7 @@ static void b43legacy_map_led(struct b43legacy_wldev *dev, case B43legacy_LED_WEIRD: case B43legacy_LED_ASSOC: snprintf(name, sizeof(name), - "b43legacy-%s:assoc", wiphy_name(hw->wiphy)); + "b43legacy-%s::assoc", wiphy_name(hw->wiphy)); b43legacy_register_led(dev, &dev->led_assoc, name, ieee80211_get_assoc_led_name(hw), led_index, activelow); -- GitLab From b34196d7d031a966c70ce2ede9087be56c7dd4bc Mon Sep 17 00:00:00 2001 From: Danny Kukawka Date: Sat, 31 Jan 2009 15:52:20 +0100 Subject: [PATCH 1495/4982] rt2x00: fix led naming Fixed led device naming for the rt2x00 driver. Due to the documentation of the led subsystem/class the naming should be "devicename:colour:function" while not applying sections should be left blank. This should lead to e.g. "%s::radio" instead of "%s:radio". Signed-off-by: Danny Kukawka Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00leds.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c index 9b531e0ca0c..49671fed91d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00leds.c +++ b/drivers/net/wireless/rt2x00/rt2x00leds.c @@ -134,7 +134,7 @@ void rt2x00leds_register(struct rt2x00_dev *rt2x00dev) rt2x00dev->ops->name, wiphy_name(rt2x00dev->hw->wiphy)); if (rt2x00dev->led_radio.flags & LED_INITIALIZED) { - snprintf(name, sizeof(name), "%s:radio", dev_name); + snprintf(name, sizeof(name), "%s::radio", dev_name); retval = rt2x00leds_register_led(rt2x00dev, &rt2x00dev->led_radio, @@ -144,7 +144,7 @@ void rt2x00leds_register(struct rt2x00_dev *rt2x00dev) } if (rt2x00dev->led_assoc.flags & LED_INITIALIZED) { - snprintf(name, sizeof(name), "%s:assoc", dev_name); + snprintf(name, sizeof(name), "%s::assoc", dev_name); retval = rt2x00leds_register_led(rt2x00dev, &rt2x00dev->led_assoc, @@ -154,7 +154,7 @@ void rt2x00leds_register(struct rt2x00_dev *rt2x00dev) } if (rt2x00dev->led_qual.flags & LED_INITIALIZED) { - snprintf(name, sizeof(name), "%s:quality", dev_name); + snprintf(name, sizeof(name), "%s::quality", dev_name); retval = rt2x00leds_register_led(rt2x00dev, &rt2x00dev->led_qual, -- GitLab From 3302e44dcdb8aff99769921af12b916a914b6317 Mon Sep 17 00:00:00 2001 From: Danny Kukawka Date: Sat, 31 Jan 2009 15:52:40 +0100 Subject: [PATCH 1496/4982] iwlwifi: another led naming fix Fixed led device naming for the iwlwifi (iwl-3945) driver. Due to the documentation of the led subsystem/class the naming should be "devicename:colour:function" while not applying sections should be left blank. This should lead to e.g. "iwl-%s::RX" instead of "iwl-%s:RX". Signed-off-by: Danny Kukawka Acked-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-led.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index 2e507e912da..a973ac13a1d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -316,7 +316,7 @@ int iwl3945_led_register(struct iwl_priv *priv) trigger = ieee80211_get_radio_led_name(priv->hw); snprintf(priv->led39[IWL_LED_TRG_RADIO].name, - sizeof(priv->led39[IWL_LED_TRG_RADIO].name), "iwl-%s:radio", + sizeof(priv->led39[IWL_LED_TRG_RADIO].name), "iwl-%s::radio", wiphy_name(priv->hw->wiphy)); priv->led39[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on; @@ -332,7 +332,7 @@ int iwl3945_led_register(struct iwl_priv *priv) trigger = ieee80211_get_assoc_led_name(priv->hw); snprintf(priv->led39[IWL_LED_TRG_ASSOC].name, - sizeof(priv->led39[IWL_LED_TRG_ASSOC].name), "iwl-%s:assoc", + sizeof(priv->led39[IWL_LED_TRG_ASSOC].name), "iwl-%s::assoc", wiphy_name(priv->hw->wiphy)); ret = iwl3945_led_register_led(priv, @@ -349,7 +349,7 @@ int iwl3945_led_register(struct iwl_priv *priv) trigger = ieee80211_get_rx_led_name(priv->hw); snprintf(priv->led39[IWL_LED_TRG_RX].name, - sizeof(priv->led39[IWL_LED_TRG_RX].name), "iwl-%s:RX", + sizeof(priv->led39[IWL_LED_TRG_RX].name), "iwl-%s::RX", wiphy_name(priv->hw->wiphy)); ret = iwl3945_led_register_led(priv, @@ -365,7 +365,7 @@ int iwl3945_led_register(struct iwl_priv *priv) trigger = ieee80211_get_tx_led_name(priv->hw); snprintf(priv->led39[IWL_LED_TRG_TX].name, - sizeof(priv->led39[IWL_LED_TRG_TX].name), "iwl-%s:TX", + sizeof(priv->led39[IWL_LED_TRG_TX].name), "iwl-%s::TX", wiphy_name(priv->hw->wiphy)); ret = iwl3945_led_register_led(priv, -- GitLab From 6c1bb9276c492c803611e63fa6fab8276c02ee70 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 31 Jan 2009 16:52:29 +0100 Subject: [PATCH 1497/4982] b43: Add LP-PHY baseband init for >=rev2 This adds code for the baseband init of LP-PHY >=2. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/Makefile | 1 + drivers/net/wireless/b43/phy_lp.c | 78 +++++++++++++++++++++- drivers/net/wireless/b43/phy_lp.h | 42 +++++++++++- drivers/net/wireless/b43/tables_lpphy.c | 89 +++++++++++++++++++++++++ drivers/net/wireless/b43/tables_lpphy.h | 21 ++++++ 5 files changed, 228 insertions(+), 3 deletions(-) create mode 100644 drivers/net/wireless/b43/tables_lpphy.c create mode 100644 drivers/net/wireless/b43/tables_lpphy.h diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile index 14a02b3aea5..281ef831035 100644 --- a/drivers/net/wireless/b43/Makefile +++ b/drivers/net/wireless/b43/Makefile @@ -6,6 +6,7 @@ b43-y += phy_g.o b43-y += phy_a.o b43-$(CONFIG_B43_NPHY) += phy_n.o b43-$(CONFIG_B43_PHY_LP) += phy_lp.o +b43-$(CONFIG_B43_PHY_LP) += tables_lpphy.o b43-y += sysfs.o b43-y += xmit.o b43-y += lo.o diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index ec83b8cd2f2..3c7be830858 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -3,7 +3,7 @@ Broadcom B43 wireless driver IEEE 802.11g LP-PHY driver - Copyright (c) 2008 Michael Buesch + Copyright (c) 2008-2009 Michael Buesch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,6 +25,7 @@ #include "b43.h" #include "phy_lp.h" #include "phy_common.h" +#include "tables_lpphy.h" static int b43_lpphy_op_allocate(struct b43_wldev *dev) @@ -69,7 +70,80 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) { - //TODO + struct b43_phy_lp *lpphy = dev->phy.lp; + + b43_phy_write(dev, B43_LPPHY_AFE_DAC_CTL, 0x50); + b43_phy_write(dev, B43_LPPHY_AFE_CTL, 0x8800); + b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVR, 0); + b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0); + b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_0, 0); + b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0); + b43_phy_write(dev, B43_PHY_OFDM(0xF9), 0); + b43_phy_write(dev, B43_LPPHY_TR_LOOKUP_1, 0); + b43_phy_set(dev, B43_LPPHY_ADC_COMPENSATION_CTL, 0x10); + b43_phy_maskset(dev, B43_LPPHY_OFDMSYNCTHRESH0, 0xFF00, 0x78); + b43_phy_maskset(dev, B43_LPPHY_DCOFFSETTRANSIENT, 0xF8FF, 0x200); + b43_phy_maskset(dev, B43_LPPHY_DCOFFSETTRANSIENT, 0xFF00, 0x7F); + b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xFF0F, 0x40); + b43_phy_maskset(dev, B43_LPPHY_PREAMBLECONFIRMTO, 0xFF00, 0x2); + b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x4000); + b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x2000); + b43_phy_set(dev, B43_PHY_OFDM(0x10A), 0x1); + b43_phy_maskset(dev, B43_LPPHY_CCKLMSSTEPSIZE, 0xFF01, 0x10); + b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0xFF00, 0xF4); + b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0x00FF, 0xF100);//FIXME specs are different + b43_phy_write(dev, B43_LPPHY_CLIPTHRESH, 0x48); + b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0xFF00, 0x46); + b43_phy_maskset(dev, B43_PHY_OFDM(0xE4), 0xFF00, 0x10); + b43_phy_maskset(dev, B43_LPPHY_PWR_THRESH1, 0xFFF0, 0x9); + b43_phy_mask(dev, B43_LPPHY_GAINDIRECTMISMATCH, ~0xF); + b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0x00FF, 0x5500); + b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xF81F, 0xA0); + b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xE0FF, 0x300); + b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0x00FF, 0x2A00); + b43_phy_maskset(dev, B43_LPPHY_LOWGAINDB, 0x00FF, 0x1E00); + b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0xD); + b43_phy_maskset(dev, B43_PHY_OFDM(0xFE), 0xFFE0, 0x1F); + b43_phy_maskset(dev, B43_PHY_OFDM(0xFF), 0xFFE0, 0xC); + b43_phy_maskset(dev, B43_PHY_OFDM(0x100), 0xFF00, 0x19); + b43_phy_maskset(dev, B43_PHY_OFDM(0xFF), 0x03FF, 0x3C00); + b43_phy_maskset(dev, B43_PHY_OFDM(0xFE), 0xFC1F, 0x3E0); + b43_phy_maskset(dev, B43_PHY_OFDM(0xFF), 0xFFE0, 0xC); + b43_phy_maskset(dev, B43_PHY_OFDM(0x100), 0x00FF, 0x1900); + b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x5800); + b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x12); + b43_phy_maskset(dev, B43_LPPHY_GAINMISMATCH, 0x0FFF, 0x9000); + + if (dev->phy.rev < 2) { + //FIXME this will never execute. + + //FIXME 32bit? + b43_lptab_write(dev, B43_LPTAB32(0x11, 0x14), 0); + b43_lptab_write(dev, B43_LPTAB32(0x08, 0x12), 0x40); + } else { + //FIXME 32bit? + b43_lptab_write(dev, B43_LPTAB32(0x08, 0x14), 0); + b43_lptab_write(dev, B43_LPTAB32(0x08, 0x12), 0x40); + } + + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x40); + b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xF0FF, 0xB00); + b43_phy_maskset(dev, B43_LPPHY_SYNCPEAKCNT, 0xFFF8, 0x6); + b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0x00FF, 0x9D00); + b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0xFF00, 0xA1); + } else /* 5GHz */ + b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x40); + + b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0xFF00, 0xB3); + b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0x00FF, 0xAD00); + b43_phy_maskset(dev, B43_LPPHY_INPUT_PWRDB, 0xFF00, lpphy->rx_pwr_offset); + b43_phy_set(dev, B43_LPPHY_RESET_CTL, 0x44); + b43_phy_write(dev, B43_LPPHY_RESET_CTL, 0x80); + b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_0, 0xA954); + b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_1, + 0x2000 | ((u16)lpphy->rssi_gs << 10) | + ((u16)lpphy->rssi_vc << 4) | lpphy->rssi_vf); } static void lpphy_baseband_init(struct b43_wldev *dev) diff --git a/drivers/net/wireless/b43/phy_lp.h b/drivers/net/wireless/b43/phy_lp.h index c3f92f17259..1e30a55d2f2 100644 --- a/drivers/net/wireless/b43/phy_lp.h +++ b/drivers/net/wireless/b43/phy_lp.h @@ -803,7 +803,47 @@ struct b43_phy_lp { - //TODO + /* Transmit isolation medium band */ + u8 tx_isolation_med_band; /* FIXME initial value? */ + /* Transmit isolation low band */ + u8 tx_isolation_low_band; /* FIXME initial value? */ + /* Transmit isolation high band */ + u8 tx_isolation_hi_band; /* FIXME initial value? */ + + /* Receive power offset */ + u8 rx_pwr_offset; /* FIXME initial value? */ + + /* TSSI transmit count */ + u16 tssi_tx_count; /* FIXME initial value? */ + /* TSSI index */ + u16 tssi_idx; /* FIXME initial value? */ + /* TSSI npt */ + u16 tssi_npt; /* FIXME initial value? */ + + /* Target TX frequency */ + u16 tgt_tx_freq; /* FIXME initial value? */ + + /* Transmit power index override */ + s8 tx_pwr_idx_over; /* FIXME initial value? */ + + /* RSSI vf */ + u8 rssi_vf; /* FIXME initial value? */ + /* RSSI vc */ + u8 rssi_vc; /* FIXME initial value? */ + /* RSSI gs */ + u8 rssi_gs; /* FIXME initial value? */ + + /* RC cap */ + u8 rc_cap; /* FIXME initial value? */ + /* BX arch */ + u8 bx_arch; /* FIXME initial value? */ + + /* Full calibration channel */ + u8 full_calib_chan; /* FIXME initial value? */ + + /* Transmit iqlocal best coeffs */ + bool tx_iqloc_best_coeffs_valid; + u8 tx_iqloc_best_coeffs[11]; }; diff --git a/drivers/net/wireless/b43/tables_lpphy.c b/drivers/net/wireless/b43/tables_lpphy.c new file mode 100644 index 00000000000..c9cff8b6827 --- /dev/null +++ b/drivers/net/wireless/b43/tables_lpphy.c @@ -0,0 +1,89 @@ +/* + + Broadcom B43 wireless driver + IEEE 802.11g LP-PHY and radio device data tables + + Copyright (c) 2009 Michael Buesch + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "b43.h" +#include "tables_lpphy.h" +#include "phy_common.h" +#include "phy_lp.h" + + +u32 b43_lptab_read(struct b43_wldev *dev, u32 offset) +{ + u32 type, value; + + type = offset & B43_LPTAB_TYPEMASK; + offset &= ~B43_LPTAB_TYPEMASK; + B43_WARN_ON(offset > 0xFFFF); + + switch (type) { + case B43_LPTAB_8BIT: + b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset); + value = b43_phy_read(dev, B43_LPPHY_TABLEDATALO) & 0xFF; + break; + case B43_LPTAB_16BIT: + b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset); + value = b43_phy_read(dev, B43_LPPHY_TABLEDATALO); + break; + case B43_LPTAB_32BIT: + b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset); + value = b43_phy_read(dev, B43_LPPHY_TABLEDATAHI); + value <<= 16; + value |= b43_phy_read(dev, B43_LPPHY_TABLEDATALO); + break; + default: + B43_WARN_ON(1); + value = 0; + } + + return value; +} + +void b43_lptab_write(struct b43_wldev *dev, u32 offset, u32 value) +{ + u32 type; + + type = offset & B43_LPTAB_TYPEMASK; + offset &= ~B43_LPTAB_TYPEMASK; + B43_WARN_ON(offset > 0xFFFF); + + switch (type) { + case B43_LPTAB_8BIT: + B43_WARN_ON(value & ~0xFF); + b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset); + b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value); + break; + case B43_LPTAB_16BIT: + B43_WARN_ON(value & ~0xFFFF); + b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset); + b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value); + break; + case B43_LPTAB_32BIT: + b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset); + b43_phy_write(dev, B43_LPPHY_TABLEDATAHI, value >> 16); + b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value); + break; + default: + B43_WARN_ON(1); + } +} diff --git a/drivers/net/wireless/b43/tables_lpphy.h b/drivers/net/wireless/b43/tables_lpphy.h new file mode 100644 index 00000000000..d32e7450680 --- /dev/null +++ b/drivers/net/wireless/b43/tables_lpphy.h @@ -0,0 +1,21 @@ +#ifndef B43_TABLES_LPPHY_H_ +#define B43_TABLES_LPPHY_H_ + + +#define B43_LPTAB_TYPEMASK 0xF0000000 +#define B43_LPTAB_8BIT 0x10000000 +#define B43_LPTAB_16BIT 0x20000000 +#define B43_LPTAB_32BIT 0x30000000 +#define B43_LPTAB8(table, offset) (((table) << 10) | (offset) | B43_LPTAB_8BIT) +#define B43_LPTAB16(table, offset) (((table) << 10) | (offset) | B43_LPTAB_16BIT) +#define B43_LPTAB32(table, offset) (((table) << 10) | (offset) | B43_LPTAB_32BIT) + +/* Table definitions */ +#define B43_LPTAB_TXPWR_R2PLUS B43_LPTAB32(0x07, 0) /* TX power lookup table (rev >= 2) */ +#define B43_LPTAB_TXPWR_R0_1 B43_LPTAB32(0xA0, 0) /* TX power lookup table (rev < 2) */ + +u32 b43_lptab_read(struct b43_wldev *dev, u32 offset); +void b43_lptab_write(struct b43_wldev *dev, u32 offset, u32 value); + + +#endif /* B43_TABLES_LPPHY_H_ */ -- GitLab From 24b5bcc6aef46346edd69becf62d2125c0b3208e Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 31 Jan 2009 19:34:53 +0100 Subject: [PATCH 1498/4982] b43: Add LP 2062 radio init This adds initialization code for the 2062 radio. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_lp.c | 111 ++++++++++- drivers/net/wireless/b43/phy_lp.h | 2 +- drivers/net/wireless/b43/tables_lpphy.c | 244 ++++++++++++++++++++++++ drivers/net/wireless/b43/tables_lpphy.h | 2 + 4 files changed, 355 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 3c7be830858..99cc9739ace 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -91,7 +91,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) b43_phy_set(dev, B43_PHY_OFDM(0x10A), 0x1); b43_phy_maskset(dev, B43_LPPHY_CCKLMSSTEPSIZE, 0xFF01, 0x10); b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0xFF00, 0xF4); - b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0x00FF, 0xF100);//FIXME specs are different + b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0x00FF, 0xF100); b43_phy_write(dev, B43_LPPHY_CLIPTHRESH, 0x48); b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0xFF00, 0x46); b43_phy_maskset(dev, B43_PHY_OFDM(0xE4), 0xFF00, 0x10); @@ -155,11 +155,114 @@ static void lpphy_baseband_init(struct b43_wldev *dev) lpphy_baseband_rev0_1_init(dev); } -static void lpphy_radio_init(struct b43_wldev *dev) +struct b2062_freqdata { + u16 freq; + u8 data[6]; +}; + +/* Initialize the 2062 radio. */ +static void lpphy_2062_init(struct b43_wldev *dev) +{ + u32 crystalfreq, pdiv, tmp, ref; + unsigned int i; + const struct b2062_freqdata *fd = NULL; + + static const struct b2062_freqdata freqdata_tab[] = { + { .freq = 12000, .data[0] = 6, .data[1] = 6, .data[2] = 6, + .data[3] = 6, .data[4] = 10, .data[5] = 6, }, + { .freq = 13000, .data[0] = 4, .data[1] = 4, .data[2] = 4, + .data[3] = 4, .data[4] = 11, .data[5] = 7, }, + { .freq = 14400, .data[0] = 3, .data[1] = 3, .data[2] = 3, + .data[3] = 3, .data[4] = 12, .data[5] = 7, }, + { .freq = 16200, .data[0] = 3, .data[1] = 3, .data[2] = 3, + .data[3] = 3, .data[4] = 13, .data[5] = 8, }, + { .freq = 18000, .data[0] = 2, .data[1] = 2, .data[2] = 2, + .data[3] = 2, .data[4] = 14, .data[5] = 8, }, + { .freq = 19200, .data[0] = 1, .data[1] = 1, .data[2] = 1, + .data[3] = 1, .data[4] = 14, .data[5] = 9, }, + }; + + b2062_upload_init_table(dev); + + b43_radio_write(dev, B2062_N_TX_CTL3, 0); + b43_radio_write(dev, B2062_N_TX_CTL4, 0); + b43_radio_write(dev, B2062_N_TX_CTL5, 0); + b43_radio_write(dev, B2062_N_PDN_CTL0, 0x40); + b43_radio_write(dev, B2062_N_PDN_CTL0, 0); + b43_radio_write(dev, B2062_N_CALIB_TS, 0x10); + b43_radio_write(dev, B2062_N_CALIB_TS, 0); + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + b43_radio_set(dev, B2062_N_TSSI_CTL0, 0x1); + else + b43_radio_mask(dev, B2062_N_TSSI_CTL0, ~0x1); + + crystalfreq = 0;//FIXME + + if (crystalfreq >= 30000000) { + pdiv = 1; + b43_radio_mask(dev, B2062_S_RFPLL_CTL1, 0xFFFB); + } else { + pdiv = 2; + b43_radio_set(dev, B2062_S_RFPLL_CTL1, 0x4); + } + + tmp = (800000000 * pdiv + crystalfreq) / (32000000 * pdiv); + tmp = (tmp - 1) & 0xFF; + b43_radio_write(dev, B2062_S_RFPLL_CTL18, tmp); + + tmp = (2 * crystalfreq + 1000000 * pdiv) / (2000000 * pdiv); + tmp = ((tmp & 0xFF) - 1) & 0xFFFF; + b43_radio_write(dev, B2062_S_RFPLL_CTL19, tmp); + + ref = (1000 * pdiv + 2 * crystalfreq) / (2000 * pdiv); + ref &= 0xFFFF; + for (i = 0; i < ARRAY_SIZE(freqdata_tab); i++) { + if (ref < freqdata_tab[i].freq) { + fd = &freqdata_tab[i]; + break; + } + } + if (B43_WARN_ON(!fd)) + return; + + b43_radio_write(dev, B2062_S_RFPLL_CTL8, + ((u16)(fd->data[1]) << 4) | fd->data[0]); + b43_radio_write(dev, B2062_S_RFPLL_CTL9, + ((u16)(fd->data[3]) << 4) | fd->data[2]);//FIXME specs are different + b43_radio_write(dev, B2062_S_RFPLL_CTL10, fd->data[4]); + b43_radio_write(dev, B2062_S_RFPLL_CTL11, fd->data[5]); +} + +/* Initialize the 2063 radio. */ +static void lpphy_2063_init(struct b43_wldev *dev) { //TODO } +static void lpphy_sync_stx(struct b43_wldev *dev) +{ + //TODO +} + +static void lpphy_radio_init(struct b43_wldev *dev) +{ + /* The radio is attached through the 4wire bus. */ + b43_phy_set(dev, B43_LPPHY_FOURWIRE_CTL, 0x2); + udelay(1); + b43_phy_mask(dev, B43_LPPHY_FOURWIRE_CTL, 0xFFFD); + udelay(1); + + if (dev->phy.rev < 2) { + lpphy_2062_init(dev); + } else { + lpphy_2063_init(dev); + lpphy_sync_stx(dev); + b43_phy_write(dev, B43_PHY_OFDM(0xF0), 0x5F80); + b43_phy_write(dev, B43_PHY_OFDM(0xF1), 0); + //TODO Do something on the backplane + } +} + static int b43_lpphy_op_init(struct b43_wldev *dev) { /* TODO: band SPROM */ @@ -222,7 +325,9 @@ static int b43_lpphy_op_switch_channel(struct b43_wldev *dev, static unsigned int b43_lpphy_op_get_default_chan(struct b43_wldev *dev) { - return 1; /* Default to channel 1 */ + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + return 1; + return 36; } static void b43_lpphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna) diff --git a/drivers/net/wireless/b43/phy_lp.h b/drivers/net/wireless/b43/phy_lp.h index 1e30a55d2f2..80703c58102 100644 --- a/drivers/net/wireless/b43/phy_lp.h +++ b/drivers/net/wireless/b43/phy_lp.h @@ -273,7 +273,7 @@ #define B43_LPPHY_TRLOOKUP4 B43_PHY_OFDM(0xBC) /* TRLookup4 */ #define B43_LPPHY_RADAR_FIFO_STAT B43_PHY_OFDM(0xBD) /* Radar FIFO Status */ #define B43_LPPHY_GPIO_OUTEN B43_PHY_OFDM(0xBE) /* GPIO Out enable */ -#define B43_LPPHY_GPOI_SELECT B43_PHY_OFDM(0xBF) /* GPOI Select */ +#define B43_LPPHY_GPIO_SELECT B43_PHY_OFDM(0xBF) /* GPIO Select */ #define B43_LPPHY_GPIO_OUT B43_PHY_OFDM(0xC0) /* GPIO Out */ diff --git a/drivers/net/wireless/b43/tables_lpphy.c b/drivers/net/wireless/b43/tables_lpphy.c index c9cff8b6827..18f6e325676 100644 --- a/drivers/net/wireless/b43/tables_lpphy.c +++ b/drivers/net/wireless/b43/tables_lpphy.c @@ -28,6 +28,250 @@ #include "phy_lp.h" +/* Entry of the 2062 radio init table */ +struct b2062_init_tab_entry { + u16 offset; + u16 value_a; + u16 value_g; + u8 flags; +}; +#define B2062_FLAG_A 0x01 /* Flag: Init in A mode */ +#define B2062_FLAG_G 0x02 /* Flag: Init in G mode */ + +static const struct b2062_init_tab_entry b2062_init_tab[] = { + /* { .offset = B2062_N_COMM1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = 0x0001, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_COMM2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_COMM3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + { .offset = B2062_N_COMM4, .value_a = 0x0001, .value_g = 0x0000, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + /* { .offset = B2062_N_COMM5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_COMM6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_COMM7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_COMM8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_COMM9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_COMM10, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_COMM11, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_COMM12, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_COMM13, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_COMM14, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_COMM15, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_PDN_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + { .offset = B2062_N_PDN_CTL1, .value_a = 0x0000, .value_g = 0x00CA, .flags = B2062_FLAG_G, }, + /* { .offset = B2062_N_PDN_CTL2, .value_a = 0x0018, .value_g = 0x0018, .flags = 0, }, */ + { .offset = B2062_N_PDN_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + { .offset = B2062_N_PDN_CTL4, .value_a = 0x0015, .value_g = 0x002A, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + /* { .offset = B2062_N_GEN_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_IQ_CALIB, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */ + { .offset = B2062_N_LGENC, .value_a = 0x00DB, .value_g = 0x00FF, .flags = B2062_FLAG_A, }, + /* { .offset = B2062_N_LGENA_LPF, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */ + /* { .offset = B2062_N_LGENA_BIAS0, .value_a = 0x0041, .value_g = 0x0041, .flags = 0, }, */ + /* { .offset = B2062_N_LGNEA_BIAS1, .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */ + /* { .offset = B2062_N_LGENA_CTL0, .value_a = 0x0032, .value_g = 0x0032, .flags = 0, }, */ + /* { .offset = B2062_N_LGENA_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_LGENA_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + { .offset = B2062_N_LGENA_TUNE0, .value_a = 0x00DD, .value_g = 0x0000, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + /* { .offset = B2062_N_LGENA_TUNE1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + { .offset = B2062_N_LGENA_TUNE2, .value_a = 0x00DD, .value_g = 0x0000, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + { .offset = B2062_N_LGENA_TUNE3, .value_a = 0x0077, .value_g = 0x00B5, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + { .offset = B2062_N_LGENA_CTL3, .value_a = 0x0000, .value_g = 0x00FF, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + /* { .offset = B2062_N_LGENA_CTL4, .value_a = 0x001F, .value_g = 0x001F, .flags = 0, }, */ + /* { .offset = B2062_N_LGENA_CTL5, .value_a = 0x0032, .value_g = 0x0032, .flags = 0, }, */ + /* { .offset = B2062_N_LGENA_CTL6, .value_a = 0x0032, .value_g = 0x0032, .flags = 0, }, */ + { .offset = B2062_N_LGENA_CTL7, .value_a = 0x0033, .value_g = 0x0033, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + /* { .offset = B2062_N_RXA_CTL0, .value_a = 0x0009, .value_g = 0x0009, .flags = 0, }, */ + { .offset = B2062_N_RXA_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = B2062_FLAG_G, }, + /* { .offset = B2062_N_RXA_CTL2, .value_a = 0x0018, .value_g = 0x0018, .flags = 0, }, */ + /* { .offset = B2062_N_RXA_CTL3, .value_a = 0x0027, .value_g = 0x0027, .flags = 0, }, */ + /* { .offset = B2062_N_RXA_CTL4, .value_a = 0x0028, .value_g = 0x0028, .flags = 0, }, */ + /* { .offset = B2062_N_RXA_CTL5, .value_a = 0x0007, .value_g = 0x0007, .flags = 0, }, */ + /* { .offset = B2062_N_RXA_CTL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_RXA_CTL7, .value_a = 0x0008, .value_g = 0x0008, .flags = 0, }, */ + { .offset = B2062_N_RXBB_CTL0, .value_a = 0x0082, .value_g = 0x0080, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + /* { .offset = B2062_N_RXBB_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_RXBB_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_RXBB_GAIN0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + { .offset = B2062_N_RXBB_GAIN1, .value_a = 0x0004, .value_g = 0x0004, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + { .offset = B2062_N_RXBB_GAIN2, .value_a = 0x0000, .value_g = 0x0000, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + /* { .offset = B2062_N_RXBB_GAIN3, .value_a = 0x0011, .value_g = 0x0011, .flags = 0, }, */ + /* { .offset = B2062_N_RXBB_RSSI0, .value_a = 0x0043, .value_g = 0x0043, .flags = 0, }, */ + /* { .offset = B2062_N_RXBB_RSSI1, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */ + /* { .offset = B2062_N_RXBB_CALIB0, .value_a = 0x0010, .value_g = 0x0010, .flags = 0, }, */ + /* { .offset = B2062_N_RXBB_CALIB1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_RXBB_CALIB2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_RXBB_BIAS0, .value_a = 0x0006, .value_g = 0x0006, .flags = 0, }, */ + /* { .offset = B2062_N_RXBB_BIAS1, .value_a = 0x002A, .value_g = 0x002A, .flags = 0, }, */ + /* { .offset = B2062_N_RXBB_BIAS2, .value_a = 0x00AA, .value_g = 0x00AA, .flags = 0, }, */ + /* { .offset = B2062_N_RXBB_BIAS3, .value_a = 0x0021, .value_g = 0x0021, .flags = 0, }, */ + /* { .offset = B2062_N_RXBB_BIAS4, .value_a = 0x00AA, .value_g = 0x00AA, .flags = 0, }, */ + /* { .offset = B2062_N_RXBB_BIAS5, .value_a = 0x0022, .value_g = 0x0022, .flags = 0, }, */ + /* { .offset = B2062_N_RXBB_RSSI2, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */ + /* { .offset = B2062_N_RXBB_RSSI3, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ + /* { .offset = B2062_N_RXBB_RSSI4, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */ + /* { .offset = B2062_N_RXBB_RSSI5, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ + /* { .offset = B2062_N_TX_CTL0, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */ + /* { .offset = B2062_N_TX_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_TX_CTL2, .value_a = 0x0084, .value_g = 0x0084, .flags = 0, }, */ + /* { .offset = B2062_N_TX_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + { .offset = B2062_N_TX_CTL4, .value_a = 0x0003, .value_g = 0x0003, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + { .offset = B2062_N_TX_CTL5, .value_a = 0x0002, .value_g = 0x0002, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + /* { .offset = B2062_N_TX_CTL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_TX_CTL7, .value_a = 0x0058, .value_g = 0x0058, .flags = 0, }, */ + /* { .offset = B2062_N_TX_CTL8, .value_a = 0x0082, .value_g = 0x0082, .flags = 0, }, */ + /* { .offset = B2062_N_TX_CTL9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_TX_CTL_A, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_TX_GC2G, .value_a = 0x00FF, .value_g = 0x00FF, .flags = 0, }, */ + /* { .offset = B2062_N_TX_GC5G, .value_a = 0x00FF, .value_g = 0x00FF, .flags = 0, }, */ + { .offset = B2062_N_TX_TUNE, .value_a = 0x0088, .value_g = 0x001B, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + /* { .offset = B2062_N_TX_PAD, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */ + /* { .offset = B2062_N_TX_PGA, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */ + /* { .offset = B2062_N_TX_PADAUX, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */ + /* { .offset = B2062_N_TX_PGAAUX, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */ + /* { .offset = B2062_N_TSSI_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_TSSI_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_TSSI_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_IQ_CALIB_CTL0, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */ + /* { .offset = B2062_N_IQ_CALIB_CTL1, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ + /* { .offset = B2062_N_IQ_CALIB_CTL2, .value_a = 0x0032, .value_g = 0x0032, .flags = 0, }, */ + /* { .offset = B2062_N_CALIB_TS, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_CALIB_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_CALIB_CTL1, .value_a = 0x0015, .value_g = 0x0015, .flags = 0, }, */ + /* { .offset = B2062_N_CALIB_CTL2, .value_a = 0x000F, .value_g = 0x000F, .flags = 0, }, */ + /* { .offset = B2062_N_CALIB_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_CALIB_CTL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_CALIB_DBG0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_CALIB_DBG1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_CALIB_DBG2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_CALIB_DBG3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_PSENSE_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_PSENSE_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_PSENSE_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_N_TEST_BUF0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_COMM1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_RADIO_ID_CODE, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_COMM2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_COMM3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + { .offset = B2062_S_COMM4, .value_a = 0x0001, .value_g = 0x0000, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + /* { .offset = B2062_S_COMM5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_COMM6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_COMM7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_COMM8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_COMM9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_COMM10, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_COMM11, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_COMM12, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_COMM13, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_COMM14, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_COMM15, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + { .offset = B2062_S_PDS_CTL0, .value_a = 0x00FF, .value_g = 0x00FF, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + /* { .offset = B2062_S_PDS_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_PDS_CTL2, .value_a = 0x008E, .value_g = 0x008E, .flags = 0, }, */ + /* { .offset = B2062_S_PDS_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_BG_CTL0, .value_a = 0x0006, .value_g = 0x0006, .flags = 0, }, */ + /* { .offset = B2062_S_BG_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_BG_CTL2, .value_a = 0x0011, .value_g = 0x0011, .flags = 0, }, */ + { .offset = B2062_S_LGENG_CTL0, .value_a = 0x00F8, .value_g = 0x00D8, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + { .offset = B2062_S_LGENG_CTL1, .value_a = 0x003C, .value_g = 0x0024, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + /* { .offset = B2062_S_LGENG_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_LGENG_CTL3, .value_a = 0x0041, .value_g = 0x0041, .flags = 0, }, */ + /* { .offset = B2062_S_LGENG_CTL4, .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */ + /* { .offset = B2062_S_LGENG_CTL5, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */ + /* { .offset = B2062_S_LGENG_CTL6, .value_a = 0x0022, .value_g = 0x0022, .flags = 0, }, */ + /* { .offset = B2062_S_LGENG_CTL7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + { .offset = B2062_S_LGENG_CTL8, .value_a = 0x0088, .value_g = 0x0080, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + /* { .offset = B2062_S_LGENG_CTL9, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */ + { .offset = B2062_S_LGENG_CTL10, .value_a = 0x0088, .value_g = 0x0080, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + /* { .offset = B2062_S_LGENG_CTL11, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_REFPLL_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_REFPLL_CTL1, .value_a = 0x0007, .value_g = 0x0007, .flags = 0, }, */ + /* { .offset = B2062_S_REFPLL_CTL2, .value_a = 0x00AF, .value_g = 0x00AF, .flags = 0, }, */ + /* { .offset = B2062_S_REFPLL_CTL3, .value_a = 0x0012, .value_g = 0x0012, .flags = 0, }, */ + /* { .offset = B2062_S_REFPLL_CTL4, .value_a = 0x000B, .value_g = 0x000B, .flags = 0, }, */ + /* { .offset = B2062_S_REFPLL_CTL5, .value_a = 0x005F, .value_g = 0x005F, .flags = 0, }, */ + /* { .offset = B2062_S_REFPLL_CTL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_REFPLL_CTL7, .value_a = 0x0040, .value_g = 0x0040, .flags = 0, }, */ + /* { .offset = B2062_S_REFPLL_CTL8, .value_a = 0x0052, .value_g = 0x0052, .flags = 0, }, */ + /* { .offset = B2062_S_REFPLL_CTL9, .value_a = 0x0026, .value_g = 0x0026, .flags = 0, }, */ + /* { .offset = B2062_S_REFPLL_CTL10, .value_a = 0x0003, .value_g = 0x0003, .flags = 0, }, */ + /* { .offset = B2062_S_REFPLL_CTL11, .value_a = 0x0036, .value_g = 0x0036, .flags = 0, }, */ + /* { .offset = B2062_S_REFPLL_CTL12, .value_a = 0x0057, .value_g = 0x0057, .flags = 0, }, */ + /* { .offset = B2062_S_REFPLL_CTL13, .value_a = 0x0011, .value_g = 0x0011, .flags = 0, }, */ + /* { .offset = B2062_S_REFPLL_CTL14, .value_a = 0x0075, .value_g = 0x0075, .flags = 0, }, */ + /* { .offset = B2062_S_REFPLL_CTL15, .value_a = 0x00B4, .value_g = 0x00B4, .flags = 0, }, */ + /* { .offset = B2062_S_REFPLL_CTL16, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + { .offset = B2062_S_RFPLL_CTL0, .value_a = 0x0098, .value_g = 0x0098, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + { .offset = B2062_S_RFPLL_CTL1, .value_a = 0x0010, .value_g = 0x0010, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + /* { .offset = B2062_S_RFPLL_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_RFPLL_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_RFPLL_CTL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + { .offset = B2062_S_RFPLL_CTL5, .value_a = 0x0043, .value_g = 0x0043, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + { .offset = B2062_S_RFPLL_CTL6, .value_a = 0x0047, .value_g = 0x0047, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + { .offset = B2062_S_RFPLL_CTL7, .value_a = 0x000C, .value_g = 0x000C, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + { .offset = B2062_S_RFPLL_CTL8, .value_a = 0x0011, .value_g = 0x0011, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + { .offset = B2062_S_RFPLL_CTL9, .value_a = 0x0011, .value_g = 0x0011, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + { .offset = B2062_S_RFPLL_CTL10, .value_a = 0x000E, .value_g = 0x000E, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + { .offset = B2062_S_RFPLL_CTL11, .value_a = 0x0008, .value_g = 0x0008, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + { .offset = B2062_S_RFPLL_CTL12, .value_a = 0x0033, .value_g = 0x0033, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + { .offset = B2062_S_RFPLL_CTL13, .value_a = 0x000A, .value_g = 0x000A, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + { .offset = B2062_S_RFPLL_CTL14, .value_a = 0x0006, .value_g = 0x0006, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + /* { .offset = B2062_S_RFPLL_CTL15, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_RFPLL_CTL16, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_RFPLL_CTL17, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + { .offset = B2062_S_RFPLL_CTL18, .value_a = 0x003E, .value_g = 0x003E, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + { .offset = B2062_S_RFPLL_CTL19, .value_a = 0x0013, .value_g = 0x0013, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + /* { .offset = B2062_S_RFPLL_CTL20, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + { .offset = B2062_S_RFPLL_CTL21, .value_a = 0x0062, .value_g = 0x0062, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + { .offset = B2062_S_RFPLL_CTL22, .value_a = 0x0007, .value_g = 0x0007, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + { .offset = B2062_S_RFPLL_CTL23, .value_a = 0x0016, .value_g = 0x0016, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + { .offset = B2062_S_RFPLL_CTL24, .value_a = 0x005C, .value_g = 0x005C, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + { .offset = B2062_S_RFPLL_CTL25, .value_a = 0x0095, .value_g = 0x0095, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + /* { .offset = B2062_S_RFPLL_CTL26, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_RFPLL_CTL27, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_RFPLL_CTL28, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_RFPLL_CTL29, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + { .offset = B2062_S_RFPLL_CTL30, .value_a = 0x00A0, .value_g = 0x00A0, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + { .offset = B2062_S_RFPLL_CTL31, .value_a = 0x0004, .value_g = 0x0004, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + /* { .offset = B2062_S_RFPLL_CTL32, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + { .offset = B2062_S_RFPLL_CTL33, .value_a = 0x00CC, .value_g = 0x00CC, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + { .offset = B2062_S_RFPLL_CTL34, .value_a = 0x0007, .value_g = 0x0007, .flags = B2062_FLAG_A | B2062_FLAG_G, }, + /* { .offset = B2062_S_RXG_CNT0, .value_a = 0x0010, .value_g = 0x0010, .flags = 0, }, */ + /* { .offset = B2062_S_RXG_CNT1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_RXG_CNT2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_RXG_CNT3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_RXG_CNT4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_RXG_CNT5, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ + /* { .offset = B2062_S_RXG_CNT6, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ + /* { .offset = B2062_S_RXG_CNT7, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */ + { .offset = B2062_S_RXG_CNT8, .value_a = 0x000F, .value_g = 0x000F, .flags = B2062_FLAG_A, }, + /* { .offset = B2062_S_RXG_CNT9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_RXG_CNT10, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ + /* { .offset = B2062_S_RXG_CNT11, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */ + /* { .offset = B2062_S_RXG_CNT12, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ + /* { .offset = B2062_S_RXG_CNT13, .value_a = 0x0044, .value_g = 0x0044, .flags = 0, }, */ + /* { .offset = B2062_S_RXG_CNT14, .value_a = 0x00A0, .value_g = 0x00A0, .flags = 0, }, */ + /* { .offset = B2062_S_RXG_CNT15, .value_a = 0x0004, .value_g = 0x0004, .flags = 0, }, */ + /* { .offset = B2062_S_RXG_CNT16, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ + /* { .offset = B2062_S_RXG_CNT17, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ +}; + +void b2062_upload_init_table(struct b43_wldev *dev) +{ + const struct b2062_init_tab_entry *e; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(b2062_init_tab); i++) { + e = &b2062_init_tab[i]; + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (!(e->flags & B2062_FLAG_G)) + continue; + b43_radio_write(dev, e->offset, e->value_g); + } else { + if (!(e->flags & B2062_FLAG_A)) + continue; + b43_radio_write(dev, e->offset, e->value_a); + } + } +} + u32 b43_lptab_read(struct b43_wldev *dev, u32 offset) { u32 type, value; diff --git a/drivers/net/wireless/b43/tables_lpphy.h b/drivers/net/wireless/b43/tables_lpphy.h index d32e7450680..03ea2ff5d13 100644 --- a/drivers/net/wireless/b43/tables_lpphy.h +++ b/drivers/net/wireless/b43/tables_lpphy.h @@ -17,5 +17,7 @@ u32 b43_lptab_read(struct b43_wldev *dev, u32 offset); void b43_lptab_write(struct b43_wldev *dev, u32 offset, u32 value); +void b2062_upload_init_table(struct b43_wldev *dev); + #endif /* B43_TABLES_LPPHY_H_ */ -- GitLab From de9f97efb2ea2a32a610932d881e4d3653e0f932 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 2 Feb 2009 20:35:05 -0800 Subject: [PATCH 1499/4982] ath9k: fix reg_notifier() flags used upon a country IE The nl80211 rule flags were being used. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/regd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath9k/regd.c b/drivers/net/wireless/ath9k/regd.c index dfcc3b5274c..fe08a4fdf77 100644 --- a/drivers/net/wireless/ath9k/regd.c +++ b/drivers/net/wireless/ath9k/regd.c @@ -192,11 +192,11 @@ static void ath9k_reg_apply_5ghz_beaconing_flags(struct wiphy *wiphy, * it by applying our static world regdomain by default during * probe */ if (!(reg_rule->flags & NL80211_RRF_NO_IBSS)) - ch->flags &= ~NL80211_RRF_NO_IBSS; + ch->flags &= ~IEEE80211_CHAN_NO_IBSS; if (!ath9k_is_radar_freq(ch->center_freq)) continue; if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) - ch->flags &= ~NL80211_RRF_PASSIVE_SCAN; + ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; } } -- GitLab From d43e87868f67c5b52defd8d82bc3f54347ed2408 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 3 Feb 2009 10:09:49 +0530 Subject: [PATCH 1500/4982] mac80211: Remove bss information of the current AP when it goes out of range There is no point having the bss information of currently associated AP when the AP is detected to be out of range. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 73808780f53..57967d32e5f 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1042,6 +1042,7 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct sta_info *sta; int disassoc; + bool remove_bss = false; /* TODO: start monitoring current AP signal quality and number of * missed beacons. Scan other channels every now and then and search @@ -1067,6 +1068,7 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, "range\n", sdata->dev->name, ifsta->bssid); disassoc = 1; + remove_bss = true; } else ieee80211_send_probe_req(sdata, ifsta->bssid, ifsta->ssid, @@ -1086,12 +1088,24 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, rcu_read_unlock(); - if (disassoc) + if (disassoc) { ieee80211_set_disassoc(sdata, ifsta, true, true, WLAN_REASON_PREV_AUTH_NOT_VALID); - else + if (remove_bss) { + struct ieee80211_bss *bss; + + bss = ieee80211_rx_bss_get(local, ifsta->bssid, + local->hw.conf.channel->center_freq, + ifsta->ssid, ifsta->ssid_len); + if (bss) { + atomic_dec(&bss->users); + ieee80211_rx_bss_put(local, bss); + } + } + } else { mod_timer(&ifsta->timer, jiffies + IEEE80211_MONITORING_INTERVAL); + } } -- GitLab From 0c2bec96945ccfc4a58a88d73531e392972ba6c5 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Tue, 3 Feb 2009 09:04:20 +0200 Subject: [PATCH 1501/4982] libertas: if_spi: add ability to call board specific setup/teardown methods In certain cases it is required to perform board specific actions before activating libertas G-SPI interface. These actions may include power up of the chip, GPIOs setup, proper pin-strapping and SPI controller config. This patch adds ability to call board specific setup/teardown methods Signed-off-by: Mike Rapoport Acked-by: Andrey Yurovsky Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_spi.c | 15 +++++++++++++++ include/linux/spi/libertas_spi.h | 7 +++++++ 2 files changed, 22 insertions(+) diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 7c02ea314fd..07311e71af9 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c @@ -42,6 +42,7 @@ struct if_spi_packet { struct if_spi_card { struct spi_device *spi; struct lbs_private *priv; + struct libertas_spi_platform_data *pdata; char helper_fw_name[FIRMWARE_NAME_MAX]; char main_fw_name[FIRMWARE_NAME_MAX]; @@ -1022,6 +1023,17 @@ static int __devinit if_spi_probe(struct spi_device *spi) lbs_deb_enter(LBS_DEB_SPI); + if (!pdata) { + err = -EINVAL; + goto out; + } + + if (pdata->setup) { + err = pdata->setup(spi); + if (err) + goto out; + } + /* Allocate card structure to represent this specific device */ card = kzalloc(sizeof(struct if_spi_card), GFP_KERNEL); if (!card) { @@ -1029,6 +1041,7 @@ static int __devinit if_spi_probe(struct spi_device *spi) goto out; } spi_set_drvdata(spi, card); + card->pdata = pdata; card->spi = spi; card->gpio_cs = pdata->gpio_cs; card->prev_xfer_time = jiffies; @@ -1158,6 +1171,8 @@ static int __devexit libertas_spi_remove(struct spi_device *spi) if_spi_terminate_spi_thread(card); lbs_remove_card(priv); /* will call free_netdev */ gpio_free(card->gpio_cs); + if (card->pdata->teardown) + card->pdata->teardown(spi); free_if_spi_card(card); lbs_deb_leave(LBS_DEB_SPI); return 0; diff --git a/include/linux/spi/libertas_spi.h b/include/linux/spi/libertas_spi.h index ada71b4f378..79506f5f9e6 100644 --- a/include/linux/spi/libertas_spi.h +++ b/include/linux/spi/libertas_spi.h @@ -10,6 +10,9 @@ */ #ifndef _LIBERTAS_SPI_H_ #define _LIBERTAS_SPI_H_ + +struct spi_device; + struct libertas_spi_platform_data { /* There are two ways to read data from the WLAN module's SPI * interface. Setting 0 or 1 here controls which one is used. @@ -21,5 +24,9 @@ struct libertas_spi_platform_data { /* GPIO number to use as chip select */ u16 gpio_cs; + + /* Board specific setup/teardown */ + int (*setup)(struct spi_device *spi); + int (*teardown)(struct spi_device *spi); }; #endif -- GitLab From baf62eecfa75a26682efdfed0d74256992a47e6b Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 3 Feb 2009 17:15:57 +0100 Subject: [PATCH 1502/4982] libertas: pos[4] tested twice, 2nd should be pos[5] pos[4] can't be both 0x43 and 0x04, 2nd should be pos[5] Signed-off-by: Roel Kluin Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 57f6c12cda2..00a57ed78af 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -692,7 +692,7 @@ static int lbs_process_bss(struct bss_descriptor *bss, bss->wpa_ie_len); } else if (pos[1] >= MARVELL_MESH_IE_LENGTH && pos[2] == 0x00 && pos[3] == 0x50 && - pos[4] == 0x43 && pos[4] == 0x04) { + pos[4] == 0x43 && pos[5] == 0x04) { lbs_deb_scan("got mesh IE\n"); bss->mesh = 1; } else { -- GitLab From c9703146158c0415a60799570397e488bc982af5 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 3 Feb 2009 19:23:18 +0100 Subject: [PATCH 1503/4982] ssb: Add PMU support This adds support for the SSB PMU. A PMU is found on Low-Power devices. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/ssb/Makefile | 1 + drivers/ssb/driver_chipcommon.c | 14 +- drivers/ssb/driver_chipcommon_pmu.c | 508 ++++++++++++++++++++++ include/linux/ssb/ssb_driver_chipcommon.h | 224 ++++++++++ 4 files changed, 734 insertions(+), 13 deletions(-) create mode 100644 drivers/ssb/driver_chipcommon_pmu.c diff --git a/drivers/ssb/Makefile b/drivers/ssb/Makefile index 6f255e9c5af..cfbb74f2982 100644 --- a/drivers/ssb/Makefile +++ b/drivers/ssb/Makefile @@ -9,6 +9,7 @@ ssb-$(CONFIG_SSB_PCMCIAHOST) += pcmcia.o # built-in drivers ssb-y += driver_chipcommon.o +ssb-y += driver_chipcommon_pmu.o ssb-$(CONFIG_SSB_DRIVER_MIPS) += driver_mipscore.o ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c index 571f4fd5523..9681536163c 100644 --- a/drivers/ssb/driver_chipcommon.c +++ b/drivers/ssb/driver_chipcommon.c @@ -26,19 +26,6 @@ enum ssb_clksrc { }; -static inline u32 chipco_read32(struct ssb_chipcommon *cc, - u16 offset) -{ - return ssb_read32(cc->dev, offset); -} - -static inline void chipco_write32(struct ssb_chipcommon *cc, - u16 offset, - u32 value) -{ - ssb_write32(cc->dev, offset, value); -} - static inline u32 chipco_write32_masked(struct ssb_chipcommon *cc, u16 offset, u32 mask, u32 value) { @@ -246,6 +233,7 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc) { if (!cc->dev) return; /* We don't have a ChipCommon */ + ssb_pmu_init(cc); chipco_powercontrol_init(cc); ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST); calc_fast_powerup_delay(cc); diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c new file mode 100644 index 00000000000..4aaddeec55a --- /dev/null +++ b/drivers/ssb/driver_chipcommon_pmu.c @@ -0,0 +1,508 @@ +/* + * Sonics Silicon Backplane + * Broadcom ChipCommon Power Management Unit driver + * + * Copyright 2009, Michael Buesch + * Copyright 2007, Broadcom Corporation + * + * Licensed under the GNU/GPL. See COPYING for details. + */ + +#include +#include +#include +#include + +#include "ssb_private.h" + +static u32 ssb_chipco_pll_read(struct ssb_chipcommon *cc, u32 offset) +{ + chipco_write32(cc, SSB_CHIPCO_PLLCTL_ADDR, offset); + return chipco_read32(cc, SSB_CHIPCO_PLLCTL_DATA); +} + +static void ssb_chipco_pll_write(struct ssb_chipcommon *cc, + u32 offset, u32 value) +{ + chipco_write32(cc, SSB_CHIPCO_PLLCTL_ADDR, offset); + chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, value); +} + +struct pmu0_plltab_entry { + u16 freq; /* Crystal frequency in kHz.*/ + u8 xf; /* Crystal frequency value for PMU control */ + u8 wb_int; + u32 wb_frac; +}; + +static const struct pmu0_plltab_entry pmu0_plltab[] = { + { .freq = 12000, .xf = 1, .wb_int = 73, .wb_frac = 349525, }, + { .freq = 13000, .xf = 2, .wb_int = 67, .wb_frac = 725937, }, + { .freq = 14400, .xf = 3, .wb_int = 61, .wb_frac = 116508, }, + { .freq = 15360, .xf = 4, .wb_int = 57, .wb_frac = 305834, }, + { .freq = 16200, .xf = 5, .wb_int = 54, .wb_frac = 336579, }, + { .freq = 16800, .xf = 6, .wb_int = 52, .wb_frac = 399457, }, + { .freq = 19200, .xf = 7, .wb_int = 45, .wb_frac = 873813, }, + { .freq = 19800, .xf = 8, .wb_int = 44, .wb_frac = 466033, }, + { .freq = 20000, .xf = 9, .wb_int = 44, .wb_frac = 0, }, + { .freq = 25000, .xf = 10, .wb_int = 70, .wb_frac = 419430, }, + { .freq = 26000, .xf = 11, .wb_int = 67, .wb_frac = 725937, }, + { .freq = 30000, .xf = 12, .wb_int = 58, .wb_frac = 699050, }, + { .freq = 38400, .xf = 13, .wb_int = 45, .wb_frac = 873813, }, + { .freq = 40000, .xf = 14, .wb_int = 45, .wb_frac = 0, }, +}; +#define SSB_PMU0_DEFAULT_XTALFREQ 20000 + +static const struct pmu0_plltab_entry * pmu0_plltab_find_entry(u32 crystalfreq) +{ + const struct pmu0_plltab_entry *e; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(pmu0_plltab); i++) { + e = &pmu0_plltab[i]; + if (e->freq == crystalfreq) + return e; + } + + return NULL; +} + +/* Tune the PLL to the crystal speed. crystalfreq is in kHz. */ +static void ssb_pmu0_pllinit_r0(struct ssb_chipcommon *cc, + u32 crystalfreq) +{ + struct ssb_bus *bus = cc->dev->bus; + const struct pmu0_plltab_entry *e = NULL; + u32 pmuctl, tmp, pllctl; + unsigned int i; + + if ((bus->chip_id == 0x5354) && !crystalfreq) { + /* The 5354 crystal freq is 25MHz */ + crystalfreq = 25000; + } + if (crystalfreq) + e = pmu0_plltab_find_entry(crystalfreq); + if (!e) + e = pmu0_plltab_find_entry(SSB_PMU0_DEFAULT_XTALFREQ); + BUG_ON(!e); + crystalfreq = e->freq; + cc->pmu.crystalfreq = e->freq; + + /* Check if the PLL already is programmed to this frequency. */ + pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL); + if (((pmuctl & SSB_CHIPCO_PMU_CTL_XTALFREQ) >> SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) == e->xf) { + /* We're already there... */ + return; + } + + ssb_printk(KERN_INFO PFX "Programming PLL to %u.%03u MHz\n", + (crystalfreq / 1000), (crystalfreq % 1000)); + + /* First turn the PLL off. */ + switch (bus->chip_id) { + case 0x4328: + chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK, + ~(1 << SSB_PMURES_4328_BB_PLL_PU)); + chipco_mask32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, + ~(1 << SSB_PMURES_4328_BB_PLL_PU)); + break; + case 0x5354: + chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK, + ~(1 << SSB_PMURES_5354_BB_PLL_PU)); + chipco_mask32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, + ~(1 << SSB_PMURES_5354_BB_PLL_PU)); + break; + default: + SSB_WARN_ON(1); + } + for (i = 1500; i; i--) { + tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); + if (!(tmp & SSB_CHIPCO_CLKCTLST_HAVEHT)) + break; + udelay(10); + } + tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); + if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT) + ssb_printk(KERN_EMERG PFX "Failed to turn the PLL off!\n"); + + /* Set PDIV in PLL control 0. */ + pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL0); + if (crystalfreq >= SSB_PMU0_PLLCTL0_PDIV_FREQ) + pllctl |= SSB_PMU0_PLLCTL0_PDIV_MSK; + else + pllctl &= ~SSB_PMU0_PLLCTL0_PDIV_MSK; + ssb_chipco_pll_write(cc, SSB_PMU0_PLLCTL0, pllctl); + + /* Set WILD in PLL control 1. */ + pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL1); + pllctl &= ~SSB_PMU0_PLLCTL1_STOPMOD; + pllctl &= ~(SSB_PMU0_PLLCTL1_WILD_IMSK | SSB_PMU0_PLLCTL1_WILD_FMSK); + pllctl |= ((u32)e->wb_int << SSB_PMU0_PLLCTL1_WILD_IMSK_SHIFT) & SSB_PMU0_PLLCTL1_WILD_IMSK; + pllctl |= ((u32)e->wb_frac << SSB_PMU0_PLLCTL1_WILD_FMSK_SHIFT) & SSB_PMU0_PLLCTL1_WILD_FMSK; + if (e->wb_frac == 0) + pllctl |= SSB_PMU0_PLLCTL1_STOPMOD; + ssb_chipco_pll_write(cc, SSB_PMU0_PLLCTL1, pllctl); + + /* Set WILD in PLL control 2. */ + pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL2); + pllctl &= ~SSB_PMU0_PLLCTL2_WILD_IMSKHI; + pllctl |= (((u32)e->wb_int >> 4) << SSB_PMU0_PLLCTL2_WILD_IMSKHI_SHIFT) & SSB_PMU0_PLLCTL2_WILD_IMSKHI; + ssb_chipco_pll_write(cc, SSB_PMU0_PLLCTL2, pllctl); + + /* Set the crystalfrequency and the divisor. */ + pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL); + pmuctl &= ~SSB_CHIPCO_PMU_CTL_ILP_DIV; + pmuctl |= (((crystalfreq + 127) / 128 - 1) << SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT) + & SSB_CHIPCO_PMU_CTL_ILP_DIV; + pmuctl &= ~SSB_CHIPCO_PMU_CTL_XTALFREQ; + pmuctl |= ((u32)e->xf << SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) & SSB_CHIPCO_PMU_CTL_XTALFREQ; + chipco_write32(cc, SSB_CHIPCO_PMU_CTL, pmuctl); +} + +struct pmu1_plltab_entry { + u16 freq; /* Crystal frequency in kHz.*/ + u8 xf; /* Crystal frequency value for PMU control */ + u8 ndiv_int; + u32 ndiv_frac; + u8 p1div; + u8 p2div; +}; + +static const struct pmu1_plltab_entry pmu1_plltab[] = { + { .freq = 12000, .xf = 1, .p1div = 3, .p2div = 22, .ndiv_int = 0x9, .ndiv_frac = 0xFFFFEF, }, + { .freq = 13000, .xf = 2, .p1div = 1, .p2div = 6, .ndiv_int = 0xb, .ndiv_frac = 0x483483, }, + { .freq = 14400, .xf = 3, .p1div = 1, .p2div = 10, .ndiv_int = 0xa, .ndiv_frac = 0x1C71C7, }, + { .freq = 15360, .xf = 4, .p1div = 1, .p2div = 5, .ndiv_int = 0xb, .ndiv_frac = 0x755555, }, + { .freq = 16200, .xf = 5, .p1div = 1, .p2div = 10, .ndiv_int = 0x5, .ndiv_frac = 0x6E9E06, }, + { .freq = 16800, .xf = 6, .p1div = 1, .p2div = 10, .ndiv_int = 0x5, .ndiv_frac = 0x3CF3CF, }, + { .freq = 19200, .xf = 7, .p1div = 1, .p2div = 9, .ndiv_int = 0x5, .ndiv_frac = 0x17B425, }, + { .freq = 19800, .xf = 8, .p1div = 1, .p2div = 11, .ndiv_int = 0x4, .ndiv_frac = 0xA57EB, }, + { .freq = 20000, .xf = 9, .p1div = 1, .p2div = 11, .ndiv_int = 0x4, .ndiv_frac = 0, }, + { .freq = 24000, .xf = 10, .p1div = 3, .p2div = 11, .ndiv_int = 0xa, .ndiv_frac = 0, }, + { .freq = 25000, .xf = 11, .p1div = 5, .p2div = 16, .ndiv_int = 0xb, .ndiv_frac = 0, }, + { .freq = 26000, .xf = 12, .p1div = 1, .p2div = 2, .ndiv_int = 0x10, .ndiv_frac = 0xEC4EC4, }, + { .freq = 30000, .xf = 13, .p1div = 3, .p2div = 8, .ndiv_int = 0xb, .ndiv_frac = 0, }, + { .freq = 38400, .xf = 14, .p1div = 1, .p2div = 5, .ndiv_int = 0x4, .ndiv_frac = 0x955555, }, + { .freq = 40000, .xf = 15, .p1div = 1, .p2div = 2, .ndiv_int = 0xb, .ndiv_frac = 0, }, +}; + +#define SSB_PMU1_DEFAULT_XTALFREQ 15360 + +static const struct pmu1_plltab_entry * pmu1_plltab_find_entry(u32 crystalfreq) +{ + const struct pmu1_plltab_entry *e; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(pmu1_plltab); i++) { + e = &pmu1_plltab[i]; + if (e->freq == crystalfreq) + return e; + } + + return NULL; +} + +/* Tune the PLL to the crystal speed. crystalfreq is in kHz. */ +static void ssb_pmu1_pllinit_r0(struct ssb_chipcommon *cc, + u32 crystalfreq) +{ + struct ssb_bus *bus = cc->dev->bus; + const struct pmu1_plltab_entry *e = NULL; + u32 buffer_strength = 0; + u32 tmp, pllctl, pmuctl; + unsigned int i; + + if (bus->chip_id == 0x4312) { + /* We do not touch the BCM4312 PLL and assume + * the default crystal settings work out-of-the-box. */ + cc->pmu.crystalfreq = 20000; + return; + } + + if (crystalfreq) + e = pmu1_plltab_find_entry(crystalfreq); + if (!e) + e = pmu1_plltab_find_entry(SSB_PMU1_DEFAULT_XTALFREQ); + BUG_ON(!e); + crystalfreq = e->freq; + cc->pmu.crystalfreq = e->freq; + + /* Check if the PLL already is programmed to this frequency. */ + pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL); + if (((pmuctl & SSB_CHIPCO_PMU_CTL_XTALFREQ) >> SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) == e->xf) { + /* We're already there... */ + return; + } + + ssb_printk(KERN_INFO PFX "Programming PLL to %u.%03u MHz\n", + (crystalfreq / 1000), (crystalfreq % 1000)); + + /* First turn the PLL off. */ + switch (bus->chip_id) { + case 0x4325: + chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK, + ~((1 << SSB_PMURES_4325_BBPLL_PWRSW_PU) | + (1 << SSB_PMURES_4325_HT_AVAIL))); + chipco_mask32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, + ~((1 << SSB_PMURES_4325_BBPLL_PWRSW_PU) | + (1 << SSB_PMURES_4325_HT_AVAIL))); + /* Adjust the BBPLL to 2 on all channels later. */ + buffer_strength = 0x222222; + break; + default: + SSB_WARN_ON(1); + } + for (i = 1500; i; i--) { + tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); + if (!(tmp & SSB_CHIPCO_CLKCTLST_HAVEHT)) + break; + udelay(10); + } + tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); + if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT) + ssb_printk(KERN_EMERG PFX "Failed to turn the PLL off!\n"); + + /* Set p1div and p2div. */ + pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL0); + pllctl &= ~(SSB_PMU1_PLLCTL0_P1DIV | SSB_PMU1_PLLCTL0_P2DIV); + pllctl |= ((u32)e->p1div << SSB_PMU1_PLLCTL0_P1DIV_SHIFT) & SSB_PMU1_PLLCTL0_P1DIV; + pllctl |= ((u32)e->p2div << SSB_PMU1_PLLCTL0_P2DIV_SHIFT) & SSB_PMU1_PLLCTL0_P2DIV; + ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, pllctl); + + /* Set ndiv int and ndiv mode */ + pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL2); + pllctl &= ~(SSB_PMU1_PLLCTL2_NDIVINT | SSB_PMU1_PLLCTL2_NDIVMODE); + pllctl |= ((u32)e->ndiv_int << SSB_PMU1_PLLCTL2_NDIVINT_SHIFT) & SSB_PMU1_PLLCTL2_NDIVINT; + pllctl |= (1 << SSB_PMU1_PLLCTL2_NDIVMODE_SHIFT) & SSB_PMU1_PLLCTL2_NDIVMODE; + ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, pllctl); + + /* Set ndiv frac */ + pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL3); + pllctl &= ~SSB_PMU1_PLLCTL3_NDIVFRAC; + pllctl |= ((u32)e->ndiv_frac << SSB_PMU1_PLLCTL3_NDIVFRAC_SHIFT) & SSB_PMU1_PLLCTL3_NDIVFRAC; + ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL3, pllctl); + + /* Change the drive strength, if required. */ + if (buffer_strength) { + pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL5); + pllctl &= ~SSB_PMU1_PLLCTL5_CLKDRV; + pllctl |= (buffer_strength << SSB_PMU1_PLLCTL5_CLKDRV_SHIFT) & SSB_PMU1_PLLCTL5_CLKDRV; + ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, pllctl); + } + + /* Tune the crystalfreq and the divisor. */ + pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL); + pmuctl &= ~(SSB_CHIPCO_PMU_CTL_ILP_DIV | SSB_CHIPCO_PMU_CTL_XTALFREQ); + pmuctl |= ((((u32)e->freq + 127) / 128 - 1) << SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT) + & SSB_CHIPCO_PMU_CTL_ILP_DIV; + pmuctl |= ((u32)e->xf << SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) & SSB_CHIPCO_PMU_CTL_XTALFREQ; + chipco_write32(cc, SSB_CHIPCO_PMU_CTL, pmuctl); +} + +static void ssb_pmu_pll_init(struct ssb_chipcommon *cc) +{ + struct ssb_bus *bus = cc->dev->bus; + u32 crystalfreq = 0; /* in kHz. 0 = keep default freq. */ + + if (bus->bustype == SSB_BUSTYPE_SSB) { + /* TODO: The user may override the crystal frequency. */ + } + + switch (bus->chip_id) { + case 0x4312: + case 0x4325: + ssb_pmu1_pllinit_r0(cc, crystalfreq); + break; + case 0x4328: + case 0x5354: + ssb_pmu0_pllinit_r0(cc, crystalfreq); + break; + default: + ssb_printk(KERN_ERR PFX + "ERROR: PLL init unknown for device %04X\n", + bus->chip_id); + } +} + +struct pmu_res_updown_tab_entry { + u8 resource; /* The resource number */ + u16 updown; /* The updown value */ +}; + +enum pmu_res_depend_tab_task { + PMU_RES_DEP_SET = 1, + PMU_RES_DEP_ADD, + PMU_RES_DEP_REMOVE, +}; + +struct pmu_res_depend_tab_entry { + u8 resource; /* The resource number */ + u8 task; /* SET | ADD | REMOVE */ + u32 depend; /* The depend mask */ +}; + +static const struct pmu_res_updown_tab_entry pmu_res_updown_tab_4328a0[] = { + { .resource = SSB_PMURES_4328_EXT_SWITCHER_PWM, .updown = 0x0101, }, + { .resource = SSB_PMURES_4328_BB_SWITCHER_PWM, .updown = 0x1F01, }, + { .resource = SSB_PMURES_4328_BB_SWITCHER_BURST, .updown = 0x010F, }, + { .resource = SSB_PMURES_4328_BB_EXT_SWITCHER_BURST, .updown = 0x0101, }, + { .resource = SSB_PMURES_4328_ILP_REQUEST, .updown = 0x0202, }, + { .resource = SSB_PMURES_4328_RADIO_SWITCHER_PWM, .updown = 0x0F01, }, + { .resource = SSB_PMURES_4328_RADIO_SWITCHER_BURST, .updown = 0x0F01, }, + { .resource = SSB_PMURES_4328_ROM_SWITCH, .updown = 0x0101, }, + { .resource = SSB_PMURES_4328_PA_REF_LDO, .updown = 0x0F01, }, + { .resource = SSB_PMURES_4328_RADIO_LDO, .updown = 0x0F01, }, + { .resource = SSB_PMURES_4328_AFE_LDO, .updown = 0x0F01, }, + { .resource = SSB_PMURES_4328_PLL_LDO, .updown = 0x0F01, }, + { .resource = SSB_PMURES_4328_BG_FILTBYP, .updown = 0x0101, }, + { .resource = SSB_PMURES_4328_TX_FILTBYP, .updown = 0x0101, }, + { .resource = SSB_PMURES_4328_RX_FILTBYP, .updown = 0x0101, }, + { .resource = SSB_PMURES_4328_XTAL_PU, .updown = 0x0101, }, + { .resource = SSB_PMURES_4328_XTAL_EN, .updown = 0xA001, }, + { .resource = SSB_PMURES_4328_BB_PLL_FILTBYP, .updown = 0x0101, }, + { .resource = SSB_PMURES_4328_RF_PLL_FILTBYP, .updown = 0x0101, }, + { .resource = SSB_PMURES_4328_BB_PLL_PU, .updown = 0x0701, }, +}; + +static const struct pmu_res_depend_tab_entry pmu_res_depend_tab_4328a0[] = { + { + /* Adjust ILP Request to avoid forcing EXT/BB into burst mode. */ + .resource = SSB_PMURES_4328_ILP_REQUEST, + .task = PMU_RES_DEP_SET, + .depend = ((1 << SSB_PMURES_4328_EXT_SWITCHER_PWM) | + (1 << SSB_PMURES_4328_BB_SWITCHER_PWM)), + }, +}; + +static const struct pmu_res_updown_tab_entry pmu_res_updown_tab_4325a0[] = { + { .resource = SSB_PMURES_4325_XTAL_PU, .updown = 0x1501, }, +}; + +static const struct pmu_res_depend_tab_entry pmu_res_depend_tab_4325a0[] = { + { + /* Adjust HT-Available dependencies. */ + .resource = SSB_PMURES_4325_HT_AVAIL, + .task = PMU_RES_DEP_ADD, + .depend = ((1 << SSB_PMURES_4325_RX_PWRSW_PU) | + (1 << SSB_PMURES_4325_TX_PWRSW_PU) | + (1 << SSB_PMURES_4325_LOGEN_PWRSW_PU) | + (1 << SSB_PMURES_4325_AFE_PWRSW_PU)), + }, +}; + +static void ssb_pmu_resources_init(struct ssb_chipcommon *cc) +{ + struct ssb_bus *bus = cc->dev->bus; + u32 min_msk = 0, max_msk = 0; + unsigned int i; + const struct pmu_res_updown_tab_entry *updown_tab = NULL; + unsigned int updown_tab_size; + const struct pmu_res_depend_tab_entry *depend_tab = NULL; + unsigned int depend_tab_size; + + switch (bus->chip_id) { + case 0x4312: + /* We keep the default settings: + * min_msk = 0xCBB + * max_msk = 0x7FFFF + */ + break; + case 0x4325: + /* Power OTP down later. */ + min_msk = (1 << SSB_PMURES_4325_CBUCK_BURST) | + (1 << SSB_PMURES_4325_LNLDO2_PU); + if (chipco_read32(cc, SSB_CHIPCO_CHIPSTAT) & + SSB_CHIPCO_CHST_4325_PMUTOP_2B) + min_msk |= (1 << SSB_PMURES_4325_CLDO_CBUCK_BURST); + /* The PLL may turn on, if it decides so. */ + max_msk = 0xFFFFF; + updown_tab = pmu_res_updown_tab_4325a0; + updown_tab_size = ARRAY_SIZE(pmu_res_updown_tab_4325a0); + depend_tab = pmu_res_depend_tab_4325a0; + depend_tab_size = ARRAY_SIZE(pmu_res_depend_tab_4325a0); + break; + case 0x4328: + min_msk = (1 << SSB_PMURES_4328_EXT_SWITCHER_PWM) | + (1 << SSB_PMURES_4328_BB_SWITCHER_PWM) | + (1 << SSB_PMURES_4328_XTAL_EN); + /* The PLL may turn on, if it decides so. */ + max_msk = 0xFFFFF; + updown_tab = pmu_res_updown_tab_4328a0; + updown_tab_size = ARRAY_SIZE(pmu_res_updown_tab_4328a0); + depend_tab = pmu_res_depend_tab_4328a0; + depend_tab_size = ARRAY_SIZE(pmu_res_depend_tab_4328a0); + break; + case 0x5354: + /* The PLL may turn on, if it decides so. */ + max_msk = 0xFFFFF; + break; + default: + ssb_printk(KERN_ERR PFX + "ERROR: PMU resource config unknown for device %04X\n", + bus->chip_id); + } + + if (updown_tab) { + for (i = 0; i < updown_tab_size; i++) { + chipco_write32(cc, SSB_CHIPCO_PMU_RES_TABSEL, + updown_tab[i].resource); + chipco_write32(cc, SSB_CHIPCO_PMU_RES_UPDNTM, + updown_tab[i].updown); + } + } + if (depend_tab) { + for (i = 0; i < depend_tab_size; i++) { + chipco_write32(cc, SSB_CHIPCO_PMU_RES_TABSEL, + depend_tab[i].resource); + switch (depend_tab[i].task) { + case PMU_RES_DEP_SET: + chipco_write32(cc, SSB_CHIPCO_PMU_RES_DEPMSK, + depend_tab[i].depend); + break; + case PMU_RES_DEP_ADD: + chipco_set32(cc, SSB_CHIPCO_PMU_RES_DEPMSK, + depend_tab[i].depend); + break; + case PMU_RES_DEP_REMOVE: + chipco_mask32(cc, SSB_CHIPCO_PMU_RES_DEPMSK, + ~(depend_tab[i].depend)); + break; + default: + SSB_WARN_ON(1); + } + } + } + + /* Set the resource masks. */ + if (min_msk) + chipco_write32(cc, SSB_CHIPCO_PMU_MINRES_MSK, min_msk); + if (max_msk) + chipco_write32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, max_msk); +} + +void ssb_pmu_init(struct ssb_chipcommon *cc) +{ + struct ssb_bus *bus = cc->dev->bus; + u32 pmucap; + + if (!(cc->capabilities & SSB_CHIPCO_CAP_PMU)) + return; + + pmucap = chipco_read32(cc, SSB_CHIPCO_PMU_CAP); + cc->pmu.rev = (pmucap & SSB_CHIPCO_PMU_CAP_REVISION); + + ssb_dprintk(KERN_DEBUG PFX "Found rev %u PMU (capabilities 0x%08X)\n", + cc->pmu.rev, pmucap); + + if (cc->pmu.rev >= 1) { + if ((bus->chip_id == 0x4325) && (bus->chip_rev < 2)) { + chipco_mask32(cc, SSB_CHIPCO_PMU_CTL, + ~SSB_CHIPCO_PMU_CTL_NOILPONW); + } else { + chipco_set32(cc, SSB_CHIPCO_PMU_CTL, + SSB_CHIPCO_PMU_CTL_NOILPONW); + } + } + ssb_pmu_pll_init(cc); + ssb_pmu_resources_init(cc); +} diff --git a/include/linux/ssb/ssb_driver_chipcommon.h b/include/linux/ssb/ssb_driver_chipcommon.h index 7d7e03dcf77..d3b1d18922f 100644 --- a/include/linux/ssb/ssb_driver_chipcommon.h +++ b/include/linux/ssb/ssb_driver_chipcommon.h @@ -181,6 +181,16 @@ #define SSB_CHIPCO_PROG_WAITCNT 0x0124 #define SSB_CHIPCO_FLASH_CFG 0x0128 #define SSB_CHIPCO_FLASH_WAITCNT 0x012C +#define SSB_CHIPCO_CLKCTLST 0x01E0 /* Clock control and status (rev >= 20) */ +#define SSB_CHIPCO_CLKCTLST_FORCEALP 0x00000001 /* Force ALP request */ +#define SSB_CHIPCO_CLKCTLST_FORCEHT 0x00000002 /* Force HT request */ +#define SSB_CHIPCO_CLKCTLST_FORCEILP 0x00000004 /* Force ILP request */ +#define SSB_CHIPCO_CLKCTLST_HAVEALPREQ 0x00000008 /* ALP available request */ +#define SSB_CHIPCO_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */ +#define SSB_CHIPCO_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */ +#define SSB_CHIPCO_CLKCTLST_HAVEHT 0x00010000 /* HT available */ +#define SSB_CHIPCO_CLKCTLST_HAVEALP 0x00020000 /* APL available */ +#define SSB_CHIPCO_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */ #define SSB_CHIPCO_UART0_DATA 0x0300 #define SSB_CHIPCO_UART0_IMR 0x0304 #define SSB_CHIPCO_UART0_FCR 0x0308 @@ -197,6 +207,196 @@ #define SSB_CHIPCO_UART1_LSR 0x0414 #define SSB_CHIPCO_UART1_MSR 0x0418 #define SSB_CHIPCO_UART1_SCRATCH 0x041C +/* PMU registers (rev >= 20) */ +#define SSB_CHIPCO_PMU_CTL 0x0600 /* PMU control */ +#define SSB_CHIPCO_PMU_CTL_ILP_DIV 0xFFFF0000 /* ILP div mask */ +#define SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT 16 +#define SSB_CHIPCO_PMU_CTL_NOILPONW 0x00000200 /* No ILP on wait */ +#define SSB_CHIPCO_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */ +#define SSB_CHIPCO_PMU_CTL_ALPREQEN 0x00000080 /* ALP req enable */ +#define SSB_CHIPCO_PMU_CTL_XTALFREQ 0x0000007C /* Crystal freq */ +#define SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT 2 +#define SSB_CHIPCO_PMU_CTL_ILPDIVEN 0x00000002 /* ILP div enable */ +#define SSB_CHIPCO_PMU_CTL_LPOSEL 0x00000001 /* LPO sel */ +#define SSB_CHIPCO_PMU_CAP 0x0604 /* PMU capabilities */ +#define SSB_CHIPCO_PMU_CAP_REVISION 0x000000FF /* Revision mask */ +#define SSB_CHIPCO_PMU_STAT 0x0608 /* PMU status */ +#define SSB_CHIPCO_PMU_STAT_INTPEND 0x00000040 /* Interrupt pending */ +#define SSB_CHIPCO_PMU_STAT_SBCLKST 0x00000030 /* Backplane clock status? */ +#define SSB_CHIPCO_PMU_STAT_HAVEALP 0x00000008 /* ALP available */ +#define SSB_CHIPCO_PMU_STAT_HAVEHT 0x00000004 /* HT available */ +#define SSB_CHIPCO_PMU_STAT_RESINIT 0x00000003 /* Res init */ +#define SSB_CHIPCO_PMU_RES_STAT 0x060C /* PMU res status */ +#define SSB_CHIPCO_PMU_RES_PEND 0x0610 /* PMU res pending */ +#define SSB_CHIPCO_PMU_TIMER 0x0614 /* PMU timer */ +#define SSB_CHIPCO_PMU_MINRES_MSK 0x0618 /* PMU min res mask */ +#define SSB_CHIPCO_PMU_MAXRES_MSK 0x061C /* PMU max res mask */ +#define SSB_CHIPCO_PMU_RES_TABSEL 0x0620 /* PMU res table sel */ +#define SSB_CHIPCO_PMU_RES_DEPMSK 0x0624 /* PMU res dep mask */ +#define SSB_CHIPCO_PMU_RES_UPDNTM 0x0628 /* PMU res updown timer */ +#define SSB_CHIPCO_PMU_RES_TIMER 0x062C /* PMU res timer */ +#define SSB_CHIPCO_PMU_CLKSTRETCH 0x0630 /* PMU clockstretch */ +#define SSB_CHIPCO_PMU_WATCHDOG 0x0634 /* PMU watchdog */ +#define SSB_CHIPCO_PMU_RES_REQTS 0x0640 /* PMU res req timer sel */ +#define SSB_CHIPCO_PMU_RES_REQT 0x0644 /* PMU res req timer */ +#define SSB_CHIPCO_PMU_RES_REQM 0x0648 /* PMU res req mask */ +#define SSB_CHIPCO_CHIPCTL_ADDR 0x0650 +#define SSB_CHIPCO_CHIPCTL_DATA 0x0654 +#define SSB_CHIPCO_REGCTL_ADDR 0x0658 +#define SSB_CHIPCO_REGCTL_DATA 0x065C +#define SSB_CHIPCO_PLLCTL_ADDR 0x0660 +#define SSB_CHIPCO_PLLCTL_DATA 0x0664 + + + +/** PMU PLL registers */ + +/* PMU rev 0 PLL registers */ +#define SSB_PMU0_PLLCTL0 0 +#define SSB_PMU0_PLLCTL0_PDIV_MSK 0x00000001 +#define SSB_PMU0_PLLCTL0_PDIV_FREQ 25000 /* kHz */ +#define SSB_PMU0_PLLCTL1 1 +#define SSB_PMU0_PLLCTL1_WILD_IMSK 0xF0000000 /* Wild int mask (low nibble) */ +#define SSB_PMU0_PLLCTL1_WILD_IMSK_SHIFT 28 +#define SSB_PMU0_PLLCTL1_WILD_FMSK 0x0FFFFF00 /* Wild frac mask */ +#define SSB_PMU0_PLLCTL1_WILD_FMSK_SHIFT 8 +#define SSB_PMU0_PLLCTL1_STOPMOD 0x00000040 /* Stop mod */ +#define SSB_PMU0_PLLCTL2 2 +#define SSB_PMU0_PLLCTL2_WILD_IMSKHI 0x0000000F /* Wild int mask (high nibble) */ +#define SSB_PMU0_PLLCTL2_WILD_IMSKHI_SHIFT 0 + +/* PMU rev 1 PLL registers */ +#define SSB_PMU1_PLLCTL0 0 +#define SSB_PMU1_PLLCTL0_P1DIV 0x00F00000 /* P1 div */ +#define SSB_PMU1_PLLCTL0_P1DIV_SHIFT 20 +#define SSB_PMU1_PLLCTL0_P2DIV 0x0F000000 /* P2 div */ +#define SSB_PMU1_PLLCTL0_P2DIV_SHIFT 24 +#define SSB_PMU1_PLLCTL1 1 +#define SSB_PMU1_PLLCTL1_M1DIV 0x000000FF /* M1 div */ +#define SSB_PMU1_PLLCTL1_M1DIV_SHIFT 0 +#define SSB_PMU1_PLLCTL1_M2DIV 0x0000FF00 /* M2 div */ +#define SSB_PMU1_PLLCTL1_M2DIV_SHIFT 8 +#define SSB_PMU1_PLLCTL1_M3DIV 0x00FF0000 /* M3 div */ +#define SSB_PMU1_PLLCTL1_M3DIV_SHIFT 16 +#define SSB_PMU1_PLLCTL1_M4DIV 0xFF000000 /* M4 div */ +#define SSB_PMU1_PLLCTL1_M4DIV_SHIFT 24 +#define SSB_PMU1_PLLCTL2 2 +#define SSB_PMU1_PLLCTL2_M5DIV 0x000000FF /* M5 div */ +#define SSB_PMU1_PLLCTL2_M5DIV_SHIFT 0 +#define SSB_PMU1_PLLCTL2_M6DIV 0x0000FF00 /* M6 div */ +#define SSB_PMU1_PLLCTL2_M6DIV_SHIFT 8 +#define SSB_PMU1_PLLCTL2_NDIVMODE 0x000E0000 /* NDIV mode */ +#define SSB_PMU1_PLLCTL2_NDIVMODE_SHIFT 17 +#define SSB_PMU1_PLLCTL2_NDIVINT 0x1FF00000 /* NDIV int */ +#define SSB_PMU1_PLLCTL2_NDIVINT_SHIFT 20 +#define SSB_PMU1_PLLCTL3 3 +#define SSB_PMU1_PLLCTL3_NDIVFRAC 0x00FFFFFF /* NDIV frac */ +#define SSB_PMU1_PLLCTL3_NDIVFRAC_SHIFT 0 +#define SSB_PMU1_PLLCTL4 4 +#define SSB_PMU1_PLLCTL5 5 +#define SSB_PMU1_PLLCTL5_CLKDRV 0xFFFFFF00 /* clk drv */ +#define SSB_PMU1_PLLCTL5_CLKDRV_SHIFT 8 + +/* BCM4312 PLL resource numbers. */ +#define SSB_PMURES_4312_SWITCHER_BURST 0 +#define SSB_PMURES_4312_SWITCHER_PWM 1 +#define SSB_PMURES_4312_PA_REF_LDO 2 +#define SSB_PMURES_4312_CORE_LDO_BURST 3 +#define SSB_PMURES_4312_CORE_LDO_PWM 4 +#define SSB_PMURES_4312_RADIO_LDO 5 +#define SSB_PMURES_4312_ILP_REQUEST 6 +#define SSB_PMURES_4312_BG_FILTBYP 7 +#define SSB_PMURES_4312_TX_FILTBYP 8 +#define SSB_PMURES_4312_RX_FILTBYP 9 +#define SSB_PMURES_4312_XTAL_PU 10 +#define SSB_PMURES_4312_ALP_AVAIL 11 +#define SSB_PMURES_4312_BB_PLL_FILTBYP 12 +#define SSB_PMURES_4312_RF_PLL_FILTBYP 13 +#define SSB_PMURES_4312_HT_AVAIL 14 + +/* BCM4325 PLL resource numbers. */ +#define SSB_PMURES_4325_BUCK_BOOST_BURST 0 +#define SSB_PMURES_4325_CBUCK_BURST 1 +#define SSB_PMURES_4325_CBUCK_PWM 2 +#define SSB_PMURES_4325_CLDO_CBUCK_BURST 3 +#define SSB_PMURES_4325_CLDO_CBUCK_PWM 4 +#define SSB_PMURES_4325_BUCK_BOOST_PWM 5 +#define SSB_PMURES_4325_ILP_REQUEST 6 +#define SSB_PMURES_4325_ABUCK_BURST 7 +#define SSB_PMURES_4325_ABUCK_PWM 8 +#define SSB_PMURES_4325_LNLDO1_PU 9 +#define SSB_PMURES_4325_LNLDO2_PU 10 +#define SSB_PMURES_4325_LNLDO3_PU 11 +#define SSB_PMURES_4325_LNLDO4_PU 12 +#define SSB_PMURES_4325_XTAL_PU 13 +#define SSB_PMURES_4325_ALP_AVAIL 14 +#define SSB_PMURES_4325_RX_PWRSW_PU 15 +#define SSB_PMURES_4325_TX_PWRSW_PU 16 +#define SSB_PMURES_4325_RFPLL_PWRSW_PU 17 +#define SSB_PMURES_4325_LOGEN_PWRSW_PU 18 +#define SSB_PMURES_4325_AFE_PWRSW_PU 19 +#define SSB_PMURES_4325_BBPLL_PWRSW_PU 20 +#define SSB_PMURES_4325_HT_AVAIL 21 + +/* BCM4328 PLL resource numbers. */ +#define SSB_PMURES_4328_EXT_SWITCHER_PWM 0 +#define SSB_PMURES_4328_BB_SWITCHER_PWM 1 +#define SSB_PMURES_4328_BB_SWITCHER_BURST 2 +#define SSB_PMURES_4328_BB_EXT_SWITCHER_BURST 3 +#define SSB_PMURES_4328_ILP_REQUEST 4 +#define SSB_PMURES_4328_RADIO_SWITCHER_PWM 5 +#define SSB_PMURES_4328_RADIO_SWITCHER_BURST 6 +#define SSB_PMURES_4328_ROM_SWITCH 7 +#define SSB_PMURES_4328_PA_REF_LDO 8 +#define SSB_PMURES_4328_RADIO_LDO 9 +#define SSB_PMURES_4328_AFE_LDO 10 +#define SSB_PMURES_4328_PLL_LDO 11 +#define SSB_PMURES_4328_BG_FILTBYP 12 +#define SSB_PMURES_4328_TX_FILTBYP 13 +#define SSB_PMURES_4328_RX_FILTBYP 14 +#define SSB_PMURES_4328_XTAL_PU 15 +#define SSB_PMURES_4328_XTAL_EN 16 +#define SSB_PMURES_4328_BB_PLL_FILTBYP 17 +#define SSB_PMURES_4328_RF_PLL_FILTBYP 18 +#define SSB_PMURES_4328_BB_PLL_PU 19 + +/* BCM5354 PLL resource numbers. */ +#define SSB_PMURES_5354_EXT_SWITCHER_PWM 0 +#define SSB_PMURES_5354_BB_SWITCHER_PWM 1 +#define SSB_PMURES_5354_BB_SWITCHER_BURST 2 +#define SSB_PMURES_5354_BB_EXT_SWITCHER_BURST 3 +#define SSB_PMURES_5354_ILP_REQUEST 4 +#define SSB_PMURES_5354_RADIO_SWITCHER_PWM 5 +#define SSB_PMURES_5354_RADIO_SWITCHER_BURST 6 +#define SSB_PMURES_5354_ROM_SWITCH 7 +#define SSB_PMURES_5354_PA_REF_LDO 8 +#define SSB_PMURES_5354_RADIO_LDO 9 +#define SSB_PMURES_5354_AFE_LDO 10 +#define SSB_PMURES_5354_PLL_LDO 11 +#define SSB_PMURES_5354_BG_FILTBYP 12 +#define SSB_PMURES_5354_TX_FILTBYP 13 +#define SSB_PMURES_5354_RX_FILTBYP 14 +#define SSB_PMURES_5354_XTAL_PU 15 +#define SSB_PMURES_5354_XTAL_EN 16 +#define SSB_PMURES_5354_BB_PLL_FILTBYP 17 +#define SSB_PMURES_5354_RF_PLL_FILTBYP 18 +#define SSB_PMURES_5354_BB_PLL_PU 19 + + + +/** Chip specific Chip-Status register contents. */ +#define SSB_CHIPCO_CHST_4325_SPROM_OTP_SEL 0x00000003 +#define SSB_CHIPCO_CHST_4325_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */ +#define SSB_CHIPCO_CHST_4325_SPROM_SEL 1 /* OTP is powered up, SPROM is present */ +#define SSB_CHIPCO_CHST_4325_OTP_SEL 2 /* OTP is powered up, no SPROM */ +#define SSB_CHIPCO_CHST_4325_OTP_PWRDN 3 /* OTP is powered down, SPROM is present */ +#define SSB_CHIPCO_CHST_4325_SDIO_USB_MODE 0x00000004 +#define SSB_CHIPCO_CHST_4325_SDIO_USB_MODE_SHIFT 2 +#define SSB_CHIPCO_CHST_4325_RCAL_VALID 0x00000008 +#define SSB_CHIPCO_CHST_4325_RCAL_VALID_SHIFT 3 +#define SSB_CHIPCO_CHST_4325_RCAL_VALUE 0x000001F0 +#define SSB_CHIPCO_CHST_4325_RCAL_VALUE_SHIFT 4 +#define SSB_CHIPCO_CHST_4325_PMUTOP_2B 0x00000200 /* 1 for 2b, 0 for to 2a */ @@ -353,11 +553,20 @@ struct ssb_device; struct ssb_serial_port; +/* Data for the PMU, if available. + * Check availability with ((struct ssb_chipcommon)->capabilities & SSB_CHIPCO_CAP_PMU) + */ +struct ssb_chipcommon_pmu { + u8 rev; /* PMU revision */ + u32 crystalfreq; /* The active crystal frequency (in kHz) */ +}; + struct ssb_chipcommon { struct ssb_device *dev; u32 capabilities; /* Fast Powerup Delay constant */ u16 fast_pwrup_delay; + struct ssb_chipcommon_pmu pmu; }; static inline bool ssb_chipco_available(struct ssb_chipcommon *cc) @@ -365,6 +574,17 @@ static inline bool ssb_chipco_available(struct ssb_chipcommon *cc) return (cc->dev != NULL); } +/* Register access */ +#define chipco_read32(cc, offset) ssb_read32((cc)->dev, offset) +#define chipco_write32(cc, offset, val) ssb_write32((cc)->dev, offset, val) + +#define chipco_mask32(cc, offset, mask) \ + chipco_write32(cc, offset, chipco_read32(cc, offset) & (mask)) +#define chipco_set32(cc, offset, set) \ + chipco_write32(cc, offset, chipco_read32(cc, offset) | (set)) +#define chipco_maskset32(cc, offset, mask, set) \ + chipco_write32(cc, offset, (chipco_read32(cc, offset) & (mask)) | (set)) + extern void ssb_chipcommon_init(struct ssb_chipcommon *cc); extern void ssb_chipco_suspend(struct ssb_chipcommon *cc); @@ -406,4 +626,8 @@ extern int ssb_chipco_serial_init(struct ssb_chipcommon *cc, struct ssb_serial_port *ports); #endif /* CONFIG_SSB_SERIAL */ +/* PMU support */ +extern void ssb_pmu_init(struct ssb_chipcommon *cc); + + #endif /* LINUX_SSB_CHIPCO_H_ */ -- GitLab From 686aa5f2137d04f389e527f0391d65232338e599 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 3 Feb 2009 19:36:45 +0100 Subject: [PATCH 1504/4982] b43: Port spec bugfixes for the LP baseband init A few bugs were fixed in the LP baseband init specs. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_lp.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 99cc9739ace..fdd31d3672d 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -70,6 +70,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) { + struct ssb_bus *bus = dev->dev->bus; struct b43_phy_lp *lpphy = dev->phy.lp; b43_phy_write(dev, B43_LPPHY_AFE_DAC_CTL, 0x50); @@ -89,7 +90,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x4000); b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x2000); b43_phy_set(dev, B43_PHY_OFDM(0x10A), 0x1); - b43_phy_maskset(dev, B43_LPPHY_CCKLMSSTEPSIZE, 0xFF01, 0x10); + b43_phy_maskset(dev, B43_PHY_OFDM(0x10A), 0xFF01, 0x10); b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0xFF00, 0xF4); b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0x00FF, 0xF100); b43_phy_write(dev, B43_LPPHY_CLIPTHRESH, 0x48); @@ -101,8 +102,13 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xF81F, 0xA0); b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xE0FF, 0x300); b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0x00FF, 0x2A00); - b43_phy_maskset(dev, B43_LPPHY_LOWGAINDB, 0x00FF, 0x1E00); - b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0xD); + if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) { + b43_phy_maskset(dev, B43_LPPHY_LOWGAINDB, 0x00FF, 0x2100); + b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0xA); + } else { + b43_phy_maskset(dev, B43_LPPHY_LOWGAINDB, 0x00FF, 0x1E00); + b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0xD); + } b43_phy_maskset(dev, B43_PHY_OFDM(0xFE), 0xFFE0, 0x1F); b43_phy_maskset(dev, B43_PHY_OFDM(0xFF), 0xFFE0, 0xC); b43_phy_maskset(dev, B43_PHY_OFDM(0x100), 0xFF00, 0x19); @@ -114,17 +120,8 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x12); b43_phy_maskset(dev, B43_LPPHY_GAINMISMATCH, 0x0FFF, 0x9000); - if (dev->phy.rev < 2) { - //FIXME this will never execute. - - //FIXME 32bit? - b43_lptab_write(dev, B43_LPTAB32(0x11, 0x14), 0); - b43_lptab_write(dev, B43_LPTAB32(0x08, 0x12), 0x40); - } else { - //FIXME 32bit? - b43_lptab_write(dev, B43_LPTAB32(0x08, 0x14), 0); - b43_lptab_write(dev, B43_LPTAB32(0x08, 0x12), 0x40); - } + b43_lptab_write(dev, B43_LPTAB16(0x08, 0x14), 0); + b43_lptab_write(dev, B43_LPTAB16(0x08, 0x12), 0x40); if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x40); -- GitLab From 99e0fca6740b98aed1f604fc2e0acbdbc9e7578a Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 3 Feb 2009 20:06:14 +0100 Subject: [PATCH 1505/4982] b43: (b2062) Fix crystal frequency calculations This fixes the crystal frequency calculations in the b2062 init code. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_lp.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index fdd31d3672d..94d9e8b215e 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -160,6 +160,7 @@ struct b2062_freqdata { /* Initialize the 2062 radio. */ static void lpphy_2062_init(struct b43_wldev *dev) { + struct ssb_bus *bus = dev->dev->bus; u32 crystalfreq, pdiv, tmp, ref; unsigned int i; const struct b2062_freqdata *fd = NULL; @@ -193,7 +194,11 @@ static void lpphy_2062_init(struct b43_wldev *dev) else b43_radio_mask(dev, B2062_N_TSSI_CTL0, ~0x1); - crystalfreq = 0;//FIXME + /* Get the crystal freq, in Hz. */ + crystalfreq = bus->chipco.pmu.crystalfreq * 1000; + + B43_WARN_ON(!(bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU)); + B43_WARN_ON(crystalfreq == 0); if (crystalfreq >= 30000000) { pdiv = 1; @@ -219,13 +224,15 @@ static void lpphy_2062_init(struct b43_wldev *dev) break; } } - if (B43_WARN_ON(!fd)) - return; + if (!fd) + fd = &freqdata_tab[ARRAY_SIZE(freqdata_tab) - 1]; + b43dbg(dev->wl, "b2062: Using crystal tab entry %u kHz.\n", + fd->freq); /* FIXME: Keep this printk until the code is fully debugged. */ b43_radio_write(dev, B2062_S_RFPLL_CTL8, ((u16)(fd->data[1]) << 4) | fd->data[0]); b43_radio_write(dev, B2062_S_RFPLL_CTL9, - ((u16)(fd->data[3]) << 4) | fd->data[2]);//FIXME specs are different + ((u16)(fd->data[3]) << 4) | fd->data[2]); b43_radio_write(dev, B2062_S_RFPLL_CTL10, fd->data[4]); b43_radio_write(dev, B2062_S_RFPLL_CTL11, fd->data[5]); } -- GitLab From 3c552ac8a747d6c26d13302c54d71dae9f56f4ac Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 9 Feb 2009 12:05:47 -0800 Subject: [PATCH 1506/4982] x86: make apic_* operations inline functions Mainly to get proper type-checking and consistency. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/apic.h | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index b03711d7990..f4835a1be36 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -139,12 +139,35 @@ struct apic_ops { extern struct apic_ops *apic_ops; -#define apic_read (apic_ops->read) -#define apic_write (apic_ops->write) -#define apic_icr_read (apic_ops->icr_read) -#define apic_icr_write (apic_ops->icr_write) -#define apic_wait_icr_idle (apic_ops->wait_icr_idle) -#define safe_apic_wait_icr_idle (apic_ops->safe_wait_icr_idle) +static inline u32 apic_read(u32 reg) +{ + return apic_ops->read(reg); +} + +static inline void apic_write(u32 reg, u32 val) +{ + apic_ops->write(reg, val); +} + +static inline u64 apic_icr_read(void) +{ + return apic_ops->icr_read(); +} + +static inline void apic_icr_write(u32 low, u32 high) +{ + apic_ops->icr_write(low, high); +} + +static inline void apic_wait_icr_idle(void) +{ + apic_ops->wait_icr_idle(); +} + +static inline u32 safe_apic_wait_icr_idle(void) +{ + return apic_ops->safe_wait_icr_idle(); +} extern int get_physical_broadcast(void); -- GitLab From 4924e228ae039029a9503ad571d91086e4042c90 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 9 Feb 2009 12:05:47 -0800 Subject: [PATCH 1507/4982] x86: unstatic mp_find_ioapic so it can be used elsewhere Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/mpspec.h | 1 + arch/x86/kernel/acpi/boot.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h index 8c5620147c4..b59371a312f 100644 --- a/arch/x86/include/asm/mpspec.h +++ b/arch/x86/include/asm/mpspec.h @@ -77,6 +77,7 @@ extern int acpi_probe_gsi(void); #ifdef CONFIG_X86_IO_APIC extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin, u32 gsi, int triggering, int polarity); +extern int mp_find_ioapic(int gsi); #else static inline int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin, diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index c334fe75dcd..068b900f4b0 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -872,7 +872,7 @@ static struct { DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1); } mp_ioapic_routing[MAX_IO_APICS]; -static int mp_find_ioapic(int gsi) +int mp_find_ioapic(int gsi) { int i = 0; -- GitLab From c3e137d1e882c4fab9adcce7ae2be9bf3eb64c4c Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 9 Feb 2009 12:05:47 -0800 Subject: [PATCH 1508/4982] x86: add mp_find_ioapic_pin Add mp_find_ioapic_pin() to find an IO APIC's specific pin from a GSI, and use this function within acpi/boot. Make it non-static so other code can use it too. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/mpspec.h | 1 + arch/x86/kernel/acpi/boot.c | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h index b59371a312f..5916c8df09d 100644 --- a/arch/x86/include/asm/mpspec.h +++ b/arch/x86/include/asm/mpspec.h @@ -78,6 +78,7 @@ extern int acpi_probe_gsi(void); extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin, u32 gsi, int triggering, int polarity); extern int mp_find_ioapic(int gsi); +extern int mp_find_ioapic_pin(int ioapic, int gsi); #else static inline int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin, diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 068b900f4b0..bba162c81d5 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -887,6 +887,16 @@ int mp_find_ioapic(int gsi) return -1; } +int mp_find_ioapic_pin(int ioapic, int gsi) +{ + if (WARN_ON(ioapic == -1)) + return -1; + if (WARN_ON(gsi > mp_ioapic_routing[ioapic].gsi_end)) + return -1; + + return gsi - mp_ioapic_routing[ioapic].gsi_base; +} + static u8 __init uniq_ioapic_id(u8 id) { #ifdef CONFIG_X86_32 @@ -1022,7 +1032,7 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) ioapic = mp_find_ioapic(gsi); if (ioapic < 0) return; - pin = gsi - mp_ioapic_routing[ioapic].gsi_base; + pin = mp_find_ioapic_pin(ioapic, gsi); /* * TBD: This check is for faulty timer entries, where the override @@ -1142,7 +1152,7 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity) return gsi; } - ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base; + ioapic_pin = mp_find_ioapic_pin(ioapic, gsi); #ifdef CONFIG_X86_32 if (ioapic_renumber_irq) @@ -1231,7 +1241,7 @@ int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin, mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3); ioapic = mp_find_ioapic(gsi); mp_irq.dstapic = mp_ioapic_routing[ioapic].apic_id; - mp_irq.dstirq = gsi - mp_ioapic_routing[ioapic].gsi_base; + mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi); save_mp_irq(&mp_irq); #endif -- GitLab From ca97ab90164c7b978abf9d82dc82d6dc2cbac4a0 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 9 Feb 2009 12:05:47 -0800 Subject: [PATCH 1509/4982] x86: unstatic ioapic entry funcs Unstatic ioapic_write_entry and setup_ioapic_entry functions so that the Xen code can do its own ioapic routing setup. Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/io_apic.h | 6 ++++++ arch/x86/kernel/io_apic.c | 10 +++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index 309d0e23193..59cb4a1317b 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h @@ -169,6 +169,12 @@ extern void reinit_intr_remapped_IO_APIC(int); extern void probe_nr_irqs_gsi(void); +extern int setup_ioapic_entry(int apic, int irq, + struct IO_APIC_route_entry *entry, + unsigned int destination, int trigger, + int polarity, int vector); +extern void ioapic_write_entry(int apic, int pin, + struct IO_APIC_route_entry e); #else /* !CONFIG_X86_IO_APIC */ #define io_apic_assign_pci_irqs 0 static const int timer_through_8259 = 0; diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 56e51eb551a..7248ca11bdc 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -486,7 +486,7 @@ __ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) io_apic_write(apic, 0x10 + 2*pin, eu.w1); } -static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) +void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) { unsigned long flags; spin_lock_irqsave(&ioapic_lock, flags); @@ -1478,10 +1478,10 @@ static void ioapic_register_intr(int irq, struct irq_desc *desc, unsigned long t handle_edge_irq, "edge"); } -static int setup_ioapic_entry(int apic_id, int irq, - struct IO_APIC_route_entry *entry, - unsigned int destination, int trigger, - int polarity, int vector) +int setup_ioapic_entry(int apic_id, int irq, + struct IO_APIC_route_entry *entry, + unsigned int destination, int trigger, + int polarity, int vector) { /* * add it to the IO-APIC irq-routing table: -- GitLab From bf56957d176c279175464f385f3eb03d65819328 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Mon, 9 Feb 2009 12:05:48 -0800 Subject: [PATCH 1510/4982] xen: expose enable_IO_APIC for 32-bit enable_IO_APIC() is defined for both 32- and 64-bit x86, so it should be declared for both. Signed-off-by: Ian Campbell Signed-off-by: Jeremy Fitzhardinge --- arch/x86/include/asm/hw_irq.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index 1b82781b898..370e1c83bb4 100644 --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h @@ -65,9 +65,7 @@ extern void disable_IO_APIC(void); extern int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn); extern void setup_ioapic_dest(void); -#ifdef CONFIG_X86_64 extern void enable_IO_APIC(void); -#endif /* Statistics */ extern atomic_t irq_err_count; -- GitLab From 6cd61c0baa8bce32271226198b46c67a7a05d108 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 9 Feb 2009 22:17:39 +0900 Subject: [PATCH 1511/4982] elf: add ELF_CORE_COPY_KERNEL_REGS() ELF core dump is used for both user land core dump and kernel crash dump. Depending on architecture, register might need to be accessed differently for userland and kernel. Allow architectures to define ELF_CORE_COPY_KERNEL_REGS() and use different operation for kernel register dump. Signed-off-by: Tejun Heo Signed-off-by: Ingo Molnar --- include/linux/elfcore.h | 9 +++++++++ kernel/kexec.c | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/linux/elfcore.h b/include/linux/elfcore.h index 5ca54d77079..7605c5e9589 100644 --- a/include/linux/elfcore.h +++ b/include/linux/elfcore.h @@ -111,6 +111,15 @@ static inline void elf_core_copy_regs(elf_gregset_t *elfregs, struct pt_regs *re #endif } +static inline void elf_core_copy_kernel_regs(elf_gregset_t *elfregs, struct pt_regs *regs) +{ +#ifdef ELF_CORE_COPY_KERNEL_REGS + ELF_CORE_COPY_KERNEL_REGS((*elfregs), regs); +#else + elf_core_copy_regs(elfregs, regs); +#endif +} + static inline int elf_core_copy_task_regs(struct task_struct *t, elf_gregset_t* elfregs) { #ifdef ELF_CORE_COPY_TASK_REGS diff --git a/kernel/kexec.c b/kernel/kexec.c index 8a6d7b08864..795e7b67a22 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -1130,7 +1130,7 @@ void crash_save_cpu(struct pt_regs *regs, int cpu) return; memset(&prstatus, 0, sizeof(prstatus)); prstatus.pr_pid = current->pid; - elf_core_copy_regs(&prstatus.pr_reg, regs); + elf_core_copy_kernel_regs(&prstatus.pr_reg, regs); buf = append_elf_note(buf, KEXEC_CORE_NOTE_NAME, NT_PRSTATUS, &prstatus, sizeof(prstatus)); final_note(buf); -- GitLab From 76397f72fb9f4c9a96dfe05462887811c81b0e17 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 9 Feb 2009 22:17:39 +0900 Subject: [PATCH 1512/4982] x86: stackprotector.h misc update Impact: misc udpate * wrap content with CONFIG_CC_STACK_PROTECTOR so that other arch files can include it directly * add missing includes This will help future changes. Signed-off-by: Tejun Heo Signed-off-by: Ingo Molnar --- arch/x86/include/asm/stackprotector.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/stackprotector.h b/arch/x86/include/asm/stackprotector.h index 36a700acaf2..ee275e9f48a 100644 --- a/arch/x86/include/asm/stackprotector.h +++ b/arch/x86/include/asm/stackprotector.h @@ -1,8 +1,12 @@ #ifndef _ASM_STACKPROTECTOR_H #define _ASM_STACKPROTECTOR_H 1 +#ifdef CONFIG_CC_STACKPROTECTOR + #include #include +#include +#include /* * Initialize the stackprotector canary value. @@ -35,4 +39,5 @@ static __always_inline void boot_init_stack_canary(void) percpu_write(irq_stack_union.stack_canary, canary); } -#endif +#endif /* CC_STACKPROTECTOR */ +#endif /* _ASM_STACKPROTECTOR_H */ -- GitLab From 5d707e9c8ef2a3596ed5c975c6ff05cec890c2b4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 9 Feb 2009 22:17:39 +0900 Subject: [PATCH 1513/4982] stackprotector: update make rules Impact: no default -fno-stack-protector if stackp is enabled, cleanup Stackprotector make rules had the following problems. * cc support test and warning are scattered across makefile and kernel/panic.c. * -fno-stack-protector was always added regardless of configuration. Update such that cc support test and warning are contained in makefile and -fno-stack-protector is added iff stackp is turned off. While at it, prepare for 32bit support. Signed-off-by: Tejun Heo Signed-off-by: Ingo Molnar --- Makefile | 3 ++- arch/x86/Makefile | 17 ++++++++++------- kernel/panic.c | 4 ---- scripts/gcc-x86_64-has-stack-protector.sh | 4 +++- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index 681c1d23b4d..77a006dae2d 100644 --- a/Makefile +++ b/Makefile @@ -532,8 +532,9 @@ KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN}) endif # Force gcc to behave correct even for buggy distributions -# Arch Makefiles may override this setting +ifndef CONFIG_CC_STACKPROTECTOR KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector) +endif ifdef CONFIG_FRAME_POINTER KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls diff --git a/arch/x86/Makefile b/arch/x86/Makefile index cacee981d16..ab48ab497e5 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -70,14 +70,17 @@ else # this works around some issues with generating unwind tables in older gccs # newer gccs do it by default KBUILD_CFLAGS += -maccumulate-outgoing-args +endif - stackp := $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh - stackp-$(CONFIG_CC_STACKPROTECTOR) := $(shell $(stackp) \ - "$(CC)" "-fstack-protector -DGCC_HAS_SP" ) - stackp-$(CONFIG_CC_STACKPROTECTOR_ALL) += $(shell $(stackp) \ - "$(CC)" -fstack-protector-all ) - - KBUILD_CFLAGS += $(stackp-y) +ifdef CONFIG_CC_STACKPROTECTOR + cc_has_sp := $(srctree)/scripts/gcc-x86_$(BITS)-has-stack-protector.sh + ifeq ($(shell $(CONFIG_SHELL) $(cc_has_sp) $(CC)),y) + stackp-y := -fstack-protector + stackp-$(CONFIG_CC_STACKPROTECTOR_ALL) += -fstack-protector-all + KBUILD_CFLAGS += $(stackp-y) + else + $(warning stack protector enabled but no compiler support) + endif endif # Stackpointer is addressed different for 32 bit and 64 bit x86 diff --git a/kernel/panic.c b/kernel/panic.c index 33cab3de176..32fe4eff1b8 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -359,10 +359,6 @@ EXPORT_SYMBOL(warn_slowpath); #ifdef CONFIG_CC_STACKPROTECTOR -#ifndef GCC_HAS_SP -#warning You have selected the CONFIG_CC_STACKPROTECTOR option, but the gcc used does not support this. -#endif - /* * Called when gcc's -fstack-protector feature is used, and * gcc detects corruption of the on-stack canary value diff --git a/scripts/gcc-x86_64-has-stack-protector.sh b/scripts/gcc-x86_64-has-stack-protector.sh index 325c0a1b03b..2d69fcdc560 100644 --- a/scripts/gcc-x86_64-has-stack-protector.sh +++ b/scripts/gcc-x86_64-has-stack-protector.sh @@ -2,5 +2,7 @@ echo "int foo(void) { char X[200]; return 3; }" | $1 -S -xc -c -O0 -mcmodel=kernel -fstack-protector - -o - 2> /dev/null | grep -q "%gs" if [ "$?" -eq "0" ] ; then - echo $2 + echo y +else + echo n fi -- GitLab From d627ded5ab2f7818154d57369e3a8cdb40db2569 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 9 Feb 2009 22:17:40 +0900 Subject: [PATCH 1514/4982] x86: no stack protector for vdso Impact: avoid crash on vsyscall Signed-off-by: Tejun Heo Signed-off-by: Ingo Molnar --- arch/x86/vdso/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile index 4d6ef0a336d..16a9020c8f1 100644 --- a/arch/x86/vdso/Makefile +++ b/arch/x86/vdso/Makefile @@ -38,7 +38,7 @@ $(obj)/%.so: $(obj)/%.so.dbg FORCE $(call if_changed,objcopy) CFL := $(PROFILING) -mcmodel=small -fPIC -O2 -fasynchronous-unwind-tables -m64 \ - $(filter -g%,$(KBUILD_CFLAGS)) + $(filter -g%,$(KBUILD_CFLAGS)) $(call cc-option, -fno-stack-protector) $(vobjs): KBUILD_CFLAGS += $(CFL) -- GitLab From f0d96110f9fd98a1a22e03b8adba69508843d910 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 9 Feb 2009 22:17:40 +0900 Subject: [PATCH 1515/4982] x86: use asm .macro instead of cpp #define in entry_32.S Impact: cleanup Use .macro instead of cpp #define where approriate. This cleans up code and will ease future changes. Signed-off-by: Tejun Heo Signed-off-by: Ingo Molnar --- arch/x86/kernel/entry_32.S | 293 +++++++++++++++++++------------------ 1 file changed, 151 insertions(+), 142 deletions(-) diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index a0b91aac72a..c461925d3b6 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S @@ -101,121 +101,127 @@ #define resume_userspace_sig resume_userspace #endif -#define SAVE_ALL \ - cld; \ - pushl %fs; \ - CFI_ADJUST_CFA_OFFSET 4;\ - /*CFI_REL_OFFSET fs, 0;*/\ - pushl %es; \ - CFI_ADJUST_CFA_OFFSET 4;\ - /*CFI_REL_OFFSET es, 0;*/\ - pushl %ds; \ - CFI_ADJUST_CFA_OFFSET 4;\ - /*CFI_REL_OFFSET ds, 0;*/\ - pushl %eax; \ - CFI_ADJUST_CFA_OFFSET 4;\ - CFI_REL_OFFSET eax, 0;\ - pushl %ebp; \ - CFI_ADJUST_CFA_OFFSET 4;\ - CFI_REL_OFFSET ebp, 0;\ - pushl %edi; \ - CFI_ADJUST_CFA_OFFSET 4;\ - CFI_REL_OFFSET edi, 0;\ - pushl %esi; \ - CFI_ADJUST_CFA_OFFSET 4;\ - CFI_REL_OFFSET esi, 0;\ - pushl %edx; \ - CFI_ADJUST_CFA_OFFSET 4;\ - CFI_REL_OFFSET edx, 0;\ - pushl %ecx; \ - CFI_ADJUST_CFA_OFFSET 4;\ - CFI_REL_OFFSET ecx, 0;\ - pushl %ebx; \ - CFI_ADJUST_CFA_OFFSET 4;\ - CFI_REL_OFFSET ebx, 0;\ - movl $(__USER_DS), %edx; \ - movl %edx, %ds; \ - movl %edx, %es; \ - movl $(__KERNEL_PERCPU), %edx; \ +.macro SAVE_ALL + cld + pushl %fs + CFI_ADJUST_CFA_OFFSET 4 + /*CFI_REL_OFFSET fs, 0;*/ + pushl %es + CFI_ADJUST_CFA_OFFSET 4 + /*CFI_REL_OFFSET es, 0;*/ + pushl %ds + CFI_ADJUST_CFA_OFFSET 4 + /*CFI_REL_OFFSET ds, 0;*/ + pushl %eax + CFI_ADJUST_CFA_OFFSET 4 + CFI_REL_OFFSET eax, 0 + pushl %ebp + CFI_ADJUST_CFA_OFFSET 4 + CFI_REL_OFFSET ebp, 0 + pushl %edi + CFI_ADJUST_CFA_OFFSET 4 + CFI_REL_OFFSET edi, 0 + pushl %esi + CFI_ADJUST_CFA_OFFSET 4 + CFI_REL_OFFSET esi, 0 + pushl %edx + CFI_ADJUST_CFA_OFFSET 4 + CFI_REL_OFFSET edx, 0 + pushl %ecx + CFI_ADJUST_CFA_OFFSET 4 + CFI_REL_OFFSET ecx, 0 + pushl %ebx + CFI_ADJUST_CFA_OFFSET 4 + CFI_REL_OFFSET ebx, 0 + movl $(__USER_DS), %edx + movl %edx, %ds + movl %edx, %es + movl $(__KERNEL_PERCPU), %edx movl %edx, %fs +.endm -#define RESTORE_INT_REGS \ - popl %ebx; \ - CFI_ADJUST_CFA_OFFSET -4;\ - CFI_RESTORE ebx;\ - popl %ecx; \ - CFI_ADJUST_CFA_OFFSET -4;\ - CFI_RESTORE ecx;\ - popl %edx; \ - CFI_ADJUST_CFA_OFFSET -4;\ - CFI_RESTORE edx;\ - popl %esi; \ - CFI_ADJUST_CFA_OFFSET -4;\ - CFI_RESTORE esi;\ - popl %edi; \ - CFI_ADJUST_CFA_OFFSET -4;\ - CFI_RESTORE edi;\ - popl %ebp; \ - CFI_ADJUST_CFA_OFFSET -4;\ - CFI_RESTORE ebp;\ - popl %eax; \ - CFI_ADJUST_CFA_OFFSET -4;\ +.macro RESTORE_INT_REGS + popl %ebx + CFI_ADJUST_CFA_OFFSET -4 + CFI_RESTORE ebx + popl %ecx + CFI_ADJUST_CFA_OFFSET -4 + CFI_RESTORE ecx + popl %edx + CFI_ADJUST_CFA_OFFSET -4 + CFI_RESTORE edx + popl %esi + CFI_ADJUST_CFA_OFFSET -4 + CFI_RESTORE esi + popl %edi + CFI_ADJUST_CFA_OFFSET -4 + CFI_RESTORE edi + popl %ebp + CFI_ADJUST_CFA_OFFSET -4 + CFI_RESTORE ebp + popl %eax + CFI_ADJUST_CFA_OFFSET -4 CFI_RESTORE eax +.endm -#define RESTORE_REGS \ - RESTORE_INT_REGS; \ -1: popl %ds; \ - CFI_ADJUST_CFA_OFFSET -4;\ - /*CFI_RESTORE ds;*/\ -2: popl %es; \ - CFI_ADJUST_CFA_OFFSET -4;\ - /*CFI_RESTORE es;*/\ -3: popl %fs; \ - CFI_ADJUST_CFA_OFFSET -4;\ - /*CFI_RESTORE fs;*/\ -.pushsection .fixup,"ax"; \ -4: movl $0,(%esp); \ - jmp 1b; \ -5: movl $0,(%esp); \ - jmp 2b; \ -6: movl $0,(%esp); \ - jmp 3b; \ -.section __ex_table,"a";\ - .align 4; \ - .long 1b,4b; \ - .long 2b,5b; \ - .long 3b,6b; \ +.macro RESTORE_REGS + RESTORE_INT_REGS +1: popl %ds + CFI_ADJUST_CFA_OFFSET -4 + /*CFI_RESTORE ds;*/ +2: popl %es + CFI_ADJUST_CFA_OFFSET -4 + /*CFI_RESTORE es;*/ +3: popl %fs + CFI_ADJUST_CFA_OFFSET -4 + /*CFI_RESTORE fs;*/ +.pushsection .fixup, "ax" +4: movl $0, (%esp) + jmp 1b +5: movl $0, (%esp) + jmp 2b +6: movl $0, (%esp) + jmp 3b +.section __ex_table, "a" + .align 4 + .long 1b, 4b + .long 2b, 5b + .long 3b, 6b .popsection +.endm -#define RING0_INT_FRAME \ - CFI_STARTPROC simple;\ - CFI_SIGNAL_FRAME;\ - CFI_DEF_CFA esp, 3*4;\ - /*CFI_OFFSET cs, -2*4;*/\ +.macro RING0_INT_FRAME + CFI_STARTPROC simple + CFI_SIGNAL_FRAME + CFI_DEF_CFA esp, 3*4 + /*CFI_OFFSET cs, -2*4;*/ CFI_OFFSET eip, -3*4 +.endm -#define RING0_EC_FRAME \ - CFI_STARTPROC simple;\ - CFI_SIGNAL_FRAME;\ - CFI_DEF_CFA esp, 4*4;\ - /*CFI_OFFSET cs, -2*4;*/\ +.macro RING0_EC_FRAME + CFI_STARTPROC simple + CFI_SIGNAL_FRAME + CFI_DEF_CFA esp, 4*4 + /*CFI_OFFSET cs, -2*4;*/ CFI_OFFSET eip, -3*4 +.endm -#define RING0_PTREGS_FRAME \ - CFI_STARTPROC simple;\ - CFI_SIGNAL_FRAME;\ - CFI_DEF_CFA esp, PT_OLDESP-PT_EBX;\ - /*CFI_OFFSET cs, PT_CS-PT_OLDESP;*/\ - CFI_OFFSET eip, PT_EIP-PT_OLDESP;\ - /*CFI_OFFSET es, PT_ES-PT_OLDESP;*/\ - /*CFI_OFFSET ds, PT_DS-PT_OLDESP;*/\ - CFI_OFFSET eax, PT_EAX-PT_OLDESP;\ - CFI_OFFSET ebp, PT_EBP-PT_OLDESP;\ - CFI_OFFSET edi, PT_EDI-PT_OLDESP;\ - CFI_OFFSET esi, PT_ESI-PT_OLDESP;\ - CFI_OFFSET edx, PT_EDX-PT_OLDESP;\ - CFI_OFFSET ecx, PT_ECX-PT_OLDESP;\ +.macro RING0_PTREGS_FRAME + CFI_STARTPROC simple + CFI_SIGNAL_FRAME + CFI_DEF_CFA esp, PT_OLDESP-PT_EBX + /*CFI_OFFSET cs, PT_CS-PT_OLDESP;*/ + CFI_OFFSET eip, PT_EIP-PT_OLDESP + /*CFI_OFFSET es, PT_ES-PT_OLDESP;*/ + /*CFI_OFFSET ds, PT_DS-PT_OLDESP;*/ + CFI_OFFSET eax, PT_EAX-PT_OLDESP + CFI_OFFSET ebp, PT_EBP-PT_OLDESP + CFI_OFFSET edi, PT_EDI-PT_OLDESP + CFI_OFFSET esi, PT_ESI-PT_OLDESP + CFI_OFFSET edx, PT_EDX-PT_OLDESP + CFI_OFFSET ecx, PT_ECX-PT_OLDESP CFI_OFFSET ebx, PT_EBX-PT_OLDESP +.endm ENTRY(ret_from_fork) CFI_STARTPROC @@ -595,28 +601,30 @@ syscall_badsys: END(syscall_badsys) CFI_ENDPROC -#define FIXUP_ESPFIX_STACK \ - /* since we are on a wrong stack, we cant make it a C code :( */ \ - PER_CPU(gdt_page, %ebx); \ - GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah); \ - addl %esp, %eax; \ - pushl $__KERNEL_DS; \ - CFI_ADJUST_CFA_OFFSET 4; \ - pushl %eax; \ - CFI_ADJUST_CFA_OFFSET 4; \ - lss (%esp), %esp; \ - CFI_ADJUST_CFA_OFFSET -8; -#define UNWIND_ESPFIX_STACK \ - movl %ss, %eax; \ - /* see if on espfix stack */ \ - cmpw $__ESPFIX_SS, %ax; \ - jne 27f; \ - movl $__KERNEL_DS, %eax; \ - movl %eax, %ds; \ - movl %eax, %es; \ - /* switch to normal stack */ \ - FIXUP_ESPFIX_STACK; \ -27:; +.macro FIXUP_ESPFIX_STACK + /* since we are on a wrong stack, we cant make it a C code :( */ + PER_CPU(gdt_page, %ebx) + GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah) + addl %esp, %eax + pushl $__KERNEL_DS + CFI_ADJUST_CFA_OFFSET 4 + pushl %eax + CFI_ADJUST_CFA_OFFSET 4 + lss (%esp), %esp + CFI_ADJUST_CFA_OFFSET -8 +.endm +.macro UNWIND_ESPFIX_STACK + movl %ss, %eax + /* see if on espfix stack */ + cmpw $__ESPFIX_SS, %ax + jne 27f + movl $__KERNEL_DS, %eax + movl %eax, %ds + movl %eax, %es + /* switch to normal stack */ + FIXUP_ESPFIX_STACK +27: +.endm /* * Build the entry stubs and pointer table with some assembler magic. @@ -1136,26 +1144,27 @@ END(page_fault) * by hand onto the new stack - while updating the return eip past * the instruction that would have done it for sysenter. */ -#define FIX_STACK(offset, ok, label) \ - cmpw $__KERNEL_CS,4(%esp); \ - jne ok; \ -label: \ - movl TSS_sysenter_sp0+offset(%esp),%esp; \ - CFI_DEF_CFA esp, 0; \ - CFI_UNDEFINED eip; \ - pushfl; \ - CFI_ADJUST_CFA_OFFSET 4; \ - pushl $__KERNEL_CS; \ - CFI_ADJUST_CFA_OFFSET 4; \ - pushl $sysenter_past_esp; \ - CFI_ADJUST_CFA_OFFSET 4; \ +.macro FIX_STACK offset ok label + cmpw $__KERNEL_CS, 4(%esp) + jne \ok +\label: + movl TSS_sysenter_sp0 + \offset(%esp), %esp + CFI_DEF_CFA esp, 0 + CFI_UNDEFINED eip + pushfl + CFI_ADJUST_CFA_OFFSET 4 + pushl $__KERNEL_CS + CFI_ADJUST_CFA_OFFSET 4 + pushl $sysenter_past_esp + CFI_ADJUST_CFA_OFFSET 4 CFI_REL_OFFSET eip, 0 +.endm ENTRY(debug) RING0_INT_FRAME cmpl $ia32_sysenter_target,(%esp) jne debug_stack_correct - FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn) + FIX_STACK 12, debug_stack_correct, debug_esp_fix_insn debug_stack_correct: pushl $-1 # mark this as an int CFI_ADJUST_CFA_OFFSET 4 @@ -1213,7 +1222,7 @@ nmi_stack_correct: nmi_stack_fixup: RING0_INT_FRAME - FIX_STACK(12,nmi_stack_correct, 1) + FIX_STACK 12, nmi_stack_correct, 1 jmp nmi_stack_correct nmi_debug_stack_check: @@ -1224,7 +1233,7 @@ nmi_debug_stack_check: jb nmi_stack_correct cmpl $debug_esp_fix_insn,(%esp) ja nmi_stack_correct - FIX_STACK(24,nmi_stack_correct, 1) + FIX_STACK 24, nmi_stack_correct, 1 jmp nmi_stack_correct nmi_espfix_stack: -- GitLab From d9a89a26e02ef9ed03f74a755a8b4d8f3a066622 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 9 Feb 2009 22:17:40 +0900 Subject: [PATCH 1516/4982] x86: add %gs accessors for x86_32 Impact: cleanup On x86_32, %gs is handled lazily. It's not saved and restored on kernel entry/exit but only when necessary which usually is during task switch but there are few other places. Currently, it's done by calling savesegment() and loadsegment() explicitly. Define get_user_gs(), set_user_gs() and task_user_gs() and use them instead. While at it, clean up register access macros in signal.c. This cleans up code a bit and will help future changes. Signed-off-by: Tejun Heo Signed-off-by: Ingo Molnar --- arch/x86/include/asm/a.out-core.h | 2 +- arch/x86/include/asm/elf.h | 2 +- arch/x86/include/asm/mmu_context.h | 2 +- arch/x86/include/asm/system.h | 9 +++++++ arch/x86/kernel/process_32.c | 6 ++--- arch/x86/kernel/ptrace.c | 14 +++++----- arch/x86/kernel/signal.c | 41 ++++++++++++------------------ arch/x86/kernel/vm86_32.c | 4 +-- arch/x86/math-emu/get_address.c | 6 ++--- 9 files changed, 41 insertions(+), 45 deletions(-) diff --git a/arch/x86/include/asm/a.out-core.h b/arch/x86/include/asm/a.out-core.h index 3c601f8224b..bb70e397aa8 100644 --- a/arch/x86/include/asm/a.out-core.h +++ b/arch/x86/include/asm/a.out-core.h @@ -55,7 +55,7 @@ static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump) dump->regs.ds = (u16)regs->ds; dump->regs.es = (u16)regs->es; dump->regs.fs = (u16)regs->fs; - savesegment(gs, dump->regs.gs); + dump->regs.gs = get_user_gs(regs); dump->regs.orig_ax = regs->orig_ax; dump->regs.ip = regs->ip; dump->regs.cs = (u16)regs->cs; diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h index f51a3ddde01..39b0aac1675 100644 --- a/arch/x86/include/asm/elf.h +++ b/arch/x86/include/asm/elf.h @@ -124,7 +124,7 @@ do { \ pr_reg[7] = regs->ds & 0xffff; \ pr_reg[8] = regs->es & 0xffff; \ pr_reg[9] = regs->fs & 0xffff; \ - savesegment(gs, pr_reg[10]); \ + pr_reg[10] = get_user_gs(regs); \ pr_reg[11] = regs->orig_ax; \ pr_reg[12] = regs->ip; \ pr_reg[13] = regs->cs & 0xffff; \ diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h index 52948df9cd1..4955165682c 100644 --- a/arch/x86/include/asm/mmu_context.h +++ b/arch/x86/include/asm/mmu_context.h @@ -79,7 +79,7 @@ do { \ #ifdef CONFIG_X86_32 #define deactivate_mm(tsk, mm) \ do { \ - loadsegment(gs, 0); \ + set_user_gs(task_pt_regs(tsk), 0); \ } while (0) #else #define deactivate_mm(tsk, mm) \ diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h index 2fcc70bc85f..70c74b8db87 100644 --- a/arch/x86/include/asm/system.h +++ b/arch/x86/include/asm/system.h @@ -182,6 +182,15 @@ extern void native_load_gs_index(unsigned); #define savesegment(seg, value) \ asm("mov %%" #seg ",%0":"=r" (value) : : "memory") +/* + * x86_32 user gs accessors. + */ +#ifdef CONFIG_X86_32 +#define get_user_gs(regs) (u16)({unsigned long v; savesegment(gs, v); v;}) +#define set_user_gs(regs, v) loadsegment(gs, (unsigned long)(v)) +#define task_user_gs(tsk) ((tsk)->thread.gs) +#endif + static inline unsigned long get_limit(unsigned long segment) { unsigned long __limit; diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 1a1ae8edc40..d58a340e1be 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -131,7 +131,7 @@ void __show_regs(struct pt_regs *regs, int all) if (user_mode_vm(regs)) { sp = regs->sp; ss = regs->ss & 0xffff; - savesegment(gs, gs); + gs = get_user_gs(regs); } else { sp = (unsigned long) (®s->sp); savesegment(ss, ss); @@ -304,7 +304,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, p->thread.ip = (unsigned long) ret_from_fork; - savesegment(gs, p->thread.gs); + task_user_gs(p) = get_user_gs(regs); tsk = current; if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) { @@ -342,7 +342,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, void start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) { - __asm__("movl %0, %%gs" : : "r"(0)); + set_user_gs(regs, 0); regs->fs = 0; set_fs(USER_DS); regs->ds = __USER_DS; diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 0a5df5f82fb..508b6b57d0c 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -90,9 +90,10 @@ static u16 get_segment_reg(struct task_struct *task, unsigned long offset) if (offset != offsetof(struct user_regs_struct, gs)) retval = *pt_regs_access(task_pt_regs(task), offset); else { - retval = task->thread.gs; if (task == current) - savesegment(gs, retval); + retval = get_user_gs(task_pt_regs(task)); + else + retval = task_user_gs(task); } return retval; } @@ -126,13 +127,10 @@ static int set_segment_reg(struct task_struct *task, break; case offsetof(struct user_regs_struct, gs): - task->thread.gs = value; if (task == current) - /* - * The user-mode %gs is not affected by - * kernel entry, so we must update the CPU. - */ - loadsegment(gs, value); + set_user_gs(task_pt_regs(task), value); + else + task_user_gs(task) = value; } return 0; diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 7fc78b01981..8562387c75a 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -50,27 +50,23 @@ # define FIX_EFLAGS __FIX_EFLAGS #endif -#define COPY(x) { \ - get_user_ex(regs->x, &sc->x); \ -} +#define COPY(x) do { \ + get_user_ex(regs->x, &sc->x); \ +} while (0) -#define COPY_SEG(seg) { \ - unsigned short tmp; \ - get_user_ex(tmp, &sc->seg); \ - regs->seg = tmp; \ -} +#define GET_SEG(seg) ({ \ + unsigned short tmp; \ + get_user_ex(tmp, &sc->seg); \ + tmp; \ +}) -#define COPY_SEG_CPL3(seg) { \ - unsigned short tmp; \ - get_user_ex(tmp, &sc->seg); \ - regs->seg = tmp | 3; \ -} +#define COPY_SEG(seg) do { \ + regs->seg = GET_SEG(seg); \ +} while (0) -#define GET_SEG(seg) { \ - unsigned short tmp; \ - get_user_ex(tmp, &sc->seg); \ - loadsegment(seg, tmp); \ -} +#define COPY_SEG_CPL3(seg) do { \ + regs->seg = GET_SEG(seg) | 3; \ +} while (0) static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, @@ -86,7 +82,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, get_user_try { #ifdef CONFIG_X86_32 - GET_SEG(gs); + set_user_gs(regs, GET_SEG(gs)); COPY_SEG(fs); COPY_SEG(es); COPY_SEG(ds); @@ -138,12 +134,7 @@ setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate, put_user_try { #ifdef CONFIG_X86_32 - { - unsigned int tmp; - - savesegment(gs, tmp); - put_user_ex(tmp, (unsigned int __user *)&sc->gs); - } + put_user_ex(get_user_gs(regs), (unsigned int __user *)&sc->gs); put_user_ex(regs->fs, (unsigned int __user *)&sc->fs); put_user_ex(regs->es, (unsigned int __user *)&sc->es); put_user_ex(regs->ds, (unsigned int __user *)&sc->ds); diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index 4eeb5cf9720..55ea30d2a3d 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c @@ -158,7 +158,7 @@ struct pt_regs *save_v86_state(struct kernel_vm86_regs *regs) ret = KVM86->regs32; ret->fs = current->thread.saved_fs; - loadsegment(gs, current->thread.saved_gs); + set_user_gs(ret, current->thread.saved_gs); return ret; } @@ -323,7 +323,7 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk info->regs32->ax = 0; tsk->thread.saved_sp0 = tsk->thread.sp0; tsk->thread.saved_fs = info->regs32->fs; - savesegment(gs, tsk->thread.saved_gs); + tsk->thread.saved_gs = get_user_gs(info->regs32); tss = &per_cpu(init_tss, get_cpu()); tsk->thread.sp0 = (unsigned long) &info->VM86_TSS_ESP0; diff --git a/arch/x86/math-emu/get_address.c b/arch/x86/math-emu/get_address.c index 420b3b6e391..6ef5e99380f 100644 --- a/arch/x86/math-emu/get_address.c +++ b/arch/x86/math-emu/get_address.c @@ -150,11 +150,9 @@ static long pm_address(u_char FPU_modrm, u_char segment, #endif /* PARANOID */ switch (segment) { - /* gs isn't used by the kernel, so it still has its - user-space value. */ case PREFIX_GS_ - 1: - /* N.B. - movl %seg, mem is a 2 byte write regardless of prefix */ - savesegment(gs, addr->selector); + /* user gs handling can be lazy, use special accessors */ + addr->selector = get_user_gs(FPU_info->regs); break; default: addr->selector = PM_REG_(segment); -- GitLab From ccbeed3a05908d201b47b6c3dd1a373138bba566 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 9 Feb 2009 22:17:40 +0900 Subject: [PATCH 1517/4982] x86: make lazy %gs optional on x86_32 Impact: pt_regs changed, lazy gs handling made optional, add slight overhead to SAVE_ALL, simplifies error_code path a bit On x86_32, %gs hasn't been used by kernel and handled lazily. pt_regs doesn't have place for it and gs is saved/loaded only when necessary. In preparation for stack protector support, this patch makes lazy %gs handling optional by doing the followings. * Add CONFIG_X86_32_LAZY_GS and place for gs in pt_regs. * Save and restore %gs along with other registers in entry_32.S unless LAZY_GS. Note that this unfortunately adds "pushl $0" on SAVE_ALL even when LAZY_GS. However, it adds no overhead to common exit path and simplifies entry path with error code. * Define different user_gs accessors depending on LAZY_GS and add lazy_save_gs() and lazy_load_gs() which are noop if !LAZY_GS. The lazy_*_gs() ops are used to save, load and clear %gs lazily. * Define ELF_CORE_COPY_KERNEL_REGS() which always read %gs directly. xen and lguest changes need to be verified. Signed-off-by: Tejun Heo Cc: Jeremy Fitzhardinge Cc: Rusty Russell Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 4 + arch/x86/include/asm/elf.h | 15 +++- arch/x86/include/asm/mmu_context.h | 2 +- arch/x86/include/asm/ptrace.h | 4 +- arch/x86/include/asm/system.h | 12 ++- arch/x86/kernel/asm-offsets_32.c | 1 + arch/x86/kernel/entry_32.S | 132 ++++++++++++++++++++++++----- arch/x86/kernel/process_32.c | 4 +- arch/x86/kernel/ptrace.c | 5 +- arch/x86/lguest/boot.c | 2 +- arch/x86/xen/enlighten.c | 17 ++-- 11 files changed, 158 insertions(+), 40 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 5c8e353c112..5bcdede71ba 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -207,6 +207,10 @@ config X86_TRAMPOLINE depends on X86_SMP || (X86_VOYAGER && SMP) || (64BIT && ACPI_SLEEP) default y +config X86_32_LAZY_GS + def_bool y + depends on X86_32 + config KTIME_SCALAR def_bool X86_32 source "init/Kconfig" diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h index 39b0aac1675..83c1bc8d2e8 100644 --- a/arch/x86/include/asm/elf.h +++ b/arch/x86/include/asm/elf.h @@ -112,7 +112,7 @@ extern unsigned int vdso_enabled; * now struct_user_regs, they are different) */ -#define ELF_CORE_COPY_REGS(pr_reg, regs) \ +#define ELF_CORE_COPY_REGS_COMMON(pr_reg, regs) \ do { \ pr_reg[0] = regs->bx; \ pr_reg[1] = regs->cx; \ @@ -124,7 +124,6 @@ do { \ pr_reg[7] = regs->ds & 0xffff; \ pr_reg[8] = regs->es & 0xffff; \ pr_reg[9] = regs->fs & 0xffff; \ - pr_reg[10] = get_user_gs(regs); \ pr_reg[11] = regs->orig_ax; \ pr_reg[12] = regs->ip; \ pr_reg[13] = regs->cs & 0xffff; \ @@ -133,6 +132,18 @@ do { \ pr_reg[16] = regs->ss & 0xffff; \ } while (0); +#define ELF_CORE_COPY_REGS(pr_reg, regs) \ +do { \ + ELF_CORE_COPY_REGS_COMMON(pr_reg, regs);\ + pr_reg[10] = get_user_gs(regs); \ +} while (0); + +#define ELF_CORE_COPY_KERNEL_REGS(pr_reg, regs) \ +do { \ + ELF_CORE_COPY_REGS_COMMON(pr_reg, regs);\ + savesegment(gs, pr_reg[10]); \ +} while (0); + #define ELF_PLATFORM (utsname()->machine) #define set_personality_64bit() do { } while (0) diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h index 4955165682c..f923203dc39 100644 --- a/arch/x86/include/asm/mmu_context.h +++ b/arch/x86/include/asm/mmu_context.h @@ -79,7 +79,7 @@ do { \ #ifdef CONFIG_X86_32 #define deactivate_mm(tsk, mm) \ do { \ - set_user_gs(task_pt_regs(tsk), 0); \ + lazy_load_gs(0); \ } while (0) #else #define deactivate_mm(tsk, mm) \ diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h index 6d34d954c22..e304b66abee 100644 --- a/arch/x86/include/asm/ptrace.h +++ b/arch/x86/include/asm/ptrace.h @@ -28,7 +28,7 @@ struct pt_regs { int xds; int xes; int xfs; - /* int gs; */ + int xgs; long orig_eax; long eip; int xcs; @@ -50,7 +50,7 @@ struct pt_regs { unsigned long ds; unsigned long es; unsigned long fs; - /* int gs; */ + unsigned long gs; unsigned long orig_ax; unsigned long ip; unsigned long cs; diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h index 70c74b8db87..79b98e5b96f 100644 --- a/arch/x86/include/asm/system.h +++ b/arch/x86/include/asm/system.h @@ -186,10 +186,20 @@ extern void native_load_gs_index(unsigned); * x86_32 user gs accessors. */ #ifdef CONFIG_X86_32 +#ifdef CONFIG_X86_32_LAZY_GS #define get_user_gs(regs) (u16)({unsigned long v; savesegment(gs, v); v;}) #define set_user_gs(regs, v) loadsegment(gs, (unsigned long)(v)) #define task_user_gs(tsk) ((tsk)->thread.gs) -#endif +#define lazy_save_gs(v) savesegment(gs, (v)) +#define lazy_load_gs(v) loadsegment(gs, (v)) +#else /* X86_32_LAZY_GS */ +#define get_user_gs(regs) (u16)((regs)->gs) +#define set_user_gs(regs, v) do { (regs)->gs = (v); } while (0) +#define task_user_gs(tsk) (task_pt_regs(tsk)->gs) +#define lazy_save_gs(v) do { } while (0) +#define lazy_load_gs(v) do { } while (0) +#endif /* X86_32_LAZY_GS */ +#endif /* X86_32 */ static inline unsigned long get_limit(unsigned long segment) { diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c index ee4df08feee..fbf2f33e308 100644 --- a/arch/x86/kernel/asm-offsets_32.c +++ b/arch/x86/kernel/asm-offsets_32.c @@ -75,6 +75,7 @@ void foo(void) OFFSET(PT_DS, pt_regs, ds); OFFSET(PT_ES, pt_regs, es); OFFSET(PT_FS, pt_regs, fs); + OFFSET(PT_GS, pt_regs, gs); OFFSET(PT_ORIG_EAX, pt_regs, orig_ax); OFFSET(PT_EIP, pt_regs, ip); OFFSET(PT_CS, pt_regs, cs); diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index c461925d3b6..82e6868bee4 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S @@ -30,12 +30,13 @@ * 1C(%esp) - %ds * 20(%esp) - %es * 24(%esp) - %fs - * 28(%esp) - orig_eax - * 2C(%esp) - %eip - * 30(%esp) - %cs - * 34(%esp) - %eflags - * 38(%esp) - %oldesp - * 3C(%esp) - %oldss + * 28(%esp) - %gs saved iff !CONFIG_X86_32_LAZY_GS + * 2C(%esp) - orig_eax + * 30(%esp) - %eip + * 34(%esp) - %cs + * 38(%esp) - %eflags + * 3C(%esp) - %oldesp + * 40(%esp) - %oldss * * "current" is in register %ebx during any slow entries. */ @@ -101,8 +102,99 @@ #define resume_userspace_sig resume_userspace #endif +/* + * User gs save/restore + * + * %gs is used for userland TLS and kernel only uses it for stack + * canary which is required to be at %gs:20 by gcc. Read the comment + * at the top of stackprotector.h for more info. + * + * Local labels 98 and 99 are used. + */ +#ifdef CONFIG_X86_32_LAZY_GS + + /* unfortunately push/pop can't be no-op */ +.macro PUSH_GS + pushl $0 + CFI_ADJUST_CFA_OFFSET 4 +.endm +.macro POP_GS pop=0 + addl $(4 + \pop), %esp + CFI_ADJUST_CFA_OFFSET -(4 + \pop) +.endm +.macro POP_GS_EX +.endm + + /* all the rest are no-op */ +.macro PTGS_TO_GS +.endm +.macro PTGS_TO_GS_EX +.endm +.macro GS_TO_REG reg +.endm +.macro REG_TO_PTGS reg +.endm +.macro SET_KERNEL_GS reg +.endm + +#else /* CONFIG_X86_32_LAZY_GS */ + +.macro PUSH_GS + pushl %gs + CFI_ADJUST_CFA_OFFSET 4 + /*CFI_REL_OFFSET gs, 0*/ +.endm + +.macro POP_GS pop=0 +98: popl %gs + CFI_ADJUST_CFA_OFFSET -4 + /*CFI_RESTORE gs*/ + .if \pop <> 0 + add $\pop, %esp + CFI_ADJUST_CFA_OFFSET -\pop + .endif +.endm +.macro POP_GS_EX +.pushsection .fixup, "ax" +99: movl $0, (%esp) + jmp 98b +.section __ex_table, "a" + .align 4 + .long 98b, 99b +.popsection +.endm + +.macro PTGS_TO_GS +98: mov PT_GS(%esp), %gs +.endm +.macro PTGS_TO_GS_EX +.pushsection .fixup, "ax" +99: movl $0, PT_GS(%esp) + jmp 98b +.section __ex_table, "a" + .align 4 + .long 98b, 99b +.popsection +.endm + +.macro GS_TO_REG reg + movl %gs, \reg + /*CFI_REGISTER gs, \reg*/ +.endm +.macro REG_TO_PTGS reg + movl \reg, PT_GS(%esp) + /*CFI_REL_OFFSET gs, PT_GS*/ +.endm +.macro SET_KERNEL_GS reg + xorl \reg, \reg + movl \reg, %gs +.endm + +#endif /* CONFIG_X86_32_LAZY_GS */ + .macro SAVE_ALL cld + PUSH_GS pushl %fs CFI_ADJUST_CFA_OFFSET 4 /*CFI_REL_OFFSET fs, 0;*/ @@ -138,6 +230,7 @@ movl %edx, %es movl $(__KERNEL_PERCPU), %edx movl %edx, %fs + SET_KERNEL_GS %edx .endm .macro RESTORE_INT_REGS @@ -164,7 +257,7 @@ CFI_RESTORE eax .endm -.macro RESTORE_REGS +.macro RESTORE_REGS pop=0 RESTORE_INT_REGS 1: popl %ds CFI_ADJUST_CFA_OFFSET -4 @@ -175,6 +268,7 @@ 3: popl %fs CFI_ADJUST_CFA_OFFSET -4 /*CFI_RESTORE fs;*/ + POP_GS \pop .pushsection .fixup, "ax" 4: movl $0, (%esp) jmp 1b @@ -188,6 +282,7 @@ .long 2b, 5b .long 3b, 6b .popsection + POP_GS_EX .endm .macro RING0_INT_FRAME @@ -368,6 +463,7 @@ sysenter_exit: xorl %ebp,%ebp TRACE_IRQS_ON 1: mov PT_FS(%esp), %fs + PTGS_TO_GS ENABLE_INTERRUPTS_SYSEXIT #ifdef CONFIG_AUDITSYSCALL @@ -416,6 +512,7 @@ sysexit_audit: .align 4 .long 1b,2b .popsection + PTGS_TO_GS_EX ENDPROC(ia32_sysenter_target) # system call handler stub @@ -458,8 +555,7 @@ restore_all: restore_nocheck: TRACE_IRQS_IRET restore_nocheck_notrace: - RESTORE_REGS - addl $4, %esp # skip orig_eax/error_code + RESTORE_REGS 4 # skip orig_eax/error_code CFI_ADJUST_CFA_OFFSET -4 irq_return: INTERRUPT_RETURN @@ -1078,7 +1174,10 @@ ENTRY(page_fault) CFI_ADJUST_CFA_OFFSET 4 ALIGN error_code: - /* the function address is in %fs's slot on the stack */ + /* the function address is in %gs's slot on the stack */ + pushl %fs + CFI_ADJUST_CFA_OFFSET 4 + /*CFI_REL_OFFSET fs, 0*/ pushl %es CFI_ADJUST_CFA_OFFSET 4 /*CFI_REL_OFFSET es, 0*/ @@ -1107,20 +1206,15 @@ error_code: CFI_ADJUST_CFA_OFFSET 4 CFI_REL_OFFSET ebx, 0 cld - pushl %fs - CFI_ADJUST_CFA_OFFSET 4 - /*CFI_REL_OFFSET fs, 0*/ movl $(__KERNEL_PERCPU), %ecx movl %ecx, %fs UNWIND_ESPFIX_STACK - popl %ecx - CFI_ADJUST_CFA_OFFSET -4 - /*CFI_REGISTER es, ecx*/ - movl PT_FS(%esp), %edi # get the function address + GS_TO_REG %ecx + movl PT_GS(%esp), %edi # get the function address movl PT_ORIG_EAX(%esp), %edx # get the error code movl $-1, PT_ORIG_EAX(%esp) # no syscall to restart - mov %ecx, PT_FS(%esp) - /*CFI_REL_OFFSET fs, ES*/ + REG_TO_PTGS %ecx + SET_KERNEL_GS %ecx movl $(__USER_DS), %ecx movl %ecx, %ds movl %ecx, %es diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index d58a340e1be..86122fa2a1b 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -539,7 +539,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) * used %fs or %gs (it does not today), or if the kernel is * running inside of a hypervisor layer. */ - savesegment(gs, prev->gs); + lazy_save_gs(prev->gs); /* * Load the per-thread Thread-Local Storage descriptor. @@ -585,7 +585,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) * Restore %gs if needed (which is common) */ if (prev->gs | next->gs) - loadsegment(gs, next->gs); + lazy_load_gs(next->gs); percpu_write(current_task, next_p); diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 508b6b57d0c..7ec39ab37a2 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -75,10 +75,7 @@ static inline bool invalid_selector(u16 value) static unsigned long *pt_regs_access(struct pt_regs *regs, unsigned long regno) { BUILD_BUG_ON(offsetof(struct pt_regs, bx) != 0); - regno >>= 2; - if (regno > FS) - --regno; - return ®s->bx + regno; + return ®s->bx + (regno >> 2); } static u16 get_segment_reg(struct task_struct *task, unsigned long offset) diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 19e33b6cd59..da2e314f61b 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -283,7 +283,7 @@ static void lguest_load_tls(struct thread_struct *t, unsigned int cpu) /* There's one problem which normal hardware doesn't have: the Host * can't handle us removing entries we're currently using. So we clear * the GS register here: if it's needed it'll be reloaded anyway. */ - loadsegment(gs, 0); + lazy_load_gs(0); lazy_hcall(LHCALL_LOAD_TLS, __pa(&t->tls_array), cpu, 0); } diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 37230342c2c..95ff6a0e942 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -323,13 +323,14 @@ static void load_TLS_descriptor(struct thread_struct *t, static void xen_load_tls(struct thread_struct *t, unsigned int cpu) { /* - * XXX sleazy hack: If we're being called in a lazy-cpu zone, - * it means we're in a context switch, and %gs has just been - * saved. This means we can zero it out to prevent faults on - * exit from the hypervisor if the next process has no %gs. - * Either way, it has been saved, and the new value will get - * loaded properly. This will go away as soon as Xen has been - * modified to not save/restore %gs for normal hypercalls. + * XXX sleazy hack: If we're being called in a lazy-cpu zone + * and lazy gs handling is enabled, it means we're in a + * context switch, and %gs has just been saved. This means we + * can zero it out to prevent faults on exit from the + * hypervisor if the next process has no %gs. Either way, it + * has been saved, and the new value will get loaded properly. + * This will go away as soon as Xen has been modified to not + * save/restore %gs for normal hypercalls. * * On x86_64, this hack is not used for %gs, because gs points * to KERNEL_GS_BASE (and uses it for PDA references), so we @@ -341,7 +342,7 @@ static void xen_load_tls(struct thread_struct *t, unsigned int cpu) */ if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_CPU) { #ifdef CONFIG_X86_32 - loadsegment(gs, 0); + lazy_load_gs(0); #else loadsegment(fs, 0); #endif -- GitLab From 60a5317ff0f42dd313094b88f809f63041568b08 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 9 Feb 2009 22:17:40 +0900 Subject: [PATCH 1518/4982] x86: implement x86_32 stack protector Impact: stack protector for x86_32 Implement stack protector for x86_32. GDT entry 28 is used for it. It's set to point to stack_canary-20 and have the length of 24 bytes. CONFIG_CC_STACKPROTECTOR turns off CONFIG_X86_32_LAZY_GS and sets %gs to the stack canary segment on entry. As %gs is otherwise unused by the kernel, the canary can be anywhere. It's defined as a percpu variable. x86_32 exception handlers take register frame on stack directly as struct pt_regs. With -fstack-protector turned on, gcc copies the whole structure after the stack canary and (of course) doesn't copy back on return thus losing all changed. For now, -fno-stack-protector is added to all files which contain those functions. We definitely need something better. Signed-off-by: Tejun Heo Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 3 +- arch/x86/include/asm/processor.h | 4 + arch/x86/include/asm/segment.h | 9 ++- arch/x86/include/asm/stackprotector.h | 91 +++++++++++++++++++++-- arch/x86/include/asm/system.h | 21 ++++++ arch/x86/kernel/Makefile | 18 +++++ arch/x86/kernel/cpu/common.c | 17 +++-- arch/x86/kernel/entry_32.S | 2 +- arch/x86/kernel/head_32.S | 20 ++++- arch/x86/kernel/process_32.c | 1 + arch/x86/kernel/setup_percpu.c | 2 + scripts/gcc-x86_32-has-stack-protector.sh | 8 ++ 12 files changed, 180 insertions(+), 16 deletions(-) create mode 100644 scripts/gcc-x86_32-has-stack-protector.sh diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 5bcdede71ba..f760a22f95d 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -209,7 +209,7 @@ config X86_TRAMPOLINE config X86_32_LAZY_GS def_bool y - depends on X86_32 + depends on X86_32 && !CC_STACKPROTECTOR config KTIME_SCALAR def_bool X86_32 @@ -1356,7 +1356,6 @@ config CC_STACKPROTECTOR_ALL config CC_STACKPROTECTOR bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" - depends on X86_64 select CC_STACKPROTECTOR_ALL help This option turns on the -fstack-protector GCC feature. This diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 9763eb70013..5a947210425 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -396,7 +396,11 @@ DECLARE_PER_CPU(union irq_stack_union, irq_stack_union); DECLARE_INIT_PER_CPU(irq_stack_union); DECLARE_PER_CPU(char *, irq_stack_ptr); +#else /* X86_64 */ +#ifdef CONFIG_CC_STACKPROTECTOR +DECLARE_PER_CPU(unsigned long, stack_canary); #endif +#endif /* X86_64 */ extern void print_cpu_info(struct cpuinfo_x86 *); extern unsigned int xstate_size; diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h index 1dc1b51ac62..14e0ed86a6f 100644 --- a/arch/x86/include/asm/segment.h +++ b/arch/x86/include/asm/segment.h @@ -61,7 +61,7 @@ * * 26 - ESPFIX small SS * 27 - per-cpu [ offset to per-cpu data area ] - * 28 - unused + * 28 - stack_canary-20 [ for stack protector ] * 29 - unused * 30 - unused * 31 - TSS for double fault handler @@ -95,6 +95,13 @@ #define __KERNEL_PERCPU 0 #endif +#define GDT_ENTRY_STACK_CANARY (GDT_ENTRY_KERNEL_BASE + 16) +#ifdef CONFIG_CC_STACKPROTECTOR +#define __KERNEL_STACK_CANARY (GDT_ENTRY_STACK_CANARY * 8) +#else +#define __KERNEL_STACK_CANARY 0 +#endif + #define GDT_ENTRY_DOUBLEFAULT_TSS 31 /* diff --git a/arch/x86/include/asm/stackprotector.h b/arch/x86/include/asm/stackprotector.h index ee275e9f48a..fa7e5bd6fbe 100644 --- a/arch/x86/include/asm/stackprotector.h +++ b/arch/x86/include/asm/stackprotector.h @@ -1,3 +1,35 @@ +/* + * GCC stack protector support. + * + * Stack protector works by putting predefined pattern at the start of + * the stack frame and verifying that it hasn't been overwritten when + * returning from the function. The pattern is called stack canary + * and unfortunately gcc requires it to be at a fixed offset from %gs. + * On x86_64, the offset is 40 bytes and on x86_32 20 bytes. x86_64 + * and x86_32 use segment registers differently and thus handles this + * requirement differently. + * + * On x86_64, %gs is shared by percpu area and stack canary. All + * percpu symbols are zero based and %gs points to the base of percpu + * area. The first occupant of the percpu area is always + * irq_stack_union which contains stack_canary at offset 40. Userland + * %gs is always saved and restored on kernel entry and exit using + * swapgs, so stack protector doesn't add any complexity there. + * + * On x86_32, it's slightly more complicated. As in x86_64, %gs is + * used for userland TLS. Unfortunately, some processors are much + * slower at loading segment registers with different value when + * entering and leaving the kernel, so the kernel uses %fs for percpu + * area and manages %gs lazily so that %gs is switched only when + * necessary, usually during task switch. + * + * As gcc requires the stack canary at %gs:20, %gs can't be managed + * lazily if stack protector is enabled, so the kernel saves and + * restores userland %gs on kernel entry and exit. This behavior is + * controlled by CONFIG_X86_32_LAZY_GS and accessors are defined in + * system.h to hide the details. + */ + #ifndef _ASM_STACKPROTECTOR_H #define _ASM_STACKPROTECTOR_H 1 @@ -6,8 +38,18 @@ #include #include #include +#include +#include #include +/* + * 24 byte read-only segment initializer for stack canary. Linker + * can't handle the address bit shifting. Address will be set in + * head_32 for boot CPU and setup_per_cpu_areas() for others. + */ +#define GDT_STACK_CANARY_INIT \ + [GDT_ENTRY_STACK_CANARY] = { { { 0x00000018, 0x00409000 } } }, + /* * Initialize the stackprotector canary value. * @@ -19,12 +61,9 @@ static __always_inline void boot_init_stack_canary(void) u64 canary; u64 tsc; - /* - * Build time only check to make sure the stack_canary is at - * offset 40 in the pda; this is a gcc ABI requirement - */ +#ifdef CONFIG_X86_64 BUILD_BUG_ON(offsetof(union irq_stack_union, stack_canary) != 40); - +#endif /* * We both use the random pool and the current TSC as a source * of randomness. The TSC only matters for very early init, @@ -36,7 +75,49 @@ static __always_inline void boot_init_stack_canary(void) canary += tsc + (tsc << 32UL); current->stack_canary = canary; +#ifdef CONFIG_X86_64 percpu_write(irq_stack_union.stack_canary, canary); +#else + percpu_write(stack_canary, canary); +#endif +} + +static inline void setup_stack_canary_segment(int cpu) +{ +#ifdef CONFIG_X86_32 + unsigned long canary = (unsigned long)&per_cpu(stack_canary, cpu); + struct desc_struct *gdt_table = get_cpu_gdt_table(cpu); + struct desc_struct desc; + + desc = gdt_table[GDT_ENTRY_STACK_CANARY]; + desc.base0 = canary & 0xffff; + desc.base1 = (canary >> 16) & 0xff; + desc.base2 = (canary >> 24) & 0xff; + write_gdt_entry(gdt_table, GDT_ENTRY_STACK_CANARY, &desc, DESCTYPE_S); +#endif +} + +static inline void load_stack_canary_segment(void) +{ +#ifdef CONFIG_X86_32 + asm("mov %0, %%gs" : : "r" (__KERNEL_STACK_CANARY) : "memory"); +#endif +} + +#else /* CC_STACKPROTECTOR */ + +#define GDT_STACK_CANARY_INIT + +/* dummy boot_init_stack_canary() is defined in linux/stackprotector.h */ + +static inline void setup_stack_canary_segment(int cpu) +{ } + +static inline void load_stack_canary_segment(void) +{ +#ifdef CONFIG_X86_32 + asm volatile ("mov %0, %%gs" : : "r" (0)); +#endif } #endif /* CC_STACKPROTECTOR */ diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h index 79b98e5b96f..2692ee8ef03 100644 --- a/arch/x86/include/asm/system.h +++ b/arch/x86/include/asm/system.h @@ -23,6 +23,22 @@ struct task_struct *__switch_to(struct task_struct *prev, #ifdef CONFIG_X86_32 +#ifdef CONFIG_CC_STACKPROTECTOR +#define __switch_canary \ + "movl "__percpu_arg([current_task])",%%ebx\n\t" \ + "movl %P[task_canary](%%ebx),%%ebx\n\t" \ + "movl %%ebx,"__percpu_arg([stack_canary])"\n\t" +#define __switch_canary_oparam \ + , [stack_canary] "=m" (per_cpu_var(stack_canary)) +#define __switch_canary_iparam \ + , [current_task] "m" (per_cpu_var(current_task)) \ + , [task_canary] "i" (offsetof(struct task_struct, stack_canary)) +#else /* CC_STACKPROTECTOR */ +#define __switch_canary +#define __switch_canary_oparam +#define __switch_canary_iparam +#endif /* CC_STACKPROTECTOR */ + /* * Saving eflags is important. It switches not only IOPL between tasks, * it also protects other tasks from NT leaking through sysenter etc. @@ -46,6 +62,7 @@ do { \ "pushl %[next_ip]\n\t" /* restore EIP */ \ "jmp __switch_to\n" /* regparm call */ \ "1:\t" \ + __switch_canary \ "popl %%ebp\n\t" /* restore EBP */ \ "popfl\n" /* restore flags */ \ \ @@ -58,6 +75,8 @@ do { \ "=b" (ebx), "=c" (ecx), "=d" (edx), \ "=S" (esi), "=D" (edi) \ \ + __switch_canary_oparam \ + \ /* input parameters: */ \ : [next_sp] "m" (next->thread.sp), \ [next_ip] "m" (next->thread.ip), \ @@ -66,6 +85,8 @@ do { \ [prev] "a" (prev), \ [next] "d" (next) \ \ + __switch_canary_iparam \ + \ : /* reloaded segment registers */ \ "memory"); \ } while (0) diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 37fa30bada1..b1f8be33300 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -24,6 +24,24 @@ CFLAGS_vsyscall_64.o := $(PROFILING) -g0 $(nostackp) CFLAGS_hpet.o := $(nostackp) CFLAGS_tsc.o := $(nostackp) CFLAGS_paravirt.o := $(nostackp) +# +# On x86_32, register frame is passed verbatim on stack as struct +# pt_regs. gcc considers the parameter to belong to the callee and +# with -fstack-protector it copies pt_regs to the callee's stack frame +# to put the structure after the stack canary causing changes made by +# the exception handlers to be lost. Turn off stack protector for all +# files containing functions which take struct pt_regs from register +# frame. +# +# The proper way to fix this is to teach gcc that the argument belongs +# to the caller for these functions, oh well... +# +ifdef CONFIG_X86_32 +CFLAGS_process_32.o := $(nostackp) +CFLAGS_vm86_32.o := $(nostackp) +CFLAGS_signal.o := $(nostackp) +CFLAGS_traps.o := $(nostackp) +endif obj-y := process_$(BITS).o signal.o entry_$(BITS).o obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 41b0de6df87..260fe4cb2c8 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -39,6 +39,7 @@ #include #include #include +#include #include "cpu.h" @@ -122,6 +123,7 @@ DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { [GDT_ENTRY_ESPFIX_SS] = { { { 0x00000000, 0x00c09200 } } }, [GDT_ENTRY_PERCPU] = { { { 0x0000ffff, 0x00cf9200 } } }, + GDT_STACK_CANARY_INIT #endif } }; EXPORT_PER_CPU_SYMBOL_GPL(gdt_page); @@ -261,6 +263,7 @@ void load_percpu_segment(int cpu) loadsegment(gs, 0); wrmsrl(MSR_GS_BASE, (unsigned long)per_cpu(irq_stack_union.gs_base, cpu)); #endif + load_stack_canary_segment(); } /* Current gdt points %fs at the "master" per-cpu area: after this, @@ -946,16 +949,21 @@ unsigned long kernel_eflags; */ DEFINE_PER_CPU(struct orig_ist, orig_ist); -#else +#else /* x86_64 */ + +#ifdef CONFIG_CC_STACKPROTECTOR +DEFINE_PER_CPU(unsigned long, stack_canary); +#endif -/* Make sure %fs is initialized properly in idle threads */ +/* Make sure %fs and %gs are initialized properly in idle threads */ struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs) { memset(regs, 0, sizeof(struct pt_regs)); regs->fs = __KERNEL_PERCPU; + regs->gs = __KERNEL_STACK_CANARY; return regs; } -#endif +#endif /* x86_64 */ /* * cpu_init() initializes state that is per-CPU. Some data is already @@ -1120,9 +1128,6 @@ void __cpuinit cpu_init(void) __set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss); #endif - /* Clear %gs. */ - asm volatile ("mov %0, %%gs" : : "r" (0)); - /* Clear all 6 debug registers: */ set_debugreg(0, 0); set_debugreg(0, 1); diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 82e6868bee4..5f5bd22adcd 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S @@ -186,7 +186,7 @@ /*CFI_REL_OFFSET gs, PT_GS*/ .endm .macro SET_KERNEL_GS reg - xorl \reg, \reg + movl $(__KERNEL_STACK_CANARY), \reg movl \reg, %gs .endm diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index 24c0e5cd71e..924e31615fb 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -19,6 +19,7 @@ #include #include #include +#include /* Physical address */ #define pa(X) ((X) - __PAGE_OFFSET) @@ -437,8 +438,25 @@ is386: movl $2,%ecx # set MP movl $(__KERNEL_PERCPU), %eax movl %eax,%fs # set this cpu's percpu - xorl %eax,%eax # Clear GS and LDT +#ifdef CONFIG_CC_STACKPROTECTOR + /* + * The linker can't handle this by relocation. Manually set + * base address in stack canary segment descriptor. + */ + cmpb $0,ready + jne 1f + movl $per_cpu__gdt_page,%eax + movl $per_cpu__stack_canary,%ecx + movw %cx, 8 * GDT_ENTRY_STACK_CANARY + 2(%eax) + shrl $16, %ecx + movb %cl, 8 * GDT_ENTRY_STACK_CANARY + 4(%eax) + movb %ch, 8 * GDT_ENTRY_STACK_CANARY + 7(%eax) +1: +#endif + movl $(__KERNEL_STACK_CANARY),%eax movl %eax,%gs + + xorl %eax,%eax # Clear LDT lldt %ax cld # gcc2 wants the direction flag cleared at all times diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 86122fa2a1b..9a62383e7c3 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -212,6 +212,7 @@ int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) regs.ds = __USER_DS; regs.es = __USER_DS; regs.fs = __KERNEL_PERCPU; + regs.gs = __KERNEL_STACK_CANARY; regs.orig_ax = -1; regs.ip = (unsigned long) kernel_thread_helper; regs.cs = __KERNEL_CS | get_kernel_rpl(); diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index ef91747bbed..d992e6cff73 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -16,6 +16,7 @@ #include #include #include +#include #ifdef CONFIG_DEBUG_PER_CPU_MAPS # define DBG(x...) printk(KERN_DEBUG x) @@ -95,6 +96,7 @@ void __init setup_per_cpu_areas(void) per_cpu(this_cpu_off, cpu) = per_cpu_offset(cpu); per_cpu(cpu_number, cpu) = cpu; setup_percpu_segment(cpu); + setup_stack_canary_segment(cpu); /* * Copy data used in early init routines from the * initial arrays to the per cpu data areas. These diff --git a/scripts/gcc-x86_32-has-stack-protector.sh b/scripts/gcc-x86_32-has-stack-protector.sh new file mode 100644 index 00000000000..4fdf6ce1b06 --- /dev/null +++ b/scripts/gcc-x86_32-has-stack-protector.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +echo "int foo(void) { char X[200]; return 3; }" | $1 -S -xc -c -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs" +if [ "$?" -eq "0" ] ; then + echo y +else + echo n +fi -- GitLab From 0012985d184b7b9d4513eacd35771715471e06ef Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 9 Feb 2009 18:05:16 -0800 Subject: [PATCH 1519/4982] ppp: section fixes re netns PPP is modular code so no initdata on netns hooks. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- drivers/net/ppp_generic.c | 2 +- drivers/net/pppoe.c | 2 +- drivers/net/pppol2tp.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 4405a76ed3d..fddc8493f35 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -901,7 +901,7 @@ static __net_exit void ppp_exit_net(struct net *net) kfree(pn); } -static __net_initdata struct pernet_operations ppp_net_ops = { +static struct pernet_operations ppp_net_ops = { .init = ppp_init_net, .exit = ppp_exit_net, }; diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 1011fd64108..af6321d9757 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -1175,7 +1175,7 @@ static __net_exit void pppoe_exit_net(struct net *net) kfree(pn); } -static __net_initdata struct pernet_operations pppoe_net_ops = { +static struct pernet_operations pppoe_net_ops = { .init = pppoe_init_net, .exit = pppoe_exit_net, }; diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index 15f4a43a689..1ba0f6864ac 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c @@ -2647,7 +2647,7 @@ static __net_exit void pppol2tp_exit_net(struct net *net) kfree(pn); } -static __net_initdata struct pernet_operations pppol2tp_net_ops = { +static struct pernet_operations pppol2tp_net_ops = { .init = pppol2tp_init_net, .exit = pppol2tp_exit_net, }; -- GitLab From ed8af6b288c0643dfe0ad91f1bfc8c56c0d307cc Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Mon, 9 Feb 2009 23:23:50 -0800 Subject: [PATCH 1520/4982] enic: bug fix: return notify intr credits Return notify intr credits after notify intr from firmware. This is especially important for legacy PCI intr mode, where not returning credits would cause PBA to remain asserted which would get us right back into the ISR. Signed-off-by: Scott Feldman Signed-off-by: David S. Miller --- drivers/net/enic/enic.h | 2 +- drivers/net/enic/enic_main.c | 17 +++++++++++------ drivers/net/enic/vnic_intr.h | 14 ++++++++++++++ 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index a832cc5d6a1..86b8c15b4d3 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h @@ -33,7 +33,7 @@ #define DRV_NAME "enic" #define DRV_DESCRIPTION "Cisco 10G Ethernet Driver" -#define DRV_VERSION "1.0.0.648" +#define DRV_VERSION "1.0.0.933" #define DRV_COPYRIGHT "Copyright 2008 Cisco Systems, Inc" #define PFX DRV_NAME ": " diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 5dd11563553..e9bc79a6f30 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -400,10 +400,13 @@ static irqreturn_t enic_isr_legacy(int irq, void *data) return IRQ_NONE; /* not our interrupt */ } - if (ENIC_TEST_INTR(pba, ENIC_INTX_NOTIFY)) + if (ENIC_TEST_INTR(pba, ENIC_INTX_NOTIFY)) { + vnic_intr_return_all_credits(&enic->intr[ENIC_INTX_NOTIFY]); enic_notify_check(enic); + } if (ENIC_TEST_INTR(pba, ENIC_INTX_ERR)) { + vnic_intr_return_all_credits(&enic->intr[ENIC_INTX_ERR]); enic_log_q_error(enic); /* schedule recovery from WQ/RQ error */ schedule_work(&enic->reset); @@ -476,6 +479,8 @@ static irqreturn_t enic_isr_msix_err(int irq, void *data) { struct enic *enic = data; + vnic_intr_return_all_credits(&enic->intr[ENIC_MSIX_ERR]); + enic_log_q_error(enic); /* schedule recovery from WQ/RQ error */ @@ -488,8 +493,8 @@ static irqreturn_t enic_isr_msix_notify(int irq, void *data) { struct enic *enic = data; + vnic_intr_return_all_credits(&enic->intr[ENIC_MSIX_NOTIFY]); enic_notify_check(enic); - vnic_intr_unmask(&enic->intr[ENIC_MSIX_NOTIFY]); return IRQ_HANDLED; } @@ -616,7 +621,7 @@ static inline void enic_queue_wq_skb(struct enic *enic, vlan_tag_insert, vlan_tag); } -/* netif_tx_lock held, process context with BHs disabled */ +/* netif_tx_lock held, process context with BHs disabled, or BH */ static int enic_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) { struct enic *enic = netdev_priv(netdev); @@ -1069,7 +1074,7 @@ static int enic_poll(struct napi_struct *napi, int budget) lro_flush_all(&enic->lro_mgr); napi_complete(napi); - vnic_intr_unmask(&enic->intr[ENIC_MSIX_RQ]); + vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]); } return rq_work_done; @@ -1095,9 +1100,9 @@ static int enic_poll_msix(struct napi_struct *napi, int budget) vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf); - /* Accumulate intr event credits for this polling + /* Return intr event credits for this polling * cycle. An intr event is the completion of a - * a WQ or RQ packet. + * RQ packet. */ vnic_intr_return_credits(&enic->intr[ENIC_MSIX_RQ], diff --git a/drivers/net/enic/vnic_intr.h b/drivers/net/enic/vnic_intr.h index ce633a5a7e3..9a53604edce 100644 --- a/drivers/net/enic/vnic_intr.h +++ b/drivers/net/enic/vnic_intr.h @@ -76,6 +76,20 @@ static inline void vnic_intr_return_credits(struct vnic_intr *intr, iowrite32(int_credit_return, &intr->ctrl->int_credit_return); } +static inline unsigned int vnic_intr_credits(struct vnic_intr *intr) +{ + return ioread32(&intr->ctrl->int_credits); +} + +static inline void vnic_intr_return_all_credits(struct vnic_intr *intr) +{ + unsigned int credits = vnic_intr_credits(intr); + int unmask = 1; + int reset_timer = 1; + + vnic_intr_return_credits(intr, credits, unmask, reset_timer); +} + static inline u32 vnic_intr_legacy_pba(u32 __iomem *legacy_pba) { /* read PBA without clearing */ -- GitLab From bd9fb1a44a5c52a1c322ebacd08f6b7416a40a86 Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Mon, 9 Feb 2009 23:24:08 -0800 Subject: [PATCH 1521/4982] enic: record all bad FCS errs as frame errors Report all bad FCS errs as frames errs. This includes frames with bad FCS on wire detected by MAC and frames which may be truncated due to ingress FIFO overruns. No longer print a driver msg on bad FCS err. Signed-off-by: Scott Feldman Signed-off-by: David S. Miller --- drivers/net/enic/enic.h | 1 + drivers/net/enic/enic_main.c | 10 +++------- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index 86b8c15b4d3..c26cea0b300 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h @@ -97,6 +97,7 @@ struct enic { ____cacheline_aligned struct vnic_rq rq[1]; unsigned int rq_count; int (*rq_alloc_buf)(struct vnic_rq *rq); + u64 rq_bad_fcs; struct napi_struct napi; struct net_lro_mgr lro_mgr; struct net_lro_desc lro_desc[ENIC_LRO_MAX_DESC]; diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index e9bc79a6f30..798cf506bff 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -688,7 +688,7 @@ static struct net_device_stats *enic_get_stats(struct net_device *netdev) net_stats->rx_bytes = stats->rx.rx_bytes_ok; net_stats->rx_errors = stats->rx.rx_errors; net_stats->multicast = stats->rx.rx_multicast_frames_ok; - net_stats->rx_crc_errors = stats->rx.rx_crc_errors; + net_stats->rx_crc_errors = enic->rq_bad_fcs; net_stats->rx_dropped = stats->rx.rx_no_bufs; return net_stats; @@ -933,12 +933,8 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq, if (packet_error) { - if (bytes_written > 0 && !fcs_ok) { - if (net_ratelimit()) - printk(KERN_ERR PFX - "%s: packet error: bad FCS\n", - netdev->name); - } + if (bytes_written > 0 && !fcs_ok) + enic->rq_bad_fcs++; dev_kfree_skb_any(skb); -- GitLab From 68f717089a62ee4c51933f4be43e4ef7b31539fd Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Mon, 9 Feb 2009 23:24:24 -0800 Subject: [PATCH 1522/4982] enic: bug fix: tx_timeout reset path fix-ups tx_timeout reset path needs to re-init dev and re-apply nic cfg to enable vlan stripping. Signed-off-by: Scott Feldman Signed-off-by: David S. Miller --- drivers/net/enic/enic_main.c | 39 +++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 798cf506bff..83a7168deee 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -1462,6 +1462,26 @@ static int enic_dev_soft_reset(struct enic *enic) return err; } +static int enic_set_niccfg(struct enic *enic) +{ + const u8 rss_default_cpu = 0; + const u8 rss_hash_type = 0; + const u8 rss_hash_bits = 0; + const u8 rss_base_cpu = 0; + const u8 rss_enable = 0; + const u8 tso_ipid_split_en = 0; + const u8 ig_vlan_strip_en = 1; + + /* Enable VLAN tag stripping. RSS not enabled (yet). + */ + + return enic_set_nic_cfg(enic, + rss_default_cpu, rss_hash_type, + rss_hash_bits, rss_base_cpu, + rss_enable, tso_ipid_split_en, + ig_vlan_strip_en); +} + static void enic_reset(struct work_struct *work) { struct enic *enic = container_of(work, struct enic, reset); @@ -1477,8 +1497,10 @@ static void enic_reset(struct work_struct *work) enic_stop(enic->netdev); enic_dev_soft_reset(enic); + vnic_dev_init(enic->vdev, 0); enic_reset_mcaddrs(enic); enic_init_vnic_resources(enic); + enic_set_niccfg(enic); enic_open(enic->netdev); rtnl_unlock(); @@ -1621,14 +1643,6 @@ static int __devinit enic_probe(struct pci_dev *pdev, unsigned int i; int err; - const u8 rss_default_cpu = 0; - const u8 rss_hash_type = 0; - const u8 rss_hash_bits = 0; - const u8 rss_base_cpu = 0; - const u8 rss_enable = 0; - const u8 tso_ipid_split_en = 0; - const u8 ig_vlan_strip_en = 1; - /* Allocate net device structure and initialize. Private * instance data is initialized to zero. */ @@ -1794,14 +1808,7 @@ static int __devinit enic_probe(struct pci_dev *pdev, enic_init_vnic_resources(enic); - /* Enable VLAN tag stripping. RSS not enabled (yet). - */ - - err = enic_set_nic_cfg(enic, - rss_default_cpu, rss_hash_type, - rss_hash_bits, rss_base_cpu, - rss_enable, tso_ipid_split_en, - ig_vlan_strip_en); + err = enic_set_niccfg(enic); if (err) { printk(KERN_ERR PFX "Failed to config nic, aborting.\n"); -- GitLab From 4cdc44a231f906a6ec586637e6e4c4c216679da4 Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Mon, 9 Feb 2009 23:25:33 -0800 Subject: [PATCH 1523/4982] enic: Add api for link down count and to get firmware notification status. Signed-off-by: Scott Feldman Signed-off-by: David S. Miller --- drivers/net/enic/enic_main.c | 2 -- drivers/net/enic/vnic_dev.c | 33 +++++++++++++++++++++++++++++---- drivers/net/enic/vnic_dev.h | 2 ++ drivers/net/enic/vnic_devcmd.h | 8 +++++++- 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 83a7168deee..03403a51f7e 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -1866,7 +1866,6 @@ static int __devinit enic_probe(struct pci_dev *pdev, if (using_dac) netdev->features |= NETIF_F_HIGHDMA; - enic->csum_rx_enabled = ENIC_SETTING(enic, RXCSUM); enic->lro_mgr.max_aggr = ENIC_LRO_MAX_AGGR; @@ -1878,7 +1877,6 @@ static int __devinit enic_probe(struct pci_dev *pdev, enic->lro_mgr.ip_summed = CHECKSUM_COMPLETE; enic->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY; - err = register_netdev(netdev); if (err) { printk(KERN_ERR PFX diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c index 11708579b6c..e21b9d636ae 100644 --- a/drivers/net/enic/vnic_dev.c +++ b/drivers/net/enic/vnic_dev.c @@ -34,6 +34,9 @@ struct vnic_res { unsigned int count; }; +#define VNIC_DEV_CAP_INIT 0x0001 +#define VNIC_DEV_CAP_PERBI 0x0002 + struct vnic_dev { void *priv; struct pci_dev *pdev; @@ -50,6 +53,7 @@ struct vnic_dev { dma_addr_t stats_pa; struct vnic_devcmd_fw_info *fw_info; dma_addr_t fw_info_pa; + u32 cap_flags; }; #define VNIC_MAX_RES_HDR_SIZE \ @@ -575,9 +579,9 @@ int vnic_dev_init(struct vnic_dev *vdev, int arg) { u64 a0 = (u32)arg, a1 = 0; int wait = 1000; - int r = 0; + int r = 0; - if (vnic_dev_capable(vdev, CMD_INIT)) + if (vdev->cap_flags & VNIC_DEV_CAP_INIT) r = vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait); else { vnic_dev_cmd(vdev, CMD_INIT_v1, &a0, &a1, wait); @@ -587,8 +591,8 @@ int vnic_dev_init(struct vnic_dev *vdev, int arg) vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait); vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait); } - } - return r; + } + return r; } int vnic_dev_link_status(struct vnic_dev *vdev) @@ -626,6 +630,22 @@ u32 vnic_dev_mtu(struct vnic_dev *vdev) return vdev->notify_copy.mtu; } +u32 vnic_dev_link_down_cnt(struct vnic_dev *vdev) +{ + if (!vnic_dev_notify_ready(vdev)) + return 0; + + return vdev->notify_copy.link_down_cnt; +} + +u32 vnic_dev_notify_status(struct vnic_dev *vdev) +{ + if (!vnic_dev_notify_ready(vdev)) + return 0; + + return vdev->notify_copy.status; +} + void vnic_dev_set_intr_mode(struct vnic_dev *vdev, enum vnic_dev_intr_mode intr_mode) { @@ -682,6 +702,11 @@ struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev, if (!vdev->devcmd) goto err_out; + vdev->cap_flags = 0; + + if (vnic_dev_capable(vdev, CMD_INIT)) + vdev->cap_flags |= VNIC_DEV_CAP_INIT; + return vdev; err_out: diff --git a/drivers/net/enic/vnic_dev.h b/drivers/net/enic/vnic_dev.h index b9dc1821c80..8aa8db2fd03 100644 --- a/drivers/net/enic/vnic_dev.h +++ b/drivers/net/enic/vnic_dev.h @@ -102,6 +102,8 @@ int vnic_dev_link_status(struct vnic_dev *vdev); u32 vnic_dev_port_speed(struct vnic_dev *vdev); u32 vnic_dev_msg_lvl(struct vnic_dev *vdev); u32 vnic_dev_mtu(struct vnic_dev *vdev); +u32 vnic_dev_link_down_cnt(struct vnic_dev *vdev); +u32 vnic_dev_notify_status(struct vnic_dev *vdev); int vnic_dev_close(struct vnic_dev *vdev); int vnic_dev_enable(struct vnic_dev *vdev); int vnic_dev_disable(struct vnic_dev *vdev); diff --git a/drivers/net/enic/vnic_devcmd.h b/drivers/net/enic/vnic_devcmd.h index 8062c75154e..2587f34fbfb 100644 --- a/drivers/net/enic/vnic_devcmd.h +++ b/drivers/net/enic/vnic_devcmd.h @@ -191,7 +191,7 @@ enum vnic_devcmd_cmd { CMD_INIT_STATUS = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 31), /* INT13 API: (u64)a0=paddr to vnic_int13_params struct - * (u8)a1=INT13_CMD_xxx */ + * (u32)a1=INT13_CMD_xxx */ CMD_INT13 = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_FC, 32), /* logical uplink enable/disable: (u64)a0: 0/1=disable/enable */ @@ -207,6 +207,11 @@ enum vnic_devcmd_cmd { * in: (u32)a0=cmd * out: (u32)a0=errno, 0:valid cmd, a1=supported VNIC_STF_* bits */ CMD_CAPABILITY = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 36), + + /* persistent binding info + * in: (u64)a0=paddr of arg + * (u32)a1=CMD_PERBI_XXX */ + CMD_PERBI = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_FC, 37), }; /* flags for CMD_OPEN */ @@ -259,6 +264,7 @@ struct vnic_devcmd_notify { u32 status; /* status bits (see VNIC_STF_*) */ u32 error; /* error code (see ERR_*) for first ERR */ u32 link_down_cnt; /* running count of link down transitions */ + u32 perbi_rebuild_cnt; /* running count of perbi rebuilds */ }; #define VNIC_STF_FATAL_ERR 0x0001 /* fatal fw error */ #define VNIC_STF_STD_PAUSE 0x0002 /* standard link-level pause on */ -- GitLab From d54e6d872767ae6512978f86a35d623a8ed948c5 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 9 Feb 2009 23:45:29 -0800 Subject: [PATCH 1524/4982] net: Kill skbuff macros from the stone ages. This kills of HAVE_ALLOC_SKB and HAVE_ALIGNABLE_SKB. Nothing in-tree uses them and nothing in-tree has used them since 2.0.x times. Signed-off-by: David S. Miller --- include/linux/skbuff.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 5eba4007e07..92470084458 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -29,9 +29,6 @@ #include #include -#define HAVE_ALLOC_SKB /* For the drivers to know */ -#define HAVE_ALIGNABLE_SKB /* Ditto 8) */ - /* Don't change this without changing skb_csum_unnecessary! */ #define CHECKSUM_NONE 0 #define CHECKSUM_UNNECESSARY 1 -- GitLab From 149490f131ab532a3b9e8806249a0e730994cdf6 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Tue, 10 Feb 2009 00:11:21 -0800 Subject: [PATCH 1525/4982] pkt_sched: sch_multiq: Change errno on non-multiqueue devices use. Current "RTNETLINK answers: Invalid argument" warning, while trying to add multiq qdisc to non-multiqueue device, isn't very helpful and some of these devs can be changed btw., so let's use a better errno. With feedback from Stephen Hemminger Reported-by: Badalian Vyacheslav Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- net/sched/sch_multiq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c index 7e151861794..91273120304 100644 --- a/net/sched/sch_multiq.c +++ b/net/sched/sch_multiq.c @@ -202,7 +202,7 @@ static int multiq_tune(struct Qdisc *sch, struct nlattr *opt) int i; if (!netif_is_multiqueue(qdisc_dev(sch))) - return -EINVAL; + return -EOPNOTSUPP; if (nla_len(opt) < sizeof(*qopt)) return -EINVAL; -- GitLab From 9034f77bad1e86c4b43e5f5739eb3b8f4878e947 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 10 Feb 2009 01:56:45 -0800 Subject: [PATCH 1526/4982] netdev: Use __netdev_alloc_skb() instead of __dev_alloc_skb(). Signed-off-by: David S. Miller --- drivers/net/b44.c | 2 +- drivers/net/defxx.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 92aaaa1ee9f..2a51c757997 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -973,7 +973,7 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev) ssb_dma_unmap_single(bp->sdev, mapping, len, DMA_TO_DEVICE); - bounce_skb = __dev_alloc_skb(len, GFP_ATOMIC | GFP_DMA); + bounce_skb = __netdev_alloc_skb(dev, len, GFP_ATOMIC | GFP_DMA); if (!bounce_skb) goto err_out; diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c index 6445cedd586..4ec055dc717 100644 --- a/drivers/net/defxx.c +++ b/drivers/net/defxx.c @@ -2937,7 +2937,7 @@ static int dfx_rcv_init(DFX_board_t *bp, int get_buffers) for (i = 0; i < (int)(bp->rcv_bufs_to_post); i++) for (j = 0; (i + j) < (int)PI_RCV_DATA_K_NUM_ENTRIES; j += bp->rcv_bufs_to_post) { - struct sk_buff *newskb = __dev_alloc_skb(NEW_SKB_SIZE, GFP_NOIO); + struct sk_buff *newskb = __netdev_alloc_skb(bp->dev, NEW_SKB_SIZE, GFP_NOIO); if (!newskb) return -ENOMEM; bp->descr_block_virt->rcv_data[i+j].long_0 = (u32) (PI_RCV_DESCR_M_SOP | -- GitLab From e4e90b210dbe8253aaf519ee6efaaab7b2b92034 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 10 Feb 2009 01:54:22 -0800 Subject: [PATCH 1527/4982] irda: Use __netdev_alloc_skb() instead of __dev_alloc_skb(). Signed-off-by: David S. Miller --- drivers/net/irda/sir_dev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c index 5b5862499de..c23d211758a 100644 --- a/drivers/net/irda/sir_dev.c +++ b/drivers/net/irda/sir_dev.c @@ -753,7 +753,8 @@ static int sirdev_alloc_buffers(struct sir_dev *dev) dev->rx_buff.truesize = IRDA_SKB_MAX_MTU; /* Bootstrap ZeroCopy Rx */ - dev->rx_buff.skb = __dev_alloc_skb(dev->rx_buff.truesize, GFP_KERNEL); + dev->rx_buff.skb = __netdev_alloc_skb(dev->netdev, dev->rx_buff.truesize, + GFP_KERNEL); if (dev->rx_buff.skb == NULL) return -ENOMEM; skb_reserve(dev->rx_buff.skb, 1); -- GitLab From b4ac530fc3af02a004729043dacf6b6330b46892 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 10 Feb 2009 02:09:24 -0800 Subject: [PATCH 1528/4982] net: Move skbuff symbol exports after each symbol's definition. net/core/skbuff.c is a hodge-podge of symbol export placement. Some of the exports are right after the definition of the symbol being exported, others are clumped together into a big group at the end of the file. Make things consistent. Signed-off-by: David S. Miller --- net/core/skbuff.c | 79 +++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 43 deletions(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 67f2a2f8582..7657cec5973 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -123,6 +123,7 @@ void skb_over_panic(struct sk_buff *skb, int sz, void *here) skb->dev ? skb->dev->name : ""); BUG(); } +EXPORT_SYMBOL(skb_over_panic); /** * skb_under_panic - private function @@ -142,6 +143,7 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here) skb->dev ? skb->dev->name : ""); BUG(); } +EXPORT_SYMBOL(skb_under_panic); void skb_truesize_bug(struct sk_buff *skb) { @@ -231,6 +233,7 @@ nodata: skb = NULL; goto out; } +EXPORT_SYMBOL(__alloc_skb); /** * __netdev_alloc_skb - allocate an skbuff for rx on a specific device @@ -258,6 +261,7 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, } return skb; } +EXPORT_SYMBOL(__netdev_alloc_skb); struct page *__netdev_alloc_page(struct net_device *dev, gfp_t gfp_mask) { @@ -426,6 +430,7 @@ void __kfree_skb(struct sk_buff *skb) skb_release_all(skb); kfree_skbmem(skb); } +EXPORT_SYMBOL(__kfree_skb); /** * kfree_skb - free an sk_buff @@ -444,6 +449,7 @@ void kfree_skb(struct sk_buff *skb) return; __kfree_skb(skb); } +EXPORT_SYMBOL(kfree_skb); /** * skb_recycle_check - check if skb can be reused for receive @@ -613,6 +619,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) return __skb_clone(n, skb); } +EXPORT_SYMBOL(skb_clone); static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) { @@ -679,7 +686,7 @@ struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask) copy_skb_header(n, skb); return n; } - +EXPORT_SYMBOL(skb_copy); /** * pskb_copy - create copy of an sk_buff with private head. @@ -738,6 +745,7 @@ struct sk_buff *pskb_copy(struct sk_buff *skb, gfp_t gfp_mask) out: return n; } +EXPORT_SYMBOL(pskb_copy); /** * pskb_expand_head - reallocate header of &sk_buff @@ -821,6 +829,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, nodata: return -ENOMEM; } +EXPORT_SYMBOL(pskb_expand_head); /* Make private copy of skb with writable head and some headroom */ @@ -841,7 +850,7 @@ struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom) } return skb2; } - +EXPORT_SYMBOL(skb_realloc_headroom); /** * skb_copy_expand - copy and expand sk_buff @@ -906,6 +915,7 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb, return n; } +EXPORT_SYMBOL(skb_copy_expand); /** * skb_pad - zero pad the tail of an skb @@ -951,6 +961,7 @@ free_skb: kfree_skb(skb); return err; } +EXPORT_SYMBOL(skb_pad); /** * skb_put - add data to a buffer @@ -1108,6 +1119,7 @@ done: return 0; } +EXPORT_SYMBOL(___pskb_trim); /** * __pskb_pull_tail - advance tail of skb header @@ -1246,6 +1258,7 @@ pull_pages: return skb_tail_pointer(skb); } +EXPORT_SYMBOL(__pskb_pull_tail); /* Copy some data bits from skb to kernel buffer. */ @@ -1323,6 +1336,7 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len) fault: return -EFAULT; } +EXPORT_SYMBOL(skb_copy_bits); /* * Callback from splice_to_pipe(), if we need to release some pages @@ -1623,7 +1637,6 @@ int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len) fault: return -EFAULT; } - EXPORT_SYMBOL(skb_store_bits); /* Checksum skb data. */ @@ -1700,6 +1713,7 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset, return csum; } +EXPORT_SYMBOL(skb_checksum); /* Both of above in one bottle. */ @@ -1781,6 +1795,7 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, BUG_ON(len); return csum; } +EXPORT_SYMBOL(skb_copy_and_csum_bits); void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to) { @@ -1807,6 +1822,7 @@ void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to) *((__sum16 *)(to + csstuff)) = csum_fold(csum); } } +EXPORT_SYMBOL(skb_copy_and_csum_dev); /** * skb_dequeue - remove from the head of the queue @@ -1827,6 +1843,7 @@ struct sk_buff *skb_dequeue(struct sk_buff_head *list) spin_unlock_irqrestore(&list->lock, flags); return result; } +EXPORT_SYMBOL(skb_dequeue); /** * skb_dequeue_tail - remove from the tail of the queue @@ -1846,6 +1863,7 @@ struct sk_buff *skb_dequeue_tail(struct sk_buff_head *list) spin_unlock_irqrestore(&list->lock, flags); return result; } +EXPORT_SYMBOL(skb_dequeue_tail); /** * skb_queue_purge - empty a list @@ -1861,6 +1879,7 @@ void skb_queue_purge(struct sk_buff_head *list) while ((skb = skb_dequeue(list)) != NULL) kfree_skb(skb); } +EXPORT_SYMBOL(skb_queue_purge); /** * skb_queue_head - queue a buffer at the list head @@ -1881,6 +1900,7 @@ void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk) __skb_queue_head(list, newsk); spin_unlock_irqrestore(&list->lock, flags); } +EXPORT_SYMBOL(skb_queue_head); /** * skb_queue_tail - queue a buffer at the list tail @@ -1901,6 +1921,7 @@ void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk) __skb_queue_tail(list, newsk); spin_unlock_irqrestore(&list->lock, flags); } +EXPORT_SYMBOL(skb_queue_tail); /** * skb_unlink - remove a buffer from a list @@ -1920,6 +1941,7 @@ void skb_unlink(struct sk_buff *skb, struct sk_buff_head *list) __skb_unlink(skb, list); spin_unlock_irqrestore(&list->lock, flags); } +EXPORT_SYMBOL(skb_unlink); /** * skb_append - append a buffer @@ -1939,7 +1961,7 @@ void skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head __skb_queue_after(list, old, newsk); spin_unlock_irqrestore(&list->lock, flags); } - +EXPORT_SYMBOL(skb_append); /** * skb_insert - insert a buffer @@ -1961,6 +1983,7 @@ void skb_insert(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head __skb_insert(newsk, old->prev, old, list); spin_unlock_irqrestore(&list->lock, flags); } +EXPORT_SYMBOL(skb_insert); static inline void skb_split_inside_header(struct sk_buff *skb, struct sk_buff* skb1, @@ -2039,6 +2062,7 @@ void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len) else /* Second chunk has no header, nothing to copy. */ skb_split_no_header(skb, skb1, len, pos); } +EXPORT_SYMBOL(skb_split); /* Shifting from/to a cloned skb is a no-go. * @@ -2201,6 +2225,7 @@ void skb_prepare_seq_read(struct sk_buff *skb, unsigned int from, st->frag_idx = st->stepped_offset = 0; st->frag_data = NULL; } +EXPORT_SYMBOL(skb_prepare_seq_read); /** * skb_seq_read - Sequentially read skb data @@ -2288,6 +2313,7 @@ next_skb: return 0; } +EXPORT_SYMBOL(skb_seq_read); /** * skb_abort_seq_read - Abort a sequential read of skb data @@ -2301,6 +2327,7 @@ void skb_abort_seq_read(struct skb_seq_state *st) if (st->frag_data) kunmap_skb_frag(st->frag_data); } +EXPORT_SYMBOL(skb_abort_seq_read); #define TS_SKB_CB(state) ((struct skb_seq_state *) &((state)->cb)) @@ -2343,6 +2370,7 @@ unsigned int skb_find_text(struct sk_buff *skb, unsigned int from, ret = textsearch_find(config, state); return (ret <= to - from ? ret : UINT_MAX); } +EXPORT_SYMBOL(skb_find_text); /** * skb_append_datato_frags: - append the user data to a skb @@ -2415,6 +2443,7 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb, return 0; } +EXPORT_SYMBOL(skb_append_datato_frags); /** * skb_pull_rcsum - pull skb and update receive checksum @@ -2602,7 +2631,6 @@ err: } return ERR_PTR(err); } - EXPORT_SYMBOL_GPL(skb_segment); int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) @@ -2800,6 +2828,7 @@ int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int le return nsg; } +EXPORT_SYMBOL_GPL(skb_to_sgvec); /** * skb_cow_data - Check that a socket buffer's data buffers are writable @@ -2909,6 +2938,7 @@ int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer) return elt; } +EXPORT_SYMBOL_GPL(skb_cow_data); /** * skb_partial_csum_set - set up and verify partial csum values for packet @@ -2937,6 +2967,7 @@ bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off) skb->csum_offset = off; return true; } +EXPORT_SYMBOL_GPL(skb_partial_csum_set); void __skb_warn_lro_forwarding(const struct sk_buff *skb) { @@ -2944,42 +2975,4 @@ void __skb_warn_lro_forwarding(const struct sk_buff *skb) pr_warning("%s: received packets cannot be forwarded" " while LRO is enabled\n", skb->dev->name); } - -EXPORT_SYMBOL(___pskb_trim); -EXPORT_SYMBOL(__kfree_skb); -EXPORT_SYMBOL(kfree_skb); -EXPORT_SYMBOL(__pskb_pull_tail); -EXPORT_SYMBOL(__alloc_skb); -EXPORT_SYMBOL(__netdev_alloc_skb); -EXPORT_SYMBOL(pskb_copy); -EXPORT_SYMBOL(pskb_expand_head); -EXPORT_SYMBOL(skb_checksum); -EXPORT_SYMBOL(skb_clone); -EXPORT_SYMBOL(skb_copy); -EXPORT_SYMBOL(skb_copy_and_csum_bits); -EXPORT_SYMBOL(skb_copy_and_csum_dev); -EXPORT_SYMBOL(skb_copy_bits); -EXPORT_SYMBOL(skb_copy_expand); -EXPORT_SYMBOL(skb_over_panic); -EXPORT_SYMBOL(skb_pad); -EXPORT_SYMBOL(skb_realloc_headroom); -EXPORT_SYMBOL(skb_under_panic); -EXPORT_SYMBOL(skb_dequeue); -EXPORT_SYMBOL(skb_dequeue_tail); -EXPORT_SYMBOL(skb_insert); -EXPORT_SYMBOL(skb_queue_purge); -EXPORT_SYMBOL(skb_queue_head); -EXPORT_SYMBOL(skb_queue_tail); -EXPORT_SYMBOL(skb_unlink); -EXPORT_SYMBOL(skb_append); -EXPORT_SYMBOL(skb_split); -EXPORT_SYMBOL(skb_prepare_seq_read); -EXPORT_SYMBOL(skb_seq_read); -EXPORT_SYMBOL(skb_abort_seq_read); -EXPORT_SYMBOL(skb_find_text); -EXPORT_SYMBOL(skb_append_datato_frags); EXPORT_SYMBOL(__skb_warn_lro_forwarding); - -EXPORT_SYMBOL_GPL(skb_to_sgvec); -EXPORT_SYMBOL_GPL(skb_cow_data); -EXPORT_SYMBOL_GPL(skb_partial_csum_set); -- GitLab From 22971e3a77f193579be525a12f3ab91dbf241517 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 10 Feb 2009 11:56:44 +0100 Subject: [PATCH 1529/4982] ALSA: hda - add digital beep support for ALC268 Added the digital beep support for ALC268. It was missing in the last patches. However, ALC268 has a strange pin use for widget 0x1d, which could be used as another purpose. So, the patch adds a check of the beep control before creating the hook for input layer. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 7ae8fad0189..97eaf3b1d97 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -11885,7 +11885,7 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = { static struct alc_config_preset alc268_presets[] = { [ALC267_QUANTA_IL1] = { - .mixers = { alc267_quanta_il1_mixer }, + .mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer }, .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, alc267_quanta_il1_verbs }, .num_dacs = ARRAY_SIZE(alc268_dac_nids), @@ -11967,7 +11967,8 @@ static struct alc_config_preset alc268_presets[] = { }, [ALC268_ACER_ASPIRE_ONE] = { .mixers = { alc268_acer_aspire_one_mixer, - alc268_capture_alt_mixer }, + alc268_beep_mixer, + alc268_capture_alt_mixer }, .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, alc268_acer_aspire_one_verbs }, .num_dacs = ARRAY_SIZE(alc268_dac_nids), @@ -12036,7 +12037,7 @@ static int patch_alc268(struct hda_codec *codec) { struct alc_spec *spec; int board_config; - int err; + int i, has_beep, err; spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); if (spec == NULL) @@ -12091,13 +12092,28 @@ static int patch_alc268(struct hda_codec *codec) spec->stream_digital_playback = &alc268_pcm_digital_playback; - if (!query_amp_caps(codec, 0x1d, HDA_INPUT)) - /* override the amp caps for beep generator */ - snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT, + has_beep = 0; + for (i = 0; i < spec->num_mixers; i++) { + if (spec->mixers[i] == alc268_beep_mixer) { + has_beep = 1; + break; + } + } + + if (has_beep) { + err = snd_hda_attach_beep_device(codec, 0x1); + if (err < 0) { + alc_free(codec); + return err; + } + if (!query_amp_caps(codec, 0x1d, HDA_INPUT)) + /* override the amp caps for beep generator */ + snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT, (0x0c << AC_AMPCAP_OFFSET_SHIFT) | (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) | (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) | (0 << AC_AMPCAP_MUTE_SHIFT)); + } if (!spec->adc_nids && spec->input_mux) { /* check whether NID 0x07 is valid */ -- GitLab From 93faee1d509926b844ad021e941a194e898f68dd Mon Sep 17 00:00:00 2001 From: Hartley Sweeten Date: Mon, 26 Jan 2009 17:24:51 +0100 Subject: [PATCH 1530/4982] [ARM] 5371/1: ep93xx: add i2c device to edb9307a Add the on-board rtc i2c device to the edb9307a platform init. The EP93xx based EDB9307A dev board has an on-board ISL1208 RTC connected to the I2C bus. Now that the core code supports the I2C bus, this patch will add support for the device. Signed-off-by: H Hartley Sweeten Signed-off-by: Russell King --- arch/arm/mach-ep93xx/edb9307a.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/mach-ep93xx/edb9307a.c b/arch/arm/mach-ep93xx/edb9307a.c index 5b5c22b681b..6171167d331 100644 --- a/arch/arm/mach-ep93xx/edb9307a.c +++ b/arch/arm/mach-ep93xx/edb9307a.c @@ -48,12 +48,24 @@ static struct ep93xx_eth_data edb9307a_eth_data = { .phy_id = 1, }; +static struct i2c_board_info __initdata edb9307a_i2c_data[] = { + { + /* On-board battery backed RTC */ + I2C_BOARD_INFO("isl1208", 0x6f), + }, + /* + * The I2C signals are also routed to the Expansion Connector (J4) + */ +}; + static void __init edb9307a_init_machine(void) { ep93xx_init_devices(); platform_device_register(&edb9307a_flash); ep93xx_register_eth(&edb9307a_eth_data, 1); + + ep93xx_init_i2c(edb9307a_i2c_data, ARRAY_SIZE(edb9307a_i2c_data)); } MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board") -- GitLab From b74788d8c118a48585ad5342560e0aea6ed0ccd4 Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Thu, 29 Jan 2009 11:33:10 +0100 Subject: [PATCH 1531/4982] [ARM] 5372/1: ACS5K: Core board support for the ACS-5000 This patch provides the core board support for the Brivo Systems LLC ACS-5000 master board for automated door/card-reader etc management. Signed-off-by: Daniel Silverstone Signed-off-by: Vincent Sanders Signed-off-by: Russell King --- arch/arm/configs/acs5k_defconfig | 1233 +++++++++++++++++++++++++ arch/arm/configs/acs5k_tiny_defconfig | 941 +++++++++++++++++++ arch/arm/mach-ks8695/Kconfig | 6 + arch/arm/mach-ks8695/Makefile | 1 + arch/arm/mach-ks8695/board-acs5k.c | 233 +++++ 5 files changed, 2414 insertions(+) create mode 100644 arch/arm/configs/acs5k_defconfig create mode 100644 arch/arm/configs/acs5k_tiny_defconfig create mode 100644 arch/arm/mach-ks8695/board-acs5k.c diff --git a/arch/arm/configs/acs5k_defconfig b/arch/arm/configs/acs5k_defconfig new file mode 100644 index 00000000000..1cab4e79d36 --- /dev/null +++ b/arch/arm/configs/acs5k_defconfig @@ -0,0 +1,1233 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.27-simtec-micrel1 +# Tue Dec 16 13:31:34 2008 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +# CONFIG_GENERIC_TIME is not set +# CONFIG_GENERIC_CLOCKEVENTS is not set +CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_SUPPORTS_AOUT=y +CONFIG_ZONE_DMA=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +# CONFIG_GROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +# CONFIG_HAVE_ARCH_TRACEHOOK is not set +# CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +# CONFIG_HAVE_CLK is not set +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_CLASSIC_RCU=y + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +CONFIG_ARCH_KS8695=y +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_MSM7X00A is not set + +# +# Boot options +# + +# +# Power management +# + +# +# Kendin/Micrel KS8695 Implementations +# +CONFIG_MACH_KS8695=y +CONFIG_MACH_DSM320=y +CONFIG_MACH_ACS5K=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM922T=y +CONFIG_CPU_32v4T=y +CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_CACHE_V4WT=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_OUTER_CACHE is not set + +# +# Bus support +# +CONFIG_PCI=y +CONFIG_PCI_SYSCALL=y +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_PCI_LEGACY=y +CONFIG_PCI_DEBUG=y +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=y +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +# CONFIG_PD6729 is not set +# CONFIG_I82092 is not set +CONFIG_PCCARD_NONSTATIC=y + +# +# Kernel Features +# +# CONFIG_TICK_ONESHOT is not set +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20410000,3145728 root=/dev/ram0 rw" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_FPE_NWFPE is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x8000000 +CONFIG_MTD_PHYSMAP_LEN=0 +CONFIG_MTD_PHYSMAP_BANKWIDTH=4 +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_INTEL_VR_NOR is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=8192 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_MISC_DEVICES=y +# CONFIG_PHANTOM is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# Enable only one of the two stacks, unless you know what you are doing +# +# CONFIG_FIREWIRE is not set +# CONFIG_IEEE1394 is not set +# CONFIG_I2O is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_ARCNET is not set +# CONFIG_PHYLIB is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_ARM_KS8695_ETHER=y +# CONFIG_AX88796 is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_NET_PCI is not set +# CONFIG_B44 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_TR is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +CONFIG_WLAN_80211=y +# CONFIG_PCMCIA_RAYCS is not set +# CONFIG_IPW2100 is not set +# CONFIG_IPW2200 is not set +# CONFIG_LIBERTAS is not set +# CONFIG_HERMES is not set +# CONFIG_ATMEL is not set +# CONFIG_AIRO_CS is not set +# CONFIG_PCMCIA_WL3501 is not set +CONFIG_PRISM54=m +# CONFIG_IWLWIFI_LEDS is not set +# CONFIG_HOSTAP is not set +# CONFIG_NET_PCMCIA is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_KS8695=y +CONFIG_SERIAL_KS8695_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=m +# CONFIG_NVRAM is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set +# CONFIG_IPWIRELESS is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y +CONFIG_ACS5KCAN=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +CONFIG_I2C_GPIO=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set + +# +# Graphics adapter I2C/DDC channel drivers +# +# CONFIG_I2C_VOODOO3 is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_AT24 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_TPS65010 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_SPI is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +CONFIG_GPIO_PCA953X=y +# CONFIG_GPIO_PCF857X is not set + +# +# PCI GPIO expanders: +# +# CONFIG_GPIO_BT8XX is not set + +# +# SPI GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7473 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_KS8695_WATCHDOG=y +# CONFIG_ALIM7101_WDT is not set + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +CONFIG_HID_DEBUG=y +# CONFIG_HIDRAW is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB is not set + +# +# Enable Host or Gadget support to see Inventra options +# + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# +# CONFIG_USB_GADGET is not set +# CONFIG_MMC is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +CONFIG_RTC_DRV_PCF8563=y +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_DMADEVICES is not set + +# +# Voltage and Current regulators +# +# CONFIG_REGULATOR is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_UIO is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4DEV_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +CONFIG_JFFS2_RUBIN=y +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +# CONFIG_JFFS2_CMODE_FAVOURLZO is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_HAVE_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +# CONFIG_FTRACE is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_HIFN_795X is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_GENERIC_FIND_FIRST_BIT is not set +# CONFIG_GENERIC_FIND_NEXT_BIT is not set +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/configs/acs5k_tiny_defconfig b/arch/arm/configs/acs5k_tiny_defconfig new file mode 100644 index 00000000000..8e3d084afd7 --- /dev/null +++ b/arch/arm/configs/acs5k_tiny_defconfig @@ -0,0 +1,941 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.27-simtec-micrel1 +# Tue Jan 6 13:23:07 2009 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +# CONFIG_GENERIC_TIME is not set +# CONFIG_GENERIC_CLOCKEVENTS is not set +CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_SUPPORTS_AOUT=y +CONFIG_ZONE_DMA=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +# CONFIG_GROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +# CONFIG_HAVE_ARCH_TRACEHOOK is not set +# CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +# CONFIG_HAVE_CLK is not set +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_CLASSIC_RCU=y + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +CONFIG_ARCH_KS8695=y +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_MSM7X00A is not set + +# +# Boot options +# + +# +# Power management +# + +# +# Kendin/Micrel KS8695 Implementations +# +# CONFIG_MACH_KS8695 is not set +# CONFIG_MACH_DSM320 is not set +CONFIG_MACH_ACS5K=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM922T=y +CONFIG_CPU_32v4T=y +CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_CACHE_V4WT=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_OUTER_CACHE is not set + +# +# Bus support +# +# CONFIG_PCI is not set +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_TICK_ONESHOT is not set +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="console=ttyAM0,115200 init=/bin/sh" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x8000000 +CONFIG_MTD_PHYSMAP_LEN=0 +CONFIG_MTD_PHYSMAP_BANKWIDTH=4 +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +# CONFIG_BLK_DEV is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_PHYLIB is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_ARM_KS8695_ETHER=y +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_B44 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +CONFIG_WLAN_80211=y +# CONFIG_LIBERTAS is not set +# CONFIG_IWLWIFI_LEDS is not set +# CONFIG_HOSTAP is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_KS8695=y +CONFIG_SERIAL_KS8695_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_NVRAM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_ACS5KCAN=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +CONFIG_I2C_GPIO=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_AT24 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_TPS65010 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_SPI is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +CONFIG_GPIO_PCA953X=y +# CONFIG_GPIO_PCF857X is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_KS8695_WATCHDOG=y + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +CONFIG_RTC_DRV_PCF8563=y +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_DMADEVICES is not set + +# +# Voltage and Current regulators +# +# CONFIG_REGULATOR is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_UIO is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4DEV_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +CONFIG_JFFS2_RUBIN=y +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +# CONFIG_JFFS2_CMODE_FAVOURLZO is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_NETWORK_FILESYSTEMS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_HAVE_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +# CONFIG_FTRACE is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_GENERIC_FIND_FIRST_BIT is not set +# CONFIG_GENERIC_FIND_NEXT_BIT is not set +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/mach-ks8695/Kconfig b/arch/arm/mach-ks8695/Kconfig index 2754daabda5..fe0c82e30b2 100644 --- a/arch/arm/mach-ks8695/Kconfig +++ b/arch/arm/mach-ks8695/Kconfig @@ -14,6 +14,12 @@ config MACH_DSM320 Say 'Y' here if you want your kernel to run on the D-Link DSM-320 Wireless Media Player. +config MACH_ACS5K + bool "Brivo Systems LLC, ACS-5000 Master board" + help + say 'Y' here if you want your kernel to run on the Brivo + Systems LLC, ACS-5000 Master board. + endmenu endif diff --git a/arch/arm/mach-ks8695/Makefile b/arch/arm/mach-ks8695/Makefile index f735d2cc029..7e3e8160ed3 100644 --- a/arch/arm/mach-ks8695/Makefile +++ b/arch/arm/mach-ks8695/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_LEDS) += leds.o # Board-specific support obj-$(CONFIG_MACH_KS8695) += board-micrel.o obj-$(CONFIG_MACH_DSM320) += board-dsm320.o +obj-$(CONFIG_MACH_ACS5K) += board-acs5k.o diff --git a/arch/arm/mach-ks8695/board-acs5k.c b/arch/arm/mach-ks8695/board-acs5k.c new file mode 100644 index 00000000000..9e3e5a640ad --- /dev/null +++ b/arch/arm/mach-ks8695/board-acs5k.c @@ -0,0 +1,233 @@ +/* + * arch/arm/mach-ks8695/board-acs5k.c + * + * Brivo Systems LLC, ACS-5000 Master Board + * + * Copyright 2008 Simtec Electronics + * Daniel Silverstone + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#include "generic.h" + +static struct i2c_gpio_platform_data acs5k_i2c_device_platdata = { + .sda_pin = 4, + .scl_pin = 5, + .udelay = 10, +}; + +static struct platform_device acs5k_i2c_device = { + .name = "i2c-gpio", + .id = -1, + .num_resources = 0, + .resource = NULL, + .dev = { + .platform_data = &acs5k_i2c_device_platdata, + }, +}; + +static int acs5k_pca9555_setup(struct i2c_client *client, + unsigned gpio_base, unsigned ngpio, + void *context) +{ + static int acs5k_gpio_value[] = { + -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, -1, 0, 1, 0, -1, -1 + }; + int n; + + for (n = 0; n < ARRAY_SIZE(acs5k_gpio_value); ++n) { + gpio_request(gpio_base + n, "ACS-5000 GPIO Expander"); + if (acs5k_gpio_value[n] < 0) + gpio_direction_input(gpio_base + n); + else + gpio_direction_output(gpio_base + n, + acs5k_gpio_value[n]); + gpio_export(gpio_base + n, 0); /* Export, direction locked down */ + } + + return 0; +} + +static struct pca953x_platform_data acs5k_i2c_pca9555_platdata = { + .gpio_base = 16, /* Start directly after the CPU's GPIO */ + .invert = 0, /* Do not invert */ + .setup = acs5k_pca9555_setup, +}; + +static struct i2c_board_info acs5k_i2c_devs[] __initdata = { + { + I2C_BOARD_INFO("pcf8563", 0x51), + }, + { + I2C_BOARD_INFO("pca9555", 0x20), + .platform_data = &acs5k_i2c_pca9555_platdata, + }, +}; + +static void __devinit acs5k_i2c_init(void) +{ + /* The gpio interface */ + platform_device_register(&acs5k_i2c_device); + /* I2C devices */ + i2c_register_board_info(0, acs5k_i2c_devs, + ARRAY_SIZE(acs5k_i2c_devs)); +} + +static struct mtd_partition acs5k_nor_partitions[] = { + [0] = { + .name = "Boot Agent and config", + .size = SZ_256K, + .offset = 0, + .mask_flags = MTD_WRITEABLE, + }, + [1] = { + .name = "Kernel", + .size = SZ_1M, + .offset = SZ_256K, + }, + [2] = { + .name = "SquashFS1", + .size = SZ_2M, + .offset = SZ_256K + SZ_1M, + }, + [3] = { + .name = "SquashFS2", + .size = SZ_4M + SZ_2M, + .offset = SZ_256K + SZ_1M + SZ_2M, + }, + [4] = { + .name = "Data", + .size = SZ_16M + SZ_4M + SZ_2M + SZ_512K, /* 22.5 MB */ + .offset = SZ_256K + SZ_8M + SZ_1M, + } +}; + +static struct physmap_flash_data acs5k_nor_pdata = { + .width = 4, + .nr_parts = ARRAY_SIZE(acs5k_nor_partitions), + .parts = acs5k_nor_partitions, +}; + +static struct resource acs5k_nor_resource[] = { + [0] = { + .start = SZ_32M, /* We expect the bootloader to map + * the flash here. + */ + .end = SZ_32M + SZ_16M - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = SZ_32M + SZ_16M, + .end = SZ_32M + SZ_32M - SZ_256K - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device acs5k_device_nor = { + .name = "physmap-flash", + .id = -1, + .num_resources = ARRAY_SIZE(acs5k_nor_resource), + .resource = acs5k_nor_resource, + .dev = { + .platform_data = &acs5k_nor_pdata, + }, +}; + +static void __init acs5k_register_nor(void) +{ + int ret; + + if (acs5k_nor_partitions[0].mask_flags == 0) + printk(KERN_WARNING "Warning: Unprotecting bootloader and configuration partition\n"); + + ret = platform_device_register(&acs5k_device_nor); + if (ret < 0) + printk(KERN_ERR "failed to register physmap-flash device\n"); +} + +static int __init acs5k_protection_setup(char *s) +{ + /* We can't allocate anything here but we should be able + * to trivially parse s and decide if we can protect the + * bootloader partition or not + */ + if (strcmp(s, "no") == 0) + acs5k_nor_partitions[0].mask_flags = 0; + + return 1; +} + +__setup("protect_bootloader=", acs5k_protection_setup); + +static void __init acs5k_init_gpio(void) +{ + int i; + + ks8695_register_gpios(); + for (i = 0; i < 4; ++i) + gpio_request(i, "ACS5K IRQ"); + gpio_request(7, "ACS5K KS_FRDY"); + for (i = 8; i < 16; ++i) + gpio_request(i, "ACS5K Unused"); + + gpio_request(3, "ACS5K CAN Control"); + gpio_request(6, "ACS5K Heartbeat"); + gpio_direction_output(3, 1); /* Default CAN_RESET high */ + gpio_direction_output(6, 0); /* Default KS8695_ACTIVE low */ + gpio_export(3, 0); /* export CAN_RESET as output only */ + gpio_export(6, 0); /* export KS8695_ACTIVE as output only */ +} + +static void __init acs5k_init(void) +{ + acs5k_init_gpio(); + + /* Network device */ + ks8695_add_device_lan(); /* eth0 = LAN */ + ks8695_add_device_wan(); /* ethX = WAN */ + + /* NOR devices */ + acs5k_register_nor(); + + /* I2C bus */ + acs5k_i2c_init(); +} + +MACHINE_START(ACS5K, "Brivo Systems LLC ACS-5000 Master board") + /* Maintainer: Simtec Electronics. */ + .phys_io = KS8695_IO_PA, + .io_pg_offst = (KS8695_IO_VA >> 18) & 0xfffc, + .boot_params = KS8695_SDRAM_PA + 0x100, + .map_io = ks8695_map_io, + .init_irq = ks8695_init_irq, + .init_machine = acs5k_init, + .timer = &ks8695_timer, +MACHINE_END -- GitLab From 17198f2d681d34b3376f3a55b2837e56062c2439 Mon Sep 17 00:00:00 2001 From: wanzongshun Date: Wed, 4 Feb 2009 05:01:38 +0100 Subject: [PATCH 1532/4982] [ARM] 5374/1: The w90p910 uart0 driver patch Add W90P910 UART0 support,the W90P910 UART0 is 8250 series. Signed-off-by: Wan ZongShun Signed-off-by: Russell King --- arch/arm/mach-w90x900/cpu.h | 17 ++++--- arch/arm/mach-w90x900/mach-w90p910evb.c | 10 +--- arch/arm/mach-w90x900/w90p910.c | 67 +++++-------------------- 3 files changed, 24 insertions(+), 70 deletions(-) diff --git a/arch/arm/mach-w90x900/cpu.h b/arch/arm/mach-w90x900/cpu.h index 40ff40845df..001d50915e3 100644 --- a/arch/arm/mach-w90x900/cpu.h +++ b/arch/arm/mach-w90x900/cpu.h @@ -43,6 +43,7 @@ extern void w90p910_init_io(struct map_desc *mach_desc, int size); extern void w90p910_init_uarts(struct w90x900_uartcfg *cfg, int no); extern void w90p910_init_clocks(int xtal); extern void w90p910_map_io(struct map_desc *mach_desc, int size); +extern struct platform_device w90p910_serial_device; extern struct sys_timer w90x900_timer; #define W90X900_RES(name) \ @@ -67,11 +68,13 @@ struct platform_device w90x900_##devname = { \ .resource = w90x900_##regname##_resource, \ } -#define W90X900_UARTCFG(port, flag, uc, ulc, ufc) \ -{ \ - .hwport = port, \ - .flags = flag, \ - .ucon = uc, \ - .ulcon = ulc, \ - .ufcon = ufc, \ +#define W90X900_8250PORT(name) \ +{ \ + .membase = name##_BA, \ + .mapbase = name##_PA, \ + .irq = IRQ_##name, \ + .uartclk = 11313600, \ + .regshift = 2, \ + .iotype = UPIO_MEM, \ + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, \ } diff --git a/arch/arm/mach-w90x900/mach-w90p910evb.c b/arch/arm/mach-w90x900/mach-w90p910evb.c index 9ebc93f4853..542527019b6 100644 --- a/arch/arm/mach-w90x900/mach-w90p910evb.c +++ b/arch/arm/mach-w90x900/mach-w90p910evb.c @@ -36,24 +36,16 @@ static struct map_desc w90p910_iodesc[] __initdata = { }; -static struct w90x900_uartcfg w90p910_uartcfgs[] = { - W90X900_UARTCFG(0, 0, 0, 0, 0), - W90X900_UARTCFG(1, 0, 0, 0, 0), - W90X900_UARTCFG(2, 0, 0, 0, 0), - W90X900_UARTCFG(3, 0, 0, 0, 0), - W90X900_UARTCFG(4, 0, 0, 0, 0), -}; - /*Here should be your evb resourse,such as LCD*/ static struct platform_device *w90p910evb_dev[] __initdata = { + &w90p910_serial_device, }; static void __init w90p910evb_map_io(void) { w90p910_map_io(w90p910_iodesc, ARRAY_SIZE(w90p910_iodesc)); w90p910_init_clocks(0); - w90p910_init_uarts(w90p910_uartcfgs, ARRAY_SIZE(w90p910_uartcfgs)); } static void __init w90p910evb_init(void) diff --git a/arch/arm/mach-w90x900/w90p910.c b/arch/arm/mach-w90x900/w90p910.c index aa783bc9431..2bcbaa681b9 100644 --- a/arch/arm/mach-w90x900/w90p910.c +++ b/arch/arm/mach-w90x900/w90p910.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -36,12 +37,6 @@ #include "cpu.h" -/*W90P910 has five uarts*/ - -#define MAX_UART_COUNT 5 -static int uart_count; -static struct platform_device *uart_devs[MAX_UART_COUNT-1]; - /* Initial IO mappings */ static struct map_desc w90p910_iodesc[] __initdata = { @@ -53,48 +48,19 @@ static struct map_desc w90p910_iodesc[] __initdata = { /*IODESC_ENT(LCD),*/ }; -/*Init the dev resource*/ - -static W90X900_RES(UART0); -static W90X900_RES(UART1); -static W90X900_RES(UART2); -static W90X900_RES(UART3); -static W90X900_RES(UART4); -static W90X900_DEVICE(uart0, UART0, 0, "w90x900-uart"); -static W90X900_DEVICE(uart1, UART1, 1, "w90x900-uart"); -static W90X900_DEVICE(uart2, UART2, 2, "w90x900-uart"); -static W90X900_DEVICE(uart3, UART3, 3, "w90x900-uart"); -static W90X900_DEVICE(uart4, UART4, 4, "w90x900-uart"); - -static struct platform_device *uart_devices[] __initdata = { - &w90x900_uart0, - &w90x900_uart1, - &w90x900_uart2, - &w90x900_uart3, - &w90x900_uart4 -}; +/* Initial serial platform data */ -/*Init W90P910 uart device*/ +struct plat_serial8250_port w90p910_uart_data[] = { + W90X900_8250PORT(UART0), +}; -void __init w90p910_init_uarts(struct w90x900_uartcfg *cfg, int no) -{ - struct platform_device *platdev; - int uart, uartdev; - - /*By min() to judge count of uart be used indeed*/ - - uartdev = ARRAY_SIZE(uart_devices); - no = min(uartdev, no); - - for (uart = 0; uart < no; uart++, cfg++) { - if (cfg->hwport != uart) - printk(KERN_ERR "w90x900_uartcfg[%d] error\n", uart); - platdev = uart_devices[cfg->hwport]; - uart_devs[uart] = platdev; - platdev->dev.platform_data = cfg; - } - uart_count = uart; -} +struct platform_device w90p910_serial_device = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM, + .dev = { + .platform_data = w90p910_uart_data, + }, +}; /*Init W90P910 evb io*/ @@ -122,13 +88,6 @@ static int __init w90p910_init_cpu(void) static int __init w90x900_arch_init(void) { - int ret; - - ret = w90p910_init_cpu(); - if (ret != 0) - return ret; - - return platform_add_devices(uart_devs, uart_count); - + return w90p910_init_cpu(); } arch_initcall(w90x900_arch_init); -- GitLab From b4e411294a193e18c41912bc3df03f5b9cd7c823 Mon Sep 17 00:00:00 2001 From: Kristoffer Ericson Date: Wed, 4 Feb 2009 16:47:38 +0100 Subject: [PATCH 1533/4982] [ARM] 5375/1: PATCH - update jornada720.c to reflect driver additions This patch updates the list of devices activated at init to also include the keyboard and touchscreen structs. We also remove a non-needed #ifdef. Signed-off-by: Kristoffer Ericson Signed-off-by: Russell King --- arch/arm/mach-sa1100/jornada720.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c index 81848aa9642..fd776bb666c 100644 --- a/arch/arm/mach-sa1100/jornada720.c +++ b/arch/arm/mach-sa1100/jornada720.c @@ -226,12 +226,22 @@ static struct platform_device jornada_ssp_device = { .id = -1, }; +static struct platform_device jornada_kbd_device = { + .name = "jornada720_kbd", + .id = -1, +}; + +static struct platform_device jornada_ts_device = { + .name = "jornada_ts", + .id = -1, +}; + static struct platform_device *devices[] __initdata = { &sa1111_device, -#ifdef CONFIG_SA1100_JORNADA720_SSP &jornada_ssp_device, -#endif &s1d13xxxfb_device, + &jornada_kbd_device, + &jornada_ts_device, }; static int __init jornada720_init(void) -- GitLab From 0d4ff4df341208b1b75e01feca27301c0dcbf490 Mon Sep 17 00:00:00 2001 From: Jaya Kumar Date: Thu, 1 Jan 2009 17:49:19 +0100 Subject: [PATCH 1534/4982] [ARM] 5353/1: fbdev: add E-Ink Broadsheet controller support v3 This patch adds support for the E-Ink Broadsheet display controller. Cc: Eric Miao Signed-off-by: Jaya Kumar Signed-off-by: Russell King --- drivers/video/Kconfig | 14 + drivers/video/Makefile | 1 + drivers/video/broadsheetfb.c | 568 +++++++++++++++++++++++++++++++++++ include/video/broadsheetfb.h | 59 ++++ 4 files changed, 642 insertions(+) create mode 100644 drivers/video/broadsheetfb.c create mode 100644 include/video/broadsheetfb.h diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index f0267706cb4..5aa099bc769 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -2135,6 +2135,20 @@ config FB_MX3 far only synchronous displays are supported. If you plan to use an LCD display with your i.MX31 system, say Y here. +config FB_BROADSHEET + tristate "E-Ink Broadsheet/Epson S1D13521 controller support" + depends on FB + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_SYS_FOPS + select FB_DEFERRED_IO + help + This driver implements support for the E-Ink Broadsheet + controller. The release name for this device was Epson S1D13521 + and could also have been called by other names when coupled with + a bridge adapter. + source "drivers/video/omap/Kconfig" source "drivers/video/backlight/Kconfig" diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 2a998ca6181..edd5a85c1eb 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -106,6 +106,7 @@ obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o obj-$(CONFIG_FB_MAXINE) += maxinefb.o obj-$(CONFIG_FB_METRONOME) += metronomefb.o +obj-$(CONFIG_FB_BROADSHEET) += broadsheetfb.o obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o obj-$(CONFIG_FB_SH7760) += sh7760fb.o obj-$(CONFIG_FB_IMX) += imxfb.o diff --git a/drivers/video/broadsheetfb.c b/drivers/video/broadsheetfb.c new file mode 100644 index 00000000000..509cb92e873 --- /dev/null +++ b/drivers/video/broadsheetfb.c @@ -0,0 +1,568 @@ +/* + * broadsheetfb.c -- FB driver for E-Ink Broadsheet controller + * + * Copyright (C) 2008, Jaya Kumar + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + * + * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven. + * + * This driver is written to be used with the Broadsheet display controller. + * + * It is intended to be architecture independent. A board specific driver + * must be used to perform all the physical IO interactions. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + Virtual Master Control API +!Esound/core/vmaster.c +!Iinclude/sound/control.h + MIDI API Raw MIDI API diff --git a/include/sound/control.h b/include/sound/control.h index 4cf8f7aaa13..ef96f07aa03 100644 --- a/include/sound/control.h +++ b/include/sound/control.h @@ -176,12 +176,44 @@ int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave, /* optional flags for slave */ #define SND_CTL_SLAVE_NEED_UPDATE (1 << 0) +/** + * snd_ctl_add_slave - Add a virtual slave control + * @master: vmaster element + * @slave: slave element to add + * + * Add a virtual slave control to the given master element created via + * snd_ctl_create_virtual_master() beforehand. + * Returns zero if successful or a negative error code. + * + * All slaves must be the same type (returning the same information + * via info callback). The fucntion doesn't check it, so it's your + * responsibility. + * + * Also, some additional limitations: + * at most two channels, + * logarithmic volume control (dB level) thus no linear volume, + * master can only attenuate the volume without gain + */ static inline int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave) { return _snd_ctl_add_slave(master, slave, 0); } +/** + * snd_ctl_add_slave_uncached - Add a virtual slave control + * @master: vmaster element + * @slave: slave element to add + * + * Add a virtual slave control to the given master. + * Unlike snd_ctl_add_slave(), the element added via this function + * is supposed to have volatile values, and get callback is called + * at each time quried from the master. + * + * When the control peeks the hardware values directly and the value + * can be changed by other means than the put callback of the element, + * this function should be used to keep the value always up-to-date. + */ static inline int snd_ctl_add_slave_uncached(struct snd_kcontrol *master, struct snd_kcontrol *slave) diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c index d51b198d06d..257624bd199 100644 --- a/sound/core/vmaster.c +++ b/sound/core/vmaster.c @@ -340,8 +340,20 @@ static void master_free(struct snd_kcontrol *kcontrol) } -/* - * Create a virtual master control with the given name +/** + * snd_ctl_make_virtual_master - Create a virtual master control + * @name: name string of the control element to create + * @tlv: optional TLV int array for dB information + * + * Creates a virtual matster control with the given name string. + * Returns the created control element, or NULL for errors (ENOMEM). + * + * After creating a vmaster element, you can add the slave controls + * via snd_ctl_add_slave() or snd_ctl_add_slave_uncached(). + * + * The optional argument @tlv can be used to specify the TLV information + * for dB scale of the master control. It should be a single element + * with #SNDRV_CTL_TLVT_DB_SCALE type, and should be the max 0dB. */ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name, const unsigned int *tlv) -- GitLab From 662c319ae4b4fb60001816dfe1dde5fdfc7a2af9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 9 Feb 2009 08:53:50 +0100 Subject: [PATCH 2967/4982] ALSA: Add sound/core/jack.c to driver-API docbook entry Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl index 9d644f7e241..37b006cdf2f 100644 --- a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl +++ b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl @@ -88,6 +88,9 @@ Miscellaneous Functions Hardware-Dependent Devices API !Esound/core/hwdep.c + + Jack Abstraction Layer API +!Esound/core/jack.c ISA DMA Helpers !Esound/core/isadma.c -- GitLab From 118dd6bfe7e0cddc8ab417ead19cc76000e92773 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 23 Feb 2009 16:35:21 +0100 Subject: [PATCH 2968/4982] ALSA: Clean up snd_monitor_file management Use the standard linked list for snd_monitor_file management. Also, move the list deletion of shutdown_list element into snd_disconnect_release() (for simplification). Signed-off-by: Takashi Iwai --- include/sound/core.h | 6 +++--- sound/core/init.c | 42 +++++++++++++++--------------------------- 2 files changed, 18 insertions(+), 30 deletions(-) diff --git a/include/sound/core.h b/include/sound/core.h index f632484bc74..bd4529e0c27 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -97,9 +97,9 @@ struct snd_device { struct snd_monitor_file { struct file *file; - struct snd_monitor_file *next; const struct file_operations *disconnected_f_op; - struct list_head shutdown_list; + struct list_head shutdown_list; /* still need to shutdown */ + struct list_head list; /* link of monitor files */ }; /* main structure for soundcard */ @@ -134,7 +134,7 @@ struct snd_card { struct snd_info_entry *proc_id; /* the card id */ struct proc_dir_entry *proc_root_link; /* number link to real id */ - struct snd_monitor_file *files; /* all files associated to this card */ + struct list_head files_list; /* all files associated to this card */ struct snd_shutdown_f_ops *s_f_ops; /* file operations in the shutdown state */ spinlock_t files_lock; /* lock the files for this card */ diff --git a/sound/core/init.c b/sound/core/init.c index 0d5520c415d..05c6da554cb 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -195,6 +195,7 @@ struct snd_card *snd_card_new(int idx, const char *xid, INIT_LIST_HEAD(&card->controls); INIT_LIST_HEAD(&card->ctl_files); spin_lock_init(&card->files_lock); + INIT_LIST_HEAD(&card->files_list); init_waitqueue_head(&card->shutdown_sleep); #ifdef CONFIG_PM mutex_init(&card->power_lock); @@ -259,6 +260,7 @@ static int snd_disconnect_release(struct inode *inode, struct file *file) list_for_each_entry(_df, &shutdown_files, shutdown_list) { if (_df->file == file) { df = _df; + list_del_init(&df->shutdown_list); break; } } @@ -347,8 +349,7 @@ int snd_card_disconnect(struct snd_card *card) /* phase 2: replace file->f_op with special dummy operations */ spin_lock(&card->files_lock); - mfile = card->files; - while (mfile) { + list_for_each_entry(mfile, &card->files_list, list) { file = mfile->file; /* it's critical part, use endless loop */ @@ -361,8 +362,6 @@ int snd_card_disconnect(struct snd_card *card) mfile->file->f_op = &snd_shutdown_f_ops; fops_get(mfile->file->f_op); - - mfile = mfile->next; } spin_unlock(&card->files_lock); @@ -442,7 +441,7 @@ int snd_card_free_when_closed(struct snd_card *card) return ret; spin_lock(&card->files_lock); - if (card->files == NULL) + if (list_empty(&card->files_list)) free_now = 1; else card->free_on_last_close = 1; @@ -462,7 +461,7 @@ int snd_card_free(struct snd_card *card) return ret; /* wait, until all devices are ready for the free operation */ - wait_event(card->shutdown_sleep, card->files == NULL); + wait_event(card->shutdown_sleep, list_empty(&card->files_list)); snd_card_do_free(card); return 0; } @@ -809,15 +808,13 @@ int snd_card_file_add(struct snd_card *card, struct file *file) return -ENOMEM; mfile->file = file; mfile->disconnected_f_op = NULL; - mfile->next = NULL; spin_lock(&card->files_lock); if (card->shutdown) { spin_unlock(&card->files_lock); kfree(mfile); return -ENODEV; } - mfile->next = card->files; - card->files = mfile; + list_add(&mfile->list, &card->files_list); spin_unlock(&card->files_lock); return 0; } @@ -839,29 +836,20 @@ EXPORT_SYMBOL(snd_card_file_add); */ int snd_card_file_remove(struct snd_card *card, struct file *file) { - struct snd_monitor_file *mfile, *pfile = NULL; + struct snd_monitor_file *mfile, *found = NULL; int last_close = 0; spin_lock(&card->files_lock); - mfile = card->files; - while (mfile) { + list_for_each_entry(mfile, &card->files_list, list) { if (mfile->file == file) { - if (pfile) - pfile->next = mfile->next; - else - card->files = mfile->next; + list_del(&mfile->list); + if (mfile->disconnected_f_op) + fops_put(mfile->disconnected_f_op); + found = mfile; break; } - pfile = mfile; - mfile = mfile->next; - } - if (mfile && mfile->disconnected_f_op) { - fops_put(mfile->disconnected_f_op); - spin_lock(&shutdown_lock); - list_del(&mfile->shutdown_list); - spin_unlock(&shutdown_lock); } - if (card->files == NULL) + if (list_empty(&card->files_list)) last_close = 1; spin_unlock(&card->files_lock); if (last_close) { @@ -869,11 +857,11 @@ int snd_card_file_remove(struct snd_card *card, struct file *file) if (card->free_on_last_close) snd_card_do_free(card); } - if (!mfile) { + if (!found) { snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file); return -ENOENT; } - kfree(mfile); + kfree(found); return 0; } -- GitLab From f9d202833d0beac09ef1c6a41305151da4fe5d4c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 11 Feb 2009 14:55:59 +0100 Subject: [PATCH 2969/4982] ALSA: rawmidi - Fix possible race in open The module refcount should be handled in the register_mutex to avoid possible races with module unloading. Signed-off-by: Takashi Iwai --- sound/core/rawmidi.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 002777ba336..60f33e9412a 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -237,15 +237,16 @@ int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice, rfile->input = rfile->output = NULL; mutex_lock(®ister_mutex); rmidi = snd_rawmidi_search(card, device); - mutex_unlock(®ister_mutex); if (rmidi == NULL) { - err = -ENODEV; - goto __error1; + mutex_unlock(®ister_mutex); + return -ENODEV; } if (!try_module_get(rmidi->card->module)) { - err = -EFAULT; - goto __error1; + mutex_unlock(®ister_mutex); + return -ENXIO; } + mutex_unlock(®ister_mutex); + if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK)) mutex_lock(&rmidi->open_mutex); if (mode & SNDRV_RAWMIDI_LFLG_INPUT) { @@ -370,10 +371,9 @@ int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice, snd_rawmidi_runtime_free(sinput); if (output != NULL) snd_rawmidi_runtime_free(soutput); - module_put(rmidi->card->module); if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK)) mutex_unlock(&rmidi->open_mutex); - __error1: + module_put(rmidi->card->module); return err; } -- GitLab From 9a1b64caac82aa02cb74587ffc798e6f42c6170a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 11 Feb 2009 17:03:49 +0100 Subject: [PATCH 2970/4982] ALSA: rawmidi - Refactor rawmidi open/close codes Refactor rawmidi open/close code messes. Signed-off-by: Takashi Iwai --- include/sound/rawmidi.h | 1 - sound/core/rawmidi.c | 377 +++++++++++++++++++++------------------- 2 files changed, 194 insertions(+), 184 deletions(-) diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h index b550a416d07..c23c2658570 100644 --- a/include/sound/rawmidi.h +++ b/include/sound/rawmidi.h @@ -42,7 +42,6 @@ #define SNDRV_RAWMIDI_LFLG_INPUT (1<<1) #define SNDRV_RAWMIDI_LFLG_OPEN (3<<0) #define SNDRV_RAWMIDI_LFLG_APPEND (1<<2) -#define SNDRV_RAWMIDI_LFLG_NOOPENLOCK (1<<3) struct snd_rawmidi; struct snd_rawmidi_substream; diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 60f33e9412a..473247c8e6d 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -224,156 +224,143 @@ int snd_rawmidi_drain_input(struct snd_rawmidi_substream *substream) return 0; } -int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice, - int mode, struct snd_rawmidi_file * rfile) +/* look for an available substream for the given stream direction; + * if a specific subdevice is given, try to assign it + */ +static int assign_substream(struct snd_rawmidi *rmidi, int subdevice, + int stream, int mode, + struct snd_rawmidi_substream **sub_ret) { - struct snd_rawmidi *rmidi; - struct list_head *list1, *list2; - struct snd_rawmidi_substream *sinput = NULL, *soutput = NULL; - struct snd_rawmidi_runtime *input = NULL, *output = NULL; - int err; + struct snd_rawmidi_substream *substream; + struct snd_rawmidi_str *s = &rmidi->streams[stream]; + static unsigned int info_flags[2] = { + [SNDRV_RAWMIDI_STREAM_OUTPUT] = SNDRV_RAWMIDI_INFO_OUTPUT, + [SNDRV_RAWMIDI_STREAM_INPUT] = SNDRV_RAWMIDI_INFO_INPUT, + }; - if (rfile) - rfile->input = rfile->output = NULL; - mutex_lock(®ister_mutex); - rmidi = snd_rawmidi_search(card, device); - if (rmidi == NULL) { - mutex_unlock(®ister_mutex); - return -ENODEV; - } - if (!try_module_get(rmidi->card->module)) { - mutex_unlock(®ister_mutex); + if (!(rmidi->info_flags & info_flags[stream])) return -ENXIO; + if (subdevice >= 0 && subdevice >= s->substream_count) + return -ENODEV; + if (s->substream_opened >= s->substream_count) + return -EAGAIN; + + list_for_each_entry(substream, &s->substreams, list) { + if (substream->opened) { + if (stream == SNDRV_RAWMIDI_STREAM_INPUT || + !(mode & SNDRV_RAWMIDI_LFLG_APPEND)) + continue; + } + if (subdevice < 0 || subdevice == substream->number) { + *sub_ret = substream; + return 0; + } } - mutex_unlock(®ister_mutex); + return -EAGAIN; +} - if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK)) - mutex_lock(&rmidi->open_mutex); +/* open and do ref-counting for the given substream */ +static int open_substream(struct snd_rawmidi *rmidi, + struct snd_rawmidi_substream *substream, + int mode) +{ + int err; + + err = snd_rawmidi_runtime_create(substream); + if (err < 0) + return err; + err = substream->ops->open(substream); + if (err < 0) + return err; + substream->opened = 1; + if (substream->use_count++ == 0) + substream->active_sensing = 1; + if (mode & SNDRV_RAWMIDI_LFLG_APPEND) + substream->append = 1; + rmidi->streams[substream->stream].substream_opened++; + return 0; +} + +static void close_substream(struct snd_rawmidi *rmidi, + struct snd_rawmidi_substream *substream, + int cleanup); + +static int rawmidi_open_priv(struct snd_rawmidi *rmidi, int subdevice, int mode, + struct snd_rawmidi_file *rfile) +{ + struct snd_rawmidi_substream *sinput = NULL, *soutput = NULL; + int err; + + rfile->input = rfile->output = NULL; if (mode & SNDRV_RAWMIDI_LFLG_INPUT) { - if (!(rmidi->info_flags & SNDRV_RAWMIDI_INFO_INPUT)) { - err = -ENXIO; - goto __error; - } - if (subdevice >= 0 && (unsigned int)subdevice >= rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_count) { - err = -ENODEV; - goto __error; - } - if (rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened >= - rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_count) { - err = -EAGAIN; + err = assign_substream(rmidi, subdevice, + SNDRV_RAWMIDI_STREAM_INPUT, + mode, &sinput); + if (err < 0) goto __error; - } } if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { - if (!(rmidi->info_flags & SNDRV_RAWMIDI_INFO_OUTPUT)) { - err = -ENXIO; - goto __error; - } - if (subdevice >= 0 && (unsigned int)subdevice >= rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_count) { - err = -ENODEV; - goto __error; - } - if (rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened >= - rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_count) { - err = -EAGAIN; + err = assign_substream(rmidi, subdevice, + SNDRV_RAWMIDI_STREAM_OUTPUT, + mode, &soutput); + if (err < 0) goto __error; - } - } - list1 = rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams.next; - while (1) { - if (list1 == &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) { - sinput = NULL; - if (mode & SNDRV_RAWMIDI_LFLG_INPUT) { - err = -EAGAIN; - goto __error; - } - break; - } - sinput = list_entry(list1, struct snd_rawmidi_substream, list); - if ((mode & SNDRV_RAWMIDI_LFLG_INPUT) && sinput->opened) - goto __nexti; - if (subdevice < 0 || (subdevice >= 0 && subdevice == sinput->number)) - break; - __nexti: - list1 = list1->next; - } - list2 = rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams.next; - while (1) { - if (list2 == &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) { - soutput = NULL; - if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { - err = -EAGAIN; - goto __error; - } - break; - } - soutput = list_entry(list2, struct snd_rawmidi_substream, list); - if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { - if (mode & SNDRV_RAWMIDI_LFLG_APPEND) { - if (soutput->opened && !soutput->append) - goto __nexto; - } else { - if (soutput->opened) - goto __nexto; - } - } - if (subdevice < 0 || (subdevice >= 0 && subdevice == soutput->number)) - break; - __nexto: - list2 = list2->next; } - if (mode & SNDRV_RAWMIDI_LFLG_INPUT) { - if ((err = snd_rawmidi_runtime_create(sinput)) < 0) - goto __error; - input = sinput->runtime; - if ((err = sinput->ops->open(sinput)) < 0) + + if (sinput) { + err = open_substream(rmidi, sinput, mode); + if (err < 0) goto __error; - sinput->opened = 1; - rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened++; - } else { - sinput = NULL; } - if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { - if (soutput->opened) - goto __skip_output; - if ((err = snd_rawmidi_runtime_create(soutput)) < 0) { - if (mode & SNDRV_RAWMIDI_LFLG_INPUT) - sinput->ops->close(sinput); - goto __error; - } - output = soutput->runtime; - if ((err = soutput->ops->open(soutput)) < 0) { - if (mode & SNDRV_RAWMIDI_LFLG_INPUT) - sinput->ops->close(sinput); + if (soutput) { + err = open_substream(rmidi, soutput, mode); + if (err < 0) { + if (sinput) + close_substream(rmidi, sinput, 0); goto __error; } - __skip_output: - soutput->opened = 1; - if (mode & SNDRV_RAWMIDI_LFLG_APPEND) - soutput->append = 1; - if (soutput->use_count++ == 0) - soutput->active_sensing = 1; - rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened++; - } else { - soutput = NULL; - } - if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK)) - mutex_unlock(&rmidi->open_mutex); - if (rfile) { - rfile->rmidi = rmidi; - rfile->input = sinput; - rfile->output = soutput; } + + rfile->rmidi = rmidi; + rfile->input = sinput; + rfile->output = soutput; return 0; __error: - if (input != NULL) + if (sinput && sinput->runtime) snd_rawmidi_runtime_free(sinput); - if (output != NULL) + if (soutput && soutput->runtime) snd_rawmidi_runtime_free(soutput); - if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK)) - mutex_unlock(&rmidi->open_mutex); - module_put(rmidi->card->module); + return err; +} + +/* called from sound/core/seq/seq_midi.c */ +int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice, + int mode, struct snd_rawmidi_file * rfile) +{ + struct snd_rawmidi *rmidi; + int err; + + if (snd_BUG_ON(!rfile)) + return -EINVAL; + + mutex_lock(®ister_mutex); + rmidi = snd_rawmidi_search(card, device); + if (rmidi == NULL) { + mutex_unlock(®ister_mutex); + return -ENODEV; + } + if (!try_module_get(rmidi->card->module)) { + mutex_unlock(®ister_mutex); + return -ENXIO; + } + mutex_unlock(®ister_mutex); + + mutex_lock(&rmidi->open_mutex); + err = rawmidi_open_priv(rmidi, subdevice, mode, rfile); + mutex_unlock(&rmidi->open_mutex); + if (err < 0) + module_put(rmidi->card->module); return err; } @@ -385,10 +372,13 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) unsigned short fflags; int err; struct snd_rawmidi *rmidi; - struct snd_rawmidi_file *rawmidi_file; + struct snd_rawmidi_file *rawmidi_file = NULL; wait_queue_t wait; struct snd_ctl_file *kctl; + if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) + return -EINVAL; /* invalid combination */ + if (maj == snd_major) { rmidi = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_RAWMIDI); @@ -402,24 +392,25 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) if (rmidi == NULL) return -ENODEV; - if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) - return -EINVAL; /* invalid combination */ + + if (!try_module_get(rmidi->card->module)) + return -ENXIO; + + mutex_lock(&rmidi->open_mutex); card = rmidi->card; err = snd_card_file_add(card, file); if (err < 0) - return -ENODEV; + goto __error_card; fflags = snd_rawmidi_file_flags(file); if ((file->f_flags & O_APPEND) || maj == SOUND_MAJOR) /* OSS emul? */ fflags |= SNDRV_RAWMIDI_LFLG_APPEND; - fflags |= SNDRV_RAWMIDI_LFLG_NOOPENLOCK; rawmidi_file = kmalloc(sizeof(*rawmidi_file), GFP_KERNEL); if (rawmidi_file == NULL) { - snd_card_file_remove(card, file); - return -ENOMEM; + err = -ENOMEM; + goto __error; } init_waitqueue_entry(&wait, current); add_wait_queue(&rmidi->open_wait, &wait); - mutex_lock(&rmidi->open_mutex); while (1) { subdevice = -1; read_lock(&card->ctl_files_rwlock); @@ -431,8 +422,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) } } read_unlock(&card->ctl_files_rwlock); - err = snd_rawmidi_kernel_open(rmidi->card, rmidi->device, - subdevice, fflags, rawmidi_file); + err = rawmidi_open_priv(rmidi, subdevice, fflags, rawmidi_file); if (err >= 0) break; if (err == -EAGAIN) { @@ -451,67 +441,89 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) break; } } + remove_wait_queue(&rmidi->open_wait, &wait); + if (err < 0) { + kfree(rawmidi_file); + goto __error; + } #ifdef CONFIG_SND_OSSEMUL if (rawmidi_file->input && rawmidi_file->input->runtime) rawmidi_file->input->runtime->oss = (maj == SOUND_MAJOR); if (rawmidi_file->output && rawmidi_file->output->runtime) rawmidi_file->output->runtime->oss = (maj == SOUND_MAJOR); #endif - remove_wait_queue(&rmidi->open_wait, &wait); - if (err >= 0) { - file->private_data = rawmidi_file; - } else { - snd_card_file_remove(card, file); - kfree(rawmidi_file); - } + file->private_data = rawmidi_file; mutex_unlock(&rmidi->open_mutex); + return 0; + + __error: + snd_card_file_remove(card, file); + __error_card: + mutex_unlock(&rmidi->open_mutex); + module_put(rmidi->card->module); return err; } -int snd_rawmidi_kernel_release(struct snd_rawmidi_file * rfile) +static void close_substream(struct snd_rawmidi *rmidi, + struct snd_rawmidi_substream *substream, + int cleanup) { - struct snd_rawmidi *rmidi; - struct snd_rawmidi_substream *substream; - struct snd_rawmidi_runtime *runtime; + rmidi->streams[substream->stream].substream_opened--; + if (--substream->use_count) + return; - if (snd_BUG_ON(!rfile)) - return -ENXIO; - rmidi = rfile->rmidi; - mutex_lock(&rmidi->open_mutex); - if (rfile->input != NULL) { - substream = rfile->input; - rfile->input = NULL; - runtime = substream->runtime; - snd_rawmidi_input_trigger(substream, 0); - substream->ops->close(substream); - if (runtime->private_free != NULL) - runtime->private_free(substream); - snd_rawmidi_runtime_free(substream); - substream->opened = 0; - rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened--; - } - if (rfile->output != NULL) { - substream = rfile->output; - rfile->output = NULL; - if (--substream->use_count == 0) { - runtime = substream->runtime; + if (cleanup) { + if (substream->stream == SNDRV_RAWMIDI_STREAM_INPUT) + snd_rawmidi_input_trigger(substream, 0); + else { if (substream->active_sensing) { unsigned char buf = 0xfe; - /* sending single active sensing message to shut the device up */ + /* sending single active sensing message + * to shut the device up + */ snd_rawmidi_kernel_write(substream, &buf, 1); } if (snd_rawmidi_drain_output(substream) == -ERESTARTSYS) snd_rawmidi_output_trigger(substream, 0); - substream->ops->close(substream); - if (runtime->private_free != NULL) - runtime->private_free(substream); - snd_rawmidi_runtime_free(substream); - substream->opened = 0; - substream->append = 0; } - rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened--; } + substream->ops->close(substream); + if (substream->runtime->private_free) + substream->runtime->private_free(substream); + snd_rawmidi_runtime_free(substream); + substream->opened = 0; + substream->append = 0; +} + +static void rawmidi_release_priv(struct snd_rawmidi_file *rfile) +{ + struct snd_rawmidi *rmidi; + + rmidi = rfile->rmidi; + mutex_lock(&rmidi->open_mutex); + if (rfile->input) { + close_substream(rmidi, rfile->input, 1); + rfile->input = NULL; + } + if (rfile->output) { + close_substream(rmidi, rfile->output, 1); + rfile->output = NULL; + } + rfile->rmidi = NULL; mutex_unlock(&rmidi->open_mutex); + wake_up(&rmidi->open_wait); +} + +/* called from sound/core/seq/seq_midi.c */ +int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile) +{ + struct snd_rawmidi *rmidi; + + if (snd_BUG_ON(!rfile)) + return -ENXIO; + + rmidi = rfile->rmidi; + rawmidi_release_priv(rfile); module_put(rmidi->card->module); return 0; } @@ -520,15 +532,14 @@ static int snd_rawmidi_release(struct inode *inode, struct file *file) { struct snd_rawmidi_file *rfile; struct snd_rawmidi *rmidi; - int err; rfile = file->private_data; - err = snd_rawmidi_kernel_release(rfile); rmidi = rfile->rmidi; - wake_up(&rmidi->open_wait); + rawmidi_release_priv(rfile); kfree(rfile); snd_card_file_remove(rmidi->card, file); - return err; + module_put(rmidi->card->module); + return 0; } static int snd_rawmidi_info(struct snd_rawmidi_substream *substream, -- GitLab From 5f8206c04857965cc2ff6c395633c4fdd977dd77 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 9 Feb 2009 08:50:43 +0100 Subject: [PATCH 2971/4982] ALSA: Fix DocBook headers Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl | 10 ++++++---- .../sound/alsa/DocBook/writing-an-alsa-driver.tmpl | 8 ++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl index 90f163c4bde..0230a96f056 100644 --- a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl +++ b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl @@ -1,11 +1,11 @@ - - - - + + + The ALSA Driver API @@ -35,6 +35,8 @@ + + Management of Cards and Devices Card Management !Esound/core/init.c diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index 320384c1791..46b08fef374 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -1,11 +1,11 @@ - - - - + + + Writing an ALSA Driver -- GitLab From e776ec19a47a325ee1d9ece2d983526dcd626c53 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 28 Feb 2009 17:40:18 +0100 Subject: [PATCH 2972/4982] ALSA: Move ALSA docbooks to be with the rest of the kernel docbooks Move ALSA docbooks to be with the rest of the kernel docbooks and add them to the Makefile so that they build. Latter required a few minor changes to alsa .tmpl files. (I did not remove all of the trailing whitespace in the .tmpl files.) Fixes kernel bugzilla #12726: http://bugzilla.kernel.org/show_bug.cgi?id=12726 Signed-off-by: Randy Dunlap Cc: documentation_man-pages@kernel-bugs.osdl.org Cc: Nicola Soranzo Signed-off-by: Takashi Iwai --- Documentation/DocBook/Makefile | 3 ++- Documentation/{sound/alsa => }/DocBook/alsa-driver-api.tmpl | 0 .../{sound/alsa => }/DocBook/writing-an-alsa-driver.tmpl | 0 3 files changed, 2 insertions(+), 1 deletion(-) rename Documentation/{sound/alsa => }/DocBook/alsa-driver-api.tmpl (100%) rename Documentation/{sound/alsa => }/DocBook/writing-an-alsa-driver.tmpl (100%) diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 1462ed86d40..a3a83d38f96 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -12,7 +12,8 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \ kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \ gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \ genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \ - mac80211.xml debugobjects.xml sh.xml regulator.xml + mac80211.xml debugobjects.xml sh.xml regulator.xml \ + alsa-driver-api.xml writing-an-alsa-driver.xml ### # The build process is as follows (targets): diff --git a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl b/Documentation/DocBook/alsa-driver-api.tmpl similarity index 100% rename from Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl rename to Documentation/DocBook/alsa-driver-api.tmpl diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/DocBook/writing-an-alsa-driver.tmpl similarity index 100% rename from Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl rename to Documentation/DocBook/writing-an-alsa-driver.tmpl -- GitLab From 6b849bcff0004aa5dd216b4d3eb56f51c9df8a72 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 9 Mar 2009 18:18:33 +0000 Subject: [PATCH 2973/4982] ASoC: Convert PXA AC97 driver to probe with the platform device This will break any boards that don't register the AC97 controller device due to using ASoC. Signed-off-by: Mark Brown --- sound/soc/pxa/pxa2xx-ac97.c | 38 +++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index 812c2b4d3e0..49a2810ca58 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c @@ -106,13 +106,13 @@ static int pxa2xx_ac97_resume(struct snd_soc_dai *dai) static int pxa2xx_ac97_probe(struct platform_device *pdev, struct snd_soc_dai *dai) { - return pxa2xx_ac97_hw_probe(pdev); + return pxa2xx_ac97_hw_probe(to_platform_device(dai->dev)); } static void pxa2xx_ac97_remove(struct platform_device *pdev, struct snd_soc_dai *dai) { - pxa2xx_ac97_hw_remove(pdev); + pxa2xx_ac97_hw_remove(to_platform_device(dai->dev)); } static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream, @@ -229,15 +229,45 @@ struct snd_soc_dai pxa_ac97_dai[] = { EXPORT_SYMBOL_GPL(pxa_ac97_dai); EXPORT_SYMBOL_GPL(soc_ac97_ops); -static int __init pxa_ac97_init(void) +static int __devinit pxa2xx_ac97_dev_probe(struct platform_device *pdev) { + int i; + + for (i = 0; i < ARRAY_SIZE(pxa_ac97_dai); i++) + pxa_ac97_dai[i].dev = &pdev->dev; + + /* Punt most of the init to the SoC probe; we may need the machine + * driver to do interesting things with the clocking to get us up + * and running. + */ return snd_soc_register_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); } + +static int __devexit pxa2xx_ac97_dev_remove(struct platform_device *pdev) +{ + snd_soc_unregister_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); + + return 0; +} + +static struct platform_driver pxa2xx_ac97_driver = { + .probe = pxa2xx_ac97_dev_probe, + .remove = __devexit_p(pxa2xx_ac97_dev_remove), + .driver = { + .name = "pxa2xx-ac97", + .owner = THIS_MODULE, + }, +}; + +static int __init pxa_ac97_init(void) +{ + return platform_driver_register(&pxa2xx_ac97_driver); +} module_init(pxa_ac97_init); static void __exit pxa_ac97_exit(void) { - snd_soc_unregister_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); + platform_driver_unregister(&pxa2xx_ac97_driver); } module_exit(pxa_ac97_exit); -- GitLab From eac84739721857f4d5be3d9127f4644f16a9bea4 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 9 Mar 2009 17:47:13 +0000 Subject: [PATCH 2974/4982] ASoC: Fix Samsung S3C2412_IISMOD_SDF_{MSB,LSB} definitions The definitions of S3C2412_IISMOD_SDF_MSB and S3C2412_IISMOD_SDF_LSB are incorrect, being the same S3C2412_IISMOD_SDF_IIS which is the only correct one in this series. Signed-off-by: Ben Dooks Signed-off-by: Mark Brown --- arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h b/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h index a5600b381d4..0fad7571030 100644 --- a/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h +++ b/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h @@ -47,8 +47,8 @@ #define S3C2412_IISMOD_LR_LLOW (0 << 7) #define S3C2412_IISMOD_LR_RLOW (1 << 7) #define S3C2412_IISMOD_SDF_IIS (0 << 5) -#define S3C2412_IISMOD_SDF_MSB (0 << 5) -#define S3C2412_IISMOD_SDF_LSB (0 << 5) +#define S3C2412_IISMOD_SDF_MSB (1 << 5) +#define S3C2412_IISMOD_SDF_LSB (2 << 5) #define S3C2412_IISMOD_SDF_MASK (3 << 5) #define S3C2412_IISMOD_RCLK_256FS (0 << 3) #define S3C2412_IISMOD_RCLK_512FS (1 << 3) -- GitLab From df7f54c012b92ec93d56b68547351dcdf8a163d3 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Mon, 9 Mar 2009 14:35:58 -0400 Subject: [PATCH 2975/4982] SELinux: inode_doinit_with_dentry drop no dentry printk Drop the printk message when an inode is found without an associated dentry. This should only happen when userspace can't be accessing those inodes and those labels will get set correctly on the next d_instantiate. Thus there is no reason to send this message. Signed-off-by: Eric Paris Signed-off-by: James Morris --- security/selinux/hooks.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index cd3307a26d1..7c52ba243c6 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1263,9 +1263,15 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent dentry = d_find_alias(inode); } if (!dentry) { - printk(KERN_WARNING "SELinux: %s: no dentry for dev=%s " - "ino=%ld\n", __func__, inode->i_sb->s_id, - inode->i_ino); + /* + * this is can be hit on boot when a file is accessed + * before the policy is loaded. When we load policy we + * may find inodes that have no dentry on the + * sbsec->isec_head list. No reason to complain as these + * will get fixed up the next time we go through + * inode_doinit with a dentry, before these inodes could + * be used again by userspace. + */ goto out_unlock; } -- GitLab From 2ef7f0dab6b3d171b6aff00a47077385ae3155b5 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 6 Mar 2009 09:47:02 +0000 Subject: [PATCH 2976/4982] sh: hibernation support Add Suspend-to-disk / swsusp / CONFIG_HIBERNATION support to the SuperH architecture. To suspend, use "swapon /dev/sda2; echo disk > /sys/power/state" To resume, pass "resume=/dev/sda2" on the kernel command line. The patch "pm: rework includes, remove arch ifdefs V2" is needed to allow the generic swsusp code to build properly. Hibernation is not enabled with this patch though, a patch setting ARCH_HIBERNATION_POSSIBLE will be submitted later. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/include/asm/sections.h | 1 + arch/sh/include/asm/suspend.h | 13 +++ arch/sh/kernel/Makefile_32 | 1 + arch/sh/kernel/asm-offsets.c | 8 ++ arch/sh/kernel/cpu/sh3/Makefile | 2 + arch/sh/kernel/cpu/sh3/entry.S | 22 +++-- arch/sh/kernel/cpu/sh3/swsusp.S | 147 ++++++++++++++++++++++++++++++++ arch/sh/kernel/cpu/sh4/Makefile | 1 + arch/sh/kernel/swsusp.c | 38 +++++++++ 9 files changed, 228 insertions(+), 5 deletions(-) create mode 100644 arch/sh/include/asm/suspend.h create mode 100644 arch/sh/kernel/cpu/sh3/swsusp.S create mode 100644 arch/sh/kernel/swsusp.c diff --git a/arch/sh/include/asm/sections.h b/arch/sh/include/asm/sections.h index 8f8f4ad400d..01a4076a371 100644 --- a/arch/sh/include/asm/sections.h +++ b/arch/sh/include/asm/sections.h @@ -3,6 +3,7 @@ #include +extern void __nosave_begin, __nosave_end; extern long __machvec_start, __machvec_end; extern char __uncached_start, __uncached_end; extern char _ebss[]; diff --git a/arch/sh/include/asm/suspend.h b/arch/sh/include/asm/suspend.h new file mode 100644 index 00000000000..5d6d8aba568 --- /dev/null +++ b/arch/sh/include/asm/suspend.h @@ -0,0 +1,13 @@ +#ifndef _ASM_SH_SUSPEND_H +#define _ASM_SH_SUSPEND_H + +static inline int arch_prepare_suspend(void) { return 0; } + +#include + +struct swsusp_arch_regs { + struct pt_regs user_regs; + unsigned long bank1_regs[8]; +}; + +#endif /* _ASM_SH_SUSPEND_H */ diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32 index 2e1b86e16ab..82a3a150c00 100644 --- a/arch/sh/kernel/Makefile_32 +++ b/arch/sh/kernel/Makefile_32 @@ -30,5 +30,6 @@ obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_GENERIC_GPIO) += gpio.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o obj-$(CONFIG_DUMP_CODE) += disassemble.o +obj-$(CONFIG_HIBERNATION) += swsusp.o EXTRA_CFLAGS += -Werror diff --git a/arch/sh/kernel/asm-offsets.c b/arch/sh/kernel/asm-offsets.c index 57cf0e0680f..99aceb28ee2 100644 --- a/arch/sh/kernel/asm-offsets.c +++ b/arch/sh/kernel/asm-offsets.c @@ -12,8 +12,10 @@ #include #include #include +#include #include +#include int main(void) { @@ -25,5 +27,11 @@ int main(void) DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count)); DEFINE(TI_RESTART_BLOCK,offsetof(struct thread_info, restart_block)); +#ifdef CONFIG_HIBERNATION + DEFINE(PBE_ADDRESS, offsetof(struct pbe, address)); + DEFINE(PBE_ORIG_ADDRESS, offsetof(struct pbe, orig_address)); + DEFINE(PBE_NEXT, offsetof(struct pbe, next)); + DEFINE(SWSUSP_ARCH_REGS_SIZE, sizeof(struct swsusp_arch_regs)); +#endif return 0; } diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile index e07c69e16d9..ecab274141a 100644 --- a/arch/sh/kernel/cpu/sh3/Makefile +++ b/arch/sh/kernel/cpu/sh3/Makefile @@ -4,6 +4,8 @@ obj-y := ex.o probe.o entry.o setup-sh3.o +obj-$(CONFIG_HIBERNATION) += swsusp.o + # CPU subtype setup obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o obj-$(CONFIG_CPU_SUBTYPE_SH7706) += setup-sh770x.o diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S index c4829d6dee5..fba6ac20bb1 100644 --- a/arch/sh/kernel/cpu/sh3/entry.S +++ b/arch/sh/kernel/cpu/sh3/entry.S @@ -216,7 +216,7 @@ ENTRY(sh_bios_handler) ! r9 trashed ! BL=0 on entry, on exit BL=1 (depending on r8). -restore_regs: +ENTRY(restore_regs) mov.l @r15+, r0 mov.l @r15+, r1 mov.l @r15+, r2 @@ -362,8 +362,10 @@ general_exception: nop ! Save registers / Switch to bank 0 + mov.l k4, k2 ! keep vector in k2 + mov.l 1f, k4 ! SR bits to clear in k4 bsr save_regs ! needs original pr value in k3 - mov k4, k2 ! keep vector in k2 + nop bra handle_exception_special nop @@ -471,6 +473,7 @@ handle_exception: ! Save registers / Switch to bank 0 mov.l 5f, k2 ! vector register address + mov.l 1f, k4 ! SR bits to clear in k4 bsr save_regs ! needs original pr value in k3 mov.l @k2, k2 ! read out vector and keep in k2 @@ -495,10 +498,10 @@ handle_exception_special: ! k0 contains original stack pointer* ! k1 trashed ! k3 passes original pr* -! k4 trashed +! k4 passes SR bitmask ! BL=1 on entry, on exit BL=0. -save_regs: +ENTRY(save_regs) mov #-1, r1 mov.l k1, @-r15 ! set TRA (default: -1) sts.l macl, @-r15 @@ -518,8 +521,16 @@ save_regs: mov.l r8, @-r15 mov.l 0f, k3 ! SR bits to set in k3 - mov.l 1f, k4 ! SR bits to clear in k4 + ! fall-through + +! save_low_regs() +! - modify SR for bank switch +! - save r7, r6, r5, r4, r3, r2, r1, r0 on the stack +! k3 passes bits to set in SR +! k4 passes bits to clear in SR + +ENTRY(save_low_regs) stc sr, r8 or k3, r8 and k4, r8 @@ -565,6 +576,7 @@ ENTRY(handle_interrupt) PREF(k0) ! Save registers / Switch to bank 0 + mov.l 1f, k4 ! SR bits to clear in k4 bsr save_regs ! needs original pr value in k3 mov #-1, k2 ! default vector kept in k2 diff --git a/arch/sh/kernel/cpu/sh3/swsusp.S b/arch/sh/kernel/cpu/sh3/swsusp.S new file mode 100644 index 00000000000..01145426a2b --- /dev/null +++ b/arch/sh/kernel/cpu/sh3/swsusp.S @@ -0,0 +1,147 @@ +/* + * arch/sh/kernel/cpu/sh3/swsusp.S + * + * Copyright (C) 2009 Magnus Damm + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include + +#define k0 r0 +#define k1 r1 +#define k2 r2 +#define k3 r3 +#define k4 r4 + +! swsusp_arch_resume() +! - copy restore_pblist pages +! - restore registers from swsusp_arch_regs_cpu0 + +ENTRY(swsusp_arch_resume) + mov.l 1f, r15 + mov.l 2f, r4 + mov.l @r4, r4 + +swsusp_copy_loop: + mov r4, r0 + cmp/eq #0, r0 + bt swsusp_restore_regs + + mov.l @(PBE_ADDRESS, r4), r2 + mov.l @(PBE_ORIG_ADDRESS, r4), r5 + + mov #(PAGE_SIZE >> 10), r3 + shll8 r3 + shlr2 r3 /* PAGE_SIZE / 16 */ +swsusp_copy_page: + dt r3 + mov.l @r2+,r1 /* 16n+0 */ + mov.l r1,@r5 + add #4,r5 + mov.l @r2+,r1 /* 16n+4 */ + mov.l r1,@r5 + add #4,r5 + mov.l @r2+,r1 /* 16n+8 */ + mov.l r1,@r5 + add #4,r5 + mov.l @r2+,r1 /* 16n+12 */ + mov.l r1,@r5 + bf/s swsusp_copy_page + add #4,r5 + + bra swsusp_copy_loop + mov.l @(PBE_NEXT, r4), r4 + +swsusp_restore_regs: + ! BL=0: R7->R0 is bank0 + mov.l 3f, r8 + mov.l 4f, r5 + jsr @r5 + nop + + ! BL=1: R7->R0 is bank1 + lds k2, pr + ldc k3, ssr + + mov.l @r15+, r0 + mov.l @r15+, r1 + mov.l @r15+, r2 + mov.l @r15+, r3 + mov.l @r15+, r4 + mov.l @r15+, r5 + mov.l @r15+, r6 + mov.l @r15+, r7 + + rte + nop + ! BL=0: R7->R0 is bank0 + + .align 2 +1: .long swsusp_arch_regs_cpu0 +2: .long restore_pblist +3: .long 0x20000000 ! RB=1 +4: .long restore_regs + +! swsusp_arch_suspend() +! - prepare pc for resume, return from function without swsusp_save on resume +! - save registers in swsusp_arch_regs_cpu0 +! - call swsusp_save write suspend image + +ENTRY(swsusp_arch_suspend) + sts pr, r0 ! save pr in r0 + mov r15, r2 ! save sp in r2 + mov r8, r5 ! save r8 in r5 + stc sr, r1 + ldc r1, ssr ! save sr in ssr + mov.l 1f, r1 + ldc r1, spc ! setup pc value for resuming + mov.l 5f, r15 ! use swsusp_arch_regs_cpu0 as stack + mov.l 6f, r3 + add r3, r15 ! save from top of structure + + ! BL=0: R7->R0 is bank0 + mov.l 2f, r3 ! get new SR value for bank1 + mov #0, r4 + mov.l 7f, r1 + jsr @r1 ! switch to bank1 and save bank1 r7->r0 + not r4, r4 + + ! BL=1: R7->R0 is bank1 + stc r2_bank, k0 ! fetch old sp from r2_bank0 + mov.l 3f, k4 ! SR bits to clear in k4 + mov.l 8f, k1 + jsr @k1 ! switch to bank0 and save all regs + stc r0_bank, k3 ! fetch old pr from r0_bank0 + + ! BL=0: R7->R0 is bank0 + mov r2, r15 ! restore old sp + mov r5, r8 ! restore old r8 + stc ssr, r1 + ldc r1, sr ! restore old sr + lds r0, pr ! restore old pr + mov.l 4f, r0 + jmp @r0 + nop + +swsusp_call_save: + mov r2, r15 ! restore old sp + mov r5, r8 ! restore old r8 + lds r0, pr ! restore old pr + rts + mov #0, r0 + + .align 2 +1: .long swsusp_call_save +2: .long 0x20000000 ! RB=1 +3: .long 0xdfffffff ! RB=0 +4: .long swsusp_save +5: .long swsusp_arch_regs_cpu0 +6: .long SWSUSP_ARCH_REGS_SIZE +7: .long save_low_regs +8: .long save_regs diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile index d608557c7a3..203b18347b8 100644 --- a/arch/sh/kernel/cpu/sh4/Makefile +++ b/arch/sh/kernel/cpu/sh4/Makefile @@ -5,6 +5,7 @@ obj-y := probe.o common.o common-y += $(addprefix ../sh3/, entry.o ex.o) +obj-$(CONFIG_HIBERNATION) += $(addprefix ../sh3/, swsusp.o) obj-$(CONFIG_SH_FPU) += fpu.o softfloat.o obj-$(CONFIG_SH_STORE_QUEUES) += sq.o diff --git a/arch/sh/kernel/swsusp.c b/arch/sh/kernel/swsusp.c new file mode 100644 index 00000000000..12b64a0f2f0 --- /dev/null +++ b/arch/sh/kernel/swsusp.c @@ -0,0 +1,38 @@ +/* + * swsusp.c - SuperH hibernation support + * + * Copyright (C) 2009 Magnus Damm + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct swsusp_arch_regs swsusp_arch_regs_cpu0; + +int pfn_is_nosave(unsigned long pfn) +{ + unsigned long begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT; + unsigned long end_pfn = PAGE_ALIGN(__pa(&__nosave_end)) >> PAGE_SHIFT; + + return (pfn >= begin_pfn) && (pfn < end_pfn); +} + +void save_processor_state(void) +{ + init_fpu(current); +} + +void restore_processor_state(void) +{ + local_flush_tlb_all(); +} -- GitLab From 508407149a7f927c4b65a20e0a08a2a94dc769c6 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 10 Mar 2009 06:13:22 +0000 Subject: [PATCH 2977/4982] sh: Show sleep state with Migo-R LEDs If CONFIG_PM is set, let Migo-R LEDs show sleep states. D11 will show STATUS0 and D12 PDSTATUS. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/boards/mach-migor/setup.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c index 28e56c5809a..bc35b4cae6b 100644 --- a/arch/sh/boards/mach-migor/setup.c +++ b/arch/sh/boards/mach-migor/setup.c @@ -450,6 +450,14 @@ static struct spi_board_info migor_spi_devices[] = { static int __init migor_devices_setup(void) { + +#ifdef CONFIG_PM + /* Let D11 LED show STATUS0 */ + gpio_request(GPIO_FN_STATUS0, NULL); + + /* Lit D12 LED show PDSTATUS */ + gpio_request(GPIO_FN_PDSTATUS, NULL); +#else /* Lit D11 LED */ gpio_request(GPIO_PTJ7, NULL); gpio_direction_output(GPIO_PTJ7, 1); @@ -459,6 +467,7 @@ static int __init migor_devices_setup(void) gpio_request(GPIO_PTJ5, NULL); gpio_direction_output(GPIO_PTJ5, 1); gpio_export(GPIO_PTJ5, 0); +#endif /* SMC91C111 - Enable IRQ0, Setup CS4 for 16-bit fast access */ gpio_request(GPIO_FN_IRQ0, NULL); -- GitLab From a29b99eccecefe5026713b226f66f117c8837ad5 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 10 Mar 2009 06:24:21 +0000 Subject: [PATCH 2978/4982] input: add suspend wakeup support to sh_keysc This patch adds wakeup support to the sh_keysc driver. With this feature the ".../power/wakeup" file can be used to enable and disable if the device takes the system out of suspend. Default is enabled. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/input/keyboard/sh_keysc.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index 5c8a1bcf7ca..bf92178644a 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -219,6 +219,8 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev) pdata->scan_timing, priv->iomem_base + KYCR1_OFFS); iowrite16(0, priv->iomem_base + KYOUTDR_OFFS); iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS); + + device_init_wakeup(&pdev->dev, 1); return 0; err5: free_irq(irq, pdev); @@ -253,17 +255,36 @@ static int __devexit sh_keysc_remove(struct platform_device *pdev) return 0; } +static int sh_keysc_suspend(struct device *dev) +{ + struct platform_device *pdev; + struct sh_keysc_priv *priv; + unsigned short value; + + pdev = container_of(dev, struct platform_device, dev); + priv = platform_get_drvdata(pdev); + + value = ioread16(priv->iomem_base + KYCR1_OFFS); -#define sh_keysc_suspend NULL -#define sh_keysc_resume NULL + if (device_may_wakeup(dev)) + value |= 0x80; + else + value &= ~0x80; + + iowrite16(value, priv->iomem_base + KYCR1_OFFS); + return 0; +} + +static struct dev_pm_ops sh_keysc_dev_pm_ops = { + .suspend = sh_keysc_suspend, +}; struct platform_driver sh_keysc_device_driver = { .probe = sh_keysc_probe, .remove = __devexit_p(sh_keysc_remove), - .suspend = sh_keysc_suspend, - .resume = sh_keysc_resume, .driver = { .name = "sh_keysc", + .pm = &sh_keysc_dev_pm_ops, } }; -- GitLab From ae6241fbf5c8863631532e8069037bae460607be Mon Sep 17 00:00:00 2001 From: Christoph Plattner Date: Sun, 8 Mar 2009 23:19:05 +0100 Subject: [PATCH 2979/4982] ALSA: hda - Added HP HDX16/HDX18 notebook support for HDA codecs (82HD71) Added codec recognition of HP HDX platforms and added support of the MUTE LED (orange/white). For this feature the CONFIG_SND_HDA_POWER_SAVE is needed to use event handling for mute control. Signed-off-by: Christoph Plattner Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 57 ++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 123bcf7c3b2..fb9f4ccba88 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -99,6 +99,7 @@ enum { STAC_DELL_M4_3, STAC_HP_M4, STAC_HP_DV5, + STAC_HP_HDX, STAC_92HD71BXX_MODELS }; @@ -1828,6 +1829,7 @@ static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = { [STAC_DELL_M4_3] = dell_m4_3_pin_configs, [STAC_HP_M4] = NULL, [STAC_HP_DV5] = NULL, + [STAC_HP_HDX] = NULL, }; static const char *stac92hd71bxx_models[STAC_92HD71BXX_MODELS] = { @@ -1838,6 +1840,7 @@ static const char *stac92hd71bxx_models[STAC_92HD71BXX_MODELS] = { [STAC_DELL_M4_3] = "dell-m4-3", [STAC_HP_M4] = "hp-m4", [STAC_HP_DV5] = "hp-dv5", + [STAC_HP_HDX] = "hp-hdx", }; static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { @@ -1852,6 +1855,10 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { "HP dv4-7", STAC_HP_DV5), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361a, "HP mini 1000", STAC_HP_M4), + SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361b, + "HP HDX", STAC_HP_HDX), /* HDX16 */ + SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3610, + "HP HDX", STAC_HP_HDX), /* HDX18 */ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233, "unknown Dell", STAC_DELL_M4_1), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0234, @@ -4472,6 +4479,41 @@ static int stac92xx_resume(struct hda_codec *codec) return 0; } + +/* + * using power check for controlling mute led of HP HDX notebooks + * check for mute state only on Speakers (nid = 0x10) + * + * For this feature CONFIG_SND_HDA_POWER_SAVE is needed, otherwise + * the LED is NOT working properly ! + */ + +#ifdef CONFIG_SND_HDA_POWER_SAVE +static int stac92xx_check_power_status (struct hda_codec * codec, hda_nid_t nid) +{ + struct sigmatel_spec *spec = codec->spec; + + /* only handle on HP HDX */ + if (spec->board_config != STAC_HP_HDX) + return 0; + + if (nid == 0x10) + { + if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & + HDA_AMP_MUTE) + spec->gpio_data &= ~0x08; /* orange */ + else + spec->gpio_data |= 0x08; /* white */ + + stac_gpio_set(codec, spec->gpio_mask, + spec->gpio_dir, + spec->gpio_data); + } + + return 0; +} +#endif + static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) { struct sigmatel_spec *spec = codec->spec; @@ -4493,6 +4535,9 @@ static struct hda_codec_ops stac92xx_patch_ops = { .suspend = stac92xx_suspend, .resume = stac92xx_resume, #endif +#ifdef CONFIG_SND_HDA_POWER_SAVE + .check_power_status = stac92xx_check_power_status, +#endif }; static int patch_stac9200(struct hda_codec *codec) @@ -5089,6 +5134,13 @@ again: /* no output amps */ spec->num_pwrs = 0; /* fallthru */ + case 0x111d76b2: /* Codec of HP HDX16/HDX18 */ + + /* orange/white mute led on GPIO3, orange=0, white=1 */ + spec->gpio_mask |= 0x08; + spec->gpio_dir |= 0x08; + spec->gpio_data |= 0x08; /* set to white */ + /* fallthru */ default: memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer, sizeof(stac92hd71bxx_dmux_amixer)); @@ -5143,6 +5195,11 @@ again: snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010); stac92xx_auto_set_pinctl(codec, 0x0d, AC_PINCTL_OUT_EN); break; + case STAC_HP_HDX: + spec->num_dmics = 1; + spec->num_dmuxes = 1; + spec->num_smuxes = 1; + break; }; spec->multiout.dac_nids = spec->dac_nids; -- GitLab From 443e26d014c242623dd70cda054cc6e5ebf7993d Mon Sep 17 00:00:00 2001 From: Christoph Plattner Date: Tue, 10 Mar 2009 00:05:56 +0100 Subject: [PATCH 2980/4982] ALSA: hda - Rework on patch_sigmatel.c for HP HDX16/HDX18 Code rework, comments of mail tiwai@suse.de (2009-03-09) incorporated. Code tested on HP HDX16 (not tested on HDX18 yet). Signed-off-by: Christoph Plattner Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index fb9f4ccba88..d119feed42c 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -4489,14 +4489,10 @@ static int stac92xx_resume(struct hda_codec *codec) */ #ifdef CONFIG_SND_HDA_POWER_SAVE -static int stac92xx_check_power_status (struct hda_codec * codec, hda_nid_t nid) +static int stac92xx_hp_hdx_check_power_status (struct hda_codec * codec, hda_nid_t nid) { struct sigmatel_spec *spec = codec->spec; - /* only handle on HP HDX */ - if (spec->board_config != STAC_HP_HDX) - return 0; - if (nid == 0x10) { if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & @@ -4535,9 +4531,6 @@ static struct hda_codec_ops stac92xx_patch_ops = { .suspend = stac92xx_suspend, .resume = stac92xx_resume, #endif -#ifdef CONFIG_SND_HDA_POWER_SAVE - .check_power_status = stac92xx_check_power_status, -#endif }; static int patch_stac9200(struct hda_codec *codec) @@ -5134,13 +5127,6 @@ again: /* no output amps */ spec->num_pwrs = 0; /* fallthru */ - case 0x111d76b2: /* Codec of HP HDX16/HDX18 */ - - /* orange/white mute led on GPIO3, orange=0, white=1 */ - spec->gpio_mask |= 0x08; - spec->gpio_dir |= 0x08; - spec->gpio_data |= 0x08; /* set to white */ - /* fallthru */ default: memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer, sizeof(stac92hd71bxx_dmux_amixer)); @@ -5199,6 +5185,20 @@ again: spec->num_dmics = 1; spec->num_dmuxes = 1; spec->num_smuxes = 1; + /* + * For controlling MUTE LED on HP HDX16/HDX18 notebooks, + * the CONFIG_SND_HDA_POWER_SAVE is needed to be set. + */ +#ifdef CONFIG_SND_HDA_POWER_SAVE + /* orange/white mute led on GPIO3, orange=0, white=1 */ + spec->gpio_mask |= 0x08; + spec->gpio_dir |= 0x08; + spec->gpio_data |= 0x08; /* set to white */ + + /* register check_power_status callback. */ + codec->patch_ops.check_power_status = + stac92xx_hp_hdx_check_power_status; +#endif break; }; -- GitLab From 6fce61aeaf0dc1dfa306092539397ab903a9afc4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 10 Mar 2009 07:48:57 +0100 Subject: [PATCH 2981/4982] ALSA: hda - Fix coding style issues in last two patches Also re-ordered the quirk entries per SSID. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index d119feed42c..72c87aa20bd 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1853,12 +1853,12 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { "HP dv4-7", STAC_HP_DV5), SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3600, "HP dv4-7", STAC_HP_DV5), + SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3610, + "HP HDX", STAC_HP_HDX), /* HDX18 */ SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361a, "HP mini 1000", STAC_HP_M4), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361b, - "HP HDX", STAC_HP_HDX), /* HDX16 */ - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3610, - "HP HDX", STAC_HP_HDX), /* HDX18 */ + "HP HDX", STAC_HP_HDX), /* HDX16 */ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233, "unknown Dell", STAC_DELL_M4_1), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0234, @@ -4489,20 +4489,20 @@ static int stac92xx_resume(struct hda_codec *codec) */ #ifdef CONFIG_SND_HDA_POWER_SAVE -static int stac92xx_hp_hdx_check_power_status (struct hda_codec * codec, hda_nid_t nid) +static int stac92xx_hp_hdx_check_power_status(struct hda_codec *codec, + hda_nid_t nid) { struct sigmatel_spec *spec = codec->spec; - - if (nid == 0x10) - { - if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & + + if (nid == 0x10) { + if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & HDA_AMP_MUTE) spec->gpio_data &= ~0x08; /* orange */ else spec->gpio_data |= 0x08; /* white */ - - stac_gpio_set(codec, spec->gpio_mask, - spec->gpio_dir, + + stac_gpio_set(codec, spec->gpio_mask, + spec->gpio_dir, spec->gpio_data); } @@ -5185,7 +5185,7 @@ again: spec->num_dmics = 1; spec->num_dmuxes = 1; spec->num_smuxes = 1; - /* + /* * For controlling MUTE LED on HP HDX16/HDX18 notebooks, * the CONFIG_SND_HDA_POWER_SAVE is needed to be set. */ @@ -5196,7 +5196,7 @@ again: spec->gpio_data |= 0x08; /* set to white */ /* register check_power_status callback. */ - codec->patch_ops.check_power_status = + codec->patch_ops.check_power_status = stac92xx_hp_hdx_check_power_status; #endif break; -- GitLab From 2f47f44790a9c8fc43e515df3c6be19a35ee5de5 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 10 Mar 2009 15:49:54 +0900 Subject: [PATCH 2982/4982] sh: Support fixed 32-bit PMB mappings from bootloader. This provides a method for supporting fixed PMB mappings inherited from the bootloader, as an alternative to the dynamic PMB mapping currently used by the kernel. In the future these methods will be combined. P1/P2 area is handled like a regular 29-bit physical address, and local bus device are assigned P3 area addresses. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- arch/sh/boot/Makefile | 20 +++++++++------ arch/sh/include/asm/addrspace.h | 4 +-- arch/sh/include/asm/io.h | 4 +-- arch/sh/include/asm/page.h | 7 ++++- arch/sh/kernel/vmlinux_32.lds.S | 5 +++- arch/sh/mm/Kconfig | 29 ++++++++++++++++++++- arch/sh/mm/Makefile_32 | 1 + arch/sh/mm/ioremap_32.c | 6 +++-- arch/sh/mm/pmb-fixed.c | 45 +++++++++++++++++++++++++++++++++ 9 files changed, 104 insertions(+), 17 deletions(-) create mode 100644 arch/sh/mm/pmb-fixed.c diff --git a/arch/sh/boot/Makefile b/arch/sh/boot/Makefile index c16ccd4bfa1..95483d16125 100644 --- a/arch/sh/boot/Makefile +++ b/arch/sh/boot/Makefile @@ -33,20 +33,24 @@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE $(obj)/compressed/vmlinux: FORCE $(Q)$(MAKE) $(build)=$(obj)/compressed $@ -ifeq ($(CONFIG_32BIT),y) -KERNEL_LOAD := $(shell /bin/bash -c 'printf "0x%08x" \ - $$[$(CONFIG_PAGE_OFFSET) + \ - $(CONFIG_ZERO_PAGE_OFFSET)]') -else +KERNEL_MEMORY := 0x00000000 +ifeq ($(CONFIG_PMB_FIXED),y) +KERNEL_MEMORY := $(shell /bin/bash -c 'printf "0x%08x" \ + $$[$(CONFIG_MEMORY_START) & 0x1fffffff]') +endif +ifeq ($(CONFIG_29BIT),y) +KERNEL_MEMORY := $(shell /bin/bash -c 'printf "0x%08x" \ + $$[$(CONFIG_MEMORY_START)]') +endif + KERNEL_LOAD := $(shell /bin/bash -c 'printf "0x%08x" \ $$[$(CONFIG_PAGE_OFFSET) + \ - $(CONFIG_MEMORY_START) + \ + $(KERNEL_MEMORY) + \ $(CONFIG_ZERO_PAGE_OFFSET)]') -endif KERNEL_ENTRY := $(shell /bin/bash -c 'printf "0x%08x" \ $$[$(CONFIG_PAGE_OFFSET) + \ - $(CONFIG_MEMORY_START) + \ + $(KERNEL_MEMORY) + \ $(CONFIG_ZERO_PAGE_OFFSET) + $(CONFIG_ENTRY_OFFSET)]') quiet_cmd_uimage = UIMAGE $@ diff --git a/arch/sh/include/asm/addrspace.h b/arch/sh/include/asm/addrspace.h index 36736c7e93d..80d40813e05 100644 --- a/arch/sh/include/asm/addrspace.h +++ b/arch/sh/include/asm/addrspace.h @@ -31,7 +31,7 @@ /* Returns the physical address of a PnSEG (n=1,2) address */ #define PHYSADDR(a) (((unsigned long)(a)) & 0x1fffffff) -#ifdef CONFIG_29BIT +#if defined(CONFIG_29BIT) || defined(CONFIG_PMB_FIXED) /* * Map an address to a certain privileged segment */ @@ -43,7 +43,7 @@ ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P3SEG)) #define P4SEGADDR(a) \ ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P4SEG)) -#endif /* 29BIT */ +#endif /* 29BIT || PMB_FIXED */ #endif /* P1SEG */ /* Check if an address can be reached in 29 bits */ diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index 61f6dae4053..0454f8d6805 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h @@ -238,7 +238,7 @@ extern void onchip_unmap(unsigned long vaddr); static inline void __iomem * __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags) { -#ifdef CONFIG_SUPERH32 +#if defined(CONFIG_SUPERH32) && !defined(CONFIG_PMB_FIXED) unsigned long last_addr = offset + size - 1; #endif void __iomem *ret; @@ -247,7 +247,7 @@ __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags) if (ret) return ret; -#ifdef CONFIG_SUPERH32 +#if defined(CONFIG_SUPERH32) && !defined(CONFIG_PMB_FIXED) /* * For P1 and P2 space this is trivial, as everything is already * mapped. Uncached access for P1 addresses are done through P2. diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h index 5871d78e47e..9c6d21ec024 100644 --- a/arch/sh/include/asm/page.h +++ b/arch/sh/include/asm/page.h @@ -129,7 +129,12 @@ typedef struct page *pgtable_t; * is not visible (it is part of the PMB mapping) and so needs to be * added or subtracted as required. */ -#ifdef CONFIG_32BIT +#if defined(CONFIG_PMB_FIXED) +/* phys = virt - PAGE_OFFSET - (__MEMORY_START & 0xe0000000) */ +#define PMB_OFFSET (PAGE_OFFSET - PXSEG(__MEMORY_START)) +#define __pa(x) ((unsigned long)(x) - PMB_OFFSET) +#define __va(x) ((void *)((unsigned long)(x) + PMB_OFFSET)) +#elif defined(CONFIG_32BIT) #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET+__MEMORY_START) #define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET-__MEMORY_START)) #else diff --git a/arch/sh/kernel/vmlinux_32.lds.S b/arch/sh/kernel/vmlinux_32.lds.S index 7b4b82bd115..d0b2a715cd1 100644 --- a/arch/sh/kernel/vmlinux_32.lds.S +++ b/arch/sh/kernel/vmlinux_32.lds.S @@ -15,7 +15,10 @@ OUTPUT_ARCH(sh) ENTRY(_start) SECTIONS { -#ifdef CONFIG_32BIT +#ifdef CONFIG_PMB_FIXED + . = CONFIG_PAGE_OFFSET + (CONFIG_MEMORY_START & 0x1fffffff) + + CONFIG_ZERO_PAGE_OFFSET; +#elif defined(CONFIG_32BIT) . = CONFIG_PAGE_OFFSET + CONFIG_ZERO_PAGE_OFFSET; #else . = CONFIG_PAGE_OFFSET + CONFIG_MEMORY_START + CONFIG_ZERO_PAGE_OFFSET; diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig index 555ec9714b9..10c24356d2d 100644 --- a/arch/sh/mm/Kconfig +++ b/arch/sh/mm/Kconfig @@ -57,7 +57,7 @@ config 32BIT bool default y if CPU_SH5 -config PMB +config PMB_ENABLE bool "Support 32-bit physical addressing through PMB" depends on MMU && EXPERIMENTAL && (CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785) select 32BIT @@ -67,6 +67,33 @@ config PMB 32-bits through the SH-4A PMB. If this is not set, legacy 29-bit physical addressing will be used. +choice + prompt "PMB handling type" + depends on PMB_ENABLE + default PMB_FIXED + +config PMB + bool "PMB" + depends on MMU && EXPERIMENTAL && (CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785) + select 32BIT + help + If you say Y here, physical addressing will be extended to + 32-bits through the SH-4A PMB. If this is not set, legacy + 29-bit physical addressing will be used. + +config PMB_FIXED + bool "fixed PMB" + depends on MMU && EXPERIMENTAL && (CPU_SUBTYPE_SH7780 || \ + CPU_SUBTYPE_SH7785) + select 32BIT + help + If this option is enabled, fixed PMB mappings are inherited + from the boot loader, and the kernel does not attempt dynamic + management. This is the closest to legacy 29-bit physical mode, + and allows systems to support up to 512MiB of system memory. + +endchoice + config X2TLB bool "Enable extended TLB mode" depends on (CPU_SHX2 || CPU_SHX3) && MMU && EXPERIMENTAL diff --git a/arch/sh/mm/Makefile_32 b/arch/sh/mm/Makefile_32 index cb2f3f29959..469ff167245 100644 --- a/arch/sh/mm/Makefile_32 +++ b/arch/sh/mm/Makefile_32 @@ -35,6 +35,7 @@ endif obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_PMB) += pmb.o +obj-$(CONFIG_PMB_FIXED) += pmb-fixed.o obj-$(CONFIG_NUMA) += numa.o EXTRA_CFLAGS += -Werror diff --git a/arch/sh/mm/ioremap_32.c b/arch/sh/mm/ioremap_32.c index 8dc77026a0b..60cc486d2c2 100644 --- a/arch/sh/mm/ioremap_32.c +++ b/arch/sh/mm/ioremap_32.c @@ -59,11 +59,13 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size, if (is_pci_memaddr(phys_addr) && is_pci_memaddr(last_addr)) return (void __iomem *)phys_addr; +#if !defined(CONFIG_PMB_FIXED) /* * Don't allow anybody to remap normal RAM that we're using.. */ if (phys_addr < virt_to_phys(high_memory)) return NULL; +#endif /* * Mappings have to be page-aligned @@ -81,7 +83,7 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size, area->phys_addr = phys_addr; orig_addr = addr = (unsigned long)area->addr; -#ifdef CONFIG_32BIT +#ifdef CONFIG_PMB /* * First try to remap through the PMB once a valid VMA has been * established. Smaller allocations (or the rest of the size @@ -122,7 +124,7 @@ void __iounmap(void __iomem *addr) if (seg < P3SEG || vaddr >= P3_ADDR_MAX || is_pci_memaddr(vaddr)) return; -#ifdef CONFIG_32BIT +#ifdef CONFIG_PMB /* * Purge any PMB entries that may have been established for this * mapping, then proceed with conventional VMA teardown. diff --git a/arch/sh/mm/pmb-fixed.c b/arch/sh/mm/pmb-fixed.c new file mode 100644 index 00000000000..43c8eac4d8a --- /dev/null +++ b/arch/sh/mm/pmb-fixed.c @@ -0,0 +1,45 @@ +/* + * arch/sh/mm/fixed_pmb.c + * + * Copyright (C) 2009 Renesas Solutions Corp. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include + +static int __uses_jump_to_uncached fixed_pmb_init(void) +{ + int i; + unsigned long addr, data; + + jump_to_uncached(); + + for (i = 0; i < PMB_ENTRY_MAX; i++) { + addr = PMB_DATA + (i << PMB_E_SHIFT); + data = ctrl_inl(addr); + if (!(data & PMB_V)) + continue; + + if (data & PMB_C) { +#if defined(CONFIG_CACHE_WRITETHROUGH) + data |= PMB_WT; +#elif defined(CONFIG_CACHE_WRITEBACK) + data &= ~PMB_WT; +#else + data &= ~(PMB_C | PMB_WT); +#endif + } + ctrl_outl(data, addr); + } + + back_to_cached(); + + return 0; +} +arch_initcall(fixed_pmb_init); -- GitLab From df4d4f1a47ed6080c7b4010149126bd1013dc3f1 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 10 Mar 2009 15:50:44 +0900 Subject: [PATCH 2983/4982] sh: sh7785lcr: Updates for fixed PMB. Add a new defconfig for SH7785LCR in 32-bit mode, and update the power off code to avoid 29-bit assumptions. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- arch/sh/boards/Kconfig | 2 +- arch/sh/boards/board-sh7785lcr.c | 10 +- arch/sh/configs/sh7785lcr_32bit_defconfig | 1553 +++++++++++++++++++++ 3 files changed, 1563 insertions(+), 2 deletions(-) create mode 100644 arch/sh/configs/sh7785lcr_32bit_defconfig diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig index 694abecf602..bd3569a9934 100644 --- a/arch/sh/boards/Kconfig +++ b/arch/sh/boards/Kconfig @@ -155,7 +155,7 @@ config SH_SH7785LCR config SH_SH7785LCR_29BIT_PHYSMAPS bool "SH7785LCR 29bit physmaps" - depends on SH_SH7785LCR + depends on SH_SH7785LCR && 29BIT default y help This board has 2 physical memory maps. It can be changed with diff --git a/arch/sh/boards/board-sh7785lcr.c b/arch/sh/boards/board-sh7785lcr.c index 38a64968d7b..6746a5fba3a 100644 --- a/arch/sh/boards/board-sh7785lcr.c +++ b/arch/sh/boards/board-sh7785lcr.c @@ -275,7 +275,15 @@ void __init init_sh7785lcr_IRQ(void) static void sh7785lcr_power_off(void) { - ctrl_outb(0x01, P2SEGADDR(PLD_POFCR)); + unsigned char *p; + + p = ioremap(PLD_POFCR, PLD_POFCR + 1); + if (!p) { + printk(KERN_ERR "%s: ioremap error.\n", __func__); + return; + } + *p = 0x01; + iounmap(p); } /* Initialize the board */ diff --git a/arch/sh/configs/sh7785lcr_32bit_defconfig b/arch/sh/configs/sh7785lcr_32bit_defconfig new file mode 100644 index 00000000000..54e1dee8e24 --- /dev/null +++ b/arch/sh/configs/sh7785lcr_32bit_defconfig @@ -0,0 +1,1553 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.29-rc4 +# Fri Feb 20 18:25:29 2009 +# +CONFIG_SUPERH=y +CONFIG_SUPERH32=y +CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig" +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_GENERIC_IRQ_PROBE=y +# CONFIG_GENERIC_GPIO is not set +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +# CONFIG_ARCH_SUSPEND_POSSIBLE is not set +# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set +CONFIG_SYS_SUPPORTS_NUMA=y +CONFIG_SYS_SUPPORTS_PCI=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_NO_VIRT_TO_BUS=y +CONFIG_IO_TRAPPED=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set +# CONFIG_CGROUPS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_PCI_QUIRKS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +CONFIG_PROFILING=y +# CONFIG_OPROFILE is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_IOREMAP_PROT=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_FREEZER is not set + +# +# System type +# +CONFIG_CPU_SH4=y +CONFIG_CPU_SH4A=y +CONFIG_CPU_SHX2=y +# CONFIG_CPU_SUBTYPE_SH7619 is not set +# CONFIG_CPU_SUBTYPE_SH7201 is not set +# CONFIG_CPU_SUBTYPE_SH7203 is not set +# CONFIG_CPU_SUBTYPE_SH7206 is not set +# CONFIG_CPU_SUBTYPE_SH7263 is not set +# CONFIG_CPU_SUBTYPE_MXG is not set +# CONFIG_CPU_SUBTYPE_SH7705 is not set +# CONFIG_CPU_SUBTYPE_SH7706 is not set +# CONFIG_CPU_SUBTYPE_SH7707 is not set +# CONFIG_CPU_SUBTYPE_SH7708 is not set +# CONFIG_CPU_SUBTYPE_SH7709 is not set +# CONFIG_CPU_SUBTYPE_SH7710 is not set +# CONFIG_CPU_SUBTYPE_SH7712 is not set +# CONFIG_CPU_SUBTYPE_SH7720 is not set +# CONFIG_CPU_SUBTYPE_SH7721 is not set +# CONFIG_CPU_SUBTYPE_SH7750 is not set +# CONFIG_CPU_SUBTYPE_SH7091 is not set +# CONFIG_CPU_SUBTYPE_SH7750R is not set +# CONFIG_CPU_SUBTYPE_SH7750S is not set +# CONFIG_CPU_SUBTYPE_SH7751 is not set +# CONFIG_CPU_SUBTYPE_SH7751R is not set +# CONFIG_CPU_SUBTYPE_SH7760 is not set +# CONFIG_CPU_SUBTYPE_SH4_202 is not set +# CONFIG_CPU_SUBTYPE_SH7723 is not set +# CONFIG_CPU_SUBTYPE_SH7763 is not set +# CONFIG_CPU_SUBTYPE_SH7770 is not set +# CONFIG_CPU_SUBTYPE_SH7780 is not set +CONFIG_CPU_SUBTYPE_SH7785=y +# CONFIG_CPU_SUBTYPE_SHX3 is not set +# CONFIG_CPU_SUBTYPE_SH7343 is not set +# CONFIG_CPU_SUBTYPE_SH7722 is not set +# CONFIG_CPU_SUBTYPE_SH7366 is not set +# CONFIG_CPU_SUBTYPE_SH5_101 is not set +# CONFIG_CPU_SUBTYPE_SH5_103 is not set + +# +# Memory management options +# +CONFIG_QUICKLIST=y +CONFIG_MMU=y +CONFIG_PAGE_OFFSET=0x80000000 +CONFIG_MEMORY_START=0x40000000 +CONFIG_MEMORY_SIZE=0x20000000 +# CONFIG_29BIT is not set +CONFIG_32BIT=y +CONFIG_PMB_ENABLE=y +# CONFIG_PMB is not set +CONFIG_PMB_FIXED=y +# CONFIG_X2TLB is not set +CONFIG_VSYSCALL=y +# CONFIG_NUMA is not set +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_MAX_ACTIVE_REGIONS=2 +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_ENTRY_OFFSET=0x00001000 +CONFIG_SELECT_MEMORY_MODEL=y +# CONFIG_FLATMEM_MANUAL is not set +# CONFIG_DISCONTIGMEM_MANUAL is not set +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM=y +CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_SPARSEMEM_STATIC=y +# CONFIG_MEMORY_HOTPLUG is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_MIGRATION=y +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_NR_QUICK=2 +CONFIG_UNEVICTABLE_LRU=y + +# +# Cache configuration +# +# CONFIG_SH_DIRECT_MAPPED is not set +CONFIG_CACHE_WRITEBACK=y +# CONFIG_CACHE_WRITETHROUGH is not set +# CONFIG_CACHE_OFF is not set + +# +# Processor features +# +CONFIG_CPU_LITTLE_ENDIAN=y +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_SH_FPU=y +CONFIG_SH_STORE_QUEUES=y +CONFIG_CPU_HAS_INTEVT=y +CONFIG_CPU_HAS_SR_RB=y +CONFIG_CPU_HAS_PTEA=y +CONFIG_CPU_HAS_FPU=y + +# +# Board support +# +# CONFIG_SH_HIGHLANDER is not set +CONFIG_SH_SH7785LCR=y + +# +# Timer and clock configuration +# +CONFIG_SH_TMU=y +CONFIG_SH_TIMER_IRQ=28 +CONFIG_SH_PCLK_FREQ=50000000 +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set + +# +# DMA support +# +# CONFIG_SH_DMA is not set + +# +# Companion Chips +# + +# +# Additional SuperH Device Drivers +# +CONFIG_HEARTBEAT=y +# CONFIG_PUSH_SWITCH is not set + +# +# Kernel features +# +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_SCHED_HRTICK=y +CONFIG_KEXEC=y +# CONFIG_CRASH_DUMP is not set +# CONFIG_SECCOMP is not set +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_GUSA=y + +# +# Boot options +# +CONFIG_ZERO_PAGE_OFFSET=0x00001000 +CONFIG_BOOT_LINK_OFFSET=0x00800000 +# CONFIG_CMDLINE_BOOL is not set + +# +# Bus options +# +CONFIG_PCI=y +CONFIG_SH_PCIDMA_NONCOHERENT=y +CONFIG_PCI_AUTO=y +CONFIG_PCI_AUTO_UPDATE_RESOURCES=y +# CONFIG_PCIEPORTBUS is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_PCI_LEGACY=y +# CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_STUB is not set +# CONFIG_PCCARD is not set +# CONFIG_HOTPLUG_PCI is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options (EXPERIMENTAL) +# +# CONFIG_PM is not set +# CONFIG_CPU_IDLE is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_COMPAT_NET_DEV_OPS=y +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_MULTIPLE_TABLES is not set +# CONFIG_IP_ROUTE_MULTIPATH is not set +# CONFIG_IP_ROUTE_VERBOSE is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_OLD_REGULATORY is not set +CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +# CONFIG_LIB80211 is not set +# CONFIG_MAC80211 is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +# CONFIG_MTD_INTEL_VR_NOR is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_QINFO_PROBE is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_HD is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_DH is not set +CONFIG_ATA=y +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_SATA_PMP=y +# CONFIG_SATA_AHCI is not set +# CONFIG_SATA_SIL24 is not set +CONFIG_ATA_SFF=y +# CONFIG_SATA_SVW is not set +# CONFIG_ATA_PIIX is not set +# CONFIG_SATA_MV is not set +# CONFIG_SATA_NV is not set +# CONFIG_PDC_ADMA is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_PROMISE is not set +# CONFIG_SATA_SX4 is not set +CONFIG_SATA_SIL=y +# CONFIG_SATA_SIS is not set +# CONFIG_SATA_ULI is not set +# CONFIG_SATA_VIA is not set +# CONFIG_SATA_VITESSE is not set +# CONFIG_SATA_INIC162X is not set +# CONFIG_PATA_ALI is not set +# CONFIG_PATA_AMD is not set +# CONFIG_PATA_ARTOP is not set +# CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_CMD64X is not set +# CONFIG_PATA_CS5520 is not set +# CONFIG_PATA_CS5530 is not set +# CONFIG_PATA_CYPRESS is not set +# CONFIG_PATA_EFAR is not set +# CONFIG_ATA_GENERIC is not set +# CONFIG_PATA_HPT366 is not set +# CONFIG_PATA_HPT37X is not set +# CONFIG_PATA_HPT3X2N is not set +# CONFIG_PATA_HPT3X3 is not set +# CONFIG_PATA_IT821X is not set +# CONFIG_PATA_IT8213 is not set +# CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_MARVELL is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_OLDPIIX is not set +# CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NINJA32 is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_NS87415 is not set +# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PDC_OLD is not set +# CONFIG_PATA_RADISYS is not set +# CONFIG_PATA_RZ1000 is not set +# CONFIG_PATA_SC1200 is not set +# CONFIG_PATA_SERVERWORKS is not set +# CONFIG_PATA_PDC2027X is not set +# CONFIG_PATA_SIL680 is not set +# CONFIG_PATA_SIS is not set +# CONFIG_PATA_VIA is not set +# CONFIG_PATA_WINBOND is not set +# CONFIG_PATA_PLATFORM is not set +# CONFIG_PATA_SCH is not set +# CONFIG_MD is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# Enable only one of the two stacks, unless you know what you are doing +# +# CONFIG_FIREWIRE is not set +# CONFIG_IEEE1394 is not set +# CONFIG_I2O is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_ARCNET is not set +# CONFIG_NET_ETHERNET is not set +CONFIG_MII=y +CONFIG_NETDEV_1000=y +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_IP1000 is not set +# CONFIG_IGB is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +CONFIG_R8169=y +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +# CONFIG_QLA3XXX is not set +# CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_JME is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_TR is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_FF_MEMLESS=m +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SH_KEYSC is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_SH_SCI=y +CONFIG_SERIAL_SH_SCI_NR_UARTS=6 +CONFIG_SERIAL_SH_SCI_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +# CONFIG_I2C_CHARDEV is not set +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOPCA=y + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_SH_MOBILE is not set +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Graphics adapter I2C/DDC channel drivers +# +# CONFIG_I2C_VOODOO3 is not set + +# +# Other I2C/SMBus bus drivers +# +CONFIG_I2C_PCA_PLATFORM=y +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_SPI is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +CONFIG_MFD_SM501=y +# CONFIG_HTC_PASIC3 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_REGULATOR is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_SYS_FILLRECT=m +CONFIG_FB_SYS_COPYAREA=m +CONFIG_FB_SYS_IMAGEBLIT=m +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_SYS_FOPS=m +CONFIG_FB_DEFERRED_IO=y +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_S3 is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_VIA is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_VT8623 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_ARK is not set +# CONFIG_FB_PM3 is not set +# CONFIG_FB_CARMINE is not set +CONFIG_FB_SH_MOBILE_LCDC=m +CONFIG_FB_SM501=y +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_LOGO_SUPERH_MONO is not set +# CONFIG_LOGO_SUPERH_VGA16 is not set +# CONFIG_LOGO_SUPERH_CLUT224 is not set +# CONFIG_SOUND is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HID_DEBUG is not set +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV is not set + +# +# Special HID drivers +# +CONFIG_HID_COMPAT=y +CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_EZKEY=y +CONFIG_HID_GYRATION=y +CONFIG_HID_LOGITECH=y +# CONFIG_LOGITECH_FF is not set +# CONFIG_LOGIRUMBLEPAD2_FF is not set +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +# CONFIG_HID_NTRIG is not set +CONFIG_HID_PANTHERLORD=y +# CONFIG_PANTHERLORD_FF is not set +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SONY=y +CONFIG_HID_SUNPLUS=y +# CONFIG_GREENASIA_FF is not set +# CONFIG_HID_TOPSEED is not set +CONFIG_THRUSTMASTER_FF=m +CONFIG_ZEROPLUS_FF=m +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +CONFIG_USB_MON=y +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_EHCI_HCD=m +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +CONFIG_USB_R8A66597_HCD=y +# CONFIG_USB_WHCI_HCD is not set +# CONFIG_USB_HWA_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; +# + +# +# see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +CONFIG_USB_TEST=m +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set +# CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_UWB is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +CONFIG_RTC_DRV_RS5C372=y +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_SH is not set +# CONFIG_DMADEVICES is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_NTFS_FS=y +# CONFIG_NTFS_DEBUG is not set +CONFIG_NTFS_RW=y + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +CONFIG_MINIX_FS=y +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +CONFIG_NFSD_V4=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +# CONFIG_SUNRPC_REGISTER_V4 is not set +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +CONFIG_NLS_CODEPAGE_932=y +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_PREEMPT=y +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_FRAME_POINTER is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y + +# +# Tracers +# +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_SH_STANDARD_BIOS is not set +# CONFIG_EARLY_SCIF_CONSOLE is not set +# CONFIG_DEBUG_BOOTMEM is not set +# CONFIG_DEBUG_STACKOVERFLOW is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_4KSTACKS is not set +# CONFIG_IRQSTACKS is not set +# CONFIG_DUMP_CODE is not set +# CONFIG_SH_NO_BSS_INIT is not set +# CONFIG_MORE_COMPILE_OPTIONS is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y -- GitLab From 8ffe31334262108be343d92e81649f9dc3efe826 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 10 Mar 2009 15:51:49 +0900 Subject: [PATCH 2984/4982] sh: pci-sh7780: fix pci memory address for fixed PMB Fix the problem that cannot work a PCI device when 32-bit physical address mode. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- arch/sh/drivers/pci/pci-sh7780.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sh/drivers/pci/pci-sh7780.c b/arch/sh/drivers/pci/pci-sh7780.c index 078dc44d6b0..773d575a04b 100644 --- a/arch/sh/drivers/pci/pci-sh7780.c +++ b/arch/sh/drivers/pci/pci-sh7780.c @@ -127,8 +127,8 @@ int __init sh7780_pcic_init(struct sh4_pci_address_map *map) pci_write_reg(word, SH4_PCILSR0); pci_write_reg(0x00000001, SH4_PCILSR1); /* Set the values on window 0 PCI config registers */ - word = (CONFIG_MEMORY_SIZE > 0x08000000) ? 0x10000000 : 0x08000000; - pci_write_reg(word | 0xa0000000, SH4_PCILAR0); + word = CONFIG_MEMORY_START | (CONFIG_MEMORY_SIZE - 0x01000000); + pci_write_reg(word, SH4_PCILAR0); pci_write_reg(word, SH7780_PCIMBAR0); /* Set the values on window 1 PCI config registers */ pci_write_reg(0x00000000, SH4_PCILAR1); -- GitLab From 6dfc0d2c4b9a5455c60e0b9ee95bbf22fc516cef Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 10 Mar 2009 07:54:20 +0100 Subject: [PATCH 2985/4982] ALSA: hda - Add missing models to documentation Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 80b796e4a80..f9253ea3c19 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -344,7 +344,9 @@ STAC92HD71B* dell-m4-1 Dell desktops dell-m4-2 Dell desktops dell-m4-3 Dell desktops - hp-m4 HP dv laptops + hp-m4 HP mini 1000 + hp-dv5 HP dv series + hp-hdx HP HDX series auto BIOS setup (default) STAC92HD73* @@ -361,6 +363,7 @@ STAC92HD83* =========== ref Reference board mic-ref Reference board with power managment for ports + dell-s14 Dell laptop auto BIOS setup (default) STAC9872 -- GitLab From dc65a977ce59f2c3171ea451b90c7e5effb6737e Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 10 Mar 2009 16:26:29 +0900 Subject: [PATCH 2986/4982] sh: Define ARCH_SHMOBILE for SH-Mobile CPUs. Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index a4c2c845863..adffbf4048b 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -179,6 +179,9 @@ config CPU_SHX2 config CPU_SHX3 bool +config ARCH_SHMOBILE + bool + choice prompt "Processor sub-type selection" @@ -330,6 +333,7 @@ config CPU_SUBTYPE_SH7723 bool "Support SH7723 processor" select CPU_SH4A select CPU_SHX2 + select ARCH_SHMOBILE select ARCH_SPARSEMEM_ENABLE select SYS_SUPPORTS_CMT help @@ -377,12 +381,14 @@ config CPU_SUBTYPE_SHX3 config CPU_SUBTYPE_SH7343 bool "Support SH7343 processor" select CPU_SH4AL_DSP + select ARCH_SHMOBILE select SYS_SUPPORTS_CMT config CPU_SUBTYPE_SH7722 bool "Support SH7722 processor" select CPU_SH4AL_DSP select CPU_SHX2 + select ARCH_SHMOBILE select ARCH_SPARSEMEM_ENABLE select SYS_SUPPORTS_NUMA select SYS_SUPPORTS_CMT @@ -391,6 +397,7 @@ config CPU_SUBTYPE_SH7366 bool "Support SH7366 processor" select CPU_SH4AL_DSP select CPU_SHX2 + select ARCH_SHMOBILE select ARCH_SPARSEMEM_ENABLE select SYS_SUPPORTS_NUMA select SYS_SUPPORTS_CMT -- GitLab From 19390c4d03688b9940a1836f06b76ec622b9cd6f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 10 Mar 2009 16:27:48 +0900 Subject: [PATCH 2987/4982] linker script: define __per_cpu_load on all SMP capable archs Impact: __per_cpu_load available on all SMP capable archs Percpu now requires three symbols to be defined - __per_cpu_load, __per_cpu_start and __per_cpu_end. There were three archs which didn't have it. Update them as follows. * powerpc: can use generic PERCPU() macro. Compile tested for powerpc32, compile/boot tested for powerpc64. * ia64: can use generic PERCPU_VADDR() macro. __phys_per_cpu_start is identical to __per_cpu_load. Compile tested and symbol table looks identical after the change except for the additional __per_cpu_load. * arm: added explicit __per_cpu_load definition. Currently uses unified .init output section so can't use the generic macro. Dunno whether the unified .init ouput section is required by arch peculiarity so I left it alone. Please break it up and use PERCPU() if possible. Signed-off-by: Tejun Heo Cc: Benjamin Herrenschmidt Cc: Pat Gefre Cc: Russell King --- arch/arm/kernel/vmlinux.lds.S | 1 + arch/ia64/kernel/vmlinux.lds.S | 12 ++---------- arch/powerpc/kernel/vmlinux.lds.S | 9 +-------- 3 files changed, 4 insertions(+), 18 deletions(-) diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 85598f7da40..1602373e539 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -64,6 +64,7 @@ SECTIONS __initramfs_end = .; #endif . = ALIGN(4096); + __per_cpu_load = .; __per_cpu_start = .; *(.data.percpu.page_aligned) *(.data.percpu) diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S index f45e4e508ec..3765efc5f96 100644 --- a/arch/ia64/kernel/vmlinux.lds.S +++ b/arch/ia64/kernel/vmlinux.lds.S @@ -213,17 +213,9 @@ SECTIONS { *(.data.cacheline_aligned) } /* Per-cpu data: */ - percpu : { } :percpu . = ALIGN(PERCPU_PAGE_SIZE); - __phys_per_cpu_start = .; - .data.percpu PERCPU_ADDR : AT(__phys_per_cpu_start - LOAD_OFFSET) - { - __per_cpu_start = .; - *(.data.percpu.page_aligned) - *(.data.percpu) - *(.data.percpu.shared_aligned) - __per_cpu_end = .; - } + PERCPU_VADDR(PERCPU_ADDR, :percpu) + __phys_per_cpu_start = __per_cpu_load; . = __phys_per_cpu_start + PERCPU_PAGE_SIZE; /* ensure percpu data fits * into percpu page size */ diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 295ccc5e86b..67f07f45338 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -181,14 +181,7 @@ SECTIONS __initramfs_end = .; } #endif - . = ALIGN(PAGE_SIZE); - .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { - __per_cpu_start = .; - *(.data.percpu.page_aligned) - *(.data.percpu) - *(.data.percpu.shared_aligned) - __per_cpu_end = .; - } + PERCPU(PAGE_SIZE) . = ALIGN(8); .machine.desc : AT(ADDR(.machine.desc) - LOAD_OFFSET) { -- GitLab From e01009833e22dc87075d770554b34d797843ed23 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 10 Mar 2009 16:27:48 +0900 Subject: [PATCH 2988/4982] percpu: make x86 addr <-> pcpu ptr conversion macros generic Impact: generic addr <-> pcpu ptr conversion macros There's nothing arch specific about x86 __addr_to_pcpu_ptr() and __pcpu_ptr_to_addr(). With proper __per_cpu_load and __per_cpu_start defined, they'll do the right thing regardless of actual layout. Move these macros from arch/x86/include/asm/percpu.h to mm/percpu.c and allow archs to override it as necessary. Signed-off-by: Tejun Heo --- arch/x86/include/asm/percpu.h | 8 -------- mm/percpu.c | 16 +++++++++++++++- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index 8f1d2fbec1d..aee103b26d0 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h @@ -43,14 +43,6 @@ #else /* ...!ASSEMBLY */ #include -#include - -#define __addr_to_pcpu_ptr(addr) \ - (void *)((unsigned long)(addr) - (unsigned long)pcpu_base_addr \ - + (unsigned long)__per_cpu_start) -#define __pcpu_ptr_to_addr(ptr) \ - (void *)((unsigned long)(ptr) + (unsigned long)pcpu_base_addr \ - - (unsigned long)__per_cpu_start) #ifdef CONFIG_SMP #define __percpu_arg(x) "%%"__stringify(__percpu_seg)":%P" #x diff --git a/mm/percpu.c b/mm/percpu.c index bfe6a3afaf4..c6f38a2afac 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -46,7 +46,8 @@ * - define CONFIG_HAVE_DYNAMIC_PER_CPU_AREA * * - define __addr_to_pcpu_ptr() and __pcpu_ptr_to_addr() to translate - * regular address to percpu pointer and back + * regular address to percpu pointer and back if they need to be + * different from the default * * - use pcpu_setup_first_chunk() during percpu area initialization to * setup the first chunk containing the kernel static percpu area @@ -67,11 +68,24 @@ #include #include +#include #include #define PCPU_SLOT_BASE_SHIFT 5 /* 1-31 shares the same slot */ #define PCPU_DFL_MAP_ALLOC 16 /* start a map with 16 ents */ +/* default addr <-> pcpu_ptr mapping, override in asm/percpu.h if necessary */ +#ifndef __addr_to_pcpu_ptr +#define __addr_to_pcpu_ptr(addr) \ + (void *)((unsigned long)(addr) - (unsigned long)pcpu_base_addr \ + + (unsigned long)__per_cpu_start) +#endif +#ifndef __pcpu_ptr_to_addr +#define __pcpu_ptr_to_addr(ptr) \ + (void *)((unsigned long)(ptr) + (unsigned long)pcpu_base_addr \ + - (unsigned long)__per_cpu_start) +#endif + struct pcpu_chunk { struct list_head list; /* linked to pcpu_slot lists */ struct rb_node rb_node; /* key is chunk->vm->addr */ -- GitLab From 6074d5b0a319fe8400ff079a3c289406ca024321 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 10 Mar 2009 16:27:48 +0900 Subject: [PATCH 2989/4982] percpu: more flexibility for @dyn_size of pcpu_setup_first_chunk() Impact: cleanup, more flexibility for first chunk init Non-negative @dyn_size used to be allowed iff @unit_size wasn't auto. This restriction stemmed from implementation detail and made things a bit less intuitive. This patch allows @dyn_size to be specified regardless of @unit_size and swaps the positions of @dyn_size and @unit_size so that the parameter order makes more sense (static, reserved and dyn sizes followed by enclosing unit_size). While at it, add @unit_size >= PCPU_MIN_UNIT_SIZE sanity check. Signed-off-by: Tejun Heo --- arch/x86/kernel/setup_percpu.c | 13 ++++++------- include/linux/percpu.h | 2 +- mm/percpu.c | 28 ++++++++++++++-------------- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index efa615f2bf4..e41c51f6ada 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -233,8 +233,8 @@ proceed: "%zu bytes\n", vm.addr, static_size); ret = pcpu_setup_first_chunk(pcpur_get_page, static_size, - PERCPU_FIRST_CHUNK_RESERVE, - PMD_SIZE, dyn_size, vm.addr, NULL); + PERCPU_FIRST_CHUNK_RESERVE, dyn_size, + PMD_SIZE, vm.addr, NULL); goto out_free_ar; enomem: @@ -315,9 +315,8 @@ static ssize_t __init setup_pcpu_embed(size_t static_size) pcpue_size >> PAGE_SHIFT, pcpue_ptr, static_size); return pcpu_setup_first_chunk(pcpue_get_page, static_size, - PERCPU_FIRST_CHUNK_RESERVE, - pcpue_unit_size, dyn_size, - pcpue_ptr, NULL); + PERCPU_FIRST_CHUNK_RESERVE, dyn_size, + pcpue_unit_size, pcpue_ptr, NULL); } /* @@ -375,8 +374,8 @@ static ssize_t __init setup_pcpu_4k(size_t static_size) pcpu4k_nr_static_pages, static_size); ret = pcpu_setup_first_chunk(pcpu4k_get_page, static_size, - PERCPU_FIRST_CHUNK_RESERVE, -1, -1, NULL, - pcpu4k_populate_pte); + PERCPU_FIRST_CHUNK_RESERVE, -1, + -1, NULL, pcpu4k_populate_pte); goto out_free_ar; enomem: diff --git a/include/linux/percpu.h b/include/linux/percpu.h index 54a968b4b92..fb455dcc59c 100644 --- a/include/linux/percpu.h +++ b/include/linux/percpu.h @@ -107,7 +107,7 @@ typedef void (*pcpu_populate_pte_fn_t)(unsigned long addr); extern size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn, size_t static_size, size_t reserved_size, - ssize_t unit_size, ssize_t dyn_size, + ssize_t dyn_size, ssize_t unit_size, void *base_addr, pcpu_populate_pte_fn_t populate_pte_fn); diff --git a/mm/percpu.c b/mm/percpu.c index c6f38a2afac..2f94661d3e3 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -1027,8 +1027,8 @@ EXPORT_SYMBOL_GPL(free_percpu); * @get_page_fn: callback to fetch page pointer * @static_size: the size of static percpu area in bytes * @reserved_size: the size of reserved percpu area in bytes - * @unit_size: unit size in bytes, must be multiple of PAGE_SIZE, -1 for auto * @dyn_size: free size for dynamic allocation in bytes, -1 for auto + * @unit_size: unit size in bytes, must be multiple of PAGE_SIZE, -1 for auto * @base_addr: mapped address, NULL for auto * @populate_pte_fn: callback to allocate pagetable, NULL if unnecessary * @@ -1053,14 +1053,14 @@ EXPORT_SYMBOL_GPL(free_percpu); * limited offset range for symbol relocations to guarantee module * percpu symbols fall inside the relocatable range. * + * @dyn_size, if non-negative, determines the number of bytes + * available for dynamic allocation in the first chunk. Specifying + * non-negative value makes percpu leave alone the area beyond + * @static_size + @reserved_size + @dyn_size. + * * @unit_size, if non-negative, specifies unit size and must be * aligned to PAGE_SIZE and equal to or larger than @static_size + - * @reserved_size + @dyn_size. - * - * @dyn_size, if non-negative, limits the number of bytes available - * for dynamic allocation in the first chunk. Specifying non-negative - * value make percpu leave alone the area beyond @static_size + - * @reserved_size + @dyn_size. + * @reserved_size + if non-negative, @dyn_size. * * Non-null @base_addr means that the caller already allocated virtual * region for the first chunk and mapped it. percpu must not mess @@ -1083,12 +1083,14 @@ EXPORT_SYMBOL_GPL(free_percpu); */ size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn, size_t static_size, size_t reserved_size, - ssize_t unit_size, ssize_t dyn_size, + ssize_t dyn_size, ssize_t unit_size, void *base_addr, pcpu_populate_pte_fn_t populate_pte_fn) { static struct vm_struct first_vm; static int smap[2], dmap[2]; + size_t size_sum = static_size + reserved_size + + (dyn_size >= 0 ? dyn_size : 0); struct pcpu_chunk *schunk, *dchunk = NULL; unsigned int cpu; int nr_pages; @@ -1099,20 +1101,18 @@ size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn, ARRAY_SIZE(dmap) >= PCPU_DFL_MAP_ALLOC); BUG_ON(!static_size); if (unit_size >= 0) { - BUG_ON(unit_size < static_size + reserved_size + - (dyn_size >= 0 ? dyn_size : 0)); + BUG_ON(unit_size < size_sum); BUG_ON(unit_size & ~PAGE_MASK); - } else { - BUG_ON(dyn_size >= 0); + BUG_ON(unit_size < PCPU_MIN_UNIT_SIZE); + } else BUG_ON(base_addr); - } BUG_ON(base_addr && populate_pte_fn); if (unit_size >= 0) pcpu_unit_pages = unit_size >> PAGE_SHIFT; else pcpu_unit_pages = max_t(int, PCPU_MIN_UNIT_SIZE >> PAGE_SHIFT, - PFN_UP(static_size + reserved_size)); + PFN_UP(size_sum)); pcpu_unit_size = pcpu_unit_pages << PAGE_SHIFT; pcpu_chunk_size = num_possible_cpus() * pcpu_unit_size; -- GitLab From 66c3a75772247c31feabefb724e082220a1ab060 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 10 Mar 2009 16:27:48 +0900 Subject: [PATCH 2990/4982] percpu: generalize embedding first chunk setup helper Impact: code reorganization Separate out embedding first chunk setup helper from x86 embedding first chunk allocator and put it in mm/percpu.c. This will be used by the default percpu first chunk allocator and possibly by other archs. Signed-off-by: Tejun Heo --- arch/x86/kernel/setup_percpu.c | 54 +++------------------ include/linux/percpu.h | 4 ++ mm/percpu.c | 86 ++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 48 deletions(-) diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index e41c51f6ada..400331b50a5 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -257,31 +257,13 @@ static ssize_t __init setup_pcpu_remap(size_t static_size) * Embedding allocator * * The first chunk is sized to just contain the static area plus - * module and dynamic reserves, and allocated as a contiguous area - * using bootmem allocator and used as-is without being mapped into - * vmalloc area. This enables the first chunk to piggy back on the - * linear physical PMD mapping and doesn't add any additional pressure - * to TLB. Note that if the needed size is smaller than the minimum - * unit size, the leftover is returned to the bootmem allocator. + * module and dynamic reserves and embedded into linear physical + * mapping so that it can use PMD mapping without additional TLB + * pressure. */ -static void *pcpue_ptr __initdata; -static size_t pcpue_size __initdata; -static size_t pcpue_unit_size __initdata; - -static struct page * __init pcpue_get_page(unsigned int cpu, int pageno) -{ - size_t off = (size_t)pageno << PAGE_SHIFT; - - if (off >= pcpue_size) - return NULL; - - return virt_to_page(pcpue_ptr + cpu * pcpue_unit_size + off); -} - static ssize_t __init setup_pcpu_embed(size_t static_size) { - unsigned int cpu; - size_t dyn_size; + size_t reserve = PERCPU_MODULE_RESERVE + PERCPU_DYNAMIC_RESERVE; /* * If large page isn't supported, there's no benefit in doing @@ -291,32 +273,8 @@ static ssize_t __init setup_pcpu_embed(size_t static_size) if (!cpu_has_pse || pcpu_need_numa()) return -EINVAL; - /* allocate and copy */ - pcpue_size = PFN_ALIGN(static_size + PERCPU_MODULE_RESERVE + - PERCPU_DYNAMIC_RESERVE); - pcpue_unit_size = max_t(size_t, pcpue_size, PCPU_MIN_UNIT_SIZE); - dyn_size = pcpue_size - static_size - PERCPU_FIRST_CHUNK_RESERVE; - - pcpue_ptr = pcpu_alloc_bootmem(0, num_possible_cpus() * pcpue_unit_size, - PAGE_SIZE); - if (!pcpue_ptr) - return -ENOMEM; - - for_each_possible_cpu(cpu) { - void *ptr = pcpue_ptr + cpu * pcpue_unit_size; - - free_bootmem(__pa(ptr + pcpue_size), - pcpue_unit_size - pcpue_size); - memcpy(ptr, __per_cpu_load, static_size); - } - - /* we're ready, commit */ - pr_info("PERCPU: Embedded %zu pages at %p, static data %zu bytes\n", - pcpue_size >> PAGE_SHIFT, pcpue_ptr, static_size); - - return pcpu_setup_first_chunk(pcpue_get_page, static_size, - PERCPU_FIRST_CHUNK_RESERVE, dyn_size, - pcpue_unit_size, pcpue_ptr, NULL); + return pcpu_embed_first_chunk(static_size, PERCPU_FIRST_CHUNK_RESERVE, + reserve - PERCPU_FIRST_CHUNK_RESERVE, -1); } /* diff --git a/include/linux/percpu.h b/include/linux/percpu.h index fb455dcc59c..ee5615d6521 100644 --- a/include/linux/percpu.h +++ b/include/linux/percpu.h @@ -111,6 +111,10 @@ extern size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn, void *base_addr, pcpu_populate_pte_fn_t populate_pte_fn); +extern ssize_t __init pcpu_embed_first_chunk( + size_t static_size, size_t reserved_size, + ssize_t dyn_size, ssize_t unit_size); + /* * Use this to get to a cpu's version of the per-cpu object * dynamically allocated. Non-atomic access to the current CPU's diff --git a/mm/percpu.c b/mm/percpu.c index 2f94661d3e3..1aa5d8fbca1 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -1238,3 +1238,89 @@ size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn, pcpu_base_addr = (void *)pcpu_chunk_addr(schunk, 0, 0); return pcpu_unit_size; } + +/* + * Embedding first chunk setup helper. + */ +static void *pcpue_ptr __initdata; +static size_t pcpue_size __initdata; +static size_t pcpue_unit_size __initdata; + +static struct page * __init pcpue_get_page(unsigned int cpu, int pageno) +{ + size_t off = (size_t)pageno << PAGE_SHIFT; + + if (off >= pcpue_size) + return NULL; + + return virt_to_page(pcpue_ptr + cpu * pcpue_unit_size + off); +} + +/** + * pcpu_embed_first_chunk - embed the first percpu chunk into bootmem + * @static_size: the size of static percpu area in bytes + * @reserved_size: the size of reserved percpu area in bytes + * @dyn_size: free size for dynamic allocation in bytes, -1 for auto + * @unit_size: unit size in bytes, must be multiple of PAGE_SIZE, -1 for auto + * + * This is a helper to ease setting up embedded first percpu chunk and + * can be called where pcpu_setup_first_chunk() is expected. + * + * If this function is used to setup the first chunk, it is allocated + * as a contiguous area using bootmem allocator and used as-is without + * being mapped into vmalloc area. This enables the first chunk to + * piggy back on the linear physical mapping which often uses larger + * page size. + * + * When @dyn_size is positive, dynamic area might be larger than + * specified to fill page alignment. Also, when @dyn_size is auto, + * @dyn_size does not fill the whole first chunk but only what's + * necessary for page alignment after static and reserved areas. + * + * If the needed size is smaller than the minimum or specified unit + * size, the leftover is returned to the bootmem allocator. + * + * RETURNS: + * The determined pcpu_unit_size which can be used to initialize + * percpu access on success, -errno on failure. + */ +ssize_t __init pcpu_embed_first_chunk(size_t static_size, size_t reserved_size, + ssize_t dyn_size, ssize_t unit_size) +{ + unsigned int cpu; + + /* determine parameters and allocate */ + pcpue_size = PFN_ALIGN(static_size + reserved_size + + (dyn_size >= 0 ? dyn_size : 0)); + if (dyn_size != 0) + dyn_size = pcpue_size - static_size - reserved_size; + + if (unit_size >= 0) { + BUG_ON(unit_size < pcpue_size); + pcpue_unit_size = unit_size; + } else + pcpue_unit_size = max_t(size_t, pcpue_size, PCPU_MIN_UNIT_SIZE); + + pcpue_ptr = __alloc_bootmem_nopanic( + num_possible_cpus() * pcpue_unit_size, + PAGE_SIZE, __pa(MAX_DMA_ADDRESS)); + if (!pcpue_ptr) + return -ENOMEM; + + /* return the leftover and copy */ + for_each_possible_cpu(cpu) { + void *ptr = pcpue_ptr + cpu * pcpue_unit_size; + + free_bootmem(__pa(ptr + pcpue_size), + pcpue_unit_size - pcpue_size); + memcpy(ptr, __per_cpu_load, static_size); + } + + /* we're ready, commit */ + pr_info("PERCPU: Embedded %zu pages at %p, static data %zu bytes\n", + pcpue_size >> PAGE_SHIFT, pcpue_ptr, static_size); + + return pcpu_setup_first_chunk(pcpue_get_page, static_size, + reserved_size, dyn_size, + pcpue_unit_size, pcpue_ptr, NULL); +} -- GitLab From ae68df5635a191c7edb75f5c1c1406353cb24a9f Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 10 Mar 2009 17:00:48 +0900 Subject: [PATCH 2991/4982] sh: Generate uImage by default on Urquell board. Signed-off-by: Paul Mundt --- arch/sh/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 4067b0d9287..bece1f7535f 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -80,6 +80,7 @@ OBJCOPYFLAGS := -O binary -R .note -R .note.gnu.build-id -R .comment \ defaultimage-$(CONFIG_SUPERH32) := zImage defaultimage-$(CONFIG_SH_SH7785LCR) := uImage defaultimage-$(CONFIG_SH_RSK) := uImage +defaultimage-$(CONFIG_SH_URQUELL) := uImage defaultimage-$(CONFIG_SH_7206_SOLUTION_ENGINE) := vmlinux defaultimage-$(CONFIG_SH_7619_SOLUTION_ENGINE) := vmlinux -- GitLab From 71b973a42c5456824c8712e00659d9616d395919 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Tue, 10 Mar 2009 17:26:49 +0900 Subject: [PATCH 2992/4982] sh: dma-sh updates for multi IRQ and new SH-4A CPUs. This adds DMA support for newer SH-4A CPUs, particularly SH7763/64/80/85. This also enables multi IRQ support for platforms that have multiple vectors bound to the same IRQ source. Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- arch/sh/drivers/dma/Kconfig | 8 +- arch/sh/drivers/dma/dma-sh.c | 172 +++++++++++++++-------- arch/sh/drivers/dma/dma-sh.h | 75 ---------- arch/sh/include/asm/dma-sh.h | 117 +++++++++++++++ arch/sh/include/asm/dma.h | 4 +- arch/sh/include/cpu-sh3/cpu/dma.h | 17 +-- arch/sh/include/cpu-sh4/cpu/dma-sh4a.h | 94 +++++++++++++ arch/sh/include/cpu-sh4/cpu/dma-sh7780.h | 39 ----- arch/sh/include/cpu-sh4/cpu/dma.h | 30 ++-- 9 files changed, 352 insertions(+), 204 deletions(-) delete mode 100644 arch/sh/drivers/dma/dma-sh.h create mode 100644 arch/sh/include/asm/dma-sh.h create mode 100644 arch/sh/include/cpu-sh4/cpu/dma-sh4a.h delete mode 100644 arch/sh/include/cpu-sh4/cpu/dma-sh7780.h diff --git a/arch/sh/drivers/dma/Kconfig b/arch/sh/drivers/dma/Kconfig index 01936368b8b..57d95fce046 100644 --- a/arch/sh/drivers/dma/Kconfig +++ b/arch/sh/drivers/dma/Kconfig @@ -12,10 +12,10 @@ config SH_DMA config NR_ONCHIP_DMA_CHANNELS int depends on SH_DMA - default "6" if CPU_SUBTYPE_SH7720 || CPU_SUBTYPE_SH7721 - default "8" if CPU_SUBTYPE_SH7750R || CPU_SUBTYPE_SH7751R - default "12" if CPU_SUBTYPE_SH7780 - default "4" + default "4" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7751 || CPU_SUBTYPE_SH7750S + default "8" if CPU_SUBTYPE_SH7750R || CPU_SUBTYPE_SH7751R || CPU_SUBTYPE_SH7760 + default "12" if CPU_SUBTYPE_SH7723 || CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785 + default "6" help This allows you to specify the number of channels that the on-chip DMAC supports. This will be 4 for SH7750/SH7751 and 8 for the diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c index 50887a592dd..ab7b18dcbab 100644 --- a/arch/sh/drivers/dma/dma-sh.c +++ b/arch/sh/drivers/dma/dma-sh.c @@ -17,28 +17,23 @@ #include #include #include -#include "dma-sh.h" - -static int dmte_irq_map[] = { - DMTE0_IRQ, - DMTE1_IRQ, - DMTE2_IRQ, - DMTE3_IRQ, -#if defined(CONFIG_CPU_SUBTYPE_SH7720) || \ - defined(CONFIG_CPU_SUBTYPE_SH7721) || \ - defined(CONFIG_CPU_SUBTYPE_SH7751R) || \ - defined(CONFIG_CPU_SUBTYPE_SH7760) || \ - defined(CONFIG_CPU_SUBTYPE_SH7709) || \ - defined(CONFIG_CPU_SUBTYPE_SH7780) - DMTE4_IRQ, - DMTE5_IRQ, +#include + +#if defined(CONFIG_CPU_SUBTYPE_SH7763) || \ + defined(CONFIG_CPU_SUBTYPE_SH7764) || \ + defined(CONFIG_CPU_SUBTYPE_SH7780) || \ + defined(CONFIG_CPU_SUBTYPE_SH7785) +#define DMAC_IRQ_MULTI 1 #endif -#if defined(CONFIG_CPU_SUBTYPE_SH7751R) || \ - defined(CONFIG_CPU_SUBTYPE_SH7760) || \ - defined(CONFIG_CPU_SUBTYPE_SH7780) - DMTE6_IRQ, - DMTE7_IRQ, + +#if defined(DMAE1_IRQ) +#define NR_DMAE 2 +#else +#define NR_DMAE 1 #endif + +static const char *dmae_name[] = { + "DMAC Address Error0", "DMAC Address Error1" }; static inline unsigned int get_dmte_irq(unsigned int chan) @@ -46,7 +41,14 @@ static inline unsigned int get_dmte_irq(unsigned int chan) unsigned int irq = 0; if (chan < ARRAY_SIZE(dmte_irq_map)) irq = dmte_irq_map[chan]; + +#if defined(DMAC_IRQ_MULTI) + if (irq > DMTE6_IRQ) + return DMTE6_IRQ; + return DMTE0_IRQ; +#else return irq; +#endif } /* @@ -59,7 +61,7 @@ static inline unsigned int get_dmte_irq(unsigned int chan) */ static inline unsigned int calc_xmit_shift(struct dma_channel *chan) { - u32 chcr = ctrl_inl(CHCR[chan->chan]); + u32 chcr = ctrl_inl(dma_base_addr[chan->chan] + CHCR); return ts_shift[(chcr & CHCR_TS_MASK)>>CHCR_TS_SHIFT]; } @@ -75,13 +77,13 @@ static irqreturn_t dma_tei(int irq, void *dev_id) struct dma_channel *chan = dev_id; u32 chcr; - chcr = ctrl_inl(CHCR[chan->chan]); + chcr = ctrl_inl(dma_base_addr[chan->chan] + CHCR); if (!(chcr & CHCR_TE)) return IRQ_NONE; chcr &= ~(CHCR_IE | CHCR_DE); - ctrl_outl(chcr, CHCR[chan->chan]); + ctrl_outl(chcr, (dma_base_addr[chan->chan] + CHCR)); wake_up(&chan->wait_queue); @@ -94,7 +96,12 @@ static int sh_dmac_request_dma(struct dma_channel *chan) return 0; return request_irq(get_dmte_irq(chan->chan), dma_tei, - IRQF_DISABLED, chan->dev_id, chan); +#if defined(DMAC_IRQ_MULTI) + IRQF_SHARED, +#else + IRQF_DISABLED, +#endif + chan->dev_id, chan); } static void sh_dmac_free_dma(struct dma_channel *chan) @@ -115,7 +122,7 @@ sh_dmac_configure_channel(struct dma_channel *chan, unsigned long chcr) chan->flags &= ~DMA_TEI_CAPABLE; } - ctrl_outl(chcr, CHCR[chan->chan]); + ctrl_outl(chcr, (dma_base_addr[chan->chan] + CHCR)); chan->flags |= DMA_CONFIGURED; return 0; @@ -126,13 +133,13 @@ static void sh_dmac_enable_dma(struct dma_channel *chan) int irq; u32 chcr; - chcr = ctrl_inl(CHCR[chan->chan]); + chcr = ctrl_inl(dma_base_addr[chan->chan] + CHCR); chcr |= CHCR_DE; if (chan->flags & DMA_TEI_CAPABLE) chcr |= CHCR_IE; - ctrl_outl(chcr, CHCR[chan->chan]); + ctrl_outl(chcr, (dma_base_addr[chan->chan] + CHCR)); if (chan->flags & DMA_TEI_CAPABLE) { irq = get_dmte_irq(chan->chan); @@ -150,9 +157,9 @@ static void sh_dmac_disable_dma(struct dma_channel *chan) disable_irq(irq); } - chcr = ctrl_inl(CHCR[chan->chan]); + chcr = ctrl_inl(dma_base_addr[chan->chan] + CHCR); chcr &= ~(CHCR_DE | CHCR_TE | CHCR_IE); - ctrl_outl(chcr, CHCR[chan->chan]); + ctrl_outl(chcr, (dma_base_addr[chan->chan] + CHCR)); } static int sh_dmac_xfer_dma(struct dma_channel *chan) @@ -183,12 +190,13 @@ static int sh_dmac_xfer_dma(struct dma_channel *chan) */ if (chan->sar || (mach_is_dreamcast() && chan->chan == PVR2_CASCADE_CHAN)) - ctrl_outl(chan->sar, SAR[chan->chan]); + ctrl_outl(chan->sar, (dma_base_addr[chan->chan]+SAR)); if (chan->dar || (mach_is_dreamcast() && chan->chan == PVR2_CASCADE_CHAN)) - ctrl_outl(chan->dar, DAR[chan->chan]); + ctrl_outl(chan->dar, (dma_base_addr[chan->chan] + DAR)); - ctrl_outl(chan->count >> calc_xmit_shift(chan), DMATCR[chan->chan]); + ctrl_outl(chan->count >> calc_xmit_shift(chan), + (dma_base_addr[chan->chan] + TCR)); sh_dmac_enable_dma(chan); @@ -197,36 +205,26 @@ static int sh_dmac_xfer_dma(struct dma_channel *chan) static int sh_dmac_get_dma_residue(struct dma_channel *chan) { - if (!(ctrl_inl(CHCR[chan->chan]) & CHCR_DE)) + if (!(ctrl_inl(dma_base_addr[chan->chan] + CHCR) & CHCR_DE)) return 0; - return ctrl_inl(DMATCR[chan->chan]) << calc_xmit_shift(chan); + return ctrl_inl(dma_base_addr[chan->chan] + TCR) + << calc_xmit_shift(chan); } -#if defined(CONFIG_CPU_SUBTYPE_SH7720) || \ - defined(CONFIG_CPU_SUBTYPE_SH7721) || \ - defined(CONFIG_CPU_SUBTYPE_SH7780) || \ - defined(CONFIG_CPU_SUBTYPE_SH7709) -#define dmaor_read_reg() ctrl_inw(DMAOR) -#define dmaor_write_reg(data) ctrl_outw(data, DMAOR) -#else -#define dmaor_read_reg() ctrl_inl(DMAOR) -#define dmaor_write_reg(data) ctrl_outl(data, DMAOR) -#endif - -static inline int dmaor_reset(void) +static inline int dmaor_reset(int no) { - unsigned long dmaor = dmaor_read_reg(); + unsigned long dmaor = dmaor_read_reg(no); /* Try to clear the error flags first, incase they are set */ dmaor &= ~(DMAOR_NMIF | DMAOR_AE); - dmaor_write_reg(dmaor); + dmaor_write_reg(no, dmaor); dmaor |= DMAOR_INIT; - dmaor_write_reg(dmaor); + dmaor_write_reg(no, dmaor); /* See if we got an error again */ - if ((dmaor_read_reg() & (DMAOR_AE | DMAOR_NMIF))) { + if ((dmaor_read_reg(no) & (DMAOR_AE | DMAOR_NMIF))) { printk(KERN_ERR "dma-sh: Can't initialize DMAOR.\n"); return -EINVAL; } @@ -237,10 +235,33 @@ static inline int dmaor_reset(void) #if defined(CONFIG_CPU_SH4) static irqreturn_t dma_err(int irq, void *dummy) { - dmaor_reset(); +#if defined(DMAC_IRQ_MULTI) + int cnt = 0; + switch (irq) { +#if defined(DMTE6_IRQ) && defined(DMAE1_IRQ) + case DMTE6_IRQ: + cnt++; +#endif + case DMTE0_IRQ: + if (dmaor_read_reg(cnt) & (DMAOR_NMIF | DMAOR_AE)) { + disable_irq(irq); + /* DMA multi and error IRQ */ + return IRQ_HANDLED; + } + default: + return IRQ_NONE; + } +#else + dmaor_reset(0); +#if defined(CONFIG_CPU_SUBTYPE_SH7723) || \ + defined(CONFIG_CPU_SUBTYPE_SH7780) || \ + defined(CONFIG_CPU_SUBTYPE_SH7785) + dmaor_reset(1); +#endif disable_irq(irq); return IRQ_HANDLED; +#endif } #endif @@ -259,24 +280,57 @@ static struct dma_info sh_dmac_info = { .flags = DMAC_CHANNELS_TEI_CAPABLE, }; +static unsigned int get_dma_error_irq(int n) +{ +#if defined(DMAC_IRQ_MULTI) + return (n == 0) ? get_dmte_irq(0) : get_dmte_irq(6); +#else + return (n == 0) ? DMAE0_IRQ : +#if defined(DMAE1_IRQ) + DMAE1_IRQ; +#else + -1; +#endif +#endif +} + static int __init sh_dmac_init(void) { struct dma_info *info = &sh_dmac_info; int i; #ifdef CONFIG_CPU_SH4 - i = request_irq(DMAE_IRQ, dma_err, IRQF_DISABLED, "DMAC Address Error", 0); - if (unlikely(i < 0)) - return i; + int n; + + for (n = 0; n < NR_DMAE; n++) { + i = request_irq(get_dma_error_irq(n), dma_err, +#if defined(DMAC_IRQ_MULTI) + IRQF_SHARED, +#else + IRQF_DISABLED, #endif + dmae_name[n], (void *)dmae_name[n]); + if (unlikely(i < 0)) { + printk(KERN_ERR "%s request_irq fail\n", dmae_name[n]); + return i; + } + } +#endif /* CONFIG_CPU_SH4 */ /* * Initialize DMAOR, and clean up any error flags that may have * been set. */ - i = dmaor_reset(); + i = dmaor_reset(0); + if (unlikely(i != 0)) + return i; +#if defined(CONFIG_CPU_SUBTYPE_SH7723) || \ + defined(CONFIG_CPU_SUBTYPE_SH7780) || \ + defined(CONFIG_CPU_SUBTYPE_SH7785) + i = dmaor_reset(1); if (unlikely(i != 0)) return i; +#endif return register_dmac(info); } @@ -284,8 +338,12 @@ static int __init sh_dmac_init(void) static void __exit sh_dmac_exit(void) { #ifdef CONFIG_CPU_SH4 - free_irq(DMAE_IRQ, 0); -#endif + int n; + + for (n = 0; n < NR_DMAE; n++) { + free_irq(get_dma_error_irq(n), (void *)dmae_name[n]); + } +#endif /* CONFIG_CPU_SH4 */ unregister_dmac(&sh_dmac_info); } diff --git a/arch/sh/drivers/dma/dma-sh.h b/arch/sh/drivers/dma/dma-sh.h deleted file mode 100644 index 05fecd5428e..00000000000 --- a/arch/sh/drivers/dma/dma-sh.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * arch/sh/drivers/dma/dma-sh.h - * - * Copyright (C) 2000 Takashi YOSHII - * Copyright (C) 2003 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#ifndef __DMA_SH_H -#define __DMA_SH_H - -#include - -/* Definitions for the SuperH DMAC */ -#define REQ_L 0x00000000 -#define REQ_E 0x00080000 -#define RACK_H 0x00000000 -#define RACK_L 0x00040000 -#define ACK_R 0x00000000 -#define ACK_W 0x00020000 -#define ACK_H 0x00000000 -#define ACK_L 0x00010000 -#define DM_INC 0x00004000 -#define DM_DEC 0x00008000 -#define SM_INC 0x00001000 -#define SM_DEC 0x00002000 -#define RS_IN 0x00000200 -#define RS_OUT 0x00000300 -#define TS_BLK 0x00000040 -#define TM_BUR 0x00000020 -#define CHCR_DE 0x00000001 -#define CHCR_TE 0x00000002 -#define CHCR_IE 0x00000004 - -/* DMAOR definitions */ -#define DMAOR_AE 0x00000004 -#define DMAOR_NMIF 0x00000002 -#define DMAOR_DME 0x00000001 - -/* - * Define the default configuration for dual address memory-memory transfer. - * The 0x400 value represents auto-request, external->external. - */ -#define RS_DUAL (DM_INC | SM_INC | 0x400 | TS_32) - -#define MAX_DMAC_CHANNELS (CONFIG_NR_ONCHIP_DMA_CHANNELS) - -/* - * Subtypes that have fewer channels than this simply need to change - * CONFIG_NR_ONCHIP_DMA_CHANNELS. Likewise, subtypes with a larger number - * of channels should expand on this. - * - * For most subtypes we can easily figure these values out with some - * basic calculation, unfortunately on other subtypes these are more - * scattered, so we just leave it unrolled for simplicity. - */ -#define SAR ((unsigned long[]){SH_DMAC_BASE + 0x00, SH_DMAC_BASE + 0x10, \ - SH_DMAC_BASE + 0x20, SH_DMAC_BASE + 0x30, \ - SH_DMAC_BASE + 0x50, SH_DMAC_BASE + 0x60}) -#define DAR ((unsigned long[]){SH_DMAC_BASE + 0x04, SH_DMAC_BASE + 0x14, \ - SH_DMAC_BASE + 0x24, SH_DMAC_BASE + 0x34, \ - SH_DMAC_BASE + 0x54, SH_DMAC_BASE + 0x64}) -#define DMATCR ((unsigned long[]){SH_DMAC_BASE + 0x08, SH_DMAC_BASE + 0x18, \ - SH_DMAC_BASE + 0x28, SH_DMAC_BASE + 0x38, \ - SH_DMAC_BASE + 0x58, SH_DMAC_BASE + 0x68}) -#define CHCR ((unsigned long[]){SH_DMAC_BASE + 0x0c, SH_DMAC_BASE + 0x1c, \ - SH_DMAC_BASE + 0x2c, SH_DMAC_BASE + 0x3c, \ - SH_DMAC_BASE + 0x5c, SH_DMAC_BASE + 0x6c}) - -#define DMAOR (SH_DMAC_BASE + 0x40) - -#endif /* __DMA_SH_H */ - diff --git a/arch/sh/include/asm/dma-sh.h b/arch/sh/include/asm/dma-sh.h new file mode 100644 index 00000000000..e873ecaa506 --- /dev/null +++ b/arch/sh/include/asm/dma-sh.h @@ -0,0 +1,117 @@ +/* + * arch/sh/include/asm/dma-sh.h + * + * Copyright (C) 2000 Takashi YOSHII + * Copyright (C) 2003 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef __DMA_SH_H +#define __DMA_SH_H + +#include + +/* DMAOR contorl: The DMAOR access size is different by CPU.*/ +#if defined(CONFIG_CPU_SUBTYPE_SH7723) || \ + defined(CONFIG_CPU_SUBTYPE_SH7780) || \ + defined(CONFIG_CPU_SUBTYPE_SH7785) +#define dmaor_read_reg(n) \ + (n ? ctrl_inw(SH_DMAC_BASE1 + DMAOR) \ + : ctrl_inw(SH_DMAC_BASE0 + DMAOR)) +#define dmaor_write_reg(n, data) \ + (n ? ctrl_outw(data, SH_DMAC_BASE1 + DMAOR) \ + : ctrl_outw(data, SH_DMAC_BASE0 + DMAOR)) +#else /* Other CPU */ +#define dmaor_read_reg(n) ctrl_inw(SH_DMAC_BASE0 + DMAOR) +#define dmaor_write_reg(n, data) ctrl_outw(data, SH_DMAC_BASE0 + DMAOR) +#endif + +static int dmte_irq_map[] __maybe_unused = { +#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 4) + DMTE0_IRQ, + DMTE0_IRQ + 1, + DMTE0_IRQ + 2, + DMTE0_IRQ + 3, +#endif +#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 6) + DMTE4_IRQ, + DMTE4_IRQ + 1, +#endif +#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 8) + DMTE6_IRQ, + DMTE6_IRQ + 1, +#endif +#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 12) + DMTE8_IRQ, + DMTE9_IRQ, + DMTE10_IRQ, + DMTE11_IRQ, +#endif +}; + +/* Definitions for the SuperH DMAC */ +#define REQ_L 0x00000000 +#define REQ_E 0x00080000 +#define RACK_H 0x00000000 +#define RACK_L 0x00040000 +#define ACK_R 0x00000000 +#define ACK_W 0x00020000 +#define ACK_H 0x00000000 +#define ACK_L 0x00010000 +#define DM_INC 0x00004000 +#define DM_DEC 0x00008000 +#define SM_INC 0x00001000 +#define SM_DEC 0x00002000 +#define RS_IN 0x00000200 +#define RS_OUT 0x00000300 +#define TS_BLK 0x00000040 +#define TM_BUR 0x00000020 +#define CHCR_DE 0x00000001 +#define CHCR_TE 0x00000002 +#define CHCR_IE 0x00000004 + +/* DMAOR definitions */ +#define DMAOR_AE 0x00000004 +#define DMAOR_NMIF 0x00000002 +#define DMAOR_DME 0x00000001 + +/* + * Define the default configuration for dual address memory-memory transfer. + * The 0x400 value represents auto-request, external->external. + */ +#define RS_DUAL (DM_INC | SM_INC | 0x400 | TS_32) + +/* DMA base address */ +static u32 dma_base_addr[] __maybe_unused = { +#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 4) + SH_DMAC_BASE0 + 0x00, /* channel 0 */ + SH_DMAC_BASE0 + 0x10, + SH_DMAC_BASE0 + 0x20, + SH_DMAC_BASE0 + 0x30, +#endif +#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 6) + SH_DMAC_BASE0 + 0x50, + SH_DMAC_BASE0 + 0x60, +#endif +#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 8) + SH_DMAC_BASE1 + 0x00, + SH_DMAC_BASE1 + 0x10, +#endif +#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 12) + SH_DMAC_BASE1 + 0x20, + SH_DMAC_BASE1 + 0x30, + SH_DMAC_BASE1 + 0x50, + SH_DMAC_BASE1 + 0x60, /* channel 11 */ +#endif +}; + +/* DMA register */ +#define SAR 0x00 +#define DAR 0x04 +#define TCR 0x08 +#define CHCR 0x0C +#define DMAOR 0x40 + +#endif /* __DMA_SH_H */ diff --git a/arch/sh/include/asm/dma.h b/arch/sh/include/asm/dma.h index beca7128e2a..6bd17847387 100644 --- a/arch/sh/include/asm/dma.h +++ b/arch/sh/include/asm/dma.h @@ -25,9 +25,9 @@ #define MAX_DMA_ADDRESS (PAGE_OFFSET+0x10000000) #ifdef CONFIG_NR_DMA_CHANNELS -# define MAX_DMA_CHANNELS (CONFIG_NR_DMA_CHANNELS) +# define MAX_DMA_CHANNELS (CONFIG_NR_DMA_CHANNELS) #else -# define MAX_DMA_CHANNELS (CONFIG_NR_ONCHIP_DMA_CHANNELS) +# define MAX_DMA_CHANNELS (CONFIG_NR_ONCHIP_DMA_CHANNELS) #endif /* diff --git a/arch/sh/include/cpu-sh3/cpu/dma.h b/arch/sh/include/cpu-sh3/cpu/dma.h index 6813c3220a1..0ea15f3f236 100644 --- a/arch/sh/include/cpu-sh3/cpu/dma.h +++ b/arch/sh/include/cpu-sh3/cpu/dma.h @@ -1,22 +1,17 @@ #ifndef __ASM_CPU_SH3_DMA_H #define __ASM_CPU_SH3_DMA_H - #if defined(CONFIG_CPU_SUBTYPE_SH7720) || \ - defined(CONFIG_CPU_SUBTYPE_SH7721) -#define SH_DMAC_BASE 0xa4010020 -#else -#define SH_DMAC_BASE 0xa4000020 + defined(CONFIG_CPU_SUBTYPE_SH7721) || \ + defined(CONFIG_CPU_SUBTYPE_SH7710) || \ + defined(CONFIG_CPU_SUBTYPE_SH7712) +#define SH_DMAC_BASE0 0xa4010020 +#else /* SH7705/06/07/09 */ +#define SH_DMAC_BASE0 0xa4000020 #endif -#if defined(CONFIG_CPU_SUBTYPE_SH7720) || defined(CONFIG_CPU_SUBTYPE_SH7709) #define DMTE0_IRQ 48 -#define DMTE1_IRQ 49 -#define DMTE2_IRQ 50 -#define DMTE3_IRQ 51 #define DMTE4_IRQ 76 -#define DMTE5_IRQ 77 -#endif /* Definitions for the SuperH DMAC */ #define TM_BURST 0x00000020 diff --git a/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h b/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h new file mode 100644 index 00000000000..0ed5178fed6 --- /dev/null +++ b/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h @@ -0,0 +1,94 @@ +#ifndef __ASM_SH_CPU_SH4_DMA_SH7780_H +#define __ASM_SH_CPU_SH4_DMA_SH7780_H + +#if defined(CONFIG_CPU_SUBTYPE_SH7343) || \ + defined(CONFIG_CPU_SUBTYPE_SH7722) || \ + defined(CONFIG_CPU_SUBTYPE_SH7730) +#define DMTE0_IRQ 48 +#define DMTE4_IRQ 76 +#define DMAE0_IRQ 78 /* DMA Error IRQ*/ +#define SH_DMAC_BASE0 0xFE008020 +#define SH_DMARS_BASE 0xFE009000 +#elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \ + defined(CONFIG_CPU_SUBTYPE_SH7764) +#define DMTE0_IRQ 34 +#define DMTE4_IRQ 44 +#define DMAE0_IRQ 38 +#define SH_DMAC_BASE0 0xFF608020 +#define SH_DMARS_BASE 0xFF609000 +#elif defined(CONFIG_CPU_SUBTYPE_SH7723) +#define DMTE0_IRQ 48 /* DMAC0A*/ +#define DMTE4_IRQ 40 /* DMAC0B */ +#define DMTE6_IRQ 42 +#define DMTE8_IRQ 76 /* DMAC1A */ +#define DMTE9_IRQ 77 +#define DMTE10_IRQ 72 /* DMAC1B */ +#define DMTE11_IRQ 73 +#define DMAE0_IRQ 78 /* DMA Error IRQ*/ +#define DMAE1_IRQ 74 /* DMA Error IRQ*/ +#define SH_DMAC_BASE0 0xFE008020 +#define SH_DMAC_BASE1 0xFDC08020 +#define SH_DMARS_BASE 0xFDC09000 +#elif defined(CONFIG_CPU_SUBTYPE_SH7780) +#define DMTE0_IRQ 34 +#define DMTE4_IRQ 44 +#define DMTE6_IRQ 46 +#define DMTE8_IRQ 92 +#define DMTE9_IRQ 93 +#define DMTE10_IRQ 94 +#define DMTE11_IRQ 95 +#define DMAE0_IRQ 38 /* DMA Error IRQ */ +#define SH_DMAC_BASE0 0xFC808020 +#define SH_DMAC_BASE1 0xFC818020 +#define SH_DMARS_BASE 0xFC809000 +#else /* SH7785 */ +#define DMTE0_IRQ 33 +#define DMTE4_IRQ 37 +#define DMTE6_IRQ 52 +#define DMTE8_IRQ 54 +#define DMTE9_IRQ 55 +#define DMTE10_IRQ 56 +#define DMTE11_IRQ 57 +#define DMAE0_IRQ 39 /* DMA Error IRQ0 */ +#define DMAE1_IRQ 58 /* DMA Error IRQ1 */ +#define SH_DMAC_BASE0 0xFC808020 +#define SH_DMAC_BASE1 0xFCC08020 +#define SH_DMARS_BASE 0xFC809000 +#endif + +#define REQ_HE 0x000000C0 +#define REQ_H 0x00000080 +#define REQ_LE 0x00000040 +#define TM_BURST 0x0000020 +#define TS_8 0x00000000 +#define TS_16 0x00000008 +#define TS_32 0x00000010 +#define TS_16BLK 0x00000018 +#define TS_32BLK 0x00100000 + +/* + * The SuperH DMAC supports a number of transmit sizes, we list them here, + * with their respective values as they appear in the CHCR registers. + * + * Defaults to a 64-bit transfer size. + */ +enum { + XMIT_SZ_8BIT, + XMIT_SZ_16BIT, + XMIT_SZ_32BIT, + XMIT_SZ_128BIT, + XMIT_SZ_256BIT, +}; + +/* + * The DMA count is defined as the number of bytes to transfer. + */ +static unsigned int ts_shift[] __maybe_unused = { + [XMIT_SZ_8BIT] = 0, + [XMIT_SZ_16BIT] = 1, + [XMIT_SZ_32BIT] = 2, + [XMIT_SZ_128BIT] = 4, + [XMIT_SZ_256BIT] = 5, +}; + +#endif /* __ASM_SH_CPU_SH4_DMA_SH7780_H */ diff --git a/arch/sh/include/cpu-sh4/cpu/dma-sh7780.h b/arch/sh/include/cpu-sh4/cpu/dma-sh7780.h deleted file mode 100644 index 71b426a6e48..00000000000 --- a/arch/sh/include/cpu-sh4/cpu/dma-sh7780.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef __ASM_SH_CPU_SH4_DMA_SH7780_H -#define __ASM_SH_CPU_SH4_DMA_SH7780_H - -#define REQ_HE 0x000000C0 -#define REQ_H 0x00000080 -#define REQ_LE 0x00000040 -#define TM_BURST 0x0000020 -#define TS_8 0x00000000 -#define TS_16 0x00000008 -#define TS_32 0x00000010 -#define TS_16BLK 0x00000018 -#define TS_32BLK 0x00100000 - -/* - * The SuperH DMAC supports a number of transmit sizes, we list them here, - * with their respective values as they appear in the CHCR registers. - * - * Defaults to a 64-bit transfer size. - */ -enum { - XMIT_SZ_8BIT, - XMIT_SZ_16BIT, - XMIT_SZ_32BIT, - XMIT_SZ_128BIT, - XMIT_SZ_256BIT, -}; - -/* - * The DMA count is defined as the number of bytes to transfer. - */ -static unsigned int ts_shift[] __maybe_unused = { - [XMIT_SZ_8BIT] = 0, - [XMIT_SZ_16BIT] = 1, - [XMIT_SZ_32BIT] = 2, - [XMIT_SZ_128BIT] = 4, - [XMIT_SZ_256BIT] = 5, -}; - -#endif /* __ASM_SH_CPU_SH4_DMA_SH7780_H */ diff --git a/arch/sh/include/cpu-sh4/cpu/dma.h b/arch/sh/include/cpu-sh4/cpu/dma.h index 235b7cd1fc9..bcb30246e85 100644 --- a/arch/sh/include/cpu-sh4/cpu/dma.h +++ b/arch/sh/include/cpu-sh4/cpu/dma.h @@ -1,31 +1,29 @@ #ifndef __ASM_CPU_SH4_DMA_H #define __ASM_CPU_SH4_DMA_H -#define DMAOR_INIT ( 0x8000 | DMAOR_DME ) - /* SH7751/7760/7780 DMA IRQ sources */ -#define DMTE0_IRQ 34 -#define DMTE1_IRQ 35 -#define DMTE2_IRQ 36 -#define DMTE3_IRQ 37 -#define DMTE4_IRQ 44 -#define DMTE5_IRQ 45 -#define DMTE6_IRQ 46 -#define DMTE7_IRQ 47 -#define DMAE_IRQ 38 #ifdef CONFIG_CPU_SH4A -#define SH_DMAC_BASE 0xfc808020 +#define DMAOR_INIT (DMAOR_DME) #define CHCR_TS_MASK 0x18 #define CHCR_TS_SHIFT 3 -#include -#else -#define SH_DMAC_BASE 0xffa00000 +#include +#else /* CONFIG_CPU_SH4A */ +/* + * SH7750/SH7751/SH7760 + */ +#define DMTE0_IRQ 34 +#define DMTE4_IRQ 44 +#define DMTE6_IRQ 46 +#define DMAE0_IRQ 38 +#define DMAOR_INIT (0x8000|DMAOR_DME) +#define SH_DMAC_BASE0 0xffa00000 +#define SH_DMAC_BASE1 0xffa00070 /* Definitions for the SuperH DMAC */ -#define TM_BURST 0x0000080 +#define TM_BURST 0x00000080 #define TS_8 0x00000010 #define TS_16 0x00000020 #define TS_32 0x00000030 -- GitLab From 47a72688fae7298e1ad5fdc9bff7e04b6a549620 Mon Sep 17 00:00:00 2001 From: Adrian McMenamin Date: Wed, 4 Mar 2009 00:31:04 +0000 Subject: [PATCH 2993/4982] mtd: flash mapping support for Dreamcast VMU. This patch adds support for the Sega Dreamcast visual memory unit as a flash mapping. It requires changes in the maple bus driver (posted separately) to support block reads and writes. The VMU is a 'smart' flash device, with a built-in 8-bit controller - for instance there is an erase before a write but it is hidden from the user. But the device's overall behaviour means it works well with the mtd layer and it is appropriate to add it as an mtd mapping. Signed-off-by: Adrian McMenamin Acked-By: David Woodhouse Signed-off-by: Paul Mundt --- drivers/mtd/maps/Kconfig | 12 +- drivers/mtd/maps/Makefile | 1 + drivers/mtd/maps/vmu-flash.c | 832 +++++++++++++++++++++++++++++++++++ 3 files changed, 844 insertions(+), 1 deletion(-) create mode 100644 drivers/mtd/maps/vmu-flash.c diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 043d50fb6ef..729f899a5cd 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -551,5 +551,15 @@ config MTD_PLATRAM This selection automatically selects the map_ram driver. -endmenu +config MTD_VMU + tristate "Map driver for Dreamcast VMU" + depends on MAPLE + help + This driver enables access to the Dreamcast Visual Memory Unit (VMU). + + Most Dreamcast users will want to say Y here. + To build this as a module select M here, the module will be called + vmu-flash. + +endmenu diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index 6d9ba35caf1..26b28a7a90b 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -61,3 +61,4 @@ obj-$(CONFIG_MTD_PLATRAM) += plat-ram.o obj-$(CONFIG_MTD_OMAP_NOR) += omap_nor.o obj-$(CONFIG_MTD_INTEL_VR_NOR) += intel_vr_nor.o obj-$(CONFIG_MTD_BFIN_ASYNC) += bfin-async-flash.o +obj-$(CONFIG_MTD_VMU) += vmu-flash.o diff --git a/drivers/mtd/maps/vmu-flash.c b/drivers/mtd/maps/vmu-flash.c new file mode 100644 index 00000000000..1f73297e777 --- /dev/null +++ b/drivers/mtd/maps/vmu-flash.c @@ -0,0 +1,832 @@ +/* vmu-flash.c + * Driver for SEGA Dreamcast Visual Memory Unit + * + * Copyright (c) Adrian McMenamin 2002 - 2009 + * Copyright (c) Paul Mundt 2001 + * + * Licensed under version 2 of the + * GNU General Public Licence + */ +#include +#include +#include +#include +#include +#include + +struct vmu_cache { + unsigned char *buffer; /* Cache */ + unsigned int block; /* Which block was cached */ + unsigned long jiffies_atc; /* When was it cached? */ + int valid; +}; + +struct mdev_part { + struct maple_device *mdev; + int partition; +}; + +struct vmupart { + u16 user_blocks; + u16 root_block; + u16 numblocks; + char *name; + struct vmu_cache *pcache; +}; + +struct memcard { + u16 tempA; + u16 tempB; + u32 partitions; + u32 blocklen; + u32 writecnt; + u32 readcnt; + u32 removeable; + int partition; + int read; + unsigned char *blockread; + struct vmupart *parts; + struct mtd_info *mtd; +}; + +struct vmu_block { + unsigned int num; /* block number */ + unsigned int ofs; /* block offset */ +}; + +static struct vmu_block *ofs_to_block(unsigned long src_ofs, + struct mtd_info *mtd, int partition) +{ + struct vmu_block *vblock; + struct maple_device *mdev; + struct memcard *card; + struct mdev_part *mpart; + int num; + + mpart = mtd->priv; + mdev = mpart->mdev; + card = maple_get_drvdata(mdev); + + if (src_ofs >= card->parts[partition].numblocks * card->blocklen) + goto failed; + + num = src_ofs / card->blocklen; + if (num > card->parts[partition].numblocks) + goto failed; + + vblock = kmalloc(sizeof(struct vmu_block), GFP_KERNEL); + if (!vblock) + goto failed; + + vblock->num = num; + vblock->ofs = src_ofs % card->blocklen; + return vblock; + +failed: + return NULL; +} + +/* Maple bus callback function for reads */ +static void vmu_blockread(struct mapleq *mq) +{ + struct maple_device *mdev; + struct memcard *card; + + mdev = mq->dev; + card = maple_get_drvdata(mdev); + /* copy the read in data */ + + if (unlikely(!card->blockread)) + return; + + memcpy(card->blockread, mq->recvbuf->buf + 12, + card->blocklen/card->readcnt); + +} + +/* Interface with maple bus to read blocks + * caching the results so that other parts + * of the driver can access block reads */ +static int maple_vmu_read_block(unsigned int num, unsigned char *buf, + struct mtd_info *mtd) +{ + struct memcard *card; + struct mdev_part *mpart; + struct maple_device *mdev; + int partition, error = 0, x, wait; + unsigned char *blockread = NULL; + struct vmu_cache *pcache; + __be32 sendbuf; + + mpart = mtd->priv; + mdev = mpart->mdev; + partition = mpart->partition; + card = maple_get_drvdata(mdev); + pcache = card->parts[partition].pcache; + pcache->valid = 0; + + /* prepare the cache for this block */ + if (!pcache->buffer) { + pcache->buffer = kmalloc(card->blocklen, GFP_KERNEL); + if (!pcache->buffer) { + dev_err(&mdev->dev, "VMU at (%d, %d) - read fails due" + " to lack of memory\n", mdev->port, + mdev->unit); + error = -ENOMEM; + goto outB; + } + } + + /* + * Reads may be phased - again the hardware spec + * supports this - though may not be any devices in + * the wild that implement it, but we will here + */ + for (x = 0; x < card->readcnt; x++) { + sendbuf = cpu_to_be32(partition << 24 | x << 16 | num); + + if (atomic_read(&mdev->busy) == 1) { + wait_event_interruptible_timeout(mdev->maple_wait, + atomic_read(&mdev->busy) == 0, HZ); + if (atomic_read(&mdev->busy) == 1) { + dev_notice(&mdev->dev, "VMU at (%d, %d)" + " is busy\n", mdev->port, mdev->unit); + error = -EAGAIN; + goto outB; + } + } + + atomic_set(&mdev->busy, 1); + blockread = kmalloc(card->blocklen/card->readcnt, GFP_KERNEL); + if (!blockread) { + error = -ENOMEM; + atomic_set(&mdev->busy, 0); + goto outB; + } + card->blockread = blockread; + + maple_getcond_callback(mdev, vmu_blockread, 0, + MAPLE_FUNC_MEMCARD); + error = maple_add_packet(mdev, MAPLE_FUNC_MEMCARD, + MAPLE_COMMAND_BREAD, 2, &sendbuf); + /* Very long timeouts seem to be needed when box is stressed */ + wait = wait_event_interruptible_timeout(mdev->maple_wait, + (atomic_read(&mdev->busy) == 0 || + atomic_read(&mdev->busy) == 2), HZ * 3); + /* + * MTD layer does not handle hotplugging well + * so have to return errors when VMU is unplugged + * in the middle of a read (busy == 2) + */ + if (error || atomic_read(&mdev->busy) == 2) { + if (atomic_read(&mdev->busy) == 2) + error = -ENXIO; + atomic_set(&mdev->busy, 0); + card->blockread = NULL; + goto outA; + } + if (wait == 0 || wait == -ERESTARTSYS) { + card->blockread = NULL; + atomic_set(&mdev->busy, 0); + error = -EIO; + list_del_init(&(mdev->mq->list)); + kfree(mdev->mq->sendbuf); + mdev->mq->sendbuf = NULL; + if (wait == -ERESTARTSYS) { + dev_warn(&mdev->dev, "VMU read on (%d, %d)" + " interrupted on block 0x%X\n", + mdev->port, mdev->unit, num); + } else + dev_notice(&mdev->dev, "VMU read on (%d, %d)" + " timed out on block 0x%X\n", + mdev->port, mdev->unit, num); + goto outA; + } + + memcpy(buf + (card->blocklen/card->readcnt) * x, blockread, + card->blocklen/card->readcnt); + + memcpy(pcache->buffer + (card->blocklen/card->readcnt) * x, + card->blockread, card->blocklen/card->readcnt); + card->blockread = NULL; + pcache->block = num; + pcache->jiffies_atc = jiffies; + pcache->valid = 1; + kfree(blockread); + } + + return error; + +outA: + kfree(blockread); +outB: + return error; +} + +/* communicate with maple bus for phased writing */ +static int maple_vmu_write_block(unsigned int num, const unsigned char *buf, + struct mtd_info *mtd) +{ + struct memcard *card; + struct mdev_part *mpart; + struct maple_device *mdev; + int partition, error, locking, x, phaselen, wait; + __be32 *sendbuf; + + mpart = mtd->priv; + mdev = mpart->mdev; + partition = mpart->partition; + card = maple_get_drvdata(mdev); + + phaselen = card->blocklen/card->writecnt; + + sendbuf = kmalloc(phaselen + 4, GFP_KERNEL); + if (!sendbuf) { + error = -ENOMEM; + goto fail_nosendbuf; + } + for (x = 0; x < card->writecnt; x++) { + sendbuf[0] = cpu_to_be32(partition << 24 | x << 16 | num); + memcpy(&sendbuf[1], buf + phaselen * x, phaselen); + /* wait until the device is not busy doing something else + * or 1 second - which ever is longer */ + if (atomic_read(&mdev->busy) == 1) { + wait_event_interruptible_timeout(mdev->maple_wait, + atomic_read(&mdev->busy) == 0, HZ); + if (atomic_read(&mdev->busy) == 1) { + error = -EBUSY; + dev_notice(&mdev->dev, "VMU write at (%d, %d)" + "failed - device is busy\n", + mdev->port, mdev->unit); + goto fail_nolock; + } + } + atomic_set(&mdev->busy, 1); + + locking = maple_add_packet(mdev, MAPLE_FUNC_MEMCARD, + MAPLE_COMMAND_BWRITE, phaselen / 4 + 2, sendbuf); + wait = wait_event_interruptible_timeout(mdev->maple_wait, + atomic_read(&mdev->busy) == 0, HZ/10); + if (locking) { + error = -EIO; + atomic_set(&mdev->busy, 0); + goto fail_nolock; + } + if (atomic_read(&mdev->busy) == 2) { + atomic_set(&mdev->busy, 0); + } else if (wait == 0 || wait == -ERESTARTSYS) { + error = -EIO; + dev_warn(&mdev->dev, "Write at (%d, %d) of block" + " 0x%X at phase %d failed: could not" + " communicate with VMU", mdev->port, + mdev->unit, num, x); + atomic_set(&mdev->busy, 0); + kfree(mdev->mq->sendbuf); + mdev->mq->sendbuf = NULL; + list_del_init(&(mdev->mq->list)); + goto fail_nolock; + } + } + kfree(sendbuf); + + return card->blocklen; + +fail_nolock: + kfree(sendbuf); +fail_nosendbuf: + dev_err(&mdev->dev, "VMU (%d, %d): write failed\n", mdev->port, + mdev->unit); + return error; +} + +/* mtd function to simulate reading byte by byte */ +static unsigned char vmu_flash_read_char(unsigned long ofs, int *retval, + struct mtd_info *mtd) +{ + struct vmu_block *vblock; + struct memcard *card; + struct mdev_part *mpart; + struct maple_device *mdev; + unsigned char *buf, ret; + int partition, error; + + mpart = mtd->priv; + mdev = mpart->mdev; + partition = mpart->partition; + card = maple_get_drvdata(mdev); + *retval = 0; + + buf = kmalloc(card->blocklen, GFP_KERNEL); + if (!buf) { + *retval = 1; + ret = -ENOMEM; + goto finish; + } + + vblock = ofs_to_block(ofs, mtd, partition); + if (!vblock) { + *retval = 3; + ret = -ENOMEM; + goto out_buf; + } + + error = maple_vmu_read_block(vblock->num, buf, mtd); + if (error) { + ret = error; + *retval = 2; + goto out_vblock; + } + + ret = buf[vblock->ofs]; + +out_vblock: + kfree(vblock); +out_buf: + kfree(buf); +finish: + return ret; +} + +/* mtd higher order function to read flash */ +static int vmu_flash_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct maple_device *mdev; + struct memcard *card; + struct mdev_part *mpart; + struct vmu_cache *pcache; + struct vmu_block *vblock; + int index = 0, retval, partition, leftover, numblocks; + unsigned char cx; + + if (len < 1) + return -EIO; + + mpart = mtd->priv; + mdev = mpart->mdev; + partition = mpart->partition; + card = maple_get_drvdata(mdev); + + numblocks = card->parts[partition].numblocks; + if (from + len > numblocks * card->blocklen) + len = numblocks * card->blocklen - from; + if (len == 0) + return -EIO; + /* Have we cached this bit already? */ + pcache = card->parts[partition].pcache; + do { + vblock = ofs_to_block(from + index, mtd, partition); + if (!vblock) + return -ENOMEM; + /* Have we cached this and is the cache valid and timely? */ + if (pcache->valid && + time_before(jiffies, pcache->jiffies_atc + HZ) && + (pcache->block == vblock->num)) { + /* we have cached it, so do necessary copying */ + leftover = card->blocklen - vblock->ofs; + if (vblock->ofs + len - index < card->blocklen) { + /* only a bit of this block to copy */ + memcpy(buf + index, + pcache->buffer + vblock->ofs, + len - index); + index = len; + } else { + /* otherwise copy remainder of whole block */ + memcpy(buf + index, pcache->buffer + + vblock->ofs, leftover); + index += leftover; + } + } else { + /* + * Not cached so read one byte - + * but cache the rest of the block + */ + cx = vmu_flash_read_char(from + index, &retval, mtd); + if (retval) { + *retlen = index; + kfree(vblock); + return cx; + } + memset(buf + index, cx, 1); + index++; + } + kfree(vblock); + } while (len > index); + *retlen = index; + + return 0; +} + +static int vmu_flash_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + struct maple_device *mdev; + struct memcard *card; + struct mdev_part *mpart; + int index = 0, partition, error = 0, numblocks; + struct vmu_cache *pcache; + struct vmu_block *vblock; + unsigned char *buffer; + + mpart = mtd->priv; + mdev = mpart->mdev; + partition = mpart->partition; + card = maple_get_drvdata(mdev); + + /* simple sanity checks */ + if (len < 1) { + error = -EIO; + goto failed; + } + numblocks = card->parts[partition].numblocks; + if (to + len > numblocks * card->blocklen) + len = numblocks * card->blocklen - to; + if (len == 0) { + error = -EIO; + goto failed; + } + + vblock = ofs_to_block(to, mtd, partition); + if (!vblock) { + error = -ENOMEM; + goto failed; + } + + buffer = kmalloc(card->blocklen, GFP_KERNEL); + if (!buffer) { + error = -ENOMEM; + goto fail_buffer; + } + + do { + /* Read in the block we are to write to */ + error = maple_vmu_read_block(vblock->num, buffer, mtd); + if (error) + goto fail_io; + + do { + buffer[vblock->ofs] = buf[index]; + vblock->ofs++; + index++; + if (index >= len) + break; + } while (vblock->ofs < card->blocklen); + + /* write out new buffer */ + error = maple_vmu_write_block(vblock->num, buffer, mtd); + /* invalidate the cache */ + pcache = card->parts[partition].pcache; + pcache->valid = 0; + + if (error != card->blocklen) + goto fail_io; + + vblock->num++; + vblock->ofs = 0; + } while (len > index); + + kfree(buffer); + *retlen = index; + kfree(vblock); + return 0; + +fail_io: + kfree(buffer); +fail_buffer: + kfree(vblock); +failed: + dev_err(&mdev->dev, "VMU write failing with error %d\n", error); + return error; +} + +static void vmu_flash_sync(struct mtd_info *mtd) +{ + /* Do nothing here */ +} + +/* Maple bus callback function to recursively query hardware details */ +static void vmu_queryblocks(struct mapleq *mq) +{ + struct maple_device *mdev; + unsigned short *res; + struct memcard *card; + __be32 partnum; + struct vmu_cache *pcache; + struct mdev_part *mpart; + struct mtd_info *mtd_cur; + struct vmupart *part_cur; + int error; + + mdev = mq->dev; + card = maple_get_drvdata(mdev); + res = (unsigned short *) (mq->recvbuf->buf); + card->tempA = res[12]; + card->tempB = res[6]; + + dev_info(&mdev->dev, "VMU device at partition %d has %d user " + "blocks with a root block at %d\n", card->partition, + card->tempA, card->tempB); + + part_cur = &card->parts[card->partition]; + part_cur->user_blocks = card->tempA; + part_cur->root_block = card->tempB; + part_cur->numblocks = card->tempB + 1; + part_cur->name = kmalloc(12, GFP_KERNEL); + if (!part_cur->name) + goto fail_name; + + sprintf(part_cur->name, "vmu%d.%d.%d", + mdev->port, mdev->unit, card->partition); + mtd_cur = &card->mtd[card->partition]; + mtd_cur->name = part_cur->name; + mtd_cur->type = 8; + mtd_cur->flags = MTD_WRITEABLE|MTD_NO_ERASE; + mtd_cur->size = part_cur->numblocks * card->blocklen; + mtd_cur->erasesize = card->blocklen; + mtd_cur->write = vmu_flash_write; + mtd_cur->read = vmu_flash_read; + mtd_cur->sync = vmu_flash_sync; + mtd_cur->writesize = card->blocklen; + + mpart = kmalloc(sizeof(struct mdev_part), GFP_KERNEL); + if (!mpart) + goto fail_mpart; + + mpart->mdev = mdev; + mpart->partition = card->partition; + mtd_cur->priv = mpart; + mtd_cur->owner = THIS_MODULE; + + pcache = kzalloc(sizeof(struct vmu_cache), GFP_KERNEL); + if (!pcache) + goto fail_cache_create; + part_cur->pcache = pcache; + + error = add_mtd_device(mtd_cur); + if (error) + goto fail_mtd_register; + + maple_getcond_callback(mdev, NULL, 0, + MAPLE_FUNC_MEMCARD); + + /* + * Set up a recursive call to the (probably theoretical) + * second or more partition + */ + if (++card->partition < card->partitions) { + partnum = cpu_to_be32(card->partition << 24); + maple_getcond_callback(mdev, vmu_queryblocks, 0, + MAPLE_FUNC_MEMCARD); + maple_add_packet(mdev, MAPLE_FUNC_MEMCARD, + MAPLE_COMMAND_GETMINFO, 2, &partnum); + } + return; + +fail_mtd_register: + dev_err(&mdev->dev, "Could not register maple device at (%d, %d)" + "error is 0x%X\n", mdev->port, mdev->unit, error); + for (error = 0; error <= card->partition; error++) { + kfree(((card->parts)[error]).pcache); + ((card->parts)[error]).pcache = NULL; + } +fail_cache_create: +fail_mpart: + for (error = 0; error <= card->partition; error++) { + kfree(((card->mtd)[error]).priv); + ((card->mtd)[error]).priv = NULL; + } + maple_getcond_callback(mdev, NULL, 0, + MAPLE_FUNC_MEMCARD); + kfree(part_cur->name); +fail_name: + return; +} + +/* Handles very basic info about the flash, queries for details */ +static int __devinit vmu_connect(struct maple_device *mdev) +{ + unsigned long test_flash_data, basic_flash_data; + int c, error; + struct memcard *card; + u32 partnum = 0; + + test_flash_data = be32_to_cpu(mdev->devinfo.function); + /* Need to count how many bits are set - to find out which + * function_data element has details of the memory card: + * using Brian Kernighan's/Peter Wegner's method */ + for (c = 0; test_flash_data; c++) + test_flash_data &= test_flash_data - 1; + + basic_flash_data = be32_to_cpu(mdev->devinfo.function_data[c - 1]); + + card = kmalloc(sizeof(struct memcard), GFP_KERNEL); + if (!card) { + error = ENOMEM; + goto fail_nomem; + } + + card->partitions = (basic_flash_data >> 24 & 0xFF) + 1; + card->blocklen = ((basic_flash_data >> 16 & 0xFF) + 1) << 5; + card->writecnt = basic_flash_data >> 12 & 0xF; + card->readcnt = basic_flash_data >> 8 & 0xF; + card->removeable = basic_flash_data >> 7 & 1; + + card->partition = 0; + + /* + * Not sure there are actually any multi-partition devices in the + * real world, but the hardware supports them, so, so will we + */ + card->parts = kmalloc(sizeof(struct vmupart) * card->partitions, + GFP_KERNEL); + if (!card->parts) { + error = -ENOMEM; + goto fail_partitions; + } + + card->mtd = kmalloc(sizeof(struct mtd_info) * card->partitions, + GFP_KERNEL); + if (!card->mtd) { + error = -ENOMEM; + goto fail_mtd_info; + } + + maple_set_drvdata(mdev, card); + + /* + * We want to trap meminfo not get cond + * so set interval to zero, but rely on maple bus + * driver to pass back the results of the meminfo + */ + maple_getcond_callback(mdev, vmu_queryblocks, 0, + MAPLE_FUNC_MEMCARD); + + /* Make sure we are clear to go */ + if (atomic_read(&mdev->busy) == 1) { + wait_event_interruptible_timeout(mdev->maple_wait, + atomic_read(&mdev->busy) == 0, HZ); + if (atomic_read(&mdev->busy) == 1) { + dev_notice(&mdev->dev, "VMU at (%d, %d) is busy\n", + mdev->port, mdev->unit); + error = -EAGAIN; + goto fail_device_busy; + } + } + + atomic_set(&mdev->busy, 1); + + /* + * Set up the minfo call: vmu_queryblocks will handle + * the information passed back + */ + error = maple_add_packet(mdev, MAPLE_FUNC_MEMCARD, + MAPLE_COMMAND_GETMINFO, 2, &partnum); + if (error) { + dev_err(&mdev->dev, "Could not lock VMU at (%d, %d)" + " error is 0x%X\n", mdev->port, mdev->unit, error); + goto fail_mtd_info; + } + return 0; + +fail_device_busy: + kfree(card->mtd); +fail_mtd_info: + kfree(card->parts); +fail_partitions: + kfree(card); +fail_nomem: + return error; +} + +static void __devexit vmu_disconnect(struct maple_device *mdev) +{ + struct memcard *card; + struct mdev_part *mpart; + int x; + + mdev->callback = NULL; + card = maple_get_drvdata(mdev); + for (x = 0; x < card->partitions; x++) { + mpart = ((card->mtd)[x]).priv; + mpart->mdev = NULL; + del_mtd_device(&((card->mtd)[x])); + kfree(((card->parts)[x]).name); + } + kfree(card->parts); + kfree(card->mtd); + kfree(card); +} + +/* Callback to handle eccentricities of both mtd subsystem + * and general flakyness of Dreamcast VMUs + */ +static int vmu_can_unload(struct maple_device *mdev) +{ + struct memcard *card; + int x; + struct mtd_info *mtd; + + card = maple_get_drvdata(mdev); + for (x = 0; x < card->partitions; x++) { + mtd = &((card->mtd)[x]); + if (mtd->usecount > 0) + return 0; + } + return 1; +} + +#define ERRSTR "VMU at (%d, %d) file error -" + +static void vmu_file_error(struct maple_device *mdev, void *recvbuf) +{ + enum maple_file_errors error = ((int *)recvbuf)[1]; + + switch (error) { + + case MAPLE_FILEERR_INVALID_PARTITION: + dev_notice(&mdev->dev, ERRSTR " invalid partition number\n", + mdev->port, mdev->unit); + break; + + case MAPLE_FILEERR_PHASE_ERROR: + dev_notice(&mdev->dev, ERRSTR " phase error\n", + mdev->port, mdev->unit); + break; + + case MAPLE_FILEERR_INVALID_BLOCK: + dev_notice(&mdev->dev, ERRSTR " invalid block number\n", + mdev->port, mdev->unit); + break; + + case MAPLE_FILEERR_WRITE_ERROR: + dev_notice(&mdev->dev, ERRSTR " write error\n", + mdev->port, mdev->unit); + break; + + case MAPLE_FILEERR_INVALID_WRITE_LENGTH: + dev_notice(&mdev->dev, ERRSTR " invalid write length\n", + mdev->port, mdev->unit); + break; + + case MAPLE_FILEERR_BAD_CRC: + dev_notice(&mdev->dev, ERRSTR " bad CRC\n", + mdev->port, mdev->unit); + break; + + default: + dev_notice(&mdev->dev, ERRSTR " 0x%X\n", + mdev->port, mdev->unit, error); + } +} + + +static int __devinit probe_maple_vmu(struct device *dev) +{ + int error; + struct maple_device *mdev = to_maple_dev(dev); + struct maple_driver *mdrv = to_maple_driver(dev->driver); + + mdev->can_unload = vmu_can_unload; + mdev->fileerr_handler = vmu_file_error; + mdev->driver = mdrv; + + error = vmu_connect(mdev); + if (error) + return error; + + return 0; +} + +static int __devexit remove_maple_vmu(struct device *dev) +{ + struct maple_device *mdev = to_maple_dev(dev); + + vmu_disconnect(mdev); + return 0; +} + +static struct maple_driver vmu_flash_driver = { + .function = MAPLE_FUNC_MEMCARD, + .drv = { + .name = "Dreamcast_visual_memory", + .probe = probe_maple_vmu, + .remove = __devexit_p(remove_maple_vmu), + }, +}; + +static int __init vmu_flash_map_init(void) +{ + return maple_driver_register(&vmu_flash_driver); +} + +static void __exit vmu_flash_map_exit(void) +{ + maple_driver_unregister(&vmu_flash_driver); +} + +module_init(vmu_flash_map_init); +module_exit(vmu_flash_map_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Adrian McMenamin"); +MODULE_DESCRIPTION("Flash mapping for Sega Dreamcast visual memory"); -- GitLab From db98812f6bbe17c5994d6290a68f8de8aa5ff8b9 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:17 +0000 Subject: [PATCH 2994/4982] qlge: Move reset logic into asic_reset_worker func. Get rid of extraneous ql_cycle_adapter. It's only called from the one place. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 41 ++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index d800ff40b32..ed7138d07ba 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3263,28 +3263,6 @@ err_init: return err; } -static int ql_cycle_adapter(struct ql_adapter *qdev) -{ - int status; - - status = ql_adapter_down(qdev); - if (status) - goto error; - - status = ql_adapter_up(qdev); - if (status) - goto error; - - return status; -error: - QPRINTK(qdev, IFUP, ALERT, - "Driver up/down cycle failed, closing device\n"); - rtnl_lock(); - dev_close(qdev->ndev); - rtnl_unlock(); - return status; -} - static void ql_release_adapter_resources(struct ql_adapter *qdev) { ql_free_mem_resources(qdev); @@ -3617,7 +3595,24 @@ static void ql_asic_reset_work(struct work_struct *work) { struct ql_adapter *qdev = container_of(work, struct ql_adapter, asic_reset_work.work); - ql_cycle_adapter(qdev); + int status; + + status = ql_adapter_down(qdev); + if (status) + goto error; + + status = ql_adapter_up(qdev); + if (status) + goto error; + + return; +error: + QPRINTK(qdev, IFUP, ALERT, + "Driver up/down cycle failed, closing device\n"); + rtnl_lock(); + set_bit(QL_ADAPTER_UP, &qdev->flags); + dev_close(qdev->ndev); + rtnl_unlock(); } static struct nic_operations qla8012_nic_ops = { -- GitLab From a75ee7f1ccace560642e5dc6b1c0e22c73da5a8c Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:18 +0000 Subject: [PATCH 2995/4982] qlge: Remove debug junk from asic reset logic. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index ed7138d07ba..bc04aebc928 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3129,36 +3129,23 @@ static int ql_adapter_initialize(struct ql_adapter *qdev) static int ql_adapter_reset(struct ql_adapter *qdev) { u32 value; - int max_wait_time; int status = 0; - int resetCnt = 0; + unsigned long end_jiffies = jiffies + + max((unsigned long)1, usecs_to_jiffies(30)); -#define MAX_RESET_CNT 1 -issueReset: - resetCnt++; - QPRINTK(qdev, IFDOWN, DEBUG, "Issue soft reset to chip.\n"); ql_write32(qdev, RST_FO, (RST_FO_FR << 16) | RST_FO_FR); - /* Wait for reset to complete. */ - max_wait_time = 3; - QPRINTK(qdev, IFDOWN, DEBUG, "Wait %d seconds for reset to complete.\n", - max_wait_time); + do { value = ql_read32(qdev, RST_FO); if ((value & RST_FO_FR) == 0) break; + cpu_relax(); + } while (time_before(jiffies, end_jiffies)); - ssleep(1); - } while ((--max_wait_time)); if (value & RST_FO_FR) { - QPRINTK(qdev, IFDOWN, ERR, - "Stuck in SoftReset: FSC_SR:0x%08x\n", value); - if (resetCnt < MAX_RESET_CNT) - goto issueReset; - } - if (max_wait_time == 0) { - status = -ETIMEDOUT; QPRINTK(qdev, IFDOWN, ERR, "ETIMEOUT!!! errored out of resetting the chip!\n"); + status = -ETIMEDOUT; } return status; -- GitLab From d555f5921f2b0d9f65b547dd0be67c870ff5a56f Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:19 +0000 Subject: [PATCH 2996/4982] qlge: Increase filtering for inbound csum settings. Chip does not do UDP checksum when fragmentation occurs. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge.h | 1 + drivers/net/qlge/qlge_main.c | 41 ++++++++++++++++++++++++------------ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 9918106f2a5..fcb159e4df5 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -977,6 +977,7 @@ struct ib_mac_iocb_rsp { u8 flags1; #define IB_MAC_IOCB_RSP_OI 0x01 /* Overide intr delay */ #define IB_MAC_IOCB_RSP_I 0x02 /* Disble Intr Generation */ +#define IB_MAC_CSUM_ERR_MASK 0x1c /* A mask to use for csum errs */ #define IB_MAC_IOCB_RSP_TE 0x04 /* Checksum error */ #define IB_MAC_IOCB_RSP_NU 0x08 /* No checksum rcvd */ #define IB_MAC_IOCB_RSP_IE 0x10 /* IPv4 checksum error */ diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index bc04aebc928..498d4bf5211 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -1531,22 +1531,37 @@ static void ql_process_mac_rx_intr(struct ql_adapter *qdev, if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_P) { QPRINTK(qdev, RX_STATUS, DEBUG, "Promiscuous Packet.\n"); } - if (ib_mac_rsp->flags1 & (IB_MAC_IOCB_RSP_IE | IB_MAC_IOCB_RSP_TE)) { - QPRINTK(qdev, RX_STATUS, ERR, - "Bad checksum for this %s packet.\n", - ((ib_mac_rsp-> - flags2 & IB_MAC_IOCB_RSP_T) ? "TCP" : "UDP")); - skb->ip_summed = CHECKSUM_NONE; - } else if (qdev->rx_csum && - ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) || - ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) && - !(ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_NU)))) { - QPRINTK(qdev, RX_STATUS, DEBUG, "RX checksum done!\n"); - skb->ip_summed = CHECKSUM_UNNECESSARY; + + + skb->protocol = eth_type_trans(skb, ndev); + skb->ip_summed = CHECKSUM_NONE; + + /* If rx checksum is on, and there are no + * csum or frame errors. + */ + if (qdev->rx_csum && + !(ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) && + !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) { + /* TCP frame. */ + if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) { + QPRINTK(qdev, RX_STATUS, DEBUG, + "TCP checksum done!\n"); + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else if ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) && + (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_V4)) { + /* Unfragmented ipv4 UDP frame. */ + struct iphdr *iph = (struct iphdr *) skb->data; + if (!(iph->frag_off & + cpu_to_be16(IP_MF|IP_OFFSET))) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + QPRINTK(qdev, RX_STATUS, DEBUG, + "TCP checksum done!\n"); + } + } } + qdev->stats.rx_packets++; qdev->stats.rx_bytes += skb->len; - skb->protocol = eth_type_trans(skb, ndev); skb_record_rx_queue(skb, rx_ring - &qdev->rx_ring[0]); if (qdev->vlgrp && (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V)) { QPRINTK(qdev, RX_STATUS, DEBUG, -- GitLab From 22bdd4f599b87734b7fc8137f47e62c13ab27e93 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:20 +0000 Subject: [PATCH 2997/4982] qlge: Add support for GRO. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 498d4bf5211..339e1da77e6 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -1507,6 +1507,8 @@ static void ql_process_mac_rx_intr(struct ql_adapter *qdev, { struct net_device *ndev = qdev->ndev; struct sk_buff *skb = NULL; + u16 vlan_id = (le16_to_cpu(ib_mac_rsp->vlan_id) & + IB_MAC_IOCB_RSP_VLAN_MASK) QL_DUMP_IB_MAC_RSP(ib_mac_rsp); @@ -1562,16 +1564,23 @@ static void ql_process_mac_rx_intr(struct ql_adapter *qdev, qdev->stats.rx_packets++; qdev->stats.rx_bytes += skb->len; - skb_record_rx_queue(skb, rx_ring - &qdev->rx_ring[0]); - if (qdev->vlgrp && (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V)) { - QPRINTK(qdev, RX_STATUS, DEBUG, - "Passing a VLAN packet upstream.\n"); - vlan_hwaccel_receive_skb(skb, qdev->vlgrp, - le16_to_cpu(ib_mac_rsp->vlan_id)); + skb_record_rx_queue(skb, + rx_ring->cq_id - qdev->rss_ring_first_cq_id); + if (skb->ip_summed == CHECKSUM_UNNECESSARY) { + if (qdev->vlgrp && + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) && + (vlan_id != 0)) + vlan_gro_receive(&rx_ring->napi, qdev->vlgrp, + vlan_id, skb); + else + napi_gro_receive(&rx_ring->napi, skb); } else { - QPRINTK(qdev, RX_STATUS, DEBUG, - "Passing a normal packet upstream.\n"); - netif_receive_skb(skb); + if (qdev->vlgrp && + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) && + (vlan_id != 0)) + vlan_hwaccel_receive_skb(skb, qdev->vlgrp, vlan_id); + else + netif_receive_skb(skb); } } @@ -1774,7 +1783,7 @@ static int ql_napi_poll_msix(struct napi_struct *napi, int budget) rx_ring->cq_id); if (work_done < budget) { - __napi_complete(napi); + napi_complete(napi); ql_enable_completion_interrupt(qdev, rx_ring->irq); } return work_done; @@ -3840,6 +3849,7 @@ static int __devinit qlge_probe(struct pci_dev *pdev, | NETIF_F_TSO_ECN | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER); + ndev->features |= NETIF_F_GRO; if (test_bit(QL_DMA64, &qdev->flags)) ndev->features |= NETIF_F_HIGHDMA; -- GitLab From 1e213303d8ef2a5d43fb64d2b373858ef70cc79b Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:21 +0000 Subject: [PATCH 2998/4982] qlge: Add tx multiqueue support. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 339e1da77e6..6da8901b0cc 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -1627,14 +1627,12 @@ static void ql_process_mac_tx_intr(struct ql_adapter *qdev, /* Fire up a handler to reset the MPI processor. */ void ql_queue_fw_error(struct ql_adapter *qdev) { - netif_stop_queue(qdev->ndev); netif_carrier_off(qdev->ndev); queue_delayed_work(qdev->workqueue, &qdev->mpi_reset_work, 0); } void ql_queue_asic_error(struct ql_adapter *qdev) { - netif_stop_queue(qdev->ndev); netif_carrier_off(qdev->ndev); ql_disable_interrupts(qdev); /* Clear adapter up bit to signal the recovery @@ -1689,6 +1687,7 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring) struct ob_mac_iocb_rsp *net_rsp = NULL; int count = 0; + struct tx_ring *tx_ring; /* While there are entries in the completion queue. */ while (prod != rx_ring->cnsmr_idx) { @@ -1714,15 +1713,16 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring) prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg); } ql_write_cq_idx(rx_ring); - if (netif_queue_stopped(qdev->ndev) && net_rsp != NULL) { - struct tx_ring *tx_ring = &qdev->tx_ring[net_rsp->txq_idx]; + tx_ring = &qdev->tx_ring[net_rsp->txq_idx]; + if (__netif_subqueue_stopped(qdev->ndev, tx_ring->wq_id) && + net_rsp != NULL) { if (atomic_read(&tx_ring->queue_stopped) && (atomic_read(&tx_ring->tx_count) > (tx_ring->wq_len / 4))) /* * The queue got stopped because the tx_ring was full. * Wake it up, because it's now at least 25% empty. */ - netif_wake_queue(qdev->ndev); + netif_wake_subqueue(qdev->ndev, tx_ring->wq_id); } return count; @@ -2054,7 +2054,7 @@ static int qlge_send(struct sk_buff *skb, struct net_device *ndev) struct ql_adapter *qdev = netdev_priv(ndev); int tso; struct tx_ring *tx_ring; - u32 tx_ring_idx = (u32) QL_TXQ_IDX(qdev, skb); + u32 tx_ring_idx = (u32) skb->queue_mapping; tx_ring = &qdev->tx_ring[tx_ring_idx]; @@ -2062,7 +2062,7 @@ static int qlge_send(struct sk_buff *skb, struct net_device *ndev) QPRINTK(qdev, TX_QUEUED, INFO, "%s: shutting down tx queue %d du to lack of resources.\n", __func__, tx_ring_idx); - netif_stop_queue(ndev); + netif_stop_subqueue(ndev, tx_ring->wq_id); atomic_inc(&tx_ring->queue_stopped); return NETDEV_TX_BUSY; } @@ -3192,12 +3192,10 @@ static void ql_display_dev_info(struct net_device *ndev) static int ql_adapter_down(struct ql_adapter *qdev) { - struct net_device *ndev = qdev->ndev; int i, status = 0; struct rx_ring *rx_ring; - netif_stop_queue(ndev); - netif_carrier_off(ndev); + netif_carrier_off(qdev->ndev); /* Don't kill the reset worker thread if we * are in the process of recovery. @@ -3261,12 +3259,11 @@ static int ql_adapter_up(struct ql_adapter *qdev) spin_unlock(&qdev->hw_lock); set_bit(QL_ADAPTER_UP, &qdev->flags); ql_alloc_rx_buffers(qdev); + if ((ql_read32(qdev, STS) & qdev->port_init)) + netif_carrier_on(qdev->ndev); ql_enable_interrupts(qdev); ql_enable_all_completion_interrupts(qdev); - if ((ql_read32(qdev, STS) & qdev->port_init)) { - netif_carrier_on(qdev->ndev); - netif_start_queue(qdev->ndev); - } + netif_tx_start_all_queues(qdev->ndev); return 0; err_init: @@ -3354,6 +3351,7 @@ static int ql_configure_rings(struct ql_adapter *qdev) * completion handler rx_rings. */ qdev->rx_ring_count = qdev->tx_ring_count + qdev->rss_ring_count + 1; + netif_set_gso_max_size(qdev->ndev, 65536); for (i = 0; i < qdev->tx_ring_count; i++) { tx_ring = &qdev->tx_ring[i]; @@ -3829,7 +3827,8 @@ static int __devinit qlge_probe(struct pci_dev *pdev, static int cards_found = 0; int err = 0; - ndev = alloc_etherdev(sizeof(struct ql_adapter)); + ndev = alloc_etherdev_mq(sizeof(struct ql_adapter), + min(MAX_CPUS, (int)num_online_cpus())); if (!ndev) return -ENOMEM; @@ -3872,7 +3871,6 @@ static int __devinit qlge_probe(struct pci_dev *pdev, return err; } netif_carrier_off(ndev); - netif_stop_queue(ndev); ql_display_dev_info(ndev); cards_found++; return 0; @@ -3926,7 +3924,6 @@ static pci_ers_result_t qlge_io_slot_reset(struct pci_dev *pdev) pci_set_master(pdev); netif_carrier_off(ndev); - netif_stop_queue(ndev); ql_adapter_reset(qdev); /* Make sure the EEPROM is good */ -- GitLab From c9cf0a04a0c20c26388c51052296d774ec92e2bd Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:22 +0000 Subject: [PATCH 2999/4982] qlge: bugfix: Tell hw to strip vlan header. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 6da8901b0cc..8b6128e7f5c 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3073,9 +3073,9 @@ static int ql_adapter_initialize(struct ql_adapter *qdev) mask = value << 16; ql_write32(qdev, SYS, mask | value); - /* Set the default queue. */ - value = NIC_RCV_CFG_DFQ; - mask = NIC_RCV_CFG_DFQ_MASK; + /* Set the default queue, and VLAN behavior. */ + value = NIC_RCV_CFG_DFQ | NIC_RCV_CFG_RV; + mask = NIC_RCV_CFG_DFQ_MASK | (NIC_RCV_CFG_RV << 16); ql_write32(qdev, NIC_RCV_CFG, (mask | value)); /* Set the MPI interrupt to enabled. */ -- GitLab From 08b1bc8f4aba4ddbc4ccef7ebc899e6faae81bbf Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:23 +0000 Subject: [PATCH 3000/4982] qlge: Get rid of irqsave/restore in intr disable. The completion interrupt disable routine is only called from the ISR, so there is no need for irqsave/restore. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 8b6128e7f5c..45ad4cc298b 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -587,7 +587,6 @@ u32 ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr) static u32 ql_disable_completion_interrupt(struct ql_adapter *qdev, u32 intr) { u32 var = 0; - unsigned long hw_flags; struct intr_context *ctx; /* HW disables for us if we're MSIX multi interrupts and @@ -597,14 +596,14 @@ static u32 ql_disable_completion_interrupt(struct ql_adapter *qdev, u32 intr) return 0; ctx = qdev->intr_context + intr; - spin_lock_irqsave(&qdev->hw_lock, hw_flags); + spin_lock(&qdev->hw_lock); if (!atomic_read(&ctx->irq_cnt)) { ql_write32(qdev, INTR_EN, ctx->intr_dis_mask); var = ql_read32(qdev, STS); } atomic_inc(&ctx->irq_cnt); - spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); + spin_unlock(&qdev->hw_lock); return var; } -- GitLab From b25215d0433f6c71b68eede3548815196a2ed5d5 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:24 +0000 Subject: [PATCH 3001/4982] qlge: Clear shadow registers before use. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 45ad4cc298b..75ad4dbb5cb 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -2142,6 +2142,7 @@ static int ql_alloc_shadow_space(struct ql_adapter *qdev) "Allocation of RX shadow space failed.\n"); return -ENOMEM; } + memset(qdev->rx_ring_shadow_reg_area, 0, PAGE_SIZE); qdev->tx_ring_shadow_reg_area = pci_alloc_consistent(qdev->pdev, PAGE_SIZE, &qdev->tx_ring_shadow_reg_dma); @@ -2150,6 +2151,7 @@ static int ql_alloc_shadow_space(struct ql_adapter *qdev) "Allocation of TX shadow space failed.\n"); goto err_wqp_sh_area; } + memset(qdev->tx_ring_shadow_reg_area, 0, PAGE_SIZE); return 0; err_wqp_sh_area: -- GitLab From 39a28bc480bff0f778d043877aff2fd16ad5f769 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:25 +0000 Subject: [PATCH 3002/4982] qlge: Remove spinlock from asic init path. There is nothing to contend with it. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 75ad4dbb5cb..f7f104ab5ff 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3250,14 +3250,12 @@ static int ql_adapter_up(struct ql_adapter *qdev) { int err = 0; - spin_lock(&qdev->hw_lock); err = ql_adapter_initialize(qdev); if (err) { QPRINTK(qdev, IFUP, INFO, "Unable to initialize adapter.\n"); spin_unlock(&qdev->hw_lock); goto err_init; } - spin_unlock(&qdev->hw_lock); set_bit(QL_ADAPTER_UP, &qdev->flags); ql_alloc_rx_buffers(qdev); if ((ql_read32(qdev, STS) & qdev->port_init)) -- GitLab From 6b318cb36813d03dd20f80e63c37176a55edae30 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:26 +0000 Subject: [PATCH 3003/4982] qlge: bugfix: Move netif_napi_del() to common call point. Moving netif_napi_del() up the call chain so it will get called from all exit points. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index f7f104ab5ff..ce826da6f16 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3236,6 +3236,11 @@ static int ql_adapter_down(struct ql_adapter *qdev) ql_tx_ring_clean(qdev); + /* Call netif_napi_del() from common point. + */ + for (i = qdev->rss_ring_first_cq_id; i < qdev->rx_ring_count; i++) + netif_napi_del(&qdev->rx_ring[i].napi); + ql_free_rx_buffers(qdev); spin_lock(&qdev->hw_lock); status = ql_adapter_reset(qdev); @@ -3964,7 +3969,7 @@ static int qlge_suspend(struct pci_dev *pdev, pm_message_t state) { struct net_device *ndev = pci_get_drvdata(pdev); struct ql_adapter *qdev = netdev_priv(ndev); - int err, i; + int err; netif_device_detach(ndev); @@ -3974,9 +3979,6 @@ static int qlge_suspend(struct pci_dev *pdev, pm_message_t state) return err; } - for (i = qdev->rss_ring_first_cq_id; i < qdev->rx_ring_count; i++) - netif_napi_del(&qdev->rx_ring[i].napi); - err = pci_save_state(pdev); if (err) return err; -- GitLab From 74c50b4bae225b8e5aff9a1ceca256ba46c665c6 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:27 +0000 Subject: [PATCH 3004/4982] qlge: bugfix: Pad outbound frames smaller than 60 bytes. With some asic configurations xmit of frames smaller than 60 bytes may fail. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index ce826da6f16..189584684aa 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -2057,6 +2057,9 @@ static int qlge_send(struct sk_buff *skb, struct net_device *ndev) tx_ring = &qdev->tx_ring[tx_ring_idx]; + if (skb_padto(skb, ETH_ZLEN)) + return NETDEV_TX_OK; + if (unlikely(atomic_read(&tx_ring->tx_count) < 2)) { QPRINTK(qdev, TX_QUEUED, INFO, "%s: shutting down tx queue %d du to lack of resources.\n", -- GitLab From d4a4aba61731ce6d102a6a93e22b8fa26511c9d5 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:28 +0000 Subject: [PATCH 3005/4982] qlge: bugfix: Fix endian issue related to rx buffers. This was introduced in an earlier net-next patch. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 189584684aa..b91b700a081 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -2526,6 +2526,7 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring) qdev->doorbell_area + (DB_PAGE_SIZE * (128 + rx_ring->cq_id)); int err = 0; u16 bq_len; + u64 tmp; /* Set up the shadow registers for this ring. */ rx_ring->prod_idx_sh_reg = shadow_reg; @@ -2571,7 +2572,8 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring) FLAGS_LI; /* Load irq delay values */ if (rx_ring->lbq_len) { cqicb->flags |= FLAGS_LL; /* Load lbq values */ - *((u64 *) rx_ring->lbq_base_indirect) = rx_ring->lbq_base_dma; + tmp = (u64)rx_ring->lbq_base_dma;; + *((__le64 *) rx_ring->lbq_base_indirect) = cpu_to_le64(tmp); cqicb->lbq_addr = cpu_to_le64(rx_ring->lbq_base_indirect_dma); bq_len = (rx_ring->lbq_buf_size == 65536) ? 0 : @@ -2587,11 +2589,12 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring) } if (rx_ring->sbq_len) { cqicb->flags |= FLAGS_LS; /* Load sbq values */ - *((u64 *) rx_ring->sbq_base_indirect) = rx_ring->sbq_base_dma; + tmp = (u64)rx_ring->sbq_base_dma;; + *((__le64 *) rx_ring->sbq_base_indirect) = cpu_to_le64(tmp); cqicb->sbq_addr = cpu_to_le64(rx_ring->sbq_base_indirect_dma); cqicb->sbq_buf_size = - cpu_to_le16(((rx_ring->sbq_buf_size / 2) + 8) & 0xfffffff8); + cpu_to_le16((u16)(rx_ring->sbq_buf_size/2)); bq_len = (rx_ring->sbq_len == 65536) ? 0 : (u16) rx_ring->sbq_len; cqicb->sbq_len = cpu_to_le16(bq_len); -- GitLab From fff94cd9f5527bbba13aa5ea5719d16531ca8e65 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 10 Mar 2009 11:48:07 +0000 Subject: [PATCH 3006/4982] [ARM] S3C: Tidy sleep code path to fix call flow As noted by Russell King, the sleep code path is not elegant and makes use of leaving items on the stack between calls. Change the code that does the following: if (s3c_cpu_save(regs_save) == 0) { flush_cache_all(); S3C_PMDBG("preparing to sleep\n"); pm_cpu_sleep(); } to simply call s3c_cpu_save, and let that do the necessary calls to quiesce and sleep the system. Signed-off-by: Ben Dooks --- arch/arm/plat-s3c/include/plat/pm.h | 8 ++++++++ arch/arm/plat-s3c/pm.c | 20 +++++++++++--------- arch/arm/plat-s3c24xx/sleep.S | 25 +++++++++---------------- 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/arch/arm/plat-s3c/include/plat/pm.h b/arch/arm/plat-s3c/include/plat/pm.h index 5ee26da2702..3779775133a 100644 --- a/arch/arm/plat-s3c/include/plat/pm.h +++ b/arch/arm/plat-s3c/include/plat/pm.h @@ -162,5 +162,13 @@ extern void s3c_pm_restore_gpios(void); */ extern void s3c_pm_save_gpios(void); +/** + * s3c_pm_cb_flushcache - callback for assembly code + * + * Callback to issue flush_cache_all() as this call is + * not a directly callable object. + */ +extern void s3c_pm_cb_flushcache(void); + extern void s3c_pm_save_core(void); extern void s3c_pm_restore_core(void); diff --git a/arch/arm/plat-s3c/pm.c b/arch/arm/plat-s3c/pm.c index a0ca18a75b0..061182ca66e 100644 --- a/arch/arm/plat-s3c/pm.c +++ b/arch/arm/plat-s3c/pm.c @@ -229,7 +229,7 @@ void (*pm_cpu_sleep)(void); static int s3c_pm_enter(suspend_state_t state) { - unsigned long regs_save[16]; + static unsigned long regs_save[16]; /* ensure the debug is initialised (if enabled) */ @@ -289,15 +289,11 @@ static int s3c_pm_enter(suspend_state_t state) s3c_pm_arch_stop_clocks(); - /* s3c2410_cpu_save will also act as our return point from when - * we resume as it saves its own register state, so use the return - * code to differentiate return from save and return from sleep */ + /* s3c_cpu_save will also act as our return point from when + * we resume as it saves its own register state and restores it + * during the resume. */ - if (s3c_cpu_save(regs_save) == 0) { - flush_cache_all(); - S3C_PMDBG("preparing to sleep\n"); - pm_cpu_sleep(); - } + s3c_cpu_save(regs_save); /* restore the cpu state using the kernel's cpu init code. */ @@ -325,6 +321,12 @@ static int s3c_pm_enter(suspend_state_t state) return 0; } +/* callback from assembly code */ +void s3c_pm_cb_flushcache(void) +{ + flush_cache_all(); +} + static int s3c_pm_prepare(void) { /* prepare check area if configured */ diff --git a/arch/arm/plat-s3c24xx/sleep.S b/arch/arm/plat-s3c24xx/sleep.S index ecb830be67d..e73e3b6e88d 100644 --- a/arch/arm/plat-s3c24xx/sleep.S +++ b/arch/arm/plat-s3c24xx/sleep.S @@ -42,21 +42,9 @@ .text /* s3c_cpu_save - * - * save enough of the CPU state to allow us to re-start - * pm.c code. as we store items like the sp/lr, we will - * end up returning from this function when the cpu resumes - * so the return value is set to mark this. - * - * This arangement means we avoid having to flush the cache - * from this code. * * entry: - * r0 = pointer to save block - * - * exit: - * r0 = 0 => we stored everything - * 1 => resumed from sleep + * r0 = save address (virtual addr of s3c_sleep_save_phys) */ ENTRY(s3c_cpu_save) @@ -71,14 +59,19 @@ ENTRY(s3c_cpu_save) stmia r0, { r4 - r13 } - mov r0, #0 - ldmfd sp, { r4 - r12, pc } + @@ write our state back to RAM + bl s3c_pm_cb_flushcache + @@ jump to final code to send system to sleep + ldr r0, =pm_cpu_sleep + @@ldr pc, [ r0 ] + ldr r0, [ r0 ] + mov pc, r0 + @@ return to the caller, after having the MMU @@ turned on, this restores the last bits from the @@ stack resume_with_mmu: - mov r0, #1 ldmfd sp!, { r4 - r12, pc } .ltorg -- GitLab From 916c775ff297dc60219a4f0e5527ba6ab4a88ed4 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Mon, 9 Mar 2009 00:52:14 +0000 Subject: [PATCH 3007/4982] bnx2x: Adding restriction on sge_buf_size sge_buff_size may not be more than 0xffff. Reported-by: Bjorn Helgaas Signed-off-by: Vladislav Zolotarov Tested-by: Bjorn Helgaas Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index d3e7775a9cc..48127f11d03 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -4518,7 +4518,8 @@ static void bnx2x_init_context(struct bnx2x *bp) (USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_TPA | USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_SGE_RING); context->ustorm_st_context.common.sge_buff_size = - (u16)(BCM_PAGE_SIZE*PAGES_PER_SGE); + (u16)min((u32)SGE_PAGE_SIZE*PAGES_PER_SGE, + (u32)0xffff); context->ustorm_st_context.common.sge_page_base_hi = U64_HI(fp->rx_sge_mapping); context->ustorm_st_context.common.sge_page_base_lo = -- GitLab From 6dc7d8c843024c2636cf52d3f93047acbcd765f2 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Mon, 9 Mar 2009 00:52:17 +0000 Subject: [PATCH 3008/4982] bnx2x: Casting page alignment Adding a proper cast to the argument of PAGE_ALIGN macro so that the output won't depend on its original type. Without this cast aligned value will be truncated to the size of the argument type. Reported-by: Bjorn Helgaas Signed-off-by: Vladislav Zolotarov Tested-by: Bjorn Helgaas Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 15a5cf0f676..3cf2b92eef3 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -152,7 +152,7 @@ struct sw_rx_page { #define PAGES_PER_SGE (1 << PAGES_PER_SGE_SHIFT) #define SGE_PAGE_SIZE PAGE_SIZE #define SGE_PAGE_SHIFT PAGE_SHIFT -#define SGE_PAGE_ALIGN(addr) PAGE_ALIGN(addr) +#define SGE_PAGE_ALIGN(addr) PAGE_ALIGN((typeof(PAGE_SIZE))addr) #define BCM_RX_ETH_PAYLOAD_ALIGN 64 -- GitLab From db434ac6bff0d991d0b60166dc9d6405b873d0f7 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Mon, 9 Mar 2009 00:52:21 +0000 Subject: [PATCH 3009/4982] bnx2x: Using DMAE to initialize the chip There was a bug, which occasionally caused failure in PRAM initialization after the cold boot. Also incremented version number to 1.45.27. Signed-off-by: Vladislav Zolotarov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_init.h | 4 ---- drivers/net/bnx2x_main.c | 18 +++++++++--------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/net/bnx2x_init.h b/drivers/net/bnx2x_init.h index a6c0b3abba2..3b0c2499ef1 100644 --- a/drivers/net/bnx2x_init.h +++ b/drivers/net/bnx2x_init.h @@ -150,7 +150,6 @@ static void bnx2x_init_ind_wr(struct bnx2x *bp, u32 addr, const u32 *data, static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len) { -#ifdef USE_DMAE int offset = 0; if (bp->dmae_ready) { @@ -164,9 +163,6 @@ static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len) addr + offset, len); } else bnx2x_init_str_wr(bp, addr, bp->gunzip_buf, len); -#else - bnx2x_init_str_wr(bp, addr, bp->gunzip_buf, len); -#endif } static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill, u32 len) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 48127f11d03..2e346a5e98c 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -57,7 +57,7 @@ #include "bnx2x.h" #include "bnx2x_init.h" -#define DRV_MODULE_VERSION "1.45.26" +#define DRV_MODULE_VERSION "1.45.27" #define DRV_MODULE_RELDATE "2009/01/26" #define BNX2X_BC_VER 0x040200 @@ -4035,10 +4035,10 @@ static void bnx2x_zero_sb(struct bnx2x *bp, int sb_id) { int port = BP_PORT(bp); - bnx2x_init_fill(bp, BAR_USTRORM_INTMEM + + bnx2x_init_fill(bp, USTORM_INTMEM_ADDR + USTORM_SB_HOST_STATUS_BLOCK_OFFSET(port, sb_id), 0, sizeof(struct ustorm_status_block)/4); - bnx2x_init_fill(bp, BAR_CSTRORM_INTMEM + + bnx2x_init_fill(bp, CSTORM_INTMEM_ADDR + CSTORM_SB_HOST_STATUS_BLOCK_OFFSET(port, sb_id), 0, sizeof(struct cstorm_status_block)/4); } @@ -4092,18 +4092,18 @@ static void bnx2x_zero_def_sb(struct bnx2x *bp) { int func = BP_FUNC(bp); - bnx2x_init_fill(bp, BAR_USTRORM_INTMEM + + bnx2x_init_fill(bp, TSTORM_INTMEM_ADDR + + TSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0, + sizeof(struct tstorm_def_status_block)/4); + bnx2x_init_fill(bp, USTORM_INTMEM_ADDR + USTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0, sizeof(struct ustorm_def_status_block)/4); - bnx2x_init_fill(bp, BAR_CSTRORM_INTMEM + + bnx2x_init_fill(bp, CSTORM_INTMEM_ADDR + CSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0, sizeof(struct cstorm_def_status_block)/4); - bnx2x_init_fill(bp, BAR_XSTRORM_INTMEM + + bnx2x_init_fill(bp, XSTORM_INTMEM_ADDR + XSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0, sizeof(struct xstorm_def_status_block)/4); - bnx2x_init_fill(bp, BAR_TSTRORM_INTMEM + - TSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0, - sizeof(struct tstorm_def_status_block)/4); } static void bnx2x_init_def_sb(struct bnx2x *bp, -- GitLab From 0ddc110c6fef34c554999448cdffe9c174a15fc9 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Mon, 9 Mar 2009 08:50:52 +0000 Subject: [PATCH 3010/4982] netxen: cleanup rx handling o remove unused rx fragment handling code. o imporove check for status descriptor ownership. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 16 +------ drivers/net/netxen/netxen_nic_init.c | 71 +++++----------------------- 2 files changed, 13 insertions(+), 74 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index bd5fbb4ce86..73cb1164457 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -392,11 +392,8 @@ struct rcv_desc { #define STATUS_CKSUM_OK (2) /* owner bits of status_desc */ -#define STATUS_OWNER_HOST (0x1) -#define STATUS_OWNER_PHANTOM (0x2) - -#define NETXEN_PROT_IP (1) -#define NETXEN_PROT_UNKNOWN (0) +#define STATUS_OWNER_HOST (0x1ULL << 56) +#define STATUS_OWNER_PHANTOM (0x2ULL << 56) /* Note: sizeof(status_desc) should always be a mutliple of 2 */ @@ -422,15 +419,6 @@ struct rcv_desc { #define netxen_get_sts_opcode(sts_data) \ (((sts_data) >> 58) & 0x03F) -#define netxen_get_sts_owner(status_desc) \ - ((le64_to_cpu((status_desc)->status_desc_data) >> 56) & 0x03) -#define netxen_set_sts_owner(status_desc, val) { \ - (status_desc)->status_desc_data = \ - ((status_desc)->status_desc_data & \ - ~cpu_to_le64(0x3ULL << 56)) | \ - cpu_to_le64((u64)((val) & 0x3) << 56); \ -} - struct status_desc { /* Bit pattern: 0-3 port, 4-7 status, 8-11 type, 12-27 total_length 28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index f323cee1b95..f8164345e3b 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -838,13 +838,8 @@ no_skb: return skb; } -/* - * netxen_process_rcv() send the received packet to the protocol stack. - * and if the number of receives exceeds RX_BUFFERS_REFILL, then we - * invoke the routine to send more rx buffers to the Phantom... - */ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid, - struct status_desc *desc, struct status_desc *frag_desc) + struct status_desc *desc) { struct net_device *netdev = adapter->netdev; u64 sts_data = le64_to_cpu(desc->status_desc_data); @@ -859,15 +854,11 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid, desc_ctx = netxen_get_sts_type(sts_data); if (unlikely(desc_ctx >= NUM_RCV_DESC_RINGS)) { - printk("%s: %s Bad Rcv descriptor ring\n", - netxen_nic_driver_name, netdev->name); return; } rds_ring = &recv_ctx->rds_rings[desc_ctx]; if (unlikely(index > rds_ring->max_rx_desc_count)) { - DPRINTK(ERR, "Got a buffer index:%x Max is %x\n", - index, rds_ring->max_rx_desc_count); return; } buffer = &rds_ring->rx_buf_arr[index]; @@ -879,14 +870,6 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid, buffer->lro_length = length; } if (buffer->lro_current_frags != buffer->lro_expected_frags) { - if (buffer->lro_expected_frags != 0) { - printk("LRO: (refhandle:%x) recv frag. " - "wait for last. flags: %x expected:%d " - "have:%d\n", index, - netxen_get_sts_desc_lro_last_frag(desc), - buffer->lro_expected_frags, - buffer->lro_current_frags); - } return; } } @@ -913,28 +896,10 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid, skb->protocol = eth_type_trans(skb, netdev); - /* - * rx buffer chaining is disabled, walk and free - * any spurious rx buffer chain. - */ - if (frag_desc) { - u16 i, nr_frags = desc->nr_frags; - - dev_kfree_skb_any(skb); - for (i = 0; i < nr_frags; i++) { - index = le16_to_cpu(frag_desc->frag_handles[i]); - skb = netxen_process_rxbuf(adapter, - rds_ring, index, cksum); - if (skb) - dev_kfree_skb_any(skb); - } - adapter->stats.rxdropped++; - } else { - netif_receive_skb(skb); + netif_receive_skb(skb); - adapter->stats.no_rcv++; - adapter->stats.rxbytes += length; - } + adapter->stats.no_rcv++; + adapter->stats.rxbytes += length; } /* Process Receive status ring */ @@ -942,7 +907,7 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max) { struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]); struct status_desc *desc_head = recv_ctx->rcv_status_desc_head; - struct status_desc *desc, *frag_desc; + struct status_desc *desc; u32 consumer = recv_ctx->status_rx_consumer; int count = 0, ring; u64 sts_data; @@ -950,41 +915,27 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max) while (count < max) { desc = &desc_head[consumer]; - if (!(netxen_get_sts_owner(desc) & STATUS_OWNER_HOST)) { - DPRINTK(ERR, "desc %p ownedby %x\n", desc, - netxen_get_sts_owner(desc)); + sts_data = le64_to_cpu(desc->status_desc_data); + + if (!(sts_data & STATUS_OWNER_HOST)) break; - } - sts_data = le64_to_cpu(desc->status_desc_data); opcode = netxen_get_sts_opcode(sts_data); - frag_desc = NULL; - if (opcode == NETXEN_NIC_RXPKT_DESC) { - if (desc->nr_frags) { - consumer = get_next_index(consumer, - adapter->max_rx_desc_count); - frag_desc = &desc_head[consumer]; - netxen_set_sts_owner(frag_desc, - STATUS_OWNER_PHANTOM); - } - } - netxen_process_rcv(adapter, ctxid, desc, frag_desc); + netxen_process_rcv(adapter, ctxid, desc); - netxen_set_sts_owner(desc, STATUS_OWNER_PHANTOM); + desc->status_desc_data = cpu_to_le64(STATUS_OWNER_PHANTOM); consumer = get_next_index(consumer, adapter->max_rx_desc_count); count++; } + for (ring = 0; ring < adapter->max_rds_rings; ring++) netxen_post_rx_buffers_nodb(adapter, ctxid, ring); - /* update the consumer index in phantom */ if (count) { recv_ctx->status_rx_consumer = consumer; - - /* Window = 1 */ adapter->pci_write_normalize(adapter, recv_ctx->crb_sts_consumer, consumer); } -- GitLab From d32cc3d24eace8a271a39ffe8aeae1861f400d2d Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Mon, 9 Mar 2009 08:50:53 +0000 Subject: [PATCH 3011/4982] netxen: small xmit optimizations Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 5 +---- drivers/net/netxen/netxen_nic_init.c | 2 ++ drivers/net/netxen/netxen_nic_main.c | 22 ++++++++++++++-------- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 73cb1164457..b5c0d66daf7 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -358,10 +358,7 @@ struct cmd_desc_type0 { __le64 addr_buffer1; }; - __le16 buffer1_length; - __le16 buffer2_length; - __le16 buffer3_length; - __le16 buffer4_length; + __le16 buffer_length[4]; union { struct { diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index f8164345e3b..72aba634554 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -955,6 +955,7 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter) int done = 0; last_consumer = adapter->last_cmd_consumer; + barrier(); /* cmd_consumer can change underneath */ consumer = le32_to_cpu(*(adapter->cmd_consumer)); while (last_consumer != consumer) { @@ -1005,6 +1006,7 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter) * There is still a possible race condition and the host could miss an * interrupt. The card has to take care of this. */ + barrier(); /* cmd_consumer can change underneath */ consumer = le32_to_cpu(*(adapter->cmd_consumer)); done = (last_consumer == consumer); diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index dfd66eaed1a..c9519843f8c 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -1212,7 +1212,16 @@ netxen_clean_tx_dma_mapping(struct pci_dev *pdev, } } -static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) +static inline void +netxen_clear_cmddesc(u64 *desc) +{ + int i; + for (i = 0; i < 8; i++) + desc[i] = 0ULL; +} + +static int +netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct netxen_adapter *adapter = netdev_priv(netdev); struct netxen_hardware_context *hw = &adapter->ahw; @@ -1245,7 +1254,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) /* Copy the descriptors into the hardware */ hwdesc = &hw->cmd_desc_head[producer]; - memset(hwdesc, 0, sizeof(struct cmd_desc_type0)); + netxen_clear_cmddesc((u64 *)hwdesc); /* Take skb->data itself */ pbuf = &adapter->cmd_buf_arr[producer]; @@ -1264,7 +1273,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) netxen_set_tx_frags_len(hwdesc, frag_count, skb->len); netxen_set_tx_port(hwdesc, adapter->portnum); - hwdesc->buffer1_length = cpu_to_le16(first_seg_len); + hwdesc->buffer_length[0] = cpu_to_le16(first_seg_len); hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma); for (i = 1, k = 1; i < frag_count; i++, k++) { @@ -1277,7 +1286,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) k = 0; producer = get_next_index(producer, num_txd); hwdesc = &hw->cmd_desc_head[producer]; - memset(hwdesc, 0, sizeof(struct cmd_desc_type0)); + netxen_clear_cmddesc((u64 *)hwdesc); pbuf = &adapter->cmd_buf_arr[producer]; pbuf->skb = NULL; } @@ -1297,21 +1306,18 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) buffrag->dma = temp_dma; buffrag->length = temp_len; + hwdesc->buffer_length[k] = cpu_to_le16(temp_len); switch (k) { case 0: - hwdesc->buffer1_length = cpu_to_le16(temp_len); hwdesc->addr_buffer1 = cpu_to_le64(temp_dma); break; case 1: - hwdesc->buffer2_length = cpu_to_le16(temp_len); hwdesc->addr_buffer2 = cpu_to_le64(temp_dma); break; case 2: - hwdesc->buffer3_length = cpu_to_le16(temp_len); hwdesc->addr_buffer3 = cpu_to_le64(temp_dma); break; case 3: - hwdesc->buffer4_length = cpu_to_le16(temp_len); hwdesc->addr_buffer4 = cpu_to_le64(temp_dma); break; } -- GitLab From 9f5bc7f1908665d7cf379f698c7bdc53bc10da85 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Mon, 9 Mar 2009 08:50:54 +0000 Subject: [PATCH 3012/4982] netxen: refactor netdev open close rearrange open and close into hardware attach(), detach() and nic up() and down(). this will be used for suspend/resume subsequently. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_main.c | 302 +++++++++++++++------------ 1 file changed, 166 insertions(+), 136 deletions(-) diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index c9519843f8c..2953a83bc85 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -94,20 +94,6 @@ static struct pci_device_id netxen_pci_tbl[] __devinitdata = { MODULE_DEVICE_TABLE(pci, netxen_pci_tbl); -/* - * In netxen_nic_down(), we must wait for any pending callback requests into - * netxen_watchdog_task() to complete; eg otherwise the watchdog_timer could be - * reenabled right after it is deleted in netxen_nic_down(). - * FLUSH_SCHEDULED_WORK() does this synchronization. - * - * Normally, schedule_work()/flush_scheduled_work() could have worked, but - * netxen_nic_close() is invoked with kernel rtnl lock held. netif_carrier_off() - * call in netxen_nic_close() triggers a schedule_work(&linkwatch_work), and a - * subsequent call to flush_scheduled_work() in netxen_nic_down() would cause - * linkwatch_event() to be executed which also attempts to acquire the rtnl - * lock thus causing a deadlock. - */ - static struct workqueue_struct *netxen_workq; #define SCHEDULE_WORK(tp) queue_work(netxen_workq, tp) #define FLUSH_SCHEDULED_WORK() flush_workqueue(netxen_workq) @@ -722,6 +708,163 @@ netxen_start_firmware(struct netxen_adapter *adapter) return 0; } +static int +netxen_nic_request_irq(struct netxen_adapter *adapter) +{ + irq_handler_t handler; + unsigned long flags = IRQF_SAMPLE_RANDOM; + struct net_device *netdev = adapter->netdev; + + if ((adapter->msi_mode != MSI_MODE_MULTIFUNC) || + (adapter->intr_scheme != INTR_SCHEME_PERPORT)) { + printk(KERN_ERR "%s: Firmware interrupt scheme is " + "incompatible with driver\n", + netdev->name); + adapter->driver_mismatch = 1; + return -EINVAL; + } + + if (adapter->flags & NETXEN_NIC_MSIX_ENABLED) + handler = netxen_msix_intr; + else if (adapter->flags & NETXEN_NIC_MSI_ENABLED) + handler = netxen_msi_intr; + else { + flags |= IRQF_SHARED; + handler = netxen_intr; + } + adapter->irq = netdev->irq; + + return request_irq(adapter->irq, handler, + flags, netdev->name, adapter); +} + +static int +netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) +{ + int err; + + err = adapter->init_port(adapter, adapter->physical_port); + if (err) { + printk(KERN_ERR "%s: Failed to initialize port %d\n", + netxen_nic_driver_name, adapter->portnum); + return err; + } + adapter->macaddr_set(adapter, netdev->dev_addr); + + netxen_nic_set_link_parameters(adapter); + + netxen_set_multicast_list(netdev); + if (adapter->set_mtu) + adapter->set_mtu(adapter, netdev->mtu); + + adapter->ahw.linkup = 0; + mod_timer(&adapter->watchdog_timer, jiffies); + + napi_enable(&adapter->napi); + netxen_nic_enable_int(adapter); + + return 0; +} + +static void +netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) +{ + netif_carrier_off(netdev); + netif_stop_queue(netdev); + napi_disable(&adapter->napi); + + if (adapter->stop_port) + adapter->stop_port(adapter); + + netxen_nic_disable_int(adapter); + + netxen_release_tx_buffers(adapter); + + FLUSH_SCHEDULED_WORK(); + del_timer_sync(&adapter->watchdog_timer); +} + + +static int +netxen_nic_attach(struct netxen_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; + int err, ctx, ring; + + err = netxen_init_firmware(adapter); + if (err != 0) { + printk(KERN_ERR "Failed to init firmware\n"); + return -EIO; + } + + if (adapter->fw_major < 4) + adapter->max_rds_rings = 3; + else + adapter->max_rds_rings = 2; + + err = netxen_alloc_sw_resources(adapter); + if (err) { + printk(KERN_ERR "%s: Error in setting sw resources\n", + netdev->name); + return err; + } + + netxen_nic_clear_stats(adapter); + + err = netxen_alloc_hw_resources(adapter); + if (err) { + printk(KERN_ERR "%s: Error in setting hw resources\n", + netdev->name); + goto err_out_free_sw; + } + + if (adapter->fw_major < 4) { + adapter->crb_addr_cmd_producer = + crb_cmd_producer[adapter->portnum]; + adapter->crb_addr_cmd_consumer = + crb_cmd_consumer[adapter->portnum]; + + netxen_nic_update_cmd_producer(adapter, 0); + netxen_nic_update_cmd_consumer(adapter, 0); + } + + for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { + for (ring = 0; ring < adapter->max_rds_rings; ring++) + netxen_post_rx_buffers(adapter, ctx, ring); + } + + err = netxen_nic_request_irq(adapter); + if (err) { + dev_err(&pdev->dev, "%s: failed to setup interrupt\n", + netdev->name); + goto err_out_free_rxbuf; + } + + adapter->is_up = NETXEN_ADAPTER_UP_MAGIC; + return 0; + +err_out_free_rxbuf: + netxen_release_rx_buffers(adapter); + netxen_free_hw_resources(adapter); +err_out_free_sw: + netxen_free_sw_resources(adapter); + return err; +} + +static void +netxen_nic_detach(struct netxen_adapter *adapter) +{ + if (adapter->irq) + free_irq(adapter->irq, adapter); + + netxen_release_rx_buffers(adapter); + netxen_free_hw_resources(adapter); + netxen_free_sw_resources(adapter); + + adapter->is_up = 0; +} + static int __devinit netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -973,9 +1116,7 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) unregister_netdev(netdev); if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { - netxen_free_hw_resources(adapter); - netxen_release_rx_buffers(adapter); - netxen_free_sw_resources(adapter); + netxen_nic_detach(adapter); if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) netxen_p3_free_mac_list(adapter); @@ -984,9 +1125,6 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) if (adapter->portnum == 0) netxen_free_adapter_offload(adapter); - if (adapter->irq) - free_irq(adapter->irq, adapter); - netxen_teardown_intr(adapter); netxen_cleanup_pci_map(adapter); @@ -998,125 +1136,30 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) free_netdev(netdev); } -/* - * Called when a network interface is made active - * @returns 0 on success, negative value on failure - */ static int netxen_nic_open(struct net_device *netdev) { struct netxen_adapter *adapter = netdev_priv(netdev); int err = 0; - int ctx, ring; - irq_handler_t handler; - unsigned long flags = IRQF_SAMPLE_RANDOM; if (adapter->driver_mismatch) return -EIO; if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) { - err = netxen_init_firmware(adapter); - if (err != 0) { - printk(KERN_ERR "Failed to init firmware\n"); - return -EIO; - } - - if (adapter->fw_major < 4) - adapter->max_rds_rings = 3; - else - adapter->max_rds_rings = 2; - - err = netxen_alloc_sw_resources(adapter); - if (err) { - printk(KERN_ERR "%s: Error in setting sw resources\n", - netdev->name); + err = netxen_nic_attach(adapter); + if (err) return err; - } - - netxen_nic_clear_stats(adapter); - - err = netxen_alloc_hw_resources(adapter); - if (err) { - printk(KERN_ERR "%s: Error in setting hw resources\n", - netdev->name); - goto err_out_free_sw; - } - - if ((adapter->msi_mode != MSI_MODE_MULTIFUNC) || - (adapter->intr_scheme != INTR_SCHEME_PERPORT)) { - printk(KERN_ERR "%s: Firmware interrupt scheme is " - "incompatible with driver\n", - netdev->name); - adapter->driver_mismatch = 1; - goto err_out_free_hw; - } - - if (adapter->fw_major < 4) { - adapter->crb_addr_cmd_producer = - crb_cmd_producer[adapter->portnum]; - adapter->crb_addr_cmd_consumer = - crb_cmd_consumer[adapter->portnum]; - - netxen_nic_update_cmd_producer(adapter, 0); - netxen_nic_update_cmd_consumer(adapter, 0); - } - - for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { - for (ring = 0; ring < adapter->max_rds_rings; ring++) - netxen_post_rx_buffers(adapter, ctx, ring); - } - if (adapter->flags & NETXEN_NIC_MSIX_ENABLED) - handler = netxen_msix_intr; - else if (adapter->flags & NETXEN_NIC_MSI_ENABLED) - handler = netxen_msi_intr; - else { - flags |= IRQF_SHARED; - handler = netxen_intr; - } - adapter->irq = netdev->irq; - err = request_irq(adapter->irq, handler, - flags, netdev->name, adapter); - if (err) { - printk(KERN_ERR "request_irq failed with: %d\n", err); - goto err_out_free_rxbuf; - } - - adapter->is_up = NETXEN_ADAPTER_UP_MAGIC; } - /* Done here again so that even if phantom sw overwrote it, - * we set it */ - err = adapter->init_port(adapter, adapter->physical_port); - if (err) { - printk(KERN_ERR "%s: Failed to initialize port %d\n", - netxen_nic_driver_name, adapter->portnum); - goto err_out_free_irq; - } - adapter->macaddr_set(adapter, netdev->dev_addr); - - netxen_nic_set_link_parameters(adapter); - - netxen_set_multicast_list(netdev); - if (adapter->set_mtu) - adapter->set_mtu(adapter, netdev->mtu); - - adapter->ahw.linkup = 0; - mod_timer(&adapter->watchdog_timer, jiffies); - - napi_enable(&adapter->napi); - netxen_nic_enable_int(adapter); + err = netxen_nic_up(adapter, netdev); + if (err) + goto err_out; netif_start_queue(netdev); return 0; -err_out_free_irq: - free_irq(adapter->irq, adapter); -err_out_free_rxbuf: - netxen_release_rx_buffers(adapter); -err_out_free_hw: - netxen_free_hw_resources(adapter); -err_out_free_sw: - netxen_free_sw_resources(adapter); +err_out: + netxen_nic_detach(adapter); return err; } @@ -1127,20 +1170,7 @@ static int netxen_nic_close(struct net_device *netdev) { struct netxen_adapter *adapter = netdev_priv(netdev); - netif_carrier_off(netdev); - netif_stop_queue(netdev); - napi_disable(&adapter->napi); - - if (adapter->stop_port) - adapter->stop_port(adapter); - - netxen_nic_disable_int(adapter); - - netxen_release_tx_buffers(adapter); - - FLUSH_SCHEDULED_WORK(); - del_timer_sync(&adapter->watchdog_timer); - + netxen_nic_down(adapter, netdev); return 0; } -- GitLab From becf46a012db667c562bbbe589c14e100b62e5a4 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Mon, 9 Mar 2009 08:50:55 +0000 Subject: [PATCH 3013/4982] netxen: cleanup superfluous multi-context code MAX_RCV_CTX was set to 1, there's only rx context per PCI function. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 7 +- drivers/net/netxen/netxen_nic_ctx.c | 130 +++++++-------- drivers/net/netxen/netxen_nic_ethtool.c | 11 +- drivers/net/netxen/netxen_nic_hdr.h | 6 - drivers/net/netxen/netxen_nic_init.c | 213 ++++++++++++------------ drivers/net/netxen/netxen_nic_main.c | 30 +--- 6 files changed, 178 insertions(+), 219 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index b5c0d66daf7..cde8e70b6b0 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -1280,7 +1280,7 @@ struct netxen_adapter { * Receive instances. These can be either one per port, * or one per peg, etc. */ - struct netxen_recv_context recv_ctx[MAX_RCV_CTX]; + struct netxen_recv_context recv_ctx; int is_up; struct netxen_dummy_dma dummy_dma; @@ -1464,10 +1464,9 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter); int netxen_init_firmware(struct netxen_adapter *adapter); void netxen_nic_clear_stats(struct netxen_adapter *adapter); void netxen_watchdog_task(struct work_struct *work); -void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, - u32 ringid); +void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid); int netxen_process_cmd_ring(struct netxen_adapter *adapter); -u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max); +int netxen_process_rcv_ring(struct netxen_adapter *adapter, int max); void netxen_p2_nic_set_multi(struct net_device *netdev); void netxen_p3_nic_set_multi(struct net_device *netdev); void netxen_p3_free_mac_list(struct netxen_adapter *adapter); diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c index 3e437065023..d125dca0131 100644 --- a/drivers/net/netxen/netxen_nic_ctx.c +++ b/drivers/net/netxen/netxen_nic_ctx.c @@ -141,7 +141,7 @@ int nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu) { u32 rcode = NX_RCODE_SUCCESS; - struct netxen_recv_context *recv_ctx = &adapter->recv_ctx[0]; + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE) rcode = netxen_issue_cmd(adapter, @@ -179,7 +179,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) int err; - struct netxen_recv_context *recv_ctx = &adapter->recv_ctx[0]; + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; /* only one sds ring for now */ nrds_rings = adapter->max_rds_rings; @@ -292,7 +292,7 @@ out_free_rq: static void nx_fw_cmd_destroy_rx_ctx(struct netxen_adapter *adapter) { - struct netxen_recv_context *recv_ctx = &adapter->recv_ctx[0]; + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; if (netxen_issue_cmd(adapter, adapter->ahw.pci_func, @@ -488,7 +488,7 @@ netxen_init_old_ctx(struct netxen_adapter *adapter) { struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; - int ctx, ring; + int ring; int func_id = adapter->portnum; adapter->ctx_desc->cmd_ring_addr = @@ -496,22 +496,20 @@ netxen_init_old_ctx(struct netxen_adapter *adapter) adapter->ctx_desc->cmd_ring_size = cpu_to_le32(adapter->max_tx_desc_count); - for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { - recv_ctx = &adapter->recv_ctx[ctx]; + recv_ctx = &adapter->recv_ctx; - for (ring = 0; ring < adapter->max_rds_rings; ring++) { - rds_ring = &recv_ctx->rds_rings[ring]; + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + rds_ring = &recv_ctx->rds_rings[ring]; - adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr = - cpu_to_le64(rds_ring->phys_addr); - adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size = - cpu_to_le32(rds_ring->max_rx_desc_count); - } - adapter->ctx_desc->sts_ring_addr = - cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr); - adapter->ctx_desc->sts_ring_size = - cpu_to_le32(adapter->max_rx_desc_count); + adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr = + cpu_to_le64(rds_ring->phys_addr); + adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size = + cpu_to_le32(rds_ring->max_rx_desc_count); } + adapter->ctx_desc->sts_ring_addr = + cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr); + adapter->ctx_desc->sts_ring_size = + cpu_to_le32(adapter->max_rx_desc_count); adapter->pci_write_normalize(adapter, CRB_CTX_ADDR_REG_LO(func_id), lower32(adapter->ctx_desc_phys_addr)); @@ -533,7 +531,7 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) u32 state = 0; void *addr; int err = 0; - int ctx, ring; + int ring; struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; @@ -575,48 +573,46 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) hw->cmd_desc_head = (struct cmd_desc_type0 *)addr; - for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { - recv_ctx = &adapter->recv_ctx[ctx]; - - for (ring = 0; ring < adapter->max_rds_rings; ring++) { - /* rx desc ring */ - rds_ring = &recv_ctx->rds_rings[ring]; - addr = pci_alloc_consistent(adapter->pdev, - RCV_DESC_RINGSIZE, - &rds_ring->phys_addr); - if (addr == NULL) { - printk(KERN_ERR "%s failed to allocate rx " - "desc ring[%d]\n", - netxen_nic_driver_name, ring); - err = -ENOMEM; - goto err_out_free; - } - rds_ring->desc_head = (struct rcv_desc *)addr; - - if (adapter->fw_major < 4) - rds_ring->crb_rcv_producer = - recv_crb_registers[adapter->portnum]. - crb_rcv_producer[ring]; - } + recv_ctx = &adapter->recv_ctx; - /* status desc ring */ + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + /* rx desc ring */ + rds_ring = &recv_ctx->rds_rings[ring]; addr = pci_alloc_consistent(adapter->pdev, - STATUS_DESC_RINGSIZE, - &recv_ctx->rcv_status_desc_phys_addr); + RCV_DESC_RINGSIZE, + &rds_ring->phys_addr); if (addr == NULL) { - printk(KERN_ERR "%s failed to allocate sts desc ring\n", - netxen_nic_driver_name); + printk(KERN_ERR "%s failed to allocate rx " + "desc ring[%d]\n", + netxen_nic_driver_name, ring); err = -ENOMEM; goto err_out_free; } - recv_ctx->rcv_status_desc_head = (struct status_desc *)addr; + rds_ring->desc_head = (struct rcv_desc *)addr; if (adapter->fw_major < 4) - recv_ctx->crb_sts_consumer = + rds_ring->crb_rcv_producer = recv_crb_registers[adapter->portnum]. - crb_sts_consumer; + crb_rcv_producer[ring]; } + /* status desc ring */ + addr = pci_alloc_consistent(adapter->pdev, + STATUS_DESC_RINGSIZE, + &recv_ctx->rcv_status_desc_phys_addr); + if (addr == NULL) { + printk(KERN_ERR "%s failed to allocate sts desc ring\n", + netxen_nic_driver_name); + err = -ENOMEM; + goto err_out_free; + } + recv_ctx->rcv_status_desc_head = (struct status_desc *)addr; + + if (adapter->fw_major < 4) + recv_ctx->crb_sts_consumer = + recv_crb_registers[adapter->portnum]. + crb_sts_consumer; + if (adapter->fw_major >= 4) { adapter->intr_scheme = INTR_SCHEME_PERPORT; adapter->msi_mode = MSI_MODE_MULTIFUNC; @@ -654,7 +650,7 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter) { struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; - int ctx, ring; + int ring; if (adapter->fw_major >= 4) { nx_fw_cmd_destroy_tx_ctx(adapter); @@ -679,27 +675,25 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter) adapter->ahw.cmd_desc_head = NULL; } - for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { - recv_ctx = &adapter->recv_ctx[ctx]; - for (ring = 0; ring < adapter->max_rds_rings; ring++) { - rds_ring = &recv_ctx->rds_rings[ring]; - - if (rds_ring->desc_head != NULL) { - pci_free_consistent(adapter->pdev, - RCV_DESC_RINGSIZE, - rds_ring->desc_head, - rds_ring->phys_addr); - rds_ring->desc_head = NULL; - } - } + recv_ctx = &adapter->recv_ctx; + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + rds_ring = &recv_ctx->rds_rings[ring]; - if (recv_ctx->rcv_status_desc_head != NULL) { + if (rds_ring->desc_head != NULL) { pci_free_consistent(adapter->pdev, - STATUS_DESC_RINGSIZE, - recv_ctx->rcv_status_desc_head, - recv_ctx->rcv_status_desc_phys_addr); - recv_ctx->rcv_status_desc_head = NULL; + RCV_DESC_RINGSIZE, + rds_ring->desc_head, + rds_ring->phys_addr); + rds_ring->desc_head = NULL; } } + + if (recv_ctx->rcv_status_desc_head != NULL) { + pci_free_consistent(adapter->pdev, + STATUS_DESC_RINGSIZE, + recv_ctx->rcv_status_desc_head, + recv_ctx->rcv_status_desc_phys_addr); + recv_ctx->rcv_status_desc_head = NULL; + } } diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index 6b25121cfc1..f811880a57c 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -474,16 +474,13 @@ static void netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring) { struct netxen_adapter *adapter = netdev_priv(dev); - int i; ring->rx_pending = 0; ring->rx_jumbo_pending = 0; - for (i = 0; i < MAX_RCV_CTX; ++i) { - ring->rx_pending += adapter->recv_ctx[i]. - rds_rings[RCV_DESC_NORMAL_CTXID].max_rx_desc_count; - ring->rx_jumbo_pending += adapter->recv_ctx[i]. - rds_rings[RCV_DESC_JUMBO_CTXID].max_rx_desc_count; - } + ring->rx_pending += adapter->recv_ctx. + rds_rings[RCV_DESC_NORMAL_CTXID].max_rx_desc_count; + ring->rx_jumbo_pending += adapter->recv_ctx. + rds_rings[RCV_DESC_JUMBO_CTXID].max_rx_desc_count; ring->tx_pending = adapter->max_tx_desc_count; if (adapter->ahw.board_type == NETXEN_NIC_GBE) diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h index e589d4bbd9b..016c62129c7 100644 --- a/drivers/net/netxen/netxen_nic_hdr.h +++ b/drivers/net/netxen/netxen_nic_hdr.h @@ -363,12 +363,6 @@ enum { #define NETXEN_HW_CRB_HUB_AGT_ADR_LPC \ ((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_LPC_CRB_AGT_ADR) -/* - * MAX_RCV_CTX : The number of receive contexts that are available on - * the phantom. - */ -#define MAX_RCV_CTX 1 - #define NETXEN_SRE_INT_STATUS (NETXEN_CRB_SRE + 0x00034) #define NETXEN_SRE_PBI_ACTIVE_STATUS (NETXEN_CRB_SRE + 0x01014) #define NETXEN_SRE_L1RE_CTL (NETXEN_CRB_SRE + 0x03000) diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 72aba634554..bd5e0d69223 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -49,8 +49,8 @@ static unsigned int crb_addr_xform[NETXEN_MAX_CRB_XFORM]; #define NETXEN_NIC_XDMA_RESET 0x8000ff -static void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, - uint32_t ctx, uint32_t ringid); +static void +netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, uint32_t ringid); static void crb_addr_transform_setup(void) { @@ -148,23 +148,21 @@ void netxen_release_rx_buffers(struct netxen_adapter *adapter) struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; struct netxen_rx_buffer *rx_buf; - int i, ctxid, ring; - - for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) { - recv_ctx = &adapter->recv_ctx[ctxid]; - for (ring = 0; ring < adapter->max_rds_rings; ring++) { - rds_ring = &recv_ctx->rds_rings[ring]; - for (i = 0; i < rds_ring->max_rx_desc_count; ++i) { - rx_buf = &(rds_ring->rx_buf_arr[i]); - if (rx_buf->state == NETXEN_BUFFER_FREE) - continue; - pci_unmap_single(adapter->pdev, - rx_buf->dma, - rds_ring->dma_size, - PCI_DMA_FROMDEVICE); - if (rx_buf->skb != NULL) - dev_kfree_skb_any(rx_buf->skb); - } + int i, ring; + + recv_ctx = &adapter->recv_ctx; + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + rds_ring = &recv_ctx->rds_rings[ring]; + for (i = 0; i < rds_ring->max_rx_desc_count; ++i) { + rx_buf = &(rds_ring->rx_buf_arr[i]); + if (rx_buf->state == NETXEN_BUFFER_FREE) + continue; + pci_unmap_single(adapter->pdev, + rx_buf->dma, + rds_ring->dma_size, + PCI_DMA_FROMDEVICE); + if (rx_buf->skb != NULL) + dev_kfree_skb_any(rx_buf->skb); } } } @@ -205,18 +203,17 @@ void netxen_free_sw_resources(struct netxen_adapter *adapter) { struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; - int ctx, ring; - - for (ctx = 0; ctx < MAX_RCV_CTX; ctx++) { - recv_ctx = &adapter->recv_ctx[ctx]; - for (ring = 0; ring < adapter->max_rds_rings; ring++) { - rds_ring = &recv_ctx->rds_rings[ring]; - if (rds_ring->rx_buf_arr) { - vfree(rds_ring->rx_buf_arr); - rds_ring->rx_buf_arr = NULL; - } + int ring; + + recv_ctx = &adapter->recv_ctx; + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + rds_ring = &recv_ctx->rds_rings[ring]; + if (rds_ring->rx_buf_arr) { + vfree(rds_ring->rx_buf_arr); + rds_ring->rx_buf_arr = NULL; } } + if (adapter->cmd_buf_arr) vfree(adapter->cmd_buf_arr); return; @@ -227,7 +224,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; struct netxen_rx_buffer *rx_buf; - int ctx, ring, i, num_rx_bufs; + int ring, i, num_rx_bufs; struct netxen_cmd_buffer *cmd_buf_arr; struct net_device *netdev = adapter->netdev; @@ -241,74 +238,72 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) memset(cmd_buf_arr, 0, TX_RINGSIZE); adapter->cmd_buf_arr = cmd_buf_arr; - for (ctx = 0; ctx < MAX_RCV_CTX; ctx++) { - recv_ctx = &adapter->recv_ctx[ctx]; - for (ring = 0; ring < adapter->max_rds_rings; ring++) { - rds_ring = &recv_ctx->rds_rings[ring]; - switch (RCV_DESC_TYPE(ring)) { - case RCV_DESC_NORMAL: - rds_ring->max_rx_desc_count = - adapter->max_rx_desc_count; - rds_ring->flags = RCV_DESC_NORMAL; - if (adapter->ahw.cut_through) { - rds_ring->dma_size = - NX_CT_DEFAULT_RX_BUF_LEN; - rds_ring->skb_size = - NX_CT_DEFAULT_RX_BUF_LEN; - } else { - rds_ring->dma_size = RX_DMA_MAP_LEN; - rds_ring->skb_size = - MAX_RX_BUFFER_LENGTH; - } - break; - - case RCV_DESC_JUMBO: - rds_ring->max_rx_desc_count = - adapter->max_jumbo_rx_desc_count; - rds_ring->flags = RCV_DESC_JUMBO; - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) - rds_ring->dma_size = - NX_P3_RX_JUMBO_BUF_MAX_LEN; - else - rds_ring->dma_size = - NX_P2_RX_JUMBO_BUF_MAX_LEN; + recv_ctx = &adapter->recv_ctx; + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + rds_ring = &recv_ctx->rds_rings[ring]; + switch (RCV_DESC_TYPE(ring)) { + case RCV_DESC_NORMAL: + rds_ring->max_rx_desc_count = + adapter->max_rx_desc_count; + rds_ring->flags = RCV_DESC_NORMAL; + if (adapter->ahw.cut_through) { + rds_ring->dma_size = + NX_CT_DEFAULT_RX_BUF_LEN; rds_ring->skb_size = - rds_ring->dma_size + NET_IP_ALIGN; - break; + NX_CT_DEFAULT_RX_BUF_LEN; + } else { + rds_ring->dma_size = RX_DMA_MAP_LEN; + rds_ring->skb_size = + MAX_RX_BUFFER_LENGTH; + } + break; - case RCV_RING_LRO: - rds_ring->max_rx_desc_count = - adapter->max_lro_rx_desc_count; - rds_ring->flags = RCV_DESC_LRO; - rds_ring->dma_size = RX_LRO_DMA_MAP_LEN; - rds_ring->skb_size = MAX_RX_LRO_BUFFER_LENGTH; - break; + case RCV_DESC_JUMBO: + rds_ring->max_rx_desc_count = + adapter->max_jumbo_rx_desc_count; + rds_ring->flags = RCV_DESC_JUMBO; + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + rds_ring->dma_size = + NX_P3_RX_JUMBO_BUF_MAX_LEN; + else + rds_ring->dma_size = + NX_P2_RX_JUMBO_BUF_MAX_LEN; + rds_ring->skb_size = + rds_ring->dma_size + NET_IP_ALIGN; + break; - } - rds_ring->rx_buf_arr = (struct netxen_rx_buffer *) - vmalloc(RCV_BUFFSIZE); - if (rds_ring->rx_buf_arr == NULL) { - printk(KERN_ERR "%s: Failed to allocate " - "rx buffer ring %d\n", - netdev->name, ring); - /* free whatever was already allocated */ - goto err_out; - } - memset(rds_ring->rx_buf_arr, 0, RCV_BUFFSIZE); - INIT_LIST_HEAD(&rds_ring->free_list); - /* - * Now go through all of them, set reference handles - * and put them in the queues. - */ - num_rx_bufs = rds_ring->max_rx_desc_count; - rx_buf = rds_ring->rx_buf_arr; - for (i = 0; i < num_rx_bufs; i++) { - list_add_tail(&rx_buf->list, - &rds_ring->free_list); - rx_buf->ref_handle = i; - rx_buf->state = NETXEN_BUFFER_FREE; - rx_buf++; - } + case RCV_RING_LRO: + rds_ring->max_rx_desc_count = + adapter->max_lro_rx_desc_count; + rds_ring->flags = RCV_DESC_LRO; + rds_ring->dma_size = RX_LRO_DMA_MAP_LEN; + rds_ring->skb_size = MAX_RX_LRO_BUFFER_LENGTH; + break; + + } + rds_ring->rx_buf_arr = (struct netxen_rx_buffer *) + vmalloc(RCV_BUFFSIZE); + if (rds_ring->rx_buf_arr == NULL) { + printk(KERN_ERR "%s: Failed to allocate " + "rx buffer ring %d\n", + netdev->name, ring); + /* free whatever was already allocated */ + goto err_out; + } + memset(rds_ring->rx_buf_arr, 0, RCV_BUFFSIZE); + INIT_LIST_HEAD(&rds_ring->free_list); + /* + * Now go through all of them, set reference handles + * and put them in the queues. + */ + num_rx_bufs = rds_ring->max_rx_desc_count; + rx_buf = rds_ring->rx_buf_arr; + for (i = 0; i < num_rx_bufs; i++) { + list_add_tail(&rx_buf->list, + &rds_ring->free_list); + rx_buf->ref_handle = i; + rx_buf->state = NETXEN_BUFFER_FREE; + rx_buf++; } } @@ -838,13 +833,13 @@ no_skb: return skb; } -static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid, +static void netxen_process_rcv(struct netxen_adapter *adapter, struct status_desc *desc) { struct net_device *netdev = adapter->netdev; u64 sts_data = le64_to_cpu(desc->status_desc_data); int index = netxen_get_sts_refhandle(sts_data); - struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]); + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; struct netxen_rx_buffer *buffer; struct sk_buff *skb; u32 length = netxen_get_sts_totallength(sts_data); @@ -902,10 +897,10 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid, adapter->stats.rxbytes += length; } -/* Process Receive status ring */ -u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max) +int +netxen_process_rcv_ring(struct netxen_adapter *adapter, int max) { - struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]); + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; struct status_desc *desc_head = recv_ctx->rcv_status_desc_head; struct status_desc *desc; u32 consumer = recv_ctx->status_rx_consumer; @@ -922,7 +917,7 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max) opcode = netxen_get_sts_opcode(sts_data); - netxen_process_rcv(adapter, ctxid, desc); + netxen_process_rcv(adapter, desc); desc->status_desc_data = cpu_to_le64(STATUS_OWNER_PHANTOM); @@ -932,7 +927,7 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max) } for (ring = 0; ring < adapter->max_rds_rings; ring++) - netxen_post_rx_buffers_nodb(adapter, ctxid, ring); + netxen_post_rx_buffers_nodb(adapter, ring); if (count) { recv_ctx->status_rx_consumer = consumer; @@ -1013,14 +1008,12 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter) return (done); } -/* - * netxen_post_rx_buffers puts buffer in the Phantom memory - */ -void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) +void +netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid) { struct pci_dev *pdev = adapter->pdev; struct sk_buff *skb; - struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]); + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; struct nx_host_rds_ring *rds_ring = NULL; uint producer; struct rcv_desc *pdesc; @@ -1098,12 +1091,12 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) } } -static void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, - uint32_t ctx, uint32_t ringid) +static void +netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, uint32_t ringid) { struct pci_dev *pdev = adapter->pdev; struct sk_buff *skb; - struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]); + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; struct nx_host_rds_ring *rds_ring = NULL; u32 producer; struct rcv_desc *pdesc; diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 2953a83bc85..3b4d923f947 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -790,7 +790,7 @@ netxen_nic_attach(struct netxen_adapter *adapter) { struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; - int err, ctx, ring; + int err, ring; err = netxen_init_firmware(adapter); if (err != 0) { @@ -829,10 +829,8 @@ netxen_nic_attach(struct netxen_adapter *adapter) netxen_nic_update_cmd_consumer(adapter, 0); } - for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { - for (ring = 0; ring < adapter->max_rds_rings; ring++) - netxen_post_rx_buffers(adapter, ctx, ring); - } + for (ring = 0; ring < adapter->max_rds_rings; ring++) + netxen_post_rx_buffers(adapter, ring); err = netxen_nic_request_irq(adapter); if (err) { @@ -1640,30 +1638,14 @@ static irqreturn_t netxen_msix_intr(int irq, void *data) static int netxen_nic_poll(struct napi_struct *napi, int budget) { - struct netxen_adapter *adapter = container_of(napi, struct netxen_adapter, napi); + struct netxen_adapter *adapter = + container_of(napi, struct netxen_adapter, napi); int tx_complete; - int ctx; int work_done; tx_complete = netxen_process_cmd_ring(adapter); - work_done = 0; - for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { - /* - * Fairness issue. This will give undue weight to the - * receive context 0. - */ - - /* - * To avoid starvation, we give each of our receivers, - * a fraction of the quota. Sometimes, it might happen that we - * have enough quota to process every packet, but since all the - * packets are on one context, it gets only half of the quota, - * and ends up not processing it. - */ - work_done += netxen_process_rcv_ring(adapter, ctx, - budget / MAX_RCV_CTX); - } + work_done = netxen_process_rcv_ring(adapter, budget); if ((work_done < budget) && tx_complete) { napi_complete(&adapter->napi); -- GitLab From 1e2d0059fc24c84356721c16c2ad0590c38015a0 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Mon, 9 Mar 2009 08:50:56 +0000 Subject: [PATCH 3014/4982] netxen: annotate board_config and board_type Remove huge board config structure from each instance, read only necessary fields from flash. Replace board_type with port_type (1G/10G), there's another board_type field describing card type (SFP/XFP/CX4). Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 12 ++- drivers/net/netxen/netxen_nic_ethtool.c | 33 ++++---- drivers/net/netxen/netxen_nic_hw.c | 108 ++++++++++++------------ drivers/net/netxen/netxen_nic_hw.h | 1 - drivers/net/netxen/netxen_nic_init.c | 2 +- drivers/net/netxen/netxen_nic_main.c | 38 ++------- 6 files changed, 85 insertions(+), 109 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index cde8e70b6b0..618507074bd 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -90,7 +90,6 @@ (sizeof(struct netxen_rx_buffer) * rds_ring->max_rx_desc_count) #define find_diff_among(a,b,range) ((a)<(b)?((b)-(a)):((b)+(range)-(a))) -#define NETXEN_NETDEV_STATUS 0x1 #define NETXEN_RCV_PRODUCER_OFFSET 0 #define NETXEN_RCV_PEG_DB_ID 2 #define NETXEN_HOST_DUMMY_DMA_SIZE 1024 @@ -795,21 +794,19 @@ struct netxen_hardware_context { void __iomem *pci_base0; void __iomem *pci_base1; void __iomem *pci_base2; - unsigned long first_page_group_end; - unsigned long first_page_group_start; void __iomem *db_base; unsigned long db_len; unsigned long pci_len0; - u8 cut_through; int qdr_sn_window; int ddr_mn_window; unsigned long mn_win_crb; unsigned long ms_win_crb; + u8 cut_through; u8 revision_id; - u16 board_type; - struct netxen_board_info boardcfg; + u16 port_type; + int board_type; u32 linkup; /* Address of cmd ring in Phantom */ struct cmd_desc_type0 *cmd_desc_head; @@ -1260,6 +1257,7 @@ struct netxen_adapter { u32 temp; u32 fw_major; + u32 fw_version; u8 msix_supported; u8 max_possible_rss_rings; @@ -1272,7 +1270,6 @@ struct netxen_adapter { u16 state; u16 link_autoneg; int rx_csum; - int status; struct netxen_cmd_buffer *cmd_buf_arr; /* Command buffers for xmit */ @@ -1391,6 +1388,7 @@ void netxen_nic_write_w1(struct netxen_adapter *adapter, u32 index, u32 value); void netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index, u32 *value); int netxen_nic_get_board_info(struct netxen_adapter *adapter); +void netxen_nic_get_firmware_info(struct netxen_adapter *adapter); int netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, ulong off, void *data, int len); diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index f811880a57c..8b4bdfd6a11 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -115,10 +115,9 @@ static int netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { struct netxen_adapter *adapter = netdev_priv(dev); - struct netxen_board_info *boardinfo = &adapter->ahw.boardcfg; /* read which mode */ - if (adapter->ahw.board_type == NETXEN_NIC_GBE) { + if (adapter->ahw.port_type == NETXEN_NIC_GBE) { ecmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | @@ -137,7 +136,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->duplex = adapter->link_duplex; ecmd->autoneg = adapter->link_autoneg; - } else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) { + } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { u32 val; adapter->hw_read_wx(adapter, NETXEN_PORT_MODE_ADDR, &val, 4); @@ -169,7 +168,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->phy_address = adapter->physical_port; ecmd->transceiver = XCVR_EXTERNAL; - switch ((netxen_brdtype_t) boardinfo->board_type) { + switch ((netxen_brdtype_t)adapter->ahw.board_type) { case NETXEN_BRDTYPE_P2_SB35_4G: case NETXEN_BRDTYPE_P2_SB31_2G: case NETXEN_BRDTYPE_P3_REF_QG: @@ -185,7 +184,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->supported |= SUPPORTED_TP; ecmd->advertising |= ADVERTISED_TP; ecmd->port = PORT_TP; - ecmd->autoneg = (boardinfo->board_type == + ecmd->autoneg = (adapter->ahw.board_type == NETXEN_BRDTYPE_P2_SB31_10G_CX4) ? (AUTONEG_DISABLE) : (adapter->link_autoneg); break; @@ -212,7 +211,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->autoneg = AUTONEG_DISABLE; break; case NETXEN_BRDTYPE_P3_10G_TP: - if (adapter->ahw.board_type == NETXEN_NIC_XGBE) { + if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { ecmd->autoneg = AUTONEG_DISABLE; ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP); ecmd->advertising |= @@ -228,7 +227,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) break; default: printk(KERN_ERR "netxen-nic: Unsupported board model %d\n", - (netxen_brdtype_t) boardinfo->board_type); + (netxen_brdtype_t)adapter->ahw.board_type); return -EIO; } @@ -242,7 +241,7 @@ netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) __u32 status; /* read which mode */ - if (adapter->ahw.board_type == NETXEN_NIC_GBE) { + if (adapter->ahw.port_type == NETXEN_NIC_GBE) { /* autonegotiation */ if (adapter->phy_write && adapter->phy_write(adapter, @@ -430,7 +429,7 @@ static u32 netxen_nic_test_link(struct net_device *dev) int val; /* read which mode */ - if (adapter->ahw.board_type == NETXEN_NIC_GBE) { + if (adapter->ahw.port_type == NETXEN_NIC_GBE) { if (adapter->phy_read && adapter->phy_read(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, @@ -440,7 +439,7 @@ static u32 netxen_nic_test_link(struct net_device *dev) val = netxen_get_phy_link(status); return !val; } - } else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) { + } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { val = adapter->pci_read_normalize(adapter, CRB_XG_STATE); return (val == XG_LINK_UP) ? 0 : 1; } @@ -483,7 +482,7 @@ netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring) rds_rings[RCV_DESC_JUMBO_CTXID].max_rx_desc_count; ring->tx_pending = adapter->max_tx_desc_count; - if (adapter->ahw.board_type == NETXEN_NIC_GBE) + if (adapter->ahw.port_type == NETXEN_NIC_GBE) ring->rx_max_pending = MAX_RCV_DESCRIPTORS_1G; else ring->rx_max_pending = MAX_RCV_DESCRIPTORS_10G; @@ -501,7 +500,7 @@ netxen_nic_get_pauseparam(struct net_device *dev, __u32 val; int port = adapter->physical_port; - if (adapter->ahw.board_type == NETXEN_NIC_GBE) { + if (adapter->ahw.port_type == NETXEN_NIC_GBE) { if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS)) return; /* get flow control settings */ @@ -524,7 +523,7 @@ netxen_nic_get_pauseparam(struct net_device *dev, pause->tx_pause = !(netxen_gb_get_gb3_mask(val)); break; } - } else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) { + } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS)) return; pause->rx_pause = 1; @@ -535,7 +534,7 @@ netxen_nic_get_pauseparam(struct net_device *dev, pause->tx_pause = !(netxen_xg_get_xg1_mask(val)); } else { printk(KERN_ERR"%s: Unknown board type: %x\n", - netxen_nic_driver_name, adapter->ahw.board_type); + netxen_nic_driver_name, adapter->ahw.port_type); } } @@ -547,7 +546,7 @@ netxen_nic_set_pauseparam(struct net_device *dev, __u32 val; int port = adapter->physical_port; /* read mode */ - if (adapter->ahw.board_type == NETXEN_NIC_GBE) { + if (adapter->ahw.port_type == NETXEN_NIC_GBE) { if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS)) return -EIO; /* set flow control */ @@ -591,7 +590,7 @@ netxen_nic_set_pauseparam(struct net_device *dev, break; } netxen_nic_write_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL, val); - } else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) { + } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS)) return -EIO; netxen_nic_read_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL, &val); @@ -610,7 +609,7 @@ netxen_nic_set_pauseparam(struct net_device *dev, } else { printk(KERN_ERR "%s: Unknown board type: %x\n", netxen_nic_driver_name, - adapter->ahw.board_type); + adapter->ahw.port_type); } return 0; } diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index b564d69cfa4..a93ab589d9c 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -728,9 +728,8 @@ int netxen_is_flash_supported(struct netxen_adapter *adapter) static int netxen_get_flash_block(struct netxen_adapter *adapter, int base, int size, __le32 * buf) { - int i, addr; + int i, v, addr; __le32 *ptr32; - u32 v; addr = base; ptr32 = buf; @@ -2089,47 +2088,44 @@ u32 netxen_nic_pci_read_normalize_2M(struct netxen_adapter *adapter, u64 off) int netxen_nic_get_board_info(struct netxen_adapter *adapter) { - int rv = 0; - int addr = NETXEN_BRDCFG_START; - struct netxen_board_info *boardinfo; - int index; - int *ptr32; + int offset, board_type, magic, header_version; + struct pci_dev *pdev = adapter->pdev; - boardinfo = &adapter->ahw.boardcfg; - ptr32 = (int *) boardinfo; + offset = NETXEN_BRDCFG_START + + offsetof(struct netxen_board_info, magic); + if (netxen_rom_fast_read(adapter, offset, &magic)) + return -EIO; - for (index = 0; index < sizeof(struct netxen_board_info) / sizeof(u32); - index++) { - if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) { - return -EIO; - } - ptr32++; - addr += sizeof(u32); - } - if (boardinfo->magic != NETXEN_BDINFO_MAGIC) { - printk("%s: ERROR reading %s board config." - " Read %x, expected %x\n", netxen_nic_driver_name, - netxen_nic_driver_name, - boardinfo->magic, NETXEN_BDINFO_MAGIC); - rv = -1; - } - if (boardinfo->header_version != NETXEN_BDINFO_VERSION) { - printk("%s: Unknown board config version." - " Read %x, expected %x\n", netxen_nic_driver_name, - boardinfo->header_version, NETXEN_BDINFO_VERSION); - rv = -1; + offset = NETXEN_BRDCFG_START + + offsetof(struct netxen_board_info, header_version); + if (netxen_rom_fast_read(adapter, offset, &header_version)) + return -EIO; + + if (magic != NETXEN_BDINFO_MAGIC || + header_version != NETXEN_BDINFO_VERSION) { + dev_err(&pdev->dev, + "invalid board config, magic=%08x, version=%08x\n", + magic, header_version); + return -EIO; } - if (boardinfo->board_type == NETXEN_BRDTYPE_P3_4_GB_MM) { + offset = NETXEN_BRDCFG_START + + offsetof(struct netxen_board_info, board_type); + if (netxen_rom_fast_read(adapter, offset, &board_type)) + return -EIO; + + adapter->ahw.board_type = board_type; + + if (board_type == NETXEN_BRDTYPE_P3_4_GB_MM) { u32 gpio = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_GLB_PAD_GPIO_I); if ((gpio & 0x8000) == 0) - boardinfo->board_type = NETXEN_BRDTYPE_P3_10G_TP; + board_type = NETXEN_BRDTYPE_P3_10G_TP; } - switch ((netxen_brdtype_t) boardinfo->board_type) { + switch ((netxen_brdtype_t)board_type) { case NETXEN_BRDTYPE_P2_SB35_4G: - adapter->ahw.board_type = NETXEN_NIC_GBE; + adapter->ahw.port_type = NETXEN_NIC_GBE; break; case NETXEN_BRDTYPE_P2_SB31_10G: case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ: @@ -2145,7 +2141,7 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter) case NETXEN_BRDTYPE_P3_10G_SFP_QT: case NETXEN_BRDTYPE_P3_10G_XFP: case NETXEN_BRDTYPE_P3_10000_BASE_T: - adapter->ahw.board_type = NETXEN_NIC_XGBE; + adapter->ahw.port_type = NETXEN_NIC_XGBE; break; case NETXEN_BRDTYPE_P1_BD: case NETXEN_BRDTYPE_P1_SB: @@ -2154,20 +2150,19 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter) case NETXEN_BRDTYPE_P3_REF_QG: case NETXEN_BRDTYPE_P3_4_GB: case NETXEN_BRDTYPE_P3_4_GB_MM: - adapter->ahw.board_type = NETXEN_NIC_GBE; + adapter->ahw.port_type = NETXEN_NIC_GBE; break; case NETXEN_BRDTYPE_P3_10G_TP: - adapter->ahw.board_type = (adapter->portnum < 2) ? + adapter->ahw.port_type = (adapter->portnum < 2) ? NETXEN_NIC_XGBE : NETXEN_NIC_GBE; break; default: - printk("%s: Unknown(%x)\n", netxen_nic_driver_name, - boardinfo->board_type); - rv = -ENODEV; + dev_err(&pdev->dev, "unknown board type %x\n", board_type); + adapter->ahw.port_type = NETXEN_NIC_XGBE; break; } - return rv; + return 0; } /* NIU access sections */ @@ -2213,7 +2208,7 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter) return; } - if (adapter->ahw.board_type == NETXEN_NIC_GBE) { + if (adapter->ahw.port_type == NETXEN_NIC_GBE) { adapter->hw_read_wx(adapter, NETXEN_PORT_MODE_ADDR, &port_mode, 4); if (port_mode == NETXEN_PORT_MODE_802_3_AP) { @@ -2268,17 +2263,14 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter) } } -void netxen_nic_flash_print(struct netxen_adapter *adapter) +void netxen_nic_get_firmware_info(struct netxen_adapter *adapter) { - u32 fw_major = 0; - u32 fw_minor = 0; - u32 fw_build = 0; + u32 fw_major, fw_minor, fw_build; char brd_name[NETXEN_MAX_SHORT_NAME]; char serial_num[32]; int i, addr; int *ptr32; - - struct netxen_board_info *board_info = &(adapter->ahw.boardcfg); + struct pci_dev *pdev = adapter->pdev; adapter->driver_mismatch = 0; @@ -2302,23 +2294,31 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter) adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_SUB, &fw_build, 4); adapter->fw_major = fw_major; + adapter->fw_version = NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build); if (adapter->portnum == 0) { - get_brd_name_by_type(board_info->board_type, brd_name); + get_brd_name_by_type(adapter->ahw.board_type, brd_name); printk(KERN_INFO "NetXen %s Board S/N %s Chip rev 0x%x\n", brd_name, serial_num, adapter->ahw.revision_id); - printk(KERN_INFO "NetXen Firmware version %d.%d.%d\n", - fw_major, fw_minor, fw_build); } - if (NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build) < - NETXEN_VERSION_CODE(3, 4, 216)) { + if (adapter->fw_version < NETXEN_VERSION_CODE(3, 4, 216)) { adapter->driver_mismatch = 1; - printk(KERN_ERR "%s: firmware version %d.%d.%d unsupported\n", - netxen_nic_driver_name, + dev_warn(&pdev->dev, "firmware version %d.%d.%d unsupported\n", fw_major, fw_minor, fw_build); return; } + + dev_info(&pdev->dev, "firmware version %d.%d.%d\n", + fw_major, fw_minor, fw_build); + + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { + adapter->hw_read_wx(adapter, + NETXEN_MIU_MN_CONTROL, &i, 4); + adapter->ahw.cut_through = (i & 0x4) ? 1 : 0; + dev_info(&pdev->dev, "firmware running in %s mode\n", + adapter->ahw.cut_through ? "cut-through" : "legacy"); + } } diff --git a/drivers/net/netxen/netxen_nic_hw.h b/drivers/net/netxen/netxen_nic_hw.h index 9fb51627ee5..04b47a7993c 100644 --- a/drivers/net/netxen/netxen_nic_hw.h +++ b/drivers/net/netxen/netxen_nic_hw.h @@ -57,7 +57,6 @@ struct netxen_adapter; struct netxen_port; void netxen_nic_set_link_parameters(struct netxen_adapter *adapter); -void netxen_nic_flash_print(struct netxen_adapter *adapter); typedef u8 netxen_ethernet_macaddr_t[6]; diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index bd5e0d69223..120b480c1e8 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -316,7 +316,7 @@ err_out: void netxen_initialize_adapter_ops(struct netxen_adapter *adapter) { - switch (adapter->ahw.board_type) { + switch (adapter->ahw.port_type) { case NETXEN_NIC_GBE: adapter->enable_phy_interrupts = netxen_niu_gbe_enable_phy_interrupts; diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 3b4d923f947..9445277321d 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -212,7 +212,7 @@ nx_update_dma_mask(struct netxen_adapter *adapter) static void netxen_check_options(struct netxen_adapter *adapter) { - switch (adapter->ahw.boardcfg.board_type) { + switch (adapter->ahw.board_type) { case NETXEN_BRDTYPE_P3_HMEZ: case NETXEN_BRDTYPE_P3_XG_LOM: case NETXEN_BRDTYPE_P3_10G_CX4: @@ -250,7 +250,7 @@ static void netxen_check_options(struct netxen_adapter *adapter) case NETXEN_BRDTYPE_P3_10G_TP: adapter->msix_supported = !!use_msi_x; - if (adapter->ahw.board_type == NETXEN_NIC_XGBE) + if (adapter->ahw.port_type == NETXEN_NIC_XGBE) adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G; else adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G; @@ -261,7 +261,7 @@ static void netxen_check_options(struct netxen_adapter *adapter) adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G; printk(KERN_WARNING "Unknown board type(0x%x)\n", - adapter->ahw.boardcfg.board_type); + adapter->ahw.board_type); break; } @@ -330,7 +330,7 @@ static void netxen_set_port_mode(struct netxen_adapter *adapter) { u32 val, data; - val = adapter->ahw.boardcfg.board_type; + val = adapter->ahw.board_type; if ((val == NETXEN_BRDTYPE_P3_HMEZ) || (val == NETXEN_BRDTYPE_P3_XG_LOM)) { if (port_mode == NETXEN_PORT_MODE_802_3_AP) { @@ -523,8 +523,6 @@ netxen_setup_pci_map(struct netxen_adapter *adapter) void __iomem *mem_ptr2 = NULL; void __iomem *db_ptr = NULL; - unsigned long first_page_group_end; - unsigned long first_page_group_start; unsigned long mem_base, mem_len, db_base, db_len = 0, pci_len0 = 0; struct pci_dev *pdev = adapter->pdev; @@ -562,14 +560,10 @@ netxen_setup_pci_map(struct netxen_adapter *adapter) SECOND_PAGE_GROUP_SIZE); mem_ptr2 = ioremap(mem_base + THIRD_PAGE_GROUP_START, THIRD_PAGE_GROUP_SIZE); - first_page_group_start = FIRST_PAGE_GROUP_START; - first_page_group_end = FIRST_PAGE_GROUP_END; } else if (mem_len == NETXEN_PCI_32MB_SIZE) { mem_ptr1 = ioremap(mem_base, SECOND_PAGE_GROUP_SIZE); mem_ptr2 = ioremap(mem_base + THIRD_PAGE_GROUP_START - SECOND_PAGE_GROUP_START, THIRD_PAGE_GROUP_SIZE); - first_page_group_start = 0; - first_page_group_end = 0; } else if (mem_len == NETXEN_PCI_2MB_SIZE) { adapter->hw_write_wx = netxen_nic_hw_write_wx_2M; adapter->hw_read_wx = netxen_nic_hw_read_wx_2M; @@ -589,8 +583,6 @@ netxen_setup_pci_map(struct netxen_adapter *adapter) return -EIO; } pci_len0 = mem_len; - first_page_group_start = 0; - first_page_group_end = 0; adapter->ahw.ddr_mn_window = 0; adapter->ahw.qdr_sn_window = 0; @@ -611,8 +603,6 @@ netxen_setup_pci_map(struct netxen_adapter *adapter) adapter->ahw.pci_base0 = mem_ptr0; adapter->ahw.pci_len0 = pci_len0; - adapter->ahw.first_page_group_start = first_page_group_start; - adapter->ahw.first_page_group_end = first_page_group_end; adapter->ahw.pci_base1 = mem_ptr1; adapter->ahw.pci_base2 = mem_ptr2; @@ -679,7 +669,7 @@ netxen_start_firmware(struct netxen_adapter *adapter) /* Initialize multicast addr pool owners */ val = 0x7654; - if (adapter->ahw.board_type == NETXEN_NIC_XGBE) + if (adapter->ahw.port_type == NETXEN_NIC_XGBE) val |= 0x0f000000; netxen_crb_writelit_adapter(adapter, NETXEN_MAC_ADDR_CNTL_REG, val); @@ -870,7 +860,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct netxen_adapter *adapter = NULL; int i = 0, err; int first_driver; - u32 val; int pci_func_id = PCI_FUNC(pdev->devfn); uint8_t revision_id; @@ -936,7 +925,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* This will be reset for mezz cards */ adapter->portnum = pci_func_id; - adapter->status &= ~NETXEN_NETDEV_STATUS; adapter->rx_csum = 1; adapter->mc_enabled = 0; if (NX_IS_REVISION_P3(revision_id)) @@ -974,7 +962,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netxen_initialize_adapter_ops(adapter); /* Mezz cards have PCI function 0,2,3 enabled */ - switch (adapter->ahw.boardcfg.board_type) { + switch (adapter->ahw.board_type) { case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ: case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ: if (pci_func_id >= 2) @@ -1007,15 +995,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) nx_update_dma_mask(adapter); - netxen_nic_flash_print(adapter); - - if (NX_IS_REVISION_P3(revision_id)) { - adapter->hw_read_wx(adapter, - NETXEN_MIU_MN_CONTROL, &val, 4); - adapter->ahw.cut_through = (val & 0x4) ? 1 : 0; - dev_info(&pdev->dev, "firmware running in %s mode\n", - adapter->ahw.cut_through ? "cut through" : "legacy"); - } + netxen_nic_get_firmware_info(adapter); /* * See if the firmware gave us a virtual-physical port mapping. @@ -1066,7 +1046,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_drvdata(pdev, adapter); - switch (adapter->ahw.board_type) { + switch (adapter->ahw.port_type) { case NETXEN_NIC_GBE: dev_info(&adapter->pdev->dev, "%s: GbE port initialized\n", adapter->netdev->name); @@ -1460,7 +1440,7 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) linkup = (val == XG_LINK_UP_P3); } else { val = adapter->pci_read_normalize(adapter, CRB_XG_STATE); - if (adapter->ahw.board_type == NETXEN_NIC_GBE) + if (adapter->ahw.port_type == NETXEN_NIC_GBE) linkup = (val >> port) & 1; else { val = (val >> port*8) & 0xff; -- GitLab From 3c420f27b7b2340a81989c8d9ed619e545dd2ad7 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sat, 7 Mar 2009 12:11:02 +0000 Subject: [PATCH 3015/4982] gigaset: Kconfig cleanup Streamline dependencies and remove some obsolete or redundant comments in the Gigaset ISDN driver's Kconfig file. In particular, remove the strong warning against the GIGASET_UNDOCREQ option, as in seven years of existence, the code in question has never been reported to cause any harm. Impact: Kconfig cleanup, no functional change Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/Kconfig | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/isdn/gigaset/Kconfig b/drivers/isdn/gigaset/Kconfig index 0017e50c694..9ca889adf12 100644 --- a/drivers/isdn/gigaset/Kconfig +++ b/drivers/isdn/gigaset/Kconfig @@ -1,5 +1,5 @@ menuconfig ISDN_DRV_GIGASET - tristate "Siemens Gigaset support (isdn)" + tristate "Siemens Gigaset support" select CRC_CCITT select BITREVERSE help @@ -11,11 +11,11 @@ menuconfig ISDN_DRV_GIGASET one of the connection specific parts that follow. This will build a module called "gigaset". -if ISDN_DRV_GIGASET!=n +if ISDN_DRV_GIGASET config GIGASET_BASE tristate "Gigaset base station support" - depends on ISDN_DRV_GIGASET && USB + depends on USB help Say M here if you want to use the USB interface of the Gigaset base for connection to your system. @@ -23,7 +23,7 @@ config GIGASET_BASE config GIGASET_M105 tristate "Gigaset M105 support" - depends on ISDN_DRV_GIGASET && USB + depends on USB help Say M here if you want to connect to the Gigaset base via DECT using a Gigaset M105 (Sinus 45 Data 2) USB DECT device. @@ -31,7 +31,6 @@ config GIGASET_M105 config GIGASET_M101 tristate "Gigaset M101 support" - depends on ISDN_DRV_GIGASET help Say M here if you want to connect to the Gigaset base via DECT using a Gigaset M101 (Sinus 45 Data 1) RS232 DECT device. @@ -48,7 +47,6 @@ config GIGASET_UNDOCREQ help This enables support for USB requests we only know from reverse engineering (currently M105 only). If you need - features like configuration mode of M105, say yes. If you - care about your device, say no. + features like configuration mode of M105, say yes. -endif # ISDN_DRV_GIGASET != n +endif # ISDN_DRV_GIGASET -- GitLab From 3f612132c7164d5cc9ed677a2fdf8950222d2170 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Sun, 8 Mar 2009 05:23:13 +0000 Subject: [PATCH 3016/4982] gigaset: return -ENOTTY for unimplemented functions A number of functions in the usb_gigaset module will return -EINVAL if CONFIG_GIGASET_UNDOCREQ is not set. Make these return -ENOTTY as it's more specific and it might make it easier to see (from userspace) why these functions actually fail. Impact: some error return codes changed Signed-off-by: Paul Bolle Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/usb-gigaset.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index fba61f67052..d7838516609 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c @@ -278,17 +278,17 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, unsigned new_state) { - return -EINVAL; + return -ENOTTY; } static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) { - return -EINVAL; + return -ENOTTY; } static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag) { - return -EINVAL; + return -ENOTTY; } #endif @@ -577,7 +577,7 @@ static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6]) return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41, 0, 0, &buf, 6, 2000); #else - return -EINVAL; + return -ENOTTY; #endif } -- GitLab From 7546dd97d27306d939c13e03318aae695badaa88 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 9 Mar 2009 08:18:29 +0000 Subject: [PATCH 3017/4982] net: convert usage of packet_type to read_mostly Protocols that use packet_type can be __read_mostly section for better locality. Elminate any unnecessary initializations of NULL. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/block/aoe/aoenet.c | 2 +- drivers/net/hamradio/bpqether.c | 2 +- drivers/net/pppoe.c | 6 +++--- drivers/net/wan/hdlc.c | 2 +- drivers/net/wan/lapbether.c | 2 +- net/8021q/vlan.c | 2 +- net/appletalk/ddp.c | 4 ++-- net/ax25/af_ax25.c | 3 +-- net/decnet/af_decnet.c | 3 +-- net/dsa/tag_dsa.c | 2 +- net/dsa/tag_edsa.c | 2 +- net/dsa/tag_trailer.c | 2 +- net/econet/af_econet.c | 2 +- net/ipv4/af_inet.c | 2 +- net/ipv4/arp.c | 2 +- net/ipv6/af_inet6.c | 2 +- net/ipx/af_ipx.c | 4 ++-- net/irda/irmod.c | 2 +- net/llc/llc_core.c | 4 ++-- net/phonet/af_phonet.c | 3 +-- net/x25/af_x25.c | 2 +- 21 files changed, 26 insertions(+), 29 deletions(-) diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c index c6099ba9a4b..ce0d62cd71b 100644 --- a/drivers/block/aoe/aoenet.c +++ b/drivers/block/aoe/aoenet.c @@ -151,7 +151,7 @@ exit: return 0; } -static struct packet_type aoe_pt = { +static struct packet_type aoe_pt __read_mostly = { .type = __constant_htons(ETH_P_AOE), .func = aoenet_rcv, }; diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index 44b183b58f5..d509b371a56 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c @@ -97,7 +97,7 @@ static char bpq_eth_addr[6]; static int bpq_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *); static int bpq_device_event(struct notifier_block *, unsigned long, void *); -static struct packet_type bpq_packet_type = { +static struct packet_type bpq_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_BPQ), .func = bpq_rcv, }; diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index e2968f08443..f0031f1f97e 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -513,17 +513,17 @@ out: return NET_RX_SUCCESS; /* Lies... :-) */ } -static struct packet_type pppoes_ptype = { +static struct packet_type pppoes_ptype __read_mostly = { .type = cpu_to_be16(ETH_P_PPP_SES), .func = pppoe_rcv, }; -static struct packet_type pppoed_ptype = { +static struct packet_type pppoed_ptype __read_mostly = { .type = cpu_to_be16(ETH_P_PPP_DISC), .func = pppoe_disc_rcv, }; -static struct proto pppoe_sk_proto = { +static struct proto pppoe_sk_proto __read_mostly = { .name = "PPPOE", .owner = THIS_MODULE, .obj_size = sizeof(struct pppox_sock), diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c index 5ce43720555..7596eae1b35 100644 --- a/drivers/net/wan/hdlc.c +++ b/drivers/net/wan/hdlc.c @@ -348,7 +348,7 @@ EXPORT_SYMBOL(unregister_hdlc_protocol); EXPORT_SYMBOL(attach_hdlc_protocol); EXPORT_SYMBOL(detach_hdlc_protocol); -static struct packet_type hdlc_packet_type = { +static struct packet_type hdlc_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_HDLC), .func = hdlc_rcv, }; diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c index 96d9eda4089..f85ca1b27f9 100644 --- a/drivers/net/wan/lapbether.c +++ b/drivers/net/wan/lapbether.c @@ -421,7 +421,7 @@ static int lapbeth_device_event(struct notifier_block *this, /* ------------------------------------------------------------------------ */ -static struct packet_type lapbeth_packet_type = { +static struct packet_type lapbeth_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_DEC), .func = lapbeth_rcv, }; diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 4163ea65bf4..2b7390e377b 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -51,7 +51,7 @@ const char vlan_version[] = DRV_VERSION; static const char vlan_copyright[] = "Ben Greear "; static const char vlan_buggyright[] = "David S. Miller "; -static struct packet_type vlan_packet_type = { +static struct packet_type vlan_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_8021Q), .func = vlan_skb_recv, /* VLAN receive method */ }; diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index cf05c43cba5..3e0671df3a3 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -1860,12 +1860,12 @@ static struct notifier_block ddp_notifier = { .notifier_call = ddp_device_event, }; -static struct packet_type ltalk_packet_type = { +static struct packet_type ltalk_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_LOCALTALK), .func = ltalk_rcv, }; -static struct packet_type ppptalk_packet_type = { +static struct packet_type ppptalk_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_PPPTALK), .func = atalk_rcv, }; diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index d127fd3ba5c..8f8f63ff656 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1985,9 +1985,8 @@ static const struct proto_ops ax25_proto_ops = { /* * Called by socket.c on kernel start up */ -static struct packet_type ax25_packet_type = { +static struct packet_type ax25_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_AX25), - .dev = NULL, /* All devices */ .func = ax25_kiss_rcv, }; diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index ec233b64f85..9647d911f91 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -2112,9 +2112,8 @@ static struct notifier_block dn_dev_notifier = { extern int dn_route_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *); -static struct packet_type dn_dix_packet_type = { +static struct packet_type dn_dix_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_DNA_RT), - .dev = NULL, /* All devices */ .func = dn_route_rcv, }; diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c index 63e532a69fd..0b8a91ddff4 100644 --- a/net/dsa/tag_dsa.c +++ b/net/dsa/tag_dsa.c @@ -175,7 +175,7 @@ out: return 0; } -static struct packet_type dsa_packet_type = { +static struct packet_type dsa_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_DSA), .func = dsa_rcv, }; diff --git a/net/dsa/tag_edsa.c b/net/dsa/tag_edsa.c index 6197f9a7ef4..16fcb6d196d 100644 --- a/net/dsa/tag_edsa.c +++ b/net/dsa/tag_edsa.c @@ -194,7 +194,7 @@ out: return 0; } -static struct packet_type edsa_packet_type = { +static struct packet_type edsa_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_EDSA), .func = edsa_rcv, }; diff --git a/net/dsa/tag_trailer.c b/net/dsa/tag_trailer.c index d7e7f424ff0..a6d959da678 100644 --- a/net/dsa/tag_trailer.c +++ b/net/dsa/tag_trailer.c @@ -111,7 +111,7 @@ out: return 0; } -static struct packet_type trailer_packet_type = { +static struct packet_type trailer_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_TRAILER), .func = trailer_rcv, }; diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index 7bf35582f65..6f479fa522c 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c @@ -1102,7 +1102,7 @@ drop: return NET_RX_DROP; } -static struct packet_type econet_packet_type = { +static struct packet_type econet_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_ECONET), .func = econet_rcv, }; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 627be4dc7fb..d5aaabbb7cb 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1500,7 +1500,7 @@ static int ipv4_proc_init(void); * IP protocol layer initialiser */ -static struct packet_type ip_packet_type = { +static struct packet_type ip_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_IP), .func = ip_rcv, .gso_send_check = inet_gso_send_check, diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 3f6b7354699..3d67d1ffed7 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -1225,7 +1225,7 @@ void arp_ifdown(struct net_device *dev) * Called once on startup. */ -static struct packet_type arp_packet_type = { +static struct packet_type arp_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_ARP), .func = arp_rcv, }; diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 57b07da1212..3e2ddfaee81 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -893,7 +893,7 @@ out_unlock: return err; } -static struct packet_type ipv6_packet_type = { +static struct packet_type ipv6_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_IPV6), .func = ipv6_rcv, .gso_send_check = ipv6_gso_send_check, diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 43d0ffc6d56..30bd322b798 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -1958,12 +1958,12 @@ static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = { SOCKOPS_WRAP(ipx_dgram, PF_IPX); -static struct packet_type ipx_8023_packet_type = { +static struct packet_type ipx_8023_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_802_3), .func = ipx_rcv, }; -static struct packet_type ipx_dix_packet_type = { +static struct packet_type ipx_dix_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_IPX), .func = ipx_rcv, }; diff --git a/net/irda/irmod.c b/net/irda/irmod.c index 1bb607f2f5c..303a68d9273 100644 --- a/net/irda/irmod.c +++ b/net/irda/irmod.c @@ -55,7 +55,7 @@ EXPORT_SYMBOL(irda_debug); /* Packet type handler. * Tell the kernel how IrDA packets should be handled. */ -static struct packet_type irda_packet_type = { +static struct packet_type irda_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_IRDA), .func = irlap_driver_rcv, /* Packet type handler irlap_frame.c */ }; diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c index a7fe1adc378..ff4c0ab96a6 100644 --- a/net/llc/llc_core.c +++ b/net/llc/llc_core.c @@ -147,12 +147,12 @@ void llc_sap_close(struct llc_sap *sap) kfree(sap); } -static struct packet_type llc_packet_type = { +static struct packet_type llc_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_802_2), .func = llc_rcv, }; -static struct packet_type llc_tr_packet_type = { +static struct packet_type llc_tr_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_TR_802_2), .func = llc_rcv, }; diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index 81795ea8779..a662e62a99c 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c @@ -382,9 +382,8 @@ out: return NET_RX_DROP; } -static struct packet_type phonet_packet_type = { +static struct packet_type phonet_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_PHONET), - .dev = NULL, .func = phonet_rcv, }; diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 8f76f4009c2..1000e9a26fd 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -1608,7 +1608,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { SOCKOPS_WRAP(x25_proto, AF_X25); -static struct packet_type x25_packet_type = { +static struct packet_type x25_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_X25), .func = x25_lapb_receive_frame, }; -- GitLab From a2205472c3017bfe97b6cb6f5acd6ca141a97eda Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 9 Mar 2009 13:51:55 +0000 Subject: [PATCH 3018/4982] net: fix warning about non-const string Since dev_set_name takes a printf style string, new gcc complains if arg is not const. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/core/net-sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 484f58750eb..2da59a0ac4a 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -498,7 +498,7 @@ int netdev_register_kobject(struct net_device *net) dev->groups = groups; BUILD_BUG_ON(BUS_ID_SIZE < IFNAMSIZ); - dev_set_name(dev, net->name); + dev_set_name(dev, "%s", net->name); #ifdef CONFIG_SYSFS *groups++ = &netstat_group; -- GitLab From 8ed1454aa8ab6c616f9c457238c6397c0529ceb9 Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Thu, 5 Mar 2009 08:01:49 +0000 Subject: [PATCH 3019/4982] forcedeth: fix stats version feature Newer versions of the stats feature would not encompass all older versions. This would result in only retreiving a subset of all available stats in HW. Signed-off-by: Ayaz Abdulla Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index e3b7305e8b8..abe3306855f 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -87,8 +87,8 @@ #define DEV_HAS_MSI_X 0x000080 /* device supports MSI-X */ #define DEV_HAS_POWER_CNTRL 0x000100 /* device supports power savings */ #define DEV_HAS_STATISTICS_V1 0x000200 /* device supports hw statistics version 1 */ -#define DEV_HAS_STATISTICS_V2 0x000400 /* device supports hw statistics version 2 */ -#define DEV_HAS_STATISTICS_V3 0x000800 /* device supports hw statistics version 3 */ +#define DEV_HAS_STATISTICS_V2 0x000600 /* device supports hw statistics version 2 */ +#define DEV_HAS_STATISTICS_V3 0x000e00 /* device supports hw statistics version 3 */ #define DEV_HAS_TEST_EXTENDED 0x001000 /* device supports extended diagnostic test */ #define DEV_HAS_MGMT_UNIT 0x002000 /* device supports management unit */ #define DEV_HAS_CORRECT_MACADDR 0x004000 /* device supports correct mac address order */ @@ -4796,12 +4796,12 @@ static int nv_get_sset_count(struct net_device *dev, int sset) else return NV_TEST_COUNT_BASE; case ETH_SS_STATS: - if (np->driver_data & DEV_HAS_STATISTICS_V1) - return NV_DEV_STATISTICS_V1_COUNT; + if (np->driver_data & DEV_HAS_STATISTICS_V3) + return NV_DEV_STATISTICS_V3_COUNT; else if (np->driver_data & DEV_HAS_STATISTICS_V2) return NV_DEV_STATISTICS_V2_COUNT; - else if (np->driver_data & DEV_HAS_STATISTICS_V3) - return NV_DEV_STATISTICS_V3_COUNT; + else if (np->driver_data & DEV_HAS_STATISTICS_V1) + return NV_DEV_STATISTICS_V1_COUNT; else return 0; default: -- GitLab From 08d935757440872d46be77f95153972cdbfe550d Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Thu, 5 Mar 2009 08:01:55 +0000 Subject: [PATCH 3020/4982] forcedeth: fix missing napi enable/disable calls This patch adds missing napi enable/disable calls. Signed-off-by: Ayaz Abdulla Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index abe3306855f..5346410aeb6 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -1069,6 +1069,24 @@ static void nv_disable_hw_interrupts(struct net_device *dev, u32 mask) } } +static void nv_napi_enable(struct net_device *dev) +{ +#ifdef CONFIG_FORCEDETH_NAPI + struct fe_priv *np = get_nvpriv(dev); + + napi_enable(&np->napi); +#endif +} + +static void nv_napi_disable(struct net_device *dev) +{ +#ifdef CONFIG_FORCEDETH_NAPI + struct fe_priv *np = get_nvpriv(dev); + + napi_disable(&np->napi); +#endif +} + #define MII_READ (-1) /* mii_rw: read/write a register on the PHY. * @@ -2924,6 +2942,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu) * Changing the MTU is a rare event, it shouldn't matter. */ nv_disable_irq(dev); + nv_napi_disable(dev); netif_tx_lock_bh(dev); netif_addr_lock(dev); spin_lock(&np->lock); @@ -2952,6 +2971,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu) spin_unlock(&np->lock); netif_addr_unlock(dev); netif_tx_unlock_bh(dev); + nv_napi_enable(dev); nv_enable_irq(dev); } return 0; @@ -4592,6 +4612,7 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri if (netif_running(dev)) { nv_disable_irq(dev); + nv_napi_disable(dev); netif_tx_lock_bh(dev); netif_addr_lock(dev); spin_lock(&np->lock); @@ -4644,6 +4665,7 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri spin_unlock(&np->lock); netif_addr_unlock(dev); netif_tx_unlock_bh(dev); + nv_napi_enable(dev); nv_enable_irq(dev); } return 0; @@ -5070,9 +5092,7 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64 if (test->flags & ETH_TEST_FL_OFFLINE) { if (netif_running(dev)) { netif_stop_queue(dev); -#ifdef CONFIG_FORCEDETH_NAPI - napi_disable(&np->napi); -#endif + nv_napi_disable(dev); netif_tx_lock_bh(dev); netif_addr_lock(dev); spin_lock_irq(&np->lock); @@ -5130,9 +5150,7 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64 /* restart rx engine */ nv_start_rxtx(dev); netif_start_queue(dev); -#ifdef CONFIG_FORCEDETH_NAPI - napi_enable(&np->napi); -#endif + nv_napi_enable(dev); nv_enable_hw_interrupts(dev, np->irqmask); } } @@ -5424,9 +5442,7 @@ static int nv_open(struct net_device *dev) ret = nv_update_linkspeed(dev); nv_start_rxtx(dev); netif_start_queue(dev); -#ifdef CONFIG_FORCEDETH_NAPI - napi_enable(&np->napi); -#endif + nv_napi_enable(dev); if (ret) { netif_carrier_on(dev); @@ -5458,9 +5474,7 @@ static int nv_close(struct net_device *dev) spin_lock_irq(&np->lock); np->in_shutdown = 1; spin_unlock_irq(&np->lock); -#ifdef CONFIG_FORCEDETH_NAPI - napi_disable(&np->napi); -#endif + nv_napi_disable(dev); synchronize_irq(np->pci_dev->irq); del_timer_sync(&np->oom_kick); -- GitLab From d41c628c514bceb33037c26f83585c629594bed5 Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Thu, 5 Mar 2009 08:01:59 +0000 Subject: [PATCH 3021/4982] forcedeth: remove msix + napi This patch removes support for msix running in conjunction with napi. There has been reported issues regarding the behaviour of irqmask and generation of interrupts by the HW when in MSIX mode. When running napi, the driver is constantly turning off/on the irqmask. For the time being, I am going to disable it until I can root cause the issue. Signed-off-by: Ayaz Abdulla Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 5346410aeb6..a4f2f146ae6 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -3731,26 +3731,6 @@ static int nv_napi_poll(struct napi_struct *napi, int budget) } #endif -#ifdef CONFIG_FORCEDETH_NAPI -static irqreturn_t nv_nic_irq_rx(int foo, void *data) -{ - struct net_device *dev = (struct net_device *) data; - struct fe_priv *np = netdev_priv(dev); - u8 __iomem *base = get_hwbase(dev); - u32 events; - - events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_RX_ALL; - - if (events) { - /* disable receive interrupts on the nic */ - writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); - pci_push(base); - writel(NVREG_IRQ_RX_ALL, base + NvRegMSIXIrqStatus); - napi_schedule(&np->napi); - } - return IRQ_HANDLED; -} -#else static irqreturn_t nv_nic_irq_rx(int foo, void *data) { struct net_device *dev = (struct net_device *) data; @@ -3797,7 +3777,6 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data) return IRQ_RETVAL(i); } -#endif static irqreturn_t nv_nic_irq_other(int foo, void *data) { @@ -5670,7 +5649,12 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i np->msi_flags |= NV_MSI_CAPABLE; } if ((id->driver_data & DEV_HAS_MSI_X) && msix) { + /* msix has had reported issues when modifying irqmask + as in the case of napi, therefore, disable for now + */ +#ifndef CONFIG_FORCEDETH_NAPI np->msi_flags |= NV_MSI_X_CAPABLE; +#endif } np->pause_flags = NV_PAUSEFRAME_RX_CAPABLE | NV_PAUSEFRAME_RX_REQ | NV_PAUSEFRAME_AUTONEG; -- GitLab From 582806be066bd35dc5d2739b090b561a5efd787a Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Thu, 5 Mar 2009 08:02:03 +0000 Subject: [PATCH 3022/4982] forcedeth: save irq events for napi processing This patch will save the irq events in the driver's context so that the napi routine knows which interrupts have occurred. Subsequent changes will be moving all interrupt processing into the napi poll routine. Signed-off-by: Ayaz Abdulla Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 47 ++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index a4f2f146ae6..37cd23fb9e4 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -759,6 +759,7 @@ struct fe_priv { dma_addr_t ring_addr; struct pci_dev *pci_dev; u32 orig_mac[2]; + u32 events; u32 irqmask; u32 desc_ver; u32 txrxctl_bits; @@ -3417,21 +3418,20 @@ static irqreturn_t nv_nic_irq(int foo, void *data) struct net_device *dev = (struct net_device *) data; struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); - u32 events; int i; dprintk(KERN_DEBUG "%s: nv_nic_irq\n", dev->name); for (i=0; ; i++) { if (!(np->msi_flags & NV_MSI_X_ENABLED)) { - events = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK; + np->events = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK; writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); } else { - events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK; + np->events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK; writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus); } - dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events); - if (!(events & np->irqmask)) + dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, np->events); + if (!(np->events & np->irqmask)) break; nv_msi_workaround(np); @@ -3441,7 +3441,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data) spin_unlock(&np->lock); #ifdef CONFIG_FORCEDETH_NAPI - if (events & NVREG_IRQ_RX_ALL) { + if (np->events & NVREG_IRQ_RX_ALL) { spin_lock(&np->lock); napi_schedule(&np->napi); @@ -3464,7 +3464,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data) } } #endif - if (unlikely(events & NVREG_IRQ_LINK)) { + if (unlikely(np->events & NVREG_IRQ_LINK)) { spin_lock(&np->lock); nv_link_irq(dev); spin_unlock(&np->lock); @@ -3475,15 +3475,15 @@ static irqreturn_t nv_nic_irq(int foo, void *data) spin_unlock(&np->lock); np->link_timeout = jiffies + LINK_TIMEOUT; } - if (unlikely(events & (NVREG_IRQ_TX_ERR))) { + if (unlikely(np->events & (NVREG_IRQ_TX_ERR))) { dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n", - dev->name, events); + dev->name, np->events); } - if (unlikely(events & (NVREG_IRQ_UNKNOWN))) { + if (unlikely(np->events & (NVREG_IRQ_UNKNOWN))) { printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n", - dev->name, events); + dev->name, np->events); } - if (unlikely(events & NVREG_IRQ_RECOVER_ERROR)) { + if (unlikely(np->events & NVREG_IRQ_RECOVER_ERROR)) { spin_lock(&np->lock); /* disable interrupts on the nic */ if (!(np->msi_flags & NV_MSI_X_ENABLED)) @@ -3534,21 +3534,20 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) struct net_device *dev = (struct net_device *) data; struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); - u32 events; int i; dprintk(KERN_DEBUG "%s: nv_nic_irq_optimized\n", dev->name); for (i=0; ; i++) { if (!(np->msi_flags & NV_MSI_X_ENABLED)) { - events = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK; + np->events = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK; writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); } else { - events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK; + np->events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK; writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus); } - dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events); - if (!(events & np->irqmask)) + dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, np->events); + if (!(np->events & np->irqmask)) break; nv_msi_workaround(np); @@ -3558,7 +3557,7 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) spin_unlock(&np->lock); #ifdef CONFIG_FORCEDETH_NAPI - if (events & NVREG_IRQ_RX_ALL) { + if (np->events & NVREG_IRQ_RX_ALL) { spin_lock(&np->lock); napi_schedule(&np->napi); @@ -3581,7 +3580,7 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) } } #endif - if (unlikely(events & NVREG_IRQ_LINK)) { + if (unlikely(np->events & NVREG_IRQ_LINK)) { spin_lock(&np->lock); nv_link_irq(dev); spin_unlock(&np->lock); @@ -3592,15 +3591,15 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) spin_unlock(&np->lock); np->link_timeout = jiffies + LINK_TIMEOUT; } - if (unlikely(events & (NVREG_IRQ_TX_ERR))) { + if (unlikely(np->events & (NVREG_IRQ_TX_ERR))) { dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n", - dev->name, events); + dev->name, np->events); } - if (unlikely(events & (NVREG_IRQ_UNKNOWN))) { + if (unlikely(np->events & (NVREG_IRQ_UNKNOWN))) { printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n", - dev->name, events); + dev->name, np->events); } - if (unlikely(events & NVREG_IRQ_RECOVER_ERROR)) { + if (unlikely(np->events & NVREG_IRQ_RECOVER_ERROR)) { spin_lock(&np->lock); /* disable interrupts on the nic */ if (!(np->msi_flags & NV_MSI_X_ENABLED)) -- GitLab From 2daac3e8f831beba2012fdefda17770456be9b7e Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Thu, 5 Mar 2009 08:02:06 +0000 Subject: [PATCH 3023/4982] forcedeth: remove overhead This patch removes unnecessary overhead code. Firstly, there is no nead to mask off unwanted interrupts as we will be checking against the irqmask field anyways. Secondly, there has been no value in last few years from detecting error or unknown interrupts. Signed-off-by: Ayaz Abdulla Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 36 ++++-------------------------------- 1 file changed, 4 insertions(+), 32 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 37cd23fb9e4..74511f7e13e 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -120,10 +120,6 @@ enum { #define NVREG_IRQ_RX_ALL (NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_RX_FORCED) #define NVREG_IRQ_OTHER (NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_RECOVER_ERROR) -#define NVREG_IRQ_UNKNOWN (~(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR| \ - NVREG_IRQ_TX_OK|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_RX_FORCED| \ - NVREG_IRQ_TX_FORCED|NVREG_IRQ_RECOVER_ERROR)) - NvRegUnknownSetupReg6 = 0x008, #define NVREG_UNKSETUP6_VAL 3 @@ -3424,10 +3420,10 @@ static irqreturn_t nv_nic_irq(int foo, void *data) for (i=0; ; i++) { if (!(np->msi_flags & NV_MSI_X_ENABLED)) { - np->events = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK; + np->events = readl(base + NvRegIrqStatus); writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); } else { - np->events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK; + np->events = readl(base + NvRegMSIXIrqStatus); writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus); } dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, np->events); @@ -3475,14 +3471,6 @@ static irqreturn_t nv_nic_irq(int foo, void *data) spin_unlock(&np->lock); np->link_timeout = jiffies + LINK_TIMEOUT; } - if (unlikely(np->events & (NVREG_IRQ_TX_ERR))) { - dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n", - dev->name, np->events); - } - if (unlikely(np->events & (NVREG_IRQ_UNKNOWN))) { - printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n", - dev->name, np->events); - } if (unlikely(np->events & NVREG_IRQ_RECOVER_ERROR)) { spin_lock(&np->lock); /* disable interrupts on the nic */ @@ -3540,10 +3528,10 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) for (i=0; ; i++) { if (!(np->msi_flags & NV_MSI_X_ENABLED)) { - np->events = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK; + np->events = readl(base + NvRegIrqStatus); writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); } else { - np->events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK; + np->events = readl(base + NvRegMSIXIrqStatus); writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus); } dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, np->events); @@ -3591,14 +3579,6 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) spin_unlock(&np->lock); np->link_timeout = jiffies + LINK_TIMEOUT; } - if (unlikely(np->events & (NVREG_IRQ_TX_ERR))) { - dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n", - dev->name, np->events); - } - if (unlikely(np->events & (NVREG_IRQ_UNKNOWN))) { - printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n", - dev->name, np->events); - } if (unlikely(np->events & NVREG_IRQ_RECOVER_ERROR)) { spin_lock(&np->lock); /* disable interrupts on the nic */ @@ -3663,10 +3643,6 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data) nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); spin_unlock_irqrestore(&np->lock, flags); - if (unlikely(events & (NVREG_IRQ_TX_ERR))) { - dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n", - dev->name, events); - } if (unlikely(i > max_interrupt_work)) { spin_lock_irqsave(&np->lock, flags); /* disable interrupts on the nic */ @@ -3825,10 +3801,6 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data) spin_unlock_irq(&np->lock); break; } - if (events & (NVREG_IRQ_UNKNOWN)) { - printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n", - dev->name, events); - } if (unlikely(i > max_interrupt_work)) { spin_lock_irqsave(&np->lock, flags); /* disable interrupts on the nic */ -- GitLab From 33912e72d00c3627dbbb7c59463df9535176059f Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Thu, 5 Mar 2009 08:02:10 +0000 Subject: [PATCH 3024/4982] forcedeth: add/modify tx done with limit There are two tx_done routines to handle tx completion processing. Both these functions now take in a limit value and return the amount of tx completions. This will be used by a future patch to determine the total amount of work done. Signed-off-by: Ayaz Abdulla Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 74511f7e13e..78c2fe18528 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -2397,14 +2397,16 @@ static inline void nv_tx_flip_ownership(struct net_device *dev) * * Caller must own np->lock. */ -static void nv_tx_done(struct net_device *dev) +static int nv_tx_done(struct net_device *dev, int limit) { struct fe_priv *np = netdev_priv(dev); u32 flags; + int tx_work = 0; struct ring_desc* orig_get_tx = np->get_tx.orig; while ((np->get_tx.orig != np->put_tx.orig) && - !((flags = le32_to_cpu(np->get_tx.orig->flaglen)) & NV_TX_VALID)) { + !((flags = le32_to_cpu(np->get_tx.orig->flaglen)) & NV_TX_VALID) && + (tx_work < limit)) { dprintk(KERN_DEBUG "%s: nv_tx_done: flags 0x%x.\n", dev->name, flags); @@ -2430,6 +2432,7 @@ static void nv_tx_done(struct net_device *dev) } dev_kfree_skb_any(np->get_tx_ctx->skb); np->get_tx_ctx->skb = NULL; + tx_work++; } } else { if (flags & NV_TX2_LASTPACKET) { @@ -2447,6 +2450,7 @@ static void nv_tx_done(struct net_device *dev) } dev_kfree_skb_any(np->get_tx_ctx->skb); np->get_tx_ctx->skb = NULL; + tx_work++; } } if (unlikely(np->get_tx.orig++ == np->last_tx.orig)) @@ -2458,17 +2462,19 @@ static void nv_tx_done(struct net_device *dev) np->tx_stop = 0; netif_wake_queue(dev); } + return tx_work; } -static void nv_tx_done_optimized(struct net_device *dev, int limit) +static int nv_tx_done_optimized(struct net_device *dev, int limit) { struct fe_priv *np = netdev_priv(dev); u32 flags; + int tx_work = 0; struct ring_desc_ex* orig_get_tx = np->get_tx.ex; while ((np->get_tx.ex != np->put_tx.ex) && !((flags = le32_to_cpu(np->get_tx.ex->flaglen)) & NV_TX_VALID) && - (limit-- > 0)) { + (tx_work < limit)) { dprintk(KERN_DEBUG "%s: nv_tx_done_optimized: flags 0x%x.\n", dev->name, flags); @@ -2492,6 +2498,7 @@ static void nv_tx_done_optimized(struct net_device *dev, int limit) dev_kfree_skb_any(np->get_tx_ctx->skb); np->get_tx_ctx->skb = NULL; + tx_work++; if (np->tx_limit) { nv_tx_flip_ownership(dev); @@ -2506,6 +2513,7 @@ static void nv_tx_done_optimized(struct net_device *dev, int limit) np->tx_stop = 0; netif_wake_queue(dev); } + return tx_work; } /* @@ -2578,7 +2586,7 @@ static void nv_tx_timeout(struct net_device *dev) /* 2) check that the packets were not sent already: */ if (!nv_optimized(np)) - nv_tx_done(dev); + nv_tx_done(dev, np->tx_ring_size); else nv_tx_done_optimized(dev, np->tx_ring_size); @@ -3433,7 +3441,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data) nv_msi_workaround(np); spin_lock(&np->lock); - nv_tx_done(dev); + nv_tx_done(dev, np->tx_ring_size); spin_unlock(&np->lock); #ifdef CONFIG_FORCEDETH_NAPI -- GitLab From f27e6f39fc37f378f5485b9a0ff905796e789f80 Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Thu, 5 Mar 2009 08:02:14 +0000 Subject: [PATCH 3025/4982] forcedeth: napi - handle all processing The napi poll routine has been modified to handle all interrupt events and process them accordingly. Therefore, the ISR will now only schedule the napi poll and disable all interrupts instead of just disabling rx interrupt. Signed-off-by: Ayaz Abdulla Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 98 +++++++++++++++++++++++++---------------- 1 file changed, 60 insertions(+), 38 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 78c2fe18528..6b6765431ea 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -3440,25 +3440,22 @@ static irqreturn_t nv_nic_irq(int foo, void *data) nv_msi_workaround(np); +#ifdef CONFIG_FORCEDETH_NAPI spin_lock(&np->lock); - nv_tx_done(dev, np->tx_ring_size); - spin_unlock(&np->lock); + napi_schedule(&np->napi); -#ifdef CONFIG_FORCEDETH_NAPI - if (np->events & NVREG_IRQ_RX_ALL) { - spin_lock(&np->lock); - napi_schedule(&np->napi); + /* Disable furthur irq's + (msix not enabled with napi) */ + writel(0, base + NvRegIrqMask); - /* Disable furthur receive irq's */ - np->irqmask &= ~NVREG_IRQ_RX_ALL; + spin_unlock(&np->lock); - if (np->msi_flags & NV_MSI_X_ENABLED) - writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); - else - writel(np->irqmask, base + NvRegIrqMask); - spin_unlock(&np->lock); - } + return IRQ_HANDLED; #else + spin_lock(&np->lock); + nv_tx_done(dev, np->tx_ring_size); + spin_unlock(&np->lock); + if (nv_rx_process(dev, RX_WORK_PER_LOOP)) { if (unlikely(nv_alloc_rx(dev))) { spin_lock(&np->lock); @@ -3467,7 +3464,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data) spin_unlock(&np->lock); } } -#endif + if (unlikely(np->events & NVREG_IRQ_LINK)) { spin_lock(&np->lock); nv_link_irq(dev); @@ -3513,7 +3510,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data) printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq.\n", dev->name, i); break; } - +#endif } dprintk(KERN_DEBUG "%s: nv_nic_irq completed\n", dev->name); @@ -3548,25 +3545,22 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) nv_msi_workaround(np); +#ifdef CONFIG_FORCEDETH_NAPI spin_lock(&np->lock); - nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); - spin_unlock(&np->lock); + napi_schedule(&np->napi); -#ifdef CONFIG_FORCEDETH_NAPI - if (np->events & NVREG_IRQ_RX_ALL) { - spin_lock(&np->lock); - napi_schedule(&np->napi); + /* Disable furthur irq's + (msix not enabled with napi) */ + writel(0, base + NvRegIrqMask); - /* Disable furthur receive irq's */ - np->irqmask &= ~NVREG_IRQ_RX_ALL; + spin_unlock(&np->lock); - if (np->msi_flags & NV_MSI_X_ENABLED) - writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); - else - writel(np->irqmask, base + NvRegIrqMask); - spin_unlock(&np->lock); - } + return IRQ_HANDLED; #else + spin_lock(&np->lock); + nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); + spin_unlock(&np->lock); + if (nv_rx_process_optimized(dev, RX_WORK_PER_LOOP)) { if (unlikely(nv_alloc_rx_optimized(dev))) { spin_lock(&np->lock); @@ -3575,7 +3569,7 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) spin_unlock(&np->lock); } } -#endif + if (unlikely(np->events & NVREG_IRQ_LINK)) { spin_lock(&np->lock); nv_link_irq(dev); @@ -3622,7 +3616,7 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq.\n", dev->name, i); break; } - +#endif } dprintk(KERN_DEBUG "%s: nv_nic_irq_optimized completed\n", dev->name); @@ -3682,9 +3676,17 @@ static int nv_napi_poll(struct napi_struct *napi, int budget) int pkts, retcode; if (!nv_optimized(np)) { + spin_lock_irqsave(&np->lock, flags); + nv_tx_done(dev, np->tx_ring_size); + spin_unlock_irqrestore(&np->lock, flags); + pkts = nv_rx_process(dev, budget); retcode = nv_alloc_rx(dev); } else { + spin_lock_irqsave(&np->lock, flags); + nv_tx_done_optimized(dev, np->tx_ring_size); + spin_unlock_irqrestore(&np->lock, flags); + pkts = nv_rx_process_optimized(dev, budget); retcode = nv_alloc_rx_optimized(dev); } @@ -3696,17 +3698,37 @@ static int nv_napi_poll(struct napi_struct *napi, int budget) spin_unlock_irqrestore(&np->lock, flags); } + if (unlikely(np->events & NVREG_IRQ_LINK)) { + spin_lock_irqsave(&np->lock, flags); + nv_link_irq(dev); + spin_unlock_irqrestore(&np->lock, flags); + } + if (unlikely(np->need_linktimer && time_after(jiffies, np->link_timeout))) { + spin_lock_irqsave(&np->lock, flags); + nv_linkchange(dev); + spin_unlock_irqrestore(&np->lock, flags); + np->link_timeout = jiffies + LINK_TIMEOUT; + } + if (unlikely(np->events & NVREG_IRQ_RECOVER_ERROR)) { + spin_lock_irqsave(&np->lock, flags); + if (!np->in_shutdown) { + np->nic_poll_irq = np->irqmask; + np->recover_error = 1; + mod_timer(&np->nic_poll, jiffies + POLL_WAIT); + } + spin_unlock_irqrestore(&np->lock, flags); + __napi_complete(napi); + return pkts; + } + if (pkts < budget) { - /* re-enable receive interrupts */ + /* re-enable interrupts + (msix not enabled in napi) */ spin_lock_irqsave(&np->lock, flags); __napi_complete(napi); - np->irqmask |= NVREG_IRQ_RX_ALL; - if (np->msi_flags & NV_MSI_X_ENABLED) - writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); - else - writel(np->irqmask, base + NvRegIrqMask); + writel(np->irqmask, base + NvRegIrqMask); spin_unlock_irqrestore(&np->lock, flags); } -- GitLab From 9e184767c956e71d9535c9fc8433e140f819d07d Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Thu, 5 Mar 2009 08:02:18 +0000 Subject: [PATCH 3026/4982] forcedeth: add new optimization mode A new optimization mode called Dynamic has been added. This will be mode where interrupt moderation logic will dynamically switch between pure throughput mode and poll based (called 'cpu') mode. Also, for newer chipsets, the timer irq is not needed for throughput mode. Secondly, since we are modifying the irqmask to change between modes, msix is not supported. Signed-off-by: Ayaz Abdulla Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 105 ++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 48 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 6b6765431ea..07e245dab68 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -842,9 +842,10 @@ static int max_interrupt_work = 15; */ enum { NV_OPTIMIZATION_MODE_THROUGHPUT, - NV_OPTIMIZATION_MODE_CPU + NV_OPTIMIZATION_MODE_CPU, + NV_OPTIMIZATION_MODE_DYNAMIC }; -static int optimization_mode = NV_OPTIMIZATION_MODE_THROUGHPUT; +static int optimization_mode = NV_OPTIMIZATION_MODE_DYNAMIC; /* * Poll interval for timer irq @@ -5645,19 +5646,6 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX; } - np->msi_flags = 0; - if ((id->driver_data & DEV_HAS_MSI) && msi) { - np->msi_flags |= NV_MSI_CAPABLE; - } - if ((id->driver_data & DEV_HAS_MSI_X) && msix) { - /* msix has had reported issues when modifying irqmask - as in the case of napi, therefore, disable for now - */ -#ifndef CONFIG_FORCEDETH_NAPI - np->msi_flags |= NV_MSI_X_CAPABLE; -#endif - } - np->pause_flags = NV_PAUSEFRAME_RX_CAPABLE | NV_PAUSEFRAME_RX_REQ | NV_PAUSEFRAME_AUTONEG; if ((id->driver_data & DEV_HAS_PAUSEFRAME_TX_V1) || (id->driver_data & DEV_HAS_PAUSEFRAME_TX_V2) || @@ -5802,14 +5790,35 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i } else { np->tx_flags = NV_TX2_VALID; } - if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT) { - np->irqmask = NVREG_IRQMASK_THROUGHPUT; - if (np->msi_flags & NV_MSI_X_CAPABLE) /* set number of vectors */ - np->msi_flags |= 0x0003; - } else { + + np->msi_flags = 0; + if ((id->driver_data & DEV_HAS_MSI) && msi) { + np->msi_flags |= NV_MSI_CAPABLE; + } + if ((id->driver_data & DEV_HAS_MSI_X) && msix) { + /* msix has had reported issues when modifying irqmask + as in the case of napi, therefore, disable for now + */ +#ifndef CONFIG_FORCEDETH_NAPI + np->msi_flags |= NV_MSI_X_CAPABLE; +#endif + } + + if (optimization_mode == NV_OPTIMIZATION_MODE_CPU) { np->irqmask = NVREG_IRQMASK_CPU; if (np->msi_flags & NV_MSI_X_CAPABLE) /* set number of vectors */ np->msi_flags |= 0x0001; + } else if (optimization_mode == NV_OPTIMIZATION_MODE_DYNAMIC && + !(id->driver_data & DEV_NEED_TIMERIRQ)) { + /* start off in throughput mode */ + np->irqmask = NVREG_IRQMASK_THROUGHPUT; + /* remove support for msix mode */ + np->msi_flags &= ~NV_MSI_X_CAPABLE; + } else { + optimization_mode = NV_OPTIMIZATION_MODE_THROUGHPUT; + np->irqmask = NVREG_IRQMASK_THROUGHPUT; + if (np->msi_flags & NV_MSI_X_CAPABLE) /* set number of vectors */ + np->msi_flags |= 0x0003; } if (id->driver_data & DEV_NEED_TIMERIRQ) @@ -6166,19 +6175,19 @@ static struct pci_device_id pci_tbl[] = { }, { /* MCP04 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_10), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1|DEV_NEED_TX_LIMIT, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1|DEV_NEED_TX_LIMIT, }, { /* MCP04 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_11), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1|DEV_NEED_TX_LIMIT, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1|DEV_NEED_TX_LIMIT, }, { /* MCP51 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_STATISTICS_V1, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_STATISTICS_V1, }, { /* MCP51 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_13), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_STATISTICS_V1, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_STATISTICS_V1, }, { /* MCP55 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14), @@ -6190,83 +6199,83 @@ static struct pci_device_id pci_tbl[] = { }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_16), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_17), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_18), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_19), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_24), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_25), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_26), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_27), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE, }, { /* MCP73 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_28), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE, }, { /* MCP73 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_29), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE, }, { /* MCP73 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_30), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE, }, { /* MCP73 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_31), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE, }, { /* MCP77 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_32), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, }, { /* MCP77 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_33), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, }, { /* MCP77 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_34), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, }, { /* MCP77 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_35), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, }, { /* MCP79 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_36), @@ -6274,15 +6283,15 @@ static struct pci_device_id pci_tbl[] = { }, { /* MCP79 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_37), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, }, { /* MCP79 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_38), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, }, { /* MCP79 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_39), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, }, {0,}, }; @@ -6310,7 +6319,7 @@ static void __exit exit_nic(void) module_param(max_interrupt_work, int, 0); MODULE_PARM_DESC(max_interrupt_work, "forcedeth maximum events handled per interrupt"); module_param(optimization_mode, int, 0); -MODULE_PARM_DESC(optimization_mode, "In throughput mode (0), every tx & rx packet will generate an interrupt. In CPU mode (1), interrupts are controlled by a timer."); +MODULE_PARM_DESC(optimization_mode, "In throughput mode (0), every tx & rx packet will generate an interrupt. In CPU mode (1), interrupts are controlled by a timer. In dynamic mode (2), the mode toggles between throughput and CPU mode based on network load."); module_param(poll_interval, int, 0); MODULE_PARM_DESC(poll_interval, "Interval determines how frequent timer interrupt is generated by [(time_in_micro_secs * 100) / (2^10)]. Min is 0 and Max is 65535."); module_param(msi, int, 0); -- GitLab From b67874ac1604cda8070d60d432e892c09d761b2e Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Thu, 5 Mar 2009 08:02:22 +0000 Subject: [PATCH 3027/4982] forcedeth: remove isr processing loop This patch is only a subset of changes so that it is easier to see the modifications. This patch removes the isr 'for' loop and shifts all the logic to account for new tab spacing. Signed-off-by: Ayaz Abdulla Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 252 +++++++++++++++++----------------------- 1 file changed, 105 insertions(+), 147 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 07e245dab68..2c3a7f851f2 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -3423,99 +3423,78 @@ static irqreturn_t nv_nic_irq(int foo, void *data) struct net_device *dev = (struct net_device *) data; struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); - int i; dprintk(KERN_DEBUG "%s: nv_nic_irq\n", dev->name); - for (i=0; ; i++) { - if (!(np->msi_flags & NV_MSI_X_ENABLED)) { - np->events = readl(base + NvRegIrqStatus); - writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); - } else { - np->events = readl(base + NvRegMSIXIrqStatus); - writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus); - } - dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, np->events); - if (!(np->events & np->irqmask)) - break; + if (!(np->msi_flags & NV_MSI_X_ENABLED)) { + np->events = readl(base + NvRegIrqStatus); + writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); + } else { + np->events = readl(base + NvRegMSIXIrqStatus); + writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus); + } + dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, np->events); + if (!(np->events & np->irqmask)) + return IRQ_NONE; - nv_msi_workaround(np); + nv_msi_workaround(np); #ifdef CONFIG_FORCEDETH_NAPI - spin_lock(&np->lock); - napi_schedule(&np->napi); + spin_lock(&np->lock); + napi_schedule(&np->napi); - /* Disable furthur irq's - (msix not enabled with napi) */ - writel(0, base + NvRegIrqMask); + /* Disable furthur irq's + (msix not enabled with napi) */ + writel(0, base + NvRegIrqMask); - spin_unlock(&np->lock); + spin_unlock(&np->lock); - return IRQ_HANDLED; + return IRQ_HANDLED; #else - spin_lock(&np->lock); - nv_tx_done(dev, np->tx_ring_size); - spin_unlock(&np->lock); - - if (nv_rx_process(dev, RX_WORK_PER_LOOP)) { - if (unlikely(nv_alloc_rx(dev))) { - spin_lock(&np->lock); - if (!np->in_shutdown) - mod_timer(&np->oom_kick, jiffies + OOM_REFILL); - spin_unlock(&np->lock); - } - } + spin_lock(&np->lock); + nv_tx_done(dev, np->tx_ring_size); + spin_unlock(&np->lock); - if (unlikely(np->events & NVREG_IRQ_LINK)) { + if (nv_rx_process(dev, RX_WORK_PER_LOOP)) { + if (unlikely(nv_alloc_rx(dev))) { spin_lock(&np->lock); - nv_link_irq(dev); - spin_unlock(&np->lock); - } - if (unlikely(np->need_linktimer && time_after(jiffies, np->link_timeout))) { - spin_lock(&np->lock); - nv_linkchange(dev); + if (!np->in_shutdown) + mod_timer(&np->oom_kick, jiffies + OOM_REFILL); spin_unlock(&np->lock); - np->link_timeout = jiffies + LINK_TIMEOUT; } - if (unlikely(np->events & NVREG_IRQ_RECOVER_ERROR)) { - spin_lock(&np->lock); - /* disable interrupts on the nic */ - if (!(np->msi_flags & NV_MSI_X_ENABLED)) - writel(0, base + NvRegIrqMask); - else - writel(np->irqmask, base + NvRegIrqMask); - pci_push(base); + } - if (!np->in_shutdown) { - np->nic_poll_irq = np->irqmask; - np->recover_error = 1; - mod_timer(&np->nic_poll, jiffies + POLL_WAIT); - } - spin_unlock(&np->lock); - break; - } - if (unlikely(i > max_interrupt_work)) { - spin_lock(&np->lock); - /* disable interrupts on the nic */ - if (!(np->msi_flags & NV_MSI_X_ENABLED)) - writel(0, base + NvRegIrqMask); - else - writel(np->irqmask, base + NvRegIrqMask); - pci_push(base); + if (unlikely(np->events & NVREG_IRQ_LINK)) { + spin_lock(&np->lock); + nv_link_irq(dev); + spin_unlock(&np->lock); + } + if (unlikely(np->need_linktimer && time_after(jiffies, np->link_timeout))) { + spin_lock(&np->lock); + nv_linkchange(dev); + spin_unlock(&np->lock); + np->link_timeout = jiffies + LINK_TIMEOUT; + } + if (unlikely(np->events & NVREG_IRQ_RECOVER_ERROR)) { + spin_lock(&np->lock); + /* disable interrupts on the nic */ + if (!(np->msi_flags & NV_MSI_X_ENABLED)) + writel(0, base + NvRegIrqMask); + else + writel(np->irqmask, base + NvRegIrqMask); + pci_push(base); - if (!np->in_shutdown) { - np->nic_poll_irq = np->irqmask; - mod_timer(&np->nic_poll, jiffies + POLL_WAIT); - } - spin_unlock(&np->lock); - printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq.\n", dev->name, i); - break; + if (!np->in_shutdown) { + np->nic_poll_irq = np->irqmask; + np->recover_error = 1; + mod_timer(&np->nic_poll, jiffies + POLL_WAIT); } -#endif + spin_unlock(&np->lock); } +#endif dprintk(KERN_DEBUG "%s: nv_nic_irq completed\n", dev->name); - return IRQ_RETVAL(i); + return IRQ_HANDLED; } /** @@ -3528,100 +3507,79 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) struct net_device *dev = (struct net_device *) data; struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); - int i; dprintk(KERN_DEBUG "%s: nv_nic_irq_optimized\n", dev->name); - for (i=0; ; i++) { - if (!(np->msi_flags & NV_MSI_X_ENABLED)) { - np->events = readl(base + NvRegIrqStatus); - writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); - } else { - np->events = readl(base + NvRegMSIXIrqStatus); - writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus); - } - dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, np->events); - if (!(np->events & np->irqmask)) - break; + if (!(np->msi_flags & NV_MSI_X_ENABLED)) { + np->events = readl(base + NvRegIrqStatus); + writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); + } else { + np->events = readl(base + NvRegMSIXIrqStatus); + writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus); + } + dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, np->events); + if (!(np->events & np->irqmask)) + return IRQ_NONE; - nv_msi_workaround(np); + nv_msi_workaround(np); #ifdef CONFIG_FORCEDETH_NAPI - spin_lock(&np->lock); - napi_schedule(&np->napi); + spin_lock(&np->lock); + napi_schedule(&np->napi); - /* Disable furthur irq's - (msix not enabled with napi) */ - writel(0, base + NvRegIrqMask); + /* Disable furthur irq's + (msix not enabled with napi) */ + writel(0, base + NvRegIrqMask); - spin_unlock(&np->lock); + spin_unlock(&np->lock); - return IRQ_HANDLED; + return IRQ_HANDLED; #else - spin_lock(&np->lock); - nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); - spin_unlock(&np->lock); - - if (nv_rx_process_optimized(dev, RX_WORK_PER_LOOP)) { - if (unlikely(nv_alloc_rx_optimized(dev))) { - spin_lock(&np->lock); - if (!np->in_shutdown) - mod_timer(&np->oom_kick, jiffies + OOM_REFILL); - spin_unlock(&np->lock); - } - } + spin_lock(&np->lock); + nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); + spin_unlock(&np->lock); - if (unlikely(np->events & NVREG_IRQ_LINK)) { + if (nv_rx_process_optimized(dev, RX_WORK_PER_LOOP)) { + if (unlikely(nv_alloc_rx_optimized(dev))) { spin_lock(&np->lock); - nv_link_irq(dev); - spin_unlock(&np->lock); - } - if (unlikely(np->need_linktimer && time_after(jiffies, np->link_timeout))) { - spin_lock(&np->lock); - nv_linkchange(dev); - spin_unlock(&np->lock); - np->link_timeout = jiffies + LINK_TIMEOUT; - } - if (unlikely(np->events & NVREG_IRQ_RECOVER_ERROR)) { - spin_lock(&np->lock); - /* disable interrupts on the nic */ - if (!(np->msi_flags & NV_MSI_X_ENABLED)) - writel(0, base + NvRegIrqMask); - else - writel(np->irqmask, base + NvRegIrqMask); - pci_push(base); - - if (!np->in_shutdown) { - np->nic_poll_irq = np->irqmask; - np->recover_error = 1; - mod_timer(&np->nic_poll, jiffies + POLL_WAIT); - } + if (!np->in_shutdown) + mod_timer(&np->oom_kick, jiffies + OOM_REFILL); spin_unlock(&np->lock); - break; } + } - if (unlikely(i > max_interrupt_work)) { - spin_lock(&np->lock); - /* disable interrupts on the nic */ - if (!(np->msi_flags & NV_MSI_X_ENABLED)) - writel(0, base + NvRegIrqMask); - else - writel(np->irqmask, base + NvRegIrqMask); - pci_push(base); + if (unlikely(np->events & NVREG_IRQ_LINK)) { + spin_lock(&np->lock); + nv_link_irq(dev); + spin_unlock(&np->lock); + } + if (unlikely(np->need_linktimer && time_after(jiffies, np->link_timeout))) { + spin_lock(&np->lock); + nv_linkchange(dev); + spin_unlock(&np->lock); + np->link_timeout = jiffies + LINK_TIMEOUT; + } + if (unlikely(np->events & NVREG_IRQ_RECOVER_ERROR)) { + spin_lock(&np->lock); + /* disable interrupts on the nic */ + if (!(np->msi_flags & NV_MSI_X_ENABLED)) + writel(0, base + NvRegIrqMask); + else + writel(np->irqmask, base + NvRegIrqMask); + pci_push(base); - if (!np->in_shutdown) { - np->nic_poll_irq = np->irqmask; - mod_timer(&np->nic_poll, jiffies + POLL_WAIT); - } - spin_unlock(&np->lock); - printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq.\n", dev->name, i); - break; + if (!np->in_shutdown) { + np->nic_poll_irq = np->irqmask; + np->recover_error = 1; + mod_timer(&np->nic_poll, jiffies + POLL_WAIT); } -#endif + spin_unlock(&np->lock); } + +#endif dprintk(KERN_DEBUG "%s: nv_nic_irq_optimized completed\n", dev->name); - return IRQ_RETVAL(i); + return IRQ_HANDLED; } static irqreturn_t nv_nic_irq_tx(int foo, void *data) -- GitLab From 4145ade2bb265b34331265bfa2221e40b069b3ca Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Thu, 5 Mar 2009 08:02:26 +0000 Subject: [PATCH 3028/4982] forcedeth: add interrupt moderation logic This patch adds the logic to moderate the interrupts by changing the mode between throughput and poll. If there has been a large amount of time without any burst of network load, the code will transition to pure throughput mode (where each tx/rx/other will cause an interrupt). If bursts of network load occurs, it will transition to poll based mode to help reduce cpu utilization (it will not interrupt on each packet) while maintaining the optimum network bandwidth utilization. Signed-off-by: Ayaz Abdulla Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 137 +++++++++++++++++++++++++++++++--------- 1 file changed, 106 insertions(+), 31 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 2c3a7f851f2..341a35117ea 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -593,6 +593,9 @@ union ring_type { #define NV_TX_LIMIT_COUNT 16 +#define NV_DYNAMIC_THRESHOLD 4 +#define NV_DYNAMIC_MAX_QUIET_COUNT 2048 + /* statistics */ struct nv_ethtool_str { char name[ETH_GSTRING_LEN]; @@ -750,6 +753,7 @@ struct fe_priv { u16 gigabit; int intr_test; int recover_error; + int quiet_count; /* General data: RO fields */ dma_addr_t ring_addr; @@ -832,7 +836,7 @@ struct fe_priv { * Maximum number of loops until we assume that a bit in the irq mask * is stuck. Overridable with module param. */ -static int max_interrupt_work = 15; +static int max_interrupt_work = 4; /* * Optimization can be either throuput mode or cpu mode @@ -3418,11 +3422,43 @@ static void nv_msi_workaround(struct fe_priv *np) } } +static inline int nv_change_interrupt_mode(struct net_device *dev, int total_work) +{ + struct fe_priv *np = netdev_priv(dev); + + if (optimization_mode == NV_OPTIMIZATION_MODE_DYNAMIC) { + if (total_work > NV_DYNAMIC_THRESHOLD) { + /* transition to poll based interrupts */ + np->quiet_count = 0; + if (np->irqmask != NVREG_IRQMASK_CPU) { + np->irqmask = NVREG_IRQMASK_CPU; + return 1; + } + } else { + if (np->quiet_count < NV_DYNAMIC_MAX_QUIET_COUNT) { + np->quiet_count++; + } else { + /* reached a period of low activity, switch + to per tx/rx packet interrupts */ + if (np->irqmask != NVREG_IRQMASK_THROUGHPUT) { + np->irqmask = NVREG_IRQMASK_THROUGHPUT; + return 1; + } + } + } + } + return 0; +} + static irqreturn_t nv_nic_irq(int foo, void *data) { struct net_device *dev = (struct net_device *) data; struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); +#ifndef CONFIG_FORCEDETH_NAPI + int total_work = 0; + int loop_count = 0; +#endif dprintk(KERN_DEBUG "%s: nv_nic_irq\n", dev->name); @@ -3449,19 +3485,35 @@ static irqreturn_t nv_nic_irq(int foo, void *data) spin_unlock(&np->lock); - return IRQ_HANDLED; #else - spin_lock(&np->lock); - nv_tx_done(dev, np->tx_ring_size); - spin_unlock(&np->lock); - - if (nv_rx_process(dev, RX_WORK_PER_LOOP)) { - if (unlikely(nv_alloc_rx(dev))) { - spin_lock(&np->lock); - if (!np->in_shutdown) - mod_timer(&np->oom_kick, jiffies + OOM_REFILL); - spin_unlock(&np->lock); + do + { + int work = 0; + if ((work = nv_rx_process(dev, RX_WORK_PER_LOOP))) { + if (unlikely(nv_alloc_rx(dev))) { + spin_lock(&np->lock); + if (!np->in_shutdown) + mod_timer(&np->oom_kick, jiffies + OOM_REFILL); + spin_unlock(&np->lock); + } } + + spin_lock(&np->lock); + work += nv_tx_done(dev, TX_WORK_PER_LOOP); + spin_unlock(&np->lock); + + if (!work) + break; + + total_work += work; + + loop_count++; + } + while (loop_count < max_interrupt_work); + + if (nv_change_interrupt_mode(dev, total_work)) { + /* setup new irq mask */ + writel(np->irqmask, base + NvRegIrqMask); } if (unlikely(np->events & NVREG_IRQ_LINK)) { @@ -3507,6 +3559,10 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) struct net_device *dev = (struct net_device *) data; struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); +#ifndef CONFIG_FORCEDETH_NAPI + int total_work = 0; + int loop_count = 0; +#endif dprintk(KERN_DEBUG "%s: nv_nic_irq_optimized\n", dev->name); @@ -3533,19 +3589,35 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) spin_unlock(&np->lock); - return IRQ_HANDLED; #else - spin_lock(&np->lock); - nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); - spin_unlock(&np->lock); - - if (nv_rx_process_optimized(dev, RX_WORK_PER_LOOP)) { - if (unlikely(nv_alloc_rx_optimized(dev))) { - spin_lock(&np->lock); - if (!np->in_shutdown) - mod_timer(&np->oom_kick, jiffies + OOM_REFILL); - spin_unlock(&np->lock); + do + { + int work = 0; + if ((work = nv_rx_process_optimized(dev, RX_WORK_PER_LOOP))) { + if (unlikely(nv_alloc_rx_optimized(dev))) { + spin_lock(&np->lock); + if (!np->in_shutdown) + mod_timer(&np->oom_kick, jiffies + OOM_REFILL); + spin_unlock(&np->lock); + } } + + spin_lock(&np->lock); + work += nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); + spin_unlock(&np->lock); + + if (!work) + break; + + total_work += work; + + loop_count++; + } + while (loop_count < max_interrupt_work); + + if (nv_change_interrupt_mode(dev, total_work)) { + /* setup new irq mask */ + writel(np->irqmask, base + NvRegIrqMask); } if (unlikely(np->events & NVREG_IRQ_LINK)) { @@ -3632,21 +3704,22 @@ static int nv_napi_poll(struct napi_struct *napi, int budget) struct net_device *dev = np->dev; u8 __iomem *base = get_hwbase(dev); unsigned long flags; - int pkts, retcode; + int retcode; + int tx_work, rx_work; if (!nv_optimized(np)) { spin_lock_irqsave(&np->lock, flags); - nv_tx_done(dev, np->tx_ring_size); + tx_work = nv_tx_done(dev, np->tx_ring_size); spin_unlock_irqrestore(&np->lock, flags); - pkts = nv_rx_process(dev, budget); + rx_work = nv_rx_process(dev, budget); retcode = nv_alloc_rx(dev); } else { spin_lock_irqsave(&np->lock, flags); - nv_tx_done_optimized(dev, np->tx_ring_size); + tx_work = nv_tx_done_optimized(dev, np->tx_ring_size); spin_unlock_irqrestore(&np->lock, flags); - pkts = nv_rx_process_optimized(dev, budget); + rx_work = nv_rx_process_optimized(dev, budget); retcode = nv_alloc_rx_optimized(dev); } @@ -3657,6 +3730,8 @@ static int nv_napi_poll(struct napi_struct *napi, int budget) spin_unlock_irqrestore(&np->lock, flags); } + nv_change_interrupt_mode(dev, tx_work + rx_work); + if (unlikely(np->events & NVREG_IRQ_LINK)) { spin_lock_irqsave(&np->lock, flags); nv_link_irq(dev); @@ -3677,10 +3752,10 @@ static int nv_napi_poll(struct napi_struct *napi, int budget) } spin_unlock_irqrestore(&np->lock, flags); __napi_complete(napi); - return pkts; + return rx_work; } - if (pkts < budget) { + if (rx_work < budget) { /* re-enable interrupts (msix not enabled in napi) */ spin_lock_irqsave(&np->lock, flags); @@ -3691,7 +3766,7 @@ static int nv_napi_poll(struct napi_struct *napi, int budget) spin_unlock_irqrestore(&np->lock, flags); } - return pkts; + return rx_work; } #endif -- GitLab From 6cef67a02f7994c97dbd716dbeb592265fb5b7b0 Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Thu, 5 Mar 2009 08:02:30 +0000 Subject: [PATCH 3029/4982] forcedeth: performance changes This patch modifies the throughput mode poll settings to reduce the number of interrupts. This is only used by older hardware that need a timer irq in throughput mode. Secondly, this patch increases the default rx ring from 128 to 512. This drastically improves bandwidth utilization for small packets sizes i.e 512 bytes. Signed-off-by: Ayaz Abdulla Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 341a35117ea..28fc3357268 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -128,7 +128,7 @@ enum { * NVREG_POLL_DEFAULT=97 would result in an interval length of 1 ms */ NvRegPollingInterval = 0x00c, -#define NVREG_POLL_DEFAULT_THROUGHPUT 970 /* backup tx cleanup if loop max reached */ +#define NVREG_POLL_DEFAULT_THROUGHPUT 65535 /* backup tx cleanup if loop max reached */ #define NVREG_POLL_DEFAULT_CPU 13 NvRegMSIMap0 = 0x020, NvRegMSIMap1 = 0x024, @@ -463,7 +463,7 @@ union ring_type { /* General driver defaults */ #define NV_WATCHDOG_TIMEO (5*HZ) -#define RX_RING_DEFAULT 128 +#define RX_RING_DEFAULT 512 #define TX_RING_DEFAULT 256 #define RX_RING_MIN 128 #define TX_RING_MIN 64 -- GitLab From 1b2bb76f575699eff3f58b18dcfebf5d3b1f6ddb Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Thu, 5 Mar 2009 08:02:34 +0000 Subject: [PATCH 3030/4982] forcedeth: fix irq clearing and napi spin lock changes This patch clears the irqstatus register with the exact same events it has read from it. Since the read-write operation is not atomic, a new irqstatus bit could have been set in between these operations and would then be cleared accidentally. Secondly, we now don't need any spin lock protection when scheduling/completing napi poll as the isr will not execute anymore (as we turn off all interrupts now). Signed-off-by: Ayaz Abdulla Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 28fc3357268..514aaf189af 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -3464,10 +3464,10 @@ static irqreturn_t nv_nic_irq(int foo, void *data) if (!(np->msi_flags & NV_MSI_X_ENABLED)) { np->events = readl(base + NvRegIrqStatus); - writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); + writel(np->events, base + NvRegIrqStatus); } else { np->events = readl(base + NvRegMSIXIrqStatus); - writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus); + writel(np->events, base + NvRegMSIXIrqStatus); } dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, np->events); if (!(np->events & np->irqmask)) @@ -3476,15 +3476,12 @@ static irqreturn_t nv_nic_irq(int foo, void *data) nv_msi_workaround(np); #ifdef CONFIG_FORCEDETH_NAPI - spin_lock(&np->lock); napi_schedule(&np->napi); /* Disable furthur irq's (msix not enabled with napi) */ writel(0, base + NvRegIrqMask); - spin_unlock(&np->lock); - #else do { @@ -3568,10 +3565,10 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) if (!(np->msi_flags & NV_MSI_X_ENABLED)) { np->events = readl(base + NvRegIrqStatus); - writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); + writel(np->events, base + NvRegIrqStatus); } else { np->events = readl(base + NvRegMSIXIrqStatus); - writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus); + writel(np->events, base + NvRegMSIXIrqStatus); } dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, np->events); if (!(np->events & np->irqmask)) @@ -3580,15 +3577,12 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) nv_msi_workaround(np); #ifdef CONFIG_FORCEDETH_NAPI - spin_lock(&np->lock); napi_schedule(&np->napi); /* Disable furthur irq's (msix not enabled with napi) */ writel(0, base + NvRegIrqMask); - spin_unlock(&np->lock); - #else do { @@ -3758,13 +3752,9 @@ static int nv_napi_poll(struct napi_struct *napi, int budget) if (rx_work < budget) { /* re-enable interrupts (msix not enabled in napi) */ - spin_lock_irqsave(&np->lock, flags); - __napi_complete(napi); writel(np->irqmask, base + NvRegIrqMask); - - spin_unlock_irqrestore(&np->lock, flags); } return rx_work; } -- GitLab From 3e1a3ce2f19a8a74fe6771f6dcd642d61ae050dc Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Thu, 5 Mar 2009 08:02:38 +0000 Subject: [PATCH 3031/4982] forcedeth: version bump to 64 This patch bumps up the version to 0.64 Signed-off-by: Ayaz Abdulla Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 514aaf189af..a858c6ff80d 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -39,7 +39,7 @@ * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few * superfluous timer interrupts from the nic. */ -#define FORCEDETH_VERSION "0.63" +#define FORCEDETH_VERSION "0.64" #define DRV_NAME "forcedeth" #include -- GitLab From 34f42a070fc98f5dc07e9fa2338b7b8d1dc347eb Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:55:45 -0800 Subject: [PATCH 3032/4982] [SCSI] libfc, fcoe: Fix kerneldoc comments 1) Added '()' for function names in kerneldoc comments 2) Changed comment bookends from '**/' to '*/'. The comment on the the mailing list was that '**/' "is consistently unconventional. Not wrong, just odd." The Documentation/kernel-doc-nano-HOWTO.txt states that kerneldoc comment blocks should end with '**/' but most (if not all) instance I found under drivers/scsi/ were only using the '*/' so I converted to that style. 3) Removed incorrect linebreaks in kerneldoc comments where found 4) Removed a few unnecessary blank comment lines in kerneldoc comment blocks Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fc_transport_fcoe.c | 77 ++++++------ drivers/scsi/fcoe/fcoe_sw.c | 42 +++---- drivers/scsi/fcoe/libfcoe.c | 162 +++++++++++++------------- drivers/scsi/libfc/fc_disc.c | 45 +++---- drivers/scsi/libfc/fc_fcp.c | 46 ++++---- drivers/scsi/libfc/fc_lport.c | 77 ++++++------ drivers/scsi/libfc/fc_rport.c | 46 ++++---- include/scsi/libfc.h | 14 +-- 8 files changed, 252 insertions(+), 257 deletions(-) diff --git a/drivers/scsi/fcoe/fc_transport_fcoe.c b/drivers/scsi/fcoe/fc_transport_fcoe.c index bf7fe6fc082..0eea4c434c3 100644 --- a/drivers/scsi/fcoe/fc_transport_fcoe.c +++ b/drivers/scsi/fcoe/fc_transport_fcoe.c @@ -33,19 +33,19 @@ static LIST_HEAD(fcoe_transports); static DEFINE_MUTEX(fcoe_transports_lock); /** - * fcoe_transport_default - returns ptr to the default transport fcoe_sw - **/ + * fcoe_transport_default() - Returns ptr to the default transport fcoe_sw + */ struct fcoe_transport *fcoe_transport_default(void) { return &fcoe_sw_transport; } /** - * fcoe_transport_to_pcidev - get the pci dev from a netdev + * fcoe_transport_to_pcidev() - get the pci dev from a netdev * @netdev: the netdev that pci dev will be retrived from * * Returns: NULL or the corrsponding pci_dev - **/ + */ struct pci_dev *fcoe_transport_pcidev(const struct net_device *netdev) { if (!netdev->dev.parent) @@ -54,16 +54,14 @@ struct pci_dev *fcoe_transport_pcidev(const struct net_device *netdev) } /** - * fcoe_transport_device_lookup - find out netdev is managed by the - * transport - * assign a transport to a device + * fcoe_transport_device_lookup() - Lookup a transport * @netdev: the netdev the transport to be attached to * * This will look for existing offload driver, if not found, it falls back to * the default sw hba (fcoe_sw) as its fcoe transport. * * Returns: 0 for success - **/ + */ static struct fcoe_transport_internal *fcoe_transport_device_lookup( struct fcoe_transport *t, struct net_device *netdev) { @@ -81,14 +79,14 @@ static struct fcoe_transport_internal *fcoe_transport_device_lookup( return NULL; } /** - * fcoe_transport_device_add - assign a transport to a device + * fcoe_transport_device_add() - Assign a transport to a device * @netdev: the netdev the transport to be attached to * * This will look for existing offload driver, if not found, it falls back to * the default sw hba (fcoe_sw) as its fcoe transport. * * Returns: 0 for success - **/ + */ static int fcoe_transport_device_add(struct fcoe_transport *t, struct net_device *netdev) { @@ -123,14 +121,14 @@ static int fcoe_transport_device_add(struct fcoe_transport *t, } /** - * fcoe_transport_device_remove - remove a device from its transport + * fcoe_transport_device_remove() - Remove a device from its transport * @netdev: the netdev the transport to be attached to * - * this removes the device from the transport so the given transport will + * This removes the device from the transport so the given transport will * not manage this device any more * * Returns: 0 for success - **/ + */ static int fcoe_transport_device_remove(struct fcoe_transport *t, struct net_device *netdev) { @@ -155,13 +153,13 @@ static int fcoe_transport_device_remove(struct fcoe_transport *t, } /** - * fcoe_transport_device_remove_all - remove all from transport devlist + * fcoe_transport_device_remove_all() - Remove all from transport devlist * - * this removes the device from the transport so the given transport will + * This removes the device from the transport so the given transport will * not manage this device any more * * Returns: 0 for success - **/ + */ static void fcoe_transport_device_remove_all(struct fcoe_transport *t) { struct fcoe_transport_internal *ti, *tmp; @@ -175,16 +173,16 @@ static void fcoe_transport_device_remove_all(struct fcoe_transport *t) } /** - * fcoe_transport_match - use the bus device match function to match the hw - * @t: the fcoe transport - * @netdev: + * fcoe_transport_match() - Use the bus device match function to match the hw + * @t: The fcoe transport to check + * @netdev: The netdev to match against * - * This function is used to check if the givne transport wants to manage the + * This function is used to check if the given transport wants to manage the * input netdev. if the transports implements the match function, it will be * called, o.w. we just compare the pci vendor and device id. * * Returns: true for match up - **/ + */ static bool fcoe_transport_match(struct fcoe_transport *t, struct net_device *netdev) { @@ -210,15 +208,15 @@ static bool fcoe_transport_match(struct fcoe_transport *t, } /** - * fcoe_transport_lookup - check if the transport is already registered + * fcoe_transport_lookup() - Check if the transport is already registered * @t: the transport to be looked up * * This compares the parent device (pci) vendor and device id * * Returns: NULL if not found * - * TODO - return default sw transport if no other transport is found - **/ + * TODO: return default sw transport if no other transport is found + */ static struct fcoe_transport *fcoe_transport_lookup( struct net_device *netdev) { @@ -239,11 +237,11 @@ static struct fcoe_transport *fcoe_transport_lookup( } /** - * fcoe_transport_register - adds a fcoe transport to the fcoe transports list + * fcoe_transport_register() - Adds a fcoe transport to the fcoe transports list * @t: ptr to the fcoe transport to be added * * Returns: 0 for success - **/ + */ int fcoe_transport_register(struct fcoe_transport *t) { struct fcoe_transport *tt; @@ -269,11 +267,11 @@ int fcoe_transport_register(struct fcoe_transport *t) EXPORT_SYMBOL_GPL(fcoe_transport_register); /** - * fcoe_transport_unregister - remove the tranport fro the fcoe transports list + * fcoe_transport_unregister() - Remove the tranport fro the fcoe transports list * @t: ptr to the fcoe transport to be removed * * Returns: 0 for success - **/ + */ int fcoe_transport_unregister(struct fcoe_transport *t) { struct fcoe_transport *tt, *tmp; @@ -294,8 +292,8 @@ int fcoe_transport_unregister(struct fcoe_transport *t) } EXPORT_SYMBOL_GPL(fcoe_transport_unregister); -/* - * fcoe_load_transport_driver - load an offload driver by alias name +/** + * fcoe_load_transport_driver() - Load an offload driver by alias name * @netdev: the target net device * * Requests for an offload driver module as the fcoe transport, if fails, it @@ -307,7 +305,7 @@ EXPORT_SYMBOL_GPL(fcoe_transport_unregister); * 3. pure hw fcoe hba may not have netdev * * Returns: 0 for success - **/ + */ int fcoe_load_transport_driver(struct net_device *netdev) { struct pci_dev *pci; @@ -335,14 +333,14 @@ int fcoe_load_transport_driver(struct net_device *netdev) EXPORT_SYMBOL_GPL(fcoe_load_transport_driver); /** - * fcoe_transport_attach - load transport to fcoe + * fcoe_transport_attach() - Load transport to fcoe * @netdev: the netdev the transport to be attached to * * This will look for existing offload driver, if not found, it falls back to * the default sw hba (fcoe_sw) as its fcoe transport. * * Returns: 0 for success - **/ + */ int fcoe_transport_attach(struct net_device *netdev) { struct fcoe_transport *t; @@ -373,11 +371,11 @@ int fcoe_transport_attach(struct net_device *netdev) EXPORT_SYMBOL_GPL(fcoe_transport_attach); /** - * fcoe_transport_release - unload transport from fcoe + * fcoe_transport_release() - Unload transport from fcoe * @netdev: the net device on which fcoe is to be released * * Returns: 0 for success - **/ + */ int fcoe_transport_release(struct net_device *netdev) { struct fcoe_transport *t; @@ -410,12 +408,12 @@ int fcoe_transport_release(struct net_device *netdev) EXPORT_SYMBOL_GPL(fcoe_transport_release); /** - * fcoe_transport_init - initializes fcoe transport layer + * fcoe_transport_init() - Initializes fcoe transport layer * * This prepares for the fcoe transport layer * * Returns: none - **/ + */ int __init fcoe_transport_init(void) { INIT_LIST_HEAD(&fcoe_transports); @@ -424,12 +422,13 @@ int __init fcoe_transport_init(void) } /** - * fcoe_transport_exit - cleans up the fcoe transport layer + * fcoe_transport_exit() - Cleans up the fcoe transport layer + * * This cleans up the fcoe transport layer. removing any transport on the list, * note that the transport destroy func is not called here. * * Returns: none - **/ + */ int __exit fcoe_transport_exit(void) { struct fcoe_transport *t, *tmp; diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c index cf83675a0fb..007d1fbae80 100644 --- a/drivers/scsi/fcoe/fcoe_sw.c +++ b/drivers/scsi/fcoe/fcoe_sw.c @@ -104,13 +104,12 @@ static struct scsi_host_template fcoe_sw_shost_template = { .max_sectors = 0xffff, }; -/* - * fcoe_sw_lport_config - sets up the fc_lport +/** + * fcoe_sw_lport_config() - sets up the fc_lport * @lp: ptr to the fc_lport * @shost: ptr to the parent scsi host * * Returns: 0 for success - * */ static int fcoe_sw_lport_config(struct fc_lport *lp) { @@ -137,16 +136,14 @@ static int fcoe_sw_lport_config(struct fc_lport *lp) return 0; } -/* - * fcoe_sw_netdev_config - sets up fcoe_softc for lport and network - * related properties +/** + * fcoe_sw_netdev_config() - Set up netdev for SW FCoE * @lp : ptr to the fc_lport * @netdev : ptr to the associated netdevice struct * * Must be called after fcoe_sw_lport_config() as it will use lport mutex * * Returns : 0 for success - * */ static int fcoe_sw_netdev_config(struct fc_lport *lp, struct net_device *netdev) { @@ -224,16 +221,15 @@ static int fcoe_sw_netdev_config(struct fc_lport *lp, struct net_device *netdev) return 0; } -/* - * fcoe_sw_shost_config - sets up fc_lport->host +/** + * fcoe_sw_shost_config() - Sets up fc_lport->host * @lp : ptr to the fc_lport * @shost : ptr to the associated scsi host * @dev : device associated to scsi host * - * Must be called after fcoe_sw_lport_config) and fcoe_sw_netdev_config() + * Must be called after fcoe_sw_lport_config() and fcoe_sw_netdev_config() * * Returns : 0 for success - * */ static int fcoe_sw_shost_config(struct fc_lport *lp, struct Scsi_Host *shost, struct device *dev) @@ -261,8 +257,8 @@ static int fcoe_sw_shost_config(struct fc_lport *lp, struct Scsi_Host *shost, return 0; } -/* - * fcoe_sw_em_config - allocates em for this lport +/** + * fcoe_sw_em_config() - allocates em for this lport * @lp: the port that em is to allocated for * * Returns : 0 on success @@ -279,8 +275,8 @@ static inline int fcoe_sw_em_config(struct fc_lport *lp) return 0; } -/* - * fcoe_sw_destroy - FCoE software HBA tear-down function +/** + * fcoe_sw_destroy() - FCoE software HBA tear-down function * @netdev: ptr to the associated net_device * * Returns: 0 if link is OK for use by FCoE. @@ -353,8 +349,8 @@ static struct libfc_function_template fcoe_sw_libfc_fcn_templ = { .frame_send = fcoe_xmit, }; -/* - * fcoe_sw_create - this function creates the fcoe interface +/** + * fcoe_sw_create() - this function creates the fcoe interface * @netdev: pointer the associated netdevice * * Creates fc_lport struct and scsi_host for lport, configures lport @@ -440,8 +436,8 @@ out_host_put: return rc; } -/* - * fcoe_sw_match - the fcoe sw transport match function +/** + * fcoe_sw_match() - The FCoE SW transport match function * * Returns : false always */ @@ -461,8 +457,8 @@ struct fcoe_transport fcoe_sw_transport = { .device = 0xffff, }; -/* - * fcoe_sw_init - registers fcoe_sw_transport +/** + * fcoe_sw_init() - Registers fcoe_sw_transport * * Returns : 0 on success */ @@ -480,8 +476,8 @@ int __init fcoe_sw_init(void) return 0; } -/* - * fcoe_sw_exit - unregisters fcoe_sw_transport +/** + * fcoe_sw_exit() - Unregisters fcoe_sw_transport * * Returns : 0 on success */ diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 296071043f5..5e68652985b 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -91,13 +91,13 @@ static struct notifier_block fcoe_cpu_notifier = { }; /** - * fcoe_create_percpu_data - creates the associated cpu data + * fcoe_create_percpu_data() - creates the associated cpu data * @cpu: index for the cpu where fcoe cpu data will be created * * create percpu stats block, from cpu add notifier * * Returns: none - **/ + */ static void fcoe_create_percpu_data(int cpu) { struct fc_lport *lp; @@ -115,13 +115,13 @@ static void fcoe_create_percpu_data(int cpu) } /** - * fcoe_destroy_percpu_data - destroys the associated cpu data + * fcoe_destroy_percpu_data() - destroys the associated cpu data * @cpu: index for the cpu where fcoe cpu data will destroyed * * destroy percpu stats block called by cpu add/remove notifier * * Retuns: none - **/ + */ static void fcoe_destroy_percpu_data(int cpu) { struct fc_lport *lp; @@ -137,7 +137,7 @@ static void fcoe_destroy_percpu_data(int cpu) } /** - * fcoe_cpu_callback - fcoe cpu hotplug event callback + * fcoe_cpu_callback() - fcoe cpu hotplug event callback * @nfb: callback data block * @action: event triggering the callback * @hcpu: index for the cpu of this event @@ -145,7 +145,7 @@ static void fcoe_destroy_percpu_data(int cpu) * this creates or destroys per cpu data for fcoe * * Returns NOTIFY_OK always. - **/ + */ static int fcoe_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -166,7 +166,7 @@ static int fcoe_cpu_callback(struct notifier_block *nfb, unsigned long action, #endif /* CONFIG_HOTPLUG_CPU */ /** - * fcoe_rcv - this is the fcoe receive function called by NET_RX_SOFTIRQ + * fcoe_rcv() - this is the fcoe receive function called by NET_RX_SOFTIRQ * @skb: the receive skb * @dev: associated net device * @ptype: context @@ -175,7 +175,7 @@ static int fcoe_cpu_callback(struct notifier_block *nfb, unsigned long action, * this function will receive the packet and build fc frame and pass it up * * Returns: 0 for success - **/ + */ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *olddev) { @@ -265,11 +265,11 @@ err2: EXPORT_SYMBOL_GPL(fcoe_rcv); /** - * fcoe_start_io - pass to netdev to start xmit for fcoe + * fcoe_start_io() - pass to netdev to start xmit for fcoe * @skb: the skb to be xmitted * * Returns: 0 for success - **/ + */ static inline int fcoe_start_io(struct sk_buff *skb) { int rc; @@ -283,12 +283,12 @@ static inline int fcoe_start_io(struct sk_buff *skb) } /** - * fcoe_get_paged_crc_eof - in case we need alloc a page for crc_eof + * fcoe_get_paged_crc_eof() - in case we need alloc a page for crc_eof * @skb: the skb to be xmitted * @tlen: total len * * Returns: 0 for success - **/ + */ static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen) { struct fcoe_percpu_s *fps; @@ -326,13 +326,12 @@ static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen) } /** - * fcoe_fc_crc - calculates FC CRC in this fcoe skb + * fcoe_fc_crc() - calculates FC CRC in this fcoe skb * @fp: the fc_frame containg data to be checksummed * * This uses crc32() to calculate the crc for fc frame * Return : 32 bit crc - * - **/ + */ u32 fcoe_fc_crc(struct fc_frame *fp) { struct sk_buff *skb = fp_skb(fp); @@ -363,13 +362,12 @@ u32 fcoe_fc_crc(struct fc_frame *fp) EXPORT_SYMBOL_GPL(fcoe_fc_crc); /** - * fcoe_xmit - FCoE frame transmit function + * fcoe_xmit() - FCoE frame transmit function * @lp: the associated local port * @fp: the fc_frame to be transmitted * * Return : 0 for success - * - **/ + */ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) { int wlen, rc = 0; @@ -511,12 +509,11 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) } EXPORT_SYMBOL_GPL(fcoe_xmit); -/* - * fcoe_percpu_receive_thread - recv thread per cpu +/** + * fcoe_percpu_receive_thread() - recv thread per cpu * @arg: ptr to the fcoe per cpu struct * * Return: 0 for success - * */ int fcoe_percpu_receive_thread(void *arg) { @@ -658,7 +655,7 @@ int fcoe_percpu_receive_thread(void *arg) } /** - * fcoe_recv_flogi - flogi receive function + * fcoe_recv_flogi() - flogi receive function * @fc: associated fcoe_softc * @fp: the recieved frame * @sa: the source address of this flogi @@ -667,7 +664,7 @@ int fcoe_percpu_receive_thread(void *arg) * mac address for the initiator, eitehr OUI based or GW based. * * Returns: none - **/ + */ static void fcoe_recv_flogi(struct fcoe_softc *fc, struct fc_frame *fp, u8 *sa) { struct fc_frame_header *fh; @@ -715,7 +712,7 @@ static void fcoe_recv_flogi(struct fcoe_softc *fc, struct fc_frame *fp, u8 *sa) } /** - * fcoe_watchdog - fcoe timer callback + * fcoe_watchdog() - fcoe timer callback * @vp: * * This checks the pending queue length for fcoe and set lport qfull @@ -723,7 +720,7 @@ static void fcoe_recv_flogi(struct fcoe_softc *fc, struct fc_frame *fp, u8 *sa) * fcoe_hostlist. * * Returns: 0 for success - **/ + */ void fcoe_watchdog(ulong vp) { struct fc_lport *lp; @@ -750,7 +747,7 @@ void fcoe_watchdog(ulong vp) /** - * fcoe_check_wait_queue - put the skb into fcoe pending xmit queue + * fcoe_check_wait_queue() - put the skb into fcoe pending xmit queue * @lp: the fc_port for this skb * @skb: the associated skb to be xmitted * @@ -764,7 +761,7 @@ void fcoe_watchdog(ulong vp) * by the next skb transmit. * * Returns: 0 for success - **/ + */ static int fcoe_check_wait_queue(struct fc_lport *lp) { int rc; @@ -797,12 +794,12 @@ static int fcoe_check_wait_queue(struct fc_lport *lp) } /** - * fcoe_insert_wait_queue_head - puts skb to fcoe pending queue head + * fcoe_insert_wait_queue_head() - puts skb to fcoe pending queue head * @lp: the fc_port for this skb * @skb: the associated skb to be xmitted * * Returns: none - **/ + */ static void fcoe_insert_wait_queue_head(struct fc_lport *lp, struct sk_buff *skb) { @@ -815,12 +812,12 @@ static void fcoe_insert_wait_queue_head(struct fc_lport *lp, } /** - * fcoe_insert_wait_queue - put the skb into fcoe pending queue tail + * fcoe_insert_wait_queue() - put the skb into fcoe pending queue tail * @lp: the fc_port for this skb * @skb: the associated skb to be xmitted * * Returns: none - **/ + */ static void fcoe_insert_wait_queue(struct fc_lport *lp, struct sk_buff *skb) { @@ -833,10 +830,9 @@ static void fcoe_insert_wait_queue(struct fc_lport *lp, } /** - * fcoe_dev_setup - setup link change notification interface - * - **/ -static void fcoe_dev_setup(void) + * fcoe_dev_setup() - setup link change notification interface + */ +static void fcoe_dev_setup() { /* * here setup a interface specific wd time to @@ -846,15 +842,15 @@ static void fcoe_dev_setup(void) } /** - * fcoe_dev_setup - cleanup link change notification interface - **/ + * fcoe_dev_setup() - cleanup link change notification interface + */ static void fcoe_dev_cleanup(void) { unregister_netdevice_notifier(&fcoe_notifier); } /** - * fcoe_device_notification - netdev event notification callback + * fcoe_device_notification() - netdev event notification callback * @notifier: context of the notification * @event: type of event * @ptr: fixed array for output parsed ifname @@ -862,7 +858,7 @@ static void fcoe_dev_cleanup(void) * This function is called by the ethernet driver in case of link change event * * Returns: 0 for success - **/ + */ static int fcoe_device_notification(struct notifier_block *notifier, ulong event, void *ptr) { @@ -926,12 +922,12 @@ out: } /** - * fcoe_if_to_netdev - parse a name buffer to get netdev + * fcoe_if_to_netdev() - parse a name buffer to get netdev * @ifname: fixed array for output parsed ifname * @buffer: incoming buffer to be copied * * Returns: NULL or ptr to netdeive - **/ + */ static struct net_device *fcoe_if_to_netdev(const char *buffer) { char *cp; @@ -948,11 +944,11 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer) } /** - * fcoe_netdev_to_module_owner - finds out the nic drive moddule of the netdev + * fcoe_netdev_to_module_owner() - finds out the nic drive moddule of the netdev * @netdev: the target netdev * * Returns: ptr to the struct module, NULL for failure - **/ + */ static struct module *fcoe_netdev_to_module_owner( const struct net_device *netdev) { @@ -972,12 +968,14 @@ static struct module *fcoe_netdev_to_module_owner( } /** - * fcoe_ethdrv_get - holds the nic driver module by try_module_get() for - * the corresponding netdev. + * fcoe_ethdrv_get() - Hold the Ethernet driver * @netdev: the target netdev * + * Holds the Ethernet driver module by try_module_get() for + * the corresponding netdev. + * * Returns: 0 for succsss - **/ + */ static int fcoe_ethdrv_get(const struct net_device *netdev) { struct module *owner; @@ -992,12 +990,14 @@ static int fcoe_ethdrv_get(const struct net_device *netdev) } /** - * fcoe_ethdrv_get - releases the nic driver module by module_put for - * the corresponding netdev. + * fcoe_ethdrv_put() - Release the Ethernet driver * @netdev: the target netdev * + * Releases the Ethernet driver module by module_put for + * the corresponding netdev. + * * Returns: 0 for succsss - **/ + */ static int fcoe_ethdrv_put(const struct net_device *netdev) { struct module *owner; @@ -1013,12 +1013,12 @@ static int fcoe_ethdrv_put(const struct net_device *netdev) } /** - * fcoe_destroy- handles the destroy from sysfs + * fcoe_destroy() - handles the destroy from sysfs * @buffer: expcted to be a eth if name * @kp: associated kernel param * * Returns: 0 for success - **/ + */ static int fcoe_destroy(const char *buffer, struct kernel_param *kp) { int rc; @@ -1051,12 +1051,12 @@ out_nodev: } /** - * fcoe_create - handles the create call from sysfs + * fcoe_create() - Handles the create call from sysfs * @buffer: expcted to be a eth if name * @kp: associated kernel param * * Returns: 0 for success - **/ + */ static int fcoe_create(const char *buffer, struct kernel_param *kp) { int rc; @@ -1097,8 +1097,8 @@ module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR); __MODULE_PARM_TYPE(destroy, "string"); MODULE_PARM_DESC(destroy, "Destroy fcoe port"); -/* - * fcoe_link_ok - check if link is ok for the fc_lport +/** + * fcoe_link_ok() - Check if link is ok for the fc_lport * @lp: ptr to the fc_lport * * Any permanently-disqualifying conditions have been previously checked. @@ -1142,9 +1142,8 @@ int fcoe_link_ok(struct fc_lport *lp) } EXPORT_SYMBOL_GPL(fcoe_link_ok); -/* - * fcoe_percpu_clean - frees skb of the corresponding lport from the per - * cpu queue. +/** + * fcoe_percpu_clean() - Clear the pending skbs for an lport * @lp: the fc_lport */ void fcoe_percpu_clean(struct fc_lport *lp) @@ -1178,11 +1177,11 @@ void fcoe_percpu_clean(struct fc_lport *lp) EXPORT_SYMBOL_GPL(fcoe_percpu_clean); /** - * fcoe_clean_pending_queue - dequeue skb and free it + * fcoe_clean_pending_queue() - Dequeue a skb and free it * @lp: the corresponding fc_lport * * Returns: none - **/ + */ void fcoe_clean_pending_queue(struct fc_lport *lp) { struct fcoe_softc *fc = lport_priv(lp); @@ -1199,12 +1198,12 @@ void fcoe_clean_pending_queue(struct fc_lport *lp) EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue); /** - * libfc_host_alloc - allocate a Scsi_Host with room for the fc_lport + * libfc_host_alloc() - Allocate a Scsi_Host with room for the fc_lport * @sht: ptr to the scsi host templ * @priv_size: size of private data after fc_lport * * Returns: ptr to Scsi_Host - * TODO - to libfc? + * TODO: to libfc? */ static inline struct Scsi_Host *libfc_host_alloc( struct scsi_host_template *sht, int priv_size) @@ -1213,7 +1212,7 @@ static inline struct Scsi_Host *libfc_host_alloc( } /** - * fcoe_host_alloc - allocate a Scsi_Host with room for the fcoe_softc + * fcoe_host_alloc() - Allocate a Scsi_Host with room for the fcoe_softc * @sht: ptr to the scsi host templ * @priv_size: size of private data after fc_lport * @@ -1225,8 +1224,8 @@ struct Scsi_Host *fcoe_host_alloc(struct scsi_host_template *sht, int priv_size) } EXPORT_SYMBOL_GPL(fcoe_host_alloc); -/* - * fcoe_reset - resets the fcoe +/** + * fcoe_reset() - Resets the fcoe * @shost: shost the reset is from * * Returns: always 0 @@ -1239,8 +1238,8 @@ int fcoe_reset(struct Scsi_Host *shost) } EXPORT_SYMBOL_GPL(fcoe_reset); -/* - * fcoe_wwn_from_mac - converts 48-bit IEEE MAC address to 64-bit FC WWN. +/** + * fcoe_wwn_from_mac() - Converts 48-bit IEEE MAC address to 64-bit FC WWN. * @mac: mac address * @scheme: check port * @port: port indicator for converting @@ -1279,8 +1278,9 @@ u64 fcoe_wwn_from_mac(unsigned char mac[MAX_ADDR_LEN], return wwn; } EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac); -/* - * fcoe_hostlist_lookup_softc - find the corresponding lport by a given device + +/** + * fcoe_hostlist_lookup_softc() - find the corresponding lport by a given device * @device: this is currently ptr to net_device * * Returns: NULL or the located fcoe_softc @@ -1301,8 +1301,8 @@ static struct fcoe_softc *fcoe_hostlist_lookup_softc( return NULL; } -/* - * fcoe_hostlist_lookup - find the corresponding lport by netdev +/** + * fcoe_hostlist_lookup() - Find the corresponding lport by netdev * @netdev: ptr to net_device * * Returns: 0 for success @@ -1317,8 +1317,8 @@ struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev) } EXPORT_SYMBOL_GPL(fcoe_hostlist_lookup); -/* - * fcoe_hostlist_add - add a lport to lports list +/** + * fcoe_hostlist_add() - Add a lport to lports list * @lp: ptr to the fc_lport to badded * * Returns: 0 for success @@ -1338,8 +1338,8 @@ int fcoe_hostlist_add(const struct fc_lport *lp) } EXPORT_SYMBOL_GPL(fcoe_hostlist_add); -/* - * fcoe_hostlist_remove - remove a lport from lports list +/** + * fcoe_hostlist_remove() - remove a lport from lports list * @lp: ptr to the fc_lport to badded * * Returns: 0 for success @@ -1359,12 +1359,12 @@ int fcoe_hostlist_remove(const struct fc_lport *lp) EXPORT_SYMBOL_GPL(fcoe_hostlist_remove); /** - * fcoe_libfc_config - sets up libfc related properties for lport + * fcoe_libfc_config() - sets up libfc related properties for lport * @lp: ptr to the fc_lport * @tt: libfc function template * * Returns : 0 for success - **/ + */ int fcoe_libfc_config(struct fc_lport *lp, struct libfc_function_template *tt) { /* Set the function pointers set by the LLDD */ @@ -1382,14 +1382,14 @@ int fcoe_libfc_config(struct fc_lport *lp, struct libfc_function_template *tt) EXPORT_SYMBOL_GPL(fcoe_libfc_config); /** - * fcoe_init - fcoe module loading initialization + * fcoe_init() - fcoe module loading initialization * * Initialization routine * 1. Will create fc transport software structure * 2. initialize the link list of port information structure * * Returns 0 on success, negative on failure - **/ + */ static int __init fcoe_init(void) { int cpu; @@ -1452,10 +1452,10 @@ static int __init fcoe_init(void) module_init(fcoe_init); /** - * fcoe_exit - fcoe module unloading cleanup + * fcoe_exit() - fcoe module unloading cleanup * * Returns 0 on success, negative on failure - **/ + */ static void __exit fcoe_exit(void) { u32 idx; diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index cfbce893941..e57556ea5b4 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -64,7 +64,7 @@ static void fc_disc_single(struct fc_disc *, struct fc_disc_port *); static void fc_disc_restart(struct fc_disc *); /** - * fc_disc_lookup_rport - lookup a remote port by port_id + * fc_disc_lookup_rport() - lookup a remote port by port_id * @lport: Fibre Channel host port instance * @port_id: remote port port_id to match */ @@ -92,7 +92,7 @@ struct fc_rport *fc_disc_lookup_rport(const struct fc_lport *lport, } /** - * fc_disc_stop_rports - delete all the remote ports associated with the lport + * fc_disc_stop_rports() - delete all the remote ports associated with the lport * @disc: The discovery job to stop rports on * * Locking Note: This function expects that the lport mutex is locked before @@ -117,7 +117,7 @@ void fc_disc_stop_rports(struct fc_disc *disc) } /** - * fc_disc_rport_callback - Event handler for rport events + * fc_disc_rport_callback() - Event handler for rport events * @lport: The lport which is receiving the event * @rport: The rport which the event has occured on * @event: The event that occured @@ -151,7 +151,7 @@ static void fc_disc_rport_callback(struct fc_lport *lport, } /** - * fc_disc_recv_rscn_req - Handle Registered State Change Notification (RSCN) + * fc_disc_recv_rscn_req() - Handle Registered State Change Notification (RSCN) * @sp: Current sequence of the RSCN exchange * @fp: RSCN Frame * @lport: Fibre Channel host port instance @@ -265,7 +265,7 @@ reject: } /** - * fc_disc_recv_req - Handle incoming requests + * fc_disc_recv_req() - Handle incoming requests * @sp: Current sequence of the request exchange * @fp: The frame * @lport: The FC local port @@ -294,7 +294,7 @@ static void fc_disc_recv_req(struct fc_seq *sp, struct fc_frame *fp, } /** - * fc_disc_restart - Restart discovery + * fc_disc_restart() - Restart discovery * @lport: FC discovery context * * Locking Note: This function expects that the disc mutex @@ -322,7 +322,7 @@ static void fc_disc_restart(struct fc_disc *disc) } /** - * fc_disc_start - Fibre Channel Target discovery + * fc_disc_start() - Fibre Channel Target discovery * @lport: FC local port * * Returns non-zero if discovery cannot be started. @@ -383,7 +383,7 @@ static struct fc_rport_operations fc_disc_rport_ops = { }; /** - * fc_disc_new_target - Handle new target found by discovery + * fc_disc_new_target() - Handle new target found by discovery * @lport: FC local port * @rport: The previous FC remote port (NULL if new remote port) * @ids: Identifiers for the new FC remote port @@ -446,7 +446,7 @@ static int fc_disc_new_target(struct fc_disc *disc, } /** - * fc_disc_del_target - Delete a target + * fc_disc_del_target() - Delete a target * @disc: FC discovery context * @rport: The remote port to be removed */ @@ -459,7 +459,7 @@ static void fc_disc_del_target(struct fc_disc *disc, struct fc_rport *rport) } /** - * fc_disc_done - Discovery has been completed + * fc_disc_done() - Discovery has been completed * @disc: FC discovery context */ static void fc_disc_done(struct fc_disc *disc) @@ -479,7 +479,7 @@ static void fc_disc_done(struct fc_disc *disc) } /** - * fc_disc_error - Handle error on dNS request + * fc_disc_error() - Handle error on dNS request * @disc: FC discovery context * @fp: The frame pointer */ @@ -519,7 +519,7 @@ static void fc_disc_error(struct fc_disc *disc, struct fc_frame *fp) } /** - * fc_disc_gpn_ft_req - Send Get Port Names by FC-4 type (GPN_FT) request + * fc_disc_gpn_ft_req() - Send Get Port Names by FC-4 type (GPN_FT) request * @lport: FC discovery context * * Locking Note: This function expects that the disc_mutex is locked @@ -553,7 +553,7 @@ err: } /** - * fc_disc_gpn_ft_parse - Parse the list of IDs and names resulting from a request + * fc_disc_gpn_ft_parse() - Parse the list of IDs and names resulting from a request * @lport: Fibre Channel host port instance * @buf: GPN_FT response buffer * @len: size of response buffer @@ -658,7 +658,10 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len) return error; } -/* +/** + * fc_disc_timeout() - Retry handler for the disc component + * @work: Structure holding disc obj that needs retry discovery + * * Handle retry of memory allocation for remote ports. */ static void fc_disc_timeout(struct work_struct *work) @@ -673,7 +676,7 @@ static void fc_disc_timeout(struct work_struct *work) } /** - * fc_disc_gpn_ft_resp - Handle a response frame from Get Port Names (GPN_FT) + * fc_disc_gpn_ft_resp() - Handle a response frame from Get Port Names (GPN_FT) * @sp: Current sequence of GPN_FT exchange * @fp: response frame * @lp_arg: Fibre Channel host port instance @@ -712,9 +715,7 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp, fr_len(fp)); } else if (ntohs(cp->ct_cmd) == FC_FS_ACC) { - /* - * Accepted. Parse response. - */ + /* Accepted, parse the response. */ buf = cp + 1; len -= sizeof(*cp); } else if (ntohs(cp->ct_cmd) == FC_FS_RJT) { @@ -746,7 +747,7 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp, } /** - * fc_disc_single - Discover the directory information for a single target + * fc_disc_single() - Discover the directory information for a single target * @lport: FC local port * @dp: The port to rediscover * @@ -782,7 +783,7 @@ out: } /** - * fc_disc_stop - Stop discovery for a given lport + * fc_disc_stop() - Stop discovery for a given lport * @lport: The lport that discovery should stop for */ void fc_disc_stop(struct fc_lport *lport) @@ -796,7 +797,7 @@ void fc_disc_stop(struct fc_lport *lport) } /** - * fc_disc_stop_final - Stop discovery for a given lport + * fc_disc_stop_final() - Stop discovery for a given lport * @lport: The lport that discovery should stop for * * This function will block until discovery has been @@ -809,7 +810,7 @@ void fc_disc_stop_final(struct fc_lport *lport) } /** - * fc_disc_init - Initialize the discovery block + * fc_disc_init() - Initialize the discovery block * @lport: FC local port */ int fc_disc_init(struct fc_lport *lport) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index ecc72612c38..2a631d7dbce 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -161,7 +161,7 @@ static struct fc_fcp_pkt *fc_fcp_pkt_alloc(struct fc_lport *lp, gfp_t gfp) } /** - * fc_fcp_pkt_release - release hold on scsi_pkt packet + * fc_fcp_pkt_release() - release hold on scsi_pkt packet * @fsp: fcp packet struct * * This is used by upper layer scsi driver. @@ -183,8 +183,7 @@ static void fc_fcp_pkt_hold(struct fc_fcp_pkt *fsp) } /** - * fc_fcp_pkt_destory - release hold on scsi_pkt packet - * + * fc_fcp_pkt_destory() - release hold on scsi_pkt packet * @seq: exchange sequence * @fsp: fcp packet struct * @@ -199,7 +198,7 @@ static void fc_fcp_pkt_destroy(struct fc_seq *seq, void *fsp) } /** - * fc_fcp_lock_pkt - lock a packet and get a ref to it. + * fc_fcp_lock_pkt() - lock a packet and get a ref to it. * @fsp: fcp packet * * We should only return error if we return a command to scsi-ml before @@ -291,9 +290,7 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp) buf = fc_frame_payload_get(fp, 0); if (offset + len > fsp->data_len) { - /* - * this should never happen - */ + /* this should never happen */ if ((fr_flags(fp) & FCPHF_CRC_UNCHECKED) && fc_frame_crc_check(fp)) goto crc_err; @@ -387,8 +384,8 @@ crc_err: fc_fcp_complete_locked(fsp); } -/* - * fc_fcp_send_data - Send SCSI data to target. +/** + * fc_fcp_send_data() - Send SCSI data to target. * @fsp: ptr to fc_fcp_pkt * @sp: ptr to this sequence * @offset: starting offset for this data request @@ -610,8 +607,8 @@ static void fc_fcp_abts_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) } } -/* - * fc_fcp_reduce_can_queue - drop can_queue +/** + * fc_fcp_reduce_can_queue() - drop can_queue * @lp: lport to drop queueing for * * If we are getting memory allocation failures, then we may @@ -642,9 +639,11 @@ done: spin_unlock_irqrestore(lp->host->host_lock, flags); } -/* - * exch mgr calls this routine to process scsi - * exchanges. +/** + * fc_fcp_recv() - Reveive FCP frames + * @seq: The sequence the frame is on + * @fp: The FC frame + * @arg: The related FCP packet * * Return : None * Context : called from Soft IRQ context @@ -832,7 +831,7 @@ err: } /** - * fc_fcp_complete_locked - complete processing of a fcp packet + * fc_fcp_complete_locked() - complete processing of a fcp packet * @fsp: fcp packet * * This function may sleep if a timer is pending. The packet lock must be @@ -900,7 +899,7 @@ static void fc_fcp_cleanup_cmd(struct fc_fcp_pkt *fsp, int error) } /** - * fc_fcp_cleanup_each_cmd - run fn on each active command + * fc_fcp_cleanup_each_cmd() - Cleanup active commads * @lp: logical port * @id: target id * @lun: lun @@ -952,7 +951,7 @@ static void fc_fcp_abort_io(struct fc_lport *lp) } /** - * fc_fcp_pkt_send - send a fcp packet to the lower level. + * fc_fcp_pkt_send() - send a fcp packet to the lower level. * @lp: fc lport * @fsp: fc packet. * @@ -1727,7 +1726,7 @@ out: EXPORT_SYMBOL(fc_queuecommand); /** - * fc_io_compl - Handle responses for completed commands + * fc_io_compl() - Handle responses for completed commands * @fsp: scsi packet * * Translates a error to a Linux SCSI error. @@ -1857,7 +1856,7 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) } /** - * fc_fcp_complete - complete processing of a fcp packet + * fc_fcp_complete() - complete processing of a fcp packet * @fsp: fcp packet * * This function may sleep if a fsp timer is pending. @@ -1874,9 +1873,10 @@ void fc_fcp_complete(struct fc_fcp_pkt *fsp) EXPORT_SYMBOL(fc_fcp_complete); /** - * fc_eh_abort - Abort a command...from scsi host template + * fc_eh_abort() - Abort a command * @sc_cmd: scsi command to abort * + * From scsi host template. * send ABTS to the target device and wait for the response * sc_cmd is the pointer to the command to be aborted. */ @@ -1920,7 +1920,7 @@ release_pkt: EXPORT_SYMBOL(fc_eh_abort); /** - * fc_eh_device_reset: Reset a single LUN + * fc_eh_device_reset() Reset a single LUN * @sc_cmd: scsi command * * Set from scsi host template to send tm cmd to the target and wait for the @@ -1973,7 +1973,7 @@ out: EXPORT_SYMBOL(fc_eh_device_reset); /** - * fc_eh_host_reset - The reset function will reset the ports on the host. + * fc_eh_host_reset() - The reset function will reset the ports on the host. * @sc_cmd: scsi command */ int fc_eh_host_reset(struct scsi_cmnd *sc_cmd) @@ -1999,7 +1999,7 @@ int fc_eh_host_reset(struct scsi_cmnd *sc_cmd) EXPORT_SYMBOL(fc_eh_host_reset); /** - * fc_slave_alloc - configure queue depth + * fc_slave_alloc() - configure queue depth * @sdev: scsi device * * Configures queue depth based on host's cmd_per_len. If not set diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index c00de2244c7..2ae50a1188e 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -139,7 +139,7 @@ static int fc_frame_drop(struct fc_lport *lport, struct fc_frame *fp) } /** - * fc_lport_rport_callback - Event handler for rport events + * fc_lport_rport_callback() - Event handler for rport events * @lport: The lport which is receiving the event * @rport: The rport which the event has occured on * @event: The event that occured @@ -195,7 +195,7 @@ static void fc_lport_rport_callback(struct fc_lport *lport, } /** - * fc_lport_state - Return a string which represents the lport's state + * fc_lport_state() - Return a string which represents the lport's state * @lport: The lport whose state is to converted to a string */ static const char *fc_lport_state(struct fc_lport *lport) @@ -209,7 +209,7 @@ static const char *fc_lport_state(struct fc_lport *lport) } /** - * fc_lport_ptp_setup - Create an rport for point-to-point mode + * fc_lport_ptp_setup() - Create an rport for point-to-point mode * @lport: The lport to attach the ptp rport to * @fid: The FID of the ptp rport * @remote_wwpn: The WWPN of the ptp rport @@ -351,7 +351,7 @@ static void fc_lport_add_fc4_type(struct fc_lport *lport, enum fc_fh_type type) } /** - * fc_lport_recv_rlir_req - Handle received Registered Link Incident Report. + * fc_lport_recv_rlir_req() - Handle received Registered Link Incident Report. * @lport: Fibre Channel local port recieving the RLIR * @sp: current sequence in the RLIR exchange * @fp: RLIR request frame @@ -370,7 +370,7 @@ static void fc_lport_recv_rlir_req(struct fc_seq *sp, struct fc_frame *fp, } /** - * fc_lport_recv_echo_req - Handle received ECHO request + * fc_lport_recv_echo_req() - Handle received ECHO request * @lport: Fibre Channel local port recieving the ECHO * @sp: current sequence in the ECHO exchange * @fp: ECHO request frame @@ -412,7 +412,7 @@ static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp, } /** - * fc_lport_recv_echo_req - Handle received Request Node ID data request + * fc_lport_recv_echo_req() - Handle received Request Node ID data request * @lport: Fibre Channel local port recieving the RNID * @sp: current sequence in the RNID exchange * @fp: RNID request frame @@ -479,7 +479,7 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, } /** - * fc_lport_recv_adisc_req - Handle received Address Discovery Request + * fc_lport_recv_adisc_req() - Handle received Address Discovery Request * @lport: Fibre Channel local port recieving the ADISC * @sp: current sequence in the ADISC exchange * @fp: ADISC request frame @@ -529,7 +529,7 @@ static void fc_lport_recv_adisc_req(struct fc_seq *sp, struct fc_frame *in_fp, } /** - * fc_lport_recv_logo_req - Handle received fabric LOGO request + * fc_lport_recv_logo_req() - Handle received fabric LOGO request * @lport: Fibre Channel local port recieving the LOGO * @sp: current sequence in the LOGO exchange * @fp: LOGO request frame @@ -546,7 +546,7 @@ static void fc_lport_recv_logo_req(struct fc_seq *sp, struct fc_frame *fp, } /** - * fc_fabric_login - Start the lport state machine + * fc_fabric_login() - Start the lport state machine * @lport: The lport that should log into the fabric * * Locking Note: This function should not be called @@ -568,7 +568,7 @@ int fc_fabric_login(struct fc_lport *lport) EXPORT_SYMBOL(fc_fabric_login); /** - * fc_linkup - Handler for transport linkup events + * fc_linkup() - Handler for transport linkup events * @lport: The lport whose link is up */ void fc_linkup(struct fc_lport *lport) @@ -588,7 +588,7 @@ void fc_linkup(struct fc_lport *lport) EXPORT_SYMBOL(fc_linkup); /** - * fc_linkdown - Handler for transport linkdown events + * fc_linkdown() - Handler for transport linkdown events * @lport: The lport whose link is down */ void fc_linkdown(struct fc_lport *lport) @@ -607,12 +607,12 @@ void fc_linkdown(struct fc_lport *lport) EXPORT_SYMBOL(fc_linkdown); /** - * fc_fabric_logoff - Logout of the fabric + * fc_fabric_logoff() - Logout of the fabric * @lport: fc_lport pointer to logoff the fabric * * Return value: * 0 for success, -1 for failure - **/ + */ int fc_fabric_logoff(struct fc_lport *lport) { lport->tt.disc_stop_final(lport); @@ -625,7 +625,7 @@ int fc_fabric_logoff(struct fc_lport *lport) EXPORT_SYMBOL(fc_fabric_logoff); /** - * fc_lport_destroy - unregister a fc_lport + * fc_lport_destroy() - unregister a fc_lport * @lport: fc_lport pointer to unregister * * Return value: @@ -635,7 +635,7 @@ EXPORT_SYMBOL(fc_fabric_logoff); * clean-up all the allocated memory * and free up other system resources. * - **/ + */ int fc_lport_destroy(struct fc_lport *lport) { lport->tt.frame_send = fc_frame_drop; @@ -646,15 +646,14 @@ int fc_lport_destroy(struct fc_lport *lport) EXPORT_SYMBOL(fc_lport_destroy); /** - * fc_set_mfs - sets up the mfs for the corresponding fc_lport + * fc_set_mfs() - sets up the mfs for the corresponding fc_lport * @lport: fc_lport pointer to unregister * @mfs: the new mfs for fc_lport * * Set mfs for the given fc_lport to the new mfs. * * Return: 0 for success - * - **/ + */ int fc_set_mfs(struct fc_lport *lport, u32 mfs) { unsigned int old_mfs; @@ -683,7 +682,7 @@ int fc_set_mfs(struct fc_lport *lport, u32 mfs) EXPORT_SYMBOL(fc_set_mfs); /** - * fc_lport_disc_callback - Callback for discovery events + * fc_lport_disc_callback() - Callback for discovery events * @lport: FC local port * @event: The discovery event */ @@ -708,7 +707,7 @@ void fc_lport_disc_callback(struct fc_lport *lport, enum fc_disc_event event) } /** - * fc_rport_enter_ready - Enter the ready state and start discovery + * fc_rport_enter_ready() - Enter the ready state and start discovery * @lport: Fibre Channel local port that is ready * * Locking Note: The lport lock is expected to be held before calling @@ -725,7 +724,7 @@ static void fc_lport_enter_ready(struct fc_lport *lport) } /** - * fc_lport_recv_flogi_req - Receive a FLOGI request + * fc_lport_recv_flogi_req() - Receive a FLOGI request * @sp_in: The sequence the FLOGI is on * @rx_fp: The frame the FLOGI is in * @lport: The lport that recieved the request @@ -815,7 +814,7 @@ out: } /** - * fc_lport_recv_req - The generic lport request handler + * fc_lport_recv_req() - The generic lport request handler * @lport: The lport that received the request * @sp: The sequence the request is on * @fp: The frame the request is in @@ -911,7 +910,7 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, } /** - * fc_lport_reset - Reset an lport + * fc_lport_reset() - Reset an lport * @lport: The lport which should be reset * * Locking Note: This functions should not be called with the @@ -928,7 +927,7 @@ int fc_lport_reset(struct fc_lport *lport) EXPORT_SYMBOL(fc_lport_reset); /** - * fc_rport_enter_reset - Reset the local port + * fc_rport_enter_reset() - Reset the local port * @lport: Fibre Channel local port to be reset * * Locking Note: The lport lock is expected to be held before calling @@ -960,7 +959,7 @@ static void fc_lport_enter_reset(struct fc_lport *lport) } /** - * fc_lport_error - Handler for any errors + * fc_lport_error() - Handler for any errors * @lport: The fc_lport object * @fp: The frame pointer * @@ -1007,8 +1006,8 @@ static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp) } /** - * fc_lport_rft_id_resp - Handle response to Register Fibre - * Channel Types by ID (RPN_ID) request + * fc_lport_rft_id_resp() - Handle response to Register Fibre + * Channel Types by ID (RPN_ID) request * @sp: current sequence in RPN_ID exchange * @fp: response frame * @lp_arg: Fibre Channel host port instance @@ -1059,8 +1058,8 @@ err: } /** - * fc_lport_rpn_id_resp - Handle response to Register Port - * Name by ID (RPN_ID) request + * fc_lport_rpn_id_resp() - Handle response to Register Port + * Name by ID (RPN_ID) request * @sp: current sequence in RPN_ID exchange * @fp: response frame * @lp_arg: Fibre Channel host port instance @@ -1111,7 +1110,7 @@ err: } /** - * fc_lport_scr_resp - Handle response to State Change Register (SCR) request + * fc_lport_scr_resp() - Handle response to State Change Register (SCR) request * @sp: current sequence in SCR exchange * @fp: response frame * @lp_arg: Fibre Channel lport port instance that sent the registration request @@ -1157,7 +1156,7 @@ err: } /** - * fc_lport_enter_scr - Send a State Change Register (SCR) request + * fc_lport_enter_scr() - Send a State Change Register (SCR) request * @lport: Fibre Channel local port to register for state changes * * Locking Note: The lport lock is expected to be held before calling @@ -1184,7 +1183,7 @@ static void fc_lport_enter_scr(struct fc_lport *lport) } /** - * fc_lport_enter_rft_id - Register FC4-types with the name server + * fc_lport_enter_rft_id() - Register FC4-types with the name server * @lport: Fibre Channel local port to register * * Locking Note: The lport lock is expected to be held before calling @@ -1226,7 +1225,7 @@ static void fc_lport_enter_rft_id(struct fc_lport *lport) } /** - * fc_rport_enter_rft_id - Register port name with the name server + * fc_rport_enter_rft_id() - Register port name with the name server * @lport: Fibre Channel local port to register * * Locking Note: The lport lock is expected to be held before calling @@ -1259,7 +1258,7 @@ static struct fc_rport_operations fc_lport_rport_ops = { }; /** - * fc_rport_enter_dns - Create a rport to the name server + * fc_rport_enter_dns() - Create a rport to the name server * @lport: Fibre Channel local port requesting a rport for the name server * * Locking Note: The lport lock is expected to be held before calling @@ -1296,7 +1295,7 @@ err: } /** - * fc_lport_timeout - Handler for the retry_work timer. + * fc_lport_timeout() - Handler for the retry_work timer. * @work: The work struct of the fc_lport */ static void fc_lport_timeout(struct work_struct *work) @@ -1337,7 +1336,7 @@ static void fc_lport_timeout(struct work_struct *work) } /** - * fc_lport_logo_resp - Handle response to LOGO request + * fc_lport_logo_resp() - Handle response to LOGO request * @sp: current sequence in LOGO exchange * @fp: response frame * @lp_arg: Fibre Channel lport port instance that sent the LOGO request @@ -1383,7 +1382,7 @@ err: } /** - * fc_rport_enter_logo - Logout of the fabric + * fc_rport_enter_logo() - Logout of the fabric * @lport: Fibre Channel local port to be logged out * * Locking Note: The lport lock is expected to be held before calling @@ -1415,7 +1414,7 @@ static void fc_lport_enter_logo(struct fc_lport *lport) } /** - * fc_lport_flogi_resp - Handle response to FLOGI request + * fc_lport_flogi_resp() - Handle response to FLOGI request * @sp: current sequence in FLOGI exchange * @fp: response frame * @lp_arg: Fibre Channel lport port instance that sent the FLOGI request @@ -1510,7 +1509,7 @@ err: } /** - * fc_rport_enter_flogi - Send a FLOGI request to the fabric manager + * fc_rport_enter_flogi() - Send a FLOGI request to the fabric manager * @lport: Fibre Channel local port to be logged in to the fabric * * Locking Note: The lport lock is expected to be held before calling diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 4f23a9bb15a..6f07de15c49 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -146,7 +146,7 @@ struct fc_rport *fc_rport_rogue_create(struct fc_disc_port *dp) } /** - * fc_rport_state - return a string for the state the rport is in + * fc_rport_state() - return a string for the state the rport is in * @rport: The rport whose state we want to get a string for */ static const char *fc_rport_state(struct fc_rport *rport) @@ -161,7 +161,7 @@ static const char *fc_rport_state(struct fc_rport *rport) } /** - * fc_set_rport_loss_tmo - Set the remote port loss timeout in seconds. + * fc_set_rport_loss_tmo() - Set the remote port loss timeout in seconds. * @rport: Pointer to Fibre Channel remote port structure * @timeout: timeout in seconds */ @@ -175,7 +175,7 @@ void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout) EXPORT_SYMBOL(fc_set_rport_loss_tmo); /** - * fc_plogi_get_maxframe - Get max payload from the common service parameters + * fc_plogi_get_maxframe() - Get max payload from the common service parameters * @flp: FLOGI payload structure * @maxval: upper limit, may be less than what is in the service parameters */ @@ -198,7 +198,7 @@ fc_plogi_get_maxframe(struct fc_els_flogi *flp, unsigned int maxval) } /** - * fc_rport_state_enter - Change the rport's state + * fc_rport_state_enter() - Change the rport's state * @rport: The rport whose state should change * @new: The new state of the rport * @@ -292,7 +292,7 @@ static void fc_rport_work(struct work_struct *work) } /** - * fc_rport_login - Start the remote port login state machine + * fc_rport_login() - Start the remote port login state machine * @rport: Fibre Channel remote port * * Locking Note: Called without the rport lock held. This @@ -315,7 +315,7 @@ int fc_rport_login(struct fc_rport *rport) } /** - * fc_rport_logoff - Logoff and remove an rport + * fc_rport_logoff() - Logoff and remove an rport * @rport: Fibre Channel remote port to be removed * * Locking Note: Called without the rport lock held. This @@ -353,7 +353,7 @@ int fc_rport_logoff(struct fc_rport *rport) } /** - * fc_rport_enter_ready - The rport is ready + * fc_rport_enter_ready() - The rport is ready * @rport: Fibre Channel remote port that is ready * * Locking Note: The rport lock is expected to be held before calling @@ -372,7 +372,7 @@ static void fc_rport_enter_ready(struct fc_rport *rport) } /** - * fc_rport_timeout - Handler for the retry_work timer. + * fc_rport_timeout() - Handler for the retry_work timer. * @work: The work struct of the fc_rport_libfc_priv * * Locking Note: Called without the rport lock held. This @@ -411,7 +411,7 @@ static void fc_rport_timeout(struct work_struct *work) } /** - * fc_rport_error - Error handler, called once retries have been exhausted + * fc_rport_error() - Error handler, called once retries have been exhausted * @rport: The fc_rport object * @fp: The frame pointer * @@ -444,7 +444,7 @@ static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp) } /** - * fc_rport_error_retry - Error handler when retries are desired + * fc_rport_error_retry() - Error handler when retries are desired * @rport: The fc_rport object * @fp: The frame pointer * @@ -479,7 +479,7 @@ static void fc_rport_error_retry(struct fc_rport *rport, struct fc_frame *fp) } /** - * fc_rport_plogi_recv_resp - Handle incoming ELS PLOGI response + * fc_rport_plogi_recv_resp() - Handle incoming ELS PLOGI response * @sp: current sequence in the PLOGI exchange * @fp: response frame * @rp_arg: Fibre Channel remote port @@ -554,7 +554,7 @@ err: } /** - * fc_rport_enter_plogi - Send Port Login (PLOGI) request to peer + * fc_rport_enter_plogi() - Send Port Login (PLOGI) request to peer * @rport: Fibre Channel remote port to send PLOGI to * * Locking Note: The rport lock is expected to be held before calling @@ -587,7 +587,7 @@ static void fc_rport_enter_plogi(struct fc_rport *rport) } /** - * fc_rport_prli_resp - Process Login (PRLI) response handler + * fc_rport_prli_resp() - Process Login (PRLI) response handler * @sp: current sequence in the PRLI exchange * @fp: response frame * @rp_arg: Fibre Channel remote port @@ -657,7 +657,7 @@ err: } /** - * fc_rport_logo_resp - Logout (LOGO) response handler + * fc_rport_logo_resp() - Logout (LOGO) response handler * @sp: current sequence in the LOGO exchange * @fp: response frame * @rp_arg: Fibre Channel remote port @@ -706,7 +706,7 @@ err: } /** - * fc_rport_enter_prli - Send Process Login (PRLI) request to peer + * fc_rport_enter_prli() - Send Process Login (PRLI) request to peer * @rport: Fibre Channel remote port to send PRLI to * * Locking Note: The rport lock is expected to be held before calling @@ -741,7 +741,7 @@ static void fc_rport_enter_prli(struct fc_rport *rport) } /** - * fc_rport_els_rtv_resp - Request Timeout Value response handler + * fc_rport_els_rtv_resp() - Request Timeout Value response handler * @sp: current sequence in the RTV exchange * @fp: response frame * @rp_arg: Fibre Channel remote port @@ -807,7 +807,7 @@ err: } /** - * fc_rport_enter_rtv - Send Request Timeout Value (RTV) request to peer + * fc_rport_enter_rtv() - Send Request Timeout Value (RTV) request to peer * @rport: Fibre Channel remote port to send RTV to * * Locking Note: The rport lock is expected to be held before calling @@ -838,7 +838,7 @@ static void fc_rport_enter_rtv(struct fc_rport *rport) } /** - * fc_rport_enter_logo - Send Logout (LOGO) request to peer + * fc_rport_enter_logo() - Send Logout (LOGO) request to peer * @rport: Fibre Channel remote port to send LOGO to * * Locking Note: The rport lock is expected to be held before calling @@ -870,7 +870,7 @@ static void fc_rport_enter_logo(struct fc_rport *rport) /** - * fc_rport_recv_req - Receive a request from a rport + * fc_rport_recv_req() - Receive a request from a rport * @sp: current sequence in the PLOGI exchange * @fp: response frame * @rp_arg: Fibre Channel remote port @@ -931,7 +931,7 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp, } /** - * fc_rport_recv_plogi_req - Handle incoming Port Login (PLOGI) request + * fc_rport_recv_plogi_req() - Handle incoming Port Login (PLOGI) request * @rport: Fibre Channel remote port that initiated PLOGI * @sp: current sequence in the PLOGI exchange * @fp: PLOGI request frame @@ -1053,7 +1053,7 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport, } /** - * fc_rport_recv_prli_req - Handle incoming Process Login (PRLI) request + * fc_rport_recv_prli_req() - Handle incoming Process Login (PRLI) request * @rport: Fibre Channel remote port that initiated PRLI * @sp: current sequence in the PRLI exchange * @fp: PRLI request frame @@ -1204,7 +1204,7 @@ static void fc_rport_recv_prli_req(struct fc_rport *rport, } /** - * fc_rport_recv_prlo_req - Handle incoming Process Logout (PRLO) request + * fc_rport_recv_prlo_req() - Handle incoming Process Logout (PRLO) request * @rport: Fibre Channel remote port that initiated PRLO * @sp: current sequence in the PRLO exchange * @fp: PRLO request frame @@ -1235,7 +1235,7 @@ static void fc_rport_recv_prlo_req(struct fc_rport *rport, struct fc_seq *sp, } /** - * fc_rport_recv_logo_req - Handle incoming Logout (LOGO) request + * fc_rport_recv_logo_req() - Handle incoming Logout (LOGO) request * @rport: Fibre Channel remote port that initiated LOGO * @sp: current sequence in the LOGO exchange * @fp: LOGO request frame diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 282829cdf35..a2e126b86e3 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -665,7 +665,7 @@ struct fc_lport { struct delayed_work disc_work; }; -/** +/* * FC_LPORT HELPER FUNCTIONS *****************************/ static inline void *lport_priv(const struct fc_lport *lp) @@ -697,7 +697,7 @@ static inline void fc_lport_state_enter(struct fc_lport *lp, } -/** +/* * LOCAL PORT LAYER *****************************/ int fc_lport_init(struct fc_lport *lp); @@ -747,19 +747,19 @@ int fc_lport_reset(struct fc_lport *); int fc_set_mfs(struct fc_lport *lp, u32 mfs); -/** +/* * REMOTE PORT LAYER *****************************/ int fc_rport_init(struct fc_lport *lp); void fc_rport_terminate_io(struct fc_rport *rp); -/** +/* * DISCOVERY LAYER *****************************/ int fc_disc_init(struct fc_lport *lp); -/** +/* * SCSI LAYER *****************************/ /* @@ -820,7 +820,7 @@ int fc_change_queue_type(struct scsi_device *sdev, int tag_type); */ void fc_fcp_destroy(struct fc_lport *); -/** +/* * ELS/CT interface *****************************/ /* @@ -829,7 +829,7 @@ void fc_fcp_destroy(struct fc_lport *); int fc_elsct_init(struct fc_lport *lp); -/** +/* * EXCHANGE MANAGER LAYER *****************************/ /* -- GitLab From b2ab99c9a300e572105d6db7f6efe0a4d1572167 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:55:50 -0800 Subject: [PATCH 3033/4982] [SCSI] libfc, fcoe: Cleanup function formatting and minor typos 1) There were a few functions with a strange layout, i.e. all arguments on the second line, when not necessary. Where ever possible I moved the return value to the same line as the function name. However, when the line was too long to have a single argument on the same line I moved the return value to above line. For example: (, ) and (, ) 2) Removed one extra whitespace line 3) Fixed two typos Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fc_transport_fcoe.c | 11 ++++++----- drivers/scsi/fcoe/libfcoe.c | 15 +++++++-------- drivers/scsi/libfc/fc_exch.c | 10 +++++----- drivers/scsi/libfc/fc_rport.c | 4 ++-- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/fcoe/fc_transport_fcoe.c b/drivers/scsi/fcoe/fc_transport_fcoe.c index 0eea4c434c3..847453a70c6 100644 --- a/drivers/scsi/fcoe/fc_transport_fcoe.c +++ b/drivers/scsi/fcoe/fc_transport_fcoe.c @@ -62,8 +62,9 @@ struct pci_dev *fcoe_transport_pcidev(const struct net_device *netdev) * * Returns: 0 for success */ -static struct fcoe_transport_internal *fcoe_transport_device_lookup( - struct fcoe_transport *t, struct net_device *netdev) +static struct fcoe_transport_internal * +fcoe_transport_device_lookup(struct fcoe_transport *t, + struct net_device *netdev) { struct fcoe_transport_internal *ti; @@ -184,7 +185,7 @@ static void fcoe_transport_device_remove_all(struct fcoe_transport *t) * Returns: true for match up */ static bool fcoe_transport_match(struct fcoe_transport *t, - struct net_device *netdev) + struct net_device *netdev) { /* match transport by vendor and device id */ struct pci_dev *pci; @@ -217,8 +218,8 @@ static bool fcoe_transport_match(struct fcoe_transport *t, * * TODO: return default sw transport if no other transport is found */ -static struct fcoe_transport *fcoe_transport_lookup( - struct net_device *netdev) +static struct fcoe_transport * +fcoe_transport_lookup(struct net_device *netdev) { struct fcoe_transport *t; diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 5e68652985b..d006d657681 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -949,8 +949,8 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer) * * Returns: ptr to the struct module, NULL for failure */ -static struct module *fcoe_netdev_to_module_owner( - const struct net_device *netdev) +static struct module * +fcoe_netdev_to_module_owner(const struct net_device *netdev) { struct device *dev; @@ -1205,8 +1205,8 @@ EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue); * Returns: ptr to Scsi_Host * TODO: to libfc? */ -static inline struct Scsi_Host *libfc_host_alloc( - struct scsi_host_template *sht, int priv_size) +static inline struct Scsi_Host * +libfc_host_alloc(struct scsi_host_template *sht, int priv_size) { return scsi_host_alloc(sht, sizeof(struct fc_lport) + priv_size); } @@ -1285,8 +1285,8 @@ EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac); * * Returns: NULL or the located fcoe_softc */ -static struct fcoe_softc *fcoe_hostlist_lookup_softc( - const struct net_device *dev) +static struct fcoe_softc * +fcoe_hostlist_lookup_softc(const struct net_device *dev) { struct fcoe_softc *fc; @@ -1426,7 +1426,6 @@ static int __init fcoe_init(void) } else { fcoe_percpu[cpu] = NULL; kfree(p); - } } } @@ -1476,7 +1475,7 @@ static void __exit fcoe_exit(void) */ del_timer_sync(&fcoe_timer); - /* releases the assocaited fcoe transport for each lport */ + /* releases the associated fcoe transport for each lport */ list_for_each_entry_safe(fc, tmp, &fcoe_hostlist, list) fcoe_transport_release(fc->real_dev); diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 8c4018956d4..7b933954c10 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -675,8 +675,8 @@ static struct fc_exch *fc_exch_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) * If fc_pf_rjt_reason is FC_RJT_NONE then this function will have a hold * on the ep that should be released by the caller. */ -static enum fc_pf_rjt_reason -fc_seq_lookup_recip(struct fc_exch_mgr *mp, struct fc_frame *fp) +static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_exch_mgr *mp, + struct fc_frame *fp) { struct fc_frame_header *fh = fc_frame_header_get(fp); struct fc_exch *ep = NULL; @@ -994,9 +994,9 @@ static void fc_seq_send_ack(struct fc_seq *sp, const struct fc_frame *rx_fp) * Send BLS Reject. * This is for rejecting BA_ABTS only. */ -static void -fc_exch_send_ba_rjt(struct fc_frame *rx_fp, enum fc_ba_rjt_reason reason, - enum fc_ba_rjt_explan explan) +static void fc_exch_send_ba_rjt(struct fc_frame *rx_fp, + enum fc_ba_rjt_reason reason, + enum fc_ba_rjt_explan explan) { struct fc_frame *fp; struct fc_frame_header *rx_fh; diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 6f07de15c49..dae65133a83 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -179,8 +179,8 @@ EXPORT_SYMBOL(fc_set_rport_loss_tmo); * @flp: FLOGI payload structure * @maxval: upper limit, may be less than what is in the service parameters */ -static unsigned int -fc_plogi_get_maxframe(struct fc_els_flogi *flp, unsigned int maxval) +static unsigned int fc_plogi_get_maxframe(struct fc_els_flogi *flp, + unsigned int maxval) { unsigned int mfs; -- GitLab From fc47ff6b1b27fb736f255ed8cd490356e0cd228f Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:55:55 -0800 Subject: [PATCH 3034/4982] [SCSI] libfc, fcoe: Remove unnecessary cast by removing inline wrapper Comment from "Andrew Morton " > +{ > + return (struct fcoe_softc *)lport_priv(lp); unneeded/undesirable cast of void*. There are probably zillions of instances of this - there always are. This whole inline function was unnecessary. The FCoE layer knows that it's data structure is stored in the lport private data, it can just access it from lport_priv(). Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe_sw.c | 2 +- drivers/scsi/fcoe/libfcoe.c | 12 ++++++------ include/scsi/libfcoe.h | 8 +------- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c index 007d1fbae80..f667dce1bbb 100644 --- a/drivers/scsi/fcoe/fcoe_sw.c +++ b/drivers/scsi/fcoe/fcoe_sw.c @@ -297,7 +297,7 @@ static int fcoe_sw_destroy(struct net_device *netdev) if (!lp) return -ENODEV; - fc = fcoe_softc(lp); + fc = lport_priv(lp); /* Logout of the fabric */ fc_fabric_logoff(lp); diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index d006d657681..02f044a8715 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -387,7 +387,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) WARN_ON((fr_len(fp) % sizeof(u32)) != 0); - fc = fcoe_softc(lp); + fc = lport_priv(lp); /* * if it is a flogi then we need to learn gw-addr * and my own fcid @@ -768,7 +768,7 @@ static int fcoe_check_wait_queue(struct fc_lport *lp) struct sk_buff *skb; struct fcoe_softc *fc; - fc = fcoe_softc(lp); + fc = lport_priv(lp); spin_lock_bh(&fc->fcoe_pending_queue.lock); /* @@ -805,7 +805,7 @@ static void fcoe_insert_wait_queue_head(struct fc_lport *lp, { struct fcoe_softc *fc; - fc = fcoe_softc(lp); + fc = lport_priv(lp); spin_lock_bh(&fc->fcoe_pending_queue.lock); __skb_queue_head(&fc->fcoe_pending_queue, skb); spin_unlock_bh(&fc->fcoe_pending_queue.lock); @@ -823,7 +823,7 @@ static void fcoe_insert_wait_queue(struct fc_lport *lp, { struct fcoe_softc *fc; - fc = fcoe_softc(lp); + fc = lport_priv(lp); spin_lock_bh(&fc->fcoe_pending_queue.lock); __skb_queue_tail(&fc->fcoe_pending_queue, skb); spin_unlock_bh(&fc->fcoe_pending_queue.lock); @@ -1113,7 +1113,7 @@ MODULE_PARM_DESC(destroy, "Destroy fcoe port"); */ int fcoe_link_ok(struct fc_lport *lp) { - struct fcoe_softc *fc = fcoe_softc(lp); + struct fcoe_softc *fc = lport_priv(lp); struct net_device *dev = fc->real_dev; struct ethtool_cmd ecmd = { ETHTOOL_GSET }; int rc = 0; @@ -1329,7 +1329,7 @@ int fcoe_hostlist_add(const struct fc_lport *lp) fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp)); if (!fc) { - fc = fcoe_softc(lp); + fc = lport_priv(lp); write_lock_bh(&fcoe_hostlist_lock); list_add_tail(&fc->list, &fcoe_hostlist); write_unlock_bh(&fcoe_hostlist_lock); diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h index 89fdbb9a6a1..f43d3833a7a 100644 --- a/include/scsi/libfcoe.h +++ b/include/scsi/libfcoe.h @@ -58,16 +58,10 @@ struct fcoe_softc { u8 address_mode; }; -static inline struct fcoe_softc *fcoe_softc( - const struct fc_lport *lp) -{ - return (struct fcoe_softc *)lport_priv(lp); -} - static inline struct net_device *fcoe_netdev( const struct fc_lport *lp) { - return fcoe_softc(lp)->real_dev; + return ((struct fcoe_softc *)lport_priv(lp))->real_dev; } static inline struct fcoe_hdr *skb_fcoe_header(const struct sk_buff *skb) -- GitLab From a468f328ad83f14556e5961ef1de80b32b428d32 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:56:00 -0800 Subject: [PATCH 3035/4982] [SCSI] fcoe: Use setup_timer() and mod_timer() Use helper functions for watchdog timer setup. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 02f044a8715..7887f2a7c2a 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -1435,11 +1435,9 @@ static int __init fcoe_init(void) */ fcoe_dev_setup(); - init_timer(&fcoe_timer); - fcoe_timer.data = 0; - fcoe_timer.function = fcoe_watchdog; - fcoe_timer.expires = (jiffies + (10 * HZ)); - add_timer(&fcoe_timer); + setup_timer(&fcoe_timer, fcoe_watchdog, 0); + + mod_timer(&fcoe_timer, jiffies + (10 * HZ)); /* initiatlize the fcoe transport */ fcoe_transport_init(); -- GitLab From 03ec862dff57ca3d1fcb439b99aadc45bc5c2f28 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:56:06 -0800 Subject: [PATCH 3036/4982] [SCSI] fcoe: Correct fcoe_transports initialization vs. registration The registration function shouldn't initialize the mutex or list head. The fcoe SW transport should initialize itself before registering. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fc_transport_fcoe.c | 3 --- drivers/scsi/fcoe/fcoe_sw.c | 5 +++++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/fcoe/fc_transport_fcoe.c b/drivers/scsi/fcoe/fc_transport_fcoe.c index 847453a70c6..8862758006c 100644 --- a/drivers/scsi/fcoe/fc_transport_fcoe.c +++ b/drivers/scsi/fcoe/fc_transport_fcoe.c @@ -258,9 +258,6 @@ int fcoe_transport_register(struct fcoe_transport *t) list_add_tail(&t->list, &fcoe_transports); mutex_unlock(&fcoe_transports_lock); - mutex_init(&t->devlock); - INIT_LIST_HEAD(&t->devlist); - printk(KERN_DEBUG "fcoe_transport_register:%s\n", t->name); return 0; diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c index f667dce1bbb..37d359db164 100644 --- a/drivers/scsi/fcoe/fcoe_sw.c +++ b/drivers/scsi/fcoe/fcoe_sw.c @@ -467,10 +467,15 @@ int __init fcoe_sw_init(void) /* attach to scsi transport */ scsi_transport_fcoe_sw = fc_attach_transport(&fcoe_sw_transport_function); + if (!scsi_transport_fcoe_sw) { printk(KERN_ERR "fcoe_sw_init:fc_attach_transport() failed\n"); return -ENODEV; } + + mutex_init(&fcoe_sw_transport.devlock); + INIT_LIST_HEAD(&fcoe_sw_transport.devlist); + /* register sw transport */ fcoe_transport_register(&fcoe_sw_transport); return 0; -- GitLab From 422819cfa3a2605a0b3bdc33aaef0bc2feaeaada Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Fri, 27 Feb 2009 10:56:11 -0800 Subject: [PATCH 3037/4982] [SCSI] libfc: do not change the fh_rx_id of a recevied frame We shouldn't be altering inbound frames. Signed-off-by: Yi Zou Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 7b933954c10..505825b6124 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -625,7 +625,6 @@ static struct fc_exch *fc_exch_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) { struct fc_exch *ep; struct fc_frame_header *fh; - u16 rxid; ep = mp->lp->tt.exch_get(mp->lp, fp); if (ep) { @@ -652,18 +651,6 @@ static struct fc_exch *fc_exch_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) if ((ntoh24(fh->fh_f_ctl) & FC_FC_SEQ_INIT) == 0) ep->esb_stat &= ~ESB_ST_SEQ_INIT; - /* - * Set the responder ID in the frame header. - * The old one should've been 0xffff. - * If it isn't, don't assign one. - * Incoming basic link service frames may specify - * a referenced RX_ID. - */ - if (fh->fh_type != FC_TYPE_BLS) { - rxid = ntohs(fh->fh_rx_id); - WARN_ON(rxid != FC_XID_UNKNOWN); - fh->fh_rx_id = htons(ep->rxid); - } fc_exch_hold(ep); /* hold for caller */ spin_unlock_bh(&ep->ex_lock); /* lock from exch_get */ } -- GitLab From 74846bf85e42b4ba851d3f0dd67aa1df245895f9 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Fri, 27 Feb 2009 10:56:16 -0800 Subject: [PATCH 3038/4982] [SCSI] fcoe: ETH_P_8021Q is already in if_ether and fcoe is not using it anyway Signed-off-by: Yi Zou Signed-off-by: Robert Love Signed-off-by: James Bottomley --- include/scsi/fc/fc_fcoe.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/scsi/fc/fc_fcoe.h b/include/scsi/fc/fc_fcoe.h index 57aaa8f0d61..f271d9cc0fc 100644 --- a/include/scsi/fc/fc_fcoe.h +++ b/include/scsi/fc/fc_fcoe.h @@ -31,10 +31,6 @@ #define ETH_P_FCOE 0x8906 /* FCOE ether type */ #endif -#ifndef ETH_P_8021Q -#define ETH_P_8021Q 0x8100 -#endif - /* * FC_FCOE_OUI hasn't been standardized yet. XXX TBD. */ -- GitLab From e904158159e9812d06646767b7c81846dc3b05e6 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Fri, 27 Feb 2009 10:56:22 -0800 Subject: [PATCH 3039/4982] [SCSI] fcoe: fix kfree(skb) Use kfree_skb instead of kfree for struct sk_buff pointers. Signed-off-by: Roel Kluin Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 7887f2a7c2a..7265e093799 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -437,7 +437,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) if (skb_is_nonlinear(skb)) { skb_frag_t *frag; if (fcoe_get_paged_crc_eof(skb, tlen)) { - kfree(skb); + kfree_skb(skb); return -ENOMEM; } frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1]; -- GitLab From c826a3145736e3baabebccfd0aecfbb6dae059f2 Mon Sep 17 00:00:00 2001 From: Vasu Dev Date: Fri, 27 Feb 2009 10:56:27 -0800 Subject: [PATCH 3040/4982] [SCSI] fcoe: Out of order tx frames was causing several check condition SCSI status frames followed by these errors in log. [sdp] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE,SUGGEST_OK [sdp] Sense Key : Aborted Command [current] [sdp] Add. Sense: Data phase error This was causing some test apps to exit due to write failure under heavy load. This was due to a race around adding and removing tx frame skb in fcoe_pending_queue, Chris Leech helped me to find that brief unlocking period when pulling skb from fcoe_pending_queue in various contexts (fcoe_watchdog and fcoe_xmit) and then adding skb back into fcoe_pending_queue up on a failed fcoe_start_io could change skb/tx frame order in fcoe_pending_queue. Thanks Chris. This patch allows only single context to pull skb from fcoe_pending_queue at any time to prevent above described ordering issue/race by use of fcoe_pending_queue_active flag. This patch simplified fcoe_watchdog with modified fcoe_check_wait_queue by use of FCOE_LOW_QUEUE_DEPTH instead previously used several conditionals to clear and set lp->qfull. I think FCOE_MAX_QUEUE_DEPTH with FCOE_LOW_QUEUE_DEPTH will work better in re/setting lp->qfull and these could be fine tuned for performance. Signed-off-by: Vasu Dev Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe_sw.c | 1 + drivers/scsi/fcoe/libfcoe.c | 45 +++++++++++++++++-------------------- include/scsi/libfcoe.h | 1 + 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c index 37d359db164..da210eba194 100644 --- a/drivers/scsi/fcoe/fcoe_sw.c +++ b/drivers/scsi/fcoe/fcoe_sw.c @@ -188,6 +188,7 @@ static int fcoe_sw_netdev_config(struct fc_lport *lp, struct net_device *netdev) skb_queue_head_init(&fc->fcoe_pending_queue); + fc->fcoe_pending_queue_active = 0; /* setup Source Mac Address */ memcpy(fc->ctl_src_addr, fc->real_dev->dev_addr, diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 7265e093799..14dd8a0402b 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -49,6 +49,7 @@ static int debug_fcoe; #define FCOE_MAX_QUEUE_DEPTH 256 +#define FCOE_LOW_QUEUE_DEPTH 32 /* destination address mode */ #define FCOE_GW_ADDR_MODE 0x00 @@ -723,21 +724,12 @@ static void fcoe_recv_flogi(struct fcoe_softc *fc, struct fc_frame *fp, u8 *sa) */ void fcoe_watchdog(ulong vp) { - struct fc_lport *lp; struct fcoe_softc *fc; - int qfilled = 0; read_lock(&fcoe_hostlist_lock); list_for_each_entry(fc, &fcoe_hostlist, list) { - lp = fc->lp; - if (lp) { - if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) - qfilled = 1; - if (fcoe_check_wait_queue(lp) < FCOE_MAX_QUEUE_DEPTH) { - if (qfilled) - lp->qfull = 0; - } - } + if (fc->lp) + fcoe_check_wait_queue(fc->lp); } read_unlock(&fcoe_hostlist_lock); @@ -753,8 +745,8 @@ void fcoe_watchdog(ulong vp) * * This empties the wait_queue, dequeue the head of the wait_queue queue * and calls fcoe_start_io() for each packet, if all skb have been - * transmitted, return 0 if a error occurs, then restore wait_queue and - * try again later. + * transmitted, return qlen or -1 if a error occurs, then restore + * wait_queue and try again later. * * The wait_queue is used when the skb transmit fails. skb will go * in the wait_queue which will be emptied by the time function OR @@ -764,33 +756,38 @@ void fcoe_watchdog(ulong vp) */ static int fcoe_check_wait_queue(struct fc_lport *lp) { - int rc; struct sk_buff *skb; struct fcoe_softc *fc; + int rc = -1; fc = lport_priv(lp); spin_lock_bh(&fc->fcoe_pending_queue.lock); - /* - * if interface pending queue full then set qfull in lport. - */ - if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) - lp->qfull = 1; + if (fc->fcoe_pending_queue_active) + goto out; + fc->fcoe_pending_queue_active = 1; if (fc->fcoe_pending_queue.qlen) { while ((skb = __skb_dequeue(&fc->fcoe_pending_queue)) != NULL) { spin_unlock_bh(&fc->fcoe_pending_queue.lock); rc = fcoe_start_io(skb); - if (rc) { + if (rc) fcoe_insert_wait_queue_head(lp, skb); - return rc; - } spin_lock_bh(&fc->fcoe_pending_queue.lock); + if (rc) + break; } - if (fc->fcoe_pending_queue.qlen < FCOE_MAX_QUEUE_DEPTH) + /* + * if interface pending queue is below FCOE_LOW_QUEUE_DEPTH + * then clear qfull flag. + */ + if (fc->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH) lp->qfull = 0; } + fc->fcoe_pending_queue_active = 0; + rc = fc->fcoe_pending_queue.qlen; +out: spin_unlock_bh(&fc->fcoe_pending_queue.lock); - return fc->fcoe_pending_queue.qlen; + return rc; } /** diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h index f43d3833a7a..941818f29f5 100644 --- a/include/scsi/libfcoe.h +++ b/include/scsi/libfcoe.h @@ -46,6 +46,7 @@ struct fcoe_softc { struct net_device *phys_dev; /* device with ethtool_ops */ struct packet_type fcoe_packet_type; struct sk_buff_head fcoe_pending_queue; + u8 fcoe_pending_queue_active; u8 dest_addr[ETH_ALEN]; u8 ctl_src_addr[ETH_ALEN]; -- GitLab From 55c8bafba549e3e82f6999db8c5a62fc3c255c14 Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Fri, 27 Feb 2009 10:56:32 -0800 Subject: [PATCH 3041/4982] [SCSI] fcoe: fix handling of pending queue, prevent out of order frames (v3) In fcoe_check_wait_queue() the queue length could temporarily drop to 0, before the last frame was successfully sent. This resulted in out of order data frames within a single sequence, leading to IO timeout errors. This builds on the approach from Vasu Dev to only fix the queue management in fcoe_check_wait_queue, where my first patch added locking to the transmit path even when the pending queue was not in use. This patch continues to use fcoe_pending_queue.qlen instead of introducing a new length counter, but takes precautions to ensure it never drops to 0 before the final frame in the queue has successfully been passed to the netdev qdisc layer. It also includes some cleanup of fcoe_check_wait_queue and removes the fcoe_insert_wait_queue(_head) wrapper functions. Signed-off-by: Chris Leech Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 81 +++++++++++-------------------------- 1 file changed, 24 insertions(+), 57 deletions(-) diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 14dd8a0402b..0e0b494fc17 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -70,8 +70,6 @@ struct fcoe_percpu_s *fcoe_percpu[NR_CPUS]; /* Function Prototyes */ static int fcoe_check_wait_queue(struct fc_lport *); -static void fcoe_insert_wait_queue_head(struct fc_lport *, struct sk_buff *); -static void fcoe_insert_wait_queue(struct fc_lport *, struct sk_buff *); static void fcoe_recv_flogi(struct fcoe_softc *, struct fc_frame *, u8 *); #ifdef CONFIG_HOTPLUG_CPU static int fcoe_cpu_callback(struct notifier_block *, ulong, void *); @@ -501,7 +499,9 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) rc = fcoe_start_io(skb); if (rc) { - fcoe_insert_wait_queue(lp, skb); + spin_lock_bh(&fc->fcoe_pending_queue.lock); + __skb_queue_tail(&fc->fcoe_pending_queue, skb); + spin_unlock_bh(&fc->fcoe_pending_queue.lock); if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) lp->qfull = 1; } @@ -756,33 +756,36 @@ void fcoe_watchdog(ulong vp) */ static int fcoe_check_wait_queue(struct fc_lport *lp) { + struct fcoe_softc *fc = lport_priv(lp); struct sk_buff *skb; - struct fcoe_softc *fc; int rc = -1; - fc = lport_priv(lp); spin_lock_bh(&fc->fcoe_pending_queue.lock); - if (fc->fcoe_pending_queue_active) goto out; fc->fcoe_pending_queue_active = 1; - if (fc->fcoe_pending_queue.qlen) { - while ((skb = __skb_dequeue(&fc->fcoe_pending_queue)) != NULL) { - spin_unlock_bh(&fc->fcoe_pending_queue.lock); - rc = fcoe_start_io(skb); - if (rc) - fcoe_insert_wait_queue_head(lp, skb); - spin_lock_bh(&fc->fcoe_pending_queue.lock); - if (rc) - break; + + while (fc->fcoe_pending_queue.qlen) { + /* keep qlen > 0 until fcoe_start_io succeeds */ + fc->fcoe_pending_queue.qlen++; + skb = __skb_dequeue(&fc->fcoe_pending_queue); + + spin_unlock_bh(&fc->fcoe_pending_queue.lock); + rc = fcoe_start_io(skb); + spin_lock_bh(&fc->fcoe_pending_queue.lock); + + if (rc) { + __skb_queue_head(&fc->fcoe_pending_queue, skb); + /* undo temporary increment above */ + fc->fcoe_pending_queue.qlen--; + break; } - /* - * if interface pending queue is below FCOE_LOW_QUEUE_DEPTH - * then clear qfull flag. - */ - if (fc->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH) - lp->qfull = 0; + /* undo temporary increment above */ + fc->fcoe_pending_queue.qlen--; } + + if (fc->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH) + lp->qfull = 0; fc->fcoe_pending_queue_active = 0; rc = fc->fcoe_pending_queue.qlen; out: @@ -790,42 +793,6 @@ out: return rc; } -/** - * fcoe_insert_wait_queue_head() - puts skb to fcoe pending queue head - * @lp: the fc_port for this skb - * @skb: the associated skb to be xmitted - * - * Returns: none - */ -static void fcoe_insert_wait_queue_head(struct fc_lport *lp, - struct sk_buff *skb) -{ - struct fcoe_softc *fc; - - fc = lport_priv(lp); - spin_lock_bh(&fc->fcoe_pending_queue.lock); - __skb_queue_head(&fc->fcoe_pending_queue, skb); - spin_unlock_bh(&fc->fcoe_pending_queue.lock); -} - -/** - * fcoe_insert_wait_queue() - put the skb into fcoe pending queue tail - * @lp: the fc_port for this skb - * @skb: the associated skb to be xmitted - * - * Returns: none - */ -static void fcoe_insert_wait_queue(struct fc_lport *lp, - struct sk_buff *skb) -{ - struct fcoe_softc *fc; - - fc = lport_priv(lp); - spin_lock_bh(&fc->fcoe_pending_queue.lock); - __skb_queue_tail(&fc->fcoe_pending_queue, skb); - spin_unlock_bh(&fc->fcoe_pending_queue.lock); -} - /** * fcoe_dev_setup() - setup link change notification interface */ -- GitLab From 4469c195da43bf8220f53da8b576c0e154c2b662 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:56:38 -0800 Subject: [PATCH 3042/4982] [SCSI] fcoe: Change fcoe receive thread nice value from 19 (lowest priority) to -20 This change makes the fcoe Rx threads have the same nice value as lpfc and qla2xxx Rx threads. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 0e0b494fc17..5548bf3bb58 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -531,7 +531,7 @@ int fcoe_percpu_receive_thread(void *arg) struct fcoe_softc *fc; struct fcoe_hdr *hp; - set_user_nice(current, 19); + set_user_nice(current, -20); while (!kthread_should_stop()) { -- GitLab From dd5746a85cb21ea5b3afca0b569586a05aa56846 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 10 Mar 2009 14:30:40 +0100 Subject: [PATCH 3043/4982] ALSA: hda - Create vmaster for conexant codecs Instead of binding volumes, create a virtual master volume for Conexant codecs. This allows separate HP and speaker volume controls. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 47 ++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 1938e92e1f0..e1476d6d8b3 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -58,6 +58,7 @@ struct conexant_spec { struct snd_kcontrol_new *mixers[5]; int num_mixers; + hda_nid_t vmaster_nid; const struct hda_verb *init_verbs[5]; /* initialization verbs * don't forget NULL @@ -462,6 +463,18 @@ static void conexant_free(struct hda_codec *codec) kfree(codec->spec); } +static const char *slave_vols[] = { + "Headphone Playback Volume", + "Speaker Playback Volume", + NULL +}; + +static const char *slave_sws[] = { + "Headphone Playback Switch", + "Speaker Playback Switch", + NULL +}; + static int conexant_build_controls(struct hda_codec *codec) { struct conexant_spec *spec = codec->spec; @@ -489,6 +502,26 @@ static int conexant_build_controls(struct hda_codec *codec) if (err < 0) return err; } + + /* if we have no master control, let's create it */ + if (spec->vmaster_nid && + !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { + unsigned int vmaster_tlv[4]; + snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, + HDA_OUTPUT, vmaster_tlv); + err = snd_hda_add_vmaster(codec, "Master Playback Volume", + vmaster_tlv, slave_vols); + if (err < 0) + return err; + } + if (spec->vmaster_nid && + !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { + err = snd_hda_add_vmaster(codec, "Master Playback Switch", + NULL, slave_sws); + if (err < 0) + return err; + } + return 0; } @@ -1182,16 +1215,6 @@ static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol, return 1; } -/* bind volumes of both NID 0x13 (Headphones) and 0x1d (Speakers) */ -static struct hda_bind_ctls cxt5047_bind_master_vol = { - .ops = &snd_hda_bind_vol, - .values = { - HDA_COMPOSE_AMP_VAL(0x13, 3, 0, HDA_OUTPUT), - HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT), - 0 - }, -}; - /* mute internal speaker if HP is plugged */ static void cxt5047_hp_automute(struct hda_codec *codec) { @@ -1311,7 +1334,8 @@ static struct snd_kcontrol_new cxt5047_toshiba_mixers[] = { HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), - HDA_BIND_VOL("Master Playback Volume", &cxt5047_bind_master_vol), + HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT), + HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x00, HDA_OUTPUT), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Master Playback Switch", @@ -1631,6 +1655,7 @@ static int patch_cxt5047(struct hda_codec *codec) codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; #endif } + spec->vmaster_nid = 0x13; return 0; } -- GitLab From b880c74adf7e79b97de710a152ea82f292f9abc7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 10 Mar 2009 14:41:05 +0100 Subject: [PATCH 3044/4982] ALSA: hda - Create "Capture Source" control dynamically in patch_conexant.c Create "Capture Source" control dynamically for Conexant codecs. If only one capture item is available, don't create such a control since it's just useless. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 61 ++++++++++------------------------ 1 file changed, 17 insertions(+), 44 deletions(-) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index e1476d6d8b3..d5d736ff7c6 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -463,6 +463,17 @@ static void conexant_free(struct hda_codec *codec) kfree(codec->spec); } +static struct snd_kcontrol_new cxt_capture_mixers[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Capture Source", + .info = conexant_mux_enum_info, + .get = conexant_mux_enum_get, + .put = conexant_mux_enum_put + }, + {} +}; + static const char *slave_vols[] = { "Headphone Playback Volume", "Speaker Playback Volume", @@ -522,6 +533,12 @@ static int conexant_build_controls(struct hda_codec *codec) return err; } + if (spec->input_mux) { + err = snd_hda_add_new_ctls(codec, cxt_capture_mixers); + if (err < 0) + return err; + } + return 0; } @@ -753,13 +770,6 @@ static void cxt5045_hp_unsol_event(struct hda_codec *codec, } static struct snd_kcontrol_new cxt5045_mixers[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = conexant_mux_enum_info, - .get = conexant_mux_enum_get, - .put = conexant_mux_enum_put - }, HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x01, HDA_INPUT), HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x01, HDA_INPUT), HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x02, HDA_INPUT), @@ -793,13 +803,6 @@ static struct snd_kcontrol_new cxt5045_benq_mixers[] = { }; static struct snd_kcontrol_new cxt5045_mixers_hp530[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = conexant_mux_enum_info, - .get = conexant_mux_enum_get, - .put = conexant_mux_enum_put - }, HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x02, HDA_INPUT), HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x02, HDA_INPUT), HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x01, HDA_INPUT), @@ -1170,20 +1173,6 @@ static struct hda_channel_mode cxt5047_modes[1] = { { 2, NULL }, }; -static struct hda_input_mux cxt5047_capture_source = { - .num_items = 1, - .items = { - { "Mic", 0x2 }, - } -}; - -static struct hda_input_mux cxt5047_hp_capture_source = { - .num_items = 1, - .items = { - { "ExtMic", 0x2 }, - } -}; - static struct hda_input_mux cxt5047_toshiba_capture_source = { .num_items = 2, .items = { @@ -1321,13 +1310,6 @@ static struct snd_kcontrol_new cxt5047_mixers[] = { }; static struct snd_kcontrol_new cxt5047_toshiba_mixers[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = conexant_mux_enum_info, - .get = conexant_mux_enum_get, - .put = conexant_mux_enum_put - }, HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT), HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT), HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), @@ -1349,13 +1331,6 @@ static struct snd_kcontrol_new cxt5047_toshiba_mixers[] = { }; static struct snd_kcontrol_new cxt5047_hp_mixers[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = conexant_mux_enum_info, - .get = conexant_mux_enum_get, - .put = conexant_mux_enum_put - }, HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT), HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19,0x02,HDA_INPUT), HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), @@ -1614,7 +1589,6 @@ static int patch_cxt5047(struct hda_codec *codec) spec->num_adc_nids = 1; spec->adc_nids = cxt5047_adc_nids; spec->capsrc_nids = cxt5047_capsrc_nids; - spec->input_mux = &cxt5047_capture_source; spec->num_mixers = 1; spec->mixers[0] = cxt5047_mixers; spec->num_init_verbs = 1; @@ -1633,7 +1607,6 @@ static int patch_cxt5047(struct hda_codec *codec) codec->patch_ops.unsol_event = cxt5047_hp2_unsol_event; break; case CXT5047_LAPTOP_HP: - spec->input_mux = &cxt5047_hp_capture_source; spec->num_init_verbs = 2; spec->init_verbs[1] = cxt5047_hp_init_verbs; spec->mixers[0] = cxt5047_hp_mixers; -- GitLab From 3b628867f328cfe1ad4811d63961579874f87041 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 10 Mar 2009 14:53:54 +0100 Subject: [PATCH 3045/4982] ALSA: hda - Remove superfluous verbs for Cxt5047 laptop-eapd model Remove superfluous verbs from cxt5047_toshiba_init_verbs[]. Also fix comments and minor coding style issues. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index d5d736ff7c6..e9e47574c61 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -1377,12 +1377,9 @@ static struct hda_verb cxt5047_init_verbs[] = { /* configuration for Toshiba Laptops */ static struct hda_verb cxt5047_toshiba_init_verbs[] = { - {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0 }, /* default on */ - /* pin sensing on HP and Mic jacks */ - {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, - {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, + {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0}, /* default off */ /* Speaker routing */ - {0x1d, AC_VERB_SET_CONNECT_SEL,0x1}, + {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1}, {} }; -- GitLab From 5b3a7440cbabdda07cfb3dcf4a07e0115a3dff9a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 10 Mar 2009 15:10:55 +0100 Subject: [PATCH 3046/4982] ALSA: hda - Fix / clean up init verbs for Cxt5047 codec Fix the initial connections of output pins 0x13 and 0x1d for Conexant 5047 codec to point to the mixer amp properly. Removed unneeded (doubly) verbs from arrays, also removed the unneeded changing of widget 0x1c, which is now completely unused. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 36 +++------------------------------- 1 file changed, 3 insertions(+), 33 deletions(-) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index e9e47574c61..71822140294 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -1165,7 +1165,7 @@ static int patch_cxt5045(struct hda_codec *codec) /* Conexant 5047 specific */ #define CXT5047_SPDIF_OUT 0x11 -static hda_nid_t cxt5047_dac_nids[2] = { 0x10, 0x1c }; +static hda_nid_t cxt5047_dac_nids[1] = { 0x10 }; /* 0x1c */ static hda_nid_t cxt5047_adc_nids[1] = { 0x12 }; static hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a }; @@ -1216,9 +1216,6 @@ static void cxt5047_hp_automute(struct hda_codec *codec) bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0, HDA_AMP_MUTE, bits); - /* Mute/Unmute PCM 2 for good measure - some systems need this */ - snd_hda_codec_amp_stereo(codec, 0x1c, HDA_OUTPUT, 0, - HDA_AMP_MUTE, bits); } /* mute internal speaker if HP is plugged */ @@ -1233,9 +1230,6 @@ static void cxt5047_hp2_automute(struct hda_codec *codec) bits = spec->hp_present ? HDA_AMP_MUTE : 0; snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0, HDA_AMP_MUTE, bits); - /* Mute/Unmute PCM 2 for good measure - some systems need this */ - snd_hda_codec_amp_stereo(codec, 0x1c, HDA_OUTPUT, 0, - HDA_AMP_MUTE, bits); } /* toggle input of built-in and mic jack appropriately */ @@ -1299,8 +1293,6 @@ static struct snd_kcontrol_new cxt5047_mixers[] = { HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), - HDA_CODEC_VOLUME("PCM-2 Volume", 0x1c, 0x00, HDA_OUTPUT), - HDA_CODEC_MUTE("PCM-2 Switch", 0x1c, 0x00, HDA_OUTPUT), HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x00, HDA_OUTPUT), HDA_CODEC_MUTE("Speaker Playback Switch", 0x1d, 0x00, HDA_OUTPUT), HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT), @@ -1356,8 +1348,8 @@ static struct hda_verb cxt5047_init_verbs[] = { {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, /* HP, Speaker */ {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, - {0x13, AC_VERB_SET_CONNECT_SEL,0x1}, - {0x1d, AC_VERB_SET_CONNECT_SEL,0x0}, + {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, /* mixer(0x19) */ + {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mixer(0x19) */ /* Record selector: Mic */ {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, {0x19, AC_VERB_SET_AMP_GAIN_MUTE, @@ -1378,26 +1370,6 @@ static struct hda_verb cxt5047_init_verbs[] = { /* configuration for Toshiba Laptops */ static struct hda_verb cxt5047_toshiba_init_verbs[] = { {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0}, /* default off */ - /* Speaker routing */ - {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1}, - {} -}; - -/* configuration for HP Laptops */ -static struct hda_verb cxt5047_hp_init_verbs[] = { - /* pin sensing on HP jack */ - {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, - /* 0x13 is actually shared by both HP and speaker; - * setting the connection to 0 (=0x19) makes the master volume control - * working mysteriouslly... - */ - {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* Record selector: Ext Mic */ - {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, - AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, - /* Speaker routing */ - {0x1d, AC_VERB_SET_CONNECT_SEL,0x1}, {} }; @@ -1604,8 +1576,6 @@ static int patch_cxt5047(struct hda_codec *codec) codec->patch_ops.unsol_event = cxt5047_hp2_unsol_event; break; case CXT5047_LAPTOP_HP: - spec->num_init_verbs = 2; - spec->init_verbs[1] = cxt5047_hp_init_verbs; spec->mixers[0] = cxt5047_hp_mixers; codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; codec->patch_ops.init = cxt5047_hp_init; -- GitLab From 6431c5dc5eeaa79863b4af300c081a01e2ccd0bb Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Thu, 5 Mar 2009 11:07:00 -0800 Subject: [PATCH 3047/4982] [SCSI] qla2xxx: Correct address range checking for option-rom updates. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index f4c57227ec1..ee9d4015243 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -244,12 +244,6 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, if (ha->optrom_state != QLA_SWAITING) break; - if (start & 0xfff) { - qla_printk(KERN_WARNING, ha, - "Invalid start region 0x%x/0x%x.\n", start, size); - return -EINVAL; - } - ha->optrom_region_start = start; ha->optrom_region_size = start + size > ha->optrom_size ? ha->optrom_size - start : size; @@ -303,8 +297,7 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, else if (start == (ha->flt_region_boot * 4) || start == (ha->flt_region_fw * 4)) valid = 1; - else if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && - start == (ha->flt_region_vpd_nvram * 4)) + else if (IS_QLA25XX(ha) || IS_QLA81XX(ha)) valid = 1; if (!valid) { qla_printk(KERN_WARNING, ha, -- GitLab From 605aa2bcd5e9dddc4666f12e0c19822809186d6d Mon Sep 17 00:00:00 2001 From: Lalit Chandivade Date: Thu, 5 Mar 2009 11:07:01 -0800 Subject: [PATCH 3048/4982] [SCSI] qla2xxx: Use correct value for max vport in LOOP topology. Use minimum value for max vport during firmware initialization in LOOP topology. Using max vport value from get resource count in LOOP topology causes firmware initialization failure. Signed-off-by: Lalit Chandivade Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 986501759ad..14325c02733 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1308,8 +1308,12 @@ qla2x00_init_rings(scsi_qla_host_t *vha) DEBUG(printk("scsi(%ld): Issue init firmware.\n", vha->host_no)); - if (ha->flags.npiv_supported) + if (ha->flags.npiv_supported) { + if (ha->operating_mode == LOOP) + ha->max_npiv_vports = MIN_MULTI_ID_FABRIC - 1; mid_init_cb->count = cpu_to_le16(ha->max_npiv_vports); + } + mid_init_cb->options = __constant_cpu_to_le16(BIT_1); -- GitLab From ee546b6e048586381462ce7bb51c7ddc03819619 Mon Sep 17 00:00:00 2001 From: Anirban Chakraborty Date: Thu, 5 Mar 2009 11:07:02 -0800 Subject: [PATCH 3049/4982] [SCSI] qla2xxx: Correct vport delete bug. Signed-off-by: Anirban Chakraborty Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 11 +++++++---- drivers/scsi/qla2xxx/qla_mbx.c | 3 ++- drivers/scsi/qla2xxx/qla_mid.c | 10 ++++++---- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 14325c02733..e54ab2f1079 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -2614,6 +2614,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, port_id_t wrap, nxt_d_id; struct qla_hw_data *ha = vha->hw; struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev); + struct scsi_qla_host *tvp; rval = QLA_SUCCESS; @@ -2713,7 +2714,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, /* Bypass virtual ports of the same host. */ found = 0; if (ha->num_vhosts) { - list_for_each_entry(vp, &ha->vp_list, list) { + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { if (new_fcport->d_id.b24 == vp->d_id.b24) { found = 1; break; @@ -2836,6 +2837,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) uint16_t first_loop_id; struct qla_hw_data *ha = vha->hw; struct scsi_qla_host *vp; + struct scsi_qla_host *tvp; rval = QLA_SUCCESS; @@ -2860,7 +2862,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) /* Check for loop ID being already in use. */ found = 0; fcport = NULL; - list_for_each_entry(vp, &ha->vp_list, list) { + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { list_for_each_entry(fcport, &vp->vp_fcports, list) { if (fcport->loop_id == dev->loop_id && fcport != dev) { @@ -3295,6 +3297,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) uint8_t status = 0; struct qla_hw_data *ha = vha->hw; struct scsi_qla_host *vp; + struct scsi_qla_host *tvp; struct req_que *req = ha->req_q_map[0]; if (vha->flags.online) { @@ -3310,7 +3313,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) if (atomic_read(&vha->loop_state) != LOOP_DOWN) { atomic_set(&vha->loop_state, LOOP_DOWN); qla2x00_mark_all_devices_lost(vha, 0); - list_for_each_entry(vp, &ha->vp_list, list) + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) qla2x00_mark_all_devices_lost(vp, 0); } else { if (!atomic_read(&vha->loop_down_timer)) @@ -3407,7 +3410,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) DEBUG(printk(KERN_INFO "qla2x00_abort_isp(%ld): succeeded.\n", vha->host_no)); - list_for_each_entry(vp, &ha->vp_list, list) { + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { if (vp->vp_idx) qla2x00_vp_abort_isp(vp); } diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 4c7504cb399..4aab7acf752 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -2685,6 +2685,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, uint16_t stat = le16_to_cpu(rptid_entry->vp_idx); struct qla_hw_data *ha = vha->hw; scsi_qla_host_t *vp; + scsi_qla_host_t *tvp; if (rptid_entry->entry_status != 0) return; @@ -2710,7 +2711,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, if (MSB(stat) == 1) return; - list_for_each_entry(vp, &ha->vp_list, list) + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) if (vp_idx == vp->vp_idx) break; if (!vp) diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 3f23932210c..785c61279e6 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -69,9 +69,10 @@ static scsi_qla_host_t * qla24xx_find_vhost_by_name(struct qla_hw_data *ha, uint8_t *port_name) { scsi_qla_host_t *vha; + struct scsi_qla_host *tvha; /* Locate matching device in database. */ - list_for_each_entry(vha, &ha->vp_list, list) { + list_for_each_entry_safe(vha, tvha, &ha->vp_list, list) { if (!memcmp(port_name, vha->port_name, WWN_SIZE)) return vha; } @@ -194,11 +195,11 @@ qla24xx_configure_vp(scsi_qla_host_t *vha) void qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb) { - scsi_qla_host_t *vha; + scsi_qla_host_t *vha, *tvha; struct qla_hw_data *ha = rsp->hw; int i = 0; - list_for_each_entry(vha, &ha->vp_list, list) { + list_for_each_entry_safe(vha, tvha, &ha->vp_list, list) { if (vha->vp_idx) { switch (mb[0]) { case MBA_LIP_OCCURRED: @@ -300,6 +301,7 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha) int ret; struct qla_hw_data *ha = vha->hw; scsi_qla_host_t *vp; + struct scsi_qla_host *tvp; if (vha->vp_idx) return; @@ -308,7 +310,7 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha) clear_bit(VP_DPC_NEEDED, &vha->dpc_flags); - list_for_each_entry(vp, &ha->vp_list, list) { + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { if (vp->vp_idx) ret = qla2x00_do_dpc_vp(vp); } -- GitLab From c6b2fca8205dc33e3bb444835769e4ea4c6bc58d Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Thu, 5 Mar 2009 11:07:03 -0800 Subject: [PATCH 3050/4982] [SCSI] qla2xxx: Correct truncation in return-code status checking. QLA_* return codes are 'int' in size. There were still several legacy check-points which assumed a return-code width of 8-bits. This could cause incorrect assumptions of 'good' status if a return of QLA_FUNCTION_TIMEOUT. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 2 +- drivers/scsi/qla2xxx/qla_os.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index e54ab2f1079..87f9abc7146 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3435,7 +3435,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) static int qla2x00_restart_isp(scsi_qla_host_t *vha) { - uint8_t status = 0; + int status = 0; uint32_t wait_time; struct qla_hw_data *ha = vha->hw; struct req_que *req = ha->req_q_map[0]; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 2f5f72531e2..16c34760b95 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2568,7 +2568,7 @@ qla2x00_do_work(struct scsi_qla_host *vha) void qla2x00_relogin(struct scsi_qla_host *vha) { fc_port_t *fcport; - uint8_t status; + int status; uint16_t next_loopid = 0; struct qla_hw_data *ha = vha->hw; -- GitLab From ca42f2b5f58702e5751e1423bd2f7987b0760eab Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Thu, 5 Mar 2009 11:07:04 -0800 Subject: [PATCH 3051/4982] [SCSI] qla2xxx: Correct overwrite of pre-assigned init-control-block structure size. The value is already pre-assigned prior to the qla2x00_mem_alloc(). Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 16c34760b95..3ddfa889e94 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2222,10 +2222,6 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, { char name[16]; - ha->init_cb_size = sizeof(init_cb_t); - if (IS_QLA2XXX_MIDTYPE(ha)) - ha->init_cb_size = sizeof(struct mid_init_cb_24xx); - ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, ha->init_cb_size, &ha->init_cb_dma, GFP_KERNEL); if (!ha->init_cb) -- GitLab From 5fa0ae19822d60307059ee64b80ba9e5effdce58 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Thu, 5 Mar 2009 11:07:05 -0800 Subject: [PATCH 3052/4982] [SCSI] qla2xxx: Update version number to 8.03.00-k4. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 79f7053da99..a772eab2f0e 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.03.00-k3" +#define QLA2XXX_VERSION "8.03.00-k4" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 3 -- GitLab From df481e41b963b7fc3d7e3543a0c7bb140a682146 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 10 Mar 2009 15:35:35 +0100 Subject: [PATCH 3053/4982] ALSA: hda - Clean up Cxt5047 parser Clean up Conexant 5047 pareser code: - Split mixer elements to separate arrays to reduce the duplicated entires - Fix mixer element names to the standard ones - Remove unneeded cxt5047_hp2_unsol_event; the normal unsol_event handler works fine. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 89 ++++++++-------------------------- 1 file changed, 19 insertions(+), 70 deletions(-) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 71822140294..d60ccb5bb12 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -1218,20 +1218,6 @@ static void cxt5047_hp_automute(struct hda_codec *codec) HDA_AMP_MUTE, bits); } -/* mute internal speaker if HP is plugged */ -static void cxt5047_hp2_automute(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - unsigned int bits; - - spec->hp_present = snd_hda_codec_read(codec, 0x13, 0, - AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; - - bits = spec->hp_present ? HDA_AMP_MUTE : 0; - snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0, - HDA_AMP_MUTE, bits); -} - /* toggle input of built-in and mic jack appropriately */ static void cxt5047_hp_automic(struct hda_codec *codec) { @@ -1269,47 +1255,14 @@ static void cxt5047_hp_unsol_event(struct hda_codec *codec, } } -/* unsolicited event for HP jack sensing - non-EAPD systems */ -static void cxt5047_hp2_unsol_event(struct hda_codec *codec, - unsigned int res) -{ - res >>= 26; - switch (res) { - case CONEXANT_HP_EVENT: - cxt5047_hp2_automute(codec); - break; - case CONEXANT_MIC_EVENT: - cxt5047_hp_automic(codec); - break; - } -} - -static struct snd_kcontrol_new cxt5047_mixers[] = { - HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Gain Volume", 0x1a, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Mic Gain Switch", 0x1a, 0x0, HDA_OUTPUT), +static struct snd_kcontrol_new cxt5047_base_mixers[] = { + HDA_CODEC_VOLUME("Mic Playback Volume", 0x19, 0x02, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x19, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Boost", 0x1a, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), - HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x00, HDA_OUTPUT), - HDA_CODEC_MUTE("Speaker Playback Switch", 0x1d, 0x00, HDA_OUTPUT), - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x13, 0x00, HDA_OUTPUT), - - {} -}; - -static struct snd_kcontrol_new cxt5047_toshiba_mixers[] = { - HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), - HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), - HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT), - HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x00, HDA_OUTPUT), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Master Playback Switch", @@ -1322,22 +1275,14 @@ static struct snd_kcontrol_new cxt5047_toshiba_mixers[] = { {} }; -static struct snd_kcontrol_new cxt5047_hp_mixers[] = { - HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19,0x02,HDA_INPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), - HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), - HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), +static struct snd_kcontrol_new cxt5047_hp_spk_mixers[] = { + HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x00, HDA_OUTPUT), + HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT), + {} +}; + +static struct snd_kcontrol_new cxt5047_hp_only_mixers[] = { HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = cxt_eapd_info, - .get = cxt_eapd_get, - .put = cxt5047_hp_master_sw_put, - .private_value = 0x13, - }, { } /* end */ }; @@ -1559,7 +1504,7 @@ static int patch_cxt5047(struct hda_codec *codec) spec->adc_nids = cxt5047_adc_nids; spec->capsrc_nids = cxt5047_capsrc_nids; spec->num_mixers = 1; - spec->mixers[0] = cxt5047_mixers; + spec->mixers[0] = cxt5047_base_mixers; spec->num_init_verbs = 1; spec->init_verbs[0] = cxt5047_init_verbs; spec->spdif_route = 0; @@ -1573,18 +1518,22 @@ static int patch_cxt5047(struct hda_codec *codec) cxt5047_cfg_tbl); switch (board_config) { case CXT5047_LAPTOP: - codec->patch_ops.unsol_event = cxt5047_hp2_unsol_event; + spec->num_mixers = 2; + spec->mixers[1] = cxt5047_hp_spk_mixers; + codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; break; case CXT5047_LAPTOP_HP: - spec->mixers[0] = cxt5047_hp_mixers; + spec->num_mixers = 2; + spec->mixers[1] = cxt5047_hp_only_mixers; codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; codec->patch_ops.init = cxt5047_hp_init; break; case CXT5047_LAPTOP_EAPD: spec->input_mux = &cxt5047_toshiba_capture_source; + spec->num_mixers = 2; + spec->mixers[1] = cxt5047_hp_spk_mixers; spec->num_init_verbs = 2; spec->init_verbs[1] = cxt5047_toshiba_init_verbs; - spec->mixers[0] = cxt5047_toshiba_mixers; codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; break; #ifdef CONFIG_SND_DEBUG -- GitLab From 14cbba89ae967d2e9106a80b270b078d7699109a Mon Sep 17 00:00:00 2001 From: Hugo Villeneuve Date: Mon, 9 Mar 2009 23:32:07 -0400 Subject: [PATCH 3054/4982] ALSA: ASoC: Davinci: Replaced DAI format RIGHT_J by DSP_B for SFFSDR Signed-off-by: Hugo Villeneuve Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-sffsdr.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c index 0bf81abba8c..a1ae3736a5d 100644 --- a/sound/soc/davinci/davinci-sffsdr.c +++ b/sound/soc/davinci/davinci-sffsdr.c @@ -36,6 +36,14 @@ #include "davinci-pcm.h" #include "davinci-i2s.h" +/* + * CLKX and CLKR are the inputs for the Sample Rate Generator. + * FSX and FSR are outputs, driven by the sample Rate Generator. + */ +#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ + SND_SOC_DAIFMT_CBM_CFS | \ + SND_SOC_DAIFMT_IB_NF) + static int sffsdr_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) @@ -56,13 +64,8 @@ static int sffsdr_hw_params(struct snd_pcm_substream *substream, } #endif - /* Set cpu DAI configuration: - * CLKX and CLKR are the inputs for the Sample Rate Generator. - * FSX and FSR are outputs, driven by the sample Rate Generator. */ - ret = snd_soc_dai_set_fmt(cpu_dai, - SND_SOC_DAIFMT_RIGHT_J | - SND_SOC_DAIFMT_CBM_CFS | - SND_SOC_DAIFMT_IB_NF); + /* set cpu DAI configuration */ + ret = snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT); if (ret < 0) return ret; -- GitLab From 090cec81ae9b4ff0c1d301b722f0e6c5fb72d8f9 Mon Sep 17 00:00:00 2001 From: Hugo Villeneuve Date: Mon, 9 Mar 2009 23:32:08 -0400 Subject: [PATCH 3055/4982] ALSA: ASoC: Davinci: Updated sffsdr_hw_params() function to new format Signed-off-by: Hugo Villeneuve Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-sffsdr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c index a1ae3736a5d..40eccfe9e35 100644 --- a/sound/soc/davinci/davinci-sffsdr.c +++ b/sound/soc/davinci/davinci-sffsdr.c @@ -45,8 +45,7 @@ SND_SOC_DAIFMT_IB_NF) static int sffsdr_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) + struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; -- GitLab From 57310a98a354e84279d7c8af2f48805a62372e53 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 9 Mar 2009 13:56:21 +0100 Subject: [PATCH 3056/4982] sched: optimize ttwu vs group scheduling Impact: micro-optimization We can avoid the sched domain walk on try_to_wake_up() when we know there are no groups. Signed-off-by: Peter Zijlstra LKML-Reference: <1236603381.8389.455.camel@laptop> Signed-off-by: Ingo Molnar --- kernel/sched.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/kernel/sched.c b/kernel/sched.c index e0fa739a441..af5cd1b2d03 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -331,6 +331,13 @@ static DEFINE_PER_CPU(struct rt_rq, init_rt_rq) ____cacheline_aligned_in_smp; */ static DEFINE_SPINLOCK(task_group_lock); +#ifdef CONFIG_SMP +static int root_task_group_empty(void) +{ + return list_empty(&root_task_group.children); +} +#endif + #ifdef CONFIG_FAIR_GROUP_SCHED #ifdef CONFIG_USER_SCHED # define INIT_TASK_GROUP_LOAD (2*NICE_0_LOAD) @@ -391,6 +398,13 @@ static inline void set_task_rq(struct task_struct *p, unsigned int cpu) #else +#ifdef CONFIG_SMP +static int root_task_group_empty(void) +{ + return 1; +} +#endif + static inline void set_task_rq(struct task_struct *p, unsigned int cpu) { } static inline struct task_group *task_group(struct task_struct *p) { @@ -2318,7 +2332,7 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync) sync = 0; #ifdef CONFIG_SMP - if (sched_feat(LB_WAKEUP_UPDATE)) { + if (sched_feat(LB_WAKEUP_UPDATE) && !root_task_group_empty()) { struct sched_domain *sd; this_cpu = raw_smp_processor_id(); -- GitLab From 5b3d515fcfe93d012107b9bd4895e2d913cbe8c3 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 12 Dec 2008 00:24:38 +0000 Subject: [PATCH 3057/4982] [ARM] S3C64XX: Add modem registers and a virtual map Add the modem registers and a virtual mapping for the modem block. This is is required as there are registers that control the LCD block that need to be saved over suspend as well as interrupt controls. Signed-off-by: Ben Dooks --- arch/arm/mach-s3c6400/include/mach/map.h | 3 ++ arch/arm/plat-s3c64xx/cpu.c | 5 +++ .../plat-s3c64xx/include/plat/regs-modem.h | 31 +++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 arch/arm/plat-s3c64xx/include/plat/regs-modem.h diff --git a/arch/arm/mach-s3c6400/include/mach/map.h b/arch/arm/mach-s3c6400/include/mach/map.h index cff27d813fc..baf1c0f1ea5 100644 --- a/arch/arm/mach-s3c6400/include/mach/map.h +++ b/arch/arm/mach-s3c6400/include/mach/map.h @@ -52,6 +52,9 @@ #define S3C64XX_PA_VIC0 (0x71200000) #define S3C64XX_PA_VIC1 (0x71300000) +#define S3C64XX_PA_MODEM (0x74108000) +#define S3C64XX_VA_MODEM S3C_ADDR(0x00600000) + /* place VICs close together */ #define S3C_VA_VIC0 (S3C_VA_IRQ + 0x00) #define S3C_VA_VIC1 (S3C_VA_IRQ + 0x10000) diff --git a/arch/arm/plat-s3c64xx/cpu.c b/arch/arm/plat-s3c64xx/cpu.c index fbde183a456..91f49a3a665 100644 --- a/arch/arm/plat-s3c64xx/cpu.c +++ b/arch/arm/plat-s3c64xx/cpu.c @@ -96,6 +96,11 @@ static struct map_desc s3c_iodesc[] __initdata = { .pfn = __phys_to_pfn(S3C64XX_PA_GPIO), .length = SZ_4K, .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S3C64XX_VA_MODEM, + .pfn = __phys_to_pfn(S3C64XX_PA_MODEM), + .length = SZ_4K, + .type = MT_DEVICE, }, }; diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-modem.h b/arch/arm/plat-s3c64xx/include/plat/regs-modem.h new file mode 100644 index 00000000000..49f7759dedf --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/regs-modem.h @@ -0,0 +1,31 @@ +/* arch/arm/plat-s3c64xx/include/plat/regs-modem.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks + * + * S3C64XX - modem block registers + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __PLAT_S3C64XX_REGS_MODEM_H +#define __PLAT_S3C64XX_REGS_MODEM_H __FILE__ + +#define S3C64XX_MODEMREG(x) (S3C64XX_VA_MODEM + (x)) + +#define S3C64XX_MODEM_INT2AP S3C64XX_MODEMREG(0x0) +#define S3C64XX_MODEM_INT2MODEM S3C64XX_MODEMREG(0x4) +#define S3C64XX_MODEM_MIFCON S3C64XX_MODEMREG(0x8) +#define S3C64XX_MODEM_MIFPCON S3C64XX_MODEMREG(0xC) +#define S3C64XX_MODEM_INTCLR S3C64XX_MODEMREG(0x10) +#define S3C64XX_MODEM_DMA_TXADDR S3C64XX_MODEMREG(0x14) +#define S3C64XX_MODEM_DMA_RXADDR S3C64XX_MODEMREG(0x18) + +#define MIFPCON_INT2M_LEVEL (1 << 4) +#define MIFPCON_LCD_BYPASS (1 << 3) + +#endif /* __PLAT_S3C64XX_REGS_MODEM_H */ -- GitLab From 333053733f52fa8c8e44c621b7b17fe5df215d4a Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 12 Dec 2008 00:24:15 +0000 Subject: [PATCH 3058/4982] [ARM] S3C64XX: Add EINT group regs and move IRQ_EINT to regs-gpio.h Add definitions for the EINT group registers and move the EINT IRQ register definitions out of arch/arm/plat-s3c64xx/irq-eint.c so that they are available for re-use with PM and the other code. Signed-off-by: Ben Dooks --- .../arm/plat-s3c64xx/include/plat/regs-gpio.h | 78 +++++++++++++++---- arch/arm/plat-s3c64xx/irq-eint.c | 14 ---- 2 files changed, 61 insertions(+), 31 deletions(-) diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h b/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h index 75b873d8280..51a84cd6320 100644 --- a/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h +++ b/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h @@ -13,23 +13,67 @@ /* Base addresses for each of the banks */ -#define S3C64XX_GPA_BASE (S3C64XX_VA_GPIO + 0x0000) -#define S3C64XX_GPB_BASE (S3C64XX_VA_GPIO + 0x0020) -#define S3C64XX_GPC_BASE (S3C64XX_VA_GPIO + 0x0040) -#define S3C64XX_GPD_BASE (S3C64XX_VA_GPIO + 0x0060) -#define S3C64XX_GPE_BASE (S3C64XX_VA_GPIO + 0x0080) -#define S3C64XX_GPF_BASE (S3C64XX_VA_GPIO + 0x00A0) -#define S3C64XX_GPG_BASE (S3C64XX_VA_GPIO + 0x00C0) -#define S3C64XX_GPH_BASE (S3C64XX_VA_GPIO + 0x00E0) -#define S3C64XX_GPI_BASE (S3C64XX_VA_GPIO + 0x0100) -#define S3C64XX_GPJ_BASE (S3C64XX_VA_GPIO + 0x0120) -#define S3C64XX_GPK_BASE (S3C64XX_VA_GPIO + 0x0800) -#define S3C64XX_GPL_BASE (S3C64XX_VA_GPIO + 0x0810) -#define S3C64XX_GPM_BASE (S3C64XX_VA_GPIO + 0x0820) -#define S3C64XX_GPN_BASE (S3C64XX_VA_GPIO + 0x0830) -#define S3C64XX_GPO_BASE (S3C64XX_VA_GPIO + 0x0140) -#define S3C64XX_GPP_BASE (S3C64XX_VA_GPIO + 0x0160) -#define S3C64XX_GPQ_BASE (S3C64XX_VA_GPIO + 0x0180) +#define S3C64XX_GPIOREG(reg) (S3C64XX_VA_GPIO + (reg)) + +#define S3C64XX_GPA_BASE S3C64XX_GPIOREG(0x0000) +#define S3C64XX_GPB_BASE S3C64XX_GPIOREG(0x0020) +#define S3C64XX_GPC_BASE S3C64XX_GPIOREG(0x0040) +#define S3C64XX_GPD_BASE S3C64XX_GPIOREG(0x0060) +#define S3C64XX_GPE_BASE S3C64XX_GPIOREG(0x0080) +#define S3C64XX_GPF_BASE S3C64XX_GPIOREG(0x00A0) +#define S3C64XX_GPG_BASE S3C64XX_GPIOREG(0x00C0) +#define S3C64XX_GPH_BASE S3C64XX_GPIOREG(0x00E0) +#define S3C64XX_GPI_BASE S3C64XX_GPIOREG(0x0100) +#define S3C64XX_GPJ_BASE S3C64XX_GPIOREG(0x0120) +#define S3C64XX_GPK_BASE S3C64XX_GPIOREG(0x0800) +#define S3C64XX_GPL_BASE S3C64XX_GPIOREG(0x0810) +#define S3C64XX_GPM_BASE S3C64XX_GPIOREG(0x0820) +#define S3C64XX_GPN_BASE S3C64XX_GPIOREG(0x0830) +#define S3C64XX_GPO_BASE S3C64XX_GPIOREG(0x0140) +#define S3C64XX_GPP_BASE S3C64XX_GPIOREG(0x0160) +#define S3C64XX_GPQ_BASE S3C64XX_GPIOREG(0x0180) + +/* External interrupt registers */ + +#define S3C64XX_EINT12CON S3C64XX_GPIOREG(0x200) +#define S3C64XX_EINT34CON S3C64XX_GPIOREG(0x204) +#define S3C64XX_EINT56CON S3C64XX_GPIOREG(0x208) +#define S3C64XX_EINT78CON S3C64XX_GPIOREG(0x20C) +#define S3C64XX_EINT9CON S3C64XX_GPIOREG(0x210) + +#define S3C64XX_EINT12FLTCON S3C64XX_GPIOREG(0x220) +#define S3C64XX_EINT34FLTCON S3C64XX_GPIOREG(0x224) +#define S3C64XX_EINT56FLTCON S3C64XX_GPIOREG(0x228) +#define S3C64XX_EINT78FLTCON S3C64XX_GPIOREG(0x22C) +#define S3C64XX_EINT9FLTCON S3C64XX_GPIOREG(0x230) + +#define S3C64XX_EINT12MASK S3C64XX_GPIOREG(0x240) +#define S3C64XX_EINT34MASK S3C64XX_GPIOREG(0x244) +#define S3C64XX_EINT56MASK S3C64XX_GPIOREG(0x248) +#define S3C64XX_EINT78MASK S3C64XX_GPIOREG(0x24C) +#define S3C64XX_EINT9MASK S3C64XX_GPIOREG(0x250) + +#define S3C64XX_EINT12PEND S3C64XX_GPIOREG(0x260) +#define S3C64XX_EINT34PEND S3C64XX_GPIOREG(0x264) +#define S3C64XX_EINT56PEND S3C64XX_GPIOREG(0x268) +#define S3C64XX_EINT78PEND S3C64XX_GPIOREG(0x26C) +#define S3C64XX_EINT9PEND S3C64XX_GPIOREG(0x270) + +#define S3C64XX_PRIORITY S3C64XX_GPIOREG(0x280) +#define S3C64XX_PRIORITY_ARB(x) (1 << (x)) + +#define S3C64XX_SERVICE S3C64XX_GPIOREG(0x284) +#define S3C64XX_SERVICEPEND S3C64XX_GPIOREG(0x288) + +#define S3C64XX_EINT0CON0 S3C64XX_GPIOREG(0x900) +#define S3C64XX_EINT0CON1 S3C64XX_GPIOREG(0x904) +#define S3C64XX_EINT0FLTCON0 S3C64XX_GPIOREG(0x910) +#define S3C64XX_EINT0FLTCON1 S3C64XX_GPIOREG(0x914) +#define S3C64XX_EINT0FLTCON2 S3C64XX_GPIOREG(0x918) +#define S3C64XX_EINT0FLTCON3 S3C64XX_GPIOREG(0x91C) + +#define S3C64XX_EINT0MASK S3C64XX_GPIOREG(0x920) +#define S3C64XX_EINT0PEND S3C64XX_GPIOREG(0x924) #endif /* __ASM_PLAT_S3C64XX_REGS_GPIO_H */ diff --git a/arch/arm/plat-s3c64xx/irq-eint.c b/arch/arm/plat-s3c64xx/irq-eint.c index cf524826c93..47e5155bb13 100644 --- a/arch/arm/plat-s3c64xx/irq-eint.c +++ b/arch/arm/plat-s3c64xx/irq-eint.c @@ -27,20 +27,6 @@ #include #include -/* GPIO is 0x7F008xxx, */ -#define S3C64XX_GPIOREG(x) (S3C64XX_VA_GPIO + (x)) - -#define S3C64XX_EINT0CON0 S3C64XX_GPIOREG(0x900) -#define S3C64XX_EINT0CON1 S3C64XX_GPIOREG(0x904) -#define S3C64XX_EINT0FLTCON0 S3C64XX_GPIOREG(0x910) -#define S3C64XX_EINT0FLTCON1 S3C64XX_GPIOREG(0x914) -#define S3C64XX_EINT0FLTCON2 S3C64XX_GPIOREG(0x918) -#define S3C64XX_EINT0FLTCON3 S3C64XX_GPIOREG(0x91C) - -#define S3C64XX_EINT0MASK S3C64XX_GPIOREG(0x920) -#define S3C64XX_EINT0PEND S3C64XX_GPIOREG(0x924) - - #define eint_offset(irq) ((irq) - IRQ_EINT(0)) #define eint_irq_to_bit(irq) (1 << eint_offset(irq)) -- GitLab From e383707131910337afadfc202c58a70361a9ea7c Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 12 Dec 2008 00:24:17 +0000 Subject: [PATCH 3059/4982] [ARM] S3C64XX: Add GPIO SPCONSLP and SLPEN register definitions Add GPIO register definitions for SPCONSLP and SLPEN for controlling the state of the pins over sleep. Signed-off-by: Ben Dooks --- .../arm/plat-s3c64xx/include/plat/regs-gpio.h | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h b/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h index 51a84cd6320..d45d66b8c2f 100644 --- a/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h +++ b/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h @@ -33,6 +33,10 @@ #define S3C64XX_GPP_BASE S3C64XX_GPIOREG(0x0160) #define S3C64XX_GPQ_BASE S3C64XX_GPIOREG(0x0180) +/* SPCON */ + +#define S3C64XX_SPCON S3C64XX_GPIOREG(0x1A0) + /* External interrupt registers */ #define S3C64XX_EINT12CON S3C64XX_GPIOREG(0x200) @@ -75,5 +79,28 @@ #define S3C64XX_EINT0MASK S3C64XX_GPIOREG(0x920) #define S3C64XX_EINT0PEND S3C64XX_GPIOREG(0x924) +/* GPIO sleep configuration */ + +#define S3C64XX_SPCONSLP S3C64XX_GPIOREG(0x880) + +#define S3C64XX_SPCONSLP_TDO_PULLDOWN (1 << 14) +#define S3C64XX_SPCONSLP_CKE1INIT (1 << 5) + +#define S3C64XX_SPCONSLP_RSTOUT_MASK (0x3 << 12) +#define S3C64XX_SPCONSLP_RSTOUT_OUT0 (0x0 << 12) +#define S3C64XX_SPCONSLP_RSTOUT_OUT1 (0x1 << 12) +#define S3C64XX_SPCONSLP_RSTOUT_HIZ (0x2 << 12) + +#define S3C64XX_SPCONSLP_KPCOL_MASK (0x3 << 0) +#define S3C64XX_SPCONSLP_KPCOL_OUT0 (0x0 << 0) +#define S3C64XX_SPCONSLP_KPCOL_OUT1 (0x1 << 0) +#define S3C64XX_SPCONSLP_KPCOL_INP (0x2 << 0) + + +#define S3C64XX_SLPEN S3C64XX_GPIOREG(0x930) + +#define S3C64XX_SLPEN_USE_xSLP (1 << 0) +#define S3C64XX_SLPEN_CFG_BYSLPEN (1 << 1) + #endif /* __ASM_PLAT_S3C64XX_REGS_GPIO_H */ -- GitLab From 2454e524bcfd8b2fefa28af0f33bfcd376ecdfcb Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 12 Dec 2008 00:24:39 +0000 Subject: [PATCH 3060/4982] [ARM] S3C64XX: Add S3C64XX_SPCON register bit definitions Add the definitions for the SPCON register in the GPIO block. Signed-off-by: Ben Dooks --- .../arm/plat-s3c64xx/include/plat/regs-gpio.h | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h b/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h index d45d66b8c2f..81f7f6e6832 100644 --- a/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h +++ b/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h @@ -37,6 +37,87 @@ #define S3C64XX_SPCON S3C64XX_GPIOREG(0x1A0) +#define S3C64XX_SPCON_DRVCON_CAM_MASK (0x3 << 30) +#define S3C64XX_SPCON_DRVCON_CAM_SHIFT (30) +#define S3C64XX_SPCON_DRVCON_CAM_2mA (0x0 << 30) +#define S3C64XX_SPCON_DRVCON_CAM_4mA (0x1 << 30) +#define S3C64XX_SPCON_DRVCON_CAM_7mA (0x2 << 30) +#define S3C64XX_SPCON_DRVCON_CAM_9mA (0x3 << 30) + +#define S3C64XX_SPCON_DRVCON_HSSPI_MASK (0x3 << 28) +#define S3C64XX_SPCON_DRVCON_HSSPI_SHIFT (28) +#define S3C64XX_SPCON_DRVCON_HSSPI_2mA (0x0 << 28) +#define S3C64XX_SPCON_DRVCON_HSSPI_4mA (0x1 << 28) +#define S3C64XX_SPCON_DRVCON_HSSPI_7mA (0x2 << 28) +#define S3C64XX_SPCON_DRVCON_HSSPI_9mA (0x3 << 28) + +#define S3C64XX_SPCON_DRVCON_HSMMC_MASK (0x3 << 26) +#define S3C64XX_SPCON_DRVCON_HSMMC_SHIFT (26) +#define S3C64XX_SPCON_DRVCON_HSMMC_2mA (0x0 << 26) +#define S3C64XX_SPCON_DRVCON_HSMMC_4mA (0x1 << 26) +#define S3C64XX_SPCON_DRVCON_HSMMC_7mA (0x2 << 26) +#define S3C64XX_SPCON_DRVCON_HSMMC_9mA (0x3 << 26) + +#define S3C64XX_SPCON_DRVCON_LCD_MASK (0x3 << 24) +#define S3C64XX_SPCON_DRVCON_LCD_SHIFT (24) +#define S3C64XX_SPCON_DRVCON_LCD_2mA (0x0 << 24) +#define S3C64XX_SPCON_DRVCON_LCD_4mA (0x1 << 24) +#define S3C64XX_SPCON_DRVCON_LCD_7mA (0x2 << 24) +#define S3C64XX_SPCON_DRVCON_LCD_9mA (0x3 << 24) + +#define S3C64XX_SPCON_DRVCON_MODEM_MASK (0x3 << 22) +#define S3C64XX_SPCON_DRVCON_MODEM_SHIFT (22) +#define S3C64XX_SPCON_DRVCON_MODEM_2mA (0x0 << 22) +#define S3C64XX_SPCON_DRVCON_MODEM_4mA (0x1 << 22) +#define S3C64XX_SPCON_DRVCON_MODEM_7mA (0x2 << 22) +#define S3C64XX_SPCON_DRVCON_MODEM_9mA (0x3 << 22) + +#define S3C64XX_SPCON_nRSTOUT_OEN (1 << 21) + +#define S3C64XX_SPCON_DRVCON_SPICLK1_MASK (0x3 << 18) +#define S3C64XX_SPCON_DRVCON_SPICLK1_SHIFT (18) +#define S3C64XX_SPCON_DRVCON_SPICLK1_2mA (0x0 << 18) +#define S3C64XX_SPCON_DRVCON_SPICLK1_4mA (0x1 << 18) +#define S3C64XX_SPCON_DRVCON_SPICLK1_7mA (0x2 << 18) +#define S3C64XX_SPCON_DRVCON_SPICLK1_9mA (0x3 << 18) + +#define S3C64XX_SPCON_MEM1_DQS_PUD_MASK (0x3 << 16) +#define S3C64XX_SPCON_MEM1_DQS_PUD_SHIFT (16) +#define S3C64XX_SPCON_MEM1_DQS_PUD_DISABLED (0x0 << 16) +#define S3C64XX_SPCON_MEM1_DQS_PUD_DOWN (0x1 << 16) +#define S3C64XX_SPCON_MEM1_DQS_PUD_UP (0x2 << 16) + +#define S3C64XX_SPCON_MEM1_D_PUD1_MASK (0x3 << 14) +#define S3C64XX_SPCON_MEM1_D_PUD1_SHIFT (14) +#define S3C64XX_SPCON_MEM1_D_PUD1_DISABLED (0x0 << 14) +#define S3C64XX_SPCON_MEM1_D_PUD1_DOWN (0x1 << 14) +#define S3C64XX_SPCON_MEM1_D_PUD1_UP (0x2 << 14) + +#define S3C64XX_SPCON_MEM1_D_PUD0_MASK (0x3 << 12) +#define S3C64XX_SPCON_MEM1_D_PUD0_SHIFT (12) +#define S3C64XX_SPCON_MEM1_D_PUD0_DISABLED (0x0 << 12) +#define S3C64XX_SPCON_MEM1_D_PUD0_DOWN (0x1 << 12) +#define S3C64XX_SPCON_MEM1_D_PUD0_UP (0x2 << 12) + +#define S3C64XX_SPCON_MEM0_D_PUD_MASK (0x3 << 8) +#define S3C64XX_SPCON_MEM0_D_PUD_SHIFT (8) +#define S3C64XX_SPCON_MEM0_D_PUD_DISABLED (0x0 << 8) +#define S3C64XX_SPCON_MEM0_D_PUD_DOWN (0x1 << 8) +#define S3C64XX_SPCON_MEM0_D_PUD_UP (0x2 << 8) + +#define S3C64XX_SPCON_USBH_DMPD (1 << 7) +#define S3C64XX_SPCON_USBH_DPPD (1 << 6) +#define S3C64XX_SPCON_USBH_PUSW2 (1 << 5) +#define S3C64XX_SPCON_USBH_PUSW1 (1 << 4) +#define S3C64XX_SPCON_USBH_SUSPND (1 << 3) + +#define S3C64XX_SPCON_LCD_SEL_MASK (0x3 << 0) +#define S3C64XX_SPCON_LCD_SEL_SHIFT (0) +#define S3C64XX_SPCON_LCD_SEL_HOST (0x0 << 0) +#define S3C64XX_SPCON_LCD_SEL_RGB (0x1 << 0) +#define S3C64XX_SPCON_LCD_SEL_606_656 (0x2 << 0) + + /* External interrupt registers */ #define S3C64XX_EINT12CON S3C64XX_GPIOREG(0x200) -- GitLab From 2ae0b117a62c46c233c421e94fd4692ad562d1c7 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 12 Dec 2008 00:24:02 +0000 Subject: [PATCH 3061/4982] [ARM] S3C64XX: SYSCON power and sleep control register defines Add the register defines for the sleep and power control functions in the S3C64XX SYSCON register block. Signed-off-by: Ben Dooks --- .../include/plat/regs-syscon-power.h | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 arch/arm/plat-s3c64xx/include/plat/regs-syscon-power.h diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-syscon-power.h b/arch/arm/plat-s3c64xx/include/plat/regs-syscon-power.h new file mode 100644 index 00000000000..270d96ac970 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/regs-syscon-power.h @@ -0,0 +1,116 @@ +/* arch/arm/plat-s3c64xx/include/plat/regs-syscon-power.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks + * + * S3C64XX - syscon power and sleep control registers + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __PLAT_S3C64XX_REGS_SYSCON_POWER_H +#define __PLAT_S3C64XX_REGS_SYSCON_POWER_H __FILE__ + +#define S3C64XX_PWR_CFG S3C_SYSREG(0x804) + +#define S3C64XX_PWRCFG_OSC_OTG_DISABLE (1 << 17) +#define S3C64XX_PWRCFG_MMC2_DISABLE (1 << 16) +#define S3C64XX_PWRCFG_MMC1_DISABLE (1 << 15) +#define S3C64XX_PWRCFG_MMC0_DISABLE (1 << 14) +#define S3C64XX_PWRCFG_HSI_DISABLE (1 << 13) +#define S3C64XX_PWRCFG_TS_DISABLE (1 << 12) +#define S3C64XX_PWRCFG_RTC_TICK_DISABLE (1 << 11) +#define S3C64XX_PWRCFG_RTC_ALARM_DISABLE (1 << 10) +#define S3C64XX_PWRCFG_MSM_DISABLE (1 << 9) +#define S3C64XX_PWRCFG_KEY_DISABLE (1 << 8) +#define S3C64XX_PWRCFG_BATF_DISABLE (1 << 7) + +#define S3C64XX_PWRCFG_CFG_WFI_MASK (0x3 << 5) +#define S3C64XX_PWRCFG_CFG_WFI_SHIFT (5) +#define S3C64XX_PWRCFG_CFG_WFI_IGNORE (0x0 << 5) +#define S3C64XX_PWRCFG_CFG_WFI_IDLE (0x1 << 5) +#define S3C64XX_PWRCFG_CFG_WFI_STOP (0x2 << 5) +#define S3C64XX_PWRCFG_CFG_WFI_SLEEP (0x3 << 5) + +#define S3C64XX_PWRCFG_CFG_BATFLT_MASK (0x3 << 3) +#define S3C64XX_PWRCFG_CFG_BATFLT_SHIFT (3) +#define S3C64XX_PWRCFG_CFG_BATFLT_IGNORE (0x0 << 3) +#define S3C64XX_PWRCFG_CFG_BATFLT_IRQ (0x1 << 3) +#define S3C64XX_PWRCFG_CFG_BATFLT_SLEEP (0x3 << 3) + +#define S3C64XX_PWRCFG_CFG_BAT_WAKE (1 << 2) +#define S3C64XX_PWRCFG_OSC27_EN (1 << 0) + +#define S3C64XX_EINT_MASK S3C_SYSREG(0x808) + +#define S3C64XX_NORMAL_CFG S3C_SYSREG(0x810) + +#define S3C64XX_NORMALCFG_IROM_ON (1 << 30) +#define S3C64XX_NORMALCFG_DOMAIN_ETM_ON (1 << 16) +#define S3C64XX_NORMALCFG_DOMAIN_S_ON (1 << 15) +#define S3C64XX_NORMALCFG_DOMAIN_F_ON (1 << 14) +#define S3C64XX_NORMALCFG_DOMAIN_P_ON (1 << 13) +#define S3C64XX_NORMALCFG_DOMAIN_I_ON (1 << 12) +#define S3C64XX_NORMALCFG_DOMAIN_G_ON (1 << 10) +#define S3C64XX_NORMALCFG_DOMAIN_V_ON (1 << 9) + +#define S3C64XX_STOP_CFG S3C_SYSREG(0x814) + +#define S3C64XX_STOPCFG_MEMORY_ARM_ON (1 << 29) +#define S3C64XX_STOPCFG_TOP_MEMORY_ON (1 << 20) +#define S3C64XX_STOPCFG_ARM_LOGIC_ON (1 << 17) +#define S3C64XX_STOPCFG_TOP_LOGIC_ON (1 << 8) +#define S3C64XX_STOPCFG_OSC_EN (1 << 0) + +#define S3C64XX_SLEEP_CFG S3C_SYSREG(0x818) + +#define S3C64XX_SLEEPCFG_OSC_EN (1 << 0) + +#define S3C64XX_STOP_MEM_CFG S3C_SYSREG(0x81c) + +#define S3C64XX_STOPMEMCFG_MODEMIF_RETAIN (1 << 6) +#define S3C64XX_STOPMEMCFG_HOSTIF_RETAIN (1 << 5) +#define S3C64XX_STOPMEMCFG_OTG_RETAIN (1 << 4) +#define S3C64XX_STOPMEMCFG_HSMCC_RETAIN (1 << 3) +#define S3C64XX_STOPMEMCFG_IROM_RETAIN (1 << 2) +#define S3C64XX_STOPMEMCFG_IRDA_RETAIN (1 << 1) +#define S3C64XX_STOPMEMCFG_NFCON_RETAIN (1 << 0) + +#define S3C64XX_OSC_STABLE S3C_SYSREG(0x824) +#define S3C64XX_PWR_STABLE S3C_SYSREG(0x828) + +#define S3C64XX_WAKEUP_STAT S3C_SYSREG(0x908) + +#define S3C64XX_WAKEUPSTAT_MMC2 (1 << 11) +#define S3C64XX_WAKEUPSTAT_MMC1 (1 << 10) +#define S3C64XX_WAKEUPSTAT_MMC0 (1 << 9) +#define S3C64XX_WAKEUPSTAT_HSI (1 << 8) +#define S3C64XX_WAKEUPSTAT_BATFLT (1 << 6) +#define S3C64XX_WAKEUPSTAT_MSM (1 << 5) +#define S3C64XX_WAKEUPSTAT_KEY (1 << 4) +#define S3C64XX_WAKEUPSTAT_TS (1 << 3) +#define S3C64XX_WAKEUPSTAT_RTC_TICK (1 << 2) +#define S3C64XX_WAKEUPSTAT_RTC_ALARM (1 << 1) +#define S3C64XX_WAKEUPSTAT_EINT (1 << 0) + +#define S3C64XX_BLK_PWR_STAT S3C_SYSREG(0x90c) + +#define S3C64XX_BLKPWRSTAT_G (1 << 7) +#define S3C64XX_BLKPWRSTAT_ETM (1 << 6) +#define S3C64XX_BLKPWRSTAT_S (1 << 5) +#define S3C64XX_BLKPWRSTAT_F (1 << 4) +#define S3C64XX_BLKPWRSTAT_P (1 << 3) +#define S3C64XX_BLKPWRSTAT_I (1 << 2) +#define S3C64XX_BLKPWRSTAT_V (1 << 1) +#define S3C64XX_BLKPWRSTAT_TOP (1 << 0) + +#define S3C64XX_INFORM0 S3C_SYSREG(0xA00) +#define S3C64XX_INFORM1 S3C_SYSREG(0xA04) +#define S3C64XX_INFORM2 S3C_SYSREG(0xA08) +#define S3C64XX_INFORM3 S3C_SYSREG(0xA0C) + +#endif /* __PLAT_S3C64XX_REGS_SYSCON_POWER_H */ -- GitLab From 36d543a3b56dc7cddb63f5734e13db16066933a4 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 12 Dec 2008 00:24:04 +0000 Subject: [PATCH 3062/4982] [ARM] S3C64XX: Add definitions for the GPIO memory port configurations Add defines for the registers that control the GPIO pins that are run the memory interface. Signed-off-by: Ben Dooks --- .../include/plat/regs-gpio-memport.h | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 arch/arm/plat-s3c64xx/include/plat/regs-gpio-memport.h diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-gpio-memport.h b/arch/arm/plat-s3c64xx/include/plat/regs-gpio-memport.h new file mode 100644 index 00000000000..82342f6fd27 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/regs-gpio-memport.h @@ -0,0 +1,25 @@ +/* linux/arch/arm/plat-s3c64xx/include/mach/regs-gpio-memport.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks + * http://armlinux.simtec.co.uk/ + * + * S3C64XX - GPIO memory port register definitions + */ + +#ifndef __ASM_PLAT_S3C64XX_REGS_GPIO_MEMPORT_H +#define __ASM_PLAT_S3C64XX_REGS_GPIO_MEMPORT_H __FILE__ + +#define S3C64XX_MEM0CONSTOP S3C64XX_GPIOREG(0x1B0) +#define S3C64XX_MEM1CONSTOP S3C64XX_GPIOREG(0x1B4) + +#define S3C64XX_MEM0CONSLP0 S3C64XX_GPIOREG(0x1C0) +#define S3C64XX_MEM0CONSLP1 S3C64XX_GPIOREG(0x1C4) +#define S3C64XX_MEM1CONSLP S3C64XX_GPIOREG(0x1C8) + +#define S3C64XX_MEM0DRVCON S3C64XX_GPIOREG(0x1D0) +#define S3C64XX_MEM1DRVCON S3C64XX_GPIOREG(0x1D4) + +#endif /* __ASM_PLAT_S3C64XX_REGS_GPIO_MEMPORT_H */ + -- GitLab From 1288b670e6cb3745392de617f223672396f98d73 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 12 Dec 2008 00:24:16 +0000 Subject: [PATCH 3063/4982] [ARM] S3C64XX: add AHB_CON and SPCON register address definitions Add the address definitions for S3C64XX_AHB_CONx and SPCON registers for use in the PM code. Signed-off-by: Ben Dooks --- arch/arm/plat-s3c64xx/include/plat/regs-sys.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-sys.h b/arch/arm/plat-s3c64xx/include/plat/regs-sys.h index d8ed8291709..69b78d9f83b 100644 --- a/arch/arm/plat-s3c64xx/include/plat/regs-sys.h +++ b/arch/arm/plat-s3c64xx/include/plat/regs-sys.h @@ -17,6 +17,10 @@ #define S3C_SYSREG(x) (S3C_VA_SYS + (x)) +#define S3C64XX_AHB_CON0 S3C_SYSREG(0x100) +#define S3C64XX_AHB_CON1 S3C_SYSREG(0x104) +#define S3C64XX_AHB_CON2 S3C_SYSREG(0x108) + #define S3C64XX_OTHERS S3C_SYSREG(0x900) #define S3C64XX_OTHERS_USBMASK (1 << 16) -- GitLab From 4184ea7f908d95f329febc3665cf66da8568b467 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Tue, 10 Mar 2009 12:39:20 -0400 Subject: [PATCH 3064/4982] Btrfs: Fix locking around adding new space_info Storage allocated to different raid levels in btrfs is tracked by a btrfs_space_info structure, and all of the current space_infos are collected into a list_head. Most filesystems have 3 or 4 of these structs total, and the list is only changed when new raid levels are added or at unmount time. This commit adds rcu locking on the list head, and properly frees things at unmount time. It also clears the space_info->full flag whenever new space is added to the FS. The locking for the space info list goes like this: reads: protected by rcu_read_lock() writes: protected by the chunk_mutex At unmount time we don't need special locking because all the readers are gone. Signed-off-by: Chris Mason --- fs/btrfs/ctree.h | 9 +++++++++ fs/btrfs/extent-tree.c | 45 +++++++++++++++++++++++++++++++++++++++--- fs/btrfs/volumes.c | 2 ++ 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 82491ba8fa4..5e1d4e30e9d 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -784,7 +784,14 @@ struct btrfs_fs_info { struct list_head dirty_cowonly_roots; struct btrfs_fs_devices *fs_devices; + + /* + * the space_info list is almost entirely read only. It only changes + * when we add a new raid type to the FS, and that happens + * very rarely. RCU is used to protect it. + */ struct list_head space_info; + spinlock_t delalloc_lock; spinlock_t new_trans_lock; u64 delalloc_bytes; @@ -1797,6 +1804,8 @@ int btrfs_cleanup_reloc_trees(struct btrfs_root *root); int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len); u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags); void btrfs_set_inode_space_info(struct btrfs_root *root, struct inode *ionde); +void btrfs_clear_space_info_full(struct btrfs_fs_info *info); + int btrfs_check_metadata_free_space(struct btrfs_root *root); int btrfs_check_data_free_space(struct btrfs_root *root, struct inode *inode, u64 bytes); diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 9abf81f71c4..fefe83ad205 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "compat.h" #include "hash.h" #include "crc32c.h" @@ -330,13 +331,33 @@ static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info, { struct list_head *head = &info->space_info; struct btrfs_space_info *found; - list_for_each_entry(found, head, list) { - if (found->flags == flags) + + rcu_read_lock(); + list_for_each_entry_rcu(found, head, list) { + if (found->flags == flags) { + rcu_read_unlock(); return found; + } } + rcu_read_unlock(); return NULL; } +/* + * after adding space to the filesystem, we need to clear the full flags + * on all the space infos. + */ +void btrfs_clear_space_info_full(struct btrfs_fs_info *info) +{ + struct list_head *head = &info->space_info; + struct btrfs_space_info *found; + + rcu_read_lock(); + list_for_each_entry_rcu(found, head, list) + found->full = 0; + rcu_read_unlock(); +} + static u64 div_factor(u64 num, int factor) { if (factor == 10) @@ -1903,7 +1924,6 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags, if (!found) return -ENOMEM; - list_add(&found->list, &info->space_info); INIT_LIST_HEAD(&found->block_groups); init_rwsem(&found->groups_sem); spin_lock_init(&found->lock); @@ -1917,6 +1937,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags, found->full = 0; found->force_alloc = 0; *space_info = found; + list_add_rcu(&found->list, &info->space_info); return 0; } @@ -6320,6 +6341,7 @@ out: int btrfs_free_block_groups(struct btrfs_fs_info *info) { struct btrfs_block_group_cache *block_group; + struct btrfs_space_info *space_info; struct rb_node *n; spin_lock(&info->block_group_cache_lock); @@ -6341,6 +6363,23 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info) spin_lock(&info->block_group_cache_lock); } spin_unlock(&info->block_group_cache_lock); + + /* now that all the block groups are freed, go through and + * free all the space_info structs. This is only called during + * the final stages of unmount, and so we know nobody is + * using them. We call synchronize_rcu() once before we start, + * just to be on the safe side. + */ + synchronize_rcu(); + + while(!list_empty(&info->space_info)) { + space_info = list_entry(info->space_info.next, + struct btrfs_space_info, + list); + + list_del(&space_info->list); + kfree(space_info); + } return 0; } diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 1316139bf9e..7aa3810d7f6 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1459,6 +1459,8 @@ static int __btrfs_grow_device(struct btrfs_trans_handle *trans, device->fs_devices->total_rw_bytes += diff; device->total_bytes = new_size; + btrfs_clear_space_info_full(device->dev_root->fs_info); + return btrfs_update_device(trans, device); } -- GitLab From 913d952eb573c3d1f7487e83b5590e13e7cae2bd Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Tue, 10 Mar 2009 13:17:18 -0400 Subject: [PATCH 3065/4982] Btrfs: Clear space_info full when adding new devices The full flag on the space info structs tells the allocator not to try and allocate more chunks because the devices in the FS are fully allocated. When more devices are added, we need to clear the full flag so the allocator knows it has more space available. Signed-off-by: Chris Mason --- fs/btrfs/volumes.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 7aa3810d7f6..dd06e18e5aa 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1374,6 +1374,12 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) ret = btrfs_add_device(trans, root, device); } + /* + * we've got more storage, clear any full flags on the space + * infos + */ + btrfs_clear_space_info_full(root->fs_info); + unlock_chunks(root); btrfs_commit_transaction(trans, root); -- GitLab From f24ade3a3332811a512ed3b6c6aa69486719b1d8 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 10 Mar 2009 19:02:30 +0100 Subject: [PATCH 3066/4982] x86, sched_clock(): mark variables read-mostly Impact: micro-optimization There's a number of variables in the sched_clock() path that are in .data/.bss - but not marked __read_mostly. This creates the danger of accidental false cacheline sharing with some other, write-often variable. So mark them __read_mostly. Signed-off-by: Ingo Molnar --- arch/x86/kernel/tsc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 599e5816863..9c8b71531ca 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -17,20 +17,21 @@ #include #include -unsigned int cpu_khz; /* TSC clocks / usec, not used here */ +unsigned int __read_mostly cpu_khz; /* TSC clocks / usec, not used here */ EXPORT_SYMBOL(cpu_khz); -unsigned int tsc_khz; + +unsigned int __read_mostly tsc_khz; EXPORT_SYMBOL(tsc_khz); /* * TSC can be unstable due to cpufreq or due to unsynced TSCs */ -static int tsc_unstable; +static int __read_mostly tsc_unstable; /* native_sched_clock() is called before tsc_init(), so we must start with the TSC soft disabled to prevent erroneous rdtsc usage on !cpu_has_tsc processors */ -static int tsc_disabled = -1; +static int __read_mostly tsc_disabled = -1; static int tsc_clocksource_reliable; /* -- GitLab From ace14b82633960a2b6bf6a0b2640c63872a65562 Mon Sep 17 00:00:00 2001 From: Martin Michlmayr Date: Tue, 10 Mar 2009 08:59:58 +0100 Subject: [PATCH 3067/4982] [ARM] Orion: Fix some typos in the DNS-323 support code Fix some typos in the DNS-323 support code. Signed-off-by: Martin Michlmayr Signed-off-by: Nicolas Pitre --- arch/arm/mach-orion5x/dns323-setup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c index 0722d6510df..b31ca4cef36 100644 --- a/arch/arm/mach-orion5x/dns323-setup.c +++ b/arch/arm/mach-orion5x/dns323-setup.c @@ -76,7 +76,7 @@ static int __init dns323_dev_id(void) static int __init dns323_pci_init(void) { - /* The 5182 doesn't really use it's PCI bus, and initialising PCI + /* The 5182 doesn't really use its PCI bus, and initialising PCI * gets in the way of initialising the SATA controller. */ if (machine_is_dns323() && dns323_dev_id() != MV88F5182_DEV_ID) @@ -418,7 +418,7 @@ static void __init dns323_init(void) orion5x_i2c_init(); orion5x_uart0_init(); - /* The 5182 has it's SATA controller on-chip, and needs it's own little + /* The 5182 has its SATA controller on-chip, and needs its own little * init routine. */ if (dns323_dev_id() == MV88F5182_DEV_ID) -- GitLab From cbf1146d5ee113152c5cdeb54ff9d4b2f0c91736 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Tue, 10 Mar 2009 16:41:00 +0100 Subject: [PATCH 3068/4982] ASoC: don't touch pxa-ssp registers when stream is running In pxa_ssp_set_dai_fmt(), check whether there is anything to do at all. If there would be but the SSP port is in use already, bail out. Signed-off-by: Daniel Mack Signed-off-by: Mark Brown --- sound/soc/pxa/pxa-ssp.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 7fc13f03d1d..52d97c4b82b 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -522,6 +522,17 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, u32 sscr1; u32 sspsp; + /* check if we need to change anything at all */ + if (priv->dai_fmt == fmt) + return 0; + + /* we can only change the settings if the port is not in use */ + if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) { + dev_err(&ssp->pdev->dev, + "can't change hardware dai format: stream is in use"); + return -EINVAL; + } + /* reset port settings */ sscr0 = ssp_read_reg(ssp, SSCR0) & (SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS); -- GitLab From f455dfb106916d855d59686fe16575c2ceb2cb2a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 10 Mar 2009 19:51:07 +0000 Subject: [PATCH 3069/4982] ASoC: Fix up merge with the ARM tree The same change has been made with the final lines in slightly differnet orders. Signed-off-by: Mark Brown --- arch/arm/mach-shark/include/mach/io.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-shark/include/mach/io.h b/arch/arm/mach-shark/include/mach/io.h index 8ca7d7f09bd..568daea93fb 100644 --- a/arch/arm/mach-shark/include/mach/io.h +++ b/arch/arm/mach-shark/include/mach/io.h @@ -15,6 +15,7 @@ #define IO_SPACE_LIMIT 0xffffffff #define __io(a) __typesafe_io(PCIO_BASE + (a)) + #define __mem_pci(addr) (addr) #endif -- GitLab From 48e7a3c95c9f98c2cb6f894820e3cc2d0448e92f Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Tue, 10 Mar 2009 22:43:56 +0100 Subject: [PATCH 3070/4982] HID: fix incorrect free in hiddev If hiddev_open() fails, it wrongly frees the shared hiddev structure kept in hiddev_table instead of the hiddev_list structure allocated for the opened file descriptor. Existing references to this structure will then accessed free memory. This was introduced by 079034073 "HID: hiddev cleanup -- handle all error conditions properly". Signed-off-by: Johannes Weiner Cc: Oliver Neukum Cc: Jiri Kosina Signed-off-by: Andrew Morton Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hiddev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 4940e4d70c2..00ea1ed282a 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -306,7 +306,7 @@ static int hiddev_open(struct inode *inode, struct file *file) return 0; bail: file->private_data = NULL; - kfree(list->hiddev); + kfree(list); return res; } -- GitLab From 96fe2ab830d7dffee1b3d8abf27ced4d7d5765e7 Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Tue, 10 Mar 2009 22:44:01 +0100 Subject: [PATCH 3071/4982] HID: fix waitqueue usage in hiddev DECLARE_WAITQUEUE doesn't initialize the wait descriptor's task_list to 'empty' but to zero. prepare_to_wait() will not enqueue the descriptor to the waitqueue and finish_wait() will do list_del_init() on a list head that contains NULL pointers, which oopses. This was introduced by 079034073 "HID: hiddev cleanup -- handle all error conditions properly". The prior code used an unconditional add_to_waitqueue() which didn't care about the wait descriptor's list head and enqueued the thing unconditionally. The new code uses prepare_to_wait() which DOES check the prior list state, so use DEFINE_WAIT instead. Signed-off-by: Johannes Weiner Cc: Oliver Neukum Cc: Jiri Kosina Signed-off-by: Andrew Morton Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hiddev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 00ea1ed282a..1f5b5d4c3c3 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -323,7 +323,7 @@ static ssize_t hiddev_write(struct file * file, const char __user * buffer, size */ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) { - DECLARE_WAITQUEUE(wait, current); + DEFINE_WAIT(wait); struct hiddev_list *list = file->private_data; int event_size; int retval; -- GitLab From 395a87bfefbc400011417e9eaae33169f9f036c0 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Tue, 10 Mar 2009 18:18:47 -0400 Subject: [PATCH 3072/4982] ext4: fix header check in ext4_ext_search_right() for deep extent trees. The ext4_ext_search_right() function is confusing; it uses a "depth" variable which is 0 at the root and maximum at the leaves, but the on-disk metadata uses a "depth" (actually eh_depth) which is opposite: maximum at the root, and 0 at the leaves. The ext4_ext_check_header() function is given a depth and checks the header agaisnt that depth; it expects the on-disk semantics, but we are giving it the opposite in the while loop in this function. We should be giving it the on-disk notion of "depth" which we can get from (p_depth - depth) - and if you look, the last (more commonly hit) call to ext4_ext_check_header() does just this. Sending in the wrong depth results in (incorrect) messages about corruption: EXT4-fs error (device sdb1): ext4_ext_search_right: bad header in inode #2621457: unexpected eh_depth - magic f30a, entries 340, max 340(0), depth 1(2) http://bugzilla.kernel.org/show_bug.cgi?id=12821 Reported-by: David Dindorp Signed-off-by: Eric Sandeen Signed-off-by: "Theodore Ts'o" --- fs/ext4/extents.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index e2eab196875..e0aa4fe4f59 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -1122,7 +1122,8 @@ ext4_ext_search_right(struct inode *inode, struct ext4_ext_path *path, struct ext4_extent_idx *ix; struct ext4_extent *ex; ext4_fsblk_t block; - int depth, ee_len; + int depth; /* Note, NOT eh_depth; depth from top of tree */ + int ee_len; BUG_ON(path == NULL); depth = path->p_depth; @@ -1179,7 +1180,8 @@ got_index: if (bh == NULL) return -EIO; eh = ext_block_hdr(bh); - if (ext4_ext_check_header(inode, eh, depth)) { + /* subtract from p_depth to get proper eh_depth */ + if (ext4_ext_check_header(inode, eh, path->p_depth - depth)) { put_bh(bh); return -EIO; } -- GitLab From eb9b55ab4d73280597fd183b367d50452f4d7846 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 10 Mar 2009 20:33:16 -0400 Subject: [PATCH 3073/4982] SUNRPC: Tighten up the task locking rules in __rpc_execute() We should probably not be testing any flags after we've cleared the RPC_TASK_RUNNING flag, since rpc_make_runnable() is then free to assign the rpc_task to another workqueue, which may then destroy it. We can fix any races with rpc_make_runnable() by ensuring that we only clear the RPC_TASK_RUNNING flag while holding the rpc_wait_queue->lock that the task is supposed to be sleeping on (and then checking whether or not the task really is sleeping). Signed-off-by: Trond Myklebust --- net/sunrpc/sched.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 385f427beda..ff50a054686 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -293,11 +293,6 @@ static void rpc_make_runnable(struct rpc_task *task) rpc_clear_queued(task); if (rpc_test_and_set_running(task)) return; - /* We might have raced */ - if (RPC_IS_QUEUED(task)) { - rpc_clear_running(task); - return; - } if (RPC_IS_ASYNC(task)) { int status; @@ -607,7 +602,9 @@ void rpc_release_calldata(const struct rpc_call_ops *ops, void *calldata) */ static void __rpc_execute(struct rpc_task *task) { - int status = 0; + struct rpc_wait_queue *queue; + int task_is_async = RPC_IS_ASYNC(task); + int status = 0; dprintk("RPC: %5u __rpc_execute flags=0x%x\n", task->tk_pid, task->tk_flags); @@ -647,15 +644,25 @@ static void __rpc_execute(struct rpc_task *task) */ if (!RPC_IS_QUEUED(task)) continue; - rpc_clear_running(task); - if (RPC_IS_ASYNC(task)) { - /* Careful! we may have raced... */ - if (RPC_IS_QUEUED(task)) - return; - if (rpc_test_and_set_running(task)) - return; + /* + * The queue->lock protects against races with + * rpc_make_runnable(). + * + * Note that once we clear RPC_TASK_RUNNING on an asynchronous + * rpc_task, rpc_make_runnable() can assign it to a + * different workqueue. We therefore cannot assume that the + * rpc_task pointer may still be dereferenced. + */ + queue = task->tk_waitqueue; + spin_lock_bh(&queue->lock); + if (!RPC_IS_QUEUED(task)) { + spin_unlock_bh(&queue->lock); continue; } + rpc_clear_running(task); + spin_unlock_bh(&queue->lock); + if (task_is_async) + return; /* sync task: sleep here */ dprintk("RPC: %5u sync task going to sleep\n", task->tk_pid); -- GitLab From ef95d31e6de6be9602ce950b85fb7ab8af46ae42 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 10 Mar 2009 20:33:17 -0400 Subject: [PATCH 3074/4982] NFS: Fix misparsing of nfsv4 fs_locations attribute (take 2) The changeset ea31a4437c59219bf3ea946d58984b01a45a289c (nfs: Fix misparsing of nfsv4 fs_locations attribute) causes the mountpath that is calculated at the beginning of try_location() to be clobbered when we later strncpy a non-nul terminated hostname using an incorrect buffer length. Signed-off-by: Trond Myklebust --- fs/nfs/nfs4namespace.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index 30befc39b3c..2a2a0a7143a 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c @@ -21,7 +21,9 @@ #define NFSDBG_FACILITY NFSDBG_VFS /* - * Check if fs_root is valid + * Convert the NFSv4 pathname components into a standard posix path. + * + * Note that the resulting string will be placed at the end of the buffer */ static inline char *nfs4_pathname_string(const struct nfs4_pathname *pathname, char *buffer, ssize_t buflen) @@ -99,21 +101,20 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata, { struct vfsmount *mnt = ERR_PTR(-ENOENT); char *mnt_path; - int page2len; + unsigned int maxbuflen; unsigned int s; mnt_path = nfs4_pathname_string(&location->rootpath, page2, PAGE_SIZE); if (IS_ERR(mnt_path)) return mnt; mountdata->mnt_path = mnt_path; - page2 += strlen(mnt_path) + 1; - page2len = PAGE_SIZE - strlen(mnt_path) - 1; + maxbuflen = mnt_path - 1 - page2; for (s = 0; s < location->nservers; s++) { const struct nfs4_string *buf = &location->servers[s]; struct sockaddr_storage addr; - if (buf->len <= 0 || buf->len >= PAGE_SIZE) + if (buf->len <= 0 || buf->len >= maxbuflen) continue; mountdata->addr = (struct sockaddr *)&addr; @@ -126,8 +127,8 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata, continue; nfs_set_port(mountdata->addr, NFS_PORT); - strncpy(page2, buf->data, page2len); - page2[page2len] = '\0'; + memcpy(page2, buf->data, buf->len); + page2[buf->len] = '\0'; mountdata->hostname = page2; snprintf(page, PAGE_SIZE, "%s:%s", -- GitLab From ae46141ff08f1965b17c531b571953c39ce8b9e2 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 10 Mar 2009 20:33:18 -0400 Subject: [PATCH 3075/4982] NFSv3: Fix posix ACL code Fix a memory leak due to allocation in the XDR layer. In cases where the RPC call needs to be retransmitted, we end up allocating new pages without clearing the old ones. Fix this by moving the allocation into nfs3_proc_setacls(). Also fix an issue discovered by Kevin Rudd, whereby the amount of memory reserved for the acls in the xdr_buf->head was miscalculated, and causing corruption. Signed-off-by: Trond Myklebust --- fs/nfs/nfs3acl.c | 27 +++++++++++++++++++++------ fs/nfs/nfs3xdr.c | 34 +++++++++++++--------------------- include/linux/nfs_xdr.h | 2 ++ include/linux/nfsacl.h | 3 +++ 4 files changed, 39 insertions(+), 27 deletions(-) diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c index cef62557c87..6bbf0e6daad 100644 --- a/fs/nfs/nfs3acl.c +++ b/fs/nfs/nfs3acl.c @@ -292,7 +292,7 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, { struct nfs_server *server = NFS_SERVER(inode); struct nfs_fattr fattr; - struct page *pages[NFSACL_MAXPAGES] = { }; + struct page *pages[NFSACL_MAXPAGES]; struct nfs3_setaclargs args = { .inode = inode, .mask = NFS_ACL, @@ -303,7 +303,7 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, .rpc_argp = &args, .rpc_resp = &fattr, }; - int status, count; + int status; status = -EOPNOTSUPP; if (!nfs_server_capable(inode, NFS_CAP_ACLS)) @@ -319,6 +319,20 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, if (S_ISDIR(inode->i_mode)) { args.mask |= NFS_DFACL; args.acl_default = dfacl; + args.len = nfsacl_size(acl, dfacl); + } else + args.len = nfsacl_size(acl, NULL); + + if (args.len > NFS_ACL_INLINE_BUFSIZE) { + unsigned int npages = 1 + ((args.len - 1) >> PAGE_SHIFT); + + status = -ENOMEM; + do { + args.pages[args.npages] = alloc_page(GFP_KERNEL); + if (args.pages[args.npages] == NULL) + goto out_freepages; + args.npages++; + } while (args.npages < npages); } dprintk("NFS call setacl\n"); @@ -329,10 +343,6 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, nfs_zap_acl_cache(inode); dprintk("NFS reply setacl: %d\n", status); - /* pages may have been allocated at the xdr layer. */ - for (count = 0; count < NFSACL_MAXPAGES && args.pages[count]; count++) - __free_page(args.pages[count]); - switch (status) { case 0: status = nfs_refresh_inode(inode, &fattr); @@ -346,6 +356,11 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, case -ENOTSUPP: status = -EOPNOTSUPP; } +out_freepages: + while (args.npages != 0) { + args.npages--; + __free_page(args.pages[args.npages]); + } out: return status; } diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index 11cdddec143..6cdeacffde4 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c @@ -82,8 +82,10 @@ #define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2) #define ACL3_getaclargs_sz (NFS3_fh_sz+1) -#define ACL3_setaclargs_sz (NFS3_fh_sz+1+2*(2+5*3)) -#define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+2*(2+5*3)) +#define ACL3_setaclargs_sz (NFS3_fh_sz+1+ \ + XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE)) +#define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+ \ + XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE)) #define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz) /* @@ -703,28 +705,18 @@ nfs3_xdr_setaclargs(struct rpc_rqst *req, __be32 *p, struct nfs3_setaclargs *args) { struct xdr_buf *buf = &req->rq_snd_buf; - unsigned int base, len_in_head, len = nfsacl_size( - (args->mask & NFS_ACL) ? args->acl_access : NULL, - (args->mask & NFS_DFACL) ? args->acl_default : NULL); - int count, err; + unsigned int base; + int err; p = xdr_encode_fhandle(p, NFS_FH(args->inode)); *p++ = htonl(args->mask); - base = (char *)p - (char *)buf->head->iov_base; - /* put as much of the acls into head as possible. */ - len_in_head = min_t(unsigned int, buf->head->iov_len - base, len); - len -= len_in_head; - req->rq_slen = xdr_adjust_iovec(req->rq_svec, p + (len_in_head >> 2)); - - for (count = 0; (count << PAGE_SHIFT) < len; count++) { - args->pages[count] = alloc_page(GFP_KERNEL); - if (!args->pages[count]) { - while (count) - __free_page(args->pages[--count]); - return -ENOMEM; - } - } - xdr_encode_pages(buf, args->pages, 0, len); + req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); + base = req->rq_slen; + + if (args->npages != 0) + xdr_encode_pages(buf, args->pages, 0, args->len); + else + req->rq_slen += args->len; err = nfsacl_encode(buf, base, args->inode, (args->mask & NFS_ACL) ? diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index a550b528319..2e5f00066af 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -406,6 +406,8 @@ struct nfs3_setaclargs { int mask; struct posix_acl * acl_access; struct posix_acl * acl_default; + size_t len; + unsigned int npages; struct page ** pages; }; diff --git a/include/linux/nfsacl.h b/include/linux/nfsacl.h index 54487a99beb..43011b69297 100644 --- a/include/linux/nfsacl.h +++ b/include/linux/nfsacl.h @@ -37,6 +37,9 @@ #define NFSACL_MAXPAGES ((2*(8+12*NFS_ACL_MAX_ENTRIES) + PAGE_SIZE-1) \ >> PAGE_SHIFT) +#define NFS_ACL_MAX_ENTRIES_INLINE (5) +#define NFS_ACL_INLINE_BUFSIZE ((2*(2+3*NFS_ACL_MAX_ENTRIES_INLINE)) << 2) + static inline unsigned int nfsacl_size(struct posix_acl *acl_access, struct posix_acl *acl_default) { -- GitLab From 78851e1aa4c3b796d5f0bb11b445016726302b44 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 10 Mar 2009 20:33:19 -0400 Subject: [PATCH 3076/4982] NLM: Shrink the IPv4-only version of nlm_cmp_addr() Clean up/micro-optimatization: Make the AF_INET-only version of nlm_cmp_addr() smaller. This matches the style of nlm_privileged_requester(), and makes the AF_INET-only version of nlm_cmp_addr() nearly the same size as it was before IPv6 support. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust --- include/linux/lockd/lockd.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index aa6fe7026de..51855dfd8ad 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h @@ -346,6 +346,7 @@ static inline int __nlm_cmp_addr4(const struct sockaddr *sap1, return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr; } +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static inline int __nlm_cmp_addr6(const struct sockaddr *sap1, const struct sockaddr *sap2) { @@ -353,6 +354,13 @@ static inline int __nlm_cmp_addr6(const struct sockaddr *sap1, const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sap2; return ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr); } +#else /* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */ +static inline int __nlm_cmp_addr6(const struct sockaddr *sap1, + const struct sockaddr *sap2) +{ + return 0; +} +#endif /* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */ /* * Compare two host addresses -- GitLab From 57df675c60c5cf0748ddba9c7f85afde1530d74d Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 10 Mar 2009 20:33:20 -0400 Subject: [PATCH 3077/4982] NLM: Fix GRANT callback address comparison when IPv6 is enabled The NFS mount command may pass an AF_INET server address to lockd. If lockd happens to be using a PF_INET6 listener, the nlm_cmp_addr() in nlmclnt_grant() will fail to match requests from that host because they will all have a mapped IPv4 AF_INET6 address. Adopt the same solution used in nfs_sockaddr_match_ipaddr() for NFSv4 callbacks: if either address is AF_INET, map it to an AF_INET6 address before doing the comparison. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust --- fs/lockd/clntlock.c | 51 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index 1f3b0fc0d35..aedc47a264c 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c @@ -139,6 +139,55 @@ int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout) return 0; } +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +static const struct in6_addr *nlmclnt_map_v4addr(const struct sockaddr *sap, + struct in6_addr *addr_mapped) +{ + const struct sockaddr_in *sin = (const struct sockaddr_in *)sap; + + switch (sap->sa_family) { + case AF_INET6: + return &((const struct sockaddr_in6 *)sap)->sin6_addr; + case AF_INET: + ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, addr_mapped); + return addr_mapped; + } + + return NULL; +} + +/* + * If lockd is using a PF_INET6 listener, all incoming requests appear + * to come from AF_INET6 remotes. The address of AF_INET remotes are + * mapped to AF_INET6 automatically by the network layer. In case the + * user passed an AF_INET server address at mount time, ensure both + * addresses are AF_INET6 before comparing them. + */ +static int nlmclnt_cmp_addr(const struct nlm_host *host, + const struct sockaddr *sap) +{ + const struct in6_addr *addr1; + const struct in6_addr *addr2; + struct in6_addr addr1_mapped; + struct in6_addr addr2_mapped; + + addr1 = nlmclnt_map_v4addr(nlm_addr(host), &addr1_mapped); + if (likely(addr1 != NULL)) { + addr2 = nlmclnt_map_v4addr(sap, &addr2_mapped); + if (likely(addr2 != NULL)) + return ipv6_addr_equal(addr1, addr2); + } + + return 0; +} +#else /* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */ +static int nlmclnt_cmp_addr(const struct nlm_host *host, + const struct sockaddr *sap) +{ + return nlm_cmp_addr(nlm_addr(host), sap); +} +#endif /* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */ + /* * The server lockd has called us back to tell us the lock was granted */ @@ -166,7 +215,7 @@ __be32 nlmclnt_grant(const struct sockaddr *addr, const struct nlm_lock *lock) */ if (fl_blocked->fl_u.nfs_fl.owner->pid != lock->svid) continue; - if (!nlm_cmp_addr(nlm_addr(block->b_host), addr)) + if (!nlmclnt_cmp_addr(block->b_host, addr)) continue; if (nfs_compare_fh(NFS_FH(fl_blocked->fl_file->f_path.dentry->d_inode) ,fh) != 0) continue; -- GitLab From a71ee337b31271e701f689d544b6153b75609bc5 Mon Sep 17 00:00:00 2001 From: Suresh Jayaraman Date: Tue, 10 Mar 2009 20:33:21 -0400 Subject: [PATCH 3078/4982] NFS: Handle -ESTALE error in access() Hi Trond, I have been looking at a bugreport where trying to open applications on KDE on a NFS mounted home fails temporarily. There have been multiple reports on different kernel versions pointing to this common issue: http://bugzilla.kernel.org/show_bug.cgi?id=12557 https://bugs.launchpad.net/ubuntu/+source/linux/+bug/269954 http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=508866.html This issue can be reproducible consistently by doing this on a NFS mounted home (KDE): 1. Open 2 xterm sessions 2. From one of the xterm session, do "ssh -X " 3. "stat ~/.Xauthority" on the remote SSH session 4. Close the two xterm sessions 5. On the server do a "stat ~/.Xauthority" 6. Now on the client, try to open xterm This will fail. Even if the filehandle had become stale, the NFS client should invalidate the cache/inode and should repeat LOOKUP. Looking at the packet capture when the failure occurs shows that there were two subsequent ACCESS() calls with the same filehandle and both fails with -ESTALE error. I have tested the fix below. Now the client issue a LOOKUP after the ACCESS() call fails with -ESTALE. If all this makes sense to you, can you consider this for inclusion? Thanks, If the server returns an -ESTALE error due to stale filehandle in response to an ACCESS() call, we need to invalidate the cache and inode so that LOOKUP() can be retried. Without this change, the nfs client retries ACCESS() with the same filehandle, fails again and could lead to temporary failure of applications running on nfs mounted home. Signed-off-by: Suresh Jayaraman Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index e35c8199f82..672368f865c 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -1892,8 +1892,14 @@ static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask) cache.cred = cred; cache.jiffies = jiffies; status = NFS_PROTO(inode)->access(inode, &cache); - if (status != 0) + if (status != 0) { + if (status == -ESTALE) { + nfs_zap_caches(inode); + if (!S_ISDIR(inode->i_mode)) + set_bit(NFS_INO_STALE, &NFS_I(inode)->flags); + } return status; + } nfs_access_add_cache(inode, &cache); out: if ((mask & ~cache.mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0) -- GitLab From d7371c41b0cda782256b1df759df4e8d4724584c Mon Sep 17 00:00:00 2001 From: Ian Dall Date: Tue, 10 Mar 2009 20:33:22 -0400 Subject: [PATCH 3079/4982] Bug 11061, NFS mounts dropped Addresses: http://bugzilla.kernel.org/show_bug.cgi?id=11061 sockaddr structures can't be reliably compared using memcmp() because there are padding bytes in the structure which can't be guaranteed to be the same even when the sockaddr structures refer to the same socket. Instead compare all the relevant fields. In the case of IPv6 sin6_flowinfo is not compared because it only affects QoS and sin6_scope_id is only compared if the address is "link local" because "link local" addresses need only be unique to a specific link. Signed-off-by: Ian Dall Signed-off-by: Trond Myklebust --- fs/nfs/client.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 9b728f3565a..06654b831d1 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -272,6 +272,65 @@ static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1, } #endif +/* + * Test if two ip4 socket addresses refer to the same socket, by + * comparing relevant fields. The padding bytes specifically, are + * not compared. + * + * The caller should ensure both socket addresses are AF_INET. + */ +static int nfs_sockaddr_cmp_ip4(const struct sockaddr_in * saddr1, + const struct sockaddr_in * saddr2) +{ + if (saddr1->sin_addr.s_addr != saddr2->sin_addr.s_addr) + return 0; + return saddr1->sin_port == saddr2->sin_port; +} + +/* + * Test if two ip6 socket addresses refer to the same socket by + * comparing relevant fields. The padding bytes specifically, are not + * compared. sin6_flowinfo is not compared because it only affects QoS + * and sin6_scope_id is only compared if the address is "link local" + * because "link local" addresses need only be unique to a specific + * link. Conversely, ordinary unicast addresses might have different + * sin6_scope_id. + * + * The caller should ensure both socket addresses are AF_INET6. + */ +static int nfs_sockaddr_cmp_ip6 (const struct sockaddr_in6 * saddr1, + const struct sockaddr_in6 * saddr2) +{ + if (!ipv6_addr_equal(&saddr1->sin6_addr, + &saddr1->sin6_addr)) + return 0; + if (ipv6_addr_scope(&saddr1->sin6_addr) == IPV6_ADDR_SCOPE_LINKLOCAL && + saddr1->sin6_scope_id != saddr2->sin6_scope_id) + return 0; + return saddr1->sin6_port == saddr2->sin6_port; +} + +/* + * Test if two socket addresses represent the same actual socket, + * by comparing (only) relevant fields. + */ +static int nfs_sockaddr_cmp(const struct sockaddr *sa1, + const struct sockaddr *sa2) +{ + if (sa1->sa_family != sa2->sa_family) + return 0; + + switch (sa1->sa_family) { + case AF_INET: + return nfs_sockaddr_cmp_ip4((const struct sockaddr_in *) sa1, + (const struct sockaddr_in *) sa2); + case AF_INET6: + return nfs_sockaddr_cmp_ip6((const struct sockaddr_in6 *) sa1, + (const struct sockaddr_in6 *) sa2); + } + return 0; +} + /* * Find a client by IP address and protocol version * - returns NULL if no such client @@ -344,8 +403,10 @@ struct nfs_client *nfs_find_client_next(struct nfs_client *clp) static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *data) { struct nfs_client *clp; + const struct sockaddr *sap = data->addr; list_for_each_entry(clp, &nfs_client_list, cl_share_link) { + const struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr; /* Don't match clients that failed to initialise properly */ if (clp->cl_cons_state < 0) continue; @@ -358,7 +419,7 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat continue; /* Match the full socket address */ - if (memcmp(&clp->cl_addr, data->addr, sizeof(clp->cl_addr)) != 0) + if (!nfs_sockaddr_cmp(sap, clap)) continue; atomic_inc(&clp->cl_count); -- GitLab From 60db56422043aaa455ac7f858ce23c273220f9d9 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 11 Mar 2009 14:36:54 +0900 Subject: [PATCH 3080/4982] percpu: fix spurious alignment WARN in legacy SMP percpu allocator Impact: remove spurious WARN on legacy SMP percpu allocator Commit f2a8205c4ef1af917d175c36a4097ae5587791c8 incorrectly added too tight WARN_ON_ONCE() on alignments for UP and legacy SMP percpu allocator. Commit e317603694bfd17b28a40de9d65e1a4ec12f816e fixed it for UP but legacy SMP allocator was forgotten. Fix it. Signed-off-by: Tejun Heo Reported-by: Sachin P. Sant --- mm/allocpercpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/allocpercpu.c b/mm/allocpercpu.c index 3653c570232..1882923bc70 100644 --- a/mm/allocpercpu.c +++ b/mm/allocpercpu.c @@ -120,7 +120,7 @@ void *__alloc_percpu(size_t size, size_t align) * on it. Larger alignment should only be used for module * percpu sections on SMP for which this path isn't used. */ - WARN_ON_ONCE(align > __alignof__(unsigned long long)); + WARN_ON_ONCE(align > SMP_CACHE_BYTES); if (unlikely(!pdata)) return NULL; -- GitLab From d680c76eccd9222031ee30dcee5fdedba2467610 Mon Sep 17 00:00:00 2001 From: Francesco VIRLINZI Date: Wed, 11 Mar 2009 07:40:54 +0000 Subject: [PATCH 3081/4982] sh: clkfwk: add clk_set_parent/clk_get_parent This patch adds the clk_set_parent/clk_get_parent routines to the sh clock framework. Signed-off-by: Francesco Virlinzi Signed-off-by: Paul Mundt --- arch/sh/include/asm/clock.h | 1 + arch/sh/kernel/cpu/clock.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/arch/sh/include/asm/clock.h b/arch/sh/include/asm/clock.h index f9c88583d90..2f6c9627bc1 100644 --- a/arch/sh/include/asm/clock.h +++ b/arch/sh/include/asm/clock.h @@ -15,6 +15,7 @@ struct clk_ops { void (*disable)(struct clk *clk); void (*recalc)(struct clk *clk); int (*set_rate)(struct clk *clk, unsigned long rate, int algo_id); + int (*set_parent)(struct clk *clk, struct clk *parent); long (*round_rate)(struct clk *clk, unsigned long rate); }; diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c index 7b17137536d..332a1798547 100644 --- a/arch/sh/kernel/cpu/clock.c +++ b/arch/sh/kernel/cpu/clock.c @@ -239,6 +239,35 @@ void clk_recalc_rate(struct clk *clk) } EXPORT_SYMBOL_GPL(clk_recalc_rate); +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + int ret = -EINVAL; + struct clk *old; + + if (!parent || !clk) + return ret; + + old = clk->parent; + if (likely(clk->ops && clk->ops->set_parent)) { + unsigned long flags; + spin_lock_irqsave(&clock_lock, flags); + ret = clk->ops->set_parent(clk, parent); + spin_unlock_irqrestore(&clock_lock, flags); + clk->parent = (ret ? old : parent); + } + + if (unlikely(clk->flags & CLK_RATE_PROPAGATES)) + propagate_rate(clk); + return ret; +} +EXPORT_SYMBOL_GPL(clk_set_parent); + +struct clk *clk_get_parent(struct clk *clk) +{ + return clk->parent; +} +EXPORT_SYMBOL_GPL(clk_get_parent); + long clk_round_rate(struct clk *clk, unsigned long rate) { if (likely(clk->ops && clk->ops->round_rate)) { -- GitLab From 4a55026fd7a08074676e87932578ff9e327e82a3 Mon Sep 17 00:00:00 2001 From: Francesco VIRLINZI Date: Wed, 11 Mar 2009 07:42:05 +0000 Subject: [PATCH 3082/4982] sh: clkfwk: Add resume from hibernation support. This patch adds PM support to the clock framework. With this, resume from hibernation is properly supported. Signed-off-by: Francesco Virlinzi Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/clock.c | 64 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c index 332a1798547..3209a8740fa 100644 --- a/arch/sh/kernel/cpu/clock.c +++ b/arch/sh/kernel/cpu/clock.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include #include @@ -358,6 +360,68 @@ static int show_clocks(char *buf, char **start, off_t off, return p - buf; } +#ifdef CONFIG_PM +static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state) +{ + static pm_message_t prev_state; + struct clk *clkp; + + switch (state.event) { + case PM_EVENT_ON: + /* Resumeing from hibernation */ + if (prev_state.event == PM_EVENT_FREEZE) { + list_for_each_entry(clkp, &clock_list, node) + if (likely(clkp->ops)) { + if (likely(clkp->ops->set_parent)) + clkp->ops->set_parent(clkp, + clkp->parent); + if (likely(clkp->ops->set_rate)) + clkp->ops->set_rate(clkp, + clkp->rate, NO_CHANGE); + else if (likely(clkp->ops->recalc)) + clkp->ops->recalc(clkp); + } + } + break; + case PM_EVENT_FREEZE: + break; + case PM_EVENT_SUSPEND: + break; + } + + prev_state = state; + return 0; +} + +static int clks_sysdev_resume(struct sys_device *dev) +{ + return clks_sysdev_suspend(dev, PMSG_ON); +} + +static struct sysdev_class clks_sysdev_class = { + .name = "clks", +}; + +static struct sysdev_driver clks_sysdev_driver = { + .suspend = clks_sysdev_suspend, + .resume = clks_sysdev_resume, +}; + +static struct sys_device clks_sysdev_dev = { + .cls = &clks_sysdev_class, +}; + +static int __init clk_sysdev_init(void) +{ + sysdev_class_register(&clks_sysdev_class); + sysdev_driver_register(&clks_sysdev_class, &clks_sysdev_driver); + sysdev_register(&clks_sysdev_dev); + + return 0; +} +subsys_initcall(clk_sysdev_init); +#endif + int __init clk_init(void) { int i, ret = 0; -- GitLab From 49976927de5c52c415d4809c7d56700cc8ff4215 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 11 Mar 2009 08:04:23 +0000 Subject: [PATCH 3083/4982] input: sh_keysc suspend can use to_platform_device() This patch changes sh_keysc to use to_platform_device() for suspend. Thanks to Trilok Soni for this suggestion. Signed-off-by: Magnus Damm Reviewed-by: Trilok Soni Signed-off-by: Paul Mundt --- drivers/input/keyboard/sh_keysc.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index bf92178644a..e1480fb11de 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -257,13 +257,10 @@ static int __devexit sh_keysc_remove(struct platform_device *pdev) static int sh_keysc_suspend(struct device *dev) { - struct platform_device *pdev; - struct sh_keysc_priv *priv; + struct platform_device *pdev = to_platform_device(dev); + struct sh_keysc_priv *priv = platform_get_drvdata(pdev); unsigned short value; - pdev = container_of(dev, struct platform_device, dev); - priv = platform_get_drvdata(pdev); - value = ioread16(priv->iomem_base + KYCR1_OFFS); if (device_may_wakeup(dev)) -- GitLab From 600fa578a95f65bc1f2a03210d3d418747024b43 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 11 Mar 2009 08:14:26 +0000 Subject: [PATCH 3084/4982] sh: improve sh7785lcr power off code Improve the sh7785lcr power off implementation to never return. It takes some time before the board is actually powered off, just hang after asking the harware to power down. This removes the serial port garbage printout. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/boards/board-sh7785lcr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/sh/boards/board-sh7785lcr.c b/arch/sh/boards/board-sh7785lcr.c index 6746a5fba3a..94c0296bc35 100644 --- a/arch/sh/boards/board-sh7785lcr.c +++ b/arch/sh/boards/board-sh7785lcr.c @@ -284,6 +284,9 @@ static void sh7785lcr_power_off(void) } *p = 0x01; iounmap(p); + set_bl_bit(); + while (1) + cpu_relax(); } /* Initialize the board */ -- GitLab From 47e78ecc2adb778c7d2b54924e90433a0182a6ba Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 11 Mar 2009 09:50:19 +0100 Subject: [PATCH 3085/4982] ALSA: Remove obsolete snd_xferv struct and ioctls Removed obsleted snd_xferv struct and ioctls that are no longer used in the current codebase. Signed-off-by: Takashi Iwai --- include/sound/asound.h | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/include/sound/asound.h b/include/sound/asound.h index 1c02ed1d7c4..b6e01e6b3f8 100644 --- a/include/sound/asound.h +++ b/include/sound/asound.h @@ -919,18 +919,4 @@ struct snd_ctl_event { #define SNDRV_CTL_NAME_IEC958_PCM_STREAM "PCM Stream" #define SNDRV_CTL_NAME_IEC958(expl,direction,what) "IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what -/* - * - */ - -struct snd_xferv { - const struct iovec *vector; - unsigned long count; -}; - -enum { - SNDRV_IOCTL_READV = _IOW('K', 0x00, struct snd_xferv), - SNDRV_IOCTL_WRITEV = _IOW('K', 0x01, struct snd_xferv), -}; - #endif /* __SOUND_ASOUND_H */ -- GitLab From 78a05b522044a50dc2a6811d10b9ee3f7c3e78f8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 11 Mar 2009 09:52:28 +0100 Subject: [PATCH 3086/4982] ALSA: Use define for ioctl definitions Use define instead of enum for ioctl definitions since strace can't parse ioctls defined via enum properly. Signed-off-by: Takashi Iwai --- include/sound/asound.h | 171 ++++++++++++++++++-------------------- include/sound/sfnt_info.h | 14 ++-- 2 files changed, 85 insertions(+), 100 deletions(-) diff --git a/include/sound/asound.h b/include/sound/asound.h index b6e01e6b3f8..fad3e0c7b93 100644 --- a/include/sound/asound.h +++ b/include/sound/asound.h @@ -126,12 +126,10 @@ struct snd_hwdep_dsp_image { unsigned long driver_data; /* W: driver-specific data */ }; -enum { - SNDRV_HWDEP_IOCTL_PVERSION = _IOR ('H', 0x00, int), - SNDRV_HWDEP_IOCTL_INFO = _IOR ('H', 0x01, struct snd_hwdep_info), - SNDRV_HWDEP_IOCTL_DSP_STATUS = _IOR('H', 0x02, struct snd_hwdep_dsp_status), - SNDRV_HWDEP_IOCTL_DSP_LOAD = _IOW('H', 0x03, struct snd_hwdep_dsp_image) -}; +#define SNDRV_HWDEP_IOCTL_PVERSION _IOR ('H', 0x00, int) +#define SNDRV_HWDEP_IOCTL_INFO _IOR ('H', 0x01, struct snd_hwdep_info) +#define SNDRV_HWDEP_IOCTL_DSP_STATUS _IOR('H', 0x02, struct snd_hwdep_dsp_status) +#define SNDRV_HWDEP_IOCTL_DSP_LOAD _IOW('H', 0x03, struct snd_hwdep_dsp_image) /***************************************************************************** * * @@ -451,40 +449,35 @@ enum { SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, }; -enum { - SNDRV_PCM_IOCTL_PVERSION = _IOR('A', 0x00, int), - SNDRV_PCM_IOCTL_INFO = _IOR('A', 0x01, struct snd_pcm_info), - SNDRV_PCM_IOCTL_TSTAMP = _IOW('A', 0x02, int), - SNDRV_PCM_IOCTL_TTSTAMP = _IOW('A', 0x03, int), - SNDRV_PCM_IOCTL_HW_REFINE = _IOWR('A', 0x10, struct snd_pcm_hw_params), - SNDRV_PCM_IOCTL_HW_PARAMS = _IOWR('A', 0x11, struct snd_pcm_hw_params), - SNDRV_PCM_IOCTL_HW_FREE = _IO('A', 0x12), - SNDRV_PCM_IOCTL_SW_PARAMS = _IOWR('A', 0x13, struct snd_pcm_sw_params), - SNDRV_PCM_IOCTL_STATUS = _IOR('A', 0x20, struct snd_pcm_status), - SNDRV_PCM_IOCTL_DELAY = _IOR('A', 0x21, snd_pcm_sframes_t), - SNDRV_PCM_IOCTL_HWSYNC = _IO('A', 0x22), - SNDRV_PCM_IOCTL_SYNC_PTR = _IOWR('A', 0x23, struct snd_pcm_sync_ptr), - SNDRV_PCM_IOCTL_CHANNEL_INFO = _IOR('A', 0x32, struct snd_pcm_channel_info), - SNDRV_PCM_IOCTL_PREPARE = _IO('A', 0x40), - SNDRV_PCM_IOCTL_RESET = _IO('A', 0x41), - SNDRV_PCM_IOCTL_START = _IO('A', 0x42), - SNDRV_PCM_IOCTL_DROP = _IO('A', 0x43), - SNDRV_PCM_IOCTL_DRAIN = _IO('A', 0x44), - SNDRV_PCM_IOCTL_PAUSE = _IOW('A', 0x45, int), - SNDRV_PCM_IOCTL_REWIND = _IOW('A', 0x46, snd_pcm_uframes_t), - SNDRV_PCM_IOCTL_RESUME = _IO('A', 0x47), - SNDRV_PCM_IOCTL_XRUN = _IO('A', 0x48), - SNDRV_PCM_IOCTL_FORWARD = _IOW('A', 0x49, snd_pcm_uframes_t), - SNDRV_PCM_IOCTL_WRITEI_FRAMES = _IOW('A', 0x50, struct snd_xferi), - SNDRV_PCM_IOCTL_READI_FRAMES = _IOR('A', 0x51, struct snd_xferi), - SNDRV_PCM_IOCTL_WRITEN_FRAMES = _IOW('A', 0x52, struct snd_xfern), - SNDRV_PCM_IOCTL_READN_FRAMES = _IOR('A', 0x53, struct snd_xfern), - SNDRV_PCM_IOCTL_LINK = _IOW('A', 0x60, int), - SNDRV_PCM_IOCTL_UNLINK = _IO('A', 0x61), -}; - -/* Trick to make alsa-lib/acinclude.m4 happy */ -#define SNDRV_PCM_IOCTL_REWIND SNDRV_PCM_IOCTL_REWIND +#define SNDRV_PCM_IOCTL_PVERSION _IOR('A', 0x00, int) +#define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info) +#define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int) +#define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int) +#define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params) +#define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params) +#define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12) +#define SNDRV_PCM_IOCTL_SW_PARAMS _IOWR('A', 0x13, struct snd_pcm_sw_params) +#define SNDRV_PCM_IOCTL_STATUS _IOR('A', 0x20, struct snd_pcm_status) +#define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, snd_pcm_sframes_t) +#define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22) +#define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct snd_pcm_sync_ptr) +#define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct snd_pcm_channel_info) +#define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40) +#define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41) +#define SNDRV_PCM_IOCTL_START _IO('A', 0x42) +#define SNDRV_PCM_IOCTL_DROP _IO('A', 0x43) +#define SNDRV_PCM_IOCTL_DRAIN _IO('A', 0x44) +#define SNDRV_PCM_IOCTL_PAUSE _IOW('A', 0x45, int) +#define SNDRV_PCM_IOCTL_REWIND _IOW('A', 0x46, snd_pcm_uframes_t) +#define SNDRV_PCM_IOCTL_RESUME _IO('A', 0x47) +#define SNDRV_PCM_IOCTL_XRUN _IO('A', 0x48) +#define SNDRV_PCM_IOCTL_FORWARD _IOW('A', 0x49, snd_pcm_uframes_t) +#define SNDRV_PCM_IOCTL_WRITEI_FRAMES _IOW('A', 0x50, struct snd_xferi) +#define SNDRV_PCM_IOCTL_READI_FRAMES _IOR('A', 0x51, struct snd_xferi) +#define SNDRV_PCM_IOCTL_WRITEN_FRAMES _IOW('A', 0x52, struct snd_xfern) +#define SNDRV_PCM_IOCTL_READN_FRAMES _IOR('A', 0x53, struct snd_xfern) +#define SNDRV_PCM_IOCTL_LINK _IOW('A', 0x60, int) +#define SNDRV_PCM_IOCTL_UNLINK _IO('A', 0x61) /***************************************************************************** * * @@ -538,14 +531,12 @@ struct snd_rawmidi_status { unsigned char reserved[16]; /* reserved for future use */ }; -enum { - SNDRV_RAWMIDI_IOCTL_PVERSION = _IOR('W', 0x00, int), - SNDRV_RAWMIDI_IOCTL_INFO = _IOR('W', 0x01, struct snd_rawmidi_info), - SNDRV_RAWMIDI_IOCTL_PARAMS = _IOWR('W', 0x10, struct snd_rawmidi_params), - SNDRV_RAWMIDI_IOCTL_STATUS = _IOWR('W', 0x20, struct snd_rawmidi_status), - SNDRV_RAWMIDI_IOCTL_DROP = _IOW('W', 0x30, int), - SNDRV_RAWMIDI_IOCTL_DRAIN = _IOW('W', 0x31, int), -}; +#define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int) +#define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct snd_rawmidi_info) +#define SNDRV_RAWMIDI_IOCTL_PARAMS _IOWR('W', 0x10, struct snd_rawmidi_params) +#define SNDRV_RAWMIDI_IOCTL_STATUS _IOWR('W', 0x20, struct snd_rawmidi_status) +#define SNDRV_RAWMIDI_IOCTL_DROP _IOW('W', 0x30, int) +#define SNDRV_RAWMIDI_IOCTL_DRAIN _IOW('W', 0x31, int) /* * Timer section - /dev/snd/timer @@ -654,23 +645,21 @@ struct snd_timer_status { unsigned char reserved[64]; /* reserved */ }; -enum { - SNDRV_TIMER_IOCTL_PVERSION = _IOR('T', 0x00, int), - SNDRV_TIMER_IOCTL_NEXT_DEVICE = _IOWR('T', 0x01, struct snd_timer_id), - SNDRV_TIMER_IOCTL_TREAD = _IOW('T', 0x02, int), - SNDRV_TIMER_IOCTL_GINFO = _IOWR('T', 0x03, struct snd_timer_ginfo), - SNDRV_TIMER_IOCTL_GPARAMS = _IOW('T', 0x04, struct snd_timer_gparams), - SNDRV_TIMER_IOCTL_GSTATUS = _IOWR('T', 0x05, struct snd_timer_gstatus), - SNDRV_TIMER_IOCTL_SELECT = _IOW('T', 0x10, struct snd_timer_select), - SNDRV_TIMER_IOCTL_INFO = _IOR('T', 0x11, struct snd_timer_info), - SNDRV_TIMER_IOCTL_PARAMS = _IOW('T', 0x12, struct snd_timer_params), - SNDRV_TIMER_IOCTL_STATUS = _IOR('T', 0x14, struct snd_timer_status), - /* The following four ioctls are changed since 1.0.9 due to confliction */ - SNDRV_TIMER_IOCTL_START = _IO('T', 0xa0), - SNDRV_TIMER_IOCTL_STOP = _IO('T', 0xa1), - SNDRV_TIMER_IOCTL_CONTINUE = _IO('T', 0xa2), - SNDRV_TIMER_IOCTL_PAUSE = _IO('T', 0xa3), -}; +#define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int) +#define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id) +#define SNDRV_TIMER_IOCTL_TREAD _IOW('T', 0x02, int) +#define SNDRV_TIMER_IOCTL_GINFO _IOWR('T', 0x03, struct snd_timer_ginfo) +#define SNDRV_TIMER_IOCTL_GPARAMS _IOW('T', 0x04, struct snd_timer_gparams) +#define SNDRV_TIMER_IOCTL_GSTATUS _IOWR('T', 0x05, struct snd_timer_gstatus) +#define SNDRV_TIMER_IOCTL_SELECT _IOW('T', 0x10, struct snd_timer_select) +#define SNDRV_TIMER_IOCTL_INFO _IOR('T', 0x11, struct snd_timer_info) +#define SNDRV_TIMER_IOCTL_PARAMS _IOW('T', 0x12, struct snd_timer_params) +#define SNDRV_TIMER_IOCTL_STATUS _IOR('T', 0x14, struct snd_timer_status) +/* The following four ioctls are changed since 1.0.9 due to confliction */ +#define SNDRV_TIMER_IOCTL_START _IO('T', 0xa0) +#define SNDRV_TIMER_IOCTL_STOP _IO('T', 0xa1) +#define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2) +#define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3) struct snd_timer_read { unsigned int resolution; @@ -847,33 +836,31 @@ struct snd_ctl_tlv { unsigned int tlv[0]; /* first TLV */ }; -enum { - SNDRV_CTL_IOCTL_PVERSION = _IOR('U', 0x00, int), - SNDRV_CTL_IOCTL_CARD_INFO = _IOR('U', 0x01, struct snd_ctl_card_info), - SNDRV_CTL_IOCTL_ELEM_LIST = _IOWR('U', 0x10, struct snd_ctl_elem_list), - SNDRV_CTL_IOCTL_ELEM_INFO = _IOWR('U', 0x11, struct snd_ctl_elem_info), - SNDRV_CTL_IOCTL_ELEM_READ = _IOWR('U', 0x12, struct snd_ctl_elem_value), - SNDRV_CTL_IOCTL_ELEM_WRITE = _IOWR('U', 0x13, struct snd_ctl_elem_value), - SNDRV_CTL_IOCTL_ELEM_LOCK = _IOW('U', 0x14, struct snd_ctl_elem_id), - SNDRV_CTL_IOCTL_ELEM_UNLOCK = _IOW('U', 0x15, struct snd_ctl_elem_id), - SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS = _IOWR('U', 0x16, int), - SNDRV_CTL_IOCTL_ELEM_ADD = _IOWR('U', 0x17, struct snd_ctl_elem_info), - SNDRV_CTL_IOCTL_ELEM_REPLACE = _IOWR('U', 0x18, struct snd_ctl_elem_info), - SNDRV_CTL_IOCTL_ELEM_REMOVE = _IOWR('U', 0x19, struct snd_ctl_elem_id), - SNDRV_CTL_IOCTL_TLV_READ = _IOWR('U', 0x1a, struct snd_ctl_tlv), - SNDRV_CTL_IOCTL_TLV_WRITE = _IOWR('U', 0x1b, struct snd_ctl_tlv), - SNDRV_CTL_IOCTL_TLV_COMMAND = _IOWR('U', 0x1c, struct snd_ctl_tlv), - SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE = _IOWR('U', 0x20, int), - SNDRV_CTL_IOCTL_HWDEP_INFO = _IOR('U', 0x21, struct snd_hwdep_info), - SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE = _IOR('U', 0x30, int), - SNDRV_CTL_IOCTL_PCM_INFO = _IOWR('U', 0x31, struct snd_pcm_info), - SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE = _IOW('U', 0x32, int), - SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE = _IOWR('U', 0x40, int), - SNDRV_CTL_IOCTL_RAWMIDI_INFO = _IOWR('U', 0x41, struct snd_rawmidi_info), - SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE = _IOW('U', 0x42, int), - SNDRV_CTL_IOCTL_POWER = _IOWR('U', 0xd0, int), - SNDRV_CTL_IOCTL_POWER_STATE = _IOR('U', 0xd1, int), -}; +#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int) +#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct snd_ctl_card_info) +#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct snd_ctl_elem_list) +#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct snd_ctl_elem_info) +#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct snd_ctl_elem_value) +#define SNDRV_CTL_IOCTL_ELEM_WRITE _IOWR('U', 0x13, struct snd_ctl_elem_value) +#define SNDRV_CTL_IOCTL_ELEM_LOCK _IOW('U', 0x14, struct snd_ctl_elem_id) +#define SNDRV_CTL_IOCTL_ELEM_UNLOCK _IOW('U', 0x15, struct snd_ctl_elem_id) +#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int) +#define SNDRV_CTL_IOCTL_ELEM_ADD _IOWR('U', 0x17, struct snd_ctl_elem_info) +#define SNDRV_CTL_IOCTL_ELEM_REPLACE _IOWR('U', 0x18, struct snd_ctl_elem_info) +#define SNDRV_CTL_IOCTL_ELEM_REMOVE _IOWR('U', 0x19, struct snd_ctl_elem_id) +#define SNDRV_CTL_IOCTL_TLV_READ _IOWR('U', 0x1a, struct snd_ctl_tlv) +#define SNDRV_CTL_IOCTL_TLV_WRITE _IOWR('U', 0x1b, struct snd_ctl_tlv) +#define SNDRV_CTL_IOCTL_TLV_COMMAND _IOWR('U', 0x1c, struct snd_ctl_tlv) +#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int) +#define SNDRV_CTL_IOCTL_HWDEP_INFO _IOR('U', 0x21, struct snd_hwdep_info) +#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE _IOR('U', 0x30, int) +#define SNDRV_CTL_IOCTL_PCM_INFO _IOWR('U', 0x31, struct snd_pcm_info) +#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int) +#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int) +#define SNDRV_CTL_IOCTL_RAWMIDI_INFO _IOWR('U', 0x41, struct snd_rawmidi_info) +#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int) +#define SNDRV_CTL_IOCTL_POWER _IOWR('U', 0xd0, int) +#define SNDRV_CTL_IOCTL_POWER_STATE _IOR('U', 0xd1, int) /* * Read interface. diff --git a/include/sound/sfnt_info.h b/include/sound/sfnt_info.h index 5d1ab9c4950..1bce7fd1725 100644 --- a/include/sound/sfnt_info.h +++ b/include/sound/sfnt_info.h @@ -202,13 +202,11 @@ struct snd_emux_misc_mode { int value2; /* reserved */ }; -enum { - SNDRV_EMUX_IOCTL_VERSION = _IOR('H', 0x80, unsigned int), - SNDRV_EMUX_IOCTL_LOAD_PATCH = _IOWR('H', 0x81, struct soundfont_patch_info), - SNDRV_EMUX_IOCTL_RESET_SAMPLES = _IO('H', 0x82), - SNDRV_EMUX_IOCTL_REMOVE_LAST_SAMPLES = _IO('H', 0x83), - SNDRV_EMUX_IOCTL_MEM_AVAIL = _IOW('H', 0x84, int), - SNDRV_EMUX_IOCTL_MISC_MODE = _IOWR('H', 0x84, struct snd_emux_misc_mode), -}; +#define SNDRV_EMUX_IOCTL_VERSION _IOR('H', 0x80, unsigned int) +#define SNDRV_EMUX_IOCTL_LOAD_PATCH _IOWR('H', 0x81, struct soundfont_patch_info) +#define SNDRV_EMUX_IOCTL_RESET_SAMPLES _IO('H', 0x82) +#define SNDRV_EMUX_IOCTL_REMOVE_LAST_SAMPLES _IO('H', 0x83) +#define SNDRV_EMUX_IOCTL_MEM_AVAIL _IOW('H', 0x84, int) +#define SNDRV_EMUX_IOCTL_MISC_MODE _IOWR('H', 0x84, struct snd_emux_misc_mode) #endif /* __SOUND_SFNT_INFO_H */ -- GitLab From df1c99d416500da8d26a4d78777467c53ee7689e Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Tue, 10 Mar 2009 19:08:11 +0100 Subject: [PATCH 3087/4982] sched: add avg_overlap decay Impact: more precise avg_overlap metric - better load-balancing avg_overlap is used to measure the runtime overlap of the waker and wakee. However, when a process changes behaviour, eg a pipe becomes un-congested and we don't need to go to sleep after a wakeup for a while, the avg_overlap value grows stale. When running we use the avg runtime between preemption as a measure for avg_overlap since the amount of runtime can be correlated to cache footprint. The longer we run, the less likely we'll be wanting to be migrated to another CPU. Signed-off-by: Mike Galbraith Signed-off-by: Peter Zijlstra LKML-Reference: <1236709131.25234.576.camel@laptop> Signed-off-by: Ingo Molnar --- kernel/sched.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/kernel/sched.c b/kernel/sched.c index af5cd1b2d03..2f28351892c 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -4620,6 +4620,28 @@ static inline void schedule_debug(struct task_struct *prev) #endif } +static void put_prev_task(struct rq *rq, struct task_struct *prev) +{ + if (prev->state == TASK_RUNNING) { + u64 runtime = prev->se.sum_exec_runtime; + + runtime -= prev->se.prev_sum_exec_runtime; + runtime = min_t(u64, runtime, 2*sysctl_sched_migration_cost); + + /* + * In order to avoid avg_overlap growing stale when we are + * indeed overlapping and hence not getting put to sleep, grow + * the avg_overlap on preemption. + * + * We use the average preemption runtime because that + * correlates to the amount of cache footprint a task can + * build up. + */ + update_avg(&prev->se.avg_overlap, runtime); + } + prev->sched_class->put_prev_task(rq, prev); +} + /* * Pick up the highest-prio task: */ @@ -4698,7 +4720,7 @@ need_resched_nonpreemptible: if (unlikely(!rq->nr_running)) idle_balance(cpu, rq); - prev->sched_class->put_prev_task(rq, prev); + put_prev_task(rq, prev); next = pick_next_task(rq); if (likely(prev != next)) { -- GitLab From a2b03461cb072eb6097a55ec0289294b09382284 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 11 Mar 2009 11:02:33 +0000 Subject: [PATCH 3088/4982] [ARM] Revert extraneous changes from the S3C audio header move These changes were included in the S3C audio header move but are not directly related to it. Signed-off-by: Mark Brown --- arch/arm/mach-s3c2410/include/mach/hardware.h | 3 +++ arch/arm/mach-shark/include/mach/io.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-s3c2410/include/mach/hardware.h b/arch/arm/mach-s3c2410/include/mach/hardware.h index db72beb61d7..74d5a1a4024 100644 --- a/arch/arm/mach-s3c2410/include/mach/hardware.h +++ b/arch/arm/mach-s3c2410/include/mach/hardware.h @@ -131,4 +131,7 @@ extern int s3c2412_gpio_set_sleepcfg(unsigned int pin, unsigned int state); /* machine specific hardware definitions should go after this */ +/* currently here until moved into config (todo) */ +#define CONFIG_NO_MULTIWORD_IO + #endif /* __ASM_ARCH_HARDWARE_H */ diff --git a/arch/arm/mach-shark/include/mach/io.h b/arch/arm/mach-shark/include/mach/io.h index 8ca7d7f09bd..c5cee829fc8 100644 --- a/arch/arm/mach-shark/include/mach/io.h +++ b/arch/arm/mach-shark/include/mach/io.h @@ -14,7 +14,7 @@ #define PCIO_BASE 0xe0000000 #define IO_SPACE_LIMIT 0xffffffff -#define __io(a) __typesafe_io(PCIO_BASE + (a)) +#define __io(a) ((void __iomem *)(PCIO_BASE + (a))) #define __mem_pci(addr) (addr) #endif -- GitLab From 5706d5013212c8afcb9fe5332ee6442488280c66 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 11 Mar 2009 02:37:25 -0800 Subject: [PATCH 3089/4982] ASoC: buildfix for OSK Buildfix: CC sound/soc/omap/osk5912.o sound/soc/omap/osk5912.c: In function 'osk_soc_init': sound/soc/omap/osk5912.c:189: error: implicit declaration of function 'clk_get_usecount' make[3]: *** [sound/soc/omap/osk5912.o] Error 1 There's no such (standard) clock interface. Signed-off-by: David Brownell Signed-off-by: Mark Brown --- sound/soc/omap/osk5912.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c index cd41a948df7..a952a4eb336 100644 --- a/sound/soc/omap/osk5912.c +++ b/sound/soc/omap/osk5912.c @@ -186,13 +186,6 @@ static int __init osk_soc_init(void) return -ENODEV; } - if (clk_get_usecount(tlv320aic23_mclk) > 0) { - /* MCLK is already in use */ - printk(KERN_WARNING - "MCLK in use at %d Hz. We change it to %d Hz\n", - (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK); - } - /* * Configure 12 MHz output on MCLK. */ @@ -205,9 +198,8 @@ static int __init osk_soc_init(void) } } - printk(KERN_INFO "MCLK = %d [%d], usecount = %d\n", - (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK, - clk_get_usecount(tlv320aic23_mclk)); + printk(KERN_INFO "MCLK = %d [%d]\n", + (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK); return 0; err1: -- GitLab From aaf1e176fa9a96fe1eea33b710684bba066aedc1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 10 Mar 2009 10:55:15 +0000 Subject: [PATCH 3090/4982] ASoC: Add initial driver for the WM8400 CODEC The WM8400 is a highly integrated audio CODEC and power management unit intended for mobile multimedia application. This driver supports the primary audio CODEC features, including: - 1W speaker driver - Fully differential headphone output - Up to 4 differential microphone inputs Signed-off-by: Mark Brown --- include/linux/mfd/wm8400-audio.h | 1 + sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/wm8400.c | 1479 ++++++++++++++++++++++++++++++ sound/soc/codecs/wm8400.h | 62 ++ 5 files changed, 1548 insertions(+) create mode 100644 sound/soc/codecs/wm8400.c create mode 100644 sound/soc/codecs/wm8400.h diff --git a/include/linux/mfd/wm8400-audio.h b/include/linux/mfd/wm8400-audio.h index b6640e01804..e06ed3eb1d0 100644 --- a/include/linux/mfd/wm8400-audio.h +++ b/include/linux/mfd/wm8400-audio.h @@ -1181,6 +1181,7 @@ #define WM8400_FLL_OUTDIV_SHIFT 0 /* FLL_OUTDIV - [2:0] */ #define WM8400_FLL_OUTDIV_WIDTH 3 /* FLL_OUTDIV - [2:0] */ +struct wm8400; void wm8400_reset_codec_reg_cache(struct wm8400 *wm8400); #endif diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index a1af311e7f0..b6c7f7a01cb 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -26,6 +26,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_UDA134X select SND_SOC_UDA1380 if I2C select SND_SOC_WM8350 if MFD_WM8350 + select SND_SOC_WM8400 if MFD_WM8400 select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI select SND_SOC_WM8580 if I2C select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI @@ -110,6 +111,9 @@ config SND_SOC_UDA1380 config SND_SOC_WM8350 tristate +config SND_SOC_WM8400 + tristate + config SND_SOC_WM8510 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 4717c3c9904..030d2454725 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -14,6 +14,7 @@ snd-soc-twl4030-objs := twl4030.o snd-soc-uda134x-objs := uda134x.o snd-soc-uda1380-objs := uda1380.o snd-soc-wm8350-objs := wm8350.o +snd-soc-wm8400-objs := wm8400.o snd-soc-wm8510-objs := wm8510.o snd-soc-wm8580-objs := wm8580.o snd-soc-wm8728-objs := wm8728.o @@ -44,6 +45,7 @@ obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o +obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c new file mode 100644 index 00000000000..9cb73d9d023 --- /dev/null +++ b/sound/soc/codecs/wm8400.c @@ -0,0 +1,1479 @@ +/* + * wm8400.c -- WM8400 ALSA Soc Audio driver + * + * Copyright 2008, 2009 Wolfson Microelectronics PLC. + * Author: Mark Brown + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wm8400.h" + +/* Fake register for internal state */ +#define WM8400_INTDRIVBITS (WM8400_REGISTER_COUNT + 1) +#define WM8400_INMIXL_PWR 0 +#define WM8400_AINLMUX_PWR 1 +#define WM8400_INMIXR_PWR 2 +#define WM8400_AINRMUX_PWR 3 + +static struct regulator_bulk_data power[] = { + { + .supply = "I2S1VDD", + }, + { + .supply = "I2S2VDD", + }, + { + .supply = "DCVDD", + }, + { + .supply = "FLLVDD", + }, + { + .supply = "HPVDD", + }, + { + .supply = "SPKVDD", + }, +}; + +/* codec private data */ +struct wm8400_priv { + struct snd_soc_codec codec; + struct wm8400 *wm8400; + u16 fake_register; + unsigned int sysclk; + unsigned int pcmclk; + struct work_struct work; +}; + +static inline unsigned int wm8400_read(struct snd_soc_codec *codec, + unsigned int reg) +{ + struct wm8400_priv *wm8400 = codec->private_data; + + if (reg == WM8400_INTDRIVBITS) + return wm8400->fake_register; + else + return wm8400_reg_read(wm8400->wm8400, reg); +} + +/* + * write to the wm8400 register space + */ +static int wm8400_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + struct wm8400_priv *wm8400 = codec->private_data; + + if (reg == WM8400_INTDRIVBITS) { + wm8400->fake_register = value; + return 0; + } else + return wm8400_set_bits(wm8400->wm8400, reg, 0xffff, value); +} + +static void wm8400_codec_reset(struct snd_soc_codec *codec) +{ + struct wm8400_priv *wm8400 = codec->private_data; + + wm8400_reset_codec_reg_cache(wm8400->wm8400); +} + +static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600); + +static const DECLARE_TLV_DB_LINEAR(in_pga_tlv, -1650, 3000); + +static const DECLARE_TLV_DB_LINEAR(out_mix_tlv, -2100, 0); + +static const DECLARE_TLV_DB_LINEAR(out_pga_tlv, -7300, 600); + +static const DECLARE_TLV_DB_LINEAR(out_omix_tlv, -600, 0); + +static const DECLARE_TLV_DB_LINEAR(out_dac_tlv, -7163, 0); + +static const DECLARE_TLV_DB_LINEAR(in_adc_tlv, -7163, 1763); + +static const DECLARE_TLV_DB_LINEAR(out_sidetone_tlv, -3600, 0); + +static int wm8400_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + int reg = mc->reg; + int ret; + u16 val; + + ret = snd_soc_put_volsw(kcontrol, ucontrol); + if (ret < 0) + return ret; + + /* now hit the volume update bits (always bit 8) */ + val = wm8400_read(codec, reg); + return wm8400_write(codec, reg, val | 0x0100); +} + +#define WM8400_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert, tlv_array) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ + SNDRV_CTL_ELEM_ACCESS_READWRITE,\ + .tlv.p = (tlv_array), \ + .info = snd_soc_info_volsw, \ + .get = snd_soc_get_volsw, .put = wm8400_outpga_put_volsw_vu, \ + .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } + + +static const char *wm8400_digital_sidetone[] = + {"None", "Left ADC", "Right ADC", "Reserved"}; + +static const struct soc_enum wm8400_left_digital_sidetone_enum = +SOC_ENUM_SINGLE(WM8400_DIGITAL_SIDE_TONE, + WM8400_ADC_TO_DACL_SHIFT, 2, wm8400_digital_sidetone); + +static const struct soc_enum wm8400_right_digital_sidetone_enum = +SOC_ENUM_SINGLE(WM8400_DIGITAL_SIDE_TONE, + WM8400_ADC_TO_DACR_SHIFT, 2, wm8400_digital_sidetone); + +static const char *wm8400_adcmode[] = + {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; + +static const struct soc_enum wm8400_right_adcmode_enum = +SOC_ENUM_SINGLE(WM8400_ADC_CTRL, WM8400_ADC_HPF_CUT_SHIFT, 3, wm8400_adcmode); + +static const struct snd_kcontrol_new wm8400_snd_controls[] = { +/* INMIXL */ +SOC_SINGLE("LIN12 PGA Boost", WM8400_INPUT_MIXER3, WM8400_L12MNBST_SHIFT, + 1, 0), +SOC_SINGLE("LIN34 PGA Boost", WM8400_INPUT_MIXER3, WM8400_L34MNBST_SHIFT, + 1, 0), +/* INMIXR */ +SOC_SINGLE("RIN12 PGA Boost", WM8400_INPUT_MIXER3, WM8400_R12MNBST_SHIFT, + 1, 0), +SOC_SINGLE("RIN34 PGA Boost", WM8400_INPUT_MIXER3, WM8400_R34MNBST_SHIFT, + 1, 0), + +/* LOMIX */ +SOC_SINGLE_TLV("LOMIX LIN3 Bypass Volume", WM8400_OUTPUT_MIXER3, + WM8400_LLI3LOVOL_SHIFT, 7, 0, out_mix_tlv), +SOC_SINGLE_TLV("LOMIX RIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER3, + WM8400_LR12LOVOL_SHIFT, 7, 0, out_mix_tlv), +SOC_SINGLE_TLV("LOMIX LIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER3, + WM8400_LL12LOVOL_SHIFT, 7, 0, out_mix_tlv), +SOC_SINGLE_TLV("LOMIX RIN3 Bypass Volume", WM8400_OUTPUT_MIXER5, + WM8400_LRI3LOVOL_SHIFT, 7, 0, out_mix_tlv), +SOC_SINGLE_TLV("LOMIX AINRMUX Bypass Volume", WM8400_OUTPUT_MIXER5, + WM8400_LRBLOVOL_SHIFT, 7, 0, out_mix_tlv), +SOC_SINGLE_TLV("LOMIX AINLMUX Bypass Volume", WM8400_OUTPUT_MIXER5, + WM8400_LRBLOVOL_SHIFT, 7, 0, out_mix_tlv), + +/* ROMIX */ +SOC_SINGLE_TLV("ROMIX RIN3 Bypass Volume", WM8400_OUTPUT_MIXER4, + WM8400_RRI3ROVOL_SHIFT, 7, 0, out_mix_tlv), +SOC_SINGLE_TLV("ROMIX LIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER4, + WM8400_RL12ROVOL_SHIFT, 7, 0, out_mix_tlv), +SOC_SINGLE_TLV("ROMIX RIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER4, + WM8400_RR12ROVOL_SHIFT, 7, 0, out_mix_tlv), +SOC_SINGLE_TLV("ROMIX LIN3 Bypass Volume", WM8400_OUTPUT_MIXER6, + WM8400_RLI3ROVOL_SHIFT, 7, 0, out_mix_tlv), +SOC_SINGLE_TLV("ROMIX AINLMUX Bypass Volume", WM8400_OUTPUT_MIXER6, + WM8400_RLBROVOL_SHIFT, 7, 0, out_mix_tlv), +SOC_SINGLE_TLV("ROMIX AINRMUX Bypass Volume", WM8400_OUTPUT_MIXER6, + WM8400_RRBROVOL_SHIFT, 7, 0, out_mix_tlv), + +/* LOUT */ +WM8400_OUTPGA_SINGLE_R_TLV("LOUT Volume", WM8400_LEFT_OUTPUT_VOLUME, + WM8400_LOUTVOL_SHIFT, WM8400_LOUTVOL_MASK, 0, out_pga_tlv), +SOC_SINGLE("LOUT ZC", WM8400_LEFT_OUTPUT_VOLUME, WM8400_LOZC_SHIFT, 1, 0), + +/* ROUT */ +WM8400_OUTPGA_SINGLE_R_TLV("ROUT Volume", WM8400_RIGHT_OUTPUT_VOLUME, + WM8400_ROUTVOL_SHIFT, WM8400_ROUTVOL_MASK, 0, out_pga_tlv), +SOC_SINGLE("ROUT ZC", WM8400_RIGHT_OUTPUT_VOLUME, WM8400_ROZC_SHIFT, 1, 0), + +/* LOPGA */ +WM8400_OUTPGA_SINGLE_R_TLV("LOPGA Volume", WM8400_LEFT_OPGA_VOLUME, + WM8400_LOPGAVOL_SHIFT, WM8400_LOPGAVOL_MASK, 0, out_pga_tlv), +SOC_SINGLE("LOPGA ZC Switch", WM8400_LEFT_OPGA_VOLUME, + WM8400_LOPGAZC_SHIFT, 1, 0), + +/* ROPGA */ +WM8400_OUTPGA_SINGLE_R_TLV("ROPGA Volume", WM8400_RIGHT_OPGA_VOLUME, + WM8400_ROPGAVOL_SHIFT, WM8400_ROPGAVOL_MASK, 0, out_pga_tlv), +SOC_SINGLE("ROPGA ZC Switch", WM8400_RIGHT_OPGA_VOLUME, + WM8400_ROPGAZC_SHIFT, 1, 0), + +SOC_SINGLE("LON Mute Switch", WM8400_LINE_OUTPUTS_VOLUME, + WM8400_LONMUTE_SHIFT, 1, 0), +SOC_SINGLE("LOP Mute Switch", WM8400_LINE_OUTPUTS_VOLUME, + WM8400_LOPMUTE_SHIFT, 1, 0), +SOC_SINGLE("LOP Attenuation Switch", WM8400_LINE_OUTPUTS_VOLUME, + WM8400_LOATTN_SHIFT, 1, 0), +SOC_SINGLE("RON Mute Switch", WM8400_LINE_OUTPUTS_VOLUME, + WM8400_RONMUTE_SHIFT, 1, 0), +SOC_SINGLE("ROP Mute Switch", WM8400_LINE_OUTPUTS_VOLUME, + WM8400_ROPMUTE_SHIFT, 1, 0), +SOC_SINGLE("ROP Attenuation Switch", WM8400_LINE_OUTPUTS_VOLUME, + WM8400_ROATTN_SHIFT, 1, 0), + +SOC_SINGLE("OUT3 Mute Switch", WM8400_OUT3_4_VOLUME, + WM8400_OUT3MUTE_SHIFT, 1, 0), +SOC_SINGLE("OUT3 Attenuation Switch", WM8400_OUT3_4_VOLUME, + WM8400_OUT3ATTN_SHIFT, 1, 0), + +SOC_SINGLE("OUT4 Mute Switch", WM8400_OUT3_4_VOLUME, + WM8400_OUT4MUTE_SHIFT, 1, 0), +SOC_SINGLE("OUT4 Attenuation Switch", WM8400_OUT3_4_VOLUME, + WM8400_OUT4ATTN_SHIFT, 1, 0), + +SOC_SINGLE("Speaker Mode Switch", WM8400_CLASSD1, + WM8400_CDMODE_SHIFT, 1, 0), + +SOC_SINGLE("Speaker Output Attenuation Volume", WM8400_SPEAKER_VOLUME, + WM8400_SPKATTN_SHIFT, WM8400_SPKATTN_MASK, 0), +SOC_SINGLE("Speaker DC Boost Volume", WM8400_CLASSD3, + WM8400_DCGAIN_SHIFT, 6, 0), +SOC_SINGLE("Speaker AC Boost Volume", WM8400_CLASSD3, + WM8400_ACGAIN_SHIFT, 6, 0), + +WM8400_OUTPGA_SINGLE_R_TLV("Left DAC Digital Volume", + WM8400_LEFT_DAC_DIGITAL_VOLUME, WM8400_DACL_VOL_SHIFT, + 127, 0, out_dac_tlv), + +WM8400_OUTPGA_SINGLE_R_TLV("Right DAC Digital Volume", + WM8400_RIGHT_DAC_DIGITAL_VOLUME, WM8400_DACR_VOL_SHIFT, + 127, 0, out_dac_tlv), + +SOC_ENUM("Left Digital Sidetone", wm8400_left_digital_sidetone_enum), +SOC_ENUM("Right Digital Sidetone", wm8400_right_digital_sidetone_enum), + +SOC_SINGLE_TLV("Left Digital Sidetone Volume", WM8400_DIGITAL_SIDE_TONE, + WM8400_ADCL_DAC_SVOL_SHIFT, 15, 0, out_sidetone_tlv), +SOC_SINGLE_TLV("Right Digital Sidetone Volume", WM8400_DIGITAL_SIDE_TONE, + WM8400_ADCR_DAC_SVOL_SHIFT, 15, 0, out_sidetone_tlv), + +SOC_SINGLE("ADC Digital High Pass Filter Switch", WM8400_ADC_CTRL, + WM8400_ADC_HPF_ENA_SHIFT, 1, 0), + +SOC_ENUM("ADC HPF Mode", wm8400_right_adcmode_enum), + +WM8400_OUTPGA_SINGLE_R_TLV("Left ADC Digital Volume", + WM8400_LEFT_ADC_DIGITAL_VOLUME, + WM8400_ADCL_VOL_SHIFT, + WM8400_ADCL_VOL_MASK, + 0, + in_adc_tlv), + +WM8400_OUTPGA_SINGLE_R_TLV("Right ADC Digital Volume", + WM8400_RIGHT_ADC_DIGITAL_VOLUME, + WM8400_ADCR_VOL_SHIFT, + WM8400_ADCR_VOL_MASK, + 0, + in_adc_tlv), + +WM8400_OUTPGA_SINGLE_R_TLV("LIN12 Volume", + WM8400_LEFT_LINE_INPUT_1_2_VOLUME, + WM8400_LIN12VOL_SHIFT, + WM8400_LIN12VOL_MASK, + 0, + in_pga_tlv), + +SOC_SINGLE("LIN12 ZC Switch", WM8400_LEFT_LINE_INPUT_1_2_VOLUME, + WM8400_LI12ZC_SHIFT, 1, 0), + +SOC_SINGLE("LIN12 Mute Switch", WM8400_LEFT_LINE_INPUT_1_2_VOLUME, + WM8400_LI12MUTE_SHIFT, 1, 0), + +WM8400_OUTPGA_SINGLE_R_TLV("LIN34 Volume", + WM8400_LEFT_LINE_INPUT_3_4_VOLUME, + WM8400_LIN34VOL_SHIFT, + WM8400_LIN34VOL_MASK, + 0, + in_pga_tlv), + +SOC_SINGLE("LIN34 ZC Switch", WM8400_LEFT_LINE_INPUT_3_4_VOLUME, + WM8400_LI34ZC_SHIFT, 1, 0), + +SOC_SINGLE("LIN34 Mute Switch", WM8400_LEFT_LINE_INPUT_3_4_VOLUME, + WM8400_LI34MUTE_SHIFT, 1, 0), + +WM8400_OUTPGA_SINGLE_R_TLV("RIN12 Volume", + WM8400_RIGHT_LINE_INPUT_1_2_VOLUME, + WM8400_RIN12VOL_SHIFT, + WM8400_RIN12VOL_MASK, + 0, + in_pga_tlv), + +SOC_SINGLE("RIN12 ZC Switch", WM8400_RIGHT_LINE_INPUT_1_2_VOLUME, + WM8400_RI12ZC_SHIFT, 1, 0), + +SOC_SINGLE("RIN12 Mute Switch", WM8400_RIGHT_LINE_INPUT_1_2_VOLUME, + WM8400_RI12MUTE_SHIFT, 1, 0), + +WM8400_OUTPGA_SINGLE_R_TLV("RIN34 Volume", + WM8400_RIGHT_LINE_INPUT_3_4_VOLUME, + WM8400_RIN34VOL_SHIFT, + WM8400_RIN34VOL_MASK, + 0, + in_pga_tlv), + +SOC_SINGLE("RIN34 ZC Switch", WM8400_RIGHT_LINE_INPUT_3_4_VOLUME, + WM8400_RI34ZC_SHIFT, 1, 0), + +SOC_SINGLE("RIN34 Mute Switch", WM8400_RIGHT_LINE_INPUT_3_4_VOLUME, + WM8400_RI34MUTE_SHIFT, 1, 0), + +}; + +/* add non dapm controls */ +static int wm8400_add_controls(struct snd_soc_codec *codec) +{ + int err, i; + + for (i = 0; i < ARRAY_SIZE(wm8400_snd_controls); i++) { + err = snd_ctl_add(codec->card, + snd_soc_cnew(&wm8400_snd_controls[i],codec, + NULL)); + if (err < 0) + return err; + } + return 0; +} + +/* + * _DAPM_ Controls + */ + +static int inmixer_event (struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + u16 reg, fakepower; + + reg = wm8400_read(w->codec, WM8400_POWER_MANAGEMENT_2); + fakepower = wm8400_read(w->codec, WM8400_INTDRIVBITS); + + if (fakepower & ((1 << WM8400_INMIXL_PWR) | + (1 << WM8400_AINLMUX_PWR))) { + reg |= WM8400_AINL_ENA; + } else { + reg &= ~WM8400_AINL_ENA; + } + + if (fakepower & ((1 << WM8400_INMIXR_PWR) | + (1 << WM8400_AINRMUX_PWR))) { + reg |= WM8400_AINR_ENA; + } else { + reg &= ~WM8400_AINL_ENA; + } + wm8400_write(w->codec, WM8400_POWER_MANAGEMENT_2, reg); + + return 0; +} + +static int outmixer_event (struct snd_soc_dapm_widget *w, + struct snd_kcontrol * kcontrol, int event) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + u32 reg_shift = mc->shift; + int ret = 0; + u16 reg; + + switch (reg_shift) { + case WM8400_SPEAKER_MIXER | (WM8400_LDSPK << 8) : + reg = wm8400_read(w->codec, WM8400_OUTPUT_MIXER1); + if (reg & WM8400_LDLO) { + printk(KERN_WARNING + "Cannot set as Output Mixer 1 LDLO Set\n"); + ret = -1; + } + break; + case WM8400_SPEAKER_MIXER | (WM8400_RDSPK << 8): + reg = wm8400_read(w->codec, WM8400_OUTPUT_MIXER2); + if (reg & WM8400_RDRO) { + printk(KERN_WARNING + "Cannot set as Output Mixer 2 RDRO Set\n"); + ret = -1; + } + break; + case WM8400_OUTPUT_MIXER1 | (WM8400_LDLO << 8): + reg = wm8400_read(w->codec, WM8400_SPEAKER_MIXER); + if (reg & WM8400_LDSPK) { + printk(KERN_WARNING + "Cannot set as Speaker Mixer LDSPK Set\n"); + ret = -1; + } + break; + case WM8400_OUTPUT_MIXER2 | (WM8400_RDRO << 8): + reg = wm8400_read(w->codec, WM8400_SPEAKER_MIXER); + if (reg & WM8400_RDSPK) { + printk(KERN_WARNING + "Cannot set as Speaker Mixer RDSPK Set\n"); + ret = -1; + } + break; + } + + return ret; +} + +/* INMIX dB values */ +static const unsigned int in_mix_tlv[] = { + TLV_DB_RANGE_HEAD(1), + 0,7, TLV_DB_LINEAR_ITEM(-1200, 600), +}; + +/* Left In PGA Connections */ +static const struct snd_kcontrol_new wm8400_dapm_lin12_pga_controls[] = { +SOC_DAPM_SINGLE("LIN1 Switch", WM8400_INPUT_MIXER2, WM8400_LMN1_SHIFT, 1, 0), +SOC_DAPM_SINGLE("LIN2 Switch", WM8400_INPUT_MIXER2, WM8400_LMP2_SHIFT, 1, 0), +}; + +static const struct snd_kcontrol_new wm8400_dapm_lin34_pga_controls[] = { +SOC_DAPM_SINGLE("LIN3 Switch", WM8400_INPUT_MIXER2, WM8400_LMN3_SHIFT, 1, 0), +SOC_DAPM_SINGLE("LIN4 Switch", WM8400_INPUT_MIXER2, WM8400_LMP4_SHIFT, 1, 0), +}; + +/* Right In PGA Connections */ +static const struct snd_kcontrol_new wm8400_dapm_rin12_pga_controls[] = { +SOC_DAPM_SINGLE("RIN1 Switch", WM8400_INPUT_MIXER2, WM8400_RMN1_SHIFT, 1, 0), +SOC_DAPM_SINGLE("RIN2 Switch", WM8400_INPUT_MIXER2, WM8400_RMP2_SHIFT, 1, 0), +}; + +static const struct snd_kcontrol_new wm8400_dapm_rin34_pga_controls[] = { +SOC_DAPM_SINGLE("RIN3 Switch", WM8400_INPUT_MIXER2, WM8400_RMN3_SHIFT, 1, 0), +SOC_DAPM_SINGLE("RIN4 Switch", WM8400_INPUT_MIXER2, WM8400_RMP4_SHIFT, 1, 0), +}; + +/* INMIXL */ +static const struct snd_kcontrol_new wm8400_dapm_inmixl_controls[] = { +SOC_DAPM_SINGLE_TLV("Record Left Volume", WM8400_INPUT_MIXER3, + WM8400_LDBVOL_SHIFT, WM8400_LDBVOL_MASK, 0, in_mix_tlv), +SOC_DAPM_SINGLE_TLV("LIN2 Volume", WM8400_INPUT_MIXER5, WM8400_LI2BVOL_SHIFT, + 7, 0, in_mix_tlv), +SOC_DAPM_SINGLE("LINPGA12 Switch", WM8400_INPUT_MIXER3, WM8400_L12MNB_SHIFT, + 1, 0), +SOC_DAPM_SINGLE("LINPGA34 Switch", WM8400_INPUT_MIXER3, WM8400_L34MNB_SHIFT, + 1, 0), +}; + +/* INMIXR */ +static const struct snd_kcontrol_new wm8400_dapm_inmixr_controls[] = { +SOC_DAPM_SINGLE_TLV("Record Right Volume", WM8400_INPUT_MIXER4, + WM8400_RDBVOL_SHIFT, WM8400_RDBVOL_MASK, 0, in_mix_tlv), +SOC_DAPM_SINGLE_TLV("RIN2 Volume", WM8400_INPUT_MIXER6, WM8400_RI2BVOL_SHIFT, + 7, 0, in_mix_tlv), +SOC_DAPM_SINGLE("RINPGA12 Switch", WM8400_INPUT_MIXER3, WM8400_L12MNB_SHIFT, + 1, 0), +SOC_DAPM_SINGLE("RINPGA34 Switch", WM8400_INPUT_MIXER3, WM8400_L34MNB_SHIFT, + 1, 0), +}; + +/* AINLMUX */ +static const char *wm8400_ainlmux[] = + {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; + +static const struct soc_enum wm8400_ainlmux_enum = +SOC_ENUM_SINGLE( WM8400_INPUT_MIXER1, WM8400_AINLMODE_SHIFT, + ARRAY_SIZE(wm8400_ainlmux), wm8400_ainlmux); + +static const struct snd_kcontrol_new wm8400_dapm_ainlmux_controls = +SOC_DAPM_ENUM("Route", wm8400_ainlmux_enum); + +/* DIFFINL */ + +/* AINRMUX */ +static const char *wm8400_ainrmux[] = + {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; + +static const struct soc_enum wm8400_ainrmux_enum = +SOC_ENUM_SINGLE( WM8400_INPUT_MIXER1, WM8400_AINRMODE_SHIFT, + ARRAY_SIZE(wm8400_ainrmux), wm8400_ainrmux); + +static const struct snd_kcontrol_new wm8400_dapm_ainrmux_controls = +SOC_DAPM_ENUM("Route", wm8400_ainrmux_enum); + +/* RXVOICE */ +static const struct snd_kcontrol_new wm8400_dapm_rxvoice_controls[] = { +SOC_DAPM_SINGLE_TLV("LIN4/RXN", WM8400_INPUT_MIXER5, WM8400_LR4BVOL_SHIFT, + WM8400_LR4BVOL_MASK, 0, in_mix_tlv), +SOC_DAPM_SINGLE_TLV("RIN4/RXP", WM8400_INPUT_MIXER6, WM8400_RL4BVOL_SHIFT, + WM8400_RL4BVOL_MASK, 0, in_mix_tlv), +}; + +/* LOMIX */ +static const struct snd_kcontrol_new wm8400_dapm_lomix_controls[] = { +SOC_DAPM_SINGLE("LOMIX Right ADC Bypass Switch", WM8400_OUTPUT_MIXER1, + WM8400_LRBLO_SHIFT, 1, 0), +SOC_DAPM_SINGLE("LOMIX Left ADC Bypass Switch", WM8400_OUTPUT_MIXER1, + WM8400_LLBLO_SHIFT, 1, 0), +SOC_DAPM_SINGLE("LOMIX RIN3 Bypass Switch", WM8400_OUTPUT_MIXER1, + WM8400_LRI3LO_SHIFT, 1, 0), +SOC_DAPM_SINGLE("LOMIX LIN3 Bypass Switch", WM8400_OUTPUT_MIXER1, + WM8400_LLI3LO_SHIFT, 1, 0), +SOC_DAPM_SINGLE("LOMIX RIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER1, + WM8400_LR12LO_SHIFT, 1, 0), +SOC_DAPM_SINGLE("LOMIX LIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER1, + WM8400_LL12LO_SHIFT, 1, 0), +SOC_DAPM_SINGLE("LOMIX Left DAC Switch", WM8400_OUTPUT_MIXER1, + WM8400_LDLO_SHIFT, 1, 0), +}; + +/* ROMIX */ +static const struct snd_kcontrol_new wm8400_dapm_romix_controls[] = { +SOC_DAPM_SINGLE("ROMIX Left ADC Bypass Switch", WM8400_OUTPUT_MIXER2, + WM8400_RLBRO_SHIFT, 1, 0), +SOC_DAPM_SINGLE("ROMIX Right ADC Bypass Switch", WM8400_OUTPUT_MIXER2, + WM8400_RRBRO_SHIFT, 1, 0), +SOC_DAPM_SINGLE("ROMIX LIN3 Bypass Switch", WM8400_OUTPUT_MIXER2, + WM8400_RLI3RO_SHIFT, 1, 0), +SOC_DAPM_SINGLE("ROMIX RIN3 Bypass Switch", WM8400_OUTPUT_MIXER2, + WM8400_RRI3RO_SHIFT, 1, 0), +SOC_DAPM_SINGLE("ROMIX LIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER2, + WM8400_RL12RO_SHIFT, 1, 0), +SOC_DAPM_SINGLE("ROMIX RIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER2, + WM8400_RR12RO_SHIFT, 1, 0), +SOC_DAPM_SINGLE("ROMIX Right DAC Switch", WM8400_OUTPUT_MIXER2, + WM8400_RDRO_SHIFT, 1, 0), +}; + +/* LONMIX */ +static const struct snd_kcontrol_new wm8400_dapm_lonmix_controls[] = { +SOC_DAPM_SINGLE("LONMIX Left Mixer PGA Switch", WM8400_LINE_MIXER1, + WM8400_LLOPGALON_SHIFT, 1, 0), +SOC_DAPM_SINGLE("LONMIX Right Mixer PGA Switch", WM8400_LINE_MIXER1, + WM8400_LROPGALON_SHIFT, 1, 0), +SOC_DAPM_SINGLE("LONMIX Inverted LOP Switch", WM8400_LINE_MIXER1, + WM8400_LOPLON_SHIFT, 1, 0), +}; + +/* LOPMIX */ +static const struct snd_kcontrol_new wm8400_dapm_lopmix_controls[] = { +SOC_DAPM_SINGLE("LOPMIX Right Mic Bypass Switch", WM8400_LINE_MIXER1, + WM8400_LR12LOP_SHIFT, 1, 0), +SOC_DAPM_SINGLE("LOPMIX Left Mic Bypass Switch", WM8400_LINE_MIXER1, + WM8400_LL12LOP_SHIFT, 1, 0), +SOC_DAPM_SINGLE("LOPMIX Left Mixer PGA Switch", WM8400_LINE_MIXER1, + WM8400_LLOPGALOP_SHIFT, 1, 0), +}; + +/* RONMIX */ +static const struct snd_kcontrol_new wm8400_dapm_ronmix_controls[] = { +SOC_DAPM_SINGLE("RONMIX Right Mixer PGA Switch", WM8400_LINE_MIXER2, + WM8400_RROPGARON_SHIFT, 1, 0), +SOC_DAPM_SINGLE("RONMIX Left Mixer PGA Switch", WM8400_LINE_MIXER2, + WM8400_RLOPGARON_SHIFT, 1, 0), +SOC_DAPM_SINGLE("RONMIX Inverted ROP Switch", WM8400_LINE_MIXER2, + WM8400_ROPRON_SHIFT, 1, 0), +}; + +/* ROPMIX */ +static const struct snd_kcontrol_new wm8400_dapm_ropmix_controls[] = { +SOC_DAPM_SINGLE("ROPMIX Left Mic Bypass Switch", WM8400_LINE_MIXER2, + WM8400_RL12ROP_SHIFT, 1, 0), +SOC_DAPM_SINGLE("ROPMIX Right Mic Bypass Switch", WM8400_LINE_MIXER2, + WM8400_RR12ROP_SHIFT, 1, 0), +SOC_DAPM_SINGLE("ROPMIX Right Mixer PGA Switch", WM8400_LINE_MIXER2, + WM8400_RROPGAROP_SHIFT, 1, 0), +}; + +/* OUT3MIX */ +static const struct snd_kcontrol_new wm8400_dapm_out3mix_controls[] = { +SOC_DAPM_SINGLE("OUT3MIX LIN4/RXP Bypass Switch", WM8400_OUT3_4_MIXER, + WM8400_LI4O3_SHIFT, 1, 0), +SOC_DAPM_SINGLE("OUT3MIX Left Out PGA Switch", WM8400_OUT3_4_MIXER, + WM8400_LPGAO3_SHIFT, 1, 0), +}; + +/* OUT4MIX */ +static const struct snd_kcontrol_new wm8400_dapm_out4mix_controls[] = { +SOC_DAPM_SINGLE("OUT4MIX Right Out PGA Switch", WM8400_OUT3_4_MIXER, + WM8400_RPGAO4_SHIFT, 1, 0), +SOC_DAPM_SINGLE("OUT4MIX RIN4/RXP Bypass Switch", WM8400_OUT3_4_MIXER, + WM8400_RI4O4_SHIFT, 1, 0), +}; + +/* SPKMIX */ +static const struct snd_kcontrol_new wm8400_dapm_spkmix_controls[] = { +SOC_DAPM_SINGLE("SPKMIX LIN2 Bypass Switch", WM8400_SPEAKER_MIXER, + WM8400_LI2SPK_SHIFT, 1, 0), +SOC_DAPM_SINGLE("SPKMIX LADC Bypass Switch", WM8400_SPEAKER_MIXER, + WM8400_LB2SPK_SHIFT, 1, 0), +SOC_DAPM_SINGLE("SPKMIX Left Mixer PGA Switch", WM8400_SPEAKER_MIXER, + WM8400_LOPGASPK_SHIFT, 1, 0), +SOC_DAPM_SINGLE("SPKMIX Left DAC Switch", WM8400_SPEAKER_MIXER, + WM8400_LDSPK_SHIFT, 1, 0), +SOC_DAPM_SINGLE("SPKMIX Right DAC Switch", WM8400_SPEAKER_MIXER, + WM8400_RDSPK_SHIFT, 1, 0), +SOC_DAPM_SINGLE("SPKMIX Right Mixer PGA Switch", WM8400_SPEAKER_MIXER, + WM8400_ROPGASPK_SHIFT, 1, 0), +SOC_DAPM_SINGLE("SPKMIX RADC Bypass Switch", WM8400_SPEAKER_MIXER, + WM8400_RL12ROP_SHIFT, 1, 0), +SOC_DAPM_SINGLE("SPKMIX RIN2 Bypass Switch", WM8400_SPEAKER_MIXER, + WM8400_RI2SPK_SHIFT, 1, 0), +}; + +static const struct snd_soc_dapm_widget wm8400_dapm_widgets[] = { +/* Input Side */ +/* Input Lines */ +SND_SOC_DAPM_INPUT("LIN1"), +SND_SOC_DAPM_INPUT("LIN2"), +SND_SOC_DAPM_INPUT("LIN3"), +SND_SOC_DAPM_INPUT("LIN4/RXN"), +SND_SOC_DAPM_INPUT("RIN3"), +SND_SOC_DAPM_INPUT("RIN4/RXP"), +SND_SOC_DAPM_INPUT("RIN1"), +SND_SOC_DAPM_INPUT("RIN2"), +SND_SOC_DAPM_INPUT("Internal ADC Source"), + +/* DACs */ +SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8400_POWER_MANAGEMENT_2, + WM8400_ADCL_ENA_SHIFT, 0), +SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8400_POWER_MANAGEMENT_2, + WM8400_ADCR_ENA_SHIFT, 0), + +/* Input PGAs */ +SND_SOC_DAPM_MIXER("LIN12 PGA", WM8400_POWER_MANAGEMENT_2, + WM8400_LIN12_ENA_SHIFT, + 0, &wm8400_dapm_lin12_pga_controls[0], + ARRAY_SIZE(wm8400_dapm_lin12_pga_controls)), +SND_SOC_DAPM_MIXER("LIN34 PGA", WM8400_POWER_MANAGEMENT_2, + WM8400_LIN34_ENA_SHIFT, + 0, &wm8400_dapm_lin34_pga_controls[0], + ARRAY_SIZE(wm8400_dapm_lin34_pga_controls)), +SND_SOC_DAPM_MIXER("RIN12 PGA", WM8400_POWER_MANAGEMENT_2, + WM8400_RIN12_ENA_SHIFT, + 0, &wm8400_dapm_rin12_pga_controls[0], + ARRAY_SIZE(wm8400_dapm_rin12_pga_controls)), +SND_SOC_DAPM_MIXER("RIN34 PGA", WM8400_POWER_MANAGEMENT_2, + WM8400_RIN34_ENA_SHIFT, + 0, &wm8400_dapm_rin34_pga_controls[0], + ARRAY_SIZE(wm8400_dapm_rin34_pga_controls)), + +/* INMIXL */ +SND_SOC_DAPM_MIXER_E("INMIXL", WM8400_INTDRIVBITS, WM8400_INMIXL_PWR, 0, + &wm8400_dapm_inmixl_controls[0], + ARRAY_SIZE(wm8400_dapm_inmixl_controls), + inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + +/* AINLMUX */ +SND_SOC_DAPM_MUX_E("AILNMUX", WM8400_INTDRIVBITS, WM8400_AINLMUX_PWR, 0, + &wm8400_dapm_ainlmux_controls, inmixer_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + +/* INMIXR */ +SND_SOC_DAPM_MIXER_E("INMIXR", WM8400_INTDRIVBITS, WM8400_INMIXR_PWR, 0, + &wm8400_dapm_inmixr_controls[0], + ARRAY_SIZE(wm8400_dapm_inmixr_controls), + inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + +/* AINRMUX */ +SND_SOC_DAPM_MUX_E("AIRNMUX", WM8400_INTDRIVBITS, WM8400_AINRMUX_PWR, 0, + &wm8400_dapm_ainrmux_controls, inmixer_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + +/* Output Side */ +/* DACs */ +SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8400_POWER_MANAGEMENT_3, + WM8400_DACL_ENA_SHIFT, 0), +SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8400_POWER_MANAGEMENT_3, + WM8400_DACR_ENA_SHIFT, 0), + +/* LOMIX */ +SND_SOC_DAPM_MIXER_E("LOMIX", WM8400_POWER_MANAGEMENT_3, + WM8400_LOMIX_ENA_SHIFT, + 0, &wm8400_dapm_lomix_controls[0], + ARRAY_SIZE(wm8400_dapm_lomix_controls), + outmixer_event, SND_SOC_DAPM_PRE_REG), + +/* LONMIX */ +SND_SOC_DAPM_MIXER("LONMIX", WM8400_POWER_MANAGEMENT_3, WM8400_LON_ENA_SHIFT, + 0, &wm8400_dapm_lonmix_controls[0], + ARRAY_SIZE(wm8400_dapm_lonmix_controls)), + +/* LOPMIX */ +SND_SOC_DAPM_MIXER("LOPMIX", WM8400_POWER_MANAGEMENT_3, WM8400_LOP_ENA_SHIFT, + 0, &wm8400_dapm_lopmix_controls[0], + ARRAY_SIZE(wm8400_dapm_lopmix_controls)), + +/* OUT3MIX */ +SND_SOC_DAPM_MIXER("OUT3MIX", WM8400_POWER_MANAGEMENT_1, WM8400_OUT3_ENA_SHIFT, + 0, &wm8400_dapm_out3mix_controls[0], + ARRAY_SIZE(wm8400_dapm_out3mix_controls)), + +/* SPKMIX */ +SND_SOC_DAPM_MIXER_E("SPKMIX", WM8400_POWER_MANAGEMENT_1, WM8400_SPK_ENA_SHIFT, + 0, &wm8400_dapm_spkmix_controls[0], + ARRAY_SIZE(wm8400_dapm_spkmix_controls), outmixer_event, + SND_SOC_DAPM_PRE_REG), + +/* OUT4MIX */ +SND_SOC_DAPM_MIXER("OUT4MIX", WM8400_POWER_MANAGEMENT_1, WM8400_OUT4_ENA_SHIFT, + 0, &wm8400_dapm_out4mix_controls[0], + ARRAY_SIZE(wm8400_dapm_out4mix_controls)), + +/* ROPMIX */ +SND_SOC_DAPM_MIXER("ROPMIX", WM8400_POWER_MANAGEMENT_3, WM8400_ROP_ENA_SHIFT, + 0, &wm8400_dapm_ropmix_controls[0], + ARRAY_SIZE(wm8400_dapm_ropmix_controls)), + +/* RONMIX */ +SND_SOC_DAPM_MIXER("RONMIX", WM8400_POWER_MANAGEMENT_3, WM8400_RON_ENA_SHIFT, + 0, &wm8400_dapm_ronmix_controls[0], + ARRAY_SIZE(wm8400_dapm_ronmix_controls)), + +/* ROMIX */ +SND_SOC_DAPM_MIXER_E("ROMIX", WM8400_POWER_MANAGEMENT_3, + WM8400_ROMIX_ENA_SHIFT, + 0, &wm8400_dapm_romix_controls[0], + ARRAY_SIZE(wm8400_dapm_romix_controls), + outmixer_event, SND_SOC_DAPM_PRE_REG), + +/* LOUT PGA */ +SND_SOC_DAPM_PGA("LOUT PGA", WM8400_POWER_MANAGEMENT_1, WM8400_LOUT_ENA_SHIFT, + 0, NULL, 0), + +/* ROUT PGA */ +SND_SOC_DAPM_PGA("ROUT PGA", WM8400_POWER_MANAGEMENT_1, WM8400_ROUT_ENA_SHIFT, + 0, NULL, 0), + +/* LOPGA */ +SND_SOC_DAPM_PGA("LOPGA", WM8400_POWER_MANAGEMENT_3, WM8400_LOPGA_ENA_SHIFT, 0, + NULL, 0), + +/* ROPGA */ +SND_SOC_DAPM_PGA("ROPGA", WM8400_POWER_MANAGEMENT_3, WM8400_ROPGA_ENA_SHIFT, 0, + NULL, 0), + +/* MICBIAS */ +SND_SOC_DAPM_MICBIAS("MICBIAS", WM8400_POWER_MANAGEMENT_1, + WM8400_MIC1BIAS_ENA_SHIFT, 0), + +SND_SOC_DAPM_OUTPUT("LON"), +SND_SOC_DAPM_OUTPUT("LOP"), +SND_SOC_DAPM_OUTPUT("OUT3"), +SND_SOC_DAPM_OUTPUT("LOUT"), +SND_SOC_DAPM_OUTPUT("SPKN"), +SND_SOC_DAPM_OUTPUT("SPKP"), +SND_SOC_DAPM_OUTPUT("ROUT"), +SND_SOC_DAPM_OUTPUT("OUT4"), +SND_SOC_DAPM_OUTPUT("ROP"), +SND_SOC_DAPM_OUTPUT("RON"), + +SND_SOC_DAPM_OUTPUT("Internal DAC Sink"), +}; + +static const struct snd_soc_dapm_route audio_map[] = { + /* Make DACs turn on when playing even if not mixed into any outputs */ + {"Internal DAC Sink", NULL, "Left DAC"}, + {"Internal DAC Sink", NULL, "Right DAC"}, + + /* Make ADCs turn on when recording + * even if not mixed from any inputs */ + {"Left ADC", NULL, "Internal ADC Source"}, + {"Right ADC", NULL, "Internal ADC Source"}, + + /* Input Side */ + /* LIN12 PGA */ + {"LIN12 PGA", "LIN1 Switch", "LIN1"}, + {"LIN12 PGA", "LIN2 Switch", "LIN2"}, + /* LIN34 PGA */ + {"LIN34 PGA", "LIN3 Switch", "LIN3"}, + {"LIN34 PGA", "LIN4 Switch", "LIN4/RXN"}, + /* INMIXL */ + {"INMIXL", "Record Left Volume", "LOMIX"}, + {"INMIXL", "LIN2 Volume", "LIN2"}, + {"INMIXL", "LINPGA12 Switch", "LIN12 PGA"}, + {"INMIXL", "LINPGA34 Switch", "LIN34 PGA"}, + /* AILNMUX */ + {"AILNMUX", "INMIXL Mix", "INMIXL"}, + {"AILNMUX", "DIFFINL Mix", "LIN12 PGA"}, + {"AILNMUX", "DIFFINL Mix", "LIN34 PGA"}, + {"AILNMUX", "RXVOICE Mix", "LIN4/RXN"}, + {"AILNMUX", "RXVOICE Mix", "RIN4/RXP"}, + /* ADC */ + {"Left ADC", NULL, "AILNMUX"}, + + /* RIN12 PGA */ + {"RIN12 PGA", "RIN1 Switch", "RIN1"}, + {"RIN12 PGA", "RIN2 Switch", "RIN2"}, + /* RIN34 PGA */ + {"RIN34 PGA", "RIN3 Switch", "RIN3"}, + {"RIN34 PGA", "RIN4 Switch", "RIN4/RXP"}, + /* INMIXL */ + {"INMIXR", "Record Right Volume", "ROMIX"}, + {"INMIXR", "RIN2 Volume", "RIN2"}, + {"INMIXR", "RINPGA12 Switch", "RIN12 PGA"}, + {"INMIXR", "RINPGA34 Switch", "RIN34 PGA"}, + /* AIRNMUX */ + {"AIRNMUX", "INMIXR Mix", "INMIXR"}, + {"AIRNMUX", "DIFFINR Mix", "RIN12 PGA"}, + {"AIRNMUX", "DIFFINR Mix", "RIN34 PGA"}, + {"AIRNMUX", "RXVOICE Mix", "LIN4/RXN"}, + {"AIRNMUX", "RXVOICE Mix", "RIN4/RXP"}, + /* ADC */ + {"Right ADC", NULL, "AIRNMUX"}, + + /* LOMIX */ + {"LOMIX", "LOMIX RIN3 Bypass Switch", "RIN3"}, + {"LOMIX", "LOMIX LIN3 Bypass Switch", "LIN3"}, + {"LOMIX", "LOMIX LIN12 PGA Bypass Switch", "LIN12 PGA"}, + {"LOMIX", "LOMIX RIN12 PGA Bypass Switch", "RIN12 PGA"}, + {"LOMIX", "LOMIX Right ADC Bypass Switch", "AIRNMUX"}, + {"LOMIX", "LOMIX Left ADC Bypass Switch", "AILNMUX"}, + {"LOMIX", "LOMIX Left DAC Switch", "Left DAC"}, + + /* ROMIX */ + {"ROMIX", "ROMIX RIN3 Bypass Switch", "RIN3"}, + {"ROMIX", "ROMIX LIN3 Bypass Switch", "LIN3"}, + {"ROMIX", "ROMIX LIN12 PGA Bypass Switch", "LIN12 PGA"}, + {"ROMIX", "ROMIX RIN12 PGA Bypass Switch", "RIN12 PGA"}, + {"ROMIX", "ROMIX Right ADC Bypass Switch", "AIRNMUX"}, + {"ROMIX", "ROMIX Left ADC Bypass Switch", "AILNMUX"}, + {"ROMIX", "ROMIX Right DAC Switch", "Right DAC"}, + + /* SPKMIX */ + {"SPKMIX", "SPKMIX LIN2 Bypass Switch", "LIN2"}, + {"SPKMIX", "SPKMIX RIN2 Bypass Switch", "RIN2"}, + {"SPKMIX", "SPKMIX LADC Bypass Switch", "AILNMUX"}, + {"SPKMIX", "SPKMIX RADC Bypass Switch", "AIRNMUX"}, + {"SPKMIX", "SPKMIX Left Mixer PGA Switch", "LOPGA"}, + {"SPKMIX", "SPKMIX Right Mixer PGA Switch", "ROPGA"}, + {"SPKMIX", "SPKMIX Right DAC Switch", "Right DAC"}, + {"SPKMIX", "SPKMIX Left DAC Switch", "Right DAC"}, + + /* LONMIX */ + {"LONMIX", "LONMIX Left Mixer PGA Switch", "LOPGA"}, + {"LONMIX", "LONMIX Right Mixer PGA Switch", "ROPGA"}, + {"LONMIX", "LONMIX Inverted LOP Switch", "LOPMIX"}, + + /* LOPMIX */ + {"LOPMIX", "LOPMIX Right Mic Bypass Switch", "RIN12 PGA"}, + {"LOPMIX", "LOPMIX Left Mic Bypass Switch", "LIN12 PGA"}, + {"LOPMIX", "LOPMIX Left Mixer PGA Switch", "LOPGA"}, + + /* OUT3MIX */ + {"OUT3MIX", "OUT3MIX LIN4/RXP Bypass Switch", "LIN4/RXN"}, + {"OUT3MIX", "OUT3MIX Left Out PGA Switch", "LOPGA"}, + + /* OUT4MIX */ + {"OUT4MIX", "OUT4MIX Right Out PGA Switch", "ROPGA"}, + {"OUT4MIX", "OUT4MIX RIN4/RXP Bypass Switch", "RIN4/RXP"}, + + /* RONMIX */ + {"RONMIX", "RONMIX Right Mixer PGA Switch", "ROPGA"}, + {"RONMIX", "RONMIX Left Mixer PGA Switch", "LOPGA"}, + {"RONMIX", "RONMIX Inverted ROP Switch", "ROPMIX"}, + + /* ROPMIX */ + {"ROPMIX", "ROPMIX Left Mic Bypass Switch", "LIN12 PGA"}, + {"ROPMIX", "ROPMIX Right Mic Bypass Switch", "RIN12 PGA"}, + {"ROPMIX", "ROPMIX Right Mixer PGA Switch", "ROPGA"}, + + /* Out Mixer PGAs */ + {"LOPGA", NULL, "LOMIX"}, + {"ROPGA", NULL, "ROMIX"}, + + {"LOUT PGA", NULL, "LOMIX"}, + {"ROUT PGA", NULL, "ROMIX"}, + + /* Output Pins */ + {"LON", NULL, "LONMIX"}, + {"LOP", NULL, "LOPMIX"}, + {"OUT3", NULL, "OUT3MIX"}, + {"LOUT", NULL, "LOUT PGA"}, + {"SPKN", NULL, "SPKMIX"}, + {"ROUT", NULL, "ROUT PGA"}, + {"OUT4", NULL, "OUT4MIX"}, + {"ROP", NULL, "ROPMIX"}, + {"RON", NULL, "RONMIX"}, +}; + +static int wm8400_add_widgets(struct snd_soc_codec *codec) +{ + snd_soc_dapm_new_controls(codec, wm8400_dapm_widgets, + ARRAY_SIZE(wm8400_dapm_widgets)); + + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); + + snd_soc_dapm_new_widgets(codec); + return 0; +} + +/* + * Clock after FLL and dividers + */ +static int wm8400_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct wm8400_priv *wm8400 = codec->private_data; + + wm8400->sysclk = freq; + return 0; +} + +/* + * Sets ADC and Voice DAC format. + */ +static int wm8400_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + u16 audio1, audio3; + + audio1 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_1); + audio3 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_3); + + /* set master/slave audio interface */ + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + audio3 &= ~WM8400_AIF_MSTR1; + break; + case SND_SOC_DAIFMT_CBM_CFM: + audio3 |= WM8400_AIF_MSTR1; + break; + default: + return -EINVAL; + } + + audio1 &= ~WM8400_AIF_FMT_MASK; + + /* interface format */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + audio1 |= WM8400_AIF_FMT_I2S; + audio1 &= ~WM8400_AIF_LRCLK_INV; + break; + case SND_SOC_DAIFMT_RIGHT_J: + audio1 |= WM8400_AIF_FMT_RIGHTJ; + audio1 &= ~WM8400_AIF_LRCLK_INV; + break; + case SND_SOC_DAIFMT_LEFT_J: + audio1 |= WM8400_AIF_FMT_LEFTJ; + audio1 &= ~WM8400_AIF_LRCLK_INV; + break; + case SND_SOC_DAIFMT_DSP_A: + audio1 |= WM8400_AIF_FMT_DSP; + audio1 &= ~WM8400_AIF_LRCLK_INV; + break; + case SND_SOC_DAIFMT_DSP_B: + audio1 |= WM8400_AIF_FMT_DSP | WM8400_AIF_LRCLK_INV; + break; + default: + return -EINVAL; + } + + wm8400_write(codec, WM8400_AUDIO_INTERFACE_1, audio1); + wm8400_write(codec, WM8400_AUDIO_INTERFACE_3, audio3); + return 0; +} + +static int wm8400_set_dai_clkdiv(struct snd_soc_dai *codec_dai, + int div_id, int div) +{ + struct snd_soc_codec *codec = codec_dai->codec; + u16 reg; + + switch (div_id) { + case WM8400_MCLK_DIV: + reg = wm8400_read(codec, WM8400_CLOCKING_2) & + ~WM8400_MCLK_DIV_MASK; + wm8400_write(codec, WM8400_CLOCKING_2, reg | div); + break; + case WM8400_DACCLK_DIV: + reg = wm8400_read(codec, WM8400_CLOCKING_2) & + ~WM8400_DAC_CLKDIV_MASK; + wm8400_write(codec, WM8400_CLOCKING_2, reg | div); + break; + case WM8400_ADCCLK_DIV: + reg = wm8400_read(codec, WM8400_CLOCKING_2) & + ~WM8400_ADC_CLKDIV_MASK; + wm8400_write(codec, WM8400_CLOCKING_2, reg | div); + break; + case WM8400_BCLK_DIV: + reg = wm8400_read(codec, WM8400_CLOCKING_1) & + ~WM8400_BCLK_DIV_MASK; + wm8400_write(codec, WM8400_CLOCKING_1, reg | div); + break; + default: + return -EINVAL; + } + + return 0; +} + +/* + * Set PCM DAI bit size and sample rate. + */ +static int wm8400_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_device *socdev = rtd->socdev; + struct snd_soc_codec *codec = socdev->card->codec; + u16 audio1 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_1); + + audio1 &= ~WM8400_AIF_WL_MASK; + /* bit size */ + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + break; + case SNDRV_PCM_FORMAT_S20_3LE: + audio1 |= WM8400_AIF_WL_20BITS; + break; + case SNDRV_PCM_FORMAT_S24_LE: + audio1 |= WM8400_AIF_WL_24BITS; + break; + case SNDRV_PCM_FORMAT_S32_LE: + audio1 |= WM8400_AIF_WL_32BITS; + break; + } + + wm8400_write(codec, WM8400_AUDIO_INTERFACE_1, audio1); + return 0; +} + +static int wm8400_mute(struct snd_soc_dai *dai, int mute) +{ + struct snd_soc_codec *codec = dai->codec; + u16 val = wm8400_read(codec, WM8400_DAC_CTRL) & ~WM8400_DAC_MUTE; + + if (mute) + wm8400_write(codec, WM8400_DAC_CTRL, val | WM8400_DAC_MUTE); + else + wm8400_write(codec, WM8400_DAC_CTRL, val); + + return 0; +} + +/* TODO: set bias for best performance at standby */ +static int wm8400_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + struct wm8400_priv *wm8400 = codec->private_data; + u16 val; + int ret; + + switch (level) { + case SND_SOC_BIAS_ON: + break; + + case SND_SOC_BIAS_PREPARE: + /* VMID=2*50k */ + val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1) & + ~WM8400_VMID_MODE_MASK; + wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val | 0x2); + break; + + case SND_SOC_BIAS_STANDBY: + if (codec->bias_level == SND_SOC_BIAS_OFF) { + ret = regulator_bulk_enable(ARRAY_SIZE(power), + &power[0]); + if (ret != 0) { + dev_err(wm8400->wm8400->dev, + "Failed to enable regulators: %d\n", + ret); + return ret; + } + + wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, + WM8400_CODEC_ENA | WM8400_SYSCLK_ENA); + + /* Enable all output discharge bits */ + wm8400_write(codec, WM8400_ANTIPOP1, WM8400_DIS_LLINE | + WM8400_DIS_RLINE | WM8400_DIS_OUT3 | + WM8400_DIS_OUT4 | WM8400_DIS_LOUT | + WM8400_DIS_ROUT); + + /* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */ + wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST | + WM8400_BUFDCOPEN | WM8400_POBCTRL); + + msleep(500); + + /* Enable outputs */ + val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1); + val |= WM8400_SPK_ENA | WM8400_OUT3_ENA | + WM8400_OUT4_ENA | WM8400_LOUT_ENA | + WM8400_ROUT_ENA; + wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val); + + /* disable all output discharge bits */ + wm8400_write(codec, WM8400_ANTIPOP1, 0); + + /* Enable VREF & VMID at 2x50k */ + val |= 0x2 | WM8400_VREF_ENA; + wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val); + + msleep(600); + + /* Enable BUFIOEN */ + wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST | + WM8400_BUFDCOPEN | WM8400_POBCTRL | + WM8400_BUFIOEN); + + /* Disable outputs */ + val &= ~(WM8400_SPK_ENA | WM8400_OUT3_ENA | + WM8400_OUT4_ENA | WM8400_LOUT_ENA | + WM8400_ROUT_ENA); + wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val); + + /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ + wm8400_write(codec, WM8400_ANTIPOP2, WM8400_BUFIOEN); + } + + /* VMID=2*300k */ + val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1) & + ~WM8400_VMID_MODE_MASK; + wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val | 0x4); + break; + + case SND_SOC_BIAS_OFF: + /* Enable POBCTRL and SOFT_ST */ + wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST | + WM8400_POBCTRL | WM8400_BUFIOEN); + + /* Enable POBCTRL, SOFT_ST and BUFDCOPEN */ + wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST | + WM8400_BUFDCOPEN | WM8400_POBCTRL | + WM8400_BUFIOEN); + + /* mute DAC */ + val = wm8400_read(codec, WM8400_DAC_CTRL); + wm8400_write(codec, WM8400_DAC_CTRL, val | WM8400_DAC_MUTE); + + /* Enable any disabled outputs */ + val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1); + val |= WM8400_SPK_ENA | WM8400_OUT3_ENA | + WM8400_OUT4_ENA | WM8400_LOUT_ENA | + WM8400_ROUT_ENA; + wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val); + + /* Disable VMID */ + val &= ~WM8400_VMID_MODE_MASK; + wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val); + + msleep(300); + + /* Enable all output discharge bits */ + wm8400_write(codec, WM8400_ANTIPOP1, WM8400_DIS_LLINE | + WM8400_DIS_RLINE | WM8400_DIS_OUT3 | + WM8400_DIS_OUT4 | WM8400_DIS_LOUT | + WM8400_DIS_ROUT); + + /* Disable VREF */ + val &= ~WM8400_VREF_ENA; + wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val); + + /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ + wm8400_write(codec, WM8400_ANTIPOP2, 0x0); + + ret = regulator_bulk_disable(ARRAY_SIZE(power), + &power[0]); + if (ret != 0) + return ret; + + break; + } + + codec->bias_level = level; + return 0; +} + +#define WM8400_RATES SNDRV_PCM_RATE_8000_96000 + +#define WM8400_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ + SNDRV_PCM_FMTBIT_S24_LE) + +/* + * The WM8400 supports 2 different and mutually exclusive DAI + * configurations. + * + * 1. ADC/DAC on Primary Interface + * 2. ADC on Primary Interface/DAC on secondary + */ +struct snd_soc_dai wm8400_dai = { +/* ADC/DAC on primary */ + .name = "WM8400 ADC/DAC Primary", + .id = 1, + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = WM8400_RATES, + .formats = WM8400_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = WM8400_RATES, + .formats = WM8400_FORMATS, + }, + .ops = { + .hw_params = wm8400_hw_params, + .digital_mute = wm8400_mute, + .set_fmt = wm8400_set_dai_fmt, + .set_clkdiv = wm8400_set_dai_clkdiv, + .set_sysclk = wm8400_set_dai_sysclk, + }, +}; +EXPORT_SYMBOL_GPL(wm8400_dai); + +static int wm8400_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->card->codec; + + wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF); + + return 0; +} + +static int wm8400_resume(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->card->codec; + + wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + + return 0; +} + +static struct snd_soc_codec *wm8400_codec; + +static int wm8400_probe(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec; + int ret; + + if (!wm8400_codec) { + dev_err(&pdev->dev, "wm8400 not yet discovered\n"); + return -ENODEV; + } + codec = wm8400_codec; + + socdev->card->codec = codec; + + /* register pcms */ + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + if (ret < 0) { + dev_err(&pdev->dev, "failed to create pcms\n"); + goto pcm_err; + } + + wm8400_add_controls(codec); + wm8400_add_widgets(codec); + + ret = snd_soc_init_card(socdev); + if (ret < 0) { + dev_err(&pdev->dev, "failed to register card\n"); + goto card_err; + } + + return ret; + +card_err: + snd_soc_free_pcms(socdev); + snd_soc_dapm_free(socdev); +pcm_err: + return ret; +} + +/* power down chip */ +static int wm8400_remove(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + + snd_soc_free_pcms(socdev); + snd_soc_dapm_free(socdev); + + return 0; +} + +struct snd_soc_codec_device soc_codec_dev_wm8400 = { + .probe = wm8400_probe, + .remove = wm8400_remove, + .suspend = wm8400_suspend, + .resume = wm8400_resume, +}; + +static void wm8400_probe_deferred(struct work_struct *work) +{ + struct wm8400_priv *priv = container_of(work, struct wm8400_priv, + work); + struct snd_soc_codec *codec = &priv->codec; + int ret; + + /* charge output caps */ + wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + + /* We're done, tell the subsystem. */ + ret = snd_soc_register_codec(codec); + if (ret != 0) { + dev_err(priv->wm8400->dev, + "Failed to register codec: %d\n", ret); + goto err; + } + + ret = snd_soc_register_dai(&wm8400_dai); + if (ret != 0) { + dev_err(priv->wm8400->dev, + "Failed to register DAI: %d\n", ret); + goto err_codec; + } + + return; + +err_codec: + snd_soc_unregister_codec(codec); +err: + wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF); +} + +static int wm8400_codec_probe(struct platform_device *dev) +{ + struct wm8400_priv *priv; + int ret; + u16 reg; + struct snd_soc_codec *codec; + + priv = kzalloc(sizeof(struct wm8400_priv), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + + codec = &priv->codec; + codec->private_data = priv; + codec->control_data = dev->dev.driver_data; + priv->wm8400 = dev->dev.driver_data; + + ret = regulator_bulk_get(priv->wm8400->dev, + ARRAY_SIZE(power), &power[0]); + if (ret != 0) { + dev_err(&dev->dev, "Failed to get regulators: %d\n", ret); + goto err; + } + + codec->dev = &dev->dev; + wm8400_dai.dev = &dev->dev; + + codec->name = "WM8400"; + codec->owner = THIS_MODULE; + codec->read = wm8400_read; + codec->write = wm8400_write; + codec->bias_level = SND_SOC_BIAS_OFF; + codec->set_bias_level = wm8400_set_bias_level; + codec->dai = &wm8400_dai; + codec->num_dai = 1; + codec->reg_cache_size = WM8400_REGISTER_COUNT; + mutex_init(&codec->mutex); + INIT_LIST_HEAD(&codec->dapm_widgets); + INIT_LIST_HEAD(&codec->dapm_paths); + INIT_WORK(&priv->work, wm8400_probe_deferred); + + wm8400_codec_reset(codec); + + reg = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1); + wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, reg | WM8400_CODEC_ENA); + + /* Latch volume update bits */ + reg = wm8400_read(codec, WM8400_LEFT_LINE_INPUT_1_2_VOLUME); + wm8400_write(codec, WM8400_LEFT_LINE_INPUT_1_2_VOLUME, + reg & WM8400_IPVU); + reg = wm8400_read(codec, WM8400_RIGHT_LINE_INPUT_1_2_VOLUME); + wm8400_write(codec, WM8400_RIGHT_LINE_INPUT_1_2_VOLUME, + reg & WM8400_IPVU); + + wm8400_write(codec, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); + wm8400_write(codec, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); + + wm8400_codec = codec; + + if (!schedule_work(&priv->work)) { + ret = -EINVAL; + goto err_regulator; + } + + return 0; + +err_regulator: + wm8400_codec = NULL; + regulator_bulk_free(ARRAY_SIZE(power), power); +err: + kfree(priv); + return ret; +} + +static int __exit wm8400_codec_remove(struct platform_device *dev) +{ + struct wm8400_priv *priv = wm8400_codec->private_data; + u16 reg; + + snd_soc_unregister_dai(&wm8400_dai); + snd_soc_unregister_codec(wm8400_codec); + + reg = wm8400_read(wm8400_codec, WM8400_POWER_MANAGEMENT_1); + wm8400_write(wm8400_codec, WM8400_POWER_MANAGEMENT_1, + reg & (~WM8400_CODEC_ENA)); + + regulator_bulk_free(ARRAY_SIZE(power), power); + kfree(priv); + + wm8400_codec = NULL; + + return 0; +} + +static struct platform_driver wm8400_codec_driver = { + .driver = { + .name = "wm8400-codec", + .owner = THIS_MODULE, + }, + .probe = wm8400_codec_probe, + .remove = __exit_p(wm8400_codec_remove), +}; + +static int __init wm8400_codec_init(void) +{ + return platform_driver_register(&wm8400_codec_driver); +} +module_init(wm8400_codec_init); + +static void __exit wm8400_codec_exit(void) +{ + platform_driver_unregister(&wm8400_codec_driver); +} +module_exit(wm8400_codec_exit); + +EXPORT_SYMBOL_GPL(soc_codec_dev_wm8400); + +MODULE_DESCRIPTION("ASoC WM8400 driver"); +MODULE_AUTHOR("Mark Brown"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:wm8400-codec"); diff --git a/sound/soc/codecs/wm8400.h b/sound/soc/codecs/wm8400.h new file mode 100644 index 00000000000..79c5934d477 --- /dev/null +++ b/sound/soc/codecs/wm8400.h @@ -0,0 +1,62 @@ +/* + * wm8400.h -- audio driver for WM8400 + * + * Copyright 2008 Wolfson Microelectronics PLC. + * Author: Mark Brown + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef _WM8400_CODEC_H +#define _WM8400_CODEC_H + +#define WM8400_MCLK_DIV 0 +#define WM8400_DACCLK_DIV 1 +#define WM8400_ADCCLK_DIV 2 +#define WM8400_BCLK_DIV 3 + +#define WM8400_MCLK_DIV_1 0x400 +#define WM8400_MCLK_DIV_2 0x800 + +#define WM8400_DAC_CLKDIV_1 0x00 +#define WM8400_DAC_CLKDIV_1_5 0x04 +#define WM8400_DAC_CLKDIV_2 0x08 +#define WM8400_DAC_CLKDIV_3 0x0c +#define WM8400_DAC_CLKDIV_4 0x10 +#define WM8400_DAC_CLKDIV_5_5 0x14 +#define WM8400_DAC_CLKDIV_6 0x18 + +#define WM8400_ADC_CLKDIV_1 0x00 +#define WM8400_ADC_CLKDIV_1_5 0x20 +#define WM8400_ADC_CLKDIV_2 0x40 +#define WM8400_ADC_CLKDIV_3 0x60 +#define WM8400_ADC_CLKDIV_4 0x80 +#define WM8400_ADC_CLKDIV_5_5 0xa0 +#define WM8400_ADC_CLKDIV_6 0xc0 + + +#define WM8400_BCLK_DIV_1 (0x0 << 1) +#define WM8400_BCLK_DIV_1_5 (0x1 << 1) +#define WM8400_BCLK_DIV_2 (0x2 << 1) +#define WM8400_BCLK_DIV_3 (0x3 << 1) +#define WM8400_BCLK_DIV_4 (0x4 << 1) +#define WM8400_BCLK_DIV_5_5 (0x5 << 1) +#define WM8400_BCLK_DIV_6 (0x6 << 1) +#define WM8400_BCLK_DIV_8 (0x7 << 1) +#define WM8400_BCLK_DIV_11 (0x8 << 1) +#define WM8400_BCLK_DIV_12 (0x9 << 1) +#define WM8400_BCLK_DIV_16 (0xA << 1) +#define WM8400_BCLK_DIV_22 (0xB << 1) +#define WM8400_BCLK_DIV_24 (0xC << 1) +#define WM8400_BCLK_DIV_32 (0xD << 1) +#define WM8400_BCLK_DIV_44 (0xE << 1) +#define WM8400_BCLK_DIV_48 (0xF << 1) + +extern struct snd_soc_dai wm8400_dai; +extern struct snd_soc_codec_device soc_codec_dev_wm8400; + +#endif -- GitLab From 02b7cbc3994622900e8fc201f5f229b591c43628 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 11 Mar 2009 14:12:28 +0000 Subject: [PATCH 3091/4982] ASoC: Remove version display from WM8580 driver Signed-off-by: Mark Brown --- sound/soc/codecs/wm8580.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index d3c51ba5e6f..6cab82a9c9d 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -35,8 +35,6 @@ #include "wm8580.h" -#define WM8580_VERSION "0.1" - struct pll_state { unsigned int in; unsigned int out; @@ -972,8 +970,6 @@ static int wm8580_probe(struct platform_device *pdev) struct wm8580_priv *wm8580; int ret = 0; - pr_info("WM8580 Audio Codec %s\n", WM8580_VERSION); - setup = socdev->codec_data; codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); if (codec == NULL) -- GitLab From 908002161247e6e68c478052926b62d9a3d72418 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 11 Mar 2009 23:18:32 +0800 Subject: [PATCH 3092/4982] nlattr: Fix build error with NET off We moved the netlink attribute support from net to lib in order for it to be available for general consumption. However, parts of the code (the bits that we don't need :) really depends on NET because the target object is sk_buff. This patch fixes this by wrapping them in CONFIG_NET. Some EXPORTs have been moved to make this work. Tested-by: Geert Uytterhoeven Signed-off-by: Herbert Xu --- lib/nlattr.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/nlattr.c b/lib/nlattr.c index 56c3ce7fe29..80009a24e21 100644 --- a/lib/nlattr.c +++ b/lib/nlattr.c @@ -281,6 +281,7 @@ int nla_strcmp(const struct nlattr *nla, const char *str) return d; } +#ifdef CONFIG_NET /** * __nla_reserve - reserve room for attribute on the skb * @skb: socket buffer to reserve room on @@ -305,6 +306,7 @@ struct nlattr *__nla_reserve(struct sk_buff *skb, int attrtype, int attrlen) return nla; } +EXPORT_SYMBOL(__nla_reserve); /** * __nla_reserve_nohdr - reserve room for attribute without header @@ -325,6 +327,7 @@ void *__nla_reserve_nohdr(struct sk_buff *skb, int attrlen) return start; } +EXPORT_SYMBOL(__nla_reserve_nohdr); /** * nla_reserve - reserve room for attribute on the skb @@ -345,6 +348,7 @@ struct nlattr *nla_reserve(struct sk_buff *skb, int attrtype, int attrlen) return __nla_reserve(skb, attrtype, attrlen); } +EXPORT_SYMBOL(nla_reserve); /** * nla_reserve_nohdr - reserve room for attribute without header @@ -363,6 +367,7 @@ void *nla_reserve_nohdr(struct sk_buff *skb, int attrlen) return __nla_reserve_nohdr(skb, attrlen); } +EXPORT_SYMBOL(nla_reserve_nohdr); /** * __nla_put - Add a netlink attribute to a socket buffer @@ -382,6 +387,7 @@ void __nla_put(struct sk_buff *skb, int attrtype, int attrlen, nla = __nla_reserve(skb, attrtype, attrlen); memcpy(nla_data(nla), data, attrlen); } +EXPORT_SYMBOL(__nla_put); /** * __nla_put_nohdr - Add a netlink attribute without header @@ -399,6 +405,7 @@ void __nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data) start = __nla_reserve_nohdr(skb, attrlen); memcpy(start, data, attrlen); } +EXPORT_SYMBOL(__nla_put_nohdr); /** * nla_put - Add a netlink attribute to a socket buffer @@ -418,6 +425,7 @@ int nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data) __nla_put(skb, attrtype, attrlen, data); return 0; } +EXPORT_SYMBOL(nla_put); /** * nla_put_nohdr - Add a netlink attribute without header @@ -436,6 +444,7 @@ int nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data) __nla_put_nohdr(skb, attrlen, data); return 0; } +EXPORT_SYMBOL(nla_put_nohdr); /** * nla_append - Add a netlink attribute without header or padding @@ -454,20 +463,13 @@ int nla_append(struct sk_buff *skb, int attrlen, const void *data) memcpy(skb_put(skb, attrlen), data, attrlen); return 0; } +EXPORT_SYMBOL(nla_append); +#endif EXPORT_SYMBOL(nla_validate); EXPORT_SYMBOL(nla_parse); EXPORT_SYMBOL(nla_find); EXPORT_SYMBOL(nla_strlcpy); -EXPORT_SYMBOL(__nla_reserve); -EXPORT_SYMBOL(__nla_reserve_nohdr); -EXPORT_SYMBOL(nla_reserve); -EXPORT_SYMBOL(nla_reserve_nohdr); -EXPORT_SYMBOL(__nla_put); -EXPORT_SYMBOL(__nla_put_nohdr); -EXPORT_SYMBOL(nla_put); -EXPORT_SYMBOL(nla_put_nohdr); EXPORT_SYMBOL(nla_memcpy); EXPORT_SYMBOL(nla_memcmp); EXPORT_SYMBOL(nla_strcmp); -EXPORT_SYMBOL(nla_append); -- GitLab From ff8cf9a93800e8118ea097c1aba7203d59a0f3f1 Mon Sep 17 00:00:00 2001 From: John Dykstra Date: Wed, 11 Mar 2009 09:22:51 -0700 Subject: [PATCH 3093/4982] ipv6: Fix BUG when disabled ipv6 module is unloaded Do not try to "uninitialize" ipv6 if its initialization had been skipped because module parameter disable=1 had been specified. Reported-by: Thomas Backlund Signed-off-by: John Dykstra Acked-by: Brian Haley Signed-off-by: David S. Miller --- net/ipv6/af_inet6.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index da944eca2ca..9c8309ed35c 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -1192,6 +1192,9 @@ module_init(inet6_init); static void __exit inet6_exit(void) { + if (disable_ipv6) + return; + /* First of all disallow new sockets creation. */ sock_unregister(PF_INET6); /* Disallow any further netlink messages */ -- GitLab From fc1ad92dfc4e363a055053746552cdb445ba5c57 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 11 Mar 2009 09:23:57 -0700 Subject: [PATCH 3094/4982] tcp: allow timestamps even if SYN packet has tsval=0 Some systems send SYN packets with apparently wrong RFC1323 timestamp option values [timestamp tsval=0 tsecr=0]. It might be for security reasons (http://www.secuobs.com/plugs/25220.shtml ) Linux TCP stack ignores this option and sends back a SYN+ACK packet without timestamp option, thus many TCP flows cannot use timestamps and lose some benefit of RFC1323. Other operating systems seem to not care about initial tsval value, and let tcp flows to negotiate timestamp option. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/tcp_ipv4.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index a7381205bbf..d0a314879d8 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1226,15 +1226,6 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) if (want_cookie && !tmp_opt.saw_tstamp) tcp_clear_options(&tmp_opt); - if (tmp_opt.saw_tstamp && !tmp_opt.rcv_tsval) { - /* Some OSes (unknown ones, but I see them on web server, which - * contains information interesting only for windows' - * users) do not send their stamp in SYN. It is easy case. - * We simply do not advertise TS support. - */ - tmp_opt.saw_tstamp = 0; - tmp_opt.tstamp_ok = 0; - } tmp_opt.tstamp_ok = tmp_opt.saw_tstamp; tcp_openreq_init(req, &tmp_opt, skb); -- GitLab From 5314adc3612d893c7cc526b3312d124805e45bc3 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 11 Mar 2009 16:28:29 +0000 Subject: [PATCH 3095/4982] ASoC: Fix formats for s3c24xx-i2s register prints The register values are all u32 so don't need the long format. Signed-off-by: Mark Brown --- sound/soc/s3c24xx/s3c24xx-i2s.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c index 580cfed71cc..407ccd7180f 100644 --- a/sound/soc/s3c24xx/s3c24xx-i2s.c +++ b/sound/soc/s3c24xx/s3c24xx-i2s.c @@ -83,7 +83,7 @@ static void s3c24xx_snd_txctrl(int on) iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); - pr_debug("r: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon); + pr_debug("r: IISCON: %x IISMOD: %x IISFCON: %x\n", iiscon, iismod, iisfcon); if (on) { iisfcon |= S3C2410_IISFCON_TXDMA | S3C2410_IISFCON_TXENABLE; @@ -113,7 +113,7 @@ static void s3c24xx_snd_txctrl(int on) writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); } - pr_debug("w: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon); + pr_debug("w: IISCON: %x IISMOD: %x IISFCON: %x\n", iiscon, iismod, iisfcon); } static void s3c24xx_snd_rxctrl(int on) @@ -128,7 +128,7 @@ static void s3c24xx_snd_rxctrl(int on) iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); - pr_debug("r: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon); + pr_debug("r: IISCON: %x IISMOD: %x IISFCON: %x\n", iiscon, iismod, iisfcon); if (on) { iisfcon |= S3C2410_IISFCON_RXDMA | S3C2410_IISFCON_RXENABLE; @@ -158,7 +158,7 @@ static void s3c24xx_snd_rxctrl(int on) writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); } - pr_debug("w: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon); + pr_debug("w: IISCON: %x IISMOD: %x IISFCON: %x\n", iiscon, iismod, iisfcon); } /* @@ -206,7 +206,7 @@ static int s3c24xx_i2s_set_fmt(struct snd_soc_dai *cpu_dai, pr_debug("Entered %s\n", __func__); iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); - pr_debug("hw_params r: IISMOD: %lx \n", iismod); + pr_debug("hw_params r: IISMOD: %x \n", iismod); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: @@ -231,7 +231,7 @@ static int s3c24xx_i2s_set_fmt(struct snd_soc_dai *cpu_dai, } writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); - pr_debug("hw_params w: IISMOD: %lx \n", iismod); + pr_debug("hw_params w: IISMOD: %x \n", iismod); return 0; } @@ -251,7 +251,7 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, /* Working copies of register */ iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); - pr_debug("hw_params r: IISMOD: %lx\n", iismod); + pr_debug("hw_params r: IISMOD: %x\n", iismod); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: @@ -269,7 +269,7 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, } writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); - pr_debug("hw_params w: IISMOD: %lx\n", iismod); + pr_debug("hw_params w: IISMOD: %x\n", iismod); return 0; } -- GitLab From 5e9ccc372dc855900c4a75b21286038938e288c7 Mon Sep 17 00:00:00 2001 From: Christine Caulfield Date: Wed, 28 Jan 2009 12:57:40 -0600 Subject: [PATCH 3096/4982] dlm: replace idr with hash table for connections Integer nodeids can be too large for the idr code; use a hash table instead. Signed-off-by: Christine Caulfield Signed-off-by: David Teigland --- fs/dlm/lowcomms.c | 171 +++++++++++++++++++++++++--------------------- 1 file changed, 92 insertions(+), 79 deletions(-) diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 982314c472c..609108a8326 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c @@ -2,7 +2,7 @@ ******************************************************************************* ** ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. -** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. +** Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved. ** ** This copyrighted material is made available to anyone wishing to use, ** modify, copy, or redistribute it subject to the terms and conditions @@ -48,7 +48,6 @@ #include #include #include -#include #include #include #include @@ -61,6 +60,7 @@ #include "config.h" #define NEEDED_RMEM (4*1024*1024) +#define CONN_HASH_SIZE 32 struct cbuf { unsigned int base; @@ -115,6 +115,7 @@ struct connection { int retries; #define MAX_CONNECT_RETRIES 3 int sctp_assoc; + struct hlist_node list; struct connection *othercon; struct work_struct rwork; /* Receive workqueue */ struct work_struct swork; /* Send workqueue */ @@ -139,14 +140,37 @@ static int dlm_local_count; static struct workqueue_struct *recv_workqueue; static struct workqueue_struct *send_workqueue; -static DEFINE_IDR(connections_idr); +static struct hlist_head connection_hash[CONN_HASH_SIZE]; static DEFINE_MUTEX(connections_lock); -static int max_nodeid; static struct kmem_cache *con_cache; static void process_recv_sockets(struct work_struct *work); static void process_send_sockets(struct work_struct *work); + +/* This is deliberately very simple because most clusters have simple + sequential nodeids, so we should be able to go straight to a connection + struct in the array */ +static inline int nodeid_hash(int nodeid) +{ + return nodeid & (CONN_HASH_SIZE-1); +} + +static struct connection *__find_con(int nodeid) +{ + int r; + struct hlist_node *h; + struct connection *con; + + r = nodeid_hash(nodeid); + + hlist_for_each_entry(con, h, &connection_hash[r], list) { + if (con->nodeid == nodeid) + return con; + } + return NULL; +} + /* * If 'allocation' is zero then we don't attempt to create a new * connection structure for this node. @@ -155,31 +179,17 @@ static struct connection *__nodeid2con(int nodeid, gfp_t alloc) { struct connection *con = NULL; int r; - int n; - con = idr_find(&connections_idr, nodeid); + con = __find_con(nodeid); if (con || !alloc) return con; - r = idr_pre_get(&connections_idr, alloc); - if (!r) - return NULL; - con = kmem_cache_zalloc(con_cache, alloc); if (!con) return NULL; - r = idr_get_new_above(&connections_idr, con, nodeid, &n); - if (r) { - kmem_cache_free(con_cache, con); - return NULL; - } - - if (n != nodeid) { - idr_remove(&connections_idr, n); - kmem_cache_free(con_cache, con); - return NULL; - } + r = nodeid_hash(nodeid); + hlist_add_head(&con->list, &connection_hash[r]); con->nodeid = nodeid; mutex_init(&con->sock_mutex); @@ -190,19 +200,30 @@ static struct connection *__nodeid2con(int nodeid, gfp_t alloc) /* Setup action pointers for child sockets */ if (con->nodeid) { - struct connection *zerocon = idr_find(&connections_idr, 0); + struct connection *zerocon = __find_con(0); con->connect_action = zerocon->connect_action; if (!con->rx_action) con->rx_action = zerocon->rx_action; } - if (nodeid > max_nodeid) - max_nodeid = nodeid; - return con; } +/* Loop round all connections */ +static void foreach_conn(void (*conn_func)(struct connection *c)) +{ + int i; + struct hlist_node *h, *n; + struct connection *con; + + for (i = 0; i < CONN_HASH_SIZE; i++) { + hlist_for_each_entry_safe(con, h, n, &connection_hash[i], list){ + conn_func(con); + } + } +} + static struct connection *nodeid2con(int nodeid, gfp_t allocation) { struct connection *con; @@ -218,14 +239,17 @@ static struct connection *nodeid2con(int nodeid, gfp_t allocation) static struct connection *assoc2con(int assoc_id) { int i; + struct hlist_node *h; struct connection *con; mutex_lock(&connections_lock); - for (i=0; i<=max_nodeid; i++) { - con = __nodeid2con(i, 0); - if (con && con->sctp_assoc == assoc_id) { - mutex_unlock(&connections_lock); - return con; + + for (i = 0 ; i < CONN_HASH_SIZE; i++) { + hlist_for_each_entry(con, h, &connection_hash[i], list) { + if (con && con->sctp_assoc == assoc_id) { + mutex_unlock(&connections_lock); + return con; + } } } mutex_unlock(&connections_lock); @@ -376,25 +400,23 @@ static void sctp_send_shutdown(sctp_assoc_t associd) log_print("send EOF to node failed: %d", ret); } +static void sctp_init_failed_foreach(struct connection *con) +{ + con->sctp_assoc = 0; + if (test_and_clear_bit(CF_CONNECT_PENDING, &con->flags)) { + if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags)) + queue_work(send_workqueue, &con->swork); + } +} + /* INIT failed but we don't know which node... restart INIT on all pending nodes */ static void sctp_init_failed(void) { - int i; - struct connection *con; - mutex_lock(&connections_lock); - for (i=1; i<=max_nodeid; i++) { - con = __nodeid2con(i, 0); - if (!con) - continue; - con->sctp_assoc = 0; - if (test_and_clear_bit(CF_CONNECT_PENDING, &con->flags)) { - if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags)) { - queue_work(send_workqueue, &con->swork); - } - } - } + + foreach_conn(sctp_init_failed_foreach); + mutex_unlock(&connections_lock); } @@ -1313,13 +1335,10 @@ out_connect: static void clean_one_writequeue(struct connection *con) { - struct list_head *list; - struct list_head *temp; + struct writequeue_entry *e, *safe; spin_lock(&con->writequeue_lock); - list_for_each_safe(list, temp, &con->writequeue) { - struct writequeue_entry *e = - list_entry(list, struct writequeue_entry, list); + list_for_each_entry_safe(e, safe, &con->writequeue, list) { list_del(&e->list); free_entry(e); } @@ -1369,14 +1388,7 @@ static void process_send_sockets(struct work_struct *work) /* Discard all entries on the write queues */ static void clean_writequeues(void) { - int nodeid; - - for (nodeid = 1; nodeid <= max_nodeid; nodeid++) { - struct connection *con = __nodeid2con(nodeid, 0); - - if (con) - clean_one_writequeue(con); - } + foreach_conn(clean_one_writequeue); } static void work_stop(void) @@ -1406,23 +1418,29 @@ static int work_start(void) return 0; } -void dlm_lowcomms_stop(void) +static void stop_conn(struct connection *con) { - int i; - struct connection *con; + con->flags |= 0x0F; + if (con->sock) + con->sock->sk->sk_user_data = NULL; +} +static void free_conn(struct connection *con) +{ + close_connection(con, true); + if (con->othercon) + kmem_cache_free(con_cache, con->othercon); + hlist_del(&con->list); + kmem_cache_free(con_cache, con); +} + +void dlm_lowcomms_stop(void) +{ /* Set all the flags to prevent any socket activity. */ mutex_lock(&connections_lock); - for (i = 0; i <= max_nodeid; i++) { - con = __nodeid2con(i, 0); - if (con) { - con->flags |= 0x0F; - if (con->sock) - con->sock->sk->sk_user_data = NULL; - } - } + foreach_conn(stop_conn); mutex_unlock(&connections_lock); work_stop(); @@ -1430,25 +1448,20 @@ void dlm_lowcomms_stop(void) mutex_lock(&connections_lock); clean_writequeues(); - for (i = 0; i <= max_nodeid; i++) { - con = __nodeid2con(i, 0); - if (con) { - close_connection(con, true); - if (con->othercon) - kmem_cache_free(con_cache, con->othercon); - kmem_cache_free(con_cache, con); - } - } - max_nodeid = 0; + foreach_conn(free_conn); + mutex_unlock(&connections_lock); kmem_cache_destroy(con_cache); - idr_init(&connections_idr); } int dlm_lowcomms_start(void) { int error = -EINVAL; struct connection *con; + int i; + + for (i = 0; i < CONN_HASH_SIZE; i++) + INIT_HLIST_HEAD(&connection_hash[i]); init_local(); if (!dlm_local_count) { -- GitLab From 43279e5376017c40b4be9af5bc79cbb4ef6f53d7 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Wed, 28 Jan 2009 14:37:54 -0600 Subject: [PATCH 3097/4982] dlm: clear defunct cancel state When a conversion completes successfully and finds that a cancel of the convert is still in progress (which is now a moot point), preemptively clear the state associated with outstanding cancel. That state could cause a subsequent conversion to be ignored. Also, improve the consistency and content of error and debug messages in this area. Signed-off-by: David Teigland --- fs/dlm/lock.c | 53 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index 01e7d39c5fb..8cb92046a58 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c @@ -835,7 +835,7 @@ static int add_to_waiters(struct dlm_lkb *lkb, int mstype) lkb->lkb_wait_count++; hold_lkb(lkb); - log_debug(ls, "add overlap %x cur %d new %d count %d flags %x", + log_debug(ls, "addwait %x cur %d overlap %d count %d f %x", lkb->lkb_id, lkb->lkb_wait_type, mstype, lkb->lkb_wait_count, lkb->lkb_flags); goto out; @@ -851,7 +851,7 @@ static int add_to_waiters(struct dlm_lkb *lkb, int mstype) list_add(&lkb->lkb_wait_reply, &ls->ls_waiters); out: if (error) - log_error(ls, "add_to_waiters %x error %d flags %x %d %d %s", + log_error(ls, "addwait error %x %d flags %x %d %d %s", lkb->lkb_id, error, lkb->lkb_flags, mstype, lkb->lkb_wait_type, lkb->lkb_resource->res_name); mutex_unlock(&ls->ls_waiters_mutex); @@ -863,23 +863,55 @@ static int add_to_waiters(struct dlm_lkb *lkb, int mstype) request reply on the requestqueue) between dlm_recover_waiters_pre() which set RESEND and dlm_recover_waiters_post() */ -static int _remove_from_waiters(struct dlm_lkb *lkb, int mstype) +static int _remove_from_waiters(struct dlm_lkb *lkb, int mstype, + struct dlm_message *ms) { struct dlm_ls *ls = lkb->lkb_resource->res_ls; int overlap_done = 0; if (is_overlap_unlock(lkb) && (mstype == DLM_MSG_UNLOCK_REPLY)) { + log_debug(ls, "remwait %x unlock_reply overlap", lkb->lkb_id); lkb->lkb_flags &= ~DLM_IFL_OVERLAP_UNLOCK; overlap_done = 1; goto out_del; } if (is_overlap_cancel(lkb) && (mstype == DLM_MSG_CANCEL_REPLY)) { + log_debug(ls, "remwait %x cancel_reply overlap", lkb->lkb_id); lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL; overlap_done = 1; goto out_del; } + /* Cancel state was preemptively cleared by a successful convert, + see next comment, nothing to do. */ + + if ((mstype == DLM_MSG_CANCEL_REPLY) && + (lkb->lkb_wait_type != DLM_MSG_CANCEL)) { + log_debug(ls, "remwait %x cancel_reply wait_type %d", + lkb->lkb_id, lkb->lkb_wait_type); + return -1; + } + + /* Remove for the convert reply, and premptively remove for the + cancel reply. A convert has been granted while there's still + an outstanding cancel on it (the cancel is moot and the result + in the cancel reply should be 0). We preempt the cancel reply + because the app gets the convert result and then can follow up + with another op, like convert. This subsequent op would see the + lingering state of the cancel and fail with -EBUSY. */ + + if ((mstype == DLM_MSG_CONVERT_REPLY) && + (lkb->lkb_wait_type == DLM_MSG_CONVERT) && + is_overlap_cancel(lkb) && ms && !ms->m_result) { + log_debug(ls, "remwait %x convert_reply zap overlap_cancel", + lkb->lkb_id); + lkb->lkb_wait_type = 0; + lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL; + lkb->lkb_wait_count--; + goto out_del; + } + /* N.B. type of reply may not always correspond to type of original msg due to lookup->request optimization, verify others? */ @@ -888,8 +920,8 @@ static int _remove_from_waiters(struct dlm_lkb *lkb, int mstype) goto out_del; } - log_error(ls, "remove_from_waiters lkid %x flags %x types %d %d", - lkb->lkb_id, lkb->lkb_flags, mstype, lkb->lkb_wait_type); + log_error(ls, "remwait error %x reply %d flags %x no wait_type", + lkb->lkb_id, mstype, lkb->lkb_flags); return -1; out_del: @@ -899,7 +931,7 @@ static int _remove_from_waiters(struct dlm_lkb *lkb, int mstype) this would happen */ if (overlap_done && lkb->lkb_wait_type) { - log_error(ls, "remove_from_waiters %x reply %d give up on %d", + log_error(ls, "remwait error %x reply %d wait_type %d overlap", lkb->lkb_id, mstype, lkb->lkb_wait_type); lkb->lkb_wait_count--; lkb->lkb_wait_type = 0; @@ -921,7 +953,7 @@ static int remove_from_waiters(struct dlm_lkb *lkb, int mstype) int error; mutex_lock(&ls->ls_waiters_mutex); - error = _remove_from_waiters(lkb, mstype); + error = _remove_from_waiters(lkb, mstype, NULL); mutex_unlock(&ls->ls_waiters_mutex); return error; } @@ -936,7 +968,7 @@ static int remove_from_waiters_ms(struct dlm_lkb *lkb, struct dlm_message *ms) if (ms != &ls->ls_stub_ms) mutex_lock(&ls->ls_waiters_mutex); - error = _remove_from_waiters(lkb, ms->m_type); + error = _remove_from_waiters(lkb, ms->m_type, ms); if (ms != &ls->ls_stub_ms) mutex_unlock(&ls->ls_waiters_mutex); return error; @@ -2083,6 +2115,11 @@ static int validate_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb, lkb->lkb_timeout_cs = args->timeout; rv = 0; out: + if (rv) + log_debug(ls, "validate_lock_args %d %x %x %x %d %d %s", + rv, lkb->lkb_id, lkb->lkb_flags, args->flags, + lkb->lkb_status, lkb->lkb_wait_type, + lkb->lkb_resource->res_name); return rv; } -- GitLab From a536e38125fe5da8ed49690f30c30a8f651cf1f5 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Fri, 27 Feb 2009 15:23:28 -0600 Subject: [PATCH 3098/4982] dlm: ignore cancel on granted lock Return immediately from dlm_unlock(CANCEL) if the lock is granted and not being converted; there's nothing to cancel. Signed-off-by: David Teigland --- fs/dlm/lock.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index 8cb92046a58..205ec95b347 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c @@ -2186,6 +2186,13 @@ static int validate_unlock_args(struct dlm_lkb *lkb, struct dlm_args *args) goto out; } + /* there's nothing to cancel */ + if (lkb->lkb_status == DLM_LKSTS_GRANTED && + !lkb->lkb_wait_type) { + rv = -EBUSY; + goto out; + } + switch (lkb->lkb_wait_type) { case DLM_MSG_LOOKUP: case DLM_MSG_REQUEST: -- GitLab From 1fecb1c4b62881e3689ba2dcf93072ae301b597c Mon Sep 17 00:00:00 2001 From: David Teigland Date: Wed, 4 Mar 2009 11:17:23 -0600 Subject: [PATCH 3099/4982] dlm: fix length calculation in compat code Using offsetof() to calculate name length does not work because it does not produce consistent results with with structure packing. This caused memcpy to corrupt memory by copying 4 extra bytes off the end of the buffer on 64 bit kernels with 32 bit userspace (the only case where this 32/64 compat code is used). The fix is to calculate name length directly from the start instead of trying to derive it later using count and offsetof. Signed-off-by: David Teigland --- fs/dlm/user.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/fs/dlm/user.c b/fs/dlm/user.c index 065149e84f4..ebce994ab0b 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved. + * Copyright (C) 2006-2009 Red Hat, Inc. All rights reserved. * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions @@ -84,7 +84,7 @@ struct dlm_lock_result32 { static void compat_input(struct dlm_write_request *kb, struct dlm_write_request32 *kb32, - size_t count) + int namelen) { kb->version[0] = kb32->version[0]; kb->version[1] = kb32->version[1]; @@ -96,8 +96,7 @@ static void compat_input(struct dlm_write_request *kb, kb->cmd == DLM_USER_REMOVE_LOCKSPACE) { kb->i.lspace.flags = kb32->i.lspace.flags; kb->i.lspace.minor = kb32->i.lspace.minor; - memcpy(kb->i.lspace.name, kb32->i.lspace.name, count - - offsetof(struct dlm_write_request32, i.lspace.name)); + memcpy(kb->i.lspace.name, kb32->i.lspace.name, namelen); } else if (kb->cmd == DLM_USER_PURGE) { kb->i.purge.nodeid = kb32->i.purge.nodeid; kb->i.purge.pid = kb32->i.purge.pid; @@ -115,8 +114,7 @@ static void compat_input(struct dlm_write_request *kb, kb->i.lock.bastaddr = (void *)(long)kb32->i.lock.bastaddr; kb->i.lock.lksb = (void *)(long)kb32->i.lock.lksb; memcpy(kb->i.lock.lvb, kb32->i.lock.lvb, DLM_USER_LVB_LEN); - memcpy(kb->i.lock.name, kb32->i.lock.name, count - - offsetof(struct dlm_write_request32, i.lock.name)); + memcpy(kb->i.lock.name, kb32->i.lock.name, namelen); } } @@ -539,9 +537,16 @@ static ssize_t device_write(struct file *file, const char __user *buf, #ifdef CONFIG_COMPAT if (!kbuf->is64bit) { struct dlm_write_request32 *k32buf; + int namelen = 0; + + if (count > sizeof(struct dlm_write_request32)) + namelen = count - sizeof(struct dlm_write_request32); + k32buf = (struct dlm_write_request32 *)kbuf; - kbuf = kmalloc(count + 1 + (sizeof(struct dlm_write_request) - - sizeof(struct dlm_write_request32)), GFP_KERNEL); + + /* add 1 after namelen so that the name string is terminated */ + kbuf = kzalloc(sizeof(struct dlm_write_request) + namelen + 1, + GFP_KERNEL); if (!kbuf) { kfree(k32buf); return -ENOMEM; @@ -549,7 +554,8 @@ static ssize_t device_write(struct file *file, const char __user *buf, if (proc) set_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags); - compat_input(kbuf, k32buf, count + 1); + + compat_input(kbuf, k32buf, namelen); kfree(k32buf); } #endif -- GitLab From fba91afbec2c004e2c8733ae9e0ca6998e962c64 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 11 Mar 2009 14:06:41 -0400 Subject: [PATCH 3100/4982] SUNRPC: Fix an Oops due to socket not set up yet... We can Oops in both xs_udp_send_request() and xs_tcp_send_request() if the call to xs_sendpages() returns an error due to the socket not yet being set up. Deal with that situation by returning a new error: ENOTSOCK, so that we know to avoid dereferencing transport->sock. Signed-off-by: Trond Myklebust --- net/sunrpc/xprtsock.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 5cbb404c4cd..a71fefd6191 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -467,7 +467,7 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, int err, sent = 0; if (unlikely(!sock)) - return -ENOTCONN; + return -ENOTSOCK; clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags); if (base != 0) { @@ -594,6 +594,10 @@ static int xs_udp_send_request(struct rpc_task *task) } switch (status) { + case -ENOTSOCK: + status = -ENOTCONN; + /* Should we call xs_close() here? */ + break; case -EAGAIN: xs_nospace(task); break; @@ -693,6 +697,10 @@ static int xs_tcp_send_request(struct rpc_task *task) } switch (status) { + case -ENOTSOCK: + status = -ENOTCONN; + /* Should we call xs_close() here? */ + break; case -EAGAIN: xs_nospace(task); break; -- GitLab From 01d37c428ae080563c0a3bb8bdfa88c65a6891d3 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 11 Mar 2009 14:09:39 -0400 Subject: [PATCH 3101/4982] SUNRPC: xprt_connect() don't abort the task if the transport isn't bound If the transport isn't bound, then we should just return ENOTCONN, letting call_connect_status() and/or call_status() deal with retrying. Currently, we appear to abort all pending tasks with an EIO error. Signed-off-by: Trond Myklebust --- net/sunrpc/xprt.c | 2 +- net/sunrpc/xprtsock.c | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 29e401bb612..62098d101a1 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -663,7 +663,7 @@ void xprt_connect(struct rpc_task *task) xprt, (xprt_connected(xprt) ? "is" : "is not")); if (!xprt_bound(xprt)) { - task->tk_status = -EIO; + task->tk_status = -EAGAIN; return; } if (!xprt_lock_write(xprt, task)) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index a71fefd6191..29c71e645b2 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -577,6 +577,8 @@ static int xs_udp_send_request(struct rpc_task *task) req->rq_svec->iov_base, req->rq_svec->iov_len); + if (!xprt_bound(xprt)) + return -ENOTCONN; status = xs_sendpages(transport->sock, xs_addr(xprt), xprt->addrlen, xdr, @@ -1531,7 +1533,7 @@ static void xs_udp_connect_worker4(struct work_struct *work) struct socket *sock = transport->sock; int err, status = -EIO; - if (xprt->shutdown || !xprt_bound(xprt)) + if (xprt->shutdown) goto out; /* Start by resetting any existing state */ @@ -1572,7 +1574,7 @@ static void xs_udp_connect_worker6(struct work_struct *work) struct socket *sock = transport->sock; int err, status = -EIO; - if (xprt->shutdown || !xprt_bound(xprt)) + if (xprt->shutdown) goto out; /* Start by resetting any existing state */ @@ -1656,6 +1658,9 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) write_unlock_bh(&sk->sk_callback_lock); } + if (!xprt_bound(xprt)) + return -ENOTCONN; + /* Tell the socket layer to start connecting... */ xprt->stat.connect_count++; xprt->stat.connect_start = jiffies; @@ -1676,7 +1681,7 @@ static void xs_tcp_connect_worker4(struct work_struct *work) struct socket *sock = transport->sock; int err, status = -EIO; - if (xprt->shutdown || !xprt_bound(xprt)) + if (xprt->shutdown) goto out; if (!sock) { @@ -1736,7 +1741,7 @@ static void xs_tcp_connect_worker6(struct work_struct *work) struct socket *sock = transport->sock; int err, status = -EIO; - if (xprt->shutdown || !xprt_bound(xprt)) + if (xprt->shutdown) goto out; if (!sock) { -- GitLab From 603b6fd5b8d313a109d3739d8706ee51962ff402 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 11 Mar 2009 18:28:24 +0000 Subject: [PATCH 3102/4982] [ARM] Revert futher extraneous changes from the S3C header move Can't see any immediate need for these; build tested. Signed-off-by: Mark Brown --- arch/arm/mach-s3c2410/include/mach/io.h | 2 +- arch/arm/plat-s3c24xx/clock-dclk.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/mach-s3c2410/include/mach/io.h b/arch/arm/mach-s3c2410/include/mach/io.h index c477771c092..9813dbf2ae4 100644 --- a/arch/arm/mach-s3c2410/include/mach/io.h +++ b/arch/arm/mach-s3c2410/include/mach/io.h @@ -9,7 +9,7 @@ #ifndef __ASM_ARM_ARCH_IO_H #define __ASM_ARM_ARCH_IO_H -#include +#include #define IO_SPACE_LIMIT 0xffffffff diff --git a/arch/arm/plat-s3c24xx/clock-dclk.c b/arch/arm/plat-s3c24xx/clock-dclk.c index 35219dcf9f0..5b75a797b5a 100644 --- a/arch/arm/plat-s3c24xx/clock-dclk.c +++ b/arch/arm/plat-s3c24xx/clock-dclk.c @@ -18,7 +18,6 @@ #include #include -#include #include #include -- GitLab From 793730bfb6711d6d14629e63845c25a3c14d205e Mon Sep 17 00:00:00 2001 From: Yevgeny Petrilin Date: Wed, 11 Mar 2009 15:47:18 -0700 Subject: [PATCH 3103/4982] mlx4_core: Don't perform SET_PORT command for Ethernet ports The same operation is performed when the Ethernet driver initializes the port. Signed-off-by: Yevgeny Petrilin Signed-off-by: Roland Dreier --- drivers/net/mlx4/port.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/net/mlx4/port.c b/drivers/net/mlx4/port.c index 0a057e5dc63..7cce3342ef8 100644 --- a/drivers/net/mlx4/port.c +++ b/drivers/net/mlx4/port.c @@ -298,20 +298,17 @@ int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port) { struct mlx4_cmd_mailbox *mailbox; int err; - u8 is_eth = dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH; mailbox = mlx4_alloc_cmd_mailbox(dev); if (IS_ERR(mailbox)) return PTR_ERR(mailbox); memset(mailbox->buf, 0, 256); - if (is_eth) { - ((u8 *) mailbox->buf)[3] = 6; - ((__be16 *) mailbox->buf)[4] = cpu_to_be16(1 << 15); - ((__be16 *) mailbox->buf)[6] = cpu_to_be16(1 << 15); - } else - ((__be32 *) mailbox->buf)[1] = dev->caps.ib_port_def_cap[port]; - err = mlx4_cmd(dev, mailbox->dma, port, is_eth, MLX4_CMD_SET_PORT, + if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH) + return 0; + + ((__be32 *) mailbox->buf)[1] = dev->caps.ib_port_def_cap[port]; + err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B); mlx4_free_cmd_mailbox(dev, mailbox); -- GitLab From b298f223559e0205244f553ceef8c7df3674da74 Mon Sep 17 00:00:00 2001 From: Steve French Date: Sat, 21 Feb 2009 21:17:43 +0000 Subject: [PATCH 3104/4982] [CIFS] Send SMB flush in cifs_fsync In contrast to the now-obsolete smbfs, cifs does not send SMB_COM_FLUSH in response to an explicit fsync(2) to guarantee that all volatile data is written to stable storage on the server side, provided the server honors the request (which, to my knowledge, is true for Windows and Samba with 'strict sync' enabled). This patch modifies the cifs_fsync implementation to restore the fsync-behavior of smbfs by triggering SMB_COM_FLUSH after sending outstanding data on the client side to the server. Signed-off-by: Horst Reiterer Acked-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/CHANGES | 4 +++- fs/cifs/cifs_debug.c | 2 ++ fs/cifs/cifsglob.h | 1 + fs/cifs/cifspdu.h | 7 +++++++ fs/cifs/cifsproto.h | 3 +++ fs/cifs/cifssmb.c | 21 +++++++++++++++++++++ fs/cifs/file.c | 7 +++++++ 7 files changed, 44 insertions(+), 1 deletion(-) diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 851388fafc7..d43e0fe3339 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -6,7 +6,9 @@ the server to treat subsequent connections, especially those that are authenticated as guest, as reconnections, invalidating the earlier user's smb session. This fix allows cifs to mount multiple times to the same server with different userids without risking invalidating earlier -established security contexts. +established security contexts. fsync now sends SMB Flush operation +to better ensure that we wait for server to write all of the data to +server disk (not just write it over the network). Version 1.56 ------------ diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 490e34bbf27..877e4d9a115 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c @@ -340,6 +340,8 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v) seq_printf(m, "\nWrites: %d Bytes: %lld", atomic_read(&tcon->num_writes), (long long)(tcon->bytes_written)); + seq_printf(m, "\nFlushes: %d", + atomic_read(&tcon->num_flushes)); seq_printf(m, "\nLocks: %d HardLinks: %d " "Symlinks: %d", atomic_read(&tcon->num_locks), diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index e004f6db5fc..44ff94d37e1 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -254,6 +254,7 @@ struct cifsTconInfo { atomic_t num_smbs_sent; atomic_t num_writes; atomic_t num_reads; + atomic_t num_flushes; atomic_t num_oplock_brks; atomic_t num_opens; atomic_t num_closes; diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index b4e2e9f0ee3..eda6e511fd3 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -43,6 +43,7 @@ #define SMB_COM_CREATE_DIRECTORY 0x00 /* trivial response */ #define SMB_COM_DELETE_DIRECTORY 0x01 /* trivial response */ #define SMB_COM_CLOSE 0x04 /* triv req/rsp, timestamp ignored */ +#define SMB_COM_FLUSH 0x05 /* triv req/rsp */ #define SMB_COM_DELETE 0x06 /* trivial response */ #define SMB_COM_RENAME 0x07 /* trivial response */ #define SMB_COM_QUERY_INFORMATION 0x08 /* aka getattr */ @@ -790,6 +791,12 @@ typedef struct smb_com_close_rsp { __u16 ByteCount; /* bct = 0 */ } __attribute__((packed)) CLOSE_RSP; +typedef struct smb_com_flush_req { + struct smb_hdr hdr; /* wct = 1 */ + __u16 FileID; + __u16 ByteCount; /* 0 */ +} __attribute__((packed)) FLUSH_REQ; + typedef struct smb_com_findclose_req { struct smb_hdr hdr; /* wct = 1 */ __u16 FileID; diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 083dfc57c7a..596fc868937 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -281,6 +281,9 @@ extern int CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, const int smb_file_id); +extern int CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, + const int smb_file_id); + extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, unsigned int count, const __u64 lseek, unsigned int *nbytes, char **buf, diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 939e2f76b95..4c344fe7a15 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1933,6 +1933,27 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) return rc; } +int +CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id) +{ + int rc = 0; + FLUSH_REQ *pSMB = NULL; + cFYI(1, ("In CIFSSMBFlush")); + + rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB); + if (rc) + return rc; + + pSMB->FileID = (__u16) smb_file_id; + pSMB->ByteCount = 0; + rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); + cifs_stats_inc(&tcon->num_flushes); + if (rc) + cERROR(1, ("Send error in Flush = %d", rc)); + + return rc; +} + int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, const char *fromName, const char *toName, diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 12bb656fbe7..83b4741b6ad 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -1523,6 +1523,9 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) { int xid; int rc = 0; + struct cifsTconInfo *tcon; + struct cifsFileInfo *smbfile = + (struct cifsFileInfo *)file->private_data; struct inode *inode = file->f_path.dentry->d_inode; xid = GetXid(); @@ -1534,7 +1537,11 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) if (rc == 0) { rc = CIFS_I(inode)->write_behind_rc; CIFS_I(inode)->write_behind_rc = 0; + tcon = CIFS_SB(inode->i_sb)->tcon; + if (!rc && tcon && smbfile) + rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); } + FreeXid(xid); return rc; } -- GitLab From 10e70afa75c90702b2326abaaa757d6b7835636f Mon Sep 17 00:00:00 2001 From: Steve French Date: Sun, 22 Feb 2009 01:33:07 +0000 Subject: [PATCH 3105/4982] [CIFS] DFS no longer experimental Also updates some DFS flag definitions Signed-off-by: Steve French --- fs/cifs/Kconfig | 21 ++++++++++++--------- fs/cifs/cifspdu.h | 20 ++++++++++---------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 341a98965bd..6994a0f54f0 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig @@ -118,6 +118,18 @@ config CIFS_DEBUG2 option can be turned off unless you are debugging cifs problems. If unsure, say N. +config CIFS_DFS_UPCALL + bool "DFS feature support" + depends on CIFS && KEYS + help + Distributed File System (DFS) support is used to access shares + transparently in an enterprise name space, even if the share + moves to a different server. This feature also enables + an upcall mechanism for CIFS which contacts userspace helper + utilities to provide server name resolution (host names to + IP addresses) which is needed for implicit mounts of DFS junction + points. If unsure, say N. + config CIFS_EXPERIMENTAL bool "CIFS Experimental Features (EXPERIMENTAL)" depends on CIFS && EXPERIMENTAL @@ -131,12 +143,3 @@ config CIFS_EXPERIMENTAL (which is disabled by default). See the file fs/cifs/README for more details. If unsure, say N. -config CIFS_DFS_UPCALL - bool "DFS feature support (EXPERIMENTAL)" - depends on CIFS_EXPERIMENTAL - depends on KEYS - help - Enables an upcall mechanism for CIFS which contacts userspace - helper utilities to provide server name resolution (host names to - IP addresses) which is needed for implicit mounts of DFS junction - points. If unsure, say N. diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index eda6e511fd3..56127638b91 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -1931,19 +1931,19 @@ typedef struct smb_com_transaction2_get_dfs_refer_req { #define DFS_TYPE_ROOT 0x0001 /* Referral Entry Flags */ -#define DFS_NAME_LIST_REF 0x0200 +#define DFS_NAME_LIST_REF 0x0200 /* set for domain or DC referral responses */ +#define DFS_TARGET_SET_BOUNDARY 0x0400 /* only valid with version 4 dfs req */ -typedef struct dfs_referral_level_3 { - __le16 VersionNumber; +typedef struct dfs_referral_level_3 { /* version 4 is same, + one flag bit */ + __le16 VersionNumber; /* must be 3 or 4 */ __le16 Size; __le16 ServerType; /* 0x0001 = root targets; 0x0000 = link targets */ - __le16 ReferralEntryFlags; /* 0x0200 bit set only for domain - or DC referral responce */ + __le16 ReferralEntryFlags; __le32 TimeToLive; __le16 DfsPathOffset; __le16 DfsAlternatePathOffset; __le16 NetworkAddressOffset; /* offset of the link target */ - __le16 ServiceSiteGuid; + __u8 ServiceSiteGuid[16]; /* MBZ, ignored */ } __attribute__((packed)) REFERRAL3; typedef struct smb_com_transaction_get_dfs_refer_rsp { @@ -1953,15 +1953,15 @@ typedef struct smb_com_transaction_get_dfs_refer_rsp { __u8 Pad; __le16 PathConsumed; __le16 NumberOfReferrals; - __le16 DFSFlags; - __u16 Pad2; + __le32 DFSFlags; REFERRAL3 referrals[1]; /* array of level 3 dfs_referral structures */ /* followed by the strings pointed to by the referral structures */ } __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_RSP; /* DFS Flags */ -#define DFSREF_REFERRAL_SERVER 0x0001 -#define DFSREF_STORAGE_SERVER 0x0002 +#define DFSREF_REFERRAL_SERVER 0x00000001 /* all targets are DFS roots */ +#define DFSREF_STORAGE_SERVER 0x00000002 /* no further ref requests needed */ +#define DFSREF_TARGET_FAILBACK 0x00000004 /* only for DFS referral version 4 */ /* IOCTL information */ /* -- GitLab From be652445fdccb8e5d4391928c3b45324ea37f9e1 Mon Sep 17 00:00:00 2001 From: Steve French Date: Mon, 23 Feb 2009 15:21:59 +0000 Subject: [PATCH 3106/4982] [CIFS] Add new nostrictsync cifs mount option to avoid slow SMB flush If this mount option is set, when an application does an fsync call then the cifs client does not send an SMB Flush to the server (to force the server to write all dirty data for this file immediately to disk), although cifs still sends all dirty (cached) file data to the server and waits for the server to respond to the write write. Since SMB Flush can be very slow, and some servers may be reliable enough (to risk delaying slightly flushing the data to disk on the server), turning on this option may be useful to improve performance for applications that fsync too much, at a small risk of server crash. If this mount option is not set, by default cifs will send an SMB flush request (and wait for a response) on every fsync call. Signed-off-by: Steve French --- fs/cifs/CHANGES | 4 +++- fs/cifs/README | 22 ++++++++++++++++++---- fs/cifs/cifs_fs_sb.h | 1 + fs/cifs/connect.c | 7 +++++++ fs/cifs/file.c | 3 ++- 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index d43e0fe3339..b33c8412e2c 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -8,7 +8,9 @@ user's smb session. This fix allows cifs to mount multiple times to the same server with different userids without risking invalidating earlier established security contexts. fsync now sends SMB Flush operation to better ensure that we wait for server to write all of the data to -server disk (not just write it over the network). +server disk (not just write it over the network). Add new mount +parameter to allow user to disable sending the (slow) SMB flush on +fsync if desired (fsync still flushes all cached write data to the server). Version 1.56 ------------ diff --git a/fs/cifs/README b/fs/cifs/README index da4515e3be2..07434181623 100644 --- a/fs/cifs/README +++ b/fs/cifs/README @@ -472,6 +472,19 @@ A partial list of the supported mount options follows: even if the cifs server would support posix advisory locks. "forcemand" is accepted as a shorter form of this mount option. + nostrictsync If this mount option is set, when an application does an + fsync call then the cifs client does not send an SMB Flush + to the server (to force the server to write all dirty data + for this file immediately to disk), although cifs still sends + all dirty (cached) file data to the server and waits for the + server to respond to the write. Since SMB Flush can be + very slow, and some servers may be reliable enough (to risk + delaying slightly flushing the data to disk on the server), + turning on this option may be useful to improve performance for + applications that fsync too much, at a small risk of server + crash. If this mount option is not set, by default cifs will + send an SMB flush request (and wait for a response) on every + fsync call. nodfs Disable DFS (global name space support) even if the server claims to support it. This can help work around a problem with parsing of DFS paths with Samba server @@ -692,13 +705,14 @@ require this helper. Note that NTLMv2 security (which does not require the cifs.upcall helper program), instead of using Kerberos, is sufficient for some use cases. -Enabling DFS support (used to access shares transparently in an MS-DFS -global name space) requires that CONFIG_CIFS_EXPERIMENTAL be enabled. In -addition, DFS support for target shares which are specified as UNC +DFS support allows transparent redirection to shares in an MS-DFS name space. +In addition, DFS support for target shares which are specified as UNC names which begin with host names (rather than IP addresses) requires a user space helper (such as cifs.upcall) to be present in order to translate host names to ip address, and the user space helper must also -be configured in the file /etc/request-key.conf +be configured in the file /etc/request-key.conf. Samba, Windows servers and +many NAS appliances support DFS as a way of constructing a global name +space to ease network configuration and improve reliability. To use cifs Kerberos and DFS support, the Linux keyutils package should be installed and something like the following lines should be added to the diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index c4c306f7b06..e9f177bb065 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h @@ -32,6 +32,7 @@ #define CIFS_MOUNT_OVERR_GID 0x800 /* override gid returned from server */ #define CIFS_MOUNT_DYNPERM 0x1000 /* allow in-memory only mode setting */ #define CIFS_MOUNT_NOPOSIXBRL 0x2000 /* mandatory not posix byte range lock */ +#define CIFS_MOUNT_NO_SSYNC 0x4000 /* don't do slow SMBflush on every sync*/ struct cifs_sb_info { struct cifsTconInfo *tcon; /* primary mount */ diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index da0f4ffa061..18e84a4e050 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -95,6 +95,7 @@ struct smb_vol { bool local_lease:1; /* check leases only on local system, not remote */ bool noblocksnd:1; bool noautotune:1; + bool nostrictsync:1; /* do not force expensive SMBflush on every sync */ unsigned int rsize; unsigned int wsize; unsigned int sockopt; @@ -1274,6 +1275,10 @@ cifs_parse_mount_options(char *options, const char *devname, vol->intr = 0; } else if (strnicmp(data, "intr", 4) == 0) { vol->intr = 1; + } else if (strnicmp(data, "nostrictsync", 12) == 0) { + vol->nostrictsync = 1; + } else if (strnicmp(data, "strictsync", 10) == 0) { + vol->nostrictsync = 0; } else if (strnicmp(data, "serverino", 7) == 0) { vol->server_ino = 1; } else if (strnicmp(data, "noserverino", 9) == 0) { @@ -2160,6 +2165,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info, cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; if (pvolume_info->nobrl) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; + if (pvolume_info->nostrictsync) + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_SSYNC; if (pvolume_info->mand_lock) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL; if (pvolume_info->cifs_acl) diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 83b4741b6ad..6411f5f65d7 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -1538,7 +1538,8 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) rc = CIFS_I(inode)->write_behind_rc; CIFS_I(inode)->write_behind_rc = 0; tcon = CIFS_SB(inode->i_sb)->tcon; - if (!rc && tcon && smbfile) + if (!rc && tcon && smbfile && + !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_SSYNC)) rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); } -- GitLab From 7fc8f4e95bf9564045985bb206af8e28a5e4e28f Mon Sep 17 00:00:00 2001 From: Steve French Date: Mon, 23 Feb 2009 20:43:11 +0000 Subject: [PATCH 3107/4982] [CIFS] reopen file via newer posix open protocol operation if available If the network connection crashes, and we have to reopen files, preferentially use the newer cifs posix open protocol operation if the server supports it. Signed-off-by: Steve French --- fs/cifs/cifsproto.h | 3 +++ fs/cifs/dir.c | 6 +++-- fs/cifs/file.c | 57 ++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 58 insertions(+), 8 deletions(-) diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 596fc868937..a069e7bfd2d 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -92,6 +92,9 @@ extern u64 cifs_UnixTimeToNT(struct timespec); extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time); extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time); +extern int cifs_posix_open(char *full_path, struct inode **pinode, + struct super_block *sb, int mode, int oflags, + int *poplock, __u16 *pnetfid, int xid); extern void posix_fill_in_inode(struct inode *tmp_inode, FILE_UNIX_BASIC_INFO *pData, int isNewInode); extern struct inode *cifs_new_inode(struct super_block *sb, __u64 *inum); diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 89fb7283265..f9b6f68be97 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -129,7 +129,7 @@ cifs_bp_rename_retry: return full_path; } -static int cifs_posix_open(char *full_path, struct inode **pinode, +int cifs_posix_open(char *full_path, struct inode **pinode, struct super_block *sb, int mode, int oflags, int *poplock, __u16 *pnetfid, int xid) { @@ -187,7 +187,9 @@ static int cifs_posix_open(char *full_path, struct inode **pinode, if (!pinode) goto posix_open_ret; /* caller does not need info */ - *pinode = cifs_new_inode(sb, &presp_data->UniqueId); + if (*pinode == NULL) + *pinode = cifs_new_inode(sb, &presp_data->UniqueId); + /* else an inode was passed in. Update its info, don't create one */ /* We do not need to close the file if new_inode fails since the caller will retry qpathinfo as long as inode is null */ diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 6411f5f65d7..6603cb4024f 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -78,8 +78,36 @@ static inline int cifs_convert_flags(unsigned int flags) return (READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA | FILE_READ_DATA); +} +static inline fmode_t cifs_posix_convert_flags(unsigned int flags) +{ + fmode_t posix_flags = 0; + if ((flags & O_ACCMODE) == O_RDONLY) + posix_flags = FMODE_READ; + else if ((flags & O_ACCMODE) == O_WRONLY) + posix_flags = FMODE_WRITE; + else if ((flags & O_ACCMODE) == O_RDWR) { + /* GENERIC_ALL is too much permission to request + can cause unnecessary access denied on create */ + /* return GENERIC_ALL; */ + posix_flags = FMODE_READ | FMODE_WRITE; + } + /* can not map O_CREAT or O_EXCL or O_TRUNC flags when + reopening a file. They had their effect on the original open */ + if (flags & O_APPEND) + posix_flags |= (fmode_t)O_APPEND; + if (flags & O_SYNC) + posix_flags |= (fmode_t)O_SYNC; + if (flags & O_DIRECTORY) + posix_flags |= (fmode_t)O_DIRECTORY; + if (flags & O_NOFOLLOW) + posix_flags |= (fmode_t)O_NOFOLLOW; + if (flags & O_DIRECT) + posix_flags |= (fmode_t)O_DIRECT; + + return posix_flags; } static inline int cifs_get_disposition(unsigned int flags) @@ -349,7 +377,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush) int rc = -EACCES; int xid, oplock; struct cifs_sb_info *cifs_sb; - struct cifsTconInfo *pTcon; + struct cifsTconInfo *tcon; struct cifsFileInfo *pCifsFile; struct cifsInodeInfo *pCifsInode; struct inode *inode; @@ -387,7 +415,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush) } cifs_sb = CIFS_SB(inode->i_sb); - pTcon = cifs_sb->tcon; + tcon = cifs_sb->tcon; /* can not grab rename sem here because various ops, including those that already have the rename sem can end up causing writepage @@ -404,20 +432,37 @@ reopen_error_exit: cFYI(1, ("inode = 0x%p file flags 0x%x for %s", inode, file->f_flags, full_path)); - desiredAccess = cifs_convert_flags(file->f_flags); if (oplockEnabled) oplock = REQ_OPLOCK; else oplock = 0; + if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && + (CIFS_UNIX_POSIX_PATH_OPS_CAP & + le64_to_cpu(tcon->fsUnixInfo.Capability))) { + int oflags = (int) cifs_posix_convert_flags(file->f_flags); + /* can not refresh inode info since size could be stale */ + rc = cifs_posix_open(full_path, NULL, inode->i_sb, + cifs_sb->mnt_file_mode /* ignored */, + oflags, &oplock, &netfid, xid); + if (rc == 0) { + cFYI(1, ("posix reopen succeeded")); + goto reopen_success; + } + /* fallthrough to retry open the old way on errors, especially + in the reconnect path it is important to retry hard */ + } + + desiredAccess = cifs_convert_flags(file->f_flags); + /* Can not refresh inode by passing in file_info buf to be returned by SMBOpen and then calling get_inode_info with returned buf since file might have write behind data that needs to be flushed and server version of file size can be stale. If we knew for sure that inode was not dirty locally we could do this */ - rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, + rc = CIFSSMBOpen(xid, tcon, full_path, disposition, desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, NULL, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); @@ -426,6 +471,7 @@ reopen_error_exit: cFYI(1, ("cifs_open returned 0x%x", rc)); cFYI(1, ("oplock: %d", oplock)); } else { +reopen_success: pCifsFile->netfid = netfid; pCifsFile->invalidHandle = false; up(&pCifsFile->fh_sem); @@ -439,7 +485,7 @@ reopen_error_exit: go to server to get inode info */ pCifsInode->clientCanCacheAll = false; pCifsInode->clientCanCacheRead = false; - if (pTcon->unix_ext) + if (tcon->unix_ext) rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb, xid); else @@ -467,7 +513,6 @@ reopen_error_exit: cifs_relock_file(pCifsFile); } } - kfree(full_path); FreeXid(xid); return rc; -- GitLab From 4717bed6806dab0270e5bfbc45e9f999e63ededd Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 24 Feb 2009 14:44:19 +0000 Subject: [PATCH 3108/4982] [CIFS] fix build error Signed-off-by: Steve French --- fs/cifs/cifs_fs_sb.h | 2 +- fs/cifs/connect.c | 2 +- fs/cifs/file.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index e9f177bb065..4797787c6a4 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h @@ -32,7 +32,7 @@ #define CIFS_MOUNT_OVERR_GID 0x800 /* override gid returned from server */ #define CIFS_MOUNT_DYNPERM 0x1000 /* allow in-memory only mode setting */ #define CIFS_MOUNT_NOPOSIXBRL 0x2000 /* mandatory not posix byte range lock */ -#define CIFS_MOUNT_NO_SSYNC 0x4000 /* don't do slow SMBflush on every sync*/ +#define CIFS_MOUNT_NOSSYNC 0x4000 /* don't do slow SMBflush on every sync*/ struct cifs_sb_info { struct cifsTconInfo *tcon; /* primary mount */ diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 18e84a4e050..cd4ccc8ce47 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2166,7 +2166,7 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info, if (pvolume_info->nobrl) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; if (pvolume_info->nostrictsync) - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_SSYNC; + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC; if (pvolume_info->mand_lock) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL; if (pvolume_info->cifs_acl) diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 6603cb4024f..e4ecb1cb0b1 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -1584,7 +1584,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) CIFS_I(inode)->write_behind_rc = 0; tcon = CIFS_SB(inode->i_sb)->tcon; if (!rc && tcon && smbfile && - !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_SSYNC)) + !(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); } -- GitLab From 1adcb71092f6461c4002ccf29d316f6da3e1f39b Mon Sep 17 00:00:00 2001 From: Steve French Date: Wed, 25 Feb 2009 14:19:56 +0000 Subject: [PATCH 3109/4982] [CIFS] add extra null attr check Although attr == NULL can not happen, this makes cifs_set_file_info safer in the future since it may not be obvious that the caller can not set attr to NULL. Signed-off-by: Steve French --- fs/cifs/inode.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 4690a360c85..a8797cc6080 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -763,6 +763,9 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, struct cifsTconInfo *pTcon = cifs_sb->tcon; FILE_BASIC_INFO info_buf; + if (attrs == NULL) + return -EINVAL; + if (attrs->ia_valid & ATTR_ATIME) { set_time = true; info_buf.LastAccessTime = -- GitLab From 0382457744969b0a3aa39ba997944903c5972cbc Mon Sep 17 00:00:00 2001 From: Steve French Date: Wed, 25 Feb 2009 16:24:04 +0000 Subject: [PATCH 3110/4982] [CIFS] Add definitions for remoteably fsctl calls There are about 60 fsctl calls which Windows claims would be able to be sent remotely and handled by the server. This adds the #defines for them. A few of them look immediately useful, but need to also add the structure definitions for them so they can be sent as SMBs. Signed-off-by: Steve French --- fs/cifs/cifspdu.h | 49 ++++----------------------- fs/cifs/smbfsctl.h | 84 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 43 deletions(-) create mode 100644 fs/cifs/smbfsctl.h diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 56127638b91..b370489c8da 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -1,7 +1,7 @@ /* * fs/cifs/cifspdu.h * - * Copyright (c) International Business Machines Corp., 2002,2008 + * Copyright (c) International Business Machines Corp., 2002,2009 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -23,6 +23,7 @@ #define _CIFSPDU_H #include +#include "smbfsctl.h" #ifdef CONFIG_CIFS_WEAK_PW_HASH #define LANMAN_PROT 0 @@ -34,11 +35,10 @@ #define POSIX_PROT (CIFS_PROT+1) #define BAD_PROT 0xFFFF -/* SMB command codes */ -/* - * Some commands have minimal (wct=0,bcc=0), or uninteresting, responses +/* SMB command codes: + * Note some commands have minimal (wct=0,bcc=0), or uninteresting, responses * (ie which include no useful data other than the SMB error code itself). - * Knowing this helps avoid response buffer allocations and copy in some cases + * This can allow us to avoid response buffer allocations and copy in some cases */ #define SMB_COM_CREATE_DIRECTORY 0x00 /* trivial response */ #define SMB_COM_DELETE_DIRECTORY 0x01 /* trivial response */ @@ -1963,39 +1963,6 @@ typedef struct smb_com_transaction_get_dfs_refer_rsp { #define DFSREF_STORAGE_SERVER 0x00000002 /* no further ref requests needed */ #define DFSREF_TARGET_FAILBACK 0x00000004 /* only for DFS referral version 4 */ -/* IOCTL information */ -/* - * List of ioctl function codes that look to be of interest to remote clients - * like this one. Need to do some experimentation to make sure they all work - * remotely. Some of the following, such as the encryption/compression ones - * would be invoked from tools via a specialized hook into the VFS rather - * than via the standard vfs entry points - */ -#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000 -#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004 -#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008 -#define FSCTL_LOCK_VOLUME 0x00090018 -#define FSCTL_UNLOCK_VOLUME 0x0009001C -#define FSCTL_GET_COMPRESSION 0x0009003C -#define FSCTL_SET_COMPRESSION 0x0009C040 -#define FSCTL_REQUEST_FILTER_OPLOCK 0x0009008C -#define FSCTL_FILESYS_GET_STATISTICS 0x00090090 -#define FSCTL_SET_REPARSE_POINT 0x000900A4 -#define FSCTL_GET_REPARSE_POINT 0x000900A8 -#define FSCTL_DELETE_REPARSE_POINT 0x000900AC -#define FSCTL_SET_SPARSE 0x000900C4 -#define FSCTL_SET_ZERO_DATA 0x000900C8 -#define FSCTL_SET_ENCRYPTION 0x000900D7 -#define FSCTL_ENCRYPTION_FSCTL_IO 0x000900DB -#define FSCTL_WRITE_RAW_ENCRYPTED 0x000900DF -#define FSCTL_READ_RAW_ENCRYPTED 0x000900E3 -#define FSCTL_SIS_COPYFILE 0x00090100 -#define FSCTL_SIS_LINK_FILES 0x0009C104 - -#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003 -#define IO_REPARSE_TAG_HSM 0xC0000004 -#define IO_REPARSE_TAG_SIS 0x80000007 - /* ************************************************************************ * All structs for everything above the SMB PDUs themselves @@ -2515,8 +2482,6 @@ struct data_blob { 6) Use nanosecond timestamps throughout all time fields if corresponding attribute flag is set 7) sendfile - handle based copy - 8) Direct i/o - 9) Misc fcntls? what about fixing 64 bit alignment @@ -2635,7 +2600,5 @@ typedef struct file_chattr_info { __le64 mode; /* list of actual attribute bits on this inode */ } __attribute__((packed)) FILE_CHATTR_INFO; /* ext attributes (chattr, chflags) level 0x206 */ - -#endif - +#endif /* POSIX */ #endif /* _CIFSPDU_H */ diff --git a/fs/cifs/smbfsctl.h b/fs/cifs/smbfsctl.h new file mode 100644 index 00000000000..7056b891e08 --- /dev/null +++ b/fs/cifs/smbfsctl.h @@ -0,0 +1,84 @@ +/* + * fs/cifs/smbfsctl.h: SMB, CIFS, SMB2 FSCTL definitions + * + * Copyright (c) International Business Machines Corp., 2002,2009 + * Author(s): Steve French (sfrench@us.ibm.com) + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* IOCTL information */ +/* + * List of ioctl/fsctl function codes that are or could be useful in the + * future to remote clients like cifs or SMB2 client. There is probably + * a slightly larger set of fsctls that NTFS local filesystem could handle, + * including the seven below that we do not have struct definitions for. + * Even with protocol definitions for most of these now available, we still + * need to do some experimentation to identify which are practical to do + * remotely. Some of the following, such as the encryption/compression ones + * could be invoked from tools via a specialized hook into the VFS rather + * than via the standard vfs entry points + */ +#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000 +#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004 +#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008 +#define FSCTL_LOCK_VOLUME 0x00090018 +#define FSCTL_UNLOCK_VOLUME 0x0009001C +#define FSCTL_IS_PATHNAME_VALID 0x0009002C /* BB add struct */ +#define FSCTL_GET_COMPRESSION 0x0009003C /* BB add struct */ +#define FSCTL_SET_COMPRESSION 0x0009C040 /* BB add struct */ +#define FSCTL_QUERY_FAT_BPB 0x00090058 /* BB add struct */ +/* Verify the next FSCTL number, we had it as 0x00090090 before */ +#define FSCTL_FILESYSTEM_GET_STATS 0x00090060 /* BB add struct */ +#define FSCTL_GET_NTFS_VOLUME_DATA 0x00090064 /* BB add struct */ +#define FSCTL_GET_RETRIEVAL_POINTERS 0x00090073 /* BB add struct */ +#define FSCTL_IS_VOLUME_DIRTY 0x00090078 /* BB add struct */ +#define FSCTL_ALLOW_EXTENDED_DASD_IO 0x00090083 /* BB add struct */ +#define FSCTL_REQUEST_FILTER_OPLOCK 0x0009008C +#define FSCTL_FIND_FILES_BY_SID 0x0009008F /* BB add struct */ +#define FSCTL_SET_OBJECT_ID 0x00090098 /* BB add struct */ +#define FSCTL_GET_OBJECT_ID 0x0009009C /* BB add struct */ +#define FSCTL_DELETE_OBJECT_ID 0x000900A0 /* BB add struct */ +#define FSCTL_SET_REPARSE_POINT 0x000900A4 /* BB add struct */ +#define FSCTL_GET_REPARSE_POINT 0x000900A8 /* BB add struct */ +#define FSCTL_DELETE_REPARSE_POINT 0x000900AC /* BB add struct */ +#define FSCTL_SET_OBJECT_ID_EXTENDED 0x000900BC /* BB add struct */ +#define FSCTL_CREATE_OR_GET_OBJECT_ID 0x000900C0 /* BB add struct */ +#define FSCTL_SET_SPARSE 0x000900C4 /* BB add struct */ +#define FSCTL_SET_ZERO_DATA 0x000900C8 /* BB add struct */ +#define FSCTL_SET_ENCRYPTION 0x000900D7 /* BB add struct */ +#define FSCTL_ENCRYPTION_FSCTL_IO 0x000900DB /* BB add struct */ +#define FSCTL_WRITE_RAW_ENCRYPTED 0x000900DF /* BB add struct */ +#define FSCTL_READ_RAW_ENCRYPTED 0x000900E3 /* BB add struct */ +#define FSCTL_READ_FILE_USN_DATA 0x000900EB /* BB add struct */ +#define FSCTL_WRITE_USN_CLOSE_RECORD 0x000900EF /* BB add struct */ +#define FSCTL_SIS_COPYFILE 0x00090100 /* BB add struct */ +#define FSCTL_RECALL_FILE 0x00090117 /* BB add struct */ +#define FSCTL_QUERY_SPARING_INFO 0x00090138 /* BB add struct */ +#define FSCTL_SET_ZERO_ON_DEALLOC 0x00090194 /* BB add struct */ +#define FSCTL_SET_SHORT_NAME_BEHAVIOR 0x000901B4 /* BB add struct */ +#define FSCTL_QUERY_ALLOCATED_RANGES 0x000940CF /* BB add struct */ +#define FSCTL_SET_DEFECT_MANAGEMENT 0x00098134 /* BB add struct */ +#define FSCTL_SIS_LINK_FILES 0x0009C104 +#define FSCTL_PIPE_PEEK 0x0011400C /* BB add struct */ +#define FSCTL_PIPE_TRANSCEIVE 0x0011C017 /* BB add struct */ +/* strange that the number for this op is not sequential with previous op */ +#define FSCTL_PIPE_WAIT 0x00110018 /* BB add struct */ +#define FSCTL_LMR_GET_LINK_TRACK_INF 0x001400E8 /* BB add struct */ +#define FSCTL_LMR_SET_LINK_TRACK_INF 0x001400EC /* BB add struct */ + +#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003 +#define IO_REPARSE_TAG_HSM 0xC0000004 +#define IO_REPARSE_TAG_SIS 0x80000007 -- GitLab From fcc7c09d94be7b75c9ea2beb22d0fae191c6b4b9 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Sat, 28 Feb 2009 12:59:03 -0500 Subject: [PATCH 3111/4982] cifs: fix buffer format byte on NT Rename/hardlink Discovered at Connnectathon 2009... The buffer format byte and the pad are transposed in NT_RENAME calls (which are used to set hardlinks). Most servers seem to ignore this fact, but NetApp filers throw back an error due to this problem. This patch fixes it. CC: Stable Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifssmb.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 4c344fe7a15..bc09c998631 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -2377,8 +2377,10 @@ winCreateHardLinkRetry: PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; - pSMB->OldFileName[name_len] = 0; /* pad */ - pSMB->OldFileName[name_len + 1] = 0x04; + + /* protocol specifies ASCII buffer format (0x04) for unicode */ + pSMB->OldFileName[name_len] = 0x04; + pSMB->OldFileName[name_len + 1] = 0x00; /* pad */ name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2], toName, PATH_MAX, nls_codepage, remap); -- GitLab From 276a74a4835ad86d6da42f3a084b060afc5656e8 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 3 Mar 2009 18:00:34 +0000 Subject: [PATCH 3112/4982] [CIFS] Use posix open on file open when server supports it Signed-off-by: Steve French --- fs/cifs/file.c | 124 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 111 insertions(+), 13 deletions(-) diff --git a/fs/cifs/file.c b/fs/cifs/file.c index e4ecb1cb0b1..7bef4cce572 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -124,6 +124,80 @@ static inline int cifs_get_disposition(unsigned int flags) return FILE_OPEN; } +/* all arguments to this function must be checked for validity in caller */ +static inline int cifs_posix_open_inode_helper(struct inode *inode, + struct file *file, struct cifsInodeInfo *pCifsInode, + struct cifsFileInfo *pCifsFile, int oplock, u16 netfid) +{ + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); +/* struct timespec temp; */ /* BB REMOVEME BB */ + + file->private_data = kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); + if (file->private_data == NULL) + return -ENOMEM; + pCifsFile = cifs_init_private(file->private_data, inode, file, netfid); + write_lock(&GlobalSMBSeslock); + list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList); + + pCifsInode = CIFS_I(file->f_path.dentry->d_inode); + if (pCifsInode == NULL) { + write_unlock(&GlobalSMBSeslock); + return -EINVAL; + } + + /* want handles we can use to read with first + in the list so we do not have to walk the + list to search for one in write_begin */ + if ((file->f_flags & O_ACCMODE) == O_WRONLY) { + list_add_tail(&pCifsFile->flist, + &pCifsInode->openFileList); + } else { + list_add(&pCifsFile->flist, + &pCifsInode->openFileList); + } + + if (pCifsInode->clientCanCacheRead) { + /* we have the inode open somewhere else + no need to discard cache data */ + goto psx_client_can_cache; + } + + /* BB FIXME need to fix this check to move it earlier into posix_open + BB fIX following section BB FIXME */ + + /* if not oplocked, invalidate inode pages if mtime or file + size changed */ +/* temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime)); + if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) && + (file->f_path.dentry->d_inode->i_size == + (loff_t)le64_to_cpu(buf->EndOfFile))) { + cFYI(1, ("inode unchanged on server")); + } else { + if (file->f_path.dentry->d_inode->i_mapping) { + rc = filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping); + if (rc != 0) + CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc; + } + cFYI(1, ("invalidating remote inode since open detected it " + "changed")); + invalidate_remote_inode(file->f_path.dentry->d_inode); + } */ + +psx_client_can_cache: + if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { + pCifsInode->clientCanCacheAll = true; + pCifsInode->clientCanCacheRead = true; + cFYI(1, ("Exclusive Oplock granted on inode %p", + file->f_path.dentry->d_inode)); + } else if ((oplock & 0xF) == OPLOCK_READ) + pCifsInode->clientCanCacheRead = true; + + /* will have to change the unlock if we reenable the + filemap_fdatawrite (which does not seem necessary */ + write_unlock(&GlobalSMBSeslock); + return 0; +} + /* all arguments to this function must be checked for validity in caller */ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file, struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile, @@ -195,7 +269,7 @@ int cifs_open(struct inode *inode, struct file *file) int rc = -EACCES; int xid, oplock; struct cifs_sb_info *cifs_sb; - struct cifsTconInfo *pTcon; + struct cifsTconInfo *tcon; struct cifsFileInfo *pCifsFile; struct cifsInodeInfo *pCifsInode; struct list_head *tmp; @@ -208,7 +282,7 @@ int cifs_open(struct inode *inode, struct file *file) xid = GetXid(); cifs_sb = CIFS_SB(inode->i_sb); - pTcon = cifs_sb->tcon; + tcon = cifs_sb->tcon; if (file->f_flags & O_CREAT) { /* search inode for this file and fill in file->private_data */ @@ -248,6 +322,35 @@ int cifs_open(struct inode *inode, struct file *file) cFYI(1, ("inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags, full_path)); + + if (oplockEnabled) + oplock = REQ_OPLOCK; + else + oplock = 0; + + if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && + (CIFS_UNIX_POSIX_PATH_OPS_CAP & + le64_to_cpu(tcon->fsUnixInfo.Capability))) { + int oflags = (int) cifs_posix_convert_flags(file->f_flags); + /* can not refresh inode info since size could be stale */ + rc = cifs_posix_open(full_path, &inode, inode->i_sb, + cifs_sb->mnt_file_mode /* ignored */, + oflags, &oplock, &netfid, xid); + if (rc == 0) { + cFYI(1, ("posix open succeeded")); + /* no need for special case handling of setting mode + on read only files needed here */ + + cifs_posix_open_inode_helper(inode, file, pCifsInode, + pCifsFile, oplock, netfid); + goto out; + } else if ((rc != -EIO) && (rc != -EREMOTE) && + (rc != -EOPNOTSUPP)) /* path not found or net err */ + goto out; + /* fallthrough to retry open the old way on operation + not supported or DFS errors */ + } + desiredAccess = cifs_convert_flags(file->f_flags); /********************************************************************* @@ -276,11 +379,6 @@ int cifs_open(struct inode *inode, struct file *file) disposition = cifs_get_disposition(file->f_flags); - if (oplockEnabled) - oplock = REQ_OPLOCK; - else - oplock = 0; - /* BB pass O_SYNC flag through on file attributes .. BB */ /* Also refresh inode by passing in file_info buf returned by SMBOpen @@ -297,7 +395,7 @@ int cifs_open(struct inode *inode, struct file *file) } if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) - rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, + rc = CIFSSMBOpen(xid, tcon, full_path, disposition, desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); @@ -306,7 +404,7 @@ int cifs_open(struct inode *inode, struct file *file) if (rc == -EIO) { /* Old server, try legacy style OpenX */ - rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, + rc = SMBLegacyOpen(xid, tcon, full_path, disposition, desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); @@ -323,12 +421,12 @@ int cifs_open(struct inode *inode, struct file *file) } pCifsFile = cifs_init_private(file->private_data, inode, file, netfid); write_lock(&GlobalSMBSeslock); - list_add(&pCifsFile->tlist, &pTcon->openFileList); + list_add(&pCifsFile->tlist, &tcon->openFileList); pCifsInode = CIFS_I(file->f_path.dentry->d_inode); if (pCifsInode) { rc = cifs_open_inode_helper(inode, file, pCifsInode, - pCifsFile, pTcon, + pCifsFile, tcon, &oplock, buf, full_path, xid); } else { write_unlock(&GlobalSMBSeslock); @@ -337,7 +435,7 @@ int cifs_open(struct inode *inode, struct file *file) if (oplock & CIFS_CREATE_ACTION) { /* time to set mode which we can not set earlier due to problems creating new read-only files */ - if (pTcon->unix_ext) { + if (tcon->unix_ext) { struct cifs_unix_set_info_args args = { .mode = inode->i_mode, .uid = NO_CHANGE_64, @@ -347,7 +445,7 @@ int cifs_open(struct inode *inode, struct file *file) .mtime = NO_CHANGE_64, .device = 0, }; - CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args, + CIFSSMBUnixSetInfo(xid, tcon, full_path, &args, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); -- GitLab From 64cc2c63694a03393985ffc8b178e72f52dd8a06 Mon Sep 17 00:00:00 2001 From: Steve French Date: Wed, 4 Mar 2009 19:54:08 +0000 Subject: [PATCH 3113/4982] [CIFS] work around bug in Samba server handling for posix open Samba server (version 3.3.1 and earlier, and 3.2.8 and earlier) incorrectly required the O_CREAT flag on posix open (even when a file was not being created). This disables posix open (create is still ok) after the first attempt returns EINVAL (and logs an error, once, recommending that they update their server). Acked-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/CHANGES | 2 ++ fs/cifs/cifsglob.h | 1 + fs/cifs/file.c | 16 +++++++++++++--- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index b33c8412e2c..fc977dfe959 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -11,6 +11,8 @@ to better ensure that we wait for server to write all of the data to server disk (not just write it over the network). Add new mount parameter to allow user to disable sending the (slow) SMB flush on fsync if desired (fsync still flushes all cached write data to the server). +Posix file open support added (turned off after one attempt if server +fails to support it properly, as with Samba server versions prior to 3.3.2) Version 1.56 ------------ diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 44ff94d37e1..9fbf4dff5da 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -299,6 +299,7 @@ struct cifsTconInfo { bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol for this mount even if server would support */ bool local_lease:1; /* check leases (only) on local system not remote */ + bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */ bool need_reconnect:1; /* connection reset, tid now invalid */ /* BB add field for back pointer to sb struct(s)? */ }; diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 7bef4cce572..81747acca4c 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -328,7 +328,8 @@ int cifs_open(struct inode *inode, struct file *file) else oplock = 0; - if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && + if (!tcon->broken_posix_open && tcon->unix_ext && + (tcon->ses->capabilities & CAP_UNIX) && (CIFS_UNIX_POSIX_PATH_OPS_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability))) { int oflags = (int) cifs_posix_convert_flags(file->f_flags); @@ -344,11 +345,20 @@ int cifs_open(struct inode *inode, struct file *file) cifs_posix_open_inode_helper(inode, file, pCifsInode, pCifsFile, oplock, netfid); goto out; + } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { + if (tcon->ses->serverNOS) + cERROR(1, ("server %s of type %s returned" + " unexpected error on SMB posix open" + ", disabling posix open support." + " Check if server update available.", + tcon->ses->serverName, + tcon->ses->serverNOS)); + tcon->broken_posix_open = true; } else if ((rc != -EIO) && (rc != -EREMOTE) && (rc != -EOPNOTSUPP)) /* path not found or net err */ goto out; - /* fallthrough to retry open the old way on operation - not supported or DFS errors */ + /* else fallthrough to retry open the old way on network i/o + or DFS errors */ } desiredAccess = cifs_convert_flags(file->f_flags); -- GitLab From ff5e2b4732b8386d8354da2cdf7c146487f51736 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 11 Mar 2009 23:24:03 -0700 Subject: [PATCH 3114/4982] wimax: fix i2400m printk formats Fix printk format warnings: drivers/net/wimax/i2400m/netdev.c:523: warning: format '%zu' expects type 'size_t', but argument 7 has type 'unsigned int' drivers/net/wimax/i2400m/netdev.c:548: warning: format '%zu' expects type 'size_t', but argument 7 has type 'unsigned int' Signed-off-by: Randy Dunlap Signed-off-by: Inaky Perez-Gonzalez Signed-off-by: David S. Miller --- drivers/net/wimax/i2400m/netdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c index a98eb4bafc5..6b1fe7a81f2 100644 --- a/drivers/net/wimax/i2400m/netdev.c +++ b/drivers/net/wimax/i2400m/netdev.c @@ -520,7 +520,7 @@ void i2400m_net_erx(struct i2400m *i2400m, struct sk_buff *skb, struct device *dev = i2400m_dev(i2400m); int protocol; - d_fnstart(2, dev, "(i2400m %p skb %p [%zu] cs %d)\n", + d_fnstart(2, dev, "(i2400m %p skb %p [%u] cs %d)\n", i2400m, skb, skb->len, cs); switch(cs) { case I2400M_CS_IPV4_0: @@ -545,7 +545,7 @@ void i2400m_net_erx(struct i2400m *i2400m, struct sk_buff *skb, d_dump(4, dev, skb->data, skb->len); netif_rx_ni(skb); /* see notes in function header */ error: - d_fnend(2, dev, "(i2400m %p skb %p [%zu] cs %d) = void\n", + d_fnend(2, dev, "(i2400m %p skb %p [%u] cs %d) = void\n", i2400m, skb, skb->len, cs); } -- GitLab From 4796417417a62e2ae83d92cb92e1ecf9ec67b5f5 Mon Sep 17 00:00:00 2001 From: Ilya Yanok Date: Wed, 11 Mar 2009 23:26:02 -0700 Subject: [PATCH 3115/4982] dnet: Dave DNET ethernet controller driver (updated) Driver for Dave DNET ethernet controller found on Dave/DENX QongEVB-LITE FPGA. Heavily based on Dave sources, I've just adopted it to current kernel version and done some code cleanup. Signed-off-by: Ilya Yanok Signed-off-by: David S. Miller --- drivers/net/Kconfig | 11 + drivers/net/Makefile | 1 + drivers/net/dnet.c | 994 +++++++++++++++++++++++++++++++++++++++++++ drivers/net/dnet.h | 225 ++++++++++ 4 files changed, 1231 insertions(+) create mode 100644 drivers/net/dnet.c create mode 100644 drivers/net/dnet.h diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index a2f185fd707..5c28b06dac6 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1040,6 +1040,17 @@ config NI65 To compile this driver as a module, choose M here. The module will be called ni65. +config DNET + tristate "Dave ethernet support (DNET)" + depends on NET_ETHERNET + select PHYLIB + help + The Dave ethernet interface (DNET) is found on Qong Board FPGA. + Say Y to include support for the DNET chip. + + To compile this driver as a module, choose M here: the module + will be called dnet. + source "drivers/net/tulip/Kconfig" config AT1700 diff --git a/drivers/net/Makefile b/drivers/net/Makefile index aca8492db65..6d9bba58b9a 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -231,6 +231,7 @@ obj-$(CONFIG_ENC28J60) += enc28j60.o obj-$(CONFIG_XTENSA_XT2000_SONIC) += xtsonic.o +obj-$(CONFIG_DNET) += dnet.o obj-$(CONFIG_MACB) += macb.o obj-$(CONFIG_ARM) += arm/ diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c new file mode 100644 index 00000000000..92c3bd3a472 --- /dev/null +++ b/drivers/net/dnet.c @@ -0,0 +1,994 @@ +/* + * Dave DNET Ethernet Controller driver + * + * Copyright (C) 2008 Dave S.r.l. + * Copyright (C) 2009 Ilya Yanok, Emcraft Systems Ltd, + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dnet.h" + +#undef DEBUG + +/* function for reading internal MAC register */ +u16 dnet_readw_mac(struct dnet *bp, u16 reg) +{ + u16 data_read; + + /* issue a read */ + dnet_writel(bp, reg, MACREG_ADDR); + + /* since a read/write op to the MAC is very slow, + * we must wait before reading the data */ + ndelay(500); + + /* read data read from the MAC register */ + data_read = dnet_readl(bp, MACREG_DATA); + + /* all done */ + return data_read; +} + +/* function for writing internal MAC register */ +void dnet_writew_mac(struct dnet *bp, u16 reg, u16 val) +{ + /* load data to write */ + dnet_writel(bp, val, MACREG_DATA); + + /* issue a write */ + dnet_writel(bp, reg | DNET_INTERNAL_WRITE, MACREG_ADDR); + + /* since a read/write op to the MAC is very slow, + * we must wait before exiting */ + ndelay(500); +} + +static void __dnet_set_hwaddr(struct dnet *bp) +{ + u16 tmp; + + tmp = cpu_to_be16(*((u16 *) bp->dev->dev_addr)); + dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_0_REG, tmp); + tmp = cpu_to_be16(*((u16 *) (bp->dev->dev_addr + 2))); + dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_1_REG, tmp); + tmp = cpu_to_be16(*((u16 *) (bp->dev->dev_addr + 4))); + dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG, tmp); +} + +static void __devinit dnet_get_hwaddr(struct dnet *bp) +{ + u16 tmp; + u8 addr[6]; + + /* + * from MAC docs: + * "Note that the MAC address is stored in the registers in Hexadecimal + * form. For example, to set the MAC Address to: AC-DE-48-00-00-80 + * would require writing 0xAC (octet 0) to address 0x0B (high byte of + * Mac_addr[15:0]), 0xDE (octet 1) to address 0x0A (Low byte of + * Mac_addr[15:0]), 0x48 (octet 2) to address 0x0D (high byte of + * Mac_addr[15:0]), 0x00 (octet 3) to address 0x0C (Low byte of + * Mac_addr[15:0]), 0x00 (octet 4) to address 0x0F (high byte of + * Mac_addr[15:0]), and 0x80 (octet 5) to address * 0x0E (Low byte of + * Mac_addr[15:0]). + */ + tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_0_REG); + *((u16 *) addr) = be16_to_cpu(tmp); + tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_1_REG); + *((u16 *) (addr + 2)) = be16_to_cpu(tmp); + tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG); + *((u16 *) (addr + 4)) = be16_to_cpu(tmp); + + if (is_valid_ether_addr(addr)) + memcpy(bp->dev->dev_addr, addr, sizeof(addr)); +} + +static int dnet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) +{ + struct dnet *bp = bus->priv; + u16 value; + + while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG) + & DNET_INTERNAL_GMII_MNG_CMD_FIN)) + cpu_relax(); + + /* only 5 bits allowed for phy-addr and reg_offset */ + mii_id &= 0x1f; + regnum &= 0x1f; + + /* prepare reg_value for a read */ + value = (mii_id << 8); + value |= regnum; + + /* write control word */ + dnet_writew_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG, value); + + /* wait for end of transfer */ + while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG) + & DNET_INTERNAL_GMII_MNG_CMD_FIN)) + cpu_relax(); + + value = dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_DAT_REG); + + pr_debug("mdio_read %02x:%02x <- %04x\n", mii_id, regnum, value); + + return value; +} + +static int dnet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, + u16 value) +{ + struct dnet *bp = bus->priv; + u16 tmp; + + pr_debug("mdio_write %02x:%02x <- %04x\n", mii_id, regnum, value); + + while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG) + & DNET_INTERNAL_GMII_MNG_CMD_FIN)) + cpu_relax(); + + /* prepare for a write operation */ + tmp = (1 << 13); + + /* only 5 bits allowed for phy-addr and reg_offset */ + mii_id &= 0x1f; + regnum &= 0x1f; + + /* only 16 bits on data */ + value &= 0xffff; + + /* prepare reg_value for a write */ + tmp |= (mii_id << 8); + tmp |= regnum; + + /* write data to write first */ + dnet_writew_mac(bp, DNET_INTERNAL_GMII_MNG_DAT_REG, value); + + /* write control word */ + dnet_writew_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG, tmp); + + while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG) + & DNET_INTERNAL_GMII_MNG_CMD_FIN)) + cpu_relax(); + + return 0; +} + +static int dnet_mdio_reset(struct mii_bus *bus) +{ + return 0; +} + +static void dnet_handle_link_change(struct net_device *dev) +{ + struct dnet *bp = netdev_priv(dev); + struct phy_device *phydev = bp->phy_dev; + unsigned long flags; + u32 mode_reg, ctl_reg; + + int status_change = 0; + + spin_lock_irqsave(&bp->lock, flags); + + mode_reg = dnet_readw_mac(bp, DNET_INTERNAL_MODE_REG); + ctl_reg = dnet_readw_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG); + + if (phydev->link) { + if (bp->duplex != phydev->duplex) { + if (phydev->duplex) + ctl_reg &= + ~(DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP); + else + ctl_reg |= + DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP; + + bp->duplex = phydev->duplex; + status_change = 1; + } + + if (bp->speed != phydev->speed) { + status_change = 1; + switch (phydev->speed) { + case 1000: + mode_reg |= DNET_INTERNAL_MODE_GBITEN; + break; + case 100: + case 10: + mode_reg &= ~DNET_INTERNAL_MODE_GBITEN; + break; + default: + printk(KERN_WARNING + "%s: Ack! Speed (%d) is not " + "10/100/1000!\n", dev->name, + phydev->speed); + break; + } + bp->speed = phydev->speed; + } + } + + if (phydev->link != bp->link) { + if (phydev->link) { + mode_reg |= + (DNET_INTERNAL_MODE_RXEN | DNET_INTERNAL_MODE_TXEN); + } else { + mode_reg &= + ~(DNET_INTERNAL_MODE_RXEN | + DNET_INTERNAL_MODE_TXEN); + bp->speed = 0; + bp->duplex = -1; + } + bp->link = phydev->link; + + status_change = 1; + } + + if (status_change) { + dnet_writew_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG, ctl_reg); + dnet_writew_mac(bp, DNET_INTERNAL_MODE_REG, mode_reg); + } + + spin_unlock_irqrestore(&bp->lock, flags); + + if (status_change) { + if (phydev->link) + printk(KERN_INFO "%s: link up (%d/%s)\n", + dev->name, phydev->speed, + DUPLEX_FULL == phydev->duplex ? "Full" : "Half"); + else + printk(KERN_INFO "%s: link down\n", dev->name); + } +} + +static int dnet_mii_probe(struct net_device *dev) +{ + struct dnet *bp = netdev_priv(dev); + struct phy_device *phydev = NULL; + int phy_addr; + + /* find the first phy */ + for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { + if (bp->mii_bus->phy_map[phy_addr]) { + phydev = bp->mii_bus->phy_map[phy_addr]; + break; + } + } + + if (!phydev) { + printk(KERN_ERR "%s: no PHY found\n", dev->name); + return -ENODEV; + } + + /* TODO : add pin_irq */ + + /* attach the mac to the phy */ + if (bp->capabilities & DNET_HAS_RMII) { + phydev = phy_connect(dev, phydev->dev.bus_id, + &dnet_handle_link_change, 0, + PHY_INTERFACE_MODE_RMII); + } else { + phydev = phy_connect(dev, phydev->dev.bus_id, + &dnet_handle_link_change, 0, + PHY_INTERFACE_MODE_MII); + } + + if (IS_ERR(phydev)) { + printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); + return PTR_ERR(phydev); + } + + /* mask with MAC supported features */ + if (bp->capabilities & DNET_HAS_GIGABIT) + phydev->supported &= PHY_GBIT_FEATURES; + else + phydev->supported &= PHY_BASIC_FEATURES; + + phydev->supported |= SUPPORTED_Asym_Pause | SUPPORTED_Pause; + + phydev->advertising = phydev->supported; + + bp->link = 0; + bp->speed = 0; + bp->duplex = -1; + bp->phy_dev = phydev; + + return 0; +} + +static int dnet_mii_init(struct dnet *bp) +{ + int err, i; + + bp->mii_bus = mdiobus_alloc(); + if (bp->mii_bus == NULL) + return -ENOMEM; + + bp->mii_bus->name = "dnet_mii_bus"; + bp->mii_bus->read = &dnet_mdio_read; + bp->mii_bus->write = &dnet_mdio_write; + bp->mii_bus->reset = &dnet_mdio_reset; + + snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0); + + bp->mii_bus->priv = bp; + + bp->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); + if (!bp->mii_bus->irq) { + err = -ENOMEM; + goto err_out; + } + + for (i = 0; i < PHY_MAX_ADDR; i++) + bp->mii_bus->irq[i] = PHY_POLL; + + platform_set_drvdata(bp->dev, bp->mii_bus); + + if (mdiobus_register(bp->mii_bus)) { + err = -ENXIO; + goto err_out_free_mdio_irq; + } + + if (dnet_mii_probe(bp->dev) != 0) { + err = -ENXIO; + goto err_out_unregister_bus; + } + + return 0; + +err_out_unregister_bus: + mdiobus_unregister(bp->mii_bus); +err_out_free_mdio_irq: + kfree(bp->mii_bus->irq); +err_out: + mdiobus_free(bp->mii_bus); + return err; +} + +/* For Neptune board: LINK1000 as Link LED and TX as activity LED */ +int dnet_phy_marvell_fixup(struct phy_device *phydev) +{ + return phy_write(phydev, 0x18, 0x4148); +} + +static void dnet_update_stats(struct dnet *bp) +{ + u32 __iomem *reg = bp->regs + DNET_RX_PKT_IGNR_CNT; + u32 *p = &bp->hw_stats.rx_pkt_ignr; + u32 *end = &bp->hw_stats.rx_byte + 1; + + WARN_ON((unsigned long)(end - p - 1) != + (DNET_RX_BYTE_CNT - DNET_RX_PKT_IGNR_CNT) / 4); + + for (; p < end; p++, reg++) + *p += readl(reg); + + reg = bp->regs + DNET_TX_UNICAST_CNT; + p = &bp->hw_stats.tx_unicast; + end = &bp->hw_stats.tx_byte + 1; + + WARN_ON((unsigned long)(end - p - 1) != + (DNET_TX_BYTE_CNT - DNET_TX_UNICAST_CNT) / 4); + + for (; p < end; p++, reg++) + *p += readl(reg); +} + +static int dnet_poll(struct napi_struct *napi, int budget) +{ + struct dnet *bp = container_of(napi, struct dnet, napi); + struct net_device *dev = bp->dev; + int npackets = 0; + unsigned int pkt_len; + struct sk_buff *skb; + unsigned int *data_ptr; + u32 int_enable; + u32 cmd_word; + int i; + + while (npackets < budget) { + /* + * break out of while loop if there are no more + * packets waiting + */ + if (!(dnet_readl(bp, RX_FIFO_WCNT) >> 16)) { + netif_rx_complete(napi); + int_enable = dnet_readl(bp, INTR_ENB); + int_enable |= DNET_INTR_SRC_RX_CMDFIFOAF; + dnet_writel(bp, int_enable, INTR_ENB); + return 0; + } + + cmd_word = dnet_readl(bp, RX_LEN_FIFO); + pkt_len = cmd_word & 0xFFFF; + + if (cmd_word & 0xDF180000) + printk(KERN_ERR "%s packet receive error %x\n", + __func__, cmd_word); + + skb = dev_alloc_skb(pkt_len + 5); + if (skb != NULL) { + /* Align IP on 16 byte boundaries */ + skb_reserve(skb, 2); + /* + * 'skb_put()' points to the start of sk_buff + * data area. + */ + data_ptr = (unsigned int *)skb_put(skb, pkt_len); + for (i = 0; i < (pkt_len + 3) >> 2; i++) + *data_ptr++ = dnet_readl(bp, RX_DATA_FIFO); + skb->protocol = eth_type_trans(skb, dev); + netif_receive_skb(skb); + npackets++; + } else + printk(KERN_NOTICE + "%s: No memory to allocate a sk_buff of " + "size %u.\n", dev->name, pkt_len); + } + + budget -= npackets; + + if (npackets < budget) { + /* We processed all packets available. Tell NAPI it can + * stop polling then re-enable rx interrupts */ + netif_rx_complete(napi); + int_enable = dnet_readl(bp, INTR_ENB); + int_enable |= DNET_INTR_SRC_RX_CMDFIFOAF; + dnet_writel(bp, int_enable, INTR_ENB); + return 0; + } + + /* There are still packets waiting */ + return 1; +} + +static irqreturn_t dnet_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct dnet *bp = netdev_priv(dev); + u32 int_src, int_enable, int_current; + unsigned long flags; + unsigned int handled = 0; + + spin_lock_irqsave(&bp->lock, flags); + + /* read and clear the DNET irq (clear on read) */ + int_src = dnet_readl(bp, INTR_SRC); + int_enable = dnet_readl(bp, INTR_ENB); + int_current = int_src & int_enable; + + /* restart the queue if we had stopped it for TX fifo almost full */ + if (int_current & DNET_INTR_SRC_TX_FIFOAE) { + int_enable = dnet_readl(bp, INTR_ENB); + int_enable &= ~DNET_INTR_ENB_TX_FIFOAE; + dnet_writel(bp, int_enable, INTR_ENB); + netif_wake_queue(dev); + handled = 1; + } + + /* RX FIFO error checking */ + if (int_current & + (DNET_INTR_SRC_RX_CMDFIFOFF | DNET_INTR_SRC_RX_DATAFIFOFF)) { + printk(KERN_ERR "%s: RX fifo error %x, irq %x\n", __func__, + dnet_readl(bp, RX_STATUS), int_current); + /* we can only flush the RX FIFOs */ + dnet_writel(bp, DNET_SYS_CTL_RXFIFOFLUSH, SYS_CTL); + ndelay(500); + dnet_writel(bp, 0, SYS_CTL); + handled = 1; + } + + /* TX FIFO error checking */ + if (int_current & + (DNET_INTR_SRC_TX_FIFOFULL | DNET_INTR_SRC_TX_DISCFRM)) { + printk(KERN_ERR "%s: TX fifo error %x, irq %x\n", __func__, + dnet_readl(bp, TX_STATUS), int_current); + /* we can only flush the TX FIFOs */ + dnet_writel(bp, DNET_SYS_CTL_TXFIFOFLUSH, SYS_CTL); + ndelay(500); + dnet_writel(bp, 0, SYS_CTL); + handled = 1; + } + + if (int_current & DNET_INTR_SRC_RX_CMDFIFOAF) { + if (netif_rx_schedule_prep(&bp->napi)) { + /* + * There's no point taking any more interrupts + * until we have processed the buffers + */ + /* Disable Rx interrupts and schedule NAPI poll */ + int_enable = dnet_readl(bp, INTR_ENB); + int_enable &= ~DNET_INTR_SRC_RX_CMDFIFOAF; + dnet_writel(bp, int_enable, INTR_ENB); + __netif_rx_schedule(&bp->napi); + } + handled = 1; + } + + if (!handled) + pr_debug("%s: irq %x remains\n", __func__, int_current); + + spin_unlock_irqrestore(&bp->lock, flags); + + return IRQ_RETVAL(handled); +} + +#ifdef DEBUG +static inline void dnet_print_skb(struct sk_buff *skb) +{ + int k; + printk(KERN_DEBUG PFX "data:"); + for (k = 0; k < skb->len; k++) + printk(" %02x", (unsigned int)skb->data[k]); + printk("\n"); +} +#else +#define dnet_print_skb(skb) do {} while (0) +#endif + +static int dnet_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + + struct dnet *bp = netdev_priv(dev); + u32 tx_status, irq_enable; + unsigned int len, i, tx_cmd, wrsz; + unsigned long flags; + unsigned int *bufp; + + tx_status = dnet_readl(bp, TX_STATUS); + + pr_debug("start_xmit: len %u head %p data %p tail %p end %p\n", + skb->len, skb->head, skb->data, skb->tail, skb->end); + dnet_print_skb(skb); + + /* frame size (words) */ + len = (skb->len + 3) >> 2; + + spin_lock_irqsave(&bp->lock, flags); + + tx_status = dnet_readl(bp, TX_STATUS); + + bufp = (unsigned int *)(((u32) skb->data) & 0xFFFFFFFC); + wrsz = (u32) skb->len + 3; + wrsz += ((u32) skb->data) & 0x3; + wrsz >>= 2; + tx_cmd = ((((unsigned int)(skb->data)) & 0x03) << 16) | (u32) skb->len; + + /* check if there is enough room for the current frame */ + if (wrsz < (DNET_FIFO_SIZE - dnet_readl(bp, TX_FIFO_WCNT))) { + for (i = 0; i < wrsz; i++) + dnet_writel(bp, *bufp++, TX_DATA_FIFO); + + /* + * inform MAC that a packet's written and ready to be + * shipped out + */ + dnet_writel(bp, tx_cmd, TX_LEN_FIFO); + } + + if (dnet_readl(bp, TX_FIFO_WCNT) > DNET_FIFO_TX_DATA_AF_TH) { + netif_stop_queue(dev); + tx_status = dnet_readl(bp, INTR_SRC); + irq_enable = dnet_readl(bp, INTR_ENB); + irq_enable |= DNET_INTR_ENB_TX_FIFOAE; + dnet_writel(bp, irq_enable, INTR_ENB); + } + + /* free the buffer */ + dev_kfree_skb(skb); + + spin_unlock_irqrestore(&bp->lock, flags); + + dev->trans_start = jiffies; + + return 0; +} + +static void dnet_reset_hw(struct dnet *bp) +{ + /* put ts_mac in IDLE state i.e. disable rx/tx */ + dnet_writew_mac(bp, DNET_INTERNAL_MODE_REG, DNET_INTERNAL_MODE_FCEN); + + /* + * RX FIFO almost full threshold: only cmd FIFO almost full is + * implemented for RX side + */ + dnet_writel(bp, DNET_FIFO_RX_CMD_AF_TH, RX_FIFO_TH); + /* + * TX FIFO almost empty threshold: only data FIFO almost empty + * is implemented for TX side + */ + dnet_writel(bp, DNET_FIFO_TX_DATA_AE_TH, TX_FIFO_TH); + + /* flush rx/tx fifos */ + dnet_writel(bp, DNET_SYS_CTL_RXFIFOFLUSH | DNET_SYS_CTL_TXFIFOFLUSH, + SYS_CTL); + msleep(1); + dnet_writel(bp, 0, SYS_CTL); +} + +static void dnet_init_hw(struct dnet *bp) +{ + u32 config; + + dnet_reset_hw(bp); + __dnet_set_hwaddr(bp); + + config = dnet_readw_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG); + + if (bp->dev->flags & IFF_PROMISC) + /* Copy All Frames */ + config |= DNET_INTERNAL_RXTX_CONTROL_ENPROMISC; + if (!(bp->dev->flags & IFF_BROADCAST)) + /* No BroadCast */ + config |= DNET_INTERNAL_RXTX_CONTROL_RXMULTICAST; + + config |= DNET_INTERNAL_RXTX_CONTROL_RXPAUSE | + DNET_INTERNAL_RXTX_CONTROL_RXBROADCAST | + DNET_INTERNAL_RXTX_CONTROL_DROPCONTROL | + DNET_INTERNAL_RXTX_CONTROL_DISCFXFCS; + + dnet_writew_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG, config); + + /* clear irq before enabling them */ + config = dnet_readl(bp, INTR_SRC); + + /* enable RX/TX interrupt, recv packet ready interrupt */ + dnet_writel(bp, DNET_INTR_ENB_GLOBAL_ENABLE | DNET_INTR_ENB_RX_SUMMARY | + DNET_INTR_ENB_TX_SUMMARY | DNET_INTR_ENB_RX_FIFOERR | + DNET_INTR_ENB_RX_ERROR | DNET_INTR_ENB_RX_FIFOFULL | + DNET_INTR_ENB_TX_FIFOFULL | DNET_INTR_ENB_TX_DISCFRM | + DNET_INTR_ENB_RX_PKTRDY, INTR_ENB); +} + +static int dnet_open(struct net_device *dev) +{ + struct dnet *bp = netdev_priv(dev); + + /* if the phy is not yet register, retry later */ + if (!bp->phy_dev) + return -EAGAIN; + + if (!is_valid_ether_addr(dev->dev_addr)) + return -EADDRNOTAVAIL; + + napi_enable(&bp->napi); + dnet_init_hw(bp); + + phy_start_aneg(bp->phy_dev); + + /* schedule a link state check */ + phy_start(bp->phy_dev); + + netif_start_queue(dev); + + return 0; +} + +static int dnet_close(struct net_device *dev) +{ + struct dnet *bp = netdev_priv(dev); + + netif_stop_queue(dev); + napi_disable(&bp->napi); + + if (bp->phy_dev) + phy_stop(bp->phy_dev); + + dnet_reset_hw(bp); + netif_carrier_off(dev); + + return 0; +} + +static inline void dnet_print_pretty_hwstats(struct dnet_stats *hwstat) +{ + pr_debug("%s\n", __func__); + pr_debug("----------------------------- RX statistics " + "-------------------------------\n"); + pr_debug("RX_PKT_IGNR_CNT %-8x\n", hwstat->rx_pkt_ignr); + pr_debug("RX_LEN_CHK_ERR_CNT %-8x\n", hwstat->rx_len_chk_err); + pr_debug("RX_LNG_FRM_CNT %-8x\n", hwstat->rx_lng_frm); + pr_debug("RX_SHRT_FRM_CNT %-8x\n", hwstat->rx_shrt_frm); + pr_debug("RX_IPG_VIOL_CNT %-8x\n", hwstat->rx_ipg_viol); + pr_debug("RX_CRC_ERR_CNT %-8x\n", hwstat->rx_crc_err); + pr_debug("RX_OK_PKT_CNT %-8x\n", hwstat->rx_ok_pkt); + pr_debug("RX_CTL_FRM_CNT %-8x\n", hwstat->rx_ctl_frm); + pr_debug("RX_PAUSE_FRM_CNT %-8x\n", hwstat->rx_pause_frm); + pr_debug("RX_MULTICAST_CNT %-8x\n", hwstat->rx_multicast); + pr_debug("RX_BROADCAST_CNT %-8x\n", hwstat->rx_broadcast); + pr_debug("RX_VLAN_TAG_CNT %-8x\n", hwstat->rx_vlan_tag); + pr_debug("RX_PRE_SHRINK_CNT %-8x\n", hwstat->rx_pre_shrink); + pr_debug("RX_DRIB_NIB_CNT %-8x\n", hwstat->rx_drib_nib); + pr_debug("RX_UNSUP_OPCD_CNT %-8x\n", hwstat->rx_unsup_opcd); + pr_debug("RX_BYTE_CNT %-8x\n", hwstat->rx_byte); + pr_debug("----------------------------- TX statistics " + "-------------------------------\n"); + pr_debug("TX_UNICAST_CNT %-8x\n", hwstat->tx_unicast); + pr_debug("TX_PAUSE_FRM_CNT %-8x\n", hwstat->tx_pause_frm); + pr_debug("TX_MULTICAST_CNT %-8x\n", hwstat->tx_multicast); + pr_debug("TX_BRDCAST_CNT %-8x\n", hwstat->tx_brdcast); + pr_debug("TX_VLAN_TAG_CNT %-8x\n", hwstat->tx_vlan_tag); + pr_debug("TX_BAD_FCS_CNT %-8x\n", hwstat->tx_bad_fcs); + pr_debug("TX_JUMBO_CNT %-8x\n", hwstat->tx_jumbo); + pr_debug("TX_BYTE_CNT %-8x\n", hwstat->tx_byte); +} + +static struct net_device_stats *dnet_get_stats(struct net_device *dev) +{ + + struct dnet *bp = netdev_priv(dev); + struct net_device_stats *nstat = &dev->stats; + struct dnet_stats *hwstat = &bp->hw_stats; + + /* read stats from hardware */ + dnet_update_stats(bp); + + /* Convert HW stats into netdevice stats */ + nstat->rx_errors = (hwstat->rx_len_chk_err + + hwstat->rx_lng_frm + hwstat->rx_shrt_frm + + /* ignore IGP violation error + hwstat->rx_ipg_viol + */ + hwstat->rx_crc_err + + hwstat->rx_pre_shrink + + hwstat->rx_drib_nib + hwstat->rx_unsup_opcd); + nstat->tx_errors = hwstat->tx_bad_fcs; + nstat->rx_length_errors = (hwstat->rx_len_chk_err + + hwstat->rx_lng_frm + + hwstat->rx_shrt_frm + hwstat->rx_pre_shrink); + nstat->rx_crc_errors = hwstat->rx_crc_err; + nstat->rx_frame_errors = hwstat->rx_pre_shrink + hwstat->rx_drib_nib; + nstat->rx_packets = hwstat->rx_ok_pkt; + nstat->tx_packets = (hwstat->tx_unicast + + hwstat->tx_multicast + hwstat->tx_brdcast); + nstat->rx_bytes = hwstat->rx_byte; + nstat->tx_bytes = hwstat->tx_byte; + nstat->multicast = hwstat->rx_multicast; + nstat->rx_missed_errors = hwstat->rx_pkt_ignr; + + dnet_print_pretty_hwstats(hwstat); + + return nstat; +} + +static int dnet_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct dnet *bp = netdev_priv(dev); + struct phy_device *phydev = bp->phy_dev; + + if (!phydev) + return -ENODEV; + + return phy_ethtool_gset(phydev, cmd); +} + +static int dnet_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct dnet *bp = netdev_priv(dev); + struct phy_device *phydev = bp->phy_dev; + + if (!phydev) + return -ENODEV; + + return phy_ethtool_sset(phydev, cmd); +} + +static int dnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct dnet *bp = netdev_priv(dev); + struct phy_device *phydev = bp->phy_dev; + + if (!netif_running(dev)) + return -EINVAL; + + if (!phydev) + return -ENODEV; + + return phy_mii_ioctl(phydev, if_mii(rq), cmd); +} + +static void dnet_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, "0"); +} + +static const struct ethtool_ops dnet_ethtool_ops = { + .get_settings = dnet_get_settings, + .set_settings = dnet_set_settings, + .get_drvinfo = dnet_get_drvinfo, + .get_link = ethtool_op_get_link, +}; + +static const struct net_device_ops dnet_netdev_ops = { + .ndo_open = dnet_open, + .ndo_stop = dnet_close, + .ndo_get_stats = dnet_get_stats, + .ndo_start_xmit = dnet_start_xmit, + .ndo_do_ioctl = dnet_ioctl, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_change_mtu = eth_change_mtu, +}; + +static int __devinit dnet_probe(struct platform_device *pdev) +{ + struct resource *res; + struct net_device *dev; + struct dnet *bp; + struct phy_device *phydev; + int err = -ENXIO; + unsigned int mem_base, mem_size, irq; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "no mmio resource defined\n"); + goto err_out; + } + mem_base = res->start; + mem_size = resource_size(res); + irq = platform_get_irq(pdev, 0); + + if (!request_mem_region(mem_base, mem_size, DRV_NAME)) { + dev_err(&pdev->dev, "no memory region available\n"); + err = -EBUSY; + goto err_out; + } + + err = -ENOMEM; + dev = alloc_etherdev(sizeof(*bp)); + if (!dev) { + dev_err(&pdev->dev, "etherdev alloc failed, aborting.\n"); + goto err_out; + } + + /* TODO: Actually, we have some interesting features... */ + dev->features |= 0; + + bp = netdev_priv(dev); + bp->dev = dev; + + SET_NETDEV_DEV(dev, &pdev->dev); + + spin_lock_init(&bp->lock); + + bp->regs = ioremap(mem_base, mem_size); + if (!bp->regs) { + dev_err(&pdev->dev, "failed to map registers, aborting.\n"); + err = -ENOMEM; + goto err_out_free_dev; + } + + dev->irq = irq; + err = request_irq(dev->irq, dnet_interrupt, 0, DRV_NAME, dev); + if (err) { + dev_err(&pdev->dev, "Unable to request IRQ %d (error %d)\n", + irq, err); + goto err_out_iounmap; + } + + dev->netdev_ops = &dnet_netdev_ops; + netif_napi_add(dev, &bp->napi, dnet_poll, 64); + dev->ethtool_ops = &dnet_ethtool_ops; + + dev->base_addr = (unsigned long)bp->regs; + + bp->capabilities = dnet_readl(bp, VERCAPS) & DNET_CAPS_MASK; + + dnet_get_hwaddr(bp); + + if (!is_valid_ether_addr(dev->dev_addr)) { + /* choose a random ethernet address */ + random_ether_addr(dev->dev_addr); + __dnet_set_hwaddr(bp); + } + + err = register_netdev(dev); + if (err) { + dev_err(&pdev->dev, "Cannot register net device, aborting.\n"); + goto err_out_free_irq; + } + + /* register the PHY board fixup (for Marvell 88E1111) */ + err = phy_register_fixup_for_uid(0x01410cc0, 0xfffffff0, + dnet_phy_marvell_fixup); + /* we can live without it, so just issue a warning */ + if (err) + dev_warn(&pdev->dev, "Cannot register PHY board fixup.\n"); + + if (dnet_mii_init(bp) != 0) + goto err_out_unregister_netdev; + + dev_info(&pdev->dev, "Dave DNET at 0x%p (0x%08x) irq %d %pM\n", + bp->regs, mem_base, dev->irq, dev->dev_addr); + dev_info(&pdev->dev, "has %smdio, %sirq, %sgigabit, %sdma \n", + (bp->capabilities & DNET_HAS_MDIO) ? "" : "no ", + (bp->capabilities & DNET_HAS_IRQ) ? "" : "no ", + (bp->capabilities & DNET_HAS_GIGABIT) ? "" : "no ", + (bp->capabilities & DNET_HAS_DMA) ? "" : "no "); + phydev = bp->phy_dev; + dev_info(&pdev->dev, "attached PHY driver [%s] " + "(mii_bus:phy_addr=%s, irq=%d)\n", + phydev->drv->name, phydev->dev.bus_id, phydev->irq); + + return 0; + +err_out_unregister_netdev: + unregister_netdev(dev); +err_out_free_irq: + free_irq(dev->irq, dev); +err_out_iounmap: + iounmap(bp->regs); +err_out_free_dev: + free_netdev(dev); +err_out: + return err; +} + +static int __devexit dnet_remove(struct platform_device *pdev) +{ + + struct net_device *dev; + struct dnet *bp; + + dev = platform_get_drvdata(pdev); + + if (dev) { + bp = netdev_priv(dev); + if (bp->phy_dev) + phy_disconnect(bp->phy_dev); + mdiobus_unregister(bp->mii_bus); + kfree(bp->mii_bus->irq); + mdiobus_free(bp->mii_bus); + unregister_netdev(dev); + free_irq(dev->irq, dev); + iounmap(bp->regs); + free_netdev(dev); + } + + return 0; +} + +static struct platform_driver dnet_driver = { + .probe = dnet_probe, + .remove = __devexit_p(dnet_remove), + .driver = { + .name = "dnet", + }, +}; + +static int __init dnet_init(void) +{ + return platform_driver_register(&dnet_driver); +} + +static void __exit dnet_exit(void) +{ + platform_driver_unregister(&dnet_driver); +} + +module_init(dnet_init); +module_exit(dnet_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Dave DNET Ethernet driver"); +MODULE_AUTHOR("Ilya Yanok , " + "Matteo Vit "); diff --git a/drivers/net/dnet.h b/drivers/net/dnet.h new file mode 100644 index 00000000000..37f5b30fa78 --- /dev/null +++ b/drivers/net/dnet.h @@ -0,0 +1,225 @@ +/* + * Dave DNET Ethernet Controller driver + * + * Copyright (C) 2008 Dave S.r.l. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef _DNET_H +#define _DNET_H + +#define DRV_NAME "dnet" +#define DRV_VERSION "0.9.1" +#define PFX DRV_NAME ": " + +/* Register access macros */ +#define dnet_writel(port, value, reg) \ + writel((value), (port)->regs + DNET_##reg) +#define dnet_readl(port, reg) readl((port)->regs + DNET_##reg) + +/* ALL DNET FIFO REGISTERS */ +#define DNET_RX_LEN_FIFO 0x000 /* RX_LEN_FIFO */ +#define DNET_RX_DATA_FIFO 0x004 /* RX_DATA_FIFO */ +#define DNET_TX_LEN_FIFO 0x008 /* TX_LEN_FIFO */ +#define DNET_TX_DATA_FIFO 0x00C /* TX_DATA_FIFO */ + +/* ALL DNET CONTROL/STATUS REGISTERS OFFSETS */ +#define DNET_VERCAPS 0x100 /* VERCAPS */ +#define DNET_INTR_SRC 0x104 /* INTR_SRC */ +#define DNET_INTR_ENB 0x108 /* INTR_ENB */ +#define DNET_RX_STATUS 0x10C /* RX_STATUS */ +#define DNET_TX_STATUS 0x110 /* TX_STATUS */ +#define DNET_RX_FRAMES_CNT 0x114 /* RX_FRAMES_CNT */ +#define DNET_TX_FRAMES_CNT 0x118 /* TX_FRAMES_CNT */ +#define DNET_RX_FIFO_TH 0x11C /* RX_FIFO_TH */ +#define DNET_TX_FIFO_TH 0x120 /* TX_FIFO_TH */ +#define DNET_SYS_CTL 0x124 /* SYS_CTL */ +#define DNET_PAUSE_TMR 0x128 /* PAUSE_TMR */ +#define DNET_RX_FIFO_WCNT 0x12C /* RX_FIFO_WCNT */ +#define DNET_TX_FIFO_WCNT 0x130 /* TX_FIFO_WCNT */ + +/* ALL DNET MAC REGISTERS */ +#define DNET_MACREG_DATA 0x200 /* Mac-Reg Data */ +#define DNET_MACREG_ADDR 0x204 /* Mac-Reg Addr */ + +/* ALL DNET RX STATISTICS COUNTERS */ +#define DNET_RX_PKT_IGNR_CNT 0x300 +#define DNET_RX_LEN_CHK_ERR_CNT 0x304 +#define DNET_RX_LNG_FRM_CNT 0x308 +#define DNET_RX_SHRT_FRM_CNT 0x30C +#define DNET_RX_IPG_VIOL_CNT 0x310 +#define DNET_RX_CRC_ERR_CNT 0x314 +#define DNET_RX_OK_PKT_CNT 0x318 +#define DNET_RX_CTL_FRM_CNT 0x31C +#define DNET_RX_PAUSE_FRM_CNT 0x320 +#define DNET_RX_MULTICAST_CNT 0x324 +#define DNET_RX_BROADCAST_CNT 0x328 +#define DNET_RX_VLAN_TAG_CNT 0x32C +#define DNET_RX_PRE_SHRINK_CNT 0x330 +#define DNET_RX_DRIB_NIB_CNT 0x334 +#define DNET_RX_UNSUP_OPCD_CNT 0x338 +#define DNET_RX_BYTE_CNT 0x33C + +/* DNET TX STATISTICS COUNTERS */ +#define DNET_TX_UNICAST_CNT 0x400 +#define DNET_TX_PAUSE_FRM_CNT 0x404 +#define DNET_TX_MULTICAST_CNT 0x408 +#define DNET_TX_BRDCAST_CNT 0x40C +#define DNET_TX_VLAN_TAG_CNT 0x410 +#define DNET_TX_BAD_FCS_CNT 0x414 +#define DNET_TX_JUMBO_CNT 0x418 +#define DNET_TX_BYTE_CNT 0x41C + +/* SOME INTERNAL MAC-CORE REGISTER */ +#define DNET_INTERNAL_MODE_REG 0x0 +#define DNET_INTERNAL_RXTX_CONTROL_REG 0x2 +#define DNET_INTERNAL_MAX_PKT_SIZE_REG 0x4 +#define DNET_INTERNAL_IGP_REG 0x8 +#define DNET_INTERNAL_MAC_ADDR_0_REG 0xa +#define DNET_INTERNAL_MAC_ADDR_1_REG 0xc +#define DNET_INTERNAL_MAC_ADDR_2_REG 0xe +#define DNET_INTERNAL_TX_RX_STS_REG 0x12 +#define DNET_INTERNAL_GMII_MNG_CTL_REG 0x14 +#define DNET_INTERNAL_GMII_MNG_DAT_REG 0x16 + +#define DNET_INTERNAL_GMII_MNG_CMD_FIN (1 << 14) + +#define DNET_INTERNAL_WRITE (1 << 31) + +/* MAC-CORE REGISTER FIELDS */ + +/* MAC-CORE MODE REGISTER FIELDS */ +#define DNET_INTERNAL_MODE_GBITEN (1 << 0) +#define DNET_INTERNAL_MODE_FCEN (1 << 1) +#define DNET_INTERNAL_MODE_RXEN (1 << 2) +#define DNET_INTERNAL_MODE_TXEN (1 << 3) + +/* MAC-CORE RXTX CONTROL REGISTER FIELDS */ +#define DNET_INTERNAL_RXTX_CONTROL_RXSHORTFRAME (1 << 8) +#define DNET_INTERNAL_RXTX_CONTROL_RXBROADCAST (1 << 7) +#define DNET_INTERNAL_RXTX_CONTROL_RXMULTICAST (1 << 4) +#define DNET_INTERNAL_RXTX_CONTROL_RXPAUSE (1 << 3) +#define DNET_INTERNAL_RXTX_CONTROL_DISTXFCS (1 << 2) +#define DNET_INTERNAL_RXTX_CONTROL_DISCFXFCS (1 << 1) +#define DNET_INTERNAL_RXTX_CONTROL_ENPROMISC (1 << 0) +#define DNET_INTERNAL_RXTX_CONTROL_DROPCONTROL (1 << 6) +#define DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP (1 << 5) + +/* SYSTEM CONTROL REGISTER FIELDS */ +#define DNET_SYS_CTL_IGNORENEXTPKT (1 << 0) +#define DNET_SYS_CTL_SENDPAUSE (1 << 2) +#define DNET_SYS_CTL_RXFIFOFLUSH (1 << 3) +#define DNET_SYS_CTL_TXFIFOFLUSH (1 << 4) + +/* TX STATUS REGISTER FIELDS */ +#define DNET_TX_STATUS_FIFO_ALMOST_EMPTY (1 << 2) +#define DNET_TX_STATUS_FIFO_ALMOST_FULL (1 << 1) + +/* INTERRUPT SOURCE REGISTER FIELDS */ +#define DNET_INTR_SRC_TX_PKTSENT (1 << 0) +#define DNET_INTR_SRC_TX_FIFOAF (1 << 1) +#define DNET_INTR_SRC_TX_FIFOAE (1 << 2) +#define DNET_INTR_SRC_TX_DISCFRM (1 << 3) +#define DNET_INTR_SRC_TX_FIFOFULL (1 << 4) +#define DNET_INTR_SRC_RX_CMDFIFOAF (1 << 8) +#define DNET_INTR_SRC_RX_CMDFIFOFF (1 << 9) +#define DNET_INTR_SRC_RX_DATAFIFOFF (1 << 10) +#define DNET_INTR_SRC_TX_SUMMARY (1 << 16) +#define DNET_INTR_SRC_RX_SUMMARY (1 << 17) +#define DNET_INTR_SRC_PHY (1 << 19) + +/* INTERRUPT ENABLE REGISTER FIELDS */ +#define DNET_INTR_ENB_TX_PKTSENT (1 << 0) +#define DNET_INTR_ENB_TX_FIFOAF (1 << 1) +#define DNET_INTR_ENB_TX_FIFOAE (1 << 2) +#define DNET_INTR_ENB_TX_DISCFRM (1 << 3) +#define DNET_INTR_ENB_TX_FIFOFULL (1 << 4) +#define DNET_INTR_ENB_RX_PKTRDY (1 << 8) +#define DNET_INTR_ENB_RX_FIFOAF (1 << 9) +#define DNET_INTR_ENB_RX_FIFOERR (1 << 10) +#define DNET_INTR_ENB_RX_ERROR (1 << 11) +#define DNET_INTR_ENB_RX_FIFOFULL (1 << 12) +#define DNET_INTR_ENB_RX_FIFOAE (1 << 13) +#define DNET_INTR_ENB_TX_SUMMARY (1 << 16) +#define DNET_INTR_ENB_RX_SUMMARY (1 << 17) +#define DNET_INTR_ENB_GLOBAL_ENABLE (1 << 18) + +/* default values: + * almost empty = less than one full sized ethernet frame (no jumbo) inside + * the fifo almost full = can write less than one full sized ethernet frame + * (no jumbo) inside the fifo + */ +#define DNET_CFG_TX_FIFO_FULL_THRES 25 +#define DNET_CFG_RX_FIFO_FULL_THRES 20 + +/* + * Capabilities. Used by the driver to know the capabilities that the ethernet + * controller inside the FPGA have. + */ + +#define DNET_HAS_MDIO (1 << 0) +#define DNET_HAS_IRQ (1 << 1) +#define DNET_HAS_GIGABIT (1 << 2) +#define DNET_HAS_DMA (1 << 3) + +#define DNET_HAS_MII (1 << 4) /* or GMII */ +#define DNET_HAS_RMII (1 << 5) /* or RGMII */ + +#define DNET_CAPS_MASK 0xFFFF + +#define DNET_FIFO_SIZE 1024 /* 1K x 32 bit */ +#define DNET_FIFO_TX_DATA_AF_TH (DNET_FIFO_SIZE - 384) /* 384 = 1536 / 4 */ +#define DNET_FIFO_TX_DATA_AE_TH 384 + +#define DNET_FIFO_RX_CMD_AF_TH (1 << 16) /* just one frame inside the FIFO */ + +/* + * Hardware-collected statistics. + */ +struct dnet_stats { + u32 rx_pkt_ignr; + u32 rx_len_chk_err; + u32 rx_lng_frm; + u32 rx_shrt_frm; + u32 rx_ipg_viol; + u32 rx_crc_err; + u32 rx_ok_pkt; + u32 rx_ctl_frm; + u32 rx_pause_frm; + u32 rx_multicast; + u32 rx_broadcast; + u32 rx_vlan_tag; + u32 rx_pre_shrink; + u32 rx_drib_nib; + u32 rx_unsup_opcd; + u32 rx_byte; + u32 tx_unicast; + u32 tx_pause_frm; + u32 tx_multicast; + u32 tx_brdcast; + u32 tx_vlan_tag; + u32 tx_bad_fcs; + u32 tx_jumbo; + u32 tx_byte; +}; + +struct dnet { + void __iomem *regs; + spinlock_t lock; + struct platform_device *pdev; + struct net_device *dev; + struct dnet_stats hw_stats; + unsigned int capabilities; /* read from FPGA */ + struct napi_struct napi; + + /* PHY stuff */ + struct mii_bus *mii_bus; + struct phy_device *phy_dev; + unsigned int link; + unsigned int speed; + unsigned int duplex; +}; + +#endif /* _DNET_H */ -- GitLab From 2c5849ea38fdad477d72dcf1c8c4842db4b33aae Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 11 Mar 2009 23:28:57 -0700 Subject: [PATCH 3116/4982] dnet: Fix warnings on 64-bit. Signed-off-by: David S. Miller --- drivers/net/dnet.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c index 92c3bd3a472..4b96974fe76 100644 --- a/drivers/net/dnet.c +++ b/drivers/net/dnet.c @@ -553,8 +553,8 @@ static int dnet_start_xmit(struct sk_buff *skb, struct net_device *dev) tx_status = dnet_readl(bp, TX_STATUS); - pr_debug("start_xmit: len %u head %p data %p tail %p end %p\n", - skb->len, skb->head, skb->data, skb->tail, skb->end); + pr_debug("start_xmit: len %u head %p data %p\n", + skb->len, skb->head, skb->data); dnet_print_skb(skb); /* frame size (words) */ @@ -564,11 +564,11 @@ static int dnet_start_xmit(struct sk_buff *skb, struct net_device *dev) tx_status = dnet_readl(bp, TX_STATUS); - bufp = (unsigned int *)(((u32) skb->data) & 0xFFFFFFFC); + bufp = (unsigned int *)(((unsigned long) skb->data) & ~0x3UL); wrsz = (u32) skb->len + 3; - wrsz += ((u32) skb->data) & 0x3; + wrsz += ((unsigned long) skb->data) & 0x3; wrsz >>= 2; - tx_cmd = ((((unsigned int)(skb->data)) & 0x03) << 16) | (u32) skb->len; + tx_cmd = ((((unsigned long)(skb->data)) & 0x03) << 16) | (u32) skb->len; /* check if there is enough room for the current frame */ if (wrsz < (DNET_FIFO_SIZE - dnet_readl(bp, TX_FIFO_WCNT))) { -- GitLab From 6b7c5b947c671a96e39f9526a5fd70c178b8dfd1 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Wed, 11 Mar 2009 23:32:03 -0700 Subject: [PATCH 3117/4982] net: Add be2net driver. Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- MAINTAINERS | 9 + drivers/net/Kconfig | 2 + drivers/net/Makefile | 1 + drivers/net/benet/Kconfig | 7 + drivers/net/benet/Makefile | 7 + drivers/net/benet/be.h | 327 ++++++ drivers/net/benet/be_cmds.c | 861 +++++++++++++++ drivers/net/benet/be_cmds.h | 688 ++++++++++++ drivers/net/benet/be_ethtool.c | 362 ++++++ drivers/net/benet/be_hw.h | 211 ++++ drivers/net/benet/be_main.c | 1903 ++++++++++++++++++++++++++++++++ 11 files changed, 4378 insertions(+) create mode 100644 drivers/net/benet/Kconfig create mode 100644 drivers/net/benet/Makefile create mode 100644 drivers/net/benet/be.h create mode 100644 drivers/net/benet/be_cmds.c create mode 100644 drivers/net/benet/be_cmds.h create mode 100644 drivers/net/benet/be_ethtool.c create mode 100644 drivers/net/benet/be_hw.h create mode 100644 drivers/net/benet/be_main.c diff --git a/MAINTAINERS b/MAINTAINERS index 1c2ca1dc66f..43934437511 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3880,6 +3880,15 @@ L: linux-ide@vger.kernel.org T: git kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git S: Supported +SERVER ENGINES 10Gbps NIC - BladeEngine 2 DRIVER +P: Sathya Perla +M: sathyap@serverengines.com +P: Subbu Seetharaman +M: subbus@serverengines.com +L: netdev@vger.kernel.org +W: http://www.serverengines.com +S: Supported + SFC NETWORK DRIVER P: Steve Hodgson P: Ben Hutchings diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 5c28b06dac6..435e2e3a82c 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2630,6 +2630,8 @@ config QLGE source "drivers/net/sfc/Kconfig" +source "drivers/net/benet/Kconfig" + endif # NETDEV_10000 source "drivers/net/tokenring/Kconfig" diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 6d9bba58b9a..471baaff229 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_GIANFAR) += gianfar_driver.o obj-$(CONFIG_TEHUTI) += tehuti.o obj-$(CONFIG_ENIC) += enic/ obj-$(CONFIG_JME) += jme.o +obj-$(CONFIG_BE2NET) += benet/ gianfar_driver-objs := gianfar.o \ gianfar_ethtool.o \ diff --git a/drivers/net/benet/Kconfig b/drivers/net/benet/Kconfig new file mode 100644 index 00000000000..c6934f179c0 --- /dev/null +++ b/drivers/net/benet/Kconfig @@ -0,0 +1,7 @@ +config BE2NET + tristate "ServerEngines' 10Gbps NIC - BladeEngine 2" + depends on PCI && INET + select INET_LRO + help + This driver implements the NIC functionality for ServerEngines' + 10Gbps network adapter - BladeEngine 2. diff --git a/drivers/net/benet/Makefile b/drivers/net/benet/Makefile new file mode 100644 index 00000000000..a60cd805113 --- /dev/null +++ b/drivers/net/benet/Makefile @@ -0,0 +1,7 @@ +# +# Makefile to build the network driver for ServerEngine's BladeEngine. +# + +obj-$(CONFIG_BE2NET) += be2net.o + +be2net-y := be_main.o be_cmds.o be_ethtool.o diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h new file mode 100644 index 00000000000..63d593d5315 --- /dev/null +++ b/drivers/net/benet/be.h @@ -0,0 +1,327 @@ +/* + * Copyright (C) 2005 - 2009 ServerEngines + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. The full GNU General + * Public License is included in this distribution in the file called COPYING. + * + * Contact Information: + * linux-drivers@serverengines.com + * + * ServerEngines + * 209 N. Fair Oaks Ave + * Sunnyvale, CA 94085 + */ + +#ifndef BE_H +#define BE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "be_hw.h" + +#define DRV_VER "2.0.348" +#define DRV_NAME "be2net" +#define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC" +#define DRV_DESC BE_NAME "Driver" + +/* Number of bytes of an RX frame that are copied to skb->data */ +#define BE_HDR_LEN 64 +#define BE_MAX_JUMBO_FRAME_SIZE 9018 +#define BE_MIN_MTU 256 + +#define BE_NUM_VLANS_SUPPORTED 64 +#define BE_MAX_EQD 96 +#define BE_MAX_TX_FRAG_COUNT 30 + +#define EVNT_Q_LEN 1024 +#define TX_Q_LEN 2048 +#define TX_CQ_LEN 1024 +#define RX_Q_LEN 1024 /* Does not support any other value */ +#define RX_CQ_LEN 1024 +#define MCC_Q_LEN 64 /* total size not to exceed 8 pages */ +#define MCC_CQ_LEN 256 + +#define BE_NAPI_WEIGHT 64 +#define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */ +#define RX_FRAGS_REFILL_WM (RX_Q_LEN - MAX_RX_POST) + +#define BE_MAX_LRO_DESCRIPTORS 16 +#define BE_MAX_FRAGS_PER_FRAME 16 + +struct be_dma_mem { + void *va; + dma_addr_t dma; + u32 size; +}; + +struct be_queue_info { + struct be_dma_mem dma_mem; + u16 len; + u16 entry_size; /* Size of an element in the queue */ + u16 id; + u16 tail, head; + bool created; + atomic_t used; /* Number of valid elements in the queue */ +}; + +struct be_ctrl_info { + u8 __iomem *csr; + u8 __iomem *db; /* Door Bell */ + u8 __iomem *pcicfg; /* PCI config space */ + int pci_func; + + /* Mbox used for cmd request/response */ + spinlock_t cmd_lock; /* For serializing cmds to BE card */ + struct be_dma_mem mbox_mem; + /* Mbox mem is adjusted to align to 16 bytes. The allocated addr + * is stored for freeing purpose */ + struct be_dma_mem mbox_mem_alloced; +}; + +#include "be_cmds.h" + +struct be_drvr_stats { + u32 be_tx_reqs; /* number of TX requests initiated */ + u32 be_tx_stops; /* number of times TX Q was stopped */ + u32 be_fwd_reqs; /* number of send reqs through forwarding i/f */ + u32 be_tx_wrbs; /* number of tx WRBs used */ + u32 be_tx_events; /* number of tx completion events */ + u32 be_tx_compl; /* number of tx completion entries processed */ + u64 be_tx_jiffies; + ulong be_tx_bytes; + ulong be_tx_bytes_prev; + u32 be_tx_rate; + + u32 cache_barrier[16]; + + u32 be_ethrx_post_fail;/* number of ethrx buffer alloc failures */ + u32 be_polls; /* number of times NAPI called poll function */ + u32 be_rx_events; /* number of ucast rx completion events */ + u32 be_rx_compl; /* number of rx completion entries processed */ + u32 be_lro_hgram_data[8]; /* histogram of LRO data packets */ + u32 be_lro_hgram_ack[8]; /* histogram of LRO ACKs */ + u64 be_rx_jiffies; + ulong be_rx_bytes; + ulong be_rx_bytes_prev; + u32 be_rx_rate; + /* number of non ether type II frames dropped where + * frame len > length field of Mac Hdr */ + u32 be_802_3_dropped_frames; + /* number of non ether type II frames malformed where + * in frame len < length field of Mac Hdr */ + u32 be_802_3_malformed_frames; + u32 be_rxcp_err; /* Num rx completion entries w/ err set. */ + ulong rx_fps_jiffies; /* jiffies at last FPS calc */ + u32 be_rx_frags; + u32 be_prev_rx_frags; + u32 be_rx_fps; /* Rx frags per second */ +}; + +struct be_stats_obj { + struct be_drvr_stats drvr_stats; + struct net_device_stats net_stats; + struct be_dma_mem cmd; +}; + +struct be_eq_obj { + struct be_queue_info q; + char desc[32]; + + /* Adaptive interrupt coalescing (AIC) info */ + bool enable_aic; + u16 min_eqd; /* in usecs */ + u16 max_eqd; /* in usecs */ + u16 cur_eqd; /* in usecs */ + + struct napi_struct napi; +}; + +struct be_tx_obj { + struct be_queue_info q; + struct be_queue_info cq; + /* Remember the skbs that were transmitted */ + struct sk_buff *sent_skb_list[TX_Q_LEN]; +}; + +/* Struct to remember the pages posted for rx frags */ +struct be_rx_page_info { + struct page *page; + dma_addr_t bus; + u16 page_offset; + bool last_page_user; +}; + +struct be_rx_obj { + struct be_queue_info q; + struct be_queue_info cq; + struct be_rx_page_info page_info_tbl[RX_Q_LEN]; + struct net_lro_mgr lro_mgr; + struct net_lro_desc lro_desc[BE_MAX_LRO_DESCRIPTORS]; +}; + +#define BE_NUM_MSIX_VECTORS 2 /* 1 each for Tx and Rx */ +struct be_adapter { + struct pci_dev *pdev; + struct net_device *netdev; + + /* Mbox, pci config, csr address information */ + struct be_ctrl_info ctrl; + + struct msix_entry msix_entries[BE_NUM_MSIX_VECTORS]; + bool msix_enabled; + bool isr_registered; + + /* TX Rings */ + struct be_eq_obj tx_eq; + struct be_tx_obj tx_obj; + + u32 cache_line_break[8]; + + /* Rx rings */ + struct be_eq_obj rx_eq; + struct be_rx_obj rx_obj; + u32 big_page_size; /* Compounded page size shared by rx wrbs */ + + struct vlan_group *vlan_grp; + u16 num_vlans; + u8 vlan_tag[VLAN_GROUP_ARRAY_LEN]; + + struct be_stats_obj stats; + /* Work queue used to perform periodic tasks like getting statistics */ + struct delayed_work work; + + /* Ethtool knobs and info */ + bool rx_csum; /* BE card must perform rx-checksumming */ + u32 max_rx_coal; + char fw_ver[FW_VER_LEN]; + u32 if_handle; /* Used to configure filtering */ + u32 pmac_id; /* MAC addr handle used by BE card */ + + struct be_link_info link; + u32 port_num; +}; + +extern struct ethtool_ops be_ethtool_ops; + +#define drvr_stats(adapter) (&adapter->stats.drvr_stats) + +#define BE_SET_NETDEV_OPS(netdev, ops) (netdev->netdev_ops = ops) + +static inline u32 MODULO(u16 val, u16 limit) +{ + BUG_ON(limit & (limit - 1)); + return val & (limit - 1); +} + +static inline void index_adv(u16 *index, u16 val, u16 limit) +{ + *index = MODULO((*index + val), limit); +} + +static inline void index_inc(u16 *index, u16 limit) +{ + *index = MODULO((*index + 1), limit); +} + +#define PAGE_SHIFT_4K 12 +#define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K) + +/* Returns number of pages spanned by the data starting at the given addr */ +#define PAGES_4K_SPANNED(_address, size) \ + ((u32)((((size_t)(_address) & (PAGE_SIZE_4K - 1)) + \ + (size) + (PAGE_SIZE_4K - 1)) >> PAGE_SHIFT_4K)) + +/* Byte offset into the page corresponding to given address */ +#define OFFSET_IN_PAGE(addr) \ + ((size_t)(addr) & (PAGE_SIZE_4K-1)) + +/* Returns bit offset within a DWORD of a bitfield */ +#define AMAP_BIT_OFFSET(_struct, field) \ + (((size_t)&(((_struct *)0)->field))%32) + +/* Returns the bit mask of the field that is NOT shifted into location. */ +static inline u32 amap_mask(u32 bitsize) +{ + return (bitsize == 32 ? 0xFFFFFFFF : (1 << bitsize) - 1); +} + +static inline void +amap_set(void *ptr, u32 dw_offset, u32 mask, u32 offset, u32 value) +{ + u32 *dw = (u32 *) ptr + dw_offset; + *dw &= ~(mask << offset); + *dw |= (mask & value) << offset; +} + +#define AMAP_SET_BITS(_struct, field, ptr, val) \ + amap_set(ptr, \ + offsetof(_struct, field)/32, \ + amap_mask(sizeof(((_struct *)0)->field)), \ + AMAP_BIT_OFFSET(_struct, field), \ + val) + +static inline u32 amap_get(void *ptr, u32 dw_offset, u32 mask, u32 offset) +{ + u32 *dw = (u32 *) ptr; + return mask & (*(dw + dw_offset) >> offset); +} + +#define AMAP_GET_BITS(_struct, field, ptr) \ + amap_get(ptr, \ + offsetof(_struct, field)/32, \ + amap_mask(sizeof(((_struct *)0)->field)), \ + AMAP_BIT_OFFSET(_struct, field)) + +#define be_dws_cpu_to_le(wrb, len) swap_dws(wrb, len) +#define be_dws_le_to_cpu(wrb, len) swap_dws(wrb, len) +static inline void swap_dws(void *wrb, int len) +{ +#ifdef __BIG_ENDIAN + u32 *dw = wrb; + BUG_ON(len % 4); + do { + *dw = cpu_to_le32(*dw); + dw++; + len -= 4; + } while (len); +#endif /* __BIG_ENDIAN */ +} + +static inline u8 is_tcp_pkt(struct sk_buff *skb) +{ + u8 val = 0; + + if (ip_hdr(skb)->version == 4) + val = (ip_hdr(skb)->protocol == IPPROTO_TCP); + else if (ip_hdr(skb)->version == 6) + val = (ipv6_hdr(skb)->nexthdr == NEXTHDR_TCP); + + return val; +} + +static inline u8 is_udp_pkt(struct sk_buff *skb) +{ + u8 val = 0; + + if (ip_hdr(skb)->version == 4) + val = (ip_hdr(skb)->protocol == IPPROTO_UDP); + else if (ip_hdr(skb)->version == 6) + val = (ipv6_hdr(skb)->nexthdr == NEXTHDR_UDP); + + return val; +} + +#endif /* BE_H */ diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c new file mode 100644 index 00000000000..d444aed962b --- /dev/null +++ b/drivers/net/benet/be_cmds.c @@ -0,0 +1,861 @@ +/* + * Copyright (C) 2005 - 2009 ServerEngines + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. The full GNU General + * Public License is included in this distribution in the file called COPYING. + * + * Contact Information: + * linux-drivers@serverengines.com + * + * ServerEngines + * 209 N. Fair Oaks Ave + * Sunnyvale, CA 94085 + */ + +#include "be.h" + +static int be_mbox_db_ready_wait(void __iomem *db) +{ + int cnt = 0, wait = 5; + u32 ready; + + do { + ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK; + if (ready) + break; + + if (cnt > 200000) { + printk(KERN_WARNING DRV_NAME + ": mbox_db poll timed out\n"); + return -1; + } + + if (cnt > 50) + wait = 200; + cnt += wait; + udelay(wait); + } while (true); + + return 0; +} + +/* + * Insert the mailbox address into the doorbell in two steps + */ +static int be_mbox_db_ring(struct be_ctrl_info *ctrl) +{ + int status; + u16 compl_status, extd_status; + u32 val = 0; + void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; + struct be_dma_mem *mbox_mem = &ctrl->mbox_mem; + struct be_mcc_mailbox *mbox = mbox_mem->va; + struct be_mcc_cq_entry *cqe = &mbox->cqe; + + memset(cqe, 0, sizeof(*cqe)); + + val &= ~MPU_MAILBOX_DB_RDY_MASK; + val |= MPU_MAILBOX_DB_HI_MASK; + /* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */ + val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; + iowrite32(val, db); + + /* wait for ready to be set */ + status = be_mbox_db_ready_wait(db); + if (status != 0) + return status; + + val = 0; + val &= ~MPU_MAILBOX_DB_RDY_MASK; + val &= ~MPU_MAILBOX_DB_HI_MASK; + /* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */ + val |= (u32)(mbox_mem->dma >> 4) << 2; + iowrite32(val, db); + + status = be_mbox_db_ready_wait(db); + if (status != 0) + return status; + + /* compl entry has been made now */ + be_dws_le_to_cpu(cqe, sizeof(*cqe)); + if (!(cqe->flags & CQE_FLAGS_VALID_MASK)) { + printk(KERN_WARNING DRV_NAME ": ERROR invalid mbox compl\n"); + return -1; + } + + compl_status = (cqe->status >> CQE_STATUS_COMPL_SHIFT) & + CQE_STATUS_COMPL_MASK; + if (compl_status != MCC_STATUS_SUCCESS) { + extd_status = (cqe->status >> CQE_STATUS_EXTD_SHIFT) & + CQE_STATUS_EXTD_MASK; + printk(KERN_WARNING DRV_NAME + ": ERROR in cmd compl. status(compl/extd)=%d/%d\n", + compl_status, extd_status); + } + + return compl_status; +} + +static int be_POST_stage_get(struct be_ctrl_info *ctrl, u16 *stage) +{ + u32 sem = ioread32(ctrl->csr + MPU_EP_SEMAPHORE_OFFSET); + + *stage = sem & EP_SEMAPHORE_POST_STAGE_MASK; + if ((sem >> EP_SEMAPHORE_POST_ERR_SHIFT) & EP_SEMAPHORE_POST_ERR_MASK) + return -1; + else + return 0; +} + +static int be_POST_stage_poll(struct be_ctrl_info *ctrl, u16 poll_stage) +{ + u16 stage, cnt, error; + for (cnt = 0; cnt < 5000; cnt++) { + error = be_POST_stage_get(ctrl, &stage); + if (error) + return -1; + + if (stage == poll_stage) + break; + udelay(1000); + } + if (stage != poll_stage) + return -1; + return 0; +} + + +int be_cmd_POST(struct be_ctrl_info *ctrl) +{ + u16 stage, error; + + error = be_POST_stage_get(ctrl, &stage); + if (error) + goto err; + + if (stage == POST_STAGE_ARMFW_RDY) + return 0; + + if (stage != POST_STAGE_AWAITING_HOST_RDY) + goto err; + + /* On awaiting host rdy, reset and again poll on awaiting host rdy */ + iowrite32(POST_STAGE_BE_RESET, ctrl->csr + MPU_EP_SEMAPHORE_OFFSET); + error = be_POST_stage_poll(ctrl, POST_STAGE_AWAITING_HOST_RDY); + if (error) + goto err; + + /* Now kickoff POST and poll on armfw ready */ + iowrite32(POST_STAGE_HOST_RDY, ctrl->csr + MPU_EP_SEMAPHORE_OFFSET); + error = be_POST_stage_poll(ctrl, POST_STAGE_ARMFW_RDY); + if (error) + goto err; + + return 0; +err: + printk(KERN_WARNING DRV_NAME ": ERROR, stage=%d\n", stage); + return -1; +} + +static inline void *embedded_payload(struct be_mcc_wrb *wrb) +{ + return wrb->payload.embedded_payload; +} + +static inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb) +{ + return &wrb->payload.sgl[0]; +} + +/* Don't touch the hdr after it's prepared */ +static void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len, + bool embedded, u8 sge_cnt) +{ + if (embedded) + wrb->embedded |= MCC_WRB_EMBEDDED_MASK; + else + wrb->embedded |= (sge_cnt & MCC_WRB_SGE_CNT_MASK) << + MCC_WRB_SGE_CNT_SHIFT; + wrb->payload_length = payload_len; + be_dws_cpu_to_le(wrb, 20); +} + +/* Don't touch the hdr after it's prepared */ +static void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, + u8 subsystem, u8 opcode, int cmd_len) +{ + req_hdr->opcode = opcode; + req_hdr->subsystem = subsystem; + req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr)); +} + +static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages, + struct be_dma_mem *mem) +{ + int i, buf_pages = min(PAGES_4K_SPANNED(mem->va, mem->size), max_pages); + u64 dma = (u64)mem->dma; + + for (i = 0; i < buf_pages; i++) { + pages[i].lo = cpu_to_le32(dma & 0xFFFFFFFF); + pages[i].hi = cpu_to_le32(upper_32_bits(dma)); + dma += PAGE_SIZE_4K; + } +} + +/* Converts interrupt delay in microseconds to multiplier value */ +static u32 eq_delay_to_mult(u32 usec_delay) +{ +#define MAX_INTR_RATE 651042 + const u32 round = 10; + u32 multiplier; + + if (usec_delay == 0) + multiplier = 0; + else { + u32 interrupt_rate = 1000000 / usec_delay; + /* Max delay, corresponding to the lowest interrupt rate */ + if (interrupt_rate == 0) + multiplier = 1023; + else { + multiplier = (MAX_INTR_RATE - interrupt_rate) * round; + multiplier /= interrupt_rate; + /* Round the multiplier to the closest value.*/ + multiplier = (multiplier + round/2) / round; + multiplier = min(multiplier, (u32)1023); + } + } + return multiplier; +} + +static inline struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem) +{ + return &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb; +} + +int be_cmd_eq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *eq, int eq_delay) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_eq_create *req = embedded_payload(wrb); + struct be_cmd_resp_eq_create *resp = embedded_payload(wrb); + struct be_dma_mem *q_mem = &eq->dma_mem; + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_EQ_CREATE, sizeof(*req)); + + req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); + + AMAP_SET_BITS(struct amap_eq_context, func, req->context, + ctrl->pci_func); + AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1); + /* 4byte eqe*/ + AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0); + AMAP_SET_BITS(struct amap_eq_context, count, req->context, + __ilog2_u32(eq->len/256)); + AMAP_SET_BITS(struct amap_eq_context, delaymult, req->context, + eq_delay_to_mult(eq_delay)); + be_dws_cpu_to_le(req->context, sizeof(req->context)); + + be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); + + status = be_mbox_db_ring(ctrl); + if (!status) { + eq->id = le16_to_cpu(resp->eq_id); + eq->created = true; + } + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_mac_addr_query(struct be_ctrl_info *ctrl, u8 *mac_addr, + u8 type, bool permanent, u32 if_handle) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_mac_query *req = embedded_payload(wrb); + struct be_cmd_resp_mac_query *resp = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_MAC_QUERY, sizeof(*req)); + + req->type = type; + if (permanent) { + req->permanent = 1; + } else { + req->if_id = cpu_to_le16((u16)if_handle); + req->permanent = 0; + } + + status = be_mbox_db_ring(ctrl); + if (!status) + memcpy(mac_addr, resp->mac.addr, ETH_ALEN); + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_pmac_add(struct be_ctrl_info *ctrl, u8 *mac_addr, + u32 if_id, u32 *pmac_id) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_pmac_add *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_PMAC_ADD, sizeof(*req)); + + req->if_id = cpu_to_le32(if_id); + memcpy(req->mac_address, mac_addr, ETH_ALEN); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_pmac_add *resp = embedded_payload(wrb); + *pmac_id = le32_to_cpu(resp->pmac_id); + } + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_pmac_del(struct be_ctrl_info *ctrl, u32 if_id, u32 pmac_id) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_pmac_del *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_PMAC_DEL, sizeof(*req)); + + req->if_id = cpu_to_le32(if_id); + req->pmac_id = cpu_to_le32(pmac_id); + + status = be_mbox_db_ring(ctrl); + spin_unlock(&ctrl->cmd_lock); + + return status; +} + +int be_cmd_cq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *cq, struct be_queue_info *eq, + bool sol_evts, bool no_delay, int coalesce_wm) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_cq_create *req = embedded_payload(wrb); + struct be_cmd_resp_cq_create *resp = embedded_payload(wrb); + struct be_dma_mem *q_mem = &cq->dma_mem; + void *ctxt = &req->context; + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_CQ_CREATE, sizeof(*req)); + + req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); + + AMAP_SET_BITS(struct amap_cq_context, coalescwm, ctxt, coalesce_wm); + AMAP_SET_BITS(struct amap_cq_context, nodelay, ctxt, no_delay); + AMAP_SET_BITS(struct amap_cq_context, count, ctxt, + __ilog2_u32(cq->len/256)); + AMAP_SET_BITS(struct amap_cq_context, valid, ctxt, 1); + AMAP_SET_BITS(struct amap_cq_context, solevent, ctxt, sol_evts); + AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1); + AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id); + AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 0); + AMAP_SET_BITS(struct amap_cq_context, func, ctxt, ctrl->pci_func); + be_dws_cpu_to_le(ctxt, sizeof(req->context)); + + be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); + + status = be_mbox_db_ring(ctrl); + if (!status) { + cq->id = le16_to_cpu(resp->cq_id); + cq->created = true; + } + spin_unlock(&ctrl->cmd_lock); + + return status; +} + +int be_cmd_txq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *txq, + struct be_queue_info *cq) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_eth_tx_create *req = embedded_payload(wrb); + struct be_dma_mem *q_mem = &txq->dma_mem; + void *ctxt = &req->context; + int status; + u32 len_encoded; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_TX_CREATE, + sizeof(*req)); + + req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); + req->ulp_num = BE_ULP1_NUM; + req->type = BE_ETH_TX_RING_TYPE_STANDARD; + + len_encoded = fls(txq->len); /* log2(len) + 1 */ + if (len_encoded == 16) + len_encoded = 0; + AMAP_SET_BITS(struct amap_tx_context, tx_ring_size, ctxt, len_encoded); + AMAP_SET_BITS(struct amap_tx_context, pci_func_id, ctxt, + ctrl->pci_func); + AMAP_SET_BITS(struct amap_tx_context, ctx_valid, ctxt, 1); + AMAP_SET_BITS(struct amap_tx_context, cq_id_send, ctxt, cq->id); + + be_dws_cpu_to_le(ctxt, sizeof(req->context)); + + be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_eth_tx_create *resp = embedded_payload(wrb); + txq->id = le16_to_cpu(resp->cid); + txq->created = true; + } + spin_unlock(&ctrl->cmd_lock); + + return status; +} + +int be_cmd_rxq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *rxq, u16 cq_id, u16 frag_size, + u16 max_frame_size, u32 if_id, u32 rss) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_eth_rx_create *req = embedded_payload(wrb); + struct be_dma_mem *q_mem = &rxq->dma_mem; + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_RX_CREATE, + sizeof(*req)); + + req->cq_id = cpu_to_le16(cq_id); + req->frag_size = fls(frag_size) - 1; + req->num_pages = 2; + be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); + req->interface_id = cpu_to_le32(if_id); + req->max_frame_size = cpu_to_le16(max_frame_size); + req->rss_queue = cpu_to_le32(rss); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb); + rxq->id = le16_to_cpu(resp->id); + rxq->created = true; + } + spin_unlock(&ctrl->cmd_lock); + + return status; +} + +/* Generic destroyer function for all types of queues */ +int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, + int queue_type) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_q_destroy *req = embedded_payload(wrb); + u8 subsys = 0, opcode = 0; + int status; + + spin_lock(&ctrl->cmd_lock); + + memset(wrb, 0, sizeof(*wrb)); + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + switch (queue_type) { + case QTYPE_EQ: + subsys = CMD_SUBSYSTEM_COMMON; + opcode = OPCODE_COMMON_EQ_DESTROY; + break; + case QTYPE_CQ: + subsys = CMD_SUBSYSTEM_COMMON; + opcode = OPCODE_COMMON_CQ_DESTROY; + break; + case QTYPE_TXQ: + subsys = CMD_SUBSYSTEM_ETH; + opcode = OPCODE_ETH_TX_DESTROY; + break; + case QTYPE_RXQ: + subsys = CMD_SUBSYSTEM_ETH; + opcode = OPCODE_ETH_RX_DESTROY; + break; + default: + printk(KERN_WARNING DRV_NAME ":bad Q type in Q destroy cmd\n"); + status = -1; + goto err; + } + be_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req)); + req->id = cpu_to_le16(q->id); + + status = be_mbox_db_ring(ctrl); +err: + spin_unlock(&ctrl->cmd_lock); + + return status; +} + +/* Create an rx filtering policy configuration on an i/f */ +int be_cmd_if_create(struct be_ctrl_info *ctrl, u32 flags, u8 *mac, + bool pmac_invalid, u32 *if_handle, u32 *pmac_id) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_if_create *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_INTERFACE_CREATE, sizeof(*req)); + + req->capability_flags = cpu_to_le32(flags); + req->enable_flags = cpu_to_le32(flags); + if (!pmac_invalid) + memcpy(req->mac_addr, mac, ETH_ALEN); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_if_create *resp = embedded_payload(wrb); + *if_handle = le32_to_cpu(resp->interface_id); + if (!pmac_invalid) + *pmac_id = le32_to_cpu(resp->pmac_id); + } + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_if_destroy(struct be_ctrl_info *ctrl, u32 interface_id) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_if_destroy *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_INTERFACE_DESTROY, sizeof(*req)); + + req->interface_id = cpu_to_le32(interface_id); + status = be_mbox_db_ring(ctrl); + + spin_unlock(&ctrl->cmd_lock); + + return status; +} + +/* Get stats is a non embedded command: the request is not embedded inside + * WRB but is a separate dma memory block + */ +int be_cmd_get_stats(struct be_ctrl_info *ctrl, struct be_dma_mem *nonemb_cmd) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_get_stats *req = nonemb_cmd->va; + struct be_sge *sge = nonembedded_sgl(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + memset(req, 0, sizeof(*req)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, + OPCODE_ETH_GET_STATISTICS, sizeof(*req)); + sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); + sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); + sge->len = cpu_to_le32(nonemb_cmd->size); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_get_stats *resp = nonemb_cmd->va; + be_dws_le_to_cpu(&resp->hw_stats, sizeof(resp->hw_stats)); + } + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_link_status_query(struct be_ctrl_info *ctrl, + struct be_link_info *link) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_link_status *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req)); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_link_status *resp = embedded_payload(wrb); + link->speed = resp->mac_speed; + link->duplex = resp->mac_duplex; + link->fault = resp->mac_fault; + } else { + link->speed = PHY_LINK_SPEED_ZERO; + } + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_get_fw_ver(struct be_ctrl_info *ctrl, char *fw_ver) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_get_fw_version *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_GET_FW_VERSION, sizeof(*req)); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb); + strncpy(fw_ver, resp->firmware_version_string, FW_VER_LEN); + } + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +/* set the EQ delay interval of an EQ to specified value */ +int be_cmd_modify_eqd(struct be_ctrl_info *ctrl, u32 eq_id, u32 eqd) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_modify_eq_delay *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req)); + + req->num_eq = cpu_to_le32(1); + req->delay[0].eq_id = cpu_to_le32(eq_id); + req->delay[0].phase = 0; + req->delay[0].delay_multiplier = cpu_to_le32(eqd); + + status = be_mbox_db_ring(ctrl); + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_vlan_config(struct be_ctrl_info *ctrl, u32 if_id, u16 *vtag_array, + u32 num, bool untagged, bool promiscuous) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_vlan_config *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req)); + + req->interface_id = if_id; + req->promiscuous = promiscuous; + req->untagged = untagged; + req->num_vlan = num; + if (!promiscuous) { + memcpy(req->normal_vlan, vtag_array, + req->num_vlan * sizeof(vtag_array[0])); + } + + status = be_mbox_db_ring(ctrl); + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, u8 port_num, bool en) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_promiscuous_config *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, + OPCODE_ETH_PROMISCUOUS, sizeof(*req)); + + if (port_num) + req->port1_promiscuous = en; + else + req->port0_promiscuous = en; + + status = be_mbox_db_ring(ctrl); + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_mcast_mac_set(struct be_ctrl_info *ctrl, u32 if_id, u8 *mac_table, + u32 num, bool promiscuous) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_mcast_mac_config *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_MULTICAST_SET, sizeof(*req)); + + req->interface_id = if_id; + req->promiscuous = promiscuous; + if (!promiscuous) { + req->num_mac = cpu_to_le16(num); + if (num) + memcpy(req->mac, mac_table, ETH_ALEN * num); + } + + status = be_mbox_db_ring(ctrl); + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, u32 tx_fc, u32 rx_fc) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_set_flow_control *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_SET_FLOW_CONTROL, sizeof(*req)); + + req->tx_flow_control = cpu_to_le16((u16)tx_fc); + req->rx_flow_control = cpu_to_le16((u16)rx_fc); + + status = be_mbox_db_ring(ctrl); + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_get_flow_control(struct be_ctrl_info *ctrl, u32 *tx_fc, u32 *rx_fc) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_get_flow_control *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_GET_FLOW_CONTROL, sizeof(*req)); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_get_flow_control *resp = + embedded_payload(wrb); + *tx_fc = le16_to_cpu(resp->tx_flow_control); + *rx_fc = le16_to_cpu(resp->rx_flow_control); + } + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_query_fw_cfg(struct be_ctrl_info *ctrl, u32 *port_num) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_query_fw_cfg *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req)); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb); + *port_num = le32_to_cpu(resp->phys_port); + } + + spin_unlock(&ctrl->cmd_lock); + return status; +} diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h new file mode 100644 index 00000000000..e499e2d5b8c --- /dev/null +++ b/drivers/net/benet/be_cmds.h @@ -0,0 +1,688 @@ +/* + * Copyright (C) 2005 - 2009 ServerEngines + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. The full GNU General + * Public License is included in this distribution in the file called COPYING. + * + * Contact Information: + * linux-drivers@serverengines.com + * + * ServerEngines + * 209 N. Fair Oaks Ave + * Sunnyvale, CA 94085 + */ + +/* + * The driver sends configuration and managements command requests to the + * firmware in the BE. These requests are communicated to the processor + * using Work Request Blocks (WRBs) submitted to the MCC-WRB ring or via one + * WRB inside a MAILBOX. + * The commands are serviced by the ARM processor in the BladeEngine's MPU. + */ + +struct be_sge { + u32 pa_lo; + u32 pa_hi; + u32 len; +}; + +#define MCC_WRB_EMBEDDED_MASK 1 /* bit 0 of dword 0*/ +#define MCC_WRB_SGE_CNT_SHIFT 3 /* bits 3 - 7 of dword 0 */ +#define MCC_WRB_SGE_CNT_MASK 0x1F /* bits 3 - 7 of dword 0 */ +struct be_mcc_wrb { + u32 embedded; /* dword 0 */ + u32 payload_length; /* dword 1 */ + u32 tag0; /* dword 2 */ + u32 tag1; /* dword 3 */ + u32 rsvd; /* dword 4 */ + union { + u8 embedded_payload[236]; /* used by embedded cmds */ + struct be_sge sgl[19]; /* used by non-embedded cmds */ + } payload; +}; + +#define CQE_FLAGS_VALID_MASK (1 << 31) +#define CQE_FLAGS_ASYNC_MASK (1 << 30) +#define CQE_FLAGS_COMPLETED_MASK (1 << 28) +#define CQE_FLAGS_CONSUMED_MASK (1 << 27) + +/* Completion Status */ +enum { + MCC_STATUS_SUCCESS = 0x0, +/* The client does not have sufficient privileges to execute the command */ + MCC_STATUS_INSUFFICIENT_PRIVILEGES = 0x1, +/* A parameter in the command was invalid. */ + MCC_STATUS_INVALID_PARAMETER = 0x2, +/* There are insufficient chip resources to execute the command */ + MCC_STATUS_INSUFFICIENT_RESOURCES = 0x3, +/* The command is completing because the queue was getting flushed */ + MCC_STATUS_QUEUE_FLUSHING = 0x4, +/* The command is completing with a DMA error */ + MCC_STATUS_DMA_FAILED = 0x5 +}; + +#define CQE_STATUS_COMPL_MASK 0xFFFF +#define CQE_STATUS_COMPL_SHIFT 0 /* bits 0 - 15 */ +#define CQE_STATUS_EXTD_MASK 0xFFFF +#define CQE_STATUS_EXTD_SHIFT 0 /* bits 0 - 15 */ + +struct be_mcc_cq_entry { + u32 status; /* dword 0 */ + u32 tag0; /* dword 1 */ + u32 tag1; /* dword 2 */ + u32 flags; /* dword 3 */ +}; + +struct be_mcc_mailbox { + struct be_mcc_wrb wrb; + struct be_mcc_cq_entry cqe; +}; + +#define CMD_SUBSYSTEM_COMMON 0x1 +#define CMD_SUBSYSTEM_ETH 0x3 + +#define OPCODE_COMMON_NTWK_MAC_QUERY 1 +#define OPCODE_COMMON_NTWK_MAC_SET 2 +#define OPCODE_COMMON_NTWK_MULTICAST_SET 3 +#define OPCODE_COMMON_NTWK_VLAN_CONFIG 4 +#define OPCODE_COMMON_NTWK_LINK_STATUS_QUERY 5 +#define OPCODE_COMMON_CQ_CREATE 12 +#define OPCODE_COMMON_EQ_CREATE 13 +#define OPCODE_COMMON_MCC_CREATE 21 +#define OPCODE_COMMON_NTWK_RX_FILTER 34 +#define OPCODE_COMMON_GET_FW_VERSION 35 +#define OPCODE_COMMON_SET_FLOW_CONTROL 36 +#define OPCODE_COMMON_GET_FLOW_CONTROL 37 +#define OPCODE_COMMON_SET_FRAME_SIZE 39 +#define OPCODE_COMMON_MODIFY_EQ_DELAY 41 +#define OPCODE_COMMON_FIRMWARE_CONFIG 42 +#define OPCODE_COMMON_NTWK_INTERFACE_CREATE 50 +#define OPCODE_COMMON_NTWK_INTERFACE_DESTROY 51 +#define OPCODE_COMMON_CQ_DESTROY 54 +#define OPCODE_COMMON_EQ_DESTROY 55 +#define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG 58 +#define OPCODE_COMMON_NTWK_PMAC_ADD 59 +#define OPCODE_COMMON_NTWK_PMAC_DEL 60 + +#define OPCODE_ETH_ACPI_CONFIG 2 +#define OPCODE_ETH_PROMISCUOUS 3 +#define OPCODE_ETH_GET_STATISTICS 4 +#define OPCODE_ETH_TX_CREATE 7 +#define OPCODE_ETH_RX_CREATE 8 +#define OPCODE_ETH_TX_DESTROY 9 +#define OPCODE_ETH_RX_DESTROY 10 + +struct be_cmd_req_hdr { + u8 opcode; /* dword 0 */ + u8 subsystem; /* dword 0 */ + u8 port_number; /* dword 0 */ + u8 domain; /* dword 0 */ + u32 timeout; /* dword 1 */ + u32 request_length; /* dword 2 */ + u32 rsvd; /* dword 3 */ +}; + +#define RESP_HDR_INFO_OPCODE_SHIFT 0 /* bits 0 - 7 */ +#define RESP_HDR_INFO_SUBSYS_SHIFT 8 /* bits 8 - 15 */ +struct be_cmd_resp_hdr { + u32 info; /* dword 0 */ + u32 status; /* dword 1 */ + u32 response_length; /* dword 2 */ + u32 actual_resp_len; /* dword 3 */ +}; + +struct phys_addr { + u32 lo; + u32 hi; +}; + +/************************** + * BE Command definitions * + **************************/ + +/* Pseudo amap definition in which each bit of the actual structure is defined + * as a byte: used to calculate offset/shift/mask of each field */ +struct amap_eq_context { + u8 cidx[13]; /* dword 0*/ + u8 rsvd0[3]; /* dword 0*/ + u8 epidx[13]; /* dword 0*/ + u8 valid; /* dword 0*/ + u8 rsvd1; /* dword 0*/ + u8 size; /* dword 0*/ + u8 pidx[13]; /* dword 1*/ + u8 rsvd2[3]; /* dword 1*/ + u8 pd[10]; /* dword 1*/ + u8 count[3]; /* dword 1*/ + u8 solevent; /* dword 1*/ + u8 stalled; /* dword 1*/ + u8 armed; /* dword 1*/ + u8 rsvd3[4]; /* dword 2*/ + u8 func[8]; /* dword 2*/ + u8 rsvd4; /* dword 2*/ + u8 delaymult[10]; /* dword 2*/ + u8 rsvd5[2]; /* dword 2*/ + u8 phase[2]; /* dword 2*/ + u8 nodelay; /* dword 2*/ + u8 rsvd6[4]; /* dword 2*/ + u8 rsvd7[32]; /* dword 3*/ +} __packed; + +struct be_cmd_req_eq_create { + struct be_cmd_req_hdr hdr; + u16 num_pages; /* sword */ + u16 rsvd0; /* sword */ + u8 context[sizeof(struct amap_eq_context) / 8]; + struct phys_addr pages[8]; +} __packed; + +struct be_cmd_resp_eq_create { + struct be_cmd_resp_hdr resp_hdr; + u16 eq_id; /* sword */ + u16 rsvd0; /* sword */ +} __packed; + +/******************** Mac query ***************************/ +enum { + MAC_ADDRESS_TYPE_STORAGE = 0x0, + MAC_ADDRESS_TYPE_NETWORK = 0x1, + MAC_ADDRESS_TYPE_PD = 0x2, + MAC_ADDRESS_TYPE_MANAGEMENT = 0x3 +}; + +struct mac_addr { + u16 size_of_struct; + u8 addr[ETH_ALEN]; +} __packed; + +struct be_cmd_req_mac_query { + struct be_cmd_req_hdr hdr; + u8 type; + u8 permanent; + u16 if_id; +} __packed; + +struct be_cmd_resp_mac_query { + struct be_cmd_resp_hdr hdr; + struct mac_addr mac; +}; + +/******************** PMac Add ***************************/ +struct be_cmd_req_pmac_add { + struct be_cmd_req_hdr hdr; + u32 if_id; + u8 mac_address[ETH_ALEN]; + u8 rsvd0[2]; +} __packed; + +struct be_cmd_resp_pmac_add { + struct be_cmd_resp_hdr hdr; + u32 pmac_id; +}; + +/******************** PMac Del ***************************/ +struct be_cmd_req_pmac_del { + struct be_cmd_req_hdr hdr; + u32 if_id; + u32 pmac_id; +}; + +/******************** Create CQ ***************************/ +/* Pseudo amap definition in which each bit of the actual structure is defined + * as a byte: used to calculate offset/shift/mask of each field */ +struct amap_cq_context { + u8 cidx[11]; /* dword 0*/ + u8 rsvd0; /* dword 0*/ + u8 coalescwm[2]; /* dword 0*/ + u8 nodelay; /* dword 0*/ + u8 epidx[11]; /* dword 0*/ + u8 rsvd1; /* dword 0*/ + u8 count[2]; /* dword 0*/ + u8 valid; /* dword 0*/ + u8 solevent; /* dword 0*/ + u8 eventable; /* dword 0*/ + u8 pidx[11]; /* dword 1*/ + u8 rsvd2; /* dword 1*/ + u8 pd[10]; /* dword 1*/ + u8 eqid[8]; /* dword 1*/ + u8 stalled; /* dword 1*/ + u8 armed; /* dword 1*/ + u8 rsvd3[4]; /* dword 2*/ + u8 func[8]; /* dword 2*/ + u8 rsvd4[20]; /* dword 2*/ + u8 rsvd5[32]; /* dword 3*/ +} __packed; + +struct be_cmd_req_cq_create { + struct be_cmd_req_hdr hdr; + u16 num_pages; + u16 rsvd0; + u8 context[sizeof(struct amap_cq_context) / 8]; + struct phys_addr pages[8]; +} __packed; + +struct be_cmd_resp_cq_create { + struct be_cmd_resp_hdr hdr; + u16 cq_id; + u16 rsvd0; +} __packed; + +/******************** Create TxQ ***************************/ +#define BE_ETH_TX_RING_TYPE_STANDARD 2 +#define BE_ULP1_NUM 1 + +/* Pseudo amap definition in which each bit of the actual structure is defined + * as a byte: used to calculate offset/shift/mask of each field */ +struct amap_tx_context { + u8 rsvd0[16]; /* dword 0 */ + u8 tx_ring_size[4]; /* dword 0 */ + u8 rsvd1[26]; /* dword 0 */ + u8 pci_func_id[8]; /* dword 1 */ + u8 rsvd2[9]; /* dword 1 */ + u8 ctx_valid; /* dword 1 */ + u8 cq_id_send[16]; /* dword 2 */ + u8 rsvd3[16]; /* dword 2 */ + u8 rsvd4[32]; /* dword 3 */ + u8 rsvd5[32]; /* dword 4 */ + u8 rsvd6[32]; /* dword 5 */ + u8 rsvd7[32]; /* dword 6 */ + u8 rsvd8[32]; /* dword 7 */ + u8 rsvd9[32]; /* dword 8 */ + u8 rsvd10[32]; /* dword 9 */ + u8 rsvd11[32]; /* dword 10 */ + u8 rsvd12[32]; /* dword 11 */ + u8 rsvd13[32]; /* dword 12 */ + u8 rsvd14[32]; /* dword 13 */ + u8 rsvd15[32]; /* dword 14 */ + u8 rsvd16[32]; /* dword 15 */ +} __packed; + +struct be_cmd_req_eth_tx_create { + struct be_cmd_req_hdr hdr; + u8 num_pages; + u8 ulp_num; + u8 type; + u8 bound_port; + u8 context[sizeof(struct amap_tx_context) / 8]; + struct phys_addr pages[8]; +} __packed; + +struct be_cmd_resp_eth_tx_create { + struct be_cmd_resp_hdr hdr; + u16 cid; + u16 rsvd0; +} __packed; + +/******************** Create RxQ ***************************/ +struct be_cmd_req_eth_rx_create { + struct be_cmd_req_hdr hdr; + u16 cq_id; + u8 frag_size; + u8 num_pages; + struct phys_addr pages[2]; + u32 interface_id; + u16 max_frame_size; + u16 rsvd0; + u32 rss_queue; +} __packed; + +struct be_cmd_resp_eth_rx_create { + struct be_cmd_resp_hdr hdr; + u16 id; + u8 cpu_id; + u8 rsvd0; +} __packed; + +/******************** Q Destroy ***************************/ +/* Type of Queue to be destroyed */ +enum { + QTYPE_EQ = 1, + QTYPE_CQ, + QTYPE_TXQ, + QTYPE_RXQ +}; + +struct be_cmd_req_q_destroy { + struct be_cmd_req_hdr hdr; + u16 id; + u16 bypass_flush; /* valid only for rx q destroy */ +} __packed; + +/************ I/f Create (it's actually I/f Config Create)**********/ + +/* Capability flags for the i/f */ +enum be_if_flags { + BE_IF_FLAGS_RSS = 0x4, + BE_IF_FLAGS_PROMISCUOUS = 0x8, + BE_IF_FLAGS_BROADCAST = 0x10, + BE_IF_FLAGS_UNTAGGED = 0x20, + BE_IF_FLAGS_ULP = 0x40, + BE_IF_FLAGS_VLAN_PROMISCUOUS = 0x80, + BE_IF_FLAGS_VLAN = 0x100, + BE_IF_FLAGS_MCAST_PROMISCUOUS = 0x200, + BE_IF_FLAGS_PASS_L2_ERRORS = 0x400, + BE_IF_FLAGS_PASS_L3L4_ERRORS = 0x800 +}; + +/* An RX interface is an object with one or more MAC addresses and + * filtering capabilities. */ +struct be_cmd_req_if_create { + struct be_cmd_req_hdr hdr; + u32 version; /* ignore currntly */ + u32 capability_flags; + u32 enable_flags; + u8 mac_addr[ETH_ALEN]; + u8 rsvd0; + u8 pmac_invalid; /* if set, don't attach the mac addr to the i/f */ + u32 vlan_tag; /* not used currently */ +} __packed; + +struct be_cmd_resp_if_create { + struct be_cmd_resp_hdr hdr; + u32 interface_id; + u32 pmac_id; +}; + +/****** I/f Destroy(it's actually I/f Config Destroy )**********/ +struct be_cmd_req_if_destroy { + struct be_cmd_req_hdr hdr; + u32 interface_id; +}; + +/*************** HW Stats Get **********************************/ +struct be_port_rxf_stats { + u32 rx_bytes_lsd; /* dword 0*/ + u32 rx_bytes_msd; /* dword 1*/ + u32 rx_total_frames; /* dword 2*/ + u32 rx_unicast_frames; /* dword 3*/ + u32 rx_multicast_frames; /* dword 4*/ + u32 rx_broadcast_frames; /* dword 5*/ + u32 rx_crc_errors; /* dword 6*/ + u32 rx_alignment_symbol_errors; /* dword 7*/ + u32 rx_pause_frames; /* dword 8*/ + u32 rx_control_frames; /* dword 9*/ + u32 rx_in_range_errors; /* dword 10*/ + u32 rx_out_range_errors; /* dword 11*/ + u32 rx_frame_too_long; /* dword 12*/ + u32 rx_address_match_errors; /* dword 13*/ + u32 rx_vlan_mismatch; /* dword 14*/ + u32 rx_dropped_too_small; /* dword 15*/ + u32 rx_dropped_too_short; /* dword 16*/ + u32 rx_dropped_header_too_small; /* dword 17*/ + u32 rx_dropped_tcp_length; /* dword 18*/ + u32 rx_dropped_runt; /* dword 19*/ + u32 rx_64_byte_packets; /* dword 20*/ + u32 rx_65_127_byte_packets; /* dword 21*/ + u32 rx_128_256_byte_packets; /* dword 22*/ + u32 rx_256_511_byte_packets; /* dword 23*/ + u32 rx_512_1023_byte_packets; /* dword 24*/ + u32 rx_1024_1518_byte_packets; /* dword 25*/ + u32 rx_1519_2047_byte_packets; /* dword 26*/ + u32 rx_2048_4095_byte_packets; /* dword 27*/ + u32 rx_4096_8191_byte_packets; /* dword 28*/ + u32 rx_8192_9216_byte_packets; /* dword 29*/ + u32 rx_ip_checksum_errs; /* dword 30*/ + u32 rx_tcp_checksum_errs; /* dword 31*/ + u32 rx_udp_checksum_errs; /* dword 32*/ + u32 rx_non_rss_packets; /* dword 33*/ + u32 rx_ipv4_packets; /* dword 34*/ + u32 rx_ipv6_packets; /* dword 35*/ + u32 rx_ipv4_bytes_lsd; /* dword 36*/ + u32 rx_ipv4_bytes_msd; /* dword 37*/ + u32 rx_ipv6_bytes_lsd; /* dword 38*/ + u32 rx_ipv6_bytes_msd; /* dword 39*/ + u32 rx_chute1_packets; /* dword 40*/ + u32 rx_chute2_packets; /* dword 41*/ + u32 rx_chute3_packets; /* dword 42*/ + u32 rx_management_packets; /* dword 43*/ + u32 rx_switched_unicast_packets; /* dword 44*/ + u32 rx_switched_multicast_packets; /* dword 45*/ + u32 rx_switched_broadcast_packets; /* dword 46*/ + u32 tx_bytes_lsd; /* dword 47*/ + u32 tx_bytes_msd; /* dword 48*/ + u32 tx_unicastframes; /* dword 49*/ + u32 tx_multicastframes; /* dword 50*/ + u32 tx_broadcastframes; /* dword 51*/ + u32 tx_pauseframes; /* dword 52*/ + u32 tx_controlframes; /* dword 53*/ + u32 tx_64_byte_packets; /* dword 54*/ + u32 tx_65_127_byte_packets; /* dword 55*/ + u32 tx_128_256_byte_packets; /* dword 56*/ + u32 tx_256_511_byte_packets; /* dword 57*/ + u32 tx_512_1023_byte_packets; /* dword 58*/ + u32 tx_1024_1518_byte_packets; /* dword 59*/ + u32 tx_1519_2047_byte_packets; /* dword 60*/ + u32 tx_2048_4095_byte_packets; /* dword 61*/ + u32 tx_4096_8191_byte_packets; /* dword 62*/ + u32 tx_8192_9216_byte_packets; /* dword 63*/ + u32 rx_fifo_overflow; /* dword 64*/ + u32 rx_input_fifo_overflow; /* dword 65*/ +}; + +struct be_rxf_stats { + struct be_port_rxf_stats port[2]; + u32 rx_drops_no_pbuf; /* dword 132*/ + u32 rx_drops_no_txpb; /* dword 133*/ + u32 rx_drops_no_erx_descr; /* dword 134*/ + u32 rx_drops_no_tpre_descr; /* dword 135*/ + u32 management_rx_port_packets; /* dword 136*/ + u32 management_rx_port_bytes; /* dword 137*/ + u32 management_rx_port_pause_frames; /* dword 138*/ + u32 management_rx_port_errors; /* dword 139*/ + u32 management_tx_port_packets; /* dword 140*/ + u32 management_tx_port_bytes; /* dword 141*/ + u32 management_tx_port_pause; /* dword 142*/ + u32 management_rx_port_rxfifo_overflow; /* dword 143*/ + u32 rx_drops_too_many_frags; /* dword 144*/ + u32 rx_drops_invalid_ring; /* dword 145*/ + u32 forwarded_packets; /* dword 146*/ + u32 rx_drops_mtu; /* dword 147*/ + u32 rsvd0[15]; +}; + +struct be_erx_stats { + u32 rx_drops_no_fragments[44]; /* dwordS 0 to 43*/ + u32 debug_wdma_sent_hold; /* dword 44*/ + u32 debug_wdma_pbfree_sent_hold; /* dword 45*/ + u32 debug_wdma_zerobyte_pbfree_sent_hold; /* dword 46*/ + u32 debug_pmem_pbuf_dealloc; /* dword 47*/ +}; + +struct be_hw_stats { + struct be_rxf_stats rxf; + u32 rsvd[48]; + struct be_erx_stats erx; +}; + +struct be_cmd_req_get_stats { + struct be_cmd_req_hdr hdr; + u8 rsvd[sizeof(struct be_hw_stats)]; +}; + +struct be_cmd_resp_get_stats { + struct be_cmd_resp_hdr hdr; + struct be_hw_stats hw_stats; +}; + +struct be_cmd_req_vlan_config { + struct be_cmd_req_hdr hdr; + u8 interface_id; + u8 promiscuous; + u8 untagged; + u8 num_vlan; + u16 normal_vlan[64]; +} __packed; + +struct be_cmd_req_promiscuous_config { + struct be_cmd_req_hdr hdr; + u8 port0_promiscuous; + u8 port1_promiscuous; + u16 rsvd0; +} __packed; + +struct macaddr { + u8 byte[ETH_ALEN]; +}; + +struct be_cmd_req_mcast_mac_config { + struct be_cmd_req_hdr hdr; + u16 num_mac; + u8 promiscuous; + u8 interface_id; + struct macaddr mac[32]; +} __packed; + +static inline struct be_hw_stats * +hw_stats_from_cmd(struct be_cmd_resp_get_stats *cmd) +{ + return &cmd->hw_stats; +} + +/******************** Link Status Query *******************/ +struct be_cmd_req_link_status { + struct be_cmd_req_hdr hdr; + u32 rsvd; +}; + +struct be_link_info { + u8 duplex; + u8 speed; + u8 fault; +}; + +enum { + PHY_LINK_DUPLEX_NONE = 0x0, + PHY_LINK_DUPLEX_HALF = 0x1, + PHY_LINK_DUPLEX_FULL = 0x2 +}; + +enum { + PHY_LINK_SPEED_ZERO = 0x0, /* => No link */ + PHY_LINK_SPEED_10MBPS = 0x1, + PHY_LINK_SPEED_100MBPS = 0x2, + PHY_LINK_SPEED_1GBPS = 0x3, + PHY_LINK_SPEED_10GBPS = 0x4 +}; + +struct be_cmd_resp_link_status { + struct be_cmd_resp_hdr hdr; + u8 physical_port; + u8 mac_duplex; + u8 mac_speed; + u8 mac_fault; + u8 mgmt_mac_duplex; + u8 mgmt_mac_speed; + u16 rsvd0; +} __packed; + +/******************** Get FW Version *******************/ +#define FW_VER_LEN 32 +struct be_cmd_req_get_fw_version { + struct be_cmd_req_hdr hdr; + u8 rsvd0[FW_VER_LEN]; + u8 rsvd1[FW_VER_LEN]; +} __packed; + +struct be_cmd_resp_get_fw_version { + struct be_cmd_resp_hdr hdr; + u8 firmware_version_string[FW_VER_LEN]; + u8 fw_on_flash_version_string[FW_VER_LEN]; +} __packed; + +/******************** Set Flow Contrl *******************/ +struct be_cmd_req_set_flow_control { + struct be_cmd_req_hdr hdr; + u16 tx_flow_control; + u16 rx_flow_control; +} __packed; + +/******************** Get Flow Contrl *******************/ +struct be_cmd_req_get_flow_control { + struct be_cmd_req_hdr hdr; + u32 rsvd; +}; + +struct be_cmd_resp_get_flow_control { + struct be_cmd_resp_hdr hdr; + u16 tx_flow_control; + u16 rx_flow_control; +} __packed; + +/******************** Modify EQ Delay *******************/ +struct be_cmd_req_modify_eq_delay { + struct be_cmd_req_hdr hdr; + u32 num_eq; + struct { + u32 eq_id; + u32 phase; + u32 delay_multiplier; + } delay[8]; +} __packed; + +struct be_cmd_resp_modify_eq_delay { + struct be_cmd_resp_hdr hdr; + u32 rsvd0; +} __packed; + +/******************** Get FW Config *******************/ +struct be_cmd_req_query_fw_cfg { + struct be_cmd_req_hdr hdr; + u32 rsvd[30]; +}; + +struct be_cmd_resp_query_fw_cfg { + struct be_cmd_resp_hdr hdr; + u32 be_config_number; + u32 asic_revision; + u32 phys_port; + u32 function_mode; + u32 rsvd[26]; +}; + +extern int be_pci_fnum_get(struct be_ctrl_info *ctrl); +extern int be_cmd_POST(struct be_ctrl_info *ctrl); +extern int be_cmd_mac_addr_query(struct be_ctrl_info *ctrl, u8 *mac_addr, + u8 type, bool permanent, u32 if_handle); +extern int be_cmd_pmac_add(struct be_ctrl_info *ctrl, u8 *mac_addr, + u32 if_id, u32 *pmac_id); +extern int be_cmd_pmac_del(struct be_ctrl_info *ctrl, u32 if_id, u32 pmac_id); +extern int be_cmd_if_create(struct be_ctrl_info *ctrl, u32 if_flags, u8 *mac, + bool pmac_invalid, u32 *if_handle, u32 *pmac_id); +extern int be_cmd_if_destroy(struct be_ctrl_info *ctrl, u32 if_handle); +extern int be_cmd_eq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *eq, int eq_delay); +extern int be_cmd_cq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *cq, struct be_queue_info *eq, + bool sol_evts, bool no_delay, + int num_cqe_dma_coalesce); +extern int be_cmd_txq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *txq, + struct be_queue_info *cq); +extern int be_cmd_rxq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *rxq, u16 cq_id, + u16 frag_size, u16 max_frame_size, u32 if_id, + u32 rss); +extern int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, + int type); +extern int be_cmd_link_status_query(struct be_ctrl_info *ctrl, + struct be_link_info *link); +extern int be_cmd_reset(struct be_ctrl_info *ctrl); +extern int be_cmd_get_stats(struct be_ctrl_info *ctrl, + struct be_dma_mem *nonemb_cmd); +extern int be_cmd_get_fw_ver(struct be_ctrl_info *ctrl, char *fw_ver); + +extern int be_cmd_modify_eqd(struct be_ctrl_info *ctrl, u32 eq_id, u32 eqd); +extern int be_cmd_vlan_config(struct be_ctrl_info *ctrl, u32 if_id, + u16 *vtag_array, u32 num, bool untagged, + bool promiscuous); +extern int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, + u8 port_num, bool en); +extern int be_cmd_mcast_mac_set(struct be_ctrl_info *ctrl, u32 if_id, + u8 *mac_table, u32 num, bool promiscuous); +extern int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, + u32 tx_fc, u32 rx_fc); +extern int be_cmd_get_flow_control(struct be_ctrl_info *ctrl, + u32 *tx_fc, u32 *rx_fc); +extern int be_cmd_query_fw_cfg(struct be_ctrl_info *ctrl, u32 *port_num); diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c new file mode 100644 index 00000000000..04f4b73fa8d --- /dev/null +++ b/drivers/net/benet/be_ethtool.c @@ -0,0 +1,362 @@ +/* + * Copyright (C) 2005 - 2009 ServerEngines + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. The full GNU General + * Public License is included in this distribution in the file called COPYING. + * + * Contact Information: + * linux-drivers@serverengines.com + * + * ServerEngines + * 209 N. Fair Oaks Ave + * Sunnyvale, CA 94085 + */ + +#include "be.h" +#include + +struct be_ethtool_stat { + char desc[ETH_GSTRING_LEN]; + int type; + int size; + int offset; +}; + +enum {NETSTAT, PORTSTAT, MISCSTAT, DRVSTAT, ERXSTAT}; +#define FIELDINFO(_struct, field) FIELD_SIZEOF(_struct, field), \ + offsetof(_struct, field) +#define NETSTAT_INFO(field) #field, NETSTAT,\ + FIELDINFO(struct net_device_stats,\ + field) +#define DRVSTAT_INFO(field) #field, DRVSTAT,\ + FIELDINFO(struct be_drvr_stats, field) +#define MISCSTAT_INFO(field) #field, MISCSTAT,\ + FIELDINFO(struct be_rxf_stats, field) +#define PORTSTAT_INFO(field) #field, PORTSTAT,\ + FIELDINFO(struct be_port_rxf_stats, \ + field) +#define ERXSTAT_INFO(field) #field, ERXSTAT,\ + FIELDINFO(struct be_erx_stats, field) + +static const struct be_ethtool_stat et_stats[] = { + {NETSTAT_INFO(rx_packets)}, + {NETSTAT_INFO(tx_packets)}, + {NETSTAT_INFO(rx_bytes)}, + {NETSTAT_INFO(tx_bytes)}, + {NETSTAT_INFO(rx_errors)}, + {NETSTAT_INFO(tx_errors)}, + {NETSTAT_INFO(rx_dropped)}, + {NETSTAT_INFO(tx_dropped)}, + {DRVSTAT_INFO(be_tx_reqs)}, + {DRVSTAT_INFO(be_tx_stops)}, + {DRVSTAT_INFO(be_fwd_reqs)}, + {DRVSTAT_INFO(be_tx_wrbs)}, + {DRVSTAT_INFO(be_polls)}, + {DRVSTAT_INFO(be_tx_events)}, + {DRVSTAT_INFO(be_rx_events)}, + {DRVSTAT_INFO(be_tx_compl)}, + {DRVSTAT_INFO(be_rx_compl)}, + {DRVSTAT_INFO(be_ethrx_post_fail)}, + {DRVSTAT_INFO(be_802_3_dropped_frames)}, + {DRVSTAT_INFO(be_802_3_malformed_frames)}, + {DRVSTAT_INFO(be_tx_rate)}, + {DRVSTAT_INFO(be_rx_rate)}, + {PORTSTAT_INFO(rx_unicast_frames)}, + {PORTSTAT_INFO(rx_multicast_frames)}, + {PORTSTAT_INFO(rx_broadcast_frames)}, + {PORTSTAT_INFO(rx_crc_errors)}, + {PORTSTAT_INFO(rx_alignment_symbol_errors)}, + {PORTSTAT_INFO(rx_pause_frames)}, + {PORTSTAT_INFO(rx_control_frames)}, + {PORTSTAT_INFO(rx_in_range_errors)}, + {PORTSTAT_INFO(rx_out_range_errors)}, + {PORTSTAT_INFO(rx_frame_too_long)}, + {PORTSTAT_INFO(rx_address_match_errors)}, + {PORTSTAT_INFO(rx_vlan_mismatch)}, + {PORTSTAT_INFO(rx_dropped_too_small)}, + {PORTSTAT_INFO(rx_dropped_too_short)}, + {PORTSTAT_INFO(rx_dropped_header_too_small)}, + {PORTSTAT_INFO(rx_dropped_tcp_length)}, + {PORTSTAT_INFO(rx_dropped_runt)}, + {PORTSTAT_INFO(rx_fifo_overflow)}, + {PORTSTAT_INFO(rx_input_fifo_overflow)}, + {PORTSTAT_INFO(rx_ip_checksum_errs)}, + {PORTSTAT_INFO(rx_tcp_checksum_errs)}, + {PORTSTAT_INFO(rx_udp_checksum_errs)}, + {PORTSTAT_INFO(rx_non_rss_packets)}, + {PORTSTAT_INFO(rx_ipv4_packets)}, + {PORTSTAT_INFO(rx_ipv6_packets)}, + {PORTSTAT_INFO(tx_unicastframes)}, + {PORTSTAT_INFO(tx_multicastframes)}, + {PORTSTAT_INFO(tx_broadcastframes)}, + {PORTSTAT_INFO(tx_pauseframes)}, + {PORTSTAT_INFO(tx_controlframes)}, + {MISCSTAT_INFO(rx_drops_no_pbuf)}, + {MISCSTAT_INFO(rx_drops_no_txpb)}, + {MISCSTAT_INFO(rx_drops_no_erx_descr)}, + {MISCSTAT_INFO(rx_drops_no_tpre_descr)}, + {MISCSTAT_INFO(rx_drops_too_many_frags)}, + {MISCSTAT_INFO(rx_drops_invalid_ring)}, + {MISCSTAT_INFO(forwarded_packets)}, + {MISCSTAT_INFO(rx_drops_mtu)}, + {ERXSTAT_INFO(rx_drops_no_fragments)}, +}; +#define ETHTOOL_STATS_NUM ARRAY_SIZE(et_stats) + +static void +be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + strcpy(drvinfo->driver, DRV_NAME); + strcpy(drvinfo->version, DRV_VER); + strncpy(drvinfo->fw_version, adapter->fw_ver, FW_VER_LEN); + strcpy(drvinfo->bus_info, pci_name(adapter->pdev)); + drvinfo->testinfo_len = 0; + drvinfo->regdump_len = 0; + drvinfo->eedump_len = 0; +} + +static int +be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_eq_obj *rx_eq = &adapter->rx_eq; + struct be_eq_obj *tx_eq = &adapter->tx_eq; + + coalesce->rx_max_coalesced_frames = adapter->max_rx_coal; + + coalesce->rx_coalesce_usecs = rx_eq->cur_eqd; + coalesce->rx_coalesce_usecs_high = rx_eq->max_eqd; + coalesce->rx_coalesce_usecs_low = rx_eq->min_eqd; + + coalesce->tx_coalesce_usecs = tx_eq->cur_eqd; + coalesce->tx_coalesce_usecs_high = tx_eq->max_eqd; + coalesce->tx_coalesce_usecs_low = tx_eq->min_eqd; + + coalesce->use_adaptive_rx_coalesce = rx_eq->enable_aic; + coalesce->use_adaptive_tx_coalesce = tx_eq->enable_aic; + + return 0; +} + +/* + * This routine is used to set interrup coalescing delay *as well as* + * the number of pkts to coalesce for LRO. + */ +static int +be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_ctrl_info *ctrl = &adapter->ctrl; + struct be_eq_obj *rx_eq = &adapter->rx_eq; + struct be_eq_obj *tx_eq = &adapter->tx_eq; + u32 tx_max, tx_min, tx_cur; + u32 rx_max, rx_min, rx_cur; + int status = 0; + + if (coalesce->use_adaptive_tx_coalesce == 1) + return -EINVAL; + + adapter->max_rx_coal = coalesce->rx_max_coalesced_frames; + if (adapter->max_rx_coal > MAX_SKB_FRAGS) + adapter->max_rx_coal = MAX_SKB_FRAGS - 1; + + /* if AIC is being turned on now, start with an EQD of 0 */ + if (rx_eq->enable_aic == 0 && + coalesce->use_adaptive_rx_coalesce == 1) { + rx_eq->cur_eqd = 0; + } + rx_eq->enable_aic = coalesce->use_adaptive_rx_coalesce; + + rx_max = coalesce->rx_coalesce_usecs_high; + rx_min = coalesce->rx_coalesce_usecs_low; + rx_cur = coalesce->rx_coalesce_usecs; + + tx_max = coalesce->tx_coalesce_usecs_high; + tx_min = coalesce->tx_coalesce_usecs_low; + tx_cur = coalesce->tx_coalesce_usecs; + + if (tx_cur > BE_MAX_EQD) + tx_cur = BE_MAX_EQD; + if (tx_eq->cur_eqd != tx_cur) { + status = be_cmd_modify_eqd(ctrl, tx_eq->q.id, tx_cur); + if (!status) + tx_eq->cur_eqd = tx_cur; + } + + if (rx_eq->enable_aic) { + if (rx_max > BE_MAX_EQD) + rx_max = BE_MAX_EQD; + if (rx_min > rx_max) + rx_min = rx_max; + rx_eq->max_eqd = rx_max; + rx_eq->min_eqd = rx_min; + if (rx_eq->cur_eqd > rx_max) + rx_eq->cur_eqd = rx_max; + if (rx_eq->cur_eqd < rx_min) + rx_eq->cur_eqd = rx_min; + } else { + if (rx_cur > BE_MAX_EQD) + rx_cur = BE_MAX_EQD; + if (rx_eq->cur_eqd != rx_cur) { + status = be_cmd_modify_eqd(ctrl, rx_eq->q.id, rx_cur); + if (!status) + rx_eq->cur_eqd = rx_cur; + } + } + return 0; +} + +static u32 be_get_rx_csum(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + return adapter->rx_csum; +} + +static int be_set_rx_csum(struct net_device *netdev, uint32_t data) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + if (data) + adapter->rx_csum = true; + else + adapter->rx_csum = false; + + return 0; +} + +static void +be_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, uint64_t *data) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_drvr_stats *drvr_stats = &adapter->stats.drvr_stats; + struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats.cmd.va); + struct be_rxf_stats *rxf_stats = &hw_stats->rxf; + struct be_port_rxf_stats *port_stats = + &rxf_stats->port[adapter->port_num]; + struct net_device_stats *net_stats = &adapter->stats.net_stats; + struct be_erx_stats *erx_stats = &hw_stats->erx; + void *p = NULL; + int i; + + for (i = 0; i < ETHTOOL_STATS_NUM; i++) { + switch (et_stats[i].type) { + case NETSTAT: + p = net_stats; + break; + case DRVSTAT: + p = drvr_stats; + break; + case PORTSTAT: + p = port_stats; + break; + case MISCSTAT: + p = rxf_stats; + break; + case ERXSTAT: /* Currently only one ERX stat is provided */ + p = (u32 *)erx_stats + adapter->rx_obj.q.id; + break; + } + + p = (u8 *)p + et_stats[i].offset; + data[i] = (et_stats[i].size == sizeof(u64)) ? + *(u64 *)p: *(u32 *)p; + } + + return; +} + +static void +be_get_stat_strings(struct net_device *netdev, uint32_t stringset, + uint8_t *data) +{ + int i; + switch (stringset) { + case ETH_SS_STATS: + for (i = 0; i < ETHTOOL_STATS_NUM; i++) { + memcpy(data, et_stats[i].desc, ETH_GSTRING_LEN); + data += ETH_GSTRING_LEN; + } + break; + } +} + +static int be_get_stats_count(struct net_device *netdev) +{ + return ETHTOOL_STATS_NUM; +} + +static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) +{ + ecmd->speed = SPEED_10000; + ecmd->duplex = DUPLEX_FULL; + ecmd->autoneg = AUTONEG_DISABLE; + return 0; +} + +static void +be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + ring->rx_max_pending = adapter->rx_obj.q.len; + ring->tx_max_pending = adapter->tx_obj.q.len; + + ring->rx_pending = atomic_read(&adapter->rx_obj.q.used); + ring->tx_pending = atomic_read(&adapter->tx_obj.q.used); +} + +static void +be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + be_cmd_get_flow_control(&adapter->ctrl, &ecmd->tx_pause, + &ecmd->rx_pause); + ecmd->autoneg = AUTONEG_ENABLE; +} + +static int +be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) +{ + struct be_adapter *adapter = netdev_priv(netdev); + int status; + + if (ecmd->autoneg != AUTONEG_ENABLE) + return -EINVAL; + + status = be_cmd_set_flow_control(&adapter->ctrl, ecmd->tx_pause, + ecmd->rx_pause); + if (!status) + dev_warn(&adapter->pdev->dev, "Pause param set failed.\n"); + + return status; +} + +struct ethtool_ops be_ethtool_ops = { + .get_settings = be_get_settings, + .get_drvinfo = be_get_drvinfo, + .get_link = ethtool_op_get_link, + .get_coalesce = be_get_coalesce, + .set_coalesce = be_set_coalesce, + .get_ringparam = be_get_ringparam, + .get_pauseparam = be_get_pauseparam, + .set_pauseparam = be_set_pauseparam, + .get_rx_csum = be_get_rx_csum, + .set_rx_csum = be_set_rx_csum, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, + .get_tso = ethtool_op_get_tso, + .set_tso = ethtool_op_set_tso, + .get_strings = be_get_stat_strings, + .get_stats_count = be_get_stats_count, + .get_ethtool_stats = be_get_ethtool_stats, +}; diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h new file mode 100644 index 00000000000..b132aa4893c --- /dev/null +++ b/drivers/net/benet/be_hw.h @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2005 - 2009 ServerEngines + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. The full GNU General + * Public License is included in this distribution in the file called COPYING. + * + * Contact Information: + * linux-drivers@serverengines.com + * + * ServerEngines + * 209 N. Fair Oaks Ave + * Sunnyvale, CA 94085 + */ + +/********* Mailbox door bell *************/ +/* Used for driver communication with the FW. + * The software must write this register twice to post any command. First, + * it writes the register with hi=1 and the upper bits of the physical address + * for the MAILBOX structure. Software must poll the ready bit until this + * is acknowledged. Then, sotware writes the register with hi=0 with the lower + * bits in the address. It must poll the ready bit until the command is + * complete. Upon completion, the MAILBOX will contain a valid completion + * queue entry. + */ +#define MPU_MAILBOX_DB_OFFSET 0x160 +#define MPU_MAILBOX_DB_RDY_MASK 0x1 /* bit 0 */ +#define MPU_MAILBOX_DB_HI_MASK 0x2 /* bit 1 */ + +#define MPU_EP_CONTROL 0 + +/********** MPU semphore ******************/ +#define MPU_EP_SEMAPHORE_OFFSET 0xac +#define EP_SEMAPHORE_POST_STAGE_MASK 0x0000FFFF +#define EP_SEMAPHORE_POST_ERR_MASK 0x1 +#define EP_SEMAPHORE_POST_ERR_SHIFT 31 +/* MPU semphore POST stage values */ +#define POST_STAGE_AWAITING_HOST_RDY 0x1 /* FW awaiting goahead from host */ +#define POST_STAGE_HOST_RDY 0x2 /* Host has given go-ahed to FW */ +#define POST_STAGE_BE_RESET 0x3 /* Host wants to reset chip */ +#define POST_STAGE_ARMFW_RDY 0xc000 /* FW is done with POST */ + +/********* Memory BAR register ************/ +#define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc +/* Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt + * Disable" may still globally block interrupts in addition to individual + * interrupt masks; a mechanism for the device driver to block all interrupts + * atomically without having to arbitrate for the PCI Interrupt Disable bit + * with the OS. + */ +#define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK (1 << 29) /* bit 29 */ +/* PCI physical function number */ +#define MEMBAR_CTRL_INT_CTRL_PFUNC_MASK 0x7 /* bits 26 - 28 */ +#define MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT 26 + +/********* Event Q door bell *************/ +#define DB_EQ_OFFSET DB_CQ_OFFSET +#define DB_EQ_RING_ID_MASK 0x1FF /* bits 0 - 8 */ +/* Clear the interrupt for this eq */ +#define DB_EQ_CLR_SHIFT (9) /* bit 9 */ +/* Must be 1 */ +#define DB_EQ_EVNT_SHIFT (10) /* bit 10 */ +/* Number of event entries processed */ +#define DB_EQ_NUM_POPPED_SHIFT (16) /* bits 16 - 28 */ +/* Rearm bit */ +#define DB_EQ_REARM_SHIFT (29) /* bit 29 */ + +/********* Compl Q door bell *************/ +#define DB_CQ_OFFSET 0x120 +#define DB_CQ_RING_ID_MASK 0x3FF /* bits 0 - 9 */ +/* Number of event entries processed */ +#define DB_CQ_NUM_POPPED_SHIFT (16) /* bits 16 - 28 */ +/* Rearm bit */ +#define DB_CQ_REARM_SHIFT (29) /* bit 29 */ + +/********** TX ULP door bell *************/ +#define DB_TXULP1_OFFSET 0x60 +#define DB_TXULP_RING_ID_MASK 0x7FF /* bits 0 - 10 */ +/* Number of tx entries posted */ +#define DB_TXULP_NUM_POSTED_SHIFT (16) /* bits 16 - 29 */ +#define DB_TXULP_NUM_POSTED_MASK 0x3FFF /* bits 16 - 29 */ + +/********** RQ(erx) door bell ************/ +#define DB_RQ_OFFSET 0x100 +#define DB_RQ_RING_ID_MASK 0x3FF /* bits 0 - 9 */ +/* Number of rx frags posted */ +#define DB_RQ_NUM_POSTED_SHIFT (24) /* bits 24 - 31 */ + +/* + * BE descriptors: host memory data structures whose formats + * are hardwired in BE silicon. + */ +/* Event Queue Descriptor */ +#define EQ_ENTRY_VALID_MASK 0x1 /* bit 0 */ +#define EQ_ENTRY_RES_ID_MASK 0xFFFF /* bits 16 - 31 */ +#define EQ_ENTRY_RES_ID_SHIFT 16 +struct be_eq_entry { + u32 evt; +}; + +/* TX Queue Descriptor */ +#define ETH_WRB_FRAG_LEN_MASK 0xFFFF +struct be_eth_wrb { + u32 frag_pa_hi; /* dword 0 */ + u32 frag_pa_lo; /* dword 1 */ + u32 rsvd0; /* dword 2 */ + u32 frag_len; /* dword 3: bits 0 - 15 */ +} __packed; + +/* Pseudo amap definition for eth_hdr_wrb in which each bit of the + * actual structure is defined as a byte : used to calculate + * offset/shift/mask of each field */ +struct amap_eth_hdr_wrb { + u8 rsvd0[32]; /* dword 0 */ + u8 rsvd1[32]; /* dword 1 */ + u8 complete; /* dword 2 */ + u8 event; + u8 crc; + u8 forward; + u8 ipsec; + u8 mgmt; + u8 ipcs; + u8 udpcs; + u8 tcpcs; + u8 lso; + u8 vlan; + u8 gso[2]; + u8 num_wrb[5]; + u8 lso_mss[14]; + u8 len[16]; /* dword 3 */ + u8 vlan_tag[16]; +} __packed; + +struct be_eth_hdr_wrb { + u32 dw[4]; +}; + +/* TX Compl Queue Descriptor */ + +/* Pseudo amap definition for eth_tx_compl in which each bit of the + * actual structure is defined as a byte: used to calculate + * offset/shift/mask of each field */ +struct amap_eth_tx_compl { + u8 wrb_index[16]; /* dword 0 */ + u8 ct[2]; /* dword 0 */ + u8 port[2]; /* dword 0 */ + u8 rsvd0[8]; /* dword 0 */ + u8 status[4]; /* dword 0 */ + u8 user_bytes[16]; /* dword 1 */ + u8 nwh_bytes[8]; /* dword 1 */ + u8 lso; /* dword 1 */ + u8 cast_enc[2]; /* dword 1 */ + u8 rsvd1[5]; /* dword 1 */ + u8 rsvd2[32]; /* dword 2 */ + u8 pkts[16]; /* dword 3 */ + u8 ringid[11]; /* dword 3 */ + u8 hash_val[4]; /* dword 3 */ + u8 valid; /* dword 3 */ +} __packed; + +struct be_eth_tx_compl { + u32 dw[4]; +}; + +/* RX Queue Descriptor */ +struct be_eth_rx_d { + u32 fragpa_hi; + u32 fragpa_lo; +}; + +/* RX Compl Queue Descriptor */ + +/* Pseudo amap definition for eth_rx_compl in which each bit of the + * actual structure is defined as a byte: used to calculate + * offset/shift/mask of each field */ +struct amap_eth_rx_compl { + u8 vlan_tag[16]; /* dword 0 */ + u8 pktsize[14]; /* dword 0 */ + u8 port; /* dword 0 */ + u8 ip_opt; /* dword 0 */ + u8 err; /* dword 1 */ + u8 rsshp; /* dword 1 */ + u8 ipf; /* dword 1 */ + u8 tcpf; /* dword 1 */ + u8 udpf; /* dword 1 */ + u8 ipcksm; /* dword 1 */ + u8 l4_cksm; /* dword 1 */ + u8 ip_version; /* dword 1 */ + u8 macdst[6]; /* dword 1 */ + u8 vtp; /* dword 1 */ + u8 rsvd0; /* dword 1 */ + u8 fragndx[10]; /* dword 1 */ + u8 ct[2]; /* dword 1 */ + u8 sw; /* dword 1 */ + u8 numfrags[3]; /* dword 1 */ + u8 rss_flush; /* dword 2 */ + u8 cast_enc[2]; /* dword 2 */ + u8 qnq; /* dword 2 */ + u8 rss_bank; /* dword 2 */ + u8 rsvd1[23]; /* dword 2 */ + u8 lro_pkt; /* dword 2 */ + u8 rsvd2[2]; /* dword 2 */ + u8 valid; /* dword 2 */ + u8 rsshash[32]; /* dword 3 */ +} __packed; + +struct be_eth_rx_compl { + u32 dw[4]; +}; diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c new file mode 100644 index 00000000000..897a63de5bd --- /dev/null +++ b/drivers/net/benet/be_main.c @@ -0,0 +1,1903 @@ +/* + * Copyright (C) 2005 - 2009 ServerEngines + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. The full GNU General + * Public License is included in this distribution in the file called COPYING. + * + * Contact Information: + * linux-drivers@serverengines.com + * + * ServerEngines + * 209 N. Fair Oaks Ave + * Sunnyvale, CA 94085 + */ + +#include "be.h" + +MODULE_VERSION(DRV_VER); +MODULE_DEVICE_TABLE(pci, be_dev_ids); +MODULE_DESCRIPTION(DRV_DESC " " DRV_VER); +MODULE_AUTHOR("ServerEngines Corporation"); +MODULE_LICENSE("GPL"); + +static unsigned int rx_frag_size = 2048; +module_param(rx_frag_size, uint, S_IRUGO); +MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data."); + +#define BE_VENDOR_ID 0x19a2 +#define BE2_DEVICE_ID_1 0x0211 +static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = { + { PCI_DEVICE(BE_VENDOR_ID, BE2_DEVICE_ID_1) }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, be_dev_ids); + +static void be_queue_free(struct be_adapter *adapter, struct be_queue_info *q) +{ + struct be_dma_mem *mem = &q->dma_mem; + if (mem->va) + pci_free_consistent(adapter->pdev, mem->size, + mem->va, mem->dma); +} + +static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q, + u16 len, u16 entry_size) +{ + struct be_dma_mem *mem = &q->dma_mem; + + memset(q, 0, sizeof(*q)); + q->len = len; + q->entry_size = entry_size; + mem->size = len * entry_size; + mem->va = pci_alloc_consistent(adapter->pdev, mem->size, &mem->dma); + if (!mem->va) + return -1; + memset(mem->va, 0, mem->size); + return 0; +} + +static inline void *queue_head_node(struct be_queue_info *q) +{ + return q->dma_mem.va + q->head * q->entry_size; +} + +static inline void *queue_tail_node(struct be_queue_info *q) +{ + return q->dma_mem.va + q->tail * q->entry_size; +} + +static inline void queue_head_inc(struct be_queue_info *q) +{ + index_inc(&q->head, q->len); +} + +static inline void queue_tail_inc(struct be_queue_info *q) +{ + index_inc(&q->tail, q->len); +} + +static void be_intr_set(struct be_ctrl_info *ctrl, bool enable) +{ + u8 __iomem *addr = ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET; + u32 reg = ioread32(addr); + u32 enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; + if (!enabled && enable) { + reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; + } else if (enabled && !enable) { + reg &= ~MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; + } else { + printk(KERN_WARNING DRV_NAME + ": bad value in membar_int_ctrl reg=0x%x\n", reg); + return; + } + iowrite32(reg, addr); +} + +static void be_rxq_notify(struct be_ctrl_info *ctrl, u16 qid, u16 posted) +{ + u32 val = 0; + val |= qid & DB_RQ_RING_ID_MASK; + val |= posted << DB_RQ_NUM_POSTED_SHIFT; + iowrite32(val, ctrl->db + DB_RQ_OFFSET); +} + +static void be_txq_notify(struct be_ctrl_info *ctrl, u16 qid, u16 posted) +{ + u32 val = 0; + val |= qid & DB_TXULP_RING_ID_MASK; + val |= (posted & DB_TXULP_NUM_POSTED_MASK) << DB_TXULP_NUM_POSTED_SHIFT; + iowrite32(val, ctrl->db + DB_TXULP1_OFFSET); +} + +static void be_eq_notify(struct be_ctrl_info *ctrl, u16 qid, + bool arm, bool clear_int, u16 num_popped) +{ + u32 val = 0; + val |= qid & DB_EQ_RING_ID_MASK; + if (arm) + val |= 1 << DB_EQ_REARM_SHIFT; + if (clear_int) + val |= 1 << DB_EQ_CLR_SHIFT; + val |= 1 << DB_EQ_EVNT_SHIFT; + val |= num_popped << DB_EQ_NUM_POPPED_SHIFT; + iowrite32(val, ctrl->db + DB_EQ_OFFSET); +} + +static void be_cq_notify(struct be_ctrl_info *ctrl, u16 qid, + bool arm, u16 num_popped) +{ + u32 val = 0; + val |= qid & DB_CQ_RING_ID_MASK; + if (arm) + val |= 1 << DB_CQ_REARM_SHIFT; + val |= num_popped << DB_CQ_NUM_POPPED_SHIFT; + iowrite32(val, ctrl->db + DB_CQ_OFFSET); +} + + +static int be_mac_addr_set(struct net_device *netdev, void *p) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct sockaddr *addr = p; + int status = 0; + + if (netif_running(netdev)) { + status = be_cmd_pmac_del(&adapter->ctrl, adapter->if_handle, + adapter->pmac_id); + if (status) + return status; + + status = be_cmd_pmac_add(&adapter->ctrl, (u8 *)addr->sa_data, + adapter->if_handle, &adapter->pmac_id); + } + + if (!status) + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + + return status; +} + +static void netdev_stats_update(struct be_adapter *adapter) +{ + struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats.cmd.va); + struct be_rxf_stats *rxf_stats = &hw_stats->rxf; + struct be_port_rxf_stats *port_stats = + &rxf_stats->port[adapter->port_num]; + struct net_device_stats *dev_stats = &adapter->stats.net_stats; + + dev_stats->rx_packets = port_stats->rx_total_frames; + dev_stats->tx_packets = port_stats->tx_unicastframes + + port_stats->tx_multicastframes + port_stats->tx_broadcastframes; + dev_stats->rx_bytes = (u64) port_stats->rx_bytes_msd << 32 | + (u64) port_stats->rx_bytes_lsd; + dev_stats->tx_bytes = (u64) port_stats->tx_bytes_msd << 32 | + (u64) port_stats->tx_bytes_lsd; + + /* bad pkts received */ + dev_stats->rx_errors = port_stats->rx_crc_errors + + port_stats->rx_alignment_symbol_errors + + port_stats->rx_in_range_errors + + port_stats->rx_out_range_errors + port_stats->rx_frame_too_long; + + /* packet transmit problems */ + dev_stats->tx_errors = 0; + + /* no space in linux buffers */ + dev_stats->rx_dropped = 0; + + /* no space available in linux */ + dev_stats->tx_dropped = 0; + + dev_stats->multicast = port_stats->tx_multicastframes; + dev_stats->collisions = 0; + + /* detailed rx errors */ + dev_stats->rx_length_errors = port_stats->rx_in_range_errors + + port_stats->rx_out_range_errors + port_stats->rx_frame_too_long; + /* receive ring buffer overflow */ + dev_stats->rx_over_errors = 0; + dev_stats->rx_crc_errors = port_stats->rx_crc_errors; + + /* frame alignment errors */ + dev_stats->rx_frame_errors = port_stats->rx_alignment_symbol_errors; + /* receiver fifo overrun */ + /* drops_no_pbuf is no per i/f, it's per BE card */ + dev_stats->rx_fifo_errors = port_stats->rx_fifo_overflow + + port_stats->rx_input_fifo_overflow + + rxf_stats->rx_drops_no_pbuf; + /* receiver missed packetd */ + dev_stats->rx_missed_errors = 0; + /* detailed tx_errors */ + dev_stats->tx_aborted_errors = 0; + dev_stats->tx_carrier_errors = 0; + dev_stats->tx_fifo_errors = 0; + dev_stats->tx_heartbeat_errors = 0; + dev_stats->tx_window_errors = 0; +} + +static void be_link_status_update(struct be_adapter *adapter) +{ + struct be_link_info *prev = &adapter->link; + struct be_link_info now = { 0 }; + struct net_device *netdev = adapter->netdev; + + be_cmd_link_status_query(&adapter->ctrl, &now); + + /* If link came up or went down */ + if (now.speed != prev->speed && (now.speed == PHY_LINK_SPEED_ZERO || + prev->speed == PHY_LINK_SPEED_ZERO)) { + if (now.speed == PHY_LINK_SPEED_ZERO) { + netif_stop_queue(netdev); + netif_carrier_off(netdev); + printk(KERN_INFO "%s: Link down\n", netdev->name); + } else { + netif_start_queue(netdev); + netif_carrier_on(netdev); + printk(KERN_INFO "%s: Link up\n", netdev->name); + } + } + *prev = now; +} + +/* Update the EQ delay n BE based on the RX frags consumed / sec */ +static void be_rx_eqd_update(struct be_adapter *adapter) +{ + u32 eqd; + struct be_ctrl_info *ctrl = &adapter->ctrl; + struct be_eq_obj *rx_eq = &adapter->rx_eq; + struct be_drvr_stats *stats = &adapter->stats.drvr_stats; + + /* Update once a second */ + if (((jiffies - stats->rx_fps_jiffies) < HZ) || rx_eq->enable_aic == 0) + return; + + stats->be_rx_fps = (stats->be_rx_frags - stats->be_prev_rx_frags) / + ((jiffies - stats->rx_fps_jiffies) / HZ); + + stats->rx_fps_jiffies = jiffies; + stats->be_prev_rx_frags = stats->be_rx_frags; + eqd = stats->be_rx_fps / 110000; + eqd = eqd << 3; + if (eqd > rx_eq->max_eqd) + eqd = rx_eq->max_eqd; + if (eqd < rx_eq->min_eqd) + eqd = rx_eq->min_eqd; + if (eqd < 10) + eqd = 0; + if (eqd != rx_eq->cur_eqd) + be_cmd_modify_eqd(ctrl, rx_eq->q.id, eqd); + + rx_eq->cur_eqd = eqd; +} + +static void be_worker(struct work_struct *work) +{ + struct be_adapter *adapter = + container_of(work, struct be_adapter, work.work); + int status; + + /* Check link */ + be_link_status_update(adapter); + + /* Get Stats */ + status = be_cmd_get_stats(&adapter->ctrl, &adapter->stats.cmd); + if (!status) + netdev_stats_update(adapter); + + /* Set EQ delay */ + be_rx_eqd_update(adapter); + + schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); +} + +static struct net_device_stats *be_get_stats(struct net_device *dev) +{ + struct be_adapter *adapter = netdev_priv(dev); + + return &adapter->stats.net_stats; +} + +static void be_tx_stats_update(struct be_adapter *adapter, + u32 wrb_cnt, u32 copied, bool stopped) +{ + struct be_drvr_stats *stats = &adapter->stats.drvr_stats; + stats->be_tx_reqs++; + stats->be_tx_wrbs += wrb_cnt; + stats->be_tx_bytes += copied; + if (stopped) + stats->be_tx_stops++; + + /* Update tx rate once in two seconds */ + if ((jiffies - stats->be_tx_jiffies) > 2 * HZ) { + u32 r; + r = (stats->be_tx_bytes - stats->be_tx_bytes_prev) / + ((u32) (jiffies - stats->be_tx_jiffies) / HZ); + r = (r / 1000000); /* M bytes/s */ + stats->be_tx_rate = (r * 8); /* M bits/s */ + stats->be_tx_jiffies = jiffies; + stats->be_tx_bytes_prev = stats->be_tx_bytes; + } +} + +/* Determine number of WRB entries needed to xmit data in an skb */ +static u32 wrb_cnt_for_skb(struct sk_buff *skb, bool *dummy) +{ + int cnt = 0; + while (skb) { + if (skb->len > skb->data_len) + cnt++; + cnt += skb_shinfo(skb)->nr_frags; + skb = skb_shinfo(skb)->frag_list; + } + /* to account for hdr wrb */ + cnt++; + if (cnt & 1) { + /* add a dummy to make it an even num */ + cnt++; + *dummy = true; + } else + *dummy = false; + BUG_ON(cnt > BE_MAX_TX_FRAG_COUNT); + return cnt; +} + +static inline void wrb_fill(struct be_eth_wrb *wrb, u64 addr, int len) +{ + wrb->frag_pa_hi = upper_32_bits(addr); + wrb->frag_pa_lo = addr & 0xFFFFFFFF; + wrb->frag_len = len & ETH_WRB_FRAG_LEN_MASK; +} + +static void wrb_fill_hdr(struct be_eth_hdr_wrb *hdr, struct sk_buff *skb, + bool vlan, u32 wrb_cnt, u32 len) +{ + memset(hdr, 0, sizeof(*hdr)); + + AMAP_SET_BITS(struct amap_eth_hdr_wrb, crc, hdr, 1); + + if (skb_shinfo(skb)->gso_segs > 1 && skb_shinfo(skb)->gso_size) { + AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso, hdr, 1); + AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso_mss, + hdr, skb_shinfo(skb)->gso_size); + } else if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (is_tcp_pkt(skb)) + AMAP_SET_BITS(struct amap_eth_hdr_wrb, tcpcs, hdr, 1); + else if (is_udp_pkt(skb)) + AMAP_SET_BITS(struct amap_eth_hdr_wrb, udpcs, hdr, 1); + } + + if (vlan && vlan_tx_tag_present(skb)) { + AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan, hdr, 1); + AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan_tag, + hdr, vlan_tx_tag_get(skb)); + } + + AMAP_SET_BITS(struct amap_eth_hdr_wrb, event, hdr, 1); + AMAP_SET_BITS(struct amap_eth_hdr_wrb, complete, hdr, 1); + AMAP_SET_BITS(struct amap_eth_hdr_wrb, num_wrb, hdr, wrb_cnt); + AMAP_SET_BITS(struct amap_eth_hdr_wrb, len, hdr, len); +} + + +static int make_tx_wrbs(struct be_adapter *adapter, + struct sk_buff *skb, u32 wrb_cnt, bool dummy_wrb) +{ + u64 busaddr; + u32 i, copied = 0; + struct pci_dev *pdev = adapter->pdev; + struct sk_buff *first_skb = skb; + struct be_queue_info *txq = &adapter->tx_obj.q; + struct be_eth_wrb *wrb; + struct be_eth_hdr_wrb *hdr; + + atomic_add(wrb_cnt, &txq->used); + hdr = queue_head_node(txq); + queue_head_inc(txq); + + while (skb) { + if (skb->len > skb->data_len) { + int len = skb->len - skb->data_len; + busaddr = pci_map_single(pdev, skb->data, len, + PCI_DMA_TODEVICE); + wrb = queue_head_node(txq); + wrb_fill(wrb, busaddr, len); + be_dws_cpu_to_le(wrb, sizeof(*wrb)); + queue_head_inc(txq); + copied += len; + } + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + struct skb_frag_struct *frag = + &skb_shinfo(skb)->frags[i]; + busaddr = pci_map_page(pdev, frag->page, + frag->page_offset, + frag->size, PCI_DMA_TODEVICE); + wrb = queue_head_node(txq); + wrb_fill(wrb, busaddr, frag->size); + be_dws_cpu_to_le(wrb, sizeof(*wrb)); + queue_head_inc(txq); + copied += frag->size; + } + skb = skb_shinfo(skb)->frag_list; + } + + if (dummy_wrb) { + wrb = queue_head_node(txq); + wrb_fill(wrb, 0, 0); + be_dws_cpu_to_le(wrb, sizeof(*wrb)); + queue_head_inc(txq); + } + + wrb_fill_hdr(hdr, first_skb, adapter->vlan_grp ? true : false, + wrb_cnt, copied); + be_dws_cpu_to_le(hdr, sizeof(*hdr)); + + return copied; +} + +static int be_xmit(struct sk_buff *skb, struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_tx_obj *tx_obj = &adapter->tx_obj; + struct be_queue_info *txq = &tx_obj->q; + u32 wrb_cnt = 0, copied = 0; + u32 start = txq->head; + bool dummy_wrb, stopped = false; + + wrb_cnt = wrb_cnt_for_skb(skb, &dummy_wrb); + + copied = make_tx_wrbs(adapter, skb, wrb_cnt, dummy_wrb); + + /* record the sent skb in the sent_skb table */ + BUG_ON(tx_obj->sent_skb_list[start]); + tx_obj->sent_skb_list[start] = skb; + + /* Ensure that txq has space for the next skb; Else stop the queue + * *BEFORE* ringing the tx doorbell, so that we serialze the + * tx compls of the current transmit which'll wake up the queue + */ + if ((BE_MAX_TX_FRAG_COUNT + atomic_read(&txq->used)) >= txq->len) { + netif_stop_queue(netdev); + stopped = true; + } + + be_txq_notify(&adapter->ctrl, txq->id, wrb_cnt); + + netdev->trans_start = jiffies; + + be_tx_stats_update(adapter, wrb_cnt, copied, stopped); + return NETDEV_TX_OK; +} + +static int be_change_mtu(struct net_device *netdev, int new_mtu) +{ + struct be_adapter *adapter = netdev_priv(netdev); + if (new_mtu < BE_MIN_MTU || + new_mtu > BE_MAX_JUMBO_FRAME_SIZE) { + dev_info(&adapter->pdev->dev, + "MTU must be between %d and %d bytes\n", + BE_MIN_MTU, BE_MAX_JUMBO_FRAME_SIZE); + return -EINVAL; + } + dev_info(&adapter->pdev->dev, "MTU changed from %d to %d bytes\n", + netdev->mtu, new_mtu); + netdev->mtu = new_mtu; + return 0; +} + +/* + * if there are BE_NUM_VLANS_SUPPORTED or lesser number of VLANS configured, + * program them in BE. If more than BE_NUM_VLANS_SUPPORTED are configured, + * set the BE in promiscuous VLAN mode. + */ +static void be_vids_config(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + u16 vtag[BE_NUM_VLANS_SUPPORTED]; + u16 ntags = 0, i; + + if (adapter->num_vlans <= BE_NUM_VLANS_SUPPORTED) { + /* Construct VLAN Table to give to HW */ + for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { + if (adapter->vlan_tag[i]) { + vtag[ntags] = cpu_to_le16(i); + ntags++; + } + } + be_cmd_vlan_config(&adapter->ctrl, adapter->if_handle, + vtag, ntags, 1, 0); + } else { + be_cmd_vlan_config(&adapter->ctrl, adapter->if_handle, + NULL, 0, 1, 1); + } +} + +static void be_vlan_register(struct net_device *netdev, struct vlan_group *grp) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_eq_obj *rx_eq = &adapter->rx_eq; + struct be_eq_obj *tx_eq = &adapter->tx_eq; + struct be_ctrl_info *ctrl = &adapter->ctrl; + + be_eq_notify(ctrl, rx_eq->q.id, false, false, 0); + be_eq_notify(ctrl, tx_eq->q.id, false, false, 0); + adapter->vlan_grp = grp; + be_eq_notify(ctrl, rx_eq->q.id, true, false, 0); + be_eq_notify(ctrl, tx_eq->q.id, true, false, 0); +} + +static void be_vlan_add_vid(struct net_device *netdev, u16 vid) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + adapter->num_vlans++; + adapter->vlan_tag[vid] = 1; + + be_vids_config(netdev); +} + +static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + adapter->num_vlans--; + adapter->vlan_tag[vid] = 0; + + vlan_group_set_device(adapter->vlan_grp, vid, NULL); + be_vids_config(netdev); +} + +static void be_set_multicast_filter(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct dev_mc_list *mc_ptr; + u8 mac_addr[32][ETH_ALEN]; + int i = 0; + + if (netdev->flags & IFF_ALLMULTI) { + /* set BE in Multicast promiscuous */ + be_cmd_mcast_mac_set(&adapter->ctrl, + adapter->if_handle, NULL, 0, true); + return; + } + + for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { + memcpy(&mac_addr[i][0], mc_ptr->dmi_addr, ETH_ALEN); + if (++i >= 32) { + be_cmd_mcast_mac_set(&adapter->ctrl, + adapter->if_handle, &mac_addr[0][0], i, false); + i = 0; + } + + } + + if (i) { + /* reset the promiscuous mode also. */ + be_cmd_mcast_mac_set(&adapter->ctrl, + adapter->if_handle, &mac_addr[0][0], i, false); + } +} + +static void be_set_multicast_list(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + if (netdev->flags & IFF_PROMISC) { + be_cmd_promiscuous_config(&adapter->ctrl, adapter->port_num, 1); + } else { + be_cmd_promiscuous_config(&adapter->ctrl, adapter->port_num, 0); + be_set_multicast_filter(netdev); + } +} + +static void be_rx_rate_update(struct be_adapter *adapter, u32 pktsize, + u16 numfrags) +{ + struct be_drvr_stats *stats = &adapter->stats.drvr_stats; + u32 rate; + + stats->be_rx_compl++; + stats->be_rx_frags += numfrags; + stats->be_rx_bytes += pktsize; + + /* Update the rate once in two seconds */ + if ((jiffies - stats->be_rx_jiffies) < 2 * HZ) + return; + + rate = (stats->be_rx_bytes - stats->be_rx_bytes_prev) / + ((u32) (jiffies - stats->be_rx_jiffies) / HZ); + rate = (rate / 1000000); /* MB/Sec */ + stats->be_rx_rate = (rate * 8); /* Mega Bits/Sec */ + stats->be_rx_jiffies = jiffies; + stats->be_rx_bytes_prev = stats->be_rx_bytes; +} + +static struct be_rx_page_info * +get_rx_page_info(struct be_adapter *adapter, u16 frag_idx) +{ + struct be_rx_page_info *rx_page_info; + struct be_queue_info *rxq = &adapter->rx_obj.q; + + rx_page_info = &adapter->rx_obj.page_info_tbl[frag_idx]; + BUG_ON(!rx_page_info->page); + + if (rx_page_info->last_page_user) + pci_unmap_page(adapter->pdev, pci_unmap_addr(rx_page_info, bus), + adapter->big_page_size, PCI_DMA_FROMDEVICE); + + atomic_dec(&rxq->used); + return rx_page_info; +} + +/* Throwaway the data in the Rx completion */ +static void be_rx_compl_discard(struct be_adapter *adapter, + struct be_eth_rx_compl *rxcp) +{ + struct be_queue_info *rxq = &adapter->rx_obj.q; + struct be_rx_page_info *page_info; + u16 rxq_idx, i, num_rcvd; + + rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); + num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); + + for (i = 0; i < num_rcvd; i++) { + page_info = get_rx_page_info(adapter, rxq_idx); + put_page(page_info->page); + memset(page_info, 0, sizeof(*page_info)); + index_inc(&rxq_idx, rxq->len); + } +} + +/* + * skb_fill_rx_data forms a complete skb for an ether frame + * indicated by rxcp. + */ +static void skb_fill_rx_data(struct be_adapter *adapter, + struct sk_buff *skb, struct be_eth_rx_compl *rxcp) +{ + struct be_queue_info *rxq = &adapter->rx_obj.q; + struct be_rx_page_info *page_info; + u16 rxq_idx, i, num_rcvd; + u32 pktsize, hdr_len, curr_frag_len; + u8 *start; + + rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); + pktsize = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); + num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); + + page_info = get_rx_page_info(adapter, rxq_idx); + + start = page_address(page_info->page) + page_info->page_offset; + prefetch(start); + + /* Copy data in the first descriptor of this completion */ + curr_frag_len = min(pktsize, rx_frag_size); + + /* Copy the header portion into skb_data */ + hdr_len = min((u32)BE_HDR_LEN, curr_frag_len); + memcpy(skb->data, start, hdr_len); + skb->len = curr_frag_len; + if (curr_frag_len <= BE_HDR_LEN) { /* tiny packet */ + /* Complete packet has now been moved to data */ + put_page(page_info->page); + skb->data_len = 0; + skb->tail += curr_frag_len; + } else { + skb_shinfo(skb)->nr_frags = 1; + skb_shinfo(skb)->frags[0].page = page_info->page; + skb_shinfo(skb)->frags[0].page_offset = + page_info->page_offset + hdr_len; + skb_shinfo(skb)->frags[0].size = curr_frag_len - hdr_len; + skb->data_len = curr_frag_len - hdr_len; + skb->tail += hdr_len; + } + memset(page_info, 0, sizeof(*page_info)); + + if (pktsize <= rx_frag_size) { + BUG_ON(num_rcvd != 1); + return; + } + + /* More frags present for this completion */ + pktsize -= curr_frag_len; /* account for above copied frag */ + for (i = 1; i < num_rcvd; i++) { + index_inc(&rxq_idx, rxq->len); + page_info = get_rx_page_info(adapter, rxq_idx); + + curr_frag_len = min(pktsize, rx_frag_size); + + skb_shinfo(skb)->frags[i].page = page_info->page; + skb_shinfo(skb)->frags[i].page_offset = page_info->page_offset; + skb_shinfo(skb)->frags[i].size = curr_frag_len; + skb->len += curr_frag_len; + skb->data_len += curr_frag_len; + skb_shinfo(skb)->nr_frags++; + pktsize -= curr_frag_len; + + memset(page_info, 0, sizeof(*page_info)); + } + + be_rx_rate_update(adapter, pktsize, num_rcvd); + return; +} + +/* Process the RX completion indicated by rxcp when LRO is disabled */ +static void be_rx_compl_process(struct be_adapter *adapter, + struct be_eth_rx_compl *rxcp) +{ + struct sk_buff *skb; + u32 vtp, vid; + int l4_cksm; + + l4_cksm = AMAP_GET_BITS(struct amap_eth_rx_compl, l4_cksm, rxcp); + vtp = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); + + skb = netdev_alloc_skb(adapter->netdev, BE_HDR_LEN + NET_IP_ALIGN); + if (!skb) { + if (net_ratelimit()) + dev_warn(&adapter->pdev->dev, "skb alloc failed\n"); + be_rx_compl_discard(adapter, rxcp); + return; + } + + skb_reserve(skb, NET_IP_ALIGN); + + skb_fill_rx_data(adapter, skb, rxcp); + + if (l4_cksm && adapter->rx_csum) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; + + skb->truesize = skb->len + sizeof(struct sk_buff); + skb->protocol = eth_type_trans(skb, adapter->netdev); + skb->dev = adapter->netdev; + + if (vtp) { + if (!adapter->vlan_grp || adapter->num_vlans == 0) { + kfree_skb(skb); + return; + } + vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp); + vid = be16_to_cpu(vid); + vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, vid); + } else { + netif_receive_skb(skb); + } + + adapter->netdev->last_rx = jiffies; + + return; +} + +/* Process the RX completion indicated by rxcp when LRO is enabled */ +static void be_rx_compl_process_lro(struct be_adapter *adapter, + struct be_eth_rx_compl *rxcp) +{ + struct be_rx_page_info *page_info; + struct skb_frag_struct rx_frags[BE_MAX_FRAGS_PER_FRAME]; + struct be_queue_info *rxq = &adapter->rx_obj.q; + u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len; + u16 i, rxq_idx = 0, vid; + + num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); + pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); + vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); + rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); + + remaining = pkt_size; + for (i = 0; i < num_rcvd; i++) { + page_info = get_rx_page_info(adapter, rxq_idx); + + curr_frag_len = min(remaining, rx_frag_size); + + rx_frags[i].page = page_info->page; + rx_frags[i].page_offset = page_info->page_offset; + rx_frags[i].size = curr_frag_len; + remaining -= curr_frag_len; + + index_inc(&rxq_idx, rxq->len); + + memset(page_info, 0, sizeof(*page_info)); + } + + if (likely(!vlanf)) { + lro_receive_frags(&adapter->rx_obj.lro_mgr, rx_frags, pkt_size, + pkt_size, NULL, 0); + } else { + vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp); + vid = be16_to_cpu(vid); + + if (!adapter->vlan_grp || adapter->num_vlans == 0) + return; + + lro_vlan_hwaccel_receive_frags(&adapter->rx_obj.lro_mgr, + rx_frags, pkt_size, pkt_size, adapter->vlan_grp, + vid, NULL, 0); + } + + be_rx_rate_update(adapter, pkt_size, num_rcvd); + return; +} + +static struct be_eth_rx_compl *be_rx_compl_get(struct be_adapter *adapter) +{ + struct be_eth_rx_compl *rxcp = queue_tail_node(&adapter->rx_obj.cq); + + if (rxcp->dw[offsetof(struct amap_eth_rx_compl, valid) / 32] == 0) + return NULL; + + be_dws_le_to_cpu(rxcp, sizeof(*rxcp)); + + rxcp->dw[offsetof(struct amap_eth_rx_compl, valid) / 32] = 0; + + queue_tail_inc(&adapter->rx_obj.cq); + return rxcp; +} + +static inline struct page *be_alloc_pages(u32 size) +{ + gfp_t alloc_flags = GFP_ATOMIC; + u32 order = get_order(size); + if (order > 0) + alloc_flags |= __GFP_COMP; + return alloc_pages(alloc_flags, order); +} + +/* + * Allocate a page, split it to fragments of size rx_frag_size and post as + * receive buffers to BE + */ +static void be_post_rx_frags(struct be_adapter *adapter) +{ + struct be_rx_page_info *page_info_tbl = adapter->rx_obj.page_info_tbl; + struct be_rx_page_info *page_info = NULL; + struct be_queue_info *rxq = &adapter->rx_obj.q; + struct page *pagep = NULL; + struct be_eth_rx_d *rxd; + u64 page_dmaaddr = 0, frag_dmaaddr; + u32 posted, page_offset = 0; + + + page_info = &page_info_tbl[rxq->head]; + for (posted = 0; posted < MAX_RX_POST && !page_info->page; posted++) { + if (!pagep) { + pagep = be_alloc_pages(adapter->big_page_size); + if (unlikely(!pagep)) { + drvr_stats(adapter)->be_ethrx_post_fail++; + break; + } + page_dmaaddr = pci_map_page(adapter->pdev, pagep, 0, + adapter->big_page_size, + PCI_DMA_FROMDEVICE); + page_info->page_offset = 0; + } else { + get_page(pagep); + page_info->page_offset = page_offset + rx_frag_size; + } + page_offset = page_info->page_offset; + page_info->page = pagep; + pci_unmap_addr_set(page_info, bus, page_dmaaddr); + frag_dmaaddr = page_dmaaddr + page_info->page_offset; + + rxd = queue_head_node(rxq); + rxd->fragpa_lo = cpu_to_le32(frag_dmaaddr & 0xFFFFFFFF); + rxd->fragpa_hi = cpu_to_le32(upper_32_bits(frag_dmaaddr)); + queue_head_inc(rxq); + + /* Any space left in the current big page for another frag? */ + if ((page_offset + rx_frag_size + rx_frag_size) > + adapter->big_page_size) { + pagep = NULL; + page_info->last_page_user = true; + } + page_info = &page_info_tbl[rxq->head]; + } + if (pagep) + page_info->last_page_user = true; + + if (posted) { + be_rxq_notify(&adapter->ctrl, rxq->id, posted); + atomic_add(posted, &rxq->used); + } + + return; +} + +static struct be_eth_tx_compl * +be_tx_compl_get(struct be_adapter *adapter) +{ + struct be_queue_info *tx_cq = &adapter->tx_obj.cq; + struct be_eth_tx_compl *txcp = queue_tail_node(tx_cq); + + if (txcp->dw[offsetof(struct amap_eth_tx_compl, valid) / 32] == 0) + return NULL; + + be_dws_le_to_cpu(txcp, sizeof(*txcp)); + + txcp->dw[offsetof(struct amap_eth_tx_compl, valid) / 32] = 0; + + queue_tail_inc(tx_cq); + return txcp; +} + +static void be_tx_compl_process(struct be_adapter *adapter, u16 last_index) +{ + struct be_queue_info *txq = &adapter->tx_obj.q; + struct be_eth_wrb *wrb; + struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list; + struct sk_buff *sent_skb; + u64 busaddr; + u16 cur_index, num_wrbs = 0; + + cur_index = txq->tail; + sent_skb = sent_skbs[cur_index]; + BUG_ON(!sent_skb); + sent_skbs[cur_index] = NULL; + + do { + cur_index = txq->tail; + wrb = queue_tail_node(txq); + be_dws_le_to_cpu(wrb, sizeof(*wrb)); + busaddr = ((u64)wrb->frag_pa_hi << 32) | (u64)wrb->frag_pa_lo; + if (busaddr != 0) { + pci_unmap_single(adapter->pdev, busaddr, + wrb->frag_len, PCI_DMA_TODEVICE); + } + num_wrbs++; + queue_tail_inc(txq); + } while (cur_index != last_index); + + atomic_sub(num_wrbs, &txq->used); + + kfree_skb(sent_skb); +} + +static void be_rx_q_clean(struct be_adapter *adapter) +{ + struct be_rx_page_info *page_info; + struct be_queue_info *rxq = &adapter->rx_obj.q; + struct be_queue_info *rx_cq = &adapter->rx_obj.cq; + struct be_eth_rx_compl *rxcp; + u16 tail; + + /* First cleanup pending rx completions */ + while ((rxcp = be_rx_compl_get(adapter)) != NULL) { + be_rx_compl_discard(adapter, rxcp); + be_cq_notify(&adapter->ctrl, rx_cq->id, true, 1); + } + + /* Then free posted rx buffer that were not used */ + tail = (rxq->head + rxq->len - atomic_read(&rxq->used)) % rxq->len; + for (; tail != rxq->head; index_inc(&tail, rxq->len)) { + page_info = get_rx_page_info(adapter, tail); + put_page(page_info->page); + memset(page_info, 0, sizeof(*page_info)); + } + BUG_ON(atomic_read(&rxq->used)); +} + +static void be_tx_q_clean(struct be_adapter *adapter) +{ + struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list; + struct sk_buff *sent_skb; + struct be_queue_info *txq = &adapter->tx_obj.q; + u16 last_index; + bool dummy_wrb; + + while (atomic_read(&txq->used)) { + sent_skb = sent_skbs[txq->tail]; + last_index = txq->tail; + index_adv(&last_index, + wrb_cnt_for_skb(sent_skb, &dummy_wrb) - 1, txq->len); + be_tx_compl_process(adapter, last_index); + } +} + +static void be_tx_queues_destroy(struct be_adapter *adapter) +{ + struct be_queue_info *q; + + q = &adapter->tx_obj.q; + if (q->created) + be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_TXQ); + be_queue_free(adapter, q); + + q = &adapter->tx_obj.cq; + if (q->created) + be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_CQ); + be_queue_free(adapter, q); + + /* No more tx completions can be rcvd now; clean up if there are + * any pending completions or pending tx requests */ + be_tx_q_clean(adapter); + + q = &adapter->tx_eq.q; + if (q->created) + be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_EQ); + be_queue_free(adapter, q); +} + +static int be_tx_queues_create(struct be_adapter *adapter) +{ + struct be_queue_info *eq, *q, *cq; + + adapter->tx_eq.max_eqd = 0; + adapter->tx_eq.min_eqd = 0; + adapter->tx_eq.cur_eqd = 96; + adapter->tx_eq.enable_aic = false; + /* Alloc Tx Event queue */ + eq = &adapter->tx_eq.q; + if (be_queue_alloc(adapter, eq, EVNT_Q_LEN, sizeof(struct be_eq_entry))) + return -1; + + /* Ask BE to create Tx Event queue */ + if (be_cmd_eq_create(&adapter->ctrl, eq, adapter->tx_eq.cur_eqd)) + goto tx_eq_free; + /* Alloc TX eth compl queue */ + cq = &adapter->tx_obj.cq; + if (be_queue_alloc(adapter, cq, TX_CQ_LEN, + sizeof(struct be_eth_tx_compl))) + goto tx_eq_destroy; + + /* Ask BE to create Tx eth compl queue */ + if (be_cmd_cq_create(&adapter->ctrl, cq, eq, false, false, 3)) + goto tx_cq_free; + + /* Alloc TX eth queue */ + q = &adapter->tx_obj.q; + if (be_queue_alloc(adapter, q, TX_Q_LEN, sizeof(struct be_eth_wrb))) + goto tx_cq_destroy; + + /* Ask BE to create Tx eth queue */ + if (be_cmd_txq_create(&adapter->ctrl, q, cq)) + goto tx_q_free; + return 0; + +tx_q_free: + be_queue_free(adapter, q); +tx_cq_destroy: + be_cmd_q_destroy(&adapter->ctrl, cq, QTYPE_CQ); +tx_cq_free: + be_queue_free(adapter, cq); +tx_eq_destroy: + be_cmd_q_destroy(&adapter->ctrl, eq, QTYPE_EQ); +tx_eq_free: + be_queue_free(adapter, eq); + return -1; +} + +static void be_rx_queues_destroy(struct be_adapter *adapter) +{ + struct be_queue_info *q; + + q = &adapter->rx_obj.q; + if (q->created) { + be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_RXQ); + be_rx_q_clean(adapter); + } + be_queue_free(adapter, q); + + q = &adapter->rx_obj.cq; + if (q->created) + be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_CQ); + be_queue_free(adapter, q); + + q = &adapter->rx_eq.q; + if (q->created) + be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_EQ); + be_queue_free(adapter, q); +} + +static int be_rx_queues_create(struct be_adapter *adapter) +{ + struct be_queue_info *eq, *q, *cq; + int rc; + + adapter->max_rx_coal = BE_MAX_FRAGS_PER_FRAME; + adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE; + adapter->rx_eq.max_eqd = BE_MAX_EQD; + adapter->rx_eq.min_eqd = 0; + adapter->rx_eq.cur_eqd = 0; + adapter->rx_eq.enable_aic = true; + + /* Alloc Rx Event queue */ + eq = &adapter->rx_eq.q; + rc = be_queue_alloc(adapter, eq, EVNT_Q_LEN, + sizeof(struct be_eq_entry)); + if (rc) + return rc; + + /* Ask BE to create Rx Event queue */ + rc = be_cmd_eq_create(&adapter->ctrl, eq, adapter->rx_eq.cur_eqd); + if (rc) + goto rx_eq_free; + + /* Alloc RX eth compl queue */ + cq = &adapter->rx_obj.cq; + rc = be_queue_alloc(adapter, cq, RX_CQ_LEN, + sizeof(struct be_eth_rx_compl)); + if (rc) + goto rx_eq_destroy; + + /* Ask BE to create Rx eth compl queue */ + rc = be_cmd_cq_create(&adapter->ctrl, cq, eq, false, false, 3); + if (rc) + goto rx_cq_free; + + /* Alloc RX eth queue */ + q = &adapter->rx_obj.q; + rc = be_queue_alloc(adapter, q, RX_Q_LEN, sizeof(struct be_eth_rx_d)); + if (rc) + goto rx_cq_destroy; + + /* Ask BE to create Rx eth queue */ + rc = be_cmd_rxq_create(&adapter->ctrl, q, cq->id, rx_frag_size, + BE_MAX_JUMBO_FRAME_SIZE, adapter->if_handle, false); + if (rc) + goto rx_q_free; + + return 0; +rx_q_free: + be_queue_free(adapter, q); +rx_cq_destroy: + be_cmd_q_destroy(&adapter->ctrl, cq, QTYPE_CQ); +rx_cq_free: + be_queue_free(adapter, cq); +rx_eq_destroy: + be_cmd_q_destroy(&adapter->ctrl, eq, QTYPE_EQ); +rx_eq_free: + be_queue_free(adapter, eq); + return rc; +} +static bool event_get(struct be_eq_obj *eq_obj, u16 *rid) +{ + struct be_eq_entry *entry = queue_tail_node(&eq_obj->q); + u32 evt = entry->evt; + + if (!evt) + return false; + + evt = le32_to_cpu(evt); + *rid = (evt >> EQ_ENTRY_RES_ID_SHIFT) & EQ_ENTRY_RES_ID_MASK; + entry->evt = 0; + queue_tail_inc(&eq_obj->q); + return true; +} + +static int event_handle(struct be_ctrl_info *ctrl, + struct be_eq_obj *eq_obj) +{ + u16 rid = 0, num = 0; + + while (event_get(eq_obj, &rid)) + num++; + + /* We can see an interrupt and no event */ + be_eq_notify(ctrl, eq_obj->q.id, true, true, num); + if (num) + napi_schedule(&eq_obj->napi); + + return num; +} + +static irqreturn_t be_intx(int irq, void *dev) +{ + struct be_adapter *adapter = dev; + struct be_ctrl_info *ctrl = &adapter->ctrl; + int rx, tx; + + tx = event_handle(ctrl, &adapter->tx_eq); + rx = event_handle(ctrl, &adapter->rx_eq); + + if (rx || tx) + return IRQ_HANDLED; + else + return IRQ_NONE; +} + +static irqreturn_t be_msix_rx(int irq, void *dev) +{ + struct be_adapter *adapter = dev; + + event_handle(&adapter->ctrl, &adapter->rx_eq); + + return IRQ_HANDLED; +} + +static irqreturn_t be_msix_tx(int irq, void *dev) +{ + struct be_adapter *adapter = dev; + + event_handle(&adapter->ctrl, &adapter->tx_eq); + + return IRQ_HANDLED; +} + +static inline bool do_lro(struct be_adapter *adapter, + struct be_eth_rx_compl *rxcp) +{ + int err = AMAP_GET_BITS(struct amap_eth_rx_compl, err, rxcp); + int tcp_frame = AMAP_GET_BITS(struct amap_eth_rx_compl, tcpf, rxcp); + + if (err) + drvr_stats(adapter)->be_rxcp_err++; + + return (!tcp_frame || err || (adapter->max_rx_coal <= 1)) ? + false : true; +} + +int be_poll_rx(struct napi_struct *napi, int budget) +{ + struct be_eq_obj *rx_eq = container_of(napi, struct be_eq_obj, napi); + struct be_adapter *adapter = + container_of(rx_eq, struct be_adapter, rx_eq); + struct be_queue_info *rx_cq = &adapter->rx_obj.cq; + struct be_eth_rx_compl *rxcp; + u32 work_done; + + for (work_done = 0; work_done < budget; work_done++) { + rxcp = be_rx_compl_get(adapter); + if (!rxcp) + break; + + if (do_lro(adapter, rxcp)) + be_rx_compl_process_lro(adapter, rxcp); + else + be_rx_compl_process(adapter, rxcp); + } + + lro_flush_all(&adapter->rx_obj.lro_mgr); + + /* Refill the queue */ + if (atomic_read(&adapter->rx_obj.q.used) < RX_FRAGS_REFILL_WM) + be_post_rx_frags(adapter); + + /* All consumed */ + if (work_done < budget) { + napi_complete(napi); + be_cq_notify(&adapter->ctrl, rx_cq->id, true, work_done); + } else { + /* More to be consumed; continue with interrupts disabled */ + be_cq_notify(&adapter->ctrl, rx_cq->id, false, work_done); + } + return work_done; +} + +/* For TX we don't honour budget; consume everything */ +int be_poll_tx(struct napi_struct *napi, int budget) +{ + struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi); + struct be_adapter *adapter = + container_of(tx_eq, struct be_adapter, tx_eq); + struct be_tx_obj *tx_obj = &adapter->tx_obj; + struct be_queue_info *tx_cq = &tx_obj->cq; + struct be_queue_info *txq = &tx_obj->q; + struct be_eth_tx_compl *txcp; + u32 num_cmpl = 0; + u16 end_idx; + + while ((txcp = be_tx_compl_get(adapter))) { + end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl, + wrb_index, txcp); + be_tx_compl_process(adapter, end_idx); + num_cmpl++; + } + + /* As Tx wrbs have been freed up, wake up netdev queue if + * it was stopped due to lack of tx wrbs. + */ + if (netif_queue_stopped(adapter->netdev) && + atomic_read(&txq->used) < txq->len / 2) { + netif_wake_queue(adapter->netdev); + } + + napi_complete(napi); + + be_cq_notify(&adapter->ctrl, tx_cq->id, true, num_cmpl); + + drvr_stats(adapter)->be_tx_events++; + drvr_stats(adapter)->be_tx_compl += num_cmpl; + + return 1; +} + +static void be_msix_enable(struct be_adapter *adapter) +{ + int i, status; + + for (i = 0; i < BE_NUM_MSIX_VECTORS; i++) + adapter->msix_entries[i].entry = i; + + status = pci_enable_msix(adapter->pdev, adapter->msix_entries, + BE_NUM_MSIX_VECTORS); + if (status == 0) + adapter->msix_enabled = true; + return; +} + +static inline int be_msix_vec_get(struct be_adapter *adapter, u32 eq_id) +{ + return adapter->msix_entries[eq_id - + 8 * adapter->ctrl.pci_func].vector; +} + +static int be_msix_register(struct be_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct be_eq_obj *tx_eq = &adapter->tx_eq; + struct be_eq_obj *rx_eq = &adapter->rx_eq; + int status, vec; + + sprintf(tx_eq->desc, "%s-tx", netdev->name); + vec = be_msix_vec_get(adapter, tx_eq->q.id); + status = request_irq(vec, be_msix_tx, 0, tx_eq->desc, adapter); + if (status) + goto err; + + sprintf(rx_eq->desc, "%s-rx", netdev->name); + vec = be_msix_vec_get(adapter, rx_eq->q.id); + status = request_irq(vec, be_msix_rx, 0, rx_eq->desc, adapter); + if (status) { /* Free TX IRQ */ + vec = be_msix_vec_get(adapter, tx_eq->q.id); + free_irq(vec, adapter); + goto err; + } + return 0; +err: + dev_warn(&adapter->pdev->dev, + "MSIX Request IRQ failed - err %d\n", status); + pci_disable_msix(adapter->pdev); + adapter->msix_enabled = false; + return status; +} + +static int be_irq_register(struct be_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + int status; + + if (adapter->msix_enabled) { + status = be_msix_register(adapter); + if (status == 0) + goto done; + } + + /* INTx */ + netdev->irq = adapter->pdev->irq; + status = request_irq(netdev->irq, be_intx, IRQF_SHARED, netdev->name, + adapter); + if (status) { + dev_err(&adapter->pdev->dev, + "INTx request IRQ failed - err %d\n", status); + return status; + } +done: + adapter->isr_registered = true; + return 0; +} + +static void be_irq_unregister(struct be_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + int vec; + + if (!adapter->isr_registered) + return; + + /* INTx */ + if (!adapter->msix_enabled) { + free_irq(netdev->irq, adapter); + goto done; + } + + /* MSIx */ + vec = be_msix_vec_get(adapter, adapter->tx_eq.q.id); + free_irq(vec, adapter); + vec = be_msix_vec_get(adapter, adapter->rx_eq.q.id); + free_irq(vec, adapter); +done: + adapter->isr_registered = false; + return; +} + +static int be_open(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_ctrl_info *ctrl = &adapter->ctrl; + struct be_eq_obj *rx_eq = &adapter->rx_eq; + struct be_eq_obj *tx_eq = &adapter->tx_eq; + u32 if_flags; + int status; + + if_flags = BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_PROMISCUOUS | + BE_IF_FLAGS_MCAST_PROMISCUOUS | BE_IF_FLAGS_UNTAGGED | + BE_IF_FLAGS_PASS_L3L4_ERRORS; + status = be_cmd_if_create(ctrl, if_flags, netdev->dev_addr, + false/* pmac_invalid */, &adapter->if_handle, + &adapter->pmac_id); + if (status != 0) + goto do_none; + + status = be_cmd_set_flow_control(ctrl, true, true); + if (status != 0) + goto if_destroy; + + status = be_tx_queues_create(adapter); + if (status != 0) + goto if_destroy; + + status = be_rx_queues_create(adapter); + if (status != 0) + goto tx_qs_destroy; + + /* First time posting */ + be_post_rx_frags(adapter); + + napi_enable(&rx_eq->napi); + napi_enable(&tx_eq->napi); + + be_irq_register(adapter); + + be_intr_set(ctrl, true); + + /* The evt queues are created in the unarmed state; arm them */ + be_eq_notify(ctrl, rx_eq->q.id, true, false, 0); + be_eq_notify(ctrl, tx_eq->q.id, true, false, 0); + + /* The compl queues are created in the unarmed state; arm them */ + be_cq_notify(ctrl, adapter->rx_obj.cq.id, true, 0); + be_cq_notify(ctrl, adapter->tx_obj.cq.id, true, 0); + + be_link_status_update(adapter); + + schedule_delayed_work(&adapter->work, msecs_to_jiffies(100)); + return 0; + +tx_qs_destroy: + be_tx_queues_destroy(adapter); +if_destroy: + be_cmd_if_destroy(ctrl, adapter->if_handle); +do_none: + return status; +} + +static int be_close(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_ctrl_info *ctrl = &adapter->ctrl; + struct be_eq_obj *rx_eq = &adapter->rx_eq; + struct be_eq_obj *tx_eq = &adapter->tx_eq; + int vec; + + cancel_delayed_work(&adapter->work); + + netif_stop_queue(netdev); + netif_carrier_off(netdev); + adapter->link.speed = PHY_LINK_SPEED_ZERO; + + be_intr_set(ctrl, false); + + if (adapter->msix_enabled) { + vec = be_msix_vec_get(adapter, tx_eq->q.id); + synchronize_irq(vec); + vec = be_msix_vec_get(adapter, rx_eq->q.id); + synchronize_irq(vec); + } else { + synchronize_irq(netdev->irq); + } + be_irq_unregister(adapter); + + napi_disable(&rx_eq->napi); + napi_disable(&tx_eq->napi); + + be_rx_queues_destroy(adapter); + be_tx_queues_destroy(adapter); + + be_cmd_if_destroy(ctrl, adapter->if_handle); + return 0; +} + +static int be_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr, + void **ip_hdr, void **tcpudp_hdr, + u64 *hdr_flags, void *priv) +{ + struct ethhdr *eh; + struct vlan_ethhdr *veh; + struct iphdr *iph; + u8 *va = page_address(frag->page) + frag->page_offset; + unsigned long ll_hlen; + + prefetch(va); + eh = (struct ethhdr *)va; + *mac_hdr = eh; + ll_hlen = ETH_HLEN; + if (eh->h_proto != htons(ETH_P_IP)) { + if (eh->h_proto == htons(ETH_P_8021Q)) { + veh = (struct vlan_ethhdr *)va; + if (veh->h_vlan_encapsulated_proto != htons(ETH_P_IP)) + return -1; + + ll_hlen += VLAN_HLEN; + } else { + return -1; + } + } + *hdr_flags = LRO_IPV4; + iph = (struct iphdr *)(va + ll_hlen); + *ip_hdr = iph; + if (iph->protocol != IPPROTO_TCP) + return -1; + *hdr_flags |= LRO_TCP; + *tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2); + + return 0; +} + +static void be_lro_init(struct be_adapter *adapter, struct net_device *netdev) +{ + struct net_lro_mgr *lro_mgr; + + lro_mgr = &adapter->rx_obj.lro_mgr; + lro_mgr->dev = netdev; + lro_mgr->features = LRO_F_NAPI; + lro_mgr->ip_summed = CHECKSUM_UNNECESSARY; + lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY; + lro_mgr->max_desc = BE_MAX_LRO_DESCRIPTORS; + lro_mgr->lro_arr = adapter->rx_obj.lro_desc; + lro_mgr->get_frag_header = be_get_frag_header; + lro_mgr->max_aggr = BE_MAX_FRAGS_PER_FRAME; +} + +static struct net_device_ops be_netdev_ops = { + .ndo_open = be_open, + .ndo_stop = be_close, + .ndo_start_xmit = be_xmit, + .ndo_get_stats = be_get_stats, + .ndo_set_rx_mode = be_set_multicast_list, + .ndo_set_mac_address = be_mac_addr_set, + .ndo_change_mtu = be_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_vlan_rx_register = be_vlan_register, + .ndo_vlan_rx_add_vid = be_vlan_add_vid, + .ndo_vlan_rx_kill_vid = be_vlan_rem_vid, +}; + +static void be_netdev_init(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + netdev->features |= NETIF_F_SG | NETIF_F_HW_VLAN_RX | NETIF_F_TSO | + NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | NETIF_F_TSO6; + + netdev->flags |= IFF_MULTICAST; + + BE_SET_NETDEV_OPS(netdev, &be_netdev_ops); + + SET_ETHTOOL_OPS(netdev, &be_ethtool_ops); + + be_lro_init(adapter, netdev); + + netif_napi_add(netdev, &adapter->rx_eq.napi, be_poll_rx, + BE_NAPI_WEIGHT); + netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx, + BE_NAPI_WEIGHT); + + netif_carrier_off(netdev); + netif_stop_queue(netdev); +} + +static void be_unmap_pci_bars(struct be_adapter *adapter) +{ + struct be_ctrl_info *ctrl = &adapter->ctrl; + if (ctrl->csr) + iounmap(ctrl->csr); + if (ctrl->db) + iounmap(ctrl->db); + if (ctrl->pcicfg) + iounmap(ctrl->pcicfg); +} + +static int be_map_pci_bars(struct be_adapter *adapter) +{ + u8 __iomem *addr; + + addr = ioremap_nocache(pci_resource_start(adapter->pdev, 2), + pci_resource_len(adapter->pdev, 2)); + if (addr == NULL) + return -ENOMEM; + adapter->ctrl.csr = addr; + + addr = ioremap_nocache(pci_resource_start(adapter->pdev, 4), + 128 * 1024); + if (addr == NULL) + goto pci_map_err; + adapter->ctrl.db = addr; + + addr = ioremap_nocache(pci_resource_start(adapter->pdev, 1), + pci_resource_len(adapter->pdev, 1)); + if (addr == NULL) + goto pci_map_err; + adapter->ctrl.pcicfg = addr; + + return 0; +pci_map_err: + be_unmap_pci_bars(adapter); + return -ENOMEM; +} + + +static void be_ctrl_cleanup(struct be_adapter *adapter) +{ + struct be_dma_mem *mem = &adapter->ctrl.mbox_mem_alloced; + + be_unmap_pci_bars(adapter); + + if (mem->va) + pci_free_consistent(adapter->pdev, mem->size, + mem->va, mem->dma); +} + +/* Initialize the mbox required to send cmds to BE */ +static int be_ctrl_init(struct be_adapter *adapter) +{ + struct be_ctrl_info *ctrl = &adapter->ctrl; + struct be_dma_mem *mbox_mem_alloc = &ctrl->mbox_mem_alloced; + struct be_dma_mem *mbox_mem_align = &ctrl->mbox_mem; + int status; + u32 val; + + status = be_map_pci_bars(adapter); + if (status) + return status; + + mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16; + mbox_mem_alloc->va = pci_alloc_consistent(adapter->pdev, + mbox_mem_alloc->size, &mbox_mem_alloc->dma); + if (!mbox_mem_alloc->va) { + be_unmap_pci_bars(adapter); + return -1; + } + mbox_mem_align->size = sizeof(struct be_mcc_mailbox); + mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16); + mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16); + memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox)); + spin_lock_init(&ctrl->cmd_lock); + + val = ioread32(ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET); + ctrl->pci_func = (val >> MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT) & + MEMBAR_CTRL_INT_CTRL_PFUNC_MASK; + return 0; +} + +static void be_stats_cleanup(struct be_adapter *adapter) +{ + struct be_stats_obj *stats = &adapter->stats; + struct be_dma_mem *cmd = &stats->cmd; + + if (cmd->va) + pci_free_consistent(adapter->pdev, cmd->size, + cmd->va, cmd->dma); +} + +static int be_stats_init(struct be_adapter *adapter) +{ + struct be_stats_obj *stats = &adapter->stats; + struct be_dma_mem *cmd = &stats->cmd; + + cmd->size = sizeof(struct be_cmd_req_get_stats); + cmd->va = pci_alloc_consistent(adapter->pdev, cmd->size, &cmd->dma); + if (cmd->va == NULL) + return -1; + return 0; +} + +static void __devexit be_remove(struct pci_dev *pdev) +{ + struct be_adapter *adapter = pci_get_drvdata(pdev); + if (!adapter) + return; + + unregister_netdev(adapter->netdev); + + be_stats_cleanup(adapter); + + be_ctrl_cleanup(adapter); + + if (adapter->msix_enabled) { + pci_disable_msix(adapter->pdev); + adapter->msix_enabled = false; + } + + pci_set_drvdata(pdev, NULL); + pci_release_regions(pdev); + pci_disable_device(pdev); + + free_netdev(adapter->netdev); +} + +static int be_hw_up(struct be_adapter *adapter) +{ + struct be_ctrl_info *ctrl = &adapter->ctrl; + int status; + + status = be_cmd_POST(ctrl); + if (status) + return status; + + status = be_cmd_get_fw_ver(ctrl, adapter->fw_ver); + if (status) + return status; + + status = be_cmd_query_fw_cfg(ctrl, &adapter->port_num); + return status; +} + +static int __devinit be_probe(struct pci_dev *pdev, + const struct pci_device_id *pdev_id) +{ + int status = 0; + struct be_adapter *adapter; + struct net_device *netdev; + struct be_ctrl_info *ctrl; + u8 mac[ETH_ALEN]; + + status = pci_enable_device(pdev); + if (status) + goto do_none; + + status = pci_request_regions(pdev, DRV_NAME); + if (status) + goto disable_dev; + pci_set_master(pdev); + + netdev = alloc_etherdev(sizeof(struct be_adapter)); + if (netdev == NULL) { + status = -ENOMEM; + goto rel_reg; + } + adapter = netdev_priv(netdev); + adapter->pdev = pdev; + pci_set_drvdata(pdev, adapter); + adapter->netdev = netdev; + + be_msix_enable(adapter); + + status = pci_set_dma_mask(pdev, DMA_64BIT_MASK); + if (!status) { + netdev->features |= NETIF_F_HIGHDMA; + } else { + status = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (status) { + dev_err(&pdev->dev, "Could not set PCI DMA Mask\n"); + goto free_netdev; + } + } + + ctrl = &adapter->ctrl; + status = be_ctrl_init(adapter); + if (status) + goto free_netdev; + + status = be_stats_init(adapter); + if (status) + goto ctrl_clean; + + status = be_hw_up(adapter); + if (status) + goto stats_clean; + + status = be_cmd_mac_addr_query(ctrl, mac, MAC_ADDRESS_TYPE_NETWORK, + true /* permanent */, 0); + if (status) + goto stats_clean; + memcpy(netdev->dev_addr, mac, ETH_ALEN); + + INIT_DELAYED_WORK(&adapter->work, be_worker); + be_netdev_init(netdev); + SET_NETDEV_DEV(netdev, &adapter->pdev->dev); + + status = register_netdev(netdev); + if (status != 0) + goto stats_clean; + + dev_info(&pdev->dev, BE_NAME " port %d\n", adapter->port_num); + return 0; + +stats_clean: + be_stats_cleanup(adapter); +ctrl_clean: + be_ctrl_cleanup(adapter); +free_netdev: + free_netdev(adapter->netdev); +rel_reg: + pci_release_regions(pdev); +disable_dev: + pci_disable_device(pdev); +do_none: + dev_warn(&pdev->dev, BE_NAME " initialization failed\n"); + return status; +} + +static int be_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct be_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; + + netif_device_detach(netdev); + if (netif_running(netdev)) { + rtnl_lock(); + be_close(netdev); + rtnl_unlock(); + } + + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + return 0; +} + +static int be_resume(struct pci_dev *pdev) +{ + int status = 0; + struct be_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; + + netif_device_detach(netdev); + + status = pci_enable_device(pdev); + if (status) + return status; + + pci_set_power_state(pdev, 0); + pci_restore_state(pdev); + + be_vids_config(netdev); + + if (netif_running(netdev)) { + rtnl_lock(); + be_open(netdev); + rtnl_unlock(); + } + netif_device_attach(netdev); + return 0; +} + +static struct pci_driver be_driver = { + .name = DRV_NAME, + .id_table = be_dev_ids, + .probe = be_probe, + .remove = be_remove, + .suspend = be_suspend, + .resume = be_resume +}; + +static int __init be_init_module(void) +{ + if (rx_frag_size != 8192 && rx_frag_size != 4096 + && rx_frag_size != 2048) { + printk(KERN_WARNING DRV_NAME + " : Module param rx_frag_size must be 2048/4096/8192." + " Using 2048\n"); + rx_frag_size = 2048; + } + /* Ensure rx_frag_size is aligned to chache line */ + if (SKB_DATA_ALIGN(rx_frag_size) != rx_frag_size) { + printk(KERN_WARNING DRV_NAME + " : Bad module param rx_frag_size. Using 2048\n"); + rx_frag_size = 2048; + } + + return pci_register_driver(&be_driver); +} +module_init(be_init_module); + +static void __exit be_exit_module(void) +{ + pci_unregister_driver(&be_driver); +} +module_exit(be_exit_module); -- GitLab From f21cfb258df6dd3ea0b3e56d75c7e994edb81b35 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 12 Mar 2009 21:05:42 +0900 Subject: [PATCH 3118/4982] irq: add remove_irq() for freeing of setup_irq() irqs Impact: add new API This patch adds a remove_irq() function for releasing interrupts requested with setup_irq(). Without this patch we have no way of releasing such interrupts since free_irq() today tries to kfree() the irqaction passed with setup_irq(). Signed-off-by: Magnus Damm LKML-Reference: <20090312120542.2926.56609.sendpatchset@rx1.opensource.se> Signed-off-by: Ingo Molnar --- include/linux/irq.h | 1 + kernel/irq/manage.c | 39 ++++++++++++++++++++++++++------------- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/include/linux/irq.h b/include/linux/irq.h index f899b502f18..56f9988362e 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -236,6 +236,7 @@ typedef struct irq_desc irq_desc_t; #include extern int setup_irq(unsigned int irq, struct irqaction *new); +extern struct irqaction *remove_irq(unsigned int irq, void *dev_id); #ifdef CONFIG_GENERIC_HARDIRQS diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 52ee1713509..8b069a7046e 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -551,20 +551,14 @@ int setup_irq(unsigned int irq, struct irqaction *act) } /** - * free_irq - free an interrupt + * remove_irq - free an interrupt * @irq: Interrupt line to free * @dev_id: Device identity to free * - * Remove an interrupt handler. The handler is removed and if the - * interrupt line is no longer in use by any driver it is disabled. - * On a shared IRQ the caller must ensure the interrupt is disabled - * on the card it drives before calling this function. The function - * does not return until any executing interrupts for this IRQ - * have completed. - * - * This function must not be called from interrupt context. + * Used to remove interrupts statically setup by the early boot process. */ -void free_irq(unsigned int irq, void *dev_id) + +struct irqaction *remove_irq(unsigned int irq, void *dev_id) { struct irq_desc *desc = irq_to_desc(irq); struct irqaction *action, **action_ptr; @@ -573,7 +567,7 @@ void free_irq(unsigned int irq, void *dev_id) WARN(in_interrupt(), "Trying to free IRQ %d from IRQ context!\n", irq); if (!desc) - return; + return NULL; spin_lock_irqsave(&desc->lock, flags); @@ -589,7 +583,7 @@ void free_irq(unsigned int irq, void *dev_id) WARN(1, "Trying to free already-free IRQ %d\n", irq); spin_unlock_irqrestore(&desc->lock, flags); - return; + return NULL; } if (action->dev_id == dev_id) @@ -636,7 +630,26 @@ void free_irq(unsigned int irq, void *dev_id) local_irq_restore(flags); } #endif - kfree(action); + return action; +} + +/** + * free_irq - free an interrupt allocated with request_irq + * @irq: Interrupt line to free + * @dev_id: Device identity to free + * + * Remove an interrupt handler. The handler is removed and if the + * interrupt line is no longer in use by any driver it is disabled. + * On a shared IRQ the caller must ensure the interrupt is disabled + * on the card it drives before calling this function. The function + * does not return until any executing interrupts for this IRQ + * have completed. + * + * This function must not be called from interrupt context. + */ +void free_irq(unsigned int irq, void *dev_id) +{ + kfree(remove_irq(irq, dev_id)); } EXPORT_SYMBOL(free_irq); -- GitLab From cbf94f06824780183e4bba165c7c29d5c7bd9a51 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 12 Mar 2009 21:05:51 +0900 Subject: [PATCH 3119/4982] irq: match remove_irq() args with setup_irq() Modify remove_irq() to match setup_irq(). Signed-off-by: Magnus Damm LKML-Reference: <20090312120551.2926.43942.sendpatchset@rx1.opensource.se> Signed-off-by: Ingo Molnar --- include/linux/irq.h | 2 +- kernel/irq/manage.c | 26 +++++++++++++++++--------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/include/linux/irq.h b/include/linux/irq.h index 56f9988362e..737eafbc1f3 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -236,7 +236,7 @@ typedef struct irq_desc irq_desc_t; #include extern int setup_irq(unsigned int irq, struct irqaction *new); -extern struct irqaction *remove_irq(unsigned int irq, void *dev_id); +extern void remove_irq(unsigned int irq, struct irqaction *act); #ifdef CONFIG_GENERIC_HARDIRQS diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 8b069a7046e..fc16570c9b4 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -550,15 +550,11 @@ int setup_irq(unsigned int irq, struct irqaction *act) return __setup_irq(irq, desc, act); } -/** - * remove_irq - free an interrupt - * @irq: Interrupt line to free - * @dev_id: Device identity to free - * - * Used to remove interrupts statically setup by the early boot process. + /* + * Internal function to unregister an irqaction - used to free + * regular and special interrupts that are part of the architecture. */ - -struct irqaction *remove_irq(unsigned int irq, void *dev_id) +static struct irqaction *__free_irq(unsigned int irq, void *dev_id) { struct irq_desc *desc = irq_to_desc(irq); struct irqaction *action, **action_ptr; @@ -633,6 +629,18 @@ struct irqaction *remove_irq(unsigned int irq, void *dev_id) return action; } +/** + * remove_irq - free an interrupt + * @irq: Interrupt line to free + * @act: irqaction for the interrupt + * + * Used to remove interrupts statically setup by the early boot process. + */ +void remove_irq(unsigned int irq, struct irqaction *act) +{ + __free_irq(irq, act->dev_id); +} + /** * free_irq - free an interrupt allocated with request_irq * @irq: Interrupt line to free @@ -649,7 +657,7 @@ struct irqaction *remove_irq(unsigned int irq, void *dev_id) */ void free_irq(unsigned int irq, void *dev_id) { - kfree(remove_irq(irq, dev_id)); + kfree(__free_irq(irq, dev_id)); } EXPORT_SYMBOL(free_irq); -- GitLab From eb53b4e8fef10ccccb49a6dbb5e19ca84ba5a305 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 12 Mar 2009 21:05:59 +0900 Subject: [PATCH 3120/4982] irq: export remove_irq() and setup_irq() symbols Export the setup_irq() and remove_irq() symbols. I'd like to export these functions since I have timer code that needs to use setup_irq() early on (too early for request_irq()), and the same code can also be compiled as a module. Signed-off-by: Magnus Damm LKML-Reference: <20090312120559.2926.82371.sendpatchset@rx1.opensource.se> [ changed to _GPL as these are special APIs deep inside the irq layer. ] Signed-off-by: Ingo Molnar --- kernel/irq/manage.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index fc16570c9b4..e28db0f656a 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -549,6 +549,7 @@ int setup_irq(unsigned int irq, struct irqaction *act) return __setup_irq(irq, desc, act); } +EXPORT_SYMBOL_GPL(setup_irq); /* * Internal function to unregister an irqaction - used to free @@ -640,6 +641,7 @@ void remove_irq(unsigned int irq, struct irqaction *act) { __free_irq(irq, act->dev_id); } +EXPORT_SYMBOL_GPL(remove_irq); /** * free_irq - free an interrupt allocated with request_irq -- GitLab From 5d75bc557859805f00eeddb09d7cc8ffc7e5334e Mon Sep 17 00:00:00 2001 From: Gregorio Guidi Date: Thu, 12 Mar 2009 16:41:51 +0100 Subject: [PATCH 3121/4982] ALSA: hda - fix headphone settings and master volume (Conexant CX20551) Update the places where the 0x1d widget is used for Conexant 5047, fixing mismatch introduced after changing the connection. Signed-off-by: Gregorio Guidi Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index d60ccb5bb12..6cb184e9c2f 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -1196,7 +1196,7 @@ static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol, * the headphone jack */ bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; - snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0, + snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01, HDA_AMP_MUTE, bits); bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE; snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0, @@ -1214,7 +1214,7 @@ static void cxt5047_hp_automute(struct hda_codec *codec) AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; - snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0, + snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01, HDA_AMP_MUTE, bits); } @@ -1276,7 +1276,7 @@ static struct snd_kcontrol_new cxt5047_base_mixers[] = { }; static struct snd_kcontrol_new cxt5047_hp_spk_mixers[] = { - HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x00, HDA_OUTPUT), + HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x01, HDA_OUTPUT), HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT), {} }; -- GitLab From 6f7cb44ba1a5195bf719f9ba1d57bd79e13262c1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 11 Mar 2009 18:31:08 +0000 Subject: [PATCH 3122/4982] ASoC: Move WM8580 to normal I2C device probe Refactor the WM8580 device registration to probe via standard I2C device registration, registering the DAIs once the device has probed via I2C. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8580.c | 326 ++++++++++++++++++-------------------- sound/soc/codecs/wm8580.h | 5 - 2 files changed, 158 insertions(+), 173 deletions(-) diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 27f9e231bf6..442ea6f160f 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -1,7 +1,7 @@ /* * wm8580.c -- WM8580 ALSA Soc Audio driver * - * Copyright 2008 Wolfson Microelectronics PLC. + * Copyright 2008, 2009 Wolfson Microelectronics PLC. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -35,17 +35,6 @@ #include "wm8580.h" -struct pll_state { - unsigned int in; - unsigned int out; -}; - -/* codec private data */ -struct wm8580_priv { - struct pll_state a; - struct pll_state b; -}; - /* WM8580 register space */ #define WM8580_PLLA1 0x00 #define WM8580_PLLA2 0x01 @@ -100,6 +89,8 @@ struct wm8580_priv { #define WM8580_READBACK 0x34 #define WM8580_RESET 0x35 +#define WM8580_MAX_REGISTER 0x35 + /* PLLB4 (register 7h) */ #define WM8580_PLLB4_MCLKOUTSRC_MASK 0x60 #define WM8580_PLLB4_MCLKOUTSRC_PLLA 0x20 @@ -191,6 +182,20 @@ static const u16 wm8580_reg[] = { 0x0000, 0x0000 /*R53*/ }; +struct pll_state { + unsigned int in; + unsigned int out; +}; + +/* codec private data */ +struct wm8580_priv { + struct snd_soc_codec codec; + u16 reg_cache[WM8580_MAX_REGISTER + 1]; + struct pll_state a; + struct pll_state b; +}; + + /* * read wm8580 register cache */ @@ -755,8 +760,22 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec, switch (level) { case SND_SOC_BIAS_ON: case SND_SOC_BIAS_PREPARE: + break; + case SND_SOC_BIAS_STANDBY: + if (codec->bias_level == SND_SOC_BIAS_OFF) { + /* Power up and get individual control of the DACs */ + reg = wm8580_read(codec, WM8580_PWRDN1); + reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD); + wm8580_write(codec, WM8580_PWRDN1, reg); + + /* Make VMID high impedence */ + reg = wm8580_read(codec, WM8580_ADC_CONTROL1); + reg &= ~0x100; + wm8580_write(codec, WM8580_ADC_CONTROL1, reg); + } break; + case SND_SOC_BIAS_OFF: reg = wm8580_read(codec, WM8580_PWRDN1); wm8580_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN); @@ -812,100 +831,163 @@ struct snd_soc_dai wm8580_dai[] = { }; EXPORT_SYMBOL_GPL(wm8580_dai); -/* - * initialise the WM8580 driver - * register the mixer and dsp interfaces with the kernel - */ -static int wm8580_init(struct snd_soc_device *socdev) +static struct snd_soc_codec *wm8580_codec; + +static int wm8580_probe(struct platform_device *pdev) { - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec; int ret = 0; - codec->name = "WM8580"; - codec->owner = THIS_MODULE; - codec->read = wm8580_read_reg_cache; - codec->write = wm8580_write; - codec->set_bias_level = wm8580_set_bias_level; - codec->dai = wm8580_dai; - codec->num_dai = ARRAY_SIZE(wm8580_dai); - codec->reg_cache_size = ARRAY_SIZE(wm8580_reg); - codec->reg_cache = kmemdup(wm8580_reg, sizeof(wm8580_reg), - GFP_KERNEL); - - if (codec->reg_cache == NULL) - return -ENOMEM; - - /* Get the codec into a known state */ - wm8580_write(codec, WM8580_RESET, 0); - - /* Power up and get individual control of the DACs */ - wm8580_write(codec, WM8580_PWRDN1, wm8580_read(codec, WM8580_PWRDN1) & - ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD)); + if (wm8580_codec == NULL) { + dev_err(&pdev->dev, "Codec device not registered\n"); + return -ENODEV; + } - /* Make VMID high impedence */ - wm8580_write(codec, WM8580_ADC_CONTROL1, - wm8580_read(codec, WM8580_ADC_CONTROL1) & ~0x100); + socdev->card->codec = wm8580_codec; + codec = wm8580_codec; /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, - SNDRV_DEFAULT_STR1); + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) { - printk(KERN_ERR "wm8580: failed to create pcms\n"); + dev_err(codec->dev, "failed to create pcms: %d\n", ret); goto pcm_err; } snd_soc_add_controls(codec, wm8580_snd_controls, - ARRAY_SIZE(wm8580_snd_controls)); + ARRAY_SIZE(wm8580_snd_controls)); wm8580_add_widgets(codec); - ret = snd_soc_init_card(socdev); if (ret < 0) { - printk(KERN_ERR "wm8580: failed to register card\n"); + dev_err(codec->dev, "failed to register card: %d\n", ret); goto card_err; } + return ret; card_err: snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); pcm_err: - kfree(codec->reg_cache); return ret; } -/* If the i2c layer weren't so broken, we could pass this kind of data - around */ -static struct snd_soc_device *wm8580_socdev; +/* power down chip */ +static int wm8580_remove(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + snd_soc_free_pcms(socdev); + snd_soc_dapm_free(socdev); -/* - * WM8580 2 wire address is determined by GPIO5 - * state during powerup. - * low = 0x1a - * high = 0x1b - */ + return 0; +} + +struct snd_soc_codec_device soc_codec_dev_wm8580 = { + .probe = wm8580_probe, + .remove = wm8580_remove, +}; +EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580); + +static int wm8580_register(struct wm8580_priv *wm8580) +{ + int ret, i; + struct snd_soc_codec *codec = &wm8580->codec; + + if (wm8580_codec) { + dev_err(codec->dev, "Another WM8580 is registered\n"); + ret = -EINVAL; + goto err; + } + + mutex_init(&codec->mutex); + INIT_LIST_HEAD(&codec->dapm_widgets); + INIT_LIST_HEAD(&codec->dapm_paths); + + codec->private_data = wm8580; + codec->name = "WM8580"; + codec->owner = THIS_MODULE; + codec->read = wm8580_read_reg_cache; + codec->write = wm8580_write; + codec->bias_level = SND_SOC_BIAS_OFF; + codec->set_bias_level = wm8580_set_bias_level; + codec->dai = wm8580_dai; + codec->num_dai = ARRAY_SIZE(wm8580_dai); + codec->reg_cache_size = ARRAY_SIZE(wm8580->reg_cache); + codec->reg_cache = &wm8580->reg_cache; + + memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg)); + + /* Get the codec into a known state */ + ret = wm8580_write(codec, WM8580_RESET, 0); + if (ret != 0) { + dev_err(codec->dev, "Failed to reset codec: %d\n", ret); + goto err; + } + + for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++) + wm8580_dai[i].dev = codec->dev; + + wm8580_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + wm8580_codec = codec; + + ret = snd_soc_register_codec(codec); + if (ret != 0) { + dev_err(codec->dev, "Failed to register codec: %d\n", ret); + goto err; + } + + ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); + if (ret != 0) { + dev_err(codec->dev, "Failed to register DAI: %d\n", ret); + goto err_codec; + } + + return 0; + +err_codec: + snd_soc_unregister_codec(codec); +err: + kfree(wm8580); + return ret; +} + +static void wm8580_unregister(struct wm8580_priv *wm8580) +{ + wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF); + snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); + snd_soc_unregister_codec(&wm8580->codec); + kfree(wm8580); + wm8580_codec = NULL; +} + +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static int wm8580_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { - struct snd_soc_device *socdev = wm8580_socdev; - struct snd_soc_codec *codec = socdev->card->codec; - int ret; + struct wm8580_priv *wm8580; + struct snd_soc_codec *codec; + + wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL); + if (wm8580 == NULL) + return -ENOMEM; + + codec = &wm8580->codec; + codec->hw_write = (hw_write_t)i2c_master_send; - i2c_set_clientdata(i2c, codec); + i2c_set_clientdata(i2c, wm8580); codec->control_data = i2c; - ret = wm8580_init(socdev); - if (ret < 0) - dev_err(&i2c->dev, "failed to initialise WM8580\n"); - return ret; + codec->dev = &i2c->dev; + + return wm8580_register(wm8580); } static int wm8580_i2c_remove(struct i2c_client *client) { - struct snd_soc_codec *codec = i2c_get_clientdata(client); - kfree(codec->reg_cache); + struct wm8580_priv *wm8580 = i2c_get_clientdata(client); + wm8580_unregister(wm8580); return 0; } @@ -917,127 +999,35 @@ MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id); static struct i2c_driver wm8580_i2c_driver = { .driver = { - .name = "WM8580 I2C Codec", + .name = "wm8580", .owner = THIS_MODULE, }, .probe = wm8580_i2c_probe, .remove = wm8580_i2c_remove, .id_table = wm8580_i2c_id, }; +#endif -static int wm8580_add_i2c_device(struct platform_device *pdev, - const struct wm8580_setup_data *setup) +static int __init wm8580_modinit(void) { - struct i2c_board_info info; - struct i2c_adapter *adapter; - struct i2c_client *client; int ret; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) ret = i2c_add_driver(&wm8580_i2c_driver); if (ret != 0) { - dev_err(&pdev->dev, "can't add i2c driver\n"); - return ret; - } - - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = setup->i2c_address; - strlcpy(info.type, "wm8580", I2C_NAME_SIZE); - - adapter = i2c_get_adapter(setup->i2c_bus); - if (!adapter) { - dev_err(&pdev->dev, "can't get i2c adapter %d\n", - setup->i2c_bus); - goto err_driver; - } - - client = i2c_new_device(adapter, &info); - i2c_put_adapter(adapter); - if (!client) { - dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", - (unsigned int)info.addr); - goto err_driver; - } - - return 0; - -err_driver: - i2c_del_driver(&wm8580_i2c_driver); - return -ENODEV; -} -#endif - -static int wm8580_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct wm8580_setup_data *setup; - struct snd_soc_codec *codec; - struct wm8580_priv *wm8580; - int ret = 0; - - setup = socdev->codec_data; - codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (codec == NULL) - return -ENOMEM; - - wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL); - if (wm8580 == NULL) { - kfree(codec); - return -ENOMEM; + pr_err("Failed to register WM8580 I2C driver: %d\n", ret); } - - codec->private_data = wm8580; - socdev->card->codec = codec; - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - wm8580_socdev = socdev; - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - if (setup->i2c_address) { - codec->hw_write = (hw_write_t)i2c_master_send; - ret = wm8580_add_i2c_device(pdev, setup); - } -#else - /* Add other interfaces here */ -#endif - return ret; -} - -/* power down chip */ -static int wm8580_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - if (codec->control_data) - wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF); - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_unregister_device(codec->control_data); - i2c_del_driver(&wm8580_i2c_driver); #endif - kfree(codec->private_data); - kfree(codec); return 0; } - -struct snd_soc_codec_device soc_codec_dev_wm8580 = { - .probe = wm8580_probe, - .remove = wm8580_remove, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580); - -static int __init wm8580_modinit(void) -{ - return snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); -} module_init(wm8580_modinit); static void __exit wm8580_exit(void) { - snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + i2c_del_driver(&wm8580_i2c_driver); +#endif } module_exit(wm8580_exit); diff --git a/sound/soc/codecs/wm8580.h b/sound/soc/codecs/wm8580.h index 09e4422f6f2..0dfb5ddde6a 100644 --- a/sound/soc/codecs/wm8580.h +++ b/sound/soc/codecs/wm8580.h @@ -28,11 +28,6 @@ #define WM8580_CLKSRC_OSC 4 #define WM8580_CLKSRC_NONE 5 -struct wm8580_setup_data { - int i2c_bus; - unsigned short i2c_address; -}; - #define WM8580_DAI_PAIFRX 0 #define WM8580_DAI_PAIFTX 1 -- GitLab From eb5f6d753e337834c7ceb07824ee472e43d9a7a2 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 12 Mar 2009 11:07:54 +0100 Subject: [PATCH 3123/4982] ASoC: Replace remaining uses of snd_soc_cnew with snd_soc_add_controls. The drivers are basically duplicating the same code over and over. As snd_soc_cnew is going to be made static some time after the next merge window, we might as well convert them now. Signed-off-by: Philipp Zabel Signed-off-by: Mark Brown --- sound/soc/codecs/cs4270.c | 23 +++++------------------ sound/soc/codecs/tlv320aic26.c | 11 ++++------- sound/soc/codecs/wm8400.c | 12 ++---------- sound/soc/omap/n810.c | 12 +++++------- sound/soc/pxa/corgi.c | 12 +++++------- sound/soc/pxa/palm27x.c | 13 +++++-------- sound/soc/pxa/poodle.c | 12 +++++------- sound/soc/pxa/spitz.c | 12 +++++------- sound/soc/pxa/tosa.c | 12 +++++------- sound/soc/s3c24xx/neo1973_wm8753.c | 13 +++++-------- 10 files changed, 46 insertions(+), 86 deletions(-) diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 2137670c9b7..7fa09a38762 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -540,7 +540,6 @@ static int cs4270_probe(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct snd_soc_codec *codec = cs4270_codec; - unsigned int i; int ret; /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */ @@ -554,23 +553,11 @@ static int cs4270_probe(struct platform_device *pdev) } /* Add the non-DAPM controls */ - for (i = 0; i < ARRAY_SIZE(cs4270_snd_controls); i++) { - struct snd_kcontrol *kctrl; - - kctrl = snd_soc_cnew(&cs4270_snd_controls[i], codec, NULL); - if (!kctrl) { - dev_err(codec->dev, "error creating control '%s'\n", - cs4270_snd_controls[i].name); - ret = -ENOMEM; - goto error_free_pcms; - } - - ret = snd_ctl_add(codec->card, kctrl); - if (ret < 0) { - dev_err(codec->dev, "error adding control '%s'\n", - cs4270_snd_controls[i].name); - goto error_free_pcms; - } + ret = snd_soc_add_controls(codec, cs4270_snd_controls, + ARRAY_SIZE(cs4270_snd_controls)); + if (ret < 0) { + dev_err(codec->dev, "failed to add controls\n"); + goto error_free_pcms; } /* And finally, register the socdev */ diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index a7f333fc579..3387d9e736e 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c @@ -324,9 +324,8 @@ static int aic26_probe(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct snd_soc_codec *codec; - struct snd_kcontrol *kcontrol; struct aic26 *aic26; - int i, ret, err; + int ret, err; dev_info(&pdev->dev, "Probing AIC26 SoC CODEC driver\n"); dev_dbg(&pdev->dev, "socdev=%p\n", socdev); @@ -353,11 +352,9 @@ static int aic26_probe(struct platform_device *pdev) /* register controls */ dev_dbg(&pdev->dev, "Registering controls\n"); - for (i = 0; i < ARRAY_SIZE(aic26_snd_controls); i++) { - kcontrol = snd_soc_cnew(&aic26_snd_controls[i], codec, NULL); - err = snd_ctl_add(codec->card, kcontrol); - WARN_ON(err < 0); - } + err = snd_soc_add_controls(codec, aic26_snd_controls, + ARRAY_SIZE(aic26_snd_controls)); + WARN_ON(err < 0); /* CODEC is setup, we can register the card now */ dev_dbg(&pdev->dev, "Registering card\n"); diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index 4e1cefff848..744e0dc73be 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c @@ -351,16 +351,8 @@ SOC_SINGLE("RIN34 Mute Switch", WM8400_RIGHT_LINE_INPUT_3_4_VOLUME, /* add non dapm controls */ static int wm8400_add_controls(struct snd_soc_codec *codec) { - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8400_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8400_snd_controls[i],codec, - NULL)); - if (err < 0) - return err; - } - return 0; + return snd_soc_add_controls(codec, wm8400_snd_controls, + ARRAY_SIZE(wm8400_snd_controls)); } /* diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c index 9f037cd0191..86471fd6340 100644 --- a/sound/soc/omap/n810.c +++ b/sound/soc/omap/n810.c @@ -248,7 +248,7 @@ static const struct snd_kcontrol_new aic33_n810_controls[] = { static int n810_aic33_init(struct snd_soc_codec *codec) { - int i, err; + int err; /* Not connected */ snd_soc_dapm_nc_pin(codec, "MONO_LOUT"); @@ -256,12 +256,10 @@ static int n810_aic33_init(struct snd_soc_codec *codec) snd_soc_dapm_nc_pin(codec, "HPRCOM"); /* Add N810 specific controls */ - for (i = 0; i < ARRAY_SIZE(aic33_n810_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&aic33_n810_controls[i], codec, NULL)); - if (err < 0) - return err; - } + err = snd_soc_add_controls(codec, aic33_n810_controls, + ARRAY_SIZE(aic33_n810_controls)); + if (err < 0) + return err; /* Add N810 specific widgets */ snd_soc_dapm_new_controls(codec, aic33_dapm_widgets, diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index 146973ae097..02263e5d8f0 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -276,18 +276,16 @@ static const struct snd_kcontrol_new wm8731_corgi_controls[] = { */ static int corgi_wm8731_init(struct snd_soc_codec *codec) { - int i, err; + int err; snd_soc_dapm_nc_pin(codec, "LLINEIN"); snd_soc_dapm_nc_pin(codec, "RLINEIN"); /* Add corgi specific controls */ - for (i = 0; i < ARRAY_SIZE(wm8731_corgi_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8731_corgi_controls[i], codec, NULL)); - if (err < 0) - return err; - } + err = snd_soc_add_controls(codec, wm8731_corgi_controls, + ARRAY_SIZE(wm8731_corgi_controls)); + if (err < 0) + return err; /* Add corgi specific widgets */ snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets, diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c index 29958cd9dae..48a73f64500 100644 --- a/sound/soc/pxa/palm27x.c +++ b/sound/soc/pxa/palm27x.c @@ -146,19 +146,16 @@ static const struct snd_kcontrol_new palm27x_controls[] = { static int palm27x_ac97_init(struct snd_soc_codec *codec) { - int i, err; + int err; snd_soc_dapm_nc_pin(codec, "OUT3"); snd_soc_dapm_nc_pin(codec, "MONOOUT"); /* add palm27x specific controls */ - for (i = 0; i < ARRAY_SIZE(palm27x_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&palm27x_controls[i], - codec, NULL)); - if (err < 0) - return err; - } + err = snd_soc_add_controls(codec, palm27x_controls, + ARRAY_SIZE(palm27x_controls)); + if (err < 0) + return err; /* add palm27x specific widgets */ snd_soc_dapm_new_controls(codec, palm27x_dapm_widgets, diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index fb17a0a5a09..ef7c6c8dc8f 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -241,19 +241,17 @@ static const struct snd_kcontrol_new wm8731_poodle_controls[] = { */ static int poodle_wm8731_init(struct snd_soc_codec *codec) { - int i, err; + int err; snd_soc_dapm_nc_pin(codec, "LLINEIN"); snd_soc_dapm_nc_pin(codec, "RLINEIN"); snd_soc_dapm_enable_pin(codec, "MICIN"); /* Add poodle specific controls */ - for (i = 0; i < ARRAY_SIZE(wm8731_poodle_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8731_poodle_controls[i], codec, NULL)); - if (err < 0) - return err; - } + err = snd_soc_add_controls(codec, wm8731_poodle_controls, + ARRAY_SIZE(wm8731_poodle_controls)); + if (err < 0) + return err; /* Add poodle specific widgets */ snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets, diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index 1aafd8c645a..6ca9f53080c 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -278,7 +278,7 @@ static const struct snd_kcontrol_new wm8750_spitz_controls[] = { */ static int spitz_wm8750_init(struct snd_soc_codec *codec) { - int i, err; + int err; /* NC codec pins */ snd_soc_dapm_nc_pin(codec, "RINPUT1"); @@ -290,12 +290,10 @@ static int spitz_wm8750_init(struct snd_soc_codec *codec) snd_soc_dapm_nc_pin(codec, "MONO1"); /* Add spitz specific controls */ - for (i = 0; i < ARRAY_SIZE(wm8750_spitz_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8750_spitz_controls[i], codec, NULL)); - if (err < 0) - return err; - } + err = snd_soc_add_controls(codec, wm8750_spitz_controls, + ARRAY_SIZE(wm8750_spitz_controls)); + if (err < 0) + return err; /* Add spitz specific widgets */ snd_soc_dapm_new_controls(codec, wm8750_dapm_widgets, diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index 09b5bada03b..fc781374b1b 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c @@ -188,18 +188,16 @@ static const struct snd_kcontrol_new tosa_controls[] = { static int tosa_ac97_init(struct snd_soc_codec *codec) { - int i, err; + int err; snd_soc_dapm_nc_pin(codec, "OUT3"); snd_soc_dapm_nc_pin(codec, "MONOOUT"); /* add tosa specific controls */ - for (i = 0; i < ARRAY_SIZE(tosa_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&tosa_controls[i],codec, NULL)); - if (err < 0) - return err; - } + err = snd_soc_add_controls(codec, tosa_controls, + ARRAY_SIZE(tosa_controls)); + if (err < 0) + return err; /* add tosa specific widgets */ snd_soc_dapm_new_controls(codec, tosa_dapm_widgets, diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c index 5f6aeec0437..289fadf60b1 100644 --- a/sound/soc/s3c24xx/neo1973_wm8753.c +++ b/sound/soc/s3c24xx/neo1973_wm8753.c @@ -498,7 +498,7 @@ static const struct snd_kcontrol_new wm8753_neo1973_controls[] = { */ static int neo1973_wm8753_init(struct snd_soc_codec *codec) { - int i, err; + int err; pr_debug("Entered %s\n", __func__); @@ -518,13 +518,10 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec) set_scenario_endpoints(codec, NEO_AUDIO_OFF); /* add neo1973 specific controls */ - for (i = 0; i < ARRAY_SIZE(wm8753_neo1973_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8753_neo1973_controls[i], - codec, NULL)); - if (err < 0) - return err; - } + err = snd_soc_add_controls(codec, wm8753_neo1973_controls, + ARRAY_SIZE(8753_neo1973_controls)); + if (err < 0) + return err; /* set up neo1973 specific audio routes */ err = snd_soc_dapm_add_routes(codec, dapm_routes, -- GitLab From 3b7523fc828e41b2988feb400704e01b67859d78 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 12 Mar 2009 16:45:01 +0100 Subject: [PATCH 3124/4982] ALSA: hda - Add comments for the previous fix for conexant codecs Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 6cb184e9c2f..bc016fade19 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -1196,6 +1196,10 @@ static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol, * the headphone jack */ bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; + /* NOTE: Conexat codec needs the index for *OUTPUT* amp of + * pin widgets unlike other codecs. In this case, we need to + * set index 0x01 for the volume from the mixer amp 0x19. + */ snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01, HDA_AMP_MUTE, bits); bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE; @@ -1214,6 +1218,7 @@ static void cxt5047_hp_automute(struct hda_codec *codec) AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; + /* See the note in cxt5047_hp_master_sw_put */ snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01, HDA_AMP_MUTE, bits); } @@ -1276,6 +1281,7 @@ static struct snd_kcontrol_new cxt5047_base_mixers[] = { }; static struct snd_kcontrol_new cxt5047_hp_spk_mixers[] = { + /* See the note in cxt5047_hp_master_sw_put */ HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x01, HDA_OUTPUT), HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT), {} -- GitLab From 9421f9543b3a0a870499f64498406003de8214b4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 12 Mar 2009 17:06:07 +0100 Subject: [PATCH 3125/4982] ALSA: hda - Print multiple out-amp values of pin widgets on Conext codecs Add a flag to work around the non-standard amp-value handling on Conexant codecs. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.h | 3 +++ sound/pci/hda/hda_proc.c | 10 ++++++++-- sound/pci/hda/patch_conexant.c | 3 +++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 2ea628478a9..079e1ab718d 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -793,6 +793,9 @@ struct hda_codec { * status change * (e.g. Realtek codecs) */ + unsigned int pin_amp_workaround:1; /* pin out-amp takes index + * (e.g. Conexant codecs) + */ #ifdef CONFIG_SND_HDA_POWER_SAVE unsigned int power_on :1; /* current (global) power-state */ unsigned int power_transition :1; /* power-state in transition */ diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 144b85276d5..93b25ba4d00 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -554,8 +554,14 @@ static void print_codec_info(struct snd_info_entry *entry, snd_iprintf(buffer, " Amp-Out caps: "); print_amp_caps(buffer, codec, nid, HDA_OUTPUT); snd_iprintf(buffer, " Amp-Out vals: "); - print_amp_vals(buffer, codec, nid, HDA_OUTPUT, - wid_caps & AC_WCAP_STEREO, 1); + if (wid_type == AC_WID_PIN && + codec->pin_amp_workaround) + print_amp_vals(buffer, codec, nid, HDA_OUTPUT, + wid_caps & AC_WCAP_STEREO, + conn_len); + else + print_amp_vals(buffer, codec, nid, HDA_OUTPUT, + wid_caps & AC_WCAP_STEREO, 1); } switch (wid_type) { diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index bc016fade19..1f2ad76ca94 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -1066,6 +1066,7 @@ static int patch_cxt5045(struct hda_codec *codec) if (!spec) return -ENOMEM; codec->spec = spec; + codec->pin_amp_workaround = 1; spec->multiout.max_channels = 2; spec->multiout.num_dacs = ARRAY_SIZE(cxt5045_dac_nids); @@ -1501,6 +1502,7 @@ static int patch_cxt5047(struct hda_codec *codec) if (!spec) return -ENOMEM; codec->spec = spec; + codec->pin_amp_workaround = 1; spec->multiout.max_channels = 2; spec->multiout.num_dacs = ARRAY_SIZE(cxt5047_dac_nids); @@ -1847,6 +1849,7 @@ static int patch_cxt5051(struct hda_codec *codec) if (!spec) return -ENOMEM; codec->spec = spec; + codec->pin_amp_workaround = 1; codec->patch_ops = conexant_patch_ops; codec->patch_ops.init = cxt5051_init; -- GitLab From 2842c3b5449f31470b61db716f1926b594fb6156 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 12 Mar 2009 12:20:01 -0400 Subject: [PATCH 3126/4982] ext4: Print the find_group_flex() warning only once This is a short-term warning, and even printk_ratelimit() can result in too much noise in system logs. So only print it once as a warning. Signed-off-by: "Theodore Ts'o" --- fs/ext4/ialloc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 627f8c3337a..2d2b3585ee9 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -698,6 +698,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode) struct inode *ret; ext4_group_t i; int free = 0; + static int once = 1; ext4_group_t flex_group; /* Cannot create files in a deleted directory */ @@ -719,7 +720,8 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode) ret2 = find_group_flex(sb, dir, &group); if (ret2 == -1) { ret2 = find_group_other(sb, dir, &group); - if (ret2 == 0 && printk_ratelimit()) + if (ret2 == 0 && once) + once = 0; printk(KERN_NOTICE "ext4: find_group_flex " "failed, fallback succeeded dir %lu\n", dir->i_ino); -- GitLab From 6dc4a47a0cf423879b505af0e29997fca4088630 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 7 Mar 2009 00:23:52 +0100 Subject: [PATCH 3127/4982] [ARM] 5420/1: MMCI devinit and devexit macros This adds __devinit and __devexit macros to the module probe and remove functions in MMCI. Now includes the __devexit_p() thing too. Signed-off-by: Linus Walleij Signed-off-by: Russell King --- drivers/mmc/host/mmci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 2909bbc8ad0..a663429b3d5 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -490,7 +490,7 @@ static void mmci_check_status(unsigned long data) mod_timer(&host->timer, jiffies + HZ); } -static int mmci_probe(struct amba_device *dev, void *id) +static int __devinit mmci_probe(struct amba_device *dev, void *id) { struct mmc_platform_data *plat = dev->dev.platform_data; struct mmci_host *host; @@ -633,7 +633,7 @@ static int mmci_probe(struct amba_device *dev, void *id) return ret; } -static int mmci_remove(struct amba_device *dev) +static int __devexit mmci_remove(struct amba_device *dev) { struct mmc_host *mmc = amba_get_drvdata(dev); @@ -730,7 +730,7 @@ static struct amba_driver mmci_driver = { .name = DRIVER_NAME, }, .probe = mmci_probe, - .remove = mmci_remove, + .remove = __devexit_p(mmci_remove), .suspend = mmci_suspend, .resume = mmci_resume, .id_table = mmci_ids, -- GitLab From 307282c8990c5658604b9fda8a64a9a07079b850 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 12 Mar 2009 18:17:58 +0100 Subject: [PATCH 3128/4982] ALSA: hda - Add model=vaio for STAC9872 Add the default pin config for model=vaio (in case of broken BIOS). Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 3 +- sound/pci/hda/patch_sigmatel.c | 33 ++++++++++++++++++-- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index f9253ea3c19..8eec05bc079 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -368,4 +368,5 @@ STAC92HD83* STAC9872 ======== - N/A + vaio VAIO laptop without SPDIF + auto BIOS setup (default) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 72c87aa20bd..e06fc7decd3 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -155,6 +155,12 @@ enum { STAC_927X_MODELS }; +enum { + STAC_9872_AUTO, + STAC_9872_VAIO, + STAC_9872_MODELS +}; + struct sigmatel_event { hda_nid_t nid; unsigned char type; @@ -5588,6 +5594,25 @@ static hda_nid_t stac9872_mux_nids[] = { 0x15 }; +static unsigned int stac9872_vaio_pin_configs[9] = { + 0x03211020, 0x411111f0, 0x411111f0, 0x03a15030, + 0x411111f0, 0x90170110, 0x411111f0, 0x411111f0, + 0x90a7013e +}; + +static const char *stac9872_models[STAC_9872_MODELS] = { + [STAC_9872_AUTO] = "auto", + [STAC_9872_VAIO] = "vaio", +}; + +static unsigned int *stac9872_brd_tbl[STAC_9872_MODELS] = { + [STAC_9872_VAIO] = stac9872_vaio_pin_configs, +}; + +static struct snd_pci_quirk stac9872_cfg_tbl[] = { + {} /* terminator */ +}; + static int patch_stac9872(struct hda_codec *codec) { struct sigmatel_spec *spec; @@ -5598,11 +5623,15 @@ static int patch_stac9872(struct hda_codec *codec) return -ENOMEM; codec->spec = spec; -#if 0 /* no model right now */ spec->board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS, stac9872_models, stac9872_cfg_tbl); -#endif + if (spec->board_config < 0) + snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9872, " + "using BIOS defaults\n"); + else + stac92xx_set_config_regs(codec, + stac9872_brd_tbl[spec->board_config]); spec->num_pins = ARRAY_SIZE(stac9872_pin_nids); spec->pin_nids = stac9872_pin_nids; -- GitLab From 881a256d84e658d14ca1c162fe56e9cbbb1cdd49 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 31 Dec 2008 13:12:46 -0500 Subject: [PATCH 3129/4982] [SCSI] Add VPD helper Based on prior work by Martin Petersen and James Bottomley, this patch adds a generic helper for retrieving VPD pages from SCSI devices. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- drivers/scsi/scsi.c | 104 +++++++++++++++++++++++++++++++++++++ include/scsi/scsi_device.h | 1 + 2 files changed, 105 insertions(+) diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index cbcd3f681b6..a2ef03243a2 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -966,6 +966,110 @@ int scsi_track_queue_full(struct scsi_device *sdev, int depth) } EXPORT_SYMBOL(scsi_track_queue_full); +/** + * scsi_vpd_inquiry - Request a device provide us with a VPD page + * @sdev: The device to ask + * @buffer: Where to put the result + * @page: Which Vital Product Data to return + * @len: The length of the buffer + * + * This is an internal helper function. You probably want to use + * scsi_get_vpd_page instead. + * + * Returns 0 on success or a negative error number. + */ +static int scsi_vpd_inquiry(struct scsi_device *sdev, unsigned char *buffer, + u8 page, unsigned len) +{ + int result; + unsigned char cmd[16]; + + cmd[0] = INQUIRY; + cmd[1] = 1; /* EVPD */ + cmd[2] = page; + cmd[3] = len >> 8; + cmd[4] = len & 0xff; + cmd[5] = 0; /* Control byte */ + + /* + * I'm not convinced we need to try quite this hard to get VPD, but + * all the existing users tried this hard. + */ + result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, + len + 4, NULL, 30 * HZ, 3, NULL); + if (result) + return result; + + /* Sanity check that we got the page back that we asked for */ + if (buffer[1] != page) + return -EIO; + + return 0; +} + +/** + * scsi_get_vpd_page - Get Vital Product Data from a SCSI device + * @sdev: The device to ask + * @page: Which Vital Product Data to return + * + * SCSI devices may optionally supply Vital Product Data. Each 'page' + * of VPD is defined in the appropriate SCSI document (eg SPC, SBC). + * If the device supports this VPD page, this routine returns a pointer + * to a buffer containing the data from that page. The caller is + * responsible for calling kfree() on this pointer when it is no longer + * needed. If we cannot retrieve the VPD page this routine returns %NULL. + */ +unsigned char *scsi_get_vpd_page(struct scsi_device *sdev, u8 page) +{ + int i, result; + unsigned int len; + unsigned char *buf = kmalloc(259, GFP_KERNEL); + + if (!buf) + return NULL; + + /* Ask for all the pages supported by this device */ + result = scsi_vpd_inquiry(sdev, buf, 0, 255); + if (result) + goto fail; + + /* If the user actually wanted this page, we can skip the rest */ + if (page == 0) + return buf; + + for (i = 0; i < buf[3]; i++) + if (buf[i + 4] == page) + goto found; + /* The device claims it doesn't support the requested page */ + goto fail; + + found: + result = scsi_vpd_inquiry(sdev, buf, page, 255); + if (result) + goto fail; + + /* + * Some pages are longer than 255 bytes. The actual length of + * the page is returned in the header. + */ + len = (buf[2] << 8) | buf[3]; + if (len <= 255) + return buf; + + kfree(buf); + buf = kmalloc(len + 4, GFP_KERNEL); + result = scsi_vpd_inquiry(sdev, buf, page, len); + if (result) + goto fail; + + return buf; + + fail: + kfree(buf); + return NULL; +} +EXPORT_SYMBOL_GPL(scsi_get_vpd_page); + /** * scsi_device_get - get an additional reference to a scsi_device * @sdev: device to get a reference to diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 01a4c58f8ba..9576690901d 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -340,6 +340,7 @@ extern int scsi_mode_select(struct scsi_device *sdev, int pf, int sp, struct scsi_sense_hdr *); extern int scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries, struct scsi_sense_hdr *sshdr); +extern unsigned char *scsi_get_vpd_page(struct scsi_device *, u8 page); extern int scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state); extern struct scsi_event *sdev_evt_alloc(enum scsi_device_event evt_type, -- GitLab From 40c3460f3cad1672f22baadcdbe20b9b3200cc20 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 31 Dec 2008 12:11:17 -0700 Subject: [PATCH 3130/4982] [SCSI] ses: Use new scsi VPD helper SES had its own code to retrieve VPD from devices; convert it to use the new scsi_get_vpd_page helper. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- drivers/scsi/ses.c | 31 ++++--------------------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c index e946e05db7f..f2cf9523554 100644 --- a/drivers/scsi/ses.c +++ b/drivers/scsi/ses.c @@ -345,44 +345,21 @@ static int ses_enclosure_find_by_addr(struct enclosure_device *edev, return 0; } -#define VPD_INQUIRY_SIZE 36 - static void ses_match_to_enclosure(struct enclosure_device *edev, struct scsi_device *sdev) { - unsigned char *buf = kmalloc(VPD_INQUIRY_SIZE, GFP_KERNEL); + unsigned char *buf; unsigned char *desc; - u16 vpd_len; + unsigned int vpd_len; struct efd efd = { .addr = 0, }; - unsigned char cmd[] = { - INQUIRY, - 1, - 0x83, - VPD_INQUIRY_SIZE >> 8, - VPD_INQUIRY_SIZE & 0xff, - 0 - }; + buf = scsi_get_vpd_page(sdev, 0x83); if (!buf) return; - if (scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, - VPD_INQUIRY_SIZE, NULL, SES_TIMEOUT, SES_RETRIES, - NULL)) - goto free; - - vpd_len = (buf[2] << 8) + buf[3]; - kfree(buf); - buf = kmalloc(vpd_len, GFP_KERNEL); - if (!buf) - return; - cmd[3] = vpd_len >> 8; - cmd[4] = vpd_len & 0xff; - if (scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, - vpd_len, NULL, SES_TIMEOUT, SES_RETRIES, NULL)) - goto free; + vpd_len = ((buf[2] << 8) | buf[3]) + 4; desc = buf + 4; while (desc < buf + vpd_len) { -- GitLab From 59d3270326fcba29226c28df27cb43fefd8c58d0 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 9 Jan 2009 15:28:13 -0800 Subject: [PATCH 3131/4982] [SCSI] scsi_sysfs: delete extra kernel-doc Warning(linux-2.6.28-git13//drivers/scsi/scsi_sysfs.c:1049): Excess function parameter 'dev' description in 'scsi_sysfs_add_host' Signed-off-by: Randy Dunlap Signed-off-by: James Bottomley --- drivers/scsi/scsi_sysfs.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index da63802cbf9..fa4711d1274 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -1043,7 +1043,6 @@ EXPORT_SYMBOL(scsi_register_interface); /** * scsi_sysfs_add_host - add scsi host to subsystem * @shost: scsi host struct to add to subsystem - * @dev: parent struct device pointer **/ int scsi_sysfs_add_host(struct Scsi_Host *shost) { -- GitLab From c6a44287417de1625a59f1d4ae52d033c03b9dab Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Sun, 4 Jan 2009 03:08:19 -0500 Subject: [PATCH 3132/4982] [SCSI] scsi_debug: DIF/DIX support This patch adds support for DIX and DIF in scsi_debug. A separate buffer is allocated for the protection information. - The dix parameter indicates whether the controller supports DIX (protection information DMA) - The dif parameter indicates whether the simulated storage device supports DIF - The guard parameter switches between T10 CRC(0) and IP checksum(1) - The ato parameter indicates whether the application tag is owned by the disk(0) or the OS(1) - DIF and DIX errors can be triggered using the scsi_debug_opts mask Signed-off-by: Martin K. Petersen Acked-by: Douglas Gilbert Signed-off-by: James Bottomley --- drivers/scsi/scsi_debug.c | 443 +++++++++++++++++++++++++++++++++++++- 1 file changed, 436 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 6eebd0bbe8a..213123b0486 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -40,6 +40,9 @@ #include #include #include +#include + +#include #include #include @@ -48,8 +51,7 @@ #include #include -#include - +#include "sd.h" #include "scsi_logging.h" #define SCSI_DEBUG_VERSION "1.81" @@ -95,6 +97,10 @@ static const char * scsi_debug_version_date = "20070104"; #define DEF_FAKE_RW 0 #define DEF_VPD_USE_HOSTNO 1 #define DEF_SECTOR_SIZE 512 +#define DEF_DIX 0 +#define DEF_DIF 0 +#define DEF_GUARD 0 +#define DEF_ATO 1 /* bit mask values for scsi_debug_opts */ #define SCSI_DEBUG_OPT_NOISE 1 @@ -102,6 +108,8 @@ static const char * scsi_debug_version_date = "20070104"; #define SCSI_DEBUG_OPT_TIMEOUT 4 #define SCSI_DEBUG_OPT_RECOVERED_ERR 8 #define SCSI_DEBUG_OPT_TRANSPORT_ERR 16 +#define SCSI_DEBUG_OPT_DIF_ERR 32 +#define SCSI_DEBUG_OPT_DIX_ERR 64 /* When "every_nth" > 0 then modulo "every_nth" commands: * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set * - a RECOVERED_ERROR is simulated on successful read and write @@ -144,6 +152,10 @@ static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB; static int scsi_debug_fake_rw = DEF_FAKE_RW; static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO; static int scsi_debug_sector_size = DEF_SECTOR_SIZE; +static int scsi_debug_dix = DEF_DIX; +static int scsi_debug_dif = DEF_DIF; +static int scsi_debug_guard = DEF_GUARD; +static int scsi_debug_ato = DEF_ATO; static int scsi_debug_cmnd_count = 0; @@ -204,11 +216,15 @@ struct sdebug_queued_cmd { static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE]; static unsigned char * fake_storep; /* ramdisk storage */ +static unsigned char *dif_storep; /* protection info */ static int num_aborts = 0; static int num_dev_resets = 0; static int num_bus_resets = 0; static int num_host_resets = 0; +static int dix_writes; +static int dix_reads; +static int dif_errors; static DEFINE_SPINLOCK(queued_arr_lock); static DEFINE_RWLOCK(atomic_rw); @@ -217,6 +233,11 @@ static char sdebug_proc_name[] = "scsi_debug"; static struct bus_type pseudo_lld_bus; +static inline sector_t dif_offset(sector_t sector) +{ + return sector << 3; +} + static struct device_driver sdebug_driverfs_driver = { .name = sdebug_proc_name, .bus = &pseudo_lld_bus, @@ -225,6 +246,9 @@ static struct device_driver sdebug_driverfs_driver = { static const int check_condition_result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; +static const int illegal_condition_result = + (DRIVER_SENSE << 24) | (DID_ABORT << 16) | SAM_STAT_CHECK_CONDITION; + static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0x2, 0x4b}; static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, @@ -726,7 +750,12 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target, } else if (0x86 == cmd[2]) { /* extended inquiry */ arr[1] = cmd[2]; /*sanity */ arr[3] = 0x3c; /* number of following entries */ - arr[4] = 0x0; /* no protection stuff */ + if (scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) + arr[4] = 0x4; /* SPT: GRD_CHK:1 */ + else if (scsi_debug_dif) + arr[4] = 0x5; /* SPT: GRD_CHK:1, REF_CHK:1 */ + else + arr[4] = 0x0; /* no protection stuff */ arr[5] = 0x7; /* head of q, ordered + simple q's */ } else if (0x87 == cmd[2]) { /* mode page policy */ arr[1] = cmd[2]; /*sanity */ @@ -767,6 +796,7 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target, arr[2] = scsi_debug_scsi_level; arr[3] = 2; /* response_data_format==2 */ arr[4] = SDEBUG_LONG_INQ_SZ - 5; + arr[5] = scsi_debug_dif ? 1 : 0; /* PROTECT bit */ if (0 == scsi_debug_vpd_use_hostno) arr[5] = 0x10; /* claim: implicit TGPS */ arr[6] = 0x10; /* claim: MultiP */ @@ -915,6 +945,12 @@ static int resp_readcap16(struct scsi_cmnd * scp, arr[9] = (scsi_debug_sector_size >> 16) & 0xff; arr[10] = (scsi_debug_sector_size >> 8) & 0xff; arr[11] = scsi_debug_sector_size & 0xff; + + if (scsi_debug_dif) { + arr[12] = (scsi_debug_dif - 1) << 1; /* P_TYPE */ + arr[12] |= 1; /* PROT_EN */ + } + return fill_from_dev_buffer(scp, arr, min(alloc_len, SDEBUG_READCAP16_ARR_SZ)); } @@ -1066,6 +1102,10 @@ static int resp_ctrl_m_pg(unsigned char * p, int pcontrol, int target) ctrl_m_pg[2] |= 0x4; else ctrl_m_pg[2] &= ~0x4; + + if (scsi_debug_ato) + ctrl_m_pg[5] |= 0x80; /* ATO=1 */ + memcpy(p, ctrl_m_pg, sizeof(ctrl_m_pg)); if (1 == pcontrol) memcpy(p + 2, ch_ctrl_m_pg, sizeof(ch_ctrl_m_pg)); @@ -1536,6 +1576,87 @@ static int do_device_access(struct scsi_cmnd *scmd, return ret; } +static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, + unsigned int sectors) +{ + unsigned int i, resid; + struct scatterlist *psgl; + struct sd_dif_tuple *sdt; + sector_t sector; + sector_t tmp_sec = start_sec; + void *paddr; + + start_sec = do_div(tmp_sec, sdebug_store_sectors); + + sdt = (struct sd_dif_tuple *)(dif_storep + dif_offset(start_sec)); + + for (i = 0 ; i < sectors ; i++) { + u16 csum; + + if (sdt[i].app_tag == 0xffff) + continue; + + sector = start_sec + i; + + switch (scsi_debug_guard) { + case 1: + csum = ip_compute_csum(fake_storep + + sector * scsi_debug_sector_size, + scsi_debug_sector_size); + break; + case 0: + csum = crc_t10dif(fake_storep + + sector * scsi_debug_sector_size, + scsi_debug_sector_size); + csum = cpu_to_be16(csum); + break; + default: + BUG(); + } + + if (sdt[i].guard_tag != csum) { + printk(KERN_ERR "%s: GUARD check failed on sector %lu" \ + " rcvd 0x%04x, data 0x%04x\n", __func__, + (unsigned long)sector, + be16_to_cpu(sdt[i].guard_tag), + be16_to_cpu(csum)); + dif_errors++; + return 0x01; + } + + if (scsi_debug_dif != SD_DIF_TYPE3_PROTECTION && + be32_to_cpu(sdt[i].ref_tag) != (sector & 0xffffffff)) { + printk(KERN_ERR "%s: REF check failed on sector %lu\n", + __func__, (unsigned long)sector); + dif_errors++; + return 0x03; + } + } + + resid = sectors * 8; /* Bytes of protection data to copy into sgl */ + sector = start_sec; + + scsi_for_each_prot_sg(SCpnt, psgl, scsi_prot_sg_count(SCpnt), i) { + int len = min(psgl->length, resid); + + paddr = kmap_atomic(sg_page(psgl), KM_IRQ0) + psgl->offset; + memcpy(paddr, dif_storep + dif_offset(sector), len); + + sector += len >> 3; + if (sector >= sdebug_store_sectors) { + /* Force wrap */ + tmp_sec = sector; + sector = do_div(tmp_sec, sdebug_store_sectors); + } + resid -= len; + kunmap_atomic(paddr, KM_IRQ0); + } + + dix_reads++; + + return 0; +} + static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba, unsigned int num, struct sdebug_dev_info *devip) { @@ -1563,12 +1684,162 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba, } return check_condition_result; } + + /* DIX + T10 DIF */ + if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) { + int prot_ret = prot_verify_read(SCpnt, lba, num); + + if (prot_ret) { + mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, prot_ret); + return illegal_condition_result; + } + } + read_lock_irqsave(&atomic_rw, iflags); ret = do_device_access(SCpnt, devip, lba, num, 0); read_unlock_irqrestore(&atomic_rw, iflags); return ret; } +void dump_sector(unsigned char *buf, int len) +{ + int i, j; + + printk(KERN_ERR ">>> Sector Dump <<<\n"); + + for (i = 0 ; i < len ; i += 16) { + printk(KERN_ERR "%04d: ", i); + + for (j = 0 ; j < 16 ; j++) { + unsigned char c = buf[i+j]; + if (c >= 0x20 && c < 0x7e) + printk(" %c ", buf[i+j]); + else + printk("%02x ", buf[i+j]); + } + + printk("\n"); + } +} + +static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, + unsigned int sectors) +{ + int i, j, ret; + struct sd_dif_tuple *sdt; + struct scatterlist *dsgl = scsi_sglist(SCpnt); + struct scatterlist *psgl = scsi_prot_sglist(SCpnt); + void *daddr, *paddr; + sector_t tmp_sec = start_sec; + sector_t sector; + int ppage_offset; + unsigned short csum; + + sector = do_div(tmp_sec, sdebug_store_sectors); + + if (((SCpnt->cmnd[1] >> 5) & 7) != 1) { + printk(KERN_WARNING "scsi_debug: WRPROTECT != 1\n"); + return 0; + } + + BUG_ON(scsi_sg_count(SCpnt) == 0); + BUG_ON(scsi_prot_sg_count(SCpnt) == 0); + + paddr = kmap_atomic(sg_page(psgl), KM_IRQ1) + psgl->offset; + ppage_offset = 0; + + /* For each data page */ + scsi_for_each_sg(SCpnt, dsgl, scsi_sg_count(SCpnt), i) { + daddr = kmap_atomic(sg_page(dsgl), KM_IRQ0) + dsgl->offset; + + /* For each sector-sized chunk in data page */ + for (j = 0 ; j < dsgl->length ; j += scsi_debug_sector_size) { + + /* If we're at the end of the current + * protection page advance to the next one + */ + if (ppage_offset >= psgl->length) { + kunmap_atomic(paddr, KM_IRQ1); + psgl = sg_next(psgl); + BUG_ON(psgl == NULL); + paddr = kmap_atomic(sg_page(psgl), KM_IRQ1) + + psgl->offset; + ppage_offset = 0; + } + + sdt = paddr + ppage_offset; + + switch (scsi_debug_guard) { + case 1: + csum = ip_compute_csum(daddr, + scsi_debug_sector_size); + break; + case 0: + csum = cpu_to_be16(crc_t10dif(daddr, + scsi_debug_sector_size)); + break; + default: + BUG(); + ret = 0; + goto out; + } + + if (sdt->guard_tag != csum) { + printk(KERN_ERR + "%s: GUARD check failed on sector %lu " \ + "rcvd 0x%04x, calculated 0x%04x\n", + __func__, (unsigned long)sector, + be16_to_cpu(sdt->guard_tag), + be16_to_cpu(csum)); + ret = 0x01; + dump_sector(daddr, scsi_debug_sector_size); + goto out; + } + + if (scsi_debug_dif != SD_DIF_TYPE3_PROTECTION && + be32_to_cpu(sdt->ref_tag) + != (start_sec & 0xffffffff)) { + printk(KERN_ERR + "%s: REF check failed on sector %lu\n", + __func__, (unsigned long)sector); + ret = 0x03; + dump_sector(daddr, scsi_debug_sector_size); + goto out; + } + + /* Would be great to copy this in bigger + * chunks. However, for the sake of + * correctness we need to verify each sector + * before writing it to "stable" storage + */ + memcpy(dif_storep + dif_offset(sector), sdt, 8); + + sector++; + + if (sector == sdebug_store_sectors) + sector = 0; /* Force wrap */ + + start_sec++; + daddr += scsi_debug_sector_size; + ppage_offset += sizeof(struct sd_dif_tuple); + } + + kunmap_atomic(daddr, KM_IRQ0); + } + + kunmap_atomic(paddr, KM_IRQ1); + + dix_writes++; + + return 0; + +out: + dif_errors++; + kunmap_atomic(daddr, KM_IRQ0); + kunmap_atomic(paddr, KM_IRQ1); + return ret; +} + static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, unsigned int num, struct sdebug_dev_info *devip) { @@ -1579,6 +1850,16 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, if (ret) return ret; + /* DIX + T10 DIF */ + if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) { + int prot_ret = prot_verify_write(SCpnt, lba, num); + + if (prot_ret) { + mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, prot_ret); + return illegal_condition_result; + } + } + write_lock_irqsave(&atomic_rw, iflags); ret = do_device_access(SCpnt, devip, lba, num, 1); write_unlock_irqrestore(&atomic_rw, iflags); @@ -2095,6 +2376,10 @@ module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR); module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int, S_IRUGO | S_IWUSR); module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO); +module_param_named(dix, scsi_debug_dix, int, S_IRUGO); +module_param_named(dif, scsi_debug_dif, int, S_IRUGO); +module_param_named(guard, scsi_debug_guard, int, S_IRUGO); +module_param_named(ato, scsi_debug_ato, int, S_IRUGO); MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert"); MODULE_DESCRIPTION("SCSI debug adapter driver"); @@ -2117,7 +2402,10 @@ MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])"); MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)"); MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)"); MODULE_PARM_DESC(sector_size, "hardware sector size in bytes (def=512)"); - +MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)"); +MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)"); +MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)"); +MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)"); static char sdebug_info[256]; @@ -2164,14 +2452,14 @@ static int scsi_debug_proc_info(struct Scsi_Host *host, char *buffer, char **sta "delay=%d, max_luns=%d, scsi_level=%d\n" "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n" "number of aborts=%d, device_reset=%d, bus_resets=%d, " - "host_resets=%d\n", + "host_resets=%d\ndix_reads=%d dix_writes=%d dif_errors=%d\n", SCSI_DEBUG_VERSION, scsi_debug_version_date, scsi_debug_num_tgts, scsi_debug_dev_size_mb, scsi_debug_opts, scsi_debug_every_nth, scsi_debug_cmnd_count, scsi_debug_delay, scsi_debug_max_luns, scsi_debug_scsi_level, scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads, sdebug_sectors_per, num_aborts, num_dev_resets, num_bus_resets, - num_host_resets); + num_host_resets, dix_reads, dix_writes, dif_errors); if (pos < offset) { len = 0; begin = pos; @@ -2452,6 +2740,31 @@ static ssize_t sdebug_sector_size_show(struct device_driver * ddp, char * buf) } DRIVER_ATTR(sector_size, S_IRUGO, sdebug_sector_size_show, NULL); +static ssize_t sdebug_dix_show(struct device_driver *ddp, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dix); +} +DRIVER_ATTR(dix, S_IRUGO, sdebug_dix_show, NULL); + +static ssize_t sdebug_dif_show(struct device_driver *ddp, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dif); +} +DRIVER_ATTR(dif, S_IRUGO, sdebug_dif_show, NULL); + +static ssize_t sdebug_guard_show(struct device_driver *ddp, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_guard); +} +DRIVER_ATTR(guard, S_IRUGO, sdebug_guard_show, NULL); + +static ssize_t sdebug_ato_show(struct device_driver *ddp, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ato); +} +DRIVER_ATTR(ato, S_IRUGO, sdebug_ato_show, NULL); + + /* Note: The following function creates attribute files in the /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these files (over those found in the /sys/module/scsi_debug/parameters @@ -2478,11 +2791,19 @@ static int do_create_driverfs_files(void) ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb); ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno); ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_sector_size); + ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_dix); + ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_dif); + ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_guard); + ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_ato); return ret; } static void do_remove_driverfs_files(void) { + driver_remove_file(&sdebug_driverfs_driver, &driver_attr_ato); + driver_remove_file(&sdebug_driverfs_driver, &driver_attr_guard); + driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dif); + driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dix); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_sector_size); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb); @@ -2526,11 +2847,33 @@ static int __init scsi_debug_init(void) case 4096: break; default: - printk(KERN_ERR "scsi_debug_init: invalid sector_size %u\n", + printk(KERN_ERR "scsi_debug_init: invalid sector_size %d\n", scsi_debug_sector_size); return -EINVAL; } + switch (scsi_debug_dif) { + + case SD_DIF_TYPE0_PROTECTION: + case SD_DIF_TYPE1_PROTECTION: + case SD_DIF_TYPE3_PROTECTION: + break; + + default: + printk(KERN_ERR "scsi_debug_init: dif must be 0, 1 or 3\n"); + return -EINVAL; + } + + if (scsi_debug_guard > 1) { + printk(KERN_ERR "scsi_debug_init: guard must be 0 or 1\n"); + return -EINVAL; + } + + if (scsi_debug_ato > 1) { + printk(KERN_ERR "scsi_debug_init: ato must be 0 or 1\n"); + return -EINVAL; + } + if (scsi_debug_dev_size_mb < 1) scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */ sz = (unsigned long)scsi_debug_dev_size_mb * 1048576; @@ -2563,6 +2906,24 @@ static int __init scsi_debug_init(void) if (scsi_debug_num_parts > 0) sdebug_build_parts(fake_storep, sz); + if (scsi_debug_dif) { + int dif_size; + + dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple); + dif_storep = vmalloc(dif_size); + + printk(KERN_ERR "scsi_debug_init: dif_storep %u bytes @ %p\n", + dif_size, dif_storep); + + if (dif_storep == NULL) { + printk(KERN_ERR "scsi_debug_init: out of mem. (DIX)\n"); + ret = -ENOMEM; + goto free_vm; + } + + memset(dif_storep, 0xff, dif_size); + } + ret = device_register(&pseudo_primary); if (ret < 0) { printk(KERN_WARNING "scsi_debug: device_register error: %d\n", @@ -2615,6 +2976,8 @@ bus_unreg: dev_unreg: device_unregister(&pseudo_primary); free_vm: + if (dif_storep) + vfree(dif_storep); vfree(fake_storep); return ret; @@ -2632,6 +2995,9 @@ static void __exit scsi_debug_exit(void) bus_unregister(&pseudo_lld_bus); device_unregister(&pseudo_primary); + if (dif_storep) + vfree(dif_storep); + vfree(fake_storep); } @@ -2732,6 +3098,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done) struct sdebug_dev_info *devip = NULL; int inj_recovered = 0; int inj_transport = 0; + int inj_dif = 0; + int inj_dix = 0; int delay_override = 0; scsi_set_resid(SCpnt, 0); @@ -2769,6 +3137,10 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done) inj_recovered = 1; /* to reads and writes below */ else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts) inj_transport = 1; /* to reads and writes below */ + else if (SCSI_DEBUG_OPT_DIF_ERR & scsi_debug_opts) + inj_dif = 1; /* to reads and writes below */ + else if (SCSI_DEBUG_OPT_DIX_ERR & scsi_debug_opts) + inj_dix = 1; /* to reads and writes below */ } if (devip->wlun) { @@ -2870,6 +3242,12 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done) mk_sense_buffer(devip, ABORTED_COMMAND, TRANSPORT_PROBLEM, ACK_NAK_TO); errsts = check_condition_result; + } else if (inj_dif && (0 == errsts)) { + mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, 1); + errsts = illegal_condition_result; + } else if (inj_dix && (0 == errsts)) { + mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, 1); + errsts = illegal_condition_result; } break; case REPORT_LUNS: /* mandatory, ignore unit attention */ @@ -2894,6 +3272,12 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done) mk_sense_buffer(devip, RECOVERED_ERROR, THRESHOLD_EXCEEDED, 0); errsts = check_condition_result; + } else if (inj_dif && (0 == errsts)) { + mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, 1); + errsts = illegal_condition_result; + } else if (inj_dix && (0 == errsts)) { + mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, 1); + errsts = illegal_condition_result; } break; case MODE_SENSE: @@ -2982,6 +3366,7 @@ static int sdebug_driver_probe(struct device * dev) int error = 0; struct sdebug_host_info *sdbg_host; struct Scsi_Host *hpnt; + int host_prot; sdbg_host = to_sdebug_host(dev); @@ -3000,6 +3385,50 @@ static int sdebug_driver_probe(struct device * dev) hpnt->max_id = scsi_debug_num_tgts; hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; /* = scsi_debug_max_luns; */ + host_prot = 0; + + switch (scsi_debug_dif) { + + case SD_DIF_TYPE1_PROTECTION: + host_prot = SHOST_DIF_TYPE1_PROTECTION; + if (scsi_debug_dix) + host_prot |= SHOST_DIX_TYPE1_PROTECTION; + break; + + case SD_DIF_TYPE2_PROTECTION: + host_prot = SHOST_DIF_TYPE2_PROTECTION; + if (scsi_debug_dix) + host_prot |= SHOST_DIX_TYPE2_PROTECTION; + break; + + case SD_DIF_TYPE3_PROTECTION: + host_prot = SHOST_DIF_TYPE3_PROTECTION; + if (scsi_debug_dix) + host_prot |= SHOST_DIX_TYPE3_PROTECTION; + break; + + default: + if (scsi_debug_dix) + host_prot |= SHOST_DIX_TYPE0_PROTECTION; + break; + } + + scsi_host_set_prot(hpnt, host_prot); + + printk(KERN_INFO "scsi_debug: host protection%s%s%s%s%s%s%s\n", + (host_prot & SHOST_DIF_TYPE1_PROTECTION) ? " DIF1" : "", + (host_prot & SHOST_DIF_TYPE2_PROTECTION) ? " DIF2" : "", + (host_prot & SHOST_DIF_TYPE3_PROTECTION) ? " DIF3" : "", + (host_prot & SHOST_DIX_TYPE0_PROTECTION) ? " DIX0" : "", + (host_prot & SHOST_DIX_TYPE1_PROTECTION) ? " DIX1" : "", + (host_prot & SHOST_DIX_TYPE2_PROTECTION) ? " DIX2" : "", + (host_prot & SHOST_DIX_TYPE3_PROTECTION) ? " DIX3" : ""); + + if (scsi_debug_guard == 1) + scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_IP); + else + scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_CRC); + error = scsi_add_host(hpnt, &sdbg_host->dev); if (error) { printk(KERN_ERR "%s: scsi_add_host failed\n", __func__); -- GitLab From d0ace3c5eedff92333de0a5dd00cfb78a18b87cd Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 12 Jan 2009 10:53:04 -0800 Subject: [PATCH 3133/4982] [SCSI] scsi_debug: needs CRC_T10DIF Fix scsi_debug build error: drivers/built-in.o: In function `resp_read': scsi_debug.c:(.text+0x21379a): undefined reference to `crc_t10dif' drivers/built-in.o: In function `resp_write': scsi_debug.c:(.text+0x213fca): undefined reference to `crc_t10dif' Signed-off-by: Randy Dunlap Signed-off-by: James Bottomley --- drivers/scsi/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 256c7bec7bd..8f0a5cbd632 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -1535,6 +1535,7 @@ config SCSI_NSP32 config SCSI_DEBUG tristate "SCSI debugging host simulator" depends on SCSI + select CRC_T10DIF help This is a host adapter simulator that can simulate multiple hosts each with multiple dummy SCSI devices (disks). It defaults to one -- GitLab From d943aeebc5194f3c6a81fb139ba406040324e4f3 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 12 Jan 2009 10:50:58 -0800 Subject: [PATCH 3134/4982] [SCSI] libfc: needs CRC32 libfc uses crc32 functions, so cause it to be built via select: drivers/built-in.o: In function `fc_frame_crc_check': (.text+0x75dae): undefined reference to `crc32_le' drivers/built-in.o: In function `fc_fcp_recv': fc_fcp.c:(.text+0x7b919): undefined reference to `crc32_le' fc_fcp.c:(.text+0x7b9d5): undefined reference to `crc32_le' fc_fcp.c:(.text+0x7ba54): undefined reference to `crc32_le' Signed-off-by: Randy Dunlap Acked-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 8f0a5cbd632..898c2b59592 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -608,6 +608,7 @@ config SCSI_FLASHPOINT config LIBFC tristate "LibFC module" select SCSI_FC_ATTRS + select CRC32 ---help--- Fibre Channel library module -- GitLab From 6e7490c73d8cc48e7084ac976c8be7bbaf530acf Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sun, 11 Jan 2009 17:38:12 +0900 Subject: [PATCH 3135/4982] [SCSI] libfc: fix compile warning I got the following warnings on IA64: drivers/scsi/libfc/fc_lport.c: In function 'fc_lport_recv_flogi_req': drivers/scsi/libfc/fc_lport.c:788: warning: format '%llx' expects type 'long long unsigned int', but argument 3 has type 'u64' drivers/scsi/libfc/fc_lport.c:792: warning: format '%llx' expects type 'long long unsigned int', but argument 3 has type 'u64' scsi/libfc/fc_rport.c: In function 'fc_rport_recv_plogi_req': /home/fujita/git/linux-2.6/drivers/scsi/libfc/fc_rport.c:968: warning: format '%llx' expects type 'long long unsigned int', but argument 4 has type 'u64' Signed-off-by: FUJITA Tomonori Cc: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_lport.c | 5 +++-- drivers/scsi/libfc/fc_rport.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 2ae50a1188e..7ef44501ecc 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -762,10 +762,11 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, remote_wwpn = get_unaligned_be64(&flp->fl_wwpn); if (remote_wwpn == lport->wwpn) { FC_DBG("FLOGI from port with same WWPN %llx " - "possible configuration error\n", remote_wwpn); + "possible configuration error\n", + (unsigned long long)remote_wwpn); goto out; } - FC_DBG("FLOGI from port WWPN %llx\n", remote_wwpn); + FC_DBG("FLOGI from port WWPN %llx\n", (unsigned long long)remote_wwpn); /* * XXX what is the right thing to do for FIDs? diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index dae65133a83..0472bb73221 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -988,7 +988,7 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport, switch (rdata->rp_state) { case RPORT_ST_INIT: FC_DEBUG_RPORT("incoming PLOGI from %6x wwpn %llx state INIT " - "- reject\n", sid, wwpn); + "- reject\n", sid, (unsigned long long)wwpn); reject = ELS_RJT_UNSUP; break; case RPORT_ST_PLOGI: -- GitLab From 71fa7421822a251fc3e9ffb54653395b6b964309 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 11 Jan 2009 10:38:59 +0100 Subject: [PATCH 3136/4982] [SCSI] lpfc: constify virtual function tables Signed-off-by: Jan Engelhardt Acked-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_debugfs.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index b615eda361d..81cdcf46c47 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -1132,7 +1132,7 @@ lpfc_debugfs_dumpDataDif_release(struct inode *inode, struct file *file) } #undef lpfc_debugfs_op_disc_trc -static struct file_operations lpfc_debugfs_op_disc_trc = { +static const struct file_operations lpfc_debugfs_op_disc_trc = { .owner = THIS_MODULE, .open = lpfc_debugfs_disc_trc_open, .llseek = lpfc_debugfs_lseek, @@ -1141,7 +1141,7 @@ static struct file_operations lpfc_debugfs_op_disc_trc = { }; #undef lpfc_debugfs_op_nodelist -static struct file_operations lpfc_debugfs_op_nodelist = { +static const struct file_operations lpfc_debugfs_op_nodelist = { .owner = THIS_MODULE, .open = lpfc_debugfs_nodelist_open, .llseek = lpfc_debugfs_lseek, @@ -1150,7 +1150,7 @@ static struct file_operations lpfc_debugfs_op_nodelist = { }; #undef lpfc_debugfs_op_hbqinfo -static struct file_operations lpfc_debugfs_op_hbqinfo = { +static const struct file_operations lpfc_debugfs_op_hbqinfo = { .owner = THIS_MODULE, .open = lpfc_debugfs_hbqinfo_open, .llseek = lpfc_debugfs_lseek, @@ -1159,7 +1159,7 @@ static struct file_operations lpfc_debugfs_op_hbqinfo = { }; #undef lpfc_debugfs_op_dumpHBASlim -static struct file_operations lpfc_debugfs_op_dumpHBASlim = { +static const struct file_operations lpfc_debugfs_op_dumpHBASlim = { .owner = THIS_MODULE, .open = lpfc_debugfs_dumpHBASlim_open, .llseek = lpfc_debugfs_lseek, @@ -1168,7 +1168,7 @@ static struct file_operations lpfc_debugfs_op_dumpHBASlim = { }; #undef lpfc_debugfs_op_dumpHostSlim -static struct file_operations lpfc_debugfs_op_dumpHostSlim = { +static const struct file_operations lpfc_debugfs_op_dumpHostSlim = { .owner = THIS_MODULE, .open = lpfc_debugfs_dumpHostSlim_open, .llseek = lpfc_debugfs_lseek, @@ -1177,7 +1177,7 @@ static struct file_operations lpfc_debugfs_op_dumpHostSlim = { }; #undef lpfc_debugfs_op_dumpData -static struct file_operations lpfc_debugfs_op_dumpData = { +static const struct file_operations lpfc_debugfs_op_dumpData = { .owner = THIS_MODULE, .open = lpfc_debugfs_dumpData_open, .llseek = lpfc_debugfs_lseek, @@ -1187,7 +1187,7 @@ static struct file_operations lpfc_debugfs_op_dumpData = { }; #undef lpfc_debugfs_op_dumpDif -static struct file_operations lpfc_debugfs_op_dumpDif = { +static const struct file_operations lpfc_debugfs_op_dumpDif = { .owner = THIS_MODULE, .open = lpfc_debugfs_dumpDif_open, .llseek = lpfc_debugfs_lseek, @@ -1197,7 +1197,7 @@ static struct file_operations lpfc_debugfs_op_dumpDif = { }; #undef lpfc_debugfs_op_slow_ring_trc -static struct file_operations lpfc_debugfs_op_slow_ring_trc = { +static const struct file_operations lpfc_debugfs_op_slow_ring_trc = { .owner = THIS_MODULE, .open = lpfc_debugfs_slow_ring_trc_open, .llseek = lpfc_debugfs_lseek, -- GitLab From 0762a4824d6c6f8eb5d2646dfda95581d99afaa5 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 12 Jan 2009 09:28:55 +0100 Subject: [PATCH 3137/4982] [SCSI] Check for deleted device in scsi_device_online() scsi_device_online() is not just a negation of SDEV_OFFLINE, also devices in state SDEV_DEL are actually offline. Signed-off-by: Hannes Reinecke Signed-off-by: James Bottomley --- include/scsi/scsi_device.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 9576690901d..15b09266b7f 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -401,7 +401,8 @@ static inline unsigned int sdev_id(struct scsi_device *sdev) */ static inline int scsi_device_online(struct scsi_device *sdev) { - return sdev->sdev_state != SDEV_OFFLINE; + return (sdev->sdev_state != SDEV_OFFLINE && + sdev->sdev_state != SDEV_DEL); } static inline int scsi_device_blocked(struct scsi_device *sdev) { -- GitLab From 5ef074161b5bcd84acfe19f0ecd72b74765d8770 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Wed, 14 Jan 2009 11:14:32 -0800 Subject: [PATCH 3138/4982] [SCSI] Improve SCSI_LOGGING Kconfig entry The Kconfig entry for SCSI_LOGGING refers the reader to drivers/scsi/scsi.c, but I didn't find any useful information there. There is certainly logging code in that file, but the logging types and logging levels are described in drivers/scsi/scsi_logging.h. Also, the procfs file referred to in the section is incorrect. It should be /proc/sys/dev/scsi/logging_level and not /proc/scsi/scsi. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/Kconfig | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 898c2b59592..601c2a8ec24 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -224,14 +224,15 @@ config SCSI_LOGGING can enable logging by saying Y to "/proc file system support" and "Sysctl support" below and executing the command - echo "scsi log token [level]" > /proc/scsi/scsi + echo > /proc/sys/dev/scsi/logging_level - at boot time after the /proc file system has been mounted. + where is a four byte value representing the logging type + and logging level for each type of logging selected. - There are a number of things that can be used for 'token' (you can - find them in the source: ), and this - allows you to select the types of information you want, and the - level allows you to select the level of verbosity. + There are a number of logging types and you can find them in the + source at . The logging levels + are also described in that file and they determine the verbosity of + the logging for each logging type. If you say N here, it may be harder to track down some types of SCSI problems. If you say Y here your kernel will be somewhat larger, but -- GitLab From 49799fee82b4f78c45b1926be24e45b5cf667083 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Thu, 15 Jan 2009 17:13:36 +0200 Subject: [PATCH 3139/4982] [SCSI] sym53c8xx: Keep transfer negotiations valid (The patch updated based on testing and comments from Tony Battersby.) Change the sym53c8xx_2 driver negotiation logic so that the driver will tolerate better device removals. Negotiation message(s) will be sent with every INQUIRY and REQUEST SENSE command, and whenever there is a change in goals or when the device reports check condition. The patch was made specifically to address the case where you hotswap the disk using remove-single-device/add-single-device commands through /proc/scsi/scsi. Without the patch the driver keeps using old transfer parameters even though the target is reset and reports check condition, so the data transfer of the very first INQUIRY will fail. Signed-off-by: Aaro Koskinen Tested-by: Tony Battersby Signed-off-by: James Bottomley --- drivers/scsi/sym53c8xx_2/sym_hipd.c | 35 +++++++++++++++++++++-------- drivers/scsi/sym53c8xx_2/sym_hipd.h | 1 + 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index 98df1651404..fe6359d4e1e 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -1433,13 +1433,12 @@ static int sym_prepare_nego(struct sym_hcb *np, struct sym_ccb *cp, u_char *msgp * Many devices implement PPR in a buggy way, so only use it if we * really want to. */ - if (goal->offset && - (goal->iu || goal->dt || goal->qas || (goal->period < 0xa))) { + if (goal->renego == NS_PPR || (goal->offset && + (goal->iu || goal->dt || goal->qas || (goal->period < 0xa)))) { nego = NS_PPR; - } else if (spi_width(starget) != goal->width) { + } else if (goal->renego == NS_WIDE || goal->width) { nego = NS_WIDE; - } else if (spi_period(starget) != goal->period || - spi_offset(starget) != goal->offset) { + } else if (goal->renego == NS_SYNC || goal->offset) { nego = NS_SYNC; } else { goal->check_nego = 0; @@ -2049,11 +2048,13 @@ static void sym_setwide(struct sym_hcb *np, int target, u_char wide) struct sym_tcb *tp = &np->target[target]; struct scsi_target *starget = tp->starget; - if (spi_width(starget) == wide) - return; - sym_settrans(np, target, 0, 0, 0, wide, 0, 0); + if (wide) + tp->tgoal.renego = NS_WIDE; + else + tp->tgoal.renego = 0; + tp->tgoal.check_nego = 0; tp->tgoal.width = wide; spi_offset(starget) = 0; spi_period(starget) = 0; @@ -2080,6 +2081,12 @@ sym_setsync(struct sym_hcb *np, int target, sym_settrans(np, target, 0, ofs, per, wide, div, fak); + if (wide) + tp->tgoal.renego = NS_WIDE; + else if (ofs) + tp->tgoal.renego = NS_SYNC; + else + tp->tgoal.renego = 0; spi_period(starget) = per; spi_offset(starget) = ofs; spi_iu(starget) = spi_dt(starget) = spi_qas(starget) = 0; @@ -2106,6 +2113,10 @@ sym_setpprot(struct sym_hcb *np, int target, u_char opts, u_char ofs, sym_settrans(np, target, opts, ofs, per, wide, div, fak); + if (wide || ofs) + tp->tgoal.renego = NS_PPR; + else + tp->tgoal.renego = 0; spi_width(starget) = tp->tgoal.width = wide; spi_period(starget) = tp->tgoal.period = per; spi_offset(starget) = tp->tgoal.offset = ofs; @@ -3516,6 +3527,7 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num) spi_dt(starget) = 0; spi_qas(starget) = 0; tp->tgoal.check_nego = 1; + tp->tgoal.renego = 0; } /* @@ -5135,9 +5147,14 @@ int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *cmd, struct sym_ccb * /* * Build a negotiation message if needed. * (nego_status is filled by sym_prepare_nego()) + * + * Always negotiate on INQUIRY and REQUEST SENSE. + * */ cp->nego_status = 0; - if (tp->tgoal.check_nego && !tp->nego_cp && lp) { + if ((tp->tgoal.check_nego || + cmd->cmnd[0] == INQUIRY || cmd->cmnd[0] == REQUEST_SENSE) && + !tp->nego_cp && lp) { msglen += sym_prepare_nego(np, cp, msgptr + msglen); } diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h index ad078805e62..233a3d0b2ce 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.h +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h @@ -354,6 +354,7 @@ struct sym_trans { unsigned int dt:1; unsigned int qas:1; unsigned int check_nego:1; + unsigned int renego:2; }; /* -- GitLab From 951948a397e3ddc96658efd648b9d66622965b19 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Thu, 15 Jan 2009 16:51:48 +0100 Subject: [PATCH 3140/4982] [SCSI] scsi_transport_fc: Add missing parenthesis to Point-To-Point description Fix typo by adding closing parenthesis. Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_fc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 5f77417ed58..2df75295921 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -95,7 +95,7 @@ static struct { { FC_PORTTYPE_NPORT, "NPort (fabric via point-to-point)" }, { FC_PORTTYPE_NLPORT, "NLPort (fabric via loop)" }, { FC_PORTTYPE_LPORT, "LPort (private loop)" }, - { FC_PORTTYPE_PTP, "Point-To-Point (direct nport connection" }, + { FC_PORTTYPE_PTP, "Point-To-Point (direct nport connection)" }, { FC_PORTTYPE_NPIV, "NPIV VPORT" }, }; fc_enum_name_search(port_type, fc_port_type, fc_port_type_names) -- GitLab From 5a9ef25b14d39b8413364df12cb8d9bb7a673a32 Mon Sep 17 00:00:00 2001 From: Wayne Boyer Date: Fri, 23 Jan 2009 09:17:35 -0800 Subject: [PATCH 3141/4982] [SCSI] ipr: add MSI support Enable MSI if available/supported. Signed-off-by: Wayne Boyer Acked-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 7 +++++++ drivers/scsi/ipr.h | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 07829009a8b..3f47cd1c46e 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -7147,6 +7147,7 @@ static void ipr_free_all_resources(struct ipr_ioa_cfg *ioa_cfg) ENTER; free_irq(pdev->irq, ioa_cfg); + pci_disable_msi(pdev); iounmap(ioa_cfg->hdw_dma_regs); pci_release_regions(pdev); ipr_free_mem(ioa_cfg); @@ -7432,6 +7433,11 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, goto out; } + if (!(rc = pci_enable_msi(pdev))) + dev_info(&pdev->dev, "MSI enabled\n"); + else if (ipr_debug) + dev_info(&pdev->dev, "Cannot enable MSI\n"); + dev_info(&pdev->dev, "Found IOA with IRQ: %d\n", pdev->irq); host = scsi_host_alloc(&driver_template, sizeof(*ioa_cfg)); @@ -7574,6 +7580,7 @@ out_release_regions: out_scsi_host_put: scsi_host_put(host); out_disable: + pci_disable_msi(pdev); pci_disable_device(pdev); goto out; } diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 8f872f816fe..79a3ae4fb2c 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -37,8 +37,8 @@ /* * Literals */ -#define IPR_DRIVER_VERSION "2.4.1" -#define IPR_DRIVER_DATE "(April 24, 2007)" +#define IPR_DRIVER_VERSION "2.4.2" +#define IPR_DRIVER_DATE "(January 21, 2009)" /* * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding -- GitLab From 1c9fbafc8c629c89183d6dccec67a8415513b0d1 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Sun, 4 Jan 2009 03:14:11 -0500 Subject: [PATCH 3142/4982] [SCSI] Remove SUGGEST flags The SUGGEST_* flags in the SCSI command result have been out of fashion for a while and we don't actually use them in the error handling. Remove the remaining occurrences. Signed-off-by: Martin K. Petersen Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_fsf.c | 1 - drivers/scsi/constants.c | 13 +++---------- drivers/scsi/hptiop.c | 3 +-- drivers/scsi/ips.c | 3 +-- drivers/scsi/libfc/fc_fcp.c | 6 +++--- drivers/scsi/lpfc/lpfc_scsi.c | 6 +++--- drivers/scsi/st.c | 6 +++--- drivers/usb/storage/transport.c | 2 +- include/scsi/scsi.h | 11 ----------- 9 files changed, 15 insertions(+), 36 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index e6416f8541b..babe1b8ba25 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -2147,7 +2147,6 @@ static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req) if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ABORTED)) { set_host_byte(scpnt, DID_SOFT_ERROR); - set_driver_byte(scpnt, SUGGEST_RETRY); goto skip_fsfstatus; } diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 4003deefb7d..e79e18101f8 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -1373,21 +1373,14 @@ static const char * const driverbyte_table[]={ "DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD", "DRIVER_SENSE"}; #define NUM_DRIVERBYTE_STRS ARRAY_SIZE(driverbyte_table) -static const char * const driversuggest_table[]={"SUGGEST_OK", -"SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP", "SUGGEST_DIE", -"SUGGEST_5", "SUGGEST_6", "SUGGEST_7", "SUGGEST_SENSE"}; -#define NUM_SUGGEST_STRS ARRAY_SIZE(driversuggest_table) - void scsi_show_result(int result) { int hb = host_byte(result); - int db = (driver_byte(result) & DRIVER_MASK); - int su = ((driver_byte(result) & SUGGEST_MASK) >> 4); + int db = driver_byte(result); - printk("Result: hostbyte=%s driverbyte=%s,%s\n", + printk("Result: hostbyte=%s driverbyte=%s\n", (hb < NUM_HOSTBYTE_STRS ? hostbyte_table[hb] : "invalid"), - (db < NUM_DRIVERBYTE_STRS ? driverbyte_table[db] : "invalid"), - (su < NUM_SUGGEST_STRS ? driversuggest_table[su] : "invalid")); + (db < NUM_DRIVERBYTE_STRS ? driverbyte_table[db] : "invalid")); } #else diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index 34be88d7afa..af1f0af0c5a 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -580,8 +580,7 @@ static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag, break; default: - scp->result = ((DRIVER_INVALID|SUGGEST_ABORT)<<24) | - (DID_ABORT<<16); + scp->result = DRIVER_INVALID << 24 | DID_ABORT << 16; break; } diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index ef683f0d2b5..457d76a4cfe 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -1004,8 +1004,7 @@ static int __ips_eh_reset(struct scsi_cmnd *SC) DEBUG_VAR(1, "(%s%d) Failing active commands", ips_name, ha->host_num); while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) { - scb->scsi_cmd->result = - (DID_RESET << 16) | (SUGGEST_RETRY << 24); + scb->scsi_cmd->result = DID_RESET << 16; scb->scsi_cmd->scsi_done(scb->scsi_cmd); ips_freescb(ha, scb); } diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 2a631d7dbce..a070e571243 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -259,7 +259,7 @@ static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp) } fsp->state &= ~FC_SRB_ABORT_PENDING; - fsp->io_status = SUGGEST_RETRY << 24; + fsp->io_status = 0; fsp->status_code = FC_ERROR; fc_fcp_complete_locked(fsp); } @@ -859,7 +859,7 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp) (!(fsp->scsi_comp_flags & FCP_RESID_UNDER) || fsp->xfer_len < fsp->data_len - fsp->scsi_resid)) { fsp->status_code = FC_DATA_UNDRUN; - fsp->io_status = SUGGEST_RETRY << 24; + fsp->io_status = 0; } } @@ -1267,7 +1267,7 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp) rp = rport->dd_data; if (!fsp->seq_ptr || rp->rp_state != RPORT_ST_READY) { fsp->status_code = FC_HRD_ERROR; - fsp->io_status = SUGGEST_RETRY << 24; + fsp->io_status = 0; fc_fcp_complete_locked(fsp); return; } diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index b103b6ed497..b1bd3fc7bae 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -1357,7 +1357,7 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, 0x10, 0x1); - cmd->result = (DRIVER_SENSE|SUGGEST_DIE) << 24 + cmd->result = DRIVER_SENSE << 24 | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); phba->bg_guard_err_cnt++; printk(KERN_ERR "BLKGRD: guard_tag error\n"); @@ -1368,7 +1368,7 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, 0x10, 0x3); - cmd->result = (DRIVER_SENSE|SUGGEST_DIE) << 24 + cmd->result = DRIVER_SENSE << 24 | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); phba->bg_reftag_err_cnt++; @@ -1380,7 +1380,7 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, 0x10, 0x2); - cmd->result = (DRIVER_SENSE|SUGGEST_DIE) << 24 + cmd->result = DRIVER_SENSE << 24 | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); phba->bg_apptag_err_cnt++; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index c6f19ee8f2c..eb24efea8f1 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -374,9 +374,9 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt) if (!debugging) { /* Abnormal conditions for tape */ if (!cmdstatp->have_sense) printk(KERN_WARNING - "%s: Error %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n", - name, result, suggestion(result), - driver_byte(result) & DRIVER_MASK, host_byte(result)); + "%s: Error %x (driver bt 0x%x, host bt 0x%x).\n", + name, result, driver_byte(result), + host_byte(result)); else if (cmdstatp->have_sense && scode != NO_SENSE && scode != RECOVERED_ERROR && diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index fb65d221ced..02e30a3ce7b 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -781,7 +781,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) /* Did we transfer less than the minimum amount required? */ if ((srb->result == SAM_STAT_GOOD || srb->sense_buffer[2] == 0) && scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow) - srb->result = (DID_ERROR << 16) | (SUGGEST_RETRY << 24); + srb->result = DID_ERROR << 16; last_sector_hacks(us, srb); return; diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index a109165714d..815d4047c4c 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -402,16 +402,6 @@ static inline int scsi_is_wlun(unsigned int lun) #define DRIVER_HARD 0x07 #define DRIVER_SENSE 0x08 -#define SUGGEST_RETRY 0x10 -#define SUGGEST_ABORT 0x20 -#define SUGGEST_REMAP 0x30 -#define SUGGEST_DIE 0x40 -#define SUGGEST_SENSE 0x80 -#define SUGGEST_IS_OK 0xff - -#define DRIVER_MASK 0x0f -#define SUGGEST_MASK 0xf0 - /* * Internal return values. */ @@ -447,7 +437,6 @@ static inline int scsi_is_wlun(unsigned int lun) #define msg_byte(result) (((result) >> 8) & 0xff) #define host_byte(result) (((result) >> 16) & 0xff) #define driver_byte(result) (((result) >> 24) & 0xff) -#define suggestion(result) (driver_byte(result) & SUGGEST_MASK) static inline void set_msg_byte(struct scsi_cmnd *cmd, char status) { -- GitLab From a4976d688650b4593831fbffbb217f2d916b1aa0 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 25 Jan 2009 15:09:42 -0600 Subject: [PATCH 3143/4982] [SCSI] osst: Remove SUGGEST flags Fix up remaining bit of SUGGEST flag removal done by patch commit 0f10274300857d98ea5ea4c800c561a9ad9ac89f Author: Martin K. Petersen Date: Sun Jan 4 03:14:11 2009 -0500 [SCSI] Remove SUGGEST flags Signed-off-by: James Bottomley --- drivers/scsi/osst.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 0ea78d9a37d..8f21cbbd7aa 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -280,8 +280,8 @@ static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt) static int notyetprinted = 1; printk(KERN_WARNING - "%s:W: Warning %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n", - name, result, suggestion(result), driver_byte(result) & DRIVER_MASK, + "%s:W: Warning %x (driver bt 0x%x, host bt 0x%x).\n", + name, result, driver_byte(result), host_byte(result)); if (notyetprinted) { notyetprinted = 0; -- GitLab From dd48ebf7ca4a6e60e6787e443f5316724309865b Mon Sep 17 00:00:00 2001 From: Ed Lin - PTU Date: Mon, 26 Jan 2009 02:40:11 -0800 Subject: [PATCH 3144/4982] [SCSI] stex: Fix for potential invalid response The interrupt routine is good for normal cases. However, if the firmware is abnormal and returns an invalid response, the driver may reuse a ccb structure that has already been handled. This may cause problem. Fix this by setting the req member to NULL. Next time we know the response is invalid and handle accordingly if req is NULL. Signed-off-by: Ed Lin Signed-off-by: James Bottomley --- drivers/scsi/stex.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index a3a18ad7312..6129db4a6a3 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c @@ -746,6 +746,7 @@ static void stex_mu_intr(struct st_hba *hba, u32 doorbell) stex_copy_data(ccb, resp, size); } + ccb->req = NULL; ccb->srb_status = resp->srb_status; ccb->scsi_status = resp->scsi_status; -- GitLab From 62e5b3d850f76190633e5a3cc8d6cc611ef96cfc Mon Sep 17 00:00:00 2001 From: Ed Lin - PTU Date: Mon, 26 Jan 2009 02:40:29 -0800 Subject: [PATCH 3145/4982] [SCSI] stex: Add new device id Add new device id for controller type st_seq. Signed-off-by: Ed Lin Signed-off-by: James Bottomley --- drivers/scsi/stex.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index 6129db4a6a3..12dc0d176f3 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c @@ -119,6 +119,7 @@ enum { st_vsc = 1, st_vsc1 = 2, st_yosemite = 3, + st_seq = 4, PASSTHRU_REQ_TYPE = 0x00000001, PASSTHRU_REQ_NO_WAKEUP = 0x00000100, @@ -1127,7 +1128,7 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) hba->cardtype = (unsigned int) id->driver_data; if (hba->cardtype == st_vsc && (pdev->subsystem_device & 0xf) == 0x1) hba->cardtype = st_vsc1; - hba->dma_size = (hba->cardtype == st_vsc1) ? + hba->dma_size = (hba->cardtype == st_vsc1 || hba->cardtype == st_seq) ? (STEX_BUFFER_SIZE + ST_ADDITIONAL_MEM) : (STEX_BUFFER_SIZE); hba->dma_mem = dma_alloc_coherent(&pdev->dev, hba->dma_size, &hba->dma_handle, GFP_KERNEL); @@ -1150,7 +1151,7 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) host->max_lun = 128; host->max_id = 1 + 1; } else { - /* st_vsc and st_vsc1 */ + /* st_vsc , st_vsc1 and st_seq */ host->max_lun = 1; host->max_id = 128 + 1; } @@ -1312,6 +1313,9 @@ static struct pci_device_id stex_pci_tbl[] = { st_yosemite }, /* SuperTrak EX8654 */ { 0x105a, 0x8650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_yosemite }, /* generic st_yosemite */ + + /* st_seq */ + { 0x105a, 0x3360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_seq }, { } /* terminate list */ }; MODULE_DEVICE_TABLE(pci, stex_pci_tbl); -- GitLab From e8a091b36cd50faa1276e6934edcc3e8b8e83b5a Mon Sep 17 00:00:00 2001 From: Ed Lin - PTU Date: Mon, 26 Jan 2009 02:40:50 -0800 Subject: [PATCH 3146/4982] [SCSI] stex: Fix for controller type st_yosemite This is the fix for controller type st_yosemite, including - max_lun is 256 (backward compatible) - remove unneeded special handling of INQUIRY - remove unnecessary listing of sub device ids Signed-off-by: Ed Lin Signed-off-by: James Bottomley --- drivers/scsi/stex.c | 64 +++------------------------------------------ 1 file changed, 3 insertions(+), 61 deletions(-) diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index 12dc0d176f3..425a61c79bb 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c @@ -153,35 +153,6 @@ enum { ST_ADDITIONAL_MEM = 0x200000, }; -/* SCSI inquiry data */ -typedef struct st_inq { - u8 DeviceType :5; - u8 DeviceTypeQualifier :3; - u8 DeviceTypeModifier :7; - u8 RemovableMedia :1; - u8 Versions; - u8 ResponseDataFormat :4; - u8 HiSupport :1; - u8 NormACA :1; - u8 ReservedBit :1; - u8 AERC :1; - u8 AdditionalLength; - u8 Reserved[2]; - u8 SoftReset :1; - u8 CommandQueue :1; - u8 Reserved2 :1; - u8 LinkedCommands :1; - u8 Synchronous :1; - u8 Wide16Bit :1; - u8 Wide32Bit :1; - u8 RelativeAddressing :1; - u8 VendorId[8]; - u8 ProductId[16]; - u8 ProductRevisionLevel[4]; - u8 VendorSpecific[20]; - u8 Reserved3[40]; -} ST_INQ; - struct st_sgitem { u8 ctrl; /* SG_CF_xxx */ u8 reserved[3]; @@ -285,7 +256,7 @@ struct st_drvver { #define MU_REQ_BUFFER_SIZE (MU_REQ_COUNT * sizeof(struct req_msg)) #define MU_STATUS_BUFFER_SIZE (MU_STATUS_COUNT * sizeof(struct status_msg)) #define MU_BUFFER_SIZE (MU_REQ_BUFFER_SIZE + MU_STATUS_BUFFER_SIZE) -#define STEX_EXTRA_SIZE max(sizeof(struct st_frame), sizeof(ST_INQ)) +#define STEX_EXTRA_SIZE sizeof(struct st_frame) #define STEX_BUFFER_SIZE (MU_BUFFER_SIZE + STEX_EXTRA_SIZE) struct st_ccb { @@ -662,24 +633,6 @@ static void stex_ys_commands(struct st_hba *hba, resp->scsi_status != SAM_STAT_CHECK_CONDITION) { scsi_set_resid(ccb->cmd, scsi_bufflen(ccb->cmd) - le32_to_cpu(*(__le32 *)&resp->variable[0])); - return; - } - - if (resp->srb_status != 0) - return; - - /* determine inquiry command status by DeviceTypeQualifier */ - if (ccb->cmd->cmnd[0] == INQUIRY && - resp->scsi_status == SAM_STAT_GOOD) { - ST_INQ *inq_data; - - scsi_sg_copy_to_buffer(ccb->cmd, hba->copy_buffer, - STEX_EXTRA_SIZE); - inq_data = (ST_INQ *)hba->copy_buffer; - if (inq_data->DeviceTypeQualifier != 0) - ccb->srb_status = SRB_STATUS_SELECTION_TIMEOUT; - else - ccb->srb_status = SRB_STATUS_SUCCESS; } } @@ -1148,7 +1101,7 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) host->max_lun = 8; host->max_id = 16 + 1; } else if (hba->cardtype == st_yosemite) { - host->max_lun = 128; + host->max_lun = 256; host->max_id = 1 + 1; } else { /* st_vsc , st_vsc1 and st_seq */ @@ -1301,18 +1254,7 @@ static struct pci_device_id stex_pci_tbl[] = { { 0x105a, 0x7250, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_vsc }, /* st_yosemite */ - { 0x105a, 0x8650, PCI_ANY_ID, 0x4600, 0, 0, - st_yosemite }, /* SuperTrak EX4650 */ - { 0x105a, 0x8650, PCI_ANY_ID, 0x4610, 0, 0, - st_yosemite }, /* SuperTrak EX4650o */ - { 0x105a, 0x8650, PCI_ANY_ID, 0x8600, 0, 0, - st_yosemite }, /* SuperTrak EX8650EL */ - { 0x105a, 0x8650, PCI_ANY_ID, 0x8601, 0, 0, - st_yosemite }, /* SuperTrak EX8650 */ - { 0x105a, 0x8650, PCI_ANY_ID, 0x8602, 0, 0, - st_yosemite }, /* SuperTrak EX8654 */ - { 0x105a, 0x8650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - st_yosemite }, /* generic st_yosemite */ + { 0x105a, 0x8650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_yosemite }, /* st_seq */ { 0x105a, 0x3360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_seq }, -- GitLab From 7cfe99a526b92e30df19673b3533f827bbe93821 Mon Sep 17 00:00:00 2001 From: Ed Lin - PTU Date: Mon, 26 Jan 2009 02:41:53 -0800 Subject: [PATCH 3147/4982] [SCSI] stex: Small fixes Some small fixes, including: - add data direction in req_msg because new firmware version may require this (backward compatible) - change internal timeout value - change judgment of type st_vsc1 - blank line handling, etc. Signed-off-by: Ed Lin Signed-off-by: James Bottomley --- drivers/scsi/stex.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index 425a61c79bb..c1a79c3f471 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c @@ -103,7 +103,7 @@ enum { MU_REQ_COUNT = (MU_MAX_REQUEST + 1), MU_STATUS_COUNT = (MU_MAX_REQUEST + 1), - STEX_CDB_LENGTH = MAX_COMMAND_SIZE, + STEX_CDB_LENGTH = 16, REQ_VARIABLE_LEN = 1024, STATUS_VAR_LEN = 128, ST_CAN_QUEUE = MU_MAX_REQUEST, @@ -114,6 +114,9 @@ enum { SG_CF_EOT = 0x80, /* end of table */ SG_CF_64B = 0x40, /* 64 bit item */ SG_CF_HOST = 0x20, /* sg in host memory */ + MSG_DATA_DIR_ND = 0, + MSG_DATA_DIR_IN = 1, + MSG_DATA_DIR_OUT = 2, st_shasta = 0, st_vsc = 1, @@ -123,7 +126,7 @@ enum { PASSTHRU_REQ_TYPE = 0x00000001, PASSTHRU_REQ_NO_WAKEUP = 0x00000100, - ST_INTERNAL_TIMEOUT = 30, + ST_INTERNAL_TIMEOUT = 180, ST_TO_CMD = 0, ST_FROM_CMD = 1, @@ -194,7 +197,7 @@ struct req_msg { u8 target; u8 task_attr; u8 task_manage; - u8 prd_entry; + u8 data_dir; u8 payload_sz; /* payload size in 4-byte, not used */ u8 cdb[STEX_CDB_LENGTH]; u8 variable[REQ_VARIABLE_LEN]; @@ -318,8 +321,8 @@ MODULE_VERSION(ST_DRIVER_VERSION); static void stex_gettime(__le32 *time) { struct timeval tv; - do_gettimeofday(&tv); + do_gettimeofday(&tv); *time = cpu_to_le32(tv.tv_sec & 0xffffffff); *(time + 1) = cpu_to_le32((tv.tv_sec >> 16) >> 16); } @@ -340,7 +343,7 @@ static void stex_invalid_field(struct scsi_cmnd *cmd, { cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; - /* "Invalid field in cbd" */ + /* "Invalid field in cdb" */ scsi_build_sense_buffer(0, cmd->sense_buffer, ILLEGAL_REQUEST, 0x24, 0x0); done(cmd); @@ -469,6 +472,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) unsigned int id,lun; struct req_msg *req; u16 tag; + host = cmd->device->host; id = cmd->device->id; lun = cmd->device->lun; @@ -480,6 +484,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) static char ms10_caching_page[12] = { 0, 0x12, 0, 0, 0, 0, 0, 0, 0x8, 0xa, 0x4, 0 }; unsigned char page; + page = cmd->cmnd[2] & 0x3f; if (page == 0x8 || page == 0x3f) { scsi_sg_copy_from_buffer(cmd, ms10_caching_page, @@ -523,6 +528,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) if (cmd->cmnd[1] == PASSTHRU_GET_DRVVER) { struct st_drvver ver; size_t cp_len = sizeof(ver); + ver.major = ST_VER_MAJOR; ver.minor = ST_VER_MINOR; ver.oem = ST_OEM; @@ -556,6 +562,13 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) /* cdb */ memcpy(req->cdb, cmd->cmnd, STEX_CDB_LENGTH); + if (cmd->sc_data_direction == DMA_FROM_DEVICE) + req->data_dir = MSG_DATA_DIR_IN; + else if (cmd->sc_data_direction == DMA_TO_DEVICE) + req->data_dir = MSG_DATA_DIR_OUT; + else + req->data_dir = MSG_DATA_DIR_ND; + hba->ccb[tag].cmd = cmd; hba->ccb[tag].sense_bufflen = SCSI_SENSE_BUFFERSIZE; hba->ccb[tag].sense_buffer = cmd->sense_buffer; @@ -614,6 +627,7 @@ static void stex_copy_data(struct st_ccb *ccb, struct status_msg *resp, unsigned int variable) { size_t count = variable; + if (resp->scsi_status != SAM_STAT_GOOD) { if (ccb->sense_buffer != NULL) memcpy(ccb->sense_buffer, resp->variable, @@ -938,6 +952,7 @@ static int stex_reset(struct scsi_cmnd *cmd) struct st_hba *hba; unsigned long flags; unsigned long before; + hba = (struct st_hba *) &cmd->device->host->hostdata[0]; printk(KERN_INFO DRV_NAME @@ -1022,6 +1037,7 @@ static struct scsi_host_template driver_template = { static int stex_set_dma_mask(struct pci_dev * pdev) { int ret; + if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK) && !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) return 0; @@ -1079,7 +1095,7 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) } hba->cardtype = (unsigned int) id->driver_data; - if (hba->cardtype == st_vsc && (pdev->subsystem_device & 0xf) == 0x1) + if (hba->cardtype == st_vsc && (pdev->subsystem_device & 1)) hba->cardtype = st_vsc1; hba->dma_size = (hba->cardtype == st_vsc1 || hba->cardtype == st_seq) ? (STEX_BUFFER_SIZE + ST_ADDITIONAL_MEM) : (STEX_BUFFER_SIZE); -- GitLab From bd5cd9cdc5379088b7e4e9a1757a1d101223a005 Mon Sep 17 00:00:00 2001 From: Ed Lin - PTU Date: Mon, 26 Jan 2009 02:42:11 -0800 Subject: [PATCH 3148/4982] [SCSI] stex: Version update Update version to 4.6.0000.1 Signed-off-by: Ed Lin Signed-off-by: James Bottomley --- drivers/scsi/stex.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index c1a79c3f471..47b614e8580 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c @@ -1,7 +1,7 @@ /* * SuperTrak EX Series Storage Controller driver for Linux * - * Copyright (C) 2005, 2006 Promise Technology Inc. + * Copyright (C) 2005-2009 Promise Technology Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -36,8 +36,8 @@ #include #define DRV_NAME "stex" -#define ST_DRIVER_VERSION "3.6.0000.1" -#define ST_VER_MAJOR 3 +#define ST_DRIVER_VERSION "4.6.0000.1" +#define ST_VER_MAJOR 4 #define ST_VER_MINOR 6 #define ST_OEM 0 #define ST_BUILD_VER 1 -- GitLab From c6517b7942fad663cc1cf3235cbe4207cf769332 Mon Sep 17 00:00:00 2001 From: Tony Battersby Date: Wed, 21 Jan 2009 14:45:50 -0500 Subject: [PATCH 3149/4982] [SCSI] sg: fix races during device removal sg has the following problems related to device removal: * opening a sg fd races with removing a device * closing a sg fd races with removing a device * /proc/scsi/sg/* access races with removing a device * command completion races with removing a device * command completion races with closing a sg fd * can rmmod sg with active commands These problems can cause kernel oopses, memory-use-after-free, or double-free errors. This patch fixes these problems by using krefs to manage the lifetime of sg_device and sg_fd. Each command submitted to the midlevel holds a reference to sg_fd until the completion callback. This ensures that sg_fd doesn't go away if the fd is closed with commands still outstanding. sg_fd gets the reference of sg_device (with scsi_device) and also makes sure that the sg module doesn't go away. /proc/scsi/sg/* functions don't play nicely with krefs because they give information about sg_fds which have been closed but not yet freed due to still having outstanding commands and sg_devices which have been removed but not yet freed due to still being referenced by one or more sg_fds. To deal with this safely without removing functionality, /proc functions now access sg_device and sg_fd while holding a lock instead of using kref_get()/kref_put(). Signed-off-by: Tony Battersby Acked-by: Douglas Gilbert Signed-off-by: James Bottomley --- drivers/scsi/sg.c | 418 ++++++++++++++++++++++------------------------ 1 file changed, 201 insertions(+), 217 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 516925d8b57..b447527555a 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -101,6 +101,7 @@ static int scatter_elem_sz_prev = SG_SCATTER_SZ; #define SG_SECTOR_MSK (SG_SECTOR_SZ - 1) static int sg_add(struct device *, struct class_interface *); +static void sg_device_destroy(struct kref *kref); static void sg_remove(struct device *, struct class_interface *); static DEFINE_IDR(sg_index_idr); @@ -158,6 +159,8 @@ typedef struct sg_fd { /* holds the state of a file descriptor */ char next_cmd_len; /* 0 -> automatic (def), >0 -> use on next write() */ char keep_orphan; /* 0 -> drop orphan (def), 1 -> keep for read() */ char mmap_called; /* 0 -> mmap() never called on this fd */ + struct kref f_ref; + struct execute_work ew; } Sg_fd; typedef struct sg_device { /* holds the state of each scsi generic device */ @@ -171,6 +174,7 @@ typedef struct sg_device { /* holds the state of each scsi generic device */ char sgdebug; /* 0->off, 1->sense, 9->dump dev, 10-> all devs */ struct gendisk *disk; struct cdev * cdev; /* char_dev [sysfs: /sys/cdev/major/sg] */ + struct kref d_ref; } Sg_device; static int sg_fasync(int fd, struct file *filp, int mode); @@ -194,13 +198,14 @@ static void sg_build_reserve(Sg_fd * sfp, int req_size); static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size); static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp); static Sg_fd *sg_add_sfp(Sg_device * sdp, int dev); -static int sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp); -static void __sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp); +static void sg_remove_sfp(struct kref *); static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id); static Sg_request *sg_add_request(Sg_fd * sfp); static int sg_remove_request(Sg_fd * sfp, Sg_request * srp); static int sg_res_in_use(Sg_fd * sfp); +static Sg_device *sg_lookup_dev(int dev); static Sg_device *sg_get_dev(int dev); +static void sg_put_dev(Sg_device *sdp); #ifdef CONFIG_SCSI_PROC_FS static int sg_last_dev(void); #endif @@ -237,22 +242,17 @@ sg_open(struct inode *inode, struct file *filp) nonseekable_open(inode, filp); SCSI_LOG_TIMEOUT(3, printk("sg_open: dev=%d, flags=0x%x\n", dev, flags)); sdp = sg_get_dev(dev); - if ((!sdp) || (!sdp->device)) { - unlock_kernel(); - return -ENXIO; - } - if (sdp->detached) { - unlock_kernel(); - return -ENODEV; + if (IS_ERR(sdp)) { + retval = PTR_ERR(sdp); + sdp = NULL; + goto sg_put; } /* This driver's module count bumped by fops_get in */ /* Prevent the device driver from vanishing while we sleep */ retval = scsi_device_get(sdp->device); - if (retval) { - unlock_kernel(); - return retval; - } + if (retval) + goto sg_put; if (!((flags & O_NONBLOCK) || scsi_block_when_processing_errors(sdp->device))) { @@ -303,16 +303,20 @@ sg_open(struct inode *inode, struct file *filp) if ((sfp = sg_add_sfp(sdp, dev))) filp->private_data = sfp; else { - if (flags & O_EXCL) + if (flags & O_EXCL) { sdp->exclude = 0; /* undo if error */ + wake_up_interruptible(&sdp->o_excl_wait); + } retval = -ENOMEM; goto error_out; } - unlock_kernel(); - return 0; - - error_out: - scsi_device_put(sdp->device); + retval = 0; +error_out: + if (retval) + scsi_device_put(sdp->device); +sg_put: + if (sdp) + sg_put_dev(sdp); unlock_kernel(); return retval; } @@ -327,13 +331,13 @@ sg_release(struct inode *inode, struct file *filp) if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) return -ENXIO; SCSI_LOG_TIMEOUT(3, printk("sg_release: %s\n", sdp->disk->disk_name)); - if (0 == sg_remove_sfp(sdp, sfp)) { /* Returns 1 when sdp gone */ - if (!sdp->detached) { - scsi_device_put(sdp->device); - } - sdp->exclude = 0; - wake_up_interruptible(&sdp->o_excl_wait); - } + + sfp->closed = 1; + + sdp->exclude = 0; + wake_up_interruptible(&sdp->o_excl_wait); + + kref_put(&sfp->f_ref, sg_remove_sfp); return 0; } @@ -755,6 +759,7 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, hp->duration = jiffies_to_msecs(jiffies); srp->rq->timeout = timeout; + kref_get(&sfp->f_ref); /* sg_rq_end_io() does kref_put(). */ blk_execute_rq_nowait(sdp->device->request_queue, sdp->disk, srp->rq, 1, sg_rq_end_io); return 0; @@ -1247,24 +1252,23 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma) static void sg_rq_end_io(struct request *rq, int uptodate) { struct sg_request *srp = rq->end_io_data; - Sg_device *sdp = NULL; + Sg_device *sdp; Sg_fd *sfp; unsigned long iflags; unsigned int ms; char *sense; - int result, resid; + int result, resid, done = 1; - if (NULL == srp) { - printk(KERN_ERR "sg_cmd_done: NULL request\n"); + if (WARN_ON(srp->done != 0)) return; - } + sfp = srp->parentfp; - if (sfp) - sdp = sfp->parentdp; - if ((NULL == sdp) || sdp->detached) { - printk(KERN_INFO "sg_cmd_done: device detached\n"); + if (WARN_ON(sfp == NULL)) return; - } + + sdp = sfp->parentdp; + if (unlikely(sdp->detached)) + printk(KERN_INFO "sg_rq_end_io: device detached\n"); sense = rq->sense; result = rq->errors; @@ -1303,33 +1307,26 @@ static void sg_rq_end_io(struct request *rq, int uptodate) } /* Rely on write phase to clean out srp status values, so no "else" */ - if (sfp->closed) { /* whoops this fd already released, cleanup */ - SCSI_LOG_TIMEOUT(1, printk("sg_cmd_done: already closed, freeing ...\n")); - sg_finish_rem_req(srp); - srp = NULL; - if (NULL == sfp->headrp) { - SCSI_LOG_TIMEOUT(1, printk("sg_cmd_done: already closed, final cleanup\n")); - if (0 == sg_remove_sfp(sdp, sfp)) { /* device still present */ - scsi_device_put(sdp->device); - } - sfp = NULL; - } - } else if (srp && srp->orphan) { + write_lock_irqsave(&sfp->rq_list_lock, iflags); + if (unlikely(srp->orphan)) { if (sfp->keep_orphan) srp->sg_io_owned = 0; - else { - sg_finish_rem_req(srp); - srp = NULL; - } + else + done = 0; } - if (sfp && srp) { - /* Now wake up any sg_read() that is waiting for this packet. */ - kill_fasync(&sfp->async_qp, SIGPOLL, POLL_IN); - write_lock_irqsave(&sfp->rq_list_lock, iflags); - srp->done = 1; + srp->done = done; + write_unlock_irqrestore(&sfp->rq_list_lock, iflags); + + if (likely(done)) { + /* Now wake up any sg_read() that is waiting for this + * packet. + */ wake_up_interruptible(&sfp->read_wait); - write_unlock_irqrestore(&sfp->rq_list_lock, iflags); - } + kill_fasync(&sfp->async_qp, SIGPOLL, POLL_IN); + } else + sg_finish_rem_req(srp); /* call with srp->done == 0 */ + + kref_put(&sfp->f_ref, sg_remove_sfp); } static struct file_operations sg_fops = { @@ -1364,17 +1361,18 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) printk(KERN_WARNING "kmalloc Sg_device failure\n"); return ERR_PTR(-ENOMEM); } - error = -ENOMEM; + if (!idr_pre_get(&sg_index_idr, GFP_KERNEL)) { printk(KERN_WARNING "idr expansion Sg_device failure\n"); + error = -ENOMEM; goto out; } write_lock_irqsave(&sg_index_lock, iflags); - error = idr_get_new(&sg_index_idr, sdp, &k); - write_unlock_irqrestore(&sg_index_lock, iflags); + error = idr_get_new(&sg_index_idr, sdp, &k); if (error) { + write_unlock_irqrestore(&sg_index_lock, iflags); printk(KERN_WARNING "idr allocation Sg_device failure: %d\n", error); goto out; @@ -1391,6 +1389,9 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) init_waitqueue_head(&sdp->o_excl_wait); sdp->sg_tablesize = min(q->max_hw_segments, q->max_phys_segments); sdp->index = k; + kref_init(&sdp->d_ref); + + write_unlock_irqrestore(&sg_index_lock, iflags); error = 0; out: @@ -1401,6 +1402,8 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) return sdp; overflow: + idr_remove(&sg_index_idr, k); + write_unlock_irqrestore(&sg_index_lock, iflags); sdev_printk(KERN_WARNING, scsidp, "Unable to attach sg device type=%d, minor " "number exceeds %d\n", scsidp->type, SG_MAX_DEVS - 1); @@ -1488,49 +1491,46 @@ out: return error; } -static void -sg_remove(struct device *cl_dev, struct class_interface *cl_intf) +static void sg_device_destroy(struct kref *kref) +{ + struct sg_device *sdp = container_of(kref, struct sg_device, d_ref); + unsigned long flags; + + /* CAUTION! Note that the device can still be found via idr_find() + * even though the refcount is 0. Therefore, do idr_remove() BEFORE + * any other cleanup. + */ + + write_lock_irqsave(&sg_index_lock, flags); + idr_remove(&sg_index_idr, sdp->index); + write_unlock_irqrestore(&sg_index_lock, flags); + + SCSI_LOG_TIMEOUT(3, + printk("sg_device_destroy: %s\n", + sdp->disk->disk_name)); + + put_disk(sdp->disk); + kfree(sdp); +} + +static void sg_remove(struct device *cl_dev, struct class_interface *cl_intf) { struct scsi_device *scsidp = to_scsi_device(cl_dev->parent); Sg_device *sdp = dev_get_drvdata(cl_dev); unsigned long iflags; Sg_fd *sfp; - Sg_fd *tsfp; - Sg_request *srp; - Sg_request *tsrp; - int delay; - if (!sdp) + if (!sdp || sdp->detached) return; - delay = 0; + SCSI_LOG_TIMEOUT(3, printk("sg_remove: %s\n", sdp->disk->disk_name)); + + /* Need a write lock to set sdp->detached. */ write_lock_irqsave(&sg_index_lock, iflags); - if (sdp->headfp) { - sdp->detached = 1; - for (sfp = sdp->headfp; sfp; sfp = tsfp) { - tsfp = sfp->nextfp; - for (srp = sfp->headrp; srp; srp = tsrp) { - tsrp = srp->nextrp; - if (sfp->closed || (0 == sg_srp_done(srp, sfp))) - sg_finish_rem_req(srp); - } - if (sfp->closed) { - scsi_device_put(sdp->device); - __sg_remove_sfp(sdp, sfp); - } else { - delay = 1; - wake_up_interruptible(&sfp->read_wait); - kill_fasync(&sfp->async_qp, SIGPOLL, - POLL_HUP); - } - } - SCSI_LOG_TIMEOUT(3, printk("sg_remove: dev=%d, dirty\n", sdp->index)); - if (NULL == sdp->headfp) { - idr_remove(&sg_index_idr, sdp->index); - } - } else { /* nothing active, simple case */ - SCSI_LOG_TIMEOUT(3, printk("sg_remove: dev=%d\n", sdp->index)); - idr_remove(&sg_index_idr, sdp->index); + sdp->detached = 1; + for (sfp = sdp->headfp; sfp; sfp = sfp->nextfp) { + wake_up_interruptible(&sfp->read_wait); + kill_fasync(&sfp->async_qp, SIGPOLL, POLL_HUP); } write_unlock_irqrestore(&sg_index_lock, iflags); @@ -1538,13 +1538,8 @@ sg_remove(struct device *cl_dev, struct class_interface *cl_intf) device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, sdp->index)); cdev_del(sdp->cdev); sdp->cdev = NULL; - put_disk(sdp->disk); - sdp->disk = NULL; - if (NULL == sdp->headfp) - kfree(sdp); - if (delay) - msleep(10); /* dirty detach so delay device destruction */ + sg_put_dev(sdp); } module_param_named(scatter_elem_sz, scatter_elem_sz, int, S_IRUGO | S_IWUSR); @@ -1941,22 +1936,6 @@ sg_get_rq_mark(Sg_fd * sfp, int pack_id) return resp; } -#ifdef CONFIG_SCSI_PROC_FS -static Sg_request * -sg_get_nth_request(Sg_fd * sfp, int nth) -{ - Sg_request *resp; - unsigned long iflags; - int k; - - read_lock_irqsave(&sfp->rq_list_lock, iflags); - for (k = 0, resp = sfp->headrp; resp && (k < nth); - ++k, resp = resp->nextrp) ; - read_unlock_irqrestore(&sfp->rq_list_lock, iflags); - return resp; -} -#endif - /* always adds to end of list */ static Sg_request * sg_add_request(Sg_fd * sfp) @@ -2032,22 +2011,6 @@ sg_remove_request(Sg_fd * sfp, Sg_request * srp) return res; } -#ifdef CONFIG_SCSI_PROC_FS -static Sg_fd * -sg_get_nth_sfp(Sg_device * sdp, int nth) -{ - Sg_fd *resp; - unsigned long iflags; - int k; - - read_lock_irqsave(&sg_index_lock, iflags); - for (k = 0, resp = sdp->headfp; resp && (k < nth); - ++k, resp = resp->nextfp) ; - read_unlock_irqrestore(&sg_index_lock, iflags); - return resp; -} -#endif - static Sg_fd * sg_add_sfp(Sg_device * sdp, int dev) { @@ -2062,6 +2025,7 @@ sg_add_sfp(Sg_device * sdp, int dev) init_waitqueue_head(&sfp->read_wait); rwlock_init(&sfp->rq_list_lock); + kref_init(&sfp->f_ref); sfp->timeout = SG_DEFAULT_TIMEOUT; sfp->timeout_user = SG_DEFAULT_TIMEOUT_USER; sfp->force_packid = SG_DEF_FORCE_PACK_ID; @@ -2089,15 +2053,54 @@ sg_add_sfp(Sg_device * sdp, int dev) sg_build_reserve(sfp, bufflen); SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: bufflen=%d, k_use_sg=%d\n", sfp->reserve.bufflen, sfp->reserve.k_use_sg)); + + kref_get(&sdp->d_ref); + __module_get(THIS_MODULE); return sfp; } -static void -__sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp) +static void sg_remove_sfp_usercontext(struct work_struct *work) +{ + struct sg_fd *sfp = container_of(work, struct sg_fd, ew.work); + struct sg_device *sdp = sfp->parentdp; + + /* Cleanup any responses which were never read(). */ + while (sfp->headrp) + sg_finish_rem_req(sfp->headrp); + + if (sfp->reserve.bufflen > 0) { + SCSI_LOG_TIMEOUT(6, + printk("sg_remove_sfp: bufflen=%d, k_use_sg=%d\n", + (int) sfp->reserve.bufflen, + (int) sfp->reserve.k_use_sg)); + sg_remove_scat(&sfp->reserve); + } + + SCSI_LOG_TIMEOUT(6, + printk("sg_remove_sfp: %s, sfp=0x%p\n", + sdp->disk->disk_name, + sfp)); + kfree(sfp); + + scsi_device_put(sdp->device); + sg_put_dev(sdp); + module_put(THIS_MODULE); +} + +static void sg_remove_sfp(struct kref *kref) { + struct sg_fd *sfp = container_of(kref, struct sg_fd, f_ref); + struct sg_device *sdp = sfp->parentdp; Sg_fd *fp; Sg_fd *prev_fp; + unsigned long iflags; + + /* CAUTION! Note that sfp can still be found by walking sdp->headfp + * even though the refcount is now 0. Therefore, unlink sfp from + * sdp->headfp BEFORE doing any other cleanup. + */ + write_lock_irqsave(&sg_index_lock, iflags); prev_fp = sdp->headfp; if (sfp == prev_fp) sdp->headfp = prev_fp->nextfp; @@ -2110,54 +2113,10 @@ __sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp) prev_fp = fp; } } - if (sfp->reserve.bufflen > 0) { - SCSI_LOG_TIMEOUT(6, - printk("__sg_remove_sfp: bufflen=%d, k_use_sg=%d\n", - (int) sfp->reserve.bufflen, (int) sfp->reserve.k_use_sg)); - sg_remove_scat(&sfp->reserve); - } - sfp->parentdp = NULL; - SCSI_LOG_TIMEOUT(6, printk("__sg_remove_sfp: sfp=0x%p\n", sfp)); - kfree(sfp); -} - -/* Returns 0 in normal case, 1 when detached and sdp object removed */ -static int -sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp) -{ - Sg_request *srp; - Sg_request *tsrp; - int dirty = 0; - int res = 0; - - for (srp = sfp->headrp; srp; srp = tsrp) { - tsrp = srp->nextrp; - if (sg_srp_done(srp, sfp)) - sg_finish_rem_req(srp); - else - ++dirty; - } - if (0 == dirty) { - unsigned long iflags; + write_unlock_irqrestore(&sg_index_lock, iflags); + wake_up_interruptible(&sdp->o_excl_wait); - write_lock_irqsave(&sg_index_lock, iflags); - __sg_remove_sfp(sdp, sfp); - if (sdp->detached && (NULL == sdp->headfp)) { - idr_remove(&sg_index_idr, sdp->index); - kfree(sdp); - res = 1; - } - write_unlock_irqrestore(&sg_index_lock, iflags); - } else { - /* MOD_INC's to inhibit unloading sg and associated adapter driver */ - /* only bump the access_count if we actually succeeded in - * throwing another counter on the host module */ - scsi_device_get(sdp->device); /* XXX: retval ignored? */ - sfp->closed = 1; /* flag dirty state on this fd */ - SCSI_LOG_TIMEOUT(1, printk("sg_remove_sfp: worrisome, %d writes pending\n", - dirty)); - } - return res; + execute_in_process_context(sg_remove_sfp_usercontext, &sfp->ew); } static int @@ -2199,19 +2158,38 @@ sg_last_dev(void) } #endif -static Sg_device * -sg_get_dev(int dev) +/* must be called with sg_index_lock held */ +static Sg_device *sg_lookup_dev(int dev) { - Sg_device *sdp; - unsigned long iflags; + return idr_find(&sg_index_idr, dev); +} - read_lock_irqsave(&sg_index_lock, iflags); - sdp = idr_find(&sg_index_idr, dev); - read_unlock_irqrestore(&sg_index_lock, iflags); +static Sg_device *sg_get_dev(int dev) +{ + struct sg_device *sdp; + unsigned long flags; + + read_lock_irqsave(&sg_index_lock, flags); + sdp = sg_lookup_dev(dev); + if (!sdp) + sdp = ERR_PTR(-ENXIO); + else if (sdp->detached) { + /* If sdp->detached, then the refcount may already be 0, in + * which case it would be a bug to do kref_get(). + */ + sdp = ERR_PTR(-ENODEV); + } else + kref_get(&sdp->d_ref); + read_unlock_irqrestore(&sg_index_lock, flags); return sdp; } +static void sg_put_dev(struct sg_device *sdp) +{ + kref_put(&sdp->d_ref, sg_device_destroy); +} + #ifdef CONFIG_SCSI_PROC_FS static struct proc_dir_entry *sg_proc_sgp = NULL; @@ -2468,8 +2446,10 @@ static int sg_proc_seq_show_dev(struct seq_file *s, void *v) struct sg_proc_deviter * it = (struct sg_proc_deviter *) v; Sg_device *sdp; struct scsi_device *scsidp; + unsigned long iflags; - sdp = it ? sg_get_dev(it->index) : NULL; + read_lock_irqsave(&sg_index_lock, iflags); + sdp = it ? sg_lookup_dev(it->index) : NULL; if (sdp && (scsidp = sdp->device) && (!sdp->detached)) seq_printf(s, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", scsidp->host->host_no, scsidp->channel, @@ -2480,6 +2460,7 @@ static int sg_proc_seq_show_dev(struct seq_file *s, void *v) (int) scsi_device_online(scsidp)); else seq_printf(s, "-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\n"); + read_unlock_irqrestore(&sg_index_lock, iflags); return 0; } @@ -2493,16 +2474,20 @@ static int sg_proc_seq_show_devstrs(struct seq_file *s, void *v) struct sg_proc_deviter * it = (struct sg_proc_deviter *) v; Sg_device *sdp; struct scsi_device *scsidp; + unsigned long iflags; - sdp = it ? sg_get_dev(it->index) : NULL; + read_lock_irqsave(&sg_index_lock, iflags); + sdp = it ? sg_lookup_dev(it->index) : NULL; if (sdp && (scsidp = sdp->device) && (!sdp->detached)) seq_printf(s, "%8.8s\t%16.16s\t%4.4s\n", scsidp->vendor, scsidp->model, scsidp->rev); else seq_printf(s, "\n"); + read_unlock_irqrestore(&sg_index_lock, iflags); return 0; } +/* must be called while holding sg_index_lock */ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp) { int k, m, new_interface, blen, usg; @@ -2512,7 +2497,8 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp) const char * cp; unsigned int ms; - for (k = 0; (fp = sg_get_nth_sfp(sdp, k)); ++k) { + for (k = 0, fp = sdp->headfp; fp != NULL; ++k, fp = fp->nextfp) { + read_lock(&fp->rq_list_lock); /* irqs already disabled */ seq_printf(s, " FD(%d): timeout=%dms bufflen=%d " "(res)sgat=%d low_dma=%d\n", k + 1, jiffies_to_msecs(fp->timeout), @@ -2522,7 +2508,9 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp) seq_printf(s, " cmd_q=%d f_packid=%d k_orphan=%d closed=%d\n", (int) fp->cmd_q, (int) fp->force_packid, (int) fp->keep_orphan, (int) fp->closed); - for (m = 0; (srp = sg_get_nth_request(fp, m)); ++m) { + for (m = 0, srp = fp->headrp; + srp != NULL; + ++m, srp = srp->nextrp) { hp = &srp->header; new_interface = (hp->interface_id == '\0') ? 0 : 1; if (srp->res_used) { @@ -2559,6 +2547,7 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp) } if (0 == m) seq_printf(s, " No requests active\n"); + read_unlock(&fp->rq_list_lock); } } @@ -2571,39 +2560,34 @@ static int sg_proc_seq_show_debug(struct seq_file *s, void *v) { struct sg_proc_deviter * it = (struct sg_proc_deviter *) v; Sg_device *sdp; + unsigned long iflags; if (it && (0 == it->index)) { seq_printf(s, "max_active_device=%d(origin 1)\n", (int)it->max); seq_printf(s, " def_reserved_size=%d\n", sg_big_buff); } - sdp = it ? sg_get_dev(it->index) : NULL; - if (sdp) { - struct scsi_device *scsidp = sdp->device; - if (NULL == scsidp) { - seq_printf(s, "device %d detached ??\n", - (int)it->index); - return 0; - } + read_lock_irqsave(&sg_index_lock, iflags); + sdp = it ? sg_lookup_dev(it->index) : NULL; + if (sdp && sdp->headfp) { + struct scsi_device *scsidp = sdp->device; - if (sg_get_nth_sfp(sdp, 0)) { - seq_printf(s, " >>> device=%s ", - sdp->disk->disk_name); - if (sdp->detached) - seq_printf(s, "detached pending close "); - else - seq_printf - (s, "scsi%d chan=%d id=%d lun=%d em=%d", - scsidp->host->host_no, - scsidp->channel, scsidp->id, - scsidp->lun, - scsidp->host->hostt->emulated); - seq_printf(s, " sg_tablesize=%d excl=%d\n", - sdp->sg_tablesize, sdp->exclude); - } + seq_printf(s, " >>> device=%s ", sdp->disk->disk_name); + if (sdp->detached) + seq_printf(s, "detached pending close "); + else + seq_printf + (s, "scsi%d chan=%d id=%d lun=%d em=%d", + scsidp->host->host_no, + scsidp->channel, scsidp->id, + scsidp->lun, + scsidp->host->hostt->emulated); + seq_printf(s, " sg_tablesize=%d excl=%d\n", + sdp->sg_tablesize, sdp->exclude); sg_proc_debug_helper(s, sdp); } + read_unlock_irqrestore(&sg_index_lock, iflags); return 0; } -- GitLab From a2dd3b4cea335713b58996bb07b3abcde1175f47 Mon Sep 17 00:00:00 2001 From: Tony Battersby Date: Tue, 20 Jan 2009 17:00:09 -0500 Subject: [PATCH 3150/4982] [SCSI] sg: fix races with ioctl(SG_IO) sg_io_owned needs to be set before the command is sent to the midlevel; otherwise, a quickly-completing command may cause a different CPU to see "srp->done == 1 && !srp->sg_io_owned", which would lead to incorrect behavior. Check srp->done and set srp->orphan while holding rq_list_lock to prevent races with sg_rq_end_io(). There is no need to check sfp->closed from read/write/ioctl/poll/etc. since the kernel guarantees that this won't happen. The usefulness of sg_srp_done() was questionable before; now it is definitely not needed. Signed-off-by: Tony Battersby Acked-by: Douglas Gilbert Signed-off-by: James Bottomley --- drivers/scsi/sg.c | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index b447527555a..18d079e3990 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -189,7 +189,7 @@ static ssize_t sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp); static ssize_t sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf, size_t count, int blocking, - int read_only, Sg_request **o_srp); + int read_only, int sg_io_owned, Sg_request **o_srp); static int sg_common_write(Sg_fd * sfp, Sg_request * srp, unsigned char *cmnd, int timeout, int blocking); static int sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer); @@ -561,7 +561,8 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) return -EFAULT; blocking = !(filp->f_flags & O_NONBLOCK); if (old_hdr.reply_len < 0) - return sg_new_write(sfp, filp, buf, count, blocking, 0, NULL); + return sg_new_write(sfp, filp, buf, count, + blocking, 0, 0, NULL); if (count < (SZ_SG_HEADER + 6)) return -EIO; /* The minimum scsi command length is 6 bytes. */ @@ -642,7 +643,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) static ssize_t sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf, - size_t count, int blocking, int read_only, + size_t count, int blocking, int read_only, int sg_io_owned, Sg_request **o_srp) { int k; @@ -662,6 +663,7 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf, SCSI_LOG_TIMEOUT(1, printk("sg_new_write: queue full\n")); return -EDOM; } + srp->sg_io_owned = sg_io_owned; hp = &srp->header; if (__copy_from_user(hp, buf, SZ_SG_IO_HDR)) { sg_remove_request(sfp, srp); @@ -765,18 +767,6 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, return 0; } -static int -sg_srp_done(Sg_request *srp, Sg_fd *sfp) -{ - unsigned long iflags; - int done; - - read_lock_irqsave(&sfp->rq_list_lock, iflags); - done = srp->done; - read_unlock_irqrestore(&sfp->rq_list_lock, iflags); - return done; -} - static int sg_ioctl(struct inode *inode, struct file *filp, unsigned int cmd_in, unsigned long arg) @@ -809,27 +799,26 @@ sg_ioctl(struct inode *inode, struct file *filp, return -EFAULT; result = sg_new_write(sfp, filp, p, SZ_SG_IO_HDR, - blocking, read_only, &srp); + blocking, read_only, 1, &srp); if (result < 0) return result; - srp->sg_io_owned = 1; while (1) { result = 0; /* following macro to beat race condition */ __wait_event_interruptible(sfp->read_wait, - (sdp->detached || sfp->closed || sg_srp_done(srp, sfp)), - result); + (srp->done || sdp->detached), + result); if (sdp->detached) return -ENODEV; - if (sfp->closed) - return 0; /* request packet dropped already */ - if (0 == result) + write_lock_irq(&sfp->rq_list_lock); + if (srp->done) { + srp->done = 2; + write_unlock_irq(&sfp->rq_list_lock); break; + } srp->orphan = 1; + write_unlock_irq(&sfp->rq_list_lock); return result; /* -ERESTARTSYS because signal hit process */ } - write_lock_irqsave(&sfp->rq_list_lock, iflags); - srp->done = 2; - write_unlock_irqrestore(&sfp->rq_list_lock, iflags); result = sg_new_read(sfp, p, SZ_SG_IO_HDR, srp); return (result < 0) ? result : 0; } -- GitLab From 71969fd9e2c523d22bf1742eb31f1562247710eb Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Sun, 25 Jan 2009 16:50:02 +0200 Subject: [PATCH 3151/4982] [SCSI] major.h: char-major number for OSD device driver Allocate major 260 for osd. Signed-off-by: Boaz Harrosh CC: Torben Mathiasen Signed-off-by: James Bottomley --- Documentation/devices.txt | 6 ++++++ include/linux/major.h | 1 + 2 files changed, 7 insertions(+) diff --git a/Documentation/devices.txt b/Documentation/devices.txt index 2be08240ee8..62254d4510c 100644 --- a/Documentation/devices.txt +++ b/Documentation/devices.txt @@ -3145,6 +3145,12 @@ Your cooperation is appreciated. 1 = /dev/blockrom1 Second ROM card's translation layer interface ... +260 char OSD (Object-based-device) SCSI Device + 0 = /dev/osd0 First OSD Device + 1 = /dev/osd1 Second OSD Device + ... + 255 = /dev/osd255 256th OSD Device + **** ADDITIONAL /dev DIRECTORY ENTRIES This section details additional entries that should or may exist in diff --git a/include/linux/major.h b/include/linux/major.h index 88249452b93..058ec15dd06 100644 --- a/include/linux/major.h +++ b/include/linux/major.h @@ -171,5 +171,6 @@ #define VIOTAPE_MAJOR 230 #define BLOCK_EXT_MAJOR 259 +#define SCSI_OSD_MAJOR 260 /* open-osd's OSD scsi device */ #endif -- GitLab From 82443a58d361123d418033e9e32ac29a842fce68 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Sun, 25 Jan 2009 16:51:33 +0200 Subject: [PATCH 3152/4982] [SCSI] add OSD_TYPE - Define the OSD_TYPE scsi device and let it show up in scans Signed-off-by: Boaz Harrosh Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 1 + include/scsi/scsi.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 8f4de20c9de..a14d245a66b 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -797,6 +797,7 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, case TYPE_ENCLOSURE: case TYPE_COMM: case TYPE_RAID: + case TYPE_OSD: sdev->writeable = 1; break; case TYPE_ROM: diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 815d4047c4c..80d7f60e266 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -263,6 +263,7 @@ static inline int scsi_status_is_good(int status) #define TYPE_RAID 0x0c #define TYPE_ENCLOSURE 0x0d /* Enclosure Services Device */ #define TYPE_RBC 0x0e +#define TYPE_OSD 0x11 #define TYPE_NO_LUN 0x7f /* SCSI protocols; these are taken from SPC-3 section 7.5 */ -- GitLab From de258bf5e63863f42e0f9a7c5ffd29916a41e399 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Sun, 25 Jan 2009 16:54:10 +0200 Subject: [PATCH 3153/4982] [SCSI] libosd: OSDv1 Headers Headers only patch. osd_protocol.h Contains a C-fied definition of the T10 OSD standard osd_types.h Contains CPU order common used types osd_initiator.h API definition of the osd_initiator library osd_sec.h Contains High level API for the security manager. [Note that checkpatch spews errors on things that are valid in this context and will not be fixed] Signed-off-by: Boaz Harrosh Reviewed-by: Benny Halevy Signed-off-by: James Bottomley --- include/scsi/osd_initiator.h | 332 +++++++++++++++++++++++ include/scsi/osd_protocol.h | 497 +++++++++++++++++++++++++++++++++++ include/scsi/osd_sec.h | 45 ++++ include/scsi/osd_types.h | 40 +++ 4 files changed, 914 insertions(+) create mode 100644 include/scsi/osd_initiator.h create mode 100644 include/scsi/osd_protocol.h create mode 100644 include/scsi/osd_sec.h create mode 100644 include/scsi/osd_types.h diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h new file mode 100644 index 00000000000..1d92247f820 --- /dev/null +++ b/include/scsi/osd_initiator.h @@ -0,0 +1,332 @@ +/* + * osd_initiator.h - OSD initiator API definition + * + * Copyright (C) 2008 Panasas Inc. All rights reserved. + * + * Authors: + * Boaz Harrosh + * Benny Halevy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * + */ +#ifndef __OSD_INITIATOR_H__ +#define __OSD_INITIATOR_H__ + +#include "osd_protocol.h" +#include "osd_types.h" + +#include + +/* Note: "NI" in comments below means "Not Implemented yet" */ + +/* + * Object-based Storage Device. + * This object represents an OSD device. + * It is not a full linux device in any way. It is only + * a place to hang resources associated with a Linux + * request Q and some default properties. + */ +struct osd_dev { + struct scsi_device *scsi_device; + unsigned def_timeout; +}; + +void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device); +void osd_dev_fini(struct osd_dev *od); + +struct osd_request; +typedef void (osd_req_done_fn)(struct osd_request *or, void *private); + +struct osd_request { + struct osd_cdb cdb; + struct osd_data_out_integrity_info out_data_integ; + struct osd_data_in_integrity_info in_data_integ; + + struct osd_dev *osd_dev; + struct request *request; + + struct _osd_req_data_segment { + void *buff; + unsigned alloc_size; /* 0 here means: don't call kfree */ + unsigned total_bytes; + } set_attr, enc_get_attr, get_attr; + + struct _osd_io_info { + struct bio *bio; + u64 total_bytes; + struct request *req; + struct _osd_req_data_segment *last_seg; + u8 *pad_buff; + } out, in; + + gfp_t alloc_flags; + unsigned timeout; + unsigned retries; + u8 sense[OSD_MAX_SENSE_LEN]; + enum osd_attributes_mode attributes_mode; + + osd_req_done_fn *async_done; + void *async_private; + int async_error; +}; + +/* + * How to use the osd library: + * + * osd_start_request + * Allocates a request. + * + * osd_req_* + * Call one of, to encode the desired operation. + * + * osd_add_{get,set}_attr + * Optionally add attributes to the CDB, list or page mode. + * + * osd_finalize_request + * Computes final data out/in offsets and signs the request, + * making it ready for execution. + * + * osd_execute_request + * May be called to execute it through the block layer. Other wise submit + * the associated block request in some other way. + * + * After execution: + * osd_req_decode_sense + * Decodes sense information to verify execution results. + * + * osd_req_decode_get_attr + * Retrieve osd_add_get_attr_list() values if used. + * + * osd_end_request + * Must be called to deallocate the request. + */ + +/** + * osd_start_request - Allocate and initialize an osd_request + * + * @osd_dev: OSD device that holds the scsi-device and default values + * that the request is associated with. + * @gfp: The allocation flags to use for request allocation, and all + * subsequent allocations. This will be stored at + * osd_request->alloc_flags, can be changed by user later + * + * Allocate osd_request and initialize all members to the + * default/initial state. + */ +struct osd_request *osd_start_request(struct osd_dev *od, gfp_t gfp); + +enum osd_req_options { + OSD_REQ_FUA = 0x08, /* Force Unit Access */ + OSD_REQ_DPO = 0x10, /* Disable Page Out */ + + OSD_REQ_BYPASS_TIMESTAMPS = 0x80, +}; + +/** + * osd_finalize_request - Sign request and prepare request for execution + * + * @or: osd_request to prepare + * @options: combination of osd_req_options bit flags or 0. + * @cap: A Pointer to an OSD_CAP_LEN bytes buffer that is received from + * The security manager as capabilities for this cdb. + * @cap_key: The cryptographic key used to sign the cdb/data. Can be null + * if NOSEC is used. + * + * The actual request and bios are only allocated here, so are the get_attr + * buffers that will receive the returned attributes. Copy's @cap to cdb. + * Sign the cdb/data with @cap_key. + */ +int osd_finalize_request(struct osd_request *or, + u8 options, const void *cap, const u8 *cap_key); + +/** + * osd_execute_request - Execute the request synchronously through block-layer + * + * @or: osd_request to Executed + * + * Calls blk_execute_rq to q the command and waits for completion. + */ +int osd_execute_request(struct osd_request *or); + +/** + * osd_execute_request_async - Execute the request without waitting. + * + * @or: - osd_request to Executed + * @done: (Optional) - Called at end of execution + * @private: - Will be passed to @done function + * + * Calls blk_execute_rq_nowait to queue the command. When execution is done + * optionally calls @done with @private as parameter. @or->async_error will + * have the return code + */ +int osd_execute_request_async(struct osd_request *or, + osd_req_done_fn *done, void *private); + +/** + * osd_end_request - return osd_request to free store + * + * @or: osd_request to free + * + * Deallocate all osd_request resources (struct req's, BIOs, buffers, etc.) + */ +void osd_end_request(struct osd_request *or); + +/* + * CDB Encoding + * + * Note: call only one of the following methods. + */ + +/* + * Device commands + */ +void osd_req_set_master_seed_xchg(struct osd_request *or, ...);/* NI */ +void osd_req_set_master_key(struct osd_request *or, ...);/* NI */ + +void osd_req_format(struct osd_request *or, u64 tot_capacity); + +/* list all partitions + * @list header must be initialized to zero on first run. + * + * Call osd_is_obj_list_done() to find if we got the complete list. + */ +int osd_req_list_dev_partitions(struct osd_request *or, + osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem); + +void osd_req_flush_obsd(struct osd_request *or, + enum osd_options_flush_scope_values); + +void osd_req_perform_scsi_command(struct osd_request *or, + const u8 *cdb, ...);/* NI */ +void osd_req_task_management(struct osd_request *or, ...);/* NI */ + +/* + * Partition commands + */ +void osd_req_create_partition(struct osd_request *or, osd_id partition); +void osd_req_remove_partition(struct osd_request *or, osd_id partition); + +void osd_req_set_partition_key(struct osd_request *or, + osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE], + u8 seed[OSD_CRYPTO_SEED_SIZE]);/* NI */ + +/* list all collections in the partition + * @list header must be init to zero on first run. + * + * Call osd_is_obj_list_done() to find if we got the complete list. + */ +int osd_req_list_partition_collections(struct osd_request *or, + osd_id partition, osd_id initial_id, struct osd_obj_id_list *list, + unsigned nelem); + +/* list all objects in the partition + * @list header must be init to zero on first run. + * + * Call osd_is_obj_list_done() to find if we got the complete list. + */ +int osd_req_list_partition_objects(struct osd_request *or, + osd_id partition, osd_id initial_id, struct osd_obj_id_list *list, + unsigned nelem); + +void osd_req_flush_partition(struct osd_request *or, + osd_id partition, enum osd_options_flush_scope_values); + +/* + * Collection commands + */ +void osd_req_create_collection(struct osd_request *or, + const struct osd_obj_id *);/* NI */ +void osd_req_remove_collection(struct osd_request *or, + const struct osd_obj_id *);/* NI */ + +/* list all objects in the collection */ +int osd_req_list_collection_objects(struct osd_request *or, + const struct osd_obj_id *, osd_id initial_id, + struct osd_obj_id_list *list, unsigned nelem); + +/* V2 only filtered list of objects in the collection */ +void osd_req_query(struct osd_request *or, ...);/* NI */ + +void osd_req_flush_collection(struct osd_request *or, + const struct osd_obj_id *, enum osd_options_flush_scope_values); + +void osd_req_get_member_attrs(struct osd_request *or, ...);/* V2-only NI */ +void osd_req_set_member_attrs(struct osd_request *or, ...);/* V2-only NI */ + +/* + * Object commands + */ +void osd_req_create_object(struct osd_request *or, struct osd_obj_id *); +void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *); + +void osd_req_write(struct osd_request *or, + const struct osd_obj_id *, struct bio *data_out, u64 offset); +void osd_req_append(struct osd_request *or, + const struct osd_obj_id *, struct bio *data_out);/* NI */ +void osd_req_create_write(struct osd_request *or, + const struct osd_obj_id *, struct bio *data_out, u64 offset);/* NI */ +void osd_req_clear(struct osd_request *or, + const struct osd_obj_id *, u64 offset, u64 len);/* NI */ +void osd_req_punch(struct osd_request *or, + const struct osd_obj_id *, u64 offset, u64 len);/* V2-only NI */ + +void osd_req_flush_object(struct osd_request *or, + const struct osd_obj_id *, enum osd_options_flush_scope_values, + /*V2*/ u64 offset, /*V2*/ u64 len); + +void osd_req_read(struct osd_request *or, + const struct osd_obj_id *, struct bio *data_in, u64 offset); + +/* + * Root/Partition/Collection/Object Attributes commands + */ + +/* get before set */ +void osd_req_get_attributes(struct osd_request *or, const struct osd_obj_id *); + +/* set before get */ +void osd_req_set_attributes(struct osd_request *or, const struct osd_obj_id *); + +/* + * Attributes appended to most commands + */ + +/* Attributes List mode (or V2 CDB) */ + /* + * TODO: In ver2 if at finalize time only one attr was set and no gets, + * then the Attributes CDB mode is used automatically to save IO. + */ + +/* set a list of attributes. */ +int osd_req_add_set_attr_list(struct osd_request *or, + const struct osd_attr *, unsigned nelem); + +/* get a list of attributes */ +int osd_req_add_get_attr_list(struct osd_request *or, + const struct osd_attr *, unsigned nelem); + +/* + * Attributes list decoding + * Must be called after osd_request.request was executed + * It is called in a loop to decode the returned get_attr + * (see osd_add_get_attr) + */ +int osd_req_decode_get_attr_list(struct osd_request *or, + struct osd_attr *, int *nelem, void **iterator); + +/* Attributes Page mode */ + +/* + * Read an attribute page and optionally set one attribute + * + * Retrieves the attribute page directly to a user buffer. + * @attr_page_data shall stay valid until end of execution. + * See osd_attributes.h for common page structures + */ +int osd_req_add_get_attr_page(struct osd_request *or, + u32 page_id, void *attr_page_data, unsigned max_page_len, + const struct osd_attr *set_one); + +#endif /* __OSD_LIB_H__ */ diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h new file mode 100644 index 00000000000..ce1a8771ea7 --- /dev/null +++ b/include/scsi/osd_protocol.h @@ -0,0 +1,497 @@ +/* + * osd_protocol.h - OSD T10 standard C definitions. + * + * Copyright (C) 2008 Panasas Inc. All rights reserved. + * + * Authors: + * Boaz Harrosh + * Benny Halevy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * + * This file contains types and constants that are defined by the protocol + * Note: All names and symbols are taken from the OSD standard's text. + */ +#ifndef __OSD_PROTOCOL_H__ +#define __OSD_PROTOCOL_H__ + +#include +#include +#include + +enum { + OSDv1_ADDITIONAL_CDB_LENGTH = 192, + OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8, + OSDv1_CAP_LEN = 80, + /* Latest supported version */ + OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH, + OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN, + OSD_CAP_LEN = OSDv1_CAP_LEN, + + OSD_SYSTEMID_LEN = 20, + OSD_CRYPTO_KEYID_SIZE = 20, + OSD_CRYPTO_SEED_SIZE = 4, + OSD_CRYPTO_NONCE_SIZE = 12, + OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */ + + OSD_PARTITION_FIRST_ID = 0x10000, + OSD_OBJECT_FIRST_ID = 0x10000, +}; + +/* (osd-r10 5.2.4) + * osd2r03: 5.2.3 Caching control bits + */ +enum osd_options_byte { + OSD_CDB_FUA = 0x08, /* Force Unit Access */ + OSD_CDB_DPO = 0x10, /* Disable Page Out */ +}; + +/* + * osd2r03: 5.2.5 Isolation. + * First 3 bits, V2-only. + * Also for attr 110h "default isolation method" at Root Information page + */ +enum osd_options_byte_isolation { + OSD_ISOLATION_DEFAULT = 0, + OSD_ISOLATION_NONE = 1, + OSD_ISOLATION_STRICT = 2, + OSD_ISOLATION_RANGE = 4, + OSD_ISOLATION_FUNCTIONAL = 5, + OSD_ISOLATION_VENDOR = 7, +}; + +/* (osd-r10: 6.7) + * osd2r03: 6.8 FLUSH, FLUSH COLLECTION, FLUSH OSD, FLUSH PARTITION + */ +enum osd_options_flush_scope_values { + OSD_CDB_FLUSH_ALL = 0, + OSD_CDB_FLUSH_ATTR_ONLY = 1, + + OSD_CDB_FLUSH_ALL_RECURSIVE = 2, + /* V2-only */ + OSD_CDB_FLUSH_ALL_RANGE = 2, +}; + +/* osd2r03: 5.2.10 Timestamps control */ +enum { + OSD_CDB_NORMAL_TIMESTAMPS = 0, + OSD_CDB_BYPASS_TIMESTAMPS = 0x7f, +}; + +/* (osd-r10: 5.2.2.1) + * osd2r03: 5.2.4.1 Get and set attributes CDB format selection + * 2 bits at second nibble of command_specific_options byte + */ +enum osd_attributes_mode { + /* V2-only */ + OSD_CDB_SET_ONE_ATTR = 0x10, + + OSD_CDB_GET_ATTR_PAGE_SET_ONE = 0x20, + OSD_CDB_GET_SET_ATTR_LISTS = 0x30, + + OSD_CDB_GET_SET_ATTR_MASK = 0x30, +}; + +/* (osd-r10: 4.12.5) + * osd2r03: 4.14.5 Data-In and Data-Out buffer offsets + * byte offset = mantissa * (2^(exponent+8)) + * struct { + * unsigned mantissa: 28; + * int exponent: 04; + * } + */ +typedef __be32 __bitwise osd_cdb_offset; + +enum { + OSD_OFFSET_UNUSED = 0xFFFFFFFF, + OSD_OFFSET_MAX_BITS = 28, + + OSDv1_OFFSET_MIN_SHIFT = 8, + OSD_OFFSET_MAX_SHIFT = 16, +}; + +/* Return the smallest allowed encoded offset that contains @offset. + * + * The actual encoded offset returned is @offset + *padding. + * (up to max_shift, non-inclusive) + */ +osd_cdb_offset __osd_encode_offset(u64 offset, unsigned *padding, + int min_shift, int max_shift); + +/* Minimum alignment is 256 bytes + * Note: Seems from std v1 that exponent can be from 0+8 to 0xE+8 (inclusive) + * which is 8 to 23 but IBM code restricts it to 16, so be it. + */ +static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding) +{ + return __osd_encode_offset(offset, padding, + OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT); +} + +/* osd2r03: 5.2.1 Overview */ +struct osd_cdb_head { + struct scsi_varlen_cdb_hdr varlen_cdb; +/*10*/ u8 options; + u8 command_specific_options; + u8 timestamp_control; +/*13*/ u8 reserved1[3]; +/*16*/ __be64 partition; +/*24*/ __be64 object; +/*32*/ union { /* V1 vs V2 alignment differences */ + struct __osdv1_cdb_addr_len { +/*32*/ __be32 list_identifier;/* Rarely used */ +/*36*/ __be64 length; +/*44*/ __be64 start_address; + } __packed v1; + }; +/*52*/ union { /* selected attributes mode Page/List/Single */ + struct osd_attributes_page_mode { +/*52*/ __be32 get_attr_page; +/*56*/ __be32 get_attr_alloc_length; +/*60*/ osd_cdb_offset get_attr_offset; + +/*64*/ __be32 set_attr_page; +/*68*/ __be32 set_attr_id; +/*72*/ __be32 set_attr_length; +/*76*/ osd_cdb_offset set_attr_offset; +/*80*/ } __packed attrs_page; + + struct osd_attributes_list_mode { +/*52*/ __be32 get_attr_desc_bytes; +/*56*/ osd_cdb_offset get_attr_desc_offset; + +/*60*/ __be32 get_attr_alloc_length; +/*64*/ osd_cdb_offset get_attr_offset; + +/*68*/ __be32 set_attr_bytes; +/*72*/ osd_cdb_offset set_attr_offset; + __be32 not_used; +/*80*/ } __packed attrs_list; + + /* osd2r03:5.2.4.2 Set one attribute value using CDB fields */ + struct osd_attributes_cdb_mode { +/*52*/ __be32 set_attr_page; +/*56*/ __be32 set_attr_id; +/*60*/ __be16 set_attr_len; +/*62*/ u8 set_attr_val[18]; +/*80*/ } __packed attrs_cdb; +/*52*/ u8 get_set_attributes_parameters[28]; + }; +} __packed; +/*80*/ + +/*160 v1*/ +struct osd_security_parameters { +/*160*/u8 integrity_check_value[OSD_CRYPTO_KEYID_SIZE]; +/*180*/u8 request_nonce[OSD_CRYPTO_NONCE_SIZE]; +/*192*/osd_cdb_offset data_in_integrity_check_offset; +/*196*/osd_cdb_offset data_out_integrity_check_offset; +} __packed; +/*200 v1*/ + +struct osdv1_cdb { + struct osd_cdb_head h; + u8 caps[OSDv1_CAP_LEN]; + struct osd_security_parameters sec_params; +} __packed; + +struct osd_cdb { + union { + struct osdv1_cdb v1; + u8 buff[OSD_TOTAL_CDB_LEN]; + }; +} __packed; + +static inline struct osd_cdb_head *osd_cdb_head(struct osd_cdb *ocdb) +{ + return (struct osd_cdb_head *)ocdb->buff; +} + +/* define both version actions + * Ex name = FORMAT_OSD we have OSD_ACT_FORMAT_OSD && OSDv1_ACT_FORMAT_OSD + */ +#define OSD_ACT___(Name, Num) \ + OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num), \ + OSDv1_ACT_##Name = __constant_cpu_to_be16(0x8800 + Num), + +/* V2 only actions */ +#define OSD_ACT_V2(Name, Num) \ + OSD_ACT_##Name = __constant_cpu_to_be16(0x8880 + Num), + +#define OSD_ACT_V1_V2(Name, Num1, Num2) \ + OSD_ACT_##Name = __constant_cpu_to_be16(Num2), \ + OSDv1_ACT_##Name = __constant_cpu_to_be16(Num1), + +enum osd_service_actions { + OSD_ACT_V2(OBJECT_STRUCTURE_CHECK, 0x00) + OSD_ACT___(FORMAT_OSD, 0x01) + OSD_ACT___(CREATE, 0x02) + OSD_ACT___(LIST, 0x03) + OSD_ACT_V2(PUNCH, 0x04) + OSD_ACT___(READ, 0x05) + OSD_ACT___(WRITE, 0x06) + OSD_ACT___(APPEND, 0x07) + OSD_ACT___(FLUSH, 0x08) + OSD_ACT_V2(CLEAR, 0x09) + OSD_ACT___(REMOVE, 0x0A) + OSD_ACT___(CREATE_PARTITION, 0x0B) + OSD_ACT___(REMOVE_PARTITION, 0x0C) + OSD_ACT___(GET_ATTRIBUTES, 0x0E) + OSD_ACT___(SET_ATTRIBUTES, 0x0F) + OSD_ACT___(CREATE_AND_WRITE, 0x12) + OSD_ACT___(CREATE_COLLECTION, 0x15) + OSD_ACT___(REMOVE_COLLECTION, 0x16) + OSD_ACT___(LIST_COLLECTION, 0x17) + OSD_ACT___(SET_KEY, 0x18) + OSD_ACT___(SET_MASTER_KEY, 0x19) + OSD_ACT___(FLUSH_COLLECTION, 0x1A) + OSD_ACT___(FLUSH_PARTITION, 0x1B) + OSD_ACT___(FLUSH_OSD, 0x1C) + + OSD_ACT_V2(QUERY, 0x20) + OSD_ACT_V2(REMOVE_MEMBER_OBJECTS, 0x21) + OSD_ACT_V2(GET_MEMBER_ATTRIBUTES, 0x22) + OSD_ACT_V2(SET_MEMBER_ATTRIBUTES, 0x23) + OSD_ACT_V2(READ_MAP, 0x31) + + OSD_ACT_V1_V2(PERFORM_SCSI_COMMAND, 0x8F7E, 0x8F7C) + OSD_ACT_V1_V2(SCSI_TASK_MANAGEMENT, 0x8F7F, 0x8F7D) + /* 0x8F80 to 0x8FFF are Vendor specific */ +}; + +/* osd2r03: 7.1.3.2 List entry format for retrieving attributes */ +struct osd_attributes_list_attrid { + __be32 attr_page; + __be32 attr_id; +} __packed; + +/* + * osd2r03: 7.1.3.3 List entry format for retrieved attributes and + * for setting attributes + */ +struct osd_attributes_list_element { + __be32 attr_page; + __be32 attr_id; + __be16 attr_bytes; + u8 attr_val[0]; +} __packed; + +enum { + OSDv1_ATTRIBUTES_ELEM_ALIGN = 1, +}; + +enum { + OSD_ATTR_LIST_ALL_PAGES = 0xFFFFFFFF, + OSD_ATTR_LIST_ALL_IN_PAGE = 0xFFFFFFFF, +}; + +static inline unsigned osdv1_attr_list_elem_size(unsigned len) +{ + return ALIGN(len + sizeof(struct osd_attributes_list_element), + OSDv1_ATTRIBUTES_ELEM_ALIGN); +} + +/* + * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values + */ +enum osd_attr_list_types { + OSD_ATTR_LIST_GET = 0x1, /* descriptors only */ + OSD_ATTR_LIST_SET_RETRIEVE = 0x9, /*descriptors/values variable-length*/ + OSD_V2_ATTR_LIST_MULTIPLE = 0xE, /* ver2, Multiple Objects lists*/ + OSD_V1_ATTR_LIST_CREATE_MULTIPLE = 0xF,/*ver1, used by create_multple*/ +}; + +/* osd2r03: 7.1.3.4 Multi-object retrieved attributes format */ +struct osd_attributes_list_multi_header { + __be64 object_id; + u8 object_type; /* object_type enum below */ + u8 reserved[5]; + __be16 list_bytes; + /* followed by struct osd_attributes_list_element's */ +}; + +struct osdv1_attributes_list_header { + u8 type; /* low 4-bit only */ + u8 pad; + __be16 list_bytes; /* Initiator shall set to Zero. Only set by target */ + /* + * type=9 followed by struct osd_attributes_list_element's + * type=E followed by struct osd_attributes_list_multi_header's + */ +} __packed; + +static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h) +{ + return be16_to_cpu(h->list_bytes); +} + +/* (osd-r10 6.13) + * osd2r03: 6.15 LIST (Table 79) LIST command parameter data. + * for root_lstchg below + */ +enum { + OSD_OBJ_ID_LIST_PAR = 0x1, /* V1-only. Not used in V2 */ + OSD_OBJ_ID_LIST_LSTCHG = 0x2, +}; + +/* + * osd2r03: 6.15.2 LIST command parameter data + * (Also for LIST COLLECTION) + */ +struct osd_obj_id_list { + __be64 list_bytes; /* bytes in list excluding list_bytes (-8) */ + __be64 continuation_id; + __be32 list_identifier; + u8 pad[3]; + u8 root_lstchg; + __be64 object_ids[0]; +} __packed; + +static inline bool osd_is_obj_list_done(struct osd_obj_id_list *list, + bool *is_changed) +{ + *is_changed = (0 != (list->root_lstchg & OSD_OBJ_ID_LIST_LSTCHG)); + return 0 != list->continuation_id; +} + +/* + * osd2r03: 4.12.4.5 The ALLDATA security method + */ +struct osd_data_out_integrity_info { + __be64 data_bytes; + __be64 set_attributes_bytes; + __be64 get_attributes_bytes; + __be64 integrity_check_value; +} __packed; + +struct osd_data_in_integrity_info { + __be64 data_bytes; + __be64 retrieved_attributes_bytes; + __be64 integrity_check_value; +} __packed; + +struct osd_timestamp { + u8 time[6]; /* number of milliseconds since 1/1/1970 UT (big endian) */ +} __packed; +/* FIXME: define helper functions to convert to/from osd time format */ + +/* + * Capability & Security definitions + * osd2r03: 4.11.2.2 Capability format + * osd2r03: 5.2.8 Security parameters + */ + +struct osd_key_identifier { + u8 id[7]; /* if you know why 7 please email bharrosh@panasas.com */ +} __packed; + +/* for osd_capability.format */ +enum { + OSD_SEC_CAP_FORMAT_NO_CAPS = 0, + OSD_SEC_CAP_FORMAT_VER1 = 1, + OSD_SEC_CAP_FORMAT_VER2 = 2, +}; + +/* security_method */ +enum { + OSD_SEC_NOSEC = 0, + OSD_SEC_CAPKEY = 1, + OSD_SEC_CMDRSP = 2, + OSD_SEC_ALLDATA = 3, +}; + +enum object_type { + OSD_SEC_OBJ_ROOT = 0x1, + OSD_SEC_OBJ_PARTITION = 0x2, + OSD_SEC_OBJ_COLLECTION = 0x40, + OSD_SEC_OBJ_USER = 0x80, +}; + +enum osd_capability_bit_masks { + OSD_SEC_CAP_APPEND = BIT(0), + OSD_SEC_CAP_OBJ_MGMT = BIT(1), + OSD_SEC_CAP_REMOVE = BIT(2), + OSD_SEC_CAP_CREATE = BIT(3), + OSD_SEC_CAP_SET_ATTR = BIT(4), + OSD_SEC_CAP_GET_ATTR = BIT(5), + OSD_SEC_CAP_WRITE = BIT(6), + OSD_SEC_CAP_READ = BIT(7), + + OSD_SEC_CAP_NONE1 = BIT(8), + OSD_SEC_CAP_NONE2 = BIT(9), + OSD_SEC_CAP_NONE3 = BIT(10), + OSD_SEC_CAP_QUERY = BIT(11), /*v2 only*/ + OSD_SEC_CAP_M_OBJECT = BIT(12), /*v2 only*/ + OSD_SEC_CAP_POL_SEC = BIT(13), + OSD_SEC_CAP_GLOBAL = BIT(14), + OSD_SEC_CAP_DEV_MGMT = BIT(15), +}; + +/* for object_descriptor_type (hi nibble used) */ +enum { + OSD_SEC_OBJ_DESC_NONE = 0, /* Not allowed */ + OSD_SEC_OBJ_DESC_OBJ = 1 << 4, /* v1: also collection */ + OSD_SEC_OBJ_DESC_PAR = 2 << 4, /* also root */ + OSD_SEC_OBJ_DESC_COL = 3 << 4, /* v2 only */ +}; + +/* (osd-r10:4.9.2.2) + * osd2r03:4.11.2.2 Capability format + */ +struct osd_capability_head { + u8 format; /* low nibble */ + u8 integrity_algorithm__key_version; /* MAKE_BYTE(integ_alg, key_ver) */ + u8 security_method; + u8 reserved1; +/*04*/ struct osd_timestamp expiration_time; +/*10*/ u8 audit[20]; +/*30*/ u8 discriminator[12]; +/*42*/ struct osd_timestamp object_created_time; +/*48*/ u8 object_type; +/*49*/ u8 permissions_bit_mask[5]; +/*54*/ u8 reserved2; +/*55*/ u8 object_descriptor_type; /* high nibble */ +} __packed; + +/*56 v1*/ +struct osdv1_cap_object_descriptor { + union { + struct { +/*56*/ __be32 policy_access_tag; +/*60*/ __be64 allowed_partition_id; +/*68*/ __be64 allowed_object_id; +/*76*/ __be32 reserved; + } __packed obj_desc; + +/*56*/ u8 object_descriptor[24]; + }; +} __packed; +/*80 v1*/ + +struct osd_capability { + struct osd_capability_head h; + struct osdv1_cap_object_descriptor od; +} __packed; + +/** + * osd_sec_set_caps - set cap-bits into the capabilities header + * + * @cap: The osd_capability_head to set cap bits to. + * @bit_mask: Use an ORed list of enum osd_capability_bit_masks values + * + * permissions_bit_mask is unaligned use below to set into caps + * in a version independent way + */ +static inline void osd_sec_set_caps(struct osd_capability_head *cap, + u16 bit_mask) +{ + /* + *Note: The bits above are defined LE order this is because this way + * they can grow in the future to more then 16, and still retain + * there constant values. + */ + put_unaligned_le16(bit_mask, &cap->permissions_bit_mask); +} + +#endif /* ndef __OSD_PROTOCOL_H__ */ diff --git a/include/scsi/osd_sec.h b/include/scsi/osd_sec.h new file mode 100644 index 00000000000..4c09fee8ae1 --- /dev/null +++ b/include/scsi/osd_sec.h @@ -0,0 +1,45 @@ +/* + * osd_sec.h - OSD security manager API + * + * Copyright (C) 2008 Panasas Inc. All rights reserved. + * + * Authors: + * Boaz Harrosh + * Benny Halevy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * + */ +#ifndef __OSD_SEC_H__ +#define __OSD_SEC_H__ + +#include "osd_protocol.h" +#include "osd_types.h" + +/* + * Contains types and constants of osd capabilities and security + * encoding/decoding. + * API is trying to keep security abstract so initiator of an object + * based pNFS client knows as little as possible about security and + * capabilities. It is the Server's osd-initiator place to know more. + * Also can be used by osd-target. + */ +void osd_sec_encode_caps(void *caps, ...);/* NI */ +void osd_sec_init_nosec_doall_caps(void *caps, + const struct osd_obj_id *obj, bool is_collection, const bool is_v1); + +bool osd_is_sec_alldata(struct osd_security_parameters *sec_params); + +/* Conditionally sign the CDB according to security setting in ocdb + * with cap_key */ +void osd_sec_sign_cdb(struct osd_cdb *ocdb, const u8 *cap_key); + +/* Unconditionally sign the BIO data with cap_key. + * Check for osd_is_sec_alldata() was done prior to calling this. */ +void osd_sec_sign_data(void *data_integ, struct bio *bio, const u8 *cap_key); + +/* Version independent copy of caps into the cdb */ +void osd_set_caps(struct osd_cdb *cdb, const void *caps); + +#endif /* ndef __OSD_SEC_H__ */ diff --git a/include/scsi/osd_types.h b/include/scsi/osd_types.h new file mode 100644 index 00000000000..3f5e88cc75c --- /dev/null +++ b/include/scsi/osd_types.h @@ -0,0 +1,40 @@ +/* + * osd_types.h - Types and constants which are not part of the protocol. + * + * Copyright (C) 2008 Panasas Inc. All rights reserved. + * + * Authors: + * Boaz Harrosh + * Benny Halevy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * + * Contains types and constants that are implementation specific and are + * used by more than one part of the osd library. + * (Eg initiator/target/security_manager/...) + */ +#ifndef __OSD_TYPES_H__ +#define __OSD_TYPES_H__ + +struct osd_systemid { + u8 data[OSD_SYSTEMID_LEN]; +}; + +typedef u64 __bitwise osd_id; + +struct osd_obj_id { + osd_id partition; + osd_id id; +}; + +static const struct __weak osd_obj_id osd_root_object = {0, 0}; + +struct osd_attr { + u32 attr_page; + u32 attr_id; + u16 len; /* byte count of operand */ + void *val_ptr; /* in network order */ +}; + +#endif /* ndef __OSD_TYPES_H__ */ -- GitLab From 02941a530ef736210b4cf8b24dd34c238d5d5a40 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Sun, 25 Jan 2009 16:55:30 +0200 Subject: [PATCH 3154/4982] [SCSI] libosd: OSDv1 preliminary implementation Implementation of the most basic OSD functionality and infrastructure. Mainly Format, Create/Remove Partition, Create/Remove Object, and read/write. - Add Makefile and Kbuild to compile libosd.ko - osd_initiator.c Implementation file for osd_initiator.h and osd_sec.h APIs - osd_debug.h - Some kprintf macro definitions Signed-off-by: Boaz Harrosh Reviewed-by: Benny Halevy Signed-off-by: James Bottomley --- drivers/scsi/osd/Kbuild | 32 +++ drivers/scsi/osd/Makefile | 37 +++ drivers/scsi/osd/osd_debug.h | 30 +++ drivers/scsi/osd/osd_initiator.c | 448 +++++++++++++++++++++++++++++++ 4 files changed, 547 insertions(+) create mode 100644 drivers/scsi/osd/Kbuild create mode 100755 drivers/scsi/osd/Makefile create mode 100644 drivers/scsi/osd/osd_debug.h create mode 100644 drivers/scsi/osd/osd_initiator.c diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild new file mode 100644 index 00000000000..a95e0251005 --- /dev/null +++ b/drivers/scsi/osd/Kbuild @@ -0,0 +1,32 @@ +# +# Kbuild for the OSD modules +# +# Copyright (C) 2008 Panasas Inc. All rights reserved. +# +# Authors: +# Boaz Harrosh +# Benny Halevy +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 +# + +ifneq ($(OSD_INC),) +# we are built out-of-tree Kconfigure everything as on + +CONFIG_SCSI_OSD_INITIATOR=m +ccflags-y += -DCONFIG_SCSI_OSD_INITIATOR -DCONFIG_SCSI_OSD_INITIATOR_MODULE + +# Uncomment to turn debug on +# ccflags-y += -DCONFIG_SCSI_OSD_DEBUG + +# if we are built out-of-tree and the hosting kernel has OSD headers +# then "ccflags-y +=" will not pick the out-off-tree headers. Only by doing +# this it will work. This might break in future kernels +LINUXINCLUDE := -I$(OSD_INC) $(LINUXINCLUDE) + +endif + +# libosd.ko - osd-initiator library +libosd-y := osd_initiator.o +obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o diff --git a/drivers/scsi/osd/Makefile b/drivers/scsi/osd/Makefile new file mode 100755 index 00000000000..d905344f83b --- /dev/null +++ b/drivers/scsi/osd/Makefile @@ -0,0 +1,37 @@ +# +# Makefile for the OSD modules (out of tree) +# +# Copyright (C) 2008 Panasas Inc. All rights reserved. +# +# Authors: +# Boaz Harrosh +# Benny Halevy +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 +# +# This Makefile is used to call the kernel Makefile in case of an out-of-tree +# build. +# $KSRC should point to a Kernel source tree otherwise host's default is +# used. (eg. /lib/modules/`uname -r`/build) + +# include path for out-of-tree Headers +OSD_INC ?= `pwd`/../../../include + +# allow users to override these +# e.g. to compile for a kernel that you aren't currently running +KSRC ?= /lib/modules/$(shell uname -r)/build +KBUILD_OUTPUT ?= +ARCH ?= +V ?= 0 + +# this is the basic Kbuild out-of-tree invocation, with the M= option +KBUILD_BASE = +$(MAKE) -C $(KSRC) M=`pwd` KBUILD_OUTPUT=$(KBUILD_OUTPUT) ARCH=$(ARCH) V=$(V) + +all: libosd + +libosd: ; + $(KBUILD_BASE) OSD_INC=$(OSD_INC) modules + +clean: + $(KBUILD_BASE) clean diff --git a/drivers/scsi/osd/osd_debug.h b/drivers/scsi/osd/osd_debug.h new file mode 100644 index 00000000000..579e491f11d --- /dev/null +++ b/drivers/scsi/osd/osd_debug.h @@ -0,0 +1,30 @@ +/* + * osd_debug.h - Some kprintf macros + * + * Copyright (C) 2008 Panasas Inc. All rights reserved. + * + * Authors: + * Boaz Harrosh + * Benny Halevy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * + */ +#ifndef __OSD_DEBUG_H__ +#define __OSD_DEBUG_H__ + +#define OSD_ERR(fmt, a...) printk(KERN_ERR "osd: " fmt, ##a) +#define OSD_INFO(fmt, a...) printk(KERN_NOTICE "osd: " fmt, ##a) + +#ifdef CONFIG_SCSI_OSD_DEBUG +#define OSD_DEBUG(fmt, a...) \ + printk(KERN_NOTICE "osd @%s:%d: " fmt, __func__, __LINE__, ##a) +#else +#define OSD_DEBUG(fmt, a...) do {} while (0) +#endif + +/* u64 has problems with printk this will cast it to unsigned long long */ +#define _LLU(x) (unsigned long long)(x) + +#endif /* ndef __OSD_DEBUG_H__ */ diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c new file mode 100644 index 00000000000..0e6d906f111 --- /dev/null +++ b/drivers/scsi/osd/osd_initiator.c @@ -0,0 +1,448 @@ +/* + * osd_initiator - Main body of the osd initiator library. + * + * Note: The file does not contain the advanced security functionality which + * is only needed by the security_manager's initiators. + * + * Copyright (C) 2008 Panasas Inc. All rights reserved. + * + * Authors: + * Boaz Harrosh + * Benny Halevy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Panasas company nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include "osd_debug.h" + +enum { OSD_REQ_RETRIES = 1 }; + +MODULE_AUTHOR("Boaz Harrosh "); +MODULE_DESCRIPTION("open-osd initiator library libosd.ko"); +MODULE_LICENSE("GPL"); + +static inline void build_test(void) +{ + /* structures were not packed */ + BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN); + BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN); +} + +static unsigned _osd_req_cdb_len(struct osd_request *or) +{ + return OSDv1_TOTAL_CDB_LEN; +} + +void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device) +{ + memset(osdd, 0, sizeof(*osdd)); + osdd->scsi_device = scsi_device; + osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT; + /* TODO: Allocate pools for osd_request attributes ... */ +} +EXPORT_SYMBOL(osd_dev_init); + +void osd_dev_fini(struct osd_dev *osdd) +{ + /* TODO: De-allocate pools */ + + osdd->scsi_device = NULL; +} +EXPORT_SYMBOL(osd_dev_fini); + +static struct osd_request *_osd_request_alloc(gfp_t gfp) +{ + struct osd_request *or; + + /* TODO: Use mempool with one saved request */ + or = kzalloc(sizeof(*or), gfp); + return or; +} + +static void _osd_request_free(struct osd_request *or) +{ + kfree(or); +} + +struct osd_request *osd_start_request(struct osd_dev *dev, gfp_t gfp) +{ + struct osd_request *or; + + or = _osd_request_alloc(gfp); + if (!or) + return NULL; + + or->osd_dev = dev; + or->alloc_flags = gfp; + or->timeout = dev->def_timeout; + or->retries = OSD_REQ_RETRIES; + + return or; +} +EXPORT_SYMBOL(osd_start_request); + +/* + * If osd_finalize_request() was called but the request was not executed through + * the block layer, then we must release BIOs. + */ +static void _abort_unexecuted_bios(struct request *rq) +{ + struct bio *bio; + + while ((bio = rq->bio) != NULL) { + rq->bio = bio->bi_next; + bio_endio(bio, 0); + } +} + +void osd_end_request(struct osd_request *or) +{ + struct request *rq = or->request; + + if (rq) { + if (rq->next_rq) { + _abort_unexecuted_bios(rq->next_rq); + blk_put_request(rq->next_rq); + } + + _abort_unexecuted_bios(rq); + blk_put_request(rq); + } + _osd_request_free(or); +} +EXPORT_SYMBOL(osd_end_request); + +int osd_execute_request(struct osd_request *or) +{ + return blk_execute_rq(or->request->q, NULL, or->request, 0); +} +EXPORT_SYMBOL(osd_execute_request); + +static void osd_request_async_done(struct request *req, int error) +{ + struct osd_request *or = req->end_io_data; + + or->async_error = error; + + if (error) + OSD_DEBUG("osd_request_async_done error recieved %d\n", error); + + if (or->async_done) + or->async_done(or, or->async_private); + else + osd_end_request(or); +} + +int osd_execute_request_async(struct osd_request *or, + osd_req_done_fn *done, void *private) +{ + or->request->end_io_data = or; + or->async_private = private; + or->async_done = done; + + blk_execute_rq_nowait(or->request->q, NULL, or->request, 0, + osd_request_async_done); + return 0; +} +EXPORT_SYMBOL(osd_execute_request_async); + +/* + * Common to all OSD commands + */ + +static void _osdv1_req_encode_common(struct osd_request *or, + __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len) +{ + struct osdv1_cdb *ocdb = &or->cdb.v1; + + /* + * For speed, the commands + * OSD_ACT_PERFORM_SCSI_COMMAND , V1 0x8F7E, V2 0x8F7C + * OSD_ACT_SCSI_TASK_MANAGEMENT , V1 0x8F7F, V2 0x8F7D + * are not supported here. Should pass zero and set after the call + */ + act &= cpu_to_be16(~0x0080); /* V1 action code */ + + OSD_DEBUG("OSDv1 execute opcode 0x%x\n", be16_to_cpu(act)); + + ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD; + ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH; + ocdb->h.varlen_cdb.service_action = act; + + ocdb->h.partition = cpu_to_be64(obj->partition); + ocdb->h.object = cpu_to_be64(obj->id); + ocdb->h.v1.length = cpu_to_be64(len); + ocdb->h.v1.start_address = cpu_to_be64(offset); +} + +static void _osd_req_encode_common(struct osd_request *or, + __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len) +{ + _osdv1_req_encode_common(or, act, obj, offset, len); +} + +/* + * Device commands + */ +void osd_req_format(struct osd_request *or, u64 tot_capacity) +{ + _osd_req_encode_common(or, OSD_ACT_FORMAT_OSD, &osd_root_object, 0, + tot_capacity); +} +EXPORT_SYMBOL(osd_req_format); + +/* + * Partition commands + */ +static void _osd_req_encode_partition(struct osd_request *or, + __be16 act, osd_id partition) +{ + struct osd_obj_id par = { + .partition = partition, + .id = 0, + }; + + _osd_req_encode_common(or, act, &par, 0, 0); +} + +void osd_req_create_partition(struct osd_request *or, osd_id partition) +{ + _osd_req_encode_partition(or, OSD_ACT_CREATE_PARTITION, partition); +} +EXPORT_SYMBOL(osd_req_create_partition); + +void osd_req_remove_partition(struct osd_request *or, osd_id partition) +{ + _osd_req_encode_partition(or, OSD_ACT_REMOVE_PARTITION, partition); +} +EXPORT_SYMBOL(osd_req_remove_partition); + +/* + * Object commands + */ +void osd_req_create_object(struct osd_request *or, struct osd_obj_id *obj) +{ + _osd_req_encode_common(or, OSD_ACT_CREATE, obj, 0, 0); +} +EXPORT_SYMBOL(osd_req_create_object); + +void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *obj) +{ + _osd_req_encode_common(or, OSD_ACT_REMOVE, obj, 0, 0); +} +EXPORT_SYMBOL(osd_req_remove_object); + +void osd_req_write(struct osd_request *or, + const struct osd_obj_id *obj, struct bio *bio, u64 offset) +{ + _osd_req_encode_common(or, OSD_ACT_WRITE, obj, offset, bio->bi_size); + WARN_ON(or->out.bio || or->out.total_bytes); + bio->bi_rw |= (1 << BIO_RW); + or->out.bio = bio; + or->out.total_bytes = bio->bi_size; +} +EXPORT_SYMBOL(osd_req_write); + +void osd_req_read(struct osd_request *or, + const struct osd_obj_id *obj, struct bio *bio, u64 offset) +{ + _osd_req_encode_common(or, OSD_ACT_READ, obj, offset, bio->bi_size); + WARN_ON(or->in.bio || or->in.total_bytes); + bio->bi_rw &= ~(1 << BIO_RW); + or->in.bio = bio; + or->in.total_bytes = bio->bi_size; +} +EXPORT_SYMBOL(osd_req_read); + +/* + * osd_finalize_request and helpers + */ + +static int _init_blk_request(struct osd_request *or, + bool has_in, bool has_out) +{ + gfp_t flags = or->alloc_flags; + struct scsi_device *scsi_device = or->osd_dev->scsi_device; + struct request_queue *q = scsi_device->request_queue; + struct request *req; + int ret = -ENOMEM; + + req = blk_get_request(q, has_out, flags); + if (!req) + goto out; + + or->request = req; + req->cmd_type = REQ_TYPE_BLOCK_PC; + req->timeout = or->timeout; + req->retries = or->retries; + req->sense = or->sense; + req->sense_len = 0; + + if (has_out) { + or->out.req = req; + if (has_in) { + /* allocate bidi request */ + req = blk_get_request(q, READ, flags); + if (!req) { + OSD_DEBUG("blk_get_request for bidi failed\n"); + goto out; + } + req->cmd_type = REQ_TYPE_BLOCK_PC; + or->in.req = or->request->next_rq = req; + } + } else if (has_in) + or->in.req = req; + + ret = 0; +out: + OSD_DEBUG("or=%p has_in=%d has_out=%d => %d, %p\n", + or, has_in, has_out, ret, or->request); + return ret; +} + +int osd_finalize_request(struct osd_request *or, + u8 options, const void *cap, const u8 *cap_key) +{ + struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb); + bool has_in, has_out; + int ret; + + if (options & OSD_REQ_FUA) + cdbh->options |= OSD_CDB_FUA; + + if (options & OSD_REQ_DPO) + cdbh->options |= OSD_CDB_DPO; + + if (options & OSD_REQ_BYPASS_TIMESTAMPS) + cdbh->timestamp_control = OSD_CDB_BYPASS_TIMESTAMPS; + + osd_set_caps(&or->cdb, cap); + + has_in = or->in.bio || or->get_attr.total_bytes; + has_out = or->out.bio || or->set_attr.total_bytes || + or->enc_get_attr.total_bytes; + + ret = _init_blk_request(or, has_in, has_out); + if (ret) { + OSD_DEBUG("_init_blk_request failed\n"); + return ret; + } + + if (or->out.bio) { + ret = blk_rq_append_bio(or->request->q, or->out.req, + or->out.bio); + if (ret) { + OSD_DEBUG("blk_rq_append_bio out failed\n"); + return ret; + } + OSD_DEBUG("out bytes=%llu (bytes_req=%u)\n", + _LLU(or->out.total_bytes), or->out.req->data_len); + } + if (or->in.bio) { + ret = blk_rq_append_bio(or->request->q, or->in.req, or->in.bio); + if (ret) { + OSD_DEBUG("blk_rq_append_bio in failed\n"); + return ret; + } + OSD_DEBUG("in bytes=%llu (bytes_req=%u)\n", + _LLU(or->in.total_bytes), or->in.req->data_len); + } + + if (!or->attributes_mode) + or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS; + cdbh->command_specific_options |= or->attributes_mode; + + or->request->cmd = or->cdb.buff; + or->request->cmd_len = _osd_req_cdb_len(or); + + return 0; +} +EXPORT_SYMBOL(osd_finalize_request); + +/* + * Implementation of osd_sec.h API + * TODO: Move to a separate osd_sec.c file at a later stage. + */ + +enum { OSD_SEC_CAP_V1_ALL_CAPS = + OSD_SEC_CAP_APPEND | OSD_SEC_CAP_OBJ_MGMT | OSD_SEC_CAP_REMOVE | + OSD_SEC_CAP_CREATE | OSD_SEC_CAP_SET_ATTR | OSD_SEC_CAP_GET_ATTR | + OSD_SEC_CAP_WRITE | OSD_SEC_CAP_READ | OSD_SEC_CAP_POL_SEC | + OSD_SEC_CAP_GLOBAL | OSD_SEC_CAP_DEV_MGMT +}; + +void osd_sec_init_nosec_doall_caps(void *caps, + const struct osd_obj_id *obj, bool is_collection, const bool is_v1) +{ + struct osd_capability *cap = caps; + u8 type; + u8 descriptor_type; + + if (likely(obj->id)) { + if (unlikely(is_collection)) { + type = OSD_SEC_OBJ_COLLECTION; + descriptor_type = is_v1 ? OSD_SEC_OBJ_DESC_OBJ : + OSD_SEC_OBJ_DESC_COL; + } else { + type = OSD_SEC_OBJ_USER; + descriptor_type = OSD_SEC_OBJ_DESC_OBJ; + } + WARN_ON(!obj->partition); + } else { + type = obj->partition ? OSD_SEC_OBJ_PARTITION : + OSD_SEC_OBJ_ROOT; + descriptor_type = OSD_SEC_OBJ_DESC_PAR; + } + + memset(cap, 0, sizeof(*cap)); + + cap->h.format = OSD_SEC_CAP_FORMAT_VER1; + cap->h.integrity_algorithm__key_version = 0; /* MAKE_BYTE(0, 0); */ + cap->h.security_method = OSD_SEC_NOSEC; +/* cap->expiration_time; + cap->AUDIT[30-10]; + cap->discriminator[42-30]; + cap->object_created_time; */ + cap->h.object_type = type; + osd_sec_set_caps(&cap->h, OSD_SEC_CAP_V1_ALL_CAPS); + cap->h.object_descriptor_type = descriptor_type; + cap->od.obj_desc.policy_access_tag = 0; + cap->od.obj_desc.allowed_partition_id = cpu_to_be64(obj->partition); + cap->od.obj_desc.allowed_object_id = cpu_to_be64(obj->id); +} +EXPORT_SYMBOL(osd_sec_init_nosec_doall_caps); + +void osd_set_caps(struct osd_cdb *cdb, const void *caps) +{ + memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN); +} -- GitLab From 95b05a7db5865855c32e0bb8b244c3a7aac1cfeb Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Sun, 25 Jan 2009 16:56:47 +0200 Subject: [PATCH 3155/4982] [SCSI] osd_uld: OSD scsi ULD Add a Linux driver module that registers as a SCSI ULD and probes for OSD type SCSI devices. When an OSD-type SCSI device is found a character device is created in the form of /dev/osdX - where X goes from 0 up to hard coded 64. The Major character device number used is 260. Signed-off-by: Boaz Harrosh Reviewed-by: Benny Halevy Signed-off-by: James Bottomley --- drivers/scsi/osd/Kbuild | 7 + drivers/scsi/osd/osd_uld.c | 419 +++++++++++++++++++++++++++++++++++ include/scsi/osd_initiator.h | 6 + 3 files changed, 432 insertions(+) create mode 100644 drivers/scsi/osd/osd_uld.c diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild index a95e0251005..9d38248afcb 100644 --- a/drivers/scsi/osd/Kbuild +++ b/drivers/scsi/osd/Kbuild @@ -17,6 +17,9 @@ ifneq ($(OSD_INC),) CONFIG_SCSI_OSD_INITIATOR=m ccflags-y += -DCONFIG_SCSI_OSD_INITIATOR -DCONFIG_SCSI_OSD_INITIATOR_MODULE +CONFIG_SCSI_OSD_ULD=m +ccflags-y += -DCONFIG_SCSI_OSD_ULD -DCONFIG_SCSI_OSD_ULD_MODULE + # Uncomment to turn debug on # ccflags-y += -DCONFIG_SCSI_OSD_DEBUG @@ -30,3 +33,7 @@ endif # libosd.ko - osd-initiator library libosd-y := osd_initiator.o obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o + +# osd.ko - SCSI ULD and char-device +osd-y := osd_uld.o +obj-$(CONFIG_SCSI_OSD_ULD) += osd.o diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c new file mode 100644 index 00000000000..f6f9a99adaa --- /dev/null +++ b/drivers/scsi/osd/osd_uld.c @@ -0,0 +1,419 @@ +/* + * osd_uld.c - OSD Upper Layer Driver + * + * A Linux driver module that registers as a SCSI ULD and probes + * for OSD type SCSI devices. + * It's main function is to export osd devices to in-kernel users like + * osdfs and pNFS-objects-LD. It also provides one ioctl for running + * in Kernel tests. + * + * Copyright (C) 2008 Panasas Inc. All rights reserved. + * + * Authors: + * Boaz Harrosh + * Benny Halevy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Panasas company nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "osd_debug.h" + +#ifndef TYPE_OSD +# define TYPE_OSD 0x11 +#endif + +#ifndef SCSI_OSD_MAJOR +# define SCSI_OSD_MAJOR 260 +#endif +#define SCSI_OSD_MAX_MINOR 64 + +static const char osd_name[] = "osd"; +static const char *osd_version_string = "open-osd 0.1.0"; +const char osd_symlink[] = "scsi_osd"; + +MODULE_AUTHOR("Boaz Harrosh "); +MODULE_DESCRIPTION("open-osd Upper-Layer-Driver osd.ko"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_CHARDEV_MAJOR(SCSI_OSD_MAJOR); +MODULE_ALIAS_SCSI_DEVICE(TYPE_OSD); + +struct osd_uld_device { + int minor; + struct kref kref; + struct cdev cdev; + struct osd_dev od; + struct gendisk *disk; + struct device *class_member; +}; + +static void __uld_get(struct osd_uld_device *oud); +static void __uld_put(struct osd_uld_device *oud); + +/* + * Char Device operations + */ + +static int osd_uld_open(struct inode *inode, struct file *file) +{ + struct osd_uld_device *oud = container_of(inode->i_cdev, + struct osd_uld_device, cdev); + + __uld_get(oud); + /* cache osd_uld_device on file handle */ + file->private_data = oud; + OSD_DEBUG("osd_uld_open %p\n", oud); + return 0; +} + +static int osd_uld_release(struct inode *inode, struct file *file) +{ + struct osd_uld_device *oud = file->private_data; + + OSD_DEBUG("osd_uld_release %p\n", file->private_data); + file->private_data = NULL; + __uld_put(oud); + return 0; +} + +/* FIXME: Only one vector for now */ +unsigned g_test_ioctl; +do_test_fn *g_do_test; + +int osduld_register_test(unsigned ioctl, do_test_fn *do_test) +{ + if (g_test_ioctl) + return -EINVAL; + + g_test_ioctl = ioctl; + g_do_test = do_test; + return 0; +} +EXPORT_SYMBOL(osduld_register_test); + +void osduld_unregister_test(unsigned ioctl) +{ + if (ioctl == g_test_ioctl) { + g_test_ioctl = 0; + g_do_test = NULL; + } +} +EXPORT_SYMBOL(osduld_unregister_test); + +static do_test_fn *_find_ioctl(unsigned cmd) +{ + if (g_test_ioctl == cmd) + return g_do_test; + else + return NULL; +} + +static long osd_uld_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct osd_uld_device *oud = file->private_data; + int ret; + do_test_fn *do_test; + + do_test = _find_ioctl(cmd); + if (do_test) + ret = do_test(&oud->od, cmd, arg); + else { + OSD_ERR("Unknown ioctl %d: osd_uld_device=%p\n", cmd, oud); + ret = -ENOIOCTLCMD; + } + return ret; +} + +static const struct file_operations osd_fops = { + .owner = THIS_MODULE, + .open = osd_uld_open, + .release = osd_uld_release, + .unlocked_ioctl = osd_uld_ioctl, +}; + +/* + * Scsi Device operations + */ + +static int __detect_osd(struct osd_uld_device *oud) +{ + struct scsi_device *scsi_device = oud->od.scsi_device; + int error; + + /* sending a test_unit_ready as first command seems to be needed + * by some targets + */ + OSD_DEBUG("start scsi_test_unit_ready %p %p %p\n", + oud, scsi_device, scsi_device->request_queue); + error = scsi_test_unit_ready(scsi_device, 10*HZ, 5, NULL); + if (error) + OSD_ERR("warning: scsi_test_unit_ready failed\n"); + + return 0; +} + +static struct class *osd_sysfs_class; +static DEFINE_IDA(osd_minor_ida); + +static int osd_probe(struct device *dev) +{ + struct scsi_device *scsi_device = to_scsi_device(dev); + struct gendisk *disk; + struct osd_uld_device *oud; + int minor; + int error; + + if (scsi_device->type != TYPE_OSD) + return -ENODEV; + + do { + if (!ida_pre_get(&osd_minor_ida, GFP_KERNEL)) + return -ENODEV; + + error = ida_get_new(&osd_minor_ida, &minor); + } while (error == -EAGAIN); + + if (error) + return error; + if (minor >= SCSI_OSD_MAX_MINOR) { + error = -EBUSY; + goto err_retract_minor; + } + + error = -ENOMEM; + oud = kzalloc(sizeof(*oud), GFP_KERNEL); + if (NULL == oud) + goto err_retract_minor; + + kref_init(&oud->kref); + dev_set_drvdata(dev, oud); + oud->minor = minor; + + /* allocate a disk and set it up */ + /* FIXME: do we need this since sg has already done that */ + disk = alloc_disk(1); + if (!disk) { + OSD_ERR("alloc_disk failed\n"); + goto err_free_osd; + } + disk->major = SCSI_OSD_MAJOR; + disk->first_minor = oud->minor; + sprintf(disk->disk_name, "osd%d", oud->minor); + oud->disk = disk; + + /* hold one more reference to the scsi_device that will get released + * in __release, in case a logout is happening while fs is mounted + */ + scsi_device_get(scsi_device); + osd_dev_init(&oud->od, scsi_device); + + /* Detect the OSD Version */ + error = __detect_osd(oud); + if (error) { + OSD_ERR("osd detection failed, non-compatible OSD device\n"); + goto err_put_disk; + } + + /* init the char-device for communication with user-mode */ + cdev_init(&oud->cdev, &osd_fops); + oud->cdev.owner = THIS_MODULE; + error = cdev_add(&oud->cdev, + MKDEV(SCSI_OSD_MAJOR, oud->minor), 1); + if (error) { + OSD_ERR("cdev_add failed\n"); + goto err_put_disk; + } + kobject_get(&oud->cdev.kobj); /* 2nd ref see osd_remove() */ + + /* class_member */ + oud->class_member = device_create(osd_sysfs_class, dev, + MKDEV(SCSI_OSD_MAJOR, oud->minor), "%s", disk->disk_name); + if (IS_ERR(oud->class_member)) { + OSD_ERR("class_device_create failed\n"); + error = PTR_ERR(oud->class_member); + goto err_put_cdev; + } + + dev_set_drvdata(oud->class_member, oud); + error = sysfs_create_link(&scsi_device->sdev_gendev.kobj, + &oud->class_member->kobj, osd_symlink); + if (error) + OSD_ERR("warning: unable to make symlink\n"); + + OSD_INFO("osd_probe %s\n", disk->disk_name); + return 0; + +err_put_cdev: + cdev_del(&oud->cdev); +err_put_disk: + scsi_device_put(scsi_device); + put_disk(disk); +err_free_osd: + dev_set_drvdata(dev, NULL); + kfree(oud); +err_retract_minor: + ida_remove(&osd_minor_ida, minor); + return error; +} + +static int osd_remove(struct device *dev) +{ + struct scsi_device *scsi_device = to_scsi_device(dev); + struct osd_uld_device *oud = dev_get_drvdata(dev); + + if (!oud || (oud->od.scsi_device != scsi_device)) { + OSD_ERR("Half cooked osd-device %p,%p || %p!=%p", + dev, oud, oud ? oud->od.scsi_device : NULL, + scsi_device); + } + + sysfs_remove_link(&oud->od.scsi_device->sdev_gendev.kobj, osd_symlink); + + if (oud->class_member) + device_destroy(osd_sysfs_class, + MKDEV(SCSI_OSD_MAJOR, oud->minor)); + + /* We have 2 references to the cdev. One is released here + * and also takes down the /dev/osdX mapping. The second + * Will be released in __remove() after all users have released + * the osd_uld_device. + */ + if (oud->cdev.owner) + cdev_del(&oud->cdev); + + __uld_put(oud); + return 0; +} + +static void __remove(struct kref *kref) +{ + struct osd_uld_device *oud = container_of(kref, + struct osd_uld_device, kref); + struct scsi_device *scsi_device = oud->od.scsi_device; + + /* now let delete the char_dev */ + kobject_put(&oud->cdev.kobj); + + osd_dev_fini(&oud->od); + scsi_device_put(scsi_device); + + OSD_INFO("osd_remove %s\n", + oud->disk ? oud->disk->disk_name : NULL); + + if (oud->disk) + put_disk(oud->disk); + + ida_remove(&osd_minor_ida, oud->minor); + kfree(oud); +} + +static void __uld_get(struct osd_uld_device *oud) +{ + kref_get(&oud->kref); +} + +static void __uld_put(struct osd_uld_device *oud) +{ + kref_put(&oud->kref, __remove); +} + +/* + * Global driver and scsi registration + */ + +static struct scsi_driver osd_driver = { + .owner = THIS_MODULE, + .gendrv = { + .name = osd_name, + .probe = osd_probe, + .remove = osd_remove, + } +}; + +static int __init osd_uld_init(void) +{ + int err; + + osd_sysfs_class = class_create(THIS_MODULE, osd_symlink); + if (IS_ERR(osd_sysfs_class)) { + OSD_ERR("Unable to register sysfs class => %ld\n", + PTR_ERR(osd_sysfs_class)); + return PTR_ERR(osd_sysfs_class); + } + + err = register_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), + SCSI_OSD_MAX_MINOR, osd_name); + if (err) { + OSD_ERR("Unable to register major %d for osd ULD => %d\n", + SCSI_OSD_MAJOR, err); + goto err_out; + } + + err = scsi_register_driver(&osd_driver.gendrv); + if (err) { + OSD_ERR("scsi_register_driver failed => %d\n", err); + goto err_out_chrdev; + } + + OSD_INFO("LOADED %s\n", osd_version_string); + return 0; + +err_out_chrdev: + unregister_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), SCSI_OSD_MAX_MINOR); +err_out: + class_destroy(osd_sysfs_class); + return err; +} + +static void __exit osd_uld_exit(void) +{ + scsi_unregister_driver(&osd_driver.gendrv); + unregister_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), SCSI_OSD_MAX_MINOR); + class_destroy(osd_sysfs_class); + OSD_INFO("UNLOADED %s\n", osd_version_string); +} + +module_init(osd_uld_init); +module_exit(osd_uld_exit); diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h index 1d92247f820..a5dbbddcf73 100644 --- a/include/scsi/osd_initiator.h +++ b/include/scsi/osd_initiator.h @@ -33,6 +33,12 @@ struct osd_dev { unsigned def_timeout; }; +/* Add/remove test ioctls from external modules */ +typedef int (do_test_fn)(struct osd_dev *od, unsigned cmd, unsigned long arg); +int osduld_register_test(unsigned ioctl, do_test_fn *do_test); +void osduld_unregister_test(unsigned ioctl); + +/* These are called by uld at probe time */ void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device); void osd_dev_fini(struct osd_dev *od); -- GitLab From b799bc7da0ce5ba4a988c521a8fb10452eb419f0 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Sun, 25 Jan 2009 16:58:03 +0200 Subject: [PATCH 3156/4982] [SCSI] osd_uld: API for retrieving osd devices from Kernel Kernel clients like exofs can retrieve struct osd_dev(s) by means of below API. + osduld_path_lookup() - given a path (e.g "/dev/osd0") locks and returns the corresponding struct osd_dev, which is then needed for subsequent libosd use. + osduld_put_device() - free up use of an osd_dev. Devices can be shared by multiple clients. The osd_uld_device's life time is governed by an embedded kref structure. The osd_uld_device holds an extra reference to both it's char-device and it's scsi_device, and will release these just before the final deallocation. There are three possible lock sources of the osd_uld_device 1. First and for most is the probe() function called by scsi-ml upon a successful login into a target. Released in release() when logout. 2. Second by user-mode file handles opened on the char-dev. 3. Third is here by Kernel users. All three locks must be removed before the osd_uld_device is freed. The MODULE has three lock sources as well: 1. scsi-ml at probe() time, removed after release(). (login/logout) 2. The user-mode file handles open/close. 3. Import symbols by client modules like exofs. TODO: This API is not enough for the pNFS-objects LD. A more versatile API will be needed. Proposed API could be: struct osd_dev *osduld_sysid_lookup(const char id[OSD_SYSTEMID_LEN]); Signed-off-by: Boaz Harrosh Signed-off-by: James Bottomley --- drivers/scsi/osd/osd_uld.c | 63 ++++++++++++++++++++++++++++++++++++ include/scsi/osd_initiator.h | 4 +++ 2 files changed, 67 insertions(+) diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c index f6f9a99adaa..cd4ca7cd9f7 100644 --- a/drivers/scsi/osd/osd_uld.c +++ b/drivers/scsi/osd/osd_uld.c @@ -173,6 +173,69 @@ static const struct file_operations osd_fops = { .unlocked_ioctl = osd_uld_ioctl, }; +struct osd_dev *osduld_path_lookup(const char *path) +{ + struct nameidata nd; + struct inode *inode; + struct cdev *cdev; + struct osd_uld_device *uninitialized_var(oud); + int error; + + if (!path || !*path) { + OSD_ERR("Mount with !path || !*path\n"); + return ERR_PTR(-EINVAL); + } + + error = path_lookup(path, LOOKUP_FOLLOW, &nd); + if (error) { + OSD_ERR("path_lookup of %s faild=>%d\n", path, error); + return ERR_PTR(error); + } + + inode = nd.path.dentry->d_inode; + error = -EINVAL; /* Not the right device e.g osd_uld_device */ + if (!S_ISCHR(inode->i_mode)) { + OSD_DEBUG("!S_ISCHR()\n"); + goto out; + } + + cdev = inode->i_cdev; + if (!cdev) { + OSD_ERR("Before mounting an OSD Based filesystem\n"); + OSD_ERR(" user-mode must open+close the %s device\n", path); + OSD_ERR(" Example: bash: echo < %s\n", path); + goto out; + } + + /* The Magic wand. Is it our char-dev */ + /* TODO: Support sg devices */ + if (cdev->owner != THIS_MODULE) { + OSD_ERR("Error mounting %s - is not an OSD device\n", path); + goto out; + } + + oud = container_of(cdev, struct osd_uld_device, cdev); + + __uld_get(oud); + error = 0; + +out: + path_put(&nd.path); + return error ? ERR_PTR(error) : &oud->od; +} +EXPORT_SYMBOL(osduld_path_lookup); + +void osduld_put_device(struct osd_dev *od) +{ + if (od) { + struct osd_uld_device *oud = container_of(od, + struct osd_uld_device, od); + + __uld_put(oud); + } +} +EXPORT_SYMBOL(osduld_put_device); + /* * Scsi Device operations */ diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h index a5dbbddcf73..e84dc7aa5e3 100644 --- a/include/scsi/osd_initiator.h +++ b/include/scsi/osd_initiator.h @@ -33,6 +33,10 @@ struct osd_dev { unsigned def_timeout; }; +/* Retrieve/return osd_dev(s) for use by Kernel clients */ +struct osd_dev *osduld_path_lookup(const char *dev_name); /*Use IS_ERR/ERR_PTR*/ +void osduld_put_device(struct osd_dev *od); + /* Add/remove test ioctls from external modules */ typedef int (do_test_fn)(struct osd_dev *od, unsigned cmd, unsigned long arg); int osduld_register_test(unsigned ioctl, do_test_fn *do_test); -- GitLab From 4ef1a3d70d02663f6bfe901db629e8e608da15b1 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Sun, 25 Jan 2009 16:59:50 +0200 Subject: [PATCH 3157/4982] [SCSI] libosd: attributes Support Support for both List-Mode and Page-Mode osd attributes. One of these operations may be added to most other operations. Define the OSD standard's attribute pages constants and structures (osd_attributes.h) Signed-off-by: Boaz Harrosh Reviewed-by: Benny Halevy Signed-off-by: James Bottomley --- drivers/scsi/osd/osd_initiator.c | 579 +++++++++++++++++++++++++++++++ include/scsi/osd_attributes.h | 327 +++++++++++++++++ 2 files changed, 906 insertions(+) create mode 100644 include/scsi/osd_attributes.h diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index 0e6d906f111..b982d767bf9 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c @@ -45,6 +45,10 @@ #include "osd_debug.h" +#ifndef __unused +# define __unused __attribute__((unused)) +#endif + enum { OSD_REQ_RETRIES = 1 }; MODULE_AUTHOR("Boaz Harrosh "); @@ -63,6 +67,50 @@ static unsigned _osd_req_cdb_len(struct osd_request *or) return OSDv1_TOTAL_CDB_LEN; } +static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len) +{ + return osdv1_attr_list_elem_size(len); +} + +static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head) +{ + return osdv1_list_size(list_head); +} + +static unsigned _osd_req_sizeof_alist_header(struct osd_request *or) +{ + return sizeof(struct osdv1_attributes_list_header); +} + +static void _osd_req_set_alist_type(struct osd_request *or, + void *list, int list_type) +{ + struct osdv1_attributes_list_header *attr_list = list; + + memset(attr_list, 0, sizeof(*attr_list)); + attr_list->type = list_type; +} + +static bool _osd_req_is_alist_type(struct osd_request *or, + void *list, int list_type) +{ + if (!list) + return false; + + if (1) { + struct osdv1_attributes_list_header *attr_list = list; + + return attr_list->type == list_type; + } +} + +static osd_cdb_offset osd_req_encode_offset(struct osd_request *or, + u64 offset, unsigned *padding) +{ + return __osd_encode_offset(offset, padding, + OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT); +} + void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device) { memset(osdd, 0, sizeof(*osdd)); @@ -125,10 +173,25 @@ static void _abort_unexecuted_bios(struct request *rq) } } +static void _osd_free_seg(struct osd_request *or __unused, + struct _osd_req_data_segment *seg) +{ + if (!seg->buff || !seg->alloc_size) + return; + + kfree(seg->buff); + seg->buff = NULL; + seg->alloc_size = 0; +} + void osd_end_request(struct osd_request *or) { struct request *rq = or->request; + _osd_free_seg(or, &or->set_attr); + _osd_free_seg(or, &or->enc_get_attr); + _osd_free_seg(or, &or->get_attr); + if (rq) { if (rq->next_rq) { _abort_unexecuted_bios(rq->next_rq); @@ -176,6 +239,54 @@ int osd_execute_request_async(struct osd_request *or, } EXPORT_SYMBOL(osd_execute_request_async); +u8 sg_out_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT]; +u8 sg_in_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT]; + +static int _osd_realloc_seg(struct osd_request *or, + struct _osd_req_data_segment *seg, unsigned max_bytes) +{ + void *buff; + + if (seg->alloc_size >= max_bytes) + return 0; + + buff = krealloc(seg->buff, max_bytes, or->alloc_flags); + if (!buff) { + OSD_ERR("Failed to Realloc %d-bytes was-%d\n", max_bytes, + seg->alloc_size); + return -ENOMEM; + } + + memset(buff + seg->alloc_size, 0, max_bytes - seg->alloc_size); + seg->buff = buff; + seg->alloc_size = max_bytes; + return 0; +} + +static int _alloc_set_attr_list(struct osd_request *or, + const struct osd_attr *oa, unsigned nelem, unsigned add_bytes) +{ + unsigned total_bytes = add_bytes; + + for (; nelem; --nelem, ++oa) + total_bytes += _osd_req_alist_elem_size(or, oa->len); + + OSD_DEBUG("total_bytes=%d\n", total_bytes); + return _osd_realloc_seg(or, &or->set_attr, total_bytes); +} + +static int _alloc_get_attr_desc(struct osd_request *or, unsigned max_bytes) +{ + OSD_DEBUG("total_bytes=%d\n", max_bytes); + return _osd_realloc_seg(or, &or->enc_get_attr, max_bytes); +} + +static int _alloc_get_attr_list(struct osd_request *or) +{ + OSD_DEBUG("total_bytes=%d\n", or->get_attr.total_bytes); + return _osd_realloc_seg(or, &or->get_attr, or->get_attr.total_bytes); +} + /* * Common to all OSD commands */ @@ -284,6 +395,410 @@ void osd_req_read(struct osd_request *or, } EXPORT_SYMBOL(osd_req_read); +void osd_req_get_attributes(struct osd_request *or, + const struct osd_obj_id *obj) +{ + _osd_req_encode_common(or, OSD_ACT_GET_ATTRIBUTES, obj, 0, 0); +} +EXPORT_SYMBOL(osd_req_get_attributes); + +void osd_req_set_attributes(struct osd_request *or, + const struct osd_obj_id *obj) +{ + _osd_req_encode_common(or, OSD_ACT_SET_ATTRIBUTES, obj, 0, 0); +} +EXPORT_SYMBOL(osd_req_set_attributes); + +/* + * Attributes List-mode + */ + +int osd_req_add_set_attr_list(struct osd_request *or, + const struct osd_attr *oa, unsigned nelem) +{ + unsigned total_bytes = or->set_attr.total_bytes; + void *attr_last; + int ret; + + if (or->attributes_mode && + or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) { + WARN_ON(1); + return -EINVAL; + } + or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS; + + if (!total_bytes) { /* first-time: allocate and put list header */ + total_bytes = _osd_req_sizeof_alist_header(or); + ret = _alloc_set_attr_list(or, oa, nelem, total_bytes); + if (ret) + return ret; + _osd_req_set_alist_type(or, or->set_attr.buff, + OSD_ATTR_LIST_SET_RETRIEVE); + } + attr_last = or->set_attr.buff + total_bytes; + + for (; nelem; --nelem) { + struct osd_attributes_list_element *attr; + unsigned elem_size = _osd_req_alist_elem_size(or, oa->len); + + total_bytes += elem_size; + if (unlikely(or->set_attr.alloc_size < total_bytes)) { + or->set_attr.total_bytes = total_bytes - elem_size; + ret = _alloc_set_attr_list(or, oa, nelem, total_bytes); + if (ret) + return ret; + attr_last = + or->set_attr.buff + or->set_attr.total_bytes; + } + + attr = attr_last; + attr->attr_page = cpu_to_be32(oa->attr_page); + attr->attr_id = cpu_to_be32(oa->attr_id); + attr->attr_bytes = cpu_to_be16(oa->len); + memcpy(attr->attr_val, oa->val_ptr, oa->len); + + attr_last += elem_size; + ++oa; + } + + or->set_attr.total_bytes = total_bytes; + return 0; +} +EXPORT_SYMBOL(osd_req_add_set_attr_list); + +static int _append_map_kern(struct request *req, + void *buff, unsigned len, gfp_t flags) +{ + struct bio *bio; + int ret; + + bio = bio_map_kern(req->q, buff, len, flags); + if (IS_ERR(bio)) { + OSD_ERR("Failed bio_map_kern(%p, %d) => %ld\n", buff, len, + PTR_ERR(bio)); + return PTR_ERR(bio); + } + ret = blk_rq_append_bio(req->q, req, bio); + if (ret) { + OSD_ERR("Failed blk_rq_append_bio(%p) => %d\n", bio, ret); + bio_put(bio); + } + return ret; +} + +static int _req_append_segment(struct osd_request *or, + unsigned padding, struct _osd_req_data_segment *seg, + struct _osd_req_data_segment *last_seg, struct _osd_io_info *io) +{ + void *pad_buff; + int ret; + + if (padding) { + /* check if we can just add it to last buffer */ + if (last_seg && + (padding <= last_seg->alloc_size - last_seg->total_bytes)) + pad_buff = last_seg->buff + last_seg->total_bytes; + else + pad_buff = io->pad_buff; + + ret = _append_map_kern(io->req, pad_buff, padding, + or->alloc_flags); + if (ret) + return ret; + io->total_bytes += padding; + } + + ret = _append_map_kern(io->req, seg->buff, seg->total_bytes, + or->alloc_flags); + if (ret) + return ret; + + io->total_bytes += seg->total_bytes; + OSD_DEBUG("padding=%d buff=%p total_bytes=%d\n", padding, seg->buff, + seg->total_bytes); + return 0; +} + +static int _osd_req_finalize_set_attr_list(struct osd_request *or) +{ + struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb); + unsigned padding; + int ret; + + if (!or->set_attr.total_bytes) { + cdbh->attrs_list.set_attr_offset = OSD_OFFSET_UNUSED; + return 0; + } + + cdbh->attrs_list.set_attr_bytes = cpu_to_be32(or->set_attr.total_bytes); + cdbh->attrs_list.set_attr_offset = + osd_req_encode_offset(or, or->out.total_bytes, &padding); + + ret = _req_append_segment(or, padding, &or->set_attr, + or->out.last_seg, &or->out); + if (ret) + return ret; + + or->out.last_seg = &or->set_attr; + return 0; +} + +int osd_req_add_get_attr_list(struct osd_request *or, + const struct osd_attr *oa, unsigned nelem) +{ + unsigned total_bytes = or->enc_get_attr.total_bytes; + void *attr_last; + int ret; + + if (or->attributes_mode && + or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) { + WARN_ON(1); + return -EINVAL; + } + or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS; + + /* first time calc data-in list header size */ + if (!or->get_attr.total_bytes) + or->get_attr.total_bytes = _osd_req_sizeof_alist_header(or); + + /* calc data-out info */ + if (!total_bytes) { /* first-time: allocate and put list header */ + unsigned max_bytes; + + total_bytes = _osd_req_sizeof_alist_header(or); + max_bytes = total_bytes + + nelem * sizeof(struct osd_attributes_list_attrid); + ret = _alloc_get_attr_desc(or, max_bytes); + if (ret) + return ret; + + _osd_req_set_alist_type(or, or->enc_get_attr.buff, + OSD_ATTR_LIST_GET); + } + attr_last = or->enc_get_attr.buff + total_bytes; + + for (; nelem; --nelem) { + struct osd_attributes_list_attrid *attrid; + const unsigned cur_size = sizeof(*attrid); + + total_bytes += cur_size; + if (unlikely(or->enc_get_attr.alloc_size < total_bytes)) { + or->enc_get_attr.total_bytes = total_bytes - cur_size; + ret = _alloc_get_attr_desc(or, + total_bytes + nelem * sizeof(*attrid)); + if (ret) + return ret; + attr_last = or->enc_get_attr.buff + + or->enc_get_attr.total_bytes; + } + + attrid = attr_last; + attrid->attr_page = cpu_to_be32(oa->attr_page); + attrid->attr_id = cpu_to_be32(oa->attr_id); + + attr_last += cur_size; + + /* calc data-in size */ + or->get_attr.total_bytes += + _osd_req_alist_elem_size(or, oa->len); + ++oa; + } + + or->enc_get_attr.total_bytes = total_bytes; + + OSD_DEBUG( + "get_attr.total_bytes=%u(%u) enc_get_attr.total_bytes=%u(%Zu)\n", + or->get_attr.total_bytes, + or->get_attr.total_bytes - _osd_req_sizeof_alist_header(or), + or->enc_get_attr.total_bytes, + (or->enc_get_attr.total_bytes - _osd_req_sizeof_alist_header(or)) + / sizeof(struct osd_attributes_list_attrid)); + + return 0; +} +EXPORT_SYMBOL(osd_req_add_get_attr_list); + +static int _osd_req_finalize_get_attr_list(struct osd_request *or) +{ + struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb); + unsigned out_padding; + unsigned in_padding; + int ret; + + if (!or->enc_get_attr.total_bytes) { + cdbh->attrs_list.get_attr_desc_offset = OSD_OFFSET_UNUSED; + cdbh->attrs_list.get_attr_offset = OSD_OFFSET_UNUSED; + return 0; + } + + ret = _alloc_get_attr_list(or); + if (ret) + return ret; + + /* The out-going buffer info update */ + OSD_DEBUG("out-going\n"); + cdbh->attrs_list.get_attr_desc_bytes = + cpu_to_be32(or->enc_get_attr.total_bytes); + + cdbh->attrs_list.get_attr_desc_offset = + osd_req_encode_offset(or, or->out.total_bytes, &out_padding); + + ret = _req_append_segment(or, out_padding, &or->enc_get_attr, + or->out.last_seg, &or->out); + if (ret) + return ret; + or->out.last_seg = &or->enc_get_attr; + + /* The incoming buffer info update */ + OSD_DEBUG("in-coming\n"); + cdbh->attrs_list.get_attr_alloc_length = + cpu_to_be32(or->get_attr.total_bytes); + + cdbh->attrs_list.get_attr_offset = + osd_req_encode_offset(or, or->in.total_bytes, &in_padding); + + ret = _req_append_segment(or, in_padding, &or->get_attr, NULL, + &or->in); + if (ret) + return ret; + or->in.last_seg = &or->get_attr; + + return 0; +} + +int osd_req_decode_get_attr_list(struct osd_request *or, + struct osd_attr *oa, int *nelem, void **iterator) +{ + unsigned cur_bytes, returned_bytes; + int n; + const unsigned sizeof_attr_list = _osd_req_sizeof_alist_header(or); + void *cur_p; + + if (!_osd_req_is_alist_type(or, or->get_attr.buff, + OSD_ATTR_LIST_SET_RETRIEVE)) { + oa->attr_page = 0; + oa->attr_id = 0; + oa->val_ptr = NULL; + oa->len = 0; + *iterator = NULL; + return 0; + } + + if (*iterator) { + BUG_ON((*iterator < or->get_attr.buff) || + (or->get_attr.buff + or->get_attr.alloc_size < *iterator)); + cur_p = *iterator; + cur_bytes = (*iterator - or->get_attr.buff) - sizeof_attr_list; + returned_bytes = or->get_attr.total_bytes; + } else { /* first time decode the list header */ + cur_bytes = sizeof_attr_list; + returned_bytes = _osd_req_alist_size(or, or->get_attr.buff) + + sizeof_attr_list; + + cur_p = or->get_attr.buff + sizeof_attr_list; + + if (returned_bytes > or->get_attr.alloc_size) { + OSD_DEBUG("target report: space was not big enough! " + "Allocate=%u Needed=%u\n", + or->get_attr.alloc_size, + returned_bytes + sizeof_attr_list); + + returned_bytes = + or->get_attr.alloc_size - sizeof_attr_list; + } + or->get_attr.total_bytes = returned_bytes; + } + + for (n = 0; (n < *nelem) && (cur_bytes < returned_bytes); ++n) { + struct osd_attributes_list_element *attr = cur_p; + unsigned inc; + + oa->len = be16_to_cpu(attr->attr_bytes); + inc = _osd_req_alist_elem_size(or, oa->len); + OSD_DEBUG("oa->len=%d inc=%d cur_bytes=%d\n", + oa->len, inc, cur_bytes); + cur_bytes += inc; + if (cur_bytes > returned_bytes) { + OSD_ERR("BAD FOOD from target. list not valid!" + "c=%d r=%d n=%d\n", + cur_bytes, returned_bytes, n); + oa->val_ptr = NULL; + break; + } + + oa->attr_page = be32_to_cpu(attr->attr_page); + oa->attr_id = be32_to_cpu(attr->attr_id); + oa->val_ptr = attr->attr_val; + + cur_p += inc; + ++oa; + } + + *iterator = (returned_bytes - cur_bytes) ? cur_p : NULL; + *nelem = n; + return returned_bytes - cur_bytes; +} +EXPORT_SYMBOL(osd_req_decode_get_attr_list); + +/* + * Attributes Page-mode + */ + +int osd_req_add_get_attr_page(struct osd_request *or, + u32 page_id, void *attar_page, unsigned max_page_len, + const struct osd_attr *set_one_attr) +{ + struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb); + + if (or->attributes_mode && + or->attributes_mode != OSD_CDB_GET_ATTR_PAGE_SET_ONE) { + WARN_ON(1); + return -EINVAL; + } + or->attributes_mode = OSD_CDB_GET_ATTR_PAGE_SET_ONE; + + or->get_attr.buff = attar_page; + or->get_attr.total_bytes = max_page_len; + + or->set_attr.buff = set_one_attr->val_ptr; + or->set_attr.total_bytes = set_one_attr->len; + + cdbh->attrs_page.get_attr_page = cpu_to_be32(page_id); + cdbh->attrs_page.get_attr_alloc_length = cpu_to_be32(max_page_len); + /* ocdb->attrs_page.get_attr_offset; */ + + cdbh->attrs_page.set_attr_page = cpu_to_be32(set_one_attr->attr_page); + cdbh->attrs_page.set_attr_id = cpu_to_be32(set_one_attr->attr_id); + cdbh->attrs_page.set_attr_length = cpu_to_be32(set_one_attr->len); + /* ocdb->attrs_page.set_attr_offset; */ + return 0; +} +EXPORT_SYMBOL(osd_req_add_get_attr_page); + +static int _osd_req_finalize_attr_page(struct osd_request *or) +{ + struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb); + unsigned in_padding, out_padding; + int ret; + + /* returned page */ + cdbh->attrs_page.get_attr_offset = + osd_req_encode_offset(or, or->in.total_bytes, &in_padding); + + ret = _req_append_segment(or, in_padding, &or->get_attr, NULL, + &or->in); + if (ret) + return ret; + + /* set one value */ + cdbh->attrs_page.set_attr_offset = + osd_req_encode_offset(or, or->out.total_bytes, &out_padding); + + ret = _req_append_segment(or, out_padding, &or->enc_get_attr, NULL, + &or->out); + return ret; +} + /* * osd_finalize_request and helpers */ @@ -378,9 +893,31 @@ int osd_finalize_request(struct osd_request *or, _LLU(or->in.total_bytes), or->in.req->data_len); } + or->out.pad_buff = sg_out_pad_buffer; + or->in.pad_buff = sg_in_pad_buffer; + if (!or->attributes_mode) or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS; cdbh->command_specific_options |= or->attributes_mode; + if (or->attributes_mode == OSD_CDB_GET_ATTR_PAGE_SET_ONE) { + ret = _osd_req_finalize_attr_page(or); + } else { + /* TODO: I think that for the GET_ATTR command these 2 should + * be reversed to keep them in execution order (for embeded + * targets with low memory footprint) + */ + ret = _osd_req_finalize_set_attr_list(or); + if (ret) { + OSD_DEBUG("_osd_req_finalize_set_attr_list failed\n"); + return ret; + } + + ret = _osd_req_finalize_get_attr_list(or); + if (ret) { + OSD_DEBUG("_osd_req_finalize_get_attr_list failed\n"); + return ret; + } + } or->request->cmd = or->cdb.buff; or->request->cmd_len = _osd_req_cdb_len(or); @@ -446,3 +983,45 @@ void osd_set_caps(struct osd_cdb *cdb, const void *caps) { memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN); } + +/* + * Declared in osd_protocol.h + * 4.12.5 Data-In and Data-Out buffer offsets + * byte offset = mantissa * (2^(exponent+8)) + * Returns the smallest allowed encoded offset that contains given @offset + * The actual encoded offset returned is @offset + *@padding. + */ +osd_cdb_offset __osd_encode_offset( + u64 offset, unsigned *padding, int min_shift, int max_shift) +{ + u64 try_offset = -1, mod, align; + osd_cdb_offset be32_offset; + int shift; + + *padding = 0; + if (!offset) + return 0; + + for (shift = min_shift; shift < max_shift; ++shift) { + try_offset = offset >> shift; + if (try_offset < (1 << OSD_OFFSET_MAX_BITS)) + break; + } + + BUG_ON(shift == max_shift); + + align = 1 << shift; + mod = offset & (align - 1); + if (mod) { + *padding = align - mod; + try_offset += 1; + } + + try_offset |= ((shift - 8) & 0xf) << 28; + be32_offset = cpu_to_be32((u32)try_offset); + + OSD_DEBUG("offset=%llu mantissa=%llu exp=%d encoded=%x pad=%d\n", + _LLU(offset), _LLU(try_offset & 0x0FFFFFFF), shift, + be32_offset, *padding); + return be32_offset; +} diff --git a/include/scsi/osd_attributes.h b/include/scsi/osd_attributes.h new file mode 100644 index 00000000000..f888a6fda07 --- /dev/null +++ b/include/scsi/osd_attributes.h @@ -0,0 +1,327 @@ +#ifndef __OSD_ATTRIBUTES_H__ +#define __OSD_ATTRIBUTES_H__ + +#include "osd_protocol.h" + +/* + * Contains types and constants that define attribute pages and attribute + * numbers and their data types. + */ + +#define ATTR_SET(pg, id, l, ptr) \ + { .attr_page = pg, .attr_id = id, .len = l, .val_ptr = ptr } + +#define ATTR_DEF(pg, id, l) ATTR_SET(pg, id, l, NULL) + +/* osd-r10 4.7.3 Attributes pages */ +enum { + OSD_APAGE_OBJECT_FIRST = 0x0, + OSD_APAGE_OBJECT_DIRECTORY = 0, + OSD_APAGE_OBJECT_INFORMATION = 1, + OSD_APAGE_OBJECT_QUOTAS = 2, + OSD_APAGE_OBJECT_TIMESTAMP = 3, + OSD_APAGE_OBJECT_COLLECTIONS = 4, + OSD_APAGE_OBJECT_SECURITY = 5, + OSD_APAGE_OBJECT_LAST = 0x2fffffff, + + OSD_APAGE_PARTITION_FIRST = 0x30000000, + OSD_APAGE_PARTITION_DIRECTORY = OSD_APAGE_PARTITION_FIRST + 0, + OSD_APAGE_PARTITION_INFORMATION = OSD_APAGE_PARTITION_FIRST + 1, + OSD_APAGE_PARTITION_QUOTAS = OSD_APAGE_PARTITION_FIRST + 2, + OSD_APAGE_PARTITION_TIMESTAMP = OSD_APAGE_PARTITION_FIRST + 3, + OSD_APAGE_PARTITION_SECURITY = OSD_APAGE_PARTITION_FIRST + 5, + OSD_APAGE_PARTITION_LAST = 0x5FFFFFFF, + + OSD_APAGE_COLLECTION_FIRST = 0x60000000, + OSD_APAGE_COLLECTION_DIRECTORY = OSD_APAGE_COLLECTION_FIRST + 0, + OSD_APAGE_COLLECTION_INFORMATION = OSD_APAGE_COLLECTION_FIRST + 1, + OSD_APAGE_COLLECTION_TIMESTAMP = OSD_APAGE_COLLECTION_FIRST + 3, + OSD_APAGE_COLLECTION_SECURITY = OSD_APAGE_COLLECTION_FIRST + 5, + OSD_APAGE_COLLECTION_LAST = 0x8FFFFFFF, + + OSD_APAGE_ROOT_FIRST = 0x90000000, + OSD_APAGE_ROOT_DIRECTORY = OSD_APAGE_ROOT_FIRST + 0, + OSD_APAGE_ROOT_INFORMATION = OSD_APAGE_ROOT_FIRST + 1, + OSD_APAGE_ROOT_QUOTAS = OSD_APAGE_ROOT_FIRST + 2, + OSD_APAGE_ROOT_TIMESTAMP = OSD_APAGE_ROOT_FIRST + 3, + OSD_APAGE_ROOT_SECURITY = OSD_APAGE_ROOT_FIRST + 5, + OSD_APAGE_ROOT_LAST = 0xBFFFFFFF, + + OSD_APAGE_RESERVED_TYPE_FIRST = 0xC0000000, + OSD_APAGE_RESERVED_TYPE_LAST = 0xEFFFFFFF, + + OSD_APAGE_COMMON_FIRST = 0xF0000000, + OSD_APAGE_COMMON_LAST = 0xFFFFFFFE, + + OSD_APAGE_REQUEST_ALL = 0xFFFFFFFF, +}; + +/* subcategories of attr pages within each range above */ +enum { + OSD_APAGE_STD_FIRST = 0x0, + OSD_APAGE_STD_DIRECTORY = 0, + OSD_APAGE_STD_INFORMATION = 1, + OSD_APAGE_STD_QUOTAS = 2, + OSD_APAGE_STD_TIMESTAMP = 3, + OSD_APAGE_STD_COLLECTIONS = 4, + OSD_APAGE_STD_POLICY_SECURITY = 5, + OSD_APAGE_STD_LAST = 0x0000007F, + + OSD_APAGE_RESERVED_FIRST = 0x00000080, + OSD_APAGE_RESERVED_LAST = 0x00007FFF, + + OSD_APAGE_OTHER_STD_FIRST = 0x00008000, + OSD_APAGE_OTHER_STD_LAST = 0x0000EFFF, + + OSD_APAGE_PUBLIC_FIRST = 0x0000F000, + OSD_APAGE_PUBLIC_LAST = 0x0000FFFF, + + OSD_APAGE_APP_DEFINED_FIRST = 0x00010000, + OSD_APAGE_APP_DEFINED_LAST = 0x1FFFFFFF, + + OSD_APAGE_VENDOR_SPECIFIC_FIRST = 0x20000000, + OSD_APAGE_VENDOR_SPECIFIC_LAST = 0x2FFFFFFF, +}; + +enum { + OSD_ATTR_PAGE_IDENTIFICATION = 0, /* in all pages 40 bytes */ +}; + +struct page_identification { + u8 vendor_identification[8]; + u8 page_identification[32]; +} __packed; + +struct osd_attr_page_header { + __be32 page_number; + __be32 page_length; +} __packed; + +/* 7.1.2.8 Root Information attributes page (OSD_APAGE_ROOT_INFORMATION) */ +enum { + OSD_ATTR_RI_OSD_SYSTEM_ID = 0x3, /* 20 */ + OSD_ATTR_RI_VENDOR_IDENTIFICATION = 0x4, /* 8 */ + OSD_ATTR_RI_PRODUCT_IDENTIFICATION = 0x5, /* 16 */ + OSD_ATTR_RI_PRODUCT_MODEL = 0x6, /* 32 */ + OSD_ATTR_RI_PRODUCT_REVISION_LEVEL = 0x7, /* 4 */ + OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER = 0x8, /* variable */ + OSD_ATTR_RI_OSD_NAME = 0x9, /* variable */ + OSD_ATTR_RI_TOTAL_CAPACITY = 0x80, /* 8 */ + OSD_ATTR_RI_USED_CAPACITY = 0x81, /* 8 */ + OSD_ATTR_RI_NUMBER_OF_PARTITIONS = 0xC0, /* 8 */ + OSD_ATTR_RI_CLOCK = 0x100, /* 6 */ +}; +/* Root_Information_attributes_page does not have a get_page structure */ + +/* 7.1.2.9 Partition Information attributes page + * (OSD_APAGE_PARTITION_INFORMATION) + */ +enum { + OSD_ATTR_PI_PARTITION_ID = 0x1, /* 8 */ + OSD_ATTR_PI_USERNAME = 0x9, /* variable */ + OSD_ATTR_PI_USED_CAPACITY = 0x81, /* 8 */ + OSD_ATTR_PI_NUMBER_OF_OBJECTS = 0xC1, /* 8 */ +}; +/* Partition Information attributes page does not have a get_page structure */ + +/* 7.1.2.10 Collection Information attributes page + * (OSD_APAGE_COLLECTION_INFORMATION) + */ +enum { + OSD_ATTR_CI_PARTITION_ID = 0x1, /* 8 */ + OSD_ATTR_CI_COLLECTION_OBJECT_ID = 0x2, /* 8 */ + OSD_ATTR_CI_USERNAME = 0x9, /* variable */ + OSD_ATTR_CI_USED_CAPACITY = 0x81, /* 8 */ +}; +/* Collection Information attributes page does not have a get_page structure */ + +/* 7.1.2.11 User Object Information attributes page + * (OSD_APAGE_OBJECT_INFORMATION) + */ +enum { + OSD_ATTR_OI_PARTITION_ID = 0x1, /* 8 */ + OSD_ATTR_OI_OBJECT_ID = 0x2, /* 8 */ + OSD_ATTR_OI_USERNAME = 0x9, /* variable */ + OSD_ATTR_OI_USED_CAPACITY = 0x81, /* 8 */ + OSD_ATTR_OI_LOGICAL_LENGTH = 0x82, /* 8 */ +}; +/* Object Information attributes page does not have a get_page structure */ + +/* 7.1.2.12 Root Quotas attributes page (OSD_APAGE_ROOT_QUOTAS) */ +enum { + OSD_ATTR_RQ_DEFAULT_MAXIMUM_USER_OBJECT_LENGTH = 0x1, /* 8 */ + OSD_ATTR_RQ_PARTITION_CAPACITY_QUOTA = 0x10001, /* 8 */ + OSD_ATTR_RQ_PARTITION_OBJECT_COUNT = 0x10002, /* 8 */ + OSD_ATTR_RQ_PARTITION_COLLECTIONS_PER_USER_OBJECT = 0x10081, /* 4 */ + OSD_ATTR_RQ_PARTITION_COUNT = 0x20002, /* 8 */ +}; + +struct Root_Quotas_attributes_page { + struct osd_attr_page_header hdr; /* id=R+2, size=0x24 */ + __be64 default_maximum_user_object_length; + __be64 partition_capacity_quota; + __be64 partition_object_count; + __be64 partition_collections_per_user_object; + __be64 partition_count; +} __packed; + +/* 7.1.2.13 Partition Quotas attributes page (OSD_APAGE_PARTITION_QUOTAS)*/ +enum { + OSD_ATTR_PQ_DEFAULT_MAXIMUM_USER_OBJECT_LENGTH = 0x1, /* 8 */ + OSD_ATTR_PQ_CAPACITY_QUOTA = 0x10001, /* 8 */ + OSD_ATTR_PQ_OBJECT_COUNT = 0x10002, /* 8 */ + OSD_ATTR_PQ_COLLECTIONS_PER_USER_OBJECT = 0x10081, /* 4 */ +}; + +struct Partition_Quotas_attributes_page { + struct osd_attr_page_header hdr; /* id=P+2, size=0x1C */ + __be64 default_maximum_user_object_length; + __be64 capacity_quota; + __be64 object_count; + __be64 collections_per_user_object; +} __packed; + +/* 7.1.2.14 User Object Quotas attributes page (OSD_APAGE_OBJECT_QUOTAS) */ +enum { + OSD_ATTR_OQ_MAXIMUM_LENGTH = 0x1, /* 8 */ +}; + +struct Object_Quotas_attributes_page { + struct osd_attr_page_header hdr; /* id=U+2, size=0x8 */ + __be64 maximum_length; +} __packed; + +/* 7.1.2.15 Root Timestamps attributes page (OSD_APAGE_ROOT_TIMESTAMP) */ +enum { + OSD_ATTR_RT_ATTRIBUTES_ACCESSED_TIME = 0x2, /* 6 */ + OSD_ATTR_RT_ATTRIBUTES_MODIFIED_TIME = 0x3, /* 6 */ + OSD_ATTR_RT_TIMESTAMP_BYPASS = 0xFFFFFFFE, /* 1 */ +}; + +struct root_timestamps_attributes_page { + struct osd_attr_page_header hdr; /* id=R+3, size=0xD */ + struct osd_timestamp attributes_accessed_time; + struct osd_timestamp attributes_modified_time; + u8 timestamp_bypass; +} __packed; + +/* 7.1.2.16 Partition Timestamps attributes page + * (OSD_APAGE_PARTITION_TIMESTAMP) + */ +enum { + OSD_ATTR_PT_CREATED_TIME = 0x1, /* 6 */ + OSD_ATTR_PT_ATTRIBUTES_ACCESSED_TIME = 0x2, /* 6 */ + OSD_ATTR_PT_ATTRIBUTES_MODIFIED_TIME = 0x3, /* 6 */ + OSD_ATTR_PT_DATA_ACCESSED_TIME = 0x4, /* 6 */ + OSD_ATTR_PT_DATA_MODIFIED_TIME = 0x5, /* 6 */ + OSD_ATTR_PT_TIMESTAMP_BYPASS = 0xFFFFFFFE, /* 1 */ +}; + +struct partition_timestamps_attributes_page { + struct osd_attr_page_header hdr; /* id=P+3, size=0x1F */ + struct osd_timestamp created_time; + struct osd_timestamp attributes_accessed_time; + struct osd_timestamp attributes_modified_time; + struct osd_timestamp data_accessed_time; + struct osd_timestamp data_modified_time; + u8 timestamp_bypass; +} __packed; + +/* 7.1.2.17/18 Collection/Object Timestamps attributes page + * (OSD_APAGE_COLLECTION_TIMESTAMP/OSD_APAGE_OBJECT_TIMESTAMP) + */ +enum { + OSD_ATTR_OT_CREATED_TIME = 0x1, /* 6 */ + OSD_ATTR_OT_ATTRIBUTES_ACCESSED_TIME = 0x2, /* 6 */ + OSD_ATTR_OT_ATTRIBUTES_MODIFIED_TIME = 0x3, /* 6 */ + OSD_ATTR_OT_DATA_ACCESSED_TIME = 0x4, /* 6 */ + OSD_ATTR_OT_DATA_MODIFIED_TIME = 0x5, /* 6 */ +}; + +/* same for collection */ +struct object_timestamps_attributes_page { + struct osd_attr_page_header hdr; /* id=C+3/3, size=0x1E */ + struct osd_timestamp created_time; + struct osd_timestamp attributes_accessed_time; + struct osd_timestamp attributes_modified_time; + struct osd_timestamp data_accessed_time; + struct osd_timestamp data_modified_time; +} __packed; + +/* 7.1.2.19 Collections attributes page */ +/* TBD */ + +/* 7.1.2.20 Root Policy/Security attributes page (OSD_APAGE_ROOT_SECURITY) */ +enum { + OSD_ATTR_RS_DEFAULT_SECURITY_METHOD = 0x1, /* 1 */ + OSD_ATTR_RS_OLDEST_VALID_NONCE_LIMIT = 0x2, /* 6 */ + OSD_ATTR_RS_NEWEST_VALID_NONCE_LIMIT = 0x3, /* 6 */ + OSD_ATTR_RS_PARTITION_DEFAULT_SECURITY_METHOD = 0x6, /* 1 */ + OSD_ATTR_RS_SUPPORTED_SECURITY_METHODS = 0x7, /* 2 */ + OSD_ATTR_RS_ADJUSTABLE_CLOCK = 0x9, /* 6 */ + OSD_ATTR_RS_MASTER_KEY_IDENTIFIER = 0x7FFD, /* 0 or 7 */ + OSD_ATTR_RS_ROOT_KEY_IDENTIFIER = 0x7FFE, /* 0 or 7 */ + OSD_ATTR_RS_SUPPORTED_INTEGRITY_ALGORITHM_0 = 0x80000000,/* 1,(x16)*/ + OSD_ATTR_RS_SUPPORTED_DH_GROUP_0 = 0x80000010,/* 1,(x16)*/ +}; + +struct root_security_attributes_page { + struct osd_attr_page_header hdr; /* id=R+5, size=0x3F */ + u8 default_security_method; + u8 partition_default_security_method; + __be16 supported_security_methods; + u8 mki_valid_rki_valid; + struct osd_timestamp oldest_valid_nonce_limit; + struct osd_timestamp newest_valid_nonce_limit; + struct osd_timestamp adjustable_clock; + u8 master_key_identifier[32-25]; + u8 root_key_identifier[39-32]; + u8 supported_integrity_algorithm[16]; + u8 supported_dh_group[16]; +} __packed; + +/* 7.1.2.21 Partition Policy/Security attributes page + * (OSD_APAGE_PARTITION_SECURITY) + */ +enum { + OSD_ATTR_PS_DEFAULT_SECURITY_METHOD = 0x1, /* 1 */ + OSD_ATTR_PS_OLDEST_VALID_NONCE = 0x2, /* 6 */ + OSD_ATTR_PS_NEWEST_VALID_NONCE = 0x3, /* 6 */ + OSD_ATTR_PS_REQUEST_NONCE_LIST_DEPTH = 0x4, /* 2 */ + OSD_ATTR_PS_FROZEN_WORKING_KEY_BIT_MASK = 0x5, /* 2 */ + OSD_ATTR_PS_PARTITION_KEY_IDENTIFIER = 0x7FFF, /* 0 or 7 */ + OSD_ATTR_PS_WORKING_KEY_IDENTIFIER_FIRST = 0x8000, /* 0 or 7 */ + OSD_ATTR_PS_WORKING_KEY_IDENTIFIER_LAST = 0x800F, /* 0 or 7 */ + OSD_ATTR_PS_POLICY_ACCESS_TAG = 0x40000001, /* 4 */ + OSD_ATTR_PS_USER_OBJECT_POLICY_ACCESS_TAG = 0x40000002, /* 4 */ +}; + +struct partition_security_attributes_page { + struct osd_attr_page_header hdr; /* id=p+5, size=0x8f */ + u8 reserved[3]; + u8 default_security_method; + struct osd_timestamp oldest_valid_nonce; + struct osd_timestamp newest_valid_nonce; + __be16 request_nonce_list_depth; + __be16 frozen_working_key_bit_mask; + __be32 policy_access_tag; + __be32 user_object_policy_access_tag; + u8 pki_valid; + __be16 wki_00_0f_vld; + struct osd_key_identifier partition_key_identifier; + struct osd_key_identifier working_key_identifiers[16]; +} __packed; + +/* 7.1.2.22/23 Collection/Object Policy-Security attributes page + * (OSD_APAGE_COLLECTION_SECURITY/OSD_APAGE_OBJECT_SECURITY) + */ +enum { + OSD_ATTR_OS_POLICY_ACCESS_TAG = 0x40000001, /* 4 */ +}; + +struct object_security_attributes_page { + struct osd_attr_page_header hdr; /* id=C+5/5, size=4 */ + __be32 policy_access_tag; +} __packed; + +#endif /*ndef __OSD_ATTRIBUTES_H__*/ -- GitLab From 345c435dbb0b77b00ffe73801102533e24c647af Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Sun, 25 Jan 2009 17:03:07 +0200 Subject: [PATCH 3158/4982] [SCSI] libosd: OSD Security processing stubs Layout the signing of OSD's CDB and all-data security modes. The actual code for signing the data and CDB is missing, but the code flow and the extra buffer segments are all in place. Signed-off-by: Boaz Harrosh Reviewed-by: Benny Halevy Signed-off-by: James Bottomley --- drivers/scsi/osd/osd_initiator.c | 86 ++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index b982d767bf9..6849f269cd1 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c @@ -111,6 +111,14 @@ static osd_cdb_offset osd_req_encode_offset(struct osd_request *or, OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT); } +static struct osd_security_parameters * +_osd_req_sec_params(struct osd_request *or) +{ + struct osd_cdb *ocdb = &or->cdb; + + return &ocdb->v1.sec_params; +} + void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device) { memset(osdd, 0, sizeof(*osdd)); @@ -799,6 +807,64 @@ static int _osd_req_finalize_attr_page(struct osd_request *or) return ret; } +static int _osd_req_finalize_data_integrity(struct osd_request *or, + bool has_in, bool has_out, const u8 *cap_key) +{ + struct osd_security_parameters *sec_parms = _osd_req_sec_params(or); + int ret; + + if (!osd_is_sec_alldata(sec_parms)) + return 0; + + if (has_out) { + struct _osd_req_data_segment seg = { + .buff = &or->out_data_integ, + .total_bytes = sizeof(or->out_data_integ), + }; + unsigned pad; + + or->out_data_integ.data_bytes = cpu_to_be64( + or->out.bio ? or->out.bio->bi_size : 0); + or->out_data_integ.set_attributes_bytes = cpu_to_be64( + or->set_attr.total_bytes); + or->out_data_integ.get_attributes_bytes = cpu_to_be64( + or->enc_get_attr.total_bytes); + + sec_parms->data_out_integrity_check_offset = + osd_req_encode_offset(or, or->out.total_bytes, &pad); + + ret = _req_append_segment(or, pad, &seg, or->out.last_seg, + &or->out); + if (ret) + return ret; + or->out.last_seg = NULL; + + /* they are now all chained to request sign them all together */ + osd_sec_sign_data(&or->out_data_integ, or->out.req->bio, + cap_key); + } + + if (has_in) { + struct _osd_req_data_segment seg = { + .buff = &or->in_data_integ, + .total_bytes = sizeof(or->in_data_integ), + }; + unsigned pad; + + sec_parms->data_in_integrity_check_offset = + osd_req_encode_offset(or, or->in.total_bytes, &pad); + + ret = _req_append_segment(or, pad, &seg, or->in.last_seg, + &or->in); + if (ret) + return ret; + + or->in.last_seg = NULL; + } + + return 0; +} + /* * osd_finalize_request and helpers */ @@ -919,6 +985,12 @@ int osd_finalize_request(struct osd_request *or, } } + ret = _osd_req_finalize_data_integrity(or, has_in, has_out, cap_key); + if (ret) + return ret; + + osd_sec_sign_cdb(&or->cdb, cap_key); + or->request->cmd = or->cdb.buff; or->request->cmd_len = _osd_req_cdb_len(or); @@ -984,6 +1056,20 @@ void osd_set_caps(struct osd_cdb *cdb, const void *caps) memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN); } +bool osd_is_sec_alldata(struct osd_security_parameters *sec_parms __unused) +{ + return false; +} + +void osd_sec_sign_cdb(struct osd_cdb *ocdb __unused, const u8 *cap_key __unused) +{ +} + +void osd_sec_sign_data(void *data_integ __unused, + struct bio *bio __unused, const u8 *cap_key __unused) +{ +} + /* * Declared in osd_protocol.h * 4.12.5 Data-In and Data-Out buffer offsets -- GitLab From 3e08613037fd4ec0b716a215602c4bdb3d0d9171 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Sun, 25 Jan 2009 17:05:07 +0200 Subject: [PATCH 3159/4982] [SCSI] libosd: Add Flush and List-objects support Add support for the various List-objects commands. List-partitions-in-device, List-collections-in-partition, List-objects-in-partition, List-objects-in-collection. All these support partial listing and continuation. Add support for the different Flush commands and options. Signed-off-by: Boaz Harrosh Reviewed-by: Benny Halevy Signed-off-by: James Bottomley --- drivers/scsi/osd/osd_initiator.c | 124 +++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index 6849f269cd1..5d9457b7e45 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c @@ -104,6 +104,16 @@ static bool _osd_req_is_alist_type(struct osd_request *or, } } +/* This is for List-objects not Attributes-Lists */ +static void _osd_req_encode_olist(struct osd_request *or, + struct osd_obj_id_list *list) +{ + struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb); + + cdbh->v1.list_identifier = list->list_identifier; + cdbh->v1.start_address = list->continuation_id; +} + static osd_cdb_offset osd_req_encode_offset(struct osd_request *or, u64 offset, unsigned *padding) { @@ -340,6 +350,29 @@ void osd_req_format(struct osd_request *or, u64 tot_capacity) } EXPORT_SYMBOL(osd_req_format); +int osd_req_list_dev_partitions(struct osd_request *or, + osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem) +{ + return osd_req_list_partition_objects(or, 0, initial_id, list, nelem); +} +EXPORT_SYMBOL(osd_req_list_dev_partitions); + +static void _osd_req_encode_flush(struct osd_request *or, + enum osd_options_flush_scope_values op) +{ + struct osd_cdb_head *ocdb = osd_cdb_head(&or->cdb); + + ocdb->command_specific_options = op; +} + +void osd_req_flush_obsd(struct osd_request *or, + enum osd_options_flush_scope_values op) +{ + _osd_req_encode_common(or, OSD_ACT_FLUSH_OSD, &osd_root_object, 0, 0); + _osd_req_encode_flush(or, op); +} +EXPORT_SYMBOL(osd_req_flush_obsd); + /* * Partition commands */ @@ -366,6 +399,88 @@ void osd_req_remove_partition(struct osd_request *or, osd_id partition) } EXPORT_SYMBOL(osd_req_remove_partition); +static int _osd_req_list_objects(struct osd_request *or, + __be16 action, const struct osd_obj_id *obj, osd_id initial_id, + struct osd_obj_id_list *list, unsigned nelem) +{ + struct request_queue *q = or->osd_dev->scsi_device->request_queue; + u64 len = nelem * sizeof(osd_id) + sizeof(*list); + struct bio *bio; + + _osd_req_encode_common(or, action, obj, (u64)initial_id, len); + + if (list->list_identifier) + _osd_req_encode_olist(or, list); + + WARN_ON(or->in.bio); + bio = bio_map_kern(q, list, len, or->alloc_flags); + if (!bio) { + OSD_ERR("!!! Failed to allocate list_objects BIO\n"); + return -ENOMEM; + } + + bio->bi_rw &= ~(1 << BIO_RW); + or->in.bio = bio; + or->in.total_bytes = bio->bi_size; + return 0; +} + +int osd_req_list_partition_collections(struct osd_request *or, + osd_id partition, osd_id initial_id, struct osd_obj_id_list *list, + unsigned nelem) +{ + struct osd_obj_id par = { + .partition = partition, + .id = 0, + }; + + return osd_req_list_collection_objects(or, &par, initial_id, list, + nelem); +} +EXPORT_SYMBOL(osd_req_list_partition_collections); + +int osd_req_list_partition_objects(struct osd_request *or, + osd_id partition, osd_id initial_id, struct osd_obj_id_list *list, + unsigned nelem) +{ + struct osd_obj_id par = { + .partition = partition, + .id = 0, + }; + + return _osd_req_list_objects(or, OSD_ACT_LIST, &par, initial_id, list, + nelem); +} +EXPORT_SYMBOL(osd_req_list_partition_objects); + +void osd_req_flush_partition(struct osd_request *or, + osd_id partition, enum osd_options_flush_scope_values op) +{ + _osd_req_encode_partition(or, OSD_ACT_FLUSH_PARTITION, partition); + _osd_req_encode_flush(or, op); +} +EXPORT_SYMBOL(osd_req_flush_partition); + +/* + * Collection commands + */ +int osd_req_list_collection_objects(struct osd_request *or, + const struct osd_obj_id *obj, osd_id initial_id, + struct osd_obj_id_list *list, unsigned nelem) +{ + return _osd_req_list_objects(or, OSD_ACT_LIST_COLLECTION, obj, + initial_id, list, nelem); +} +EXPORT_SYMBOL(osd_req_list_collection_objects); + +void osd_req_flush_collection(struct osd_request *or, + const struct osd_obj_id *obj, enum osd_options_flush_scope_values op) +{ + _osd_req_encode_common(or, OSD_ACT_FLUSH_PARTITION, obj, 0, 0); + _osd_req_encode_flush(or, op); +} +EXPORT_SYMBOL(osd_req_flush_collection); + /* * Object commands */ @@ -392,6 +507,15 @@ void osd_req_write(struct osd_request *or, } EXPORT_SYMBOL(osd_req_write); +void osd_req_flush_object(struct osd_request *or, + const struct osd_obj_id *obj, enum osd_options_flush_scope_values op, + /*V2*/ u64 offset, /*V2*/ u64 len) +{ + _osd_req_encode_common(or, OSD_ACT_FLUSH, obj, offset, len); + _osd_req_encode_flush(or, op); +} +EXPORT_SYMBOL(osd_req_flush_object); + void osd_req_read(struct osd_request *or, const struct osd_obj_id *obj, struct bio *bio, u64 offset) { -- GitLab From ae30c994a4bb70510fdcb9e7223805bb2a8bc9ee Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Sun, 25 Jan 2009 17:07:14 +0200 Subject: [PATCH 3160/4982] [SCSI] libosd: Not implemented commands Some commands declared in header are not yet implemented. Put them as stubs in .c file, just so they take their place in the file Signed-off-by: Boaz Harrosh Reviewed-by: Benny Halevy Signed-off-by: James Bottomley --- drivers/scsi/osd/osd_initiator.c | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index 5d9457b7e45..3fd021a57e5 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c @@ -343,6 +343,9 @@ static void _osd_req_encode_common(struct osd_request *or, /* * Device commands */ +/*TODO: void osd_req_set_master_seed_xchg(struct osd_request *, ...); */ +/*TODO: void osd_req_set_master_key(struct osd_request *, ...); */ + void osd_req_format(struct osd_request *or, u64 tot_capacity) { _osd_req_encode_common(or, OSD_ACT_FORMAT_OSD, &osd_root_object, 0, @@ -373,6 +376,10 @@ void osd_req_flush_obsd(struct osd_request *or, } EXPORT_SYMBOL(osd_req_flush_obsd); +/*TODO: void osd_req_perform_scsi_command(struct osd_request *, + const u8 *cdb, ...); */ +/*TODO: void osd_req_task_management(struct osd_request *, ...); */ + /* * Partition commands */ @@ -399,6 +406,10 @@ void osd_req_remove_partition(struct osd_request *or, osd_id partition) } EXPORT_SYMBOL(osd_req_remove_partition); +/*TODO: void osd_req_set_partition_key(struct osd_request *, + osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE], + u8 seed[OSD_CRYPTO_SEED_SIZE]); */ + static int _osd_req_list_objects(struct osd_request *or, __be16 action, const struct osd_obj_id *obj, osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem) @@ -464,6 +475,11 @@ EXPORT_SYMBOL(osd_req_flush_partition); /* * Collection commands */ +/*TODO: void osd_req_create_collection(struct osd_request *, + const struct osd_obj_id *); */ +/*TODO: void osd_req_remove_collection(struct osd_request *, + const struct osd_obj_id *); */ + int osd_req_list_collection_objects(struct osd_request *or, const struct osd_obj_id *obj, osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem) @@ -473,6 +489,8 @@ int osd_req_list_collection_objects(struct osd_request *or, } EXPORT_SYMBOL(osd_req_list_collection_objects); +/*TODO: void query(struct osd_request *, ...); V2 */ + void osd_req_flush_collection(struct osd_request *or, const struct osd_obj_id *obj, enum osd_options_flush_scope_values op) { @@ -481,6 +499,9 @@ void osd_req_flush_collection(struct osd_request *or, } EXPORT_SYMBOL(osd_req_flush_collection); +/*TODO: void get_member_attrs(struct osd_request *, ...); V2 */ +/*TODO: void set_member_attrs(struct osd_request *, ...); V2 */ + /* * Object commands */ @@ -496,6 +517,11 @@ void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *obj) } EXPORT_SYMBOL(osd_req_remove_object); + +/*TODO: void osd_req_create_multi(struct osd_request *or, + struct osd_obj_id *first, struct osd_obj_id_list *list, unsigned nelem); +*/ + void osd_req_write(struct osd_request *or, const struct osd_obj_id *obj, struct bio *bio, u64 offset) { @@ -507,6 +533,15 @@ void osd_req_write(struct osd_request *or, } EXPORT_SYMBOL(osd_req_write); +/*TODO: void osd_req_append(struct osd_request *, + const struct osd_obj_id *, struct bio *data_out); */ +/*TODO: void osd_req_create_write(struct osd_request *, + const struct osd_obj_id *, struct bio *data_out, u64 offset); */ +/*TODO: void osd_req_clear(struct osd_request *, + const struct osd_obj_id *, u64 offset, u64 len); */ +/*TODO: void osd_req_punch(struct osd_request *, + const struct osd_obj_id *, u64 offset, u64 len); V2 */ + void osd_req_flush_object(struct osd_request *or, const struct osd_obj_id *obj, enum osd_options_flush_scope_values op, /*V2*/ u64 offset, /*V2*/ u64 len) -- GitLab From c6572c983726fe3f3bb5f07e9afe3a9b8e402d1b Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Sun, 25 Jan 2009 17:09:40 +0200 Subject: [PATCH 3161/4982] [SCSI] libosd: OSD version 2 Support Add support for OSD2 at run time. It is now possible to run with both OSDv1 and OSDv2 targets at the same time. The actual detection should be preformed by the security manager, as the version is encoded in the capability structure. Signed-off-by: Boaz Harrosh Reviewed-by: Benny Halevy Signed-off-by: James Bottomley --- drivers/scsi/osd/osd_initiator.c | 94 +++++++++++++++++++++++++++----- include/scsi/osd_initiator.h | 39 +++++++++++++ include/scsi/osd_protocol.h | 90 ++++++++++++++++++++++++++++-- 3 files changed, 205 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index 3fd021a57e5..86a76cccfeb 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c @@ -59,36 +59,50 @@ static inline void build_test(void) { /* structures were not packed */ BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN); + BUILD_BUG_ON(sizeof(struct osdv2_cdb) != OSD_TOTAL_CDB_LEN); BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN); } static unsigned _osd_req_cdb_len(struct osd_request *or) { - return OSDv1_TOTAL_CDB_LEN; + return osd_req_is_ver1(or) ? OSDv1_TOTAL_CDB_LEN : OSD_TOTAL_CDB_LEN; } static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len) { - return osdv1_attr_list_elem_size(len); + return osd_req_is_ver1(or) ? + osdv1_attr_list_elem_size(len) : + osdv2_attr_list_elem_size(len); } static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head) { - return osdv1_list_size(list_head); + return osd_req_is_ver1(or) ? + osdv1_list_size(list_head) : + osdv2_list_size(list_head); } static unsigned _osd_req_sizeof_alist_header(struct osd_request *or) { - return sizeof(struct osdv1_attributes_list_header); + return osd_req_is_ver1(or) ? + sizeof(struct osdv1_attributes_list_header) : + sizeof(struct osdv2_attributes_list_header); } static void _osd_req_set_alist_type(struct osd_request *or, void *list, int list_type) { - struct osdv1_attributes_list_header *attr_list = list; + if (osd_req_is_ver1(or)) { + struct osdv1_attributes_list_header *attr_list = list; + + memset(attr_list, 0, sizeof(*attr_list)); + attr_list->type = list_type; + } else { + struct osdv2_attributes_list_header *attr_list = list; - memset(attr_list, 0, sizeof(*attr_list)); - attr_list->type = list_type; + memset(attr_list, 0, sizeof(*attr_list)); + attr_list->type = list_type; + } } static bool _osd_req_is_alist_type(struct osd_request *or, @@ -97,9 +111,13 @@ static bool _osd_req_is_alist_type(struct osd_request *or, if (!list) return false; - if (1) { + if (osd_req_is_ver1(or)) { struct osdv1_attributes_list_header *attr_list = list; + return attr_list->type == list_type; + } else { + struct osdv2_attributes_list_header *attr_list = list; + return attr_list->type == list_type; } } @@ -110,15 +128,22 @@ static void _osd_req_encode_olist(struct osd_request *or, { struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb); - cdbh->v1.list_identifier = list->list_identifier; - cdbh->v1.start_address = list->continuation_id; + if (osd_req_is_ver1(or)) { + cdbh->v1.list_identifier = list->list_identifier; + cdbh->v1.start_address = list->continuation_id; + } else { + cdbh->v2.list_identifier = list->list_identifier; + cdbh->v2.start_address = list->continuation_id; + } } static osd_cdb_offset osd_req_encode_offset(struct osd_request *or, u64 offset, unsigned *padding) { return __osd_encode_offset(offset, padding, - OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT); + osd_req_is_ver1(or) ? + OSDv1_OFFSET_MIN_SHIFT : OSD_OFFSET_MIN_SHIFT, + OSD_OFFSET_MAX_SHIFT); } static struct osd_security_parameters * @@ -126,7 +151,10 @@ _osd_req_sec_params(struct osd_request *or) { struct osd_cdb *ocdb = &or->cdb; - return &ocdb->v1.sec_params; + if (osd_req_is_ver1(or)) + return &ocdb->v1.sec_params; + else + return &ocdb->v2.sec_params; } void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device) @@ -134,6 +162,9 @@ void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device) memset(osdd, 0, sizeof(*osdd)); osdd->scsi_device = scsi_device; osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT; +#ifdef OSD_VER1_SUPPORT + osdd->version = OSD_VER2; +#endif /* TODO: Allocate pools for osd_request attributes ... */ } EXPORT_SYMBOL(osd_dev_init); @@ -334,10 +365,30 @@ static void _osdv1_req_encode_common(struct osd_request *or, ocdb->h.v1.start_address = cpu_to_be64(offset); } +static void _osdv2_req_encode_common(struct osd_request *or, + __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len) +{ + struct osdv2_cdb *ocdb = &or->cdb.v2; + + OSD_DEBUG("OSDv2 execute opcode 0x%x\n", be16_to_cpu(act)); + + ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD; + ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH; + ocdb->h.varlen_cdb.service_action = act; + + ocdb->h.partition = cpu_to_be64(obj->partition); + ocdb->h.object = cpu_to_be64(obj->id); + ocdb->h.v2.length = cpu_to_be64(len); + ocdb->h.v2.start_address = cpu_to_be64(offset); +} + static void _osd_req_encode_common(struct osd_request *or, __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len) { - _osdv1_req_encode_common(or, act, obj, offset, len); + if (osd_req_is_ver1(or)) + _osdv1_req_encode_common(or, act, obj, offset, len); + else + _osdv2_req_encode_common(or, act, obj, offset, len); } /* @@ -546,6 +597,12 @@ void osd_req_flush_object(struct osd_request *or, const struct osd_obj_id *obj, enum osd_options_flush_scope_values op, /*V2*/ u64 offset, /*V2*/ u64 len) { + if (unlikely(osd_req_is_ver1(or) && (offset || len))) { + OSD_DEBUG("OSD Ver1 flush on specific range ignored\n"); + offset = 0; + len = 0; + } + _osd_req_encode_common(or, OSD_ACT_FLUSH, obj, offset, len); _osd_req_encode_flush(or, op); } @@ -1169,6 +1226,10 @@ enum { OSD_SEC_CAP_V1_ALL_CAPS = OSD_SEC_CAP_GLOBAL | OSD_SEC_CAP_DEV_MGMT }; +enum { OSD_SEC_CAP_V2_ALL_CAPS = + OSD_SEC_CAP_V1_ALL_CAPS | OSD_SEC_CAP_QUERY | OSD_SEC_CAP_M_OBJECT +}; + void osd_sec_init_nosec_doall_caps(void *caps, const struct osd_obj_id *obj, bool is_collection, const bool is_v1) { @@ -1210,9 +1271,14 @@ void osd_sec_init_nosec_doall_caps(void *caps, } EXPORT_SYMBOL(osd_sec_init_nosec_doall_caps); +/* FIXME: Extract version from caps pointer. + * Also Pete's target only supports caps from OSDv1 for now + */ void osd_set_caps(struct osd_cdb *cdb, const void *caps) { - memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN); + bool is_ver1 = true; + /* NOTE: They start at same address */ + memcpy(&cdb->v1.caps, caps, is_ver1 ? OSDv1_CAP_LEN : OSD_CAP_LEN); } bool osd_is_sec_alldata(struct osd_security_parameters *sec_parms __unused) diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h index e84dc7aa5e3..8482777416d 100644 --- a/include/scsi/osd_initiator.h +++ b/include/scsi/osd_initiator.h @@ -21,6 +21,23 @@ /* Note: "NI" in comments below means "Not Implemented yet" */ +/* Configure of code: + * #undef if you *don't* want OSD v1 support in runtime. + * If #defined the initiator will dynamically configure to encode OSD v1 + * CDB's if the target is detected to be OSD v1 only. + * OSD v2 only commands, options, and attributes will be ignored if target + * is v1 only. + * If #defined will result in bigger/slower code (OK Slower maybe not) + * Q: Should this be CONFIG_SCSI_OSD_VER1_SUPPORT and set from Kconfig? + */ +#define OSD_VER1_SUPPORT y + +enum osd_std_version { + OSD_VER_NONE = 0, + OSD_VER1 = 1, + OSD_VER2 = 2, +}; + /* * Object-based Storage Device. * This object represents an OSD device. @@ -31,6 +48,10 @@ struct osd_dev { struct scsi_device *scsi_device; unsigned def_timeout; + +#ifdef OSD_VER1_SUPPORT + enum osd_std_version version; +#endif }; /* Retrieve/return osd_dev(s) for use by Kernel clients */ @@ -46,6 +67,14 @@ void osduld_unregister_test(unsigned ioctl); void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device); void osd_dev_fini(struct osd_dev *od); +/* we might want to use function vector in the future */ +static inline void osd_dev_set_ver(struct osd_dev *od, enum osd_std_version v) +{ +#ifdef OSD_VER1_SUPPORT + od->version = v; +#endif +} + struct osd_request; typedef void (osd_req_done_fn)(struct osd_request *or, void *private); @@ -82,6 +111,16 @@ struct osd_request { int async_error; }; +/* OSD Version control */ +static inline bool osd_req_is_ver1(struct osd_request *or) +{ +#ifdef OSD_VER1_SUPPORT + return or->osd_dev->version == OSD_VER1; +#else + return false; +#endif +} + /* * How to use the osd library: * diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h index ce1a8771ea7..cd3cbf76465 100644 --- a/include/scsi/osd_protocol.h +++ b/include/scsi/osd_protocol.h @@ -25,12 +25,16 @@ enum { OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8, OSDv1_CAP_LEN = 80, /* Latest supported version */ - OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH, - OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN, - OSD_CAP_LEN = OSDv1_CAP_LEN, +/* OSD_ADDITIONAL_CDB_LENGTH = 216,*/ + OSD_ADDITIONAL_CDB_LENGTH = + OSDv1_ADDITIONAL_CDB_LENGTH, /* FIXME: Pete rev-001 sup */ + OSD_TOTAL_CDB_LEN = OSD_ADDITIONAL_CDB_LENGTH + 8, +/* OSD_CAP_LEN = 104,*/ + OSD_CAP_LEN = OSDv1_CAP_LEN,/* FIXME: Pete rev-001 sup */ OSD_SYSTEMID_LEN = 20, OSD_CRYPTO_KEYID_SIZE = 20, + /*FIXME: OSDv2_CRYPTO_KEYID_SIZE = 32,*/ OSD_CRYPTO_SEED_SIZE = 4, OSD_CRYPTO_NONCE_SIZE = 12, OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */ @@ -108,6 +112,7 @@ enum { OSD_OFFSET_MAX_BITS = 28, OSDv1_OFFSET_MIN_SHIFT = 8, + OSD_OFFSET_MIN_SHIFT = 3, OSD_OFFSET_MAX_SHIFT = 16, }; @@ -129,6 +134,16 @@ static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding) OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT); } +/* Minimum 8 bytes alignment + * Same as v1 but since exponent can be signed than a less than + * 256 alignment can be reached with small offsets (<2GB) + */ +static inline osd_cdb_offset osd_encode_offset_v2(u64 offset, unsigned *padding) +{ + return __osd_encode_offset(offset, padding, + OSD_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT); +} + /* osd2r03: 5.2.1 Overview */ struct osd_cdb_head { struct scsi_varlen_cdb_hdr varlen_cdb; @@ -144,6 +159,13 @@ struct osd_cdb_head { /*36*/ __be64 length; /*44*/ __be64 start_address; } __packed v1; + + struct __osdv2_cdb_addr_len { + /* called allocation_length in some commands */ +/*32*/ __be64 length; +/*40*/ __be64 start_address; +/*48*/ __be32 list_identifier;/* Rarely used */ + } __packed v2; }; /*52*/ union { /* selected attributes mode Page/List/Single */ struct osd_attributes_page_mode { @@ -182,6 +204,7 @@ struct osd_cdb_head { /*80*/ /*160 v1*/ +/*184 v2*/ struct osd_security_parameters { /*160*/u8 integrity_check_value[OSD_CRYPTO_KEYID_SIZE]; /*180*/u8 request_nonce[OSD_CRYPTO_NONCE_SIZE]; @@ -189,6 +212,9 @@ struct osd_security_parameters { /*196*/osd_cdb_offset data_out_integrity_check_offset; } __packed; /*200 v1*/ +/*224 v2*/ + +/* FIXME: osdv2_security_parameters */ struct osdv1_cdb { struct osd_cdb_head h; @@ -196,9 +222,17 @@ struct osdv1_cdb { struct osd_security_parameters sec_params; } __packed; +struct osdv2_cdb { + struct osd_cdb_head h; + u8 caps[OSD_CAP_LEN]; + struct osd_security_parameters sec_params; + /* FIXME: osdv2_security_parameters */ +} __packed; + struct osd_cdb { union { struct osdv1_cdb v1; + struct osdv2_cdb v2; u8 buff[OSD_TOTAL_CDB_LEN]; }; } __packed; @@ -269,6 +303,7 @@ struct osd_attributes_list_attrid { /* * osd2r03: 7.1.3.3 List entry format for retrieved attributes and * for setting attributes + * NOTE: v2 is 8-bytes aligned, v1 is not aligned. */ struct osd_attributes_list_element { __be32 attr_page; @@ -279,6 +314,7 @@ struct osd_attributes_list_element { enum { OSDv1_ATTRIBUTES_ELEM_ALIGN = 1, + OSD_ATTRIBUTES_ELEM_ALIGN = 8, }; enum { @@ -292,6 +328,12 @@ static inline unsigned osdv1_attr_list_elem_size(unsigned len) OSDv1_ATTRIBUTES_ELEM_ALIGN); } +static inline unsigned osdv2_attr_list_elem_size(unsigned len) +{ + return ALIGN(len + sizeof(struct osd_attributes_list_element), + OSD_ATTRIBUTES_ELEM_ALIGN); +} + /* * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values */ @@ -326,6 +368,21 @@ static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h) return be16_to_cpu(h->list_bytes); } +struct osdv2_attributes_list_header { + u8 type; /* lower 4-bits only */ + u8 pad[3]; +/*4*/ __be32 list_bytes; /* Initiator shall set to zero. Only set by target */ + /* + * type=9 followed by struct osd_attributes_list_element's + * type=E followed by struct osd_attributes_list_multi_header's + */ +} __packed; + +static inline unsigned osdv2_list_size(struct osdv2_attributes_list_header *h) +{ + return be32_to_cpu(h->list_bytes); +} + /* (osd-r10 6.13) * osd2r03: 6.15 LIST (Table 79) LIST command parameter data. * for root_lstchg below @@ -469,11 +526,36 @@ struct osdv1_cap_object_descriptor { } __packed; /*80 v1*/ -struct osd_capability { +/*56 v2*/ +struct osd_cap_object_descriptor { + union { + struct { +/*56*/ __be32 allowed_attributes_access; +/*60*/ __be32 policy_access_tag; +/*64*/ __be16 boot_epoch; +/*66*/ u8 reserved[6]; +/*72*/ __be64 allowed_partition_id; +/*80*/ __be64 allowed_object_id; +/*88*/ __be64 allowed_range_length; +/*96*/ __be64 allowed_range_start; + } __packed obj_desc; + +/*56*/ u8 object_descriptor[48]; + }; +} __packed; +/*104 v2*/ + +struct osdv1_capability { struct osd_capability_head h; struct osdv1_cap_object_descriptor od; } __packed; +struct osd_capability { + struct osd_capability_head h; +/* struct osd_cap_object_descriptor od;*/ + struct osdv1_cap_object_descriptor od; /* FIXME: Pete rev-001 sup */ +} __packed; + /** * osd_sec_set_caps - set cap-bits into the capabilities header * -- GitLab From 1b9dce94c8a24a3f1a01fcdf688f2d903b32acdf Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Sun, 25 Jan 2009 17:13:38 +0200 Subject: [PATCH 3162/4982] [SCSI] libosd: OSDv2 auto detection Auto detect an OSDv2 or OSDv1 target at run time. Note how none of the OSD API calls change. The tests do not know what device version it is. This test now passes against both the IBM-OSD-SIM OSD1 target as well as OSC's OSD2 target. Signed-off-by: Boaz Harrosh Reviewed-by: Benny Halevy Signed-off-by: James Bottomley --- drivers/scsi/osd/osd_initiator.c | 125 +++++++++++++++++++++++++++++++ drivers/scsi/osd/osd_uld.c | 5 ++ include/scsi/osd_initiator.h | 3 + 3 files changed, 133 insertions(+) diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index 86a76cccfeb..f6340c2ceb2 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c @@ -41,6 +41,7 @@ #include #include +#include #include #include "osd_debug.h" @@ -63,6 +64,130 @@ static inline void build_test(void) BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN); } +static const char *_osd_ver_desc(struct osd_request *or) +{ + return osd_req_is_ver1(or) ? "OSD1" : "OSD2"; +} + +#define ATTR_DEF_RI(id, len) ATTR_DEF(OSD_APAGE_ROOT_INFORMATION, id, len) + +static int _osd_print_system_info(struct osd_dev *od, void *caps) +{ + struct osd_request *or; + struct osd_attr get_attrs[] = { + ATTR_DEF_RI(OSD_ATTR_RI_VENDOR_IDENTIFICATION, 8), + ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_IDENTIFICATION, 16), + ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_MODEL, 32), + ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_REVISION_LEVEL, 4), + ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER, 64 /*variable*/), + ATTR_DEF_RI(OSD_ATTR_RI_OSD_NAME, 64 /*variable*/), + ATTR_DEF_RI(OSD_ATTR_RI_TOTAL_CAPACITY, 8), + ATTR_DEF_RI(OSD_ATTR_RI_USED_CAPACITY, 8), + ATTR_DEF_RI(OSD_ATTR_RI_NUMBER_OF_PARTITIONS, 8), + ATTR_DEF_RI(OSD_ATTR_RI_CLOCK, 6), + /* IBM-OSD-SIM Has a bug with this one put it last */ + ATTR_DEF_RI(OSD_ATTR_RI_OSD_SYSTEM_ID, 20), + }; + void *iter = NULL, *pFirst; + int nelem = ARRAY_SIZE(get_attrs), a = 0; + int ret; + + or = osd_start_request(od, GFP_KERNEL); + if (!or) + return -ENOMEM; + + /* get attrs */ + osd_req_get_attributes(or, &osd_root_object); + osd_req_add_get_attr_list(or, get_attrs, ARRAY_SIZE(get_attrs)); + + ret = osd_finalize_request(or, 0, caps, NULL); + if (ret) + goto out; + + ret = osd_execute_request(or); + if (ret) { + OSD_ERR("Failed to detect %s => %d\n", _osd_ver_desc(or), ret); + goto out; + } + + osd_req_decode_get_attr_list(or, get_attrs, &nelem, &iter); + + OSD_INFO("Detected %s device\n", + _osd_ver_desc(or)); + + pFirst = get_attrs[a++].val_ptr; + OSD_INFO("OSD_ATTR_RI_VENDOR_IDENTIFICATION [%s]\n", + (char *)pFirst); + + pFirst = get_attrs[a++].val_ptr; + OSD_INFO("OSD_ATTR_RI_PRODUCT_IDENTIFICATION [%s]\n", + (char *)pFirst); + + pFirst = get_attrs[a++].val_ptr; + OSD_INFO("OSD_ATTR_RI_PRODUCT_MODEL [%s]\n", + (char *)pFirst); + + pFirst = get_attrs[a++].val_ptr; + OSD_INFO("OSD_ATTR_RI_PRODUCT_REVISION_LEVEL [%u]\n", + get_unaligned_be32(pFirst)); + + pFirst = get_attrs[a++].val_ptr; + OSD_INFO("OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER [%s]\n", + (char *)pFirst); + + pFirst = get_attrs[a].val_ptr; + OSD_INFO("OSD_ATTR_RI_OSD_NAME [%s]\n", (char *)pFirst); + a++; + + pFirst = get_attrs[a++].val_ptr; + OSD_INFO("OSD_ATTR_RI_TOTAL_CAPACITY [0x%llx]\n", + _LLU(get_unaligned_be64(pFirst))); + + pFirst = get_attrs[a++].val_ptr; + OSD_INFO("OSD_ATTR_RI_USED_CAPACITY [0x%llx]\n", + _LLU(get_unaligned_be64(pFirst))); + + pFirst = get_attrs[a++].val_ptr; + OSD_INFO("OSD_ATTR_RI_NUMBER_OF_PARTITIONS [%llu]\n", + _LLU(get_unaligned_be64(pFirst))); + + /* FIXME: Where are the time utilities */ + pFirst = get_attrs[a++].val_ptr; + OSD_INFO("OSD_ATTR_RI_CLOCK [0x%02x%02x%02x%02x%02x%02x]\n", + ((char *)pFirst)[0], ((char *)pFirst)[1], + ((char *)pFirst)[2], ((char *)pFirst)[3], + ((char *)pFirst)[4], ((char *)pFirst)[5]); + + if (a < nelem) { /* IBM-OSD-SIM bug, Might not have it */ + unsigned len = get_attrs[a].len; + char sid_dump[32*4 + 2]; /* 2nibbles+space+ASCII */ + + hex_dump_to_buffer(get_attrs[a].val_ptr, len, 32, 1, + sid_dump, sizeof(sid_dump), true); + OSD_INFO("OSD_ATTR_RI_OSD_SYSTEM_ID(%d) [%s]\n", len, sid_dump); + a++; + } +out: + osd_end_request(or); + return ret; +} + +int osd_auto_detect_ver(struct osd_dev *od, void *caps) +{ + int ret; + + /* Auto-detect the osd version */ + ret = _osd_print_system_info(od, caps); + if (ret) { + osd_dev_set_ver(od, OSD_VER1); + OSD_DEBUG("converting to OSD1\n"); + ret = _osd_print_system_info(od, caps); + } + + return ret; +} +EXPORT_SYMBOL(osd_auto_detect_ver); + static unsigned _osd_req_cdb_len(struct osd_request *or) { return osd_req_is_ver1(or) ? OSDv1_TOTAL_CDB_LEN : OSD_TOTAL_CDB_LEN; diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c index cd4ca7cd9f7..f8b1a749958 100644 --- a/drivers/scsi/osd/osd_uld.c +++ b/drivers/scsi/osd/osd_uld.c @@ -243,6 +243,7 @@ EXPORT_SYMBOL(osduld_put_device); static int __detect_osd(struct osd_uld_device *oud) { struct scsi_device *scsi_device = oud->od.scsi_device; + char caps[OSD_CAP_LEN]; int error; /* sending a test_unit_ready as first command seems to be needed @@ -254,6 +255,10 @@ static int __detect_osd(struct osd_uld_device *oud) if (error) OSD_ERR("warning: scsi_test_unit_ready failed\n"); + osd_sec_init_nosec_doall_caps(caps, &osd_root_object, false, true); + if (osd_auto_detect_ver(&oud->od, caps)) + return -ENODEV; + return 0; } diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h index 8482777416d..24edeae4893 100644 --- a/include/scsi/osd_initiator.h +++ b/include/scsi/osd_initiator.h @@ -67,6 +67,9 @@ void osduld_unregister_test(unsigned ioctl); void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device); void osd_dev_fini(struct osd_dev *od); +/* some hi level device operations */ +int osd_auto_detect_ver(struct osd_dev *od, void *caps); /* GFP_KERNEL */ + /* we might want to use function vector in the future */ static inline void osd_dev_set_ver(struct osd_dev *od, enum osd_std_version v) { -- GitLab From 98f3aea2bd4b4f9cd7a6a6479ed9410787f756fd Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Sun, 25 Jan 2009 17:15:16 +0200 Subject: [PATCH 3163/4982] [SCSI] libosd: SCSI/OSD Sense decoding support Implementation of the osd_req_decode_sense() API. Can be called by library users to decode what failed in command executions. Add SCSI_OSD_DPRINT_SENSE Kconfig variable. Possible values are: 0 - Do not print any errors to messages file 1 - (Default) Print only decoded errors that are not recoverable. Recoverable errors are those that the target has complied with the request but with a warning. For example read passed end of object will return zeros after the last valid byte. 2- Print all errors. Signed-off-by: Boaz Harrosh Signed-off-by: James Bottomley --- drivers/scsi/osd/Kbuild | 6 + drivers/scsi/osd/osd_initiator.c | 191 +++++++++++++++++++++++ include/scsi/osd_initiator.h | 49 ++++++ include/scsi/osd_sense.h | 260 +++++++++++++++++++++++++++++++ 4 files changed, 506 insertions(+) create mode 100644 include/scsi/osd_sense.h diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild index 9d38248afcb..0e207aa67d1 100644 --- a/drivers/scsi/osd/Kbuild +++ b/drivers/scsi/osd/Kbuild @@ -20,6 +20,12 @@ ccflags-y += -DCONFIG_SCSI_OSD_INITIATOR -DCONFIG_SCSI_OSD_INITIATOR_MODULE CONFIG_SCSI_OSD_ULD=m ccflags-y += -DCONFIG_SCSI_OSD_ULD -DCONFIG_SCSI_OSD_ULD_MODULE +# CONFIG_SCSI_OSD_DPRINT_SENSE = +# 0 - no print of errors +# 1 - print errors +# 2 - errors + warrnings +ccflags-y += -DCONFIG_SCSI_OSD_DPRINT_SENSE=1 + # Uncomment to turn debug on # ccflags-y += -DCONFIG_SCSI_OSD_DEBUG diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index f6340c2ceb2..0bbbf271fbb 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c @@ -42,6 +42,8 @@ #include #include #include +#include + #include #include "osd_debug.h" @@ -1339,6 +1341,195 @@ int osd_finalize_request(struct osd_request *or, } EXPORT_SYMBOL(osd_finalize_request); +#define OSD_SENSE_PRINT1(fmt, a...) \ + do { \ + if (__cur_sense_need_output) \ + OSD_ERR(fmt, ##a); \ + } while (0) + +#define OSD_SENSE_PRINT2(fmt, a...) OSD_SENSE_PRINT1(" " fmt, ##a) + +int osd_req_decode_sense_full(struct osd_request *or, + struct osd_sense_info *osi, bool silent, + struct osd_obj_id *bad_obj_list __unused, int max_obj __unused, + struct osd_attr *bad_attr_list, int max_attr) +{ + int sense_len, original_sense_len; + struct osd_sense_info local_osi; + struct scsi_sense_descriptor_based *ssdb; + void *cur_descriptor; +#if (CONFIG_SCSI_OSD_DPRINT_SENSE == 0) + const bool __cur_sense_need_output = false; +#else + bool __cur_sense_need_output = !silent; +#endif + + if (!or->request->errors) + return 0; + + ssdb = or->request->sense; + sense_len = or->request->sense_len; + if ((sense_len < (int)sizeof(*ssdb) || !ssdb->sense_key)) { + OSD_ERR("Block-layer returned error(0x%x) but " + "sense_len(%u) || key(%d) is empty\n", + or->request->errors, sense_len, ssdb->sense_key); + return -EIO; + } + + if ((ssdb->response_code != 0x72) && (ssdb->response_code != 0x73)) { + OSD_ERR("Unrecognized scsi sense: rcode=%x length=%d\n", + ssdb->response_code, sense_len); + return -EIO; + } + + osi = osi ? : &local_osi; + memset(osi, 0, sizeof(*osi)); + osi->key = ssdb->sense_key; + osi->additional_code = be16_to_cpu(ssdb->additional_sense_code); + original_sense_len = ssdb->additional_sense_length + 8; + +#if (CONFIG_SCSI_OSD_DPRINT_SENSE == 1) + if (__cur_sense_need_output) + __cur_sense_need_output = (osi->key > scsi_sk_recovered_error); +#endif + OSD_SENSE_PRINT1("Main Sense information key=0x%x length(%d, %d) " + "additional_code=0x%x\n", + osi->key, original_sense_len, sense_len, + osi->additional_code); + + if (original_sense_len < sense_len) + sense_len = original_sense_len; + + cur_descriptor = ssdb->ssd; + sense_len -= sizeof(*ssdb); + while (sense_len > 0) { + struct scsi_sense_descriptor *ssd = cur_descriptor; + int cur_len = ssd->additional_length + 2; + + sense_len -= cur_len; + + if (sense_len < 0) + break; /* sense was truncated */ + + switch (ssd->descriptor_type) { + case scsi_sense_information: + case scsi_sense_command_specific_information: + { + struct scsi_sense_command_specific_data_descriptor + *sscd = cur_descriptor; + + osi->command_info = + get_unaligned_be64(&sscd->information) ; + OSD_SENSE_PRINT2( + "command_specific_information 0x%llx \n", + _LLU(osi->command_info)); + break; + } + case scsi_sense_key_specific: + { + struct scsi_sense_key_specific_data_descriptor + *ssks = cur_descriptor; + + osi->sense_info = get_unaligned_be16(&ssks->value); + OSD_SENSE_PRINT2( + "sense_key_specific_information %u" + "sksv_cd_bpv_bp (0x%x)\n", + osi->sense_info, ssks->sksv_cd_bpv_bp); + break; + } + case osd_sense_object_identification: + { /*FIXME: Keep first not last, Store in array*/ + struct osd_sense_identification_data_descriptor + *osidd = cur_descriptor; + + osi->not_initiated_command_functions = + le32_to_cpu(osidd->not_initiated_functions); + osi->completed_command_functions = + le32_to_cpu(osidd->completed_functions); + osi->obj.partition = be64_to_cpu(osidd->partition_id); + osi->obj.id = be64_to_cpu(osidd->object_id); + OSD_SENSE_PRINT2( + "object_identification pid=0x%llx oid=0x%llx\n", + _LLU(osi->obj.partition), _LLU(osi->obj.id)); + OSD_SENSE_PRINT2( + "not_initiated_bits(%x) " + "completed_command_bits(%x)\n", + osi->not_initiated_command_functions, + osi->completed_command_functions); + break; + } + case osd_sense_response_integrity_check: + { + struct osd_sense_response_integrity_check_descriptor + *osricd = cur_descriptor; + const unsigned len = + sizeof(osricd->integrity_check_value); + char key_dump[len*4 + 2]; /* 2nibbles+space+ASCII */ + + hex_dump_to_buffer(osricd->integrity_check_value, len, + 32, 1, key_dump, sizeof(key_dump), true); + OSD_SENSE_PRINT2("response_integrity [%s]\n", key_dump); + } + case osd_sense_attribute_identification: + { + struct osd_sense_attributes_data_descriptor + *osadd = cur_descriptor; + int len = min(cur_len, sense_len); + int i = 0; + struct osd_sense_attr *pattr = osadd->sense_attrs; + + while (len < 0) { + u32 attr_page = be32_to_cpu(pattr->attr_page); + u32 attr_id = be32_to_cpu(pattr->attr_id); + + if (i++ == 0) { + osi->attr.attr_page = attr_page; + osi->attr.attr_id = attr_id; + } + + if (bad_attr_list && max_attr) { + bad_attr_list->attr_page = attr_page; + bad_attr_list->attr_id = attr_id; + bad_attr_list++; + max_attr--; + } + OSD_SENSE_PRINT2( + "osd_sense_attribute_identification" + "attr_page=0x%x attr_id=0x%x\n", + attr_page, attr_id); + } + } + /*These are not legal for OSD*/ + case scsi_sense_field_replaceable_unit: + OSD_SENSE_PRINT2("scsi_sense_field_replaceable_unit\n"); + break; + case scsi_sense_stream_commands: + OSD_SENSE_PRINT2("scsi_sense_stream_commands\n"); + break; + case scsi_sense_block_commands: + OSD_SENSE_PRINT2("scsi_sense_block_commands\n"); + break; + case scsi_sense_ata_return: + OSD_SENSE_PRINT2("scsi_sense_ata_return\n"); + break; + default: + if (ssd->descriptor_type <= scsi_sense_Reserved_last) + OSD_SENSE_PRINT2( + "scsi_sense Reserved descriptor (0x%x)", + ssd->descriptor_type); + else + OSD_SENSE_PRINT2( + "scsi_sense Vendor descriptor (0x%x)", + ssd->descriptor_type); + } + + cur_descriptor += cur_len; + } + + return (osi->key > scsi_sk_recovered_error) ? -EIO : 0; +} +EXPORT_SYMBOL(osd_req_decode_sense_full); + /* * Implementation of osd_sec.h API * TODO: Move to a separate osd_sec.c file at a later stage. diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h index 24edeae4893..b24d9616eb4 100644 --- a/include/scsi/osd_initiator.h +++ b/include/scsi/osd_initiator.h @@ -216,6 +216,55 @@ int osd_execute_request(struct osd_request *or); int osd_execute_request_async(struct osd_request *or, osd_req_done_fn *done, void *private); +/** + * osd_req_decode_sense_full - Decode sense information after execution. + * + * @or: - osd_request to examine + * @osi - Recievs a more detailed error report information (optional). + * @silent - Do not print to dmsg (Even if enabled) + * @bad_obj_list - Some commands act on multiple objects. Failed objects will + * be recieved here (optional) + * @max_obj - Size of @bad_obj_list. + * @bad_attr_list - List of failing attributes (optional) + * @max_attr - Size of @bad_attr_list. + * + * After execution, sense + return code can be analyzed using this function. The + * return code is the final disposition on the error. So it is possible that a + * CHECK_CONDITION was returned from target but this will return NO_ERROR, for + * example on recovered errors. All parameters are optional if caller does + * not need any returned information. + * Note: This function will also dump the error to dmsg according to settings + * of the SCSI_OSD_DPRINT_SENSE Kconfig value. Set @silent if you know the + * command would routinely fail, to not spam the dmsg file. + */ +struct osd_sense_info { + int key; /* one of enum scsi_sense_keys */ + int additional_code ; /* enum osd_additional_sense_codes */ + union { /* Sense specific information */ + u16 sense_info; + u16 cdb_field_offset; /* scsi_invalid_field_in_cdb */ + }; + union { /* Command specific information */ + u64 command_info; + }; + + u32 not_initiated_command_functions; /* osd_command_functions_bits */ + u32 completed_command_functions; /* osd_command_functions_bits */ + struct osd_obj_id obj; + struct osd_attr attr; +}; + +int osd_req_decode_sense_full(struct osd_request *or, + struct osd_sense_info *osi, bool silent, + struct osd_obj_id *bad_obj_list, int max_obj, + struct osd_attr *bad_attr_list, int max_attr); + +static inline int osd_req_decode_sense(struct osd_request *or, + struct osd_sense_info *osi) +{ + return osd_req_decode_sense_full(or, osi, false, NULL, 0, NULL, 0); +} + /** * osd_end_request - return osd_request to free store * diff --git a/include/scsi/osd_sense.h b/include/scsi/osd_sense.h new file mode 100644 index 00000000000..ff9b33c773c --- /dev/null +++ b/include/scsi/osd_sense.h @@ -0,0 +1,260 @@ +/* + * osd_sense.h - OSD Related sense handling definitions. + * + * Copyright (C) 2008 Panasas Inc. All rights reserved. + * + * Authors: + * Boaz Harrosh + * Benny Halevy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * + * This file contains types and constants that are defined by the protocol + * Note: All names and symbols are taken from the OSD standard's text. + */ +#ifndef __OSD_SENSE_H__ +#define __OSD_SENSE_H__ + +#include + +/* SPC3r23 4.5.6 Sense key and sense code definitions table 27 */ +enum scsi_sense_keys { + scsi_sk_no_sense = 0x0, + scsi_sk_recovered_error = 0x1, + scsi_sk_not_ready = 0x2, + scsi_sk_medium_error = 0x3, + scsi_sk_hardware_error = 0x4, + scsi_sk_illegal_request = 0x5, + scsi_sk_unit_attention = 0x6, + scsi_sk_data_protect = 0x7, + scsi_sk_blank_check = 0x8, + scsi_sk_vendor_specific = 0x9, + scsi_sk_copy_aborted = 0xa, + scsi_sk_aborted_command = 0xb, + scsi_sk_volume_overflow = 0xd, + scsi_sk_miscompare = 0xe, + scsi_sk_reserved = 0xf, +}; + +/* SPC3r23 4.5.6 Sense key and sense code definitions table 28 */ +/* Note: only those which can be returned by an OSD target. Most of + * these errors are taken care of by the generic scsi layer. + */ +enum osd_additional_sense_codes { + scsi_no_additional_sense_information = 0x0000, + scsi_operation_in_progress = 0x0016, + scsi_cleaning_requested = 0x0017, + scsi_lunr_cause_not_reportable = 0x0400, + scsi_logical_unit_is_in_process_of_becoming_ready = 0x0401, + scsi_lunr_initializing_command_required = 0x0402, + scsi_lunr_manual_intervention_required = 0x0403, + scsi_lunr_operation_in_progress = 0x0407, + scsi_lunr_selftest_in_progress = 0x0409, + scsi_luna_asymmetric_access_state_transition = 0x040a, + scsi_luna_target_port_in_standby_state = 0x040b, + scsi_luna_target_port_in_unavailable_state = 0x040c, + scsi_lunr_notify_enable_spinup_required = 0x0411, + scsi_logical_unit_does_not_respond_to_selection = 0x0500, + scsi_logical_unit_communication_failure = 0x0800, + scsi_logical_unit_communication_timeout = 0x0801, + scsi_logical_unit_communication_parity_error = 0x0802, + scsi_error_log_overflow = 0x0a00, + scsi_warning = 0x0b00, + scsi_warning_specified_temperature_exceeded = 0x0b01, + scsi_warning_enclosure_degraded = 0x0b02, + scsi_write_error_unexpected_unsolicited_data = 0x0c0c, + scsi_write_error_not_enough_unsolicited_data = 0x0c0d, + scsi_invalid_information_unit = 0x0e00, + scsi_invalid_field_in_command_information_unit = 0x0e03, + scsi_read_error_failed_retransmission_request = 0x1113, + scsi_parameter_list_length_error = 0x1a00, + scsi_invalid_command_operation_code = 0x2000, + scsi_invalid_field_in_cdb = 0x2400, + osd_security_audit_value_frozen = 0x2404, + osd_security_working_key_frozen = 0x2405, + osd_nonce_not_unique = 0x2406, + osd_nonce_timestamp_out_of_range = 0x2407, + scsi_logical_unit_not_supported = 0x2500, + scsi_invalid_field_in_parameter_list = 0x2600, + scsi_parameter_not_supported = 0x2601, + scsi_parameter_value_invalid = 0x2602, + scsi_invalid_release_of_persistent_reservation = 0x2604, + osd_invalid_dataout_buffer_integrity_check_value = 0x260f, + scsi_not_ready_to_ready_change_medium_may_have_changed = 0x2800, + scsi_power_on_reset_or_bus_device_reset_occurred = 0x2900, + scsi_power_on_occurred = 0x2901, + scsi_scsi_bus_reset_occurred = 0x2902, + scsi_bus_device_reset_function_occurred = 0x2903, + scsi_device_internal_reset = 0x2904, + scsi_transceiver_mode_changed_to_single_ended = 0x2905, + scsi_transceiver_mode_changed_to_lvd = 0x2906, + scsi_i_t_nexus_loss_occurred = 0x2907, + scsi_parameters_changed = 0x2a00, + scsi_mode_parameters_changed = 0x2a01, + scsi_asymmetric_access_state_changed = 0x2a06, + scsi_priority_changed = 0x2a08, + scsi_command_sequence_error = 0x2c00, + scsi_previous_busy_status = 0x2c07, + scsi_previous_task_set_full_status = 0x2c08, + scsi_previous_reservation_conflict_status = 0x2c09, + osd_partition_or_collection_contains_user_objects = 0x2c0a, + scsi_commands_cleared_by_another_initiator = 0x2f00, + scsi_cleaning_failure = 0x3007, + scsi_enclosure_failure = 0x3400, + scsi_enclosure_services_failure = 0x3500, + scsi_unsupported_enclosure_function = 0x3501, + scsi_enclosure_services_unavailable = 0x3502, + scsi_enclosure_services_transfer_failure = 0x3503, + scsi_enclosure_services_transfer_refused = 0x3504, + scsi_enclosure_services_checksum_error = 0x3505, + scsi_rounded_parameter = 0x3700, + osd_read_past_end_of_user_object = 0x3b17, + scsi_logical_unit_has_not_self_configured_yet = 0x3e00, + scsi_logical_unit_failure = 0x3e01, + scsi_timeout_on_logical_unit = 0x3e02, + scsi_logical_unit_failed_selftest = 0x3e03, + scsi_logical_unit_unable_to_update_selftest_log = 0x3e04, + scsi_target_operating_conditions_have_changed = 0x3f00, + scsi_microcode_has_been_changed = 0x3f01, + scsi_inquiry_data_has_changed = 0x3f03, + scsi_echo_buffer_overwritten = 0x3f0f, + scsi_diagnostic_failure_on_component_nn_first = 0x4080, + scsi_diagnostic_failure_on_component_nn_last = 0x40ff, + scsi_message_error = 0x4300, + scsi_internal_target_failure = 0x4400, + scsi_select_or_reselect_failure = 0x4500, + scsi_scsi_parity_error = 0x4700, + scsi_data_phase_crc_error_detected = 0x4701, + scsi_scsi_parity_error_detected_during_st_data_phase = 0x4702, + scsi_asynchronous_information_protection_error_detected = 0x4704, + scsi_protocol_service_crc_error = 0x4705, + scsi_phy_test_function_in_progress = 0x4706, + scsi_invalid_message_error = 0x4900, + scsi_command_phase_error = 0x4a00, + scsi_data_phase_error = 0x4b00, + scsi_logical_unit_failed_self_configuration = 0x4c00, + scsi_overlapped_commands_attempted = 0x4e00, + osd_quota_error = 0x5507, + scsi_failure_prediction_threshold_exceeded = 0x5d00, + scsi_failure_prediction_threshold_exceeded_false = 0x5dff, + scsi_voltage_fault = 0x6500, +}; + +enum scsi_descriptor_types { + scsi_sense_information = 0x0, + scsi_sense_command_specific_information = 0x1, + scsi_sense_key_specific = 0x2, + scsi_sense_field_replaceable_unit = 0x3, + scsi_sense_stream_commands = 0x4, + scsi_sense_block_commands = 0x5, + osd_sense_object_identification = 0x6, + osd_sense_response_integrity_check = 0x7, + osd_sense_attribute_identification = 0x8, + scsi_sense_ata_return = 0x9, + + scsi_sense_Reserved_first = 0x0A, + scsi_sense_Reserved_last = 0x7F, + scsi_sense_Vendor_specific_first = 0x80, + scsi_sense_Vendor_specific_last = 0xFF, +}; + +struct scsi_sense_descriptor { /* for picking into desc type */ + u8 descriptor_type; /* one of enum scsi_descriptor_types */ + u8 additional_length; /* n - 1 */ + u8 data[]; +} __packed; + +/* OSD deploys only scsi descriptor_based sense buffers */ +struct scsi_sense_descriptor_based { +/*0*/ u8 response_code; /* 0x72 or 0x73 */ +/*1*/ u8 sense_key; /* one of enum scsi_sense_keys (4 lower bits) */ +/*2*/ __be16 additional_sense_code; /* enum osd_additional_sense_codes */ +/*4*/ u8 Reserved[3]; +/*7*/ u8 additional_sense_length; /* n - 7 */ +/*8*/ struct scsi_sense_descriptor ssd[0]; /* variable length, 1 or more */ +} __packed; + +/* some descriptors deployed by OSD */ + +/* SPC3r23 4.5.2.3 Command-specific information sense data descriptor */ +/* Note: this is the same for descriptor_type=00 but with type=00 the + * Reserved[0] == 0x80 (ie. bit-7 set) + */ +struct scsi_sense_command_specific_data_descriptor { +/*0*/ u8 descriptor_type; /* (00h/01h) */ +/*1*/ u8 additional_length; /* (0Ah) */ +/*2*/ u8 Reserved[2]; +/*4*/ __be64 information; +} __packed; +/*12*/ + +struct scsi_sense_key_specific_data_descriptor { +/*0*/ u8 descriptor_type; /* (02h) */ +/*1*/ u8 additional_length; /* (06h) */ +/*2*/ u8 Reserved[2]; +/* SKSV, C/D, Reserved (2), BPV, BIT POINTER (3) */ +/*4*/ u8 sksv_cd_bpv_bp; +/*5*/ __be16 value; /* field-pointer/progress-value/retry-count/... */ +/*7*/ u8 Reserved2; +} __packed; +/*8*/ + +/* 4.16.2.1 OSD error identification sense data descriptor - table 52 */ +/* Note: these bits are defined LE order for easy definition, this way the BIT() + * number is the same as in the documentation. Below members at + * osd_sense_identification_data_descriptor are therefore defined __le32. + */ +enum osd_command_functions_bits { + OSD_CFB_COMMAND = BIT(4), + OSD_CFB_CMD_CAP_VERIFIED = BIT(5), + OSD_CFB_VALIDATION = BIT(7), + OSD_CFB_IMP_ST_ATT = BIT(12), + OSD_CFB_SET_ATT = BIT(20), + OSD_CFB_SA_CAP_VERIFIED = BIT(21), + OSD_CFB_GET_ATT = BIT(28), + OSD_CFB_GA_CAP_VERIFIED = BIT(29), +}; + +struct osd_sense_identification_data_descriptor { +/*0*/ u8 descriptor_type; /* (06h) */ +/*1*/ u8 additional_length; /* (1Eh) */ +/*2*/ u8 Reserved[6]; +/*8*/ __le32 not_initiated_functions; /*osd_command_functions_bits*/ +/*12*/ __le32 completed_functions; /*osd_command_functions_bits*/ +/*16*/ __be64 partition_id; +/*24*/ __be64 object_id; +} __packed; +/*32*/ + +struct osd_sense_response_integrity_check_descriptor { +/*0*/ u8 descriptor_type; /* (07h) */ +/*1*/ u8 additional_length; /* (20h) */ +/*2*/ u8 integrity_check_value[32]; /*FIXME: OSDv2_CRYPTO_KEYID_SIZE*/ +} __packed; +/*34*/ + +struct osd_sense_attributes_data_descriptor { +/*0*/ u8 descriptor_type; /* (08h) */ +/*1*/ u8 additional_length; /* (n-2) */ +/*2*/ u8 Reserved[6]; + struct osd_sense_attr { +/*8*/ __be32 attr_page; +/*12*/ __be32 attr_id; +/*16*/ } sense_attrs[0]; /* 1 or more */ +} __packed; +/*variable*/ + +/* Dig into scsi_sk_illegal_request/scsi_invalid_field_in_cdb errors */ + +/*FIXME: Support also field in CAPS*/ +#define OSD_CDB_OFFSET(F) offsetof(struct osd_cdb_head, F) + +enum osdv2_cdb_field_offset { + OSDv1_CFO_STARTING_BYTE = OSD_CDB_OFFSET(v1.start_address), + OSD_CFO_STARTING_BYTE = OSD_CDB_OFFSET(v2.start_address), + OSD_CFO_PARTITION_ID = OSD_CDB_OFFSET(partition), + OSD_CFO_OBJECT_ID = OSD_CDB_OFFSET(object), +}; + +#endif /* ndef __OSD_SENSE_H__ */ -- GitLab From 78e0c621deca08e5f802383dbe75fd20b258ea4e Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Sun, 25 Jan 2009 17:21:40 +0200 Subject: [PATCH 3164/4982] [SCSI] osd: Documentation for OSD library Add osd.txt to Documentation/scsi/ Signed-off-by: Boaz Harrosh Reviewed-by: Benny Halevy Signed-off-by: James Bottomley --- Documentation/scsi/osd.txt | 198 +++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 Documentation/scsi/osd.txt diff --git a/Documentation/scsi/osd.txt b/Documentation/scsi/osd.txt new file mode 100644 index 00000000000..da162f7fd5f --- /dev/null +++ b/Documentation/scsi/osd.txt @@ -0,0 +1,198 @@ +The OSD Standard +================ +OSD (Object-Based Storage Device) is a T10 SCSI command set that is designed +to provide efficient operation of input/output logical units that manage the +allocation, placement, and accessing of variable-size data-storage containers, +called objects. Objects are intended to contain operating system and application +constructs. Each object has associated attributes attached to it, which are +integral part of the object and provide metadata about the object. The standard +defines some common obligatory attributes, but user attributes can be added as +needed. + +See: http://www.t10.org/ftp/t10/drafts/osd2/ for the latest draft for OSD 2 +or search the web for "OSD SCSI" + +OSD in the Linux Kernel +======================= +osd-initiator: + The main component of OSD in Kernel is the osd-initiator library. Its main +user is intended to be the pNFS-over-objects layout driver, which uses objects +as its back-end data storage. Other clients are the other osd parts listed below. + +osd-uld: + This is a SCSI ULD that registers for OSD type devices and provides a testing +platform, both for the in-kernel initiator as well as connected targets. It +currently has no useful user-mode API, though it could have if need be. + +exofs: + Is an OSD based Linux file system. It uses the osd-initiator and osd-uld, +to export a usable file system for users. +See Documentation/filesystems/exofs.txt for more details + +osd target: + There are no current plans for an OSD target implementation in kernel. For all +needs, a user-mode target that is based on the scsi tgt target framework is +available from Ohio Supercomputer Center (OSC) at: +http://www.open-osd.org/bin/view/Main/OscOsdProject +There are several other target implementations. See http://open-osd.org for more +links. + +Files and Folders +================= +This is the complete list of files included in this work: +include/scsi/ + osd_initiator.h Main API for the initiator library + osd_types.h Common OSD types + osd_sec.h Security Manager API + osd_protocol.h Wire definitions of the OSD standard protocol + osd_attributes.h Wire definitions of OSD attributes + +drivers/scsi/osd/ + osd_initiator.c OSD-Initiator library implementation + osd_uld.c The OSD scsi ULD + osd_ktest.{h,c} In-kernel test suite (called by osd_uld) + osd_debug.h Some printk macros + Makefile For both in-tree and out-of-tree compilation + Kconfig Enables inclusion of the different pieces + osd_test.c User-mode application to call the kernel tests + +The OSD-Initiator Library +========================= +osd_initiator is a low level implementation of an osd initiator encoder. +But even though, it should be intuitive and easy to use. Perhaps over time an +higher lever will form that automates some of the more common recipes. + +init/fini: +- osd_dev_init() associates a scsi_device with an osd_dev structure + and initializes some global pools. This should be done once per scsi_device + (OSD LUN). The osd_dev structure is needed for calling osd_start_request(). + +- osd_dev_fini() cleans up before a osd_dev/scsi_device destruction. + +OSD commands encoding, execution, and decoding of results: + +struct osd_request's is used to iteratively encode an OSD command and carry +its state throughout execution. Each request goes through these stages: + +a. osd_start_request() allocates the request. + +b. Any of the osd_req_* methods is used to encode a request of the specified + type. + +c. osd_req_add_{get,set}_attr_* may be called to add get/set attributes to the + CDB. "List" or "Page" mode can be used exclusively. The attribute-list API + can be called multiple times on the same request. However, only one + attribute-page can be read, as mandated by the OSD standard. + +d. osd_finalize_request() computes offsets into the data-in and data-out buffers + and signs the request using the provided capability key and integrity- + check parameters. + +e. osd_execute_request() may be called to execute the request via the block + layer and wait for its completion. The request can be executed + asynchronously by calling the block layer API directly. + +f. After execution, osd_req_decode_sense() can be called to decode the request's + sense information. + +g. osd_req_decode_get_attr() may be called to retrieve osd_add_get_attr_list() + values. + +h. osd_end_request() must be called to deallocate the request and any resource + associated with it. Note that osd_end_request cleans up the request at any + stage and it must always be called after a successful osd_start_request(). + +osd_request's structure: + +The OSD standard defines a complex structure of IO segments pointed to by +members in the CDB. Up to 3 segments can be deployed in the IN-Buffer and up to +4 in the OUT-Buffer. The ASCII illustration below depicts a secure-read with +associated get+set of attributes-lists. Other combinations very on the same +basic theme. From no-segments-used up to all-segments-used. + +|________OSD-CDB__________| +| | +|read_len (offset=0) -|---------\ +| | | +|get_attrs_list_length | | +|get_attrs_list_offset -|----\ | +| | | | +|retrieved_attrs_alloc_len| | | +|retrieved_attrs_offset -|----|----|-\ +| | | | | +|set_attrs_list_length | | | | +|set_attrs_list_offset -|-\ | | | +| | | | | | +|in_data_integ_offset -|-|--|----|-|-\ +|out_data_integ_offset -|-|--|--\ | | | +\_________________________/ | | | | | | + | | | | | | +|_______OUT-BUFFER________| | | | | | | +| Set attr list | + +More up-to-date information can be found on: +http://open-osd.org + +Boaz Harrosh +Benny Halevy + +References +========== +Weber, R., "SCSI Object-Based Storage Device Commands", +T10/1355-D ANSI/INCITS 400-2004, +http://www.t10.org/ftp/t10/drafts/osd/osd-r10.pdf + +Weber, R., "SCSI Object-Based Storage Device Commands -2 (OSD-2)" +T10/1729-D, Working Draft, rev. 3 +http://www.t10.org/ftp/t10/drafts/osd2/osd2r03.pdf -- GitLab From 6864abd8b730435d6ae9cb061095229a5a85153f Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Sun, 25 Jan 2009 17:22:52 +0200 Subject: [PATCH 3165/4982] [SCSI] osd: Kconfig file for in-tree builds Kconfig file for the drivers/scsi/osd subdirectory. Adds the following config items: config SCSI_OSD_INITIATOR config SCSI_OSD_ULD config SCSI_OSD_DPRINT_SENSE config SCSI_OSD_DEBUG Signed-off-by: Boaz Harrosh Reviewed-by: Benny Halevy Signed-off-by: James Bottomley --- drivers/scsi/osd/Kconfig | 53 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 drivers/scsi/osd/Kconfig diff --git a/drivers/scsi/osd/Kconfig b/drivers/scsi/osd/Kconfig new file mode 100644 index 00000000000..861b5cebaea --- /dev/null +++ b/drivers/scsi/osd/Kconfig @@ -0,0 +1,53 @@ +# +# Kernel configuration file for the OSD scsi protocol +# +# Copyright (C) 2008 Panasas Inc. All rights reserved. +# +# Authors: +# Boaz Harrosh +# Benny Halevy +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public version 2 License as +# published by the Free Software Foundation +# +# FIXME: SCSI_OSD_INITIATOR should select CONFIG (HMAC) SHA1 somehow. +# How is it done properly? +# + +config SCSI_OSD_INITIATOR + tristate "OSD-Initiator library" + depends on SCSI + help + Enable the OSD-Initiator library (libosd.ko). + NOTE: You must also select CRYPTO_SHA1 + CRYPTO_HMAC and their + dependencies + +config SCSI_OSD_ULD + tristate "OSD Upper Level driver" + depends on SCSI_OSD_INITIATOR + help + Build a SCSI upper layer driver that exports /dev/osdX devices + to user-mode for testing and controlling OSD devices. It is also + needed by exofs, for mounting an OSD based file system. + +config SCSI_OSD_DPRINT_SENSE + int "(0-2) When sense is returned, DEBUG print all sense descriptors" + default 1 + depends on SCSI_OSD_INITIATOR + help + When a CHECK_CONDITION status is returned from a target, and a + sense-buffer is retrieved, turning this on will dump a full + sense-decoding message. Setting to 2 will also print recoverable + errors that might be regularly returned for some filesystem + operations. + +config SCSI_OSD_DEBUG + bool "Compile All OSD modules with lots of DEBUG prints" + default n + depends on SCSI_OSD_INITIATOR + help + OSD Code is populated with lots of OSD_DEBUG(..) printouts to + dmesg. Enable this if you found a bug and you want to help us + track the problem (see also MAINTAINERS). Setting this will also + force SCSI_OSD_DPRINT_SENSE=2. -- GitLab From 68274794c69991121eaf0a4a35b78aa7f088ec2c Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Sun, 25 Jan 2009 17:24:14 +0200 Subject: [PATCH 3166/4982] [SCSI] scsi: Add osd library to build system OSD in kernel source code is assumed to be at: drivers/scsi/osd/ with its own Makefile and Kconfig Add includes to them from drivers/scsi Makefile and Kconfig Add OSD to MAINTAINERS file Signed-off-by: Boaz Harrosh Reviewed-by: Benny Halevy Signed-off-by: James Bottomley --- MAINTAINERS | 10 ++++++++++ drivers/scsi/Kconfig | 2 ++ drivers/scsi/Makefile | 2 ++ 3 files changed, 14 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 1c2ca1dc66f..e26fb02ac75 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3291,6 +3291,16 @@ L: orinoco-devel@lists.sourceforge.net W: http://www.nongnu.org/orinoco/ S: Maintained +OSD LIBRARY +P: Boaz Harrosh +M: bharrosh@panasas.com +P: Benny Halevy +M: bhalevy@panasas.com +L: osd-dev@open-osd.org +W: http://open-osd.org +T: git://git.open-osd.org/open-osd.git +S: Maintained + P54 WIRELESS DRIVER P: Michael Wu M: flamingice@sourmilk.net diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 601c2a8ec24..e420ad0aceb 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -1806,4 +1806,6 @@ source "drivers/scsi/pcmcia/Kconfig" source "drivers/scsi/device_handler/Kconfig" +source "drivers/scsi/osd/Kconfig" + endmenu diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 7461eb09a03..05558b17041 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -137,6 +137,8 @@ obj-$(CONFIG_CHR_DEV_SG) += sg.o obj-$(CONFIG_CHR_DEV_SCH) += ch.o obj-$(CONFIG_SCSI_ENCLOSURE) += ses.o +obj-$(CONFIG_SCSI_OSD_INITIATOR) += osd/ + # This goes last, so that "real" scsi devices probe earlier obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o -- GitLab From 78a42ce8fb2604c459e9ebb2a4f2d546b8250111 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sun, 14 Dec 2008 00:55:17 +0900 Subject: [PATCH 3167/4982] [SCSI] osst: make all the buffer the same size This simiplifies the buffer management; all the buffers in osst_buffer become the same size. This is necessary to use the block layer API (sg driver was modified in the same way) since the block layer API takes the same size page frames instead of scatter gatter. Signed-off-by: FUJITA Tomonori Cc: Willem Riede Signed-off-by: James Bottomley --- drivers/scsi/osst.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 8f21cbbd7aa..13f908cb067 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -5286,11 +5286,6 @@ static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma) struct page *page = alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order); STbuffer->sg[segs].offset = 0; if (page == NULL) { - if (OS_FRAME_SIZE - got <= (max_segs - segs) * b_size / 2 && order) { - b_size /= 2; /* Large enough for the rest of the buffers */ - order--; - continue; - } printk(KERN_WARNING "osst :W: Failed to enlarge buffer to %d bytes.\n", OS_FRAME_SIZE); #if DEBUG -- GitLab From 26243043f207b3faa00594a33e10b2103205f27b Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sun, 14 Dec 2008 00:55:18 +0900 Subject: [PATCH 3168/4982] [SCSI] osst: replace scsi_execute_async with the block layer API This replaces scsi_execute_async with the block layer API. st does the same thing so it might make sense to have something like libst (there are other things that os and osst can share). Signed-off-by: FUJITA Tomonori Cc: Willem Riede Signed-off-by: James Bottomley --- drivers/scsi/osst.c | 87 +++++++++++++++++++++++++++++++++++++++++---- drivers/scsi/osst.h | 2 ++ 2 files changed, 83 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 13f908cb067..acb835837ee 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -317,18 +317,25 @@ static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt) /* Wakeup from interrupt */ -static void osst_sleep_done(void *data, char *sense, int result, int resid) +static void osst_end_async(struct request *req, int update) { - struct osst_request *SRpnt = data; + struct osst_request *SRpnt = req->end_io_data; struct osst_tape *STp = SRpnt->stp; + struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data; - memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE); - STp->buffer->cmdstat.midlevel_result = SRpnt->result = result; + STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors; #if DEBUG STp->write_pending = 0; #endif if (SRpnt->waiting) complete(SRpnt->waiting); + + if (SRpnt->bio) { + kfree(mdata->pages); + blk_rq_unmap_user(SRpnt->bio); + } + + __blk_put_request(req->q, req); } /* osst_request memory management */ @@ -342,6 +349,74 @@ static void osst_release_request(struct osst_request *streq) kfree(streq); } +static int osst_execute(struct osst_request *SRpnt, const unsigned char *cmd, + int cmd_len, int data_direction, void *buffer, unsigned bufflen, + int use_sg, int timeout, int retries) +{ + struct request *req; + struct page **pages = NULL; + struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data; + + int err = 0; + int write = (data_direction == DMA_TO_DEVICE); + + req = blk_get_request(SRpnt->stp->device->request_queue, write, GFP_KERNEL); + if (!req) + return DRIVER_ERROR << 24; + + req->cmd_type = REQ_TYPE_BLOCK_PC; + req->cmd_flags |= REQ_QUIET; + + SRpnt->bio = NULL; + + if (use_sg) { + struct scatterlist *sg, *sgl = (struct scatterlist *)buffer; + int i; + + pages = kzalloc(use_sg * sizeof(struct page *), GFP_KERNEL); + if (!pages) + goto free_req; + + for_each_sg(sgl, sg, use_sg, i) + pages[i] = sg_page(sg); + + mdata->null_mapped = 1; + + mdata->page_order = get_order(sgl[0].length); + mdata->nr_entries = + DIV_ROUND_UP(bufflen, PAGE_SIZE << mdata->page_order); + mdata->offset = 0; + + err = blk_rq_map_user(req->q, req, mdata, NULL, bufflen, GFP_KERNEL); + if (err) { + kfree(pages); + goto free_req; + } + SRpnt->bio = req->bio; + mdata->pages = pages; + + } else if (bufflen) { + err = blk_rq_map_kern(req->q, req, buffer, bufflen, GFP_KERNEL); + if (err) + goto free_req; + } + + req->cmd_len = cmd_len; + memset(req->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */ + memcpy(req->cmd, cmd, req->cmd_len); + req->sense = SRpnt->sense; + req->sense_len = 0; + req->timeout = timeout; + req->retries = retries; + req->end_io_data = SRpnt; + + blk_execute_rq_nowait(req->q, NULL, req, 1, osst_end_async); + return 0; +free_req: + blk_put_request(req); + return DRIVER_ERROR << 24; +} + /* Do the scsi command. Waits until command performed if do_wait is true. Otherwise osst_write_behind_check() is used to check that the command has finished. */ @@ -403,8 +478,8 @@ static struct osst_request * osst_do_scsi(struct osst_request *SRpnt, struct oss STp->buffer->cmdstat.have_sense = 0; STp->buffer->syscall_result = 0; - if (scsi_execute_async(STp->device, cmd, COMMAND_SIZE(cmd[0]), direction, bp, bytes, - use_sg, timeout, retries, SRpnt, osst_sleep_done, GFP_KERNEL)) + if (osst_execute(SRpnt, cmd, COMMAND_SIZE(cmd[0]), direction, bp, bytes, + use_sg, timeout, retries)) /* could not allocate the buffer or request was too large */ (STp->buffer)->syscall_result = (-EBUSY); else if (do_wait) { diff --git a/drivers/scsi/osst.h b/drivers/scsi/osst.h index 5aa22740b5d..11d26c57f3f 100644 --- a/drivers/scsi/osst.h +++ b/drivers/scsi/osst.h @@ -520,6 +520,7 @@ struct osst_buffer { int syscall_result; struct osst_request *last_SRpnt; struct st_cmdstatus cmdstat; + struct rq_map_data map_data; unsigned char *b_data; os_aux_t *aux; /* onstream AUX structure at end of each block */ unsigned short use_sg; /* zero or number of s/g segments for this adapter */ @@ -634,6 +635,7 @@ struct osst_request { int result; struct osst_tape *stp; struct completion *waiting; + struct bio *bio; }; /* Values of write_type */ -- GitLab From f078727b250c2653fc9a564f15547c17ebac3f99 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sun, 14 Dec 2008 01:23:45 +0900 Subject: [PATCH 3169/4982] [SCSI] remove scsi_req_map_sg No one uses scsi_execute_async with data transfer now. We can remove scsi_req_map_sg. Only scsi_eh_lock_door uses scsi_execute_async. scsi_eh_lock_door doesn't handle sense and the callback. So we can remove scsi_io_context too. Signed-off-by: FUJITA Tomonori Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 34 +++++-- drivers/scsi/scsi_lib.c | 203 +------------------------------------ include/scsi/scsi_device.h | 6 -- 3 files changed, 25 insertions(+), 218 deletions(-) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index ad6a1370761..0c2c73be197 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1441,6 +1441,11 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd) } } +static void eh_lock_door_done(struct request *req, int uptodate) +{ + __blk_put_request(req->q, req); +} + /** * scsi_eh_lock_door - Prevent medium removal for the specified device * @sdev: SCSI device to prevent medium removal @@ -1463,19 +1468,28 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd) */ static void scsi_eh_lock_door(struct scsi_device *sdev) { - unsigned char cmnd[MAX_COMMAND_SIZE]; + struct request *req; - cmnd[0] = ALLOW_MEDIUM_REMOVAL; - cmnd[1] = 0; - cmnd[2] = 0; - cmnd[3] = 0; - cmnd[4] = SCSI_REMOVAL_PREVENT; - cmnd[5] = 0; + req = blk_get_request(sdev->request_queue, READ, GFP_KERNEL); + if (!req) + return; - scsi_execute_async(sdev, cmnd, 6, DMA_NONE, NULL, 0, 0, 10 * HZ, - 5, NULL, NULL, GFP_KERNEL); -} + req->cmd[0] = ALLOW_MEDIUM_REMOVAL; + req->cmd[1] = 0; + req->cmd[2] = 0; + req->cmd[3] = 0; + req->cmd[4] = SCSI_REMOVAL_PREVENT; + req->cmd[5] = 0; + req->cmd_len = COMMAND_SIZE(req->cmd[0]); + + req->cmd_type = REQ_TYPE_BLOCK_PC; + req->cmd_flags |= REQ_QUIET; + req->timeout = 10 * HZ; + req->retries = 5; + + blk_execute_rq_nowait(req->q, NULL, req, 1, eh_lock_door_done); +} /** * scsi_restart_operations - restart io operations to the specified host. diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index b82ffd90632..4b13e36d3aa 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -277,196 +277,6 @@ int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, } EXPORT_SYMBOL(scsi_execute_req); -struct scsi_io_context { - void *data; - void (*done)(void *data, char *sense, int result, int resid); - char sense[SCSI_SENSE_BUFFERSIZE]; -}; - -static struct kmem_cache *scsi_io_context_cache; - -static void scsi_end_async(struct request *req, int uptodate) -{ - struct scsi_io_context *sioc = req->end_io_data; - - if (sioc->done) - sioc->done(sioc->data, sioc->sense, req->errors, req->data_len); - - kmem_cache_free(scsi_io_context_cache, sioc); - __blk_put_request(req->q, req); -} - -static int scsi_merge_bio(struct request *rq, struct bio *bio) -{ - struct request_queue *q = rq->q; - - bio->bi_flags &= ~(1 << BIO_SEG_VALID); - if (rq_data_dir(rq) == WRITE) - bio->bi_rw |= (1 << BIO_RW); - blk_queue_bounce(q, &bio); - - return blk_rq_append_bio(q, rq, bio); -} - -static void scsi_bi_endio(struct bio *bio, int error) -{ - bio_put(bio); -} - -/** - * scsi_req_map_sg - map a scatterlist into a request - * @rq: request to fill - * @sgl: scatterlist - * @nsegs: number of elements - * @bufflen: len of buffer - * @gfp: memory allocation flags - * - * scsi_req_map_sg maps a scatterlist into a request so that the - * request can be sent to the block layer. We do not trust the scatterlist - * sent to use, as some ULDs use that struct to only organize the pages. - */ -static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl, - int nsegs, unsigned bufflen, gfp_t gfp) -{ - struct request_queue *q = rq->q; - int nr_pages = (bufflen + sgl[0].offset + PAGE_SIZE - 1) >> PAGE_SHIFT; - unsigned int data_len = bufflen, len, bytes, off; - struct scatterlist *sg; - struct page *page; - struct bio *bio = NULL; - int i, err, nr_vecs = 0; - - for_each_sg(sgl, sg, nsegs, i) { - page = sg_page(sg); - off = sg->offset; - len = sg->length; - - while (len > 0 && data_len > 0) { - /* - * sg sends a scatterlist that is larger than - * the data_len it wants transferred for certain - * IO sizes - */ - bytes = min_t(unsigned int, len, PAGE_SIZE - off); - bytes = min(bytes, data_len); - - if (!bio) { - nr_vecs = min_t(int, BIO_MAX_PAGES, nr_pages); - nr_pages -= nr_vecs; - - bio = bio_alloc(gfp, nr_vecs); - if (!bio) { - err = -ENOMEM; - goto free_bios; - } - bio->bi_end_io = scsi_bi_endio; - } - - if (bio_add_pc_page(q, bio, page, bytes, off) != - bytes) { - bio_put(bio); - err = -EINVAL; - goto free_bios; - } - - if (bio->bi_vcnt >= nr_vecs) { - err = scsi_merge_bio(rq, bio); - if (err) { - bio_endio(bio, 0); - goto free_bios; - } - bio = NULL; - } - - page++; - len -= bytes; - data_len -=bytes; - off = 0; - } - } - - rq->buffer = rq->data = NULL; - rq->data_len = bufflen; - return 0; - -free_bios: - while ((bio = rq->bio) != NULL) { - rq->bio = bio->bi_next; - /* - * call endio instead of bio_put incase it was bounced - */ - bio_endio(bio, 0); - } - - return err; -} - -/** - * scsi_execute_async - insert request - * @sdev: scsi device - * @cmd: scsi command - * @cmd_len: length of scsi cdb - * @data_direction: DMA_TO_DEVICE, DMA_FROM_DEVICE, or DMA_NONE - * @buffer: data buffer (this can be a kernel buffer or scatterlist) - * @bufflen: len of buffer - * @use_sg: if buffer is a scatterlist this is the number of elements - * @timeout: request timeout in seconds - * @retries: number of times to retry request - * @privdata: data passed to done() - * @done: callback function when done - * @gfp: memory allocation flags - */ -int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd, - int cmd_len, int data_direction, void *buffer, unsigned bufflen, - int use_sg, int timeout, int retries, void *privdata, - void (*done)(void *, char *, int, int), gfp_t gfp) -{ - struct request *req; - struct scsi_io_context *sioc; - int err = 0; - int write = (data_direction == DMA_TO_DEVICE); - - sioc = kmem_cache_zalloc(scsi_io_context_cache, gfp); - if (!sioc) - return DRIVER_ERROR << 24; - - req = blk_get_request(sdev->request_queue, write, gfp); - if (!req) - goto free_sense; - req->cmd_type = REQ_TYPE_BLOCK_PC; - req->cmd_flags |= REQ_QUIET; - - if (use_sg) - err = scsi_req_map_sg(req, buffer, use_sg, bufflen, gfp); - else if (bufflen) - err = blk_rq_map_kern(req->q, req, buffer, bufflen, gfp); - - if (err) - goto free_req; - - req->cmd_len = cmd_len; - memset(req->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */ - memcpy(req->cmd, cmd, req->cmd_len); - req->sense = sioc->sense; - req->sense_len = 0; - req->timeout = timeout; - req->retries = retries; - req->end_io_data = sioc; - - sioc->data = privdata; - sioc->done = done; - - blk_execute_rq_nowait(req->q, NULL, req, 1, scsi_end_async); - return 0; - -free_req: - blk_put_request(req); -free_sense: - kmem_cache_free(scsi_io_context_cache, sioc); - return DRIVER_ERROR << 24; -} -EXPORT_SYMBOL_GPL(scsi_execute_async); - /* * Function: scsi_init_cmd_errh() * @@ -1920,20 +1730,12 @@ int __init scsi_init_queue(void) { int i; - scsi_io_context_cache = kmem_cache_create("scsi_io_context", - sizeof(struct scsi_io_context), - 0, 0, NULL); - if (!scsi_io_context_cache) { - printk(KERN_ERR "SCSI: can't init scsi io context cache\n"); - return -ENOMEM; - } - scsi_sdb_cache = kmem_cache_create("scsi_data_buffer", sizeof(struct scsi_data_buffer), 0, 0, NULL); if (!scsi_sdb_cache) { printk(KERN_ERR "SCSI: can't init scsi sdb cache\n"); - goto cleanup_io_context; + return -ENOMEM; } for (i = 0; i < SG_MEMPOOL_NR; i++) { @@ -1968,8 +1770,6 @@ cleanup_sdb: kmem_cache_destroy(sgp->slab); } kmem_cache_destroy(scsi_sdb_cache); -cleanup_io_context: - kmem_cache_destroy(scsi_io_context_cache); return -ENOMEM; } @@ -1978,7 +1778,6 @@ void scsi_exit_queue(void) { int i; - kmem_cache_destroy(scsi_io_context_cache); kmem_cache_destroy(scsi_sdb_cache); for (i = 0; i < SG_MEMPOOL_NR; i++) { diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 15b09266b7f..3f566af3f10 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -371,12 +371,6 @@ extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, int data_direction, void *buffer, unsigned bufflen, struct scsi_sense_hdr *, int timeout, int retries, int *resid); -extern int scsi_execute_async(struct scsi_device *sdev, - const unsigned char *cmd, int cmd_len, int data_direction, - void *buffer, unsigned bufflen, int use_sg, - int timeout, int retries, void *privdata, - void (*done)(void *, char *, int, int), - gfp_t gfp); static inline int __must_check scsi_device_reprobe(struct scsi_device *sdev) { -- GitLab From ef3fa8c6a2e7c53dbaf2eb33a09ad05177425f12 Mon Sep 17 00:00:00 2001 From: Ilgu Hong Date: Fri, 30 Jan 2009 17:00:09 -0600 Subject: [PATCH 3170/4982] [SCSI] scsi dh alua: fix group id masking The buf[i] is a byte but we are only asking 4 bits off the group_id. This patch has us take off a byte. Signed-off-by: Ilgu Hong Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/device_handler/scsi_dh_alua.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index e356b43753f..5096b0bf00e 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -247,8 +247,8 @@ static unsigned submit_stpg(struct scsi_device *sdev, struct alua_dh_data *h) /* Prepare the data buffer */ memset(h->buff, 0, stpg_len); h->buff[4] = TPGS_STATE_OPTIMIZED & 0x0f; - h->buff[6] = (h->group_id >> 8) & 0x0f; - h->buff[7] = h->group_id & 0x0f; + h->buff[6] = (h->group_id >> 8) & 0xff; + h->buff[7] = h->group_id & 0xff; rq = get_alua_req(sdev, h->buff, stpg_len, WRITE); if (!rq) -- GitLab From 49baef0a5dc3c964601c656c1bb2c3458a6934c6 Mon Sep 17 00:00:00 2001 From: Ilgu Hong Date: Fri, 30 Jan 2009 17:00:10 -0600 Subject: [PATCH 3171/4982] [SCSI] scsi dh alua: add intel Multi-Flex device This adds the Intel Multi-Flex device to scsi_dh_alua's scsi_dh_devlist, so the module attaches to these devs. Signed-off-by: Ilgu Hong Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/device_handler/scsi_dh_alua.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 5096b0bf00e..31e1df5c366 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -691,6 +691,7 @@ static const struct scsi_dh_devlist alua_dev_list[] = { {"IBM", "2107900" }, {"IBM", "2145" }, {"Pillar", "Axiom" }, + {"Intel", "Multi-Flex"}, {NULL, NULL} }; -- GitLab From 4d086f6baf73c02d12482c27c9f1e0682825ca13 Mon Sep 17 00:00:00 2001 From: Ilgu Hong Date: Fri, 30 Jan 2009 17:00:11 -0600 Subject: [PATCH 3172/4982] [SCSI] scsi dh alua: handle report luns data changed in check sense callout When we switch controllers the Intel Multi-Flex reports REPORTED_LUNS_DATA_HAS_CHANGED. This patch just has us retry the command. Signed-off-by: Ilgu Hong Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/device_handler/scsi_dh_alua.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 31e1df5c366..dba154c8ff6 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -461,6 +461,15 @@ static int alua_check_sense(struct scsi_device *sdev, */ return ADD_TO_MLQUEUE; } + if (sense_hdr->asc == 0x3f && sense_hdr->ascq == 0x0e) { + /* + * REPORTED_LUNS_DATA_HAS_CHANGED is reported + * when switching controllers on targets like + * Intel Multi-Flex. We can just retry. + */ + return ADD_TO_MLQUEUE; + } + break; } -- GitLab From b75424fcfe8fae56344a65e3f04bbc7e975e750e Mon Sep 17 00:00:00 2001 From: Wayne Boyer Date: Wed, 28 Jan 2009 08:24:50 -0800 Subject: [PATCH 3173/4982] [SCSI] ipr: add message to error table Adds a message to the error table for an error that wasn't previously handled. In some cases the I/O Adapter will detect an error condition and mark a block as "logically bad". Signed-off-by: Wayne Boyer Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 3f47cd1c46e..9d54c200685 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -354,6 +354,8 @@ struct ipr_error_table_t ipr_error_table[] = { "9076: Configuration error, missing remote IOA"}, {0x06679100, 0, IPR_DEFAULT_LOG_LEVEL, "4050: Enclosure does not support a required multipath function"}, + {0x06690000, 0, IPR_DEFAULT_LOG_LEVEL, + "4070: Logically bad block written on device"}, {0x06690200, 0, IPR_DEFAULT_LOG_LEVEL, "9041: Array protection temporarily suspended"}, {0x06698200, 0, IPR_DEFAULT_LOG_LEVEL, -- GitLab From ea41e41588c248ee8b8162869c1e1c0565a4b3f6 Mon Sep 17 00:00:00 2001 From: "Chauhan, Vijay" Date: Mon, 26 Jan 2009 21:29:37 +0530 Subject: [PATCH 3174/4982] [SCSI] scsi_dh_rdac: Retry for Quiescence in Progress in rdac device handler During device discovery read capacity fails with 0x068b02 and sets the device size to 0. As a reason any I/O submitted to this path gets killed at sd_prep_fn with BLKPREP_KILL. This patch is to retry for 0x068b02 Signed-off-by: Vijay Chauhan Acked-by: Chandra Seetharaman Signed-off-by: James Bottomley --- drivers/scsi/device_handler/scsi_dh_rdac.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 53664765570..f2b9d197e80 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -579,6 +579,11 @@ static int rdac_check_sense(struct scsi_device *sdev, * Power On, Reset, or Bus Device Reset, just retry. */ return ADD_TO_MLQUEUE; + if (sense_hdr->asc == 0x8b && sense_hdr->ascq == 0x02) + /* + * Quiescence in progress , just retry. + */ + return ADD_TO_MLQUEUE; break; } /* success just means we do not care what scsi-ml does */ -- GitLab From a3b7aeaba29e3dd995ece05ba50db9e0650c16b6 Mon Sep 17 00:00:00 2001 From: Brian King Date: Mon, 2 Feb 2009 18:39:40 -0600 Subject: [PATCH 3175/4982] [SCSI] ibmvfc: Better handle other FC initiators The ibmvfc driver currently always sets the role of all rports to FC_PORT_ROLE_FCP_TARGET, which is not correct for other initiators. This can cause problems if other initiators are on the fabric when we then try to scan the rport for LUNs. Fix this by looking at the service parameters returned in the PRLI to set the roles appropriately. Also look at the returned service parameters to decide whether or not we were actually able to successfully log into the target. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvfc.c | 62 +++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index ed1e728763a..93d1fbe4ee5 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -2767,6 +2767,40 @@ static void ibmvfc_retry_tgt_init(struct ibmvfc_target *tgt, ibmvfc_init_tgt(tgt, job_step); } +/* Defined in FC-LS */ +static const struct { + int code; + int retry; + int logged_in; +} prli_rsp [] = { + { 0, 1, 0 }, + { 1, 0, 1 }, + { 2, 1, 0 }, + { 3, 1, 0 }, + { 4, 0, 0 }, + { 5, 0, 0 }, + { 6, 0, 1 }, + { 7, 0, 0 }, + { 8, 1, 0 }, +}; + +/** + * ibmvfc_get_prli_rsp - Find PRLI response index + * @flags: PRLI response flags + * + **/ +static int ibmvfc_get_prli_rsp(u16 flags) +{ + int i; + int code = (flags & 0x0f00) >> 8; + + for (i = 0; i < ARRAY_SIZE(prli_rsp); i++) + if (prli_rsp[i].code == code) + return i; + + return 0; +} + /** * ibmvfc_tgt_prli_done - Completion handler for Process Login * @evt: ibmvfc event struct @@ -2777,15 +2811,36 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt) struct ibmvfc_target *tgt = evt->tgt; struct ibmvfc_host *vhost = evt->vhost; struct ibmvfc_process_login *rsp = &evt->xfer_iu->prli; + struct ibmvfc_prli_svc_parms *parms = &rsp->parms; u32 status = rsp->common.status; + int index; vhost->discovery_threads--; ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE); switch (status) { case IBMVFC_MAD_SUCCESS: - tgt_dbg(tgt, "Process Login succeeded\n"); - tgt->need_login = 0; - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_ADD_RPORT); + tgt_dbg(tgt, "Process Login succeeded: %X %02X %04X\n", + parms->type, parms->flags, parms->service_parms); + + if (parms->type == IBMVFC_SCSI_FCP_TYPE) { + index = ibmvfc_get_prli_rsp(parms->flags); + if (prli_rsp[index].logged_in) { + if (parms->flags & IBMVFC_PRLI_EST_IMG_PAIR) { + tgt->need_login = 0; + tgt->ids.roles = 0; + if (parms->service_parms & IBMVFC_PRLI_TARGET_FUNC) + tgt->ids.roles |= FC_PORT_ROLE_FCP_TARGET; + if (parms->service_parms & IBMVFC_PRLI_INITIATOR_FUNC) + tgt->ids.roles |= FC_PORT_ROLE_FCP_INITIATOR; + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_ADD_RPORT); + } else + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + } else if (prli_rsp[index].retry) + ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_prli); + else + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + } else + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); break; case IBMVFC_MAD_DRIVER_FAILED: break; @@ -2874,7 +2929,6 @@ static void ibmvfc_tgt_plogi_done(struct ibmvfc_event *evt) tgt->ids.node_name = wwn_to_u64(rsp->service_parms.node_name); tgt->ids.port_name = wwn_to_u64(rsp->service_parms.port_name); tgt->ids.port_id = tgt->scsi_id; - tgt->ids.roles = FC_PORT_ROLE_FCP_TARGET; memcpy(&tgt->service_parms, &rsp->service_parms, sizeof(tgt->service_parms)); memcpy(&tgt->service_parms_change, &rsp->service_parms_change, -- GitLab From c96952ed7031e7c576ecf90cf95b8ec099d5295a Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Wed, 4 Feb 2009 11:36:27 +0900 Subject: [PATCH 3176/4982] [SCSI] sg: avoid blk_put_request/blk_rq_unmap_user in interrupt This fixes the following oops: http://marc.info/?l=linux-kernel&m=123316111415677&w=2 You can reproduce this bug by interrupting a program before a sg response completes. This leads to the special sg state (the orphan state), then sg calls blk_put_request in interrupt (rq->end_io). The above bug report shows the recursive lock problem because sg calls blk_put_request in interrupt. We could call __blk_put_request here instead however we also need to handle blk_rq_unmap_user here, which can't be called in interrupt too. In the orphan state, we don't need to care about the data transfer (the program revoked the command) so adding 'just free the resource' mode to blk_rq_unmap_user is a possible option. I prefer to avoid complicating the blk mapping API when possible. I change the orphan state to call sg_finish_rem_req via execute_in_process_context. We hold sg_fd->kref so sg_fd doesn't go away until keventd_wq finishes our work. copy_from_user/to_user fails so blk_rq_unmap_user just frees the resource without the data transfer. Signed-off-by: FUJITA Tomonori Acked-by: Douglas Gilbert Signed-off-by: James Bottomley --- drivers/scsi/sg.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 18d079e3990..cdd83cf9710 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -138,6 +138,7 @@ typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */ volatile char done; /* 0->before bh, 1->before read, 2->read */ struct request *rq; struct bio *bio; + struct execute_work ew; } Sg_request; typedef struct sg_fd { /* holds the state of a file descriptor */ @@ -1234,6 +1235,15 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma) return 0; } +static void sg_rq_end_io_usercontext(struct work_struct *work) +{ + struct sg_request *srp = container_of(work, struct sg_request, ew.work); + struct sg_fd *sfp = srp->parentfp; + + sg_finish_rem_req(srp); + kref_put(&sfp->f_ref, sg_remove_sfp); +} + /* * This function is a "bottom half" handler that is called by the mid * level when a command is completed (or has failed). @@ -1312,10 +1322,9 @@ static void sg_rq_end_io(struct request *rq, int uptodate) */ wake_up_interruptible(&sfp->read_wait); kill_fasync(&sfp->async_qp, SIGPOLL, POLL_IN); + kref_put(&sfp->f_ref, sg_remove_sfp); } else - sg_finish_rem_req(srp); /* call with srp->done == 0 */ - - kref_put(&sfp->f_ref, sg_remove_sfp); + execute_in_process_context(sg_rq_end_io_usercontext, &srp->ew); } static struct file_operations sg_fops = { -- GitLab From 97218a1499391b174ea95e05b7a40fbb73e79813 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Sun, 8 Feb 2009 18:02:22 +0200 Subject: [PATCH 3177/4982] [SCSI] libosd: Fix NULL dereference BUG when target is not OSD conformant Very old OSC's Target had a BUG in the Get/Set attributes where it was looking in the wrong places for attribute lists length. If used with the open-osd initiator, the initiator would dereference a NULL pointer when retrieving system_information attributes. Checks are added that retrieval of each attribute is successful before accessing its value. Signed-off-by: Boaz Harrosh Signed-off-by: James Bottomley --- drivers/scsi/osd/osd_initiator.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index 0bbbf271fbb..552f58b655d 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c @@ -131,7 +131,7 @@ static int _osd_print_system_info(struct osd_dev *od, void *caps) pFirst = get_attrs[a++].val_ptr; OSD_INFO("OSD_ATTR_RI_PRODUCT_REVISION_LEVEL [%u]\n", - get_unaligned_be32(pFirst)); + pFirst ? get_unaligned_be32(pFirst) : ~0U); pFirst = get_attrs[a++].val_ptr; OSD_INFO("OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER [%s]\n", @@ -143,15 +143,18 @@ static int _osd_print_system_info(struct osd_dev *od, void *caps) pFirst = get_attrs[a++].val_ptr; OSD_INFO("OSD_ATTR_RI_TOTAL_CAPACITY [0x%llx]\n", - _LLU(get_unaligned_be64(pFirst))); + pFirst ? _LLU(get_unaligned_be64(pFirst)) : ~0ULL); pFirst = get_attrs[a++].val_ptr; OSD_INFO("OSD_ATTR_RI_USED_CAPACITY [0x%llx]\n", - _LLU(get_unaligned_be64(pFirst))); + pFirst ? _LLU(get_unaligned_be64(pFirst)) : ~0ULL); pFirst = get_attrs[a++].val_ptr; OSD_INFO("OSD_ATTR_RI_NUMBER_OF_PARTITIONS [%llu]\n", - _LLU(get_unaligned_be64(pFirst))); + pFirst ? _LLU(get_unaligned_be64(pFirst)) : ~0ULL); + + if (a >= nelem) + goto out; /* FIXME: Where are the time utilities */ pFirst = get_attrs[a++].val_ptr; -- GitLab From f290f1970f01287eaaffc798a677594a57ebd65e Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 8 Feb 2009 21:59:48 -0600 Subject: [PATCH 3178/4982] [SCSI] Make scsi.h independent of the rest of the scsi includes This allows it to compile and be used on the ps3 platform that wants to use the #define values in scsi.h without actually having CONFIG_SCSI set. Signed-off-by: James Bottomley --- block/cmd-filter.c | 1 + include/scsi/scsi.h | 19 ++----------------- include/scsi/scsi_cmnd.h | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/block/cmd-filter.c b/block/cmd-filter.c index 504b275e1b9..572bbc2f900 100644 --- a/block/cmd-filter.c +++ b/block/cmd-filter.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 80d7f60e266..084478e14d2 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -9,7 +9,8 @@ #define _SCSI_SCSI_H #include -#include + +struct scsi_cmnd; /* * The maximum number of SG segments that we will put inside a @@ -439,22 +440,6 @@ static inline int scsi_is_wlun(unsigned int lun) #define host_byte(result) (((result) >> 16) & 0xff) #define driver_byte(result) (((result) >> 24) & 0xff) -static inline void set_msg_byte(struct scsi_cmnd *cmd, char status) -{ - cmd->result |= status << 8; -} - -static inline void set_host_byte(struct scsi_cmnd *cmd, char status) -{ - cmd->result |= status << 16; -} - -static inline void set_driver_byte(struct scsi_cmnd *cmd, char status) -{ - cmd->result |= status << 24; -} - - #define sense_class(sense) (((sense) >> 4) & 0x7) #define sense_error(sense) ((sense) & 0xf) #define sense_valid(sense) ((sense) & 0x80); diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 855bf95963e..43b50d36925 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -291,4 +291,19 @@ static inline struct scsi_data_buffer *scsi_prot(struct scsi_cmnd *cmd) #define scsi_for_each_prot_sg(cmd, sg, nseg, __i) \ for_each_sg(scsi_prot_sglist(cmd), sg, nseg, __i) +static inline void set_msg_byte(struct scsi_cmnd *cmd, char status) +{ + cmd->result |= status << 8; +} + +static inline void set_host_byte(struct scsi_cmnd *cmd, char status) +{ + cmd->result |= status << 16; +} + +static inline void set_driver_byte(struct scsi_cmnd *cmd, char status) +{ + cmd->result |= status << 24; +} + #endif /* _SCSI_SCSI_CMND_H */ -- GitLab From aa6cd29b72a5d8e6e5c8f536bc48693824ebfe09 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 4 Feb 2009 22:17:29 +0100 Subject: [PATCH 3179/4982] [SCSI] libfc: Correct use of ! and & !ep->esb_stat is either 1 or 0, and the rightmost bit of ESB_ST_COMPLETE is always 0, making the result of !ep->esb_stat & ESB_ST_COMPLETE always 0. Thus parentheses around the argument to ! seem needed. The semantic patch that makes this change is as follows: (http://www.emn.fr/x-info/coccinelle/) // @@ expression E; constant C; @@ ( !E & !C | - !E & C + !(E & C) ) // Signed-off-by: Julia Lawall Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 505825b6124..8a0c5c239e9 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -281,7 +281,7 @@ static void fc_exch_release(struct fc_exch *ep) ep->destructor(&ep->seq, ep->arg); if (ep->lp->tt.exch_put) ep->lp->tt.exch_put(ep->lp, mp, ep->xid); - WARN_ON(!ep->esb_stat & ESB_ST_COMPLETE); + WARN_ON(!(ep->esb_stat & ESB_ST_COMPLETE)); mempool_free(ep, mp->ep_pool); } } -- GitLab From 2134bc72ddc04d412c0c2ce93a9c6f19de6cac35 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 12 Feb 2009 02:42:56 +0900 Subject: [PATCH 3180/4982] [SCSI] sg: remove unnecessary function declarations Signed-off-by: FUJITA Tomonori Acked-by: Douglas Gilbert Signed-off-by: James Bottomley --- drivers/scsi/sg.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index cdd83cf9710..f493d7fca34 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -101,7 +101,6 @@ static int scatter_elem_sz_prev = SG_SCATTER_SZ; #define SG_SECTOR_MSK (SG_SECTOR_SZ - 1) static int sg_add(struct device *, struct class_interface *); -static void sg_device_destroy(struct kref *kref); static void sg_remove(struct device *, struct class_interface *); static DEFINE_IDR(sg_index_idr); @@ -178,14 +177,11 @@ typedef struct sg_device { /* holds the state of each scsi generic device */ struct kref d_ref; } Sg_device; -static int sg_fasync(int fd, struct file *filp, int mode); /* tasklet or soft irq callback */ static void sg_rq_end_io(struct request *rq, int uptodate); static int sg_start_req(Sg_request *srp, unsigned char *cmd); static void sg_finish_rem_req(Sg_request * srp); static int sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size); -static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, - int tablesize); static ssize_t sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp); static ssize_t sg_new_write(Sg_fd *sfp, struct file *file, @@ -204,12 +200,8 @@ static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id); static Sg_request *sg_add_request(Sg_fd * sfp); static int sg_remove_request(Sg_fd * sfp, Sg_request * srp); static int sg_res_in_use(Sg_fd * sfp); -static Sg_device *sg_lookup_dev(int dev); static Sg_device *sg_get_dev(int dev); static void sg_put_dev(Sg_device *sdp); -#ifdef CONFIG_SCSI_PROC_FS -static int sg_last_dev(void); -#endif #define SZ_SG_HEADER sizeof(struct sg_header) #define SZ_SG_IO_HDR sizeof(sg_io_hdr_t) -- GitLab From b2ed6c69aa3c1a3f496e2a72f770d53069371df3 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 12 Feb 2009 02:42:57 +0900 Subject: [PATCH 3181/4982] [SCSI] sg: use ALIGN macro This changes sg_build_indirect() to use ALIGN macro instead of calculating by hand. Signed-off-by: FUJITA Tomonori Acked-by: Douglas Gilbert Signed-off-by: James Bottomley --- drivers/scsi/sg.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index f493d7fca34..d45ac4aab92 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -98,7 +98,6 @@ static int scatter_elem_sz = SG_SCATTER_SZ; static int scatter_elem_sz_prev = SG_SCATTER_SZ; #define SG_SECTOR_SZ 512 -#define SG_SECTOR_MSK (SG_SECTOR_SZ - 1) static int sg_add(struct device *, struct class_interface *); static void sg_remove(struct device *, struct class_interface *); @@ -1723,8 +1722,8 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) return -EFAULT; if (0 == blk_size) ++blk_size; /* don't know why */ -/* round request up to next highest SG_SECTOR_SZ byte boundary */ - blk_size = (blk_size + SG_SECTOR_MSK) & (~SG_SECTOR_MSK); + /* round request up to next highest SG_SECTOR_SZ byte boundary */ + blk_size = ALIGN(blk_size, SG_SECTOR_SZ); SCSI_LOG_TIMEOUT(4, printk("sg_build_indirect: buff_size=%d, blk_size=%d\n", buff_size, blk_size)); -- GitLab From 3442f802a8169a0c18d411d95f0e71b9205ed607 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Mon, 16 Feb 2009 13:26:53 +0900 Subject: [PATCH 3182/4982] [SCSI] sg: remove the own list management for struct sg_fd This replaces the own list management for struct sg_fd with the standard list_head structure. Signed-off-by: FUJITA Tomonori Acked-by: Douglas Gilbert Signed-off-by: James Bottomley --- drivers/scsi/sg.c | 50 +++++++++++++---------------------------------- 1 file changed, 14 insertions(+), 36 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index d45ac4aab92..7bf54c9a33b 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -140,7 +140,7 @@ typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */ } Sg_request; typedef struct sg_fd { /* holds the state of a file descriptor */ - struct sg_fd *nextfp; /* NULL when last opened fd on this device */ + struct list_head sfd_siblings; struct sg_device *parentdp; /* owning device */ wait_queue_head_t read_wait; /* queue read until command done */ rwlock_t rq_list_lock; /* protect access to list in req_arr */ @@ -167,7 +167,7 @@ typedef struct sg_device { /* holds the state of each scsi generic device */ wait_queue_head_t o_excl_wait; /* queue open() when O_EXCL in use */ int sg_tablesize; /* adapter's max scatter-gather table size */ u32 index; /* device index number */ - Sg_fd *headfp; /* first open fd belonging to this device */ + struct list_head sfds; volatile char detached; /* 0->attached, 1->detached pending removal */ volatile char exclude; /* opened for exclusive access */ char sgdebug; /* 0->off, 1->sense, 9->dump dev, 10-> all devs */ @@ -258,13 +258,13 @@ sg_open(struct inode *inode, struct file *filp) retval = -EPERM; /* Can't lock it with read only access */ goto error_out; } - if (sdp->headfp && (flags & O_NONBLOCK)) { + if (!list_empty(&sdp->sfds) && (flags & O_NONBLOCK)) { retval = -EBUSY; goto error_out; } res = 0; __wait_event_interruptible(sdp->o_excl_wait, - ((sdp->headfp || sdp->exclude) ? 0 : (sdp->exclude = 1)), res); + ((!list_empty(&sdp->sfds) || sdp->exclude) ? 0 : (sdp->exclude = 1)), res); if (res) { retval = res; /* -ERESTARTSYS because signal hit process */ goto error_out; @@ -286,7 +286,7 @@ sg_open(struct inode *inode, struct file *filp) retval = -ENODEV; goto error_out; } - if (!sdp->headfp) { /* no existing opens on this device */ + if (list_empty(&sdp->sfds)) { /* no existing opens on this device */ sdp->sgdebug = 0; q = sdp->device->request_queue; sdp->sg_tablesize = min(q->max_hw_segments, @@ -1375,6 +1375,7 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) disk->first_minor = k; sdp->disk = disk; sdp->device = scsidp; + INIT_LIST_HEAD(&sdp->sfds); init_waitqueue_head(&sdp->o_excl_wait); sdp->sg_tablesize = min(q->max_hw_segments, q->max_phys_segments); sdp->index = k; @@ -1517,7 +1518,7 @@ static void sg_remove(struct device *cl_dev, struct class_interface *cl_intf) /* Need a write lock to set sdp->detached. */ write_lock_irqsave(&sg_index_lock, iflags); sdp->detached = 1; - for (sfp = sdp->headfp; sfp; sfp = sfp->nextfp) { + list_for_each_entry(sfp, &sdp->sfds, sfd_siblings) { wake_up_interruptible(&sfp->read_wait); kill_fasync(&sfp->async_qp, SIGPOLL, POLL_HUP); } @@ -2024,14 +2025,7 @@ sg_add_sfp(Sg_device * sdp, int dev) sfp->keep_orphan = SG_DEF_KEEP_ORPHAN; sfp->parentdp = sdp; write_lock_irqsave(&sg_index_lock, iflags); - if (!sdp->headfp) - sdp->headfp = sfp; - else { /* add to tail of existing list */ - Sg_fd *pfp = sdp->headfp; - while (pfp->nextfp) - pfp = pfp->nextfp; - pfp->nextfp = sfp; - } + list_add_tail(&sfp->sfd_siblings, &sdp->sfds); write_unlock_irqrestore(&sg_index_lock, iflags); SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p\n", sfp)); if (unlikely(sg_big_buff != def_reserved_size)) @@ -2080,28 +2074,10 @@ static void sg_remove_sfp(struct kref *kref) { struct sg_fd *sfp = container_of(kref, struct sg_fd, f_ref); struct sg_device *sdp = sfp->parentdp; - Sg_fd *fp; - Sg_fd *prev_fp; unsigned long iflags; - /* CAUTION! Note that sfp can still be found by walking sdp->headfp - * even though the refcount is now 0. Therefore, unlink sfp from - * sdp->headfp BEFORE doing any other cleanup. - */ - write_lock_irqsave(&sg_index_lock, iflags); - prev_fp = sdp->headfp; - if (sfp == prev_fp) - sdp->headfp = prev_fp->nextfp; - else { - while ((fp = prev_fp->nextfp)) { - if (sfp == fp) { - prev_fp->nextfp = fp->nextfp; - break; - } - prev_fp = fp; - } - } + list_del(&sfp->sfd_siblings); write_unlock_irqrestore(&sg_index_lock, iflags); wake_up_interruptible(&sdp->o_excl_wait); @@ -2486,10 +2462,12 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp) const char * cp; unsigned int ms; - for (k = 0, fp = sdp->headfp; fp != NULL; ++k, fp = fp->nextfp) { + k = 0; + list_for_each_entry(fp, &sdp->sfds, sfd_siblings) { + k++; read_lock(&fp->rq_list_lock); /* irqs already disabled */ seq_printf(s, " FD(%d): timeout=%dms bufflen=%d " - "(res)sgat=%d low_dma=%d\n", k + 1, + "(res)sgat=%d low_dma=%d\n", k, jiffies_to_msecs(fp->timeout), fp->reserve.bufflen, (int) fp->reserve.k_use_sg, @@ -2559,7 +2537,7 @@ static int sg_proc_seq_show_debug(struct seq_file *s, void *v) read_lock_irqsave(&sg_index_lock, iflags); sdp = it ? sg_lookup_dev(it->index) : NULL; - if (sdp && sdp->headfp) { + if (sdp && !list_empty(&sdp->sfds)) { struct scsi_device *scsidp = sdp->device; seq_printf(s, " >>> device=%s ", sdp->disk->disk_name); -- GitLab From b3f1f9aa082b2ab86dec4db3d8b1566af345387e Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 17 Feb 2009 16:59:24 +0100 Subject: [PATCH 3183/4982] [SCSI] ses: code_set == 1 is tested twice Signed-off-by: Roel Kluin Signed-off-by: James Bottomley --- drivers/scsi/ses.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c index f2cf9523554..c9146d751cb 100644 --- a/drivers/scsi/ses.c +++ b/drivers/scsi/ses.c @@ -370,7 +370,7 @@ static void ses_match_to_enclosure(struct enclosure_device *edev, u8 type = desc[1] & 0x0f; u8 len = desc[3]; - if (piv && code_set == 1 && assoc == 1 && code_set == 1 + if (piv && code_set == 1 && assoc == 1 && proto == SCSI_PROTOCOL_SAS && type == 3 && len == 8) efd.addr = (u64)desc[4] << 56 | (u64)desc[5] << 48 | -- GitLab From 5c211caa9f341f9eefbda89436d1440d1eccb3bc Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 18 Feb 2009 10:54:44 -0500 Subject: [PATCH 3184/4982] [SCSI] sd: tell the user when a disk's capacity is adjusted This patch (as1188) combines the tests for decrementing a drive's reported capacity and expands the comment. It also adds an informational message to the system log, informing the user when the reported value has been changed. Signed-off-by: Alan Stern Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 4970ae4a62d..e744ee40be6 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1383,18 +1383,22 @@ repeat: sd_read_protection_type(sdkp, buffer); } - /* Some devices return the total number of sectors, not the - * highest sector number. Make the necessary adjustment. */ - if (sdp->fix_capacity) { + /* Some devices are known to return the total number of blocks, + * not the highest block number. Some devices have versions + * which do this and others which do not. Some devices we might + * suspect of doing this but we don't know for certain. + * + * If we know the reported capacity is wrong, decrement it. If + * we can only guess, then assume the number of blocks is even + * (usually true but not always) and err on the side of lowering + * the capacity. + */ + if (sdp->fix_capacity || + (sdp->guess_capacity && (sdkp->capacity & 0x01))) { + sd_printk(KERN_INFO, sdkp, "Adjusting the sector count " + "from its reported value: %llu\n", + (unsigned long long) sdkp->capacity); --sdkp->capacity; - - /* Some devices have version which report the correct sizes - * and others which do not. We guess size according to a heuristic - * and err on the side of lowering the capacity. */ - } else { - if (sdp->guess_capacity) - if (sdkp->capacity & 0x01) /* odd sizes are odd */ - --sdkp->capacity; } got_data: -- GitLab From 2cf22be045ee1b29f9ce5cf4f4552811bb24916a Mon Sep 17 00:00:00 2001 From: Wayne Boyer Date: Tue, 24 Feb 2009 11:36:00 -0800 Subject: [PATCH 3185/4982] [SCSI] ipr: Expose debug and fastfail parameters Expose the debug and fastfail parameters to /sys/module/ipr/parameters such that they can be enabled/disabled at run time. Signed-off-by: Wayne Boyer Acked-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 9d54c200685..def473f0a98 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -152,13 +152,13 @@ module_param_named(log_level, ipr_log_level, uint, 0); MODULE_PARM_DESC(log_level, "Set to 0 - 4 for increasing verbosity of device driver"); module_param_named(testmode, ipr_testmode, int, 0); MODULE_PARM_DESC(testmode, "DANGEROUS!!! Allows unsupported configurations"); -module_param_named(fastfail, ipr_fastfail, int, 0); +module_param_named(fastfail, ipr_fastfail, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(fastfail, "Reduce timeouts and retries"); module_param_named(transop_timeout, ipr_transop_timeout, int, 0); MODULE_PARM_DESC(transop_timeout, "Time in seconds to wait for adapter to come operational (default: 300)"); module_param_named(enable_cache, ipr_enable_cache, int, 0); MODULE_PARM_DESC(enable_cache, "Enable adapter's non-volatile write cache (default: 1)"); -module_param_named(debug, ipr_debug, int, 0); +module_param_named(debug, ipr_debug, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Enable device driver debugging logging. Set to 1 to enable. (default: 0)"); module_param_named(dual_ioa_raid, ipr_dual_ioa_raid, int, 0); MODULE_PARM_DESC(dual_ioa_raid, "Enable dual adapter RAID support. Set to 1 to enable. (default: 1)"); -- GitLab From d3ce65d12668ef1e3a164d48e04c59228d5ecf7b Mon Sep 17 00:00:00 2001 From: Tony Battersby Date: Thu, 8 Jan 2009 12:52:32 -0500 Subject: [PATCH 3186/4982] [SCSI] sym53c8xx: fix shost use-after-free and memory leak This patch fixes two bugs: 1) rmmod sym53c8xx uses shost after freeing it with scsi_put_host(shost). 2) insmod sym53c8xx doesn't call scsi_put_host(shost) if scsi_add_host() fails, causing a memory leak on the error path. Signed-off-by: Tony Battersby Signed-off-by: James Bottomley --- drivers/scsi/sym53c8xx_2/sym_glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index f4e6cde1fd0..ff5be958d3d 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -1660,6 +1660,7 @@ static int sym_detach(struct Scsi_Host *shost, struct pci_dev *pdev) OUTB(np, nc_istat, 0); sym_free_resources(np, pdev); + scsi_host_put(shost); return 1; } @@ -1749,7 +1750,6 @@ static void sym2_remove(struct pci_dev *pdev) struct Scsi_Host *shost = pci_get_drvdata(pdev); scsi_remove_host(shost); - scsi_host_put(shost); sym_detach(shost, pdev); pci_release_regions(pdev); pci_disable_device(pdev); -- GitLab From 07b9d81e849f64b990e943de6ad75b63dafe5a4b Mon Sep 17 00:00:00 2001 From: Tony Battersby Date: Thu, 8 Jan 2009 12:53:37 -0500 Subject: [PATCH 3187/4982] [SCSI] sym53c8xx: fix NULL deref on error path If sym_attach() fails to allocate np, the error path will dereference a NULL pointer for printk. Signed-off-by: Tony Battersby Signed-off-by: James Bottomley --- drivers/scsi/sym53c8xx_2/sym_glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index ff5be958d3d..cef03e76836 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -1418,7 +1418,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, attach_failed: if (!shost) return NULL; - printf_info("%s: giving up ...\n", sym_name(np)); + printf_info("sym%d: giving up ...\n", unit); if (np) sym_free_resources(np, pdev); scsi_host_put(shost); -- GitLab From b409063a9b7a56c0d658feaffedeb74ad71edce7 Mon Sep 17 00:00:00 2001 From: Tony Battersby Date: Thu, 8 Jan 2009 12:54:45 -0500 Subject: [PATCH 3188/4982] [SCSI] sym53c8xx: fix bogus free_irq() on error path If sym_attach() gets an error at or before request_irq(), then sym_free_resources() will call free_irq() for an unregistered interrupt handler. Signed-off-by: Tony Battersby Signed-off-by: James Bottomley --- drivers/scsi/sym53c8xx_2/sym_glue.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index cef03e76836..a8ac60caadc 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -1238,12 +1238,13 @@ static int sym53c8xx_proc_info(struct Scsi_Host *shost, char *buffer, /* * Free controller resources. */ -static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev) +static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev, + int do_free_irq) { /* * Free O/S specific resources. */ - if (pdev->irq) + if (do_free_irq) free_irq(pdev->irq, np->s.host); if (np->s.ioaddr) pci_iounmap(pdev, np->s.ioaddr); @@ -1275,6 +1276,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, struct pci_dev *pdev = dev->pdev; unsigned long flags; struct sym_fw *fw; + int do_free_irq = 0; printk(KERN_INFO "sym%d: <%s> rev 0x%x at pci %s irq %u\n", unit, dev->chip.name, pdev->revision, pci_name(pdev), @@ -1364,6 +1366,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, sym_name(np), pdev->irq); goto attach_failed; } + do_free_irq = 1; /* * After SCSI devices have been opened, we cannot @@ -1420,7 +1423,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, return NULL; printf_info("sym%d: giving up ...\n", unit); if (np) - sym_free_resources(np, pdev); + sym_free_resources(np, pdev, do_free_irq); scsi_host_put(shost); return NULL; @@ -1659,7 +1662,7 @@ static int sym_detach(struct Scsi_Host *shost, struct pci_dev *pdev) udelay(10); OUTB(np, nc_istat, 0); - sym_free_resources(np, pdev); + sym_free_resources(np, pdev, 1); scsi_host_put(shost); return 1; -- GitLab From a71d035de835caa7d14ef69928e0fde9fc241cc0 Mon Sep 17 00:00:00 2001 From: Tony Battersby Date: Thu, 8 Jan 2009 12:55:52 -0500 Subject: [PATCH 3189/4982] [SCSI] sym53c8xx: unmap pci memory after probe errors During sym2_probe(), sym_init_device() does pci_iomap(), but there is no corresponding pci_iounmap() if an error occurs before sym_attach() copies sym_device::s.{ioaddr,ramaddr} to np. 1) Add the sym_iounmap_device() function. 2) Call sym_iounmap_device() if an error occurs between sym_init_device() and the time sym_attach() allocates np. 3) Make sym_attach() copy sym_device::s.{ioaddr,ramaddr} to np before calling any function that can fail so that sym_free_resources() will do the unmap instead of sym_iounmap_device(). Also fixed by this patch: During sym2_probe(), if sym_check_raid() returns nonzero, then pci_release_regions() is never called. Signed-off-by: Tony Battersby Signed-off-by: James Bottomley --- drivers/scsi/sym53c8xx_2/sym_glue.c | 66 ++++++++++++++++++----------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index a8ac60caadc..8e69b5c35f5 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -1235,6 +1235,20 @@ static int sym53c8xx_proc_info(struct Scsi_Host *shost, char *buffer, } #endif /* SYM_LINUX_PROC_INFO_SUPPORT */ +/* + * Free resources claimed by sym_init_device(). Note that + * sym_free_resources() should be used instead of this function after calling + * sym_attach(). + */ +static void __devinit +sym_iounmap_device(struct sym_device *device) +{ + if (device->s.ioaddr) + pci_iounmap(device->pdev, device->s.ioaddr); + if (device->s.ramaddr) + pci_iounmap(device->pdev, device->s.ramaddr); +} + /* * Free controller resources. */ @@ -1272,7 +1286,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, { struct sym_data *sym_data; struct sym_hcb *np = NULL; - struct Scsi_Host *shost; + struct Scsi_Host *shost = NULL; struct pci_dev *pdev = dev->pdev; unsigned long flags; struct sym_fw *fw; @@ -1287,11 +1301,11 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, */ fw = sym_find_firmware(&dev->chip); if (!fw) - return NULL; + goto attach_failed; shost = scsi_host_alloc(tpnt, sizeof(*sym_data)); if (!shost) - return NULL; + goto attach_failed; sym_data = shost_priv(shost); /* @@ -1321,6 +1335,13 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, np->maxoffs = dev->chip.offset_max; np->maxburst = dev->chip.burst_max; np->myaddr = dev->host_id; + np->mmio_ba = (u32)dev->mmio_base; + np->s.ioaddr = dev->s.ioaddr; + np->s.ramaddr = dev->s.ramaddr; + if (!(np->features & FE_RAM)) + dev->ram_base = 0; + if (dev->ram_base) + np->ram_ba = (u32)dev->ram_base; /* * Edit its name. @@ -1336,22 +1357,6 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, goto attach_failed; } - /* - * Try to map the controller chip to - * virtual and physical memory. - */ - np->mmio_ba = (u32)dev->mmio_base; - np->s.ioaddr = dev->s.ioaddr; - np->s.ramaddr = dev->s.ramaddr; - - /* - * Map on-chip RAM if present and supported. - */ - if (!(np->features & FE_RAM)) - dev->ram_base = 0; - if (dev->ram_base) - np->ram_ba = (u32)dev->ram_base; - if (sym_hcb_attach(shost, fw, dev->nvram)) goto attach_failed; @@ -1419,12 +1424,13 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, "TERMINATION, DEVICE POWER etc.!\n", sym_name(np)); spin_unlock_irqrestore(shost->host_lock, flags); attach_failed: - if (!shost) - return NULL; printf_info("sym%d: giving up ...\n", unit); if (np) sym_free_resources(np, pdev, do_free_irq); - scsi_host_put(shost); + else + sym_iounmap_device(dev); + if (shost) + scsi_host_put(shost); return NULL; } @@ -1700,6 +1706,8 @@ static int __devinit sym2_probe(struct pci_dev *pdev, struct sym_device sym_dev; struct sym_nvram nvram; struct Scsi_Host *shost; + int do_iounmap = 0; + int do_disable_device = 1; memset(&sym_dev, 0, sizeof(sym_dev)); memset(&nvram, 0, sizeof(nvram)); @@ -1713,11 +1721,15 @@ static int __devinit sym2_probe(struct pci_dev *pdev, goto disable; sym_init_device(pdev, &sym_dev); + do_iounmap = 1; + if (sym_check_supported(&sym_dev)) goto free; - if (sym_check_raid(&sym_dev)) - goto leave; /* Don't disable the device */ + if (sym_check_raid(&sym_dev)) { + do_disable_device = 0; /* Don't disable the device */ + goto free; + } if (sym_set_workarounds(&sym_dev)) goto free; @@ -1726,6 +1738,7 @@ static int __devinit sym2_probe(struct pci_dev *pdev, sym_get_nvram(&sym_dev, &nvram); + do_iounmap = 0; /* Don't sym_iounmap_device() after sym_attach(). */ shost = sym_attach(&sym2_template, attach_count, &sym_dev); if (!shost) goto free; @@ -1741,9 +1754,12 @@ static int __devinit sym2_probe(struct pci_dev *pdev, detach: sym_detach(pci_get_drvdata(pdev), pdev); free: + if (do_iounmap) + sym_iounmap_device(&sym_dev); pci_release_regions(pdev); disable: - pci_disable_device(pdev); + if (do_disable_device) + pci_disable_device(pdev); leave: return -ENODEV; } -- GitLab From 783fa7311b2c639f39c6163f9fbb05253fb2d702 Mon Sep 17 00:00:00 2001 From: Tony Battersby Date: Thu, 8 Jan 2009 12:56:58 -0500 Subject: [PATCH 3190/4982] [SCSI] sym53c8xx: handle pci_iomap() failures sym_init_device() doesn't check if pci_iomap() fails. It also tries to map device RAM without first checking FE_RAM. 1) Move some initialization from sym_init_device() to the top of sym2_probe(). 2) Rename sym_init_device() to sym_iomap_device(). 3) Call sym_iomap_device() after sym_check_supported() instead of before so that device->chip.features will be set. 4) Check FE_RAM in sym_iomap_device() before mapping RAM. 5) If sym_iomap_device() cannot map registers, then abort. 6) If sym_iomap_device() cannot map RAM, then fall back to not using RAM and continue. 7) Remove the check for FE_RAM in sym_attach() since dev->ram_base is now always set correctly. Signed-off-by: Tony Battersby Signed-off-by: James Bottomley --- drivers/scsi/sym53c8xx_2/sym_glue.c | 62 +++++++++++++++++------------ 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 8e69b5c35f5..a0d5aa6aad7 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -1236,7 +1236,7 @@ static int sym53c8xx_proc_info(struct Scsi_Host *shost, char *buffer, #endif /* SYM_LINUX_PROC_INFO_SUPPORT */ /* - * Free resources claimed by sym_init_device(). Note that + * Free resources claimed by sym_iomap_device(). Note that * sym_free_resources() should be used instead of this function after calling * sym_attach(). */ @@ -1336,12 +1336,9 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, np->maxburst = dev->chip.burst_max; np->myaddr = dev->host_id; np->mmio_ba = (u32)dev->mmio_base; + np->ram_ba = (u32)dev->ram_base; np->s.ioaddr = dev->s.ioaddr; np->s.ramaddr = dev->s.ramaddr; - if (!(np->features & FE_RAM)) - dev->ram_base = 0; - if (dev->ram_base) - np->ram_ba = (u32)dev->ram_base; /* * Edit its name. @@ -1559,30 +1556,28 @@ static int __devinit sym_set_workarounds(struct sym_device *device) } /* - * Read and check the PCI configuration for any detected NCR - * boards and save data for attaching after all boards have - * been detected. + * Map HBA registers and on-chip SRAM (if present). */ -static void __devinit -sym_init_device(struct pci_dev *pdev, struct sym_device *device) +static int __devinit +sym_iomap_device(struct sym_device *device) { - int i = 2; + struct pci_dev *pdev = device->pdev; struct pci_bus_region bus_addr; - - device->host_id = SYM_SETUP_HOST_ID; - device->pdev = pdev; + int i = 2; pcibios_resource_to_bus(pdev, &bus_addr, &pdev->resource[1]); device->mmio_base = bus_addr.start; - /* - * If the BAR is 64-bit, resource 2 will be occupied by the - * upper 32 bits - */ - if (!pdev->resource[i].flags) - i++; - pcibios_resource_to_bus(pdev, &bus_addr, &pdev->resource[i]); - device->ram_base = bus_addr.start; + if (device->chip.features & FE_RAM) { + /* + * If the BAR is 64-bit, resource 2 will be occupied by the + * upper 32 bits + */ + if (!pdev->resource[i].flags) + i++; + pcibios_resource_to_bus(pdev, &bus_addr, &pdev->resource[i]); + device->ram_base = bus_addr.start; + } #ifdef CONFIG_SCSI_SYM53C8XX_MMIO if (device->mmio_base) @@ -1592,9 +1587,21 @@ sym_init_device(struct pci_dev *pdev, struct sym_device *device) if (!device->s.ioaddr) device->s.ioaddr = pci_iomap(pdev, 0, pci_resource_len(pdev, 0)); - if (device->ram_base) + if (!device->s.ioaddr) { + dev_err(&pdev->dev, "could not map registers; giving up.\n"); + return -EIO; + } + if (device->ram_base) { device->s.ramaddr = pci_iomap(pdev, i, pci_resource_len(pdev, i)); + if (!device->s.ramaddr) { + dev_warn(&pdev->dev, + "could not map SRAM; continuing anyway.\n"); + device->ram_base = 0; + } + } + + return 0; } /* @@ -1711,6 +1718,8 @@ static int __devinit sym2_probe(struct pci_dev *pdev, memset(&sym_dev, 0, sizeof(sym_dev)); memset(&nvram, 0, sizeof(nvram)); + sym_dev.pdev = pdev; + sym_dev.host_id = SYM_SETUP_HOST_ID; if (pci_enable_device(pdev)) goto leave; @@ -1720,12 +1729,13 @@ static int __devinit sym2_probe(struct pci_dev *pdev, if (pci_request_regions(pdev, NAME53C8XX)) goto disable; - sym_init_device(pdev, &sym_dev); - do_iounmap = 1; - if (sym_check_supported(&sym_dev)) goto free; + if (sym_iomap_device(&sym_dev)) + goto free; + do_iounmap = 1; + if (sym_check_raid(&sym_dev)) { do_disable_device = 0; /* Don't disable the device */ goto free; -- GitLab From c2fd206e08cd55e7ee0d865affc172eb5af01c16 Mon Sep 17 00:00:00 2001 From: Tony Battersby Date: Thu, 8 Jan 2009 12:58:04 -0500 Subject: [PATCH 3191/4982] [SCSI] sym53c8xx: use a queue depth of 1 for untagged devices sym53c8xx uses a command queue depth of 2 for untagged devices, without good reason. This _mostly_ seems to work ok, but it has caused me some subtle problems. For example, I have an application where one thread sends write commands to a tape drive, and another thread sends log sense polling commands. With a queue depth of 2, the polling commands end up being starved for long periods of time while multiple write commands are serviced (this may also be related to the fact the the sg driver queues commands in LIFO order). This problem is fixed by changing the queue depth to 1 for untagged devices. I have tested this change extensively with many different tape drives, medium changers, and disk drives (disk drives of course use tagged commands and are therefore unaffected by this patch). Signed-off-by: Tony Battersby Signed-off-by: James Bottomley --- drivers/scsi/sym53c8xx_2/sym_glue.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index a0d5aa6aad7..23e78201588 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -792,9 +792,9 @@ static int sym53c8xx_slave_configure(struct scsi_device *sdev) /* * Select queue depth from driver setup. - * Donnot use more than configured by user. - * Use at least 2. - * Donnot use more than our maximum. + * Do not use more than configured by user. + * Use at least 1. + * Do not use more than our maximum. */ reqtags = sym_driver_setup.max_tag; if (reqtags > tp->usrtags) @@ -803,7 +803,7 @@ static int sym53c8xx_slave_configure(struct scsi_device *sdev) reqtags = 0; if (reqtags > SYM_CONF_MAX_TAG) reqtags = SYM_CONF_MAX_TAG; - depth_to_use = reqtags ? reqtags : 2; + depth_to_use = reqtags ? reqtags : 1; scsi_adjust_queue_depth(sdev, sdev->tagged_supported ? MSG_SIMPLE_TAG : 0, depth_to_use); -- GitLab From 058bb82c5628c88af802c19e2b56ae43551552d5 Mon Sep 17 00:00:00 2001 From: Tony Battersby Date: Thu, 8 Jan 2009 12:59:08 -0500 Subject: [PATCH 3192/4982] [SCSI] sym53c8xx: don't flood syslog with negotiation messages sym53c8xx prints a negotiation message after every check condition. This can add up to a lot of messages for removable-medium devices (CD-ROM, tape drives, etc.) that are being polled, since they return check condition when no medium is present. This patch suppresses the negotiation message if it would be the same as the last one printed. Signed-off-by: Tony Battersby Signed-off-by: James Bottomley --- drivers/scsi/sym53c8xx_2/sym_hipd.c | 29 ++++++++++++++++++++++++++--- drivers/scsi/sym53c8xx_2/sym_hipd.h | 3 +++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index fe6359d4e1e..ccea7db59f4 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -2039,6 +2039,29 @@ static void sym_settrans(struct sym_hcb *np, int target, u_char opts, u_char ofs } } +static void sym_announce_transfer_rate(struct sym_tcb *tp) +{ + struct scsi_target *starget = tp->starget; + + if (tp->tprint.period != spi_period(starget) || + tp->tprint.offset != spi_offset(starget) || + tp->tprint.width != spi_width(starget) || + tp->tprint.iu != spi_iu(starget) || + tp->tprint.dt != spi_dt(starget) || + tp->tprint.qas != spi_qas(starget) || + !tp->tprint.check_nego) { + tp->tprint.period = spi_period(starget); + tp->tprint.offset = spi_offset(starget); + tp->tprint.width = spi_width(starget); + tp->tprint.iu = spi_iu(starget); + tp->tprint.dt = spi_dt(starget); + tp->tprint.qas = spi_qas(starget); + tp->tprint.check_nego = 1; + + spi_display_xfer_agreement(starget); + } +} + /* * We received a WDTR. * Let everything be aware of the changes. @@ -2064,7 +2087,7 @@ static void sym_setwide(struct sym_hcb *np, int target, u_char wide) spi_qas(starget) = 0; if (sym_verbose >= 3) - spi_display_xfer_agreement(starget); + sym_announce_transfer_rate(tp); } /* @@ -2097,7 +2120,7 @@ sym_setsync(struct sym_hcb *np, int target, tp->tgoal.check_nego = 0; } - spi_display_xfer_agreement(starget); + sym_announce_transfer_rate(tp); } /* @@ -2125,7 +2148,7 @@ sym_setpprot(struct sym_hcb *np, int target, u_char opts, u_char ofs, spi_qas(starget) = tp->tgoal.qas = !!(opts & PPR_OPT_QAS); tp->tgoal.check_nego = 0; - spi_display_xfer_agreement(starget); + sym_announce_transfer_rate(tp); } /* diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h index 233a3d0b2ce..61d28fcfffb 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.h +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h @@ -420,6 +420,9 @@ struct sym_tcb { /* Transfer goal */ struct sym_trans tgoal; + /* Last printed transfer speed */ + struct sym_trans tprint; + /* * Keep track of the CCB used for the negotiation in order * to ensure that only 1 negotiation is queued at a time. -- GitLab From 77c019768f0607c36e25bec11ce3e1eabef09277 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 27 Feb 2009 16:51:42 -0500 Subject: [PATCH 3193/4982] [SCSI] fix /proc memory leak in the SCSI core The SCSI core calls scsi_proc_hostdir_add() from within scsi_host_alloc(), but the corresponding scsi_proc_hostdir_rm() routine is called from within scsi_remove_host(). As a result, if a host is allocated and then deallocated without ever being registered, the host's directory in /proc is leaked. This patch (as1181b) fixes this bug in the SCSI core by moving scsi_proc_hostdir_rm() into scsi_host_dev_release(). Signed-off-by: Alan Stern Signed-off-by: James Bottomley --- drivers/scsi/hosts.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index aa670a1d151..89d41a424b3 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -176,7 +176,6 @@ void scsi_remove_host(struct Scsi_Host *shost) transport_unregister_device(&shost->shost_gendev); device_unregister(&shost->shost_dev); device_del(&shost->shost_gendev); - scsi_proc_hostdir_rm(shost->hostt); } EXPORT_SYMBOL(scsi_remove_host); @@ -270,6 +269,8 @@ static void scsi_host_dev_release(struct device *dev) struct Scsi_Host *shost = dev_to_shost(dev); struct device *parent = dev->parent; + scsi_proc_hostdir_rm(shost->hostt); + if (shost->ehandler) kthread_stop(shost->ehandler); if (shost->work_q) -- GitLab From a5b11dda12ed7e3a79180b10ad6209a40a02989f Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Mon, 2 Mar 2009 13:08:54 +0100 Subject: [PATCH 3194/4982] [SCSI] zfcp: Remove some port flags PORT_PHYS_CLOSING is only set and cleared, but not actually used for status checking. PORT_INVALID_WWPN is set when the GID_PN request does not return a d_id for a remote port, e.g. when a remote port has been unplugged. For this case, the d_id is zero. In the erp we can check the d_id and use the normal escalation procedure that gives up after three retries and remove the special case. PORT_NO_WWPN is unused: Each port in the remote port list has a valid wwpn. The WKA ports are now tracked outside the port list. Remove the PORT_NO_WWPN flag, since this is no longer set for any port. Acked-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_aux.c | 13 ++++++------- drivers/s390/scsi/zfcp_def.h | 3 --- drivers/s390/scsi/zfcp_erp.c | 16 ++-------------- drivers/s390/scsi/zfcp_fc.c | 5 ++--- drivers/s390/scsi/zfcp_fsf.c | 6 +----- 5 files changed, 11 insertions(+), 32 deletions(-) diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 8af7dfbe022..497986f6d64 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -249,8 +249,8 @@ struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter, struct zfcp_port *port; list_for_each_entry(port, &adapter->port_list_head, list) - if ((port->wwpn == wwpn) && !(atomic_read(&port->status) & - (ZFCP_STATUS_PORT_NO_WWPN | ZFCP_STATUS_COMMON_REMOVE))) + if ((port->wwpn == wwpn) && + !(atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE)) return port; return NULL; } @@ -620,11 +620,10 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, dev_set_drvdata(&port->sysfs_device, port); read_lock_irq(&zfcp_data.config_lock); - if (!(status & ZFCP_STATUS_PORT_NO_WWPN)) - if (zfcp_get_port_by_wwpn(adapter, wwpn)) { - read_unlock_irq(&zfcp_data.config_lock); - goto err_out_free; - } + if (zfcp_get_port_by_wwpn(adapter, wwpn)) { + read_unlock_irq(&zfcp_data.config_lock); + goto err_out_free; + } read_unlock_irq(&zfcp_data.config_lock); if (device_register(&port->sysfs_device)) diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 510662783a6..62f9ee58c9b 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -243,9 +243,6 @@ struct zfcp_ls_adisc { /* remote port status */ #define ZFCP_STATUS_PORT_PHYS_OPEN 0x00000001 -#define ZFCP_STATUS_PORT_PHYS_CLOSING 0x00000004 -#define ZFCP_STATUS_PORT_NO_WWPN 0x00000008 -#define ZFCP_STATUS_PORT_INVALID_WWPN 0x00000020 /* well known address (WKA) port status*/ enum zfcp_wka_status { diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 387a3af528a..aed08e70aa9 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -777,10 +777,7 @@ static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *act) static void zfcp_erp_port_strategy_clearstati(struct zfcp_port *port) { - atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | - ZFCP_STATUS_PORT_PHYS_CLOSING | - ZFCP_STATUS_PORT_INVALID_WWPN, - &port->status); + atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, &port->status); } static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action) @@ -875,13 +872,8 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) return ZFCP_ERP_CONTINUES; } case ZFCP_ERP_STEP_NAMESERVER_LOOKUP: - if (!port->d_id) { - if (p_status & (ZFCP_STATUS_PORT_INVALID_WWPN)) { - zfcp_erp_port_failed(port, 26, NULL); - return ZFCP_ERP_EXIT; - } + if (!port->d_id) return ZFCP_ERP_FAILED; - } return zfcp_erp_port_strategy_open_port(act); case ZFCP_ERP_STEP_PORT_OPENING: @@ -1269,10 +1261,6 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: case ZFCP_ERP_ACTION_REOPEN_PORT: - if (atomic_read(&port->status) & ZFCP_STATUS_PORT_NO_WWPN) { - zfcp_port_put(port); - return; - } if ((result == ZFCP_ERP_SUCCEEDED) && !port->rport) zfcp_erp_rport_register(port); if ((result != ZFCP_ERP_SUCCEEDED) && port->rport) { diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index eabdfe24456..67e6b717787 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -259,10 +259,9 @@ static void zfcp_fc_ns_gid_pn_eval(unsigned long data) if (ct->status) return; - if (ct_iu_resp->header.cmd_rsp_code != ZFCP_CT_ACCEPT) { - atomic_set_mask(ZFCP_STATUS_PORT_INVALID_WWPN, &port->status); + if (ct_iu_resp->header.cmd_rsp_code != ZFCP_CT_ACCEPT) return; - } + /* paranoia */ if (ct_iu_req->wwpn != port->wwpn) return; diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index babe1b8ba25..638cd5a2919 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -1712,7 +1712,7 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req) struct zfcp_unit *unit; if (req->status & ZFCP_STATUS_FSFREQ_ERROR) - goto skip_fsfstatus; + return; switch (header->fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: @@ -1752,8 +1752,6 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req) &unit->status); break; } -skip_fsfstatus: - atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_CLOSING, &port->status); } /** @@ -1789,8 +1787,6 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) req->erp_action = erp_action; req->handler = zfcp_fsf_close_physical_port_handler; erp_action->fsf_req = req; - atomic_set_mask(ZFCP_STATUS_PORT_PHYS_CLOSING, - &erp_action->port->status); zfcp_fsf_start_erp_timer(req); retval = zfcp_fsf_req_send(req); -- GitLab From 86f8a1b4b472e4b2b58df5826709d4797d84d46f Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Mon, 2 Mar 2009 13:08:55 +0100 Subject: [PATCH 3195/4982] [SCSI] zfcp: Remove UNIT_REGISTERED status flag Use the device pointer in zfcp_unit for tracking if we have a registered SCSI device. With this approach, the flag ZFCP_STATUS_UNIT_REGISTERED is only redundant and can be removed. Acked-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_ccw.c | 3 +-- drivers/s390/scsi/zfcp_def.h | 1 - drivers/s390/scsi/zfcp_erp.c | 2 -- drivers/s390/scsi/zfcp_scsi.c | 4 +--- 4 files changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 285881f0764..683ac4ed5e5 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -72,8 +72,7 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device) list_for_each_entry_safe(port, p, &port_remove_lh, list) { list_for_each_entry_safe(unit, u, &unit_remove_lh, list) { - if (atomic_read(&unit->status) & - ZFCP_STATUS_UNIT_REGISTERED) + if (unit->device) scsi_remove_device(unit->device); zfcp_unit_dequeue(unit); } diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 62f9ee58c9b..56302a1a4b6 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -255,7 +255,6 @@ enum zfcp_wka_status { /* logical unit status */ #define ZFCP_STATUS_UNIT_SHARED 0x00000004 #define ZFCP_STATUS_UNIT_READONLY 0x00000008 -#define ZFCP_STATUS_UNIT_REGISTERED 0x00000010 #define ZFCP_STATUS_UNIT_SCSI_WORK_PENDING 0x00000020 /* FSF request status (this does not have a common part) */ diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index aed08e70aa9..2a00f812779 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -1250,8 +1250,6 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) case ZFCP_ERP_ACTION_REOPEN_UNIT: if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device && port->rport) { - atomic_set_mask(ZFCP_STATUS_UNIT_REGISTERED, - &unit->status); if (!(atomic_read(&unit->status) & ZFCP_STATUS_UNIT_SCSI_WORK_PENDING)) zfcp_erp_schedule_work(unit); diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 9dc42a68fbd..7829c72d83d 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -27,7 +27,6 @@ char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *fcp_rsp_iu) static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) { struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; - atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status); unit->device = NULL; zfcp_erp_unit_failed(unit, 12, NULL); zfcp_unit_put(unit); @@ -133,8 +132,7 @@ static int zfcp_scsi_slave_alloc(struct scsi_device *sdp) read_lock_irqsave(&zfcp_data.config_lock, flags); unit = zfcp_unit_lookup(adapter, sdp->channel, sdp->id, sdp->lun); - if (unit && - (atomic_read(&unit->status) & ZFCP_STATUS_UNIT_REGISTERED)) { + if (unit) { sdp->hostdata = unit; unit->device = sdp; zfcp_unit_get(unit); -- GitLab From 94506fd1483b39cd5d66b8ccb4ead3c9cc9542ac Mon Sep 17 00:00:00 2001 From: Martin Peschke Date: Mon, 2 Mar 2009 13:08:56 +0100 Subject: [PATCH 3196/4982] [SCSI] zfcp: add measurement data for average qdio queue utilisation Provide measurement data for the utilisation of the QDIO outbound queue. The additional value allows to calculate an average queue utilisation by looking at the deltas per time unit. Needed for capacity planning. It is up to user space to handle wrap-arounds of the 64 bit value. The new counter neatly complements the existing counter for queue full conditions. That is why, both statistics counter have been integrated. Signed-off-by: Martin Peschke Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_aux.c | 1 + drivers/s390/scsi/zfcp_def.h | 3 +++ drivers/s390/scsi/zfcp_qdio.c | 20 ++++++++++++++++++++ drivers/s390/scsi/zfcp_sysfs.c | 3 ++- 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 497986f6d64..969a3f09303 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -501,6 +501,7 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device) spin_lock_init(&adapter->scsi_dbf_lock); spin_lock_init(&adapter->rec_dbf_lock); spin_lock_init(&adapter->req_q_lock); + spin_lock_init(&adapter->qdio_stat_lock); rwlock_init(&adapter->erp_lock); rwlock_init(&adapter->abort_lock); diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 56302a1a4b6..a0cd4b08017 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -445,6 +445,9 @@ struct zfcp_adapter { spinlock_t req_q_lock; /* for operations on queue */ int req_q_pci_batch; /* SBALs since PCI indication was last set */ + ktime_t req_q_time; /* time of last fill level change */ + u64 req_q_util; /* for accounting */ + spinlock_t qdio_stat_lock; u32 fsf_req_seq_no; /* FSF cmnd seq number */ wait_queue_head_t request_wq; /* can be used to wait for more avaliable SBALs */ diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 33e0a206a0a..3d068709027 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -77,6 +77,23 @@ static void zfcp_qdio_zero_sbals(struct qdio_buffer *sbal[], int first, int cnt) } } +/* this needs to be called prior to updating the queue fill level */ +static void zfcp_qdio_account(struct zfcp_adapter *adapter) +{ + ktime_t now; + s64 span; + int free, used; + + spin_lock(&adapter->qdio_stat_lock); + now = ktime_get(); + span = ktime_us_delta(now, adapter->req_q_time); + free = max(0, atomic_read(&adapter->req_q.count)); + used = QDIO_MAX_BUFFERS_PER_Q - free; + adapter->req_q_util += used * span; + adapter->req_q_time = now; + spin_unlock(&adapter->qdio_stat_lock); +} + static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err, int queue_no, int first, int count, unsigned long parm) @@ -93,6 +110,7 @@ static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err, /* cleanup all SBALs being program-owned now */ zfcp_qdio_zero_sbals(queue->sbal, first, count); + zfcp_qdio_account(adapter); atomic_add(count, &queue->count); wake_up(&adapter->request_wq); } @@ -359,6 +377,8 @@ int zfcp_qdio_send(struct zfcp_fsf_req *fsf_req) sbale->flags |= SBAL_FLAGS0_PCI; } + zfcp_qdio_account(adapter); + retval = do_QDIO(adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, 0, first, count); if (unlikely(retval)) { diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index 899af2b45b1..9e9931af1b5 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c @@ -487,7 +487,8 @@ static ssize_t zfcp_sysfs_adapter_q_full_show(struct device *dev, struct zfcp_adapter *adapter = (struct zfcp_adapter *) scsi_host->hostdata[0]; - return sprintf(buf, "%d\n", atomic_read(&adapter->qdio_outb_full)); + return sprintf(buf, "%d %llu\n", atomic_read(&adapter->qdio_outb_full), + (unsigned long long)adapter->req_q_util); } static DEVICE_ATTR(queue_full, S_IRUGO, zfcp_sysfs_adapter_q_full_show, NULL); -- GitLab From 49f0f01c9966639f8fd7ce784a412e22057d9f2a Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Mon, 2 Mar 2009 13:08:57 +0100 Subject: [PATCH 3197/4982] [SCSI] zfcp: Simplify latency lock handling The lock only needs to protect the softirq context called from qdio against the userspace context called from sysfs. spin_lock and spin_lock_bh is enough. Acked-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_fsf.c | 5 ++--- drivers/s390/scsi/zfcp_sysfs.c | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 638cd5a2919..cce698114b0 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -2069,7 +2069,6 @@ static void zfcp_fsf_req_latency(struct zfcp_fsf_req *req) struct fsf_qual_latency_info *lat_inf; struct latency_cont *lat; struct zfcp_unit *unit = req->unit; - unsigned long flags; lat_inf = &req->qtcb->prefix.prot_status_qual.latency_info; @@ -2087,11 +2086,11 @@ static void zfcp_fsf_req_latency(struct zfcp_fsf_req *req) return; } - spin_lock_irqsave(&unit->latencies.lock, flags); + spin_lock(&unit->latencies.lock); zfcp_fsf_update_lat(&lat->channel, lat_inf->channel_lat); zfcp_fsf_update_lat(&lat->fabric, lat_inf->fabric_lat); lat->counter++; - spin_unlock_irqrestore(&unit->latencies.lock, flags); + spin_unlock(&unit->latencies.lock); } #ifdef CONFIG_BLK_DEV_IO_TRACE diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index 9e9931af1b5..14e38c231f0 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c @@ -318,10 +318,9 @@ zfcp_sysfs_unit_##_name##_latency_show(struct device *dev, \ struct zfcp_unit *unit = sdev->hostdata; \ struct zfcp_latencies *lat = &unit->latencies; \ struct zfcp_adapter *adapter = unit->port->adapter; \ - unsigned long flags; \ unsigned long long fsum, fmin, fmax, csum, cmin, cmax, cc; \ \ - spin_lock_irqsave(&lat->lock, flags); \ + spin_lock_bh(&lat->lock); \ fsum = lat->_name.fabric.sum * adapter->timer_ticks; \ fmin = lat->_name.fabric.min * adapter->timer_ticks; \ fmax = lat->_name.fabric.max * adapter->timer_ticks; \ @@ -329,7 +328,7 @@ zfcp_sysfs_unit_##_name##_latency_show(struct device *dev, \ cmin = lat->_name.channel.min * adapter->timer_ticks; \ cmax = lat->_name.channel.max * adapter->timer_ticks; \ cc = lat->_name.counter; \ - spin_unlock_irqrestore(&lat->lock, flags); \ + spin_unlock_bh(&lat->lock); \ \ do_div(fsum, 1000); \ do_div(fmin, 1000); \ -- GitLab From 52bfb558d2803590f86360ec3af1750897a9c010 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Mon, 2 Mar 2009 13:08:58 +0100 Subject: [PATCH 3198/4982] [SCSI] zfcp: Only increment req_id for successfully issued requests Only increment the req_id for successfully issued requests. This avoids some confusion when debugging issued fsf requests. Acked-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_fsf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index cce698114b0..14d7413b9e8 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -735,7 +735,7 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter, req->adapter = adapter; req->fsf_command = fsf_cmd; - req->req_id = adapter->req_no++; + req->req_id = adapter->req_no; req->sbal_number = 1; req->sbal_first = req_q->first; req->sbal_last = req_q->first; @@ -798,6 +798,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) /* Don't increase for unsolicited status */ if (req->qtcb) adapter->fsf_req_seq_no++; + adapter->req_no++; return 0; } -- GitLab From 92cab0d93a1107ad7f6d827fde62d1aa4db15e86 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Mon, 2 Mar 2009 13:08:59 +0100 Subject: [PATCH 3199/4982] [SCSI] zfcp: Wait for free SBALs when possible For calls from zfcp erp, scsi_eh and sysfs switch the calls issuing FSF requests to zfcp_fsf_req_sbal_get to wait for free SBALs. Acked-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_fsf.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 14d7413b9e8..1b25158c50f 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -929,8 +929,8 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id, struct qdio_buffer_element *sbale; struct zfcp_fsf_req *req = NULL; - spin_lock(&adapter->req_q_lock); - if (!zfcp_fsf_sbal_available(adapter)) + spin_lock_bh(&adapter->req_q_lock); + if (zfcp_fsf_req_sbal_get(adapter)) goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_ABORT_FCP_CMND, req_flags, adapter->pool.fsf_req_abort); @@ -961,7 +961,7 @@ out_error_free: zfcp_fsf_req_free(req); req = NULL; out: - spin_unlock(&adapter->req_q_lock); + spin_unlock_bh(&adapter->req_q_lock); return req; } @@ -1225,7 +1225,7 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) int retval = -EIO; spin_lock_bh(&adapter->req_q_lock); - if (!zfcp_fsf_sbal_available(adapter)) + if (zfcp_fsf_req_sbal_get(adapter)) goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA, @@ -1321,7 +1321,7 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action) return -EOPNOTSUPP; spin_lock_bh(&adapter->req_q_lock); - if (!zfcp_fsf_sbal_available(adapter)) + if (zfcp_fsf_req_sbal_get(adapter)) goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, ZFCP_REQ_AUTO_CLEANUP, @@ -1367,7 +1367,7 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter, return -EOPNOTSUPP; spin_lock_bh(&adapter->req_q_lock); - if (!zfcp_fsf_sbal_available(adapter)) + if (zfcp_fsf_req_sbal_get(adapter)) goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, 0, @@ -2452,8 +2452,8 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter, ZFCP_STATUS_COMMON_UNBLOCKED))) return NULL; - spin_lock(&adapter->req_q_lock); - if (!zfcp_fsf_sbal_available(adapter)) + spin_lock_bh(&adapter->req_q_lock); + if (zfcp_fsf_req_sbal_get(adapter)) goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags, adapter->pool.fsf_req_scsi); @@ -2487,7 +2487,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter, zfcp_fsf_req_free(req); req = NULL; out: - spin_unlock(&adapter->req_q_lock); + spin_unlock_bh(&adapter->req_q_lock); return req; } -- GitLab From 63caf367e1c92e0667a344d9b687c04e6ef054b5 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Mon, 2 Mar 2009 13:09:00 +0100 Subject: [PATCH 3200/4982] [SCSI] zfcp: Improve reliability of SCSI eh handlers in zfcp When the SCSI midlayer is running error recovery, the low-level error recovery in zfcp could be running and preventing the SCSI midlayer to issue error recovery requests. To avoid unnecessary error recovery escalation, wait for the zfcp erp to finish and retry if necessary. While reworking the SCSI eh handlers, alsa cleanup the code and simplify the interface from zfcp_scsi to the fsf layer. Acked-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_def.h | 3 - drivers/s390/scsi/zfcp_ext.h | 11 ++- drivers/s390/scsi/zfcp_fsf.c | 39 ++++------- drivers/s390/scsi/zfcp_scsi.c | 124 ++++++++++++++++------------------ 4 files changed, 78 insertions(+), 99 deletions(-) diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index a0cd4b08017..ff15f11923e 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -586,9 +586,6 @@ struct zfcp_fsf_req_qtcb { /********************** ZFCP SPECIFIC DEFINES ********************************/ -#define ZFCP_REQ_AUTO_CLEANUP 0x00000002 -#define ZFCP_REQ_NO_QTCB 0x00000008 - #define ZFCP_SET 0x00000100 #define ZFCP_CLEAR 0x00000200 diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index b5adeda93e1..799ce1db1f5 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -125,16 +125,13 @@ extern int zfcp_status_read_refill(struct zfcp_adapter *adapter); extern int zfcp_fsf_send_ct(struct zfcp_send_ct *, mempool_t *, struct zfcp_erp_action *); extern int zfcp_fsf_send_els(struct zfcp_send_els *); -extern int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *, - struct zfcp_unit *, - struct scsi_cmnd *, int, int); +extern int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *, + struct scsi_cmnd *); extern void zfcp_fsf_req_complete(struct zfcp_fsf_req *); extern void zfcp_fsf_req_free(struct zfcp_fsf_req *); -extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *, - struct zfcp_unit *, u8, int); +extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *, u8); extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long, - struct zfcp_adapter *, - struct zfcp_unit *, int); + struct zfcp_unit *); /* zfcp_qdio.c */ extern int zfcp_qdio_allocate(struct zfcp_adapter *); diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 1b25158c50f..cc69db3b71e 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -12,6 +12,9 @@ #include #include "zfcp_ext.h" +#define ZFCP_REQ_AUTO_CLEANUP 0x00000002 +#define ZFCP_REQ_NO_QTCB 0x00000008 + static void zfcp_fsf_request_timeout_handler(unsigned long data) { struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; @@ -913,27 +916,22 @@ static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req) /** * zfcp_fsf_abort_fcp_command - abort running SCSI command * @old_req_id: unsigned long - * @adapter: pointer to struct zfcp_adapter * @unit: pointer to struct zfcp_unit - * @req_flags: integer specifying the request flags * Returns: pointer to struct zfcp_fsf_req - * - * FIXME(design): should be watched by a timeout !!! */ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id, - struct zfcp_adapter *adapter, - struct zfcp_unit *unit, - int req_flags) + struct zfcp_unit *unit) { struct qdio_buffer_element *sbale; struct zfcp_fsf_req *req = NULL; + struct zfcp_adapter *adapter = unit->port->adapter; spin_lock_bh(&adapter->req_q_lock); if (zfcp_fsf_req_sbal_get(adapter)) goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_ABORT_FCP_CMND, - req_flags, adapter->pool.fsf_req_abort); + 0, adapter->pool.fsf_req_abort); if (IS_ERR(req)) { req = NULL; goto out; @@ -2309,21 +2307,17 @@ static void zfcp_set_fcp_dl(struct fcp_cmnd_iu *fcp_cmd, u32 fcp_dl) /** * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command) - * @adapter: adapter where scsi command is issued * @unit: unit where command is sent to * @scsi_cmnd: scsi command to be sent - * @timer: timer to be started when request is initiated - * @req_flags: flags for fsf_request */ -int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, - struct zfcp_unit *unit, - struct scsi_cmnd *scsi_cmnd, - int use_timer, int req_flags) +int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit, + struct scsi_cmnd *scsi_cmnd) { struct zfcp_fsf_req *req; struct fcp_cmnd_iu *fcp_cmnd_iu; unsigned int sbtype; int real_bytes, retval = -EIO; + struct zfcp_adapter *adapter = unit->port->adapter; if (unlikely(!(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_UNBLOCKED))) @@ -2332,7 +2326,8 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, spin_lock(&adapter->req_q_lock); if (!zfcp_fsf_sbal_available(adapter)) goto out; - req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags, + req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, + ZFCP_REQ_AUTO_CLEANUP, adapter->pool.fsf_req_scsi); if (IS_ERR(req)) { retval = PTR_ERR(req); @@ -2414,9 +2409,6 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, zfcp_set_fcp_dl(fcp_cmnd_iu, real_bytes); - if (use_timer) - zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); - retval = zfcp_fsf_req_send(req); if (unlikely(retval)) goto failed_scsi_cmnd; @@ -2434,19 +2426,16 @@ out: /** * zfcp_fsf_send_fcp_ctm - send SCSI task management command - * @adapter: pointer to struct zfcp-adapter * @unit: pointer to struct zfcp_unit * @tm_flags: unsigned byte for task management flags - * @req_flags: int request flags * Returns: on success pointer to struct fsf_req, NULL otherwise */ -struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter, - struct zfcp_unit *unit, - u8 tm_flags, int req_flags) +struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags) { struct qdio_buffer_element *sbale; struct zfcp_fsf_req *req = NULL; struct fcp_cmnd_iu *fcp_cmnd_iu; + struct zfcp_adapter *adapter = unit->port->adapter; if (unlikely(!(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_UNBLOCKED))) @@ -2455,7 +2444,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter, spin_lock_bh(&adapter->req_q_lock); if (zfcp_fsf_req_sbal_get(adapter)) goto out; - req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags, + req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, 0, adapter->pool.fsf_req_scsi); if (IS_ERR(req)) { req = NULL; diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 7829c72d83d..c17505f767a 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -87,8 +87,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt, return 0;; } - ret = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, 0, - ZFCP_REQ_AUTO_CLEANUP); + ret = zfcp_fsf_send_fcp_command_task(unit, scpnt); if (unlikely(ret == -EBUSY)) return SCSI_MLQUEUE_DEVICE_BUSY; else if (unlikely(ret < 0)) @@ -145,79 +144,91 @@ out: static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) { - struct Scsi_Host *scsi_host; - struct zfcp_adapter *adapter; - struct zfcp_unit *unit; - struct zfcp_fsf_req *fsf_req; + struct Scsi_Host *scsi_host = scpnt->device->host; + struct zfcp_adapter *adapter = + (struct zfcp_adapter *) scsi_host->hostdata[0]; + struct zfcp_unit *unit = scpnt->device->hostdata; + struct zfcp_fsf_req *old_req, *abrt_req; unsigned long flags; unsigned long old_req_id = (unsigned long) scpnt->host_scribble; int retval = SUCCESS; - - scsi_host = scpnt->device->host; - adapter = (struct zfcp_adapter *) scsi_host->hostdata[0]; - unit = scpnt->device->hostdata; + int retry = 3; /* avoid race condition between late normal completion and abort */ write_lock_irqsave(&adapter->abort_lock, flags); - /* Check whether corresponding fsf_req is still pending */ spin_lock(&adapter->req_list_lock); - fsf_req = zfcp_reqlist_find(adapter, old_req_id); + old_req = zfcp_reqlist_find(adapter, old_req_id); spin_unlock(&adapter->req_list_lock); - if (!fsf_req) { + if (!old_req) { write_unlock_irqrestore(&adapter->abort_lock, flags); - zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, 0); - return retval; + zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, + old_req_id); + return SUCCESS; } - fsf_req->data = NULL; + old_req->data = NULL; /* don't access old fsf_req after releasing the abort_lock */ write_unlock_irqrestore(&adapter->abort_lock, flags); - fsf_req = zfcp_fsf_abort_fcp_command(old_req_id, adapter, unit, 0); - if (!fsf_req) { - zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL, - old_req_id); - retval = FAILED; - return retval; + while (retry--) { + abrt_req = zfcp_fsf_abort_fcp_command(old_req_id, unit); + if (abrt_req) + break; + + zfcp_erp_wait(adapter); + if (!(atomic_read(&adapter->status) & + ZFCP_STATUS_COMMON_RUNNING)) { + zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL, + old_req_id); + return SUCCESS; + } } + if (!abrt_req) + return FAILED; - __wait_event(fsf_req->completion_wq, - fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); + wait_event(abrt_req->completion_wq, + abrt_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); - if (fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) { - zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, fsf_req, 0); - } else if (fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) { - zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, fsf_req, 0); - } else { - zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, fsf_req, 0); + if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) + zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, abrt_req, 0); + else if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) + zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, abrt_req, 0); + else { + zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, abrt_req, 0); retval = FAILED; } - zfcp_fsf_req_free(fsf_req); - + zfcp_fsf_req_free(abrt_req); return retval; } -static int zfcp_task_mgmt_function(struct zfcp_unit *unit, u8 tm_flags, - struct scsi_cmnd *scpnt) +static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags) { + struct zfcp_unit *unit = scpnt->device->hostdata; struct zfcp_adapter *adapter = unit->port->adapter; struct zfcp_fsf_req *fsf_req; int retval = SUCCESS; - - /* issue task management function */ - fsf_req = zfcp_fsf_send_fcp_ctm(adapter, unit, tm_flags, 0); - if (!fsf_req) { - zfcp_scsi_dbf_event_devreset("nres", tm_flags, unit, scpnt); - return FAILED; + int retry = 3; + + while (retry--) { + fsf_req = zfcp_fsf_send_fcp_ctm(unit, tm_flags); + if (fsf_req) + break; + + zfcp_erp_wait(adapter); + if (!(atomic_read(&adapter->status) & + ZFCP_STATUS_COMMON_RUNNING)) { + zfcp_scsi_dbf_event_devreset("nres", tm_flags, unit, + scpnt); + return SUCCESS; + } } + if (!fsf_req) + return FAILED; - __wait_event(fsf_req->completion_wq, - fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); + wait_event(fsf_req->completion_wq, + fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); - /* - * check completion status of task management function - */ if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) { zfcp_scsi_dbf_event_devreset("fail", tm_flags, unit, scpnt); retval = FAILED; @@ -228,39 +239,24 @@ static int zfcp_task_mgmt_function(struct zfcp_unit *unit, u8 tm_flags, zfcp_scsi_dbf_event_devreset("okay", tm_flags, unit, scpnt); zfcp_fsf_req_free(fsf_req); - return retval; } static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) { - struct zfcp_unit *unit = scpnt->device->hostdata; - - if (!unit) { - WARN_ON(1); - return SUCCESS; - } - return zfcp_task_mgmt_function(unit, FCP_LOGICAL_UNIT_RESET, scpnt); + return zfcp_task_mgmt_function(scpnt, FCP_LOGICAL_UNIT_RESET); } static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt) { - struct zfcp_unit *unit = scpnt->device->hostdata; - - if (!unit) { - WARN_ON(1); - return SUCCESS; - } - return zfcp_task_mgmt_function(unit, FCP_TARGET_RESET, scpnt); + return zfcp_task_mgmt_function(scpnt, FCP_TARGET_RESET); } static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) { - struct zfcp_unit *unit; - struct zfcp_adapter *adapter; + struct zfcp_unit *unit = scpnt->device->hostdata; + struct zfcp_adapter *adapter = unit->port->adapter; - unit = scpnt->device->hostdata; - adapter = unit->port->adapter; zfcp_erp_adapter_reopen(adapter, 0, 141, scpnt); zfcp_erp_wait(adapter); -- GitLab From 8fdf30d5429605a4c30cc515c73e5eab140035de Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Mon, 2 Mar 2009 13:09:01 +0100 Subject: [PATCH 3201/4982] [SCSI] zfcp: Send ELS ADISC from workqueue Issue ELS ADISC requests from workqueue. This allows the link test request to be sent when the request queue is full due to I/O load for other remote ports. It also simplifies request queue locking, zfcp_fsf_send_fcp_command_task is now the only function that has interrupts disabled from the caller. This is also a prereq for the FC passthrough support that issues ELS requests from userspace. Acked-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_aux.c | 1 + drivers/s390/scsi/zfcp_def.h | 1 + drivers/s390/scsi/zfcp_ext.h | 1 + drivers/s390/scsi/zfcp_fc.c | 28 ++++++++++++++++++---------- drivers/s390/scsi/zfcp_fsf.c | 18 ++++++------------ 5 files changed, 27 insertions(+), 22 deletions(-) diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 969a3f09303..1e16ab58b24 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -604,6 +604,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, init_waitqueue_head(&port->remove_wq); INIT_LIST_HEAD(&port->unit_list_head); INIT_WORK(&port->gid_pn_work, zfcp_erp_port_strategy_open_lookup); + INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work); port->adapter = adapter; port->d_id = d_id; diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index ff15f11923e..8412bb992ea 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -513,6 +513,7 @@ struct zfcp_port { u32 maxframe_size; u32 supported_classes; struct work_struct gid_pn_work; + struct work_struct test_link_work; }; struct zfcp_unit { diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 799ce1db1f5..a2b4987ac65 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -101,6 +101,7 @@ extern void zfcp_fc_incoming_els(struct zfcp_fsf_req *); extern int zfcp_fc_ns_gid_pn(struct zfcp_erp_action *); extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *); extern void zfcp_test_link(struct zfcp_port *); +extern void zfcp_fc_link_test_work(struct work_struct *); extern void zfcp_fc_nameserver_init(struct zfcp_adapter *); /* zfcp_fsf.c */ diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 67e6b717787..0f435ed9d1a 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -421,19 +421,12 @@ static int zfcp_fc_adisc(struct zfcp_port *port) return zfcp_fsf_send_els(&adisc->els); } -/** - * zfcp_test_link - lightweight link test procedure - * @port: port to be tested - * - * Test status of a link to a remote port using the ELS command ADISC. - * If there is a problem with the remote port, error recovery steps - * will be triggered. - */ -void zfcp_test_link(struct zfcp_port *port) +void zfcp_fc_link_test_work(struct work_struct *work) { + struct zfcp_port *port = + container_of(work, struct zfcp_port, test_link_work); int retval; - zfcp_port_get(port); retval = zfcp_fc_adisc(port); if (retval == 0) return; @@ -444,6 +437,21 @@ void zfcp_test_link(struct zfcp_port *port) zfcp_erp_port_forced_reopen(port, 0, 65, NULL); } +/** + * zfcp_test_link - lightweight link test procedure + * @port: port to be tested + * + * Test status of a link to a remote port using the ELS command ADISC. + * If there is a problem with the remote port, error recovery steps + * will be triggered. + */ +void zfcp_test_link(struct zfcp_port *port) +{ + zfcp_port_get(port); + if (!queue_work(zfcp_data.work_queue, &port->test_link_work)) + zfcp_port_put(port); +} + static void zfcp_free_sg_env(struct zfcp_gpn_ft *gpn_ft, int buf_num) { struct scatterlist *sg = &gpn_ft->sg_req; diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index cc69db3b71e..9c3f91a343f 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -647,14 +647,6 @@ static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req) } } -static int zfcp_fsf_sbal_available(struct zfcp_adapter *adapter) -{ - if (atomic_read(&adapter->req_q.count) > 0) - return 1; - atomic_inc(&adapter->qdio_outb_full); - return 0; -} - static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter) __releases(&adapter->req_q_lock) __acquires(&adapter->req_q_lock) @@ -1177,8 +1169,8 @@ int zfcp_fsf_send_els(struct zfcp_send_els *els) ZFCP_STATUS_COMMON_UNBLOCKED))) return -EBUSY; - spin_lock(&adapter->req_q_lock); - if (!zfcp_fsf_sbal_available(adapter)) + spin_lock_bh(&adapter->req_q_lock); + if (zfcp_fsf_req_sbal_get(adapter)) goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_ELS, ZFCP_REQ_AUTO_CLEANUP, NULL); @@ -1211,7 +1203,7 @@ int zfcp_fsf_send_els(struct zfcp_send_els *els) failed_send: zfcp_fsf_req_free(req); out: - spin_unlock(&adapter->req_q_lock); + spin_unlock_bh(&adapter->req_q_lock); return ret; } @@ -2324,8 +2316,10 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit, return -EBUSY; spin_lock(&adapter->req_q_lock); - if (!zfcp_fsf_sbal_available(adapter)) + if (atomic_read(&adapter->req_q.count) <= 0) { + atomic_inc(&adapter->qdio_outb_full); goto out; + } req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, ZFCP_REQ_AUTO_CLEANUP, adapter->pool.fsf_req_scsi); -- GitLab From 21283916322f579a580e413652cdefbfa3ec676f Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Mon, 2 Mar 2009 13:09:02 +0100 Subject: [PATCH 3202/4982] [SCSI] zfcp: remove undefined subtype for status read response The status read response FSF_STATUS_READ_SUB_ERROR_PORT is not defined in the specs and therefore not valid. All occurrences are removed from the code. Signed-off-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_dbf.c | 2 +- drivers/s390/scsi/zfcp_fsf.c | 9 +-------- drivers/s390/scsi/zfcp_fsf.h | 4 ---- 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index cb6df609953..ab843f23d42 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -615,7 +615,7 @@ static const char *zfcp_rec_dbf_ids[] = { [119] = "unknown protocol status", [120] = "unknown fsf command", [121] = "no recommendation for status qualifier", - [122] = "status read physical port closed in error", + [122] = "", [123] = "fc service class not supported", [124] = "", [125] = "need newer zfcp", diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 9c3f91a343f..698e42214a3 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -162,14 +162,7 @@ static void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req) list_for_each_entry(port, &adapter->port_list_head, list) if (port->d_id == d_id) { read_unlock_irqrestore(&zfcp_data.config_lock, flags); - switch (sr_buf->status_subtype) { - case FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT: - zfcp_erp_port_reopen(port, 0, 101, req); - break; - case FSF_STATUS_READ_SUB_ERROR_PORT: - zfcp_erp_port_shutdown(port, 0, 122, req); - break; - } + zfcp_erp_port_reopen(port, 0, 101, req); return; } read_unlock_irqrestore(&zfcp_data.config_lock, flags); diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index 8bb20025234..df7f232faba 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h @@ -127,10 +127,6 @@ #define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A #define FSF_STATUS_READ_FEATURE_UPDATE_ALERT 0x0000000C -/* status subtypes in status read buffer */ -#define FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT 0x00000001 -#define FSF_STATUS_READ_SUB_ERROR_PORT 0x00000002 - /* status subtypes for link down */ #define FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK 0x00000000 #define FSF_STATUS_READ_SUB_FDISC_FAILED 0x00000001 -- GitLab From cf13c08223148e525d28f4a740f2e73518ec6abe Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Mon, 2 Mar 2009 13:09:03 +0100 Subject: [PATCH 3203/4982] [SCSI] zfcp: prevent adapter close on initial adapter open An adapter close was always performed whether it was required, (e.g. in an error scenario) or not (e.g. initial open). This patch is changing the process in only doing an adapter close when it is required. Signed-off-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_erp.c | 69 ++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 2a00f812779..28c7185f24b 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -705,32 +705,10 @@ static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *act) return ZFCP_ERP_SUCCEEDED; } -static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *act, - int close) +static void zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *act) { - int retval = ZFCP_ERP_SUCCEEDED; struct zfcp_adapter *adapter = act->adapter; - if (close) - goto close_only; - - retval = zfcp_erp_adapter_strategy_open_qdio(act); - if (retval != ZFCP_ERP_SUCCEEDED) - goto failed_qdio; - - retval = zfcp_erp_adapter_strategy_open_fsf(act); - if (retval != ZFCP_ERP_SUCCEEDED) - goto failed_openfcp; - - atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &act->adapter->status); - - return ZFCP_ERP_SUCCEEDED; - - close_only: - atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, - &act->adapter->status); - - failed_openfcp: /* close queues to ensure that buffers are not accessed by adapter */ zfcp_qdio_close(adapter); zfcp_fsf_req_dismiss_all(adapter); @@ -738,27 +716,48 @@ static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *act, /* all ports and units are closed */ zfcp_erp_modify_adapter_status(adapter, 24, NULL, ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR); - failed_qdio: + atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | - ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, - &act->adapter->status); - return retval; + ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status); } -static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *act) +static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *act) { - int retval; + struct zfcp_adapter *adapter = act->adapter; - zfcp_erp_adapter_strategy_generic(act, 1); /* close */ - if (act->status & ZFCP_STATUS_ERP_CLOSE_ONLY) - return ZFCP_ERP_EXIT; + if (zfcp_erp_adapter_strategy_open_qdio(act)) { + atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | + ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, + &adapter->status); + return ZFCP_ERP_FAILED; + } - retval = zfcp_erp_adapter_strategy_generic(act, 0); /* open */ + if (zfcp_erp_adapter_strategy_open_fsf(act)) { + zfcp_erp_adapter_strategy_close(act); + return ZFCP_ERP_FAILED; + } + + atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &adapter->status); + + return ZFCP_ERP_SUCCEEDED; +} + +static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *act) +{ + struct zfcp_adapter *adapter = act->adapter; + + if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_OPEN) { + zfcp_erp_adapter_strategy_close(act); + if (act->status & ZFCP_STATUS_ERP_CLOSE_ONLY) + return ZFCP_ERP_EXIT; + } - if (retval == ZFCP_ERP_FAILED) + if (zfcp_erp_adapter_strategy_open(act)) { ssleep(8); + return ZFCP_ERP_FAILED; + } - return retval; + return ZFCP_ERP_SUCCEEDED; } static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *act) -- GitLab From 5ffd51a5e495a2a002efd523aef0001912b080bd Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Mon, 2 Mar 2009 13:09:04 +0100 Subject: [PATCH 3204/4982] [SCSI] zfcp: replace current ERP logging with a more convenient version The current number based id ERP logging is replaced by a string based tag version. The benefit is an easier location of the code in question and the removal of the lengthy array referencing the individual messages. The string (7 bytes) based version does not use more space since those bytes were "used" anyway due to the alignment of the structure. The encoding of the 7 byte string is as follows [0-1] = filename [2-5] = task/function [6] = section Due to the character of this string (fixed length) a string termination is not required here. Signed-off-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_aux.c | 3 +- drivers/s390/scsi/zfcp_ccw.c | 18 ++-- drivers/s390/scsi/zfcp_dbf.c | 188 +++------------------------------ drivers/s390/scsi/zfcp_dbf.h | 3 +- drivers/s390/scsi/zfcp_erp.c | 137 ++++++++++++------------ drivers/s390/scsi/zfcp_ext.h | 55 +++++----- drivers/s390/scsi/zfcp_fc.c | 14 +-- drivers/s390/scsi/zfcp_fsf.c | 131 ++++++++++++----------- drivers/s390/scsi/zfcp_qdio.c | 6 +- drivers/s390/scsi/zfcp_scsi.c | 4 +- drivers/s390/scsi/zfcp_sysfs.c | 12 +-- 11 files changed, 215 insertions(+), 356 deletions(-) diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 1e16ab58b24..69a31187e54 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -421,7 +421,8 @@ int zfcp_status_read_refill(struct zfcp_adapter *adapter) while (atomic_read(&adapter->stat_miss) > 0) if (zfcp_fsf_status_read(adapter)) { if (atomic_read(&adapter->stat_miss) >= 16) { - zfcp_erp_adapter_reopen(adapter, 0, 103, NULL); + zfcp_erp_adapter_reopen(adapter, 0, "axsref1", + NULL); return 1; } break; diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 683ac4ed5e5..3aeef289fe7 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -109,10 +109,10 @@ static int zfcp_ccw_set_online(struct ccw_device *ccw_device) BUG_ON(!zfcp_reqlist_isempty(adapter)); adapter->req_no = 0; - zfcp_erp_modify_adapter_status(adapter, 10, NULL, + zfcp_erp_modify_adapter_status(adapter, "ccsonl1", NULL, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); - zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 85, - NULL); + zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, + "ccsonl2", NULL); zfcp_erp_wait(adapter); up(&zfcp_data.config_sema); flush_work(&adapter->scan_work); @@ -136,7 +136,7 @@ static int zfcp_ccw_set_offline(struct ccw_device *ccw_device) down(&zfcp_data.config_sema); adapter = dev_get_drvdata(&ccw_device->dev); - zfcp_erp_adapter_shutdown(adapter, 0, 86, NULL); + zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1", NULL); zfcp_erp_wait(adapter); zfcp_erp_thread_kill(adapter); up(&zfcp_data.config_sema); @@ -159,21 +159,21 @@ static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event) case CIO_GONE: dev_warn(&adapter->ccw_device->dev, "The FCP device has been detached\n"); - zfcp_erp_adapter_shutdown(adapter, 0, 87, NULL); + zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1", NULL); break; case CIO_NO_PATH: dev_warn(&adapter->ccw_device->dev, "The CHPID for the FCP device is offline\n"); - zfcp_erp_adapter_shutdown(adapter, 0, 88, NULL); + zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2", NULL); break; case CIO_OPER: dev_info(&adapter->ccw_device->dev, "The FCP device is operational again\n"); - zfcp_erp_modify_adapter_status(adapter, 11, NULL, + zfcp_erp_modify_adapter_status(adapter, "ccnoti3", NULL, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, - 89, NULL); + "ccnoti4", NULL); break; } return 1; @@ -189,7 +189,7 @@ static void zfcp_ccw_shutdown(struct ccw_device *cdev) down(&zfcp_data.config_sema); adapter = dev_get_drvdata(&cdev->dev); - zfcp_erp_adapter_shutdown(adapter, 0, 90, NULL); + zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1", NULL); zfcp_erp_wait(adapter); up(&zfcp_data.config_sema); } diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index ab843f23d42..0a1a5dd8d01 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -490,172 +490,17 @@ static const char *zfcp_rec_dbf_tags[] = { [ZFCP_REC_DBF_ID_ACTION] = "action", }; -static const char *zfcp_rec_dbf_ids[] = { - [1] = "new", - [2] = "ready", - [3] = "kill", - [4] = "down sleep", - [5] = "down wakeup", - [6] = "down sleep ecd", - [7] = "down wakeup ecd", - [8] = "down sleep epd", - [9] = "down wakeup epd", - [10] = "online", - [11] = "operational", - [12] = "scsi slave destroy", - [13] = "propagate failed adapter", - [14] = "propagate failed port", - [15] = "block adapter", - [16] = "unblock adapter", - [17] = "block port", - [18] = "unblock port", - [19] = "block unit", - [20] = "unblock unit", - [21] = "unit recovery failed", - [22] = "port recovery failed", - [23] = "adapter recovery failed", - [24] = "qdio queues down", - [25] = "p2p failed", - [26] = "nameserver lookup failed", - [27] = "nameserver port failed", - [28] = "link up", - [29] = "link down", - [30] = "link up status read", - [31] = "open port failed", - [32] = "", - [33] = "close port", - [34] = "open unit failed", - [35] = "exclusive open unit failed", - [36] = "shared open unit failed", - [37] = "link down", - [38] = "link down status read no link", - [39] = "link down status read fdisc login", - [40] = "link down status read firmware update", - [41] = "link down status read unknown reason", - [42] = "link down ecd incomplete", - [43] = "link down epd incomplete", - [44] = "sysfs adapter recovery", - [45] = "sysfs port recovery", - [46] = "sysfs unit recovery", - [47] = "port boxed abort", - [48] = "unit boxed abort", - [49] = "port boxed ct", - [50] = "port boxed close physical", - [51] = "port boxed open unit", - [52] = "port boxed close unit", - [53] = "port boxed fcp", - [54] = "unit boxed fcp", - [55] = "port access denied", - [56] = "", - [57] = "", - [58] = "", - [59] = "unit access denied", - [60] = "shared unit access denied open unit", - [61] = "", - [62] = "request timeout", - [63] = "adisc link test reject or timeout", - [64] = "adisc link test d_id changed", - [65] = "adisc link test failed", - [66] = "recovery out of memory", - [67] = "adapter recovery repeated after state change", - [68] = "port recovery repeated after state change", - [69] = "unit recovery repeated after state change", - [70] = "port recovery follow-up after successful adapter recovery", - [71] = "adapter recovery escalation after failed adapter recovery", - [72] = "port recovery follow-up after successful physical port " - "recovery", - [73] = "adapter recovery escalation after failed physical port " - "recovery", - [74] = "unit recovery follow-up after successful port recovery", - [75] = "physical port recovery escalation after failed port " - "recovery", - [76] = "port recovery escalation after failed unit recovery", - [77] = "", - [78] = "duplicate request id", - [79] = "link down", - [80] = "exclusive read-only unit access unsupported", - [81] = "shared read-write unit access unsupported", - [82] = "incoming rscn", - [83] = "incoming wwpn", - [84] = "wka port handle not valid close port", - [85] = "online", - [86] = "offline", - [87] = "ccw device gone", - [88] = "ccw device no path", - [89] = "ccw device operational", - [90] = "ccw device shutdown", - [91] = "sysfs port addition", - [92] = "sysfs port removal", - [93] = "sysfs adapter recovery", - [94] = "sysfs unit addition", - [95] = "sysfs unit removal", - [96] = "sysfs port recovery", - [97] = "sysfs unit recovery", - [98] = "sequence number mismatch", - [99] = "link up", - [100] = "error state", - [101] = "status read physical port closed", - [102] = "link up status read", - [103] = "too many failed status read buffers", - [104] = "port handle not valid abort", - [105] = "lun handle not valid abort", - [106] = "port handle not valid ct", - [107] = "port handle not valid close port", - [108] = "port handle not valid close physical port", - [109] = "port handle not valid open unit", - [110] = "port handle not valid close unit", - [111] = "lun handle not valid close unit", - [112] = "port handle not valid fcp", - [113] = "lun handle not valid fcp", - [114] = "handle mismatch fcp", - [115] = "lun not valid fcp", - [116] = "qdio send failed", - [117] = "version mismatch", - [118] = "incompatible qtcb type", - [119] = "unknown protocol status", - [120] = "unknown fsf command", - [121] = "no recommendation for status qualifier", - [122] = "", - [123] = "fc service class not supported", - [124] = "", - [125] = "need newer zfcp", - [126] = "need newer microcode", - [127] = "arbitrated loop not supported", - [128] = "", - [129] = "qtcb size mismatch", - [130] = "unknown fsf status ecd", - [131] = "fcp request too big", - [132] = "", - [133] = "data direction not valid fcp", - [134] = "command length not valid fcp", - [135] = "status read act update", - [136] = "status read cfdc update", - [137] = "hbaapi port open", - [138] = "hbaapi unit open", - [139] = "hbaapi unit shutdown", - [140] = "qdio error outbound", - [141] = "scsi host reset", - [142] = "dismissing fsf request for recovery action", - [143] = "recovery action timed out", - [144] = "recovery action gone", - [145] = "recovery action being processed", - [146] = "recovery action ready for next step", - [147] = "qdio error inbound", - [148] = "nameserver needed for port scan", - [149] = "port scan", - [150] = "ptp attach", - [151] = "port validation failed", -}; - static int zfcp_rec_dbf_view_format(debug_info_t *id, struct debug_view *view, char *buf, const char *_rec) { struct zfcp_rec_dbf_record *r = (struct zfcp_rec_dbf_record *)_rec; char *p = buf; + char hint[ZFCP_DBF_ID_SIZE + 1]; + memcpy(hint, r->id2, ZFCP_DBF_ID_SIZE); + hint[ZFCP_DBF_ID_SIZE] = 0; zfcp_dbf_outs(&p, "tag", zfcp_rec_dbf_tags[r->id]); - zfcp_dbf_outs(&p, "hint", zfcp_rec_dbf_ids[r->id2]); - zfcp_dbf_out(&p, "id", "%d", r->id2); + zfcp_dbf_outs(&p, "hint", hint); switch (r->id) { case ZFCP_REC_DBF_ID_THREAD: zfcp_dbf_out(&p, "total", "%d", r->u.thread.total); @@ -707,7 +552,7 @@ static struct debug_view zfcp_rec_dbf_view = { * @adapter: adapter * This function assumes that the caller is holding erp_lock. */ -void zfcp_rec_dbf_event_thread(u8 id2, struct zfcp_adapter *adapter) +void zfcp_rec_dbf_event_thread(char *id2, struct zfcp_adapter *adapter) { struct zfcp_rec_dbf_record *r = &adapter->rec_dbf_buf; unsigned long flags = 0; @@ -723,7 +568,7 @@ void zfcp_rec_dbf_event_thread(u8 id2, struct zfcp_adapter *adapter) spin_lock_irqsave(&adapter->rec_dbf_lock, flags); memset(r, 0, sizeof(*r)); r->id = ZFCP_REC_DBF_ID_THREAD; - r->id2 = id2; + memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE); r->u.thread.total = total; r->u.thread.ready = ready; r->u.thread.running = running; @@ -737,7 +582,7 @@ void zfcp_rec_dbf_event_thread(u8 id2, struct zfcp_adapter *adapter) * @adapter: adapter * This function assumes that the caller does not hold erp_lock. */ -void zfcp_rec_dbf_event_thread_lock(u8 id2, struct zfcp_adapter *adapter) +void zfcp_rec_dbf_event_thread_lock(char *id2, struct zfcp_adapter *adapter) { unsigned long flags; @@ -746,7 +591,7 @@ void zfcp_rec_dbf_event_thread_lock(u8 id2, struct zfcp_adapter *adapter) read_unlock_irqrestore(&adapter->erp_lock, flags); } -static void zfcp_rec_dbf_event_target(u8 id2, void *ref, +static void zfcp_rec_dbf_event_target(char *id2, void *ref, struct zfcp_adapter *adapter, atomic_t *status, atomic_t *erp_count, u64 wwpn, u32 d_id, u64 fcp_lun) @@ -757,7 +602,7 @@ static void zfcp_rec_dbf_event_target(u8 id2, void *ref, spin_lock_irqsave(&adapter->rec_dbf_lock, flags); memset(r, 0, sizeof(*r)); r->id = ZFCP_REC_DBF_ID_TARGET; - r->id2 = id2; + memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE); r->u.target.ref = (unsigned long)ref; r->u.target.status = atomic_read(status); r->u.target.wwpn = wwpn; @@ -774,7 +619,8 @@ static void zfcp_rec_dbf_event_target(u8 id2, void *ref, * @ref: additional reference (e.g. request) * @adapter: adapter */ -void zfcp_rec_dbf_event_adapter(u8 id, void *ref, struct zfcp_adapter *adapter) +void zfcp_rec_dbf_event_adapter(char *id, void *ref, + struct zfcp_adapter *adapter) { zfcp_rec_dbf_event_target(id, ref, adapter, &adapter->status, &adapter->erp_counter, 0, 0, 0); @@ -786,7 +632,7 @@ void zfcp_rec_dbf_event_adapter(u8 id, void *ref, struct zfcp_adapter *adapter) * @ref: additional reference (e.g. request) * @port: port */ -void zfcp_rec_dbf_event_port(u8 id, void *ref, struct zfcp_port *port) +void zfcp_rec_dbf_event_port(char *id, void *ref, struct zfcp_port *port) { struct zfcp_adapter *adapter = port->adapter; @@ -801,7 +647,7 @@ void zfcp_rec_dbf_event_port(u8 id, void *ref, struct zfcp_port *port) * @ref: additional reference (e.g. request) * @unit: unit */ -void zfcp_rec_dbf_event_unit(u8 id, void *ref, struct zfcp_unit *unit) +void zfcp_rec_dbf_event_unit(char *id, void *ref, struct zfcp_unit *unit) { struct zfcp_port *port = unit->port; struct zfcp_adapter *adapter = port->adapter; @@ -822,7 +668,7 @@ void zfcp_rec_dbf_event_unit(u8 id, void *ref, struct zfcp_unit *unit) * @port: port * @unit: unit */ -void zfcp_rec_dbf_event_trigger(u8 id2, void *ref, u8 want, u8 need, +void zfcp_rec_dbf_event_trigger(char *id2, void *ref, u8 want, u8 need, void *action, struct zfcp_adapter *adapter, struct zfcp_port *port, struct zfcp_unit *unit) { @@ -832,7 +678,7 @@ void zfcp_rec_dbf_event_trigger(u8 id2, void *ref, u8 want, u8 need, spin_lock_irqsave(&adapter->rec_dbf_lock, flags); memset(r, 0, sizeof(*r)); r->id = ZFCP_REC_DBF_ID_TRIGGER; - r->id2 = id2; + memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE); r->u.trigger.ref = (unsigned long)ref; r->u.trigger.want = want; r->u.trigger.need = need; @@ -855,7 +701,7 @@ void zfcp_rec_dbf_event_trigger(u8 id2, void *ref, u8 want, u8 need, * @id2: identifier * @erp_action: error recovery action struct pointer */ -void zfcp_rec_dbf_event_action(u8 id2, struct zfcp_erp_action *erp_action) +void zfcp_rec_dbf_event_action(char *id2, struct zfcp_erp_action *erp_action) { struct zfcp_adapter *adapter = erp_action->adapter; struct zfcp_rec_dbf_record *r = &adapter->rec_dbf_buf; @@ -864,7 +710,7 @@ void zfcp_rec_dbf_event_action(u8 id2, struct zfcp_erp_action *erp_action) spin_lock_irqsave(&adapter->rec_dbf_lock, flags); memset(r, 0, sizeof(*r)); r->id = ZFCP_REC_DBF_ID_ACTION; - r->id2 = id2; + memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE); r->u.action.action = (unsigned long)erp_action; r->u.action.status = erp_action->status; r->u.action.step = erp_action->step; diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h index 74998ff88e5..a573f7344dd 100644 --- a/drivers/s390/scsi/zfcp_dbf.h +++ b/drivers/s390/scsi/zfcp_dbf.h @@ -25,6 +25,7 @@ #include "zfcp_fsf.h" #define ZFCP_DBF_TAG_SIZE 4 +#define ZFCP_DBF_ID_SIZE 7 struct zfcp_dbf_dump { u8 tag[ZFCP_DBF_TAG_SIZE]; @@ -70,7 +71,7 @@ struct zfcp_rec_dbf_record_action { struct zfcp_rec_dbf_record { u8 id; - u8 id2; + char id2[7]; union { struct zfcp_rec_dbf_record_action action; struct zfcp_rec_dbf_record_thread thread; diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 28c7185f24b..65addf6a91e 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -55,7 +55,7 @@ enum zfcp_erp_act_result { static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int mask) { - zfcp_erp_modify_adapter_status(adapter, 15, NULL, + zfcp_erp_modify_adapter_status(adapter, "erablk1", NULL, ZFCP_STATUS_COMMON_UNBLOCKED | mask, ZFCP_CLEAR); } @@ -75,9 +75,9 @@ static void zfcp_erp_action_ready(struct zfcp_erp_action *act) struct zfcp_adapter *adapter = act->adapter; list_move(&act->list, &act->adapter->erp_ready_head); - zfcp_rec_dbf_event_action(146, act); + zfcp_rec_dbf_event_action("erardy1", act); up(&adapter->erp_ready_sem); - zfcp_rec_dbf_event_thread(2, adapter); + zfcp_rec_dbf_event_thread("erardy2", adapter); } static void zfcp_erp_action_dismiss(struct zfcp_erp_action *act) @@ -208,7 +208,7 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, struct zfcp_port *port, - struct zfcp_unit *unit, u8 id, void *ref) + struct zfcp_unit *unit, char *id, void *ref) { int retval = 1, need; struct zfcp_erp_action *act = NULL; @@ -228,7 +228,7 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, ++adapter->erp_total_count; list_add_tail(&act->list, &adapter->erp_ready_head); up(&adapter->erp_ready_sem); - zfcp_rec_dbf_event_thread(1, adapter); + zfcp_rec_dbf_event_thread("eracte1", adapter); retval = 0; out: zfcp_rec_dbf_event_trigger(id, ref, want, need, act, @@ -237,13 +237,13 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, } static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, - int clear_mask, u8 id, void *ref) + int clear_mask, char *id, void *ref) { zfcp_erp_adapter_block(adapter, clear_mask); /* ensure propagation of failed status to new devices */ if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { - zfcp_erp_adapter_failed(adapter, 13, NULL); + zfcp_erp_adapter_failed(adapter, "erareo1", NULL); return -EIO; } return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, @@ -258,7 +258,7 @@ static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, * @ref: Reference for debug trace event. */ void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, - u8 id, void *ref) + char *id, void *ref) { unsigned long flags; @@ -277,7 +277,7 @@ void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, * @ref: Reference for debug trace event. */ void zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear, - u8 id, void *ref) + char *id, void *ref) { int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; zfcp_erp_adapter_reopen(adapter, clear | flags, id, ref); @@ -290,7 +290,8 @@ void zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear, * @id: Id for debug trace event. * @ref: Reference for debug trace event. */ -void zfcp_erp_port_shutdown(struct zfcp_port *port, int clear, u8 id, void *ref) +void zfcp_erp_port_shutdown(struct zfcp_port *port, int clear, char *id, + void *ref) { int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; zfcp_erp_port_reopen(port, clear | flags, id, ref); @@ -303,7 +304,8 @@ void zfcp_erp_port_shutdown(struct zfcp_port *port, int clear, u8 id, void *ref) * @id: Id for debug trace event. * @ref: Reference for debug trace event. */ -void zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear, u8 id, void *ref) +void zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear, char *id, + void *ref) { int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; zfcp_erp_unit_reopen(unit, clear | flags, id, ref); @@ -311,13 +313,13 @@ void zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear, u8 id, void *ref) static void zfcp_erp_port_block(struct zfcp_port *port, int clear) { - zfcp_erp_modify_port_status(port, 17, NULL, + zfcp_erp_modify_port_status(port, "erpblk1", NULL, ZFCP_STATUS_COMMON_UNBLOCKED | clear, ZFCP_CLEAR); } static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, - int clear, u8 id, void *ref) + int clear, char *id, void *ref) { zfcp_erp_port_block(port, clear); @@ -334,7 +336,7 @@ static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, * @id: Id for debug trace event. * @ref: Reference for debug trace event. */ -void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, u8 id, +void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, char *id, void *ref) { unsigned long flags; @@ -347,14 +349,14 @@ void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, u8 id, read_unlock_irqrestore(&zfcp_data.config_lock, flags); } -static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, u8 id, +static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, void *ref) { zfcp_erp_port_block(port, clear); if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { /* ensure propagation of failed status to new devices */ - zfcp_erp_port_failed(port, 14, NULL); + zfcp_erp_port_failed(port, "erpreo1", NULL); return -EIO; } @@ -369,7 +371,7 @@ static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, u8 id, * * Returns 0 if recovery has been triggered, < 0 if not. */ -int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, u8 id, void *ref) +int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, void *ref) { unsigned long flags; int retval; @@ -386,12 +388,12 @@ int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, u8 id, void *ref) static void zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask) { - zfcp_erp_modify_unit_status(unit, 19, NULL, + zfcp_erp_modify_unit_status(unit, "erublk1", NULL, ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask, ZFCP_CLEAR); } -static void _zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, u8 id, +static void _zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, char *id, void *ref) { struct zfcp_adapter *adapter = unit->port->adapter; @@ -411,7 +413,8 @@ static void _zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, u8 id, * @clear_mask: specifies flags in unit status to be cleared * Return: 0 on success, < 0 on error */ -void zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, u8 id, void *ref) +void zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, char *id, + void *ref) { unsigned long flags; struct zfcp_port *port = unit->port; @@ -437,28 +440,28 @@ static int status_change_clear(unsigned long mask, atomic_t *status) static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter) { if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status)) - zfcp_rec_dbf_event_adapter(16, NULL, adapter); + zfcp_rec_dbf_event_adapter("eraubl1", NULL, adapter); atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status); } static void zfcp_erp_port_unblock(struct zfcp_port *port) { if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status)) - zfcp_rec_dbf_event_port(18, NULL, port); + zfcp_rec_dbf_event_port("erpubl1", NULL, port); atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status); } static void zfcp_erp_unit_unblock(struct zfcp_unit *unit) { if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status)) - zfcp_rec_dbf_event_unit(20, NULL, unit); + zfcp_rec_dbf_event_unit("eruubl1", NULL, unit); atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status); } static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) { list_move(&erp_action->list, &erp_action->adapter->erp_running_head); - zfcp_rec_dbf_event_action(145, erp_action); + zfcp_rec_dbf_event_action("erator1", erp_action); } static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act) @@ -474,11 +477,11 @@ static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act) if (act->status & (ZFCP_STATUS_ERP_DISMISSED | ZFCP_STATUS_ERP_TIMEDOUT)) { act->fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; - zfcp_rec_dbf_event_action(142, act); + zfcp_rec_dbf_event_action("erscf_1", act); act->fsf_req->erp_action = NULL; } if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) - zfcp_rec_dbf_event_action(143, act); + zfcp_rec_dbf_event_action("erscf_2", act); if (act->fsf_req->status & (ZFCP_STATUS_FSFREQ_COMPLETED | ZFCP_STATUS_FSFREQ_DISMISSED)) act->fsf_req = NULL; @@ -530,7 +533,7 @@ static void zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action) } static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, - int clear, u8 id, void *ref) + int clear, char *id, void *ref) { struct zfcp_port *port; @@ -538,8 +541,8 @@ static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, _zfcp_erp_port_reopen(port, clear, id, ref); } -static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear, u8 id, - void *ref) +static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear, + char *id, void *ref) { struct zfcp_unit *unit; @@ -559,28 +562,28 @@ static void zfcp_erp_strategy_followup_actions(struct zfcp_erp_action *act) case ZFCP_ERP_ACTION_REOPEN_ADAPTER: if (status == ZFCP_ERP_SUCCEEDED) - _zfcp_erp_port_reopen_all(adapter, 0, 70, NULL); + _zfcp_erp_port_reopen_all(adapter, 0, "ersfa_1", NULL); else - _zfcp_erp_adapter_reopen(adapter, 0, 71, NULL); + _zfcp_erp_adapter_reopen(adapter, 0, "ersfa_2", NULL); break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: if (status == ZFCP_ERP_SUCCEEDED) - _zfcp_erp_port_reopen(port, 0, 72, NULL); + _zfcp_erp_port_reopen(port, 0, "ersfa_3", NULL); else - _zfcp_erp_adapter_reopen(adapter, 0, 73, NULL); + _zfcp_erp_adapter_reopen(adapter, 0, "ersfa_4", NULL); break; case ZFCP_ERP_ACTION_REOPEN_PORT: if (status == ZFCP_ERP_SUCCEEDED) - _zfcp_erp_unit_reopen_all(port, 0, 74, NULL); + _zfcp_erp_unit_reopen_all(port, 0, "ersfa_5", NULL); else - _zfcp_erp_port_forced_reopen(port, 0, 75, NULL); + _zfcp_erp_port_forced_reopen(port, 0, "ersfa_6", NULL); break; case ZFCP_ERP_ACTION_REOPEN_UNIT: if (status != ZFCP_ERP_SUCCEEDED) - _zfcp_erp_port_reopen(unit->port, 0, 76, NULL); + _zfcp_erp_port_reopen(unit->port, 0, "ersfa_7", NULL); break; } } @@ -617,7 +620,7 @@ static void zfcp_erp_enqueue_ptp_port(struct zfcp_adapter *adapter) adapter->peer_d_id); if (IS_ERR(port)) /* error or port already attached */ return; - _zfcp_erp_port_reopen(port, 0, 150, NULL); + _zfcp_erp_port_reopen(port, 0, "ereptp1", NULL); } static int zfcp_erp_adapter_strat_fsf_xconf(struct zfcp_erp_action *erp_action) @@ -640,9 +643,9 @@ static int zfcp_erp_adapter_strat_fsf_xconf(struct zfcp_erp_action *erp_action) return ZFCP_ERP_FAILED; } - zfcp_rec_dbf_event_thread_lock(6, adapter); + zfcp_rec_dbf_event_thread_lock("erasfx1", adapter); down(&adapter->erp_ready_sem); - zfcp_rec_dbf_event_thread_lock(7, adapter); + zfcp_rec_dbf_event_thread_lock("erasfx2", adapter); if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) break; @@ -681,9 +684,9 @@ static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *act) if (ret) return ZFCP_ERP_FAILED; - zfcp_rec_dbf_event_thread_lock(8, adapter); + zfcp_rec_dbf_event_thread_lock("erasox1", adapter); down(&adapter->erp_ready_sem); - zfcp_rec_dbf_event_thread_lock(9, adapter); + zfcp_rec_dbf_event_thread_lock("erasox2", adapter); if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) return ZFCP_ERP_FAILED; @@ -714,7 +717,7 @@ static void zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *act) zfcp_fsf_req_dismiss_all(adapter); adapter->fsf_req_seq_no = 0; /* all ports and units are closed */ - zfcp_erp_modify_adapter_status(adapter, 24, NULL, + zfcp_erp_modify_adapter_status(adapter, "erascl1", NULL, ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR); atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | @@ -832,7 +835,7 @@ static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act) struct zfcp_port *port = act->port; if (port->wwpn != adapter->peer_wwpn) { - zfcp_erp_port_failed(port, 25, NULL); + zfcp_erp_port_failed(port, "eroptp1", NULL); return ZFCP_ERP_FAILED; } port->d_id = adapter->peer_d_id; @@ -986,7 +989,7 @@ static int zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result) "port 0x%016Lx\n", (unsigned long long)unit->fcp_lun, (unsigned long long)unit->port->wwpn); - zfcp_erp_unit_failed(unit, 21, NULL); + zfcp_erp_unit_failed(unit, "erusck1", NULL); } break; } @@ -1016,7 +1019,7 @@ static int zfcp_erp_strategy_check_port(struct zfcp_port *port, int result) dev_err(&port->adapter->ccw_device->dev, "ERP failed for remote port 0x%016Lx\n", (unsigned long long)port->wwpn); - zfcp_erp_port_failed(port, 22, NULL); + zfcp_erp_port_failed(port, "erpsck1", NULL); } break; } @@ -1043,7 +1046,7 @@ static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, dev_err(&adapter->ccw_device->dev, "ERP cannot recover an error " "on the FCP device\n"); - zfcp_erp_adapter_failed(adapter, 23, NULL); + zfcp_erp_adapter_failed(adapter, "erasck1", NULL); } break; } @@ -1108,7 +1111,7 @@ static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret) if (zfcp_erp_strat_change_det(&adapter->status, erp_status)) { _zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, - 67, NULL); + "ersscg1", NULL); return ZFCP_ERP_EXIT; } break; @@ -1118,7 +1121,7 @@ static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret) if (zfcp_erp_strat_change_det(&port->status, erp_status)) { _zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, - 68, NULL); + "ersscg2", NULL); return ZFCP_ERP_EXIT; } break; @@ -1127,7 +1130,7 @@ static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret) if (zfcp_erp_strat_change_det(&unit->status, erp_status)) { _zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, - 69, NULL); + "ersscg3", NULL); return ZFCP_ERP_EXIT; } break; @@ -1146,7 +1149,7 @@ static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) } list_del(&erp_action->list); - zfcp_rec_dbf_event_action(144, erp_action); + zfcp_rec_dbf_event_action("eractd1", erp_action); switch (erp_action->action) { case ZFCP_ERP_ACTION_REOPEN_UNIT: @@ -1331,7 +1334,7 @@ static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action) erp_action->status |= ZFCP_STATUS_ERP_LOWMEM; } if (adapter->erp_total_count == adapter->erp_low_mem_count) - _zfcp_erp_adapter_reopen(adapter, 0, 66, NULL); + _zfcp_erp_adapter_reopen(adapter, 0, "erstgy1", NULL); else { zfcp_erp_strategy_memwait(erp_action); retval = ZFCP_ERP_CONTINUES; @@ -1391,9 +1394,9 @@ static int zfcp_erp_thread(void *data) zfcp_erp_wakeup(adapter); } - zfcp_rec_dbf_event_thread_lock(4, adapter); + zfcp_rec_dbf_event_thread_lock("erthrd1", adapter); ignore = down_interruptible(&adapter->erp_ready_sem); - zfcp_rec_dbf_event_thread_lock(5, adapter); + zfcp_rec_dbf_event_thread_lock("erthrd2", adapter); } atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); @@ -1438,7 +1441,7 @@ void zfcp_erp_thread_kill(struct zfcp_adapter *adapter) { atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, &adapter->status); up(&adapter->erp_ready_sem); - zfcp_rec_dbf_event_thread_lock(3, adapter); + zfcp_rec_dbf_event_thread_lock("erthrk1", adapter); wait_event(adapter->erp_thread_wqh, !(atomic_read(&adapter->status) & @@ -1454,7 +1457,7 @@ void zfcp_erp_thread_kill(struct zfcp_adapter *adapter) * @id: Event id for debug trace. * @ref: Reference for debug trace. */ -void zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, u8 id, void *ref) +void zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, char *id, void *ref) { zfcp_erp_modify_adapter_status(adapter, id, ref, ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); @@ -1466,7 +1469,7 @@ void zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, u8 id, void *ref) * @id: Event id for debug trace. * @ref: Reference for debug trace. */ -void zfcp_erp_port_failed(struct zfcp_port *port, u8 id, void *ref) +void zfcp_erp_port_failed(struct zfcp_port *port, char *id, void *ref) { zfcp_erp_modify_port_status(port, id, ref, ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); @@ -1478,7 +1481,7 @@ void zfcp_erp_port_failed(struct zfcp_port *port, u8 id, void *ref) * @id: Event id for debug trace. * @ref: Reference for debug trace. */ -void zfcp_erp_unit_failed(struct zfcp_unit *unit, u8 id, void *ref) +void zfcp_erp_unit_failed(struct zfcp_unit *unit, char *id, void *ref) { zfcp_erp_modify_unit_status(unit, id, ref, ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); @@ -1505,7 +1508,7 @@ void zfcp_erp_wait(struct zfcp_adapter *adapter) * * Changes in common status bits are propagated to attached ports and units. */ -void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, u8 id, +void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, char *id, void *ref, u32 mask, int set_or_clear) { struct zfcp_port *port; @@ -1539,7 +1542,7 @@ void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, u8 id, * * Changes in common status bits are propagated to attached units. */ -void zfcp_erp_modify_port_status(struct zfcp_port *port, u8 id, void *ref, +void zfcp_erp_modify_port_status(struct zfcp_port *port, char *id, void *ref, u32 mask, int set_or_clear) { struct zfcp_unit *unit; @@ -1571,7 +1574,7 @@ void zfcp_erp_modify_port_status(struct zfcp_port *port, u8 id, void *ref, * @mask: status bits to change * @set_or_clear: ZFCP_SET or ZFCP_CLEAR */ -void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, u8 id, void *ref, +void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, char *id, void *ref, u32 mask, int set_or_clear) { if (set_or_clear == ZFCP_SET) { @@ -1594,7 +1597,7 @@ void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, u8 id, void *ref, * @id: The debug trace id. * @id: Reference for the debug trace. */ -void zfcp_erp_port_boxed(struct zfcp_port *port, u8 id, void *ref) +void zfcp_erp_port_boxed(struct zfcp_port *port, char *id, void *ref) { unsigned long flags; @@ -1611,7 +1614,7 @@ void zfcp_erp_port_boxed(struct zfcp_port *port, u8 id, void *ref) * @id: The debug trace id. * @id: Reference for the debug trace. */ -void zfcp_erp_unit_boxed(struct zfcp_unit *unit, u8 id, void *ref) +void zfcp_erp_unit_boxed(struct zfcp_unit *unit, char *id, void *ref) { zfcp_erp_modify_unit_status(unit, id, ref, ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET); @@ -1627,7 +1630,7 @@ void zfcp_erp_unit_boxed(struct zfcp_unit *unit, u8 id, void *ref) * Since the adapter has denied access, stop using the port and the * attached units. */ -void zfcp_erp_port_access_denied(struct zfcp_port *port, u8 id, void *ref) +void zfcp_erp_port_access_denied(struct zfcp_port *port, char *id, void *ref) { unsigned long flags; @@ -1646,14 +1649,14 @@ void zfcp_erp_port_access_denied(struct zfcp_port *port, u8 id, void *ref) * * Since the adapter has denied access, stop using the unit. */ -void zfcp_erp_unit_access_denied(struct zfcp_unit *unit, u8 id, void *ref) +void zfcp_erp_unit_access_denied(struct zfcp_unit *unit, char *id, void *ref) { zfcp_erp_modify_unit_status(unit, id, ref, ZFCP_STATUS_COMMON_ERP_FAILED | ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET); } -static void zfcp_erp_unit_access_changed(struct zfcp_unit *unit, u8 id, +static void zfcp_erp_unit_access_changed(struct zfcp_unit *unit, char *id, void *ref) { int status = atomic_read(&unit->status); @@ -1664,7 +1667,7 @@ static void zfcp_erp_unit_access_changed(struct zfcp_unit *unit, u8 id, zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); } -static void zfcp_erp_port_access_changed(struct zfcp_port *port, u8 id, +static void zfcp_erp_port_access_changed(struct zfcp_port *port, char *id, void *ref) { struct zfcp_unit *unit; @@ -1686,7 +1689,7 @@ static void zfcp_erp_port_access_changed(struct zfcp_port *port, u8 id, * @id: Id for debug trace * @ref: Reference for debug trace */ -void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, u8 id, +void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, char *id, void *ref) { struct zfcp_port *port; diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index a2b4987ac65..569d2437e99 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -35,15 +35,15 @@ extern struct miscdevice zfcp_cfdc_misc; /* zfcp_dbf.c */ extern int zfcp_adapter_debug_register(struct zfcp_adapter *); extern void zfcp_adapter_debug_unregister(struct zfcp_adapter *); -extern void zfcp_rec_dbf_event_thread(u8, struct zfcp_adapter *); -extern void zfcp_rec_dbf_event_thread_lock(u8, struct zfcp_adapter *); -extern void zfcp_rec_dbf_event_adapter(u8, void *, struct zfcp_adapter *); -extern void zfcp_rec_dbf_event_port(u8, void *, struct zfcp_port *); -extern void zfcp_rec_dbf_event_unit(u8, void *, struct zfcp_unit *); -extern void zfcp_rec_dbf_event_trigger(u8, void *, u8, u8, void *, +extern void zfcp_rec_dbf_event_thread(char *, struct zfcp_adapter *); +extern void zfcp_rec_dbf_event_thread_lock(char *, struct zfcp_adapter *); +extern void zfcp_rec_dbf_event_adapter(char *, void *, struct zfcp_adapter *); +extern void zfcp_rec_dbf_event_port(char *, void *, struct zfcp_port *); +extern void zfcp_rec_dbf_event_unit(char *, void *, struct zfcp_unit *); +extern void zfcp_rec_dbf_event_trigger(char *, void *, u8, u8, void *, struct zfcp_adapter *, struct zfcp_port *, struct zfcp_unit *); -extern void zfcp_rec_dbf_event_action(u8, struct zfcp_erp_action *); +extern void zfcp_rec_dbf_event_action(char *, struct zfcp_erp_action *); extern void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *); extern void zfcp_hba_dbf_event_fsf_unsol(const char *, struct zfcp_adapter *, struct fsf_status_read_buffer *); @@ -66,31 +66,34 @@ extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *, struct scsi_cmnd *); /* zfcp_erp.c */ -extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, u8, void *, - u32, int); -extern void zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, u8, void *); -extern void zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, u8, void *); -extern void zfcp_erp_adapter_failed(struct zfcp_adapter *, u8, void *); -extern void zfcp_erp_modify_port_status(struct zfcp_port *, u8, void *, u32, +extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, char *, + void *, u32, int); +extern void zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, char *, void *); +extern void zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, char *, + void *); +extern void zfcp_erp_adapter_failed(struct zfcp_adapter *, char *, void *); +extern void zfcp_erp_modify_port_status(struct zfcp_port *, char *, void *, u32, int); -extern int zfcp_erp_port_reopen(struct zfcp_port *, int, u8, void *); -extern void zfcp_erp_port_shutdown(struct zfcp_port *, int, u8, void *); -extern void zfcp_erp_port_forced_reopen(struct zfcp_port *, int, u8, void *); -extern void zfcp_erp_port_failed(struct zfcp_port *, u8, void *); -extern void zfcp_erp_modify_unit_status(struct zfcp_unit *, u8, void *, u32, +extern int zfcp_erp_port_reopen(struct zfcp_port *, int, char *, void *); +extern void zfcp_erp_port_shutdown(struct zfcp_port *, int, char *, void *); +extern void zfcp_erp_port_forced_reopen(struct zfcp_port *, int, char *, + void *); +extern void zfcp_erp_port_failed(struct zfcp_port *, char *, void *); +extern void zfcp_erp_modify_unit_status(struct zfcp_unit *, char *, void *, u32, int); -extern void zfcp_erp_unit_reopen(struct zfcp_unit *, int, u8, void *); -extern void zfcp_erp_unit_shutdown(struct zfcp_unit *, int, u8, void *); -extern void zfcp_erp_unit_failed(struct zfcp_unit *, u8, void *); +extern void zfcp_erp_unit_reopen(struct zfcp_unit *, int, char *, void *); +extern void zfcp_erp_unit_shutdown(struct zfcp_unit *, int, char *, void *); +extern void zfcp_erp_unit_failed(struct zfcp_unit *, char *, void *); extern int zfcp_erp_thread_setup(struct zfcp_adapter *); extern void zfcp_erp_thread_kill(struct zfcp_adapter *); extern void zfcp_erp_wait(struct zfcp_adapter *); extern void zfcp_erp_notify(struct zfcp_erp_action *, unsigned long); -extern void zfcp_erp_port_boxed(struct zfcp_port *, u8, void *); -extern void zfcp_erp_unit_boxed(struct zfcp_unit *, u8, void *); -extern void zfcp_erp_port_access_denied(struct zfcp_port *, u8, void *); -extern void zfcp_erp_unit_access_denied(struct zfcp_unit *, u8, void *); -extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, u8, void *); +extern void zfcp_erp_port_boxed(struct zfcp_port *, char *, void *); +extern void zfcp_erp_unit_boxed(struct zfcp_unit *, char *, void *); +extern void zfcp_erp_port_access_denied(struct zfcp_port *, char *, void *); +extern void zfcp_erp_unit_access_denied(struct zfcp_unit *, char *, void *); +extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, char *, + void *); extern void zfcp_erp_timeout_handler(unsigned long); extern void zfcp_erp_port_strategy_open_lookup(struct work_struct *); diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 0f435ed9d1a..ec700b3c210 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -150,7 +150,7 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, /* Try to connect to unused ports anyway. */ zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, - 82, fsf_req); + "fcirsc1", fsf_req); else if ((port->d_id & range) == (elem->nport_did & range)) /* Check connection status for connected ports */ zfcp_test_link(port); @@ -196,7 +196,7 @@ static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, u64 wwpn) read_unlock_irqrestore(&zfcp_data.config_lock, flags); if (port && (port->wwpn == wwpn)) - zfcp_erp_port_forced_reopen(port, 0, 83, req); + zfcp_erp_port_forced_reopen(port, 0, "fciwwp1", req); } static void zfcp_fc_incoming_plogi(struct zfcp_fsf_req *req) @@ -374,7 +374,7 @@ static void zfcp_fc_adisc_handler(unsigned long data) if (adisc->els.status) { /* request rejected or timed out */ - zfcp_erp_port_forced_reopen(port, 0, 63, NULL); + zfcp_erp_port_forced_reopen(port, 0, "fcadh_1", NULL); goto out; } @@ -382,7 +382,7 @@ static void zfcp_fc_adisc_handler(unsigned long data) port->wwnn = ls_adisc->wwnn; if (port->wwpn != ls_adisc->wwpn) - zfcp_erp_port_reopen(port, 0, 64, NULL); + zfcp_erp_port_reopen(port, 0, "fcadh_2", NULL); out: zfcp_port_put(port); @@ -434,7 +434,7 @@ void zfcp_fc_link_test_work(struct work_struct *work) /* send of ADISC was not possible */ zfcp_port_put(port); if (retval != -EBUSY) - zfcp_erp_port_forced_reopen(port, 0, 65, NULL); + zfcp_erp_port_forced_reopen(port, 0, "fcltwk1", NULL); } /** @@ -536,7 +536,7 @@ static void zfcp_validate_port(struct zfcp_port *port) zfcp_port_put(port); return; } - zfcp_erp_port_shutdown(port, 0, 151, NULL); + zfcp_erp_port_shutdown(port, 0, "fcpval1", NULL); zfcp_erp_wait(adapter); zfcp_port_put(port); zfcp_port_dequeue(port); @@ -599,7 +599,7 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft, int max_entries) if (IS_ERR(port)) ret = PTR_ERR(port); else - zfcp_erp_port_reopen(port, 0, 149, NULL); + zfcp_erp_port_reopen(port, 0, "fcegpf1", NULL); } zfcp_erp_wait(adapter); diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 698e42214a3..b4c9ba08509 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -18,8 +18,8 @@ static void zfcp_fsf_request_timeout_handler(unsigned long data) { struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; - zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 62, - NULL); + zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, + "fsrth_1", NULL); } static void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, @@ -78,7 +78,7 @@ static void zfcp_fsf_access_denied_port(struct zfcp_fsf_req *req, (unsigned long long)port->wwpn); zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]); zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]); - zfcp_erp_port_access_denied(port, 55, req); + zfcp_erp_port_access_denied(port, "fspad_1", req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; } @@ -92,7 +92,7 @@ static void zfcp_fsf_access_denied_unit(struct zfcp_fsf_req *req, (unsigned long long)unit->port->wwpn); zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]); zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]); - zfcp_erp_unit_access_denied(unit, 59, req); + zfcp_erp_unit_access_denied(unit, "fsuad_1", req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; } @@ -100,7 +100,7 @@ static void zfcp_fsf_class_not_supp(struct zfcp_fsf_req *req) { dev_err(&req->adapter->ccw_device->dev, "FCP device not " "operational because of an unsupported FC class\n"); - zfcp_erp_adapter_shutdown(req->adapter, 0, 123, req); + zfcp_erp_adapter_shutdown(req->adapter, 0, "fscns_1", req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; } @@ -162,13 +162,13 @@ static void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req) list_for_each_entry(port, &adapter->port_list_head, list) if (port->d_id == d_id) { read_unlock_irqrestore(&zfcp_data.config_lock, flags); - zfcp_erp_port_reopen(port, 0, 101, req); + zfcp_erp_port_reopen(port, 0, "fssrpc1", req); return; } read_unlock_irqrestore(&zfcp_data.config_lock, flags); } -static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, u8 id, +static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, char *id, struct fsf_link_down_info *link_down) { struct zfcp_adapter *adapter = req->adapter; @@ -257,13 +257,13 @@ static void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req) switch (sr_buf->status_subtype) { case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK: - zfcp_fsf_link_down_info_eval(req, 38, ldi); + zfcp_fsf_link_down_info_eval(req, "fssrld1", ldi); break; case FSF_STATUS_READ_SUB_FDISC_FAILED: - zfcp_fsf_link_down_info_eval(req, 39, ldi); + zfcp_fsf_link_down_info_eval(req, "fssrld2", ldi); break; case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE: - zfcp_fsf_link_down_info_eval(req, 40, NULL); + zfcp_fsf_link_down_info_eval(req, "fssrld3", NULL); }; } @@ -303,22 +303,23 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) dev_info(&adapter->ccw_device->dev, "The local link has been restored\n"); /* All ports should be marked as ready to run again */ - zfcp_erp_modify_adapter_status(adapter, 30, NULL, + zfcp_erp_modify_adapter_status(adapter, "fssrh_1", NULL, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | ZFCP_STATUS_COMMON_ERP_FAILED, - 102, req); + "fssrh_2", req); break; case FSF_STATUS_READ_NOTIFICATION_LOST: if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_ACT_UPDATED) - zfcp_erp_adapter_access_changed(adapter, 135, req); + zfcp_erp_adapter_access_changed(adapter, "fssrh_3", + req); if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS) schedule_work(&adapter->scan_work); break; case FSF_STATUS_READ_CFDC_UPDATED: - zfcp_erp_adapter_access_changed(adapter, 136, req); + zfcp_erp_adapter_access_changed(adapter, "fssrh_4", req); break; case FSF_STATUS_READ_FEATURE_UPDATE_ALERT: adapter->adapter_features = sr_buf->payload.word[0]; @@ -347,7 +348,7 @@ static void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req) dev_err(&req->adapter->ccw_device->dev, "The FCP adapter reported a problem " "that cannot be recovered\n"); - zfcp_erp_adapter_shutdown(req->adapter, 0, 121, req); + zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfsqe1", req); break; } /* all non-return stats set FSFREQ_ERROR*/ @@ -364,7 +365,7 @@ static void zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *req) dev_err(&req->adapter->ccw_device->dev, "The FCP adapter does not recognize the command 0x%x\n", req->qtcb->header.fsf_command); - zfcp_erp_adapter_shutdown(req->adapter, 0, 120, req); + zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfse_1", req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_ADAPTER_STATUS_AVAILABLE: @@ -396,17 +397,17 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req) "QTCB version 0x%x not supported by FCP adapter " "(0x%x to 0x%x)\n", FSF_QTCB_CURRENT_VERSION, psq->word[0], psq->word[1]); - zfcp_erp_adapter_shutdown(adapter, 0, 117, req); + zfcp_erp_adapter_shutdown(adapter, 0, "fspse_1", req); break; case FSF_PROT_ERROR_STATE: case FSF_PROT_SEQ_NUMB_ERROR: - zfcp_erp_adapter_reopen(adapter, 0, 98, req); + zfcp_erp_adapter_reopen(adapter, 0, "fspse_2", req); req->status |= ZFCP_STATUS_FSFREQ_RETRY; break; case FSF_PROT_UNSUPP_QTCB_TYPE: dev_err(&adapter->ccw_device->dev, "The QTCB type is not supported by the FCP adapter\n"); - zfcp_erp_adapter_shutdown(adapter, 0, 118, req); + zfcp_erp_adapter_shutdown(adapter, 0, "fspse_3", req); break; case FSF_PROT_HOST_CONNECTION_INITIALIZING: atomic_set_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, @@ -416,27 +417,29 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req) dev_err(&adapter->ccw_device->dev, "0x%Lx is an ambiguous request identifier\n", (unsigned long long)qtcb->bottom.support.req_handle); - zfcp_erp_adapter_shutdown(adapter, 0, 78, req); + zfcp_erp_adapter_shutdown(adapter, 0, "fspse_4", req); break; case FSF_PROT_LINK_DOWN: - zfcp_fsf_link_down_info_eval(req, 37, &psq->link_down_info); + zfcp_fsf_link_down_info_eval(req, "fspse_5", + &psq->link_down_info); /* FIXME: reopening adapter now? better wait for link up */ - zfcp_erp_adapter_reopen(adapter, 0, 79, req); + zfcp_erp_adapter_reopen(adapter, 0, "fspse_6", req); break; case FSF_PROT_REEST_QUEUE: /* All ports should be marked as ready to run again */ - zfcp_erp_modify_adapter_status(adapter, 28, NULL, + zfcp_erp_modify_adapter_status(adapter, "fspse_7", NULL, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | - ZFCP_STATUS_COMMON_ERP_FAILED, 99, req); + ZFCP_STATUS_COMMON_ERP_FAILED, + "fspse_8", req); break; default: dev_err(&adapter->ccw_device->dev, "0x%x is not a valid transfer protocol status\n", qtcb->prefix.prot_status); - zfcp_erp_adapter_shutdown(adapter, 0, 119, req); + zfcp_erp_adapter_shutdown(adapter, 0, "fspse_9", req); } req->status |= ZFCP_STATUS_FSFREQ_ERROR; } @@ -522,7 +525,7 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) dev_err(&adapter->ccw_device->dev, "Unknown or unsupported arbitrated loop " "fibre channel topology detected\n"); - zfcp_erp_adapter_shutdown(adapter, 0, 127, req); + zfcp_erp_adapter_shutdown(adapter, 0, "fsece_1", req); return -EIO; } @@ -556,7 +559,7 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) "FCP adapter maximum QTCB size (%d bytes) " "is too small\n", bottom->max_qtcb_size); - zfcp_erp_adapter_shutdown(adapter, 0, 129, req); + zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh1", req); return; } atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, @@ -573,11 +576,11 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status); - zfcp_fsf_link_down_info_eval(req, 42, + zfcp_fsf_link_down_info_eval(req, "fsecdh2", &qtcb->header.fsf_status_qual.link_down_info); break; default: - zfcp_erp_adapter_shutdown(adapter, 0, 130, req); + zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh3", req); return; } @@ -593,14 +596,14 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) dev_err(&adapter->ccw_device->dev, "The FCP adapter only supports newer " "control block versions\n"); - zfcp_erp_adapter_shutdown(adapter, 0, 125, req); + zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh4", req); return; } if (FSF_QTCB_CURRENT_VERSION > bottom->high_qtcb_version) { dev_err(&adapter->ccw_device->dev, "The FCP adapter only supports older " "control block versions\n"); - zfcp_erp_adapter_shutdown(adapter, 0, 126, req); + zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh5", req); } } @@ -634,7 +637,7 @@ static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req) break; case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: zfcp_fsf_exchange_port_evaluate(req); - zfcp_fsf_link_down_info_eval(req, 43, + zfcp_fsf_link_down_info_eval(req, "fsepdh1", &qtcb->header.fsf_status_qual.link_down_info); break; } @@ -779,7 +782,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) if (zfcp_reqlist_find_safe(adapter, req)) zfcp_reqlist_remove(adapter, req); spin_unlock_irqrestore(&adapter->req_list_lock, flags); - zfcp_erp_adapter_reopen(adapter, 0, 116, req); + zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1", req); return -EIO; } @@ -859,14 +862,14 @@ static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req) switch (req->qtcb->header.fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: if (fsq->word[0] == fsq->word[1]) { - zfcp_erp_adapter_reopen(unit->port->adapter, 0, 104, - req); + zfcp_erp_adapter_reopen(unit->port->adapter, 0, + "fsafch1", req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; } break; case FSF_LUN_HANDLE_NOT_VALID: if (fsq->word[0] == fsq->word[1]) { - zfcp_erp_port_reopen(unit->port, 0, 105, req); + zfcp_erp_port_reopen(unit->port, 0, "fsafch2", req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; } break; @@ -874,12 +877,12 @@ static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req) req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED; break; case FSF_PORT_BOXED: - zfcp_erp_port_boxed(unit->port, 47, req); + zfcp_erp_port_boxed(unit->port, "fsafch3", req); req->status |= ZFCP_STATUS_FSFREQ_ERROR | ZFCP_STATUS_FSFREQ_RETRY; break; case FSF_LUN_BOXED: - zfcp_erp_unit_boxed(unit, 48, req); + zfcp_erp_unit_boxed(unit, "fsafch4", req); req->status |= ZFCP_STATUS_FSFREQ_ERROR | ZFCP_STATUS_FSFREQ_RETRY; break; @@ -982,7 +985,7 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req) ZFCP_STATUS_FSFREQ_RETRY; break; case FSF_PORT_HANDLE_NOT_VALID: - zfcp_erp_adapter_reopen(adapter, 0, 106, req); + zfcp_erp_adapter_reopen(adapter, 0, "fsscth1", req); case FSF_GENERIC_COMMAND_REJECTED: case FSF_PAYLOAD_SIZE_MISMATCH: case FSF_REQUEST_SIZE_TOO_LARGE: @@ -1400,7 +1403,7 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) "Not enough FCP adapter resources to open " "remote port 0x%016Lx\n", (unsigned long long)port->wwpn); - zfcp_erp_port_failed(port, 31, req); + zfcp_erp_port_failed(port, "fsoph_1", req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_ADAPTER_STATUS_AVAILABLE: @@ -1506,13 +1509,13 @@ static void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req) switch (req->qtcb->header.fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: - zfcp_erp_adapter_reopen(port->adapter, 0, 107, req); + zfcp_erp_adapter_reopen(port->adapter, 0, "fscph_1", req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_ADAPTER_STATUS_AVAILABLE: break; case FSF_GOOD: - zfcp_erp_modify_port_status(port, 33, req, + zfcp_erp_modify_port_status(port, "fscph_2", req, ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR); break; @@ -1641,7 +1644,7 @@ static void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req) if (req->qtcb->header.fsf_status == FSF_PORT_HANDLE_NOT_VALID) { req->status |= ZFCP_STATUS_FSFREQ_ERROR; - zfcp_erp_adapter_reopen(wka_port->adapter, 0, 84, req); + zfcp_erp_adapter_reopen(wka_port->adapter, 0, "fscwph1", req); } wka_port->status = ZFCP_WKA_PORT_OFFLINE; @@ -1700,14 +1703,14 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req) switch (header->fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: - zfcp_erp_adapter_reopen(port->adapter, 0, 108, req); + zfcp_erp_adapter_reopen(port->adapter, 0, "fscpph1", req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_ACCESS_DENIED: zfcp_fsf_access_denied_port(req, port); break; case FSF_PORT_BOXED: - zfcp_erp_port_boxed(port, 50, req); + zfcp_erp_port_boxed(port, "fscpph2", req); req->status |= ZFCP_STATUS_FSFREQ_ERROR | ZFCP_STATUS_FSFREQ_RETRY; /* can't use generic zfcp_erp_modify_port_status because @@ -1805,7 +1808,7 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req) switch (header->fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: - zfcp_erp_adapter_reopen(unit->port->adapter, 0, 109, req); + zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fsouh_1", req); /* fall through */ case FSF_LUN_ALREADY_OPEN: break; @@ -1815,7 +1818,7 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req) atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status); break; case FSF_PORT_BOXED: - zfcp_erp_port_boxed(unit->port, 51, req); + zfcp_erp_port_boxed(unit->port, "fsouh_2", req); req->status |= ZFCP_STATUS_FSFREQ_ERROR | ZFCP_STATUS_FSFREQ_RETRY; break; @@ -1831,7 +1834,7 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req) else zfcp_act_eval_err(adapter, header->fsf_status_qual.word[2]); - zfcp_erp_unit_access_denied(unit, 60, req); + zfcp_erp_unit_access_denied(unit, "fsouh_3", req); atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status); atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status); req->status |= ZFCP_STATUS_FSFREQ_ERROR; @@ -1842,7 +1845,7 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req) "0x%016Lx on port 0x%016Lx\n", (unsigned long long)unit->fcp_lun, (unsigned long long)unit->port->wwpn); - zfcp_erp_unit_failed(unit, 34, req); + zfcp_erp_unit_failed(unit, "fsouh_4", req); /* fall through */ case FSF_INVALID_COMMAND_OPTION: req->status |= ZFCP_STATUS_FSFREQ_ERROR; @@ -1891,9 +1894,9 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req) "port 0x%016Lx)\n", (unsigned long long)unit->fcp_lun, (unsigned long long)unit->port->wwpn); - zfcp_erp_unit_failed(unit, 35, req); + zfcp_erp_unit_failed(unit, "fsouh_5", req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; - zfcp_erp_unit_shutdown(unit, 0, 80, req); + zfcp_erp_unit_shutdown(unit, 0, "fsouh_6", req); } else if (!exclusive && readwrite) { dev_err(&adapter->ccw_device->dev, "Shared read-write access not " @@ -1901,9 +1904,9 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req) "0x%016Lx)\n", (unsigned long long)unit->fcp_lun, (unsigned long long)unit->port->wwpn); - zfcp_erp_unit_failed(unit, 36, req); + zfcp_erp_unit_failed(unit, "fsouh_7", req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; - zfcp_erp_unit_shutdown(unit, 0, 81, req); + zfcp_erp_unit_shutdown(unit, 0, "fsouh_8", req); } } break; @@ -1968,15 +1971,15 @@ static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req) switch (req->qtcb->header.fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: - zfcp_erp_adapter_reopen(unit->port->adapter, 0, 110, req); + zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fscuh_1", req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_LUN_HANDLE_NOT_VALID: - zfcp_erp_port_reopen(unit->port, 0, 111, req); + zfcp_erp_port_reopen(unit->port, 0, "fscuh_2", req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_PORT_BOXED: - zfcp_erp_port_boxed(unit->port, 52, req); + zfcp_erp_port_boxed(unit->port, "fscuh_3", req); req->status |= ZFCP_STATUS_FSFREQ_ERROR | ZFCP_STATUS_FSFREQ_RETRY; break; @@ -2215,12 +2218,12 @@ static void zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *req) switch (header->fsf_status) { case FSF_HANDLE_MISMATCH: case FSF_PORT_HANDLE_NOT_VALID: - zfcp_erp_adapter_reopen(unit->port->adapter, 0, 112, req); + zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fssfch1", req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_FCPLUN_NOT_VALID: case FSF_LUN_HANDLE_NOT_VALID: - zfcp_erp_port_reopen(unit->port, 0, 113, req); + zfcp_erp_port_reopen(unit->port, 0, "fssfch2", req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_SERVICE_CLASS_NOT_SUPPORTED: @@ -2236,7 +2239,8 @@ static void zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *req) req->qtcb->bottom.io.data_direction, (unsigned long long)unit->fcp_lun, (unsigned long long)unit->port->wwpn); - zfcp_erp_adapter_shutdown(unit->port->adapter, 0, 133, req); + zfcp_erp_adapter_shutdown(unit->port->adapter, 0, "fssfch3", + req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_CMND_LENGTH_NOT_VALID: @@ -2246,16 +2250,17 @@ static void zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *req) req->qtcb->bottom.io.fcp_cmnd_length, (unsigned long long)unit->fcp_lun, (unsigned long long)unit->port->wwpn); - zfcp_erp_adapter_shutdown(unit->port->adapter, 0, 134, req); + zfcp_erp_adapter_shutdown(unit->port->adapter, 0, "fssfch4", + req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_PORT_BOXED: - zfcp_erp_port_boxed(unit->port, 53, req); + zfcp_erp_port_boxed(unit->port, "fssfch5", req); req->status |= ZFCP_STATUS_FSFREQ_ERROR | ZFCP_STATUS_FSFREQ_RETRY; break; case FSF_LUN_BOXED: - zfcp_erp_unit_boxed(unit, 54, req); + zfcp_erp_unit_boxed(unit, "fssfch6", req); req->status |= ZFCP_STATUS_FSFREQ_ERROR | ZFCP_STATUS_FSFREQ_RETRY; break; @@ -2388,7 +2393,7 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit, "on port 0x%016Lx closed\n", (unsigned long long)unit->fcp_lun, (unsigned long long)unit->port->wwpn); - zfcp_erp_unit_shutdown(unit, 0, 131, req); + zfcp_erp_unit_shutdown(unit, 0, "fssfct1", req); retval = -EINVAL; } goto failed_scsi_cmnd; diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 3d068709027..c2eb94f6370 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -58,7 +58,7 @@ void zfcp_qdio_free(struct zfcp_adapter *adapter) } } -static void zfcp_qdio_handler_error(struct zfcp_adapter *adapter, u8 id) +static void zfcp_qdio_handler_error(struct zfcp_adapter *adapter, char *id) { dev_warn(&adapter->ccw_device->dev, "A QDIO problem occurred\n"); @@ -103,7 +103,7 @@ static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err, if (unlikely(qdio_err)) { zfcp_hba_dbf_event_qdio(adapter, qdio_err, first, count); - zfcp_qdio_handler_error(adapter, 140); + zfcp_qdio_handler_error(adapter, "qdireq1"); return; } @@ -172,7 +172,7 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err, if (unlikely(qdio_err)) { zfcp_hba_dbf_event_qdio(adapter, qdio_err, first, count); - zfcp_qdio_handler_error(adapter, 147); + zfcp_qdio_handler_error(adapter, "qdires1"); return; } diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index c17505f767a..2af8cfbc389 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -28,7 +28,7 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) { struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; unit->device = NULL; - zfcp_erp_unit_failed(unit, 12, NULL); + zfcp_erp_unit_failed(unit, "scslvd1", NULL); zfcp_unit_put(unit); } @@ -257,7 +257,7 @@ static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) struct zfcp_unit *unit = scpnt->device->hostdata; struct zfcp_adapter *adapter = unit->port->adapter; - zfcp_erp_adapter_reopen(adapter, 0, 141, scpnt); + zfcp_erp_adapter_reopen(adapter, 0, "schrh_1", scpnt); zfcp_erp_wait(adapter); return SUCCESS; diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index 14e38c231f0..9a3b8e261c0 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c @@ -112,9 +112,9 @@ static ZFCP_DEV_ATTR(_feat, failed, S_IWUSR | S_IRUGO, \ zfcp_sysfs_##_feat##_failed_show, \ zfcp_sysfs_##_feat##_failed_store); -ZFCP_SYSFS_FAILED(zfcp_adapter, adapter, adapter, 44, 93); -ZFCP_SYSFS_FAILED(zfcp_port, port, port->adapter, 45, 96); -ZFCP_SYSFS_FAILED(zfcp_unit, unit, unit->port->adapter, 46, 97); +ZFCP_SYSFS_FAILED(zfcp_adapter, adapter, adapter, "syafai1", "syafai2"); +ZFCP_SYSFS_FAILED(zfcp_port, port, port->adapter, "sypfai1", "sypfai2"); +ZFCP_SYSFS_FAILED(zfcp_unit, unit, unit->port->adapter, "syufai1", "syufai2"); static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev, struct device_attribute *attr, @@ -168,7 +168,7 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, goto out; } - zfcp_erp_port_shutdown(port, 0, 92, NULL); + zfcp_erp_port_shutdown(port, 0, "syprs_1", NULL); zfcp_erp_wait(adapter); zfcp_port_put(port); zfcp_port_dequeue(port); @@ -222,7 +222,7 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev, retval = 0; - zfcp_erp_unit_reopen(unit, 0, 94, NULL); + zfcp_erp_unit_reopen(unit, 0, "syuas_1", NULL); zfcp_erp_wait(unit->port->adapter); zfcp_unit_put(unit); out: @@ -268,7 +268,7 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev, goto out; } - zfcp_erp_unit_shutdown(unit, 0, 95, NULL); + zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL); zfcp_erp_wait(unit->port->adapter); zfcp_unit_put(unit); zfcp_unit_dequeue(unit); -- GitLab From 21ddaa53f92dba820a3778978e617f20ecb6ab6f Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Mon, 2 Mar 2009 13:09:05 +0100 Subject: [PATCH 3205/4982] [SCSI] zfcp: Remove PCI flag The usage of the PCI flag to trigger interrupts is optional. Even without setting the flag, qdio still receives interrupts to continue working on the queue. Remove the PCI flag from zfcp, it is not necessary. Acked-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_def.h | 2 -- drivers/s390/scsi/zfcp_qdio.c | 23 +++-------------------- 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 8412bb992ea..22e418db451 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -443,8 +443,6 @@ struct zfcp_adapter { spinlock_t req_list_lock; /* request list lock */ struct zfcp_qdio_queue req_q; /* request queue */ spinlock_t req_q_lock; /* for operations on queue */ - int req_q_pci_batch; /* SBALs since PCI indication - was last set */ ktime_t req_q_time; /* time of last fill level change */ u64 req_q_util; /* for accounting */ spinlock_t qdio_stat_lock; diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index c2eb94f6370..e0a215309df 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -11,9 +11,6 @@ #include "zfcp_ext.h" -/* FIXME(tune): free space should be one max. SBAL chain plus what? */ -#define ZFCP_QDIO_PCI_INTERVAL (QDIO_MAX_BUFFERS_PER_Q \ - - (FSF_MAX_SBALS_PER_REQ + 4)) #define QBUFF_PER_PAGE (PAGE_SIZE / sizeof(struct qdio_buffer)) static int zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbal) @@ -364,23 +361,12 @@ int zfcp_qdio_send(struct zfcp_fsf_req *fsf_req) struct zfcp_qdio_queue *req_q = &adapter->req_q; int first = fsf_req->sbal_first; int count = fsf_req->sbal_number; - int retval, pci, pci_batch; - struct qdio_buffer_element *sbale; - - /* acknowledgements for transferred buffers */ - pci_batch = adapter->req_q_pci_batch + count; - if (unlikely(pci_batch >= ZFCP_QDIO_PCI_INTERVAL)) { - pci_batch %= ZFCP_QDIO_PCI_INTERVAL; - pci = first + count - (pci_batch + 1); - pci %= QDIO_MAX_BUFFERS_PER_Q; - sbale = zfcp_qdio_sbale(req_q, pci, 0); - sbale->flags |= SBAL_FLAGS0_PCI; - } + int retval; + unsigned int qdio_flags = QDIO_FLAG_SYNC_OUTPUT; zfcp_qdio_account(adapter); - retval = do_QDIO(adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, 0, first, - count); + retval = do_QDIO(adapter->ccw_device, qdio_flags, 0, first, count); if (unlikely(retval)) { zfcp_qdio_zero_sbals(req_q->sbal, first, count); return retval; @@ -390,7 +376,6 @@ int zfcp_qdio_send(struct zfcp_fsf_req *fsf_req) atomic_sub(count, &req_q->count); req_q->first += count; req_q->first %= QDIO_MAX_BUFFERS_PER_Q; - adapter->req_q_pci_batch = pci_batch; return 0; } @@ -461,7 +446,6 @@ void zfcp_qdio_close(struct zfcp_adapter *adapter) } req_q->first = 0; atomic_set(&req_q->count, 0); - adapter->req_q_pci_batch = 0; adapter->resp_q.first = 0; atomic_set(&adapter->resp_q.count, 0); } @@ -499,7 +483,6 @@ int zfcp_qdio_open(struct zfcp_adapter *adapter) /* set index of first avalable SBALS / number of available SBALS */ adapter->req_q.first = 0; atomic_set(&adapter->req_q.count, QDIO_MAX_BUFFERS_PER_Q); - adapter->req_q_pci_batch = 0; return 0; -- GitLab From 24095490681d130979c18685dc0b5a308057e225 Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Mon, 2 Mar 2009 13:09:07 +0100 Subject: [PATCH 3206/4982] [SCSI] zfcp: incorrect reaction on incoming RSCN After an error condition resolved a remote storage port was never re-opened. The incoming RSCN was not processed accordingly due to a misinterpreted status flag / return value combination. Signed-off-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_fc.c | 18 +++++++----------- drivers/s390/scsi/zfcp_fsf.c | 4 ---- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index ec700b3c210..49a7a90501b 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -145,16 +145,10 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, struct zfcp_port *port; read_lock_irqsave(&zfcp_data.config_lock, flags); - list_for_each_entry(port, &fsf_req->adapter->port_list_head, list) { - if (!(atomic_read(&port->status) & ZFCP_STATUS_PORT_PHYS_OPEN)) - /* Try to connect to unused ports anyway. */ - zfcp_erp_port_reopen(port, - ZFCP_STATUS_COMMON_ERP_FAILED, - "fcirsc1", fsf_req); - else if ((port->d_id & range) == (elem->nport_did & range)) - /* Check connection status for connected ports */ + list_for_each_entry(port, &fsf_req->adapter->port_list_head, list) + if ((port->d_id & range) == (elem->nport_did & range)) zfcp_test_link(port); - } + read_unlock_irqrestore(&zfcp_data.config_lock, flags); } @@ -381,8 +375,10 @@ static void zfcp_fc_adisc_handler(unsigned long data) if (!port->wwnn) port->wwnn = ls_adisc->wwnn; - if (port->wwpn != ls_adisc->wwpn) - zfcp_erp_port_reopen(port, 0, "fcadh_2", NULL); + if ((port->wwpn != ls_adisc->wwpn) || + !(atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN)) + zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, + "fcadh_2", NULL); out: zfcp_port_put(port); diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index b4c9ba08509..71c32f3ffcb 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -1161,10 +1161,6 @@ int zfcp_fsf_send_els(struct zfcp_send_els *els) struct fsf_qtcb_bottom_support *bottom; int ret = -EIO; - if (unlikely(!(atomic_read(&els->port->status) & - ZFCP_STATUS_COMMON_UNBLOCKED))) - return -EBUSY; - spin_lock_bh(&adapter->req_q_lock); if (zfcp_fsf_req_sbal_get(adapter)) goto out; -- GitLab From a2fa0aede07c9488239dcac1eae58233181c355a Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Mon, 2 Mar 2009 13:09:08 +0100 Subject: [PATCH 3207/4982] [SCSI] zfcp: Block FC transport rports early on errors Use the I/O blocking mechanism in the FC transport class to allow faster failovers for multipathing: - Call fc_remote_port_delete early to set the rport to BLOCKED. - Check the rport status in queuecommand with fc_remote_portchkready to no longer accept new I/O for this port and fail the I/O with the appropriate scsi_cmnd result. - Implement the terminate_rport_io handler to abort all pending I/O requests - Return SCSI commands with DID_TRANSPORT_DISRUPTED while erp is running. - When updating the remote port status, check for late changes and update the remote ports status accordingly. Acked-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_aux.c | 4 +- drivers/s390/scsi/zfcp_def.h | 4 +- drivers/s390/scsi/zfcp_erp.c | 56 ++++------------ drivers/s390/scsi/zfcp_ext.h | 6 +- drivers/s390/scsi/zfcp_fc.c | 21 ++++-- drivers/s390/scsi/zfcp_fsf.c | 3 +- drivers/s390/scsi/zfcp_scsi.c | 119 +++++++++++++++++++++++++++++++++- 7 files changed, 157 insertions(+), 56 deletions(-) diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 69a31187e54..b2be6593b56 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -3,7 +3,7 @@ * * Module interface and handling of zfcp data structures. * - * Copyright IBM Corporation 2002, 2008 + * Copyright IBM Corporation 2002, 2009 */ /* @@ -606,10 +606,12 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, INIT_LIST_HEAD(&port->unit_list_head); INIT_WORK(&port->gid_pn_work, zfcp_erp_port_strategy_open_lookup); INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work); + INIT_WORK(&port->rport_work, zfcp_scsi_rport_work); port->adapter = adapter; port->d_id = d_id; port->wwpn = wwpn; + port->rport_task = RPORT_NONE; /* mark port unusable as long as sysfs registration is not complete */ atomic_set_mask(status | ZFCP_STATUS_COMMON_REMOVE, &port->status); diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 22e418db451..a0318630f04 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -3,7 +3,7 @@ * * Global definitions for the zfcp device driver. * - * Copyright IBM Corporation 2002, 2008 + * Copyright IBM Corporation 2002, 2009 */ #ifndef ZFCP_DEF_H @@ -512,6 +512,8 @@ struct zfcp_port { u32 supported_classes; struct work_struct gid_pn_work; struct work_struct test_link_work; + struct work_struct rport_work; + enum { RPORT_NONE, RPORT_ADD, RPORT_DEL } rport_task; }; struct zfcp_unit { diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 65addf6a91e..dee1cc3ce21 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -3,7 +3,7 @@ * * Error Recovery Procedures (ERP). * - * Copyright IBM Corporation 2002, 2008 + * Copyright IBM Corporation 2002, 2009 */ #define KMSG_COMPONENT "zfcp" @@ -240,6 +240,7 @@ static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear_mask, char *id, void *ref) { zfcp_erp_adapter_block(adapter, clear_mask); + zfcp_scsi_schedule_rports_block(adapter); /* ensure propagation of failed status to new devices */ if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { @@ -322,6 +323,7 @@ static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, char *id, void *ref) { zfcp_erp_port_block(port, clear); + zfcp_scsi_schedule_rport_block(port); if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) return; @@ -353,6 +355,7 @@ static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, void *ref) { zfcp_erp_port_block(port, clear); + zfcp_scsi_schedule_rport_block(port); if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { /* ensure propagation of failed status to new devices */ @@ -1211,37 +1214,6 @@ static void zfcp_erp_schedule_work(struct zfcp_unit *unit) queue_work(zfcp_data.work_queue, &p->work); } -static void zfcp_erp_rport_register(struct zfcp_port *port) -{ - struct fc_rport_identifiers ids; - ids.node_name = port->wwnn; - ids.port_name = port->wwpn; - ids.port_id = port->d_id; - ids.roles = FC_RPORT_ROLE_FCP_TARGET; - port->rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids); - if (!port->rport) { - dev_err(&port->adapter->ccw_device->dev, - "Registering port 0x%016Lx failed\n", - (unsigned long long)port->wwpn); - return; - } - - scsi_target_unblock(&port->rport->dev); - port->rport->maxframe_size = port->maxframe_size; - port->rport->supported_classes = port->supported_classes; -} - -static void zfcp_erp_rports_del(struct zfcp_adapter *adapter) -{ - struct zfcp_port *port; - list_for_each_entry(port, &adapter->port_list_head, list) { - if (!port->rport) - continue; - fc_remote_port_delete(port->rport); - port->rport = NULL; - } -} - static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) { struct zfcp_adapter *adapter = act->adapter; @@ -1250,8 +1222,8 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) switch (act->action) { case ZFCP_ERP_ACTION_REOPEN_UNIT: - if ((result == ZFCP_ERP_SUCCEEDED) && - !unit->device && port->rport) { + flush_work(&port->rport_work); + if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) { if (!(atomic_read(&unit->status) & ZFCP_STATUS_UNIT_SCSI_WORK_PENDING)) zfcp_erp_schedule_work(unit); @@ -1261,23 +1233,17 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: case ZFCP_ERP_ACTION_REOPEN_PORT: - if ((result == ZFCP_ERP_SUCCEEDED) && !port->rport) - zfcp_erp_rport_register(port); - if ((result != ZFCP_ERP_SUCCEEDED) && port->rport) { - fc_remote_port_delete(port->rport); - port->rport = NULL; - } + if (result == ZFCP_ERP_SUCCEEDED) + zfcp_scsi_schedule_rport_register(port); zfcp_port_put(port); break; case ZFCP_ERP_ACTION_REOPEN_ADAPTER: - if (result != ZFCP_ERP_SUCCEEDED) { - unregister_service_level(&adapter->service_level); - zfcp_erp_rports_del(adapter); - } else { + if (result == ZFCP_ERP_SUCCEEDED) { register_service_level(&adapter->service_level); schedule_work(&adapter->scan_work); - } + } else + unregister_service_level(&adapter->service_level); zfcp_adapter_put(adapter); break; } diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 569d2437e99..f6399ca97bc 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -3,7 +3,7 @@ * * External function declarations. * - * Copyright IBM Corporation 2002, 2008 + * Copyright IBM Corporation 2002, 2009 */ #ifndef ZFCP_EXT_H @@ -154,6 +154,10 @@ extern int zfcp_adapter_scsi_register(struct zfcp_adapter *); extern void zfcp_adapter_scsi_unregister(struct zfcp_adapter *); extern char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *); extern struct fc_function_template zfcp_transport_functions; +extern void zfcp_scsi_rport_work(struct work_struct *); +extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *); +extern void zfcp_scsi_schedule_rport_block(struct zfcp_port *); +extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *); /* zfcp_sysfs.c */ extern struct attribute_group zfcp_sysfs_unit_attrs; diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 49a7a90501b..c22c4786855 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -3,7 +3,7 @@ * * Fibre Channel related functions for the zfcp device driver. * - * Copyright IBM Corporation 2008 + * Copyright IBM Corporation 2008, 2009 */ #define KMSG_COMPONENT "zfcp" @@ -376,10 +376,14 @@ static void zfcp_fc_adisc_handler(unsigned long data) port->wwnn = ls_adisc->wwnn; if ((port->wwpn != ls_adisc->wwpn) || - !(atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN)) + !(atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN)) { zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, "fcadh_2", NULL); + goto out; + } + /* port is good, unblock rport without going through erp */ + zfcp_scsi_schedule_rport_register(port); out: zfcp_port_put(port); kfree(adisc); @@ -423,14 +427,23 @@ void zfcp_fc_link_test_work(struct work_struct *work) container_of(work, struct zfcp_port, test_link_work); int retval; + if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_UNBLOCKED)) { + zfcp_port_put(port); + return; /* port erp is running and will update rport status */ + } + + zfcp_port_get(port); + port->rport_task = RPORT_DEL; + zfcp_scsi_rport_work(&port->rport_work); + retval = zfcp_fc_adisc(port); if (retval == 0) return; /* send of ADISC was not possible */ + zfcp_erp_port_forced_reopen(port, 0, "fcltwk1", NULL); + zfcp_port_put(port); - if (retval != -EBUSY) - zfcp_erp_port_forced_reopen(port, 0, "fcltwk1", NULL); } /** diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 71c32f3ffcb..9fa8c8990a1 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -3,7 +3,7 @@ * * Implementation of FSF commands. * - * Copyright IBM Corporation 2002, 2008 + * Copyright IBM Corporation 2002, 2009 */ #define KMSG_COMPONENT "zfcp" @@ -177,6 +177,7 @@ static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, char *id, return; atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status); + zfcp_scsi_schedule_rports_block(adapter); if (!link_down) goto out; diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 2af8cfbc389..7141f9a675d 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -3,7 +3,7 @@ * * Interface to Linux SCSI midlayer. * - * Copyright IBM Corporation 2002, 2008 + * Copyright IBM Corporation 2002, 2009 */ #define KMSG_COMPONENT "zfcp" @@ -57,8 +57,8 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt, { struct zfcp_unit *unit; struct zfcp_adapter *adapter; - int status; - int ret; + int status, scsi_result, ret; + struct fc_rport *rport = starget_to_rport(scsi_target(scpnt->device)); /* reset the status for this request */ scpnt->result = 0; @@ -80,6 +80,14 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt, return 0; } + scsi_result = fc_remote_port_chkready(rport); + if (unlikely(scsi_result)) { + scpnt->result = scsi_result; + zfcp_scsi_dbf_event_result("fail", 4, adapter, scpnt, NULL); + scpnt->scsi_done(scpnt); + return 0; + } + status = atomic_read(&unit->status); if (unlikely((status & ZFCP_STATUS_COMMON_ERP_FAILED) || !(status & ZFCP_STATUS_COMMON_RUNNING))) { @@ -473,6 +481,109 @@ static void zfcp_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout) rport->dev_loss_tmo = timeout; } +/** + * zfcp_scsi_dev_loss_tmo_callbk - Free any reference to rport + * @rport: The rport that is about to be deleted. + */ +static void zfcp_scsi_dev_loss_tmo_callbk(struct fc_rport *rport) +{ + struct zfcp_port *port = rport->dd_data; + + write_lock_irq(&zfcp_data.config_lock); + port->rport = NULL; + write_unlock_irq(&zfcp_data.config_lock); +} + +/** + * zfcp_scsi_terminate_rport_io - Terminate all I/O on a rport + * @rport: The FC rport where to teminate I/O + * + * Abort all pending SCSI commands for a port by closing the + * port. Using a reopen for avoids a conflict with a shutdown + * overwriting a reopen. + */ +static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport) +{ + struct zfcp_port *port = rport->dd_data; + + zfcp_erp_port_reopen(port, 0, "sctrpi1", NULL); +} + +static void zfcp_scsi_rport_register(struct zfcp_port *port) +{ + struct fc_rport_identifiers ids; + struct fc_rport *rport; + + ids.node_name = port->wwnn; + ids.port_name = port->wwpn; + ids.port_id = port->d_id; + ids.roles = FC_RPORT_ROLE_FCP_TARGET; + + rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids); + if (!rport) { + dev_err(&port->adapter->ccw_device->dev, + "Registering port 0x%016Lx failed\n", + (unsigned long long)port->wwpn); + return; + } + + rport->dd_data = port; + rport->maxframe_size = port->maxframe_size; + rport->supported_classes = port->supported_classes; + port->rport = rport; +} + +static void zfcp_scsi_rport_block(struct zfcp_port *port) +{ + if (port->rport) + fc_remote_port_delete(port->rport); +} + +void zfcp_scsi_schedule_rport_register(struct zfcp_port *port) +{ + zfcp_port_get(port); + port->rport_task = RPORT_ADD; + + if (!queue_work(zfcp_data.work_queue, &port->rport_work)) + zfcp_port_put(port); +} + +void zfcp_scsi_schedule_rport_block(struct zfcp_port *port) +{ + zfcp_port_get(port); + port->rport_task = RPORT_DEL; + + if (!queue_work(zfcp_data.work_queue, &port->rport_work)) + zfcp_port_put(port); +} + +void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *adapter) +{ + struct zfcp_port *port; + + list_for_each_entry(port, &adapter->port_list_head, list) + zfcp_scsi_schedule_rport_block(port); +} + +void zfcp_scsi_rport_work(struct work_struct *work) +{ + struct zfcp_port *port = container_of(work, struct zfcp_port, + rport_work); + + while (port->rport_task) { + if (port->rport_task == RPORT_ADD) { + port->rport_task = RPORT_NONE; + zfcp_scsi_rport_register(port); + } else { + port->rport_task = RPORT_NONE; + zfcp_scsi_rport_block(port); + } + } + + zfcp_port_put(port); +} + + struct fc_function_template zfcp_transport_functions = { .show_starget_port_id = 1, .show_starget_port_name = 1, @@ -491,6 +602,8 @@ struct fc_function_template zfcp_transport_functions = { .reset_fc_host_stats = zfcp_reset_fc_host_stats, .set_rport_dev_loss_tmo = zfcp_set_rport_dev_loss_tmo, .get_host_port_state = zfcp_get_host_port_state, + .dev_loss_tmo_callbk = zfcp_scsi_dev_loss_tmo_callbk, + .terminate_rport_io = zfcp_scsi_terminate_rport_io, .show_host_port_state = 1, /* no functions registered for following dynamic attributes but directly set by LLDD */ -- GitLab From 2cb5b2ca6dddcdfb0e220f18b4612890a23a1c92 Mon Sep 17 00:00:00 2001 From: Martin Petermann Date: Mon, 2 Mar 2009 13:09:09 +0100 Subject: [PATCH 3208/4982] [SCSI] zfcp: erp failed status bit will not be set It will not be necessary to set the erp failed status bit in case a SCSI device is removed by the SCSI mid layer. In the case a SCSI device is unavailable for a short time (15 to 20 seconds) a FCP unit will not get on-line again. Signed-off-by: Martin Petermann Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_scsi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 7141f9a675d..58201e1ae47 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -28,7 +28,6 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) { struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; unit->device = NULL; - zfcp_erp_unit_failed(unit, "scslvd1", NULL); zfcp_unit_put(unit); } -- GitLab From 947a9aca86eb2a921ed7aa92397cf7f38b896f90 Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Mon, 2 Mar 2009 13:09:10 +0100 Subject: [PATCH 3209/4982] [SCSI] zfcp: fix queue, scheduled work processing. Ensure the refcounting is correct even if we were not able to schedule a work. In addition we have to make sure no scheduled work is pending while we're dequeing the adapter from the systems environment. Signed-off-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_aux.c | 1 + drivers/s390/scsi/zfcp_erp.c | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index b2be6593b56..c4d07be6279 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -554,6 +554,7 @@ void zfcp_adapter_dequeue(struct zfcp_adapter *adapter) cancel_work_sync(&adapter->scan_work); cancel_work_sync(&adapter->stat_work); + cancel_delayed_work_sync(&adapter->nsp.work); zfcp_adapter_scsi_unregister(adapter); sysfs_remove_group(&adapter->ccw_device->dev.kobj, &zfcp_sysfs_adapter_attrs); diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index dee1cc3ce21..631bdb1dfd6 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -857,7 +857,7 @@ void zfcp_erp_port_strategy_open_lookup(struct work_struct *work) port->erp_action.step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP; if (retval) zfcp_erp_notify(&port->erp_action, ZFCP_ERP_FAILED); - + zfcp_port_put(port); } static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) @@ -873,7 +873,10 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) return zfcp_erp_open_ptp_port(act); if (!port->d_id) { - queue_work(zfcp_data.work_queue, &port->gid_pn_work); + zfcp_port_get(port); + if (!queue_work(zfcp_data.work_queue, + &port->gid_pn_work)) + zfcp_port_put(port); return ZFCP_ERP_CONTINUES; } case ZFCP_ERP_STEP_NAMESERVER_LOOKUP: @@ -1211,7 +1214,8 @@ static void zfcp_erp_schedule_work(struct zfcp_unit *unit) atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); INIT_WORK(&p->work, zfcp_erp_scsi_scan); p->unit = unit; - queue_work(zfcp_data.work_queue, &p->work); + if (!queue_work(zfcp_data.work_queue, &p->work)) + zfcp_unit_put(unit); } static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) -- GitLab From 6d1a27f630f1d30bf85c61ec0436c287d0945fcc Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Mon, 2 Mar 2009 13:09:11 +0100 Subject: [PATCH 3210/4982] [SCSI] zfcp: Ensure all work is cancelled on adapter dequeue A scheduled work might still be pending, running while the adapter is in progress to get dequeued from the system. This can lead to an invalid pointer dereference (Oops). Once the adpater is set online again, ensure the nameserver environment is initialized to the appropriate values again. Signed-off-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_aux.c | 1 - drivers/s390/scsi/zfcp_ccw.c | 3 ++- drivers/s390/scsi/zfcp_fc.c | 8 ++++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index c4d07be6279..616c60ffcf2 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -524,7 +524,6 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device) goto sysfs_failed; atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); - zfcp_fc_nameserver_init(adapter); if (!zfcp_adapter_scsi_register(adapter)) return 0; diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 3aeef289fe7..1fe1e2eda51 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -3,7 +3,7 @@ * * Registration and callback for the s390 common I/O layer. * - * Copyright IBM Corporation 2002, 2008 + * Copyright IBM Corporation 2002, 2009 */ #define KMSG_COMPONENT "zfcp" @@ -108,6 +108,7 @@ static int zfcp_ccw_set_online(struct ccw_device *ccw_device) /* initialize request counter */ BUG_ON(!zfcp_reqlist_isempty(adapter)); adapter->req_no = 0; + zfcp_fc_nameserver_init(adapter); zfcp_erp_modify_adapter_status(adapter, "ccsonl1", NULL, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index c22c4786855..aab8123c596 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -98,8 +98,12 @@ static void zfcp_wka_port_offline(struct work_struct *work) struct zfcp_wka_port *wka_port = container_of(dw, struct zfcp_wka_port, work); - wait_event(wka_port->completion_wq, - atomic_read(&wka_port->refcount) == 0); + /* Don't wait forvever. If the wka_port is too busy take it offline + through a new call later */ + if (!wait_event_timeout(wka_port->completion_wq, + atomic_read(&wka_port->refcount) == 0, + HZ >> 1)) + return; mutex_lock(&wka_port->mutex); if ((atomic_read(&wka_port->refcount) != 0) || -- GitLab From 0282985da5923fa6365adcc1a1586ae0c13c1617 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Mon, 2 Mar 2009 13:09:06 +0100 Subject: [PATCH 3211/4982] [SCSI] zfcp: Report fc_host_port_type as NPIV Report the fc_host_port_type as FC_PORTTYPE_NPIV when the subchannel is running in NPIV mode. This allows to see the correct type with lsscsi -H -t --list Acked-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_fsf.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 9fa8c8990a1..b29f3121b66 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -617,9 +617,10 @@ static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req) if (req->data) memcpy(req->data, bottom, sizeof(*bottom)); - if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) + if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) { fc_host_permanent_port_name(shost) = bottom->wwpn; - else + fc_host_port_type(shost) = FC_PORTTYPE_NPIV; + } else fc_host_permanent_port_name(shost) = fc_host_port_name(shost); fc_host_maxframe_size(shost) = bottom->maximum_frame_size; fc_host_supported_speeds(shost) = bottom->supported_speed; -- GitLab From 7687fb9209422d35334995b8ace38de92e595d16 Mon Sep 17 00:00:00 2001 From: "Chauhan, Vijay" Date: Wed, 4 Mar 2009 12:17:54 +0530 Subject: [PATCH 3212/4982] [SCSI] scsi_dh_rdac: Retry mode select for NO_SENSE, ABORTED_COMMAND, UNIT_ATTENTION, NOT_READY(02/04/01) This patch is to add retry for mode select if mode select command is returned with sense NO_SENSE, UNIT_ATTENTION, ABORTED_COMMAND, NOT_READY(02/04/01). This patch reorganise the sense keys from if-else to switch-case format for better maintainability. Signed-off-by: Vijay Chauhan Acked-by: Chandra Seetharaman Signed-off-by: James Bottomley --- drivers/scsi/device_handler/scsi_dh_rdac.c | 38 ++++++++++++++-------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index f2b9d197e80..07962f675fe 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -449,28 +449,40 @@ static int mode_select_handle_sense(struct scsi_device *sdev, unsigned char *sensebuf) { struct scsi_sense_hdr sense_hdr; - int sense, err = SCSI_DH_IO, ret; + int err = SCSI_DH_IO, ret; ret = scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE, &sense_hdr); if (!ret) goto done; err = SCSI_DH_OK; - sense = (sense_hdr.sense_key << 16) | (sense_hdr.asc << 8) | - sense_hdr.ascq; - /* If it is retryable failure, submit the c9 inquiry again */ - if (sense == 0x59136 || sense == 0x68b02 || sense == 0xb8b02 || - sense == 0x62900) { - /* 0x59136 - Command lock contention - * 0x[6b]8b02 - Quiesense in progress or achieved - * 0x62900 - Power On, Reset, or Bus Device Reset - */ + + switch (sense_hdr.sense_key) { + case NO_SENSE: + case ABORTED_COMMAND: + case UNIT_ATTENTION: err = SCSI_DH_RETRY; + break; + case NOT_READY: + if (sense_hdr.asc == 0x04 && sense_hdr.ascq == 0x01) + /* LUN Not Ready and is in the Process of Becoming + * Ready + */ + err = SCSI_DH_RETRY; + break; + case ILLEGAL_REQUEST: + if (sense_hdr.asc == 0x91 && sense_hdr.ascq == 0x36) + /* + * Command Lock contention + */ + err = SCSI_DH_RETRY; + break; + default: + sdev_printk(KERN_INFO, sdev, + "MODE_SELECT failed with sense %02x/%02x/%02x.\n", + sense_hdr.sense_key, sense_hdr.asc, sense_hdr.ascq); } - if (sense) - sdev_printk(KERN_INFO, sdev, - "MODE_SELECT failed with sense 0x%x.\n", sense); done: return err; } -- GitLab From 9f4c899c0d90e1b51b6864834f3877b47c161a0e Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 12 Mar 2009 14:51:32 -0400 Subject: [PATCH 3213/4982] NFS: Fix the fix to Bugzilla #11061, when IPv6 isn't defined... Stephen Rothwell reports: Today's linux-next build (powerpc ppc64_defconfig) failed like this: fs/built-in.o: In function `.nfs_get_client': client.c:(.text+0x115010): undefined reference to `.__ipv6_addr_type' Fix by moving the IPV6 specific parts of commit d7371c41b0cda782256b1df759df4e8d4724584c ("Bug 11061, NFS mounts dropped") into the '#ifdef IPV6..." section. Also fix up a couple of formatting issues. Signed-off-by: Trond Myklebust --- fs/nfs/client.c | 68 ++++++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 06654b831d1..574158ae239 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -255,6 +255,32 @@ static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1, } return 0; } + +/* + * Test if two ip6 socket addresses refer to the same socket by + * comparing relevant fields. The padding bytes specifically, are not + * compared. sin6_flowinfo is not compared because it only affects QoS + * and sin6_scope_id is only compared if the address is "link local" + * because "link local" addresses need only be unique to a specific + * link. Conversely, ordinary unicast addresses might have different + * sin6_scope_id. + * + * The caller should ensure both socket addresses are AF_INET6. + */ +static int nfs_sockaddr_cmp_ip6(const struct sockaddr *sa1, + const struct sockaddr *sa2) +{ + const struct sockaddr_in6 *saddr1 = (const struct sockaddr_in6 *)sa1; + const struct sockaddr_in6 *saddr2 = (const struct sockaddr_in6 *)sa2; + + if (!ipv6_addr_equal(&saddr1->sin6_addr, + &saddr1->sin6_addr)) + return 0; + if (ipv6_addr_scope(&saddr1->sin6_addr) == IPV6_ADDR_SCOPE_LINKLOCAL && + saddr1->sin6_scope_id != saddr2->sin6_scope_id) + return 0; + return saddr1->sin6_port == saddr2->sin6_port; +} #else static int nfs_sockaddr_match_ipaddr4(const struct sockaddr_in *sa1, const struct sockaddr_in *sa2) @@ -270,6 +296,12 @@ static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1, return nfs_sockaddr_match_ipaddr4((const struct sockaddr_in *)sa1, (const struct sockaddr_in *)sa2); } + +static int nfs_sockaddr_cmp_ip6(const struct sockaddr * sa1, + const struct sockaddr * sa2) +{ + return 0; +} #endif /* @@ -279,37 +311,17 @@ static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1, * * The caller should ensure both socket addresses are AF_INET. */ -static int nfs_sockaddr_cmp_ip4(const struct sockaddr_in * saddr1, - const struct sockaddr_in * saddr2) +static int nfs_sockaddr_cmp_ip4(const struct sockaddr *sa1, + const struct sockaddr *sa2) { + const struct sockaddr_in *saddr1 = (const struct sockaddr_in *)sa1; + const struct sockaddr_in *saddr2 = (const struct sockaddr_in *)sa2; + if (saddr1->sin_addr.s_addr != saddr2->sin_addr.s_addr) return 0; return saddr1->sin_port == saddr2->sin_port; } -/* - * Test if two ip6 socket addresses refer to the same socket by - * comparing relevant fields. The padding bytes specifically, are not - * compared. sin6_flowinfo is not compared because it only affects QoS - * and sin6_scope_id is only compared if the address is "link local" - * because "link local" addresses need only be unique to a specific - * link. Conversely, ordinary unicast addresses might have different - * sin6_scope_id. - * - * The caller should ensure both socket addresses are AF_INET6. - */ -static int nfs_sockaddr_cmp_ip6 (const struct sockaddr_in6 * saddr1, - const struct sockaddr_in6 * saddr2) -{ - if (!ipv6_addr_equal(&saddr1->sin6_addr, - &saddr1->sin6_addr)) - return 0; - if (ipv6_addr_scope(&saddr1->sin6_addr) == IPV6_ADDR_SCOPE_LINKLOCAL && - saddr1->sin6_scope_id != saddr2->sin6_scope_id) - return 0; - return saddr1->sin6_port == saddr2->sin6_port; -} - /* * Test if two socket addresses represent the same actual socket, * by comparing (only) relevant fields. @@ -322,11 +334,9 @@ static int nfs_sockaddr_cmp(const struct sockaddr *sa1, switch (sa1->sa_family) { case AF_INET: - return nfs_sockaddr_cmp_ip4((const struct sockaddr_in *) sa1, - (const struct sockaddr_in *) sa2); + return nfs_sockaddr_cmp_ip4(sa1, sa2); case AF_INET6: - return nfs_sockaddr_cmp_ip6((const struct sockaddr_in6 *) sa1, - (const struct sockaddr_in6 *) sa2); + return nfs_sockaddr_cmp_ip6(sa1, sa2); } return 0; } -- GitLab From e4707dd3e9d0cb57597b6568a5e51fea5d6fca41 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Thu, 12 Mar 2009 20:11:43 +0100 Subject: [PATCH 3214/4982] [ARM] 5422/1: ARM: MMU: add a Non-cacheable Normal executable memory type This patch adds a Non-cacheable Normal ARM executable memory type, MT_MEMORY_NONCACHED. On OMAP3, this is used for rapid dynamic voltage/frequency scaling in the VDD2 voltage domain. OMAP3's SDRAM controller (SDRC) is in the VDD2 voltage domain, and its clock frequency must change along with voltage. The SDRC clock change code cannot run from SDRAM itself, since SDRAM accesses are paused during the clock change. So the current implementation of the DVFS code executes from OMAP on-chip SRAM, aka "OCM RAM." If the OCM RAM pages are marked as Cacheable, the ARM cache controller will attempt to flush dirty cache lines to the SDRC, so it can fill those lines with OCM RAM instruction code. The problem is that the SDRC is paused during DVFS, and so any SDRAM access causes the ARM MPU subsystem to hang. TI's original solution to this problem was to mark the OCM RAM sections as Strongly Ordered memory, thus preventing caching. This is overkill: since the memory is marked as non-bufferable, OCM RAM writes become needlessly slow. The idea of "Strongly Ordered SRAM" is also conceptually disturbing. Previous LAKML list discussion is here: http://www.spinics.net/lists/arm-kernel/msg54312.html This memory type MT_MEMORY_NONCACHED is used for OCM RAM by a future patch. Cc: Richard Woodruff Signed-off-by: Paul Walmsley Signed-off-by: Russell King --- arch/arm/include/asm/mach/map.h | 1 + arch/arm/mm/mmu.c | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h index 39d949b63e8..58cf91f38e6 100644 --- a/arch/arm/include/asm/mach/map.h +++ b/arch/arm/include/asm/mach/map.h @@ -26,6 +26,7 @@ struct map_desc { #define MT_HIGH_VECTORS 8 #define MT_MEMORY 9 #define MT_ROM 10 +#define MT_MEMORY_NONCACHED 11 #ifdef CONFIG_MMU extern void iotable_init(struct map_desc *, int); diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 9b36c5cb5e9..aa424e1da8a 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -243,6 +243,10 @@ static struct mem_type mem_types[] = { .prot_sect = PMD_TYPE_SECT, .domain = DOMAIN_KERNEL, }, + [MT_MEMORY_NONCACHED] = { + .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, + .domain = DOMAIN_KERNEL, + }, }; const struct mem_type *get_mem_type(unsigned int type) @@ -406,9 +410,28 @@ static void __init build_mem_type_table(void) kern_pgprot |= L_PTE_SHARED; vecs_pgprot |= L_PTE_SHARED; mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; + mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S; #endif } + /* + * Non-cacheable Normal - intended for memory areas that must + * not cause dirty cache line writebacks when used + */ + if (cpu_arch >= CPU_ARCH_ARMv6) { + if (cpu_arch >= CPU_ARCH_ARMv7 && (cr & CR_TRE)) { + /* Non-cacheable Normal is XCB = 001 */ + mem_types[MT_MEMORY_NONCACHED].prot_sect |= + PMD_SECT_BUFFERED; + } else { + /* For both ARMv6 and non-TEX-remapping ARMv7 */ + mem_types[MT_MEMORY_NONCACHED].prot_sect |= + PMD_SECT_TEX(1); + } + } else { + mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_BUFFERABLE; + } + for (i = 0; i < 16; i++) { unsigned long v = pgprot_val(protection_map[i]); protection_map[i] = __pgprot(v | user_pgprot); -- GitLab From 446c92b2901bedb3725d29b4e73def8aba623ffc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 12 Mar 2009 18:03:16 +0100 Subject: [PATCH 3215/4982] [ARM] 5421/1: ftrace: fix crash due to tracing of __naked functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a fix for the following crash observed in 2.6.29-rc3: http://lkml.org/lkml/2009/1/29/150 On ARM it doesn't make sense to trace a naked function because then mcount is called without stack and frame pointer being set up and there is no chance to restore the lr register to the value before mcount was called. Reported-by: Matthias Kaehlcke Tested-by: Matthias Kaehlcke Cc: Abhishek Sagar Cc: Steven Rostedt Cc: Ingo Molnar Signed-off-by: Uwe Kleine-König Signed-off-by: Russell King --- arch/arm/kernel/fiq.c | 4 ++-- arch/arm/mm/copypage-feroceon.c | 2 +- arch/arm/mm/copypage-v3.c | 2 +- arch/arm/mm/copypage-v4mc.c | 2 +- arch/arm/mm/copypage-v4wb.c | 2 +- arch/arm/mm/copypage-v4wt.c | 2 +- arch/arm/mm/copypage-xsc3.c | 2 +- arch/arm/mm/copypage-xscale.c | 2 +- include/linux/compiler-gcc.h | 10 +++++++++- 9 files changed, 18 insertions(+), 10 deletions(-) diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index 36f81d96797..6ff7919613d 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c @@ -88,7 +88,7 @@ void set_fiq_handler(void *start, unsigned int length) * disable irqs for the duration. Note - these functions are almost * entirely coded in assembly. */ -void __attribute__((naked)) set_fiq_regs(struct pt_regs *regs) +void __naked set_fiq_regs(struct pt_regs *regs) { register unsigned long tmp; asm volatile ( @@ -106,7 +106,7 @@ void __attribute__((naked)) set_fiq_regs(struct pt_regs *regs) : "r" (®s->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE)); } -void __attribute__((naked)) get_fiq_regs(struct pt_regs *regs) +void __naked get_fiq_regs(struct pt_regs *regs) { register unsigned long tmp; asm volatile ( diff --git a/arch/arm/mm/copypage-feroceon.c b/arch/arm/mm/copypage-feroceon.c index c3ba6a94da0..70997d5bee2 100644 --- a/arch/arm/mm/copypage-feroceon.c +++ b/arch/arm/mm/copypage-feroceon.c @@ -13,7 +13,7 @@ #include #include -static void __attribute__((naked)) +static void __naked feroceon_copy_user_page(void *kto, const void *kfrom) { asm("\ diff --git a/arch/arm/mm/copypage-v3.c b/arch/arm/mm/copypage-v3.c index 70ed96c8af8..de9c06854ad 100644 --- a/arch/arm/mm/copypage-v3.c +++ b/arch/arm/mm/copypage-v3.c @@ -15,7 +15,7 @@ * * FIXME: do we need to handle cache stuff... */ -static void __attribute__((naked)) +static void __naked v3_copy_user_page(void *kto, const void *kfrom) { asm("\n\ diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c index 1601698b980..7370a7142b0 100644 --- a/arch/arm/mm/copypage-v4mc.c +++ b/arch/arm/mm/copypage-v4mc.c @@ -44,7 +44,7 @@ static DEFINE_SPINLOCK(minicache_lock); * instruction. If your processor does not supply this, you have to write your * own copy_user_highpage that does the right thing. */ -static void __attribute__((naked)) +static void __naked mc_copy_user_page(void *from, void *to) { asm volatile( diff --git a/arch/arm/mm/copypage-v4wb.c b/arch/arm/mm/copypage-v4wb.c index 3ec93dab765..9ab09841422 100644 --- a/arch/arm/mm/copypage-v4wb.c +++ b/arch/arm/mm/copypage-v4wb.c @@ -22,7 +22,7 @@ * instruction. If your processor does not supply this, you have to write your * own copy_user_highpage that does the right thing. */ -static void __attribute__((naked)) +static void __naked v4wb_copy_user_page(void *kto, const void *kfrom) { asm("\ diff --git a/arch/arm/mm/copypage-v4wt.c b/arch/arm/mm/copypage-v4wt.c index 0f1188efae4..300efafd664 100644 --- a/arch/arm/mm/copypage-v4wt.c +++ b/arch/arm/mm/copypage-v4wt.c @@ -20,7 +20,7 @@ * dirty data in the cache. However, we do have to ensure that * subsequent reads are up to date. */ -static void __attribute__((naked)) +static void __naked v4wt_copy_user_page(void *kto, const void *kfrom) { asm("\ diff --git a/arch/arm/mm/copypage-xsc3.c b/arch/arm/mm/copypage-xsc3.c index 39a994542ca..bc4525f5ab2 100644 --- a/arch/arm/mm/copypage-xsc3.c +++ b/arch/arm/mm/copypage-xsc3.c @@ -29,7 +29,7 @@ * if we eventually end up using our copied page. * */ -static void __attribute__((naked)) +static void __naked xsc3_mc_copy_user_page(void *kto, const void *kfrom) { asm("\ diff --git a/arch/arm/mm/copypage-xscale.c b/arch/arm/mm/copypage-xscale.c index d18f2397ee2..76824d3e966 100644 --- a/arch/arm/mm/copypage-xscale.c +++ b/arch/arm/mm/copypage-xscale.c @@ -42,7 +42,7 @@ static DEFINE_SPINLOCK(minicache_lock); * Dcache aliasing issue. The writes will be forwarded to the write buffer, * and merged as appropriate. */ -static void __attribute__((naked)) +static void __naked mc_copy_user_page(void *from, void *to) { /* diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index 1514d534dee..a3ed7cb8ca3 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -52,7 +52,15 @@ #define __deprecated __attribute__((deprecated)) #define __packed __attribute__((packed)) #define __weak __attribute__((weak)) -#define __naked __attribute__((naked)) + +/* + * it doesn't make sense on ARM (currently the only user of __naked) to trace + * naked functions because then mcount is called without stack and frame pointer + * being set up and there is no chance to restore the lr register to the value + * before mcount was called. + */ +#define __naked __attribute__((naked)) notrace + #define __noreturn __attribute__((noreturn)) /* -- GitLab From 305b07680f6c6a7e59f996c5bd85f009caff5bb1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 12 Mar 2009 18:03:01 +0000 Subject: [PATCH 3216/4982] [ARM] update mach-types Signed-off-by: Russell King --- arch/arm/tools/mach-types | 136 +++++++++++++++++++++++++++++++++++++- 1 file changed, 133 insertions(+), 3 deletions(-) diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index fd23c0e9e69..b4211d8b2ac 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -12,7 +12,7 @@ # # http://www.arm.linux.org.uk/developer/machines/?action=new # -# Last update: Sun Nov 30 16:39:36 2008 +# Last update: Thu Mar 12 18:01:45 2009 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -1811,7 +1811,7 @@ pilz_pmi5 MACH_PILZ_PMI5 PILZ_PMI5 1820 jade MACH_JADE JADE 1821 ks8695_softplc MACH_KS8695_SOFTPLC KS8695_SOFTPLC 1822 gprisc3 MACH_GPRISC3 GPRISC3 1823 -stamp9260 MACH_STAMP9260 STAMP9260 1824 +stamp9g20 MACH_STAMP9G20 STAMP9G20 1824 smdk6430 MACH_SMDK6430 SMDK6430 1825 smdkc100 MACH_SMDKC100 SMDKC100 1826 tavorevb MACH_TAVOREVB TAVOREVB 1827 @@ -1993,4 +1993,134 @@ spark MACH_SPARK SPARK 2002 benzina MACH_BENZINA BENZINA 2003 blaze MACH_BLAZE BLAZE 2004 linkstation_ls_hgl MACH_LINKSTATION_LS_HGL LINKSTATION_LS_HGL 2005 -htcvenus MACH_HTCVENUS HTCVENUS 2006 +htckovsky MACH_HTCVENUS HTCVENUS 2006 +sony_prs505 MACH_SONY_PRS505 SONY_PRS505 2007 +hanlin_v3 MACH_HANLIN_V3 HANLIN_V3 2008 +sapphira MACH_SAPPHIRA SAPPHIRA 2009 +dack_sda_01 MACH_DACK_SDA_01 DACK_SDA_01 2010 +armbox MACH_ARMBOX ARMBOX 2011 +harris_rvp MACH_HARRIS_RVP HARRIS_RVP 2012 +ribaldo MACH_RIBALDO RIBALDO 2013 +agora MACH_AGORA AGORA 2014 +omap3_mini MACH_OMAP3_MINI OMAP3_MINI 2015 +a9sam6432_b MACH_A9SAM6432_B A9SAM6432_B 2016 +usg2410 MACH_USG2410 USG2410 2017 +pc72052_i10_revb MACH_PC72052_I10_REVB PC72052_I10_REVB 2018 +mx35_exm32 MACH_MX35_EXM32 MX35_EXM32 2019 +topas910 MACH_TOPAS910 TOPAS910 2020 +hyena MACH_HYENA HYENA 2021 +pospax MACH_POSPAX POSPAX 2022 +hdl_gx MACH_HDL_GX HDL_GX 2023 +ctera_4bay MACH_CTERA_4BAY CTERA_4BAY 2024 +ctera_plug_c MACH_CTERA_PLUG_C CTERA_PLUG_C 2025 +crwea_plug_i MACH_CRWEA_PLUG_I CRWEA_PLUG_I 2026 +egauge2 MACH_EGAUGE2 EGAUGE2 2027 +didj MACH_DIDJ DIDJ 2028 +m_s3c2443 MACH_MEISTER MEISTER 2029 +htcblackstone MACH_HTCBLACKSTONE HTCBLACKSTONE 2030 +cpuat9g20 MACH_CPUAT9G20 CPUAT9G20 2031 +smdk6440 MACH_SMDK6440 SMDK6440 2032 +omap_35xx_mvp MACH_OMAP_35XX_MVP OMAP_35XX_MVP 2033 +ctera_plug_i MACH_CTERA_PLUG_I CTERA_PLUG_I 2034 +pvg610_100 MACH_PVG610 PVG610 2035 +hprw6815 MACH_HPRW6815 HPRW6815 2036 +omap3_oswald MACH_OMAP3_OSWALD OMAP3_OSWALD 2037 +nas4220b MACH_NAS4220B NAS4220B 2038 +htcraphael_cdma MACH_HTCRAPHAEL_CDMA HTCRAPHAEL_CDMA 2039 +htcdiamond_cdma MACH_HTCDIAMOND_CDMA HTCDIAMOND_CDMA 2040 +scaler MACH_SCALER SCALER 2041 +zylonite2 MACH_ZYLONITE2 ZYLONITE2 2042 +aspenite MACH_ASPENITE ASPENITE 2043 +teton MACH_TETON TETON 2044 +ttc_dkb MACH_TTC_DKB TTC_DKB 2045 +bishop2 MACH_BISHOP2 BISHOP2 2046 +ippv5 MACH_IPPV5 IPPV5 2047 +farm926 MACH_FARM926 FARM926 2048 +mmccpu MACH_MMCCPU MMCCPU 2049 +sgmsfl MACH_SGMSFL SGMSFL 2050 +tt8000 MACH_TT8000 TT8000 2051 +zrn4300lp MACH_ZRN4300LP ZRN4300LP 2052 +mptc MACH_MPTC MPTC 2053 +h6051 MACH_H6051 H6051 2054 +pvg610_101 MACH_PVG610_101 PVG610_101 2055 +stamp9261_pc_evb MACH_STAMP9261_PC_EVB STAMP9261_PC_EVB 2056 +pelco_odysseus MACH_PELCO_ODYSSEUS PELCO_ODYSSEUS 2057 +tny_a9260 MACH_TNY_A9260 TNY_A9260 2058 +tny_a9g20 MACH_TNY_A9G20 TNY_A9G20 2059 +aesop_mp2530f MACH_AESOP_MP2530F AESOP_MP2530F 2060 +dx900 MACH_DX900 DX900 2061 +cpodc2 MACH_CPODC2 CPODC2 2062 +tilt_8925 MACH_TILT_8925 TILT_8925 2063 +davinci_dm357_evm MACH_DAVINCI_DM357_EVM DAVINCI_DM357_EVM 2064 +swordfish MACH_SWORDFISH SWORDFISH 2065 +corvus MACH_CORVUS CORVUS 2066 +taurus MACH_TAURUS TAURUS 2067 +axm MACH_AXM AXM 2068 +axc MACH_AXC AXC 2069 +baby MACH_BABY BABY 2070 +mp200 MACH_MP200 MP200 2071 +pcm043 MACH_PCM043 PCM043 2072 +hanlin_v3c MACH_HANLIN_V3C HANLIN_V3C 2073 +kbk9g20 MACH_KBK9G20 KBK9G20 2074 +adsturbog5 MACH_ADSTURBOG5 ADSTURBOG5 2075 +avenger_lite1 MACH_AVENGER_LITE1 AVENGER_LITE1 2076 +suc82x MACH_SUC SUC 2077 +at91sam7s256 MACH_AT91SAM7S256 AT91SAM7S256 2078 +mendoza MACH_MENDOZA MENDOZA 2079 +kira MACH_KIRA KIRA 2080 +mx1hbm MACH_MX1HBM MX1HBM 2081 +quatro43xx MACH_QUATRO43XX QUATRO43XX 2082 +quatro4230 MACH_QUATRO4230 QUATRO4230 2083 +nsb400 MACH_NSB400 NSB400 2084 +drp255 MACH_DRP255 DRP255 2085 +thoth MACH_THOTH THOTH 2086 +firestone MACH_FIRESTONE FIRESTONE 2087 +asusp750 MACH_ASUSP750 ASUSP750 2088 +ctera_dl MACH_CTERA_DL CTERA_DL 2089 +socr MACH_SOCR SOCR 2090 +htcoxygen MACH_HTCOXYGEN HTCOXYGEN 2091 +heroc MACH_HEROC HEROC 2092 +zeno6800 MACH_ZENO6800 ZENO6800 2093 +sc2mcs MACH_SC2MCS SC2MCS 2094 +gene100 MACH_GENE100 GENE100 2095 +as353x MACH_AS353X AS353X 2096 +sheevaplug MACH_SHEEVAPLUG SHEEVAPLUG 2097 +at91sam9g20 MACH_AT91SAM9G20 AT91SAM9G20 2098 +mv88f6192gtw_fe MACH_MV88F6192GTW_FE MV88F6192GTW_FE 2099 +cc9200 MACH_CC9200 CC9200 2100 +sm9200 MACH_SM9200 SM9200 2101 +tp9200 MACH_TP9200 TP9200 2102 +snapperdv MACH_SNAPPERDV SNAPPERDV 2103 +avengers_lite MACH_AVENGERS_LITE AVENGERS_LITE 2104 +avengers_lite1 MACH_AVENGERS_LITE1 AVENGERS_LITE1 2105 +omap3axon MACH_OMAP3AXON OMAP3AXON 2106 +ma8xx MACH_MA8XX MA8XX 2107 +mp201ek MACH_MP201EK MP201EK 2108 +davinci_tux MACH_DAVINCI_TUX DAVINCI_TUX 2109 +mpa1600 MACH_MPA1600 MPA1600 2110 +pelco_troy MACH_PELCO_TROY PELCO_TROY 2111 +nsb667 MACH_NSB667 NSB667 2112 +rovers5_4mpix MACH_ROVERS5_4MPIX ROVERS5_4MPIX 2113 +twocom MACH_TWOCOM TWOCOM 2114 +ubisys_p9_rcu3r2 MACH_UBISYS_P9_RCU3R2 UBISYS_P9_RCU3R2 2115 +hero_espresso MACH_HERO_ESPRESSO HERO_ESPRESSO 2116 +afeusb MACH_AFEUSB AFEUSB 2117 +t830 MACH_T830 T830 2118 +spd8020_cc MACH_SPD8020_CC SPD8020_CC 2119 +om_3d7k MACH_OM_3D7K OM_3D7K 2120 +picocom2 MACH_PICOCOM2 PICOCOM2 2121 +uwg4mx27 MACH_UWG4MX27 UWG4MX27 2122 +uwg4mx31 MACH_UWG4MX31 UWG4MX31 2123 +cherry MACH_CHERRY CHERRY 2124 +mx51_babbage MACH_MX51_BABBAGE MX51_BABBAGE 2125 +s3c2440turkiye MACH_S3C2440TURKIYE S3C2440TURKIYE 2126 +tx37 MACH_TX37 TX37 2127 +sbc2800_9g20 MACH_SBC2800_9G20 SBC2800_9G20 2128 +benzglb MACH_BENZGLB BENZGLB 2129 +benztd MACH_BENZTD BENZTD 2130 +cartesio_plus MACH_CARTESIO_PLUS CARTESIO_PLUS 2131 +solrad_g20 MACH_SOLRAD_G20 SOLRAD_G20 2132 +mx27wallace MACH_MX27WALLACE MX27WALLACE 2133 +fmzwebmodul MACH_FMZWEBMODUL FMZWEBMODUL 2134 +rd78x00_masa MACH_RD78X00_MASA RD78X00_MASA 2135 +smallogger MACH_SMALLOGGER SMALLOGGER 2136 -- GitLab From 1522ac3ec95ff0230e7aa516f86b674fdf72866c Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 12 Mar 2009 17:03:48 +0000 Subject: [PATCH 3217/4982] [ARM] Fix virtual to physical translation macro corner cases The current use of these macros works well when the conversion is entirely linear. In this case, we can be assured that the following holds true: __va(p + s) - s = __va(p) However, this is not always the case, especially when there is a non-linear conversion (eg, when there is a 3.5GB hole in memory.) In this case, if 's' is the size of the region (eg, PAGE_SIZE) and 'p' is the final page, the above is most definitely not true. So, we must ensure that __va() and __pa() are only used with valid kernel direct mapped RAM addresses. This patch tweaks the code to achieve this. Tested-by: Charles Moschel Signed-off-by: Russell King --- arch/arm/mm/dma-mapping.c | 20 ++++++++++++-------- arch/arm/mm/init.c | 2 +- arch/arm/mm/mmap.c | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 310e479309e..f1ef5613ccd 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -490,26 +490,30 @@ core_initcall(consistent_init); */ void dma_cache_maint(const void *start, size_t size, int direction) { - const void *end = start + size; + void (*inner_op)(const void *, const void *); + void (*outer_op)(unsigned long, unsigned long); - BUG_ON(!virt_addr_valid(start) || !virt_addr_valid(end - 1)); + BUG_ON(!virt_addr_valid(start) || !virt_addr_valid(start + size - 1)); switch (direction) { case DMA_FROM_DEVICE: /* invalidate only */ - dmac_inv_range(start, end); - outer_inv_range(__pa(start), __pa(end)); + inner_op = dmac_inv_range; + outer_op = outer_inv_range; break; case DMA_TO_DEVICE: /* writeback only */ - dmac_clean_range(start, end); - outer_clean_range(__pa(start), __pa(end)); + inner_op = dmac_clean_range; + outer_op = outer_clean_range; break; case DMA_BIDIRECTIONAL: /* writeback and invalidate */ - dmac_flush_range(start, end); - outer_flush_range(__pa(start), __pa(end)); + inner_op = dmac_flush_range; + outer_op = outer_flush_range; break; default: BUG(); } + + inner_op(start, start + size); + outer_op(__pa(start), __pa(start) + size); } EXPORT_SYMBOL(dma_cache_maint); diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 34df4d9d03a..80fd3b69ae1 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -382,7 +382,7 @@ void __init bootmem_init(void) for_each_node(node) bootmem_free_node(node, mi); - high_memory = __va(memend_pfn << PAGE_SHIFT); + high_memory = __va((memend_pfn << PAGE_SHIFT) - 1) + 1; /* * This doesn't seem to be used by the Linux memory manager any diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c index 5358fcc7f61..f7457fea6de 100644 --- a/arch/arm/mm/mmap.c +++ b/arch/arm/mm/mmap.c @@ -124,7 +124,7 @@ int valid_phys_addr_range(unsigned long addr, size_t size) { if (addr < PHYS_OFFSET) return 0; - if (addr + size > __pa(high_memory)) + if (addr + size >= __pa(high_memory - 1)) return 0; return 1; -- GitLab From 6c9fd1dc0a597e575617a7de7086c8a3efa8f524 Mon Sep 17 00:00:00 2001 From: Tiger Yang Date: Fri, 6 Mar 2009 10:19:30 +0800 Subject: [PATCH 3218/4982] ocfs2: reserve xattr block for new directory with inline data If this is a new directory with inline data, we choose to reserve the entire inline area for directory contents and force an external xattr block. Signed-off-by: Tiger Yang Acked-by: Joel Becker Signed-off-by: Mark Fasheh --- fs/ocfs2/xattr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 4ddd788add6..c63efb5ef13 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -547,8 +547,12 @@ int ocfs2_calc_xattr_init(struct inode *dir, * when blocksize = 512, may reserve one more cluser for * xattr bucket, otherwise reserve one metadata block * for them is ok. + * If this is a new directory with inline data, + * we choose to reserve the entire inline area for + * directory contents and force an external xattr block. */ if (dir->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE || + (S_ISDIR(mode) && ocfs2_supports_inline_data(osb)) || (s_size + a_size) > OCFS2_XATTR_FREE_IN_IBODY) { ret = ocfs2_reserve_new_metadata_blocks(osb, 1, xattr_ac); if (ret) { -- GitLab From d9ae49d6e2b1ac9166e58ae3c9345135604beaa6 Mon Sep 17 00:00:00 2001 From: Tiger Yang Date: Thu, 5 Mar 2009 11:06:15 +0800 Subject: [PATCH 3219/4982] ocfs2: tweak to get the maximum inline data size with xattr Replace max_inline_data with max_inline_data_with_xattr to ensure it correct when xattr inlined. Signed-off-by: Tiger Yang Acked-by: Joel Becker Signed-off-by: Mark Fasheh --- fs/ocfs2/aops.c | 7 +++++-- fs/ocfs2/namei.c | 3 ++- fs/ocfs2/ocfs2_fs.h | 6 ------ 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index a067a6cffb0..8e1709a679b 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -227,7 +227,7 @@ int ocfs2_read_inline_data(struct inode *inode, struct page *page, size = i_size_read(inode); if (size > PAGE_CACHE_SIZE || - size > ocfs2_max_inline_data(inode->i_sb)) { + size > ocfs2_max_inline_data_with_xattr(inode->i_sb, di)) { ocfs2_error(inode->i_sb, "Inode %llu has with inline data has bad size: %Lu", (unsigned long long)OCFS2_I(inode)->ip_blkno, @@ -1555,6 +1555,7 @@ static int ocfs2_try_to_write_inline_data(struct address_space *mapping, int ret, written = 0; loff_t end = pos + len; struct ocfs2_inode_info *oi = OCFS2_I(inode); + struct ocfs2_dinode *di = NULL; mlog(0, "Inode %llu, write of %u bytes at off %llu. features: 0x%x\n", (unsigned long long)oi->ip_blkno, len, (unsigned long long)pos, @@ -1587,7 +1588,9 @@ static int ocfs2_try_to_write_inline_data(struct address_space *mapping, /* * Check whether the write can fit. */ - if (mmap_page || end > ocfs2_max_inline_data(inode->i_sb)) + di = (struct ocfs2_dinode *)wc->w_di_bh->b_data; + if (mmap_page || + end > ocfs2_max_inline_data_with_xattr(inode->i_sb, di)) return 0; do_inline_write: diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 084aba86c3b..4b11762f249 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -532,7 +532,8 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, fe->i_dyn_features = cpu_to_le16(feat | OCFS2_INLINE_DATA_FL); - fe->id2.i_data.id_count = cpu_to_le16(ocfs2_max_inline_data(osb->sb)); + fe->id2.i_data.id_count = cpu_to_le16( + ocfs2_max_inline_data_with_xattr(osb->sb, fe)); } else { fel = &fe->id2.i_list; fel->l_tree_depth = 0; diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h index c7ae45aaa36..2332ef740f4 100644 --- a/fs/ocfs2/ocfs2_fs.h +++ b/fs/ocfs2/ocfs2_fs.h @@ -1070,12 +1070,6 @@ static inline int ocfs2_fast_symlink_chars(struct super_block *sb) offsetof(struct ocfs2_dinode, id2.i_symlink); } -static inline int ocfs2_max_inline_data(struct super_block *sb) -{ - return sb->s_blocksize - - offsetof(struct ocfs2_dinode, id2.i_data.id_data); -} - static inline int ocfs2_max_inline_data_with_xattr(struct super_block *sb, struct ocfs2_dinode *di) { -- GitLab From 74e77eb30d0ecbb12964d005b439c8b84a505b84 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Thu, 12 Mar 2009 06:24:23 +0800 Subject: [PATCH 3220/4982] ocfs2: Fix a bug found by sparse check. We need to use le32_to_cpu to test rec->e_cpos in ocfs2_dinode_insert_check. Signed-off-by: Tao Ma Acked-by: Joel Becker Signed-off-by: Mark Fasheh --- fs/ocfs2/alloc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 3a9e5deed74..19e3a96aa02 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -176,7 +176,8 @@ static int ocfs2_dinode_insert_check(struct inode *inode, BUG_ON(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL); mlog_bug_on_msg(!ocfs2_sparse_alloc(osb) && - (OCFS2_I(inode)->ip_clusters != rec->e_cpos), + (OCFS2_I(inode)->ip_clusters != + le32_to_cpu(rec->e_cpos)), "Device %s, asking for sparse allocation: inode %llu, " "cpos %u, clusters %u\n", osb->dev_str, -- GitLab From 712e53e46a1da35fcd88c05aa0c675b10f7c0e9d Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Thu, 12 Mar 2009 08:37:34 +0800 Subject: [PATCH 3221/4982] ocfs2: Use xs->bucket to set xattr value outside A long time ago, xs->base is allocated a 4K size and all the contents in the bucket are copied to the it. Now we use ocfs2_xattr_bucket to abstract xattr bucket and xs->base is initialized to the start of the bu_bhs[0]. So xs->base + offset will overflow when the value root is stored outside the first block. Then why we can survive the xattr test by now? It is because we always read the bucket contiguously now and kernel mm allocate continguous memory for us. We are lucky, but we should fix it. So just get the right value root as other callers do. Signed-off-by: Tao Ma Acked-by: Joel Becker Signed-off-by: Mark Fasheh --- fs/ocfs2/xattr.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index c63efb5ef13..2563df89fc2 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -4795,19 +4795,33 @@ static int ocfs2_xattr_bucket_set_value_outside(struct inode *inode, char *val, int value_len) { - int offset; + int ret, offset, block_off; struct ocfs2_xattr_value_root *xv; struct ocfs2_xattr_entry *xe = xs->here; + struct ocfs2_xattr_header *xh = bucket_xh(xs->bucket); + void *base; BUG_ON(!xs->base || !xe || ocfs2_xattr_is_local(xe)); - offset = le16_to_cpu(xe->xe_name_offset) + - OCFS2_XATTR_SIZE(xe->xe_name_len); + ret = ocfs2_xattr_bucket_get_name_value(inode, xh, + xe - xh->xh_entries, + &block_off, + &offset); + if (ret) { + mlog_errno(ret); + goto out; + } - xv = (struct ocfs2_xattr_value_root *)(xs->base + offset); + base = bucket_block(xs->bucket, block_off); + xv = (struct ocfs2_xattr_value_root *)(base + offset + + OCFS2_XATTR_SIZE(xe->xe_name_len)); - return __ocfs2_xattr_set_value_outside(inode, handle, - xv, val, value_len); + ret = __ocfs2_xattr_set_value_outside(inode, handle, + xv, val, value_len); + if (ret) + mlog_errno(ret); +out: + return ret; } static int ocfs2_rm_xattr_cluster(struct inode *inode, -- GitLab From 53f5649b21a7c7b894d68ac4848eb01136fa64aa Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Fri, 13 Mar 2009 10:50:17 +0800 Subject: [PATCH 3222/4982] [ARM] pxa: fix typo in BANK_OFF() macro in gpio.h The typo was originally fixed by Mike Rapoport and missed. And is later reported by Matthias Meier. Signed-off-by: Matthias Meier Signed-off-by: Mike Rapoport Signed-off-by: Eric Miao --- arch/arm/mach-pxa/include/mach/gpio.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-pxa/include/mach/gpio.h b/arch/arm/mach-pxa/include/mach/gpio.h index 406fa102cb4..c72c89a2285 100644 --- a/arch/arm/mach-pxa/include/mach/gpio.h +++ b/arch/arm/mach-pxa/include/mach/gpio.h @@ -30,7 +30,7 @@ #define GPIO_REGS_VIRT io_p2v(0x40E00000) -#define BANK_OFF(n) (((n) > 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) +#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) #define GPIO_REG(x) (*(volatile u32 *)(GPIO_REGS_VIRT + (x))) /* GPIO Pin Level Registers */ -- GitLab From 5f77af93266e107bd46c010c51d772c0fb003232 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 10 Mar 2009 13:06:40 -0300 Subject: [PATCH 3223/4982] V4L/DVB (10972): zl10353: i2c_gate_ctrl bug fix zl10353 i2c-gate was always closed and due to that devices having tuner behind i2c-gate were broken. Add module configuration which allows disabling i2c-gate only when really needed. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/zl10353.c | 2 +- drivers/media/dvb/frontends/zl10353.h | 3 +++ drivers/media/video/saa7134/saa7134-dvb.c | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c index 170720b0281..b150ed30669 100644 --- a/drivers/media/dvb/frontends/zl10353.c +++ b/drivers/media/dvb/frontends/zl10353.c @@ -590,7 +590,7 @@ static int zl10353_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) struct zl10353_state *state = fe->demodulator_priv; u8 val = 0x0a; - if (state->config.no_tuner) { + if (state->config.disable_i2c_gate_ctrl) { /* No tuner attached to the internal I2C bus */ /* If set enable I2C bridge, the main I2C bus stopped hardly */ return 0; diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h index fdbb88ff75f..2287bac4624 100644 --- a/drivers/media/dvb/frontends/zl10353.h +++ b/drivers/media/dvb/frontends/zl10353.h @@ -38,6 +38,9 @@ struct zl10353_config /* set if parallel ts output is required */ int parallel_ts; + + /* set if i2c_gate_ctrl disable is required */ + u8 disable_i2c_gate_ctrl:1; }; #if defined(CONFIG_DVB_ZL10353) || (defined(CONFIG_DVB_ZL10353_MODULE) && defined(MODULE)) diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 0776ecf56d2..b5370b3e1a3 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -860,6 +860,7 @@ static struct zl10353_config behold_h6_config = { .demod_address = 0x1e>>1, .no_tuner = 1, .parallel_ts = 1, + .disable_i2c_gate_ctrl = 1, }; /* ================================================================== -- GitLab From f507cd22035fdadd5dbb476dd05e9e7ee21c3b84 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 6 Mar 2009 02:54:09 +0000 Subject: [PATCH 3224/4982] ps3/block: Replace mtd/ps3vram by block/ps3vram Convert the PS3 Video RAM Storage Driver from an MTD driver to a plain block device driver. The ps3vram driver exposes unused video RAM on the PS3 as a block device suitable for storage or swap. Fast data transfer is achieved using a local cache in system RAM and DMA transfers via the GPU. The new driver is ca. 50% faster for reading, and ca. 10% for writing. Signed-off-by: Geert Uytterhoeven Acked-by: Geoff Levand Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/ps3/Kconfig | 7 + drivers/block/Makefile | 1 + drivers/block/ps3vram.c | 865 +++++++++++++++++++++++++++++ drivers/mtd/devices/Kconfig | 7 - drivers/mtd/devices/Makefile | 1 - drivers/mtd/devices/ps3vram.c | 768 ------------------------- 6 files changed, 873 insertions(+), 776 deletions(-) create mode 100644 drivers/block/ps3vram.c delete mode 100644 drivers/mtd/devices/ps3vram.c diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig index 920cf7a454b..740ef56a155 100644 --- a/arch/powerpc/platforms/ps3/Kconfig +++ b/arch/powerpc/platforms/ps3/Kconfig @@ -128,6 +128,13 @@ config PS3_FLASH be disabled on the kernel command line using "ps3flash=off", to not allocate this fixed buffer. +config PS3_VRAM + tristate "PS3 Video RAM Storage Driver" + depends on FB_PS3=y && BLOCK && m + help + This driver allows you to use excess PS3 video RAM as volatile + storage or system swap. + config PS3_LPM tristate "PS3 Logical Performance Monitor support" depends on PPC_PS3 diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 204332b2957..87e120e0a79 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_MAC_FLOPPY) += swim3.o obj-$(CONFIG_BLK_DEV_FD) += floppy.o obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o obj-$(CONFIG_PS3_DISK) += ps3disk.o +obj-$(CONFIG_PS3_VRAM) += ps3vram.o obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o obj-$(CONFIG_BLK_DEV_RAM) += brd.o diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c new file mode 100644 index 00000000000..393ed6760d7 --- /dev/null +++ b/drivers/block/ps3vram.c @@ -0,0 +1,865 @@ +/* + * ps3vram - Use extra PS3 video ram as MTD block device. + * + * Copyright 2009 Sony Corporation + * + * Based on the MTD ps3vram driver, which is + * Copyright (c) 2007-2008 Jim Paris + * Added support RSX DMA Vivien Chappelier + */ + +#include +#include +#include +#include + +#include +#include +#include + + +#define DEVICE_NAME "ps3vram" + + +#define XDR_BUF_SIZE (2 * 1024 * 1024) /* XDR buffer (must be 1MiB aligned) */ +#define XDR_IOIF 0x0c000000 + +#define FIFO_BASE XDR_IOIF +#define FIFO_SIZE (64 * 1024) + +#define DMA_PAGE_SIZE (4 * 1024) + +#define CACHE_PAGE_SIZE (256 * 1024) +#define CACHE_PAGE_COUNT ((XDR_BUF_SIZE - FIFO_SIZE) / CACHE_PAGE_SIZE) + +#define CACHE_OFFSET CACHE_PAGE_SIZE +#define FIFO_OFFSET 0 + +#define CTRL_PUT 0x10 +#define CTRL_GET 0x11 +#define CTRL_TOP 0x15 + +#define UPLOAD_SUBCH 1 +#define DOWNLOAD_SUBCH 2 + +#define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN 0x0000030c +#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY 0x00000104 + +#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT 0x601 + +#define CACHE_PAGE_PRESENT 1 +#define CACHE_PAGE_DIRTY 2 + +struct ps3vram_tag { + unsigned int address; + unsigned int flags; +}; + +struct ps3vram_cache { + unsigned int page_count; + unsigned int page_size; + struct ps3vram_tag *tags; + unsigned int hit; + unsigned int miss; +}; + +struct ps3vram_priv { + struct request_queue *queue; + struct gendisk *gendisk; + + u64 size; + + u64 memory_handle; + u64 context_handle; + u32 *ctrl; + u32 *reports; + u8 __iomem *ddr_base; + u8 *xdr_buf; + + u32 *fifo_base; + u32 *fifo_ptr; + + struct ps3vram_cache cache; + + /* Used to serialize cache/DMA operations */ + struct mutex lock; +}; + + +static int ps3vram_major; + + +static struct block_device_operations ps3vram_fops = { + .owner = THIS_MODULE, +}; + + +#define DMA_NOTIFIER_HANDLE_BASE 0x66604200 /* first DMA notifier handle */ +#define DMA_NOTIFIER_OFFSET_BASE 0x1000 /* first DMA notifier offset */ +#define DMA_NOTIFIER_SIZE 0x40 +#define NOTIFIER 7 /* notifier used for completion report */ + +static char *size = "256M"; +module_param(size, charp, 0); +MODULE_PARM_DESC(size, "memory size"); + +static u32 *ps3vram_get_notifier(u32 *reports, int notifier) +{ + return (void *)reports + DMA_NOTIFIER_OFFSET_BASE + + DMA_NOTIFIER_SIZE * notifier; +} + +static void ps3vram_notifier_reset(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER); + int i; + + for (i = 0; i < 4; i++) + notify[i] = 0xffffffff; +} + +static int ps3vram_notifier_wait(struct ps3_system_bus_device *dev, + unsigned int timeout_ms) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER); + unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); + + do { + if (!notify[3]) + return 0; + msleep(1); + } while (time_before(jiffies, timeout)); + + return -ETIMEDOUT; +} + +static void ps3vram_init_ring(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET; + priv->ctrl[CTRL_GET] = FIFO_BASE + FIFO_OFFSET; +} + +static int ps3vram_wait_ring(struct ps3_system_bus_device *dev, + unsigned int timeout_ms) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); + + do { + if (priv->ctrl[CTRL_PUT] == priv->ctrl[CTRL_GET]) + return 0; + msleep(1); + } while (time_before(jiffies, timeout)); + + dev_warn(&dev->core, "FIFO timeout (%08x/%08x/%08x)\n", + priv->ctrl[CTRL_PUT], priv->ctrl[CTRL_GET], + priv->ctrl[CTRL_TOP]); + + return -ETIMEDOUT; +} + +static void ps3vram_out_ring(struct ps3vram_priv *priv, u32 data) +{ + *(priv->fifo_ptr)++ = data; +} + +static void ps3vram_begin_ring(struct ps3vram_priv *priv, u32 chan, u32 tag, + u32 size) +{ + ps3vram_out_ring(priv, (size << 18) | (chan << 13) | tag); +} + +static void ps3vram_rewind_ring(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + int status; + + ps3vram_out_ring(priv, 0x20000000 | (FIFO_BASE + FIFO_OFFSET)); + + priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET; + + /* asking the HV for a blit will kick the FIFO */ + status = lv1_gpu_context_attribute(priv->context_handle, + L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, 0, + 0, 0, 0); + if (status) + dev_err(&dev->core, + "%s: lv1_gpu_context_attribute failed %d\n", __func__, + status); + + priv->fifo_ptr = priv->fifo_base; +} + +static void ps3vram_fire_ring(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + int status; + + mutex_lock(&ps3_gpu_mutex); + + priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET + + (priv->fifo_ptr - priv->fifo_base) * sizeof(u32); + + /* asking the HV for a blit will kick the FIFO */ + status = lv1_gpu_context_attribute(priv->context_handle, + L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, 0, + 0, 0, 0); + if (status) + dev_err(&dev->core, + "%s: lv1_gpu_context_attribute failed %d\n", __func__, + status); + + if ((priv->fifo_ptr - priv->fifo_base) * sizeof(u32) > + FIFO_SIZE - 1024) { + dev_dbg(&dev->core, "FIFO full, rewinding\n"); + ps3vram_wait_ring(dev, 200); + ps3vram_rewind_ring(dev); + } + + mutex_unlock(&ps3_gpu_mutex); +} + +static void ps3vram_bind(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0, 1); + ps3vram_out_ring(priv, 0x31337303); + ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x180, 3); + ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER); + ps3vram_out_ring(priv, 0xfeed0001); /* DMA system RAM instance */ + ps3vram_out_ring(priv, 0xfeed0000); /* DMA video RAM instance */ + + ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0, 1); + ps3vram_out_ring(priv, 0x3137c0de); + ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x180, 3); + ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER); + ps3vram_out_ring(priv, 0xfeed0000); /* DMA video RAM instance */ + ps3vram_out_ring(priv, 0xfeed0001); /* DMA system RAM instance */ + + ps3vram_fire_ring(dev); +} + +static int ps3vram_upload(struct ps3_system_bus_device *dev, + unsigned int src_offset, unsigned int dst_offset, + int len, int count) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + ps3vram_begin_ring(priv, UPLOAD_SUBCH, + NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); + ps3vram_out_ring(priv, XDR_IOIF + src_offset); + ps3vram_out_ring(priv, dst_offset); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, count); + ps3vram_out_ring(priv, (1 << 8) | 1); + ps3vram_out_ring(priv, 0); + + ps3vram_notifier_reset(dev); + ps3vram_begin_ring(priv, UPLOAD_SUBCH, + NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1); + ps3vram_out_ring(priv, 0); + ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x100, 1); + ps3vram_out_ring(priv, 0); + ps3vram_fire_ring(dev); + if (ps3vram_notifier_wait(dev, 200) < 0) { + dev_warn(&dev->core, "%s: Notifier timeout\n", __func__); + return -1; + } + + return 0; +} + +static int ps3vram_download(struct ps3_system_bus_device *dev, + unsigned int src_offset, unsigned int dst_offset, + int len, int count) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, + NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); + ps3vram_out_ring(priv, src_offset); + ps3vram_out_ring(priv, XDR_IOIF + dst_offset); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, count); + ps3vram_out_ring(priv, (1 << 8) | 1); + ps3vram_out_ring(priv, 0); + + ps3vram_notifier_reset(dev); + ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, + NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1); + ps3vram_out_ring(priv, 0); + ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x100, 1); + ps3vram_out_ring(priv, 0); + ps3vram_fire_ring(dev); + if (ps3vram_notifier_wait(dev, 200) < 0) { + dev_warn(&dev->core, "%s: Notifier timeout\n", __func__); + return -1; + } + + return 0; +} + +static void ps3vram_cache_evict(struct ps3_system_bus_device *dev, int entry) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + struct ps3vram_cache *cache = &priv->cache; + + if (!(cache->tags[entry].flags & CACHE_PAGE_DIRTY)) + return; + + dev_dbg(&dev->core, "Flushing %d: 0x%08x\n", entry, + cache->tags[entry].address); + if (ps3vram_upload(dev, CACHE_OFFSET + entry * cache->page_size, + cache->tags[entry].address, DMA_PAGE_SIZE, + cache->page_size / DMA_PAGE_SIZE) < 0) { + dev_err(&dev->core, + "Failed to upload from 0x%x to " "0x%x size 0x%x\n", + entry * cache->page_size, cache->tags[entry].address, + cache->page_size); + } + cache->tags[entry].flags &= ~CACHE_PAGE_DIRTY; +} + +static void ps3vram_cache_load(struct ps3_system_bus_device *dev, int entry, + unsigned int address) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + struct ps3vram_cache *cache = &priv->cache; + + dev_dbg(&dev->core, "Fetching %d: 0x%08x\n", entry, address); + if (ps3vram_download(dev, address, + CACHE_OFFSET + entry * cache->page_size, + DMA_PAGE_SIZE, + cache->page_size / DMA_PAGE_SIZE) < 0) { + dev_err(&dev->core, + "Failed to download from 0x%x to 0x%x size 0x%x\n", + address, entry * cache->page_size, cache->page_size); + } + + cache->tags[entry].address = address; + cache->tags[entry].flags |= CACHE_PAGE_PRESENT; +} + + +static void ps3vram_cache_flush(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + struct ps3vram_cache *cache = &priv->cache; + int i; + + dev_dbg(&dev->core, "FLUSH\n"); + for (i = 0; i < cache->page_count; i++) { + ps3vram_cache_evict(dev, i); + cache->tags[i].flags = 0; + } +} + +static unsigned int ps3vram_cache_match(struct ps3_system_bus_device *dev, + loff_t address) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + struct ps3vram_cache *cache = &priv->cache; + unsigned int base; + unsigned int offset; + int i; + static int counter; + + offset = (unsigned int) (address & (cache->page_size - 1)); + base = (unsigned int) (address - offset); + + /* fully associative check */ + for (i = 0; i < cache->page_count; i++) { + if ((cache->tags[i].flags & CACHE_PAGE_PRESENT) && + cache->tags[i].address == base) { + cache->hit++; + dev_dbg(&dev->core, "Found entry %d: 0x%08x\n", i, + cache->tags[i].address); + return i; + } + } + + /* choose a random entry */ + i = (jiffies + (counter++)) % cache->page_count; + dev_dbg(&dev->core, "Using entry %d\n", i); + + ps3vram_cache_evict(dev, i); + ps3vram_cache_load(dev, i, base); + + cache->miss++; + return i; +} + +static int ps3vram_cache_init(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + priv->cache.page_count = CACHE_PAGE_COUNT; + priv->cache.page_size = CACHE_PAGE_SIZE; + priv->cache.tags = kzalloc(sizeof(struct ps3vram_tag) * + CACHE_PAGE_COUNT, GFP_KERNEL); + if (priv->cache.tags == NULL) { + dev_err(&dev->core, "Could not allocate cache tags\n"); + return -ENOMEM; + } + + dev_info(&dev->core, "Created ram cache: %d entries, %d KiB each\n", + CACHE_PAGE_COUNT, CACHE_PAGE_SIZE / 1024); + + return 0; +} + +static void ps3vram_cache_cleanup(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + ps3vram_cache_flush(dev); + kfree(priv->cache.tags); +} + +static int ps3vram_read(struct ps3_system_bus_device *dev, loff_t from, + size_t len, size_t *retlen, u_char *buf) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + unsigned int cached, count; + + dev_dbg(&dev->core, "%s: from=0x%08x len=0x%zx\n", __func__, + (unsigned int)from, len); + + if (from >= priv->size) + return -EIO; + + if (len > priv->size - from) + len = priv->size - from; + + /* Copy from vram to buf */ + count = len; + while (count) { + unsigned int offset, avail; + unsigned int entry; + + offset = (unsigned int) (from & (priv->cache.page_size - 1)); + avail = priv->cache.page_size - offset; + + mutex_lock(&priv->lock); + + entry = ps3vram_cache_match(dev, from); + cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; + + dev_dbg(&dev->core, "%s: from=%08x cached=%08x offset=%08x " + "avail=%08x count=%08x\n", __func__, + (unsigned int)from, cached, offset, avail, count); + + if (avail > count) + avail = count; + memcpy(buf, priv->xdr_buf + cached, avail); + + mutex_unlock(&priv->lock); + + buf += avail; + count -= avail; + from += avail; + } + + *retlen = len; + return 0; +} + +static int ps3vram_write(struct ps3_system_bus_device *dev, loff_t to, + size_t len, size_t *retlen, const u_char *buf) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + unsigned int cached, count; + + if (to >= priv->size) + return -EIO; + + if (len > priv->size - to) + len = priv->size - to; + + /* Copy from buf to vram */ + count = len; + while (count) { + unsigned int offset, avail; + unsigned int entry; + + offset = (unsigned int) (to & (priv->cache.page_size - 1)); + avail = priv->cache.page_size - offset; + + mutex_lock(&priv->lock); + + entry = ps3vram_cache_match(dev, to); + cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; + + dev_dbg(&dev->core, "%s: to=%08x cached=%08x offset=%08x " + "avail=%08x count=%08x\n", __func__, (unsigned int)to, + cached, offset, avail, count); + + if (avail > count) + avail = count; + memcpy(priv->xdr_buf + cached, buf, avail); + + priv->cache.tags[entry].flags |= CACHE_PAGE_DIRTY; + + mutex_unlock(&priv->lock); + + buf += avail; + count -= avail; + to += avail; + } + + *retlen = len; + return 0; +} + +static int ps3vram_proc_show(struct seq_file *m, void *v) +{ + struct ps3vram_priv *priv = m->private; + + seq_printf(m, "hit:%u\nmiss:%u\n", priv->cache.hit, priv->cache.miss); + return 0; +} + +static int ps3vram_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, ps3vram_proc_show, PDE(inode)->data); +} + +static const struct file_operations ps3vram_proc_fops = { + .owner = THIS_MODULE, + .open = ps3vram_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void __devinit ps3vram_proc_init(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + struct proc_dir_entry *pde; + + pde = proc_create(DEVICE_NAME, 0444, NULL, &ps3vram_proc_fops); + if (!pde) { + dev_warn(&dev->core, "failed to create /proc entry\n"); + return; + } + + pde->owner = THIS_MODULE; + pde->data = priv; +} + +static int ps3vram_make_request(struct request_queue *q, struct bio *bio) +{ + struct ps3_system_bus_device *dev = q->queuedata; + int write = bio_data_dir(bio) == WRITE; + const char *op = write ? "write" : "read"; + loff_t offset = bio->bi_sector << 9; + int error = 0; + struct bio_vec *bvec; + unsigned int i; + + dev_dbg(&dev->core, "%s\n", __func__); + + bio_for_each_segment(bvec, bio, i) { + /* PS3 is ppc64, so we don't handle highmem */ + char *ptr = page_address(bvec->bv_page) + bvec->bv_offset; + size_t len = bvec->bv_len, retlen; + + dev_dbg(&dev->core, " %s %zu bytes at offset %llu\n", op, + len, offset); + if (write) + error = ps3vram_write(dev, offset, len, &retlen, ptr); + else + error = ps3vram_read(dev, offset, len, &retlen, ptr); + + if (error) { + dev_err(&dev->core, "%s failed\n", op); + goto out; + } + + if (retlen != len) { + dev_err(&dev->core, "Short %s\n", op); + goto out; + } + + offset += len; + } + + dev_dbg(&dev->core, "%s completed\n", op); + +out: + bio_endio(bio, error); + return 0; +} + +static int __devinit ps3vram_probe(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv; + int error, status; + struct request_queue *queue; + struct gendisk *gendisk; + u64 ddr_lpar, ctrl_lpar, info_lpar, reports_lpar, ddr_size, + reports_size; + char *rest; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) { + error = -ENOMEM; + goto fail; + } + + mutex_init(&priv->lock); + dev->core.driver_data = priv; + + priv = dev->core.driver_data; + + /* Allocate XDR buffer (1MiB aligned) */ + priv->xdr_buf = (void *)__get_free_pages(GFP_KERNEL, + get_order(XDR_BUF_SIZE)); + if (priv->xdr_buf == NULL) { + dev_err(&dev->core, "Could not allocate XDR buffer\n"); + error = -ENOMEM; + goto fail_free_priv; + } + + /* Put FIFO at begginning of XDR buffer */ + priv->fifo_base = (u32 *) (priv->xdr_buf + FIFO_OFFSET); + priv->fifo_ptr = priv->fifo_base; + + /* XXX: Need to open GPU, in case ps3fb or snd_ps3 aren't loaded */ + if (ps3_open_hv_device(dev)) { + dev_err(&dev->core, "ps3_open_hv_device failed\n"); + error = -EAGAIN; + goto out_close_gpu; + } + + /* Request memory */ + status = -1; + ddr_size = ALIGN(memparse(size, &rest), 1024*1024); + if (!ddr_size) { + dev_err(&dev->core, "Specified size is too small\n"); + error = -EINVAL; + goto out_close_gpu; + } + + while (ddr_size > 0) { + status = lv1_gpu_memory_allocate(ddr_size, 0, 0, 0, 0, + &priv->memory_handle, + &ddr_lpar); + if (!status) + break; + ddr_size -= 1024*1024; + } + if (status) { + dev_err(&dev->core, "lv1_gpu_memory_allocate failed %d\n", + status); + error = -ENOMEM; + goto out_free_xdr_buf; + } + + /* Request context */ + status = lv1_gpu_context_allocate(priv->memory_handle, 0, + &priv->context_handle, &ctrl_lpar, + &info_lpar, &reports_lpar, + &reports_size); + if (status) { + dev_err(&dev->core, "lv1_gpu_context_allocate failed %d\n", + status); + error = -ENOMEM; + goto out_free_memory; + } + + /* Map XDR buffer to RSX */ + status = lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF, + ps3_mm_phys_to_lpar(__pa(priv->xdr_buf)), + XDR_BUF_SIZE, 0); + if (status) { + dev_err(&dev->core, "lv1_gpu_context_iomap failed %d\n", + status); + error = -ENOMEM; + goto out_free_context; + } + + priv->ddr_base = ioremap_flags(ddr_lpar, ddr_size, _PAGE_NO_CACHE); + + if (!priv->ddr_base) { + dev_err(&dev->core, "ioremap DDR failed\n"); + error = -ENOMEM; + goto out_free_context; + } + + priv->ctrl = ioremap(ctrl_lpar, 64 * 1024); + if (!priv->ctrl) { + dev_err(&dev->core, "ioremap CTRL failed\n"); + error = -ENOMEM; + goto out_unmap_vram; + } + + priv->reports = ioremap(reports_lpar, reports_size); + if (!priv->reports) { + dev_err(&dev->core, "ioremap REPORTS failed\n"); + error = -ENOMEM; + goto out_unmap_ctrl; + } + + mutex_lock(&ps3_gpu_mutex); + ps3vram_init_ring(dev); + mutex_unlock(&ps3_gpu_mutex); + + priv->size = ddr_size; + + ps3vram_bind(dev); + + mutex_lock(&ps3_gpu_mutex); + error = ps3vram_wait_ring(dev, 100); + mutex_unlock(&ps3_gpu_mutex); + if (error < 0) { + dev_err(&dev->core, "Failed to initialize channels\n"); + error = -ETIMEDOUT; + goto out_unmap_reports; + } + + ps3vram_cache_init(dev); + ps3vram_proc_init(dev); + + queue = blk_alloc_queue(GFP_KERNEL); + if (!queue) { + dev_err(&dev->core, "blk_alloc_queue failed\n"); + error = -ENOMEM; + goto out_cache_cleanup; + } + + priv->queue = queue; + queue->queuedata = dev; + blk_queue_make_request(queue, ps3vram_make_request); + blk_queue_max_phys_segments(queue, MAX_PHYS_SEGMENTS); + blk_queue_max_hw_segments(queue, MAX_HW_SEGMENTS); + blk_queue_max_segment_size(queue, MAX_SEGMENT_SIZE); + blk_queue_max_sectors(queue, SAFE_MAX_SECTORS); + + gendisk = alloc_disk(1); + if (!gendisk) { + dev_err(&dev->core, "alloc_disk failed\n"); + error = -ENOMEM; + goto fail_cleanup_queue; + } + + priv->gendisk = gendisk; + gendisk->major = ps3vram_major; + gendisk->first_minor = 0; + gendisk->fops = &ps3vram_fops; + gendisk->queue = queue; + gendisk->private_data = dev; + gendisk->driverfs_dev = &dev->core; + strlcpy(gendisk->disk_name, DEVICE_NAME, sizeof(gendisk->disk_name)); + set_capacity(gendisk, priv->size >> 9); + + dev_info(&dev->core, "%s: Using %lu MiB of GPU memory\n", + gendisk->disk_name, get_capacity(gendisk) >> 11); + + add_disk(gendisk); + return 0; + +fail_cleanup_queue: + blk_cleanup_queue(queue); +out_cache_cleanup: + remove_proc_entry(DEVICE_NAME, NULL); + ps3vram_cache_cleanup(dev); +out_unmap_reports: + iounmap(priv->reports); +out_unmap_ctrl: + iounmap(priv->ctrl); +out_unmap_vram: + iounmap(priv->ddr_base); +out_free_context: + lv1_gpu_context_free(priv->context_handle); +out_free_memory: + lv1_gpu_memory_free(priv->memory_handle); +out_close_gpu: + ps3_close_hv_device(dev); +out_free_xdr_buf: + free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE)); +fail_free_priv: + kfree(priv); + dev->core.driver_data = NULL; +fail: + return error; +} + +static int ps3vram_remove(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + del_gendisk(priv->gendisk); + put_disk(priv->gendisk); + blk_cleanup_queue(priv->queue); + remove_proc_entry(DEVICE_NAME, NULL); + ps3vram_cache_cleanup(dev); + iounmap(priv->reports); + iounmap(priv->ctrl); + iounmap(priv->ddr_base); + lv1_gpu_context_free(priv->context_handle); + lv1_gpu_memory_free(priv->memory_handle); + ps3_close_hv_device(dev); + free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE)); + kfree(priv); + dev->core.driver_data = NULL; + return 0; +} + +static struct ps3_system_bus_driver ps3vram = { + .match_id = PS3_MATCH_ID_GPU, + .match_sub_id = PS3_MATCH_SUB_ID_GPU_RAMDISK, + .core.name = DEVICE_NAME, + .core.owner = THIS_MODULE, + .probe = ps3vram_probe, + .remove = ps3vram_remove, + .shutdown = ps3vram_remove, +}; + + +static int __init ps3vram_init(void) +{ + int error; + + if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) + return -ENODEV; + + error = register_blkdev(0, DEVICE_NAME); + if (error <= 0) { + pr_err("%s: register_blkdev failed %d\n", DEVICE_NAME, error); + return error; + } + ps3vram_major = error; + + pr_info("%s: registered block device major %d\n", DEVICE_NAME, + ps3vram_major); + + error = ps3_system_bus_driver_register(&ps3vram); + if (error) + unregister_blkdev(ps3vram_major, DEVICE_NAME); + + return error; +} + +static void __exit ps3vram_exit(void) +{ + ps3_system_bus_driver_unregister(&ps3vram); + unregister_blkdev(ps3vram_major, DEVICE_NAME); +} + +module_init(ps3vram_init); +module_exit(ps3vram_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("PS3 Video RAM Storage Driver"); +MODULE_AUTHOR("Sony Corporation"); +MODULE_ALIAS(PS3_MODULE_ALIAS_GPU_RAMDISK); diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index bc33200535f..6fde0a2e356 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig @@ -120,13 +120,6 @@ config MTD_PHRAM doesn't have access to, memory beyond the mem=xxx limit, nvram, memory on the video card, etc... -config MTD_PS3VRAM - tristate "PS3 video RAM" - depends on FB_PS3 - help - This driver allows you to use excess PS3 video RAM as volatile - storage or system swap. - config MTD_LART tristate "28F160xx flash driver for LART" depends on SA1100_LART diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile index e51521df4e4..0993d5cf392 100644 --- a/drivers/mtd/devices/Makefile +++ b/drivers/mtd/devices/Makefile @@ -16,4 +16,3 @@ obj-$(CONFIG_MTD_LART) += lart.o obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o obj-$(CONFIG_MTD_M25P80) += m25p80.o -obj-$(CONFIG_MTD_PS3VRAM) += ps3vram.o diff --git a/drivers/mtd/devices/ps3vram.c b/drivers/mtd/devices/ps3vram.c deleted file mode 100644 index d21e9beb7ed..00000000000 --- a/drivers/mtd/devices/ps3vram.c +++ /dev/null @@ -1,768 +0,0 @@ -/** - * ps3vram - Use extra PS3 video ram as MTD block device. - * - * Copyright (c) 2007-2008 Jim Paris - * Added support RSX DMA Vivien Chappelier - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define DEVICE_NAME "ps3vram" - -#define XDR_BUF_SIZE (2 * 1024 * 1024) /* XDR buffer (must be 1MiB aligned) */ -#define XDR_IOIF 0x0c000000 - -#define FIFO_BASE XDR_IOIF -#define FIFO_SIZE (64 * 1024) - -#define DMA_PAGE_SIZE (4 * 1024) - -#define CACHE_PAGE_SIZE (256 * 1024) -#define CACHE_PAGE_COUNT ((XDR_BUF_SIZE - FIFO_SIZE) / CACHE_PAGE_SIZE) - -#define CACHE_OFFSET CACHE_PAGE_SIZE -#define FIFO_OFFSET 0 - -#define CTRL_PUT 0x10 -#define CTRL_GET 0x11 -#define CTRL_TOP 0x15 - -#define UPLOAD_SUBCH 1 -#define DOWNLOAD_SUBCH 2 - -#define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN 0x0000030c -#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY 0x00000104 - -#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT 0x601 - -struct mtd_info ps3vram_mtd; - -#define CACHE_PAGE_PRESENT 1 -#define CACHE_PAGE_DIRTY 2 - -struct ps3vram_tag { - unsigned int address; - unsigned int flags; -}; - -struct ps3vram_cache { - unsigned int page_count; - unsigned int page_size; - struct ps3vram_tag *tags; -}; - -struct ps3vram_priv { - u64 memory_handle; - u64 context_handle; - u32 *ctrl; - u32 *reports; - u8 __iomem *ddr_base; - u8 *xdr_buf; - - u32 *fifo_base; - u32 *fifo_ptr; - - struct device *dev; - struct ps3vram_cache cache; - - /* Used to serialize cache/DMA operations */ - struct mutex lock; -}; - -#define DMA_NOTIFIER_HANDLE_BASE 0x66604200 /* first DMA notifier handle */ -#define DMA_NOTIFIER_OFFSET_BASE 0x1000 /* first DMA notifier offset */ -#define DMA_NOTIFIER_SIZE 0x40 -#define NOTIFIER 7 /* notifier used for completion report */ - -/* A trailing '-' means to subtract off ps3fb_videomemory.size */ -char *size = "256M-"; -module_param(size, charp, 0); -MODULE_PARM_DESC(size, "memory size"); - -static u32 *ps3vram_get_notifier(u32 *reports, int notifier) -{ - return (void *) reports + - DMA_NOTIFIER_OFFSET_BASE + - DMA_NOTIFIER_SIZE * notifier; -} - -static void ps3vram_notifier_reset(struct mtd_info *mtd) -{ - int i; - - struct ps3vram_priv *priv = mtd->priv; - u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER); - for (i = 0; i < 4; i++) - notify[i] = 0xffffffff; -} - -static int ps3vram_notifier_wait(struct mtd_info *mtd, unsigned int timeout_ms) -{ - struct ps3vram_priv *priv = mtd->priv; - u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER); - unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); - - do { - if (!notify[3]) - return 0; - msleep(1); - } while (time_before(jiffies, timeout)); - - return -ETIMEDOUT; -} - -static void ps3vram_init_ring(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - - priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET; - priv->ctrl[CTRL_GET] = FIFO_BASE + FIFO_OFFSET; -} - -static int ps3vram_wait_ring(struct mtd_info *mtd, unsigned int timeout_ms) -{ - struct ps3vram_priv *priv = mtd->priv; - unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); - - do { - if (priv->ctrl[CTRL_PUT] == priv->ctrl[CTRL_GET]) - return 0; - msleep(1); - } while (time_before(jiffies, timeout)); - - dev_dbg(priv->dev, "%s:%d: FIFO timeout (%08x/%08x/%08x)\n", __func__, - __LINE__, priv->ctrl[CTRL_PUT], priv->ctrl[CTRL_GET], - priv->ctrl[CTRL_TOP]); - - return -ETIMEDOUT; -} - -static void ps3vram_out_ring(struct ps3vram_priv *priv, u32 data) -{ - *(priv->fifo_ptr)++ = data; -} - -static void ps3vram_begin_ring(struct ps3vram_priv *priv, u32 chan, - u32 tag, u32 size) -{ - ps3vram_out_ring(priv, (size << 18) | (chan << 13) | tag); -} - -static void ps3vram_rewind_ring(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - u64 status; - - ps3vram_out_ring(priv, 0x20000000 | (FIFO_BASE + FIFO_OFFSET)); - - priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET; - - /* asking the HV for a blit will kick the fifo */ - status = lv1_gpu_context_attribute(priv->context_handle, - L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, - 0, 0, 0, 0); - if (status) - dev_err(priv->dev, "%s:%d: lv1_gpu_context_attribute failed\n", - __func__, __LINE__); - - priv->fifo_ptr = priv->fifo_base; -} - -static void ps3vram_fire_ring(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - u64 status; - - mutex_lock(&ps3_gpu_mutex); - - priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET + - (priv->fifo_ptr - priv->fifo_base) * sizeof(u32); - - /* asking the HV for a blit will kick the fifo */ - status = lv1_gpu_context_attribute(priv->context_handle, - L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, - 0, 0, 0, 0); - if (status) - dev_err(priv->dev, "%s:%d: lv1_gpu_context_attribute failed\n", - __func__, __LINE__); - - if ((priv->fifo_ptr - priv->fifo_base) * sizeof(u32) > - FIFO_SIZE - 1024) { - dev_dbg(priv->dev, "%s:%d: fifo full, rewinding\n", __func__, - __LINE__); - ps3vram_wait_ring(mtd, 200); - ps3vram_rewind_ring(mtd); - } - - mutex_unlock(&ps3_gpu_mutex); -} - -static void ps3vram_bind(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - - ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0, 1); - ps3vram_out_ring(priv, 0x31337303); - ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x180, 3); - ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER); - ps3vram_out_ring(priv, 0xfeed0001); /* DMA system RAM instance */ - ps3vram_out_ring(priv, 0xfeed0000); /* DMA video RAM instance */ - - ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0, 1); - ps3vram_out_ring(priv, 0x3137c0de); - ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x180, 3); - ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER); - ps3vram_out_ring(priv, 0xfeed0000); /* DMA video RAM instance */ - ps3vram_out_ring(priv, 0xfeed0001); /* DMA system RAM instance */ - - ps3vram_fire_ring(mtd); -} - -static int ps3vram_upload(struct mtd_info *mtd, unsigned int src_offset, - unsigned int dst_offset, int len, int count) -{ - struct ps3vram_priv *priv = mtd->priv; - - ps3vram_begin_ring(priv, UPLOAD_SUBCH, - NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); - ps3vram_out_ring(priv, XDR_IOIF + src_offset); - ps3vram_out_ring(priv, dst_offset); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, count); - ps3vram_out_ring(priv, (1 << 8) | 1); - ps3vram_out_ring(priv, 0); - - ps3vram_notifier_reset(mtd); - ps3vram_begin_ring(priv, UPLOAD_SUBCH, - NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1); - ps3vram_out_ring(priv, 0); - ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x100, 1); - ps3vram_out_ring(priv, 0); - ps3vram_fire_ring(mtd); - if (ps3vram_notifier_wait(mtd, 200) < 0) { - dev_dbg(priv->dev, "%s:%d: notifier timeout\n", __func__, - __LINE__); - return -1; - } - - return 0; -} - -static int ps3vram_download(struct mtd_info *mtd, unsigned int src_offset, - unsigned int dst_offset, int len, int count) -{ - struct ps3vram_priv *priv = mtd->priv; - - ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, - NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); - ps3vram_out_ring(priv, src_offset); - ps3vram_out_ring(priv, XDR_IOIF + dst_offset); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, count); - ps3vram_out_ring(priv, (1 << 8) | 1); - ps3vram_out_ring(priv, 0); - - ps3vram_notifier_reset(mtd); - ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, - NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1); - ps3vram_out_ring(priv, 0); - ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x100, 1); - ps3vram_out_ring(priv, 0); - ps3vram_fire_ring(mtd); - if (ps3vram_notifier_wait(mtd, 200) < 0) { - dev_dbg(priv->dev, "%s:%d: notifier timeout\n", __func__, - __LINE__); - return -1; - } - - return 0; -} - -static void ps3vram_cache_evict(struct mtd_info *mtd, int entry) -{ - struct ps3vram_priv *priv = mtd->priv; - struct ps3vram_cache *cache = &priv->cache; - - if (cache->tags[entry].flags & CACHE_PAGE_DIRTY) { - dev_dbg(priv->dev, "%s:%d: flushing %d : 0x%08x\n", __func__, - __LINE__, entry, cache->tags[entry].address); - if (ps3vram_upload(mtd, - CACHE_OFFSET + entry * cache->page_size, - cache->tags[entry].address, - DMA_PAGE_SIZE, - cache->page_size / DMA_PAGE_SIZE) < 0) { - dev_dbg(priv->dev, "%s:%d: failed to upload from " - "0x%x to 0x%x size 0x%x\n", __func__, __LINE__, - entry * cache->page_size, - cache->tags[entry].address, cache->page_size); - } - cache->tags[entry].flags &= ~CACHE_PAGE_DIRTY; - } -} - -static void ps3vram_cache_load(struct mtd_info *mtd, int entry, - unsigned int address) -{ - struct ps3vram_priv *priv = mtd->priv; - struct ps3vram_cache *cache = &priv->cache; - - dev_dbg(priv->dev, "%s:%d: fetching %d : 0x%08x\n", __func__, __LINE__, - entry, address); - if (ps3vram_download(mtd, - address, - CACHE_OFFSET + entry * cache->page_size, - DMA_PAGE_SIZE, - cache->page_size / DMA_PAGE_SIZE) < 0) { - dev_err(priv->dev, "%s:%d: failed to download from " - "0x%x to 0x%x size 0x%x\n", __func__, __LINE__, address, - entry * cache->page_size, cache->page_size); - } - - cache->tags[entry].address = address; - cache->tags[entry].flags |= CACHE_PAGE_PRESENT; -} - - -static void ps3vram_cache_flush(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - struct ps3vram_cache *cache = &priv->cache; - int i; - - dev_dbg(priv->dev, "%s:%d: FLUSH\n", __func__, __LINE__); - for (i = 0; i < cache->page_count; i++) { - ps3vram_cache_evict(mtd, i); - cache->tags[i].flags = 0; - } -} - -static unsigned int ps3vram_cache_match(struct mtd_info *mtd, loff_t address) -{ - struct ps3vram_priv *priv = mtd->priv; - struct ps3vram_cache *cache = &priv->cache; - unsigned int base; - unsigned int offset; - int i; - static int counter; - - offset = (unsigned int) (address & (cache->page_size - 1)); - base = (unsigned int) (address - offset); - - /* fully associative check */ - for (i = 0; i < cache->page_count; i++) { - if ((cache->tags[i].flags & CACHE_PAGE_PRESENT) && - cache->tags[i].address == base) { - dev_dbg(priv->dev, "%s:%d: found entry %d : 0x%08x\n", - __func__, __LINE__, i, cache->tags[i].address); - return i; - } - } - - /* choose a random entry */ - i = (jiffies + (counter++)) % cache->page_count; - dev_dbg(priv->dev, "%s:%d: using entry %d\n", __func__, __LINE__, i); - - ps3vram_cache_evict(mtd, i); - ps3vram_cache_load(mtd, i, base); - - return i; -} - -static int ps3vram_cache_init(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - - priv->cache.page_count = CACHE_PAGE_COUNT; - priv->cache.page_size = CACHE_PAGE_SIZE; - priv->cache.tags = kzalloc(sizeof(struct ps3vram_tag) * - CACHE_PAGE_COUNT, GFP_KERNEL); - if (priv->cache.tags == NULL) { - dev_err(priv->dev, "%s:%d: could not allocate cache tags\n", - __func__, __LINE__); - return -ENOMEM; - } - - dev_info(priv->dev, "created ram cache: %d entries, %d KiB each\n", - CACHE_PAGE_COUNT, CACHE_PAGE_SIZE / 1024); - - return 0; -} - -static void ps3vram_cache_cleanup(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - - ps3vram_cache_flush(mtd); - kfree(priv->cache.tags); -} - -static int ps3vram_erase(struct mtd_info *mtd, struct erase_info *instr) -{ - struct ps3vram_priv *priv = mtd->priv; - - if (instr->addr + instr->len > mtd->size) - return -EINVAL; - - mutex_lock(&priv->lock); - - ps3vram_cache_flush(mtd); - - /* Set bytes to 0xFF */ - memset_io(priv->ddr_base + instr->addr, 0xFF, instr->len); - - mutex_unlock(&priv->lock); - - instr->state = MTD_ERASE_DONE; - mtd_erase_callback(instr); - - return 0; -} - -static int ps3vram_read(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf) -{ - struct ps3vram_priv *priv = mtd->priv; - unsigned int cached, count; - - dev_dbg(priv->dev, "%s:%d: from=0x%08x len=0x%zx\n", __func__, __LINE__, - (unsigned int)from, len); - - if (from >= mtd->size) - return -EINVAL; - - if (len > mtd->size - from) - len = mtd->size - from; - - /* Copy from vram to buf */ - count = len; - while (count) { - unsigned int offset, avail; - unsigned int entry; - - offset = (unsigned int) (from & (priv->cache.page_size - 1)); - avail = priv->cache.page_size - offset; - - mutex_lock(&priv->lock); - - entry = ps3vram_cache_match(mtd, from); - cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; - - dev_dbg(priv->dev, "%s:%d: from=%08x cached=%08x offset=%08x " - "avail=%08x count=%08x\n", __func__, __LINE__, - (unsigned int)from, cached, offset, avail, count); - - if (avail > count) - avail = count; - memcpy(buf, priv->xdr_buf + cached, avail); - - mutex_unlock(&priv->lock); - - buf += avail; - count -= avail; - from += avail; - } - - *retlen = len; - return 0; -} - -static int ps3vram_write(struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf) -{ - struct ps3vram_priv *priv = mtd->priv; - unsigned int cached, count; - - if (to >= mtd->size) - return -EINVAL; - - if (len > mtd->size - to) - len = mtd->size - to; - - /* Copy from buf to vram */ - count = len; - while (count) { - unsigned int offset, avail; - unsigned int entry; - - offset = (unsigned int) (to & (priv->cache.page_size - 1)); - avail = priv->cache.page_size - offset; - - mutex_lock(&priv->lock); - - entry = ps3vram_cache_match(mtd, to); - cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; - - dev_dbg(priv->dev, "%s:%d: to=%08x cached=%08x offset=%08x " - "avail=%08x count=%08x\n", __func__, __LINE__, - (unsigned int)to, cached, offset, avail, count); - - if (avail > count) - avail = count; - memcpy(priv->xdr_buf + cached, buf, avail); - - priv->cache.tags[entry].flags |= CACHE_PAGE_DIRTY; - - mutex_unlock(&priv->lock); - - buf += avail; - count -= avail; - to += avail; - } - - *retlen = len; - return 0; -} - -static int __devinit ps3vram_probe(struct ps3_system_bus_device *dev) -{ - struct ps3vram_priv *priv; - int status; - u64 ddr_lpar; - u64 ctrl_lpar; - u64 info_lpar; - u64 reports_lpar; - u64 ddr_size; - u64 reports_size; - int ret = -ENOMEM; - char *rest; - - ret = -EIO; - ps3vram_mtd.priv = kzalloc(sizeof(struct ps3vram_priv), GFP_KERNEL); - if (!ps3vram_mtd.priv) - goto out; - priv = ps3vram_mtd.priv; - - mutex_init(&priv->lock); - priv->dev = &dev->core; - - /* Allocate XDR buffer (1MiB aligned) */ - priv->xdr_buf = (void *)__get_free_pages(GFP_KERNEL, - get_order(XDR_BUF_SIZE)); - if (priv->xdr_buf == NULL) { - dev_dbg(&dev->core, "%s:%d: could not allocate XDR buffer\n", - __func__, __LINE__); - ret = -ENOMEM; - goto out_free_priv; - } - - /* Put FIFO at begginning of XDR buffer */ - priv->fifo_base = (u32 *) (priv->xdr_buf + FIFO_OFFSET); - priv->fifo_ptr = priv->fifo_base; - - /* XXX: Need to open GPU, in case ps3fb or snd_ps3 aren't loaded */ - if (ps3_open_hv_device(dev)) { - dev_err(&dev->core, "%s:%d: ps3_open_hv_device failed\n", - __func__, __LINE__); - ret = -EAGAIN; - goto out_close_gpu; - } - - /* Request memory */ - status = -1; - ddr_size = memparse(size, &rest); - if (*rest == '-') - ddr_size -= ps3fb_videomemory.size; - ddr_size = ALIGN(ddr_size, 1024*1024); - if (ddr_size <= 0) { - dev_err(&dev->core, "%s:%d: specified size is too small\n", - __func__, __LINE__); - ret = -EINVAL; - goto out_close_gpu; - } - - while (ddr_size > 0) { - status = lv1_gpu_memory_allocate(ddr_size, 0, 0, 0, 0, - &priv->memory_handle, - &ddr_lpar); - if (!status) - break; - ddr_size -= 1024*1024; - } - if (status || ddr_size <= 0) { - dev_err(&dev->core, "%s:%d: lv1_gpu_memory_allocate failed\n", - __func__, __LINE__); - ret = -ENOMEM; - goto out_free_xdr_buf; - } - - /* Request context */ - status = lv1_gpu_context_allocate(priv->memory_handle, - 0, - &priv->context_handle, - &ctrl_lpar, - &info_lpar, - &reports_lpar, - &reports_size); - if (status) { - dev_err(&dev->core, "%s:%d: lv1_gpu_context_allocate failed\n", - __func__, __LINE__); - ret = -ENOMEM; - goto out_free_memory; - } - - /* Map XDR buffer to RSX */ - status = lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF, - ps3_mm_phys_to_lpar(__pa(priv->xdr_buf)), - XDR_BUF_SIZE, 0); - if (status) { - dev_err(&dev->core, "%s:%d: lv1_gpu_context_iomap failed\n", - __func__, __LINE__); - ret = -ENOMEM; - goto out_free_context; - } - - priv->ddr_base = ioremap_flags(ddr_lpar, ddr_size, _PAGE_NO_CACHE); - - if (!priv->ddr_base) { - dev_err(&dev->core, "%s:%d: ioremap failed\n", __func__, - __LINE__); - ret = -ENOMEM; - goto out_free_context; - } - - priv->ctrl = ioremap(ctrl_lpar, 64 * 1024); - if (!priv->ctrl) { - dev_err(&dev->core, "%s:%d: ioremap failed\n", __func__, - __LINE__); - ret = -ENOMEM; - goto out_unmap_vram; - } - - priv->reports = ioremap(reports_lpar, reports_size); - if (!priv->reports) { - dev_err(&dev->core, "%s:%d: ioremap failed\n", __func__, - __LINE__); - ret = -ENOMEM; - goto out_unmap_ctrl; - } - - mutex_lock(&ps3_gpu_mutex); - ps3vram_init_ring(&ps3vram_mtd); - mutex_unlock(&ps3_gpu_mutex); - - ps3vram_mtd.name = "ps3vram"; - ps3vram_mtd.size = ddr_size; - ps3vram_mtd.flags = MTD_CAP_RAM; - ps3vram_mtd.erase = ps3vram_erase; - ps3vram_mtd.point = NULL; - ps3vram_mtd.unpoint = NULL; - ps3vram_mtd.read = ps3vram_read; - ps3vram_mtd.write = ps3vram_write; - ps3vram_mtd.owner = THIS_MODULE; - ps3vram_mtd.type = MTD_RAM; - ps3vram_mtd.erasesize = CACHE_PAGE_SIZE; - ps3vram_mtd.writesize = 1; - - ps3vram_bind(&ps3vram_mtd); - - mutex_lock(&ps3_gpu_mutex); - ret = ps3vram_wait_ring(&ps3vram_mtd, 100); - mutex_unlock(&ps3_gpu_mutex); - if (ret < 0) { - dev_err(&dev->core, "%s:%d: failed to initialize channels\n", - __func__, __LINE__); - ret = -ETIMEDOUT; - goto out_unmap_reports; - } - - ps3vram_cache_init(&ps3vram_mtd); - - if (add_mtd_device(&ps3vram_mtd)) { - dev_err(&dev->core, "%s:%d: add_mtd_device failed\n", - __func__, __LINE__); - ret = -EAGAIN; - goto out_cache_cleanup; - } - - dev_info(&dev->core, "reserved %u MiB of gpu memory\n", - (unsigned int)(ddr_size / 1024 / 1024)); - - return 0; - -out_cache_cleanup: - ps3vram_cache_cleanup(&ps3vram_mtd); -out_unmap_reports: - iounmap(priv->reports); -out_unmap_ctrl: - iounmap(priv->ctrl); -out_unmap_vram: - iounmap(priv->ddr_base); -out_free_context: - lv1_gpu_context_free(priv->context_handle); -out_free_memory: - lv1_gpu_memory_free(priv->memory_handle); -out_close_gpu: - ps3_close_hv_device(dev); -out_free_xdr_buf: - free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE)); -out_free_priv: - kfree(ps3vram_mtd.priv); - ps3vram_mtd.priv = NULL; -out: - return ret; -} - -static int ps3vram_shutdown(struct ps3_system_bus_device *dev) -{ - struct ps3vram_priv *priv; - - priv = ps3vram_mtd.priv; - - del_mtd_device(&ps3vram_mtd); - ps3vram_cache_cleanup(&ps3vram_mtd); - iounmap(priv->reports); - iounmap(priv->ctrl); - iounmap(priv->ddr_base); - lv1_gpu_context_free(priv->context_handle); - lv1_gpu_memory_free(priv->memory_handle); - ps3_close_hv_device(dev); - free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE)); - kfree(priv); - return 0; -} - -static struct ps3_system_bus_driver ps3vram_driver = { - .match_id = PS3_MATCH_ID_GPU, - .match_sub_id = PS3_MATCH_SUB_ID_GPU_RAMDISK, - .core.name = DEVICE_NAME, - .core.owner = THIS_MODULE, - .probe = ps3vram_probe, - .remove = ps3vram_shutdown, - .shutdown = ps3vram_shutdown, -}; - -static int __init ps3vram_init(void) -{ - return ps3_system_bus_driver_register(&ps3vram_driver); -} - -static void __exit ps3vram_exit(void) -{ - ps3_system_bus_driver_unregister(&ps3vram_driver); -} - -module_init(ps3vram_init); -module_exit(ps3vram_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jim Paris "); -MODULE_DESCRIPTION("MTD driver for PS3 video RAM"); -MODULE_ALIAS(PS3_MODULE_ALIAS_GPU_RAMDISK); -- GitLab From 8980a7baf93e478205e32ec7d6ef3bfb6c0bdfa7 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 6 Jan 2009 12:57:01 +0100 Subject: [PATCH 3225/4982] parisc: BUG_ON() cleanup - convert a few "if (xx) BUG();" to BUG_ON(xx) - remove a few printk()s, as we get a backtrace with BUG_ON() anyway Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- arch/parisc/kernel/cache.c | 5 +---- arch/parisc/kernel/pci-dma.c | 22 ++++++---------------- arch/parisc/mm/init.c | 6 ++---- 3 files changed, 9 insertions(+), 24 deletions(-) diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index 5259d8c2067..837530ea32e 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -551,10 +551,7 @@ void flush_cache_range(struct vm_area_struct *vma, { int sr3; - if (!vma->vm_mm->context) { - BUG(); - return; - } + BUG_ON(!vma->vm_mm->context); sr3 = mfsp(3); if (vma->vm_mm->context == sr3) { diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c index df47895db82..7d927eac932 100644 --- a/arch/parisc/kernel/pci-dma.c +++ b/arch/parisc/kernel/pci-dma.c @@ -447,10 +447,7 @@ static void pa11_dma_free_consistent (struct device *dev, size_t size, void *vad static dma_addr_t pa11_dma_map_single(struct device *dev, void *addr, size_t size, enum dma_data_direction direction) { - if (direction == DMA_NONE) { - printk(KERN_ERR "pa11_dma_map_single(PCI_DMA_NONE) called by %p\n", __builtin_return_address(0)); - BUG(); - } + BUG_ON(direction == DMA_NONE); flush_kernel_dcache_range((unsigned long) addr, size); return virt_to_phys(addr); @@ -458,10 +455,7 @@ static dma_addr_t pa11_dma_map_single(struct device *dev, void *addr, size_t siz static void pa11_dma_unmap_single(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) { - if (direction == DMA_NONE) { - printk(KERN_ERR "pa11_dma_unmap_single(PCI_DMA_NONE) called by %p\n", __builtin_return_address(0)); - BUG(); - } + BUG_ON(direction == DMA_NONE); if (direction == DMA_TO_DEVICE) return; @@ -480,8 +474,7 @@ static int pa11_dma_map_sg(struct device *dev, struct scatterlist *sglist, int n { int i; - if (direction == DMA_NONE) - BUG(); + BUG_ON(direction == DMA_NONE); for (i = 0; i < nents; i++, sglist++ ) { unsigned long vaddr = sg_virt_addr(sglist); @@ -496,8 +489,7 @@ static void pa11_dma_unmap_sg(struct device *dev, struct scatterlist *sglist, in { int i; - if (direction == DMA_NONE) - BUG(); + BUG_ON(direction == DMA_NONE); if (direction == DMA_TO_DEVICE) return; @@ -511,16 +503,14 @@ static void pa11_dma_unmap_sg(struct device *dev, struct scatterlist *sglist, in static void pa11_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, unsigned long offset, size_t size, enum dma_data_direction direction) { - if (direction == DMA_NONE) - BUG(); + BUG_ON(direction == DMA_NONE); flush_kernel_dcache_range((unsigned long) phys_to_virt(dma_handle) + offset, size); } static void pa11_dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, unsigned long offset, size_t size, enum dma_data_direction direction) { - if (direction == DMA_NONE) - BUG(); + BUG_ON(direction == DMA_NONE); flush_kernel_dcache_range((unsigned long) phys_to_virt(dma_handle) + offset, size); } diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 7c155c254e7..9d704d9831d 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -304,10 +304,8 @@ static void __init setup_bootmem(void) */ max_low_pfn = max_pfn; - if ((bootmap_pfn - bootmap_start_pfn) != bootmap_pages) { - printk(KERN_WARNING "WARNING! bootmap sizing is messed up!\n"); - BUG(); - } + /* bootmap sizing messed up? */ + BUG_ON((bootmap_pfn - bootmap_start_pfn) != bootmap_pages); /* reserve PAGE0 pdc memory, kernel text/data/bss & bootmap */ -- GitLab From bfe4f4f800ccbb499a1120735016a20d3feacd4f Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Fri, 9 Jan 2009 18:57:06 -0600 Subject: [PATCH 3226/4982] parisc: remove klist iterators commit 11c3b5c3e08f4d855cbef52883c266b9ab9df879 Author: Greg Kroah-Hartman Date: Tue Dec 16 12:24:56 2008 -0800 driver core: move klist_children into private structure Broke our parisc build pretty badly because we touch the klists directly in three cases (AGP, SBA and GSC). Although GregKH will revert this patch, there's no reason we should be using the iterators directly, we can just move to the standard device_for_each_child() API. Signed-off-by: James Bottomley Tested-by: Helge Deller Tested-by: Kyle McMartin Signed-off-by: Kyle McMartin --- drivers/char/agp/parisc-agp.c | 23 +++++++------ drivers/parisc/gsc.c | 39 ++++++++++++---------- drivers/parisc/sba_iommu.c | 61 ++++++++++++++++++++--------------- 3 files changed, 68 insertions(+), 55 deletions(-) diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c index db60539bf67..699e3422ad9 100644 --- a/drivers/char/agp/parisc-agp.c +++ b/drivers/char/agp/parisc-agp.c @@ -359,9 +359,16 @@ fail: return error; } -static struct device *next_device(struct klist_iter *i) { - struct klist_node * n = klist_next(i); - return n ? container_of(n, struct device, knode_parent) : NULL; +static int +find_quicksilver(struct device *dev, void *data) +{ + struct parisc_device **lba = data; + struct parisc_device *padev = to_parisc_device(dev); + + if (IS_QUICKSILVER(padev)) + *lba = padev; + + return 0; } static int @@ -372,8 +379,6 @@ parisc_agp_init(void) int err = -1; struct parisc_device *sba = NULL, *lba = NULL; struct lba_device *lbadev = NULL; - struct device *dev = NULL; - struct klist_iter i; if (!sba_list) goto out; @@ -386,13 +391,7 @@ parisc_agp_init(void) } /* Now search our Pluto for our precious AGP device... */ - klist_iter_init(&sba->dev.klist_children, &i); - while ((dev = next_device(&i))) { - struct parisc_device *padev = to_parisc_device(dev); - if (IS_QUICKSILVER(padev)) - lba = padev; - } - klist_iter_exit(&i); + device_for_each_child(&sba->dev, &lba, find_quicksilver); if (!lba) { printk(KERN_INFO DRVPFX "No AGP devices found.\n"); diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c index e76db9e4d50..d3363291769 100644 --- a/drivers/parisc/gsc.c +++ b/drivers/parisc/gsc.c @@ -186,29 +186,34 @@ void gsc_asic_assign_irq(struct gsc_asic *asic, int local_irq, int *irqp) *irqp = irq; } -static struct device *next_device(struct klist_iter *i) +struct gsc_fixup_struct { + void (*choose_irq)(struct parisc_device *, void *); + void *ctrl; +}; + +static int gsc_fixup_irqs_callback(struct device *dev, void *data) { - struct klist_node * n = klist_next(i); - return n ? container_of(n, struct device, knode_parent) : NULL; + struct parisc_device *padev = to_parisc_device(dev); + struct gsc_fixup_struct *gf = data; + + /* work-around for 715/64 and others which have parent + at path [5] and children at path [5/0/x] */ + if (padev->id.hw_type == HPHW_FAULTY) + gsc_fixup_irqs(padev, gf->ctrl, gf->choose_irq); + gf->choose_irq(padev, gf->ctrl); + + return 0; } void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl, void (*choose_irq)(struct parisc_device *, void *)) { - struct device *dev; - struct klist_iter i; - - klist_iter_init(&parent->dev.klist_children, &i); - while ((dev = next_device(&i))) { - struct parisc_device *padev = to_parisc_device(dev); - - /* work-around for 715/64 and others which have parent - at path [5] and children at path [5/0/x] */ - if (padev->id.hw_type == HPHW_FAULTY) - return gsc_fixup_irqs(padev, ctrl, choose_irq); - choose_irq(padev, ctrl); - } - klist_iter_exit(&i); + struct gsc_fixup_struct data = { + .choose_irq = choose_irq, + .ctrl = ctrl, + }; + + device_for_each_child(&parent->dev, &data, gsc_fixup_irqs_callback); } int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic) diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index a70cf16ee1a..6aad8546fd2 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -1206,31 +1206,49 @@ sba_alloc_pdir(unsigned int pdir_size) return (void *) pdir_base; } -static struct device *next_device(struct klist_iter *i) +struct ibase_data_struct { + struct ioc *ioc; + int ioc_num; +}; + +static int setup_ibase_imask_callback(struct device *dev, void *data) { - struct klist_node * n = klist_next(i); - return n ? container_of(n, struct device, knode_parent) : NULL; + /* lba_set_iregs() is in drivers/parisc/lba_pci.c */ + extern void lba_set_iregs(struct parisc_device *, u32, u32); + struct parisc_device *lba = to_parisc_device(dev); + struct ibase_data_struct *ibd = data; + int rope_num = (lba->hpa.start >> 13) & 0xf; + if (rope_num >> 3 == ibd->ioc_num) + lba_set_iregs(lba, ibd->ioc->ibase, ibd->ioc->imask); + return 0; } /* setup Mercury or Elroy IBASE/IMASK registers. */ static void setup_ibase_imask(struct parisc_device *sba, struct ioc *ioc, int ioc_num) { - /* lba_set_iregs() is in drivers/parisc/lba_pci.c */ - extern void lba_set_iregs(struct parisc_device *, u32, u32); - struct device *dev; - struct klist_iter i; - - klist_iter_init(&sba->dev.klist_children, &i); - while ((dev = next_device(&i))) { - struct parisc_device *lba = to_parisc_device(dev); - int rope_num = (lba->hpa.start >> 13) & 0xf; - if (rope_num >> 3 == ioc_num) - lba_set_iregs(lba, ioc->ibase, ioc->imask); - } - klist_iter_exit(&i); + struct ibase_data_struct ibase_data = { + .ioc = ioc, + .ioc_num = ioc_num, + }; + + device_for_each_child(&sba->dev, &ibase_data, + setup_ibase_imask_callback); } +#ifdef SBA_AGP_SUPPORT +static int +sba_ioc_find_quicksilver(struct device *dev, void *data) +{ + int *agp_found = data; + struct parisc_device *lba = to_parisc_device(dev); + + if (IS_QUICKSILVER(lba)) + *agp_found = 1; + return 0; +} +#endif + static void sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) { @@ -1332,9 +1350,6 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) WRITE_REG(ioc->ibase | 31, ioc->ioc_hpa + IOC_PCOM); #ifdef SBA_AGP_SUPPORT -{ - struct klist_iter i; - struct device *dev = NULL; /* ** If an AGP device is present, only use half of the IOV space @@ -1344,13 +1359,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ** We program the next pdir index after we stop w/ a key for ** the GART code to handshake on. */ - klist_iter_init(&sba->dev.klist_children, &i); - while ((dev = next_device(&i))) { - struct parisc_device *lba = to_parisc_device(dev); - if (IS_QUICKSILVER(lba)) - agp_found = 1; - } - klist_iter_exit(&i); + device_for_each_child(&sba->dev, &agp_found, sba_ioc_find_quicksilver); if (agp_found && sba_reserve_agpgart) { printk(KERN_INFO "%s: reserving %dMb of IOVA space for agpgart\n", -- GitLab From 24dc029f71c1411c5974a79848d68bb3e34263b9 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 13 Jan 2009 20:51:29 +0100 Subject: [PATCH 3227/4982] parisc: fix section mismatch warnings Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- arch/parisc/kernel/firmware.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c index 03f26bd75bd..f6d241238a7 100644 --- a/arch/parisc/kernel/firmware.c +++ b/arch/parisc/kernel/firmware.c @@ -151,7 +151,7 @@ static void convert_to_wide(unsigned long *addr) } #ifdef CONFIG_64BIT -void __init set_firmware_width_unlocked(void) +void __cpuinit set_firmware_width_unlocked(void) { int ret; @@ -168,7 +168,7 @@ void __init set_firmware_width_unlocked(void) * This function must be called before any pdc_* function that uses the * convert_to_wide function. */ -void __init set_firmware_width(void) +void __cpuinit set_firmware_width(void) { unsigned long flags; spin_lock_irqsave(&pdc_lock, flags); @@ -176,11 +176,11 @@ void __init set_firmware_width(void) spin_unlock_irqrestore(&pdc_lock, flags); } #else -void __init set_firmware_width_unlocked(void) { +void __cpuinit set_firmware_width_unlocked(void) { return; } -void __init set_firmware_width(void) { +void __cpuinit set_firmware_width(void) { return; } #endif /*CONFIG_64BIT*/ @@ -302,7 +302,7 @@ int pdc_chassis_warn(unsigned long *warn) return retval; } -int __init pdc_coproc_cfg_unlocked(struct pdc_coproc_cfg *pdc_coproc_info) +int __cpuinit pdc_coproc_cfg_unlocked(struct pdc_coproc_cfg *pdc_coproc_info) { int ret; @@ -323,7 +323,7 @@ int __init pdc_coproc_cfg_unlocked(struct pdc_coproc_cfg *pdc_coproc_info) * This PDC call returns the presence and status of all the coprocessors * attached to the processor. */ -int __init pdc_coproc_cfg(struct pdc_coproc_cfg *pdc_coproc_info) +int __cpuinit pdc_coproc_cfg(struct pdc_coproc_cfg *pdc_coproc_info) { int ret; unsigned long flags; -- GitLab From e448372c79c49ef80df23496339ce0915abef76e Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 13 Jan 2009 20:52:46 +0100 Subject: [PATCH 3228/4982] parisc: fix `struct pt_regs' declared inside parameter list warning Fix those compile warnings: uaccess.h:244: warning: `struct pt_regs' declared inside parameter list uaccess.h:244: warning: its scope is only this definition or declaration, which is probably not what you want Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- arch/parisc/include/asm/uaccess.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h index 1c6dbb6f6e5..cd4c0b2a8e7 100644 --- a/arch/parisc/include/asm/uaccess.h +++ b/arch/parisc/include/asm/uaccess.h @@ -241,6 +241,7 @@ unsigned long copy_in_user(void __user *dst, const void __user *src, unsigned lo #define __copy_to_user_inatomic __copy_to_user #define __copy_from_user_inatomic __copy_from_user +struct pt_regs; int fixup_exception(struct pt_regs *regs); #endif /* __PARISC_UACCESS_H */ -- GitLab From ddd1f6c66dd964c106377f2be37b318794f112f4 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 13 Jan 2009 20:54:25 +0100 Subject: [PATCH 3229/4982] parisc: remove unused local out_putf label Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- arch/parisc/hpux/fs.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/parisc/hpux/fs.c b/arch/parisc/hpux/fs.c index bd9a4db3bd4..5cbe9f9e5d9 100644 --- a/arch/parisc/hpux/fs.c +++ b/arch/parisc/hpux/fs.c @@ -137,7 +137,6 @@ int hpux_getdents(unsigned int fd, struct hpux_dirent __user *dirent, unsigned i error = count - buf.count; } -out_putf: fput(file); out: return error; -- GitLab From 7f384ce780c6091968fc848b14f17b45cb849e14 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 13 Jan 2009 21:14:51 +0100 Subject: [PATCH 3230/4982] parisc: fix dev_printk() compile warnings for accessing a device struct Fix compile warnings: drivers/scsi/zalon.c: In function `zalon_probe': drivers/scsi/zalon.c:140: warning: passing arg 1 of `dev_driver_string' from incompatible pointer type drivers/scsi/zalon.c:140: warning: passing arg 1 of `dev_name' from incompatible pointer type Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- drivers/scsi/lasi700.c | 2 +- drivers/scsi/zalon.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c index 4a4e6954ec7..f23c4ca9a2e 100644 --- a/drivers/scsi/lasi700.c +++ b/drivers/scsi/lasi700.c @@ -103,7 +103,7 @@ lasi700_probe(struct parisc_device *dev) hostdata = kzalloc(sizeof(*hostdata), GFP_KERNEL); if (!hostdata) { - dev_printk(KERN_ERR, dev, "Failed to allocate host data\n"); + dev_printk(KERN_ERR, &dev->dev, "Failed to allocate host data\n"); return -ENOMEM; } diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c index a8d61a62522..97f3158fa7b 100644 --- a/drivers/scsi/zalon.c +++ b/drivers/scsi/zalon.c @@ -137,7 +137,7 @@ zalon_probe(struct parisc_device *dev) goto fail; if (request_irq(dev->irq, ncr53c8xx_intr, IRQF_SHARED, "zalon", host)) { - dev_printk(KERN_ERR, dev, "irq problem with %d, detaching\n ", + dev_printk(KERN_ERR, &dev->dev, "irq problem with %d, detaching\n ", dev->irq); goto fail; } -- GitLab From 2cfeb9a6755d4d7be1026422b6aced48e3bad492 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 18 Jan 2009 18:13:53 +0100 Subject: [PATCH 3231/4982] parisc: add braces around arguments in assembler macros Add braces around the macro arguments, else for example "shl %r1, 5-3, %r2" would not expand to what you would assume. Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- arch/parisc/include/asm/assembly.h | 10 +++++----- arch/parisc/kernel/entry.S | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/parisc/include/asm/assembly.h b/arch/parisc/include/asm/assembly.h index ffb208840ec..ab7cc373ee5 100644 --- a/arch/parisc/include/asm/assembly.h +++ b/arch/parisc/include/asm/assembly.h @@ -129,27 +129,27 @@ /* Shift Left - note the r and t can NOT be the same! */ .macro shl r, sa, t - dep,z \r, 31-\sa, 32-\sa, \t + dep,z \r, 31-(\sa), 32-(\sa), \t .endm /* The PA 2.0 shift left */ .macro shlw r, sa, t - depw,z \r, 31-\sa, 32-\sa, \t + depw,z \r, 31-(\sa), 32-(\sa), \t .endm /* And the PA 2.0W shift left */ .macro shld r, sa, t - depd,z \r, 63-\sa, 64-\sa, \t + depd,z \r, 63-(\sa), 64-(\sa), \t .endm /* Shift Right - note the r and t can NOT be the same! */ .macro shr r, sa, t - extru \r, 31-\sa, 32-\sa, \t + extru \r, 31-(\sa), 32-(\sa), \t .endm /* pa20w version of shift right */ .macro shrd r, sa, t - extrd,u \r, 63-\sa, 64-\sa, \t + extrd,u \r, 63-(\sa), 64-(\sa), \t .endm /* load 32-bit 'value' into 'reg' compensating for the ldil diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index d1fa4edd2d8..0db9fdcb770 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -368,7 +368,7 @@ * abstractions for the macros */ .macro EXTR reg1,start,length,reg2 #ifdef CONFIG_64BIT - extrd,u \reg1,32+\start,\length,\reg2 + extrd,u \reg1,32+(\start),\length,\reg2 #else extrw,u \reg1,\start,\length,\reg2 #endif @@ -376,7 +376,7 @@ .macro DEP reg1,start,length,reg2 #ifdef CONFIG_64BIT - depd \reg1,32+\start,\length,\reg2 + depd \reg1,32+(\start),\length,\reg2 #else depw \reg1,\start,\length,\reg2 #endif @@ -384,7 +384,7 @@ .macro DEPI val,start,length,reg #ifdef CONFIG_64BIT - depdi \val,32+\start,\length,\reg + depdi \val,32+(\start),\length,\reg #else depwi \val,\start,\length,\reg #endif -- GitLab From c1da90fd099531e9449019dc53a5a02a5eaef2b4 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Mon, 26 Jan 2009 22:24:38 +0100 Subject: [PATCH 3232/4982] parisc: fix 64bit build Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- arch/parisc/include/asm/assembly.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/parisc/include/asm/assembly.h b/arch/parisc/include/asm/assembly.h index ab7cc373ee5..89fb40005e3 100644 --- a/arch/parisc/include/asm/assembly.h +++ b/arch/parisc/include/asm/assembly.h @@ -79,6 +79,7 @@ #include #include +#include #include -- GitLab From 9785d646c10b0707412516ffe56b71b9eb18861f Mon Sep 17 00:00:00 2001 From: Grant Grundler Date: Wed, 28 Jan 2009 22:30:55 -0700 Subject: [PATCH 3233/4982] parisc: fix wrong assumption about bus->self Kenji Kaneshige posted a patch series to linux-pci to fix a wrong assumption about pci_bus->self==NULL for all PCI host bus controllers. While PARISC platforms to not behave this way, I prefer to have the code consistent across architectures. The following patch replaces pci_bus->self with pci_bus->parent when used as a test to check for "root bus controller". Signed-off-by: Grant Grundler Signed-off-by: Kyle McMartin --- drivers/parisc/dino.c | 2 +- drivers/parisc/iosapic.c | 9 ++++----- drivers/parisc/lba_pci.c | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index d539d9df88e..f79266cd00e 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -587,7 +587,7 @@ dino_fixup_bus(struct pci_bus *bus) bus->resource[i+1] = &res[i]; } - } else if(bus->self) { + } else if (bus->parent) { int i; pci_read_bridge_bases(bus); diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 0797659ee01..1cdfdea5d7e 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -487,7 +487,7 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev) } /* Check if pcidev behind a PPB */ - if (NULL != pcidev->bus->self) { + if (pcidev->bus->parent) { /* Convert pcidev INTR_PIN into something we ** can lookup in the IRT. */ @@ -523,10 +523,9 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev) #endif /* PCI_BRIDGE_FUNCS */ /* - ** Locate the host slot the PPB nearest the Host bus - ** adapter. - */ - while (NULL != p->parent->self) + * Locate the host slot of the PPB. + */ + while (p->parent->parent) p = p->parent; intr_slot = PCI_SLOT(p->self->devfn); diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index d8233de8c75..59fbbf12836 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -644,7 +644,7 @@ lba_fixup_bus(struct pci_bus *bus) ** Properly Setup MMIO resources for this bus. ** pci_alloc_primary_bus() mangles this. */ - if (bus->self) { + if (bus->parent) { int i; /* PCI-PCI Bridge */ pci_read_bridge_bases(bus); @@ -802,7 +802,7 @@ lba_fixup_bus(struct pci_bus *bus) ** Can't fixup here anyway....garr... */ if (fbb_enable) { - if (bus->self) { + if (bus->parent) { u8 control; /* enable on PPB */ (void) pci_read_config_byte(bus->self, PCI_BRIDGE_CONTROL, &control); -- GitLab From 763461194817bc39905c7c41d08e8d9548a3916d Mon Sep 17 00:00:00 2001 From: Grant Grundler Date: Mon, 1 Dec 2008 00:21:35 -0700 Subject: [PATCH 3234/4982] parisc: update MAINTAINERS Signed-off-By: Grant Grundler Reviewed-by: Matthew Wilcox Acked-by: Helge Deller Signed-off-by: Kyle McMartin --- MAINTAINERS | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 61aeb5aae24..4a1cfca4968 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3350,10 +3350,8 @@ S: Maintained PARISC ARCHITECTURE P: Kyle McMartin M: kyle@mcmartin.ca -P: Matthew Wilcox -M: matthew@wil.cx -P: Grant Grundler -M: grundler@parisc-linux.org +P: Helge Deller +M: deller@gmx.de L: linux-parisc@vger.kernel.org W: http://www.parisc-linux.org/ T: git kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6.git -- GitLab From 5a8247ca4c6441cafbb852cb1048d1056734a90c Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Tue, 13 Jan 2009 03:05:25 +0000 Subject: [PATCH 3235/4982] parisc: update parisc for new irq_desc Impact: cleanup, update to new cpumask API Irq_desc.affinity and irq_desc.pending_mask are now cpumask_var_t's so access to them should be using the new cpumask API. Signed-off-by: Mike Travis Signed-off-by: Kyle McMartin --- arch/parisc/kernel/irq.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index ac2c822928c..49482806863 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -120,7 +120,7 @@ int cpu_check_affinity(unsigned int irq, cpumask_t *dest) if (CHECK_IRQ_PER_CPU(irq)) { /* Bad linux design decision. The mask has already * been set; we must reset it */ - irq_desc[irq].affinity = CPU_MASK_ALL; + cpumask_setall(irq_desc[irq].affinity); return -EINVAL; } @@ -136,7 +136,7 @@ static void cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest) if (cpu_check_affinity(irq, dest)) return; - irq_desc[irq].affinity = *dest; + cpumask_copy(irq_desc[irq].affinity, dest); } #endif @@ -295,7 +295,7 @@ int txn_alloc_irq(unsigned int bits_wide) unsigned long txn_affinity_addr(unsigned int irq, int cpu) { #ifdef CONFIG_SMP - irq_desc[irq].affinity = cpumask_of_cpu(cpu); + cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu)); #endif return per_cpu(cpu_data, cpu).txn_addr; @@ -352,7 +352,7 @@ void do_cpu_irq_mask(struct pt_regs *regs) irq = eirr_to_irq(eirr_val); #ifdef CONFIG_SMP - dest = irq_desc[irq].affinity; + cpumask_copy(&dest, irq_desc[irq].affinity); if (CHECK_IRQ_PER_CPU(irq_desc[irq].status) && !cpu_isset(smp_processor_id(), dest)) { int cpu = first_cpu(dest); -- GitLab From 7c4be70e6d07582a111a1b66942c8a1d45528dfb Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 16 Feb 2009 02:53:03 -0500 Subject: [PATCH 3236/4982] parisc: fix use of new cpumask api in irq.c cpumask api needs to take a pointer to irq_desc[cpu].affinity Signed-off-by: Kyle McMartin --- arch/parisc/kernel/irq.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index 49482806863..a572112f5ab 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -120,7 +120,7 @@ int cpu_check_affinity(unsigned int irq, cpumask_t *dest) if (CHECK_IRQ_PER_CPU(irq)) { /* Bad linux design decision. The mask has already * been set; we must reset it */ - cpumask_setall(irq_desc[irq].affinity); + cpumask_setall(&irq_desc[irq].affinity); return -EINVAL; } @@ -136,7 +136,7 @@ static void cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest) if (cpu_check_affinity(irq, dest)) return; - cpumask_copy(irq_desc[irq].affinity, dest); + cpumask_copy(&irq_desc[irq].affinity, dest); } #endif @@ -295,7 +295,7 @@ int txn_alloc_irq(unsigned int bits_wide) unsigned long txn_affinity_addr(unsigned int irq, int cpu) { #ifdef CONFIG_SMP - cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu)); + cpumask_copy(&irq_desc[irq].affinity, cpumask_of(cpu)); #endif return per_cpu(cpu_data, cpu).txn_addr; @@ -352,7 +352,7 @@ void do_cpu_irq_mask(struct pt_regs *regs) irq = eirr_to_irq(eirr_val); #ifdef CONFIG_SMP - cpumask_copy(&dest, irq_desc[irq].affinity); + cpumask_copy(&dest, &irq_desc[irq].affinity); if (CHECK_IRQ_PER_CPU(irq_desc[irq].status) && !cpu_isset(smp_processor_id(), dest)) { int cpu = first_cpu(dest); -- GitLab From 9dfe914da83ebc88f85d94b4d30d0e45882766d1 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 16 Feb 2009 03:05:02 -0500 Subject: [PATCH 3237/4982] parisc: convert (read|write)bwlq to inlines Kills the 'value computed but not used' due to leX_to_cpu. Signed-off-by: Kyle McMartin --- arch/parisc/include/asm/io.h | 42 ++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/arch/parisc/include/asm/io.h b/arch/parisc/include/asm/io.h index d3031d1f9d0..1fa905ea53d 100644 --- a/arch/parisc/include/asm/io.h +++ b/arch/parisc/include/asm/io.h @@ -174,15 +174,39 @@ static inline void __raw_writeq(unsigned long long b, volatile void __iomem *add *(volatile unsigned long long __force *) addr = b; } -/* readb can never be const, so use __fswab instead of le*_to_cpu */ -#define readb(addr) __raw_readb(addr) -#define readw(addr) le16_to_cpu(__raw_readw(addr)) -#define readl(addr) le32_to_cpu(__raw_readl(addr)) -#define readq(addr) le64_to_cpu(__raw_readq(addr)) -#define writeb(b, addr) __raw_writeb(b, addr) -#define writew(b, addr) __raw_writew(cpu_to_le16(b), addr) -#define writel(b, addr) __raw_writel(cpu_to_le32(b), addr) -#define writeq(b, addr) __raw_writeq(cpu_to_le64(b), addr) +static inline unsigned char readb(const volatile void __iomem *addr) +{ + return __raw_readb(addr); +} +static inline unsigned short readw(const volatile void __iomem *addr) +{ + return le16_to_cpu(__raw_readw(addr)); +} +static inline unsigned int readl(const volatile void __iomem *addr) +{ + return le32_to_cpu(__raw_readl(addr)); +} +static inline unsigned long long readq(const volatile void __iomem *addr) +{ + return le64_to_cpu(__raw_readq(addr)); +} + +static inline void writeb(unsigned char b, volatile void __iomem *addr) +{ + __raw_writeb(b, addr); +} +static inline void writew(unsigned short w, volatile void __iomem *addr) +{ + __raw_writew(cpu_to_le16(w), addr); +} +static inline void writel(unsigned int l, volatile void __iomem *addr) +{ + __raw_writel(cpu_to_le32(l), addr); +} +static inline void writeq(unsigned long long q, volatile void __iomem *addr) +{ + __raw_writeq(cpu_to_le64(q), addr); +} #define readb_relaxed(addr) readb(addr) #define readw_relaxed(addr) readw(addr) -- GitLab From 8b6649c575e0d8312f62fe643ae43558892da2e1 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 16 Feb 2009 03:20:54 -0500 Subject: [PATCH 3238/4982] parisc: convert cpu_check_affinity to new cpumask api cpumask arg to the affinity function is now const, sort that out through the irq_desc implementations. Signed-off-by: Kyle McMartin --- arch/parisc/include/asm/irq.h | 2 +- arch/parisc/kernel/irq.c | 12 +++++++----- drivers/parisc/iosapic.c | 7 +++++-- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/arch/parisc/include/asm/irq.h b/arch/parisc/include/asm/irq.h index 399c81981ed..dfa26b67f91 100644 --- a/arch/parisc/include/asm/irq.h +++ b/arch/parisc/include/asm/irq.h @@ -49,7 +49,7 @@ extern unsigned long txn_alloc_addr(unsigned int); extern unsigned long txn_affinity_addr(unsigned int irq, int cpu); extern int cpu_claim_irq(unsigned int irq, struct irq_chip *, void *); -extern int cpu_check_affinity(unsigned int irq, cpumask_t *dest); +extern int cpu_check_affinity(unsigned int irq, const struct cpumask *dest); /* soft power switch support (power.c) */ extern struct tasklet_struct power_tasklet; diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index a572112f5ab..29e70e16ede 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -112,7 +112,7 @@ void cpu_end_irq(unsigned int irq) } #ifdef CONFIG_SMP -int cpu_check_affinity(unsigned int irq, cpumask_t *dest) +int cpu_check_affinity(unsigned int irq, const struct cpumask *dest) { int cpu_dest; @@ -126,17 +126,19 @@ int cpu_check_affinity(unsigned int irq, cpumask_t *dest) /* whatever mask they set, we just allow one CPU */ cpu_dest = first_cpu(*dest); - *dest = cpumask_of_cpu(cpu_dest); - return 0; + return cpu_dest; } static void cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest) { - if (cpu_check_affinity(irq, dest)) + int cpu_dest; + + cpu_dest = cpu_check_affinity(irq, dest); + if (cpu_dest < 0) return; - cpumask_copy(&irq_desc[irq].affinity, dest); + cpumask_copy(&irq_desc[irq].affinity, &cpumask_of_cpu(cpu_dest)); } #endif diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 1cdfdea5d7e..501aaf1f253 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -708,11 +708,14 @@ static void iosapic_set_affinity_irq(unsigned int irq, struct vector_info *vi = iosapic_get_vector(irq); u32 d0, d1, dummy_d0; unsigned long flags; + int dest_cpu; - if (cpu_check_affinity(irq, dest)) + dest_cpu = cpu_check_affinity(irq, dest); + if (dest_cpu < 0) return; - vi->txn_addr = txn_affinity_addr(irq, cpumask_first(dest)); + irq_desc[irq].affinity = cpumask_of_cpu(dest_cpu); + vi->txn_addr = txn_affinity_addr(irq, dest_cpu); spin_lock_irqsave(&iosapic_lock, flags); /* d1 contains the destination CPU, so only want to set that -- GitLab From d4995244bd4c02eb7bea3c63aee81a2f2b64910e Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Mon, 26 Jan 2009 03:53:16 +0000 Subject: [PATCH 3239/4982] parisc: dino: struct device - replace bus_id with dev_name(), dev_set_name() Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers Signed-off-by: Kyle McMartin --- drivers/parisc/dino.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index f79266cd00e..bb5a1c9597c 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -479,7 +479,7 @@ dino_card_setup(struct pci_bus *bus, void __iomem *base_addr) res = &dino_dev->hba.lmmio_space; res->flags = IORESOURCE_MEM; size = scnprintf(name, sizeof(name), "Dino LMMIO (%s)", - bus->bridge->bus_id); + dev_name(bus->bridge)); res->name = kmalloc(size+1, GFP_KERNEL); if(res->name) strcpy((char *)res->name, name); @@ -493,7 +493,7 @@ dino_card_setup(struct pci_bus *bus, void __iomem *base_addr) struct list_head *ln, *tmp_ln; printk(KERN_ERR "Dino: cannot attach bus %s\n", - bus->bridge->bus_id); + dev_name(bus->bridge)); /* kill the bus, we can't do anything with it */ list_for_each_safe(ln, tmp_ln, &bus->devices) { struct pci_dev *dev = pci_dev_b(ln); @@ -611,12 +611,12 @@ dino_fixup_bus(struct pci_bus *bus) } DBG("DEBUG %s assigning %d [0x%lx,0x%lx]\n", - bus->self->dev.bus_id, i, + dev_name(&bus->self->dev), i, bus->self->resource[i].start, bus->self->resource[i].end); pci_assign_resource(bus->self, i); DBG("DEBUG %s after assign %d [0x%lx,0x%lx]\n", - bus->self->dev.bus_id, i, + dev_name(&bus->self->dev), i, bus->self->resource[i].start, bus->self->resource[i].end); } @@ -1026,7 +1026,8 @@ static int __init dino_probe(struct parisc_device *dev) dino_current_bus = bus->subordinate + 1; pci_bus_assign_resources(bus); } else { - printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (probably duplicate bus number %d)\n", dev->dev.bus_id, dino_current_bus); + printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (probably duplicate bus number %d)\n", + dev_name(&dev->dev), dino_current_bus); /* increment the bus number in case of duplicates */ dino_current_bus++; } -- GitLab From 0cb385e3ff54ee095d9873209f4da764dfb17fec Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Tue, 17 Feb 2009 12:42:52 -0500 Subject: [PATCH 3240/4982] parisc: define x->x mmio accessors Bloody inconsiderate driver writers... Signed-off-by: Kyle McMartin --- arch/parisc/include/asm/io.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/parisc/include/asm/io.h b/arch/parisc/include/asm/io.h index 1fa905ea53d..1f6d2ae7aba 100644 --- a/arch/parisc/include/asm/io.h +++ b/arch/parisc/include/asm/io.h @@ -208,6 +208,15 @@ static inline void writeq(unsigned long long q, volatile void __iomem *addr) __raw_writeq(cpu_to_le64(q), addr); } +#define readb readb +#define readw readw +#define readl readl +#define readq readq +#define writeb writeb +#define writew writew +#define writel writel +#define writeq writeq + #define readb_relaxed(addr) readb(addr) #define readw_relaxed(addr) readw(addr) #define readl_relaxed(addr) readl(addr) -- GitLab From e8f208e8f727515bc605f241a5f854b41f77d0ed Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Fri, 13 Mar 2009 01:33:34 -0400 Subject: [PATCH 3241/4982] parisc: update defconfigs Signed-off-by: Kyle McMartin --- arch/parisc/configs/712_defconfig | 429 ++++++++++++------- arch/parisc/configs/a500_defconfig | 490 ++++++++++++++------- arch/parisc/configs/b180_defconfig | 433 ++++++++++++------- arch/parisc/configs/c3000_defconfig | 575 ++++++++++++++++--------- arch/parisc/configs/default_defconfig | 585 +++++++++++++++++--------- 5 files changed, 1681 insertions(+), 831 deletions(-) diff --git a/arch/parisc/configs/712_defconfig b/arch/parisc/configs/712_defconfig index 9fc96e72716..bf34a28895f 100644 --- a/arch/parisc/configs/712_defconfig +++ b/arch/parisc/configs/712_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.23 -# Fri Oct 12 21:00:07 2007 +# Linux kernel version: 2.6.29-rc8 +# Fri Mar 13 01:32:55 2009 # CONFIG_PARISC=y CONFIG_MMU=y @@ -33,17 +33,35 @@ CONFIG_SYSVIPC_SYSCTL=y CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set -# CONFIG_USER_NS is not set # CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=16 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_NET_NS is not set CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y # CONFIG_EMBEDDED is not set CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y @@ -55,29 +73,38 @@ CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y -CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y +CONFIG_AIO=y CONFIG_VM_EVENT_COUNTERS=y +CONFIG_COMPAT_BRK=y CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set +CONFIG_PROFILING=y +CONFIG_TRACEPOINTS=y +# CONFIG_MARKERS is not set +CONFIG_OPROFILE=m +CONFIG_HAVE_OPROFILE=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y +CONFIG_INIT_ALL_POSSIBLE=y CONFIG_BLOCK=y # CONFIG_LBD is not set # CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set # CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -91,6 +118,7 @@ CONFIG_DEFAULT_AS=y # CONFIG_DEFAULT_CFQ is not set # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="anticipatory" +# CONFIG_FREEZER is not set # # Processor type and features @@ -114,17 +142,19 @@ CONFIG_HZ_250=y # CONFIG_HZ_300 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=250 +# CONFIG_SCHED_HRTICK is not set CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y # CONFIG_DISCONTIGMEM_MANUAL is not set # CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4096 -# CONFIG_RESOURCES_64BIT is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y # CONFIG_HPUX is not set # @@ -138,10 +168,6 @@ CONFIG_GSC_LASI=y # CONFIG_EISA is not set # CONFIG_PCI is not set # CONFIG_ARCH_SUPPORTS_MSI is not set - -# -# PCCARD (PCMCIA/CardBus) support -# # CONFIG_PCCARD is not set # @@ -156,16 +182,15 @@ CONFIG_PDC_STABLE=y # Executable file formats # CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set CONFIG_BINFMT_MISC=m - -# -# Networking -# CONFIG_NET=y # # Networking options # +CONFIG_COMPAT_NET_DEV_OPS=y CONFIG_PACKET=y CONFIG_PACKET_MMAP=y CONFIG_UNIX=y @@ -173,6 +198,7 @@ CONFIG_XFRM=y CONFIG_XFRM_USER=m # CONFIG_XFRM_SUB_POLICY is not set # CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set CONFIG_NET_KEY=m # CONFIG_NET_KEY_MIGRATE is not set CONFIG_INET=y @@ -203,25 +229,25 @@ CONFIG_INET_TCP_DIAG=m CONFIG_TCP_CONG_CUBIC=y CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_TCP_MD5SIG is not set -# CONFIG_IP_VS is not set # CONFIG_IPV6 is not set -# CONFIG_INET6_XFRM_TUNNEL is not set -# CONFIG_INET6_TUNNEL is not set # CONFIG_NETWORK_SECMARK is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y # # Core Netfilter Configuration # -# CONFIG_NETFILTER_NETLINK is not set -# CONFIG_NF_CONNTRACK_ENABLED is not set +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set # CONFIG_NF_CONNTRACK is not set # CONFIG_NETFILTER_XTABLES is not set +# CONFIG_IP_VS is not set # # IP: Netfilter Configuration # +# CONFIG_NF_DEFRAG_IPV4 is not set CONFIG_IP_NF_QUEUE=m # CONFIG_IP_NF_IPTABLES is not set # CONFIG_IP_NF_ARPTABLES is not set @@ -230,6 +256,7 @@ CONFIG_IP_NF_QUEUE=m # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set CONFIG_LLC=m @@ -240,28 +267,26 @@ CONFIG_LLC2=m # CONFIG_LAPB is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# # CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set # # Network testing # CONFIG_NET_PKTGEN=m # CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set # CONFIG_IRDA is not set # CONFIG_BT is not set # CONFIG_AF_RXRPC is not set - -# -# Wireless -# +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y # CONFIG_CFG80211 is not set +CONFIG_WIRELESS_OLD_REGULATORY=y # CONFIG_WIRELESS_EXT is not set +# CONFIG_LIB80211 is not set # CONFIG_MAC80211 is not set -# CONFIG_IEEE80211 is not set +# CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set @@ -276,6 +301,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set @@ -298,11 +325,19 @@ CONFIG_BLK_DEV_CRYPTOLOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=6144 -CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +# CONFIG_BLK_DEV_XIP is not set # CONFIG_CDROM_PKTCDVD is not set CONFIG_ATA_OVER_ETH=m +# CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# # CONFIG_EEPROM_93CX6 is not set +CONFIG_HAVE_IDE=y # CONFIG_IDE is not set # @@ -342,14 +377,17 @@ CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_FC_ATTRS is not set CONFIG_SCSI_ISCSI_ATTRS=m # CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set +# CONFIG_LIBFC is not set # CONFIG_SCSI_PPA is not set # CONFIG_SCSI_IMM is not set CONFIG_SCSI_LASI700=y CONFIG_53C700_LE_ON_BE=y # CONFIG_SCSI_ZALON is not set CONFIG_SCSI_DEBUG=m +# CONFIG_SCSI_DH is not set # CONFIG_ATA is not set CONFIG_MD=y CONFIG_BLK_DEV_MD=m @@ -362,7 +400,6 @@ CONFIG_MD_RAID1=m # CONFIG_MD_FAULTY is not set # CONFIG_BLK_DEV_DM is not set CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set CONFIG_DUMMY=m CONFIG_BONDING=m # CONFIG_MACVLAN is not set @@ -377,6 +414,9 @@ CONFIG_LASI_82596=y # CONFIG_IBM_NEW_EMAC_RGMII is not set # CONFIG_IBM_NEW_EMAC_TAH is not set # CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set # CONFIG_B44 is not set # CONFIG_NET_POCKET is not set CONFIG_NETDEV_1000=y @@ -387,6 +427,11 @@ CONFIG_NETDEV_10000=y # # CONFIG_WLAN_PRE80211 is not set # CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# # CONFIG_WAN is not set # CONFIG_PLIP is not set CONFIG_PPP=m @@ -401,7 +446,6 @@ CONFIG_PPPOE=m # CONFIG_PPPOL2TP is not set # CONFIG_SLIP is not set CONFIG_SLHC=m -# CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set @@ -423,7 +467,6 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set # CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_EVBUG is not set @@ -446,8 +489,8 @@ CONFIG_MOUSE_PS2=y CONFIG_MOUSE_PS2_ALPS=y CONFIG_MOUSE_PS2_LOGIPS2PP=y CONFIG_MOUSE_PS2_SYNAPTICS=y -CONFIG_MOUSE_PS2_LIFEBOOK=y CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set # CONFIG_MOUSE_PS2_TOUCHKIT is not set CONFIG_MOUSE_SERIAL=m # CONFIG_MOUSE_VSXXXAA is not set @@ -474,9 +517,11 @@ CONFIG_SERIO_LIBPS2=y # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y # CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y # CONFIG_SERIAL_NONSTANDARD is not set # @@ -501,72 +546,76 @@ CONFIG_PDC_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=64 CONFIG_PRINTER=m # CONFIG_LP_CONSOLE is not set CONFIG_PPDEV=m -# CONFIG_TIPAR is not set # CONFIG_IPMI_HANDLER is not set -# CONFIG_WATCHDOG is not set # CONFIG_HW_RANDOM is not set -CONFIG_GEN_RTC=y -CONFIG_GEN_RTC_X=y # CONFIG_R3964 is not set CONFIG_RAW_DRIVER=y CONFIG_MAX_RAW_DEVS=256 # CONFIG_TCG_TPM is not set # CONFIG_I2C is not set - -# -# SPI support -# # CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y # # Sonics Silicon Backplane # -CONFIG_SSB_POSSIBLE=y # CONFIG_SSB is not set # # Multifunction device drivers # +# CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_REGULATOR is not set # # Multimedia devices # + +# +# Multimedia core support +# # CONFIG_VIDEO_DEV is not set # CONFIG_DVB_CORE is not set -# CONFIG_DAB is not set +# CONFIG_VIDEO_MEDIA is not set # -# Graphics support +# Multimedia drivers # -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_DAB is not set # -# Display device support +# Graphics support # -# CONFIG_DISPLAY_SUPPORT is not set # CONFIG_VGASTATE is not set CONFIG_VIDEO_OUTPUT_CONTROL=m CONFIG_FB=y # CONFIG_FIRMWARE_EDID is not set # CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set # CONFIG_FB_SYS_FILLRECT is not set # CONFIG_FB_SYS_COPYAREA is not set # CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set -CONFIG_FB_DEFERRED_IO=y # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -579,6 +628,14 @@ CONFIG_FB_TILEBLITTING=y CONFIG_FB_STI=y # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set # # Console display driver support @@ -606,15 +663,8 @@ CONFIG_LOGO=y # CONFIG_LOGO_LINUX_VGA16 is not set # CONFIG_LOGO_LINUX_CLUT224 is not set CONFIG_LOGO_PARISC_CLUT224=y - -# -# Sound -# CONFIG_SOUND=y - -# -# Advanced Linux Sound Architecture -# +CONFIG_SOUND_OSS_CORE=y CONFIG_SND=y CONFIG_SND_TIMER=y CONFIG_SND_PCM=y @@ -630,10 +680,7 @@ CONFIG_SND_SUPPORT_OLD_API=y CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set - -# -# Generic devices -# +CONFIG_SND_DRIVERS=y # CONFIG_SND_DUMMY is not set # CONFIG_SND_VIRMIDI is not set # CONFIG_SND_MTPAV is not set @@ -641,63 +688,82 @@ CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_SERIAL_U16550 is not set # CONFIG_SND_MPU401 is not set # CONFIG_SND_PORTMAN2X4 is not set - -# -# GSC devices -# +CONFIG_SND_GSC=y CONFIG_SND_HARMONY=y - -# -# System on Chip audio support -# # CONFIG_SND_SOC is not set - -# -# SoC Audio support for SuperH -# - -# -# Open Sound System -# # CONFIG_SOUND_PRIME is not set CONFIG_HID_SUPPORT=y CONFIG_HID=y CONFIG_HID_DEBUG=y +# CONFIG_HIDRAW is not set +# CONFIG_HID_PID is not set + +# +# Special HID drivers +# +CONFIG_HID_COMPAT=y CONFIG_USB_SUPPORT=y # CONFIG_USB_ARCH_HAS_HCD is not set # CONFIG_USB_ARCH_HAS_OHCI is not set # CONFIG_USB_ARCH_HAS_EHCI is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# Enable Host or Gadget support to see Inventra options # # -# USB Gadget Support +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; # # CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# # CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set -# CONFIG_RTC_CLASS is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set # -# DMA Engine support +# RTC interfaces # -# CONFIG_DMA_ENGINE is not set +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set # -# DMA Clients +# SPI RTC drivers # # -# DMA Devices -# -# CONFIG_AUXDISPLAY is not set +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_V3020 is not set # -# Userspace I/O +# on-CPU RTC drivers # +CONFIG_RTC_DRV_PARISC=y +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set +# CONFIG_STAGING is not set # # File systems @@ -707,7 +773,7 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set -# CONFIG_EXT4DEV_FS is not set +# CONFIG_EXT4_FS is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set # CONFIG_REISERFS_FS is not set @@ -717,19 +783,18 @@ CONFIG_JFS_FS=m # CONFIG_JFS_DEBUG is not set # CONFIG_JFS_STATISTICS is not set CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y CONFIG_XFS_FS=m # CONFIG_XFS_QUOTA is not set -# CONFIG_XFS_SECURITY is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set -# CONFIG_GFS2_FS is not set +# CONFIG_XFS_DEBUG is not set # CONFIG_OCFS2_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set CONFIG_AUTOFS4_FS=y # CONFIG_FUSE_FS is not set @@ -759,16 +824,13 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y # CONFIG_CONFIGFS_FS is not set - -# -# Miscellaneous filesystems -# +CONFIG_MISC_FILESYSTEMS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_ECRYPT_FS is not set @@ -778,35 +840,34 @@ CONFIG_RAMFS=y # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set CONFIG_UFS_FS=m # CONFIG_UFS_FS_WRITE is not set # CONFIG_UFS_DEBUG is not set - -# -# Network File Systems -# +CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set CONFIG_NFS_V4=y -CONFIG_NFS_DIRECTIO=y +CONFIG_ROOT_NFS=y CONFIG_NFSD=m CONFIG_NFSD_V3=y # CONFIG_NFSD_V3_ACL is not set CONFIG_NFSD_V4=y -CONFIG_NFSD_TCP=y -CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=m CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y -# CONFIG_SUNRPC_BIND34 is not set +# CONFIG_SUNRPC_REGISTER_V4 is not set CONFIG_RPCSEC_GSS_KRB5=y CONFIG_RPCSEC_GSS_SPKM3=m CONFIG_SMB_FS=m @@ -815,6 +876,7 @@ CONFIG_SMB_NLS_REMOTE="cp437" CONFIG_CIFS=m # CONFIG_CIFS_STATS is not set # CONFIG_CIFS_WEAK_PW_HASH is not set +# CONFIG_CIFS_UPCALL is not set # CONFIG_CIFS_XATTR is not set # CONFIG_CIFS_DEBUG2 is not set # CONFIG_CIFS_EXPERIMENTAL is not set @@ -827,10 +889,6 @@ CONFIG_CIFS=m # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y - -# -# Native Language Support -# CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" CONFIG_NLS_CODEPAGE_437=m @@ -871,33 +929,28 @@ CONFIG_NLS_ISO8859_15=m CONFIG_NLS_KOI8_R=m CONFIG_NLS_KOI8_U=m CONFIG_NLS_UTF8=m - -# -# Distributed Lock Manager -# # CONFIG_DLM is not set -# -# Profiling support -# -CONFIG_PROFILING=y -CONFIG_OPROFILE=m - # # Kernel hacking # # CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 CONFIG_MAGIC_SYSRQ=y # CONFIG_UNUSED_SYMBOLS is not set -# CONFIG_DEBUG_FS is not set +CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SHIRQ is not set CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set @@ -909,10 +962,32 @@ CONFIG_DEBUG_MUTEXES=y CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y # CONFIG_DEBUG_LIST is not set -CONFIG_FORCED_INLINING=y +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_FAULT_INJECTION is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_NOP_TRACER=y +CONFIG_RING_BUFFER=y +CONFIG_TRACING=y + +# +# Tracers +# +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_FTRACE_STARTUP_TEST is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set CONFIG_DEBUG_RODATA=y # @@ -921,57 +996,113 @@ CONFIG_DEBUG_RODATA=y CONFIG_KEYS=y CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=m +CONFIG_CRYPTO_AEAD2=y CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_GF128MUL is not set +CONFIG_CRYPTO_NULL=m +# CONFIG_CRYPTO_CRYPTD is not set +CONFIG_CRYPTO_AUTHENC=m +CONFIG_CRYPTO_TEST=m + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=m +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set -CONFIG_CRYPTO_NULL=m + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=m CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=m +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=m CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_TGR192=m -# CONFIG_CRYPTO_GF128MUL is not set -CONFIG_CRYPTO_ECB=m -CONFIG_CRYPTO_CBC=y -# CONFIG_CRYPTO_PCBC is not set -# CONFIG_CRYPTO_LRW is not set -# CONFIG_CRYPTO_XTS is not set -# CONFIG_CRYPTO_CRYPTD is not set -CONFIG_CRYPTO_DES=y -# CONFIG_CRYPTO_FCRYPT is not set -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_TWOFISH_COMMON=m -CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_WP512=m + +# +# Ciphers +# CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_BLOWFISH=m +# CONFIG_CRYPTO_CAMELLIA is not set CONFIG_CRYPTO_CAST5=m CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_TEA=m -CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set CONFIG_CRYPTO_KHAZAD=m -CONFIG_CRYPTO_ANUBIS=m +# CONFIG_CRYPTO_SALSA20 is not set # CONFIG_CRYPTO_SEED is not set +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_TWOFISH_COMMON=m + +# +# Compression +# CONFIG_CRYPTO_DEFLATE=m -CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_CRC32C=m -# CONFIG_CRYPTO_CAMELLIA is not set -CONFIG_CRYPTO_TEST=m -# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set # # Library routines # CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y CONFIG_CRC_CCITT=m # CONFIG_CRC16 is not set -# CONFIG_CRC_ITU_T is not set +# CONFIG_CRC_T10DIF is not set +CONFIG_CRC_ITU_T=m CONFIG_CRC32=y # CONFIG_CRC7 is not set CONFIG_LIBCRC32C=m diff --git a/arch/parisc/configs/a500_defconfig b/arch/parisc/configs/a500_defconfig index ddacc72e38f..f12e4b8349d 100644 --- a/arch/parisc/configs/a500_defconfig +++ b/arch/parisc/configs/a500_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.23 -# Fri Oct 12 21:12:44 2007 +# Linux kernel version: 2.6.29-rc8 +# Fri Mar 13 01:32:56 2009 # CONFIG_PARISC=y CONFIG_MMU=y @@ -34,18 +34,30 @@ CONFIG_SYSVIPC_SYSCTL=y CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set -# CONFIG_USER_NS is not set # CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=16 -# CONFIG_CPUSETS is not set +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y CONFIG_EMBEDDED=y CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y @@ -57,28 +69,40 @@ CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y -CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y +CONFIG_AIO=y CONFIG_VM_EVENT_COUNTERS=y +CONFIG_PCI_QUIRKS=y +CONFIG_COMPAT_BRK=y CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set +CONFIG_PROFILING=y +CONFIG_TRACEPOINTS=y +# CONFIG_MARKERS is not set +CONFIG_OPROFILE=m +CONFIG_HAVE_OPROFILE=y +CONFIG_USE_GENERIC_SMP_HELPERS=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y +CONFIG_INIT_ALL_POSSIBLE=y CONFIG_STOP_MACHINE=y CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set CONFIG_BLOCK_COMPAT=y # @@ -93,6 +117,7 @@ CONFIG_IOSCHED_CFQ=y CONFIG_DEFAULT_CFQ=y # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_FREEZER is not set # # Processor type and features @@ -118,12 +143,12 @@ CONFIG_NODES_SHIFT=3 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set -CONFIG_PREEMPT_BKL=y # CONFIG_HZ_100 is not set CONFIG_HZ_250=y # CONFIG_HZ_300 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=250 +# CONFIG_SCHED_HRTICK is not set CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_FLATMEM_MANUAL is not set CONFIG_DISCONTIGMEM_MANUAL=y @@ -131,11 +156,12 @@ CONFIG_DISCONTIGMEM_MANUAL=y CONFIG_DISCONTIGMEM=y CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_NEED_MULTIPLE_NODES=y -# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 -CONFIG_RESOURCES_64BIT=y +CONFIG_PHYS_ADDR_T_64BIT=y CONFIG_ZONE_DMA_FLAG=0 CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y CONFIG_COMPAT=y CONFIG_NR_CPUS=8 @@ -145,14 +171,13 @@ CONFIG_NR_CPUS=8 # CONFIG_GSC is not set CONFIG_PCI=y # CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_PCI_LEGACY=y # CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_STUB is not set CONFIG_PCI_LBA=y CONFIG_IOSAPIC=y CONFIG_IOMMU_SBA=y - -# -# PCCARD (PCMCIA/CardBus) support -# +CONFIG_IOMMU_HELPER=y CONFIG_PCCARD=m # CONFIG_PCMCIA_DEBUG is not set CONFIG_PCMCIA=m @@ -187,16 +212,15 @@ CONFIG_PDC_STABLE=y # Executable file formats # CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set # CONFIG_BINFMT_MISC is not set - -# -# Networking -# CONFIG_NET=y # # Networking options # +CONFIG_COMPAT_NET_DEV_OPS=y CONFIG_PACKET=y CONFIG_PACKET_MMAP=y CONFIG_UNIX=y @@ -204,6 +228,8 @@ CONFIG_XFRM=y CONFIG_XFRM_USER=m # CONFIG_XFRM_SUB_POLICY is not set # CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=m CONFIG_NET_KEY=m # CONFIG_NET_KEY_MIGRATE is not set CONFIG_INET=y @@ -234,7 +260,6 @@ CONFIG_INET_TCP_DIAG=y CONFIG_TCP_CONG_CUBIC=y CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_TCP_MD5SIG is not set -# CONFIG_IP_VS is not set CONFIG_IPV6=m # CONFIG_IPV6_PRIVACY is not set # CONFIG_IPV6_ROUTER_PREF is not set @@ -250,66 +275,72 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=m CONFIG_INET6_XFRM_MODE_BEET=m # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set CONFIG_IPV6_SIT=m +CONFIG_IPV6_NDISC_NODETYPE=y CONFIG_IPV6_TUNNEL=m # CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set # CONFIG_NETWORK_SECMARK is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y # # Core Netfilter Configuration # -# CONFIG_NETFILTER_NETLINK is not set -# CONFIG_NF_CONNTRACK_ENABLED is not set +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set # CONFIG_NF_CONNTRACK is not set CONFIG_NETFILTER_XTABLES=m # CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set # CONFIG_NETFILTER_XT_TARGET_DSCP is not set # CONFIG_NETFILTER_XT_TARGET_MARK is not set -# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set # CONFIG_NETFILTER_XT_TARGET_NFLOG is not set +# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set # CONFIG_NETFILTER_XT_TARGET_TRACE is not set # CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set # CONFIG_NETFILTER_XT_MATCH_COMMENT is not set # CONFIG_NETFILTER_XT_MATCH_DCCP is not set # CONFIG_NETFILTER_XT_MATCH_DSCP is not set # CONFIG_NETFILTER_XT_MATCH_ESP is not set +# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set # CONFIG_NETFILTER_XT_MATCH_LENGTH is not set # CONFIG_NETFILTER_XT_MATCH_LIMIT is not set # CONFIG_NETFILTER_XT_MATCH_MAC is not set # CONFIG_NETFILTER_XT_MATCH_MARK is not set -# CONFIG_NETFILTER_XT_MATCH_POLICY is not set # CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set +# CONFIG_NETFILTER_XT_MATCH_POLICY is not set # CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set # CONFIG_NETFILTER_XT_MATCH_QUOTA is not set +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set # CONFIG_NETFILTER_XT_MATCH_REALM is not set +# CONFIG_NETFILTER_XT_MATCH_RECENT is not set # CONFIG_NETFILTER_XT_MATCH_SCTP is not set # CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set # CONFIG_NETFILTER_XT_MATCH_STRING is not set # CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set # CONFIG_NETFILTER_XT_MATCH_TIME is not set # CONFIG_NETFILTER_XT_MATCH_U32 is not set -# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set +# CONFIG_IP_VS is not set # # IP: Netfilter Configuration # +# CONFIG_NF_DEFRAG_IPV4 is not set CONFIG_IP_NF_QUEUE=m CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_IPRANGE=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_RECENT=m -CONFIG_IP_NF_MATCH_ECN=m +# CONFIG_IP_NF_MATCH_ADDRTYPE is not set # CONFIG_IP_NF_MATCH_AH is not set +CONFIG_IP_NF_MATCH_ECN=m CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_OWNER=m -# CONFIG_IP_NF_MATCH_ADDRTYPE is not set CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m CONFIG_IP_NF_TARGET_LOG=m CONFIG_IP_NF_TARGET_ULOG=m CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m CONFIG_IP_NF_TARGET_ECN=m # CONFIG_IP_NF_TARGET_TTL is not set CONFIG_IP_NF_RAW=m @@ -318,33 +349,30 @@ CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m # -# IPv6: Netfilter Configuration (EXPERIMENTAL) +# IPv6: Netfilter Configuration # # CONFIG_IP6_NF_QUEUE is not set CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_RT=m -CONFIG_IP6_NF_MATCH_OPTS=m +# CONFIG_IP6_NF_MATCH_AH is not set +# CONFIG_IP6_NF_MATCH_EUI64 is not set CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m CONFIG_IP6_NF_MATCH_HL=m -# CONFIG_IP6_NF_MATCH_OWNER is not set CONFIG_IP6_NF_MATCH_IPV6HEADER=m -# CONFIG_IP6_NF_MATCH_AH is not set # CONFIG_IP6_NF_MATCH_MH is not set -# CONFIG_IP6_NF_MATCH_EUI64 is not set -CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_MATCH_RT=m CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_FILTER=m CONFIG_IP6_NF_TARGET_REJECT=m CONFIG_IP6_NF_MANGLE=m # CONFIG_IP6_NF_TARGET_HL is not set CONFIG_IP6_NF_RAW=m CONFIG_IP_DCCP=m CONFIG_INET_DCCP_DIAG=m -CONFIG_IP_DCCP_ACKVEC=y # # DCCP CCIDs Configuration (EXPERIMENTAL) # -CONFIG_IP_DCCP_CCID2=m # CONFIG_IP_DCCP_CCID2_DEBUG is not set # CONFIG_IP_DCCP_CCID3 is not set @@ -356,6 +384,7 @@ CONFIG_IP_DCCP_CCID2=m # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set CONFIG_LLC=m @@ -366,28 +395,26 @@ CONFIG_LLC2=m # CONFIG_LAPB is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# # CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set # # Network testing # CONFIG_NET_PKTGEN=m # CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set # CONFIG_IRDA is not set # CONFIG_BT is not set # CONFIG_AF_RXRPC is not set - -# -# Wireless -# +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y # CONFIG_CFG80211 is not set +CONFIG_WIRELESS_OLD_REGULATORY=y # CONFIG_WIRELESS_EXT is not set +# CONFIG_LIB80211 is not set # CONFIG_MAC80211 is not set -# CONFIG_IEEE80211 is not set +# CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set @@ -402,6 +429,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set @@ -421,14 +450,23 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=6144 -CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +# CONFIG_BLK_DEV_XIP is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_PHANTOM is not set -# CONFIG_EEPROM_93CX6 is not set # CONFIG_SGI_IOC4 is not set # CONFIG_TIFM_CORE is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_93CX6 is not set +CONFIG_HAVE_IDE=y # CONFIG_IDE is not set # @@ -468,8 +506,10 @@ CONFIG_SCSI_SPI_ATTRS=y CONFIG_SCSI_FC_ATTRS=m CONFIG_SCSI_ISCSI_ATTRS=m # CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_CXGB3_ISCSI is not set # CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_ACARD is not set @@ -478,16 +518,21 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_ARCMSR is not set # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set # CONFIG_SCSI_HPTIOP is not set +# CONFIG_LIBFC is not set +# CONFIG_FCOE is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_IPS is not set # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_MVSAS is not set # CONFIG_SCSI_STEX is not set CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 @@ -503,9 +548,11 @@ CONFIG_SCSI_QLOGIC_1280=m CONFIG_SCSI_DEBUG=m # CONFIG_SCSI_SRP is not set # CONFIG_SCSI_LOWLEVEL_PCMCIA is not set +# CONFIG_SCSI_DH is not set # CONFIG_ATA is not set CONFIG_MD=y CONFIG_BLK_DEV_MD=y +CONFIG_MD_AUTODETECT=y CONFIG_MD_LINEAR=y CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y @@ -514,10 +561,6 @@ CONFIG_MD_RAID1=y # CONFIG_MD_MULTIPATH is not set # CONFIG_MD_FAULTY is not set # CONFIG_BLK_DEV_DM is not set - -# -# Fusion MPT device support -# CONFIG_FUSION=y CONFIG_FUSION_SPI=m CONFIG_FUSION_FC=m @@ -529,20 +572,40 @@ CONFIG_FUSION_CTL=m # # IEEE 1394 (FireWire) support # + +# +# Enable only one of the two stacks, unless you know what you are doing +# # CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set # CONFIG_I2O is not set CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set CONFIG_DUMMY=m CONFIG_BONDING=m # CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set CONFIG_TUN=m # CONFIG_VETH is not set -# CONFIG_IP1000 is not set # CONFIG_ARCNET is not set -# CONFIG_PHYLIB is not set +CONFIG_PHYLIB=m + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MDIO_BITBANG is not set CONFIG_NET_ETHERNET=y CONFIG_MII=m # CONFIG_HAPPYMEAL is not set @@ -567,33 +630,38 @@ CONFIG_HP100=m # CONFIG_IBM_NEW_EMAC_RGMII is not set # CONFIG_IBM_NEW_EMAC_TAH is not set # CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set CONFIG_NET_PCI=y CONFIG_PCNET32=m -# CONFIG_PCNET32_NAPI is not set # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set -# CONFIG_EEPRO100 is not set CONFIG_E100=m # CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set # CONFIG_NE2K_PCI is not set # CONFIG_8139CP is not set # CONFIG_8139TOO is not set +# CONFIG_R6040 is not set # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set +# CONFIG_SMSC9420 is not set # CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set # CONFIG_SC92031 is not set +# CONFIG_ATL2 is not set CONFIG_NETDEV_1000=y CONFIG_ACENIC=m CONFIG_ACENIC_OMIT_TIGON_I=y # CONFIG_DL2K is not set CONFIG_E1000=m -CONFIG_E1000_NAPI=y -# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_E1000E is not set +# CONFIG_IP1000 is not set +# CONFIG_IGB is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set @@ -601,23 +669,31 @@ CONFIG_E1000_NAPI=y # CONFIG_SIS190 is not set # CONFIG_SKGE is not set # CONFIG_SKY2 is not set -# CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set CONFIG_TIGON3=m # CONFIG_BNX2 is not set # CONFIG_QLA3XXX is not set # CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_ATL1C is not set +# CONFIG_JME is not set CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set +CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_CHELSIO_T3 is not set +# CONFIG_ENIC is not set # CONFIG_IXGBE is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set # CONFIG_NETXEN_NIC is not set # CONFIG_NIU is not set +# CONFIG_MLX4_EN is not set # CONFIG_MLX4_CORE is not set # CONFIG_TEHUTI is not set +# CONFIG_BNX2X is not set +# CONFIG_QLGE is not set +# CONFIG_SFC is not set # CONFIG_TR is not set # @@ -625,6 +701,11 @@ CONFIG_NETDEV_10000=y # # CONFIG_WLAN_PRE80211 is not set # CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# CONFIG_NET_PCMCIA=y CONFIG_PCMCIA_3C589=m CONFIG_PCMCIA_3C574=m @@ -650,7 +731,6 @@ CONFIG_PPP_BSDCOMP=m # CONFIG_SLIP is not set CONFIG_SLHC=m # CONFIG_NET_FC is not set -# CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set @@ -669,7 +749,6 @@ CONFIG_INPUT=y # # CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set # CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_EVBUG is not set @@ -693,10 +772,13 @@ CONFIG_INPUT=y # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y # CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y # CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set # # Serial drivers @@ -721,17 +803,12 @@ CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set # CONFIG_LEGACY_PTYS is not set # CONFIG_IPMI_HANDLER is not set -# CONFIG_WATCHDOG is not set # CONFIG_HW_RANDOM is not set -CONFIG_GEN_RTC=y -CONFIG_GEN_RTC_X=y # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -CONFIG_AGP=y -CONFIG_AGP_PARISC=y -# CONFIG_DRM is not set # # PCMCIA character devices @@ -739,51 +816,66 @@ CONFIG_AGP_PARISC=y # CONFIG_SYNCLINK_CS is not set # CONFIG_CARDMAN_4000 is not set # CONFIG_CARDMAN_4040 is not set +# CONFIG_IPWIRELESS is not set CONFIG_RAW_DRIVER=y CONFIG_MAX_RAW_DEVS=256 # CONFIG_TCG_TPM is not set CONFIG_DEVPORT=y # CONFIG_I2C is not set - -# -# SPI support -# # CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y # # Sonics Silicon Backplane # -CONFIG_SSB_POSSIBLE=y # CONFIG_SSB is not set # # Multifunction device drivers # +# CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_REGULATOR is not set # # Multimedia devices # + +# +# Multimedia core support +# # CONFIG_VIDEO_DEV is not set # CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# # CONFIG_DAB is not set # # Graphics support # +CONFIG_AGP=y +CONFIG_AGP_PARISC=y +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set # CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Display device support # # CONFIG_DISPLAY_SUPPORT is not set -# CONFIG_VGASTATE is not set -# CONFIG_VIDEO_OUTPUT_CONTROL is not set -# CONFIG_FB is not set # # Console display driver support @@ -792,50 +884,83 @@ CONFIG_DUMMY_CONSOLE=y CONFIG_DUMMY_CONSOLE_COLUMNS=160 CONFIG_DUMMY_CONSOLE_ROWS=64 # CONFIG_STI_CONSOLE is not set - -# -# Sound -# # CONFIG_SOUND is not set CONFIG_HID_SUPPORT=y CONFIG_HID=y # CONFIG_HID_DEBUG is not set +# CONFIG_HIDRAW is not set +# CONFIG_HID_PID is not set + +# +# Special HID drivers +# +CONFIG_HID_COMPAT=y CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y CONFIG_USB_ARCH_HAS_EHCI=y # CONFIG_USB is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# Enable Host or Gadget support to see Inventra options # # -# USB Gadget Support +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; # # CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_UWB is not set # CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set -# CONFIG_RTC_CLASS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set # -# DMA Engine support +# RTC interfaces # -# CONFIG_DMA_ENGINE is not set +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set # -# DMA Clients +# SPI RTC drivers # # -# DMA Devices -# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_V3020 is not set # -# Userspace I/O +# on-CPU RTC drivers # +CONFIG_RTC_DRV_PARISC=y +# CONFIG_DMADEVICES is not set # CONFIG_UIO is not set +# CONFIG_STAGING is not set # # File systems @@ -845,7 +970,7 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set -# CONFIG_EXT4DEV_FS is not set +# CONFIG_EXT4_FS is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set # CONFIG_REISERFS_FS is not set @@ -855,19 +980,19 @@ CONFIG_JFS_FS=m # CONFIG_JFS_DEBUG is not set # CONFIG_JFS_STATISTICS is not set CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y CONFIG_XFS_FS=m # CONFIG_XFS_QUOTA is not set -# CONFIG_XFS_SECURITY is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set +# CONFIG_XFS_DEBUG is not set # CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set CONFIG_AUTOFS4_FS=y # CONFIG_FUSE_FS is not set @@ -897,16 +1022,13 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y # CONFIG_CONFIGFS_FS is not set - -# -# Miscellaneous filesystems -# +CONFIG_MISC_FILESYSTEMS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_ECRYPT_FS is not set @@ -916,34 +1038,33 @@ CONFIG_RAMFS=y # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set CONFIG_UFS_FS=m # CONFIG_UFS_FS_WRITE is not set # CONFIG_UFS_DEBUG is not set - -# -# Network File Systems -# +CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=m CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set CONFIG_NFS_V4=y -CONFIG_NFS_DIRECTIO=y CONFIG_NFSD=m CONFIG_NFSD_V3=y # CONFIG_NFSD_V3_ACL is not set CONFIG_NFSD_V4=y -CONFIG_NFSD_TCP=y CONFIG_LOCKD=m CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=m CONFIG_NFS_COMMON=y CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m -# CONFIG_SUNRPC_BIND34 is not set +# CONFIG_SUNRPC_REGISTER_V4 is not set CONFIG_RPCSEC_GSS_KRB5=m CONFIG_RPCSEC_GSS_SPKM3=m CONFIG_SMB_FS=m @@ -952,6 +1073,7 @@ CONFIG_SMB_NLS_REMOTE="cp437" CONFIG_CIFS=m # CONFIG_CIFS_STATS is not set # CONFIG_CIFS_WEAK_PW_HASH is not set +# CONFIG_CIFS_UPCALL is not set # CONFIG_CIFS_XATTR is not set # CONFIG_CIFS_DEBUG2 is not set # CONFIG_CIFS_EXPERIMENTAL is not set @@ -964,10 +1086,6 @@ CONFIG_CIFS=m # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y - -# -# Native Language Support -# CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" CONFIG_NLS_CODEPAGE_437=m @@ -1008,33 +1126,28 @@ CONFIG_NLS_ISO8859_15=m # CONFIG_NLS_KOI8_R is not set # CONFIG_NLS_KOI8_U is not set CONFIG_NLS_UTF8=m - -# -# Distributed Lock Manager -# # CONFIG_DLM is not set -# -# Profiling support -# -CONFIG_PROFILING=y -CONFIG_OPROFILE=m - # # Kernel hacking # # CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=2048 CONFIG_MAGIC_SYSRQ=y # CONFIG_UNUSED_SYMBOLS is not set -# CONFIG_DEBUG_FS is not set +CONFIG_DEBUG_FS=y CONFIG_HEADERS_CHECK=y CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SHIRQ is not set CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set @@ -1046,10 +1159,33 @@ CONFIG_SCHED_DEBUG=y # CONFIG_DEBUG_BUGVERBOSE is not set # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_DEBUG_LIST is not set -CONFIG_FORCED_INLINING=y +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_FAULT_INJECTION is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_NOP_TRACER=y +CONFIG_RING_BUFFER=y +CONFIG_TRACING=y + +# +# Tracers +# +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_FTRACE_STARTUP_TEST is not set +# CONFIG_BUILD_DOCSRC is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set # CONFIG_DEBUG_RODATA is not set # @@ -1058,56 +1194,112 @@ CONFIG_FORCED_INLINING=y CONFIG_KEYS=y CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=m +CONFIG_CRYPTO_AEAD2=y CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_BLKCIPHER2=y CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_GF128MUL is not set +CONFIG_CRYPTO_NULL=m +# CONFIG_CRYPTO_CRYPTD is not set +CONFIG_CRYPTO_AUTHENC=m +CONFIG_CRYPTO_TEST=m + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=m +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set -CONFIG_CRYPTO_NULL=m + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=m # CONFIG_CRYPTO_MD4 is not set CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=m # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA512 is not set -# CONFIG_CRYPTO_WP512 is not set # CONFIG_CRYPTO_TGR192 is not set -# CONFIG_CRYPTO_GF128MUL is not set -# CONFIG_CRYPTO_ECB is not set -CONFIG_CRYPTO_CBC=m -# CONFIG_CRYPTO_PCBC is not set -# CONFIG_CRYPTO_LRW is not set -# CONFIG_CRYPTO_XTS is not set -# CONFIG_CRYPTO_CRYPTD is not set -CONFIG_CRYPTO_DES=m -# CONFIG_CRYPTO_FCRYPT is not set -CONFIG_CRYPTO_BLOWFISH=m -# CONFIG_CRYPTO_TWOFISH is not set -# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# # CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +CONFIG_CRYPTO_BLOWFISH=m +# CONFIG_CRYPTO_CAMELLIA is not set CONFIG_CRYPTO_CAST5=m # CONFIG_CRYPTO_CAST6 is not set -# CONFIG_CRYPTO_TEA is not set -# CONFIG_CRYPTO_ARC4 is not set +CONFIG_CRYPTO_DES=m +# CONFIG_CRYPTO_FCRYPT is not set # CONFIG_CRYPTO_KHAZAD is not set -# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_SALSA20 is not set # CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# CONFIG_CRYPTO_DEFLATE=m -# CONFIG_CRYPTO_MICHAEL_MIC is not set -CONFIG_CRYPTO_CRC32C=m -# CONFIG_CRYPTO_CAMELLIA is not set -CONFIG_CRYPTO_TEST=m -# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set # # Library routines # CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y CONFIG_CRC_CCITT=m # CONFIG_CRC16 is not set -# CONFIG_CRC_ITU_T is not set +# CONFIG_CRC_T10DIF is not set +CONFIG_CRC_ITU_T=m CONFIG_CRC32=y # CONFIG_CRC7 is not set CONFIG_LIBCRC32C=m diff --git a/arch/parisc/configs/b180_defconfig b/arch/parisc/configs/b180_defconfig index 1bf22c9a461..98bb05ee6e8 100644 --- a/arch/parisc/configs/b180_defconfig +++ b/arch/parisc/configs/b180_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.23 -# Fri Oct 12 21:16:46 2007 +# Linux kernel version: 2.6.29-rc8 +# Fri Mar 13 01:32:57 2009 # CONFIG_PARISC=y CONFIG_MMU=y @@ -33,13 +33,29 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=16 +# CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set # CONFIG_BLK_DEV_INITRD is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y # CONFIG_EMBEDDED is not set CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y @@ -51,27 +67,34 @@ CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y -CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y +CONFIG_AIO=y CONFIG_VM_EVENT_COUNTERS=y +CONFIG_PCI_QUIRKS=y +CONFIG_COMPAT_BRK=y CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set # CONFIG_MODULE_UNLOAD is not set CONFIG_MODVERSIONS=y # CONFIG_MODULE_SRCVERSION_ALL is not set -# CONFIG_KMOD is not set +CONFIG_INIT_ALL_POSSIBLE=y CONFIG_BLOCK=y # CONFIG_LBD is not set # CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -85,6 +108,7 @@ CONFIG_IOSCHED_CFQ=y CONFIG_DEFAULT_CFQ=y # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_FREEZER is not set # # Processor type and features @@ -108,13 +132,15 @@ CONFIG_HZ_250=y # CONFIG_HZ_300 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=250 +# CONFIG_SCHED_HRTICK is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4096 -# CONFIG_RESOURCES_64BIT is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y # CONFIG_HPUX is not set # @@ -130,14 +156,14 @@ CONFIG_EISA_NAMES=y CONFIG_ISA=y CONFIG_PCI=y # CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_PCI_LEGACY=y # CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_STUB is not set CONFIG_GSC_DINO=y # CONFIG_PCI_LBA is not set - -# -# PCCARD (PCMCIA/CardBus) support -# +CONFIG_IOMMU_HELPER=y # CONFIG_PCCARD is not set +# CONFIG_HOTPLUG_PCI is not set # # PA-RISC specific drivers @@ -151,16 +177,15 @@ CONFIG_PDC_STABLE=y # Executable file formats # CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set # CONFIG_BINFMT_MISC is not set - -# -# Networking -# CONFIG_NET=y # # Networking options # +CONFIG_COMPAT_NET_DEV_OPS=y CONFIG_PACKET=y CONFIG_PACKET_MMAP=y CONFIG_UNIX=y @@ -205,36 +230,37 @@ CONFIG_INET6_XFRM_MODE_TRANSPORT=y CONFIG_INET6_XFRM_MODE_TUNNEL=y CONFIG_INET6_XFRM_MODE_BEET=y CONFIG_IPV6_SIT=y +CONFIG_IPV6_NDISC_NODETYPE=y # CONFIG_IPV6_TUNNEL is not set # CONFIG_NETLABEL is not set # CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set +# CONFIG_ATM is not set # CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set - -# -# QoS and/or fair queueing -# # CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set # # Network testing # # CONFIG_NET_PKTGEN is not set # CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set # CONFIG_IRDA is not set # CONFIG_BT is not set - -# -# Wireless -# +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y # CONFIG_CFG80211 is not set +CONFIG_WIRELESS_OLD_REGULATORY=y # CONFIG_WIRELESS_EXT is not set -# CONFIG_IEEE80211 is not set +# CONFIG_LIB80211 is not set +# CONFIG_MAC80211 is not set +# CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # @@ -247,7 +273,9 @@ CONFIG_IPV6_SIT=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y # CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_FW_LOADER is not set +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set @@ -275,10 +303,18 @@ CONFIG_BLK_DEV_CRYPTOLOOP=y CONFIG_CDROM_PKTCDVD=m CONFIG_CDROM_PKTCDVD_BUFFERS=8 CONFIG_ATA_OVER_ETH=y +# CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_PHANTOM is not set -# CONFIG_EEPROM_93CX6 is not set # CONFIG_SGI_IOC4 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_93CX6 is not set +CONFIG_HAVE_IDE=y # CONFIG_IDE is not set # @@ -317,8 +353,10 @@ CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_FC_ATTRS is not set # CONFIG_SCSI_ISCSI_ATTRS is not set # CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_CXGB3_ISCSI is not set # CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_ACARD is not set @@ -330,12 +368,15 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_AIC94XX is not set # CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set # CONFIG_SCSI_ARCMSR is not set # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set # CONFIG_SCSI_HPTIOP is not set +# CONFIG_LIBFC is not set +# CONFIG_FCOE is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_DTC3280 is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set @@ -346,6 +387,7 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_PPA is not set # CONFIG_SCSI_IMM is not set +# CONFIG_SCSI_MVSAS is not set # CONFIG_SCSI_NCR53C406A is not set CONFIG_SCSI_LASI700=y CONFIG_53C700_LE_ON_BE=y @@ -360,7 +402,6 @@ CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 CONFIG_SCSI_NCR53C8XX_SYNC=40 # CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PSI240I is not set # CONFIG_SCSI_QLOGIC_FAS is not set # CONFIG_SCSI_QLOGIC_1280 is not set # CONFIG_SCSI_QLA_FC is not set @@ -373,9 +414,11 @@ CONFIG_SCSI_NCR53C8XX_SYNC=40 # CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set # CONFIG_SCSI_SRP is not set +# CONFIG_SCSI_DH is not set # CONFIG_ATA is not set CONFIG_MD=y CONFIG_BLK_DEV_MD=y +CONFIG_MD_AUTODETECT=y CONFIG_MD_LINEAR=y CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y @@ -383,26 +426,18 @@ CONFIG_MD_RAID1=y # CONFIG_MD_MULTIPATH is not set # CONFIG_MD_FAULTY is not set # CONFIG_BLK_DEV_DM is not set - -# -# Fusion MPT device support -# # CONFIG_FUSION is not set -# CONFIG_FUSION_SPI is not set -# CONFIG_FUSION_FC is not set -# CONFIG_FUSION_SAS is not set # # IEEE 1394 (FireWire) support # # -# An alternative FireWire stack is available with EXPERIMENTAL=y +# A new alternative FireWire stack is available with EXPERIMENTAL=y # # CONFIG_IEEE1394 is not set # CONFIG_I2O is not set CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -434,36 +469,49 @@ CONFIG_TULIP=y # CONFIG_IBM_NEW_EMAC_RGMII is not set # CONFIG_IBM_NEW_EMAC_TAH is not set # CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set # CONFIG_NET_PCI is not set # CONFIG_B44 is not set +# CONFIG_CS89x0 is not set # CONFIG_NET_POCKET is not set +# CONFIG_ATL2 is not set CONFIG_NETDEV_1000=y # CONFIG_ACENIC is not set # CONFIG_DL2K is not set # CONFIG_E1000 is not set # CONFIG_E1000E is not set +# CONFIG_IGB is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_R8169 is not set # CONFIG_SIS190 is not set # CONFIG_SKGE is not set # CONFIG_SKY2 is not set -# CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set # CONFIG_TIGON3 is not set # CONFIG_BNX2 is not set # CONFIG_QLA3XXX is not set +# CONFIG_ATL1 is not set +# CONFIG_JME is not set CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set +CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_CHELSIO_T3 is not set +# CONFIG_ENIC is not set # CONFIG_IXGBE is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set # CONFIG_NETXEN_NIC is not set # CONFIG_NIU is not set +# CONFIG_MLX4_EN is not set # CONFIG_MLX4_CORE is not set # CONFIG_TEHUTI is not set +# CONFIG_BNX2X is not set +# CONFIG_QLGE is not set +# CONFIG_SFC is not set # CONFIG_TR is not set # @@ -471,6 +519,11 @@ CONFIG_NETDEV_10000=y # # CONFIG_WLAN_PRE80211 is not set # CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_PLIP is not set @@ -503,7 +556,6 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set CONFIG_INPUT_EVDEV=y # CONFIG_INPUT_EVBUG is not set @@ -526,11 +578,12 @@ CONFIG_MOUSE_PS2=y CONFIG_MOUSE_PS2_ALPS=y CONFIG_MOUSE_PS2_LOGIPS2PP=y CONFIG_MOUSE_PS2_SYNAPTICS=y -CONFIG_MOUSE_PS2_LIFEBOOK=y CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set # CONFIG_MOUSE_PS2_TOUCHKIT is not set # CONFIG_MOUSE_SERIAL is not set # CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set # CONFIG_MOUSE_INPORT is not set # CONFIG_MOUSE_LOGIBM is not set # CONFIG_MOUSE_PC110PAD is not set @@ -564,9 +617,11 @@ CONFIG_SERIO_LIBPS2=y # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y # CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y # CONFIG_SERIAL_NONSTANDARD is not set # @@ -598,75 +653,79 @@ CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 CONFIG_PRINTER=y # CONFIG_LP_CONSOLE is not set # CONFIG_PPDEV is not set -# CONFIG_TIPAR is not set # CONFIG_IPMI_HANDLER is not set -# CONFIG_WATCHDOG is not set # CONFIG_HW_RANDOM is not set -CONFIG_GEN_RTC=y -# CONFIG_GEN_RTC_X is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set CONFIG_DEVPORT=y # CONFIG_I2C is not set - -# -# SPI support -# # CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y # # Sonics Silicon Backplane # -CONFIG_SSB_POSSIBLE=y # CONFIG_SSB is not set # # Multifunction device drivers # +# CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_REGULATOR is not set # # Multimedia devices # + +# +# Multimedia core support +# # CONFIG_VIDEO_DEV is not set # CONFIG_DVB_CORE is not set -# CONFIG_DAB is not set +# CONFIG_VIDEO_MEDIA is not set # -# Graphics support +# Multimedia drivers # -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_DAB is not set # -# Display device support +# Graphics support # -# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set # CONFIG_VGASTATE is not set CONFIG_VIDEO_OUTPUT_CONTROL=m CONFIG_FB=y # CONFIG_FIRMWARE_EDID is not set # CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set # CONFIG_FB_SYS_FILLRECT is not set # CONFIG_FB_SYS_COPYAREA is not set # CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set -CONFIG_FB_DEFERRED_IO=y # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -691,6 +750,7 @@ CONFIG_FB_STI=y # CONFIG_FB_ATY is not set # CONFIG_FB_S3 is not set # CONFIG_FB_SIS is not set +# CONFIG_FB_VIA is not set # CONFIG_FB_NEOMAGIC is not set # CONFIG_FB_KYRO is not set # CONFIG_FB_3DFX is not set @@ -698,7 +758,16 @@ CONFIG_FB_STI=y # CONFIG_FB_VT8623 is not set # CONFIG_FB_TRIDENT is not set # CONFIG_FB_ARK is not set +# CONFIG_FB_CARMINE is not set # CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set # # Console display driver support @@ -718,15 +787,8 @@ CONFIG_LOGO_LINUX_MONO=y CONFIG_LOGO_LINUX_VGA16=y CONFIG_LOGO_LINUX_CLUT224=y CONFIG_LOGO_PARISC_CLUT224=y - -# -# Sound -# CONFIG_SOUND=y - -# -# Advanced Linux Sound Architecture -# +CONFIG_SOUND_OSS_CORE=y CONFIG_SND=y CONFIG_SND_TIMER=y CONFIG_SND_PCM=y @@ -742,10 +804,7 @@ CONFIG_SND_SUPPORT_OLD_API=y CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set - -# -# Generic devices -# +CONFIG_SND_DRIVERS=y # CONFIG_SND_DUMMY is not set # CONFIG_SND_VIRMIDI is not set # CONFIG_SND_MTPAV is not set @@ -753,10 +812,7 @@ CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_SERIAL_U16550 is not set # CONFIG_SND_MPU401 is not set # CONFIG_SND_PORTMAN2X4 is not set - -# -# PCI devices -# +CONFIG_SND_PCI=y # CONFIG_SND_AD1889 is not set # CONFIG_SND_ALS300 is not set # CONFIG_SND_ALI5451 is not set @@ -765,9 +821,11 @@ CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_AU8810 is not set # CONFIG_SND_AU8820 is not set # CONFIG_SND_AU8830 is not set +# CONFIG_SND_AW2 is not set # CONFIG_SND_BT87X is not set # CONFIG_SND_CA0106 is not set # CONFIG_SND_CMIPCI is not set +# CONFIG_SND_OXYGEN is not set # CONFIG_SND_CS4281 is not set # CONFIG_SND_CS46XX is not set # CONFIG_SND_DARLA20 is not set @@ -792,6 +850,7 @@ CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_HDA_INTEL is not set # CONFIG_SND_HDSP is not set # CONFIG_SND_HDSPM is not set +# CONFIG_SND_HIFIER is not set # CONFIG_SND_ICE1712 is not set # CONFIG_SND_ICE1724 is not set # CONFIG_SND_INTEL8X0 is not set @@ -809,30 +868,23 @@ CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_TRIDENT is not set # CONFIG_SND_VIA82XX is not set # CONFIG_SND_VIA82XX_MODEM is not set +# CONFIG_SND_VIRTUOSO is not set # CONFIG_SND_VX222 is not set # CONFIG_SND_YMFPCI is not set - -# -# GSC devices -# +CONFIG_SND_GSC=y CONFIG_SND_HARMONY=y - -# -# System on Chip audio support -# # CONFIG_SND_SOC is not set - -# -# SoC Audio support for SuperH -# - -# -# Open Sound System -# # CONFIG_SOUND_PRIME is not set CONFIG_HID_SUPPORT=y CONFIG_HID=y CONFIG_HID_DEBUG=y +# CONFIG_HIDRAW is not set +# CONFIG_HID_PID is not set + +# +# Special HID drivers +# +CONFIG_HID_COMPAT=y CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y @@ -840,36 +892,63 @@ CONFIG_USB_ARCH_HAS_EHCI=y # CONFIG_USB is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# Enable Host or Gadget support to see Inventra options # # -# USB Gadget Support +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; # # CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# # CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set -# CONFIG_RTC_CLASS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set # -# DMA Engine support +# RTC interfaces # -# CONFIG_DMA_ENGINE is not set +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set # -# DMA Clients +# SPI RTC drivers # # -# DMA Devices -# -# CONFIG_AUXDISPLAY is not set +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_V3020 is not set # -# Userspace I/O +# on-CPU RTC drivers # +CONFIG_RTC_DRV_PARISC=y +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set +# CONFIG_STAGING is not set # # File systems @@ -879,19 +958,18 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set +# CONFIG_EXT4_FS is not set CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set # CONFIG_OCFS2_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set +CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set CONFIG_AUTOFS4_FS=y # CONFIG_FUSE_FS is not set @@ -917,35 +995,32 @@ CONFIG_JOLIET=y CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y # CONFIG_HFSPLUS_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set - -# -# Network File Systems -# +CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set -# CONFIG_NFS_DIRECTIO is not set +CONFIG_ROOT_NFS=y CONFIG_NFSD=y CONFIG_NFSD_V3=y # CONFIG_NFSD_V3_ACL is not set -CONFIG_NFSD_TCP=y -CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y @@ -962,10 +1037,6 @@ CONFIG_SMB_FS=y # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y - -# -# Native Language Support -# CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" CONFIG_NLS_CODEPAGE_437=m @@ -1011,7 +1082,9 @@ CONFIG_NLS_UTF8=m # Kernel hacking # # CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 CONFIG_MAGIC_SYSRQ=y # CONFIG_UNUSED_SYMBOLS is not set # CONFIG_DEBUG_FS is not set @@ -1019,9 +1092,12 @@ CONFIG_HEADERS_CHECK=y CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SHIRQ is not set CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set @@ -1033,10 +1109,29 @@ CONFIG_SCHED_DEBUG=y CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y # CONFIG_DEBUG_LIST is not set -CONFIG_FORCED_INLINING=y +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_FAULT_INJECTION is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set + +# +# Tracers +# +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_BUILD_DOCSRC is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set # CONFIG_DEBUG_RODATA is not set # @@ -1044,52 +1139,108 @@ CONFIG_FORCED_INLINING=y # # CONFIG_KEYS is not set CONFIG_SECURITY=y +# CONFIG_SECURITYFS is not set # CONFIG_SECURITY_NETWORK is not set -CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_PATH is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0 CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD2=y CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y CONFIG_CRYPTO_MANAGER=y -# CONFIG_CRYPTO_HMAC is not set +CONFIG_CRYPTO_MANAGER2=y # CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_PCBC is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set # CONFIG_CRYPTO_MD4 is not set # CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set # CONFIG_CRYPTO_SHA1 is not set # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA512 is not set -# CONFIG_CRYPTO_WP512 is not set # CONFIG_CRYPTO_TGR192 is not set -# CONFIG_CRYPTO_ECB is not set -CONFIG_CRYPTO_CBC=y -# CONFIG_CRYPTO_PCBC is not set -# CONFIG_CRYPTO_CRYPTD is not set -# CONFIG_CRYPTO_DES is not set -# CONFIG_CRYPTO_FCRYPT is not set -# CONFIG_CRYPTO_BLOWFISH is not set -# CONFIG_CRYPTO_TWOFISH is not set -# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# # CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set -# CONFIG_CRYPTO_TEA is not set -# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set # CONFIG_CRYPTO_KHAZAD is not set -# CONFIG_CRYPTO_ANUBIS is not set # CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# # CONFIG_CRYPTO_DEFLATE is not set -# CONFIG_CRYPTO_MICHAEL_MIC is not set -# CONFIG_CRYPTO_CRC32C is not set -# CONFIG_CRYPTO_CAMELLIA is not set -# CONFIG_CRYPTO_TEST is not set -# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_HIFN_795X is not set # # Library routines # CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y # CONFIG_CRC_CCITT is not set # CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set # CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y # CONFIG_CRC7 is not set diff --git a/arch/parisc/configs/c3000_defconfig b/arch/parisc/configs/c3000_defconfig index c6def3c1d20..0aa8014f758 100644 --- a/arch/parisc/configs/c3000_defconfig +++ b/arch/parisc/configs/c3000_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.23 -# Fri Oct 12 21:24:00 2007 +# Linux kernel version: 2.6.29-rc8 +# Fri Mar 13 01:32:58 2009 # CONFIG_PARISC=y CONFIG_MMU=y @@ -33,16 +33,29 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set -# CONFIG_USER_NS is not set # CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=16 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set # CONFIG_BLK_DEV_INITRD is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y CONFIG_EMBEDDED=y CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y @@ -54,29 +67,39 @@ CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y -CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y +CONFIG_AIO=y CONFIG_VM_EVENT_COUNTERS=y +CONFIG_PCI_QUIRKS=y +CONFIG_COMPAT_BRK=y CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set +CONFIG_PROFILING=y +CONFIG_TRACEPOINTS=y +# CONFIG_MARKERS is not set +CONFIG_OPROFILE=m +CONFIG_HAVE_OPROFILE=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y +CONFIG_INIT_ALL_POSSIBLE=y CONFIG_BLOCK=y # CONFIG_LBD is not set # CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set # CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -90,6 +113,7 @@ CONFIG_DEFAULT_AS=y # CONFIG_DEFAULT_CFQ is not set # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="anticipatory" +# CONFIG_FREEZER is not set # # Processor type and features @@ -115,17 +139,19 @@ CONFIG_HZ_250=y # CONFIG_HZ_300 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=250 +# CONFIG_SCHED_HRTICK is not set CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y # CONFIG_DISCONTIGMEM_MANUAL is not set # CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 -# CONFIG_RESOURCES_64BIT is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y # CONFIG_HPUX is not set # @@ -134,14 +160,13 @@ CONFIG_VIRT_TO_BUS=y # CONFIG_GSC is not set CONFIG_PCI=y # CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_PCI_LEGACY=y # CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_STUB is not set CONFIG_PCI_LBA=y CONFIG_IOSAPIC=y CONFIG_IOMMU_SBA=y - -# -# PCCARD (PCMCIA/CardBus) support -# +CONFIG_IOMMU_HELPER=y # CONFIG_PCCARD is not set # CONFIG_HOTPLUG_PCI is not set @@ -158,16 +183,15 @@ CONFIG_PDC_STABLE=y # Executable file formats # CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set # CONFIG_BINFMT_MISC is not set - -# -# Networking -# CONFIG_NET=y # # Networking options # +CONFIG_COMPAT_NET_DEV_OPS=y CONFIG_PACKET=y CONFIG_PACKET_MMAP=y CONFIG_UNIX=y @@ -175,6 +199,8 @@ CONFIG_XFRM=y CONFIG_XFRM_USER=m # CONFIG_XFRM_SUB_POLICY is not set # CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=m CONFIG_NET_KEY=m # CONFIG_NET_KEY_MIGRATE is not set CONFIG_INET=y @@ -204,7 +230,6 @@ CONFIG_INET_XFRM_MODE_BEET=y CONFIG_TCP_CONG_CUBIC=y CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_TCP_MD5SIG is not set -# CONFIG_IP_VS is not set CONFIG_IPV6=m # CONFIG_IPV6_PRIVACY is not set # CONFIG_IPV6_ROUTER_PREF is not set @@ -220,29 +245,34 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=m CONFIG_INET6_XFRM_MODE_BEET=m # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set CONFIG_IPV6_SIT=m +CONFIG_IPV6_NDISC_NODETYPE=y CONFIG_IPV6_TUNNEL=m # CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set # CONFIG_NETWORK_SECMARK is not set CONFIG_NETFILTER=y CONFIG_NETFILTER_DEBUG=y +CONFIG_NETFILTER_ADVANCED=y # # Core Netfilter Configuration # -# CONFIG_NETFILTER_NETLINK is not set -# CONFIG_NF_CONNTRACK_ENABLED is not set +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set # CONFIG_NF_CONNTRACK is not set # CONFIG_NETFILTER_XTABLES is not set +# CONFIG_IP_VS is not set # # IP: Netfilter Configuration # +# CONFIG_NF_DEFRAG_IPV4 is not set CONFIG_IP_NF_QUEUE=m # CONFIG_IP_NF_IPTABLES is not set # CONFIG_IP_NF_ARPTABLES is not set # -# IPv6: Netfilter Configuration (EXPERIMENTAL) +# IPv6: Netfilter Configuration # # CONFIG_IP6_NF_QUEUE is not set # CONFIG_IP6_NF_IPTABLES is not set @@ -251,6 +281,7 @@ CONFIG_IP_NF_QUEUE=m # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set # CONFIG_LLC2 is not set @@ -260,28 +291,26 @@ CONFIG_IP_NF_QUEUE=m # CONFIG_LAPB is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# # CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set # # Network testing # CONFIG_NET_PKTGEN=m # CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set # CONFIG_IRDA is not set # CONFIG_BT is not set # CONFIG_AF_RXRPC is not set - -# -# Wireless -# +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y # CONFIG_CFG80211 is not set +CONFIG_WIRELESS_OLD_REGULATORY=y # CONFIG_WIRELESS_EXT is not set +# CONFIG_LIB80211 is not set # CONFIG_MAC80211 is not set -# CONFIG_IEEE80211 is not set +# CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set @@ -296,6 +325,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set @@ -316,59 +347,62 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m # CONFIG_BLK_DEV_RAM is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_PHANTOM is not set -# CONFIG_EEPROM_93CX6 is not set # CONFIG_SGI_IOC4 is not set # CONFIG_TIFM_CORE is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_93CX6 is not set +CONFIG_HAVE_IDE=y CONFIG_IDE=y -CONFIG_IDE_MAX_HWIFS=4 -CONFIG_BLK_DEV_IDE=y # -# Please see Documentation/ide.txt for help/info on IDE drives +# Please see Documentation/ide/ide.txt for help/info on IDE drives # +CONFIG_IDE_ATAPI=y # CONFIG_BLK_DEV_IDE_SATA is not set -CONFIG_BLK_DEV_IDEDISK=m -# CONFIG_IDEDISK_MULTI_MODE is not set +CONFIG_IDE_GD=y +CONFIG_IDE_GD_ATA=y +# CONFIG_IDE_GD_ATAPI is not set CONFIG_BLK_DEV_IDECD=y +CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y # CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -CONFIG_BLK_DEV_IDESCSI=y # CONFIG_IDE_TASK_IOCTL is not set CONFIG_IDE_PROC_FS=y # # IDE chipset support/bugfixes # -CONFIG_IDE_GENERIC=y # CONFIG_BLK_DEV_PLATFORM is not set +CONFIG_BLK_DEV_IDEDMA_SFF=y # # PCI IDE chipsets support # CONFIG_BLK_DEV_IDEPCI=y -CONFIG_IDEPCI_SHARE_IRQ=y CONFIG_IDEPCI_PCIBUS_ORDER=y -# CONFIG_BLK_DEV_OFFBOARD is not set # CONFIG_BLK_DEV_GENERIC is not set # CONFIG_BLK_DEV_OPTI621 is not set CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_ONLYDISK=y # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_BLK_DEV_AMD74XX is not set # CONFIG_BLK_DEV_CMD64X is not set # CONFIG_BLK_DEV_TRIFLEX is not set -# CONFIG_BLK_DEV_CY82C693 is not set # CONFIG_BLK_DEV_CS5520 is not set # CONFIG_BLK_DEV_CS5530 is not set -# CONFIG_BLK_DEV_HPT34X is not set # CONFIG_BLK_DEV_HPT366 is not set # CONFIG_BLK_DEV_JMICRON is not set # CONFIG_BLK_DEV_SC1200 is not set # CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT8172 is not set # CONFIG_BLK_DEV_IT8213 is not set # CONFIG_BLK_DEV_IT821X is not set CONFIG_BLK_DEV_NS87415=y @@ -380,10 +414,7 @@ CONFIG_BLK_DEV_SIIMAGE=m # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set # CONFIG_BLK_DEV_TC86C001 is not set -# CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_IVB is not set -# CONFIG_BLK_DEV_HD is not set # # SCSI device support @@ -422,8 +453,10 @@ CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_FC_ATTRS is not set CONFIG_SCSI_ISCSI_ATTRS=m # CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_CXGB3_ISCSI is not set # CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_ACARD is not set @@ -433,16 +466,20 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_AIC94XX is not set # CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_ARCMSR is not set # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set # CONFIG_SCSI_HPTIOP is not set +# CONFIG_LIBFC is not set +# CONFIG_FCOE is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_IPS is not set # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_MVSAS is not set # CONFIG_SCSI_STEX is not set CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 @@ -458,9 +495,11 @@ CONFIG_SCSI_SYM53C8XX_MMIO=y # CONFIG_SCSI_NSP32 is not set CONFIG_SCSI_DEBUG=m # CONFIG_SCSI_SRP is not set +# CONFIG_SCSI_DH is not set # CONFIG_ATA is not set CONFIG_MD=y CONFIG_BLK_DEV_MD=y +CONFIG_MD_AUTODETECT=y CONFIG_MD_LINEAR=y CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y @@ -475,13 +514,8 @@ CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m CONFIG_DM_MULTIPATH=m -# CONFIG_DM_MULTIPATH_EMC is not set -# CONFIG_DM_MULTIPATH_RDAC is not set # CONFIG_DM_DELAY is not set - -# -# Fusion MPT device support -# +# CONFIG_DM_UEVENT is not set CONFIG_FUSION=y CONFIG_FUSION_SPI=m # CONFIG_FUSION_FC is not set @@ -493,20 +527,40 @@ CONFIG_FUSION_CTL=m # # IEEE 1394 (FireWire) support # + +# +# Enable only one of the two stacks, unless you know what you are doing +# # CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set # CONFIG_I2O is not set CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set CONFIG_DUMMY=m CONFIG_BONDING=m # CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set CONFIG_TUN=m # CONFIG_VETH is not set -# CONFIG_IP1000 is not set # CONFIG_ARCNET is not set -# CONFIG_PHYLIB is not set +CONFIG_PHYLIB=m + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MDIO_BITBANG is not set CONFIG_NET_ETHERNET=y CONFIG_MII=m # CONFIG_HAPPYMEAL is not set @@ -528,33 +582,38 @@ CONFIG_TULIP_MMIO=y # CONFIG_IBM_NEW_EMAC_RGMII is not set # CONFIG_IBM_NEW_EMAC_TAH is not set # CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set -# CONFIG_EEPRO100 is not set CONFIG_E100=m # CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set # CONFIG_NE2K_PCI is not set # CONFIG_8139CP is not set # CONFIG_8139TOO is not set +# CONFIG_R6040 is not set # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set +# CONFIG_SMSC9420 is not set # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set # CONFIG_SC92031 is not set +# CONFIG_ATL2 is not set CONFIG_NETDEV_1000=y CONFIG_ACENIC=m # CONFIG_ACENIC_OMIT_TIGON_I is not set # CONFIG_DL2K is not set CONFIG_E1000=m -# CONFIG_E1000_NAPI is not set -# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_E1000E is not set +# CONFIG_IP1000 is not set +# CONFIG_IGB is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set @@ -562,23 +621,31 @@ CONFIG_E1000=m # CONFIG_SIS190 is not set # CONFIG_SKGE is not set # CONFIG_SKY2 is not set -# CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set CONFIG_TIGON3=m # CONFIG_BNX2 is not set # CONFIG_QLA3XXX is not set # CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_ATL1C is not set +# CONFIG_JME is not set CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set +CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_CHELSIO_T3 is not set +# CONFIG_ENIC is not set # CONFIG_IXGBE is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set # CONFIG_NETXEN_NIC is not set # CONFIG_NIU is not set +# CONFIG_MLX4_EN is not set # CONFIG_MLX4_CORE is not set # CONFIG_TEHUTI is not set +# CONFIG_BNX2X is not set +# CONFIG_QLGE is not set +# CONFIG_SFC is not set # CONFIG_TR is not set # @@ -586,6 +653,11 @@ CONFIG_NETDEV_10000=y # # CONFIG_WLAN_PRE80211 is not set # CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# # # USB Network Adapters @@ -594,7 +666,6 @@ CONFIG_NETDEV_10000=y # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET_MII is not set # CONFIG_USB_USBNET is not set # CONFIG_WAN is not set # CONFIG_FDDI is not set @@ -612,7 +683,6 @@ CONFIG_PPPOE=m # CONFIG_SLIP is not set CONFIG_SLHC=m # CONFIG_NET_FC is not set -# CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set @@ -634,7 +704,6 @@ CONFIG_INPUT_MOUSEDEV=y CONFIG_INPUT_MOUSEDEV_SCREEN_X=1600 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=1200 # CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set # CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_EVBUG is not set @@ -652,6 +721,7 @@ CONFIG_INPUT_MOUSE=y # CONFIG_MOUSE_PS2 is not set # CONFIG_MOUSE_SERIAL is not set # CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set # CONFIG_MOUSE_VSXXXAA is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TABLET is not set @@ -672,10 +742,13 @@ CONFIG_SERIO_LIBPS2=m # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y # CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y # CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set # # Serial drivers @@ -699,72 +772,77 @@ CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_IPMI_HANDLER is not set -# CONFIG_WATCHDOG is not set # CONFIG_HW_RANDOM is not set -CONFIG_GEN_RTC=y -CONFIG_GEN_RTC_X=y # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set CONFIG_RAW_DRIVER=y CONFIG_MAX_RAW_DEVS=256 # CONFIG_TCG_TPM is not set CONFIG_DEVPORT=y # CONFIG_I2C is not set - -# -# SPI support -# # CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y # # Sonics Silicon Backplane # -CONFIG_SSB_POSSIBLE=y # CONFIG_SSB is not set # # Multifunction device drivers # +# CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_REGULATOR is not set # # Multimedia devices # + +# +# Multimedia core support +# # CONFIG_VIDEO_DEV is not set # CONFIG_DVB_CORE is not set -# CONFIG_DAB is not set +# CONFIG_VIDEO_MEDIA is not set # -# Graphics support +# Multimedia drivers # -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_DAB is not set # -# Display device support +# Graphics support # -# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set # CONFIG_VGASTATE is not set CONFIG_VIDEO_OUTPUT_CONTROL=m CONFIG_FB=y # CONFIG_FIRMWARE_EDID is not set # CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set # CONFIG_FB_SYS_FILLRECT is not set # CONFIG_FB_SYS_COPYAREA is not set # CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set -CONFIG_FB_DEFERRED_IO=y # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -790,6 +868,7 @@ CONFIG_FB_STI=y # CONFIG_FB_S3 is not set # CONFIG_FB_SAVAGE is not set # CONFIG_FB_SIS is not set +# CONFIG_FB_VIA is not set # CONFIG_FB_NEOMAGIC is not set # CONFIG_FB_KYRO is not set # CONFIG_FB_3DFX is not set @@ -798,7 +877,16 @@ CONFIG_FB_STI=y # CONFIG_FB_TRIDENT is not set # CONFIG_FB_ARK is not set # CONFIG_FB_PM3 is not set +# CONFIG_FB_CARMINE is not set # CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set # # Console display driver support @@ -818,15 +906,8 @@ CONFIG_LOGO=y # CONFIG_LOGO_LINUX_VGA16 is not set # CONFIG_LOGO_LINUX_CLUT224 is not set CONFIG_LOGO_PARISC_CLUT224=y - -# -# Sound -# CONFIG_SOUND=y - -# -# Advanced Linux Sound Architecture -# +CONFIG_SOUND_OSS_CORE=y CONFIG_SND=y CONFIG_SND_TIMER=y CONFIG_SND_PCM=y @@ -842,20 +923,16 @@ CONFIG_SND_SUPPORT_OLD_API=y CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set - -# -# Generic devices -# +CONFIG_SND_VMASTER=y CONFIG_SND_AC97_CODEC=y +CONFIG_SND_DRIVERS=y # CONFIG_SND_DUMMY is not set # CONFIG_SND_VIRMIDI is not set # CONFIG_SND_MTPAV is not set # CONFIG_SND_SERIAL_U16550 is not set # CONFIG_SND_MPU401 is not set - -# -# PCI devices -# +# CONFIG_SND_AC97_POWER_SAVE is not set +CONFIG_SND_PCI=y CONFIG_SND_AD1889=y # CONFIG_SND_ALS300 is not set # CONFIG_SND_ALI5451 is not set @@ -864,10 +941,12 @@ CONFIG_SND_AD1889=y # CONFIG_SND_AU8810 is not set # CONFIG_SND_AU8820 is not set # CONFIG_SND_AU8830 is not set +# CONFIG_SND_AW2 is not set # CONFIG_SND_AZT3328 is not set # CONFIG_SND_BT87X is not set # CONFIG_SND_CA0106 is not set # CONFIG_SND_CMIPCI is not set +# CONFIG_SND_OXYGEN is not set # CONFIG_SND_CS4281 is not set # CONFIG_SND_CS46XX is not set # CONFIG_SND_DARLA20 is not set @@ -892,6 +971,7 @@ CONFIG_SND_AD1889=y # CONFIG_SND_HDA_INTEL is not set # CONFIG_SND_HDSP is not set # CONFIG_SND_HDSPM is not set +# CONFIG_SND_HIFIER is not set # CONFIG_SND_ICE1712 is not set # CONFIG_SND_ICE1724 is not set # CONFIG_SND_INTEL8X0 is not set @@ -909,47 +989,59 @@ CONFIG_SND_AD1889=y # CONFIG_SND_TRIDENT is not set # CONFIG_SND_VIA82XX is not set # CONFIG_SND_VIA82XX_MODEM is not set +# CONFIG_SND_VIRTUOSO is not set # CONFIG_SND_VX222 is not set # CONFIG_SND_YMFPCI is not set -# CONFIG_SND_AC97_POWER_SAVE is not set - -# -# USB devices -# +CONFIG_SND_USB=y # CONFIG_SND_USB_AUDIO is not set # CONFIG_SND_USB_CAIAQ is not set - -# -# System on Chip audio support -# # CONFIG_SND_SOC is not set - -# -# SoC Audio support for SuperH -# - -# -# Open Sound System -# # CONFIG_SOUND_PRIME is not set CONFIG_AC97_BUS=y CONFIG_HID_SUPPORT=y CONFIG_HID=y # CONFIG_HID_DEBUG is not set +# CONFIG_HIDRAW is not set # # USB Input Devices # CONFIG_USB_HID=y -# CONFIG_USB_HIDINPUT_POWERBOOK is not set -# CONFIG_HID_FF is not set +# CONFIG_HID_PID is not set CONFIG_USB_HIDDEV=y + +# +# Special HID drivers +# +CONFIG_HID_COMPAT=y +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_LOGITECH is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_GREENASIA_FF is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_THRUSTMASTER_FF is not set +# CONFIG_ZEROPLUS_FF is not set CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y CONFIG_USB_ARCH_HAS_EHCI=y CONFIG_USB=y CONFIG_USB_DEBUG=y +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set # # Miscellaneous USB options @@ -958,12 +1050,20 @@ CONFIG_USB_DEVICEFS=y CONFIG_USB_DEVICE_CLASS=y # CONFIG_USB_DYNAMIC_MINORS is not set # CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set # # USB Host Controller Drivers # +# CONFIG_USB_C67X00_HCD is not set # CONFIG_USB_EHCI_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set @@ -971,32 +1071,37 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_UHCI_HCD is not set # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_WHCI_HCD is not set +# CONFIG_USB_HWA_HCD is not set # # USB Device Class drivers # # CONFIG_USB_ACM is not set CONFIG_USB_PRINTER=m +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; # # -# may also be needed; see USB_STORAGE Help for more information +# see USB_STORAGE Help for more information # CONFIG_USB_STORAGE=m # CONFIG_USB_STORAGE_DEBUG is not set # CONFIG_USB_STORAGE_DATAFAB is not set # CONFIG_USB_STORAGE_FREECOM is not set # CONFIG_USB_STORAGE_ISD200 is not set -CONFIG_USB_STORAGE_DPCM=y CONFIG_USB_STORAGE_USBAT=y CONFIG_USB_STORAGE_SDDR09=y CONFIG_USB_STORAGE_SDDR55=y CONFIG_USB_STORAGE_JUMPSHOT=y # CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set # CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set # CONFIG_USB_LIBUSUAL is not set # @@ -1004,15 +1109,10 @@ CONFIG_USB_STORAGE_JUMPSHOT=y # CONFIG_USB_MDC800=m CONFIG_USB_MICROTEK=m -# CONFIG_USB_MON is not set # # USB port drivers # - -# -# USB Serial Converter support -# # CONFIG_USB_SERIAL is not set # @@ -1021,7 +1121,7 @@ CONFIG_USB_MICROTEK=m # CONFIG_USB_EMI62 is not set # CONFIG_USB_EMI26 is not set # CONFIG_USB_ADUTUX is not set -# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_SEVSEG is not set # CONFIG_USB_RIO500 is not set CONFIG_USB_LEGOTOWER=m # CONFIG_USB_LCD is not set @@ -1037,37 +1137,59 @@ CONFIG_USB_LEGOTOWER=m # CONFIG_USB_TRANCEVIBRATOR is not set # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set +# CONFIG_USB_GADGET is not set # -# USB DSL modem support -# - -# -# USB Gadget Support +# OTG and related infrastructure # -# CONFIG_USB_GADGET is not set +# CONFIG_UWB is not set # CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set -# CONFIG_RTC_CLASS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set # -# DMA Engine support +# RTC interfaces # -# CONFIG_DMA_ENGINE is not set +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set # -# DMA Clients +# SPI RTC drivers # # -# DMA Devices +# Platform RTC drivers # +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_V3020 is not set # -# Userspace I/O +# on-CPU RTC drivers # +CONFIG_RTC_DRV_PARISC=y +# CONFIG_DMADEVICES is not set # CONFIG_UIO is not set +# CONFIG_STAGING is not set # # File systems @@ -1077,25 +1199,24 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set -# CONFIG_EXT4DEV_FS is not set +# CONFIG_EXT4_FS is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y CONFIG_XFS_FS=m # CONFIG_XFS_QUOTA is not set -# CONFIG_XFS_SECURITY is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set -# CONFIG_GFS2_FS is not set +# CONFIG_XFS_DEBUG is not set # CONFIG_OCFS2_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set CONFIG_AUTOFS4_FS=y # CONFIG_FUSE_FS is not set @@ -1124,16 +1245,13 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y # CONFIG_CONFIGFS_FS is not set - -# -# Miscellaneous filesystems -# +CONFIG_MISC_FILESYSTEMS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set @@ -1142,32 +1260,31 @@ CONFIG_RAMFS=y # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set - -# -# Network File Systems -# +CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set # CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set +CONFIG_ROOT_NFS=y CONFIG_NFSD=y CONFIG_NFSD_V3=y # CONFIG_NFSD_V3_ACL is not set # CONFIG_NFSD_V4 is not set -# CONFIG_NFSD_TCP is not set -CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y -# CONFIG_SUNRPC_BIND34 is not set +# CONFIG_SUNRPC_REGISTER_V4 is not set # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set @@ -1181,10 +1298,6 @@ CONFIG_SUNRPC=y # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y - -# -# Native Language Support -# CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" CONFIG_NLS_CODEPAGE_437=m @@ -1225,33 +1338,28 @@ CONFIG_NLS_ISO8859_15=m # CONFIG_NLS_KOI8_R is not set # CONFIG_NLS_KOI8_U is not set CONFIG_NLS_UTF8=m - -# -# Distributed Lock Manager -# # CONFIG_DLM is not set -# -# Profiling support -# -CONFIG_PROFILING=y -CONFIG_OPROFILE=m - # # Kernel hacking # # CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 CONFIG_MAGIC_SYSRQ=y # CONFIG_UNUSED_SYMBOLS is not set -# CONFIG_DEBUG_FS is not set +CONFIG_DEBUG_FS=y CONFIG_HEADERS_CHECK=y CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SHIRQ is not set CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set @@ -1263,10 +1371,33 @@ CONFIG_DEBUG_MUTEXES=y # CONFIG_DEBUG_BUGVERBOSE is not set # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_DEBUG_LIST is not set -CONFIG_FORCED_INLINING=y +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_FAULT_INJECTION is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_NOP_TRACER=y +CONFIG_RING_BUFFER=y +CONFIG_TRACING=y + +# +# Tracers +# +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_FTRACE_STARTUP_TEST is not set +# CONFIG_BUILD_DOCSRC is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set CONFIG_DEBUG_RODATA=y # @@ -1274,54 +1405,110 @@ CONFIG_DEBUG_RODATA=y # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=m +CONFIG_CRYPTO_ALGAPI2=m +CONFIG_CRYPTO_AEAD2=m CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_BLKCIPHER2=m +CONFIG_CRYPTO_HASH=m +CONFIG_CRYPTO_HASH2=m +CONFIG_CRYPTO_RNG2=m CONFIG_CRYPTO_MANAGER=m +CONFIG_CRYPTO_MANAGER2=m +# CONFIG_CRYPTO_GF128MUL is not set +CONFIG_CRYPTO_NULL=m +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +CONFIG_CRYPTO_TEST=m + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=m +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# # CONFIG_CRYPTO_HMAC is not set # CONFIG_CRYPTO_XCBC is not set -CONFIG_CRYPTO_NULL=m + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=m # CONFIG_CRYPTO_MD4 is not set CONFIG_CRYPTO_MD5=m +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set # CONFIG_CRYPTO_SHA1 is not set # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA512 is not set -# CONFIG_CRYPTO_WP512 is not set # CONFIG_CRYPTO_TGR192 is not set -# CONFIG_CRYPTO_GF128MUL is not set -# CONFIG_CRYPTO_ECB is not set -CONFIG_CRYPTO_CBC=m -# CONFIG_CRYPTO_PCBC is not set -# CONFIG_CRYPTO_LRW is not set -# CONFIG_CRYPTO_XTS is not set -# CONFIG_CRYPTO_CRYPTD is not set -CONFIG_CRYPTO_DES=m -# CONFIG_CRYPTO_FCRYPT is not set -CONFIG_CRYPTO_BLOWFISH=m -# CONFIG_CRYPTO_TWOFISH is not set -# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# # CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +CONFIG_CRYPTO_BLOWFISH=m +# CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set -# CONFIG_CRYPTO_TEA is not set -# CONFIG_CRYPTO_ARC4 is not set +CONFIG_CRYPTO_DES=m +# CONFIG_CRYPTO_FCRYPT is not set # CONFIG_CRYPTO_KHAZAD is not set -# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_SALSA20 is not set # CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# CONFIG_CRYPTO_DEFLATE=m -# CONFIG_CRYPTO_MICHAEL_MIC is not set -CONFIG_CRYPTO_CRC32C=m -# CONFIG_CRYPTO_CAMELLIA is not set -CONFIG_CRYPTO_TEST=m -# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set # # Library routines # CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y CONFIG_CRC_CCITT=m # CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set # CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y # CONFIG_CRC7 is not set diff --git a/arch/parisc/configs/default_defconfig b/arch/parisc/configs/default_defconfig index 448a757b06c..283a96c1b5e 100644 --- a/arch/parisc/configs/default_defconfig +++ b/arch/parisc/configs/default_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.23 -# Fri Oct 12 20:54:57 2007 +# Linux kernel version: 2.6.29-rc8 +# Fri Mar 13 01:32:59 2009 # CONFIG_PARISC=y CONFIG_MMU=y @@ -33,17 +33,35 @@ CONFIG_SYSVIPC_SYSCTL=y CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set -# CONFIG_USER_NS is not set # CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=16 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_NET_NS is not set CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y # CONFIG_EMBEDDED is not set CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y @@ -55,29 +73,39 @@ CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y -CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y +CONFIG_AIO=y CONFIG_VM_EVENT_COUNTERS=y +CONFIG_PCI_QUIRKS=y +CONFIG_COMPAT_BRK=y CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set +CONFIG_PROFILING=y +CONFIG_TRACEPOINTS=y +# CONFIG_MARKERS is not set +CONFIG_OPROFILE=m +CONFIG_HAVE_OPROFILE=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y +CONFIG_INIT_ALL_POSSIBLE=y CONFIG_BLOCK=y # CONFIG_LBD is not set # CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set # CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -91,6 +119,7 @@ CONFIG_DEFAULT_AS=y # CONFIG_DEFAULT_CFQ is not set # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="anticipatory" +# CONFIG_FREEZER is not set # # Processor type and features @@ -114,17 +143,19 @@ CONFIG_HZ_250=y # CONFIG_HZ_300 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=250 +# CONFIG_SCHED_HRTICK is not set CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y # CONFIG_DISCONTIGMEM_MANUAL is not set # CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4096 -# CONFIG_RESOURCES_64BIT is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y # CONFIG_HPUX is not set # @@ -140,15 +171,14 @@ CONFIG_EISA_NAMES=y # CONFIG_ISA is not set CONFIG_PCI=y # CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_PCI_LEGACY=y # CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_STUB is not set CONFIG_GSC_DINO=y CONFIG_PCI_LBA=y CONFIG_IOSAPIC=y CONFIG_IOMMU_SBA=y - -# -# PCCARD (PCMCIA/CardBus) support -# +CONFIG_IOMMU_HELPER=y CONFIG_PCCARD=y # CONFIG_PCMCIA_DEBUG is not set CONFIG_PCMCIA=y @@ -183,16 +213,15 @@ CONFIG_PDC_STABLE=y # Executable file formats # CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set CONFIG_BINFMT_MISC=m - -# -# Networking -# CONFIG_NET=y # # Networking options # +CONFIG_COMPAT_NET_DEV_OPS=y CONFIG_PACKET=y CONFIG_PACKET_MMAP=y CONFIG_UNIX=y @@ -200,6 +229,8 @@ CONFIG_XFRM=y CONFIG_XFRM_USER=m # CONFIG_XFRM_SUB_POLICY is not set # CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=y CONFIG_NET_KEY=m # CONFIG_NET_KEY_MIGRATE is not set CONFIG_INET=y @@ -245,8 +276,10 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=y CONFIG_INET6_XFRM_MODE_BEET=y # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set CONFIG_IPV6_SIT=y +CONFIG_IPV6_NDISC_NODETYPE=y # CONFIG_IPV6_TUNNEL is not set # CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set # CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set # CONFIG_IP_DCCP is not set @@ -254,6 +287,7 @@ CONFIG_IPV6_SIT=y # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set CONFIG_LLC=m @@ -264,28 +298,26 @@ CONFIG_LLC2=m # CONFIG_LAPB is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# # CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set # # Network testing # # CONFIG_NET_PKTGEN is not set # CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set # CONFIG_IRDA is not set # CONFIG_BT is not set # CONFIG_AF_RXRPC is not set - -# -# Wireless -# +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y # CONFIG_CFG80211 is not set +CONFIG_WIRELESS_OLD_REGULATORY=y # CONFIG_WIRELESS_EXT is not set +# CONFIG_LIB80211 is not set # CONFIG_MAC80211 is not set -# CONFIG_IEEE80211 is not set +# CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set @@ -300,6 +332,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set @@ -330,63 +364,68 @@ CONFIG_BLK_DEV_CRYPTOLOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=6144 -CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +# CONFIG_BLK_DEV_XIP is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_PHANTOM is not set -# CONFIG_EEPROM_93CX6 is not set # CONFIG_SGI_IOC4 is not set # CONFIG_TIFM_CORE is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_93CX6 is not set +CONFIG_HAVE_IDE=y CONFIG_IDE=y -CONFIG_BLK_DEV_IDE=y # -# Please see Documentation/ide.txt for help/info on IDE drives +# Please see Documentation/ide/ide.txt for help/info on IDE drives # +CONFIG_IDE_ATAPI=y # CONFIG_BLK_DEV_IDE_SATA is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_IDE_GD=y +CONFIG_IDE_GD_ATA=y +# CONFIG_IDE_GD_ATAPI is not set CONFIG_BLK_DEV_IDECS=y # CONFIG_BLK_DEV_DELKIN is not set CONFIG_BLK_DEV_IDECD=y +CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y # CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -CONFIG_BLK_DEV_IDESCSI=y # CONFIG_IDE_TASK_IOCTL is not set CONFIG_IDE_PROC_FS=y # # IDE chipset support/bugfixes # -CONFIG_IDE_GENERIC=y # CONFIG_BLK_DEV_PLATFORM is not set +CONFIG_BLK_DEV_IDEDMA_SFF=y # # PCI IDE chipsets support # CONFIG_BLK_DEV_IDEPCI=y -CONFIG_IDEPCI_SHARE_IRQ=y CONFIG_IDEPCI_PCIBUS_ORDER=y # CONFIG_BLK_DEV_OFFBOARD is not set CONFIG_BLK_DEV_GENERIC=y # CONFIG_BLK_DEV_OPTI621 is not set CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_ONLYDISK=y # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_BLK_DEV_AMD74XX is not set # CONFIG_BLK_DEV_CMD64X is not set # CONFIG_BLK_DEV_TRIFLEX is not set -# CONFIG_BLK_DEV_CY82C693 is not set # CONFIG_BLK_DEV_CS5520 is not set # CONFIG_BLK_DEV_CS5530 is not set -# CONFIG_BLK_DEV_HPT34X is not set # CONFIG_BLK_DEV_HPT366 is not set # CONFIG_BLK_DEV_JMICRON is not set # CONFIG_BLK_DEV_SC1200 is not set # CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT8172 is not set # CONFIG_BLK_DEV_IT8213 is not set # CONFIG_BLK_DEV_IT821X is not set CONFIG_BLK_DEV_NS87415=y @@ -398,10 +437,7 @@ CONFIG_BLK_DEV_NS87415=y # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set # CONFIG_BLK_DEV_TC86C001 is not set -# CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_IVB is not set -# CONFIG_BLK_DEV_HD is not set # # SCSI device support @@ -440,8 +476,10 @@ CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_FC_ATTRS is not set # CONFIG_SCSI_ISCSI_ATTRS is not set # CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_CXGB3_ISCSI is not set # CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_ACARD is not set @@ -452,11 +490,14 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_AIC94XX is not set # CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_ARCMSR is not set # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set # CONFIG_SCSI_HPTIOP is not set +# CONFIG_LIBFC is not set +# CONFIG_FCOE is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_IPS is not set @@ -464,6 +505,7 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_PPA is not set # CONFIG_SCSI_IMM is not set +# CONFIG_SCSI_MVSAS is not set CONFIG_SCSI_LASI700=y CONFIG_53C700_LE_ON_BE=y # CONFIG_SCSI_STEX is not set @@ -487,9 +529,11 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20 # CONFIG_SCSI_DEBUG is not set # CONFIG_SCSI_SRP is not set # CONFIG_SCSI_LOWLEVEL_PCMCIA is not set +# CONFIG_SCSI_DH is not set # CONFIG_ATA is not set CONFIG_MD=y CONFIG_BLK_DEV_MD=y +CONFIG_MD_AUTODETECT=y CONFIG_MD_LINEAR=y CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y @@ -505,32 +549,47 @@ CONFIG_BLK_DEV_DM=y # CONFIG_DM_ZERO is not set # CONFIG_DM_MULTIPATH is not set # CONFIG_DM_DELAY is not set +# CONFIG_DM_UEVENT is not set +# CONFIG_FUSION is not set # -# Fusion MPT device support +# IEEE 1394 (FireWire) support # -# CONFIG_FUSION is not set -# CONFIG_FUSION_SPI is not set -# CONFIG_FUSION_FC is not set -# CONFIG_FUSION_SAS is not set # -# IEEE 1394 (FireWire) support +# Enable only one of the two stacks, unless you know what you are doing # # CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set # CONFIG_I2O is not set CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set CONFIG_DUMMY=m CONFIG_BONDING=m # CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set CONFIG_TUN=m # CONFIG_VETH is not set -# CONFIG_IP1000 is not set # CONFIG_ARCNET is not set -# CONFIG_PHYLIB is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set CONFIG_NET_ETHERNET=y CONFIG_MII=m CONFIG_LASI_82596=y @@ -550,13 +609,15 @@ CONFIG_TULIP=y # CONFIG_DM9102 is not set # CONFIG_ULI526X is not set # CONFIG_PCMCIA_XIRCOM is not set -# CONFIG_PCMCIA_XIRTULIP is not set # CONFIG_DEPCA is not set # CONFIG_HP100 is not set # CONFIG_IBM_NEW_EMAC_ZMII is not set # CONFIG_IBM_NEW_EMAC_RGMII is not set # CONFIG_IBM_NEW_EMAC_TAH is not set # CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set @@ -564,7 +625,7 @@ CONFIG_NET_PCI=y # CONFIG_AC3200 is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set -# CONFIG_EEPRO100 is not set +# CONFIG_CS89x0 is not set # CONFIG_E100 is not set # CONFIG_LNE390 is not set # CONFIG_FEALNX is not set @@ -574,19 +635,24 @@ CONFIG_NET_PCI=y # CONFIG_ES3210 is not set # CONFIG_8139CP is not set # CONFIG_8139TOO is not set +# CONFIG_R6040 is not set # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set +# CONFIG_SMSC9420 is not set # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set # CONFIG_SC92031 is not set # CONFIG_NET_POCKET is not set +# CONFIG_ATL2 is not set CONFIG_NETDEV_1000=y CONFIG_ACENIC=y # CONFIG_ACENIC_OMIT_TIGON_I is not set # CONFIG_DL2K is not set # CONFIG_E1000 is not set # CONFIG_E1000E is not set +# CONFIG_IP1000 is not set +# CONFIG_IGB is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set @@ -594,23 +660,31 @@ CONFIG_ACENIC=y # CONFIG_SIS190 is not set # CONFIG_SKGE is not set # CONFIG_SKY2 is not set -# CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set CONFIG_TIGON3=y # CONFIG_BNX2 is not set # CONFIG_QLA3XXX is not set # CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_ATL1C is not set +# CONFIG_JME is not set CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set +CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_CHELSIO_T3 is not set +# CONFIG_ENIC is not set # CONFIG_IXGBE is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set # CONFIG_NETXEN_NIC is not set # CONFIG_NIU is not set +# CONFIG_MLX4_EN is not set # CONFIG_MLX4_CORE is not set # CONFIG_TEHUTI is not set +# CONFIG_BNX2X is not set +# CONFIG_QLGE is not set +# CONFIG_SFC is not set # CONFIG_TR is not set # @@ -618,6 +692,11 @@ CONFIG_NETDEV_10000=y # # CONFIG_WLAN_PRE80211 is not set # CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# # # USB Network Adapters @@ -626,7 +705,6 @@ CONFIG_NETDEV_10000=y # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET_MII is not set # CONFIG_USB_USBNET is not set CONFIG_NET_PCMCIA=y # CONFIG_PCMCIA_3C589 is not set @@ -654,7 +732,6 @@ CONFIG_PPPOE=m # CONFIG_SLIP is not set CONFIG_SLHC=m # CONFIG_NET_FC is not set -# CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set @@ -676,7 +753,6 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set # CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_EVBUG is not set @@ -699,11 +775,12 @@ CONFIG_MOUSE_PS2=y CONFIG_MOUSE_PS2_ALPS=y CONFIG_MOUSE_PS2_LOGIPS2PP=y CONFIG_MOUSE_PS2_SYNAPTICS=y -CONFIG_MOUSE_PS2_LIFEBOOK=y CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set # CONFIG_MOUSE_PS2_TOUCHKIT is not set CONFIG_MOUSE_SERIAL=y # CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set # CONFIG_MOUSE_VSXXXAA is not set CONFIG_MOUSE_HIL=y # CONFIG_INPUT_JOYSTICK is not set @@ -729,10 +806,13 @@ CONFIG_SERIO_LIBPS2=y # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y # CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y # CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set # # Serial drivers @@ -759,21 +839,16 @@ CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=64 CONFIG_PRINTER=m # CONFIG_LP_CONSOLE is not set CONFIG_PPDEV=m -# CONFIG_TIPAR is not set # CONFIG_IPMI_HANDLER is not set -# CONFIG_WATCHDOG is not set # CONFIG_HW_RANDOM is not set -CONFIG_GEN_RTC=y -CONFIG_GEN_RTC_X=y # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set # # PCMCIA character devices @@ -781,60 +856,70 @@ CONFIG_GEN_RTC_X=y # CONFIG_SYNCLINK_CS is not set # CONFIG_CARDMAN_4000 is not set # CONFIG_CARDMAN_4040 is not set +# CONFIG_IPWIRELESS is not set # CONFIG_RAW_DRIVER is not set # CONFIG_TCG_TPM is not set CONFIG_DEVPORT=y # CONFIG_I2C is not set - -# -# SPI support -# # CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y # # Sonics Silicon Backplane # -CONFIG_SSB_POSSIBLE=y # CONFIG_SSB is not set # # Multifunction device drivers # +# CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_REGULATOR is not set # # Multimedia devices # + +# +# Multimedia core support +# # CONFIG_VIDEO_DEV is not set # CONFIG_DVB_CORE is not set -# CONFIG_DAB is not set +# CONFIG_VIDEO_MEDIA is not set # -# Graphics support +# Multimedia drivers # -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_DAB is not set # -# Display device support +# Graphics support # -# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set # CONFIG_VGASTATE is not set CONFIG_VIDEO_OUTPUT_CONTROL=m CONFIG_FB=y # CONFIG_FIRMWARE_EDID is not set # CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set # CONFIG_FB_SYS_FILLRECT is not set # CONFIG_FB_SYS_COPYAREA is not set # CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set -CONFIG_FB_DEFERRED_IO=y # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -860,6 +945,7 @@ CONFIG_FB_STI=y # CONFIG_FB_S3 is not set # CONFIG_FB_SAVAGE is not set # CONFIG_FB_SIS is not set +# CONFIG_FB_VIA is not set # CONFIG_FB_NEOMAGIC is not set # CONFIG_FB_KYRO is not set # CONFIG_FB_3DFX is not set @@ -868,7 +954,16 @@ CONFIG_FB_STI=y # CONFIG_FB_TRIDENT is not set # CONFIG_FB_ARK is not set # CONFIG_FB_PM3 is not set +# CONFIG_FB_CARMINE is not set # CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set # # Console display driver support @@ -896,15 +991,8 @@ CONFIG_LOGO=y # CONFIG_LOGO_LINUX_VGA16 is not set # CONFIG_LOGO_LINUX_CLUT224 is not set CONFIG_LOGO_PARISC_CLUT224=y - -# -# Sound -# CONFIG_SOUND=y - -# -# Advanced Linux Sound Architecture -# +CONFIG_SOUND_OSS_CORE=y CONFIG_SND=y CONFIG_SND_TIMER=y CONFIG_SND_PCM=y @@ -920,11 +1008,9 @@ CONFIG_SND_SUPPORT_OLD_API=y CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set - -# -# Generic devices -# +CONFIG_SND_VMASTER=y CONFIG_SND_AC97_CODEC=y +CONFIG_SND_DRIVERS=y # CONFIG_SND_DUMMY is not set # CONFIG_SND_VIRMIDI is not set # CONFIG_SND_MTPAV is not set @@ -932,10 +1018,8 @@ CONFIG_SND_AC97_CODEC=y # CONFIG_SND_SERIAL_U16550 is not set # CONFIG_SND_MPU401 is not set # CONFIG_SND_PORTMAN2X4 is not set - -# -# PCI devices -# +# CONFIG_SND_AC97_POWER_SAVE is not set +CONFIG_SND_PCI=y CONFIG_SND_AD1889=y # CONFIG_SND_ALS300 is not set # CONFIG_SND_ALI5451 is not set @@ -944,10 +1028,12 @@ CONFIG_SND_AD1889=y # CONFIG_SND_AU8810 is not set # CONFIG_SND_AU8820 is not set # CONFIG_SND_AU8830 is not set +# CONFIG_SND_AW2 is not set # CONFIG_SND_AZT3328 is not set # CONFIG_SND_BT87X is not set # CONFIG_SND_CA0106 is not set # CONFIG_SND_CMIPCI is not set +# CONFIG_SND_OXYGEN is not set # CONFIG_SND_CS4281 is not set # CONFIG_SND_CS46XX is not set # CONFIG_SND_DARLA20 is not set @@ -972,6 +1058,7 @@ CONFIG_SND_AD1889=y # CONFIG_SND_HDA_INTEL is not set # CONFIG_SND_HDSP is not set # CONFIG_SND_HDSPM is not set +# CONFIG_SND_HIFIER is not set # CONFIG_SND_ICE1712 is not set # CONFIG_SND_ICE1724 is not set # CONFIG_SND_INTEL8X0 is not set @@ -989,58 +1076,67 @@ CONFIG_SND_AD1889=y # CONFIG_SND_TRIDENT is not set # CONFIG_SND_VIA82XX is not set # CONFIG_SND_VIA82XX_MODEM is not set +# CONFIG_SND_VIRTUOSO is not set # CONFIG_SND_VX222 is not set # CONFIG_SND_YMFPCI is not set -# CONFIG_SND_AC97_POWER_SAVE is not set - -# -# USB devices -# +CONFIG_SND_USB=y # CONFIG_SND_USB_AUDIO is not set # CONFIG_SND_USB_CAIAQ is not set - -# -# PCMCIA devices -# +CONFIG_SND_PCMCIA=y # CONFIG_SND_VXPOCKET is not set # CONFIG_SND_PDAUDIOCF is not set - -# -# GSC devices -# +CONFIG_SND_GSC=y CONFIG_SND_HARMONY=y - -# -# System on Chip audio support -# # CONFIG_SND_SOC is not set - -# -# SoC Audio support for SuperH -# - -# -# Open Sound System -# # CONFIG_SOUND_PRIME is not set CONFIG_AC97_BUS=y CONFIG_HID_SUPPORT=y CONFIG_HID=y CONFIG_HID_DEBUG=y +# CONFIG_HIDRAW is not set # # USB Input Devices # CONFIG_USB_HID=y -# CONFIG_USB_HIDINPUT_POWERBOOK is not set -# CONFIG_HID_FF is not set +# CONFIG_HID_PID is not set # CONFIG_USB_HIDDEV is not set + +# +# Special HID drivers +# +CONFIG_HID_COMPAT=y +CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_EZKEY=y +CONFIG_HID_GYRATION=y +CONFIG_HID_LOGITECH=y +# CONFIG_LOGITECH_FF is not set +# CONFIG_LOGIRUMBLEPAD2_FF is not set +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_NTRIG=y +CONFIG_HID_PANTHERLORD=y +# CONFIG_PANTHERLORD_FF is not set +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SONY=y +CONFIG_HID_SUNPLUS=y +# CONFIG_GREENASIA_FF is not set +CONFIG_HID_TOPSEED=y +# CONFIG_THRUSTMASTER_FF is not set +# CONFIG_ZEROPLUS_FF is not set CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y CONFIG_USB_ARCH_HAS_EHCI=y CONFIG_USB=y # CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set # # Miscellaneous USB options @@ -1049,12 +1145,18 @@ CONFIG_USB_DEVICEFS=y CONFIG_USB_DEVICE_CLASS=y # CONFIG_USB_DYNAMIC_MINORS is not set # CONFIG_USB_OTG is not set +CONFIG_USB_MON=y +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set # # USB Host Controller Drivers # +# CONFIG_USB_C67X00_HCD is not set # CONFIG_USB_EHCI_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set @@ -1062,19 +1164,23 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y CONFIG_USB_UHCI_HCD=y # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_WHCI_HCD is not set +# CONFIG_USB_HWA_HCD is not set # # USB Device Class drivers # # CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; # # -# may also be needed; see USB_STORAGE Help for more information +# see USB_STORAGE Help for more information # # CONFIG_USB_STORAGE is not set # CONFIG_USB_LIBUSUAL is not set @@ -1084,16 +1190,11 @@ CONFIG_USB_UHCI_HCD=y # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set -CONFIG_USB_MON=y # # USB port drivers # # CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support -# # CONFIG_USB_SERIAL is not set # @@ -1102,7 +1203,7 @@ CONFIG_USB_MON=y # CONFIG_USB_EMI62 is not set # CONFIG_USB_EMI26 is not set # CONFIG_USB_ADUTUX is not set -# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_SEVSEG is not set # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set @@ -1118,38 +1219,60 @@ CONFIG_USB_MON=y # CONFIG_USB_TRANCEVIBRATOR is not set # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set +# CONFIG_USB_GADGET is not set # -# USB DSL modem support -# - -# -# USB Gadget Support +# OTG and related infrastructure # -# CONFIG_USB_GADGET is not set +# CONFIG_UWB is not set # CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set -# CONFIG_RTC_CLASS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set # -# DMA Engine support +# RTC interfaces # -# CONFIG_DMA_ENGINE is not set +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set # -# DMA Clients +# SPI RTC drivers # # -# DMA Devices +# Platform RTC drivers # -# CONFIG_AUXDISPLAY is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_V3020 is not set # -# Userspace I/O +# on-CPU RTC drivers # +CONFIG_RTC_DRV_PARISC=y +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set +# CONFIG_STAGING is not set # # File systems @@ -1159,21 +1282,20 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set -# CONFIG_EXT4DEV_FS is not set +# CONFIG_EXT4_FS is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set -# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=y # CONFIG_AUTOFS4_FS is not set # CONFIG_FUSE_FS is not set @@ -1202,16 +1324,13 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y # CONFIG_CONFIGFS_FS is not set - -# -# Miscellaneous filesystems -# +CONFIG_MISC_FILESYSTEMS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_ECRYPT_FS is not set @@ -1221,33 +1340,32 @@ CONFIG_RAMFS=y # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set - -# -# Network File Systems -# +CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set # CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set +CONFIG_ROOT_NFS=y CONFIG_NFSD=y CONFIG_NFSD_V3=y # CONFIG_NFSD_V3_ACL is not set CONFIG_NFSD_V4=y -CONFIG_NFSD_TCP=y -CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y -# CONFIG_SUNRPC_BIND34 is not set +# CONFIG_SUNRPC_REGISTER_V4 is not set CONFIG_RPCSEC_GSS_KRB5=y CONFIG_RPCSEC_GSS_SPKM3=m CONFIG_SMB_FS=m @@ -1256,6 +1374,7 @@ CONFIG_SMB_NLS_REMOTE="cp437" CONFIG_CIFS=m # CONFIG_CIFS_STATS is not set # CONFIG_CIFS_WEAK_PW_HASH is not set +# CONFIG_CIFS_UPCALL is not set # CONFIG_CIFS_XATTR is not set # CONFIG_CIFS_DEBUG2 is not set # CONFIG_CIFS_EXPERIMENTAL is not set @@ -1268,10 +1387,6 @@ CONFIG_CIFS=m # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y - -# -# Native Language Support -# CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" CONFIG_NLS_CODEPAGE_437=y @@ -1312,33 +1427,28 @@ CONFIG_NLS_ISO8859_15=m CONFIG_NLS_KOI8_R=m CONFIG_NLS_KOI8_U=m CONFIG_NLS_UTF8=y - -# -# Distributed Lock Manager -# # CONFIG_DLM is not set -# -# Profiling support -# -CONFIG_PROFILING=y -CONFIG_OPROFILE=m - # # Kernel hacking # # CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 CONFIG_MAGIC_SYSRQ=y # CONFIG_UNUSED_SYMBOLS is not set -# CONFIG_DEBUG_FS is not set +CONFIG_DEBUG_FS=y CONFIG_HEADERS_CHECK=y CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SHIRQ is not set CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set @@ -1350,10 +1460,33 @@ CONFIG_DEBUG_MUTEXES=y CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y # CONFIG_DEBUG_LIST is not set -CONFIG_FORCED_INLINING=y +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_FAULT_INJECTION is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_NOP_TRACER=y +CONFIG_RING_BUFFER=y +CONFIG_TRACING=y + +# +# Tracers +# +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_FTRACE_STARTUP_TEST is not set +# CONFIG_BUILD_DOCSRC is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set # CONFIG_DEBUG_RODATA is not set # @@ -1362,56 +1495,112 @@ CONFIG_FORCED_INLINING=y CONFIG_KEYS=y CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_GF128MUL is not set +CONFIG_CRYPTO_NULL=m +# CONFIG_CRYPTO_CRYPTD is not set +CONFIG_CRYPTO_AUTHENC=y +CONFIG_CRYPTO_TEST=m + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set -CONFIG_CRYPTO_NULL=m + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=m CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=m +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_TGR192=m -# CONFIG_CRYPTO_GF128MUL is not set -# CONFIG_CRYPTO_ECB is not set -CONFIG_CRYPTO_CBC=y -# CONFIG_CRYPTO_PCBC is not set -# CONFIG_CRYPTO_LRW is not set -# CONFIG_CRYPTO_XTS is not set -# CONFIG_CRYPTO_CRYPTD is not set -CONFIG_CRYPTO_DES=y -# CONFIG_CRYPTO_FCRYPT is not set -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_TWOFISH_COMMON=m -CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_WP512=m + +# +# Ciphers +# CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_BLOWFISH=m +# CONFIG_CRYPTO_CAMELLIA is not set CONFIG_CRYPTO_CAST5=m CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_TEA=m -CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set CONFIG_CRYPTO_KHAZAD=m -CONFIG_CRYPTO_ANUBIS=m +# CONFIG_CRYPTO_SALSA20 is not set # CONFIG_CRYPTO_SEED is not set +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_TWOFISH_COMMON=m + +# +# Compression +# CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_CRC32C=m -# CONFIG_CRYPTO_CAMELLIA is not set -CONFIG_CRYPTO_TEST=m -# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set # # Library routines # CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y CONFIG_CRC_CCITT=m # CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set # CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y # CONFIG_CRC7 is not set -- GitLab From bb6ac72fb19c6676eb8bafa8e3b8bf970a2294a2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 13 Mar 2009 09:02:42 +0100 Subject: [PATCH 3242/4982] ALSA: hda - power up before codec initialization Change the power state of each widget before starting the initialization work so that all verbs are executed properly. Also, keep power-up during hwdep reconfiguration. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 15 ++++++++------- sound/pci/hda/hda_hwdep.c | 14 +++++++++----- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 1885e764910..cf6339436de 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -842,6 +842,9 @@ static void snd_hda_codec_free(struct hda_codec *codec) kfree(codec); } +static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, + unsigned int power_state); + /** * snd_hda_codec_new - create a HDA codec * @bus: the bus to assign @@ -941,6 +944,11 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr if (bus->modelname) codec->modelname = kstrdup(bus->modelname, GFP_KERNEL); + /* power-up all before initialization */ + hda_set_power_state(codec, + codec->afg ? codec->afg : codec->mfg, + AC_PWRST_D0); + if (do_init) { err = snd_hda_codec_configure(codec); if (err < 0) @@ -2413,19 +2421,12 @@ EXPORT_SYMBOL_HDA(snd_hda_build_controls); int snd_hda_codec_build_controls(struct hda_codec *codec) { int err = 0; - /* fake as if already powered-on */ - hda_keep_power_on(codec); - /* then fire up */ - hda_set_power_state(codec, - codec->afg ? codec->afg : codec->mfg, - AC_PWRST_D0); hda_exec_init_verbs(codec); /* continue to initialize... */ if (codec->patch_ops.init) err = codec->patch_ops.init(codec); if (!err && codec->patch_ops.build_controls) err = codec->patch_ops.build_controls(codec); - snd_hda_power_down(codec); if (err < 0) return err; return 0; diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c index 1e3ccc740af..1c57505c287 100644 --- a/sound/pci/hda/hda_hwdep.c +++ b/sound/pci/hda/hda_hwdep.c @@ -176,25 +176,29 @@ static int reconfig_codec(struct hda_codec *codec) { int err; + snd_hda_power_up(codec); snd_printk(KERN_INFO "hda-codec: reconfiguring\n"); err = snd_hda_codec_reset(codec); if (err < 0) { snd_printk(KERN_ERR "The codec is being used, can't reconfigure.\n"); - return err; + goto error; } err = snd_hda_codec_configure(codec); if (err < 0) - return err; + goto error; /* rebuild PCMs */ err = snd_hda_codec_build_pcms(codec); if (err < 0) - return err; + goto error; /* rebuild mixers */ err = snd_hda_codec_build_controls(codec); if (err < 0) - return err; - return snd_card_register(codec->bus->card); + goto error; + err = snd_card_register(codec->bus->card); + error: + snd_hda_power_down(codec); + return err; } /* -- GitLab From aac429707df233e9dc7ed70ea04cd29d832dfe61 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Mon, 16 Feb 2009 20:40:55 +0300 Subject: [PATCH 3243/4982] [ARM] pxa: add initial support for Cogent CSB726 board Signed-off-by: Dmitry Eremin-Solenikov Signed-off-by: Eric Miao --- arch/arm/mach-pxa/Kconfig | 8 + arch/arm/mach-pxa/Makefile | 1 + arch/arm/mach-pxa/csb726.c | 318 ++++++++++++++++++++ arch/arm/mach-pxa/include/mach/csb726.h | 26 ++ arch/arm/mach-pxa/include/mach/uncompress.h | 3 +- 5 files changed, 355 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-pxa/csb726.c create mode 100644 arch/arm/mach-pxa/include/mach/csb726.h diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 33214c1e060..ff1872db5b3 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -393,6 +393,14 @@ config PCM990_DISPLAY_NONE endchoice +config MACH_CSB726 + bool "Enable Cogent CSB726 System On a Module" + select PXA27x + select IWMMXT + help + Say Y here if you intend to run this kernel on a Cogent + CSB726 System On Module. + config PXA_EZX bool "Motorola EZX Platform" select PXA27x diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 361fcfa7531..96a72f02c13 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -75,6 +75,7 @@ obj-$(CONFIG_MACH_CM_X300) += cm-x300.o obj-$(CONFIG_PXA_EZX) += ezx.o obj-$(CONFIG_MACH_INTELMOTE2) += imote2.o +obj-$(CONFIG_MACH_CSB726) += csb726.o # Support for blinky lights led-y := leds.o diff --git a/arch/arm/mach-pxa/csb726.c b/arch/arm/mach-pxa/csb726.c new file mode 100644 index 00000000000..2b289f83a61 --- /dev/null +++ b/arch/arm/mach-pxa/csb726.c @@ -0,0 +1,318 @@ +/* + * Support for Cogent CSB726 + * + * Copyright (c) 2008 Dmitry Eremin-Solenikov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "generic.h" +#include "devices.h" + +/* + * n/a: 2, 5, 6, 7, 8, 23, 24, 25, 26, 27, 87, 88, 89, + * nu: 58 -- 77, 90, 91, 93, 102, 105-108, 114-116, + * XXX: 21, + * XXX: 79 CS_3 for LAN9215 or PSKTSEL on R2, R3 + * XXX: 33 CS_5 for LAN9215 on R1 + */ + +static unsigned long csb726_pin_config[] = { + GPIO78_nCS_2, /* EXP_CS */ + GPIO79_nCS_3, /* SMSC9215 */ + GPIO80_nCS_4, /* SM501 */ + + GPIO52_GPIO, /* #SMSC9251 int */ + GPIO53_GPIO, /* SM501 int */ + + GPIO1_GPIO, /* GPIO0 */ + GPIO11_GPIO, /* GPIO1 */ + GPIO9_GPIO, /* GPIO2 */ + GPIO10_GPIO, /* GPIO3 */ + GPIO16_PWM0_OUT, /* or GPIO4 */ + GPIO17_PWM1_OUT, /* or GPIO5 */ + GPIO94_GPIO, /* GPIO6 */ + GPIO95_GPIO, /* GPIO7 */ + GPIO96_GPIO, /* GPIO8 */ + GPIO97_GPIO, /* GPIO9 */ + GPIO15_GPIO, /* EXP_IRQ */ + GPIO18_RDY, /* EXP_WAIT */ + + GPIO0_GPIO, /* PWR_INT */ + GPIO104_GPIO, /* PWR_OFF */ + + GPIO12_GPIO, /* touch irq */ + + GPIO13_SSP2_TXD, + GPIO14_SSP2_SFRM, + MFP_CFG_OUT(GPIO19, AF1, DRIVE_LOW),/* SSP2_SYSCLK */ + GPIO22_SSP2_SCLK, + + GPIO81_SSP3_TXD, + GPIO82_SSP3_RXD, + GPIO83_SSP3_SFRM, + GPIO84_SSP3_SCLK, + + GPIO20_GPIO, /* SDIO int */ + GPIO32_MMC_CLK, + GPIO92_MMC_DAT_0, + GPIO109_MMC_DAT_1, + GPIO110_MMC_DAT_2, + GPIO111_MMC_DAT_3, + GPIO112_MMC_CMD, + GPIO100_GPIO, /* SD CD */ + GPIO101_GPIO, /* SD WP */ + + GPIO28_AC97_BITCLK, + GPIO29_AC97_SDATA_IN_0, + GPIO30_AC97_SDATA_OUT, + GPIO31_AC97_SYNC, + GPIO113_AC97_nRESET, + + GPIO34_FFUART_RXD, + GPIO35_FFUART_CTS, + GPIO36_FFUART_DCD, + GPIO37_FFUART_DSR, + GPIO38_FFUART_RI, + GPIO39_FFUART_TXD, + GPIO40_FFUART_DTR, + GPIO41_FFUART_RTS, + + GPIO42_BTUART_RXD, + GPIO43_BTUART_TXD, + GPIO44_BTUART_CTS, + GPIO45_BTUART_RTS, + + GPIO46_STUART_RXD, + GPIO47_STUART_TXD, + + GPIO48_nPOE, + GPIO49_nPWE, + GPIO50_nPIOR, + GPIO51_nPIOW, + GPIO54_nPCE_2, + GPIO55_nPREG, + GPIO56_nPWAIT, + GPIO57_nIOIS16, /* maybe unused */ + GPIO85_nPCE_1, + GPIO98_GPIO, /* CF IRQ */ + GPIO99_GPIO, /* CF CD */ + GPIO103_GPIO, /* Reset */ + + GPIO117_I2C_SCL, + GPIO118_I2C_SDA, +}; + +static struct pxamci_platform_data csb726_mci_data; + +static int csb726_mci_init(struct device *dev, + irq_handler_t detect, void *data) +{ + int err; + + csb726_mci_data.detect_delay = msecs_to_jiffies(500); + + err = gpio_request(CSB726_GPIO_MMC_DETECT, "MMC detect"); + if (err) + goto err_det_req; + + err = gpio_direction_input(CSB726_GPIO_MMC_DETECT); + if (err) + goto err_det_dir; + + err = gpio_request(CSB726_GPIO_MMC_RO, "MMC ro"); + if (err) + goto err_ro_req; + + err = gpio_direction_input(CSB726_GPIO_MMC_RO); + if (err) + goto err_ro_dir; + + err = request_irq(gpio_to_irq(CSB726_GPIO_MMC_DETECT), detect, + IRQF_DISABLED, "MMC card detect", data); + if (err) + goto err_irq; + + return 0; + +err_irq: +err_ro_dir: + gpio_free(CSB726_GPIO_MMC_RO); +err_ro_req: +err_det_dir: + gpio_free(CSB726_GPIO_MMC_DETECT); +err_det_req: + return err; +} + +static int csb726_mci_get_ro(struct device *dev) +{ + return gpio_get_value(CSB726_GPIO_MMC_RO); +} + +static void csb726_mci_exit(struct device *dev, void *data) +{ + free_irq(gpio_to_irq(CSB726_GPIO_MMC_DETECT), data); + gpio_free(CSB726_GPIO_MMC_RO); + gpio_free(CSB726_GPIO_MMC_DETECT); +} + +static struct pxamci_platform_data csb726_mci = { + .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, + .init = csb726_mci_init, + .get_ro = csb726_mci_get_ro, + /* FIXME setpower */ + .exit = csb726_mci_exit, +}; + +static struct pxaohci_platform_data csb726_ohci_platform_data = { + .port_mode = PMM_NPS_MODE, + .flags = ENABLE_PORT1 | NO_OC_PROTECTION, +}; + +static struct mtd_partition csb726_flash_partitions[] = { + { + .name = "Bootloader", + .offset = 0, + .size = CSB726_FLASH_uMON, + .mask_flags = MTD_WRITEABLE /* force read-only */ + }, + { + .name = "root", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + } +}; + +static struct physmap_flash_data csb726_flash_data = { + .width = 2, + .parts = csb726_flash_partitions, + .nr_parts = ARRAY_SIZE(csb726_flash_partitions), +}; + +static struct resource csb726_flash_resources[] = { + { + .start = PXA_CS0_PHYS, + .end = PXA_CS0_PHYS + CSB726_FLASH_SIZE - 1 , + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device csb726_flash = { + .name = "physmap-flash", + .dev = { + .platform_data = &csb726_flash_data, + }, + .resource = csb726_flash_resources, + .num_resources = ARRAY_SIZE(csb726_flash_resources), +}; + +static struct resource csb726_sm501_resources[] = { + { + .start = PXA_CS4_PHYS, + .end = PXA_CS4_PHYS + SZ_8M - 1, + .flags = IORESOURCE_MEM, + .name = "sm501-localmem", + }, + { + .start = PXA_CS4_PHYS + SZ_64M - SZ_2M, + .end = PXA_CS4_PHYS + SZ_64M - 1, + .flags = IORESOURCE_MEM, + .name = "sm501-regs", + }, + { + .start = CSB726_IRQ_SM501, + .end = CSB726_IRQ_SM501, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct sm501_initdata csb726_sm501_initdata = { +/* .devices = SM501_USE_USB_HOST, */ + .devices = SM501_USE_USB_HOST | SM501_USE_UART0 | SM501_USE_UART1, +}; + +static struct sm501_platdata csb726_sm501_platdata = { + .init = &csb726_sm501_initdata, +}; + +static struct platform_device csb726_sm501 = { + .name = "sm501", + .id = 0, + .num_resources = ARRAY_SIZE(csb726_sm501_resources), + .resource = csb726_sm501_resources, + .dev = { + .platform_data = &csb726_sm501_platdata, + }, +}; + +static struct resource csb726_lan_resources[] = { + { + .start = PXA_CS3_PHYS, + .end = PXA_CS3_PHYS + SZ_64K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = CSB726_IRQ_LAN, + .end = CSB726_IRQ_LAN, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device csb726_lan = { + .name = "smc911x", + .id = -1, + .num_resources = ARRAY_SIZE(csb726_lan_resources), + .resource = csb726_lan_resources, +}; + +static struct platform_device *devices[] __initdata = { + &csb726_flash, + &csb726_sm501, + &csb726_lan, +}; + +static void __init csb726_init(void) +{ + pxa2xx_mfp_config(ARRAY_AND_SIZE(csb726_pin_config)); +/* MSC1 = 0x7ffc3ffc; *//* LAN9215/EXP_CS */ +/* MSC2 = 0x06697ff4; *//* none/SM501 */ + MSC2 = (MSC2 & ~0xffff) | 0x7ff4; /* SM501 */ + + pxa_set_i2c_info(NULL); + pxa27x_set_i2c_power_info(NULL); + pxa_set_mci_info(&csb726_mci); + pxa_set_ohci_info(&csb726_ohci_platform_data); + + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +MACHINE_START(CSB726, "Cogent CSB726") + .phys_io = 0x40000000, + .boot_params = 0xa0000100, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .map_io = pxa_map_io, + .init_irq = pxa27x_init_irq, + .init_machine = csb726_init, + .timer = &pxa_timer, +MACHINE_END diff --git a/arch/arm/mach-pxa/include/mach/csb726.h b/arch/arm/mach-pxa/include/mach/csb726.h new file mode 100644 index 00000000000..747ab1a71f2 --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/csb726.h @@ -0,0 +1,26 @@ +/* + * Support for Cogent CSB726 + * + * Copyright (c) 2008 Dmitry Baryshkov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#ifndef CSB726_H +#define CSB726_H + +#define CSB726_GPIO_IRQ_LAN 52 +#define CSB726_GPIO_IRQ_SM501 53 +#define CSB726_GPIO_MMC_DETECT 100 +#define CSB726_GPIO_MMC_RO 101 + +#define CSB726_FLASH_SIZE (64 * 1024 * 1024) +#define CSB726_FLASH_uMON (8 * 1024 * 1024) + +#define CSB726_IRQ_LAN gpio_to_irq(CSB726_GPIO_IRQ_LAN) +#define CSB726_IRQ_SM501 gpio_to_irq(CSB726_GPIO_IRQ_SM501) + +#endif + diff --git a/arch/arm/mach-pxa/include/mach/uncompress.h b/arch/arm/mach-pxa/include/mach/uncompress.h index f4b029c0395..5706cea95d1 100644 --- a/arch/arm/mach-pxa/include/mach/uncompress.h +++ b/arch/arm/mach-pxa/include/mach/uncompress.h @@ -35,7 +35,8 @@ static inline void flush(void) static inline void arch_decomp_setup(void) { - if (machine_is_littleton() || machine_is_intelmote2()) + if (machine_is_littleton() || machine_is_intelmote2() + || machine_is_csb726()) UART = STUART; } -- GitLab From 3b31fabfe258ecc1ffccd01dd186a534d5c804b3 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Mon, 16 Feb 2009 20:40:57 +0300 Subject: [PATCH 3244/4982] [ARM] pxa: add support for CSB701 baseboard CSB701 is one of baseboards that can be used with CSB726 SOM. This currently adds support for button and LED on the board. More to come later. Signed-off-by: Dmitry Eremin-Solenikov Signed-off-by: Eric Miao --- arch/arm/mach-pxa/Kconfig | 4 +++ arch/arm/mach-pxa/Makefile | 1 + arch/arm/mach-pxa/csb701.c | 61 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 arch/arm/mach-pxa/csb701.c diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index ff1872db5b3..d13282d773a 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -401,6 +401,10 @@ config MACH_CSB726 Say Y here if you intend to run this kernel on a Cogent CSB726 System On Module. +config CSB726_CSB701 + bool "Enable supprot for CSB701 baseboard" + depends on MACH_CSB726 + config PXA_EZX bool "Motorola EZX Platform" select PXA27x diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 96a72f02c13..8da8e63d048 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -76,6 +76,7 @@ obj-$(CONFIG_PXA_EZX) += ezx.o obj-$(CONFIG_MACH_INTELMOTE2) += imote2.o obj-$(CONFIG_MACH_CSB726) += csb726.o +obj-$(CONFIG_CSB726_CSB701) += csb701.o # Support for blinky lights led-y := leds.o diff --git a/arch/arm/mach-pxa/csb701.c b/arch/arm/mach-pxa/csb701.c new file mode 100644 index 00000000000..4a2a2952c37 --- /dev/null +++ b/arch/arm/mach-pxa/csb701.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include +#include + +static struct gpio_keys_button csb701_buttons[] = { + { + .code = 0x7, + .gpio = 1, + .active_low = 1, + .desc = "SW2", + .type = EV_SW, + .wakeup = 1, + }, +}; + +static struct gpio_keys_platform_data csb701_gpio_keys_data = { + .buttons = csb701_buttons, + .nbuttons = ARRAY_SIZE(csb701_buttons), +}; + +static struct gpio_led csb701_leds[] = { + { + .name = "csb701:yellow:heartbeat", + .default_trigger = "heartbeat", + .gpio = 11, + .active_low = 1, + }, +}; + +static struct platform_device csb701_gpio_keys = { + .name = "gpio-keys", + .id = -1, + .dev.platform_data = &csb701_gpio_keys_data, +}; + +static struct gpio_led_platform_data csb701_leds_gpio_data = { + .leds = csb701_leds, + .num_leds = ARRAY_SIZE(csb701_leds), +}; + +static struct platform_device csb701_leds_gpio = { + .name = "leds-gpio", + .id = -1, + .dev.platform_data = &csb701_leds_gpio_data, +}; + +static struct platform_device *devices[] __initdata = { + &csb701_gpio_keys, + &csb701_leds_gpio, +}; + +static int __init csb701_init(void) +{ + return platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +module_init(csb701_init); + -- GitLab From 689b4febeca7e98ad1986cf5b036539649cc1a0c Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Fri, 30 Jan 2009 20:48:24 +0100 Subject: [PATCH 3245/4982] [ARM] pxa/MioA701: add gpio_vbus driver Add gpio vbus detection to udc driver, by taking advantage of the new gpio_vbus driver. Signed-off-by: Robert Jarzmik Signed-off-by: Eric Miao --- arch/arm/mach-pxa/mioa701.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c index e77c95ca67f..735cb94c4a1 100644 --- a/arch/arm/mach-pxa/mioa701.c +++ b/arch/arm/mach-pxa/mioa701.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -452,6 +453,12 @@ static void udc_exit(void) mio_gpio_free(ARRAY_AND_SIZE(udc_gpios)); } +struct gpio_vbus_mach_info gpio_vbus_data = { + .gpio_vbus = GPIO13_nUSB_DETECT, + .gpio_vbus_inverted = 1, + .gpio_pullup = -1, +}; + /* * SDIO/MMC Card controller */ @@ -790,6 +797,7 @@ MIO_SIMPLE_DEV(pxa2xx_ac97, "pxa2xx-ac97", NULL) MIO_PARENT_DEV(mio_wm9713_codec, "wm9713-codec", &pxa2xx_ac97.dev, NULL) MIO_SIMPLE_DEV(mioa701_sound, "mioa701-wm9713", NULL) MIO_SIMPLE_DEV(mioa701_board, "mioa701-board", NULL) +MIO_SIMPLE_DEV(gpio_vbus, "gpio-vbus", &gpio_vbus_data); static struct platform_device *devices[] __initdata = { &mioa701_gpio_keys, @@ -801,7 +809,8 @@ static struct platform_device *devices[] __initdata = { &mioa701_sound, &power_dev, &strataflash, - &mioa701_board + &gpio_vbus, + &mioa701_board, }; static void mioa701_machine_exit(void); -- GitLab From cefdb2a4436ec83b4c8b349aa30f976d30c22e25 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 31 Jan 2009 21:07:09 +0100 Subject: [PATCH 3246/4982] [ARM] pxa/MioA701: Migrate after pxa27x_udc gpio_pullup functionality. Signed-off-by: Robert Jarzmik Signed-off-by: Eric Miao --- arch/arm/mach-pxa/mioa701.c | 35 ++--------------------------------- 1 file changed, 2 insertions(+), 33 deletions(-) diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c index 735cb94c4a1..025772785d3 100644 --- a/arch/arm/mach-pxa/mioa701.c +++ b/arch/arm/mach-pxa/mioa701.c @@ -413,21 +413,6 @@ static void gsm_exit(void) /* * USB UDC */ -static void udc_power_command(int cmd) -{ - switch (cmd) { - case PXA2XX_UDC_CMD_DISCONNECT: - gpio_set_value(GPIO22_USB_ENABLE, 0); - break; - case PXA2XX_UDC_CMD_CONNECT: - gpio_set_value(GPIO22_USB_ENABLE, 1); - break; - default: - printk(KERN_INFO "udc_control: unknown command (0x%x)!\n", cmd); - break; - } -} - static int is_usb_connected(void) { return !gpio_get_value(GPIO13_nUSB_DETECT); @@ -435,24 +420,9 @@ static int is_usb_connected(void) static struct pxa2xx_udc_mach_info mioa701_udc_info = { .udc_is_connected = is_usb_connected, - .udc_command = udc_power_command, + .gpio_pullup = GPIO22_USB_ENABLE, }; -struct gpio_ress udc_gpios[] = { - MIO_GPIO_OUT(GPIO22_USB_ENABLE, 0, "USB Vbus enable") -}; - -static int __init udc_init(void) -{ - pxa_set_udc_info(&mioa701_udc_info); - return mio_gpio_request(ARRAY_AND_SIZE(udc_gpios)); -} - -static void udc_exit(void) -{ - mio_gpio_free(ARRAY_AND_SIZE(udc_gpios)); -} - struct gpio_vbus_mach_info gpio_vbus_data = { .gpio_vbus = GPIO13_nUSB_DETECT, .gpio_vbus_inverted = 1, @@ -847,7 +817,7 @@ static void __init mioa701_machine_init(void) pxa_set_mci_info(&mioa701_mci_info); pxa_set_keypad_info(&mioa701_keypad_info); wm97xx_bat_set_pdata(&mioa701_battery_data); - udc_init(); + pxa_set_udc_info(&mioa701_udc_info); pm_power_off = mioa701_poweroff; arm_pm_restart = mioa701_restart; platform_add_devices(devices, ARRAY_SIZE(devices)); @@ -860,7 +830,6 @@ static void __init mioa701_machine_init(void) static void mioa701_machine_exit(void) { - udc_exit(); bootstrap_exit(); gsm_exit(); } -- GitLab From ccfe30a7c8329e85ae426813a1060e27e2547dd1 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Thu, 29 Jan 2009 10:07:50 +0100 Subject: [PATCH 3247/4982] arm/imx2x: new IOMUX definitions * removed iomux-mx1-mx2.h completely * distributes the former contents to four different files (iomux-mx1.h, iomux-mx21.h, iomux-mx27.h and the file iomux-mx2x.h, which is common to both i.MX21 and i.MX27). * adds all documented IOMUX definitions for i.MX21 and i.MX27 * fixes a few that were wrong (PD14_AOUT_FEC_CLR, PE16_AF_RTCK). * don't silenly include * and fixes all collateral damage from above Signed-off-by: Holger Schurig Signed-off-by: Sascha Hauer --- arch/arm/mach-mx1/devices.c | 1 + arch/arm/mach-mx1/mx1ads.c | 2 +- arch/arm/mach-mx2/mx27ads.c | 4 +- arch/arm/mach-mx2/pcm038.c | 7 +- .../arm/plat-mxc/include/mach/iomux-mx1-mx2.h | 416 ------------------ arch/arm/plat-mxc/include/mach/iomux-mx1.h | 166 +++++++ arch/arm/plat-mxc/include/mach/iomux-mx21.h | 126 ++++++ arch/arm/plat-mxc/include/mach/iomux-mx27.h | 207 +++++++++ arch/arm/plat-mxc/include/mach/iomux-mx2x.h | 237 ++++++++++ arch/arm/plat-mxc/include/mach/iomux.h | 127 ++++++ arch/arm/plat-mxc/iomux-mx1-mx2.c | 2 +- 11 files changed, 872 insertions(+), 423 deletions(-) delete mode 100644 arch/arm/plat-mxc/include/mach/iomux-mx1-mx2.h create mode 100644 arch/arm/plat-mxc/include/mach/iomux-mx1.h create mode 100644 arch/arm/plat-mxc/include/mach/iomux-mx21.h create mode 100644 arch/arm/plat-mxc/include/mach/iomux-mx27.h create mode 100644 arch/arm/plat-mxc/include/mach/iomux-mx2x.h create mode 100644 arch/arm/plat-mxc/include/mach/iomux.h diff --git a/arch/arm/mach-mx1/devices.c b/arch/arm/mach-mx1/devices.c index 686d8d2dbb2..cea8f2c7119 100644 --- a/arch/arm/mach-mx1/devices.c +++ b/arch/arm/mach-mx1/devices.c @@ -23,6 +23,7 @@ #include #include #include +#include #include static struct resource imx_csi_resources[] = { diff --git a/arch/arm/mach-mx1/mx1ads.c b/arch/arm/mach-mx1/mx1ads.c index 2e4b185fe4a..be7dd75ebbe 100644 --- a/arch/arm/mach-mx1/mx1ads.c +++ b/arch/arm/mach-mx1/mx1ads.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include "devices.h" /* diff --git a/arch/arm/mach-mx2/mx27ads.c b/arch/arm/mach-mx2/mx27ads.c index 2b5c67f5457..7721c470d5a 100644 --- a/arch/arm/mach-mx2/mx27ads.c +++ b/arch/arm/mach-mx2/mx27ads.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include "devices.h" @@ -196,7 +196,7 @@ static int mxc_fec_pins[] = { PD11_AOUT_FEC_TX_CLK, PD12_AOUT_FEC_RXD0, PD13_AOUT_FEC_RX_DV, - PD14_AOUT_FEC_CLR, + PD14_AOUT_FEC_RX_CLK, PD15_AOUT_FEC_COL, PD16_AIN_FEC_TX_ER, PF23_AIN_FEC_TX_EN diff --git a/arch/arm/mach-mx2/pcm038.c b/arch/arm/mach-mx2/pcm038.c index dfd4156da7d..534fd9a4ff9 100644 --- a/arch/arm/mach-mx2/pcm038.c +++ b/arch/arm/mach-mx2/pcm038.c @@ -20,11 +20,12 @@ #include #include #include +#include #include #include #include #include -#include +#include #include #include #include @@ -170,7 +171,7 @@ static int mxc_fec_pins[] = { PD11_AOUT_FEC_TX_CLK, PD12_AOUT_FEC_RXD0, PD13_AOUT_FEC_RX_DV, - PD14_AOUT_FEC_CLR, + PD14_AOUT_FEC_RX_CLK, PD15_AOUT_FEC_COL, PD16_AIN_FEC_TX_ER, PF23_AIN_FEC_TX_EN @@ -217,7 +218,7 @@ static void __init pcm038_init(void) mxc_register_device(&mxc_uart_device1, &uart_pdata[1]); mxc_register_device(&mxc_uart_device2, &uart_pdata[2]); - mxc_gpio_mode(PE16_AF_RTCK); /* OWIRE */ + mxc_gpio_mode(PE16_AF_OWIRE); mxc_register_device(&mxc_nand_device, &pcm038_nand_board_info); platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx1-mx2.h b/arch/arm/plat-mxc/include/mach/iomux-mx1-mx2.h deleted file mode 100644 index 95a383be628..00000000000 --- a/arch/arm/plat-mxc/include/mach/iomux-mx1-mx2.h +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Copyright (C) 2008 by Sascha Hauer - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ - -#ifndef _MXC_GPIO_MX1_MX2_H -#define _MXC_GPIO_MX1_MX2_H - -#include - -/* - * GPIO Module and I/O Multiplexer - * x = 0..3 for reg_A, reg_B, reg_C, reg_D - */ -#define VA_GPIO_BASE IO_ADDRESS(GPIO_BASE_ADDR) -#define MXC_DDIR(x) (0x00 + ((x) << 8)) -#define MXC_OCR1(x) (0x04 + ((x) << 8)) -#define MXC_OCR2(x) (0x08 + ((x) << 8)) -#define MXC_ICONFA1(x) (0x0c + ((x) << 8)) -#define MXC_ICONFA2(x) (0x10 + ((x) << 8)) -#define MXC_ICONFB1(x) (0x14 + ((x) << 8)) -#define MXC_ICONFB2(x) (0x18 + ((x) << 8)) -#define MXC_DR(x) (0x1c + ((x) << 8)) -#define MXC_GIUS(x) (0x20 + ((x) << 8)) -#define MXC_SSR(x) (0x24 + ((x) << 8)) -#define MXC_ICR1(x) (0x28 + ((x) << 8)) -#define MXC_ICR2(x) (0x2c + ((x) << 8)) -#define MXC_IMR(x) (0x30 + ((x) << 8)) -#define MXC_ISR(x) (0x34 + ((x) << 8)) -#define MXC_GPR(x) (0x38 + ((x) << 8)) -#define MXC_SWR(x) (0x3c + ((x) << 8)) -#define MXC_PUEN(x) (0x40 + ((x) << 8)) - -#ifdef CONFIG_ARCH_MX1 -# define GPIO_PORT_MAX 3 -#endif -#ifdef CONFIG_ARCH_MX2 -# define GPIO_PORT_MAX 5 -#endif - -#ifndef GPIO_PORT_MAX -# error "GPIO config port count unknown!" -#endif - -#define GPIO_PIN_MASK 0x1f - -#define GPIO_PORT_SHIFT 5 -#define GPIO_PORT_MASK (0x7 << GPIO_PORT_SHIFT) - -#define GPIO_PORTA (0 << GPIO_PORT_SHIFT) -#define GPIO_PORTB (1 << GPIO_PORT_SHIFT) -#define GPIO_PORTC (2 << GPIO_PORT_SHIFT) -#define GPIO_PORTD (3 << GPIO_PORT_SHIFT) -#define GPIO_PORTE (4 << GPIO_PORT_SHIFT) -#define GPIO_PORTF (5 << GPIO_PORT_SHIFT) - -#define GPIO_OUT (1 << 8) -#define GPIO_IN (0 << 8) -#define GPIO_PUEN (1 << 9) - -#define GPIO_PF (1 << 10) -#define GPIO_AF (1 << 11) - -#define GPIO_OCR_SHIFT 12 -#define GPIO_OCR_MASK (3 << GPIO_OCR_SHIFT) -#define GPIO_AIN (0 << GPIO_OCR_SHIFT) -#define GPIO_BIN (1 << GPIO_OCR_SHIFT) -#define GPIO_CIN (2 << GPIO_OCR_SHIFT) -#define GPIO_GPIO (3 << GPIO_OCR_SHIFT) - -#define GPIO_AOUT_SHIFT 14 -#define GPIO_AOUT_MASK (3 << GPIO_AOUT_SHIFT) -#define GPIO_AOUT (0 << GPIO_AOUT_SHIFT) -#define GPIO_AOUT_ISR (1 << GPIO_AOUT_SHIFT) -#define GPIO_AOUT_0 (2 << GPIO_AOUT_SHIFT) -#define GPIO_AOUT_1 (3 << GPIO_AOUT_SHIFT) - -#define GPIO_BOUT_SHIFT 16 -#define GPIO_BOUT_MASK (3 << GPIO_BOUT_SHIFT) -#define GPIO_BOUT (0 << GPIO_BOUT_SHIFT) -#define GPIO_BOUT_ISR (1 << GPIO_BOUT_SHIFT) -#define GPIO_BOUT_0 (2 << GPIO_BOUT_SHIFT) -#define GPIO_BOUT_1 (3 << GPIO_BOUT_SHIFT) - -extern void mxc_gpio_mode(int gpio_mode); -extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count, - const char *label); -extern void mxc_gpio_release_multiple_pins(const int *pin_list, int count); - -/*-------------------------------------------------------------------------*/ - -/* assignements for GPIO alternate/primary functions */ - -/* FIXME: This list is not completed. The correct directions are - * missing on some (many) pins - */ -#ifdef CONFIG_ARCH_MX1 -#define PA0_AIN_SPI2_CLK (GPIO_PORTA | GPIO_OUT | 0) -#define PA0_AF_ETMTRACESYNC (GPIO_PORTA | GPIO_AF | 0) -#define PA1_AOUT_SPI2_RXD (GPIO_PORTA | GPIO_IN | 1) -#define PA1_PF_TIN (GPIO_PORTA | GPIO_PF | 1) -#define PA2_PF_PWM0 (GPIO_PORTA | GPIO_OUT | GPIO_PF | 2) -#define PA3_PF_CSI_MCLK (GPIO_PORTA | GPIO_PF | 3) -#define PA4_PF_CSI_D0 (GPIO_PORTA | GPIO_PF | 4) -#define PA5_PF_CSI_D1 (GPIO_PORTA | GPIO_PF | 5) -#define PA6_PF_CSI_D2 (GPIO_PORTA | GPIO_PF | 6) -#define PA7_PF_CSI_D3 (GPIO_PORTA | GPIO_PF | 7) -#define PA8_PF_CSI_D4 (GPIO_PORTA | GPIO_PF | 8) -#define PA9_PF_CSI_D5 (GPIO_PORTA | GPIO_PF | 9) -#define PA10_PF_CSI_D6 (GPIO_PORTA | GPIO_PF | 10) -#define PA11_PF_CSI_D7 (GPIO_PORTA | GPIO_PF | 11) -#define PA12_PF_CSI_VSYNC (GPIO_PORTA | GPIO_PF | 12) -#define PA13_PF_CSI_HSYNC (GPIO_PORTA | GPIO_PF | 13) -#define PA14_PF_CSI_PIXCLK (GPIO_PORTA | GPIO_PF | 14) -#define PA15_PF_I2C_SDA (GPIO_PORTA | GPIO_OUT | GPIO_PF | 15) -#define PA16_PF_I2C_SCL (GPIO_PORTA | GPIO_OUT | GPIO_PF | 16) -#define PA17_AF_ETMTRACEPKT4 (GPIO_PORTA | GPIO_AF | 17) -#define PA17_AIN_SPI2_SS (GPIO_PORTA | GPIO_OUT | 17) -#define PA18_AF_ETMTRACEPKT5 (GPIO_PORTA | GPIO_AF | 18) -#define PA19_AF_ETMTRACEPKT6 (GPIO_PORTA | GPIO_AF | 19) -#define PA20_AF_ETMTRACEPKT7 (GPIO_PORTA | GPIO_AF | 20) -#define PA21_PF_A0 (GPIO_PORTA | GPIO_PF | 21) -#define PA22_PF_CS4 (GPIO_PORTA | GPIO_PF | 22) -#define PA23_PF_CS5 (GPIO_PORTA | GPIO_PF | 23) -#define PA24_PF_A16 (GPIO_PORTA | GPIO_PF | 24) -#define PA24_AF_ETMTRACEPKT0 (GPIO_PORTA | GPIO_AF | 24) -#define PA25_PF_A17 (GPIO_PORTA | GPIO_PF | 25) -#define PA25_AF_ETMTRACEPKT1 (GPIO_PORTA | GPIO_AF | 25) -#define PA26_PF_A18 (GPIO_PORTA | GPIO_PF | 26) -#define PA26_AF_ETMTRACEPKT2 (GPIO_PORTA | GPIO_AF | 26) -#define PA27_PF_A19 (GPIO_PORTA | GPIO_PF | 27) -#define PA27_AF_ETMTRACEPKT3 (GPIO_PORTA | GPIO_AF | 27) -#define PA28_PF_A20 (GPIO_PORTA | GPIO_PF | 28) -#define PA28_AF_ETMPIPESTAT0 (GPIO_PORTA | GPIO_AF | 28) -#define PA29_PF_A21 (GPIO_PORTA | GPIO_PF | 29) -#define PA29_AF_ETMPIPESTAT1 (GPIO_PORTA | GPIO_AF | 29) -#define PA30_PF_A22 (GPIO_PORTA | GPIO_PF | 30) -#define PA30_AF_ETMPIPESTAT2 (GPIO_PORTA | GPIO_AF | 30) -#define PA31_PF_A23 (GPIO_PORTA | GPIO_PF | 31) -#define PA31_AF_ETMTRACECLK (GPIO_PORTA | GPIO_AF | 31) -#define PB8_PF_SD_DAT0 (GPIO_PORTB | GPIO_PF | GPIO_PUEN | 8) -#define PB8_AF_MS_PIO (GPIO_PORTB | GPIO_AF | 8) -#define PB9_PF_SD_DAT1 (GPIO_PORTB | GPIO_PF | GPIO_PUEN | 9) -#define PB9_AF_MS_PI1 (GPIO_PORTB | GPIO_AF | 9) -#define PB10_PF_SD_DAT2 (GPIO_PORTB | GPIO_PF | GPIO_PUEN | 10) -#define PB10_AF_MS_SCLKI (GPIO_PORTB | GPIO_AF | 10) -#define PB11_PF_SD_DAT3 (GPIO_PORTB | GPIO_PF | 11) -#define PB11_AF_MS_SDIO (GPIO_PORTB | GPIO_AF | 11) -#define PB12_PF_SD_CLK (GPIO_PORTB | GPIO_PF | 12) -#define PB12_AF_MS_SCLK0 (GPIO_PORTB | GPIO_AF | 12) -#define PB13_PF_SD_CMD (GPIO_PORTB | GPIO_PF | GPIO_PUEN | 13) -#define PB13_AF_MS_BS (GPIO_PORTB | GPIO_AF | 13) -#define PB14_AF_SSI_RXFS (GPIO_PORTB | GPIO_AF | 14) -#define PB15_AF_SSI_RXCLK (GPIO_PORTB | GPIO_AF | 15) -#define PB16_AF_SSI_RXDAT (GPIO_PORTB | GPIO_IN | GPIO_AF | 16) -#define PB17_AF_SSI_TXDAT (GPIO_PORTB | GPIO_OUT | GPIO_AF | 17) -#define PB18_AF_SSI_TXFS (GPIO_PORTB | GPIO_AF | 18) -#define PB19_AF_SSI_TXCLK (GPIO_PORTB | GPIO_AF | 19) -#define PB20_PF_USBD_AFE (GPIO_PORTB | GPIO_PF | 20) -#define PB21_PF_USBD_OE (GPIO_PORTB | GPIO_PF | 21) -#define PB22_PFUSBD_RCV (GPIO_PORTB | GPIO_PF | 22) -#define PB23_PF_USBD_SUSPND (GPIO_PORTB | GPIO_PF | 23) -#define PB24_PF_USBD_VP (GPIO_PORTB | GPIO_PF | 24) -#define PB25_PF_USBD_VM (GPIO_PORTB | GPIO_PF | 25) -#define PB26_PF_USBD_VPO (GPIO_PORTB | GPIO_PF | 26) -#define PB27_PF_USBD_VMO (GPIO_PORTB | GPIO_PF | 27) -#define PB28_PF_UART2_CTS (GPIO_PORTB | GPIO_OUT | GPIO_PF | 28) -#define PB29_PF_UART2_RTS (GPIO_PORTB | GPIO_IN | GPIO_PF | 29) -#define PB30_PF_UART2_TXD (GPIO_PORTB | GPIO_OUT | GPIO_PF | 30) -#define PB31_PF_UART2_RXD (GPIO_PORTB | GPIO_IN | GPIO_PF | 31) -#define PC3_PF_SSI_RXFS (GPIO_PORTC | GPIO_PF | 3) -#define PC4_PF_SSI_RXCLK (GPIO_PORTC | GPIO_PF | 4) -#define PC5_PF_SSI_RXDAT (GPIO_PORTC | GPIO_IN | GPIO_PF | 5) -#define PC6_PF_SSI_TXDAT (GPIO_PORTC | GPIO_OUT | GPIO_PF | 6) -#define PC7_PF_SSI_TXFS (GPIO_PORTC | GPIO_PF | 7) -#define PC8_PF_SSI_TXCLK (GPIO_PORTC | GPIO_PF | 8) -#define PC9_PF_UART1_CTS (GPIO_PORTC | GPIO_OUT | GPIO_PF | 9) -#define PC10_PF_UART1_RTS (GPIO_PORTC | GPIO_IN | GPIO_PF | 10) -#define PC11_PF_UART1_TXD (GPIO_PORTC | GPIO_OUT | GPIO_PF | 11) -#define PC12_PF_UART1_RXD (GPIO_PORTC | GPIO_IN | GPIO_PF | 12) -#define PC13_PF_SPI1_SPI_RDY (GPIO_PORTC | GPIO_PF | 13) -#define PC14_PF_SPI1_SCLK (GPIO_PORTC | GPIO_PF | 14) -#define PC15_PF_SPI1_SS (GPIO_PORTC | GPIO_PF | 15) -#define PC16_PF_SPI1_MISO (GPIO_PORTC | GPIO_PF | 16) -#define PC17_PF_SPI1_MOSI (GPIO_PORTC | GPIO_PF | 17) -#define PC24_BIN_UART3_RI (GPIO_PORTC | GPIO_OUT | GPIO_BIN | 24) -#define PC25_BIN_UART3_DSR (GPIO_PORTC | GPIO_OUT | GPIO_BIN | 25) -#define PC26_AOUT_UART3_DTR (GPIO_PORTC | GPIO_IN | 26) -#define PC27_BIN_UART3_DCD (GPIO_PORTC | GPIO_OUT | GPIO_BIN | 27) -#define PC28_BIN_UART3_CTS (GPIO_PORTC | GPIO_OUT | GPIO_BIN | 28) -#define PC29_AOUT_UART3_RTS (GPIO_PORTC | GPIO_IN | 29) -#define PC30_BIN_UART3_TX (GPIO_PORTC | GPIO_BIN | 30) -#define PC31_AOUT_UART3_RX (GPIO_PORTC | GPIO_IN | 31) -#define PD6_PF_LSCLK (GPIO_PORTD | GPIO_OUT | GPIO_PF | 6) -#define PD7_PF_REV (GPIO_PORTD | GPIO_PF | 7) -#define PD7_AF_UART2_DTR (GPIO_PORTD | GPIO_IN | GPIO_AF | 7) -#define PD7_AIN_SPI2_SCLK (GPIO_PORTD | GPIO_AIN | 7) -#define PD8_PF_CLS (GPIO_PORTD | GPIO_PF | 8) -#define PD8_AF_UART2_DCD (GPIO_PORTD | GPIO_OUT | GPIO_AF | 8) -#define PD8_AIN_SPI2_SS (GPIO_PORTD | GPIO_AIN | 8) -#define PD9_PF_PS (GPIO_PORTD | GPIO_PF | 9) -#define PD9_AF_UART2_RI (GPIO_PORTD | GPIO_OUT | GPIO_AF | 9) -#define PD9_AOUT_SPI2_RXD (GPIO_PORTD | GPIO_IN | 9) -#define PD10_PF_SPL_SPR (GPIO_PORTD | GPIO_OUT | GPIO_PF | 10) -#define PD10_AF_UART2_DSR (GPIO_PORTD | GPIO_OUT | GPIO_AF | 10) -#define PD10_AIN_SPI2_TXD (GPIO_PORTD | GPIO_OUT | 10) -#define PD11_PF_CONTRAST (GPIO_PORTD | GPIO_OUT | GPIO_PF | 11) -#define PD12_PF_ACD_OE (GPIO_PORTD | GPIO_OUT | GPIO_PF | 12) -#define PD13_PF_LP_HSYNC (GPIO_PORTD | GPIO_OUT | GPIO_PF | 13) -#define PD14_PF_FLM_VSYNC (GPIO_PORTD | GPIO_OUT | GPIO_PF | 14) -#define PD15_PF_LD0 (GPIO_PORTD | GPIO_OUT | GPIO_PF | 15) -#define PD16_PF_LD1 (GPIO_PORTD | GPIO_OUT | GPIO_PF | 16) -#define PD17_PF_LD2 (GPIO_PORTD | GPIO_OUT | GPIO_PF | 17) -#define PD18_PF_LD3 (GPIO_PORTD | GPIO_OUT | GPIO_PF | 18) -#define PD19_PF_LD4 (GPIO_PORTD | GPIO_OUT | GPIO_PF | 19) -#define PD20_PF_LD5 (GPIO_PORTD | GPIO_OUT | GPIO_PF | 20) -#define PD21_PF_LD6 (GPIO_PORTD | GPIO_OUT | GPIO_PF | 21) -#define PD22_PF_LD7 (GPIO_PORTD | GPIO_OUT | GPIO_PF | 22) -#define PD23_PF_LD8 (GPIO_PORTD | GPIO_OUT | GPIO_PF | 23) -#define PD24_PF_LD9 (GPIO_PORTD | GPIO_OUT | GPIO_PF | 24) -#define PD25_PF_LD10 (GPIO_PORTD | GPIO_OUT | GPIO_PF | 25) -#define PD26_PF_LD11 (GPIO_PORTD | GPIO_OUT | GPIO_PF | 26) -#define PD27_PF_LD12 (GPIO_PORTD | GPIO_OUT | GPIO_PF | 27) -#define PD28_PF_LD13 (GPIO_PORTD | GPIO_OUT | GPIO_PF | 28) -#define PD29_PF_LD14 (GPIO_PORTD | GPIO_OUT | GPIO_PF | 29) -#define PD30_PF_LD15 (GPIO_PORTD | GPIO_OUT | GPIO_PF | 30) -#define PD31_PF_TMR2OUT (GPIO_PORTD | GPIO_PF | 31) -#define PD31_BIN_SPI2_TXD (GPIO_PORTD | GPIO_BIN | 31) -#endif - -#ifdef CONFIG_ARCH_MX2 -#define PA0_PF_USBH2_CLK (GPIO_PORTA | GPIO_PF | 0) -#define PA1_PF_USBH2_DIR (GPIO_PORTA | GPIO_PF | 1) -#define PA2_PF_USBH2_DATA7 (GPIO_PORTA | GPIO_PF | 2) -#define PA3_PF_USBH2_NXT (GPIO_PORTA | GPIO_PF | 3) -#define PA4_PF_USBH2_STP (GPIO_PORTA | GPIO_PF | 4) -#define PA5_PF_LSCLK (GPIO_PORTA | GPIO_OUT | GPIO_PF | 5) -#define PA6_PF_LD0 (GPIO_PORTA | GPIO_OUT | GPIO_PF | 6) -#define PA7_PF_LD1 (GPIO_PORTA | GPIO_OUT | GPIO_PF | 7) -#define PA8_PF_LD2 (GPIO_PORTA | GPIO_OUT | GPIO_PF | 8) -#define PA9_PF_LD3 (GPIO_PORTA | GPIO_OUT | GPIO_PF | 9) -#define PA10_PF_LD4 (GPIO_PORTA | GPIO_OUT | GPIO_PF | 10) -#define PA11_PF_LD5 (GPIO_PORTA | GPIO_OUT | GPIO_PF | 11) -#define PA12_PF_LD6 (GPIO_PORTA | GPIO_OUT | GPIO_PF | 12) -#define PA13_PF_LD7 (GPIO_PORTA | GPIO_OUT | GPIO_PF | 13) -#define PA14_PF_LD8 (GPIO_PORTA | GPIO_OUT | GPIO_PF | 14) -#define PA15_PF_LD9 (GPIO_PORTA | GPIO_OUT | GPIO_PF | 15) -#define PA16_PF_LD10 (GPIO_PORTA | GPIO_OUT | GPIO_PF | 16) -#define PA17_PF_LD11 (GPIO_PORTA | GPIO_OUT | GPIO_PF | 17) -#define PA18_PF_LD12 (GPIO_PORTA | GPIO_OUT | GPIO_PF | 18) -#define PA19_PF_LD13 (GPIO_PORTA | GPIO_OUT | GPIO_PF | 19) -#define PA20_PF_LD14 (GPIO_PORTA | GPIO_OUT | GPIO_PF | 20) -#define PA21_PF_LD15 (GPIO_PORTA | GPIO_OUT | GPIO_PF | 21) -#define PA22_PF_LD16 (GPIO_PORTA | GPIO_OUT | GPIO_PF | 22) -#define PA23_PF_LD17 (GPIO_PORTA | GPIO_OUT | GPIO_PF | 23) -#define PA24_PF_REV (GPIO_PORTA | GPIO_OUT | GPIO_PF | 24) -#define PA25_PF_CLS (GPIO_PORTA | GPIO_OUT | GPIO_PF | 25) -#define PA26_PF_PS (GPIO_PORTA | GPIO_OUT | GPIO_PF | 26) -#define PA27_PF_SPL_SPR (GPIO_PORTA | GPIO_OUT | GPIO_PF | 27) -#define PA28_PF_HSYNC (GPIO_PORTA | GPIO_OUT | GPIO_PF | 28) -#define PA29_PF_VSYNC (GPIO_PORTA | GPIO_OUT | GPIO_PF | 29) -#define PA30_PF_CONTRAST (GPIO_PORTA | GPIO_OUT | GPIO_PF | 30) -#define PA31_PF_OE_ACD (GPIO_PORTA | GPIO_OUT | GPIO_PF | 31) -#define PB4_PF_SD2_D0 (GPIO_PORTB | GPIO_PF | 4) -#define PB5_PF_SD2_D1 (GPIO_PORTB | GPIO_PF | 5) -#define PB6_PF_SD2_D2 (GPIO_PORTB | GPIO_PF | 6) -#define PB7_PF_SD2_D3 (GPIO_PORTB | GPIO_PF | 7) -#define PB8_PF_SD2_CMD (GPIO_PORTB | GPIO_PF | 8) -#define PB9_PF_SD2_CLK (GPIO_PORTB | GPIO_PF | 9) -#define PB10_PF_CSI_D0 (GPIO_PORTB | GPIO_OUT | GPIO_PF | 10) -#define PB10_AF_UART6_TXD (GPIO_PORTB | GPIO_OUT | GPIO_AF | 10) -#define PB11_PF_CSI_D1 (GPIO_PORTB | GPIO_OUT | GPIO_PF | 11) -#define PB11_AF_UART6_RXD (GPIO_PORTB | GPIO_IN | GPIO_AF | 11) -#define PB12_PF_CSI_D2 (GPIO_PORTB | GPIO_OUT | GPIO_PF | 12) -#define PB12_AF_UART6_CTS (GPIO_PORTB | GPIO_OUT | GPIO_AF | 12) -#define PB13_PF_CSI_D3 (GPIO_PORTB | GPIO_OUT | GPIO_PF | 13) -#define PB13_AF_UART6_RTS (GPIO_PORTB | GPIO_IN | GPIO_AF | 13) -#define PB14_PF_CSI_D4 (GPIO_PORTB | GPIO_OUT | GPIO_PF | 14) -#define PB15_PF_CSI_MCLK (GPIO_PORTB | GPIO_OUT | GPIO_PF | 15) -#define PB16_PF_CSI_PIXCLK (GPIO_PORTB | GPIO_OUT | GPIO_PF | 16) -#define PB17_PF_CSI_D5 (GPIO_PORTB | GPIO_OUT | GPIO_PF | 17) -#define PB18_PF_CSI_D6 (GPIO_PORTB | GPIO_OUT | GPIO_PF | 18) -#define PB18_AF_UART5_TXD (GPIO_PORTB | GPIO_OUT | GPIO_AF | 18) -#define PB19_PF_CSI_D7 (GPIO_PORTB | GPIO_OUT | GPIO_PF | 19) -#define PB19_AF_UART5_RXD (GPIO_PORTB | GPIO_IN | GPIO_AF | 19) -#define PB20_PF_CSI_VSYNC (GPIO_PORTB | GPIO_OUT | GPIO_PF | 20) -#define PB20_AF_UART5_CTS (GPIO_PORTB | GPIO_OUT | GPIO_AF | 20) -#define PB21_PF_CSI_HSYNC (GPIO_PORTB | GPIO_OUT | GPIO_PF | 21) -#define PB21_AF_UART5_RTS (GPIO_PORTB | GPIO_IN | GPIO_AF | 21) -#define PB22_PF_USBH1_SUSP (GPIO_PORTB | GPIO_PF | 22) -#define PB23_PF_USB_PWR (GPIO_PORTB | GPIO_PF | 23) -#define PB24_PF_USB_OC_B (GPIO_PORTB | GPIO_PF | 24) -#define PB25_PF_USBH1_RCV (GPIO_PORTB | GPIO_PF | 25) -#define PB26_PF_USBH1_FS (GPIO_PORTB | GPIO_PF | 26) -#define PB27_PF_USBH1_OE_B (GPIO_PORTB | GPIO_PF | 27) -#define PB28_PF_USBH1_TXDM (GPIO_PORTB | GPIO_PF | 28) -#define PB29_PF_USBH1_TXDP (GPIO_PORTB | GPIO_PF | 29) -#define PB30_PF_USBH1_RXDM (GPIO_PORTB | GPIO_PF | 30) -#define PB31_PF_USBH1_RXDP (GPIO_PORTB | GPIO_PF | 31) -#define PB26_AF_UART4_RTS (GPIO_PORTB | GPIO_IN | GPIO_PF | 26) -#define PB28_AF_UART4_TXD (GPIO_PORTB | GPIO_OUT | GPIO_AF | 28) -#define PB29_AF_UART4_CTS (GPIO_PORTB | GPIO_OUT | GPIO_AF | 29) -#define PB31_AF_UART4_RXD (GPIO_PORTB | GPIO_IN | GPIO_AF | 31) -#define PC5_PF_I2C2_SDA (GPIO_PORTC | GPIO_IN | GPIO_PF | 5) -#define PC6_PF_I2C2_SCL (GPIO_PORTC | GPIO_IN | GPIO_PF | 6) -#define PC7_PF_USBOTG_DATA5 (GPIO_PORTC | GPIO_OUT | GPIO_PF | 7) -#define PC8_PF_USBOTG_DATA6 (GPIO_PORTC | GPIO_OUT | GPIO_PF | 8) -#define PC9_PF_USBOTG_DATA0 (GPIO_PORTC | GPIO_OUT | GPIO_PF | 9) -#define PC10_PF_USBOTG_DATA2 (GPIO_PORTC | GPIO_OUT | GPIO_PF | 10) -#define PC11_PF_USBOTG_DATA1 (GPIO_PORTC | GPIO_OUT | GPIO_PF | 11) -#define PC12_PF_USBOTG_DATA4 (GPIO_PORTC | GPIO_OUT | GPIO_PF | 12) -#define PC13_PF_USBOTG_DATA3 (GPIO_PORTC | GPIO_OUT | GPIO_PF | 13) -#define PC16_PF_SSI4_FS (GPIO_PORTC | GPIO_IN | GPIO_PF | 16) -#define PC17_PF_SSI4_RXD (GPIO_PORTC | GPIO_IN | GPIO_PF | 17) -#define PC18_PF_SSI4_TXD (GPIO_PORTC | GPIO_IN | GPIO_PF | 18) -#define PC19_PF_SSI4_CLK (GPIO_PORTC | GPIO_IN | GPIO_PF | 19) -#define PC20_PF_SSI1_FS (GPIO_PORTC | GPIO_IN | GPIO_PF | 20) -#define PC21_PF_SSI1_RXD (GPIO_PORTC | GPIO_IN | GPIO_PF | 21) -#define PC22_PF_SSI1_TXD (GPIO_PORTC | GPIO_IN | GPIO_PF | 22) -#define PC23_PF_SSI1_CLK (GPIO_PORTC | GPIO_IN | GPIO_PF | 23) -#define PC24_PF_SSI2_FS (GPIO_PORTC | GPIO_IN | GPIO_PF | 24) -#define PC25_PF_SSI2_RXD (GPIO_PORTC | GPIO_IN | GPIO_PF | 25) -#define PC26_PF_SSI2_TXD (GPIO_PORTC | GPIO_IN | GPIO_PF | 26) -#define PC27_PF_SSI2_CLK (GPIO_PORTC | GPIO_IN | GPIO_PF | 27) -#define PC28_PF_SSI3_FS (GPIO_PORTC | GPIO_IN | GPIO_PF | 28) -#define PC29_PF_SSI3_RXD (GPIO_PORTC | GPIO_IN | GPIO_PF | 29) -#define PC30_PF_SSI3_TXD (GPIO_PORTC | GPIO_IN | GPIO_PF | 30) -#define PC31_PF_SSI3_CLK (GPIO_PORTC | GPIO_IN | GPIO_PF | 31) -#define PD0_AIN_FEC_TXD0 (GPIO_PORTD | GPIO_OUT | GPIO_AIN | 0) -#define PD1_AIN_FEC_TXD1 (GPIO_PORTD | GPIO_OUT | GPIO_AIN | 1) -#define PD2_AIN_FEC_TXD2 (GPIO_PORTD | GPIO_OUT | GPIO_AIN | 2) -#define PD3_AIN_FEC_TXD3 (GPIO_PORTD | GPIO_OUT | GPIO_AIN | 3) -#define PD4_AOUT_FEC_RX_ER (GPIO_PORTD | GPIO_IN | GPIO_AOUT | 4) -#define PD5_AOUT_FEC_RXD1 (GPIO_PORTD | GPIO_IN | GPIO_AOUT | 5) -#define PD6_AOUT_FEC_RXD2 (GPIO_PORTD | GPIO_IN | GPIO_AOUT | 6) -#define PD7_AOUT_FEC_RXD3 (GPIO_PORTD | GPIO_IN | GPIO_AOUT | 7) -#define PD8_AF_FEC_MDIO (GPIO_PORTD | GPIO_IN | GPIO_AF | 8) -#define PD9_AIN_FEC_MDC (GPIO_PORTD | GPIO_OUT | GPIO_AIN | 9) -#define PD10_AOUT_FEC_CRS (GPIO_PORTD | GPIO_IN | GPIO_AOUT | 10) -#define PD11_AOUT_FEC_TX_CLK (GPIO_PORTD | GPIO_IN | GPIO_AOUT | 11) -#define PD12_AOUT_FEC_RXD0 (GPIO_PORTD | GPIO_IN | GPIO_AOUT | 12) -#define PD13_AOUT_FEC_RX_DV (GPIO_PORTD | GPIO_IN | GPIO_AOUT | 13) -#define PD14_AOUT_FEC_CLR (GPIO_PORTD | GPIO_IN | GPIO_AOUT | 14) -#define PD15_AOUT_FEC_COL (GPIO_PORTD | GPIO_IN | GPIO_AOUT | 15) -#define PD16_AIN_FEC_TX_ER (GPIO_PORTD | GPIO_OUT | GPIO_AIN | 16) -#define PD17_PF_I2C_DATA (GPIO_PORTD | GPIO_OUT | GPIO_PF | 17) -#define PD18_PF_I2C_CLK (GPIO_PORTD | GPIO_OUT | GPIO_PF | 18) -#define PD19_AF_USBH2_DATA4 (GPIO_PORTD | GPIO_AF | 19) -#define PD20_AF_USBH2_DATA3 (GPIO_PORTD | GPIO_AF | 20) -#define PD21_AF_USBH2_DATA6 (GPIO_PORTD | GPIO_AF | 21) -#define PD22_AF_USBH2_DATA0 (GPIO_PORTD | GPIO_AF | 22) -#define PD23_AF_USBH2_DATA2 (GPIO_PORTD | GPIO_AF | 23) -#define PD24_AF_USBH2_DATA1 (GPIO_PORTD | GPIO_AF | 24) -#define PD25_PF_CSPI1_RDY (GPIO_PORTD | GPIO_OUT | GPIO_PF | 25) -#define PD26_PF_CSPI1_SS2 (GPIO_PORTD | GPIO_OUT | GPIO_PF | 26) -#define PD26_AF_USBH2_DATA5 (GPIO_PORTD | GPIO_AF | 26) -#define PD27_PF_CSPI1_SS1 (GPIO_PORTD | GPIO_OUT | GPIO_PF | 27) -#define PD28_PF_CSPI1_SS0 (GPIO_PORTD | GPIO_OUT | GPIO_PF | 28) -#define PD29_PF_CSPI1_SCLK (GPIO_PORTD | GPIO_OUT | GPIO_PF | 29) -#define PD30_PF_CSPI1_MISO (GPIO_PORTD | GPIO_IN | GPIO_PF | 30) -#define PD31_PF_CSPI1_MOSI (GPIO_PORTD | GPIO_OUT | GPIO_PF | 31) -#define PF23_AIN_FEC_TX_EN (GPIO_PORTF | GPIO_OUT | GPIO_AIN | 23) -#define PE0_PF_USBOTG_NXT (GPIO_PORTE | GPIO_OUT | GPIO_PF | 0) -#define PE1_PF_USBOTG_STP (GPIO_PORTE | GPIO_OUT | GPIO_PF | 1) -#define PE2_PF_USBOTG_DIR (GPIO_PORTE | GPIO_OUT | GPIO_PF | 2) -#define PE3_PF_UART2_CTS (GPIO_PORTE | GPIO_OUT | GPIO_PF | 3) -#define PE4_PF_UART2_RTS (GPIO_PORTE | GPIO_IN | GPIO_PF | 4) -#define PE6_PF_UART2_TXD (GPIO_PORTE | GPIO_OUT | GPIO_PF | 6) -#define PE7_PF_UART2_RXD (GPIO_PORTE | GPIO_IN | GPIO_PF | 7) -#define PE8_PF_UART3_TXD (GPIO_PORTE | GPIO_OUT | GPIO_PF | 8) -#define PE9_PF_UART3_RXD (GPIO_PORTE | GPIO_IN | GPIO_PF | 9) -#define PE10_PF_UART3_CTS (GPIO_PORTE | GPIO_OUT | GPIO_PF | 10) -#define PE11_PF_UART3_RTS (GPIO_PORTE | GPIO_IN | GPIO_PF | 11) -#define PE12_PF_UART1_TXD (GPIO_PORTE | GPIO_OUT | GPIO_PF | 12) -#define PE13_PF_UART1_RXD (GPIO_PORTE | GPIO_IN | GPIO_PF | 13) -#define PE14_PF_UART1_CTS (GPIO_PORTE | GPIO_OUT | GPIO_PF | 14) -#define PE15_PF_UART1_RTS (GPIO_PORTE | GPIO_IN | GPIO_PF | 15) -#define PE16_AF_RTCK (GPIO_PORTE | GPIO_OUT | GPIO_AF | 16) -#define PE16_PF_RTCK (GPIO_PORTE | GPIO_OUT | GPIO_PF | 16) -#define PE18_PF_SDHC1_D0 (GPIO_PORTE | GPIO_PF | 18) -#define PE18_AF_CSPI3_MISO (GPIO_PORTE | GPIO_IN | GPIO_AF | 18) -#define PE19_PF_SDHC1_D1 (GPIO_PORTE | GPIO_PF | 19) -#define PE20_PF_SDHC1_D2 (GPIO_PORTE | GPIO_PF | 20) -#define PE21_PF_SDHC1_D3 (GPIO_PORTE | GPIO_PF | 21) -#define PE21_AF_CSPI3_SS (GPIO_PORTE | GPIO_OUT | GPIO_AF | 21) -#define PE22_PF_SDHC1_CMD (GPIO_PORTE | GPIO_PF | 22) -#define PE22_AF_CSPI3_MOSI (GPIO_PORTE | GPIO_OUT | GPIO_AF | 22) -#define PE22_PF_SDHC1_CLK (GPIO_PORTE | GPIO_PF | 23) -#define PE23_AF_CSPI3_SCLK (GPIO_PORTE | GPIO_OUT | GPIO_AF | 23) -#define PE24_PF_USBOTG_CLK (GPIO_PORTE | GPIO_OUT | GPIO_PF | 24) -#define PE25_PF_USBOTG_DATA7 (GPIO_PORTE | GPIO_OUT | GPIO_PF | 25) -#endif - -/* decode irq number to use with IMR(x), ISR(x) and friends */ -#define IRQ_TO_REG(irq) ((irq - MXC_INTERNAL_IRQS) >> 5) - -#define IRQ_GPIOA(x) (MXC_GPIO_IRQ_START + x) -#define IRQ_GPIOB(x) (IRQ_GPIOA(32) + x) -#define IRQ_GPIOC(x) (IRQ_GPIOB(32) + x) -#define IRQ_GPIOD(x) (IRQ_GPIOC(32) + x) -#define IRQ_GPIOE(x) (IRQ_GPIOD(32) + x) - -#endif /* _MXC_GPIO_MX1_MX2_H */ diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx1.h b/arch/arm/plat-mxc/include/mach/iomux-mx1.h new file mode 100644 index 00000000000..bf23305c19c --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/iomux-mx1.h @@ -0,0 +1,166 @@ +/* +* Copyright (C) 2008 by Sascha Hauer +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +* MA 02110-1301, USA. +*/ + +#ifndef _MXC_IOMUX_MX1_H +#define _MXC_IOMUX_MX1_H + +#ifndef GPIO_PORTA +#error Please include mach/iomux.h +#endif + +/* FIXME: This list is not completed. The correct directions are +* missing on some (many) pins +*/ + + +/* Primary GPIO pin functions */ + +#define PA0_AIN_SPI2_CLK (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 0) +#define PA0_AF_ETMTRACESYNC (GPIO_PORTA | GPIO_AF | 0) +#define PA1_AOUT_SPI2_RXD (GPIO_PORTA | GPIO_AOUT | GPIO_IN | 1) +#define PA1_PF_TIN (GPIO_PORTA | GPIO_PF | 1) +#define PA2_PF_PWM0 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 2) +#define PA3_PF_CSI_MCLK (GPIO_PORTA | GPIO_PF | 3) +#define PA4_PF_CSI_D0 (GPIO_PORTA | GPIO_PF | 4) +#define PA5_PF_CSI_D1 (GPIO_PORTA | GPIO_PF | 5) +#define PA6_PF_CSI_D2 (GPIO_PORTA | GPIO_PF | 6) +#define PA7_PF_CSI_D3 (GPIO_PORTA | GPIO_PF | 7) +#define PA8_PF_CSI_D4 (GPIO_PORTA | GPIO_PF | 8) +#define PA9_PF_CSI_D5 (GPIO_PORTA | GPIO_PF | 9) +#define PA10_PF_CSI_D6 (GPIO_PORTA | GPIO_PF | 10) +#define PA11_PF_CSI_D7 (GPIO_PORTA | GPIO_PF | 11) +#define PA12_PF_CSI_VSYNC (GPIO_PORTA | GPIO_PF | 12) +#define PA13_PF_CSI_HSYNC (GPIO_PORTA | GPIO_PF | 13) +#define PA14_PF_CSI_PIXCLK (GPIO_PORTA | GPIO_PF | 14) +#define PA15_PF_I2C_SDA (GPIO_PORTA | GPIO_PF | GPIO_OUT | 15) +#define PA16_PF_I2C_SCL (GPIO_PORTA | GPIO_PF | GPIO_OUT | 16) +#define PA17_AF_ETMTRACEPKT4 (GPIO_PORTA | GPIO_AF | 17) +#define PA17_AIN_SPI2_SS (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 17) +#define PA18_AF_ETMTRACEPKT5 (GPIO_PORTA | GPIO_AF | 18) +#define PA19_AF_ETMTRACEPKT6 (GPIO_PORTA | GPIO_AF | 19) +#define PA20_AF_ETMTRACEPKT7 (GPIO_PORTA | GPIO_AF | 20) +#define PA21_PF_A0 (GPIO_PORTA | GPIO_PF | 21) +#define PA22_PF_CS4 (GPIO_PORTA | GPIO_PF | 22) +#define PA23_PF_CS5 (GPIO_PORTA | GPIO_PF | 23) +#define PA24_PF_A16 (GPIO_PORTA | GPIO_PF | 24) +#define PA24_AF_ETMTRACEPKT0 (GPIO_PORTA | GPIO_AF | 24) +#define PA25_PF_A17 (GPIO_PORTA | GPIO_PF | 25) +#define PA25_AF_ETMTRACEPKT1 (GPIO_PORTA | GPIO_AF | 25) +#define PA26_PF_A18 (GPIO_PORTA | GPIO_PF | 26) +#define PA26_AF_ETMTRACEPKT2 (GPIO_PORTA | GPIO_AF | 26) +#define PA27_PF_A19 (GPIO_PORTA | GPIO_PF | 27) +#define PA27_AF_ETMTRACEPKT3 (GPIO_PORTA | GPIO_AF | 27) +#define PA28_PF_A20 (GPIO_PORTA | GPIO_PF | 28) +#define PA28_AF_ETMPIPESTAT0 (GPIO_PORTA | GPIO_AF | 28) +#define PA29_PF_A21 (GPIO_PORTA | GPIO_PF | 29) +#define PA29_AF_ETMPIPESTAT1 (GPIO_PORTA | GPIO_AF | 29) +#define PA30_PF_A22 (GPIO_PORTA | GPIO_PF | 30) +#define PA30_AF_ETMPIPESTAT2 (GPIO_PORTA | GPIO_AF | 30) +#define PA31_PF_A23 (GPIO_PORTA | GPIO_PF | 31) +#define PA31_AF_ETMTRACECLK (GPIO_PORTA | GPIO_AF | 31) +#define PB8_PF_SD_DAT0 (GPIO_PORTB | GPIO_PF | GPIO_PUEN | 8) +#define PB8_AF_MS_PIO (GPIO_PORTB | GPIO_AF | 8) +#define PB9_PF_SD_DAT1 (GPIO_PORTB | GPIO_PF | GPIO_PUEN | 9) +#define PB9_AF_MS_PI1 (GPIO_PORTB | GPIO_AF | 9) +#define PB10_PF_SD_DAT2 (GPIO_PORTB | GPIO_PF | GPIO_PUEN | 10) +#define PB10_AF_MS_SCLKI (GPIO_PORTB | GPIO_AF | 10) +#define PB11_PF_SD_DAT3 (GPIO_PORTB | GPIO_PF | 11) +#define PB11_AF_MS_SDIO (GPIO_PORTB | GPIO_AF | 11) +#define PB12_PF_SD_CLK (GPIO_PORTB | GPIO_PF | 12) +#define PB12_AF_MS_SCLK0 (GPIO_PORTB | GPIO_AF | 12) +#define PB13_PF_SD_CMD (GPIO_PORTB | GPIO_PF | GPIO_PUEN | 13) +#define PB13_AF_MS_BS (GPIO_PORTB | GPIO_AF | 13) +#define PB14_AF_SSI_RXFS (GPIO_PORTB | GPIO_AF | 14) +#define PB15_AF_SSI_RXCLK (GPIO_PORTB | GPIO_AF | 15) +#define PB16_AF_SSI_RXDAT (GPIO_PORTB | GPIO_AF | GPIO_IN | 16) +#define PB17_AF_SSI_TXDAT (GPIO_PORTB | GPIO_AF | GPIO_OUT | 17) +#define PB18_AF_SSI_TXFS (GPIO_PORTB | GPIO_AF | 18) +#define PB19_AF_SSI_TXCLK (GPIO_PORTB | GPIO_AF | 19) +#define PB20_PF_USBD_AFE (GPIO_PORTB | GPIO_PF | 20) +#define PB21_PF_USBD_OE (GPIO_PORTB | GPIO_PF | 21) +#define PB22_PF_USBD_RCV (GPIO_PORTB | GPIO_PF | 22) +#define PB23_PF_USBD_SUSPND (GPIO_PORTB | GPIO_PF | 23) +#define PB24_PF_USBD_VP (GPIO_PORTB | GPIO_PF | 24) +#define PB25_PF_USBD_VM (GPIO_PORTB | GPIO_PF | 25) +#define PB26_PF_USBD_VPO (GPIO_PORTB | GPIO_PF | 26) +#define PB27_PF_USBD_VMO (GPIO_PORTB | GPIO_PF | 27) +#define PB28_PF_UART2_CTS (GPIO_PORTB | GPIO_PF | GPIO_OUT | 28) +#define PB29_PF_UART2_RTS (GPIO_PORTB | GPIO_PF | GPIO_IN | 29) +#define PB30_PF_UART2_TXD (GPIO_PORTB | GPIO_PF | GPIO_OUT | 30) +#define PB31_PF_UART2_RXD (GPIO_PORTB | GPIO_PF | GPIO_IN | 31) +#define PC3_PF_SSI_RXFS (GPIO_PORTC | GPIO_PF | 3) +#define PC4_PF_SSI_RXCLK (GPIO_PORTC | GPIO_PF | 4) +#define PC5_PF_SSI_RXDAT (GPIO_PORTC | GPIO_PF | GPIO_IN | 5) +#define PC6_PF_SSI_TXDAT (GPIO_PORTC | GPIO_PF | GPIO_OUT | 6) +#define PC7_PF_SSI_TXFS (GPIO_PORTC | GPIO_PF | 7) +#define PC8_PF_SSI_TXCLK (GPIO_PORTC | GPIO_PF | 8) +#define PC9_PF_UART1_CTS (GPIO_PORTC | GPIO_PF | GPIO_OUT | 9) +#define PC10_PF_UART1_RTS (GPIO_PORTC | GPIO_PF | GPIO_IN | 10) +#define PC11_PF_UART1_TXD (GPIO_PORTC | GPIO_PF | GPIO_OUT | 11) +#define PC12_PF_UART1_RXD (GPIO_PORTC | GPIO_PF | GPIO_IN | 12) +#define PC13_PF_SPI1_SPI_RDY (GPIO_PORTC | GPIO_PF | 13) +#define PC14_PF_SPI1_SCLK (GPIO_PORTC | GPIO_PF | 14) +#define PC15_PF_SPI1_SS (GPIO_PORTC | GPIO_PF | 15) +#define PC16_PF_SPI1_MISO (GPIO_PORTC | GPIO_PF | 16) +#define PC17_PF_SPI1_MOSI (GPIO_PORTC | GPIO_PF | 17) +#define PC24_BIN_UART3_RI (GPIO_PORTC | GPIO_BIN | GPIO_OUT | 24) +#define PC25_BIN_UART3_DSR (GPIO_PORTC | GPIO_BIN | GPIO_OUT | 25) +#define PC26_AOUT_UART3_DTR (GPIO_PORTC | GPIO_AOUT | GPIO_IN | 26) +#define PC27_BIN_UART3_DCD (GPIO_PORTC | GPIO_BIN | GPIO_OUT | 27) +#define PC28_BIN_UART3_CTS (GPIO_PORTC | GPIO_BIN | GPIO_OUT | 28) +#define PC29_AOUT_UART3_RTS (GPIO_PORTC | GPIO_AOUT | GPIO_IN | 29) +#define PC30_BIN_UART3_TX (GPIO_PORTC | GPIO_BIN | 30) +#define PC31_AOUT_UART3_RX (GPIO_PORTC | GPIO_AOUT | GPIO_IN | 31) +#define PD6_PF_LSCLK (GPIO_PORTD | GPIO_PF | GPIO_OUT | 6) +#define PD7_PF_REV (GPIO_PORTD | GPIO_PF | 7) +#define PD7_AF_UART2_DTR (GPIO_PORTD | GPIO_AF | GPIO_IN | 7) +#define PD7_AIN_SPI2_SCLK (GPIO_PORTD | GPIO_AIN | 7) +#define PD8_PF_CLS (GPIO_PORTD | GPIO_PF | 8) +#define PD8_AF_UART2_DCD (GPIO_PORTD | GPIO_AF | GPIO_OUT | 8) +#define PD8_AIN_SPI2_SS (GPIO_PORTD | GPIO_AIN | 8) +#define PD9_PF_PS (GPIO_PORTD | GPIO_PF | 9) +#define PD9_AF_UART2_RI (GPIO_PORTD | GPIO_AF | GPIO_OUT | 9) +#define PD9_AOUT_SPI2_RXD (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 9) +#define PD10_PF_SPL_SPR (GPIO_PORTD | GPIO_PF | GPIO_OUT | 10) +#define PD10_AF_UART2_DSR (GPIO_PORTD | GPIO_AF | GPIO_OUT | 10) +#define PD10_AIN_SPI2_TXD (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 10) +#define PD11_PF_CONTRAST (GPIO_PORTD | GPIO_PF | GPIO_OUT | 11) +#define PD12_PF_ACD_OE (GPIO_PORTD | GPIO_PF | GPIO_OUT | 12) +#define PD13_PF_LP_HSYNC (GPIO_PORTD | GPIO_PF | GPIO_OUT | 13) +#define PD14_PF_FLM_VSYNC (GPIO_PORTD | GPIO_PF | GPIO_OUT | 14) +#define PD15_PF_LD0 (GPIO_PORTD | GPIO_PF | GPIO_OUT | 15) +#define PD16_PF_LD1 (GPIO_PORTD | GPIO_PF | GPIO_OUT | 16) +#define PD17_PF_LD2 (GPIO_PORTD | GPIO_PF | GPIO_OUT | 17) +#define PD18_PF_LD3 (GPIO_PORTD | GPIO_PF | GPIO_OUT | 18) +#define PD19_PF_LD4 (GPIO_PORTD | GPIO_PF | GPIO_OUT | 19) +#define PD20_PF_LD5 (GPIO_PORTD | GPIO_PF | GPIO_OUT | 20) +#define PD21_PF_LD6 (GPIO_PORTD | GPIO_PF | GPIO_OUT | 21) +#define PD22_PF_LD7 (GPIO_PORTD | GPIO_PF | GPIO_OUT | 22) +#define PD23_PF_LD8 (GPIO_PORTD | GPIO_PF | GPIO_OUT | 23) +#define PD24_PF_LD9 (GPIO_PORTD | GPIO_PF | GPIO_OUT | 24) +#define PD25_PF_LD10 (GPIO_PORTD | GPIO_PF | GPIO_OUT | 25) +#define PD26_PF_LD11 (GPIO_PORTD | GPIO_PF | GPIO_OUT | 26) +#define PD27_PF_LD12 (GPIO_PORTD | GPIO_PF | GPIO_OUT | 27) +#define PD28_PF_LD13 (GPIO_PORTD | GPIO_PF | GPIO_OUT | 28) +#define PD29_PF_LD14 (GPIO_PORTD | GPIO_PF | GPIO_OUT | 29) +#define PD30_PF_LD15 (GPIO_PORTD | GPIO_PF | GPIO_OUT | 30) +#define PD31_PF_TMR2OUT (GPIO_PORTD | GPIO_PF | 31) +#define PD31_BIN_SPI2_TXD (GPIO_PORTD | GPIO_BIN | 31) + + +#endif diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx21.h b/arch/arm/plat-mxc/include/mach/iomux-mx21.h new file mode 100644 index 00000000000..63aaa972e27 --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/iomux-mx21.h @@ -0,0 +1,126 @@ +/* +* Copyright (C) 2009 by Holger Schurig +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +* MA 02110-1301, USA. +*/ + +#ifndef _MXC_IOMUX_MX21_H +#define _MXC_IOMUX_MX21_H + +#ifndef GPIO_PORTA +#error Please include mach/iomux.h +#endif + + +/* Primary GPIO pin functions */ + +#define PB22_PF_USBH1_BYP (GPIO_PORTB | GPIO_PF | 22) +#define PB25_PF_USBH1_ON (GPIO_PORTB | GPIO_PF | 25) +#define PC5_PF_USBOTG_SDA (GPIO_PORTC | GPIO_PF | 5) +#define PC6_PF_USBOTG_SCL (GPIO_PORTC | GPIO_PF | 6) +#define PC7_PF_USBOTG_ON (GPIO_PORTC | GPIO_PF | 7) +#define PC8_PF_USBOTG_FS (GPIO_PORTC | GPIO_PF | 8) +#define PC9_PF_USBOTG_OE (GPIO_PORTC | GPIO_PF | 9) +#define PC10_PF_USBOTG_TXDM (GPIO_PORTC | GPIO_PF | 10) +#define PC11_PF_USBOTG_TXDP (GPIO_PORTC | GPIO_PF | 11) +#define PC12_PF_USBOTG_RXDM (GPIO_PORTC | GPIO_PF | 12) +#define PC13_PF_USBOTG_RXDP (GPIO_PORTC | GPIO_PF | 13) +#define PC16_PF_SAP_FS (GPIO_PORTC | GPIO_PF | 16) +#define PC17_PF_SAP_RXD (GPIO_PORTC | GPIO_PF | 17) +#define PC18_PF_SAP_TXD (GPIO_PORTC | GPIO_PF | 18) +#define PC19_PF_SAP_CLK (GPIO_PORTC | GPIO_PF | 19) +#define PE0_PF_TEST_WB2 (GPIO_PORTE | GPIO_PF | 0) +#define PE1_PF_TEST_WB1 (GPIO_PORTE | GPIO_PF | 1) +#define PE2_PF_TEST_WB0 (GPIO_PORTE | GPIO_PF | 2) +#define PF1_PF_NFCE (GPIO_PORTF | GPIO_PF | 1) +#define PF3_PF_NFCLE (GPIO_PORTF | GPIO_PF | 3) +#define PF7_PF_NFIO0 (GPIO_PORTF | GPIO_PF | 7) +#define PF8_PF_NFIO1 (GPIO_PORTF | GPIO_PF | 8) +#define PF9_PF_NFIO2 (GPIO_PORTF | GPIO_PF | 9) +#define PF10_PF_NFIO3 (GPIO_PORTF | GPIO_PF | 10) +#define PF11_PF_NFIO4 (GPIO_PORTF | GPIO_PF | 11) +#define PF12_PF_NFIO5 (GPIO_PORTF | GPIO_PF | 12) +#define PF13_PF_NFIO6 (GPIO_PORTF | GPIO_PF | 13) +#define PF14_PF_NFIO7 (GPIO_PORTF | GPIO_PF | 14) +#define PF16_PF_RES (GPIO_PORTF | GPIO_PF | 16) + +/* Alternate GPIO pin functions */ + +#define PA5_AF_BMI_CLK_CS (GPIO_PORTA | GPIO_AF | 5) +#define PA6_AF_BMI_D0 (GPIO_PORTA | GPIO_AF | 6) +#define PA7_AF_BMI_D1 (GPIO_PORTA | GPIO_AF | 7) +#define PA8_AF_BMI_D2 (GPIO_PORTA | GPIO_AF | 8) +#define PA9_AF_BMI_D3 (GPIO_PORTA | GPIO_AF | 9) +#define PA10_AF_BMI_D4 (GPIO_PORTA | GPIO_AF | 10) +#define PA11_AF_BMI_D5 (GPIO_PORTA | GPIO_AF | 11) +#define PA12_AF_BMI_D6 (GPIO_PORTA | GPIO_AF | 12) +#define PA13_AF_BMI_D7 (GPIO_PORTA | GPIO_AF | 13) +#define PA14_AF_BMI_D8 (GPIO_PORTA | GPIO_AF | 14) +#define PA15_AF_BMI_D9 (GPIO_PORTA | GPIO_AF | 15) +#define PA16_AF_BMI_D10 (GPIO_PORTA | GPIO_AF | 16) +#define PA17_AF_BMI_D11 (GPIO_PORTA | GPIO_AF | 17) +#define PA18_AF_BMI_D12 (GPIO_PORTA | GPIO_AF | 18) +#define PA19_AF_BMI_D13 (GPIO_PORTA | GPIO_AF | 19) +#define PA20_AF_BMI_D14 (GPIO_PORTA | GPIO_AF | 20) +#define PA21_AF_BMI_D15 (GPIO_PORTA | GPIO_AF | 21) +#define PA22_AF_BMI_READ_REQ (GPIO_PORTA | GPIO_AF | 22) +#define PA23_AF_BMI_WRITE (GPIO_PORTA | GPIO_AF | 23) +#define PA29_AF_BMI_RX_FULL (GPIO_PORTA | GPIO_AF | 29) +#define PA30_AF_BMI_READ (GPIO_PORTA | GPIO_AF | 30) + +/* AIN GPIO pin functions */ + +#define PC14_AIN_SYS_CLK (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 14) +#define PD21_AIN_USBH2_FS (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 21) +#define PD22_AIN_USBH2_OE (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 22) +#define PD23_AIN_USBH2_TXDM (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 23) +#define PD24_AIN_USBH2_TXDP (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 24) +#define PE8_AIN_IR_TXD (GPIO_PORTE | GPIO_AIN | GPIO_OUT | 8) +#define PF0_AIN_PC_RST (GPIO_PORTF | GPIO_AIN | GPIO_OUT | 0) +#define PF1_AIN_PC_CE1 (GPIO_PORTF | GPIO_AIN | GPIO_OUT | 1) +#define PF2_AIN_PC_CE2 (GPIO_PORTF | GPIO_AIN | GPIO_OUT | 2) +#define PF3_AIN_PC_POE (GPIO_PORTF | GPIO_AIN | GPIO_OUT | 3) +#define PF4_AIN_PC_OE (GPIO_PORTF | GPIO_AIN | GPIO_OUT | 4) +#define PF5_AIN_PC_RW (GPIO_PORTF | GPIO_AIN | GPIO_OUT | 5) + +/* BIN GPIO pin functions */ + +#define PC14_BIN_SYS_CLK (GPIO_PORTC | GPIO_BIN | GPIO_OUT | 14) +#define PD27_BIN_EXT_DMA_GRANT (GPIO_PORTD | GPIO_BIN | GPIO_OUT | 27) + +/* CIN GPIO pin functions */ + +#define PB26_CIN_USBH1_RXDAT (GPIO_PORTB | GPIO_CIN | GPIO_OUT | 26) + +/* AOUT GPIO pin functions */ + +#define PA29_AOUT_BMI_WAIT (GPIO_PORTA | GPIO_AOUT | GPIO_IN | 29) +#define PD19_AOUT_USBH2_RXDM (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 19) +#define PD20_AOUT_USBH2_RXDP (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 20) +#define PD25_AOUT_EXT_DMAREQ (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 25) +#define PD26_AOUT_USBOTG_RXDAT (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 26) +#define PE9_AOUT_IR_RXD (GPIO_PORTE | GPIO_AOUT | GPIO_IN | 9) +#define PF6_AOUT_PC_BVD2 (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 6) +#define PF7_AOUT_PC_BVD1 (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 7) +#define PF8_AOUT_PC_VS2 (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 8) +#define PF9_AOUT_PC_VS1 (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 9) +#define PF10_AOUT_PC_WP (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 10) +#define PF11_AOUT_PC_READY (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 11) +#define PF12_AOUT_PC_WAIT (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 12) +#define PF13_AOUT_PC_CD2 (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 13) +#define PF14_AOUT_PC_CD1 (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 14) + + +#endif diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx27.h b/arch/arm/plat-mxc/include/mach/iomux-mx27.h new file mode 100644 index 00000000000..5ac158b70f6 --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/iomux-mx27.h @@ -0,0 +1,207 @@ +/* +* Copyright (C) 2008 by Sascha Hauer +* Copyright (C) 2009 by Holger Schurig +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +* MA 02110-1301, USA. +*/ + +#ifndef _MXC_IOMUX_MX27_H +#define _MXC_IOMUX_MX27_H + +#ifndef GPIO_PORTA +#error Please include mach/iomux.h +#endif + + +/* Primary GPIO pin functions */ + +#define PA0_PF_USBH2_CLK (GPIO_PORTA | GPIO_PF | 0) +#define PA1_PF_USBH2_DIR (GPIO_PORTA | GPIO_PF | 1) +#define PA2_PF_USBH2_DATA7 (GPIO_PORTA | GPIO_PF | 2) +#define PA3_PF_USBH2_NXT (GPIO_PORTA | GPIO_PF | 3) +#define PA4_PF_USBH2_STP (GPIO_PORTA | GPIO_PF | 4) +#define PB22_PF_USBH1_SUSP (GPIO_PORTB | GPIO_PF | 22) +#define PB25_PF_USBH1_RCV (GPIO_PORTB | GPIO_PF | 25) +#define PC5_PF_I2C2_SDA (GPIO_PORTC | GPIO_PF | GPIO_IN | 5) +#define PC6_PF_I2C2_SCL (GPIO_PORTC | GPIO_PF | GPIO_IN | 6) +#define PC7_PF_USBOTG_DATA5 (GPIO_PORTC | GPIO_PF | GPIO_OUT | 7) +#define PC8_PF_USBOTG_DATA6 (GPIO_PORTC | GPIO_PF | GPIO_OUT | 8) +#define PC9_PF_USBOTG_DATA0 (GPIO_PORTC | GPIO_PF | GPIO_OUT | 9) +#define PC10_PF_USBOTG_DATA2 (GPIO_PORTC | GPIO_PF | GPIO_OUT | 10) +#define PC11_PF_USBOTG_DATA1 (GPIO_PORTC | GPIO_PF | GPIO_OUT | 11) +#define PC12_PF_USBOTG_DATA4 (GPIO_PORTC | GPIO_PF | GPIO_OUT | 12) +#define PC13_PF_USBOTG_DATA3 (GPIO_PORTC | GPIO_PF | GPIO_OUT | 13) +#define PC16_PF_SSI4_FS (GPIO_PORTC | GPIO_PF | GPIO_IN | 16) +#define PC17_PF_SSI4_RXD (GPIO_PORTC | GPIO_PF | GPIO_IN | 17) +#define PC18_PF_SSI4_TXD (GPIO_PORTC | GPIO_PF | GPIO_IN | 18) +#define PC19_PF_SSI4_CLK (GPIO_PORTC | GPIO_PF | GPIO_IN | 19) +#define PC25_AF_GPT5_TIN (GPIO_PORTC | GPIO_AF | 25) +#define PC27_AF_GPT4_TIN (GPIO_PORTC | GPIO_AF | 27) +#define PD0_PF_SD3_CMD (GPIO_PORTD | GPIO_PF | 0) +#define PD1_PF_SD3_CLK (GPIO_PORTD | GPIO_PF | 1) +#define PD2_PF_ATA_DATA0 (GPIO_PORTD | GPIO_PF | 2) +#define PD3_PF_ATA_DATA1 (GPIO_PORTD | GPIO_PF | 3) +#define PD4_PF_ATA_DATA2 (GPIO_PORTD | GPIO_PF | 4) +#define PD5_PF_ATA_DATA3 (GPIO_PORTD | GPIO_PF | 5) +#define PD6_PF_ATA_DATA4 (GPIO_PORTD | GPIO_PF | 6) +#define PD7_PF_ATA_DATA5 (GPIO_PORTD | GPIO_PF | 7) +#define PD8_PF_ATA_DATA6 (GPIO_PORTD | GPIO_PF | 8) +#define PD9_PF_ATA_DATA7 (GPIO_PORTD | GPIO_PF | 9) +#define PD10_PF_ATA_DATA8 (GPIO_PORTD | GPIO_PF | 10) +#define PD11_PF_ATA_DATA9 (GPIO_PORTD | GPIO_PF | 11) +#define PD12_PF_ATA_DATA10 (GPIO_PORTD | GPIO_PF | 12) +#define PD13_PF_ATA_DATA11 (GPIO_PORTD | GPIO_PF | 13) +#define PD14_PF_ATA_DATA12 (GPIO_PORTD | GPIO_PF | 14) +#define PD15_PF_ATA_DATA13 (GPIO_PORTD | GPIO_PF | 15) +#define PD16_PF_ATA_DATA14 (GPIO_PORTD | GPIO_PF | 16) +#define PE0_PF_USBOTG_NXT (GPIO_PORTE | GPIO_PF | GPIO_OUT | 0) +#define PE1_PF_USBOTG_STP (GPIO_PORTE | GPIO_PF | GPIO_OUT | 1) +#define PE2_PF_USBOTG_DIR (GPIO_PORTE | GPIO_PF | GPIO_OUT | 2) +#define PE24_PF_USBOTG_CLK (GPIO_PORTE | GPIO_PF | GPIO_OUT | 24) +#define PE25_PF_USBOTG_DATA7 (GPIO_PORTE | GPIO_PF | GPIO_OUT | 25) +#define PF1_PF_NFCLE (GPIO_PORTF | GPIO_PF | 1) +#define PF3_PF_NFCE (GPIO_PORTF | GPIO_PF | 3) +#define PF7_PF_PC_POE (GPIO_PORTF | GPIO_PF | 7) +#define PF8_PF_PC_RW (GPIO_PORTF | GPIO_PF | 8) +#define PF9_PF_PC_IOIS16 (GPIO_PORTF | GPIO_PF | 9) +#define PF10_PF_PC_RST (GPIO_PORTF | GPIO_PF | 10) +#define PF11_PF_PC_BVD2 (GPIO_PORTF | GPIO_PF | 11) +#define PF12_PF_PC_BVD1 (GPIO_PORTF | GPIO_PF | 12) +#define PF13_PF_PC_VS2 (GPIO_PORTF | GPIO_PF | 13) +#define PF14_PF_PC_VS1 (GPIO_PORTF | GPIO_PF | 14) +#define PF16_PF_PC_PWRON (GPIO_PORTF | GPIO_PF | 16) +#define PF17_PF_PC_READY (GPIO_PORTF | GPIO_PF | 17) +#define PF18_PF_PC_WAIT (GPIO_PORTF | GPIO_PF | 18) +#define PF19_PF_PC_CD2 (GPIO_PORTF | GPIO_PF | 19) +#define PF20_PF_PC_CD1 (GPIO_PORTF | GPIO_PF | 20) +#define PF23_PF_ATA_DATA15 (GPIO_PORTF | GPIO_PF | 23) + +/* Alternate GPIO pin functions */ + +#define PB4_AF_MSHC_DATA0 (GPIO_PORTB | GPIO_AF | GPIO_OUT | 4) +#define PB5_AF_MSHC_DATA1 (GPIO_PORTB | GPIO_AF | GPIO_OUT | 5) +#define PB6_AF_MSHC_DATA2 (GPIO_PORTB | GPIO_AF | GPIO_OUT | 6) +#define PB7_AF_MSHC_DATA4 (GPIO_PORTB | GPIO_AF | GPIO_OUT | 7) +#define PB8_AF_MSHC_BS (GPIO_PORTB | GPIO_AF | GPIO_OUT | 8) +#define PB9_AF_MSHC_SCLK (GPIO_PORTB | GPIO_AF | GPIO_OUT | 9) +#define PB10_AF_UART6_TXD (GPIO_PORTB | GPIO_AF | GPIO_OUT | 10) +#define PB11_AF_UART6_RXD (GPIO_PORTB | GPIO_AF | GPIO_IN | 11) +#define PB12_AF_UART6_CTS (GPIO_PORTB | GPIO_AF | GPIO_OUT | 12) +#define PB13_AF_UART6_RTS (GPIO_PORTB | GPIO_AF | GPIO_IN | 13) +#define PB18_AF_UART5_TXD (GPIO_PORTB | GPIO_AF | GPIO_OUT | 18) +#define PB19_AF_UART5_RXD (GPIO_PORTB | GPIO_AF | GPIO_IN | 19) +#define PB20_AF_UART5_CTS (GPIO_PORTB | GPIO_AF | GPIO_OUT | 20) +#define PB21_AF_UART5_RTS (GPIO_PORTB | GPIO_AF | GPIO_IN | 21) +#define PC8_AF_FEC_MDIO (GPIO_PORTC | GPIO_AF | GPIO_IN | 8) +#define PC24_AF_GPT5_TOUT (GPIO_PORTC | GPIO_AF | 24) +#define PC26_AF_GPT4_TOUT (GPIO_PORTC | GPIO_AF | 26) +#define PD1_AF_ETMTRACE_PKT15 (GPIO_PORTD | GPIO_AF | 1) +#define PD6_AF_ETMTRACE_PKT14 (GPIO_PORTD | GPIO_AF | 6) +#define PD7_AF_ETMTRACE_PKT13 (GPIO_PORTD | GPIO_AF | 7) +#define PD9_AF_ETMTRACE_PKT12 (GPIO_PORTD | GPIO_AF | 9) +#define PD2_AF_SD3_D0 (GPIO_PORTD | GPIO_AF | 2) +#define PD3_AF_SD3_D1 (GPIO_PORTD | GPIO_AF | 3) +#define PD4_AF_SD3_D2 (GPIO_PORTD | GPIO_AF | 4) +#define PD5_AF_SD3_D3 (GPIO_PORTD | GPIO_AF | 5) +#define PD8_AF_FEC_MDIO (GPIO_PORTD | GPIO_AF | GPIO_IN | 8) +#define PD10_AF_ETMTRACE_PKT11 (GPIO_PORTD | GPIO_AF | 10) +#define PD11_AF_ETMTRACE_PKT10 (GPIO_PORTD | GPIO_AF | 11) +#define PD12_AF_ETMTRACE_PKT9 (GPIO_PORTD | GPIO_AF | 12) +#define PD13_AF_ETMTRACE_PKT8 (GPIO_PORTD | GPIO_AF | 13) +#define PD14_AF_ETMTRACE_PKT7 (GPIO_PORTD | GPIO_AF | 14) +#define PD15_AF_ETMTRACE_PKT6 (GPIO_PORTD | GPIO_AF | 15) +#define PD16_AF_ETMTRACE_PKT5 (GPIO_PORTD | GPIO_AF | 16) +#define PF1_AF_ETMTRACE_PKT0 (GPIO_PORTF | GPIO_AF | 1) +#define PF3_AF_ETMTRACE_PKT2 (GPIO_PORTF | GPIO_AF | 3) +#define PF5_AF_ETMPIPESTAT11 (GPIO_PORTF | GPIO_AF | 5) +#define PF7_AF_ATA_BUFFER_EN (GPIO_PORTF | GPIO_AF | 7) +#define PF8_AF_ATA_IORDY (GPIO_PORTF | GPIO_AF | 8) +#define PF9_AF_ATA_INTRQ (GPIO_PORTF | GPIO_AF | 9) +#define PF10_AF_ATA_RESET (GPIO_PORTF | GPIO_AF | 10) +#define PF11_AF_ATA_DMACK (GPIO_PORTF | GPIO_AF | 11) +#define PF12_AF_ATA_DMAREQ (GPIO_PORTF | GPIO_AF | 12) +#define PF13_AF_ATA_DA0 (GPIO_PORTF | GPIO_AF | 13) +#define PF14_AF_ATA_DA1 (GPIO_PORTF | GPIO_AF | 14) +#define PF15_AF_ETMTRACE_SYNC (GPIO_PORTF | GPIO_AF | 15) +#define PF16_AF_ATA_DA2 (GPIO_PORTF | GPIO_AF | 16) +#define PF17_AF_ATA_CS0 (GPIO_PORTF | GPIO_AF | 17) +#define PF18_AF_ATA_CS1 (GPIO_PORTF | GPIO_AF | 18) +#define PF19_AF_ATA_DIOW (GPIO_PORTF | GPIO_AF | 19) +#define PF20_AF_ATA_DIOR (GPIO_PORTF | GPIO_AF | 20) +#define PF22_AF_ETMTRACE_CLK (GPIO_PORTF | GPIO_AF | 22) +#define PF23_AF_ETMTRACE_PKT4 (GPIO_PORTF | GPIO_AF | 23) + +/* AIN GPIO pin functions */ + +#define PC14_AIN_SSI1_MCLK (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 14) +#define PC15_AIN_GPT6_TOUT (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 15) +#define PD0_AIN_FEC_TXD0 (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 0) +#define PD1_AIN_FEC_TXD1 (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 1) +#define PD2_AIN_FEC_TXD2 (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 2) +#define PD3_AIN_FEC_TXD3 (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 3) +#define PD9_AIN_FEC_MDC (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 9) +#define PD16_AIN_FEC_TX_ER (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 16) +#define PD27_AIN_EXT_DMA_GRANT (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 27) +#define PF23_AIN_FEC_TX_EN (GPIO_PORTF | GPIO_AIN | GPIO_OUT | 23) + +/* BIN GPIO pin functions */ + +#define PC14_BIN_SSI2_MCLK (GPIO_PORTC | GPIO_BIN | GPIO_OUT | 14) + +/* CIN GPIO pin functions */ + +#define PD2_CIN_SLCDC1_DAT0 (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 2) +#define PD3_CIN_SLCDC1_DAT1 (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 3) +#define PD4_CIN_SLCDC1_DAT2 (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 4) +#define PD5_CIN_SLCDC1_DAT3 (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 5) +#define PD6_CIN_SLCDC1_DAT4 (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 6) +#define PD7_CIN_SLCDC1_DAT5 (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 7) +#define PD8_CIN_SLCDC1_DAT6 (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 8) +#define PD9_CIN_SLCDC1_DAT7 (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 9) +#define PD10_CIN_SLCDC1_DAT8 (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 10) +#define PD11_CIN_SLCDC1_DAT9 (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 11) +#define PD12_CIN_SLCDC1_DAT10 (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 12) +#define PD13_CIN_SLCDC1_DAT11 (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 13) +#define PD14_CIN_SLCDC1_DAT12 (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 14) +#define PD15_CIN_SLCDC1_DAT13 (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 15) +#define PD16_CIN_SLCDC1_DAT14 (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 16) +#define PD23_CIN_SLCDC1_DAT15 (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 23) +#define PF27_CIN_EXT_DMA_GRANT (GPIO_PORTF | GPIO_CIN | GPIO_OUT | 27) +/* LCDC_TESTx on PBxx omitted, because it's not clear what they do */ + +/* AOUT GPIO pin functions */ + +#define PC14_AOUT_GPT6_TIN (GPIO_PORTC | GPIO_AOUT | GPIO_IN | 14) +#define PD4_AOUT_FEC_RX_ER (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 4) +#define PD5_AOUT_FEC_RXD1 (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 5) +#define PD6_AOUT_FEC_RXD2 (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 6) +#define PD7_AOUT_FEC_RXD3 (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 7) +#define PD10_AOUT_FEC_CRS (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 10) +#define PD11_AOUT_FEC_TX_CLK (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 11) +#define PD12_AOUT_FEC_RXD0 (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 12) +#define PD13_AOUT_FEC_RX_DV (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 13) +#define PD14_AOUT_FEC_RX_CLK (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 14) +#define PD15_AOUT_FEC_COL (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 15) + +#define PC17_BOUT_PC_IOIS16 (GPIO_PORTC | GPIO_BOUT | GPIO_IN | 17) +#define PC18_BOUT_PC_BVD2 (GPIO_PORTC | GPIO_BOUT | GPIO_IN | 18) +#define PC19_BOUT_PC_BVD1 (GPIO_PORTC | GPIO_BOUT | GPIO_IN | 19) +#define PC28_BOUT_PC_BVD2 (GPIO_PORTC | GPIO_BOUT | GPIO_IN | 28) +#define PC29_BOUT_PC_VS1 (GPIO_PORTC | GPIO_BOUT | GPIO_IN | 29) +#define PC30_BOUT_PC_READY (GPIO_PORTC | GPIO_BOUT | GPIO_IN | 30) +#define PC31_BOUT_PC_WAIT (GPIO_PORTC | GPIO_BOUT | GPIO_IN | 31) + + +#endif /* _MXC_GPIO_MX1_MX2_H */ diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx2x.h b/arch/arm/plat-mxc/include/mach/iomux-mx2x.h new file mode 100644 index 00000000000..fb5ae638e79 --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/iomux-mx2x.h @@ -0,0 +1,237 @@ +/* +* Copyright (C) 2008 by Sascha Hauer +* Copyright (C) 2009 by Holger Schurig +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +* MA 02110-1301, USA. +*/ + +#ifndef _MXC_IOMUX_MX2x_H +#define _MXC_IOMUX_MX2x_H + +#ifndef GPIO_PORTA +#error Please include mach/iomux.h +#endif + + +/* Primary GPIO pin functions */ + +#define PA5_PF_LSCLK (GPIO_PORTA | GPIO_PF | GPIO_OUT | 5) +#define PA6_PF_LD0 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 6) +#define PA7_PF_LD1 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 7) +#define PA8_PF_LD2 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 8) +#define PA9_PF_LD3 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 9) +#define PA10_PF_LD4 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 10) +#define PA11_PF_LD5 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 11) +#define PA12_PF_LD6 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 12) +#define PA13_PF_LD7 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 13) +#define PA14_PF_LD8 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 14) +#define PA15_PF_LD9 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 15) +#define PA16_PF_LD10 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 16) +#define PA17_PF_LD11 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 17) +#define PA18_PF_LD12 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 18) +#define PA19_PF_LD13 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 19) +#define PA20_PF_LD14 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 20) +#define PA21_PF_LD15 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 21) +#define PA22_PF_LD16 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 22) +#define PA23_PF_LD17 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 23) +#define PA24_PF_REV (GPIO_PORTA | GPIO_PF | GPIO_OUT | 24) +#define PA25_PF_CLS (GPIO_PORTA | GPIO_PF | GPIO_OUT | 25) +#define PA26_PF_PS (GPIO_PORTA | GPIO_PF | GPIO_OUT | 26) +#define PA27_PF_SPL_SPR (GPIO_PORTA | GPIO_PF | GPIO_OUT | 27) +#define PA28_PF_HSYNC (GPIO_PORTA | GPIO_PF | GPIO_OUT | 28) +#define PA29_PF_VSYNC (GPIO_PORTA | GPIO_PF | GPIO_OUT | 29) +#define PA30_PF_CONTRAST (GPIO_PORTA | GPIO_PF | GPIO_OUT | 30) +#define PA31_PF_OE_ACD (GPIO_PORTA | GPIO_PF | GPIO_OUT | 31) +#define PB4_PF_SD2_D0 (GPIO_PORTB | GPIO_PF | 4) +#define PB5_PF_SD2_D1 (GPIO_PORTB | GPIO_PF | 5) +#define PB6_PF_SD2_D2 (GPIO_PORTB | GPIO_PF | 6) +#define PB7_PF_SD2_D3 (GPIO_PORTB | GPIO_PF | 7) +#define PB8_PF_SD2_CMD (GPIO_PORTB | GPIO_PF | 8) +#define PB9_PF_SD2_CLK (GPIO_PORTB | GPIO_PF | 9) +#define PB10_PF_CSI_D0 (GPIO_PORTB | GPIO_PF | GPIO_OUT | 10) +#define PB11_PF_CSI_D1 (GPIO_PORTB | GPIO_PF | GPIO_OUT | 11) +#define PB12_PF_CSI_D2 (GPIO_PORTB | GPIO_PF | GPIO_OUT | 12) +#define PB13_PF_CSI_D3 (GPIO_PORTB | GPIO_PF | GPIO_OUT | 13) +#define PB14_PF_CSI_D4 (GPIO_PORTB | GPIO_PF | GPIO_OUT | 14) +#define PB15_PF_CSI_MCLK (GPIO_PORTB | GPIO_PF | GPIO_OUT | 15) +#define PB16_PF_CSI_PIXCLK (GPIO_PORTB | GPIO_PF | GPIO_OUT | 16) +#define PB17_PF_CSI_D5 (GPIO_PORTB | GPIO_PF | GPIO_OUT | 17) +#define PB18_PF_CSI_D6 (GPIO_PORTB | GPIO_PF | GPIO_OUT | 18) +#define PB19_PF_CSI_D7 (GPIO_PORTB | GPIO_PF | GPIO_OUT | 19) +#define PB20_PF_CSI_VSYNC (GPIO_PORTB | GPIO_PF | GPIO_OUT | 20) +#define PB21_PF_CSI_HSYNC (GPIO_PORTB | GPIO_PF | GPIO_OUT | 21) +#define PB23_PF_USB_PWR (GPIO_PORTB | GPIO_PF | 23) +#define PB24_PF_USB_OC (GPIO_PORTB | GPIO_PF | 24) +#define PB26_PF_USBH1_FS (GPIO_PORTB | GPIO_PF | 26) +#define PB27_PF_USBH1_OE (GPIO_PORTB | GPIO_PF | 27) +#define PB28_PF_USBH1_TXDM (GPIO_PORTB | GPIO_PF | 28) +#define PB29_PF_USBH1_TXDP (GPIO_PORTB | GPIO_PF | 29) +#define PB30_PF_USBH1_RXDM (GPIO_PORTB | GPIO_PF | 30) +#define PB31_PF_USBH1_RXDP (GPIO_PORTB | GPIO_PF | 31) +#define PC14_PF_TOUT (GPIO_PORTC | GPIO_PF | 14) +#define PC15_PF_TIN (GPIO_PORTC | GPIO_PF | 15) +#define PC20_PF_SSI1_FS (GPIO_PORTC | GPIO_PF | GPIO_IN | 20) +#define PC21_PF_SSI1_RXD (GPIO_PORTC | GPIO_PF | GPIO_IN | 21) +#define PC22_PF_SSI1_TXD (GPIO_PORTC | GPIO_PF | GPIO_IN | 22) +#define PC23_PF_SSI1_CLK (GPIO_PORTC | GPIO_PF | GPIO_IN | 23) +#define PC24_PF_SSI2_FS (GPIO_PORTC | GPIO_PF | GPIO_IN | 24) +#define PC25_PF_SSI2_RXD (GPIO_PORTC | GPIO_PF | GPIO_IN | 25) +#define PC26_PF_SSI2_TXD (GPIO_PORTC | GPIO_PF | GPIO_IN | 26) +#define PC27_PF_SSI2_CLK (GPIO_PORTC | GPIO_PF | GPIO_IN | 27) +#define PC28_PF_SSI3_FS (GPIO_PORTC | GPIO_PF | GPIO_IN | 28) +#define PC29_PF_SSI3_RXD (GPIO_PORTC | GPIO_PF | GPIO_IN | 29) +#define PC30_PF_SSI3_TXD (GPIO_PORTC | GPIO_PF | GPIO_IN | 30) +#define PC31_PF_SSI3_CLK (GPIO_PORTC | GPIO_PF | GPIO_IN | 31) +#define PD17_PF_I2C_DATA (GPIO_PORTD | GPIO_PF | GPIO_OUT | 17) +#define PD18_PF_I2C_CLK (GPIO_PORTD | GPIO_PF | GPIO_OUT | 18) +#define PD19_PF_CSPI2_SS2 (GPIO_PORTD | GPIO_PF | 19) +#define PD20_PF_CSPI2_SS1 (GPIO_PORTD | GPIO_PF | 20) +#define PD21_PF_CSPI2_SS0 (GPIO_PORTD | GPIO_PF | 21) +#define PD22_PF_CSPI2_SCLK (GPIO_PORTD | GPIO_PF | 22) +#define PD23_PF_CSPI2_MISO (GPIO_PORTD | GPIO_PF | 23) +#define PD24_PF_CSPI2_MOSI (GPIO_PORTD | GPIO_PF | 24) +#define PD25_PF_CSPI1_RDY (GPIO_PORTD | GPIO_PF | GPIO_OUT | 25) +#define PD26_PF_CSPI1_SS2 (GPIO_PORTD | GPIO_PF | GPIO_OUT | 26) +#define PD27_PF_CSPI1_SS1 (GPIO_PORTD | GPIO_PF | GPIO_OUT | 27) +#define PD28_PF_CSPI1_SS0 (GPIO_PORTD | GPIO_PF | GPIO_OUT | 28) +#define PD29_PF_CSPI1_SCLK (GPIO_PORTD | GPIO_PF | GPIO_OUT | 29) +#define PD30_PF_CSPI1_MISO (GPIO_PORTD | GPIO_PF | GPIO_IN | 30) +#define PD31_PF_CSPI1_MOSI (GPIO_PORTD | GPIO_PF | GPIO_OUT | 31) +#define PE3_PF_UART2_CTS (GPIO_PORTE | GPIO_PF | GPIO_OUT | 3) +#define PE4_PF_UART2_RTS (GPIO_PORTE | GPIO_PF | GPIO_IN | 4) +#define PE5_PF_PWMO (GPIO_PORTE | GPIO_PF | 5) +#define PE6_PF_UART2_TXD (GPIO_PORTE | GPIO_PF | GPIO_OUT | 6) +#define PE7_PF_UART2_RXD (GPIO_PORTE | GPIO_PF | GPIO_IN | 7) +#define PE8_PF_UART3_TXD (GPIO_PORTE | GPIO_PF | GPIO_OUT | 8) +#define PE9_PF_UART3_RXD (GPIO_PORTE | GPIO_PF | GPIO_IN | 9) +#define PE10_PF_UART3_CTS (GPIO_PORTE | GPIO_PF | GPIO_OUT | 10) +#define PE11_PF_UART3_RTS (GPIO_PORTE | GPIO_PF | GPIO_IN | 11) +#define PE12_PF_UART1_TXD (GPIO_PORTE | GPIO_PF | GPIO_OUT | 12) +#define PE13_PF_UART1_RXD (GPIO_PORTE | GPIO_PF | GPIO_IN | 13) +#define PE14_PF_UART1_CTS (GPIO_PORTE | GPIO_PF | GPIO_OUT | 14) +#define PE15_PF_UART1_RTS (GPIO_PORTE | GPIO_PF | GPIO_IN | 15) +#define PE16_PF_RTCK (GPIO_PORTE | GPIO_PF | GPIO_OUT | 16) +#define PE17_PF_RESET_OUT (GPIO_PORTE | GPIO_PF | 17) +#define PE18_PF_SD1_D0 (GPIO_PORTE | GPIO_PF | 18) +#define PE19_PF_SD1_D1 (GPIO_PORTE | GPIO_PF | 19) +#define PE20_PF_SD1_D2 (GPIO_PORTE | GPIO_PF | 20) +#define PE21_PF_SD1_D3 (GPIO_PORTE | GPIO_PF | 21) +#define PE22_PF_SD1_CMD (GPIO_PORTE | GPIO_PF | 22) +#define PE23_PF_SD1_CLK (GPIO_PORTE | GPIO_PF | 23) +#define PF0_PF_NRFB (GPIO_PORTF | GPIO_PF | 0) +#define PF2_PF_NFWP (GPIO_PORTF | GPIO_PF | 2) +#define PF4_PF_NFALE (GPIO_PORTF | GPIO_PF | 4) +#define PF5_PF_NFRE (GPIO_PORTF | GPIO_PF | 5) +#define PF6_PF_NFWE (GPIO_PORTF | GPIO_PF | 6) +#define PF15_PF_CLKO (GPIO_PORTF | GPIO_PF | 15) +#define PF21_PF_CS4 (GPIO_PORTF | GPIO_PF | 21) +#define PF22_PF_CS5 (GPIO_PORTF | GPIO_PF | 22) + +/* Alternate GPIO pin functions */ + +#define PB26_AF_UART4_RTS (GPIO_PORTB | GPIO_AF | GPIO_IN | 26) +#define PB28_AF_UART4_TXD (GPIO_PORTB | GPIO_AF | GPIO_OUT | 28) +#define PB29_AF_UART4_CTS (GPIO_PORTB | GPIO_AF | GPIO_OUT | 29) +#define PB31_AF_UART4_RXD (GPIO_PORTB | GPIO_AF | GPIO_IN | 31) +#define PC28_AF_SLCDC2_D0 (GPIO_PORTC | GPIO_AF | 28) +#define PC29_AF_SLCDC2_RS (GPIO_PORTC | GPIO_AF | 29) +#define PC30_AF_SLCDC2_CS (GPIO_PORTC | GPIO_AF | 30) +#define PC31_AF_SLCDC2_CLK (GPIO_PORTC | GPIO_AF | 31) +#define PD19_AF_USBH2_DATA4 (GPIO_PORTD | GPIO_AF | 19) +#define PD20_AF_USBH2_DATA3 (GPIO_PORTD | GPIO_AF | 20) +#define PD21_AF_USBH2_DATA6 (GPIO_PORTD | GPIO_AF | 21) +#define PD22_AF_USBH2_DATA0 (GPIO_PORTD | GPIO_AF | 22) +#define PD23_AF_USBH2_DATA2 (GPIO_PORTD | GPIO_AF | 23) +#define PD24_AF_USBH2_DATA1 (GPIO_PORTD | GPIO_AF | 24) +#define PD26_AF_USBH2_DATA5 (GPIO_PORTD | GPIO_AF | 26) +#define PE0_AF_KP_COL6 (GPIO_PORTE | GPIO_AF | 0) +#define PE1_AF_KP_ROW6 (GPIO_PORTE | GPIO_AF | 1) +#define PE2_AF_KP_ROW7 (GPIO_PORTE | GPIO_AF | 2) +#define PE3_AF_KP_COL7 (GPIO_PORTE | GPIO_AF | 3) +#define PE4_AF_KP_ROW7 (GPIO_PORTE | GPIO_AF | 4) +#define PE6_AF_KP_COL6 (GPIO_PORTE | GPIO_AF | 6) +#define PE7_AF_KP_ROW6 (GPIO_PORTE | GPIO_AF | 7) +#define PE16_AF_OWIRE (GPIO_PORTE | GPIO_AF | 16) +#define PE18_AF_CSPI3_MISO (GPIO_PORTE | GPIO_AF | GPIO_IN | 18) +#define PE21_AF_CSPI3_SS (GPIO_PORTE | GPIO_AF | GPIO_OUT | 21) +#define PE22_AF_CSPI3_MOSI (GPIO_PORTE | GPIO_AF | GPIO_OUT | 22) +#define PE23_AF_CSPI3_SCLK (GPIO_PORTE | GPIO_AF | GPIO_OUT | 23) + +/* AIN GPIO pin functions */ + +#define PA6_AIN_SLCDC1_DAT0 (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 6) +#define PA7_AIN_SLCDC1_DAT1 (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 7) +#define PA8_AIN_SLCDC1_DAT2 (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 8) +#define PA0_AIN_SLCDC1_DAT3 (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 0) +#define PA11_AIN_SLCDC1_DAT5 (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 11) +#define PA13_AIN_SLCDC1_DAT7 (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 13) +#define PA15_AIN_SLCDC1_DAT9 (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 15) +#define PA17_AIN_SLCDC1_DAT11 (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 17) +#define PA19_AIN_SLCDC1_DAT13 (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 19) +#define PA21_AIN_SLCDC1_DAT15 (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 21) +#define PA22_AIN_EXT_DMAGRANT (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 22) +#define PA24_AIN_SLCDC1_D0 (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 24) +#define PA25_AIN_SLCDC1_RS (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 25) +#define PA26_AIN_SLCDC1_CS (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 26) +#define PA27_AIN_SLCDC1_CLK (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 27) +#define PB6_AIN_SLCDC1_D0 (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 6) +#define PB7_AIN_SLCDC1_RS (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 7) +#define PB8_AIN_SLCDC1_CS (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 8) +#define PB9_AIN_SLCDC1_CLK (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 9) +#define PB25_AIN_SLCDC1_DAT0 (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 25) +#define PB26_AIN_SLCDC1_DAT1 (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 26) +#define PB27_AIN_SLCDC1_DAT2 (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 27) +#define PB28_AIN_SLCDC1_DAT3 (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 28) +#define PB29_AIN_SLCDC1_DAT4 (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 29) +#define PB30_AIN_SLCDC1_DAT5 (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 30) +#define PB31_AIN_SLCDC1_DAT6 (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 31) +#define PC5_AIN_SLCDC1_DAT7 (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 5) +#define PC6_AIN_SLCDC1_DAT8 (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 6) +#define PC7_AIN_SLCDC1_DAT9 (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 7) +#define PC8_AIN_SLCDC1_DAT10 (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 8) +#define PC9_AIN_SLCDC1_DAT11 (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 9) +#define PC10_AIN_SLCDC1_DAT12 (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 10) +#define PC11_AIN_SLCDC1_DAT13 (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 11) +#define PC12_AIN_SLCDC1_DAT14 (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 12) +#define PC13_AIN_SLCDC1_DAT15 (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 13) +#define PE5_AIN_PC_SPKOUT (GPIO_PORTE | GPIO_AIN | GPIO_OUT | 5) + +/* BIN GPIO pin functions */ + +#define PE5_BIN_TOUT2 (GPIO_PORTE | GPIO_BIN | GPIO_OUT | 5) + +/* CIN GPIO pin functions */ + +#define PA14_CIN_SLCDC1_DAT0 (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 14) +#define PA15_CIN_SLCDC1_DAT1 (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 15) +#define PA16_CIN_SLCDC1_DAT2 (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 16) +#define PA17_CIN_SLCDC1_DAT3 (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 17) +#define PA18_CIN_SLCDC1_DAT4 (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 18) +#define PA19_CIN_SLCDC1_DAT5 (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 19) +#define PA20_CIN_SLCDC1_DAT6 (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 20) +#define PA21_CIN_SLCDC1_DAT7 (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 21) +#define PB30_CIN_UART4_CTS (GPIO_PORTB | GPIO_CIN | GPIO_OUT | 30) +#define PE5_CIN_TOUT3 (GPIO_PORTE | GPIO_CIN | GPIO_OUT | 5) + +/* AOUT GPIO pin functions */ + +#define PB29_AOUT_UART4_RXD (GPIO_PORTB | GPIO_AOUT | GPIO_IN | 29) +#define PB31_AOUT_UART4_RTS (GPIO_PORTB | GPIO_AOUT | GPIO_IN | 31) +#define PC8_AOUT_USBOTG_TXR_INT (GPIO_PORTC | GPIO_AOUT | GPIO_IN | 8) +#define PC15_AOUT_WKGD (GPIO_PORTC | GPIO_AOUT | GPIO_IN | 15) +#define PF21_AOUT_DTACK (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 21) + + +#endif diff --git a/arch/arm/plat-mxc/include/mach/iomux.h b/arch/arm/plat-mxc/include/mach/iomux.h new file mode 100644 index 00000000000..171f8adc110 --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/iomux.h @@ -0,0 +1,127 @@ +/* +* Copyright (C) 2008 by Sascha Hauer +* Copyright (C) 2009 by Holger Schurig +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +* MA 02110-1301, USA. +*/ + +#ifndef _MXC_IOMUX_H +#define _MXC_IOMUX_H + +/* +* GPIO Module and I/O Multiplexer +* x = 0..3 for reg_A, reg_B, reg_C, reg_D +*/ +#define VA_GPIO_BASE IO_ADDRESS(GPIO_BASE_ADDR) +#define MXC_DDIR(x) (0x00 + ((x) << 8)) +#define MXC_OCR1(x) (0x04 + ((x) << 8)) +#define MXC_OCR2(x) (0x08 + ((x) << 8)) +#define MXC_ICONFA1(x) (0x0c + ((x) << 8)) +#define MXC_ICONFA2(x) (0x10 + ((x) << 8)) +#define MXC_ICONFB1(x) (0x14 + ((x) << 8)) +#define MXC_ICONFB2(x) (0x18 + ((x) << 8)) +#define MXC_DR(x) (0x1c + ((x) << 8)) +#define MXC_GIUS(x) (0x20 + ((x) << 8)) +#define MXC_SSR(x) (0x24 + ((x) << 8)) +#define MXC_ICR1(x) (0x28 + ((x) << 8)) +#define MXC_ICR2(x) (0x2c + ((x) << 8)) +#define MXC_IMR(x) (0x30 + ((x) << 8)) +#define MXC_ISR(x) (0x34 + ((x) << 8)) +#define MXC_GPR(x) (0x38 + ((x) << 8)) +#define MXC_SWR(x) (0x3c + ((x) << 8)) +#define MXC_PUEN(x) (0x40 + ((x) << 8)) + +#ifdef CONFIG_ARCH_MX1 +# define GPIO_PORT_MAX 3 +#endif +#ifdef CONFIG_ARCH_MX2 +# define GPIO_PORT_MAX 5 +#endif + +#ifndef GPIO_PORT_MAX +# error "GPIO config port count unknown!" +#endif + +#define GPIO_PIN_MASK 0x1f + +#define GPIO_PORT_SHIFT 5 +#define GPIO_PORT_MASK (0x7 << GPIO_PORT_SHIFT) + +#define GPIO_PORTA (0 << GPIO_PORT_SHIFT) +#define GPIO_PORTB (1 << GPIO_PORT_SHIFT) +#define GPIO_PORTC (2 << GPIO_PORT_SHIFT) +#define GPIO_PORTD (3 << GPIO_PORT_SHIFT) +#define GPIO_PORTE (4 << GPIO_PORT_SHIFT) +#define GPIO_PORTF (5 << GPIO_PORT_SHIFT) + +#define GPIO_OUT (1 << 8) +#define GPIO_IN (0 << 8) +#define GPIO_PUEN (1 << 9) + +#define GPIO_PF (1 << 10) +#define GPIO_AF (1 << 11) + +#define GPIO_OCR_SHIFT 12 +#define GPIO_OCR_MASK (3 << GPIO_OCR_SHIFT) +#define GPIO_AIN (0 << GPIO_OCR_SHIFT) +#define GPIO_BIN (1 << GPIO_OCR_SHIFT) +#define GPIO_CIN (2 << GPIO_OCR_SHIFT) +#define GPIO_GPIO (3 << GPIO_OCR_SHIFT) + +#define GPIO_AOUT_SHIFT 14 +#define GPIO_AOUT_MASK (3 << GPIO_AOUT_SHIFT) +#define GPIO_AOUT (0 << GPIO_AOUT_SHIFT) +#define GPIO_AOUT_ISR (1 << GPIO_AOUT_SHIFT) +#define GPIO_AOUT_0 (2 << GPIO_AOUT_SHIFT) +#define GPIO_AOUT_1 (3 << GPIO_AOUT_SHIFT) + +#define GPIO_BOUT_SHIFT 16 +#define GPIO_BOUT_MASK (3 << GPIO_BOUT_SHIFT) +#define GPIO_BOUT (0 << GPIO_BOUT_SHIFT) +#define GPIO_BOUT_ISR (1 << GPIO_BOUT_SHIFT) +#define GPIO_BOUT_0 (2 << GPIO_BOUT_SHIFT) +#define GPIO_BOUT_1 (3 << GPIO_BOUT_SHIFT) + + +#ifdef CONFIG_ARCH_MX1 +#include +#endif +#ifdef CONFIG_ARCH_MX2 +#include +#ifdef CONFIG_MACH_MX21 +#include +#endif +#ifdef CONFIG_MACH_MX27 +#include +#endif +#endif + + +/* decode irq number to use with IMR(x), ISR(x) and friends */ +#define IRQ_TO_REG(irq) ((irq - MXC_INTERNAL_IRQS) >> 5) + +#define IRQ_GPIOA(x) (MXC_GPIO_IRQ_START + x) +#define IRQ_GPIOB(x) (IRQ_GPIOA(32) + x) +#define IRQ_GPIOC(x) (IRQ_GPIOB(32) + x) +#define IRQ_GPIOD(x) (IRQ_GPIOC(32) + x) +#define IRQ_GPIOE(x) (IRQ_GPIOD(32) + x) + + +extern void mxc_gpio_mode(int gpio_mode); +extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count, + const char *label); +extern void mxc_gpio_release_multiple_pins(const int *pin_list, int count); + +#endif diff --git a/arch/arm/plat-mxc/iomux-mx1-mx2.c b/arch/arm/plat-mxc/iomux-mx1-mx2.c index df6f1839568..a37163ce280 100644 --- a/arch/arm/plat-mxc/iomux-mx1-mx2.c +++ b/arch/arm/plat-mxc/iomux-mx1-mx2.c @@ -32,7 +32,7 @@ #include #include -#include +#include void mxc_gpio_mode(int gpio_mode) { -- GitLab From 5512e88f3a1f1b498fd07181f14596ee117b3471 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Mon, 26 Jan 2009 16:34:52 +0100 Subject: [PATCH 3248/4982] arm/imx21: add kbuild support for the Freescale i.MX21 * adds Kconfig variables * specifies different physical address for i.MX21 because of the different memory layouts * disables support for UART5/UART6 in the i.MX serial driver (the i.MX21 doesn't have those modules) Based on code from "Martin Fuzzey" Signed-off-by: Holger Schurig Signed-off-by: Sascha Hauer --- arch/arm/mach-mx2/Kconfig | 13 +++++++++++++ arch/arm/mach-mx2/Makefile.boot | 10 +++++++--- arch/arm/mach-mx2/serial.c | 2 ++ arch/arm/plat-mxc/include/mach/memory.h | 5 +++++ arch/arm/plat-mxc/include/mach/mxc.h | 4 ++++ 5 files changed, 31 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-mx2/Kconfig b/arch/arm/mach-mx2/Kconfig index 1eaa97cb716..412d2d55b08 100644 --- a/arch/arm/mach-mx2/Kconfig +++ b/arch/arm/mach-mx2/Kconfig @@ -1,12 +1,25 @@ comment "MX2 family CPU support" depends on ARCH_MX2 +choice + prompt "MX2 Type" + depends on ARCH_MX2 + default MACH_MX21 + +config MACH_MX21 + bool "i.MX21 support" + depends on ARCH_MX2 + help + This enables support for Freescale's MX2 based i.MX21 processor. + config MACH_MX27 bool "i.MX27 support" depends on ARCH_MX2 help This enables support for Freescale's MX2 based i.MX27 processor. +endchoice + comment "MX2 Platforms" depends on ARCH_MX2 diff --git a/arch/arm/mach-mx2/Makefile.boot b/arch/arm/mach-mx2/Makefile.boot index 696831dcd48..e867398a8fd 100644 --- a/arch/arm/mach-mx2/Makefile.boot +++ b/arch/arm/mach-mx2/Makefile.boot @@ -1,3 +1,7 @@ - zreladdr-y := 0xA0008000 -params_phys-y := 0xA0000100 -initrd_phys-y := 0xA0800000 +zreladdr-$(CONFIG_MACH_MX21) := 0xC0008000 +params_phys-$(CONFIG_MACH_MX21) := 0xC0000100 +initrd_phys-$(CONFIG_MACH_MX21) := 0xC0800000 + +zreladdr-$(CONFIG_MACH_MX27) := 0xA0008000 +params_phys-$(CONFIG_MACH_MX27) := 0xA0000100 +initrd_phys-$(CONFIG_MACH_MX27) := 0xA0800000 diff --git a/arch/arm/mach-mx2/serial.c b/arch/arm/mach-mx2/serial.c index 16debc296da..b9e66fb1186 100644 --- a/arch/arm/mach-mx2/serial.c +++ b/arch/arm/mach-mx2/serial.c @@ -99,6 +99,7 @@ struct platform_device mxc_uart_device3 = { .num_resources = ARRAY_SIZE(uart3), }; +#ifdef CONFIG_MACH_MX27 static struct resource uart4[] = { { .start = UART5_BASE_ADDR, @@ -136,3 +137,4 @@ struct platform_device mxc_uart_device5 = { .resource = uart5, .num_resources = ARRAY_SIZE(uart5), }; +#endif diff --git a/arch/arm/plat-mxc/include/mach/memory.h b/arch/arm/plat-mxc/include/mach/memory.h index 0b808399097..e0783e61958 100644 --- a/arch/arm/plat-mxc/include/mach/memory.h +++ b/arch/arm/plat-mxc/include/mach/memory.h @@ -14,7 +14,12 @@ #if defined CONFIG_ARCH_MX1 #define PHYS_OFFSET UL(0x08000000) #elif defined CONFIG_ARCH_MX2 +#ifdef CONFIG_MACH_MX21 +#define PHYS_OFFSET UL(0xC0000000) +#endif +#ifdef CONFIG_MACH_MX27 #define PHYS_OFFSET UL(0xA0000000) +#endif #elif defined CONFIG_ARCH_MX3 #define PHYS_OFFSET UL(0x80000000) #endif diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h index f6caab06213..bbd848e004d 100644 --- a/arch/arm/plat-mxc/include/mach/mxc.h +++ b/arch/arm/plat-mxc/include/mach/mxc.h @@ -29,6 +29,10 @@ # define cpu_is_mx31() (0) #endif +#ifndef CONFIG_MACH_MX21 +# define cpu_is_mx21() (0) +#endif + #ifndef CONFIG_MACH_MX27 # define cpu_is_mx27() (0) #endif -- GitLab From a2865197a5dad23c619c84f44b7fdf7fdbef3f9c Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 26 Jan 2009 15:41:16 +0100 Subject: [PATCH 3249/4982] [ARM] MXC: Use a single function for decoding a PLL We had 3 versions of this function in clock support for MX1/2/3 Use a single one instead. I picked the one from the MX3 as it seems to calculate more accurate as the other ones. Also, on MX27 and MX31 mfn can be negative, this hasn't been handled correctly on MX27 since now. This patch has been tested on MX27 and MX31 and produces the same clock frequencies for me. Signed-off-by: Sascha Hauer --- arch/arm/mach-mx1/clock.c | 31 ++---------------- arch/arm/mach-mx2/clock_imx27.c | 42 ++++-------------------- arch/arm/mach-mx3/clock.c | 26 ++------------- arch/arm/plat-mxc/clock.c | 44 ++++++++++++++++++++++++++ arch/arm/plat-mxc/include/mach/clock.h | 2 ++ 5 files changed, 57 insertions(+), 88 deletions(-) diff --git a/arch/arm/mach-mx1/clock.c b/arch/arm/mach-mx1/clock.c index 4bcd1ece55f..3c464331b87 100644 --- a/arch/arm/mach-mx1/clock.c +++ b/arch/arm/mach-mx1/clock.c @@ -87,33 +87,6 @@ static int _clk_parent_set_rate(struct clk *clk, unsigned long rate) return clk->parent->set_rate(clk->parent, rate); } -/* - * get the system pll clock in Hz - * - * mfi + mfn / (mfd +1) - * f = 2 * f_ref * -------------------- - * pd + 1 - */ -static unsigned long mx1_decode_pll(unsigned int pll, u32 f_ref) -{ - unsigned long long ll; - unsigned long quot; - - u32 mfi = (pll >> 10) & 0xf; - u32 mfn = pll & 0x3ff; - u32 mfd = (pll >> 16) & 0x3ff; - u32 pd = (pll >> 26) & 0xf; - - mfi = mfi <= 5 ? 5 : mfi; - - ll = 2 * (unsigned long long)f_ref * - ((mfi << 16) + (mfn << 16) / (mfd + 1)); - quot = (pd + 1) * (1 << 16); - ll += quot / 2; - do_div(ll, quot); - return (unsigned long)ll; -} - static unsigned long clk16m_get_rate(struct clk *clk) { return 16000000; @@ -188,7 +161,7 @@ static struct clk prem_clk = { static unsigned long system_clk_get_rate(struct clk *clk) { - return mx1_decode_pll(__raw_readl(CCM_SPCTL0), + return mxc_decode_pll(__raw_readl(CCM_SPCTL0), clk_get_rate(clk->parent)); } @@ -200,7 +173,7 @@ static struct clk system_clk = { static unsigned long mcu_clk_get_rate(struct clk *clk) { - return mx1_decode_pll(__raw_readl(CCM_MPCTL0), + return mxc_decode_pll(__raw_readl(CCM_MPCTL0), clk_get_rate(clk->parent)); } diff --git a/arch/arm/mach-mx2/clock_imx27.c b/arch/arm/mach-mx2/clock_imx27.c index c69896d011a..047e71e6ea9 100644 --- a/arch/arm/mach-mx2/clock_imx27.c +++ b/arch/arm/mach-mx2/clock_imx27.c @@ -486,26 +486,8 @@ static struct clk ckil_clk = { static unsigned long get_mpll_clk(struct clk *clk) { - uint32_t reg; - unsigned long ref_clk; - unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0; - unsigned long long temp; - - ref_clk = clk_get_rate(clk->parent); - - reg = __raw_readl(CCM_MPCTL0); - pdf = (reg & CCM_MPCTL0_PD_MASK) >> CCM_MPCTL0_PD_OFFSET; - mfd = (reg & CCM_MPCTL0_MFD_MASK) >> CCM_MPCTL0_MFD_OFFSET; - mfi = (reg & CCM_MPCTL0_MFI_MASK) >> CCM_MPCTL0_MFI_OFFSET; - mfn = (reg & CCM_MPCTL0_MFN_MASK) >> CCM_MPCTL0_MFN_OFFSET; - - mfi = (mfi <= 5) ? 5 : mfi; - temp = 2LL * ref_clk * mfn; - do_div(temp, mfd + 1); - temp = 2LL * ref_clk * mfi + temp; - do_div(temp, pdf + 1); - - return (unsigned long)temp; + return mxc_decode_pll(__raw_readl(CCM_MPCTL0), + clk_get_rate(clk->parent)); } static struct clk mpll_clk = { @@ -555,28 +537,18 @@ static unsigned long get_spll_clk(struct clk *clk) { uint32_t reg; unsigned long ref_clk; - unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0; - unsigned long long temp; ref_clk = clk_get_rate(clk->parent); reg = __raw_readl(CCM_SPCTL0); - /*TODO: This is TO2 Bug */ + + /* On TO2 we have to write the value back. Otherwise we + * read 0 from this register the next time. + */ if (mx27_revision() >= CHIP_REV_2_0) __raw_writel(reg, CCM_SPCTL0); - pdf = (reg & CCM_SPCTL0_PD_MASK) >> CCM_SPCTL0_PD_OFFSET; - mfd = (reg & CCM_SPCTL0_MFD_MASK) >> CCM_SPCTL0_MFD_OFFSET; - mfi = (reg & CCM_SPCTL0_MFI_MASK) >> CCM_SPCTL0_MFI_OFFSET; - mfn = (reg & CCM_SPCTL0_MFN_MASK) >> CCM_SPCTL0_MFN_OFFSET; - - mfi = (mfi <= 5) ? 5 : mfi; - temp = 2LL * ref_clk * mfn; - do_div(temp, mfd + 1); - temp = 2LL * ref_clk * mfi + temp; - do_div(temp, pdf + 1); - - return (unsigned long)temp; + return mxc_decode_pll(reg, ref_clk); } static struct clk spll_clk = { diff --git a/arch/arm/mach-mx3/clock.c b/arch/arm/mach-mx3/clock.c index b1746aae1f8..8486ea46d6c 100644 --- a/arch/arm/mach-mx3/clock.c +++ b/arch/arm/mach-mx3/clock.c @@ -158,10 +158,8 @@ static int _clk_pll_set_rate(struct clk *clk, unsigned long rate) static unsigned long _clk_pll_get_rate(struct clk *clk) { - long mfi, mfn, mfd, pdf, ref_clk, mfn_abs; unsigned long reg, ccmr; - s64 temp; - unsigned int prcs; + unsigned int prcs, ref_clk; ccmr = __raw_readl(MXC_CCM_CCMR); prcs = (ccmr & MXC_CCM_CCMR_PRCS_MASK) >> MXC_CCM_CCMR_PRCS_OFFSET; @@ -185,27 +183,7 @@ static unsigned long _clk_pll_get_rate(struct clk *clk) return 0; } - pdf = (reg & MXC_CCM_PCTL_PD_MASK) >> MXC_CCM_PCTL_PD_OFFSET; - mfd = (reg & MXC_CCM_PCTL_MFD_MASK) >> MXC_CCM_PCTL_MFD_OFFSET; - mfi = (reg & MXC_CCM_PCTL_MFI_MASK) >> MXC_CCM_PCTL_MFI_OFFSET; - mfi = (mfi <= 5) ? 5 : mfi; - mfn = mfn_abs = reg & MXC_CCM_PCTL_MFN_MASK; - - if (mfn >= 0x200) { - mfn |= 0xFFFFFE00; - mfn_abs = -mfn; - } - - ref_clk *= 2; - ref_clk /= pdf + 1; - - temp = (u64) ref_clk * mfn_abs; - do_div(temp, mfd + 1); - if (mfn < 0) - temp = -temp; - temp = (ref_clk * mfi) + temp; - - return temp; + return mxc_decode_pll(reg, ref_clk); } static int _clk_usb_pll_enable(struct clk *clk) diff --git a/arch/arm/plat-mxc/clock.c b/arch/arm/plat-mxc/clock.c index 0a38f0b396e..888dd33abf7 100644 --- a/arch/arm/plat-mxc/clock.c +++ b/arch/arm/plat-mxc/clock.c @@ -328,3 +328,47 @@ static int __init mxc_setup_proc_entry(void) late_initcall(mxc_setup_proc_entry); #endif + +/* + * Get the resulting clock rate from a PLL register value and the input + * frequency. PLLs with this register layout can at least be found on + * MX1, MX21, MX27 and MX31 + * + * mfi + mfn / (mfd + 1) + * f = 2 * f_ref * -------------------- + * pd + 1 + */ +unsigned long mxc_decode_pll(unsigned int reg_val, u32 freq) +{ + long long ll; + int mfn_abs; + unsigned int mfi, mfn, mfd, pd; + + mfi = (reg_val >> 10) & 0xf; + mfn = reg_val & 0x3ff; + mfd = (reg_val >> 16) & 0x3ff; + pd = (reg_val >> 26) & 0xf; + + mfi = mfi <= 5 ? 5 : mfi; + + mfn_abs = mfn; + +#if !defined CONFIG_ARCH_MX1 && !defined CONFIG_ARCH_MX21 + if (mfn >= 0x200) { + mfn |= 0xFFFFFE00; + mfn_abs = -mfn; + } +#endif + + freq *= 2; + freq /= pd + 1; + + ll = (unsigned long long)freq * mfn_abs; + + do_div(ll, mfd + 1); + if (mfn < 0) + ll = -ll; + ll = (freq * mfi) + ll; + + return ll; +} diff --git a/arch/arm/plat-mxc/include/mach/clock.h b/arch/arm/plat-mxc/include/mach/clock.h index d21f78e7881..b830655514e 100644 --- a/arch/arm/plat-mxc/include/mach/clock.h +++ b/arch/arm/plat-mxc/include/mach/clock.h @@ -63,5 +63,7 @@ struct clk { int clk_register(struct clk *clk); void clk_unregister(struct clk *clk); +unsigned long mxc_decode_pll(unsigned int pll, u32 f_ref); + #endif /* __ASSEMBLY__ */ #endif /* __ASM_ARCH_MXC_CLOCK_H__ */ -- GitLab From 30c730f8f90b08d77a73998d2ee34cf1f56e95cc Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 16 Feb 2009 14:36:49 +0100 Subject: [PATCH 3250/4982] [ARM] MXC: rework timer/clock initialisation - rename mxc_clocks_init to architecture specific versions. This allows us to have more than one architecture compiled in. - call mxc_timer_init from clock initialisation instead from board code Signed-off-by: Sascha Hauer --- arch/arm/mach-mx1/clock.c | 5 ++++- arch/arm/mach-mx1/mx1ads.c | 3 +-- arch/arm/mach-mx2/clock_imx27.c | 5 ++++- arch/arm/mach-mx2/mx27ads.c | 3 +-- arch/arm/mach-mx2/pcm038.c | 3 +-- arch/arm/mach-mx3/clock.c | 5 ++++- arch/arm/mach-mx3/mx31ads.c | 3 +-- arch/arm/mach-mx3/mx31lite.c | 3 +-- arch/arm/mach-mx3/mx31moboard.c | 3 +-- arch/arm/mach-mx3/mx31pdk.c | 3 +-- arch/arm/mach-mx3/pcm037.c | 3 +-- arch/arm/plat-mxc/include/mach/common.h | 7 +++++-- arch/arm/plat-mxc/time.c | 20 +++++--------------- 13 files changed, 30 insertions(+), 36 deletions(-) diff --git a/arch/arm/mach-mx1/clock.c b/arch/arm/mach-mx1/clock.c index 3c464331b87..40a2274380a 100644 --- a/arch/arm/mach-mx1/clock.c +++ b/arch/arm/mach-mx1/clock.c @@ -25,6 +25,7 @@ #include #include +#include #include "crm_regs.h" static int _clk_enable(struct clk *clk) @@ -594,7 +595,7 @@ static struct clk *mxc_clks[] = { &rtc_clk, }; -int __init mxc_clocks_init(unsigned long fref) +int __init mx1_clocks_init(unsigned long fref) { struct clk **clkp; unsigned int reg; @@ -625,5 +626,7 @@ int __init mxc_clocks_init(unsigned long fref) clk_enable(&hclk); clk_enable(&fclk); + mxc_timer_init(&gpt_clk); + return 0; } diff --git a/arch/arm/mach-mx1/mx1ads.c b/arch/arm/mach-mx1/mx1ads.c index be7dd75ebbe..09dc77bb481 100644 --- a/arch/arm/mach-mx1/mx1ads.c +++ b/arch/arm/mach-mx1/mx1ads.c @@ -118,8 +118,7 @@ static void __init mx1ads_init(void) static void __init mx1ads_timer_init(void) { - mxc_clocks_init(32000); - mxc_timer_init("gpt_clk"); + mx1_clocks_init(32000); } struct sys_timer mx1ads_timer = { diff --git a/arch/arm/mach-mx2/clock_imx27.c b/arch/arm/mach-mx2/clock_imx27.c index 047e71e6ea9..7b2c1122d9a 100644 --- a/arch/arm/mach-mx2/clock_imx27.c +++ b/arch/arm/mach-mx2/clock_imx27.c @@ -1551,7 +1551,7 @@ static void __init probe_mxc_clocks(void) * must be called very early to get information about the * available clock rate when the timer framework starts */ -int __init mxc_clocks_init(unsigned long fref) +int __init mx27_clocks_init(unsigned long fref) { u32 cscr; struct clk **clkp; @@ -1593,5 +1593,8 @@ int __init mxc_clocks_init(unsigned long fref) #ifdef CONFIG_DEBUG_LL_CONSOLE clk_enable(&uart1_clk[0]); #endif + + mxc_timer_init(&gpt1_clk[0]); + return 0; } diff --git a/arch/arm/mach-mx2/mx27ads.c b/arch/arm/mach-mx2/mx27ads.c index 7721c470d5a..536bf64bc7c 100644 --- a/arch/arm/mach-mx2/mx27ads.c +++ b/arch/arm/mach-mx2/mx27ads.c @@ -263,8 +263,7 @@ static void __init mx27ads_timer_init(void) if ((__raw_readw(PBC_VERSION_REG) & CKIH_27MHZ_BIT_SET) == 0) fref = 27000000; - mxc_clocks_init(fref); - mxc_timer_init("gpt_clk.0"); + mx27_clocks_init(fref); } struct sys_timer mx27ads_timer = { diff --git a/arch/arm/mach-mx2/pcm038.c b/arch/arm/mach-mx2/pcm038.c index 534fd9a4ff9..63cdef8565d 100644 --- a/arch/arm/mach-mx2/pcm038.c +++ b/arch/arm/mach-mx2/pcm038.c @@ -230,8 +230,7 @@ static void __init pcm038_init(void) static void __init pcm038_timer_init(void) { - mxc_clocks_init(26000000); - mxc_timer_init("gpt_clk.0"); + mx27_clocks_init(26000000); } struct sys_timer pcm038_timer = { diff --git a/arch/arm/mach-mx3/clock.c b/arch/arm/mach-mx3/clock.c index 8486ea46d6c..8b41facb391 100644 --- a/arch/arm/mach-mx3/clock.c +++ b/arch/arm/mach-mx3/clock.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "crm_regs.h" @@ -1071,7 +1072,7 @@ static struct clk *mxc_clks[] = { &iim_clk, }; -int __init mxc_clocks_init(unsigned long fref) +int __init mx31_clocks_init(unsigned long fref) { u32 reg; struct clk **clkp; @@ -1121,6 +1122,8 @@ int __init mxc_clocks_init(unsigned long fref) __raw_writel(reg, MXC_CCM_PMCR1); } + mxc_timer_init(&ipg_clk); + return 0; } diff --git a/arch/arm/mach-mx3/mx31ads.c b/arch/arm/mach-mx3/mx31ads.c index f902a7c37c3..f913999eedf 100644 --- a/arch/arm/mach-mx3/mx31ads.c +++ b/arch/arm/mach-mx3/mx31ads.c @@ -244,8 +244,7 @@ static void __init mxc_board_init(void) static void __init mx31ads_timer_init(void) { - mxc_clocks_init(26000000); - mxc_timer_init("ipg_clk.0"); + mx31_clocks_init(26000000); } struct sys_timer mx31ads_timer = { diff --git a/arch/arm/mach-mx3/mx31lite.c b/arch/arm/mach-mx3/mx31lite.c index c4344007014..e61fad2f60f 100644 --- a/arch/arm/mach-mx3/mx31lite.c +++ b/arch/arm/mach-mx3/mx31lite.c @@ -82,8 +82,7 @@ static void __init mxc_board_init(void) static void __init mx31lite_timer_init(void) { - mxc_clocks_init(26000000); - mxc_timer_init("ipg_clk.0"); + mx31_clocks_init(26000000); } struct sys_timer mx31lite_timer = { diff --git a/arch/arm/mach-mx3/mx31moboard.c b/arch/arm/mach-mx3/mx31moboard.c index c29098af739..3d2773e4bc8 100644 --- a/arch/arm/mach-mx3/mx31moboard.c +++ b/arch/arm/mach-mx3/mx31moboard.c @@ -120,8 +120,7 @@ void __init mx31moboard_map_io(void) static void __init mx31moboard_timer_init(void) { - mxc_clocks_init(26000000); - mxc_timer_init("ipg_clk.0"); + mx31_clocks_init(26000000); } struct sys_timer mx31moboard_timer = { diff --git a/arch/arm/mach-mx3/mx31pdk.c b/arch/arm/mach-mx3/mx31pdk.c index d464d068a4a..ac427edb4db 100644 --- a/arch/arm/mach-mx3/mx31pdk.c +++ b/arch/arm/mach-mx3/mx31pdk.c @@ -91,8 +91,7 @@ static void __init mxc_board_init(void) static void __init mx31pdk_timer_init(void) { - mxc_clocks_init(26000000); - mxc_timer_init("ipg_clk.0"); + mx31_clocks_init(26000000); } static struct sys_timer mx31pdk_timer = { diff --git a/arch/arm/mach-mx3/pcm037.c b/arch/arm/mach-mx3/pcm037.c index 8cea8258722..3b5ba551cb1 100644 --- a/arch/arm/mach-mx3/pcm037.c +++ b/arch/arm/mach-mx3/pcm037.c @@ -181,8 +181,7 @@ void __init pcm037_map_io(void) static void __init pcm037_timer_init(void) { - mxc_clocks_init(26000000); - mxc_timer_init("ipg_clk.0"); + mx31_clocks_init(26000000); } struct sys_timer pcm037_timer = { diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h index 6350287a59b..2c08b8e14e3 100644 --- a/arch/arm/plat-mxc/include/mach/common.h +++ b/arch/arm/plat-mxc/include/mach/common.h @@ -12,11 +12,14 @@ #define __ASM_ARCH_MXC_COMMON_H__ struct platform_device; +struct clk; extern void mxc_map_io(void); extern void mxc_init_irq(void); -extern void mxc_timer_init(const char *clk_timer); -extern int mxc_clocks_init(unsigned long fref); +extern void mxc_timer_init(struct clk *timer_clk); +extern int mx1_clocks_init(unsigned long fref); +extern int mx27_clocks_init(unsigned long fref); +extern int mx31_clocks_init(unsigned long fref); extern int mxc_register_gpios(void); extern int mxc_register_device(struct platform_device *pdev, void *data); diff --git a/arch/arm/plat-mxc/time.c b/arch/arm/plat-mxc/time.c index 758a1293bcf..eb93fd1789d 100644 --- a/arch/arm/plat-mxc/time.c +++ b/arch/arm/plat-mxc/time.c @@ -34,9 +34,6 @@ static struct clock_event_device clockevent_mxc; static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED; -/* clock source for the timer */ -static struct clk *timer_clk; - /* clock source */ static cycle_t mxc_get_cycles(void) @@ -53,7 +50,7 @@ static struct clocksource clocksource_mxc = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -static int __init mxc_clocksource_init(void) +static int __init mxc_clocksource_init(struct clk *timer_clk) { unsigned int clock; @@ -177,7 +174,7 @@ static struct clock_event_device clockevent_mxc = { .rating = 200, }; -static int __init mxc_clockevent_init(void) +static int __init mxc_clockevent_init(struct clk *timer_clk) { unsigned int clock; @@ -197,14 +194,8 @@ static int __init mxc_clockevent_init(void) return 0; } -void __init mxc_timer_init(const char *clk_timer) +void __init mxc_timer_init(struct clk *timer_clk) { - timer_clk = clk_get(NULL, clk_timer); - if (!timer_clk) { - printk(KERN_ERR"Cannot determine timer clock. Giving up.\n"); - return; - } - clk_enable(timer_clk); /* @@ -219,10 +210,9 @@ void __init mxc_timer_init(const char *clk_timer) TIMER_BASE + MXC_TCTL); /* init and register the timer to the framework */ - mxc_clocksource_init(); - mxc_clockevent_init(); + mxc_clocksource_init(timer_clk); + mxc_clockevent_init(timer_clk); /* Make irqs happen */ setup_irq(TIMER_INTERRUPT, &mxc_timer_irq); } - -- GitLab From e65fb0099fe4fe82d59ffe84f1e88a489218d7f9 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 16 Feb 2009 14:29:10 +0100 Subject: [PATCH 3251/4982] [ARM] MXC: remove _clk suffix from clock names The context makes it clear already that these are clocks, so there's no need for such a suffix. This patch only changes the clocks actually used in the tree. The remaining clocks are renamed in the subsequent architecture specific patches. Signed-off-by: Sascha Hauer --- arch/arm/mach-mx1/clock.c | 4 ++-- arch/arm/mach-mx2/clock_imx27.c | 18 +++++++++--------- arch/arm/mach-mx3/clock.c | 14 +++++++------- arch/arm/plat-mxc/dma-mx1-mx2.c | 2 +- drivers/mtd/nand/mxc_nand.c | 2 +- drivers/serial/imx.c | 2 +- drivers/w1/masters/mxc_w1.c | 2 +- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/arch/arm/mach-mx1/clock.c b/arch/arm/mach-mx1/clock.c index 40a2274380a..0d0f306851d 100644 --- a/arch/arm/mach-mx1/clock.c +++ b/arch/arm/mach-mx1/clock.c @@ -462,7 +462,7 @@ static struct clk clko_clk = { }; static struct clk dma_clk = { - .name = "dma_clk", + .name = "dma", .parent = &hclk, .round_rate = _clk_parent_round_rate, .set_rate = _clk_parent_set_rate, @@ -513,7 +513,7 @@ static struct clk gpt_clk = { }; static struct clk uart_clk = { - .name = "uart_clk", + .name = "uart", .parent = &perclk[0], .round_rate = _clk_parent_round_rate, .set_rate = _clk_parent_set_rate, diff --git a/arch/arm/mach-mx2/clock_imx27.c b/arch/arm/mach-mx2/clock_imx27.c index 7b2c1122d9a..700a22f5ae8 100644 --- a/arch/arm/mach-mx2/clock_imx27.c +++ b/arch/arm/mach-mx2/clock_imx27.c @@ -685,7 +685,7 @@ static struct clk per_clk[] = { struct clk uart1_clk[] = { { - .name = "uart_clk", + .name = "uart", .id = 0, .parent = &per_clk[0], .secondary = &uart1_clk[1], @@ -702,7 +702,7 @@ struct clk uart1_clk[] = { struct clk uart2_clk[] = { { - .name = "uart_clk", + .name = "uart", .id = 1, .parent = &per_clk[0], .secondary = &uart2_clk[1], @@ -719,7 +719,7 @@ struct clk uart2_clk[] = { struct clk uart3_clk[] = { { - .name = "uart_clk", + .name = "uart", .id = 2, .parent = &per_clk[0], .secondary = &uart3_clk[1], @@ -736,7 +736,7 @@ struct clk uart3_clk[] = { struct clk uart4_clk[] = { { - .name = "uart_clk", + .name = "uart", .id = 3, .parent = &per_clk[0], .secondary = &uart4_clk[1], @@ -753,7 +753,7 @@ struct clk uart4_clk[] = { struct clk uart5_clk[] = { { - .name = "uart_clk", + .name = "uart", .id = 4, .parent = &per_clk[0], .secondary = &uart5_clk[1], @@ -770,7 +770,7 @@ struct clk uart5_clk[] = { struct clk uart6_clk[] = { { - .name = "uart_clk", + .name = "uart", .id = 5, .parent = &per_clk[0], .secondary = &uart6_clk[1], @@ -1110,7 +1110,7 @@ static struct clk ssi2_clk[] = { }; static struct clk nfc_clk = { - .name = "nfc_clk", + .name = "nfc", .parent = &cpu_clk, .get_rate = _clk_nfc_recalc, .enable = _clk_enable, @@ -1128,7 +1128,7 @@ static struct clk vpu_clk = { }; static struct clk dma_clk = { - .name = "dma_clk", + .name = "dma", .parent = &ahb_clk, .enable = _clk_dma_enable, .disable = _clk_dma_disable, @@ -1260,7 +1260,7 @@ static struct clk kpp_clk = { }; static struct clk owire_clk = { - .name = "owire_clk", + .name = "owire", .parent = &ipg_clk, .enable = _clk_enable, .enable_reg = CCM_PCCR0, diff --git a/arch/arm/mach-mx3/clock.c b/arch/arm/mach-mx3/clock.c index 8b41facb391..bc3a3beb9a6 100644 --- a/arch/arm/mach-mx3/clock.c +++ b/arch/arm/mach-mx3/clock.c @@ -593,7 +593,7 @@ static struct clk epit_clk[] = { }; static struct clk nfc_clk = { - .name = "nfc_clk", + .name = "nfc", .parent = &ahb_clk, .get_rate = _clk_nfc_get_rate, }; @@ -667,7 +667,7 @@ static struct clk csi_clk = { static struct clk uart_clk[] = { { - .name = "uart_clk", + .name = "uart", .id = 0, .parent = &perclk_clk, .enable = _clk_enable, @@ -675,7 +675,7 @@ static struct clk uart_clk[] = { .enable_shift = MXC_CCM_CGR0_UART1_OFFSET, .disable = _clk_disable,}, { - .name = "uart_clk", + .name = "uart", .id = 1, .parent = &perclk_clk, .enable = _clk_enable, @@ -683,7 +683,7 @@ static struct clk uart_clk[] = { .enable_shift = MXC_CCM_CGR0_UART2_OFFSET, .disable = _clk_disable,}, { - .name = "uart_clk", + .name = "uart", .id = 2, .parent = &perclk_clk, .enable = _clk_enable, @@ -691,7 +691,7 @@ static struct clk uart_clk[] = { .enable_shift = MXC_CCM_CGR1_UART3_OFFSET, .disable = _clk_disable,}, { - .name = "uart_clk", + .name = "uart", .id = 3, .parent = &perclk_clk, .enable = _clk_enable, @@ -699,7 +699,7 @@ static struct clk uart_clk[] = { .enable_shift = MXC_CCM_CGR1_UART4_OFFSET, .disable = _clk_disable,}, { - .name = "uart_clk", + .name = "uart", .id = 4, .parent = &perclk_clk, .enable = _clk_enable, @@ -736,7 +736,7 @@ static struct clk i2c_clk[] = { }; static struct clk owire_clk = { - .name = "owire_clk", + .name = "owire", .parent = &perclk_clk, .enable_reg = MXC_CCM_CGR1, .enable_shift = MXC_CCM_CGR1_OWIRE_OFFSET, diff --git a/arch/arm/plat-mxc/dma-mx1-mx2.c b/arch/arm/plat-mxc/dma-mx1-mx2.c index 2905ec75875..1d64287c307 100644 --- a/arch/arm/plat-mxc/dma-mx1-mx2.c +++ b/arch/arm/plat-mxc/dma-mx1-mx2.c @@ -802,7 +802,7 @@ static int __init imx_dma_init(void) int ret = 0; int i; - dma_clk = clk_get(NULL, "dma_clk"); + dma_clk = clk_get(NULL, "dma"); clk_enable(dma_clk); /* reset DMA module */ diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 21fd4f1c480..bad048aca89 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -880,7 +880,7 @@ static int __init mxcnd_probe(struct platform_device *pdev) this->read_buf = mxc_nand_read_buf; this->verify_buf = mxc_nand_verify_buf; - host->clk = clk_get(&pdev->dev, "nfc_clk"); + host->clk = clk_get(&pdev->dev, "nfc"); if (IS_ERR(host->clk)) goto eclk; diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index a50954612b6..9f460b175c5 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -1129,7 +1129,7 @@ static int serial_imx_probe(struct platform_device *pdev) sport->timer.function = imx_timeout; sport->timer.data = (unsigned long)sport; - sport->clk = clk_get(&pdev->dev, "uart_clk"); + sport->clk = clk_get(&pdev->dev, "uart"); if (IS_ERR(sport->clk)) { ret = PTR_ERR(sport->clk); goto unmap; diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c index b9d74d0b353..65244c02551 100644 --- a/drivers/w1/masters/mxc_w1.c +++ b/drivers/w1/masters/mxc_w1.c @@ -116,7 +116,7 @@ static int __init mxc_w1_probe(struct platform_device *pdev) if (!mdev) return -ENOMEM; - mdev->clk = clk_get(&pdev->dev, "owire_clk"); + mdev->clk = clk_get(&pdev->dev, "owire"); if (!mdev->clk) { err = -ENODEV; goto failed_clk; -- GitLab From d1755e3592305f8866b4d60d63a481959d5e58bf Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 16 Feb 2009 14:27:06 +0100 Subject: [PATCH 3252/4982] [ARM] MXC: add clkdev support This patch only adds general clkdev support without actually switching any MXC architecture to clkdev. Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/clock.c | 10 ++++++++++ arch/arm/plat-mxc/include/mach/clkdev.h | 7 +++++++ arch/arm/plat-mxc/include/mach/clock.h | 4 ++++ 3 files changed, 21 insertions(+) create mode 100644 arch/arm/plat-mxc/include/mach/clkdev.h diff --git a/arch/arm/plat-mxc/clock.c b/arch/arm/plat-mxc/clock.c index 888dd33abf7..92e13566cd4 100644 --- a/arch/arm/plat-mxc/clock.c +++ b/arch/arm/plat-mxc/clock.c @@ -47,6 +47,11 @@ static DEFINE_MUTEX(clocks_mutex); * Standard clock functions defined in include/linux/clk.h *-------------------------------------------------------------------------*/ +/* + * All the code inside #ifndef CONFIG_COMMON_CLKDEV can be removed once all + * MXC architectures have switched to using clkdev. + */ +#ifndef CONFIG_COMMON_CLKDEV /* * Retrieve a clock by name. * @@ -110,6 +115,7 @@ found: return clk; } EXPORT_SYMBOL(clk_get); +#endif static void __clk_disable(struct clk *clk) { @@ -187,6 +193,7 @@ unsigned long clk_get_rate(struct clk *clk) } EXPORT_SYMBOL(clk_get_rate); +#ifndef CONFIG_COMMON_CLKDEV /* Decrement the clock's module reference count */ void clk_put(struct clk *clk) { @@ -194,6 +201,7 @@ void clk_put(struct clk *clk) module_put(clk->owner); } EXPORT_SYMBOL(clk_put); +#endif /* Round the requested clock rate to the nearest supported * rate that is less than or equal to the requested rate. @@ -257,6 +265,7 @@ struct clk *clk_get_parent(struct clk *clk) } EXPORT_SYMBOL(clk_get_parent); +#ifndef CONFIG_COMMON_CLKDEV /* * Add a new clock to the clock tree. */ @@ -327,6 +336,7 @@ static int __init mxc_setup_proc_entry(void) } late_initcall(mxc_setup_proc_entry); +#endif /* CONFIG_PROC_FS */ #endif /* diff --git a/arch/arm/plat-mxc/include/mach/clkdev.h b/arch/arm/plat-mxc/include/mach/clkdev.h new file mode 100644 index 00000000000..04b37a89801 --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/clkdev.h @@ -0,0 +1,7 @@ +#ifndef __ASM_MACH_CLKDEV_H +#define __ASM_MACH_CLKDEV_H + +#define __clk_get(clk) ({ 1; }) +#define __clk_put(clk) do { } while (0) + +#endif diff --git a/arch/arm/plat-mxc/include/mach/clock.h b/arch/arm/plat-mxc/include/mach/clock.h index b830655514e..43a82d0c534 100644 --- a/arch/arm/plat-mxc/include/mach/clock.h +++ b/arch/arm/plat-mxc/include/mach/clock.h @@ -26,9 +26,13 @@ struct module; struct clk { +#ifndef CONFIG_COMMON_CLKDEV + /* As soon as i.MX1 and i.MX31 switched to clkdev, this + * block can go away */ struct list_head node; struct module *owner; const char *name; +#endif int id; /* Source clock this clk depends on */ struct clk *parent; -- GitLab From edfcea80eb12b43680c4be0f2e31c8f5b1288edd Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 16 Feb 2009 15:13:43 +0100 Subject: [PATCH 3253/4982] [ARM] MX27 Clock rework This changes MX27 to use common clkdev. It also cleans up MX27 clock support to be more readable. Signed-off-by: Sascha Hauer --- arch/arm/mach-mx2/clock_imx27.c | 1613 ++++++++----------------------- arch/arm/mach-mx2/cpu_imx27.c | 4 +- arch/arm/mach-mx2/crm_regs.h | 273 ------ arch/arm/plat-mxc/Kconfig | 1 + 4 files changed, 387 insertions(+), 1504 deletions(-) delete mode 100644 arch/arm/mach-mx2/crm_regs.h diff --git a/arch/arm/mach-mx2/clock_imx27.c b/arch/arm/mach-mx2/clock_imx27.c index 700a22f5ae8..3f7280c490f 100644 --- a/arch/arm/mach-mx2/clock_imx27.c +++ b/arch/arm/mach-mx2/clock_imx27.c @@ -1,6 +1,7 @@ /* * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. * Copyright 2008 Juergen Beisert, kernel@pengutronix.de + * Copyright 2008 Martin Fuzzey, mfuzzey@gmail.com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -20,23 +21,60 @@ #include #include #include -#include -#include -#include +#include #include -#include "crm_regs.h" - -static struct clk ckil_clk; -static struct clk mpll_clk; -static struct clk mpll_main_clk[]; -static struct clk spll_clk; - -static int _clk_enable(struct clk *clk) +#include +#include +#include + +/* Register offsets */ +#define CCM_CSCR (IO_ADDRESS(CCM_BASE_ADDR) + 0x0) +#define CCM_MPCTL0 (IO_ADDRESS(CCM_BASE_ADDR) + 0x4) +#define CCM_MPCTL1 (IO_ADDRESS(CCM_BASE_ADDR) + 0x8) +#define CCM_SPCTL0 (IO_ADDRESS(CCM_BASE_ADDR) + 0xC) +#define CCM_SPCTL1 (IO_ADDRESS(CCM_BASE_ADDR) + 0x10) +#define CCM_OSC26MCTL (IO_ADDRESS(CCM_BASE_ADDR) + 0x14) +#define CCM_PCDR0 (IO_ADDRESS(CCM_BASE_ADDR) + 0x18) +#define CCM_PCDR1 (IO_ADDRESS(CCM_BASE_ADDR) + 0x1c) +#define CCM_PCCR0 (IO_ADDRESS(CCM_BASE_ADDR) + 0x20) +#define CCM_PCCR1 (IO_ADDRESS(CCM_BASE_ADDR) + 0x24) +#define CCM_CCSR (IO_ADDRESS(CCM_BASE_ADDR) + 0x28) +#define CCM_PMCTL (IO_ADDRESS(CCM_BASE_ADDR) + 0x2c) +#define CCM_PMCOUNT (IO_ADDRESS(CCM_BASE_ADDR) + 0x30) +#define CCM_WKGDCTL (IO_ADDRESS(CCM_BASE_ADDR) + 0x34) + +#define CCM_CSCR_UPDATE_DIS (1 << 31) +#define CCM_CSCR_SSI2 (1 << 23) +#define CCM_CSCR_SSI1 (1 << 22) +#define CCM_CSCR_VPU (1 << 21) +#define CCM_CSCR_MSHC (1 << 20) +#define CCM_CSCR_SPLLRES (1 << 19) +#define CCM_CSCR_MPLLRES (1 << 18) +#define CCM_CSCR_SP (1 << 17) +#define CCM_CSCR_MCU (1 << 16) +#define CCM_CSCR_OSC26MDIV (1 << 4) +#define CCM_CSCR_OSC26M (1 << 3) +#define CCM_CSCR_FPM (1 << 2) +#define CCM_CSCR_SPEN (1 << 1) +#define CCM_CSCR_MPEN (1 << 0) + +/* i.MX27 TO 2+ */ +#define CCM_CSCR_ARM_SRC (1 << 15) + +#define CCM_SPCTL1_LF (1 << 15) +#define CCM_SPCTL1_BRMO (1 << 6) + +static struct clk mpll_main1_clk, mpll_main2_clk; + +static int clk_pccr_enable(struct clk *clk) { unsigned long reg; + if (!clk->enable_reg) + return 0; + reg = __raw_readl(clk->enable_reg); reg |= 1 << clk->enable_shift; __raw_writel(reg, clk->enable_reg); @@ -44,16 +82,19 @@ static int _clk_enable(struct clk *clk) return 0; } -static void _clk_disable(struct clk *clk) +static void clk_pccr_disable(struct clk *clk) { unsigned long reg; + if (!clk->enable_reg) + return; + reg = __raw_readl(clk->enable_reg); reg &= ~(1 << clk->enable_shift); __raw_writel(reg, clk->enable_reg); } -static int _clk_spll_enable(struct clk *clk) +static int clk_spll_enable(struct clk *clk) { unsigned long reg; @@ -61,13 +102,12 @@ static int _clk_spll_enable(struct clk *clk) reg |= CCM_CSCR_SPEN; __raw_writel(reg, CCM_CSCR); - while ((__raw_readl(CCM_SPCTL1) & CCM_SPCTL1_LF) == 0) - ; + while (!(__raw_readl(CCM_SPCTL1) & CCM_SPCTL1_LF)); return 0; } -static void _clk_spll_disable(struct clk *clk) +static void clk_spll_disable(struct clk *clk) { unsigned long reg; @@ -76,192 +116,30 @@ static void _clk_spll_disable(struct clk *clk) __raw_writel(reg, CCM_CSCR); } -static void _clk_pccr01_enable(unsigned long mask0, unsigned long mask1) -{ - unsigned long reg; - - reg = __raw_readl(CCM_PCCR0); - reg |= mask0; - __raw_writel(reg, CCM_PCCR0); - - reg = __raw_readl(CCM_PCCR1); - reg |= mask1; - __raw_writel(reg, CCM_PCCR1); - -} - -static void _clk_pccr01_disable(unsigned long mask0, unsigned long mask1) -{ - unsigned long reg; - - reg = __raw_readl(CCM_PCCR0); - reg &= ~mask0; - __raw_writel(reg, CCM_PCCR0); - - reg = __raw_readl(CCM_PCCR1); - reg &= ~mask1; - __raw_writel(reg, CCM_PCCR1); -} - -static void _clk_pccr10_enable(unsigned long mask1, unsigned long mask0) -{ - unsigned long reg; - - reg = __raw_readl(CCM_PCCR1); - reg |= mask1; - __raw_writel(reg, CCM_PCCR1); - - reg = __raw_readl(CCM_PCCR0); - reg |= mask0; - __raw_writel(reg, CCM_PCCR0); -} - -static void _clk_pccr10_disable(unsigned long mask1, unsigned long mask0) -{ - unsigned long reg; - - reg = __raw_readl(CCM_PCCR1); - reg &= ~mask1; - __raw_writel(reg, CCM_PCCR1); - - reg = __raw_readl(CCM_PCCR0); - reg &= ~mask0; - __raw_writel(reg, CCM_PCCR0); -} - -static int _clk_dma_enable(struct clk *clk) -{ - _clk_pccr01_enable(CCM_PCCR0_DMA_MASK, CCM_PCCR1_HCLK_DMA_MASK); - - return 0; -} - -static void _clk_dma_disable(struct clk *clk) -{ - _clk_pccr01_disable(CCM_PCCR0_DMA_MASK, CCM_PCCR1_HCLK_DMA_MASK); -} - -static int _clk_rtic_enable(struct clk *clk) -{ - _clk_pccr01_enable(CCM_PCCR0_RTIC_MASK, CCM_PCCR1_HCLK_RTIC_MASK); - - return 0; -} - -static void _clk_rtic_disable(struct clk *clk) -{ - _clk_pccr01_disable(CCM_PCCR0_RTIC_MASK, CCM_PCCR1_HCLK_RTIC_MASK); -} - -static int _clk_emma_enable(struct clk *clk) -{ - _clk_pccr01_enable(CCM_PCCR0_EMMA_MASK, CCM_PCCR1_HCLK_EMMA_MASK); - - return 0; -} - -static void _clk_emma_disable(struct clk *clk) -{ - _clk_pccr01_disable(CCM_PCCR0_EMMA_MASK, CCM_PCCR1_HCLK_EMMA_MASK); -} - -static int _clk_slcdc_enable(struct clk *clk) -{ - _clk_pccr01_enable(CCM_PCCR0_SLCDC_MASK, CCM_PCCR1_HCLK_SLCDC_MASK); - - return 0; -} - -static void _clk_slcdc_disable(struct clk *clk) -{ - _clk_pccr01_disable(CCM_PCCR0_SLCDC_MASK, CCM_PCCR1_HCLK_SLCDC_MASK); -} - -static int _clk_fec_enable(struct clk *clk) -{ - _clk_pccr01_enable(CCM_PCCR0_FEC_MASK, CCM_PCCR1_HCLK_FEC_MASK); - - return 0; -} - -static void _clk_fec_disable(struct clk *clk) -{ - _clk_pccr01_disable(CCM_PCCR0_FEC_MASK, CCM_PCCR1_HCLK_FEC_MASK); -} - -static int _clk_vpu_enable(struct clk *clk) -{ - unsigned long reg; - - reg = __raw_readl(CCM_PCCR1); - reg |= CCM_PCCR1_VPU_BAUD_MASK | CCM_PCCR1_HCLK_VPU_MASK; - __raw_writel(reg, CCM_PCCR1); - - return 0; -} - -static void _clk_vpu_disable(struct clk *clk) -{ - unsigned long reg; - - reg = __raw_readl(CCM_PCCR1); - reg &= ~(CCM_PCCR1_VPU_BAUD_MASK | CCM_PCCR1_HCLK_VPU_MASK); - __raw_writel(reg, CCM_PCCR1); -} - -static int _clk_sahara2_enable(struct clk *clk) -{ - _clk_pccr01_enable(CCM_PCCR0_SAHARA_MASK, CCM_PCCR1_HCLK_SAHARA_MASK); - - return 0; -} - -static void _clk_sahara2_disable(struct clk *clk) -{ - _clk_pccr01_disable(CCM_PCCR0_SAHARA_MASK, CCM_PCCR1_HCLK_SAHARA_MASK); -} - -static int _clk_mstick1_enable(struct clk *clk) -{ - _clk_pccr10_enable(CCM_PCCR1_MSHC_BAUD_MASK, CCM_PCCR0_MSHC_MASK); - - return 0; -} - -static void _clk_mstick1_disable(struct clk *clk) +static int clk_cpu_set_parent(struct clk *clk, struct clk *parent) { - _clk_pccr10_disable(CCM_PCCR1_MSHC_BAUD_MASK, CCM_PCCR0_MSHC_MASK); -} - -#define CSCR() (__raw_readl(CCM_CSCR)) -#define PCDR0() (__raw_readl(CCM_PCDR0)) -#define PCDR1() (__raw_readl(CCM_PCDR1)) - -static int _clk_cpu_set_parent(struct clk *clk, struct clk *parent) -{ - int cscr = CSCR(); + int cscr = __raw_readl(CCM_CSCR); if (clk->parent == parent) return 0; if (mx27_revision() >= CHIP_REV_2_0) { - if (parent == &mpll_main_clk[0]) { + if (parent == &mpll_main1_clk) { cscr |= CCM_CSCR_ARM_SRC; } else { - if (parent == &mpll_main_clk[1]) + if (parent == &mpll_main2_clk) cscr &= ~CCM_CSCR_ARM_SRC; else return -EINVAL; } __raw_writel(cscr, CCM_CSCR); - } else - return -ENODEV; - - clk->parent = parent; - return 0; + clk->parent = parent; + return 0; + } + return -ENODEV; } -static unsigned long _clk_cpu_round_rate(struct clk *clk, unsigned long rate) +static unsigned long round_rate_cpu(struct clk *clk, unsigned long rate) { int div; unsigned long parent_rate; @@ -278,7 +156,7 @@ static unsigned long _clk_cpu_round_rate(struct clk *clk, unsigned long rate) return parent_rate / div; } -static int _clk_cpu_set_rate(struct clk *clk, unsigned long rate) +static int set_rate_cpu(struct clk *clk, unsigned long rate) { unsigned int div; uint32_t reg; @@ -295,19 +173,18 @@ static int _clk_cpu_set_rate(struct clk *clk, unsigned long rate) reg = __raw_readl(CCM_CSCR); if (mx27_revision() >= CHIP_REV_2_0) { - reg &= ~CCM_CSCR_ARM_MASK; - reg |= div << CCM_CSCR_ARM_OFFSET; - reg &= ~0x06; - __raw_writel(reg | 0x80000000, CCM_CSCR); + reg &= ~(3 << 12); + reg |= div << 12; + reg &= ~(CCM_CSCR_FPM | CCM_CSCR_SPEN); + __raw_writel(reg | CCM_CSCR_UPDATE_DIS, CCM_CSCR); } else { - printk(KERN_ERR "Cant set CPU frequency!\n"); + printk(KERN_ERR "Can't set CPU frequency!\n"); } return 0; } -static unsigned long _clk_perclkx_round_rate(struct clk *clk, - unsigned long rate) +static unsigned long round_rate_per(struct clk *clk, unsigned long rate) { u32 div; unsigned long parent_rate; @@ -324,7 +201,7 @@ static unsigned long _clk_perclkx_round_rate(struct clk *clk, return parent_rate / div; } -static int _clk_perclkx_set_rate(struct clk *clk, unsigned long rate) +static int set_rate_per(struct clk *clk, unsigned long rate) { u32 reg; u32 div; @@ -340,84 +217,65 @@ static int _clk_perclkx_set_rate(struct clk *clk, unsigned long rate) return -EINVAL; div--; - reg = - __raw_readl(CCM_PCDR1) & ~(CCM_PCDR1_PERDIV1_MASK << - (clk->id << 3)); + reg = __raw_readl(CCM_PCDR1) & ~(0x3f << (clk->id << 3)); reg |= div << (clk->id << 3); __raw_writel(reg, CCM_PCDR1); return 0; } -static unsigned long _clk_usb_recalc(struct clk *clk) +static unsigned long get_rate_usb(struct clk *clk) { unsigned long usb_pdf; unsigned long parent_rate; parent_rate = clk_get_rate(clk->parent); - usb_pdf = (CSCR() & CCM_CSCR_USB_MASK) >> CCM_CSCR_USB_OFFSET; + usb_pdf = (__raw_readl(CCM_CSCR) >> 28) & 0x7; return parent_rate / (usb_pdf + 1U); } -static unsigned long _clk_ssi1_recalc(struct clk *clk) +static unsigned long get_rate_ssix(struct clk *clk, unsigned long pdf) { - unsigned long ssi1_pdf; unsigned long parent_rate; parent_rate = clk_get_rate(clk->parent); - ssi1_pdf = (PCDR0() & CCM_PCDR0_SSI1BAUDDIV_MASK) >> - CCM_PCDR0_SSI1BAUDDIV_OFFSET; - if (mx27_revision() >= CHIP_REV_2_0) - ssi1_pdf += 4; + pdf += 4; /* MX27 TO2+ */ else - ssi1_pdf = (ssi1_pdf < 2) ? 124UL : ssi1_pdf; + pdf = (pdf < 2) ? 124UL : pdf; /* MX21 & MX27 TO1 */ - return 2UL * parent_rate / ssi1_pdf; + return 2UL * parent_rate / pdf; } -static unsigned long _clk_ssi2_recalc(struct clk *clk) +static unsigned long get_rate_ssi1(struct clk *clk) { - unsigned long ssi2_pdf; - unsigned long parent_rate; - - parent_rate = clk_get_rate(clk->parent); - - ssi2_pdf = (PCDR0() & CCM_PCDR0_SSI2BAUDDIV_MASK) >> - CCM_PCDR0_SSI2BAUDDIV_OFFSET; - - if (mx27_revision() >= CHIP_REV_2_0) - ssi2_pdf += 4; - else - ssi2_pdf = (ssi2_pdf < 2) ? 124UL : ssi2_pdf; + return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 16) & 0x3f); +} - return 2UL * parent_rate / ssi2_pdf; +static unsigned long get_rate_ssi2(struct clk *clk) +{ + return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 26) & 0x3f); } -static unsigned long _clk_nfc_recalc(struct clk *clk) +static unsigned long get_rate_nfc(struct clk *clk) { unsigned long nfc_pdf; unsigned long parent_rate; parent_rate = clk_get_rate(clk->parent); - if (mx27_revision() >= CHIP_REV_2_0) { - nfc_pdf = - (PCDR0() & CCM_PCDR0_NFCDIV2_MASK) >> - CCM_PCDR0_NFCDIV2_OFFSET; - } else { - nfc_pdf = - (PCDR0() & CCM_PCDR0_NFCDIV_MASK) >> - CCM_PCDR0_NFCDIV_OFFSET; - } + if (mx27_revision() >= CHIP_REV_2_0) + nfc_pdf = (__raw_readl(CCM_PCDR0) >> 6) & 0xf; + else + nfc_pdf = (__raw_readl(CCM_PCDR0) >> 12) & 0xf; return parent_rate / (nfc_pdf + 1); } -static unsigned long _clk_vpu_recalc(struct clk *clk) +static unsigned long get_rate_vpu(struct clk *clk) { unsigned long vpu_pdf; unsigned long parent_rate; @@ -425,25 +283,27 @@ static unsigned long _clk_vpu_recalc(struct clk *clk) parent_rate = clk_get_rate(clk->parent); if (mx27_revision() >= CHIP_REV_2_0) { - vpu_pdf = - (PCDR0() & CCM_PCDR0_VPUDIV2_MASK) >> - CCM_PCDR0_VPUDIV2_OFFSET; + vpu_pdf = (__raw_readl(CCM_PCDR0) >> 10) & 0x3f; vpu_pdf += 4; } else { - vpu_pdf = - (PCDR0() & CCM_PCDR0_VPUDIV_MASK) >> - CCM_PCDR0_VPUDIV_OFFSET; + vpu_pdf = (__raw_readl(CCM_PCDR0) >> 8) & 0xf; vpu_pdf = (vpu_pdf < 2) ? 124 : vpu_pdf; } + return 2UL * parent_rate / vpu_pdf; } -static unsigned long _clk_parent_round_rate(struct clk *clk, unsigned long rate) +static unsigned long round_rate_parent(struct clk *clk, unsigned long rate) { return clk->parent->round_rate(clk->parent, rate); } -static int _clk_parent_set_rate(struct clk *clk, unsigned long rate) +static unsigned long get_rate_parent(struct clk *clk) +{ + return clk_get_rate(clk->parent); +} + +static int set_rate_parent(struct clk *clk, unsigned long rate) { return clk->parent->set_rate(clk->parent, rate); } @@ -451,94 +311,52 @@ static int _clk_parent_set_rate(struct clk *clk, unsigned long rate) /* in Hz */ static unsigned long external_high_reference = 26000000; -static unsigned long get_high_reference_clock_rate(struct clk *clk) +static unsigned long get_rate_high_reference(struct clk *clk) { return external_high_reference; } -/* - * the high frequency external clock reference - * Default case is 26MHz. Could be changed at runtime - * with a call to change_external_high_reference() - */ -static struct clk ckih_clk = { - .name = "ckih", - .get_rate = get_high_reference_clock_rate, -}; - /* in Hz */ static unsigned long external_low_reference = 32768; -static unsigned long get_low_reference_clock_rate(struct clk *clk) +static unsigned long get_rate_low_reference(struct clk *clk) { return external_low_reference; } -/* - * the low frequency external clock reference - * Default case is 32.768kHz Could be changed at runtime - * with a call to change_external_low_reference() - */ -static struct clk ckil_clk = { - .name = "ckil", - .get_rate = get_low_reference_clock_rate, -}; +static unsigned long get_rate_fpm(struct clk *clk) +{ + return clk_get_rate(clk->parent) * 1024; +} -static unsigned long get_mpll_clk(struct clk *clk) +static unsigned long get_rate_mpll(struct clk *clk) { return mxc_decode_pll(__raw_readl(CCM_MPCTL0), clk_get_rate(clk->parent)); } -static struct clk mpll_clk = { - .name = "mpll", - .parent = &ckih_clk, - .get_rate = get_mpll_clk, -}; - -static unsigned long _clk_mpll_main_get_rate(struct clk *clk) +static unsigned long get_rate_mpll_main(struct clk *clk) { unsigned long parent_rate; parent_rate = clk_get_rate(clk->parent); /* i.MX27 TO2: - * clk->id == 0: arm clock source path 1 which is from 2*MPLL/DIV_2 - * clk->id == 1: arm clock source path 2 which is from 2*MPLL/DIV_3 + * clk->id == 0: arm clock source path 1 which is from 2 * MPLL / 2 + * clk->id == 1: arm clock source path 2 which is from 2 * MPLL / 3 */ - if (mx27_revision() >= CHIP_REV_2_0 && clk->id == 1) return 2UL * parent_rate / 3UL; return parent_rate; } -static struct clk mpll_main_clk[] = { - { - /* For i.MX27 TO2, it is the MPLL path 1 of ARM core - * It provide the clock source whose rate is same as MPLL - */ - .name = "mpll_main", - .id = 0, - .parent = &mpll_clk, - .get_rate = _clk_mpll_main_get_rate - }, { - /* For i.MX27 TO2, it is the MPLL path 2 of ARM core - * It provide the clock source whose rate is same MPLL * 2/3 - */ - .name = "mpll_main", - .id = 1, - .parent = &mpll_clk, - .get_rate = _clk_mpll_main_get_rate - } -}; - -static unsigned long get_spll_clk(struct clk *clk) +static unsigned long get_rate_spll(struct clk *clk) { uint32_t reg; - unsigned long ref_clk; + unsigned long rate; - ref_clk = clk_get_rate(clk->parent); + rate = clk_get_rate(clk->parent); reg = __raw_readl(CCM_SPCTL0); @@ -548,987 +366,325 @@ static unsigned long get_spll_clk(struct clk *clk) if (mx27_revision() >= CHIP_REV_2_0) __raw_writel(reg, CCM_SPCTL0); - return mxc_decode_pll(reg, ref_clk); + return mxc_decode_pll(reg, rate); } -static struct clk spll_clk = { - .name = "spll", - .parent = &ckih_clk, - .get_rate = get_spll_clk, - .enable = _clk_spll_enable, - .disable = _clk_spll_disable, -}; - -static unsigned long get_cpu_clk(struct clk *clk) +static unsigned long get_rate_cpu(struct clk *clk) { u32 div; unsigned long rate; if (mx27_revision() >= CHIP_REV_2_0) - div = (CSCR() & CCM_CSCR_ARM_MASK) >> CCM_CSCR_ARM_OFFSET; + div = (__raw_readl(CCM_CSCR) >> 12) & 0x3; else - div = (CSCR() & CCM_CSCR_PRESC_MASK) >> CCM_CSCR_PRESC_OFFSET; + div = (__raw_readl(CCM_CSCR) >> 13) & 0x7; rate = clk_get_rate(clk->parent); return rate / (div + 1); } -static struct clk cpu_clk = { - .name = "cpu_clk", - .parent = &mpll_main_clk[1], - .set_parent = _clk_cpu_set_parent, - .round_rate = _clk_cpu_round_rate, - .get_rate = get_cpu_clk, - .set_rate = _clk_cpu_set_rate, -}; - -static unsigned long get_ahb_clk(struct clk *clk) +static unsigned long get_rate_ahb(struct clk *clk) { - unsigned long rate; - unsigned long bclk_pdf; + unsigned long rate, bclk_pdf; if (mx27_revision() >= CHIP_REV_2_0) - bclk_pdf = (CSCR() & CCM_CSCR_AHB_MASK) - >> CCM_CSCR_AHB_OFFSET; + bclk_pdf = (__raw_readl(CCM_CSCR) >> 8) & 0x3; else - bclk_pdf = (CSCR() & CCM_CSCR_BCLK_MASK) - >> CCM_CSCR_BCLK_OFFSET; + bclk_pdf = (__raw_readl(CCM_CSCR) >> 9) & 0xf; rate = clk_get_rate(clk->parent); return rate / (bclk_pdf + 1); } -static struct clk ahb_clk = { - .name = "ahb_clk", - .parent = &mpll_main_clk[1], - .get_rate = get_ahb_clk, -}; - -static unsigned long get_ipg_clk(struct clk *clk) +static unsigned long get_rate_ipg(struct clk *clk) { - unsigned long rate; - unsigned long ipg_pdf; + unsigned long rate, ipg_pdf; if (mx27_revision() >= CHIP_REV_2_0) return clk_get_rate(clk->parent); else - ipg_pdf = (CSCR() & CCM_CSCR_IPDIV) >> CCM_CSCR_IPDIV_OFFSET; + ipg_pdf = (__raw_readl(CCM_CSCR) >> 8) & 1; rate = clk_get_rate(clk->parent); return rate / (ipg_pdf + 1); } -static struct clk ipg_clk = { - .name = "ipg_clk", - .parent = &ahb_clk, - .get_rate = get_ipg_clk, -}; - -static unsigned long _clk_perclkx_recalc(struct clk *clk) +static unsigned long get_rate_per(struct clk *clk) { - unsigned long perclk_pdf; - unsigned long parent_rate; + unsigned long perclk_pdf, parent_rate; parent_rate = clk_get_rate(clk->parent); if (clk->id < 0 || clk->id > 3) return 0; - perclk_pdf = (PCDR1() >> (clk->id << 3)) & CCM_PCDR1_PERDIV1_MASK; + perclk_pdf = (__raw_readl(CCM_PCDR1) >> (clk->id << 3)) & 0x3f; return parent_rate / (perclk_pdf + 1); } -static struct clk per_clk[] = { - { - .name = "per_clk", - .id = 0, - .parent = &mpll_main_clk[1], - .get_rate = _clk_perclkx_recalc, - .enable = _clk_enable, - .enable_reg = CCM_PCCR1, - .enable_shift = CCM_PCCR1_PERCLK1_OFFSET, - .disable = _clk_disable, - }, { - .name = "per_clk", - .id = 1, - .parent = &mpll_main_clk[1], - .get_rate = _clk_perclkx_recalc, - .enable = _clk_enable, - .enable_reg = CCM_PCCR1, - .enable_shift = CCM_PCCR1_PERCLK2_OFFSET, - .disable = _clk_disable, - }, { - .name = "per_clk", - .id = 2, - .parent = &mpll_main_clk[1], - .round_rate = _clk_perclkx_round_rate, - .set_rate = _clk_perclkx_set_rate, - .get_rate = _clk_perclkx_recalc, - .enable = _clk_enable, - .enable_reg = CCM_PCCR1, - .enable_shift = CCM_PCCR1_PERCLK3_OFFSET, - .disable = _clk_disable, - }, { - .name = "per_clk", - .id = 3, - .parent = &mpll_main_clk[1], - .round_rate = _clk_perclkx_round_rate, - .set_rate = _clk_perclkx_set_rate, - .get_rate = _clk_perclkx_recalc, - .enable = _clk_enable, - .enable_reg = CCM_PCCR1, - .enable_shift = CCM_PCCR1_PERCLK4_OFFSET, - .disable = _clk_disable, - }, -}; - -struct clk uart1_clk[] = { - { - .name = "uart", - .id = 0, - .parent = &per_clk[0], - .secondary = &uart1_clk[1], - }, { - .name = "uart_ipg_clk", - .id = 0, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR1, - .enable_shift = CCM_PCCR1_UART1_OFFSET, - .disable = _clk_disable, - }, -}; - -struct clk uart2_clk[] = { - { - .name = "uart", - .id = 1, - .parent = &per_clk[0], - .secondary = &uart2_clk[1], - }, { - .name = "uart_ipg_clk", - .id = 1, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR1, - .enable_shift = CCM_PCCR1_UART2_OFFSET, - .disable = _clk_disable, - }, -}; - -struct clk uart3_clk[] = { - { - .name = "uart", - .id = 2, - .parent = &per_clk[0], - .secondary = &uart3_clk[1], - }, { - .name = "uart_ipg_clk", - .id = 2, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR1, - .enable_shift = CCM_PCCR1_UART3_OFFSET, - .disable = _clk_disable, - }, -}; - -struct clk uart4_clk[] = { - { - .name = "uart", - .id = 3, - .parent = &per_clk[0], - .secondary = &uart4_clk[1], - }, { - .name = "uart_ipg_clk", - .id = 3, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR1, - .enable_shift = CCM_PCCR1_UART4_OFFSET, - .disable = _clk_disable, - }, -}; - -struct clk uart5_clk[] = { - { - .name = "uart", - .id = 4, - .parent = &per_clk[0], - .secondary = &uart5_clk[1], - }, { - .name = "uart_ipg_clk", - .id = 4, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR1, - .enable_shift = CCM_PCCR1_UART5_OFFSET, - .disable = _clk_disable, - }, -}; - -struct clk uart6_clk[] = { - { - .name = "uart", - .id = 5, - .parent = &per_clk[0], - .secondary = &uart6_clk[1], - }, { - .name = "uart_ipg_clk", - .id = 5, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR1, - .enable_shift = CCM_PCCR1_UART6_OFFSET, - .disable = _clk_disable, - }, -}; - -static struct clk gpt1_clk[] = { - { - .name = "gpt_clk", - .id = 0, - .parent = &per_clk[0], - .secondary = &gpt1_clk[1], - }, { - .name = "gpt_ipg_clk", - .id = 0, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR0, - .enable_shift = CCM_PCCR0_GPT1_OFFSET, - .disable = _clk_disable, - }, -}; - -static struct clk gpt2_clk[] = { - { - .name = "gpt_clk", - .id = 1, - .parent = &per_clk[0], - .secondary = &gpt2_clk[1], - }, { - .name = "gpt_ipg_clk", - .id = 1, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR0, - .enable_shift = CCM_PCCR0_GPT2_OFFSET, - .disable = _clk_disable, - }, -}; - -static struct clk gpt3_clk[] = { - { - .name = "gpt_clk", - .id = 2, - .parent = &per_clk[0], - .secondary = &gpt3_clk[1], - }, { - .name = "gpt_ipg_clk", - .id = 2, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR0, - .enable_shift = CCM_PCCR0_GPT3_OFFSET, - .disable = _clk_disable, - }, -}; - -static struct clk gpt4_clk[] = { - { - .name = "gpt_clk", - .id = 3, - .parent = &per_clk[0], - .secondary = &gpt4_clk[1], - }, { - .name = "gpt_ipg_clk", - .id = 3, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR0, - .enable_shift = CCM_PCCR0_GPT4_OFFSET, - .disable = _clk_disable, - }, -}; - -static struct clk gpt5_clk[] = { - { - .name = "gpt_clk", - .id = 4, - .parent = &per_clk[0], - .secondary = &gpt5_clk[1], - }, { - .name = "gpt_ipg_clk", - .id = 4, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR0, - .enable_shift = CCM_PCCR0_GPT5_OFFSET, - .disable = _clk_disable, - }, +/* + * the high frequency external clock reference + * Default case is 26MHz. Could be changed at runtime + * with a call to change_external_high_reference() + */ +static struct clk ckih_clk = { + .get_rate = get_rate_high_reference, }; -static struct clk gpt6_clk[] = { - { - .name = "gpt_clk", - .id = 5, - .parent = &per_clk[0], - .secondary = &gpt6_clk[1], - }, { - .name = "gpt_ipg_clk", - .id = 5, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR0, - .enable_shift = CCM_PCCR0_GPT6_OFFSET, - .disable = _clk_disable, - }, +static struct clk mpll_clk = { + .parent = &ckih_clk, + .get_rate = get_rate_mpll, }; -static struct clk pwm_clk[] = { - { - .name = "pwm_clk", - .parent = &per_clk[0], - .secondary = &pwm_clk[1], - }, { - .name = "pwm_clk", - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR0, - .enable_shift = CCM_PCCR0_PWM_OFFSET, - .disable = _clk_disable, - }, +/* For i.MX27 TO2, it is the MPLL path 1 of ARM core + * It provides the clock source whose rate is same as MPLL + */ +static struct clk mpll_main1_clk = { + .id = 0, + .parent = &mpll_clk, + .get_rate = get_rate_mpll_main, }; -static struct clk sdhc1_clk[] = { - { - .name = "sdhc_clk", - .id = 0, - .parent = &per_clk[1], - .secondary = &sdhc1_clk[1], - }, { - .name = "sdhc_ipg_clk", - .id = 0, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR0, - .enable_shift = CCM_PCCR0_SDHC1_OFFSET, - .disable = _clk_disable, - }, +/* For i.MX27 TO2, it is the MPLL path 2 of ARM core + * It provides the clock source whose rate is same MPLL * 2 / 3 + */ +static struct clk mpll_main2_clk = { + .id = 1, + .parent = &mpll_clk, + .get_rate = get_rate_mpll_main, }; -static struct clk sdhc2_clk[] = { - { - .name = "sdhc_clk", - .id = 1, - .parent = &per_clk[1], - .secondary = &sdhc2_clk[1], - }, { - .name = "sdhc_ipg_clk", - .id = 1, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR0, - .enable_shift = CCM_PCCR0_SDHC2_OFFSET, - .disable = _clk_disable, - }, +static struct clk ahb_clk = { + .parent = &mpll_main2_clk, + .get_rate = get_rate_ahb, }; -static struct clk sdhc3_clk[] = { - { - .name = "sdhc_clk", - .id = 2, - .parent = &per_clk[1], - .secondary = &sdhc3_clk[1], - }, { - .name = "sdhc_ipg_clk", - .id = 2, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR0, - .enable_shift = CCM_PCCR0_SDHC3_OFFSET, - .disable = _clk_disable, - }, +static struct clk ipg_clk = { + .parent = &ahb_clk, + .get_rate = get_rate_ipg, }; -static struct clk cspi1_clk[] = { - { - .name = "cspi_clk", - .id = 0, - .parent = &per_clk[1], - .secondary = &cspi1_clk[1], - }, { - .name = "cspi_ipg_clk", - .id = 0, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR0, - .enable_shift = CCM_PCCR0_CSPI1_OFFSET, - .disable = _clk_disable, - }, +static struct clk cpu_clk = { + .parent = &mpll_main2_clk, + .set_parent = clk_cpu_set_parent, + .round_rate = round_rate_cpu, + .get_rate = get_rate_cpu, + .set_rate = set_rate_cpu, }; -static struct clk cspi2_clk[] = { - { - .name = "cspi_clk", - .id = 1, - .parent = &per_clk[1], - .secondary = &cspi2_clk[1], - }, { - .name = "cspi_ipg_clk", - .id = 1, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR0, - .enable_shift = CCM_PCCR0_CSPI2_OFFSET, - .disable = _clk_disable, - }, +static struct clk spll_clk = { + .parent = &ckih_clk, + .get_rate = get_rate_spll, + .enable = clk_spll_enable, + .disable = clk_spll_disable, }; -static struct clk cspi3_clk[] = { - { - .name = "cspi_clk", - .id = 2, - .parent = &per_clk[1], - .secondary = &cspi3_clk[1], - }, { - .name = "cspi_ipg_clk", - .id = 2, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR0, - .enable_shift = CCM_PCCR0_CSPI3_OFFSET, - .disable = _clk_disable, - }, +/* + * the low frequency external clock reference + * Default case is 32.768kHz. + */ +static struct clk ckil_clk = { + .get_rate = get_rate_low_reference, }; -static struct clk lcdc_clk[] = { - { - .name = "lcdc_clk", - .parent = &per_clk[2], - .secondary = &lcdc_clk[1], - .round_rate = _clk_parent_round_rate, - .set_rate = _clk_parent_set_rate, - }, { - .name = "lcdc_ipg_clk", - .parent = &ipg_clk, - .secondary = &lcdc_clk[2], - .enable = _clk_enable, - .enable_reg = CCM_PCCR0, - .enable_shift = CCM_PCCR0_LCDC_OFFSET, - .disable = _clk_disable, - }, { - .name = "lcdc_ahb_clk", - .parent = &ahb_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR1, - .enable_shift = CCM_PCCR1_HCLK_LCDC_OFFSET, - .disable = _clk_disable, - }, +/* Output of frequency pre multiplier */ +static struct clk fpm_clk = { + .parent = &ckil_clk, + .get_rate = get_rate_fpm, }; -static struct clk csi_clk[] = { - { - .name = "csi_perclk", - .parent = &per_clk[3], - .secondary = &csi_clk[1], - .round_rate = _clk_parent_round_rate, - .set_rate = _clk_parent_set_rate, - }, { - .name = "csi_ahb_clk", - .parent = &ahb_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR1, - .enable_shift = CCM_PCCR1_HCLK_CSI_OFFSET, - .disable = _clk_disable, - }, -}; +#define PCCR0 CCM_PCCR0 +#define PCCR1 CCM_PCCR1 -static struct clk usb_clk[] = { - { - .name = "usb_clk", - .parent = &spll_clk, - .get_rate = _clk_usb_recalc, - .enable = _clk_enable, - .enable_reg = CCM_PCCR1, - .enable_shift = CCM_PCCR1_USBOTG_OFFSET, - .disable = _clk_disable, - }, { - .name = "usb_ahb_clk", - .parent = &ahb_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR1, - .enable_shift = CCM_PCCR1_HCLK_USBOTG_OFFSET, - .disable = _clk_disable, +#define DEFINE_CLOCK(name, i, er, es, gr, s, p) \ + static struct clk name = { \ + .id = i, \ + .enable_reg = er, \ + .enable_shift = es, \ + .get_rate = gr, \ + .enable = clk_pccr_enable, \ + .disable = clk_pccr_disable, \ + .secondary = s, \ + .parent = p, \ } -}; - -static struct clk ssi1_clk[] = { - { - .name = "ssi_clk", - .id = 0, - .parent = &mpll_main_clk[1], - .secondary = &ssi1_clk[1], - .get_rate = _clk_ssi1_recalc, - .enable = _clk_enable, - .enable_reg = CCM_PCCR1, - .enable_shift = CCM_PCCR1_SSI1_BAUD_OFFSET, - .disable = _clk_disable, - }, { - .name = "ssi_ipg_clk", - .id = 0, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR0, - .enable_shift = CCM_PCCR0_SSI1_IPG_OFFSET, - .disable = _clk_disable, - }, -}; - -static struct clk ssi2_clk[] = { - { - .name = "ssi_clk", - .id = 1, - .parent = &mpll_main_clk[1], - .secondary = &ssi2_clk[1], - .get_rate = _clk_ssi2_recalc, - .enable = _clk_enable, - .enable_reg = CCM_PCCR1, - .enable_shift = CCM_PCCR1_SSI2_BAUD_OFFSET, - .disable = _clk_disable, - }, { - .name = "ssi_ipg_clk", - .id = 1, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR0, - .enable_shift = CCM_PCCR0_SSI2_IPG_OFFSET, - .disable = _clk_disable, - }, -}; - -static struct clk nfc_clk = { - .name = "nfc", - .parent = &cpu_clk, - .get_rate = _clk_nfc_recalc, - .enable = _clk_enable, - .enable_reg = CCM_PCCR1, - .enable_shift = CCM_PCCR1_NFC_BAUD_OFFSET, - .disable = _clk_disable, -}; - -static struct clk vpu_clk = { - .name = "vpu_clk", - .parent = &mpll_main_clk[1], - .get_rate = _clk_vpu_recalc, - .enable = _clk_vpu_enable, - .disable = _clk_vpu_disable, -}; - -static struct clk dma_clk = { - .name = "dma", - .parent = &ahb_clk, - .enable = _clk_dma_enable, - .disable = _clk_dma_disable, -}; - -static struct clk rtic_clk = { - .name = "rtic_clk", - .parent = &ahb_clk, - .enable = _clk_rtic_enable, - .disable = _clk_rtic_disable, -}; -static struct clk brom_clk = { - .name = "brom_clk", - .parent = &ahb_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR1, - .enable_shift = CCM_PCCR1_HCLK_BROM_OFFSET, - .disable = _clk_disable, -}; - -static struct clk emma_clk = { - .name = "emma_clk", - .parent = &ahb_clk, - .enable = _clk_emma_enable, - .disable = _clk_emma_disable, -}; - -static struct clk slcdc_clk = { - .name = "slcdc_clk", - .parent = &ahb_clk, - .enable = _clk_slcdc_enable, - .disable = _clk_slcdc_disable, -}; - -static struct clk fec_clk = { - .name = "fec_clk", - .parent = &ahb_clk, - .enable = _clk_fec_enable, - .disable = _clk_fec_disable, -}; - -static struct clk emi_clk = { - .name = "emi_clk", - .parent = &ahb_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR1, - .enable_shift = CCM_PCCR1_HCLK_EMI_OFFSET, - .disable = _clk_disable, -}; - -static struct clk sahara2_clk = { - .name = "sahara_clk", - .parent = &ahb_clk, - .enable = _clk_sahara2_enable, - .disable = _clk_sahara2_disable, -}; - -static struct clk ata_clk = { - .name = "ata_clk", - .parent = &ahb_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR1, - .enable_shift = CCM_PCCR1_HCLK_ATA_OFFSET, - .disable = _clk_disable, -}; - -static struct clk mstick1_clk = { - .name = "mstick1_clk", - .parent = &ipg_clk, - .enable = _clk_mstick1_enable, - .disable = _clk_mstick1_disable, -}; - -static struct clk wdog_clk = { - .name = "wdog_clk", - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR1, - .enable_shift = CCM_PCCR1_WDT_OFFSET, - .disable = _clk_disable, -}; - -static struct clk gpio_clk = { - .name = "gpio_clk", - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR1, - .enable_shift = CCM_PCCR0_GPIO_OFFSET, - .disable = _clk_disable, -}; +#define DEFINE_CLOCK1(name, i, er, es, getsetround, s, p) \ + static struct clk name = { \ + .id = i, \ + .enable_reg = er, \ + .enable_shift = es, \ + .get_rate = get_rate_##getsetround, \ + .set_rate = set_rate_##getsetround, \ + .round_rate = round_rate_##getsetround, \ + .enable = clk_pccr_enable, \ + .disable = clk_pccr_disable, \ + .secondary = s, \ + .parent = p, \ + } -static struct clk i2c_clk[] = { - { - .name = "i2c_clk", - .id = 0, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR0, - .enable_shift = CCM_PCCR0_I2C1_OFFSET, - .disable = _clk_disable, - }, { - .name = "i2c_clk", - .id = 1, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR0, - .enable_shift = CCM_PCCR0_I2C2_OFFSET, - .disable = _clk_disable, +/* Forward declaration to keep the following list in order */ +static struct clk slcdc_clk1, sahara2_clk1, rtic_clk1, fec_clk1, emma_clk1, + dma_clk1, lcdc_clk2, vpu_clk1; + +/* All clocks we can gate through PCCRx in the order of PCCRx bits */ +DEFINE_CLOCK(ssi2_clk1, 1, PCCR0, 0, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(ssi1_clk1, 0, PCCR0, 1, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(slcdc_clk, 0, PCCR0, 2, NULL, &slcdc_clk1, &ahb_clk); +DEFINE_CLOCK(sdhc3_clk1, 0, PCCR0, 3, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(sdhc2_clk1, 0, PCCR0, 4, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(sdhc1_clk1, 0, PCCR0, 5, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(scc_clk, 0, PCCR0, 6, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(sahara2_clk, 0, PCCR0, 7, NULL, &sahara2_clk1, &ahb_clk); +DEFINE_CLOCK(rtic_clk, 0, PCCR0, 8, NULL, &rtic_clk1, &ahb_clk); +DEFINE_CLOCK(rtc_clk, 0, PCCR0, 9, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(pwm_clk1, 0, PCCR0, 11, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(owire_clk, 0, PCCR0, 12, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(mstick_clk1, 0, PCCR0, 13, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(lcdc_clk1, 0, PCCR0, 14, NULL, &lcdc_clk2, &ipg_clk); +DEFINE_CLOCK(kpp_clk, 0, PCCR0, 15, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(iim_clk, 0, PCCR0, 16, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(i2c2_clk, 1, PCCR0, 17, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(i2c1_clk, 0, PCCR0, 18, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(gpt6_clk1, 0, PCCR0, 29, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(gpt5_clk1, 0, PCCR0, 20, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(gpt4_clk1, 0, PCCR0, 21, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(gpt3_clk1, 0, PCCR0, 22, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(gpt2_clk1, 0, PCCR0, 23, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(gpt1_clk1, 0, PCCR0, 24, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(gpio_clk, 0, PCCR0, 25, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(fec_clk, 0, PCCR0, 26, NULL, &fec_clk1, &ahb_clk); +DEFINE_CLOCK(emma_clk, 0, PCCR0, 27, NULL, &emma_clk1, &ahb_clk); +DEFINE_CLOCK(dma_clk, 0, PCCR0, 28, NULL, &dma_clk1, &ahb_clk); +DEFINE_CLOCK(cspi13_clk1, 0, PCCR0, 29, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(cspi2_clk1, 0, PCCR0, 30, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(cspi1_clk1, 0, PCCR0, 31, NULL, NULL, &ipg_clk); + +DEFINE_CLOCK(mstick_clk, 0, PCCR1, 2, NULL, &mstick_clk1, &ipg_clk); +DEFINE_CLOCK(nfc_clk, 0, PCCR1, 3, get_rate_nfc, NULL, &cpu_clk); +DEFINE_CLOCK(ssi2_clk, 1, PCCR1, 4, get_rate_ssi2, &ssi2_clk1, &mpll_main2_clk); +DEFINE_CLOCK(ssi1_clk, 0, PCCR1, 5, get_rate_ssi1, &ssi1_clk1, &mpll_main2_clk); +DEFINE_CLOCK(vpu_clk, 0, PCCR1, 6, get_rate_vpu, &vpu_clk1, &mpll_main2_clk); +DEFINE_CLOCK1(per4_clk, 3, PCCR1, 7, per, NULL, &mpll_main2_clk); +DEFINE_CLOCK1(per3_clk, 2, PCCR1, 8, per, NULL, &mpll_main2_clk); +DEFINE_CLOCK1(per2_clk, 1, PCCR1, 9, per, NULL, &mpll_main2_clk); +DEFINE_CLOCK1(per1_clk, 0, PCCR1, 10, per, NULL, &mpll_main2_clk); +DEFINE_CLOCK(usb_clk1, 0, PCCR1, 11, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(slcdc_clk1, 0, PCCR1, 12, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(sahara2_clk1, 0, PCCR1, 13, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(rtic_clk1, 0, PCCR1, 14, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(lcdc_clk2, 0, PCCR1, 15, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(vpu_clk1, 0, PCCR1, 16, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(fec_clk1, 0, PCCR1, 17, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(emma_clk1, 0, PCCR1, 18, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(emi_clk, 0, PCCR1, 19, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(dma_clk1, 0, PCCR1, 20, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(csi_clk1, 0, PCCR1, 21, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(brom_clk, 0, PCCR1, 22, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(ata_clk, 0, PCCR1, 23, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(wdog_clk, 0, PCCR1, 24, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(usb_clk, 0, PCCR1, 25, get_rate_usb, &usb_clk1, &spll_clk); +DEFINE_CLOCK(uart6_clk1, 0, PCCR1, 26, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(uart5_clk1, 0, PCCR1, 27, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(uart4_clk1, 0, PCCR1, 28, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(uart3_clk1, 0, PCCR1, 29, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(uart2_clk1, 0, PCCR1, 30, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(uart1_clk1, 0, PCCR1, 31, NULL, NULL, &ipg_clk); + +/* Clocks we cannot directly gate, but drivers need their rates */ +DEFINE_CLOCK(cspi1_clk, 0, 0, 0, NULL, &cspi1_clk1, &per2_clk); +DEFINE_CLOCK(cspi2_clk, 1, 0, 0, NULL, &cspi2_clk1, &per2_clk); +DEFINE_CLOCK(cspi3_clk, 2, 0, 0, NULL, &cspi13_clk1, &per2_clk); +DEFINE_CLOCK(sdhc1_clk, 0, 0, 0, NULL, &sdhc1_clk1, &per2_clk); +DEFINE_CLOCK(sdhc2_clk, 1, 0, 0, NULL, &sdhc2_clk1, &per2_clk); +DEFINE_CLOCK(sdhc3_clk, 2, 0, 0, NULL, &sdhc3_clk1, &per2_clk); +DEFINE_CLOCK(pwm_clk, 0, 0, 0, NULL, &pwm_clk1, &per1_clk); +DEFINE_CLOCK(gpt1_clk, 0, 0, 0, NULL, &gpt1_clk1, &per1_clk); +DEFINE_CLOCK(gpt2_clk, 1, 0, 0, NULL, &gpt2_clk1, &per1_clk); +DEFINE_CLOCK(gpt3_clk, 2, 0, 0, NULL, &gpt3_clk1, &per1_clk); +DEFINE_CLOCK(gpt4_clk, 3, 0, 0, NULL, &gpt4_clk1, &per1_clk); +DEFINE_CLOCK(gpt5_clk, 4, 0, 0, NULL, &gpt5_clk1, &per1_clk); +DEFINE_CLOCK(gpt6_clk, 5, 0, 0, NULL, &gpt6_clk1, &per1_clk); +DEFINE_CLOCK(uart1_clk, 0, 0, 0, NULL, &uart1_clk1, &per1_clk); +DEFINE_CLOCK(uart2_clk, 1, 0, 0, NULL, &uart2_clk1, &per1_clk); +DEFINE_CLOCK(uart3_clk, 2, 0, 0, NULL, &uart3_clk1, &per1_clk); +DEFINE_CLOCK(uart4_clk, 3, 0, 0, NULL, &uart4_clk1, &per1_clk); +DEFINE_CLOCK(uart5_clk, 4, 0, 0, NULL, &uart5_clk1, &per1_clk); +DEFINE_CLOCK(uart6_clk, 5, 0, 0, NULL, &uart6_clk1, &per1_clk); +DEFINE_CLOCK1(lcdc_clk, 0, 0, 0, parent, &lcdc_clk1, &per3_clk); +DEFINE_CLOCK1(csi_clk, 0, 0, 0, parent, &csi_clk1, &per4_clk); + +#define _REGISTER_CLOCK(d, n, c) \ + { \ + .dev_id = d, \ + .con_id = n, \ + .clk = &c, \ }, -}; -static struct clk iim_clk = { - .name = "iim_clk", - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR0, - .enable_shift = CCM_PCCR0_IIM_OFFSET, - .disable = _clk_disable, -}; - -static struct clk kpp_clk = { - .name = "kpp_clk", - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR0, - .enable_shift = CCM_PCCR0_KPP_OFFSET, - .disable = _clk_disable, -}; - -static struct clk owire_clk = { - .name = "owire", - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR0, - .enable_shift = CCM_PCCR0_OWIRE_OFFSET, - .disable = _clk_disable, -}; - -static struct clk rtc_clk = { - .name = "rtc_clk", - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR0, - .enable_shift = CCM_PCCR0_RTC_OFFSET, - .disable = _clk_disable, -}; - -static struct clk scc_clk = { - .name = "scc_clk", - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = CCM_PCCR0, - .enable_shift = CCM_PCCR0_SCC_OFFSET, - .disable = _clk_disable, -}; - -static unsigned long _clk_clko_round_rate(struct clk *clk, unsigned long rate) -{ - u32 div; - unsigned long parent_rate; - - parent_rate = clk_get_rate(clk->parent); - div = parent_rate / rate; - if (parent_rate % rate) - div++; - - if (div > 8) - div = 8; - - return parent_rate / div; -} - -static int _clk_clko_set_rate(struct clk *clk, unsigned long rate) -{ - u32 reg; - u32 div; - unsigned long parent_rate; - - parent_rate = clk_get_rate(clk->parent); - - div = parent_rate / rate; - - if (div > 8 || div < 1 || ((parent_rate / div) != rate)) - return -EINVAL; - div--; - - reg = __raw_readl(CCM_PCDR0) & ~CCM_PCDR0_CLKODIV_MASK; - reg |= div << CCM_PCDR0_CLKODIV_OFFSET; - __raw_writel(reg, CCM_PCDR0); - - return 0; -} - -static unsigned long _clk_clko_recalc(struct clk *clk) -{ - u32 div; - unsigned long parent_rate; - - parent_rate = clk_get_rate(clk->parent); - - div = __raw_readl(CCM_PCDR0) & CCM_PCDR0_CLKODIV_MASK >> - CCM_PCDR0_CLKODIV_OFFSET; - div++; - - return parent_rate / div; -} - -static int _clk_clko_set_parent(struct clk *clk, struct clk *parent) -{ - u32 reg; - - reg = __raw_readl(CCM_CCSR) & ~CCM_CCSR_CLKOSEL_MASK; - - if (parent == &ckil_clk) - reg |= 0 << CCM_CCSR_CLKOSEL_OFFSET; - else if (parent == &ckih_clk) - reg |= 2 << CCM_CCSR_CLKOSEL_OFFSET; - else if (parent == mpll_clk.parent) - reg |= 3 << CCM_CCSR_CLKOSEL_OFFSET; - else if (parent == spll_clk.parent) - reg |= 4 << CCM_CCSR_CLKOSEL_OFFSET; - else if (parent == &mpll_clk) - reg |= 5 << CCM_CCSR_CLKOSEL_OFFSET; - else if (parent == &spll_clk) - reg |= 6 << CCM_CCSR_CLKOSEL_OFFSET; - else if (parent == &cpu_clk) - reg |= 7 << CCM_CCSR_CLKOSEL_OFFSET; - else if (parent == &ahb_clk) - reg |= 8 << CCM_CCSR_CLKOSEL_OFFSET; - else if (parent == &ipg_clk) - reg |= 9 << CCM_CCSR_CLKOSEL_OFFSET; - else if (parent == &per_clk[0]) - reg |= 0xA << CCM_CCSR_CLKOSEL_OFFSET; - else if (parent == &per_clk[1]) - reg |= 0xB << CCM_CCSR_CLKOSEL_OFFSET; - else if (parent == &per_clk[2]) - reg |= 0xC << CCM_CCSR_CLKOSEL_OFFSET; - else if (parent == &per_clk[3]) - reg |= 0xD << CCM_CCSR_CLKOSEL_OFFSET; - else if (parent == &ssi1_clk[0]) - reg |= 0xE << CCM_CCSR_CLKOSEL_OFFSET; - else if (parent == &ssi2_clk[0]) - reg |= 0xF << CCM_CCSR_CLKOSEL_OFFSET; - else if (parent == &nfc_clk) - reg |= 0x10 << CCM_CCSR_CLKOSEL_OFFSET; - else if (parent == &mstick1_clk) - reg |= 0x11 << CCM_CCSR_CLKOSEL_OFFSET; - else if (parent == &vpu_clk) - reg |= 0x12 << CCM_CCSR_CLKOSEL_OFFSET; - else if (parent == &usb_clk[0]) - reg |= 0x15 << CCM_CCSR_CLKOSEL_OFFSET; - else - return -EINVAL; - - __raw_writel(reg, CCM_CCSR); - - return 0; -} - -static int _clk_clko_enable(struct clk *clk) -{ - u32 reg; - - reg = __raw_readl(CCM_PCDR0) | CCM_PCDR0_CLKO_EN; - __raw_writel(reg, CCM_PCDR0); - - return 0; -} - -static void _clk_clko_disable(struct clk *clk) -{ - u32 reg; - - reg = __raw_readl(CCM_PCDR0) & ~CCM_PCDR0_CLKO_EN; - __raw_writel(reg, CCM_PCDR0); -} - -static struct clk clko_clk = { - .name = "clko_clk", - .get_rate = _clk_clko_recalc, - .set_rate = _clk_clko_set_rate, - .round_rate = _clk_clko_round_rate, - .set_parent = _clk_clko_set_parent, - .enable = _clk_clko_enable, - .disable = _clk_clko_disable, -}; - -static struct clk *mxc_clks[] = { - &ckih_clk, - &ckil_clk, - &mpll_clk, - &mpll_main_clk[0], - &mpll_main_clk[1], - &spll_clk, - &cpu_clk, - &ahb_clk, - &ipg_clk, - &per_clk[0], - &per_clk[1], - &per_clk[2], - &per_clk[3], - &clko_clk, - &uart1_clk[0], - &uart1_clk[1], - &uart2_clk[0], - &uart2_clk[1], - &uart3_clk[0], - &uart3_clk[1], - &uart4_clk[0], - &uart4_clk[1], - &uart5_clk[0], - &uart5_clk[1], - &uart6_clk[0], - &uart6_clk[1], - &gpt1_clk[0], - &gpt1_clk[1], - &gpt2_clk[0], - &gpt2_clk[1], - &gpt3_clk[0], - &gpt3_clk[1], - &gpt4_clk[0], - &gpt4_clk[1], - &gpt5_clk[0], - &gpt5_clk[1], - &gpt6_clk[0], - &gpt6_clk[1], - &pwm_clk[0], - &pwm_clk[1], - &sdhc1_clk[0], - &sdhc1_clk[1], - &sdhc2_clk[0], - &sdhc2_clk[1], - &sdhc3_clk[0], - &sdhc3_clk[1], - &cspi1_clk[0], - &cspi1_clk[1], - &cspi2_clk[0], - &cspi2_clk[1], - &cspi3_clk[0], - &cspi3_clk[1], - &lcdc_clk[0], - &lcdc_clk[1], - &lcdc_clk[2], - &csi_clk[0], - &csi_clk[1], - &usb_clk[0], - &usb_clk[1], - &ssi1_clk[0], - &ssi1_clk[1], - &ssi2_clk[0], - &ssi2_clk[1], - &nfc_clk, - &vpu_clk, - &dma_clk, - &rtic_clk, - &brom_clk, - &emma_clk, - &slcdc_clk, - &fec_clk, - &emi_clk, - &sahara2_clk, - &ata_clk, - &mstick1_clk, - &wdog_clk, - &gpio_clk, - &i2c_clk[0], - &i2c_clk[1], - &iim_clk, - &kpp_clk, - &owire_clk, - &rtc_clk, - &scc_clk, -}; - -void __init change_external_low_reference(unsigned long new_ref) -{ - external_low_reference = new_ref; -} - -unsigned long __init clk_early_get_timer_rate(void) -{ - return clk_get_rate(&per_clk[0]); -} - -static void __init probe_mxc_clocks(void) -{ - int i; +static struct clk_lookup lookups[] __initdata = { + _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk) + _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk) + _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk) + _REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk) + _REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk) + _REGISTER_CLOCK("imx-uart.5", NULL, uart6_clk) + _REGISTER_CLOCK(NULL, "gpt1", gpt1_clk) + _REGISTER_CLOCK(NULL, "gpt2", gpt2_clk) + _REGISTER_CLOCK(NULL, "gpt3", gpt3_clk) + _REGISTER_CLOCK(NULL, "gpt4", gpt4_clk) + _REGISTER_CLOCK(NULL, "gpt5", gpt5_clk) + _REGISTER_CLOCK(NULL, "gpt6", gpt6_clk) + _REGISTER_CLOCK("mxc_pwm.0", NULL, pwm_clk) + _REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk) + _REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk) + _REGISTER_CLOCK("mxc-mmc.2", NULL, sdhc3_clk) + _REGISTER_CLOCK(NULL, "cspi1", cspi1_clk) + _REGISTER_CLOCK(NULL, "cspi2", cspi2_clk) + _REGISTER_CLOCK(NULL, "cspi3", cspi3_clk) + _REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk) + _REGISTER_CLOCK(NULL, "csi", csi_clk) + _REGISTER_CLOCK(NULL, "usb", usb_clk) + _REGISTER_CLOCK(NULL, "ssi1", ssi1_clk) + _REGISTER_CLOCK(NULL, "ssi2", ssi2_clk) + _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk) + _REGISTER_CLOCK(NULL, "vpu", vpu_clk) + _REGISTER_CLOCK(NULL, "dma", dma_clk) + _REGISTER_CLOCK(NULL, "rtic", rtic_clk) + _REGISTER_CLOCK(NULL, "brom", brom_clk) + _REGISTER_CLOCK(NULL, "emma", emma_clk) + _REGISTER_CLOCK(NULL, "slcdc", slcdc_clk) + _REGISTER_CLOCK("fec.0", NULL, fec_clk) + _REGISTER_CLOCK(NULL, "emi", emi_clk) + _REGISTER_CLOCK(NULL, "sahara2", sahara2_clk) + _REGISTER_CLOCK(NULL, "ata", ata_clk) + _REGISTER_CLOCK(NULL, "mstick", mstick_clk) + _REGISTER_CLOCK(NULL, "wdog", wdog_clk) + _REGISTER_CLOCK(NULL, "gpio", gpio_clk) + _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk) + _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk) + _REGISTER_CLOCK(NULL, "iim", iim_clk) + _REGISTER_CLOCK(NULL, "kpp", kpp_clk) + _REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk) + _REGISTER_CLOCK(NULL, "rtc", rtc_clk) + _REGISTER_CLOCK(NULL, "scc", scc_clk) +}; + +/* Adjust the clock path for TO2 and later */ +static void __init to2_adjust_clocks(void) +{ + unsigned long cscr = __raw_readl(CCM_CSCR); if (mx27_revision() >= CHIP_REV_2_0) { - if (CSCR() & 0x8000) - cpu_clk.parent = &mpll_main_clk[0]; + if (cscr & CCM_CSCR_ARM_SRC) + cpu_clk.parent = &mpll_main1_clk; - if (!(CSCR() & 0x00800000)) - ssi2_clk[0].parent = &spll_clk; + if (!(cscr & CCM_CSCR_SSI2)) + ssi1_clk.parent = &spll_clk; - if (!(CSCR() & 0x00400000)) - ssi1_clk[0].parent = &spll_clk; + if (!(cscr & CCM_CSCR_SSI1)) + ssi1_clk.parent = &spll_clk; - if (!(CSCR() & 0x00200000)) + if (!(cscr & CCM_CSCR_VPU)) vpu_clk.parent = &spll_clk; } else { cpu_clk.parent = &mpll_clk; @@ -1537,11 +693,13 @@ static void __init probe_mxc_clocks(void) cpu_clk.set_rate = NULL; ahb_clk.parent = &mpll_clk; - for (i = 0; i < sizeof(per_clk) / sizeof(per_clk[0]); i++) - per_clk[i].parent = &mpll_clk; + per1_clk.parent = &mpll_clk; + per2_clk.parent = &mpll_clk; + per3_clk.parent = &mpll_clk; + per4_clk.parent = &mpll_clk; - ssi1_clk[0].parent = &mpll_clk; - ssi2_clk[0].parent = &mpll_clk; + ssi1_clk.parent = &mpll_clk; + ssi2_clk.parent = &mpll_clk; vpu_clk.parent = &mpll_clk; } @@ -1553,48 +711,45 @@ static void __init probe_mxc_clocks(void) */ int __init mx27_clocks_init(unsigned long fref) { - u32 cscr; - struct clk **clkp; + u32 cscr = __raw_readl(CCM_CSCR); + int i; external_high_reference = fref; - /* detect clock reference for both system PLL */ - cscr = CSCR(); + /* detect clock reference for both system PLLs */ if (cscr & CCM_CSCR_MCU) mpll_clk.parent = &ckih_clk; else - mpll_clk.parent = &ckil_clk; + mpll_clk.parent = &fpm_clk; if (cscr & CCM_CSCR_SP) spll_clk.parent = &ckih_clk; else - spll_clk.parent = &ckil_clk; + spll_clk.parent = &fpm_clk; - probe_mxc_clocks(); + to2_adjust_clocks(); - per_clk[0].enable(&per_clk[0]); - gpt1_clk[1].enable(&gpt1_clk[1]); + for (i = 0; i < ARRAY_SIZE(lookups); i++) + clkdev_add(&lookups[i]); - for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++) - clk_register(*clkp); + /* Turn off all clocks we do not need */ + __raw_writel(0, CCM_PCCR0); + __raw_writel((1 << 10) | (1 << 19), CCM_PCCR1); - /* Turn off all possible clocks */ - __raw_writel(CCM_PCCR0_GPT1_MASK, CCM_PCCR0); - __raw_writel(CCM_PCCR1_PERCLK1_MASK | CCM_PCCR1_HCLK_EMI_MASK, - CCM_PCCR1); spll_clk.disable(&spll_clk); - /* This will propagate to all children and init all the clock rates */ - - clk_enable(&emi_clk); + /* enable basic clocks */ + clk_enable(&per1_clk); clk_enable(&gpio_clk); + clk_enable(&emi_clk); clk_enable(&iim_clk); - clk_enable(&gpt1_clk[0]); + #ifdef CONFIG_DEBUG_LL_CONSOLE - clk_enable(&uart1_clk[0]); + clk_enable(&uart1_clk); #endif - mxc_timer_init(&gpt1_clk[0]); + mxc_timer_init(&gpt1_clk); return 0; } + diff --git a/arch/arm/mach-mx2/cpu_imx27.c b/arch/arm/mach-mx2/cpu_imx27.c index 239308fe665..d9e3bf9644c 100644 --- a/arch/arm/mach-mx2/cpu_imx27.c +++ b/arch/arm/mach-mx2/cpu_imx27.c @@ -26,11 +26,11 @@ #include -#include "crm_regs.h" - static int cpu_silicon_rev = -1; static int cpu_partnumber; +#define SYS_CHIP_ID 0x00 /* The offset of CHIP ID register */ + static void query_silicon_parameter(void) { u32 val; diff --git a/arch/arm/mach-mx2/crm_regs.h b/arch/arm/mach-mx2/crm_regs.h deleted file mode 100644 index 94644cd0a0f..00000000000 --- a/arch/arm/mach-mx2/crm_regs.h +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright 2008 Juergen Beisert, kernel@pengutronix.de - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ - -#ifndef __ARCH_ARM_MACH_MX2_CRM_REGS_H__ -#define __ARCH_ARM_MACH_MX2_CRM_REGS_H__ - -#include - -/* Register offsets */ -#define CCM_CSCR (IO_ADDRESS(CCM_BASE_ADDR) + 0x0) -#define CCM_MPCTL0 (IO_ADDRESS(CCM_BASE_ADDR) + 0x4) -#define CCM_MPCTL1 (IO_ADDRESS(CCM_BASE_ADDR) + 0x8) -#define CCM_SPCTL0 (IO_ADDRESS(CCM_BASE_ADDR) + 0xC) -#define CCM_SPCTL1 (IO_ADDRESS(CCM_BASE_ADDR) + 0x10) -#define CCM_OSC26MCTL (IO_ADDRESS(CCM_BASE_ADDR) + 0x14) -#define CCM_PCDR0 (IO_ADDRESS(CCM_BASE_ADDR) + 0x18) -#define CCM_PCDR1 (IO_ADDRESS(CCM_BASE_ADDR) + 0x1c) -#define CCM_PCCR0 (IO_ADDRESS(CCM_BASE_ADDR) + 0x20) -#define CCM_PCCR1 (IO_ADDRESS(CCM_BASE_ADDR) + 0x24) -#define CCM_CCSR (IO_ADDRESS(CCM_BASE_ADDR) + 0x28) -#define CCM_PMCTL (IO_ADDRESS(CCM_BASE_ADDR) + 0x2c) -#define CCM_PMCOUNT (IO_ADDRESS(CCM_BASE_ADDR) + 0x30) -#define CCM_WKGDCTL (IO_ADDRESS(CCM_BASE_ADDR) + 0x34) - -#define CCM_CSCR_USB_OFFSET 28 -#define CCM_CSCR_USB_MASK (0x7 << 28) -#define CCM_CSCR_SD_OFFSET 24 -#define CCM_CSCR_SD_MASK (0x3 << 24) -#define CCM_CSCR_SSI2 (1 << 23) -#define CCM_CSCR_SSI2_OFFSET 23 -#define CCM_CSCR_SSI1 (1 << 22) -#define CCM_CSCR_SSI1_OFFSET 22 -#define CCM_CSCR_VPU (1 << 21) -#define CCM_CSCR_VPU_OFFSET 21 -#define CCM_CSCR_MSHC (1 << 20) -#define CCM_CSCR_SPLLRES (1 << 19) -#define CCM_CSCR_MPLLRES (1 << 18) -#define CCM_CSCR_SP (1 << 17) -#define CCM_CSCR_MCU (1 << 16) -/* CCM_CSCR_ARM_xxx just be avaliable on i.MX27 TO2*/ -#define CCM_CSCR_ARM_SRC (1 << 15) -#define CCM_CSCR_ARM_OFFSET 12 -#define CCM_CSCR_ARM_MASK (0x3 << 12) -/* CCM_CSCR_ARM_xxx just be avaliable on i.MX27 TO2*/ -#define CCM_CSCR_PRESC_OFFSET 13 -#define CCM_CSCR_PRESC_MASK (0x7 << 13) -#define CCM_CSCR_BCLK_OFFSET 9 -#define CCM_CSCR_BCLK_MASK (0xf << 9) -#define CCM_CSCR_IPDIV_OFFSET 8 -#define CCM_CSCR_IPDIV (1 << 8) -/* CCM_CSCR_AHB_xxx just be avaliable on i.MX27 TO2*/ -#define CCM_CSCR_AHB_OFFSET 8 -#define CCM_CSCR_AHB_MASK (0x3 << 8) -/* CCM_CSCR_AHB_xxx just be avaliable on i.MX27 TO2*/ -#define CCM_CSCR_OSC26MDIV (1 << 4) -#define CCM_CSCR_OSC26M (1 << 3) -#define CCM_CSCR_FPM (1 << 2) -#define CCM_CSCR_SPEN (1 << 1) -#define CCM_CSCR_MPEN 1 - -#define CCM_MPCTL0_CPLM (1 << 31) -#define CCM_MPCTL0_PD_OFFSET 26 -#define CCM_MPCTL0_PD_MASK (0xf << 26) -#define CCM_MPCTL0_MFD_OFFSET 16 -#define CCM_MPCTL0_MFD_MASK (0x3ff << 16) -#define CCM_MPCTL0_MFI_OFFSET 10 -#define CCM_MPCTL0_MFI_MASK (0xf << 10) -#define CCM_MPCTL0_MFN_OFFSET 0 -#define CCM_MPCTL0_MFN_MASK 0x3ff - -#define CCM_MPCTL1_LF (1 << 15) -#define CCM_MPCTL1_BRMO (1 << 6) - -#define CCM_SPCTL0_CPLM (1 << 31) -#define CCM_SPCTL0_PD_OFFSET 26 -#define CCM_SPCTL0_PD_MASK (0xf << 26) -#define CCM_SPCTL0_MFD_OFFSET 16 -#define CCM_SPCTL0_MFD_MASK (0x3ff << 16) -#define CCM_SPCTL0_MFI_OFFSET 10 -#define CCM_SPCTL0_MFI_MASK (0xf << 10) -#define CCM_SPCTL0_MFN_OFFSET 0 -#define CCM_SPCTL0_MFN_MASK 0x3ff - -#define CCM_SPCTL1_LF (1 << 15) -#define CCM_SPCTL1_BRMO (1 << 6) - -#define CCM_OSC26MCTL_PEAK_OFFSET 16 -#define CCM_OSC26MCTL_PEAK_MASK (0x3 << 16) -#define CCM_OSC26MCTL_AGC_OFFSET 8 -#define CCM_OSC26MCTL_AGC_MASK (0x3f << 8) -#define CCM_OSC26MCTL_ANATEST_OFFSET 0 -#define CCM_OSC26MCTL_ANATEST_MASK 0x3f - -#define CCM_PCDR0_SSI2BAUDDIV_OFFSET 26 -#define CCM_PCDR0_SSI2BAUDDIV_MASK (0x3f << 26) -#define CCM_PCDR0_CLKO_EN 25 -#define CCM_PCDR0_CLKODIV_OFFSET 22 -#define CCM_PCDR0_CLKODIV_MASK (0x7 << 22) -#define CCM_PCDR0_SSI1BAUDDIV_OFFSET 16 -#define CCM_PCDR0_SSI1BAUDDIV_MASK (0x3f << 16) -/*The difinition for i.MX27 TO2*/ -#define CCM_PCDR0_VPUDIV2_OFFSET 10 -#define CCM_PCDR0_VPUDIV2_MASK (0x3f << 10) -#define CCM_PCDR0_NFCDIV2_OFFSET 6 -#define CCM_PCDR0_NFCDIV2_MASK (0xf << 6) -#define CCM_PCDR0_MSHCDIV2_MASK 0x3f -/*The difinition for i.MX27 TO2*/ -#define CCM_PCDR0_NFCDIV_OFFSET 12 -#define CCM_PCDR0_NFCDIV_MASK (0xf << 12) -#define CCM_PCDR0_VPUDIV_OFFSET 8 -#define CCM_PCDR0_VPUDIV_MASK (0xf << 8) -#define CCM_PCDR0_MSHCDIV_OFFSET 0 -#define CCM_PCDR0_MSHCDIV_MASK 0x1f - -#define CCM_PCDR1_PERDIV4_OFFSET 24 -#define CCM_PCDR1_PERDIV4_MASK (0x3f << 24) -#define CCM_PCDR1_PERDIV3_OFFSET 16 -#define CCM_PCDR1_PERDIV3_MASK (0x3f << 16) -#define CCM_PCDR1_PERDIV2_OFFSET 8 -#define CCM_PCDR1_PERDIV2_MASK (0x3f << 8) -#define CCM_PCDR1_PERDIV1_OFFSET 0 -#define CCM_PCDR1_PERDIV1_MASK 0x3f - -#define CCM_PCCR0_CSPI1_OFFSET 31 -#define CCM_PCCR0_CSPI1_MASK (1 << 31) -#define CCM_PCCR0_CSPI2_OFFSET 30 -#define CCM_PCCR0_CSPI2_MASK (1 << 30) -#define CCM_PCCR0_CSPI3_OFFSET 29 -#define CCM_PCCR0_CSPI3_MASK (1 << 29) -#define CCM_PCCR0_DMA_OFFSET 28 -#define CCM_PCCR0_DMA_MASK (1 << 28) -#define CCM_PCCR0_EMMA_OFFSET 27 -#define CCM_PCCR0_EMMA_MASK (1 << 27) -#define CCM_PCCR0_FEC_OFFSET 26 -#define CCM_PCCR0_FEC_MASK (1 << 26) -#define CCM_PCCR0_GPIO_OFFSET 25 -#define CCM_PCCR0_GPIO_MASK (1 << 25) -#define CCM_PCCR0_GPT1_OFFSET 24 -#define CCM_PCCR0_GPT1_MASK (1 << 24) -#define CCM_PCCR0_GPT2_OFFSET 23 -#define CCM_PCCR0_GPT2_MASK (1 << 23) -#define CCM_PCCR0_GPT3_OFFSET 22 -#define CCM_PCCR0_GPT3_MASK (1 << 22) -#define CCM_PCCR0_GPT4_OFFSET 21 -#define CCM_PCCR0_GPT4_MASK (1 << 21) -#define CCM_PCCR0_GPT5_OFFSET 20 -#define CCM_PCCR0_GPT5_MASK (1 << 20) -#define CCM_PCCR0_GPT6_OFFSET 19 -#define CCM_PCCR0_GPT6_MASK (1 << 19) -#define CCM_PCCR0_I2C1_OFFSET 18 -#define CCM_PCCR0_I2C1_MASK (1 << 18) -#define CCM_PCCR0_I2C2_OFFSET 17 -#define CCM_PCCR0_I2C2_MASK (1 << 17) -#define CCM_PCCR0_IIM_OFFSET 16 -#define CCM_PCCR0_IIM_MASK (1 << 16) -#define CCM_PCCR0_KPP_OFFSET 15 -#define CCM_PCCR0_KPP_MASK (1 << 15) -#define CCM_PCCR0_LCDC_OFFSET 14 -#define CCM_PCCR0_LCDC_MASK (1 << 14) -#define CCM_PCCR0_MSHC_OFFSET 13 -#define CCM_PCCR0_MSHC_MASK (1 << 13) -#define CCM_PCCR0_OWIRE_OFFSET 12 -#define CCM_PCCR0_OWIRE_MASK (1 << 12) -#define CCM_PCCR0_PWM_OFFSET 11 -#define CCM_PCCR0_PWM_MASK (1 << 11) -#define CCM_PCCR0_RTC_OFFSET 9 -#define CCM_PCCR0_RTC_MASK (1 << 9) -#define CCM_PCCR0_RTIC_OFFSET 8 -#define CCM_PCCR0_RTIC_MASK (1 << 8) -#define CCM_PCCR0_SAHARA_OFFSET 7 -#define CCM_PCCR0_SAHARA_MASK (1 << 7) -#define CCM_PCCR0_SCC_OFFSET 6 -#define CCM_PCCR0_SCC_MASK (1 << 6) -#define CCM_PCCR0_SDHC1_OFFSET 5 -#define CCM_PCCR0_SDHC1_MASK (1 << 5) -#define CCM_PCCR0_SDHC2_OFFSET 4 -#define CCM_PCCR0_SDHC2_MASK (1 << 4) -#define CCM_PCCR0_SDHC3_OFFSET 3 -#define CCM_PCCR0_SDHC3_MASK (1 << 3) -#define CCM_PCCR0_SLCDC_OFFSET 2 -#define CCM_PCCR0_SLCDC_MASK (1 << 2) -#define CCM_PCCR0_SSI1_IPG_OFFSET 1 -#define CCM_PCCR0_SSI1_IPG_MASK (1 << 1) -#define CCM_PCCR0_SSI2_IPG_OFFSET 0 -#define CCM_PCCR0_SSI2_IPG_MASK (1 << 0) - -#define CCM_PCCR1_UART1_OFFSET 31 -#define CCM_PCCR1_UART1_MASK (1 << 31) -#define CCM_PCCR1_UART2_OFFSET 30 -#define CCM_PCCR1_UART2_MASK (1 << 30) -#define CCM_PCCR1_UART3_OFFSET 29 -#define CCM_PCCR1_UART3_MASK (1 << 29) -#define CCM_PCCR1_UART4_OFFSET 28 -#define CCM_PCCR1_UART4_MASK (1 << 28) -#define CCM_PCCR1_UART5_OFFSET 27 -#define CCM_PCCR1_UART5_MASK (1 << 27) -#define CCM_PCCR1_UART6_OFFSET 26 -#define CCM_PCCR1_UART6_MASK (1 << 26) -#define CCM_PCCR1_USBOTG_OFFSET 25 -#define CCM_PCCR1_USBOTG_MASK (1 << 25) -#define CCM_PCCR1_WDT_OFFSET 24 -#define CCM_PCCR1_WDT_MASK (1 << 24) -#define CCM_PCCR1_HCLK_ATA_OFFSET 23 -#define CCM_PCCR1_HCLK_ATA_MASK (1 << 23) -#define CCM_PCCR1_HCLK_BROM_OFFSET 22 -#define CCM_PCCR1_HCLK_BROM_MASK (1 << 22) -#define CCM_PCCR1_HCLK_CSI_OFFSET 21 -#define CCM_PCCR1_HCLK_CSI_MASK (1 << 21) -#define CCM_PCCR1_HCLK_DMA_OFFSET 20 -#define CCM_PCCR1_HCLK_DMA_MASK (1 << 20) -#define CCM_PCCR1_HCLK_EMI_OFFSET 19 -#define CCM_PCCR1_HCLK_EMI_MASK (1 << 19) -#define CCM_PCCR1_HCLK_EMMA_OFFSET 18 -#define CCM_PCCR1_HCLK_EMMA_MASK (1 << 18) -#define CCM_PCCR1_HCLK_FEC_OFFSET 17 -#define CCM_PCCR1_HCLK_FEC_MASK (1 << 17) -#define CCM_PCCR1_HCLK_VPU_OFFSET 16 -#define CCM_PCCR1_HCLK_VPU_MASK (1 << 16) -#define CCM_PCCR1_HCLK_LCDC_OFFSET 15 -#define CCM_PCCR1_HCLK_LCDC_MASK (1 << 15) -#define CCM_PCCR1_HCLK_RTIC_OFFSET 14 -#define CCM_PCCR1_HCLK_RTIC_MASK (1 << 14) -#define CCM_PCCR1_HCLK_SAHARA_OFFSET 13 -#define CCM_PCCR1_HCLK_SAHARA_MASK (1 << 13) -#define CCM_PCCR1_HCLK_SLCDC_OFFSET 12 -#define CCM_PCCR1_HCLK_SLCDC_MASK (1 << 12) -#define CCM_PCCR1_HCLK_USBOTG_OFFSET 11 -#define CCM_PCCR1_HCLK_USBOTG_MASK (1 << 11) -#define CCM_PCCR1_PERCLK1_OFFSET 10 -#define CCM_PCCR1_PERCLK1_MASK (1 << 10) -#define CCM_PCCR1_PERCLK2_OFFSET 9 -#define CCM_PCCR1_PERCLK2_MASK (1 << 9) -#define CCM_PCCR1_PERCLK3_OFFSET 8 -#define CCM_PCCR1_PERCLK3_MASK (1 << 8) -#define CCM_PCCR1_PERCLK4_OFFSET 7 -#define CCM_PCCR1_PERCLK4_MASK (1 << 7) -#define CCM_PCCR1_VPU_BAUD_OFFSET 6 -#define CCM_PCCR1_VPU_BAUD_MASK (1 << 6) -#define CCM_PCCR1_SSI1_BAUD_OFFSET 5 -#define CCM_PCCR1_SSI1_BAUD_MASK (1 << 5) -#define CCM_PCCR1_SSI2_BAUD_OFFSET 4 -#define CCM_PCCR1_SSI2_BAUD_MASK (1 << 4) -#define CCM_PCCR1_NFC_BAUD_OFFSET 3 -#define CCM_PCCR1_NFC_BAUD_MASK (1 << 3) -#define CCM_PCCR1_MSHC_BAUD_OFFSET 2 -#define CCM_PCCR1_MSHC_BAUD_MASK (1 << 2) - -#define CCM_CCSR_32KSR (1 << 15) -#define CCM_CCSR_CLKMODE1 (1 << 9) -#define CCM_CCSR_CLKMODE0 (1 << 8) -#define CCM_CCSR_CLKOSEL_OFFSET 0 -#define CCM_CCSR_CLKOSEL_MASK 0x1f - -#define SYS_FMCR 0x14 /* Functional Muxing Control Reg */ -#define SYS_CHIP_ID 0x00 /* The offset of CHIP ID register */ - -#endif /* __ARCH_ARM_MACH_MX2_CRM_REGS_H__ */ diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig index 9cc2b16fdf7..10f65bf27b2 100644 --- a/arch/arm/plat-mxc/Kconfig +++ b/arch/arm/plat-mxc/Kconfig @@ -15,6 +15,7 @@ config ARCH_MX1 config ARCH_MX2 bool "MX2-based" select CPU_ARM926T + select COMMON_CLKDEV help This enables support for systems based on the Freescale i.MX2 family -- GitLab From 058b7a6f465bebd87c1f295afdd56cc6a33dffbd Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Mon, 26 Jan 2009 16:34:51 +0100 Subject: [PATCH 3254/4982] arm/imx2x: removes a bunch of sparse-warnings Here are some of the warnings that get fixed by this: > 200 times: warning: cast adds address space to expression () twelve times: warning: symbol 'xxx' was not declared. Should it be static two times: warning: symbol 'clock' shadows an earlier one five times: warning: incorrect type in initializer (different address spaces) Signed-off-by: Holger Schurig Signed-off-by: Sascha Hauer --- arch/arm/mach-mx2/devices.c | 15 +++++++++------ arch/arm/mach-mx2/generic.c | 1 + arch/arm/mach-mx2/mx27ads.c | 4 ++-- arch/arm/mach-mx2/pcm038.c | 2 +- arch/arm/mach-mx2/serial.c | 1 + arch/arm/plat-mxc/devices.c | 1 + arch/arm/plat-mxc/include/mach/board-mx27ads.h | 3 ++- arch/arm/plat-mxc/include/mach/mx27.h | 2 +- arch/arm/plat-mxc/time.c | 12 ++++-------- 9 files changed, 22 insertions(+), 19 deletions(-) diff --git a/arch/arm/mach-mx2/devices.c b/arch/arm/mach-mx2/devices.c index 2f9240be1c7..9ddd6d06105 100644 --- a/arch/arm/mach-mx2/devices.c +++ b/arch/arm/mach-mx2/devices.c @@ -34,6 +34,9 @@ #include #include +#include + +#include "devices.h" /* * Resource definition for the MXC IrDA @@ -230,32 +233,32 @@ static struct mxc_gpio_port imx_gpio_ports[] = { [0] = { .chip.label = "gpio-0", .irq = MXC_INT_GPIO, - .base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 0), + .base = IO_ADDRESS(GPIO_BASE_ADDR), .virtual_irq_start = MXC_GPIO_IRQ_START, }, [1] = { .chip.label = "gpio-1", - .base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 1), + .base = IO_ADDRESS(GPIO_BASE_ADDR + 0x100), .virtual_irq_start = MXC_GPIO_IRQ_START + 32, }, [2] = { .chip.label = "gpio-2", - .base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 2), + .base = IO_ADDRESS(GPIO_BASE_ADDR + 0x200), .virtual_irq_start = MXC_GPIO_IRQ_START + 64, }, [3] = { .chip.label = "gpio-3", - .base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 3), + .base = IO_ADDRESS(GPIO_BASE_ADDR + 0x300), .virtual_irq_start = MXC_GPIO_IRQ_START + 96, }, [4] = { .chip.label = "gpio-4", - .base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 4), + .base = IO_ADDRESS(GPIO_BASE_ADDR + 0x400), .virtual_irq_start = MXC_GPIO_IRQ_START + 128, }, [5] = { .chip.label = "gpio-5", - .base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 5), + .base = IO_ADDRESS(GPIO_BASE_ADDR + 0x500), .virtual_irq_start = MXC_GPIO_IRQ_START + 160, } }; diff --git a/arch/arm/mach-mx2/generic.c b/arch/arm/mach-mx2/generic.c index dea6521d4d5..bd51dd04948 100644 --- a/arch/arm/mach-mx2/generic.c +++ b/arch/arm/mach-mx2/generic.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/mach-mx2/mx27ads.c b/arch/arm/mach-mx2/mx27ads.c index 536bf64bc7c..4548631eb3a 100644 --- a/arch/arm/mach-mx2/mx27ads.c +++ b/arch/arm/mach-mx2/mx27ads.c @@ -266,7 +266,7 @@ static void __init mx27ads_timer_init(void) mx27_clocks_init(fref); } -struct sys_timer mx27ads_timer = { +static struct sys_timer mx27ads_timer = { .init = mx27ads_timer_init, }; @@ -279,7 +279,7 @@ static struct map_desc mx27ads_io_desc[] __initdata = { }, }; -void __init mx27ads_map_io(void) +static void __init mx27ads_map_io(void) { mxc_map_io(); iotable_init(mx27ads_io_desc, ARRAY_SIZE(mx27ads_io_desc)); diff --git a/arch/arm/mach-mx2/pcm038.c b/arch/arm/mach-mx2/pcm038.c index 63cdef8565d..2942d59b570 100644 --- a/arch/arm/mach-mx2/pcm038.c +++ b/arch/arm/mach-mx2/pcm038.c @@ -233,7 +233,7 @@ static void __init pcm038_timer_init(void) mx27_clocks_init(26000000); } -struct sys_timer pcm038_timer = { +static struct sys_timer pcm038_timer = { .init = pcm038_timer_init, }; diff --git a/arch/arm/mach-mx2/serial.c b/arch/arm/mach-mx2/serial.c index b9e66fb1186..40a485cdc10 100644 --- a/arch/arm/mach-mx2/serial.c +++ b/arch/arm/mach-mx2/serial.c @@ -22,6 +22,7 @@ #include #include #include +#include "devices.h" static struct resource uart0[] = { { diff --git a/arch/arm/plat-mxc/devices.c b/arch/arm/plat-mxc/devices.c index c66748267c4..56f2fb5cc45 100644 --- a/arch/arm/plat-mxc/devices.c +++ b/arch/arm/plat-mxc/devices.c @@ -19,6 +19,7 @@ #include #include #include +#include int __init mxc_register_device(struct platform_device *pdev, void *data) { diff --git a/arch/arm/plat-mxc/include/mach/board-mx27ads.h b/arch/arm/plat-mxc/include/mach/board-mx27ads.h index 8f34a05afc8..1cac9d1135c 100644 --- a/arch/arm/plat-mxc/include/mach/board-mx27ads.h +++ b/arch/arm/plat-mxc/include/mach/board-mx27ads.h @@ -48,7 +48,8 @@ * Base address of PBC controller, CS4 */ #define PBC_BASE_ADDRESS 0xEB000000 -#define PBC_REG_ADDR(offset) (PBC_BASE_ADDRESS + (offset)) +#define PBC_REG_ADDR(offset) (void __force __iomem *) \ + (PBC_BASE_ADDRESS + (offset)) /* * PBC Interupt name definitions diff --git a/arch/arm/plat-mxc/include/mach/mx27.h b/arch/arm/plat-mxc/include/mach/mx27.h index 0313be72055..9c609d3ba23 100644 --- a/arch/arm/plat-mxc/include/mach/mx27.h +++ b/arch/arm/plat-mxc/include/mach/mx27.h @@ -129,7 +129,7 @@ * it returns 0xDEADBEEF */ #define IO_ADDRESS(x) \ - (void __iomem *) \ + (void __force __iomem *) \ (((x >= AIPI_BASE_ADDR) && (x < (AIPI_BASE_ADDR + AIPI_SIZE))) ? \ AIPI_IO_ADDRESS(x) : \ ((x >= SAHB1_BASE_ADDR) && (x < (SAHB1_BASE_ADDR + SAHB1_SIZE))) ? \ diff --git a/arch/arm/plat-mxc/time.c b/arch/arm/plat-mxc/time.c index eb93fd1789d..ef1b3cd85bd 100644 --- a/arch/arm/plat-mxc/time.c +++ b/arch/arm/plat-mxc/time.c @@ -52,11 +52,9 @@ static struct clocksource clocksource_mxc = { static int __init mxc_clocksource_init(struct clk *timer_clk) { - unsigned int clock; + unsigned int c = clk_get_rate(timer_clk); - clock = clk_get_rate(timer_clk); - - clocksource_mxc.mult = clocksource_hz2mult(clock, + clocksource_mxc.mult = clocksource_hz2mult(c, clocksource_mxc.shift); clocksource_register(&clocksource_mxc); @@ -176,11 +174,9 @@ static struct clock_event_device clockevent_mxc = { static int __init mxc_clockevent_init(struct clk *timer_clk) { - unsigned int clock; - - clock = clk_get_rate(timer_clk); + unsigned int c = clk_get_rate(timer_clk); - clockevent_mxc.mult = div_sc(clock, NSEC_PER_SEC, + clockevent_mxc.mult = div_sc(c, NSEC_PER_SEC, clockevent_mxc.shift); clockevent_mxc.max_delta_ns = clockevent_delta2ns(0xfffffffe, &clockevent_mxc); -- GitLab From 260a1fd26c62af482a22c6b31cc7882b4ec980d2 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Mon, 26 Jan 2009 16:34:53 +0100 Subject: [PATCH 3255/4982] arm/imx2x: split i.MX21/i.MX27 register definitions * define new CONFIG_ARCH_MX21 (this one is currently mutually exclusive to CONFIG_ARCH_MX27, but this might change) * splits one header file. Memory definitions, interrupt sources, DMA channels are split into common part, i.MX27 specific and i.MX21 specific. * guard access to UART5/UART6, which don't exist on i.MX21 Signed-off-by: Holger Schurig Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/include/mach/hardware.h | 4 + arch/arm/plat-mxc/include/mach/mx21.h | 81 +++++++++ arch/arm/plat-mxc/include/mach/mx27.h | 197 ++------------------- arch/arm/plat-mxc/include/mach/mx2x.h | 200 ++++++++++++++++++++++ arch/arm/plat-mxc/include/mach/mxc.h | 4 + 5 files changed, 306 insertions(+), 180 deletions(-) create mode 100644 arch/arm/plat-mxc/include/mach/mx21.h create mode 100644 arch/arm/plat-mxc/include/mach/mx2x.h diff --git a/arch/arm/plat-mxc/include/mach/hardware.h b/arch/arm/plat-mxc/include/mach/hardware.h index a612d8bb73c..11f5727ea44 100644 --- a/arch/arm/plat-mxc/include/mach/hardware.h +++ b/arch/arm/plat-mxc/include/mach/hardware.h @@ -27,6 +27,10 @@ #endif #ifdef CONFIG_ARCH_MX2 +# include +# ifdef CONFIG_MACH_MX21 +# include +# endif # ifdef CONFIG_MACH_MX27 # include # endif diff --git a/arch/arm/plat-mxc/include/mach/mx21.h b/arch/arm/plat-mxc/include/mach/mx21.h new file mode 100644 index 00000000000..cfdbe051caf --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/mx21.h @@ -0,0 +1,81 @@ +/* + * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2008 Juergen Beisert, kernel@pengutronix.de + * Copyright 2009 Holger Schurig, hs4233@mail.mn-solutions.de + * + * This contains i.MX21-specific hardware definitions. For those + * hardware pieces that are common between i.MX21 and i.MX27, have a + * look at mx2x.h. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef __ASM_ARCH_MXC_MX21_H__ +#define __ASM_ARCH_MXC_MX21_H__ + +#ifndef __ASM_ARCH_MXC_HARDWARE_H__ +#error "Do not include directly." +#endif + + +/* Memory regions and CS */ +#define SDRAM_BASE_ADDR 0xC0000000 +#define CSD1_BASE_ADDR 0xC4000000 + +#define CS0_BASE_ADDR 0xC8000000 +#define CS1_BASE_ADDR 0xCC000000 +#define CS2_BASE_ADDR 0xD0000000 +#define CS3_BASE_ADDR 0xD1000000 +#define CS4_BASE_ADDR 0xD2000000 +#define CS5_BASE_ADDR 0xDD000000 +#define PCMCIA_MEM_BASE_ADDR 0xD4000000 + +/* NAND, SDRAM, WEIM etc controllers */ +#define X_MEMC_BASE_ADDR 0xDF000000 +#define X_MEMC_BASE_ADDR_VIRT 0xF4200000 +#define X_MEMC_SIZE SZ_256K + +#define SDRAMC_BASE_ADDR (X_MEMC_BASE_ADDR + 0x0000) +#define EIM_BASE_ADDR (X_MEMC_BASE_ADDR + 0x1000) +#define PCMCIA_CTL_BASE_ADDR (X_MEMC_BASE_ADDR + 0x2000) +#define NFC_BASE_ADDR (X_MEMC_BASE_ADDR + 0x3000) + +#define IRAM_BASE_ADDR 0xFFFFE800 /* internal ram */ + +/* this is an i.MX21 CPU */ +#define cpu_is_mx21() (1) + +/* this CPU supports up to 192 GPIOs (don't forget the baseboard!) */ +#define ARCH_NR_GPIOS (6*32 + 16) + +/* fixed interrupt numbers */ +#define MXC_INT_USBCTRL 58 +#define MXC_INT_USBCTRL 58 +#define MXC_INT_USBMNP 57 +#define MXC_INT_USBFUNC 56 +#define MXC_INT_USBHOST 55 +#define MXC_INT_USBDMA 54 +#define MXC_INT_USBWKUP 53 +#define MXC_INT_EMMADEC 50 +#define MXC_INT_EMMAENC 49 +#define MXC_INT_BMI 30 +#define MXC_INT_FIRI 9 + +/* fixed DMA request numbers */ +#define DMA_REQ_BMI_RX 29 +#define DMA_REQ_BMI_TX 28 +#define DMA_REQ_FIRI_RX 4 + +#endif /* __ASM_ARCH_MXC_MX21_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/mx27.h b/arch/arm/plat-mxc/include/mach/mx27.h index 9c609d3ba23..5f6a8a7bb19 100644 --- a/arch/arm/plat-mxc/include/mach/mx27.h +++ b/arch/arm/plat-mxc/include/mach/mx27.h @@ -2,6 +2,10 @@ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. * Copyright 2008 Juergen Beisert, kernel@pengutronix.de * + * This contains i.MX27-specific hardware definitions. For those + * hardware pieces that are common between i.MX21 and i.MX27, have a + * look at mx2x.h. + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -27,35 +31,6 @@ /* IRAM */ #define IRAM_BASE_ADDR 0xFFFF4C00 /* internal ram */ -/* Register offests */ -#define AIPI_BASE_ADDR 0x10000000 -#define AIPI_BASE_ADDR_VIRT 0xF4000000 -#define AIPI_SIZE SZ_1M - -#define DMA_BASE_ADDR (AIPI_BASE_ADDR + 0x01000) -#define WDOG_BASE_ADDR (AIPI_BASE_ADDR + 0x02000) -#define GPT1_BASE_ADDR (AIPI_BASE_ADDR + 0x03000) -#define GPT2_BASE_ADDR (AIPI_BASE_ADDR + 0x04000) -#define GPT3_BASE_ADDR (AIPI_BASE_ADDR + 0x05000) -#define PWM_BASE_ADDR (AIPI_BASE_ADDR + 0x06000) -#define RTC_BASE_ADDR (AIPI_BASE_ADDR + 0x07000) -#define KPP_BASE_ADDR (AIPI_BASE_ADDR + 0x08000) -#define OWIRE_BASE_ADDR (AIPI_BASE_ADDR + 0x09000) -#define UART1_BASE_ADDR (AIPI_BASE_ADDR + 0x0A000) -#define UART2_BASE_ADDR (AIPI_BASE_ADDR + 0x0B000) -#define UART3_BASE_ADDR (AIPI_BASE_ADDR + 0x0C000) -#define UART4_BASE_ADDR (AIPI_BASE_ADDR + 0x0D000) -#define CSPI1_BASE_ADDR (AIPI_BASE_ADDR + 0x0E000) -#define CSPI2_BASE_ADDR (AIPI_BASE_ADDR + 0x0F000) -#define SSI1_BASE_ADDR (AIPI_BASE_ADDR + 0x10000) -#define SSI2_BASE_ADDR (AIPI_BASE_ADDR + 0x11000) -#define I2C_BASE_ADDR (AIPI_BASE_ADDR + 0x12000) -#define SDHC1_BASE_ADDR (AIPI_BASE_ADDR + 0x13000) -#define SDHC2_BASE_ADDR (AIPI_BASE_ADDR + 0x14000) -#define GPIO_BASE_ADDR (AIPI_BASE_ADDR + 0x15000) -#define AUDMUX_BASE_ADDR (AIPI_BASE_ADDR + 0x16000) - -#define CSPI3_BASE_ADDR (AIPI_BASE_ADDR + 0x17000) #define MSHC_BASE_ADDR (AIPI_BASE_ADDR + 0x18000) #define GPT5_BASE_ADDR (AIPI_BASE_ADDR + 0x19000) #define GPT4_BASE_ADDR (AIPI_BASE_ADDR + 0x1A000) @@ -64,55 +39,24 @@ #define I2C2_BASE_ADDR (AIPI_BASE_ADDR + 0x1D000) #define SDHC3_BASE_ADDR (AIPI_BASE_ADDR + 0x1E000) #define GPT6_BASE_ADDR (AIPI_BASE_ADDR + 0x1F000) - -#define LCDC_BASE_ADDR (AIPI_BASE_ADDR + 0x21000) -#define SLCDC_BASE_ADDR (AIPI_BASE_ADDR + 0x22000) #define VPU_BASE_ADDR (AIPI_BASE_ADDR + 0x23000) -#define USBOTG_BASE_ADDR (AIPI_BASE_ADDR + 0x24000) -/* for mx27*/ #define OTG_BASE_ADDR USBOTG_BASE_ADDR #define SAHARA_BASE_ADDR (AIPI_BASE_ADDR + 0x25000) -#define EMMA_PP_BASE_ADDR (AIPI_BASE_ADDR + 0x26000) -#define EMMA_PRP_BASE_ADDR (AIPI_BASE_ADDR + 0x26400) -#define CCM_BASE_ADDR (AIPI_BASE_ADDR + 0x27000) -#define SYSCTRL_BASE_ADDR (AIPI_BASE_ADDR + 0x27800) #define IIM_BASE_ADDR (AIPI_BASE_ADDR + 0x28000) - #define RTIC_BASE_ADDR (AIPI_BASE_ADDR + 0x2A000) #define FEC_BASE_ADDR (AIPI_BASE_ADDR + 0x2B000) #define SCC_BASE_ADDR (AIPI_BASE_ADDR + 0x2C000) #define ETB_BASE_ADDR (AIPI_BASE_ADDR + 0x3B000) #define ETB_RAM_BASE_ADDR (AIPI_BASE_ADDR + 0x3C000) -#define JAM_BASE_ADDR (AIPI_BASE_ADDR + 0x3E000) -#define MAX_BASE_ADDR (AIPI_BASE_ADDR + 0x3F000) - -/* ROMP and AVIC */ +/* ROM patch */ #define ROMP_BASE_ADDR 0x10041000 -#define AVIC_BASE_ADDR 0x10040000 - -#define SAHB1_BASE_ADDR 0x80000000 -#define SAHB1_BASE_ADDR_VIRT 0xF4100000 -#define SAHB1_SIZE SZ_1M - -#define CSI_BASE_ADDR (SAHB1_BASE_ADDR + 0x0000) #define ATA_BASE_ADDR (SAHB1_BASE_ADDR + 0x1000) -/* NAND, SDRAM, WEIM, M3IF, EMI controllers */ -#define X_MEMC_BASE_ADDR 0xD8000000 -#define X_MEMC_BASE_ADDR_VIRT 0xF4200000 -#define X_MEMC_SIZE SZ_1M - -#define NFC_BASE_ADDR (X_MEMC_BASE_ADDR) -#define SDRAMC_BASE_ADDR (X_MEMC_BASE_ADDR + 0x1000) -#define WEIM_BASE_ADDR (X_MEMC_BASE_ADDR + 0x2000) -#define M3IF_BASE_ADDR (X_MEMC_BASE_ADDR + 0x3000) -#define PCMCIA_CTL_BASE_ADDR (X_MEMC_BASE_ADDR + 0x4000) - /* Memory regions and CS */ -#define SDRAM_BASE_ADDR 0xA0000000 -#define CSD1_BASE_ADDR 0xB0000000 +#define SDRAM_BASE_ADDR 0xA0000000 +#define CSD1_BASE_ADDR 0xB0000000 #define CS0_BASE_ADDR 0xC0000000 #define CS1_BASE_ADDR 0xC8000000 @@ -122,44 +66,20 @@ #define CS5_BASE_ADDR 0xD6000000 #define PCMCIA_MEM_BASE_ADDR 0xDC000000 -/* - * This macro defines the physical to virtual address mapping for all the - * peripheral modules. It is used by passing in the physical address as x - * and returning the virtual address. If the physical address is not mapped, - * it returns 0xDEADBEEF - */ -#define IO_ADDRESS(x) \ - (void __force __iomem *) \ - (((x >= AIPI_BASE_ADDR) && (x < (AIPI_BASE_ADDR + AIPI_SIZE))) ? \ - AIPI_IO_ADDRESS(x) : \ - ((x >= SAHB1_BASE_ADDR) && (x < (SAHB1_BASE_ADDR + SAHB1_SIZE))) ? \ - SAHB1_IO_ADDRESS(x) : \ - ((x >= X_MEMC_BASE_ADDR) && (x < (X_MEMC_BASE_ADDR + X_MEMC_SIZE))) ? \ - X_MEMC_IO_ADDRESS(x) : 0xDEADBEEF) - -/* define the address mapping macros: in physical address order */ -#define AIPI_IO_ADDRESS(x) \ - (((x) - AIPI_BASE_ADDR) + AIPI_BASE_ADDR_VIRT) - -#define AVIC_IO_ADDRESS(x) AIPI_IO_ADDRESS(x) - -#define SAHB1_IO_ADDRESS(x) \ - (((x) - SAHB1_BASE_ADDR) + SAHB1_BASE_ADDR_VIRT) - -#define CS4_IO_ADDRESS(x) \ - (((x) - CS4_BASE_ADDR) + CS4_BASE_ADDR_VIRT) - -#define X_MEMC_IO_ADDRESS(x) \ - (((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT) +/* NAND, SDRAM, WEIM, M3IF, EMI controllers */ +#define X_MEMC_BASE_ADDR 0xD8000000 +#define X_MEMC_BASE_ADDR_VIRT 0xF4200000 +#define X_MEMC_SIZE SZ_1M -#define PCMCIA_IO_ADDRESS(x) \ - (((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT) +#define NFC_BASE_ADDR (X_MEMC_BASE_ADDR) +#define SDRAMC_BASE_ADDR (X_MEMC_BASE_ADDR + 0x1000) +#define WEIM_BASE_ADDR (X_MEMC_BASE_ADDR + 0x2000) +#define M3IF_BASE_ADDR (X_MEMC_BASE_ADDR + 0x3000) +#define PCMCIA_CTL_BASE_ADDR (X_MEMC_BASE_ADDR + 0x4000) -/* fixed interrput numbers */ +/* fixed interrupt numbers */ #define MXC_INT_CCM 63 #define MXC_INT_IIM 62 -#define MXC_INT_LCDC 61 -#define MXC_INT_SLCDC 60 #define MXC_INT_SAHARA 59 #define MXC_INT_SCC_SCM 58 #define MXC_INT_SCC_SMN 57 @@ -167,54 +87,12 @@ #define MXC_INT_USB2 55 #define MXC_INT_USB1 54 #define MXC_INT_VPU 53 -#define MXC_INT_EMMAPP 52 -#define MXC_INT_EMMAPRP 51 #define MXC_INT_FEC 50 #define MXC_INT_UART5 49 #define MXC_INT_UART6 48 -#define MXC_INT_DMACH15 47 -#define MXC_INT_DMACH14 46 -#define MXC_INT_DMACH13 45 -#define MXC_INT_DMACH12 44 -#define MXC_INT_DMACH11 43 -#define MXC_INT_DMACH10 42 -#define MXC_INT_DMACH9 41 -#define MXC_INT_DMACH8 40 -#define MXC_INT_DMACH7 39 -#define MXC_INT_DMACH6 38 -#define MXC_INT_DMACH5 37 -#define MXC_INT_DMACH4 36 -#define MXC_INT_DMACH3 35 -#define MXC_INT_DMACH2 34 -#define MXC_INT_DMACH1 33 -#define MXC_INT_DMACH0 32 -#define MXC_INT_CSI 31 #define MXC_INT_ATA 30 -#define MXC_INT_NANDFC 29 -#define MXC_INT_PCMCIA 28 -#define MXC_INT_WDOG 27 -#define MXC_INT_GPT1 26 -#define MXC_INT_GPT2 25 -#define MXC_INT_GPT3 24 -#define MXC_INT_GPT INT_GPT1 -#define MXC_INT_PWM 23 -#define MXC_INT_RTC 22 -#define MXC_INT_KPP 21 -#define MXC_INT_UART1 20 -#define MXC_INT_UART2 19 -#define MXC_INT_UART3 18 -#define MXC_INT_UART4 17 -#define MXC_INT_CSPI1 16 -#define MXC_INT_CSPI2 15 -#define MXC_INT_SSI1 14 -#define MXC_INT_SSI2 13 -#define MXC_INT_I2C 12 -#define MXC_INT_SDHC1 11 -#define MXC_INT_SDHC2 10 #define MXC_INT_SDHC3 9 -#define MXC_INT_GPIO 8 #define MXC_INT_SDHC 7 -#define MXC_INT_CSPI3 6 #define MXC_INT_RTIC 5 #define MXC_INT_GPT4 4 #define MXC_INT_GPT5 3 @@ -228,36 +106,9 @@ #define DMA_REQ_UART6_TX 34 #define DMA_REQ_UART5_RX 33 #define DMA_REQ_UART5_TX 32 -#define DMA_REQ_CSI_RX 31 -#define DMA_REQ_CSI_STAT 30 #define DMA_REQ_ATA_RCV 29 #define DMA_REQ_ATA_TX 28 -#define DMA_REQ_UART1_TX 27 -#define DMA_REQ_UART1_RX 26 -#define DMA_REQ_UART2_TX 25 -#define DMA_REQ_UART2_RX 24 -#define DMA_REQ_UART3_TX 23 -#define DMA_REQ_UART3_RX 22 -#define DMA_REQ_UART4_TX 21 -#define DMA_REQ_UART4_RX 20 -#define DMA_REQ_CSPI1_TX 19 -#define DMA_REQ_CSPI1_RX 18 -#define DMA_REQ_CSPI2_TX 17 -#define DMA_REQ_CSPI2_RX 16 -#define DMA_REQ_SSI1_TX1 15 -#define DMA_REQ_SSI1_RX1 14 -#define DMA_REQ_SSI1_TX0 13 -#define DMA_REQ_SSI1_RX0 12 -#define DMA_REQ_SSI2_TX1 11 -#define DMA_REQ_SSI2_RX1 10 -#define DMA_REQ_SSI2_TX0 9 -#define DMA_REQ_SSI2_RX0 8 -#define DMA_REQ_SDHC1 7 -#define DMA_REQ_SDHC2 6 #define DMA_REQ_MSHC 4 -#define DMA_REQ_EXT 3 -#define DMA_REQ_CSPI3_TX 2 -#define DMA_REQ_CSPI3_RX 1 /* silicon revisions specific to i.MX27 */ #define CHIP_REV_1_0 0x00 @@ -267,20 +118,6 @@ extern int mx27_revision(void); #endif -/* gpio and gpio based interrupt handling */ -#define GPIO_DR 0x1C -#define GPIO_GDIR 0x00 -#define GPIO_PSR 0x24 -#define GPIO_ICR1 0x28 -#define GPIO_ICR2 0x2C -#define GPIO_IMR 0x30 -#define GPIO_ISR 0x34 -#define GPIO_INT_LOW_LEV 0x3 -#define GPIO_INT_HIGH_LEV 0x2 -#define GPIO_INT_RISE_EDGE 0x0 -#define GPIO_INT_FALL_EDGE 0x1 -#define GPIO_INT_NONE 0x4 - /* Mandatory defines used globally */ /* this is an i.MX27 CPU */ diff --git a/arch/arm/plat-mxc/include/mach/mx2x.h b/arch/arm/plat-mxc/include/mach/mx2x.h new file mode 100644 index 00000000000..fc40d3ab8c5 --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/mx2x.h @@ -0,0 +1,200 @@ +/* + * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2008 Juergen Beisert, kernel@pengutronix.de + * + * This contains hardware definitions that are common between i.MX21 and + * i.MX27. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef __ASM_ARCH_MXC_MX2x_H__ +#define __ASM_ARCH_MXC_MX2x_H__ + +#ifndef __ASM_ARCH_MXC_HARDWARE_H__ +#error "Do not include directly." +#endif + +/* The following addresses are common between i.MX21 and i.MX27 */ + +/* Register offests */ +#define AIPI_BASE_ADDR 0x10000000 +#define AIPI_BASE_ADDR_VIRT 0xF4000000 +#define AIPI_SIZE SZ_1M + +#define DMA_BASE_ADDR (AIPI_BASE_ADDR + 0x01000) +#define WDOG_BASE_ADDR (AIPI_BASE_ADDR + 0x02000) +#define GPT1_BASE_ADDR (AIPI_BASE_ADDR + 0x03000) +#define GPT2_BASE_ADDR (AIPI_BASE_ADDR + 0x04000) +#define GPT3_BASE_ADDR (AIPI_BASE_ADDR + 0x05000) +#define PWM_BASE_ADDR (AIPI_BASE_ADDR + 0x06000) +#define RTC_BASE_ADDR (AIPI_BASE_ADDR + 0x07000) +#define KPP_BASE_ADDR (AIPI_BASE_ADDR + 0x08000) +#define OWIRE_BASE_ADDR (AIPI_BASE_ADDR + 0x09000) +#define UART1_BASE_ADDR (AIPI_BASE_ADDR + 0x0A000) +#define UART2_BASE_ADDR (AIPI_BASE_ADDR + 0x0B000) +#define UART3_BASE_ADDR (AIPI_BASE_ADDR + 0x0C000) +#define UART4_BASE_ADDR (AIPI_BASE_ADDR + 0x0D000) +#define CSPI1_BASE_ADDR (AIPI_BASE_ADDR + 0x0E000) +#define CSPI2_BASE_ADDR (AIPI_BASE_ADDR + 0x0F000) +#define SSI1_BASE_ADDR (AIPI_BASE_ADDR + 0x10000) +#define SSI2_BASE_ADDR (AIPI_BASE_ADDR + 0x11000) +#define I2C_BASE_ADDR (AIPI_BASE_ADDR + 0x12000) +#define SDHC1_BASE_ADDR (AIPI_BASE_ADDR + 0x13000) +#define SDHC2_BASE_ADDR (AIPI_BASE_ADDR + 0x14000) +#define GPIO_BASE_ADDR (AIPI_BASE_ADDR + 0x15000) +#define AUDMUX_BASE_ADDR (AIPI_BASE_ADDR + 0x16000) +#define CSPI3_BASE_ADDR (AIPI_BASE_ADDR + 0x17000) +#define LCDC_BASE_ADDR (AIPI_BASE_ADDR + 0x21000) +#define SLCDC_BASE_ADDR (AIPI_BASE_ADDR + 0x22000) +#define USBOTG_BASE_ADDR (AIPI_BASE_ADDR + 0x24000) +#define EMMA_PP_BASE_ADDR (AIPI_BASE_ADDR + 0x26000) +#define EMMA_PRP_BASE_ADDR (AIPI_BASE_ADDR + 0x26400) +#define CCM_BASE_ADDR (AIPI_BASE_ADDR + 0x27000) +#define SYSCTRL_BASE_ADDR (AIPI_BASE_ADDR + 0x27800) +#define JAM_BASE_ADDR (AIPI_BASE_ADDR + 0x3E000) +#define MAX_BASE_ADDR (AIPI_BASE_ADDR + 0x3F000) + +#define AVIC_BASE_ADDR 0x10040000 + +#define SAHB1_BASE_ADDR 0x80000000 +#define SAHB1_BASE_ADDR_VIRT 0xF4100000 +#define SAHB1_SIZE SZ_1M + +#define CSI_BASE_ADDR (SAHB1_BASE_ADDR + 0x0000) + +/* + * This macro defines the physical to virtual address mapping for all the + * peripheral modules. It is used by passing in the physical address as x + * and returning the virtual address. If the physical address is not mapped, + * it returns 0xDEADBEEF + */ +#define IO_ADDRESS(x) \ + (void __force __iomem *) \ + (((x >= AIPI_BASE_ADDR) && (x < (AIPI_BASE_ADDR + AIPI_SIZE))) ? \ + AIPI_IO_ADDRESS(x) : \ + ((x >= SAHB1_BASE_ADDR) && (x < (SAHB1_BASE_ADDR + SAHB1_SIZE))) ? \ + SAHB1_IO_ADDRESS(x) : \ + ((x >= X_MEMC_BASE_ADDR) && (x < (X_MEMC_BASE_ADDR + X_MEMC_SIZE))) ? \ + X_MEMC_IO_ADDRESS(x) : 0xDEADBEEF) + +/* define the address mapping macros: in physical address order */ +#define AIPI_IO_ADDRESS(x) \ + (((x) - AIPI_BASE_ADDR) + AIPI_BASE_ADDR_VIRT) + +#define AVIC_IO_ADDRESS(x) AIPI_IO_ADDRESS(x) + +#define SAHB1_IO_ADDRESS(x) \ + (((x) - SAHB1_BASE_ADDR) + SAHB1_BASE_ADDR_VIRT) + +#define CS4_IO_ADDRESS(x) \ + (((x) - CS4_BASE_ADDR) + CS4_BASE_ADDR_VIRT) + +#define X_MEMC_IO_ADDRESS(x) \ + (((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT) + +#define PCMCIA_IO_ADDRESS(x) \ + (((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT) + +/* fixed interrupt numbers */ +#define MXC_INT_LCDC 61 +#define MXC_INT_SLCDC 60 +#define MXC_INT_EMMAPP 52 +#define MXC_INT_EMMAPRP 51 +#define MXC_INT_DMACH15 47 +#define MXC_INT_DMACH14 46 +#define MXC_INT_DMACH13 45 +#define MXC_INT_DMACH12 44 +#define MXC_INT_DMACH11 43 +#define MXC_INT_DMACH10 42 +#define MXC_INT_DMACH9 41 +#define MXC_INT_DMACH8 40 +#define MXC_INT_DMACH7 39 +#define MXC_INT_DMACH6 38 +#define MXC_INT_DMACH5 37 +#define MXC_INT_DMACH4 36 +#define MXC_INT_DMACH3 35 +#define MXC_INT_DMACH2 34 +#define MXC_INT_DMACH1 33 +#define MXC_INT_DMACH0 32 +#define MXC_INT_CSI 31 +#define MXC_INT_NANDFC 29 +#define MXC_INT_PCMCIA 28 +#define MXC_INT_WDOG 27 +#define MXC_INT_GPT1 26 +#define MXC_INT_GPT2 25 +#define MXC_INT_GPT3 24 +#define MXC_INT_GPT INT_GPT1 +#define MXC_INT_PWM 23 +#define MXC_INT_RTC 22 +#define MXC_INT_KPP 21 +#define MXC_INT_UART1 20 +#define MXC_INT_UART2 19 +#define MXC_INT_UART3 18 +#define MXC_INT_UART4 17 +#define MXC_INT_CSPI1 16 +#define MXC_INT_CSPI2 15 +#define MXC_INT_SSI1 14 +#define MXC_INT_SSI2 13 +#define MXC_INT_I2C 12 +#define MXC_INT_SDHC1 11 +#define MXC_INT_SDHC2 10 +#define MXC_INT_GPIO 8 +#define MXC_INT_CSPI3 6 + +/* gpio and gpio based interrupt handling */ +#define GPIO_DR 0x1C +#define GPIO_GDIR 0x00 +#define GPIO_PSR 0x24 +#define GPIO_ICR1 0x28 +#define GPIO_ICR2 0x2C +#define GPIO_IMR 0x30 +#define GPIO_ISR 0x34 +#define GPIO_INT_LOW_LEV 0x3 +#define GPIO_INT_HIGH_LEV 0x2 +#define GPIO_INT_RISE_EDGE 0x0 +#define GPIO_INT_FALL_EDGE 0x1 +#define GPIO_INT_NONE 0x4 + +/* fixed DMA request numbers */ +#define DMA_REQ_CSI_RX 31 +#define DMA_REQ_CSI_STAT 30 +#define DMA_REQ_UART1_TX 27 +#define DMA_REQ_UART1_RX 26 +#define DMA_REQ_UART2_TX 25 +#define DMA_REQ_UART2_RX 24 +#define DMA_REQ_UART3_TX 23 +#define DMA_REQ_UART3_RX 22 +#define DMA_REQ_UART4_TX 21 +#define DMA_REQ_UART4_RX 20 +#define DMA_REQ_CSPI1_TX 19 +#define DMA_REQ_CSPI1_RX 18 +#define DMA_REQ_CSPI2_TX 17 +#define DMA_REQ_CSPI2_RX 16 +#define DMA_REQ_SSI1_TX1 15 +#define DMA_REQ_SSI1_RX1 14 +#define DMA_REQ_SSI1_TX0 13 +#define DMA_REQ_SSI1_RX0 12 +#define DMA_REQ_SSI2_TX1 11 +#define DMA_REQ_SSI2_RX1 10 +#define DMA_REQ_SSI2_TX0 9 +#define DMA_REQ_SSI2_RX0 8 +#define DMA_REQ_SDHC1 7 +#define DMA_REQ_SDHC2 6 +#define DMA_REQ_EXT 3 +#define DMA_REQ_CSPI3_TX 2 +#define DMA_REQ_CSPI3_RX 1 + +#endif /* __ASM_ARCH_MXC_MX2x_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h index bbd848e004d..d6b0c472cd9 100644 --- a/arch/arm/plat-mxc/include/mach/mxc.h +++ b/arch/arm/plat-mxc/include/mach/mxc.h @@ -37,6 +37,10 @@ # define cpu_is_mx27() (0) #endif +#ifndef CONFIG_MACH_MX21 +# define cpu_is_mx21() (0) +#endif + #if defined(CONFIG_ARCH_MX3) || defined(CONFIG_ARCH_MX2) #define CSCR_U(n) (IO_ADDRESS(WEIM_BASE_ADDR) + n * 0x10) #define CSCR_L(n) (IO_ADDRESS(WEIM_BASE_ADDR) + n * 0x10 + 0x4) -- GitLab From aa3b0a6f57be50f1009a409e82731a8f9be80fc4 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Mon, 26 Jan 2009 16:34:54 +0100 Subject: [PATCH 3256/4982] arm/imx21: clock support for i.MX21 Based on code from "Martin Fuzzey" Signed-off-by: Holger Schurig Signed-off-by: Sascha Hauer --- arch/arm/mach-mx2/Makefile | 2 + arch/arm/mach-mx2/clock_imx21.c | 984 ++++++++++++++++++++++++ arch/arm/mach-mx2/crm_regs.h | 258 +++++++ arch/arm/plat-mxc/include/mach/common.h | 1 + 4 files changed, 1245 insertions(+) create mode 100644 arch/arm/mach-mx2/clock_imx21.c create mode 100644 arch/arm/mach-mx2/crm_regs.h diff --git a/arch/arm/mach-mx2/Makefile b/arch/arm/mach-mx2/Makefile index 382d86080e8..6e1a2bffc81 100644 --- a/arch/arm/mach-mx2/Makefile +++ b/arch/arm/mach-mx2/Makefile @@ -6,6 +6,8 @@ obj-y := system.o generic.o devices.o serial.o +obj-$(CONFIG_MACH_MX21) += clock_imx21.o + obj-$(CONFIG_MACH_MX27) += cpu_imx27.o obj-$(CONFIG_MACH_MX27) += clock_imx27.o diff --git a/arch/arm/mach-mx2/clock_imx21.c b/arch/arm/mach-mx2/clock_imx21.c new file mode 100644 index 00000000000..2dee5c87614 --- /dev/null +++ b/arch/arm/mach-mx2/clock_imx21.c @@ -0,0 +1,984 @@ +/* + * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2008 Juergen Beisert, kernel@pengutronix.de + * Copyright 2008 Martin Fuzzey, mfuzzey@gmail.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "crm_regs.h" + +static int _clk_enable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(clk->enable_reg); + reg |= 1 << clk->enable_shift; + __raw_writel(reg, clk->enable_reg); + return 0; +} + +static void _clk_disable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(clk->enable_reg); + reg &= ~(1 << clk->enable_shift); + __raw_writel(reg, clk->enable_reg); +} + +static int _clk_spll_enable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(CCM_CSCR); + reg |= CCM_CSCR_SPEN; + __raw_writel(reg, CCM_CSCR); + + while ((__raw_readl(CCM_SPCTL1) & CCM_SPCTL1_LF) == 0) + ; + return 0; +} + +static void _clk_spll_disable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(CCM_CSCR); + reg &= ~CCM_CSCR_SPEN; + __raw_writel(reg, CCM_CSCR); +} + + +#define CSCR() (__raw_readl(CCM_CSCR)) +#define PCDR0() (__raw_readl(CCM_PCDR0)) +#define PCDR1() (__raw_readl(CCM_PCDR1)) + +static unsigned long _clk_perclkx_round_rate(struct clk *clk, + unsigned long rate) +{ + u32 div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + if (parent_rate % rate) + div++; + + if (div > 64) + div = 64; + + return parent_rate / div; +} + +static int _clk_perclkx_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg; + u32 div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + if (clk->id < 0 || clk->id > 3) + return -EINVAL; + + div = parent_rate / rate; + if (div > 64 || div < 1 || ((parent_rate / div) != rate)) + return -EINVAL; + div--; + + reg = + __raw_readl(CCM_PCDR1) & ~(CCM_PCDR1_PERDIV1_MASK << + (clk->id << 3)); + reg |= div << (clk->id << 3); + __raw_writel(reg, CCM_PCDR1); + + return 0; +} + +static unsigned long _clk_usb_recalc(struct clk *clk) +{ + unsigned long usb_pdf; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + usb_pdf = (CSCR() & CCM_CSCR_USB_MASK) >> CCM_CSCR_USB_OFFSET; + + return parent_rate / (usb_pdf + 1U); +} + +static unsigned long _clk_ssix_recalc(struct clk *clk, unsigned long pdf) +{ + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + pdf = (pdf < 2) ? 124UL : pdf; /* MX21 & MX27 TO1 */ + + return 2UL * parent_rate / pdf; +} + +static unsigned long _clk_ssi1_recalc(struct clk *clk) +{ + return _clk_ssix_recalc(clk, + (PCDR0() & CCM_PCDR0_SSI1BAUDDIV_MASK) + >> CCM_PCDR0_SSI1BAUDDIV_OFFSET); +} + +static unsigned long _clk_ssi2_recalc(struct clk *clk) +{ + return _clk_ssix_recalc(clk, + (PCDR0() & CCM_PCDR0_SSI2BAUDDIV_MASK) >> + CCM_PCDR0_SSI2BAUDDIV_OFFSET); +} + +static unsigned long _clk_nfc_recalc(struct clk *clk) +{ + unsigned long nfc_pdf; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + nfc_pdf = (PCDR0() & CCM_PCDR0_NFCDIV_MASK) + >> CCM_PCDR0_NFCDIV_OFFSET; + + return parent_rate / (nfc_pdf + 1); +} + +static unsigned long _clk_parent_round_rate(struct clk *clk, unsigned long rate) +{ + return clk->parent->round_rate(clk->parent, rate); +} + +static int _clk_parent_set_rate(struct clk *clk, unsigned long rate) +{ + return clk->parent->set_rate(clk->parent, rate); +} + +static unsigned long external_high_reference; /* in Hz */ + +static unsigned long get_high_reference_clock_rate(struct clk *clk) +{ + return external_high_reference; +} + +/* + * the high frequency external clock reference + * Default case is 26MHz. + */ +static struct clk ckih_clk = { + .get_rate = get_high_reference_clock_rate, +}; + +static unsigned long external_low_reference; /* in Hz */ + +static unsigned long get_low_reference_clock_rate(struct clk *clk) +{ + return external_low_reference; +} + +/* + * the low frequency external clock reference + * Default case is 32.768kHz. + */ +static struct clk ckil_clk = { + .get_rate = get_low_reference_clock_rate, +}; + + +static unsigned long _clk_fpm_recalc(struct clk *clk) +{ + return clk_get_rate(clk->parent) * 512; +} + +/* Output of frequency pre multiplier */ +static struct clk fpm_clk = { + .parent = &ckil_clk, + .get_rate = _clk_fpm_recalc, +}; + +static unsigned long get_mpll_clk(struct clk *clk) +{ + uint32_t reg; + unsigned long ref_clk; + unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0; + unsigned long long temp; + + ref_clk = clk_get_rate(clk->parent); + + reg = __raw_readl(CCM_MPCTL0); + pdf = (reg & CCM_MPCTL0_PD_MASK) >> CCM_MPCTL0_PD_OFFSET; + mfd = (reg & CCM_MPCTL0_MFD_MASK) >> CCM_MPCTL0_MFD_OFFSET; + mfi = (reg & CCM_MPCTL0_MFI_MASK) >> CCM_MPCTL0_MFI_OFFSET; + mfn = (reg & CCM_MPCTL0_MFN_MASK) >> CCM_MPCTL0_MFN_OFFSET; + + mfi = (mfi <= 5) ? 5 : mfi; + temp = 2LL * ref_clk * mfn; + do_div(temp, mfd + 1); + temp = 2LL * ref_clk * mfi + temp; + do_div(temp, pdf + 1); + + return (unsigned long)temp; +} + +static struct clk mpll_clk = { + .parent = &ckih_clk, + .get_rate = get_mpll_clk, +}; + +static unsigned long _clk_fclk_get_rate(struct clk *clk) +{ + unsigned long parent_rate; + u32 div; + + div = (CSCR() & CCM_CSCR_PRESC_MASK) >> CCM_CSCR_PRESC_OFFSET; + parent_rate = clk_get_rate(clk->parent); + + return parent_rate / (div+1); +} + +static struct clk fclk_clk = { + .parent = &mpll_clk, + .get_rate = _clk_fclk_get_rate +}; + +static unsigned long get_spll_clk(struct clk *clk) +{ + uint32_t reg; + unsigned long ref_clk; + unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0; + unsigned long long temp; + + ref_clk = clk_get_rate(clk->parent); + + reg = __raw_readl(CCM_SPCTL0); + pdf = (reg & CCM_SPCTL0_PD_MASK) >> CCM_SPCTL0_PD_OFFSET; + mfd = (reg & CCM_SPCTL0_MFD_MASK) >> CCM_SPCTL0_MFD_OFFSET; + mfi = (reg & CCM_SPCTL0_MFI_MASK) >> CCM_SPCTL0_MFI_OFFSET; + mfn = (reg & CCM_SPCTL0_MFN_MASK) >> CCM_SPCTL0_MFN_OFFSET; + + mfi = (mfi <= 5) ? 5 : mfi; + temp = 2LL * ref_clk * mfn; + do_div(temp, mfd + 1); + temp = 2LL * ref_clk * mfi + temp; + do_div(temp, pdf + 1); + + return (unsigned long)temp; +} + +static struct clk spll_clk = { + .parent = &ckih_clk, + .get_rate = get_spll_clk, + .enable = _clk_spll_enable, + .disable = _clk_spll_disable, +}; + +static unsigned long get_hclk_clk(struct clk *clk) +{ + unsigned long rate; + unsigned long bclk_pdf; + + bclk_pdf = (CSCR() & CCM_CSCR_BCLK_MASK) + >> CCM_CSCR_BCLK_OFFSET; + + rate = clk_get_rate(clk->parent); + return rate / (bclk_pdf + 1); +} + +static struct clk hclk_clk = { + .parent = &fclk_clk, + .get_rate = get_hclk_clk, +}; + +static unsigned long get_ipg_clk(struct clk *clk) +{ + unsigned long rate; + unsigned long ipg_pdf; + + ipg_pdf = (CSCR() & CCM_CSCR_IPDIV) >> CCM_CSCR_IPDIV_OFFSET; + + rate = clk_get_rate(clk->parent); + return rate / (ipg_pdf + 1); +} + +static struct clk ipg_clk = { + .parent = &hclk_clk, + .get_rate = get_ipg_clk, +}; + +static unsigned long _clk_perclkx_recalc(struct clk *clk) +{ + unsigned long perclk_pdf; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + if (clk->id < 0 || clk->id > 3) + return 0; + + perclk_pdf = (PCDR1() >> (clk->id << 3)) & CCM_PCDR1_PERDIV1_MASK; + + return parent_rate / (perclk_pdf + 1); +} + +static struct clk per_clk[] = { + { + .id = 0, + .parent = &mpll_clk, + .get_rate = _clk_perclkx_recalc, + }, { + .id = 1, + .parent = &mpll_clk, + .get_rate = _clk_perclkx_recalc, + }, { + .id = 2, + .parent = &mpll_clk, + .round_rate = _clk_perclkx_round_rate, + .set_rate = _clk_perclkx_set_rate, + .get_rate = _clk_perclkx_recalc, + /* Enable/Disable done via lcd_clkc[1] */ + }, { + .id = 3, + .parent = &mpll_clk, + .round_rate = _clk_perclkx_round_rate, + .set_rate = _clk_perclkx_set_rate, + .get_rate = _clk_perclkx_recalc, + /* Enable/Disable done via csi_clk[1] */ + }, +}; + +static struct clk uart_ipg_clk[]; + +static struct clk uart_clk[] = { + { + .id = 0, + .parent = &per_clk[0], + .secondary = &uart_ipg_clk[0], + }, { + .id = 1, + .parent = &per_clk[0], + .secondary = &uart_ipg_clk[1], + }, { + .id = 2, + .parent = &per_clk[0], + .secondary = &uart_ipg_clk[2], + }, { + .id = 3, + .parent = &per_clk[0], + .secondary = &uart_ipg_clk[3], + }, +}; + +static struct clk uart_ipg_clk[] = { + { + .id = 0, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_UART1_REG, + .enable_shift = CCM_PCCR_UART1_OFFSET, + .disable = _clk_disable, + }, { + .id = 1, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_UART2_REG, + .enable_shift = CCM_PCCR_UART2_OFFSET, + .disable = _clk_disable, + }, { + .id = 2, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_UART3_REG, + .enable_shift = CCM_PCCR_UART3_OFFSET, + .disable = _clk_disable, + }, { + .id = 3, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_UART4_REG, + .enable_shift = CCM_PCCR_UART4_OFFSET, + .disable = _clk_disable, + }, +}; + +static struct clk gpt_ipg_clk[]; + +static struct clk gpt_clk[] = { + { + .id = 0, + .parent = &per_clk[0], + .secondary = &gpt_ipg_clk[0], + }, { + .id = 1, + .parent = &per_clk[0], + .secondary = &gpt_ipg_clk[1], + }, { + .id = 2, + .parent = &per_clk[0], + .secondary = &gpt_ipg_clk[2], + }, +}; + +static struct clk gpt_ipg_clk[] = { + { + .id = 0, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_GPT1_REG, + .enable_shift = CCM_PCCR_GPT1_OFFSET, + .disable = _clk_disable, + }, { + .id = 1, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_GPT2_REG, + .enable_shift = CCM_PCCR_GPT2_OFFSET, + .disable = _clk_disable, + }, { + .id = 2, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_GPT3_REG, + .enable_shift = CCM_PCCR_GPT3_OFFSET, + .disable = _clk_disable, + }, +}; + +static struct clk pwm_clk[] = { + { + .parent = &per_clk[0], + .secondary = &pwm_clk[1], + }, { + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_PWM_REG, + .enable_shift = CCM_PCCR_PWM_OFFSET, + .disable = _clk_disable, + }, +}; + +static struct clk sdhc_ipg_clk[]; + +static struct clk sdhc_clk[] = { + { + .id = 0, + .parent = &per_clk[1], + .secondary = &sdhc_ipg_clk[0], + }, { + .id = 1, + .parent = &per_clk[1], + .secondary = &sdhc_ipg_clk[1], + }, +}; + +static struct clk sdhc_ipg_clk[] = { + { + .id = 0, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_SDHC1_REG, + .enable_shift = CCM_PCCR_SDHC1_OFFSET, + .disable = _clk_disable, + }, { + .id = 1, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_SDHC2_REG, + .enable_shift = CCM_PCCR_SDHC2_OFFSET, + .disable = _clk_disable, + }, +}; + +static struct clk cspi_ipg_clk[]; + +static struct clk cspi_clk[] = { + { + .id = 0, + .parent = &per_clk[1], + .secondary = &cspi_ipg_clk[0], + }, { + .id = 1, + .parent = &per_clk[1], + .secondary = &cspi_ipg_clk[1], + }, { + .id = 2, + .parent = &per_clk[1], + .secondary = &cspi_ipg_clk[2], + }, +}; + +static struct clk cspi_ipg_clk[] = { + { + .id = 0, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_CSPI1_REG, + .enable_shift = CCM_PCCR_CSPI1_OFFSET, + .disable = _clk_disable, + }, { + .id = 1, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_CSPI2_REG, + .enable_shift = CCM_PCCR_CSPI2_OFFSET, + .disable = _clk_disable, + }, { + .id = 3, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_CSPI3_REG, + .enable_shift = CCM_PCCR_CSPI3_OFFSET, + .disable = _clk_disable, + }, +}; + +static struct clk lcdc_clk[] = { + { + .parent = &per_clk[2], + .secondary = &lcdc_clk[1], + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, + }, { + .parent = &ipg_clk, + .secondary = &lcdc_clk[2], + .enable = _clk_enable, + .enable_reg = CCM_PCCR_LCDC_REG, + .enable_shift = CCM_PCCR_LCDC_OFFSET, + .disable = _clk_disable, + }, { + .parent = &hclk_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_HCLK_LCDC_REG, + .enable_shift = CCM_PCCR_HCLK_LCDC_OFFSET, + .disable = _clk_disable, + }, +}; + +static struct clk csi_clk[] = { + { + .parent = &per_clk[3], + .secondary = &csi_clk[1], + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate, + }, { + .parent = &hclk_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_HCLK_CSI_REG, + .enable_shift = CCM_PCCR_HCLK_CSI_OFFSET, + .disable = _clk_disable, + }, +}; + +static struct clk usb_clk[] = { + { + .parent = &spll_clk, + .get_rate = _clk_usb_recalc, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_USBOTG_REG, + .enable_shift = CCM_PCCR_USBOTG_OFFSET, + .disable = _clk_disable, + }, { + .parent = &hclk_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_HCLK_USBOTG_REG, + .enable_shift = CCM_PCCR_HCLK_USBOTG_OFFSET, + .disable = _clk_disable, + } +}; + +static struct clk ssi_ipg_clk[]; + +static struct clk ssi_clk[] = { + { + .id = 0, + .parent = &mpll_clk, + .secondary = &ssi_ipg_clk[0], + .get_rate = _clk_ssi1_recalc, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_SSI1_BAUD_REG, + .enable_shift = CCM_PCCR_SSI1_BAUD_OFFSET, + .disable = _clk_disable, + }, { + .id = 1, + .parent = &mpll_clk, + .secondary = &ssi_ipg_clk[1], + .get_rate = _clk_ssi2_recalc, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_SSI2_BAUD_REG, + .enable_shift = CCM_PCCR_SSI2_BAUD_OFFSET, + .disable = _clk_disable, + }, +}; + +static struct clk ssi_ipg_clk[] = { + { + .id = 0, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_SSI1_REG, + .enable_shift = CCM_PCCR_SSI1_IPG_OFFSET, + .disable = _clk_disable, + }, { + .id = 1, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_SSI2_REG, + .enable_shift = CCM_PCCR_SSI2_IPG_OFFSET, + .disable = _clk_disable, + }, +}; + + +static struct clk nfc_clk = { + .parent = &fclk_clk, + .get_rate = _clk_nfc_recalc, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_NFC_REG, + .enable_shift = CCM_PCCR_NFC_OFFSET, + .disable = _clk_disable, +}; + +static struct clk dma_clk[] = { + { + .parent = &hclk_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_DMA_REG, + .enable_shift = CCM_PCCR_DMA_OFFSET, + .disable = _clk_disable, + .secondary = &dma_clk[1], + }, { + .enable = _clk_enable, + .enable_reg = CCM_PCCR_HCLK_DMA_REG, + .enable_shift = CCM_PCCR_HCLK_DMA_OFFSET, + .disable = _clk_disable, + }, +}; + +static struct clk brom_clk = { + .parent = &hclk_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_HCLK_BROM_REG, + .enable_shift = CCM_PCCR_HCLK_BROM_OFFSET, + .disable = _clk_disable, +}; + +static struct clk emma_clk[] = { + { + .parent = &hclk_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_EMMA_REG, + .enable_shift = CCM_PCCR_EMMA_OFFSET, + .disable = _clk_disable, + .secondary = &emma_clk[1], + }, { + .enable = _clk_enable, + .enable_reg = CCM_PCCR_HCLK_EMMA_REG, + .enable_shift = CCM_PCCR_HCLK_EMMA_OFFSET, + .disable = _clk_disable, + } +}; + +static struct clk slcdc_clk[] = { + { + .parent = &hclk_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_SLCDC_REG, + .enable_shift = CCM_PCCR_SLCDC_OFFSET, + .disable = _clk_disable, + .secondary = &slcdc_clk[1], + }, { + .enable = _clk_enable, + .enable_reg = CCM_PCCR_HCLK_SLCDC_REG, + .enable_shift = CCM_PCCR_HCLK_SLCDC_OFFSET, + .disable = _clk_disable, + } +}; + +static struct clk wdog_clk = { + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_WDT_REG, + .enable_shift = CCM_PCCR_WDT_OFFSET, + .disable = _clk_disable, +}; + +static struct clk gpio_clk = { + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_GPIO_REG, + .enable_shift = CCM_PCCR_GPIO_OFFSET, + .disable = _clk_disable, +}; + +static struct clk i2c_clk = { + .id = 0, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_I2C1_REG, + .enable_shift = CCM_PCCR_I2C1_OFFSET, + .disable = _clk_disable, +}; + +static struct clk kpp_clk = { + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_KPP_REG, + .enable_shift = CCM_PCCR_KPP_OFFSET, + .disable = _clk_disable, +}; + +static struct clk owire_clk = { + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_OWIRE_REG, + .enable_shift = CCM_PCCR_OWIRE_OFFSET, + .disable = _clk_disable, +}; + +static struct clk rtc_clk = { + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR_RTC_REG, + .enable_shift = CCM_PCCR_RTC_OFFSET, + .disable = _clk_disable, +}; + +static unsigned long _clk_clko_round_rate(struct clk *clk, unsigned long rate) +{ + u32 div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + div = parent_rate / rate; + if (parent_rate % rate) + div++; + + if (div > 8) + div = 8; + + return parent_rate / div; +} + +static int _clk_clko_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg; + u32 div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + + if (div > 8 || div < 1 || ((parent_rate / div) != rate)) + return -EINVAL; + div--; + + reg = __raw_readl(CCM_PCDR0); + + if (clk->parent == &usb_clk[0]) { + reg &= ~CCM_PCDR0_48MDIV_MASK; + reg |= div << CCM_PCDR0_48MDIV_OFFSET; + } + __raw_writel(reg, CCM_PCDR0); + + return 0; +} + +static unsigned long _clk_clko_recalc(struct clk *clk) +{ + u32 div = 0; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + if (clk->parent == &usb_clk[0]) /* 48M */ + div = __raw_readl(CCM_PCDR0) & CCM_PCDR0_48MDIV_MASK + >> CCM_PCDR0_48MDIV_OFFSET; + div++; + + return parent_rate / div; +} + +static struct clk clko_clk; + +static int _clk_clko_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(CCM_CCSR) & ~CCM_CCSR_CLKOSEL_MASK; + + if (parent == &ckil_clk) + reg |= 0 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &fpm_clk) + reg |= 1 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &ckih_clk) + reg |= 2 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == mpll_clk.parent) + reg |= 3 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == spll_clk.parent) + reg |= 4 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &mpll_clk) + reg |= 5 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &spll_clk) + reg |= 6 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &fclk_clk) + reg |= 7 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &hclk_clk) + reg |= 8 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &ipg_clk) + reg |= 9 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &per_clk[0]) + reg |= 0xA << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &per_clk[1]) + reg |= 0xB << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &per_clk[2]) + reg |= 0xC << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &per_clk[3]) + reg |= 0xD << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &ssi_clk[0]) + reg |= 0xE << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &ssi_clk[1]) + reg |= 0xF << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &nfc_clk) + reg |= 0x10 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &usb_clk[0]) + reg |= 0x14 << CCM_CCSR_CLKOSEL_OFFSET; + else if (parent == &clko_clk) + reg |= 0x15 << CCM_CCSR_CLKOSEL_OFFSET; + else + return -EINVAL; + + __raw_writel(reg, CCM_CCSR); + + return 0; +} + +static struct clk clko_clk = { + .get_rate = _clk_clko_recalc, + .set_rate = _clk_clko_set_rate, + .round_rate = _clk_clko_round_rate, + .set_parent = _clk_clko_set_parent, +}; + + +#define _REGISTER_CLOCK(d, n, c) \ + { \ + .dev_id = d, \ + .con_id = n, \ + .clk = &c, \ + }, +static struct clk_lookup lookups[] __initdata = { +/* It's unlikely that any driver wants one of them directly: + _REGISTER_CLOCK(NULL, "ckih", ckih_clk) + _REGISTER_CLOCK(NULL, "ckil", ckil_clk) + _REGISTER_CLOCK(NULL, "fpm", fpm_clk) + _REGISTER_CLOCK(NULL, "mpll", mpll_clk) + _REGISTER_CLOCK(NULL, "spll", spll_clk) + _REGISTER_CLOCK(NULL, "fclk", fclk_clk) + _REGISTER_CLOCK(NULL, "hclk", hclk_clk) + _REGISTER_CLOCK(NULL, "ipg", ipg_clk) +*/ + _REGISTER_CLOCK(NULL, "perclk1", per_clk[0]) + _REGISTER_CLOCK(NULL, "perclk2", per_clk[1]) + _REGISTER_CLOCK(NULL, "perclk3", per_clk[2]) + _REGISTER_CLOCK(NULL, "perclk4", per_clk[3]) + _REGISTER_CLOCK(NULL, "clko", clko_clk) + _REGISTER_CLOCK("imx-uart.0", NULL, uart_clk[0]) + _REGISTER_CLOCK("imx-uart.1", NULL, uart_clk[1]) + _REGISTER_CLOCK("imx-uart.2", NULL, uart_clk[2]) + _REGISTER_CLOCK("imx-uart.3", NULL, uart_clk[3]) + _REGISTER_CLOCK(NULL, "gpt1", gpt_clk[0]) + _REGISTER_CLOCK(NULL, "gpt1", gpt_clk[1]) + _REGISTER_CLOCK(NULL, "gpt1", gpt_clk[2]) + _REGISTER_CLOCK(NULL, "pwm", pwm_clk[0]) + _REGISTER_CLOCK(NULL, "sdhc1", sdhc_clk[0]) + _REGISTER_CLOCK(NULL, "sdhc2", sdhc_clk[1]) + _REGISTER_CLOCK(NULL, "cspi1", cspi_clk[0]) + _REGISTER_CLOCK(NULL, "cspi2", cspi_clk[1]) + _REGISTER_CLOCK(NULL, "cspi3", cspi_clk[2]) + _REGISTER_CLOCK(NULL, "lcdc", lcdc_clk[0]) + _REGISTER_CLOCK(NULL, "csi", csi_clk[0]) + _REGISTER_CLOCK(NULL, "usb", usb_clk[0]) + _REGISTER_CLOCK(NULL, "ssi1", ssi_clk[0]) + _REGISTER_CLOCK(NULL, "ssi2", ssi_clk[1]) + _REGISTER_CLOCK(NULL, "nfc", nfc_clk) + _REGISTER_CLOCK(NULL, "dma", dma_clk[0]) + _REGISTER_CLOCK(NULL, "brom", brom_clk) + _REGISTER_CLOCK(NULL, "emma", emma_clk[0]) + _REGISTER_CLOCK(NULL, "slcdc", slcdc_clk[0]) + _REGISTER_CLOCK(NULL, "wdog", wdog_clk) + _REGISTER_CLOCK(NULL, "gpio", gpio_clk) + _REGISTER_CLOCK(NULL, "i2c", i2c_clk) + _REGISTER_CLOCK("mxc-keypad", NULL, kpp_clk) + _REGISTER_CLOCK(NULL, "owire", owire_clk) + _REGISTER_CLOCK(NULL, "rtc", rtc_clk) +}; + +/* + * must be called very early to get information about the + * available clock rate when the timer framework starts + */ +int __init mx21_clocks_init(unsigned long lref, unsigned long href) +{ + int i; + u32 cscr; + + external_low_reference = lref; + external_high_reference = href; + + /* detect clock reference for both system PLL */ + cscr = CSCR(); + if (cscr & CCM_CSCR_MCU) + mpll_clk.parent = &ckih_clk; + else + mpll_clk.parent = &fpm_clk; + + if (cscr & CCM_CSCR_SP) + spll_clk.parent = &ckih_clk; + else + spll_clk.parent = &fpm_clk; + + for (i = 0; i < ARRAY_SIZE(lookups); i++) + clkdev_add(&lookups[i]); + + /* Turn off all clock gates */ + __raw_writel(0, CCM_PCCR0); + __raw_writel(CCM_PCCR_GPT1_MASK, CCM_PCCR1); + + /* This turns of the serial PLL as well */ + spll_clk.disable(&spll_clk); + + /* This will propagate to all children and init all the clock rates. */ + clk_enable(&per_clk[0]); + clk_enable(&gpio_clk); + +#ifdef CONFIG_DEBUG_LL_CONSOLE + clk_enable(&uart_clk[0]); +#endif + + mxc_timer_init(&gpt_clk[0]); + return 0; +} diff --git a/arch/arm/mach-mx2/crm_regs.h b/arch/arm/mach-mx2/crm_regs.h new file mode 100644 index 00000000000..749de76b3f9 --- /dev/null +++ b/arch/arm/mach-mx2/crm_regs.h @@ -0,0 +1,258 @@ +/* + * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2008 Juergen Beisert, kernel@pengutronix.de + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef __ARCH_ARM_MACH_MX2_CRM_REGS_H__ +#define __ARCH_ARM_MACH_MX2_CRM_REGS_H__ + +#include + +/* Register offsets */ +#define CCM_CSCR (IO_ADDRESS(CCM_BASE_ADDR) + 0x0) +#define CCM_MPCTL0 (IO_ADDRESS(CCM_BASE_ADDR) + 0x4) +#define CCM_MPCTL1 (IO_ADDRESS(CCM_BASE_ADDR) + 0x8) +#define CCM_SPCTL0 (IO_ADDRESS(CCM_BASE_ADDR) + 0xC) +#define CCM_SPCTL1 (IO_ADDRESS(CCM_BASE_ADDR) + 0x10) +#define CCM_OSC26MCTL (IO_ADDRESS(CCM_BASE_ADDR) + 0x14) +#define CCM_PCDR0 (IO_ADDRESS(CCM_BASE_ADDR) + 0x18) +#define CCM_PCDR1 (IO_ADDRESS(CCM_BASE_ADDR) + 0x1c) +#define CCM_PCCR0 (IO_ADDRESS(CCM_BASE_ADDR) + 0x20) +#define CCM_PCCR1 (IO_ADDRESS(CCM_BASE_ADDR) + 0x24) +#define CCM_CCSR (IO_ADDRESS(CCM_BASE_ADDR) + 0x28) +#define CCM_PMCTL (IO_ADDRESS(CCM_BASE_ADDR) + 0x2c) +#define CCM_PMCOUNT (IO_ADDRESS(CCM_BASE_ADDR) + 0x30) +#define CCM_WKGDCTL (IO_ADDRESS(CCM_BASE_ADDR) + 0x34) + +#define CCM_CSCR_PRESC_OFFSET 29 +#define CCM_CSCR_PRESC_MASK (0x7 << CCM_CSCR_PRESC_OFFSET) + +#define CCM_CSCR_USB_OFFSET 26 +#define CCM_CSCR_USB_MASK (0x7 << CCM_CSCR_USB_OFFSET) +#define CCM_CSCR_SD_OFFSET 24 +#define CCM_CSCR_SD_MASK (0x3 << CCM_CSCR_SD_OFFSET) +#define CCM_CSCR_SPLLRES (1 << 22) +#define CCM_CSCR_MPLLRES (1 << 21) +#define CCM_CSCR_SSI2_OFFSET 20 +#define CCM_CSCR_SSI2 (1 << CCM_CSCR_SSI2_OFFSET) +#define CCM_CSCR_SSI1_OFFSET 19 +#define CCM_CSCR_SSI1 (1 << CCM_CSCR_SSI1_OFFSET) +#define CCM_CSCR_FIR_OFFSET 18 +#define CCM_CSCR_FIR (1 << CCM_CSCR_FIR_OFFSET) +#define CCM_CSCR_SP (1 << 17) +#define CCM_CSCR_MCU (1 << 16) +#define CCM_CSCR_BCLK_OFFSET 10 +#define CCM_CSCR_BCLK_MASK (0xf << CCM_CSCR_BCLK_OFFSET) +#define CCM_CSCR_IPDIV_OFFSET 9 +#define CCM_CSCR_IPDIV (1 << CCM_CSCR_IPDIV_OFFSET) + +#define CCM_CSCR_OSC26MDIV (1 << 4) +#define CCM_CSCR_OSC26M (1 << 3) +#define CCM_CSCR_FPM (1 << 2) +#define CCM_CSCR_SPEN (1 << 1) +#define CCM_CSCR_MPEN 1 + + + +#define CCM_MPCTL0_CPLM (1 << 31) +#define CCM_MPCTL0_PD_OFFSET 26 +#define CCM_MPCTL0_PD_MASK (0xf << 26) +#define CCM_MPCTL0_MFD_OFFSET 16 +#define CCM_MPCTL0_MFD_MASK (0x3ff << 16) +#define CCM_MPCTL0_MFI_OFFSET 10 +#define CCM_MPCTL0_MFI_MASK (0xf << 10) +#define CCM_MPCTL0_MFN_OFFSET 0 +#define CCM_MPCTL0_MFN_MASK 0x3ff + +#define CCM_MPCTL1_LF (1 << 15) +#define CCM_MPCTL1_BRMO (1 << 6) + +#define CCM_SPCTL0_CPLM (1 << 31) +#define CCM_SPCTL0_PD_OFFSET 26 +#define CCM_SPCTL0_PD_MASK (0xf << 26) +#define CCM_SPCTL0_MFD_OFFSET 16 +#define CCM_SPCTL0_MFD_MASK (0x3ff << 16) +#define CCM_SPCTL0_MFI_OFFSET 10 +#define CCM_SPCTL0_MFI_MASK (0xf << 10) +#define CCM_SPCTL0_MFN_OFFSET 0 +#define CCM_SPCTL0_MFN_MASK 0x3ff + +#define CCM_SPCTL1_LF (1 << 15) +#define CCM_SPCTL1_BRMO (1 << 6) + +#define CCM_OSC26MCTL_PEAK_OFFSET 16 +#define CCM_OSC26MCTL_PEAK_MASK (0x3 << 16) +#define CCM_OSC26MCTL_AGC_OFFSET 8 +#define CCM_OSC26MCTL_AGC_MASK (0x3f << 8) +#define CCM_OSC26MCTL_ANATEST_OFFSET 0 +#define CCM_OSC26MCTL_ANATEST_MASK 0x3f + +#define CCM_PCDR0_SSI2BAUDDIV_OFFSET 26 +#define CCM_PCDR0_SSI2BAUDDIV_MASK (0x3f << 26) +#define CCM_PCDR0_SSI1BAUDDIV_OFFSET 16 +#define CCM_PCDR0_SSI1BAUDDIV_MASK (0x3f << 16) +#define CCM_PCDR0_NFCDIV_OFFSET 12 +#define CCM_PCDR0_NFCDIV_MASK (0xf << 12) +#define CCM_PCDR0_48MDIV_OFFSET 5 +#define CCM_PCDR0_48MDIV_MASK (0x7 << CCM_PCDR0_48MDIV_OFFSET) +#define CCM_PCDR0_FIRIDIV_OFFSET 0 +#define CCM_PCDR0_FIRIDIV_MASK 0x1f +#define CCM_PCDR1_PERDIV4_OFFSET 24 +#define CCM_PCDR1_PERDIV4_MASK (0x3f << 24) +#define CCM_PCDR1_PERDIV3_OFFSET 16 +#define CCM_PCDR1_PERDIV3_MASK (0x3f << 16) +#define CCM_PCDR1_PERDIV2_OFFSET 8 +#define CCM_PCDR1_PERDIV2_MASK (0x3f << 8) +#define CCM_PCDR1_PERDIV1_OFFSET 0 +#define CCM_PCDR1_PERDIV1_MASK 0x3f + +#define CCM_PCCR_HCLK_CSI_OFFSET 31 +#define CCM_PCCR_HCLK_CSI_REG CCM_PCCR0 +#define CCM_PCCR_HCLK_DMA_OFFSET 30 +#define CCM_PCCR_HCLK_DMA_REG CCM_PCCR0 +#define CCM_PCCR_HCLK_BROM_OFFSET 28 +#define CCM_PCCR_HCLK_BROM_REG CCM_PCCR0 +#define CCM_PCCR_HCLK_EMMA_OFFSET 27 +#define CCM_PCCR_HCLK_EMMA_REG CCM_PCCR0 +#define CCM_PCCR_HCLK_LCDC_OFFSET 26 +#define CCM_PCCR_HCLK_LCDC_REG CCM_PCCR0 +#define CCM_PCCR_HCLK_SLCDC_OFFSET 25 +#define CCM_PCCR_HCLK_SLCDC_REG CCM_PCCR0 +#define CCM_PCCR_HCLK_USBOTG_OFFSET 24 +#define CCM_PCCR_HCLK_USBOTG_REG CCM_PCCR0 +#define CCM_PCCR_HCLK_BMI_OFFSET 23 +#define CCM_PCCR_BMI_MASK (1 << CCM_PCCR_BMI_MASK) +#define CCM_PCCR_HCLK_BMI_REG CCM_PCCR0 +#define CCM_PCCR_PERCLK4_OFFSET 22 +#define CCM_PCCR_PERCLK4_REG CCM_PCCR0 +#define CCM_PCCR_SLCDC_OFFSET 21 +#define CCM_PCCR_SLCDC_REG CCM_PCCR0 +#define CCM_PCCR_FIRI_BAUD_OFFSET 20 +#define CCM_PCCR_FIRI_BAUD_MASK (1 << CCM_PCCR_FIRI_BAUD_MASK) +#define CCM_PCCR_FIRI_BAUD_REG CCM_PCCR0 +#define CCM_PCCR_NFC_OFFSET 19 +#define CCM_PCCR_NFC_REG CCM_PCCR0 +#define CCM_PCCR_LCDC_OFFSET 18 +#define CCM_PCCR_LCDC_REG CCM_PCCR0 +#define CCM_PCCR_SSI1_BAUD_OFFSET 17 +#define CCM_PCCR_SSI1_BAUD_REG CCM_PCCR0 +#define CCM_PCCR_SSI2_BAUD_OFFSET 16 +#define CCM_PCCR_SSI2_BAUD_REG CCM_PCCR0 +#define CCM_PCCR_EMMA_OFFSET 15 +#define CCM_PCCR_EMMA_REG CCM_PCCR0 +#define CCM_PCCR_USBOTG_OFFSET 14 +#define CCM_PCCR_USBOTG_REG CCM_PCCR0 +#define CCM_PCCR_DMA_OFFSET 13 +#define CCM_PCCR_DMA_REG CCM_PCCR0 +#define CCM_PCCR_I2C1_OFFSET 12 +#define CCM_PCCR_I2C1_REG CCM_PCCR0 +#define CCM_PCCR_GPIO_OFFSET 11 +#define CCM_PCCR_GPIO_REG CCM_PCCR0 +#define CCM_PCCR_SDHC2_OFFSET 10 +#define CCM_PCCR_SDHC2_REG CCM_PCCR0 +#define CCM_PCCR_SDHC1_OFFSET 9 +#define CCM_PCCR_SDHC1_REG CCM_PCCR0 +#define CCM_PCCR_FIRI_OFFSET 8 +#define CCM_PCCR_FIRI_MASK (1 << CCM_PCCR_BAUD_MASK) +#define CCM_PCCR_FIRI_REG CCM_PCCR0 +#define CCM_PCCR_SSI2_IPG_OFFSET 7 +#define CCM_PCCR_SSI2_REG CCM_PCCR0 +#define CCM_PCCR_SSI1_IPG_OFFSET 6 +#define CCM_PCCR_SSI1_REG CCM_PCCR0 +#define CCM_PCCR_CSPI2_OFFSET 5 +#define CCM_PCCR_CSPI2_REG CCM_PCCR0 +#define CCM_PCCR_CSPI1_OFFSET 4 +#define CCM_PCCR_CSPI1_REG CCM_PCCR0 +#define CCM_PCCR_UART4_OFFSET 3 +#define CCM_PCCR_UART4_REG CCM_PCCR0 +#define CCM_PCCR_UART3_OFFSET 2 +#define CCM_PCCR_UART3_REG CCM_PCCR0 +#define CCM_PCCR_UART2_OFFSET 1 +#define CCM_PCCR_UART2_REG CCM_PCCR0 +#define CCM_PCCR_UART1_OFFSET 0 +#define CCM_PCCR_UART1_REG CCM_PCCR0 + +#define CCM_PCCR_OWIRE_OFFSET 31 +#define CCM_PCCR_OWIRE_REG CCM_PCCR1 +#define CCM_PCCR_KPP_OFFSET 30 +#define CCM_PCCR_KPP_REG CCM_PCCR1 +#define CCM_PCCR_RTC_OFFSET 29 +#define CCM_PCCR_RTC_REG CCM_PCCR1 +#define CCM_PCCR_PWM_OFFSET 28 +#define CCM_PCCR_PWM_REG CCM_PCCR1 +#define CCM_PCCR_GPT3_OFFSET 27 +#define CCM_PCCR_GPT3_REG CCM_PCCR1 +#define CCM_PCCR_GPT2_OFFSET 26 +#define CCM_PCCR_GPT2_REG CCM_PCCR1 +#define CCM_PCCR_GPT1_OFFSET 25 +#define CCM_PCCR_GPT1_REG CCM_PCCR1 +#define CCM_PCCR_WDT_OFFSET 24 +#define CCM_PCCR_WDT_REG CCM_PCCR1 +#define CCM_PCCR_CSPI3_OFFSET 23 +#define CCM_PCCR_CSPI3_REG CCM_PCCR1 + +#define CCM_PCCR_CSPI1_MASK (1 << CCM_PCCR_CSPI1_OFFSET) +#define CCM_PCCR_CSPI2_MASK (1 << CCM_PCCR_CSPI2_OFFSET) +#define CCM_PCCR_CSPI3_MASK (1 << CCM_PCCR_CSPI3_OFFSET) +#define CCM_PCCR_DMA_MASK (1 << CCM_PCCR_DMA_OFFSET) +#define CCM_PCCR_EMMA_MASK (1 << CCM_PCCR_EMMA_OFFSET) +#define CCM_PCCR_GPIO_MASK (1 << CCM_PCCR_GPIO_OFFSET) +#define CCM_PCCR_GPT1_MASK (1 << CCM_PCCR_GPT1_OFFSET) +#define CCM_PCCR_GPT2_MASK (1 << CCM_PCCR_GPT2_OFFSET) +#define CCM_PCCR_GPT3_MASK (1 << CCM_PCCR_GPT3_OFFSET) +#define CCM_PCCR_HCLK_BROM_MASK (1 << CCM_PCCR_HCLK_BROM_OFFSET) +#define CCM_PCCR_HCLK_CSI_MASK (1 << CCM_PCCR_HCLK_CSI_OFFSET) +#define CCM_PCCR_HCLK_DMA_MASK (1 << CCM_PCCR_HCLK_DMA_OFFSET) +#define CCM_PCCR_HCLK_EMMA_MASK (1 << CCM_PCCR_HCLK_EMMA_OFFSET) +#define CCM_PCCR_HCLK_LCDC_MASK (1 << CCM_PCCR_HCLK_LCDC_OFFSET) +#define CCM_PCCR_HCLK_SLCDC_MASK (1 << CCM_PCCR_HCLK_SLCDC_OFFSET) +#define CCM_PCCR_HCLK_USBOTG_MASK (1 << CCM_PCCR_HCLK_USBOTG_OFFSET) +#define CCM_PCCR_I2C1_MASK (1 << CCM_PCCR_I2C1_OFFSET) +#define CCM_PCCR_KPP_MASK (1 << CCM_PCCR_KPP_OFFSET) +#define CCM_PCCR_LCDC_MASK (1 << CCM_PCCR_LCDC_OFFSET) +#define CCM_PCCR_NFC_MASK (1 << CCM_PCCR_NFC_OFFSET) +#define CCM_PCCR_OWIRE_MASK (1 << CCM_PCCR_OWIRE_OFFSET) +#define CCM_PCCR_PERCLK4_MASK (1 << CCM_PCCR_PERCLK4_OFFSET) +#define CCM_PCCR_PWM_MASK (1 << CCM_PCCR_PWM_OFFSET) +#define CCM_PCCR_RTC_MASK (1 << CCM_PCCR_RTC_OFFSET) +#define CCM_PCCR_SDHC1_MASK (1 << CCM_PCCR_SDHC1_OFFSET) +#define CCM_PCCR_SDHC2_MASK (1 << CCM_PCCR_SDHC2_OFFSET) +#define CCM_PCCR_SLCDC_MASK (1 << CCM_PCCR_SLCDC_OFFSET) +#define CCM_PCCR_SSI1_BAUD_MASK (1 << CCM_PCCR_SSI1_BAUD_OFFSET) +#define CCM_PCCR_SSI1_IPG_MASK (1 << CCM_PCCR_SSI1_IPG_OFFSET) +#define CCM_PCCR_SSI2_BAUD_MASK (1 << CCM_PCCR_SSI2_BAUD_OFFSET) +#define CCM_PCCR_SSI2_IPG_MASK (1 << CCM_PCCR_SSI2_IPG_OFFSET) +#define CCM_PCCR_UART1_MASK (1 << CCM_PCCR_UART1_OFFSET) +#define CCM_PCCR_UART2_MASK (1 << CCM_PCCR_UART2_OFFSET) +#define CCM_PCCR_UART3_MASK (1 << CCM_PCCR_UART3_OFFSET) +#define CCM_PCCR_UART4_MASK (1 << CCM_PCCR_UART4_OFFSET) +#define CCM_PCCR_USBOTG_MASK (1 << CCM_PCCR_USBOTG_OFFSET) +#define CCM_PCCR_WDT_MASK (1 << CCM_PCCR_WDT_OFFSET) + + +#define CCM_CCSR_32KSR (1 << 15) + +#define CCM_CCSR_CLKMODE1 (1 << 9) +#define CCM_CCSR_CLKMODE0 (1 << 8) + +#define CCM_CCSR_CLKOSEL_OFFSET 0 +#define CCM_CCSR_CLKOSEL_MASK 0x1f + +#define SYS_FMCR 0x14 /* Functional Muxing Control Reg */ +#define SYS_CHIP_ID 0x00 /* The offset of CHIP ID register */ + +#endif /* __ARCH_ARM_MACH_MX2_CRM_REGS_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h index 2c08b8e14e3..3051eee9953 100644 --- a/arch/arm/plat-mxc/include/mach/common.h +++ b/arch/arm/plat-mxc/include/mach/common.h @@ -18,6 +18,7 @@ extern void mxc_map_io(void); extern void mxc_init_irq(void); extern void mxc_timer_init(struct clk *timer_clk); extern int mx1_clocks_init(unsigned long fref); +extern int mx21_clocks_init(unsigned long lref, unsigned long fref); extern int mx27_clocks_init(unsigned long fref); extern int mx31_clocks_init(unsigned long fref); extern int mxc_register_gpios(void); -- GitLab From e48135519bd569eed374e0e17ed5233d4105fa97 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Mon, 26 Jan 2009 16:34:56 +0100 Subject: [PATCH 3257/4982] arm/imx21: Framebuffer support for i.MX21 This patch mimicks what Martin wrote on the mailing list: * move arch/arm/mach-imx/include/mach/imxfb.h into arch/arm/mach-mxc/include/mach/imxfb.h * changes Kconfig so that CONFIG_FB_IMX is selectable * adds a platform device (copied from some pengutronix patches) Signed-off-by: Holger Schurig Signed-off-by: Sascha Hauer --- arch/arm/mach-mx2/devices.c | 33 +++++++++++++++++++ arch/arm/mach-mx2/devices.h | 2 +- .../include/mach/imxfb.h | 0 drivers/video/Kconfig | 2 +- 4 files changed, 35 insertions(+), 2 deletions(-) rename arch/arm/{mach-imx => plat-mxc}/include/mach/imxfb.h (100%) diff --git a/arch/arm/mach-mx2/devices.c b/arch/arm/mach-mx2/devices.c index 9ddd6d06105..07061e64454 100644 --- a/arch/arm/mach-mx2/devices.c +++ b/arch/arm/mach-mx2/devices.c @@ -228,6 +228,39 @@ struct platform_device mxc_nand_device = { .resource = mxc_nand_resources, }; +#ifdef CONFIG_FB_IMX +/* + * lcdc: + * - i.MX1: the basic controller + * - i.MX21: to be checked + * - i.MX27: like i.MX1, with slightly variations + */ +static struct resource mxc_fb[] = { + { + .start = LCDC_BASE_ADDR, + .end = LCDC_BASE_ADDR + 0xFFF, + .flags = IORESOURCE_MEM, + }, + { + .start = MXC_INT_LCDC, + .end = MXC_INT_LCDC, + .flags = IORESOURCE_IRQ, + } +}; + +/* mxc lcd driver */ +struct platform_device mxc_fb_device = { + .name = "imx-fb", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_fb), + .resource = mxc_fb, + .dev = { + .coherent_dma_mask = 0xFFFFFFFF, + }, +}; + +#endif + /* GPIO port description */ static struct mxc_gpio_port imx_gpio_ports[] = { [0] = { diff --git a/arch/arm/mach-mx2/devices.h b/arch/arm/mach-mx2/devices.h index 1e8cb577a64..f4cb0ce29f1 100644 --- a/arch/arm/mach-mx2/devices.h +++ b/arch/arm/mach-mx2/devices.h @@ -1,4 +1,3 @@ - extern struct platform_device mxc_gpt1; extern struct platform_device mxc_gpt2; extern struct platform_device mxc_gpt3; @@ -14,3 +13,4 @@ extern struct platform_device mxc_uart_device4; extern struct platform_device mxc_uart_device5; extern struct platform_device mxc_w1_master_device; extern struct platform_device mxc_nand_device; +extern struct platform_device mxc_fb_device; diff --git a/arch/arm/mach-imx/include/mach/imxfb.h b/arch/arm/plat-mxc/include/mach/imxfb.h similarity index 100% rename from arch/arm/mach-imx/include/mach/imxfb.h rename to arch/arm/plat-mxc/include/mach/imxfb.h diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index fb19803060c..967ac3d359a 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -397,7 +397,7 @@ config FB_SA1100 config FB_IMX tristate "Motorola i.MX LCD support" - depends on FB && ARM && ARCH_IMX + depends on FB && (ARCH_IMX || ARCH_MX2) select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT -- GitLab From 39d1dc068b61a8f36a3c1377fa52ed4901968a4f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 15 Jan 2009 16:14:27 +0000 Subject: [PATCH 3258/4982] mx31: Add device definitions for the i.MX3x I2C controllers The i.MX I2C driver has not yet been merged into mainline but it is near to that and the device defintions don't depend directly on it so we can add the devices now. Signed-off-by: Mark Brown Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/devices.c | 60 +++++++++++++++++++++++++++++++++++++ arch/arm/mach-mx3/devices.h | 3 ++ 2 files changed, 63 insertions(+) diff --git a/arch/arm/mach-mx3/devices.c b/arch/arm/mach-mx3/devices.c index f8428800f28..c48a341bccf 100644 --- a/arch/arm/mach-mx3/devices.c +++ b/arch/arm/mach-mx3/devices.c @@ -180,3 +180,63 @@ struct platform_device mxc_nand_device = { .num_resources = ARRAY_SIZE(mxc_nand_resources), .resource = mxc_nand_resources, }; + +static struct resource mxc_i2c0_resources[] = { + { + .start = I2C_BASE_ADDR, + .end = I2C_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = MXC_INT_I2C, + .end = MXC_INT_I2C, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_i2c_device0 = { + .name = "imx-i2c", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_i2c0_resources), + .resource = mxc_i2c0_resources, +}; + +static struct resource mxc_i2c1_resources[] = { + { + .start = I2C2_BASE_ADDR, + .end = I2C2_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = MXC_INT_I2C2, + .end = MXC_INT_I2C2, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_i2c_device1 = { + .name = "imx-i2c", + .id = 1, + .num_resources = ARRAY_SIZE(mxc_i2c1_resources), + .resource = mxc_i2c1_resources, +}; + +static struct resource mxc_i2c2_resources[] = { + { + .start = I2C3_BASE_ADDR, + .end = I2C3_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = MXC_INT_I2C3, + .end = MXC_INT_I2C3, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_i2c_device2 = { + .name = "imx-i2c", + .id = 2, + .num_resources = ARRAY_SIZE(mxc_i2c2_resources), + .resource = mxc_i2c2_resources, +}; diff --git a/arch/arm/mach-mx3/devices.h b/arch/arm/mach-mx3/devices.h index 9949ef4e069..077a90226a7 100644 --- a/arch/arm/mach-mx3/devices.h +++ b/arch/arm/mach-mx3/devices.h @@ -6,3 +6,6 @@ extern struct platform_device mxc_uart_device3; extern struct platform_device mxc_uart_device4; extern struct platform_device mxc_w1_master_device; extern struct platform_device mxc_nand_device; +extern struct platform_device mxc_i2c_device0; +extern struct platform_device mxc_i2c_device1; +extern struct platform_device mxc_i2c_device2; -- GitLab From 4d5f9cdacb74d35b4e435cb66443da203d8be6f0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 15 Jan 2009 16:14:28 +0000 Subject: [PATCH 3259/4982] mx31ads: Fix build for missing mx31.h Several of the macros in mx31ads.h depend on mx31.h which is no longer included in quite so many standard headers as it once was. Include it directly so we can build. Signed-off-by: Mark Brown Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/include/mach/board-mx31ads.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/plat-mxc/include/mach/board-mx31ads.h b/arch/arm/plat-mxc/include/mach/board-mx31ads.h index 451d510d08c..318c72ada13 100644 --- a/arch/arm/plat-mxc/include/mach/board-mx31ads.h +++ b/arch/arm/plat-mxc/include/mach/board-mx31ads.h @@ -11,6 +11,8 @@ #ifndef __ASM_ARCH_MXC_BOARD_MX31ADS_H__ #define __ASM_ARCH_MXC_BOARD_MX31ADS_H__ +#include + /* Base address of PBC controller */ #define PBC_BASE_ADDRESS IO_ADDRESS(CS4_BASE_ADDR) /* Offsets for the PBC Controller register */ -- GitLab From 8b785b9dfb309be8d44d655df1f370b15dda7687 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 15 Jan 2009 16:14:29 +0000 Subject: [PATCH 3260/4982] mx31ads: Make unexported data static Keeps sparse happy. Signed-off-by: Mark Brown Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/mx31ads.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-mx3/mx31ads.c b/arch/arm/mach-mx3/mx31ads.c index f913999eedf..6804fbe266e 100644 --- a/arch/arm/mach-mx3/mx31ads.c +++ b/arch/arm/mach-mx3/mx31ads.c @@ -221,13 +221,13 @@ static struct map_desc mx31ads_io_desc[] __initdata = { /*! * Set up static virtual mappings. */ -void __init mx31ads_map_io(void) +static void __init mx31ads_map_io(void) { mxc_map_io(); iotable_init(mx31ads_io_desc, ARRAY_SIZE(mx31ads_io_desc)); } -void __init mx31ads_init_irq(void) +static void __init mx31ads_init_irq(void) { mxc_init_irq(); mx31ads_init_expio(); @@ -247,7 +247,7 @@ static void __init mx31ads_timer_init(void) mx31_clocks_init(26000000); } -struct sys_timer mx31ads_timer = { +static struct sys_timer mx31ads_timer = { .init = mx31ads_timer_init, }; -- GitLab From e600eb6b0d41c3e69297137388733bd0a50aa5e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 21 Jan 2009 21:25:03 +0100 Subject: [PATCH 3261/4982] fix warning "control reaches end of non-void function" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a return 0 analogous to uart_mxc_port[0-2]_exit. Signed-off-by: Uwe Kleine-König Signed-off-by: Sascha Hauer Cc: Holger Schurig Cc: Russell King Cc: Sascha Hauer Cc: Martin Fuzzey --- arch/arm/mach-mx2/mx27ads.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-mx2/mx27ads.c b/arch/arm/mach-mx2/mx27ads.c index 4548631eb3a..a078aa52a6a 100644 --- a/arch/arm/mach-mx2/mx27ads.c +++ b/arch/arm/mach-mx2/mx27ads.c @@ -135,6 +135,7 @@ static int uart_mxc_port3_exit(struct platform_device *pdev) { mxc_gpio_release_multiple_pins(mxc_uart3_pins, ARRAY_SIZE(mxc_uart3_pins)); + return 0; } static int mxc_uart4_pins[] = { -- GitLab From 41a1d91e7e7b08a13d78e03e67dcd7634f2d5cca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 21 Jan 2009 21:25:02 +0100 Subject: [PATCH 3262/4982] remove unused static function gpio_fec_inactive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ... from both mx27ads.c and pcm038.c Signed-off-by: Uwe Kleine-König Signed-off-by: Sascha Hauer Cc: Holger Schurig Cc: Russell King Cc: Sascha Hauer Cc: Martin Fuzzey --- arch/arm/mach-mx2/mx27ads.c | 6 ------ arch/arm/mach-mx2/pcm038.c | 6 ------ 2 files changed, 12 deletions(-) diff --git a/arch/arm/mach-mx2/mx27ads.c b/arch/arm/mach-mx2/mx27ads.c index a078aa52a6a..3c967f460b3 100644 --- a/arch/arm/mach-mx2/mx27ads.c +++ b/arch/arm/mach-mx2/mx27ads.c @@ -209,12 +209,6 @@ static void gpio_fec_active(void) ARRAY_SIZE(mxc_fec_pins), "FEC"); } -static void gpio_fec_inactive(void) -{ - mxc_gpio_release_multiple_pins(mxc_fec_pins, - ARRAY_SIZE(mxc_fec_pins)); -} - static struct imxuart_platform_data uart_pdata[] = { { .init = uart_mxc_port0_init, diff --git a/arch/arm/mach-mx2/pcm038.c b/arch/arm/mach-mx2/pcm038.c index 2942d59b570..58552a01c0d 100644 --- a/arch/arm/mach-mx2/pcm038.c +++ b/arch/arm/mach-mx2/pcm038.c @@ -183,12 +183,6 @@ static void gpio_fec_active(void) ARRAY_SIZE(mxc_fec_pins), "FEC"); } -static void gpio_fec_inactive(void) -{ - mxc_gpio_release_multiple_pins(mxc_fec_pins, - ARRAY_SIZE(mxc_fec_pins)); -} - static struct mxc_nand_platform_data pcm038_nand_board_info = { .width = 1, .hw_ecc = 1, -- GitLab From b7222631c3d0fd26e6d85dd78b1d0aa10dc64929 Mon Sep 17 00:00:00 2001 From: Valentin Longchamp Date: Wed, 28 Jan 2009 15:13:50 +0100 Subject: [PATCH 3263/4982] mx31: rework of iomux support This new implemenatation avoids that two physical pins are claimed by the same driver (also with the the gpr hardware modes). The gpio kernel lib is also called when a capable gpio pin is assigned its gpio function. The mxc_iomux_mode function is still here for backward compatibility but should not be used anymore. V2: In the precendent revision, the iomux code was claiming a pin when its hardware mode was changed. This was uncorrect: when the hardware mode is changed, the pin must still be claimed through the iomux. In order to have a pin working in mode hw2, we must fist issue the mxc_iomux_set_gpr call and then the corresponding mxc_iomux_mode calls with the FUNC mode (usually done with mxc_iomux_setup_multiple_pins). The reverse calls must be done to fee the pins. Signed-off-by: Valentin Longchamp Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/iomux.c | 88 +++++++++++++++++++++- arch/arm/plat-mxc/include/mach/iomux-mx3.h | 45 +++++++++-- 2 files changed, 122 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-mx3/iomux.c b/arch/arm/mach-mx3/iomux.c index 7a5088b519a..40ffc5a664d 100644 --- a/arch/arm/mach-mx3/iomux.c +++ b/arch/arm/mach-mx3/iomux.c @@ -1,6 +1,7 @@ /* * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved. * Copyright (C) 2008 by Sascha Hauer + * Copyright (C) 2009 by Valentin Longchamp * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -21,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +40,8 @@ static DEFINE_SPINLOCK(gpio_mux_lock); #define IOMUX_REG_MASK (IOMUX_PADNUM_MASK & ~0x3) + +unsigned long mxc_pin_alloc_map[NB_PORTS * 32 / BITS_PER_LONG]; /* * set the mode for a IOMUX pin. */ @@ -50,9 +54,6 @@ int mxc_iomux_mode(unsigned int pin_mode) field = pin_mode & 0x3; mode = (pin_mode & IOMUX_MODE_MASK) >> IOMUX_MODE_SHIFT; - pr_debug("%s: reg offset = 0x%x field = %d mode = 0x%02x\n", - __func__, (pin_mode & IOMUX_REG_MASK), field, mode); - spin_lock(&gpio_mux_lock); l = __raw_readl(reg); @@ -92,6 +93,86 @@ void mxc_iomux_set_pad(enum iomux_pins pin, u32 config) } EXPORT_SYMBOL(mxc_iomux_set_pad); +/* + * setups a single pin: + * - reserves the pin so that it is not claimed by another driver + * - setups the iomux according to the configuration + * - if the pin is configured as a GPIO, we claim it through kernel gpiolib + */ +int mxc_iomux_setup_pin(const unsigned int pin, const char *label) +{ + unsigned pad = pin & IOMUX_PADNUM_MASK; + unsigned gpio; + + if (pad >= (PIN_MAX + 1)) { + printk(KERN_ERR "mxc_iomux: Attempt to request nonexistant pin %u for \"%s\"\n", + pad, label ? label : "?"); + return -EINVAL; + } + + if (test_and_set_bit(pad, mxc_pin_alloc_map)) { + printk(KERN_ERR "mxc_iomux: pin %u already used. Allocation for \"%s\" failed\n", + pad, label ? label : "?"); + return -EINVAL; + } + mxc_iomux_mode(pin); + + /* if we have a gpio, we can allocate it */ + gpio = (pin & IOMUX_GPIONUM_MASK) >> IOMUX_GPIONUM_SHIFT; + if (gpio < (GPIO_PORT_MAX + 1) * 32) + if (gpio_request(gpio, label)) + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL(mxc_iomux_setup_pin); + +int mxc_iomux_setup_multiple_pins(unsigned int *pin_list, unsigned count, + const char *label) +{ + unsigned int *p = pin_list; + int i; + int ret = -EINVAL; + + for (i = 0; i < count; i++) { + if (mxc_iomux_setup_pin(*p, label)) + goto setup_error; + p++; + } + return 0; + +setup_error: + mxc_iomux_release_multiple_pins(pin_list, i); + return ret; +} +EXPORT_SYMBOL(mxc_iomux_setup_multiple_pins); + +void mxc_iomux_release_pin(const unsigned int pin) +{ + unsigned pad = pin & IOMUX_PADNUM_MASK; + unsigned gpio; + + if (pad < (PIN_MAX + 1)) + clear_bit(pad, mxc_pin_alloc_map); + + gpio = (pin & IOMUX_GPIONUM_MASK) >> IOMUX_GPIONUM_SHIFT; + if (gpio < (GPIO_PORT_MAX + 1) * 32) + gpio_free(gpio); +} +EXPORT_SYMBOL(mxc_iomux_release_pin); + +void mxc_iomux_release_multiple_pins(unsigned int *pin_list, int count) +{ + unsigned int *p = pin_list; + int i; + + for (i = 0; i < count; i++) { + mxc_iomux_release_pin(*p); + p++; + } +} +EXPORT_SYMBOL(mxc_iomux_release_multiple_pins); + /* * This function enables/disables the general purpose function for a particular * signal. @@ -111,4 +192,3 @@ void mxc_iomux_set_gpr(enum iomux_gp_func gp, bool en) spin_unlock(&gpio_mux_lock); } EXPORT_SYMBOL(mxc_iomux_set_gpr); - diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx3.h b/arch/arm/plat-mxc/include/mach/iomux-mx3.h index c9198c0aea1..4bdc4712be1 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-mx3.h +++ b/arch/arm/plat-mxc/include/mach/iomux-mx3.h @@ -92,7 +92,7 @@ enum iomux_gp_func { MUX_EXTDMAREQ2_MBX_SEL = 1 << 15, MUX_TAMPER_DETECT_EN = 1 << 16, MUX_PGP_USB_4WIRE = 1 << 17, - MUX_PGB_USB_COMMON = 1 << 18, + MUX_PGP_USB_COMMON = 1 << 18, MUX_SDHC_MEMSTICK1 = 1 << 19, MUX_SDHC_MEMSTICK2 = 1 << 20, MUX_PGP_SPLL_BYP = 1 << 21, @@ -109,21 +109,44 @@ enum iomux_gp_func { }; /* - * This function enables/disables the general purpose function for a particular - * signal. + * setups a single pin: + * - reserves the pin so that it is not claimed by another driver + * - setups the iomux according to the configuration + * - if the pin is configured as a GPIO, we claim it throug kernel gpiolib + */ +int mxc_iomux_setup_pin(const unsigned int pin, const char *label); +/* + * setups mutliple pins + * convenient way to call the above function with tables */ -void iomux_config_gpr(enum iomux_gp_func , bool); +int mxc_iomux_setup_multiple_pins(unsigned int *pin_list, unsigned count, + const char *label); /* - * set the mode for a IOMUX pin. + * releases a single pin: + * - make it available for a future use by another driver + * - frees the GPIO if the pin was configured as GPIO + * - DOES NOT reconfigure the IOMUX in its reset state */ -int mxc_iomux_mode(unsigned int); +void mxc_iomux_release_pin(const unsigned int pin); +/* + * releases multiple pins + * convenvient way to call the above function with tables + */ +void mxc_iomux_release_multiple_pins(unsigned int *pin_list, int count); /* * This function enables/disables the general purpose function for a particular * signal. */ -void mxc_iomux_set_gpr(enum iomux_gp_func, bool); +void mxc_iomux_set_gpr(enum iomux_gp_func, bool en); + +/* + * This function only configures the iomux hardware. + * It is called by the setup functions and should not be called directly anymore. + * It is here visible for backward compatibility + */ +int mxc_iomux_mode(unsigned int pin_mode); #define IOMUX_PADNUM_MASK 0x1ff #define IOMUX_GPIONUM_SHIFT 9 @@ -143,6 +166,11 @@ void mxc_iomux_set_gpr(enum iomux_gp_func, bool); (((iomux_pin & IOMUX_GPIONUM_MASK) >> IOMUX_GPIONUM_SHIFT) + \ MXC_GPIO_IRQ_START) +/* + * The number of gpio devices among the pads + */ +#define GPIO_PORT_MAX 3 + /* * This enumeration is constructed based on the Section * "sw_pad_ctl & sw_mux_ctl details" of the MX31 IC Spec. Each enumerated @@ -480,6 +508,9 @@ enum iomux_pins { MX31_PIN_CAPTURE = IOMUX_PIN( 7, 327), }; +#define PIN_MAX 327 +#define NB_PORTS 12 /* NB_PINS/32, we chose 32 pins per "PORT" */ + /* * Convenience values for use with mxc_iomux_mode() * -- GitLab From bfbc6a1fc1d4d4ecbf73bcb7eefcd2a2ca5ddf2a Mon Sep 17 00:00:00 2001 From: Valentin Longchamp Date: Wed, 28 Jan 2009 15:13:51 +0100 Subject: [PATCH 3264/4982] mx31moboard: use of new iomux implementation This example takes advantage of the possibility to use tables of iomux configs. This is inspired from mx1-mx2 iomux code. It allows a better code readability. Signed-off-by: Valentin Longchamp Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/mx31moboard.c | 37 ++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-mx3/mx31moboard.c b/arch/arm/mach-mx3/mx31moboard.c index 3d2773e4bc8..f29c8782cff 100644 --- a/arch/arm/mach-mx3/mx31moboard.c +++ b/arch/arm/mach-mx3/mx31moboard.c @@ -63,6 +63,25 @@ static struct platform_device *devices[] __initdata = { &mx31moboard_flash, }; +static int mxc_uart0_pins[] = { + MX31_PIN_CTS1__CTS1, + MX31_PIN_RTS1__RTS1, + MX31_PIN_TXD1__TXD1, + MX31_PIN_RXD1__RXD1 +}; +static int mxc_uart1_pins[] = { + MX31_PIN_CTS2__CTS2, + MX31_PIN_RTS2__RTS2, + MX31_PIN_TXD2__TXD2, + MX31_PIN_RXD2__RXD2 +}; +static int mxc_uart4_pins[] = { + MX31_PIN_PC_RST__CTS5, + MX31_PIN_PC_VS2__RTS5, + MX31_PIN_PC_BVD2__TXD5, + MX31_PIN_PC_BVD1__RXD5 +}; + /* * Board specific initialization. */ @@ -70,25 +89,13 @@ static void __init mxc_board_init(void) { platform_add_devices(devices, ARRAY_SIZE(devices)); - mxc_iomux_mode(MX31_PIN_CTS1__CTS1); - mxc_iomux_mode(MX31_PIN_RTS1__RTS1); - mxc_iomux_mode(MX31_PIN_TXD1__TXD1); - mxc_iomux_mode(MX31_PIN_RXD1__RXD1); - + mxc_iomux_setup_multiple_pins(mxc_uart0_pins, ARRAY_SIZE(mxc_uart0_pins), "uart0"); mxc_register_device(&mxc_uart_device0, &uart_pdata); - mxc_iomux_mode(MX31_PIN_CTS2__CTS2); - mxc_iomux_mode(MX31_PIN_RTS2__RTS2); - mxc_iomux_mode(MX31_PIN_TXD2__TXD2); - mxc_iomux_mode(MX31_PIN_RXD2__RXD2); - + mxc_iomux_setup_multiple_pins(mxc_uart1_pins, ARRAY_SIZE(mxc_uart1_pins), "uart1"); mxc_register_device(&mxc_uart_device1, &uart_pdata); - mxc_iomux_mode(MX31_PIN_PC_RST__CTS5); - mxc_iomux_mode(MX31_PIN_PC_VS2__RTS5); - mxc_iomux_mode(MX31_PIN_PC_BVD2__TXD5); - mxc_iomux_mode(MX31_PIN_PC_BVD1__RXD5); - + mxc_iomux_setup_multiple_pins(mxc_uart4_pins, ARRAY_SIZE(mxc_uart4_pins), "uart4"); mxc_register_device(&mxc_uart_device4, &uart_pdata); } -- GitLab From 945c10b87c4d72ac9ad392132d19d17f3ebdb310 Mon Sep 17 00:00:00 2001 From: Valentin Longchamp Date: Wed, 28 Jan 2009 15:13:52 +0100 Subject: [PATCH 3265/4982] mx31ads: use of new iomux implementation This was only compilation tested. Signed-off-by: Valentin Longchamp Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/mx31ads.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-mx3/mx31ads.c b/arch/arm/mach-mx3/mx31ads.c index 6804fbe266e..7941db3caf6 100644 --- a/arch/arm/mach-mx3/mx31ads.c +++ b/arch/arm/mach-mx3/mx31ads.c @@ -94,13 +94,16 @@ static struct imxuart_platform_data uart_pdata = { .flags = IMXUART_HAVE_RTSCTS, }; +static int uart_pins[] = { + MX31_PIN_CTS1__CTS1, + MX31_PIN_RTS1__RTS1, + MX31_PIN_TXD1__TXD1, + MX31_PIN_RXD1__RXD1 +}; + static inline void mxc_init_imx_uart(void) { - mxc_iomux_mode(MX31_PIN_CTS1__CTS1); - mxc_iomux_mode(MX31_PIN_RTS1__RTS1); - mxc_iomux_mode(MX31_PIN_TXD1__TXD1); - mxc_iomux_mode(MX31_PIN_RXD1__RXD1); - + mxc_iomux_setup_multiple_pins(uart_pins, ARRAY_SIZE(uart_pins), "uart-0"); mxc_register_device(&mxc_uart_device0, &uart_pdata); } #else /* !SERIAL_IMX */ @@ -176,7 +179,7 @@ static void __init mx31ads_init_expio(void) /* * Configure INT line as GPIO input */ - mxc_iomux_mode(IOMUX_MODE(MX31_PIN_GPIO1_4, IOMUX_CONFIG_GPIO)); + mxc_iomux_setup_pin(IOMUX_MODE(MX31_PIN_GPIO1_4, IOMUX_CONFIG_GPIO), "expio"); /* disable the interrupt and clear the status */ __raw_writew(0xFFFF, PBC_INTMASK_CLEAR_REG); -- GitLab From 63d976672e39176316b2a479464aa3aaf7c2a7fd Mon Sep 17 00:00:00 2001 From: Valentin Longchamp Date: Wed, 28 Jan 2009 15:13:53 +0100 Subject: [PATCH 3266/4982] mx31pdk: use of new iomux implementation This was only compilation tested. Signed-off-by: Valentin Longchamp Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/mx31pdk.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-mx3/mx31pdk.c b/arch/arm/mach-mx3/mx31pdk.c index ac427edb4db..9108f157b76 100644 --- a/arch/arm/mach-mx3/mx31pdk.c +++ b/arch/arm/mach-mx3/mx31pdk.c @@ -45,13 +45,16 @@ static struct imxuart_platform_data uart_pdata = { .flags = IMXUART_HAVE_RTSCTS, }; +static int uart_pins[] = { + MX31_PIN_CTS1__CTS1, + MX31_PIN_RTS1__RTS1, + MX31_PIN_TXD1__TXD1, + MX31_PIN_RXD1__RXD1 +}; + static inline void mxc_init_imx_uart(void) { - mxc_iomux_mode(MX31_PIN_CTS1__CTS1); - mxc_iomux_mode(MX31_PIN_RTS1__RTS1); - mxc_iomux_mode(MX31_PIN_TXD1__TXD1); - mxc_iomux_mode(MX31_PIN_RXD1__RXD1); - + mxc_iomux_setup_multiple_pins(uart_pins, ARRAY_SIZE(uart_pins), "uart-0"); mxc_register_device(&mxc_uart_device0, &uart_pdata); } -- GitLab From bab389c8750d7f41f499517b308600f13bd2788d Mon Sep 17 00:00:00 2001 From: Valentin Longchamp Date: Wed, 28 Jan 2009 15:13:54 +0100 Subject: [PATCH 3267/4982] pcm037: use of new iomux implementation This was only compilation tested. Signed-off-by: Valentin Longchamp Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/pcm037.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-mx3/pcm037.c b/arch/arm/mach-mx3/pcm037.c index 3b5ba551cb1..18cda92432b 100644 --- a/arch/arm/mach-mx3/pcm037.c +++ b/arch/arm/mach-mx3/pcm037.c @@ -123,6 +123,18 @@ static struct platform_device *devices[] __initdata = { &pcm037_sram_device, }; +static int uart0_pins[] = { + MX31_PIN_CTS1__CTS1, + MX31_PIN_RTS1__RTS1, + MX31_PIN_TXD1__TXD1, + MX31_PIN_RXD1__RXD1 +}; + +static int uart2_pins[] = { + MX31_PIN_CSPI3_MOSI__RXD3, + MX31_PIN_CSPI3_MISO__TXD3 +}; + /* * Board specific initialization. */ @@ -130,24 +142,18 @@ static void __init mxc_board_init(void) { platform_add_devices(devices, ARRAY_SIZE(devices)); - mxc_iomux_mode(MX31_PIN_CTS1__CTS1); - mxc_iomux_mode(MX31_PIN_RTS1__RTS1); - mxc_iomux_mode(MX31_PIN_TXD1__TXD1); - mxc_iomux_mode(MX31_PIN_RXD1__RXD1); - + mxc_iomux_setup_multiple_pins(uart0_pins, ARRAY_SIZE(uart0_pins), "uart-0"); mxc_register_device(&mxc_uart_device0, &uart_pdata); - mxc_iomux_mode(MX31_PIN_CSPI3_MOSI__RXD3); - mxc_iomux_mode(MX31_PIN_CSPI3_MISO__TXD3); - + mxc_iomux_setup_multiple_pins(uart2_pins, ARRAY_SIZE(uart2_pins), "uart-2"); mxc_register_device(&mxc_uart_device2, &uart_pdata); - mxc_iomux_mode(MX31_PIN_BATT_LINE__OWIRE); + mxc_iomux_setup_pin(MX31_PIN_BATT_LINE__OWIRE, "batt-0wire"); mxc_register_device(&mxc_w1_master_device, NULL); /* SMSC9215 IRQ pin */ - mxc_iomux_mode(IOMUX_MODE(MX31_PIN_GPIO3_1, IOMUX_CONFIG_GPIO)); - if (!gpio_request(MX31_PIN_GPIO3_1, "pcm037-eth")) + if (!mxc_iomux_setup_pin(IOMUX_MODE(MX31_PIN_GPIO3_1, IOMUX_CONFIG_GPIO), + "pcm037-eth")) gpio_direction_input(MX31_PIN_GPIO3_1); mxc_register_device(&mxc_nand_device, &pcm037_nand_board_info); -- GitLab From fe7316bff119a11e68f895ecf9a5a713ed30004c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 15 Jan 2009 16:14:30 +0000 Subject: [PATCH 3268/4982] mx31ads: Initial support for Wolfson Microelectronics 1133-EV1 module The i.MX31ADS supports pluggable PMU modules, including the WM835x based Wolfson Microelectronics 1133-EV1. These boards provide power, audio, RTC and watchdiog services to the system. This patch adds initial support for those boards in I2C mode. Currently support is limited by the available support for the features of the i.MX31 in the mainline kernel. Some further work will be needed once other PMU modules are supported and once there is SPI support. Many of the regulator constraints will be sharable with other PMU boards. Signed-off-by: Mark Brown Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/Kconfig | 9 ++ arch/arm/mach-mx3/mx31ads.c | 294 ++++++++++++++++++++++++++++++++++++ 2 files changed, 303 insertions(+) diff --git a/arch/arm/mach-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig index e79659e8176..6fea5419632 100644 --- a/arch/arm/mach-mx3/Kconfig +++ b/arch/arm/mach-mx3/Kconfig @@ -8,6 +8,15 @@ config MACH_MX31ADS Include support for MX31ADS platform. This includes specific configurations for the board and its peripherals. +config MACH_MX31ADS_WM1133_EV1 + bool "Support Wolfson Microelectronics 1133-EV1 module" + depends on MACH_MX31ADS + select MFD_WM8350_CONFIG_MODE_0 + select MFD_WM8352_CONFIG_MODE_0 + help + Include support for the Wolfson Microelectronics 1133-EV1 PMU + and audio module for the MX31ADS platform. + config MACH_PCM037 bool "Support Phytec pcm037 platforms" help diff --git a/arch/arm/mach-mx3/mx31ads.c b/arch/arm/mach-mx3/mx31ads.c index 7941db3caf6..5c76ac5ba0f 100644 --- a/arch/arm/mach-mx3/mx31ads.c +++ b/arch/arm/mach-mx3/mx31ads.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include @@ -35,6 +37,12 @@ #include #include +#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1 +#include +#include +#include +#endif + #include "devices.h" /*! @@ -194,6 +202,291 @@ static void __init mx31ads_init_expio(void) set_irq_chained_handler(EXPIO_PARENT_INT, mx31ads_expio_irq_handler); } +#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1 +/* This section defines setup for the Wolfson Microelectronics + * 1133-EV1 PMU/audio board. When other PMU boards are supported the + * regulator definitions may be shared with them, but for now they can + * only be used with this board so would generate warnings about + * unused statics and some of the configuration is specific to this + * module. + */ + +/* CPU */ +static struct regulator_consumer_supply sw1a_consumers[] = { + { + .supply = "cpu_vcc", + } +}; + +static struct regulator_init_data sw1a_data = { + .constraints = { + .name = "SW1A", + .min_uV = 1275000, + .max_uV = 1600000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_NORMAL | + REGULATOR_MODE_FAST, + .state_mem = { + .uV = 1400000, + .mode = REGULATOR_MODE_NORMAL, + .enabled = 1, + }, + .initial_state = PM_SUSPEND_MEM, + .always_on = 1, + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(sw1a_consumers), + .consumer_supplies = sw1a_consumers, +}; + +/* System IO - High */ +static struct regulator_init_data viohi_data = { + .constraints = { + .name = "VIOHO", + .min_uV = 2800000, + .max_uV = 2800000, + .state_mem = { + .uV = 2800000, + .mode = REGULATOR_MODE_NORMAL, + .enabled = 1, + }, + .initial_state = PM_SUSPEND_MEM, + .always_on = 1, + .boot_on = 1, + }, +}; + +/* System IO - Low */ +static struct regulator_init_data violo_data = { + .constraints = { + .name = "VIOLO", + .min_uV = 1800000, + .max_uV = 1800000, + .state_mem = { + .uV = 1800000, + .mode = REGULATOR_MODE_NORMAL, + .enabled = 1, + }, + .initial_state = PM_SUSPEND_MEM, + .always_on = 1, + .boot_on = 1, + }, +}; + +/* DDR RAM */ +static struct regulator_init_data sw2a_data = { + .constraints = { + .name = "SW2A", + .min_uV = 1800000, + .max_uV = 1800000, + .valid_modes_mask = REGULATOR_MODE_NORMAL, + .state_mem = { + .uV = 1800000, + .mode = REGULATOR_MODE_NORMAL, + .enabled = 1, + }, + .state_disk = { + .mode = REGULATOR_MODE_NORMAL, + .enabled = 0, + }, + .always_on = 1, + .boot_on = 1, + .initial_state = PM_SUSPEND_MEM, + }, +}; + +static struct regulator_init_data ldo1_data = { + .constraints = { + .name = "VCAM/VMMC1/VMMC2", + .min_uV = 2800000, + .max_uV = 2800000, + .valid_modes_mask = REGULATOR_MODE_NORMAL, + .apply_uV = 1, + }, +}; + +static struct regulator_consumer_supply ldo2_consumers[] = { + { + .supply = "AVDD", + }, + { + .supply = "HPVDD", + }, +}; + +/* CODEC and SIM */ +static struct regulator_init_data ldo2_data = { + .constraints = { + .name = "VESIM/VSIM/AVDD", + .min_uV = 3300000, + .max_uV = 3300000, + .valid_modes_mask = REGULATOR_MODE_NORMAL, + .apply_uV = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(ldo2_consumers), + .consumer_supplies = ldo2_consumers, +}; + +/* General */ +static struct regulator_init_data vdig_data = { + .constraints = { + .name = "VDIG", + .min_uV = 1500000, + .max_uV = 1500000, + .valid_modes_mask = REGULATOR_MODE_NORMAL, + .apply_uV = 1, + .always_on = 1, + .boot_on = 1, + }, +}; + +/* Tranceivers */ +static struct regulator_init_data ldo4_data = { + .constraints = { + .name = "VRF1/CVDD_2.775", + .min_uV = 2500000, + .max_uV = 2500000, + .valid_modes_mask = REGULATOR_MODE_NORMAL, + .apply_uV = 1, + .always_on = 1, + .boot_on = 1, + }, +}; + +static struct wm8350_led_platform_data wm8350_led_data = { + .name = "wm8350:white", + .default_trigger = "heartbeat", + .max_uA = 27899, +}; + +static struct wm8350_audio_platform_data imx32ads_wm8350_setup = { + .vmid_discharge_msecs = 1000, + .drain_msecs = 30, + .cap_discharge_msecs = 700, + .vmid_charge_msecs = 700, + .vmid_s_curve = WM8350_S_CURVE_SLOW, + .dis_out4 = WM8350_DISCHARGE_SLOW, + .dis_out3 = WM8350_DISCHARGE_SLOW, + .dis_out2 = WM8350_DISCHARGE_SLOW, + .dis_out1 = WM8350_DISCHARGE_SLOW, + .vroi_out4 = WM8350_TIE_OFF_500R, + .vroi_out3 = WM8350_TIE_OFF_500R, + .vroi_out2 = WM8350_TIE_OFF_500R, + .vroi_out1 = WM8350_TIE_OFF_500R, + .vroi_enable = 0, + .codec_current_on = WM8350_CODEC_ISEL_1_0, + .codec_current_standby = WM8350_CODEC_ISEL_0_5, + .codec_current_charge = WM8350_CODEC_ISEL_1_5, +}; + +static int mx31_wm8350_init(struct wm8350 *wm8350) +{ + int i; + + wm8350_gpio_config(wm8350, 0, WM8350_GPIO_DIR_IN, + WM8350_GPIO0_PWR_ON_IN, WM8350_GPIO_ACTIVE_LOW, + WM8350_GPIO_PULL_UP, WM8350_GPIO_INVERT_OFF, + WM8350_GPIO_DEBOUNCE_ON); + + wm8350_gpio_config(wm8350, 3, WM8350_GPIO_DIR_IN, + WM8350_GPIO3_PWR_OFF_IN, WM8350_GPIO_ACTIVE_HIGH, + WM8350_GPIO_PULL_DOWN, WM8350_GPIO_INVERT_OFF, + WM8350_GPIO_DEBOUNCE_ON); + + wm8350_gpio_config(wm8350, 4, WM8350_GPIO_DIR_IN, + WM8350_GPIO4_MR_IN, WM8350_GPIO_ACTIVE_HIGH, + WM8350_GPIO_PULL_DOWN, WM8350_GPIO_INVERT_OFF, + WM8350_GPIO_DEBOUNCE_OFF); + + wm8350_gpio_config(wm8350, 7, WM8350_GPIO_DIR_IN, + WM8350_GPIO7_HIBERNATE_IN, WM8350_GPIO_ACTIVE_HIGH, + WM8350_GPIO_PULL_DOWN, WM8350_GPIO_INVERT_OFF, + WM8350_GPIO_DEBOUNCE_OFF); + + wm8350_gpio_config(wm8350, 6, WM8350_GPIO_DIR_OUT, + WM8350_GPIO6_SDOUT_OUT, WM8350_GPIO_ACTIVE_HIGH, + WM8350_GPIO_PULL_NONE, WM8350_GPIO_INVERT_OFF, + WM8350_GPIO_DEBOUNCE_OFF); + + wm8350_gpio_config(wm8350, 8, WM8350_GPIO_DIR_OUT, + WM8350_GPIO8_VCC_FAULT_OUT, WM8350_GPIO_ACTIVE_LOW, + WM8350_GPIO_PULL_NONE, WM8350_GPIO_INVERT_OFF, + WM8350_GPIO_DEBOUNCE_OFF); + + wm8350_gpio_config(wm8350, 9, WM8350_GPIO_DIR_OUT, + WM8350_GPIO9_BATT_FAULT_OUT, WM8350_GPIO_ACTIVE_LOW, + WM8350_GPIO_PULL_NONE, WM8350_GPIO_INVERT_OFF, + WM8350_GPIO_DEBOUNCE_OFF); + + /* Fix up for our own supplies. */ + for (i = 0; i < ARRAY_SIZE(ldo2_consumers); i++) + ldo2_consumers[i].dev = wm8350->dev; + + wm8350_register_regulator(wm8350, WM8350_DCDC_1, &sw1a_data); + wm8350_register_regulator(wm8350, WM8350_DCDC_3, &viohi_data); + wm8350_register_regulator(wm8350, WM8350_DCDC_4, &violo_data); + wm8350_register_regulator(wm8350, WM8350_DCDC_6, &sw2a_data); + wm8350_register_regulator(wm8350, WM8350_LDO_1, &ldo1_data); + wm8350_register_regulator(wm8350, WM8350_LDO_2, &ldo2_data); + wm8350_register_regulator(wm8350, WM8350_LDO_3, &vdig_data); + wm8350_register_regulator(wm8350, WM8350_LDO_4, &ldo4_data); + + /* LEDs */ + wm8350_dcdc_set_slot(wm8350, WM8350_DCDC_5, 1, 1, + WM8350_DC5_ERRACT_SHUTDOWN_CONV); + wm8350_isink_set_flash(wm8350, WM8350_ISINK_A, + WM8350_ISINK_FLASH_DISABLE, + WM8350_ISINK_FLASH_TRIG_BIT, + WM8350_ISINK_FLASH_DUR_32MS, + WM8350_ISINK_FLASH_ON_INSTANT, + WM8350_ISINK_FLASH_OFF_INSTANT, + WM8350_ISINK_FLASH_MODE_EN); + wm8350_dcdc25_set_mode(wm8350, WM8350_DCDC_5, + WM8350_ISINK_MODE_BOOST, + WM8350_ISINK_ILIM_NORMAL, + WM8350_DC5_RMP_20V, + WM8350_DC5_FBSRC_ISINKA); + wm8350_register_led(wm8350, 0, WM8350_DCDC_5, WM8350_ISINK_A, + &wm8350_led_data); + + wm8350->codec.platform_data = &imx32ads_wm8350_setup; + + return 0; +} + +static struct wm8350_platform_data __initdata mx31_wm8350_pdata = { + .init = mx31_wm8350_init, +}; +#endif + +#if defined(CONFIG_I2C_IMX) || defined(CONFIG_I2C_IMX_MODULE) +static struct i2c_board_info __initdata mx31ads_i2c1_devices[] = { +#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1 + { + I2C_BOARD_INFO("wm8350", 0x1a), + .platform_data = &mx31_wm8350_pdata, + .irq = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3), + }, +#endif +}; + +static void mxc_init_i2c(void) +{ + i2c_register_board_info(1, mx31ads_i2c1_devices, + ARRAY_SIZE(mx31ads_i2c1_devices)); + + mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSPI2_MOSI, IOMUX_CONFIG_ALT1)); + mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSPI2_MISO, IOMUX_CONFIG_ALT1)); + + mxc_register_device(&mxc_i2c_device1, NULL); +} +#else +static void mxc_init_i2c(void) +{ +} +#endif + /*! * This structure defines static mappings for the i.MX31ADS board. */ @@ -243,6 +536,7 @@ static void __init mxc_board_init(void) { mxc_init_extuart(); mxc_init_imx_uart(); + mxc_init_i2c(); } static void __init mx31ads_timer_init(void) -- GitLab From 879fea1b486d2b6fa399c40b8aed172b0dfdedb9 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 26 Jan 2009 17:26:02 +0100 Subject: [PATCH 3269/4982] [ARM] MX2: Add FEC platform device The in kernel FEC driver has recently been ported to a platform driver. Add a platform_device for it and register it for pcm038 and mx27ads. Signed-off-by: Sascha Hauer --- arch/arm/mach-mx2/devices.c | 20 ++++++++++++++++++++ arch/arm/mach-mx2/devices.h | 1 + arch/arm/mach-mx2/mx27ads.c | 1 + arch/arm/mach-mx2/pcm038.c | 1 + 4 files changed, 23 insertions(+) diff --git a/arch/arm/mach-mx2/devices.c b/arch/arm/mach-mx2/devices.c index 07061e64454..684d5d92c2e 100644 --- a/arch/arm/mach-mx2/devices.c +++ b/arch/arm/mach-mx2/devices.c @@ -258,7 +258,27 @@ struct platform_device mxc_fb_device = { .coherent_dma_mask = 0xFFFFFFFF, }, }; +#endif +#ifdef CONFIG_MACH_MX27 +static struct resource mxc_fec_resources[] = { + { + .start = FEC_BASE_ADDR, + .end = FEC_BASE_ADDR + 0xfff, + .flags = IORESOURCE_MEM + }, { + .start = MXC_INT_FEC, + .end = MXC_INT_FEC, + .flags = IORESOURCE_IRQ + }, +}; + +struct platform_device mxc_fec_device = { + .name = "fec", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_fec_resources), + .resource = mxc_fec_resources, +}; #endif /* GPIO port description */ diff --git a/arch/arm/mach-mx2/devices.h b/arch/arm/mach-mx2/devices.h index f4cb0ce29f1..d85d5b26c98 100644 --- a/arch/arm/mach-mx2/devices.h +++ b/arch/arm/mach-mx2/devices.h @@ -14,3 +14,4 @@ extern struct platform_device mxc_uart_device5; extern struct platform_device mxc_w1_master_device; extern struct platform_device mxc_nand_device; extern struct platform_device mxc_fb_device; +extern struct platform_device mxc_fec_device; diff --git a/arch/arm/mach-mx2/mx27ads.c b/arch/arm/mach-mx2/mx27ads.c index 3c967f460b3..4a3b097adc1 100644 --- a/arch/arm/mach-mx2/mx27ads.c +++ b/arch/arm/mach-mx2/mx27ads.c @@ -180,6 +180,7 @@ static int uart_mxc_port5_exit(struct platform_device *pdev) static struct platform_device *platform_devices[] __initdata = { &mx27ads_nor_mtd_device, + &mxc_fec_device, }; static int mxc_fec_pins[] = { diff --git a/arch/arm/mach-mx2/pcm038.c b/arch/arm/mach-mx2/pcm038.c index 58552a01c0d..d246eb1bb3c 100644 --- a/arch/arm/mach-mx2/pcm038.c +++ b/arch/arm/mach-mx2/pcm038.c @@ -191,6 +191,7 @@ static struct mxc_nand_platform_data pcm038_nand_board_info = { static struct platform_device *platform_devices[] __initdata = { &pcm038_nor_mtd_device, &mxc_w1_master_device, + &mxc_fec_device, &pcm038_sram_mtd_device, }; -- GitLab From c0b90a31efe30987ab4bb21298b410913779e62f Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 15 Jan 2009 15:37:22 +0100 Subject: [PATCH 3270/4982] imxfb: add platform specific init/exit functions Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/include/mach/imxfb.h | 3 +++ drivers/video/imxfb.c | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/arch/arm/plat-mxc/include/mach/imxfb.h b/arch/arm/plat-mxc/include/mach/imxfb.h index 870d0d93961..762a7b0430e 100644 --- a/arch/arm/plat-mxc/include/mach/imxfb.h +++ b/arch/arm/plat-mxc/include/mach/imxfb.h @@ -76,6 +76,9 @@ struct imx_fb_platform_data { u_char * fixed_screen_cpu; dma_addr_t fixed_screen_dma; + int (*init)(struct platform_device*); + int (*exit)(struct platform_device*); + void (*lcd_power)(int); void (*backlight_power)(int); }; diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index d58c68cd456..629d66f3230 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -650,6 +650,12 @@ static int __init imxfb_probe(struct platform_device *pdev) info->fix.smem_start = fbi->screen_dma; } + if (pdata->init) { + ret = pdata->init(fbi->pdev); + if (ret) + goto failed_platform_init; + } + /* * This makes sure that our colour bitfield * descriptors are correctly initialised. @@ -674,6 +680,9 @@ static int __init imxfb_probe(struct platform_device *pdev) failed_register: fb_dealloc_cmap(&info->cmap); failed_cmap: + if (pdata->exit) + pdata->exit(fbi->pdev); +failed_platform_init: if (!pdata->fixed_screen_cpu) dma_free_writecombine(&pdev->dev,fbi->map_size,fbi->map_cpu, fbi->map_dma); @@ -691,6 +700,7 @@ failed_init: static int __devexit imxfb_remove(struct platform_device *pdev) { + struct imx_fb_platform_data *pdata; struct fb_info *info = platform_get_drvdata(pdev); struct imxfb_info *fbi = info->par; struct resource *res; @@ -701,6 +711,10 @@ static int __devexit imxfb_remove(struct platform_device *pdev) unregister_framebuffer(info); + pdata = pdev->dev.platform_data; + if (pdata->exit) + pdata->exit(fbi->pdev); + fb_dealloc_cmap(&info->cmap); kfree(info->pseudo_palette); framebuffer_release(info); -- GitLab From 9db973a59b73fb5baf69f8b5d005daccec6d997e Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 15 Jan 2009 12:44:45 +0100 Subject: [PATCH 3271/4982] [ARM] pcm038: Add framebuffer support Add framebuffer support for PCM038 Signed-off-by: Sascha Hauer --- arch/arm/mach-mx2/pcm970-baseboard.c | 70 +++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-mx2/pcm970-baseboard.c b/arch/arm/mach-mx2/pcm970-baseboard.c index a560cd6ad23..232e0416f15 100644 --- a/arch/arm/mach-mx2/pcm970-baseboard.c +++ b/arch/arm/mach-mx2/pcm970-baseboard.c @@ -17,9 +17,76 @@ */ #include -#include + #include +#include +#include +#include +#include + +#include "devices.h" + +static int mxc_fb_pins[] = { + PA5_PF_LSCLK, PA6_PF_LD0, PA7_PF_LD1, PA8_PF_LD2, + PA9_PF_LD3, PA10_PF_LD4, PA11_PF_LD5, PA12_PF_LD6, + PA13_PF_LD7, PA14_PF_LD8, PA15_PF_LD9, PA16_PF_LD10, + PA17_PF_LD11, PA18_PF_LD12, PA19_PF_LD13, PA20_PF_LD14, + PA21_PF_LD15, PA22_PF_LD16, PA23_PF_LD17, PA24_PF_REV, + PA25_PF_CLS, PA26_PF_PS, PA27_PF_SPL_SPR, PA28_PF_HSYNC, + PA29_PF_VSYNC, PA30_PF_CONTRAST, PA31_PF_OE_ACD +}; + +static int pcm038_fb_init(struct platform_device *pdev) +{ + return mxc_gpio_setup_multiple_pins(mxc_fb_pins, + ARRAY_SIZE(mxc_fb_pins), "FB"); +} + +static int pcm038_fb_exit(struct platform_device *pdev) +{ + mxc_gpio_release_multiple_pins(mxc_fb_pins, ARRAY_SIZE(mxc_fb_pins)); + + return 0; +} + +/* + * Connected is a portrait Sharp-QVGA display + * of type: LQ035Q7DH06 + */ +static struct imx_fb_platform_data pcm038_fb_data = { + .pixclock = 188679, /* in ps (5.3MHz) */ + .xres = 240, + .yres = 320, + + .bpp = 16, + .hsync_len = 7, + .left_margin = 5, + .right_margin = 16, + + .vsync_len = 1, + .upper_margin = 7, + .lower_margin = 9, + .fixed_screen_cpu = 0, + + /* + * - HSYNC active high + * - VSYNC active high + * - clk notenabled while idle + * - clock not inverted + * - data not inverted + * - data enable low active + * - enable sharp mode + */ + .pcr = 0xFA0080C0, + .pwmr = 0x00A903FF, + .lscr1 = 0x00120300, + .dmacr = 0x00020010, + + .init = pcm038_fb_init, + .exit = pcm038_fb_exit, +}; + /* * system init for baseboard usage. Will be called by pcm038 init. * @@ -28,4 +95,5 @@ */ void __init pcm970_baseboard_init(void) { + mxc_register_device(&mxc_fb_device, &pcm038_fb_data); } -- GitLab From 1512222b105beaff7b7fe11aa4220bcd0088e421 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 26 Jan 2009 17:31:02 +0100 Subject: [PATCH 3272/4982] imxfb: add 18 bit support v2: As pointed out by Hans J. Koch we have to claim we can do 24bit to make software like X work. We are lucky on i.MX that 18bit support has the necessary gaps in the fields to do so. Signed-off-by: Sascha Hauer --- drivers/video/imxfb.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 629d66f3230..5c61286d7ff 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -14,7 +14,6 @@ * linux-arm-kernel@lists.arm.linux.org.uk */ - #include #include #include @@ -159,6 +158,17 @@ struct imxfb_info { #define MIN_XRES 64 #define MIN_YRES 64 +/* Actually this really is 18bit support, the lowest 2 bits of each colour + * are unused in hardware. We claim to have 24bit support to make software + * like X work, which does not support 18bit. + */ +static struct imxfb_rgb def_rgb_18 = { + .red = {.offset = 16, .length = 8,}, + .green = {.offset = 8, .length = 8,}, + .blue = {.offset = 0, .length = 8,}, + .transp = {.offset = 0, .length = 0,}, +}; + static struct imxfb_rgb def_rgb_16_tft = { .red = {.offset = 11, .length = 5,}, .green = {.offset = 5, .length = 6,}, @@ -286,6 +296,9 @@ static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) pr_debug("var->bits_per_pixel=%d\n", var->bits_per_pixel); switch (var->bits_per_pixel) { + case 32: + rgb = &def_rgb_18; + break; case 16: default: if (readl(fbi->regs + LCDC_PCR) & PCR_TFT) @@ -327,9 +340,7 @@ static int imxfb_set_par(struct fb_info *info) struct imxfb_info *fbi = info->par; struct fb_var_screeninfo *var = &info->var; - pr_debug("set_par\n"); - - if (var->bits_per_pixel == 16) + if (var->bits_per_pixel == 16 || var->bits_per_pixel == 32) info->fix.visual = FB_VISUAL_TRUECOLOR; else if (!fbi->cmap_static) info->fix.visual = FB_VISUAL_PSEUDOCOLOR; -- GitLab From 166091b1894df3de736f43c649f2e6639f4a31ac Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 16 Jan 2009 15:17:16 +0100 Subject: [PATCH 3273/4982] [ARM] MXC: add pwm driver for i.MX SoCs This driver has been tested on MX27/MX31. It should work on MX1/MX1 aswell, but the actual setting of the PWM is missing so far. Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/Kconfig | 6 + arch/arm/plat-mxc/Makefile | 1 + arch/arm/plat-mxc/pwm.c | 300 +++++++++++++++++++++++++++++++++++++ 3 files changed, 307 insertions(+) create mode 100644 arch/arm/plat-mxc/pwm.c diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig index 10f65bf27b2..71c3c848b0e 100644 --- a/arch/arm/plat-mxc/Kconfig +++ b/arch/arm/plat-mxc/Kconfig @@ -44,4 +44,10 @@ config MXC_IRQ_PRIOR requirements for timing. Say N here, unless you have a specialized requirement. +config MXC_PWM + tristate "Enable PWM driver" + depends on ARCH_MXC + help + Enable support for the i.MX PWM controller(s). + endif diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile index db74a929179..f204192f9b9 100644 --- a/arch/arm/plat-mxc/Makefile +++ b/arch/arm/plat-mxc/Makefile @@ -7,3 +7,4 @@ obj-y := irq.o clock.o gpio.o time.o devices.o obj-$(CONFIG_ARCH_MX1) += iomux-mx1-mx2.o dma-mx1-mx2.o obj-$(CONFIG_ARCH_MX2) += iomux-mx1-mx2.o dma-mx1-mx2.o +obj-$(CONFIG_MXC_PWM) += pwm.o diff --git a/arch/arm/plat-mxc/pwm.c b/arch/arm/plat-mxc/pwm.c new file mode 100644 index 00000000000..9bffbc507cc --- /dev/null +++ b/arch/arm/plat-mxc/pwm.c @@ -0,0 +1,300 @@ +/* + * simple driver for PWM (Pulse Width Modulator) controller + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Derived from pxa PWM driver by eric miao + */ + +#include +#include +#include +#include +#include +#include +#include + +#if defined CONFIG_ARCH_MX1 || defined CONFIG_ARCH_MX21 +#define PWM_VER_1 + +#define PWMCR 0x00 /* PWM Control Register */ +#define PWMSR 0x04 /* PWM Sample Register */ +#define PWMPR 0x08 /* PWM Period Register */ +#define PWMCNR 0x0C /* PWM Counter Register */ + +#define PWMCR_HCTR (1 << 18) /* Halfword FIFO Data Swapping */ +#define PWMCR_BCTR (1 << 17) /* Byte FIFO Data Swapping */ +#define PWMCR_SWR (1 << 16) /* Software Reset */ +#define PWMCR_CLKSRC_PERCLK (0 << 15) /* PERCLK Clock Source */ +#define PWMCR_CLKSRC_CLK32 (1 << 15) /* 32KHz Clock Source */ +#define PWMCR_PRESCALER(x) (((x - 1) & 0x7F) << 8) /* PRESCALER */ +#define PWMCR_IRQ (1 << 7) /* Interrupt Request */ +#define PWMCR_IRQEN (1 << 6) /* Interrupt Request Enable */ +#define PWMCR_FIFOAV (1 << 5) /* FIFO Available */ +#define PWMCR_EN (1 << 4) /* Enables/Disables the PWM */ +#define PWMCR_REPEAT(x) (((x) & 0x03) << 2) /* Sample Repeats */ +#define PWMCR_DIV(x) (((x) & 0x03) << 0) /* Clock divider 2/4/8/16 */ + +#define MAX_DIV (128 * 16) +#endif + +#if defined CONFIG_MACH_MX27 || defined CONFIG_ARCH_MX31 +#define PWM_VER_2 + +#define PWMCR 0x00 /* PWM Control Register */ +#define PWMSR 0x04 /* PWM Status Register */ +#define PWMIR 0x08 /* PWM Interrupt Register */ +#define PWMSAR 0x0C /* PWM Sample Register */ +#define PWMPR 0x10 /* PWM Period Register */ +#define PWMCNR 0x14 /* PWM Counter Register */ + +#define PWMCR_EN (1 << 0) /* Enables/Disables the PWM */ +#define PWMCR_REPEAT(x) (((x) & 0x03) << 1) /* Sample Repeats */ +#define PWMCR_SWR (1 << 3) /* Software Reset */ +#define PWMCR_PRESCALER(x) (((x - 1) & 0xFFF) << 4)/* PRESCALER */ +#define PWMCR_CLKSRC(x) (((x) & 0x3) << 16) +#define PWMCR_CLKSRC_OFF (0 << 16) +#define PWMCR_CLKSRC_IPG (1 << 16) +#define PWMCR_CLKSRC_IPG_HIGH (2 << 16) +#define PWMCR_CLKSRC_CLK32 (3 << 16) +#define PWMCR_POUTC +#define PWMCR_HCTR (1 << 20) /* Halfword FIFO Data Swapping */ +#define PWMCR_BCTR (1 << 21) /* Byte FIFO Data Swapping */ +#define PWMCR_DBGEN (1 << 22) /* Debug Mode */ +#define PWMCR_WAITEN (1 << 23) /* Wait Mode */ +#define PWMCR_DOZEN (1 << 24) /* Doze Mode */ +#define PWMCR_STOPEN (1 << 25) /* Stop Mode */ +#define PWMCR_FWM(x) (((x) & 0x3) << 26) /* FIFO Water Mark */ + +#define MAX_DIV 4096 +#endif + +#define PWMS_SAMPLE(x) ((x) & 0xFFFF) /* Contains a two-sample word */ +#define PWMP_PERIOD(x) ((x) & 0xFFFF) /* Represents the PWM's period */ +#define PWMC_COUNTER(x) ((x) & 0xFFFF) /* Represents the current count value */ + +struct pwm_device { + struct list_head node; + struct platform_device *pdev; + + const char *label; + struct clk *clk; + + int clk_enabled; + void __iomem *mmio_base; + + unsigned int use_count; + unsigned int pwm_id; +}; + +int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) +{ + unsigned long long c; + unsigned long period_cycles, duty_cycles, prescale; + + if (pwm == NULL || period_ns == 0 || duty_ns > period_ns) + return -EINVAL; + + c = clk_get_rate(pwm->clk); + c = c * period_ns; + do_div(c, 1000000000); + period_cycles = c; + + prescale = period_cycles / 0x10000 + 1; + + period_cycles /= prescale; + c = (unsigned long long)period_cycles * duty_ns; + do_div(c, period_ns); + duty_cycles = c; + +#ifdef PWM_VER_2 + writel(duty_cycles, pwm->mmio_base + PWMSAR); + writel(period_cycles, pwm->mmio_base + PWMPR); + writel(PWMCR_PRESCALER(prescale - 1) | PWMCR_CLKSRC_IPG_HIGH | PWMCR_EN, + pwm->mmio_base + PWMCR); +#elif defined PWM_VER_1 +#error PWM not yet working on MX1 / MX21 +#endif + + return 0; +} +EXPORT_SYMBOL(pwm_config); + +int pwm_enable(struct pwm_device *pwm) +{ + int rc = 0; + + if (!pwm->clk_enabled) { + rc = clk_enable(pwm->clk); + if (!rc) + pwm->clk_enabled = 1; + } + return rc; +} +EXPORT_SYMBOL(pwm_enable); + +void pwm_disable(struct pwm_device *pwm) +{ + if (pwm->clk_enabled) { + clk_disable(pwm->clk); + pwm->clk_enabled = 0; + } +} +EXPORT_SYMBOL(pwm_disable); + +static DEFINE_MUTEX(pwm_lock); +static LIST_HEAD(pwm_list); + +struct pwm_device *pwm_request(int pwm_id, const char *label) +{ + struct pwm_device *pwm; + int found = 0; + + mutex_lock(&pwm_lock); + + list_for_each_entry(pwm, &pwm_list, node) { + if (pwm->pwm_id == pwm_id) { + found = 1; + break; + } + } + + if (found) { + if (pwm->use_count == 0) { + pwm->use_count++; + pwm->label = label; + } else + pwm = ERR_PTR(-EBUSY); + } else + pwm = ERR_PTR(-ENOENT); + + mutex_unlock(&pwm_lock); + return pwm; +} +EXPORT_SYMBOL(pwm_request); + +void pwm_free(struct pwm_device *pwm) +{ + mutex_lock(&pwm_lock); + + if (pwm->use_count) { + pwm->use_count--; + pwm->label = NULL; + } else + pr_warning("PWM device already freed\n"); + + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL(pwm_free); + +static int __devinit mxc_pwm_probe(struct platform_device *pdev) +{ + struct pwm_device *pwm; + struct resource *r; + int ret = 0; + + pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); + if (pwm == NULL) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + pwm->clk = clk_get(&pdev->dev, "pwm"); + + if (IS_ERR(pwm->clk)) { + ret = PTR_ERR(pwm->clk); + goto err_free; + } + + pwm->clk_enabled = 0; + + pwm->use_count = 0; + pwm->pwm_id = pdev->id; + pwm->pdev = pdev; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (r == NULL) { + dev_err(&pdev->dev, "no memory resource defined\n"); + ret = -ENODEV; + goto err_free_clk; + } + + r = request_mem_region(r->start, r->end - r->start + 1, pdev->name); + if (r == NULL) { + dev_err(&pdev->dev, "failed to request memory resource\n"); + ret = -EBUSY; + goto err_free_clk; + } + + pwm->mmio_base = ioremap(r->start, r->end - r->start + 1); + if (pwm->mmio_base == NULL) { + dev_err(&pdev->dev, "failed to ioremap() registers\n"); + ret = -ENODEV; + goto err_free_mem; + } + + mutex_lock(&pwm_lock); + list_add_tail(&pwm->node, &pwm_list); + mutex_unlock(&pwm_lock); + + platform_set_drvdata(pdev, pwm); + return 0; + +err_free_mem: + release_mem_region(r->start, r->end - r->start + 1); +err_free_clk: + clk_put(pwm->clk); +err_free: + kfree(pwm); + return ret; +} + +static int __devexit mxc_pwm_remove(struct platform_device *pdev) +{ + struct pwm_device *pwm; + struct resource *r; + + pwm = platform_get_drvdata(pdev); + if (pwm == NULL) + return -ENODEV; + + mutex_lock(&pwm_lock); + list_del(&pwm->node); + mutex_unlock(&pwm_lock); + + iounmap(pwm->mmio_base); + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(r->start, r->end - r->start + 1); + + clk_put(pwm->clk); + + kfree(pwm); + return 0; +} + +static struct platform_driver mxc_pwm_driver = { + .driver = { + .name = "mxc_pwm", + }, + .probe = mxc_pwm_probe, + .remove = __devexit_p(mxc_pwm_remove), +}; + +static int __init mxc_pwm_init(void) +{ + return platform_driver_register(&mxc_pwm_driver); +} +arch_initcall(mxc_pwm_init); + +static void __exit mxc_pwm_exit(void) +{ + platform_driver_unregister(&mxc_pwm_driver); +} +module_exit(mxc_pwm_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Sascha Hauer "); + -- GitLab From 824b16e66b70f5df61345f5708c149f6886eef30 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 16 Jan 2009 15:17:46 +0100 Subject: [PATCH 3274/4982] [ARM] MX2: add pwm device/resources Signed-off-by: Sascha Hauer --- arch/arm/mach-mx2/devices.c | 20 ++++++++++++++++++++ arch/arm/mach-mx2/devices.h | 1 + 2 files changed, 21 insertions(+) diff --git a/arch/arm/mach-mx2/devices.c b/arch/arm/mach-mx2/devices.c index 684d5d92c2e..bef418e0e60 100644 --- a/arch/arm/mach-mx2/devices.c +++ b/arch/arm/mach-mx2/devices.c @@ -281,6 +281,26 @@ struct platform_device mxc_fec_device = { }; #endif +static struct resource mxc_pwm_resources[] = { + [0] = { + .start = PWM_BASE_ADDR, + .end = PWM_BASE_ADDR + 0x0fff, + .flags = IORESOURCE_MEM + }, + [1] = { + .start = MXC_INT_PWM, + .end = MXC_INT_PWM, + .flags = IORESOURCE_IRQ, + } +}; + +struct platform_device mxc_pwm_device = { + .name = "mxc_pwm", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_pwm_resources), + .resource = mxc_pwm_resources +}; + /* GPIO port description */ static struct mxc_gpio_port imx_gpio_ports[] = { [0] = { diff --git a/arch/arm/mach-mx2/devices.h b/arch/arm/mach-mx2/devices.h index d85d5b26c98..94a241419af 100644 --- a/arch/arm/mach-mx2/devices.h +++ b/arch/arm/mach-mx2/devices.h @@ -15,3 +15,4 @@ extern struct platform_device mxc_w1_master_device; extern struct platform_device mxc_nand_device; extern struct platform_device mxc_fb_device; extern struct platform_device mxc_fec_device; +extern struct platform_device mxc_pwm_device; -- GitLab From c5d4dbff965b77b39c0188e4146892d76c775a98 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 28 Jan 2009 13:26:56 +0100 Subject: [PATCH 3275/4982] [ARM] MX2: Add I2C devices / resources Signed-off-by: Sascha Hauer --- arch/arm/mach-mx2/devices.c | 42 +++++++++++++++++++++++++++++++++++++ arch/arm/mach-mx2/devices.h | 2 ++ 2 files changed, 44 insertions(+) diff --git a/arch/arm/mach-mx2/devices.c b/arch/arm/mach-mx2/devices.c index bef418e0e60..7d12c2c4108 100644 --- a/arch/arm/mach-mx2/devices.c +++ b/arch/arm/mach-mx2/devices.c @@ -281,6 +281,48 @@ struct platform_device mxc_fec_device = { }; #endif +static struct resource mxc_i2c_1_resources[] = { + [0] = { + .start = I2C_BASE_ADDR, + .end = I2C_BASE_ADDR + 0x0fff, + .flags = IORESOURCE_MEM + }, + [1] = { + .start = MXC_INT_I2C, + .end = MXC_INT_I2C, + .flags = IORESOURCE_IRQ + } +}; + +struct platform_device mxc_i2c_device0 = { + .name = "imx-i2c", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_i2c_1_resources), + .resource = mxc_i2c_1_resources +}; + +#ifdef CONFIG_MACH_MX27 +static struct resource mxc_i2c_2_resources[] = { + [0] = { + .start = I2C2_BASE_ADDR, + .end = I2C2_BASE_ADDR + 0x0fff, + .flags = IORESOURCE_MEM + }, + [1] = { + .start = MXC_INT_I2C2, + .end = MXC_INT_I2C2, + .flags = IORESOURCE_IRQ + } +}; + +struct platform_device mxc_i2c_device1 = { + .name = "imx-i2c", + .id = 1, + .num_resources = ARRAY_SIZE(mxc_i2c_2_resources), + .resource = mxc_i2c_2_resources +}; +#endif + static struct resource mxc_pwm_resources[] = { [0] = { .start = PWM_BASE_ADDR, diff --git a/arch/arm/mach-mx2/devices.h b/arch/arm/mach-mx2/devices.h index 94a241419af..271ab1e6982 100644 --- a/arch/arm/mach-mx2/devices.h +++ b/arch/arm/mach-mx2/devices.h @@ -16,3 +16,5 @@ extern struct platform_device mxc_nand_device; extern struct platform_device mxc_fb_device; extern struct platform_device mxc_fec_device; extern struct platform_device mxc_pwm_device; +extern struct platform_device mxc_i2c_device0; +extern struct platform_device mxc_i2c_device1; -- GitLab From a4e9a65a1f90e94eca3af1a69b42d039054ef9de Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 28 Jan 2009 13:07:11 +0100 Subject: [PATCH 3276/4982] [ARM] PCM038 board: Add I2C support Signed-off-by: Sascha Hauer --- arch/arm/mach-mx2/pcm038.c | 59 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/arch/arm/mach-mx2/pcm038.c b/arch/arm/mach-mx2/pcm038.c index d246eb1bb3c..7d935e17aa1 100644 --- a/arch/arm/mach-mx2/pcm038.c +++ b/arch/arm/mach-mx2/pcm038.c @@ -21,11 +21,17 @@ #include #include #include +#include +#include + #include #include #include #include #include +#ifdef CONFIG_I2C_IMX +#include +#endif #include #include #include @@ -204,6 +210,51 @@ static void __init pcm038_init_sram(void) __raw_writel(0x22220a00, CSCR_A(1)); } +#ifdef CONFIG_I2C_IMX +static int mxc_i2c1_pins[] = { + PC5_PF_I2C2_SDA, + PC6_PF_I2C2_SCL +}; + +static int pcm038_i2c_1_init(struct device *dev) +{ + return mxc_gpio_setup_multiple_pins(mxc_i2c1_pins, ARRAY_SIZE(mxc_i2c1_pins), + "I2C1"); +} + +static void pcm038_i2c_1_exit(struct device *dev) +{ + mxc_gpio_release_multiple_pins(mxc_i2c1_pins, ARRAY_SIZE(mxc_i2c1_pins)); +} + +static struct imxi2c_platform_data pcm038_i2c_1_data = { + .bitrate = 100000, + .init = pcm038_i2c_1_init, + .exit = pcm038_i2c_1_exit, +}; + +static struct at24_platform_data board_eeprom = { + .byte_len = 4096, + .page_size = 32, + .flags = AT24_FLAG_ADDR16, +}; + +static struct i2c_board_info pcm038_i2c_devices[] = { + [0] = { + I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */ + .platform_data = &board_eeprom, + }, + [1] = { + I2C_BOARD_INFO("rtc-pcf8563", 0x51), + .type = "pcf8563" + }, + [2] = { + I2C_BOARD_INFO("lm75", 0x4a), + .type = "lm75" + } +}; +#endif + static void __init pcm038_init(void) { gpio_fec_active(); @@ -216,6 +267,14 @@ static void __init pcm038_init(void) mxc_gpio_mode(PE16_AF_OWIRE); mxc_register_device(&mxc_nand_device, &pcm038_nand_board_info); +#ifdef CONFIG_I2C_IMX + /* only the i2c master 1 is used on this CPU card */ + i2c_register_board_info(1, pcm038_i2c_devices, + ARRAY_SIZE(pcm038_i2c_devices)); + + mxc_register_device(&mxc_i2c_device1, &pcm038_i2c_1_data); +#endif + platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); #ifdef CONFIG_MACH_PCM970_BASEBOARD -- GitLab From b8b19b0d1c2d9ede8a3f8b9f609fd66cf5ede057 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 28 Jan 2009 14:06:20 +0100 Subject: [PATCH 3277/4982] [ARM] mx1ads: add I2C support Signed-off-by: Sascha Hauer --- arch/arm/mach-mx1/mx1ads.c | 63 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/arch/arm/mach-mx1/mx1ads.c b/arch/arm/mach-mx1/mx1ads.c index 09dc77bb481..89738fe576b 100644 --- a/arch/arm/mach-mx1/mx1ads.c +++ b/arch/arm/mach-mx1/mx1ads.c @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include #include @@ -24,6 +26,10 @@ #include #include #include +#include +#ifdef CONFIG_I2C_IMX +#include +#endif #include #include "devices.h" @@ -103,6 +109,55 @@ static struct platform_device flash_device = { .num_resources = 1, }; +/* + * I2C + */ + +#ifdef CONFIG_I2C_IMX +static int i2c_pins[] = { + PA15_PF_I2C_SDA, + PA16_PF_I2C_SCL, +}; + +static int i2c_init(struct device *dev) +{ + return mxc_gpio_setup_multiple_pins(i2c_pins, + ARRAY_SIZE(i2c_pins), "I2C"); +} + +static void i2c_exit(struct device *dev) +{ + mxc_gpio_release_multiple_pins(i2c_pins, + ARRAY_SIZE(i2c_pins)); +} + +static struct pcf857x_platform_data pcf857x_data[] = { + { + .gpio_base = 4 * 32, + }, { + .gpio_base = 4 * 32 + 16, + } +}; + +static struct imxi2c_platform_data mx1ads_i2c_data = { + .bitrate = 100000, + .init = i2c_init, + .exit = i2c_exit, +}; + +static struct i2c_board_info mx1ads_i2c_devices[] = { + { + I2C_BOARD_INFO("pcf857x", 0x22), + .type = "pcf8575", + .platform_data = &pcf857x_data[0], + }, { + I2C_BOARD_INFO("pcf857x", 0x24), + .type = "pcf8575", + .platform_data = &pcf857x_data[1], + }, +}; +#endif + /* * Board init */ @@ -114,6 +169,14 @@ static void __init mx1ads_init(void) /* Physmap flash */ mxc_register_device(&flash_device, &mx1ads_flash_data); + + /* I2C */ +#ifdef CONFIG_I2C_IMX + i2c_register_board_info(0, mx1ads_i2c_devices, + ARRAY_SIZE(mx1ads_i2c_devices)); + + mxc_register_device(&imx_i2c_device, &mx1ads_i2c_data); +#endif } static void __init mx1ads_timer_init(void) -- GitLab From c2aaac70cd00cf5d4687cc35f462e3888c9ac76f Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 28 Jan 2009 17:11:02 +0100 Subject: [PATCH 3278/4982] [ARM] iommux mx3: Add pin definitions for I2C Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/include/mach/iomux-mx3.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx3.h b/arch/arm/plat-mxc/include/mach/iomux-mx3.h index 4bdc4712be1..a38aa8510cb 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-mx3.h +++ b/arch/arm/plat-mxc/include/mach/iomux-mx3.h @@ -538,7 +538,9 @@ enum iomux_pins { #define MX31_PIN_CSPI1_SS1__SS1 IOMUX_MODE(MX31_PIN_CSPI1_SS1, IOMUX_CONFIG_FUNC) #define MX31_PIN_CSPI1_SS2__SS2 IOMUX_MODE(MX31_PIN_CSPI1_SS2, IOMUX_CONFIG_FUNC) #define MX31_PIN_CSPI2_MOSI__MOSI IOMUX_MODE(MX31_PIN_CSPI2_MOSI, IOMUX_CONFIG_FUNC) +#define MX31_PIN_CSPI2_MOSI__SCL IOMUX_MODE(MX31_PIN_CSPI2_MOSI, IOMUX_CONFIG_ALT1) #define MX31_PIN_CSPI2_MISO__MISO IOMUX_MODE(MX31_PIN_CSPI2_MISO, IOMUX_CONFIG_FUNC) +#define MX31_PIN_CSPI2_MISO__SDA IOMUX_MODE(MX31_PIN_CSPI2_MISO, IOMUX_CONFIG_ALT1) #define MX31_PIN_CSPI2_SCLK__SCLK IOMUX_MODE(MX31_PIN_CSPI2_SCLK, IOMUX_CONFIG_FUNC) #define MX31_PIN_CSPI2_SPI_RDY__SPI_RDY IOMUX_MODE(MX31_PIN_CSPI2_SPI_RDY, IOMUX_CONFIG_FUNC) #define MX31_PIN_CSPI2_SS0__SS0 IOMUX_MODE(MX31_PIN_CSPI2_SS0, IOMUX_CONFIG_FUNC) -- GitLab From 792067507b8bf5eaf220ee6994423381b7ae5c0b Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 28 Jan 2009 17:10:32 +0100 Subject: [PATCH 3279/4982] [ARM] PCM037 Board: Add I2C support Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/pcm037.c | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/arch/arm/mach-mx3/pcm037.c b/arch/arm/mach-mx3/pcm037.c index 18cda92432b..a05e37b731b 100644 --- a/arch/arm/mach-mx3/pcm037.c +++ b/arch/arm/mach-mx3/pcm037.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include @@ -37,6 +39,9 @@ #include #include #include +#ifdef CONFIG_I2C_IMX +#include +#endif #include "devices.h" @@ -117,6 +122,46 @@ static struct mxc_nand_platform_data pcm037_nand_board_info = { .hw_ecc = 1, }; +#ifdef CONFIG_I2C_IMX +static int i2c_1_pins[] = { + MX31_PIN_CSPI2_MOSI__SCL, + MX31_PIN_CSPI2_MISO__SDA, +}; + +static int pcm037_i2c_1_init(struct device *dev) +{ + return mxc_iomux_setup_multiple_pins(i2c_1_pins, ARRAY_SIZE(i2c_1_pins), + "i2c-1"); +} + +static void pcm037_i2c_1_exit(struct device *dev) +{ + mxc_iomux_release_multiple_pins(i2c_1_pins, ARRAY_SIZE(i2c_1_pins)); +} + +static struct imxi2c_platform_data pcm037_i2c_1_data = { + .bitrate = 100000, + .init = pcm037_i2c_1_init, + .exit = pcm037_i2c_1_exit, +}; + +static struct at24_platform_data board_eeprom = { + .byte_len = 4096, + .page_size = 32, + .flags = AT24_FLAG_ADDR16, +}; + +static struct i2c_board_info pcm037_i2c_devices[] = { + { + I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */ + .platform_data = &board_eeprom, + }, { + I2C_BOARD_INFO("rtc-pcf8563", 0x51), + .type = "pcf8563", + } +}; +#endif + static struct platform_device *devices[] __initdata = { &pcm037_flash, &pcm037_eth, @@ -156,6 +201,12 @@ static void __init mxc_board_init(void) "pcm037-eth")) gpio_direction_input(MX31_PIN_GPIO3_1); +#ifdef CONFIG_I2C_IMX + i2c_register_board_info(1, pcm037_i2c_devices, + ARRAY_SIZE(pcm037_i2c_devices)); + + mxc_register_device(&mxc_i2c_device1, &pcm037_i2c_1_data); +#endif mxc_register_device(&mxc_nand_device, &pcm037_nand_board_info); } -- GitLab From 2420563227897ed3900606e720f886e122944d2c Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 28 Jan 2009 17:36:37 +0100 Subject: [PATCH 3280/4982] [ARM] Add Synertronixx scb9328 board support Signed-off-by: Sascha Hauer --- arch/arm/mach-mx1/Kconfig | 4 + arch/arm/mach-mx1/Makefile | 1 + arch/arm/mach-mx1/scb9328.c | 160 ++++++++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 arch/arm/mach-mx1/scb9328.c diff --git a/arch/arm/mach-mx1/Kconfig b/arch/arm/mach-mx1/Kconfig index 2b59fc74784..f86cfcb6022 100644 --- a/arch/arm/mach-mx1/Kconfig +++ b/arch/arm/mach-mx1/Kconfig @@ -11,4 +11,8 @@ config ARCH_MX1ADS help Say Y here if you are using Motorola MX1ADS/MXLADS boards +config MACH_SCB9328 + bool "Synertronixx scb9328" + help + Say Y here if you are using a Synertronixx scb9328 board endif diff --git a/arch/arm/mach-mx1/Makefile b/arch/arm/mach-mx1/Makefile index b969719011f..82f1309568e 100644 --- a/arch/arm/mach-mx1/Makefile +++ b/arch/arm/mach-mx1/Makefile @@ -8,3 +8,4 @@ obj-y += generic.o clock.o devices.o # Specific board support obj-$(CONFIG_ARCH_MX1ADS) += mx1ads.o +obj-$(CONFIG_MACH_SCB9328) += scb9328.o \ No newline at end of file diff --git a/arch/arm/mach-mx1/scb9328.c b/arch/arm/mach-mx1/scb9328.c new file mode 100644 index 00000000000..0e71f3fa28b --- /dev/null +++ b/arch/arm/mach-mx1/scb9328.c @@ -0,0 +1,160 @@ +/* + * linux/arch/arm/mach-mx1/scb9328.c + * + * Copyright (c) 2004 Sascha Hauer + * Copyright (c) 2006-2008 Juergen Beisert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "devices.h" + +/* + * This scb9328 has a 32MiB flash + */ +static struct resource flash_resource = { + .start = IMX_CS0_PHYS, + .end = IMX_CS0_PHYS + (32 * 1024 * 1024) - 1, + .flags = IORESOURCE_MEM, +}; + +static struct physmap_flash_data scb_flash_data = { + .width = 2, +}; + +static struct platform_device scb_flash_device = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &scb_flash_data, + }, + .resource = &flash_resource, + .num_resources = 1, +}; + +/* + * scb9328 has a DM9000 network controller + * connected to CS5, with 16 bit data path + * and interrupt connected to GPIO 3 + */ + +/* + * internal datapath is fixed 16 bit + */ +static struct dm9000_plat_data dm9000_platdata = { + .flags = DM9000_PLATF_16BITONLY, +}; + +/* + * the DM9000 drivers wants two defined address spaces + * to gain access to address latch registers and the data path. + */ +static struct resource dm9000x_resources[] = { + [0] = { + .name = "address area", + .start = IMX_CS5_PHYS, + .end = IMX_CS5_PHYS + 1, + .flags = IORESOURCE_MEM /* address access */ + }, + [1] = { + .name = "data area", + .start = IMX_CS5_PHYS + 4, + .end = IMX_CS5_PHYS + 5, + .flags = IORESOURCE_MEM /* data access */ + }, + [2] = { + .start = IRQ_GPIOC(3), + .end = IRQ_GPIOC(3), + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL + }, +}; + +static struct platform_device dm9000x_device = { + .name = "dm9000", + .id = 0, + .num_resources = ARRAY_SIZE(dm9000x_resources), + .resource = dm9000x_resources, + .dev = { + .platform_data = &dm9000_platdata, + } +}; + +static int mxc_uart1_pins[] = { + PC9_PF_UART1_CTS, + PC10_PF_UART1_RTS, + PC11_PF_UART1_TXD, + PC12_PF_UART1_RXD, +}; + +static int uart1_mxc_init(struct platform_device *pdev) +{ + return mxc_gpio_setup_multiple_pins(mxc_uart1_pins, + ARRAY_SIZE(mxc_uart1_pins), "UART1"); +} + +static int uart1_mxc_exit(struct platform_device *pdev) +{ + mxc_gpio_release_multiple_pins(mxc_uart1_pins, + ARRAY_SIZE(mxc_uart1_pins)); + return 0; +} + +static struct imxuart_platform_data uart_pdata = { + .init = uart1_mxc_init, + .exit = uart1_mxc_exit, + .flags = IMXUART_HAVE_RTSCTS, +}; + +static struct platform_device *devices[] __initdata = { + &scb_flash_device, + &dm9000x_device, +}; + +/* + * scb9328_init - Init the CPU card itself + */ +static void __init scb9328_init(void) +{ + mxc_register_device(&imx_uart1_device, &uart_pdata); + + printk(KERN_INFO"Scb9328: Adding devices\n"); + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +static void __init scb9328_timer_init(void) +{ + mx1_clocks_init(32000); +} + +static struct sys_timer scb9328_timer = { + .init = scb9328_timer_init, +}; + +MACHINE_START(SCB9328, "Synertronixx scb9328") + /* Sascha Hauer */ + .phys_io = 0x00200000, + .io_pg_offst = ((0xe0200000) >> 18) & 0xfffc, + .boot_params = 0x08000100, + .map_io = mxc_map_io, + .init_irq = mxc_init_irq, + .timer = &scb9328_timer, + .init_machine = scb9328_init, +MACHINE_END -- GitLab From 87bbb19721fbd6b5e556105c188da80d06f738b1 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 29 Jan 2009 16:00:23 +0100 Subject: [PATCH 3281/4982] [ARM] mxc: add missing include include devices.h from devices.c to avoid inconsistencies and to fix sparse warnings Signed-off-by: Sascha Hauer --- arch/arm/mach-mx1/devices.c | 2 ++ arch/arm/mach-mx3/devices.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arch/arm/mach-mx1/devices.c b/arch/arm/mach-mx1/devices.c index cea8f2c7119..97f42d96d7a 100644 --- a/arch/arm/mach-mx1/devices.c +++ b/arch/arm/mach-mx1/devices.c @@ -26,6 +26,8 @@ #include #include +#include "devices.h" + static struct resource imx_csi_resources[] = { [0] = { .start = 0x00224000, diff --git a/arch/arm/mach-mx3/devices.c b/arch/arm/mach-mx3/devices.c index c48a341bccf..7cfdef0aad4 100644 --- a/arch/arm/mach-mx3/devices.c +++ b/arch/arm/mach-mx3/devices.c @@ -25,6 +25,8 @@ #include #include +#include "devices.h" + static struct resource uart0[] = { { .start = UART1_BASE_ADDR, -- GitLab From 6bbdbf2f95771c0a2dbccc423b99b37fde9a5078 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Thu, 29 Jan 2009 14:42:25 +0100 Subject: [PATCH 3282/4982] arm/imx: Kconfig beautification Signed-off-by: Holger Schurig Signed-off-by: Sascha Hauer --- arch/arm/mach-mx1/Kconfig | 3 ++- arch/arm/mach-mx2/Kconfig | 13 +++++-------- arch/arm/mach-mx3/Kconfig | 8 ++++---- arch/arm/plat-mxc/Kconfig | 2 +- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/arch/arm/mach-mx1/Kconfig b/arch/arm/mach-mx1/Kconfig index f86cfcb6022..eb7660f5d4b 100644 --- a/arch/arm/mach-mx1/Kconfig +++ b/arch/arm/mach-mx1/Kconfig @@ -1,6 +1,6 @@ if ARCH_MX1 -comment "MX1 Platforms" +comment "MX1 platforms:" config MACH_MXLADS bool @@ -15,4 +15,5 @@ config MACH_SCB9328 bool "Synertronixx scb9328" help Say Y here if you are using a Synertronixx scb9328 board + endif diff --git a/arch/arm/mach-mx2/Kconfig b/arch/arm/mach-mx2/Kconfig index 412d2d55b08..42a788842f4 100644 --- a/arch/arm/mach-mx2/Kconfig +++ b/arch/arm/mach-mx2/Kconfig @@ -1,27 +1,22 @@ -comment "MX2 family CPU support" - depends on ARCH_MX2 +if ARCH_MX2 choice - prompt "MX2 Type" - depends on ARCH_MX2 + prompt "CPUs:" default MACH_MX21 config MACH_MX21 bool "i.MX21 support" - depends on ARCH_MX2 help This enables support for Freescale's MX2 based i.MX21 processor. config MACH_MX27 bool "i.MX27 support" - depends on ARCH_MX2 help This enables support for Freescale's MX2 based i.MX27 processor. endchoice -comment "MX2 Platforms" - depends on ARCH_MX2 +comment "MX2 platforms:" config MACH_MX27ADS bool "MX27ADS platform" @@ -50,3 +45,5 @@ config MACH_PCM970_BASEBOARD PCM970 evaluation board. endchoice + +endif diff --git a/arch/arm/mach-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig index 6fea5419632..6933d2d0b56 100644 --- a/arch/arm/mach-mx3/Kconfig +++ b/arch/arm/mach-mx3/Kconfig @@ -1,5 +1,6 @@ -menu "MX3 Options" - depends on ARCH_MX3 +if ARCH_MX3 + +comment "MX3 platforms:" config MACH_MX31ADS bool "Support MX31ADS platforms" @@ -44,5 +45,4 @@ config MACH_MX31MOBOARD Include support for mx31moboard platform. This includes specific configurations for the board and its peripherals. -endmenu - +endif diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig index 71c3c848b0e..ed5ab8ed7cf 100644 --- a/arch/arm/plat-mxc/Kconfig +++ b/arch/arm/plat-mxc/Kconfig @@ -3,7 +3,7 @@ if ARCH_MXC menu "Freescale MXC Implementations" choice - prompt "MXC/iMX Base Type" + prompt "Freescale CPU family:" default ARCH_MX3 config ARCH_MX1 -- GitLab From 999981d943e626bff5d031de1bf06435afb10ced Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 12 Feb 2009 14:27:22 +0100 Subject: [PATCH 3283/4982] mxc: first set GPIO level, then switch direction to output Make sure not to create spurious pulses on GPIOs, when configuring them as output: first set required level, then switch direction. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c index ccbd94adc66..c6483bad8a2 100644 --- a/arch/arm/plat-mxc/gpio.c +++ b/arch/arm/plat-mxc/gpio.c @@ -200,8 +200,8 @@ static int mxc_gpio_direction_input(struct gpio_chip *chip, unsigned offset) static int mxc_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { - _set_gpio_direction(chip, offset, 1); mxc_gpio_set(chip, offset, value); + _set_gpio_direction(chip, offset, 1); return 0; } -- GitLab From e180a5c26fae12dcc02244df68a6089cd5522df7 Mon Sep 17 00:00:00 2001 From: Valentin Longchamp Date: Wed, 11 Feb 2009 16:55:17 +0100 Subject: [PATCH 3284/4982] mx31: add pin definition for LCD Signed-off-by: Valentin Longchamp Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/include/mach/iomux-mx3.h | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx3.h b/arch/arm/plat-mxc/include/mach/iomux-mx3.h index a38aa8510cb..ab838cfe94f 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-mx3.h +++ b/arch/arm/plat-mxc/include/mach/iomux-mx3.h @@ -558,6 +558,33 @@ enum iomux_pins { #define MX31_PIN_SD1_DATA0__SD1_DATA0 IOMUX_MODE(MX31_PIN_SD1_DATA0, IOMUX_CONFIG_FUNC) #define MX31_PIN_SD1_CLK__SD1_CLK IOMUX_MODE(MX31_PIN_SD1_CLK, IOMUX_CONFIG_FUNC) #define MX31_PIN_SD1_CMD__SD1_CMD IOMUX_MODE(MX31_PIN_SD1_CMD, IOMUX_CONFIG_FUNC) +#define MX31_PIN_LD0__LD0 IOMUX_MODE(MX31_PIN_LD0, IOMUX_CONFIG_FUNC) +#define MX31_PIN_LD1__LD1 IOMUX_MODE(MX31_PIN_LD1, IOMUX_CONFIG_FUNC) +#define MX31_PIN_LD2__LD2 IOMUX_MODE(MX31_PIN_LD2, IOMUX_CONFIG_FUNC) +#define MX31_PIN_LD3__LD3 IOMUX_MODE(MX31_PIN_LD3, IOMUX_CONFIG_FUNC) +#define MX31_PIN_LD4__LD4 IOMUX_MODE(MX31_PIN_LD4, IOMUX_CONFIG_FUNC) +#define MX31_PIN_LD5__LD5 IOMUX_MODE(MX31_PIN_LD5, IOMUX_CONFIG_FUNC) +#define MX31_PIN_LD6__LD6 IOMUX_MODE(MX31_PIN_LD6, IOMUX_CONFIG_FUNC) +#define MX31_PIN_LD7__LD7 IOMUX_MODE(MX31_PIN_LD7, IOMUX_CONFIG_FUNC) +#define MX31_PIN_LD8__LD8 IOMUX_MODE(MX31_PIN_LD8, IOMUX_CONFIG_FUNC) +#define MX31_PIN_LD9__LD9 IOMUX_MODE(MX31_PIN_LD9, IOMUX_CONFIG_FUNC) +#define MX31_PIN_LD10__LD10 IOMUX_MODE(MX31_PIN_LD10, IOMUX_CONFIG_FUNC) +#define MX31_PIN_LD11__LD11 IOMUX_MODE(MX31_PIN_LD11, IOMUX_CONFIG_FUNC) +#define MX31_PIN_LD12__LD12 IOMUX_MODE(MX31_PIN_LD12, IOMUX_CONFIG_FUNC) +#define MX31_PIN_LD13__LD13 IOMUX_MODE(MX31_PIN_LD13, IOMUX_CONFIG_FUNC) +#define MX31_PIN_LD14__LD14 IOMUX_MODE(MX31_PIN_LD14, IOMUX_CONFIG_FUNC) +#define MX31_PIN_LD15__LD15 IOMUX_MODE(MX31_PIN_LD15, IOMUX_CONFIG_FUNC) +#define MX31_PIN_LD16__LD16 IOMUX_MODE(MX31_PIN_LD16, IOMUX_CONFIG_FUNC) +#define MX31_PIN_LD17__LD17 IOMUX_MODE(MX31_PIN_LD17, IOMUX_CONFIG_FUNC) +#define MX31_PIN_VSYNC3__VSYNC3 IOMUX_MODE(MX31_PIN_VSYNC3, IOMUX_CONFIG_FUNC) +#define MX31_PIN_HSYNC__HSYNC IOMUX_MODE(MX31_PIN_HSYNC, IOMUX_CONFIG_FUNC) +#define MX31_PIN_FPSHIFT__FPSHIFT IOMUX_MODE(MX31_PIN_FPSHIFT, IOMUX_CONFIG_FUNC) +#define MX31_PIN_DRDY0__DRDY0 IOMUX_MODE(MX31_PIN_DRDY0, IOMUX_CONFIG_FUNC) +#define MX31_PIN_D3_REV__D3_REV IOMUX_MODE(MX31_PIN_D3_REV, IOMUX_CONFIG_FUNC) +#define MX31_PIN_CONTRAST__CONTRAST IOMUX_MODE(MX31_PIN_CONTRAST, IOMUX_CONFIG_FUNC) +#define MX31_PIN_D3_SPL__D3_SPL IOMUX_MODE(MX31_PIN_D3_SPL, IOMUX_CONFIG_FUNC) +#define MX31_PIN_D3_CLS__D3_CLS IOMUX_MODE(MX31_PIN_D3_CLS, IOMUX_CONFIG_FUNC) +#define MX31_PIN_LCS0__GPI03_23 IOMUX_MODE(MX31_PIN_LCS0, IOMUX_CONFIG_GPIO) /*XXX: The SS0, SS1, SS2, SS3 lines of spi3 are multiplexed by cspi2_ss0, cspi2_ss1, cspi1_ss0 * cspi1_ss1*/ -- GitLab From e00f0b4a9316c9de000697e489f6102271e94dc4 Mon Sep 17 00:00:00 2001 From: Valentin Longchamp Date: Mon, 16 Feb 2009 12:47:51 +0100 Subject: [PATCH 3285/4982] mx31moboard: initial support for various baseboards This enables our mx31moboard to be used on the different baseboards that we are developping according to the application needs. There are not many differences between the boards for now, but when other peripherals are available for mx31 the differences are going to grow. v2: takes Sascha's comments into account Signed-off-by: Valentin Longchamp Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/Makefile | 3 +- arch/arm/mach-mx3/mx31moboard-devboard.c | 48 +++++++++++++++++++ arch/arm/mach-mx3/mx31moboard-marxbot.c | 37 ++++++++++++++ arch/arm/mach-mx3/mx31moboard.c | 39 ++++++++------- .../plat-mxc/include/mach/board-mx31moboard.h | 45 +++++++++++++++++ 5 files changed, 154 insertions(+), 18 deletions(-) create mode 100644 arch/arm/mach-mx3/mx31moboard-devboard.c create mode 100644 arch/arm/mach-mx3/mx31moboard-marxbot.c create mode 100644 arch/arm/plat-mxc/include/mach/board-mx31moboard.h diff --git a/arch/arm/mach-mx3/Makefile b/arch/arm/mach-mx3/Makefile index 5a151540fe8..d50d9878a65 100644 --- a/arch/arm/mach-mx3/Makefile +++ b/arch/arm/mach-mx3/Makefile @@ -9,4 +9,5 @@ obj-$(CONFIG_MACH_MX31ADS) += mx31ads.o obj-$(CONFIG_MACH_MX31LITE) += mx31lite.o obj-$(CONFIG_MACH_PCM037) += pcm037.o obj-$(CONFIG_MACH_MX31_3DS) += mx31pdk.o -obj-$(CONFIG_MACH_MX31MOBOARD) += mx31moboard.o +obj-$(CONFIG_MACH_MX31MOBOARD) += mx31moboard.o mx31moboard-devboard.o \ + mx31moboard-marxbot.o diff --git a/arch/arm/mach-mx3/mx31moboard-devboard.c b/arch/arm/mach-mx3/mx31moboard-devboard.c new file mode 100644 index 00000000000..d080b4add79 --- /dev/null +++ b/arch/arm/mach-mx3/mx31moboard-devboard.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2009 Valentin Longchamp, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include + +#include +#include +#include +#include + +#include "devices.h" + +static struct imxuart_platform_data uart_pdata = { + .flags = IMXUART_HAVE_RTSCTS, +}; + +static int mxc_uart1_pins[] = { + MX31_PIN_CTS2__CTS2, MX31_PIN_RTS2__RTS2, + MX31_PIN_TXD2__TXD2, MX31_PIN_RXD2__RXD2, +}; + +/* + * system init for baseboard usage. Will be called by mx31moboard init. + */ +void __init mx31moboard_devboard_init(void) +{ + printk(KERN_INFO "Initializing mx31devboard peripherals\n"); + mxc_iomux_setup_multiple_pins(mxc_uart1_pins, ARRAY_SIZE(mxc_uart1_pins), "uart1"); + mxc_register_device(&mxc_uart_device1, &uart_pdata); +} diff --git a/arch/arm/mach-mx3/mx31moboard-marxbot.c b/arch/arm/mach-mx3/mx31moboard-marxbot.c new file mode 100644 index 00000000000..9ef9566823f --- /dev/null +++ b/arch/arm/mach-mx3/mx31moboard-marxbot.c @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2009 Valentin Longchamp, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include + +#include +#include +#include +#include + +#include "devices.h" + +/* + * system init for baseboard usage. Will be called by mx31moboard init. + */ +void __init mx31moboard_marxbot_init(void) +{ + printk(KERN_INFO "Initializing mx31marxbot peripherals\n"); +} diff --git a/arch/arm/mach-mx3/mx31moboard.c b/arch/arm/mach-mx3/mx31moboard.c index f29c8782cff..2d51739e24b 100644 --- a/arch/arm/mach-mx3/mx31moboard.c +++ b/arch/arm/mach-mx3/mx31moboard.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "devices.h" @@ -64,24 +65,17 @@ static struct platform_device *devices[] __initdata = { }; static int mxc_uart0_pins[] = { - MX31_PIN_CTS1__CTS1, - MX31_PIN_RTS1__RTS1, - MX31_PIN_TXD1__TXD1, - MX31_PIN_RXD1__RXD1 -}; -static int mxc_uart1_pins[] = { - MX31_PIN_CTS2__CTS2, - MX31_PIN_RTS2__RTS2, - MX31_PIN_TXD2__TXD2, - MX31_PIN_RXD2__RXD2 + MX31_PIN_CTS1__CTS1, MX31_PIN_RTS1__RTS1, + MX31_PIN_TXD1__TXD1, MX31_PIN_RXD1__RXD1, }; static int mxc_uart4_pins[] = { - MX31_PIN_PC_RST__CTS5, - MX31_PIN_PC_VS2__RTS5, - MX31_PIN_PC_BVD2__TXD5, - MX31_PIN_PC_BVD1__RXD5 + MX31_PIN_PC_RST__CTS5, MX31_PIN_PC_VS2__RTS5, + MX31_PIN_PC_BVD2__TXD5, MX31_PIN_PC_BVD1__RXD5, }; +static int mx31moboard_baseboard; +core_param(mx31moboard_baseboard, mx31moboard_baseboard, int, 0444); + /* * Board specific initialization. */ @@ -92,11 +86,22 @@ static void __init mxc_board_init(void) mxc_iomux_setup_multiple_pins(mxc_uart0_pins, ARRAY_SIZE(mxc_uart0_pins), "uart0"); mxc_register_device(&mxc_uart_device0, &uart_pdata); - mxc_iomux_setup_multiple_pins(mxc_uart1_pins, ARRAY_SIZE(mxc_uart1_pins), "uart1"); - mxc_register_device(&mxc_uart_device1, &uart_pdata); - mxc_iomux_setup_multiple_pins(mxc_uart4_pins, ARRAY_SIZE(mxc_uart4_pins), "uart4"); mxc_register_device(&mxc_uart_device4, &uart_pdata); + + switch (mx31moboard_baseboard) { + case MX31NOBOARD: + break; + case MX31DEVBOARD: + mx31moboard_devboard_init(); + break; + case MX31MARXBOT: + mx31moboard_marxbot_init(); + break; + default: + printk(KERN_ERR "Illegal mx31moboard_baseboard type %d\n", mx31moboard_baseboard); + } + } /* diff --git a/arch/arm/plat-mxc/include/mach/board-mx31moboard.h b/arch/arm/plat-mxc/include/mach/board-mx31moboard.h new file mode 100644 index 00000000000..f8aef1babb7 --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/board-mx31moboard.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2009 Valentin Longchamp, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef __ASM_ARCH_MXC_BOARD_MX31MOBOARD_H__ +#define __ASM_ARCH_MXC_BOARD_MX31MOBOARD_H__ + +/* mandatory for CONFIG_LL_DEBUG */ + +#define MXC_LL_UART_PADDR UART1_BASE_ADDR +#define MXC_LL_UART_VADDR (AIPI_BASE_ADDR_VIRT + 0x0A000) + +#ifndef __ASSEMBLY__ + +enum mx31moboard_boards { + MX31NOBOARD = 0, + MX31DEVBOARD = 1, + MX31MARXBOT = 2, +}; + +/* + * This CPU module needs a baseboard to work. After basic initializing + * its own devices, it calls baseboard's init function. + */ + +extern void mx31moboard_devboard_init(void); +extern void mx31moboard_marxbot_init(void); + +#endif + +#endif /* __ASM_ARCH_MXC_BOARD_MX31MOBOARD_H__ */ -- GitLab From ca489f8e4ac1127e6aee1ffcdaea29858f89506c Mon Sep 17 00:00:00 2001 From: Valentin Longchamp Date: Mon, 16 Feb 2009 12:47:52 +0100 Subject: [PATCH 3286/4982] mx31: add dma and fb devices This adds the dma (ipu_dma) and fb devices for the mx31 for which drivers now are available. v2: merge the ipu and fb device in the same patch as suggested by Sascha Signed-off-by: Valentin Longchamp Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/devices.c | 48 +++++++++++++++++++++++++++++++++ arch/arm/mach-mx3/devices.h | 2 ++ arch/arm/mach-mx3/mx31moboard.c | 1 - 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-mx3/devices.c b/arch/arm/mach-mx3/devices.c index 7cfdef0aad4..b7d4900b02e 100644 --- a/arch/arm/mach-mx3/devices.c +++ b/arch/arm/mach-mx3/devices.c @@ -242,3 +242,51 @@ struct platform_device mxc_i2c_device2 = { .num_resources = ARRAY_SIZE(mxc_i2c2_resources), .resource = mxc_i2c2_resources, }; + +/* i.MX31 Image Processing Unit */ + +/* The resource order is important! */ +static struct resource mx3_ipu_rsrc[] = { + { + .start = IPU_CTRL_BASE_ADDR, + .end = IPU_CTRL_BASE_ADDR + 0x5F, + .flags = IORESOURCE_MEM, + }, { + .start = IPU_CTRL_BASE_ADDR + 0x88, + .end = IPU_CTRL_BASE_ADDR + 0xB3, + .flags = IORESOURCE_MEM, + }, { + .start = MXC_INT_IPU_SYN, + .end = MXC_INT_IPU_SYN, + .flags = IORESOURCE_IRQ, + }, { + .start = MXC_INT_IPU_ERR, + .end = MXC_INT_IPU_ERR, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mx3_ipu = { + .name = "ipu-core", + .id = -1, + .num_resources = ARRAY_SIZE(mx3_ipu_rsrc), + .resource = mx3_ipu_rsrc, +}; + +static struct resource fb_resources[] = { + { + .start = IPU_CTRL_BASE_ADDR + 0xB4, + .end = IPU_CTRL_BASE_ADDR + 0x1BF, + .flags = IORESOURCE_MEM, + }, +}; + +struct platform_device mx3_fb = { + .name = "mx3_sdc_fb", + .id = -1, + .num_resources = ARRAY_SIZE(fb_resources), + .resource = fb_resources, + .dev = { + .coherent_dma_mask = 0xffffffff, + }, +}; diff --git a/arch/arm/mach-mx3/devices.h b/arch/arm/mach-mx3/devices.h index 077a90226a7..d1638518a9d 100644 --- a/arch/arm/mach-mx3/devices.h +++ b/arch/arm/mach-mx3/devices.h @@ -9,3 +9,5 @@ extern struct platform_device mxc_nand_device; extern struct platform_device mxc_i2c_device0; extern struct platform_device mxc_i2c_device1; extern struct platform_device mxc_i2c_device2; +extern struct platform_device mx3_ipu; +extern struct platform_device mx3_fb; diff --git a/arch/arm/mach-mx3/mx31moboard.c b/arch/arm/mach-mx3/mx31moboard.c index 2d51739e24b..b30460a2a55 100644 --- a/arch/arm/mach-mx3/mx31moboard.c +++ b/arch/arm/mach-mx3/mx31moboard.c @@ -101,7 +101,6 @@ static void __init mxc_board_init(void) default: printk(KERN_ERR "Illegal mx31moboard_baseboard type %d\n", mx31moboard_baseboard); } - } /* -- GitLab From 1d0f98709347c4babac08dd933466674e089f188 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 26 Jan 2009 17:29:10 +0100 Subject: [PATCH 3287/4982] imxfb: add mx27 support Signed-off-by: Sascha Hauer --- drivers/video/imxfb.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 5c61286d7ff..9dd27576db7 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -43,7 +43,12 @@ #define LCDC_SIZE 0x04 #define SIZE_XMAX(x) ((((x) >> 4) & 0x3f) << 20) + +#ifdef CONFIG_ARCH_MX1 #define SIZE_YMAX(y) ((y) & 0x1ff) +#else +#define SIZE_YMAX(y) ((y) & 0x3ff) +#endif #define LCDC_VPW 0x08 #define VPW_VPW(x) ((x) & 0x3ff) @@ -53,7 +58,12 @@ #define CPOS_CC0 (1<<30) #define CPOS_OP (1<<28) #define CPOS_CXP(x) (((x) & 3ff) << 16) + +#ifdef CONFIG_ARCH_MX1 #define CPOS_CYP(y) ((y) & 0x1ff) +#else +#define CPOS_CYP(y) ((y) & 0x3ff) +#endif #define LCDC_LCWHB 0x10 #define LCWHB_BK_EN (1<<31) @@ -62,9 +72,16 @@ #define LCWHB_BD(x) ((x) & 0xff) #define LCDC_LCHCC 0x14 + +#ifdef CONFIG_ARCH_MX1 #define LCHCC_CUR_COL_R(r) (((r) & 0x1f) << 11) #define LCHCC_CUR_COL_G(g) (((g) & 0x3f) << 5) #define LCHCC_CUR_COL_B(b) ((b) & 0x1f) +#else +#define LCHCC_CUR_COL_R(r) (((r) & 0x3f) << 12) +#define LCHCC_CUR_COL_G(g) (((g) & 0x3f) << 6) +#define LCHCC_CUR_COL_B(b) ((b) & 0x3f) +#endif #define LCDC_PCR 0x18 @@ -91,7 +108,13 @@ /* bit fields in imxfb.h */ #define LCDC_RMCR 0x34 + +#ifdef CONFIG_ARCH_MX1 #define RMCR_LCDC_EN (1<<1) +#else +#define RMCR_LCDC_EN 0 +#endif + #define RMCR_SELF_REF (1<<0) #define LCDC_LCDICR 0x38 @@ -365,10 +388,6 @@ static void imxfb_enable_controller(struct imxfb_info *fbi) { pr_debug("Enabling LCD controller\n"); - /* initialize LCDC */ - writel(readl(fbi->regs + LCDC_RMCR) & ~RMCR_LCDC_EN, - fbi->regs + LCDC_RMCR); /* just to be safe... */ - writel(fbi->screen_dma, fbi->regs + LCDC_SSA); /* physical screen start address */ -- GitLab From 7e8549bcee00d92040904361cb1840c7a5eda615 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sat, 14 Feb 2009 16:29:38 +0100 Subject: [PATCH 3288/4982] imxfb: Fix margin settings The var->hsync_len, var->right_margin and var->left_margin fields should contain the real values, not the hardware dependent values. Signed-off-by: Sascha Hauer --- drivers/video/imxfb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 9dd27576db7..bd1cb75cd14 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -495,9 +495,9 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf info->fix.id, var->lower_margin); #endif - writel(HCR_H_WIDTH(var->hsync_len) | - HCR_H_WAIT_1(var->right_margin) | - HCR_H_WAIT_2(var->left_margin), + writel(HCR_H_WIDTH(var->hsync_len - 1) | + HCR_H_WAIT_1(var->right_margin - 1) | + HCR_H_WAIT_2(var->left_margin - 3), fbi->regs + LCDC_HCR); writel(VCR_V_WIDTH(var->vsync_len) | -- GitLab From c0a5f85523132dc893916d6059370233fac1cb11 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 2 Feb 2009 14:11:54 +0100 Subject: [PATCH 3289/4982] [ARM] MX35: Add register definitions for the i.MX35 This patch moves the stuff common to i.MX31 and i.MX35 to mx3x.h and the specifics to mx31.h/mx35.h. We can build a kernel which runs on i.MX31 and i.MX35, so always include mx31.h and mx35.h Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/include/mach/hardware.h | 4 +- arch/arm/plat-mxc/include/mach/mx31.h | 329 +--------------------- arch/arm/plat-mxc/include/mach/mx35.h | 29 ++ arch/arm/plat-mxc/include/mach/mx3x.h | 290 +++++++++++++++++++ 4 files changed, 329 insertions(+), 323 deletions(-) create mode 100644 arch/arm/plat-mxc/include/mach/mx35.h create mode 100644 arch/arm/plat-mxc/include/mach/mx3x.h diff --git a/arch/arm/plat-mxc/include/mach/hardware.h b/arch/arm/plat-mxc/include/mach/hardware.h index 11f5727ea44..42e4ee37ca1 100644 --- a/arch/arm/plat-mxc/include/mach/hardware.h +++ b/arch/arm/plat-mxc/include/mach/hardware.h @@ -23,7 +23,9 @@ #include #ifdef CONFIG_ARCH_MX3 -# include +#include +#include +#include #endif #ifdef CONFIG_ARCH_MX2 diff --git a/arch/arm/plat-mxc/include/mach/mx31.h b/arch/arm/plat-mxc/include/mach/mx31.h index de026654b00..0b06941b613 100644 --- a/arch/arm/plat-mxc/include/mach/mx31.h +++ b/arch/arm/plat-mxc/include/mach/mx31.h @@ -1,360 +1,45 @@ -/* - * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __ASM_ARCH_MXC_MX31_H__ -#define __ASM_ARCH_MXC_MX31_H__ - -#ifndef __ASM_ARCH_MXC_HARDWARE_H__ -#error "Do not include directly." -#endif - -/* - * MX31 memory map: - * - * Virt Phys Size What - * --------------------------------------------------------------------------- - * F8000000 1FFC0000 16K IRAM - * F9000000 30000000 256M L2CC - * FC000000 43F00000 1M AIPS 1 - * FC100000 50000000 1M SPBA - * FC200000 53F00000 1M AIPS 2 - * FC500000 60000000 128M ROMPATCH - * FC400000 68000000 128M AVIC - * 70000000 256M IPU (MAX M2) - * 80000000 256M CSD0 SDRAM/DDR - * 90000000 256M CSD1 SDRAM/DDR - * A0000000 128M CS0 Flash - * A8000000 128M CS1 Flash - * B0000000 32M CS2 - * B2000000 32M CS3 - * F4000000 B4000000 32M CS4 - * B6000000 32M CS5 - * FC320000 B8000000 64K NAND, SDRAM, WEIM, M3IF, EMI controllers - * C0000000 64M PCMCIA/CF - */ - -#define CS0_BASE_ADDR 0xA0000000 -#define CS1_BASE_ADDR 0xA8000000 -#define CS2_BASE_ADDR 0xB0000000 -#define CS3_BASE_ADDR 0xB2000000 - -#define CS4_BASE_ADDR 0xB4000000 -#define CS4_BASE_ADDR_VIRT 0xF4000000 -#define CS4_SIZE SZ_32M - -#define CS5_BASE_ADDR 0xB6000000 -#define PCMCIA_MEM_BASE_ADDR 0xBC000000 - /* * IRAM */ -#define IRAM_BASE_ADDR 0x1FFC0000 /* internal ram */ -#define IRAM_BASE_ADDR_VIRT 0xF8000000 -#define IRAM_SIZE SZ_16K - -/* - * L2CC - */ -#define L2CC_BASE_ADDR 0x30000000 -#define L2CC_BASE_ADDR_VIRT 0xF9000000 -#define L2CC_SIZE SZ_1M - -/* - * AIPS 1 - */ -#define AIPS1_BASE_ADDR 0x43F00000 -#define AIPS1_BASE_ADDR_VIRT 0xFC000000 -#define AIPS1_SIZE SZ_1M +#define MX31_IRAM_BASE_ADDR 0x1FFC0000 /* internal ram */ +#define MX31_IRAM_SIZE SZ_16K -#define MAX_BASE_ADDR (AIPS1_BASE_ADDR + 0x00004000) -#define EVTMON_BASE_ADDR (AIPS1_BASE_ADDR + 0x00008000) -#define CLKCTL_BASE_ADDR (AIPS1_BASE_ADDR + 0x0000C000) -#define ETB_SLOT4_BASE_ADDR (AIPS1_BASE_ADDR + 0x00010000) -#define ETB_SLOT5_BASE_ADDR (AIPS1_BASE_ADDR + 0x00014000) -#define ECT_CTIO_BASE_ADDR (AIPS1_BASE_ADDR + 0x00018000) -#define I2C_BASE_ADDR (AIPS1_BASE_ADDR + 0x00080000) -#define I2C3_BASE_ADDR (AIPS1_BASE_ADDR + 0x00084000) #define OTG_BASE_ADDR (AIPS1_BASE_ADDR + 0x00088000) #define ATA_BASE_ADDR (AIPS1_BASE_ADDR + 0x0008C000) -#define UART1_BASE_ADDR (AIPS1_BASE_ADDR + 0x00090000) -#define UART2_BASE_ADDR (AIPS1_BASE_ADDR + 0x00094000) -#define I2C2_BASE_ADDR (AIPS1_BASE_ADDR + 0x00098000) -#define OWIRE_BASE_ADDR (AIPS1_BASE_ADDR + 0x0009C000) -#define SSI1_BASE_ADDR (AIPS1_BASE_ADDR + 0x000A0000) -#define CSPI1_BASE_ADDR (AIPS1_BASE_ADDR + 0x000A4000) -#define KPP_BASE_ADDR (AIPS1_BASE_ADDR + 0x000A8000) -#define IOMUXC_BASE_ADDR (AIPS1_BASE_ADDR + 0x000AC000) #define UART4_BASE_ADDR (AIPS1_BASE_ADDR + 0x000B0000) #define UART5_BASE_ADDR (AIPS1_BASE_ADDR + 0x000B4000) -#define ECT_IP1_BASE_ADDR (AIPS1_BASE_ADDR + 0x000B8000) -#define ECT_IP2_BASE_ADDR (AIPS1_BASE_ADDR + 0x000BC000) - -/* - * SPBA global module enabled #0 - */ -#define SPBA0_BASE_ADDR 0x50000000 -#define SPBA0_BASE_ADDR_VIRT 0xFC100000 -#define SPBA0_SIZE SZ_1M #define MMC_SDHC1_BASE_ADDR (SPBA0_BASE_ADDR + 0x00004000) #define MMC_SDHC2_BASE_ADDR (SPBA0_BASE_ADDR + 0x00008000) -#define UART3_BASE_ADDR (SPBA0_BASE_ADDR + 0x0000C000) -#define CSPI2_BASE_ADDR (SPBA0_BASE_ADDR + 0x00010000) -#define SSI2_BASE_ADDR (SPBA0_BASE_ADDR + 0x00014000) #define SIM1_BASE_ADDR (SPBA0_BASE_ADDR + 0x00018000) #define IIM_BASE_ADDR (SPBA0_BASE_ADDR + 0x0001C000) -#define ATA_DMA_BASE_ADDR (SPBA0_BASE_ADDR + 0x00020000) -#define MSHC1_BASE_ADDR (SPBA0_BASE_ADDR + 0x00024000) -#define MSHC2_BASE_ADDR (SPBA0_BASE_ADDR + 0x00024000) -#define SPBA_CTRL_BASE_ADDR (SPBA0_BASE_ADDR + 0x0003C000) -/* - * AIPS 2 - */ -#define AIPS2_BASE_ADDR 0x53F00000 -#define AIPS2_BASE_ADDR_VIRT 0xFC200000 -#define AIPS2_SIZE SZ_1M -#define CCM_BASE_ADDR (AIPS2_BASE_ADDR + 0x00080000) #define CSPI3_BASE_ADDR (AIPS2_BASE_ADDR + 0x00084000) #define FIRI_BASE_ADDR (AIPS2_BASE_ADDR + 0x0008C000) -#define GPT1_BASE_ADDR (AIPS2_BASE_ADDR + 0x00090000) -#define EPIT1_BASE_ADDR (AIPS2_BASE_ADDR + 0x00094000) -#define EPIT2_BASE_ADDR (AIPS2_BASE_ADDR + 0x00098000) -#define GPIO3_BASE_ADDR (AIPS2_BASE_ADDR + 0x000A4000) -#define SCC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000AC000) #define SCM_BASE_ADDR (AIPS2_BASE_ADDR + 0x000AE000) #define SMN_BASE_ADDR (AIPS2_BASE_ADDR + 0x000AF000) -#define RNGA_BASE_ADDR (AIPS2_BASE_ADDR + 0x000B0000) -#define IPU_CTRL_BASE_ADDR (AIPS2_BASE_ADDR + 0x000C0000) -#define AUDMUX_BASE_ADDR (AIPS2_BASE_ADDR + 0x000C4000) #define MPEG4_ENC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000C8000) -#define GPIO1_BASE_ADDR (AIPS2_BASE_ADDR + 0x000CC000) -#define GPIO2_BASE_ADDR (AIPS2_BASE_ADDR + 0x000D0000) -#define SDMA_BASE_ADDR (AIPS2_BASE_ADDR + 0x000D4000) -#define RTC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000D8000) -#define WDOG_BASE_ADDR (AIPS2_BASE_ADDR + 0x000DC000) -#define PWM_BASE_ADDR (AIPS2_BASE_ADDR + 0x000E0000) -#define RTIC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000EC000) - -/* - * ROMP and AVIC - */ -#define ROMP_BASE_ADDR 0x60000000 -#define ROMP_BASE_ADDR_VIRT 0xFC500000 -#define ROMP_SIZE SZ_1M - -#define AVIC_BASE_ADDR 0x68000000 -#define AVIC_BASE_ADDR_VIRT 0xFC400000 -#define AVIC_SIZE SZ_1M - -/* - * NAND, SDRAM, WEIM, M3IF, EMI controllers - */ -#define X_MEMC_BASE_ADDR 0xB8000000 -#define X_MEMC_BASE_ADDR_VIRT 0xFC320000 -#define X_MEMC_SIZE SZ_64K -#define NFC_BASE_ADDR (X_MEMC_BASE_ADDR + 0x0000) -#define ESDCTL_BASE_ADDR (X_MEMC_BASE_ADDR + 0x1000) -#define WEIM_BASE_ADDR (X_MEMC_BASE_ADDR + 0x2000) -#define M3IF_BASE_ADDR (X_MEMC_BASE_ADDR + 0x3000) -#define EMI_CTL_BASE_ADDR (X_MEMC_BASE_ADDR + 0x4000) -#define PCMCIA_CTL_BASE_ADDR EMI_CTL_BASE_ADDR +#define MX31_NFC_BASE_ADDR (X_MEMC_BASE_ADDR + 0x0000) -/* - * Memory regions and CS - */ -#define IPU_MEM_BASE_ADDR 0x70000000 -#define CSD0_BASE_ADDR 0x80000000 -#define CSD1_BASE_ADDR 0x90000000 -#define CS0_BASE_ADDR 0xA0000000 -#define CS1_BASE_ADDR 0xA8000000 -#define CS2_BASE_ADDR 0xB0000000 -#define CS3_BASE_ADDR 0xB2000000 - -#define CS4_BASE_ADDR 0xB4000000 -#define CS4_BASE_ADDR_VIRT 0xF4000000 -#define CS4_SIZE SZ_32M - -#define CS5_BASE_ADDR 0xB6000000 -#define PCMCIA_MEM_BASE_ADDR 0xBC000000 - -/*! - * This macro defines the physical to virtual address mapping for all the - * peripheral modules. It is used by passing in the physical address as x - * and returning the virtual address. If the physical address is not mapped, - * it returns 0xDEADBEEF - */ -#define IO_ADDRESS(x) \ - (void __iomem *) \ - (((x >= IRAM_BASE_ADDR) && (x < (IRAM_BASE_ADDR + IRAM_SIZE))) ? IRAM_IO_ADDRESS(x):\ - ((x >= L2CC_BASE_ADDR) && (x < (L2CC_BASE_ADDR + L2CC_SIZE))) ? L2CC_IO_ADDRESS(x):\ - ((x >= AIPS1_BASE_ADDR) && (x < (AIPS1_BASE_ADDR + AIPS1_SIZE))) ? AIPS1_IO_ADDRESS(x):\ - ((x >= SPBA0_BASE_ADDR) && (x < (SPBA0_BASE_ADDR + SPBA0_SIZE))) ? SPBA0_IO_ADDRESS(x):\ - ((x >= AIPS2_BASE_ADDR) && (x < (AIPS2_BASE_ADDR + AIPS2_SIZE))) ? AIPS2_IO_ADDRESS(x):\ - ((x >= ROMP_BASE_ADDR) && (x < (ROMP_BASE_ADDR + ROMP_SIZE))) ? ROMP_IO_ADDRESS(x):\ - ((x >= AVIC_BASE_ADDR) && (x < (AVIC_BASE_ADDR + AVIC_SIZE))) ? AVIC_IO_ADDRESS(x):\ - ((x >= CS4_BASE_ADDR) && (x < (CS4_BASE_ADDR + CS4_SIZE))) ? CS4_IO_ADDRESS(x):\ - ((x >= X_MEMC_BASE_ADDR) && (x < (X_MEMC_BASE_ADDR + X_MEMC_SIZE))) ? X_MEMC_IO_ADDRESS(x):\ - 0xDEADBEEF) - -/* - * define the address mapping macros: in physical address order - */ - -#define IRAM_IO_ADDRESS(x) \ - (((x) - IRAM_BASE_ADDR) + IRAM_BASE_ADDR_VIRT) - -#define L2CC_IO_ADDRESS(x) \ - (((x) - L2CC_BASE_ADDR) + L2CC_BASE_ADDR_VIRT) - -#define AIPS1_IO_ADDRESS(x) \ - (((x) - AIPS1_BASE_ADDR) + AIPS1_BASE_ADDR_VIRT) - -#define SPBA0_IO_ADDRESS(x) \ - (((x) - SPBA0_BASE_ADDR) + SPBA0_BASE_ADDR_VIRT) - -#define AIPS2_IO_ADDRESS(x) \ - (((x) - AIPS2_BASE_ADDR) + AIPS2_BASE_ADDR_VIRT) - -#define ROMP_IO_ADDRESS(x) \ - (((x) - ROMP_BASE_ADDR) + ROMP_BASE_ADDR_VIRT) - -#define AVIC_IO_ADDRESS(x) \ - (((x) - AVIC_BASE_ADDR) + AVIC_BASE_ADDR_VIRT) - -#define CS4_IO_ADDRESS(x) \ - (((x) - CS4_BASE_ADDR) + CS4_BASE_ADDR_VIRT) - -#define X_MEMC_IO_ADDRESS(x) \ - (((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT) - -#define PCMCIA_IO_ADDRESS(x) \ - (((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT) - -/* - * Interrupt numbers - */ -#define MXC_INT_PEN_ADS7843 0 -#define MXC_INT_RESV1 1 -#define MXC_INT_CS8900A 2 -#define MXC_INT_I2C3 3 -#define MXC_INT_I2C2 4 #define MXC_INT_MPEG4_ENCODER 5 -#define MXC_INT_RTIC 6 #define MXC_INT_FIRI 7 -#define MXC_INT_MMC_SDHC2 8 +#define MX31_INT_MMC_SDHC2 8 #define MXC_INT_MMC_SDHC1 9 -#define MXC_INT_I2C 10 -#define MXC_INT_SSI2 11 -#define MXC_INT_SSI1 12 -#define MXC_INT_CSPI2 13 -#define MXC_INT_CSPI1 14 -#define MXC_INT_ATA 15 +#define MX31_INT_SSI2 11 +#define MX31_INT_SSI1 12 #define MXC_INT_MBX 16 #define MXC_INT_CSPI3 17 -#define MXC_INT_UART3 18 -#define MXC_INT_IIM 19 #define MXC_INT_SIM2 20 #define MXC_INT_SIM1 21 -#define MXC_INT_RNGA 22 -#define MXC_INT_EVTMON 23 -#define MXC_INT_KPP 24 -#define MXC_INT_RTC 25 -#define MXC_INT_PWM 26 -#define MXC_INT_EPIT2 27 -#define MXC_INT_EPIT1 28 -#define MXC_INT_GPT 29 -#define MXC_INT_RESV30 30 -#define MXC_INT_RESV31 31 -#define MXC_INT_UART2 32 -#define MXC_INT_NANDFC 33 -#define MXC_INT_SDMA 34 +#define MXC_INT_CCM_DVFS 31 #define MXC_INT_USB1 35 #define MXC_INT_USB2 36 #define MXC_INT_USB3 37 #define MXC_INT_USB4 38 -#define MXC_INT_MSHC1 39 #define MXC_INT_MSHC2 40 -#define MXC_INT_IPU_ERR 41 -#define MXC_INT_IPU_SYN 42 -#define MXC_INT_RESV43 43 -#define MXC_INT_RESV44 44 -#define MXC_INT_UART1 45 #define MXC_INT_UART4 46 #define MXC_INT_UART5 47 -#define MXC_INT_ECT 48 -#define MXC_INT_SCC_SCM 49 -#define MXC_INT_SCC_SMN 50 -#define MXC_INT_GPIO2 51 -#define MXC_INT_GPIO1 52 #define MXC_INT_CCM 53 #define MXC_INT_PCMCIA 54 -#define MXC_INT_WDOG 55 -#define MXC_INT_GPIO3 56 -#define MXC_INT_RESV57 57 -#define MXC_INT_EXT_POWER 58 -#define MXC_INT_EXT_TEMPER 59 -#define MXC_INT_EXT_SENSOR60 60 -#define MXC_INT_EXT_SENSOR61 61 -#define MXC_INT_EXT_WDOG 62 -#define MXC_INT_EXT_TV 63 - -#define PROD_SIGNATURE 0x1 /* For MX31 */ - -/* silicon revisions specific to i.MX31 */ -#define CHIP_REV_1_0 0x10 -#define CHIP_REV_1_1 0x11 -#define CHIP_REV_1_2 0x12 -#define CHIP_REV_1_3 0x13 -#define CHIP_REV_2_0 0x20 -#define CHIP_REV_2_1 0x21 -#define CHIP_REV_2_2 0x22 -#define CHIP_REV_2_3 0x23 -#define CHIP_REV_3_0 0x30 -#define CHIP_REV_3_1 0x31 -#define CHIP_REV_3_2 0x32 - -#define SYSTEM_REV_MIN CHIP_REV_1_0 -#define SYSTEM_REV_NUM 3 - -/* gpio and gpio based interrupt handling */ -#define GPIO_DR 0x00 -#define GPIO_GDIR 0x04 -#define GPIO_PSR 0x08 -#define GPIO_ICR1 0x0C -#define GPIO_ICR2 0x10 -#define GPIO_IMR 0x14 -#define GPIO_ISR 0x18 -#define GPIO_INT_LOW_LEV 0x0 -#define GPIO_INT_HIGH_LEV 0x1 -#define GPIO_INT_RISE_EDGE 0x2 -#define GPIO_INT_FALL_EDGE 0x3 -#define GPIO_INT_NONE 0x4 - -/* Mandatory defines used globally */ - -/* this CPU supports up to 96 GPIOs */ -#define ARCH_NR_GPIOS 96 - -#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS) - -/* this is a i.MX31 CPU */ -#define cpu_is_mx31() (1) - -extern unsigned int system_rev; - -static inline int mx31_revision(void) -{ - return system_rev; -} -#endif -#endif /* __ASM_ARCH_MXC_MX31_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/mx35.h b/arch/arm/plat-mxc/include/mach/mx35.h new file mode 100644 index 00000000000..6465fefb42e --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/mx35.h @@ -0,0 +1,29 @@ +/* + * IRAM + */ +#define MX35_IRAM_BASE_ADDR 0x10000000 /* internal ram */ +#define MX35_IRAM_SIZE SZ_128K + +#define MXC_FEC_BASE_ADDR 0x50038000 +#define MX35_NFC_BASE_ADDR 0xBB000000 + +/* + * Interrupt numbers + */ +#define MXC_INT_OWIRE 2 +#define MX35_INT_MMC_SDHC1 7 +#define MXC_INT_MMC_SDHC2 8 +#define MXC_INT_MMC_SDHC3 9 +#define MX35_INT_SSI1 11 +#define MX35_INT_SSI2 12 +#define MXC_INT_GPU2D 16 +#define MXC_INT_ASRC 17 +#define MXC_INT_USBHS 35 +#define MXC_INT_USBOTG 37 +#define MXC_INT_ESAI 40 +#define MXC_INT_CAN1 43 +#define MXC_INT_CAN2 44 +#define MXC_INT_MLB 46 +#define MXC_INT_SPDIF 47 +#define MXC_INT_FEC 57 + diff --git a/arch/arm/plat-mxc/include/mach/mx3x.h b/arch/arm/plat-mxc/include/mach/mx3x.h new file mode 100644 index 00000000000..83a172b51b0 --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/mx3x.h @@ -0,0 +1,290 @@ +/* + * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_ARCH_MXC_MX31_H__ +#define __ASM_ARCH_MXC_MX31_H__ + +#ifndef __ASM_ARCH_MXC_HARDWARE_H__ +#error "Do not include directly." +#endif + +/* + * MX31 memory map: + * + * Virt Phys Size What + * --------------------------------------------------------------------------- + * FC000000 43F00000 1M AIPS 1 + * FC100000 50000000 1M SPBA + * FC200000 53F00000 1M AIPS 2 + * FC500000 60000000 128M ROMPATCH + * FC400000 68000000 128M AVIC + * 70000000 256M IPU (MAX M2) + * 80000000 256M CSD0 SDRAM/DDR + * 90000000 256M CSD1 SDRAM/DDR + * A0000000 128M CS0 Flash + * A8000000 128M CS1 Flash + * B0000000 32M CS2 + * B2000000 32M CS3 + * F4000000 B4000000 32M CS4 + * B6000000 32M CS5 + * FC320000 B8000000 64K NAND, SDRAM, WEIM, M3IF, EMI controllers + * C0000000 64M PCMCIA/CF + */ + +#define CS0_BASE_ADDR 0xA0000000 +#define CS1_BASE_ADDR 0xA8000000 +#define CS2_BASE_ADDR 0xB0000000 +#define CS3_BASE_ADDR 0xB2000000 + +#define CS4_BASE_ADDR 0xB4000000 +#define CS4_BASE_ADDR_VIRT 0xF4000000 +#define CS4_SIZE SZ_32M + +#define CS5_BASE_ADDR 0xB6000000 +#define PCMCIA_MEM_BASE_ADDR 0xBC000000 + +/* + * L2CC + */ +#define L2CC_BASE_ADDR 0x30000000 +#define L2CC_SIZE SZ_1M + +/* + * AIPS 1 + */ +#define AIPS1_BASE_ADDR 0x43F00000 +#define AIPS1_BASE_ADDR_VIRT 0xFC000000 +#define AIPS1_SIZE SZ_1M + +#define MAX_BASE_ADDR (AIPS1_BASE_ADDR + 0x00004000) +#define EVTMON_BASE_ADDR (AIPS1_BASE_ADDR + 0x00008000) +#define CLKCTL_BASE_ADDR (AIPS1_BASE_ADDR + 0x0000C000) +#define ETB_SLOT4_BASE_ADDR (AIPS1_BASE_ADDR + 0x00010000) +#define ETB_SLOT5_BASE_ADDR (AIPS1_BASE_ADDR + 0x00014000) +#define ECT_CTIO_BASE_ADDR (AIPS1_BASE_ADDR + 0x00018000) +#define I2C_BASE_ADDR (AIPS1_BASE_ADDR + 0x00080000) +#define I2C3_BASE_ADDR (AIPS1_BASE_ADDR + 0x00084000) +#define UART1_BASE_ADDR (AIPS1_BASE_ADDR + 0x00090000) +#define UART2_BASE_ADDR (AIPS1_BASE_ADDR + 0x00094000) +#define I2C2_BASE_ADDR (AIPS1_BASE_ADDR + 0x00098000) +#define OWIRE_BASE_ADDR (AIPS1_BASE_ADDR + 0x0009C000) +#define SSI1_BASE_ADDR (AIPS1_BASE_ADDR + 0x000A0000) +#define CSPI1_BASE_ADDR (AIPS1_BASE_ADDR + 0x000A4000) +#define KPP_BASE_ADDR (AIPS1_BASE_ADDR + 0x000A8000) +#define IOMUXC_BASE_ADDR (AIPS1_BASE_ADDR + 0x000AC000) +#define ECT_IP1_BASE_ADDR (AIPS1_BASE_ADDR + 0x000B8000) +#define ECT_IP2_BASE_ADDR (AIPS1_BASE_ADDR + 0x000BC000) + +/* + * SPBA global module enabled #0 + */ +#define SPBA0_BASE_ADDR 0x50000000 +#define SPBA0_BASE_ADDR_VIRT 0xFC100000 +#define SPBA0_SIZE SZ_1M + +#define UART3_BASE_ADDR (SPBA0_BASE_ADDR + 0x0000C000) +#define CSPI2_BASE_ADDR (SPBA0_BASE_ADDR + 0x00010000) +#define SSI2_BASE_ADDR (SPBA0_BASE_ADDR + 0x00014000) +#define ATA_DMA_BASE_ADDR (SPBA0_BASE_ADDR + 0x00020000) +#define MSHC1_BASE_ADDR (SPBA0_BASE_ADDR + 0x00024000) +#define SPBA_CTRL_BASE_ADDR (SPBA0_BASE_ADDR + 0x0003C000) + +/* + * AIPS 2 + */ +#define AIPS2_BASE_ADDR 0x53F00000 +#define AIPS2_BASE_ADDR_VIRT 0xFC200000 +#define AIPS2_SIZE SZ_1M +#define CCM_BASE_ADDR (AIPS2_BASE_ADDR + 0x00080000) +#define GPT1_BASE_ADDR (AIPS2_BASE_ADDR + 0x00090000) +#define EPIT1_BASE_ADDR (AIPS2_BASE_ADDR + 0x00094000) +#define EPIT2_BASE_ADDR (AIPS2_BASE_ADDR + 0x00098000) +#define GPIO3_BASE_ADDR (AIPS2_BASE_ADDR + 0x000A4000) +#define SCC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000AC000) +#define RNGA_BASE_ADDR (AIPS2_BASE_ADDR + 0x000B0000) +#define IPU_CTRL_BASE_ADDR (AIPS2_BASE_ADDR + 0x000C0000) +#define AUDMUX_BASE_ADDR (AIPS2_BASE_ADDR + 0x000C4000) +#define GPIO1_BASE_ADDR (AIPS2_BASE_ADDR + 0x000CC000) +#define GPIO2_BASE_ADDR (AIPS2_BASE_ADDR + 0x000D0000) +#define SDMA_BASE_ADDR (AIPS2_BASE_ADDR + 0x000D4000) +#define RTC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000D8000) +#define WDOG_BASE_ADDR (AIPS2_BASE_ADDR + 0x000DC000) +#define PWM_BASE_ADDR (AIPS2_BASE_ADDR + 0x000E0000) +#define RTIC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000EC000) + +/* + * ROMP and AVIC + */ +#define ROMP_BASE_ADDR 0x60000000 +#define ROMP_BASE_ADDR_VIRT 0xFC500000 +#define ROMP_SIZE SZ_1M + +#define AVIC_BASE_ADDR 0x68000000 +#define AVIC_BASE_ADDR_VIRT 0xFC400000 +#define AVIC_SIZE SZ_1M + +/* + * NAND, SDRAM, WEIM, M3IF, EMI controllers + */ +#define X_MEMC_BASE_ADDR 0xB8000000 +#define X_MEMC_BASE_ADDR_VIRT 0xFC320000 +#define X_MEMC_SIZE SZ_64K + +#define ESDCTL_BASE_ADDR (X_MEMC_BASE_ADDR + 0x1000) +#define WEIM_BASE_ADDR (X_MEMC_BASE_ADDR + 0x2000) +#define M3IF_BASE_ADDR (X_MEMC_BASE_ADDR + 0x3000) +#define EMI_CTL_BASE_ADDR (X_MEMC_BASE_ADDR + 0x4000) +#define PCMCIA_CTL_BASE_ADDR EMI_CTL_BASE_ADDR + +/* + * Memory regions and CS + */ +#define IPU_MEM_BASE_ADDR 0x70000000 +#define CSD0_BASE_ADDR 0x80000000 +#define CSD1_BASE_ADDR 0x90000000 + +/*! + * This macro defines the physical to virtual address mapping for all the + * peripheral modules. It is used by passing in the physical address as x + * and returning the virtual address. If the physical address is not mapped, + * it returns 0xDEADBEEF + */ +#define IO_ADDRESS(x) \ + (void __iomem *) \ + (((x >= AIPS1_BASE_ADDR) && (x < (AIPS1_BASE_ADDR + AIPS1_SIZE))) ? AIPS1_IO_ADDRESS(x):\ + ((x >= SPBA0_BASE_ADDR) && (x < (SPBA0_BASE_ADDR + SPBA0_SIZE))) ? SPBA0_IO_ADDRESS(x):\ + ((x >= AIPS2_BASE_ADDR) && (x < (AIPS2_BASE_ADDR + AIPS2_SIZE))) ? AIPS2_IO_ADDRESS(x):\ + ((x >= ROMP_BASE_ADDR) && (x < (ROMP_BASE_ADDR + ROMP_SIZE))) ? ROMP_IO_ADDRESS(x):\ + ((x >= AVIC_BASE_ADDR) && (x < (AVIC_BASE_ADDR + AVIC_SIZE))) ? AVIC_IO_ADDRESS(x):\ + ((x >= CS4_BASE_ADDR) && (x < (CS4_BASE_ADDR + CS4_SIZE))) ? CS4_IO_ADDRESS(x):\ + ((x >= X_MEMC_BASE_ADDR) && (x < (X_MEMC_BASE_ADDR + X_MEMC_SIZE))) ? X_MEMC_IO_ADDRESS(x):\ + 0xDEADBEEF) + +/* + * define the address mapping macros: in physical address order + */ +#define L2CC_IO_ADDRESS(x) \ + (((x) - L2CC_BASE_ADDR) + L2CC_BASE_ADDR_VIRT) + +#define AIPS1_IO_ADDRESS(x) \ + (((x) - AIPS1_BASE_ADDR) + AIPS1_BASE_ADDR_VIRT) + +#define SPBA0_IO_ADDRESS(x) \ + (((x) - SPBA0_BASE_ADDR) + SPBA0_BASE_ADDR_VIRT) + +#define AIPS2_IO_ADDRESS(x) \ + (((x) - AIPS2_BASE_ADDR) + AIPS2_BASE_ADDR_VIRT) + +#define ROMP_IO_ADDRESS(x) \ + (((x) - ROMP_BASE_ADDR) + ROMP_BASE_ADDR_VIRT) + +#define AVIC_IO_ADDRESS(x) \ + (((x) - AVIC_BASE_ADDR) + AVIC_BASE_ADDR_VIRT) + +#define CS4_IO_ADDRESS(x) \ + (((x) - CS4_BASE_ADDR) + CS4_BASE_ADDR_VIRT) + +#define X_MEMC_IO_ADDRESS(x) \ + (((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT) + +#define PCMCIA_IO_ADDRESS(x) \ + (((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT) + +/* + * Interrupt numbers + */ +#define MXC_INT_I2C3 3 +#define MXC_INT_I2C2 4 +#define MXC_INT_RTIC 6 +#define MXC_INT_I2C 10 +#define MXC_INT_CSPI2 13 +#define MXC_INT_CSPI1 14 +#define MXC_INT_ATA 15 +#define MXC_INT_UART3 18 +#define MXC_INT_IIM 19 +#define MXC_INT_RNGA 22 +#define MXC_INT_EVTMON 23 +#define MXC_INT_KPP 24 +#define MXC_INT_RTC 25 +#define MXC_INT_PWM 26 +#define MXC_INT_EPIT2 27 +#define MXC_INT_EPIT1 28 +#define MXC_INT_GPT 29 +#define MXC_INT_POWER_FAIL 30 +#define MXC_INT_UART2 32 +#define MXC_INT_NANDFC 33 +#define MXC_INT_SDMA 34 +#define MXC_INT_MSHC1 39 +#define MXC_INT_IPU_ERR 41 +#define MXC_INT_IPU_SYN 42 +#define MXC_INT_UART1 45 +#define MXC_INT_ECT 48 +#define MXC_INT_SCC_SCM 49 +#define MXC_INT_SCC_SMN 50 +#define MXC_INT_GPIO2 51 +#define MXC_INT_GPIO1 52 +#define MXC_INT_WDOG 55 +#define MXC_INT_GPIO3 56 +#define MXC_INT_EXT_POWER 58 +#define MXC_INT_EXT_TEMPER 59 +#define MXC_INT_EXT_SENSOR60 60 +#define MXC_INT_EXT_SENSOR61 61 +#define MXC_INT_EXT_WDOG 62 +#define MXC_INT_EXT_TV 63 + +#define PROD_SIGNATURE 0x1 /* For MX31 */ + +/* silicon revisions specific to i.MX31 */ +#define CHIP_REV_1_0 0x10 +#define CHIP_REV_1_1 0x11 +#define CHIP_REV_1_2 0x12 +#define CHIP_REV_1_3 0x13 +#define CHIP_REV_2_0 0x20 +#define CHIP_REV_2_1 0x21 +#define CHIP_REV_2_2 0x22 +#define CHIP_REV_2_3 0x23 +#define CHIP_REV_3_0 0x30 +#define CHIP_REV_3_1 0x31 +#define CHIP_REV_3_2 0x32 + +#define SYSTEM_REV_MIN CHIP_REV_1_0 +#define SYSTEM_REV_NUM 3 + +/* gpio and gpio based interrupt handling */ +#define GPIO_DR 0x00 +#define GPIO_GDIR 0x04 +#define GPIO_PSR 0x08 +#define GPIO_ICR1 0x0C +#define GPIO_ICR2 0x10 +#define GPIO_IMR 0x14 +#define GPIO_ISR 0x18 +#define GPIO_INT_LOW_LEV 0x0 +#define GPIO_INT_HIGH_LEV 0x1 +#define GPIO_INT_RISE_EDGE 0x2 +#define GPIO_INT_FALL_EDGE 0x3 +#define GPIO_INT_NONE 0x4 + +/* Mandatory defines used globally */ + +/* this CPU supports up to 96 GPIOs */ +#define ARCH_NR_GPIOS 96 + +#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS) + +extern unsigned int system_rev; + +static inline int mx31_revision(void) +{ + return system_rev; +} +#endif + +#endif /* __ASM_ARCH_MXC_MX31_H__ */ + -- GitLab From 198016e1b12d781ef00aaafbf571775a8e723f54 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 6 Feb 2009 15:38:22 +0100 Subject: [PATCH 3290/4982] [ARM] MXC: add cpu_is_ macros We had hardcoded cpu_is_ macros for mxc architectures till now. As we want to run the same kernel on i.MX31 and i.MX35 this patch adds cpu_is_ macros which expand to 0 or 1 if only one architecture is compiled in and only check for the cpu type if more than one architecture is compiled in. Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/clock.c | 2 + arch/arm/plat-mxc/Makefile | 2 +- arch/arm/plat-mxc/cpu.c | 11 ++++ arch/arm/plat-mxc/include/mach/common.h | 1 + arch/arm/plat-mxc/include/mach/mx21.h | 3 - arch/arm/plat-mxc/include/mach/mx27.h | 3 - arch/arm/plat-mxc/include/mach/mxc.h | 74 ++++++++++++++++++++++--- 7 files changed, 80 insertions(+), 16 deletions(-) create mode 100644 arch/arm/plat-mxc/cpu.c diff --git a/arch/arm/mach-mx3/clock.c b/arch/arm/mach-mx3/clock.c index bc3a3beb9a6..9ab5f8b2bc3 100644 --- a/arch/arm/mach-mx3/clock.c +++ b/arch/arm/mach-mx3/clock.c @@ -1077,6 +1077,8 @@ int __init mx31_clocks_init(unsigned long fref) u32 reg; struct clk **clkp; + mxc_set_cpu_type(MXC_CPU_MX31); + ckih_rate = fref; for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++) diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile index f204192f9b9..564fd4ebf38 100644 --- a/arch/arm/plat-mxc/Makefile +++ b/arch/arm/plat-mxc/Makefile @@ -3,7 +3,7 @@ # # Common support -obj-y := irq.o clock.o gpio.o time.o devices.o +obj-y := irq.o clock.o gpio.o time.o devices.o cpu.o obj-$(CONFIG_ARCH_MX1) += iomux-mx1-mx2.o dma-mx1-mx2.o obj-$(CONFIG_ARCH_MX2) += iomux-mx1-mx2.o dma-mx1-mx2.o diff --git a/arch/arm/plat-mxc/cpu.c b/arch/arm/plat-mxc/cpu.c new file mode 100644 index 00000000000..386e0d52cf5 --- /dev/null +++ b/arch/arm/plat-mxc/cpu.c @@ -0,0 +1,11 @@ + +#include + +unsigned int __mxc_cpu_type; +EXPORT_SYMBOL(__mxc_cpu_type); + +void mxc_set_cpu_type(unsigned int type) +{ + __mxc_cpu_type = type; +} + diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h index 3051eee9953..f467159cbdc 100644 --- a/arch/arm/plat-mxc/include/mach/common.h +++ b/arch/arm/plat-mxc/include/mach/common.h @@ -23,5 +23,6 @@ extern int mx27_clocks_init(unsigned long fref); extern int mx31_clocks_init(unsigned long fref); extern int mxc_register_gpios(void); extern int mxc_register_device(struct platform_device *pdev, void *data); +extern void mxc_set_cpu_type(unsigned int type); #endif diff --git a/arch/arm/plat-mxc/include/mach/mx21.h b/arch/arm/plat-mxc/include/mach/mx21.h index cfdbe051caf..e8c4cf56c24 100644 --- a/arch/arm/plat-mxc/include/mach/mx21.h +++ b/arch/arm/plat-mxc/include/mach/mx21.h @@ -54,9 +54,6 @@ #define IRAM_BASE_ADDR 0xFFFFE800 /* internal ram */ -/* this is an i.MX21 CPU */ -#define cpu_is_mx21() (1) - /* this CPU supports up to 192 GPIOs (don't forget the baseboard!) */ #define ARCH_NR_GPIOS (6*32 + 16) diff --git a/arch/arm/plat-mxc/include/mach/mx27.h b/arch/arm/plat-mxc/include/mach/mx27.h index 5f6a8a7bb19..6e93f2c0b7b 100644 --- a/arch/arm/plat-mxc/include/mach/mx27.h +++ b/arch/arm/plat-mxc/include/mach/mx27.h @@ -120,9 +120,6 @@ extern int mx27_revision(void); /* Mandatory defines used globally */ -/* this is an i.MX27 CPU */ -#define cpu_is_mx27() (1) - /* this CPU supports up to 192 GPIOs (don't forget the baseboard!) */ #define ARCH_NR_GPIOS (192 + 16) diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h index d6b0c472cd9..5fa2a07f4ea 100644 --- a/arch/arm/plat-mxc/include/mach/mxc.h +++ b/arch/arm/plat-mxc/include/mach/mxc.h @@ -24,21 +24,74 @@ #error "Do not include directly." #endif -/* clean up all things that are not used */ -#ifndef CONFIG_ARCH_MX3 -# define cpu_is_mx31() (0) +#define MXC_CPU_MX1 1 +#define MXC_CPU_MX21 21 +#define MXC_CPU_MX27 27 +#define MXC_CPU_MX31 31 +#define MXC_CPU_MX35 35 + +#ifndef __ASSEMBLY__ +extern unsigned int __mxc_cpu_type; +#endif + +#ifdef CONFIG_ARCH_MX1 +# ifdef mxc_cpu_type +# undef mxc_cpu_type +# define mxc_cpu_type __mxc_cpu_type +# else +# define mxc_cpu_type MXC_CPU_MX1 +# endif +# define cpu_is_mx1() (mxc_cpu_type == MXC_CPU_MX1) +#else +# define cpu_is_mx1() (0) #endif -#ifndef CONFIG_MACH_MX21 -# define cpu_is_mx21() (0) +#ifdef CONFIG_MACH_MX21 +# ifdef mxc_cpu_type +# undef mxc_cpu_type +# define mxc_cpu_type __mxc_cpu_type +# else +# define mxc_cpu_type MXC_CPU_MX21 +# endif +# define cpu_is_mx21() (mxc_cpu_type == MXC_CPU_MX21) +#else +# define cpu_is_mx21() (0) #endif -#ifndef CONFIG_MACH_MX27 -# define cpu_is_mx27() (0) +#ifdef CONFIG_MACH_MX27 +# ifdef mxc_cpu_type +# undef mxc_cpu_type +# define mxc_cpu_type __mxc_cpu_type +# else +# define mxc_cpu_type MXC_CPU_MX27 +# endif +# define cpu_is_mx27() (mxc_cpu_type == MXC_CPU_MX27) +#else +# define cpu_is_mx27() (0) #endif -#ifndef CONFIG_MACH_MX21 -# define cpu_is_mx21() (0) +#ifdef CONFIG_ARCH_MX31 +# ifdef mxc_cpu_type +# undef mxc_cpu_type +# define mxc_cpu_type __mxc_cpu_type +# else +# define mxc_cpu_type MXC_CPU_MX31 +# endif +# define cpu_is_mx31() (mxc_cpu_type == MXC_CPU_MX31) +#else +# define cpu_is_mx31() (0) +#endif + +#ifdef CONFIG_ARCH_MX35 +# ifdef mxc_cpu_type +# undef mxc_cpu_type +# define mxc_cpu_type __mxc_cpu_type +# else +# define mxc_cpu_type MXC_CPU_MX35 +# endif +# define cpu_is_mx35() (mxc_cpu_type == MXC_CPU_MX35) +#else +# define cpu_is_mx35() (0) #endif #if defined(CONFIG_ARCH_MX3) || defined(CONFIG_ARCH_MX2) @@ -47,4 +100,7 @@ #define CSCR_A(n) (IO_ADDRESS(WEIM_BASE_ADDR) + n * 0x10 + 0x8) #endif +#define cpu_is_mx3() (cpu_is_mx31() || cpu_is_mx35()) +#define cpu_is_mx2() (cpu_is_mx21() || cpu_is_mx27()) + #endif /* __ASM_ARCH_MXC_H__ */ -- GitLab From cb8ebb0223a5a2ec6f2e0b46ef5812113847df61 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 6 Feb 2009 15:41:45 +0100 Subject: [PATCH 3291/4982] [ARM] add i.MX35 build support Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/Kconfig | 13 ++++++++++++- arch/arm/mach-mx3/Makefile | 3 ++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig index 6933d2d0b56..7c939c69d6d 100644 --- a/arch/arm/mach-mx3/Kconfig +++ b/arch/arm/mach-mx3/Kconfig @@ -1,9 +1,16 @@ if ARCH_MX3 +config ARCH_MX31 + bool + +config ARCH_MX35 + bool + comment "MX3 platforms:" config MACH_MX31ADS bool "Support MX31ADS platforms" + select ARCH_MX31 default y help Include support for MX31ADS platform. This includes specific @@ -19,13 +26,15 @@ config MACH_MX31ADS_WM1133_EV1 and audio module for the MX31ADS platform. config MACH_PCM037 - bool "Support Phytec pcm037 platforms" + bool "Support Phytec pcm037 (i.MX31) platforms" + select ARCH_MX31 help Include support for Phytec pcm037 platform. This includes specific configurations for the board and its peripherals. config MACH_MX31LITE bool "Support MX31 LITEKIT (LogicPD)" + select ARCH_MX31 default n help Include support for MX31 LITEKIT platform. This includes specific @@ -33,6 +42,7 @@ config MACH_MX31LITE config MACH_MX31_3DS bool "Support MX31PDK (3DS)" + select ARCH_MX31 default n help Include support for MX31PDK (3DS) platform. This includes specific @@ -40,6 +50,7 @@ config MACH_MX31_3DS config MACH_MX31MOBOARD bool "Support mx31moboard platforms (EPFL Mobots group)" + select ARCH_MX31 default n help Include support for mx31moboard platform. This includes specific diff --git a/arch/arm/mach-mx3/Makefile b/arch/arm/mach-mx3/Makefile index d50d9878a65..68c4837cce6 100644 --- a/arch/arm/mach-mx3/Makefile +++ b/arch/arm/mach-mx3/Makefile @@ -4,7 +4,8 @@ # Object file lists. -obj-y := mm.o clock.o devices.o iomux.o +obj-y := mm.o devices.o +obj-$(CONFIG_ARCH_MX31) += clock.o iomux.o obj-$(CONFIG_MACH_MX31ADS) += mx31ads.o obj-$(CONFIG_MACH_MX31LITE) += mx31lite.o obj-$(CONFIG_MACH_PCM037) += pcm037.o -- GitLab From 2cb536d13cf9fbce029055b7603b3ca4ca1cf407 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 6 Feb 2009 17:48:59 +0100 Subject: [PATCH 3292/4982] [ARM] MX35: add clock support This patch adds clock support for i.MX35 SoCs. We do not support setting of clock rates yet, but most interesting clock rates should be reported. I couldn't test all clock rates and the datasheet contains some obvious bugs, so expect some bugs in this code. Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/Makefile | 1 + arch/arm/mach-mx3/clock-imx35.c | 487 ++++++++++++++++++++++++ arch/arm/plat-mxc/include/mach/common.h | 1 + 3 files changed, 489 insertions(+) create mode 100644 arch/arm/mach-mx3/clock-imx35.c diff --git a/arch/arm/mach-mx3/Makefile b/arch/arm/mach-mx3/Makefile index 68c4837cce6..ab0bec0a4d9 100644 --- a/arch/arm/mach-mx3/Makefile +++ b/arch/arm/mach-mx3/Makefile @@ -6,6 +6,7 @@ obj-y := mm.o devices.o obj-$(CONFIG_ARCH_MX31) += clock.o iomux.o +obj-$(CONFIG_ARCH_MX35) += clock-imx35.o obj-$(CONFIG_MACH_MX31ADS) += mx31ads.o obj-$(CONFIG_MACH_MX31LITE) += mx31lite.o obj-$(CONFIG_MACH_PCM037) += pcm037.o diff --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c new file mode 100644 index 00000000000..53a112d4e04 --- /dev/null +++ b/arch/arm/mach-mx3/clock-imx35.c @@ -0,0 +1,487 @@ +/* + * Copyright (C) 2009 by Sascha Hauer, Pengutronix + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#define CCM_BASE IO_ADDRESS(CCM_BASE_ADDR) + +#define CCM_CCMR 0x00 +#define CCM_PDR0 0x04 +#define CCM_PDR1 0x08 +#define CCM_PDR2 0x0C +#define CCM_PDR3 0x10 +#define CCM_PDR4 0x14 +#define CCM_RCSR 0x18 +#define CCM_MPCTL 0x1C +#define CCM_PPCTL 0x20 +#define CCM_ACMR 0x24 +#define CCM_COSR 0x28 +#define CCM_CGR0 0x2C +#define CCM_CGR1 0x30 +#define CCM_CGR2 0x34 +#define CCM_CGR3 0x38 + +#ifdef HAVE_SET_RATE_SUPPORT +static void calc_dividers(u32 div, u32 *pre, u32 *post, u32 maxpost) +{ + u32 min_pre, temp_pre, old_err, err; + + min_pre = (div - 1) / maxpost + 1; + old_err = 8; + + for (temp_pre = 8; temp_pre >= min_pre; temp_pre--) { + if (div > (temp_pre * maxpost)) + break; + + if (div < (temp_pre * temp_pre)) + continue; + + err = div % temp_pre; + + if (err == 0) { + *pre = temp_pre; + break; + } + + err = temp_pre - err; + + if (err < old_err) { + old_err = err; + *pre = temp_pre; + } + } + + *post = (div + *pre - 1) / *pre; +} + +/* get the best values for a 3-bit divider combined with a 6-bit divider */ +static void calc_dividers_3_6(u32 div, u32 *pre, u32 *post) +{ + if (div >= 512) { + *pre = 8; + *post = 64; + } else if (div >= 64) { + calc_dividers(div, pre, post, 64); + } else if (div <= 8) { + *pre = div; + *post = 1; + } else { + *pre = 1; + *post = div; + } +} + +/* get the best values for two cascaded 3-bit dividers */ +static void calc_dividers_3_3(u32 div, u32 *pre, u32 *post) +{ + if (div >= 64) { + *pre = *post = 8; + } else if (div > 8) { + calc_dividers(div, pre, post, 8); + } else { + *pre = 1; + *post = div; + } +} +#endif + +static unsigned long get_rate_mpll(void) +{ + ulong mpctl = __raw_readl(CCM_BASE + CCM_MPCTL); + + return mxc_decode_pll(mpctl, 24000000); +} + +static unsigned long get_rate_ppll(void) +{ + ulong ppctl = __raw_readl(CCM_BASE + CCM_PPCTL); + + return mxc_decode_pll(ppctl, 24000000); +} + +struct arm_ahb_div { + unsigned char arm, ahb, sel; +}; + +static struct arm_ahb_div clk_consumer[] = { + { .arm = 1, .ahb = 4, .sel = 0}, + { .arm = 1, .ahb = 3, .sel = 1}, + { .arm = 2, .ahb = 2, .sel = 0}, + { .arm = 0, .ahb = 0, .sel = 0}, + { .arm = 0, .ahb = 0, .sel = 0}, + { .arm = 0, .ahb = 0, .sel = 0}, + { .arm = 4, .ahb = 1, .sel = 0}, + { .arm = 1, .ahb = 5, .sel = 0}, + { .arm = 1, .ahb = 8, .sel = 0}, + { .arm = 1, .ahb = 6, .sel = 1}, + { .arm = 2, .ahb = 4, .sel = 0}, + { .arm = 0, .ahb = 0, .sel = 0}, + { .arm = 0, .ahb = 0, .sel = 0}, + { .arm = 0, .ahb = 0, .sel = 0}, + { .arm = 4, .ahb = 2, .sel = 0}, + { .arm = 0, .ahb = 0, .sel = 0}, +}; + +static struct arm_ahb_div clk_automotive[] = { + { .arm = 1, .ahb = 3, .sel = 0}, + { .arm = 1, .ahb = 2, .sel = 1}, + { .arm = 2, .ahb = 1, .sel = 1}, + { .arm = 0, .ahb = 0, .sel = 0}, + { .arm = 1, .ahb = 6, .sel = 0}, + { .arm = 1, .ahb = 4, .sel = 1}, + { .arm = 2, .ahb = 2, .sel = 1}, + { .arm = 0, .ahb = 0, .sel = 0}, +}; + +static unsigned long get_rate_arm(void) +{ + unsigned long pdr0 = __raw_readl(CCM_BASE + CCM_PDR0); + struct arm_ahb_div *aad; + unsigned long fref = get_rate_mpll(); + + if (pdr0 & 1) { + /* consumer path */ + aad = &clk_consumer[(pdr0 >> 16) & 0xf]; + if (aad->sel) + fref = fref * 2 / 3; + } else { + /* auto path */ + aad = &clk_automotive[(pdr0 >> 9) & 0x7]; + if (aad->sel) + fref = fref * 3 / 4; + } + return fref / aad->arm; +} + +static unsigned long get_rate_ahb(struct clk *clk) +{ + unsigned long pdr0 = __raw_readl(CCM_BASE + CCM_PDR0); + struct arm_ahb_div *aad; + unsigned long fref = get_rate_mpll(); + + if (pdr0 & 1) + /* consumer path */ + aad = &clk_consumer[(pdr0 >> 16) & 0xf]; + else + /* auto path */ + aad = &clk_automotive[(pdr0 >> 9) & 0x7]; + + return fref / aad->ahb; +} + +static unsigned long get_rate_ipg(struct clk *clk) +{ + return get_rate_ahb(NULL) >> 1; +} + +static unsigned long get_3_3_div(unsigned long in) +{ + return (((in >> 3) & 0x7) + 1) * ((in & 0x7) + 1); +} + +static unsigned long get_rate_uart(struct clk *clk) +{ + unsigned long pdr3 = __raw_readl(CCM_BASE + CCM_PDR3); + unsigned long pdr4 = __raw_readl(CCM_BASE + CCM_PDR4); + unsigned long div = get_3_3_div(pdr4 >> 10); + + if (pdr3 & (1 << 14)) + return get_rate_arm() / div; + else + return get_rate_ppll() / div; +} + +static unsigned long get_rate_sdhc(struct clk *clk) +{ + unsigned long pdr3 = __raw_readl(CCM_BASE + CCM_PDR3); + unsigned long div, rate; + + if (pdr3 & (1 << 6)) + rate = get_rate_arm(); + else + rate = get_rate_ppll(); + + switch (clk->id) { + default: + case 0: + div = pdr3 & 0x3f; + break; + case 1: + div = (pdr3 >> 8) & 0x3f; + break; + case 2: + div = (pdr3 >> 16) & 0x3f; + break; + } + + return rate / get_3_3_div(div); +} + +static unsigned long get_rate_mshc(struct clk *clk) +{ + unsigned long pdr1 = __raw_readl(CCM_BASE + CCM_PDR1); + unsigned long div1, div2, rate; + + if (pdr1 & (1 << 7)) + rate = get_rate_arm(); + else + rate = get_rate_ppll(); + + div1 = (pdr1 >> 29) & 0x7; + div2 = (pdr1 >> 22) & 0x3f; + + return rate / ((div1 + 1) * (div2 + 1)); +} + +static unsigned long get_rate_ssi(struct clk *clk) +{ + unsigned long pdr2 = __raw_readl(CCM_BASE + CCM_PDR2); + unsigned long div1, div2, rate; + + if (pdr2 & (1 << 6)) + rate = get_rate_arm(); + else + rate = get_rate_ppll(); + + switch (clk->id) { + default: + case 0: + div1 = pdr2 & 0x3f; + div2 = (pdr2 >> 24) & 0x7; + break; + case 1: + div1 = (pdr2 >> 8) & 0x3f; + div2 = (pdr2 >> 27) & 0x7; + break; + } + + return rate / ((div1 + 1) * (div2 + 1)); +} + +static unsigned long get_rate_csi(struct clk *clk) +{ + unsigned long pdr2 = __raw_readl(CCM_BASE + CCM_PDR2); + unsigned long rate; + + if (pdr2 & (1 << 7)) + rate = get_rate_arm(); + else + rate = get_rate_ppll(); + + return rate / get_3_3_div((pdr2 >> 16) & 0x3f); +} + +static unsigned long get_rate_ipg_per(struct clk *clk) +{ + unsigned long pdr0 = __raw_readl(CCM_BASE + CCM_PDR0); + unsigned long pdr4 = __raw_readl(CCM_BASE + CCM_PDR4); + unsigned long div1, div2; + + if (pdr0 & (1 << 26)) { + div1 = (pdr4 >> 19) & 0x7; + div2 = (pdr4 >> 16) & 0x7; + return get_rate_arm() / ((div1 + 1) * (div2 + 1)); + } else { + div1 = (pdr0 >> 12) & 0x7; + return get_rate_ahb(NULL) / div1; + } +} + +static int clk_cgr_enable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(clk->enable_reg); + reg |= 3 << clk->enable_shift; + __raw_writel(reg, clk->enable_reg); + + return 0; +} + +static void clk_cgr_disable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(clk->enable_reg); + reg &= ~(3 << clk->enable_shift); + __raw_writel(reg, clk->enable_reg); +} + +#define DEFINE_CLOCK(name, i, er, es, gr, sr) \ + static struct clk name = { \ + .id = i, \ + .enable_reg = CCM_BASE + er, \ + .enable_shift = es, \ + .get_rate = gr, \ + .set_rate = sr, \ + .enable = clk_cgr_enable, \ + .disable = clk_cgr_disable, \ + } + +DEFINE_CLOCK(asrc_clk, 0, CCM_CGR0, 0, NULL, NULL); +DEFINE_CLOCK(ata_clk, 0, CCM_CGR0, 2, get_rate_ipg, NULL); +DEFINE_CLOCK(audmux_clk, 0, CCM_CGR0, 4, NULL, NULL); +DEFINE_CLOCK(can1_clk, 0, CCM_CGR0, 6, get_rate_ipg, NULL); +DEFINE_CLOCK(can2_clk, 1, CCM_CGR0, 8, get_rate_ipg, NULL); +DEFINE_CLOCK(cspi1_clk, 0, CCM_CGR0, 10, get_rate_ipg, NULL); +DEFINE_CLOCK(cspi2_clk, 1, CCM_CGR0, 12, get_rate_ipg, NULL); +DEFINE_CLOCK(ect_clk, 0, CCM_CGR0, 14, get_rate_ipg, NULL); +DEFINE_CLOCK(edio_clk, 0, CCM_CGR0, 16, NULL, NULL); +DEFINE_CLOCK(emi_clk, 0, CCM_CGR0, 18, get_rate_ipg, NULL); +DEFINE_CLOCK(epit1_clk, 0, CCM_CGR0, 20, get_rate_ipg_per, NULL); +DEFINE_CLOCK(epit2_clk, 1, CCM_CGR0, 22, get_rate_ipg_per, NULL); +DEFINE_CLOCK(esai_clk, 0, CCM_CGR0, 24, NULL, NULL); +DEFINE_CLOCK(esdhc1_clk, 0, CCM_CGR0, 26, get_rate_sdhc, NULL); +DEFINE_CLOCK(esdhc2_clk, 1, CCM_CGR0, 28, get_rate_sdhc, NULL); +DEFINE_CLOCK(esdhc3_clk, 2, CCM_CGR0, 30, get_rate_sdhc, NULL); + +DEFINE_CLOCK(fec_clk, 0, CCM_CGR1, 0, get_rate_ipg, NULL); +DEFINE_CLOCK(gpio1_clk, 0, CCM_CGR1, 2, NULL, NULL); +DEFINE_CLOCK(gpio2_clk, 1, CCM_CGR1, 4, NULL, NULL); +DEFINE_CLOCK(gpio3_clk, 2, CCM_CGR1, 6, NULL, NULL); +DEFINE_CLOCK(gpt_clk, 0, CCM_CGR1, 8, get_rate_ipg, NULL); +DEFINE_CLOCK(i2c1_clk, 0, CCM_CGR1, 10, get_rate_ipg_per, NULL); +DEFINE_CLOCK(i2c2_clk, 1, CCM_CGR1, 12, get_rate_ipg_per, NULL); +DEFINE_CLOCK(i2c3_clk, 2, CCM_CGR1, 14, get_rate_ipg_per, NULL); +DEFINE_CLOCK(iomuxc_clk, 0, CCM_CGR1, 16, NULL, NULL); +DEFINE_CLOCK(ipu_clk, 0, CCM_CGR1, 18, NULL, NULL); +DEFINE_CLOCK(kpp_clk, 0, CCM_CGR1, 20, get_rate_ipg, NULL); +DEFINE_CLOCK(mlb_clk, 0, CCM_CGR1, 22, get_rate_ahb, NULL); +DEFINE_CLOCK(mshc_clk, 0, CCM_CGR1, 24, get_rate_mshc, NULL); +DEFINE_CLOCK(owire_clk, 0, CCM_CGR1, 26, get_rate_ipg_per, NULL); +DEFINE_CLOCK(pwm_clk, 0, CCM_CGR1, 28, get_rate_ipg_per, NULL); +DEFINE_CLOCK(rngc_clk, 0, CCM_CGR1, 30, get_rate_ipg, NULL); + +DEFINE_CLOCK(rtc_clk, 0, CCM_CGR2, 0, get_rate_ipg, NULL); +DEFINE_CLOCK(rtic_clk, 0, CCM_CGR2, 2, get_rate_ahb, NULL); +DEFINE_CLOCK(scc_clk, 0, CCM_CGR2, 4, get_rate_ipg, NULL); +DEFINE_CLOCK(sdma_clk, 0, CCM_CGR2, 6, NULL, NULL); +DEFINE_CLOCK(spba_clk, 0, CCM_CGR2, 8, get_rate_ipg, NULL); +DEFINE_CLOCK(spdif_clk, 0, CCM_CGR2, 10, NULL, NULL); +DEFINE_CLOCK(ssi1_clk, 0, CCM_CGR2, 12, get_rate_ssi, NULL); +DEFINE_CLOCK(ssi2_clk, 1, CCM_CGR2, 14, get_rate_ssi, NULL); +DEFINE_CLOCK(uart1_clk, 0, CCM_CGR2, 16, get_rate_uart, NULL); +DEFINE_CLOCK(uart2_clk, 1, CCM_CGR2, 18, get_rate_uart, NULL); +DEFINE_CLOCK(uart3_clk, 2, CCM_CGR2, 20, get_rate_uart, NULL); +DEFINE_CLOCK(usbotg_clk, 0, CCM_CGR2, 22, NULL, NULL); +DEFINE_CLOCK(wdog_clk, 0, CCM_CGR2, 24, NULL, NULL); +DEFINE_CLOCK(max_clk, 0, CCM_CGR2, 26, NULL, NULL); +DEFINE_CLOCK(admux_clk, 0, CCM_CGR2, 30, NULL, NULL); + +DEFINE_CLOCK(csi_clk, 0, CCM_CGR3, 0, get_rate_csi, NULL); +DEFINE_CLOCK(iim_clk, 0, CCM_CGR3, 2, NULL, NULL); +DEFINE_CLOCK(gpu2d_clk, 0, CCM_CGR3, 4, NULL, NULL); + +#define _REGISTER_CLOCK(d, n, c) \ + { \ + .dev_id = d, \ + .con_id = n, \ + .clk = &c, \ + }, + +static struct clk_lookup lookups[] __initdata = { + _REGISTER_CLOCK(NULL, "asrc", asrc_clk) + _REGISTER_CLOCK(NULL, "ata", ata_clk) + _REGISTER_CLOCK(NULL, "audmux", audmux_clk) + _REGISTER_CLOCK(NULL, "can", can1_clk) + _REGISTER_CLOCK(NULL, "can", can2_clk) + _REGISTER_CLOCK("spi_imx.0", NULL, cspi1_clk) + _REGISTER_CLOCK("spi_imx.1", NULL, cspi2_clk) + _REGISTER_CLOCK(NULL, "ect", ect_clk) + _REGISTER_CLOCK(NULL, "edio", edio_clk) + _REGISTER_CLOCK(NULL, "emi", emi_clk) + _REGISTER_CLOCK(NULL, "epit", epit1_clk) + _REGISTER_CLOCK(NULL, "epit", epit2_clk) + _REGISTER_CLOCK(NULL, "esai", esai_clk) + _REGISTER_CLOCK(NULL, "sdhc", esdhc1_clk) + _REGISTER_CLOCK(NULL, "sdhc", esdhc2_clk) + _REGISTER_CLOCK(NULL, "sdhc", esdhc3_clk) + _REGISTER_CLOCK("fec.0", NULL, fec_clk) + _REGISTER_CLOCK(NULL, "gpio", gpio1_clk) + _REGISTER_CLOCK(NULL, "gpio", gpio2_clk) + _REGISTER_CLOCK(NULL, "gpio", gpio3_clk) + _REGISTER_CLOCK("gpt.0", NULL, gpt_clk) + _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk) + _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk) + _REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_clk) + _REGISTER_CLOCK(NULL, "iomuxc", iomuxc_clk) + _REGISTER_CLOCK(NULL, "ipu", ipu_clk) + _REGISTER_CLOCK(NULL, "kpp", kpp_clk) + _REGISTER_CLOCK(NULL, "mlb", mlb_clk) + _REGISTER_CLOCK(NULL, "mshc", mshc_clk) + _REGISTER_CLOCK("mxc_w1", NULL, owire_clk) + _REGISTER_CLOCK(NULL, "pwm", pwm_clk) + _REGISTER_CLOCK(NULL, "rngc", rngc_clk) + _REGISTER_CLOCK(NULL, "rtc", rtc_clk) + _REGISTER_CLOCK(NULL, "rtic", rtic_clk) + _REGISTER_CLOCK(NULL, "scc", scc_clk) + _REGISTER_CLOCK(NULL, "sdma", sdma_clk) + _REGISTER_CLOCK(NULL, "spba", spba_clk) + _REGISTER_CLOCK(NULL, "spdif", spdif_clk) + _REGISTER_CLOCK(NULL, "ssi", ssi1_clk) + _REGISTER_CLOCK(NULL, "ssi", ssi2_clk) + _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk) + _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk) + _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk) + _REGISTER_CLOCK(NULL, "usbotg", usbotg_clk) + _REGISTER_CLOCK("mxc_wdt.0", NULL, wdog_clk) + _REGISTER_CLOCK(NULL, "max", max_clk) + _REGISTER_CLOCK(NULL, "admux", admux_clk) + _REGISTER_CLOCK(NULL, "csi", csi_clk) + _REGISTER_CLOCK(NULL, "iim", iim_clk) + _REGISTER_CLOCK(NULL, "gpu2d", gpu2d_clk) +}; + +int __init mx35_clocks_init() +{ + int i; + unsigned int ll = 0; + + mxc_set_cpu_type(MXC_CPU_MX35); + +#ifdef CONFIG_DEBUG_LL_CONSOLE + ll = (3 << 16); +#endif + + for (i = 0; i < ARRAY_SIZE(lookups); i++) + clkdev_add(&lookups[i]); + + /* Turn off all clocks except the ones we need to survive, namely: + * EMI, GPIO1/2/3, GPT, IOMUX, MAX and eventually uart + */ + __raw_writel((3 << 18), CCM_BASE + CCM_CGR0); + __raw_writel((3 << 2) | (3 << 4) | (3 << 6) | (3 << 8) | (3 << 16), + CCM_BASE + CCM_CGR1); + __raw_writel((3 << 26) | ll, CCM_BASE + CCM_CGR2); + __raw_writel(0, CCM_BASE + CCM_CGR3); + + mxc_timer_init(&gpt_clk); + + return 0; +} + diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h index f467159cbdc..b2f9b72644d 100644 --- a/arch/arm/plat-mxc/include/mach/common.h +++ b/arch/arm/plat-mxc/include/mach/common.h @@ -21,6 +21,7 @@ extern int mx1_clocks_init(unsigned long fref); extern int mx21_clocks_init(unsigned long lref, unsigned long fref); extern int mx27_clocks_init(unsigned long fref); extern int mx31_clocks_init(unsigned long fref); +extern int mx35_clocks_init(void); extern int mxc_register_gpios(void); extern int mxc_register_device(struct platform_device *pdev, void *data); extern void mxc_set_cpu_type(unsigned int type); -- GitLab From 9536ff33619e13fcc4bd16354faea97dba244f73 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 6 Feb 2009 15:38:51 +0100 Subject: [PATCH 3293/4982] [ARM] MX35 devices support The i.MX35 basically features the same peripherals as the i.MX31 with some differences: - The i.MX35 has a FEC ethernet controller - The NAND controller base addresses are different - The i.MX35 has only 3 UARTs Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/devices.c | 43 +++++++++++++++++++++++++++++++++++-- arch/arm/mach-mx3/devices.h | 1 + 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-mx3/devices.c b/arch/arm/mach-mx3/devices.c index b7d4900b02e..ab090602cea 100644 --- a/arch/arm/mach-mx3/devices.c +++ b/arch/arm/mach-mx3/devices.c @@ -84,6 +84,7 @@ struct platform_device mxc_uart_device2 = { .num_resources = ARRAY_SIZE(uart2), }; +#ifdef CONFIG_ARCH_MX31 static struct resource uart3[] = { { .start = UART4_BASE_ADDR, @@ -121,6 +122,7 @@ struct platform_device mxc_uart_device4 = { .resource = uart4, .num_resources = ARRAY_SIZE(uart4), }; +#endif /* CONFIG_ARCH_MX31 */ /* GPIO port description */ static struct mxc_gpio_port imx_gpio_ports[] = { @@ -166,8 +168,8 @@ struct platform_device mxc_w1_master_device = { static struct resource mxc_nand_resources[] = { { - .start = NFC_BASE_ADDR, - .end = NFC_BASE_ADDR + 0xfff, + .start = 0, /* runtime dependent */ + .end = 0, .flags = IORESOURCE_MEM }, { .start = MXC_INT_NANDFC, @@ -290,3 +292,40 @@ struct platform_device mx3_fb = { .coherent_dma_mask = 0xffffffff, }, }; + +#ifdef CONFIG_ARCH_MX35 +static struct resource mxc_fec_resources[] = { + { + .start = MXC_FEC_BASE_ADDR, + .end = MXC_FEC_BASE_ADDR + 0xfff, + .flags = IORESOURCE_MEM + }, { + .start = MXC_INT_FEC, + .end = MXC_INT_FEC, + .flags = IORESOURCE_IRQ + }, +}; + +struct platform_device mxc_fec_device = { + .name = "fec", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_fec_resources), + .resource = mxc_fec_resources, +}; +#endif + +static int mx3_devices_init(void) +{ + if (cpu_is_mx31()) { + mxc_nand_resources[0].start = MX31_NFC_BASE_ADDR; + mxc_nand_resources[0].end = MX31_NFC_BASE_ADDR + 0xfff; + } + if (cpu_is_mx35()) { + mxc_nand_resources[0].start = MX35_NFC_BASE_ADDR; + mxc_nand_resources[0].end = MX35_NFC_BASE_ADDR + 0xfff; + } + + return 0; +} + +subsys_initcall(mx3_devices_init); diff --git a/arch/arm/mach-mx3/devices.h b/arch/arm/mach-mx3/devices.h index d1638518a9d..4faac6552e0 100644 --- a/arch/arm/mach-mx3/devices.h +++ b/arch/arm/mach-mx3/devices.h @@ -11,3 +11,4 @@ extern struct platform_device mxc_i2c_device1; extern struct platform_device mxc_i2c_device2; extern struct platform_device mx3_ipu; extern struct platform_device mx3_fb; +extern struct platform_device mxc_fec_device; -- GitLab From cb88214d726b337d49c1f65cbc5e5ac85837b11b Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sun, 8 Feb 2009 02:00:50 +0100 Subject: [PATCH 3294/4982] [ARM] MX31/MX35: Add l2x0 cache support Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/mm.c | 27 ++++++++++++++++++++++++++- arch/arm/mm/Kconfig | 3 ++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-mx3/mm.c b/arch/arm/mach-mx3/mm.c index 0589b5cd33c..44fcb6679f9 100644 --- a/arch/arm/mach-mx3/mm.c +++ b/arch/arm/mach-mx3/mm.c @@ -22,10 +22,14 @@ #include #include -#include +#include + #include #include +#include + #include +#include /*! * @file mm.c @@ -62,3 +66,24 @@ void __init mxc_map_io(void) { iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc)); } + +#ifdef CONFIG_CACHE_L2X0 +static int mxc_init_l2x0(void) +{ + void __iomem *l2x0_base; + + l2x0_base = ioremap(L2CC_BASE_ADDR, 4096); + if (IS_ERR(l2x0_base)) { + printk(KERN_ERR "remapping L2 cache area failed with %ld\n", + PTR_ERR(l2x0_base)); + return 0; + } + + l2x0_init(l2x0_base, 0x00030024, 0x00000000); + + return 0; +} + +arch_initcall(mxc_init_l2x0); +#endif + diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index d490f3773c0..0d8581f1121 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -704,7 +704,8 @@ config CACHE_FEROCEON_L2_WRITETHROUGH config CACHE_L2X0 bool "Enable the L2x0 outer cache controller" - depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || REALVIEW_EB_A9MP + depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \ + REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 default y select OUTER_CACHE help -- GitLab From fb4416ad61e4dac816ae866999115500c818406b Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 6 Feb 2009 18:15:06 +0100 Subject: [PATCH 3295/4982] [ARM] MX31: Move static virtual mappings of AIPS1/2 to common file On MX31 we can't do much without mapping the AIPS1/2 register space. Move these mappings from individual boards to plat-mxc/mm.c Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/mm.c | 10 ++++++++++ arch/arm/mach-mx3/mx31ads.c | 10 ---------- arch/arm/mach-mx3/mx31lite.c | 10 ---------- arch/arm/mach-mx3/mx31moboard.c | 28 +--------------------------- arch/arm/mach-mx3/mx31pdk.c | 28 +--------------------------- arch/arm/mach-mx3/pcm037.c | 28 +--------------------------- 6 files changed, 13 insertions(+), 101 deletions(-) diff --git a/arch/arm/mach-mx3/mm.c b/arch/arm/mach-mx3/mm.c index 44fcb6679f9..9e1459cb4b7 100644 --- a/arch/arm/mach-mx3/mm.c +++ b/arch/arm/mach-mx3/mm.c @@ -54,6 +54,16 @@ static struct map_desc mxc_io_desc[] __initdata = { .pfn = __phys_to_pfn(AVIC_BASE_ADDR), .length = AVIC_SIZE, .type = MT_DEVICE_NONSHARED + }, { + .virtual = AIPS1_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(AIPS1_BASE_ADDR), + .length = AIPS1_SIZE, + .type = MT_DEVICE_NONSHARED + }, { + .virtual = AIPS2_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(AIPS2_BASE_ADDR), + .length = AIPS2_SIZE, + .type = MT_DEVICE_NONSHARED }, }; diff --git a/arch/arm/mach-mx3/mx31ads.c b/arch/arm/mach-mx3/mx31ads.c index 5c76ac5ba0f..83e5e8e1276 100644 --- a/arch/arm/mach-mx3/mx31ads.c +++ b/arch/arm/mach-mx3/mx31ads.c @@ -492,20 +492,10 @@ static void mxc_init_i2c(void) */ static struct map_desc mx31ads_io_desc[] __initdata = { { - .virtual = AIPS1_BASE_ADDR_VIRT, - .pfn = __phys_to_pfn(AIPS1_BASE_ADDR), - .length = AIPS1_SIZE, - .type = MT_DEVICE_NONSHARED - }, { .virtual = SPBA0_BASE_ADDR_VIRT, .pfn = __phys_to_pfn(SPBA0_BASE_ADDR), .length = SPBA0_SIZE, .type = MT_DEVICE_NONSHARED - }, { - .virtual = AIPS2_BASE_ADDR_VIRT, - .pfn = __phys_to_pfn(AIPS2_BASE_ADDR), - .length = AIPS2_SIZE, - .type = MT_DEVICE_NONSHARED }, { .virtual = CS4_BASE_ADDR_VIRT, .pfn = __phys_to_pfn(CS4_BASE_ADDR), diff --git a/arch/arm/mach-mx3/mx31lite.c b/arch/arm/mach-mx3/mx31lite.c index e61fad2f60f..894d98cd994 100644 --- a/arch/arm/mach-mx3/mx31lite.c +++ b/arch/arm/mach-mx3/mx31lite.c @@ -42,20 +42,10 @@ */ static struct map_desc mx31lite_io_desc[] __initdata = { { - .virtual = AIPS1_BASE_ADDR_VIRT, - .pfn = __phys_to_pfn(AIPS1_BASE_ADDR), - .length = AIPS1_SIZE, - .type = MT_DEVICE_NONSHARED - }, { .virtual = SPBA0_BASE_ADDR_VIRT, .pfn = __phys_to_pfn(SPBA0_BASE_ADDR), .length = SPBA0_SIZE, .type = MT_DEVICE_NONSHARED - }, { - .virtual = AIPS2_BASE_ADDR_VIRT, - .pfn = __phys_to_pfn(AIPS2_BASE_ADDR), - .length = AIPS2_SIZE, - .type = MT_DEVICE_NONSHARED }, { .virtual = CS4_BASE_ADDR_VIRT, .pfn = __phys_to_pfn(CS4_BASE_ADDR), diff --git a/arch/arm/mach-mx3/mx31moboard.c b/arch/arm/mach-mx3/mx31moboard.c index b30460a2a55..34c2a1b99d4 100644 --- a/arch/arm/mach-mx3/mx31moboard.c +++ b/arch/arm/mach-mx3/mx31moboard.c @@ -103,32 +103,6 @@ static void __init mxc_board_init(void) } } -/* - * This structure defines static mappings for the mx31moboard. - */ -static struct map_desc mx31moboard_io_desc[] __initdata = { - { - .virtual = AIPS1_BASE_ADDR_VIRT, - .pfn = __phys_to_pfn(AIPS1_BASE_ADDR), - .length = AIPS1_SIZE, - .type = MT_DEVICE_NONSHARED - }, { - .virtual = AIPS2_BASE_ADDR_VIRT, - .pfn = __phys_to_pfn(AIPS2_BASE_ADDR), - .length = AIPS2_SIZE, - .type = MT_DEVICE_NONSHARED - }, -}; - -/* - * Set up static virtual mappings. - */ -void __init mx31moboard_map_io(void) -{ - mxc_map_io(); - iotable_init(mx31moboard_io_desc, ARRAY_SIZE(mx31moboard_io_desc)); -} - static void __init mx31moboard_timer_init(void) { mx31_clocks_init(26000000); @@ -143,7 +117,7 @@ MACHINE_START(MX31MOBOARD, "EPFL Mobots mx31moboard") .phys_io = AIPS1_BASE_ADDR, .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x100, - .map_io = mx31moboard_map_io, + .map_io = mxc_map_io, .init_irq = mxc_init_irq, .init_machine = mxc_board_init, .timer = &mx31moboard_timer, diff --git a/arch/arm/mach-mx3/mx31pdk.c b/arch/arm/mach-mx3/mx31pdk.c index 9108f157b76..bc63f178569 100644 --- a/arch/arm/mach-mx3/mx31pdk.c +++ b/arch/arm/mach-mx3/mx31pdk.c @@ -58,32 +58,6 @@ static inline void mxc_init_imx_uart(void) mxc_register_device(&mxc_uart_device0, &uart_pdata); } -/*! - * This structure defines static mappings for the i.MX31PDK board. - */ -static struct map_desc mx31pdk_io_desc[] __initdata = { - { - .virtual = AIPS1_BASE_ADDR_VIRT, - .pfn = __phys_to_pfn(AIPS1_BASE_ADDR), - .length = AIPS1_SIZE, - .type = MT_DEVICE_NONSHARED - }, { - .virtual = AIPS2_BASE_ADDR_VIRT, - .pfn = __phys_to_pfn(AIPS2_BASE_ADDR), - .length = AIPS2_SIZE, - .type = MT_DEVICE_NONSHARED - }, -}; - -/*! - * Set up static virtual mappings. - */ -static void __init mx31pdk_map_io(void) -{ - mxc_map_io(); - iotable_init(mx31pdk_io_desc, ARRAY_SIZE(mx31pdk_io_desc)); -} - /*! * Board specific initialization. */ @@ -110,7 +84,7 @@ MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)") .phys_io = AIPS1_BASE_ADDR, .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x100, - .map_io = mx31pdk_map_io, + .map_io = mxc_map_io, .init_irq = mxc_init_irq, .init_machine = mxc_board_init, .timer = &mx31pdk_timer, diff --git a/arch/arm/mach-mx3/pcm037.c b/arch/arm/mach-mx3/pcm037.c index a05e37b731b..7743c13beba 100644 --- a/arch/arm/mach-mx3/pcm037.c +++ b/arch/arm/mach-mx3/pcm037.c @@ -210,32 +210,6 @@ static void __init mxc_board_init(void) mxc_register_device(&mxc_nand_device, &pcm037_nand_board_info); } -/* - * This structure defines static mappings for the pcm037 board. - */ -static struct map_desc pcm037_io_desc[] __initdata = { - { - .virtual = AIPS1_BASE_ADDR_VIRT, - .pfn = __phys_to_pfn(AIPS1_BASE_ADDR), - .length = AIPS1_SIZE, - .type = MT_DEVICE_NONSHARED - }, { - .virtual = AIPS2_BASE_ADDR_VIRT, - .pfn = __phys_to_pfn(AIPS2_BASE_ADDR), - .length = AIPS2_SIZE, - .type = MT_DEVICE_NONSHARED - }, -}; - -/* - * Set up static virtual mappings. - */ -void __init pcm037_map_io(void) -{ - mxc_map_io(); - iotable_init(pcm037_io_desc, ARRAY_SIZE(pcm037_io_desc)); -} - static void __init pcm037_timer_init(void) { mx31_clocks_init(26000000); @@ -250,7 +224,7 @@ MACHINE_START(PCM037, "Phytec Phycore pcm037") .phys_io = AIPS1_BASE_ADDR, .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x100, - .map_io = pcm037_map_io, + .map_io = mxc_map_io, .init_irq = mxc_init_irq, .init_machine = mxc_board_init, .timer = &pcm037_timer, -- GitLab From 9a51157bab06ab54d6ee442e34fe9574ff14c8c3 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 9 Feb 2009 11:00:03 +0100 Subject: [PATCH 3296/4982] [ARM] pcm038: Fix pins for UART3 The UART3 had a copy-paste bug. instead of claiming rxd, txd, rts and cts pins, cts and rts were claimed twice Signed-off-by: Sascha Hauer --- arch/arm/mach-mx2/pcm038.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-mx2/pcm038.c b/arch/arm/mach-mx2/pcm038.c index 7d935e17aa1..aa4eaa61d1b 100644 --- a/arch/arm/mach-mx2/pcm038.c +++ b/arch/arm/mach-mx2/pcm038.c @@ -128,10 +128,10 @@ static int uart_mxc_port1_exit(struct platform_device *pdev) return 0; } -static int mxc_uart2_pins[] = { PE10_PF_UART3_CTS, +static int mxc_uart2_pins[] = { PE8_PF_UART3_TXD, PE9_PF_UART3_RXD, PE10_PF_UART3_CTS, - PE9_PF_UART3_RXD }; + PE11_PF_UART3_RTS }; static int uart_mxc_port2_init(struct platform_device *pdev) { -- GitLab From 9eb2eb8c40ffd30da322648c4415bae0288eb167 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 18 Feb 2009 11:55:33 +0100 Subject: [PATCH 3297/4982] MX31 clkdev support This patch adds clkdev support for i.MX31. This is done in a similar way done previously for i.MX27 Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/clock.c | 932 ++++++++--------------------------- arch/arm/mach-mx3/crm_regs.h | 153 ------ arch/arm/plat-mxc/Kconfig | 1 + drivers/dma/ipu/ipu_idmac.c | 2 +- drivers/video/mx3fb.c | 2 +- 5 files changed, 206 insertions(+), 884 deletions(-) diff --git a/arch/arm/mach-mx3/clock.c b/arch/arm/mach-mx3/clock.c index 9ab5f8b2bc3..ca46f4801c3 100644 --- a/arch/arm/mach-mx3/clock.c +++ b/arch/arm/mach-mx3/clock.c @@ -23,10 +23,13 @@ #include #include #include + +#include +#include + #include #include #include -#include #include "crm_regs.h" @@ -65,17 +68,17 @@ static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post) } static struct clk mcu_pll_clk; -static struct clk mcu_main_clk; -static struct clk usb_pll_clk; static struct clk serial_pll_clk; static struct clk ipg_clk; static struct clk ckih_clk; -static struct clk ahb_clk; -static int _clk_enable(struct clk *clk) +static int cgr_enable(struct clk *clk) { u32 reg; + if (!clk->enable_reg) + return 0; + reg = __raw_readl(clk->enable_reg); reg |= 3 << clk->enable_shift; __raw_writel(reg, clk->enable_reg); @@ -83,111 +86,69 @@ static int _clk_enable(struct clk *clk) return 0; } -static void _clk_disable(struct clk *clk) +static void cgr_disable(struct clk *clk) { u32 reg; + if (!clk->enable_reg) + return; + reg = __raw_readl(clk->enable_reg); reg &= ~(3 << clk->enable_shift); + + /* special case for EMI clock */ + if (clk->enable_reg == MXC_CCM_CGR2 && clk->enable_shift == 8) + reg |= (1 << clk->enable_shift); + __raw_writel(reg, clk->enable_reg); } -static void _clk_emi_disable(struct clk *clk) +static unsigned long pll_ref_get_rate(void) { - u32 reg; + unsigned long ccmr; + unsigned int prcs; - reg = __raw_readl(clk->enable_reg); - reg &= ~(3 << clk->enable_shift); - reg |= (1 << clk->enable_shift); - __raw_writel(reg, clk->enable_reg); + ccmr = __raw_readl(MXC_CCM_CCMR); + prcs = (ccmr & MXC_CCM_CCMR_PRCS_MASK) >> MXC_CCM_CCMR_PRCS_OFFSET; + if (prcs == 0x1) + return CKIL_CLK_FREQ * 1024; + else + return clk_get_rate(&ckih_clk); } -static int _clk_pll_set_rate(struct clk *clk, unsigned long rate) +static unsigned long usb_pll_get_rate(struct clk *clk) { - u32 reg; - signed long pd = 1; /* Pre-divider */ - signed long mfi; /* Multiplication Factor (Integer part) */ - signed long mfn; /* Multiplication Factor (Integer part) */ - signed long mfd; /* Multiplication Factor (Denominator Part) */ - signed long tmp; - u32 ref_freq = clk_get_rate(clk->parent); + unsigned long reg; - while (((ref_freq / pd) * 10) > rate) - pd++; + reg = __raw_readl(MXC_CCM_UPCTL); - if ((ref_freq / pd) < PRE_DIV_MIN_FREQ) - return -EINVAL; + return mxc_decode_pll(reg, pll_ref_get_rate()); +} - /* the ref_freq/2 in the following is to round up */ - mfi = (((rate / 2) * pd) + (ref_freq / 2)) / ref_freq; - if (mfi < 5 || mfi > 15) - return -EINVAL; +static unsigned long serial_pll_get_rate(struct clk *clk) +{ + unsigned long reg; - /* pick a mfd value that will work - * then solve for mfn */ - mfd = ref_freq / 50000; - - /* - * pll_freq * pd * mfd - * mfn = -------------------- - (mfi * mfd) - * 2 * ref_freq - */ - /* the tmp/2 is for rounding */ - tmp = ref_freq / 10000; - mfn = - ((((((rate / 2) + (tmp / 2)) / tmp) * pd) * mfd) / 10000) - - (mfi * mfd); - - mfn = mfn & 0x3ff; - pd--; - mfd--; - - /* Change the Pll value */ - reg = (mfi << MXC_CCM_PCTL_MFI_OFFSET) | - (mfn << MXC_CCM_PCTL_MFN_OFFSET) | - (mfd << MXC_CCM_PCTL_MFD_OFFSET) | (pd << MXC_CCM_PCTL_PD_OFFSET); - - if (clk == &mcu_pll_clk) - __raw_writel(reg, MXC_CCM_MPCTL); - else if (clk == &usb_pll_clk) - __raw_writel(reg, MXC_CCM_UPCTL); - else if (clk == &serial_pll_clk) - __raw_writel(reg, MXC_CCM_SRPCTL); + reg = __raw_readl(MXC_CCM_SRPCTL); - return 0; + return mxc_decode_pll(reg, pll_ref_get_rate()); } -static unsigned long _clk_pll_get_rate(struct clk *clk) +static unsigned long mcu_pll_get_rate(struct clk *clk) { unsigned long reg, ccmr; - unsigned int prcs, ref_clk; ccmr = __raw_readl(MXC_CCM_CCMR); - prcs = (ccmr & MXC_CCM_CCMR_PRCS_MASK) >> MXC_CCM_CCMR_PRCS_OFFSET; - if (prcs == 0x1) - ref_clk = CKIL_CLK_FREQ * 1024; - else - ref_clk = clk_get_rate(&ckih_clk); - - if (clk == &mcu_pll_clk) { - if ((ccmr & MXC_CCM_CCMR_MPE) == 0) - return ref_clk; - if ((ccmr & MXC_CCM_CCMR_MDS) != 0) - return ref_clk; - reg = __raw_readl(MXC_CCM_MPCTL); - } else if (clk == &usb_pll_clk) - reg = __raw_readl(MXC_CCM_UPCTL); - else if (clk == &serial_pll_clk) - reg = __raw_readl(MXC_CCM_SRPCTL); - else { - BUG(); - return 0; - } - return mxc_decode_pll(reg, ref_clk); + if (!(ccmr & MXC_CCM_CCMR_MPE) || (ccmr & MXC_CCM_CCMR_MDS)) + return clk_get_rate(&ckih_clk); + + reg = __raw_readl(MXC_CCM_MPCTL); + + return mxc_decode_pll(reg, pll_ref_get_rate()); } -static int _clk_usb_pll_enable(struct clk *clk) +static int usb_pll_enable(struct clk *clk) { u32 reg; @@ -201,7 +162,7 @@ static int _clk_usb_pll_enable(struct clk *clk) return 0; } -static void _clk_usb_pll_disable(struct clk *clk) +static void usb_pll_disable(struct clk *clk) { u32 reg; @@ -210,7 +171,7 @@ static void _clk_usb_pll_disable(struct clk *clk) __raw_writel(reg, MXC_CCM_CCMR); } -static int _clk_serial_pll_enable(struct clk *clk) +static int serial_pll_enable(struct clk *clk) { u32 reg; @@ -224,7 +185,7 @@ static int _clk_serial_pll_enable(struct clk *clk) return 0; } -static void _clk_serial_pll_disable(struct clk *clk) +static void serial_pll_disable(struct clk *clk) { u32 reg; @@ -237,7 +198,7 @@ static void _clk_serial_pll_disable(struct clk *clk) #define PDR1(mask, off) ((__raw_readl(MXC_CCM_PDR1) & mask) >> off) #define PDR2(mask, off) ((__raw_readl(MXC_CCM_PDR2) & mask) >> off) -static unsigned long _clk_mcu_main_get_rate(struct clk *clk) +static unsigned long mcu_main_get_rate(struct clk *clk) { u32 pmcr0 = __raw_readl(MXC_CCM_PMCR0); @@ -247,7 +208,7 @@ static unsigned long _clk_mcu_main_get_rate(struct clk *clk) return clk_get_rate(&mcu_pll_clk); } -static unsigned long _clk_hclk_get_rate(struct clk *clk) +static unsigned long ahb_get_rate(struct clk *clk) { unsigned long max_pdf; @@ -256,7 +217,7 @@ static unsigned long _clk_hclk_get_rate(struct clk *clk) return clk_get_rate(clk->parent) / (max_pdf + 1); } -static unsigned long _clk_ipg_get_rate(struct clk *clk) +static unsigned long ipg_get_rate(struct clk *clk) { unsigned long ipg_pdf; @@ -265,7 +226,7 @@ static unsigned long _clk_ipg_get_rate(struct clk *clk) return clk_get_rate(clk->parent) / (ipg_pdf + 1); } -static unsigned long _clk_nfc_get_rate(struct clk *clk) +static unsigned long nfc_get_rate(struct clk *clk) { unsigned long nfc_pdf; @@ -274,7 +235,7 @@ static unsigned long _clk_nfc_get_rate(struct clk *clk) return clk_get_rate(clk->parent) / (nfc_pdf + 1); } -static unsigned long _clk_hsp_get_rate(struct clk *clk) +static unsigned long hsp_get_rate(struct clk *clk) { unsigned long hsp_pdf; @@ -283,7 +244,7 @@ static unsigned long _clk_hsp_get_rate(struct clk *clk) return clk_get_rate(clk->parent) / (hsp_pdf + 1); } -static unsigned long _clk_usb_get_rate(struct clk *clk) +static unsigned long usb_get_rate(struct clk *clk) { unsigned long usb_pdf, usb_prepdf; @@ -294,7 +255,7 @@ static unsigned long _clk_usb_get_rate(struct clk *clk) return clk_get_rate(clk->parent) / (usb_prepdf + 1) / (usb_pdf + 1); } -static unsigned long _clk_csi_get_rate(struct clk *clk) +static unsigned long csi_get_rate(struct clk *clk) { u32 reg, pre, post; @@ -308,7 +269,7 @@ static unsigned long _clk_csi_get_rate(struct clk *clk) return clk_get_rate(clk->parent) / (pre * post); } -static unsigned long _clk_csi_round_rate(struct clk *clk, unsigned long rate) +static unsigned long csi_round_rate(struct clk *clk, unsigned long rate) { u32 pre, post, parent = clk_get_rate(clk->parent); u32 div = parent / rate; @@ -321,7 +282,7 @@ static unsigned long _clk_csi_round_rate(struct clk *clk, unsigned long rate) return parent / (pre * post); } -static int _clk_csi_set_rate(struct clk *clk, unsigned long rate) +static int csi_set_rate(struct clk *clk, unsigned long rate) { u32 reg, div, pre, post, parent = clk_get_rate(clk->parent); @@ -342,16 +303,7 @@ static int _clk_csi_set_rate(struct clk *clk, unsigned long rate) return 0; } -static unsigned long _clk_per_get_rate(struct clk *clk) -{ - unsigned long per_pdf; - - per_pdf = PDR0(MXC_CCM_PDR0_PER_PODF_MASK, - MXC_CCM_PDR0_PER_PODF_OFFSET); - return clk_get_rate(clk->parent) / (per_pdf + 1); -} - -static unsigned long _clk_ssi1_get_rate(struct clk *clk) +static unsigned long ssi1_get_rate(struct clk *clk) { unsigned long ssi1_pdf, ssi1_prepdf; @@ -362,7 +314,7 @@ static unsigned long _clk_ssi1_get_rate(struct clk *clk) return clk_get_rate(clk->parent) / (ssi1_prepdf + 1) / (ssi1_pdf + 1); } -static unsigned long _clk_ssi2_get_rate(struct clk *clk) +static unsigned long ssi2_get_rate(struct clk *clk) { unsigned long ssi2_pdf, ssi2_prepdf; @@ -373,7 +325,7 @@ static unsigned long _clk_ssi2_get_rate(struct clk *clk) return clk_get_rate(clk->parent) / (ssi2_prepdf + 1) / (ssi2_pdf + 1); } -static unsigned long _clk_firi_get_rate(struct clk *clk) +static unsigned long firi_get_rate(struct clk *clk) { unsigned long firi_pdf, firi_prepdf; @@ -384,7 +336,7 @@ static unsigned long _clk_firi_get_rate(struct clk *clk) return clk_get_rate(clk->parent) / (firi_prepdf + 1) / (firi_pdf + 1); } -static unsigned long _clk_firi_round_rate(struct clk *clk, unsigned long rate) +static unsigned long firi_round_rate(struct clk *clk, unsigned long rate) { u32 pre, post; u32 parent = clk_get_rate(clk->parent); @@ -399,7 +351,7 @@ static unsigned long _clk_firi_round_rate(struct clk *clk, unsigned long rate) } -static int _clk_firi_set_rate(struct clk *clk, unsigned long rate) +static int firi_set_rate(struct clk *clk, unsigned long rate) { u32 reg, div, pre, post, parent = clk_get_rate(clk->parent); @@ -420,12 +372,12 @@ static int _clk_firi_set_rate(struct clk *clk, unsigned long rate) return 0; } -static unsigned long _clk_mbx_get_rate(struct clk *clk) +static unsigned long mbx_get_rate(struct clk *clk) { return clk_get_rate(clk->parent) / 2; } -static unsigned long _clk_mstick1_get_rate(struct clk *clk) +static unsigned long mstick1_get_rate(struct clk *clk) { unsigned long msti_pdf; @@ -434,7 +386,7 @@ static unsigned long _clk_mstick1_get_rate(struct clk *clk) return clk_get_rate(clk->parent) / (msti_pdf + 1); } -static unsigned long _clk_mstick2_get_rate(struct clk *clk) +static unsigned long mstick2_get_rate(struct clk *clk) { unsigned long msti_pdf; @@ -451,663 +403,185 @@ static unsigned long clk_ckih_get_rate(struct clk *clk) } static struct clk ckih_clk = { - .name = "ckih", .get_rate = clk_ckih_get_rate, }; -static unsigned long clk_ckil_get_rate(struct clk *clk) -{ - return CKIL_CLK_FREQ; -} - -static struct clk ckil_clk = { - .name = "ckil", - .get_rate = clk_ckil_get_rate, -}; - static struct clk mcu_pll_clk = { - .name = "mcu_pll", .parent = &ckih_clk, - .set_rate = _clk_pll_set_rate, - .get_rate = _clk_pll_get_rate, + .get_rate = mcu_pll_get_rate, }; static struct clk mcu_main_clk = { - .name = "mcu_main_clk", .parent = &mcu_pll_clk, - .get_rate = _clk_mcu_main_get_rate, + .get_rate = mcu_main_get_rate, }; static struct clk serial_pll_clk = { - .name = "serial_pll", .parent = &ckih_clk, - .set_rate = _clk_pll_set_rate, - .get_rate = _clk_pll_get_rate, - .enable = _clk_serial_pll_enable, - .disable = _clk_serial_pll_disable, + .get_rate = serial_pll_get_rate, + .enable = serial_pll_enable, + .disable = serial_pll_disable, }; static struct clk usb_pll_clk = { - .name = "usb_pll", .parent = &ckih_clk, - .set_rate = _clk_pll_set_rate, - .get_rate = _clk_pll_get_rate, - .enable = _clk_usb_pll_enable, - .disable = _clk_usb_pll_disable, + .get_rate = usb_pll_get_rate, + .enable = usb_pll_enable, + .disable = usb_pll_disable, }; static struct clk ahb_clk = { - .name = "ahb_clk", .parent = &mcu_main_clk, - .get_rate = _clk_hclk_get_rate, -}; - -static struct clk per_clk = { - .name = "per_clk", - .parent = &usb_pll_clk, - .get_rate = _clk_per_get_rate, -}; - -static struct clk perclk_clk = { - .name = "perclk_clk", - .parent = &ipg_clk, -}; - -static struct clk cspi_clk[] = { - { - .name = "cspi_clk", - .id = 0, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR2, - .enable_shift = MXC_CCM_CGR2_CSPI1_OFFSET, - .disable = _clk_disable,}, - { - .name = "cspi_clk", - .id = 1, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR2, - .enable_shift = MXC_CCM_CGR2_CSPI2_OFFSET, - .disable = _clk_disable,}, - { - .name = "cspi_clk", - .id = 2, - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR0, - .enable_shift = MXC_CCM_CGR0_CSPI3_OFFSET, - .disable = _clk_disable,}, -}; - -static struct clk ipg_clk = { - .name = "ipg_clk", - .parent = &ahb_clk, - .get_rate = _clk_ipg_get_rate, -}; - -static struct clk emi_clk = { - .name = "emi_clk", - .parent = &ahb_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR2, - .enable_shift = MXC_CCM_CGR2_EMI_OFFSET, - .disable = _clk_emi_disable, -}; - -static struct clk gpt_clk = { - .name = "gpt_clk", - .parent = &perclk_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR0, - .enable_shift = MXC_CCM_CGR0_GPT_OFFSET, - .disable = _clk_disable, -}; - -static struct clk pwm_clk = { - .name = "pwm_clk", - .parent = &perclk_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR0, - .enable_shift = MXC_CCM_CGR1_PWM_OFFSET, - .disable = _clk_disable, -}; - -static struct clk epit_clk[] = { - { - .name = "epit_clk", - .id = 0, - .parent = &perclk_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR0, - .enable_shift = MXC_CCM_CGR0_EPIT1_OFFSET, - .disable = _clk_disable,}, - { - .name = "epit_clk", - .id = 1, - .parent = &perclk_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR0, - .enable_shift = MXC_CCM_CGR0_EPIT2_OFFSET, - .disable = _clk_disable,}, -}; - -static struct clk nfc_clk = { - .name = "nfc", - .parent = &ahb_clk, - .get_rate = _clk_nfc_get_rate, -}; - -static struct clk scc_clk = { - .name = "scc_clk", - .parent = &ipg_clk, -}; - -static struct clk ipu_clk = { - .name = "ipu_clk", - .parent = &mcu_main_clk, - .get_rate = _clk_hsp_get_rate, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR1, - .enable_shift = MXC_CCM_CGR1_IPU_OFFSET, - .disable = _clk_disable, -}; - -static struct clk kpp_clk = { - .name = "kpp_clk", - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR1, - .enable_shift = MXC_CCM_CGR1_KPP_OFFSET, - .disable = _clk_disable, -}; - -static struct clk wdog_clk = { - .name = "wdog_clk", - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR1, - .enable_shift = MXC_CCM_CGR1_WDOG_OFFSET, - .disable = _clk_disable, -}; -static struct clk rtc_clk = { - .name = "rtc_clk", - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR1, - .enable_shift = MXC_CCM_CGR1_RTC_OFFSET, - .disable = _clk_disable, -}; - -static struct clk usb_clk[] = { - { - .name = "usb_clk", - .parent = &usb_pll_clk, - .get_rate = _clk_usb_get_rate,}, - { - .name = "usb_ahb_clk", - .parent = &ahb_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR1, - .enable_shift = MXC_CCM_CGR1_USBOTG_OFFSET, - .disable = _clk_disable,}, -}; - -static struct clk csi_clk = { - .name = "csi_clk", - .parent = &serial_pll_clk, - .get_rate = _clk_csi_get_rate, - .round_rate = _clk_csi_round_rate, - .set_rate = _clk_csi_set_rate, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR1, - .enable_shift = MXC_CCM_CGR1_CSI_OFFSET, - .disable = _clk_disable, -}; - -static struct clk uart_clk[] = { - { - .name = "uart", - .id = 0, - .parent = &perclk_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR0, - .enable_shift = MXC_CCM_CGR0_UART1_OFFSET, - .disable = _clk_disable,}, - { - .name = "uart", - .id = 1, - .parent = &perclk_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR0, - .enable_shift = MXC_CCM_CGR0_UART2_OFFSET, - .disable = _clk_disable,}, - { - .name = "uart", - .id = 2, - .parent = &perclk_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR1, - .enable_shift = MXC_CCM_CGR1_UART3_OFFSET, - .disable = _clk_disable,}, - { - .name = "uart", - .id = 3, - .parent = &perclk_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR1, - .enable_shift = MXC_CCM_CGR1_UART4_OFFSET, - .disable = _clk_disable,}, - { - .name = "uart", - .id = 4, - .parent = &perclk_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR1, - .enable_shift = MXC_CCM_CGR1_UART5_OFFSET, - .disable = _clk_disable,}, -}; - -static struct clk i2c_clk[] = { - { - .name = "i2c_clk", - .id = 0, - .parent = &perclk_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR0, - .enable_shift = MXC_CCM_CGR0_I2C1_OFFSET, - .disable = _clk_disable,}, - { - .name = "i2c_clk", - .id = 1, - .parent = &perclk_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR0, - .enable_shift = MXC_CCM_CGR0_I2C2_OFFSET, - .disable = _clk_disable,}, - { - .name = "i2c_clk", - .id = 2, - .parent = &perclk_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR0, - .enable_shift = MXC_CCM_CGR0_I2C3_OFFSET, - .disable = _clk_disable,}, -}; - -static struct clk owire_clk = { - .name = "owire", - .parent = &perclk_clk, - .enable_reg = MXC_CCM_CGR1, - .enable_shift = MXC_CCM_CGR1_OWIRE_OFFSET, - .enable = _clk_enable, - .disable = _clk_disable, -}; - -static struct clk sdhc_clk[] = { - { - .name = "sdhc_clk", - .id = 0, - .parent = &perclk_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR0, - .enable_shift = MXC_CCM_CGR0_SD_MMC1_OFFSET, - .disable = _clk_disable,}, - { - .name = "sdhc_clk", - .id = 1, - .parent = &perclk_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR0, - .enable_shift = MXC_CCM_CGR0_SD_MMC2_OFFSET, - .disable = _clk_disable,}, -}; - -static struct clk ssi_clk[] = { - { - .name = "ssi_clk", - .parent = &serial_pll_clk, - .get_rate = _clk_ssi1_get_rate, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR0, - .enable_shift = MXC_CCM_CGR0_SSI1_OFFSET, - .disable = _clk_disable,}, - { - .name = "ssi_clk", - .id = 1, - .parent = &serial_pll_clk, - .get_rate = _clk_ssi2_get_rate, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR2, - .enable_shift = MXC_CCM_CGR2_SSI2_OFFSET, - .disable = _clk_disable,}, -}; - -static struct clk firi_clk = { - .name = "firi_clk", - .parent = &usb_pll_clk, - .round_rate = _clk_firi_round_rate, - .set_rate = _clk_firi_set_rate, - .get_rate = _clk_firi_get_rate, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR2, - .enable_shift = MXC_CCM_CGR2_FIRI_OFFSET, - .disable = _clk_disable, -}; - -static struct clk ata_clk = { - .name = "ata_clk", - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR0, - .enable_shift = MXC_CCM_CGR0_ATA_OFFSET, - .disable = _clk_disable, -}; - -static struct clk mbx_clk = { - .name = "mbx_clk", - .parent = &ahb_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR2, - .enable_shift = MXC_CCM_CGR2_GACC_OFFSET, - .get_rate = _clk_mbx_get_rate, -}; - -static struct clk vpu_clk = { - .name = "vpu_clk", - .parent = &ahb_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR2, - .enable_shift = MXC_CCM_CGR2_GACC_OFFSET, - .get_rate = _clk_mbx_get_rate, -}; - -static struct clk rtic_clk = { - .name = "rtic_clk", - .parent = &ahb_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR2, - .enable_shift = MXC_CCM_CGR2_RTIC_OFFSET, - .disable = _clk_disable, -}; - -static struct clk rng_clk = { - .name = "rng_clk", - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR0, - .enable_shift = MXC_CCM_CGR0_RNG_OFFSET, - .disable = _clk_disable, -}; - -static struct clk sdma_clk[] = { - { - .name = "sdma_ahb_clk", - .parent = &ahb_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR0, - .enable_shift = MXC_CCM_CGR0_SDMA_OFFSET, - .disable = _clk_disable,}, - { - .name = "sdma_ipg_clk", - .parent = &ipg_clk,} -}; - -static struct clk mpeg4_clk = { - .name = "mpeg4_clk", - .parent = &ahb_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR1, - .enable_shift = MXC_CCM_CGR1_HANTRO_OFFSET, - .disable = _clk_disable, -}; - -static struct clk vl2cc_clk = { - .name = "vl2cc_clk", - .parent = &ahb_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR1, - .enable_shift = MXC_CCM_CGR1_HANTRO_OFFSET, - .disable = _clk_disable, -}; - -static struct clk mstick_clk[] = { - { - .name = "mstick_clk", - .id = 0, - .parent = &usb_pll_clk, - .get_rate = _clk_mstick1_get_rate, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR1, - .enable_shift = MXC_CCM_CGR1_MEMSTICK1_OFFSET, - .disable = _clk_disable,}, - { - .name = "mstick_clk", - .id = 1, - .parent = &usb_pll_clk, - .get_rate = _clk_mstick2_get_rate, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR1, - .enable_shift = MXC_CCM_CGR1_MEMSTICK2_OFFSET, - .disable = _clk_disable,}, -}; - -static struct clk iim_clk = { - .name = "iim_clk", - .parent = &ipg_clk, - .enable = _clk_enable, - .enable_reg = MXC_CCM_CGR0, - .enable_shift = MXC_CCM_CGR0_IIM_OFFSET, - .disable = _clk_disable, -}; - -static unsigned long _clk_cko1_round_rate(struct clk *clk, unsigned long rate) -{ - u32 div, parent = clk_get_rate(clk->parent); - - div = parent / rate; - if (parent % rate) - div++; - - if (div > 8) - div = 16; - else if (div > 4) - div = 8; - else if (div > 2) - div = 4; - - return parent / div; -} - -static int _clk_cko1_set_rate(struct clk *clk, unsigned long rate) -{ - u32 reg, div, parent = clk_get_rate(clk->parent); - - div = parent / rate; - - if (div == 16) - div = 4; - else if (div == 8) - div = 3; - else if (div == 4) - div = 2; - else if (div == 2) - div = 1; - else if (div == 1) - div = 0; - else - return -EINVAL; - - reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOUTDIV_MASK; - reg |= div << MXC_CCM_COSR_CLKOUTDIV_OFFSET; - __raw_writel(reg, MXC_CCM_COSR); - - return 0; -} - -static unsigned long _clk_cko1_get_rate(struct clk *clk) -{ - u32 div; - - div = __raw_readl(MXC_CCM_COSR) & MXC_CCM_COSR_CLKOUTDIV_MASK >> - MXC_CCM_COSR_CLKOUTDIV_OFFSET; - - return clk_get_rate(clk->parent) / (1 << div); -} - -static int _clk_cko1_set_parent(struct clk *clk, struct clk *parent) -{ - u32 reg; - - reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOSEL_MASK; - - if (parent == &mcu_main_clk) - reg |= 0 << MXC_CCM_COSR_CLKOSEL_OFFSET; - else if (parent == &ipg_clk) - reg |= 1 << MXC_CCM_COSR_CLKOSEL_OFFSET; - else if (parent == &usb_pll_clk) - reg |= 2 << MXC_CCM_COSR_CLKOSEL_OFFSET; - else if (parent == mcu_main_clk.parent) - reg |= 3 << MXC_CCM_COSR_CLKOSEL_OFFSET; - else if (parent == &ahb_clk) - reg |= 5 << MXC_CCM_COSR_CLKOSEL_OFFSET; - else if (parent == &serial_pll_clk) - reg |= 7 << MXC_CCM_COSR_CLKOSEL_OFFSET; - else if (parent == &ckih_clk) - reg |= 8 << MXC_CCM_COSR_CLKOSEL_OFFSET; - else if (parent == &emi_clk) - reg |= 9 << MXC_CCM_COSR_CLKOSEL_OFFSET; - else if (parent == &ipu_clk) - reg |= 0xA << MXC_CCM_COSR_CLKOSEL_OFFSET; - else if (parent == &nfc_clk) - reg |= 0xB << MXC_CCM_COSR_CLKOSEL_OFFSET; - else if (parent == &uart_clk[0]) - reg |= 0xC << MXC_CCM_COSR_CLKOSEL_OFFSET; - else - return -EINVAL; - - __raw_writel(reg, MXC_CCM_COSR); - - return 0; -} - -static int _clk_cko1_enable(struct clk *clk) -{ - u32 reg; - - reg = __raw_readl(MXC_CCM_COSR) | MXC_CCM_COSR_CLKOEN; - __raw_writel(reg, MXC_CCM_COSR); - - return 0; -} - -static void _clk_cko1_disable(struct clk *clk) -{ - u32 reg; - - reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOEN; - __raw_writel(reg, MXC_CCM_COSR); -} + .get_rate = ahb_get_rate, +}; + +#define DEFINE_CLOCK(name, i, er, es, gr, s, p) \ + static struct clk name = { \ + .id = i, \ + .enable_reg = er, \ + .enable_shift = es, \ + .get_rate = gr, \ + .enable = cgr_enable, \ + .disable = cgr_disable, \ + .secondary = s, \ + .parent = p, \ + } -static struct clk cko1_clk = { - .name = "cko1_clk", - .get_rate = _clk_cko1_get_rate, - .set_rate = _clk_cko1_set_rate, - .round_rate = _clk_cko1_round_rate, - .set_parent = _clk_cko1_set_parent, - .enable = _clk_cko1_enable, - .disable = _clk_cko1_disable, -}; +#define DEFINE_CLOCK1(name, i, er, es, getsetround, s, p) \ + static struct clk name = { \ + .id = i, \ + .enable_reg = er, \ + .enable_shift = es, \ + .get_rate = getsetround##_get_rate, \ + .set_rate = getsetround##_set_rate, \ + .round_rate = getsetround##_round_rate, \ + .enable = cgr_enable, \ + .disable = cgr_disable, \ + .secondary = s, \ + .parent = p, \ + } -static struct clk *mxc_clks[] = { - &ckih_clk, - &ckil_clk, - &mcu_pll_clk, - &usb_pll_clk, - &serial_pll_clk, - &mcu_main_clk, - &ahb_clk, - &per_clk, - &perclk_clk, - &cko1_clk, - &emi_clk, - &cspi_clk[0], - &cspi_clk[1], - &cspi_clk[2], - &ipg_clk, - &gpt_clk, - &pwm_clk, - &wdog_clk, - &rtc_clk, - &epit_clk[0], - &epit_clk[1], - &nfc_clk, - &ipu_clk, - &kpp_clk, - &usb_clk[0], - &usb_clk[1], - &csi_clk, - &uart_clk[0], - &uart_clk[1], - &uart_clk[2], - &uart_clk[3], - &uart_clk[4], - &i2c_clk[0], - &i2c_clk[1], - &i2c_clk[2], - &owire_clk, - &sdhc_clk[0], - &sdhc_clk[1], - &ssi_clk[0], - &ssi_clk[1], - &firi_clk, - &ata_clk, - &rtic_clk, - &rng_clk, - &sdma_clk[0], - &sdma_clk[1], - &mstick_clk[0], - &mstick_clk[1], - &scc_clk, - &iim_clk, +DEFINE_CLOCK(perclk_clk, 0, NULL, 0, NULL, NULL, &ipg_clk); + +DEFINE_CLOCK(sdhc1_clk, 0, MXC_CCM_CGR0, 0, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(sdhc2_clk, 1, MXC_CCM_CGR0, 2, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CGR0, 4, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(epit1_clk, 0, MXC_CCM_CGR0, 6, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(epit2_clk, 1, MXC_CCM_CGR0, 8, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(iim_clk, 0, MXC_CCM_CGR0, 10, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(ata_clk, 0, MXC_CCM_CGR0, 12, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(sdma_clk1, 0, MXC_CCM_CGR0, 14, NULL, &sdma_clk1, &ahb_clk); +DEFINE_CLOCK(cspi3_clk, 2, MXC_CCM_CGR0, 16, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(rng_clk, 0, MXC_CCM_CGR0, 18, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CGR0, 20, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CGR0, 22, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CGR0, 24, ssi1_get_rate, NULL, &serial_pll_clk); +DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CGR0, 26, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(i2c2_clk, 1, MXC_CCM_CGR0, 28, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(i2c3_clk, 2, MXC_CCM_CGR0, 30, NULL, NULL, &perclk_clk); + +DEFINE_CLOCK(mpeg4_clk, 0, MXC_CCM_CGR1, 0, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(mstick1_clk, 0, MXC_CCM_CGR1, 2, mstick1_get_rate, NULL, &usb_pll_clk); +DEFINE_CLOCK(mstick2_clk, 1, MXC_CCM_CGR1, 4, mstick2_get_rate, NULL, &usb_pll_clk); +DEFINE_CLOCK1(csi_clk, 0, MXC_CCM_CGR1, 6, csi, NULL, &ahb_clk); +DEFINE_CLOCK(rtc_clk, 0, MXC_CCM_CGR1, 8, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(wdog_clk, 0, MXC_CCM_CGR1, 10, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(pwm_clk, 0, MXC_CCM_CGR1, 12, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(usb_clk2, 0, MXC_CCM_CGR1, 18, usb_get_rate, NULL, &ahb_clk); +DEFINE_CLOCK(kpp_clk, 0, MXC_CCM_CGR1, 20, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(ipu_clk, 0, MXC_CCM_CGR1, 22, hsp_get_rate, NULL, &mcu_main_clk); +DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CGR1, 24, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(uart4_clk, 3, MXC_CCM_CGR1, 26, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(uart5_clk, 4, MXC_CCM_CGR1, 28, NULL, NULL, &perclk_clk); +DEFINE_CLOCK(owire_clk, 0, MXC_CCM_CGR1, 30, NULL, NULL, &perclk_clk); + +DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CGR2, 0, ssi2_get_rate, NULL, &serial_pll_clk); +DEFINE_CLOCK(cspi1_clk, 0, MXC_CCM_CGR2, 2, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(cspi2_clk, 1, MXC_CCM_CGR2, 4, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(mbx_clk, 0, MXC_CCM_CGR2, 6, mbx_get_rate, NULL, &ahb_clk); +DEFINE_CLOCK(emi_clk, 0, MXC_CCM_CGR2, 8, NULL, NULL, &ahb_clk); +DEFINE_CLOCK(rtic_clk, 0, MXC_CCM_CGR2, 10, NULL, NULL, &ahb_clk); +DEFINE_CLOCK1(firi_clk, 0, MXC_CCM_CGR2, 12, firi, NULL, &usb_pll_clk); + +DEFINE_CLOCK(sdma_clk2, 0, NULL, 0, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(usb_clk1, 0, NULL, 0, usb_get_rate, NULL, &usb_pll_clk); +DEFINE_CLOCK(nfc_clk, 0, NULL, 0, nfc_get_rate, NULL, &ahb_clk); +DEFINE_CLOCK(scc_clk, 0, NULL, 0, NULL, NULL, &ipg_clk); +DEFINE_CLOCK(ipg_clk, 0, NULL, 0, ipg_get_rate, NULL, &ahb_clk); + +#define _REGISTER_CLOCK(d, n, c) \ + { \ + .dev_id = d, \ + .con_id = n, \ + .clk = &c, \ + }, + +static struct clk_lookup lookups[] __initdata = { + _REGISTER_CLOCK(NULL, "emi", emi_clk) + _REGISTER_CLOCK(NULL, "cspi", cspi1_clk) + _REGISTER_CLOCK(NULL, "cspi", cspi2_clk) + _REGISTER_CLOCK(NULL, "cspi", cspi3_clk) + _REGISTER_CLOCK(NULL, "gpt", gpt_clk) + _REGISTER_CLOCK(NULL, "pwm", pwm_clk) + _REGISTER_CLOCK(NULL, "wdog", wdog_clk) + _REGISTER_CLOCK(NULL, "rtc", rtc_clk) + _REGISTER_CLOCK(NULL, "epit", epit1_clk) + _REGISTER_CLOCK(NULL, "epit", epit2_clk) + _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk) + _REGISTER_CLOCK("ipu-core", NULL, ipu_clk) + _REGISTER_CLOCK("mx3_sdc_fb", NULL, ipu_clk) + _REGISTER_CLOCK(NULL, "kpp", kpp_clk) + _REGISTER_CLOCK("fsl-usb2-udc", "usb", usb_clk1) + _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", usb_clk2) + _REGISTER_CLOCK("mx3-camera.0", "csi", csi_clk) + _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk) + _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk) + _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk) + _REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk) + _REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk) + _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk) + _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk) + _REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_clk) + _REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk) + _REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk) + _REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk) + _REGISTER_CLOCK(NULL, "ssi", ssi1_clk) + _REGISTER_CLOCK(NULL, "ssi", ssi2_clk) + _REGISTER_CLOCK(NULL, "firi", firi_clk) + _REGISTER_CLOCK(NULL, "ata", ata_clk) + _REGISTER_CLOCK(NULL, "rtic", rtic_clk) + _REGISTER_CLOCK(NULL, "rng", rng_clk) + _REGISTER_CLOCK(NULL, "sdma_ahb", sdma_clk1) + _REGISTER_CLOCK(NULL, "sdma_ipg", sdma_clk2) + _REGISTER_CLOCK(NULL, "mstick", mstick1_clk) + _REGISTER_CLOCK(NULL, "mstick", mstick2_clk) + _REGISTER_CLOCK(NULL, "scc", scc_clk) + _REGISTER_CLOCK(NULL, "iim", iim_clk) + _REGISTER_CLOCK(NULL, "mpeg4", mpeg4_clk) + _REGISTER_CLOCK(NULL, "mbx", mbx_clk) }; int __init mx31_clocks_init(unsigned long fref) { u32 reg; - struct clk **clkp; + int i; mxc_set_cpu_type(MXC_CPU_MX31); ckih_rate = fref; - for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++) - clk_register(*clkp); - - if (cpu_is_mx31()) { - clk_register(&mpeg4_clk); - clk_register(&mbx_clk); - } else { - clk_register(&vpu_clk); - clk_register(&vl2cc_clk); - } + for (i = 0; i < ARRAY_SIZE(lookups); i++) + clkdev_add(&lookups[i]); /* Turn off all possible clocks */ - __raw_writel(MXC_CCM_CGR0_GPT_MASK, MXC_CCM_CGR0); + __raw_writel((3 << 4), MXC_CCM_CGR0); __raw_writel(0, MXC_CCM_CGR1); - - __raw_writel(MXC_CCM_CGR2_EMI_MASK | - MXC_CCM_CGR2_IPMUX1_MASK | - MXC_CCM_CGR2_IPMUX2_MASK | - MXC_CCM_CGR2_MXCCLKENSEL_MASK | /* for MX32 */ - MXC_CCM_CGR2_CHIKCAMPEN_MASK | /* for MX32 */ - MXC_CCM_CGR2_OVRVPUBUSY_MASK | /* for MX32 */ + __raw_writel((3 << 8) | (3 << 14) | (3 << 16)| 1 << 27 | 1 << 28, /* Bit 27 and 28 are not defined for MX32, but still required to be set */ MXC_CCM_CGR2); - clk_disable(&cko1_clk); - clk_disable(&usb_pll_clk); + usb_pll_disable(&usb_pll_clk); pr_info("Clock input source is %ld\n", clk_get_rate(&ckih_clk)); diff --git a/arch/arm/mach-mx3/crm_regs.h b/arch/arm/mach-mx3/crm_regs.h index 4a0e0ede23b..adfa3627ad8 100644 --- a/arch/arm/mach-mx3/crm_regs.h +++ b/arch/arm/mach-mx3/crm_regs.h @@ -91,47 +91,6 @@ #define MXC_CCM_PDR0_MCU_PODF_OFFSET 0 #define MXC_CCM_PDR0_MCU_PODF_MASK 0x7 -#define MXC_CCM_PDR0_HSP_DIV_1 (0x0 << 11) -#define MXC_CCM_PDR0_HSP_DIV_2 (0x1 << 11) -#define MXC_CCM_PDR0_HSP_DIV_3 (0x2 << 11) -#define MXC_CCM_PDR0_HSP_DIV_4 (0x3 << 11) -#define MXC_CCM_PDR0_HSP_DIV_5 (0x4 << 11) -#define MXC_CCM_PDR0_HSP_DIV_6 (0x5 << 11) -#define MXC_CCM_PDR0_HSP_DIV_7 (0x6 << 11) -#define MXC_CCM_PDR0_HSP_DIV_8 (0x7 << 11) - -#define MXC_CCM_PDR0_IPG_DIV_1 (0x0 << 6) -#define MXC_CCM_PDR0_IPG_DIV_2 (0x1 << 6) -#define MXC_CCM_PDR0_IPG_DIV_3 (0x2 << 6) -#define MXC_CCM_PDR0_IPG_DIV_4 (0x3 << 6) - -#define MXC_CCM_PDR0_MAX_DIV_1 (0x0 << 3) -#define MXC_CCM_PDR0_MAX_DIV_2 (0x1 << 3) -#define MXC_CCM_PDR0_MAX_DIV_3 (0x2 << 3) -#define MXC_CCM_PDR0_MAX_DIV_4 (0x3 << 3) -#define MXC_CCM_PDR0_MAX_DIV_5 (0x4 << 3) -#define MXC_CCM_PDR0_MAX_DIV_6 (0x5 << 3) -#define MXC_CCM_PDR0_MAX_DIV_7 (0x6 << 3) -#define MXC_CCM_PDR0_MAX_DIV_8 (0x7 << 3) - -#define MXC_CCM_PDR0_NFC_DIV_1 (0x0 << 8) -#define MXC_CCM_PDR0_NFC_DIV_2 (0x1 << 8) -#define MXC_CCM_PDR0_NFC_DIV_3 (0x2 << 8) -#define MXC_CCM_PDR0_NFC_DIV_4 (0x3 << 8) -#define MXC_CCM_PDR0_NFC_DIV_5 (0x4 << 8) -#define MXC_CCM_PDR0_NFC_DIV_6 (0x5 << 8) -#define MXC_CCM_PDR0_NFC_DIV_7 (0x6 << 8) -#define MXC_CCM_PDR0_NFC_DIV_8 (0x7 << 8) - -#define MXC_CCM_PDR0_MCU_DIV_1 0x0 -#define MXC_CCM_PDR0_MCU_DIV_2 0x1 -#define MXC_CCM_PDR0_MCU_DIV_3 0x2 -#define MXC_CCM_PDR0_MCU_DIV_4 0x3 -#define MXC_CCM_PDR0_MCU_DIV_5 0x4 -#define MXC_CCM_PDR0_MCU_DIV_6 0x5 -#define MXC_CCM_PDR0_MCU_DIV_7 0x6 -#define MXC_CCM_PDR0_MCU_DIV_8 0x7 - #define MXC_CCM_PDR1_USB_PRDF_OFFSET 30 #define MXC_CCM_PDR1_USB_PRDF_MASK (0x3 << 30) #define MXC_CCM_PDR1_USB_PODF_OFFSET 27 @@ -152,118 +111,6 @@ /* Bit definitions for RCSR */ #define MXC_CCM_RCSR_NF16B 0x80000000 -/* Bit definitions for both MCU, USB and SR PLL control registers */ -#define MXC_CCM_PCTL_BRM 0x80000000 -#define MXC_CCM_PCTL_PD_OFFSET 26 -#define MXC_CCM_PCTL_PD_MASK (0xF << 26) -#define MXC_CCM_PCTL_MFD_OFFSET 16 -#define MXC_CCM_PCTL_MFD_MASK (0x3FF << 16) -#define MXC_CCM_PCTL_MFI_OFFSET 10 -#define MXC_CCM_PCTL_MFI_MASK (0xF << 10) -#define MXC_CCM_PCTL_MFN_OFFSET 0 -#define MXC_CCM_PCTL_MFN_MASK 0x3FF - -#define MXC_CCM_CGR0_SD_MMC1_OFFSET 0 -#define MXC_CCM_CGR0_SD_MMC1_MASK (0x3 << 0) -#define MXC_CCM_CGR0_SD_MMC2_OFFSET 2 -#define MXC_CCM_CGR0_SD_MMC2_MASK (0x3 << 2) -#define MXC_CCM_CGR0_GPT_OFFSET 4 -#define MXC_CCM_CGR0_GPT_MASK (0x3 << 4) -#define MXC_CCM_CGR0_EPIT1_OFFSET 6 -#define MXC_CCM_CGR0_EPIT1_MASK (0x3 << 6) -#define MXC_CCM_CGR0_EPIT2_OFFSET 8 -#define MXC_CCM_CGR0_EPIT2_MASK (0x3 << 8) -#define MXC_CCM_CGR0_IIM_OFFSET 10 -#define MXC_CCM_CGR0_IIM_MASK (0x3 << 10) -#define MXC_CCM_CGR0_ATA_OFFSET 12 -#define MXC_CCM_CGR0_ATA_MASK (0x3 << 12) -#define MXC_CCM_CGR0_SDMA_OFFSET 14 -#define MXC_CCM_CGR0_SDMA_MASK (0x3 << 14) -#define MXC_CCM_CGR0_CSPI3_OFFSET 16 -#define MXC_CCM_CGR0_CSPI3_MASK (0x3 << 16) -#define MXC_CCM_CGR0_RNG_OFFSET 18 -#define MXC_CCM_CGR0_RNG_MASK (0x3 << 18) -#define MXC_CCM_CGR0_UART1_OFFSET 20 -#define MXC_CCM_CGR0_UART1_MASK (0x3 << 20) -#define MXC_CCM_CGR0_UART2_OFFSET 22 -#define MXC_CCM_CGR0_UART2_MASK (0x3 << 22) -#define MXC_CCM_CGR0_SSI1_OFFSET 24 -#define MXC_CCM_CGR0_SSI1_MASK (0x3 << 24) -#define MXC_CCM_CGR0_I2C1_OFFSET 26 -#define MXC_CCM_CGR0_I2C1_MASK (0x3 << 26) -#define MXC_CCM_CGR0_I2C2_OFFSET 28 -#define MXC_CCM_CGR0_I2C2_MASK (0x3 << 28) -#define MXC_CCM_CGR0_I2C3_OFFSET 30 -#define MXC_CCM_CGR0_I2C3_MASK (0x3 << 30) - -#define MXC_CCM_CGR1_HANTRO_OFFSET 0 -#define MXC_CCM_CGR1_HANTRO_MASK (0x3 << 0) -#define MXC_CCM_CGR1_MEMSTICK1_OFFSET 2 -#define MXC_CCM_CGR1_MEMSTICK1_MASK (0x3 << 2) -#define MXC_CCM_CGR1_MEMSTICK2_OFFSET 4 -#define MXC_CCM_CGR1_MEMSTICK2_MASK (0x3 << 4) -#define MXC_CCM_CGR1_CSI_OFFSET 6 -#define MXC_CCM_CGR1_CSI_MASK (0x3 << 6) -#define MXC_CCM_CGR1_RTC_OFFSET 8 -#define MXC_CCM_CGR1_RTC_MASK (0x3 << 8) -#define MXC_CCM_CGR1_WDOG_OFFSET 10 -#define MXC_CCM_CGR1_WDOG_MASK (0x3 << 10) -#define MXC_CCM_CGR1_PWM_OFFSET 12 -#define MXC_CCM_CGR1_PWM_MASK (0x3 << 12) -#define MXC_CCM_CGR1_SIM_OFFSET 14 -#define MXC_CCM_CGR1_SIM_MASK (0x3 << 14) -#define MXC_CCM_CGR1_ECT_OFFSET 16 -#define MXC_CCM_CGR1_ECT_MASK (0x3 << 16) -#define MXC_CCM_CGR1_USBOTG_OFFSET 18 -#define MXC_CCM_CGR1_USBOTG_MASK (0x3 << 18) -#define MXC_CCM_CGR1_KPP_OFFSET 20 -#define MXC_CCM_CGR1_KPP_MASK (0x3 << 20) -#define MXC_CCM_CGR1_IPU_OFFSET 22 -#define MXC_CCM_CGR1_IPU_MASK (0x3 << 22) -#define MXC_CCM_CGR1_UART3_OFFSET 24 -#define MXC_CCM_CGR1_UART3_MASK (0x3 << 24) -#define MXC_CCM_CGR1_UART4_OFFSET 26 -#define MXC_CCM_CGR1_UART4_MASK (0x3 << 26) -#define MXC_CCM_CGR1_UART5_OFFSET 28 -#define MXC_CCM_CGR1_UART5_MASK (0x3 << 28) -#define MXC_CCM_CGR1_OWIRE_OFFSET 30 -#define MXC_CCM_CGR1_OWIRE_MASK (0x3 << 30) - -#define MXC_CCM_CGR2_SSI2_OFFSET 0 -#define MXC_CCM_CGR2_SSI2_MASK (0x3 << 0) -#define MXC_CCM_CGR2_CSPI1_OFFSET 2 -#define MXC_CCM_CGR2_CSPI1_MASK (0x3 << 2) -#define MXC_CCM_CGR2_CSPI2_OFFSET 4 -#define MXC_CCM_CGR2_CSPI2_MASK (0x3 << 4) -#define MXC_CCM_CGR2_GACC_OFFSET 6 -#define MXC_CCM_CGR2_GACC_MASK (0x3 << 6) -#define MXC_CCM_CGR2_EMI_OFFSET 8 -#define MXC_CCM_CGR2_EMI_MASK (0x3 << 8) -#define MXC_CCM_CGR2_RTIC_OFFSET 10 -#define MXC_CCM_CGR2_RTIC_MASK (0x3 << 10) -#define MXC_CCM_CGR2_FIRI_OFFSET 12 -#define MXC_CCM_CGR2_FIRI_MASK (0x3 << 12) -#define MXC_CCM_CGR2_IPMUX1_OFFSET 14 -#define MXC_CCM_CGR2_IPMUX1_MASK (0x3 << 14) -#define MXC_CCM_CGR2_IPMUX2_OFFSET 16 -#define MXC_CCM_CGR2_IPMUX2_MASK (0x3 << 16) - -/* These new CGR2 bits are added in MX32 */ -#define MXC_CCM_CGR2_APMSYSCLKSEL_OFFSET 18 -#define MXC_CCM_CGR2_APMSYSCLKSEL_MASK (0x3 << 18) -#define MXC_CCM_CGR2_APMSSICLKSEL_OFFSET 20 -#define MXC_CCM_CGR2_APMSSICLKSEL_MASK (0x3 << 20) -#define MXC_CCM_CGR2_APMPERCLKSEL_OFFSET 22 -#define MXC_CCM_CGR2_APMPERCLKSEL_MASK (0x3 << 22) -#define MXC_CCM_CGR2_MXCCLKENSEL_OFFSET 24 -#define MXC_CCM_CGR2_MXCCLKENSEL_MASK (0x1 << 24) -#define MXC_CCM_CGR2_CHIKCAMPEN_OFFSET 25 -#define MXC_CCM_CGR2_CHIKCAMPEN_MASK (0x1 << 25) -#define MXC_CCM_CGR2_OVRVPUBUSY_OFFSET 26 -#define MXC_CCM_CGR2_OVRVPUBUSY_MASK (0x1 << 26) -#define MXC_CCM_CGR2_APMENA_OFFSET 30 -#define MXC_CCM_CGR2_AOMENA_MASK (0x1 << 30) - /* * LTR0 register offsets */ diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig index ed5ab8ed7cf..17d0e9906d5 100644 --- a/arch/arm/plat-mxc/Kconfig +++ b/arch/arm/plat-mxc/Kconfig @@ -22,6 +22,7 @@ config ARCH_MX2 config ARCH_MX3 bool "MX3-based" select CPU_V6 + select COMMON_CLKDEV help This enables support for systems based on the Freescale i.MX3 family diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c index ae50a9d1a4e..da781d10789 100644 --- a/drivers/dma/ipu/ipu_idmac.c +++ b/drivers/dma/ipu/ipu_idmac.c @@ -1649,7 +1649,7 @@ static int ipu_probe(struct platform_device *pdev) } /* Get IPU clock */ - ipu_data.ipu_clk = clk_get(&pdev->dev, "ipu_clk"); + ipu_data.ipu_clk = clk_get(&pdev->dev, NULL); if (IS_ERR(ipu_data.ipu_clk)) { ret = PTR_ERR(ipu_data.ipu_clk); goto err_clk_get; diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index 8a75d05f433..0c27961e47f 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c @@ -493,7 +493,7 @@ static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel, */ dev_dbg(mx3fb->dev, "pixel clk = %d\n", pixel_clk); - ipu_clk = clk_get(mx3fb->dev, "ipu_clk"); + ipu_clk = clk_get(mx3fb->dev, NULL); div = clk_get_rate(ipu_clk) * 16 / pixel_clk; clk_put(ipu_clk); -- GitLab From cc83e4096c6db1f13406c7dedf5516b4b5bcba55 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 19 Feb 2009 12:48:35 +0100 Subject: [PATCH 3298/4982] Use __force in IO_ADDRESS macro to silence sparse Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/include/mach/mx3x.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/plat-mxc/include/mach/mx3x.h b/arch/arm/plat-mxc/include/mach/mx3x.h index 83a172b51b0..3878c6085d5 100644 --- a/arch/arm/plat-mxc/include/mach/mx3x.h +++ b/arch/arm/plat-mxc/include/mach/mx3x.h @@ -157,7 +157,7 @@ * it returns 0xDEADBEEF */ #define IO_ADDRESS(x) \ - (void __iomem *) \ + (void __force __iomem *) \ (((x >= AIPS1_BASE_ADDR) && (x < (AIPS1_BASE_ADDR + AIPS1_SIZE))) ? AIPS1_IO_ADDRESS(x):\ ((x >= SPBA0_BASE_ADDR) && (x < (SPBA0_BASE_ADDR + SPBA0_SIZE))) ? SPBA0_IO_ADDRESS(x):\ ((x >= AIPS2_BASE_ADDR) && (x < (AIPS2_BASE_ADDR + AIPS2_SIZE))) ? AIPS2_IO_ADDRESS(x):\ -- GitLab From 06277b5c40be283779d55db16b50fc201a2ff8bb Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 23 Feb 2009 13:33:31 +0100 Subject: [PATCH 3299/4982] mxcmmc: Do not pass clock name, we have only one clock for this device Signed-off-by: Sascha Hauer --- drivers/mmc/host/mxcmmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index dda0be4e25d..776230df3df 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -707,7 +707,7 @@ static int mxcmci_probe(struct platform_device *pdev) host->res = r; host->irq = irq; - host->clk = clk_get(&pdev->dev, "sdhc_clk"); + host->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(host->clk)) { ret = PTR_ERR(host->clk); goto out_iounmap; -- GitLab From 9563b1dbb6aa48b685ce8d11d941ed7d3e71f6fc Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 23 Feb 2009 13:08:06 +0100 Subject: [PATCH 3300/4982] MX2/MX3 SDHC driver: rename platform driver Rename driver from imx-mmc to mxc-mmc to avoid conflicts with the mx1 mmc driver. Signed-off-by: Sascha Hauer --- drivers/mmc/host/mxcmmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 776230df3df..b4a615c55f2 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -42,7 +42,7 @@ #define HAS_DMA #endif -#define DRIVER_NAME "imx-mmc" +#define DRIVER_NAME "mxc-mmc" #define MMC_REG_STR_STP_CLK 0x00 #define MMC_REG_STATUS 0x04 -- GitLab From 1a02be0ee77b68aef67b656bc47f0fb4ab177e67 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 19 Dec 2008 14:32:07 +0100 Subject: [PATCH 3301/4982] MX2: Add SDHC platform_devices and resources Signed-of-by: Julien Boibessot Signed-off-by: Sascha Hauer --- arch/arm/mach-mx2/devices.c | 66 +++++++++++++++++++++++++++++++++++++ arch/arm/mach-mx2/devices.h | 2 ++ 2 files changed, 68 insertions(+) diff --git a/arch/arm/mach-mx2/devices.c b/arch/arm/mach-mx2/devices.c index 7d12c2c4108..f81aa8a8fbb 100644 --- a/arch/arm/mach-mx2/devices.c +++ b/arch/arm/mach-mx2/devices.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "devices.h" @@ -343,6 +344,71 @@ struct platform_device mxc_pwm_device = { .resource = mxc_pwm_resources }; +/* + * Resource definition for the MXC SDHC + */ +static struct resource mxc_sdhc1_resources[] = { + [0] = { + .start = SDHC1_BASE_ADDR, + .end = SDHC1_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_SDHC1, + .end = MXC_INT_SDHC1, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = DMA_REQ_SDHC1, + .end = DMA_REQ_SDHC1, + .flags = IORESOURCE_DMA + }, +}; + +static u64 mxc_sdhc1_dmamask = 0xffffffffUL; + +struct platform_device mxc_sdhc_device0 = { + .name = "mxc-mmc", + .id = 0, + .dev = { + .dma_mask = &mxc_sdhc1_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(mxc_sdhc1_resources), + .resource = mxc_sdhc1_resources, +}; + +static struct resource mxc_sdhc2_resources[] = { + [0] = { + .start = SDHC2_BASE_ADDR, + .end = SDHC2_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_SDHC2, + .end = MXC_INT_SDHC2, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = DMA_REQ_SDHC2, + .end = DMA_REQ_SDHC2, + .flags = IORESOURCE_DMA + }, +}; + +static u64 mxc_sdhc2_dmamask = 0xffffffffUL; + +struct platform_device mxc_sdhc_device1 = { + .name = "mxc-mmc", + .id = 1, + .dev = { + .dma_mask = &mxc_sdhc2_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(mxc_sdhc2_resources), + .resource = mxc_sdhc2_resources, +}; + /* GPIO port description */ static struct mxc_gpio_port imx_gpio_ports[] = { [0] = { diff --git a/arch/arm/mach-mx2/devices.h b/arch/arm/mach-mx2/devices.h index 271ab1e6982..049005bb6aa 100644 --- a/arch/arm/mach-mx2/devices.h +++ b/arch/arm/mach-mx2/devices.h @@ -18,3 +18,5 @@ extern struct platform_device mxc_fec_device; extern struct platform_device mxc_pwm_device; extern struct platform_device mxc_i2c_device0; extern struct platform_device mxc_i2c_device1; +extern struct platform_device mxc_sdhc_device0; +extern struct platform_device mxc_sdhc_device1; -- GitLab From 2adc1d654e41f4308193fdd46cee885b7a35c149 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 19 Dec 2008 14:32:06 +0100 Subject: [PATCH 3302/4982] MX31: Add sdhc resources/platform devices Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/devices.c | 40 +++++++++++++++++++++++++++++++++++++ arch/arm/mach-mx3/devices.h | 2 ++ 2 files changed, 42 insertions(+) diff --git a/arch/arm/mach-mx3/devices.c b/arch/arm/mach-mx3/devices.c index ab090602cea..380be0c9b21 100644 --- a/arch/arm/mach-mx3/devices.c +++ b/arch/arm/mach-mx3/devices.c @@ -245,6 +245,46 @@ struct platform_device mxc_i2c_device2 = { .resource = mxc_i2c2_resources, }; +#ifdef CONFIG_ARCH_MX31 +static struct resource mxcsdhc0_resources[] = { + { + .start = MMC_SDHC1_BASE_ADDR, + .end = MMC_SDHC1_BASE_ADDR + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = MXC_INT_MMC_SDHC1, + .end = MXC_INT_MMC_SDHC1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource mxcsdhc1_resources[] = { + { + .start = MMC_SDHC2_BASE_ADDR, + .end = MMC_SDHC2_BASE_ADDR + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = MXC_INT_MMC_SDHC2, + .end = MXC_INT_MMC_SDHC2, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxcsdhc_device0 = { + .name = "mxc-mmc", + .id = 0, + .num_resources = ARRAY_SIZE(mxcsdhc0_resources), + .resource = mxcsdhc0_resources, +}; + +struct platform_device mxcsdhc_device1 = { + .name = "mxc-mmc", + .id = 1, + .num_resources = ARRAY_SIZE(mxcsdhc1_resources), + .resource = mxcsdhc1_resources, +}; +#endif /* CONFIG_ARCH_MX31 */ + /* i.MX31 Image Processing Unit */ /* The resource order is important! */ diff --git a/arch/arm/mach-mx3/devices.h b/arch/arm/mach-mx3/devices.h index 4faac6552e0..88c04b296fa 100644 --- a/arch/arm/mach-mx3/devices.h +++ b/arch/arm/mach-mx3/devices.h @@ -12,3 +12,5 @@ extern struct platform_device mxc_i2c_device2; extern struct platform_device mx3_ipu; extern struct platform_device mx3_fb; extern struct platform_device mxc_fec_device; +extern struct platform_device mxcsdhc_device0; +extern struct platform_device mxcsdhc_device1; -- GitLab From f2cb641f565dccebfa934b1a940bc6517734d391 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 11 Nov 2008 15:03:28 +0100 Subject: [PATCH 3303/4982] pcm037: Add sdhc support Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/pcm037.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/arch/arm/mach-mx3/pcm037.c b/arch/arm/mach-mx3/pcm037.c index 7743c13beba..5fce022114d 100644 --- a/arch/arm/mach-mx3/pcm037.c +++ b/arch/arm/mach-mx3/pcm037.c @@ -39,6 +39,7 @@ #include #include #include +#include #ifdef CONFIG_I2C_IMX #include #endif @@ -162,6 +163,32 @@ static struct i2c_board_info pcm037_i2c_devices[] = { }; #endif +static int sdhc1_pins[] = { + MX31_PIN_SD1_DATA3__SD1_DATA3, + MX31_PIN_SD1_DATA2__SD1_DATA2, + MX31_PIN_SD1_DATA1__SD1_DATA1, + MX31_PIN_SD1_DATA0__SD1_DATA0, + MX31_PIN_SD1_CLK__SD1_CLK, + MX31_PIN_SD1_CMD__SD1_CMD, +}; + +static int pcm970_sdhc1_init(struct device *dev, irq_handler_t h, void *data) +{ + return mxc_iomux_setup_multiple_pins(sdhc1_pins, ARRAY_SIZE(sdhc1_pins), + "sdhc-1"); +} + +static void pcm970_sdhc1_exit(struct device *dev, void *data) +{ + mxc_iomux_release_multiple_pins(sdhc1_pins, ARRAY_SIZE(sdhc1_pins)); +} + +/* No card and rw detection at the moment */ +static struct imxmmc_platform_data sdhc_pdata = { + .init = pcm970_sdhc1_init, + .exit = pcm970_sdhc1_exit, +}; + static struct platform_device *devices[] __initdata = { &pcm037_flash, &pcm037_eth, @@ -208,6 +235,7 @@ static void __init mxc_board_init(void) mxc_register_device(&mxc_i2c_device1, &pcm037_i2c_1_data); #endif mxc_register_device(&mxc_nand_device, &pcm037_nand_board_info); + mxc_register_device(&mxcsdhc_device0, &sdhc_pdata); } static void __init pcm037_timer_init(void) -- GitLab From 7c107dcb652c2101426adfc3193140db95b44594 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 19 Dec 2008 14:32:07 +0100 Subject: [PATCH 3304/4982] pcm970 baseboard: Add SDHC support Signed-off-by: Sascha Hauer --- arch/arm/mach-mx2/pcm970-baseboard.c | 63 ++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/arch/arm/mach-mx2/pcm970-baseboard.c b/arch/arm/mach-mx2/pcm970-baseboard.c index 232e0416f15..bf4e520bc1b 100644 --- a/arch/arm/mach-mx2/pcm970-baseboard.c +++ b/arch/arm/mach-mx2/pcm970-baseboard.c @@ -17,16 +17,78 @@ */ #include +#include +#include #include #include #include +#include #include #include #include "devices.h" +static int pcm970_sdhc2_get_ro(struct device *dev) +{ + return gpio_get_value(GPIO_PORTC + 28); +} + +static int pcm970_sdhc2_pins[] = { + PB4_PF_SD2_D0, + PB5_PF_SD2_D1, + PB6_PF_SD2_D2, + PB7_PF_SD2_D3, + PB8_PF_SD2_CMD, + PB9_PF_SD2_CLK, +}; + +static int pcm970_sdhc2_init(struct device *dev, irq_handler_t detect_irq, void *data) +{ + int ret; + + ret = mxc_gpio_setup_multiple_pins(pcm970_sdhc2_pins, + ARRAY_SIZE(pcm970_sdhc2_pins), "sdhc2"); + if(ret) + return ret; + + ret = request_irq(IRQ_GPIOC(29), detect_irq, 0, + "imx-mmc-detect", data); + if (ret) + goto out_release_gpio; + + set_irq_type(IRQ_GPIOC(29), IRQF_TRIGGER_FALLING); + + ret = gpio_request(GPIO_PORTC + 28, "imx-mmc-ro"); + if (ret) + goto out_release_gpio; + + mxc_gpio_mode((GPIO_PORTC | 28) | GPIO_GPIO | GPIO_IN); + gpio_direction_input(GPIO_PORTC + 28); + + return 0; + +out_release_gpio: + mxc_gpio_release_multiple_pins(pcm970_sdhc2_pins, + ARRAY_SIZE(pcm970_sdhc2_pins)); + return ret; +} + +static void pcm970_sdhc2_exit(struct device *dev, void *data) +{ + free_irq(IRQ_GPIOC(29), data); + gpio_free(GPIO_PORTC + 28); + mxc_gpio_release_multiple_pins(pcm970_sdhc2_pins, + ARRAY_SIZE(pcm970_sdhc2_pins)); +} + +static struct imxmmc_platform_data sdhc_pdata = { + .get_ro = pcm970_sdhc2_get_ro, + .init = pcm970_sdhc2_init, + .exit = pcm970_sdhc2_exit, +}; + static int mxc_fb_pins[] = { PA5_PF_LSCLK, PA6_PF_LD0, PA7_PF_LD1, PA8_PF_LD2, PA9_PF_LD3, PA10_PF_LD4, PA11_PF_LD5, PA12_PF_LD6, @@ -96,4 +158,5 @@ static struct imx_fb_platform_data pcm038_fb_data = { void __init pcm970_baseboard_init(void) { mxc_register_device(&mxc_fb_device, &pcm038_fb_data); + mxc_register_device(&mxc_sdhc_device1, &sdhc_pdata); } -- GitLab From 148854c65ea8046b045672fd49f4333aefaa3ab5 Mon Sep 17 00:00:00 2001 From: Ilya Yanok Date: Wed, 11 Mar 2009 03:22:00 +0300 Subject: [PATCH 3305/4982] qong: basic support for Dave/DENX QongEVB-LITE board This patch adds basic support for Dave/DENX QongEVB-LITE i.MX31-based board. It includes support for clocks initialization, UART1, NOR-flash, FPGA-attached NAND flash and DNET ethernet controller (inside FPGA). Signed-off-by: Ilya Yanok Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/Kconfig | 8 + arch/arm/mach-mx3/Makefile | 1 + arch/arm/mach-mx3/qong.c | 312 +++++++++++++++++++ arch/arm/plat-mxc/include/mach/board-qong.h | 22 ++ arch/arm/plat-mxc/include/mach/debug-macro.S | 3 + 5 files changed, 346 insertions(+) create mode 100644 arch/arm/mach-mx3/qong.c create mode 100644 arch/arm/plat-mxc/include/mach/board-qong.h diff --git a/arch/arm/mach-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig index 7c939c69d6d..d6235583e97 100644 --- a/arch/arm/mach-mx3/Kconfig +++ b/arch/arm/mach-mx3/Kconfig @@ -56,4 +56,12 @@ config MACH_MX31MOBOARD Include support for mx31moboard platform. This includes specific configurations for the board and its peripherals. +config MACH_QONG + bool "Support Dave/DENX QongEVB-LITE platform" + select ARCH_MX31 + default n + help + Include support for Dave/DENX QongEVB-LITE platform. This includes + specific configurations for the board and its peripherals. + endif diff --git a/arch/arm/mach-mx3/Makefile b/arch/arm/mach-mx3/Makefile index ab0bec0a4d9..272c8a953b3 100644 --- a/arch/arm/mach-mx3/Makefile +++ b/arch/arm/mach-mx3/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_MACH_PCM037) += pcm037.o obj-$(CONFIG_MACH_MX31_3DS) += mx31pdk.o obj-$(CONFIG_MACH_MX31MOBOARD) += mx31moboard.o mx31moboard-devboard.o \ mx31moboard-marxbot.o +obj-$(CONFIG_MACH_QONG) += qong.o diff --git a/arch/arm/mach-mx3/qong.c b/arch/arm/mach-mx3/qong.c new file mode 100644 index 00000000000..6c4283cec6f --- /dev/null +++ b/arch/arm/mach-mx3/qong.c @@ -0,0 +1,312 @@ +/* + * Copyright (C) 2009 Ilya Yanok, Emcraft Systems Ltd, + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "devices.h" + +/* FPGA defines */ +#define QONG_FPGA_VERSION(major, minor, rev) \ + (((major & 0xF) << 12) | ((minor & 0xF) << 8) | (rev & 0xFF)) + +#define QONG_FPGA_BASEADDR CS1_BASE_ADDR +#define QONG_FPGA_PERIPH_SIZE (1 << 24) + +#define QONG_FPGA_CTRL_BASEADDR QONG_FPGA_BASEADDR +#define QONG_FPGA_CTRL_SIZE 0x10 +/* FPGA control registers */ +#define QONG_FPGA_CTRL_VERSION 0x00 + +#define QONG_DNET_ID 1 +#define QONG_DNET_BASEADDR \ + (QONG_FPGA_BASEADDR + QONG_DNET_ID * QONG_FPGA_PERIPH_SIZE) +#define QONG_DNET_SIZE 0x00001000 + +#define QONG_FPGA_IRQ IOMUX_TO_IRQ(MX31_PIN_DTR_DCE1) + +/* + * This file contains the board-specific initialization routines. + */ + +static struct imxuart_platform_data uart_pdata = { + .flags = IMXUART_HAVE_RTSCTS, +}; + +static int uart_pins[] = { + MX31_PIN_CTS1__CTS1, + MX31_PIN_RTS1__RTS1, + MX31_PIN_TXD1__TXD1, + MX31_PIN_RXD1__RXD1 +}; + +static inline void mxc_init_imx_uart(void) +{ + mxc_iomux_setup_multiple_pins(uart_pins, ARRAY_SIZE(uart_pins), + "uart-0"); + mxc_register_device(&mxc_uart_device0, &uart_pdata); +} + +static struct resource dnet_resources[] = { + [0] = { + .name = "dnet-memory", + .start = QONG_DNET_BASEADDR, + .end = QONG_DNET_BASEADDR + QONG_DNET_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = QONG_FPGA_IRQ, + .end = QONG_FPGA_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device dnet_device = { + .name = "dnet", + .id = -1, + .num_resources = ARRAY_SIZE(dnet_resources), + .resource = dnet_resources, +}; + +static int __init qong_init_dnet(void) +{ + int ret; + + ret = platform_device_register(&dnet_device); + return ret; +} + +/* MTD NOR flash */ + +static struct physmap_flash_data qong_flash_data = { + .width = 2, +}; + +static struct resource qong_flash_resource = { + .start = CS0_BASE_ADDR, + .end = CS0_BASE_ADDR + QONG_NOR_SIZE - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device qong_nor_mtd_device = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &qong_flash_data, + }, + .resource = &qong_flash_resource, + .num_resources = 1, +}; + +static void qong_init_nor_mtd(void) +{ + (void)platform_device_register(&qong_nor_mtd_device); +} + +/* + * Hardware specific access to control-lines + */ +static void qong_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{ + struct nand_chip *nand_chip = mtd->priv; + + if (cmd == NAND_CMD_NONE) + return; + + if (ctrl & NAND_CLE) + writeb(cmd, nand_chip->IO_ADDR_W + (1 << 24)); + else + writeb(cmd, nand_chip->IO_ADDR_W + (1 << 23)); +} + +/* + * Read the Device Ready pin. + */ +static int qong_nand_device_ready(struct mtd_info *mtd) +{ + return gpio_get_value(IOMUX_TO_GPIO(MX31_PIN_NFRB)); +} + +static void qong_nand_select_chip(struct mtd_info *mtd, int chip) +{ + if (chip >= 0) + gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), 0); + else + gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), 1); +} + +static struct platform_nand_data qong_nand_data = { + .chip = { + .chip_delay = 20, + .options = 0, + }, + .ctrl = { + .cmd_ctrl = qong_nand_cmd_ctrl, + .dev_ready = qong_nand_device_ready, + .select_chip = qong_nand_select_chip, + } +}; + +static struct resource qong_nand_resource = { + .start = CS3_BASE_ADDR, + .end = CS3_BASE_ADDR + SZ_32M - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device qong_nand_device = { + .name = "gen_nand", + .id = -1, + .dev = { + .platform_data = &qong_nand_data, + }, + .num_resources = 1, + .resource = &qong_nand_resource, +}; + +static void __init qong_init_nand_mtd(void) +{ + /* init CS */ + __raw_writel(0x00004f00, CSCR_U(3)); + __raw_writel(0x20013b31, CSCR_L(3)); + __raw_writel(0x00020800, CSCR_A(3)); + mxc_iomux_set_gpr(MUX_SDCTL_CSD1_SEL, true); + + /* enable pin */ + mxc_iomux_mode(IOMUX_MODE(MX31_PIN_NFCE_B, IOMUX_CONFIG_GPIO)); + if (!gpio_request(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), "nand_enable")) + gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), 0); + + /* ready/busy pin */ + mxc_iomux_mode(IOMUX_MODE(MX31_PIN_NFRB, IOMUX_CONFIG_GPIO)); + if (!gpio_request(IOMUX_TO_GPIO(MX31_PIN_NFRB), "nand_rdy")) + gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_NFRB)); + + /* write protect pin */ + mxc_iomux_mode(IOMUX_MODE(MX31_PIN_NFWP_B, IOMUX_CONFIG_GPIO)); + if (!gpio_request(IOMUX_TO_GPIO(MX31_PIN_NFWP_B), "nand_wp")) + gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_NFWP_B)); + + platform_device_register(&qong_nand_device); +} + +static void __init qong_init_fpga(void) +{ + void __iomem *regs; + u32 fpga_ver; + + regs = ioremap(QONG_FPGA_CTRL_BASEADDR, QONG_FPGA_CTRL_SIZE); + if (!regs) { + printk(KERN_ERR "%s: failed to map registers, aborting.\n", + __func__); + return; + } + + fpga_ver = readl(regs + QONG_FPGA_CTRL_VERSION); + iounmap(regs); + printk(KERN_INFO "Qong FPGA version %d.%d.%d\n", + (fpga_ver & 0xF000) >> 12, + (fpga_ver & 0x0F00) >> 8, fpga_ver & 0x00FF); + if (fpga_ver < QONG_FPGA_VERSION(0, 8, 7)) { + printk(KERN_ERR "qong: Unexpected FPGA version, FPGA-based " + "devices won't be registered!\n"); + return; + } + + /* register FPGA-based devices */ + qong_init_nand_mtd(); + qong_init_dnet(); +} + +/* + * This structure defines the MX31 memory map. + */ +static struct map_desc qong_io_desc[] __initdata = { + { + .virtual = AIPS1_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(AIPS1_BASE_ADDR), + .length = AIPS1_SIZE, + .type = MT_DEVICE_NONSHARED + }, { + .virtual = AIPS2_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(AIPS2_BASE_ADDR), + .length = AIPS2_SIZE, + .type = MT_DEVICE_NONSHARED + } +}; + +/* + * Set up static virtual mappings. + */ +static void __init qong_map_io(void) +{ + mxc_map_io(); + iotable_init(qong_io_desc, ARRAY_SIZE(qong_io_desc)); +} + +/* + * Board specific initialization. + */ +static void __init mxc_board_init(void) +{ + mxc_init_imx_uart(); + qong_init_nor_mtd(); + qong_init_fpga(); +} + +static void __init qong_timer_init(void) +{ + mx31_clocks_init(26000000); +} + +static struct sys_timer qong_timer = { + .init = qong_timer_init, +}; + +/* + * The following uses standard kernel macros defined in arch.h in order to + * initialize __mach_desc_QONG data structure. + */ + +MACHINE_START(QONG, "Dave/DENX QongEVB-LITE") + /* Maintainer: DENX Software Engineering GmbH */ + .phys_io = AIPS1_BASE_ADDR, + .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc, + .boot_params = PHYS_OFFSET + 0x100, + .map_io = qong_map_io, + .init_irq = mxc_init_irq, + .init_machine = mxc_board_init, + .timer = &qong_timer, +MACHINE_END diff --git a/arch/arm/plat-mxc/include/mach/board-qong.h b/arch/arm/plat-mxc/include/mach/board-qong.h new file mode 100644 index 00000000000..4ff762dd45c --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/board-qong.h @@ -0,0 +1,22 @@ +/* + * Copyright 2009 Ilya Yanok, Emcraft Systems Ltd, + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_ARCH_MXC_BOARD_QONG_H__ +#define __ASM_ARCH_MXC_BOARD_QONG_H__ + +/* mandatory for CONFIG_LL_DEBUG */ + +#define MXC_LL_UART_PADDR UART1_BASE_ADDR +#define MXC_LL_UART_VADDR AIPS1_IO_ADDRESS(UART1_BASE_ADDR) + +/* NOR FLASH */ +#define QONG_NOR_SIZE (128*1024*1024) + +#endif /* __ASM_ARCH_MXC_BOARD_QONG_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/debug-macro.S b/arch/arm/plat-mxc/include/mach/debug-macro.S index 602768b427e..4f773148bc2 100644 --- a/arch/arm/plat-mxc/include/mach/debug-macro.S +++ b/arch/arm/plat-mxc/include/mach/debug-macro.S @@ -30,6 +30,9 @@ #endif #ifdef CONFIG_MACH_MX31_3DS #include +#endif +#ifdef CONFIG_MACH_QONG +#include #endif .macro addruart,rx mrc p15, 0, \rx, c1, c0 -- GitLab From 77dd7e17b86bd81b3638e01d784a72652071508b Mon Sep 17 00:00:00 2001 From: "Lopez Cruz, Misael" Date: Thu, 12 Mar 2009 21:45:27 -0500 Subject: [PATCH 3306/4982] ASoC: Move headset jack registration to device initialization for SDP3430 Move headset jack registration to the codec/machine specific initialization. Having the jack registration in machine init causes that the jack device gets initialized but not registered since the sound card is registered before the jack. Moving jack registration to device initialization will register the jack device along with all other devices associated to the card when the card is registed. As a consequence of jack device registered properly, the jack is detected as an input device. Signed-off-by: Misael Lopez Cruz Signed-off-by: Mark Brown --- sound/soc/omap/sdp3430.c | 74 +++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c index 715c648203a..0a41de677e7 100644 --- a/sound/soc/omap/sdp3430.c +++ b/sound/soc/omap/sdp3430.c @@ -39,6 +39,8 @@ #include "omap-pcm.h" #include "../codecs/twl4030.h" +static struct snd_soc_card snd_soc_sdp3430; + static int sdp3430_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -82,6 +84,27 @@ static struct snd_soc_ops sdp3430_ops = { .hw_params = sdp3430_hw_params, }; +/* Headset jack */ +static struct snd_soc_jack hs_jack; + +/* Headset jack detection DAPM pins */ +static struct snd_soc_jack_pin hs_jack_pins[] = { + { + .pin = "Headset Jack", + .mask = SND_JACK_HEADSET, + }, +}; + +/* Headset jack detection gpios */ +static struct snd_soc_jack_gpio hs_jack_gpios[] = { + { + .gpio = (OMAP_MAX_GPIO_LINES + 2), + .name = "hsdet-gpio", + .report = SND_JACK_HEADSET, + .debounce_time = 200, + }, +}; + /* SDP3430 machine DAPM */ static const struct snd_soc_dapm_widget sdp3430_twl4030_dapm_widgets[] = { SND_SOC_DAPM_MIC("Ext Mic", NULL), @@ -141,30 +164,25 @@ static int sdp3430_twl4030_init(struct snd_soc_codec *codec) snd_soc_dapm_nc_pin(codec, "CARKITR"); ret = snd_soc_dapm_sync(codec); + if (ret) + return ret; - return ret; -} + /* Headset jack detection */ + ret = snd_soc_jack_new(&snd_soc_sdp3430, "Headset Jack", + SND_JACK_HEADSET, &hs_jack); + if (ret) + return ret; -/* Headset jack */ -static struct snd_soc_jack hs_jack; + ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins), + hs_jack_pins); + if (ret) + return ret; -/* Headset jack detection DAPM pins */ -static struct snd_soc_jack_pin hs_jack_pins[] = { - { - .pin = "Headset Jack", - .mask = SND_JACK_HEADSET, - }, -}; + ret = snd_soc_jack_add_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios), + hs_jack_gpios); -/* Headset jack detection gpios */ -static struct snd_soc_jack_gpio hs_jack_gpios[] = { - { - .gpio = (OMAP_MAX_GPIO_LINES + 2), - .name = "hsdet-gpio", - .report = SND_JACK_HEADSET, - .debounce_time = 200, - }, -}; + return ret; +} /* Digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link sdp3430_dai = { @@ -216,21 +234,7 @@ static int __init sdp3430_soc_init(void) if (ret) goto err1; - /* Headset jack detection */ - ret = snd_soc_jack_new(&snd_soc_sdp3430, "SDP3430 headset jack", - SND_JACK_HEADSET, &hs_jack); - if (ret) - return ret; - - ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins), - hs_jack_pins); - if (ret) - return ret; - - ret = snd_soc_jack_add_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios), - hs_jack_gpios); - - return ret; + return 0; err1: printk(KERN_ERR "Unable to add platform device\n"); -- GitLab From 72d7466468b471f99cefae3c5f4a414bbbaa0bdd Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Thu, 12 Mar 2009 11:27:49 +0100 Subject: [PATCH 3307/4982] ASoC: switch PXA SSP driver from network mode to PSP This switches the pxa ssp port usage from network mode to PSP mode. Removed some comments and checks for configured TDM channels. A special case is added to support configuration where BCLK = 64fs. We need to do some black magic in this case which doesn't look nice but there is unfortunately no other option than that. Diagnosed-by: Tim Ruetz Signed-off-by: Daniel Mack Signed-off-by: Mark Brown --- sound/soc/pxa/pxa-ssp.c | 44 ++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index d3fa6357a9f..4dd0d7c5722 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -558,18 +558,17 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: - sscr0 |= SSCR0_MOD | SSCR0_PSP; + sscr0 |= SSCR0_PSP; sscr1 |= SSCR1_RWOT | SSCR1_TRAIL; switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: - sspsp |= SSPSP_FSRT; break; case SND_SOC_DAIFMT_NB_IF: - sspsp |= SSPSP_SFRMP | SSPSP_FSRT; + sspsp |= SSPSP_SFRMP; break; case SND_SOC_DAIFMT_IB_IF: - sspsp |= SSPSP_SFRMP; + sspsp |= SSPSP_SFRMP | SSPSP_SCMODE(3); break; default: return -EINVAL; @@ -655,33 +654,56 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, sscr0 |= SSCR0_FPCKE; #endif sscr0 |= SSCR0_DataSize(16); - /* use network mode (2 slots) for 16 bit stereo */ break; case SNDRV_PCM_FORMAT_S24_LE: sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(8)); - /* we must be in network mode (2 slots) for 24 bit stereo */ break; case SNDRV_PCM_FORMAT_S32_LE: sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(16)); - /* we must be in network mode (2 slots) for 32 bit stereo */ break; } ssp_write_reg(ssp, SSCR0, sscr0); switch (priv->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: - /* Cleared when the DAI format is set */ - sspsp = ssp_read_reg(ssp, SSPSP) | SSPSP_SFRMWDTH(width); + sspsp = ssp_read_reg(ssp, SSPSP); + + if (((sscr0 & SSCR0_SCR) == SSCR0_SerClkDiv(4)) && + (width == 16)) { + /* This is a special case where the bitclk is 64fs + * and we're not dealing with 2*32 bits of audio + * samples. + * + * The SSP values used for that are all found out by + * trying and failing a lot; some of the registers + * needed for that mode are only available on PXA3xx. + */ + +#ifdef CONFIG_PXA3xx + if (!cpu_is_pxa3xx()) + return -EINVAL; + + sspsp |= SSPSP_SFRMWDTH(width * 2); + sspsp |= SSPSP_SFRMDLY(width * 4); + sspsp |= SSPSP_EDMYSTOP(3); + sspsp |= SSPSP_DMYSTOP(3); + sspsp |= SSPSP_DMYSTRT(1); +#else + return -EINVAL; +#endif + } else + sspsp |= SSPSP_SFRMWDTH(width); + ssp_write_reg(ssp, SSPSP, sspsp); break; default: break; } - /* We always use a network mode so we always require TDM slots + /* When we use a network mode, we always require TDM slots * - complain loudly and fail if they've not been set up yet. */ - if (!(ssp_read_reg(ssp, SSTSA) & 0xf)) { + if ((sscr0 & SSCR0_MOD) && !(ssp_read_reg(ssp, SSTSA) & 0xf)) { dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n"); return -EINVAL; } -- GitLab From 3dd3d46b78c22503957230ca5981849b7bb29b9a Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 9 Mar 2009 21:48:32 +0100 Subject: [PATCH 3308/4982] genirq: remove unused hw_irq_controller typedef hw_irq_controller is unused. Remove the typedef Impact: cleanup Signed-off-by: Thomas Gleixner --- include/linux/irq.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/irq.h b/include/linux/irq.h index 737eafbc1f3..7c07a09931d 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -226,7 +226,6 @@ irq_remap_to_desc(unsigned int irq, struct irq_desc *desc) * Migration helpers for obsolete names, they will go away: */ #define hw_interrupt_type irq_chip -typedef struct irq_chip hw_irq_controller; #define no_irq_type no_irq_chip typedef struct irq_desc irq_desc_t; -- GitLab From c8e2aeef0b8ac9fb8821b8b3734c031579d0b77a Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 9 Mar 2009 20:26:23 +0100 Subject: [PATCH 3309/4982] genirq: remove redundant if condition Impact: cleanup The code is only compiled if CONFIG_GENERIC_HARDIRQS=y so another check for this define in the code is redundant. Remove it. Signed-off-by: Thomas Gleixner --- kernel/irq/manage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index e28db0f656a..4600f877c29 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -15,7 +15,7 @@ #include "internals.h" -#if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_HARDIRQS) +#ifdef CONFIG_SMP cpumask_var_t irq_default_affinity; /** -- GitLab From bedd30d986a05e32dc3eab874e4b9ed8a38058bb Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 30 Sep 2008 23:14:27 +0200 Subject: [PATCH 3310/4982] genirq: make irqreturn_t an enum Impact: cleanup Remove the 2.4 compabiliy cruft Signed-off-by: Thomas Gleixner Reviewed-by: Peter Zijlstra --- include/linux/irq.h | 4 ++-- include/linux/irqreturn.h | 28 ++++++++++------------------ 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/include/linux/irq.h b/include/linux/irq.h index 7c07a09931d..19770923bcb 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -280,7 +280,7 @@ static inline int irq_balancing_disabled(unsigned int irq) } /* Handle irq action chains: */ -extern int handle_IRQ_event(unsigned int irq, struct irqaction *action); +extern irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action); /* * Built-in IRQ handlers for various IRQ types, @@ -325,7 +325,7 @@ static inline void generic_handle_irq(unsigned int irq) /* Handling of unhandled and spurious interrupts: */ extern void note_interrupt(unsigned int irq, struct irq_desc *desc, - int action_ret); + irqreturn_t action_ret); /* Resending of interrupts :*/ void check_irq_resend(struct irq_desc *desc, unsigned int irq); diff --git a/include/linux/irqreturn.h b/include/linux/irqreturn.h index 881883c2009..c5584ca5b8c 100644 --- a/include/linux/irqreturn.h +++ b/include/linux/irqreturn.h @@ -1,25 +1,17 @@ -/* irqreturn.h */ #ifndef _LINUX_IRQRETURN_H #define _LINUX_IRQRETURN_H -/* - * For 2.4.x compatibility, 2.4.x can use - * - * typedef void irqreturn_t; - * #define IRQ_NONE - * #define IRQ_HANDLED - * #define IRQ_RETVAL(x) - * - * To mix old-style and new-style irq handler returns. - * - * IRQ_NONE means we didn't handle it. - * IRQ_HANDLED means that we did have a valid interrupt and handled it. - * IRQ_RETVAL(x) selects on the two depending on x being non-zero (for handled) +/** + * enum irqreturn + * @IRQ_NONE interrupt was not from this device + * @IRQ_HANDLED interrupt was handled by this device */ -typedef int irqreturn_t; +enum irqreturn { + IRQ_NONE, + IRQ_HANDLED, +}; -#define IRQ_NONE (0) -#define IRQ_HANDLED (1) -#define IRQ_RETVAL(x) ((x) != 0) +typedef enum irqreturn irqreturn_t; +#define IRQ_RETVAL(x) ((x) != IRQ_NONE) #endif -- GitLab From 4553573277906901f62f73c0432b332c53de5e2c Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sun, 22 Feb 2009 23:00:32 +0100 Subject: [PATCH 3311/4982] genirq: use kzalloc instead of explicit zero initialization Impact: simplification Signed-off-by: Thomas Gleixner Reviewed-by: Peter Zijlstra --- kernel/irq/manage.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 4600f877c29..8a22039a90b 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -737,15 +737,13 @@ int request_irq(unsigned int irq, irq_handler_t handler, if (!handler) return -EINVAL; - action = kmalloc(sizeof(struct irqaction), GFP_KERNEL); + action = kzalloc(sizeof(struct irqaction), GFP_KERNEL); if (!action) return -ENOMEM; action->handler = handler; action->flags = irqflags; - cpus_clear(action->mask); action->name = devname; - action->next = NULL; action->dev_id = dev_id; retval = __setup_irq(irq, desc, action); -- GitLab From a9d0a1a38352c4fb8946e73b3e42ba4ada29e733 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 3 Mar 2009 16:58:16 +0100 Subject: [PATCH 3312/4982] genirq: add doc to struct irqaction Impact: documentation struct irqaction is not documented. Add kernel doc comments and add interrupt.h to the genirq docbook. Signed-off-by: Thomas Gleixner --- Documentation/DocBook/genericirq.tmpl | 1 + include/linux/interrupt.h | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/Documentation/DocBook/genericirq.tmpl b/Documentation/DocBook/genericirq.tmpl index 3a882d9a90a..c671a016809 100644 --- a/Documentation/DocBook/genericirq.tmpl +++ b/Documentation/DocBook/genericirq.tmpl @@ -440,6 +440,7 @@ desc->chip->end(); used in the generic IRQ layer. !Iinclude/linux/irq.h +!Iinclude/linux/interrupt.h diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 468e3a25a4a..91658d07659 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -61,6 +61,17 @@ typedef irqreturn_t (*irq_handler_t)(int, void *); +/** + * struct irqaction - per interrupt action descriptor + * @handler: interrupt handler function + * @flags: flags (see IRQF_* above) + * @mask: no comment as it is useless and about to be removed + * @name: name of the device + * @dev_id: cookie to identify the device + * @next: pointer to the next irqaction for shared interrupts + * @irq: interrupt number + * @dir: pointer to the proc/irq/NN/name entry + */ struct irqaction { irq_handler_t handler; unsigned long flags; -- GitLab From 0e57aa11abb15b70db53d1f95ae70b3c980ac885 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 13 Mar 2009 14:34:05 +0100 Subject: [PATCH 3313/4982] genirq: deprecate __do_IRQ Two years migration time is enough. Remove the compability cruft. Add the deprecated warning in kernel/irq/handle.c because marking __do_IRQ itself is way too noisy. Signed-off-by: Thomas Gleixner --- Documentation/feature-removal-schedule.txt | 8 ++++++++ kernel/irq/handle.c | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 20d3b94703a..63b4550411b 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -344,3 +344,11 @@ Why: See commits 129f8ae9b1b5be94517da76009ea956e89104ce8 and Removal is subject to fixing any remaining bugs in ACPI which may cause the thermal throttling not to happen at the right time. Who: Dave Jones , Matthew Garrett + +----------------------------- + +What: __do_IRQ all in one fits nothing interrupt handler +When: 2.6.32 +Why: __do_IRQ was kept for easy migration to the type flow handlers. + More than two years of migration time is enough. +Who: Thomas Gleixner diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index a2ee682bca2..6661704140c 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -349,6 +349,11 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action) } #ifndef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ + +#ifdef CONFIG_ENABLE_WARN_DEPRECATED +# warning __do_IRQ is deprecated. Please convert to proper flow handlers +#endif + /** * __do_IRQ - original all in one highlevel IRQ handler * @irq: the interrupt number -- GitLab From cb065c06b6cc615a58860d619d7fa7952cd6a18b Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 13 Mar 2009 14:40:27 +0100 Subject: [PATCH 3314/4982] genirq: deprecate obsolete typedefs and defines More than two years is enough migration time. Remove the compability cruft. Signed-off-by: Thomas Gleixner --- Documentation/feature-removal-schedule.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 63b4550411b..9aa1dda5d38 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -352,3 +352,12 @@ When: 2.6.32 Why: __do_IRQ was kept for easy migration to the type flow handlers. More than two years of migration time is enough. Who: Thomas Gleixner + +----------------------------- + +What: obsolete generic irq defines and typedefs +When: 2.6.30 +Why: The defines and typedefs (hw_interrupt_type, no_irq_type, irq_desc_t) + have been kept around for migration reasons. After more than two years + it's time to remove them finally +Who: Thomas Gleixner -- GitLab From 58d8395b74f78a2f4225c5faea8b5bffb8af1cf9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 13 Mar 2009 17:04:34 +0100 Subject: [PATCH 3315/4982] ALSA: hda - Add another HP model with IDT92HD71bx codec HP laptops require GPIO0 on as EAPD. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index e06fc7decd3..4da72403fc8 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1855,6 +1855,8 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { "DFI LanParty", STAC_92HD71BXX_REF), SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, "DFI LanParty", STAC_92HD71BXX_REF), + SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3080, + "HP", STAC_HP_DV5), SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x30f0, "HP dv4-7", STAC_HP_DV5), SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3600, -- GitLab From d284e4f71dd42826fb60df33846ba310310c6c51 Mon Sep 17 00:00:00 2001 From: Sigmund Augdal Date: Mon, 26 Jan 2009 19:08:48 -0300 Subject: [PATCH 3316/4982] V4L/DVB (10974): Use Diseqc 3/3 mode to send data Signed-off-by: Sigmund Augdal Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stb0899_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/stb0899_drv.c b/drivers/media/dvb/frontends/stb0899_drv.c index 10613acf18f..a04c782fff8 100644 --- a/drivers/media/dvb/frontends/stb0899_drv.c +++ b/drivers/media/dvb/frontends/stb0899_drv.c @@ -794,7 +794,7 @@ static int stb0899_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t reg = stb0899_read_reg(state, STB0899_DISCNTRL1); old_state = reg; /* set to burst mode */ - STB0899_SETFIELD_VAL(DISEQCMODE, reg, 0x02); + STB0899_SETFIELD_VAL(DISEQCMODE, reg, 0x03); STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0x01); stb0899_write_reg(state, STB0899_DISCNTRL1, reg); switch (burst) { -- GitLab From b5d067b8e331ce78f4a81eb220965ffa36069d3f Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 27 Jan 2009 11:03:16 -0300 Subject: [PATCH 3317/4982] V4L/DVB (10975): Bug: Use signed types, Offsets and range can be negative Code simplification: use in kernel macros Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stb0899_algo.c | 14 +++++++------- drivers/media/dvb/frontends/stb0899_priv.h | 12 ++++-------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/drivers/media/dvb/frontends/stb0899_algo.c b/drivers/media/dvb/frontends/stb0899_algo.c index a67d1775a43..2da55ec2039 100644 --- a/drivers/media/dvb/frontends/stb0899_algo.c +++ b/drivers/media/dvb/frontends/stb0899_algo.c @@ -156,7 +156,7 @@ static void stb0899_first_subrange(struct stb0899_state *state) } if (range > 0) - internal->sub_range = MIN(internal->srch_range, range); + internal->sub_range = min(internal->srch_range, range); else internal->sub_range = 0; @@ -185,7 +185,7 @@ static enum stb0899_status stb0899_check_tmg(struct stb0899_state *state) timing = stb0899_read_reg(state, STB0899_RTF); if (lock >= 42) { - if ((lock > 48) && (ABS(timing) >= 110)) { + if ((lock > 48) && (abs(timing) >= 110)) { internal->status = ANALOGCARRIER; dprintk(state->verbose, FE_DEBUG, 1, "-->ANALOG Carrier !"); } else { @@ -222,7 +222,7 @@ static enum stb0899_status stb0899_search_tmg(struct stb0899_state *state) index++; derot_freq += index * internal->direction * derot_step; /* next derot zig zag position */ - if (ABS(derot_freq) > derot_limit) + if (abs(derot_freq) > derot_limit) next_loop--; if (next_loop) { @@ -298,7 +298,7 @@ static enum stb0899_status stb0899_search_carrier(struct stb0899_state *state) last_derot_freq = derot_freq; derot_freq += index * internal->direction * internal->derot_step; /* next zig zag derotator position */ - if(ABS(derot_freq) > derot_limit) + if(abs(derot_freq) > derot_limit) next_loop--; if (next_loop) { @@ -400,7 +400,7 @@ static enum stb0899_status stb0899_search_data(struct stb0899_state *state) if ((internal->status != CARRIEROK) || (stb0899_check_data(state) != DATAOK)) { derot_freq += index * internal->direction * derot_step; /* next zig zag derotator position */ - if (ABS(derot_freq) > derot_limit) + if (abs(derot_freq) > derot_limit) next_loop--; if (next_loop) { @@ -467,7 +467,7 @@ static void next_sub_range(struct stb0899_state *state) if (internal->sub_dir > 0) { old_sub_range = internal->sub_range; - internal->sub_range = MIN((internal->srch_range / 2) - + internal->sub_range = min((internal->srch_range / 2) - (internal->tuner_offst + internal->sub_range / 2), internal->sub_range); @@ -771,7 +771,7 @@ static long Log2Int(int number) int i; i = 0; - while ((1 << i) <= ABS(number)) + while ((1 << i) <= abs(number)) i++; if (number == 0) diff --git a/drivers/media/dvb/frontends/stb0899_priv.h b/drivers/media/dvb/frontends/stb0899_priv.h index 24619e3689d..82395b91281 100644 --- a/drivers/media/dvb/frontends/stb0899_priv.h +++ b/drivers/media/dvb/frontends/stb0899_priv.h @@ -59,10 +59,6 @@ #define MAKEWORD32(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) #define MAKEWORD16(a, b) (((a) << 8) | (b)) -#define MIN(x, y) ((x) <= (y) ? (x) : (y)) -#define MAX(x, y) ((x) >= (y) ? (x) : (y)) -#define ABS(x) ((x) >= 0 ? (x) : -(x)) - #define LSB(x) ((x & 0xff)) #define MSB(y) ((y >> 8) & 0xff) @@ -168,10 +164,10 @@ struct stb0899_internal { u32 freq; /* Demod internal Frequency */ u32 srate; /* Demod internal Symbol rate */ enum stb0899_fec fecrate; /* Demod internal FEC rate */ - u32 srch_range; /* Demod internal Search Range */ - u32 sub_range; /* Demod current sub range (Hz) */ - u32 tuner_step; /* Tuner step (Hz) */ - u32 tuner_offst; /* Relative offset to carrier (Hz) */ + s32 srch_range; /* Demod internal Search Range */ + s32 sub_range; /* Demod current sub range (Hz) */ + s32 tuner_step; /* Tuner step (Hz) */ + s32 tuner_offst; /* Relative offset to carrier (Hz) */ u32 tuner_bw; /* Current bandwidth of the tuner (Hz) */ s32 mclk; /* Masterclock Divider factor (binary) */ -- GitLab From 1d06059c13fc64b67027334507f734ec0f2f4b6c Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sun, 9 Nov 2008 11:35:13 -0300 Subject: [PATCH 3318/4982] V4L/DVB (10976): Bug fix: For legacy applications stv0899 performs search only first time after insmod. For legacy applications stv0899 performs search only first time after insmod due to not set DVBFE_ALGO_SEARCH_AGAIN bit Signed-off-by: Igor M. Liplianin Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 84340778508..8dcb3fbf7ac 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1290,9 +1290,6 @@ static int dtv_property_process_set(struct dvb_frontend *fe, dprintk("%s() Finalised property cache\n", __func__); dtv_property_cache_submit(fe); - /* Request the search algorithm to search */ - fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; - r |= dvb_frontend_ioctl_legacy(inode, file, FE_SET_FRONTEND, &fepriv->parameters); break; @@ -1717,6 +1714,10 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000; fepriv->state = FESTATE_RETUNE; + + /* Request the search algorithm to search */ + fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; + dvb_frontend_wakeup(fe); dvb_frontend_add_event(fe, 0); fepriv->status = 0; -- GitLab From 26f26fa8e3a0822aa43ee0a80bd0196fa2554c42 Mon Sep 17 00:00:00 2001 From: Hans Werner Date: Tue, 27 Jan 2009 16:09:12 -0300 Subject: [PATCH 3319/4982] V4L/DVB (10977): STB6100 init fix, the call to stb6100_set_bandwidth needs an argument in Hz not kHz, and a comment incorrectly says MHz instead of Hz. I don't know if this caused real problems anywhere Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stb6100.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/frontends/stb6100.c b/drivers/media/dvb/frontends/stb6100.c index ff39275ab49..1ed5a7db4c5 100644 --- a/drivers/media/dvb/frontends/stb6100.c +++ b/drivers/media/dvb/frontends/stb6100.c @@ -427,11 +427,11 @@ static int stb6100_init(struct dvb_frontend *fe) status->refclock = 27000000; /* Hz */ status->iqsense = 1; status->bandwidth = 36000; /* kHz */ - state->bandwidth = status->bandwidth * 1000; /* MHz */ + state->bandwidth = status->bandwidth * 1000; /* Hz */ state->reference = status->refclock / 1000; /* kHz */ /* Set default bandwidth. */ - return stb6100_set_bandwidth(fe, status->bandwidth); + return stb6100_set_bandwidth(fe, state->bandwidth); } static int stb6100_get_state(struct dvb_frontend *fe, -- GitLab From a00d0bb86b20a86a72f4df9d6e31dda94c02b4fa Mon Sep 17 00:00:00 2001 From: Matthias Schwarzzot Date: Tue, 27 Jan 2009 16:29:44 -0300 Subject: [PATCH 3320/4982] V4L/DVB (10978): Report tuning algorith correctly Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/dst.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index 29e8f1546ab..fec1d77fa85 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -1683,7 +1683,7 @@ static int dst_tune_frontend(struct dvb_frontend* fe, static int dst_get_tuning_algo(struct dvb_frontend *fe) { - return dst_algo; + return dst_algo ? DVBFE_ALGO_HW : DVBFE_ALGO_SW; } static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) -- GitLab From 9fae6c3f648e38f023b99b5f5a5280907b2e796e Mon Sep 17 00:00:00 2001 From: Ilya Yanok Date: Fri, 13 Mar 2009 09:51:46 -0700 Subject: [PATCH 3321/4982] dnet: replace obsolete *netif_rx_* functions with *napi_* *netif_rx_* functions is obsolete and removed in newer kernels so we need to use corresponding *napi_* functions instead. Signed-off-by: Ilya Yanok Signed-off-by: David S. Miller --- drivers/net/dnet.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c index 4b96974fe76..5c347f70cb6 100644 --- a/drivers/net/dnet.c +++ b/drivers/net/dnet.c @@ -408,7 +408,7 @@ static int dnet_poll(struct napi_struct *napi, int budget) * packets waiting */ if (!(dnet_readl(bp, RX_FIFO_WCNT) >> 16)) { - netif_rx_complete(napi); + napi_complete(napi); int_enable = dnet_readl(bp, INTR_ENB); int_enable |= DNET_INTR_SRC_RX_CMDFIFOAF; dnet_writel(bp, int_enable, INTR_ENB); @@ -447,7 +447,7 @@ static int dnet_poll(struct napi_struct *napi, int budget) if (npackets < budget) { /* We processed all packets available. Tell NAPI it can * stop polling then re-enable rx interrupts */ - netif_rx_complete(napi); + napi_complete(napi); int_enable = dnet_readl(bp, INTR_ENB); int_enable |= DNET_INTR_SRC_RX_CMDFIFOAF; dnet_writel(bp, int_enable, INTR_ENB); @@ -507,7 +507,7 @@ static irqreturn_t dnet_interrupt(int irq, void *dev_id) } if (int_current & DNET_INTR_SRC_RX_CMDFIFOAF) { - if (netif_rx_schedule_prep(&bp->napi)) { + if (napi_schedule_prep(&bp->napi)) { /* * There's no point taking any more interrupts * until we have processed the buffers @@ -516,7 +516,7 @@ static irqreturn_t dnet_interrupt(int irq, void *dev_id) int_enable = dnet_readl(bp, INTR_ENB); int_enable &= ~DNET_INTR_SRC_RX_CMDFIFOAF; dnet_writel(bp, int_enable, INTR_ENB); - __netif_rx_schedule(&bp->napi); + __napi_schedule(&bp->napi); } handled = 1; } -- GitLab From c3c6496dc3d94d87bb0da86cf0bf48764577bf77 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Wed, 11 Mar 2009 11:55:40 +0000 Subject: [PATCH 3322/4982] qlge: bugfix: Increase filter on inbound csum. Chip does not do UDP checksum when fragmentation occurs. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge.h | 1 + drivers/net/qlge/qlge_main.c | 38 ++++++++++++++++++++++++------------ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index e6fdce9206c..aff9c5fec73 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -927,6 +927,7 @@ struct ib_mac_iocb_rsp { u8 flags1; #define IB_MAC_IOCB_RSP_OI 0x01 /* Overide intr delay */ #define IB_MAC_IOCB_RSP_I 0x02 /* Disble Intr Generation */ +#define IB_MAC_CSUM_ERR_MASK 0x1c /* A mask to use for csum errs */ #define IB_MAC_IOCB_RSP_TE 0x04 /* Checksum error */ #define IB_MAC_IOCB_RSP_NU 0x08 /* No checksum rcvd */ #define IB_MAC_IOCB_RSP_IE 0x10 /* IPv4 checksum error */ diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 8ea72dc60f7..87787b1ecab 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -1436,18 +1436,32 @@ static void ql_process_mac_rx_intr(struct ql_adapter *qdev, if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_P) { QPRINTK(qdev, RX_STATUS, DEBUG, "Promiscuous Packet.\n"); } - if (ib_mac_rsp->flags1 & (IB_MAC_IOCB_RSP_IE | IB_MAC_IOCB_RSP_TE)) { - QPRINTK(qdev, RX_STATUS, ERR, - "Bad checksum for this %s packet.\n", - ((ib_mac_rsp-> - flags2 & IB_MAC_IOCB_RSP_T) ? "TCP" : "UDP")); - skb->ip_summed = CHECKSUM_NONE; - } else if (qdev->rx_csum && - ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) || - ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) && - !(ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_NU)))) { - QPRINTK(qdev, RX_STATUS, DEBUG, "RX checksum done!\n"); - skb->ip_summed = CHECKSUM_UNNECESSARY; + + skb->protocol = eth_type_trans(skb, ndev); + skb->ip_summed = CHECKSUM_NONE; + + /* If rx checksum is on, and there are no + * csum or frame errors. + */ + if (qdev->rx_csum && + !(ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) && + !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) { + /* TCP frame. */ + if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) { + QPRINTK(qdev, RX_STATUS, DEBUG, + "TCP checksum done!\n"); + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else if ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) && + (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_V4)) { + /* Unfragmented ipv4 UDP frame. */ + struct iphdr *iph = (struct iphdr *) skb->data; + if (!(iph->frag_off & + cpu_to_be16(IP_MF|IP_OFFSET))) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + QPRINTK(qdev, RX_STATUS, DEBUG, + "TCP checksum done!\n"); + } + } } qdev->stats.rx_packets++; qdev->stats.rx_bytes += skb->len; -- GitLab From a7a655f22c75f48e0afe8b86be03ecd70bd68b07 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Wed, 11 Mar 2009 11:55:41 +0000 Subject: [PATCH 3323/4982] qlge: bugfix: Tell hw to strip vlan header. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 87787b1ecab..54d54ea03d4 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -2984,9 +2984,9 @@ static int ql_adapter_initialize(struct ql_adapter *qdev) mask = value << 16; ql_write32(qdev, SYS, mask | value); - /* Set the default queue. */ - value = NIC_RCV_CFG_DFQ; - mask = NIC_RCV_CFG_DFQ_MASK; + /* Set the default queue, and VLAN behavior. */ + value = NIC_RCV_CFG_DFQ | NIC_RCV_CFG_RV; + mask = NIC_RCV_CFG_DFQ_MASK | (NIC_RCV_CFG_RV << 16); ql_write32(qdev, NIC_RCV_CFG, (mask | value)); /* Set the MPI interrupt to enabled. */ -- GitLab From 6612a6344aba8ba7b5af67cd006453bfedbb2967 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Wed, 11 Mar 2009 11:55:42 +0000 Subject: [PATCH 3324/4982] qlge: bugfix: Move netif_napi_del() to common call point. Moving netif_napi_del() up the call chain so it will get called from all exit points. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 54d54ea03d4..00c37c0f8a9 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3163,6 +3163,11 @@ static int ql_adapter_down(struct ql_adapter *qdev) ql_tx_ring_clean(qdev); + /* Call netif_napi_del() from common point. + */ + for (i = qdev->rss_ring_first_cq_id; i < qdev->rx_ring_count; i++) + netif_napi_del(&qdev->rx_ring[i].napi); + spin_lock(&qdev->hw_lock); status = ql_adapter_reset(qdev); if (status) @@ -3867,7 +3872,7 @@ static int qlge_suspend(struct pci_dev *pdev, pm_message_t state) { struct net_device *ndev = pci_get_drvdata(pdev); struct ql_adapter *qdev = netdev_priv(ndev); - int err, i; + int err; netif_device_detach(ndev); @@ -3877,9 +3882,6 @@ static int qlge_suspend(struct pci_dev *pdev, pm_message_t state) return err; } - for (i = qdev->rss_ring_first_cq_id; i < qdev->rx_ring_count; i++) - netif_napi_del(&qdev->rx_ring[i].napi); - err = pci_save_state(pdev); if (err) return err; -- GitLab From 855b0993f216a9b0f9cb33573bd05e314105d86c Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Wed, 11 Mar 2009 11:55:43 +0000 Subject: [PATCH 3325/4982] qlge: bugfix: Pad outbound frames smaller than 60 bytes. With some asic configurations xmit of frames smaller than 60 bytes may fail. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 00c37c0f8a9..91191f761fb 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -1941,6 +1941,9 @@ static int qlge_send(struct sk_buff *skb, struct net_device *ndev) tx_ring = &qdev->tx_ring[tx_ring_idx]; + if (skb_padto(skb, ETH_ZLEN)) + return NETDEV_TX_OK; + if (unlikely(atomic_read(&tx_ring->tx_count) < 2)) { QPRINTK(qdev, TX_QUEUED, INFO, "%s: shutting down tx queue %d du to lack of resources.\n", -- GitLab From 26b3871d2c82b7c733a3b6d631a6e48c9ebf1c5a Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Thu, 12 Mar 2009 21:13:43 +0000 Subject: [PATCH 3326/4982] cxgb3: ring rx door bell less frequently Ring free lists door bell less frequently, specifically every quarter of the active FL size. Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/adapter.h | 1 + drivers/net/cxgb3/sge.c | 32 ++++++++++++++++++++++++-------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h index fbe15699584..95dce483247 100644 --- a/drivers/net/cxgb3/adapter.h +++ b/drivers/net/cxgb3/adapter.h @@ -91,6 +91,7 @@ struct rx_sw_desc; struct sge_fl { /* SGE per free-buffer list state */ unsigned int buf_size; /* size of each Rx buffer */ unsigned int credits; /* # of available Rx buffers */ + unsigned int pend_cred; /* new buffers since last FL DB ring */ unsigned int size; /* capacity of free list */ unsigned int cidx; /* consumer index */ unsigned int pidx; /* producer index */ diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 8205aa4ae94..882beafeb74 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -62,6 +62,10 @@ #define SGE_RX_DROP_THRES 16 +/* + * Max number of Rx buffers we replenish at a time. + */ +#define MAX_RX_REFILL 16U /* * Period of the Tx buffer reclaim timer. This timer does not need to run * frequently as Tx buffers are usually reclaimed by new Tx packets. @@ -423,6 +427,14 @@ static int alloc_pg_chunk(struct sge_fl *q, struct rx_sw_desc *sd, gfp_t gfp, return 0; } +static inline void ring_fl_db(struct adapter *adap, struct sge_fl *q) +{ + if (q->pend_cred >= q->credits / 4) { + q->pend_cred = 0; + t3_write_reg(adap, A_SG_KDOORBELL, V_EGRCNTX(q->cntxt_id)); + } +} + /** * refill_fl - refill an SGE free-buffer list * @adapter: the adapter @@ -478,19 +490,19 @@ nomem: q->alloc_failed++; sd = q->sdesc; d = q->desc; } - q->credits++; count++; } - wmb(); - if (likely(count)) - t3_write_reg(adap, A_SG_KDOORBELL, V_EGRCNTX(q->cntxt_id)); + + q->credits += count; + q->pend_cred += count; + ring_fl_db(adap, q); return count; } static inline void __refill_fl(struct adapter *adap, struct sge_fl *fl) { - refill_fl(adap, fl, min(16U, fl->size - fl->credits), + refill_fl(adap, fl, min(MAX_RX_REFILL, fl->size - fl->credits), GFP_ATOMIC | __GFP_COMP); } @@ -515,13 +527,15 @@ static void recycle_rx_buf(struct adapter *adap, struct sge_fl *q, wmb(); to->len_gen = cpu_to_be32(V_FLD_GEN1(q->gen)); to->gen2 = cpu_to_be32(V_FLD_GEN2(q->gen)); - q->credits++; if (++q->pidx == q->size) { q->pidx = 0; q->gen ^= 1; } - t3_write_reg(adap, A_SG_KDOORBELL, V_EGRCNTX(q->cntxt_id)); + + q->credits++; + q->pend_cred++; + ring_fl_db(adap, q); } /** @@ -732,7 +746,9 @@ recycle: return skb; } - if (unlikely(fl->credits < drop_thres)) + if (unlikely(fl->credits < drop_thres) && + refill_fl(adap, fl, min(MAX_RX_REFILL, fl->size - fl->credits - 1), + GFP_ATOMIC | __GFP_COMP) == 0) goto recycle; use_orig_buf: -- GitLab From 9bb2b31e6f87dba06b81429af91362a9127f5bf2 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Thu, 12 Mar 2009 21:13:49 +0000 Subject: [PATCH 3327/4982] cxgb3: release page ref on mapping error Release page chunk reference in case we fail to map it. Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/sge.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 882beafeb74..808b8af0c74 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -338,6 +338,18 @@ static inline int should_restart_tx(const struct sge_txq *q) return q->in_use - r < (q->size >> 1); } +static void clear_rx_desc(const struct sge_fl *q, struct rx_sw_desc *d) +{ + if (q->use_pages) { + if (d->pg_chunk.page) + put_page(d->pg_chunk.page); + d->pg_chunk.page = NULL; + } else { + kfree_skb(d->skb); + d->skb = NULL; + } +} + /** * free_rx_bufs - free the Rx buffers on an SGE free list * @pdev: the PCI device associated with the adapter @@ -355,14 +367,7 @@ static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q) pci_unmap_single(pdev, pci_unmap_addr(d, dma_addr), q->buf_size, PCI_DMA_FROMDEVICE); - if (q->use_pages) { - if (d->pg_chunk.page) - put_page(d->pg_chunk.page); - d->pg_chunk.page = NULL; - } else { - kfree_skb(d->skb); - d->skb = NULL; - } + clear_rx_desc(q, d); if (++cidx == q->size) cidx = 0; } @@ -475,10 +480,7 @@ nomem: q->alloc_failed++; err = add_one_rx_buf(buf_start, q->buf_size, d, sd, q->gen, adap->pdev); if (unlikely(err)) { - if (!q->use_pages) { - kfree_skb(sd->skb); - sd->skb = NULL; - } + clear_rx_desc(q, sd); break; } -- GitLab From 8f4358044d7d694f2e0c18a6ce5db6ec0790451a Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Thu, 12 Mar 2009 21:13:54 +0000 Subject: [PATCH 3328/4982] cxgb3: fix skb truesize in jumbo mode Update skb truesize correctly for the 2nd buffer from a Jumbo frame Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/sge.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 808b8af0c74..90f6f82d3bf 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -830,14 +830,15 @@ recycle: len - SGE_RX_PULL_LEN); newskb->len = len; newskb->data_len = len - SGE_RX_PULL_LEN; + newskb->truesize += newskb->data_len; } else { skb_fill_page_desc(newskb, skb_shinfo(newskb)->nr_frags, sd->pg_chunk.page, sd->pg_chunk.offset, len); newskb->len += len; newskb->data_len += len; + newskb->truesize += len; } - newskb->truesize += newskb->data_len; fl->credits--; /* -- GitLab From b2b964f0647c5156038834dd879f90442e33f2a5 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Thu, 12 Mar 2009 21:13:59 +0000 Subject: [PATCH 3329/4982] cxgb3: prefetch buffer access in GRO mode Elmininate a cache miss when accessing the CPL header within the first aggregated buffer. Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/sge.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 90f6f82d3bf..a482429846e 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -2029,6 +2029,8 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs, pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr), fl->buf_size, PCI_DMA_FROMDEVICE); + prefetch(&qs->lro_frag_tbl); + rx_frag += nr_frags; rx_frag->page = sd->pg_chunk.page; rx_frag->page_offset = sd->pg_chunk.offset + offset; @@ -2997,6 +2999,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, V_NEWTIMER(q->rspq.holdoff_tmr)); mod_timer(&q->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD); + return 0; err_unlock: -- GitLab From 42c8ea17e8f78752ed5a354791b0ea1697dc3480 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Thu, 12 Mar 2009 21:14:04 +0000 Subject: [PATCH 3330/4982] cxgb3: separate TX and RX reclaim handlers Separate TX and RX reclaim handlers Don't disable interrupts in RX reclaim handler. Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/adapter.h | 1 + drivers/net/cxgb3/sge.c | 128 +++++++++++++++++++++++++----------- 2 files changed, 89 insertions(+), 40 deletions(-) diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h index 95dce483247..66ce456614a 100644 --- a/drivers/net/cxgb3/adapter.h +++ b/drivers/net/cxgb3/adapter.h @@ -197,6 +197,7 @@ struct sge_qset { /* an SGE queue set */ struct netdev_queue *tx_q; /* associated netdev TX queue */ unsigned long txq_stopped; /* which Tx queues are stopped */ struct timer_list tx_reclaim_timer; /* reclaims TX buffers */ + struct timer_list rx_reclaim_timer; /* reclaims RX buffers */ unsigned long port_stats[SGE_PSTAT_MAX]; } ____cacheline_aligned; diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index a482429846e..7d779d18e13 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -61,6 +61,7 @@ #define FL1_PG_ORDER (PAGE_SIZE > 8192 ? 0 : 1) #define SGE_RX_DROP_THRES 16 +#define RX_RECLAIM_PERIOD (HZ/4) /* * Max number of Rx buffers we replenish at a time. @@ -71,6 +72,8 @@ * frequently as Tx buffers are usually reclaimed by new Tx packets. */ #define TX_RECLAIM_PERIOD (HZ / 4) +#define TX_RECLAIM_TIMER_CHUNK 64U +#define TX_RECLAIM_CHUNK 16U /* WR size in bytes */ #define WR_LEN (WR_FLITS * 8) @@ -308,21 +311,25 @@ static void free_tx_desc(struct adapter *adapter, struct sge_txq *q, * reclaim_completed_tx - reclaims completed Tx descriptors * @adapter: the adapter * @q: the Tx queue to reclaim completed descriptors from + * @chunk: maximum number of descriptors to reclaim * * Reclaims Tx descriptors that the SGE has indicated it has processed, * and frees the associated buffers if possible. Called with the Tx * queue's lock held. */ -static inline void reclaim_completed_tx(struct adapter *adapter, - struct sge_txq *q) +static inline unsigned int reclaim_completed_tx(struct adapter *adapter, + struct sge_txq *q, + unsigned int chunk) { unsigned int reclaim = q->processed - q->cleaned; + reclaim = min(chunk, reclaim); if (reclaim) { free_tx_desc(adapter, q, reclaim); q->cleaned += reclaim; q->in_use -= reclaim; } + return q->processed - q->cleaned; } /** @@ -601,6 +608,7 @@ static void t3_reset_qset(struct sge_qset *q) memset(q->txq, 0, sizeof(struct sge_txq) * SGE_TXQ_PER_SET); q->txq_stopped = 0; q->tx_reclaim_timer.function = NULL; /* for t3_stop_sge_timers() */ + q->rx_reclaim_timer.function = NULL; q->lro_frag_tbl.nr_frags = q->lro_frag_tbl.len = 0; } @@ -1179,7 +1187,7 @@ int t3_eth_xmit(struct sk_buff *skb, struct net_device *dev) txq = netdev_get_tx_queue(dev, qidx); spin_lock(&q->lock); - reclaim_completed_tx(adap, q); + reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK); credits = q->size - q->in_use; ndesc = calc_tx_descs(skb); @@ -1588,7 +1596,7 @@ static int ofld_xmit(struct adapter *adap, struct sge_txq *q, unsigned int ndesc = calc_tx_descs_ofld(skb), pidx, gen; spin_lock(&q->lock); - again:reclaim_completed_tx(adap, q); +again: reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK); ret = check_desc_avail(adap, q, skb, ndesc, TXQ_OFLD); if (unlikely(ret)) { @@ -1630,7 +1638,7 @@ static void restart_offloadq(unsigned long data) struct adapter *adap = pi->adapter; spin_lock(&q->lock); - again:reclaim_completed_tx(adap, q); +again: reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK); while ((skb = skb_peek(&q->sendq)) != NULL) { unsigned int gen, pidx; @@ -2747,13 +2755,13 @@ void t3_sge_err_intr_handler(struct adapter *adapter) } /** - * sge_timer_cb - perform periodic maintenance of an SGE qset + * sge_timer_tx - perform periodic maintenance of an SGE qset * @data: the SGE queue set to maintain * * Runs periodically from a timer to perform maintenance of an SGE queue * set. It performs two tasks: * - * a) Cleans up any completed Tx descriptors that may still be pending. + * Cleans up any completed Tx descriptors that may still be pending. * Normal descriptor cleanup happens when new packets are added to a Tx * queue so this timer is relatively infrequent and does any cleanup only * if the Tx queue has not seen any new packets in a while. We make a @@ -2763,51 +2771,87 @@ void t3_sge_err_intr_handler(struct adapter *adapter) * up). Since control queues use immediate data exclusively we don't * bother cleaning them up here. * - * b) Replenishes Rx queues that have run out due to memory shortage. - * Normally new Rx buffers are added when existing ones are consumed but - * when out of memory a queue can become empty. We try to add only a few - * buffers here, the queue will be replenished fully as these new buffers - * are used up if memory shortage has subsided. */ -static void sge_timer_cb(unsigned long data) +static void sge_timer_tx(unsigned long data) { - spinlock_t *lock; struct sge_qset *qs = (struct sge_qset *)data; - struct adapter *adap = qs->adap; + struct port_info *pi = netdev_priv(qs->netdev); + struct adapter *adap = pi->adapter; + unsigned int tbd[SGE_TXQ_PER_SET] = {0, 0}; + unsigned long next_period; if (spin_trylock(&qs->txq[TXQ_ETH].lock)) { - reclaim_completed_tx(adap, &qs->txq[TXQ_ETH]); + tbd[TXQ_ETH] = reclaim_completed_tx(adap, &qs->txq[TXQ_ETH], + TX_RECLAIM_TIMER_CHUNK); spin_unlock(&qs->txq[TXQ_ETH].lock); } if (spin_trylock(&qs->txq[TXQ_OFLD].lock)) { - reclaim_completed_tx(adap, &qs->txq[TXQ_OFLD]); + tbd[TXQ_OFLD] = reclaim_completed_tx(adap, &qs->txq[TXQ_OFLD], + TX_RECLAIM_TIMER_CHUNK); spin_unlock(&qs->txq[TXQ_OFLD].lock); } - lock = (adap->flags & USING_MSIX) ? &qs->rspq.lock : - &adap->sge.qs[0].rspq.lock; - if (spin_trylock_irq(lock)) { - if (!napi_is_scheduled(&qs->napi)) { - u32 status = t3_read_reg(adap, A_SG_RSPQ_FL_STATUS); - - if (qs->fl[0].credits < qs->fl[0].size) - __refill_fl(adap, &qs->fl[0]); - if (qs->fl[1].credits < qs->fl[1].size) - __refill_fl(adap, &qs->fl[1]); - - if (status & (1 << qs->rspq.cntxt_id)) { - qs->rspq.starved++; - if (qs->rspq.credits) { - refill_rspq(adap, &qs->rspq, 1); - qs->rspq.credits--; - qs->rspq.restarted++; - t3_write_reg(adap, A_SG_RSPQ_FL_STATUS, - 1 << qs->rspq.cntxt_id); - } + + next_period = TX_RECLAIM_PERIOD >> + (max(tbd[TXQ_ETH], tbd[TXQ_OFLD]) / + TX_RECLAIM_TIMER_CHUNK); + mod_timer(&qs->tx_reclaim_timer, jiffies + next_period); +} + +/* + * sge_timer_rx - perform periodic maintenance of an SGE qset + * @data: the SGE queue set to maintain + * + * a) Replenishes Rx queues that have run out due to memory shortage. + * Normally new Rx buffers are added when existing ones are consumed but + * when out of memory a queue can become empty. We try to add only a few + * buffers here, the queue will be replenished fully as these new buffers + * are used up if memory shortage has subsided. + * + * b) Return coalesced response queue credits in case a response queue is + * starved. + * + */ +static void sge_timer_rx(unsigned long data) +{ + spinlock_t *lock; + struct sge_qset *qs = (struct sge_qset *)data; + struct port_info *pi = netdev_priv(qs->netdev); + struct adapter *adap = pi->adapter; + u32 status; + + lock = adap->params.rev > 0 ? + &qs->rspq.lock : &adap->sge.qs[0].rspq.lock; + + if (!spin_trylock_irq(lock)) + goto out; + + if (napi_is_scheduled(&qs->napi)) + goto unlock; + + if (adap->params.rev < 4) { + status = t3_read_reg(adap, A_SG_RSPQ_FL_STATUS); + + if (status & (1 << qs->rspq.cntxt_id)) { + qs->rspq.starved++; + if (qs->rspq.credits) { + qs->rspq.credits--; + refill_rspq(adap, &qs->rspq, 1); + qs->rspq.restarted++; + t3_write_reg(adap, A_SG_RSPQ_FL_STATUS, + 1 << qs->rspq.cntxt_id); } } - spin_unlock_irq(lock); } - mod_timer(&qs->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD); + + if (qs->fl[0].credits < qs->fl[0].size) + __refill_fl(adap, &qs->fl[0]); + if (qs->fl[1].credits < qs->fl[1].size) + __refill_fl(adap, &qs->fl[1]); + +unlock: + spin_unlock_irq(lock); +out: + mod_timer(&qs->rx_reclaim_timer, jiffies + RX_RECLAIM_PERIOD); } /** @@ -2850,7 +2894,8 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, struct sge_qset *q = &adapter->sge.qs[id]; init_qset_cntxt(q, id); - setup_timer(&q->tx_reclaim_timer, sge_timer_cb, (unsigned long)q); + setup_timer(&q->tx_reclaim_timer, sge_timer_tx, (unsigned long)q); + setup_timer(&q->rx_reclaim_timer, sge_timer_rx, (unsigned long)q); q->fl[0].desc = alloc_ring(adapter->pdev, p->fl_size, sizeof(struct rx_desc), @@ -2999,6 +3044,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, V_NEWTIMER(q->rspq.holdoff_tmr)); mod_timer(&q->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD); + mod_timer(&q->rx_reclaim_timer, jiffies + RX_RECLAIM_PERIOD); return 0; @@ -3024,6 +3070,8 @@ void t3_stop_sge_timers(struct adapter *adap) if (q->tx_reclaim_timer.function) del_timer_sync(&q->tx_reclaim_timer); + if (q->rx_reclaim_timer.function) + del_timer_sync(&q->rx_reclaim_timer); } } -- GitLab From fc88219601aa3f94def89433a6afde154e8faa8c Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Thu, 12 Mar 2009 21:14:09 +0000 Subject: [PATCH 3331/4982] cxgb3: disable high freq non-data interrupts Under RX pressure, The HW might generate a high load of interrupts to signal mac fifo or free lists overflow. Disable the interrupts, and poll the relevant status bits to maintain stats. Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/cxgb3_main.c | 50 ++++++++++++++++++++++++++++++++++ drivers/net/cxgb3/regs.h | 8 ++++++ drivers/net/cxgb3/sge.c | 3 +- drivers/net/cxgb3/t3_hw.c | 30 +++++++++++++++++--- 4 files changed, 86 insertions(+), 5 deletions(-) diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index c32f514c41a..9ff0452fcdd 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -2471,6 +2471,8 @@ static void t3_adap_check_task(struct work_struct *work) struct adapter *adapter = container_of(work, struct adapter, adap_check_task.work); const struct adapter_params *p = &adapter->params; + int port; + unsigned int v, status, reset; adapter->check_task_cnt++; @@ -2489,6 +2491,54 @@ static void t3_adap_check_task(struct work_struct *work) if (p->rev == T3_REV_B2) check_t3b2_mac(adapter); + /* + * Scan the XGMAC's to check for various conditions which we want to + * monitor in a periodic polling manner rather than via an interrupt + * condition. This is used for conditions which would otherwise flood + * the system with interrupts and we only really need to know that the + * conditions are "happening" ... For each condition we count the + * detection of the condition and reset it for the next polling loop. + */ + for_each_port(adapter, port) { + struct cmac *mac = &adap2pinfo(adapter, port)->mac; + u32 cause; + + cause = t3_read_reg(adapter, A_XGM_INT_CAUSE + mac->offset); + reset = 0; + if (cause & F_RXFIFO_OVERFLOW) { + mac->stats.rx_fifo_ovfl++; + reset |= F_RXFIFO_OVERFLOW; + } + + t3_write_reg(adapter, A_XGM_INT_CAUSE + mac->offset, reset); + } + + /* + * We do the same as above for FL_EMPTY interrupts. + */ + status = t3_read_reg(adapter, A_SG_INT_CAUSE); + reset = 0; + + if (status & F_FLEMPTY) { + struct sge_qset *qs = &adapter->sge.qs[0]; + int i = 0; + + reset |= F_FLEMPTY; + + v = (t3_read_reg(adapter, A_SG_RSPQ_FL_STATUS) >> S_FL0EMPTY) & + 0xffff; + + while (v) { + qs->fl[i].empty += (v & 1); + if (i) + qs++; + i ^= 1; + v >>= 1; + } + } + + t3_write_reg(adapter, A_SG_INT_CAUSE, reset); + /* Schedule the next check update if any port is active. */ spin_lock_irq(&adapter->work_lock); if (adapter->open_device_map & PORT_MASK) diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h index a035d5c2444..aa08550ee99 100644 --- a/drivers/net/cxgb3/regs.h +++ b/drivers/net/cxgb3/regs.h @@ -170,6 +170,10 @@ #define S_RSPQ0DISABLED 8 +#define S_FL0EMPTY 16 +#define V_FL0EMPTY(x) ((x) << S_FL0EMPTY) +#define F_FL0EMPTY V_FL0EMPTY(1U) + #define A_SG_EGR_RCQ_DRB_THRSH 0x54 #define S_HIRCQDRBTHRSH 16 @@ -258,6 +262,10 @@ #define V_RSPQCREDITOVERFOW(x) ((x) << S_RSPQCREDITOVERFOW) #define F_RSPQCREDITOVERFOW V_RSPQCREDITOVERFOW(1U) +#define S_FLEMPTY 1 +#define V_FLEMPTY(x) ((x) << S_FLEMPTY) +#define F_FLEMPTY V_FLEMPTY(1U) + #define A_SG_INT_ENABLE 0x60 #define A_SG_CMDQ_CREDIT_TH 0x64 diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 7d779d18e13..a7555cb3fa4 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -2725,7 +2725,8 @@ irq_handler_t t3_intr_handler(struct adapter *adap, int polling) */ void t3_sge_err_intr_handler(struct adapter *adapter) { - unsigned int v, status = t3_read_reg(adapter, A_SG_INT_CAUSE); + unsigned int v, status = t3_read_reg(adapter, A_SG_INT_CAUSE) & + ~F_FLEMPTY; if (status & SGE_PARERR) CH_ALERT(adapter, "SGE parity error (0x%x)\n", diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index ac2a974dfe3..7c6ee0c9b6f 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c @@ -1323,7 +1323,7 @@ static int t3_handle_intr_status(struct adapter *adapter, unsigned int reg, #define MC7_INTR_MASK (F_AE | F_UE | F_CE | V_PE(M_PE)) #define XGM_INTR_MASK (V_TXFIFO_PRTY_ERR(M_TXFIFO_PRTY_ERR) | \ V_RXFIFO_PRTY_ERR(M_RXFIFO_PRTY_ERR) | \ - F_TXFIFO_UNDERRUN | F_RXFIFO_OVERFLOW) + F_TXFIFO_UNDERRUN) #define PCIX_INTR_MASK (F_MSTDETPARERR | F_SIGTARABT | F_RCVTARABT | \ F_RCVMSTABT | F_SIGSYSERR | F_DETPARERR | \ F_SPLCMPDIS | F_UNXSPLCMP | F_RCVSPLCMPERR | \ @@ -1695,7 +1695,14 @@ static void mc7_intr_handler(struct mc7 *mc7) static int mac_intr_handler(struct adapter *adap, unsigned int idx) { struct cmac *mac = &adap2pinfo(adap, idx)->mac; - u32 cause = t3_read_reg(adap, A_XGM_INT_CAUSE + mac->offset); + /* + * We mask out interrupt causes for which we're not taking interrupts. + * This allows us to use polling logic to monitor some of the other + * conditions when taking interrupts would impose too much load on the + * system. + */ + u32 cause = t3_read_reg(adap, A_XGM_INT_CAUSE + mac->offset) & + ~F_RXFIFO_OVERFLOW; if (cause & V_TXFIFO_PRTY_ERR(M_TXFIFO_PRTY_ERR)) { mac->stats.tx_fifo_parity_err++; @@ -3617,7 +3624,15 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, adapter->params.info = ai; adapter->params.nports = ai->nports; adapter->params.rev = t3_read_reg(adapter, A_PL_REV); - adapter->params.linkpoll_period = 0; + /* + * We used to only run the "adapter check task" once a second if + * we had PHYs which didn't support interrupts (we would check + * their link status once a second). Now we check other conditions + * in that routine which could potentially impose a very high + * interrupt load on the system. As such, we now always scan the + * adapter state once a second ... + */ + adapter->params.linkpoll_period = 10; adapter->params.stats_update_period = is_10G(adapter) ? MAC_STATS_ACCUM_SECS : (MAC_STATS_ACCUM_SECS * 10); adapter->params.pci.vpd_cap_addr = @@ -3707,7 +3722,14 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, ETH_ALEN); init_link_config(&p->link_config, p->phy.caps); p->phy.ops->power_down(&p->phy, 1); - if (!(p->phy.caps & SUPPORTED_IRQ)) + + /* + * If the PHY doesn't support interrupts for link status + * changes, schedule a scan of the adapter links at least + * once a second. + */ + if (!(p->phy.caps & SUPPORTED_IRQ) && + adapter->params.linkpoll_period > 10) adapter->params.linkpoll_period = 10; } -- GitLab From cd40658a616050df0a50d0a3ded06e3ebcc0a04a Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Thu, 12 Mar 2009 21:14:14 +0000 Subject: [PATCH 3332/4982] cxgb3: Update Rev3 mac workaround Update the heurstics workaround unlocking a hung mac: - reduce Tx mac toggling by enabling Tx drain before resetting the mac - Take Tx (lack of) activity in account only - Update the monitoring counter range to 64 bits Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/xgmac.c | 72 ++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 39 deletions(-) diff --git a/drivers/net/cxgb3/xgmac.c b/drivers/net/cxgb3/xgmac.c index 9d7786937aa..4bd0901a97a 100644 --- a/drivers/net/cxgb3/xgmac.c +++ b/drivers/net/cxgb3/xgmac.c @@ -150,7 +150,8 @@ int t3_mac_reset(struct cmac *mac) static int t3b2_mac_reset(struct cmac *mac) { struct adapter *adap = mac->adapter; - unsigned int oft = mac->offset; + unsigned int oft = mac->offset, store; + int idx = macidx(mac); u32 val; if (!macidx(mac)) @@ -158,14 +159,28 @@ static int t3b2_mac_reset(struct cmac *mac) else t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE, 0); + /* Stop NIC traffic to reduce the number of TXTOGGLES */ + t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 0); + /* Ensure TX drains */ + t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN, 0); + t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_); t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ + /* Store A_TP_TX_DROP_CFG_CH0 */ + t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); + store = t3_read_reg(adap, A_TP_TX_DROP_CFG_CH0 + idx); + msleep(10); + /* Change DROP_CFG to 0xc0000011 */ + t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); + t3_write_reg(adap, A_TP_PIO_DATA, 0xc0000011); + /* Check for xgm Rx fifo empty */ + /* Increased loop count to 1000 from 5 cover 1G and 100Mbps case */ if (t3_wait_op_done(adap, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + oft, - 0x80000000, 1, 5, 2)) { + 0x80000000, 1, 1000, 2)) { CH_ERR(adap, "MAC %d Rx fifo drain failed\n", macidx(mac)); return -1; @@ -191,11 +206,18 @@ static int t3b2_mac_reset(struct cmac *mac) F_DISPAUSEFRAMES | F_EN1536BFRAMES | F_RMFCS | F_ENJUMBO | F_ENHASHMCAST); - if (!macidx(mac)) + /* Restore the DROP_CFG */ + t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); + t3_write_reg(adap, A_TP_PIO_DATA, store); + + if (!idx) t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT0ACTIVE); else t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT1ACTIVE); + /* re-enable nic traffic */ + t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 1); + return 0; } @@ -332,15 +354,6 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu) return -EINVAL; t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu); - /* - * Adjust the PAUSE frame watermarks. We always set the LWM, and the - * HWM only if flow-control is enabled. - */ - hwm = max_t(unsigned int, MAC_RXFIFO_SIZE - 3 * mtu, - MAC_RXFIFO_SIZE * 38 / 100); - hwm = min(hwm, MAC_RXFIFO_SIZE - 8192); - lwm = min(3 * (int)mtu, MAC_RXFIFO_SIZE / 4); - if (adap->params.rev >= T3_REV_B2 && (t3_read_reg(adap, A_XGM_RX_CTRL + mac->offset) & F_RXEN)) { disable_exact_filters(mac); @@ -452,9 +465,12 @@ int t3_mac_enable(struct cmac *mac, int which) if (which & MAC_DIRECTION_TX) { t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); - t3_write_reg(adap, A_TP_PIO_DATA, 0xc0ede401); + t3_write_reg(adap, A_TP_PIO_DATA, + adap->params.rev == T3_REV_C ? + 0xc4ffff01 : 0xc0ede401); t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE); - t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx); + t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, + adap->params.rev == T3_REV_C ? 0 : 1 << idx); t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN); @@ -510,15 +526,12 @@ int t3b2_mac_watchdog_task(struct cmac *mac) struct adapter *adap = mac->adapter; struct mac_stats *s = &mac->stats; unsigned int tx_tcnt, tx_xcnt; - unsigned int tx_mcnt = s->tx_frames; - unsigned int rx_mcnt = s->rx_frames; - unsigned int rx_xcnt; + u64 tx_mcnt = s->tx_frames; int status; status = 0; tx_xcnt = 1; /* By default tx_xcnt is making progress */ tx_tcnt = mac->tx_tcnt; /* If tx_mcnt is progressing ignore tx_tcnt */ - rx_xcnt = 1; /* By default rx_xcnt is making progress */ if (tx_mcnt == mac->tx_mcnt && mac->rx_pause == s->rx_pause) { tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, A_XGM_TX_SPI4_SOP_EOP_CNT + @@ -529,11 +542,11 @@ int t3b2_mac_watchdog_task(struct cmac *mac) tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap, A_TP_PIO_DATA))); } else { - goto rxcheck; + goto out; } } else { mac->toggle_cnt = 0; - goto rxcheck; + goto out; } if ((tx_tcnt != mac->tx_tcnt) && (mac->tx_xcnt == 0)) { @@ -546,23 +559,6 @@ int t3b2_mac_watchdog_task(struct cmac *mac) } } else { mac->toggle_cnt = 0; - goto rxcheck; - } - -rxcheck: - if (rx_mcnt != mac->rx_mcnt) { - rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, - A_XGM_RX_SPI4_SOP_EOP_CNT + - mac->offset))) + - (s->rx_fifo_ovfl - - mac->rx_ocnt); - mac->rx_ocnt = s->rx_fifo_ovfl; - } else - goto out; - - if (mac->rx_mcnt != s->rx_frames && rx_xcnt == 0 && - mac->rx_xcnt == 0) { - status = 2; goto out; } @@ -570,8 +566,6 @@ out: mac->tx_tcnt = tx_tcnt; mac->tx_xcnt = tx_xcnt; mac->tx_mcnt = s->tx_frames; - mac->rx_xcnt = rx_xcnt; - mac->rx_mcnt = s->rx_frames; mac->rx_pause = s->rx_pause; if (status == 1) { t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0); -- GitLab From bf792094ef830117312b3990b63474320ec864c0 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Thu, 12 Mar 2009 21:14:19 +0000 Subject: [PATCH 3333/4982] cxgb3: detect mac link faults. The driver currently ignores the local or remote link faults raised at the mac layer. This patch fixes it. Our mac however only advertizes link events, so wait for the phy to stabilize the link, then enable mac link events interrupts. Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/adapter.h | 5 ++ drivers/net/cxgb3/common.h | 6 ++ drivers/net/cxgb3/cxgb3_main.c | 123 +++++++++++++++++++++++++++++- drivers/net/cxgb3/regs.h | 13 ++++ drivers/net/cxgb3/t3_hw.c | 134 ++++++++++++++++++++++++++++++++- drivers/net/cxgb3/xgmac.c | 13 ++-- 6 files changed, 285 insertions(+), 9 deletions(-) diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h index 66ce456614a..71eaa431371 100644 --- a/drivers/net/cxgb3/adapter.h +++ b/drivers/net/cxgb3/adapter.h @@ -68,6 +68,8 @@ struct port_info { struct net_device_stats netstats; int activity; __be32 iscsi_ipv4addr; + + int link_fault; /* link fault was detected */ }; enum { /* adapter flags */ @@ -241,6 +243,7 @@ struct adapter { struct delayed_work adap_check_task; struct work_struct ext_intr_handler_task; struct work_struct fatal_error_handler_task; + struct work_struct link_fault_handler_task; struct dentry *debugfs_root; @@ -283,6 +286,8 @@ void t3_os_ext_intr_handler(struct adapter *adapter); void t3_os_link_changed(struct adapter *adapter, int port_id, int link_status, int speed, int duplex, int fc); void t3_os_phymod_changed(struct adapter *adap, int port_id); +void t3_os_link_fault(struct adapter *adapter, int port_id, int state); +void t3_os_link_fault_handler(struct adapter *adapter, int port_id); void t3_sge_start(struct adapter *adap); void t3_sge_stop(struct adapter *adap); diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h index db4f4f575b6..9ee021e750c 100644 --- a/drivers/net/cxgb3/common.h +++ b/drivers/net/cxgb3/common.h @@ -280,6 +280,7 @@ struct mac_stats { unsigned long num_toggled; /* # times toggled TxEn due to stuck TX */ unsigned long num_resets; /* # times reset due to stuck TX */ + unsigned long link_faults; /* # detected link faults */ }; struct tp_mib_stats { @@ -701,6 +702,8 @@ int t3_phy_lasi_intr_handler(struct cphy *phy); void t3_intr_enable(struct adapter *adapter); void t3_intr_disable(struct adapter *adapter); void t3_intr_clear(struct adapter *adapter); +void t3_xgm_intr_enable(struct adapter *adapter, int idx); +void t3_xgm_intr_disable(struct adapter *adapter, int idx); void t3_port_intr_enable(struct adapter *adapter, int idx); void t3_port_intr_disable(struct adapter *adapter, int idx); void t3_port_intr_clear(struct adapter *adapter, int idx); @@ -708,6 +711,7 @@ int t3_slow_intr_handler(struct adapter *adapter); int t3_phy_intr_handler(struct adapter *adapter); void t3_link_changed(struct adapter *adapter, int port_id); +void t3_link_fault(struct adapter *adapter, int port_id); int t3_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc); const struct adapter_info *t3_get_adapter_info(unsigned int board_id); int t3_seeprom_read(struct adapter *adapter, u32 addr, __le32 *data); @@ -744,6 +748,8 @@ int t3_mc7_bd_read(struct mc7 *mc7, unsigned int start, unsigned int n, int t3_mac_reset(struct cmac *mac); void t3b_pcs_reset(struct cmac *mac); +void t3_mac_disable_exact_filters(struct cmac *mac); +void t3_mac_enable_exact_filters(struct cmac *mac); int t3_mac_enable(struct cmac *mac, int which); int t3_mac_disable(struct cmac *mac, int which); int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu); diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 9ff0452fcdd..d8be89621bf 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -170,6 +170,40 @@ static void link_report(struct net_device *dev) } } +void t3_os_link_fault(struct adapter *adap, int port_id, int state) +{ + struct net_device *dev = adap->port[port_id]; + struct port_info *pi = netdev_priv(dev); + + if (state == netif_carrier_ok(dev)) + return; + + if (state) { + struct cmac *mac = &pi->mac; + + netif_carrier_on(dev); + + /* Clear local faults */ + t3_xgm_intr_disable(adap, pi->port_id); + t3_read_reg(adap, A_XGM_INT_STATUS + + pi->mac.offset); + t3_write_reg(adap, + A_XGM_INT_CAUSE + pi->mac.offset, + F_XGM_INT); + + t3_set_reg_field(adap, + A_XGM_INT_ENABLE + + pi->mac.offset, + F_XGM_INT, F_XGM_INT); + t3_xgm_intr_enable(adap, pi->port_id); + + t3_mac_enable(mac, MAC_DIRECTION_TX); + } else + netif_carrier_off(dev); + + link_report(dev); +} + /** * t3_os_link_changed - handle link status changes * @adapter: the adapter associated with the link change @@ -197,10 +231,34 @@ void t3_os_link_changed(struct adapter *adapter, int port_id, int link_stat, if (link_stat != netif_carrier_ok(dev)) { if (link_stat) { t3_mac_enable(mac, MAC_DIRECTION_RX); + + /* Clear local faults */ + t3_xgm_intr_disable(adapter, pi->port_id); + t3_read_reg(adapter, A_XGM_INT_STATUS + + pi->mac.offset); + t3_write_reg(adapter, + A_XGM_INT_CAUSE + pi->mac.offset, + F_XGM_INT); + + t3_set_reg_field(adapter, + A_XGM_INT_ENABLE + pi->mac.offset, + F_XGM_INT, F_XGM_INT); + t3_xgm_intr_enable(adapter, pi->port_id); + netif_carrier_on(dev); } else { netif_carrier_off(dev); - pi->phy.ops->power_down(&pi->phy, 1); + + t3_xgm_intr_disable(adapter, pi->port_id); + t3_read_reg(adapter, A_XGM_INT_STATUS + pi->mac.offset); + t3_set_reg_field(adapter, + A_XGM_INT_ENABLE + pi->mac.offset, + F_XGM_INT, 0); + + if (is_10G(adapter)) + pi->phy.ops->power_down(&pi->phy, 1); + + t3_read_reg(adapter, A_XGM_INT_STATUS + pi->mac.offset); t3_mac_disable(mac, MAC_DIRECTION_RX); t3_link_start(&pi->phy, mac, &pi->link_config); } @@ -1173,6 +1231,10 @@ static int cxgb_close(struct net_device *dev) struct port_info *pi = netdev_priv(dev); struct adapter *adapter = pi->adapter; + /* Stop link fault interrupts */ + t3_xgm_intr_disable(adapter, pi->port_id); + t3_read_reg(adapter, A_XGM_INT_STATUS + pi->mac.offset); + t3_port_intr_disable(adapter, pi->port_id); netif_tx_stop_all_queues(dev); pi->phy.ops->power_down(&pi->phy, 1); @@ -1299,6 +1361,7 @@ static char stats_strings[][ETH_GSTRING_LEN] = { "CheckTXEnToggled ", "CheckResets ", + "LinkFaults ", }; static int get_sset_count(struct net_device *dev, int sset) @@ -1431,6 +1494,8 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats, *data++ = s->num_toggled; *data++ = s->num_resets; + + *data++ = s->link_faults; } static inline void reg_block_dump(struct adapter *ap, void *buf, @@ -2425,8 +2490,20 @@ static void check_link_status(struct adapter *adapter) struct net_device *dev = adapter->port[i]; struct port_info *p = netdev_priv(dev); - if (!(p->phy.caps & SUPPORTED_IRQ) && netif_running(dev)) + spin_lock_irq(&adapter->work_lock); + if (p->link_fault) { + spin_unlock_irq(&adapter->work_lock); + continue; + } + spin_unlock_irq(&adapter->work_lock); + + if (!(p->phy.caps & SUPPORTED_IRQ) && netif_running(dev)) { + t3_xgm_intr_disable(adapter, i); + t3_read_reg(adapter, A_XGM_INT_STATUS + p->mac.offset); + t3_link_changed(adapter, i); + t3_xgm_intr_enable(adapter, i); + } } } @@ -2553,9 +2630,23 @@ static void ext_intr_task(struct work_struct *work) { struct adapter *adapter = container_of(work, struct adapter, ext_intr_handler_task); + int i; + + /* Disable link fault interrupts */ + for_each_port(adapter, i) { + struct net_device *dev = adapter->port[i]; + struct port_info *p = netdev_priv(dev); + + t3_xgm_intr_disable(adapter, i); + t3_read_reg(adapter, A_XGM_INT_STATUS + p->mac.offset); + } + /* Re-enable link fault interrupts */ t3_phy_intr_handler(adapter); + for_each_port(adapter, i) + t3_xgm_intr_enable(adapter, i); + /* Now reenable external interrupts */ spin_lock_irq(&adapter->work_lock); if (adapter->slow_intr_mask) { @@ -2588,6 +2679,32 @@ void t3_os_ext_intr_handler(struct adapter *adapter) spin_unlock(&adapter->work_lock); } +static void link_fault_task(struct work_struct *work) +{ + struct adapter *adapter = container_of(work, struct adapter, + link_fault_handler_task); + int i; + + for_each_port(adapter, i) { + struct net_device *netdev = adapter->port[i]; + struct port_info *pi = netdev_priv(netdev); + + if (pi->link_fault) + t3_link_fault(adapter, i); + } +} + +void t3_os_link_fault_handler(struct adapter *adapter, int port_id) +{ + struct net_device *netdev = adapter->port[port_id]; + struct port_info *pi = netdev_priv(netdev); + + spin_lock(&adapter->work_lock); + pi->link_fault = 1; + queue_work(cxgb3_wq, &adapter->link_fault_handler_task); + spin_unlock(&adapter->work_lock); +} + static int t3_adapter_error(struct adapter *adapter, int reset) { int i, ret = 0; @@ -2704,7 +2821,6 @@ void t3_fatal_err(struct adapter *adapter) CH_ALERT(adapter, "FW status: 0x%x, 0x%x, 0x%x, 0x%x\n", fw_status[0], fw_status[1], fw_status[2], fw_status[3]); - } /** @@ -2962,6 +3078,7 @@ static int __devinit init_one(struct pci_dev *pdev, INIT_LIST_HEAD(&adapter->adapter_list); INIT_WORK(&adapter->ext_intr_handler_task, ext_intr_task); + INIT_WORK(&adapter->link_fault_handler_task, link_fault_task); INIT_WORK(&adapter->fatal_error_handler_task, fatal_error_task); INIT_DELAYED_WORK(&adapter->adap_check_task, t3_adap_check_task); diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h index aa08550ee99..1b5327b5a96 100644 --- a/drivers/net/cxgb3/regs.h +++ b/drivers/net/cxgb3/regs.h @@ -2215,6 +2215,15 @@ #define A_XGM_RX_EXACT_MATCH_LOW_8 0x854 +#define A_XGM_INT_STATUS 0x86c + +#define S_LINKFAULTCHANGE 9 +#define V_LINKFAULTCHANGE(x) ((x) << S_LINKFAULTCHANGE) +#define F_LINKFAULTCHANGE V_LINKFAULTCHANGE(1U) + +#define A_XGM_XGM_INT_ENABLE 0x874 +#define A_XGM_XGM_INT_DISABLE 0x878 + #define A_XGM_STAT_CTRL 0x880 #define S_CLRSTATS 2 @@ -2413,6 +2422,10 @@ #define V_XAUIPCSALIGNCHANGE(x) ((x) << S_XAUIPCSALIGNCHANGE) #define F_XAUIPCSALIGNCHANGE V_XAUIPCSALIGNCHANGE(1U) +#define S_XGM_INT 0 +#define V_XGM_INT(x) ((x) << S_XGM_INT) +#define F_XGM_INT V_XGM_INT(1U) + #define A_XGM_INT_CAUSE 0x8d8 #define A_XGM_XAUI_ACT_CTRL 0x8dc diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index 7c6ee0c9b6f..ff262a04ded 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c @@ -1153,6 +1153,38 @@ int t3_cim_ctl_blk_read(struct adapter *adap, unsigned int addr, return ret; } +static void t3_gate_rx_traffic(struct cmac *mac, u32 *rx_cfg, + u32 *rx_hash_high, u32 *rx_hash_low) +{ + /* stop Rx unicast traffic */ + t3_mac_disable_exact_filters(mac); + + /* stop broadcast, multicast, promiscuous mode traffic */ + *rx_cfg = t3_read_reg(mac->adapter, A_XGM_RX_CFG); + t3_set_reg_field(mac->adapter, A_XGM_RX_CFG, + F_ENHASHMCAST | F_DISBCAST | F_COPYALLFRAMES, + F_DISBCAST); + + *rx_hash_high = t3_read_reg(mac->adapter, A_XGM_RX_HASH_HIGH); + t3_write_reg(mac->adapter, A_XGM_RX_HASH_HIGH, 0); + + *rx_hash_low = t3_read_reg(mac->adapter, A_XGM_RX_HASH_LOW); + t3_write_reg(mac->adapter, A_XGM_RX_HASH_LOW, 0); + + /* Leave time to drain max RX fifo */ + msleep(1); +} + +static void t3_open_rx_traffic(struct cmac *mac, u32 rx_cfg, + u32 rx_hash_high, u32 rx_hash_low) +{ + t3_mac_enable_exact_filters(mac); + t3_set_reg_field(mac->adapter, A_XGM_RX_CFG, + F_ENHASHMCAST | F_DISBCAST | F_COPYALLFRAMES, + rx_cfg); + t3_write_reg(mac->adapter, A_XGM_RX_HASH_HIGH, rx_hash_high); + t3_write_reg(mac->adapter, A_XGM_RX_HASH_LOW, rx_hash_low); +} /** * t3_link_changed - handle interface link changes @@ -1170,9 +1202,32 @@ void t3_link_changed(struct adapter *adapter, int port_id) struct cphy *phy = &pi->phy; struct cmac *mac = &pi->mac; struct link_config *lc = &pi->link_config; + int force_link_down = 0; phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc); + if (!lc->link_ok && link_ok) { + u32 rx_cfg, rx_hash_high, rx_hash_low; + u32 status; + + t3_xgm_intr_enable(adapter, port_id); + t3_gate_rx_traffic(mac, &rx_cfg, &rx_hash_high, &rx_hash_low); + t3_write_reg(adapter, A_XGM_RX_CTRL + mac->offset, 0); + t3_mac_enable(mac, MAC_DIRECTION_RX); + + status = t3_read_reg(adapter, A_XGM_INT_STATUS + mac->offset); + if (status & F_LINKFAULTCHANGE) { + mac->stats.link_faults++; + force_link_down = 1; + } + t3_open_rx_traffic(mac, rx_cfg, rx_hash_high, rx_hash_low); + + if (force_link_down) { + t3_os_link_fault_handler(adapter, port_id); + return; + } + } + if (lc->requested_fc & PAUSE_AUTONEG) fc &= lc->requested_fc; else @@ -1202,6 +1257,57 @@ void t3_link_changed(struct adapter *adapter, int port_id) t3_os_link_changed(adapter, port_id, link_ok, speed, duplex, fc); } +void t3_link_fault(struct adapter *adapter, int port_id) +{ + struct port_info *pi = adap2pinfo(adapter, port_id); + struct cmac *mac = &pi->mac; + struct cphy *phy = &pi->phy; + struct link_config *lc = &pi->link_config; + int link_ok, speed, duplex, fc, link_fault; + u32 rx_cfg, rx_hash_high, rx_hash_low; + + t3_gate_rx_traffic(mac, &rx_cfg, &rx_hash_high, &rx_hash_low); + + if (adapter->params.rev > 0 && uses_xaui(adapter)) + t3_write_reg(adapter, A_XGM_XAUI_ACT_CTRL + mac->offset, 0); + + t3_write_reg(adapter, A_XGM_RX_CTRL + mac->offset, 0); + t3_mac_enable(mac, MAC_DIRECTION_RX); + + t3_open_rx_traffic(mac, rx_cfg, rx_hash_high, rx_hash_low); + + link_fault = t3_read_reg(adapter, + A_XGM_INT_STATUS + mac->offset); + link_fault &= F_LINKFAULTCHANGE; + + phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc); + + if (link_fault) { + lc->link_ok = 0; + lc->speed = SPEED_INVALID; + lc->duplex = DUPLEX_INVALID; + + t3_os_link_fault(adapter, port_id, 0); + + /* Account link faults only when the phy reports a link up */ + if (link_ok) + mac->stats.link_faults++; + + msleep(1000); + t3_os_link_fault_handler(adapter, port_id); + } else { + if (link_ok) + t3_write_reg(adapter, A_XGM_XAUI_ACT_CTRL + mac->offset, + F_TXACTENABLE | F_RXEN); + + pi->link_fault = 0; + lc->link_ok = (unsigned char)link_ok; + lc->speed = speed < 0 ? SPEED_INVALID : speed; + lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex; + t3_os_link_fault(adapter, port_id, link_ok); + } +} + /** * t3_link_start - apply link configuration to MAC/PHY * @phy: the PHY to setup @@ -1360,11 +1466,11 @@ static int t3_handle_intr_status(struct adapter *adapter, unsigned int reg, V_TX1TPPARERRENB(M_TX1TPPARERRENB) | \ V_RXTPPARERRENB(M_RXTPPARERRENB) | \ V_MCAPARERRENB(M_MCAPARERRENB)) +#define XGM_EXTRA_INTR_MASK (F_LINKFAULTCHANGE) #define PL_INTR_MASK (F_T3DBG | F_XGMAC0_0 | F_XGMAC0_1 | F_MC5A | F_PM1_TX | \ F_PM1_RX | F_ULP2_TX | F_ULP2_RX | F_TP1 | F_CIM | \ F_MC7_CM | F_MC7_PMTX | F_MC7_PMRX | F_SGE3 | F_PCIM0 | \ F_MPS0 | F_CPL_SWITCH) - /* * Interrupt handler for the PCIX1 module. */ @@ -1722,10 +1828,20 @@ static int mac_intr_handler(struct adapter *adap, unsigned int idx) mac->stats.xaui_pcs_ctc_err++; if (cause & F_XAUIPCSALIGNCHANGE) mac->stats.xaui_pcs_align_change++; + if (cause & F_XGM_INT) { + t3_set_reg_field(adap, + A_XGM_INT_ENABLE + mac->offset, + F_XGM_INT, 0); + mac->stats.link_faults++; + + t3_os_link_fault_handler(adap, idx); + } t3_write_reg(adap, A_XGM_INT_CAUSE + mac->offset, cause); + if (cause & XGM_INTR_FATAL) t3_fatal_err(adap); + return cause != 0; } @@ -1931,6 +2047,22 @@ void t3_intr_clear(struct adapter *adapter) t3_read_reg(adapter, A_PL_INT_CAUSE0); /* flush */ } +void t3_xgm_intr_enable(struct adapter *adapter, int idx) +{ + struct port_info *pi = adap2pinfo(adapter, idx); + + t3_write_reg(adapter, A_XGM_XGM_INT_ENABLE + pi->mac.offset, + XGM_EXTRA_INTR_MASK); +} + +void t3_xgm_intr_disable(struct adapter *adapter, int idx) +{ + struct port_info *pi = adap2pinfo(adapter, idx); + + t3_write_reg(adapter, A_XGM_XGM_INT_DISABLE + pi->mac.offset, + 0x7ff); +} + /** * t3_port_intr_enable - enable port-specific interrupts * @adapter: associated adapter diff --git a/drivers/net/cxgb3/xgmac.c b/drivers/net/cxgb3/xgmac.c index 4bd0901a97a..f87f9435049 100644 --- a/drivers/net/cxgb3/xgmac.c +++ b/drivers/net/cxgb3/xgmac.c @@ -218,6 +218,9 @@ static int t3b2_mac_reset(struct cmac *mac) /* re-enable nic traffic */ t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 1); + /* Set: re-enable NIC traffic */ + t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 1); + return 0; } @@ -258,7 +261,7 @@ int t3_mac_set_num_ucast(struct cmac *mac, int n) return 0; } -static void disable_exact_filters(struct cmac *mac) +void t3_mac_disable_exact_filters(struct cmac *mac) { unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_LOW_1; @@ -269,7 +272,7 @@ static void disable_exact_filters(struct cmac *mac) t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1); /* flush */ } -static void enable_exact_filters(struct cmac *mac) +void t3_mac_enable_exact_filters(struct cmac *mac) { unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_HIGH_1; @@ -356,7 +359,7 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu) if (adap->params.rev >= T3_REV_B2 && (t3_read_reg(adap, A_XGM_RX_CTRL + mac->offset) & F_RXEN)) { - disable_exact_filters(mac); + t3_mac_disable_exact_filters(mac); v = t3_read_reg(adap, A_XGM_RX_CFG + mac->offset); t3_set_reg_field(adap, A_XGM_RX_CFG + mac->offset, F_ENHASHMCAST | F_COPYALLFRAMES, F_DISBCAST); @@ -368,14 +371,14 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu) if (t3_wait_op_done(adap, reg + mac->offset, F_RXFIFO_EMPTY, 1, 20, 5)) { t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v); - enable_exact_filters(mac); + t3_mac_enable_exact_filters(mac); return -EIO; } t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, V_RXMAXPKTSIZE(M_RXMAXPKTSIZE), V_RXMAXPKTSIZE(mtu)); t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v); - enable_exact_filters(mac); + t3_mac_enable_exact_filters(mac); } else t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, V_RXMAXPKTSIZE(M_RXMAXPKTSIZE), -- GitLab From d9507a532acd25588b0d7957c660da35de41701b Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Thu, 12 Mar 2009 21:14:24 +0000 Subject: [PATCH 3334/4982] cxgb3: update FW Update FW to 7.1 Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/version.h | 2 +- firmware/Makefile | 2 +- firmware/WHENCE | 2 +- firmware/cxgb3/t3fw-7.0.0.bin.ihex | 1881 --------------------------- firmware/cxgb3/t3fw-7.1.0.bin.ihex | 1885 ++++++++++++++++++++++++++++ 5 files changed, 1888 insertions(+), 1884 deletions(-) delete mode 100644 firmware/cxgb3/t3fw-7.0.0.bin.ihex create mode 100644 firmware/cxgb3/t3fw-7.1.0.bin.ihex diff --git a/drivers/net/cxgb3/version.h b/drivers/net/cxgb3/version.h index b1b25c37aa1..6f6c30c50dd 100644 --- a/drivers/net/cxgb3/version.h +++ b/drivers/net/cxgb3/version.h @@ -39,6 +39,6 @@ /* Firmware version */ #define FW_VERSION_MAJOR 7 -#define FW_VERSION_MINOR 0 +#define FW_VERSION_MINOR 1 #define FW_VERSION_MICRO 0 #endif /* __CHELSIO_VERSION_H */ diff --git a/firmware/Makefile b/firmware/Makefile index aa2e02d72c0..c6af61b4e51 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -35,7 +35,7 @@ fw-shipped-$(CONFIG_CASSINI) += sun/cassini.bin fw-shipped-$(CONFIG_COMPUTONE) += intelliport2.bin fw-shipped-$(CONFIG_CHELSIO_T3) += cxgb3/t3b_psram-1.1.0.bin \ cxgb3/t3c_psram-1.1.0.bin \ - cxgb3/t3fw-7.0.0.bin + cxgb3/t3fw-7.1.0.bin fw-shipped-$(CONFIG_DVB_TTUSB_BUDGET) += ttusb-budget/dspbootcode.bin fw-shipped-$(CONFIG_E100) += e100/d101m_ucode.bin e100/d101s_ucode.bin \ e100/d102e_ucode.bin diff --git a/firmware/WHENCE b/firmware/WHENCE index ea4fc2e00c6..00b6e3c0905 100644 --- a/firmware/WHENCE +++ b/firmware/WHENCE @@ -368,7 +368,7 @@ Driver: cxgb3 - Chelsio Terminator 3 1G/10G Ethernet adapter File: cxgb3/t3b_psram-1.1.0.bin.ihex File: cxgb3/t3c_psram-1.1.0.bin.ihex -file: cxgb3/t3fw-7.0.0.bin.ihex +file: cxgb3/t3fw-7.1.0.bin.ihex License: GPLv2 or OpenIB.org BSD license, no source visible diff --git a/firmware/cxgb3/t3fw-7.0.0.bin.ihex b/firmware/cxgb3/t3fw-7.0.0.bin.ihex deleted file mode 100644 index e66117938e8..00000000000 --- a/firmware/cxgb3/t3fw-7.0.0.bin.ihex +++ /dev/null @@ -1,1881 +0,0 @@ -:1000000060007400200380002003700000001000D6 -:1000100000002000E100028400070000E1000288E7 -:1000200000010000E0000000E00000A0010000006E -:1000300044444440E3000183200200002001E0002A -:100040002001FF101FFFD0001FFFC000E300043C91 -:1000500002000000200069541FFFC5802000699C39 -:100060001FFFC584200069DC1FFFC58820006A507F -:100070001FFFC58C200003C0C00000E43100EA313E -:1000800000A13100A03103020002ED306E2A05000C -:10009000ED3100020002160012FFDBC03014FFDA5F -:1000A000D30FD30FD30F03431F244C107249F0D347 -:1000B0000FD30FD30F12FFD5230A00240A00D30F4A -:1000C000D30FD30F03431F244C107249F0D30FD327 -:1000D0000FD30F14FFCE03421F14FFCB03421F1296 -:1000E000FFCCC0302D37302D37342D37382D373CED -:1000F000233D017233ED00020012FFC4C0302F37E0 -:10010000002F37102F37202F3730233D017233ED6A -:1001100000020012FFBEC0302737002737102737F4 -:1001200020273730233D017233ED03020012FFB95F -:1001300013FFBA0C0200932012FFB913FFB90C028F -:1001400000932012FFB8C0319320822012FFB71312 -:10015000FFB7932012FFB715FFB316FFB6C030D715 -:100160002005660160001B00000000000000000088 -:10017000043605000200D30FD30F7531140747145E -:1001800005330C0704437631E60436057539ED0076 -:10019000020012FFA715FFA3C030D72060000600A1 -:1001A00007471405330C070443043E057539F00373 -:1001B000020012FFA1C03014FFA1D30FD30FD30F41 -:1001C0009340B4447249F2D30FD30FD30F14FF9B63 -:1001D000834014FF9B834012FF9B230A0014FF9A65 -:1001E000D30FD30FD30F9340B4447249F2D30FD33C -:1001F0000FD30F14FF95834012FF95CA20832084EC -:10020000218522BC22743B108650B4559630B433FD -:100210007433F463FFE6000000653FE0655FDD12C4 -:10022000FF7CC03028374028374428374828374CCF -:10023000233D017233ED03020000020012FF7AC079 -:1002400032032E0503020012FF7813FF819320C0B2 -:1002500011014931004831010200C00014FF7E0441 -:10026000D23115FF7D945014FF7D04D33115FF7CEE -:10027000945014FF7C04D43115FF7C24560014FFE5 -:100280007B04D53115FF7B24560010FF7A03000054 -:10029000000000000000000000000000000000005E -:1002A000000000000000000000000000000000004E -:1002B000000000000000000000000000000000003E -:1002C000000000000000000000000000000000002E -:1002D000000000000000000000000000000000001E -:1002E000000000000000000000000000000000000E -:1002F00000000000000000000000000000000000FE -:1003000000000000000000000000000000000000ED -:1003100000000000000000000000000000000000DD -:1003200000000000000000000000000000000000CD -:1003300000000000000000000000000000000000BD -:1003400000000000000000000000000000000000AD -:10035000000000000000000000000000000000009D -:10036000000000000000000000000000000000008D -:10037000000000000000000000000000000000007D -:10038000000000000000000000000000000000006D -:10039000000000000000000000000000000000005D -:1003A000000000000000000000000000000000004D -:1003B000000000000000000000000000000000003D -:1003C000000000000000000000000000000000002D -:1003D000000000000000000000000000000000001D -:1003E000000000000000000000000000000000000D -:1003F00000000000000000000000000000000000FD -:1004000000000000000000000000000000000000EC -:1004100000000000000000000000000000000000DC -:1004200063FFFC000000000000000000000000006E -:100430000000000000000000000000001FFC0000A1 -:100440001FFC0000E30005C81FFC00001FFC0000AB -:10045000E30005C81FFC00001FFC0000E30005C806 -:100460001FFFC0001FFFC000E30005C81FFFC00042 -:100470001FFFC018E30005C81FFFC0181FFFC018EA -:10048000E30005E01FFFC0181FFFC288E30005E07E -:100490001FFFC2881FFFC288E30008501FFFC290E1 -:1004A0001FFFC57CE3000850200000002000016A07 -:1004B000E3000B3C2000018020000180E3000CA839 -:1004C0002000020020000203E3000CA82000021C10 -:1004D00020000220E3000CAC2000022020000226B5 -:1004E000E3000CB02000023C20000240E3000CB806 -:1004F0002000024020000249E3000CBC2000024C16 -:1005000020000250E3000CC82000025020000259D5 -:10051000E3000CCC2000025C20000260E3000CD859 -:100520002000026020000269E3000CDC2000026C65 -:1005300020000270E3000CE8200002702000027925 -:10054000E3000CEC2000028C2000028CE3000CF88D -:100550002000029020000293E3000CF8200002AC7F -:10056000200002B0E3000CFC200002D0200002F2C8 -:10057000E3000D00200003B0200003B0E3000D24D1 -:10058000200003B0200003B0E3000D24200003B0DE -:10059000200003B0E3000D24200003B0200003B0CE -:1005A000E3000D24200003B020006B74E3000D2451 -:1005B00020006B7420006B74E30074E800000000FE -:1005C00000000000000000001FFC00001FFC0000F5 -:1005D0001FFFC5801FFFC67020006B7820006B785E -:1005E000DEFFFE000000080CDEADBEEF1FFFC29074 -:1005F0001FFCFE001FFFC0841FFFC5C030000000AD -:10060000003FFFFF8040000010000000080FFFFFC8 -:100610001FFFC25D000FFFFF804FFFFF8000000043 -:1006200000000880B000000560500000600000007D -:1006300040000011350000004100000010000001E2 -:1006400020000000000010007FFFFFFF40000000BE -:1006500005000000800000190400000000000800F0 -:1006600010000005806000007000000020000009FC -:10067000001FF8008000001EA0000000F80000002D -:100680000800000007FFFFFF1800000001008001C4 -:10069000420000001FFFC20D1FFFC0CC0001008000 -:1006A000604000001A0000000C0000000000300054 -:1006B000600008008000001C000100008000001A9B -:1006C00080000018FC0000008000000100004000D5 -:1006D000800004000300000050000003FFFFBFFF84 -:1006E00000000FFF1FFFC390FFFFF000000016D0B7 -:1006F0000000FFF7A50000001FFFC4A01FFFC451AA -:100700000001000800000B20202FFF801FFFC445C0 -:1007100000002C00FFFEFFF800FFFFFF1FFFC56871 -:1007200000002000FFFFDFFF0000FFEF01001100CD -:100730001FFFC4611FFFC3C21FFFC4101FFFC5906E -:10074000FFFFEFFF0000FFFB1FFFBE90FFFFF7FF63 -:100750001FFFC0540000FFFD0001FBD01FFFC5B00C -:100760001FFFC6601FFFC591E0FFFE000000800074 -:100770001FFFC52C1FFFC5B41FFFC0581FFFC4D0EB -:100780001FFCFFD800010081E100060000002710D7 -:100790001FFCFE301FFCFE70E10002001FFFC52899 -:1007A0001FFFC5400003D0901FFFC5542B5063802E -:1007B0002B5079802B5090802B50A6801FFFC4595E -:1007C0000100110F202FFE0020300080202FFF009D -:1007D0000000FFFF0001FFF82B50B2002B50B208C1 -:1007E000000100102B50B1802B50B2802B50BA006A -:1007F000000100112B50BD282B50BC802B50BDA0F8 -:1008000020300000DFFFFE005000000200C00000AA -:1008100002000000FFFFF7F41FFFC05C000FF800AC -:1008200004400000001000000C4000001C400000CC -:10083000E00000A01FFFC5301FFD00081FFFC544DA -:100840001FFFC5581FFFC56CE1000690E10006ECD4 -:100850000100000000000000000000000000000097 -:100860002010004020100040201000402014008084 -:10087000200C0000200C0000200C00002010004084 -:10088000201400802014008020140080201800C054 -:10089000201C0100201C0100201C01002020014020 -:1008A000201800C0201800C0201800C0201C010023 -:1008B000201800C0201800C0201800C0201C010013 -:1008C000202001402020014020200140202009401C -:1008D00020200940202009402020094020240980B0 -:1008E000FFFFFFFFFFFFFFFFFFFFFFFF0000000014 -:1008F00000000000000000000000000000000000F8 -:100900002000525420005124200052542000525400 -:1009100020005060200050602000506020004E9465 -:1009200020004E9420004E8C20004DFC20004CA056 -:1009300020004A88200048880000000000000000D5 -:1009400020005224200050F02000519420005194A7 -:1009500020004F3820004F3820004F3820004F38FB -:1009600020004F3820004E8420004F3820004BC418 -:1009700020004A3C20004838000000000000000031 -:1009800020000B702000384C200004C02000442CB4 -:1009900020000B6820003F40200003F0200043ECC3 -:1009A0002000481420003C5020003B6C200037C839 -:1009B00020003654200033CC20002EF8200039CC03 -:1009C00020002B5C200027942000648C2000232032 -:1009D0002000200420001FB820001CA4200017B015 -:1009E000200014F020000D8C20000BB4200010BC5F -:1009F000200012A02000413020003C0420000B7891 -:100A0000200004C000000000000000000000000002 -:100A100000000000000000000000000000000000D6 -:100A200000000000000000000000000000000000C6 -:100A300000000000000000000000000000000000B6 -:100A400000000000000000000000000000000000A6 -:100A50000000000000000000000000000000000096 -:100A60000000000000000000000000000000000086 -:100A70000000000000000000000000000000000076 -:100A8000000000003264000000000000326400003A -:100A90006400640064006400640064006400640036 -:100AA0000000000000000000000000000000000046 -:100AB0000000000000000000000000000000000036 -:100AC0000000000000000000000000000000000026 -:100AD0000000000000000000000000000000000016 -:100AE00000000000000000000000100000000000F6 -:100AF00000000000000000000000000000000000F6 -:100B000000001000000000000000000000000000D5 -:100B100000000000004323800000000000000000EF -:100B200000000000000000000000000000000000C5 -:100B3000000000000000000000000000005C9401C4 -:100B40005D94025E94035F94004300000000000087 -:100B50000000000000000000000000000000000095 -:100B60000000000000000000000000000000000085 -:100B7000000000000000000000000000005C900188 -:100B80005D90025E90035F90005300000000000043 -:100B90000000000000000000000000000000000055 -:100BA0000000000000000000000000000000000045 -:100BB000000000000000000000000000009C940005 -:100BC0001D90019D94029E94039F9404089405092E -:100BD00094060A94070B94004300000000000000F4 -:100BE0000000000000000000000000000000000005 -:100BF000000000000000000000000000009C9001C8 -:100C00009D90029E90071D90039F90047890057917 -:100C100090067A90077B90005300000000000000CF -:100C200000000000000000000000000000000000C4 -:100C300000000000000000000000000000DC940044 -:100C40001D9001DD9402DE9403DF940404940505F5 -:100C5000940606940707940808940909940A0A94CC -:100C60000B0B940043000000000000000000000097 -:100C700000000000000000000000000000DC900107 -:100C8000DD9002DE900B1D9003DF9004B49005B55B -:100C90009006B69007B79008B89009B9900ABA9034 -:100CA0000BBB90005300000063FFFC002000693084 -:100CB00010FFFF0A000000002000695400D231102C -:100CC000FFFE0A00000000002000699C00D33110E4 -:100CD000FFFE0A0000000000200069DC00D4311093 -:100CE000FFFE0A000000000020006A5000D531100D -:100CF000FFFE0A000000000063FFFC00E00000A00F -:100D000012FFF78220028257C82163FFFC12FFF313 -:100D100003E83004EE3005C030932094219522631F -:100D2000FFFC00001FFFD000000400201FFFC58053 -:100D30001FFFC670200A0011FFFB13FFFB03E63103 -:100D400001020016FFFA17FFFAD30F776B069060C7 -:100D5000B4667763F85415265419D90F140063FF4D -:100D6000F90000006C1004C020D10F006C1006C008 -:100D7000C71AEF060D4911D830D7201BEF05BC224A -:100D80008572AB76837105450B957209330C23761A -:100D900001723B05233D08237601A39D19EEFE7DDC -:100DA0006326C021C0E0032E380E0E42C8EE29A6ED -:100DB0007E6D4A0500808800308C8271D10FC0F0B2 -:100DC000082F387FC0EA63FFE49210037F0CABFF6B -:100DD0000F3D12DB802EDC100E4E36C021C05003BA -:100DE0002538221200050542CB5029A67E6DEA0562 -:100DF00000B08800308CBC76C050A8F3C081068556 -:100E000038050542CA5129A67E0D480CD30F6D8ABC -:100E10000500308800208C8271D10F00C061C05065 -:100E200008653875C0C663FFC0C0B0038B387BC08F -:100E3000D763FFD16C101216EED82A221E2E221D67 -:100E4000C0D07AE11B2CA000D7A028CCE96481484F -:100E500029CCE8649341C1B97BC12569CC1B6000F2 -:100E6000222CD000D7D028CCE964815429CCE86466 -:100E700093BAC1B97BC10968CC09C020D10F000069 -:100E8000002D25028C32C0900C6F5065F586292408 -:100E900067090847658582B44927200C18EEC00C05 -:100EA0007F11A8FF28F286DB707893026005541941 -:100EB000EEBC09790A2992A36890082822000988C3 -:100EC0000C65853F29F28564953929161A655563A5 -:100ED0007AE104DBA0600001C0B022161B8DB412C1 -:100EE000EEB10D881482240D0D47A82218EEAF092B -:100EF000DD10082202929018EEAD12EEAE08C80185 -:100F00000D88020242021DEEAA92910D880298926B -:100F100022B0232DB02204281006DD100242120850 -:100F2000DD0228B0210722100C88100288020D88EB -:100F30000212EEA18D3302DD0182340D88029893F6 -:100F400092B992948DB582399D9588B68D389896D0 -:100F500088B792999D989897C0D028F28512EE97FD -:100F600008480BA2722D24CF28F68522121B655447 -:100F7000DE7AE104DBA0600001C0B064BEFB2CB0EF -:100F80000728B000DA2006880A28824CC0D10B80DE -:100F900000DBA065AFE763FEE02EA0032B2067D93E -:100FA000E0D4E065B1AB8B320BFC5064C4B218EEF8 -:100FB000848F2A08B80108FF0C64F2CDC09260014A -:100FC0008A2AD003292067D4A06594C98B320BFCF0 -:100FD0005064C48C1FEE7B8E2A0FBF017FE9DC8C2E -:100FE000330CE8506484B4C0B00CA5118F592B1693 -:100FF000128A578E582A1611DBE0AAFA7FAB01B18C -:10100000EB75CE599E1F8937951CAF98981D798B2B -:101010000825160C29EC0129160F9A168A1D851F22 -:101020002A16192A0A007BE30A7BE9052B12067FA0 -:10103000BB01C0A165A4698B35C0A0C08078E30462 -:1010400064E3B5C0A165A458891C2916170C4A543D -:101050002A1616BCAA2A16186000AF0000008837AE -:10106000893628161429161508F80C09E90C2916D2 -:1010700013981E78FB07281213B088281613891EB0 -:101080009A189F172A1213C0F02916197BE30C7BBC -:10109000E9078E172B12087EBB01C0F165F406C06C -:1010A000B02F121988352E12129819281211AAEE93 -:1010B000AF8F78FB022EEC019F138F199F12C0F0A7 -:1010C0007BE30C7EB9078913281202798B01C0F1EA -:1010D00065F3D22516172912150C4F54C0E12F16AF -:1010E00016BCFF2F161800F10400EE1A2F1214B0D0 -:1010F000EE0EF8130988010FEE012F1219A8AAAEFF -:10110000FE7FEB01B1AAD5A02E16192B1219DA50C9 -:101110002C12185818D3C0D0C0902E121907480AA4 -:101120002C1218DAB08F34C0B1AAFF00C1042A1201 -:10113000162F86162C121700BB1AB0BB0EBE019ECE -:10114000C90BFB1305BB019BC82A7410292467290E -:1011500070038E75B19F2F7403B0EE0E4E0C65EDCB -:10116000182820672D25026583132A221E29221D97 -:101170007A9104DBA0600001C0B064BCFC2CB00715 -:1011800028B000DA2006880A28824CC0D10B8000E3 -:10119000DBA065AFE763FCE189AAB199659094890A -:1011A000341BEE0899AA88331FEE0208485428A47D -:1011B0002C8E2A8C320FEE020BCB017EB9640C4BC5 -:1011C000516FB25E8B3375B6592CA0130BEE510ED6 -:1011D000CE010E0E410C0C417EC9472FA012B0FF6C -:1011E00065F2DD8E378CA88B368FA97CB3077BC95F -:1011F000027EFB01C0D1CED98835DDB00E8E0878D5 -:10120000EB01B1BD89A7DAC00F9B0879BB022ACCDC -:1012100001DCB0C0B07DA3077AD9027CEB01C0B17C -:1012200064B163C091292467C020D10F008BDAB16B -:10123000BB64B0C02C20672D250265C2281DEDDCE3 -:101240008C321FEDE10DCD010FDD0C65D1C10C4FCE -:10125000516FF2026001B8C0902924670908476500 -:10126000820F7AE104DBA0600001C0B064BC0A2CEC -:10127000B00728B000DA2006880A28824CC0D10BBB -:101280008000DBA065AFE763FBEF8C330CE95064B3 -:1012900092090CEF11AFAF2F16178EF885F7DBE030 -:1012A0008FF9251610A5F57F5B022BEC010CA850D9 -:1012B0006580DD8837DAE0AF8929160A789B022A33 -:1012C000EC019514891AD5A02916192A0A007BE386 -:1012D0000A7BE9052B12047FBB01C0A165A1C18B6C -:1012E00035C0A0C08078E30464E104C0A164AD5CB3 -:1012F0006001AD00008E3419EDB39EDA8C331BED26 -:10130000AC0C4C542CD42C8A2A8C320BAA0209C95E -:10131000010A990C659F0B0C4F516EF20263FF029C -:101320008B330BA850648EFA29D0130BEA510A9A1A -:10133000010A0A410909410A990C659EE52BD01260 -:10134000B0BB65B188C0A08E378CD82B32062FD2A7 -:10135000097CB3077BC9027EFB01C0A165AEC388CF -:1013600035D3B0AE8E78EB01B1B389D7DAC0AF9B7D -:1013700079BB01B1CADCB0C0B073A3077A39027C73 -:10138000EB01C0B165BE9BC090292467C020D10F7E -:10139000008A3688372A16152816140AEA0C08F827 -:1013A0000C981B78FB01B0AA9F158F1B2F16192FC5 -:1013B0000A007BE30A7BE905281205785B01C0F18E -:1013C00065F0E2AADE8B352F1219291210C050AF3A -:1013D0009F79FB01B1EE9F11C0F075E30A7E5905BC -:1013E00028120178BB01C0F164FCEA6000B700007C -:1013F0007FB30263FEF663FEF17FB30263FC4563D5 -:10140000FC4000006450A4DA205815C8C020D10F59 -:10141000C09163FE43C09163FA73DA20DB70C0D1E0 -:101420002E0A80C09A2924682C70075814B8D2A0BC -:10143000D10F000019ED6603480B9810088B0209C4 -:1014400029087983022B8DF829121A63FA8B000080 -:101450002A2C74DB40580E442E221D2A221E63FBC8 -:101460000FC09163FCE5022A0258024C0AA2020650 -:101470000000022A025802490AA202060000DB709C -:10148000DA20C0D12E0A80C0CE2C24682C700758D8 -:10149000149FC020D10FD9A063FCB600C09463FC98 -:1014A000AAC09663FCA5C09663FCA0002A2C74DB3E -:1014B00030DC405BFE2EC2D02DA4002B200C63FF3D -:1014C000458F358EA77FEB0263FEBB63FD548935E4 -:1014D00088D7798B0263FEAE63FD47006C1004C0B1 -:1014E00020D10F006C1004C020D10F006C10042B11 -:1014F000221E28221DC0A0C0942924062A25027B72 -:101500008901DBA0C9B913ED24DA2028B0002CB082 -:101510000703880A28824CC0D10B8000DBA065AF8E -:10152000E7C020D10F0000006C100602260229201F -:1015300006C0E0689805289CF96581202A61021799 -:10154000ED170A0A4C65A0F02B729E1AED136FB8C6 -:10155000026000F42AA22668A0098B60D30F0ABBA0 -:101560000C65B0E42A729D64A0DE2B600C0CBC11EB -:1015700007CC082DC2866FD9026000D71DED090D7A -:10158000BD0A2DD2A368D0078F600DFF0C65F0C394 -:1015900022C285C0F06420BB1DED0E68434D18EDDE -:1015A0000D8C6B08CC029C208A6008AA110DAA023F -:1015B0009A21896A9924883298252C610408CC11D3 -:1015C0009C271CECFE0CBA11A7AA29A285ACBC2F43 -:1015D000C4CF299C2829A685C85A2A6C74DB405898 -:1015E0000DE2D2A0D10FD2E0D10F0000289CF96407 -:1015F00080912C60668931B1CC0C0C472C64666FED -:10160000C669709E661AECF48C30896B0C8C400BAA -:10161000CC100C99020A9902992088600888110D53 -:10162000880298218C339C238A329A22896A9924D1 -:101630008834982563FF820000CC57DA60DB30DC09 -:10164000405814A7C020D10F00DA60C0B658153733 -:1016500063FFE500DA6058153563FFDC00DA20DB54 -:1016600030DC40DD505815B7D2A0D10F9E102B6151 -:10167000045813C81DECD78E102B600CC0F02F64DB -:101680006663FF80296123C08879830263FF752E1A -:1016900016002C60662B61042CCC010C0C472C64CA -:1016A000665813BC1DECCB8E102B600CC0F02F6461 -:1016B0006663FF506C1004C0B7C0A116ECC815ECEF -:1016C000BAD720D840B822C040053502967195702F -:1016D00002A438040442C94B1AECAD19ECAE29A699 -:1016E0007EC140D30F6D4A0500808800208C220AFD -:1016F00088A272D10FC05008A53875B0E363FFD738 -:101700006C100893149412292006655270C07168F9 -:1017100098052A9CF965A28016ECA12921028A1459 -:1017200009094C6590C78AA00A6A512AACFD65A0D8 -:10173000BCCC5FDB30DA208C12581469C0519A148B -:10174000C7BF9BA98E142EE20968E0602F629E1D20 -:10175000EC926FF8026000812DD22668D0052F220E -:10176000007DF9752C629DC79064C06D9C118A1430 -:101770002B200C2AA0200CBD11A6DD0A4F14BFA8F7 -:1017800009880129D286AF88288C09798B551FECEE -:10179000840FBF0A2FF2A368F0052822007F894337 -:1017A00029D285D49065907760003D00002B200CF5 -:1017B0001FEC7C0CBD11A6DD29D2860FBF0A6E96E8 -:1017C000102FF2A368F00488207F890529D285654F -:1017D0009155DA205814D5600013DA20C0B6581499 -:1017E000D3600009C09063FFB9DA205814D089147F -:1017F000899109FE506551CC8C128D14DA20DBD012 -:101800008DD09E100D6D515813419A1464A1F0C7EC -:101810005F8FA195A9C0510F0F479F1263FEFB0078 -:10182000C091C0F12820062C2066288CF9A7CC0C8A -:101830000C472C24666FC6088D148DD170DE01C054 -:1018400090DD90648141C9D28A112B210458135133 -:101850008A14C0B02B24668EA92AA020C1701CEC6B -:101860005B0E281415EC508E148556AC2C9C132E50 -:10187000EC28A855DDE07CE3022DEDF8D3D00A7703 -:1018800036DA40DB50DC305BFF8BD4A02E200CB46A -:1018900055290A88C0C01BEC490CEF11A6FF28F29D -:1018A00085ABEE2CE4CFA98828F685290A80881319 -:1018B000A933DD3089147833022D3DF8289020D3E8 -:1018C000D007880CC170080847289420087736652F -:1018D0007FAE891413EC438990C0D477973D18EC00 -:1018E00041C1BA2721048514099C4006CC118653B6 -:1018F00004771185520C77020B7702C0C098A09D27 -:10190000A18D2B9CA597A496A795A603DD029DA269 -:101910002BF2852CE4CF2BBC202BF6852A2C748B44 -:1019200012580D11D2A0D10F28203DC0E07C87773E -:101930002E24670E0A4765A07318EC2B8F201CEC31 -:10194000198E148CC48EE408FF1108FF020E8E1449 -:10195000AECC1EEC269F910ECC029C90C0801EEC5B -:10196000242C21021AEC162FD285AABAB8FF2FD642 -:10197000850ECC0228A4CF2C2502C020D10F8714BD -:10198000877007074763FD86282123C099798B025A -:1019900063FEB2DDF063FEAD00DA20DB308C12DDD9 -:1019A000505814E8D2A0D10FC0E163FF828B148C91 -:1019B00012DD50C0AA2E0A802A2468DA2058135358 -:1019C000D2A0D10F007096552B629E6EB8531DEBBE -:1019D000F22DD22668D0048E207DE9452A629DCB67 -:1019E000AF2B21042C20665812EBC090292466826C -:1019F0001418EC008F2108FF019F21C020D10F0097 -:101A00008B10C9B88CA00C6C51CCCC8E241FEBEE83 -:101A10008DE19E140FDD029DE18810658FA9C02025 -:101A2000D10FDA20C0B6581441C020D10F000000F9 -:101A30006C1006C0D02A2102941175A70E89347F3C -:101A400097098B357FBF042D2502DAD00A0C4C652F -:101A5000C17B16EBD21FEBD028629EC0EA78E3026E -:101A600060018129F2266890078A2009AA0C65A1E5 -:101A7000732A629DDEA064A1702B200CC0700CBC88 -:101A80001106CC0829C286280A0C79830260014C11 -:101A900019EBC409B90A2992A3689007882009881C -:101AA0000C65813824C2851CEBC664412F8931093D -:101AB0008B140CBB016FB11D2C20669E10B1CC0C99 -:101AC0000C472C24666EC60260013409FE5065E1A5 -:101AD0002E8A102AAC188934C0E47F973617EBC7DA -:101AE000C0821BEBC58C359E419B408B2098459D49 -:101AF0004418EBC307BB029B420C07400F771198B9 -:101B0000439747D7E07FC70B2C2102284A0008CC17 -:101B1000022C25027E97048B362B25227D97048C80 -:101B2000372C25217C973A0AAB022C0A01C0800A87 -:101B3000C8382A3C200808426480821CEB9419EBC8 -:101B40009529C67E00A08800B08C00A08800B08CCB -:101B500000A08800B08C28629D2DF4A2288C182843 -:101B6000669D89307797351FEB9F8C338832047BD5 -:101B70000B2A2104B47704AA119EB19FB08F2B9D2C -:101B8000B598B69CB718EB96099C4006CC110CAAE8 -:101B90000208FF029FB2C1CC0CAA029AB4C9772AEC -:101BA000200C1BEB860CA911A699289285ABAA2DB7 -:101BB000A4CF08780B289685CF58C020D10FC087B6 -:101BC000C0900AC93879880263FF7863FF6CCC57EC -:101BD000DA20DB308C11581342C020D10FDA2058A4 -:101BE00013D363FFE8C0A063FE89DA20C0B65813A0 -:101BF000CF63FFD92A2C748B11580C5BD2A0D10F64 -:101C00008A102B21045812631FEB64C0D02D246668 -:101C100063FEBD006C1006D62019EB5F1EEB612839 -:101C2000610217EB5E08084C65805F8A300A6A51D2 -:101C300069A3572B729E6EB83F2A922668A0048C27 -:101C4000607AC9342A729D2C4CFECAAB2B600CB64C -:101C50004F0CBD11A7DD28D2860EBE0A78FB269C4C -:101C6000112EE2A32C160068E0052F62007EF91504 -:101C700022D285CF2560000D00DA60C0B65813ABC4 -:101C8000C85A60010F00DA605813A8655106DC409D -:101C9000DB308D30DA600D6D5158121CD3A064A07A -:101CA000F384A1C05104044763FF6D00C0B02C60F1 -:101CB000668931B1CC0C0C472C64666FC6027096F5 -:101CC0000A2B6104581233C0B02B64666550B42AE5 -:101CD0003C10C0E7DC20C0D1C0F002DF380F0F425B -:101CE00064F09019EB2A18EB2B28967E8D106DDA94 -:101CF0000500A08800C08CC0A089301DEB3A779702 -:101D00005388328C108F3302CE0BC02492E12261B3 -:101D1000049DE00422118D6B9BE59FE798E61FEB85 -:101D2000300998400688110822020FDD02C18D9DFE -:101D3000E208220292E4B4C22E600C1FEB200CE8F1 -:101D400011A7882C8285AFEE0C220B2BE4CF2286C4 -:101D500085D2A0D10F28600CD2A08C1119EB180CE1 -:101D60008D11A7DD2ED285A9882B84CF0ECC0B2C0C -:101D7000D685D10FC0F00ADF387FE80263FF6C63BD -:101D8000FF6000002A6C74C0B2DC20DD40581211E4 -:101D9000C0B063FF63C020D10F0000006C10042CA2 -:101DA000221D2A221EC049D320293006243468C0AF -:101DB000407AC105DDA060000200C0D06E9738C037 -:101DC0008F2E0A802B3014C0962934060EBB022EAB -:101DD00031022B34147E8004243502DE407AC10E99 -:101DE000C8ABDBD0DA302C0A00580A792E31020E4B -:101DF0000F4CC8FEC020D10F6895F82831020808A2 -:101E00004C658FEF1AEAE61CEAE42BA29EC09A7B8F -:101E10009B462BC22668B0048D307BD93B29A29DFE -:101E2000C0E3CB9394901BEAF72D31049B9608DD19 -:101E3000110EDD029D979D9124C4A212EAF32F3169 -:101E40000228A29DC0E52E3406288C3028A69D02CB -:101E5000FF022F3502C020D10FDA30C0B65813333D -:101E6000C020D10F6C10062A2006941168A80528FE -:101E7000ACF965824F29210209094C659206CC5FB5 -:101E8000DB30DA208C11581296C051D3A0C7AF9A1C -:101E90003AC0E019EAC31DEAC91AEAC28F3A16EA43 -:101EA000BFB1FB64B1352C629E6FC8026001E927A7 -:101EB000DC33277226687007882007880C6581D874 -:101EC00024629DC0766441D02B200C0CBC11A6CCA2 -:101ED00028C286C09E7893026001C819EAB109B988 -:101EE0000A2992A39410689007882009880C6581BC -:101EF000B224C2856441AC292006299CF96491DF93 -:101F00002C20668931B1CC0C0C472C24666EC6029D -:101F100060019809F8506581921AEAA38C3619EA93 -:101F2000A10C881489940C0C4709CC10A8990A9923 -:101F30000218EAB62A210499409841882A19EAB47D -:101F40000C8802098802984228302C2C3013293042 -:101F50001204CC100699100C88109F4408A8020C9B -:101F6000990209880298438F379F458C389C46898F -:101F700039C0F1994719EAA788359F4B98480888D6 -:101F800014098802984A8F3018EA9777F732C0749C -:101F900089328C33984C974D0F9740882B2E4611E1 -:101FA0000677112C461329461204AC1119EA8D0745 -:101FB000CC02C179098802984E07CC022C4610C089 -:101FC0007AADBC0CBA11A6AA29A2852EC4CF097974 -:101FD0000B29A6856550FCC020D10F002B200C0CCE -:101FE000BC1106CC082FC28609B90A6FF90260013C -:101FF0001E2992A36890082F220009FF0C65F10F9B -:102000002FC28564F10928203D082840648084841B -:102010003504841464407C85A57453778436048425 -:102020001464406F74536C293013C08C798864C079 -:10203000902924670908476580DD882089A48435B4 -:102040001AEA6B048414A4940A440294F014EA6615 -:1020500008881104880298F1843698F3048414A443 -:10206000990A990299F21AEA6229210224C285ADDD -:10207000B82E84CF244C1024C6850A990229250243 -:10208000C020D10F00CC57DA20DB308C115812144D -:10209000C020D10FC09163FF97DA20C0B65812A3B9 -:1020A00063FFE100DA205812A163FFD88A102B21C8 -:1020B000045811381DEA422B200CC0E02E24668FF4 -:1020C0003A63FE5400DA20DB30DC40DD5058131D4B -:1020D000D2A0D10F2A2C748B11580B23D2A0D10F70 -:1020E000292123C08879830263FE2D2A12002C2027 -:1020F000662B21042CCC010C0C472C24665811258E -:102100001DEA2F2B200CC0E02E24668F3A63FE08B8 -:10211000DA2058128663FF6CDA205BFF20D2A0D150 -:102120000F0000006C100A9516C061C1B0D9402A9A -:10213000203DC0400BAA010A64382A200629160750 -:1021400068A8052CACF965C33B1DEA16C8442F12DC -:102150000664F29B2621021EEA12961406064C65BE -:1021600062DE15EA0E6440CF8A352930039A150ADB -:10217000990C6490C22C200C8B159C120CCC11A5D0 -:10218000CC9C132CC286B4BB7CB3026002CE8F12EF -:102190000EFE0A2EE2A368E0082622000E660C65F9 -:1021A00062BA88132882856482B2891564905EDAE7 -:1021B00080D9308C201EEA0C1FEA0D1DE9FA8B1520 -:1021C0008DD4D4B07FB718B88A293C10853608C69C -:1021D000110E66029681058514A5D50F55029580CE -:1021E0000418146D8927889608CB110888140EBB33 -:1021F00002A8D8299C200F88029BA198A088929BB6 -:10220000A3088814A8D80F880298A22AAC10C0D0BE -:102210008A151FE9EA8E1219E9F68B1388142CB27D -:1022200085098802AFEE0CAA0B2DE4CF2AB68528CB -:102230002502C020D10F000026529E18E9D76F68F2 -:102240000260020D2882266880098920D30F089930 -:102250000C6591FD2A529DC0FD9A1164A1F32B20BB -:102260000CC1CA0CB8110588082D82860EBE0A7DE5 -:10227000C30260020A2EE2A368E0082622000E666E -:102280000C6561FB288285DE806482072920069820 -:1022900010299CF96492042C20668831B1CC0C0C76 -:1022A000472C24666EC6026001BD08FD5065D1B79B -:1022B00017E9DA1CE9BD19E9C42A21048B2D28305D -:1022C000102D211D0C88100BDB090A8802098802D9 -:1022D0000CBB0264415589109B909791989284356C -:1022E000D9E064406FD730DB40D8307F4715273CBA -:1022F00010BCE92632168C3996E69CE78A37283CD2 -:10230000042AE6080B131464304A2A821686799A46 -:102310009696978C778A7D9C982B82172C7C209A96 -:102320009A2A9C189B99867BB03B298C086DB92111 -:102330008BC996A52692162AAC18B8999BA196A08F -:102340008BC786CD9BA22B921596A49BA386CB2CE4 -:10235000CC2026A605C0346B4420043B0C0448095D -:102360000E880A7FB705C0909988BC88C0900B1A68 -:10237000126DAA069988998B288C181CE9A81BE96C -:10238000A816E99DB1DD2A211C23E6130D0D4F2669 -:10239000E6122D251DC06087207DA907C0D0280A20 -:1023A0000028251D26E6172CE6162BE61505D81164 -:1023B0001AE99328E6180A7A022AE614292006293F -:1023C0009CF96491062A200CC0901BE97C0CAD118D -:1023D000A5DD2CD285ABAAC0B029A4CF0CFC0B2C58 -:1023E000D685DA208C172D120658110DD2A0D10FE8 -:1023F0008A356FA546D8308BD56DA90C8A860A8A96 -:1024000014CBA77AB335288C10C080282467080B1A -:102410004765B11CDA20DB308C17581131D3A0C0CE -:10242000C1C0D02DA4039C1663FD280086366461CC -:102430001689109B909791989263FEA1C08163FFCB -:10244000C98A16CCA7DA20DB308C17581125C0209A -:10245000D10FDA20C0B65811B563FFE400DA208B43 -:10246000125811B263FFD9009F189E198A112B21AF -:10247000045810488E198F18C0B02B246663FE2FA5 -:10248000C08063FE01DA20DB308C17DD5058122D3E -:10249000D2A0D10FDA205811A563FFA42D2123C0AB -:1024A000C87DC30263FE089F188A112B21042C20CB -:1024B000669819B1CC0C0C472C24665810368E192E -:1024C0008F18C0D02D246663FDE50000262123B0BF -:1024D0006606064F262523656EEA28206A7F870553 -:1024E0000829416490FDC0D01BE93F19E94E262020 -:1024F0000723E61BB166097A022BE61A28200A2D6B -:10250000E61D2AE61E09880228E61C8826060647DC -:1025100028E6208B2826E53E2BE6212D24072C20BB -:10252000062A20642CCCFD64C09DB4FF63FE950098 -:1025300000DB30DA208D16C0CE2E0A802C24688C69 -:1025400017581072D2A0D10F8E102632161FE9151F -:102550000626148FF62BE61297E127E61328E614D9 -:10256000A6FF0CFF029FE0C1F62EEC4826ECC064EB -:102570006D6B8435C080644DDBD9E0DC30DBE0DDA1 -:1025800030B18814E92986C98AC8279DFF2CCC1050 -:10259000299C102A76322A76300464011AE9242410 -:1025A0007631AA442476332AD21617E9219AB6073F -:1025B000660196B784C3BCBB94B58435B4DD74831F -:1025C000BF2D211D63FD8D0064AF5E1DE8F62C203C -:1025D000168DD20ACC0C00D10400CC1AACBC9C29BC -:1025E00063FF46002B21046EB8222C2066B8CC0C69 -:1025F0000C472C2466C9C49F189E198A11580FE5F0 -:102600008E198F18C0348720C0D02D2466C068264C -:10261000240663FED00000006C1008292006289CC8 -:10262000F86582C3292102C0AA09094C6590E62BEE -:10263000200C16E8DA0CBC11A6CC2EC286C1D27EC4 -:10264000D30260028E19E8D609B90A2992A32A1684 -:10265000026890078A2009AA0C65A27729C28564BE -:1026600092712B629E1AE8CC6FB80260026E2AA2A9 -:102670002629160168A0082B22000ABB0C65B25C53 -:1026800029629DC18C6492542A21200A806099108D -:102690002C203CC7EF000F3E010B3EB1BD0FDB39D4 -:1026A0000BBB098F260DBD112DDC1C0D0D410EDD60 -:1026B000038E27B1DD0D0D410FEE0C0DBB0B2BBCB6 -:1026C0001C0BB7027EC71C2C21257BCB162D1AFCB8 -:1026D0000CBA0C0DA16000093E01073EB1780987D4 -:1026E000390B770A77EB026002062B212328212180 -:1026F000B1BB0B0B4F2B25237B8B29B0BD2D252385 -:10270000C855DA20DB30580FF0292102CC96C0E8FA -:102710000E9E022E2502CC57DA20DB30DC4058100A -:1027200070C020D10F2C20668931B1CC0C0C472C05 -:1027300024666EC6026001CF09FD5065D1C92F0A1B -:10274000012830112922146480112A221B090C440B -:1027500000C10400FB1A0BAA022A261B2D3010C050 -:10276000A0C0E088301BE88F94139514240A01253B -:10277000203C2BB022088C14778704C0F10BFA3868 -:10278000C0F2C0840858010F5F010F4E3805354074 -:1027900007EE10C0F0084F3808FF100FEE0228DCDB -:1027A000FEC0F0084F38842B0BA8100AFF102A2116 -:1027B000200F88020E880208440218E89E8F110834 -:1027C00044022821250A2A140828140488110A889A -:1027D000022A210494F08E2004D41008EE1104EE95 -:1027E00002C04A04EE029EF1842A08AE110EDE02F7 -:1027F00094F40A54110E44020555100C1E4094F72F -:1028000007EE100E5502085502C08195F68433C0BC -:102810005094F3B1948E3295F898F99EF2C080C12D -:10282000EC24261498FB9EF599FA853895FC843A99 -:1028300094FD8E3B9EFE883998FF853525F61084E1 -:1028400036851424F6118E3784132EF612C0E064F8 -:10285000B04989307797442B301088338C111FE8AA -:10286000618D322FC614C0F42FC6158F2B2EC619BA -:102870002DC61A28C61B04AD1109984006881108F8 -:10288000DD020DBB0218E856C1D00DBB0208FF02E5 -:102890002FC6162BC618280A0E2816022B200C88C5 -:1028A000121CE8460CB911A6992A9285ACBB2EB42D -:1028B000CF0A880B289685C9718B268A2907BB0801 -:1028C0002B26060BAA0C0A0A482A2525655048C063 -:1028D00020D10F00DA2058109563FE3900DA20C0AD -:1028E000B658109263FE2E00689738C020D10F00B2 -:1028F00000DA20DB7058104FC0C0C0D10ADA390AA4 -:10290000DC3865CDE463FE0D8A102B2104580F21BD -:10291000C0E02E246663FE25DB402A2C7458091281 -:10292000D2A0D10FDA20580F2663FCF76C1004C038 -:1029300020D10F006C1004270A801CE83F1DE83FDF -:102940001AE8170C2911AA992A2CFC2B92850DAA9A -:10295000029CB19AB0C05113E83C28928516E83821 -:1029600014E839A62604240AB888289685234691B7 -:10297000A76625649FD10F006C100AD6302830104E -:10298000292006288CF964829768980B2A9CF9659F -:10299000A1B2022A02580F0A89371BE802C89164C3 -:1029A000520E2A21020A0C4C65C2558D3019E7FBE4 -:1029B00074D7052E212365E29A2F929E1AE7F76FAE -:1029C000F8026002502AA22668A0082C22000ACC35 -:1029D0000C65C2412A929D64A23B9A151FE7F18DB6 -:1029E00067C1E6C8DD2B620618E7EF64B0052880F2 -:1029F000217B8B432B200C18E7E90CBC11A8CC29B8 -:102A0000C28679EB460FBE0A2EE2A368E0052F22AC -:102A1000007EF9372CC2859C1864C22F2B212F878A -:102A2000660B7B360B790C6F9D266ED2462C203DB3 -:102A30007BC740CE5560001E2A200CC1B28C2058A6 -:102A4000106F9A1864A2418D6763FFCFC0C063FF07 -:102A5000C5D7B063FFD300C0E06000022E60030E54 -:102A6000DB0C6EB20EDC700CEA11AA6A2AAC20589C -:102A70000198D7A0DA20DB70C1C82D21205810158D -:102A80008C268B279A160CBB0C7AB3348F1889636B -:102A900099F3886298F28E659EF82D60108A189DD1 -:102AA0001768D729C0D09DA92C22182B22139CABC4 -:102AB0009BAA97A58E667E7302600097CF58600030 -:102AC0001FDA208B16580FDB65A13563FFBDC0816F -:102AD000C0908F18C0A29AF999FB98FA97F563FFF6 -:102AE000D2DB30DA20DC40580F7EC051D6A0C0C007 -:102AF0002BA0102CA4039B172C1208022A02066B91 -:102B000002DF702D60038E179D149E100CDD11C026 -:102B1000E0AD6D2DDC205801178C148B16ACAC2C5D -:102B200064038A268929ABAA0A990C9A2688660921 -:102B3000094829252507880C98662F2218A7FF2FFA -:102B4000261863FE96DA20DB30DC40DD5058107D1D -:102B5000D2A0D10FC0302C20668961B1CC0C0C47BB -:102B60002C24666EC6026000CEC03009FD5065D0D0 -:102B7000C68E6764E069647066DB608C18DF70DAAB -:102B8000202D60038E170CDD119E10AD6D2DDC2005 -:102B90001EE7A75800F8232618DA208B16DC402FF2 -:102BA0002213DD50B1FF2F2613580F1DD2A0D10FD5 -:102BB0000028203D084840658DE76F953EDA308D4E -:102BC000B56D990C8CA80C8C14CACF7CD32D2AAC73 -:102BD00010C090292467090D4764DDC560008E0090 -:102BE0002C1208066B022D6C20077F028E17DA204C -:102BF0009E101EE78E58007C63FF9A00C09163FF11 -:102C0000D1655080DA20DB60DC40580F35C020C031 -:102C1000F02FA403D10FDA20C0B6580FC463FFE031 -:102C2000006F950263FD70DA20DB30DC40DD50C4BC -:102C3000E0580EB6D2A0D10F8A152B2104580E559C -:102C4000232466286010981763FF2500DA20580FA8 -:102C5000B763FFACC858DB30DA20580E9B2A21023C -:102C600065AF9DC09409A90229250263FF92DB305C -:102C7000DC40DD50C0A32E0A802A2468DA20580EDA -:102C8000A3D2A0D10FC020D10FDA202B200C580FD7 -:102C9000C063FF6C6C1004282006C062288CF865A5 -:102CA0008125C050C7DF2B221BC0E12A206B2921C0 -:102CB0002300A104B099292523B1AA00EC1A0BC462 -:102CC000010A0A442A246B04E4390DCC030CBB012D -:102CD0002B261B64406929200C1BE7300C9A110B32 -:102CE000AA082FA2861BE72E6FF9026000B60B9B85 -:102CF0000A2BB2A368B0082C22000BCC0C65C0A430 -:102D00002BA2851CE75264B09B882B2F21040C88D2 -:102D10000298B08420C08508441108440294B1840C -:102D20002A08FF1194B48E349FB79EB5C0401DE7AA -:102D3000232EA2850D9D082EEC282EA68525D4CF06 -:102D400029210209094C68941A689820C9402A214F -:102D50000265A00B2A221E2B221D7AB10265A079E2 -:102D6000C020D10F2C212365CFDE6000082E212149 -:102D70002D21237EDBD52B221E2F221D2525027B14 -:102D8000F901C0B064BFC413E7042CB00728B00039 -:102D9000DA2003880A28824CC0D10B8000DBA065B2 -:102DA000AFE763FFA62A2C74C0B02C0A02580D8D21 -:102DB0001CE7289CA08B2008BB1106BB029BA189A5 -:102DC0003499A263FF790000262468DA20DB30DC26 -:102DD00040DD50580FDCD2A0D10FDA202B200C5848 -:102DE0000F53C020D10F00006C1006073D14C080A7 -:102DF000DC30DB40DA20C047C02123BC3003283858 -:102E00000808427740022DDC016481571EE6E01974 -:102E1000E6E129E67E6DDA0500508800308CC0E0DE -:102E2000C02025A03C14E6DFB6D38FC0C0D00F87EA -:102E3000142440220F8940941077F704C081048243 -:102E400038C0F10B2810C044C02204540104FD38DE -:102E500002520102FE3808DD10821C07EE100E6ED1 -:102E6000020EDD02242CFEC0E004FE380AEE100E35 -:102E700088020D88028DAB1EE6CF08D8020E8802AC -:102E800098B0C0E80428100E5E0184A025A1250892 -:102E90004411084402052514045511043402C0816C -:102EA0000E8E3994B18FAA84109FB475660A26A13C -:102EB0001FC0F206261460000726A120C0F20626D5 -:102EC000140565020F770107873905E610077810AA -:102ED00008660206550295B625A1040AE6110858AF -:102EE0001108280208660296B7C0606440566490D4 -:102EF00053067E11C0F489C288C30B340B964598E3 -:102F000047994618E6B79F410459110E99021FE6EA -:102F1000B5020E4708D8029F4098420E9902B43875 -:102F2000C1E00E990299442FA00C0CF91114E6A3EC -:102F30001EE69BA4FFAE992E928526F4CF0E880B39 -:102F4000289685D10F2BA00C0CBE111CE69C1FE609 -:102F500093ACBBAFEE2DE28526B4CF0D3D0B2DE635 -:102F600085D10F00C08005283878480263FEA5632C -:102F7000FE9900006C1006C0B0C0A6C0C06570F01D -:102F80008830C0300887140888406580D3C0E0C00E -:102F900091C0D4C08225203C0B3F109712831CC0E7 -:102FA000700858010D5D01089738C0800B983807EC -:102FB0007710048810086802087702C0800D9838DE -:102FC0002D3CFE0888100D9E388D2B0AEE1008EE61 -:102FD0000207EE020CB8100FDD02053B400EDD02C9 -:102FE0009D408920043D100899110D99022D21045E -:102FF00009A90208DD119941872A05B9100D3D0282 -:103000000ABB110DBB0208770297442821258712BD -:10301000082814048811071E4007EE100E99027547 -:10302000660926211F0626146000060026212006B8 -:1030300026140868029B47098802984629200CD26A -:10304000C0C0800C9E111BE65D1FE654AB99AFEE2D -:103050002DE2852894CF0DAD0B2DE685D10F000014 -:10306000001FE6502FF022C03065FF20C03163FF03 -:103070001BDD408E51CAE00E7836981008770CB2EE -:10308000AAB1BB8F502DDC1098D99FD889538F528D -:10309000991199DB9FDA7E830AB1CC255C10C9783F -:1030A00063FFCF0088108D1108E70C9751AD8DD7C5 -:1030B000F078DB01B1F79D5397528830C030088714 -:1030C00014088840648EC565BFA163FF93000000AB -:1030D0006C1004D720B03A8820C0308221CAA17475 -:1030E0002B1F2972046D080FC981C9928575B133F0 -:1030F000A2527A3B0C742B0963FFE90000649FEB3A -:10310000D10FD240D10F00006C1008D630C070959E -:1031100015DA408E3914E6239A1464E0026451F8FB -:103120002920062A9CF865A25B2A21020A0B4C651D -:10313000B21B2C320015E61974C7052D212365D367 -:10314000202E529E1AE6156FE8026002172AA22668 -:1031500068A0082B22000ABB0C65B2082E529D1DE8 -:10316000E61064E1FF8B3864B2299E16C8BC8D69F5 -:103170001EE60D64D0052EE0217BEB492E200C18B5 -:10318000E6070CEF11A8FF29F286C186798B4A1752 -:10319000E60407E70A2772A3687004882077893954 -:1031A00025F28564529E27212E07B73607B90C6F8A -:1031B0009D01D7B089696E924228203D7B873C8A69 -:1031C00015CDAF600018C1B28C202A200C580E8B90 -:1031D000D5A064A2A88B6863FFCBC05063FFC3C0B7 -:1031E000E06000022E60030E9B0C6EB20EDC700CD1 -:1031F000EA11AA6A2AAC285BFFB6D7A0DA20DB70F6 -:10320000C1C42D211F580E338C268B27D4A00CBB94 -:103210000C7AB3258A63C0909A5388629958985261 -:103220008F659F598E679E5B8D6697559D5A8B68FB -:103230007B7B748B15CEB360000DDA20DB40580D1C -:10324000FD65A10963FFCC00DA20DB308C14580D3A -:10325000A4D6A0C0C0C0D19D152CA403DA20DB6089 -:10326000DF70DC50C0E02560039E101EE5E60C5DBB -:1032700011AD6D2DDC285BFF3F8E66A5A88F6728FA -:103280006403AF7F77FB01B1EE9E669F678D268C4E -:1032900029A4DD0DCC0C9D268B680C0C482C252513 -:1032A00007BB0C9B6863FEC32C20668961B1CC0C04 -:1032B0000C472C24666EC6026000B409FD5065D030 -:1032C000AECBBB8E69CBE7DB60DC50DF70DA201E53 -:1032D000E5E12D6003C08098100CDD11AD6D2DDC93 -:1032E000285BFF248B15C84F8A268929A4AA9A2611 -:1032F0000A990C09094829252565B13BC020D10F41 -:10330000DB602D6C28DF70DA20C0C01EE5D29C1077 -:10331000DC505BFEB563FFCB002D203D0D4D4065BD -:10332000DDFD6FE522DA308F456DE90C8EAA0E8E39 -:1033300014C9E37EF3112AAC10C090292467090F49 -:103340004764FDDB60014100C09163FFED0088151B -:1033500065814CDA20DB608C14580D61C020C09070 -:1033600029A403D10FDA20C0B6580DF063FFDE00A8 -:103370008A162B2104580C87C0A02A24668B686308 -:10338000FF3E0000002B9CF965B0C5DA20580C8C7C -:1033900063FD95002B200C0CBA11A5AA2FA286C1A3 -:1033A000C27FC3026000FC0DB90A2992A36890078E -:1033B0008C2009CC0C65C0EB26A2856460E52C202E -:1033C000668931B1CC0C0C472C24666FC60270960E -:1033D0000ADAE02B2104580C6F272466893077978E -:1033E0004B18E57F1DE5808A328B33C0F42C210415 -:1033F000099E4006EE1104CC110ECC029F61C1E083 -:103400000ECC029D608F2B9A669B679C6497650823 -:10341000FF029F622F200C18E5690CFE11A5EE2D0E -:10342000E285A8FF27F4CF2DDC202DE6858F1565DA -:10343000F091C020D10F00002A2C748B1458064A3A -:10344000D2A0D10F00DA20DBE0580DB863FEFE00F9 -:1034500000DA20DB308C148D15580E3AD2A0D10F33 -:1034600000008815C888DA20DB30580C972A210222 -:1034700065AEDAC09409A90229250263FECFDA20DD -:103480002B200C580DC363FEC4272468DA20DB30E0 -:103490002C12042D12052E0A80580C9C63FC80000F -:1034A000C020D10FDA20580DA18A15CDA1DA200352 -:1034B0003B022C1204580D0A27A403C020D10F0090 -:1034C000C020D10F2A2C748B14580627D2A0D10FFC -:1034D0006C100E282102941008084C65835E1FE5CD -:1034E0002F29F29E6F98026003621DE52B29D226D8 -:1034F0006890082A220009AA0C65A3502CF29D644A -:10350000C34A2B200C0CB611AF66286286C1EC783A -:10351000E30260034219E52209B90A2992A36890DF -:10352000078A2009AA0C65A32E246285644328C05B -:10353000E12A3109C07027246689359A12992A88B0 -:10354000369913982B89379814992C88389915082F -:1035500058149816982D89392A25042E251D2925B9 -:103560001C283028C09228243C2A30290808479873 -:10357000170989012A243D2A311599180A09410998 -:10358000A90C299CEC29251F7E87192D2A000DA046 -:103590006000083E010A3EB1AD08DA390EAA110AF0 -:1035A000990C29251F27211F18E52C078160010888 -:1035B0003E000D3EB18A0DA8392D9CFC2D2520C161 -:1035C0009009883608DD1C08771C893D8A3C2E2628 -:1035D000132E26142E26152E246B2925222A25216A -:1035E000282014C0A027252E2D252F0808432D2183 -:1035F0001C282414C07027252427252527252C279F -:10360000261827261B2724672724682932112725F7 -:103610002399196ED2156D080AB1AA00A10400E918 -:103620001A7D9B0563FFEE00000089191DE4FDC0B3 -:10363000E0C0729B1D8813951B9F1F9C1E961C1C2F -:10364000E50826203DC0F006054008DB14076601AA -:103650000D8810C071057E38067F3885120BFF106B -:1036600016E4E60AEE1096400FEE020D5511B0AFCB -:1036700009FF110FEE021FE4F90855020FEE02C018 -:10368000F49F418A209F4996489C4B9B4E9D439EA8 -:10369000468D161EE4DA8B15C7CF9C4D9C4C9C457D -:1036A0009C440BD8140EAE020DBB109E4A9E4208DD -:1036B0005502954F0D181415E4CD0D88110588029B -:1036C000984718E4E885262E46122E461A2E4622E2 -:1036D0002646102646182646202F46112F46192F1B -:1036E00046212846242846262C46142C461595119A -:1036F0008C1718E4DD0505488F1805551109064893 -:1037000028461389140E66110655020F7F390C3EA8 -:103710004002EE1017E4D60D99110C26400F6611E9 -:103720000B99020C0C408B1D01CC1006FF022746A2 -:103730001B294616C07029311616E4CD0ECC0205A1 -:10374000FF021EE49C15E4CB2F461726461CC0F052 -:10375000861C2F461D2F461F2F46272546230ECC9D -:1037600002851B2C461E1EE4C41CE48E8F1F8CC7D2 -:103770002E4625ADCC28200629246A2431179C2DFD -:103780002425238C1ECC81272407C0D77F97188E31 -:10379000110928419E2964808E644098C098094987 -:1037A000362D240660000B00644075C09809493628 -:1037B0002D240601C4042D0AA02E210428628508A8 -:1037C000EE11AD88286685863F843E2D321006486E -:1037D0001898C300C40406461818E47804C45300BB -:1037E000661106DD02A8B82784CF9DC409064E964F -:1037F000C51DE4A305A61106440216E4A09DC0065B -:10380000440294C2C04304EE029EC114E46326F253 -:103810009D2744A2266C1826F69D655042C020D1F3 -:103820000FC09063FF890000654F70C098C0E82EFC -:10383000240663FF7D2D2406C09063FF75CC57DA04 -:1038400020DB308C10580C26C020D10F00DA20C0AD -:10385000B6580CB663FFE500DA20580CB463FFDC01 -:103860002A2C748B10580540D2A0D10F6C1006285A -:1038700020068A336F8202600161C05013E4472939 -:10388000210216E446699204252502D9502C201500 -:103890009A2814E4448F2627200B0AFE0C0477098B -:1038A0002B711C64E1398E428D436FBC0260016F45 -:1038B00000E104B0C800881A08A80808D8029827B0 -:1038C0002B200668B32ECE972B221E2C221D011111 -:1038D000027BC901C0B064B0172CB00728B000DA71 -:1038E0002003880A28824CC0D10B8000DBA065AF82 -:1038F000E7C020D10F2D206464DFCA8B29C0F10BF3 -:10390000AB0C66BFC02B200C0CBC11A6CC28C28609 -:103910002E0A0878EB611EE4220EBE0A2EE2A3688E -:10392000E0052822007E894F29C2851EE42E64907E -:10393000461FE43C9E90C084989128200A95930FDE -:10394000880298928E200FEE029E942F20078826E0 -:103950002F950A98969A972E200625240768E34308 -:103960002921021AE4162DC285AABA2DDC202DC603 -:103970008525A4CF63FF4E002B2065CBBDC0C22C94 -:103980002465C9F605E4310002002E62821FE41EA0 -:103990002D41020FEE022E66820DE43129210263D1 -:1039A000FF23000064DFB889422820160091040D2F -:1039B000880C00881AA8A8982963FFA38C202D32B0 -:1039C00021B1CC9CD02B32212A3223B4BB2B3621FF -:1039D0007BA9A92D32222D362163FFA0C020D10F53 -:1039E0009F27252415ACB828751C2B2006C0C12E96 -:1039F000BCFE64E0AB68B7772DBCFD65DEC72D204B -:103A000064C0F064D0868E290EAE0C66E089C0F1E9 -:103A100028205A288CFE08CF3865FEE863FF58003E -:103A200000E0049310C0810AF30C038339C78F08A8 -:103A3000D80308A80108F80C080819A83303C80C13 -:103A4000A8B828751C030B472B24158310CBB7008F -:103A5000E104B0BC00CC1AACAC0CDC029C27659E27 -:103A60005EC0B20B990209094F29250263FE50007E -:103A70002D206A0D2D4165DF7EDA20C0B0580C7212 -:103A800064AF18C0F163FEEF9F2763FFD02E221FA3 -:103A900065EE3263FF79000028221F658E2763FFE1 -:103AA0006E252406252502C09063FE196C1006655C -:103AB00071332B4C18C0C7293C18C0A1C08009A87D -:103AC000380808426481101CE3B11AE3B22AC67EAA -:103AD0002A5CFDD30F6DAA0500B08800908C884049 -:103AE000C0A00889471FE3DB090B47084C50080DAD -:103AF0005304DD10B4CC04CC100D5D029D310CBB21 -:103B0000029B3088438E2098350FEE029E328D2620 -:103B1000D850A6DD9D268E40C0900E5E5064E09782 -:103B20001CE3C11EE3B0038B0BC0F49FB19EB02D0C -:103B3000200A99B30CDD029DB28F200CFF029FB4C6 -:103B40008E262D20079EB68C282DB50A9CB72924D9 -:103B5000072F20062B206469F339CBB61DE392238F -:103B600020168DD20B330C00D10400331AA3C3B43A -:103B70008D932922200C13E3911FE3880C2E11AFA3 -:103B8000EEA3222924CF2FE285D2A00FDD0B2DE654 -:103B900085D10F00B48C2E200C0CEB111FE3881D77 -:103BA000E37FAFEEADBB22B28529E4CF02C20B2288 -:103BB000B685D2A0D10F00002E200C0CEB111FE314 -:103BC0007F1CE376AFEEACBB22B28529E4CF028244 -:103BD0000B22B685D2A0D10FC0D00BAD387DC80264 -:103BE00063FEEC63FEE08E40272C747BEE12DA70ED -:103BF000C0B32C3C18DD50580A77C090884063FE53 -:103C0000E3066E02022A02033B02DC40DD5058004C -:103C1000049A10DB50DA70580454881063FEF600E2 -:103C20006C10082E3C18C0A092161FE3688C40AFA1 -:103C30002F0C8C47C02304CB0BDDB07FB3022DBD0E -:103C4000F8D9D0C0B075C30260008D9F146D084FC5 -:103C50008D900D6D36ADAA0D660C0EB70B0EBF0A1A -:103C60009DF0B877B89FD8F000808800708C9711CD -:103C700087909810971568B12AB22277D32D889132 -:103C8000C0D0CB8F9890279C10007088971200F0BE -:103C90008C9F139D916460A0C08108BB0375CB38D5 -:103CA00063FFA900B1222EEC1863FFCE85920D7739 -:103CB0000C86939790A6D67D6B01B15595929693FD -:103CC0008942600017B3CC299C188814DD90789342 -:103CD000022D9DF8D9D063FFBB8942DA9085160C7E -:103CE0000D472D44021BE36792319B3086437A9146 -:103CF000261BE3581EE36589500E660196350B9925 -:103D000002993288420A880C98428756A7A797568C -:103D10008F44AFAF9F44D10F1BE34F895096350BB3 -:103D20009902993288420A880C98428756A7A79729 -:103D3000568F44AFAF9F44D10F894263FF9E00006E -:103D40006C10061FE3529310D6308830C091086380 -:103D5000510808470598389811282102293CFD0888 -:103D6000084C6581576591542A62030A2B5065B14E -:103D70007E0A68142E0AFF7CA60A2C205ACCC42D79 -:103D80000A022D245A78E0026002088A288926183F -:103D9000E3400A990C6592032E200B1CE33F08EECA -:103DA0000B2EED012DE0322EE03308DD110EDD0289 -:103DB0001EE339AFDD0EDD010DCC372D200C8960FF -:103DC000C1E07B96231AE2F78B622AA0219C127B2A -:103DD000A316DAD0C1B00B4B37B4BB8C20580B877D -:103DE0008C12DBA0CEAB6001BF0E4E371BE2EC0C99 -:103DF000DA11ABAA28A286B8EE78EB351EE2E90EFE -:103E0000DE0A2EE2A368E00488207E89242BA285A6 -:103E100064B0A28762DE700C79369B1388268D27EA -:103E2000097A0C08DD0C6FAD0E77D3107E7B6960CC -:103E3000001FC0B063FFD800D79063FFEB9C12DA7D -:103E400020DB70580AFC8B138C1265A06F8E627E8B -:103E50007B469C129B13CC5FDA208B10044C0258DB -:103E60000AA0D6A08B13250A01DE70DA20DC60DD03 -:103E7000405BFF6B8C12D9A02D200CC0E01BE2C769 -:103E800017E2CF0CDA11A7D7ABAA2BA2852E74CFDD -:103E90000B990B29A68563FF24DA20DC60DD40DE68 -:103EA000708911282007DF50A9882824075BFEFFAE -:103EB000D2A0D10F0000DBD0DA20580B1C6550F3E4 -:103EC0002A20140A3A4065A0EEDB60DC40DD30DADF -:103ED0002058098E1FE2EED6A064A0D784A183A04B -:103EE0000404470305479511036351C05163FE68FD -:103EF0002C200628CCFD6480A868C704C093292420 -:103F000006C0C18E6419E2A79E269E299E2889922A -:103F10009E2700910400CC1A009004B0C88D65085B -:103F2000EE01AECC0D0E5E01EE11AECCB0CC2E0A81 -:103F3000FE0C0C190ECC36C0E20C0C470ECC372C04 -:103F40002416C0B02B24072C20061BE29F0A0E4526 -:103F50000D084228240B2E240AB48929240C7DB88C -:103F60005A2920160A5D52B09E0EDD362D24642B90 -:103F7000CCFD65BDFB0D0C4764CDF51DE28A88289C -:103F80008DD20C9B0C00D10400BB1AAB889829631E -:103F9000FDDE00001CE2B963FE2000001CE2AF63FE -:103FA000FE188D6563FFA20000DA202B200C580A52 -:103FB000F8645F0BC020D10FC020D10FC093C0E3C5 -:103FC0002E241663FF9D00006C1004C06017E2727F -:103FD0001DE275C3812931012A300829240A78A1FC -:103FE00008C3B27BA172D260D10FC0C16550512607 -:103FF00025022AD0202F200B290AFB2B20142E204B -:104000001526241509BB010DFF0928F11C2B2414CA -:10401000A8EE2EF51C64A0B52B221E28221D01112E -:10402000027B8901DB6064B0172CB00728B000DA8E -:104030002007880A28824CC0D10B8000DBA065AF26 -:10404000E7DB30DC40DD50DA205800D829210209B6 -:104050000B4CCAB2D2A0D10F00CC5A2C30087BC175 -:10406000372ED02064E02D022A02033B02DC40DD23 -:10407000505800CED2A0D10F2B2014B0BB2B24144B -:104080000B0F4164F0827CB7CAC0C10C9C022C2586 -:1040900002D2A0D10FC020D10F2E200669E2C12F7D -:1040A00021020F0F4C69F1B82624062625022B2287 -:1040B0001E28221D2A200B2920150DAA092CA11C1F -:1040C000262415AC9929A51C7B814A600049B0BB08 -:1040D0002B24140B0D41CBD67CB7022C25022B22AE -:1040E0001E2E221D7BE9022B0A0064B0172CB0079C -:1040F00028B000DA2007880A28824CC0D10B800043 -:10410000DBA065AFE7C020D10F262406D2A0D10FD7 -:1041100026240663FFC7DB601DE22364BF422CB088 -:104120000728B000DA2007880A28824CC0D10B800B -:1041300000DBA065AFE71DE21B63FF246C100428C1 -:104140002006C0646F8564CA5B2920147D9726DA37 -:1041500020DB30DC40055D02580019292102090AE4 -:104160004CC8A3C020D10F00C0B10B9B022B25026D -:10417000C020D10F0000022A02033B022C0A015882 -:1041800000C9C9AADA20DB30DC405809D529A011C2 -:10419000D3A07E97082C0AFD0C9C012CA411C051C1 -:1041A0002D201406DD022D241463FFA2DA20DB305B -:1041B000DC40DD50C0E0580955D2A0D10F0000000E -:1041C0006C100616E1F61CE1F665513BC0E117E103 -:1041D000F22821028B2008084C65807C29320009D6 -:1041E00069516993732A629E6EA8482A722668A054 -:1041F000027AB93F2A629DB44FCBA72B200C0CBD8D -:104200001106DD0828D28678FB150CBF0A2FF2A311 -:1042100068F00488207F89072DD285D30F65D06090 -:104220002A210419E21ED30F7A9B1DDA2058085365 -:10423000600025002C21041BE2197CBB14DA20C08D -:10424000B658084EC9546000EFDA20580A386000AA -:104250000700DA20C0B6580A356550DCDC40DB3098 -:104260008D30DA200D6D515808A9D3A064A0C91C67 -:10427000E1CCC05184A18EA00404470E0E4763FF19 -:104280004F2B2104C08C8931C070DF7009F95009AF -:104290008F386EB8172C2066AECC0C0C472C2466D9 -:1042A0007CFB099D105808BB8D1027246694D11EF5 -:1042B000E1D2B8DC9ED0655056C0D7B83AC0B1C084 -:1042C000F00CBF380F0F42CBF119E1B018E1B22862 -:1042D000967EB04BD30F6DBA0500A08800C08C2C21 -:1042E000200CC0201DE1B60CCF11A6FF2EF285AD2B -:1042F000CC27C4CF0E4E0B2EF685D10FC0800AB846 -:104300003878D0CD63FFC1008E300E0E4763FEBDFE -:104310002A2C742B0A01044D025808AE2F200C12CF -:10432000E1A70CF911A699289285A2FF27F4CFD214 -:10433000A008480B289685D10FC020D10F0000009F -:104340006C1004C060CB55DB30DC40055D02022AF6 -:10435000025BFF9B29210209084CC882D2A0D10F21 -:104360002B2014B0BB2B24140B0C41CBC57DB7EB19 -:10437000C0C10C9C022C2502D2A0D10F0000022A41 -:1043800002033B02066C02C0D0C7F72E201428316E -:104390000126250228240A0FEE012E241458010CB0 -:1043A00063FFA300262406D2A0D10F006C100628BC -:1043B0002102D62008084C6580992B200C12E17749 -:1043C0000CB811A2882A8286B5497A9302600093BC -:1043D00019E17409B90A2992A36890082A620009B0 -:1043E000AA0C65A07E2882851CE17F6480759C8074 -:1043F000B887B14B9B819B10655072C0A7D97028BC -:104400000A01C0D0078D380D0D42CBDB1FE1601EC5 -:10441000E1612EF67ED830D30F6D4A05008088000A -:10442000908CC0802F30082F740029600C1AE16333 -:104430000C9D11A2DD2CD285C020AA992294CF0C0C -:10444000BC0B2CD685D280D10FC0E0038E387EA065 -:10445000C363FFB7CC582A6C74DB30DC405807E1EB -:10446000C020D10FDA605809B163FFE70000DD40DA -:1044700085102A6C74C0B0DC705808562F30082F95 -:10448000740028600CC0F00C8B11A2BB29B28512FD -:10449000E14B09590BA2822F24CF29B685D2A0D196 -:1044A0000F0000006C1004292014282006B199295F -:1044B0002414688124C0AF2C0A012B21022C24066D -:1044C0007BA004C0D02D2502022A02033B02044C2B -:1044D00002C0D05800BFD2A0D10FC020D10F000021 -:1044E0006C1004293101C2B429240A2A3011C28374 -:1044F00078A16C7BA1696450472C2006C0686FC509 -:1045000062CA572D20147CD722DA20DB30DC40DD54 -:10451000505BFFA6292102090E4CC8E2C020D10F32 -:10452000C0F10F9F022F2502C020D10FDA20DB300F -:10453000C0C05BFFDC28201406880228241463FF17 -:10454000C72920151BE1182A200BC0C09C240BAAE8 -:10455000092BA11C2C2415AB9929A51C63FF9900DC -:10456000C020D10FDA20DB30DC40DD50C0E058083D -:1045700067D2A0D10F0000006C1004CB5513E113DB -:1045800025221F0D461106550CA32326221E252683 -:104590001F06440B24261E734B1DC852D240D10F58 -:1045A000280A80C04024261FA82828261E28261D49 -:1045B000D240D10FC020D10F244DF824261E63FF16 -:1045C000D80000006C1004282006D6206E850260FA -:1045D00000DE17E0F21DE0F919E0F2C0C1C0202AA8 -:1045E0008CFC64A1322B6102B44E0B0B4C65B0A85D -:1045F0002B600C2A62000CB8110788082F828609EC -:10460000B90A7FE30260009F2992A368900509AA76 -:104610000C65A09328828564808DB8891BE0F7948F -:10462000819B8065514DC0B7B838C0A1C0E009AECC -:10463000380E0E4264E0481AE0D51FE0D62FA67E61 -:10464000B04A6DAA0500808800908CC0A02E600C36 -:104650000CE811A7882F8285ADEE0F4F0B2F8685B2 -:104660002B600622E4CF68B12A296015C0B2C99A2E -:10467000D2A02D61022B64060CDD022D6502D10F44 -:10468000C0E008AE387EB0B763FFAB00226406D24C -:10469000A0D10F00D2A0D10F00CC57DA60DB30DC04 -:1046A0004058088FC020D10FDA6058092063FFE816 -:1046B0000028221E29221D789902280A00C176C1ED -:1046C000C1C1D21BE0C2C124AB6B6480437891406E -:1046D0002A80000CAF0C64F0AE0DAE0C64E0A802B2 -:1046E000AF0C64F0A207AE0C64E09C2FACE864F061 -:1046F000962EACE764E0902FACE664F08A2A80073F -:1047000008A80B088A027B83022A8DF8D8A065AF1F -:10471000BBC09060007300002B600C0CB811A78820 -:104720002E82866EE87909BA0A2AA2A368A0048EAE -:10473000607AE96B2A828564A0651FE0AAC0E32E37 -:1047400064069EA19FA01FE0D62E600A92A30FEEE2 -:10475000029EA28E600FEE029EA42F60147AFF4785 -:1047600022A4172F8285ADBE22E4CF2FFC182F86FE -:104770008563FE702A6C74C0B1DC90DD40580795EB -:104780001DE08FC0C163FEC4D9A0DA60DB30DC401D -:10479000DD50C2F0C1E009FE395807DCD2A0D10FCC -:1047A000DA605808E263FEF02CA4172982850DBE5A -:1047B0000822E4CF299C1829868564500C2A6C7441 -:1047C000044B02580169D2A0D10FC020D10F0000C4 -:1047D0006C10062B221E28221D93107B8901C0B06D -:1047E000C0C9C03BC1F20406401DE078C0E2C074FD -:1047F0000747010E4E01AD2D9E11C0402E0A1464D4 -:10480000B06E6D084428221D7B81652AB0007EA110 -:104810003B7FA1477B51207CA14968A91768AA1456 -:1048200073A111C09F79A10CC18B78A107C1AE29DA -:104830000A1E29B4007CA12B2AB0070BAB0BDAB0FF -:104840007DB3022ABDF8DBA0CAA563FFB428B0106F -:1048500089116987BB649FB863FFDC00647FB46320 -:10486000FFD50000646FD0C041C1AE2AB40063FF21 -:10487000C62B2102CEBE2A221D2B221E7AB12A8CE3 -:10488000107CB1217AB901C0B0C9B913E043DA2074 -:1048900028B0002CB00703880A28824CC0D10B80B6 -:1048A00000DBA065AFE7D240D10F8910659FD463CC -:1048B000FFF300006C1008C0706451718F30292123 -:1048C000020F0F4716E036090C4C65C08F8D300D76 -:1048D0006E5168E30260008428629E1AE02F6E88A1 -:1048E000522AA22668A0048B207AB9472A629DB07A -:1048F0004ECBAF9A102B200C9E110CBC11A6CC29CC -:10490000C286B748798B4117E02607B70A2772A3FA -:1049100068700488207789302CC2859C12D7C065C6 -:10492000C0622C21041AE05D7CAB22DA2058069389 -:10493000600029002E21041DE0597EDB18DA20C01A -:10494000B658068EC958600156C0C063FFCCDA2045 -:10495000580876600006DA20C0B658087465513FE2 -:10496000DC40DB308D30DA200D6D515806E8D3A0E5 -:1049700064A12CC05129210284A18FA00404470FF7 -:104980000F4763FF412B2104C08C8931C0A009F976 -:1049900050098A386EB81E2C2066AFCC0C0C472C00 -:1049A00024667CAB109E142A12005806FA8E14C09E -:1049B000D02D24668D30C0921BE010C1F87FD60C3C -:1049C00087129B702976012F7408277C106550B7D9 -:1049D000B83AC0D7DC70C051C080075838080842C8 -:1049E0006480791DDFEA19DFEB29D67E6A420AD39B -:1049F0000F6DE90500A08800C08CC0A08830C0926F -:104A00007F863807E80B2F84089B809981B4E82CB7 -:104A1000200CC0901DDFEA0CC311A633223285ADF5 -:104A2000CC02820B29C4CF223685D2A0D10F8A3086 -:104A3000C0F17EAE3229210263FE88002C200C8E4C -:104A400011C0B01DDFDE0CCF11A6FF22F285ADCC68 -:104A50002BC4CF02EE0B2EF685D2A0D10FC0800A58 -:104A6000583878D08663FF7A9F13DB30DA20C0C1D4 -:104A7000DD705BFF572921028F132A9CFE65AE4330 -:104A8000272502C09063FE3B9E142A2C74C0B1DC23 -:104A900070DD405806D08E141BDFD8C1F863FF5B71 -:104AA000C020D10F6C100628210216DFBC08084C6C -:104AB00065821529629E6F980260021C19DFB72972 -:104AC00092266890078A2009AA0C65A20B27629D8E -:104AD000C0CC6472032B21048E31C0A0DDA00EFE79 -:104AE000500ECD386EB8112C20662CCC010C0C4722 -:104AF0002C24667CDB026001EAC0C12930081BDF80 -:104B0000A96490972F0AFFC0D3B09E64E0FD68921D -:104B10000E6450832A2C74DB40580093D2A0D10F2E -:104B20002B200C2721040CBC11A6CC29C286280AF4 -:104B3000087983026001B919DF9A09B90A2992A399 -:104B40006890082E220009EE0C65E1A42EC285644F -:104B5000E19E26200713DFA36E7B0260019A17DF18 -:104B60009A1FDFA319DFD0C0D228200A93E09DE16D -:104B7000A9690F880298E22F90802A9480B1FF07DC -:104B8000FF029FE31EDF8E2FC285AEBE0FDF0B2F0D -:104B9000C6852AE4CF655F7BC020D10F2F30102956 -:104BA00030112E301300993200ED3264F0EE2A30CD -:104BB000141FDFBD00AA3278EF050F9E092DE47F98 -:104BC0001EDFBB66A0050F98092A8480B4A718DFF2 -:104BD000B8C76F009104AE9EDDE000AF1A00C31AA3 -:104BE0006EE1052DB2000DED0C1EDFB208D81C06DB -:104BF0003303AE882A848B2EB02E27848C03EE01DB -:104C00000FEE022EB42E58018F63FF0429310829BC -:104C100025042830142E3109B0886480A32E240A7C -:104C2000C0812E30162CB4232E240BB4EF2F240C6D -:104C30008C378B36292504DEB0DFC00F8F390E8EFE -:104C4000390FEE0264EEC9089F1101C4048D380CBF -:104C5000B81800C4040CBE1800EE110EDD02C0E34B -:104C60000EFF021EDF879F719E701EDF848F2098CB -:104C7000739D7405FF110BCD53C18098750FDD0234 -:104C80000EDD029D722A24661EDF442F629D2AE4F7 -:104C9000A22FFC182F669D63FE760000002F3012B5 -:104CA0001BDF8600FA3278FF050B980B2A847F669B -:104CB000D0050B9A0B2DA4802A301100AA3263FF75 -:104CC000442F240A9E2B63FF56CC57DA20DB30DCBE -:104CD00040580703C020D10F00DA20C0B658079310 -:104CE00063FFE500DA7058062BC0A02A246663FE35 -:104CF00007DA2058078E63FFCFB16928200A862083 -:104D0000090947991129240798107F812693E027E4 -:104D1000E50A9AE388109DE119DF628D11096F029F -:104D20009FE42DE416098802C0D398E22A24076381 -:104D3000FE5100001FDF2B08691188118D2B93E0B5 -:104D4000098802C09F98E50FDD020478119DE2C03A -:104D5000F49FE1C0D409880298E463FFCE0000000C -:104D60006C1004C020D10F006C100485210D381187 -:104D700014DF088622A42408660C962205330B93C0 -:104D800021743B13C862D230D10FC030BC299921A5 -:104D900099209322D230D10F233DF8932163FFE372 -:104DA0006C100AD620941817DEFDD930B83898193F -:104DB0009914655252C0E1D2E02E61021DDEFA0E56 -:104DC0000E4C65E1638F308E190F6F512FFCFD651E -:104DD000F1568EE129D0230E8F5077E66B8F181E87 -:104DE000DF37B0FF0FF4110F1F146590CE18DF34BA -:104DF0008C60A8CCC0B119DEE828600B09CC0B0D83 -:104E0000880929811C28811A2A0A0009880C08BAF5 -:104E1000381BDF2A0CA90A2992947B9B0260008C24 -:104E20002B600C94160CBD11A7DD29D286B84879E9 -:104E300083026000D219DEDA09B80A2882A3981723 -:104E40006880026000A36000A51ADF1E84180AEEC5 -:104E500001CA981BDED18C192BB0008CC06EB31325 -:104E60001DDECE0C1C520DCC0B2DC295C0A17EDBDD -:104E7000AE6000380C0C5360000900000018DF1011 -:104E80008C60A8CCC0B119DEC428600B09CC0B0D16 -:104E9000880929811C28811A2A0A0009880C08BA65 -:104EA000380CA90A2992947E930263FF72DA60C0DB -:104EB000BA58071E64507460026600001ADEB78C90 -:104EC000192AA0008CC06EA31A18DEB30C1C52085D -:104ED000CC0B18DEFA2BC295C0A178B30263FF3F5A -:104EE00063FFC9000C0C5363FF0989607899182986 -:104EF000D285C9922B729E1DDEA86EB8242DD226B3 -:104F0000991369D00C60000EDA6058070860001829 -:104F1000000088607D890A9A1A29729D9C12991551 -:104F2000CF94DA60C0B65807016551F48D148C181F -:104F3000DBD08DD0DA600D6D51580574D3A09A1472 -:104F400064A1DD82A085A1B8AF9F190505470202C3 -:104F5000479518C05163FE602B6104C08C8931C035 -:104F6000A009F950098A386EB81F2C6066A2CC0CD3 -:104F70000C472C64667CAB119F119E1B8A1558054B -:104F8000858E1B8F11C0A02A64669F1164F0E18991 -:104F9000138819DEF06DE9172F810300908DAEFEA6 -:104FA0000080889F9200908C008088B89900908C37 -:104FB00065514E8A10851A8B301FDE8A881229604F -:104FC0000708580A2C82942D61040ECC0C2C869470 -:104FD0006FDB3C1CDEB4AC9C29C0800B5D50A299F9 -:104FE00009094729C48065D0DA2E600CC0D01FDEC5 -:104FF000730CE811A788228285AFEE02420B2DE4E4 -:10500000CF228685D2A0D10F8E300E0E4763FDA62B -:10501000A29C0C0C472C64077AB6CD8B602E600ADC -:10502000280AFF08E80C64810E18DE9D831682139F -:10503000B33902330B2C34162D350AC02392319F1D -:1050400030C020923308B20208E80292349832C08D -:10505000802B600C286407D2A01CDE580CBE11A760 -:10506000EE2DE285ACBB28B4CF0D9D0B2DE685D18E -:105070000F8B1888138D30B88C0D8F470D4950B4A5 -:10508000990499100D0D5F04DD1009FF029F800D3A -:10509000BB029B8165508D851AB83AC0F1C0800C67 -:1050A000F83808084264806B1BDE3919DE3A29B6ED -:1050B0007E8D18B0DD6DDA0500A08800C08CC0A020 -:1050C00063FEF3001DDE4B28600A82138B16C0E0DE -:1050D0002EC48002B20B0D8802B2BB99239F20C060 -:1050E000D298229D2122600C0C2D11A7DD28D2859B -:1050F00008BB0B18DE322BD685A8222E24CFD2A0D7 -:10510000D10F9E1B851A2A6C748B185BFF178E1BA0 -:1051100063FEA300C087C0900AF93879809263FFCC -:1051200086C020D10F9E1B2A6C74C0B18D18580503 -:10513000298E1B851A63FE7E886B8213891608BE32 -:10514000110ECE0202920B9E25B4991EDE259F20E1 -:105150000E88029822C0EF04D8110E88029824C04D -:10516000E49E21C080D2A02B600C2864071CDE13B3 -:105170000CBE11A7EE2DE285ACBB28B4CF0D9D0B64 -:105180002DE685D10F0000006C1004C020D10F0067 -:105190006C10048633C071C030600001B13300313F -:1051A0000400741A0462017460F1D10F6C100402DF -:1051B0002A02033B025BFFF61DDDFB1BDE43C79F9C -:1051C00088B009A903098A019AB02BD10279801B02 -:1051D0001CDDF3C0E00EE4310002002AC2821DDEB5 -:1051E0003B0DAA022AC6820BE431D10FC1F00FBFDA -:1051F000020F0F4F2FD5020FE431D10F6C100412A4 -:10520000DDE91ADDE6C0C00CE43100020029A2820B -:1052100018DE311BDE2F2621020B990108660129B9 -:10522000A68226250206E43114DE2C15DE27236A29 -:10523000902326128550242611252613222C40D196 -:105240000F0000006C100816DE252B0A642C1AB41F -:1052500017DDD51DDDD118DE220F2E110D2A11B25A -:10526000E90EEE11A8A80E9911ADAAA799A7EE9E76 -:10527000169911ACAA9A152C80FF2A80FE288D0160 -:1052800029800108AA112880000CAA0208881109A7 -:10529000880208AA1CB88828160058085D297116CB -:1052A0009A122916038A158B122AA0800BAA288B22 -:1052B00010580857D4708C168B1315DE0A0BAB28C8 -:1052C000235C419B142BC6282C308072C9158C148A -:1052D0002A50C02B3A200CAA2858084DC0D10ADD0C -:1052E000372D4540B444B255B2337639DAB2778FB0 -:1052F000118E168815B4EEB18898159E167FE9A414 -:10530000D10F00006C1004C021D10F006C1006C03A -:10531000701ADDA21EDDAD1DDDB31CDDB51BDD9EEB -:1053200013DDE1220A0818DD9F14DDEF28802E240A -:1053300040002816006D2A70A349289080C0F164AF -:1053400080598510004104C06100661A06550105A8 -:10535000F5390C56110A66082F62966EF74D0B5FF1 -:105360000A2FF22468F00812DDD102420872F93BDC -:105370002362950C4202CB349232C0F29D309F31B1 -:105380000E8F029F33236295AB522F0A002F948019 -:105390002F24A0233C1023669513DDC2B17712DDC4 -:1053A000D2B144040442242400D10F00D10FD10F04 -:1053B0006C10041ADD792AA00058021B5BFFD3028F -:1053C0002A02033B025BFFCF1BDD77C0C429B10279 -:1053D000C8AC0C9C020C0C4F2CB5020CE431D10F64 -:1053E0001EDD6FC08008E4310002002DE2821FDD67 -:1053F000800FDD022DE68209E431D10F6C10041517 -:10540000DD6716DD68C02002E4310002002452820C -:10541000226102734F0602E431C020D10F18DDB4BF -:1054200019DDB308280109490129568228650208B7 -:10543000E43113DDA9226C7023661DD10F0000003A -:105440006C1004292006289CF96480A02A9CFD6524 -:10545000A0968A288D262F0A087AD9042B221FC8E5 -:10546000BD2C206464C0812E22090EAE0C66E0784B -:105470002B200C1EDD4A0CBC11AECC28C28619DDD7 -:105480004878F3026000A909B90A2992A368900834 -:105490002E220009EE0C65E09729C2851FDD5264BB -:1054A000908E9F90C0E41FDD5F9E9128200AC0E08F -:1054B0009E930F8802989288200F880298942F203C -:1054C000079A979D962F950A2E24072820062920B3 -:1054D0006468832F28C28512DD39288C20A2B22E61 -:1054E00024CF28C685C020D10FC020D10F2A206A22 -:1054F0000A2A4165AF55DA20C0B05805D364AFE839 -:10550000C021D10F649FCC1FDD272D20168FF209FB -:10551000DD0C00F10400DD1AADAD9D2928C2851215 -:10552000DD27288C20A2B22E24CF28C685C020D10A -:105530000FC021D10F0000006C1004260A001BDDF3 -:105540006D15DD1828206517DD15288CFE64809404 -:105550000C4D11ADBD2CD2F52BD2F42A51027CB1E9 -:10556000422A5102B4BB2ED2F72BD6F47BE9052B8D -:10557000D2F62BD6F47CB92B29D2F629D6F529D62A -:10558000F406E4310002002F7282C79F004104C07C -:105590008100881A09880308FF012F76820AE43106 -:1055A000600000002624652BD2F48E5A2CD2F5B070 -:1055B000EE9E5A7BCB1629D2F62FD2F70CB80C09E7 -:1055C000FF0C08FF0C0F2F14C8F960002F0BCD0C37 -:1055D0000D2D14CED6C0E20EAE020E0E4F2E550289 -:1055E0000EE431D10FDB30DA205BFF951BDD426426 -:1055F000AF5D2A51020C4D11ADBD63FFA906E43128 -:105600000002002E72821FDD000FEE022E76820A4B -:10561000E431D10F6C100416DCE115DCE2C030037C -:10562000E43100020024628274472118DD33875A76 -:10563000084801286682CD7319DD310C2A11AA9918 -:105640002292832992847291038220CC292B5102C9 -:105650000BE431C020D10F001FDD2A2E51020FEEC6 -:10566000012E55020EE431B02DB17C9C5A225C60B3 -:1056700008DD112D5619D10F6C100A1ADCC71DDC7C -:10568000C923A00019DD206F33791CDD07C0281560 -:10569000DD1F1EDD1D2B1C10D4B083E0005086954D -:1056A0001000408A94186D2A4F0F35110C340924CC -:1056B00040800A560A2862940D55092F51400F4424 -:1056C000110B440A08970C0F77368F400F7736225C -:1056D000514107FF0C9F40A8772F62952766940FD2 -:1056E000980C0288368741078836B13308770CAFAB -:1056F0008F2F66959741030342B13808084298E01E -:10570000D10F00001CDD0314DD03BFC52442B564C6 -:105710003055C091C0D016DD000488432BC000C0B6 -:10572000406D393E00410400971A7780162FA295EC -:105730008E50AFEE2EED2006EE369E502DA69560D3 -:10574000001A000077B00983509D5023A695600091 -:105750000223A295223D2006223622A695B144B40A -:1057600055B8AA28C400D10F04884328C400D10F1B -:105770006C100415DCEA13DCEAC04004E4310002DA -:10578000008850CB815BFFBC1CDCE70C2D11ADCC3D -:105790002BC2822AC28394507BAB142EC28429C2AE -:1057A000850ABD0C0E990C0D990C09291460000591 -:1057B0000BA90C092914993015DC7B2A51020AE443 -:1057C000312A2CFC5800492B32001EDC742BBCFF04 -:1057D0002B3600CCB5C8A3D2A0D10F00D2A004E4D0 -:1057E000310002002DE2822C51022FBAFF0FDD01A1 -:1057F0002DE6820CE431D10F6C1004D10F000000B3 -:105800006C1004C020D10F006C100413DCC7C0D191 -:1058100003230923318DC0A06F34026000891BDC93 -:1058200061C7CF18DCC00C2911A988268283258284 -:105830008219DC5A7651442752002E8285255C0459 -:1058400025868275E9052582842586827659542627 -:105850008284D5602686822686830AE4310002008F -:105860002392822FB10200210400D41A0C440304B5 -:1058700033012396820FE43160000200D7A07659ED -:10588000220AE4310002002E928200210428B10293 -:1058900000DF1A0CFF030FEE012E968208E431D2CE -:1058A00070D10F00D270D10FC020D10F6C1004DB6B -:1058B00030862015DC39280A00282502DA2028B095 -:1058C000002CB00705880A28824C2D0A010B8000A5 -:1058D000DBA065AFE61ADC320A4A0A29A2A3C7BFD9 -:1058E000769101D10F2BA6A3D10F00006C1004C03C -:1058F000D1C7CF1BDC2CC0A018DC280C2911A9882B -:105900008785858419DC2677517986508E87B45532 -:10591000958475E9038586958477596C8F869F8574 -:105920009F840AE431000200239282B42E00E10435 -:105930002FB10200D41A0C44030433012396820FC2 -:10594000E4310AE43100020023928200D41A0C44AC -:10595000030433012396820FE431D260D10F00009B -:105960000AE431000200239282B42800810422B1AB -:105970000200D41A0C440304330123968202E4315A -:10598000D2A0D10FD6A07751D6D260D10F0000009F -:105990006C1004270A801CDC281DDC281ADC000C93 -:1059A0002911AA992A2CFC2B92850DAA029CB19A46 -:1059B000B0C05113DC2528928516DC2114DC22A608 -:1059C0002604240AB888289685234691A76625646C -:1059D0009FD10F006C100419DC550C2A11A9A9895C -:1059E00090C484798B761BDC45ABAC2AC2832CC275 -:1059F000847AC1688AA02BBC30D3A064A05E0B2B34 -:105A00000A2CB2A319DC0F68C0071DDC49D30F7D37 -:105A1000C94AA929299D0129901F68913270A603BE -:105A2000D3A0CA9E689210C7AF2AB6A32A2CFC5BEB -:105A3000FFAFD230D10F000013DBEF03A3018C3195 -:105A40001DDBE00C8C140DCC012CB6A363FFDC0035 -:105A5000C020D10FDA205BFFCEC020D10FC020D1F3 -:105A60000F0000006C1004DB30C0D019DBCBDA2053 -:105A700028300022300708481209880A28824CDCA6 -:105A8000200B80001BDBC60C4A11ABAA29A284099B -:105A9000290B29A684D10F006C1004C04118DBBF6C -:105AA00017DBC10C2611A727277030A86625628650 -:105AB000007104A35500441A75414822628415DB25 -:105AC000E202320BC922882117DBBE088414074486 -:105AD00001754905C834C020D10FD10F1DDC15C098 -:105AE000B28E201FDBAD0E0E43AFEC0FEE0A2BC4BF -:105AF000A02DE624C0202A62840809470A990B29B0 -:105B00006684D10FC020D10F6C1004DB30C0D018D8 -:105B1000DBA2DA2025300022300708580A28824C00 -:105B2000DC200B80008931709E121BDB9C0C4A111B -:105B3000ABAA29A28409290B29A684D10F09C9522D -:105B400068532600910418DB97C0A12F811200AA88 -:105B50001A0AFF022F85121EDB910C4D11AEDD2CAF -:105B6000D2840C2C0B2CD684D10FC0811FDB8EB8B5 -:105B70009A0A0A4700A1042EF11200881A08EE02C0 -:105B80002EF5121DDB860C4C11ADCC2BC2840B2BD9 -:105B90000B2BC684D10F00006C1004DB30C0D01971 -:105BA000DB7EDA2028300022300709880A28824C60 -:105BB000DC200B80001CDB790C4B11ACBB2AB284BF -:105BC0000A2A0B2AB684D10F6C1004C04118DB736B -:105BD00016DB750C2711A626266030A872252286B2 -:105BE000006104A35500441A754108222284023240 -:105BF0000BD10F00C020D10F6C100415DBCE024971 -:105C000014295611245212C0730208430F88110040 -:105C1000810400361AC78F00771A087703074401FA -:105C2000064402245612D10F6C1006C0B06E230237 -:105C30006000A264209D851013DBAA16DBBEC04065 -:105C4000A6BA2BA2AE0B194164905E68915568927A -:105C50004A6893372930FF2830FE2AA2AA08881103 -:105C60000A0A4D2AACF20988027589442B3D0129A4 -:105C7000B0002BB0010899110B99027A9932B83310 -:105C80002B2A00B1447249B7600048007FBF051558 -:105C9000DBAA63FFBE253AE863FFB800253AE86354 -:105CA000FFB10000250A6463FFA9C05A63FFA40086 -:105CB00000705F082534FF058C142C34FE70AF0B88 -:105CC0000A8D142E3D012AE4012DE400DA405BFD2B -:105CD0005D63FFA9D10FD10F6C10041ADB3219DB01 -:105CE0002F1CDB961BDB97C080C07160000D00008D -:105CF0000022A430B1AA299C107B915F269286795C -:105D0000C215C0206E62E96D080AB12200210400AC -:105D1000741A764BDB63FFEE2292850D6311032527 -:105D200014645FCFD650032D436DD9039820B4225D -:105D30000644146D4922982098219822982398248B -:105D400098259826982798289829982A982B982C4F -:105D5000982D982E982F222C4063FF971EDB10273A -:105D6000E68027E681D10F006C1004C062C04112AA -:105D7000DB0D13DB7423322D1ADB0819DB6E2AA02E -:105D8000002992AE6EA30260009128ACFE090D407E -:105D90002C1AC2C2BD0DCB392B25166480895BFF3E -:105DA000A215DB691ADB142B3AE80A3A0158059868 -:105DB0002B21160ABB28D3A02B56005805AF8B50B9 -:105DC0000ABB082A0A005805AE15DB602D21022CFB -:105DD0003AE80C3C2804DD022D25029C505805A60B -:105DE0008B50AABBC0A15805A61CDB592D21020C63 -:105DF0003C2806DD0213DB572D25029C3058059EFA -:105E00008B30AABBC0A258059E2A2102C0B40BAA9F -:105E1000020A0A4F2A25025805B2D10F242423C3AF -:105E2000CC2C251663FF760018DB4F1CDB4B19DBEF -:105E30004C1BDB4A17DB1F85202E0AFD1FDB4B2D79 -:105E4000202E24F47A24F47E24F4820EDD0124F43E -:105E5000862E0AF707552806DD02C0750EDD0105FE -:105E60000506AB5BA959C0E8AC5C24C4AB0EDD02EF -:105E700027C4AC2E0ADFA85527B4EC0EDD0124B4EC -:105E8000EBC2E027942C0EDD0224942B2E0A800D09 -:105E90000D4627546C24546B0EDD022D242E63FE18 -:105EA000FC0000006C1004C3A0C0B35BFF53C04AE9 -:105EB00012DB21C380282616242617C3A1C0B35B9A -:105EC000FF4EC03CC3A12A261619DAB6299020231A -:105ED000261764908F2A0A322B0A015BFF47C3A260 -:105EE0002B0A015BFF45C3B22B2616232617C2AF30 -:105EF000C0B15BFF41C2FF2F2616C0EE2E2617C28F -:105F0000D22D2616C0C82C26172426112A2212C7E5 -:105F1000B30BAA01C0B40BAA022A2612290AA1298E -:105F20002616C182282617C0B32B26112E22121F37 -:105F3000DACA0FEE022E2612C3D62D26162A0AA280 -:105F4000C1C32C26175BFF2C2C0AA22C2616C1B528 -:105F50002B2617C2AB2A2616C09729261718DB0353 -:105F6000282610D10FC3A2C0B35BFF2363FF6E00CE -:105F70006C10041CDACE1BDABB18DAFD17DAFE1639 -:105F8000DAFE15DAFEC0E0C0D414DACA1FDA8622BF -:105F90000A082FF2006D2A36DAC0D9C07C5B020FE6 -:105FA000C90C1CDAC30C9C28A8C3A6C22A36802AB6 -:105FB0002584A4C2A7CC2D248C2B248A2B24872EA5 -:105FC000248BB1BB2E369F2C369E2C369DB1AC1C3B -:105FD000DAA51BDAEBC0286D2A33DAC0D9C07C5BA6 -:105FE000020FC90C1CDAB30C9C28A8C3A6C22A361F -:105FF000802B2584A4C2B1BBA7CC2D248C2E248B4E -:106000002A248A2E369F2C369E2C369DB1ACC07920 -:1060100019DAA31BDADE13DADB1ADADB18DADD149D -:10602000DAA416DADC04F42812DADC04660C0405BF -:1060300006A252A858AA5AA3539B3029A500278428 -:106040008AC091C0A52A848C29848B17DAD518DAE6 -:10605000D3A75726361D26361E2E361F16DAD21324 -:10606000DAD2A65504330C2826C82E75002D54AC60 -:106070002E54AB2E54AA2326E62326E52E26E7D15E -:106080000F0000006C100613DAAF17DAAA24723D75 -:106090002232937F2F0B6D08052832937F8F026386 -:1060A000FFF3C0C4C0B01EDA3FC061D940096939EE -:1060B00029E4206E4401D6B0C328DFB026E42206CE -:1060C0002F392FE421C0501FDAB919DAAA16DAAB3A -:1060D00018DA7994102A72458DE017DAA59D111D02 -:1060E000DAB46DA94BD450255C037A5B18DE507589 -:1060F0006B052E12010E5E0C12DA6E02E2280111FF -:1061000002AF2222D681D54013DA6A746B052512BC -:106110000105450C035328B145A83EA932A73322F7 -:10612000369D22369E2436802B369F2BE48B2CE422 -:106130008C14DA8424424DC030041414C84C6D0809 -:1061400006B133041414C84263FFF20016DA13C414 -:1061500040C1580031041ADA13C0B193A200BB1A2F -:10616000B0BB9BA318DA7829824D23824E28825334 -:106170007A871C2C64008C106FC4481EDA0A043D18 -:106180000C2DE51C2FE11D2DE51A2FE51BD10F006D -:10619000C07212DA6882207E27DB03034F27640077 -:1061A0008810C0616F8430C0A00319140A54391AD2 -:1061B000D9FD04990C29A51C29A51D29A51A29A5D5 -:1061C0001BD10F001CD9F8053B0C2BC51C2DC11D84 -:1061D0002BC51A2DC51BD10F065439031E1404EE0E -:1061E0000C2EA51C2EA51D2EA51A2EA51BD10F0009 -:1061F0006C10081AD9EC14DA4F13DA52C72FC050BA -:1062000016DA6C2566A82566A92566AA2566AB223E -:1062100036292B424519DA13D8101CDA66C0D49DF2 -:10622000119C100080890B990C99A02816025BFF25 -:10623000952A32E31FD9DC0A5A149AF42932E4B1C0 -:10624000990959140A990C99F52832E508581498B7 -:10625000F62E32CD0E5E142EF6075BFF455BFF1166 -:1062600022463B1CD9D02AC102C1B00BAA021BDABC -:106270002A0A0A4F2AC5022B463A5804995BFEBAED -:106280005BFE95C0B0861317D9C525362DC74EC005 -:10629000309414C05014D9CA60004300007F9F0F8F -:1062A000B155091914659FF4C0500AA9027FA7EFE0 -:1062B00018D9BADA5008580A28822C2B0A000B8009 -:1062C00000005104D2A0C091C7AF00991A0A9903E7 -:1062D000291604CE33642063D3202B2007D6508C9C -:1062E000142A72827CA85C18D9AC08580A28822C1F -:1062F000DA500B8000D2A0643FDA8A310A8A140493 -:10630000AA01C82A2B22010B8B1404BB017AB940C5 -:10631000DDA06EA1081DD9A32DD2000DAD0CDB3080 -:10632000DC601AD9E318D99C0ADA2808680A1DDA51 -:106330001F28823CADAA0B8000652F9BD320C0B0E4 -:1063400063FF9B00CA5CB1550050040A091963FF42 -:106350004BDCB06EB1091CD9938CC0D30F0CBC0CB4 -:106360001DD9D41EDA120DCD28AEDD1EDA112DE6B0 -:106370008163FF9B7FA7CE63FF6C00006C10041B42 -:10638000D98727221EC08008E4310002002AB28289 -:1063900019D985003104C06100661A2991020A6A80 -:1063A000022AB68209E43115D9DF0C3811A8532826 -:1063B00032822432842A8CFC7841102921022A3628 -:1063C0008297A0096902292502D10F002B21022CF6 -:1063D00032850B6B022CCCFC2C368297C02B25020D -:1063E000D10F00006C1006C0C71BD9681AD96A0DFE -:1063F0004E11D72088208522D98005450B02820CBA -:106400009572222CF4C8346F2E026000AB1FD96045 -:10641000A9E2AF7D72D334C93DC0212F0A00092FF4 -:10642000380F0F42C9F92AB67E6D4A050030880040 -:10643000908C22720002E20872D1749270D280D1E4 -:106440000FC05003253875C0DF63FFD9097D0CAF3D -:10645000DD0DEE0C64304ED2300D3F1296112F162A -:10646000002FFC100F4F36260A01250A0009653857 -:106470000505426450712AB67E6DFA050020880039 -:10648000908CC050A3D28910237C0C09440C290A9B -:106490000103953805054264505A2AB67E6D4A05B7 -:1064A00000208800308CD280A7EABCAA9A70D10F55 -:1064B000D280BC7B9B70D10F00023F14C1D0D23080 -:1064C0000FDD0C0D4D36298D08C0F1250A0009F5A8 -:1064D00038050542CA582AB67E6DDA0500208800C4 -:1064E000908C897063FF2500C061C05003653875CA -:1064F000C08663FF80C0D0029D387DC09F63FF9936 -:10650000C05003F53875C0D063FFCA006C1004D6C4 -:106510002068520F695324DA20DB30DC405800F049 -:10652000D2A0D10FDA20DB30DC405800ED9A2424D1 -:10653000240EC02122640FC020D10F00B83BB04C04 -:106540002A2C7489242D200E2E200FA4DDB1EE2ECE -:10655000240FB0DD2D240E2890072D9003A488B0C1 -:1065600088B1DD2D94032894075BFF9E69511DC0FF -:10657000E082242A600F18D9902A240329600E8F04 -:106580002029240708FF029F209E64D10FC020D13C -:106590000F0000006C1004942319D988C0B3083A86 -:1065A000110BAA02992019D8FD9A2128929D16D87C -:1065B000FAC0502564A2288C1828969DD10F00009F -:1065C0006C1004282066C038232406B78828246667 -:1065D000D10F00006C1006035A0C0D36110D5C1122 -:1065E000D8208B2282210CBB0C06550F9B820232D5 -:1065F0000B928113D8E7D920A38F6450531CD8E3A2 -:10660000C0D71BD8E4A256C0E1290A0004E9380922 -:10661000094276F34A044302C99E2BC67E6DAA0541 -:1066200000208800308C8981A95909FA0C64A0796E -:1066300099818A82C8ADD290D10FC06002E63876C7 -:10664000D0DA63FFD4C020BC89998199809282D12D -:106650000F7F2304292DF8998165BFD963FFE500D9 -:10666000028F0CA3FF0F3312931003AA0CD340CB5D -:106670009E2BC67E86106D6A0500208800308CBC7B -:1066800082290A0004F308240A010349380909424F -:10669000CA982BC67E6DAA0500208800308C0F5941 -:1066A0000CA989BC99998163FF87BC89998163FF93 -:1066B00080C06002E63876D0BA63FFB4C07002478B -:1066C0003877D0D063FFCA006C100414D8C0C15210 -:1066D000A424C93E28221D738119292102CD932AA1 -:1066E000300075A912DA20DB302C3007C0D25801F7 -:1066F000C4653FDFD10F00002B300703BB0BDAB0BE -:1067000074B3022ABDF8D3A063FFC6006C1004293D -:106710002006C0706E9741292102C08F2A2014C024 -:10672000B62B240606AA022A241479800227250201 -:106730002A221E2C221D7AC10EC8ABDA20DB302C97 -:106740000A00033D025BF8226450752D21020D0DF5 -:106750004CC9D3C020D10F00002E9CFB64E0822FD7 -:1067600021020F0F4C65F0911AD88D1CD88B29A2ED -:106770009EC08A798B5D2BC22668B0048D207BD9A0 -:106780005229A29DC0F364904A97901DD89E2E2155 -:10679000049D9608EE110FEE029E979E9127C4A2CB -:1067A00018D89A2F21022BA29DC0E52E24062BBCBF -:1067B0003008FF022BA69D2F2502C020D10F00001C -:1067C000002F300068F938DA20DB30DC4058004414 -:1067D00063FF7700022A022B0A065800D4220A001F -:1067E000D10F655010283000688924022A02033B2B -:1067F00002DC4058003BC020D10FD270D10F000006 -:106800002A2C74033B02044C025BFEF663FF3B0040 -:10681000DB30DC402A2C745BFEF3C020D10F00007B -:106820006C1004C83F89268829A399992609880CE9 -:10683000080848282525CC52C020D10FDB402A2C3F -:10684000745BF949D2A0D10F6C1004D820D73082E4 -:10685000220D451105220C928264207407420B130D -:10686000D84CD420A383732302242DF8858074513F -:106870004CBC82C0906D081600408800708C77393F -:1068800003D720C0918680743901D42074610263DB -:10689000FFE2CA98C097C0411BD8CAC0A00B8B0C9E -:1068A0000B4A380A0A42C9AA1DD8391CD83A2CD634 -:1068B0007EC140D30F6D4A0500208800308C978040 -:1068C000D270D10FBC8FC0E00F4E387E90E263FFD4 -:1068D000D6BC8292819280C0209282D10F000000AB -:1068E0006C1006C0D71CD8291BD82B0D4911D720F6 -:1068F0002A221F28221D0A4A0BD28007860C2A76DC -:106900001F266C80C8346F6E026000D02F0A801A78 -:10691000D82FA29EAA7A7EA33FC93FC0E1C05002F1 -:10692000E538050542CA552BC67EDB20D30F6D4ADC -:106930000500308800B08C2E721DAE9E0EA50C6432 -:10694000508AD2802E761DC091298403D10FC05069 -:1069500003E53875D0D363FFCD15D81C027E0CA596 -:10696000EE643055DA300E351296129511255C1012 -:10697000054536C0619510C0500265380505426472 -:1069800050892BC67E8510D30F6D5A0500A0880054 -:10699000208CC0A1A3E2C05023FA8003730C03A58E -:1069A00038AF730505426450722BC67E85110545CC -:1069B0000C6D5A0500208800308CD280C0A10E9B3F -:1069C0000CAB7BAFBB2B761D2A8403D10FD280C0CA -:1069D000C1AF7D2D761D2C8403D10F0000063F141E -:1069E000C1E0D2300FEE0C0E4E362A8D08C0F125D4 -:1069F0000A000AF538050542CA5C2BC67E6DEA0519 -:106A000000208800A08C22721D63FEFFC061C05070 -:106A100003653875D80263FF6B63FF65C05002A53C -:106A20003875D08763FF8100C06003F63876D0CC1C -:106A300063FFC6006C10042A201529201614D7D92C -:106A40000A990CCB9D2E200B04ED092BD11C09BCFF -:106A500036ACAA0CBB0C2BD51C0A0A472A2415CB32 -:106A6000A18B438F288942B0A800910400881AA8FE -:106A7000FF0FBB029B278F260FB80C783B1AC02054 -:106A8000D10F0000292102C0A20A9902292502C0C3 -:106A900021D10F008B2763FFDC2BD11C0CAA0C0A21 -:106AA0000A472A2415ACBB2BD51CC9AE8B438C28B6 -:106AB0008F42B0AD00F10400DD1AADCC0CBB029BDF -:106AC00027DA20B7EB580019C021D10F9F2763FFA9 -:106AD000EF0000006C100428203C64304705306053 -:106AE00000073E01053EB156076539054928C77FB5 -:106AF000A933030641076603B166060641A6337E45 -:106B0000871E222125291AFC732B1502380C0981B6 -:106B10006000063E01023EB12406423903220AD13A -:106B20000FD230D10FC05163FFC000006C10041DA4 -:106B3000D79B27221EC08008E4310002002CD2829D -:106B40001BD799003104C06100661A2BB1020C6C8E -:106B5000022CD6820BE43119D81B0C3A11AA9328C7 -:106B600032829780253282243284B455253682754C -:106B7000410A292102096902292502D10F2A21028D -:106B80002B32830A6A022B36822A2502D10F00009B -:106B90006C10041DD78219D78C27221EC08009775C -:106BA0000208E4310002002CD2821BD77E0031049F -:106BB000C06100661A2BB1020C6C022CD6820BE469 -:106BC0003119D8000C3A11AA9328328297802532C5 -:106BD00082243284B45525368275410B2A21020A5B -:106BE0006A022A2502D10F002B21022C32830B6B63 -:106BF000022C36822B2502D10F0000006C10041BE2 -:106C0000D7670C2A11ABAA29A286B438798B221B2C -:106C1000D76419D78B0B2B0A2BB2A309290868B0AC -:106C20000274B90D299D0129901F6E920822A28538 -:106C3000D10FC020D10FC892C020D10FDA205BEF56 -:106C40003DC020D10F0000006C100414D75428421E -:106C50009E19D7516F88026000B929922668900763 -:106C60008A2009AA0C65A0AB2A429DC0DC64A0A3BF -:106C70002B200C19D74B0CBC11A4CC2EC28609B901 -:106C80000A7ED3026000992992A36890078D20099B -:106C9000DD0C65D08B25C2856450852D2104C03064 -:106CA0006ED80D2C2066B8CC0C0C472C246665C021 -:106CB0007A1AD7521CD75B1DD7481ED74FC084986D -:106CC000519E5089209D569D54935793559C530A2D -:106CD00099021CD7BD1AD76499528F26995A985990 -:106CE0009E58935E9C5D935C9A5B0F0D4805DD1189 -:106CF0009D5FC0D81ED7320CB911A499289285AED9 -:106D0000BE23E4CF288C402896859F292D2406C0D9 -:106D100020D10F00CA32DA20C0B65BFF84C72FD162 -:106D20000FC939DA205BFF81C72FD10FDBD05BFEA3 -:106D3000192324662B200C63FF76C72FD10FC72F92 -:106D4000D10F00006C1004C85B29200668941C68F1 -:106D50009607C020D10FC020D10FDA20DB30DC40F5 -:106D6000DD502E0A005BFE69D2A0D10F2E200C1838 -:106D7000D70B0CEF11A8FF29F286C088798B751A02 -:106D8000D7080AEA0A2AA2A368A0048B207AB96469 -:106D900023F28564305E1CD7122A0A802D206829D0 -:106DA00020672821040B991104881109880208DD45 -:106DB00002C094284A1008DD0218D70A9931983089 -:106DC0008B2B9A379D340CBB029B32C0C09C359CE8 -:106DD000362A2C74DB40C0D318D6F929F285A8EEE8 -:106DE000299C2029F6852CE4CF2D2406DD405BFD6F -:106DF000F9D2A0D10FDA20DBE05BFF4CC020D10F2D -:106E00006C100AD6302A2006941028ACF86583FF4F -:106E10002B2122270A022A2124CC572AAC010A0A54 -:106E20004F2A25247ABB026003F72C21022A200C6A -:106E30000C0C4C65C38E2E22158D32C0F10EDD0C6C -:106E400065D40488381ED6D56483E18F37C0C8C0A6 -:106E5000960FC9399914B49B9B110D99119913C9B7 -:106E6000FB19D6D02990217F93138B148C205BFFC4 -:106E7000631ED6CADDA064A41C8F676000298C1134 -:106E80000CAD11AEDD28D2860AAB0278CB621AD6E1 -:106E9000C40ABA0A2AA2A368A0052C22007AC95003 -:106EA0002AD285DDA064A3D729212E09F9362A200C -:106EB0003C09F80C6F8D3ED7F0CB7F28211F08705E -:106EC00060010B3E00043EB1BC04CB39C74F0BBB85 -:106ED0000A07BB0A0B0C4104CC03B1CC0C0C41AC2F -:106EE000BBD4B0C0C27CA04C2A21257BAB4660003D -:106EF0002CC0A063FFACD79063FFBD00C092C74F0A -:106F00002C7C140C0B4104BB03B1BB0B0B41AB74C9 -:106F1000244C1479A01E2A212574AB18ACBB241A6A -:106F2000FC0ABC0C04C16000093E01043EB14809E2 -:106F300084390B440A8926882709880C74831DC06C -:106F40008098D88C649CD98B668A659BDB9ADA978B -:106F5000D57F730260013ACE5E600016009D15DA9F -:106F600020DB405BFEB48D151ED68D65A2568F6763 -:106F700063FFCB9D15DA20DB308C105BFE598D153D -:106F80001ED687C051D6A08FA7C0C08A6897DD9A49 -:106F9000DC8869896A98DE99DF8B6A8A69AB7B77BE -:106FA000BB022AAC019B6A9A698860C0A0088B1456 -:106FB000778701C0A1C09028203C9417951893169C -:106FC000C050C031C044048401043938089910C04D -:106FD00042048401043538083840832B0BA4100781 -:106FE00055102A211F0955020544020B19400A2A8F -:106FF000140799100585100433020A881114D6F37A -:10700000095502292104043302089911098802C094 -:107010009209880229212593D00929140499110A7B -:1070200099020955028A20891408AA110A99021A9C -:10703000D66F14D6E70A990299D1832A95D698D7A4 -:10704000851804330293D4841783168A658D66AA43 -:10705000CAAD7D77DB01B1AA07FF0C9A659D6688F2 -:10706000268C29A48808CC0C98260C0C482C2525A5 -:107070009F672A200CC0C01BD6510CA911AE99AB3A -:10708000AB2892852CB4CF8B13AB8828968563FDF3 -:10709000CD00C091C0F0C0B2C0C4886023203C982D -:1070A000120C3C010B3A010888140B88010A9F3826 -:1070B00007FF10089839C0A00C9A3807881008AA52 -:1070C000100AFF02C0A80A33010393392A210429B8 -:1070D0002125053C1008CC020A331108AA11092900 -:1070E0001403AA020499110BAA022B211F83140B6B -:1070F0002B140B99020C99028B201CD63C08BB1157 -:1071000003BB020CBB02832A8C2B647084886897B3 -:10711000DD98DC8769886A97DE98DF8812C070770F -:107120008701C0719BD199D60B78109AD717D6A931 -:1071300008F80208C80207880217D6A598D00737B2 -:107140000297D428200C295CFE2B2124C0F01AD6EB -:107150001B0C8D11AEDD2CD285AA882F84CF8F1306 -:10716000B0BBAFCC2CD6852A22152B2524B1AA2A58 -:1071700026156490DCC84F8C268B29A4CC9C260C49 -:10718000BB0C0B0B482B25256550E8C020D10F0008 -:107190000000C0709BD199D69AD7881293D4778774 -:1071A0000E18D600921A288022C021082738821A89 -:1071B00018D68A0B731003F30203C3020833029339 -:1071C000D063FF7E00CC57DA20DB608C105BFDC4FF -:1071D000292102689806689403C020D10F2B221E33 -:1071E000C09028221D2925027B8901C0B064BFE818 -:1071F00013D5EA2CB00728B000DA2003880A2882C9 -:107200004CC0D10B8000DBA065AFE763FFCA000074 -:1072100068A775DA20DB30DC40DD505BFECAD2A007 -:10722000D10FC1FDC19D29252C600003002F252C05 -:107230002F2467272468DA20DB308C10DD502E0ADB -:10724000805BFD32D2A0D10FC1F8C1A82A252C63E2 -:10725000FFDDC84F8C268B29A4CC9C260CBB0C0BC5 -:107260000B482B25252A2C74DB602C12005BFD7645 -:10727000D2A0D10F2A2C748B105BF6BBD2A0D10FF9 -:10728000DA205BFE2A63FF3C00DA20C0B15BFE6EB1 -:1072900065AF3163FB79DA202B200C5BFE3D63FF89 -:1072A0002300000012D64E8220028257C82163FFBD -:1072B000FC12D64A03E83004EE3005B13093209436 -:1072C00021952263FFFC000010D6469100920193A5 -:1072D00002940311D61D821001EA30A21101F0318F -:1072E000C04004E41600020011D63F8210234A0079 -:1072F000032202921011D609C021921004E43184B5 -:107300000383028201810000D230012300000000CB -:1073100010D636910092019302940311D60C82107C -:1073200001EA30A21101F131C04004E4160002006C -:1073300011D62D821013D5B4032202921004E43129 -:10734000840383028201810000D3300133000000F6 -:1073500010D6279100810165104981026510448192 -:1073600003CF1F92019302940311D5FA821001EA10 -:1073700030A21101F231C04004E41600020011D61F -:1073800019821013D59B032202921004E431840366 -:1073900083028201C010910391029101810000D407 -:1073A0003001430012D5CAC030283740283744285E -:1073B000374828374C233D017233ED03020063FF49 -:1073C000FC00000010D60B9100920193029403116F -:1073D000D6098210921011D5BC831003220292109C -:1073E00011D60612D5CD9210C04004E4160002005A -:1073F00011D5FD821013D5B5032202921004E43199 -:10740000840383028201810000D530015300000013 -:107410006C10026E322FD620056F04043F04745B9B -:107420002A05440C00410400331A220A006D490D5C -:1074300073630403660CB1220F22110313147363E8 -:1074400002222C01D10FC83BD10F000073630CC086 -:1074500021D10F000000000044495630C020D10F58 -:107460006C10020040046B4C07032318020219D170 -:107470000F020319C020D10F6C100202EA30D10FA5 -:107480006C1002CC2503F03160000F006F22050361 -:10749000F1316000056F230503F231000200D10FC6 -:1074A0006C1002CC2502F030D10F00006F220402D4 -:1074B000F130D10F6F230402F230D10FC020D10F71 -:1074C0006C1002220A20230A006D280E283740285B -:1074D000374428374828374C233D01030200D10F99 -:1074E0006C100202E431D10F0A004368656C7369C5 -:1074F0006F2046572044454255473D30202842756D -:10750000696C7420547565204175672031322030D4 -:10751000393A34333A303420504454203230303801 -:10752000206F6E2066656C69782E6173696364658F -:107530007369676E6572732E636F6D3A2F686F6D36 -:10754000652F66656C69782F772F66775F362E30EA -:10755000292C2056657273696F6E20543378782019 -:107560003030372E30302E3030202D203130303733 -:0C7570003030303010070000CC44A0D6B2 -:00000001FF diff --git a/firmware/cxgb3/t3fw-7.1.0.bin.ihex b/firmware/cxgb3/t3fw-7.1.0.bin.ihex new file mode 100644 index 00000000000..1042f755f68 --- /dev/null +++ b/firmware/cxgb3/t3fw-7.1.0.bin.ihex @@ -0,0 +1,1885 @@ +:1000000060007400200380002003700000001000D6 +:1000100000002000E100028400070000E1000288E7 +:1000200000010000E0000000E00000A0010000006E +:1000300044444440E3000183200200002001E0002A +:100040002001FF101FFFD0001FFFC000E300043C91 +:1000500002000000200069881FFFC290200069D0C4 +:100060001FFFC29420006A101FFFC29820006A84FC +:100070001FFFC29C200003C0C00000E43100EA3131 +:1000800000A13100A03103020002ED306E2A05000C +:10009000ED3100020002160012FFDBC03014FFDA5F +:1000A000D30FD30FD30F03431F244C107249F0D347 +:1000B0000FD30FD30F12FFD5230A00240A00D30F4A +:1000C000D30FD30F03431F244C107249F0D30FD327 +:1000D0000FD30F14FFCE03421F14FFCB03421F1296 +:1000E000FFCCC0302D37302D37342D37382D373CED +:1000F000233D017233ED00020012FFC4C0302F37E0 +:10010000002F37102F37202F3730233D017233ED6A +:1001100000020012FFBEC0302737002737102737F4 +:1001200020273730233D017233ED03020012FFB95F +:1001300013FFBA0C0200932012FFB913FFB90C028F +:1001400000932012FFB8C0319320822012FFB71312 +:10015000FFB7932012FFB715FFB316FFB6C030D715 +:100160002005660160001B00000000000000000088 +:10017000043605000200D30FD30F05330C6E3B1479 +:100180000747140704437631E604360505330C6F40 +:100190003BED00020012FFA615FFA3230A00D720A3 +:1001A000070443043E0505330C0747146F3BF00377 +:1001B000020012FFA1C03014FFA1D30FD30FD30F41 +:1001C0009340B4447249F2D30FD30FD30F14FF9B63 +:1001D000834014FF9B834012FF9B230A0014FF9A65 +:1001E000D30FD30FD30F9340B4447249F2D30FD33C +:1001F0000FD30F14FF95834012FF95C92F832084DE +:10020000218522BC22743B0F8650B4559630B433FE +:100210007433F463FFE60000653FE1655FDE12FFC3 +:100220007C230A0028374028374428374828374C91 +:10023000233D017233ED03020000020012FF7AC079 +:1002400032032E0503020012FF7813FF819320C0B2 +:1002500011014931004831010200C00014FF7E0441 +:10026000D23115FF7D945014FF7D04D33115FF7CEE +:10027000945014FF7C04D43115FF7C24560014FFE5 +:100280007B04D53115FF7B24560010FF7A03000054 +:10029000000000000000000000000000000000005E +:1002A000000000000000000000000000000000004E +:1002B000000000000000000000000000000000003E +:1002C000000000000000000000000000000000002E +:1002D000000000000000000000000000000000001E +:1002E000000000000000000000000000000000000E +:1002F00000000000000000000000000000000000FE +:1003000000000000000000000000000000000000ED +:1003100000000000000000000000000000000000DD +:1003200000000000000000000000000000000000CD +:1003300000000000000000000000000000000000BD +:1003400000000000000000000000000000000000AD +:10035000000000000000000000000000000000009D +:10036000000000000000000000000000000000008D +:10037000000000000000000000000000000000007D +:10038000000000000000000000000000000000006D +:10039000000000000000000000000000000000005D +:1003A000000000000000000000000000000000004D +:1003B000000000000000000000000000000000003D +:1003C000000000000000000000000000000000002D +:1003D000000000000000000000000000000000001D +:1003E000000000000000000000000000000000000D +:1003F00000000000000000000000000000000000FD +:1004000000000000000000000000000000000000EC +:1004100000000000000000000000000000000000DC +:1004200063FFFC000000000000000000000000006E +:100430000000000000000000000000001FFC0000A1 +:100440001FFC0000E30005C81FFC00001FFC0000AB +:10045000E30005C81FFC00001FFC0000E30005C806 +:100460001FFFC0001FFFC000E30005C81FFFC00042 +:100470001FFFC018E30005C81FFFC0181FFFC018EA +:10048000E30005E01FFFC0181FFFC28CE30005E07A +:100490001FFFC28C1FFFC28CE30008541FFFC290D5 +:1004A0001FFFC58CE3000854200000002000016AF3 +:1004B000E3000B502000018020000180E3000CBC11 +:1004C0002000020020000203E3000CBC2000021CFC +:1004D00020000220E3000CC02000022020000226A1 +:1004E000E3000CC42000023C20000240E3000CCCDE +:1004F0002000024020000249E3000CD02000024C02 +:1005000020000250E3000CDC2000025020000259C1 +:10051000E3000CE02000025C20000260E3000CEC31 +:100520002000026020000269E3000CF02000026C51 +:1005300020000270E3000CFC200002702000027911 +:10054000E3000D002000028C2000028CE3000D0C63 +:100550002000029020000293E3000D0C200002AC6A +:10056000200002B0E3000D10200002D0200002F2B3 +:10057000E3000D14200003B0200003B0E3000D38A9 +:10058000200003B0200003B0E3000D38200003B0CA +:10059000200003B0E3000D38200003B0200003B0BA +:1005A000E3000D38200003B020006BA8E3000D38F5 +:1005B00020006BA820006BA8E3007530000000004D +:1005C00000000000000000001FFC00001FFC0000F5 +:1005D0001FFFC5901FFFC67020006BA820006BA8EE +:1005E000DEFFFE000000080CDEADBEEF1FFFC2A064 +:1005F0001FFCFE001FFFC0941FFFC5C0300000009D +:10060000003FFFFF8040000010000000080FFFFFC8 +:100610001FFFC26D000FFFFF804FFFFF8000000033 +:1006200000000880B000000560500000600000007D +:1006300040000011350000004100000010000001E2 +:1006400020000000000010007FFFFFFF40000000BE +:1006500005000000800000190400000000000800F0 +:1006600010000005806000007000000020000009FC +:10067000001FF8008000001EA0000000F80000002D +:1006800007FFFFFF080000001800000001008001C4 +:10069000420000001FFFC21D1FFFC0DC00010080E0 +:1006A000604000001A0000000C0000000000300054 +:1006B000600008008000001C000100008000001A9B +:1006C00080000018FC0000008000000100004000D5 +:1006D000030000008000040050000003FFFFBFFF84 +:1006E0001FFFC3D400000FFFFFFFF000000016D073 +:1006F0000000FFF7A50000001FFFC4B01FFFC4618A +:100700000001000800000B20202FFF801FFFC455B0 +:1007100000002C00FFFEFFF800FFFFFF1FFFC57861 +:1007200000002000FFFFDFFF0000FFEF01001100CD +:100730001FFFC3D21FFFC590FFFFEFFF0000FFFBAD +:100740001FFFC6301FFFBEA0FFFFF7FF1FFFC064E3 +:100750000000FFFD1FFFC6200001FBD01FFFC5B03A +:100760001FFFC6601FFFC591E0FFFE001FFFC5A071 +:10077000000080001FFFC53C1FFFC5B41FFFC068FD +:100780001FFFC4D01FFCFFD800010081E10006005C +:10079000000027101FFCFE301FFCFE70E10002006D +:1007A0001FFFC5381FFFC5500003D0901FFFC56451 +:1007B0002B5063802B5079802B5090802B50A6803B +:1007C0001FFFC4690100110F202FFE0020300080A0 +:1007D000202FFF000000FFFF0001FFF82B50B200A8 +:1007E0002B50B208000100102B50B1802B50B2806A +:1007F0002B50BA00000100112B50BD282B50BC809B +:100800002B50BDA020300000DFFFFE005000000292 +:1008100000C0000002000000FFFFF7F41FFFC06CE3 +:10082000000FF80004400000001000000C40000021 +:100830001C400000E00000A01FFFC5401FFD000895 +:100840001FFFC5541FFFC5681FFFC57CE100069050 +:10085000E10006EC000000000000000000000000C5 +:100860000000000001000000000000000000000087 +:100870000000000020100040201000402010004028 +:1008800020140080200C0000200C0000200C000030 +:1008900020100040201400802014008020140080CC +:1008A000201800C0201C0100201C0100201C010099 +:1008B00020200140201800C0201800C0201800C0CF +:1008C000201C0100201800C0201800C0201800C003 +:1008D000201C010020200140202001402020014058 +:1008E00020200940202009402020094020200940E4 +:1008F00020240980FFFFFFFFFFFFFFFFFFFFFFFF37 +:1009000000000000000000000000000000000000E7 +:1009100000000000200052FC200051CC200052FCBE +:10092000200052FC200051082000510820005108EE +:1009300020004F4820004F4820004F4020004EAC80 +:1009400020004D5420004B342000490800000000D6 +:1009500000000000200052CC200051982000523CA2 +:100960002000523C20004FF020004FF020004FF0BC +:1009700020004FF020004FF020004F3820004FF0B3 +:1009800020004C7420004AE4200048B4000000001D +:100990000000000020000BE0200038BC200004C054 +:1009A000200044A820000BD820003FB4200003F012 +:1009B000200044682000489020003CC420003BE018 +:1009C00020003838200036C42000343420002F9412 +:1009D00020003A3C20002BF4200028282000653419 +:1009E000200023B4200020942000204020001D2C53 +:1009F000200018402000157020000DEC20000C2471 +:100A00002000113420001320200041AC20003C784D +:100A100020000BE8200004C00000000000000000DF +:100A200000000000000000000000000000000000C6 +:100A300000000000000000000000000000000000B6 +:100A400000000000000000000000000000000000A6 +:100A50000000000000000000000000000000000096 +:100A60000000000000000000000000000000000086 +:100A70000000000000000000000000000000000076 +:100A80000000000000000000000000000000000066 +:100A900000000000000000003264000000000000C0 +:100AA0003264000064006400640064006400640058 +:100AB000640064000000000000000000000000006E +:100AC0000000000000000000000000000000000026 +:100AD0000000000000000000000000000000000016 +:100AE0000000000000000000000000000000000006 +:100AF00000000000000000000000000000001000E6 +:100B000000000000000000000000000000000000E5 +:100B100000000000000010000000000000000000C5 +:100B200000000000000000000043238000000000DF +:100B300000000000000000000000000000000000B5 +:100B400000000000000000000000000000000000A5 +:100B5000005C94015D94025E94035F940043000086 +:100B60000000000000000000000000000000000085 +:100B70000000000000000000000000000000000075 +:100B80000000000000000000000000000000000065 +:100B9000005C90015D90025E90035F900053000046 +:100BA0000000000000000000000000000000000045 +:100BB0000000000000000000000000000000000035 +:100BC0000000000000000000000000000000000025 +:100BD000009C94001D90019D94029E94039F940498 +:100BE0000894050994060A94070B9400430000003A +:100BF00000000000000000000000000000000000F5 +:100C000000000000000000000000000000000000E4 +:100C1000009C90019D90029E90071D90039F900460 +:100C20007890057990067A90077B90005300000039 +:100C300000000000000000000000000000000000B4 +:100C400000000000000000000000000000000000A4 +:100C500000DC94001D9001DD9402DE9403DF940417 +:100C60000494050594060694070794080894090956 +:100C7000940A0A940B0B940043000000000000004B +:100C80000000000000000000000000000000000064 +:100C900000DC9001DD9002DE900B1D9003DF9004DC +:100CA000B49005B59006B69007B79008B89009B90A +:100CB000900ABA900BBB90005300000063FFFC0049 +:100CC0002000696410FFFF0A00000000200069880E +:100CD00000D23110FFFE0A0000000000200069D0A1 +:100CE00000D33110FFFE0A000000000020006A104F +:100CF00000D43110FFFE0A000000000020006A84CA +:100D000000D53110FFFE0A000000000063FFFC0068 +:100D1000E00000A012FFF78220028257C82163FF83 +:100D2000FC12FFF303E83004EE3005C0309320944A +:100D300021952263FFFC00001FFFD000000400206B +:100D40001FFFC5901FFFC670200A0011FFFB13FF95 +:100D5000FB03E63101020016FFFA17FFFAD30F7703 +:100D60006B069060B4667763F85415505419E60F1B +:100D7000140063FFF90000006C1004C020D10F00C4 +:100D80006C1004C0C71AEF06D830BC2BD720857270 +:100D90000D4211837105450B957202330C237601C8 +:100DA0007B3B04233D089371A32D12EEFE19EEFE4A +:100DB000A2767D632C2E0A00088202280A01038E87 +:100DC000380E0E42C8EE29A67E6D4A050020880026 +:100DD000308C8271D10FC0F0028F387FC0EA63FF80 +:100DE000E400C0F1C050037E0CA2EE0E3D1208825A +:100DF0000203F538050542CB5729A67E2FDC100FDC +:100E00004F366DFA0500208800308CBC75C0300864 +:100E1000E208280A01058338030342C93E29A67E59 +:100E20000D480CD30F6D8A0500208800B08C8271AC +:100E3000D10FC05008F53875C0C163FFBBC0600258 +:100E4000863876C0DA63FFD46C101216EED8C1F87B +:100E5000C1E72B221E2C221DC0D07BC12F292006CA +:100E6000D7B0299CFACC57282070288CFF282470F2 +:100E700064915C2AB0000EA80C6481670FA90C6411 +:100E800092B3C1E97EA13969AC2F600036292006F2 +:100E9000D7D0299CFACC57282070288CFF282470A2 +:100EA0006491352AD0000EA80C6481640FA90C64EB +:100EB000931BC1E97EA10968AC09C020D10F0000D5 +:100EC000002D25028A32C0900A6F5065F5AD2924A5 +:100ED000670908476585A92F200C18EEB50CFE118F +:100EE000A8EE28E286B44978930260057A19EEB13B +:100EF00009F90A2992A3689007882009880C65855A +:100F00006627E28564756065558E7BC104D9B06043 +:100F10000001C0908B941CEEA80B88148CC40B0BA2 +:100F200047A8CC18EEA609BB1008CC029C7018EE9E +:100F3000A41CEEA508A8010B88020C4C021BEEA114 +:100F40009C710B880298722C90232B902204C8105D +:100F500006BB100C4C1208BB0228902107CC100CC9 +:100F600088100C88020B88021CEE998B330CBB0195 +:100F70008C340B880298739C999C748B958C399B4C +:100F80007588968B38987688979C799B7898771C8B +:100F9000EE9028E2850CFC082DC4CF08480B28E60B +:100FA0008565550B2B221E2D221D7BD9022B0A0095 +:100FB00064BF062CB00728B000DA2006880A288211 +:100FC0004CC0D10B8000DBA065AFE763FEEB0000F7 +:100FD000292070659E9C6004E42A207065AEC36081 +:100FE00004DB00002EB0032C2067D4E065C1058A25 +:100FF000328C330AFF500C4554BC5564F4E619EEAC +:1010000075882A09A90109880C64821BC0926000B6 +:10101000DD2ED0032A2067D4E065A0D88A328B3336 +:101020000AFC500B4554BC5564C4B919EE6A882AB1 +:1010300009A9017989D50BEA5064A4DD0CEE11C031 +:10104000F02F16132E16168AE78CE82A16128EE950 +:10105000DFC0AAEA7EAB01B1CF0BA85065834288FE +:1010600037DBC0AE89991E789B022BCC012B161B57 +:1010700029120E2B0A0029161A7FC3077FC9027E88 +:10108000AB01C0B165B4988B352F0A002A0A007AEB +:10109000C30564C3C72F0A0165F4842B12162B16EF +:1010A00019005104C0C100CC1A2CCCFF2C16170C0F +:1010B000FC132C16182B121A2A121BDC505818FA83 +:1010C000C0D0C0902E5CF42C12172812182F121BBF +:1010D0002A121A08FF010CAA018834074C0AAB8BAC +:1010E0002812192BC6162F86082A86092E74102955 +:1010F00024672E70038975B1EA2A7403B0990949EF +:101100000C659DB52B20672D250265B3F42B221E9F +:101110002C221D7BC901C0B064BD9E2CB00728B035 +:1011200000DA2006880A28824CC0D10B8000DBA0A0 +:1011300065AFE763FD8389BAB19965909788341CE0 +:10114000EE2698BA8F331EEE1F0F4F542FB42C8DFE +:101150002A8A320EDD020CAC017DC9660A49516F44 +:1011600092608A3375A65B2CB0130AED510DCD0148 +:101170000D0D410C0C417DC9492EB012B0EE65E356 +:10118000C2C0D08E378CB88A368FB97CA3077AC993 +:10119000027EFB01C0D1CED988350AAD020E8E0881 +:1011A00078EB022DAC0189B7DAC0AF9B79BB01B1F6 +:1011B000CADCB0C0B07DA3077AD9027CEB01C0B114 +:1011C00064B15DC091292467C020D10F00008ADA84 +:1011D000B1AA64A0BC2E20672D250265E30B1FED8C +:1011E000F98A3218EDFE0FAF0108FF0C65F2860A8E +:1011F00048516F820260027DC090292467090A4726 +:1012000065A2F27BC901C0B064BCAE2CB00728B0A7 +:1012100000DA2006880A28824CC0D10B8000DBA0AF +:1012200065AFE763FC9300000CE9506492EB0CEFB0 +:1012300011C080281611AFBF2F16198EF88BF7DA60 +:10124000E08FF92B1610ABFB7FBB01B1EA0CA85065 +:101250006580D68837DCE0AF89991C789B022CEC3E +:10126000012C161B29120C2C0A0029161A7AE307E6 +:101270007AE9027FBB01C0C165C2A48B352C0A008C +:101280002A0A007AE30564E1CA2C0A0164CE1160DF +:10129000028D88341BEDD198DA8F331EEDCA0F4FC3 +:1012A000542FD42C8C2A8A320ECC020BAB010CBBEF +:1012B0000C65BF0E0A49516E920263FF058A330A1C +:1012C000AB5064BEFD2CD0130AEE510ECE010E0EB3 +:1012D000410C0C410ECC0C65CEE82FD012B0FF654E +:1012E000F26EC0B08E378CD88A362FD2097CA30715 +:1012F0007AC9027EFB01C0B165BEC78835DBA0AEEE +:101300008E78EB01B1AB89D7DAC0AF9D79DB01B143 +:10131000CAC0C07BA3077AB9027DEB01C0C165CE0C +:10132000A1C090292467C020D10F88378C3698142B +:101330000CE90C29161408F80C981D78FB072812E4 +:1013400014B088281614891D9F159B16C0F02B1207 +:101350001429161A2B161B8B147AE30B7AE90688CC +:10136000158E1678EB01C0F165F1B929121A2F120A +:10137000118A352E121B9A1AAFEE2F1210C0A0AF91 +:101380009F79FB01B1EE9F11881AC0F098107AE3A3 +:101390000A7EA9052A12017A8B01C0F164F08160EE +:1013A000018289368B3799170BE80C981F09C90CF5 +:1013B00029161578EB07281215B088281615D9C0FC +:1013C0009A199E188A1F2E12152A161A2E161BDA23 +:1013D000C0C0E08C177F930B7FA90688188F1978FF +:1013E000FB01C0E165E13D29121A2F12138A352E47 +:1013F000121B9A1BAFEE2F1212C0A0AF9F79FB01F8 +:10140000B1EE9F13881BC0F098127AE30A7EA905FB +:101410002A12037A8B01C0F165F1092E12162E16DD +:10142000192A121B005104C0E100EE1AB0EE2E166C +:10143000170EFF132F16180FCC01ACAA2F121A0E7D +:10144000BC01ACFC7FCB01B1AA2A161B2C161A6377 +:10145000FC6200007FB30263FE3163FE2B7EB302A9 +:1014600063FC3463FC2E00006450C0DA20DBF058CB +:1014700015DEC020D10FC09163FD7E00C09163FADC +:101480004CDA20DB70C0D12E0A80C09A2924682C47 +:1014900070075814CED2A0D10F034C0B18ED51DBBE +:1014A000C0A82878C3022BCDF8D9B063FA65000034 +:1014B0002A2C74DB40580E5063FAE80000002D25FA +:1014C000027BC901C0B064B0172CB00728B000DAA5 +:1014D0002006880A28824CC0D10B8000DBA065AFB3 +:1014E000E7C020D10FC09163FC04022A02580250C9 +:1014F0000AA202060000022A0258024D0AA20206AF +:101500000000DB70DA20C0D12E0A80C09E2924683A +:101510002C70075814AEC020D10FC09463FBCF00CD +:10152000C09663FBC9C09663FBC400002A2C74DB21 +:1015300030DC405BFE13DBA0C2A02AB4002F200CDD +:1015400063FF27008D358CB77DCB0263FDD263FC32 +:10155000718F358ED77FEB0263FDC563FC6400009D +:101560006C1004C020D10F006C1004C020D10F00FB +:101570006C10042B221E28221DC0A0C09429240612 +:101580002A25027B8901DBA0C9B913ED08DA2028DE +:10159000B0002CB00703880A28824CC0D10B800011 +:1015A000DBA065AFE7C020D10F0000006C1004295C +:1015B00020062A2102689805289CF965811A0A0AE2 +:1015C0004C65A0F016ECFB2B629E1AECF86FB8028B +:1015D0006000F12AA22668A0078B200ABB0C65B028 +:1015E000E32A629D64A0DD2B200C0CBC11A6CC2D3F +:1015F000C2866FD9026000D71DECEF0DBD0A2DD257 +:10160000A368D0078E200DEE0C65E0C327C285C00D +:10161000E06470BB1DECF468434D1CECF38A2B0CAA +:10162000AA029A7089200899110D99029971882A45 +:1016300098748F329F75282104088811987718ECC8 +:10164000E40CBF11A6FF2DF285A8B82E84CF2DDCA7 +:10165000282DF685C85A2A2C74DB40580DE7D2A0F5 +:10166000D10FC020D10F00002C9CF964C08D2C201C +:10167000668931B1CC0C0C472C24666FC669709E0C +:101680006618ECDA89308F2B0989400B991009FF15 +:101690000208FF029F708C2008CC110DCC029C71B7 +:1016A0008A339A7389329972882A98748F349F7515 +:1016B00063FF820000CC57DA20DB30DC405814B8DE +:1016C000C020D10F00DA20C0B658154763FFE500EF +:1016D000DA2058154563FFDC00DA20DB30DC40DD22 +:1016E000505815C7D2A0D10F2B21045813DA1DEC86 +:1016F000BD2B200CC0E02E246663FF842F2123C065 +:10170000C87FC30263FF792C20662B2104B1CC0C67 +:101710000C472C24665813CF1DECB32B200CC0E0D3 +:101720002E246663FF5A00006C1004C0B7C0A116D7 +:10173000ECB015ECA2D720D840B822C04005350245 +:101740009671957002A438040442C94B1AEC95199D +:10175000EC9629A67EC140D30F6D4A050080880013 +:10176000208C220A88A272D10FC05008A53875B00B +:10177000E363FFD76C100893149412292006655276 +:1017800088C0716898052A9CF965A29816EC892989 +:1017900021028A1409094C6590C78AA00A6A512A55 +:1017A000ACFD65A0BCCC5FDB30DA208C1258147C19 +:1017B000C0519A14C7BF9BA98E142EE20968E0603D +:1017C0002F629E1DEC7A6FF8026000812DD2266890 +:1017D000D0052F22007DF9752C629DC79064C06DE5 +:1017E0009C118A142B200C2AA0200CBD11A6DD0A06 +:1017F0004F14BFA809880129D286AF88288C09799F +:101800008B551FEC6C0FBF0A2FF2A368F00528223E +:10181000007F894329D285D49065907760003D0090 +:10182000002B200C1FEC640CBD11A6DD29D2860F05 +:10183000BF0A6E96102FF2A368F00488207F8905F6 +:1018400029D285659165DA205814E7600013DA2003 +:10185000C0B65814E5600009C09063FFB9DA20589B +:1018600014E28914899109FE506551E48C128D149B +:10187000DA20DBD08DD09E100D6D515813549A1480 +:1018800064A208C75F8FA195A9C0510F0F479F128F +:1018900063FEFB00C091C0F12820062C2066288C36 +:1018A000F9A7CC0C0C472C24666FC6088D148DD17B +:1018B00070DE01C090DD90648159C9D32A12012BDA +:1018C00021045813648A14C0B02B24668EA92AA060 +:1018D000200E28141CEC438D1415EC37C1700A77C8 +:1018E0003685562DDC28AC2C9C13DED0A8557CD335 +:1018F000022EDDF8D3E0DA40055B02DC305BFF8AC4 +:10190000D4A028200CB455C0D02B0A882F0A800CF4 +:101910008C11A6CC29C285AF3FAB9929C6851CEC9A +:101920002CDEF0AC882D84CF28120329120478F322 +:10193000022EFDF8289020D3E007880CC17008081B +:1019400047289420087736657FAB891413EC2A89E1 +:1019500090C0F47797491BEC28C1CA28210485144C +:10196000099E4006EE11875304881185520E8802A5 +:101970000C88029BA09FA18F2B9DA598A497A7954B +:10198000A603FF029FA22C200C1EEC11AECE0CCCA5 +:101990001106CC082BC2852DE4CF2BBC202BC6858D +:1019A0002A2C748B12580D14D2A0D10F28203DC0C0 +:1019B000E07C877F2E24670E0A4765A07B1AEC0F18 +:1019C00088201EEBFD8F148EE48FF40888110A889E +:1019D000020F8F14AFEE1FEC0A98910FEE029E904B +:1019E0001EEC09C0801AEBFA2CD285AABAB8CC2812 +:1019F000A4CF2CD6852C21022F20700ECC02B1FF53 +:101A00002F24702C2502C020D10F87148770070760 +:101A10004763FD6E282123C099798B0263FE9ADD0E +:101A2000F063FE9500DA20DB308C12DD505814F4A0 +:101A3000D2A0D10FC0E163FF7A8B148C12DD50C0AD +:101A4000AA2E0A802A2468DA20581360D2A0D10F67 +:101A5000007096552B629E6EB8531DEBD42DD22686 +:101A600068D0048E207DE9452A629DCBAF2B2104EE +:101A70002C20665812F8C090292466821418EBE2D4 +:101A80008F2108FF019F21C020D10F008B10C9B802 +:101A90008CA00C6C51CCCC8E241FEBD08DE19E140D +:101AA0000FDD029DE18810658FA9C020D10FDA20DB +:101AB000C0B658144DC020D10F0000006C1006298C +:101AC0002102C0D07597102A32047FA70A8B357F78 +:101AD000BF052D25020DD902090C4C65C18216EBFC +:101AE000B41EEBB228629EC0FA78F3026001882926 +:101AF000E2266890078A2009AA0C65A17A2A629DCD +:101B0000DFA064A1772B200C0CBC11A6CC29C286C7 +:101B1000C08C79830260015719EBA709B90A299291 +:101B2000A3689007882009880C65814327C2851C1B +:101B3000EBA964713A8931098B140CBB016FB11D9B +:101B40002C20669F10B1CC0C0C472C24666EC6026C +:101B500060014009FF5065F13A8A102AAC188934B7 +:101B6000C0C47F973C18EBAA1BEBA98F359C719BD7 +:101B7000708B209D7408BB029B72C08298751BEB12 +:101B8000A50F08409B730F881198777FF70B2F21C3 +:101B900002284A0008FF022F2502C0B4600004009A +:101BA0000000C0B07E97048F362F25227D970488D1 +:101BB000372825217C9736C0F1C0900AF9382F3C90 +:101BC0002009094264908619EB7618EB7728967EF7 +:101BD00000F08800A08C00F08800A08C00F0880045 +:101BE000A08C2A629D2DE4A22AAC182A669D893019 +:101BF0007797388F338A3218EB8007BE0B2C21047D +:101C0000B4BB04CC1198E0C08498E1882B9DE59A80 +:101C1000E69FE71AEB78099F4006FF110FCC020AF6 +:101C2000880298E2C1FC0FCC022CE604C9B82C2033 +:101C30000C1EEB670CCA11AECC06AA0829A2852D92 +:101C4000C4CF09B90B29A685CF5CC020D10FC081B4 +:101C5000C0900F8938C08779880263FF7263FF667E +:101C600000CC57DA20DB30DC4058134DC020D10FB8 +:101C7000DA205813DD63FFE8C0A063FE82DA20C0DB +:101C8000B65813D963FFD900DB402A2C74580C5A7C +:101C9000D2A0D10F8A102B210458126E1EEB44C023 +:101CA000D02D246663FEB1006C1006D62019EB3FE0 +:101CB0001EEB4128610217EB3E08084C65805F8AE5 +:101CC000300A6A5169A3572B729E6EB83F2A92263A +:101CD00068A0048C607AC9342A729D2C4CFECAAB71 +:101CE0002B600CB64F0CBD11A7DD28D2860EBE0AA4 +:101CF00078FB269C112EE2A32C160068E0052F62CB +:101D0000007EF91522D285CF2560000D00DA60C073 +:101D1000B65813B5C85A60010F00DA605813B2659F +:101D20005106DC40DB308D30DA600D6D51581227E2 +:101D3000D3A064A0F384A1C05104044763FF6D00E5 +:101D4000C0B02C60668931B1CC0C0C472C64666F36 +:101D5000C60270960A2B610458123EC0B02B64660E +:101D60006550B42A3C10C0E7DC20C0D1C0F002DFCF +:101D7000380F0F4264F09019EB0A18EB0B28967E8F +:101D80008D106DDA0500A08800C08CC0A089301DC0 +:101D9000EB1A77975388328C108F3302CE0BC02406 +:101DA00092E12261049DE00422118D6B9BE59FE787 +:101DB00098E61FEB100998400688110822020FDDF3 +:101DC00002C18D9DE208220292E4B4C22E600C1F73 +:101DD000EB000CE811A7882C8285AFEE0C220B2BB0 +:101DE000E4CF228685D2A0D10F28600CD2A08C111E +:101DF00019EAF80C8D11A988A7DD2ED2852B84CF86 +:101E00000ECC0B2CD685D10FC0F00ADF387FE8024C +:101E100063FF6C63FF6000002A6C74C0B2DC20DDDD +:101E20004058121CC0B063FF63C020D10F000000F7 +:101E30006C10042C221D2A221EC049D320293006F2 +:101E4000243468C0407AC105DDA060000200C0D023 +:101E50006E9738C08F2E0A802B3014C09629340616 +:101E60000EBB022E31022B34147E8004243502DE98 +:101E7000407AC10EC8ABDBD0DA302C0A00580A76A3 +:101E80002E31020E0F4CC8FEC020D10F6895F828E5 +:101E9000310208084C658FEF1AEAC61CEAC42BA26F +:101EA0009EC09A7B9B462BC22668B0048D307BD99E +:101EB0003B29A29DC0E3CB9394901BEAD72D31041C +:101EC0009B9608DD110EDD029D979D9112EAD4C00C +:101ED000E524C4A22E34062F310228A29D02FF025F +:101EE000288C3028A69D2F3502C020D10FDA30C0B3 +:101EF000B658133DC020D10F6C10062920066898F3 +:101F000005289CF965825D29210209094C6592101A +:101F1000CD51DB30DA20044C025812A1C051D3A0BD +:101F2000C7AF2A360AC0E019EAA31DEAA91FEAA230 +:101F30008A3A16EA9FB1AC64C13528629E6F880266 +:101F40006001F129DC332992266890078B2009BBB8 +:101F50000C65B1E027629DC08E6471D82B200C0CFB +:101F6000BC11A6CC29C2867983026001D219EA91FC +:101F700009B90A2992A397106890082822000988B5 +:101F80000C6581BB27C2856471B5292006299CF99F +:101F90006491EC2C20668931B1CC0C0C472C246662 +:101FA0006EC6026001A109F85065819B883689F4EC +:101FB000088C14AC991CEA810C99022C21049970AC +:101FC00019EA980808479971892A0988100899021E +:101FD00018EA95089902997228301329301204885A +:101FE0001006991008990228302C9A740C88100851 +:101FF000C802098802987389379975883898768A53 +:1020000039C0819A771AEA888935987B9978098945 +:10201000140A9902997A8A30893277A73618EA76B3 +:102020008F33987CC084987D882B2E761129761268 +:102030002F761319EA700A9F4006FF1104CA11098E +:1020400088020FAA02987EC1F90FAA022A7610C050 +:10205000AA600001C0A6ADBF0CBC11A6CC29C285E8 +:102060002EF4CF09A90B29C685655107C020D10FD1 +:102070002B200C0CBC1106CC0828C28609B90A6FAB +:10208000890260012E2992A36890082A220009AAD9 +:102090000C65A11F2AC28564A11928203D0828408B +:1020A00064808C843504841464408485F574537F83 +:1020B0008436048414644077745374293013C08CBC +:1020C00079886CC0902924670908476580ED8820CD +:1020D00089F484351FEA4B048414A4940F440294B9 +:1020E000A014EA4608881104880298A1843698A3AF +:1020F000048414A4990F990299A219EA42ADB42854 +:10210000C2852E44CF288C1028C6852821022F2076 +:1021100070098802B2FF2F2470282502C020D10F39 +:1021200000CC57DA20DB30DC4058121DC020D10F24 +:10213000C09163FF8FDA20C0B65812AB63FFE10095 +:10214000DA205812A963FFD88A102B2104581141B4 +:102150001DEA201FEA192B200CC0E02E24668A3AC3 +:1021600063FE480000DA20DB30DC40DD50581324E9 +:10217000D2A0D10F2A2C74DB40580B1FD2A0D10F54 +:10218000292123C08879830263FE202A12002C2093 +:10219000662B21042CCC010C0C472C246658112DE5 +:1021A0001DEA0C1FEA052B200CC0E02E24668A3A9B +:1021B00063FDF800DA2058128C63FF64DA205BFFBD +:1021C0001CD2A0D10F0000006C10089515C061C191 +:1021D000B0D9402A203DC0400BAA010A64382A2009 +:1021E0000629160668A8052CACF965C33B1DE9F263 +:1021F0006440052F120564F29C2621021EE9EE06BA +:10220000064C6562E315E9EA6440D98A3529300352 +:102210009A140A990C6490CC2C200C8B149C110CF1 +:10222000CC11A5CC9C122CC286B4BB7CB30260023C +:10223000D38F110EFE0A2EE2A368E0098620D30F89 +:102240000E660C6562BE88122882856482B6891487 +:1022500064905EDA80D9308C201EE9E81FE9E91D20 +:10226000E9D68B148DD4D4B07FB718B88A293C1026 +:10227000853608C6110E66029681058514A5D50F10 +:10228000550295800418146D8927889608CB11088B +:1022900088140EBB02A8D8299C200F88029BA19805 +:1022A000A088929BA3088814A8D80F880298A22A15 +:1022B000AC1019E9D4C0C08F141EE9C586128D1167 +:1022C000286285AEDD08FF0B2CD4CF2821022F66B3 +:1022D000858B352A2070098802ABAA2825022A247A +:1022E00070C020D10F29529E18E9B16F9802600288 +:1022F0000828822668800829220008990C6591F92F +:102300002A529DC1CA9A1364A1EF2B200C262006E5 +:102310000CB811A5882D82860EBE0A7DC30260020C +:10232000022EE2A368E0082F22000EFF0C65F1F3F5 +:10233000288285DE806481FF9810266CF96461FF35 +:102340002C20668831B1CC0C0C472C24666EC6025A +:102350006001BC08FD5065D1B617E9B419E9981AB7 +:10236000E99F2C21048B2D2830102F211D0C881063 +:102370000BFB090C88020A880209BB0264415289DE +:1023800010C04D9B90979198928D35D9E064D06C98 +:10239000D730DBD0D8307FD713273C10BCE92632AA +:1023A000168C3996E69CE78A37B4389AE80B1314F2 +:1023B0006430492A821686799A9696978C778A7D18 +:1023C0009C982B82172C7C209A9A2A9C189B998681 +:1023D0007BB03BB8896DB9218BC996A52692162A88 +:1023E000AC18B8999BA196A08BC786CD9BA22B92C7 +:1023F0001596A49BA386CB2CCC2026A605C0346BB7 +:10240000D4200D3B0C0DD8090E880A7FB705C0906B +:102410009988BC88C0900B1A126DAA069988998B6E +:10242000288C18C0D01BE9831CE98216E978B1FF1B +:102430002A211C23E6130F0F4F26E6122F251D7F9E +:10244000A906C0F0C08028251D05F6111AE9718F74 +:10245000202BE6152CE6162DE61726E6180AFA02BA +:102460002AE614292006299CF96490FF29200C8D66 +:1024700015C0801AE9570C9C11AA99A5CCDA202B1B +:10248000C2852894CF0B4B0B2BC685C0B08C165839 +:102490001114D2A0D10F8A356FA548D8308BD56DD5 +:1024A000A90C8A860A8A14CBA97AB337288C10C063 +:1024B00080282467080B4765B112DA20DB302C1224 +:1024C00006581137D3A0C0C1C0D02DA4039C1563FA +:1024D000FD26863664610C8910C04D9B90979198BB +:1024E0009263FEA4C08163FFC78A15CCA7DA20DB04 +:1024F000308C1658112BC020D10FDA20C0B65811DD +:10250000BA63FFE400DA208B115811B763FFD900DA +:102510009E178A132B210458104F8E17C0B02B24FE +:102520006663FE34C08063FE09DA20DB308C16DD82 +:1025300050581233D2A0D10FDA205811AB63FFA844 +:102540002D2123C0C87DC30263FE0D8A132B2104F5 +:102550002C20669817B1CC0C0C472C246658103DE3 +:102560008E17C0D02D246663FDEE0000262123B017 +:102570006606064F262523656EF128206A7F8705AB +:102580000829416490A5C0D01BE91C19E92B26201D +:102590000723E61BB16609FA022BE61A28200A2D4A +:1025A000E61D2AE61E09880228E61C88260606473C +:1025B00028E6202B220826E53E2BE6212D24072C99 +:1025C00020062A206468C347B44463FE9EDB30DAE9 +:1025D000208D15C0CE2E0A802C24688C1658107BB6 +:1025E000D2A0D10F8E102A321616E8F30A2A1486CA +:1025F000662BE61297E127E61328E614AA66096619 +:102600000296E02EEC4869ED50C14663FD7A000069 +:1026100064AFB419E8E928201689920A880C009161 +:102620000400881AA8B8982963FF9C002B21046E27 +:10263000B81E2C2066B8CC0C0C472C2466C9C09E52 +:10264000178A135810048E17C0348F20C0D02D2441 +:1026500066C06826240663FF2C008D35C08064D0D8 +:102660004AD9E0DC30DBE0DF301AE8F4B188B4FFAF +:1026700017E8F486C9249DFF8DC82CCC102D463058 +:102680000767012D46320A66011DE8EE264631AD88 +:102690006D2D463326F21597B796B684C3BCBB940E +:1026A000B58D35299C107D83C22F211DC14663FD48 +:1026B0004B0000006C1006292006289CF86582C398 +:1026C0002921022B200C09094C6590E116E8B90C70 +:1026D000BA11A6AA2DA2862C0A127DC3026002900E +:1026E00019E8B509B90A2992A36890078C2009CC8A +:1026F0000C65C27C29A2856492762D629E1AE8AB95 +:102700006FD8026002722AA22629160168A0082B3F +:1027100022000ABB0C65B26029629DC18C6492588C +:102720002A21200A806099102C203CC7EF000F3E20 +:10273000010B3EB1BD0FDB390BBB098F260DBD115F +:102740002DDC1C0D0D410EDD038E27B1DD0D0D417D +:102750000FEE0C0DBB0B2BBC1C0BB7027EC71C2C49 +:1027600021257BCB162D1AFC0CBA0C0DA16000099B +:102770003E01073EB1780987390B770A77EB026093 +:10278000020A2C2123282121B1CC0C0C4F2C25230B +:102790007C8B29B0CD2D2523C855DA20DB30580F8E +:1027A000FA292102CC96C0E80E9E022E2502CC57B3 +:1027B000DA20DB30DC4058107AC020D10F2C2066A4 +:1027C0008931B1CC0C0C472C24666EC6026001D353 +:1027D00009FD5065D1CD2F0A012E30112922146434 +:1027E000E01128221B090C4400C10400FA1A0A88CF +:1027F0000228261B2E3010C0A0C0B088301CE86E06 +:1028000094129513C04125203C2CC022088D1477CA +:1028100087052F0A010CFA38C0F2C0840858010F4E +:102820005F010F4B3805354007BB10C0F0084F382B +:1028300008FF100FBB0228ECFEC0F0084F38842BB5 +:102840000BA8100AFF102A21200F88020B8802080B +:10285000440218E87D8F110844022821250A2A1411 +:102860000828140488110A88022A210494F08B2075 +:1028700004E41008BB1104BB02C04A04BB029BF174 +:10288000842A08AB110BEB0294F40A54110B440296 +:102890000555100D1B4094F707BB100B550208554A +:1028A00002C08195F68433C05094F3B1948B329575 +:1028B000F898F99BF2C080C1BC24261498FB9BF5C4 +:1028C00099FA853895FC843A94FD8B3B9BFE8839B8 +:1028D00098FF853525F6108436851324F6118B373D +:1028E00084122BF612C0B064C08189307797468D70 +:1028F0003288332E30108F111CE840099940069918 +:10290000112CF614C0C42CF6158C2B2DF61A28F6B3 +:102910001B2BF61904A81109880208EE0219E835E4 +:10292000C18008EE0209C90229F6162EF618C09ECB +:10293000600004000000C09A2F200C18E8250CFE4F +:1029400011A8FFA6EE2DE2852BF4CF0D9D0B2DE6F1 +:1029500085C87F8A268929A7AA9A260A990C090977 +:102960004829252565504CC020D10F00C09A63FF2F +:10297000C6DA2058109D63FE34DA20C0B658109A8B +:1029800063FE2A00689738C020D10F0000DA20DBF0 +:1029900070581057C0B0C0C10ACA390ACB3865BDDB +:1029A000E063FE098A102B2104580F2AC0B02B24A3 +:1029B0006663FE21DB402A2C7458090FD2A0D10F88 +:1029C000DA20580F2F63FCF76C1004C020D10F00E1 +:1029D0006C1004290A801EE81D1FE81D1CE7F50C79 +:1029E0002B11ACBB2C2CFC2DB2850FCC029ED19CA4 +:1029F000D0C051C07013E81914E81818E8162AB2AC +:102A000085A82804240A234691A986B8AA2AB6854F +:102A1000A98827849F25649FD10F00006C100AD6D7 +:102A200030283010292006288CF964829B68980B86 +:102A30002A9CF965A1B2022A02580F1189371BE7B7 +:102A4000DEC89164520E2A21020A0C4C65C2588DD0 +:102A50003019E7D774D7052E212365E29E2F929E69 +:102A60001AE7D36FF8026002532AA22668A0082C46 +:102A700022000ACC0C65C2442A929D64A23E9A159B +:102A80001FE7CD8D67C1E664D00E2B620618E7CA3A +:102A900064B0052880217B8B422B200C18E7C50CE5 +:102AA000BC11A8CC29C28679EB450FBE0A2EE2A341 +:102AB00068E0048F207EF9372CC2859C1864C233ED +:102AC0002B212F87660B7B360B790C6F9D266ED2E0 +:102AD000462C203D7BC740CE5560001E2A200CC1ED +:102AE000B28C205810759A1864A2458D6763FFCF89 +:102AF000C0C063FFC5D7B063FFD300C0E060000271 +:102B00002E60030EDB0C6EB20EDC700CEA11AA6AAA +:102B10002AAC20580199D7A0DA20DB70C1C82D213A +:102B20002058101B8C268B279A160CBB0C7AB334BA +:102B30008F18896399F3886298F28E659EF82D60EC +:102B4000108A189D1768D729C0D09DA92C22182B50 +:102B500022139CAB9BAA97A58E667E73026000979A +:102B6000CF5860001FDA208B16580FE165A138633B +:102B7000FFBDC081C0908F18C0A29AF999FB98FA46 +:102B800097F563FFD2DB30DA20DC40580F85C05167 +:102B9000D6A0C0C02BA0102CA4039B172C12080297 +:102BA0002A02066B02DF702D60038E179D149E10A3 +:102BB0000CDD11C0E0AD6D2DDC205801188C148B9C +:102BC00016ACAC2C64038A268929ABAA0A990C9A04 +:102BD00026886609094829252507880C98662F222A +:102BE00018A7FF2F261863FE96DA20DB30DC40DDC5 +:102BF00050581083D2A0D10FC0302C20668961B10B +:102C0000CC0C0C472C24666EC6026000D2C0300982 +:102C1000FD5065D0CA8E6764E069647066DB608CC5 +:102C200018DF70DA202D60038E170CDD119E10ADB9 +:102C30006D2DDC201EE7845800F9232618DA208B3E +:102C400016DC402F2213DD50B1FF2F2613580F241E +:102C5000D2A0D10F0028203D084840658DE76F9530 +:102C60003EDA308DB56D990C8CA80C8C14CACF7CD3 +:102C7000D32D2AAC10C090292467090D4764DDC507 +:102C8000600092002C1208066B022D6C20077F0258 +:102C90008E17DA209E101EE76B58007D63FF9A00A6 +:102CA000C09163FFD1000000655081DA20DB60DC59 +:102CB00040580F3BC020C0F02FA403D10FDA20C032 +:102CC000B6580FC963FFE000006F950263FD6CDA30 +:102CD00020DB30DC40DD50C4E0580EBCD2A0D10F68 +:102CE0008A152B2104580E5B232466286010981740 +:102CF00063FF2100DA20580FBC63FFABC858DB30FC +:102D0000DA20580EA12A210265AF9CC09409A902BD +:102D100029250263FF91DB30DC40DD50C0A32E0A81 +:102D2000802A2468DA20580EA9D2A0D10FC020D161 +:102D30000FDA202B200C580FC563FF6B6C10042892 +:102D40002006C062288CF8658125C050C7DF2B2281 +:102D50001BC0E12A206B29212300A104B099292559 +:102D600023B1AA00EC1A0BC4010A0A442A246B04FA +:102D7000E4390DCC030CBB012B261B6440692920D0 +:102D80000C1BE70B0C9A110BAA082FA2861BE70954 +:102D90006FF9026000B60B9B0A2BB2A368B0082C37 +:102DA00022000BCC0C65C0A42BA2851DE72D64B0BE +:102DB0009B8C2B2421040DCC029CB08820C0C5081C +:102DC00088110C880298B1882A08441198B48F346D +:102DD00094B79FB5C0401EE6FE2DA2850E9E082525 +:102DE000E4CF2DDC282DA68529210209094C689401 +:102DF0001A689820C9402A210265A00B2A221E2B9E +:102E0000221D7AB10265A079C020D10F2C21236543 +:102E1000CFDE6000082E21212D21237EDBD52B2241 +:102E20001E2F221D2525027BF901C0B064BFC413EB +:102E3000E6DF2CB00728B000DA2003880A28824C8D +:102E4000C0D10B8000DBA065AFE763FFA62A2C741E +:102E5000C0B02C0A02580D951CE7039CA08B2008DB +:102E6000BB1106BB029BA1893499A263FF790000C4 +:102E7000262468DA20DB30DC40DD50580FE1D2A098 +:102E8000D10FDA202B200C580F58C020D10F000092 +:102E90006C1006073D14C080DC30DB40DA20C047F0 +:102EA000C02123BC30032838080842774001B1DD37 +:102EB00064815A1EE6BB19E6BC29E67ED30F6DDAA3 +:102EC0000500508800308CC0E0C02025A03C14E6EE +:102ED000BAB6D38FC0C0D00F87142440220F8940C8 +:102EE000941077F704C081048238C0F10B2810C019 +:102EF00044C02204540104FD3802520102FE380885 +:102F0000DD10821C07EE100E6E020EDD02242CFE78 +:102F1000C0E004FE380AEE100E88020D88028DAB68 +:102F20001EE6AA08D8020E880298B0C0E80428104D +:102F30000E5E0184A025A125084411084402052540 +:102F400014045511043402C0810E8E3994B18FAA35 +:102F500084109FB475660C26A11FC0F2062614606B +:102F60000009000026A120C0F20626140565020F04 +:102F7000770107873905E6100778100866020655BD +:102F80000295B625A1040AE611085811082802087E +:102F9000660296B7C060644056649053067E11C0C6 +:102FA000F489C288C30B340B96459847994618E6B6 +:102FB000919F410459110E99021FE68F020E470896 +:102FC000D80298420E99029F40C1E00E990299449E +:102FD0002FA00CB4380CF91114E67E1EE675A4FF80 +:102FE000AE992E928526F4CF0E880B289685D10FA8 +:102FF0002BA00C1FE66F1CE6760CBE11ACBBAFEE2F +:103000002DE28526B4CF0D3D0B2DE685D10FC08076 +:1030100005283878480263FEA263FE966C1006C04D +:10302000C06570F18830C030088714778712C0B04F +:10303000C0A619E661299022C030CC97C03160004B +:1030400003C0B0C0A6C0E0C091C0D4C08225203C5F +:103050000B3F109712831CC0700858010D5D0108CA +:103060009738C0800B9838077710048810086802DA +:10307000087702C0800D98382D3CFE0888100D9E00 +:10308000388D2B0AEE1008EE0207EE020CB8100F76 +:10309000DD02053B400EDD029D408920043D100805 +:1030A00099110D99022D210409A90208DD119941F8 +:1030B000872A05B9100D3D020ABB110DBB02087726 +:1030C0000297442821258712082814048811071E16 +:1030D0004007EE100E990275660926211F06261478 +:1030E000600006002621200626140868029B470976 +:1030F0008802984629200CD2C0C0800C9E111BE685 +:10310000341FE62BAB99AFEE2DE2852894CF0DADA1 +:103110000B2DE685D10FDD40C0A6C0B08E51CAE0B0 +:10312000B2AAB1BB2DDC108F500E783698100877FC +:103130000C9FD898D989538F52991199DB9FDA7EC9 +:103140008309B1CC255C10C97763FFCF88108D113E +:1031500008E70C9751AD8DD7F078DB01B1F79D539F +:1031600097528830C030088714088840648ED5652F +:10317000BEC963FEBC0000006C1004D720B03A88C2 +:1031800020C0308221CAA0742B1E2972046D080F42 +:10319000C980C9918575B133A2527A3B0B742B0853 +:1031A00063FFE900649FECD10FD240D10F00000013 +:1031B0006C1008D630C0709515DA408E3914E5FED3 +:1031C0009A1464E0026451FC2920062A9CF865A246 +:1031D0005F2A21020A0B4C65B21F2C320015E5F460 +:1031E00074C7052D212365D3242E529E1AE5F06F56 +:1031F000E80260021B2AA22668A0082B22000ABB54 +:103200000C65B20C2E529D1DE5EB64E2038B386415 +:10321000B22D9E16C8BC8D691EE5E864D0052EE06F +:10322000217BEB492E200C18E5E20CEF11A8FF29B9 +:10323000F286C186798B4A17E5DF07E70A2772A372 +:10324000687004882077893925F2856452A2272185 +:103250002E07B73607B90C6F9D01D7B089696E92FA +:103260004228203D7B873C8A15CDAF600018C1B253 +:103270008C202A200C580E90D5A064A2AC8B6863D9 +:10328000FFCBC05063FFC3C0E06000022E60030E9E +:103290009B0C6EB20EDC700CEA11AA6A2AAC285B99 +:1032A000FFB6D7A0DA20DB70C1C42D211F580E381D +:1032B0008C268B27D4A00CBB0C7AB3258A63C090D4 +:1032C0009A538862995898528F659F598E679E5B72 +:1032D0008D6697559D5A8B687B7B748B15CEB3603A +:1032E000000DDA20DB40580E0265A10D63FFCC0013 +:1032F000DA20DB308C14580DAAD6A0C0C0C0D19DF6 +:10330000152CA403DA20DB60DF70DC50C0E0256000 +:10331000039E101EE5C10C5D11AD6D2DDC285BFF19 +:103320003F8E66A5A88F67286403AF7F77FB01B146 +:10333000EE9E669F678D268C29A4DD0DCC0C9D2604 +:103340008B680C0C482C252507BB0C9B6863FEC3BF +:103350002C20668961B1CC0C0C472C24666EC60209 +:103360006000B809FD5065D0B2CBBF8E69CBEBDBF6 +:1033700060DC50DF70DA201EE5BC2D6003C0809851 +:10338000100CDD11AD6D2DDC285BFF248B15C942BF +:103390008A2629220904AA082A26060A990C09095C +:1033A0004829252565B13CC020D10F00DB602D6C7C +:1033B00028DF70DA20C0C01EE5AC9C10DC505BFE3C +:1033C000B463FFC7002D203D0D4D4065DDF96FE56D +:1033D00022DA308F456DE90C8EAA0E8E14C9E37E79 +:1033E000F3112AAC10C090292467090F4764FDD758 +:1033F00060014100C09163FFED00881565814CDAE2 +:1034000020DB608C14580D66C020C09029A403D125 +:103410000FDA20C0B6580DF463FFDE008A162B21A8 +:1034200004580C8CC0A02A24668B6863FF3A000005 +:10343000002B9CF965B0C5DA20580C9163FD910012 +:103440002B200C0CBA11A5AA2FA286C1C27FC302E1 +:103450006000FC0DB90A2992A36890078C2009CC62 +:103460000C65C0EB26A2856460E52C20668931B12D +:10347000CC0C0C472C24666FC60270960ADAE02B3F +:103480002104580C74272466893077974B18E55926 +:103490001DE55A8A328B33C0F42C2104099E400664 +:1034A000EE1104CC110ECC029F61C1E00ECC029D46 +:1034B000608F2B9A669B679C64976508FF029F62EA +:1034C0002F200C18E5430CFE11A5EE2DE285A8FF78 +:1034D00027F4CF2DDC202DE6858F1565F091C020D7 +:1034E000D10F00002A2C748B14580643D2A0D10FA0 +:1034F00000DA20DBE0580DBC63FEFE0000DA20DBC2 +:10350000308C148D15580E3ED2A0D10F00008815B6 +:10351000C888DA20DB30580C9C2A210265AEDAC05C +:103520009409A90229250263FECFDA202B200C582A +:103530000DC763FEC4272468DA20DB302C12042D6B +:1035400012052E0A80580CA163FC7C00C020D10F0C +:10355000DA20580DA58A15CDA1DA20033B022C12E2 +:1035600004580D0F27A403C020D10F00C020D10F95 +:103570002A2C748B14580620D2A0D10F6C100C2862 +:103580002102941008084C6583621FE50929F29E08 +:103590006F98026003661DE50529D2266890082A07 +:1035A000220009AA0C65A3542CF29D64C34E2B2063 +:1035B0000C0CB611AF66286286C1EC78E30260039A +:1035C0004619E4FC09B90A2992A36890078A2009E0 +:1035D000AA0C65A33224628564432CC0E12A310918 +:1035E000C07027246689359A11992A8836991298CD +:1035F0002B89379813992C883899140858149815E2 +:10360000982D89392A25042E251D29251C28302886 +:10361000C09228243C2A30290808479816098901B5 +:103620002A243D2A311599170A094109A90C299C18 +:10363000EC29251F7E87192D2A000DA06000083E69 +:10364000010A3EB1AD08DA390EAA110A990C2925F2 +:103650001F2A211F18E5060A8160C1D0941A951B04 +:1036600001083E00053EB184054839843C259CFC98 +:103670000D883629201408AA1C8D3D2726182E26D1 +:10368000132E26142E261527261B2E246B2724677F +:1036900027246808581C0909432924142932112AAF +:1036A000252E28252F27252427252527252C2725A6 +:1036B000232525202425212D2522841A2D211C8512 +:1036C0001B6FD202600209C0A099186D080AB1AA46 +:1036D00000A10400E91A7D9B0263FFEE8918C080F7 +:1036E000C0E1C070C0D29B1D951B961C9C1E16E4A9 +:1036F000D12C203D15E4E00C0B400DCC010BE7383C +:103700001DE4C30A77100CE8380B8810C0C49C4134 +:103710000877029D40B0A80988118B209C499D48DC +:10372000954B9643087702861418E4D115E4B9083E +:10373000770205BB029B4A9B429746881287110875 +:10374000DA149A4E0D88100D77110877021AE4AC3E +:1037500006D8140D6610087702974FC78F984D98BA +:103760004C9845871598440715140D55110A5502B4 +:10377000954715E4C18A262D46102D46182D462062 +:103780002C46112C46192C46212B46122B461A2862 +:1037900046142846152B46228816254624254626FB +:1037A0008B170A0C48090D4885130EDD1105CC1145 +:1037B0000839400BEB390299101EE4B00DCC020D14 +:1037C0005511082D400655022E461316E47B0FDDD9 +:1037D00011254616080840851B0188100DBB02867E +:1037E000671DE4A70988020CBB0219E4771CE4A555 +:1037F0002B46172D461BA7661BE4A4C0702C461C45 +:103800000988028C1E28461E2B4623C0908B1D293A +:10381000461D29461F18E49D29462728462529319B +:10382000162E200629246A243117962D2425238656 +:103830001CCCE1272407C0D7090E4064E0829A29F6 +:1038400009284164809164409B2D2406C098094951 +:1038500036280AA024628501C404A844282104242F +:1038600066850888118E3F8A3E2D32100EA41800FE +:10387000C4040EAE1800EE110ACA530EDD02C0E3F6 +:103880000E880298C11EE48209084E9EC08E2094C4 +:10389000C398C59DC418E44E1DE47F05EE110EAA21 +:1038A000020DAA02A8B82784CF9AC21EE44024F2CF +:1038B0009D27E4A2244C1824F69D655052C020D1C7 +:1038C0000F2D2406C0A0C09809493604A93863FF0B +:1038D0007FC0A063FE070000654F6DC098C0A82A96 +:1038E000240663FF6B2D2406C09063FF63CC57DA78 +:1038F00020DB308C10580C2AC020D10F00DA20C0F9 +:10390000B6580CB963FFE500DA20580CB763FFDC4A +:103910002A2C748B10580538D2A0D10F6C100628B1 +:1039200020068A336F8202600161C05013E42029AF +:10393000210216E41F699204252502D9502C201576 +:103940009A2814E41D8F2627200B0AFE0C04770901 +:103950002B711C64E1398E428D436FBC0260016F94 +:1039600000E104B0C800881A08A80808D8029827FF +:103970002B200668B32ECE972B221E2C221D011160 +:10398000027BC901C0B064B0172CB00728B000DAC0 +:103990002003880A28824CC0D10B8000DBA065AFD1 +:1039A000E7C020D10F2D206464DFCA8B29C0F10B42 +:1039B000AB0C66BFC02B200C0CBC11A6CC28C28659 +:1039C0002E0A0878EB611EE3FB0EBE0A2EE2A36806 +:1039D000E0052822007E894F29C2851EE4076490F5 +:1039E000461FE4159E90C084989128200A95930F55 +:1039F000880298928E200FEE029E942F2007882630 +:103A00002F950A98969A972E200625240768E34357 +:103A10002921022AC2851DE3EE2AAC20ADBD25D4A2 +:103A2000CF2AC68563FF4E002E2065CBEDC08228CD +:103A30002465C9F605E4310002002A62821BE3F71F +:103A40002941020BAA022A668209E4312921026374 +:103A5000FF23000064DFB88F422E201600F1040D12 +:103A6000EE0C00EE1AAEAE9E2963FFA38A202B3225 +:103A700021B1AA9AB0293221283223B499293621BA +:103A80007989A92B32222B362163FFA0C020D10FC8 +:103A90009F27252415ACB828751C2B2006C0C12EE5 +:103AA000BCFE64E0AB68B7772DBCFD65DEC72D209A +:103AB00064C0F064D0868E290EAE0C66E089C0F139 +:103AC00028205A288CFE08CF3865FEE863FF58008E +:103AD00000E0049310C0810AF30C038339C78F08F8 +:103AE000D80308A80108F80C080819A83303C80C63 +:103AF000A8B828751C030B472B24158310CBB700DF +:103B0000E104B0BC00CC1AACAC0CDC029C27659E76 +:103B10005EC0B20B990209094F29250263FE5000CD +:103B20002D206A0D2D4165DF7EDA20C0B0580C755E +:103B300064AF18C0F163FEEF9F2763FFD02E221FF2 +:103B400065EE3263FF79000028221F658E2763FF30 +:103B50006E252406252502C09063FE196C100665AB +:103B600071332B4C18C0C7293C18C0A1C08009A8CC +:103B7000380808426481101CE38A1AE38B2AC67E47 +:103B80002A5CFDD30F6DAA0500B08800908C894097 +:103B9000C0A00988471FE3B4080B47094C50090D22 +:103BA0005304DD10B4CC04CC100D5D029D310CBB70 +:103BB000029B3088438E2098350FEE029E328D2670 +:103BC000D850A6DD9D268E40C0900E5E5064E097D2 +:103BD0001CE39A1EE389038B0BC0F49FB19EB02DAA +:103BE000200A99B30CDD029DB28F200CFF029FB416 +:103BF0008E262D20079EB68C282DB50A9CB7292429 +:103C0000072F20062B206469F339CBB61DE36B2305 +:103C100020168DD20B330C00D10400331AB48DA3BF +:103C2000C3932922200C13E36A1FE3610C2E11AF0A +:103C3000EEA3222924CF2FE285D2A00FDD0B2DE6A3 +:103C400085D10F002E200CB48C0CEB111FE3611DED +:103C5000E358AFEEADBB22B28529E4CF02C20B22FE +:103C6000B685D2A0D10F00002E200C1CE3511FE31B +:103C7000580CEB11AFEEACBB22B28529E4CF028227 +:103C80000B22B685D2A0D10FC0D00BAD387DC802B3 +:103C900063FEEC63FEE08E40272C747BEE12DA703C +:103CA000C0B32C3C18DD50580A7B8940C08063FEAD +:103CB000E3DE60DA20DB30DC40DD505800059A108E +:103CC000DB50077A0258044C881063FEF8000000AD +:103CD0006C100692121EE3428C40AE2D0C8C472EC7 +:103CE0003C1804CA0BD9A07DA30229ADF875C30204 +:103CF000600084C0B0C023C0A09D106D0844B89F70 +:103D00000EB80A8D900EB70BB8770D6D36ADAA9D23 +:103D1000800D660CD8F000808800708C879068B1A8 +:103D200024B22277D3278891C0D0CB879890279C44 +:103D30001000708800F08C9D91CB6FC08108BB0390 +:103D400075CB3663FFB4B1222EEC1863FFD4859295 +:103D50000D770C86939790A6D67D6B01B1559693FF +:103D60009592600016B3CC2D9C188810D9D078D3CA +:103D7000C729DDF863FFC100C0238A421BE3470067 +:103D8000CD322D44029B3092318942854379A10581 +:103D90001EE3430E550187121BE334897095350BE2 +:103DA0009902993288420A880C98428676A6A6968D +:103DB000768F44AFAF9F44D10F0000006C10089382 +:103DC00011D6308830C091086351080847059838EB +:103DD0009812282102293CFD08084C6581656591EF +:103DE000628A630A2B5065B18B0A6F142E0AFF7C1E +:103DF000A60A2C205ACCC42D0A022D245A7FE00298 +:103E0000600215892888261FE32609880C65820F21 +:103E10002E200B0FEE0B2DE0FE2EE0FF08DD110E25 +:103E2000DD021EE320AEDD1EE3201CE3200EDD01DB +:103E30000DCC37C180084837B88DB4889810896098 +:103E40001AE2DE7B96218B622AA0219C147BA317A9 +:103E50009D132A200C8B108C20580B978C148D13DB +:103E6000DBA0CEAC6001C4002E200C1BE2D10CEA1A +:103E7000110BAA082BA2861FE2CF7BDB3B0FEF0AB8 +:103E80002FF2A368F0052822007F892C2BA28564DD +:103E9000B0AA87628826DE700C7936097A0C6FAD7D +:103EA0001C8F279B1508FF0C77F3197E7B729D13DF +:103EB0009C149B15CF56600025C0B063FFD0D790EF +:103EC00063FFDD00009D139C14DA20DB70580B08A3 +:103ED0008B158C148D1365A06A8E6263FFCC00DA9B +:103EE000208B11DC40580AAED6A08B15C051DE7075 +:103EF000DA20DC60DD405BFF768D138C14D9A02EB8 +:103F0000200C1BE2AB1FE2B20CEA11AFEFC0E0AB3A +:103F1000AA2BA2852EF4CF0B990B29A68563FF1D32 +:103F200000DA20DC60DD40DE708912282007DF50D7 +:103F3000A9882824075BFF09D2A0D10F00DBE0DAB3 +:103F400020580B296550EF2A20140A3A4065A0EB4F +:103F5000DB60DC40DD30022A0258099CD6A064A058 +:103F6000D584A183A0040447030547951203635138 +:103F7000C05163FE5C2C2006D30F28CCFD6480A5C5 +:103F800068C704C0932924062C2006C0B18D641F85 +:103F9000E28A9D279D289D298FF29D2600F104002D +:103FA000BB1A00F004B0BE0EDD01C0F0ADBB8D65E4 +:103FB0002F24070D0E5E01EE11AEBB2E0AFEB0BB24 +:103FC0000B0B190EBB36C0E20B0B470EBB372B2475 +:103FD0001618E2820A09450D0B422B240B29240AEC +:103FE000B4BE2E240C7D88572920162FCCFDB09D01 +:103FF0000A5C520DCC362C246465FDEC0C0C476435 +:10400000CDE618E26D8E2888820C9F0C008104009A +:10401000FF1AAFEE9E2963FDCF1CE29C63FE1300E6 +:104020001CE29363FE0C8D6563FFA500DA202B2054 +:104030000C580B06645F0FC020D10F00C020D10FB9 +:10404000C093292416C09363FFA000006C1004C025 +:104050006017E2561DE259C3812931012A3008292F +:10406000240A78A108C3B27BA172D260D10FC0C16B +:104070006550512625022AD0202F200B290AFB2B20 +:1040800020142E201526241509BB010DFF0928F147 +:104090001C2B2414A8EE2EF51C64A0B52B221E2880 +:1040A000221D0111027B8901DB6064B0172CB0076F +:1040B00028B000DA2007880A28824CC0D10B800083 +:1040C000DBA065AFE7DB30DC40DD50DA205800D8FC +:1040D000292102090B4CCAB2D2A0D10F00CC5A2C14 +:1040E00030087BC1372ED02064E02D022A02033B2A +:1040F00002DC40DD505800CED2A0D10F2B2014B0EE +:10410000BB2B24140B0F4164F0827CB7CAC0C10CD6 +:104110009C022C2502D2A0D10FC020D10F2E200648 +:1041200069E2C12F21020F0F4C69F1B8262406263F +:1041300025022B221E28221D2A200B2920150DAA1C +:10414000092CA11C262415AC9929A51C7B814A6049 +:104150000049B0BB2B24140B0D41CBD67CB7022CED +:1041600025022B221E2E221D7BE9022B0A0064B0A1 +:10417000172CB00728B000DA2007880A28824CC024 +:10418000D10B8000DBA065AFE7C020D10F2624064D +:10419000D2A0D10F26240663FFC7DB601DE20764AF +:1041A000BF422CB00728B000DA2007880A28824CCA +:1041B000C0D10B8000DBA065AFE71DE1FF63FF24EA +:1041C0006C1004282006C0646F8564CA5B29201423 +:1041D0007D9726DA20DB30DC40055D025800192986 +:1041E0002102090A4CC8A3C020D10F00C0B10B9B0B +:1041F000022B2502C020D10F0000022A02033B023D +:104200002C0A015800CAC9AADA20DB30DC40580960 +:10421000E429A011D3A07E97082C0AFD0C9C012C48 +:10422000A411C0512D201406DD022D241463FFA219 +:10423000DA20DB30DC40DD50C0E0580964D2A0D188 +:104240000F0000006C100616E1DA1CE1DA65513B44 +:10425000C0E117E1D62821028B2008084C65807B3D +:104260002932000969516993722A629E6EA8482A10 +:10427000722668A0027AB93F2A629DB44FCBA72B61 +:10428000200C0CBD1106DD0828D28678FB150CBF6A +:104290000A2FF2A368F00488207F89072DD285D3E6 +:1042A0000F65D0602A210419E202D30F7A9B1DDA30 +:1042B00020580864600024002C21041BE1FD7CBB15 +:1042C00013DA20C0B658085FC9536000EFDA2058EF +:1042D0000A46600006DA20C0B6580A436550DDDCA5 +:1042E00040DB308D30DA200D6D515808B8D3A06412 +:1042F000A0CA1CE1B0C05184A18EA00404470E0ED8 +:104300004763FF50002B2104C08C8931C070DF70DF +:1043100009F950098F386EB8172C2066AECC0C0CFA +:10432000472C24667CFB099D105808CA8D10272451 +:104330006694D11EE1B6B8DC9ED0655056C0D7B8A1 +:104340003AC0B1C0F00CBF380F0F42CBF119E19465 +:1043500018E19628967EB04BD30F6DBA0500A08861 +:1043600000C08C2C200CC0201DE19A0CCF11A6FFA0 +:104370002EF285ADCC27C4CF0E4E0B2EF685D10F75 +:10438000C0800AB83878D0CD63FFC1008E300E0EE1 +:104390004763FEBD2A2C742B0A01044D025808BD48 +:1043A0002F200C12E18B0CF911A699A2FF27F4CF54 +:1043B000289285D2A008480B289685D10FC020D11D +:1043C0000F0000006C1004C060CB55DB30DC4005F2 +:1043D0005D02022A025BFF9B29210209084CC88268 +:1043E000D2A0D10F2B2014B0BB2B24140B0C41CB2B +:1043F000C57DB7EBC0C10C9C022C2502D2A0D10F09 +:104400000000022A02033B02066C02C0D0C7F72E4E +:10441000201428310126250228240A0FEE012E241B +:104420001458010D63FFA300262406D2A0D10F006B +:104430006C1006282102D62008084C65809D2B2090 +:104440000C12E15B0CB811A2882A8286B5497A93D6 +:104450000260009719E15809B90A2992A3689008E7 +:104460002A620009AA0C65A0822882851CE1636487 +:1044700080799C80B887B14B9B819B10655074C03C +:10448000A7D970280A01C0D0078D380D0D42CBDEA8 +:104490001FE1441EE1452EF67ED830D30F6D4A054C +:1044A00000808800908C2E3008C0A000EE322E7460 +:1044B0000028600C19E1470C8D11A2DDA988C020ED +:1044C0002CD2852284CFD2A00CBC0B2CD685D10F48 +:1044D000C0F0038F387FA0C063FFB400CC582A6CB3 +:1044E00074DB30DC405807F1C020D10FDA60580986 +:1044F000BE63FFE7DD402A6C74C0B0DC705808650D +:104500002E30088B1000EE322E740028600C19E15A +:10451000300C8D11A2DDA988C0202CD2852284CF39 +:10452000D2A00CBC0B2CD685D10F00006C10042936 +:104530002014282006B199292414688124C0AF2CA6 +:104540000A012B21022C24067BA004C0D02D2502B9 +:10455000022A02033B02044C02C0D05800BFD2A082 +:10456000D10FC020D10F00006C1004293101C2B45A +:1045700029240A2A3011C28378A16C7BA169645076 +:10458000472C2006C0686FC562CA572D20147CD7FF +:1045900022DA20DB30DC40DD505BFFA52921020957 +:1045A0000E4CC8E2C020D10FC0F10F9F022F250290 +:1045B000C020D10FDA20DB30C0C05BFFDC28201424 +:1045C00006880228241463FFC72920151BE0FB2A54 +:1045D000200BC0C09C240BAA092BA11C2C2415ABBA +:1045E0009929A51C63FF9900C020D10FDA20DB3088 +:1045F000DC40DD50C0E0580875D2A0D10F000000AB +:104600006C1004CB5513E0F625221F0D46110655FC +:104610000CA32326221E25261F06440B24261E73C8 +:104620004B1DC852D240D10F280A80C04024261FFB +:10463000A82828261E28261DD240D10FC020D10F21 +:10464000244DF824261E63FFD80000006C100428B7 +:104650002006D6206E85026000DE17E0D51DE0DC66 +:1046600019E0D5C0C1C0202A8CFC64A1322B6102A4 +:10467000B44E0B0B4C65B0A82B600C2A62000CB832 +:10468000110788082F828609B90A7FE30260009F1C +:104690002992A368900509AA0C65A09328828564D5 +:1046A000808DB8891BE0DA94819B8065514DC0B73D +:1046B000B838C0A1C0E009AE380E0E4264E0481A16 +:1046C000E0B81FE0B92FA67EB04A6DAA0500808829 +:1046D00000908CC0A02E600C0CE811A7882F82855A +:1046E000ADEE0F4F0B2F86852B600622E4CF68B10D +:1046F0002A296015C0B2C99AD2A02D61022B640686 +:104700000CDD022D6502D10FC0E008AE387EB0B7D7 +:1047100063FFAB00226406D2A0D10F00D2A0D10F5C +:1047200000CC57DA60DB30DC4058089DC020D10F48 +:10473000DA6058092D63FFE80028221E29221D781F +:104740009902280A00C176C1C1C1D21BE0A5C124CB +:10475000AB6B6480437891402A80000CAF0C64F00E +:10476000AE0DAE0C64E0A802AF0C64F0A207AE0C74 +:1047700064E09C2FACE864F0962EACE764E0902FE8 +:10478000ACE664F08A2A800708A80B088A027B83BB +:10479000022A8DF8D8A065AFBBC0906000730000FE +:1047A0002B600C0CB811A7882E82866EE87909BAA6 +:1047B0000A2AA2A368A0048E607AE96B2A82856423 +:1047C000A0651FE08DC0E32E64069EA19FA01FE0A0 +:1047D000B92E600A92A30FEE029EA28E600FEE0227 +:1047E0009EA42F60147AFF4722A417ADBE2F8285A6 +:1047F00022E4CF2FFC182F868563FE702A6C74C0CC +:10480000B1DC90DD405807A31DE072C0C163FEC457 +:10481000D9A0DA60DB30DC40DD50C2F0C1E009FE37 +:10482000395807EAD2A0D10FDA605808EF63FEF0DA +:104830002CA4170DBE0829828522E4CF299C1829B3 +:10484000868564500C2A6C74044B0258016BD2A00C +:10485000D10FC020D10F00006C10062B221E282281 +:104860001D93107B8901C0B0C0C9C03BC1F20406D2 +:10487000401DE05BC0E2C0740747010E4E01AD2D44 +:104880009E11C0402E0A1464B06E6D084428221D8B +:104890007B81652AB0007EA13B7FA1477B51207CB4 +:1048A000A14968A91768AA1473A111C09F79A10C26 +:1048B000C18B78A107C1AE290A1E29B4007CA12BA7 +:1048C0002AB0070BAB0BDAB07DB3022ABDF8DBA030 +:1048D000CAA563FFB428B01089116987BB649FB86B +:1048E00063FFDC00647FB463FFD50000646FD0C059 +:1048F00041C1AE2AB40063FFC62B2102CEBE2A22DC +:104900001D2B221E7AB12A8C107CB1217AB901C0EC +:10491000B0C9B913E026DA2028B0002CB00703880C +:104920000A28824CC0D10B8000DBA065AFE7D240E3 +:10493000D10F8910659FD463FFF300006C1008C08D +:10494000D0C8598C302921020C0C4760000C8E30E5 +:104950000E1E5065E19E292102C0C116E015090B0B +:104960004C65B0908A300A6E5168E3026000852F72 +:10497000629E1BE00E6EF8532BB22668B0052E2205 +:10498000007BE94727629DB748CB7F97102B200C0F +:10499000B04E0CBF11A6FF29F2869E12798B4117EB +:1049A000E00507B70A2772A368700488207789306A +:1049B00029F285DF90D7906590652A210419E03CA3 +:1049C0007A9B22DA2058069F600029002C21041BC4 +:1049D000E0387CBB18DA20C0B658069AC958600186 +:1049E0004CC09063FFCCDA2058087F600006DA20C4 +:1049F000C0B658087D655135DC40DB308D30DA209B +:104A00000D6D515806F2C0D0D3A064A12029210217 +:104A1000C05184A18CA00404470C0C4763FF3E00E6 +:104A2000C09C8831DBD008F850089B3828210498B6 +:104A3000116E8823282066AC8C0C0C472C24667CD5 +:104A4000BB159F139E148A108B115807028E148F6A +:104A500013C0D02D24668A30C092C1C81BDFEC7F02 +:104A6000A6099BF099F12CF40827FC106550A4B816 +:104A70003ADF70C051C08007583808084264806728 +:104A800018DFC819DFC929867E6A420AD30F6DE98B +:104A90000500A08800F08CC0A08930B4E37F962880 +:104AA000C0F207E90B2C94089B909F912F200C12C9 +:104AB000DFC80CF811A688298285A2FF2DF4CFD279 +:104AC000A009330B238685D10F22200C891218DF11 +:104AD000C00C2B11A6BBA8222D24CF2CB285D2A0AE +:104AE0000C990B29B685D10FC087C0900A59387927 +:104AF000809663FF8ADB30DA20C0C1C0D05BFF56EE +:104B0000292102C0D02A9CFE65AE4D2D2502C09001 +:104B100063FE45009E142A2C74C0B1DC70DD405841 +:104B200006DD8E14C0D01BDFB9C1C863FF6AC02088 +:104B3000D10F00006C100628210216DF9D08084CDA +:104B400065821929629E6F980260022019DF9829F8 +:104B500092266890078A2009AA0C65A20F27629DF9 +:104B6000C0CC6472072B21048E31C0A0DDA00EFEE4 +:104B7000500ECD386EB8102C2066B1CC0C0C472CE2 +:104B800024667CDB026001EFC0C12930081BDF8A8C +:104B900064909C2F0AFFC0D3B09E64E10268921318 +:104BA0006450882A2C74044B025800930AA202060F +:104BB000000000002B200C2721040CBC11A6CC29DE +:104BC000C286280A087983026001B919DF7A09B917 +:104BD0000A2992A36890082E220009EE0C65E1A430 +:104BE0002EC28564E19E26200713DF836E7B026060 +:104BF000019A17DF7A1FDF8319DFB0C0D228200A9D +:104C000093E09DE1A9690F880298E22F90802A9491 +:104C100080B1FF07FF029FE32EC2851FDF6D0EDE0E +:104C20000BAFBF2AF4CF2EC685655F76C020D10FAB +:104C30002830102930112E301300993200ED3264E3 +:104C400080EE2A30141FDF9D00AA3278EF050F9EF8 +:104C5000092DE47F1EDF9B66A0050F98092A84803A +:104C6000B4A718DF98C76F009104AE9EDDE000AFD7 +:104C70001A00C31A6EE1052DB2000DED0C1EDF9275 +:104C800008D81C063303AE882A848B2EB02E2784C6 +:104C90008C03EE010FEE022EB42E58018F63FEFF3F +:104CA0002931082925042830142E3109B088648060 +:104CB000A32E240AC0812E30162CB4232E240BB42C +:104CC000EF2F240C8C378B36292504DEB0DFC00C87 +:104CD0008F390B8E390FEE0264EEC4089F1101C4A8 +:104CE000048D380CB81800C4040CBE1800EE110E68 +:104CF000DD02C0E30EFF021EDF669F719E701EDFA5 +:104D0000658F2098739D7405FF110BCD53C180985A +:104D1000750FDD020EDD029D721EDF242A24662F30 +:104D2000629D2AE4A22FFC182F669D63FE7100008D +:104D3000002F30121BDF6600FA3278FF050B980B4C +:104D40002A847F66D0050B9A0B2DA4802A3011008F +:104D5000AA3263FF442F240A9E2B63FF56CC57DAF6 +:104D600020DB30DC4058070EC020D10F00DA20C015 +:104D7000B658079D63FFE500DA70580636C0A02AD2 +:104D8000246663FE02DA2058079863FFCFB16928D2 +:104D9000200A8620090947991129240798107F8144 +:104DA0002693E027E50A9AE388109DE119DF428DFA +:104DB00011096F029FE42DE416098802C0D398E21E +:104DC0002A240763FE5100001DDF0B0868118F11B4 +:104DD000892B93E008FF02C08F9FE50D990299E2AD +:104DE000047F11C0D49DE108FF029FE463FFD0005F +:104DF0006C1004C020D10F006C100485210D3811F7 +:104E000014DEE98622A42408660C962205330B934F +:104E100021743B13C862D230D10FC030BC29992114 +:104E200099209322D230D10F233DF8932163FFE3E1 +:104E30006C100AD620941817DEDED930B8389819CD +:104E40009914655252C0E1D2E02E61021DDEDB0EE4 +:104E50000E4C65E1628F308E190F6F512FFCFD658E +:104E6000F1558EE129D0230E8F5077E66B8F181EF7 +:104E7000DF18B0FF0FF4110F1F146590CE18DF1567 +:104E80008C60A8CCC0B119DEC928600B09CC0B0D11 +:104E9000880929811C28811A2A0A0009880C08BA65 +:104EA000381BDF0B0CA90A2992947B9B0260008CB3 +:104EB0002B600C94160CBD11A7DD29D286B8487959 +:104EC00083026000D219DEBB09B80A2882A39817B2 +:104ED0006880026000A36000A51ADEFF84180AEE55 +:104EE00001CA981BDEB28C192BB0008CC06EB313B4 +:104EF0001DDEAF0C1C520DCC0B2DC295C0A17EDB6C +:104F0000AE6000380C0C5360000900000018DEF1A0 +:104F10008C60A8CCC0B119DEA528600B09CC0B0DA4 +:104F2000880929811C28811A2A0A0009880C08BAD4 +:104F3000380CA90A2992947E930263FF72DA60C04A +:104F4000BA58072964507360026600001ADE988C14 +:104F5000192AA0008CC06EA31A18DE940C1C5208EB +:104F6000CC0B18DEDB2BC295C0A178B30263FF3FE8 +:104F700063FFC9000C0C5363FF09896078991829F5 +:104F8000D285C9922B729E1DDE896EB8232DD22642 +:104F9000991369D00B60000DDA6058071360001791 +:104FA0000088607D890A9A1A29729D9C129915CFF2 +:104FB00095DA60C0B658070C6551F58D148C18DB76 +:104FC000D08DD0066A020D6D51580580D3A09A1479 +:104FD00064A1DD82A085A1B8AF9F19050547020233 +:104FE000479518C05163FE602B6104C08C8931C0A5 +:104FF000A009F950098A386EB81F2C6066A2CC0C43 +:105000000C472C64667CAB119F119E1B8A155805BA +:10501000918E1B8F11C0A02A64669F1164F0E12954 +:1050200012032812096DF9172F810300908DAEFE2F +:105030000080889F9200908C008088B89900908CA6 +:1050400065514E8A10851A8B301FDE6B88122960DD +:105050000708580A2C82942D61040ECC0C2C8694DF +:105060006FDB3C1CDE95AC9C29C0800B5D50A29987 +:1050700009094729C48065D0DA2E600CC0D01FDE34 +:10508000540CE811AFEEA7882282852DE4CF0242AE +:105090000B228685D2A0D10F8E300E0E4763FDA65F +:1050A000A29C0C0C472C64077AB6CD8B602E600A4C +:1050B000280AFF08E80C64810E18DE7E831682132E +:1050C000B33902330B2C34162D350AC02392319F8D +:1050D00030C020923308B20208E80292349832C0FD +:1050E000802864072B600CD2A01CDE390CBE11A7EF +:1050F000EE2DE285ACBB28B4CF0D9D0B2DE685D1FE +:105100000F8B1888138D30B88C0D8F470D4950B414 +:10511000990499100D0D5F04DD1009FF029F800DA9 +:10512000BB029B8165508D851AB83AC0F1C0800CD6 +:10513000F83808084264806B1BDE1A19DE1B29B69A +:105140007E8D18B0DD6DDA0500A08800C08CC0A08F +:1051500063FEF30082138B161DDE2B28600AC0E06D +:105160002EC4800D880202B20B99239F20C0D298D2 +:10517000229D2122600CB2BB0C2D11A7DD28D28507 +:1051800008BB0B18DE132BD685A8222E24CFD2A065 +:10519000D10F9E1B851A2A6C748B185BFF178E1B10 +:1051A00063FEA300C087C0900AF93879809263FF3C +:1051B00086C020D10F9E1B2A6C74C0B18D18580573 +:1051C000358E1B851A63FE7E886B8213891608BE96 +:1051D000110ECE0202920B9E25B4991EDE069F2070 +:1051E0000E88029822C0EF04D8110E88029824C0BD +:1051F000E49E21C080D2A02B600C2864071CDDF443 +:105200000CBE11A7EE2DE285ACBB28B4CF0D9D0BD3 +:105210002DE685D10F0000006C1004C020D10F00D6 +:105220006C10048633C071C030600001B1330031AE +:105230000400741A0462017460F1D10F6C1004024E +:105240002A02033B025BFFF61CDDDC1BDE24C79F4A +:1052500088B009A903098A019AB079801EC0F00FAD +:10526000E4311DDDD30002002BD2821EDE1D2AC1D7 +:10527000020EBB022BD6820AE431D10F28C102C133 +:105280009009880208084F28C50208E431D10F00B0 +:105290006C1004C0C00CE43112DDC81ADDC5000278 +:1052A0000029A28218DE111BDE0F2621020B9901B4 +:1052B00008660129A68226250206E43114DE0C15B3 +:1052C000DE07236A902326128550242611252613F3 +:1052D000222C40D10F0000006C1008D6102B0A645D +:1052E000291AB41ADDB20D23111CDDB30F2511B834 +:1052F0001898130E551118DDFEAC55A838AA332C9A +:1053000080FF2A80FEA933288D0129800108AA1177 +:105310002880000CAA0208881109880208AA1C2803 +:105320008C0828160458084C14DDA40AA70224414E +:10533000162A30802B120407AA28580847B1338B4D +:1053400013B4559A6004AC28B4662C56277B69E0E8 +:1053500016DDDB9412C050C0D017DD979D15D370B9 +:10536000D4102F60802E60829F169E178816728937 +:105370001A8D128C402A607F0DCC282B3A200CAA63 +:1053800028580835C0B10ABE372E35408F1772F93C +:105390001A8D128C402A60810DCC282B3A200CAA41 +:1053A0002858082DC0B10ABE372E3542B233B44456 +:1053B000B1556952B6B466C0508F15B877D370B284 +:1053C000FF9F156EF899D10F6C1004C021D10F000A +:1053D0006C1004270A001CDD761FDD871EDD8A1D88 +:1053E000DD731ADDB51BDDC3C02824B0006D2A753E +:1053F000AA48288080C09164806100410415DD6E58 +:10540000C03125502E00361A0655010595390C5627 +:10541000110C66082962966E974D0D590A2992243F +:1054200068900812DDA702420872993B2362951228 +:10543000DD6BCB349F300282020E4402C092993160 +:1054400094329233AD52246295C090244C1024665D +:105450009524B0002924A0AA42292480B177B14420 +:1054600004044224B400D10FD10FD10F6C10041AE0 +:10547000DD4F2AA00058021C5BFFD5022A02033B25 +:10548000025BFFD11BDD4DC9A12CB102C0D40DCCF4 +:10549000020C0C4F2CB5020CE431D10FC0A00AE471 +:1054A0003118DD430002002F828219DD562EB10231 +:1054B00009FF022F86820EE431D10F006C1004C068 +:1054C0002002E43114DD3D16DD3A00020022628242 +:1054D000234102732F0603E431C020D10F19DD8769 +:1054E0001ADD862841020A2A010988012A668228D3 +:1054F000450208E43115DD7D12DD8225461DD10F00 +:105500006C1004292006289CF96480A02A9CFD6563 +:10551000A0968A288D262F0A087AD9042B221FC824 +:10552000BD2C206464C0812E22090EAE0C66E0788A +:105530002B200C1EDD1F0CBC11AECC28C28619DD41 +:105540001D78F3026000AD09B90A2992A36890089A +:105550002E220009EE0C65E09B29C2851FDD276421 +:1055600090929F90C0E41FDD349E9128200AC0E0F5 +:105570009E930F8802989288200F880298942F207B +:10558000079A979D962F950A2E24072820062920F2 +:105590006468833328C28512DD0E288C20A2B22EC7 +:1055A00024CF28C685C020D10FC020D10F2A206A61 +:1055B0000111020A2A4165AF52DA20C0B05805D164 +:1055C00064AFE5C021D10F00649FC81FDCFB2D2014 +:1055D000168FF209DD0C00F10400DD1AADAD9D2936 +:1055E00012DCFC28C285A2B22E24CF288C2028C62B +:1055F00085C020D10FC021D10F0000006C100426FF +:105600000A001BDD4015DCEC28206517DCE9288C3E +:10561000FE6480940C4D110DBD082CD2F52BD2F4F4 +:105620002ED2F77CB13DB4BB2BD6F47BE9052BD24F +:10563000F62BD6F47CB92C2AD2F62AD6F52AD6F443 +:1056400006E4310002002872822AFAFF0041042990 +:105650000A012F510200991A0A9903098801287634 +:10566000820FE4312624652BD2F48E5A2CD2F5B069 +:10567000EE9E5A7BCB1629D2F62FD2F70CB80C0926 +:10568000FF0C08FF0C0F2F14C8F96000320BCA0C76 +:105690000A2A14CEA92B5102C0C20CBB020B0B4F1D +:1056A0002B55020BE431D10F00DB30DA205BFF9485 +:1056B0001BDD1564AF5D0C4D11ADBD63FFA800008F +:1056C00006E4310002002F728218DCD42E51020849 +:1056D000FF022F76820EE431D10F00006C1004C05F +:1056E0003003E43116DCB315DCB40002002462821E +:1056F00074472118DD05875A084801286682CD7352 +:1057000019DD030C2A11AA9922928329928472919D +:10571000038220CC292B51020BE431C020D10F0091 +:105720001FDCFC2E51020FEE012E55020EE431B0AB +:105730002DB17C9C5A12DCF708DD112D5619D10FC2 +:105740006C10061BDC9A1EDC9C22B0001ADCF36F86 +:1057500023721DDCDAC04818DCF21FDCF0DC10D547 +:10576000C083F000808600508A6D4A4F0F35110DBE +:1057700034092440800B560A296294B1330E55092E +:105780002251400F44110C440A874009A80C02889A +:105790003622514107883608770CA89929669497D4 +:1057A00040296295874109A80C0288360788360887 +:1057B000770CA8992966959741030342B1380808E8 +:1057C0004298F0D10F1CDCD713DCD827B00023326D +:1057D000B5647057C091C0D016DCD615DCD4C0407B +:1057E0002AC00003884328C4006D793C004104B1FD +:1057F0004400971A7780148E502FB2952DB695AF2E +:10580000EE2EED2006EE369E5060001877A009833C +:10581000509D5023B69560000223B295223D20068C +:10582000223622B695B455B8BBD10F000388432861 +:10583000C400D10F6C1004C04004E43115DCBE007C +:105840000200885013DCBDCB815BFFBD1CDCBC0CAF +:105850002D11ADCC2BC2822AC28394507BAB142E67 +:10586000C28429C2850ABD0C0E990C0D990C092918 +:10587000146000050BA90C092914993015DC4F2A76 +:1058800051020AE4312A2CFC58004B2B32000AA2A8 +:10589000022BBCFF9B30CCB6C8A4D2A0D10F000015 +:1058A00004E4311EDC430002002DE2822FBAFF2CFB +:1058B00051020FDD012DE6820CE431D10F00000012 +:1058C0006C1004D10F0000006C1004C020D10F0038 +:1058D0006C100413DC9BC0D103230923318DC0A0BD +:1058E0006F340260008D19DC321BDC3317DC940C42 +:1058F0002811A8772672832572822CFAFF765147E9 +:1059000088502E7285255C0425768275E9052572FE +:10591000842576827659292E72842E76822E76837D +:105920000AE4310002002392820021042FB1020018 +:10593000D61A0C66030633012396820FE4312672D1 +:105940008325728260000200D8A07659220AE431D1 +:1059500000020023928200210400D21A2FB1020C0F +:1059600022030232012296820FE431D280D10F004D +:10597000D280D10FC020D10F6C1004DB30862015EF +:10598000DC0B280A00282502DA2028B0002CB007FA +:1059900005880A28824C2D0A010B8000DBA065AF28 +:1059A000E61ADC040A4A0A29A2A3C7BF769101D1EC +:1059B0000F2BA6A3D10F00006C1004C0D1C7CF1BC2 +:1059C000DBFE19DBFB17DBF90C2811A87786758540 +:1059D00074C0A076516288508E77B455957475E97D +:1059E00003857695747659278F769F759F740AE4A0 +:1059F00031000200239282B42E2FB10200E1040094 +:105A0000D61A0C66030633012396820FE43186759D +:105A100083747639280AE4310002002E9282B4227F +:105A200000210424B10200DF1A0CFF030FEE012E47 +:105A3000968204E431D280D10FD8A07651D6D2809C +:105A4000D10F00006C1004290A801EDC001FDC004E +:105A50001CDBD80C2B11ACBB2C2CFC2DB2850FCC35 +:105A6000029ED19CD0C051C07013DBFC14DBFB182C +:105A7000DBF92AB285A82804240A234691A986B80E +:105A8000AA2AB685A98827849F25649FD10F000084 +:105A90006C100419DC2C0C2A11A9A98990C48479F2 +:105AA0008B761BDC1AABAC2AC2832CC2847AC16809 +:105AB0008AA02BBC30D3A064A05E0B2B0A2CB2A30F +:105AC00019DBE568C0071DDC20D30F7DC94AA92971 +:105AD000299D0129901F68913270A603D3A0CA9E08 +:105AE000689210C7AF2AB6A32A2CFC5BFFB3D23052 +:105AF000D10F000013DBC503A3018C311DDBB60CF5 +:105B00008C140DCC012CB6A363FFDC00C020D10F98 +:105B1000DA205BFFCCC020D10FC020D10F000000E5 +:105B20006C1004DB30C0D019DBA1DA202830002251 +:105B3000300708481209880A28824CDC200B8000B4 +:105B40001BDB9C0C4A11ABAA29A28409290B29A6AC +:105B500084D10F006C1004C04118DB9517DB970C43 +:105B60002611A727277030A866256286007104A336 +:105B70005500441A75414822628415DBB802320B85 +:105B8000C922882117DB940884140744017549054C +:105B9000C834C020D10FD10F0809471DDBEBC0B2BC +:105BA0008E201FDB820E0E43AFEC2BC4A00FEE0A3B +:105BB0002DE6242A6284C0200A990B296684D10F1D +:105BC000C020D10F6C1004DB30C0D018DB78DA2095 +:105BD00025300022300708580A28824CDC200B8030 +:105BE000008931709E121BDB720C4A11ABAA29A2EC +:105BF0008409290B29A684D10F09C95268532600AC +:105C0000910418DB6DC0A12F811200AA1A0AFF02AD +:105C10002F85121EDB670C4D11AEDD2CD2840C2CAF +:105C20000B2CD684D10FC0811FDB64B89A0A0A47B7 +:105C30002EF11200A10400881A08EE022EF5121DA2 +:105C4000DB5C0C4C11ADCC2BC2840B2B0B2BC68414 +:105C5000D10F00006C1004DB30C0D019DB54DA2007 +:105C600028300022300709880A28824CDC200B806B +:105C7000001CDB4F0C4B11ACBB2AB2840A2A0B2A46 +:105C8000B684D10F6C1004C04118DB4916DB4B0CF5 +:105C90002711A626266030A872252286006104A35B +:105CA0005500441A75410822228402320BD10F009C +:105CB000C020D10F6C100415DBA502491429561120 +:105CC0002452120208430F8811C073008104003669 +:105CD0001A008104C78F00771A087703074401066A +:105CE0004402245612D10F006C10066E230260008D +:105CF000AC6420A7C0A0851013DB7E16DB94C040E7 +:105D0000A6AA2BA2AE0B194164906668915D6892B9 +:105D10005268933C2AA2AA283C7F288C7F0A0A4D0D +:105D20002980012880002AACF208881109880275B0 +:105D300089462B3D0129B0002BB0010899110B9920 +:105D4000027A9934B8332A2A00B1447249B160000A +:105D50004A7FBF0715DB7F63FFB90000253AE86380 +:105D6000FFB10000253AE863FFA90000250A64633B +:105D7000FFA1C05A63FF9C0000705F082534FF0537 +:105D80008C142C34FE70AF0B0A8D142E3D012AE4C6 +:105D9000012DE400DA405BFD5063FFA7D10FD10F66 +:105DA0006C10041ADB0519DB021CDB6A1BDB6BC001 +:105DB00080C07160000D00000022A430B1AA299CAF +:105DC000107B915F26928679C2156E6262C0206D4B +:105DD000080AB12200210400741A764BDB63FFEE3F +:105DE0002292850D6311032514645FCFD650032DD5 +:105DF000436DD9039820B4220644146D492298209B +:105E000098219822982398249825982698279828AE +:105E10009829982A982B982C982D982E982F222CD8 +:105E20004063FF971EDAE327E68027E681D10F0063 +:105E3000C02063FF830000006C1004C062C04112E8 +:105E4000DADE1ADADA13DB452AA00023322D19DB59 +:105E50003F2BACFE2992AE6EA30260008E090E406D +:105E60002D1AC2C2CD0EDC392C251664B0895BFF19 +:105E70009E15DB3B1ADAE52B3AE80A3A015805761B +:105E80002B21160ABB28D3A02B560058058D8B500A +:105E90000ABB082A0A0058058C15DB322D21022C7A +:105EA0003AE80C3C2804DD022D25029C505805845C +:105EB0008B50AABBC0A15805841CDB2B2D21020CE2 +:105EC0003C2806DD0213DB292D25029C3058057C79 +:105ED0008B30AABBC0A258057C2A2102C0B40BAAF1 +:105EE000020A0A4F2A2502580590D10F242423C301 +:105EF000CC2C251663FF760018DB211CDB1D19DB7B +:105F00001E1BDB1C17DAF085202E0AFD1FDB1D2D62 +:105F1000202E24F47A24F47E24F4820EDD0124F46D +:105F2000862E0AF707552806DD02C0750EDD01052D +:105F30000506AB5BA959C0E8AC5C24C4AB0EDD021E +:105F400027C4AC2E0ADFA85527B4EC0EDD0124B41B +:105F5000EBC2E027942C0EDD0224942B2E0A800D38 +:105F60000D4627546C24546B0EDD022D242E63FE47 +:105F7000FC0000006C10042A0A302B0A035BFF4D62 +:105F800012DAF3C390292616C3A1C0B3C08A28260B +:105F9000175BFF48C03CC3B12B26161ADA872AA02C +:105FA0002023261764A079C3A2C0B15BFF42C3A21D +:105FB000C0B15BFF40C3C22C2616C2AFC0B12326BE +:105FC000175BFF3CC28F282616C0FE2F2617C2E2A1 +:105FD0002E26162A0AA1C0B1C0D82D26175BFF3580 +:105FE0002A0AA12A2616C3A6C0B3C1922926175B86 +:105FF000FF31C3C62C2616C1B32A0AA22B2617C00E +:10600000B35BFF2C290AA2292616C185282617C2B0 +:10601000FB2F2616C0E72E26171DDADA2D2610D103 +:106020000FC3A2C0B35BFF2363FF82006C10041C8C +:10603000DAA41BDA9118DAD417DAD516DAD515DA1C +:10604000D5C0E0C0D414DAA01FDA5CC0288FF06D90 +:106050002A36DAC0D9C07C5B020FC90C1CDA9A0C54 +:106060009C28A8C3A6C22A36802A2584A4C2A7CC0D +:106070002D248C2B248A2B24872E248BB1BB2E36E7 +:106080009F2C369E2C369DB1AC1CDA7B1BDAC3C02C +:10609000286D2A33DAC0D9C07C5B020FC90C1CDA28 +:1060A000890C9C28A8C3A6C22A36802B2584A4C2AA +:1060B000B1BBA7CC2D248C2E248B2A248A2E369F6C +:1060C0002C369E2C369DB1ACC07919DA791BDAB525 +:1060D00013DAB31ADAB318DAB414DA7A16DAB404C3 +:1060E000F42812DAB304660C040506A252A858AAD2 +:1060F0005AA3539B3029A50027848AC091C0A52AA2 +:10610000848C29848B17DAAC18DAABA75726361D96 +:1061100026361E2E361F16DAA913DAA9A655043321 +:106120000C2826C82E75002D54AC2E54AB2E54AA24 +:106130002326E62326E52E26E7D10F006C10061352 +:10614000DA8717DA8224723D2232937F2F0B6D0893 +:10615000052832937F8F0263FFF3C0C4C0B01ADA00 +:1061600016C051D94004593929A4206E44020BB5F8 +:1061700002C3281EDA11DDB025E422052D392DE4F5 +:1061800021C0501EDA9019DA8018DA8016DA821DE2 +:10619000DA8E94102A724517DA4C6DA94BD450B39D +:1061A000557A5B17DF50756B071FDA038FF00F5FAF +:1061B0000C12DA4402F228AE2222D681D54013DA3C +:1061C00041746B0715D9FD855005450C035328B163 +:1061D00045A73FA832A93322369D22369E24368019 +:1061E0002B369F2BF48B2CF48C14DA5C24424DC09C +:1061F00030041414C84C6D0806B133041414C8429A +:1062000063FFF20015D9EAC4400031041AD9EBC08B +:10621000D193A200DD1AC138B0DD9DA318DA502B4E +:10622000824D29824E29A51C2882537A871E2C5420 +:10623000008E106FE45D12D9E02F211D23211C2F49 +:10624000251B04330C23251C23251AD10FC06218EB +:10625000DA3F88807E87D989102654006F94191BF5 +:10626000D9D62AB11C0A1A1404AA0C2AB51C2AB5BC +:106270001D2AB51A2AB51BD10F1BD9CF2AB11C0A6A +:106280001A1403AA0C2AB51C2AB51D2AB51A2AB558 +:106290001BD10F001CD9C92BC11D2DC11C2BC51B27 +:1062A00003DD0C2DC51C2DC51AD10F006C1006196D +:1062B000D9C214DA2612DA2915DA44C73FC0E02E13 +:1062C00056A82E56A92E56AA2E56AB23262918D9E3 +:1062D000EADB101CDA3EC0D42A42452D16019C1080 +:1062E00000B0890A880C2896005BFF942B22E318E3 +:1062F000D9B20B5B149B842A22E48B84B1AA0A5A7C +:10630000140BAA0C9A852922E509591499862F2283 +:10631000CD0F5F149F875BFF455BFF1623463BC194 +:10632000B01DD9A51CDA032AD1022C463A0BAA02C9 +:106330000A0A4F2AD50258047C5BFEBF5BFE98C058 +:1063400050C0B016D99B14D9A317DA12C0C0C73EEB +:1063500093122C262DC0306000430000007F9F0F59 +:10636000B155091914659FF4C0500AA9027FA7EF1F +:1063700018D98FDA5008580A28822C2B0A000B8073 +:1063800000005104D2A0C091C7AF00991A0A990326 +:106390009912CE33642067D3202B200795138C12DB +:1063A0002A62827CA85F18D98108580A28822CDAD0 +:1063B000500B8000D2A0643FDA8A310A8A1404AA02 +:1063C00001C8298B210B8B1404BB017BA945DDA0DF +:1063D0007A7B081DD9792DD2000DAD0CDB3019D98F +:1063E000731AD9B82812030ADA28088C021DD9F5C5 +:1063F00009880A28823C0DAA080B8000652F97D3D4 +:1064000020C0B063FF97CB53B1550050040A09195F +:1064100063FF4900DAB07B7B071AD9678AA00ABA02 +:106420000C1BD9A88C310BAB280C8A141CD9E6ACF8 +:10643000BB1CD9E504AA012BC68163FF907FA7C7C7 +:1064400063FF62006C100427221EC08008E4311B29 +:10645000D9580002002AB28219D958003104C0610B +:1064600000661A2991020A6A022AB68209E43115E5 +:10647000D9B30C3811A8532832822432842A8CFCD8 +:106480007841102921022A368297A009690229251C +:1064900002D10F002B21022C32850B6B022CCCFC7D +:1064A0002C368297C02B2502D10F00006C1004C03F +:1064B000E71DD93B1CD93D0D4911D7208B228A20DD +:1064C0000B4B0BD2A007A80C9B72288CF4C8346F1E +:1064D0008E026000A21FD933A298AF7B78B334C973 +:1064E0003DC081C0F0028F380F0F42C9FA2CD67E12 +:1064F000D5206D4A0500308800508C8870089808B7 +:1065000078B16CD2A09870D10FC0F0038F387FE0C3 +:10651000DE63FFD8027B0CAFBB0B990C643046D80E +:1065200030C0F1C05002F5380505426450792CD6D0 +:106530007E0B36122F6C100F4F366DFA05008088D7 +:1065400000208C06440CC081250A0003B208237C7D +:106550000C0385380505426450592CD67E6D4A05DA +:1065600000208800308CD2A0A798BC889870D10FEA +:10657000D2A0BC799970D10FD2302BAD08C0F1C038 +:10658000500BF538050542CB552CD67E083F14C17B +:10659000600F660C064636D30F6D6A050020880032 +:1065A000B08C827063FF2D00C05003F53875E08019 +:1065B00063FF7A00C06002863876E0A063FF9A002D +:1065C000C05003F53875E0C363FFBD006C1004D6FE +:1065D0002068520F695324DA20DB30DC405800F089 +:1065E000D2A0D10FDA20DB30DC405800ED9A242411 +:1065F000240EC02122640FC020D10F00B83BB04C44 +:106600002A2C7489242D200E2E200FA4DDB1EE2E0D +:10661000240FB0DD2D240E2890072D9003A488B000 +:1066200088B1DD2D94032894075BFFA069511DC03C +:10663000E082242A600F18D9662A240329600E8F6D +:106640002029240708FF029F209E64D10FC020D17B +:106650000F0000006C1004942319D95EC0B3083AEF +:10666000110BAA02992019D8D29A2116D8D0C0505D +:1066700028929D2564A2288C1828969DD10F000091 +:106680006C1004282066C038232406B788282466A6 +:10669000D10F00006C1006035A0C0D36110D5C1161 +:1066A000D8208B2282210CBB0C06550F9B82023214 +:1066B0000B928113D8BCD920A38F6450531CD8B837 +:1066C000C0D71BD8B9A256C0E1290A0004E938098D +:1066D000094276F34A044302C99E2BC67E6DAA0581 +:1066E00000208800308C8981A95909FA0C64A079AE +:1066F00099818A82C8ADD290D10FC06002E6387607 +:10670000D0DA63FFD4C020BC89998199809282D16C +:106710000F7F2304292DF8998165BFD963FFE50018 +:10672000028F0CA3FF0F3312931003AA0CD340CB9C +:106730009E2BC67E86106D6A0500208800308CBCBA +:1067400082290A0004F308240A010349380909428E +:10675000CA982BC67E6DAA0500208800308C0F5980 +:106760000CA989BC99998163FF87BC89998163FFD2 +:1067700080C06002E63876D0BA63FFB4C0700247CA +:106780003877D0D063FFCA006C100414D895C1527A +:10679000A424CA3028221D73811B292102CD952AE9 +:1067A000300075A912DA20033B022C30072D0A02B3 +:1067B0005801C2653FDDD10F2B300703BB0BDAB0A8 +:1067C00074B3022ABDF8D3A063FFC6006C1004297D +:1067D0002006C0706E9741292102C08F2A2014C064 +:1067E000B62B240606AA022A241479800227250241 +:1067F0002A221E2C221D7AC10EC8ABDA20DB302CD7 +:106800000A00033D025BF8146450752D21020D0D42 +:106810004CC9D3C020D10F00002E9CFB64E0822F16 +:1068200021020F0F4C65F0911AD8621CD86029A282 +:106830009EC08A798B5D2BC22668B0048D207BD9DF +:106840005229A29DC0F364904A97901DD8732E21BF +:10685000049D9608EE110FEE029E979E9118D86F38 +:10686000C0E527C4A22E24062BA29D2F21022BBCFB +:106870003008FF022F25022BA69DC020D10F00005B +:10688000002F300068F938DA20DB30DC4058004453 +:1068900063FF7700022A022B0A065800D3220A005F +:1068A000D10F655010283000688924022A02033B6A +:1068B00002DC4058003BC020D10FD270D10F000045 +:1068C0002A2C74033B02044C025BFEF863FF3B007E +:1068D000DB30DC402A2C745BFEF5C020D10F0000B9 +:1068E0006C1004C83F89268829A399992609880C29 +:1068F000080848282525CC52C020D10FDB402A2C7F +:10690000745BF93DD2A0D10F6C1004D820D730822F +:10691000220D451105220C928264207407420B134C +:10692000D821D420A383732302242DF885807451A9 +:106930004CBC82C0906D081600408800708C77397E +:1069400003D720C0918680743901D420746102631A +:10695000FFE2CA98C097C0411BD8A0C0A00B8B0C07 +:106960000B4A380A0A42C9AA1DD80E1CD80F2CD6C9 +:106970007EC140D30F6D4A0500208800308C97807F +:10698000D270D10FBC8FC0E00F4E387E90E263FF13 +:10699000D6BC8292819280C0209282D10F000000EA +:1069A0006C1006C0D71CD7FE1BD8000D4911D7208C +:1069B0002E221F28221D0E4E0BD280078A0C2E7607 +:1069C0001F2AAC80C8346FAE026000CB2F0A801A39 +:1069D000D804A29EAA7A7EA33FC93FC0E1C050025C +:1069E000E538050542CA552BC67EDB20D30F6D4A1C +:1069F0000500308800B08C2E721DAE9E0EA50C6472 +:106A00005086D2802E761DC091298403D10FC050AC +:106A100003E53875D0D363FFCD15D7F1027E0CA501 +:106A2000EE643051C0A1250A0002A538033A0205E0 +:106A300005426450922BC67E0E35129510255C10CF +:106A4000054536D30F6D5A0500A08800208CC0A1E3 +:106A5000A3E2C05023FA8003730C03A538AF73057B +:106A600005426450722BC67E851005450C6D5A0593 +:106A700000208800308CD280C0A10E9B0CAB7BAF75 +:106A8000BB2B761D2A8403D10FD280C0C1AF7D2DD0 +:106A9000761D2C8403D10F00D2302E8D08C0F1C09A +:106AA000500EF538050542CB592BC67E0A3F14C15E +:106AB000600F660C064636D30F6D6A05002088000D +:106AC000E08C22721D63FF03C061C05003653875FE +:106AD000D80263FF6263FF5CC05002A53875D0879F +:106AE00063FF8100C06003F63876D0BF63FFB90052 +:106AF0006C10042A201529201614D7AF0A990CCB44 +:106B00009D2E200B04ED092BD11C8F2809BC36AC1F +:106B1000AA0CBB0C2BD51C0A0A472A2415CAAF8B1A +:106B2000438942B0A800910400881AA8FF0FBB0255 +:106B30009B278F260FB80C783B1AC020D10F00007E +:106B4000292102C0A20A9902292502C021D10F00E1 +:106B50008B2763FFDC2BD11C0CAA0C0A0A472A24C2 +:106B600015ACBB2BD51CC9AE8B438C288F42B0AD66 +:106B700000F10400DD1AADCC0CBB029B27DA20B774 +:106B8000EB580019C021D10F9F2763FFEF000000D1 +:106B90006C100428203C64304705306000073E013B +:106BA000053EB156076539054928C77FA933030655 +:106BB00041076603B166060641A6337E871E222181 +:106BC00025291AFC732B1502380C09816000063E3A +:106BD00001023EB12406423903220AD10FD230D13C +:106BE0000FC05163FFC000006C100427221EC0803C +:106BF00008E4311DD76F0002002CD2821BD76F0032 +:106C00003104C06100661A2BB1020C6C022CD682D2 +:106C10000BE43119D7F20C3A11AA932832829780EB +:106C2000253282243284B45525368275410A2921C1 +:106C300002096902292502D10F2A21022B32830A77 +:106C40006A022B36822A2502D10F00006C1004192B +:106C5000D76327221EC08009770208E4311DD7546C +:106C60000002002CD2821BD754003104C0610066A0 +:106C70001A2BB1020C6C022CD6820BE43119D7D737 +:106C80000C3A11AA932832829780253282243284CA +:106C9000B45525368275410B2A21020A6A022A253B +:106CA00002D10F002B21022C32830B6B022C368277 +:106CB0002B2502D10F0000006C10041BD73D0C2ABD +:106CC00011ABAA29A286B438798B221BD73A19D7DF +:106CD000610B2B0A2BB2A309290868B00274B90D05 +:106CE000299D0129901F6E920822A285D10FC020F4 +:106CF000D10FC892C020D10FDA205BEF35C020D170 +:106D00000F0000006C100414D72A28429E19D727C0 +:106D10006F88026000BA2992266890078A2009AA23 +:106D20000C65A0AC2A429DC0DC64A0A42B200C19E9 +:106D3000D7210CBC11A4CC2EC28609B90A7ED3027D +:106D400060009A2992A36890078D2009DD0C65D018 +:106D50008C25C2856450862D2104C0306ED80D2C40 +:106D60002066B8CC0C0C472C246665C07B1CD79CD5 +:106D700018D7281AD71E19D72F1DD724C0E49E5123 +:106D80009D508F209357935599539A569A5408FFC4 +:106D9000021AD73A9F5288269F5A9E599D58935E51 +:106DA0009C5D935C9A5B080848058811985FC0D881 +:106DB0001FD7080CB911A499289285AFBF23F4CF2F +:106DC000288C402896858E262D24069E29C020D109 +:106DD0000FCA33DA20C0B65BFF84C72FD10FC93A80 +:106DE000DA205BFF81C72FD10FDBD05BFE1A232493 +:106DF000662B200C63FF7500C72FD10FC72FD10F53 +:106E00006C1004C85B29200668941C689607C02093 +:106E1000D10FC020D10FDA20DB30DC40DD502E0A4C +:106E2000005BFE6AD2A0D10F2E200C18D6E10CEF29 +:106E300011A8FF29F286C088798B751AD6DE0AEA76 +:106E40000A2AA2A368A0048B207AB96423F285647D +:106E5000305E1CD6E82A0A802D2068292067282168 +:106E6000040B991104881109880208DD02C09428D6 +:106E70004A1008DD0218D6E0993198308B2B9A37EA +:106E80009D340CBB029B32C0C09C359C362A2C74AE +:106E9000DB40C0D318D6CF29F285A8EE299C202C40 +:106EA000E4CF29F6852D2406DD405BFDFAD2A0D182 +:106EB0000FDA20DBE05BFF4CC020D10F6C100AD64C +:106EC000302A2006941128ACF86583872B2122C034 +:106ED000F22A21246550082AAC010A0A4F2A2524E7 +:106EE0007ABB0260037F2C21020C0C4C65C3192E67 +:106EF00022158D32C0910EDD0C65D39088381ED6D8 +:106F0000AC64836B8C37C0B8C0960CB9399914B493 +:106F10009A9A120D991199138F6718D6A7C9FB2851 +:106F200080217F83168B142C22002A200C5BFF62A9 +:106F3000D4A064A3A88F6760002800002B200C89D0 +:106F4000120CBA11AEAA2CA2861DD69A7C9B3E0DBD +:106F5000BD0A2DD2A368D00488207D893024A28563 +:106F600064436427212E07F73607F90C6F9D01D77C +:106F7000F0DA20DB70C1C42D211F5BFF0589268854 +:106F800027DDA009880C7A8B179A10600006C04094 +:106F900063FFCC0000DA208B105BFED58D1065A25C +:106FA00067C0E09E488C649C498B658A669B4A9AC0 +:106FB0004B97458F677F7302600120CD529D10DA99 +:106FC00020DB302C12015BFE768D10C051D6A08FD5 +:106FD000A7C0C08A68974D9A4C8869896A984E996B +:106FE0004F8E6A8A69AE7E77EB01B1AA9E6A9A6972 +:106FF0008B60C0A00B8E1477B701C0A1C091C08474 +:1070000093159D179516C0D025203CC03008580117 +:10701000089338C082083310085B010535400B9D8A +:107020003807DD100BAB100E19402A211F079910ED +:1070300003DD020DBB020553100933020A55112965 +:1070400021250A2A140929140499110A99020933DD +:10705000028A2B2921040BAA021BD6E208991109E6 +:1070600055020855020BAA029A40892088140899F3 +:107070001109880219D6631DD6DC09880298418B54 +:107080002A9346954783150DBB0285168D179B44A1 +:107090008A658966AACAA97C77CB01B1AA07FB0CCD +:1070A0009C669A6588268E29AD87972607EE0C0E7A +:1070B0000E482E25259B672B200C87131ED63D0CD2 +:1070C000B911AE99289285A78828968517D641C010 +:1070D00090A7BB29B4CF871863FE3C008C60C0E04A +:1070E000C091C0F0C034C0B82A210428203C08AAAE +:1070F000110B8B01038301039F380B9B39C03208AE +:10710000FF10038801089E380C881407EE100FEE5C +:107110000203880108983905BF1029211F0ABB11F5 +:1071200007881008FF020BAA0218D6350929140394 +:10713000AA022B212583200B2B1404BB1108331129 +:107140000FBB020B99028B148F2A0B3302083302F8 +:107150008B2B6470868868974D984C8769886A93F2 +:10716000419946974E984FC07077C701C0719A47B2 +:1071700018D69E0B7C100CEC0208F802984418D626 +:107180009B0CBC0208CC029C402A200C295CFEC04F +:10719000801FD6071CD60F0CAE112B2124ACAAAF32 +:1071A000EEB0BB8F132CE28528A4CFAFCC2CE685A4 +:1071B0002A22152B2524B1AA2A26156490DBC9D2D0 +:1071C0008F262E22090DFF082F26060FEE0C0E0E1D +:1071D000482E25256550E4C020D10F00C070934192 +:1071E0009F4499469A4777C70A1CD5F32CC022C002 +:1071F000810C87381CD67F0B781008E80208B8028B +:107200000C8802984063FF8000CC57DA20DB608C4A +:10721000115BFDE3292102689806689403C020D120 +:107220000F2B221EC0A029221D2A25027B9901C0F6 +:10723000B064BFE813D5DE2CB00728B000DA200315 +:10724000880A28824CC0D10B8000DBA065AFE763C1 +:10725000FFCA000068A779DA20DB30DC40DD505B34 +:10726000FEE8D2A0D10FC16DC19D29252C6000047C +:1072700029252CD6902624672F2468DA20DB308C31 +:1072800011DD502E0A805BFD51D2A0D10FC168C123 +:10729000A82A252C63FFDD000000C8DF8C268B297F +:1072A000ADCC9C260CBB0C0B0B482B25252A2C7433 +:1072B000DB602C12015BFD94D2A0D10F2A2C748BC1 +:1072C000115BF6CDD2A0D10FDA205BFE4763FF3809 +:1072D00000DA20C0B15BFE8B65AF2D63FBEDDA20D9 +:1072E0002B200C5BFE5A63FF1F00000012D6428267 +:1072F00020028257C82163FFFC12D63E03E8300407 +:10730000EE3005B13093209421952263FFFC0000FC +:1073100010D63A910092019302940311D611821073 +:1073200001EA30A21101F031C04004E4160002006D +:1073300011D6338210234A00032202921011D5FD88 +:10734000C021921004E43184038302820181000091 +:10735000D23001230000000010D62A910092019340 +:1073600002940311D600821001EA30A21101F1311A +:10737000C04004E41600020011D621821013D5A7E4 +:10738000032202921004E43184038302820181000B +:1073900000D330013300000010D61B91008101653D +:1073A000104981026510448103CF1F92019302941A +:1073B0000311D5EE821001EA30A21101F231C04072 +:1073C00004E41600020011D60D821013D58E03229C +:1073D00002921004E431840383028201C0109103FD +:1073E00091029101810000D43001430012D5BDC04B +:1073F0003028374028374428374828374C233D0168 +:107400007233ED03020063FFFC00000010D5FF9112 +:107410000092019302940311D5FD8210921011D5B0 +:10742000AF8310032202921011D5FA12D5C1921027 +:10743000C04004E41600020011D5F1821013D5A853 +:10744000032202921004E43184038302820181004A +:1074500000D53001530000006C10026E322FD62090 +:10746000056F04043F04745B2A05440C00410400CA +:10747000331A220A006D490D73630403660CB122AE +:107480000F2211031314736302222C01D10FC83B86 +:10749000D10F000073630CC021D10F000000000069 +:1074A00044495630C020D10F6C10020040046B4C90 +:1074B00007032318020219D10F020319C020D10FAC +:1074C0006C100202EA30D10F6C1002CC2503F031AF +:1074D00060000F006F220503F1316000056F230586 +:1074E00003F231000200D10F6C1002CC2502F03003 +:1074F000D10F00006F220402F130D10F6F2304027C +:10750000F230D10FC020D10F6C1002220A20230AC2 +:10751000006D280E28374028374428374828374C34 +:10752000233D01030200D10F6C100202E431D10FA0 +:107530000A0000004368656C73696F204657204459 +:10754000454255473D3020284275696C7420576587 +:1075500064204F63742020382031353A35303A3575 +:1075600030205044542032303038206F6E20636C0D +:10757000656F70617472613A2F686F6D652F666513 +:107580006C69782F772F66775F372E30292C20563D +:10759000657273696F6E2054337878203030372EDF +:1075A00030312E3030202D203130303730313030F6 +:0875B000100701006F4EF8BB4B +:00000001FF -- GitLab From 3bcb1255bae39cae1b4d2660f2b5a6ab2f404c10 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Thu, 12 Mar 2009 21:14:29 +0000 Subject: [PATCH 3335/4982] cxgb3: update driver version update driver version to 1.1.1-ko Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/cxgb3/version.h b/drivers/net/cxgb3/version.h index 6f6c30c50dd..7bf963ec554 100644 --- a/drivers/net/cxgb3/version.h +++ b/drivers/net/cxgb3/version.h @@ -35,7 +35,7 @@ #define DRV_DESC "Chelsio T3 Network Driver" #define DRV_NAME "cxgb3" /* Driver version */ -#define DRV_VERSION "1.1.1-ko" +#define DRV_VERSION "1.1.2-ko" /* Firmware version */ #define FW_VERSION_MAJOR 7 -- GitLab From 5e8f3f703ae4e4af65e2695e486b3cd198328863 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 12 Mar 2009 09:49:17 +0000 Subject: [PATCH 3336/4982] sctp: simplify sctp listening code sctp_inet_listen() call is split between UDP and TCP style. Looking at the code, the two functions are almost the same and can be merged into a single helper. This also fixes a bug that was fixed in the UDP function, but missed in the TCP function. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/socket.c | 152 +++++++++++++++------------------------------- 1 file changed, 50 insertions(+), 102 deletions(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index bbd3cd238d7..5fb3a8c9792 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -5843,37 +5843,28 @@ static int sctp_get_port(struct sock *sk, unsigned short snum) } /* - * 3.1.3 listen() - UDP Style Syntax - * - * By default, new associations are not accepted for UDP style sockets. - * An application uses listen() to mark a socket as being able to - * accept new associations. + * Move a socket to LISTENING state. */ -SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) +SCTP_STATIC int sctp_listen_start(struct sock *sk, int backlog) { struct sctp_sock *sp = sctp_sk(sk); struct sctp_endpoint *ep = sp->ep; + struct crypto_hash *tfm = NULL; - /* Only UDP style sockets that are not peeled off are allowed to - * listen(). - */ - if (!sctp_style(sk, UDP)) - return -EINVAL; - - /* If backlog is zero, disable listening. */ - if (!backlog) { - if (sctp_sstate(sk, CLOSED)) - return 0; - - sctp_unhash_endpoint(ep); - sk->sk_state = SCTP_SS_CLOSED; - return 0; + /* Allocate HMAC for generating cookie. */ + if (!sctp_sk(sk)->hmac && sctp_hmac_alg) { + tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(tfm)) { + if (net_ratelimit()) { + printk(KERN_INFO + "SCTP: failed to load transform for %s: %ld\n", + sctp_hmac_alg, PTR_ERR(tfm)); + } + return -ENOSYS; + } + sctp_sk(sk)->hmac = tfm; } - /* Return if we are already listening. */ - if (sctp_sstate(sk, LISTENING)) - return 0; - /* * If a bind() or sctp_bindx() is not called prior to a listen() * call that allows new associations to be accepted, the system @@ -5884,7 +5875,6 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) * extensions draft, but follows the practice as seen in TCP * sockets. * - * Additionally, turn off fastreuse flag since we are not listening */ sk->sk_state = SCTP_SS_LISTENING; if (!ep->base.bind_addr.port) { @@ -5895,113 +5885,71 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) sk->sk_state = SCTP_SS_CLOSED; return -EADDRINUSE; } - sctp_sk(sk)->bind_hash->fastreuse = 0; } - sctp_hash_endpoint(ep); - return 0; -} - -/* - * 4.1.3 listen() - TCP Style Syntax - * - * Applications uses listen() to ready the SCTP endpoint for accepting - * inbound associations. - */ -SCTP_STATIC int sctp_stream_listen(struct sock *sk, int backlog) -{ - struct sctp_sock *sp = sctp_sk(sk); - struct sctp_endpoint *ep = sp->ep; - - /* If backlog is zero, disable listening. */ - if (!backlog) { - if (sctp_sstate(sk, CLOSED)) - return 0; - - sctp_unhash_endpoint(ep); - sk->sk_state = SCTP_SS_CLOSED; - return 0; - } - - if (sctp_sstate(sk, LISTENING)) - return 0; - - /* - * If a bind() or sctp_bindx() is not called prior to a listen() - * call that allows new associations to be accepted, the system - * picks an ephemeral port and will choose an address set equivalent - * to binding with a wildcard address. - * - * This is not currently spelled out in the SCTP sockets - * extensions draft, but follows the practice as seen in TCP - * sockets. - */ - sk->sk_state = SCTP_SS_LISTENING; - if (!ep->base.bind_addr.port) { - if (sctp_autobind(sk)) - return -EAGAIN; - } else - sctp_sk(sk)->bind_hash->fastreuse = 0; - sk->sk_max_ack_backlog = backlog; sctp_hash_endpoint(ep); return 0; } /* + * 4.1.3 / 5.1.3 listen() + * + * By default, new associations are not accepted for UDP style sockets. + * An application uses listen() to mark a socket as being able to + * accept new associations. + * + * On TCP style sockets, applications use listen() to ready the SCTP + * endpoint for accepting inbound associations. + * + * On both types of endpoints a backlog of '0' disables listening. + * * Move a socket to LISTENING state. */ int sctp_inet_listen(struct socket *sock, int backlog) { struct sock *sk = sock->sk; - struct crypto_hash *tfm = NULL; + struct sctp_endpoint *ep = sctp_sk(sk)->ep; int err = -EINVAL; if (unlikely(backlog < 0)) - goto out; + return err; sctp_lock_sock(sk); + /* Peeled-off sockets are not allowed to listen(). */ + if (sctp_style(sk, UDP_HIGH_BANDWIDTH)) + goto out; + if (sock->state != SS_UNCONNECTED) goto out; - /* Allocate HMAC for generating cookie. */ - if (!sctp_sk(sk)->hmac && sctp_hmac_alg) { - tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm)) { - if (net_ratelimit()) { - printk(KERN_INFO - "SCTP: failed to load transform for %s: %ld\n", - sctp_hmac_alg, PTR_ERR(tfm)); - } - err = -ENOSYS; + /* If backlog is zero, disable listening. */ + if (!backlog) { + if (sctp_sstate(sk, CLOSED)) goto out; - } - } - switch (sock->type) { - case SOCK_SEQPACKET: - err = sctp_seqpacket_listen(sk, backlog); - break; - case SOCK_STREAM: - err = sctp_stream_listen(sk, backlog); - break; - default: - break; + err = 0; + sctp_unhash_endpoint(ep); + sk->sk_state = SCTP_SS_CLOSED; + if (sk->sk_reuse) + sctp_sk(sk)->bind_hash->fastreuse = 1; + goto out; } - if (err) - goto cleanup; + /* If we are already listening, just update the backlog */ + if (sctp_sstate(sk, LISTENING)) + sk->sk_max_ack_backlog = backlog; + else { + err = sctp_listen_start(sk, backlog); + if (err) + goto out; + } - /* Store away the transform reference. */ - if (!sctp_sk(sk)->hmac) - sctp_sk(sk)->hmac = tfm; + err = 0; out: sctp_release_sock(sk); return err; -cleanup: - crypto_free_hash(tfm); - goto out; } /* -- GitLab From 5ffad5acebec735b7a368851bf22394b734cae8a Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 12 Mar 2009 09:49:18 +0000 Subject: [PATCH 3337/4982] sctp: fix to indicate ASCONF support in INIT-ACK only if peer has such capable This patch fix to indicate ASCONF support in INIT-ACK only if peer has such capable. This patch also fix to calc the chunk size if peer has no FWD-TSN capable. Signed-off-by: Wei Yongjun Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/sm_make_chunk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index b40e95f9851..9484f33730f 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -372,10 +372,10 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, if (asoc->peer.ecn_capable) chunksize += sizeof(ecap_param); - if (sctp_prsctp_enable) + if (asoc->peer.prsctp_capable) chunksize += sizeof(prsctp_param); - if (sctp_addip_enable) { + if (asoc->peer.asconf_capable) { extensions[num_ext] = SCTP_CID_ASCONF; extensions[num_ext+1] = SCTP_CID_ASCONF_ACK; num_ext += 2; -- GitLab From 76595024ffab3599bd28ea014f6c23c1a8c8dd2c Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 12 Mar 2009 09:49:19 +0000 Subject: [PATCH 3338/4982] sctp: fix to send FORWARD-TSN chunk only if peer has such capable RFC3758 Section 3.3.1. Sending Forward-TSN-Supported param in INIT Note that if the endpoint chooses NOT to include the parameter, then at no time during the life of the association can it send or process a FORWARD TSN. If peer does not support PR-SCTP capable, don't send FORWARD-TSN chunk to peer. Signed-off-by: Wei Yongjun Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/outqueue.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index a367d15a21a..d765fc53e74 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -1758,6 +1758,9 @@ static void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 ctsn) struct sctp_chunk *chunk; struct list_head *lchunk, *temp; + if (!asoc->peer.prsctp_capable) + return; + /* PR-SCTP C1) Let SackCumAck be the Cumulative TSN ACK carried in the * received SACK. * -- GitLab From 6fc791ee631728b2beddda87560f1af59e32230e Mon Sep 17 00:00:00 2001 From: malc Date: Thu, 12 Mar 2009 09:49:20 +0000 Subject: [PATCH 3339/4982] sctp: add Adaptation Layer Indication parameter only when it's set RFC5061 states: Each adaptation layer that is defined that wishes to use this parameter MUST specify an adaptation code point in an appropriate RFC defining its use and meaning. If the user has not set one - assume they don't want to sent the param with a zero Adaptation Code Point. Rationale - Currently the IANA defines zero as reserved - and 1 as the only valid value - so we consider zero to be unset - to save adding a boolean to the socket structure. Including this parameter unconditionally causes endpoints that do not understand it to report errors unnecessarily. Signed-off-by: Malcolm Lashley Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/sm_make_chunk.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 9484f33730f..6851ee94e97 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -224,7 +224,9 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, num_ext += 2; } - chunksize += sizeof(aiparam); + if (sp->adaptation_ind) + chunksize += sizeof(aiparam); + chunksize += vparam_len; /* Account for AUTH related parameters */ @@ -304,10 +306,12 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, if (sctp_prsctp_enable) sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param); - aiparam.param_hdr.type = SCTP_PARAM_ADAPTATION_LAYER_IND; - aiparam.param_hdr.length = htons(sizeof(aiparam)); - aiparam.adaptation_ind = htonl(sp->adaptation_ind); - sctp_addto_chunk(retval, sizeof(aiparam), &aiparam); + if (sp->adaptation_ind) { + aiparam.param_hdr.type = SCTP_PARAM_ADAPTATION_LAYER_IND; + aiparam.param_hdr.length = htons(sizeof(aiparam)); + aiparam.adaptation_ind = htonl(sp->adaptation_ind); + sctp_addto_chunk(retval, sizeof(aiparam), &aiparam); + } /* Add SCTP-AUTH chunks to the parameter list */ if (sctp_auth_enable) { @@ -332,6 +336,7 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, sctp_inithdr_t initack; struct sctp_chunk *retval; union sctp_params addrs; + struct sctp_sock *sp; int addrs_len; sctp_cookie_param_t *cookie; int cookie_len; @@ -366,6 +371,7 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, /* Calculate the total size of allocation, include the reserved * space for reporting unknown parameters if it is specified. */ + sp = sctp_sk(asoc->base.sk); chunksize = sizeof(initack) + addrs_len + cookie_len + unkparam_len; /* Tell peer that we'll do ECN only if peer advertised such cap. */ @@ -381,7 +387,8 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, num_ext += 2; } - chunksize += sizeof(aiparam); + if (sp->adaptation_ind) + chunksize += sizeof(aiparam); if (asoc->peer.auth_capable) { auth_random = (sctp_paramhdr_t *)asoc->c.auth_random; @@ -432,10 +439,12 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, if (asoc->peer.prsctp_capable) sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param); - aiparam.param_hdr.type = SCTP_PARAM_ADAPTATION_LAYER_IND; - aiparam.param_hdr.length = htons(sizeof(aiparam)); - aiparam.adaptation_ind = htonl(sctp_sk(asoc->base.sk)->adaptation_ind); - sctp_addto_chunk(retval, sizeof(aiparam), &aiparam); + if (sp->adaptation_ind) { + aiparam.param_hdr.type = SCTP_PARAM_ADAPTATION_LAYER_IND; + aiparam.param_hdr.length = htons(sizeof(aiparam)); + aiparam.adaptation_ind = htonl(sp->adaptation_ind); + sctp_addto_chunk(retval, sizeof(aiparam), &aiparam); + } if (asoc->peer.auth_capable) { sctp_addto_chunk(retval, ntohs(auth_random->length), -- GitLab From c048aaf4ca854fa67a3bfa9dab5b9ddc5083b3b7 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 13 Mar 2009 11:47:48 -0700 Subject: [PATCH 3340/4982] 8139cp: allow to set mac address on running device So far there was not a chance to set a mac address on running 8139cp device. This is for example needed when you want to use this NIC as a bonding slave in bonding device in mode balance-alb. This simple patch allows it. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/8139cp.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 35517b06ec3..a09e3a7cac4 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -1602,6 +1602,28 @@ static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) return rc; } +static int cp_set_mac_address(struct net_device *dev, void *p) +{ + struct cp_private *cp = netdev_priv(dev); + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + + spin_lock_irq(&cp->lock); + + cpw8_f(Cfg9346, Cfg9346_Unlock); + cpw32_f(MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); + cpw32_f(MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4))); + cpw8_f(Cfg9346, Cfg9346_Lock); + + spin_unlock_irq(&cp->lock); + + return 0; +} + /* Serial EEPROM section. */ /* EEPROM_Ctrl bits. */ @@ -1821,7 +1843,7 @@ static const struct net_device_ops cp_netdev_ops = { .ndo_open = cp_open, .ndo_stop = cp_close, .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, + .ndo_set_mac_address = cp_set_mac_address, .ndo_set_multicast_list = cp_set_rx_mode, .ndo_get_stats = cp_get_stats, .ndo_do_ioctl = cp_ioctl, -- GitLab From bda6a15a0d283d531b865fb7c596bb3ff258e87e Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 13 Mar 2009 11:48:18 -0700 Subject: [PATCH 3341/4982] 8139too: allow to set mac address on running device Similar patch as for 8139cp posted yesterday, so the same comment: So far there was not a chance to set a mac address on running 8139too device. This is for example needed when you want to use this NIC as a bonding slave in bonding device in mode balance-alb. This simple patch allows it. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/8139too.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index 5341da604e8..29df398b772 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -640,6 +640,7 @@ static int rtl8139_start_xmit (struct sk_buff *skb, #ifdef CONFIG_NET_POLL_CONTROLLER static void rtl8139_poll_controller(struct net_device *dev); #endif +static int rtl8139_set_mac_address(struct net_device *dev, void *p); static int rtl8139_poll(struct napi_struct *napi, int budget); static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance); static int rtl8139_close (struct net_device *dev); @@ -917,7 +918,7 @@ static const struct net_device_ops rtl8139_netdev_ops = { .ndo_stop = rtl8139_close, .ndo_get_stats = rtl8139_get_stats, .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, + .ndo_set_mac_address = rtl8139_set_mac_address, .ndo_start_xmit = rtl8139_start_xmit, .ndo_set_multicast_list = rtl8139_set_rx_mode, .ndo_do_ioctl = netdev_ioctl, @@ -2215,6 +2216,29 @@ static void rtl8139_poll_controller(struct net_device *dev) } #endif +static int rtl8139_set_mac_address(struct net_device *dev, void *p) +{ + struct rtl8139_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + + spin_lock_irq(&tp->lock); + + RTL_W8_F(Cfg9346, Cfg9346_Unlock); + RTL_W32_F(MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); + RTL_W32_F(MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); + RTL_W8_F(Cfg9346, Cfg9346_Lock); + + spin_unlock_irq(&tp->lock); + + return 0; +} + static int rtl8139_close (struct net_device *dev) { struct rtl8139_private *tp = netdev_priv(dev); -- GitLab From 9d51af7bd2f1d730cb6eeeb9ff837e3441ad4e07 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Tue, 10 Mar 2009 16:28:51 -0400 Subject: [PATCH 3342/4982] sata_mv: fix MSI irq race condition Fix a (rare) race condition in mv_interrupt() when using MSI. The value of hpriv->main_irq_mask_addr can change on on the fly, and without this patch we could end up writing back a stale copy to the hardware. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 7007edd2d45..74b1080d116 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -2218,12 +2218,13 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance) else handled = mv_host_intr(host, pending_irqs); } - spin_unlock(&host->lock); /* for MSI: unmask; interrupt cause bits will retrigger now */ if (using_msi) writel(hpriv->main_irq_mask, hpriv->main_irq_mask_addr); + spin_unlock(&host->lock); + return IRQ_RETVAL(handled); } -- GitLab From e3e4385f6181f434c0d786998ad1d0eef4e21c9b Mon Sep 17 00:00:00 2001 From: Stuart MENEFY Date: Tue, 10 Mar 2009 11:38:13 +0000 Subject: [PATCH 3343/4982] libata: Keep shadow last_ctl up to date during resets libata keeps a shadow copy of the ATA CTL register (which is write only), and only writes to the hardware when the required value doesn't match the shadow. However this copy wasn't being maintained when performing reset functions. This could cause problems for the first operation after a reset when the correct value might not be written to the CTL register. This problem was observed when hotplugging a drive: the identify command was being issued with interrupts enabled, when they should have been disabled. Signed-off-by: Stuart Menefy Signed-off-by: Jeff Garzik --- drivers/ata/libata-sff.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 714cb046b59..f93dc029dfd 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -2066,6 +2066,7 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask, iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr); udelay(20); /* FIXME: flush */ iowrite8(ap->ctl, ioaddr->ctl_addr); + ap->last_ctl = ap->ctl; /* wait the port to become ready */ return ata_sff_wait_after_reset(&ap->link, devmask, deadline); @@ -2190,8 +2191,10 @@ void ata_sff_postreset(struct ata_link *link, unsigned int *classes) } /* set up device control */ - if (ap->ioaddr.ctl_addr) + if (ap->ioaddr.ctl_addr) { iowrite8(ap->ctl, ap->ioaddr.ctl_addr); + ap->last_ctl = ap->ctl; + } } EXPORT_SYMBOL_GPL(ata_sff_postreset); @@ -2534,6 +2537,7 @@ void ata_bus_reset(struct ata_port *ap) if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) { /* set up device control for ATA_FLAG_SATA_RESET */ iowrite8(ap->ctl, ioaddr->ctl_addr); + ap->last_ctl = ap->ctl; } DPRINTK("EXIT\n"); -- GitLab From e9c1670c2a14ef9cc20d86b24b829f3947aad34e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 3 Mar 2009 13:52:16 +0900 Subject: [PATCH 3344/4982] ata_piix: add workaround for Samsung DB-P70 Samsung DB-P70 somehow botched the first ICH9 SATA port. The board doesn't expose the first port but somehow SStatus reports link online while failing SRST protocol leading to repeated probe failures and thus long boot delay. Because the BIOS doesn't carry any identifying DMI information, the port can't be blacklisted safely. Fortunately, the controller does have subsystem vendor and ID set. It's unclear whether the subsystem IDs are used only for the board but it can be safely worked around by disabling SIDPR access and just using SRST works around the problem. Even when the workaround is triggered on an unaffected board the only side effect will be missing SCR access. Signed-off-by: Tejun Heo Reported-by: Joseph Jang Reported-by: Jonghyon Sohn Signed-off-by: Jeff Garzik --- drivers/ata/ata_piix.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 54961c0b2c7..ef8b30d577b 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -1289,6 +1289,39 @@ static const int *__devinit piix_init_sata_map(struct pci_dev *pdev, return map; } +static bool piix_no_sidpr(struct ata_host *host) +{ + struct pci_dev *pdev = to_pci_dev(host->dev); + + /* + * Samsung DB-P70 only has three ATA ports exposed and + * curiously the unconnected first port reports link online + * while not responding to SRST protocol causing excessive + * detection delay. + * + * Unfortunately, the system doesn't carry enough DMI + * information to identify the machine but does have subsystem + * vendor and device set. As it's unclear whether the + * subsystem vendor/device is used only for this specific + * board, the port can't be disabled solely with the + * information; however, turning off SIDPR access works around + * the problem. Turn it off. + * + * This problem is reported in bnc#441240. + * + * https://bugzilla.novell.com/show_bug.cgi?id=441420 + */ + if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == 0x2920 && + pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG && + pdev->subsystem_device == 0xb049) { + dev_printk(KERN_WARNING, host->dev, + "Samsung DB-P70 detected, disabling SIDPR\n"); + return true; + } + + return false; +} + static int __devinit piix_init_sidpr(struct ata_host *host) { struct pci_dev *pdev = to_pci_dev(host->dev); @@ -1302,6 +1335,10 @@ static int __devinit piix_init_sidpr(struct ata_host *host) if (hpriv->map[i] == IDE) return 0; + /* is it blacklisted? */ + if (piix_no_sidpr(host)) + return 0; + if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR)) return 0; -- GitLab From db46db157746e57fb1ca59223bf0f72d9f875d89 Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Tue, 10 Mar 2009 12:58:27 +0000 Subject: [PATCH 3345/4982] gianfar: remove gianfar_mii.c commit 1577ecef766650a57fceb171acee2b13cbfaf1d3 Author: Andy Fleming Date: Wed Feb 4 16:42:12 2009 -0800 netdev: Merge UCC and gianfar MDIO bus drivers left out the deletion of gianfar_mii.c. Signed-off-by: Andy Fleming Signed-off-by: David S. Miller --- drivers/net/gianfar_mii.c | 379 -------------------------------------- 1 file changed, 379 deletions(-) delete mode 100644 drivers/net/gianfar_mii.c diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c deleted file mode 100644 index 64e4679b327..00000000000 --- a/drivers/net/gianfar_mii.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * drivers/net/gianfar_mii.c - * - * Gianfar Ethernet Driver -- MIIM bus implementation - * Provides Bus interface for MIIM regs - * - * Author: Andy Fleming - * Maintainer: Kumar Gala - * - * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "gianfar.h" -#include "gianfar_mii.h" - -/* - * Write value to the PHY at mii_id at register regnum, - * on the bus attached to the local interface, which may be different from the - * generic mdio bus (tied to a single interface), waiting until the write is - * done before returning. This is helpful in programming interfaces like - * the TBI which control interfaces like onchip SERDES and are always tied to - * the local mdio pins, which may not be the same as system mdio bus, used for - * controlling the external PHYs, for example. - */ -int gfar_local_mdio_write(struct gfar_mii __iomem *regs, int mii_id, - int regnum, u16 value) -{ - /* Set the PHY address and the register address we want to write */ - gfar_write(®s->miimadd, (mii_id << 8) | regnum); - - /* Write out the value we want */ - gfar_write(®s->miimcon, value); - - /* Wait for the transaction to finish */ - while (gfar_read(®s->miimind) & MIIMIND_BUSY) - cpu_relax(); - - return 0; -} - -/* - * Read the bus for PHY at addr mii_id, register regnum, and - * return the value. Clears miimcom first. All PHY operation - * done on the bus attached to the local interface, - * which may be different from the generic mdio bus - * This is helpful in programming interfaces like - * the TBI which, inturn, control interfaces like onchip SERDES - * and are always tied to the local mdio pins, which may not be the - * same as system mdio bus, used for controlling the external PHYs, for eg. - */ -int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum) -{ - u16 value; - - /* Set the PHY address and the register address we want to read */ - gfar_write(®s->miimadd, (mii_id << 8) | regnum); - - /* Clear miimcom, and then initiate a read */ - gfar_write(®s->miimcom, 0); - gfar_write(®s->miimcom, MII_READ_COMMAND); - - /* Wait for the transaction to finish */ - while (gfar_read(®s->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY)) - cpu_relax(); - - /* Grab the value of the register from miimstat */ - value = gfar_read(®s->miimstat); - - return value; -} - -/* Write value to the PHY at mii_id at register regnum, - * on the bus, waiting until the write is done before returning. - * All PHY configuration is done through the TSEC1 MIIM regs */ -int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) -{ - struct gfar_mii __iomem *regs = (void __force __iomem *)bus->priv; - - /* Write to the local MII regs */ - return(gfar_local_mdio_write(regs, mii_id, regnum, value)); -} - -/* Read the bus for PHY at addr mii_id, register regnum, and - * return the value. Clears miimcom first. All PHY - * configuration has to be done through the TSEC1 MIIM regs */ -int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum) -{ - struct gfar_mii __iomem *regs = (void __force __iomem *)bus->priv; - - /* Read the local MII regs */ - return(gfar_local_mdio_read(regs, mii_id, regnum)); -} - -/* Reset the MIIM registers, and wait for the bus to free */ -static int gfar_mdio_reset(struct mii_bus *bus) -{ - struct gfar_mii __iomem *regs = (void __force __iomem *)bus->priv; - unsigned int timeout = PHY_INIT_TIMEOUT; - - mutex_lock(&bus->mdio_lock); - - /* Reset the management interface */ - gfar_write(®s->miimcfg, MIIMCFG_RESET); - - /* Setup the MII Mgmt clock speed */ - gfar_write(®s->miimcfg, MIIMCFG_INIT_VALUE); - - /* Wait until the bus is free */ - while ((gfar_read(®s->miimind) & MIIMIND_BUSY) && - --timeout) - cpu_relax(); - - mutex_unlock(&bus->mdio_lock); - - if(timeout == 0) { - printk(KERN_ERR "%s: The MII Bus is stuck!\n", - bus->name); - return -EBUSY; - } - - return 0; -} - -/* Allocate an array which provides irq #s for each PHY on the given bus */ -static int *create_irq_map(struct device_node *np) -{ - int *irqs; - int i; - struct device_node *child = NULL; - - irqs = kcalloc(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL); - - if (!irqs) - return NULL; - - for (i = 0; i < PHY_MAX_ADDR; i++) - irqs[i] = PHY_POLL; - - while ((child = of_get_next_child(np, child)) != NULL) { - int irq = irq_of_parse_and_map(child, 0); - const u32 *id; - - if (irq == NO_IRQ) - continue; - - id = of_get_property(child, "reg", NULL); - - if (!id) - continue; - - if (*id < PHY_MAX_ADDR && *id >= 0) - irqs[*id] = irq; - else - printk(KERN_WARNING "%s: " - "%d is not a valid PHY address\n", - np->full_name, *id); - } - - return irqs; -} - - -void gfar_mdio_bus_name(char *name, struct device_node *np) -{ - const u32 *reg; - - reg = of_get_property(np, "reg", NULL); - - snprintf(name, MII_BUS_ID_SIZE, "%s@%x", np->name, reg ? *reg : 0); -} - -/* Scan the bus in reverse, looking for an empty spot */ -static int gfar_mdio_find_free(struct mii_bus *new_bus) -{ - int i; - - for (i = PHY_MAX_ADDR; i > 0; i--) { - u32 phy_id; - - if (get_phy_id(new_bus, i, &phy_id)) - return -1; - - if (phy_id == 0xffffffff) - break; - } - - return i; -} - -static int gfar_mdio_probe(struct of_device *ofdev, - const struct of_device_id *match) -{ - struct gfar_mii __iomem *regs; - struct gfar __iomem *enet_regs; - struct mii_bus *new_bus; - int err = 0; - u64 addr, size; - struct device_node *np = ofdev->node; - struct device_node *tbi; - int tbiaddr = -1; - - new_bus = mdiobus_alloc(); - if (NULL == new_bus) - return -ENOMEM; - - device_init_wakeup(&ofdev->dev, 1); - - new_bus->name = "Gianfar MII Bus", - new_bus->read = &gfar_mdio_read, - new_bus->write = &gfar_mdio_write, - new_bus->reset = &gfar_mdio_reset, - gfar_mdio_bus_name(new_bus->id, np); - - /* Set the PHY base address */ - addr = of_translate_address(np, of_get_address(np, 0, &size, NULL)); - regs = ioremap(addr, size); - - if (NULL == regs) { - err = -ENOMEM; - goto err_free_bus; - } - - new_bus->priv = (void __force *)regs; - - new_bus->irq = create_irq_map(np); - - if (new_bus->irq == NULL) { - err = -ENOMEM; - goto err_unmap_regs; - } - - new_bus->parent = &ofdev->dev; - dev_set_drvdata(&ofdev->dev, new_bus); - - /* - * This is mildly evil, but so is our hardware for doing this. - * Also, we have to cast back to struct gfar_mii because of - * definition weirdness done in gianfar.h. - */ - enet_regs = (struct gfar __force __iomem *) - ((char __force *)regs - offsetof(struct gfar, gfar_mii_regs)); - - for_each_child_of_node(np, tbi) { - if (!strncmp(tbi->type, "tbi-phy", 8)) - break; - } - - if (tbi) { - const u32 *prop = of_get_property(tbi, "reg", NULL); - - if (prop) - tbiaddr = *prop; - } - - if (tbiaddr == -1) { - gfar_write(&enet_regs->tbipa, 0); - - tbiaddr = gfar_mdio_find_free(new_bus); - } - - /* - * We define TBIPA at 0 to be illegal, opting to fail for boards that - * have PHYs at 1-31, rather than change tbipa and rescan. - */ - if (tbiaddr == 0) { - err = -EBUSY; - - goto err_free_irqs; - } - - gfar_write(&enet_regs->tbipa, tbiaddr); - - /* - * The TBIPHY-only buses will find PHYs at every address, - * so we mask them all but the TBI - */ - if (!of_device_is_compatible(np, "fsl,gianfar-mdio")) - new_bus->phy_mask = ~(1 << tbiaddr); - - err = mdiobus_register(new_bus); - - if (err != 0) { - printk (KERN_ERR "%s: Cannot register as MDIO bus\n", - new_bus->name); - goto err_free_irqs; - } - - return 0; - -err_free_irqs: - kfree(new_bus->irq); -err_unmap_regs: - iounmap(regs); -err_free_bus: - mdiobus_free(new_bus); - - return err; -} - - -static int gfar_mdio_remove(struct of_device *ofdev) -{ - struct mii_bus *bus = dev_get_drvdata(&ofdev->dev); - - mdiobus_unregister(bus); - - dev_set_drvdata(&ofdev->dev, NULL); - - iounmap((void __force __iomem *)bus->priv); - bus->priv = NULL; - kfree(bus->irq); - mdiobus_free(bus); - - return 0; -} - -static struct of_device_id gfar_mdio_match[] = -{ - { - .compatible = "fsl,gianfar-mdio", - }, - { - .compatible = "fsl,gianfar-tbi", - }, - { - .type = "mdio", - .compatible = "gianfar", - }, - {}, -}; - -static struct of_platform_driver gianfar_mdio_driver = { - .name = "fsl-gianfar_mdio", - .match_table = gfar_mdio_match, - - .probe = gfar_mdio_probe, - .remove = gfar_mdio_remove, -}; - -int __init gfar_mdio_init(void) -{ - return of_register_platform_driver(&gianfar_mdio_driver); -} - -void gfar_mdio_exit(void) -{ - of_unregister_platform_driver(&gianfar_mdio_driver); -} -- GitLab From 26ccfc37da21e6f02d5e805c38ca7551c16b2fe0 Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Tue, 10 Mar 2009 12:58:28 +0000 Subject: [PATCH 3346/4982] gianfar: Convert to use netdev_ops Signed-off-by: Andy Fleming Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index bd42502b85c..bed30ef4379 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -140,11 +140,26 @@ static void gfar_halt_nodisable(struct net_device *dev); void gfar_start(struct net_device *dev); static void gfar_clear_exact_match(struct net_device *dev); static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr); +static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); MODULE_AUTHOR("Freescale Semiconductor, Inc"); MODULE_DESCRIPTION("Gianfar Ethernet Driver"); MODULE_LICENSE("GPL"); +static const struct net_device_ops gfar_netdev_ops = { + .ndo_open = gfar_enet_open, + .ndo_start_xmit = gfar_start_xmit, + .ndo_stop = gfar_close, + .ndo_change_mtu = gfar_change_mtu, + .ndo_set_multicast_list = gfar_set_multi, + .ndo_tx_timeout = gfar_timeout, + .ndo_do_ioctl = gfar_ioctl, + .ndo_vlan_rx_register = gfar_vlan_rx_register, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = gfar_netpoll, +#endif +}; + /* Returns 1 if incoming frames use an FCB */ static inline int gfar_uses_fcb(struct gfar_private *priv) { @@ -390,21 +405,12 @@ static int gfar_probe(struct of_device *ofdev, SET_NETDEV_DEV(dev, &ofdev->dev); /* Fill in the dev structure */ - dev->open = gfar_enet_open; - dev->hard_start_xmit = gfar_start_xmit; - dev->tx_timeout = gfar_timeout; dev->watchdog_timeo = TX_TIMEOUT; netif_napi_add(dev, &priv->napi, gfar_poll, GFAR_DEV_WEIGHT); -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = gfar_netpoll; -#endif - dev->stop = gfar_close; - dev->change_mtu = gfar_change_mtu; dev->mtu = 1500; - dev->set_multicast_list = gfar_set_multi; + dev->netdev_ops = &gfar_netdev_ops; dev->ethtool_ops = &gfar_ethtool_ops; - dev->do_ioctl = gfar_ioctl; if (priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) { priv->rx_csum_enable = 1; @@ -414,11 +420,8 @@ static int gfar_probe(struct of_device *ofdev, priv->vlgrp = NULL; - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) { - dev->vlan_rx_register = gfar_vlan_rx_register; - + if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - } if (priv->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) { priv->extended_hash = 1; -- GitLab From 4893d39e865b2897bf9fcd329697d37032d853a1 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Wed, 11 Mar 2009 09:48:26 +0000 Subject: [PATCH 3347/4982] Network Drop Monitor: Add trace declaration for skb frees Signed-off-by: Neil Horman include/trace/skb.h | 8 ++++++++ net/core/Makefile | 2 ++ net/core/net-traces.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) Signed-off-by: David S. Miller --- include/trace/skb.h | 8 ++++++++ net/core/Makefile | 2 ++ net/core/net-traces.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 include/trace/skb.h create mode 100644 net/core/net-traces.c diff --git a/include/trace/skb.h b/include/trace/skb.h new file mode 100644 index 00000000000..3aa864697c0 --- /dev/null +++ b/include/trace/skb.h @@ -0,0 +1,8 @@ +#ifndef _TRACE_SKB_H_ +#define _TRACE_SKB_H_ + +DECLARE_TRACE(kfree_skb, + TPPROTO(struct sk_buff *skb, void *location), + TPARGS(skb, location)); + +#endif diff --git a/net/core/Makefile b/net/core/Makefile index 26a37cb3192..d47092bc525 100644 --- a/net/core/Makefile +++ b/net/core/Makefile @@ -17,3 +17,5 @@ obj-$(CONFIG_NET_PKTGEN) += pktgen.o obj-$(CONFIG_NETPOLL) += netpoll.o obj-$(CONFIG_NET_DMA) += user_dma.o obj-$(CONFIG_FIB_RULES) += fib_rules.o +obj-$(CONFIG_TRACEPOINTS) += net-traces.o + diff --git a/net/core/net-traces.c b/net/core/net-traces.c new file mode 100644 index 00000000000..c8fb45665e4 --- /dev/null +++ b/net/core/net-traces.c @@ -0,0 +1,29 @@ +/* + * consolidates trace point definitions + * + * Copyright (C) 2009 Neil Horman + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +DEFINE_TRACE(kfree_skb); +EXPORT_TRACEPOINT_SYMBOL_GPL(kfree_skb); -- GitLab From ead2ceb0ec9f85cff19c43b5cdb2f8a054484431 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Wed, 11 Mar 2009 09:49:55 +0000 Subject: [PATCH 3348/4982] Network Drop Monitor: Adding kfree_skb_clean for non-drops and modifying end-of-line points for skbs Signed-off-by: Neil Horman include/linux/skbuff.h | 4 +++- net/core/datagram.c | 2 +- net/core/skbuff.c | 22 ++++++++++++++++++++++ net/ipv4/arp.c | 2 +- net/ipv4/udp.c | 2 +- net/packet/af_packet.c | 2 +- 6 files changed, 29 insertions(+), 5 deletions(-) Signed-off-by: David S. Miller --- include/linux/skbuff.h | 4 +++- net/core/datagram.c | 2 +- net/core/skbuff.c | 22 ++++++++++++++++++++++ net/ipv4/arp.c | 2 +- net/ipv4/udp.c | 2 +- net/packet/af_packet.c | 2 +- 6 files changed, 29 insertions(+), 5 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 1f659e8c2b8..1fbab2ae613 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -421,6 +421,7 @@ extern void skb_dma_unmap(struct device *dev, struct sk_buff *skb, #endif extern void kfree_skb(struct sk_buff *skb); +extern void consume_skb(struct sk_buff *skb); extern void __kfree_skb(struct sk_buff *skb); extern struct sk_buff *__alloc_skb(unsigned int size, gfp_t priority, int fclone, int node); @@ -459,7 +460,8 @@ extern int skb_to_sgvec(struct sk_buff *skb, extern int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer); extern int skb_pad(struct sk_buff *skb, int pad); -#define dev_kfree_skb(a) kfree_skb(a) +#define dev_kfree_skb(a) consume_skb(a) +#define dev_consume_skb(a) kfree_skb_clean(a) extern void skb_over_panic(struct sk_buff *skb, int len, void *here); extern void skb_under_panic(struct sk_buff *skb, int len, diff --git a/net/core/datagram.c b/net/core/datagram.c index 5e2ac0c4b07..d0de644b378 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -208,7 +208,7 @@ struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, void skb_free_datagram(struct sock *sk, struct sk_buff *skb) { - kfree_skb(skb); + consume_skb(skb); sk_mem_reclaim_partial(sk); } diff --git a/net/core/skbuff.c b/net/core/skbuff.c index e5e2111a397..6acbf9e79eb 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -65,6 +65,7 @@ #include #include +#include #include "kmap_skb.h" @@ -442,10 +443,31 @@ void kfree_skb(struct sk_buff *skb) smp_rmb(); else if (likely(!atomic_dec_and_test(&skb->users))) return; + trace_kfree_skb(skb, __builtin_return_address(0)); __kfree_skb(skb); } EXPORT_SYMBOL(kfree_skb); +/** + * consume_skb - free an skbuff + * @skb: buffer to free + * + * Drop a ref to the buffer and free it if the usage count has hit zero + * Functions identically to kfree_skb, but kfree_skb assumes that the frame + * is being dropped after a failure and notes that + */ +void consume_skb(struct sk_buff *skb) +{ + if (unlikely(!skb)) + return; + if (likely(atomic_read(&skb->users) == 1)) + smp_rmb(); + else if (likely(!atomic_dec_and_test(&skb->users))) + return; + __kfree_skb(skb); +} +EXPORT_SYMBOL(consume_skb); + /** * skb_recycle_check - check if skb can be reused for receive * @skb: buffer diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 3d67d1ffed7..9c220323f35 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -892,7 +892,7 @@ static int arp_process(struct sk_buff *skb) out: if (in_dev) in_dev_put(in_dev); - kfree_skb(skb); + consume_skb(skb); return 0; } diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 4bd178a111d..05b7abb99f6 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1184,7 +1184,7 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb, sk = sknext; } while (sknext); } else - kfree_skb(skb); + consume_skb(skb); spin_unlock(&hslot->lock); return 0; } diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index d8cc006fac4..74776de523e 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -584,7 +584,7 @@ drop_n_restore: skb->len = skb_len; } drop: - kfree_skb(skb); + consume_skb(skb); return 0; } -- GitLab From 9a8afc8d3962f3ed26fd6b56db34133860ed1e72 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Wed, 11 Mar 2009 09:51:26 +0000 Subject: [PATCH 3349/4982] Network Drop Monitor: Adding drop monitor implementation & Netlink protocol Signed-off-by: Neil Horman include/linux/net_dropmon.h | 56 +++++++++ net/core/drop_monitor.c | 263 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 319 insertions(+) Signed-off-by: David S. Miller --- include/linux/net_dropmon.h | 56 ++++++++ net/core/drop_monitor.c | 263 ++++++++++++++++++++++++++++++++++++ 2 files changed, 319 insertions(+) create mode 100644 include/linux/net_dropmon.h create mode 100644 net/core/drop_monitor.c diff --git a/include/linux/net_dropmon.h b/include/linux/net_dropmon.h new file mode 100644 index 00000000000..0217fb81a63 --- /dev/null +++ b/include/linux/net_dropmon.h @@ -0,0 +1,56 @@ +#ifndef __NET_DROPMON_H +#define __NET_DROPMON_H + +#include + +struct net_dm_drop_point { + __u8 pc[8]; + __u32 count; +}; + +#define NET_DM_CFG_VERSION 0 +#define NET_DM_CFG_ALERT_COUNT 1 +#define NET_DM_CFG_ALERT_DELAY 2 +#define NET_DM_CFG_MAX 3 + +struct net_dm_config_entry { + __u32 type; + __u64 data __attribute__((aligned(8))); +}; + +struct net_dm_config_msg { + __u32 entries; + struct net_dm_config_entry options[0]; +}; + +struct net_dm_alert_msg { + __u32 entries; + struct net_dm_drop_point points[0]; +}; + +struct net_dm_user_msg { + union { + struct net_dm_config_msg user; + struct net_dm_alert_msg alert; + } u; +}; + + +/* These are the netlink message types for this protocol */ + +enum { + NET_DM_CMD_UNSPEC = 0, + NET_DM_CMD_ALERT, + NET_DM_CMD_CONFIG, + NET_DM_CMD_START, + NET_DM_CMD_STOP, + _NET_DM_CMD_MAX, +}; + +#define NET_DM_CMD_MAX (_NET_DM_CMD_MAX - 1) + +/* + * Our group identifiers + */ +#define NET_DM_GRP_ALERT 1 +#endif diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c new file mode 100644 index 00000000000..9fd0dc3cca9 --- /dev/null +++ b/net/core/drop_monitor.c @@ -0,0 +1,263 @@ +/* + * Monitoring code for network dropped packet alerts + * + * Copyright (C) 2009 Neil Horman + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#define TRACE_ON 1 +#define TRACE_OFF 0 + +static void send_dm_alert(struct work_struct *unused); + + +/* + * Globals, our netlink socket pointer + * and the work handle that will send up + * netlink alerts + */ +struct sock *dm_sock; + +struct per_cpu_dm_data { + struct work_struct dm_alert_work; + struct sk_buff *skb; + atomic_t dm_hit_count; + struct timer_list send_timer; +}; + +static struct genl_family net_drop_monitor_family = { + .id = GENL_ID_GENERATE, + .hdrsize = 0, + .name = "NET_DM", + .version = 1, + .maxattr = NET_DM_CMD_MAX, +}; + +static DEFINE_PER_CPU(struct per_cpu_dm_data, dm_cpu_data); + +static int dm_hit_limit = 64; +static int dm_delay = 1; + + +static void reset_per_cpu_data(struct per_cpu_dm_data *data) +{ + size_t al; + struct net_dm_alert_msg *msg; + + al = sizeof(struct net_dm_alert_msg); + al += dm_hit_limit * sizeof(struct net_dm_drop_point); + data->skb = genlmsg_new(al, GFP_KERNEL); + genlmsg_put(data->skb, 0, 0, &net_drop_monitor_family, + 0, NET_DM_CMD_ALERT); + msg = __nla_reserve_nohdr(data->skb, sizeof(struct net_dm_alert_msg)); + memset(msg, 0, al); + atomic_set(&data->dm_hit_count, dm_hit_limit); +} + +static void send_dm_alert(struct work_struct *unused) +{ + struct sk_buff *skb; + struct per_cpu_dm_data *data = &__get_cpu_var(dm_cpu_data); + + /* + * Grab the skb we're about to send + */ + skb = data->skb; + + /* + * Replace it with a new one + */ + reset_per_cpu_data(data); + + /* + * Ship it! + */ + genlmsg_multicast(skb, 0, NET_DM_GRP_ALERT, GFP_KERNEL); + +} + +/* + * This is the timer function to delay the sending of an alert + * in the event that more drops will arrive during the + * hysteresis period. Note that it operates under the timer interrupt + * so we don't need to disable preemption here + */ +static void sched_send_work(unsigned long unused) +{ + struct per_cpu_dm_data *data = &__get_cpu_var(dm_cpu_data); + + schedule_work(&data->dm_alert_work); +} + +static void trace_kfree_skb_hit(struct sk_buff *skb, void *location) +{ + struct net_dm_alert_msg *msg; + struct nlmsghdr *nlh; + int i; + struct per_cpu_dm_data *data = &__get_cpu_var(dm_cpu_data); + + + if (!atomic_add_unless(&data->dm_hit_count, -1, 0)) { + /* + * we're already at zero, discard this hit + */ + goto out; + } + + nlh = (struct nlmsghdr *)data->skb->data; + msg = genlmsg_data(nlmsg_data(nlh)); + for (i = 0; i < msg->entries; i++) { + if (!memcmp(&location, msg->points[i].pc, sizeof(void *))) { + msg->points[i].count++; + goto out; + } + } + + /* + * We need to create a new entry + */ + __nla_reserve_nohdr(data->skb, sizeof(struct net_dm_drop_point)); + memcpy(msg->points[msg->entries].pc, &location, sizeof(void *)); + msg->points[msg->entries].count = 1; + msg->entries++; + + if (!timer_pending(&data->send_timer)) { + data->send_timer.expires = jiffies + dm_delay * HZ; + add_timer_on(&data->send_timer, smp_processor_id()); + } + +out: + return; +} + +static int set_all_monitor_traces(int state) +{ + int rc = 0; + + switch (state) { + case TRACE_ON: + rc |= register_trace_kfree_skb(trace_kfree_skb_hit); + break; + case TRACE_OFF: + rc |= unregister_trace_kfree_skb(trace_kfree_skb_hit); + + tracepoint_synchronize_unregister(); + break; + default: + rc = 1; + break; + } + + if (rc) + return -EINPROGRESS; + return rc; +} + + +static int net_dm_cmd_config(struct sk_buff *skb, + struct genl_info *info) +{ + return -ENOTSUPP; +} + +static int net_dm_cmd_trace(struct sk_buff *skb, + struct genl_info *info) +{ + switch (info->genlhdr->cmd) { + case NET_DM_CMD_START: + return set_all_monitor_traces(TRACE_ON); + break; + case NET_DM_CMD_STOP: + return set_all_monitor_traces(TRACE_OFF); + break; + } + + return -ENOTSUPP; +} + + +static struct genl_ops dropmon_ops[] = { + { + .cmd = NET_DM_CMD_CONFIG, + .doit = net_dm_cmd_config, + }, + { + .cmd = NET_DM_CMD_START, + .doit = net_dm_cmd_trace, + }, + { + .cmd = NET_DM_CMD_STOP, + .doit = net_dm_cmd_trace, + }, +}; + +static int __init init_net_drop_monitor(void) +{ + int cpu; + int rc, i, ret; + struct per_cpu_dm_data *data; + printk(KERN_INFO "Initalizing network drop monitor service\n"); + + if (sizeof(void *) > 8) { + printk(KERN_ERR "Unable to store program counters on this arch, Drop monitor failed\n"); + return -ENOSPC; + } + + if (genl_register_family(&net_drop_monitor_family) < 0) { + printk(KERN_ERR "Could not create drop monitor netlink family\n"); + return -EFAULT; + } + + rc = -EFAULT; + + for (i = 0; i < ARRAY_SIZE(dropmon_ops); i++) { + ret = genl_register_ops(&net_drop_monitor_family, + &dropmon_ops[i]); + if (ret) { + printk(KERN_CRIT "failed to register operation %d\n", + dropmon_ops[i].cmd); + goto out_unreg; + } + } + + rc = 0; + + for_each_present_cpu(cpu) { + data = &per_cpu(dm_cpu_data, cpu); + reset_per_cpu_data(data); + INIT_WORK(&data->dm_alert_work, send_dm_alert); + init_timer(&data->send_timer); + data->send_timer.data = cpu; + data->send_timer.function = sched_send_work; + } + goto out; + +out_unreg: + genl_unregister_family(&net_drop_monitor_family); +out: + return rc; +} + +late_initcall(init_net_drop_monitor); -- GitLab From 273ae44b9cb9443e0b5265cdc99f127ddb95c8db Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Wed, 11 Mar 2009 09:53:16 +0000 Subject: [PATCH 3350/4982] Network Drop Monitor: Adding Build changes to enable drop monitor Network Drop Monitor: Adding Build changes to enable drop monitor Signed-off-by: Neil Horman include/linux/Kbuild | 1 + net/Kconfig | 11 +++++++++++ net/core/Makefile | 1 + 3 files changed, 13 insertions(+) Signed-off-by: David S. Miller --- include/linux/Kbuild | 1 + net/Kconfig | 11 +++++++++++ net/core/Makefile | 1 + 3 files changed, 13 insertions(+) diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 106c3ba5084..e9581fd9fb6 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -115,6 +115,7 @@ header-y += mqueue.h header-y += mtio.h header-y += ncp_no.h header-y += neighbour.h +header-y += net_dropmon.h header-y += netfilter_arp.h header-y += netrom.h header-y += nfs2.h diff --git a/net/Kconfig b/net/Kconfig index 6b39ede3b1b..c9fdcd7e71e 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -222,6 +222,17 @@ config NET_TCPPROBE To compile this code as a module, choose M here: the module will be called tcp_probe. +config NET_DROP_MONITOR + boolean "Network packet drop alerting service" + depends on INET && EXPERIMENTAL && TRACEPOINTS + ---help--- + This feature provides an alerting service to userspace in the + event that packets are discarded in the network stack. Alerts + are broadcast via netlink socket to any listening user space + process. If you don't need network drop alerts, or if you are ok + just checking the various proc files and other utilities for + drop statistics, say N here. + endmenu endmenu diff --git a/net/core/Makefile b/net/core/Makefile index d47092bc525..796f46eece5 100644 --- a/net/core/Makefile +++ b/net/core/Makefile @@ -18,4 +18,5 @@ obj-$(CONFIG_NETPOLL) += netpoll.o obj-$(CONFIG_NET_DMA) += user_dma.o obj-$(CONFIG_FIB_RULES) += fib_rules.o obj-$(CONFIG_TRACEPOINTS) += net-traces.o +obj-$(CONFIG_NET_DROP_MONITOR) += drop_monitor.o -- GitLab From 8dacd548129d03e87751f75ea83b42a8a17ee651 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Wed, 4 Mar 2009 07:33:24 +0000 Subject: [PATCH 3351/4982] smsc911x: check for FFWD success before checking for timeout This patch from Juha Leppanen suppresses a false warning if a fast forward operation succeeds on the very last attempt. Juha> If smsc911x_reg_read loop is executed 500 times, timeout reaches 0 Juha> and the 500th smsc911x_reg_read result in val is ignored. If Juha> testing order is changed, then val is checked first. The 500th Juha> reg_read might be GOOD, why ignore it! Signed-off-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/smsc911x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index dceae8a6580..9a795105cc7 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -955,7 +955,7 @@ smsc911x_rx_fastforward(struct smsc911x_data *pdata, unsigned int pktbytes) do { udelay(1); val = smsc911x_reg_read(pdata, RX_DP_CTRL); - } while (--timeout && (val & RX_DP_CTRL_RX_FFWD_)); + } while ((val & RX_DP_CTRL_RX_FFWD_) && --timeout); if (unlikely(timeout == 0)) SMSC_WARNING(HW, "Timed out waiting for " -- GitLab From f7efb6ccc2113911e4e064f78bcd0343c4673038 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Wed, 4 Mar 2009 07:33:25 +0000 Subject: [PATCH 3352/4982] smsc911x: improve EEPROM loading timeout logic in open This patch from Juha Leppanen suppresses a false warning if the eeprom load succeeds on the very last attempt. Juha> In function smsc911x_open smsc911x_reg_read+udelay can be run 50 Juha> times with timeout reaching -1, and the following if statetement Juha> does not catch the timeout and no warning is issued. Also if the Juha> 50th smsc911x_reg_read is GOOD, loop is exited with timeout as 0 Juha> and bogus warning issued. Replace testing order and --timeout Juha> instead of timeout-- and now max 50 smsc911x_reg_read's are done, Juha> with max 49 udelays. Signed-off-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/smsc911x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 9a795105cc7..ad15aab2137 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1162,8 +1162,8 @@ static int smsc911x_open(struct net_device *dev) /* Make sure EEPROM has finished loading before setting GPIO_CFG */ timeout = 50; - while ((timeout--) && - (smsc911x_reg_read(pdata, E2P_CMD) & E2P_CMD_EPC_BUSY_)) { + while ((smsc911x_reg_read(pdata, E2P_CMD) & E2P_CMD_EPC_BUSY_) && + --timeout) { udelay(10); } -- GitLab From 211c738d86f3f423f1b218ab3a356c9538e38047 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Fri, 27 Feb 2009 14:06:37 -0800 Subject: [PATCH 3353/4982] [SCSI] net, fcoe: add ETH_P_FCOE for Fibre Channel over Ethernet (FCoE) This adds eth type ETH_P_FCOE for Fibre Channel over Ethernet (FCoE), consequently, the ETH_P_FCOE from fc_fcoe.h and fcoe skb->protocol is not set as ETH_P_FCOE. Signed-off-by: Yi Zou Acked-by: David Miller Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 2 +- include/linux/if_ether.h | 1 + include/scsi/fc/fc_fcoe.h | 7 ------- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 5548bf3bb58..a99a42807b3 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -460,7 +460,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) skb_reset_mac_header(skb); skb_reset_network_header(skb); skb->mac_len = elen; - skb->protocol = htons(ETH_P_802_3); + skb->protocol = htons(ETH_P_FCOE); skb->dev = fc->real_dev; /* fill up mac and fcoe headers */ diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index 7f3c735f422..59d197cb485 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -78,6 +78,7 @@ #define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ #define ETH_P_AOE 0x88A2 /* ATA over Ethernet */ #define ETH_P_TIPC 0x88CA /* TIPC */ +#define ETH_P_FCOE 0x8906 /* Fibre Channel over Ethernet */ #define ETH_P_EDSA 0xDADA /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */ /* diff --git a/include/scsi/fc/fc_fcoe.h b/include/scsi/fc/fc_fcoe.h index f271d9cc0fc..ccb3dbe9046 100644 --- a/include/scsi/fc/fc_fcoe.h +++ b/include/scsi/fc/fc_fcoe.h @@ -24,13 +24,6 @@ * FCoE - Fibre Channel over Ethernet. */ -/* - * The FCoE ethertype eventually goes in net/if_ether.h. - */ -#ifndef ETH_P_FCOE -#define ETH_P_FCOE 0x8906 /* FCOE ether type */ -#endif - /* * FC_FCOE_OUI hasn't been standardized yet. XXX TBD. */ -- GitLab From 43eb99c5b349b188f82725652f3d1018c619d682 Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Fri, 27 Feb 2009 14:06:43 -0800 Subject: [PATCH 3354/4982] [SCSI] net: reclaim 8 upper bits of the netdev->features from GSO Reclaim 8 upper bits of netdev->features from GSO. Signed-off-by: Chris Leech Signed-off-by: Yi Zou Acked-by: David Miller Signed-off-by: James Bottomley --- drivers/net/xen-netfront.c | 2 +- include/linux/netdevice.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index cd6184ee08e..2ce536fcd20 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1511,7 +1511,7 @@ static int xennet_set_tso(struct net_device *dev, u32 data) static void xennet_set_features(struct net_device *dev) { /* Turn off all GSO bits except ROBUST. */ - dev->features &= (1 << NETIF_F_GSO_SHIFT) - 1; + dev->features &= ~NETIF_F_GSO_MASK; dev->features |= NETIF_F_GSO_ROBUST; xennet_set_sg(dev, 0); diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index ec54785d34f..c8238d9ba37 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -652,7 +652,7 @@ struct net_device /* Segmentation offload features */ #define NETIF_F_GSO_SHIFT 16 -#define NETIF_F_GSO_MASK 0xffff0000 +#define NETIF_F_GSO_MASK 0x00ff0000 #define NETIF_F_TSO (SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT) #define NETIF_F_UFO (SKB_GSO_UDP << NETIF_F_GSO_SHIFT) #define NETIF_F_GSO_ROBUST (SKB_GSO_DODGY << NETIF_F_GSO_SHIFT) -- GitLab From 01d5b2fca1fa58ed5039239fd531e9f658971ace Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Fri, 27 Feb 2009 14:06:49 -0800 Subject: [PATCH 3355/4982] [SCSI] net: define feature flags for FCoE offloads Define feature flags for FCoE offloads. Signed-off-by: Chris Leech Signed-off-by: Yi Zou Acked-by: David Miller Signed-off-by: James Bottomley --- include/linux/netdevice.h | 3 +++ include/linux/skbuff.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index c8238d9ba37..5c405571cb6 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -650,6 +650,8 @@ struct net_device #define NETIF_F_GRO 16384 /* Generic receive offload */ #define NETIF_F_LRO 32768 /* large receive offload */ +#define NETIF_F_FCOE_CRC (1 << 24) /* FCoE CRC32 */ + /* Segmentation offload features */ #define NETIF_F_GSO_SHIFT 16 #define NETIF_F_GSO_MASK 0x00ff0000 @@ -658,6 +660,7 @@ struct net_device #define NETIF_F_GSO_ROBUST (SKB_GSO_DODGY << NETIF_F_GSO_SHIFT) #define NETIF_F_TSO_ECN (SKB_GSO_TCP_ECN << NETIF_F_GSO_SHIFT) #define NETIF_F_TSO6 (SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT) +#define NETIF_F_FSO (SKB_GSO_FCOE << NETIF_F_GSO_SHIFT) /* List of features with software fallbacks. */ #define NETIF_F_GSO_SOFTWARE (NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 9dcf956ad18..02adea2099a 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -188,6 +188,8 @@ enum { SKB_GSO_TCP_ECN = 1 << 3, SKB_GSO_TCPV6 = 1 << 4, + + SKB_GSO_FCOE = 1 << 5, }; #if BITS_PER_LONG > 32 -- GitLab From 1c8dbcf6496c2612d883a8bc6bccc38000e14866 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Fri, 27 Feb 2009 14:06:54 -0800 Subject: [PATCH 3356/4982] [SCSI] net: add NETIF_F_FCOE_CRC to can_checksum_protocol Add FC CRC offload check for ETH_P_FCOE. Signed-off-by: Yi Zou Acked-by: David Miller Signed-off-by: James Bottomley --- net/core/dev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index 72b0d26fd46..3d3670640c2 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1457,7 +1457,9 @@ static bool can_checksum_protocol(unsigned long features, __be16 protocol) ((features & NETIF_F_IP_CSUM) && protocol == htons(ETH_P_IP)) || ((features & NETIF_F_IPV6_CSUM) && - protocol == htons(ETH_P_IPV6))); + protocol == htons(ETH_P_IPV6)) || + ((features & NETIF_F_FCOE_CRC) && + protocol == htons(ETH_P_FCOE))); } static bool dev_can_checksum(struct net_device *dev, struct sk_buff *skb) -- GitLab From 4d288d5767f853bfca25adc7b6030dc95518cb2e Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Fri, 27 Feb 2009 14:06:59 -0800 Subject: [PATCH 3357/4982] [SCSI] net: add FCoE offload support through net_device This adds support to provide Fiber Channel over Ethernet (FCoE) offload through net_device's net_device_ops struct. The offload through net_device for FCoE is enabled in kernel as built-in or module driver. Signed-off-by: Yi Zou Acked-by: David Miller Signed-off-by: James Bottomley --- include/linux/netdevice.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 5c405571cb6..7ed49f5335b 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -582,6 +582,14 @@ struct net_device_ops { #define HAVE_NETDEV_POLL void (*ndo_poll_controller)(struct net_device *dev); #endif +#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) + int (*ndo_fcoe_ddp_setup)(struct net_device *dev, + u16 xid, + struct scatterlist *sgl, + unsigned int sgc); + int (*ndo_fcoe_ddp_done)(struct net_device *dev, + u16 xid); +#endif }; /* @@ -843,6 +851,11 @@ struct net_device struct dcbnl_rtnl_ops *dcbnl_ops; #endif +#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) + /* max exchange id for FCoE LRO by ddp */ + unsigned int fcoe_ddp_xid; +#endif + #ifdef CONFIG_COMPAT_NET_DEV_OPS struct { int (*init)(struct net_device *dev); -- GitLab From ea1e9a9df5e1fde7ad8878c85b4a097cad0ddcea Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Fri, 27 Feb 2009 14:07:04 -0800 Subject: [PATCH 3358/4982] [SCSI] fcoe, libfc: check offload features from LLD through netdev This checks if net_devices supports FCoE offload ops in netdev_ops and it if it does, then sets up the corresponding flags in the associated fc_lport. For large send offload, the maximum length supported in one large send is now described by the added lso_max in fc_lport, which is setup initially from netdev->gso_max_size. Signed-off-by: Yi Zou Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe_sw.c | 29 ++++++++++++++++++++++++++++- include/scsi/libfc.h | 1 + 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c index da210eba194..d99217d0510 100644 --- a/drivers/scsi/fcoe/fcoe_sw.c +++ b/drivers/scsi/fcoe/fcoe_sw.c @@ -133,6 +133,13 @@ static int fcoe_sw_lport_config(struct fc_lport *lp) /* lport fc_lport related configuration */ fc_lport_config(lp); + /* offload related configuration */ + lp->crc_offload = 0; + lp->seq_offload = 0; + lp->lro_enabled = 0; + lp->lro_xid = 0; + lp->lso_max = 0; + return 0; } @@ -186,7 +193,27 @@ static int fcoe_sw_netdev_config(struct fc_lport *lp, struct net_device *netdev) if (fc->real_dev->features & NETIF_F_SG) lp->sg_supp = 1; - +#ifdef NETIF_F_FCOE_CRC + if (netdev->features & NETIF_F_FCOE_CRC) { + lp->crc_offload = 1; + printk(KERN_DEBUG "fcoe:%s supports FCCRC offload\n", + netdev->name); + } +#endif +#ifdef NETIF_F_FSO + if (netdev->features & NETIF_F_FSO) { + lp->seq_offload = 1; + lp->lso_max = netdev->gso_max_size; + printk(KERN_DEBUG "fcoe:%s supports LSO for max len 0x%x\n", + netdev->name, lp->lso_max); + } +#endif + if (netdev->fcoe_ddp_xid) { + lp->lro_enabled = 1; + lp->lro_xid = netdev->fcoe_ddp_xid; + printk(KERN_DEBUG "fcoe:%s supports LRO for max xid 0x%x\n", + netdev->name, lp->lro_xid); + } skb_queue_head_init(&fc->fcoe_pending_queue); fc->fcoe_pending_queue_active = 0; diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index a2e126b86e3..61c746cf55f 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -654,6 +654,7 @@ struct fc_lport { u16 link_speed; u16 link_supported_speeds; u16 lro_xid; /* max xid for fcoe lro */ + unsigned int lso_max; /* max large send size */ struct fc_ns_fts fcts; /* FC-4 type masks */ struct fc_els_rnid_gen rnid_gen; /* RNID information */ -- GitLab From 276d68142b7b676594ab8739355c27e9e5b3d41d Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Fri, 27 Feb 2009 14:07:10 -0800 Subject: [PATCH 3359/4982] [SCSI] libfc: use lso_max for sequence offload Make sure for large send is supported by LLD in outgoing FCP data, we are only sending the lso_max a time in one single large send, since that is what supported by LLD. Signed-off-by: Yi Zou Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_fcp.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index a070e571243..48adb89d911 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -435,7 +435,13 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, * burst length (t_blen) to seq_blen, otherwise set t_blen * to max FC frame payload previously set in fsp->max_payload. */ - t_blen = lp->seq_offload ? seq_blen : fsp->max_payload; + t_blen = fsp->max_payload; + if (lp->seq_offload) { + t_blen = min(seq_blen, (size_t)lp->lso_max); + FC_DEBUG_FCP("fsp=%p:lso:blen=%zx lso_max=0x%x t_blen=%zx\n", + fsp, seq_blen, lp->lso_max, t_blen); + } + WARN_ON(t_blen < FC_MIN_MAX_PAYLOAD); if (t_blen > 512) t_blen &= ~(512 - 1); /* round down to block size */ -- GitLab From 39ca9a065a5a0a6f2f0cd648090a979ba3f4f018 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Fri, 27 Feb 2009 14:07:15 -0800 Subject: [PATCH 3360/4982] [SCSI] fcoe: add support to large send by gso through net_device for fcoe_sw Change fcoe_xmit to setup gso for LLD LSO offload as well as CRC offload Signed-off-by: Yi Zou Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index a99a42807b3..5dae823057a 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -423,7 +423,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) /* crc offload */ if (likely(lp->crc_offload)) { - skb->ip_summed = CHECKSUM_COMPLETE; + skb->ip_summed = CHECKSUM_PARTIAL; skb->csum_start = skb_headroom(skb); skb->csum_offset = skb->len; crc = 0; @@ -483,6 +483,16 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) FC_FCOE_ENCAPS_VER(hp, FC_FCOE_VER); hp->fcoe_sof = sof; +#ifdef NETIF_F_FSO + /* fcoe lso, mss is in max_payload which is non-zero for FCP data */ + if (lp->seq_offload && fr_max_payload(fp)) { + skb_shinfo(skb)->gso_type = SKB_GSO_FCOE; + skb_shinfo(skb)->gso_size = fr_max_payload(fp); + } else { + skb_shinfo(skb)->gso_type = 0; + skb_shinfo(skb)->gso_size = 0; + } +#endif /* update tx stats: regardless if LLD fails */ stats = lp->dev_stats[smp_processor_id()]; if (stats) { -- GitLab From b277d2aa9a4d969002c4157bf77b76b9ad9ca04a Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Fri, 27 Feb 2009 14:07:21 -0800 Subject: [PATCH 3361/4982] [SCSI] libfc: add support of large receive offload by ddp in fc_fcp When LLD supports direct data placement (ddp) for large receive of an scsi i/o coming into fc_fcp, we call into libfc_function_template's ddp_setup() to prepare for a ddp of large receive for this read I/O. When I/O is complete, we call the corresponding ddp_done() to get the length of data ddped as well as to let LLD do clean up. fc_fcp_ddp_setup()/fc_fcp_ddp_done() are added to setup and complete a ddped read I/O described by the given fc_fcp_pkt. They would call into corresponding ddp_setup/ddp_done implemented by the fcoe layer. Eventually, fcoe layer calls into LLD's ddp_setup/ddp_done provided through net_device Signed-off-by: Yi Zou Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 4 ++- drivers/scsi/libfc/fc_fcp.c | 61 +++++++++++++++++++++++++++++++++++- include/scsi/fc_frame.h | 19 ++--------- include/scsi/libfc.h | 30 ++++++++++++++++++ include/scsi/libfcoe.h | 18 ----------- 5 files changed, 95 insertions(+), 37 deletions(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 8a0c5c239e9..992af05aacf 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -489,7 +489,7 @@ static u16 fc_em_alloc_xid(struct fc_exch_mgr *mp, const struct fc_frame *fp) struct fc_exch *ep = NULL; if (mp->max_read) { - if (fc_frame_is_read(fp)) { + if (fc_fcp_is_read(fr_fsp(fp))) { min = mp->min_xid; max = mp->max_read; plast = &mp->last_read; @@ -1841,6 +1841,8 @@ struct fc_seq *fc_exch_seq_send(struct fc_lport *lp, fc_exch_setup_hdr(ep, fp, ep->f_ctl); sp->cnt++; + fc_fcp_ddp_setup(fr_fsp(fp), ep->xid); + if (unlikely(lp->tt.frame_send(lp, fp))) goto err; diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 48adb89d911..a5725f3b7ce 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -264,6 +264,56 @@ static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp) fc_fcp_complete_locked(fsp); } +/* + * fc_fcp_ddp_setup - calls to LLD's ddp_setup to set up DDP + * transfer for a read I/O indicated by the fc_fcp_pkt. + * @fsp: ptr to the fc_fcp_pkt + * + * This is called in exch_seq_send() when we have a newly allocated + * exchange with a valid exchange id to setup ddp. + * + * returns: none + */ +void fc_fcp_ddp_setup(struct fc_fcp_pkt *fsp, u16 xid) +{ + struct fc_lport *lp; + + if (!fsp) + return; + + lp = fsp->lp; + if ((fsp->req_flags & FC_SRB_READ) && + (lp->lro_enabled) && (lp->tt.ddp_setup)) { + if (lp->tt.ddp_setup(lp, xid, scsi_sglist(fsp->cmd), + scsi_sg_count(fsp->cmd))) + fsp->xfer_ddp = xid; + } +} +EXPORT_SYMBOL(fc_fcp_ddp_setup); + +/* + * fc_fcp_ddp_done - calls to LLD's ddp_done to release any + * DDP related resources for this I/O if it is initialized + * as a ddp transfer + * @fsp: ptr to the fc_fcp_pkt + * + * returns: none + */ +static void fc_fcp_ddp_done(struct fc_fcp_pkt *fsp) +{ + struct fc_lport *lp; + + if (!fsp) + return; + + lp = fsp->lp; + if (fsp->xfer_ddp && lp->tt.ddp_done) { + fsp->xfer_len = lp->tt.ddp_done(lp, fsp->xfer_ddp); + fsp->xfer_ddp = 0; + } +} + + /* * Receive SCSI data from target. * Called after receiving solicited data. @@ -289,6 +339,9 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp) len = fr_len(fp) - sizeof(*fh); buf = fc_frame_payload_get(fp, 0); + /* if this I/O is ddped, update xfer len */ + fc_fcp_ddp_done(fsp); + if (offset + len > fsp->data_len) { /* this should never happen */ if ((fr_flags(fp) & FCPHF_CRC_UNCHECKED) && @@ -750,6 +803,9 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) fsp->scsi_comp_flags = flags; expected_len = fsp->data_len; + /* if ddp, update xfer len */ + fc_fcp_ddp_done(fsp); + if (unlikely((flags & ~FCP_CONF_REQ) || fc_rp->fr_status)) { rp_ex = (void *)(fc_rp + 1); if (flags & (FCP_RSP_LEN_VAL | FCP_SNS_LEN_VAL)) { @@ -1012,7 +1068,7 @@ static int fc_fcp_cmd_send(struct fc_lport *lp, struct fc_fcp_pkt *fsp, } memcpy(fc_frame_payload_get(fp, len), &fsp->cdb_cmd, len); - fr_cmd(fp) = fsp->cmd; + fr_fsp(fp) = fsp; rport = fsp->rport; fsp->max_payload = rport->maxframe_size; rp = rport->dd_data; @@ -1746,6 +1802,9 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) struct fc_lport *lp; unsigned long flags; + /* release outstanding ddp context */ + fc_fcp_ddp_done(fsp); + fsp->state |= FC_SRB_COMPL; if (!(fsp->state & FC_SRB_FCP_PROCESSING_TMO)) { spin_unlock_bh(&fsp->scsi_pkt_lock); diff --git a/include/scsi/fc_frame.h b/include/scsi/fc_frame.h index 04d34a71355..59511057cee 100644 --- a/include/scsi/fc_frame.h +++ b/include/scsi/fc_frame.h @@ -54,8 +54,7 @@ #define fr_eof(fp) (fr_cb(fp)->fr_eof) #define fr_flags(fp) (fr_cb(fp)->fr_flags) #define fr_max_payload(fp) (fr_cb(fp)->fr_max_payload) -#define fr_cmd(fp) (fr_cb(fp)->fr_cmd) -#define fr_dir(fp) (fr_cmd(fp)->sc_data_direction) +#define fr_fsp(fp) (fr_cb(fp)->fr_fsp) #define fr_crc(fp) (fr_cb(fp)->fr_crc) struct fc_frame { @@ -66,7 +65,7 @@ struct fcoe_rcv_info { struct packet_type *ptype; struct fc_lport *fr_dev; /* transport layer private pointer */ struct fc_seq *fr_seq; /* for use with exchange manager */ - struct scsi_cmnd *fr_cmd; /* for use of scsi command */ + struct fc_fcp_pkt *fr_fsp; /* for the corresponding fcp I/O */ u32 fr_crc; u16 fr_max_payload; /* max FC payload */ enum fc_sof fr_sof; /* start of frame delimiter */ @@ -218,20 +217,6 @@ static inline bool fc_frame_is_cmd(const struct fc_frame *fp) return fc_frame_rctl(fp) == FC_RCTL_DD_UNSOL_CMD; } -static inline bool fc_frame_is_read(const struct fc_frame *fp) -{ - if (fc_frame_is_cmd(fp) && fr_cmd(fp)) - return fr_dir(fp) == DMA_FROM_DEVICE; - return false; -} - -static inline bool fc_frame_is_write(const struct fc_frame *fp) -{ - if (fc_frame_is_cmd(fp) && fr_cmd(fp)) - return fr_dir(fp) == DMA_TO_DEVICE; - return false; -} - /* * Check for leaks. * Print the frame header of any currently allocated frame, assuming there diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 61c746cf55f..a70eafaad08 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -245,6 +245,7 @@ struct fc_fcp_pkt { */ struct fcp_cmnd cdb_cmd; size_t xfer_len; + u16 xfer_ddp; /* this xfer is ddped */ u32 xfer_contig_end; /* offset of end of contiguous xfer */ u16 max_payload; /* max payload size in bytes */ @@ -267,6 +268,15 @@ struct fc_fcp_pkt { u8 recov_retry; /* count of recovery retries */ struct fc_seq *recov_seq; /* sequence for REC or SRR */ }; +/* + * FC_FCP HELPER FUNCTIONS + *****************************/ +static inline bool fc_fcp_is_read(const struct fc_fcp_pkt *fsp) +{ + if (fsp && fsp->cmd) + return fsp->cmd->sc_data_direction == DMA_FROM_DEVICE; + return false; +} /* * Structure and function definitions for managing Fibre Channel Exchanges @@ -399,6 +409,21 @@ struct libfc_function_template { void *arg), void *arg, unsigned int timer_msec); + /* + * Sets up the DDP context for a given exchange id on the given + * scatterlist if LLD supports DDP for large receive. + * + * STATUS: OPTIONAL + */ + int (*ddp_setup)(struct fc_lport *lp, u16 xid, + struct scatterlist *sgl, unsigned int sgc); + /* + * Completes the DDP transfer and returns the length of data DDPed + * for the given exchange id. + * + * STATUS: OPTIONAL + */ + int (*ddp_done)(struct fc_lport *lp, u16 xid); /* * Send a frame using an existing sequence and exchange. * @@ -821,6 +846,11 @@ int fc_change_queue_type(struct scsi_device *sdev, int tag_type); */ void fc_fcp_destroy(struct fc_lport *); +/* + * Set up direct-data placement for this I/O request + */ +void fc_fcp_ddp_setup(struct fc_fcp_pkt *fsp, u16 xid); + /* * ELS/CT interface *****************************/ diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h index 941818f29f5..c41f7d0c6ef 100644 --- a/include/scsi/libfcoe.h +++ b/include/scsi/libfcoe.h @@ -124,24 +124,6 @@ static inline u16 skb_fc_rxid(const struct sk_buff *skb) return be16_to_cpu(skb_fc_header(skb)->fh_rx_id); } -/* FIXME - DMA_BIDIRECTIONAL ? */ -#define skb_cb(skb) ((struct fcoe_rcv_info *)&((skb)->cb[0])) -#define skb_cmd(skb) (skb_cb(skb)->fr_cmd) -#define skb_dir(skb) (skb_cmd(skb)->sc_data_direction) -static inline bool skb_fc_is_read(const struct sk_buff *skb) -{ - if (skb_fc_is_cmd(skb) && skb_cmd(skb)) - return skb_dir(skb) == DMA_FROM_DEVICE; - return false; -} - -static inline bool skb_fc_is_write(const struct sk_buff *skb) -{ - if (skb_fc_is_cmd(skb) && skb_cmd(skb)) - return skb_dir(skb) == DMA_TO_DEVICE; - return false; -} - /* libfcoe funcs */ int fcoe_reset(struct Scsi_Host *shost); u64 fcoe_wwn_from_mac(unsigned char mac[MAX_ADDR_LEN], -- GitLab From e05620073625935290120be93a6214b1b52ae34f Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Fri, 27 Feb 2009 14:07:26 -0800 Subject: [PATCH 3362/4982] [SCSI] fcoe: add support to FCoE offload support in fcoe_sw through net_device This adds implementation of ddp_setup()/ddp_done() in fcoe_sw for its fcoe_sw_libfc_fcn_templ. Signed-off-by: Yi Zou Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe_sw.c | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c index d99217d0510..2bbbe3c0cc7 100644 --- a/drivers/scsi/fcoe/fcoe_sw.c +++ b/drivers/scsi/fcoe/fcoe_sw.c @@ -373,8 +373,46 @@ static int fcoe_sw_destroy(struct net_device *netdev) return 0; } +/* + * fcoe_sw_ddp_setup - calls LLD's ddp_setup through net_device + * @lp: the corresponding fc_lport + * @xid: the exchange id for this ddp transfer + * @sgl: the scatterlist describing this transfer + * @sgc: number of sg items + * + * Returns : 0 no ddp + */ +static int fcoe_sw_ddp_setup(struct fc_lport *lp, u16 xid, + struct scatterlist *sgl, unsigned int sgc) +{ + struct net_device *n = fcoe_netdev(lp); + + if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_setup) + return n->netdev_ops->ndo_fcoe_ddp_setup(n, xid, sgl, sgc); + + return 0; +} + +/* + * fcoe_sw_ddp_done - calls LLD's ddp_done through net_device + * @lp: the corresponding fc_lport + * @xid: the exchange id for this ddp transfer + * + * Returns : the length of data that have been completed by ddp + */ +static int fcoe_sw_ddp_done(struct fc_lport *lp, u16 xid) +{ + struct net_device *n = fcoe_netdev(lp); + + if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_done) + return n->netdev_ops->ndo_fcoe_ddp_done(n, xid); + return 0; +} + static struct libfc_function_template fcoe_sw_libfc_fcn_templ = { .frame_send = fcoe_xmit, + .ddp_setup = fcoe_sw_ddp_setup, + .ddp_done = fcoe_sw_ddp_done, }; /** -- GitLab From b0832a2961022a076c812384435b5f0290b3fc91 Mon Sep 17 00:00:00 2001 From: Eric Biederman Date: Fri, 13 Mar 2009 13:15:37 -0700 Subject: [PATCH 3363/4982] macvlan: Support creating macvlans from macvlans When running in a network namespace whose only link to the outside world is a macvlan device, not being able to create another macvlan is a real pain. So modify macvlan creation to allow automatically forward a creation of a macvlan on a macvlan to become a creation of a macvlan on the underlying network device. Signed-off-by: Eric Biederman Acked-by: Patrick McHardy Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 7e24b504868..b5241fc0f51 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -461,12 +461,13 @@ static int macvlan_newlink(struct net_device *dev, if (lowerdev == NULL) return -ENODEV; - /* Don't allow macvlans on top of other macvlans - its not really - * wrong, but lockdep can't handle it and its not useful for anything - * you couldn't do directly on top of the real device. + /* When creating macvlans on top of other macvlans - use + * the real device as the lowerdev. */ - if (lowerdev->rtnl_link_ops == dev->rtnl_link_ops) - return -ENODEV; + if (lowerdev->rtnl_link_ops == dev->rtnl_link_ops) { + struct macvlan_dev *lowervlan = netdev_priv(lowerdev); + lowerdev = lowervlan->lowerdev; + } if (!tb[IFLA_MTU]) dev->mtu = lowerdev->mtu; -- GitLab From 07c00ec449d4d94042063a6900d7d04fdc9f8e62 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Fri, 27 Feb 2009 14:07:31 -0800 Subject: [PATCH 3364/4982] [SCSI] fcoe: fcoe fc crc offload indication by skb->ip_summed If LLD supports FCCRC offload, it should set ip_summed to be CHECKSUM_UNNECESSARY so we don't have to do CRC check again. Signed-off-by: Yi Zou Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 5dae823057a..0d6f5beb7f9 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -633,7 +633,7 @@ int fcoe_percpu_receive_thread(void *arg) * it's solicited data, in which case, the FCP layer would * check it during the copy. */ - if (lp->crc_offload) + if (lp->crc_offload && skb->ip_summed == CHECKSUM_UNNECESSARY) fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; else fr_flags(fp) |= FCPHF_CRC_UNCHECKED; -- GitLab From 3eb76c1ccde496c3c0bfda23d1c803e40b762ce6 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 13 Mar 2009 21:16:12 +0100 Subject: [PATCH 3365/4982] ide-floppy: do not map dataless cmds to an sg since it fails the virt_to_page() translation check with DEBUG_VIRTUAL enabled. Signed-off-by: Borislav Petkov [bart: backport to Linus' tree] Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-atapi.c | 12 ++++++++++++ drivers/ide/ide-floppy.c | 6 ++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index e96c0126059..e9d042dba0e 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -140,6 +140,12 @@ static void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk, rq->cmd_flags |= REQ_PREEMPT; rq->buffer = (char *)pc; rq->rq_disk = disk; + + if (pc->req_xfer) { + rq->data = pc->buf; + rq->data_len = pc->req_xfer; + } + memcpy(rq->cmd, pc->c, 12); if (drive->media == ide_tape) rq->cmd[13] = REQ_IDETAPE_PC1; @@ -159,6 +165,12 @@ int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk, rq = blk_get_request(drive->queue, READ, __GFP_WAIT); rq->cmd_type = REQ_TYPE_SPECIAL; rq->buffer = (char *)pc; + + if (pc->req_xfer) { + rq->data = pc->buf; + rq->data_len = pc->req_xfer; + } + memcpy(rq->cmd, pc->c, 12); if (drive->media == ide_tape) rq->cmd[13] = REQ_IDETAPE_PC1; diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 3eab1c6c9b3..317ec62c33d 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -327,8 +327,10 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, return ide_stopped; } - ide_init_sg_cmd(drive, rq); - ide_map_sg(drive, rq); + if (blk_fs_request(rq) || pc->req_xfer) { + ide_init_sg_cmd(drive, rq); + ide_map_sg(drive, rq); + } pc->sg = hwif->sg_table; pc->sg_cnt = hwif->sg_nents; -- GitLab From f9ac30f080d23ef0a2d4a1b7c6806c9a21c0f324 Mon Sep 17 00:00:00 2001 From: Eric Biederman Date: Fri, 13 Mar 2009 13:16:13 -0700 Subject: [PATCH 3366/4982] macvlan: Deterministic ingress packet delivery Changing the mac address when a macvlan device is up will leave the device on the wrong hash chain making it impossible to receive packets. There is no checking of the mac address set on the macvlan. Allowing a misconfiguration to grab packets from the the underlying device or another macvlan. To resolve these problems I update the hash table of macvlans when the mac address of a macvlan changes, and when updating the hash table I verify that the new mac address is usable. The result is well defined and predictable if not perfect handling of mac vlan mac addresses. To keep the code clear I have created a set of hash table maintenance in macvlan so I am not open coding the hash function and the logic needed to update the hash table all over the place. Signed-off-by: Eric Biederman Acked-by: Patrick McHardy Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 73 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 60 insertions(+), 13 deletions(-) diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index b5241fc0f51..70d3ef4a2c5 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -60,6 +60,47 @@ static struct macvlan_dev *macvlan_hash_lookup(const struct macvlan_port *port, return NULL; } +static void macvlan_hash_add(struct macvlan_dev *vlan) +{ + struct macvlan_port *port = vlan->port; + const unsigned char *addr = vlan->dev->dev_addr; + + hlist_add_head_rcu(&vlan->hlist, &port->vlan_hash[addr[5]]); +} + +static void macvlan_hash_del(struct macvlan_dev *vlan) +{ + hlist_del_rcu(&vlan->hlist); + synchronize_rcu(); +} + +static void macvlan_hash_change_addr(struct macvlan_dev *vlan, + const unsigned char *addr) +{ + macvlan_hash_del(vlan); + /* Now that we are unhashed it is safe to change the device + * address without confusing packet delivery. + */ + memcpy(vlan->dev->dev_addr, addr, ETH_ALEN); + macvlan_hash_add(vlan); +} + +static int macvlan_addr_busy(const struct macvlan_port *port, + const unsigned char *addr) +{ + /* Test to see if the specified multicast address is + * currently in use by the underlying device or + * another macvlan. + */ + if (memcmp(port->dev->dev_addr, addr, ETH_ALEN) == 0) + return 1; + + if (macvlan_hash_lookup(port, addr)) + return 1; + + return 0; +} + static void macvlan_broadcast(struct sk_buff *skb, const struct macvlan_port *port) { @@ -184,10 +225,13 @@ static const struct header_ops macvlan_hard_header_ops = { static int macvlan_open(struct net_device *dev) { struct macvlan_dev *vlan = netdev_priv(dev); - struct macvlan_port *port = vlan->port; struct net_device *lowerdev = vlan->lowerdev; int err; + err = -EBUSY; + if (macvlan_addr_busy(vlan->port, dev->dev_addr)) + goto out; + err = dev_unicast_add(lowerdev, dev->dev_addr, ETH_ALEN); if (err < 0) goto out; @@ -196,8 +240,7 @@ static int macvlan_open(struct net_device *dev) if (err < 0) goto del_unicast; } - - hlist_add_head_rcu(&vlan->hlist, &port->vlan_hash[dev->dev_addr[5]]); + macvlan_hash_add(vlan); return 0; del_unicast: @@ -217,8 +260,7 @@ static int macvlan_stop(struct net_device *dev) dev_unicast_delete(lowerdev, dev->dev_addr, ETH_ALEN); - hlist_del_rcu(&vlan->hlist); - synchronize_rcu(); + macvlan_hash_del(vlan); return 0; } @@ -232,16 +274,21 @@ static int macvlan_set_mac_address(struct net_device *dev, void *p) if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - if (!(dev->flags & IFF_UP)) - goto out; + if (!(dev->flags & IFF_UP)) { + /* Just copy in the new address */ + memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); + } else { + /* Rehash and update the device filters */ + if (macvlan_addr_busy(vlan->port, addr->sa_data)) + return -EBUSY; - err = dev_unicast_add(lowerdev, addr->sa_data, ETH_ALEN); - if (err < 0) - return err; - dev_unicast_delete(lowerdev, dev->dev_addr, ETH_ALEN); + if ((err = dev_unicast_add(lowerdev, addr->sa_data, ETH_ALEN))) + return err; -out: - memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); + dev_unicast_delete(lowerdev, dev->dev_addr, ETH_ALEN); + + macvlan_hash_change_addr(vlan, addr->sa_data); + } return 0; } -- GitLab From 5d82720a7f41f0c877e026c7d17e3bf20ccdbae0 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Fri, 13 Mar 2009 21:16:13 +0100 Subject: [PATCH 3367/4982] ide: save the returned value of dma_map_sg dma_map_sg could return a value different to 'nents' argument of dma_map_sg so the ide stack needs to save it for the later usage (e.g. for_each_sg). The ide stack also needs to save the original sg_nents value for pci_unmap_sg. Signed-off-by: FUJITA Tomonori [bart: backport to Linus' tree] Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-dma.c | 12 +++++++++--- include/linux/ide.h | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 72ebab0bc75..059c90bb5ad 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -128,6 +128,7 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq) { ide_hwif_t *hwif = drive->hwif; struct scatterlist *sg = hwif->sg_table; + int i; ide_map_sg(drive, rq); @@ -136,8 +137,13 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq) else hwif->sg_dma_direction = DMA_TO_DEVICE; - return dma_map_sg(hwif->dev, sg, hwif->sg_nents, - hwif->sg_dma_direction); + i = dma_map_sg(hwif->dev, sg, hwif->sg_nents, hwif->sg_dma_direction); + if (i) { + hwif->orig_sg_nents = hwif->sg_nents; + hwif->sg_nents = i; + } + + return i; } EXPORT_SYMBOL_GPL(ide_build_sglist); @@ -156,7 +162,7 @@ void ide_destroy_dmatable(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; - dma_unmap_sg(hwif->dev, hwif->sg_table, hwif->sg_nents, + dma_unmap_sg(hwif->dev, hwif->sg_table, hwif->orig_sg_nents, hwif->sg_dma_direction); } EXPORT_SYMBOL_GPL(ide_destroy_dmatable); diff --git a/include/linux/ide.h b/include/linux/ide.h index e0cedfe9fad..25087aead65 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -797,6 +797,7 @@ typedef struct hwif_s { struct scatterlist *sg_table; int sg_max_nents; /* Maximum number of entries in it */ int sg_nents; /* Current number of entries in it */ + int orig_sg_nents; int sg_dma_direction; /* dma transfer direction */ /* data phase of the active command (currently only valid for PIO/DMA) */ -- GitLab From f474a37bc48667595b5653a983b635c95ed82a3b Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 5 Mar 2009 14:45:55 -0600 Subject: [PATCH 3368/4982] [SCSI] libiscsi: fix iscsi pool error path Memory freeing in iscsi_pool_free() looks wrong to me. Either q->pool can be NULL and this should be tested before dereferencing it, or it can't be NULL and it shouldn't be tested at all. As far as I can see, the only case where q->pool is NULL is on early error in iscsi_pool_init(). One possible way to fix the bug is thus to not call iscsi_pool_free() in this case (nothing needs to be freed anyway) and then we can get rid of the q->pool check. Signed-off-by: Jean Delvare Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 809d32d95c7..c33e28fd49b 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1944,7 +1944,7 @@ iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size) num_arrays++; q->pool = kzalloc(num_arrays * max * sizeof(void*), GFP_KERNEL); if (q->pool == NULL) - goto enomem; + return -ENOMEM; q->queue = kfifo_init((void*)q->pool, max * sizeof(void*), GFP_KERNEL, NULL); @@ -1979,8 +1979,7 @@ void iscsi_pool_free(struct iscsi_pool *q) for (i = 0; i < q->max; i++) kfree(q->pool[i]); - if (q->pool) - kfree(q->pool); + kfree(q->pool); kfree(q->queue); } EXPORT_SYMBOL_GPL(iscsi_pool_free); -- GitLab From 091e6dbec966d0727ae7fb2d5a8a2b8ace09a02e Mon Sep 17 00:00:00 2001 From: Pete Wyckoff Date: Thu, 5 Mar 2009 14:45:56 -0600 Subject: [PATCH 3369/4982] [SCSI] iscsi tcp: bidi capable Mark iscsi_tcp as being capable of bidirectional transfers. The bsg interface checks this bit before attempting any bidirectional commands. Signed-off-by: Pete Wyckoff Signed-off-by: Boaz Harrosh Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 23808dfe22b..5a08ca48fb3 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -813,6 +813,12 @@ static void iscsi_sw_tcp_session_destroy(struct iscsi_cls_session *cls_session) iscsi_host_free(shost); } +static int iscsi_sw_tcp_slave_alloc(struct scsi_device *sdev) +{ + set_bit(QUEUE_FLAG_BIDI, &sdev->request_queue->queue_flags); + return 0; +} + static int iscsi_sw_tcp_slave_configure(struct scsi_device *sdev) { blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_ANY); @@ -833,6 +839,7 @@ static struct scsi_host_template iscsi_sw_tcp_sht = { .eh_device_reset_handler= iscsi_eh_device_reset, .eh_target_reset_handler= iscsi_eh_target_reset, .use_clustering = DISABLE_CLUSTERING, + .slave_alloc = iscsi_sw_tcp_slave_alloc, .slave_configure = iscsi_sw_tcp_slave_configure, .proc_name = "iscsi_tcp", .this_id = -1, -- GitLab From 48a237a26db0a31404c83a88e984b37a30ddcf5a Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 5 Mar 2009 14:45:57 -0600 Subject: [PATCH 3370/4982] [SCSI] iser: have iser use its own logging iser has its own logging inrfastrucutre. Convert it to use it instead of libiscsi. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/infiniband/ulp/iser/iscsi_iser.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index 12876392516..4338f54c41f 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -168,7 +168,7 @@ iscsi_iser_mtask_xmit(struct iscsi_conn *conn, struct iscsi_task *task) { int error = 0; - debug_scsi("task deq [cid %d itt 0x%x]\n", conn->id, task->itt); + iser_dbg("task deq [cid %d itt 0x%x]\n", conn->id, task->itt); error = iser_send_control(conn, task); @@ -195,7 +195,7 @@ iscsi_iser_task_xmit_unsol_data(struct iscsi_conn *conn, /* Send data-out PDUs while there's still unsolicited data to send */ while (iscsi_task_has_unsol_data(task)) { iscsi_prep_data_out_pdu(task, r2t, &hdr); - debug_scsi("Sending data-out: itt 0x%x, data count %d\n", + iser_dbg("Sending data-out: itt 0x%x, data count %d\n", hdr.itt, r2t->data_count); /* the buffer description has been passed with the command */ @@ -206,7 +206,7 @@ iscsi_iser_task_xmit_unsol_data(struct iscsi_conn *conn, goto iscsi_iser_task_xmit_unsol_data_exit; } r2t->sent += r2t->data_count; - debug_scsi("Need to send %d more as data-out PDUs\n", + iser_dbg("Need to send %d more as data-out PDUs\n", r2t->data_length - r2t->sent); } @@ -227,12 +227,12 @@ iscsi_iser_task_xmit(struct iscsi_task *task) if (task->sc->sc_data_direction == DMA_TO_DEVICE) { BUG_ON(scsi_bufflen(task->sc) == 0); - debug_scsi("cmd [itt %x total %d imm %d unsol_data %d\n", + iser_dbg("cmd [itt %x total %d imm %d unsol_data %d\n", task->itt, scsi_bufflen(task->sc), task->imm_count, task->unsol_r2t.data_length); } - debug_scsi("task deq [cid %d itt 0x%x]\n", + iser_dbg("task deq [cid %d itt 0x%x]\n", conn->id, task->itt); /* Send the cmd PDU */ -- GitLab From 1b2c7af877f427a2b25583c9033616c9ebd30aed Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 5 Mar 2009 14:45:58 -0600 Subject: [PATCH 3371/4982] [SCSI] libiscsi: replace scsi_debug logging with session/conn logging This makes the logging a compile time option and replaces the scsi_debug macro with session and connection ones that print out a driver model id prefix. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 164 +++++++++++++++++++++++++--------------- include/scsi/libiscsi.h | 7 -- 2 files changed, 103 insertions(+), 68 deletions(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index c33e28fd49b..701457cca08 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -38,6 +38,28 @@ #include #include +static int iscsi_dbg_lib; +module_param_named(debug_libiscsi, iscsi_dbg_lib, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug_libiscsi, "Turn on debugging for libiscsi module. " + "Set to 1 to turn on, and zero to turn off. Default " + "is off."); + +#define ISCSI_DBG_CONN(_conn, dbg_fmt, arg...) \ + do { \ + if (iscsi_dbg_lib) \ + iscsi_conn_printk(KERN_INFO, _conn, \ + "%s " dbg_fmt, \ + __func__, ##arg); \ + } while (0); + +#define ISCSI_DBG_SESSION(_session, dbg_fmt, arg...) \ + do { \ + if (iscsi_dbg_lib) \ + iscsi_session_printk(KERN_INFO, _session, \ + "%s " dbg_fmt, \ + __func__, ##arg); \ + } while (0); + /* Serial Number Arithmetic, 32 bits, less than, RFC1982 */ #define SNA32_CHECK 2147483648UL @@ -176,10 +198,11 @@ static int iscsi_prep_ecdb_ahs(struct iscsi_task *task) ecdb_ahdr->reserved = 0; memcpy(ecdb_ahdr->ecdb, cmd->cmnd + ISCSI_CDB_SIZE, rlen); - debug_scsi("iscsi_prep_ecdb_ahs: varlen_cdb_len %d " - "rlen %d pad_len %d ahs_length %d iscsi_headers_size %u\n", - cmd->cmd_len, rlen, pad_len, ahslength, task->hdr_len); - + ISCSI_DBG_SESSION(task->conn->session, + "iscsi_prep_ecdb_ahs: varlen_cdb_len %d " + "rlen %d pad_len %d ahs_length %d iscsi_headers_size " + "%u\n", cmd->cmd_len, rlen, pad_len, ahslength, + task->hdr_len); return 0; } @@ -201,10 +224,11 @@ static int iscsi_prep_bidi_ahs(struct iscsi_task *task) rlen_ahdr->reserved = 0; rlen_ahdr->read_length = cpu_to_be32(scsi_in(sc)->length); - debug_scsi("bidi-in rlen_ahdr->read_length(%d) " - "rlen_ahdr->ahslength(%d)\n", - be32_to_cpu(rlen_ahdr->read_length), - be16_to_cpu(rlen_ahdr->ahslength)); + ISCSI_DBG_SESSION(task->conn->session, + "bidi-in rlen_ahdr->read_length(%d) " + "rlen_ahdr->ahslength(%d)\n", + be32_to_cpu(rlen_ahdr->read_length), + be16_to_cpu(rlen_ahdr->ahslength)); return 0; } @@ -335,13 +359,15 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) list_move_tail(&task->running, &conn->run_list); conn->scsicmd_pdus_cnt++; - debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d " - "bidi_len %d cmdsn %d win %d]\n", scsi_bidi_cmnd(sc) ? - "bidirectional" : sc->sc_data_direction == DMA_TO_DEVICE ? - "write" : "read", conn->id, sc, sc->cmnd[0], task->itt, - scsi_bufflen(sc), - scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0, - session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); + ISCSI_DBG_SESSION(session, "iscsi prep [%s cid %d sc %p cdb 0x%x " + "itt 0x%x len %d bidi_len %d cmdsn %d win %d]\n", + scsi_bidi_cmnd(sc) ? "bidirectional" : + sc->sc_data_direction == DMA_TO_DEVICE ? + "write" : "read", conn->id, sc, sc->cmnd[0], + task->itt, scsi_bufflen(sc), + scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0, + session->cmdsn, + session->max_cmdsn - session->exp_cmdsn + 1); return 0; } @@ -483,9 +509,9 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, task->state = ISCSI_TASK_RUNNING; list_move_tail(&task->running, &conn->mgmt_run_list); - debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n", - hdr->opcode & ISCSI_OPCODE_MASK, hdr->itt, - task->data_count); + ISCSI_DBG_SESSION(session, "mgmtpdu [op 0x%x hdr->itt 0x%x " + "datalen %d]\n", hdr->opcode & ISCSI_OPCODE_MASK, + hdr->itt, task->data_count); return 0; } @@ -637,8 +663,9 @@ invalid_datalen: memcpy(sc->sense_buffer, data + 2, min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE)); - debug_scsi("copied %d bytes of sense\n", - min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE)); + ISCSI_DBG_SESSION(session, "copied %d bytes of sense\n", + min_t(uint16_t, senselen, + SCSI_SENSE_BUFFERSIZE)); } if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW | @@ -666,8 +693,8 @@ invalid_datalen: sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; } out: - debug_scsi("done [sc %lx res %d itt 0x%x]\n", - (long)sc, sc->result, task->itt); + ISCSI_DBG_SESSION(session, "done [sc %p res %d itt 0x%x]\n", + sc, sc->result, task->itt); conn->scsirsp_pdus_cnt++; __iscsi_put_task(task); @@ -835,8 +862,8 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, else itt = ~0U; - debug_scsi("[op 0x%x cid %d itt 0x%x len %d]\n", - opcode, conn->id, itt, datalen); + ISCSI_DBG_SESSION(session, "[op 0x%x cid %d itt 0x%x len %d]\n", + opcode, conn->id, itt, datalen); if (itt == ~0U) { iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); @@ -1095,10 +1122,10 @@ static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn) * Check for iSCSI window and take care of CmdSN wrap-around */ if (!iscsi_sna_lte(session->queued_cmdsn, session->max_cmdsn)) { - debug_scsi("iSCSI CmdSN closed. ExpCmdSn %u MaxCmdSN %u " - "CmdSN %u/%u\n", session->exp_cmdsn, - session->max_cmdsn, session->cmdsn, - session->queued_cmdsn); + ISCSI_DBG_SESSION(session, "iSCSI CmdSN closed. ExpCmdSn " + "%u MaxCmdSN %u CmdSN %u/%u\n", + session->exp_cmdsn, session->max_cmdsn, + session->cmdsn, session->queued_cmdsn); return -ENOSPC; } return 0; @@ -1152,7 +1179,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) spin_lock_bh(&conn->session->lock); if (unlikely(conn->suspend_tx)) { - debug_scsi("conn %d Tx suspended!\n", conn->id); + ISCSI_DBG_SESSION(conn->session, "Tx suspended!\n"); spin_unlock_bh(&conn->session->lock); return -ENODATA; } @@ -1398,7 +1425,8 @@ prepd_reject: iscsi_complete_command(task); reject: spin_unlock(&session->lock); - debug_scsi("cmd 0x%x rejected (%d)\n", sc->cmnd[0], reason); + ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n", + sc->cmnd[0], reason); spin_lock(host->host_lock); return SCSI_MLQUEUE_TARGET_BUSY; @@ -1407,7 +1435,8 @@ prepd_fault: iscsi_complete_command(task); fault: spin_unlock(&session->lock); - debug_scsi("iscsi: cmd 0x%x is not queued (%d)\n", sc->cmnd[0], reason); + ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n", + sc->cmnd[0], reason); if (!scsi_bidi_cmnd(sc)) scsi_set_resid(sc, scsi_bufflen(sc)); else { @@ -1457,8 +1486,10 @@ int iscsi_eh_target_reset(struct scsi_cmnd *sc) spin_lock_bh(&session->lock); if (session->state == ISCSI_STATE_TERMINATE) { failed: - debug_scsi("failing target reset: session terminated " - "[CID %d age %d]\n", conn->id, session->age); + iscsi_session_printk(KERN_INFO, session, + "failing target reset: Could not log " + "back into target [age %d]\n", + session->age); spin_unlock_bh(&session->lock); mutex_unlock(&session->eh_mutex); return FAILED; @@ -1472,7 +1503,7 @@ failed: */ iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); - debug_scsi("iscsi_eh_target_reset wait for relogin\n"); + ISCSI_DBG_SESSION(session, "wait for relogin\n"); wait_event_interruptible(conn->ehwait, session->state == ISCSI_STATE_TERMINATE || session->state == ISCSI_STATE_LOGGED_IN || @@ -1501,7 +1532,7 @@ static void iscsi_tmf_timedout(unsigned long data) spin_lock(&session->lock); if (conn->tmf_state == TMF_QUEUED) { conn->tmf_state = TMF_TIMEDOUT; - debug_scsi("tmf timedout\n"); + ISCSI_DBG_SESSION(session, "tmf timedout\n"); /* unblock eh_abort() */ wake_up(&conn->ehwait); } @@ -1521,7 +1552,7 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, spin_unlock_bh(&session->lock); iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); spin_lock_bh(&session->lock); - debug_scsi("tmf exec failure\n"); + ISCSI_DBG_SESSION(session, "tmf exec failure\n"); return -EPERM; } conn->tmfcmd_pdus_cnt++; @@ -1529,7 +1560,7 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, conn->tmf_timer.function = iscsi_tmf_timedout; conn->tmf_timer.data = (unsigned long)conn; add_timer(&conn->tmf_timer); - debug_scsi("tmf set timeout\n"); + ISCSI_DBG_SESSION(session, "tmf set timeout\n"); spin_unlock_bh(&session->lock); mutex_unlock(&session->eh_mutex); @@ -1573,16 +1604,18 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun, /* flush pending */ list_for_each_entry_safe(task, tmp, &conn->xmitqueue, running) { if (lun == task->sc->device->lun || lun == -1) { - debug_scsi("failing pending sc %p itt 0x%x\n", - task->sc, task->itt); + ISCSI_DBG_SESSION(conn->session, + "failing pending sc %p itt 0x%x\n", + task->sc, task->itt); fail_command(conn, task, error << 16); } } list_for_each_entry_safe(task, tmp, &conn->requeue, running) { if (lun == task->sc->device->lun || lun == -1) { - debug_scsi("failing requeued sc %p itt 0x%x\n", - task->sc, task->itt); + ISCSI_DBG_SESSION(conn->session, + "failing requeued sc %p itt 0x%x\n", + task->sc, task->itt); fail_command(conn, task, error << 16); } } @@ -1590,8 +1623,9 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun, /* fail all other running */ list_for_each_entry_safe(task, tmp, &conn->run_list, running) { if (lun == task->sc->device->lun || lun == -1) { - debug_scsi("failing in progress sc %p itt 0x%x\n", - task->sc, task->itt); + ISCSI_DBG_SESSION(conn->session, + "failing in progress sc %p itt 0x%x\n", + task->sc, task->itt); fail_command(conn, task, error << 16); } } @@ -1622,7 +1656,7 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) cls_session = starget_to_session(scsi_target(scmd->device)); session = cls_session->dd_data; - debug_scsi("scsi cmd %p timedout\n", scmd); + ISCSI_DBG_SESSION(session, "scsi cmd %p timedout\n", scmd); spin_lock(&session->lock); if (session->state != ISCSI_STATE_LOGGED_IN) { @@ -1662,8 +1696,8 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) rc = BLK_EH_RESET_TIMER; done: spin_unlock(&session->lock); - debug_scsi("return %s\n", rc == BLK_EH_RESET_TIMER ? - "timer reset" : "nh"); + ISCSI_DBG_SESSION(session, "return %s\n", rc == BLK_EH_RESET_TIMER ? + "timer reset" : "nh"); return rc; } @@ -1697,13 +1731,13 @@ static void iscsi_check_transport_timeouts(unsigned long data) if (time_before_eq(last_recv + recv_timeout, jiffies)) { /* send a ping to try to provoke some traffic */ - debug_scsi("Sending nopout as ping on conn %p\n", conn); + ISCSI_DBG_CONN(conn, "Sending nopout as ping\n"); iscsi_send_nopout(conn, NULL); next_timeout = conn->last_ping + (conn->ping_timeout * HZ); } else next_timeout = last_recv + recv_timeout; - debug_scsi("Setting next tmo %lu\n", next_timeout); + ISCSI_DBG_CONN(conn, "Setting next tmo %lu\n", next_timeout); mod_timer(&conn->transport_timer, next_timeout); done: spin_unlock(&session->lock); @@ -1740,7 +1774,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) * got the command. */ if (!sc->SCp.ptr) { - debug_scsi("sc never reached iscsi layer or it completed.\n"); + ISCSI_DBG_SESSION(session, "sc never reached iscsi layer or " + "it completed.\n"); spin_unlock_bh(&session->lock); mutex_unlock(&session->eh_mutex); return SUCCESS; @@ -1762,11 +1797,13 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) age = session->age; task = (struct iscsi_task *)sc->SCp.ptr; - debug_scsi("aborting [sc %p itt 0x%x]\n", sc, task->itt); + ISCSI_DBG_SESSION(session, "aborting [sc %p itt 0x%x]\n", + sc, task->itt); /* task completed before time out */ if (!task->sc) { - debug_scsi("sc completed while abort in progress\n"); + ISCSI_DBG_SESSION(session, "sc completed while abort in " + "progress\n"); goto success; } @@ -1815,7 +1852,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) if (!sc->SCp.ptr) { conn->tmf_state = TMF_INITIAL; /* task completed before tmf abort response */ - debug_scsi("sc completed while abort in progress\n"); + ISCSI_DBG_SESSION(session, "sc completed while abort " + "in progress\n"); goto success; } /* fall through */ @@ -1827,15 +1865,16 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) success: spin_unlock_bh(&session->lock); success_unlocked: - debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, task->itt); + ISCSI_DBG_SESSION(session, "abort success [sc %p itt 0x%x]\n", + sc, task->itt); mutex_unlock(&session->eh_mutex); return SUCCESS; failed: spin_unlock_bh(&session->lock); failed_unlocked: - debug_scsi("abort failed [sc %p itt 0x%x]\n", sc, - task ? task->itt : 0); + ISCSI_DBG_SESSION(session, "abort failed [sc %p itt 0x%x]\n", sc, + task ? task->itt : 0); mutex_unlock(&session->eh_mutex); return FAILED; } @@ -1862,7 +1901,8 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) cls_session = starget_to_session(scsi_target(sc->device)); session = cls_session->dd_data; - debug_scsi("LU Reset [sc %p lun %u]\n", sc, sc->device->lun); + ISCSI_DBG_SESSION(session, "LU Reset [sc %p lun %u]\n", + sc, sc->device->lun); mutex_lock(&session->eh_mutex); spin_lock_bh(&session->lock); @@ -1916,8 +1956,8 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) unlock: spin_unlock_bh(&session->lock); done: - debug_scsi("iscsi_eh_device_reset %s\n", - rc == SUCCESS ? "SUCCESS" : "FAILED"); + ISCSI_DBG_SESSION(session, "dev reset result = %s\n", + rc == SUCCESS ? "SUCCESS" : "FAILED"); mutex_unlock(&session->eh_mutex); return rc; } @@ -2466,14 +2506,16 @@ flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn) /* handle pending */ list_for_each_entry_safe(task, tmp, &conn->mgmtqueue, running) { - debug_scsi("flushing pending mgmt task itt 0x%x\n", task->itt); + ISCSI_DBG_SESSION(session, "flushing pending mgmt task " + "itt 0x%x\n", task->itt); /* release ref from prep task */ __iscsi_put_task(task); } /* handle running */ list_for_each_entry_safe(task, tmp, &conn->mgmt_run_list, running) { - debug_scsi("flushing running mgmt task itt 0x%x\n", task->itt); + ISCSI_DBG_SESSION(session, "flushing running mgmt task " + "itt 0x%x\n", task->itt); /* release ref from prep task */ __iscsi_put_task(task); } @@ -2523,7 +2565,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, conn->datadgst_en = 0; if (session->state == ISCSI_STATE_IN_RECOVERY && old_stop_stage != STOP_CONN_RECOVER) { - debug_scsi("blocking session\n"); + ISCSI_DBG_SESSION(session, "blocking session\n"); iscsi_block_session(session->cls_session); } } diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 7360e1916e7..67542aa3aed 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -45,13 +45,6 @@ struct iscsi_session; struct iscsi_nopin; struct device; -/* #define DEBUG_SCSI */ -#ifdef DEBUG_SCSI -#define debug_scsi(fmt...) printk(KERN_INFO "iscsi: " fmt) -#else -#define debug_scsi(fmt...) -#endif - #define ISCSI_DEF_XMIT_CMDS_MAX 128 /* must be power of 2 */ #define ISCSI_MGMT_CMDS_MAX 15 -- GitLab From 0ab1c2529e6a70e1b3c63fe9c6b41d4049758a8e Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 5 Mar 2009 14:45:59 -0600 Subject: [PATCH 3372/4982] [SCSI] libiscsi_tcp: replace tcp_debug/scsi_debug logging with session/conn logging This makes the logging a compile time option and replaces the scsi_debug and tcp_debug macro with session and connection ones that print out a driver model id prefix. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi_tcp.c | 122 ++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 60 deletions(-) diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c index e7705d3532c..91f8ce4d8d0 100644 --- a/drivers/scsi/libiscsi_tcp.c +++ b/drivers/scsi/libiscsi_tcp.c @@ -49,13 +49,21 @@ MODULE_AUTHOR("Mike Christie , " "Alex Aizman "); MODULE_DESCRIPTION("iSCSI/TCP data-path"); MODULE_LICENSE("GPL"); -#undef DEBUG_TCP -#ifdef DEBUG_TCP -#define debug_tcp(fmt...) printk(KERN_INFO "tcp: " fmt) -#else -#define debug_tcp(fmt...) -#endif +static int iscsi_dbg_libtcp; +module_param_named(debug_libiscsi_tcp, iscsi_dbg_libtcp, int, + S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug_libiscsi_tcp, "Turn on debugging for libiscsi_tcp " + "module. Set to 1 to turn on, and zero to turn off. Default " + "is off."); + +#define ISCSI_DBG_TCP(_conn, dbg_fmt, arg...) \ + do { \ + if (iscsi_dbg_libtcp) \ + iscsi_conn_printk(KERN_INFO, _conn, \ + "%s " dbg_fmt, \ + __func__, ##arg); \ + } while (0); static int iscsi_tcp_hdr_recv_done(struct iscsi_tcp_conn *tcp_conn, struct iscsi_segment *segment); @@ -123,18 +131,13 @@ static void iscsi_tcp_segment_map(struct iscsi_segment *segment, int recv) if (page_count(sg_page(sg)) >= 1 && !recv) return; - debug_tcp("iscsi_tcp_segment_map %s %p\n", recv ? "recv" : "xmit", - segment); segment->sg_mapped = kmap_atomic(sg_page(sg), KM_SOFTIRQ0); segment->data = segment->sg_mapped + sg->offset + segment->sg_offset; } void iscsi_tcp_segment_unmap(struct iscsi_segment *segment) { - debug_tcp("iscsi_tcp_segment_unmap %p\n", segment); - if (segment->sg_mapped) { - debug_tcp("iscsi_tcp_segment_unmap valid\n"); kunmap_atomic(segment->sg_mapped, KM_SOFTIRQ0); segment->sg_mapped = NULL; segment->data = NULL; @@ -180,8 +183,9 @@ int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn, struct scatterlist sg; unsigned int pad; - debug_tcp("copied %u %u size %u %s\n", segment->copied, copied, - segment->size, recv ? "recv" : "xmit"); + ISCSI_DBG_TCP(tcp_conn->iscsi_conn, "copied %u %u size %u %s\n", + segment->copied, copied, segment->size, + recv ? "recv" : "xmit"); if (segment->hash && copied) { /* * If a segment is kmapd we must unmap it before sending @@ -214,8 +218,8 @@ int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn, iscsi_tcp_segment_unmap(segment); /* Do we have more scatterlist entries? */ - debug_tcp("total copied %u total size %u\n", segment->total_copied, - segment->total_size); + ISCSI_DBG_TCP(tcp_conn->iscsi_conn, "total copied %u total size %u\n", + segment->total_copied, segment->total_size); if (segment->total_copied < segment->total_size) { /* Proceed to the next entry in the scatterlist. */ iscsi_tcp_segment_init_sg(segment, sg_next(segment->sg), @@ -229,7 +233,8 @@ int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn, if (!(tcp_conn->iscsi_conn->session->tt->caps & CAP_PADDING_OFFLOAD)) { pad = iscsi_padding(segment->total_copied); if (pad != 0) { - debug_tcp("consume %d pad bytes\n", pad); + ISCSI_DBG_TCP(tcp_conn->iscsi_conn, + "consume %d pad bytes\n", pad); segment->total_size += pad; segment->size = pad; segment->data = segment->padbuf; @@ -278,13 +283,13 @@ iscsi_tcp_segment_recv(struct iscsi_tcp_conn *tcp_conn, while (!iscsi_tcp_segment_done(tcp_conn, segment, 1, copy)) { if (copied == len) { - debug_tcp("iscsi_tcp_segment_recv copied %d bytes\n", - len); + ISCSI_DBG_TCP(tcp_conn->iscsi_conn, + "copied %d bytes\n", len); break; } copy = min(len - copied, segment->size - segment->copied); - debug_tcp("iscsi_tcp_segment_recv copying %d\n", copy); + ISCSI_DBG_TCP(tcp_conn->iscsi_conn, "copying %d\n", copy); memcpy(segment->data + segment->copied, ptr + copied, copy); copied += copy; } @@ -311,7 +316,7 @@ iscsi_tcp_dgst_verify(struct iscsi_tcp_conn *tcp_conn, if (memcmp(segment->recv_digest, segment->digest, segment->digest_len)) { - debug_scsi("digest mismatch\n"); + ISCSI_DBG_TCP(tcp_conn->iscsi_conn, "digest mismatch\n"); return 0; } @@ -355,12 +360,8 @@ iscsi_segment_seek_sg(struct iscsi_segment *segment, struct scatterlist *sg; unsigned int i; - debug_scsi("iscsi_segment_seek_sg offset %u size %llu\n", - offset, size); __iscsi_segment_init(segment, size, done, hash); for_each_sg(sg_list, sg, sg_count, i) { - debug_scsi("sg %d, len %u offset %u\n", i, sg->length, - sg->offset); if (offset < sg->length) { iscsi_tcp_segment_init_sg(segment, sg, offset); return 0; @@ -382,8 +383,9 @@ EXPORT_SYMBOL_GPL(iscsi_segment_seek_sg); */ void iscsi_tcp_hdr_recv_prep(struct iscsi_tcp_conn *tcp_conn) { - debug_tcp("iscsi_tcp_hdr_recv_prep(%p%s)\n", tcp_conn, - tcp_conn->iscsi_conn->hdrdgst_en ? ", digest enabled" : ""); + ISCSI_DBG_TCP(tcp_conn->iscsi_conn, + "(%s)\n", tcp_conn->iscsi_conn->hdrdgst_en ? + "digest enabled" : "digest disabled"); iscsi_segment_init_linear(&tcp_conn->in.segment, tcp_conn->in.hdr_buf, sizeof(struct iscsi_hdr), iscsi_tcp_hdr_recv_done, NULL); @@ -446,7 +448,7 @@ void iscsi_tcp_cleanup_task(struct iscsi_task *task) while (__kfifo_get(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*))) { __kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); - debug_scsi("iscsi_tcp_cleanup_task pending r2t dropped\n"); + ISCSI_DBG_TCP(task->conn, "pending r2t dropped\n"); } r2t = tcp_task->r2t; @@ -476,8 +478,8 @@ static int iscsi_tcp_data_in(struct iscsi_conn *conn, struct iscsi_task *task) return 0; if (tcp_task->exp_datasn != datasn) { - debug_tcp("%s: task->exp_datasn(%d) != rhdr->datasn(%d)\n", - __func__, tcp_task->exp_datasn, datasn); + ISCSI_DBG_TCP(conn, "task->exp_datasn(%d) != rhdr->datasn(%d)" + "\n", tcp_task->exp_datasn, datasn); return ISCSI_ERR_DATASN; } @@ -485,9 +487,9 @@ static int iscsi_tcp_data_in(struct iscsi_conn *conn, struct iscsi_task *task) tcp_task->data_offset = be32_to_cpu(rhdr->offset); if (tcp_task->data_offset + tcp_conn->in.datalen > total_in_length) { - debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n", - __func__, tcp_task->data_offset, - tcp_conn->in.datalen, total_in_length); + ISCSI_DBG_TCP(conn, "data_offset(%d) + data_len(%d) > " + "total_length_in(%d)\n", tcp_task->data_offset, + tcp_conn->in.datalen, total_in_length); return ISCSI_ERR_DATA_OFFSET; } @@ -518,8 +520,8 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) } if (tcp_task->exp_datasn != r2tsn){ - debug_tcp("%s: task->exp_datasn(%d) != rhdr->r2tsn(%d)\n", - __func__, tcp_task->exp_datasn, r2tsn); + ISCSI_DBG_TCP(conn, "task->exp_datasn(%d) != rhdr->r2tsn(%d)\n", + tcp_task->exp_datasn, r2tsn); return ISCSI_ERR_R2TSN; } @@ -552,9 +554,9 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) } if (r2t->data_length > session->max_burst) - debug_scsi("invalid R2T with data len %u and max burst %u." - "Attempting to execute request.\n", - r2t->data_length, session->max_burst); + ISCSI_DBG_TCP(conn, "invalid R2T with data len %u and max " + "burst %u. Attempting to execute request.\n", + r2t->data_length, session->max_burst); r2t->data_offset = be32_to_cpu(rhdr->data_offset); if (r2t->data_offset + r2t->data_length > scsi_out(task->sc)->length) { @@ -641,8 +643,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) if (rc) return rc; - debug_tcp("opcode 0x%x ahslen %d datalen %d\n", - opcode, ahslen, tcp_conn->in.datalen); + ISCSI_DBG_TCP(conn, "opcode 0x%x ahslen %d datalen %d\n", + opcode, ahslen, tcp_conn->in.datalen); switch(opcode) { case ISCSI_OP_SCSI_DATA_IN: @@ -674,10 +676,10 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) !(conn->session->tt->caps & CAP_DIGEST_OFFLOAD)) rx_hash = tcp_conn->rx_hash; - debug_tcp("iscsi_tcp_begin_data_in(%p, offset=%d, " - "datalen=%d)\n", tcp_conn, - tcp_task->data_offset, - tcp_conn->in.datalen); + ISCSI_DBG_TCP(conn, "iscsi_tcp_begin_data_in( " + "offset=%d, datalen=%d)\n", + tcp_task->data_offset, + tcp_conn->in.datalen); rc = iscsi_segment_seek_sg(&tcp_conn->in.segment, sdb->table.sgl, sdb->table.nents, @@ -854,10 +856,10 @@ int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb, unsigned int consumed = 0; int rc = 0; - debug_tcp("in %d bytes\n", skb->len - offset); + ISCSI_DBG_TCP(conn, "in %d bytes\n", skb->len - offset); if (unlikely(conn->suspend_rx)) { - debug_tcp("conn %d Rx suspended!\n", conn->id); + ISCSI_DBG_TCP(conn, "Rx suspended!\n"); *status = ISCSI_TCP_SUSPENDED; return 0; } @@ -874,15 +876,16 @@ int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb, avail = skb_seq_read(consumed, &ptr, &seq); if (avail == 0) { - debug_tcp("no more data avail. Consumed %d\n", - consumed); + ISCSI_DBG_TCP(conn, "no more data avail. Consumed %d\n", + consumed); *status = ISCSI_TCP_SKB_DONE; skb_abort_seq_read(&seq); goto skb_done; } BUG_ON(segment->copied >= segment->size); - debug_tcp("skb %p ptr=%p avail=%u\n", skb, ptr, avail); + ISCSI_DBG_TCP(conn, "skb %p ptr=%p avail=%u\n", skb, ptr, + avail); rc = iscsi_tcp_segment_recv(tcp_conn, segment, ptr, avail); BUG_ON(rc == 0); consumed += rc; @@ -895,11 +898,11 @@ int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb, segment_done: *status = ISCSI_TCP_SEGMENT_DONE; - debug_tcp("segment done\n"); + ISCSI_DBG_TCP(conn, "segment done\n"); rc = segment->done(tcp_conn, segment); if (rc != 0) { *status = ISCSI_TCP_CONN_ERR; - debug_tcp("Error receiving PDU, errno=%d\n", rc); + ISCSI_DBG_TCP(conn, "Error receiving PDU, errno=%d\n", rc); iscsi_conn_failure(conn, rc); return 0; } @@ -929,8 +932,7 @@ int iscsi_tcp_task_init(struct iscsi_task *task) * mgmt tasks do not have a scatterlist since they come * in from the iscsi interface. */ - debug_scsi("mtask deq [cid %d itt 0x%x]\n", conn->id, - task->itt); + ISCSI_DBG_TCP(conn, "mtask deq [itt 0x%x]\n", task->itt); return conn->session->tt->init_pdu(task, 0, task->data_count); } @@ -939,9 +941,8 @@ int iscsi_tcp_task_init(struct iscsi_task *task) tcp_task->exp_datasn = 0; /* Prepare PDU, optionally w/ immediate data */ - debug_scsi("task deq [cid %d itt 0x%x imm %d unsol %d]\n", - conn->id, task->itt, task->imm_count, - task->unsol_r2t.data_length); + ISCSI_DBG_TCP(conn, "task deq [itt 0x%x imm %d unsol %d]\n", + task->itt, task->imm_count, task->unsol_r2t.data_length); err = conn->session->tt->init_pdu(task, 0, task->imm_count); if (err) @@ -965,7 +966,8 @@ static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task) r2t = tcp_task->r2t; /* Continue with this R2T? */ if (r2t->data_length <= r2t->sent) { - debug_scsi(" done with r2t %p\n", r2t); + ISCSI_DBG_TCP(task->conn, + " done with r2t %p\n", r2t); __kfifo_put(tcp_task->r2tpool.queue, (void *)&tcp_task->r2t, sizeof(void *)); @@ -1019,7 +1021,7 @@ flush: r2t = iscsi_tcp_get_curr_r2t(task); if (r2t == NULL) { /* Waiting for more R2Ts to arrive. */ - debug_tcp("no R2Ts yet\n"); + ISCSI_DBG_TCP(conn, "no R2Ts yet\n"); return 0; } @@ -1028,9 +1030,9 @@ flush: return rc; iscsi_prep_data_out_pdu(task, r2t, (struct iscsi_data *) task->hdr); - debug_scsi("sol dout %p [dsn %d itt 0x%x doff %d dlen %d]\n", - r2t, r2t->datasn - 1, task->hdr->itt, - r2t->data_offset + r2t->sent, r2t->data_count); + ISCSI_DBG_TCP(conn, "sol dout %p [dsn %d itt 0x%x doff %d dlen %d]\n", + r2t, r2t->datasn - 1, task->hdr->itt, + r2t->data_offset + r2t->sent, r2t->data_count); rc = conn->session->tt->init_pdu(task, r2t->data_offset + r2t->sent, r2t->data_count); -- GitLab From c93f87c727ad4e6a5d94cfab219b1492ccc5ca5e Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 5 Mar 2009 14:46:00 -0600 Subject: [PATCH 3373/4982] [SCSI] iscsi_tcp: replace scsi_debug/tcp_debug logging with iscsi conn logging This makes the logging a compile time option and replaces the tcp_debug macro with a iscsi connection one that prints out a driver model id prefix. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 57 ++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 5a08ca48fb3..9c2e52792bd 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -48,13 +48,6 @@ MODULE_AUTHOR("Mike Christie , " "Alex Aizman "); MODULE_DESCRIPTION("iSCSI/TCP data-path"); MODULE_LICENSE("GPL"); -#undef DEBUG_TCP - -#ifdef DEBUG_TCP -#define debug_tcp(fmt...) printk(KERN_INFO "tcp: " fmt) -#else -#define debug_tcp(fmt...) -#endif static struct scsi_transport_template *iscsi_sw_tcp_scsi_transport; static struct scsi_host_template iscsi_sw_tcp_sht; @@ -63,6 +56,21 @@ static struct iscsi_transport iscsi_sw_tcp_transport; static unsigned int iscsi_max_lun = 512; module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO); +static int iscsi_sw_tcp_dbg; +module_param_named(debug_iscsi_tcp, iscsi_sw_tcp_dbg, int, + S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug_iscsi_tcp, "Turn on debugging for iscsi_tcp module " + "Set to 1 to turn on, and zero to turn off. Default is off."); + +#define ISCSI_SW_TCP_DBG(_conn, dbg_fmt, arg...) \ + do { \ + if (iscsi_sw_tcp_dbg) \ + iscsi_conn_printk(KERN_INFO, _conn, \ + "%s " dbg_fmt, \ + __func__, ##arg); \ + } while (0); + + /** * iscsi_sw_tcp_recv - TCP receive in sendfile fashion * @rd_desc: read descriptor @@ -77,7 +85,7 @@ static int iscsi_sw_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, unsigned int consumed, total_consumed = 0; int status; - debug_tcp("in %d bytes\n", skb->len - offset); + ISCSI_SW_TCP_DBG(conn, "in %d bytes\n", skb->len - offset); do { status = 0; @@ -86,7 +94,8 @@ static int iscsi_sw_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, total_consumed += consumed; } while (consumed != 0 && status != ISCSI_TCP_SKB_DONE); - debug_tcp("read %d bytes status %d\n", skb->len - offset, status); + ISCSI_SW_TCP_DBG(conn, "read %d bytes status %d\n", + skb->len - offset, status); return total_consumed; } @@ -131,7 +140,8 @@ static void iscsi_sw_tcp_state_change(struct sock *sk) if ((sk->sk_state == TCP_CLOSE_WAIT || sk->sk_state == TCP_CLOSE) && !atomic_read(&sk->sk_rmem_alloc)) { - debug_tcp("iscsi_tcp_state_change: TCP_CLOSE|TCP_CLOSE_WAIT\n"); + ISCSI_SW_TCP_DBG(conn, "iscsi_tcp_state_change: " + "TCP_CLOSE|TCP_CLOSE_WAIT\n"); iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); } @@ -155,7 +165,7 @@ static void iscsi_sw_tcp_write_space(struct sock *sk) struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; tcp_sw_conn->old_write_space(sk); - debug_tcp("iscsi_write_space: cid %d\n", conn->id); + ISCSI_SW_TCP_DBG(conn, "iscsi_write_space\n"); scsi_queue_work(conn->session->host, &conn->xmitwork); } @@ -283,7 +293,7 @@ static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn) } } - debug_tcp("xmit %d bytes\n", consumed); + ISCSI_SW_TCP_DBG(conn, "xmit %d bytes\n", consumed); conn->txdata_octets += consumed; return consumed; @@ -291,7 +301,7 @@ static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn) error: /* Transmit error. We could initiate error recovery * here. */ - debug_tcp("Error sending PDU, errno=%d\n", rc); + ISCSI_SW_TCP_DBG(conn, "Error sending PDU, errno=%d\n", rc); iscsi_conn_failure(conn, rc); return -EIO; } @@ -334,9 +344,10 @@ static int iscsi_sw_tcp_send_hdr_done(struct iscsi_tcp_conn *tcp_conn, struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; tcp_sw_conn->out.segment = tcp_sw_conn->out.data_segment; - debug_tcp("Header done. Next segment size %u total_size %u\n", - tcp_sw_conn->out.segment.size, - tcp_sw_conn->out.segment.total_size); + ISCSI_SW_TCP_DBG(tcp_conn->iscsi_conn, + "Header done. Next segment size %u total_size %u\n", + tcp_sw_conn->out.segment.size, + tcp_sw_conn->out.segment.total_size); return 0; } @@ -346,8 +357,8 @@ static void iscsi_sw_tcp_send_hdr_prep(struct iscsi_conn *conn, void *hdr, struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; - debug_tcp("%s(%p%s)\n", __func__, tcp_conn, - conn->hdrdgst_en? ", digest enabled" : ""); + ISCSI_SW_TCP_DBG(conn, "%s\n", conn->hdrdgst_en ? + "digest enabled" : "digest disabled"); /* Clear the data segment - needs to be filled in by the * caller using iscsi_tcp_send_data_prep() */ @@ -389,9 +400,9 @@ iscsi_sw_tcp_send_data_prep(struct iscsi_conn *conn, struct scatterlist *sg, struct hash_desc *tx_hash = NULL; unsigned int hdr_spec_len; - debug_tcp("%s(%p, offset=%d, datalen=%d%s)\n", __func__, - tcp_conn, offset, len, - conn->datadgst_en? ", digest enabled" : ""); + ISCSI_SW_TCP_DBG(conn, "offset=%d, datalen=%d %s\n", offset, len, + conn->datadgst_en ? + "digest enabled" : "digest disabled"); /* Make sure the datalen matches what the caller said he would send. */ @@ -415,8 +426,8 @@ iscsi_sw_tcp_send_linear_data_prep(struct iscsi_conn *conn, void *data, struct hash_desc *tx_hash = NULL; unsigned int hdr_spec_len; - debug_tcp("%s(%p, datalen=%d%s)\n", __func__, tcp_conn, len, - conn->datadgst_en? ", digest enabled" : ""); + ISCSI_SW_TCP_DBG(conn, "datalen=%zd %s\n", len, conn->datadgst_en ? + "digest enabled" : "digest disabled"); /* Make sure the datalen matches what the caller said he would send. */ -- GitLab From e28f3d5b51ed07d822f135cd941b01e2d485270e Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 5 Mar 2009 14:46:01 -0600 Subject: [PATCH 3374/4982] [SCSI] libiscsi: don't cap queue depth in iscsi modules There is no need to cap the queue depth in the modules. We set this in userspace and can do that there. For performance testing with ram based targets, this is helpful since we can have very high queue depths. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/infiniband/ulp/iser/iscsi_iser.c | 4 ++-- drivers/infiniband/ulp/iser/iscsi_iser.h | 2 +- drivers/scsi/libiscsi.c | 9 +-------- include/scsi/libiscsi.h | 3 +-- 4 files changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index 4338f54c41f..5f79c0a5faf 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -404,7 +404,7 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep, struct Scsi_Host *shost; struct iser_conn *ib_conn; - shost = iscsi_host_alloc(&iscsi_iser_sht, 0, ISCSI_MAX_CMD_PER_LUN); + shost = iscsi_host_alloc(&iscsi_iser_sht, 0, ISER_DEF_CMD_PER_LUN); if (!shost) return NULL; shost->transportt = iscsi_iser_scsi_transport; @@ -596,7 +596,7 @@ static struct scsi_host_template iscsi_iser_sht = { .change_queue_depth = iscsi_change_queue_depth, .sg_tablesize = ISCSI_ISER_SG_TABLESIZE, .max_sectors = 1024, - .cmd_per_lun = ISCSI_MAX_CMD_PER_LUN, + .cmd_per_lun = ISER_DEF_CMD_PER_LUN, .eh_abort_handler = iscsi_eh_abort, .eh_device_reset_handler= iscsi_eh_device_reset, .eh_target_reset_handler= iscsi_eh_target_reset, diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h index 861119593f2..9d529cae1f0 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.h +++ b/drivers/infiniband/ulp/iser/iscsi_iser.h @@ -93,7 +93,7 @@ /* support upto 512KB in one RDMA */ #define ISCSI_ISER_SG_TABLESIZE (0x80000 >> SHIFT_4K) -#define ISCSI_ISER_MAX_LUN 256 +#define ISER_DEF_CMD_PER_LUN 128 /* QP settings */ /* Maximal bounds on received asynchronous PDUs */ diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 701457cca08..a5168a67350 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1451,8 +1451,6 @@ EXPORT_SYMBOL_GPL(iscsi_queuecommand); int iscsi_change_queue_depth(struct scsi_device *sdev, int depth) { - if (depth > ISCSI_MAX_CMD_PER_LUN) - depth = ISCSI_MAX_CMD_PER_LUN; scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth); return sdev->queue_depth; } @@ -2062,13 +2060,8 @@ struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, if (!shost) return NULL; - if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) { - if (qdepth != 0) - printk(KERN_ERR "iscsi: invalid queue depth of %d. " - "Queue depth must be between 1 and %d.\n", - qdepth, ISCSI_MAX_CMD_PER_LUN); + if (qdepth == 0) qdepth = ISCSI_DEF_CMD_PER_LUN; - } shost->cmd_per_lun = qdepth; ihost = shost_priv(shost); diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 67542aa3aed..898de4a7372 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -48,8 +48,7 @@ struct device; #define ISCSI_DEF_XMIT_CMDS_MAX 128 /* must be power of 2 */ #define ISCSI_MGMT_CMDS_MAX 15 -#define ISCSI_DEF_CMD_PER_LUN 32 -#define ISCSI_MAX_CMD_PER_LUN 128 +#define ISCSI_DEF_CMD_PER_LUN 32 /* Task Mgmt states */ enum { -- GitLab From 06d25af4edb60f9e9c7e74d342a6963a32e3392f Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 5 Mar 2009 14:46:02 -0600 Subject: [PATCH 3375/4982] [SCSI] iscsi class: fix lock dep warning on logout We never should hit the lock up that is spit out when lock dep is on and we logout. But we have been using the shost work queue in a odd way. This patch has us use the work queue for scanning instead of creating our own, and this ends up also killing the lock dep warnings. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_iscsi.c | 38 +++++------------------------ include/scsi/scsi_transport_iscsi.h | 2 -- 2 files changed, 6 insertions(+), 34 deletions(-) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 75c9297694c..4f22f9e37c5 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -246,30 +246,13 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev, memset(ihost, 0, sizeof(*ihost)); atomic_set(&ihost->nr_scans, 0); mutex_init(&ihost->mutex); - - snprintf(ihost->scan_workq_name, sizeof(ihost->scan_workq_name), - "iscsi_scan_%d", shost->host_no); - ihost->scan_workq = create_singlethread_workqueue( - ihost->scan_workq_name); - if (!ihost->scan_workq) - return -ENOMEM; - return 0; -} - -static int iscsi_remove_host(struct transport_container *tc, struct device *dev, - struct device *cdev) -{ - struct Scsi_Host *shost = dev_to_shost(dev); - struct iscsi_cls_host *ihost = shost->shost_data; - - destroy_workqueue(ihost->scan_workq); return 0; } static DECLARE_TRANSPORT_CLASS(iscsi_host_class, "iscsi_host", iscsi_setup_host, - iscsi_remove_host, + NULL, NULL); static DECLARE_TRANSPORT_CLASS(iscsi_session_class, @@ -568,7 +551,7 @@ static void __iscsi_unblock_session(struct work_struct *work) * scanning from userspace). */ if (shost->hostt->scan_finished) { - if (queue_work(ihost->scan_workq, &session->scan_work)) + if (scsi_queue_work(shost, &session->scan_work)) atomic_inc(&ihost->nr_scans); } } @@ -636,14 +619,6 @@ static void __iscsi_unbind_session(struct work_struct *work) iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION); } -static int iscsi_unbind_session(struct iscsi_cls_session *session) -{ - struct Scsi_Host *shost = iscsi_session_to_shost(session); - struct iscsi_cls_host *ihost = shost->shost_data; - - return queue_work(ihost->scan_workq, &session->unbind_work); -} - struct iscsi_cls_session * iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport, int dd_size) @@ -796,7 +771,6 @@ static int iscsi_iter_destroy_conn_fn(struct device *dev, void *data) void iscsi_remove_session(struct iscsi_cls_session *session) { struct Scsi_Host *shost = iscsi_session_to_shost(session); - struct iscsi_cls_host *ihost = shost->shost_data; unsigned long flags; int err; @@ -821,7 +795,7 @@ void iscsi_remove_session(struct iscsi_cls_session *session) scsi_target_unblock(&session->dev); /* flush running scans then delete devices */ - flush_workqueue(ihost->scan_workq); + scsi_flush_work(shost); __iscsi_unbind_session(&session->unbind_work); /* hw iscsi may not have removed all connections from session */ @@ -1447,7 +1421,8 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) case ISCSI_UEVENT_UNBIND_SESSION: session = iscsi_session_lookup(ev->u.d_session.sid); if (session) - iscsi_unbind_session(session); + scsi_queue_work(iscsi_session_to_shost(session), + &session->unbind_work); else err = -EINVAL; break; @@ -1809,8 +1784,7 @@ iscsi_register_transport(struct iscsi_transport *tt) priv->daemon_pid = -1; priv->iscsi_transport = tt; priv->t.user_scan = iscsi_user_scan; - if (!(tt->caps & CAP_DATA_PATH_OFFLOAD)) - priv->t.create_work_queue = 1; + priv->t.create_work_queue = 1; priv->dev.class = &iscsi_transport_class; dev_set_name(&priv->dev, "%s", tt->name); diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index b50aabe2861..ac29fbd3554 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -206,8 +206,6 @@ struct iscsi_cls_session { struct iscsi_cls_host { atomic_t nr_scans; struct mutex mutex; - struct workqueue_struct *scan_workq; - char scan_workq_name[20]; }; extern void iscsi_host_for_each_session(struct Scsi_Host *shost, -- GitLab From 32ae763e3fce4192cd008956a340353a2e5c3192 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 5 Mar 2009 14:46:03 -0600 Subject: [PATCH 3376/4982] [SCSI] iscsi lib: have lib create work queue for transmitting IO We were using the shost work queue which ended up being a little akward since all iscsi hosts need a thread for scanning, but only drivers hooked into libiscsi need a workqueue for transmitting. So this patch moves the xmit workqueue to the lib. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/infiniband/ulp/iser/iscsi_iser.c | 2 +- drivers/infiniband/ulp/iser/iser_initiator.c | 2 +- drivers/scsi/cxgb3i/cxgb3i_iscsi.c | 2 +- drivers/scsi/cxgb3i/cxgb3i_pdu.c | 2 +- drivers/scsi/iscsi_tcp.c | 4 +- drivers/scsi/libiscsi.c | 45 ++++++++++++++++---- include/scsi/libiscsi.h | 7 ++- 7 files changed, 48 insertions(+), 16 deletions(-) diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index 5f79c0a5faf..a50cd53e275 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -404,7 +404,7 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep, struct Scsi_Host *shost; struct iser_conn *ib_conn; - shost = iscsi_host_alloc(&iscsi_iser_sht, 0, ISER_DEF_CMD_PER_LUN); + shost = iscsi_host_alloc(&iscsi_iser_sht, 0, ISER_DEF_CMD_PER_LUN, 1); if (!shost) return NULL; shost->transportt = iscsi_iser_scsi_transport; diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c index e209cb8dd94..9de640200ad 100644 --- a/drivers/infiniband/ulp/iser/iser_initiator.c +++ b/drivers/infiniband/ulp/iser/iser_initiator.c @@ -661,7 +661,7 @@ void iser_snd_completion(struct iser_desc *tx_desc) if (resume_tx) { iser_dbg("%ld resuming tx\n",jiffies); - scsi_queue_work(conn->session->host, &conn->xmitwork); + iscsi_conn_queue_work(conn); } if (tx_desc->type == ISCSI_TX_CONTROL) { diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c index fa2a44f37b3..f6ed9c62efb 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c +++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c @@ -171,7 +171,7 @@ struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *snic, shost = iscsi_host_alloc(&cxgb3i_host_template, sizeof(struct cxgb3i_hba), - CXGB3I_SCSI_QDEPTH_DFLT); + CXGB3I_SCSI_QDEPTH_DFLT, 1); if (!shost) { cxgb3i_log_info("iscsi_host_alloc failed.\n"); return NULL; diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.c b/drivers/scsi/cxgb3i/cxgb3i_pdu.c index 17115c230d6..7eebc9a7cb3 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_pdu.c +++ b/drivers/scsi/cxgb3i/cxgb3i_pdu.c @@ -479,7 +479,7 @@ void cxgb3i_conn_tx_open(struct s3_conn *c3cn) cxgb3i_tx_debug("cn 0x%p.\n", c3cn); if (conn) { cxgb3i_tx_debug("cn 0x%p, cid %d.\n", c3cn, conn->id); - scsi_queue_work(conn->session->host, &conn->xmitwork); + iscsi_conn_queue_work(conn); } } diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 9c2e52792bd..79a706a94c6 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -166,7 +166,7 @@ static void iscsi_sw_tcp_write_space(struct sock *sk) tcp_sw_conn->old_write_space(sk); ISCSI_SW_TCP_DBG(conn, "iscsi_write_space\n"); - scsi_queue_work(conn->session->host, &conn->xmitwork); + iscsi_conn_queue_work(conn); } static void iscsi_sw_tcp_conn_set_callbacks(struct iscsi_conn *conn) @@ -777,7 +777,7 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, return NULL; } - shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 0, qdepth); + shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 0, qdepth, 1); if (!shost) return NULL; shost->transportt = iscsi_sw_tcp_scsi_transport; diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index a5168a67350..ff891543df2 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -76,6 +76,15 @@ static int iscsi_sna_lte(u32 n1, u32 n2) (n1 > n2 && (n2 - n1 < SNA32_CHECK))); } +inline void iscsi_conn_queue_work(struct iscsi_conn *conn) +{ + struct Scsi_Host *shost = conn->session->host; + struct iscsi_host *ihost = shost_priv(shost); + + queue_work(ihost->workq, &conn->xmitwork); +} +EXPORT_SYMBOL_GPL(iscsi_conn_queue_work); + void iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) { @@ -103,8 +112,7 @@ iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) if (!list_empty(&session->leadconn->xmitqueue) || !list_empty(&session->leadconn->mgmtqueue)) { if (!(session->tt->caps & CAP_DATA_PATH_OFFLOAD)) - scsi_queue_work(session->host, - &session->leadconn->xmitwork); + iscsi_conn_queue_work(session->leadconn); } } } @@ -586,7 +594,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, goto free_task; } else - scsi_queue_work(conn->session->host, &conn->xmitwork); + iscsi_conn_queue_work(conn); return task; @@ -1160,7 +1168,7 @@ void iscsi_requeue_task(struct iscsi_task *task) struct iscsi_conn *conn = task->conn; list_move_tail(&task->running, &conn->requeue); - scsi_queue_work(conn->session->host, &conn->xmitwork); + iscsi_conn_queue_work(conn); } EXPORT_SYMBOL_GPL(iscsi_requeue_task); @@ -1413,7 +1421,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) goto prepd_reject; } } else - scsi_queue_work(session->host, &conn->xmitwork); + iscsi_conn_queue_work(conn); session->queued_cmdsn++; spin_unlock(&session->lock); @@ -1631,9 +1639,12 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun, void iscsi_suspend_tx(struct iscsi_conn *conn) { + struct Scsi_Host *shost = conn->session->host; + struct iscsi_host *ihost = shost_priv(shost); + set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD)) - scsi_flush_work(conn->session->host); + flush_workqueue(ihost->workq); } EXPORT_SYMBOL_GPL(iscsi_suspend_tx); @@ -1641,7 +1652,7 @@ static void iscsi_start_tx(struct iscsi_conn *conn) { clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD)) - scsi_queue_work(conn->session->host, &conn->xmitwork); + iscsi_conn_queue_work(conn); } static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) @@ -2046,12 +2057,14 @@ EXPORT_SYMBOL_GPL(iscsi_host_add); * @sht: scsi host template * @dd_data_size: driver host data size * @qdepth: default device queue depth + * @xmit_can_sleep: bool indicating if LLD will queue IO from a work queue * * This should be called by partial offload and software iscsi drivers. * To access the driver specific memory use the iscsi_host_priv() macro. */ struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, - int dd_data_size, uint16_t qdepth) + int dd_data_size, uint16_t qdepth, + bool xmit_can_sleep) { struct Scsi_Host *shost; struct iscsi_host *ihost; @@ -2063,13 +2076,25 @@ struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, if (qdepth == 0) qdepth = ISCSI_DEF_CMD_PER_LUN; shost->cmd_per_lun = qdepth; - ihost = shost_priv(shost); + + if (xmit_can_sleep) { + snprintf(ihost->workq_name, sizeof(ihost->workq_name), + "iscsi_q_%d", shost->host_no); + ihost->workq = create_singlethread_workqueue(ihost->workq_name); + if (!ihost->workq) + goto free_host; + } + spin_lock_init(&ihost->lock); ihost->state = ISCSI_HOST_SETUP; ihost->num_sessions = 0; init_waitqueue_head(&ihost->session_removal_wq); return shost; + +free_host: + scsi_host_put(shost); + return NULL; } EXPORT_SYMBOL_GPL(iscsi_host_alloc); @@ -2101,6 +2126,8 @@ void iscsi_host_remove(struct Scsi_Host *shost) flush_signals(current); scsi_remove_host(shost); + if (ihost->workq) + destroy_workqueue(ihost->workq); } EXPORT_SYMBOL_GPL(iscsi_host_remove); diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 898de4a7372..b0b8a699249 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -318,6 +318,9 @@ struct iscsi_host { spinlock_t lock; int num_sessions; int state; + + struct workqueue_struct *workq; + char workq_name[20]; }; /* @@ -343,7 +346,8 @@ extern int iscsi_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param, char *buf); extern int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev); extern struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, - int dd_data_size, uint16_t qdepth); + int dd_data_size, uint16_t qdepth, + bool xmit_can_sleep); extern void iscsi_host_remove(struct Scsi_Host *shost); extern void iscsi_host_free(struct Scsi_Host *shost); @@ -379,6 +383,7 @@ extern void iscsi_session_failure(struct iscsi_cls_session *cls_session, extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, char *buf); extern void iscsi_suspend_tx(struct iscsi_conn *conn); +extern void iscsi_conn_queue_work(struct iscsi_conn *conn); #define iscsi_conn_printk(prefix, _c, fmt, a...) \ iscsi_cls_conn_printk(prefix, ((struct iscsi_conn *)_c)->cls_conn, \ -- GitLab From 4d1083509a69a36cc1394f188b7b8956e5526a16 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 5 Mar 2009 14:46:04 -0600 Subject: [PATCH 3377/4982] [SCSI] iscsi lib: remove qdepth param from iscsi host allocation The qdepth setting was useful when we needed libiscsi to verify the setting. Now we just need to make sure if older tools passed in zero then we need to set some default. So this patch just has us use the sht->cmd_per_lun or if for LLD does a host per session then we can set it on per host basis. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/infiniband/ulp/iser/iscsi_iser.c | 2 +- drivers/scsi/cxgb3i/cxgb3i_iscsi.c | 5 ++--- drivers/scsi/iscsi_tcp.c | 3 ++- drivers/scsi/libiscsi.c | 11 ++++------- include/scsi/libiscsi.h | 2 +- 5 files changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index a50cd53e275..6c61ed12f29 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -404,7 +404,7 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep, struct Scsi_Host *shost; struct iser_conn *ib_conn; - shost = iscsi_host_alloc(&iscsi_iser_sht, 0, ISER_DEF_CMD_PER_LUN, 1); + shost = iscsi_host_alloc(&iscsi_iser_sht, 0, 1); if (!shost) return NULL; shost->transportt = iscsi_iser_scsi_transport; diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c index f6ed9c62efb..307f55e329f 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c +++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c @@ -170,8 +170,7 @@ struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *snic, int err; shost = iscsi_host_alloc(&cxgb3i_host_template, - sizeof(struct cxgb3i_hba), - CXGB3I_SCSI_QDEPTH_DFLT, 1); + sizeof(struct cxgb3i_hba), 1); if (!shost) { cxgb3i_log_info("iscsi_host_alloc failed.\n"); return NULL; @@ -843,7 +842,7 @@ static struct scsi_host_template cxgb3i_host_template = { .can_queue = CXGB3I_SCSI_QDEPTH_DFLT - 1, .sg_tablesize = SG_ALL, .max_sectors = 0xFFFF, - .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, + .cmd_per_lun = CXGB3I_SCSI_QDEPTH_DFLT, .eh_abort_handler = iscsi_eh_abort, .eh_device_reset_handler = iscsi_eh_device_reset, .eh_target_reset_handler = iscsi_eh_target_reset, diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 79a706a94c6..ad8676c98c6 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -777,10 +777,11 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, return NULL; } - shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 0, qdepth, 1); + shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 0, 1); if (!shost) return NULL; shost->transportt = iscsi_sw_tcp_scsi_transport; + shost->cmd_per_lun = qdepth; shost->max_lun = iscsi_max_lun; shost->max_id = 0; shost->max_channel = 0; diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index ff891543df2..d12f9794fcd 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -2046,6 +2046,9 @@ int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev) if (!shost->can_queue) shost->can_queue = ISCSI_DEF_XMIT_CMDS_MAX; + if (!shost->cmd_per_lun) + shost->cmd_per_lun = ISCSI_DEF_CMD_PER_LUN; + if (!shost->transportt->eh_timed_out) shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out; return scsi_add_host(shost, pdev); @@ -2056,15 +2059,13 @@ EXPORT_SYMBOL_GPL(iscsi_host_add); * iscsi_host_alloc - allocate a host and driver data * @sht: scsi host template * @dd_data_size: driver host data size - * @qdepth: default device queue depth * @xmit_can_sleep: bool indicating if LLD will queue IO from a work queue * * This should be called by partial offload and software iscsi drivers. * To access the driver specific memory use the iscsi_host_priv() macro. */ struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, - int dd_data_size, uint16_t qdepth, - bool xmit_can_sleep) + int dd_data_size, bool xmit_can_sleep) { struct Scsi_Host *shost; struct iscsi_host *ihost; @@ -2072,10 +2073,6 @@ struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, shost = scsi_host_alloc(sht, sizeof(struct iscsi_host) + dd_data_size); if (!shost) return NULL; - - if (qdepth == 0) - qdepth = ISCSI_DEF_CMD_PER_LUN; - shost->cmd_per_lun = qdepth; ihost = shost_priv(shost); if (xmit_can_sleep) { diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index b0b8a699249..84eded91b94 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -346,7 +346,7 @@ extern int iscsi_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param, char *buf); extern int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev); extern struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, - int dd_data_size, uint16_t qdepth, + int dd_data_size, bool xmit_can_sleep); extern void iscsi_host_remove(struct Scsi_Host *shost); extern void iscsi_host_free(struct Scsi_Host *shost); -- GitLab From 40a06e755d8524cd0b24f795e8bdce5ad19fc41b Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 5 Mar 2009 14:46:05 -0600 Subject: [PATCH 3378/4982] [SCSI] libiscsi: pass session failure a session struct The api for conn and session failures is akward because one takes a conn from the lib and one takes a session from the class. This syncs up the interfaces to use structs from the lib. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 5 ++--- include/scsi/libiscsi.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index d12f9794fcd..d0701791113 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1069,10 +1069,9 @@ struct iscsi_task *iscsi_itt_to_ctask(struct iscsi_conn *conn, itt_t itt) } EXPORT_SYMBOL_GPL(iscsi_itt_to_ctask); -void iscsi_session_failure(struct iscsi_cls_session *cls_session, +void iscsi_session_failure(struct iscsi_session *session, enum iscsi_err err) { - struct iscsi_session *session = cls_session->dd_data; struct iscsi_conn *conn; struct device *dev; unsigned long flags; @@ -2097,7 +2096,7 @@ EXPORT_SYMBOL_GPL(iscsi_host_alloc); static void iscsi_notify_host_removed(struct iscsi_cls_session *cls_session) { - iscsi_session_failure(cls_session, ISCSI_ERR_INVALID_HOST); + iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_INVALID_HOST); } /** diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 84eded91b94..7ffaed2f94d 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -378,7 +378,7 @@ extern void iscsi_conn_stop(struct iscsi_cls_conn *, int); extern int iscsi_conn_bind(struct iscsi_cls_session *, struct iscsi_cls_conn *, int); extern void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err); -extern void iscsi_session_failure(struct iscsi_cls_session *cls_session, +extern void iscsi_session_failure(struct iscsi_session *session, enum iscsi_err err); extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, char *buf); -- GitLab From 5e7facb77ff4b6961d936773fb1f175f7abf76b7 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 5 Mar 2009 14:46:06 -0600 Subject: [PATCH 3379/4982] [SCSI] iscsi class: remove host no argument from session creation callout We do not need to have llds set the host no for the session's parent, because we know the session's parent is going to be the host. This removes it from the session creation callback and converts the drivers. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/infiniband/ulp/iser/iscsi_iser.c | 3 +-- drivers/scsi/cxgb3i/cxgb3i_iscsi.c | 5 +---- drivers/scsi/iscsi_tcp.c | 4 +--- drivers/scsi/scsi_transport_iscsi.c | 7 ++++--- include/scsi/scsi_transport_iscsi.h | 2 +- 5 files changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index 6c61ed12f29..13d7674b293 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -397,7 +397,7 @@ static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session) static struct iscsi_cls_session * iscsi_iser_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, uint16_t qdepth, - uint32_t initial_cmdsn, uint32_t *hostno) + uint32_t initial_cmdsn) { struct iscsi_cls_session *cls_session; struct iscsi_session *session; @@ -423,7 +423,6 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep, if (iscsi_host_add(shost, ep ? ib_conn->device->ib_device->dma_device : NULL)) goto free_host; - *hostno = shost->host_no; /* * we do not support setting can_queue cmd_per_lun from userspace yet diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c index 307f55e329f..ae4a9309072 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c +++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c @@ -334,13 +334,12 @@ static void cxgb3i_ep_disconnect(struct iscsi_endpoint *ep) * @cmds_max: max # of commands * @qdepth: scsi queue depth * @initial_cmdsn: initial iscsi CMDSN for this session - * @host_no: pointer to return host no * * Creates a new iSCSI session */ static struct iscsi_cls_session * cxgb3i_session_create(struct iscsi_endpoint *ep, u16 cmds_max, u16 qdepth, - u32 initial_cmdsn, u32 *host_no) + u32 initial_cmdsn) { struct cxgb3i_endpoint *cep; struct cxgb3i_hba *hba; @@ -359,8 +358,6 @@ cxgb3i_session_create(struct iscsi_endpoint *ep, u16 cmds_max, u16 qdepth, cxgb3i_api_debug("ep 0x%p, cep 0x%p, hba 0x%p.\n", ep, cep, hba); BUG_ON(hba != iscsi_host_priv(shost)); - *host_no = shost->host_no; - cls_session = iscsi_session_setup(&cxgb3i_iscsi_transport, shost, cmds_max, sizeof(struct iscsi_tcp_task) + diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index ad8676c98c6..b3e5e08e44a 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -765,8 +765,7 @@ iscsi_sw_tcp_conn_get_stats(struct iscsi_cls_conn *cls_conn, static struct iscsi_cls_session * iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, - uint16_t qdepth, uint32_t initial_cmdsn, - uint32_t *hostno) + uint16_t qdepth, uint32_t initial_cmdsn) { struct iscsi_cls_session *cls_session; struct iscsi_session *session; @@ -789,7 +788,6 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, if (iscsi_host_add(shost, NULL)) goto free_host; - *hostno = shost->host_no; cls_session = iscsi_session_setup(&iscsi_sw_tcp_transport, shost, cmds_max, diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 4f22f9e37c5..2340e2c5c02 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1197,14 +1197,15 @@ iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_endpoint *ep, { struct iscsi_transport *transport = priv->iscsi_transport; struct iscsi_cls_session *session; - uint32_t host_no; + struct Scsi_Host *shost; session = transport->create_session(ep, cmds_max, queue_depth, - initial_cmdsn, &host_no); + initial_cmdsn); if (!session) return -ENOMEM; - ev->r.c_session_ret.host_no = host_no; + shost = iscsi_session_to_shost(session); + ev->r.c_session_ret.host_no = shost->host_no; ev->r.c_session_ret.sid = session->sid; return 0; } diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index ac29fbd3554..457588e1119 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -88,7 +88,7 @@ struct iscsi_transport { uint64_t host_param_mask; struct iscsi_cls_session *(*create_session) (struct iscsi_endpoint *ep, uint16_t cmds_max, uint16_t qdepth, - uint32_t sn, uint32_t *hn); + uint32_t sn); void (*destroy_session) (struct iscsi_cls_session *session); struct iscsi_cls_conn *(*create_conn) (struct iscsi_cls_session *sess, uint32_t cid); -- GitLab From 728996829b3e2a3bbacb7390e6c040dd839cdf21 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 5 Mar 2009 14:46:07 -0600 Subject: [PATCH 3380/4982] [SCSI] libiscsi: fix possbile null ptr session command cleanup If the iscsi eh fires when the current task is a nop, then the task->sc pointer is null. fail_all_commands could then try to do task->sc->device and oops. We actually do not need to access the curr task in this path, because if it is a cmd task the fail_command call will handle this and if it is mgmt task then the flush of the mgmt queues will handle that. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index d0701791113..dfaa8adf099 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1603,8 +1603,11 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun, { struct iscsi_task *task, *tmp; - if (conn->task && (conn->task->sc->device->lun == lun || lun == -1)) - conn->task = NULL; + if (conn->task) { + if (lun == -1 || + (conn->task->sc && conn->task->sc->device->lun == lun)) + conn->task = NULL; + } /* flush pending */ list_for_each_entry_safe(task, tmp, &conn->xmitqueue, running) { -- GitLab From 154229a33e5698cd89910c9762201bc7edd446b4 Mon Sep 17 00:00:00 2001 From: Karen Xie Date: Thu, 5 Mar 2009 14:46:08 -0600 Subject: [PATCH 3381/4982] [SCSI] cxgb3i: fix function descriptions Limit function descriptions to be one line. Signed-off-by: Karen Xie Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/cxgb3i/cxgb3i_ddp.c | 5 ++--- drivers/scsi/cxgb3i/cxgb3i_ddp.h | 8 +++----- drivers/scsi/cxgb3i/cxgb3i_iscsi.c | 17 +++++++---------- drivers/scsi/cxgb3i/cxgb3i_offload.c | 3 +-- drivers/scsi/cxgb3i/cxgb3i_offload.h | 1 + 5 files changed, 14 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.c b/drivers/scsi/cxgb3i/cxgb3i_ddp.c index a83d36e4926..4eb6f5593b3 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_ddp.c +++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.c @@ -196,7 +196,7 @@ static inline int ddp_alloc_gl_skb(struct cxgb3i_ddp_info *ddp, int idx, } /** - * cxgb3i_ddp_find_page_index - return ddp page index for a given page size. + * cxgb3i_ddp_find_page_index - return ddp page index for a given page size * @pgsz: page size * return the ddp page index, if no match is found return DDP_PGIDX_MAX. */ @@ -355,8 +355,7 @@ EXPORT_SYMBOL_GPL(cxgb3i_ddp_release_gl); * @tdev: t3cdev adapter * @tid: connection id * @tformat: tag format - * @tagp: the s/w tag, if ddp setup is successful, it will be updated with - * ddp/hw tag + * @tagp: contains s/w tag initially, will be updated with ddp/hw tag * @gl: the page momory list * @gfp: allocation mode * diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.h b/drivers/scsi/cxgb3i/cxgb3i_ddp.h index 3faae7831c8..75a63a81e87 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_ddp.h +++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.h @@ -185,12 +185,11 @@ static inline int cxgb3i_is_ddp_tag(struct cxgb3i_tag_format *tformat, u32 tag) } /** - * cxgb3i_sw_tag_usable - check if a given s/w tag has enough bits left for - * the reserved/hw bits + * cxgb3i_sw_tag_usable - check if s/w tag has enough bits left for hw bits * @tformat: tag format information * @sw_tag: s/w tag to be checked * - * return true if the tag is a ddp tag, false otherwise. + * return true if the tag can be used for hw ddp tag, false otherwise. */ static inline int cxgb3i_sw_tag_usable(struct cxgb3i_tag_format *tformat, u32 sw_tag) @@ -222,8 +221,7 @@ static inline u32 cxgb3i_set_non_ddp_tag(struct cxgb3i_tag_format *tformat, } /** - * cxgb3i_ddp_tag_base - shift the s/w tag bits so that reserved bits are not - * used. + * cxgb3i_ddp_tag_base - shift s/w tag bits so that reserved bits are not used * @tformat: tag format information * @sw_tag: s/w tag to be checked */ diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c index ae4a9309072..e185dedc4c1 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c +++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c @@ -101,8 +101,7 @@ free_snic: } /** - * cxgb3i_adapter_remove - release all the resources held and cleanup any - * h/w settings + * cxgb3i_adapter_remove - release the resources held and cleanup h/w settings * @t3dev: t3cdev adapter */ void cxgb3i_adapter_remove(struct t3cdev *t3dev) @@ -135,8 +134,7 @@ void cxgb3i_adapter_remove(struct t3cdev *t3dev) } /** - * cxgb3i_hba_find_by_netdev - find the cxgb3i_hba structure with a given - * net_device + * cxgb3i_hba_find_by_netdev - find the cxgb3i_hba structure via net_device * @t3dev: t3cdev adapter */ struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *ndev) @@ -390,9 +388,9 @@ static void cxgb3i_session_destroy(struct iscsi_cls_session *cls_session) } /** - * cxgb3i_conn_max_xmit_dlength -- check the max. xmit pdu segment size, - * reduce it to be within the hardware limit if needed + * cxgb3i_conn_max_xmit_dlength -- calc the max. xmit pdu segment size * @conn: iscsi connection + * check the max. xmit pdu payload, reduce it if needed */ static inline int cxgb3i_conn_max_xmit_dlength(struct iscsi_conn *conn) @@ -413,8 +411,7 @@ static inline int cxgb3i_conn_max_xmit_dlength(struct iscsi_conn *conn) } /** - * cxgb3i_conn_max_recv_dlength -- check the max. recv pdu segment size against - * the hardware limit + * cxgb3i_conn_max_recv_dlength -- check the max. recv pdu segment size * @conn: iscsi connection * return 0 if the value is valid, < 0 otherwise. */ @@ -755,9 +752,9 @@ static void cxgb3i_parse_itt(struct iscsi_conn *conn, itt_t itt, /** * cxgb3i_reserve_itt - generate tag for a give task - * Try to set up ddp for a scsi read task. * @task: iscsi task * @hdr_itt: tag, filled in by this function + * Set up ddp for scsi read tasks if possible. */ int cxgb3i_reserve_itt(struct iscsi_task *task, itt_t *hdr_itt) { @@ -805,9 +802,9 @@ int cxgb3i_reserve_itt(struct iscsi_task *task, itt_t *hdr_itt) /** * cxgb3i_release_itt - release the tag for a given task - * if the tag is a ddp tag, release the ddp setup * @task: iscsi task * @hdr_itt: tag + * If the tag is a ddp tag, release the ddp setup */ void cxgb3i_release_itt(struct iscsi_task *task, itt_t hdr_itt) { diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.c b/drivers/scsi/cxgb3i/cxgb3i_offload.c index de3b3b614cc..c2e434e54e2 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_offload.c +++ b/drivers/scsi/cxgb3i/cxgb3i_offload.c @@ -1417,8 +1417,7 @@ static void c3cn_active_close(struct s3_conn *c3cn) } /** - * cxgb3i_c3cn_release - close and release an iscsi tcp connection and any - * resource held + * cxgb3i_c3cn_release - close and release an iscsi tcp connection * @c3cn: the iscsi tcp connection */ void cxgb3i_c3cn_release(struct s3_conn *c3cn) diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.h b/drivers/scsi/cxgb3i/cxgb3i_offload.h index 6344b9eb258..275f23f16eb 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_offload.h +++ b/drivers/scsi/cxgb3i/cxgb3i_offload.h @@ -139,6 +139,7 @@ enum c3cn_flags { /** * cxgb3i_sdev_data - Per adapter data. + * * Linked off of each Ethernet device port on the adapter. * Also available via the t3cdev structure since we have pointers to our port * net_device's there ... -- GitLab From 4ab3b73f85ca2e99d9dbdb55ac13e57327a7e915 Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Mon, 9 Mar 2009 10:51:38 -0400 Subject: [PATCH 3382/4982] [SCSI] bsg: add linux/types.h include to bsg.h Since bsg.h has recently been added to the list of kernel headers that should be exported to the user space, this attachment makes bsg.h more user space "friendly". Specifically autotools dislike headers that don't compile freestanding and bsg.h's use of __u32 types (and friends) are not standard C (C90 or C99). The inclusion of linux/types.h fixes that. Signed-off-by: Douglas Gilbert Signed-off-by: James Bottomley --- include/linux/bsg.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/bsg.h b/include/linux/bsg.h index cf0303a6061..6c0a00dfa90 100644 --- a/include/linux/bsg.h +++ b/include/linux/bsg.h @@ -1,6 +1,8 @@ #ifndef BSG_H #define BSG_H +#include + #define BSG_PROTOCOL_SCSI 0 #define BSG_SUB_PROTOCOL_SCSI_CMD 0 -- GitLab From 59f8e169e25c5fce91826412c38359ecaf940b82 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 13 Mar 2009 13:37:46 -0700 Subject: [PATCH 3383/4982] via-velocity: Fix DMA mapping length errors on transmit. From: Dave Jones The dma-debug changes caught that this driver uses the wrong DMA mapping length when skb_padto() does something. With suggestions from Eric Dumazet. Signed-off-by: David S. Miller --- drivers/net/via-velocity.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index c5691fdb707..fb53ef872df 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -1838,17 +1838,19 @@ static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_ { struct sk_buff *skb = tdinfo->skb; int i; + int pktlen; /* * Don't unmap the pre-allocated tx_bufs */ if (tdinfo->skb_dma) { + pktlen = (skb->len > ETH_ZLEN ? : ETH_ZLEN); for (i = 0; i < tdinfo->nskb_dma; i++) { #ifdef VELOCITY_ZERO_COPY_SUPPORT pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], le16_to_cpu(td->tdesc1.len), PCI_DMA_TODEVICE); #else - pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], skb->len, PCI_DMA_TODEVICE); + pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], pktlen, PCI_DMA_TODEVICE); #endif tdinfo->skb_dma[i] = 0; } @@ -2080,17 +2082,14 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev) struct tx_desc *td_ptr; struct velocity_td_info *tdinfo; unsigned long flags; - int pktlen = skb->len; + int pktlen; __le16 len; int index; - - if (skb->len < ETH_ZLEN) { - if (skb_padto(skb, ETH_ZLEN)) - goto out; - pktlen = ETH_ZLEN; - } + if (skb_padto(skb, ETH_ZLEN)) + goto out; + pktlen = max_t(unsigned int, skb->len, ETH_ZLEN); len = cpu_to_le16(pktlen); -- GitLab From e90d400c2b65c7bf038d3646780f4a81f602cd19 Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Tue, 10 Mar 2009 16:00:24 +0000 Subject: [PATCH 3384/4982] ixgbe: fix multiple unicast address support Multiple unicast address support appears to have been broken with the change to support net_device_ops. This a regression from 2.6.28 to 2.6.29. I'm not 100% on whether ndo_set_multicast_list can be NULL after this or not. If ndo_set_rx_mode is set everything _should_ be using it. Signed-off-by: Chris Leech Acked-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index d2f4d5f508b..5d364a96e35 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3973,6 +3973,7 @@ static const struct net_device_ops ixgbe_netdev_ops = { .ndo_stop = ixgbe_close, .ndo_start_xmit = ixgbe_xmit_frame, .ndo_get_stats = ixgbe_get_stats, + .ndo_set_rx_mode = ixgbe_set_rx_mode, .ndo_set_multicast_list = ixgbe_set_rx_mode, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = ixgbe_set_mac, -- GitLab From 7a252fe7bcf64f1174b55c5c696ef2506b849f80 Mon Sep 17 00:00:00 2001 From: adam radford Date: Mon, 9 Mar 2009 12:15:01 -0800 Subject: [PATCH 3385/4982] [SCSI] 3w-9xxx: add power management support Signed-off-by: Adam Radford Signed-off-by: James Bottomley --- drivers/scsi/3w-9xxx.c | 101 ++++++++++++++++++++++++++++++++++++++++- drivers/scsi/3w-9xxx.h | 2 +- 2 files changed, 100 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index 5311317c2e4..a12783ebb42 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -4,7 +4,7 @@ Written By: Adam Radford Modifications By: Tom Couch - Copyright (C) 2004-2008 Applied Micro Circuits Corporation. + Copyright (C) 2004-2009 Applied Micro Circuits Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -75,6 +75,7 @@ Add MSI support and "use_msi" module parameter. Fix bug in twa_get_param() on 4GB+. Use pci_resource_len() for ioremap(). + 2.26.02.012 - Add power management support. */ #include @@ -99,7 +100,7 @@ #include "3w-9xxx.h" /* Globals */ -#define TW_DRIVER_VERSION "2.26.02.011" +#define TW_DRIVER_VERSION "2.26.02.012" static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; static unsigned int twa_device_extension_count; static int twa_major = -1; @@ -2182,6 +2183,98 @@ static void twa_remove(struct pci_dev *pdev) twa_device_extension_count--; } /* End twa_remove() */ +#ifdef CONFIG_PM +/* This function is called on PCI suspend */ +static int twa_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct Scsi_Host *host = pci_get_drvdata(pdev); + TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata; + + printk(KERN_WARNING "3w-9xxx: Suspending host %d.\n", tw_dev->host->host_no); + + TW_DISABLE_INTERRUPTS(tw_dev); + free_irq(tw_dev->tw_pci_dev->irq, tw_dev); + + if (test_bit(TW_USING_MSI, &tw_dev->flags)) + pci_disable_msi(pdev); + + /* Tell the card we are shutting down */ + if (twa_initconnection(tw_dev, 1, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL)) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x38, "Connection shutdown failed during suspend"); + } else { + printk(KERN_WARNING "3w-9xxx: Suspend complete.\n"); + } + TW_CLEAR_ALL_INTERRUPTS(tw_dev); + + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + + return 0; +} /* End twa_suspend() */ + +/* This function is called on PCI resume */ +static int twa_resume(struct pci_dev *pdev) +{ + int retval = 0; + struct Scsi_Host *host = pci_get_drvdata(pdev); + TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata; + + printk(KERN_WARNING "3w-9xxx: Resuming host %d.\n", tw_dev->host->host_no); + pci_set_power_state(pdev, PCI_D0); + pci_enable_wake(pdev, PCI_D0, 0); + pci_restore_state(pdev); + + retval = pci_enable_device(pdev); + if (retval) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x39, "Enable device failed during resume"); + return retval; + } + + pci_set_master(pdev); + pci_try_set_mwi(pdev); + + if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) + || pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) + || pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) { + TW_PRINTK(host, TW_DRIVER, 0x40, "Failed to set dma mask during resume"); + retval = -ENODEV; + goto out_disable_device; + } + + /* Initialize the card */ + if (twa_reset_sequence(tw_dev, 0)) { + retval = -ENODEV; + goto out_disable_device; + } + + /* Now setup the interrupt handler */ + retval = request_irq(pdev->irq, twa_interrupt, IRQF_SHARED, "3w-9xxx", tw_dev); + if (retval) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x42, "Error requesting IRQ during resume"); + retval = -ENODEV; + goto out_disable_device; + } + + /* Now enable MSI if enabled */ + if (test_bit(TW_USING_MSI, &tw_dev->flags)) + pci_enable_msi(pdev); + + /* Re-enable interrupts on the card */ + TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev); + + printk(KERN_WARNING "3w-9xxx: Resume complete.\n"); + return 0; + +out_disable_device: + scsi_remove_host(host); + pci_disable_device(pdev); + + return retval; +} /* End twa_resume() */ +#endif + /* PCI Devices supported by this driver */ static struct pci_device_id twa_pci_tbl[] __devinitdata = { { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9000, @@ -2202,6 +2295,10 @@ static struct pci_driver twa_driver = { .id_table = twa_pci_tbl, .probe = twa_probe, .remove = twa_remove, +#ifdef CONFIG_PM + .suspend = twa_suspend, + .resume = twa_resume, +#endif .shutdown = twa_shutdown }; diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h index 1729a8785fe..2893eec78ed 100644 --- a/drivers/scsi/3w-9xxx.h +++ b/drivers/scsi/3w-9xxx.h @@ -4,7 +4,7 @@ Written By: Adam Radford Modifications By: Tom Couch - Copyright (C) 2004-2008 Applied Micro Circuits Corporation. + Copyright (C) 2004-2009 Applied Micro Circuits Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -- GitLab From 95f6c83f6c57be92c67247802d0f699137957457 Mon Sep 17 00:00:00 2001 From: Scott James Remnant Date: Tue, 10 Mar 2009 16:19:44 +0000 Subject: [PATCH 3386/4982] [SCSI] ch: Add scsi type modalias The ch module is missing the scsi:t-0x08* alias that would cause it to be auto-loaded when a device of that type if found by udev, requiring udev to have a specific rule just for this one module. This patch adds the alias. Signed-off-by: Scott James Remnant Signed-off-by: James Bottomley --- drivers/scsi/ch.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index af9725409f4..7b1633a8c15 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c @@ -41,6 +41,7 @@ MODULE_DESCRIPTION("device driver for scsi media changer devices"); MODULE_AUTHOR("Gerd Knorr "); MODULE_LICENSE("GPL"); MODULE_ALIAS_CHARDEV_MAJOR(SCSI_CHANGER_MAJOR); +MODULE_ALIAS_SCSI_DEVICE(TYPE_MEDIUM_CHANGER); static int init = 1; module_param(init, int, 0444); -- GitLab From 9616a75505be9b87f9625c4d87d8b07a45ddad4d Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 13 Mar 2009 13:48:46 -0700 Subject: [PATCH 3387/4982] emac: Fix clock control for 405EX and 405EXr chips The EMAC variant in the 405EX and 405EXr chips needs the "440EP" type clock control workaround to avoid lockups of the Rx side during reset. Signed-off-by: Benjamin Herrenschmidt Tested-by: Felix Radensky Signed-off-by: David S. Miller --- drivers/net/ibm_newemac/core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index 87a706694fb..6fd7aa61736 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -2594,6 +2594,9 @@ static int __devinit emac_init_config(struct emac_instance *dev) if (of_device_is_compatible(np, "ibm,emac-460ex") || of_device_is_compatible(np, "ibm,emac-460gt")) dev->features |= EMAC_FTR_460EX_PHY_CLK_FIX; + if (of_device_is_compatible(np, "ibm,emac-405ex") || + of_device_is_compatible(np, "ibm,emac-405exr")) + dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX; } else if (of_device_is_compatible(np, "ibm,emac4")) { dev->features |= EMAC_FTR_EMAC4; if (of_device_is_compatible(np, "ibm,emac-440gx")) -- GitLab From 52e21b1bd96444c452f6eab7dc438a8a898aa14a Mon Sep 17 00:00:00 2001 From: Jan-Bernd Themann Date: Fri, 13 Mar 2009 13:50:40 -0700 Subject: [PATCH 3388/4982] ehea: fix circular locking problem This patch fixes the circular locking problem by changing the locking strategy concerning the logging of firmware handles. Signed-off-by: Jan-Bernd Themann Signed-off-by: David S. Miller --- drivers/net/ehea/ehea.h | 2 +- drivers/net/ehea/ehea_main.c | 56 +++++++++++++++++++----------------- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 029631c58f0..6e317caf429 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -40,7 +40,7 @@ #include #define DRV_NAME "ehea" -#define DRV_VERSION "EHEA_0099" +#define DRV_VERSION "EHEA_0100" /* eHEA capability flags */ #define DLPAR_PORT_ADD_REM 1 diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 40c34bfe2cf..ac0c5b438e0 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -155,6 +155,8 @@ static void ehea_update_firmware_handles(void) int num_fw_handles, k, l; /* Determine number of handles */ + mutex_lock(&ehea_fw_handles.lock); + list_for_each_entry(adapter, &adapter_list, list) { num_adapters++; @@ -176,15 +178,19 @@ static void ehea_update_firmware_handles(void) if (num_fw_handles) { arr = kzalloc(num_fw_handles * sizeof(*arr), GFP_KERNEL); if (!arr) - return; /* Keep the existing array */ + goto out; /* Keep the existing array */ } else goto out_update; list_for_each_entry(adapter, &adapter_list, list) { + if (num_adapters == 0) + break; + for (k = 0; k < EHEA_MAX_PORTS; k++) { struct ehea_port *port = adapter->port[k]; - if (!port || (port->state != EHEA_PORT_UP)) + if (!port || (port->state != EHEA_PORT_UP) + || (num_ports == 0)) continue; for (l = 0; @@ -207,6 +213,7 @@ static void ehea_update_firmware_handles(void) } arr[i].adh = adapter->handle; arr[i++].fwh = port->qp_eq->fw_handle; + num_ports--; } arr[i].adh = adapter->handle; @@ -216,16 +223,20 @@ static void ehea_update_firmware_handles(void) arr[i].adh = adapter->handle; arr[i++].fwh = adapter->mr.handle; } + num_adapters--; } out_update: kfree(ehea_fw_handles.arr); ehea_fw_handles.arr = arr; ehea_fw_handles.num_entries = i; +out: + mutex_unlock(&ehea_fw_handles.lock); } static void ehea_update_bcmc_registrations(void) { + unsigned long flags; struct ehea_bcmc_reg_entry *arr = NULL; struct ehea_adapter *adapter; struct ehea_mc_list *mc_entry; @@ -233,6 +244,8 @@ static void ehea_update_bcmc_registrations(void) int i = 0; int k; + spin_lock_irqsave(&ehea_bcmc_regs.lock, flags); + /* Determine number of registrations */ list_for_each_entry(adapter, &adapter_list, list) for (k = 0; k < EHEA_MAX_PORTS; k++) { @@ -250,7 +263,7 @@ static void ehea_update_bcmc_registrations(void) if (num_registrations) { arr = kzalloc(num_registrations * sizeof(*arr), GFP_ATOMIC); if (!arr) - return; /* Keep the existing array */ + goto out; /* Keep the existing array */ } else goto out_update; @@ -261,6 +274,9 @@ static void ehea_update_bcmc_registrations(void) if (!port || (port->state != EHEA_PORT_UP)) continue; + if (num_registrations == 0) + goto out_update; + arr[i].adh = adapter->handle; arr[i].port_id = port->logical_port_id; arr[i].reg_type = EHEA_BCMC_BROADCAST | @@ -272,9 +288,13 @@ static void ehea_update_bcmc_registrations(void) arr[i].reg_type = EHEA_BCMC_BROADCAST | EHEA_BCMC_VLANID_ALL; arr[i++].macaddr = port->mac_addr; + num_registrations -= 2; list_for_each_entry(mc_entry, &port->mc_list->list, list) { + if (num_registrations == 0) + goto out_update; + arr[i].adh = adapter->handle; arr[i].port_id = port->logical_port_id; arr[i].reg_type = EHEA_BCMC_SCOPE_ALL | @@ -288,6 +308,7 @@ static void ehea_update_bcmc_registrations(void) EHEA_BCMC_MULTICAST | EHEA_BCMC_VLANID_ALL; arr[i++].macaddr = mc_entry->macaddr; + num_registrations -= 2; } } } @@ -296,6 +317,8 @@ out_update: kfree(ehea_bcmc_regs.arr); ehea_bcmc_regs.arr = arr; ehea_bcmc_regs.num_entries = i; +out: + spin_unlock_irqrestore(&ehea_bcmc_regs.lock, flags); } static struct net_device_stats *ehea_get_stats(struct net_device *dev) @@ -1762,8 +1785,6 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa) memcpy(dev->dev_addr, mac_addr->sa_data, dev->addr_len); - spin_lock(&ehea_bcmc_regs.lock); - /* Deregister old MAC in pHYP */ if (port->state == EHEA_PORT_UP) { ret = ehea_broadcast_reg_helper(port, H_DEREG_BCMC); @@ -1784,7 +1805,6 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa) out_upregs: ehea_update_bcmc_registrations(); - spin_unlock(&ehea_bcmc_regs.lock); out_free: free_page((unsigned long)cb0); out: @@ -1946,8 +1966,6 @@ static void ehea_set_multicast_list(struct net_device *dev) } ehea_promiscuous(dev, 0); - spin_lock(&ehea_bcmc_regs.lock); - if (dev->flags & IFF_ALLMULTI) { ehea_allmulti(dev, 1); goto out; @@ -1977,7 +1995,6 @@ static void ehea_set_multicast_list(struct net_device *dev) } out: ehea_update_bcmc_registrations(); - spin_unlock(&ehea_bcmc_regs.lock); return; } @@ -2458,8 +2475,6 @@ static int ehea_up(struct net_device *dev) if (port->state == EHEA_PORT_UP) return 0; - mutex_lock(&ehea_fw_handles.lock); - ret = ehea_port_res_setup(port, port->num_def_qps, port->num_add_tx_qps); if (ret) { @@ -2496,8 +2511,6 @@ static int ehea_up(struct net_device *dev) } } - spin_lock(&ehea_bcmc_regs.lock); - ret = ehea_broadcast_reg_helper(port, H_REG_BCMC); if (ret) { ret = -EIO; @@ -2519,10 +2532,7 @@ out: ehea_info("Failed starting %s. ret=%i", dev->name, ret); ehea_update_bcmc_registrations(); - spin_unlock(&ehea_bcmc_regs.lock); - ehea_update_firmware_handles(); - mutex_unlock(&ehea_fw_handles.lock); return ret; } @@ -2572,9 +2582,6 @@ static int ehea_down(struct net_device *dev) if (port->state == EHEA_PORT_DOWN) return 0; - mutex_lock(&ehea_fw_handles.lock); - - spin_lock(&ehea_bcmc_regs.lock); ehea_drop_multicast_list(dev); ehea_broadcast_reg_helper(port, H_DEREG_BCMC); @@ -2583,7 +2590,6 @@ static int ehea_down(struct net_device *dev) port->state = EHEA_PORT_DOWN; ehea_update_bcmc_registrations(); - spin_unlock(&ehea_bcmc_regs.lock); ret = ehea_clean_all_portres(port); if (ret) @@ -2591,7 +2597,6 @@ static int ehea_down(struct net_device *dev) dev->name, ret); ehea_update_firmware_handles(); - mutex_unlock(&ehea_fw_handles.lock); return ret; } @@ -3368,7 +3373,6 @@ static int __devinit ehea_probe_adapter(struct of_device *dev, ehea_error("Invalid ibmebus device probed"); return -EINVAL; } - mutex_lock(&ehea_fw_handles.lock); adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); if (!adapter) { @@ -3453,7 +3457,7 @@ out_free_ad: out: ehea_update_firmware_handles(); - mutex_unlock(&ehea_fw_handles.lock); + return ret; } @@ -3472,8 +3476,6 @@ static int __devexit ehea_remove(struct of_device *dev) flush_scheduled_work(); - mutex_lock(&ehea_fw_handles.lock); - ibmebus_free_irq(adapter->neq->attr.ist1, adapter); tasklet_kill(&adapter->neq_tasklet); @@ -3483,7 +3485,6 @@ static int __devexit ehea_remove(struct of_device *dev) kfree(adapter); ehea_update_firmware_handles(); - mutex_unlock(&ehea_fw_handles.lock); return 0; } @@ -3532,6 +3533,9 @@ static int ehea_mem_notifier(struct notifier_block *nb, default: break; } + + ehea_update_firmware_handles(); + return NOTIFY_OK; } -- GitLab From dec3f95959bff957f5bcbf16c2a2823f7e33d1e7 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Mon, 9 Mar 2009 01:27:49 -0600 Subject: [PATCH 3389/4982] [SCSI] mpt2sas: add MPT2SAS_MINOR(221) to miscdevice.h Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- include/linux/miscdevice.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h index a820f816a49..beb6ec99cfe 100644 --- a/include/linux/miscdevice.h +++ b/include/linux/miscdevice.h @@ -26,6 +26,7 @@ #define TUN_MINOR 200 #define MWAVE_MINOR 219 /* ACP/Mwave Modem */ #define MPT_MINOR 220 +#define MPT2SAS_MINOR 221 #define HPET_MINOR 228 #define FUSE_MINOR 229 #define KVM_MINOR 232 -- GitLab From 635374e7eb110e80d9918b8611198edd56a32975 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Mon, 9 Mar 2009 01:21:12 -0600 Subject: [PATCH 3390/4982] [SCSI] mpt2sas v00.100.11.15 * This is new scsi lld device driver from LSI supporting the SAS 2.0 standard. I have split patchs by filename. * Here is list of new 6gb host controllers: LSI SAS2004 LSI SAS2008 LSI SAS2108 LSI SAS2116 * Here are the changes in the 4th posting of this patch set: (1) fix compile errors when SCSI_MPT2SAS_LOGGING is not enabled (2) add mpt2sas to the SCSI Mid Layer Makefile (3) append mpt2sas_ to the naming of all non-static functions (4) fix oops for SMP_PASSTHRU (5) doorbell algorithm imported changes from windows driver * Here are the changes in the 3rd posting of this patch set: (1) add readl following writel from the function that disables interrupts (2) replace 0xFFFFFFFFFFFFFFFFULL with ~0ULL (3) when calling pci_enable_msix, only pass one msix entry (instead of 15). (4) remove the "current HW implementation uses..... " comment in the sources (5) merged bug fix for SIGIO/POLLIN notifcation; reported by the storlib team. * Here are the changes in the 2nd posting of this patch set: (1) use little endian types in the mpi headers (2) merged in bug fix's from inhouse drivers. Signed-off-by: Eric Moore Tested-by: peter Bogdanovic Signed-off-by: James Bottomley --- drivers/scsi/Kconfig | 1 + drivers/scsi/Makefile | 1 + drivers/scsi/mpt2sas/Kconfig | 66 + drivers/scsi/mpt2sas/Makefile | 7 + drivers/scsi/mpt2sas/mpi/mpi2.h | 1067 ++++ drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h | 2151 ++++++++ drivers/scsi/mpt2sas/mpi/mpi2_init.h | 420 ++ drivers/scsi/mpt2sas/mpi/mpi2_ioc.h | 1295 +++++ drivers/scsi/mpt2sas/mpi/mpi2_raid.h | 295 ++ drivers/scsi/mpt2sas/mpi/mpi2_sas.h | 282 ++ drivers/scsi/mpt2sas/mpi/mpi2_tool.h | 249 + drivers/scsi/mpt2sas/mpi/mpi2_type.h | 61 + drivers/scsi/mpt2sas/mpt2sas_base.c | 3435 +++++++++++++ drivers/scsi/mpt2sas/mpt2sas_base.h | 779 +++ drivers/scsi/mpt2sas/mpt2sas_config.c | 1873 +++++++ drivers/scsi/mpt2sas/mpt2sas_ctl.c | 2516 ++++++++++ drivers/scsi/mpt2sas/mpt2sas_ctl.h | 416 ++ drivers/scsi/mpt2sas/mpt2sas_debug.h | 181 + drivers/scsi/mpt2sas/mpt2sas_scsih.c | 5687 ++++++++++++++++++++++ drivers/scsi/mpt2sas/mpt2sas_transport.c | 1211 +++++ 20 files changed, 21993 insertions(+) create mode 100644 drivers/scsi/mpt2sas/Kconfig create mode 100644 drivers/scsi/mpt2sas/Makefile create mode 100644 drivers/scsi/mpt2sas/mpi/mpi2.h create mode 100644 drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h create mode 100644 drivers/scsi/mpt2sas/mpi/mpi2_init.h create mode 100644 drivers/scsi/mpt2sas/mpi/mpi2_ioc.h create mode 100644 drivers/scsi/mpt2sas/mpi/mpi2_raid.h create mode 100644 drivers/scsi/mpt2sas/mpi/mpi2_sas.h create mode 100644 drivers/scsi/mpt2sas/mpi/mpi2_tool.h create mode 100644 drivers/scsi/mpt2sas/mpi/mpi2_type.h create mode 100644 drivers/scsi/mpt2sas/mpt2sas_base.c create mode 100644 drivers/scsi/mpt2sas/mpt2sas_base.h create mode 100644 drivers/scsi/mpt2sas/mpt2sas_config.c create mode 100644 drivers/scsi/mpt2sas/mpt2sas_ctl.c create mode 100644 drivers/scsi/mpt2sas/mpt2sas_ctl.h create mode 100644 drivers/scsi/mpt2sas/mpt2sas_debug.h create mode 100644 drivers/scsi/mpt2sas/mpt2sas_scsih.c create mode 100644 drivers/scsi/mpt2sas/mpt2sas_transport.c diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index e420ad0aceb..e2f44e6c0bc 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -571,6 +571,7 @@ config SCSI_ARCMSR_AER To enable this function, choose Y here. source "drivers/scsi/megaraid/Kconfig.megaraid" +source "drivers/scsi/mpt2sas/Kconfig" config SCSI_HPTIOP tristate "HighPoint RocketRAID 3xxx/4xxx Controller support" diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 05558b17041..cf792963466 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -99,6 +99,7 @@ obj-$(CONFIG_SCSI_DC390T) += tmscsim.o obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/ obj-$(CONFIG_MEGARAID_SAS) += megaraid/ +obj-$(CONFIG_SCSI_MPT2SAS) += mpt2sas/ obj-$(CONFIG_SCSI_ACARD) += atp870u.o obj-$(CONFIG_SCSI_SUNESP) += esp_scsi.o sun_esp.o obj-$(CONFIG_SCSI_GDTH) += gdth.o diff --git a/drivers/scsi/mpt2sas/Kconfig b/drivers/scsi/mpt2sas/Kconfig new file mode 100644 index 00000000000..4a86855c23b --- /dev/null +++ b/drivers/scsi/mpt2sas/Kconfig @@ -0,0 +1,66 @@ +# +# Kernel configuration file for the MPT2SAS +# +# This code is based on drivers/scsi/mpt2sas/Kconfig +# Copyright (C) 2007-2008 LSI Corporation +# (mailto:DL-MPTFusionLinux@lsi.com) + +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# NO WARRANTY +# THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT +# LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, +# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is +# solely responsible for determining the appropriateness of using and +# distributing the Program and assumes all risks associated with its +# exercise of rights under this Agreement, including but not limited to +# the risks and costs of program errors, damage to or loss of data, +# programs or equipment, and unavailability or interruption of operations. + +# DISCLAIMER OF LIABILITY +# NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +# USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED +# HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. + +config SCSI_MPT2SAS + tristate "LSI MPT Fusion SAS 2.0 Device Driver" + depends on PCI && SCSI + select SCSI_SAS_ATTRS + ---help--- + This driver supports PCI-Express SAS 6Gb/s Host Adapters. + +config SCSI_MPT2SAS_MAX_SGE + int "LSI MPT Fusion Max number of SG Entries (16 - 128)" + depends on PCI && SCSI && SCSI_MPT2SAS + default "128" + range 16 128 + ---help--- + This option allows you to specify the maximum number of scatter- + gather entries per I/O. The driver default is 128, which matches + SAFE_PHYS_SEGMENTS. However, it may decreased down to 16. + Decreasing this parameter will reduce memory requirements + on a per controller instance. + +config SCSI_MPT2SAS_LOGGING + bool "LSI MPT Fusion logging facility" + depends on PCI && SCSI && SCSI_MPT2SAS + ---help--- + This turns on a logging facility. diff --git a/drivers/scsi/mpt2sas/Makefile b/drivers/scsi/mpt2sas/Makefile new file mode 100644 index 00000000000..728f0475711 --- /dev/null +++ b/drivers/scsi/mpt2sas/Makefile @@ -0,0 +1,7 @@ +# mpt2sas makefile +obj-$(CONFIG_SCSI_MPT2SAS) += mpt2sas.o +mpt2sas-y += mpt2sas_base.o \ + mpt2sas_config.o \ + mpt2sas_scsih.o \ + mpt2sas_transport.o \ + mpt2sas_ctl.o diff --git a/drivers/scsi/mpt2sas/mpi/mpi2.h b/drivers/scsi/mpt2sas/mpi/mpi2.h new file mode 100644 index 00000000000..7bb2ece8b2e --- /dev/null +++ b/drivers/scsi/mpt2sas/mpi/mpi2.h @@ -0,0 +1,1067 @@ +/* + * Copyright (c) 2000-2009 LSI Corporation. + * + * + * Name: mpi2.h + * Title: MPI Message independent structures and definitions + * including System Interface Register Set and + * scatter/gather formats. + * Creation Date: June 21, 2006 + * + * mpi2.h Version: 02.00.11 + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 06-04-07 02.00.01 Bumped MPI2_HEADER_VERSION_UNIT. + * 06-26-07 02.00.02 Bumped MPI2_HEADER_VERSION_UNIT. + * 08-31-07 02.00.03 Bumped MPI2_HEADER_VERSION_UNIT. + * Moved ReplyPostHostIndex register to offset 0x6C of the + * MPI2_SYSTEM_INTERFACE_REGS and modified the define for + * MPI2_REPLY_POST_HOST_INDEX_OFFSET. + * Added union of request descriptors. + * Added union of reply descriptors. + * 10-31-07 02.00.04 Bumped MPI2_HEADER_VERSION_UNIT. + * Added define for MPI2_VERSION_02_00. + * Fixed the size of the FunctionDependent5 field in the + * MPI2_DEFAULT_REPLY structure. + * 12-18-07 02.00.05 Bumped MPI2_HEADER_VERSION_UNIT. + * Removed the MPI-defined Fault Codes and extended the + * product specific codes up to 0xEFFF. + * Added a sixth key value for the WriteSequence register + * and changed the flush value to 0x0. + * Added message function codes for Diagnostic Buffer Post + * and Diagnsotic Release. + * New IOCStatus define: MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED + * Moved MPI2_VERSION_UNION from mpi2_ioc.h. + * 02-29-08 02.00.06 Bumped MPI2_HEADER_VERSION_UNIT. + * 03-03-08 02.00.07 Bumped MPI2_HEADER_VERSION_UNIT. + * 05-21-08 02.00.08 Bumped MPI2_HEADER_VERSION_UNIT. + * Added #defines for marking a reply descriptor as unused. + * 06-27-08 02.00.09 Bumped MPI2_HEADER_VERSION_UNIT. + * 10-02-08 02.00.10 Bumped MPI2_HEADER_VERSION_UNIT. + * Moved LUN field defines from mpi2_init.h. + * 01-19-09 02.00.11 Bumped MPI2_HEADER_VERSION_UNIT. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI2_H +#define MPI2_H + + +/***************************************************************************** +* +* MPI Version Definitions +* +*****************************************************************************/ + +#define MPI2_VERSION_MAJOR (0x02) +#define MPI2_VERSION_MINOR (0x00) +#define MPI2_VERSION_MAJOR_MASK (0xFF00) +#define MPI2_VERSION_MAJOR_SHIFT (8) +#define MPI2_VERSION_MINOR_MASK (0x00FF) +#define MPI2_VERSION_MINOR_SHIFT (0) +#define MPI2_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \ + MPI2_VERSION_MINOR) + +#define MPI2_VERSION_02_00 (0x0200) + +/* versioning for this MPI header set */ +#define MPI2_HEADER_VERSION_UNIT (0x0B) +#define MPI2_HEADER_VERSION_DEV (0x00) +#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00) +#define MPI2_HEADER_VERSION_UNIT_SHIFT (8) +#define MPI2_HEADER_VERSION_DEV_MASK (0x00FF) +#define MPI2_HEADER_VERSION_DEV_SHIFT (0) +#define MPI2_HEADER_VERSION ((MPI2_HEADER_VERSION_UNIT << 8) | MPI2_HEADER_VERSION_DEV) + + +/***************************************************************************** +* +* IOC State Definitions +* +*****************************************************************************/ + +#define MPI2_IOC_STATE_RESET (0x00000000) +#define MPI2_IOC_STATE_READY (0x10000000) +#define MPI2_IOC_STATE_OPERATIONAL (0x20000000) +#define MPI2_IOC_STATE_FAULT (0x40000000) + +#define MPI2_IOC_STATE_MASK (0xF0000000) +#define MPI2_IOC_STATE_SHIFT (28) + +/* Fault state range for prodcut specific codes */ +#define MPI2_FAULT_PRODUCT_SPECIFIC_MIN (0x0000) +#define MPI2_FAULT_PRODUCT_SPECIFIC_MAX (0xEFFF) + + +/***************************************************************************** +* +* System Interface Register Definitions +* +*****************************************************************************/ + +typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS +{ + U32 Doorbell; /* 0x00 */ + U32 WriteSequence; /* 0x04 */ + U32 HostDiagnostic; /* 0x08 */ + U32 Reserved1; /* 0x0C */ + U32 DiagRWData; /* 0x10 */ + U32 DiagRWAddressLow; /* 0x14 */ + U32 DiagRWAddressHigh; /* 0x18 */ + U32 Reserved2[5]; /* 0x1C */ + U32 HostInterruptStatus; /* 0x30 */ + U32 HostInterruptMask; /* 0x34 */ + U32 DCRData; /* 0x38 */ + U32 DCRAddress; /* 0x3C */ + U32 Reserved3[2]; /* 0x40 */ + U32 ReplyFreeHostIndex; /* 0x48 */ + U32 Reserved4[8]; /* 0x4C */ + U32 ReplyPostHostIndex; /* 0x6C */ + U32 Reserved5; /* 0x70 */ + U32 HCBSize; /* 0x74 */ + U32 HCBAddressLow; /* 0x78 */ + U32 HCBAddressHigh; /* 0x7C */ + U32 Reserved6[16]; /* 0x80 */ + U32 RequestDescriptorPostLow; /* 0xC0 */ + U32 RequestDescriptorPostHigh; /* 0xC4 */ + U32 Reserved7[14]; /* 0xC8 */ +} MPI2_SYSTEM_INTERFACE_REGS, MPI2_POINTER PTR_MPI2_SYSTEM_INTERFACE_REGS, + Mpi2SystemInterfaceRegs_t, MPI2_POINTER pMpi2SystemInterfaceRegs_t; + +/* + * Defines for working with the Doorbell register. + */ +#define MPI2_DOORBELL_OFFSET (0x00000000) + +/* IOC --> System values */ +#define MPI2_DOORBELL_USED (0x08000000) +#define MPI2_DOORBELL_WHO_INIT_MASK (0x07000000) +#define MPI2_DOORBELL_WHO_INIT_SHIFT (24) +#define MPI2_DOORBELL_FAULT_CODE_MASK (0x0000FFFF) +#define MPI2_DOORBELL_DATA_MASK (0x0000FFFF) + +/* System --> IOC values */ +#define MPI2_DOORBELL_FUNCTION_MASK (0xFF000000) +#define MPI2_DOORBELL_FUNCTION_SHIFT (24) +#define MPI2_DOORBELL_ADD_DWORDS_MASK (0x00FF0000) +#define MPI2_DOORBELL_ADD_DWORDS_SHIFT (16) + + +/* + * Defines for the WriteSequence register + */ +#define MPI2_WRITE_SEQUENCE_OFFSET (0x00000004) +#define MPI2_WRSEQ_KEY_VALUE_MASK (0x0000000F) +#define MPI2_WRSEQ_FLUSH_KEY_VALUE (0x0) +#define MPI2_WRSEQ_1ST_KEY_VALUE (0xF) +#define MPI2_WRSEQ_2ND_KEY_VALUE (0x4) +#define MPI2_WRSEQ_3RD_KEY_VALUE (0xB) +#define MPI2_WRSEQ_4TH_KEY_VALUE (0x2) +#define MPI2_WRSEQ_5TH_KEY_VALUE (0x7) +#define MPI2_WRSEQ_6TH_KEY_VALUE (0xD) + +/* + * Defines for the HostDiagnostic register + */ +#define MPI2_HOST_DIAGNOSTIC_OFFSET (0x00000008) + +#define MPI2_DIAG_BOOT_DEVICE_SELECT_MASK (0x00001800) +#define MPI2_DIAG_BOOT_DEVICE_SELECT_DEFAULT (0x00000000) +#define MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW (0x00000800) + +#define MPI2_DIAG_CLEAR_FLASH_BAD_SIG (0x00000400) +#define MPI2_DIAG_FORCE_HCB_ON_RESET (0x00000200) +#define MPI2_DIAG_HCB_MODE (0x00000100) +#define MPI2_DIAG_DIAG_WRITE_ENABLE (0x00000080) +#define MPI2_DIAG_FLASH_BAD_SIG (0x00000040) +#define MPI2_DIAG_RESET_HISTORY (0x00000020) +#define MPI2_DIAG_DIAG_RW_ENABLE (0x00000010) +#define MPI2_DIAG_RESET_ADAPTER (0x00000004) +#define MPI2_DIAG_HOLD_IOC_RESET (0x00000002) + +/* + * Offsets for DiagRWData and address + */ +#define MPI2_DIAG_RW_DATA_OFFSET (0x00000010) +#define MPI2_DIAG_RW_ADDRESS_LOW_OFFSET (0x00000014) +#define MPI2_DIAG_RW_ADDRESS_HIGH_OFFSET (0x00000018) + +/* + * Defines for the HostInterruptStatus register + */ +#define MPI2_HOST_INTERRUPT_STATUS_OFFSET (0x00000030) +#define MPI2_HIS_SYS2IOC_DB_STATUS (0x80000000) +#define MPI2_HIS_IOP_DOORBELL_STATUS MPI2_HIS_SYS2IOC_DB_STATUS +#define MPI2_HIS_RESET_IRQ_STATUS (0x40000000) +#define MPI2_HIS_REPLY_DESCRIPTOR_INTERRUPT (0x00000008) +#define MPI2_HIS_IOC2SYS_DB_STATUS (0x00000001) +#define MPI2_HIS_DOORBELL_INTERRUPT MPI2_HIS_IOC2SYS_DB_STATUS + +/* + * Defines for the HostInterruptMask register + */ +#define MPI2_HOST_INTERRUPT_MASK_OFFSET (0x00000034) +#define MPI2_HIM_RESET_IRQ_MASK (0x40000000) +#define MPI2_HIM_REPLY_INT_MASK (0x00000008) +#define MPI2_HIM_RIM MPI2_HIM_REPLY_INT_MASK +#define MPI2_HIM_IOC2SYS_DB_MASK (0x00000001) +#define MPI2_HIM_DIM MPI2_HIM_IOC2SYS_DB_MASK + +/* + * Offsets for DCRData and address + */ +#define MPI2_DCR_DATA_OFFSET (0x00000038) +#define MPI2_DCR_ADDRESS_OFFSET (0x0000003C) + +/* + * Offset for the Reply Free Queue + */ +#define MPI2_REPLY_FREE_HOST_INDEX_OFFSET (0x00000048) + +/* + * Offset for the Reply Descriptor Post Queue + */ +#define MPI2_REPLY_POST_HOST_INDEX_OFFSET (0x0000006C) + +/* + * Defines for the HCBSize and address + */ +#define MPI2_HCB_SIZE_OFFSET (0x00000074) +#define MPI2_HCB_SIZE_SIZE_MASK (0xFFFFF000) +#define MPI2_HCB_SIZE_HCB_ENABLE (0x00000001) + +#define MPI2_HCB_ADDRESS_LOW_OFFSET (0x00000078) +#define MPI2_HCB_ADDRESS_HIGH_OFFSET (0x0000007C) + +/* + * Offsets for the Request Queue + */ +#define MPI2_REQUEST_DESCRIPTOR_POST_LOW_OFFSET (0x000000C0) +#define MPI2_REQUEST_DESCRIPTOR_POST_HIGH_OFFSET (0x000000C4) + + +/***************************************************************************** +* +* Message Descriptors +* +*****************************************************************************/ + +/* Request Descriptors */ + +/* Default Request Descriptor */ +typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR +{ + U8 RequestFlags; /* 0x00 */ + U8 VF_ID; /* 0x01 */ + U16 SMID; /* 0x02 */ + U16 LMID; /* 0x04 */ + U16 DescriptorTypeDependent; /* 0x06 */ +} MPI2_DEFAULT_REQUEST_DESCRIPTOR, + MPI2_POINTER PTR_MPI2_DEFAULT_REQUEST_DESCRIPTOR, + Mpi2DefaultRequestDescriptor_t, MPI2_POINTER pMpi2DefaultRequestDescriptor_t; + +/* defines for the RequestFlags field */ +#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK (0x0E) +#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO (0x00) +#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET (0x02) +#define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY (0x06) +#define MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE (0x08) + +#define MPI2_REQ_DESCRIPT_FLAGS_IOC_FIFO_MARKER (0x01) + + +/* High Priority Request Descriptor */ +typedef struct _MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR +{ + U8 RequestFlags; /* 0x00 */ + U8 VF_ID; /* 0x01 */ + U16 SMID; /* 0x02 */ + U16 LMID; /* 0x04 */ + U16 Reserved1; /* 0x06 */ +} MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR, + MPI2_POINTER PTR_MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR, + Mpi2HighPriorityRequestDescriptor_t, + MPI2_POINTER pMpi2HighPriorityRequestDescriptor_t; + + +/* SCSI IO Request Descriptor */ +typedef struct _MPI2_SCSI_IO_REQUEST_DESCRIPTOR +{ + U8 RequestFlags; /* 0x00 */ + U8 VF_ID; /* 0x01 */ + U16 SMID; /* 0x02 */ + U16 LMID; /* 0x04 */ + U16 DevHandle; /* 0x06 */ +} MPI2_SCSI_IO_REQUEST_DESCRIPTOR, + MPI2_POINTER PTR_MPI2_SCSI_IO_REQUEST_DESCRIPTOR, + Mpi2SCSIIORequestDescriptor_t, MPI2_POINTER pMpi2SCSIIORequestDescriptor_t; + + +/* SCSI Target Request Descriptor */ +typedef struct _MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR +{ + U8 RequestFlags; /* 0x00 */ + U8 VF_ID; /* 0x01 */ + U16 SMID; /* 0x02 */ + U16 LMID; /* 0x04 */ + U16 IoIndex; /* 0x06 */ +} MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR, + MPI2_POINTER PTR_MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR, + Mpi2SCSITargetRequestDescriptor_t, + MPI2_POINTER pMpi2SCSITargetRequestDescriptor_t; + +/* union of Request Descriptors */ +typedef union _MPI2_REQUEST_DESCRIPTOR_UNION +{ + MPI2_DEFAULT_REQUEST_DESCRIPTOR Default; + MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR HighPriority; + MPI2_SCSI_IO_REQUEST_DESCRIPTOR SCSIIO; + MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR SCSITarget; + U64 Words; +} MPI2_REQUEST_DESCRIPTOR_UNION, MPI2_POINTER PTR_MPI2_REQUEST_DESCRIPTOR_UNION, + Mpi2RequestDescriptorUnion_t, MPI2_POINTER pMpi2RequestDescriptorUnion_t; + + +/* Reply Descriptors */ + +/* Default Reply Descriptor */ +typedef struct _MPI2_DEFAULT_REPLY_DESCRIPTOR +{ + U8 ReplyFlags; /* 0x00 */ + U8 VF_ID; /* 0x01 */ + U16 DescriptorTypeDependent1; /* 0x02 */ + U32 DescriptorTypeDependent2; /* 0x04 */ +} MPI2_DEFAULT_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_DEFAULT_REPLY_DESCRIPTOR, + Mpi2DefaultReplyDescriptor_t, MPI2_POINTER pMpi2DefaultReplyDescriptor_t; + +/* defines for the ReplyFlags field */ +#define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK (0x0F) +#define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS (0x00) +#define MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY (0x01) +#define MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS (0x02) +#define MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER (0x03) +#define MPI2_RPY_DESCRIPT_FLAGS_UNUSED (0x0F) + +/* values for marking a reply descriptor as unused */ +#define MPI2_RPY_DESCRIPT_UNUSED_WORD0_MARK (0xFFFFFFFF) +#define MPI2_RPY_DESCRIPT_UNUSED_WORD1_MARK (0xFFFFFFFF) + +/* Address Reply Descriptor */ +typedef struct _MPI2_ADDRESS_REPLY_DESCRIPTOR +{ + U8 ReplyFlags; /* 0x00 */ + U8 VF_ID; /* 0x01 */ + U16 SMID; /* 0x02 */ + U32 ReplyFrameAddress; /* 0x04 */ +} MPI2_ADDRESS_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_ADDRESS_REPLY_DESCRIPTOR, + Mpi2AddressReplyDescriptor_t, MPI2_POINTER pMpi2AddressReplyDescriptor_t; + +#define MPI2_ADDRESS_REPLY_SMID_INVALID (0x00) + + +/* SCSI IO Success Reply Descriptor */ +typedef struct _MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR +{ + U8 ReplyFlags; /* 0x00 */ + U8 VF_ID; /* 0x01 */ + U16 SMID; /* 0x02 */ + U16 TaskTag; /* 0x04 */ + U16 DevHandle; /* 0x06 */ +} MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR, + MPI2_POINTER PTR_MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR, + Mpi2SCSIIOSuccessReplyDescriptor_t, + MPI2_POINTER pMpi2SCSIIOSuccessReplyDescriptor_t; + + +/* TargetAssist Success Reply Descriptor */ +typedef struct _MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR +{ + U8 ReplyFlags; /* 0x00 */ + U8 VF_ID; /* 0x01 */ + U16 SMID; /* 0x02 */ + U8 SequenceNumber; /* 0x04 */ + U8 Reserved1; /* 0x05 */ + U16 IoIndex; /* 0x06 */ +} MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR, + MPI2_POINTER PTR_MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR, + Mpi2TargetAssistSuccessReplyDescriptor_t, + MPI2_POINTER pMpi2TargetAssistSuccessReplyDescriptor_t; + + +/* Target Command Buffer Reply Descriptor */ +typedef struct _MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR +{ + U8 ReplyFlags; /* 0x00 */ + U8 VF_ID; /* 0x01 */ + U8 VP_ID; /* 0x02 */ + U8 Flags; /* 0x03 */ + U16 InitiatorDevHandle; /* 0x04 */ + U16 IoIndex; /* 0x06 */ +} MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR, + MPI2_POINTER PTR_MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR, + Mpi2TargetCommandBufferReplyDescriptor_t, + MPI2_POINTER pMpi2TargetCommandBufferReplyDescriptor_t; + +/* defines for Flags field */ +#define MPI2_RPY_DESCRIPT_TCB_FLAGS_PHYNUM_MASK (0x3F) + + +/* union of Reply Descriptors */ +typedef union _MPI2_REPLY_DESCRIPTORS_UNION +{ + MPI2_DEFAULT_REPLY_DESCRIPTOR Default; + MPI2_ADDRESS_REPLY_DESCRIPTOR AddressReply; + MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR SCSIIOSuccess; + MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR TargetAssistSuccess; + MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer; + U64 Words; +} MPI2_REPLY_DESCRIPTORS_UNION, MPI2_POINTER PTR_MPI2_REPLY_DESCRIPTORS_UNION, + Mpi2ReplyDescriptorsUnion_t, MPI2_POINTER pMpi2ReplyDescriptorsUnion_t; + + + +/***************************************************************************** +* +* Message Functions +* 0x80 -> 0x8F reserved for private message use per product +* +* +*****************************************************************************/ + +#define MPI2_FUNCTION_SCSI_IO_REQUEST (0x00) /* SCSI IO */ +#define MPI2_FUNCTION_SCSI_TASK_MGMT (0x01) /* SCSI Task Management */ +#define MPI2_FUNCTION_IOC_INIT (0x02) /* IOC Init */ +#define MPI2_FUNCTION_IOC_FACTS (0x03) /* IOC Facts */ +#define MPI2_FUNCTION_CONFIG (0x04) /* Configuration */ +#define MPI2_FUNCTION_PORT_FACTS (0x05) /* Port Facts */ +#define MPI2_FUNCTION_PORT_ENABLE (0x06) /* Port Enable */ +#define MPI2_FUNCTION_EVENT_NOTIFICATION (0x07) /* Event Notification */ +#define MPI2_FUNCTION_EVENT_ACK (0x08) /* Event Acknowledge */ +#define MPI2_FUNCTION_FW_DOWNLOAD (0x09) /* FW Download */ +#define MPI2_FUNCTION_TARGET_ASSIST (0x0B) /* Target Assist */ +#define MPI2_FUNCTION_TARGET_STATUS_SEND (0x0C) /* Target Status Send */ +#define MPI2_FUNCTION_TARGET_MODE_ABORT (0x0D) /* Target Mode Abort */ +#define MPI2_FUNCTION_FW_UPLOAD (0x12) /* FW Upload */ +#define MPI2_FUNCTION_RAID_ACTION (0x15) /* RAID Action */ +#define MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH (0x16) /* SCSI IO RAID Passthrough */ +#define MPI2_FUNCTION_TOOLBOX (0x17) /* Toolbox */ +#define MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR (0x18) /* SCSI Enclosure Processor */ +#define MPI2_FUNCTION_SMP_PASSTHROUGH (0x1A) /* SMP Passthrough */ +#define MPI2_FUNCTION_SAS_IO_UNIT_CONTROL (0x1B) /* SAS IO Unit Control */ +#define MPI2_FUNCTION_SATA_PASSTHROUGH (0x1C) /* SATA Passthrough */ +#define MPI2_FUNCTION_DIAG_BUFFER_POST (0x1D) /* Diagnostic Buffer Post */ +#define MPI2_FUNCTION_DIAG_RELEASE (0x1E) /* Diagnostic Release */ +#define MPI2_FUNCTION_TARGET_CMD_BUF_BASE_POST (0x24) /* Target Command Buffer Post Base */ +#define MPI2_FUNCTION_TARGET_CMD_BUF_LIST_POST (0x25) /* Target Command Buffer Post List */ + + + +/* Doorbell functions */ +#define MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET (0x40) +/* #define MPI2_FUNCTION_IO_UNIT_RESET (0x41) */ +#define MPI2_FUNCTION_HANDSHAKE (0x42) + + +/***************************************************************************** +* +* IOC Status Values +* +*****************************************************************************/ + +/* mask for IOCStatus status value */ +#define MPI2_IOCSTATUS_MASK (0x7FFF) + +/**************************************************************************** +* Common IOCStatus values for all replies +****************************************************************************/ + +#define MPI2_IOCSTATUS_SUCCESS (0x0000) +#define MPI2_IOCSTATUS_INVALID_FUNCTION (0x0001) +#define MPI2_IOCSTATUS_BUSY (0x0002) +#define MPI2_IOCSTATUS_INVALID_SGL (0x0003) +#define MPI2_IOCSTATUS_INTERNAL_ERROR (0x0004) +#define MPI2_IOCSTATUS_INVALID_VPID (0x0005) +#define MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES (0x0006) +#define MPI2_IOCSTATUS_INVALID_FIELD (0x0007) +#define MPI2_IOCSTATUS_INVALID_STATE (0x0008) +#define MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED (0x0009) + +/**************************************************************************** +* Config IOCStatus values +****************************************************************************/ + +#define MPI2_IOCSTATUS_CONFIG_INVALID_ACTION (0x0020) +#define MPI2_IOCSTATUS_CONFIG_INVALID_TYPE (0x0021) +#define MPI2_IOCSTATUS_CONFIG_INVALID_PAGE (0x0022) +#define MPI2_IOCSTATUS_CONFIG_INVALID_DATA (0x0023) +#define MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS (0x0024) +#define MPI2_IOCSTATUS_CONFIG_CANT_COMMIT (0x0025) + +/**************************************************************************** +* SCSI IO Reply +****************************************************************************/ + +#define MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR (0x0040) +#define MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE (0x0042) +#define MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE (0x0043) +#define MPI2_IOCSTATUS_SCSI_DATA_OVERRUN (0x0044) +#define MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN (0x0045) +#define MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR (0x0046) +#define MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR (0x0047) +#define MPI2_IOCSTATUS_SCSI_TASK_TERMINATED (0x0048) +#define MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH (0x0049) +#define MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED (0x004A) +#define MPI2_IOCSTATUS_SCSI_IOC_TERMINATED (0x004B) +#define MPI2_IOCSTATUS_SCSI_EXT_TERMINATED (0x004C) + +/**************************************************************************** +* For use by SCSI Initiator and SCSI Target end-to-end data protection +****************************************************************************/ + +#define MPI2_IOCSTATUS_EEDP_GUARD_ERROR (0x004D) +#define MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR (0x004E) +#define MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR (0x004F) + +/**************************************************************************** +* SCSI Target values +****************************************************************************/ + +#define MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX (0x0062) +#define MPI2_IOCSTATUS_TARGET_ABORTED (0x0063) +#define MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE (0x0064) +#define MPI2_IOCSTATUS_TARGET_NO_CONNECTION (0x0065) +#define MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH (0x006A) +#define MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D) +#define MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E) +#define MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F) +#define MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT (0x0070) +#define MPI2_IOCSTATUS_TARGET_NAK_RECEIVED (0x0071) + +/**************************************************************************** +* Serial Attached SCSI values +****************************************************************************/ + +#define MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090) +#define MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN (0x0091) + +/**************************************************************************** +* Diagnostic Buffer Post / Diagnostic Release values +****************************************************************************/ + +#define MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED (0x00A0) + + +/**************************************************************************** +* IOCStatus flag to indicate that log info is available +****************************************************************************/ + +#define MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE (0x8000) + +/**************************************************************************** +* IOCLogInfo Types +****************************************************************************/ + +#define MPI2_IOCLOGINFO_TYPE_MASK (0xF0000000) +#define MPI2_IOCLOGINFO_TYPE_SHIFT (28) +#define MPI2_IOCLOGINFO_TYPE_NONE (0x0) +#define MPI2_IOCLOGINFO_TYPE_SCSI (0x1) +#define MPI2_IOCLOGINFO_TYPE_FC (0x2) +#define MPI2_IOCLOGINFO_TYPE_SAS (0x3) +#define MPI2_IOCLOGINFO_TYPE_ISCSI (0x4) +#define MPI2_IOCLOGINFO_LOG_DATA_MASK (0x0FFFFFFF) + + +/***************************************************************************** +* +* Standard Message Structures +* +*****************************************************************************/ + +/**************************************************************************** +* Request Message Header for all request messages +****************************************************************************/ + +typedef struct _MPI2_REQUEST_HEADER +{ + U16 FunctionDependent1; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 FunctionDependent2; /* 0x04 */ + U8 FunctionDependent3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved1; /* 0x0A */ +} MPI2_REQUEST_HEADER, MPI2_POINTER PTR_MPI2_REQUEST_HEADER, + MPI2RequestHeader_t, MPI2_POINTER pMPI2RequestHeader_t; + + +/**************************************************************************** +* Default Reply +****************************************************************************/ + +typedef struct _MPI2_DEFAULT_REPLY +{ + U16 FunctionDependent1; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 FunctionDependent2; /* 0x04 */ + U8 FunctionDependent3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved1; /* 0x0A */ + U16 FunctionDependent5; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ +} MPI2_DEFAULT_REPLY, MPI2_POINTER PTR_MPI2_DEFAULT_REPLY, + MPI2DefaultReply_t, MPI2_POINTER pMPI2DefaultReply_t; + + +/* common version structure/union used in messages and configuration pages */ + +typedef struct _MPI2_VERSION_STRUCT +{ + U8 Dev; /* 0x00 */ + U8 Unit; /* 0x01 */ + U8 Minor; /* 0x02 */ + U8 Major; /* 0x03 */ +} MPI2_VERSION_STRUCT; + +typedef union _MPI2_VERSION_UNION +{ + MPI2_VERSION_STRUCT Struct; + U32 Word; +} MPI2_VERSION_UNION; + + +/* LUN field defines, common to many structures */ +#define MPI2_LUN_FIRST_LEVEL_ADDRESSING (0x0000FFFF) +#define MPI2_LUN_SECOND_LEVEL_ADDRESSING (0xFFFF0000) +#define MPI2_LUN_THIRD_LEVEL_ADDRESSING (0x0000FFFF) +#define MPI2_LUN_FOURTH_LEVEL_ADDRESSING (0xFFFF0000) +#define MPI2_LUN_LEVEL_1_WORD (0xFF00) +#define MPI2_LUN_LEVEL_1_DWORD (0x0000FF00) + + +/***************************************************************************** +* +* Fusion-MPT MPI Scatter Gather Elements +* +*****************************************************************************/ + +/**************************************************************************** +* MPI Simple Element structures +****************************************************************************/ + +typedef struct _MPI2_SGE_SIMPLE32 +{ + U32 FlagsLength; + U32 Address; +} MPI2_SGE_SIMPLE32, MPI2_POINTER PTR_MPI2_SGE_SIMPLE32, + Mpi2SGESimple32_t, MPI2_POINTER pMpi2SGESimple32_t; + +typedef struct _MPI2_SGE_SIMPLE64 +{ + U32 FlagsLength; + U64 Address; +} MPI2_SGE_SIMPLE64, MPI2_POINTER PTR_MPI2_SGE_SIMPLE64, + Mpi2SGESimple64_t, MPI2_POINTER pMpi2SGESimple64_t; + +typedef struct _MPI2_SGE_SIMPLE_UNION +{ + U32 FlagsLength; + union + { + U32 Address32; + U64 Address64; + } u; +} MPI2_SGE_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_SGE_SIMPLE_UNION, + Mpi2SGESimpleUnion_t, MPI2_POINTER pMpi2SGESimpleUnion_t; + + +/**************************************************************************** +* MPI Chain Element structures +****************************************************************************/ + +typedef struct _MPI2_SGE_CHAIN32 +{ + U16 Length; + U8 NextChainOffset; + U8 Flags; + U32 Address; +} MPI2_SGE_CHAIN32, MPI2_POINTER PTR_MPI2_SGE_CHAIN32, + Mpi2SGEChain32_t, MPI2_POINTER pMpi2SGEChain32_t; + +typedef struct _MPI2_SGE_CHAIN64 +{ + U16 Length; + U8 NextChainOffset; + U8 Flags; + U64 Address; +} MPI2_SGE_CHAIN64, MPI2_POINTER PTR_MPI2_SGE_CHAIN64, + Mpi2SGEChain64_t, MPI2_POINTER pMpi2SGEChain64_t; + +typedef struct _MPI2_SGE_CHAIN_UNION +{ + U16 Length; + U8 NextChainOffset; + U8 Flags; + union + { + U32 Address32; + U64 Address64; + } u; +} MPI2_SGE_CHAIN_UNION, MPI2_POINTER PTR_MPI2_SGE_CHAIN_UNION, + Mpi2SGEChainUnion_t, MPI2_POINTER pMpi2SGEChainUnion_t; + + +/**************************************************************************** +* MPI Transaction Context Element structures +****************************************************************************/ + +typedef struct _MPI2_SGE_TRANSACTION32 +{ + U8 Reserved; + U8 ContextSize; + U8 DetailsLength; + U8 Flags; + U32 TransactionContext[1]; + U32 TransactionDetails[1]; +} MPI2_SGE_TRANSACTION32, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION32, + Mpi2SGETransaction32_t, MPI2_POINTER pMpi2SGETransaction32_t; + +typedef struct _MPI2_SGE_TRANSACTION64 +{ + U8 Reserved; + U8 ContextSize; + U8 DetailsLength; + U8 Flags; + U32 TransactionContext[2]; + U32 TransactionDetails[1]; +} MPI2_SGE_TRANSACTION64, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION64, + Mpi2SGETransaction64_t, MPI2_POINTER pMpi2SGETransaction64_t; + +typedef struct _MPI2_SGE_TRANSACTION96 +{ + U8 Reserved; + U8 ContextSize; + U8 DetailsLength; + U8 Flags; + U32 TransactionContext[3]; + U32 TransactionDetails[1]; +} MPI2_SGE_TRANSACTION96, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION96, + Mpi2SGETransaction96_t, MPI2_POINTER pMpi2SGETransaction96_t; + +typedef struct _MPI2_SGE_TRANSACTION128 +{ + U8 Reserved; + U8 ContextSize; + U8 DetailsLength; + U8 Flags; + U32 TransactionContext[4]; + U32 TransactionDetails[1]; +} MPI2_SGE_TRANSACTION128, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION128, + Mpi2SGETransaction_t128, MPI2_POINTER pMpi2SGETransaction_t128; + +typedef struct _MPI2_SGE_TRANSACTION_UNION +{ + U8 Reserved; + U8 ContextSize; + U8 DetailsLength; + U8 Flags; + union + { + U32 TransactionContext32[1]; + U32 TransactionContext64[2]; + U32 TransactionContext96[3]; + U32 TransactionContext128[4]; + } u; + U32 TransactionDetails[1]; +} MPI2_SGE_TRANSACTION_UNION, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION_UNION, + Mpi2SGETransactionUnion_t, MPI2_POINTER pMpi2SGETransactionUnion_t; + + +/**************************************************************************** +* MPI SGE union for IO SGL's +****************************************************************************/ + +typedef struct _MPI2_MPI_SGE_IO_UNION +{ + union + { + MPI2_SGE_SIMPLE_UNION Simple; + MPI2_SGE_CHAIN_UNION Chain; + } u; +} MPI2_MPI_SGE_IO_UNION, MPI2_POINTER PTR_MPI2_MPI_SGE_IO_UNION, + Mpi2MpiSGEIOUnion_t, MPI2_POINTER pMpi2MpiSGEIOUnion_t; + + +/**************************************************************************** +* MPI SGE union for SGL's with Simple and Transaction elements +****************************************************************************/ + +typedef struct _MPI2_SGE_TRANS_SIMPLE_UNION +{ + union + { + MPI2_SGE_SIMPLE_UNION Simple; + MPI2_SGE_TRANSACTION_UNION Transaction; + } u; +} MPI2_SGE_TRANS_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_SGE_TRANS_SIMPLE_UNION, + Mpi2SGETransSimpleUnion_t, MPI2_POINTER pMpi2SGETransSimpleUnion_t; + + +/**************************************************************************** +* All MPI SGE types union +****************************************************************************/ + +typedef struct _MPI2_MPI_SGE_UNION +{ + union + { + MPI2_SGE_SIMPLE_UNION Simple; + MPI2_SGE_CHAIN_UNION Chain; + MPI2_SGE_TRANSACTION_UNION Transaction; + } u; +} MPI2_MPI_SGE_UNION, MPI2_POINTER PTR_MPI2_MPI_SGE_UNION, + Mpi2MpiSgeUnion_t, MPI2_POINTER pMpi2MpiSgeUnion_t; + + +/**************************************************************************** +* MPI SGE field definition and masks +****************************************************************************/ + +/* Flags field bit definitions */ + +#define MPI2_SGE_FLAGS_LAST_ELEMENT (0x80) +#define MPI2_SGE_FLAGS_END_OF_BUFFER (0x40) +#define MPI2_SGE_FLAGS_ELEMENT_TYPE_MASK (0x30) +#define MPI2_SGE_FLAGS_LOCAL_ADDRESS (0x08) +#define MPI2_SGE_FLAGS_DIRECTION (0x04) +#define MPI2_SGE_FLAGS_ADDRESS_SIZE (0x02) +#define MPI2_SGE_FLAGS_END_OF_LIST (0x01) + +#define MPI2_SGE_FLAGS_SHIFT (24) + +#define MPI2_SGE_LENGTH_MASK (0x00FFFFFF) +#define MPI2_SGE_CHAIN_LENGTH_MASK (0x0000FFFF) + +/* Element Type */ + +#define MPI2_SGE_FLAGS_TRANSACTION_ELEMENT (0x00) +#define MPI2_SGE_FLAGS_SIMPLE_ELEMENT (0x10) +#define MPI2_SGE_FLAGS_CHAIN_ELEMENT (0x30) +#define MPI2_SGE_FLAGS_ELEMENT_MASK (0x30) + +/* Address location */ + +#define MPI2_SGE_FLAGS_SYSTEM_ADDRESS (0x00) + +/* Direction */ + +#define MPI2_SGE_FLAGS_IOC_TO_HOST (0x00) +#define MPI2_SGE_FLAGS_HOST_TO_IOC (0x04) + +/* Address Size */ + +#define MPI2_SGE_FLAGS_32_BIT_ADDRESSING (0x00) +#define MPI2_SGE_FLAGS_64_BIT_ADDRESSING (0x02) + +/* Context Size */ + +#define MPI2_SGE_FLAGS_32_BIT_CONTEXT (0x00) +#define MPI2_SGE_FLAGS_64_BIT_CONTEXT (0x02) +#define MPI2_SGE_FLAGS_96_BIT_CONTEXT (0x04) +#define MPI2_SGE_FLAGS_128_BIT_CONTEXT (0x06) + +#define MPI2_SGE_CHAIN_OFFSET_MASK (0x00FF0000) +#define MPI2_SGE_CHAIN_OFFSET_SHIFT (16) + +/**************************************************************************** +* MPI SGE operation Macros +****************************************************************************/ + +/* SIMPLE FlagsLength manipulations... */ +#define MPI2_SGE_SET_FLAGS(f) ((U32)(f) << MPI2_SGE_FLAGS_SHIFT) +#define MPI2_SGE_GET_FLAGS(f) (((f) & ~MPI2_SGE_LENGTH_MASK) >> MPI2_SGE_FLAGS_SHIFT) +#define MPI2_SGE_LENGTH(f) ((f) & MPI2_SGE_LENGTH_MASK) +#define MPI2_SGE_CHAIN_LENGTH(f) ((f) & MPI2_SGE_CHAIN_LENGTH_MASK) + +#define MPI2_SGE_SET_FLAGS_LENGTH(f,l) (MPI2_SGE_SET_FLAGS(f) | MPI2_SGE_LENGTH(l)) + +#define MPI2_pSGE_GET_FLAGS(psg) MPI2_SGE_GET_FLAGS((psg)->FlagsLength) +#define MPI2_pSGE_GET_LENGTH(psg) MPI2_SGE_LENGTH((psg)->FlagsLength) +#define MPI2_pSGE_SET_FLAGS_LENGTH(psg,f,l) (psg)->FlagsLength = MPI2_SGE_SET_FLAGS_LENGTH(f,l) + +/* CAUTION - The following are READ-MODIFY-WRITE! */ +#define MPI2_pSGE_SET_FLAGS(psg,f) (psg)->FlagsLength |= MPI2_SGE_SET_FLAGS(f) +#define MPI2_pSGE_SET_LENGTH(psg,l) (psg)->FlagsLength |= MPI2_SGE_LENGTH(l) + +#define MPI2_GET_CHAIN_OFFSET(x) ((x & MPI2_SGE_CHAIN_OFFSET_MASK) >> MPI2_SGE_CHAIN_OFFSET_SHIFT) + + +/***************************************************************************** +* +* Fusion-MPT IEEE Scatter Gather Elements +* +*****************************************************************************/ + +/**************************************************************************** +* IEEE Simple Element structures +****************************************************************************/ + +typedef struct _MPI2_IEEE_SGE_SIMPLE32 +{ + U32 Address; + U32 FlagsLength; +} MPI2_IEEE_SGE_SIMPLE32, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE32, + Mpi2IeeeSgeSimple32_t, MPI2_POINTER pMpi2IeeeSgeSimple32_t; + +typedef struct _MPI2_IEEE_SGE_SIMPLE64 +{ + U64 Address; + U32 Length; + U16 Reserved1; + U8 Reserved2; + U8 Flags; +} MPI2_IEEE_SGE_SIMPLE64, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE64, + Mpi2IeeeSgeSimple64_t, MPI2_POINTER pMpi2IeeeSgeSimple64_t; + +typedef union _MPI2_IEEE_SGE_SIMPLE_UNION +{ + MPI2_IEEE_SGE_SIMPLE32 Simple32; + MPI2_IEEE_SGE_SIMPLE64 Simple64; +} MPI2_IEEE_SGE_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE_UNION, + Mpi2IeeeSgeSimpleUnion_t, MPI2_POINTER pMpi2IeeeSgeSimpleUnion_t; + + +/**************************************************************************** +* IEEE Chain Element structures +****************************************************************************/ + +typedef MPI2_IEEE_SGE_SIMPLE32 MPI2_IEEE_SGE_CHAIN32; + +typedef MPI2_IEEE_SGE_SIMPLE64 MPI2_IEEE_SGE_CHAIN64; + +typedef union _MPI2_IEEE_SGE_CHAIN_UNION +{ + MPI2_IEEE_SGE_CHAIN32 Chain32; + MPI2_IEEE_SGE_CHAIN64 Chain64; +} MPI2_IEEE_SGE_CHAIN_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_CHAIN_UNION, + Mpi2IeeeSgeChainUnion_t, MPI2_POINTER pMpi2IeeeSgeChainUnion_t; + + +/**************************************************************************** +* All IEEE SGE types union +****************************************************************************/ + +typedef struct _MPI2_IEEE_SGE_UNION +{ + union + { + MPI2_IEEE_SGE_SIMPLE_UNION Simple; + MPI2_IEEE_SGE_CHAIN_UNION Chain; + } u; +} MPI2_IEEE_SGE_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_UNION, + Mpi2IeeeSgeUnion_t, MPI2_POINTER pMpi2IeeeSgeUnion_t; + + +/**************************************************************************** +* IEEE SGE field definitions and masks +****************************************************************************/ + +/* Flags field bit definitions */ + +#define MPI2_IEEE_SGE_FLAGS_ELEMENT_TYPE_MASK (0x80) + +#define MPI2_IEEE32_SGE_FLAGS_SHIFT (24) + +#define MPI2_IEEE32_SGE_LENGTH_MASK (0x00FFFFFF) + +/* Element Type */ + +#define MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT (0x00) +#define MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT (0x80) + +/* Data Location Address Space */ + +#define MPI2_IEEE_SGE_FLAGS_ADDR_MASK (0x03) +#define MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR (0x00) +#define MPI2_IEEE_SGE_FLAGS_IOCDDR_ADDR (0x01) +#define MPI2_IEEE_SGE_FLAGS_IOCPLB_ADDR (0x02) +#define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03) + + +/**************************************************************************** +* IEEE SGE operation Macros +****************************************************************************/ + +/* SIMPLE FlagsLength manipulations... */ +#define MPI2_IEEE32_SGE_SET_FLAGS(f) ((U32)(f) << MPI2_IEEE32_SGE_FLAGS_SHIFT) +#define MPI2_IEEE32_SGE_GET_FLAGS(f) (((f) & ~MPI2_IEEE32_SGE_LENGTH_MASK) >> MPI2_IEEE32_SGE_FLAGS_SHIFT) +#define MPI2_IEEE32_SGE_LENGTH(f) ((f) & MPI2_IEEE32_SGE_LENGTH_MASK) + +#define MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f, l) (MPI2_IEEE32_SGE_SET_FLAGS(f) | MPI2_IEEE32_SGE_LENGTH(l)) + +#define MPI2_IEEE32_pSGE_GET_FLAGS(psg) MPI2_IEEE32_SGE_GET_FLAGS((psg)->FlagsLength) +#define MPI2_IEEE32_pSGE_GET_LENGTH(psg) MPI2_IEEE32_SGE_LENGTH((psg)->FlagsLength) +#define MPI2_IEEE32_pSGE_SET_FLAGS_LENGTH(psg,f,l) (psg)->FlagsLength = MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f,l) + +/* CAUTION - The following are READ-MODIFY-WRITE! */ +#define MPI2_IEEE32_pSGE_SET_FLAGS(psg,f) (psg)->FlagsLength |= MPI2_IEEE32_SGE_SET_FLAGS(f) +#define MPI2_IEEE32_pSGE_SET_LENGTH(psg,l) (psg)->FlagsLength |= MPI2_IEEE32_SGE_LENGTH(l) + + + + +/***************************************************************************** +* +* Fusion-MPT MPI/IEEE Scatter Gather Unions +* +*****************************************************************************/ + +typedef union _MPI2_SIMPLE_SGE_UNION +{ + MPI2_SGE_SIMPLE_UNION MpiSimple; + MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple; +} MPI2_SIMPLE_SGE_UNION, MPI2_POINTER PTR_MPI2_SIMPLE_SGE_UNION, + Mpi2SimpleSgeUntion_t, MPI2_POINTER pMpi2SimpleSgeUntion_t; + + +typedef union _MPI2_SGE_IO_UNION +{ + MPI2_SGE_SIMPLE_UNION MpiSimple; + MPI2_SGE_CHAIN_UNION MpiChain; + MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple; + MPI2_IEEE_SGE_CHAIN_UNION IeeeChain; +} MPI2_SGE_IO_UNION, MPI2_POINTER PTR_MPI2_SGE_IO_UNION, + Mpi2SGEIOUnion_t, MPI2_POINTER pMpi2SGEIOUnion_t; + + +/**************************************************************************** +* +* Values for SGLFlags field, used in many request messages with an SGL +* +****************************************************************************/ + +/* values for MPI SGL Data Location Address Space subfield */ +#define MPI2_SGLFLAGS_ADDRESS_SPACE_MASK (0x0C) +#define MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE (0x00) +#define MPI2_SGLFLAGS_IOCDDR_ADDRESS_SPACE (0x04) +#define MPI2_SGLFLAGS_IOCPLB_ADDRESS_SPACE (0x08) +#define MPI2_SGLFLAGS_IOCPLBNTA_ADDRESS_SPACE (0x0C) +/* values for SGL Type subfield */ +#define MPI2_SGLFLAGS_SGL_TYPE_MASK (0x03) +#define MPI2_SGLFLAGS_SGL_TYPE_MPI (0x00) +#define MPI2_SGLFLAGS_SGL_TYPE_IEEE32 (0x01) +#define MPI2_SGLFLAGS_SGL_TYPE_IEEE64 (0x02) + + +#endif + diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h new file mode 100644 index 00000000000..2f27cf6d6c6 --- /dev/null +++ b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h @@ -0,0 +1,2151 @@ +/* + * Copyright (c) 2000-2009 LSI Corporation. + * + * + * Name: mpi2_cnfg.h + * Title: MPI Configuration messages and pages + * Creation Date: November 10, 2006 + * + * mpi2_cnfg.h Version: 02.00.10 + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 06-04-07 02.00.01 Added defines for SAS IO Unit Page 2 PhyFlags. + * Added Manufacturing Page 11. + * Added MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE + * define. + * 06-26-07 02.00.02 Adding generic structure for product-specific + * Manufacturing pages: MPI2_CONFIG_PAGE_MANUFACTURING_PS. + * Rework of BIOS Page 2 configuration page. + * Fixed MPI2_BIOSPAGE2_BOOT_DEVICE to be a union of the + * forms. + * Added configuration pages IOC Page 8 and Driver + * Persistent Mapping Page 0. + * 08-31-07 02.00.03 Modified configuration pages dealing with Integrated + * RAID (Manufacturing Page 4, RAID Volume Pages 0 and 1, + * RAID Physical Disk Pages 0 and 1, RAID Configuration + * Page 0). + * Added new value for AccessStatus field of SAS Device + * Page 0 (_SATA_NEEDS_INITIALIZATION). + * 10-31-07 02.00.04 Added missing SEPDevHandle field to + * MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0. + * 12-18-07 02.00.05 Modified IO Unit Page 0 to use 32-bit version fields for + * NVDATA. + * Modified IOC Page 7 to use masks and added field for + * SASBroadcastPrimitiveMasks. + * Added MPI2_CONFIG_PAGE_BIOS_4. + * Added MPI2_CONFIG_PAGE_LOG_0. + * 02-29-08 02.00.06 Modified various names to make them 32-character unique. + * Added SAS Device IDs. + * Updated Integrated RAID configuration pages including + * Manufacturing Page 4, IOC Page 6, and RAID Configuration + * Page 0. + * 05-21-08 02.00.07 Added define MPI2_MANPAGE4_MIX_SSD_SAS_SATA. + * Added define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION. + * Fixed define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING. + * Added missing MaxNumRoutedSasAddresses field to + * MPI2_CONFIG_PAGE_EXPANDER_0. + * Added SAS Port Page 0. + * Modified structure layout for + * MPI2_CONFIG_PAGE_DRIVER_MAPPING_0. + * 06-27-08 02.00.08 Changed MPI2_CONFIG_PAGE_RD_PDISK_1 to use + * MPI2_RAID_PHYS_DISK1_PATH_MAX to size the array. + * 10-02-08 02.00.09 Changed MPI2_RAID_PGAD_CONFIGNUM_MASK from 0x0000FFFF + * to 0x000000FF. + * Added two new values for the Physical Disk Coercion Size + * bits in the Flags field of Manufacturing Page 4. + * Added product-specific Manufacturing pages 16 to 31. + * Modified Flags bits for controlling write cache on SATA + * drives in IO Unit Page 1. + * Added new bit to AdditionalControlFlags of SAS IO Unit + * Page 1 to control Invalid Topology Correction. + * Added additional defines for RAID Volume Page 0 + * VolumeStatusFlags field. + * Modified meaning of RAID Volume Page 0 VolumeSettings + * define for auto-configure of hot-swap drives. + * Added SupportedPhysDisks field to RAID Volume Page 1 and + * added related defines. + * Added PhysDiskAttributes field (and related defines) to + * RAID Physical Disk Page 0. + * Added MPI2_SAS_PHYINFO_PHY_VACANT define. + * Added three new DiscoveryStatus bits for SAS IO Unit + * Page 0 and SAS Expander Page 0. + * Removed multiplexing information from SAS IO Unit pages. + * Added BootDeviceWaitTime field to SAS IO Unit Page 4. + * Removed Zone Address Resolved bit from PhyInfo and from + * Expander Page 0 Flags field. + * Added two new AccessStatus values to SAS Device Page 0 + * for indicating routing problems. Added 3 reserved words + * to this page. + * 01-19-09 02.00.10 Fixed defines for GPIOVal field of IO Unit Page 3. + * Inserted missing reserved field into structure for IOC + * Page 6. + * Added more pending task bits to RAID Volume Page 0 + * VolumeStatusFlags defines. + * Added MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED define. + * Added a new DiscoveryStatus bit for SAS IO Unit Page 0 + * and SAS Expander Page 0 to flag a downstream initiator + * when in simplified routing mode. + * Removed SATA Init Failure defines for DiscoveryStatus + * fields of SAS IO Unit Page 0 and SAS Expander Page 0. + * Added MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED define. + * Added PortGroups, DmaGroup, and ControlGroup fields to + * SAS Device Page 0. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI2_CNFG_H +#define MPI2_CNFG_H + +/***************************************************************************** +* Configuration Page Header and defines +*****************************************************************************/ + +/* Config Page Header */ +typedef struct _MPI2_CONFIG_PAGE_HEADER +{ + U8 PageVersion; /* 0x00 */ + U8 PageLength; /* 0x01 */ + U8 PageNumber; /* 0x02 */ + U8 PageType; /* 0x03 */ +} MPI2_CONFIG_PAGE_HEADER, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_HEADER, + Mpi2ConfigPageHeader_t, MPI2_POINTER pMpi2ConfigPageHeader_t; + +typedef union _MPI2_CONFIG_PAGE_HEADER_UNION +{ + MPI2_CONFIG_PAGE_HEADER Struct; + U8 Bytes[4]; + U16 Word16[2]; + U32 Word32; +} MPI2_CONFIG_PAGE_HEADER_UNION, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_HEADER_UNION, + Mpi2ConfigPageHeaderUnion, MPI2_POINTER pMpi2ConfigPageHeaderUnion; + +/* Extended Config Page Header */ +typedef struct _MPI2_CONFIG_EXTENDED_PAGE_HEADER +{ + U8 PageVersion; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 PageNumber; /* 0x02 */ + U8 PageType; /* 0x03 */ + U16 ExtPageLength; /* 0x04 */ + U8 ExtPageType; /* 0x06 */ + U8 Reserved2; /* 0x07 */ +} MPI2_CONFIG_EXTENDED_PAGE_HEADER, + MPI2_POINTER PTR_MPI2_CONFIG_EXTENDED_PAGE_HEADER, + Mpi2ConfigExtendedPageHeader_t, MPI2_POINTER pMpi2ConfigExtendedPageHeader_t; + +typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION +{ + MPI2_CONFIG_PAGE_HEADER Struct; + MPI2_CONFIG_EXTENDED_PAGE_HEADER Ext; + U8 Bytes[8]; + U16 Word16[4]; + U32 Word32[2]; +} MPI2_CONFIG_EXT_PAGE_HEADER_UNION, MPI2_POINTER PTR_MPI2_CONFIG_EXT_PAGE_HEADER_UNION, + Mpi2ConfigPageExtendedHeaderUnion, MPI2_POINTER pMpi2ConfigPageExtendedHeaderUnion; + + +/* PageType field values */ +#define MPI2_CONFIG_PAGEATTR_READ_ONLY (0x00) +#define MPI2_CONFIG_PAGEATTR_CHANGEABLE (0x10) +#define MPI2_CONFIG_PAGEATTR_PERSISTENT (0x20) +#define MPI2_CONFIG_PAGEATTR_MASK (0xF0) + +#define MPI2_CONFIG_PAGETYPE_IO_UNIT (0x00) +#define MPI2_CONFIG_PAGETYPE_IOC (0x01) +#define MPI2_CONFIG_PAGETYPE_BIOS (0x02) +#define MPI2_CONFIG_PAGETYPE_RAID_VOLUME (0x08) +#define MPI2_CONFIG_PAGETYPE_MANUFACTURING (0x09) +#define MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK (0x0A) +#define MPI2_CONFIG_PAGETYPE_EXTENDED (0x0F) +#define MPI2_CONFIG_PAGETYPE_MASK (0x0F) + +#define MPI2_CONFIG_TYPENUM_MASK (0x0FFF) + + +/* ExtPageType field values */ +#define MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT (0x10) +#define MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER (0x11) +#define MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE (0x12) +#define MPI2_CONFIG_EXTPAGETYPE_SAS_PHY (0x13) +#define MPI2_CONFIG_EXTPAGETYPE_LOG (0x14) +#define MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE (0x15) +#define MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG (0x16) +#define MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING (0x17) +#define MPI2_CONFIG_EXTPAGETYPE_SAS_PORT (0x18) + + +/***************************************************************************** +* PageAddress defines +*****************************************************************************/ + +/* RAID Volume PageAddress format */ +#define MPI2_RAID_VOLUME_PGAD_FORM_MASK (0xF0000000) +#define MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) +#define MPI2_RAID_VOLUME_PGAD_FORM_HANDLE (0x10000000) + +#define MPI2_RAID_VOLUME_PGAD_HANDLE_MASK (0x0000FFFF) + + +/* RAID Physical Disk PageAddress format */ +#define MPI2_PHYSDISK_PGAD_FORM_MASK (0xF0000000) +#define MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM (0x00000000) +#define MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM (0x10000000) +#define MPI2_PHYSDISK_PGAD_FORM_DEVHANDLE (0x20000000) + +#define MPI2_PHYSDISK_PGAD_PHYSDISKNUM_MASK (0x000000FF) +#define MPI2_PHYSDISK_PGAD_DEVHANDLE_MASK (0x0000FFFF) + + +/* SAS Expander PageAddress format */ +#define MPI2_SAS_EXPAND_PGAD_FORM_MASK (0xF0000000) +#define MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL (0x00000000) +#define MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM (0x10000000) +#define MPI2_SAS_EXPAND_PGAD_FORM_HNDL (0x20000000) + +#define MPI2_SAS_EXPAND_PGAD_HANDLE_MASK (0x0000FFFF) +#define MPI2_SAS_EXPAND_PGAD_PHYNUM_MASK (0x00FF0000) +#define MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT (16) + + +/* SAS Device PageAddress format */ +#define MPI2_SAS_DEVICE_PGAD_FORM_MASK (0xF0000000) +#define MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) +#define MPI2_SAS_DEVICE_PGAD_FORM_HANDLE (0x20000000) + +#define MPI2_SAS_DEVICE_PGAD_HANDLE_MASK (0x0000FFFF) + + +/* SAS PHY PageAddress format */ +#define MPI2_SAS_PHY_PGAD_FORM_MASK (0xF0000000) +#define MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER (0x00000000) +#define MPI2_SAS_PHY_PGAD_FORM_PHY_TBL_INDEX (0x10000000) + +#define MPI2_SAS_PHY_PGAD_PHY_NUMBER_MASK (0x000000FF) +#define MPI2_SAS_PHY_PGAD_PHY_TBL_INDEX_MASK (0x0000FFFF) + + +/* SAS Port PageAddress format */ +#define MPI2_SASPORT_PGAD_FORM_MASK (0xF0000000) +#define MPI2_SASPORT_PGAD_FORM_GET_NEXT_PORT (0x00000000) +#define MPI2_SASPORT_PGAD_FORM_PORT_NUM (0x10000000) + +#define MPI2_SASPORT_PGAD_PORTNUMBER_MASK (0x00000FFF) + + +/* SAS Enclosure PageAddress format */ +#define MPI2_SAS_ENCLOS_PGAD_FORM_MASK (0xF0000000) +#define MPI2_SAS_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) +#define MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE (0x10000000) + +#define MPI2_SAS_ENCLOS_PGAD_HANDLE_MASK (0x0000FFFF) + + +/* RAID Configuration PageAddress format */ +#define MPI2_RAID_PGAD_FORM_MASK (0xF0000000) +#define MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM (0x00000000) +#define MPI2_RAID_PGAD_FORM_CONFIGNUM (0x10000000) +#define MPI2_RAID_PGAD_FORM_ACTIVE_CONFIG (0x20000000) + +#define MPI2_RAID_PGAD_CONFIGNUM_MASK (0x000000FF) + + +/* Driver Persistent Mapping PageAddress format */ +#define MPI2_DPM_PGAD_FORM_MASK (0xF0000000) +#define MPI2_DPM_PGAD_FORM_ENTRY_RANGE (0x00000000) + +#define MPI2_DPM_PGAD_ENTRY_COUNT_MASK (0x0FFF0000) +#define MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT (16) +#define MPI2_DPM_PGAD_START_ENTRY_MASK (0x0000FFFF) + + +/**************************************************************************** +* Configuration messages +****************************************************************************/ + +/* Configuration Request Message */ +typedef struct _MPI2_CONFIG_REQUEST +{ + U8 Action; /* 0x00 */ + U8 SGLFlags; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 ExtPageLength; /* 0x04 */ + U8 ExtPageType; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved1; /* 0x0A */ + U32 Reserved2; /* 0x0C */ + U32 Reserved3; /* 0x10 */ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x14 */ + U32 PageAddress; /* 0x18 */ + MPI2_SGE_IO_UNION PageBufferSGE; /* 0x1C */ +} MPI2_CONFIG_REQUEST, MPI2_POINTER PTR_MPI2_CONFIG_REQUEST, + Mpi2ConfigRequest_t, MPI2_POINTER pMpi2ConfigRequest_t; + +/* values for the Action field */ +#define MPI2_CONFIG_ACTION_PAGE_HEADER (0x00) +#define MPI2_CONFIG_ACTION_PAGE_READ_CURRENT (0x01) +#define MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT (0x02) +#define MPI2_CONFIG_ACTION_PAGE_DEFAULT (0x03) +#define MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM (0x04) +#define MPI2_CONFIG_ACTION_PAGE_READ_DEFAULT (0x05) +#define MPI2_CONFIG_ACTION_PAGE_READ_NVRAM (0x06) +#define MPI2_CONFIG_ACTION_PAGE_GET_CHANGEABLE (0x07) + +/* values for SGLFlags field are in the SGL section of mpi2.h */ + + +/* Config Reply Message */ +typedef struct _MPI2_CONFIG_REPLY +{ + U8 Action; /* 0x00 */ + U8 SGLFlags; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 ExtPageLength; /* 0x04 */ + U8 ExtPageType; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved1; /* 0x0A */ + U16 Reserved2; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x14 */ +} MPI2_CONFIG_REPLY, MPI2_POINTER PTR_MPI2_CONFIG_REPLY, + Mpi2ConfigReply_t, MPI2_POINTER pMpi2ConfigReply_t; + + + +/***************************************************************************** +* +* C o n f i g u r a t i o n P a g e s +* +*****************************************************************************/ + +/**************************************************************************** +* Manufacturing Config pages +****************************************************************************/ + +#define MPI2_MFGPAGE_VENDORID_LSI (0x1000) + +/* SAS */ +#define MPI2_MFGPAGE_DEVID_SAS2004 (0x0070) +#define MPI2_MFGPAGE_DEVID_SAS2008 (0x0072) +#define MPI2_MFGPAGE_DEVID_SAS2108_1 (0x0074) +#define MPI2_MFGPAGE_DEVID_SAS2108_2 (0x0076) +#define MPI2_MFGPAGE_DEVID_SAS2108_3 (0x0077) +#define MPI2_MFGPAGE_DEVID_SAS2116_1 (0x0064) +#define MPI2_MFGPAGE_DEVID_SAS2116_2 (0x0065) + + +/* Manufacturing Page 0 */ + +typedef struct _MPI2_CONFIG_PAGE_MAN_0 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U8 ChipName[16]; /* 0x04 */ + U8 ChipRevision[8]; /* 0x14 */ + U8 BoardName[16]; /* 0x1C */ + U8 BoardAssembly[16]; /* 0x2C */ + U8 BoardTracerNumber[16]; /* 0x3C */ +} MPI2_CONFIG_PAGE_MAN_0, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_0, + Mpi2ManufacturingPage0_t, MPI2_POINTER pMpi2ManufacturingPage0_t; + +#define MPI2_MANUFACTURING0_PAGEVERSION (0x00) + + +/* Manufacturing Page 1 */ + +typedef struct _MPI2_CONFIG_PAGE_MAN_1 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U8 VPD[256]; /* 0x04 */ +} MPI2_CONFIG_PAGE_MAN_1, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_1, + Mpi2ManufacturingPage1_t, MPI2_POINTER pMpi2ManufacturingPage1_t; + +#define MPI2_MANUFACTURING1_PAGEVERSION (0x00) + + +typedef struct _MPI2_CHIP_REVISION_ID +{ + U16 DeviceID; /* 0x00 */ + U8 PCIRevisionID; /* 0x02 */ + U8 Reserved; /* 0x03 */ +} MPI2_CHIP_REVISION_ID, MPI2_POINTER PTR_MPI2_CHIP_REVISION_ID, + Mpi2ChipRevisionId_t, MPI2_POINTER pMpi2ChipRevisionId_t; + + +/* Manufacturing Page 2 */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.PageLength at runtime. + */ +#ifndef MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS +#define MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_MAN_2 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + MPI2_CHIP_REVISION_ID ChipId; /* 0x04 */ + U32 HwSettings[MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS];/* 0x08 */ +} MPI2_CONFIG_PAGE_MAN_2, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_2, + Mpi2ManufacturingPage2_t, MPI2_POINTER pMpi2ManufacturingPage2_t; + +#define MPI2_MANUFACTURING2_PAGEVERSION (0x00) + + +/* Manufacturing Page 3 */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.PageLength at runtime. + */ +#ifndef MPI2_MAN_PAGE_3_INFO_WORDS +#define MPI2_MAN_PAGE_3_INFO_WORDS (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_MAN_3 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + MPI2_CHIP_REVISION_ID ChipId; /* 0x04 */ + U32 Info[MPI2_MAN_PAGE_3_INFO_WORDS];/* 0x08 */ +} MPI2_CONFIG_PAGE_MAN_3, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_3, + Mpi2ManufacturingPage3_t, MPI2_POINTER pMpi2ManufacturingPage3_t; + +#define MPI2_MANUFACTURING3_PAGEVERSION (0x00) + + +/* Manufacturing Page 4 */ + +typedef struct _MPI2_MANPAGE4_PWR_SAVE_SETTINGS +{ + U8 PowerSaveFlags; /* 0x00 */ + U8 InternalOperationsSleepTime; /* 0x01 */ + U8 InternalOperationsRunTime; /* 0x02 */ + U8 HostIdleTime; /* 0x03 */ +} MPI2_MANPAGE4_PWR_SAVE_SETTINGS, + MPI2_POINTER PTR_MPI2_MANPAGE4_PWR_SAVE_SETTINGS, + Mpi2ManPage4PwrSaveSettings_t, MPI2_POINTER pMpi2ManPage4PwrSaveSettings_t; + +/* defines for the PowerSaveFlags field */ +#define MPI2_MANPAGE4_MASK_POWERSAVE_MODE (0x03) +#define MPI2_MANPAGE4_POWERSAVE_MODE_DISABLED (0x00) +#define MPI2_MANPAGE4_CUSTOM_POWERSAVE_MODE (0x01) +#define MPI2_MANPAGE4_FULL_POWERSAVE_MODE (0x02) + +typedef struct _MPI2_CONFIG_PAGE_MAN_4 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x04 */ + U32 Flags; /* 0x08 */ + U8 InquirySize; /* 0x0C */ + U8 Reserved2; /* 0x0D */ + U16 Reserved3; /* 0x0E */ + U8 InquiryData[56]; /* 0x10 */ + U32 RAID0VolumeSettings; /* 0x48 */ + U32 RAID1EVolumeSettings; /* 0x4C */ + U32 RAID1VolumeSettings; /* 0x50 */ + U32 RAID10VolumeSettings; /* 0x54 */ + U32 Reserved4; /* 0x58 */ + U32 Reserved5; /* 0x5C */ + MPI2_MANPAGE4_PWR_SAVE_SETTINGS PowerSaveSettings; /* 0x60 */ + U8 MaxOCEDisks; /* 0x64 */ + U8 ResyncRate; /* 0x65 */ + U16 DataScrubDuration; /* 0x66 */ + U8 MaxHotSpares; /* 0x68 */ + U8 MaxPhysDisksPerVol; /* 0x69 */ + U8 MaxPhysDisks; /* 0x6A */ + U8 MaxVolumes; /* 0x6B */ +} MPI2_CONFIG_PAGE_MAN_4, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_4, + Mpi2ManufacturingPage4_t, MPI2_POINTER pMpi2ManufacturingPage4_t; + +#define MPI2_MANUFACTURING4_PAGEVERSION (0x0A) + +/* Manufacturing Page 4 Flags field */ +#define MPI2_MANPAGE4_METADATA_SIZE_MASK (0x00030000) +#define MPI2_MANPAGE4_METADATA_512MB (0x00000000) + +#define MPI2_MANPAGE4_MIX_SSD_SAS_SATA (0x00008000) +#define MPI2_MANPAGE4_MIX_SSD_AND_NON_SSD (0x00004000) +#define MPI2_MANPAGE4_HIDE_PHYSDISK_NON_IR (0x00002000) + +#define MPI2_MANPAGE4_MASK_PHYSDISK_COERCION (0x00001C00) +#define MPI2_MANPAGE4_PHYSDISK_COERCION_1GB (0x00000000) +#define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION (0x00000400) +#define MPI2_MANPAGE4_PHYSDISK_ADAPTIVE_COERCION (0x00000800) +#define MPI2_MANPAGE4_PHYSDISK_ZERO_COERCION (0x00000C00) + +#define MPI2_MANPAGE4_MASK_BAD_BLOCK_MARKING (0x00000300) +#define MPI2_MANPAGE4_DEFAULT_BAD_BLOCK_MARKING (0x00000000) +#define MPI2_MANPAGE4_TABLE_BAD_BLOCK_MARKING (0x00000100) +#define MPI2_MANPAGE4_WRITE_LONG_BAD_BLOCK_MARKING (0x00000200) + +#define MPI2_MANPAGE4_FORCE_OFFLINE_FAILOVER (0x00000080) +#define MPI2_MANPAGE4_RAID10_DISABLE (0x00000040) +#define MPI2_MANPAGE4_RAID1E_DISABLE (0x00000020) +#define MPI2_MANPAGE4_RAID1_DISABLE (0x00000010) +#define MPI2_MANPAGE4_RAID0_DISABLE (0x00000008) +#define MPI2_MANPAGE4_IR_MODEPAGE8_DISABLE (0x00000004) +#define MPI2_MANPAGE4_IM_RESYNC_CACHE_ENABLE (0x00000002) +#define MPI2_MANPAGE4_IR_NO_MIX_SAS_SATA (0x00000001) + + +/* Manufacturing Page 5 */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.PageLength or NumPhys at runtime. + */ +#ifndef MPI2_MAN_PAGE_5_PHY_ENTRIES +#define MPI2_MAN_PAGE_5_PHY_ENTRIES (1) +#endif + +typedef struct _MPI2_MANUFACTURING5_ENTRY +{ + U64 WWID; /* 0x00 */ + U64 DeviceName; /* 0x08 */ +} MPI2_MANUFACTURING5_ENTRY, MPI2_POINTER PTR_MPI2_MANUFACTURING5_ENTRY, + Mpi2Manufacturing5Entry_t, MPI2_POINTER pMpi2Manufacturing5Entry_t; + +typedef struct _MPI2_CONFIG_PAGE_MAN_5 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U8 NumPhys; /* 0x04 */ + U8 Reserved1; /* 0x05 */ + U16 Reserved2; /* 0x06 */ + U32 Reserved3; /* 0x08 */ + U32 Reserved4; /* 0x0C */ + MPI2_MANUFACTURING5_ENTRY Phy[MPI2_MAN_PAGE_5_PHY_ENTRIES];/* 0x08 */ +} MPI2_CONFIG_PAGE_MAN_5, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_5, + Mpi2ManufacturingPage5_t, MPI2_POINTER pMpi2ManufacturingPage5_t; + +#define MPI2_MANUFACTURING5_PAGEVERSION (0x03) + + +/* Manufacturing Page 6 */ + +typedef struct _MPI2_CONFIG_PAGE_MAN_6 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 ProductSpecificInfo;/* 0x04 */ +} MPI2_CONFIG_PAGE_MAN_6, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_6, + Mpi2ManufacturingPage6_t, MPI2_POINTER pMpi2ManufacturingPage6_t; + +#define MPI2_MANUFACTURING6_PAGEVERSION (0x00) + + +/* Manufacturing Page 7 */ + +typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO +{ + U32 Pinout; /* 0x00 */ + U8 Connector[16]; /* 0x04 */ + U8 Location; /* 0x14 */ + U8 Reserved1; /* 0x15 */ + U16 Slot; /* 0x16 */ + U32 Reserved2; /* 0x18 */ +} MPI2_MANPAGE7_CONNECTOR_INFO, MPI2_POINTER PTR_MPI2_MANPAGE7_CONNECTOR_INFO, + Mpi2ManPage7ConnectorInfo_t, MPI2_POINTER pMpi2ManPage7ConnectorInfo_t; + +/* defines for the Pinout field */ +#define MPI2_MANPAGE7_PINOUT_SFF_8484_L4 (0x00080000) +#define MPI2_MANPAGE7_PINOUT_SFF_8484_L3 (0x00040000) +#define MPI2_MANPAGE7_PINOUT_SFF_8484_L2 (0x00020000) +#define MPI2_MANPAGE7_PINOUT_SFF_8484_L1 (0x00010000) +#define MPI2_MANPAGE7_PINOUT_SFF_8470_L4 (0x00000800) +#define MPI2_MANPAGE7_PINOUT_SFF_8470_L3 (0x00000400) +#define MPI2_MANPAGE7_PINOUT_SFF_8470_L2 (0x00000200) +#define MPI2_MANPAGE7_PINOUT_SFF_8470_L1 (0x00000100) +#define MPI2_MANPAGE7_PINOUT_SFF_8482 (0x00000002) +#define MPI2_MANPAGE7_PINOUT_CONNECTION_UNKNOWN (0x00000001) + +/* defines for the Location field */ +#define MPI2_MANPAGE7_LOCATION_UNKNOWN (0x01) +#define MPI2_MANPAGE7_LOCATION_INTERNAL (0x02) +#define MPI2_MANPAGE7_LOCATION_EXTERNAL (0x04) +#define MPI2_MANPAGE7_LOCATION_SWITCHABLE (0x08) +#define MPI2_MANPAGE7_LOCATION_AUTO (0x10) +#define MPI2_MANPAGE7_LOCATION_NOT_PRESENT (0x20) +#define MPI2_MANPAGE7_LOCATION_NOT_CONNECTED (0x80) + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check NumPhys at runtime. + */ +#ifndef MPI2_MANPAGE7_CONNECTOR_INFO_MAX +#define MPI2_MANPAGE7_CONNECTOR_INFO_MAX (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_MAN_7 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x04 */ + U32 Reserved2; /* 0x08 */ + U32 Flags; /* 0x0C */ + U8 EnclosureName[16]; /* 0x10 */ + U8 NumPhys; /* 0x20 */ + U8 Reserved3; /* 0x21 */ + U16 Reserved4; /* 0x22 */ + MPI2_MANPAGE7_CONNECTOR_INFO ConnectorInfo[MPI2_MANPAGE7_CONNECTOR_INFO_MAX]; /* 0x24 */ +} MPI2_CONFIG_PAGE_MAN_7, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_7, + Mpi2ManufacturingPage7_t, MPI2_POINTER pMpi2ManufacturingPage7_t; + +#define MPI2_MANUFACTURING7_PAGEVERSION (0x00) + +/* defines for the Flags field */ +#define MPI2_MANPAGE7_FLAG_USE_SLOT_INFO (0x00000001) + + +/* + * Generic structure to use for product-specific manufacturing pages + * (currently Manufacturing Page 8 through Manufacturing Page 31). + */ + +typedef struct _MPI2_CONFIG_PAGE_MAN_PS +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 ProductSpecificInfo;/* 0x04 */ +} MPI2_CONFIG_PAGE_MAN_PS, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_PS, + Mpi2ManufacturingPagePS_t, MPI2_POINTER pMpi2ManufacturingPagePS_t; + +#define MPI2_MANUFACTURING8_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING9_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING10_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING11_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING12_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING13_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING14_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING15_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING16_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING17_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING18_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING19_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING20_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING21_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING22_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING23_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING24_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING25_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING26_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING27_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING28_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING29_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING30_PAGEVERSION (0x00) +#define MPI2_MANUFACTURING31_PAGEVERSION (0x00) + + +/**************************************************************************** +* IO Unit Config Pages +****************************************************************************/ + +/* IO Unit Page 0 */ + +typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_0 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U64 UniqueValue; /* 0x04 */ + MPI2_VERSION_UNION NvdataVersionDefault; /* 0x08 */ + MPI2_VERSION_UNION NvdataVersionPersistent; /* 0x0A */ +} MPI2_CONFIG_PAGE_IO_UNIT_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_0, + Mpi2IOUnitPage0_t, MPI2_POINTER pMpi2IOUnitPage0_t; + +#define MPI2_IOUNITPAGE0_PAGEVERSION (0x02) + + +/* IO Unit Page 1 */ + +typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_1 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 Flags; /* 0x04 */ +} MPI2_CONFIG_PAGE_IO_UNIT_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_1, + Mpi2IOUnitPage1_t, MPI2_POINTER pMpi2IOUnitPage1_t; + +#define MPI2_IOUNITPAGE1_PAGEVERSION (0x04) + +/* IO Unit Page 1 Flags defines */ +#define MPI2_IOUNITPAGE1_MASK_SATA_WRITE_CACHE (0x00000600) +#define MPI2_IOUNITPAGE1_ENABLE_SATA_WRITE_CACHE (0x00000000) +#define MPI2_IOUNITPAGE1_DISABLE_SATA_WRITE_CACHE (0x00000200) +#define MPI2_IOUNITPAGE1_UNCHANGED_SATA_WRITE_CACHE (0x00000400) +#define MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE (0x00000100) +#define MPI2_IOUNITPAGE1_DISABLE_IR (0x00000040) +#define MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING (0x00000020) +#define MPI2_IOUNITPAGE1_IR_USE_STATIC_VOLUME_ID (0x00000004) +#define MPI2_IOUNITPAGE1_MULTI_PATHING (0x00000002) +#define MPI2_IOUNITPAGE1_SINGLE_PATHING (0x00000000) + + +/* IO Unit Page 3 */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.PageLength at runtime. + */ +#ifndef MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX +#define MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_3 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U8 GPIOCount; /* 0x04 */ + U8 Reserved1; /* 0x05 */ + U16 Reserved2; /* 0x06 */ + U16 GPIOVal[MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX];/* 0x08 */ +} MPI2_CONFIG_PAGE_IO_UNIT_3, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_3, + Mpi2IOUnitPage3_t, MPI2_POINTER pMpi2IOUnitPage3_t; + +#define MPI2_IOUNITPAGE3_PAGEVERSION (0x01) + +/* defines for IO Unit Page 3 GPIOVal field */ +#define MPI2_IOUNITPAGE3_GPIO_FUNCTION_MASK (0xFFFC) +#define MPI2_IOUNITPAGE3_GPIO_FUNCTION_SHIFT (2) +#define MPI2_IOUNITPAGE3_GPIO_SETTING_OFF (0x0000) +#define MPI2_IOUNITPAGE3_GPIO_SETTING_ON (0x0001) + + +/**************************************************************************** +* IOC Config Pages +****************************************************************************/ + +/* IOC Page 0 */ + +typedef struct _MPI2_CONFIG_PAGE_IOC_0 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x04 */ + U32 Reserved2; /* 0x08 */ + U16 VendorID; /* 0x0C */ + U16 DeviceID; /* 0x0E */ + U8 RevisionID; /* 0x10 */ + U8 Reserved3; /* 0x11 */ + U16 Reserved4; /* 0x12 */ + U32 ClassCode; /* 0x14 */ + U16 SubsystemVendorID; /* 0x18 */ + U16 SubsystemID; /* 0x1A */ +} MPI2_CONFIG_PAGE_IOC_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_0, + Mpi2IOCPage0_t, MPI2_POINTER pMpi2IOCPage0_t; + +#define MPI2_IOCPAGE0_PAGEVERSION (0x02) + + +/* IOC Page 1 */ + +typedef struct _MPI2_CONFIG_PAGE_IOC_1 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 Flags; /* 0x04 */ + U32 CoalescingTimeout; /* 0x08 */ + U8 CoalescingDepth; /* 0x0C */ + U8 PCISlotNum; /* 0x0D */ + U8 PCIBusNum; /* 0x0E */ + U8 PCIDomainSegment; /* 0x0F */ + U32 Reserved1; /* 0x10 */ + U32 Reserved2; /* 0x14 */ +} MPI2_CONFIG_PAGE_IOC_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_1, + Mpi2IOCPage1_t, MPI2_POINTER pMpi2IOCPage1_t; + +#define MPI2_IOCPAGE1_PAGEVERSION (0x05) + +/* defines for IOC Page 1 Flags field */ +#define MPI2_IOCPAGE1_REPLY_COALESCING (0x00000001) + +#define MPI2_IOCPAGE1_PCISLOTNUM_UNKNOWN (0xFF) +#define MPI2_IOCPAGE1_PCIBUSNUM_UNKNOWN (0xFF) +#define MPI2_IOCPAGE1_PCIDOMAIN_UNKNOWN (0xFF) + +/* IOC Page 6 */ + +typedef struct _MPI2_CONFIG_PAGE_IOC_6 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 CapabilitiesFlags; /* 0x04 */ + U8 MaxDrivesRAID0; /* 0x08 */ + U8 MaxDrivesRAID1; /* 0x09 */ + U8 MaxDrivesRAID1E; /* 0x0A */ + U8 MaxDrivesRAID10; /* 0x0B */ + U8 MinDrivesRAID0; /* 0x0C */ + U8 MinDrivesRAID1; /* 0x0D */ + U8 MinDrivesRAID1E; /* 0x0E */ + U8 MinDrivesRAID10; /* 0x0F */ + U32 Reserved1; /* 0x10 */ + U8 MaxGlobalHotSpares; /* 0x14 */ + U8 MaxPhysDisks; /* 0x15 */ + U8 MaxVolumes; /* 0x16 */ + U8 MaxConfigs; /* 0x17 */ + U8 MaxOCEDisks; /* 0x18 */ + U8 Reserved2; /* 0x19 */ + U16 Reserved3; /* 0x1A */ + U32 SupportedStripeSizeMapRAID0; /* 0x1C */ + U32 SupportedStripeSizeMapRAID1E; /* 0x20 */ + U32 SupportedStripeSizeMapRAID10; /* 0x24 */ + U32 Reserved4; /* 0x28 */ + U32 Reserved5; /* 0x2C */ + U16 DefaultMetadataSize; /* 0x30 */ + U16 Reserved6; /* 0x32 */ + U16 MaxBadBlockTableEntries; /* 0x34 */ + U16 Reserved7; /* 0x36 */ + U32 IRNvsramVersion; /* 0x38 */ +} MPI2_CONFIG_PAGE_IOC_6, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_6, + Mpi2IOCPage6_t, MPI2_POINTER pMpi2IOCPage6_t; + +#define MPI2_IOCPAGE6_PAGEVERSION (0x04) + +/* defines for IOC Page 6 CapabilitiesFlags */ +#define MPI2_IOCPAGE6_CAP_FLAGS_RAID10_SUPPORT (0x00000010) +#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1_SUPPORT (0x00000008) +#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1E_SUPPORT (0x00000004) +#define MPI2_IOCPAGE6_CAP_FLAGS_RAID0_SUPPORT (0x00000002) +#define MPI2_IOCPAGE6_CAP_FLAGS_GLOBAL_HOT_SPARE (0x00000001) + + +/* IOC Page 7 */ + +#define MPI2_IOCPAGE7_EVENTMASK_WORDS (4) + +typedef struct _MPI2_CONFIG_PAGE_IOC_7 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x04 */ + U32 EventMasks[MPI2_IOCPAGE7_EVENTMASK_WORDS];/* 0x08 */ + U16 SASBroadcastPrimitiveMasks; /* 0x18 */ + U16 Reserved2; /* 0x1A */ + U32 Reserved3; /* 0x1C */ +} MPI2_CONFIG_PAGE_IOC_7, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_7, + Mpi2IOCPage7_t, MPI2_POINTER pMpi2IOCPage7_t; + +#define MPI2_IOCPAGE7_PAGEVERSION (0x01) + + +/* IOC Page 8 */ + +typedef struct _MPI2_CONFIG_PAGE_IOC_8 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U8 NumDevsPerEnclosure; /* 0x04 */ + U8 Reserved1; /* 0x05 */ + U16 Reserved2; /* 0x06 */ + U16 MaxPersistentEntries; /* 0x08 */ + U16 MaxNumPhysicalMappedIDs; /* 0x0A */ + U16 Flags; /* 0x0C */ + U16 Reserved3; /* 0x0E */ + U16 IRVolumeMappingFlags; /* 0x10 */ + U16 Reserved4; /* 0x12 */ + U32 Reserved5; /* 0x14 */ +} MPI2_CONFIG_PAGE_IOC_8, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_8, + Mpi2IOCPage8_t, MPI2_POINTER pMpi2IOCPage8_t; + +#define MPI2_IOCPAGE8_PAGEVERSION (0x00) + +/* defines for IOC Page 8 Flags field */ +#define MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1 (0x00000020) +#define MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0 (0x00000010) + +#define MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE (0x0000000E) +#define MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING (0x00000000) +#define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING (0x00000002) + +#define MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING (0x00000001) +#define MPI2_IOCPAGE8_FLAGS_ENABLE_PERSISTENT_MAPPING (0x00000000) + +/* defines for IOC Page 8 IRVolumeMappingFlags */ +#define MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE (0x00000003) +#define MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING (0x00000000) +#define MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING (0x00000001) + + +/**************************************************************************** +* BIOS Config Pages +****************************************************************************/ + +/* BIOS Page 1 */ + +typedef struct _MPI2_CONFIG_PAGE_BIOS_1 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 BiosOptions; /* 0x04 */ + U32 IOCSettings; /* 0x08 */ + U32 Reserved1; /* 0x0C */ + U32 DeviceSettings; /* 0x10 */ + U16 NumberOfDevices; /* 0x14 */ + U16 Reserved2; /* 0x16 */ + U16 IOTimeoutBlockDevicesNonRM; /* 0x18 */ + U16 IOTimeoutSequential; /* 0x1A */ + U16 IOTimeoutOther; /* 0x1C */ + U16 IOTimeoutBlockDevicesRM; /* 0x1E */ +} MPI2_CONFIG_PAGE_BIOS_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_1, + Mpi2BiosPage1_t, MPI2_POINTER pMpi2BiosPage1_t; + +#define MPI2_BIOSPAGE1_PAGEVERSION (0x04) + +/* values for BIOS Page 1 BiosOptions field */ +#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001) + +/* values for BIOS Page 1 IOCSettings field */ +#define MPI2_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000) +#define MPI2_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT (0x00000000) +#define MPI2_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT (0x00010000) + +#define MPI2_BIOSPAGE1_IOCSET_MASK_RM_SETTING (0x000000C0) +#define MPI2_BIOSPAGE1_IOCSET_NONE_RM_SETTING (0x00000000) +#define MPI2_BIOSPAGE1_IOCSET_BOOT_RM_SETTING (0x00000040) +#define MPI2_BIOSPAGE1_IOCSET_MEDIA_RM_SETTING (0x00000080) + +#define MPI2_BIOSPAGE1_IOCSET_MASK_ADAPTER_SUPPORT (0x00000030) +#define MPI2_BIOSPAGE1_IOCSET_NO_SUPPORT (0x00000000) +#define MPI2_BIOSPAGE1_IOCSET_BIOS_SUPPORT (0x00000010) +#define MPI2_BIOSPAGE1_IOCSET_OS_SUPPORT (0x00000020) +#define MPI2_BIOSPAGE1_IOCSET_ALL_SUPPORT (0x00000030) + +#define MPI2_BIOSPAGE1_IOCSET_ALTERNATE_CHS (0x00000008) + +/* values for BIOS Page 1 DeviceSettings field */ +#define MPI2_BIOSPAGE1_DEVSET_DISABLE_SMART_POLLING (0x00000010) +#define MPI2_BIOSPAGE1_DEVSET_DISABLE_SEQ_LUN (0x00000008) +#define MPI2_BIOSPAGE1_DEVSET_DISABLE_RM_LUN (0x00000004) +#define MPI2_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN (0x00000002) +#define MPI2_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN (0x00000001) + + +/* BIOS Page 2 */ + +typedef struct _MPI2_BOOT_DEVICE_ADAPTER_ORDER +{ + U32 Reserved1; /* 0x00 */ + U32 Reserved2; /* 0x04 */ + U32 Reserved3; /* 0x08 */ + U32 Reserved4; /* 0x0C */ + U32 Reserved5; /* 0x10 */ + U32 Reserved6; /* 0x14 */ +} MPI2_BOOT_DEVICE_ADAPTER_ORDER, + MPI2_POINTER PTR_MPI2_BOOT_DEVICE_ADAPTER_ORDER, + Mpi2BootDeviceAdapterOrder_t, MPI2_POINTER pMpi2BootDeviceAdapterOrder_t; + +typedef struct _MPI2_BOOT_DEVICE_SAS_WWID +{ + U64 SASAddress; /* 0x00 */ + U8 LUN[8]; /* 0x08 */ + U32 Reserved1; /* 0x10 */ + U32 Reserved2; /* 0x14 */ +} MPI2_BOOT_DEVICE_SAS_WWID, MPI2_POINTER PTR_MPI2_BOOT_DEVICE_SAS_WWID, + Mpi2BootDeviceSasWwid_t, MPI2_POINTER pMpi2BootDeviceSasWwid_t; + +typedef struct _MPI2_BOOT_DEVICE_ENCLOSURE_SLOT +{ + U64 EnclosureLogicalID; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U32 Reserved2; /* 0x0C */ + U16 SlotNumber; /* 0x10 */ + U16 Reserved3; /* 0x12 */ + U32 Reserved4; /* 0x14 */ +} MPI2_BOOT_DEVICE_ENCLOSURE_SLOT, + MPI2_POINTER PTR_MPI2_BOOT_DEVICE_ENCLOSURE_SLOT, + Mpi2BootDeviceEnclosureSlot_t, MPI2_POINTER pMpi2BootDeviceEnclosureSlot_t; + +typedef struct _MPI2_BOOT_DEVICE_DEVICE_NAME +{ + U64 DeviceName; /* 0x00 */ + U8 LUN[8]; /* 0x08 */ + U32 Reserved1; /* 0x10 */ + U32 Reserved2; /* 0x14 */ +} MPI2_BOOT_DEVICE_DEVICE_NAME, MPI2_POINTER PTR_MPI2_BOOT_DEVICE_DEVICE_NAME, + Mpi2BootDeviceDeviceName_t, MPI2_POINTER pMpi2BootDeviceDeviceName_t; + +typedef union _MPI2_MPI2_BIOSPAGE2_BOOT_DEVICE +{ + MPI2_BOOT_DEVICE_ADAPTER_ORDER AdapterOrder; + MPI2_BOOT_DEVICE_SAS_WWID SasWwid; + MPI2_BOOT_DEVICE_ENCLOSURE_SLOT EnclosureSlot; + MPI2_BOOT_DEVICE_DEVICE_NAME DeviceName; +} MPI2_BIOSPAGE2_BOOT_DEVICE, MPI2_POINTER PTR_MPI2_BIOSPAGE2_BOOT_DEVICE, + Mpi2BiosPage2BootDevice_t, MPI2_POINTER pMpi2BiosPage2BootDevice_t; + +typedef struct _MPI2_CONFIG_PAGE_BIOS_2 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x04 */ + U32 Reserved2; /* 0x08 */ + U32 Reserved3; /* 0x0C */ + U32 Reserved4; /* 0x10 */ + U32 Reserved5; /* 0x14 */ + U32 Reserved6; /* 0x18 */ + U8 ReqBootDeviceForm; /* 0x1C */ + U8 Reserved7; /* 0x1D */ + U16 Reserved8; /* 0x1E */ + MPI2_BIOSPAGE2_BOOT_DEVICE RequestedBootDevice; /* 0x20 */ + U8 ReqAltBootDeviceForm; /* 0x38 */ + U8 Reserved9; /* 0x39 */ + U16 Reserved10; /* 0x3A */ + MPI2_BIOSPAGE2_BOOT_DEVICE RequestedAltBootDevice; /* 0x3C */ + U8 CurrentBootDeviceForm; /* 0x58 */ + U8 Reserved11; /* 0x59 */ + U16 Reserved12; /* 0x5A */ + MPI2_BIOSPAGE2_BOOT_DEVICE CurrentBootDevice; /* 0x58 */ +} MPI2_CONFIG_PAGE_BIOS_2, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_2, + Mpi2BiosPage2_t, MPI2_POINTER pMpi2BiosPage2_t; + +#define MPI2_BIOSPAGE2_PAGEVERSION (0x04) + +/* values for BIOS Page 2 BootDeviceForm fields */ +#define MPI2_BIOSPAGE2_FORM_MASK (0x0F) +#define MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED (0x00) +#define MPI2_BIOSPAGE2_FORM_SAS_WWID (0x05) +#define MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT (0x06) +#define MPI2_BIOSPAGE2_FORM_DEVICE_NAME (0x07) + + +/* BIOS Page 3 */ + +typedef struct _MPI2_ADAPTER_INFO +{ + U8 PciBusNumber; /* 0x00 */ + U8 PciDeviceAndFunctionNumber; /* 0x01 */ + U16 AdapterFlags; /* 0x02 */ +} MPI2_ADAPTER_INFO, MPI2_POINTER PTR_MPI2_ADAPTER_INFO, + Mpi2AdapterInfo_t, MPI2_POINTER pMpi2AdapterInfo_t; + +#define MPI2_ADAPTER_INFO_FLAGS_EMBEDDED (0x0001) +#define MPI2_ADAPTER_INFO_FLAGS_INIT_STATUS (0x0002) + +typedef struct _MPI2_CONFIG_PAGE_BIOS_3 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 GlobalFlags; /* 0x04 */ + U32 BiosVersion; /* 0x08 */ + MPI2_ADAPTER_INFO AdapterOrder[4]; /* 0x0C */ + U32 Reserved1; /* 0x1C */ +} MPI2_CONFIG_PAGE_BIOS_3, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_3, + Mpi2BiosPage3_t, MPI2_POINTER pMpi2BiosPage3_t; + +#define MPI2_BIOSPAGE3_PAGEVERSION (0x00) + +/* values for BIOS Page 3 GlobalFlags */ +#define MPI2_BIOSPAGE3_FLAGS_PAUSE_ON_ERROR (0x00000002) +#define MPI2_BIOSPAGE3_FLAGS_VERBOSE_ENABLE (0x00000004) +#define MPI2_BIOSPAGE3_FLAGS_HOOK_INT_40_DISABLE (0x00000010) + +#define MPI2_BIOSPAGE3_FLAGS_DEV_LIST_DISPLAY_MASK (0x000000E0) +#define MPI2_BIOSPAGE3_FLAGS_INSTALLED_DEV_DISPLAY (0x00000000) +#define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DISPLAY (0x00000020) +#define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DEV_DISPLAY (0x00000040) + + +/* BIOS Page 4 */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.PageLength or NumPhys at runtime. + */ +#ifndef MPI2_BIOS_PAGE_4_PHY_ENTRIES +#define MPI2_BIOS_PAGE_4_PHY_ENTRIES (1) +#endif + +typedef struct _MPI2_BIOS4_ENTRY +{ + U64 ReassignmentWWID; /* 0x00 */ + U64 ReassignmentDeviceName; /* 0x08 */ +} MPI2_BIOS4_ENTRY, MPI2_POINTER PTR_MPI2_BIOS4_ENTRY, + Mpi2MBios4Entry_t, MPI2_POINTER pMpi2Bios4Entry_t; + +typedef struct _MPI2_CONFIG_PAGE_BIOS_4 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U8 NumPhys; /* 0x04 */ + U8 Reserved1; /* 0x05 */ + U16 Reserved2; /* 0x06 */ + MPI2_BIOS4_ENTRY Phy[MPI2_BIOS_PAGE_4_PHY_ENTRIES]; /* 0x08 */ +} MPI2_CONFIG_PAGE_BIOS_4, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_4, + Mpi2BiosPage4_t, MPI2_POINTER pMpi2BiosPage4_t; + +#define MPI2_BIOSPAGE4_PAGEVERSION (0x01) + + +/**************************************************************************** +* RAID Volume Config Pages +****************************************************************************/ + +/* RAID Volume Page 0 */ + +typedef struct _MPI2_RAIDVOL0_PHYS_DISK +{ + U8 RAIDSetNum; /* 0x00 */ + U8 PhysDiskMap; /* 0x01 */ + U8 PhysDiskNum; /* 0x02 */ + U8 Reserved; /* 0x03 */ +} MPI2_RAIDVOL0_PHYS_DISK, MPI2_POINTER PTR_MPI2_RAIDVOL0_PHYS_DISK, + Mpi2RaidVol0PhysDisk_t, MPI2_POINTER pMpi2RaidVol0PhysDisk_t; + +/* defines for the PhysDiskMap field */ +#define MPI2_RAIDVOL0_PHYSDISK_PRIMARY (0x01) +#define MPI2_RAIDVOL0_PHYSDISK_SECONDARY (0x02) + +typedef struct _MPI2_RAIDVOL0_SETTINGS +{ + U16 Settings; /* 0x00 */ + U8 HotSparePool; /* 0x01 */ + U8 Reserved; /* 0x02 */ +} MPI2_RAIDVOL0_SETTINGS, MPI2_POINTER PTR_MPI2_RAIDVOL0_SETTINGS, + Mpi2RaidVol0Settings_t, MPI2_POINTER pMpi2RaidVol0Settings_t; + +/* RAID Volume Page 0 HotSparePool defines, also used in RAID Physical Disk */ +#define MPI2_RAID_HOT_SPARE_POOL_0 (0x01) +#define MPI2_RAID_HOT_SPARE_POOL_1 (0x02) +#define MPI2_RAID_HOT_SPARE_POOL_2 (0x04) +#define MPI2_RAID_HOT_SPARE_POOL_3 (0x08) +#define MPI2_RAID_HOT_SPARE_POOL_4 (0x10) +#define MPI2_RAID_HOT_SPARE_POOL_5 (0x20) +#define MPI2_RAID_HOT_SPARE_POOL_6 (0x40) +#define MPI2_RAID_HOT_SPARE_POOL_7 (0x80) + +/* RAID Volume Page 0 VolumeSettings defines */ +#define MPI2_RAIDVOL0_SETTING_USE_PRODUCT_ID_SUFFIX (0x0008) +#define MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE (0x0004) + +#define MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING (0x0003) +#define MPI2_RAIDVOL0_SETTING_UNCHANGED (0x0000) +#define MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING (0x0001) +#define MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING (0x0002) + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.PageLength at runtime. + */ +#ifndef MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX +#define MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_0 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U16 DevHandle; /* 0x04 */ + U8 VolumeState; /* 0x06 */ + U8 VolumeType; /* 0x07 */ + U32 VolumeStatusFlags; /* 0x08 */ + MPI2_RAIDVOL0_SETTINGS VolumeSettings; /* 0x0C */ + U64 MaxLBA; /* 0x10 */ + U32 StripeSize; /* 0x18 */ + U16 BlockSize; /* 0x1C */ + U16 Reserved1; /* 0x1E */ + U8 SupportedPhysDisks; /* 0x20 */ + U8 ResyncRate; /* 0x21 */ + U16 DataScrubDuration; /* 0x22 */ + U8 NumPhysDisks; /* 0x24 */ + U8 Reserved2; /* 0x25 */ + U8 Reserved3; /* 0x26 */ + U8 InactiveStatus; /* 0x27 */ + MPI2_RAIDVOL0_PHYS_DISK PhysDisk[MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX]; /* 0x28 */ +} MPI2_CONFIG_PAGE_RAID_VOL_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_VOL_0, + Mpi2RaidVolPage0_t, MPI2_POINTER pMpi2RaidVolPage0_t; + +#define MPI2_RAIDVOLPAGE0_PAGEVERSION (0x0A) + +/* values for RAID VolumeState */ +#define MPI2_RAID_VOL_STATE_MISSING (0x00) +#define MPI2_RAID_VOL_STATE_FAILED (0x01) +#define MPI2_RAID_VOL_STATE_INITIALIZING (0x02) +#define MPI2_RAID_VOL_STATE_ONLINE (0x03) +#define MPI2_RAID_VOL_STATE_DEGRADED (0x04) +#define MPI2_RAID_VOL_STATE_OPTIMAL (0x05) + +/* values for RAID VolumeType */ +#define MPI2_RAID_VOL_TYPE_RAID0 (0x00) +#define MPI2_RAID_VOL_TYPE_RAID1E (0x01) +#define MPI2_RAID_VOL_TYPE_RAID1 (0x02) +#define MPI2_RAID_VOL_TYPE_RAID10 (0x05) +#define MPI2_RAID_VOL_TYPE_UNKNOWN (0xFF) + +/* values for RAID Volume Page 0 VolumeStatusFlags field */ +#define MPI2_RAIDVOL0_STATUS_FLAG_PENDING_RESYNC (0x02000000) +#define MPI2_RAIDVOL0_STATUS_FLAG_BACKG_INIT_PENDING (0x01000000) +#define MPI2_RAIDVOL0_STATUS_FLAG_MDC_PENDING (0x00800000) +#define MPI2_RAIDVOL0_STATUS_FLAG_USER_CONSIST_PENDING (0x00400000) +#define MPI2_RAIDVOL0_STATUS_FLAG_MAKE_DATA_CONSISTENT (0x00200000) +#define MPI2_RAIDVOL0_STATUS_FLAG_DATA_SCRUB (0x00100000) +#define MPI2_RAIDVOL0_STATUS_FLAG_CONSISTENCY_CHECK (0x00080000) +#define MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION (0x00040000) +#define MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT (0x00020000) +#define MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS (0x00010000) +#define MPI2_RAIDVOL0_STATUS_FLAG_OCE_ALLOWED (0x00000040) +#define MPI2_RAIDVOL0_STATUS_FLAG_BGI_COMPLETE (0x00000020) +#define MPI2_RAIDVOL0_STATUS_FLAG_1E_OFFSET_MIRROR (0x00000000) +#define MPI2_RAIDVOL0_STATUS_FLAG_1E_ADJACENT_MIRROR (0x00000010) +#define MPI2_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL (0x00000008) +#define MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE (0x00000004) +#define MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED (0x00000002) +#define MPI2_RAIDVOL0_STATUS_FLAG_ENABLED (0x00000001) + +/* values for RAID Volume Page 0 SupportedPhysDisks field */ +#define MPI2_RAIDVOL0_SUPPORT_SOLID_STATE_DISKS (0x08) +#define MPI2_RAIDVOL0_SUPPORT_HARD_DISKS (0x04) +#define MPI2_RAIDVOL0_SUPPORT_SAS_PROTOCOL (0x02) +#define MPI2_RAIDVOL0_SUPPORT_SATA_PROTOCOL (0x01) + +/* values for RAID Volume Page 0 InactiveStatus field */ +#define MPI2_RAIDVOLPAGE0_UNKNOWN_INACTIVE (0x00) +#define MPI2_RAIDVOLPAGE0_STALE_METADATA_INACTIVE (0x01) +#define MPI2_RAIDVOLPAGE0_FOREIGN_VOLUME_INACTIVE (0x02) +#define MPI2_RAIDVOLPAGE0_INSUFFICIENT_RESOURCE_INACTIVE (0x03) +#define MPI2_RAIDVOLPAGE0_CLONE_VOLUME_INACTIVE (0x04) +#define MPI2_RAIDVOLPAGE0_INSUFFICIENT_METADATA_INACTIVE (0x05) +#define MPI2_RAIDVOLPAGE0_PREVIOUSLY_DELETED (0x06) + + +/* RAID Volume Page 1 */ + +typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_1 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U16 DevHandle; /* 0x04 */ + U16 Reserved0; /* 0x06 */ + U8 GUID[24]; /* 0x08 */ + U8 Name[16]; /* 0x20 */ + U64 WWID; /* 0x30 */ + U32 Reserved1; /* 0x38 */ + U32 Reserved2; /* 0x3C */ +} MPI2_CONFIG_PAGE_RAID_VOL_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_VOL_1, + Mpi2RaidVolPage1_t, MPI2_POINTER pMpi2RaidVolPage1_t; + +#define MPI2_RAIDVOLPAGE1_PAGEVERSION (0x03) + + +/**************************************************************************** +* RAID Physical Disk Config Pages +****************************************************************************/ + +/* RAID Physical Disk Page 0 */ + +typedef struct _MPI2_RAIDPHYSDISK0_SETTINGS +{ + U16 Reserved1; /* 0x00 */ + U8 HotSparePool; /* 0x02 */ + U8 Reserved2; /* 0x03 */ +} MPI2_RAIDPHYSDISK0_SETTINGS, MPI2_POINTER PTR_MPI2_RAIDPHYSDISK0_SETTINGS, + Mpi2RaidPhysDisk0Settings_t, MPI2_POINTER pMpi2RaidPhysDisk0Settings_t; + +/* use MPI2_RAID_HOT_SPARE_POOL_ defines for the HotSparePool field */ + +typedef struct _MPI2_RAIDPHYSDISK0_INQUIRY_DATA +{ + U8 VendorID[8]; /* 0x00 */ + U8 ProductID[16]; /* 0x08 */ + U8 ProductRevLevel[4]; /* 0x18 */ + U8 SerialNum[32]; /* 0x1C */ +} MPI2_RAIDPHYSDISK0_INQUIRY_DATA, + MPI2_POINTER PTR_MPI2_RAIDPHYSDISK0_INQUIRY_DATA, + Mpi2RaidPhysDisk0InquiryData_t, MPI2_POINTER pMpi2RaidPhysDisk0InquiryData_t; + +typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_0 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U16 DevHandle; /* 0x04 */ + U8 Reserved1; /* 0x06 */ + U8 PhysDiskNum; /* 0x07 */ + MPI2_RAIDPHYSDISK0_SETTINGS PhysDiskSettings; /* 0x08 */ + U32 Reserved2; /* 0x0C */ + MPI2_RAIDPHYSDISK0_INQUIRY_DATA InquiryData; /* 0x10 */ + U32 Reserved3; /* 0x4C */ + U8 PhysDiskState; /* 0x50 */ + U8 OfflineReason; /* 0x51 */ + U8 IncompatibleReason; /* 0x52 */ + U8 PhysDiskAttributes; /* 0x53 */ + U32 PhysDiskStatusFlags; /* 0x54 */ + U64 DeviceMaxLBA; /* 0x58 */ + U64 HostMaxLBA; /* 0x60 */ + U64 CoercedMaxLBA; /* 0x68 */ + U16 BlockSize; /* 0x70 */ + U16 Reserved5; /* 0x72 */ + U32 Reserved6; /* 0x74 */ +} MPI2_CONFIG_PAGE_RD_PDISK_0, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RD_PDISK_0, + Mpi2RaidPhysDiskPage0_t, MPI2_POINTER pMpi2RaidPhysDiskPage0_t; + +#define MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION (0x05) + +/* PhysDiskState defines */ +#define MPI2_RAID_PD_STATE_NOT_CONFIGURED (0x00) +#define MPI2_RAID_PD_STATE_NOT_COMPATIBLE (0x01) +#define MPI2_RAID_PD_STATE_OFFLINE (0x02) +#define MPI2_RAID_PD_STATE_ONLINE (0x03) +#define MPI2_RAID_PD_STATE_HOT_SPARE (0x04) +#define MPI2_RAID_PD_STATE_DEGRADED (0x05) +#define MPI2_RAID_PD_STATE_REBUILDING (0x06) +#define MPI2_RAID_PD_STATE_OPTIMAL (0x07) + +/* OfflineReason defines */ +#define MPI2_PHYSDISK0_ONLINE (0x00) +#define MPI2_PHYSDISK0_OFFLINE_MISSING (0x01) +#define MPI2_PHYSDISK0_OFFLINE_FAILED (0x03) +#define MPI2_PHYSDISK0_OFFLINE_INITIALIZING (0x04) +#define MPI2_PHYSDISK0_OFFLINE_REQUESTED (0x05) +#define MPI2_PHYSDISK0_OFFLINE_FAILED_REQUESTED (0x06) +#define MPI2_PHYSDISK0_OFFLINE_OTHER (0xFF) + +/* IncompatibleReason defines */ +#define MPI2_PHYSDISK0_COMPATIBLE (0x00) +#define MPI2_PHYSDISK0_INCOMPATIBLE_PROTOCOL (0x01) +#define MPI2_PHYSDISK0_INCOMPATIBLE_BLOCKSIZE (0x02) +#define MPI2_PHYSDISK0_INCOMPATIBLE_MAX_LBA (0x03) +#define MPI2_PHYSDISK0_INCOMPATIBLE_SATA_EXTENDED_CMD (0x04) +#define MPI2_PHYSDISK0_INCOMPATIBLE_REMOVEABLE_MEDIA (0x05) +#define MPI2_PHYSDISK0_INCOMPATIBLE_UNKNOWN (0xFF) + +/* PhysDiskAttributes defines */ +#define MPI2_PHYSDISK0_ATTRIB_SOLID_STATE_DRIVE (0x08) +#define MPI2_PHYSDISK0_ATTRIB_HARD_DISK_DRIVE (0x04) +#define MPI2_PHYSDISK0_ATTRIB_SAS_PROTOCOL (0x02) +#define MPI2_PHYSDISK0_ATTRIB_SATA_PROTOCOL (0x01) + +/* PhysDiskStatusFlags defines */ +#define MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED (0x00000040) +#define MPI2_PHYSDISK0_STATUS_FLAG_OCE_TARGET (0x00000020) +#define MPI2_PHYSDISK0_STATUS_FLAG_WRITE_CACHE_ENABLED (0x00000010) +#define MPI2_PHYSDISK0_STATUS_FLAG_OPTIMAL_PREVIOUS (0x00000000) +#define MPI2_PHYSDISK0_STATUS_FLAG_NOT_OPTIMAL_PREVIOUS (0x00000008) +#define MPI2_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME (0x00000004) +#define MPI2_PHYSDISK0_STATUS_FLAG_QUIESCED (0x00000002) +#define MPI2_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC (0x00000001) + + +/* RAID Physical Disk Page 1 */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.PageLength or NumPhysDiskPaths at runtime. + */ +#ifndef MPI2_RAID_PHYS_DISK1_PATH_MAX +#define MPI2_RAID_PHYS_DISK1_PATH_MAX (1) +#endif + +typedef struct _MPI2_RAIDPHYSDISK1_PATH +{ + U16 DevHandle; /* 0x00 */ + U16 Reserved1; /* 0x02 */ + U64 WWID; /* 0x04 */ + U64 OwnerWWID; /* 0x0C */ + U8 OwnerIdentifier; /* 0x14 */ + U8 Reserved2; /* 0x15 */ + U16 Flags; /* 0x16 */ +} MPI2_RAIDPHYSDISK1_PATH, MPI2_POINTER PTR_MPI2_RAIDPHYSDISK1_PATH, + Mpi2RaidPhysDisk1Path_t, MPI2_POINTER pMpi2RaidPhysDisk1Path_t; + +/* RAID Physical Disk Page 1 Physical Disk Path Flags field defines */ +#define MPI2_RAID_PHYSDISK1_FLAG_PRIMARY (0x0004) +#define MPI2_RAID_PHYSDISK1_FLAG_BROKEN (0x0002) +#define MPI2_RAID_PHYSDISK1_FLAG_INVALID (0x0001) + +typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U8 NumPhysDiskPaths; /* 0x04 */ + U8 PhysDiskNum; /* 0x05 */ + U16 Reserved1; /* 0x06 */ + U32 Reserved2; /* 0x08 */ + MPI2_RAIDPHYSDISK1_PATH PhysicalDiskPath[MPI2_RAID_PHYS_DISK1_PATH_MAX];/* 0x0C */ +} MPI2_CONFIG_PAGE_RD_PDISK_1, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RD_PDISK_1, + Mpi2RaidPhysDiskPage1_t, MPI2_POINTER pMpi2RaidPhysDiskPage1_t; + +#define MPI2_RAIDPHYSDISKPAGE1_PAGEVERSION (0x02) + + +/**************************************************************************** +* values for fields used by several types of SAS Config Pages +****************************************************************************/ + +/* values for NegotiatedLinkRates fields */ +#define MPI2_SAS_NEG_LINK_RATE_MASK_LOGICAL (0xF0) +#define MPI2_SAS_NEG_LINK_RATE_SHIFT_LOGICAL (4) +#define MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL (0x0F) +/* link rates used for Negotiated Physical and Logical Link Rate */ +#define MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE (0x00) +#define MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED (0x01) +#define MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED (0x02) +#define MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE (0x03) +#define MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR (0x04) +#define MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS (0x05) +#define MPI2_SAS_NEG_LINK_RATE_1_5 (0x08) +#define MPI2_SAS_NEG_LINK_RATE_3_0 (0x09) +#define MPI2_SAS_NEG_LINK_RATE_6_0 (0x0A) + + +/* values for AttachedPhyInfo fields */ +#define MPI2_SAS_APHYINFO_INSIDE_ZPSDS_PERSISTENT (0x00000040) +#define MPI2_SAS_APHYINFO_REQUESTED_INSIDE_ZPSDS (0x00000020) +#define MPI2_SAS_APHYINFO_BREAK_REPLY_CAPABLE (0x00000010) + +#define MPI2_SAS_APHYINFO_REASON_MASK (0x0000000F) +#define MPI2_SAS_APHYINFO_REASON_UNKNOWN (0x00000000) +#define MPI2_SAS_APHYINFO_REASON_POWER_ON (0x00000001) +#define MPI2_SAS_APHYINFO_REASON_HARD_RESET (0x00000002) +#define MPI2_SAS_APHYINFO_REASON_SMP_PHY_CONTROL (0x00000003) +#define MPI2_SAS_APHYINFO_REASON_LOSS_OF_SYNC (0x00000004) +#define MPI2_SAS_APHYINFO_REASON_MULTIPLEXING_SEQ (0x00000005) +#define MPI2_SAS_APHYINFO_REASON_IT_NEXUS_LOSS_TIMER (0x00000006) +#define MPI2_SAS_APHYINFO_REASON_BREAK_TIMEOUT (0x00000007) +#define MPI2_SAS_APHYINFO_REASON_PHY_TEST_STOPPED (0x00000008) + + +/* values for PhyInfo fields */ +#define MPI2_SAS_PHYINFO_PHY_VACANT (0x80000000) +#define MPI2_SAS_PHYINFO_CHANGED_REQ_INSIDE_ZPSDS (0x04000000) +#define MPI2_SAS_PHYINFO_INSIDE_ZPSDS_PERSISTENT (0x02000000) +#define MPI2_SAS_PHYINFO_REQ_INSIDE_ZPSDS (0x01000000) +#define MPI2_SAS_PHYINFO_ZONE_GROUP_PERSISTENT (0x00400000) +#define MPI2_SAS_PHYINFO_INSIDE_ZPSDS (0x00200000) +#define MPI2_SAS_PHYINFO_ZONING_ENABLED (0x00100000) + +#define MPI2_SAS_PHYINFO_REASON_MASK (0x000F0000) +#define MPI2_SAS_PHYINFO_REASON_UNKNOWN (0x00000000) +#define MPI2_SAS_PHYINFO_REASON_POWER_ON (0x00010000) +#define MPI2_SAS_PHYINFO_REASON_HARD_RESET (0x00020000) +#define MPI2_SAS_PHYINFO_REASON_SMP_PHY_CONTROL (0x00030000) +#define MPI2_SAS_PHYINFO_REASON_LOSS_OF_SYNC (0x00040000) +#define MPI2_SAS_PHYINFO_REASON_MULTIPLEXING_SEQ (0x00050000) +#define MPI2_SAS_PHYINFO_REASON_IT_NEXUS_LOSS_TIMER (0x00060000) +#define MPI2_SAS_PHYINFO_REASON_BREAK_TIMEOUT (0x00070000) +#define MPI2_SAS_PHYINFO_REASON_PHY_TEST_STOPPED (0x00080000) + +#define MPI2_SAS_PHYINFO_MULTIPLEXING_SUPPORTED (0x00008000) +#define MPI2_SAS_PHYINFO_SATA_PORT_ACTIVE (0x00004000) +#define MPI2_SAS_PHYINFO_SATA_PORT_SELECTOR_PRESENT (0x00002000) +#define MPI2_SAS_PHYINFO_VIRTUAL_PHY (0x00001000) + +#define MPI2_SAS_PHYINFO_MASK_PARTIAL_PATHWAY_TIME (0x00000F00) +#define MPI2_SAS_PHYINFO_SHIFT_PARTIAL_PATHWAY_TIME (8) + +#define MPI2_SAS_PHYINFO_MASK_ROUTING_ATTRIBUTE (0x000000F0) +#define MPI2_SAS_PHYINFO_DIRECT_ROUTING (0x00000000) +#define MPI2_SAS_PHYINFO_SUBTRACTIVE_ROUTING (0x00000010) +#define MPI2_SAS_PHYINFO_TABLE_ROUTING (0x00000020) + + +/* values for SAS ProgrammedLinkRate fields */ +#define MPI2_SAS_PRATE_MAX_RATE_MASK (0xF0) +#define MPI2_SAS_PRATE_MAX_RATE_NOT_PROGRAMMABLE (0x00) +#define MPI2_SAS_PRATE_MAX_RATE_1_5 (0x80) +#define MPI2_SAS_PRATE_MAX_RATE_3_0 (0x90) +#define MPI2_SAS_PRATE_MAX_RATE_6_0 (0xA0) +#define MPI2_SAS_PRATE_MIN_RATE_MASK (0x0F) +#define MPI2_SAS_PRATE_MIN_RATE_NOT_PROGRAMMABLE (0x00) +#define MPI2_SAS_PRATE_MIN_RATE_1_5 (0x08) +#define MPI2_SAS_PRATE_MIN_RATE_3_0 (0x09) +#define MPI2_SAS_PRATE_MIN_RATE_6_0 (0x0A) + + +/* values for SAS HwLinkRate fields */ +#define MPI2_SAS_HWRATE_MAX_RATE_MASK (0xF0) +#define MPI2_SAS_HWRATE_MAX_RATE_1_5 (0x80) +#define MPI2_SAS_HWRATE_MAX_RATE_3_0 (0x90) +#define MPI2_SAS_HWRATE_MAX_RATE_6_0 (0xA0) +#define MPI2_SAS_HWRATE_MIN_RATE_MASK (0x0F) +#define MPI2_SAS_HWRATE_MIN_RATE_1_5 (0x08) +#define MPI2_SAS_HWRATE_MIN_RATE_3_0 (0x09) +#define MPI2_SAS_HWRATE_MIN_RATE_6_0 (0x0A) + + + +/**************************************************************************** +* SAS IO Unit Config Pages +****************************************************************************/ + +/* SAS IO Unit Page 0 */ + +typedef struct _MPI2_SAS_IO_UNIT0_PHY_DATA +{ + U8 Port; /* 0x00 */ + U8 PortFlags; /* 0x01 */ + U8 PhyFlags; /* 0x02 */ + U8 NegotiatedLinkRate; /* 0x03 */ + U32 ControllerPhyDeviceInfo;/* 0x04 */ + U16 AttachedDevHandle; /* 0x08 */ + U16 ControllerDevHandle; /* 0x0A */ + U32 DiscoveryStatus; /* 0x0C */ + U32 Reserved; /* 0x10 */ +} MPI2_SAS_IO_UNIT0_PHY_DATA, MPI2_POINTER PTR_MPI2_SAS_IO_UNIT0_PHY_DATA, + Mpi2SasIOUnit0PhyData_t, MPI2_POINTER pMpi2SasIOUnit0PhyData_t; + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.ExtPageLength or NumPhys at runtime. + */ +#ifndef MPI2_SAS_IOUNIT0_PHY_MAX +#define MPI2_SAS_IOUNIT0_PHY_MAX (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_0 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U8 NumPhys; /* 0x0C */ + U8 Reserved2; /* 0x0D */ + U16 Reserved3; /* 0x0E */ + MPI2_SAS_IO_UNIT0_PHY_DATA PhyData[MPI2_SAS_IOUNIT0_PHY_MAX]; /* 0x10 */ +} MPI2_CONFIG_PAGE_SASIOUNIT_0, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_0, + Mpi2SasIOUnitPage0_t, MPI2_POINTER pMpi2SasIOUnitPage0_t; + +#define MPI2_SASIOUNITPAGE0_PAGEVERSION (0x05) + +/* values for SAS IO Unit Page 0 PortFlags */ +#define MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS (0x08) +#define MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG (0x01) + +/* values for SAS IO Unit Page 0 PhyFlags */ +#define MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED (0x10) +#define MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED (0x08) + +/* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */ + +/* see mpi2_sas.h for values for SAS IO Unit Page 0 ControllerPhyDeviceInfo values */ + +/* values for SAS IO Unit Page 0 DiscoveryStatus */ +#define MPI2_SASIOUNIT0_DS_MAX_ENCLOSURES_EXCEED (0x80000000) +#define MPI2_SASIOUNIT0_DS_MAX_EXPANDERS_EXCEED (0x40000000) +#define MPI2_SASIOUNIT0_DS_MAX_DEVICES_EXCEED (0x20000000) +#define MPI2_SASIOUNIT0_DS_MAX_TOPO_PHYS_EXCEED (0x10000000) +#define MPI2_SASIOUNIT0_DS_DOWNSTREAM_INITIATOR (0x08000000) +#define MPI2_SASIOUNIT0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000) +#define MPI2_SASIOUNIT0_DS_EXP_MULTI_SUBTRACTIVE (0x00004000) +#define MPI2_SASIOUNIT0_DS_MULTI_PORT_DOMAIN (0x00002000) +#define MPI2_SASIOUNIT0_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000) +#define MPI2_SASIOUNIT0_DS_UNSUPPORTED_DEVICE (0x00000800) +#define MPI2_SASIOUNIT0_DS_TABLE_LINK (0x00000400) +#define MPI2_SASIOUNIT0_DS_SUBTRACTIVE_LINK (0x00000200) +#define MPI2_SASIOUNIT0_DS_SMP_CRC_ERROR (0x00000100) +#define MPI2_SASIOUNIT0_DS_SMP_FUNCTION_FAILED (0x00000080) +#define MPI2_SASIOUNIT0_DS_INDEX_NOT_EXIST (0x00000040) +#define MPI2_SASIOUNIT0_DS_OUT_ROUTE_ENTRIES (0x00000020) +#define MPI2_SASIOUNIT0_DS_SMP_TIMEOUT (0x00000010) +#define MPI2_SASIOUNIT0_DS_MULTIPLE_PORTS (0x00000004) +#define MPI2_SASIOUNIT0_DS_UNADDRESSABLE_DEVICE (0x00000002) +#define MPI2_SASIOUNIT0_DS_LOOP_DETECTED (0x00000001) + + +/* SAS IO Unit Page 1 */ + +typedef struct _MPI2_SAS_IO_UNIT1_PHY_DATA +{ + U8 Port; /* 0x00 */ + U8 PortFlags; /* 0x01 */ + U8 PhyFlags; /* 0x02 */ + U8 MaxMinLinkRate; /* 0x03 */ + U32 ControllerPhyDeviceInfo; /* 0x04 */ + U16 MaxTargetPortConnectTime; /* 0x08 */ + U16 Reserved1; /* 0x0A */ +} MPI2_SAS_IO_UNIT1_PHY_DATA, MPI2_POINTER PTR_MPI2_SAS_IO_UNIT1_PHY_DATA, + Mpi2SasIOUnit1PhyData_t, MPI2_POINTER pMpi2SasIOUnit1PhyData_t; + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.ExtPageLength or NumPhys at runtime. + */ +#ifndef MPI2_SAS_IOUNIT1_PHY_MAX +#define MPI2_SAS_IOUNIT1_PHY_MAX (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U16 ControlFlags; /* 0x08 */ + U16 SASNarrowMaxQueueDepth; /* 0x0A */ + U16 AdditionalControlFlags; /* 0x0C */ + U16 SASWideMaxQueueDepth; /* 0x0E */ + U8 NumPhys; /* 0x10 */ + U8 SATAMaxQDepth; /* 0x11 */ + U8 ReportDeviceMissingDelay; /* 0x12 */ + U8 IODeviceMissingDelay; /* 0x13 */ + MPI2_SAS_IO_UNIT1_PHY_DATA PhyData[MPI2_SAS_IOUNIT1_PHY_MAX]; /* 0x14 */ +} MPI2_CONFIG_PAGE_SASIOUNIT_1, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_1, + Mpi2SasIOUnitPage1_t, MPI2_POINTER pMpi2SasIOUnitPage1_t; + +#define MPI2_SASIOUNITPAGE1_PAGEVERSION (0x09) + +/* values for SAS IO Unit Page 1 ControlFlags */ +#define MPI2_SASIOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000) +#define MPI2_SASIOUNIT1_CONTROL_SATA_3_0_MAX (0x4000) +#define MPI2_SASIOUNIT1_CONTROL_SATA_1_5_MAX (0x2000) +#define MPI2_SASIOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000) + +#define MPI2_SASIOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600) +#define MPI2_SASIOUNIT1_CONTROL_SHIFT_DEV_SUPPORT (9) +#define MPI2_SASIOUNIT1_CONTROL_DEV_SUPPORT_BOTH (0x0) +#define MPI2_SASIOUNIT1_CONTROL_DEV_SAS_SUPPORT (0x1) +#define MPI2_SASIOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x2) + +#define MPI2_SASIOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080) +#define MPI2_SASIOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040) +#define MPI2_SASIOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020) +#define MPI2_SASIOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010) +#define MPI2_SASIOUNIT1_CONTROL_TABLE_SUBTRACTIVE_ILLEGAL (0x0008) +#define MPI2_SASIOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004) +#define MPI2_SASIOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002) +#define MPI2_SASIOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001) + +/* values for SAS IO Unit Page 1 AdditionalControlFlags */ +#define MPI2_SASIOUNIT1_ACONTROL_MULTI_PORT_DOMAIN_ILLEGAL (0x0080) +#define MPI2_SASIOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION (0x0040) +#define MPI2_SASIOUNIT1_ACONTROL_INVALID_TOPOLOGY_CORRECTION (0x0020) +#define MPI2_SASIOUNIT1_ACONTROL_PORT_ENABLE_ONLY_SATA_LINK_RESET (0x0010) +#define MPI2_SASIOUNIT1_ACONTROL_OTHER_AFFILIATION_SATA_LINK_RESET (0x0008) +#define MPI2_SASIOUNIT1_ACONTROL_SELF_AFFILIATION_SATA_LINK_RESET (0x0004) +#define MPI2_SASIOUNIT1_ACONTROL_NO_AFFILIATION_SATA_LINK_RESET (0x0002) +#define MPI2_SASIOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE (0x0001) + +/* defines for SAS IO Unit Page 1 ReportDeviceMissingDelay */ +#define MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK (0x7F) +#define MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16 (0x80) + +/* values for SAS IO Unit Page 1 PortFlags */ +#define MPI2_SASIOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01) + +/* values for SAS IO Unit Page 2 PhyFlags */ +#define MPI2_SASIOUNIT1_PHYFLAGS_ZONING_ENABLE (0x10) +#define MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE (0x08) + +/* values for SAS IO Unit Page 0 MaxMinLinkRate */ +#define MPI2_SASIOUNIT1_MAX_RATE_MASK (0xF0) +#define MPI2_SASIOUNIT1_MAX_RATE_1_5 (0x80) +#define MPI2_SASIOUNIT1_MAX_RATE_3_0 (0x90) +#define MPI2_SASIOUNIT1_MAX_RATE_6_0 (0xA0) +#define MPI2_SASIOUNIT1_MIN_RATE_MASK (0x0F) +#define MPI2_SASIOUNIT1_MIN_RATE_1_5 (0x08) +#define MPI2_SASIOUNIT1_MIN_RATE_3_0 (0x09) +#define MPI2_SASIOUNIT1_MIN_RATE_6_0 (0x0A) + +/* see mpi2_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */ + + +/* SAS IO Unit Page 4 */ + +typedef struct _MPI2_SAS_IOUNIT4_SPINUP_GROUP +{ + U8 MaxTargetSpinup; /* 0x00 */ + U8 SpinupDelay; /* 0x01 */ + U16 Reserved1; /* 0x02 */ +} MPI2_SAS_IOUNIT4_SPINUP_GROUP, MPI2_POINTER PTR_MPI2_SAS_IOUNIT4_SPINUP_GROUP, + Mpi2SasIOUnit4SpinupGroup_t, MPI2_POINTER pMpi2SasIOUnit4SpinupGroup_t; + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * four and check Header.ExtPageLength or NumPhys at runtime. + */ +#ifndef MPI2_SAS_IOUNIT4_PHY_MAX +#define MPI2_SAS_IOUNIT4_PHY_MAX (4) +#endif + +typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_4 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + MPI2_SAS_IOUNIT4_SPINUP_GROUP SpinupGroupParameters[4]; /* 0x08 */ + U32 Reserved1; /* 0x18 */ + U32 Reserved2; /* 0x1C */ + U32 Reserved3; /* 0x20 */ + U8 BootDeviceWaitTime; /* 0x24 */ + U8 Reserved4; /* 0x25 */ + U16 Reserved5; /* 0x26 */ + U8 NumPhys; /* 0x28 */ + U8 PEInitialSpinupDelay; /* 0x29 */ + U8 PEReplyDelay; /* 0x2A */ + U8 Flags; /* 0x2B */ + U8 PHY[MPI2_SAS_IOUNIT4_PHY_MAX]; /* 0x2C */ +} MPI2_CONFIG_PAGE_SASIOUNIT_4, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_4, + Mpi2SasIOUnitPage4_t, MPI2_POINTER pMpi2SasIOUnitPage4_t; + +#define MPI2_SASIOUNITPAGE4_PAGEVERSION (0x02) + +/* defines for Flags field */ +#define MPI2_SASIOUNIT4_FLAGS_AUTO_PORTENABLE (0x01) + +/* defines for PHY field */ +#define MPI2_SASIOUNIT4_PHY_SPINUP_GROUP_MASK (0x03) + + +/**************************************************************************** +* SAS Expander Config Pages +****************************************************************************/ + +/* SAS Expander Page 0 */ + +typedef struct _MPI2_CONFIG_PAGE_EXPANDER_0 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U8 PhysicalPort; /* 0x08 */ + U8 ReportGenLength; /* 0x09 */ + U16 EnclosureHandle; /* 0x0A */ + U64 SASAddress; /* 0x0C */ + U32 DiscoveryStatus; /* 0x14 */ + U16 DevHandle; /* 0x18 */ + U16 ParentDevHandle; /* 0x1A */ + U16 ExpanderChangeCount; /* 0x1C */ + U16 ExpanderRouteIndexes; /* 0x1E */ + U8 NumPhys; /* 0x20 */ + U8 SASLevel; /* 0x21 */ + U16 Flags; /* 0x22 */ + U16 STPBusInactivityTimeLimit; /* 0x24 */ + U16 STPMaxConnectTimeLimit; /* 0x26 */ + U16 STP_SMP_NexusLossTime; /* 0x28 */ + U16 MaxNumRoutedSasAddresses; /* 0x2A */ + U64 ActiveZoneManagerSASAddress;/* 0x2C */ + U16 ZoneLockInactivityLimit; /* 0x34 */ + U16 Reserved1; /* 0x36 */ +} MPI2_CONFIG_PAGE_EXPANDER_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXPANDER_0, + Mpi2ExpanderPage0_t, MPI2_POINTER pMpi2ExpanderPage0_t; + +#define MPI2_SASEXPANDER0_PAGEVERSION (0x05) + +/* values for SAS Expander Page 0 DiscoveryStatus field */ +#define MPI2_SAS_EXPANDER0_DS_MAX_ENCLOSURES_EXCEED (0x80000000) +#define MPI2_SAS_EXPANDER0_DS_MAX_EXPANDERS_EXCEED (0x40000000) +#define MPI2_SAS_EXPANDER0_DS_MAX_DEVICES_EXCEED (0x20000000) +#define MPI2_SAS_EXPANDER0_DS_MAX_TOPO_PHYS_EXCEED (0x10000000) +#define MPI2_SAS_EXPANDER0_DS_DOWNSTREAM_INITIATOR (0x08000000) +#define MPI2_SAS_EXPANDER0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000) +#define MPI2_SAS_EXPANDER0_DS_EXP_MULTI_SUBTRACTIVE (0x00004000) +#define MPI2_SAS_EXPANDER0_DS_MULTI_PORT_DOMAIN (0x00002000) +#define MPI2_SAS_EXPANDER0_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000) +#define MPI2_SAS_EXPANDER0_DS_UNSUPPORTED_DEVICE (0x00000800) +#define MPI2_SAS_EXPANDER0_DS_TABLE_LINK (0x00000400) +#define MPI2_SAS_EXPANDER0_DS_SUBTRACTIVE_LINK (0x00000200) +#define MPI2_SAS_EXPANDER0_DS_SMP_CRC_ERROR (0x00000100) +#define MPI2_SAS_EXPANDER0_DS_SMP_FUNCTION_FAILED (0x00000080) +#define MPI2_SAS_EXPANDER0_DS_INDEX_NOT_EXIST (0x00000040) +#define MPI2_SAS_EXPANDER0_DS_OUT_ROUTE_ENTRIES (0x00000020) +#define MPI2_SAS_EXPANDER0_DS_SMP_TIMEOUT (0x00000010) +#define MPI2_SAS_EXPANDER0_DS_MULTIPLE_PORTS (0x00000004) +#define MPI2_SAS_EXPANDER0_DS_UNADDRESSABLE_DEVICE (0x00000002) +#define MPI2_SAS_EXPANDER0_DS_LOOP_DETECTED (0x00000001) + +/* values for SAS Expander Page 0 Flags field */ +#define MPI2_SAS_EXPANDER0_FLAGS_ZONE_LOCKED (0x1000) +#define MPI2_SAS_EXPANDER0_FLAGS_SUPPORTED_PHYSICAL_PRES (0x0800) +#define MPI2_SAS_EXPANDER0_FLAGS_ASSERTED_PHYSICAL_PRES (0x0400) +#define MPI2_SAS_EXPANDER0_FLAGS_ZONING_SUPPORT (0x0200) +#define MPI2_SAS_EXPANDER0_FLAGS_ENABLED_ZONING (0x0100) +#define MPI2_SAS_EXPANDER0_FLAGS_TABLE_TO_TABLE_SUPPORT (0x0080) +#define MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE (0x0010) +#define MPI2_SAS_EXPANDER0_FLAGS_OTHERS_CONFIG (0x0004) +#define MPI2_SAS_EXPANDER0_FLAGS_CONFIG_IN_PROGRESS (0x0002) +#define MPI2_SAS_EXPANDER0_FLAGS_ROUTE_TABLE_CONFIG (0x0001) + + +/* SAS Expander Page 1 */ + +typedef struct _MPI2_CONFIG_PAGE_EXPANDER_1 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U8 PhysicalPort; /* 0x08 */ + U8 Reserved1; /* 0x09 */ + U16 Reserved2; /* 0x0A */ + U8 NumPhys; /* 0x0C */ + U8 Phy; /* 0x0D */ + U16 NumTableEntriesProgrammed; /* 0x0E */ + U8 ProgrammedLinkRate; /* 0x10 */ + U8 HwLinkRate; /* 0x11 */ + U16 AttachedDevHandle; /* 0x12 */ + U32 PhyInfo; /* 0x14 */ + U32 AttachedDeviceInfo; /* 0x18 */ + U16 ExpanderDevHandle; /* 0x1C */ + U8 ChangeCount; /* 0x1E */ + U8 NegotiatedLinkRate; /* 0x1F */ + U8 PhyIdentifier; /* 0x20 */ + U8 AttachedPhyIdentifier; /* 0x21 */ + U8 Reserved3; /* 0x22 */ + U8 DiscoveryInfo; /* 0x23 */ + U32 AttachedPhyInfo; /* 0x24 */ + U8 ZoneGroup; /* 0x28 */ + U8 SelfConfigStatus; /* 0x29 */ + U16 Reserved4; /* 0x2A */ +} MPI2_CONFIG_PAGE_EXPANDER_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXPANDER_1, + Mpi2ExpanderPage1_t, MPI2_POINTER pMpi2ExpanderPage1_t; + +#define MPI2_SASEXPANDER1_PAGEVERSION (0x02) + +/* use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */ + +/* use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */ + +/* use MPI2_SAS_PHYINFO_ for the PhyInfo field */ + +/* see mpi2_sas.h for the MPI2_SAS_DEVICE_INFO_ defines used for the AttachedDeviceInfo field */ + +/* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */ + +/* use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */ + +/* values for SAS Expander Page 1 DiscoveryInfo field */ +#define MPI2_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED (0x04) +#define MPI2_SAS_EXPANDER1_DISCINFO_LINK_STATUS_CHANGE (0x02) +#define MPI2_SAS_EXPANDER1_DISCINFO_NO_ROUTING_ENTRIES (0x01) + + +/**************************************************************************** +* SAS Device Config Pages +****************************************************************************/ + +/* SAS Device Page 0 */ + +typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_0 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U16 Slot; /* 0x08 */ + U16 EnclosureHandle; /* 0x0A */ + U64 SASAddress; /* 0x0C */ + U16 ParentDevHandle; /* 0x14 */ + U8 PhyNum; /* 0x16 */ + U8 AccessStatus; /* 0x17 */ + U16 DevHandle; /* 0x18 */ + U8 AttachedPhyIdentifier; /* 0x1A */ + U8 ZoneGroup; /* 0x1B */ + U32 DeviceInfo; /* 0x1C */ + U16 Flags; /* 0x20 */ + U8 PhysicalPort; /* 0x22 */ + U8 MaxPortConnections; /* 0x23 */ + U64 DeviceName; /* 0x24 */ + U8 PortGroups; /* 0x2C */ + U8 DmaGroup; /* 0x2D */ + U8 ControlGroup; /* 0x2E */ + U8 Reserved1; /* 0x2F */ + U32 Reserved2; /* 0x30 */ + U32 Reserved3; /* 0x34 */ +} MPI2_CONFIG_PAGE_SAS_DEV_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_DEV_0, + Mpi2SasDevicePage0_t, MPI2_POINTER pMpi2SasDevicePage0_t; + +#define MPI2_SASDEVICE0_PAGEVERSION (0x08) + +/* values for SAS Device Page 0 AccessStatus field */ +#define MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS (0x00) +#define MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED (0x01) +#define MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED (0x02) +#define MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT (0x03) +#define MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION (0x04) +#define MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE (0x05) +#define MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE (0x06) +#define MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED (0x07) +/* specific values for SATA Init failures */ +#define MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN (0x10) +#define MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT (0x11) +#define MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG (0x12) +#define MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION (0x13) +#define MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER (0x14) +#define MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN (0x15) +#define MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN (0x16) +#define MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN (0x17) +#define MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION (0x18) +#define MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE (0x19) +#define MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX (0x1F) + +/* see mpi2_sas.h for values for SAS Device Page 0 DeviceInfo values */ + +/* values for SAS Device Page 0 Flags field */ +#define MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY (0x0400) +#define MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE (0x0200) +#define MPI2_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE (0x0100) +#define MPI2_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED (0x0080) +#define MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED (0x0040) +#define MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED (0x0020) +#define MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED (0x0010) +#define MPI2_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH (0x0008) +#define MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001) + + +/* SAS Device Page 1 */ + +typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_1 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U64 SASAddress; /* 0x0C */ + U32 Reserved2; /* 0x14 */ + U16 DevHandle; /* 0x18 */ + U16 Reserved3; /* 0x1A */ + U8 InitialRegDeviceFIS[20];/* 0x1C */ +} MPI2_CONFIG_PAGE_SAS_DEV_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_DEV_1, + Mpi2SasDevicePage1_t, MPI2_POINTER pMpi2SasDevicePage1_t; + +#define MPI2_SASDEVICE1_PAGEVERSION (0x01) + + +/**************************************************************************** +* SAS PHY Config Pages +****************************************************************************/ + +/* SAS PHY Page 0 */ + +typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_0 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U16 OwnerDevHandle; /* 0x08 */ + U16 Reserved1; /* 0x0A */ + U16 AttachedDevHandle; /* 0x0C */ + U8 AttachedPhyIdentifier; /* 0x0E */ + U8 Reserved2; /* 0x0F */ + U32 AttachedPhyInfo; /* 0x10 */ + U8 ProgrammedLinkRate; /* 0x14 */ + U8 HwLinkRate; /* 0x15 */ + U8 ChangeCount; /* 0x16 */ + U8 Flags; /* 0x17 */ + U32 PhyInfo; /* 0x18 */ + U8 NegotiatedLinkRate; /* 0x1C */ + U8 Reserved3; /* 0x1D */ + U16 Reserved4; /* 0x1E */ +} MPI2_CONFIG_PAGE_SAS_PHY_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_0, + Mpi2SasPhyPage0_t, MPI2_POINTER pMpi2SasPhyPage0_t; + +#define MPI2_SASPHY0_PAGEVERSION (0x03) + +/* use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */ + +/* use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */ + +/* values for SAS PHY Page 0 Flags field */ +#define MPI2_SAS_PHY0_FLAGS_SGPIO_DIRECT_ATTACH_ENC (0x01) + +/* use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */ + +/* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */ + +/* use MPI2_SAS_PHYINFO_ for the PhyInfo field */ + + +/* SAS PHY Page 1 */ + +typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_1 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U32 InvalidDwordCount; /* 0x0C */ + U32 RunningDisparityErrorCount; /* 0x10 */ + U32 LossDwordSynchCount; /* 0x14 */ + U32 PhyResetProblemCount; /* 0x18 */ +} MPI2_CONFIG_PAGE_SAS_PHY_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_1, + Mpi2SasPhyPage1_t, MPI2_POINTER pMpi2SasPhyPage1_t; + +#define MPI2_SASPHY1_PAGEVERSION (0x01) + + +/**************************************************************************** +* SAS Port Config Pages +****************************************************************************/ + +/* SAS Port Page 0 */ + +typedef struct _MPI2_CONFIG_PAGE_SAS_PORT_0 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U8 PortNumber; /* 0x08 */ + U8 PhysicalPort; /* 0x09 */ + U8 PortWidth; /* 0x0A */ + U8 PhysicalPortWidth; /* 0x0B */ + U8 ZoneGroup; /* 0x0C */ + U8 Reserved1; /* 0x0D */ + U16 Reserved2; /* 0x0E */ + U64 SASAddress; /* 0x10 */ + U32 DeviceInfo; /* 0x18 */ + U32 Reserved3; /* 0x1C */ + U32 Reserved4; /* 0x20 */ +} MPI2_CONFIG_PAGE_SAS_PORT_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PORT_0, + Mpi2SasPortPage0_t, MPI2_POINTER pMpi2SasPortPage0_t; + +#define MPI2_SASPORT0_PAGEVERSION (0x00) + +/* see mpi2_sas.h for values for SAS Port Page 0 DeviceInfo values */ + + +/**************************************************************************** +* SAS Enclosure Config Pages +****************************************************************************/ + +/* SAS Enclosure Page 0 */ + +typedef struct _MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U64 EnclosureLogicalID; /* 0x0C */ + U16 Flags; /* 0x14 */ + U16 EnclosureHandle; /* 0x16 */ + U16 NumSlots; /* 0x18 */ + U16 StartSlot; /* 0x1A */ + U16 Reserved2; /* 0x1C */ + U16 SEPDevHandle; /* 0x1E */ + U32 Reserved3; /* 0x20 */ + U32 Reserved4; /* 0x24 */ +} MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0, + Mpi2SasEnclosurePage0_t, MPI2_POINTER pMpi2SasEnclosurePage0_t; + +#define MPI2_SASENCLOSURE0_PAGEVERSION (0x03) + +/* values for SAS Enclosure Page 0 Flags field */ +#define MPI2_SAS_ENCLS0_FLAGS_MNG_MASK (0x000F) +#define MPI2_SAS_ENCLS0_FLAGS_MNG_UNKNOWN (0x0000) +#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SES (0x0001) +#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SGPIO (0x0002) +#define MPI2_SAS_ENCLS0_FLAGS_MNG_EXP_SGPIO (0x0003) +#define MPI2_SAS_ENCLS0_FLAGS_MNG_SES_ENCLOSURE (0x0004) +#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_GPIO (0x0005) + + +/**************************************************************************** +* Log Config Page +****************************************************************************/ + +/* Log Page 0 */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.ExtPageLength or NumPhys at runtime. + */ +#ifndef MPI2_LOG_0_NUM_LOG_ENTRIES +#define MPI2_LOG_0_NUM_LOG_ENTRIES (1) +#endif + +#define MPI2_LOG_0_LOG_DATA_LENGTH (0x1C) + +typedef struct _MPI2_LOG_0_ENTRY +{ + U64 TimeStamp; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U16 LogSequence; /* 0x0C */ + U16 LogEntryQualifier; /* 0x0E */ + U8 VP_ID; /* 0x10 */ + U8 VF_ID; /* 0x11 */ + U16 Reserved2; /* 0x12 */ + U8 LogData[MPI2_LOG_0_LOG_DATA_LENGTH];/* 0x14 */ +} MPI2_LOG_0_ENTRY, MPI2_POINTER PTR_MPI2_LOG_0_ENTRY, + Mpi2Log0Entry_t, MPI2_POINTER pMpi2Log0Entry_t; + +/* values for Log Page 0 LogEntry LogEntryQualifier field */ +#define MPI2_LOG_0_ENTRY_QUAL_ENTRY_UNUSED (0x0000) +#define MPI2_LOG_0_ENTRY_QUAL_POWER_ON_RESET (0x0001) +#define MPI2_LOG_0_ENTRY_QUAL_TIMESTAMP_UPDATE (0x0002) +#define MPI2_LOG_0_ENTRY_QUAL_MIN_IMPLEMENT_SPEC (0x8000) +#define MPI2_LOG_0_ENTRY_QUAL_MAX_IMPLEMENT_SPEC (0xFFFF) + +typedef struct _MPI2_CONFIG_PAGE_LOG_0 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U32 Reserved2; /* 0x0C */ + U16 NumLogEntries; /* 0x10 */ + U16 Reserved3; /* 0x12 */ + MPI2_LOG_0_ENTRY LogEntry[MPI2_LOG_0_NUM_LOG_ENTRIES]; /* 0x14 */ +} MPI2_CONFIG_PAGE_LOG_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_LOG_0, + Mpi2LogPage0_t, MPI2_POINTER pMpi2LogPage0_t; + +#define MPI2_LOG_0_PAGEVERSION (0x02) + + +/**************************************************************************** +* RAID Config Page +****************************************************************************/ + +/* RAID Page 0 */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.ExtPageLength or NumPhys at runtime. + */ +#ifndef MPI2_RAIDCONFIG0_MAX_ELEMENTS +#define MPI2_RAIDCONFIG0_MAX_ELEMENTS (1) +#endif + +typedef struct _MPI2_RAIDCONFIG0_CONFIG_ELEMENT +{ + U16 ElementFlags; /* 0x00 */ + U16 VolDevHandle; /* 0x02 */ + U8 HotSparePool; /* 0x04 */ + U8 PhysDiskNum; /* 0x05 */ + U16 PhysDiskDevHandle; /* 0x06 */ +} MPI2_RAIDCONFIG0_CONFIG_ELEMENT, + MPI2_POINTER PTR_MPI2_RAIDCONFIG0_CONFIG_ELEMENT, + Mpi2RaidConfig0ConfigElement_t, MPI2_POINTER pMpi2RaidConfig0ConfigElement_t; + +/* values for the ElementFlags field */ +#define MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE (0x000F) +#define MPI2_RAIDCONFIG0_EFLAGS_VOLUME_ELEMENT (0x0000) +#define MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT (0x0001) +#define MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT (0x0002) +#define MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT (0x0003) + + +typedef struct _MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U8 NumHotSpares; /* 0x08 */ + U8 NumPhysDisks; /* 0x09 */ + U8 NumVolumes; /* 0x0A */ + U8 ConfigNum; /* 0x0B */ + U32 Flags; /* 0x0C */ + U8 ConfigGUID[24]; /* 0x10 */ + U32 Reserved1; /* 0x28 */ + U8 NumElements; /* 0x2C */ + U8 Reserved2; /* 0x2D */ + U16 Reserved3; /* 0x2E */ + MPI2_RAIDCONFIG0_CONFIG_ELEMENT ConfigElement[MPI2_RAIDCONFIG0_MAX_ELEMENTS]; /* 0x30 */ +} MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0, + Mpi2RaidConfigurationPage0_t, MPI2_POINTER pMpi2RaidConfigurationPage0_t; + +#define MPI2_RAIDCONFIG0_PAGEVERSION (0x00) + +/* values for RAID Configuration Page 0 Flags field */ +#define MPI2_RAIDCONFIG0_FLAG_FOREIGN_CONFIG (0x00000001) + + +/**************************************************************************** +* Driver Persistent Mapping Config Pages +****************************************************************************/ + +/* Driver Persistent Mapping Page 0 */ + +typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY +{ + U64 PhysicalIdentifier; /* 0x00 */ + U16 MappingInformation; /* 0x08 */ + U16 DeviceIndex; /* 0x0A */ + U32 PhysicalBitsMapping; /* 0x0C */ + U32 Reserved1; /* 0x10 */ +} MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY, + Mpi2DriverMap0Entry_t, MPI2_POINTER pMpi2DriverMap0Entry_t; + +typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 +{ + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY Entry; /* 0x08 */ +} MPI2_CONFIG_PAGE_DRIVER_MAPPING_0, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_DRIVER_MAPPING_0, + Mpi2DriverMappingPage0_t, MPI2_POINTER pMpi2DriverMappingPage0_t; + +#define MPI2_DRIVERMAPPING0_PAGEVERSION (0x00) + +/* values for Driver Persistent Mapping Page 0 MappingInformation field */ +#define MPI2_DRVMAP0_MAPINFO_SLOT_MASK (0x07F0) +#define MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT (4) +#define MPI2_DRVMAP0_MAPINFO_MISSING_MASK (0x000F) + + +#endif + diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_init.h b/drivers/scsi/mpt2sas/mpi/mpi2_init.h new file mode 100644 index 00000000000..f1115f0f0eb --- /dev/null +++ b/drivers/scsi/mpt2sas/mpi/mpi2_init.h @@ -0,0 +1,420 @@ +/* + * Copyright (c) 2000-2008 LSI Corporation. + * + * + * Name: mpi2_init.h + * Title: MPI SCSI initiator mode messages and structures + * Creation Date: June 23, 2006 + * + * mpi2_init.h Version: 02.00.06 + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 10-31-07 02.00.01 Fixed name for pMpi2SCSITaskManagementRequest_t. + * 12-18-07 02.00.02 Modified Task Management Target Reset Method defines. + * 02-29-08 02.00.03 Added Query Task Set and Query Unit Attention. + * 03-03-08 02.00.04 Fixed name of struct _MPI2_SCSI_TASK_MANAGE_REPLY. + * 05-21-08 02.00.05 Fixed typo in name of Mpi2SepRequest_t. + * 10-02-08 02.00.06 Removed Untagged and No Disconnect values from SCSI IO + * Control field Task Attribute flags. + * Moved LUN field defines to mpi2.h becasue they are + * common to many structures. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI2_INIT_H +#define MPI2_INIT_H + +/***************************************************************************** +* +* SCSI Initiator Messages +* +*****************************************************************************/ + +/**************************************************************************** +* SCSI IO messages and associated structures +****************************************************************************/ + +typedef struct +{ + U8 CDB[20]; /* 0x00 */ + U32 PrimaryReferenceTag; /* 0x14 */ + U16 PrimaryApplicationTag; /* 0x18 */ + U16 PrimaryApplicationTagMask; /* 0x1A */ + U32 TransferLength; /* 0x1C */ +} MPI2_SCSI_IO_CDB_EEDP32, MPI2_POINTER PTR_MPI2_SCSI_IO_CDB_EEDP32, + Mpi2ScsiIoCdbEedp32_t, MPI2_POINTER pMpi2ScsiIoCdbEedp32_t; + +/* TBD: I don't think this is needed for MPI2/Gen2 */ +#if 0 +typedef struct +{ + U8 CDB[16]; /* 0x00 */ + U32 DataLength; /* 0x10 */ + U32 PrimaryReferenceTag; /* 0x14 */ + U16 PrimaryApplicationTag; /* 0x18 */ + U16 PrimaryApplicationTagMask; /* 0x1A */ + U32 TransferLength; /* 0x1C */ +} MPI2_SCSI_IO32_CDB_EEDP16, MPI2_POINTER PTR_MPI2_SCSI_IO32_CDB_EEDP16, + Mpi2ScsiIo32CdbEedp16_t, MPI2_POINTER pMpi2ScsiIo32CdbEedp16_t; +#endif + +typedef union +{ + U8 CDB32[32]; + MPI2_SCSI_IO_CDB_EEDP32 EEDP32; + MPI2_SGE_SIMPLE_UNION SGE; +} MPI2_SCSI_IO_CDB_UNION, MPI2_POINTER PTR_MPI2_SCSI_IO_CDB_UNION, + Mpi2ScsiIoCdb_t, MPI2_POINTER pMpi2ScsiIoCdb_t; + +/* SCSI IO Request Message */ +typedef struct _MPI2_SCSI_IO_REQUEST +{ + U16 DevHandle; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved1; /* 0x04 */ + U8 Reserved2; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U32 SenseBufferLowAddress; /* 0x0C */ + U16 SGLFlags; /* 0x10 */ + U8 SenseBufferLength; /* 0x12 */ + U8 Reserved4; /* 0x13 */ + U8 SGLOffset0; /* 0x14 */ + U8 SGLOffset1; /* 0x15 */ + U8 SGLOffset2; /* 0x16 */ + U8 SGLOffset3; /* 0x17 */ + U32 SkipCount; /* 0x18 */ + U32 DataLength; /* 0x1C */ + U32 BidirectionalDataLength; /* 0x20 */ + U16 IoFlags; /* 0x24 */ + U16 EEDPFlags; /* 0x26 */ + U32 EEDPBlockSize; /* 0x28 */ + U32 SecondaryReferenceTag; /* 0x2C */ + U16 SecondaryApplicationTag; /* 0x30 */ + U16 ApplicationTagTranslationMask; /* 0x32 */ + U8 LUN[8]; /* 0x34 */ + U32 Control; /* 0x3C */ + MPI2_SCSI_IO_CDB_UNION CDB; /* 0x40 */ + MPI2_SGE_IO_UNION SGL; /* 0x60 */ +} MPI2_SCSI_IO_REQUEST, MPI2_POINTER PTR_MPI2_SCSI_IO_REQUEST, + Mpi2SCSIIORequest_t, MPI2_POINTER pMpi2SCSIIORequest_t; + +/* SCSI IO MsgFlags bits */ + +/* MsgFlags for SenseBufferAddressSpace */ +#define MPI2_SCSIIO_MSGFLAGS_MASK_SENSE_ADDR (0x0C) +#define MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR (0x00) +#define MPI2_SCSIIO_MSGFLAGS_IOCDDR_SENSE_ADDR (0x04) +#define MPI2_SCSIIO_MSGFLAGS_IOCPLB_SENSE_ADDR (0x08) +#define MPI2_SCSIIO_MSGFLAGS_IOCPLBNTA_SENSE_ADDR (0x0C) + +/* SCSI IO SGLFlags bits */ + +/* base values for Data Location Address Space */ +#define MPI2_SCSIIO_SGLFLAGS_ADDR_MASK (0x0C) +#define MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR (0x00) +#define MPI2_SCSIIO_SGLFLAGS_IOCDDR_ADDR (0x04) +#define MPI2_SCSIIO_SGLFLAGS_IOCPLB_ADDR (0x08) +#define MPI2_SCSIIO_SGLFLAGS_IOCPLBNTA_ADDR (0x0C) + +/* base values for Type */ +#define MPI2_SCSIIO_SGLFLAGS_TYPE_MASK (0x03) +#define MPI2_SCSIIO_SGLFLAGS_TYPE_MPI (0x00) +#define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE32 (0x01) +#define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE64 (0x02) + +/* shift values for each sub-field */ +#define MPI2_SCSIIO_SGLFLAGS_SGL3_SHIFT (12) +#define MPI2_SCSIIO_SGLFLAGS_SGL2_SHIFT (8) +#define MPI2_SCSIIO_SGLFLAGS_SGL1_SHIFT (4) +#define MPI2_SCSIIO_SGLFLAGS_SGL0_SHIFT (0) + +/* SCSI IO IoFlags bits */ + +/* Large CDB Address Space */ +#define MPI2_SCSIIO_CDB_ADDR_MASK (0x6000) +#define MPI2_SCSIIO_CDB_ADDR_SYSTEM (0x0000) +#define MPI2_SCSIIO_CDB_ADDR_IOCDDR (0x2000) +#define MPI2_SCSIIO_CDB_ADDR_IOCPLB (0x4000) +#define MPI2_SCSIIO_CDB_ADDR_IOCPLBNTA (0x6000) + +#define MPI2_SCSIIO_IOFLAGS_LARGE_CDB (0x1000) +#define MPI2_SCSIIO_IOFLAGS_BIDIRECTIONAL (0x0800) +#define MPI2_SCSIIO_IOFLAGS_MULTICAST (0x0400) +#define MPI2_SCSIIO_IOFLAGS_CMD_DETERMINES_DATA_DIR (0x0200) +#define MPI2_SCSIIO_IOFLAGS_CDBLENGTH_MASK (0x01FF) + +/* SCSI IO EEDPFlags bits */ + +#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG (0x8000) +#define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_REFTAG (0x4000) +#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_APPTAG (0x2000) +#define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_APPTAG (0x1000) + +#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG (0x0400) +#define MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG (0x0200) +#define MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD (0x0100) + +#define MPI2_SCSIIO_EEDPFLAGS_PASSTHRU_REFTAG (0x0008) + +#define MPI2_SCSIIO_EEDPFLAGS_MASK_OP (0x0007) +#define MPI2_SCSIIO_EEDPFLAGS_NOOP_OP (0x0000) +#define MPI2_SCSIIO_EEDPFLAGS_CHECK_OP (0x0001) +#define MPI2_SCSIIO_EEDPFLAGS_STRIP_OP (0x0002) +#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP (0x0003) +#define MPI2_SCSIIO_EEDPFLAGS_INSERT_OP (0x0004) +#define MPI2_SCSIIO_EEDPFLAGS_REPLACE_OP (0x0006) +#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REGEN_OP (0x0007) + +/* SCSI IO LUN fields: use MPI2_LUN_ from mpi2.h */ + +/* SCSI IO Control bits */ +#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_MASK (0xFC000000) +#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT (26) + +#define MPI2_SCSIIO_CONTROL_DATADIRECTION_MASK (0x03000000) +#define MPI2_SCSIIO_CONTROL_NODATATRANSFER (0x00000000) +#define MPI2_SCSIIO_CONTROL_WRITE (0x01000000) +#define MPI2_SCSIIO_CONTROL_READ (0x02000000) +#define MPI2_SCSIIO_CONTROL_BIDIRECTIONAL (0x03000000) + +#define MPI2_SCSIIO_CONTROL_TASKPRI_MASK (0x00007800) +#define MPI2_SCSIIO_CONTROL_TASKPRI_SHIFT (11) + +#define MPI2_SCSIIO_CONTROL_TASKATTRIBUTE_MASK (0x00000700) +#define MPI2_SCSIIO_CONTROL_SIMPLEQ (0x00000000) +#define MPI2_SCSIIO_CONTROL_HEADOFQ (0x00000100) +#define MPI2_SCSIIO_CONTROL_ORDEREDQ (0x00000200) +#define MPI2_SCSIIO_CONTROL_ACAQ (0x00000400) + +#define MPI2_SCSIIO_CONTROL_TLR_MASK (0x000000C0) +#define MPI2_SCSIIO_CONTROL_NO_TLR (0x00000000) +#define MPI2_SCSIIO_CONTROL_TLR_ON (0x00000040) +#define MPI2_SCSIIO_CONTROL_TLR_OFF (0x00000080) + + +/* SCSI IO Error Reply Message */ +typedef struct _MPI2_SCSI_IO_REPLY +{ + U16 DevHandle; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved1; /* 0x04 */ + U8 Reserved2; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U8 SCSIStatus; /* 0x0C */ + U8 SCSIState; /* 0x0D */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U32 TransferCount; /* 0x14 */ + U32 SenseCount; /* 0x18 */ + U32 ResponseInfo; /* 0x1C */ + U16 TaskTag; /* 0x20 */ + U16 Reserved4; /* 0x22 */ + U32 BidirectionalTransferCount; /* 0x24 */ + U32 Reserved5; /* 0x28 */ + U32 Reserved6; /* 0x2C */ +} MPI2_SCSI_IO_REPLY, MPI2_POINTER PTR_MPI2_SCSI_IO_REPLY, + Mpi2SCSIIOReply_t, MPI2_POINTER pMpi2SCSIIOReply_t; + +/* SCSI IO Reply SCSIStatus values (SAM-4 status codes) */ + +#define MPI2_SCSI_STATUS_GOOD (0x00) +#define MPI2_SCSI_STATUS_CHECK_CONDITION (0x02) +#define MPI2_SCSI_STATUS_CONDITION_MET (0x04) +#define MPI2_SCSI_STATUS_BUSY (0x08) +#define MPI2_SCSI_STATUS_INTERMEDIATE (0x10) +#define MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET (0x14) +#define MPI2_SCSI_STATUS_RESERVATION_CONFLICT (0x18) +#define MPI2_SCSI_STATUS_COMMAND_TERMINATED (0x22) /* obsolete */ +#define MPI2_SCSI_STATUS_TASK_SET_FULL (0x28) +#define MPI2_SCSI_STATUS_ACA_ACTIVE (0x30) +#define MPI2_SCSI_STATUS_TASK_ABORTED (0x40) + +/* SCSI IO Reply SCSIState flags */ + +#define MPI2_SCSI_STATE_RESPONSE_INFO_VALID (0x10) +#define MPI2_SCSI_STATE_TERMINATED (0x08) +#define MPI2_SCSI_STATE_NO_SCSI_STATUS (0x04) +#define MPI2_SCSI_STATE_AUTOSENSE_FAILED (0x02) +#define MPI2_SCSI_STATE_AUTOSENSE_VALID (0x01) + +#define MPI2_SCSI_TASKTAG_UNKNOWN (0xFFFF) + + +/**************************************************************************** +* SCSI Task Management messages +****************************************************************************/ + +/* SCSI Task Management Request Message */ +typedef struct _MPI2_SCSI_TASK_MANAGE_REQUEST +{ + U16 DevHandle; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U8 Reserved1; /* 0x04 */ + U8 TaskType; /* 0x05 */ + U8 Reserved2; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U8 LUN[8]; /* 0x0C */ + U32 Reserved4[7]; /* 0x14 */ + U16 TaskMID; /* 0x30 */ + U16 Reserved5; /* 0x32 */ +} MPI2_SCSI_TASK_MANAGE_REQUEST, + MPI2_POINTER PTR_MPI2_SCSI_TASK_MANAGE_REQUEST, + Mpi2SCSITaskManagementRequest_t, + MPI2_POINTER pMpi2SCSITaskManagementRequest_t; + +/* TaskType values */ + +#define MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK (0x01) +#define MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET (0x02) +#define MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET (0x03) +#define MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05) +#define MPI2_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET (0x06) +#define MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07) +#define MPI2_SCSITASKMGMT_TASKTYPE_CLR_ACA (0x08) +#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_TASK_SET (0x09) +#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION (0x0A) + +/* MsgFlags bits */ + +#define MPI2_SCSITASKMGMT_MSGFLAGS_MASK_TARGET_RESET (0x18) +#define MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET (0x00) +#define MPI2_SCSITASKMGMT_MSGFLAGS_NEXUS_RESET_SRST (0x08) +#define MPI2_SCSITASKMGMT_MSGFLAGS_SAS_HARD_LINK_RESET (0x10) + +#define MPI2_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU (0x01) + + + +/* SCSI Task Management Reply Message */ +typedef struct _MPI2_SCSI_TASK_MANAGE_REPLY +{ + U16 DevHandle; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U8 ResponseCode; /* 0x04 */ + U8 TaskType; /* 0x05 */ + U8 Reserved1; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved2; /* 0x0A */ + U16 Reserved3; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U32 TerminationCount; /* 0x14 */ +} MPI2_SCSI_TASK_MANAGE_REPLY, + MPI2_POINTER PTR_MPI2_SCSI_TASK_MANAGE_REPLY, + Mpi2SCSITaskManagementReply_t, MPI2_POINTER pMpi2SCSIManagementReply_t; + +/* ResponseCode values */ + +#define MPI2_SCSITASKMGMT_RSP_TM_COMPLETE (0x00) +#define MPI2_SCSITASKMGMT_RSP_INVALID_FRAME (0x02) +#define MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED (0x04) +#define MPI2_SCSITASKMGMT_RSP_TM_FAILED (0x05) +#define MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED (0x08) +#define MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN (0x09) +#define MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC (0x80) + + +/**************************************************************************** +* SCSI Enclosure Processor messages +****************************************************************************/ + +/* SCSI Enclosure Processor Request Message */ +typedef struct _MPI2_SEP_REQUEST +{ + U16 DevHandle; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U8 Action; /* 0x04 */ + U8 Flags; /* 0x05 */ + U8 Reserved1; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved2; /* 0x0A */ + U32 SlotStatus; /* 0x0C */ + U32 Reserved3; /* 0x10 */ + U32 Reserved4; /* 0x14 */ + U32 Reserved5; /* 0x18 */ + U16 Slot; /* 0x1C */ + U16 EnclosureHandle; /* 0x1E */ +} MPI2_SEP_REQUEST, MPI2_POINTER PTR_MPI2_SEP_REQUEST, + Mpi2SepRequest_t, MPI2_POINTER pMpi2SepRequest_t; + +/* Action defines */ +#define MPI2_SEP_REQ_ACTION_WRITE_STATUS (0x00) +#define MPI2_SEP_REQ_ACTION_READ_STATUS (0x01) + +/* Flags defines */ +#define MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS (0x00) +#define MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS (0x01) + +/* SlotStatus defines */ +#define MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE (0x00040000) +#define MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000) +#define MPI2_SEP_REQ_SLOTSTATUS_REBUILD_STOPPED (0x00000200) +#define MPI2_SEP_REQ_SLOTSTATUS_HOT_SPARE (0x00000100) +#define MPI2_SEP_REQ_SLOTSTATUS_UNCONFIGURED (0x00000080) +#define MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT (0x00000040) +#define MPI2_SEP_REQ_SLOTSTATUS_DEV_REBUILDING (0x00000004) +#define MPI2_SEP_REQ_SLOTSTATUS_DEV_FAULTY (0x00000002) +#define MPI2_SEP_REQ_SLOTSTATUS_NO_ERROR (0x00000001) + + +/* SCSI Enclosure Processor Reply Message */ +typedef struct _MPI2_SEP_REPLY +{ + U16 DevHandle; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U8 Action; /* 0x04 */ + U8 Flags; /* 0x05 */ + U8 Reserved1; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved2; /* 0x0A */ + U16 Reserved3; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U32 SlotStatus; /* 0x14 */ + U32 Reserved4; /* 0x18 */ + U16 Slot; /* 0x1C */ + U16 EnclosureHandle; /* 0x1E */ +} MPI2_SEP_REPLY, MPI2_POINTER PTR_MPI2_SEP_REPLY, + Mpi2SepReply_t, MPI2_POINTER pMpi2SepReply_t; + +/* SlotStatus defines */ +#define MPI2_SEP_REPLY_SLOTSTATUS_REMOVE_READY (0x00040000) +#define MPI2_SEP_REPLY_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000) +#define MPI2_SEP_REPLY_SLOTSTATUS_REBUILD_STOPPED (0x00000200) +#define MPI2_SEP_REPLY_SLOTSTATUS_HOT_SPARE (0x00000100) +#define MPI2_SEP_REPLY_SLOTSTATUS_UNCONFIGURED (0x00000080) +#define MPI2_SEP_REPLY_SLOTSTATUS_PREDICTED_FAULT (0x00000040) +#define MPI2_SEP_REPLY_SLOTSTATUS_DEV_REBUILDING (0x00000004) +#define MPI2_SEP_REPLY_SLOTSTATUS_DEV_FAULTY (0x00000002) +#define MPI2_SEP_REPLY_SLOTSTATUS_NO_ERROR (0x00000001) + + +#endif + + diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h new file mode 100644 index 00000000000..8c5d81870c0 --- /dev/null +++ b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h @@ -0,0 +1,1295 @@ +/* + * Copyright (c) 2000-2009 LSI Corporation. + * + * + * Name: mpi2_ioc.h + * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages + * Creation Date: October 11, 2006 + * + * mpi2_ioc.h Version: 02.00.10 + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 06-04-07 02.00.01 In IOCFacts Reply structure, renamed MaxDevices to + * MaxTargets. + * Added TotalImageSize field to FWDownload Request. + * Added reserved words to FWUpload Request. + * 06-26-07 02.00.02 Added IR Configuration Change List Event. + * 08-31-07 02.00.03 Removed SystemReplyQueueDepth field from the IOCInit + * request and replaced it with + * ReplyDescriptorPostQueueDepth and ReplyFreeQueueDepth. + * Replaced the MinReplyQueueDepth field of the IOCFacts + * reply with MaxReplyDescriptorPostQueueDepth. + * Added MPI2_RDPQ_DEPTH_MIN define to specify the minimum + * depth for the Reply Descriptor Post Queue. + * Added SASAddress field to Initiator Device Table + * Overflow Event data. + * 10-31-07 02.00.04 Added ReasonCode MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING + * for SAS Initiator Device Status Change Event data. + * Modified Reason Code defines for SAS Topology Change + * List Event data, including adding a bit for PHY Vacant + * status, and adding a mask for the Reason Code. + * Added define for + * MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING. + * Added define for MPI2_EXT_IMAGE_TYPE_MEGARAID. + * 12-18-07 02.00.05 Added Boot Status defines for the IOCExceptions field of + * the IOCFacts Reply. + * Removed MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define. + * Moved MPI2_VERSION_UNION to mpi2.h. + * Changed MPI2_EVENT_NOTIFICATION_REQUEST to use masks + * instead of enables, and added SASBroadcastPrimitiveMasks + * field. + * Added Log Entry Added Event and related structure. + * 02-29-08 02.00.06 Added define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID. + * Removed define MPI2_IOCFACTS_PROTOCOL_SMP_TARGET. + * Added MaxVolumes and MaxPersistentEntries fields to + * IOCFacts reply. + * Added ProtocalFlags and IOCCapabilities fields to + * MPI2_FW_IMAGE_HEADER. + * Removed MPI2_PORTENABLE_FLAGS_ENABLE_SINGLE_PORT. + * 03-03-08 02.00.07 Fixed MPI2_FW_IMAGE_HEADER by changing Reserved26 to + * a U16 (from a U32). + * Removed extra 's' from EventMasks name. + * 06-27-08 02.00.08 Fixed an offset in a comment. + * 10-02-08 02.00.09 Removed SystemReplyFrameSize from MPI2_IOC_INIT_REQUEST. + * Removed CurReplyFrameSize from MPI2_IOC_FACTS_REPLY and + * renamed MinReplyFrameSize to ReplyFrameSize. + * Added MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX. + * Added two new RAIDOperation values for Integrated RAID + * Operations Status Event data. + * Added four new IR Configuration Change List Event data + * ReasonCode values. + * Added two new ReasonCode defines for SAS Device Status + * Change Event data. + * Added three new DiscoveryStatus bits for the SAS + * Discovery event data. + * Added Multiplexing Status Change bit to the PhyStatus + * field of the SAS Topology Change List event data. + * Removed define for MPI2_INIT_IMAGE_BOOTFLAGS_XMEMCOPY. + * BootFlags are now product-specific. + * Added defines for the indivdual signature bytes + * for MPI2_INIT_IMAGE_FOOTER. + * 01-19-09 02.00.10 Added MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY define. + * Added MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR + * define. + * Added MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE + * define. + * Removed MPI2_EVENT_SAS_DISC_DS_SATA_INIT_FAILURE define. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI2_IOC_H +#define MPI2_IOC_H + +/***************************************************************************** +* +* IOC Messages +* +*****************************************************************************/ + +/**************************************************************************** +* IOCInit message +****************************************************************************/ + +/* IOCInit Request message */ +typedef struct _MPI2_IOC_INIT_REQUEST +{ + U8 WhoInit; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 MsgVersion; /* 0x0C */ + U16 HeaderVersion; /* 0x0E */ + U32 Reserved5; /* 0x10 */ + U32 Reserved6; /* 0x14 */ + U16 Reserved7; /* 0x18 */ + U16 SystemRequestFrameSize; /* 0x1A */ + U16 ReplyDescriptorPostQueueDepth; /* 0x1C */ + U16 ReplyFreeQueueDepth; /* 0x1E */ + U32 SenseBufferAddressHigh; /* 0x20 */ + U32 SystemReplyAddressHigh; /* 0x24 */ + U64 SystemRequestFrameBaseAddress; /* 0x28 */ + U64 ReplyDescriptorPostQueueAddress;/* 0x30 */ + U64 ReplyFreeQueueAddress; /* 0x38 */ + U64 TimeStamp; /* 0x40 */ +} MPI2_IOC_INIT_REQUEST, MPI2_POINTER PTR_MPI2_IOC_INIT_REQUEST, + Mpi2IOCInitRequest_t, MPI2_POINTER pMpi2IOCInitRequest_t; + +/* WhoInit values */ +#define MPI2_WHOINIT_NOT_INITIALIZED (0x00) +#define MPI2_WHOINIT_SYSTEM_BIOS (0x01) +#define MPI2_WHOINIT_ROM_BIOS (0x02) +#define MPI2_WHOINIT_PCI_PEER (0x03) +#define MPI2_WHOINIT_HOST_DRIVER (0x04) +#define MPI2_WHOINIT_MANUFACTURER (0x05) + +/* MsgVersion */ +#define MPI2_IOCINIT_MSGVERSION_MAJOR_MASK (0xFF00) +#define MPI2_IOCINIT_MSGVERSION_MAJOR_SHIFT (8) +#define MPI2_IOCINIT_MSGVERSION_MINOR_MASK (0x00FF) +#define MPI2_IOCINIT_MSGVERSION_MINOR_SHIFT (0) + +/* HeaderVersion */ +#define MPI2_IOCINIT_HDRVERSION_UNIT_MASK (0xFF00) +#define MPI2_IOCINIT_HDRVERSION_UNIT_SHIFT (8) +#define MPI2_IOCINIT_HDRVERSION_DEV_MASK (0x00FF) +#define MPI2_IOCINIT_HDRVERSION_DEV_SHIFT (0) + +/* minimum depth for the Reply Descriptor Post Queue */ +#define MPI2_RDPQ_DEPTH_MIN (16) + + +/* IOCInit Reply message */ +typedef struct _MPI2_IOC_INIT_REPLY +{ + U8 WhoInit; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 Reserved5; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ +} MPI2_IOC_INIT_REPLY, MPI2_POINTER PTR_MPI2_IOC_INIT_REPLY, + Mpi2IOCInitReply_t, MPI2_POINTER pMpi2IOCInitReply_t; + + +/**************************************************************************** +* IOCFacts message +****************************************************************************/ + +/* IOCFacts Request message */ +typedef struct _MPI2_IOC_FACTS_REQUEST +{ + U16 Reserved1; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ +} MPI2_IOC_FACTS_REQUEST, MPI2_POINTER PTR_MPI2_IOC_FACTS_REQUEST, + Mpi2IOCFactsRequest_t, MPI2_POINTER pMpi2IOCFactsRequest_t; + + +/* IOCFacts Reply message */ +typedef struct _MPI2_IOC_FACTS_REPLY +{ + U16 MsgVersion; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 HeaderVersion; /* 0x04 */ + U8 IOCNumber; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved1; /* 0x0A */ + U16 IOCExceptions; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U8 MaxChainDepth; /* 0x14 */ + U8 WhoInit; /* 0x15 */ + U8 NumberOfPorts; /* 0x16 */ + U8 Reserved2; /* 0x17 */ + U16 RequestCredit; /* 0x18 */ + U16 ProductID; /* 0x1A */ + U32 IOCCapabilities; /* 0x1C */ + MPI2_VERSION_UNION FWVersion; /* 0x20 */ + U16 IOCRequestFrameSize; /* 0x24 */ + U16 Reserved3; /* 0x26 */ + U16 MaxInitiators; /* 0x28 */ + U16 MaxTargets; /* 0x2A */ + U16 MaxSasExpanders; /* 0x2C */ + U16 MaxEnclosures; /* 0x2E */ + U16 ProtocolFlags; /* 0x30 */ + U16 HighPriorityCredit; /* 0x32 */ + U16 MaxReplyDescriptorPostQueueDepth; /* 0x34 */ + U8 ReplyFrameSize; /* 0x36 */ + U8 MaxVolumes; /* 0x37 */ + U16 MaxDevHandle; /* 0x38 */ + U16 MaxPersistentEntries; /* 0x3A */ + U32 Reserved4; /* 0x3C */ +} MPI2_IOC_FACTS_REPLY, MPI2_POINTER PTR_MPI2_IOC_FACTS_REPLY, + Mpi2IOCFactsReply_t, MPI2_POINTER pMpi2IOCFactsReply_t; + +/* MsgVersion */ +#define MPI2_IOCFACTS_MSGVERSION_MAJOR_MASK (0xFF00) +#define MPI2_IOCFACTS_MSGVERSION_MAJOR_SHIFT (8) +#define MPI2_IOCFACTS_MSGVERSION_MINOR_MASK (0x00FF) +#define MPI2_IOCFACTS_MSGVERSION_MINOR_SHIFT (0) + +/* HeaderVersion */ +#define MPI2_IOCFACTS_HDRVERSION_UNIT_MASK (0xFF00) +#define MPI2_IOCFACTS_HDRVERSION_UNIT_SHIFT (8) +#define MPI2_IOCFACTS_HDRVERSION_DEV_MASK (0x00FF) +#define MPI2_IOCFACTS_HDRVERSION_DEV_SHIFT (0) + +/* IOCExceptions */ +#define MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX (0x0100) + +#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_MASK (0x00E0) +#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_GOOD (0x0000) +#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_BACKUP (0x0020) +#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_RESTORED (0x0040) +#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_CORRUPT_BACKUP (0x0060) + +#define MPI2_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED (0x0010) +#define MPI2_IOCFACTS_EXCEPT_MANUFACT_CHECKSUM_FAIL (0x0008) +#define MPI2_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL (0x0004) +#define MPI2_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID (0x0002) +#define MPI2_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL (0x0001) + +/* defines for WhoInit field are after the IOCInit Request */ + +/* ProductID field uses MPI2_FW_HEADER_PID_ */ + +/* IOCCapabilities */ +#define MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY (0x00002000) +#define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID (0x00001000) +#define MPI2_IOCFACTS_CAPABILITY_TLR (0x00000800) +#define MPI2_IOCFACTS_CAPABILITY_MULTICAST (0x00000100) +#define MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET (0x00000080) +#define MPI2_IOCFACTS_CAPABILITY_EEDP (0x00000040) +#define MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER (0x00000010) +#define MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER (0x00000008) +#define MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING (0x00000004) + +/* ProtocolFlags */ +#define MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET (0x0001) +#define MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR (0x0002) + + +/**************************************************************************** +* PortFacts message +****************************************************************************/ + +/* PortFacts Request message */ +typedef struct _MPI2_PORT_FACTS_REQUEST +{ + U16 Reserved1; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 PortNumber; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ +} MPI2_PORT_FACTS_REQUEST, MPI2_POINTER PTR_MPI2_PORT_FACTS_REQUEST, + Mpi2PortFactsRequest_t, MPI2_POINTER pMpi2PortFactsRequest_t; + +/* PortFacts Reply message */ +typedef struct _MPI2_PORT_FACTS_REPLY +{ + U16 Reserved1; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 PortNumber; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U16 Reserved4; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U8 Reserved5; /* 0x14 */ + U8 PortType; /* 0x15 */ + U16 Reserved6; /* 0x16 */ + U16 MaxPostedCmdBuffers; /* 0x18 */ + U16 Reserved7; /* 0x1A */ +} MPI2_PORT_FACTS_REPLY, MPI2_POINTER PTR_MPI2_PORT_FACTS_REPLY, + Mpi2PortFactsReply_t, MPI2_POINTER pMpi2PortFactsReply_t; + +/* PortType values */ +#define MPI2_PORTFACTS_PORTTYPE_INACTIVE (0x00) +#define MPI2_PORTFACTS_PORTTYPE_FC (0x10) +#define MPI2_PORTFACTS_PORTTYPE_ISCSI (0x20) +#define MPI2_PORTFACTS_PORTTYPE_SAS_PHYSICAL (0x30) +#define MPI2_PORTFACTS_PORTTYPE_SAS_VIRTUAL (0x31) + + +/**************************************************************************** +* PortEnable message +****************************************************************************/ + +/* PortEnable Request message */ +typedef struct _MPI2_PORT_ENABLE_REQUEST +{ + U16 Reserved1; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U8 Reserved2; /* 0x04 */ + U8 PortFlags; /* 0x05 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ +} MPI2_PORT_ENABLE_REQUEST, MPI2_POINTER PTR_MPI2_PORT_ENABLE_REQUEST, + Mpi2PortEnableRequest_t, MPI2_POINTER pMpi2PortEnableRequest_t; + + +/* PortEnable Reply message */ +typedef struct _MPI2_PORT_ENABLE_REPLY +{ + U16 Reserved1; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U8 Reserved2; /* 0x04 */ + U8 PortFlags; /* 0x05 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 Reserved5; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ +} MPI2_PORT_ENABLE_REPLY, MPI2_POINTER PTR_MPI2_PORT_ENABLE_REPLY, + Mpi2PortEnableReply_t, MPI2_POINTER pMpi2PortEnableReply_t; + + +/**************************************************************************** +* EventNotification message +****************************************************************************/ + +/* EventNotification Request message */ +#define MPI2_EVENT_NOTIFY_EVENTMASK_WORDS (4) + +typedef struct _MPI2_EVENT_NOTIFICATION_REQUEST +{ + U16 Reserved1; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U32 Reserved5; /* 0x0C */ + U32 Reserved6; /* 0x10 */ + U32 EventMasks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];/* 0x14 */ + U16 SASBroadcastPrimitiveMasks; /* 0x24 */ + U16 Reserved7; /* 0x26 */ + U32 Reserved8; /* 0x28 */ +} MPI2_EVENT_NOTIFICATION_REQUEST, + MPI2_POINTER PTR_MPI2_EVENT_NOTIFICATION_REQUEST, + Mpi2EventNotificationRequest_t, MPI2_POINTER pMpi2EventNotificationRequest_t; + + +/* EventNotification Reply message */ +typedef struct _MPI2_EVENT_NOTIFICATION_REPLY +{ + U16 EventDataLength; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved1; /* 0x04 */ + U8 AckRequired; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved2; /* 0x0A */ + U16 Reserved3; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U16 Event; /* 0x14 */ + U16 Reserved4; /* 0x16 */ + U32 EventContext; /* 0x18 */ + U32 EventData[1]; /* 0x1C */ +} MPI2_EVENT_NOTIFICATION_REPLY, MPI2_POINTER PTR_MPI2_EVENT_NOTIFICATION_REPLY, + Mpi2EventNotificationReply_t, MPI2_POINTER pMpi2EventNotificationReply_t; + +/* AckRequired */ +#define MPI2_EVENT_NOTIFICATION_ACK_NOT_REQUIRED (0x00) +#define MPI2_EVENT_NOTIFICATION_ACK_REQUIRED (0x01) + +/* Event */ +#define MPI2_EVENT_LOG_DATA (0x0001) +#define MPI2_EVENT_STATE_CHANGE (0x0002) +#define MPI2_EVENT_HARD_RESET_RECEIVED (0x0005) +#define MPI2_EVENT_EVENT_CHANGE (0x000A) +#define MPI2_EVENT_TASK_SET_FULL (0x000E) +#define MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE (0x000F) +#define MPI2_EVENT_IR_OPERATION_STATUS (0x0014) +#define MPI2_EVENT_SAS_DISCOVERY (0x0016) +#define MPI2_EVENT_SAS_BROADCAST_PRIMITIVE (0x0017) +#define MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE (0x0018) +#define MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW (0x0019) +#define MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST (0x001C) +#define MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE (0x001D) +#define MPI2_EVENT_IR_VOLUME (0x001E) +#define MPI2_EVENT_IR_PHYSICAL_DISK (0x001F) +#define MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST (0x0020) +#define MPI2_EVENT_LOG_ENTRY_ADDED (0x0021) + + +/* Log Entry Added Event data */ + +/* the following structure matches MPI2_LOG_0_ENTRY in mpi2_cnfg.h */ +#define MPI2_EVENT_DATA_LOG_DATA_LENGTH (0x1C) + +typedef struct _MPI2_EVENT_DATA_LOG_ENTRY_ADDED +{ + U64 TimeStamp; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U16 LogSequence; /* 0x0C */ + U16 LogEntryQualifier; /* 0x0E */ + U8 VP_ID; /* 0x10 */ + U8 VF_ID; /* 0x11 */ + U16 Reserved2; /* 0x12 */ + U8 LogData[MPI2_EVENT_DATA_LOG_DATA_LENGTH];/* 0x14 */ +} MPI2_EVENT_DATA_LOG_ENTRY_ADDED, + MPI2_POINTER PTR_MPI2_EVENT_DATA_LOG_ENTRY_ADDED, + Mpi2EventDataLogEntryAdded_t, MPI2_POINTER pMpi2EventDataLogEntryAdded_t; + +/* Hard Reset Received Event data */ + +typedef struct _MPI2_EVENT_DATA_HARD_RESET_RECEIVED +{ + U8 Reserved1; /* 0x00 */ + U8 Port; /* 0x01 */ + U16 Reserved2; /* 0x02 */ +} MPI2_EVENT_DATA_HARD_RESET_RECEIVED, + MPI2_POINTER PTR_MPI2_EVENT_DATA_HARD_RESET_RECEIVED, + Mpi2EventDataHardResetReceived_t, + MPI2_POINTER pMpi2EventDataHardResetReceived_t; + +/* Task Set Full Event data */ + +typedef struct _MPI2_EVENT_DATA_TASK_SET_FULL +{ + U16 DevHandle; /* 0x00 */ + U16 CurrentDepth; /* 0x02 */ +} MPI2_EVENT_DATA_TASK_SET_FULL, MPI2_POINTER PTR_MPI2_EVENT_DATA_TASK_SET_FULL, + Mpi2EventDataTaskSetFull_t, MPI2_POINTER pMpi2EventDataTaskSetFull_t; + + +/* SAS Device Status Change Event data */ + +typedef struct _MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE +{ + U16 TaskTag; /* 0x00 */ + U8 ReasonCode; /* 0x02 */ + U8 Reserved1; /* 0x03 */ + U8 ASC; /* 0x04 */ + U8 ASCQ; /* 0x05 */ + U16 DevHandle; /* 0x06 */ + U32 Reserved2; /* 0x08 */ + U64 SASAddress; /* 0x0C */ + U8 LUN[8]; /* 0x14 */ +} MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE, + MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE, + Mpi2EventDataSasDeviceStatusChange_t, + MPI2_POINTER pMpi2EventDataSasDeviceStatusChange_t; + +/* SAS Device Status Change Event data ReasonCode values */ +#define MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05) +#define MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07) +#define MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08) +#define MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL (0x09) +#define MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL (0x0A) +#define MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL (0x0B) +#define MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL (0x0C) +#define MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION (0x0D) +#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET (0x0E) +#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL (0x0F) +#define MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE (0x10) + + +/* Integrated RAID Operation Status Event data */ + +typedef struct _MPI2_EVENT_DATA_IR_OPERATION_STATUS +{ + U16 VolDevHandle; /* 0x00 */ + U16 Reserved1; /* 0x02 */ + U8 RAIDOperation; /* 0x04 */ + U8 PercentComplete; /* 0x05 */ + U16 Reserved2; /* 0x06 */ + U32 Resereved3; /* 0x08 */ +} MPI2_EVENT_DATA_IR_OPERATION_STATUS, + MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_OPERATION_STATUS, + Mpi2EventDataIrOperationStatus_t, + MPI2_POINTER pMpi2EventDataIrOperationStatus_t; + +/* Integrated RAID Operation Status Event data RAIDOperation values */ +#define MPI2_EVENT_IR_RAIDOP_RESYNC (0x00) +#define MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION (0x01) +#define MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK (0x02) +#define MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT (0x03) +#define MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT (0x04) + + +/* Integrated RAID Volume Event data */ + +typedef struct _MPI2_EVENT_DATA_IR_VOLUME +{ + U16 VolDevHandle; /* 0x00 */ + U8 ReasonCode; /* 0x02 */ + U8 Reserved1; /* 0x03 */ + U32 NewValue; /* 0x04 */ + U32 PreviousValue; /* 0x08 */ +} MPI2_EVENT_DATA_IR_VOLUME, MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_VOLUME, + Mpi2EventDataIrVolume_t, MPI2_POINTER pMpi2EventDataIrVolume_t; + +/* Integrated RAID Volume Event data ReasonCode values */ +#define MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED (0x01) +#define MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED (0x02) +#define MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED (0x03) + + +/* Integrated RAID Physical Disk Event data */ + +typedef struct _MPI2_EVENT_DATA_IR_PHYSICAL_DISK +{ + U16 Reserved1; /* 0x00 */ + U8 ReasonCode; /* 0x02 */ + U8 PhysDiskNum; /* 0x03 */ + U16 PhysDiskDevHandle; /* 0x04 */ + U16 Reserved2; /* 0x06 */ + U16 Slot; /* 0x08 */ + U16 EnclosureHandle; /* 0x0A */ + U32 NewValue; /* 0x0C */ + U32 PreviousValue; /* 0x10 */ +} MPI2_EVENT_DATA_IR_PHYSICAL_DISK, + MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_PHYSICAL_DISK, + Mpi2EventDataIrPhysicalDisk_t, MPI2_POINTER pMpi2EventDataIrPhysicalDisk_t; + +/* Integrated RAID Physical Disk Event data ReasonCode values */ +#define MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED (0x01) +#define MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED (0x02) +#define MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED (0x03) + + +/* Integrated RAID Configuration Change List Event data */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check NumElements at runtime. + */ +#ifndef MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT +#define MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT (1) +#endif + +typedef struct _MPI2_EVENT_IR_CONFIG_ELEMENT +{ + U16 ElementFlags; /* 0x00 */ + U16 VolDevHandle; /* 0x02 */ + U8 ReasonCode; /* 0x04 */ + U8 PhysDiskNum; /* 0x05 */ + U16 PhysDiskDevHandle; /* 0x06 */ +} MPI2_EVENT_IR_CONFIG_ELEMENT, MPI2_POINTER PTR_MPI2_EVENT_IR_CONFIG_ELEMENT, + Mpi2EventIrConfigElement_t, MPI2_POINTER pMpi2EventIrConfigElement_t; + +/* IR Configuration Change List Event data ElementFlags values */ +#define MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK (0x000F) +#define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT (0x0000) +#define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT (0x0001) +#define MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT (0x0002) + +/* IR Configuration Change List Event data ReasonCode values */ +#define MPI2_EVENT_IR_CHANGE_RC_ADDED (0x01) +#define MPI2_EVENT_IR_CHANGE_RC_REMOVED (0x02) +#define MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE (0x03) +#define MPI2_EVENT_IR_CHANGE_RC_HIDE (0x04) +#define MPI2_EVENT_IR_CHANGE_RC_UNHIDE (0x05) +#define MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED (0x06) +#define MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED (0x07) +#define MPI2_EVENT_IR_CHANGE_RC_PD_CREATED (0x08) +#define MPI2_EVENT_IR_CHANGE_RC_PD_DELETED (0x09) + +typedef struct _MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST +{ + U8 NumElements; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 Reserved2; /* 0x02 */ + U8 ConfigNum; /* 0x03 */ + U32 Flags; /* 0x04 */ + MPI2_EVENT_IR_CONFIG_ELEMENT ConfigElement[MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT]; /* 0x08 */ +} MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST, + MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST, + Mpi2EventDataIrConfigChangeList_t, + MPI2_POINTER pMpi2EventDataIrConfigChangeList_t; + +/* IR Configuration Change List Event data Flags values */ +#define MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG (0x00000001) + + +/* SAS Discovery Event data */ + +typedef struct _MPI2_EVENT_DATA_SAS_DISCOVERY +{ + U8 Flags; /* 0x00 */ + U8 ReasonCode; /* 0x01 */ + U8 PhysicalPort; /* 0x02 */ + U8 Reserved1; /* 0x03 */ + U32 DiscoveryStatus; /* 0x04 */ +} MPI2_EVENT_DATA_SAS_DISCOVERY, + MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_DISCOVERY, + Mpi2EventDataSasDiscovery_t, MPI2_POINTER pMpi2EventDataSasDiscovery_t; + +/* SAS Discovery Event data Flags values */ +#define MPI2_EVENT_SAS_DISC_DEVICE_CHANGE (0x02) +#define MPI2_EVENT_SAS_DISC_IN_PROGRESS (0x01) + +/* SAS Discovery Event data ReasonCode values */ +#define MPI2_EVENT_SAS_DISC_RC_STARTED (0x01) +#define MPI2_EVENT_SAS_DISC_RC_COMPLETED (0x02) + +/* SAS Discovery Event data DiscoveryStatus values */ +#define MPI2_EVENT_SAS_DISC_DS_MAX_ENCLOSURES_EXCEED (0x80000000) +#define MPI2_EVENT_SAS_DISC_DS_MAX_EXPANDERS_EXCEED (0x40000000) +#define MPI2_EVENT_SAS_DISC_DS_MAX_DEVICES_EXCEED (0x20000000) +#define MPI2_EVENT_SAS_DISC_DS_MAX_TOPO_PHYS_EXCEED (0x10000000) +#define MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR (0x08000000) +#define MPI2_EVENT_SAS_DISC_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000) +#define MPI2_EVENT_SAS_DISC_DS_EXP_MULTI_SUBTRACTIVE (0x00004000) +#define MPI2_EVENT_SAS_DISC_DS_MULTI_PORT_DOMAIN (0x00002000) +#define MPI2_EVENT_SAS_DISC_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000) +#define MPI2_EVENT_SAS_DISC_DS_UNSUPPORTED_DEVICE (0x00000800) +#define MPI2_EVENT_SAS_DISC_DS_TABLE_LINK (0x00000400) +#define MPI2_EVENT_SAS_DISC_DS_SUBTRACTIVE_LINK (0x00000200) +#define MPI2_EVENT_SAS_DISC_DS_SMP_CRC_ERROR (0x00000100) +#define MPI2_EVENT_SAS_DISC_DS_SMP_FUNCTION_FAILED (0x00000080) +#define MPI2_EVENT_SAS_DISC_DS_INDEX_NOT_EXIST (0x00000040) +#define MPI2_EVENT_SAS_DISC_DS_OUT_ROUTE_ENTRIES (0x00000020) +#define MPI2_EVENT_SAS_DISC_DS_SMP_TIMEOUT (0x00000010) +#define MPI2_EVENT_SAS_DISC_DS_MULTIPLE_PORTS (0x00000004) +#define MPI2_EVENT_SAS_DISC_DS_UNADDRESSABLE_DEVICE (0x00000002) +#define MPI2_EVENT_SAS_DISC_DS_LOOP_DETECTED (0x00000001) + + +/* SAS Broadcast Primitive Event data */ + +typedef struct _MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE +{ + U8 PhyNum; /* 0x00 */ + U8 Port; /* 0x01 */ + U8 PortWidth; /* 0x02 */ + U8 Primitive; /* 0x03 */ +} MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE, + MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE, + Mpi2EventDataSasBroadcastPrimitive_t, + MPI2_POINTER pMpi2EventDataSasBroadcastPrimitive_t; + +/* defines for the Primitive field */ +#define MPI2_EVENT_PRIMITIVE_CHANGE (0x01) +#define MPI2_EVENT_PRIMITIVE_SES (0x02) +#define MPI2_EVENT_PRIMITIVE_EXPANDER (0x03) +#define MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT (0x04) +#define MPI2_EVENT_PRIMITIVE_RESERVED3 (0x05) +#define MPI2_EVENT_PRIMITIVE_RESERVED4 (0x06) +#define MPI2_EVENT_PRIMITIVE_CHANGE0_RESERVED (0x07) +#define MPI2_EVENT_PRIMITIVE_CHANGE1_RESERVED (0x08) + + +/* SAS Initiator Device Status Change Event data */ + +typedef struct _MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE +{ + U8 ReasonCode; /* 0x00 */ + U8 PhysicalPort; /* 0x01 */ + U16 DevHandle; /* 0x02 */ + U64 SASAddress; /* 0x04 */ +} MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE, + MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE, + Mpi2EventDataSasInitDevStatusChange_t, + MPI2_POINTER pMpi2EventDataSasInitDevStatusChange_t; + +/* SAS Initiator Device Status Change event ReasonCode values */ +#define MPI2_EVENT_SAS_INIT_RC_ADDED (0x01) +#define MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING (0x02) + + +/* SAS Initiator Device Table Overflow Event data */ + +typedef struct _MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW +{ + U16 MaxInit; /* 0x00 */ + U16 CurrentInit; /* 0x02 */ + U64 SASAddress; /* 0x04 */ +} MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW, + MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW, + Mpi2EventDataSasInitTableOverflow_t, + MPI2_POINTER pMpi2EventDataSasInitTableOverflow_t; + + +/* SAS Topology Change List Event data */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check NumEntries at runtime. + */ +#ifndef MPI2_EVENT_SAS_TOPO_PHY_COUNT +#define MPI2_EVENT_SAS_TOPO_PHY_COUNT (1) +#endif + +typedef struct _MPI2_EVENT_SAS_TOPO_PHY_ENTRY +{ + U16 AttachedDevHandle; /* 0x00 */ + U8 LinkRate; /* 0x02 */ + U8 PhyStatus; /* 0x03 */ +} MPI2_EVENT_SAS_TOPO_PHY_ENTRY, MPI2_POINTER PTR_MPI2_EVENT_SAS_TOPO_PHY_ENTRY, + Mpi2EventSasTopoPhyEntry_t, MPI2_POINTER pMpi2EventSasTopoPhyEntry_t; + +typedef struct _MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST +{ + U16 EnclosureHandle; /* 0x00 */ + U16 ExpanderDevHandle; /* 0x02 */ + U8 NumPhys; /* 0x04 */ + U8 Reserved1; /* 0x05 */ + U16 Reserved2; /* 0x06 */ + U8 NumEntries; /* 0x08 */ + U8 StartPhyNum; /* 0x09 */ + U8 ExpStatus; /* 0x0A */ + U8 PhysicalPort; /* 0x0B */ + MPI2_EVENT_SAS_TOPO_PHY_ENTRY PHY[MPI2_EVENT_SAS_TOPO_PHY_COUNT]; /* 0x0C*/ +} MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST, + MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST, + Mpi2EventDataSasTopologyChangeList_t, + MPI2_POINTER pMpi2EventDataSasTopologyChangeList_t; + +/* values for the ExpStatus field */ +#define MPI2_EVENT_SAS_TOPO_ES_ADDED (0x01) +#define MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING (0x02) +#define MPI2_EVENT_SAS_TOPO_ES_RESPONDING (0x03) +#define MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING (0x04) + +/* defines for the LinkRate field */ +#define MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK (0xF0) +#define MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT (4) +#define MPI2_EVENT_SAS_TOPO_LR_PREV_MASK (0x0F) +#define MPI2_EVENT_SAS_TOPO_LR_PREV_SHIFT (0) + +#define MPI2_EVENT_SAS_TOPO_LR_UNKNOWN_LINK_RATE (0x00) +#define MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED (0x01) +#define MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED (0x02) +#define MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE (0x03) +#define MPI2_EVENT_SAS_TOPO_LR_PORT_SELECTOR (0x04) +#define MPI2_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS (0x05) +#define MPI2_EVENT_SAS_TOPO_LR_RATE_1_5 (0x08) +#define MPI2_EVENT_SAS_TOPO_LR_RATE_3_0 (0x09) +#define MPI2_EVENT_SAS_TOPO_LR_RATE_6_0 (0x0A) + +/* values for the PhyStatus field */ +#define MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT (0x80) +#define MPI2_EVENT_SAS_TOPO_PS_MULTIPLEX_CHANGE (0x10) +/* values for the PhyStatus ReasonCode sub-field */ +#define MPI2_EVENT_SAS_TOPO_RC_MASK (0x0F) +#define MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED (0x01) +#define MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING (0x02) +#define MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED (0x03) +#define MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE (0x04) +#define MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING (0x05) + + +/* SAS Enclosure Device Status Change Event data */ + +typedef struct _MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE +{ + U16 EnclosureHandle; /* 0x00 */ + U8 ReasonCode; /* 0x02 */ + U8 PhysicalPort; /* 0x03 */ + U64 EnclosureLogicalID; /* 0x04 */ + U16 NumSlots; /* 0x0C */ + U16 StartSlot; /* 0x0E */ + U32 PhyBits; /* 0x10 */ +} MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE, + MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE, + Mpi2EventDataSasEnclDevStatusChange_t, + MPI2_POINTER pMpi2EventDataSasEnclDevStatusChange_t; + +/* SAS Enclosure Device Status Change event ReasonCode values */ +#define MPI2_EVENT_SAS_ENCL_RC_ADDED (0x01) +#define MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING (0x02) + + +/**************************************************************************** +* EventAck message +****************************************************************************/ + +/* EventAck Request message */ +typedef struct _MPI2_EVENT_ACK_REQUEST +{ + U16 Reserved1; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 Event; /* 0x0C */ + U16 Reserved5; /* 0x0E */ + U32 EventContext; /* 0x10 */ +} MPI2_EVENT_ACK_REQUEST, MPI2_POINTER PTR_MPI2_EVENT_ACK_REQUEST, + Mpi2EventAckRequest_t, MPI2_POINTER pMpi2EventAckRequest_t; + + +/* EventAck Reply message */ +typedef struct _MPI2_EVENT_ACK_REPLY +{ + U16 Reserved1; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 Reserved5; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ +} MPI2_EVENT_ACK_REPLY, MPI2_POINTER PTR_MPI2_EVENT_ACK_REPLY, + Mpi2EventAckReply_t, MPI2_POINTER pMpi2EventAckReply_t; + + +/**************************************************************************** +* FWDownload message +****************************************************************************/ + +/* FWDownload Request message */ +typedef struct _MPI2_FW_DOWNLOAD_REQUEST +{ + U8 ImageType; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U32 TotalImageSize; /* 0x0C */ + U32 Reserved5; /* 0x10 */ + MPI2_MPI_SGE_UNION SGL; /* 0x14 */ +} MPI2_FW_DOWNLOAD_REQUEST, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_REQUEST, + Mpi2FWDownloadRequest, MPI2_POINTER pMpi2FWDownloadRequest; + +#define MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT (0x01) + +#define MPI2_FW_DOWNLOAD_ITYPE_FW (0x01) +#define MPI2_FW_DOWNLOAD_ITYPE_BIOS (0x02) +#define MPI2_FW_DOWNLOAD_ITYPE_MANUFACTURING (0x06) +#define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_1 (0x07) +#define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_2 (0x08) +#define MPI2_FW_DOWNLOAD_ITYPE_MEGARAID (0x09) +#define MPI2_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B) + +/* FWDownload TransactionContext Element */ +typedef struct _MPI2_FW_DOWNLOAD_TCSGE +{ + U8 Reserved1; /* 0x00 */ + U8 ContextSize; /* 0x01 */ + U8 DetailsLength; /* 0x02 */ + U8 Flags; /* 0x03 */ + U32 Reserved2; /* 0x04 */ + U32 ImageOffset; /* 0x08 */ + U32 ImageSize; /* 0x0C */ +} MPI2_FW_DOWNLOAD_TCSGE, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_TCSGE, + Mpi2FWDownloadTCSGE_t, MPI2_POINTER pMpi2FWDownloadTCSGE_t; + +/* FWDownload Reply message */ +typedef struct _MPI2_FW_DOWNLOAD_REPLY +{ + U8 ImageType; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 Reserved5; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ +} MPI2_FW_DOWNLOAD_REPLY, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_REPLY, + Mpi2FWDownloadReply_t, MPI2_POINTER pMpi2FWDownloadReply_t; + + +/**************************************************************************** +* FWUpload message +****************************************************************************/ + +/* FWUpload Request message */ +typedef struct _MPI2_FW_UPLOAD_REQUEST +{ + U8 ImageType; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U32 Reserved5; /* 0x0C */ + U32 Reserved6; /* 0x10 */ + MPI2_MPI_SGE_UNION SGL; /* 0x14 */ +} MPI2_FW_UPLOAD_REQUEST, MPI2_POINTER PTR_MPI2_FW_UPLOAD_REQUEST, + Mpi2FWUploadRequest_t, MPI2_POINTER pMpi2FWUploadRequest_t; + +#define MPI2_FW_UPLOAD_ITYPE_FW_CURRENT (0x00) +#define MPI2_FW_UPLOAD_ITYPE_FW_FLASH (0x01) +#define MPI2_FW_UPLOAD_ITYPE_BIOS_FLASH (0x02) +#define MPI2_FW_UPLOAD_ITYPE_FW_BACKUP (0x05) +#define MPI2_FW_UPLOAD_ITYPE_MANUFACTURING (0x06) +#define MPI2_FW_UPLOAD_ITYPE_CONFIG_1 (0x07) +#define MPI2_FW_UPLOAD_ITYPE_CONFIG_2 (0x08) +#define MPI2_FW_UPLOAD_ITYPE_MEGARAID (0x09) +#define MPI2_FW_UPLOAD_ITYPE_COMPLETE (0x0A) +#define MPI2_FW_UPLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B) + +typedef struct _MPI2_FW_UPLOAD_TCSGE +{ + U8 Reserved1; /* 0x00 */ + U8 ContextSize; /* 0x01 */ + U8 DetailsLength; /* 0x02 */ + U8 Flags; /* 0x03 */ + U32 Reserved2; /* 0x04 */ + U32 ImageOffset; /* 0x08 */ + U32 ImageSize; /* 0x0C */ +} MPI2_FW_UPLOAD_TCSGE, MPI2_POINTER PTR_MPI2_FW_UPLOAD_TCSGE, + Mpi2FWUploadTCSGE_t, MPI2_POINTER pMpi2FWUploadTCSGE_t; + +/* FWUpload Reply message */ +typedef struct _MPI2_FW_UPLOAD_REPLY +{ + U8 ImageType; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 Reserved5; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U32 ActualImageSize; /* 0x14 */ +} MPI2_FW_UPLOAD_REPLY, MPI2_POINTER PTR_MPI2_FW_UPLOAD_REPLY, + Mpi2FWUploadReply_t, MPI2_POINTER pMPi2FWUploadReply_t; + + +/* FW Image Header */ +typedef struct _MPI2_FW_IMAGE_HEADER +{ + U32 Signature; /* 0x00 */ + U32 Signature0; /* 0x04 */ + U32 Signature1; /* 0x08 */ + U32 Signature2; /* 0x0C */ + MPI2_VERSION_UNION MPIVersion; /* 0x10 */ + MPI2_VERSION_UNION FWVersion; /* 0x14 */ + MPI2_VERSION_UNION NVDATAVersion; /* 0x18 */ + MPI2_VERSION_UNION PackageVersion; /* 0x1C */ + U16 VendorID; /* 0x20 */ + U16 ProductID; /* 0x22 */ + U16 ProtocolFlags; /* 0x24 */ + U16 Reserved26; /* 0x26 */ + U32 IOCCapabilities; /* 0x28 */ + U32 ImageSize; /* 0x2C */ + U32 NextImageHeaderOffset; /* 0x30 */ + U32 Checksum; /* 0x34 */ + U32 Reserved38; /* 0x38 */ + U32 Reserved3C; /* 0x3C */ + U32 Reserved40; /* 0x40 */ + U32 Reserved44; /* 0x44 */ + U32 Reserved48; /* 0x48 */ + U32 Reserved4C; /* 0x4C */ + U32 Reserved50; /* 0x50 */ + U32 Reserved54; /* 0x54 */ + U32 Reserved58; /* 0x58 */ + U32 Reserved5C; /* 0x5C */ + U32 Reserved60; /* 0x60 */ + U32 FirmwareVersionNameWhat; /* 0x64 */ + U8 FirmwareVersionName[32]; /* 0x68 */ + U32 VendorNameWhat; /* 0x88 */ + U8 VendorName[32]; /* 0x8C */ + U32 PackageNameWhat; /* 0x88 */ + U8 PackageName[32]; /* 0x8C */ + U32 ReservedD0; /* 0xD0 */ + U32 ReservedD4; /* 0xD4 */ + U32 ReservedD8; /* 0xD8 */ + U32 ReservedDC; /* 0xDC */ + U32 ReservedE0; /* 0xE0 */ + U32 ReservedE4; /* 0xE4 */ + U32 ReservedE8; /* 0xE8 */ + U32 ReservedEC; /* 0xEC */ + U32 ReservedF0; /* 0xF0 */ + U32 ReservedF4; /* 0xF4 */ + U32 ReservedF8; /* 0xF8 */ + U32 ReservedFC; /* 0xFC */ +} MPI2_FW_IMAGE_HEADER, MPI2_POINTER PTR_MPI2_FW_IMAGE_HEADER, + Mpi2FWImageHeader_t, MPI2_POINTER pMpi2FWImageHeader_t; + +/* Signature field */ +#define MPI2_FW_HEADER_SIGNATURE_OFFSET (0x00) +#define MPI2_FW_HEADER_SIGNATURE_MASK (0xFF000000) +#define MPI2_FW_HEADER_SIGNATURE (0xEA000000) + +/* Signature0 field */ +#define MPI2_FW_HEADER_SIGNATURE0_OFFSET (0x04) +#define MPI2_FW_HEADER_SIGNATURE0 (0x5AFAA55A) + +/* Signature1 field */ +#define MPI2_FW_HEADER_SIGNATURE1_OFFSET (0x08) +#define MPI2_FW_HEADER_SIGNATURE1 (0xA55AFAA5) + +/* Signature2 field */ +#define MPI2_FW_HEADER_SIGNATURE2_OFFSET (0x0C) +#define MPI2_FW_HEADER_SIGNATURE2 (0x5AA55AFA) + + +/* defines for using the ProductID field */ +#define MPI2_FW_HEADER_PID_TYPE_MASK (0xF000) +#define MPI2_FW_HEADER_PID_TYPE_SAS (0x2000) + +#define MPI2_FW_HEADER_PID_PROD_MASK (0x0F00) +#define MPI2_FW_HEADER_PID_PROD_A (0x0000) + +#define MPI2_FW_HEADER_PID_FAMILY_MASK (0x00FF) +/* SAS */ +#define MPI2_FW_HEADER_PID_FAMILY_2108_SAS (0x0010) + +/* use MPI2_IOCFACTS_PROTOCOL_ defines for ProtocolFlags field */ + +/* use MPI2_IOCFACTS_CAPABILITY_ defines for IOCCapabilities field */ + + +#define MPI2_FW_HEADER_IMAGESIZE_OFFSET (0x2C) +#define MPI2_FW_HEADER_NEXTIMAGE_OFFSET (0x30) +#define MPI2_FW_HEADER_VERNMHWAT_OFFSET (0x64) + +#define MPI2_FW_HEADER_WHAT_SIGNATURE (0x29232840) + +#define MPI2_FW_HEADER_SIZE (0x100) + + +/* Extended Image Header */ +typedef struct _MPI2_EXT_IMAGE_HEADER + +{ + U8 ImageType; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U16 Reserved2; /* 0x02 */ + U32 Checksum; /* 0x04 */ + U32 ImageSize; /* 0x08 */ + U32 NextImageHeaderOffset; /* 0x0C */ + U32 PackageVersion; /* 0x10 */ + U32 Reserved3; /* 0x14 */ + U32 Reserved4; /* 0x18 */ + U32 Reserved5; /* 0x1C */ + U8 IdentifyString[32]; /* 0x20 */ +} MPI2_EXT_IMAGE_HEADER, MPI2_POINTER PTR_MPI2_EXT_IMAGE_HEADER, + Mpi2ExtImageHeader_t, MPI2_POINTER pMpi2ExtImageHeader_t; + +/* useful offsets */ +#define MPI2_EXT_IMAGE_IMAGETYPE_OFFSET (0x00) +#define MPI2_EXT_IMAGE_IMAGESIZE_OFFSET (0x08) +#define MPI2_EXT_IMAGE_NEXTIMAGE_OFFSET (0x0C) + +#define MPI2_EXT_IMAGE_HEADER_SIZE (0x40) + +/* defines for the ImageType field */ +#define MPI2_EXT_IMAGE_TYPE_UNSPECIFIED (0x00) +#define MPI2_EXT_IMAGE_TYPE_FW (0x01) +#define MPI2_EXT_IMAGE_TYPE_NVDATA (0x03) +#define MPI2_EXT_IMAGE_TYPE_BOOTLOADER (0x04) +#define MPI2_EXT_IMAGE_TYPE_INITIALIZATION (0x05) +#define MPI2_EXT_IMAGE_TYPE_FLASH_LAYOUT (0x06) +#define MPI2_EXT_IMAGE_TYPE_SUPPORTED_DEVICES (0x07) +#define MPI2_EXT_IMAGE_TYPE_MEGARAID (0x08) + +#define MPI2_EXT_IMAGE_TYPE_MAX (MPI2_EXT_IMAGE_TYPE_MEGARAID) + + + +/* FLASH Layout Extended Image Data */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check RegionsPerLayout at runtime. + */ +#ifndef MPI2_FLASH_NUMBER_OF_REGIONS +#define MPI2_FLASH_NUMBER_OF_REGIONS (1) +#endif + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check NumberOfLayouts at runtime. + */ +#ifndef MPI2_FLASH_NUMBER_OF_LAYOUTS +#define MPI2_FLASH_NUMBER_OF_LAYOUTS (1) +#endif + +typedef struct _MPI2_FLASH_REGION +{ + U8 RegionType; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U16 Reserved2; /* 0x02 */ + U32 RegionOffset; /* 0x04 */ + U32 RegionSize; /* 0x08 */ + U32 Reserved3; /* 0x0C */ +} MPI2_FLASH_REGION, MPI2_POINTER PTR_MPI2_FLASH_REGION, + Mpi2FlashRegion_t, MPI2_POINTER pMpi2FlashRegion_t; + +typedef struct _MPI2_FLASH_LAYOUT +{ + U32 FlashSize; /* 0x00 */ + U32 Reserved1; /* 0x04 */ + U32 Reserved2; /* 0x08 */ + U32 Reserved3; /* 0x0C */ + MPI2_FLASH_REGION Region[MPI2_FLASH_NUMBER_OF_REGIONS];/* 0x10 */ +} MPI2_FLASH_LAYOUT, MPI2_POINTER PTR_MPI2_FLASH_LAYOUT, + Mpi2FlashLayout_t, MPI2_POINTER pMpi2FlashLayout_t; + +typedef struct _MPI2_FLASH_LAYOUT_DATA +{ + U8 ImageRevision; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 SizeOfRegion; /* 0x02 */ + U8 Reserved2; /* 0x03 */ + U16 NumberOfLayouts; /* 0x04 */ + U16 RegionsPerLayout; /* 0x06 */ + U16 MinimumSectorAlignment; /* 0x08 */ + U16 Reserved3; /* 0x0A */ + U32 Reserved4; /* 0x0C */ + MPI2_FLASH_LAYOUT Layout[MPI2_FLASH_NUMBER_OF_LAYOUTS];/* 0x10 */ +} MPI2_FLASH_LAYOUT_DATA, MPI2_POINTER PTR_MPI2_FLASH_LAYOUT_DATA, + Mpi2FlashLayoutData_t, MPI2_POINTER pMpi2FlashLayoutData_t; + +/* defines for the RegionType field */ +#define MPI2_FLASH_REGION_UNUSED (0x00) +#define MPI2_FLASH_REGION_FIRMWARE (0x01) +#define MPI2_FLASH_REGION_BIOS (0x02) +#define MPI2_FLASH_REGION_NVDATA (0x03) +#define MPI2_FLASH_REGION_FIRMWARE_BACKUP (0x05) +#define MPI2_FLASH_REGION_MFG_INFORMATION (0x06) +#define MPI2_FLASH_REGION_CONFIG_1 (0x07) +#define MPI2_FLASH_REGION_CONFIG_2 (0x08) +#define MPI2_FLASH_REGION_MEGARAID (0x09) +#define MPI2_FLASH_REGION_INIT (0x0A) + +/* ImageRevision */ +#define MPI2_FLASH_LAYOUT_IMAGE_REVISION (0x00) + + + +/* Supported Devices Extended Image Data */ + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check NumberOfDevices at runtime. + */ +#ifndef MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES +#define MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES (1) +#endif + +typedef struct _MPI2_SUPPORTED_DEVICE +{ + U16 DeviceID; /* 0x00 */ + U16 VendorID; /* 0x02 */ + U16 DeviceIDMask; /* 0x04 */ + U16 Reserved1; /* 0x06 */ + U8 LowPCIRev; /* 0x08 */ + U8 HighPCIRev; /* 0x09 */ + U16 Reserved2; /* 0x0A */ + U32 Reserved3; /* 0x0C */ +} MPI2_SUPPORTED_DEVICE, MPI2_POINTER PTR_MPI2_SUPPORTED_DEVICE, + Mpi2SupportedDevice_t, MPI2_POINTER pMpi2SupportedDevice_t; + +typedef struct _MPI2_SUPPORTED_DEVICES_DATA +{ + U8 ImageRevision; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 NumberOfDevices; /* 0x02 */ + U8 Reserved2; /* 0x03 */ + U32 Reserved3; /* 0x04 */ + MPI2_SUPPORTED_DEVICE SupportedDevice[MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES]; /* 0x08 */ +} MPI2_SUPPORTED_DEVICES_DATA, MPI2_POINTER PTR_MPI2_SUPPORTED_DEVICES_DATA, + Mpi2SupportedDevicesData_t, MPI2_POINTER pMpi2SupportedDevicesData_t; + +/* ImageRevision */ +#define MPI2_SUPPORTED_DEVICES_IMAGE_REVISION (0x00) + + +/* Init Extended Image Data */ + +typedef struct _MPI2_INIT_IMAGE_FOOTER + +{ + U32 BootFlags; /* 0x00 */ + U32 ImageSize; /* 0x04 */ + U32 Signature0; /* 0x08 */ + U32 Signature1; /* 0x0C */ + U32 Signature2; /* 0x10 */ + U32 ResetVector; /* 0x14 */ +} MPI2_INIT_IMAGE_FOOTER, MPI2_POINTER PTR_MPI2_INIT_IMAGE_FOOTER, + Mpi2InitImageFooter_t, MPI2_POINTER pMpi2InitImageFooter_t; + +/* defines for the BootFlags field */ +#define MPI2_INIT_IMAGE_BOOTFLAGS_OFFSET (0x00) + +/* defines for the ImageSize field */ +#define MPI2_INIT_IMAGE_IMAGESIZE_OFFSET (0x04) + +/* defines for the Signature0 field */ +#define MPI2_INIT_IMAGE_SIGNATURE0_OFFSET (0x08) +#define MPI2_INIT_IMAGE_SIGNATURE0 (0x5AA55AEA) + +/* defines for the Signature1 field */ +#define MPI2_INIT_IMAGE_SIGNATURE1_OFFSET (0x0C) +#define MPI2_INIT_IMAGE_SIGNATURE1 (0xA55AEAA5) + +/* defines for the Signature2 field */ +#define MPI2_INIT_IMAGE_SIGNATURE2_OFFSET (0x10) +#define MPI2_INIT_IMAGE_SIGNATURE2 (0x5AEAA55A) + +/* Signature fields as individual bytes */ +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_0 (0xEA) +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_1 (0x5A) +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_2 (0xA5) +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_3 (0x5A) + +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_4 (0xA5) +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_5 (0xEA) +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_6 (0x5A) +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_7 (0xA5) + +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_8 (0x5A) +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_9 (0xA5) +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_A (0xEA) +#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_B (0x5A) + +/* defines for the ResetVector field */ +#define MPI2_INIT_IMAGE_RESETVECTOR_OFFSET (0x14) + + +#endif + diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_raid.h b/drivers/scsi/mpt2sas/mpi/mpi2_raid.h new file mode 100644 index 00000000000..7134816d904 --- /dev/null +++ b/drivers/scsi/mpt2sas/mpi/mpi2_raid.h @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2000-2008 LSI Corporation. + * + * + * Name: mpi2_raid.h + * Title: MPI Integrated RAID messages and structures + * Creation Date: April 26, 2007 + * + * mpi2_raid.h Version: 02.00.03 + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 08-31-07 02.00.01 Modifications to RAID Action request and reply, + * including the Actions and ActionData. + * 02-29-08 02.00.02 Added MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD. + * 05-21-08 02.00.03 Added MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS so that + * the PhysDisk array in MPI2_RAID_VOLUME_CREATION_STRUCT + * can be sized by the build environment. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI2_RAID_H +#define MPI2_RAID_H + +/***************************************************************************** +* +* Integrated RAID Messages +* +*****************************************************************************/ + +/**************************************************************************** +* RAID Action messages +****************************************************************************/ + +/* ActionDataWord defines for use with MPI2_RAID_ACTION_DELETE_VOLUME action */ +#define MPI2_RAID_ACTION_ADATA_KEEP_LBA0 (0x00000000) +#define MPI2_RAID_ACTION_ADATA_ZERO_LBA0 (0x00000001) + +/* use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */ + +/* ActionDataWord defines for use with MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES action */ +#define MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD (0x00000001) + +/* ActionDataWord for MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE Action */ +typedef struct _MPI2_RAID_ACTION_RATE_DATA +{ + U8 RateToChange; /* 0x00 */ + U8 RateOrMode; /* 0x01 */ + U16 DataScrubDuration; /* 0x02 */ +} MPI2_RAID_ACTION_RATE_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_RATE_DATA, + Mpi2RaidActionRateData_t, MPI2_POINTER pMpi2RaidActionRateData_t; + +#define MPI2_RAID_ACTION_SET_RATE_RESYNC (0x00) +#define MPI2_RAID_ACTION_SET_RATE_DATA_SCRUB (0x01) +#define MPI2_RAID_ACTION_SET_RATE_POWERSAVE_MODE (0x02) + +/* ActionDataWord for MPI2_RAID_ACTION_START_RAID_FUNCTION Action */ +typedef struct _MPI2_RAID_ACTION_START_RAID_FUNCTION +{ + U8 RAIDFunction; /* 0x00 */ + U8 Flags; /* 0x01 */ + U16 Reserved1; /* 0x02 */ +} MPI2_RAID_ACTION_START_RAID_FUNCTION, + MPI2_POINTER PTR_MPI2_RAID_ACTION_START_RAID_FUNCTION, + Mpi2RaidActionStartRaidFunction_t, + MPI2_POINTER pMpi2RaidActionStartRaidFunction_t; + +/* defines for the RAIDFunction field */ +#define MPI2_RAID_ACTION_START_BACKGROUND_INIT (0x00) +#define MPI2_RAID_ACTION_START_ONLINE_CAP_EXPANSION (0x01) +#define MPI2_RAID_ACTION_START_CONSISTENCY_CHECK (0x02) + +/* defines for the Flags field */ +#define MPI2_RAID_ACTION_START_NEW (0x00) +#define MPI2_RAID_ACTION_START_RESUME (0x01) + +/* ActionDataWord for MPI2_RAID_ACTION_STOP_RAID_FUNCTION Action */ +typedef struct _MPI2_RAID_ACTION_STOP_RAID_FUNCTION +{ + U8 RAIDFunction; /* 0x00 */ + U8 Flags; /* 0x01 */ + U16 Reserved1; /* 0x02 */ +} MPI2_RAID_ACTION_STOP_RAID_FUNCTION, + MPI2_POINTER PTR_MPI2_RAID_ACTION_STOP_RAID_FUNCTION, + Mpi2RaidActionStopRaidFunction_t, + MPI2_POINTER pMpi2RaidActionStopRaidFunction_t; + +/* defines for the RAIDFunction field */ +#define MPI2_RAID_ACTION_STOP_BACKGROUND_INIT (0x00) +#define MPI2_RAID_ACTION_STOP_ONLINE_CAP_EXPANSION (0x01) +#define MPI2_RAID_ACTION_STOP_CONSISTENCY_CHECK (0x02) + +/* defines for the Flags field */ +#define MPI2_RAID_ACTION_STOP_ABORT (0x00) +#define MPI2_RAID_ACTION_STOP_PAUSE (0x01) + +/* ActionDataWord for MPI2_RAID_ACTION_CREATE_HOT_SPARE Action */ +typedef struct _MPI2_RAID_ACTION_HOT_SPARE +{ + U8 HotSparePool; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U16 DevHandle; /* 0x02 */ +} MPI2_RAID_ACTION_HOT_SPARE, MPI2_POINTER PTR_MPI2_RAID_ACTION_HOT_SPARE, + Mpi2RaidActionHotSpare_t, MPI2_POINTER pMpi2RaidActionHotSpare_t; + +/* ActionDataWord for MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE Action */ +typedef struct _MPI2_RAID_ACTION_FW_UPDATE_MODE +{ + U8 Flags; /* 0x00 */ + U8 DeviceFirmwareUpdateModeTimeout; /* 0x01 */ + U16 Reserved1; /* 0x02 */ +} MPI2_RAID_ACTION_FW_UPDATE_MODE, + MPI2_POINTER PTR_MPI2_RAID_ACTION_FW_UPDATE_MODE, + Mpi2RaidActionFwUpdateMode_t, MPI2_POINTER pMpi2RaidActionFwUpdateMode_t; + +/* ActionDataWord defines for use with MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE action */ +#define MPI2_RAID_ACTION_ADATA_DISABLE_FW_UPDATE (0x00) +#define MPI2_RAID_ACTION_ADATA_ENABLE_FW_UPDATE (0x01) + +typedef union _MPI2_RAID_ACTION_DATA +{ + U32 Word; + MPI2_RAID_ACTION_RATE_DATA Rates; + MPI2_RAID_ACTION_START_RAID_FUNCTION StartRaidFunction; + MPI2_RAID_ACTION_STOP_RAID_FUNCTION StopRaidFunction; + MPI2_RAID_ACTION_HOT_SPARE HotSpare; + MPI2_RAID_ACTION_FW_UPDATE_MODE FwUpdateMode; +} MPI2_RAID_ACTION_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_DATA, + Mpi2RaidActionData_t, MPI2_POINTER pMpi2RaidActionData_t; + + +/* RAID Action Request Message */ +typedef struct _MPI2_RAID_ACTION_REQUEST +{ + U8 Action; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 VolDevHandle; /* 0x04 */ + U8 PhysDiskNum; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved2; /* 0x0A */ + U32 Reserved3; /* 0x0C */ + MPI2_RAID_ACTION_DATA ActionDataWord; /* 0x10 */ + MPI2_SGE_SIMPLE_UNION ActionDataSGE; /* 0x14 */ +} MPI2_RAID_ACTION_REQUEST, MPI2_POINTER PTR_MPI2_RAID_ACTION_REQUEST, + Mpi2RaidActionRequest_t, MPI2_POINTER pMpi2RaidActionRequest_t; + +/* RAID Action request Action values */ + +#define MPI2_RAID_ACTION_INDICATOR_STRUCT (0x01) +#define MPI2_RAID_ACTION_CREATE_VOLUME (0x02) +#define MPI2_RAID_ACTION_DELETE_VOLUME (0x03) +#define MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES (0x04) +#define MPI2_RAID_ACTION_ENABLE_ALL_VOLUMES (0x05) +#define MPI2_RAID_ACTION_PHYSDISK_OFFLINE (0x0A) +#define MPI2_RAID_ACTION_PHYSDISK_ONLINE (0x0B) +#define MPI2_RAID_ACTION_FAIL_PHYSDISK (0x0F) +#define MPI2_RAID_ACTION_ACTIVATE_VOLUME (0x11) +#define MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE (0x15) +#define MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE (0x17) +#define MPI2_RAID_ACTION_SET_VOLUME_NAME (0x18) +#define MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE (0x19) +#define MPI2_RAID_ACTION_ENABLE_FAILED_VOLUME (0x1C) +#define MPI2_RAID_ACTION_CREATE_HOT_SPARE (0x1D) +#define MPI2_RAID_ACTION_DELETE_HOT_SPARE (0x1E) +#define MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED (0x20) +#define MPI2_RAID_ACTION_START_RAID_FUNCTION (0x21) +#define MPI2_RAID_ACTION_STOP_RAID_FUNCTION (0x22) + + +/* RAID Volume Creation Structure */ + +/* + * The following define can be customized for the targeted product. + */ +#ifndef MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS +#define MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS (1) +#endif + +typedef struct _MPI2_RAID_VOLUME_PHYSDISK +{ + U8 RAIDSetNum; /* 0x00 */ + U8 PhysDiskMap; /* 0x01 */ + U16 PhysDiskDevHandle; /* 0x02 */ +} MPI2_RAID_VOLUME_PHYSDISK, MPI2_POINTER PTR_MPI2_RAID_VOLUME_PHYSDISK, + Mpi2RaidVolumePhysDisk_t, MPI2_POINTER pMpi2RaidVolumePhysDisk_t; + +/* defines for the PhysDiskMap field */ +#define MPI2_RAIDACTION_PHYSDISK_PRIMARY (0x01) +#define MPI2_RAIDACTION_PHYSDISK_SECONDARY (0x02) + +typedef struct _MPI2_RAID_VOLUME_CREATION_STRUCT +{ + U8 NumPhysDisks; /* 0x00 */ + U8 VolumeType; /* 0x01 */ + U16 Reserved1; /* 0x02 */ + U32 VolumeCreationFlags; /* 0x04 */ + U32 VolumeSettings; /* 0x08 */ + U8 Reserved2; /* 0x0C */ + U8 ResyncRate; /* 0x0D */ + U16 DataScrubDuration; /* 0x0E */ + U64 VolumeMaxLBA; /* 0x10 */ + U32 StripeSize; /* 0x18 */ + U8 Name[16]; /* 0x1C */ + MPI2_RAID_VOLUME_PHYSDISK PhysDisk[MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS];/* 0x2C */ +} MPI2_RAID_VOLUME_CREATION_STRUCT, + MPI2_POINTER PTR_MPI2_RAID_VOLUME_CREATION_STRUCT, + Mpi2RaidVolumeCreationStruct_t, MPI2_POINTER pMpi2RaidVolumeCreationStruct_t; + +/* use MPI2_RAID_VOL_TYPE_ defines from mpi2_cnfg.h for VolumeType */ + +/* defines for the VolumeCreationFlags field */ +#define MPI2_RAID_VOL_CREATION_USE_DEFAULT_SETTINGS (0x80) +#define MPI2_RAID_VOL_CREATION_BACKGROUND_INIT (0x04) +#define MPI2_RAID_VOL_CREATION_LOW_LEVEL_INIT (0x02) +#define MPI2_RAID_VOL_CREATION_MIGRATE_DATA (0x01) + + +/* RAID Online Capacity Expansion Structure */ + +typedef struct _MPI2_RAID_ONLINE_CAPACITY_EXPANSION +{ + U32 Flags; /* 0x00 */ + U16 DevHandle0; /* 0x04 */ + U16 Reserved1; /* 0x06 */ + U16 DevHandle1; /* 0x08 */ + U16 Reserved2; /* 0x0A */ +} MPI2_RAID_ONLINE_CAPACITY_EXPANSION, + MPI2_POINTER PTR_MPI2_RAID_ONLINE_CAPACITY_EXPANSION, + Mpi2RaidOnlineCapacityExpansion_t, + MPI2_POINTER pMpi2RaidOnlineCapacityExpansion_t; + + +/* RAID Volume Indicator Structure */ + +typedef struct _MPI2_RAID_VOL_INDICATOR +{ + U64 TotalBlocks; /* 0x00 */ + U64 BlocksRemaining; /* 0x08 */ + U32 Flags; /* 0x10 */ +} MPI2_RAID_VOL_INDICATOR, MPI2_POINTER PTR_MPI2_RAID_VOL_INDICATOR, + Mpi2RaidVolIndicator_t, MPI2_POINTER pMpi2RaidVolIndicator_t; + +/* defines for RAID Volume Indicator Flags field */ +#define MPI2_RAID_VOL_FLAGS_OP_MASK (0x0000000F) +#define MPI2_RAID_VOL_FLAGS_OP_BACKGROUND_INIT (0x00000000) +#define MPI2_RAID_VOL_FLAGS_OP_ONLINE_CAP_EXPANSION (0x00000001) +#define MPI2_RAID_VOL_FLAGS_OP_CONSISTENCY_CHECK (0x00000002) +#define MPI2_RAID_VOL_FLAGS_OP_RESYNC (0x00000003) + + +/* RAID Action Reply ActionData union */ +typedef union _MPI2_RAID_ACTION_REPLY_DATA +{ + U32 Word[5]; + MPI2_RAID_VOL_INDICATOR RaidVolumeIndicator; + U16 VolDevHandle; + U8 VolumeState; + U8 PhysDiskNum; +} MPI2_RAID_ACTION_REPLY_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_REPLY_DATA, + Mpi2RaidActionReplyData_t, MPI2_POINTER pMpi2RaidActionReplyData_t; + +/* use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */ + + +/* RAID Action Reply Message */ +typedef struct _MPI2_RAID_ACTION_REPLY +{ + U8 Action; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 VolDevHandle; /* 0x04 */ + U8 PhysDiskNum; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved2; /* 0x0A */ + U16 Reserved3; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + MPI2_RAID_ACTION_REPLY_DATA ActionData; /* 0x14 */ +} MPI2_RAID_ACTION_REPLY, MPI2_POINTER PTR_MPI2_RAID_ACTION_REPLY, + Mpi2RaidActionReply_t, MPI2_POINTER pMpi2RaidActionReply_t; + + +#endif + diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_sas.h b/drivers/scsi/mpt2sas/mpi/mpi2_sas.h new file mode 100644 index 00000000000..8a42b136cf5 --- /dev/null +++ b/drivers/scsi/mpt2sas/mpi/mpi2_sas.h @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2000-2007 LSI Corporation. + * + * + * Name: mpi2_sas.h + * Title: MPI Serial Attached SCSI structures and definitions + * Creation Date: February 9, 2007 + * + * mpi2.h Version: 02.00.02 + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 06-26-07 02.00.01 Added Clear All Persistent Operation to SAS IO Unit + * Control Request. + * 10-02-08 02.00.02 Added Set IOC Parameter Operation to SAS IO Unit Control + * Request. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI2_SAS_H +#define MPI2_SAS_H + +/* + * Values for SASStatus. + */ +#define MPI2_SASSTATUS_SUCCESS (0x00) +#define MPI2_SASSTATUS_UNKNOWN_ERROR (0x01) +#define MPI2_SASSTATUS_INVALID_FRAME (0x02) +#define MPI2_SASSTATUS_UTC_BAD_DEST (0x03) +#define MPI2_SASSTATUS_UTC_BREAK_RECEIVED (0x04) +#define MPI2_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED (0x05) +#define MPI2_SASSTATUS_UTC_PORT_LAYER_REQUEST (0x06) +#define MPI2_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED (0x07) +#define MPI2_SASSTATUS_UTC_STP_RESOURCES_BUSY (0x08) +#define MPI2_SASSTATUS_UTC_WRONG_DESTINATION (0x09) +#define MPI2_SASSTATUS_SHORT_INFORMATION_UNIT (0x0A) +#define MPI2_SASSTATUS_LONG_INFORMATION_UNIT (0x0B) +#define MPI2_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA (0x0C) +#define MPI2_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR (0x0D) +#define MPI2_SASSTATUS_XFER_RDY_NOT_EXPECTED (0x0E) +#define MPI2_SASSTATUS_DATA_INCORRECT_DATA_LENGTH (0x0F) +#define MPI2_SASSTATUS_DATA_TOO_MUCH_READ_DATA (0x10) +#define MPI2_SASSTATUS_DATA_OFFSET_ERROR (0x11) +#define MPI2_SASSTATUS_SDSF_NAK_RECEIVED (0x12) +#define MPI2_SASSTATUS_SDSF_CONNECTION_FAILED (0x13) +#define MPI2_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT (0x14) + + +/* + * Values for the SAS DeviceInfo field used in SAS Device Status Change Event + * data and SAS Configuration pages. + */ +#define MPI2_SAS_DEVICE_INFO_SEP (0x00004000) +#define MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000) +#define MPI2_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000) +#define MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800) +#define MPI2_SAS_DEVICE_INFO_SSP_TARGET (0x00000400) +#define MPI2_SAS_DEVICE_INFO_STP_TARGET (0x00000200) +#define MPI2_SAS_DEVICE_INFO_SMP_TARGET (0x00000100) +#define MPI2_SAS_DEVICE_INFO_SATA_DEVICE (0x00000080) +#define MPI2_SAS_DEVICE_INFO_SSP_INITIATOR (0x00000040) +#define MPI2_SAS_DEVICE_INFO_STP_INITIATOR (0x00000020) +#define MPI2_SAS_DEVICE_INFO_SMP_INITIATOR (0x00000010) +#define MPI2_SAS_DEVICE_INFO_SATA_HOST (0x00000008) + +#define MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE (0x00000007) +#define MPI2_SAS_DEVICE_INFO_NO_DEVICE (0x00000000) +#define MPI2_SAS_DEVICE_INFO_END_DEVICE (0x00000001) +#define MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER (0x00000002) +#define MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER (0x00000003) + + +/***************************************************************************** +* +* SAS Messages +* +*****************************************************************************/ + +/**************************************************************************** +* SMP Passthrough messages +****************************************************************************/ + +/* SMP Passthrough Request Message */ +typedef struct _MPI2_SMP_PASSTHROUGH_REQUEST +{ + U8 PassthroughFlags; /* 0x00 */ + U8 PhysicalPort; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 RequestDataLength; /* 0x04 */ + U8 SGLFlags; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved1; /* 0x0A */ + U32 Reserved2; /* 0x0C */ + U64 SASAddress; /* 0x10 */ + U32 Reserved3; /* 0x18 */ + U32 Reserved4; /* 0x1C */ + MPI2_SIMPLE_SGE_UNION SGL; /* 0x20 */ +} MPI2_SMP_PASSTHROUGH_REQUEST, MPI2_POINTER PTR_MPI2_SMP_PASSTHROUGH_REQUEST, + Mpi2SmpPassthroughRequest_t, MPI2_POINTER pMpi2SmpPassthroughRequest_t; + +/* values for PassthroughFlags field */ +#define MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE (0x80) + +/* values for SGLFlags field are in the SGL section of mpi2.h */ + + +/* SMP Passthrough Reply Message */ +typedef struct _MPI2_SMP_PASSTHROUGH_REPLY +{ + U8 PassthroughFlags; /* 0x00 */ + U8 PhysicalPort; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 ResponseDataLength; /* 0x04 */ + U8 SGLFlags; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved1; /* 0x0A */ + U8 Reserved2; /* 0x0C */ + U8 SASStatus; /* 0x0D */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U32 Reserved3; /* 0x14 */ + U8 ResponseData[4]; /* 0x18 */ +} MPI2_SMP_PASSTHROUGH_REPLY, MPI2_POINTER PTR_MPI2_SMP_PASSTHROUGH_REPLY, + Mpi2SmpPassthroughReply_t, MPI2_POINTER pMpi2SmpPassthroughReply_t; + +/* values for PassthroughFlags field */ +#define MPI2_SMP_PT_REPLY_PT_FLAGS_IMMEDIATE (0x80) + +/* values for SASStatus field are at the top of this file */ + + +/**************************************************************************** +* SATA Passthrough messages +****************************************************************************/ + +/* SATA Passthrough Request Message */ +typedef struct _MPI2_SATA_PASSTHROUGH_REQUEST +{ + U16 DevHandle; /* 0x00 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 PassthroughFlags; /* 0x04 */ + U8 SGLFlags; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved1; /* 0x0A */ + U32 Reserved2; /* 0x0C */ + U32 Reserved3; /* 0x10 */ + U32 Reserved4; /* 0x14 */ + U32 DataLength; /* 0x18 */ + U8 CommandFIS[20]; /* 0x1C */ + MPI2_SIMPLE_SGE_UNION SGL; /* 0x20 */ +} MPI2_SATA_PASSTHROUGH_REQUEST, MPI2_POINTER PTR_MPI2_SATA_PASSTHROUGH_REQUEST, + Mpi2SataPassthroughRequest_t, MPI2_POINTER pMpi2SataPassthroughRequest_t; + +/* values for PassthroughFlags field */ +#define MPI2_SATA_PT_REQ_PT_FLAGS_EXECUTE_DIAG (0x0100) +#define MPI2_SATA_PT_REQ_PT_FLAGS_DMA (0x0020) +#define MPI2_SATA_PT_REQ_PT_FLAGS_PIO (0x0010) +#define MPI2_SATA_PT_REQ_PT_FLAGS_UNSPECIFIED_VU (0x0004) +#define MPI2_SATA_PT_REQ_PT_FLAGS_WRITE (0x0002) +#define MPI2_SATA_PT_REQ_PT_FLAGS_READ (0x0001) + +/* values for SGLFlags field are in the SGL section of mpi2.h */ + + +/* SATA Passthrough Reply Message */ +typedef struct _MPI2_SATA_PASSTHROUGH_REPLY +{ + U16 DevHandle; /* 0x00 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 PassthroughFlags; /* 0x04 */ + U8 SGLFlags; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved1; /* 0x0A */ + U8 Reserved2; /* 0x0C */ + U8 SASStatus; /* 0x0D */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U8 StatusFIS[20]; /* 0x14 */ + U32 StatusControlRegisters; /* 0x28 */ + U32 TransferCount; /* 0x2C */ +} MPI2_SATA_PASSTHROUGH_REPLY, MPI2_POINTER PTR_MPI2_SATA_PASSTHROUGH_REPLY, + Mpi2SataPassthroughReply_t, MPI2_POINTER pMpi2SataPassthroughReply_t; + +/* values for SASStatus field are at the top of this file */ + + +/**************************************************************************** +* SAS IO Unit Control messages +****************************************************************************/ + +/* SAS IO Unit Control Request Message */ +typedef struct _MPI2_SAS_IOUNIT_CONTROL_REQUEST +{ + U8 Operation; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 DevHandle; /* 0x04 */ + U8 IOCParameter; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U16 Reserved4; /* 0x0C */ + U8 PhyNum; /* 0x0E */ + U8 PrimFlags; /* 0x0F */ + U32 Primitive; /* 0x10 */ + U8 LookupMethod; /* 0x14 */ + U8 Reserved5; /* 0x15 */ + U16 SlotNumber; /* 0x16 */ + U64 LookupAddress; /* 0x18 */ + U32 IOCParameterValue; /* 0x20 */ + U32 Reserved7; /* 0x24 */ + U32 Reserved8; /* 0x28 */ +} MPI2_SAS_IOUNIT_CONTROL_REQUEST, + MPI2_POINTER PTR_MPI2_SAS_IOUNIT_CONTROL_REQUEST, + Mpi2SasIoUnitControlRequest_t, MPI2_POINTER pMpi2SasIoUnitControlRequest_t; + +/* values for the Operation field */ +#define MPI2_SAS_OP_CLEAR_ALL_PERSISTENT (0x02) +#define MPI2_SAS_OP_PHY_LINK_RESET (0x06) +#define MPI2_SAS_OP_PHY_HARD_RESET (0x07) +#define MPI2_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08) +#define MPI2_SAS_OP_SEND_PRIMITIVE (0x0A) +#define MPI2_SAS_OP_FORCE_FULL_DISCOVERY (0x0B) +#define MPI2_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL (0x0C) +#define MPI2_SAS_OP_REMOVE_DEVICE (0x0D) +#define MPI2_SAS_OP_LOOKUP_MAPPING (0x0E) +#define MPI2_SAS_OP_SET_IOC_PARAMETER (0x0F) +#define MPI2_SAS_OP_PRODUCT_SPECIFIC_MIN (0x80) + +/* values for the PrimFlags field */ +#define MPI2_SAS_PRIMFLAGS_SINGLE (0x08) +#define MPI2_SAS_PRIMFLAGS_TRIPLE (0x02) +#define MPI2_SAS_PRIMFLAGS_REDUNDANT (0x01) + +/* values for the LookupMethod field */ +#define MPI2_SAS_LOOKUP_METHOD_SAS_ADDRESS (0x01) +#define MPI2_SAS_LOOKUP_METHOD_SAS_ENCLOSURE_SLOT (0x02) +#define MPI2_SAS_LOOKUP_METHOD_SAS_DEVICE_NAME (0x03) + + +/* SAS IO Unit Control Reply Message */ +typedef struct _MPI2_SAS_IOUNIT_CONTROL_REPLY +{ + U8 Operation; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 DevHandle; /* 0x04 */ + U8 IOCParameter; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U16 Reserved4; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ +} MPI2_SAS_IOUNIT_CONTROL_REPLY, + MPI2_POINTER PTR_MPI2_SAS_IOUNIT_CONTROL_REPLY, + Mpi2SasIoUnitControlReply_t, MPI2_POINTER pMpi2SasIoUnitControlReply_t; + + +#endif + + diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_tool.h b/drivers/scsi/mpt2sas/mpi/mpi2_tool.h new file mode 100644 index 00000000000..2ff4e936bd3 --- /dev/null +++ b/drivers/scsi/mpt2sas/mpi/mpi2_tool.h @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2000-2008 LSI Corporation. + * + * + * Name: mpi2_tool.h + * Title: MPI diagnostic tool structures and definitions + * Creation Date: March 26, 2007 + * + * mpi2_tool.h Version: 02.00.02 + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 12-18-07 02.00.01 Added Diagnostic Buffer Post and Diagnostic Release + * structures and defines. + * 02-29-08 02.00.02 Modified various names to make them 32-character unique. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI2_TOOL_H +#define MPI2_TOOL_H + +/***************************************************************************** +* +* Toolbox Messages +* +*****************************************************************************/ + +/* defines for the Tools */ +#define MPI2_TOOLBOX_CLEAN_TOOL (0x00) +#define MPI2_TOOLBOX_MEMORY_MOVE_TOOL (0x01) +#define MPI2_TOOLBOX_BEACON_TOOL (0x05) + +/**************************************************************************** +* Toolbox reply +****************************************************************************/ + +typedef struct _MPI2_TOOLBOX_REPLY +{ + U8 Tool; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 Reserved5; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ +} MPI2_TOOLBOX_REPLY, MPI2_POINTER PTR_MPI2_TOOLBOX_REPLY, + Mpi2ToolboxReply_t, MPI2_POINTER pMpi2ToolboxReply_t; + + +/**************************************************************************** +* Toolbox Clean Tool request +****************************************************************************/ + +typedef struct _MPI2_TOOLBOX_CLEAN_REQUEST +{ + U8 Tool; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U32 Flags; /* 0x0C */ + } MPI2_TOOLBOX_CLEAN_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_CLEAN_REQUEST, + Mpi2ToolboxCleanRequest_t, MPI2_POINTER pMpi2ToolboxCleanRequest_t; + +/* values for the Flags field */ +#define MPI2_TOOLBOX_CLEAN_BOOT_SERVICES (0x80000000) +#define MPI2_TOOLBOX_CLEAN_PERSIST_MANUFACT_PAGES (0x40000000) +#define MPI2_TOOLBOX_CLEAN_OTHER_PERSIST_PAGES (0x20000000) +#define MPI2_TOOLBOX_CLEAN_FW_CURRENT (0x10000000) +#define MPI2_TOOLBOX_CLEAN_FW_BACKUP (0x08000000) +#define MPI2_TOOLBOX_CLEAN_MEGARAID (0x02000000) +#define MPI2_TOOLBOX_CLEAN_INITIALIZATION (0x01000000) +#define MPI2_TOOLBOX_CLEAN_FLASH (0x00000004) +#define MPI2_TOOLBOX_CLEAN_SEEPROM (0x00000002) +#define MPI2_TOOLBOX_CLEAN_NVSRAM (0x00000001) + + +/**************************************************************************** +* Toolbox Memory Move request +****************************************************************************/ + +typedef struct _MPI2_TOOLBOX_MEM_MOVE_REQUEST +{ + U8 Tool; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + MPI2_SGE_SIMPLE_UNION SGL; /* 0x0C */ +} MPI2_TOOLBOX_MEM_MOVE_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_MEM_MOVE_REQUEST, + Mpi2ToolboxMemMoveRequest_t, MPI2_POINTER pMpi2ToolboxMemMoveRequest_t; + + +/**************************************************************************** +* Toolbox Beacon Tool request +****************************************************************************/ + +typedef struct _MPI2_TOOLBOX_BEACON_REQUEST +{ + U8 Tool; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U8 Reserved5; /* 0x0C */ + U8 PhysicalPort; /* 0x0D */ + U8 Reserved6; /* 0x0E */ + U8 Flags; /* 0x0F */ +} MPI2_TOOLBOX_BEACON_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_BEACON_REQUEST, + Mpi2ToolboxBeaconRequest_t, MPI2_POINTER pMpi2ToolboxBeaconRequest_t; + +/* values for the Flags field */ +#define MPI2_TOOLBOX_FLAGS_BEACONMODE_OFF (0x00) +#define MPI2_TOOLBOX_FLAGS_BEACONMODE_ON (0x01) + + +/***************************************************************************** +* +* Diagnostic Buffer Messages +* +*****************************************************************************/ + + +/**************************************************************************** +* Diagnostic Buffer Post request +****************************************************************************/ + +typedef struct _MPI2_DIAG_BUFFER_POST_REQUEST +{ + U8 Reserved1; /* 0x00 */ + U8 BufferType; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U64 BufferAddress; /* 0x0C */ + U32 BufferLength; /* 0x14 */ + U32 Reserved5; /* 0x18 */ + U32 Reserved6; /* 0x1C */ + U32 Flags; /* 0x20 */ + U32 ProductSpecific[23]; /* 0x24 */ +} MPI2_DIAG_BUFFER_POST_REQUEST, MPI2_POINTER PTR_MPI2_DIAG_BUFFER_POST_REQUEST, + Mpi2DiagBufferPostRequest_t, MPI2_POINTER pMpi2DiagBufferPostRequest_t; + +/* values for the BufferType field */ +#define MPI2_DIAG_BUF_TYPE_TRACE (0x00) +#define MPI2_DIAG_BUF_TYPE_SNAPSHOT (0x01) +/* count of the number of buffer types */ +#define MPI2_DIAG_BUF_TYPE_COUNT (0x02) + + +/**************************************************************************** +* Diagnostic Buffer Post reply +****************************************************************************/ + +typedef struct _MPI2_DIAG_BUFFER_POST_REPLY +{ + U8 Reserved1; /* 0x00 */ + U8 BufferType; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 Reserved5; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ + U32 TransferLength; /* 0x14 */ +} MPI2_DIAG_BUFFER_POST_REPLY, MPI2_POINTER PTR_MPI2_DIAG_BUFFER_POST_REPLY, + Mpi2DiagBufferPostReply_t, MPI2_POINTER pMpi2DiagBufferPostReply_t; + + +/**************************************************************************** +* Diagnostic Release request +****************************************************************************/ + +typedef struct _MPI2_DIAG_RELEASE_REQUEST +{ + U8 Reserved1; /* 0x00 */ + U8 BufferType; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ +} MPI2_DIAG_RELEASE_REQUEST, MPI2_POINTER PTR_MPI2_DIAG_RELEASE_REQUEST, + Mpi2DiagReleaseRequest_t, MPI2_POINTER pMpi2DiagReleaseRequest_t; + + +/**************************************************************************** +* Diagnostic Buffer Post reply +****************************************************************************/ + +typedef struct _MPI2_DIAG_RELEASE_REPLY +{ + U8 Reserved1; /* 0x00 */ + U8 BufferType; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 Reserved5; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ +} MPI2_DIAG_RELEASE_REPLY, MPI2_POINTER PTR_MPI2_DIAG_RELEASE_REPLY, + Mpi2DiagReleaseReply_t, MPI2_POINTER pMpi2DiagReleaseReply_t; + + +#endif + diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_type.h b/drivers/scsi/mpt2sas/mpi/mpi2_type.h new file mode 100644 index 00000000000..cfde017bf16 --- /dev/null +++ b/drivers/scsi/mpt2sas/mpi/mpi2_type.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2000-2007 LSI Corporation. + * + * + * Name: mpi2_type.h + * Title: MPI basic type definitions + * Creation Date: August 16, 2006 + * + * mpi2_type.h Version: 02.00.00 + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI2_TYPE_H +#define MPI2_TYPE_H + + +/******************************************************************************* + * Define MPI2_POINTER if it hasn't already been defined. By default + * MPI2_POINTER is defined to be a near pointer. MPI2_POINTER can be defined as + * a far pointer by defining MPI2_POINTER as "far *" before this header file is + * included. + */ +#ifndef MPI2_POINTER +#define MPI2_POINTER * +#endif + +/* the basic types may have already been included by mpi_type.h */ +#ifndef MPI_TYPE_H +/***************************************************************************** +* +* Basic Types +* +*****************************************************************************/ + +typedef u8 U8; +typedef __le16 U16; +typedef __le32 U32; +typedef __le64 U64 __attribute__((aligned(4))); + +/***************************************************************************** +* +* Pointer Types +* +*****************************************************************************/ + +typedef U8 *PU8; +typedef U16 *PU16; +typedef U32 *PU32; +typedef U64 *PU64; + +#endif + +#endif + diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c new file mode 100644 index 00000000000..52427a8324f --- /dev/null +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -0,0 +1,3435 @@ +/* + * This is the Fusion MPT base driver providing common API layer interface + * for access to MPT (Message Passing Technology) firmware. + * + * This code is based on drivers/scsi/mpt2sas/mpt2_base.c + * Copyright (C) 2007-2008 LSI Corporation + * (mailto:DL-MPTFusionLinux@lsi.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * NO WARRANTY + * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT + * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is + * solely responsible for determining the appropriateness of using and + * distributing the Program and assumes all risks associated with its + * exercise of rights under this Agreement, including but not limited to + * the risks and costs of program errors, damage to or loss of data, + * programs or equipment, and unavailability or interruption of operations. + + * DISCLAIMER OF LIABILITY + * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED + * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mpt2sas_base.h" + +static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS]; + +#define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */ +#define MPT2SAS_MAX_REQUEST_QUEUE 500 /* maximum controller queue depth */ + +static int max_queue_depth = -1; +module_param(max_queue_depth, int, 0); +MODULE_PARM_DESC(max_queue_depth, " max controller queue depth "); + +static int max_sgl_entries = -1; +module_param(max_sgl_entries, int, 0); +MODULE_PARM_DESC(max_sgl_entries, " max sg entries "); + +static int msix_disable = -1; +module_param(msix_disable, int, 0); +MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)"); + +/** + * _base_fault_reset_work - workq handling ioc fault conditions + * @work: input argument, used to derive ioc + * Context: sleep. + * + * Return nothing. + */ +static void +_base_fault_reset_work(struct work_struct *work) +{ + struct MPT2SAS_ADAPTER *ioc = + container_of(work, struct MPT2SAS_ADAPTER, fault_reset_work.work); + unsigned long flags; + u32 doorbell; + int rc; + + spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); + if (ioc->ioc_reset_in_progress) + goto rearm_timer; + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + + doorbell = mpt2sas_base_get_iocstate(ioc, 0); + if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) { + rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, + FORCE_BIG_HAMMER); + printk(MPT2SAS_WARN_FMT "%s: hard reset: %s\n", ioc->name, + __func__, (rc == 0) ? "success" : "failed"); + doorbell = mpt2sas_base_get_iocstate(ioc, 0); + if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) + mpt2sas_base_fault_info(ioc, doorbell & + MPI2_DOORBELL_DATA_MASK); + } + + spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); + rearm_timer: + if (ioc->fault_reset_work_q) + queue_delayed_work(ioc->fault_reset_work_q, + &ioc->fault_reset_work, + msecs_to_jiffies(FAULT_POLLING_INTERVAL)); + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); +} + +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING +/** + * _base_sas_ioc_info - verbose translation of the ioc status + * @ioc: pointer to scsi command object + * @mpi_reply: reply mf payload returned from firmware + * @request_hdr: request mf + * + * Return nothing. + */ +static void +_base_sas_ioc_info(struct MPT2SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply, + MPI2RequestHeader_t *request_hdr) +{ + u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & + MPI2_IOCSTATUS_MASK; + char *desc = NULL; + u16 frame_sz; + char *func_str = NULL; + + /* SCSI_IO, RAID_PASS are handled from _scsih_scsi_ioc_info */ + if (request_hdr->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || + request_hdr->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH || + request_hdr->Function == MPI2_FUNCTION_EVENT_NOTIFICATION) + return; + + switch (ioc_status) { + +/**************************************************************************** +* Common IOCStatus values for all replies +****************************************************************************/ + + case MPI2_IOCSTATUS_INVALID_FUNCTION: + desc = "invalid function"; + break; + case MPI2_IOCSTATUS_BUSY: + desc = "busy"; + break; + case MPI2_IOCSTATUS_INVALID_SGL: + desc = "invalid sgl"; + break; + case MPI2_IOCSTATUS_INTERNAL_ERROR: + desc = "internal error"; + break; + case MPI2_IOCSTATUS_INVALID_VPID: + desc = "invalid vpid"; + break; + case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES: + desc = "insufficient resources"; + break; + case MPI2_IOCSTATUS_INVALID_FIELD: + desc = "invalid field"; + break; + case MPI2_IOCSTATUS_INVALID_STATE: + desc = "invalid state"; + break; + case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED: + desc = "op state not supported"; + break; + +/**************************************************************************** +* Config IOCStatus values +****************************************************************************/ + + case MPI2_IOCSTATUS_CONFIG_INVALID_ACTION: + desc = "config invalid action"; + break; + case MPI2_IOCSTATUS_CONFIG_INVALID_TYPE: + desc = "config invalid type"; + break; + case MPI2_IOCSTATUS_CONFIG_INVALID_PAGE: + desc = "config invalid page"; + break; + case MPI2_IOCSTATUS_CONFIG_INVALID_DATA: + desc = "config invalid data"; + break; + case MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS: + desc = "config no defaults"; + break; + case MPI2_IOCSTATUS_CONFIG_CANT_COMMIT: + desc = "config cant commit"; + break; + +/**************************************************************************** +* SCSI IO Reply +****************************************************************************/ + + case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: + case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE: + case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: + case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: + case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN: + case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR: + case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: + case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: + case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: + case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED: + case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: + case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: + break; + +/**************************************************************************** +* For use by SCSI Initiator and SCSI Target end-to-end data protection +****************************************************************************/ + + case MPI2_IOCSTATUS_EEDP_GUARD_ERROR: + desc = "eedp guard error"; + break; + case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR: + desc = "eedp ref tag error"; + break; + case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR: + desc = "eedp app tag error"; + break; + +/**************************************************************************** +* SCSI Target values +****************************************************************************/ + + case MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX: + desc = "target invalid io index"; + break; + case MPI2_IOCSTATUS_TARGET_ABORTED: + desc = "target aborted"; + break; + case MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE: + desc = "target no conn retryable"; + break; + case MPI2_IOCSTATUS_TARGET_NO_CONNECTION: + desc = "target no connection"; + break; + case MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH: + desc = "target xfer count mismatch"; + break; + case MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR: + desc = "target data offset error"; + break; + case MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA: + desc = "target too much write data"; + break; + case MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT: + desc = "target iu too short"; + break; + case MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT: + desc = "target ack nak timeout"; + break; + case MPI2_IOCSTATUS_TARGET_NAK_RECEIVED: + desc = "target nak received"; + break; + +/**************************************************************************** +* Serial Attached SCSI values +****************************************************************************/ + + case MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED: + desc = "smp request failed"; + break; + case MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN: + desc = "smp data overrun"; + break; + +/**************************************************************************** +* Diagnostic Buffer Post / Diagnostic Release values +****************************************************************************/ + + case MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED: + desc = "diagnostic released"; + break; + default: + break; + } + + if (!desc) + return; + + switch (request_hdr->Function) { + case MPI2_FUNCTION_CONFIG: + frame_sz = sizeof(Mpi2ConfigRequest_t) + ioc->sge_size; + func_str = "config_page"; + break; + case MPI2_FUNCTION_SCSI_TASK_MGMT: + frame_sz = sizeof(Mpi2SCSITaskManagementRequest_t); + func_str = "task_mgmt"; + break; + case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL: + frame_sz = sizeof(Mpi2SasIoUnitControlRequest_t); + func_str = "sas_iounit_ctl"; + break; + case MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR: + frame_sz = sizeof(Mpi2SepRequest_t); + func_str = "enclosure"; + break; + case MPI2_FUNCTION_IOC_INIT: + frame_sz = sizeof(Mpi2IOCInitRequest_t); + func_str = "ioc_init"; + break; + case MPI2_FUNCTION_PORT_ENABLE: + frame_sz = sizeof(Mpi2PortEnableRequest_t); + func_str = "port_enable"; + break; + case MPI2_FUNCTION_SMP_PASSTHROUGH: + frame_sz = sizeof(Mpi2SmpPassthroughRequest_t) + ioc->sge_size; + func_str = "smp_passthru"; + break; + default: + frame_sz = 32; + func_str = "unknown"; + break; + } + + printk(MPT2SAS_WARN_FMT "ioc_status: %s(0x%04x), request(0x%p)," + " (%s)\n", ioc->name, desc, ioc_status, request_hdr, func_str); + + _debug_dump_mf(request_hdr, frame_sz/4); +} + +/** + * _base_display_event_data - verbose translation of firmware asyn events + * @ioc: pointer to scsi command object + * @mpi_reply: reply mf payload returned from firmware + * + * Return nothing. + */ +static void +_base_display_event_data(struct MPT2SAS_ADAPTER *ioc, + Mpi2EventNotificationReply_t *mpi_reply) +{ + char *desc = NULL; + u16 event; + + if (!(ioc->logging_level & MPT_DEBUG_EVENTS)) + return; + + event = le16_to_cpu(mpi_reply->Event); + + switch (event) { + case MPI2_EVENT_LOG_DATA: + desc = "Log Data"; + break; + case MPI2_EVENT_STATE_CHANGE: + desc = "Status Change"; + break; + case MPI2_EVENT_HARD_RESET_RECEIVED: + desc = "Hard Reset Received"; + break; + case MPI2_EVENT_EVENT_CHANGE: + desc = "Event Change"; + break; + case MPI2_EVENT_TASK_SET_FULL: + desc = "Task Set Full"; + break; + case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: + desc = "Device Status Change"; + break; + case MPI2_EVENT_IR_OPERATION_STATUS: + desc = "IR Operation Status"; + break; + case MPI2_EVENT_SAS_DISCOVERY: + desc = "Discovery"; + break; + case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE: + desc = "SAS Broadcast Primitive"; + break; + case MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE: + desc = "SAS Init Device Status Change"; + break; + case MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW: + desc = "SAS Init Table Overflow"; + break; + case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: + desc = "SAS Topology Change List"; + break; + case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: + desc = "SAS Enclosure Device Status Change"; + break; + case MPI2_EVENT_IR_VOLUME: + desc = "IR Volume"; + break; + case MPI2_EVENT_IR_PHYSICAL_DISK: + desc = "IR Physical Disk"; + break; + case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: + desc = "IR Configuration Change List"; + break; + case MPI2_EVENT_LOG_ENTRY_ADDED: + desc = "Log Entry Added"; + break; + } + + if (!desc) + return; + + printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, desc); +} +#endif + +/** + * _base_sas_log_info - verbose translation of firmware log info + * @ioc: pointer to scsi command object + * @log_info: log info + * + * Return nothing. + */ +static void +_base_sas_log_info(struct MPT2SAS_ADAPTER *ioc , u32 log_info) +{ + union loginfo_type { + u32 loginfo; + struct { + u32 subcode:16; + u32 code:8; + u32 originator:4; + u32 bus_type:4; + } dw; + }; + union loginfo_type sas_loginfo; + char *originator_str = NULL; + + sas_loginfo.loginfo = log_info; + if (sas_loginfo.dw.bus_type != 3 /*SAS*/) + return; + + /* eat the loginfos associated with task aborts */ + if (ioc->ignore_loginfos && (log_info == 30050000 || log_info == + 0x31140000 || log_info == 0x31130000)) + return; + + switch (sas_loginfo.dw.originator) { + case 0: + originator_str = "IOP"; + break; + case 1: + originator_str = "PL"; + break; + case 2: + originator_str = "IR"; + break; + } + + printk(MPT2SAS_WARN_FMT "log_info(0x%08x): originator(%s), " + "code(0x%02x), sub_code(0x%04x)\n", ioc->name, log_info, + originator_str, sas_loginfo.dw.code, + sas_loginfo.dw.subcode); +} + +/** + * mpt2sas_base_fault_info - verbose translation of firmware FAULT code + * @ioc: pointer to scsi command object + * @fault_code: fault code + * + * Return nothing. + */ +void +mpt2sas_base_fault_info(struct MPT2SAS_ADAPTER *ioc , u16 fault_code) +{ + printk(MPT2SAS_ERR_FMT "fault_state(0x%04x)!\n", + ioc->name, fault_code); +} + +/** + * _base_display_reply_info - + * @ioc: pointer to scsi command object + * @smid: system request message index + * @VF_ID: virtual function id + * @reply: reply message frame(lower 32bit addr) + * + * Return nothing. + */ +static void +_base_display_reply_info(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, + u32 reply) +{ + MPI2DefaultReply_t *mpi_reply; + u16 ioc_status; + + mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); + ioc_status = le16_to_cpu(mpi_reply->IOCStatus); +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING + if ((ioc_status & MPI2_IOCSTATUS_MASK) && + (ioc->logging_level & MPT_DEBUG_REPLY)) { + _base_sas_ioc_info(ioc , mpi_reply, + mpt2sas_base_get_msg_frame(ioc, smid)); + } +#endif + if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) + _base_sas_log_info(ioc, le32_to_cpu(mpi_reply->IOCLogInfo)); +} + +/** + * mpt2sas_base_done - base internal command completion routine + * @ioc: pointer to scsi command object + * @smid: system request message index + * @VF_ID: virtual function id + * @reply: reply message frame(lower 32bit addr) + * + * Return nothing. + */ +void +mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) +{ + MPI2DefaultReply_t *mpi_reply; + + mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); + if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK) + return; + + if (ioc->base_cmds.status == MPT2_CMD_NOT_USED) + return; + + ioc->base_cmds.status |= MPT2_CMD_COMPLETE; + if (mpi_reply) { + ioc->base_cmds.status |= MPT2_CMD_REPLY_VALID; + memcpy(ioc->base_cmds.reply, mpi_reply, mpi_reply->MsgLength*4); + } + ioc->base_cmds.status &= ~MPT2_CMD_PENDING; + complete(&ioc->base_cmds.done); +} + +/** + * _base_async_event - main callback handler for firmware asyn events + * @ioc: pointer to scsi command object + * @VF_ID: virtual function id + * @reply: reply message frame(lower 32bit addr) + * + * Return nothing. + */ +static void +_base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply) +{ + Mpi2EventNotificationReply_t *mpi_reply; + Mpi2EventAckRequest_t *ack_request; + u16 smid; + + mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); + if (!mpi_reply) + return; + if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION) + return; +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING + _base_display_event_data(ioc, mpi_reply); +#endif + if (!(mpi_reply->AckRequired & MPI2_EVENT_NOTIFICATION_ACK_REQUIRED)) + goto out; + smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx); + if (!smid) { + printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", + ioc->name, __func__); + goto out; + } + + ack_request = mpt2sas_base_get_msg_frame(ioc, smid); + memset(ack_request, 0, sizeof(Mpi2EventAckRequest_t)); + ack_request->Function = MPI2_FUNCTION_EVENT_ACK; + ack_request->Event = mpi_reply->Event; + ack_request->EventContext = mpi_reply->EventContext; + ack_request->VF_ID = VF_ID; + mpt2sas_base_put_smid_default(ioc, smid, VF_ID); + + out: + + /* scsih callback handler */ + mpt2sas_scsih_event_callback(ioc, VF_ID, reply); + + /* ctl callback handler */ + mpt2sas_ctl_event_callback(ioc, VF_ID, reply); +} + +/** + * _base_mask_interrupts - disable interrupts + * @ioc: pointer to scsi command object + * + * Disabling ResetIRQ, Reply and Doorbell Interrupts + * + * Return nothing. + */ +static void +_base_mask_interrupts(struct MPT2SAS_ADAPTER *ioc) +{ + u32 him_register; + + ioc->mask_interrupts = 1; + him_register = readl(&ioc->chip->HostInterruptMask); + him_register |= MPI2_HIM_DIM + MPI2_HIM_RIM + MPI2_HIM_RESET_IRQ_MASK; + writel(him_register, &ioc->chip->HostInterruptMask); + readl(&ioc->chip->HostInterruptMask); +} + +/** + * _base_unmask_interrupts - enable interrupts + * @ioc: pointer to scsi command object + * + * Enabling only Reply Interrupts + * + * Return nothing. + */ +static void +_base_unmask_interrupts(struct MPT2SAS_ADAPTER *ioc) +{ + u32 him_register; + + writel(0, &ioc->chip->HostInterruptStatus); + him_register = readl(&ioc->chip->HostInterruptMask); + him_register &= ~MPI2_HIM_RIM; + writel(him_register, &ioc->chip->HostInterruptMask); + ioc->mask_interrupts = 0; +} + +/** + * _base_interrupt - MPT adapter (IOC) specific interrupt handler. + * @irq: irq number (not used) + * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure + * @r: pt_regs pointer (not used) + * + * Return IRQ_HANDLE if processed, else IRQ_NONE. + */ +static irqreturn_t +_base_interrupt(int irq, void *bus_id) +{ + u32 post_index, post_index_next, completed_cmds; + u8 request_desript_type; + u16 smid; + u8 cb_idx; + u32 reply; + u8 VF_ID; + int i; + struct MPT2SAS_ADAPTER *ioc = bus_id; + + if (ioc->mask_interrupts) + return IRQ_NONE; + + post_index = ioc->reply_post_host_index; + request_desript_type = ioc->reply_post_free[post_index]. + Default.ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; + if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) + return IRQ_NONE; + + completed_cmds = 0; + do { + if (ioc->reply_post_free[post_index].Words == ~0ULL) + goto out; + reply = 0; + cb_idx = 0xFF; + smid = le16_to_cpu(ioc->reply_post_free[post_index]. + Default.DescriptorTypeDependent1); + VF_ID = ioc->reply_post_free[post_index]. + Default.VF_ID; + if (request_desript_type == + MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) { + reply = le32_to_cpu(ioc->reply_post_free[post_index]. + AddressReply.ReplyFrameAddress); + } else if (request_desript_type == + MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER) + goto next; + else if (request_desript_type == + MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS) + goto next; + if (smid) + cb_idx = ioc->scsi_lookup[smid - 1].cb_idx; + if (smid && cb_idx != 0xFF) { + mpt_callbacks[cb_idx](ioc, smid, VF_ID, reply); + if (reply) + _base_display_reply_info(ioc, smid, VF_ID, + reply); + mpt2sas_base_free_smid(ioc, smid); + } + if (!smid) + _base_async_event(ioc, VF_ID, reply); + + /* reply free queue handling */ + if (reply) { + ioc->reply_free_host_index = + (ioc->reply_free_host_index == + (ioc->reply_free_queue_depth - 1)) ? + 0 : ioc->reply_free_host_index + 1; + ioc->reply_free[ioc->reply_free_host_index] = + cpu_to_le32(reply); + writel(ioc->reply_free_host_index, + &ioc->chip->ReplyFreeHostIndex); + wmb(); + } + + next: + post_index_next = (post_index == (ioc->reply_post_queue_depth - + 1)) ? 0 : post_index + 1; + request_desript_type = + ioc->reply_post_free[post_index_next].Default.ReplyFlags + & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; + completed_cmds++; + if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) + goto out; + post_index = post_index_next; + } while (1); + + out: + + if (!completed_cmds) + return IRQ_NONE; + + /* reply post descriptor handling */ + post_index_next = ioc->reply_post_host_index; + for (i = 0 ; i < completed_cmds; i++) { + post_index = post_index_next; + /* poison the reply post descriptor */ + ioc->reply_post_free[post_index_next].Words = ~0ULL; + post_index_next = (post_index == + (ioc->reply_post_queue_depth - 1)) + ? 0 : post_index + 1; + } + ioc->reply_post_host_index = post_index_next; + writel(post_index_next, &ioc->chip->ReplyPostHostIndex); + wmb(); + return IRQ_HANDLED; +} + +/** + * mpt2sas_base_release_callback_handler - clear interupt callback handler + * @cb_idx: callback index + * + * Return nothing. + */ +void +mpt2sas_base_release_callback_handler(u8 cb_idx) +{ + mpt_callbacks[cb_idx] = NULL; +} + +/** + * mpt2sas_base_register_callback_handler - obtain index for the interrupt callback handler + * @cb_func: callback function + * + * Returns cb_func. + */ +u8 +mpt2sas_base_register_callback_handler(MPT_CALLBACK cb_func) +{ + u8 cb_idx; + + for (cb_idx = MPT_MAX_CALLBACKS-1; cb_idx; cb_idx--) + if (mpt_callbacks[cb_idx] == NULL) + break; + + mpt_callbacks[cb_idx] = cb_func; + return cb_idx; +} + +/** + * mpt2sas_base_initialize_callback_handler - initialize the interrupt callback handler + * + * Return nothing. + */ +void +mpt2sas_base_initialize_callback_handler(void) +{ + u8 cb_idx; + + for (cb_idx = 0; cb_idx < MPT_MAX_CALLBACKS; cb_idx++) + mpt2sas_base_release_callback_handler(cb_idx); +} + +/** + * mpt2sas_base_build_zero_len_sge - build zero length sg entry + * @ioc: per adapter object + * @paddr: virtual address for SGE + * + * Create a zero length scatter gather entry to insure the IOCs hardware has + * something to use if the target device goes brain dead and tries + * to send data even when none is asked for. + * + * Return nothing. + */ +void +mpt2sas_base_build_zero_len_sge(struct MPT2SAS_ADAPTER *ioc, void *paddr) +{ + u32 flags_length = (u32)((MPI2_SGE_FLAGS_LAST_ELEMENT | + MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST | + MPI2_SGE_FLAGS_SIMPLE_ELEMENT) << + MPI2_SGE_FLAGS_SHIFT); + ioc->base_add_sg_single(paddr, flags_length, -1); +} + +/** + * _base_add_sg_single_32 - Place a simple 32 bit SGE at address pAddr. + * @paddr: virtual address for SGE + * @flags_length: SGE flags and data transfer length + * @dma_addr: Physical address + * + * Return nothing. + */ +static void +_base_add_sg_single_32(void *paddr, u32 flags_length, dma_addr_t dma_addr) +{ + Mpi2SGESimple32_t *sgel = paddr; + + flags_length |= (MPI2_SGE_FLAGS_32_BIT_ADDRESSING | + MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT; + sgel->FlagsLength = cpu_to_le32(flags_length); + sgel->Address = cpu_to_le32(dma_addr); +} + + +/** + * _base_add_sg_single_64 - Place a simple 64 bit SGE at address pAddr. + * @paddr: virtual address for SGE + * @flags_length: SGE flags and data transfer length + * @dma_addr: Physical address + * + * Return nothing. + */ +static void +_base_add_sg_single_64(void *paddr, u32 flags_length, dma_addr_t dma_addr) +{ + Mpi2SGESimple64_t *sgel = paddr; + + flags_length |= (MPI2_SGE_FLAGS_64_BIT_ADDRESSING | + MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT; + sgel->FlagsLength = cpu_to_le32(flags_length); + sgel->Address = cpu_to_le64(dma_addr); +} + +#define convert_to_kb(x) ((x) << (PAGE_SHIFT - 10)) + +/** + * _base_config_dma_addressing - set dma addressing + * @ioc: per adapter object + * @pdev: PCI device struct + * + * Returns 0 for success, non-zero for failure. + */ +static int +_base_config_dma_addressing(struct MPT2SAS_ADAPTER *ioc, struct pci_dev *pdev) +{ + struct sysinfo s; + char *desc = NULL; + + if (sizeof(dma_addr_t) > 4) { + const uint64_t required_mask = + dma_get_required_mask(&pdev->dev); + if ((required_mask > DMA_32BIT_MASK) && !pci_set_dma_mask(pdev, + DMA_64BIT_MASK) && !pci_set_consistent_dma_mask(pdev, + DMA_64BIT_MASK)) { + ioc->base_add_sg_single = &_base_add_sg_single_64; + ioc->sge_size = sizeof(Mpi2SGESimple64_t); + desc = "64"; + goto out; + } + } + + if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK) + && !pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) { + ioc->base_add_sg_single = &_base_add_sg_single_32; + ioc->sge_size = sizeof(Mpi2SGESimple32_t); + desc = "32"; + } else + return -ENODEV; + + out: + si_meminfo(&s); + printk(MPT2SAS_INFO_FMT "%s BIT PCI BUS DMA ADDRESSING SUPPORTED, " + "total mem (%ld kB)\n", ioc->name, desc, convert_to_kb(s.totalram)); + + return 0; +} + +/** + * _base_save_msix_table - backup msix vector table + * @ioc: per adapter object + * + * This address an errata where diag reset clears out the table + */ +static void +_base_save_msix_table(struct MPT2SAS_ADAPTER *ioc) +{ + int i; + + if (!ioc->msix_enable || ioc->msix_table_backup == NULL) + return; + + for (i = 0; i < ioc->msix_vector_count; i++) + ioc->msix_table_backup[i] = ioc->msix_table[i]; +} + +/** + * _base_restore_msix_table - this restores the msix vector table + * @ioc: per adapter object + * + */ +static void +_base_restore_msix_table(struct MPT2SAS_ADAPTER *ioc) +{ + int i; + + if (!ioc->msix_enable || ioc->msix_table_backup == NULL) + return; + + for (i = 0; i < ioc->msix_vector_count; i++) + ioc->msix_table[i] = ioc->msix_table_backup[i]; +} + +/** + * _base_check_enable_msix - checks MSIX capabable. + * @ioc: per adapter object + * + * Check to see if card is capable of MSIX, and set number + * of avaliable msix vectors + */ +static int +_base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc) +{ + int base; + u16 message_control; + u32 msix_table_offset; + + base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX); + if (!base) { + dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "msix not " + "supported\n", ioc->name)); + return -EINVAL; + } + + /* get msix vector count */ + pci_read_config_word(ioc->pdev, base + 2, &message_control); + ioc->msix_vector_count = (message_control & 0x3FF) + 1; + + /* get msix table */ + pci_read_config_dword(ioc->pdev, base + 4, &msix_table_offset); + msix_table_offset &= 0xFFFFFFF8; + ioc->msix_table = (u32 *)((void *)ioc->chip + msix_table_offset); + + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "msix is supported, " + "vector_count(%d), table_offset(0x%08x), table(%p)\n", ioc->name, + ioc->msix_vector_count, msix_table_offset, ioc->msix_table)); + return 0; +} + +/** + * _base_disable_msix - disables msix + * @ioc: per adapter object + * + */ +static void +_base_disable_msix(struct MPT2SAS_ADAPTER *ioc) +{ + if (ioc->msix_enable) { + pci_disable_msix(ioc->pdev); + kfree(ioc->msix_table_backup); + ioc->msix_table_backup = NULL; + ioc->msix_enable = 0; + } +} + +/** + * _base_enable_msix - enables msix, failback to io_apic + * @ioc: per adapter object + * + */ +static int +_base_enable_msix(struct MPT2SAS_ADAPTER *ioc) +{ + struct msix_entry entries; + int r; + u8 try_msix = 0; + + if (msix_disable == -1 || msix_disable == 0) + try_msix = 1; + + if (!try_msix) + goto try_ioapic; + + if (_base_check_enable_msix(ioc) != 0) + goto try_ioapic; + + ioc->msix_table_backup = kcalloc(ioc->msix_vector_count, + sizeof(u32), GFP_KERNEL); + if (!ioc->msix_table_backup) { + dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "allocation for " + "msix_table_backup failed!!!\n", ioc->name)); + goto try_ioapic; + } + + memset(&entries, 0, sizeof(struct msix_entry)); + r = pci_enable_msix(ioc->pdev, &entries, 1); + if (r) { + dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "pci_enable_msix " + "failed (r=%d) !!!\n", ioc->name, r)); + goto try_ioapic; + } + + r = request_irq(entries.vector, _base_interrupt, IRQF_SHARED, + ioc->name, ioc); + if (r) { + dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "unable to allocate " + "interrupt %d !!!\n", ioc->name, entries.vector)); + pci_disable_msix(ioc->pdev); + goto try_ioapic; + } + + ioc->pci_irq = entries.vector; + ioc->msix_enable = 1; + return 0; + +/* failback to io_apic interrupt routing */ + try_ioapic: + + r = request_irq(ioc->pdev->irq, _base_interrupt, IRQF_SHARED, + ioc->name, ioc); + if (r) { + printk(MPT2SAS_ERR_FMT "unable to allocate interrupt %d!\n", + ioc->name, ioc->pdev->irq); + r = -EBUSY; + goto out_fail; + } + + ioc->pci_irq = ioc->pdev->irq; + return 0; + + out_fail: + return r; +} + +/** + * mpt2sas_base_map_resources - map in controller resources (io/irq/memap) + * @ioc: per adapter object + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) +{ + struct pci_dev *pdev = ioc->pdev; + u32 memap_sz; + u32 pio_sz; + int i, r = 0; + + dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", + ioc->name, __func__)); + + ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM); + if (pci_enable_device_mem(pdev)) { + printk(MPT2SAS_WARN_FMT "pci_enable_device_mem: " + "failed\n", ioc->name); + return -ENODEV; + } + + + if (pci_request_selected_regions(pdev, ioc->bars, + MPT2SAS_DRIVER_NAME)) { + printk(MPT2SAS_WARN_FMT "pci_request_selected_regions: " + "failed\n", ioc->name); + r = -ENODEV; + goto out_fail; + } + + pci_set_master(pdev); + + if (_base_config_dma_addressing(ioc, pdev) != 0) { + printk(MPT2SAS_WARN_FMT "no suitable DMA mask for %s\n", + ioc->name, pci_name(pdev)); + r = -ENODEV; + goto out_fail; + } + + for (i = 0, memap_sz = 0, pio_sz = 0 ; i < DEVICE_COUNT_RESOURCE; i++) { + if (pci_resource_flags(pdev, i) & PCI_BASE_ADDRESS_SPACE_IO) { + if (pio_sz) + continue; + ioc->pio_chip = pci_resource_start(pdev, i); + pio_sz = pci_resource_len(pdev, i); + } else { + if (memap_sz) + continue; + ioc->chip_phys = pci_resource_start(pdev, i); + memap_sz = pci_resource_len(pdev, i); + ioc->chip = ioremap(ioc->chip_phys, memap_sz); + if (ioc->chip == NULL) { + printk(MPT2SAS_ERR_FMT "unable to map adapter " + "memory!\n", ioc->name); + r = -EINVAL; + goto out_fail; + } + } + } + + pci_set_drvdata(pdev, ioc->shost); + _base_mask_interrupts(ioc); + r = _base_enable_msix(ioc); + if (r) + goto out_fail; + + printk(MPT2SAS_INFO_FMT "%s: IRQ %d\n", + ioc->name, ((ioc->msix_enable) ? "PCI-MSI-X enabled" : + "IO-APIC enabled"), ioc->pci_irq); + printk(MPT2SAS_INFO_FMT "iomem(0x%lx), mapped(0x%p), size(%d)\n", + ioc->name, ioc->chip_phys, ioc->chip, memap_sz); + printk(MPT2SAS_INFO_FMT "ioport(0x%lx), size(%d)\n", + ioc->name, ioc->pio_chip, pio_sz); + + return 0; + + out_fail: + if (ioc->chip_phys) + iounmap(ioc->chip); + ioc->chip_phys = 0; + ioc->pci_irq = -1; + pci_release_selected_regions(ioc->pdev, ioc->bars); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + return r; +} + +/** + * mpt2sas_base_get_msg_frame_dma - obtain request mf pointer phys addr + * @ioc: per adapter object + * @smid: system request message index(smid zero is invalid) + * + * Returns phys pointer to message frame. + */ +dma_addr_t +mpt2sas_base_get_msg_frame_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid) +{ + return ioc->request_dma + (smid * ioc->request_sz); +} + +/** + * mpt2sas_base_get_msg_frame - obtain request mf pointer + * @ioc: per adapter object + * @smid: system request message index(smid zero is invalid) + * + * Returns virt pointer to message frame. + */ +void * +mpt2sas_base_get_msg_frame(struct MPT2SAS_ADAPTER *ioc, u16 smid) +{ + return (void *)(ioc->request + (smid * ioc->request_sz)); +} + +/** + * mpt2sas_base_get_sense_buffer - obtain a sense buffer assigned to a mf request + * @ioc: per adapter object + * @smid: system request message index + * + * Returns virt pointer to sense buffer. + */ +void * +mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid) +{ + return (void *)(ioc->sense + ((smid - 1) * SCSI_SENSE_BUFFERSIZE)); +} + +/** + * mpt2sas_base_get_sense_buffer_dma - obtain a sense buffer assigned to a mf request + * @ioc: per adapter object + * @smid: system request message index + * + * Returns phys pointer to sense buffer. + */ +dma_addr_t +mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid) +{ + return ioc->sense_dma + ((smid - 1) * SCSI_SENSE_BUFFERSIZE); +} + +/** + * mpt2sas_base_get_reply_virt_addr - obtain reply frames virt address + * @ioc: per adapter object + * @phys_addr: lower 32 physical addr of the reply + * + * Converts 32bit lower physical addr into a virt address. + */ +void * +mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr) +{ + if (!phys_addr) + return NULL; + return ioc->reply + (phys_addr - (u32)ioc->reply_dma); +} + +/** + * mpt2sas_base_get_smid - obtain a free smid + * @ioc: per adapter object + * @cb_idx: callback index + * + * Returns smid (zero is invalid) + */ +u16 +mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx) +{ + unsigned long flags; + struct request_tracker *request; + u16 smid; + + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); + if (list_empty(&ioc->free_list)) { + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); + printk(MPT2SAS_ERR_FMT "%s: smid not available\n", + ioc->name, __func__); + return 0; + } + + request = list_entry(ioc->free_list.next, + struct request_tracker, tracker_list); + request->cb_idx = cb_idx; + smid = request->smid; + list_del(&request->tracker_list); + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); + return smid; +} + + +/** + * mpt2sas_base_free_smid - put smid back on free_list + * @ioc: per adapter object + * @smid: system request message index + * + * Return nothing. + */ +void +mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid) +{ + unsigned long flags; + + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); + ioc->scsi_lookup[smid - 1].cb_idx = 0xFF; + list_add_tail(&ioc->scsi_lookup[smid - 1].tracker_list, + &ioc->free_list); + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); + + /* + * See _wait_for_commands_to_complete() call with regards to this code. + */ + if (ioc->shost_recovery && ioc->pending_io_count) { + if (ioc->pending_io_count == 1) + wake_up(&ioc->reset_wq); + ioc->pending_io_count--; + } +} + +/** + * _base_writeq - 64 bit write to MMIO + * @ioc: per adapter object + * @b: data payload + * @addr: address in MMIO space + * @writeq_lock: spin lock + * + * Glue for handling an atomic 64 bit word to MMIO. This special handling takes + * care of 32 bit environment where its not quarenteed to send the entire word + * in one transfer. + */ +#ifndef writeq +static inline void _base_writeq(__u64 b, volatile void __iomem *addr, + spinlock_t *writeq_lock) +{ + unsigned long flags; + __u64 data_out = cpu_to_le64(b); + + spin_lock_irqsave(writeq_lock, flags); + writel((u32)(data_out), addr); + writel((u32)(data_out >> 32), (addr + 4)); + spin_unlock_irqrestore(writeq_lock, flags); +} +#else +static inline void _base_writeq(__u64 b, volatile void __iomem *addr, + spinlock_t *writeq_lock) +{ + writeq(cpu_to_le64(b), addr); +} +#endif + +/** + * mpt2sas_base_put_smid_scsi_io - send SCSI_IO request to firmware + * @ioc: per adapter object + * @smid: system request message index + * @vf_id: virtual function id + * @handle: device handle + * + * Return nothing. + */ +void +mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id, + u16 handle) +{ + Mpi2RequestDescriptorUnion_t descriptor; + u64 *request = (u64 *)&descriptor; + + + descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO; + descriptor.SCSIIO.VF_ID = vf_id; + descriptor.SCSIIO.SMID = cpu_to_le16(smid); + descriptor.SCSIIO.DevHandle = cpu_to_le16(handle); + descriptor.SCSIIO.LMID = 0; + _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow, + &ioc->scsi_lookup_lock); +} + + +/** + * mpt2sas_base_put_smid_hi_priority - send Task Managment request to firmware + * @ioc: per adapter object + * @smid: system request message index + * @vf_id: virtual function id + * + * Return nothing. + */ +void +mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid, + u8 vf_id) +{ + Mpi2RequestDescriptorUnion_t descriptor; + u64 *request = (u64 *)&descriptor; + + descriptor.HighPriority.RequestFlags = + MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; + descriptor.HighPriority.VF_ID = vf_id; + descriptor.HighPriority.SMID = cpu_to_le16(smid); + descriptor.HighPriority.LMID = 0; + descriptor.HighPriority.Reserved1 = 0; + _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow, + &ioc->scsi_lookup_lock); +} + +/** + * mpt2sas_base_put_smid_default - Default, primarily used for config pages + * @ioc: per adapter object + * @smid: system request message index + * @vf_id: virtual function id + * + * Return nothing. + */ +void +mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id) +{ + Mpi2RequestDescriptorUnion_t descriptor; + u64 *request = (u64 *)&descriptor; + + descriptor.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; + descriptor.Default.VF_ID = vf_id; + descriptor.Default.SMID = cpu_to_le16(smid); + descriptor.Default.LMID = 0; + descriptor.Default.DescriptorTypeDependent = 0; + _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow, + &ioc->scsi_lookup_lock); +} + +/** + * mpt2sas_base_put_smid_target_assist - send Target Assist/Status to firmware + * @ioc: per adapter object + * @smid: system request message index + * @vf_id: virtual function id + * @io_index: value used to track the IO + * + * Return nothing. + */ +void +mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid, + u8 vf_id, u16 io_index) +{ + Mpi2RequestDescriptorUnion_t descriptor; + u64 *request = (u64 *)&descriptor; + + descriptor.SCSITarget.RequestFlags = + MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET; + descriptor.SCSITarget.VF_ID = vf_id; + descriptor.SCSITarget.SMID = cpu_to_le16(smid); + descriptor.SCSITarget.LMID = 0; + descriptor.SCSITarget.IoIndex = cpu_to_le16(io_index); + _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow, + &ioc->scsi_lookup_lock); +} + +/** + * _base_display_ioc_capabilities - Disply IOC's capabilities. + * @ioc: per adapter object + * + * Return nothing. + */ +static void +_base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc) +{ + int i = 0; + char desc[16]; + u8 revision; + u32 iounit_pg1_flags; + + pci_read_config_byte(ioc->pdev, PCI_CLASS_REVISION, &revision); + strncpy(desc, ioc->manu_pg0.ChipName, 16); + printk(MPT2SAS_INFO_FMT "%s: FWVersion(%02d.%02d.%02d.%02d), " + "ChipRevision(0x%02x), BiosVersion(%02d.%02d.%02d.%02d)\n", + ioc->name, desc, + (ioc->facts.FWVersion.Word & 0xFF000000) >> 24, + (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16, + (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8, + ioc->facts.FWVersion.Word & 0x000000FF, + revision, + (ioc->bios_pg3.BiosVersion & 0xFF000000) >> 24, + (ioc->bios_pg3.BiosVersion & 0x00FF0000) >> 16, + (ioc->bios_pg3.BiosVersion & 0x0000FF00) >> 8, + ioc->bios_pg3.BiosVersion & 0x000000FF); + + printk(MPT2SAS_INFO_FMT "Protocol=(", ioc->name); + + if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR) { + printk("Initiator"); + i++; + } + + if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET) { + printk("%sTarget", i ? "," : ""); + i++; + } + + i = 0; + printk("), "); + printk("Capabilities=("); + + if (ioc->facts.IOCCapabilities & + MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) { + printk("Raid"); + i++; + } + + if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR) { + printk("%sTLR", i ? "," : ""); + i++; + } + + if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_MULTICAST) { + printk("%sMulticast", i ? "," : ""); + i++; + } + + if (ioc->facts.IOCCapabilities & + MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET) { + printk("%sBIDI Target", i ? "," : ""); + i++; + } + + if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_EEDP) { + printk("%sEEDP", i ? "," : ""); + i++; + } + + if (ioc->facts.IOCCapabilities & + MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) { + printk("%sSnapshot Buffer", i ? "," : ""); + i++; + } + + if (ioc->facts.IOCCapabilities & + MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) { + printk("%sDiag Trace Buffer", i ? "," : ""); + i++; + } + + if (ioc->facts.IOCCapabilities & + MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING) { + printk("%sTask Set Full", i ? "," : ""); + i++; + } + + iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags); + if (!(iounit_pg1_flags & MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE)) { + printk("%sNCQ", i ? "," : ""); + i++; + } + + printk(")\n"); +} + +/** + * _base_static_config_pages - static start of day config pages + * @ioc: per adapter object + * + * Return nothing. + */ +static void +_base_static_config_pages(struct MPT2SAS_ADAPTER *ioc) +{ + Mpi2ConfigReply_t mpi_reply; + u32 iounit_pg1_flags; + + mpt2sas_config_get_manufacturing_pg0(ioc, &mpi_reply, &ioc->manu_pg0); + mpt2sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2); + mpt2sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3); + mpt2sas_config_get_ioc_pg8(ioc, &mpi_reply, &ioc->ioc_pg8); + mpt2sas_config_get_iounit_pg0(ioc, &mpi_reply, &ioc->iounit_pg0); + mpt2sas_config_get_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1); + _base_display_ioc_capabilities(ioc); + + /* + * Enable task_set_full handling in iounit_pg1 when the + * facts capabilities indicate that its supported. + */ + iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags); + if ((ioc->facts.IOCCapabilities & + MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING)) + iounit_pg1_flags &= + ~MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING; + else + iounit_pg1_flags |= + MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING; + ioc->iounit_pg1.Flags = cpu_to_le32(iounit_pg1_flags); + mpt2sas_config_set_iounit_pg1(ioc, &mpi_reply, ioc->iounit_pg1); +} + +/** + * _base_release_memory_pools - release memory + * @ioc: per adapter object + * + * Free memory allocated from _base_allocate_memory_pools. + * + * Return nothing. + */ +static void +_base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc) +{ + dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + __func__)); + + if (ioc->request) { + pci_free_consistent(ioc->pdev, ioc->request_dma_sz, + ioc->request, ioc->request_dma); + dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "request_pool(0x%p)" + ": free\n", ioc->name, ioc->request)); + ioc->request = NULL; + } + + if (ioc->sense) { + pci_pool_free(ioc->sense_dma_pool, ioc->sense, ioc->sense_dma); + if (ioc->sense_dma_pool) + pci_pool_destroy(ioc->sense_dma_pool); + dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "sense_pool(0x%p)" + ": free\n", ioc->name, ioc->sense)); + ioc->sense = NULL; + } + + if (ioc->reply) { + pci_pool_free(ioc->reply_dma_pool, ioc->reply, ioc->reply_dma); + if (ioc->reply_dma_pool) + pci_pool_destroy(ioc->reply_dma_pool); + dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_pool(0x%p)" + ": free\n", ioc->name, ioc->reply)); + ioc->reply = NULL; + } + + if (ioc->reply_free) { + pci_pool_free(ioc->reply_free_dma_pool, ioc->reply_free, + ioc->reply_free_dma); + if (ioc->reply_free_dma_pool) + pci_pool_destroy(ioc->reply_free_dma_pool); + dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free_pool" + "(0x%p): free\n", ioc->name, ioc->reply_free)); + ioc->reply_free = NULL; + } + + if (ioc->reply_post_free) { + pci_pool_free(ioc->reply_post_free_dma_pool, + ioc->reply_post_free, ioc->reply_post_free_dma); + if (ioc->reply_post_free_dma_pool) + pci_pool_destroy(ioc->reply_post_free_dma_pool); + dexitprintk(ioc, printk(MPT2SAS_INFO_FMT + "reply_post_free_pool(0x%p): free\n", ioc->name, + ioc->reply_post_free)); + ioc->reply_post_free = NULL; + } + + if (ioc->config_page) { + dexitprintk(ioc, printk(MPT2SAS_INFO_FMT + "config_page(0x%p): free\n", ioc->name, + ioc->config_page)); + pci_free_consistent(ioc->pdev, ioc->config_page_sz, + ioc->config_page, ioc->config_page_dma); + } + + kfree(ioc->scsi_lookup); +} + + +/** + * _base_allocate_memory_pools - allocate start of day memory pools + * @ioc: per adapter object + * @sleep_flag: CAN_SLEEP or NO_SLEEP + * + * Returns 0 success, anything else error + */ +static int +_base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) +{ + Mpi2IOCFactsReply_t *facts; + u32 queue_size, queue_diff; + u16 max_sge_elements; + u16 num_of_reply_frames; + u16 chains_needed_per_io; + u32 sz, total_sz; + u16 i; + u32 retry_sz; + u16 max_request_credit; + + dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + __func__)); + + retry_sz = 0; + facts = &ioc->facts; + + /* command line tunables for max sgl entries */ + if (max_sgl_entries != -1) { + ioc->shost->sg_tablesize = (max_sgl_entries < + MPT2SAS_SG_DEPTH) ? max_sgl_entries : + MPT2SAS_SG_DEPTH; + } else { + ioc->shost->sg_tablesize = MPT2SAS_SG_DEPTH; + } + + /* command line tunables for max controller queue depth */ + if (max_queue_depth != -1) { + max_request_credit = (max_queue_depth < facts->RequestCredit) + ? max_queue_depth : facts->RequestCredit; + } else { + max_request_credit = (facts->RequestCredit > + MPT2SAS_MAX_REQUEST_QUEUE) ? MPT2SAS_MAX_REQUEST_QUEUE : + facts->RequestCredit; + } + ioc->request_depth = max_request_credit; + + /* request frame size */ + ioc->request_sz = facts->IOCRequestFrameSize * 4; + + /* reply frame size */ + ioc->reply_sz = facts->ReplyFrameSize * 4; + + retry_allocation: + total_sz = 0; + /* calculate number of sg elements left over in the 1st frame */ + max_sge_elements = ioc->request_sz - ((sizeof(Mpi2SCSIIORequest_t) - + sizeof(Mpi2SGEIOUnion_t)) + ioc->sge_size); + ioc->max_sges_in_main_message = max_sge_elements/ioc->sge_size; + + /* now do the same for a chain buffer */ + max_sge_elements = ioc->request_sz - ioc->sge_size; + ioc->max_sges_in_chain_message = max_sge_elements/ioc->sge_size; + + ioc->chain_offset_value_for_main_message = + ((sizeof(Mpi2SCSIIORequest_t) - sizeof(Mpi2SGEIOUnion_t)) + + (ioc->max_sges_in_chain_message * ioc->sge_size)) / 4; + + /* + * MPT2SAS_SG_DEPTH = CONFIG_FUSION_MAX_SGE + */ + chains_needed_per_io = ((ioc->shost->sg_tablesize - + ioc->max_sges_in_main_message)/ioc->max_sges_in_chain_message) + + 1; + if (chains_needed_per_io > facts->MaxChainDepth) { + chains_needed_per_io = facts->MaxChainDepth; + ioc->shost->sg_tablesize = min_t(u16, + ioc->max_sges_in_main_message + (ioc->max_sges_in_chain_message + * chains_needed_per_io), ioc->shost->sg_tablesize); + } + ioc->chains_needed_per_io = chains_needed_per_io; + + /* reply free queue sizing - taking into account for events */ + num_of_reply_frames = ioc->request_depth + 32; + + /* number of replies frames can't be a multiple of 16 */ + /* decrease number of reply frames by 1 */ + if (!(num_of_reply_frames % 16)) + num_of_reply_frames--; + + /* calculate number of reply free queue entries + * (must be multiple of 16) + */ + + /* (we know reply_free_queue_depth is not a multiple of 16) */ + queue_size = num_of_reply_frames; + queue_size += 16 - (queue_size % 16); + ioc->reply_free_queue_depth = queue_size; + + /* reply descriptor post queue sizing */ + /* this size should be the number of request frames + number of reply + * frames + */ + + queue_size = ioc->request_depth + num_of_reply_frames + 1; + /* round up to 16 byte boundary */ + if (queue_size % 16) + queue_size += 16 - (queue_size % 16); + + /* check against IOC maximum reply post queue depth */ + if (queue_size > facts->MaxReplyDescriptorPostQueueDepth) { + queue_diff = queue_size - + facts->MaxReplyDescriptorPostQueueDepth; + + /* round queue_diff up to multiple of 16 */ + if (queue_diff % 16) + queue_diff += 16 - (queue_diff % 16); + + /* adjust request_depth, reply_free_queue_depth, + * and queue_size + */ + ioc->request_depth -= queue_diff; + ioc->reply_free_queue_depth -= queue_diff; + queue_size -= queue_diff; + } + ioc->reply_post_queue_depth = queue_size; + + /* max scsi host queue depth */ + ioc->shost->can_queue = ioc->request_depth - INTERNAL_CMDS_COUNT; + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsi host queue: depth" + "(%d)\n", ioc->name, ioc->shost->can_queue)); + + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scatter gather: " + "sge_in_main_msg(%d), sge_per_chain(%d), sge_per_io(%d), " + "chains_per_io(%d)\n", ioc->name, ioc->max_sges_in_main_message, + ioc->max_sges_in_chain_message, ioc->shost->sg_tablesize, + ioc->chains_needed_per_io)); + + /* contiguous pool for request and chains, 16 byte align, one extra " + * "frame for smid=0 + */ + ioc->chain_depth = ioc->chains_needed_per_io * ioc->request_depth; + sz = ((ioc->request_depth + 1 + ioc->chain_depth) * ioc->request_sz); + + ioc->request_dma_sz = sz; + ioc->request = pci_alloc_consistent(ioc->pdev, sz, &ioc->request_dma); + if (!ioc->request) { + printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent " + "failed: req_depth(%d), chains_per_io(%d), frame_sz(%d), " + "total(%d kB)\n", ioc->name, ioc->request_depth, + ioc->chains_needed_per_io, ioc->request_sz, sz/1024); + if (ioc->request_depth < MPT2SAS_SAS_QUEUE_DEPTH) + goto out; + retry_sz += 64; + ioc->request_depth = max_request_credit - retry_sz; + goto retry_allocation; + } + + if (retry_sz) + printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent " + "succeed: req_depth(%d), chains_per_io(%d), frame_sz(%d), " + "total(%d kb)\n", ioc->name, ioc->request_depth, + ioc->chains_needed_per_io, ioc->request_sz, sz/1024); + + ioc->chain = ioc->request + ((ioc->request_depth + 1) * + ioc->request_sz); + ioc->chain_dma = ioc->request_dma + ((ioc->request_depth + 1) * + ioc->request_sz); + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool(0x%p): " + "depth(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, + ioc->request, ioc->request_depth, ioc->request_sz, + ((ioc->request_depth + 1) * ioc->request_sz)/1024)); + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "chain pool(0x%p): depth" + "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->chain, + ioc->chain_depth, ioc->request_sz, ((ioc->chain_depth * + ioc->request_sz))/1024)); + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool: dma(0x%llx)\n", + ioc->name, (unsigned long long) ioc->request_dma)); + total_sz += sz; + + ioc->scsi_lookup = kcalloc(ioc->request_depth, + sizeof(struct request_tracker), GFP_KERNEL); + if (!ioc->scsi_lookup) { + printk(MPT2SAS_ERR_FMT "scsi_lookup: kcalloc failed\n", + ioc->name); + goto out; + } + + /* initialize some bits */ + for (i = 0; i < ioc->request_depth; i++) + ioc->scsi_lookup[i].smid = i + 1; + + /* sense buffers, 4 byte align */ + sz = ioc->request_depth * SCSI_SENSE_BUFFERSIZE; + ioc->sense_dma_pool = pci_pool_create("sense pool", ioc->pdev, sz, 4, + 0); + if (!ioc->sense_dma_pool) { + printk(MPT2SAS_ERR_FMT "sense pool: pci_pool_create failed\n", + ioc->name); + goto out; + } + ioc->sense = pci_pool_alloc(ioc->sense_dma_pool , GFP_KERNEL, + &ioc->sense_dma); + if (!ioc->sense) { + printk(MPT2SAS_ERR_FMT "sense pool: pci_pool_alloc failed\n", + ioc->name); + goto out; + } + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT + "sense pool(0x%p): depth(%d), element_size(%d), pool_size" + "(%d kB)\n", ioc->name, ioc->sense, ioc->request_depth, + SCSI_SENSE_BUFFERSIZE, sz/1024)); + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "sense_dma(0x%llx)\n", + ioc->name, (unsigned long long)ioc->sense_dma)); + total_sz += sz; + + /* reply pool, 4 byte align */ + sz = ioc->reply_free_queue_depth * ioc->reply_sz; + ioc->reply_dma_pool = pci_pool_create("reply pool", ioc->pdev, sz, 4, + 0); + if (!ioc->reply_dma_pool) { + printk(MPT2SAS_ERR_FMT "reply pool: pci_pool_create failed\n", + ioc->name); + goto out; + } + ioc->reply = pci_pool_alloc(ioc->reply_dma_pool , GFP_KERNEL, + &ioc->reply_dma); + if (!ioc->reply) { + printk(MPT2SAS_ERR_FMT "reply pool: pci_pool_alloc failed\n", + ioc->name); + goto out; + } + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply pool(0x%p): depth" + "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->reply, + ioc->reply_free_queue_depth, ioc->reply_sz, sz/1024)); + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_dma(0x%llx)\n", + ioc->name, (unsigned long long)ioc->reply_dma)); + total_sz += sz; + + /* reply free queue, 16 byte align */ + sz = ioc->reply_free_queue_depth * 4; + ioc->reply_free_dma_pool = pci_pool_create("reply_free pool", + ioc->pdev, sz, 16, 0); + if (!ioc->reply_free_dma_pool) { + printk(MPT2SAS_ERR_FMT "reply_free pool: pci_pool_create " + "failed\n", ioc->name); + goto out; + } + ioc->reply_free = pci_pool_alloc(ioc->reply_free_dma_pool , GFP_KERNEL, + &ioc->reply_free_dma); + if (!ioc->reply_free) { + printk(MPT2SAS_ERR_FMT "reply_free pool: pci_pool_alloc " + "failed\n", ioc->name); + goto out; + } + memset(ioc->reply_free, 0, sz); + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free pool(0x%p): " + "depth(%d), element_size(%d), pool_size(%d kB)\n", ioc->name, + ioc->reply_free, ioc->reply_free_queue_depth, 4, sz/1024)); + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free_dma" + "(0x%llx)\n", ioc->name, (unsigned long long)ioc->reply_free_dma)); + total_sz += sz; + + /* reply post queue, 16 byte align */ + sz = ioc->reply_post_queue_depth * sizeof(Mpi2DefaultReplyDescriptor_t); + ioc->reply_post_free_dma_pool = pci_pool_create("reply_post_free pool", + ioc->pdev, sz, 16, 0); + if (!ioc->reply_post_free_dma_pool) { + printk(MPT2SAS_ERR_FMT "reply_post_free pool: pci_pool_create " + "failed\n", ioc->name); + goto out; + } + ioc->reply_post_free = pci_pool_alloc(ioc->reply_post_free_dma_pool , + GFP_KERNEL, &ioc->reply_post_free_dma); + if (!ioc->reply_post_free) { + printk(MPT2SAS_ERR_FMT "reply_post_free pool: pci_pool_alloc " + "failed\n", ioc->name); + goto out; + } + memset(ioc->reply_post_free, 0, sz); + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply post free pool" + "(0x%p): depth(%d), element_size(%d), pool_size(%d kB)\n", + ioc->name, ioc->reply_post_free, ioc->reply_post_queue_depth, 8, + sz/1024)); + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_post_free_dma = " + "(0x%llx)\n", ioc->name, (unsigned long long) + ioc->reply_post_free_dma)); + total_sz += sz; + + ioc->config_page_sz = 512; + ioc->config_page = pci_alloc_consistent(ioc->pdev, + ioc->config_page_sz, &ioc->config_page_dma); + if (!ioc->config_page) { + printk(MPT2SAS_ERR_FMT "config page: pci_pool_alloc " + "failed\n", ioc->name); + goto out; + } + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "config page(0x%p): size" + "(%d)\n", ioc->name, ioc->config_page, ioc->config_page_sz)); + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "config_page_dma" + "(0x%llx)\n", ioc->name, (unsigned long long)ioc->config_page_dma)); + total_sz += ioc->config_page_sz; + + printk(MPT2SAS_INFO_FMT "Allocated physical memory: size(%d kB)\n", + ioc->name, total_sz/1024); + printk(MPT2SAS_INFO_FMT "Current Controller Queue Depth(%d), " + "Max Controller Queue Depth(%d)\n", + ioc->name, ioc->shost->can_queue, facts->RequestCredit); + printk(MPT2SAS_INFO_FMT "Scatter Gather Elements per IO(%d)\n", + ioc->name, ioc->shost->sg_tablesize); + return 0; + + out: + _base_release_memory_pools(ioc); + return -ENOMEM; +} + + +/** + * mpt2sas_base_get_iocstate - Get the current state of a MPT adapter. + * @ioc: Pointer to MPT_ADAPTER structure + * @cooked: Request raw or cooked IOC state + * + * Returns all IOC Doorbell register bits if cooked==0, else just the + * Doorbell bits in MPI_IOC_STATE_MASK. + */ +u32 +mpt2sas_base_get_iocstate(struct MPT2SAS_ADAPTER *ioc, int cooked) +{ + u32 s, sc; + + s = readl(&ioc->chip->Doorbell); + sc = s & MPI2_IOC_STATE_MASK; + return cooked ? sc : s; +} + +/** + * _base_wait_on_iocstate - waiting on a particular ioc state + * @ioc_state: controller state { READY, OPERATIONAL, or RESET } + * @timeout: timeout in second + * @sleep_flag: CAN_SLEEP or NO_SLEEP + * + * Returns 0 for success, non-zero for failure. + */ +static int +_base_wait_on_iocstate(struct MPT2SAS_ADAPTER *ioc, u32 ioc_state, int timeout, + int sleep_flag) +{ + u32 count, cntdn; + u32 current_state; + + count = 0; + cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; + do { + current_state = mpt2sas_base_get_iocstate(ioc, 1); + if (current_state == ioc_state) + return 0; + if (count && current_state == MPI2_IOC_STATE_FAULT) + break; + if (sleep_flag == CAN_SLEEP) + msleep(1); + else + udelay(500); + count++; + } while (--cntdn); + + return current_state; +} + +/** + * _base_wait_for_doorbell_int - waiting for controller interrupt(generated by + * a write to the doorbell) + * @ioc: per adapter object + * @timeout: timeout in second + * @sleep_flag: CAN_SLEEP or NO_SLEEP + * + * Returns 0 for success, non-zero for failure. + * + * Notes: MPI2_HIS_IOC2SYS_DB_STATUS - set to one when IOC writes to doorbell. + */ +static int +_base_wait_for_doorbell_int(struct MPT2SAS_ADAPTER *ioc, int timeout, + int sleep_flag) +{ + u32 cntdn, count; + u32 int_status; + + count = 0; + cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; + do { + int_status = readl(&ioc->chip->HostInterruptStatus); + if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) { + dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + "successfull count(%d), timeout(%d)\n", ioc->name, + __func__, count, timeout)); + return 0; + } + if (sleep_flag == CAN_SLEEP) + msleep(1); + else + udelay(500); + count++; + } while (--cntdn); + + printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), " + "int_status(%x)!\n", ioc->name, __func__, count, int_status); + return -EFAULT; +} + +/** + * _base_wait_for_doorbell_ack - waiting for controller to read the doorbell. + * @ioc: per adapter object + * @timeout: timeout in second + * @sleep_flag: CAN_SLEEP or NO_SLEEP + * + * Returns 0 for success, non-zero for failure. + * + * Notes: MPI2_HIS_SYS2IOC_DB_STATUS - set to one when host writes to + * doorbell. + */ +static int +_base_wait_for_doorbell_ack(struct MPT2SAS_ADAPTER *ioc, int timeout, + int sleep_flag) +{ + u32 cntdn, count; + u32 int_status; + u32 doorbell; + + count = 0; + cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; + do { + int_status = readl(&ioc->chip->HostInterruptStatus); + if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) { + dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + "successfull count(%d), timeout(%d)\n", ioc->name, + __func__, count, timeout)); + return 0; + } else if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) { + doorbell = readl(&ioc->chip->Doorbell); + if ((doorbell & MPI2_IOC_STATE_MASK) == + MPI2_IOC_STATE_FAULT) { + mpt2sas_base_fault_info(ioc , doorbell); + return -EFAULT; + } + } else if (int_status == 0xFFFFFFFF) + goto out; + + if (sleep_flag == CAN_SLEEP) + msleep(1); + else + udelay(500); + count++; + } while (--cntdn); + + out: + printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), " + "int_status(%x)!\n", ioc->name, __func__, count, int_status); + return -EFAULT; +} + +/** + * _base_wait_for_doorbell_not_used - waiting for doorbell to not be in use + * @ioc: per adapter object + * @timeout: timeout in second + * @sleep_flag: CAN_SLEEP or NO_SLEEP + * + * Returns 0 for success, non-zero for failure. + * + */ +static int +_base_wait_for_doorbell_not_used(struct MPT2SAS_ADAPTER *ioc, int timeout, + int sleep_flag) +{ + u32 cntdn, count; + u32 doorbell_reg; + + count = 0; + cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; + do { + doorbell_reg = readl(&ioc->chip->Doorbell); + if (!(doorbell_reg & MPI2_DOORBELL_USED)) { + dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + "successfull count(%d), timeout(%d)\n", ioc->name, + __func__, count, timeout)); + return 0; + } + if (sleep_flag == CAN_SLEEP) + msleep(1); + else + udelay(500); + count++; + } while (--cntdn); + + printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), " + "doorbell_reg(%x)!\n", ioc->name, __func__, count, doorbell_reg); + return -EFAULT; +} + +/** + * _base_send_ioc_reset - send doorbell reset + * @ioc: per adapter object + * @reset_type: currently only supports: MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET + * @timeout: timeout in second + * @sleep_flag: CAN_SLEEP or NO_SLEEP + * + * Returns 0 for success, non-zero for failure. + */ +static int +_base_send_ioc_reset(struct MPT2SAS_ADAPTER *ioc, u8 reset_type, int timeout, + int sleep_flag) +{ + u32 ioc_state; + int r = 0; + + if (reset_type != MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET) { + printk(MPT2SAS_ERR_FMT "%s: unknown reset_type\n", + ioc->name, __func__); + return -EFAULT; + } + + if (!(ioc->facts.IOCCapabilities & + MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY)) + return -EFAULT; + + printk(MPT2SAS_INFO_FMT "sending message unit reset !!\n", ioc->name); + + writel(reset_type << MPI2_DOORBELL_FUNCTION_SHIFT, + &ioc->chip->Doorbell); + if ((_base_wait_for_doorbell_ack(ioc, 15, sleep_flag))) { + r = -EFAULT; + goto out; + } + ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, + timeout, sleep_flag); + if (ioc_state) { + printk(MPT2SAS_ERR_FMT "%s: failed going to ready state " + " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state); + r = -EFAULT; + goto out; + } + out: + printk(MPT2SAS_INFO_FMT "message unit reset: %s\n", + ioc->name, ((r == 0) ? "SUCCESS" : "FAILED")); + return r; +} + +/** + * _base_handshake_req_reply_wait - send request thru doorbell interface + * @ioc: per adapter object + * @request_bytes: request length + * @request: pointer having request payload + * @reply_bytes: reply length + * @reply: pointer to reply payload + * @timeout: timeout in second + * @sleep_flag: CAN_SLEEP or NO_SLEEP + * + * Returns 0 for success, non-zero for failure. + */ +static int +_base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes, + u32 *request, int reply_bytes, u16 *reply, int timeout, int sleep_flag) +{ + MPI2DefaultReply_t *default_reply = (MPI2DefaultReply_t *)reply; + int i; + u8 failed; + u16 dummy; + u32 *mfp; + + /* make sure doorbell is not in use */ + if ((readl(&ioc->chip->Doorbell) & MPI2_DOORBELL_USED)) { + printk(MPT2SAS_ERR_FMT "doorbell is in use " + " (line=%d)\n", ioc->name, __LINE__); + return -EFAULT; + } + + /* clear pending doorbell interrupts from previous state changes */ + if (readl(&ioc->chip->HostInterruptStatus) & + MPI2_HIS_IOC2SYS_DB_STATUS) + writel(0, &ioc->chip->HostInterruptStatus); + + /* send message to ioc */ + writel(((MPI2_FUNCTION_HANDSHAKE<chip->Doorbell); + + if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) { + printk(MPT2SAS_ERR_FMT "doorbell handshake " + "int failed (line=%d)\n", ioc->name, __LINE__); + return -EFAULT; + } + writel(0, &ioc->chip->HostInterruptStatus); + + if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag))) { + printk(MPT2SAS_ERR_FMT "doorbell handshake " + "ack failed (line=%d)\n", ioc->name, __LINE__); + return -EFAULT; + } + + /* send message 32-bits at a time */ + for (i = 0, failed = 0; i < request_bytes/4 && !failed; i++) { + writel(cpu_to_le32(request[i]), &ioc->chip->Doorbell); + if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag))) + failed = 1; + } + + if (failed) { + printk(MPT2SAS_ERR_FMT "doorbell handshake " + "sending request failed (line=%d)\n", ioc->name, __LINE__); + return -EFAULT; + } + + /* now wait for the reply */ + if ((_base_wait_for_doorbell_int(ioc, timeout, sleep_flag))) { + printk(MPT2SAS_ERR_FMT "doorbell handshake " + "int failed (line=%d)\n", ioc->name, __LINE__); + return -EFAULT; + } + + /* read the first two 16-bits, it gives the total length of the reply */ + reply[0] = le16_to_cpu(readl(&ioc->chip->Doorbell) + & MPI2_DOORBELL_DATA_MASK); + writel(0, &ioc->chip->HostInterruptStatus); + if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) { + printk(MPT2SAS_ERR_FMT "doorbell handshake " + "int failed (line=%d)\n", ioc->name, __LINE__); + return -EFAULT; + } + reply[1] = le16_to_cpu(readl(&ioc->chip->Doorbell) + & MPI2_DOORBELL_DATA_MASK); + writel(0, &ioc->chip->HostInterruptStatus); + + for (i = 2; i < default_reply->MsgLength * 2; i++) { + if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) { + printk(MPT2SAS_ERR_FMT "doorbell " + "handshake int failed (line=%d)\n", ioc->name, + __LINE__); + return -EFAULT; + } + if (i >= reply_bytes/2) /* overflow case */ + dummy = readl(&ioc->chip->Doorbell); + else + reply[i] = le16_to_cpu(readl(&ioc->chip->Doorbell) + & MPI2_DOORBELL_DATA_MASK); + writel(0, &ioc->chip->HostInterruptStatus); + } + + _base_wait_for_doorbell_int(ioc, 5, sleep_flag); + if (_base_wait_for_doorbell_not_used(ioc, 5, sleep_flag) != 0) { + dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "doorbell is in use " + " (line=%d)\n", ioc->name, __LINE__)); + } + writel(0, &ioc->chip->HostInterruptStatus); + + if (ioc->logging_level & MPT_DEBUG_INIT) { + mfp = (u32 *)reply; + printk(KERN_DEBUG "\toffset:data\n"); + for (i = 0; i < reply_bytes/4; i++) + printk(KERN_DEBUG "\t[0x%02x]:%08x\n", i*4, + le32_to_cpu(mfp[i])); + } + return 0; +} + +/** + * mpt2sas_base_sas_iounit_control - send sas iounit control to FW + * @ioc: per adapter object + * @mpi_reply: the reply payload from FW + * @mpi_request: the request payload sent to FW + * + * The SAS IO Unit Control Request message allows the host to perform low-level + * operations, such as resets on the PHYs of the IO Unit, also allows the host + * to obtain the IOC assigned device handles for a device if it has other + * identifying information about the device, in addition allows the host to + * remove IOC resources associated with the device. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_base_sas_iounit_control(struct MPT2SAS_ADAPTER *ioc, + Mpi2SasIoUnitControlReply_t *mpi_reply, + Mpi2SasIoUnitControlRequest_t *mpi_request) +{ + u16 smid; + u32 ioc_state; + unsigned long timeleft; + u8 issue_reset; + int rc; + void *request; + u16 wait_state_count; + + dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + __func__)); + + mutex_lock(&ioc->base_cmds.mutex); + + if (ioc->base_cmds.status != MPT2_CMD_NOT_USED) { + printk(MPT2SAS_ERR_FMT "%s: base_cmd in use\n", + ioc->name, __func__); + rc = -EAGAIN; + goto out; + } + + wait_state_count = 0; + ioc_state = mpt2sas_base_get_iocstate(ioc, 1); + while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { + if (wait_state_count++ == 10) { + printk(MPT2SAS_ERR_FMT + "%s: failed due to ioc not operational\n", + ioc->name, __func__); + rc = -EFAULT; + goto out; + } + ssleep(1); + ioc_state = mpt2sas_base_get_iocstate(ioc, 1); + printk(MPT2SAS_INFO_FMT "%s: waiting for " + "operational state(count=%d)\n", ioc->name, + __func__, wait_state_count); + } + + smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx); + if (!smid) { + printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", + ioc->name, __func__); + rc = -EAGAIN; + goto out; + } + + rc = 0; + ioc->base_cmds.status = MPT2_CMD_PENDING; + request = mpt2sas_base_get_msg_frame(ioc, smid); + ioc->base_cmds.smid = smid; + memcpy(request, mpi_request, sizeof(Mpi2SasIoUnitControlRequest_t)); + if (mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || + mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) + ioc->ioc_link_reset_in_progress = 1; + mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); + timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, + msecs_to_jiffies(10000)); + if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || + mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) && + ioc->ioc_link_reset_in_progress) + ioc->ioc_link_reset_in_progress = 0; + if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { + printk(MPT2SAS_ERR_FMT "%s: timeout\n", + ioc->name, __func__); + _debug_dump_mf(mpi_request, + sizeof(Mpi2SasIoUnitControlRequest_t)/4); + if (!(ioc->base_cmds.status & MPT2_CMD_RESET)) + issue_reset = 1; + goto issue_host_reset; + } + if (ioc->base_cmds.status & MPT2_CMD_REPLY_VALID) + memcpy(mpi_reply, ioc->base_cmds.reply, + sizeof(Mpi2SasIoUnitControlReply_t)); + else + memset(mpi_reply, 0, sizeof(Mpi2SasIoUnitControlReply_t)); + ioc->base_cmds.status = MPT2_CMD_NOT_USED; + goto out; + + issue_host_reset: + if (issue_reset) + mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, + FORCE_BIG_HAMMER); + ioc->base_cmds.status = MPT2_CMD_NOT_USED; + rc = -EFAULT; + out: + mutex_unlock(&ioc->base_cmds.mutex); + return rc; +} + + +/** + * mpt2sas_base_scsi_enclosure_processor - sending request to sep device + * @ioc: per adapter object + * @mpi_reply: the reply payload from FW + * @mpi_request: the request payload sent to FW + * + * The SCSI Enclosure Processor request message causes the IOC to + * communicate with SES devices to control LED status signals. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc, + Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request) +{ + u16 smid; + u32 ioc_state; + unsigned long timeleft; + u8 issue_reset; + int rc; + void *request; + u16 wait_state_count; + + dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + __func__)); + + mutex_lock(&ioc->base_cmds.mutex); + + if (ioc->base_cmds.status != MPT2_CMD_NOT_USED) { + printk(MPT2SAS_ERR_FMT "%s: base_cmd in use\n", + ioc->name, __func__); + rc = -EAGAIN; + goto out; + } + + wait_state_count = 0; + ioc_state = mpt2sas_base_get_iocstate(ioc, 1); + while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { + if (wait_state_count++ == 10) { + printk(MPT2SAS_ERR_FMT + "%s: failed due to ioc not operational\n", + ioc->name, __func__); + rc = -EFAULT; + goto out; + } + ssleep(1); + ioc_state = mpt2sas_base_get_iocstate(ioc, 1); + printk(MPT2SAS_INFO_FMT "%s: waiting for " + "operational state(count=%d)\n", ioc->name, + __func__, wait_state_count); + } + + smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx); + if (!smid) { + printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", + ioc->name, __func__); + rc = -EAGAIN; + goto out; + } + + rc = 0; + ioc->base_cmds.status = MPT2_CMD_PENDING; + request = mpt2sas_base_get_msg_frame(ioc, smid); + ioc->base_cmds.smid = smid; + memcpy(request, mpi_request, sizeof(Mpi2SepReply_t)); + mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); + timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, + msecs_to_jiffies(10000)); + if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { + printk(MPT2SAS_ERR_FMT "%s: timeout\n", + ioc->name, __func__); + _debug_dump_mf(mpi_request, + sizeof(Mpi2SepRequest_t)/4); + if (!(ioc->base_cmds.status & MPT2_CMD_RESET)) + issue_reset = 1; + goto issue_host_reset; + } + if (ioc->base_cmds.status & MPT2_CMD_REPLY_VALID) + memcpy(mpi_reply, ioc->base_cmds.reply, + sizeof(Mpi2SepReply_t)); + else + memset(mpi_reply, 0, sizeof(Mpi2SepReply_t)); + ioc->base_cmds.status = MPT2_CMD_NOT_USED; + goto out; + + issue_host_reset: + if (issue_reset) + mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, + FORCE_BIG_HAMMER); + ioc->base_cmds.status = MPT2_CMD_NOT_USED; + rc = -EFAULT; + out: + mutex_unlock(&ioc->base_cmds.mutex); + return rc; +} + +/** + * _base_get_port_facts - obtain port facts reply and save in ioc + * @ioc: per adapter object + * @sleep_flag: CAN_SLEEP or NO_SLEEP + * + * Returns 0 for success, non-zero for failure. + */ +static int +_base_get_port_facts(struct MPT2SAS_ADAPTER *ioc, int port, int sleep_flag) +{ + Mpi2PortFactsRequest_t mpi_request; + Mpi2PortFactsReply_t mpi_reply, *pfacts; + int mpi_reply_sz, mpi_request_sz, r; + + dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + __func__)); + + mpi_reply_sz = sizeof(Mpi2PortFactsReply_t); + mpi_request_sz = sizeof(Mpi2PortFactsRequest_t); + memset(&mpi_request, 0, mpi_request_sz); + mpi_request.Function = MPI2_FUNCTION_PORT_FACTS; + mpi_request.PortNumber = port; + r = _base_handshake_req_reply_wait(ioc, mpi_request_sz, + (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP); + + if (r != 0) { + printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n", + ioc->name, __func__, r); + return r; + } + + pfacts = &ioc->pfacts[port]; + memset(pfacts, 0, sizeof(Mpi2PortFactsReply_t)); + pfacts->PortNumber = mpi_reply.PortNumber; + pfacts->VP_ID = mpi_reply.VP_ID; + pfacts->VF_ID = mpi_reply.VF_ID; + pfacts->MaxPostedCmdBuffers = + le16_to_cpu(mpi_reply.MaxPostedCmdBuffers); + + return 0; +} + +/** + * _base_get_ioc_facts - obtain ioc facts reply and save in ioc + * @ioc: per adapter object + * @sleep_flag: CAN_SLEEP or NO_SLEEP + * + * Returns 0 for success, non-zero for failure. + */ +static int +_base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) +{ + Mpi2IOCFactsRequest_t mpi_request; + Mpi2IOCFactsReply_t mpi_reply, *facts; + int mpi_reply_sz, mpi_request_sz, r; + + dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + __func__)); + + mpi_reply_sz = sizeof(Mpi2IOCFactsReply_t); + mpi_request_sz = sizeof(Mpi2IOCFactsRequest_t); + memset(&mpi_request, 0, mpi_request_sz); + mpi_request.Function = MPI2_FUNCTION_IOC_FACTS; + r = _base_handshake_req_reply_wait(ioc, mpi_request_sz, + (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP); + + if (r != 0) { + printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n", + ioc->name, __func__, r); + return r; + } + + facts = &ioc->facts; + memset(facts, 0, sizeof(Mpi2IOCFactsReply_t)); + facts->MsgVersion = le16_to_cpu(mpi_reply.MsgVersion); + facts->HeaderVersion = le16_to_cpu(mpi_reply.HeaderVersion); + facts->VP_ID = mpi_reply.VP_ID; + facts->VF_ID = mpi_reply.VF_ID; + facts->IOCExceptions = le16_to_cpu(mpi_reply.IOCExceptions); + facts->MaxChainDepth = mpi_reply.MaxChainDepth; + facts->WhoInit = mpi_reply.WhoInit; + facts->NumberOfPorts = mpi_reply.NumberOfPorts; + facts->RequestCredit = le16_to_cpu(mpi_reply.RequestCredit); + facts->MaxReplyDescriptorPostQueueDepth = + le16_to_cpu(mpi_reply.MaxReplyDescriptorPostQueueDepth); + facts->ProductID = le16_to_cpu(mpi_reply.ProductID); + facts->IOCCapabilities = le32_to_cpu(mpi_reply.IOCCapabilities); + if ((facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID)) + ioc->ir_firmware = 1; + facts->FWVersion.Word = le32_to_cpu(mpi_reply.FWVersion.Word); + facts->IOCRequestFrameSize = + le16_to_cpu(mpi_reply.IOCRequestFrameSize); + facts->MaxInitiators = le16_to_cpu(mpi_reply.MaxInitiators); + facts->MaxTargets = le16_to_cpu(mpi_reply.MaxTargets); + ioc->shost->max_id = -1; + facts->MaxSasExpanders = le16_to_cpu(mpi_reply.MaxSasExpanders); + facts->MaxEnclosures = le16_to_cpu(mpi_reply.MaxEnclosures); + facts->ProtocolFlags = le16_to_cpu(mpi_reply.ProtocolFlags); + facts->HighPriorityCredit = + le16_to_cpu(mpi_reply.HighPriorityCredit); + facts->ReplyFrameSize = mpi_reply.ReplyFrameSize; + facts->MaxDevHandle = le16_to_cpu(mpi_reply.MaxDevHandle); + + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "hba queue depth(%d), " + "max chains per io(%d)\n", ioc->name, facts->RequestCredit, + facts->MaxChainDepth)); + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request frame size(%d), " + "reply frame size(%d)\n", ioc->name, + facts->IOCRequestFrameSize * 4, facts->ReplyFrameSize * 4)); + return 0; +} + +/** + * _base_send_ioc_init - send ioc_init to firmware + * @ioc: per adapter object + * @VF_ID: virtual function id + * @sleep_flag: CAN_SLEEP or NO_SLEEP + * + * Returns 0 for success, non-zero for failure. + */ +static int +_base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag) +{ + Mpi2IOCInitRequest_t mpi_request; + Mpi2IOCInitReply_t mpi_reply; + int r; + + dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + __func__)); + + memset(&mpi_request, 0, sizeof(Mpi2IOCInitRequest_t)); + mpi_request.Function = MPI2_FUNCTION_IOC_INIT; + mpi_request.WhoInit = MPI2_WHOINIT_HOST_DRIVER; + mpi_request.VF_ID = VF_ID; + mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION); + mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION); + + /* In MPI Revision I (0xA), the SystemReplyFrameSize(offset 0x18) was + * removed and made reserved. For those with older firmware will need + * this fix. It was decided that the Reply and Request frame sizes are + * the same. + */ + if ((ioc->facts.HeaderVersion >> 8) < 0xA) { + mpi_request.Reserved7 = cpu_to_le16(ioc->reply_sz); +/* mpi_request.SystemReplyFrameSize = + * cpu_to_le16(ioc->reply_sz); + */ + } + + mpi_request.SystemRequestFrameSize = cpu_to_le16(ioc->request_sz/4); + mpi_request.ReplyDescriptorPostQueueDepth = + cpu_to_le16(ioc->reply_post_queue_depth); + mpi_request.ReplyFreeQueueDepth = + cpu_to_le16(ioc->reply_free_queue_depth); + +#if BITS_PER_LONG > 32 + mpi_request.SenseBufferAddressHigh = + cpu_to_le32(ioc->sense_dma >> 32); + mpi_request.SystemReplyAddressHigh = + cpu_to_le32(ioc->reply_dma >> 32); + mpi_request.SystemRequestFrameBaseAddress = + cpu_to_le64(ioc->request_dma); + mpi_request.ReplyFreeQueueAddress = + cpu_to_le64(ioc->reply_free_dma); + mpi_request.ReplyDescriptorPostQueueAddress = + cpu_to_le64(ioc->reply_post_free_dma); +#else + mpi_request.SystemRequestFrameBaseAddress = + cpu_to_le32(ioc->request_dma); + mpi_request.ReplyFreeQueueAddress = + cpu_to_le32(ioc->reply_free_dma); + mpi_request.ReplyDescriptorPostQueueAddress = + cpu_to_le32(ioc->reply_post_free_dma); +#endif + + if (ioc->logging_level & MPT_DEBUG_INIT) { + u32 *mfp; + int i; + + mfp = (u32 *)&mpi_request; + printk(KERN_DEBUG "\toffset:data\n"); + for (i = 0; i < sizeof(Mpi2IOCInitRequest_t)/4; i++) + printk(KERN_DEBUG "\t[0x%02x]:%08x\n", i*4, + le32_to_cpu(mfp[i])); + } + + r = _base_handshake_req_reply_wait(ioc, + sizeof(Mpi2IOCInitRequest_t), (u32 *)&mpi_request, + sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 10, + sleep_flag); + + if (r != 0) { + printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n", + ioc->name, __func__, r); + return r; + } + + if (mpi_reply.IOCStatus != MPI2_IOCSTATUS_SUCCESS || + mpi_reply.IOCLogInfo) { + printk(MPT2SAS_ERR_FMT "%s: failed\n", ioc->name, __func__); + r = -EIO; + } + + return 0; +} + +/** + * _base_send_port_enable - send port_enable(discovery stuff) to firmware + * @ioc: per adapter object + * @VF_ID: virtual function id + * @sleep_flag: CAN_SLEEP or NO_SLEEP + * + * Returns 0 for success, non-zero for failure. + */ +static int +_base_send_port_enable(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag) +{ + Mpi2PortEnableRequest_t *mpi_request; + u32 ioc_state; + unsigned long timeleft; + int r = 0; + u16 smid; + + printk(MPT2SAS_INFO_FMT "sending port enable !!\n", ioc->name); + + if (ioc->base_cmds.status & MPT2_CMD_PENDING) { + printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n", + ioc->name, __func__); + return -EAGAIN; + } + + smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx); + if (!smid) { + printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", + ioc->name, __func__); + return -EAGAIN; + } + + ioc->base_cmds.status = MPT2_CMD_PENDING; + mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); + ioc->base_cmds.smid = smid; + memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t)); + mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE; + mpi_request->VF_ID = VF_ID; + + mpt2sas_base_put_smid_default(ioc, smid, VF_ID); + timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, + 300*HZ); + if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { + printk(MPT2SAS_ERR_FMT "%s: timeout\n", + ioc->name, __func__); + _debug_dump_mf(mpi_request, + sizeof(Mpi2PortEnableRequest_t)/4); + if (ioc->base_cmds.status & MPT2_CMD_RESET) + r = -EFAULT; + else + r = -ETIME; + goto out; + } else + dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: complete\n", + ioc->name, __func__)); + + ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_OPERATIONAL, + 60, sleep_flag); + if (ioc_state) { + printk(MPT2SAS_ERR_FMT "%s: failed going to operational state " + " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state); + r = -EFAULT; + } + out: + ioc->base_cmds.status = MPT2_CMD_NOT_USED; + printk(MPT2SAS_INFO_FMT "port enable: %s\n", + ioc->name, ((r == 0) ? "SUCCESS" : "FAILED")); + return r; +} + +/** + * _base_unmask_events - turn on notification for this event + * @ioc: per adapter object + * @event: firmware event + * + * The mask is stored in ioc->event_masks. + */ +static void +_base_unmask_events(struct MPT2SAS_ADAPTER *ioc, u16 event) +{ + u32 desired_event; + + if (event >= 128) + return; + + desired_event = (1 << (event % 32)); + + if (event < 32) + ioc->event_masks[0] &= ~desired_event; + else if (event < 64) + ioc->event_masks[1] &= ~desired_event; + else if (event < 96) + ioc->event_masks[2] &= ~desired_event; + else if (event < 128) + ioc->event_masks[3] &= ~desired_event; +} + +/** + * _base_event_notification - send event notification + * @ioc: per adapter object + * @VF_ID: virtual function id + * @sleep_flag: CAN_SLEEP or NO_SLEEP + * + * Returns 0 for success, non-zero for failure. + */ +static int +_base_event_notification(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag) +{ + Mpi2EventNotificationRequest_t *mpi_request; + unsigned long timeleft; + u16 smid; + int r = 0; + int i; + + dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + __func__)); + + if (ioc->base_cmds.status & MPT2_CMD_PENDING) { + printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n", + ioc->name, __func__); + return -EAGAIN; + } + + smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx); + if (!smid) { + printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", + ioc->name, __func__); + return -EAGAIN; + } + ioc->base_cmds.status = MPT2_CMD_PENDING; + mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); + ioc->base_cmds.smid = smid; + memset(mpi_request, 0, sizeof(Mpi2EventNotificationRequest_t)); + mpi_request->Function = MPI2_FUNCTION_EVENT_NOTIFICATION; + mpi_request->VF_ID = VF_ID; + for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) + mpi_request->EventMasks[i] = + le32_to_cpu(ioc->event_masks[i]); + mpt2sas_base_put_smid_default(ioc, smid, VF_ID); + timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ); + if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { + printk(MPT2SAS_ERR_FMT "%s: timeout\n", + ioc->name, __func__); + _debug_dump_mf(mpi_request, + sizeof(Mpi2EventNotificationRequest_t)/4); + if (ioc->base_cmds.status & MPT2_CMD_RESET) + r = -EFAULT; + else + r = -ETIME; + } else + dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: complete\n", + ioc->name, __func__)); + ioc->base_cmds.status = MPT2_CMD_NOT_USED; + return r; +} + +/** + * mpt2sas_base_validate_event_type - validating event types + * @ioc: per adapter object + * @event: firmware event + * + * This will turn on firmware event notification when application + * ask for that event. We don't mask events that are already enabled. + */ +void +mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type) +{ + int i, j; + u32 event_mask, desired_event; + u8 send_update_to_fw; + + for (i = 0, send_update_to_fw = 0; i < + MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) { + event_mask = ~event_type[i]; + desired_event = 1; + for (j = 0; j < 32; j++) { + if (!(event_mask & desired_event) && + (ioc->event_masks[i] & desired_event)) { + ioc->event_masks[i] &= ~desired_event; + send_update_to_fw = 1; + } + desired_event = (desired_event << 1); + } + } + + if (!send_update_to_fw) + return; + + mutex_lock(&ioc->base_cmds.mutex); + _base_event_notification(ioc, 0, CAN_SLEEP); + mutex_unlock(&ioc->base_cmds.mutex); +} + +/** + * _base_diag_reset - the "big hammer" start of day reset + * @ioc: per adapter object + * @sleep_flag: CAN_SLEEP or NO_SLEEP + * + * Returns 0 for success, non-zero for failure. + */ +static int +_base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) +{ + u32 host_diagnostic; + u32 ioc_state; + u32 count; + u32 hcb_size; + + printk(MPT2SAS_INFO_FMT "sending diag reset !!\n", ioc->name); + + _base_save_msix_table(ioc); + + drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "clear interrupts\n", + ioc->name)); + writel(0, &ioc->chip->HostInterruptStatus); + + count = 0; + do { + /* Write magic sequence to WriteSequence register + * Loop until in diagnostic mode + */ + drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "write magic " + "sequence\n", ioc->name)); + writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence); + writel(MPI2_WRSEQ_1ST_KEY_VALUE, &ioc->chip->WriteSequence); + writel(MPI2_WRSEQ_2ND_KEY_VALUE, &ioc->chip->WriteSequence); + writel(MPI2_WRSEQ_3RD_KEY_VALUE, &ioc->chip->WriteSequence); + writel(MPI2_WRSEQ_4TH_KEY_VALUE, &ioc->chip->WriteSequence); + writel(MPI2_WRSEQ_5TH_KEY_VALUE, &ioc->chip->WriteSequence); + writel(MPI2_WRSEQ_6TH_KEY_VALUE, &ioc->chip->WriteSequence); + + /* wait 100 msec */ + if (sleep_flag == CAN_SLEEP) + msleep(100); + else + mdelay(100); + + if (count++ > 20) + goto out; + + host_diagnostic = readl(&ioc->chip->HostDiagnostic); + drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "wrote magic " + "sequence: count(%d), host_diagnostic(0x%08x)\n", + ioc->name, count, host_diagnostic)); + + } while ((host_diagnostic & MPI2_DIAG_DIAG_WRITE_ENABLE) == 0); + + hcb_size = readl(&ioc->chip->HCBSize); + + drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "diag reset: issued\n", + ioc->name)); + writel(host_diagnostic | MPI2_DIAG_RESET_ADAPTER, + &ioc->chip->HostDiagnostic); + + /* don't access any registers for 50 milliseconds */ + msleep(50); + + /* 300 second max wait */ + for (count = 0; count < 3000000 ; count++) { + + host_diagnostic = readl(&ioc->chip->HostDiagnostic); + + if (host_diagnostic == 0xFFFFFFFF) + goto out; + if (!(host_diagnostic & MPI2_DIAG_RESET_ADAPTER)) + break; + + /* wait 100 msec */ + if (sleep_flag == CAN_SLEEP) + msleep(1); + else + mdelay(1); + } + + if (host_diagnostic & MPI2_DIAG_HCB_MODE) { + + drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "restart the adapter " + "assuming the HCB Address points to good F/W\n", + ioc->name)); + host_diagnostic &= ~MPI2_DIAG_BOOT_DEVICE_SELECT_MASK; + host_diagnostic |= MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW; + writel(host_diagnostic, &ioc->chip->HostDiagnostic); + + drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT + "re-enable the HCDW\n", ioc->name)); + writel(hcb_size | MPI2_HCB_SIZE_HCB_ENABLE, + &ioc->chip->HCBSize); + } + + drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "restart the adapter\n", + ioc->name)); + writel(host_diagnostic & ~MPI2_DIAG_HOLD_IOC_RESET, + &ioc->chip->HostDiagnostic); + + drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "disable writes to the " + "diagnostic register\n", ioc->name)); + writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence); + + drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "Wait for FW to go to the " + "READY state\n", ioc->name)); + ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, 20, + sleep_flag); + if (ioc_state) { + printk(MPT2SAS_ERR_FMT "%s: failed going to ready state " + " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state); + goto out; + } + + _base_restore_msix_table(ioc); + printk(MPT2SAS_INFO_FMT "diag reset: SUCCESS\n", ioc->name); + return 0; + + out: + printk(MPT2SAS_ERR_FMT "diag reset: FAILED\n", ioc->name); + return -EFAULT; +} + +/** + * _base_make_ioc_ready - put controller in READY state + * @ioc: per adapter object + * @sleep_flag: CAN_SLEEP or NO_SLEEP + * @type: FORCE_BIG_HAMMER or SOFT_RESET + * + * Returns 0 for success, non-zero for failure. + */ +static int +_base_make_ioc_ready(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, + enum reset_type type) +{ + u32 ioc_state; + + dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + __func__)); + + ioc_state = mpt2sas_base_get_iocstate(ioc, 0); + dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: ioc_state(0x%08x)\n", + ioc->name, __func__, ioc_state)); + + if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_READY) + return 0; + + if (ioc_state & MPI2_DOORBELL_USED) { + dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "unexpected doorbell " + "active!\n", ioc->name)); + goto issue_diag_reset; + } + + if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) { + mpt2sas_base_fault_info(ioc, ioc_state & + MPI2_DOORBELL_DATA_MASK); + goto issue_diag_reset; + } + + if (type == FORCE_BIG_HAMMER) + goto issue_diag_reset; + + if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_OPERATIONAL) + if (!(_base_send_ioc_reset(ioc, + MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET, 15, CAN_SLEEP))) + return 0; + + issue_diag_reset: + return _base_diag_reset(ioc, CAN_SLEEP); +} + +/** + * _base_make_ioc_operational - put controller in OPERATIONAL state + * @ioc: per adapter object + * @VF_ID: virtual function id + * @sleep_flag: CAN_SLEEP or NO_SLEEP + * + * Returns 0 for success, non-zero for failure. + */ +static int +_base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, + int sleep_flag) +{ + int r, i; + unsigned long flags; + u32 reply_address; + + dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + __func__)); + + /* initialize the scsi lookup free list */ + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); + INIT_LIST_HEAD(&ioc->free_list); + for (i = 0; i < ioc->request_depth; i++) { + ioc->scsi_lookup[i].cb_idx = 0xFF; + list_add_tail(&ioc->scsi_lookup[i].tracker_list, + &ioc->free_list); + } + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); + + /* initialize Reply Free Queue */ + for (i = 0, reply_address = (u32)ioc->reply_dma ; + i < ioc->reply_free_queue_depth ; i++, reply_address += + ioc->reply_sz) + ioc->reply_free[i] = cpu_to_le32(reply_address); + + /* initialize Reply Post Free Queue */ + for (i = 0; i < ioc->reply_post_queue_depth; i++) + ioc->reply_post_free[i].Words = ~0ULL; + + r = _base_send_ioc_init(ioc, VF_ID, sleep_flag); + if (r) + return r; + + /* initialize the index's */ + ioc->reply_free_host_index = ioc->reply_free_queue_depth - 1; + ioc->reply_post_host_index = 0; + writel(ioc->reply_free_host_index, &ioc->chip->ReplyFreeHostIndex); + writel(0, &ioc->chip->ReplyPostHostIndex); + + _base_unmask_interrupts(ioc); + r = _base_event_notification(ioc, VF_ID, sleep_flag); + if (r) + return r; + + if (sleep_flag == CAN_SLEEP) + _base_static_config_pages(ioc); + + r = _base_send_port_enable(ioc, VF_ID, sleep_flag); + if (r) + return r; + + return r; +} + +/** + * mpt2sas_base_free_resources - free resources controller resources (io/irq/memap) + * @ioc: per adapter object + * + * Return nothing. + */ +void +mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc) +{ + struct pci_dev *pdev = ioc->pdev; + + dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + __func__)); + + _base_mask_interrupts(ioc); + _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); + if (ioc->pci_irq) { + synchronize_irq(pdev->irq); + free_irq(ioc->pci_irq, ioc); + } + _base_disable_msix(ioc); + if (ioc->chip_phys) + iounmap(ioc->chip); + ioc->pci_irq = -1; + ioc->chip_phys = 0; + pci_release_selected_regions(ioc->pdev, ioc->bars); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + return; +} + +/** + * mpt2sas_base_attach - attach controller instance + * @ioc: per adapter object + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) +{ + int r, i; + unsigned long flags; + + dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + __func__)); + + r = mpt2sas_base_map_resources(ioc); + if (r) + return r; + + r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); + if (r) + goto out_free_resources; + + r = _base_get_ioc_facts(ioc, CAN_SLEEP); + if (r) + goto out_free_resources; + + r = _base_allocate_memory_pools(ioc, CAN_SLEEP); + if (r) + goto out_free_resources; + + init_waitqueue_head(&ioc->reset_wq); + + /* base internal command bits */ + mutex_init(&ioc->base_cmds.mutex); + init_completion(&ioc->base_cmds.done); + ioc->base_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); + ioc->base_cmds.status = MPT2_CMD_NOT_USED; + + /* transport internal command bits */ + ioc->transport_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); + ioc->transport_cmds.status = MPT2_CMD_NOT_USED; + mutex_init(&ioc->transport_cmds.mutex); + init_completion(&ioc->transport_cmds.done); + + /* task management internal command bits */ + ioc->tm_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); + ioc->tm_cmds.status = MPT2_CMD_NOT_USED; + mutex_init(&ioc->tm_cmds.mutex); + init_completion(&ioc->tm_cmds.done); + + /* config page internal command bits */ + ioc->config_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); + ioc->config_cmds.status = MPT2_CMD_NOT_USED; + mutex_init(&ioc->config_cmds.mutex); + init_completion(&ioc->config_cmds.done); + + /* ctl module internal command bits */ + ioc->ctl_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); + ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; + mutex_init(&ioc->ctl_cmds.mutex); + init_completion(&ioc->ctl_cmds.done); + + for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) + ioc->event_masks[i] = -1; + + /* here we enable the events we care about */ + _base_unmask_events(ioc, MPI2_EVENT_SAS_DISCOVERY); + _base_unmask_events(ioc, MPI2_EVENT_SAS_BROADCAST_PRIMITIVE); + _base_unmask_events(ioc, MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST); + _base_unmask_events(ioc, MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE); + _base_unmask_events(ioc, MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE); + _base_unmask_events(ioc, MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST); + _base_unmask_events(ioc, MPI2_EVENT_IR_VOLUME); + _base_unmask_events(ioc, MPI2_EVENT_IR_PHYSICAL_DISK); + _base_unmask_events(ioc, MPI2_EVENT_IR_OPERATION_STATUS); + _base_unmask_events(ioc, MPI2_EVENT_TASK_SET_FULL); + _base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED); + + ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts, + sizeof(Mpi2PortFactsReply_t), GFP_KERNEL); + if (!ioc->pfacts) + goto out_free_resources; + + for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) { + r = _base_get_port_facts(ioc, i, CAN_SLEEP); + if (r) + goto out_free_resources; + } + r = _base_make_ioc_operational(ioc, 0, CAN_SLEEP); + if (r) + goto out_free_resources; + + /* initialize fault polling */ + INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work); + snprintf(ioc->fault_reset_work_q_name, + sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id); + ioc->fault_reset_work_q = + create_singlethread_workqueue(ioc->fault_reset_work_q_name); + if (!ioc->fault_reset_work_q) { + printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n", + ioc->name, __func__, __LINE__); + goto out_free_resources; + } + spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); + if (ioc->fault_reset_work_q) + queue_delayed_work(ioc->fault_reset_work_q, + &ioc->fault_reset_work, + msecs_to_jiffies(FAULT_POLLING_INTERVAL)); + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + return 0; + + out_free_resources: + + ioc->remove_host = 1; + mpt2sas_base_free_resources(ioc); + _base_release_memory_pools(ioc); + kfree(ioc->tm_cmds.reply); + kfree(ioc->transport_cmds.reply); + kfree(ioc->config_cmds.reply); + kfree(ioc->base_cmds.reply); + kfree(ioc->ctl_cmds.reply); + kfree(ioc->pfacts); + ioc->ctl_cmds.reply = NULL; + ioc->base_cmds.reply = NULL; + ioc->tm_cmds.reply = NULL; + ioc->transport_cmds.reply = NULL; + ioc->config_cmds.reply = NULL; + ioc->pfacts = NULL; + return r; +} + + +/** + * mpt2sas_base_detach - remove controller instance + * @ioc: per adapter object + * + * Return nothing. + */ +void +mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc) +{ + unsigned long flags; + struct workqueue_struct *wq; + + dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + __func__)); + + spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); + wq = ioc->fault_reset_work_q; + ioc->fault_reset_work_q = NULL; + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + if (!cancel_delayed_work(&ioc->fault_reset_work)) + flush_workqueue(wq); + destroy_workqueue(wq); + + mpt2sas_base_free_resources(ioc); + _base_release_memory_pools(ioc); + kfree(ioc->pfacts); + kfree(ioc->ctl_cmds.reply); + kfree(ioc->base_cmds.reply); + kfree(ioc->tm_cmds.reply); + kfree(ioc->transport_cmds.reply); + kfree(ioc->config_cmds.reply); +} + +/** + * _base_reset_handler - reset callback handler (for base) + * @ioc: per adapter object + * @reset_phase: phase + * + * The handler for doing any required cleanup or initialization. + * + * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET, + * MPT2_IOC_DONE_RESET + * + * Return nothing. + */ +static void +_base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) +{ + switch (reset_phase) { + case MPT2_IOC_PRE_RESET: + dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + "MPT2_IOC_PRE_RESET\n", ioc->name, __func__)); + break; + case MPT2_IOC_AFTER_RESET: + dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__)); + if (ioc->transport_cmds.status & MPT2_CMD_PENDING) { + ioc->transport_cmds.status |= MPT2_CMD_RESET; + mpt2sas_base_free_smid(ioc, ioc->transport_cmds.smid); + complete(&ioc->transport_cmds.done); + } + if (ioc->base_cmds.status & MPT2_CMD_PENDING) { + ioc->base_cmds.status |= MPT2_CMD_RESET; + mpt2sas_base_free_smid(ioc, ioc->base_cmds.smid); + complete(&ioc->base_cmds.done); + } + if (ioc->config_cmds.status & MPT2_CMD_PENDING) { + ioc->config_cmds.status |= MPT2_CMD_RESET; + mpt2sas_base_free_smid(ioc, ioc->config_cmds.smid); + complete(&ioc->config_cmds.done); + } + break; + case MPT2_IOC_DONE_RESET: + dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); + break; + } + mpt2sas_scsih_reset_handler(ioc, reset_phase); + mpt2sas_ctl_reset_handler(ioc, reset_phase); +} + +/** + * _wait_for_commands_to_complete - reset controller + * @ioc: Pointer to MPT_ADAPTER structure + * @sleep_flag: CAN_SLEEP or NO_SLEEP + * + * This function waiting(3s) for all pending commands to complete + * prior to putting controller in reset. + */ +static void +_wait_for_commands_to_complete(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) +{ + u32 ioc_state; + unsigned long flags; + u16 i; + + ioc->pending_io_count = 0; + if (sleep_flag != CAN_SLEEP) + return; + + ioc_state = mpt2sas_base_get_iocstate(ioc, 0); + if ((ioc_state & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL) + return; + + /* pending command count */ + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); + for (i = 0; i < ioc->request_depth; i++) + if (ioc->scsi_lookup[i].cb_idx != 0xFF) + ioc->pending_io_count++; + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); + + if (!ioc->pending_io_count) + return; + + /* wait for pending commands to complete */ + wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, 3 * HZ); +} + +/** + * mpt2sas_base_hard_reset_handler - reset controller + * @ioc: Pointer to MPT_ADAPTER structure + * @sleep_flag: CAN_SLEEP or NO_SLEEP + * @type: FORCE_BIG_HAMMER or SOFT_RESET + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, + enum reset_type type) +{ + int r, i; + unsigned long flags; + + dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, + __func__)); + + spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); + if (ioc->ioc_reset_in_progress) { + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + printk(MPT2SAS_ERR_FMT "%s: busy\n", + ioc->name, __func__); + return -EBUSY; + } + ioc->ioc_reset_in_progress = 1; + ioc->shost_recovery = 1; + if (ioc->shost->shost_state == SHOST_RUNNING) { + /* set back to SHOST_RUNNING in mpt2sas_scsih.c */ + scsi_host_set_state(ioc->shost, SHOST_RECOVERY); + printk(MPT2SAS_INFO_FMT "putting controller into " + "SHOST_RECOVERY\n", ioc->name); + } + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + + _base_reset_handler(ioc, MPT2_IOC_PRE_RESET); + _wait_for_commands_to_complete(ioc, sleep_flag); + _base_mask_interrupts(ioc); + r = _base_make_ioc_ready(ioc, sleep_flag, type); + if (r) + goto out; + _base_reset_handler(ioc, MPT2_IOC_AFTER_RESET); + for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) + r = _base_make_ioc_operational(ioc, ioc->pfacts[i].VF_ID, + sleep_flag); + if (!r) + _base_reset_handler(ioc, MPT2_IOC_DONE_RESET); + out: + dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: %s\n", + ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED"))); + + spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); + ioc->ioc_reset_in_progress = 0; + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + return r; +} diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h new file mode 100644 index 00000000000..11fc17f218c --- /dev/null +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -0,0 +1,779 @@ +/* + * This is the Fusion MPT base driver providing common API layer interface + * for access to MPT (Message Passing Technology) firmware. + * + * This code is based on drivers/scsi/mpt2sas/mpt2_base.h + * Copyright (C) 2007-2008 LSI Corporation + * (mailto:DL-MPTFusionLinux@lsi.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * NO WARRANTY + * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT + * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is + * solely responsible for determining the appropriateness of using and + * distributing the Program and assumes all risks associated with its + * exercise of rights under this Agreement, including but not limited to + * the risks and costs of program errors, damage to or loss of data, + * programs or equipment, and unavailability or interruption of operations. + + * DISCLAIMER OF LIABILITY + * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED + * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#ifndef MPT2SAS_BASE_H_INCLUDED +#define MPT2SAS_BASE_H_INCLUDED + +#include "mpi/mpi2_type.h" +#include "mpi/mpi2.h" +#include "mpi/mpi2_ioc.h" +#include "mpi/mpi2_cnfg.h" +#include "mpi/mpi2_init.h" +#include "mpi/mpi2_raid.h" +#include "mpi/mpi2_tool.h" +#include "mpi/mpi2_sas.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "mpt2sas_debug.h" + +/* driver versioning info */ +#define MPT2SAS_DRIVER_NAME "mpt2sas" +#define MPT2SAS_AUTHOR "LSI Corporation " +#define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver" +#define MPT2SAS_DRIVER_VERSION "00.100.11.15" +#define MPT2SAS_MAJOR_VERSION 00 +#define MPT2SAS_MINOR_VERSION 100 +#define MPT2SAS_BUILD_VERSION 11 +#define MPT2SAS_RELEASE_VERSION 15 + +/* + * Set MPT2SAS_SG_DEPTH value based on user input. + */ +#ifdef CONFIG_SCSI_MPT2SAS_MAX_SGE +#if CONFIG_SCSI_MPT2SAS_MAX_SGE < 16 +#define MPT2SAS_SG_DEPTH 16 +#elif CONFIG_SCSI_MPT2SAS_MAX_SGE > 128 +#define MPT2SAS_SG_DEPTH 128 +#else +#define MPT2SAS_SG_DEPTH CONFIG_SCSI_MPT2SAS_MAX_SGE +#endif +#else +#define MPT2SAS_SG_DEPTH 128 /* MAX_HW_SEGMENTS */ +#endif + + +/* + * Generic Defines + */ +#define MPT2SAS_SATA_QUEUE_DEPTH 32 +#define MPT2SAS_SAS_QUEUE_DEPTH 254 +#define MPT2SAS_RAID_QUEUE_DEPTH 128 + +#define MPT_NAME_LENGTH 32 /* generic length of strings */ +#define MPT_STRING_LENGTH 64 + +#define MPT_MAX_CALLBACKS 16 + +#define CAN_SLEEP 1 +#define NO_SLEEP 0 + +#define INTERNAL_CMDS_COUNT 10 /* reserved cmds */ + +#define MPI2_HIM_MASK 0xFFFFFFFF /* mask every bit*/ + +#define MPT2SAS_INVALID_DEVICE_HANDLE 0xFFFF + + +/* + * reset phases + */ +#define MPT2_IOC_PRE_RESET 1 /* prior to host reset */ +#define MPT2_IOC_AFTER_RESET 2 /* just after host reset */ +#define MPT2_IOC_DONE_RESET 3 /* links re-initialized */ + +/* + * logging format + */ +#define MPT2SAS_FMT "%s: " +#define MPT2SAS_DEBUG_FMT KERN_DEBUG MPT2SAS_FMT +#define MPT2SAS_INFO_FMT KERN_INFO MPT2SAS_FMT +#define MPT2SAS_NOTE_FMT KERN_NOTICE MPT2SAS_FMT +#define MPT2SAS_WARN_FMT KERN_WARNING MPT2SAS_FMT +#define MPT2SAS_ERR_FMT KERN_ERR MPT2SAS_FMT + +/* + * per target private data + */ +#define MPT_TARGET_FLAGS_RAID_COMPONENT 0x01 +#define MPT_TARGET_FLAGS_VOLUME 0x02 +#define MPT_TARGET_FLAGS_DELETED 0x04 + +/** + * struct MPT2SAS_TARGET - starget private hostdata + * @starget: starget object + * @sas_address: target sas address + * @handle: device handle + * @num_luns: number luns + * @flags: MPT_TARGET_FLAGS_XXX flags + * @deleted: target flaged for deletion + * @tm_busy: target is busy with TM request. + */ +struct MPT2SAS_TARGET { + struct scsi_target *starget; + u64 sas_address; + u16 handle; + int num_luns; + u32 flags; + u8 deleted; + u8 tm_busy; +}; + +/* + * per device private data + */ +#define MPT_DEVICE_FLAGS_INIT 0x01 +#define MPT_DEVICE_TLR_ON 0x02 + +/** + * struct MPT2SAS_DEVICE - sdev private hostdata + * @sas_target: starget private hostdata + * @lun: lun number + * @flags: MPT_DEVICE_XXX flags + * @configured_lun: lun is configured + * @block: device is in SDEV_BLOCK state + * @tlr_snoop_check: flag used in determining whether to disable TLR + */ +struct MPT2SAS_DEVICE { + struct MPT2SAS_TARGET *sas_target; + unsigned int lun; + u32 flags; + u8 configured_lun; + u8 block; + u8 tlr_snoop_check; +}; + +#define MPT2_CMD_NOT_USED 0x8000 /* free */ +#define MPT2_CMD_COMPLETE 0x0001 /* completed */ +#define MPT2_CMD_PENDING 0x0002 /* pending */ +#define MPT2_CMD_REPLY_VALID 0x0004 /* reply is valid */ +#define MPT2_CMD_RESET 0x0008 /* host reset dropped the command */ + +/** + * struct _internal_cmd - internal commands struct + * @mutex: mutex + * @done: completion + * @reply: reply message pointer + * @status: MPT2_CMD_XXX status + * @smid: system message id + */ +struct _internal_cmd { + struct mutex mutex; + struct completion done; + void *reply; + u16 status; + u16 smid; +}; + +/* + * SAS Topology Structures + */ + +/** + * struct _sas_device - attached device information + * @list: sas device list + * @starget: starget object + * @sas_address: device sas address + * @device_name: retrieved from the SAS IDENTIFY frame. + * @handle: device handle + * @parent_handle: handle to parent device + * @enclosure_handle: enclosure handle + * @enclosure_logical_id: enclosure logical identifier + * @volume_handle: volume handle (valid when hidden raid member) + * @volume_wwid: volume unique identifier + * @device_info: bitfield provides detailed info about the device + * @id: target id + * @channel: target channel + * @slot: number number + * @hidden_raid_component: set to 1 when this is a raid member + * @responding: used in _scsih_sas_device_mark_responding + */ +struct _sas_device { + struct list_head list; + struct scsi_target *starget; + u64 sas_address; + u64 device_name; + u16 handle; + u16 parent_handle; + u16 enclosure_handle; + u64 enclosure_logical_id; + u16 volume_handle; + u64 volume_wwid; + u32 device_info; + int id; + int channel; + u16 slot; + u8 hidden_raid_component; + u8 responding; +}; + +/** + * struct _raid_device - raid volume link list + * @list: sas device list + * @starget: starget object + * @sdev: scsi device struct (volumes are single lun) + * @wwid: unique identifier for the volume + * @handle: device handle + * @id: target id + * @channel: target channel + * @volume_type: the raid level + * @device_info: bitfield provides detailed info about the hidden components + * @num_pds: number of hidden raid components + * @responding: used in _scsih_raid_device_mark_responding + */ +struct _raid_device { + struct list_head list; + struct scsi_target *starget; + struct scsi_device *sdev; + u64 wwid; + u16 handle; + int id; + int channel; + u8 volume_type; + u32 device_info; + u8 num_pds; + u8 responding; +}; + +/** + * struct _boot_device - boot device info + * @is_raid: flag to indicate whether this is volume + * @device: holds pointer for either struct _sas_device or + * struct _raid_device + */ +struct _boot_device { + u8 is_raid; + void *device; +}; + +/** + * struct _sas_port - wide/narrow sas port information + * @port_list: list of ports belonging to expander + * @handle: device handle for this port + * @sas_address: sas address of this port + * @num_phys: number of phys belonging to this port + * @remote_identify: attached device identification + * @rphy: sas transport rphy object + * @port: sas transport wide/narrow port object + * @phy_list: _sas_phy list objects belonging to this port + */ +struct _sas_port { + struct list_head port_list; + u16 handle; + u64 sas_address; + u8 num_phys; + struct sas_identify remote_identify; + struct sas_rphy *rphy; + struct sas_port *port; + struct list_head phy_list; +}; + +/** + * struct _sas_phy - phy information + * @port_siblings: list of phys belonging to a port + * @identify: phy identification + * @remote_identify: attached device identification + * @phy: sas transport phy object + * @phy_id: unique phy id + * @handle: device handle for this phy + * @attached_handle: device handle for attached device + */ +struct _sas_phy { + struct list_head port_siblings; + struct sas_identify identify; + struct sas_identify remote_identify; + struct sas_phy *phy; + u8 phy_id; + u16 handle; + u16 attached_handle; +}; + +/** + * struct _sas_node - sas_host/expander information + * @list: list of expanders + * @parent_dev: parent device class + * @num_phys: number phys belonging to this sas_host/expander + * @sas_address: sas address of this sas_host/expander + * @handle: handle for this sas_host/expander + * @parent_handle: parent handle + * @enclosure_handle: handle for this a member of an enclosure + * @device_info: bitwise defining capabilities of this sas_host/expander + * @responding: used in _scsih_expander_device_mark_responding + * @phy: a list of phys that make up this sas_host/expander + * @sas_port_list: list of ports attached to this sas_host/expander + */ +struct _sas_node { + struct list_head list; + struct device *parent_dev; + u8 num_phys; + u64 sas_address; + u16 handle; + u16 parent_handle; + u16 enclosure_handle; + u64 enclosure_logical_id; + u8 responding; + struct _sas_phy *phy; + struct list_head sas_port_list; +}; + +/** + * enum reset_type - reset state + * @FORCE_BIG_HAMMER: issue diagnostic reset + * @SOFT_RESET: issue message_unit_reset, if fails to to big hammer + */ +enum reset_type { + FORCE_BIG_HAMMER, + SOFT_RESET, +}; + +/** + * struct request_tracker - firmware request tracker + * @smid: system message id + * @scmd: scsi request pointer + * @cb_idx: callback index + * @chain_list: list of chains associated to this IO + * @tracker_list: list of free request (ioc->free_list) + */ +struct request_tracker { + u16 smid; + struct scsi_cmnd *scmd; + u8 cb_idx; + struct list_head tracker_list; +}; + +typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr); + +/** + * struct MPT2SAS_ADAPTER - per adapter struct + * @list: ioc_list + * @shost: shost object + * @id: unique adapter id + * @pci_irq: irq number + * @name: generic ioc string + * @tmp_string: tmp string used for logging + * @pdev: pci pdev object + * @chip: memory mapped register space + * @chip_phys: physical addrss prior to mapping + * @pio_chip: I/O mapped register space + * @logging_level: see mpt2sas_debug.h + * @ir_firmware: IR firmware present + * @bars: bitmask of BAR's that must be configured + * @mask_interrupts: ignore interrupt + * @fault_reset_work_q_name: fw fault work queue + * @fault_reset_work_q: "" + * @fault_reset_work: "" + * @firmware_event_name: fw event work queue + * @firmware_event_thread: "" + * @fw_events_off: flag to turn off fw event handling + * @fw_event_lock: + * @fw_event_list: list of fw events + * @aen_event_read_flag: event log was read + * @broadcast_aen_busy: broadcast aen waiting to be serviced + * @ioc_reset_in_progress: host reset in progress + * @ioc_reset_in_progress_lock: + * @ioc_link_reset_in_progress: phy/hard reset in progress + * @ignore_loginfos: ignore loginfos during task managment + * @remove_host: flag for when driver unloads, to avoid sending dev resets + * @wait_for_port_enable_to_complete: + * @msix_enable: flag indicating msix is enabled + * @msix_vector_count: number msix vectors + * @msix_table: virt address to the msix table + * @msix_table_backup: backup msix table + * @scsi_io_cb_idx: shost generated commands + * @tm_cb_idx: task management commands + * @transport_cb_idx: transport internal commands + * @ctl_cb_idx: clt internal commands + * @base_cb_idx: base internal commands + * @config_cb_idx: base internal commands + * @base_cmds: + * @transport_cmds: + * @tm_cmds: + * @ctl_cmds: + * @config_cmds: + * @base_add_sg_single: handler for either 32/64 bit sgl's + * @event_type: bits indicating which events to log + * @event_context: unique id for each logged event + * @event_log: event log pointer + * @event_masks: events that are masked + * @facts: static facts data + * @pfacts: static port facts data + * @manu_pg0: static manufacturing page 0 + * @bios_pg2: static bios page 2 + * @bios_pg3: static bios page 3 + * @ioc_pg8: static ioc page 8 + * @iounit_pg0: static iounit page 0 + * @iounit_pg1: static iounit page 1 + * @sas_hba: sas host object + * @sas_expander_list: expander object list + * @sas_node_lock: + * @sas_device_list: sas device object list + * @sas_device_init_list: sas device object list (used only at init time) + * @sas_device_lock: + * @io_missing_delay: time for IO completed by fw when PDR enabled + * @device_missing_delay: time for device missing by fw when PDR enabled + * @config_page_sz: config page size + * @config_page: reserve memory for config page payload + * @config_page_dma: + * @sge_size: sg element size for either 32/64 bit + * @request_depth: hba request queue depth + * @request_sz: per request frame size + * @request: pool of request frames + * @request_dma: + * @request_dma_sz: + * @scsi_lookup: firmware request tracker list + * @scsi_lookup_lock: + * @free_list: free list of request + * @chain: pool of chains + * @pending_io_count: + * @reset_wq: + * @chain_dma: + * @max_sges_in_main_message: number sg elements in main message + * @max_sges_in_chain_message: number sg elements per chain + * @chains_needed_per_io: max chains per io + * @chain_offset_value_for_main_message: location 1st sg in main + * @chain_depth: total chains allocated + * @sense: pool of sense + * @sense_dma: + * @sense_dma_pool: + * @reply_depth: hba reply queue depth: + * @reply_sz: per reply frame size: + * @reply: pool of replys: + * @reply_dma: + * @reply_dma_pool: + * @reply_free_queue_depth: reply free depth + * @reply_free: pool for reply free queue (32 bit addr) + * @reply_free_dma: + * @reply_free_dma_pool: + * @reply_free_host_index: tail index in pool to insert free replys + * @reply_post_queue_depth: reply post queue depth + * @reply_post_free: pool for reply post (64bit descriptor) + * @reply_post_free_dma: + * @reply_post_free_dma_pool: + * @reply_post_host_index: head index in the pool where FW completes IO + */ +struct MPT2SAS_ADAPTER { + struct list_head list; + struct Scsi_Host *shost; + u8 id; + u32 pci_irq; + char name[MPT_NAME_LENGTH]; + char tmp_string[MPT_STRING_LENGTH]; + struct pci_dev *pdev; + Mpi2SystemInterfaceRegs_t __iomem *chip; + unsigned long chip_phys; + unsigned long pio_chip; + int logging_level; + u8 ir_firmware; + int bars; + u8 mask_interrupts; + + /* fw fault handler */ + char fault_reset_work_q_name[20]; + struct workqueue_struct *fault_reset_work_q; + struct delayed_work fault_reset_work; + + /* fw event handler */ + char firmware_event_name[20]; + struct workqueue_struct *firmware_event_thread; + u8 fw_events_off; + spinlock_t fw_event_lock; + struct list_head fw_event_list; + + /* misc flags */ + int aen_event_read_flag; + u8 broadcast_aen_busy; + u8 ioc_reset_in_progress; + u8 shost_recovery; + spinlock_t ioc_reset_in_progress_lock; + u8 ioc_link_reset_in_progress; + u8 ignore_loginfos; + u8 remove_host; + u8 wait_for_port_enable_to_complete; + + u8 msix_enable; + u16 msix_vector_count; + u32 *msix_table; + u32 *msix_table_backup; + + /* internal commands, callback index */ + u8 scsi_io_cb_idx; + u8 tm_cb_idx; + u8 transport_cb_idx; + u8 ctl_cb_idx; + u8 base_cb_idx; + u8 config_cb_idx; + struct _internal_cmd base_cmds; + struct _internal_cmd transport_cmds; + struct _internal_cmd tm_cmds; + struct _internal_cmd ctl_cmds; + struct _internal_cmd config_cmds; + + MPT_ADD_SGE base_add_sg_single; + + /* event log */ + u32 event_type[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS]; + u32 event_context; + void *event_log; + u32 event_masks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS]; + + /* static config pages */ + Mpi2IOCFactsReply_t facts; + Mpi2PortFactsReply_t *pfacts; + Mpi2ManufacturingPage0_t manu_pg0; + Mpi2BiosPage2_t bios_pg2; + Mpi2BiosPage3_t bios_pg3; + Mpi2IOCPage8_t ioc_pg8; + Mpi2IOUnitPage0_t iounit_pg0; + Mpi2IOUnitPage1_t iounit_pg1; + + struct _boot_device req_boot_device; + struct _boot_device req_alt_boot_device; + struct _boot_device current_boot_device; + + /* sas hba, expander, and device list */ + struct _sas_node sas_hba; + struct list_head sas_expander_list; + spinlock_t sas_node_lock; + struct list_head sas_device_list; + struct list_head sas_device_init_list; + spinlock_t sas_device_lock; + struct list_head raid_device_list; + spinlock_t raid_device_lock; + u8 io_missing_delay; + u16 device_missing_delay; + int sas_id; + + /* config page */ + u16 config_page_sz; + void *config_page; + dma_addr_t config_page_dma; + + /* request */ + u16 sge_size; + u16 request_depth; + u16 request_sz; + u8 *request; + dma_addr_t request_dma; + u32 request_dma_sz; + struct request_tracker *scsi_lookup; + spinlock_t scsi_lookup_lock; + struct list_head free_list; + int pending_io_count; + wait_queue_head_t reset_wq; + + /* chain */ + u8 *chain; + dma_addr_t chain_dma; + u16 max_sges_in_main_message; + u16 max_sges_in_chain_message; + u16 chains_needed_per_io; + u16 chain_offset_value_for_main_message; + u16 chain_depth; + + /* sense */ + u8 *sense; + dma_addr_t sense_dma; + struct dma_pool *sense_dma_pool; + + /* reply */ + u16 reply_sz; + u8 *reply; + dma_addr_t reply_dma; + struct dma_pool *reply_dma_pool; + + /* reply free queue */ + u16 reply_free_queue_depth; + u32 *reply_free; + dma_addr_t reply_free_dma; + struct dma_pool *reply_free_dma_pool; + u32 reply_free_host_index; + + /* reply post queue */ + u16 reply_post_queue_depth; + Mpi2ReplyDescriptorsUnion_t *reply_post_free; + dma_addr_t reply_post_free_dma; + struct dma_pool *reply_post_free_dma_pool; + u32 reply_post_host_index; + + /* diag buffer support */ + u8 *diag_buffer[MPI2_DIAG_BUF_TYPE_COUNT]; + u32 diag_buffer_sz[MPI2_DIAG_BUF_TYPE_COUNT]; + dma_addr_t diag_buffer_dma[MPI2_DIAG_BUF_TYPE_COUNT]; + u8 diag_buffer_status[MPI2_DIAG_BUF_TYPE_COUNT]; + u32 unique_id[MPI2_DIAG_BUF_TYPE_COUNT]; + u32 product_specific[MPI2_DIAG_BUF_TYPE_COUNT][23]; + u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT]; +}; + +typedef void (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, + u32 reply); + + +/* base shared API */ +extern struct list_head ioc_list; + +int mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc); +void mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc); +int mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc); +void mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc); +int mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, + enum reset_type type); + +void *mpt2sas_base_get_msg_frame(struct MPT2SAS_ADAPTER *ioc, u16 smid); +void *mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid); +void mpt2sas_base_build_zero_len_sge(struct MPT2SAS_ADAPTER *ioc, void *paddr); +dma_addr_t mpt2sas_base_get_msg_frame_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid); +dma_addr_t mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid); + +u16 mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx); +void mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid); +void mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id, + u16 handle); +void mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id); +void mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid, + u8 vf_id, u16 io_index); +void mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id); +void mpt2sas_base_initialize_callback_handler(void); +u8 mpt2sas_base_register_callback_handler(MPT_CALLBACK cb_func); +void mpt2sas_base_release_callback_handler(u8 cb_idx); + +void mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply); +void *mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr); + +u32 mpt2sas_base_get_iocstate(struct MPT2SAS_ADAPTER *ioc, int cooked); + +void mpt2sas_base_fault_info(struct MPT2SAS_ADAPTER *ioc , u16 fault_code); +int mpt2sas_base_sas_iounit_control(struct MPT2SAS_ADAPTER *ioc, + Mpi2SasIoUnitControlReply_t *mpi_reply, Mpi2SasIoUnitControlRequest_t + *mpi_request); +int mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc, + Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request); +void mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type); + +/* scsih shared API */ +void mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint lun, + u8 type, u16 smid_task, ulong timeout); +void mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle); +void mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle); +struct _sas_node *mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc, + u16 handle); +struct _sas_node *mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER + *ioc, u64 sas_address); +struct _sas_device *mpt2sas_scsih_sas_device_find_by_sas_address( + struct MPT2SAS_ADAPTER *ioc, u64 sas_address); + +void mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply); +void mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase); + +/* config shared API */ +void mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply); +int mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys); +int mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page); +int mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2BiosPage2_t *config_page); +int mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2BiosPage3_t *config_page); +int mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2IOUnitPage0_t *config_page); +int mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u32 handle); +int mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2SasDevicePage1_t *config_page, u32 form, u32 handle); +int mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, u16 sz); +int mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2IOUnitPage1_t *config_page); +int mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2IOUnitPage1_t config_page); +int mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz); +int mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2IOCPage8_t *config_page); +int mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle); +int mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number, u16 handle); +int mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle); +int mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number); +int mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number); +int mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u32 handle); +int mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 *num_pds); +int mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form, u32 handle, u16 sz); +int mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form, + u32 form_specific); +int mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle, + u16 *volume_handle); +int mpt2sas_config_get_volume_wwid(struct MPT2SAS_ADAPTER *ioc, u16 volume_handle, + u64 *wwid); + +/* ctl shared API */ +extern struct device_attribute *mpt2sas_host_attrs[]; +extern struct device_attribute *mpt2sas_dev_attrs[]; +void mpt2sas_ctl_init(void); +void mpt2sas_ctl_exit(void); +void mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply); +void mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase); +void mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply); +void mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc, + Mpi2EventNotificationReply_t *mpi_reply); + +/* transport shared API */ +void mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply); +struct _sas_port *mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, + u16 handle, u16 parent_handle); +void mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address, + u16 parent_handle); +int mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy + *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev); +int mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy + *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev); +void mpt2sas_transport_update_phy_link_change(struct MPT2SAS_ADAPTER *ioc, u16 handle, + u16 attached_handle, u8 phy_number, u8 link_rate); +extern struct sas_function_template mpt2sas_transport_functions; +extern struct scsi_transport_template *mpt2sas_transport_template; + +#endif /* MPT2SAS_BASE_H_INCLUDED */ diff --git a/drivers/scsi/mpt2sas/mpt2sas_config.c b/drivers/scsi/mpt2sas/mpt2sas_config.c new file mode 100644 index 00000000000..58cfb97846f --- /dev/null +++ b/drivers/scsi/mpt2sas/mpt2sas_config.c @@ -0,0 +1,1873 @@ +/* + * This module provides common API for accessing firmware configuration pages + * + * This code is based on drivers/scsi/mpt2sas/mpt2_base.c + * Copyright (C) 2007-2008 LSI Corporation + * (mailto:DL-MPTFusionLinux@lsi.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * NO WARRANTY + * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT + * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is + * solely responsible for determining the appropriateness of using and + * distributing the Program and assumes all risks associated with its + * exercise of rights under this Agreement, including but not limited to + * the risks and costs of program errors, damage to or loss of data, + * programs or equipment, and unavailability or interruption of operations. + + * DISCLAIMER OF LIABILITY + * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED + * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mpt2sas_base.h" + +/* local definitions */ + +/* Timeout for config page request (in seconds) */ +#define MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT 15 + +/* Common sgl flags for READING a config page. */ +#define MPT2_CONFIG_COMMON_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \ + MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \ + | MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT) + +/* Common sgl flags for WRITING a config page. */ +#define MPT2_CONFIG_COMMON_WRITE_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \ + MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \ + | MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC) \ + << MPI2_SGE_FLAGS_SHIFT) + +/** + * struct config_request - obtain dma memory via routine + * @config_page_sz: size + * @config_page: virt pointer + * @config_page_dma: phys pointer + * + */ +struct config_request{ + u16 config_page_sz; + void *config_page; + dma_addr_t config_page_dma; +}; + +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING +/** + * _config_display_some_debug - debug routine + * @ioc: per adapter object + * @smid: system request message index + * @calling_function_name: string pass from calling function + * @mpi_reply: reply message frame + * Context: none. + * + * Function for displaying debug info helpfull when debugging issues + * in this module. + */ +static void +_config_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid, + char *calling_function_name, MPI2DefaultReply_t *mpi_reply) +{ + Mpi2ConfigRequest_t *mpi_request; + char *desc = NULL; + + if (!(ioc->logging_level & MPT_DEBUG_CONFIG)) + return; + + mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); + switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) { + case MPI2_CONFIG_PAGETYPE_IO_UNIT: + desc = "io_unit"; + break; + case MPI2_CONFIG_PAGETYPE_IOC: + desc = "ioc"; + break; + case MPI2_CONFIG_PAGETYPE_BIOS: + desc = "bios"; + break; + case MPI2_CONFIG_PAGETYPE_RAID_VOLUME: + desc = "raid_volume"; + break; + case MPI2_CONFIG_PAGETYPE_MANUFACTURING: + desc = "manufaucturing"; + break; + case MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK: + desc = "physdisk"; + break; + case MPI2_CONFIG_PAGETYPE_EXTENDED: + switch (mpi_request->ExtPageType) { + case MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT: + desc = "sas_io_unit"; + break; + case MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER: + desc = "sas_expander"; + break; + case MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE: + desc = "sas_device"; + break; + case MPI2_CONFIG_EXTPAGETYPE_SAS_PHY: + desc = "sas_phy"; + break; + case MPI2_CONFIG_EXTPAGETYPE_LOG: + desc = "log"; + break; + case MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE: + desc = "enclosure"; + break; + case MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG: + desc = "raid_config"; + break; + case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING: + desc = "driver_mappping"; + break; + } + break; + } + + if (!desc) + return; + + printk(MPT2SAS_DEBUG_FMT "%s: %s(%d), action(%d), form(0x%08x), " + "smid(%d)\n", ioc->name, calling_function_name, desc, + mpi_request->Header.PageNumber, mpi_request->Action, + le32_to_cpu(mpi_request->PageAddress), smid); + + if (!mpi_reply) + return; + + if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo) + printk(MPT2SAS_DEBUG_FMT + "\tiocstatus(0x%04x), loginfo(0x%08x)\n", + ioc->name, le16_to_cpu(mpi_reply->IOCStatus), + le32_to_cpu(mpi_reply->IOCLogInfo)); +} +#endif + +/** + * mpt2sas_config_done - config page completion routine + * @ioc: per adapter object + * @smid: system request message index + * @VF_ID: virtual function id + * @reply: reply message frame(lower 32bit addr) + * Context: none. + * + * The callback handler when using _config_request. + * + * Return nothing. + */ +void +mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) +{ + MPI2DefaultReply_t *mpi_reply; + + if (ioc->config_cmds.status == MPT2_CMD_NOT_USED) + return; + if (ioc->config_cmds.smid != smid) + return; + ioc->config_cmds.status |= MPT2_CMD_COMPLETE; + mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); + if (mpi_reply) { + ioc->config_cmds.status |= MPT2_CMD_REPLY_VALID; + memcpy(ioc->config_cmds.reply, mpi_reply, + mpi_reply->MsgLength*4); + } + ioc->config_cmds.status &= ~MPT2_CMD_PENDING; +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING + _config_display_some_debug(ioc, smid, "config_done", mpi_reply); +#endif + complete(&ioc->config_cmds.done); +} + +/** + * _config_request - main routine for sending config page requests + * @ioc: per adapter object + * @mpi_request: request message frame + * @mpi_reply: reply mf payload returned from firmware + * @timeout: timeout in seconds + * Context: sleep, the calling function needs to acquire the config_cmds.mutex + * + * A generic API for config page requests to firmware. + * + * The ioc->config_cmds.status flag should be MPT2_CMD_NOT_USED before calling + * this API. + * + * The callback index is set inside `ioc->config_cb_idx. + * + * Returns 0 for success, non-zero for failure. + */ +static int +_config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t + *mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout) +{ + u16 smid; + u32 ioc_state; + unsigned long timeleft; + Mpi2ConfigRequest_t *config_request; + int r; + u8 retry_count; + u8 issue_reset; + u16 wait_state_count; + + if (ioc->config_cmds.status != MPT2_CMD_NOT_USED) { + printk(MPT2SAS_ERR_FMT "%s: config_cmd in use\n", + ioc->name, __func__); + return -EAGAIN; + } + retry_count = 0; + + retry_config: + wait_state_count = 0; + ioc_state = mpt2sas_base_get_iocstate(ioc, 1); + while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { + if (wait_state_count++ == MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT) { + printk(MPT2SAS_ERR_FMT + "%s: failed due to ioc not operational\n", + ioc->name, __func__); + ioc->config_cmds.status = MPT2_CMD_NOT_USED; + return -EFAULT; + } + ssleep(1); + ioc_state = mpt2sas_base_get_iocstate(ioc, 1); + printk(MPT2SAS_INFO_FMT "%s: waiting for " + "operational state(count=%d)\n", ioc->name, + __func__, wait_state_count); + } + if (wait_state_count) + printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n", + ioc->name, __func__); + + smid = mpt2sas_base_get_smid(ioc, ioc->config_cb_idx); + if (!smid) { + printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", + ioc->name, __func__); + ioc->config_cmds.status = MPT2_CMD_NOT_USED; + return -EAGAIN; + } + + r = 0; + memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t)); + ioc->config_cmds.status = MPT2_CMD_PENDING; + config_request = mpt2sas_base_get_msg_frame(ioc, smid); + ioc->config_cmds.smid = smid; + memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t)); +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING + _config_display_some_debug(ioc, smid, "config_request", NULL); +#endif + mpt2sas_base_put_smid_default(ioc, smid, config_request->VF_ID); + timeleft = wait_for_completion_timeout(&ioc->config_cmds.done, + timeout*HZ); + if (!(ioc->config_cmds.status & MPT2_CMD_COMPLETE)) { + printk(MPT2SAS_ERR_FMT "%s: timeout\n", + ioc->name, __func__); + _debug_dump_mf(mpi_request, + sizeof(Mpi2ConfigRequest_t)/4); + if (!(ioc->config_cmds.status & MPT2_CMD_RESET)) + issue_reset = 1; + goto issue_host_reset; + } + if (ioc->config_cmds.status & MPT2_CMD_REPLY_VALID) + memcpy(mpi_reply, ioc->config_cmds.reply, + sizeof(Mpi2ConfigReply_t)); + if (retry_count) + printk(MPT2SAS_INFO_FMT "%s: retry completed!!\n", + ioc->name, __func__); + ioc->config_cmds.status = MPT2_CMD_NOT_USED; + return r; + + issue_host_reset: + if (issue_reset) + mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, + FORCE_BIG_HAMMER); + ioc->config_cmds.status = MPT2_CMD_NOT_USED; + if (!retry_count) { + printk(MPT2SAS_INFO_FMT "%s: attempting retry\n", + ioc->name, __func__); + retry_count++; + goto retry_config; + } + return -EFAULT; +} + +/** + * _config_alloc_config_dma_memory - obtain physical memory + * @ioc: per adapter object + * @mem: struct config_request + * + * A wrapper for obtaining dma-able memory for config page request. + * + * Returns 0 for success, non-zero for failure. + */ +static int +_config_alloc_config_dma_memory(struct MPT2SAS_ADAPTER *ioc, + struct config_request *mem) +{ + int r = 0; + + mem->config_page = pci_alloc_consistent(ioc->pdev, mem->config_page_sz, + &mem->config_page_dma); + if (!mem->config_page) + r = -ENOMEM; + return r; +} + +/** + * _config_free_config_dma_memory - wrapper to free the memory + * @ioc: per adapter object + * @mem: struct config_request + * + * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory. + * + * Returns 0 for success, non-zero for failure. + */ +static void +_config_free_config_dma_memory(struct MPT2SAS_ADAPTER *ioc, + struct config_request *mem) +{ + pci_free_consistent(ioc->pdev, mem->config_page_sz, mem->config_page, + mem->config_page_dma); +} + +/** + * mpt2sas_config_get_manufacturing_pg0 - obtain manufacturing page 0 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + struct config_request mem; + + mutex_lock(&ioc->config_cmds.mutex); + memset(config_page, 0, sizeof(Mpi2ManufacturingPage0_t)); + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; + mpi_request.Header.PageNumber = 0; + mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION; + mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (r) + goto out; + + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; + mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; + mpi_request.Header.PageType = mpi_reply->Header.PageType; + mpi_request.Header.PageLength = mpi_reply->Header.PageLength; + mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4; + if (mem.config_page_sz > ioc->config_page_sz) { + r = _config_alloc_config_dma_memory(ioc, &mem); + if (r) + goto out; + } else { + mem.config_page_dma = ioc->config_page_dma; + mem.config_page = ioc->config_page; + } + ioc->base_add_sg_single(&mpi_request.PageBufferSGE, + MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, + mem.config_page_dma); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (!r) + memcpy(config_page, mem.config_page, + min_t(u16, mem.config_page_sz, + sizeof(Mpi2ManufacturingPage0_t))); + + if (mem.config_page_sz > ioc->config_page_sz) + _config_free_config_dma_memory(ioc, &mem); + + out: + mutex_unlock(&ioc->config_cmds.mutex); + return r; +} + +/** + * mpt2sas_config_get_bios_pg2 - obtain bios page 2 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + struct config_request mem; + + mutex_lock(&ioc->config_cmds.mutex); + memset(config_page, 0, sizeof(Mpi2BiosPage2_t)); + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; + mpi_request.Header.PageNumber = 2; + mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION; + mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (r) + goto out; + + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; + mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; + mpi_request.Header.PageType = mpi_reply->Header.PageType; + mpi_request.Header.PageLength = mpi_reply->Header.PageLength; + mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4; + if (mem.config_page_sz > ioc->config_page_sz) { + r = _config_alloc_config_dma_memory(ioc, &mem); + if (r) + goto out; + } else { + mem.config_page_dma = ioc->config_page_dma; + mem.config_page = ioc->config_page; + } + ioc->base_add_sg_single(&mpi_request.PageBufferSGE, + MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, + mem.config_page_dma); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (!r) + memcpy(config_page, mem.config_page, + min_t(u16, mem.config_page_sz, + sizeof(Mpi2BiosPage2_t))); + + if (mem.config_page_sz > ioc->config_page_sz) + _config_free_config_dma_memory(ioc, &mem); + + out: + mutex_unlock(&ioc->config_cmds.mutex); + return r; +} + +/** + * mpt2sas_config_get_bios_pg3 - obtain bios page 3 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2BiosPage3_t *config_page) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + struct config_request mem; + + mutex_lock(&ioc->config_cmds.mutex); + memset(config_page, 0, sizeof(Mpi2BiosPage3_t)); + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; + mpi_request.Header.PageNumber = 3; + mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; + mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (r) + goto out; + + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; + mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; + mpi_request.Header.PageType = mpi_reply->Header.PageType; + mpi_request.Header.PageLength = mpi_reply->Header.PageLength; + mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4; + if (mem.config_page_sz > ioc->config_page_sz) { + r = _config_alloc_config_dma_memory(ioc, &mem); + if (r) + goto out; + } else { + mem.config_page_dma = ioc->config_page_dma; + mem.config_page = ioc->config_page; + } + ioc->base_add_sg_single(&mpi_request.PageBufferSGE, + MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, + mem.config_page_dma); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (!r) + memcpy(config_page, mem.config_page, + min_t(u16, mem.config_page_sz, + sizeof(Mpi2BiosPage3_t))); + + if (mem.config_page_sz > ioc->config_page_sz) + _config_free_config_dma_memory(ioc, &mem); + + out: + mutex_unlock(&ioc->config_cmds.mutex); + return r; +} + +/** + * mpt2sas_config_get_iounit_pg0 - obtain iounit page 0 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + struct config_request mem; + + mutex_lock(&ioc->config_cmds.mutex); + memset(config_page, 0, sizeof(Mpi2IOUnitPage0_t)); + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; + mpi_request.Header.PageNumber = 0; + mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION; + mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (r) + goto out; + + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; + mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; + mpi_request.Header.PageType = mpi_reply->Header.PageType; + mpi_request.Header.PageLength = mpi_reply->Header.PageLength; + mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4; + if (mem.config_page_sz > ioc->config_page_sz) { + r = _config_alloc_config_dma_memory(ioc, &mem); + if (r) + goto out; + } else { + mem.config_page_dma = ioc->config_page_dma; + mem.config_page = ioc->config_page; + } + ioc->base_add_sg_single(&mpi_request.PageBufferSGE, + MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, + mem.config_page_dma); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (!r) + memcpy(config_page, mem.config_page, + min_t(u16, mem.config_page_sz, + sizeof(Mpi2IOUnitPage0_t))); + + if (mem.config_page_sz > ioc->config_page_sz) + _config_free_config_dma_memory(ioc, &mem); + + out: + mutex_unlock(&ioc->config_cmds.mutex); + return r; +} + +/** + * mpt2sas_config_get_iounit_pg1 - obtain iounit page 1 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + struct config_request mem; + + mutex_lock(&ioc->config_cmds.mutex); + memset(config_page, 0, sizeof(Mpi2IOUnitPage1_t)); + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; + mpi_request.Header.PageNumber = 1; + mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION; + mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (r) + goto out; + + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; + mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; + mpi_request.Header.PageType = mpi_reply->Header.PageType; + mpi_request.Header.PageLength = mpi_reply->Header.PageLength; + mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4; + if (mem.config_page_sz > ioc->config_page_sz) { + r = _config_alloc_config_dma_memory(ioc, &mem); + if (r) + goto out; + } else { + mem.config_page_dma = ioc->config_page_dma; + mem.config_page = ioc->config_page; + } + ioc->base_add_sg_single(&mpi_request.PageBufferSGE, + MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, + mem.config_page_dma); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (!r) + memcpy(config_page, mem.config_page, + min_t(u16, mem.config_page_sz, + sizeof(Mpi2IOUnitPage1_t))); + + if (mem.config_page_sz > ioc->config_page_sz) + _config_free_config_dma_memory(ioc, &mem); + + out: + mutex_unlock(&ioc->config_cmds.mutex); + return r; +} + +/** + * mpt2sas_config_set_iounit_pg1 - set iounit page 1 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t config_page) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + struct config_request mem; + + mutex_lock(&ioc->config_cmds.mutex); + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; + mpi_request.Header.PageNumber = 1; + mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION; + mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (r) + goto out; + + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; + mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; + mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; + mpi_request.Header.PageType = mpi_reply->Header.PageType; + mpi_request.Header.PageLength = mpi_reply->Header.PageLength; + mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4; + if (mem.config_page_sz > ioc->config_page_sz) { + r = _config_alloc_config_dma_memory(ioc, &mem); + if (r) + goto out; + } else { + mem.config_page_dma = ioc->config_page_dma; + mem.config_page = ioc->config_page; + } + + memset(mem.config_page, 0, mem.config_page_sz); + memcpy(mem.config_page, &config_page, + sizeof(Mpi2IOUnitPage1_t)); + + ioc->base_add_sg_single(&mpi_request.PageBufferSGE, + MPT2_CONFIG_COMMON_WRITE_SGLFLAGS | mem.config_page_sz, + mem.config_page_dma); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + + if (mem.config_page_sz > ioc->config_page_sz) + _config_free_config_dma_memory(ioc, &mem); + + out: + mutex_unlock(&ioc->config_cmds.mutex); + return r; +} + +/** + * mpt2sas_config_get_ioc_pg8 - obtain ioc page 8 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + struct config_request mem; + + mutex_lock(&ioc->config_cmds.mutex); + memset(config_page, 0, sizeof(Mpi2IOCPage8_t)); + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; + mpi_request.Header.PageNumber = 8; + mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; + mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (r) + goto out; + + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; + mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; + mpi_request.Header.PageType = mpi_reply->Header.PageType; + mpi_request.Header.PageLength = mpi_reply->Header.PageLength; + mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4; + if (mem.config_page_sz > ioc->config_page_sz) { + r = _config_alloc_config_dma_memory(ioc, &mem); + if (r) + goto out; + } else { + mem.config_page_dma = ioc->config_page_dma; + mem.config_page = ioc->config_page; + } + ioc->base_add_sg_single(&mpi_request.PageBufferSGE, + MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, + mem.config_page_dma); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (!r) + memcpy(config_page, mem.config_page, + min_t(u16, mem.config_page_sz, + sizeof(Mpi2IOCPage8_t))); + + if (mem.config_page_sz > ioc->config_page_sz) + _config_free_config_dma_memory(ioc, &mem); + + out: + mutex_unlock(&ioc->config_cmds.mutex); + return r; +} + +/** + * mpt2sas_config_get_sas_device_pg0 - obtain sas device page 0 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * @form: GET_NEXT_HANDLE or HANDLE + * @handle: device handle + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u32 handle) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + struct config_request mem; + + mutex_lock(&ioc->config_cmds.mutex); + memset(config_page, 0, sizeof(Mpi2SasDevicePage0_t)); + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; + mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; + mpi_request.Header.PageNumber = 0; + mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (r) + goto out; + + mpi_request.PageAddress = cpu_to_le32(form | handle); + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; + mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; + mpi_request.Header.PageType = mpi_reply->Header.PageType; + mpi_request.ExtPageLength = mpi_reply->ExtPageLength; + mpi_request.ExtPageType = mpi_reply->ExtPageType; + mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4; + if (mem.config_page_sz > ioc->config_page_sz) { + r = _config_alloc_config_dma_memory(ioc, &mem); + if (r) + goto out; + } else { + mem.config_page_dma = ioc->config_page_dma; + mem.config_page = ioc->config_page; + } + ioc->base_add_sg_single(&mpi_request.PageBufferSGE, + MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, + mem.config_page_dma); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (!r) + memcpy(config_page, mem.config_page, + min_t(u16, mem.config_page_sz, + sizeof(Mpi2SasDevicePage0_t))); + + if (mem.config_page_sz > ioc->config_page_sz) + _config_free_config_dma_memory(ioc, &mem); + + out: + mutex_unlock(&ioc->config_cmds.mutex); + return r; +} + +/** + * mpt2sas_config_get_sas_device_pg1 - obtain sas device page 1 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * @form: GET_NEXT_HANDLE or HANDLE + * @handle: device handle + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2SasDevicePage1_t *config_page, u32 form, u32 handle) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + struct config_request mem; + + mutex_lock(&ioc->config_cmds.mutex); + memset(config_page, 0, sizeof(Mpi2SasDevicePage1_t)); + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; + mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION; + mpi_request.Header.PageNumber = 1; + mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (r) + goto out; + + mpi_request.PageAddress = cpu_to_le32(form | handle); + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; + mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; + mpi_request.Header.PageType = mpi_reply->Header.PageType; + mpi_request.ExtPageLength = mpi_reply->ExtPageLength; + mpi_request.ExtPageType = mpi_reply->ExtPageType; + mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4; + if (mem.config_page_sz > ioc->config_page_sz) { + r = _config_alloc_config_dma_memory(ioc, &mem); + if (r) + goto out; + } else { + mem.config_page_dma = ioc->config_page_dma; + mem.config_page = ioc->config_page; + } + ioc->base_add_sg_single(&mpi_request.PageBufferSGE, + MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, + mem.config_page_dma); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (!r) + memcpy(config_page, mem.config_page, + min_t(u16, mem.config_page_sz, + sizeof(Mpi2SasDevicePage1_t))); + + if (mem.config_page_sz > ioc->config_page_sz) + _config_free_config_dma_memory(ioc, &mem); + + out: + mutex_unlock(&ioc->config_cmds.mutex); + return r; +} + +/** + * mpt2sas_config_get_number_hba_phys - obtain number of phys on the host + * @ioc: per adapter object + * @num_phys: pointer returned with the number of phys + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + struct config_request mem; + u16 ioc_status; + Mpi2ConfigReply_t mpi_reply; + Mpi2SasIOUnitPage0_t config_page; + + mutex_lock(&ioc->config_cmds.mutex); + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; + mpi_request.Header.PageNumber = 0; + mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION; + mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, &mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (r) + goto out; + + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + mpi_request.Header.PageVersion = mpi_reply.Header.PageVersion; + mpi_request.Header.PageNumber = mpi_reply.Header.PageNumber; + mpi_request.Header.PageType = mpi_reply.Header.PageType; + mpi_request.ExtPageLength = mpi_reply.ExtPageLength; + mpi_request.ExtPageType = mpi_reply.ExtPageType; + mem.config_page_sz = le16_to_cpu(mpi_reply.ExtPageLength) * 4; + if (mem.config_page_sz > ioc->config_page_sz) { + r = _config_alloc_config_dma_memory(ioc, &mem); + if (r) + goto out; + } else { + mem.config_page_dma = ioc->config_page_dma; + mem.config_page = ioc->config_page; + } + ioc->base_add_sg_single(&mpi_request.PageBufferSGE, + MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, + mem.config_page_dma); + r = _config_request(ioc, &mpi_request, &mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (!r) { + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { + memcpy(&config_page, mem.config_page, + min_t(u16, mem.config_page_sz, + sizeof(Mpi2SasIOUnitPage0_t))); + *num_phys = config_page.NumPhys; + } + } + + if (mem.config_page_sz > ioc->config_page_sz) + _config_free_config_dma_memory(ioc, &mem); + + out: + mutex_unlock(&ioc->config_cmds.mutex); + return r; +} + +/** + * mpt2sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * @sz: size of buffer passed in config_page + * Context: sleep. + * + * Calling function should call config_get_number_hba_phys prior to + * this function, so enough memory is allocated for config_page. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, u16 sz) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + struct config_request mem; + + mutex_lock(&ioc->config_cmds.mutex); + memset(config_page, 0, sz); + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; + mpi_request.Header.PageNumber = 0; + mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION; + mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (r) + goto out; + + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; + mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; + mpi_request.Header.PageType = mpi_reply->Header.PageType; + mpi_request.ExtPageLength = mpi_reply->ExtPageLength; + mpi_request.ExtPageType = mpi_reply->ExtPageType; + mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4; + if (mem.config_page_sz > ioc->config_page_sz) { + r = _config_alloc_config_dma_memory(ioc, &mem); + if (r) + goto out; + } else { + mem.config_page_dma = ioc->config_page_dma; + mem.config_page = ioc->config_page; + } + ioc->base_add_sg_single(&mpi_request.PageBufferSGE, + MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, + mem.config_page_dma); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (!r) + memcpy(config_page, mem.config_page, + min_t(u16, sz, mem.config_page_sz)); + + if (mem.config_page_sz > ioc->config_page_sz) + _config_free_config_dma_memory(ioc, &mem); + + out: + mutex_unlock(&ioc->config_cmds.mutex); + return r; +} + +/** + * mpt2sas_config_get_sas_iounit_pg1 - obtain sas iounit page 0 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * @sz: size of buffer passed in config_page + * Context: sleep. + * + * Calling function should call config_get_number_hba_phys prior to + * this function, so enough memory is allocated for config_page. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + struct config_request mem; + + mutex_lock(&ioc->config_cmds.mutex); + memset(config_page, 0, sz); + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; + mpi_request.Header.PageNumber = 1; + mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION; + mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (r) + goto out; + + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; + mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; + mpi_request.Header.PageType = mpi_reply->Header.PageType; + mpi_request.ExtPageLength = mpi_reply->ExtPageLength; + mpi_request.ExtPageType = mpi_reply->ExtPageType; + mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4; + if (mem.config_page_sz > ioc->config_page_sz) { + r = _config_alloc_config_dma_memory(ioc, &mem); + if (r) + goto out; + } else { + mem.config_page_dma = ioc->config_page_dma; + mem.config_page = ioc->config_page; + } + ioc->base_add_sg_single(&mpi_request.PageBufferSGE, + MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, + mem.config_page_dma); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (!r) + memcpy(config_page, mem.config_page, + min_t(u16, sz, mem.config_page_sz)); + + if (mem.config_page_sz > ioc->config_page_sz) + _config_free_config_dma_memory(ioc, &mem); + + out: + mutex_unlock(&ioc->config_cmds.mutex); + return r; +} + +/** + * mpt2sas_config_get_expander_pg0 - obtain expander page 0 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * @form: GET_NEXT_HANDLE or HANDLE + * @handle: expander handle + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + struct config_request mem; + + mutex_lock(&ioc->config_cmds.mutex); + memset(config_page, 0, sizeof(Mpi2ExpanderPage0_t)); + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER; + mpi_request.Header.PageNumber = 0; + mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION; + mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (r) + goto out; + + mpi_request.PageAddress = cpu_to_le32(form | handle); + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; + mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; + mpi_request.Header.PageType = mpi_reply->Header.PageType; + mpi_request.ExtPageLength = mpi_reply->ExtPageLength; + mpi_request.ExtPageType = mpi_reply->ExtPageType; + mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4; + if (mem.config_page_sz > ioc->config_page_sz) { + r = _config_alloc_config_dma_memory(ioc, &mem); + if (r) + goto out; + } else { + mem.config_page_dma = ioc->config_page_dma; + mem.config_page = ioc->config_page; + } + ioc->base_add_sg_single(&mpi_request.PageBufferSGE, + MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, + mem.config_page_dma); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (!r) + memcpy(config_page, mem.config_page, + min_t(u16, mem.config_page_sz, + sizeof(Mpi2ExpanderPage0_t))); + + if (mem.config_page_sz > ioc->config_page_sz) + _config_free_config_dma_memory(ioc, &mem); + + out: + mutex_unlock(&ioc->config_cmds.mutex); + return r; +} + +/** + * mpt2sas_config_get_expander_pg1 - obtain expander page 1 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * @phy_number: phy number + * @handle: expander handle + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number, + u16 handle) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + struct config_request mem; + + mutex_lock(&ioc->config_cmds.mutex); + memset(config_page, 0, sizeof(Mpi2ExpanderPage1_t)); + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER; + mpi_request.Header.PageNumber = 1; + mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION; + mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (r) + goto out; + + mpi_request.PageAddress = + cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM | + (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle); + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; + mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; + mpi_request.Header.PageType = mpi_reply->Header.PageType; + mpi_request.ExtPageLength = mpi_reply->ExtPageLength; + mpi_request.ExtPageType = mpi_reply->ExtPageType; + mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4; + if (mem.config_page_sz > ioc->config_page_sz) { + r = _config_alloc_config_dma_memory(ioc, &mem); + if (r) + goto out; + } else { + mem.config_page_dma = ioc->config_page_dma; + mem.config_page = ioc->config_page; + } + ioc->base_add_sg_single(&mpi_request.PageBufferSGE, + MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, + mem.config_page_dma); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (!r) + memcpy(config_page, mem.config_page, + min_t(u16, mem.config_page_sz, + sizeof(Mpi2ExpanderPage1_t))); + + if (mem.config_page_sz > ioc->config_page_sz) + _config_free_config_dma_memory(ioc, &mem); + + out: + mutex_unlock(&ioc->config_cmds.mutex); + return r; +} + +/** + * mpt2sas_config_get_enclosure_pg0 - obtain enclosure page 0 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * @form: GET_NEXT_HANDLE or HANDLE + * @handle: expander handle + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + struct config_request mem; + + mutex_lock(&ioc->config_cmds.mutex); + memset(config_page, 0, sizeof(Mpi2SasEnclosurePage0_t)); + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE; + mpi_request.Header.PageNumber = 0; + mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION; + mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (r) + goto out; + + mpi_request.PageAddress = cpu_to_le32(form | handle); + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; + mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; + mpi_request.Header.PageType = mpi_reply->Header.PageType; + mpi_request.ExtPageLength = mpi_reply->ExtPageLength; + mpi_request.ExtPageType = mpi_reply->ExtPageType; + mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4; + if (mem.config_page_sz > ioc->config_page_sz) { + r = _config_alloc_config_dma_memory(ioc, &mem); + if (r) + goto out; + } else { + mem.config_page_dma = ioc->config_page_dma; + mem.config_page = ioc->config_page; + } + ioc->base_add_sg_single(&mpi_request.PageBufferSGE, + MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, + mem.config_page_dma); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (!r) + memcpy(config_page, mem.config_page, + min_t(u16, mem.config_page_sz, + sizeof(Mpi2SasEnclosurePage0_t))); + + if (mem.config_page_sz > ioc->config_page_sz) + _config_free_config_dma_memory(ioc, &mem); + + out: + mutex_unlock(&ioc->config_cmds.mutex); + return r; +} + +/** + * mpt2sas_config_get_phy_pg0 - obtain phy page 0 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * @phy_number: phy number + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + struct config_request mem; + + mutex_lock(&ioc->config_cmds.mutex); + memset(config_page, 0, sizeof(Mpi2SasPhyPage0_t)); + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY; + mpi_request.Header.PageNumber = 0; + mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION; + mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (r) + goto out; + + mpi_request.PageAddress = + cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number); + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; + mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; + mpi_request.Header.PageType = mpi_reply->Header.PageType; + mpi_request.ExtPageLength = mpi_reply->ExtPageLength; + mpi_request.ExtPageType = mpi_reply->ExtPageType; + mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4; + if (mem.config_page_sz > ioc->config_page_sz) { + r = _config_alloc_config_dma_memory(ioc, &mem); + if (r) + goto out; + } else { + mem.config_page_dma = ioc->config_page_dma; + mem.config_page = ioc->config_page; + } + ioc->base_add_sg_single(&mpi_request.PageBufferSGE, + MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, + mem.config_page_dma); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (!r) + memcpy(config_page, mem.config_page, + min_t(u16, mem.config_page_sz, + sizeof(Mpi2SasPhyPage0_t))); + + if (mem.config_page_sz > ioc->config_page_sz) + _config_free_config_dma_memory(ioc, &mem); + + out: + mutex_unlock(&ioc->config_cmds.mutex); + return r; +} + +/** + * mpt2sas_config_get_phy_pg1 - obtain phy page 1 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * @phy_number: phy number + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + struct config_request mem; + + mutex_lock(&ioc->config_cmds.mutex); + memset(config_page, 0, sizeof(Mpi2SasPhyPage1_t)); + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY; + mpi_request.Header.PageNumber = 1; + mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION; + mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (r) + goto out; + + mpi_request.PageAddress = + cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number); + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; + mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; + mpi_request.Header.PageType = mpi_reply->Header.PageType; + mpi_request.ExtPageLength = mpi_reply->ExtPageLength; + mpi_request.ExtPageType = mpi_reply->ExtPageType; + mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4; + if (mem.config_page_sz > ioc->config_page_sz) { + r = _config_alloc_config_dma_memory(ioc, &mem); + if (r) + goto out; + } else { + mem.config_page_dma = ioc->config_page_dma; + mem.config_page = ioc->config_page; + } + ioc->base_add_sg_single(&mpi_request.PageBufferSGE, + MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, + mem.config_page_dma); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (!r) + memcpy(config_page, mem.config_page, + min_t(u16, mem.config_page_sz, + sizeof(Mpi2SasPhyPage1_t))); + + if (mem.config_page_sz > ioc->config_page_sz) + _config_free_config_dma_memory(ioc, &mem); + + out: + mutex_unlock(&ioc->config_cmds.mutex); + return r; +} + +/** + * mpt2sas_config_get_raid_volume_pg1 - obtain raid volume page 1 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * @form: GET_NEXT_HANDLE or HANDLE + * @handle: volume handle + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, + u32 handle) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + struct config_request mem; + + mutex_lock(&ioc->config_cmds.mutex); + memset(config_page, 0, sizeof(Mpi2RaidVolPage1_t)); + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; + mpi_request.Header.PageNumber = 1; + mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION; + mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (r) + goto out; + + mpi_request.PageAddress = cpu_to_le32(form | handle); + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; + mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; + mpi_request.Header.PageType = mpi_reply->Header.PageType; + mpi_request.Header.PageLength = mpi_reply->Header.PageLength; + mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4; + if (mem.config_page_sz > ioc->config_page_sz) { + r = _config_alloc_config_dma_memory(ioc, &mem); + if (r) + goto out; + } else { + mem.config_page_dma = ioc->config_page_dma; + mem.config_page = ioc->config_page; + } + ioc->base_add_sg_single(&mpi_request.PageBufferSGE, + MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, + mem.config_page_dma); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (!r) + memcpy(config_page, mem.config_page, + min_t(u16, mem.config_page_sz, + sizeof(Mpi2RaidVolPage1_t))); + + if (mem.config_page_sz > ioc->config_page_sz) + _config_free_config_dma_memory(ioc, &mem); + + out: + mutex_unlock(&ioc->config_cmds.mutex); + return r; +} + +/** + * mpt2sas_config_get_number_pds - obtain number of phys disk assigned to volume + * @ioc: per adapter object + * @handle: volume handle + * @num_pds: returns pds count + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle, + u8 *num_pds) +{ + Mpi2ConfigRequest_t mpi_request; + Mpi2RaidVolPage0_t *config_page; + Mpi2ConfigReply_t mpi_reply; + int r; + struct config_request mem; + u16 ioc_status; + + mutex_lock(&ioc->config_cmds.mutex); + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + *num_pds = 0; + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; + mpi_request.Header.PageNumber = 0; + mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; + mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, &mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (r) + goto out; + + mpi_request.PageAddress = + cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle); + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + mpi_request.Header.PageVersion = mpi_reply.Header.PageVersion; + mpi_request.Header.PageNumber = mpi_reply.Header.PageNumber; + mpi_request.Header.PageType = mpi_reply.Header.PageType; + mpi_request.Header.PageLength = mpi_reply.Header.PageLength; + mem.config_page_sz = le16_to_cpu(mpi_reply.Header.PageLength) * 4; + if (mem.config_page_sz > ioc->config_page_sz) { + r = _config_alloc_config_dma_memory(ioc, &mem); + if (r) + goto out; + } else { + mem.config_page_dma = ioc->config_page_dma; + mem.config_page = ioc->config_page; + } + ioc->base_add_sg_single(&mpi_request.PageBufferSGE, + MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, + mem.config_page_dma); + r = _config_request(ioc, &mpi_request, &mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (!r) { + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { + config_page = mem.config_page; + *num_pds = config_page->NumPhysDisks; + } + } + + if (mem.config_page_sz > ioc->config_page_sz) + _config_free_config_dma_memory(ioc, &mem); + + out: + mutex_unlock(&ioc->config_cmds.mutex); + return r; +} + +/** + * mpt2sas_config_get_raid_volume_pg0 - obtain raid volume page 0 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * @form: GET_NEXT_HANDLE or HANDLE + * @handle: volume handle + * @sz: size of buffer passed in config_page + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form, + u32 handle, u16 sz) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + struct config_request mem; + + mutex_lock(&ioc->config_cmds.mutex); + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + memset(config_page, 0, sz); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; + mpi_request.Header.PageNumber = 0; + mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; + mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (r) + goto out; + + mpi_request.PageAddress = cpu_to_le32(form | handle); + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; + mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; + mpi_request.Header.PageType = mpi_reply->Header.PageType; + mpi_request.Header.PageLength = mpi_reply->Header.PageLength; + mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4; + if (mem.config_page_sz > ioc->config_page_sz) { + r = _config_alloc_config_dma_memory(ioc, &mem); + if (r) + goto out; + } else { + mem.config_page_dma = ioc->config_page_dma; + mem.config_page = ioc->config_page; + } + ioc->base_add_sg_single(&mpi_request.PageBufferSGE, + MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, + mem.config_page_dma); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (!r) + memcpy(config_page, mem.config_page, + min_t(u16, sz, mem.config_page_sz)); + + if (mem.config_page_sz > ioc->config_page_sz) + _config_free_config_dma_memory(ioc, &mem); + + out: + mutex_unlock(&ioc->config_cmds.mutex); + return r; +} + +/** + * mpt2sas_config_get_phys_disk_pg0 - obtain phys disk page 0 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE + * @form_specific: specific to the form + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t + *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form, + u32 form_specific) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + struct config_request mem; + + mutex_lock(&ioc->config_cmds.mutex); + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + memset(config_page, 0, sizeof(Mpi2RaidPhysDiskPage0_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; + mpi_request.Header.PageNumber = 0; + mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION; + mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (r) + goto out; + + mpi_request.PageAddress = cpu_to_le32(form | form_specific); + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; + mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; + mpi_request.Header.PageType = mpi_reply->Header.PageType; + mpi_request.Header.PageLength = mpi_reply->Header.PageLength; + mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4; + if (mem.config_page_sz > ioc->config_page_sz) { + r = _config_alloc_config_dma_memory(ioc, &mem); + if (r) + goto out; + } else { + mem.config_page_dma = ioc->config_page_dma; + mem.config_page = ioc->config_page; + } + ioc->base_add_sg_single(&mpi_request.PageBufferSGE, + MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, + mem.config_page_dma); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (!r) + memcpy(config_page, mem.config_page, + min_t(u16, mem.config_page_sz, + sizeof(Mpi2RaidPhysDiskPage0_t))); + + if (mem.config_page_sz > ioc->config_page_sz) + _config_free_config_dma_memory(ioc, &mem); + + out: + mutex_unlock(&ioc->config_cmds.mutex); + return r; +} + +/** + * mpt2sas_config_get_volume_handle - returns volume handle for give hidden raid components + * @ioc: per adapter object + * @pd_handle: phys disk handle + * @volume_handle: volume handle + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle, + u16 *volume_handle) +{ + Mpi2RaidConfigurationPage0_t *config_page; + Mpi2ConfigRequest_t mpi_request; + Mpi2ConfigReply_t mpi_reply; + int r, i; + struct config_request mem; + u16 ioc_status; + + mutex_lock(&ioc->config_cmds.mutex); + *volume_handle = 0; + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG; + mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION; + mpi_request.Header.PageNumber = 0; + mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, &mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (r) + goto out; + + mpi_request.PageAddress = + cpu_to_le32(MPI2_RAID_PGAD_FORM_ACTIVE_CONFIG); + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + mpi_request.Header.PageVersion = mpi_reply.Header.PageVersion; + mpi_request.Header.PageNumber = mpi_reply.Header.PageNumber; + mpi_request.Header.PageType = mpi_reply.Header.PageType; + mpi_request.ExtPageLength = mpi_reply.ExtPageLength; + mpi_request.ExtPageType = mpi_reply.ExtPageType; + mem.config_page_sz = le16_to_cpu(mpi_reply.ExtPageLength) * 4; + if (mem.config_page_sz > ioc->config_page_sz) { + r = _config_alloc_config_dma_memory(ioc, &mem); + if (r) + goto out; + } else { + mem.config_page_dma = ioc->config_page_dma; + mem.config_page = ioc->config_page; + } + ioc->base_add_sg_single(&mpi_request.PageBufferSGE, + MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, + mem.config_page_dma); + r = _config_request(ioc, &mpi_request, &mpi_reply, + MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); + if (r) + goto out; + + r = -1; + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) + goto done; + config_page = mem.config_page; + for (i = 0; i < config_page->NumElements; i++) { + if ((config_page->ConfigElement[i].ElementFlags & + MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE) != + MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT) + continue; + if (config_page->ConfigElement[i].PhysDiskDevHandle == + pd_handle) { + *volume_handle = le16_to_cpu(config_page-> + ConfigElement[i].VolDevHandle); + r = 0; + goto done; + } + } + + done: + if (mem.config_page_sz > ioc->config_page_sz) + _config_free_config_dma_memory(ioc, &mem); + + out: + mutex_unlock(&ioc->config_cmds.mutex); + return r; +} + +/** + * mpt2sas_config_get_volume_wwid - returns wwid given the volume handle + * @ioc: per adapter object + * @volume_handle: volume handle + * @wwid: volume wwid + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_config_get_volume_wwid(struct MPT2SAS_ADAPTER *ioc, u16 volume_handle, + u64 *wwid) +{ + Mpi2ConfigReply_t mpi_reply; + Mpi2RaidVolPage1_t raid_vol_pg1; + + *wwid = 0; + if (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply, + &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, + volume_handle))) { + *wwid = le64_to_cpu(raid_vol_pg1.WWID); + return 0; + } else + return -1; +} diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c new file mode 100644 index 00000000000..4fbe3f83319 --- /dev/null +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c @@ -0,0 +1,2516 @@ +/* + * Management Module Support for MPT (Message Passing Technology) based + * controllers + * + * This code is based on drivers/scsi/mpt2sas/mpt2_ctl.c + * Copyright (C) 2007-2008 LSI Corporation + * (mailto:DL-MPTFusionLinux@lsi.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * NO WARRANTY + * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT + * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is + * solely responsible for determining the appropriateness of using and + * distributing the Program and assumes all risks associated with its + * exercise of rights under this Agreement, including but not limited to + * the risks and costs of program errors, damage to or loss of data, + * programs or equipment, and unavailability or interruption of operations. + + * DISCLAIMER OF LIABILITY + * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED + * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "mpt2sas_base.h" +#include "mpt2sas_ctl.h" + +static struct fasync_struct *async_queue; +static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait); + +/** + * enum block_state - blocking state + * @NON_BLOCKING: non blocking + * @BLOCKING: blocking + * + * These states are for ioctls that need to wait for a response + * from firmware, so they probably require sleep. + */ +enum block_state { + NON_BLOCKING, + BLOCKING, +}; + +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING +/** + * _ctl_display_some_debug - debug routine + * @ioc: per adapter object + * @smid: system request message index + * @calling_function_name: string pass from calling function + * @mpi_reply: reply message frame + * Context: none. + * + * Function for displaying debug info helpfull when debugging issues + * in this module. + */ +static void +_ctl_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid, + char *calling_function_name, MPI2DefaultReply_t *mpi_reply) +{ + Mpi2ConfigRequest_t *mpi_request; + char *desc = NULL; + + if (!(ioc->logging_level & MPT_DEBUG_IOCTL)) + return; + + mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); + switch (mpi_request->Function) { + case MPI2_FUNCTION_SCSI_IO_REQUEST: + { + Mpi2SCSIIORequest_t *scsi_request = + (Mpi2SCSIIORequest_t *)mpi_request; + + snprintf(ioc->tmp_string, MPT_STRING_LENGTH, + "scsi_io, cmd(0x%02x), cdb_len(%d)", + scsi_request->CDB.CDB32[0], + le16_to_cpu(scsi_request->IoFlags) & 0xF); + desc = ioc->tmp_string; + break; + } + case MPI2_FUNCTION_SCSI_TASK_MGMT: + desc = "task_mgmt"; + break; + case MPI2_FUNCTION_IOC_INIT: + desc = "ioc_init"; + break; + case MPI2_FUNCTION_IOC_FACTS: + desc = "ioc_facts"; + break; + case MPI2_FUNCTION_CONFIG: + { + Mpi2ConfigRequest_t *config_request = + (Mpi2ConfigRequest_t *)mpi_request; + + snprintf(ioc->tmp_string, MPT_STRING_LENGTH, + "config, type(0x%02x), ext_type(0x%02x), number(%d)", + (config_request->Header.PageType & + MPI2_CONFIG_PAGETYPE_MASK), config_request->ExtPageType, + config_request->Header.PageNumber); + desc = ioc->tmp_string; + break; + } + case MPI2_FUNCTION_PORT_FACTS: + desc = "port_facts"; + break; + case MPI2_FUNCTION_PORT_ENABLE: + desc = "port_enable"; + break; + case MPI2_FUNCTION_EVENT_NOTIFICATION: + desc = "event_notification"; + break; + case MPI2_FUNCTION_FW_DOWNLOAD: + desc = "fw_download"; + break; + case MPI2_FUNCTION_FW_UPLOAD: + desc = "fw_upload"; + break; + case MPI2_FUNCTION_RAID_ACTION: + desc = "raid_action"; + break; + case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH: + { + Mpi2SCSIIORequest_t *scsi_request = + (Mpi2SCSIIORequest_t *)mpi_request; + + snprintf(ioc->tmp_string, MPT_STRING_LENGTH, + "raid_pass, cmd(0x%02x), cdb_len(%d)", + scsi_request->CDB.CDB32[0], + le16_to_cpu(scsi_request->IoFlags) & 0xF); + desc = ioc->tmp_string; + break; + } + case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL: + desc = "sas_iounit_cntl"; + break; + case MPI2_FUNCTION_SATA_PASSTHROUGH: + desc = "sata_pass"; + break; + case MPI2_FUNCTION_DIAG_BUFFER_POST: + desc = "diag_buffer_post"; + break; + case MPI2_FUNCTION_DIAG_RELEASE: + desc = "diag_release"; + break; + case MPI2_FUNCTION_SMP_PASSTHROUGH: + desc = "smp_passthrough"; + break; + } + + if (!desc) + return; + + printk(MPT2SAS_DEBUG_FMT "%s: %s, smid(%d)\n", + ioc->name, calling_function_name, desc, smid); + + if (!mpi_reply) + return; + + if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo) + printk(MPT2SAS_DEBUG_FMT + "\tiocstatus(0x%04x), loginfo(0x%08x)\n", + ioc->name, le16_to_cpu(mpi_reply->IOCStatus), + le32_to_cpu(mpi_reply->IOCLogInfo)); + + if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || + mpi_request->Function == + MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) { + Mpi2SCSIIOReply_t *scsi_reply = + (Mpi2SCSIIOReply_t *)mpi_reply; + if (scsi_reply->SCSIState || scsi_reply->SCSIStatus) + printk(MPT2SAS_DEBUG_FMT + "\tscsi_state(0x%02x), scsi_status" + "(0x%02x)\n", ioc->name, + scsi_reply->SCSIState, + scsi_reply->SCSIStatus); + } +} +#endif + +/** + * mpt2sas_ctl_done - ctl module completion routine + * @ioc: per adapter object + * @smid: system request message index + * @VF_ID: virtual function id + * @reply: reply message frame(lower 32bit addr) + * Context: none. + * + * The callback handler when using ioc->ctl_cb_idx. + * + * Return nothing. + */ +void +mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) +{ + MPI2DefaultReply_t *mpi_reply; + + if (ioc->ctl_cmds.status == MPT2_CMD_NOT_USED) + return; + if (ioc->ctl_cmds.smid != smid) + return; + ioc->ctl_cmds.status |= MPT2_CMD_COMPLETE; + mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); + if (mpi_reply) { + memcpy(ioc->ctl_cmds.reply, mpi_reply, mpi_reply->MsgLength*4); + ioc->ctl_cmds.status |= MPT2_CMD_REPLY_VALID; + } +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING + _ctl_display_some_debug(ioc, smid, "ctl_done", mpi_reply); +#endif + ioc->ctl_cmds.status &= ~MPT2_CMD_PENDING; + complete(&ioc->ctl_cmds.done); +} + +/** + * _ctl_check_event_type - determines when an event needs logging + * @ioc: per adapter object + * @event: firmware event + * + * The bitmask in ioc->event_type[] indicates which events should be + * be saved in the driver event_log. This bitmask is set by application. + * + * Returns 1 when event should be captured, or zero means no match. + */ +static int +_ctl_check_event_type(struct MPT2SAS_ADAPTER *ioc, u16 event) +{ + u16 i; + u32 desired_event; + + if (event >= 128 || !event || !ioc->event_log) + return 0; + + desired_event = (1 << (event % 32)); + if (!desired_event) + desired_event = 1; + i = event / 32; + return desired_event & ioc->event_type[i]; +} + +/** + * mpt2sas_ctl_add_to_event_log - add event + * @ioc: per adapter object + * @mpi_reply: reply message frame + * + * Return nothing. + */ +void +mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc, + Mpi2EventNotificationReply_t *mpi_reply) +{ + struct MPT2_IOCTL_EVENTS *event_log; + u16 event; + int i; + u32 sz, event_data_sz; + u8 send_aen = 0; + + if (!ioc->event_log) + return; + + event = le16_to_cpu(mpi_reply->Event); + + if (_ctl_check_event_type(ioc, event)) { + + /* insert entry into circular event_log */ + i = ioc->event_context % MPT2SAS_CTL_EVENT_LOG_SIZE; + event_log = ioc->event_log; + event_log[i].event = event; + event_log[i].context = ioc->event_context++; + + event_data_sz = le16_to_cpu(mpi_reply->EventDataLength)*4; + sz = min_t(u32, event_data_sz, MPT2_EVENT_DATA_SIZE); + memset(event_log[i].data, 0, MPT2_EVENT_DATA_SIZE); + memcpy(event_log[i].data, mpi_reply->EventData, sz); + send_aen = 1; + } + + /* This aen_event_read_flag flag is set until the + * application has read the event log. + * For MPI2_EVENT_LOG_ENTRY_ADDED, we always notify. + */ + if (event == MPI2_EVENT_LOG_ENTRY_ADDED || + (send_aen && !ioc->aen_event_read_flag)) { + ioc->aen_event_read_flag = 1; + wake_up_interruptible(&ctl_poll_wait); + if (async_queue) + kill_fasync(&async_queue, SIGIO, POLL_IN); + } +} + +/** + * mpt2sas_ctl_event_callback - firmware event handler (called at ISR time) + * @ioc: per adapter object + * @VF_ID: virtual function id + * @reply: reply message frame(lower 32bit addr) + * Context: interrupt. + * + * This function merely adds a new work task into ioc->firmware_event_thread. + * The tasks are worked from _firmware_event_work in user context. + * + * Return nothing. + */ +void +mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply) +{ + Mpi2EventNotificationReply_t *mpi_reply; + + mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); + mpt2sas_ctl_add_to_event_log(ioc, mpi_reply); +} + +/** + * _ctl_verify_adapter - validates ioc_number passed from application + * @ioc: per adapter object + * @iocpp: The ioc pointer is returned in this. + * + * Return (-1) means error, else ioc_number. + */ +static int +_ctl_verify_adapter(int ioc_number, struct MPT2SAS_ADAPTER **iocpp) +{ + struct MPT2SAS_ADAPTER *ioc; + + list_for_each_entry(ioc, &ioc_list, list) { + if (ioc->id != ioc_number) + continue; + *iocpp = ioc; + return ioc_number; + } + *iocpp = NULL; + return -1; +} + +/** + * mpt2sas_ctl_reset_handler - reset callback handler (for ctl) + * @ioc: per adapter object + * @reset_phase: phase + * + * The handler for doing any required cleanup or initialization. + * + * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET, + * MPT2_IOC_DONE_RESET + */ +void +mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) +{ + switch (reset_phase) { + case MPT2_IOC_PRE_RESET: + dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + "MPT2_IOC_PRE_RESET\n", ioc->name, __func__)); + break; + case MPT2_IOC_AFTER_RESET: + dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__)); + if (ioc->ctl_cmds.status & MPT2_CMD_PENDING) { + ioc->ctl_cmds.status |= MPT2_CMD_RESET; + mpt2sas_base_free_smid(ioc, ioc->ctl_cmds.smid); + complete(&ioc->ctl_cmds.done); + } + break; + case MPT2_IOC_DONE_RESET: + dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); + break; + } +} + +/** + * _ctl_fasync - + * @fd - + * @filep - + * @mode - + * + * Called when application request fasyn callback handler. + */ +static int +_ctl_fasync(int fd, struct file *filep, int mode) +{ + return fasync_helper(fd, filep, mode, &async_queue); +} + +/** + * _ctl_release - + * @inode - + * @filep - + * + * Called when application releases the fasyn callback handler. + */ +static int +_ctl_release(struct inode *inode, struct file *filep) +{ + return fasync_helper(-1, filep, 0, &async_queue); +} + +/** + * _ctl_poll - + * @file - + * @wait - + * + */ +static unsigned int +_ctl_poll(struct file *filep, poll_table *wait) +{ + struct MPT2SAS_ADAPTER *ioc; + + poll_wait(filep, &ctl_poll_wait, wait); + + list_for_each_entry(ioc, &ioc_list, list) { + if (ioc->aen_event_read_flag) + return POLLIN | POLLRDNORM; + } + return 0; +} + +/** + * _ctl_do_task_abort - assign an active smid to the abort_task + * @ioc: per adapter object + * @karg - (struct mpt2_ioctl_command) + * @tm_request - pointer to mf from user space + * + * Returns 0 when an smid if found, else fail. + * during failure, the reply frame is filled. + */ +static int +_ctl_do_task_abort(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command *karg, + Mpi2SCSITaskManagementRequest_t *tm_request) +{ + u8 found = 0; + u16 i; + u16 handle; + struct scsi_cmnd *scmd; + struct MPT2SAS_DEVICE *priv_data; + unsigned long flags; + Mpi2SCSITaskManagementReply_t *tm_reply; + u32 sz; + u32 lun; + + lun = scsilun_to_int((struct scsi_lun *)tm_request->LUN); + + handle = le16_to_cpu(tm_request->DevHandle); + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); + for (i = ioc->request_depth; i && !found; i--) { + scmd = ioc->scsi_lookup[i - 1].scmd; + if (scmd == NULL || scmd->device == NULL || + scmd->device->hostdata == NULL) + continue; + if (lun != scmd->device->lun) + continue; + priv_data = scmd->device->hostdata; + if (priv_data->sas_target == NULL) + continue; + if (priv_data->sas_target->handle != handle) + continue; + tm_request->TaskMID = cpu_to_le16(ioc->scsi_lookup[i - 1].smid); + found = 1; + } + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); + + if (!found) { + dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "ABORT_TASK: " + "DevHandle(0x%04x), lun(%d), no active mid!!\n", ioc->name, + tm_request->DevHandle, lun)); + tm_reply = ioc->ctl_cmds.reply; + tm_reply->DevHandle = tm_request->DevHandle; + tm_reply->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; + tm_reply->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK; + tm_reply->MsgLength = sizeof(Mpi2SCSITaskManagementReply_t)/4; + tm_reply->VP_ID = tm_request->VP_ID; + tm_reply->VF_ID = tm_request->VF_ID; + sz = min_t(u32, karg->max_reply_bytes, ioc->reply_sz); + if (copy_to_user(karg->reply_frame_buf_ptr, ioc->ctl_cmds.reply, + sz)) + printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, + __LINE__, __func__); + return 1; + } + + dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "ABORT_TASK: " + "DevHandle(0x%04x), lun(%d), smid(%d)\n", ioc->name, + tm_request->DevHandle, lun, tm_request->TaskMID)); + return 0; +} + +/** + * _ctl_do_mpt_command - main handler for MPT2COMMAND opcode + * @ioc: per adapter object + * @karg - (struct mpt2_ioctl_command) + * @mf - pointer to mf in user space + * @state - NON_BLOCKING or BLOCKING + */ +static long +_ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, + struct mpt2_ioctl_command karg, void __user *mf, enum block_state state) +{ + MPI2RequestHeader_t *mpi_request; + MPI2DefaultReply_t *mpi_reply; + u32 ioc_state; + u16 ioc_status; + u16 smid; + unsigned long timeout, timeleft; + u8 issue_reset; + u32 sz; + void *psge; + void *priv_sense = NULL; + void *data_out = NULL; + dma_addr_t data_out_dma; + size_t data_out_sz = 0; + void *data_in = NULL; + dma_addr_t data_in_dma; + size_t data_in_sz = 0; + u32 sgl_flags; + long ret; + u16 wait_state_count; + + issue_reset = 0; + + if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex)) + return -EAGAIN; + else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) + return -ERESTARTSYS; + + if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) { + printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n", + ioc->name, __func__); + ret = -EAGAIN; + goto out; + } + + wait_state_count = 0; + ioc_state = mpt2sas_base_get_iocstate(ioc, 1); + while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { + if (wait_state_count++ == 10) { + printk(MPT2SAS_ERR_FMT + "%s: failed due to ioc not operational\n", + ioc->name, __func__); + ret = -EFAULT; + goto out; + } + ssleep(1); + ioc_state = mpt2sas_base_get_iocstate(ioc, 1); + printk(MPT2SAS_INFO_FMT "%s: waiting for " + "operational state(count=%d)\n", ioc->name, + __func__, wait_state_count); + } + if (wait_state_count) + printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n", + ioc->name, __func__); + + smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx); + if (!smid) { + printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", + ioc->name, __func__); + ret = -EAGAIN; + goto out; + } + + ret = 0; + ioc->ctl_cmds.status = MPT2_CMD_PENDING; + memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); + mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); + ioc->ctl_cmds.smid = smid; + data_out_sz = karg.data_out_size; + data_in_sz = karg.data_in_size; + + /* copy in request message frame from user */ + if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, __LINE__, + __func__); + ret = -EFAULT; + mpt2sas_base_free_smid(ioc, smid); + goto out; + } + + if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || + mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) { + if (!mpi_request->FunctionDependent1 || + mpi_request->FunctionDependent1 > + cpu_to_le16(ioc->facts.MaxDevHandle)) { + ret = -EINVAL; + mpt2sas_base_free_smid(ioc, smid); + goto out; + } + } + + /* obtain dma-able memory for data transfer */ + if (data_out_sz) /* WRITE */ { + data_out = pci_alloc_consistent(ioc->pdev, data_out_sz, + &data_out_dma); + if (!data_out) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, + __LINE__, __func__); + ret = -ENOMEM; + mpt2sas_base_free_smid(ioc, smid); + goto out; + } + if (copy_from_user(data_out, karg.data_out_buf_ptr, + data_out_sz)) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, + __LINE__, __func__); + ret = -EFAULT; + mpt2sas_base_free_smid(ioc, smid); + goto out; + } + } + + if (data_in_sz) /* READ */ { + data_in = pci_alloc_consistent(ioc->pdev, data_in_sz, + &data_in_dma); + if (!data_in) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, + __LINE__, __func__); + ret = -ENOMEM; + mpt2sas_base_free_smid(ioc, smid); + goto out; + } + } + + /* add scatter gather elements */ + psge = (void *)mpi_request + (karg.data_sge_offset*4); + + if (!data_out_sz && !data_in_sz) { + mpt2sas_base_build_zero_len_sge(ioc, psge); + } else if (data_out_sz && data_in_sz) { + /* WRITE sgel first */ + sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | + MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC); + sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; + ioc->base_add_sg_single(psge, sgl_flags | + data_out_sz, data_out_dma); + + /* incr sgel */ + psge += ioc->sge_size; + + /* READ sgel last */ + sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | + MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | + MPI2_SGE_FLAGS_END_OF_LIST); + sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; + ioc->base_add_sg_single(psge, sgl_flags | + data_in_sz, data_in_dma); + } else if (data_out_sz) /* WRITE */ { + sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | + MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | + MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC); + sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; + ioc->base_add_sg_single(psge, sgl_flags | + data_out_sz, data_out_dma); + } else if (data_in_sz) /* READ */ { + sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | + MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | + MPI2_SGE_FLAGS_END_OF_LIST); + sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; + ioc->base_add_sg_single(psge, sgl_flags | + data_in_sz, data_in_dma); + } + + /* send command to firmware */ +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING + _ctl_display_some_debug(ioc, smid, "ctl_request", NULL); +#endif + + switch (mpi_request->Function) { + case MPI2_FUNCTION_SCSI_IO_REQUEST: + case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH: + { + Mpi2SCSIIORequest_t *scsiio_request = + (Mpi2SCSIIORequest_t *)mpi_request; + scsiio_request->SenseBufferLowAddress = + (u32)mpt2sas_base_get_sense_buffer_dma(ioc, smid); + priv_sense = mpt2sas_base_get_sense_buffer(ioc, smid); + memset(priv_sense, 0, SCSI_SENSE_BUFFERSIZE); + mpt2sas_base_put_smid_scsi_io(ioc, smid, 0, + le16_to_cpu(mpi_request->FunctionDependent1)); + break; + } + case MPI2_FUNCTION_SCSI_TASK_MGMT: + { + Mpi2SCSITaskManagementRequest_t *tm_request = + (Mpi2SCSITaskManagementRequest_t *)mpi_request; + + if (tm_request->TaskType == + MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { + if (_ctl_do_task_abort(ioc, &karg, tm_request)) + goto out; + } + + mutex_lock(&ioc->tm_cmds.mutex); + mpt2sas_scsih_set_tm_flag(ioc, le16_to_cpu( + tm_request->DevHandle)); + mpt2sas_base_put_smid_hi_priority(ioc, smid, + mpi_request->VF_ID); + break; + } + case MPI2_FUNCTION_SMP_PASSTHROUGH: + { + Mpi2SmpPassthroughRequest_t *smp_request = + (Mpi2SmpPassthroughRequest_t *)mpi_request; + u8 *data; + + /* ioc determines which port to use */ + smp_request->PhysicalPort = 0xFF; + if (smp_request->PassthroughFlags & + MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE) + data = (u8 *)&smp_request->SGL; + else + data = data_out; + + if (data[1] == 0x91 && (data[10] == 1 || data[10] == 2)) { + ioc->ioc_link_reset_in_progress = 1; + ioc->ignore_loginfos = 1; + } + mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); + break; + } + case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL: + { + Mpi2SasIoUnitControlRequest_t *sasiounit_request = + (Mpi2SasIoUnitControlRequest_t *)mpi_request; + + if (sasiounit_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET + || sasiounit_request->Operation == + MPI2_SAS_OP_PHY_LINK_RESET) { + ioc->ioc_link_reset_in_progress = 1; + ioc->ignore_loginfos = 1; + } + mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); + break; + } + default: + mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); + break; + } + + if (karg.timeout < MPT2_IOCTL_DEFAULT_TIMEOUT) + timeout = MPT2_IOCTL_DEFAULT_TIMEOUT; + else + timeout = karg.timeout; + timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, + timeout*HZ); + if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) { + Mpi2SCSITaskManagementRequest_t *tm_request = + (Mpi2SCSITaskManagementRequest_t *)mpi_request; + mutex_unlock(&ioc->tm_cmds.mutex); + mpt2sas_scsih_clear_tm_flag(ioc, le16_to_cpu( + tm_request->DevHandle)); + } else if ((mpi_request->Function == MPI2_FUNCTION_SMP_PASSTHROUGH || + mpi_request->Function == MPI2_FUNCTION_SAS_IO_UNIT_CONTROL) && + ioc->ioc_link_reset_in_progress) { + ioc->ioc_link_reset_in_progress = 0; + ioc->ignore_loginfos = 0; + } + if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) { + printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name, + __func__); + _debug_dump_mf(mpi_request, karg.data_sge_offset); + if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET)) + issue_reset = 1; + goto issue_host_reset; + } + + mpi_reply = ioc->ctl_cmds.reply; + ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; + +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING + if (mpi_reply->Function == MPI2_FUNCTION_SCSI_TASK_MGMT && + (ioc->logging_level & MPT_DEBUG_TM)) { + Mpi2SCSITaskManagementReply_t *tm_reply = + (Mpi2SCSITaskManagementReply_t *)mpi_reply; + + printk(MPT2SAS_DEBUG_FMT "TASK_MGMT: " + "IOCStatus(0x%04x), IOCLogInfo(0x%08x), " + "TerminationCount(0x%08x)\n", ioc->name, + tm_reply->IOCStatus, tm_reply->IOCLogInfo, + tm_reply->TerminationCount); + } +#endif + /* copy out xdata to user */ + if (data_in_sz) { + if (copy_to_user(karg.data_in_buf_ptr, data_in, + data_in_sz)) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, + __LINE__, __func__); + ret = -ENODATA; + goto out; + } + } + + /* copy out reply message frame to user */ + if (karg.max_reply_bytes) { + sz = min_t(u32, karg.max_reply_bytes, ioc->reply_sz); + if (copy_to_user(karg.reply_frame_buf_ptr, ioc->ctl_cmds.reply, + sz)) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, + __LINE__, __func__); + ret = -ENODATA; + goto out; + } + } + + /* copy out sense to user */ + if (karg.max_sense_bytes && (mpi_request->Function == + MPI2_FUNCTION_SCSI_IO_REQUEST || mpi_request->Function == + MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) { + sz = min_t(u32, karg.max_sense_bytes, SCSI_SENSE_BUFFERSIZE); + if (copy_to_user(karg.sense_data_ptr, priv_sense, sz)) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, + __LINE__, __func__); + ret = -ENODATA; + goto out; + } + } + + issue_host_reset: + if (issue_reset) { + if ((mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || + mpi_request->Function == + MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) { + printk(MPT2SAS_INFO_FMT "issue target reset: handle " + "= (0x%04x)\n", ioc->name, + mpi_request->FunctionDependent1); + mutex_lock(&ioc->tm_cmds.mutex); + mpt2sas_scsih_issue_tm(ioc, + mpi_request->FunctionDependent1, 0, + MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 10); + ioc->tm_cmds.status = MPT2_CMD_NOT_USED; + mutex_unlock(&ioc->tm_cmds.mutex); + } else + mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, + FORCE_BIG_HAMMER); + } + + out: + + /* free memory associated with sg buffers */ + if (data_in) + pci_free_consistent(ioc->pdev, data_in_sz, data_in, + data_in_dma); + + if (data_out) + pci_free_consistent(ioc->pdev, data_out_sz, data_out, + data_out_dma); + + ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; + mutex_unlock(&ioc->ctl_cmds.mutex); + return ret; +} + +/** + * _ctl_getiocinfo - main handler for MPT2IOCINFO opcode + * @arg - user space buffer containing ioctl content + */ +static long +_ctl_getiocinfo(void __user *arg) +{ + struct mpt2_ioctl_iocinfo karg; + struct MPT2SAS_ADAPTER *ioc; + u8 revision; + + if (copy_from_user(&karg, arg, sizeof(karg))) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return -EFAULT; + } + if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) + return -ENODEV; + + dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, + __func__)); + + memset(&karg, 0 , sizeof(karg)); + karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2; + if (ioc->pfacts) + karg.port_number = ioc->pfacts[0].PortNumber; + pci_read_config_byte(ioc->pdev, PCI_CLASS_REVISION, &revision); + karg.hw_rev = revision; + karg.pci_id = ioc->pdev->device; + karg.subsystem_device = ioc->pdev->subsystem_device; + karg.subsystem_vendor = ioc->pdev->subsystem_vendor; + karg.pci_information.u.bits.bus = ioc->pdev->bus->number; + karg.pci_information.u.bits.device = PCI_SLOT(ioc->pdev->devfn); + karg.pci_information.u.bits.function = PCI_FUNC(ioc->pdev->devfn); + karg.pci_information.segment_id = pci_domain_nr(ioc->pdev->bus); + karg.firmware_version = ioc->facts.FWVersion.Word; + strncpy(karg.driver_version, MPT2SAS_DRIVER_VERSION, + MPT2_IOCTL_VERSION_LENGTH); + karg.driver_version[MPT2_IOCTL_VERSION_LENGTH - 1] = '\0'; + karg.bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion); + + if (copy_to_user(arg, &karg, sizeof(karg))) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return -EFAULT; + } + return 0; +} + +/** + * _ctl_eventquery - main handler for MPT2EVENTQUERY opcode + * @arg - user space buffer containing ioctl content + */ +static long +_ctl_eventquery(void __user *arg) +{ + struct mpt2_ioctl_eventquery karg; + struct MPT2SAS_ADAPTER *ioc; + + if (copy_from_user(&karg, arg, sizeof(karg))) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return -EFAULT; + } + if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) + return -ENODEV; + + dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, + __func__)); + + karg.event_entries = MPT2SAS_CTL_EVENT_LOG_SIZE; + memcpy(karg.event_types, ioc->event_type, + MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32)); + + if (copy_to_user(arg, &karg, sizeof(karg))) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return -EFAULT; + } + return 0; +} + +/** + * _ctl_eventenable - main handler for MPT2EVENTENABLE opcode + * @arg - user space buffer containing ioctl content + */ +static long +_ctl_eventenable(void __user *arg) +{ + struct mpt2_ioctl_eventenable karg; + struct MPT2SAS_ADAPTER *ioc; + + if (copy_from_user(&karg, arg, sizeof(karg))) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return -EFAULT; + } + if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) + return -ENODEV; + + dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, + __func__)); + + if (ioc->event_log) + return 0; + memcpy(ioc->event_type, karg.event_types, + MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32)); + mpt2sas_base_validate_event_type(ioc, ioc->event_type); + + /* initialize event_log */ + ioc->event_context = 0; + ioc->aen_event_read_flag = 0; + ioc->event_log = kcalloc(MPT2SAS_CTL_EVENT_LOG_SIZE, + sizeof(struct MPT2_IOCTL_EVENTS), GFP_KERNEL); + if (!ioc->event_log) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return -ENOMEM; + } + return 0; +} + +/** + * _ctl_eventreport - main handler for MPT2EVENTREPORT opcode + * @arg - user space buffer containing ioctl content + */ +static long +_ctl_eventreport(void __user *arg) +{ + struct mpt2_ioctl_eventreport karg; + struct MPT2SAS_ADAPTER *ioc; + u32 number_bytes, max_events, max; + struct mpt2_ioctl_eventreport __user *uarg = arg; + + if (copy_from_user(&karg, arg, sizeof(karg))) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return -EFAULT; + } + if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) + return -ENODEV; + + dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, + __func__)); + + number_bytes = karg.hdr.max_data_size - + sizeof(struct mpt2_ioctl_header); + max_events = number_bytes/sizeof(struct MPT2_IOCTL_EVENTS); + max = min_t(u32, MPT2SAS_CTL_EVENT_LOG_SIZE, max_events); + + /* If fewer than 1 event is requested, there must have + * been some type of error. + */ + if (!max || !ioc->event_log) + return -ENODATA; + + number_bytes = max * sizeof(struct MPT2_IOCTL_EVENTS); + if (copy_to_user(uarg->event_data, ioc->event_log, number_bytes)) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return -EFAULT; + } + + /* reset flag so SIGIO can restart */ + ioc->aen_event_read_flag = 0; + return 0; +} + +/** + * _ctl_do_reset - main handler for MPT2HARDRESET opcode + * @arg - user space buffer containing ioctl content + */ +static long +_ctl_do_reset(void __user *arg) +{ + struct mpt2_ioctl_diag_reset karg; + struct MPT2SAS_ADAPTER *ioc; + int retval; + + if (copy_from_user(&karg, arg, sizeof(karg))) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return -EFAULT; + } + if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) + return -ENODEV; + + dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, + __func__)); + + retval = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, + FORCE_BIG_HAMMER); + printk(MPT2SAS_INFO_FMT "host reset: %s\n", + ioc->name, ((!retval) ? "SUCCESS" : "FAILED")); + return 0; +} + +/** + * _ctl_btdh_search_sas_device - searching for sas device + * @ioc: per adapter object + * @btdh: btdh ioctl payload + */ +static int +_ctl_btdh_search_sas_device(struct MPT2SAS_ADAPTER *ioc, + struct mpt2_ioctl_btdh_mapping *btdh) +{ + struct _sas_device *sas_device; + unsigned long flags; + int rc = 0; + + if (list_empty(&ioc->sas_device_list)) + return rc; + + spin_lock_irqsave(&ioc->sas_device_lock, flags); + list_for_each_entry(sas_device, &ioc->sas_device_list, list) { + if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF && + btdh->handle == sas_device->handle) { + btdh->bus = sas_device->channel; + btdh->id = sas_device->id; + rc = 1; + goto out; + } else if (btdh->bus == sas_device->channel && btdh->id == + sas_device->id && btdh->handle == 0xFFFF) { + btdh->handle = sas_device->handle; + rc = 1; + goto out; + } + } + out: + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + return rc; +} + +/** + * _ctl_btdh_search_raid_device - searching for raid device + * @ioc: per adapter object + * @btdh: btdh ioctl payload + */ +static int +_ctl_btdh_search_raid_device(struct MPT2SAS_ADAPTER *ioc, + struct mpt2_ioctl_btdh_mapping *btdh) +{ + struct _raid_device *raid_device; + unsigned long flags; + int rc = 0; + + if (list_empty(&ioc->raid_device_list)) + return rc; + + spin_lock_irqsave(&ioc->raid_device_lock, flags); + list_for_each_entry(raid_device, &ioc->raid_device_list, list) { + if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF && + btdh->handle == raid_device->handle) { + btdh->bus = raid_device->channel; + btdh->id = raid_device->id; + rc = 1; + goto out; + } else if (btdh->bus == raid_device->channel && btdh->id == + raid_device->id && btdh->handle == 0xFFFF) { + btdh->handle = raid_device->handle; + rc = 1; + goto out; + } + } + out: + spin_unlock_irqrestore(&ioc->raid_device_lock, flags); + return rc; +} + +/** + * _ctl_btdh_mapping - main handler for MPT2BTDHMAPPING opcode + * @arg - user space buffer containing ioctl content + */ +static long +_ctl_btdh_mapping(void __user *arg) +{ + struct mpt2_ioctl_btdh_mapping karg; + struct MPT2SAS_ADAPTER *ioc; + int rc; + + if (copy_from_user(&karg, arg, sizeof(karg))) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return -EFAULT; + } + if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) + return -ENODEV; + + dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + __func__)); + + rc = _ctl_btdh_search_sas_device(ioc, &karg); + if (!rc) + _ctl_btdh_search_raid_device(ioc, &karg); + + if (copy_to_user(arg, &karg, sizeof(karg))) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return -EFAULT; + } + return 0; +} + +/** + * _ctl_diag_capability - return diag buffer capability + * @ioc: per adapter object + * @buffer_type: specifies either TRACE or SNAPSHOT + * + * returns 1 when diag buffer support is enabled in firmware + */ +static u8 +_ctl_diag_capability(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type) +{ + u8 rc = 0; + + switch (buffer_type) { + case MPI2_DIAG_BUF_TYPE_TRACE: + if (ioc->facts.IOCCapabilities & + MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) + rc = 1; + break; + case MPI2_DIAG_BUF_TYPE_SNAPSHOT: + if (ioc->facts.IOCCapabilities & + MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) + rc = 1; + break; + } + + return rc; +} + +/** + * _ctl_diag_register - application register with driver + * @arg - user space buffer containing ioctl content + * @state - NON_BLOCKING or BLOCKING + * + * This will allow the driver to setup any required buffers that will be + * needed by firmware to communicate with the driver. + */ +static long +_ctl_diag_register(void __user *arg, enum block_state state) +{ + struct mpt2_diag_register karg; + struct MPT2SAS_ADAPTER *ioc; + int rc, i; + void *request_data = NULL; + dma_addr_t request_data_dma; + u32 request_data_sz = 0; + Mpi2DiagBufferPostRequest_t *mpi_request; + Mpi2DiagBufferPostReply_t *mpi_reply; + u8 buffer_type; + unsigned long timeleft; + u16 smid; + u16 ioc_status; + u8 issue_reset = 0; + + if (copy_from_user(&karg, arg, sizeof(karg))) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return -EFAULT; + } + if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) + return -ENODEV; + + dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + __func__)); + + buffer_type = karg.buffer_type; + if (!_ctl_diag_capability(ioc, buffer_type)) { + printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for " + "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); + return -EPERM; + } + + if (ioc->diag_buffer_status[buffer_type] & + MPT2_DIAG_BUFFER_IS_REGISTERED) { + printk(MPT2SAS_ERR_FMT "%s: already has a registered " + "buffer for buffer_type(0x%02x)\n", ioc->name, __func__, + buffer_type); + return -EINVAL; + } + + if (karg.requested_buffer_size % 4) { + printk(MPT2SAS_ERR_FMT "%s: the requested_buffer_size " + "is not 4 byte aligned\n", ioc->name, __func__); + return -EINVAL; + } + + if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex)) + return -EAGAIN; + else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) + return -ERESTARTSYS; + + if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) { + printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n", + ioc->name, __func__); + rc = -EAGAIN; + goto out; + } + + smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx); + if (!smid) { + printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", + ioc->name, __func__); + rc = -EAGAIN; + goto out; + } + + rc = 0; + ioc->ctl_cmds.status = MPT2_CMD_PENDING; + memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); + mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); + ioc->ctl_cmds.smid = smid; + + request_data = ioc->diag_buffer[buffer_type]; + request_data_sz = karg.requested_buffer_size; + ioc->unique_id[buffer_type] = karg.unique_id; + ioc->diag_buffer_status[buffer_type] = 0; + memcpy(ioc->product_specific[buffer_type], karg.product_specific, + MPT2_PRODUCT_SPECIFIC_DWORDS); + ioc->diagnostic_flags[buffer_type] = karg.diagnostic_flags; + + if (request_data) { + request_data_dma = ioc->diag_buffer_dma[buffer_type]; + if (request_data_sz != ioc->diag_buffer_sz[buffer_type]) { + pci_free_consistent(ioc->pdev, + ioc->diag_buffer_sz[buffer_type], + request_data, request_data_dma); + request_data = NULL; + } + } + + if (request_data == NULL) { + ioc->diag_buffer_sz[buffer_type] = 0; + ioc->diag_buffer_dma[buffer_type] = 0; + request_data = pci_alloc_consistent( + ioc->pdev, request_data_sz, &request_data_dma); + if (request_data == NULL) { + printk(MPT2SAS_ERR_FMT "%s: failed allocating memory" + " for diag buffers, requested size(%d)\n", + ioc->name, __func__, request_data_sz); + mpt2sas_base_free_smid(ioc, smid); + return -ENOMEM; + } + ioc->diag_buffer[buffer_type] = request_data; + ioc->diag_buffer_sz[buffer_type] = request_data_sz; + ioc->diag_buffer_dma[buffer_type] = request_data_dma; + } + + mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST; + mpi_request->BufferType = karg.buffer_type; + mpi_request->Flags = cpu_to_le32(karg.diagnostic_flags); + mpi_request->BufferAddress = cpu_to_le64(request_data_dma); + mpi_request->BufferLength = cpu_to_le32(request_data_sz); + + dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: diag_buffer(0x%p), " + "dma(0x%llx), sz(%d)\n", ioc->name, __func__, request_data, + (unsigned long long)request_data_dma, mpi_request->BufferLength)); + + for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++) + mpi_request->ProductSpecific[i] = + cpu_to_le32(ioc->product_specific[buffer_type][i]); + + mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); + timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, + MPT2_IOCTL_DEFAULT_TIMEOUT*HZ); + + if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) { + printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name, + __func__); + _debug_dump_mf(mpi_request, + sizeof(Mpi2DiagBufferPostRequest_t)/4); + if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET)) + issue_reset = 1; + goto issue_host_reset; + } + + /* process the completed Reply Message Frame */ + if ((ioc->ctl_cmds.status & MPT2_CMD_REPLY_VALID) == 0) { + printk(MPT2SAS_ERR_FMT "%s: no reply message\n", + ioc->name, __func__); + rc = -EFAULT; + goto out; + } + + mpi_reply = ioc->ctl_cmds.reply; + ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; + + if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { + ioc->diag_buffer_status[buffer_type] |= + MPT2_DIAG_BUFFER_IS_REGISTERED; + dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: success\n", + ioc->name, __func__)); + } else { + printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) " + "log_info(0x%08x)\n", ioc->name, __func__, + ioc_status, mpi_reply->IOCLogInfo); + rc = -EFAULT; + } + + issue_host_reset: + if (issue_reset) + mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, + FORCE_BIG_HAMMER); + + out: + + if (rc && request_data) + pci_free_consistent(ioc->pdev, request_data_sz, + request_data, request_data_dma); + + ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; + mutex_unlock(&ioc->ctl_cmds.mutex); + return rc; +} + +/** + * _ctl_diag_unregister - application unregister with driver + * @arg - user space buffer containing ioctl content + * + * This will allow the driver to cleanup any memory allocated for diag + * messages and to free up any resources. + */ +static long +_ctl_diag_unregister(void __user *arg) +{ + struct mpt2_diag_unregister karg; + struct MPT2SAS_ADAPTER *ioc; + void *request_data; + dma_addr_t request_data_dma; + u32 request_data_sz; + u8 buffer_type; + + if (copy_from_user(&karg, arg, sizeof(karg))) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return -EFAULT; + } + if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) + return -ENODEV; + + dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + __func__)); + + buffer_type = karg.unique_id & 0x000000ff; + if (!_ctl_diag_capability(ioc, buffer_type)) { + printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for " + "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); + return -EPERM; + } + + if ((ioc->diag_buffer_status[buffer_type] & + MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) { + printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not " + "registered\n", ioc->name, __func__, buffer_type); + return -EINVAL; + } + if ((ioc->diag_buffer_status[buffer_type] & + MPT2_DIAG_BUFFER_IS_RELEASED) == 0) { + printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) has not been " + "released\n", ioc->name, __func__, buffer_type); + return -EINVAL; + } + + if (karg.unique_id != ioc->unique_id[buffer_type]) { + printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not " + "registered\n", ioc->name, __func__, karg.unique_id); + return -EINVAL; + } + + request_data = ioc->diag_buffer[buffer_type]; + if (!request_data) { + printk(MPT2SAS_ERR_FMT "%s: doesn't have memory allocated for " + "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); + return -ENOMEM; + } + + request_data_sz = ioc->diag_buffer_sz[buffer_type]; + request_data_dma = ioc->diag_buffer_dma[buffer_type]; + pci_free_consistent(ioc->pdev, request_data_sz, + request_data, request_data_dma); + ioc->diag_buffer[buffer_type] = NULL; + ioc->diag_buffer_status[buffer_type] = 0; + return 0; +} + +/** + * _ctl_diag_query - query relevant info associated with diag buffers + * @arg - user space buffer containing ioctl content + * + * The application will send only buffer_type and unique_id. Driver will + * inspect unique_id first, if valid, fill in all the info. If unique_id is + * 0x00, the driver will return info specified by Buffer Type. + */ +static long +_ctl_diag_query(void __user *arg) +{ + struct mpt2_diag_query karg; + struct MPT2SAS_ADAPTER *ioc; + void *request_data; + int i; + u8 buffer_type; + + if (copy_from_user(&karg, arg, sizeof(karg))) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return -EFAULT; + } + if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) + return -ENODEV; + + dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + __func__)); + + karg.application_flags = 0; + buffer_type = karg.buffer_type; + + if (!_ctl_diag_capability(ioc, buffer_type)) { + printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for " + "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); + return -EPERM; + } + + if ((ioc->diag_buffer_status[buffer_type] & + MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) { + printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not " + "registered\n", ioc->name, __func__, buffer_type); + return -EINVAL; + } + + if (karg.unique_id & 0xffffff00) { + if (karg.unique_id != ioc->unique_id[buffer_type]) { + printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not " + "registered\n", ioc->name, __func__, + karg.unique_id); + return -EINVAL; + } + } + + request_data = ioc->diag_buffer[buffer_type]; + if (!request_data) { + printk(MPT2SAS_ERR_FMT "%s: doesn't have buffer for " + "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); + return -ENOMEM; + } + + if (ioc->diag_buffer_status[buffer_type] & MPT2_DIAG_BUFFER_IS_RELEASED) + karg.application_flags = (MPT2_APP_FLAGS_APP_OWNED | + MPT2_APP_FLAGS_BUFFER_VALID); + else + karg.application_flags = (MPT2_APP_FLAGS_APP_OWNED | + MPT2_APP_FLAGS_BUFFER_VALID | + MPT2_APP_FLAGS_FW_BUFFER_ACCESS); + + for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++) + karg.product_specific[i] = + ioc->product_specific[buffer_type][i]; + + karg.total_buffer_size = ioc->diag_buffer_sz[buffer_type]; + karg.driver_added_buffer_size = 0; + karg.unique_id = ioc->unique_id[buffer_type]; + karg.diagnostic_flags = ioc->diagnostic_flags[buffer_type]; + + if (copy_to_user(arg, &karg, sizeof(struct mpt2_diag_query))) { + printk(MPT2SAS_ERR_FMT "%s: unable to write mpt2_diag_query " + "data @ %p\n", ioc->name, __func__, arg); + return -EFAULT; + } + return 0; +} + +/** + * _ctl_diag_release - request to send Diag Release Message to firmware + * @arg - user space buffer containing ioctl content + * @state - NON_BLOCKING or BLOCKING + * + * This allows ownership of the specified buffer to returned to the driver, + * allowing an application to read the buffer without fear that firmware is + * overwritting information in the buffer. + */ +static long +_ctl_diag_release(void __user *arg, enum block_state state) +{ + struct mpt2_diag_release karg; + struct MPT2SAS_ADAPTER *ioc; + void *request_data; + int rc; + Mpi2DiagReleaseRequest_t *mpi_request; + Mpi2DiagReleaseReply_t *mpi_reply; + u8 buffer_type; + unsigned long timeleft; + u16 smid; + u16 ioc_status; + u8 issue_reset = 0; + + if (copy_from_user(&karg, arg, sizeof(karg))) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return -EFAULT; + } + if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) + return -ENODEV; + + dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + __func__)); + + buffer_type = karg.unique_id & 0x000000ff; + if (!_ctl_diag_capability(ioc, buffer_type)) { + printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for " + "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); + return -EPERM; + } + + if ((ioc->diag_buffer_status[buffer_type] & + MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) { + printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not " + "registered\n", ioc->name, __func__, buffer_type); + return -EINVAL; + } + + if (karg.unique_id != ioc->unique_id[buffer_type]) { + printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not " + "registered\n", ioc->name, __func__, karg.unique_id); + return -EINVAL; + } + + if (ioc->diag_buffer_status[buffer_type] & + MPT2_DIAG_BUFFER_IS_RELEASED) { + printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) " + "is already released\n", ioc->name, __func__, + buffer_type); + return 0; + } + + request_data = ioc->diag_buffer[buffer_type]; + + if (!request_data) { + printk(MPT2SAS_ERR_FMT "%s: doesn't have memory allocated for " + "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); + return -ENOMEM; + } + + if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex)) + return -EAGAIN; + else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) + return -ERESTARTSYS; + + if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) { + printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n", + ioc->name, __func__); + rc = -EAGAIN; + goto out; + } + + smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx); + if (!smid) { + printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", + ioc->name, __func__); + rc = -EAGAIN; + goto out; + } + + rc = 0; + ioc->ctl_cmds.status = MPT2_CMD_PENDING; + memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); + mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); + ioc->ctl_cmds.smid = smid; + + mpi_request->Function = MPI2_FUNCTION_DIAG_RELEASE; + mpi_request->BufferType = buffer_type; + + mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); + timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, + MPT2_IOCTL_DEFAULT_TIMEOUT*HZ); + + if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) { + printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name, + __func__); + _debug_dump_mf(mpi_request, + sizeof(Mpi2DiagReleaseRequest_t)/4); + if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET)) + issue_reset = 1; + goto issue_host_reset; + } + + /* process the completed Reply Message Frame */ + if ((ioc->ctl_cmds.status & MPT2_CMD_REPLY_VALID) == 0) { + printk(MPT2SAS_ERR_FMT "%s: no reply message\n", + ioc->name, __func__); + rc = -EFAULT; + goto out; + } + + mpi_reply = ioc->ctl_cmds.reply; + ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; + + if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { + ioc->diag_buffer_status[buffer_type] |= + MPT2_DIAG_BUFFER_IS_RELEASED; + dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: success\n", + ioc->name, __func__)); + } else { + printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) " + "log_info(0x%08x)\n", ioc->name, __func__, + ioc_status, mpi_reply->IOCLogInfo); + rc = -EFAULT; + } + + issue_host_reset: + if (issue_reset) + mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, + FORCE_BIG_HAMMER); + + out: + + ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; + mutex_unlock(&ioc->ctl_cmds.mutex); + return rc; +} + +/** + * _ctl_diag_read_buffer - request for copy of the diag buffer + * @arg - user space buffer containing ioctl content + * @state - NON_BLOCKING or BLOCKING + */ +static long +_ctl_diag_read_buffer(void __user *arg, enum block_state state) +{ + struct mpt2_diag_read_buffer karg; + struct mpt2_diag_read_buffer __user *uarg = arg; + struct MPT2SAS_ADAPTER *ioc; + void *request_data, *diag_data; + Mpi2DiagBufferPostRequest_t *mpi_request; + Mpi2DiagBufferPostReply_t *mpi_reply; + int rc, i; + u8 buffer_type; + unsigned long timeleft; + u16 smid; + u16 ioc_status; + u8 issue_reset = 0; + + if (copy_from_user(&karg, arg, sizeof(karg))) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return -EFAULT; + } + if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) + return -ENODEV; + + dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + __func__)); + + buffer_type = karg.unique_id & 0x000000ff; + if (!_ctl_diag_capability(ioc, buffer_type)) { + printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for " + "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); + return -EPERM; + } + + if (karg.unique_id != ioc->unique_id[buffer_type]) { + printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not " + "registered\n", ioc->name, __func__, karg.unique_id); + return -EINVAL; + } + + request_data = ioc->diag_buffer[buffer_type]; + if (!request_data) { + printk(MPT2SAS_ERR_FMT "%s: doesn't have buffer for " + "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); + return -ENOMEM; + } + + if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) { + printk(MPT2SAS_ERR_FMT "%s: either the starting_offset " + "or bytes_to_read are not 4 byte aligned\n", ioc->name, + __func__); + return -EINVAL; + } + + diag_data = (void *)(request_data + karg.starting_offset); + dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: diag_buffer(%p), " + "offset(%d), sz(%d)\n", ioc->name, __func__, + diag_data, karg.starting_offset, karg.bytes_to_read)); + + if (copy_to_user((void __user *)uarg->diagnostic_data, + diag_data, karg.bytes_to_read)) { + printk(MPT2SAS_ERR_FMT "%s: Unable to write " + "mpt_diag_read_buffer_t data @ %p\n", ioc->name, + __func__, diag_data); + return -EFAULT; + } + + if ((karg.flags & MPT2_FLAGS_REREGISTER) == 0) + return 0; + + dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: Reregister " + "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type)); + if ((ioc->diag_buffer_status[buffer_type] & + MPT2_DIAG_BUFFER_IS_RELEASED) == 0) { + dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + "buffer_type(0x%02x) is still registered\n", ioc->name, + __func__, buffer_type)); + return 0; + } + /* Get a free request frame and save the message context. + */ + if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex)) + return -EAGAIN; + else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) + return -ERESTARTSYS; + + if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) { + printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n", + ioc->name, __func__); + rc = -EAGAIN; + goto out; + } + + smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx); + if (!smid) { + printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", + ioc->name, __func__); + rc = -EAGAIN; + goto out; + } + + rc = 0; + ioc->ctl_cmds.status = MPT2_CMD_PENDING; + memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); + mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); + ioc->ctl_cmds.smid = smid; + + mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST; + mpi_request->BufferType = buffer_type; + mpi_request->BufferLength = + cpu_to_le32(ioc->diag_buffer_sz[buffer_type]); + mpi_request->BufferAddress = + cpu_to_le64(ioc->diag_buffer_dma[buffer_type]); + for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++) + mpi_request->ProductSpecific[i] = + cpu_to_le32(ioc->product_specific[buffer_type][i]); + + mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); + timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, + MPT2_IOCTL_DEFAULT_TIMEOUT*HZ); + + if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) { + printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name, + __func__); + _debug_dump_mf(mpi_request, + sizeof(Mpi2DiagBufferPostRequest_t)/4); + if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET)) + issue_reset = 1; + goto issue_host_reset; + } + + /* process the completed Reply Message Frame */ + if ((ioc->ctl_cmds.status & MPT2_CMD_REPLY_VALID) == 0) { + printk(MPT2SAS_ERR_FMT "%s: no reply message\n", + ioc->name, __func__); + rc = -EFAULT; + goto out; + } + + mpi_reply = ioc->ctl_cmds.reply; + ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; + + if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { + ioc->diag_buffer_status[buffer_type] |= + MPT2_DIAG_BUFFER_IS_REGISTERED; + dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: success\n", + ioc->name, __func__)); + } else { + printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) " + "log_info(0x%08x)\n", ioc->name, __func__, + ioc_status, mpi_reply->IOCLogInfo); + rc = -EFAULT; + } + + issue_host_reset: + if (issue_reset) + mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, + FORCE_BIG_HAMMER); + + out: + + ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; + mutex_unlock(&ioc->ctl_cmds.mutex); + return rc; +} + +/** + * _ctl_ioctl_main - main ioctl entry point + * @file - (struct file) + * @cmd - ioctl opcode + * @arg - + */ +static long +_ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg) +{ + enum block_state state; + long ret = -EINVAL; + unsigned long flags; + + state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : + BLOCKING; + + switch (cmd) { + case MPT2IOCINFO: + if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_iocinfo)) + ret = _ctl_getiocinfo(arg); + break; + case MPT2COMMAND: + { + struct mpt2_ioctl_command karg; + struct mpt2_ioctl_command __user *uarg; + struct MPT2SAS_ADAPTER *ioc; + + if (copy_from_user(&karg, arg, sizeof(karg))) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return -EFAULT; + } + + if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || + !ioc) + return -ENODEV; + + spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); + if (ioc->shost_recovery) { + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, + flags); + return -EAGAIN; + } + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + + if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_command)) { + uarg = arg; + ret = _ctl_do_mpt_command(ioc, karg, &uarg->mf, state); + } + break; + } + case MPT2EVENTQUERY: + if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_eventquery)) + ret = _ctl_eventquery(arg); + break; + case MPT2EVENTENABLE: + if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_eventenable)) + ret = _ctl_eventenable(arg); + break; + case MPT2EVENTREPORT: + ret = _ctl_eventreport(arg); + break; + case MPT2HARDRESET: + if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_diag_reset)) + ret = _ctl_do_reset(arg); + break; + case MPT2BTDHMAPPING: + if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_btdh_mapping)) + ret = _ctl_btdh_mapping(arg); + break; + case MPT2DIAGREGISTER: + if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_register)) + ret = _ctl_diag_register(arg, state); + break; + case MPT2DIAGUNREGISTER: + if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_unregister)) + ret = _ctl_diag_unregister(arg); + break; + case MPT2DIAGQUERY: + if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_query)) + ret = _ctl_diag_query(arg); + break; + case MPT2DIAGRELEASE: + if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_release)) + ret = _ctl_diag_release(arg, state); + break; + case MPT2DIAGREADBUFFER: + if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_read_buffer)) + ret = _ctl_diag_read_buffer(arg, state); + break; + default: + { + struct mpt2_ioctl_command karg; + struct MPT2SAS_ADAPTER *ioc; + + if (copy_from_user(&karg, arg, sizeof(karg))) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return -EFAULT; + } + + if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || + !ioc) + return -ENODEV; + + dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT + "unsupported ioctl opcode(0x%08x)\n", ioc->name, cmd)); + break; + } + } + return ret; +} + +/** + * _ctl_ioctl - main ioctl entry point (unlocked) + * @file - (struct file) + * @cmd - ioctl opcode + * @arg - + */ +static long +_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + long ret; + lock_kernel(); + ret = _ctl_ioctl_main(file, cmd, (void __user *)arg); + unlock_kernel(); + return ret; +} + +#ifdef CONFIG_COMPAT +/** + * _ctl_compat_mpt_command - convert 32bit pointers to 64bit. + * @file - (struct file) + * @cmd - ioctl opcode + * @arg - (struct mpt2_ioctl_command32) + * + * MPT2COMMAND32 - Handle 32bit applications running on 64bit os. + */ +static long +_ctl_compat_mpt_command(struct file *file, unsigned cmd, unsigned long arg) +{ + struct mpt2_ioctl_command32 karg32; + struct mpt2_ioctl_command32 __user *uarg; + struct mpt2_ioctl_command karg; + struct MPT2SAS_ADAPTER *ioc; + enum block_state state; + unsigned long flags; + + if (_IOC_SIZE(cmd) != sizeof(struct mpt2_ioctl_command32)) + return -EINVAL; + + uarg = (struct mpt2_ioctl_command32 __user *) arg; + + if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32))) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return -EFAULT; + } + if (_ctl_verify_adapter(karg32.hdr.ioc_number, &ioc) == -1 || !ioc) + return -ENODEV; + + spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); + if (ioc->shost_recovery) { + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, + flags); + return -EAGAIN; + } + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + + memset(&karg, 0, sizeof(struct mpt2_ioctl_command)); + karg.hdr.ioc_number = karg32.hdr.ioc_number; + karg.hdr.port_number = karg32.hdr.port_number; + karg.hdr.max_data_size = karg32.hdr.max_data_size; + karg.timeout = karg32.timeout; + karg.max_reply_bytes = karg32.max_reply_bytes; + karg.data_in_size = karg32.data_in_size; + karg.data_out_size = karg32.data_out_size; + karg.max_sense_bytes = karg32.max_sense_bytes; + karg.data_sge_offset = karg32.data_sge_offset; + memcpy(&karg.reply_frame_buf_ptr, &karg32.reply_frame_buf_ptr, + sizeof(uint32_t)); + memcpy(&karg.data_in_buf_ptr, &karg32.data_in_buf_ptr, + sizeof(uint32_t)); + memcpy(&karg.data_out_buf_ptr, &karg32.data_out_buf_ptr, + sizeof(uint32_t)); + memcpy(&karg.sense_data_ptr, &karg32.sense_data_ptr, + sizeof(uint32_t)); + state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING; + return _ctl_do_mpt_command(ioc, karg, &uarg->mf, state); +} + +/** + * _ctl_ioctl_compat - main ioctl entry point (compat) + * @file - + * @cmd - + * @arg - + * + * This routine handles 32 bit applications in 64bit os. + */ +static long +_ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg) +{ + long ret; + lock_kernel(); + if (cmd == MPT2COMMAND32) + ret = _ctl_compat_mpt_command(file, cmd, arg); + else + ret = _ctl_ioctl_main(file, cmd, (void __user *)arg); + unlock_kernel(); + return ret; +} +#endif + +/* scsi host attributes */ + +/** + * _ctl_version_fw_show - firmware version + * @cdev - pointer to embedded class device + * @buf - the buffer returned + * + * A sysfs 'read-only' shost attribute. + */ +static ssize_t +_ctl_version_fw_show(struct device *cdev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + + return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n", + (ioc->facts.FWVersion.Word & 0xFF000000) >> 24, + (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16, + (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8, + ioc->facts.FWVersion.Word & 0x000000FF); +} +static DEVICE_ATTR(version_fw, S_IRUGO, _ctl_version_fw_show, NULL); + +/** + * _ctl_version_bios_show - bios version + * @cdev - pointer to embedded class device + * @buf - the buffer returned + * + * A sysfs 'read-only' shost attribute. + */ +static ssize_t +_ctl_version_bios_show(struct device *cdev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + + u32 version = le32_to_cpu(ioc->bios_pg3.BiosVersion); + + return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n", + (version & 0xFF000000) >> 24, + (version & 0x00FF0000) >> 16, + (version & 0x0000FF00) >> 8, + version & 0x000000FF); +} +static DEVICE_ATTR(version_bios, S_IRUGO, _ctl_version_bios_show, NULL); + +/** + * _ctl_version_mpi_show - MPI (message passing interface) version + * @cdev - pointer to embedded class device + * @buf - the buffer returned + * + * A sysfs 'read-only' shost attribute. + */ +static ssize_t +_ctl_version_mpi_show(struct device *cdev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + + return snprintf(buf, PAGE_SIZE, "%03x.%02x\n", + ioc->facts.MsgVersion, ioc->facts.HeaderVersion >> 8); +} +static DEVICE_ATTR(version_mpi, S_IRUGO, _ctl_version_mpi_show, NULL); + +/** + * _ctl_version_product_show - product name + * @cdev - pointer to embedded class device + * @buf - the buffer returned + * + * A sysfs 'read-only' shost attribute. + */ +static ssize_t +_ctl_version_product_show(struct device *cdev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + + return snprintf(buf, 16, "%s\n", ioc->manu_pg0.ChipName); +} +static DEVICE_ATTR(version_product, S_IRUGO, + _ctl_version_product_show, NULL); + +/** + * _ctl_version_nvdata_persistent_show - ndvata persistent version + * @cdev - pointer to embedded class device + * @buf - the buffer returned + * + * A sysfs 'read-only' shost attribute. + */ +static ssize_t +_ctl_version_nvdata_persistent_show(struct device *cdev, + struct device_attribute *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + + return snprintf(buf, PAGE_SIZE, "%02xh\n", + le16_to_cpu(ioc->iounit_pg0.NvdataVersionPersistent.Word)); +} +static DEVICE_ATTR(version_nvdata_persistent, S_IRUGO, + _ctl_version_nvdata_persistent_show, NULL); + +/** + * _ctl_version_nvdata_default_show - nvdata default version + * @cdev - pointer to embedded class device + * @buf - the buffer returned + * + * A sysfs 'read-only' shost attribute. + */ +static ssize_t +_ctl_version_nvdata_default_show(struct device *cdev, + struct device_attribute *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + + return snprintf(buf, PAGE_SIZE, "%02xh\n", + le16_to_cpu(ioc->iounit_pg0.NvdataVersionDefault.Word)); +} +static DEVICE_ATTR(version_nvdata_default, S_IRUGO, + _ctl_version_nvdata_default_show, NULL); + +/** + * _ctl_board_name_show - board name + * @cdev - pointer to embedded class device + * @buf - the buffer returned + * + * A sysfs 'read-only' shost attribute. + */ +static ssize_t +_ctl_board_name_show(struct device *cdev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + + return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardName); +} +static DEVICE_ATTR(board_name, S_IRUGO, _ctl_board_name_show, NULL); + +/** + * _ctl_board_assembly_show - board assembly name + * @cdev - pointer to embedded class device + * @buf - the buffer returned + * + * A sysfs 'read-only' shost attribute. + */ +static ssize_t +_ctl_board_assembly_show(struct device *cdev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + + return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardAssembly); +} +static DEVICE_ATTR(board_assembly, S_IRUGO, + _ctl_board_assembly_show, NULL); + +/** + * _ctl_board_tracer_show - board tracer number + * @cdev - pointer to embedded class device + * @buf - the buffer returned + * + * A sysfs 'read-only' shost attribute. + */ +static ssize_t +_ctl_board_tracer_show(struct device *cdev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + + return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardTracerNumber); +} +static DEVICE_ATTR(board_tracer, S_IRUGO, + _ctl_board_tracer_show, NULL); + +/** + * _ctl_io_delay_show - io missing delay + * @cdev - pointer to embedded class device + * @buf - the buffer returned + * + * This is for firmware implemention for deboucing device + * removal events. + * + * A sysfs 'read-only' shost attribute. + */ +static ssize_t +_ctl_io_delay_show(struct device *cdev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + + return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay); +} +static DEVICE_ATTR(io_delay, S_IRUGO, + _ctl_io_delay_show, NULL); + +/** + * _ctl_device_delay_show - device missing delay + * @cdev - pointer to embedded class device + * @buf - the buffer returned + * + * This is for firmware implemention for deboucing device + * removal events. + * + * A sysfs 'read-only' shost attribute. + */ +static ssize_t +_ctl_device_delay_show(struct device *cdev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + + return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay); +} +static DEVICE_ATTR(device_delay, S_IRUGO, + _ctl_device_delay_show, NULL); + +/** + * _ctl_fw_queue_depth_show - global credits + * @cdev - pointer to embedded class device + * @buf - the buffer returned + * + * This is firmware queue depth limit + * + * A sysfs 'read-only' shost attribute. + */ +static ssize_t +_ctl_fw_queue_depth_show(struct device *cdev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + + return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->facts.RequestCredit); +} +static DEVICE_ATTR(fw_queue_depth, S_IRUGO, + _ctl_fw_queue_depth_show, NULL); + +/** + * _ctl_sas_address_show - sas address + * @cdev - pointer to embedded class device + * @buf - the buffer returned + * + * This is the controller sas address + * + * A sysfs 'read-only' shost attribute. + */ +static ssize_t +_ctl_host_sas_address_show(struct device *cdev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + + return snprintf(buf, PAGE_SIZE, "0x%016llx\n", + (unsigned long long)ioc->sas_hba.sas_address); +} +static DEVICE_ATTR(host_sas_address, S_IRUGO, + _ctl_host_sas_address_show, NULL); + +/** + * _ctl_logging_level_show - logging level + * @cdev - pointer to embedded class device + * @buf - the buffer returned + * + * A sysfs 'read/write' shost attribute. + */ +static ssize_t +_ctl_logging_level_show(struct device *cdev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + + return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->logging_level); +} +static ssize_t +_ctl_logging_level_store(struct device *cdev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + int val = 0; + + if (sscanf(buf, "%x", &val) != 1) + return -EINVAL; + + ioc->logging_level = val; + printk(MPT2SAS_INFO_FMT "logging_level=%08xh\n", ioc->name, + ioc->logging_level); + return strlen(buf); +} +static DEVICE_ATTR(logging_level, S_IRUGO | S_IWUSR, + _ctl_logging_level_show, _ctl_logging_level_store); + +struct device_attribute *mpt2sas_host_attrs[] = { + &dev_attr_version_fw, + &dev_attr_version_bios, + &dev_attr_version_mpi, + &dev_attr_version_product, + &dev_attr_version_nvdata_persistent, + &dev_attr_version_nvdata_default, + &dev_attr_board_name, + &dev_attr_board_assembly, + &dev_attr_board_tracer, + &dev_attr_io_delay, + &dev_attr_device_delay, + &dev_attr_logging_level, + &dev_attr_fw_queue_depth, + &dev_attr_host_sas_address, + NULL, +}; + +/* device attributes */ + +/** + * _ctl_device_sas_address_show - sas address + * @cdev - pointer to embedded class device + * @buf - the buffer returned + * + * This is the sas address for the target + * + * A sysfs 'read-only' shost attribute. + */ +static ssize_t +_ctl_device_sas_address_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct scsi_device *sdev = to_scsi_device(dev); + struct MPT2SAS_DEVICE *sas_device_priv_data = sdev->hostdata; + + return snprintf(buf, PAGE_SIZE, "0x%016llx\n", + (unsigned long long)sas_device_priv_data->sas_target->sas_address); +} +static DEVICE_ATTR(sas_address, S_IRUGO, _ctl_device_sas_address_show, NULL); + +/** + * _ctl_device_handle_show - device handle + * @cdev - pointer to embedded class device + * @buf - the buffer returned + * + * This is the firmware assigned device handle + * + * A sysfs 'read-only' shost attribute. + */ +static ssize_t +_ctl_device_handle_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct scsi_device *sdev = to_scsi_device(dev); + struct MPT2SAS_DEVICE *sas_device_priv_data = sdev->hostdata; + + return snprintf(buf, PAGE_SIZE, "0x%04x\n", + sas_device_priv_data->sas_target->handle); +} +static DEVICE_ATTR(sas_device_handle, S_IRUGO, _ctl_device_handle_show, NULL); + +struct device_attribute *mpt2sas_dev_attrs[] = { + &dev_attr_sas_address, + &dev_attr_sas_device_handle, + NULL, +}; + +static const struct file_operations ctl_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = _ctl_ioctl, + .release = _ctl_release, + .poll = _ctl_poll, + .fasync = _ctl_fasync, +#ifdef CONFIG_COMPAT + .compat_ioctl = _ctl_ioctl_compat, +#endif +}; + +static struct miscdevice ctl_dev = { + .minor = MPT2SAS_MINOR, + .name = MPT2SAS_DEV_NAME, + .fops = &ctl_fops, +}; + +/** + * mpt2sas_ctl_init - main entry point for ctl. + * + */ +void +mpt2sas_ctl_init(void) +{ + async_queue = NULL; + if (misc_register(&ctl_dev) < 0) + printk(KERN_ERR "%s can't register misc device [minor=%d]\n", + MPT2SAS_DRIVER_NAME, MPT2SAS_MINOR); + + init_waitqueue_head(&ctl_poll_wait); +} + +/** + * mpt2sas_ctl_exit - exit point for ctl + * + */ +void +mpt2sas_ctl_exit(void) +{ + struct MPT2SAS_ADAPTER *ioc; + int i; + + list_for_each_entry(ioc, &ioc_list, list) { + + /* free memory associated to diag buffers */ + for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) { + if (!ioc->diag_buffer[i]) + continue; + pci_free_consistent(ioc->pdev, ioc->diag_buffer_sz[i], + ioc->diag_buffer[i], ioc->diag_buffer_dma[i]); + ioc->diag_buffer[i] = NULL; + ioc->diag_buffer_status[i] = 0; + } + + kfree(ioc->event_log); + } + misc_deregister(&ctl_dev); +} + diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.h b/drivers/scsi/mpt2sas/mpt2sas_ctl.h new file mode 100644 index 00000000000..dbb6c0cf888 --- /dev/null +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.h @@ -0,0 +1,416 @@ +/* + * Management Module Support for MPT (Message Passing Technology) based + * controllers + * + * This code is based on drivers/scsi/mpt2sas/mpt2_ctl.h + * Copyright (C) 2007-2008 LSI Corporation + * (mailto:DL-MPTFusionLinux@lsi.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * NO WARRANTY + * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT + * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is + * solely responsible for determining the appropriateness of using and + * distributing the Program and assumes all risks associated with its + * exercise of rights under this Agreement, including but not limited to + * the risks and costs of program errors, damage to or loss of data, + * programs or equipment, and unavailability or interruption of operations. + + * DISCLAIMER OF LIABILITY + * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED + * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#ifndef MPT2SAS_CTL_H_INCLUDED +#define MPT2SAS_CTL_H_INCLUDED + +#ifdef __KERNEL__ +#include +#endif + +#define MPT2SAS_DEV_NAME "mpt2ctl" +#define MPT2_MAGIC_NUMBER 'm' +#define MPT2_IOCTL_DEFAULT_TIMEOUT (10) /* in seconds */ + +/** + * IOCTL opcodes + */ +#define MPT2IOCINFO _IOWR(MPT2_MAGIC_NUMBER, 17, \ + struct mpt2_ioctl_iocinfo) +#define MPT2COMMAND _IOWR(MPT2_MAGIC_NUMBER, 20, \ + struct mpt2_ioctl_command) +#ifdef CONFIG_COMPAT +#define MPT2COMMAND32 _IOWR(MPT2_MAGIC_NUMBER, 20, \ + struct mpt2_ioctl_command32) +#endif +#define MPT2EVENTQUERY _IOWR(MPT2_MAGIC_NUMBER, 21, \ + struct mpt2_ioctl_eventquery) +#define MPT2EVENTENABLE _IOWR(MPT2_MAGIC_NUMBER, 22, \ + struct mpt2_ioctl_eventenable) +#define MPT2EVENTREPORT _IOWR(MPT2_MAGIC_NUMBER, 23, \ + struct mpt2_ioctl_eventreport) +#define MPT2HARDRESET _IOWR(MPT2_MAGIC_NUMBER, 24, \ + struct mpt2_ioctl_diag_reset) +#define MPT2BTDHMAPPING _IOWR(MPT2_MAGIC_NUMBER, 31, \ + struct mpt2_ioctl_btdh_mapping) + +/* diag buffer support */ +#define MPT2DIAGREGISTER _IOWR(MPT2_MAGIC_NUMBER, 26, \ + struct mpt2_diag_register) +#define MPT2DIAGRELEASE _IOWR(MPT2_MAGIC_NUMBER, 27, \ + struct mpt2_diag_release) +#define MPT2DIAGUNREGISTER _IOWR(MPT2_MAGIC_NUMBER, 28, \ + struct mpt2_diag_unregister) +#define MPT2DIAGQUERY _IOWR(MPT2_MAGIC_NUMBER, 29, \ + struct mpt2_diag_query) +#define MPT2DIAGREADBUFFER _IOWR(MPT2_MAGIC_NUMBER, 30, \ + struct mpt2_diag_read_buffer) + +/** + * struct mpt2_ioctl_header - main header structure + * @ioc_number - IOC unit number + * @port_number - IOC port number + * @max_data_size - maximum number bytes to transfer on read + */ +struct mpt2_ioctl_header { + uint32_t ioc_number; + uint32_t port_number; + uint32_t max_data_size; +}; + +/** + * struct mpt2_ioctl_diag_reset - diagnostic reset + * @hdr - generic header + */ +struct mpt2_ioctl_diag_reset { + struct mpt2_ioctl_header hdr; +}; + + +/** + * struct mpt2_ioctl_pci_info - pci device info + * @device - pci device id + * @function - pci function id + * @bus - pci bus id + * @segment_id - pci segment id + */ +struct mpt2_ioctl_pci_info { + union { + struct { + uint32_t device:5; + uint32_t function:3; + uint32_t bus:24; + } bits; + uint32_t word; + } u; + uint32_t segment_id; +}; + + +#define MPT2_IOCTL_INTERFACE_SCSI (0x00) +#define MPT2_IOCTL_INTERFACE_FC (0x01) +#define MPT2_IOCTL_INTERFACE_FC_IP (0x02) +#define MPT2_IOCTL_INTERFACE_SAS (0x03) +#define MPT2_IOCTL_INTERFACE_SAS2 (0x04) +#define MPT2_IOCTL_VERSION_LENGTH (32) + +/** + * struct mpt2_ioctl_iocinfo - generic controller info + * @hdr - generic header + * @adapter_type - type of adapter (spi, fc, sas) + * @port_number - port number + * @pci_id - PCI Id + * @hw_rev - hardware revision + * @sub_system_device - PCI subsystem Device ID + * @sub_system_vendor - PCI subsystem Vendor ID + * @rsvd0 - reserved + * @firmware_version - firmware version + * @bios_version - BIOS version + * @driver_version - driver version - 32 ASCII characters + * @rsvd1 - reserved + * @scsi_id - scsi id of adapter 0 + * @rsvd2 - reserved + * @pci_information - pci info (2nd revision) + */ +struct mpt2_ioctl_iocinfo { + struct mpt2_ioctl_header hdr; + uint32_t adapter_type; + uint32_t port_number; + uint32_t pci_id; + uint32_t hw_rev; + uint32_t subsystem_device; + uint32_t subsystem_vendor; + uint32_t rsvd0; + uint32_t firmware_version; + uint32_t bios_version; + uint8_t driver_version[MPT2_IOCTL_VERSION_LENGTH]; + uint8_t rsvd1; + uint8_t scsi_id; + uint16_t rsvd2; + struct mpt2_ioctl_pci_info pci_information; +}; + + +/* number of event log entries */ +#define MPT2SAS_CTL_EVENT_LOG_SIZE (50) + +/** + * struct mpt2_ioctl_eventquery - query event count and type + * @hdr - generic header + * @event_entries - number of events returned by get_event_report + * @rsvd - reserved + * @event_types - type of events currently being captured + */ +struct mpt2_ioctl_eventquery { + struct mpt2_ioctl_header hdr; + uint16_t event_entries; + uint16_t rsvd; + uint32_t event_types[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS]; +}; + +/** + * struct mpt2_ioctl_eventenable - enable/disable event capturing + * @hdr - generic header + * @event_types - toggle off/on type of events to be captured + */ +struct mpt2_ioctl_eventenable { + struct mpt2_ioctl_header hdr; + uint32_t event_types[4]; +}; + +#define MPT2_EVENT_DATA_SIZE (192) +/** + * struct MPT2_IOCTL_EVENTS - + * @event - the event that was reported + * @context - unique value for each event assigned by driver + * @data - event data returned in fw reply message + */ +struct MPT2_IOCTL_EVENTS { + uint32_t event; + uint32_t context; + uint8_t data[MPT2_EVENT_DATA_SIZE]; +}; + +/** + * struct mpt2_ioctl_eventreport - returing event log + * @hdr - generic header + * @event_data - (see struct MPT2_IOCTL_EVENTS) + */ +struct mpt2_ioctl_eventreport { + struct mpt2_ioctl_header hdr; + struct MPT2_IOCTL_EVENTS event_data[1]; +}; + +/** + * struct mpt2_ioctl_command - generic mpt firmware passthru ioclt + * @hdr - generic header + * @timeout - command timeout in seconds. (if zero then use driver default + * value). + * @reply_frame_buf_ptr - reply location + * @data_in_buf_ptr - destination for read + * @data_out_buf_ptr - data source for write + * @sense_data_ptr - sense data location + * @max_reply_bytes - maximum number of reply bytes to be sent to app. + * @data_in_size - number bytes for data transfer in (read) + * @data_out_size - number bytes for data transfer out (write) + * @max_sense_bytes - maximum number of bytes for auto sense buffers + * @data_sge_offset - offset in words from the start of the request message to + * the first SGL + * @mf[1]; + */ +struct mpt2_ioctl_command { + struct mpt2_ioctl_header hdr; + uint32_t timeout; + void __user *reply_frame_buf_ptr; + void __user *data_in_buf_ptr; + void __user *data_out_buf_ptr; + void __user *sense_data_ptr; + uint32_t max_reply_bytes; + uint32_t data_in_size; + uint32_t data_out_size; + uint32_t max_sense_bytes; + uint32_t data_sge_offset; + uint8_t mf[1]; +}; + +#ifdef CONFIG_COMPAT +struct mpt2_ioctl_command32 { + struct mpt2_ioctl_header hdr; + uint32_t timeout; + uint32_t reply_frame_buf_ptr; + uint32_t data_in_buf_ptr; + uint32_t data_out_buf_ptr; + uint32_t sense_data_ptr; + uint32_t max_reply_bytes; + uint32_t data_in_size; + uint32_t data_out_size; + uint32_t max_sense_bytes; + uint32_t data_sge_offset; + uint8_t mf[1]; +}; +#endif + +/** + * struct mpt2_ioctl_btdh_mapping - mapping info + * @hdr - generic header + * @id - target device identification number + * @bus - SCSI bus number that the target device exists on + * @handle - device handle for the target device + * @rsvd - reserved + * + * To obtain a bus/id the application sets + * handle to valid handle, and bus/id to 0xFFFF. + * + * To obtain the device handle the application sets + * bus/id valid value, and the handle to 0xFFFF. + */ +struct mpt2_ioctl_btdh_mapping { + struct mpt2_ioctl_header hdr; + uint32_t id; + uint32_t bus; + uint16_t handle; + uint16_t rsvd; +}; + + +/* status bits for ioc->diag_buffer_status */ +#define MPT2_DIAG_BUFFER_IS_REGISTERED (0x01) +#define MPT2_DIAG_BUFFER_IS_RELEASED (0x02) + +/* application flags for mpt2_diag_register, mpt2_diag_query */ +#define MPT2_APP_FLAGS_APP_OWNED (0x0001) +#define MPT2_APP_FLAGS_BUFFER_VALID (0x0002) +#define MPT2_APP_FLAGS_FW_BUFFER_ACCESS (0x0004) + +/* flags for mpt2_diag_read_buffer */ +#define MPT2_FLAGS_REREGISTER (0x0001) + +#define MPT2_PRODUCT_SPECIFIC_DWORDS 23 + +/** + * struct mpt2_diag_register - application register with driver + * @hdr - generic header + * @reserved - + * @buffer_type - specifies either TRACE or SNAPSHOT + * @application_flags - misc flags + * @diagnostic_flags - specifies flags affecting command processing + * @product_specific - product specific information + * @requested_buffer_size - buffers size in bytes + * @unique_id - tag specified by application that is used to signal ownership + * of the buffer. + * + * This will allow the driver to setup any required buffers that will be + * needed by firmware to communicate with the driver. + */ +struct mpt2_diag_register { + struct mpt2_ioctl_header hdr; + uint8_t reserved; + uint8_t buffer_type; + uint16_t application_flags; + uint32_t diagnostic_flags; + uint32_t product_specific[MPT2_PRODUCT_SPECIFIC_DWORDS]; + uint32_t requested_buffer_size; + uint32_t unique_id; +}; + +/** + * struct mpt2_diag_unregister - application unregister with driver + * @hdr - generic header + * @unique_id - tag uniquely identifies the buffer to be unregistered + * + * This will allow the driver to cleanup any memory allocated for diag + * messages and to free up any resources. + */ +struct mpt2_diag_unregister { + struct mpt2_ioctl_header hdr; + uint32_t unique_id; +}; + +/** + * struct mpt2_diag_query - query relevant info associated with diag buffers + * @hdr - generic header + * @reserved - + * @buffer_type - specifies either TRACE or SNAPSHOT + * @application_flags - misc flags + * @diagnostic_flags - specifies flags affecting command processing + * @product_specific - product specific information + * @total_buffer_size - diag buffer size in bytes + * @driver_added_buffer_size - size of extra space appended to end of buffer + * @unique_id - unique id associated with this buffer. + * + * The application will send only buffer_type and unique_id. Driver will + * inspect unique_id first, if valid, fill in all the info. If unique_id is + * 0x00, the driver will return info specified by Buffer Type. + */ +struct mpt2_diag_query { + struct mpt2_ioctl_header hdr; + uint8_t reserved; + uint8_t buffer_type; + uint16_t application_flags; + uint32_t diagnostic_flags; + uint32_t product_specific[MPT2_PRODUCT_SPECIFIC_DWORDS]; + uint32_t total_buffer_size; + uint32_t driver_added_buffer_size; + uint32_t unique_id; +}; + +/** + * struct mpt2_diag_release - request to send Diag Release Message to firmware + * @hdr - generic header + * @unique_id - tag uniquely identifies the buffer to be released + * + * This allows ownership of the specified buffer to returned to the driver, + * allowing an application to read the buffer without fear that firmware is + * overwritting information in the buffer. + */ +struct mpt2_diag_release { + struct mpt2_ioctl_header hdr; + uint32_t unique_id; +}; + +/** + * struct mpt2_diag_read_buffer - request for copy of the diag buffer + * @hdr - generic header + * @status - + * @reserved - + * @flags - misc flags + * @starting_offset - starting offset within drivers buffer where to start + * reading data at into the specified application buffer + * @bytes_to_read - number of bytes to copy from the drivers buffer into the + * application buffer starting at starting_offset. + * @unique_id - unique id associated with this buffer. + * @diagnostic_data - data payload + */ +struct mpt2_diag_read_buffer { + struct mpt2_ioctl_header hdr; + uint8_t status; + uint8_t reserved; + uint16_t flags; + uint32_t starting_offset; + uint32_t bytes_to_read; + uint32_t unique_id; + uint32_t diagnostic_data[1]; +}; + +#endif /* MPT2SAS_CTL_H_INCLUDED */ diff --git a/drivers/scsi/mpt2sas/mpt2sas_debug.h b/drivers/scsi/mpt2sas/mpt2sas_debug.h new file mode 100644 index 00000000000..ad325096e84 --- /dev/null +++ b/drivers/scsi/mpt2sas/mpt2sas_debug.h @@ -0,0 +1,181 @@ +/* + * Logging Support for MPT (Message Passing Technology) based controllers + * + * This code is based on drivers/scsi/mpt2sas/mpt2_debug.c + * Copyright (C) 2007-2008 LSI Corporation + * (mailto:DL-MPTFusionLinux@lsi.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * NO WARRANTY + * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT + * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is + * solely responsible for determining the appropriateness of using and + * distributing the Program and assumes all risks associated with its + * exercise of rights under this Agreement, including but not limited to + * the risks and costs of program errors, damage to or loss of data, + * programs or equipment, and unavailability or interruption of operations. + + * DISCLAIMER OF LIABILITY + * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED + * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#ifndef MPT2SAS_DEBUG_H_INCLUDED +#define MPT2SAS_DEBUG_H_INCLUDED + +#define MPT_DEBUG 0x00000001 +#define MPT_DEBUG_MSG_FRAME 0x00000002 +#define MPT_DEBUG_SG 0x00000004 +#define MPT_DEBUG_EVENTS 0x00000008 +#define MPT_DEBUG_EVENT_WORK_TASK 0x00000010 +#define MPT_DEBUG_INIT 0x00000020 +#define MPT_DEBUG_EXIT 0x00000040 +#define MPT_DEBUG_FAIL 0x00000080 +#define MPT_DEBUG_TM 0x00000100 +#define MPT_DEBUG_REPLY 0x00000200 +#define MPT_DEBUG_HANDSHAKE 0x00000400 +#define MPT_DEBUG_CONFIG 0x00000800 +#define MPT_DEBUG_DL 0x00001000 +#define MPT_DEBUG_RESET 0x00002000 +#define MPT_DEBUG_SCSI 0x00004000 +#define MPT_DEBUG_IOCTL 0x00008000 +#define MPT_DEBUG_CSMISAS 0x00010000 +#define MPT_DEBUG_SAS 0x00020000 +#define MPT_DEBUG_TRANSPORT 0x00040000 +#define MPT_DEBUG_TASK_SET_FULL 0x00080000 + +#define MPT_DEBUG_TARGET_MODE 0x00100000 + + +/* + * CONFIG_SCSI_MPT2SAS_LOGGING - enabled in Kconfig + */ + +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING +#define MPT_CHECK_LOGGING(IOC, CMD, BITS) \ +{ \ + if (IOC->logging_level & BITS) \ + CMD; \ +} +#else +#define MPT_CHECK_LOGGING(IOC, CMD, BITS) +#endif /* CONFIG_SCSI_MPT2SAS_LOGGING */ + + +/* + * debug macros + */ + +#define dprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG) + +#define dsgprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SG) + +#define devtprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EVENTS) + +#define dewtprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EVENT_WORK_TASK) + +#define dinitprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_INIT) + +#define dexitprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EXIT) + +#define dfailprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_FAIL) + +#define dtmprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TM) + +#define dreplyprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_REPLY) + +#define dhsprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_HANDSHAKE) + +#define dcprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_CONFIG) + +#define ddlprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_DL) + +#define drsprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_RESET) + +#define dsprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SCSI) + +#define dctlprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_IOCTL) + +#define dcsmisasprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_CSMISAS) + +#define dsasprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS) + +#define dsastransport(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS_WIDE) + +#define dmfprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_MSG_FRAME) + +#define dtsfprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TASK_SET_FULL) + +#define dtransportprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TRANSPORT) + +#define dTMprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TARGET_MODE) + +/* inline functions for dumping debug data*/ +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING +/** + * _debug_dump_mf - print message frame contents + * @mpi_request: pointer to message frame + * @sz: number of dwords + */ +static inline void +_debug_dump_mf(void *mpi_request, int sz) +{ + int i; + u32 *mfp = (u32 *)mpi_request; + + printk(KERN_INFO "mf:\n\t"); + for (i = 0; i < sz; i++) { + if (i && ((i % 8) == 0)) + printk("\n\t"); + printk("%08x ", le32_to_cpu(mfp[i])); + } + printk("\n"); +} +#else +#define _debug_dump_mf(mpi_request, sz) +#endif /* CONFIG_SCSI_MPT2SAS_LOGGING */ + +#endif /* MPT2SAS_DEBUG_H_INCLUDED */ diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c new file mode 100644 index 00000000000..50865a8e1a4 --- /dev/null +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -0,0 +1,5687 @@ +/* + * Scsi Host Layer for MPT (Message Passing Technology) based controllers + * + * This code is based on drivers/scsi/mpt2sas/mpt2_scsih.c + * Copyright (C) 2007-2008 LSI Corporation + * (mailto:DL-MPTFusionLinux@lsi.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * NO WARRANTY + * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT + * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is + * solely responsible for determining the appropriateness of using and + * distributing the Program and assumes all risks associated with its + * exercise of rights under this Agreement, including but not limited to + * the risks and costs of program errors, damage to or loss of data, + * programs or equipment, and unavailability or interruption of operations. + + * DISCLAIMER OF LIABILITY + * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED + * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mpt2sas_base.h" + +MODULE_AUTHOR(MPT2SAS_AUTHOR); +MODULE_DESCRIPTION(MPT2SAS_DESCRIPTION); +MODULE_LICENSE("GPL"); +MODULE_VERSION(MPT2SAS_DRIVER_VERSION); + +#define RAID_CHANNEL 1 + +/* forward proto's */ +static void _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc, + struct _sas_node *sas_expander); +static void _firmware_event_work(struct work_struct *work); + +/* global parameters */ +LIST_HEAD(ioc_list); + +/* local parameters */ +static u32 logging_level; +static u8 scsi_io_cb_idx = -1; +static u8 tm_cb_idx = -1; +static u8 ctl_cb_idx = -1; +static u8 base_cb_idx = -1; +static u8 transport_cb_idx = -1; +static u8 config_cb_idx = -1; +static int mpt_ids; + +/* command line options */ +MODULE_PARM_DESC(logging_level, " bits for enabling additional logging info " + "(default=0)"); + +/* scsi-mid layer global parmeter is max_report_luns, which is 511 */ +#define MPT2SAS_MAX_LUN (16895) +static int max_lun = MPT2SAS_MAX_LUN; +module_param(max_lun, int, 0); +MODULE_PARM_DESC(max_lun, " max lun, default=16895 "); + +/** + * struct sense_info - common structure for obtaining sense keys + * @skey: sense key + * @asc: additional sense code + * @ascq: additional sense code qualifier + */ +struct sense_info { + u8 skey; + u8 asc; + u8 ascq; +}; + + +#define MPT2SAS_RESCAN_AFTER_HOST_RESET (0xFFFF) +/** + * struct fw_event_work - firmware event struct + * @list: link list framework + * @work: work object (ioc->fault_reset_work_q) + * @ioc: per adapter object + * @VF_ID: virtual function id + * @host_reset_handling: handling events during host reset + * @ignore: flag meaning this event has been marked to ignore + * @event: firmware event MPI2_EVENT_XXX defined in mpt2_ioc.h + * @event_data: reply event data payload follows + * + * This object stored on ioc->fw_event_list. + */ +struct fw_event_work { + struct list_head list; + struct delayed_work work; + struct MPT2SAS_ADAPTER *ioc; + u8 VF_ID; + u8 host_reset_handling; + u8 ignore; + u16 event; + void *event_data; +}; + +/** + * struct _scsi_io_transfer - scsi io transfer + * @handle: sas device handle (assigned by firmware) + * @is_raid: flag set for hidden raid components + * @dir: DMA_TO_DEVICE, DMA_FROM_DEVICE, + * @data_length: data transfer length + * @data_dma: dma pointer to data + * @sense: sense data + * @lun: lun number + * @cdb_length: cdb length + * @cdb: cdb contents + * @valid_reply: flag set for reply message + * @timeout: timeout for this command + * @sense_length: sense length + * @ioc_status: ioc status + * @scsi_state: scsi state + * @scsi_status: scsi staus + * @log_info: log information + * @transfer_length: data length transfer when there is a reply message + * + * Used for sending internal scsi commands to devices within this module. + * Refer to _scsi_send_scsi_io(). + */ +struct _scsi_io_transfer { + u16 handle; + u8 is_raid; + enum dma_data_direction dir; + u32 data_length; + dma_addr_t data_dma; + u8 sense[SCSI_SENSE_BUFFERSIZE]; + u32 lun; + u8 cdb_length; + u8 cdb[32]; + u8 timeout; + u8 valid_reply; + /* the following bits are only valid when 'valid_reply = 1' */ + u32 sense_length; + u16 ioc_status; + u8 scsi_state; + u8 scsi_status; + u32 log_info; + u32 transfer_length; +}; + +/* + * The pci device ids are defined in mpi/mpi2_cnfg.h. + */ +static struct pci_device_id scsih_pci_table[] = { + { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2004, + PCI_ANY_ID, PCI_ANY_ID }, + /* Falcon ~ 2008*/ + { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2008, + PCI_ANY_ID, PCI_ANY_ID }, + /* Liberator ~ 2108 */ + { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_1, + PCI_ANY_ID, PCI_ANY_ID }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_2, + PCI_ANY_ID, PCI_ANY_ID }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_3, + PCI_ANY_ID, PCI_ANY_ID }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_1, + PCI_ANY_ID, PCI_ANY_ID }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_2, + PCI_ANY_ID, PCI_ANY_ID }, + {0} /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(pci, scsih_pci_table); + +/** + * scsih_set_debug_level - global setting of ioc->logging_level. + * + * Note: The logging levels are defined in mpt2sas_debug.h. + */ +static int +scsih_set_debug_level(const char *val, struct kernel_param *kp) +{ + int ret = param_set_int(val, kp); + struct MPT2SAS_ADAPTER *ioc; + + if (ret) + return ret; + + printk(KERN_INFO "setting logging_level(0x%08x)\n", logging_level); + list_for_each_entry(ioc, &ioc_list, list) + ioc->logging_level = logging_level; + return 0; +} +module_param_call(logging_level, scsih_set_debug_level, param_get_int, + &logging_level, 0644); + +/** + * _scsih_srch_boot_sas_address - search based on sas_address + * @sas_address: sas address + * @boot_device: boot device object from bios page 2 + * + * Returns 1 when there's a match, 0 means no match. + */ +static inline int +_scsih_srch_boot_sas_address(u64 sas_address, + Mpi2BootDeviceSasWwid_t *boot_device) +{ + return (sas_address == le64_to_cpu(boot_device->SASAddress)) ? 1 : 0; +} + +/** + * _scsih_srch_boot_device_name - search based on device name + * @device_name: device name specified in INDENTIFY fram + * @boot_device: boot device object from bios page 2 + * + * Returns 1 when there's a match, 0 means no match. + */ +static inline int +_scsih_srch_boot_device_name(u64 device_name, + Mpi2BootDeviceDeviceName_t *boot_device) +{ + return (device_name == le64_to_cpu(boot_device->DeviceName)) ? 1 : 0; +} + +/** + * _scsih_srch_boot_encl_slot - search based on enclosure_logical_id/slot + * @enclosure_logical_id: enclosure logical id + * @slot_number: slot number + * @boot_device: boot device object from bios page 2 + * + * Returns 1 when there's a match, 0 means no match. + */ +static inline int +_scsih_srch_boot_encl_slot(u64 enclosure_logical_id, u16 slot_number, + Mpi2BootDeviceEnclosureSlot_t *boot_device) +{ + return (enclosure_logical_id == le64_to_cpu(boot_device-> + EnclosureLogicalID) && slot_number == le16_to_cpu(boot_device-> + SlotNumber)) ? 1 : 0; +} + +/** + * _scsih_is_boot_device - search for matching boot device. + * @sas_address: sas address + * @device_name: device name specified in INDENTIFY fram + * @enclosure_logical_id: enclosure logical id + * @slot_number: slot number + * @form: specifies boot device form + * @boot_device: boot device object from bios page 2 + * + * Returns 1 when there's a match, 0 means no match. + */ +static int +_scsih_is_boot_device(u64 sas_address, u64 device_name, + u64 enclosure_logical_id, u16 slot, u8 form, + Mpi2BiosPage2BootDevice_t *boot_device) +{ + int rc = 0; + + switch (form) { + case MPI2_BIOSPAGE2_FORM_SAS_WWID: + if (!sas_address) + break; + rc = _scsih_srch_boot_sas_address( + sas_address, &boot_device->SasWwid); + break; + case MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT: + if (!enclosure_logical_id) + break; + rc = _scsih_srch_boot_encl_slot( + enclosure_logical_id, + slot, &boot_device->EnclosureSlot); + break; + case MPI2_BIOSPAGE2_FORM_DEVICE_NAME: + if (!device_name) + break; + rc = _scsih_srch_boot_device_name( + device_name, &boot_device->DeviceName); + break; + case MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED: + break; + } + + return rc; +} + +/** + * _scsih_determine_boot_device - determine boot device. + * @ioc: per adapter object + * @device: either sas_device or raid_device object + * @is_raid: [flag] 1 = raid object, 0 = sas object + * + * Determines whether this device should be first reported device to + * to scsi-ml or sas transport, this purpose is for persistant boot device. + * There are primary, alternate, and current entries in bios page 2. The order + * priority is primary, alternate, then current. This routine saves + * the corresponding device object and is_raid flag in the ioc object. + * The saved data to be used later in _scsih_probe_boot_devices(). + */ +static void +_scsih_determine_boot_device(struct MPT2SAS_ADAPTER *ioc, + void *device, u8 is_raid) +{ + struct _sas_device *sas_device; + struct _raid_device *raid_device; + u64 sas_address; + u64 device_name; + u64 enclosure_logical_id; + u16 slot; + + /* only process this function when driver loads */ + if (!ioc->wait_for_port_enable_to_complete) + return; + + if (!is_raid) { + sas_device = device; + sas_address = sas_device->sas_address; + device_name = sas_device->device_name; + enclosure_logical_id = sas_device->enclosure_logical_id; + slot = sas_device->slot; + } else { + raid_device = device; + sas_address = raid_device->wwid; + device_name = 0; + enclosure_logical_id = 0; + slot = 0; + } + + if (!ioc->req_boot_device.device) { + if (_scsih_is_boot_device(sas_address, device_name, + enclosure_logical_id, slot, + (ioc->bios_pg2.ReqBootDeviceForm & + MPI2_BIOSPAGE2_FORM_MASK), + &ioc->bios_pg2.RequestedBootDevice)) { + dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT + "%s: req_boot_device(0x%016llx)\n", + ioc->name, __func__, + (unsigned long long)sas_address)); + ioc->req_boot_device.device = device; + ioc->req_boot_device.is_raid = is_raid; + } + } + + if (!ioc->req_alt_boot_device.device) { + if (_scsih_is_boot_device(sas_address, device_name, + enclosure_logical_id, slot, + (ioc->bios_pg2.ReqAltBootDeviceForm & + MPI2_BIOSPAGE2_FORM_MASK), + &ioc->bios_pg2.RequestedAltBootDevice)) { + dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT + "%s: req_alt_boot_device(0x%016llx)\n", + ioc->name, __func__, + (unsigned long long)sas_address)); + ioc->req_alt_boot_device.device = device; + ioc->req_alt_boot_device.is_raid = is_raid; + } + } + + if (!ioc->current_boot_device.device) { + if (_scsih_is_boot_device(sas_address, device_name, + enclosure_logical_id, slot, + (ioc->bios_pg2.CurrentBootDeviceForm & + MPI2_BIOSPAGE2_FORM_MASK), + &ioc->bios_pg2.CurrentBootDevice)) { + dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT + "%s: current_boot_device(0x%016llx)\n", + ioc->name, __func__, + (unsigned long long)sas_address)); + ioc->current_boot_device.device = device; + ioc->current_boot_device.is_raid = is_raid; + } + } +} + +/** + * mpt2sas_scsih_sas_device_find_by_sas_address - sas device search + * @ioc: per adapter object + * @sas_address: sas address + * Context: Calling function should acquire ioc->sas_device_lock + * + * This searches for sas_device based on sas_address, then return sas_device + * object. + */ +struct _sas_device * +mpt2sas_scsih_sas_device_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc, + u64 sas_address) +{ + struct _sas_device *sas_device, *r; + + r = NULL; + /* check the sas_device_init_list */ + list_for_each_entry(sas_device, &ioc->sas_device_init_list, + list) { + if (sas_device->sas_address != sas_address) + continue; + r = sas_device; + goto out; + } + + /* then check the sas_device_list */ + list_for_each_entry(sas_device, &ioc->sas_device_list, list) { + if (sas_device->sas_address != sas_address) + continue; + r = sas_device; + goto out; + } + out: + return r; +} + +/** + * _scsih_sas_device_find_by_handle - sas device search + * @ioc: per adapter object + * @handle: sas device handle (assigned by firmware) + * Context: Calling function should acquire ioc->sas_device_lock + * + * This searches for sas_device based on sas_address, then return sas_device + * object. + */ +static struct _sas_device * +_scsih_sas_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) +{ + struct _sas_device *sas_device, *r; + + r = NULL; + if (ioc->wait_for_port_enable_to_complete) { + list_for_each_entry(sas_device, &ioc->sas_device_init_list, + list) { + if (sas_device->handle != handle) + continue; + r = sas_device; + goto out; + } + } else { + list_for_each_entry(sas_device, &ioc->sas_device_list, list) { + if (sas_device->handle != handle) + continue; + r = sas_device; + goto out; + } + } + + out: + return r; +} + +/** + * _scsih_sas_device_remove - remove sas_device from list. + * @ioc: per adapter object + * @sas_device: the sas_device object + * Context: This function will acquire ioc->sas_device_lock. + * + * Removing object and freeing associated memory from the ioc->sas_device_list. + */ +static void +_scsih_sas_device_remove(struct MPT2SAS_ADAPTER *ioc, + struct _sas_device *sas_device) +{ + unsigned long flags; + + spin_lock_irqsave(&ioc->sas_device_lock, flags); + list_del(&sas_device->list); + memset(sas_device, 0, sizeof(struct _sas_device)); + kfree(sas_device); + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); +} + +/** + * _scsih_sas_device_add - insert sas_device to the list. + * @ioc: per adapter object + * @sas_device: the sas_device object + * Context: This function will acquire ioc->sas_device_lock. + * + * Adding new object to the ioc->sas_device_list. + */ +static void +_scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc, + struct _sas_device *sas_device) +{ + unsigned long flags; + u16 handle, parent_handle; + u64 sas_address; + + dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle" + "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__, + sas_device->handle, (unsigned long long)sas_device->sas_address)); + + spin_lock_irqsave(&ioc->sas_device_lock, flags); + list_add_tail(&sas_device->list, &ioc->sas_device_list); + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + + handle = sas_device->handle; + parent_handle = sas_device->parent_handle; + sas_address = sas_device->sas_address; + if (!mpt2sas_transport_port_add(ioc, handle, parent_handle)) { + _scsih_sas_device_remove(ioc, sas_device); + } else if (!sas_device->starget) { + mpt2sas_transport_port_remove(ioc, sas_address, parent_handle); + _scsih_sas_device_remove(ioc, sas_device); + } +} + +/** + * _scsih_sas_device_init_add - insert sas_device to the list. + * @ioc: per adapter object + * @sas_device: the sas_device object + * Context: This function will acquire ioc->sas_device_lock. + * + * Adding new object at driver load time to the ioc->sas_device_init_list. + */ +static void +_scsih_sas_device_init_add(struct MPT2SAS_ADAPTER *ioc, + struct _sas_device *sas_device) +{ + unsigned long flags; + + dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle" + "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__, + sas_device->handle, (unsigned long long)sas_device->sas_address)); + + spin_lock_irqsave(&ioc->sas_device_lock, flags); + list_add_tail(&sas_device->list, &ioc->sas_device_init_list); + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + _scsih_determine_boot_device(ioc, sas_device, 0); +} + +/** + * mpt2sas_scsih_expander_find_by_handle - expander device search + * @ioc: per adapter object + * @handle: expander handle (assigned by firmware) + * Context: Calling function should acquire ioc->sas_device_lock + * + * This searches for expander device based on handle, then returns the + * sas_node object. + */ +struct _sas_node * +mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) +{ + struct _sas_node *sas_expander, *r; + + r = NULL; + list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { + if (sas_expander->handle != handle) + continue; + r = sas_expander; + goto out; + } + out: + return r; +} + +/** + * _scsih_raid_device_find_by_id - raid device search + * @ioc: per adapter object + * @id: sas device target id + * @channel: sas device channel + * Context: Calling function should acquire ioc->raid_device_lock + * + * This searches for raid_device based on target id, then return raid_device + * object. + */ +static struct _raid_device * +_scsih_raid_device_find_by_id(struct MPT2SAS_ADAPTER *ioc, int id, int channel) +{ + struct _raid_device *raid_device, *r; + + r = NULL; + list_for_each_entry(raid_device, &ioc->raid_device_list, list) { + if (raid_device->id == id && raid_device->channel == channel) { + r = raid_device; + goto out; + } + } + + out: + return r; +} + +/** + * _scsih_raid_device_find_by_handle - raid device search + * @ioc: per adapter object + * @handle: sas device handle (assigned by firmware) + * Context: Calling function should acquire ioc->raid_device_lock + * + * This searches for raid_device based on handle, then return raid_device + * object. + */ +static struct _raid_device * +_scsih_raid_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) +{ + struct _raid_device *raid_device, *r; + + r = NULL; + list_for_each_entry(raid_device, &ioc->raid_device_list, list) { + if (raid_device->handle != handle) + continue; + r = raid_device; + goto out; + } + + out: + return r; +} + +/** + * _scsih_raid_device_find_by_wwid - raid device search + * @ioc: per adapter object + * @handle: sas device handle (assigned by firmware) + * Context: Calling function should acquire ioc->raid_device_lock + * + * This searches for raid_device based on wwid, then return raid_device + * object. + */ +static struct _raid_device * +_scsih_raid_device_find_by_wwid(struct MPT2SAS_ADAPTER *ioc, u64 wwid) +{ + struct _raid_device *raid_device, *r; + + r = NULL; + list_for_each_entry(raid_device, &ioc->raid_device_list, list) { + if (raid_device->wwid != wwid) + continue; + r = raid_device; + goto out; + } + + out: + return r; +} + +/** + * _scsih_raid_device_add - add raid_device object + * @ioc: per adapter object + * @raid_device: raid_device object + * + * This is added to the raid_device_list link list. + */ +static void +_scsih_raid_device_add(struct MPT2SAS_ADAPTER *ioc, + struct _raid_device *raid_device) +{ + unsigned long flags; + + dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle" + "(0x%04x), wwid(0x%016llx)\n", ioc->name, __func__, + raid_device->handle, (unsigned long long)raid_device->wwid)); + + spin_lock_irqsave(&ioc->raid_device_lock, flags); + list_add_tail(&raid_device->list, &ioc->raid_device_list); + spin_unlock_irqrestore(&ioc->raid_device_lock, flags); +} + +/** + * _scsih_raid_device_remove - delete raid_device object + * @ioc: per adapter object + * @raid_device: raid_device object + * + * This is removed from the raid_device_list link list. + */ +static void +_scsih_raid_device_remove(struct MPT2SAS_ADAPTER *ioc, + struct _raid_device *raid_device) +{ + unsigned long flags; + + spin_lock_irqsave(&ioc->raid_device_lock, flags); + list_del(&raid_device->list); + memset(raid_device, 0, sizeof(struct _raid_device)); + kfree(raid_device); + spin_unlock_irqrestore(&ioc->raid_device_lock, flags); +} + +/** + * mpt2sas_scsih_expander_find_by_sas_address - expander device search + * @ioc: per adapter object + * @sas_address: sas address + * Context: Calling function should acquire ioc->sas_node_lock. + * + * This searches for expander device based on sas_address, then returns the + * sas_node object. + */ +struct _sas_node * +mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc, + u64 sas_address) +{ + struct _sas_node *sas_expander, *r; + + r = NULL; + list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { + if (sas_expander->sas_address != sas_address) + continue; + r = sas_expander; + goto out; + } + out: + return r; +} + +/** + * _scsih_expander_node_add - insert expander device to the list. + * @ioc: per adapter object + * @sas_expander: the sas_device object + * Context: This function will acquire ioc->sas_node_lock. + * + * Adding new object to the ioc->sas_expander_list. + * + * Return nothing. + */ +static void +_scsih_expander_node_add(struct MPT2SAS_ADAPTER *ioc, + struct _sas_node *sas_expander) +{ + unsigned long flags; + + spin_lock_irqsave(&ioc->sas_node_lock, flags); + list_add_tail(&sas_expander->list, &ioc->sas_expander_list); + spin_unlock_irqrestore(&ioc->sas_node_lock, flags); +} + +/** + * _scsih_is_end_device - determines if device is an end device + * @device_info: bitfield providing information about the device. + * Context: none + * + * Returns 1 if end device. + */ +static int +_scsih_is_end_device(u32 device_info) +{ + if (device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE && + ((device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) | + (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET) | + (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE))) + return 1; + else + return 0; +} + +/** + * _scsih_scsi_lookup_get - returns scmd entry + * @ioc: per adapter object + * @smid: system request message index + * Context: This function will acquire ioc->scsi_lookup_lock. + * + * Returns the smid stored scmd pointer. + */ +static struct scsi_cmnd * +_scsih_scsi_lookup_get(struct MPT2SAS_ADAPTER *ioc, u16 smid) +{ + unsigned long flags; + struct scsi_cmnd *scmd; + + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); + scmd = ioc->scsi_lookup[smid - 1].scmd; + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); + return scmd; +} + +/** + * mptscsih_getclear_scsi_lookup - returns scmd entry + * @ioc: per adapter object + * @smid: system request message index + * Context: This function will acquire ioc->scsi_lookup_lock. + * + * Returns the smid stored scmd pointer, as well as clearing the scmd pointer. + */ +static struct scsi_cmnd * +_scsih_scsi_lookup_getclear(struct MPT2SAS_ADAPTER *ioc, u16 smid) +{ + unsigned long flags; + struct scsi_cmnd *scmd; + + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); + scmd = ioc->scsi_lookup[smid - 1].scmd; + ioc->scsi_lookup[smid - 1].scmd = NULL; + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); + return scmd; +} + +/** + * _scsih_scsi_lookup_set - updates scmd entry in lookup + * @ioc: per adapter object + * @smid: system request message index + * @scmd: pointer to scsi command object + * Context: This function will acquire ioc->scsi_lookup_lock. + * + * This will save scmd pointer in the scsi_lookup array. + * + * Return nothing. + */ +static void +_scsih_scsi_lookup_set(struct MPT2SAS_ADAPTER *ioc, u16 smid, + struct scsi_cmnd *scmd) +{ + unsigned long flags; + + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); + ioc->scsi_lookup[smid - 1].scmd = scmd; + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); +} + +/** + * _scsih_scsi_lookup_find_by_scmd - scmd lookup + * @ioc: per adapter object + * @smid: system request message index + * @scmd: pointer to scsi command object + * Context: This function will acquire ioc->scsi_lookup_lock. + * + * This will search for a scmd pointer in the scsi_lookup array, + * returning the revelent smid. A returned value of zero means invalid. + */ +static u16 +_scsih_scsi_lookup_find_by_scmd(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd + *scmd) +{ + u16 smid; + unsigned long flags; + int i; + + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); + smid = 0; + for (i = 0; i < ioc->request_depth; i++) { + if (ioc->scsi_lookup[i].scmd == scmd) { + smid = i + 1; + goto out; + } + } + out: + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); + return smid; +} + +/** + * _scsih_scsi_lookup_find_by_target - search for matching channel:id + * @ioc: per adapter object + * @id: target id + * @channel: channel + * Context: This function will acquire ioc->scsi_lookup_lock. + * + * This will search for a matching channel:id in the scsi_lookup array, + * returning 1 if found. + */ +static u8 +_scsih_scsi_lookup_find_by_target(struct MPT2SAS_ADAPTER *ioc, int id, + int channel) +{ + u8 found; + unsigned long flags; + int i; + + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); + found = 0; + for (i = 0 ; i < ioc->request_depth; i++) { + if (ioc->scsi_lookup[i].scmd && + (ioc->scsi_lookup[i].scmd->device->id == id && + ioc->scsi_lookup[i].scmd->device->channel == channel)) { + found = 1; + goto out; + } + } + out: + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); + return found; +} + +/** + * _scsih_get_chain_buffer_dma - obtain block of chains (dma address) + * @ioc: per adapter object + * @smid: system request message index + * + * Returns phys pointer to chain buffer. + */ +static dma_addr_t +_scsih_get_chain_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid) +{ + return ioc->chain_dma + ((smid - 1) * (ioc->request_sz * + ioc->chains_needed_per_io)); +} + +/** + * _scsih_get_chain_buffer - obtain block of chains assigned to a mf request + * @ioc: per adapter object + * @smid: system request message index + * + * Returns virt pointer to chain buffer. + */ +static void * +_scsih_get_chain_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid) +{ + return (void *)(ioc->chain + ((smid - 1) * (ioc->request_sz * + ioc->chains_needed_per_io))); +} + +/** + * _scsih_build_scatter_gather - main sg creation routine + * @ioc: per adapter object + * @scmd: scsi command + * @smid: system request message index + * Context: none. + * + * The main routine that builds scatter gather table from a given + * scsi request sent via the .queuecommand main handler. + * + * Returns 0 success, anything else error + */ +static int +_scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc, + struct scsi_cmnd *scmd, u16 smid) +{ + Mpi2SCSIIORequest_t *mpi_request; + dma_addr_t chain_dma; + struct scatterlist *sg_scmd; + void *sg_local, *chain; + u32 chain_offset; + u32 chain_length; + u32 chain_flags; + u32 sges_left; + u32 sges_in_segment; + u32 sgl_flags; + u32 sgl_flags_last_element; + u32 sgl_flags_end_buffer; + + mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); + + /* init scatter gather flags */ + sgl_flags = MPI2_SGE_FLAGS_SIMPLE_ELEMENT; + if (scmd->sc_data_direction == DMA_TO_DEVICE) + sgl_flags |= MPI2_SGE_FLAGS_HOST_TO_IOC; + sgl_flags_last_element = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT) + << MPI2_SGE_FLAGS_SHIFT; + sgl_flags_end_buffer = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT | + MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST) + << MPI2_SGE_FLAGS_SHIFT; + sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; + + sg_scmd = scsi_sglist(scmd); + sges_left = scsi_dma_map(scmd); + if (!sges_left) { + sdev_printk(KERN_ERR, scmd->device, "pci_map_sg" + " failed: request for %d bytes!\n", scsi_bufflen(scmd)); + return -ENOMEM; + } + + sg_local = &mpi_request->SGL; + sges_in_segment = ioc->max_sges_in_main_message; + if (sges_left <= sges_in_segment) + goto fill_in_last_segment; + + mpi_request->ChainOffset = (offsetof(Mpi2SCSIIORequest_t, SGL) + + (sges_in_segment * ioc->sge_size))/4; + + /* fill in main message segment when there is a chain following */ + while (sges_in_segment) { + if (sges_in_segment == 1) + ioc->base_add_sg_single(sg_local, + sgl_flags_last_element | sg_dma_len(sg_scmd), + sg_dma_address(sg_scmd)); + else + ioc->base_add_sg_single(sg_local, sgl_flags | + sg_dma_len(sg_scmd), sg_dma_address(sg_scmd)); + sg_scmd = sg_next(sg_scmd); + sg_local += ioc->sge_size; + sges_left--; + sges_in_segment--; + } + + /* initializing the chain flags and pointers */ + chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT; + chain = _scsih_get_chain_buffer(ioc, smid); + chain_dma = _scsih_get_chain_buffer_dma(ioc, smid); + do { + sges_in_segment = (sges_left <= + ioc->max_sges_in_chain_message) ? sges_left : + ioc->max_sges_in_chain_message; + chain_offset = (sges_left == sges_in_segment) ? + 0 : (sges_in_segment * ioc->sge_size)/4; + chain_length = sges_in_segment * ioc->sge_size; + if (chain_offset) { + chain_offset = chain_offset << + MPI2_SGE_CHAIN_OFFSET_SHIFT; + chain_length += ioc->sge_size; + } + ioc->base_add_sg_single(sg_local, chain_flags | chain_offset | + chain_length, chain_dma); + sg_local = chain; + if (!chain_offset) + goto fill_in_last_segment; + + /* fill in chain segments */ + while (sges_in_segment) { + if (sges_in_segment == 1) + ioc->base_add_sg_single(sg_local, + sgl_flags_last_element | + sg_dma_len(sg_scmd), + sg_dma_address(sg_scmd)); + else + ioc->base_add_sg_single(sg_local, sgl_flags | + sg_dma_len(sg_scmd), + sg_dma_address(sg_scmd)); + sg_scmd = sg_next(sg_scmd); + sg_local += ioc->sge_size; + sges_left--; + sges_in_segment--; + } + + chain_dma += ioc->request_sz; + chain += ioc->request_sz; + } while (1); + + + fill_in_last_segment: + + /* fill the last segment */ + while (sges_left) { + if (sges_left == 1) + ioc->base_add_sg_single(sg_local, sgl_flags_end_buffer | + sg_dma_len(sg_scmd), sg_dma_address(sg_scmd)); + else + ioc->base_add_sg_single(sg_local, sgl_flags | + sg_dma_len(sg_scmd), sg_dma_address(sg_scmd)); + sg_scmd = sg_next(sg_scmd); + sg_local += ioc->sge_size; + sges_left--; + } + + return 0; +} + +/** + * scsih_change_queue_depth - setting device queue depth + * @sdev: scsi device struct + * @qdepth: requested queue depth + * + * Returns queue depth. + */ +static int +scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) +{ + struct Scsi_Host *shost = sdev->host; + int max_depth; + int tag_type; + + max_depth = shost->can_queue; + if (!sdev->tagged_supported) + max_depth = 1; + if (qdepth > max_depth) + qdepth = max_depth; + tag_type = (qdepth == 1) ? 0 : MSG_SIMPLE_TAG; + scsi_adjust_queue_depth(sdev, tag_type, qdepth); + + if (sdev->inquiry_len > 7) + sdev_printk(KERN_INFO, sdev, "qdepth(%d), tagged(%d), " + "simple(%d), ordered(%d), scsi_level(%d), cmd_que(%d)\n", + sdev->queue_depth, sdev->tagged_supported, sdev->simple_tags, + sdev->ordered_tags, sdev->scsi_level, + (sdev->inquiry[7] & 2) >> 1); + + return sdev->queue_depth; +} + +/** + * scsih_change_queue_depth - changing device queue tag type + * @sdev: scsi device struct + * @tag_type: requested tag type + * + * Returns queue tag type. + */ +static int +scsih_change_queue_type(struct scsi_device *sdev, int tag_type) +{ + if (sdev->tagged_supported) { + scsi_set_tag_type(sdev, tag_type); + if (tag_type) + scsi_activate_tcq(sdev, sdev->queue_depth); + else + scsi_deactivate_tcq(sdev, sdev->queue_depth); + } else + tag_type = 0; + + return tag_type; +} + +/** + * scsih_target_alloc - target add routine + * @starget: scsi target struct + * + * Returns 0 if ok. Any other return is assumed to be an error and + * the device is ignored. + */ +static int +scsih_target_alloc(struct scsi_target *starget) +{ + struct Scsi_Host *shost = dev_to_shost(&starget->dev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + struct MPT2SAS_TARGET *sas_target_priv_data; + struct _sas_device *sas_device; + struct _raid_device *raid_device; + unsigned long flags; + struct sas_rphy *rphy; + + sas_target_priv_data = kzalloc(sizeof(struct scsi_target), GFP_KERNEL); + if (!sas_target_priv_data) + return -ENOMEM; + + starget->hostdata = sas_target_priv_data; + sas_target_priv_data->starget = starget; + sas_target_priv_data->handle = MPT2SAS_INVALID_DEVICE_HANDLE; + + /* RAID volumes */ + if (starget->channel == RAID_CHANNEL) { + spin_lock_irqsave(&ioc->raid_device_lock, flags); + raid_device = _scsih_raid_device_find_by_id(ioc, starget->id, + starget->channel); + if (raid_device) { + sas_target_priv_data->handle = raid_device->handle; + sas_target_priv_data->sas_address = raid_device->wwid; + sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME; + raid_device->starget = starget; + } + spin_unlock_irqrestore(&ioc->raid_device_lock, flags); + return 0; + } + + /* sas/sata devices */ + spin_lock_irqsave(&ioc->sas_device_lock, flags); + rphy = dev_to_rphy(starget->dev.parent); + sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, + rphy->identify.sas_address); + + if (sas_device) { + sas_target_priv_data->handle = sas_device->handle; + sas_target_priv_data->sas_address = sas_device->sas_address; + sas_device->starget = starget; + sas_device->id = starget->id; + sas_device->channel = starget->channel; + if (sas_device->hidden_raid_component) + sas_target_priv_data->flags |= + MPT_TARGET_FLAGS_RAID_COMPONENT; + } + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + + return 0; +} + +/** + * scsih_target_destroy - target destroy routine + * @starget: scsi target struct + * + * Returns nothing. + */ +static void +scsih_target_destroy(struct scsi_target *starget) +{ + struct Scsi_Host *shost = dev_to_shost(&starget->dev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + struct MPT2SAS_TARGET *sas_target_priv_data; + struct _sas_device *sas_device; + struct _raid_device *raid_device; + unsigned long flags; + struct sas_rphy *rphy; + + sas_target_priv_data = starget->hostdata; + if (!sas_target_priv_data) + return; + + if (starget->channel == RAID_CHANNEL) { + spin_lock_irqsave(&ioc->raid_device_lock, flags); + raid_device = _scsih_raid_device_find_by_id(ioc, starget->id, + starget->channel); + if (raid_device) { + raid_device->starget = NULL; + raid_device->sdev = NULL; + } + spin_unlock_irqrestore(&ioc->raid_device_lock, flags); + goto out; + } + + spin_lock_irqsave(&ioc->sas_device_lock, flags); + rphy = dev_to_rphy(starget->dev.parent); + sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, + rphy->identify.sas_address); + if (sas_device) + sas_device->starget = NULL; + + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + + out: + kfree(sas_target_priv_data); + starget->hostdata = NULL; +} + +/** + * scsih_slave_alloc - device add routine + * @sdev: scsi device struct + * + * Returns 0 if ok. Any other return is assumed to be an error and + * the device is ignored. + */ +static int +scsih_slave_alloc(struct scsi_device *sdev) +{ + struct Scsi_Host *shost; + struct MPT2SAS_ADAPTER *ioc; + struct MPT2SAS_TARGET *sas_target_priv_data; + struct MPT2SAS_DEVICE *sas_device_priv_data; + struct scsi_target *starget; + struct _raid_device *raid_device; + struct _sas_device *sas_device; + unsigned long flags; + + sas_device_priv_data = kzalloc(sizeof(struct scsi_device), GFP_KERNEL); + if (!sas_device_priv_data) + return -ENOMEM; + + sas_device_priv_data->lun = sdev->lun; + sas_device_priv_data->flags = MPT_DEVICE_FLAGS_INIT; + + starget = scsi_target(sdev); + sas_target_priv_data = starget->hostdata; + sas_target_priv_data->num_luns++; + sas_device_priv_data->sas_target = sas_target_priv_data; + sdev->hostdata = sas_device_priv_data; + if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT)) + sdev->no_uld_attach = 1; + + shost = dev_to_shost(&starget->dev); + ioc = shost_priv(shost); + if (starget->channel == RAID_CHANNEL) { + spin_lock_irqsave(&ioc->raid_device_lock, flags); + raid_device = _scsih_raid_device_find_by_id(ioc, + starget->id, starget->channel); + if (raid_device) + raid_device->sdev = sdev; /* raid is single lun */ + spin_unlock_irqrestore(&ioc->raid_device_lock, flags); + } else { + /* set TLR bit for SSP devices */ + if (!(ioc->facts.IOCCapabilities & + MPI2_IOCFACTS_CAPABILITY_TLR)) + goto out; + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, + sas_device_priv_data->sas_target->sas_address); + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + if (sas_device && sas_device->device_info & + MPI2_SAS_DEVICE_INFO_SSP_TARGET) + sas_device_priv_data->flags |= MPT_DEVICE_TLR_ON; + } + + out: + return 0; +} + +/** + * scsih_slave_destroy - device destroy routine + * @sdev: scsi device struct + * + * Returns nothing. + */ +static void +scsih_slave_destroy(struct scsi_device *sdev) +{ + struct MPT2SAS_TARGET *sas_target_priv_data; + struct scsi_target *starget; + + if (!sdev->hostdata) + return; + + starget = scsi_target(sdev); + sas_target_priv_data = starget->hostdata; + sas_target_priv_data->num_luns--; + kfree(sdev->hostdata); + sdev->hostdata = NULL; +} + +/** + * scsih_display_sata_capabilities - sata capabilities + * @ioc: per adapter object + * @sas_device: the sas_device object + * @sdev: scsi device struct + */ +static void +scsih_display_sata_capabilities(struct MPT2SAS_ADAPTER *ioc, + struct _sas_device *sas_device, struct scsi_device *sdev) +{ + Mpi2ConfigReply_t mpi_reply; + Mpi2SasDevicePage0_t sas_device_pg0; + u32 ioc_status; + u16 flags; + u32 device_info; + + if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, + MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, sas_device->handle))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return; + } + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return; + } + + flags = le16_to_cpu(sas_device_pg0.Flags); + device_info = le16_to_cpu(sas_device_pg0.DeviceInfo); + + sdev_printk(KERN_INFO, sdev, + "atapi(%s), ncq(%s), asyn_notify(%s), smart(%s), fua(%s), " + "sw_preserve(%s)\n", + (device_info & MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? "y" : "n", + (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED) ? "y" : "n", + (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY) ? "y" : + "n", + (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED) ? "y" : "n", + (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED) ? "y" : "n", + (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE) ? "y" : "n"); +} + +/** + * _scsih_get_volume_capabilities - volume capabilities + * @ioc: per adapter object + * @sas_device: the raid_device object + */ +static void +_scsih_get_volume_capabilities(struct MPT2SAS_ADAPTER *ioc, + struct _raid_device *raid_device) +{ + Mpi2RaidVolPage0_t *vol_pg0; + Mpi2RaidPhysDiskPage0_t pd_pg0; + Mpi2SasDevicePage0_t sas_device_pg0; + Mpi2ConfigReply_t mpi_reply; + u16 sz; + u8 num_pds; + + if ((mpt2sas_config_get_number_pds(ioc, raid_device->handle, + &num_pds)) || !num_pds) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return; + } + + raid_device->num_pds = num_pds; + sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds * + sizeof(Mpi2RaidVol0PhysDisk_t)); + vol_pg0 = kzalloc(sz, GFP_KERNEL); + if (!vol_pg0) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return; + } + + if ((mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0, + MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + kfree(vol_pg0); + return; + } + + raid_device->volume_type = vol_pg0->VolumeType; + + /* figure out what the underlying devices are by + * obtaining the device_info bits for the 1st device + */ + if (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply, + &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM, + vol_pg0->PhysDisk[0].PhysDiskNum))) { + if (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, + &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, + le16_to_cpu(pd_pg0.DevHandle)))) { + raid_device->device_info = + le32_to_cpu(sas_device_pg0.DeviceInfo); + } + } + + kfree(vol_pg0); +} + +/** + * scsih_slave_configure - device configure routine. + * @sdev: scsi device struct + * + * Returns 0 if ok. Any other return is assumed to be an error and + * the device is ignored. + */ +static int +scsih_slave_configure(struct scsi_device *sdev) +{ + struct Scsi_Host *shost = sdev->host; + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + struct MPT2SAS_DEVICE *sas_device_priv_data; + struct MPT2SAS_TARGET *sas_target_priv_data; + struct _sas_device *sas_device; + struct _raid_device *raid_device; + unsigned long flags; + int qdepth; + u8 ssp_target = 0; + char *ds = ""; + char *r_level = ""; + + qdepth = 1; + sas_device_priv_data = sdev->hostdata; + sas_device_priv_data->configured_lun = 1; + sas_device_priv_data->flags &= ~MPT_DEVICE_FLAGS_INIT; + sas_target_priv_data = sas_device_priv_data->sas_target; + + /* raid volume handling */ + if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME) { + + spin_lock_irqsave(&ioc->raid_device_lock, flags); + raid_device = _scsih_raid_device_find_by_handle(ioc, + sas_target_priv_data->handle); + spin_unlock_irqrestore(&ioc->raid_device_lock, flags); + if (!raid_device) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return 0; + } + + _scsih_get_volume_capabilities(ioc, raid_device); + + /* RAID Queue Depth Support + * IS volume = underlying qdepth of drive type, either + * MPT2SAS_SAS_QUEUE_DEPTH or MPT2SAS_SATA_QUEUE_DEPTH + * IM/IME/R10 = 128 (MPT2SAS_RAID_QUEUE_DEPTH) + */ + if (raid_device->device_info & + MPI2_SAS_DEVICE_INFO_SSP_TARGET) { + qdepth = MPT2SAS_SAS_QUEUE_DEPTH; + ds = "SSP"; + } else { + qdepth = MPT2SAS_SATA_QUEUE_DEPTH; + if (raid_device->device_info & + MPI2_SAS_DEVICE_INFO_SATA_DEVICE) + ds = "SATA"; + else + ds = "STP"; + } + + switch (raid_device->volume_type) { + case MPI2_RAID_VOL_TYPE_RAID0: + r_level = "RAID0"; + break; + case MPI2_RAID_VOL_TYPE_RAID1E: + qdepth = MPT2SAS_RAID_QUEUE_DEPTH; + r_level = "RAID1E"; + break; + case MPI2_RAID_VOL_TYPE_RAID1: + qdepth = MPT2SAS_RAID_QUEUE_DEPTH; + r_level = "RAID1"; + break; + case MPI2_RAID_VOL_TYPE_RAID10: + qdepth = MPT2SAS_RAID_QUEUE_DEPTH; + r_level = "RAID10"; + break; + case MPI2_RAID_VOL_TYPE_UNKNOWN: + default: + qdepth = MPT2SAS_RAID_QUEUE_DEPTH; + r_level = "RAIDX"; + break; + } + + sdev_printk(KERN_INFO, sdev, "%s: " + "handle(0x%04x), wwid(0x%016llx), pd_count(%d), type(%s)\n", + r_level, raid_device->handle, + (unsigned long long)raid_device->wwid, + raid_device->num_pds, ds); + scsih_change_queue_depth(sdev, qdepth); + return 0; + } + + /* non-raid handling */ + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, + sas_device_priv_data->sas_target->sas_address); + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + if (sas_device) { + if (sas_target_priv_data->flags & + MPT_TARGET_FLAGS_RAID_COMPONENT) { + mpt2sas_config_get_volume_handle(ioc, + sas_device->handle, &sas_device->volume_handle); + mpt2sas_config_get_volume_wwid(ioc, + sas_device->volume_handle, + &sas_device->volume_wwid); + } + if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) { + qdepth = MPT2SAS_SAS_QUEUE_DEPTH; + ssp_target = 1; + ds = "SSP"; + } else { + qdepth = MPT2SAS_SATA_QUEUE_DEPTH; + if (sas_device->device_info & + MPI2_SAS_DEVICE_INFO_STP_TARGET) + ds = "STP"; + else if (sas_device->device_info & + MPI2_SAS_DEVICE_INFO_SATA_DEVICE) + ds = "SATA"; + } + + sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), " + "sas_addr(0x%016llx), device_name(0x%016llx)\n", + ds, sas_device->handle, + (unsigned long long)sas_device->sas_address, + (unsigned long long)sas_device->device_name); + sdev_printk(KERN_INFO, sdev, "%s: " + "enclosure_logical_id(0x%016llx), slot(%d)\n", ds, + (unsigned long long) sas_device->enclosure_logical_id, + sas_device->slot); + + if (!ssp_target) + scsih_display_sata_capabilities(ioc, sas_device, sdev); + } + + scsih_change_queue_depth(sdev, qdepth); + + if (ssp_target) + sas_read_port_mode_page(sdev); + return 0; +} + +/** + * scsih_bios_param - fetch head, sector, cylinder info for a disk + * @sdev: scsi device struct + * @bdev: pointer to block device context + * @capacity: device size (in 512 byte sectors) + * @params: three element array to place output: + * params[0] number of heads (max 255) + * params[1] number of sectors (max 63) + * params[2] number of cylinders + * + * Return nothing. + */ +static int +scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev, + sector_t capacity, int params[]) +{ + int heads; + int sectors; + sector_t cylinders; + ulong dummy; + + heads = 64; + sectors = 32; + + dummy = heads * sectors; + cylinders = capacity; + sector_div(cylinders, dummy); + + /* + * Handle extended translation size for logical drives + * > 1Gb + */ + if ((ulong)capacity >= 0x200000) { + heads = 255; + sectors = 63; + dummy = heads * sectors; + cylinders = capacity; + sector_div(cylinders, dummy); + } + + /* return result */ + params[0] = heads; + params[1] = sectors; + params[2] = cylinders; + + return 0; +} + +/** + * _scsih_response_code - translation of device response code + * @ioc: per adapter object + * @response_code: response code returned by the device + * + * Return nothing. + */ +static void +_scsih_response_code(struct MPT2SAS_ADAPTER *ioc, u8 response_code) +{ + char *desc; + + switch (response_code) { + case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE: + desc = "task management request completed"; + break; + case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME: + desc = "invalid frame"; + break; + case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED: + desc = "task management request not supported"; + break; + case MPI2_SCSITASKMGMT_RSP_TM_FAILED: + desc = "task management request failed"; + break; + case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED: + desc = "task management request succeeded"; + break; + case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN: + desc = "invalid lun"; + break; + case 0xA: + desc = "overlapped tag attempted"; + break; + case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC: + desc = "task queued, however not sent to target"; + break; + default: + desc = "unknown"; + break; + } + printk(MPT2SAS_WARN_FMT "response_code(0x%01x): %s\n", + ioc->name, response_code, desc); +} + +/** + * scsih_tm_done - tm completion routine + * @ioc: per adapter object + * @smid: system request message index + * @VF_ID: virtual function id + * @reply: reply message frame(lower 32bit addr) + * Context: none. + * + * The callback handler when using scsih_issue_tm. + * + * Return nothing. + */ +static void +scsih_tm_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) +{ + MPI2DefaultReply_t *mpi_reply; + + if (ioc->tm_cmds.status == MPT2_CMD_NOT_USED) + return; + if (ioc->tm_cmds.smid != smid) + return; + ioc->tm_cmds.status |= MPT2_CMD_COMPLETE; + mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); + if (mpi_reply) { + memcpy(ioc->tm_cmds.reply, mpi_reply, mpi_reply->MsgLength*4); + ioc->tm_cmds.status |= MPT2_CMD_REPLY_VALID; + } + ioc->tm_cmds.status &= ~MPT2_CMD_PENDING; + complete(&ioc->tm_cmds.done); +} + +/** + * mpt2sas_scsih_set_tm_flag - set per target tm_busy + * @ioc: per adapter object + * @handle: device handle + * + * During taskmangement request, we need to freeze the device queue. + */ +void +mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle) +{ + struct MPT2SAS_DEVICE *sas_device_priv_data; + struct scsi_device *sdev; + u8 skip = 0; + + shost_for_each_device(sdev, ioc->shost) { + if (skip) + continue; + sas_device_priv_data = sdev->hostdata; + if (!sas_device_priv_data) + continue; + if (sas_device_priv_data->sas_target->handle == handle) { + sas_device_priv_data->sas_target->tm_busy = 1; + skip = 1; + ioc->ignore_loginfos = 1; + } + } +} + +/** + * mpt2sas_scsih_clear_tm_flag - clear per target tm_busy + * @ioc: per adapter object + * @handle: device handle + * + * During taskmangement request, we need to freeze the device queue. + */ +void +mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle) +{ + struct MPT2SAS_DEVICE *sas_device_priv_data; + struct scsi_device *sdev; + u8 skip = 0; + + shost_for_each_device(sdev, ioc->shost) { + if (skip) + continue; + sas_device_priv_data = sdev->hostdata; + if (!sas_device_priv_data) + continue; + if (sas_device_priv_data->sas_target->handle == handle) { + sas_device_priv_data->sas_target->tm_busy = 0; + skip = 1; + ioc->ignore_loginfos = 0; + } + } +} + +/** + * mpt2sas_scsih_issue_tm - main routine for sending tm requests + * @ioc: per adapter struct + * @device_handle: device handle + * @lun: lun number + * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h) + * @smid_task: smid assigned to the task + * @timeout: timeout in seconds + * Context: The calling function needs to acquire the tm_cmds.mutex + * + * A generic API for sending task management requests to firmware. + * + * The ioc->tm_cmds.status flag should be MPT2_CMD_NOT_USED before calling + * this API. + * + * The callback index is set inside `ioc->tm_cb_idx`. + * + * Return nothing. + */ +void +mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint lun, + u8 type, u16 smid_task, ulong timeout) +{ + Mpi2SCSITaskManagementRequest_t *mpi_request; + Mpi2SCSITaskManagementReply_t *mpi_reply; + u16 smid = 0; + u32 ioc_state; + unsigned long timeleft; + u8 VF_ID = 0; + unsigned long flags; + + spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); + if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED || + ioc->shost_recovery) { + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n", + __func__, ioc->name); + return; + } + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + + ioc_state = mpt2sas_base_get_iocstate(ioc, 0); + if (ioc_state & MPI2_DOORBELL_USED) { + dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "unexpected doorbell " + "active!\n", ioc->name)); + goto issue_host_reset; + } + + if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) { + mpt2sas_base_fault_info(ioc, ioc_state & + MPI2_DOORBELL_DATA_MASK); + goto issue_host_reset; + } + + smid = mpt2sas_base_get_smid(ioc, ioc->tm_cb_idx); + if (!smid) { + printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", + ioc->name, __func__); + return; + } + + dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "sending tm: handle(0x%04x)," + " task_type(0x%02x), smid(%d)\n", ioc->name, handle, type, smid)); + ioc->tm_cmds.status = MPT2_CMD_PENDING; + mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); + ioc->tm_cmds.smid = smid; + memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t)); + mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; + mpi_request->DevHandle = cpu_to_le16(handle); + mpi_request->TaskType = type; + mpi_request->TaskMID = cpu_to_le16(smid_task); + int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN); + mpt2sas_scsih_set_tm_flag(ioc, handle); + mpt2sas_base_put_smid_hi_priority(ioc, smid, VF_ID); + timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ); + mpt2sas_scsih_clear_tm_flag(ioc, handle); + if (!(ioc->tm_cmds.status & MPT2_CMD_COMPLETE)) { + printk(MPT2SAS_ERR_FMT "%s: timeout\n", + ioc->name, __func__); + _debug_dump_mf(mpi_request, + sizeof(Mpi2SCSITaskManagementRequest_t)/4); + if (!(ioc->tm_cmds.status & MPT2_CMD_RESET)) + goto issue_host_reset; + } + + if (ioc->tm_cmds.status & MPT2_CMD_REPLY_VALID) { + mpi_reply = ioc->tm_cmds.reply; + dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "complete tm: " + "ioc_status(0x%04x), loginfo(0x%08x), term_count(0x%08x)\n", + ioc->name, le16_to_cpu(mpi_reply->IOCStatus), + le32_to_cpu(mpi_reply->IOCLogInfo), + le32_to_cpu(mpi_reply->TerminationCount))); + if (ioc->logging_level & MPT_DEBUG_TM) + _scsih_response_code(ioc, mpi_reply->ResponseCode); + } + return; + issue_host_reset: + mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, FORCE_BIG_HAMMER); +} + +/** + * scsih_abort - eh threads main abort routine + * @sdev: scsi device struct + * + * Returns SUCCESS if command aborted else FAILED + */ +static int +scsih_abort(struct scsi_cmnd *scmd) +{ + struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host); + struct MPT2SAS_DEVICE *sas_device_priv_data; + u16 smid; + u16 handle; + int r; + struct scsi_cmnd *scmd_lookup; + + printk(MPT2SAS_INFO_FMT "attempting task abort! scmd(%p)\n", + ioc->name, scmd); + scsi_print_command(scmd); + + sas_device_priv_data = scmd->device->hostdata; + if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { + printk(MPT2SAS_INFO_FMT "device been deleted! scmd(%p)\n", + ioc->name, scmd); + scmd->result = DID_NO_CONNECT << 16; + scmd->scsi_done(scmd); + r = SUCCESS; + goto out; + } + + /* search for the command */ + smid = _scsih_scsi_lookup_find_by_scmd(ioc, scmd); + if (!smid) { + scmd->result = DID_RESET << 16; + r = SUCCESS; + goto out; + } + + /* for hidden raid components and volumes this is not supported */ + if (sas_device_priv_data->sas_target->flags & + MPT_TARGET_FLAGS_RAID_COMPONENT || + sas_device_priv_data->sas_target->flags & MPT_TARGET_FLAGS_VOLUME) { + scmd->result = DID_RESET << 16; + r = FAILED; + goto out; + } + + mutex_lock(&ioc->tm_cmds.mutex); + handle = sas_device_priv_data->sas_target->handle; + mpt2sas_scsih_issue_tm(ioc, handle, sas_device_priv_data->lun, + MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30); + + /* sanity check - see whether command actually completed */ + scmd_lookup = _scsih_scsi_lookup_get(ioc, smid); + if (scmd_lookup && (scmd_lookup->serial_number == scmd->serial_number)) + r = FAILED; + else + r = SUCCESS; + ioc->tm_cmds.status = MPT2_CMD_NOT_USED; + mutex_unlock(&ioc->tm_cmds.mutex); + + out: + printk(MPT2SAS_INFO_FMT "task abort: %s scmd(%p)\n", + ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); + return r; +} + + +/** + * scsih_dev_reset - eh threads main device reset routine + * @sdev: scsi device struct + * + * Returns SUCCESS if command aborted else FAILED + */ +static int +scsih_dev_reset(struct scsi_cmnd *scmd) +{ + struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host); + struct MPT2SAS_DEVICE *sas_device_priv_data; + struct _sas_device *sas_device; + unsigned long flags; + u16 handle; + int r; + + printk(MPT2SAS_INFO_FMT "attempting target reset! scmd(%p)\n", + ioc->name, scmd); + scsi_print_command(scmd); + + sas_device_priv_data = scmd->device->hostdata; + if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { + printk(MPT2SAS_INFO_FMT "device been deleted! scmd(%p)\n", + ioc->name, scmd); + scmd->result = DID_NO_CONNECT << 16; + scmd->scsi_done(scmd); + r = SUCCESS; + goto out; + } + + /* for hidden raid components obtain the volume_handle */ + handle = 0; + if (sas_device_priv_data->sas_target->flags & + MPT_TARGET_FLAGS_RAID_COMPONENT) { + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = _scsih_sas_device_find_by_handle(ioc, + sas_device_priv_data->sas_target->handle); + if (sas_device) + handle = sas_device->volume_handle; + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + } else + handle = sas_device_priv_data->sas_target->handle; + + if (!handle) { + scmd->result = DID_RESET << 16; + r = FAILED; + goto out; + } + + mutex_lock(&ioc->tm_cmds.mutex); + mpt2sas_scsih_issue_tm(ioc, handle, 0, + MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 30); + + /* + * sanity check see whether all commands to this target been + * completed + */ + if (_scsih_scsi_lookup_find_by_target(ioc, scmd->device->id, + scmd->device->channel)) + r = FAILED; + else + r = SUCCESS; + ioc->tm_cmds.status = MPT2_CMD_NOT_USED; + mutex_unlock(&ioc->tm_cmds.mutex); + + out: + printk(MPT2SAS_INFO_FMT "target reset: %s scmd(%p)\n", + ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); + return r; +} + +/** + * scsih_abort - eh threads main host reset routine + * @sdev: scsi device struct + * + * Returns SUCCESS if command aborted else FAILED + */ +static int +scsih_host_reset(struct scsi_cmnd *scmd) +{ + struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host); + int r, retval; + + printk(MPT2SAS_INFO_FMT "attempting host reset! scmd(%p)\n", + ioc->name, scmd); + scsi_print_command(scmd); + + retval = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, + FORCE_BIG_HAMMER); + r = (retval < 0) ? FAILED : SUCCESS; + printk(MPT2SAS_INFO_FMT "host reset: %s scmd(%p)\n", + ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); + + return r; +} + +/** + * _scsih_fw_event_add - insert and queue up fw_event + * @ioc: per adapter object + * @fw_event: object describing the event + * Context: This function will acquire ioc->fw_event_lock. + * + * This adds the firmware event object into link list, then queues it up to + * be processed from user context. + * + * Return nothing. + */ +static void +_scsih_fw_event_add(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work *fw_event) +{ + unsigned long flags; + + if (ioc->firmware_event_thread == NULL) + return; + + spin_lock_irqsave(&ioc->fw_event_lock, flags); + list_add_tail(&fw_event->list, &ioc->fw_event_list); + INIT_DELAYED_WORK(&fw_event->work, _firmware_event_work); + queue_delayed_work(ioc->firmware_event_thread, &fw_event->work, 1); + spin_unlock_irqrestore(&ioc->fw_event_lock, flags); +} + +/** + * _scsih_fw_event_free - delete fw_event + * @ioc: per adapter object + * @fw_event: object describing the event + * Context: This function will acquire ioc->fw_event_lock. + * + * This removes firmware event object from link list, frees associated memory. + * + * Return nothing. + */ +static void +_scsih_fw_event_free(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work + *fw_event) +{ + unsigned long flags; + + spin_lock_irqsave(&ioc->fw_event_lock, flags); + list_del(&fw_event->list); + kfree(fw_event->event_data); + kfree(fw_event); + spin_unlock_irqrestore(&ioc->fw_event_lock, flags); +} + +/** + * _scsih_fw_event_add - requeue an event + * @ioc: per adapter object + * @fw_event: object describing the event + * Context: This function will acquire ioc->fw_event_lock. + * + * Return nothing. + */ +static void +_scsih_fw_event_requeue(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work + *fw_event, unsigned long delay) +{ + unsigned long flags; + if (ioc->firmware_event_thread == NULL) + return; + + spin_lock_irqsave(&ioc->fw_event_lock, flags); + queue_delayed_work(ioc->firmware_event_thread, &fw_event->work, delay); + spin_unlock_irqrestore(&ioc->fw_event_lock, flags); +} + +/** + * _scsih_fw_event_off - turn flag off preventing event handling + * @ioc: per adapter object + * + * Used to prevent handling of firmware events during adapter reset + * driver unload. + * + * Return nothing. + */ +static void +_scsih_fw_event_off(struct MPT2SAS_ADAPTER *ioc) +{ + unsigned long flags; + + spin_lock_irqsave(&ioc->fw_event_lock, flags); + ioc->fw_events_off = 1; + spin_unlock_irqrestore(&ioc->fw_event_lock, flags); + +} + +/** + * _scsih_fw_event_on - turn flag on allowing firmware event handling + * @ioc: per adapter object + * + * Returns nothing. + */ +static void +_scsih_fw_event_on(struct MPT2SAS_ADAPTER *ioc) +{ + unsigned long flags; + + spin_lock_irqsave(&ioc->fw_event_lock, flags); + ioc->fw_events_off = 0; + spin_unlock_irqrestore(&ioc->fw_event_lock, flags); +} + +/** + * _scsih_ublock_io_device - set the device state to SDEV_RUNNING + * @ioc: per adapter object + * @handle: device handle + * + * During device pull we need to appropiately set the sdev state. + */ +static void +_scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) +{ + struct MPT2SAS_DEVICE *sas_device_priv_data; + struct scsi_device *sdev; + + shost_for_each_device(sdev, ioc->shost) { + sas_device_priv_data = sdev->hostdata; + if (!sas_device_priv_data) + continue; + if (!sas_device_priv_data->block) + continue; + if (sas_device_priv_data->sas_target->handle == handle) { + dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, + MPT2SAS_INFO_FMT "SDEV_RUNNING: " + "handle(0x%04x)\n", ioc->name, handle)); + sas_device_priv_data->block = 0; + scsi_device_set_state(sdev, SDEV_RUNNING); + } + } +} + +/** + * _scsih_block_io_device - set the device state to SDEV_BLOCK + * @ioc: per adapter object + * @handle: device handle + * + * During device pull we need to appropiately set the sdev state. + */ +static void +_scsih_block_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) +{ + struct MPT2SAS_DEVICE *sas_device_priv_data; + struct scsi_device *sdev; + + shost_for_each_device(sdev, ioc->shost) { + sas_device_priv_data = sdev->hostdata; + if (!sas_device_priv_data) + continue; + if (sas_device_priv_data->block) + continue; + if (sas_device_priv_data->sas_target->handle == handle) { + dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, + MPT2SAS_INFO_FMT "SDEV_BLOCK: " + "handle(0x%04x)\n", ioc->name, handle)); + sas_device_priv_data->block = 1; + scsi_device_set_state(sdev, SDEV_BLOCK); + } + } +} + +/** + * _scsih_block_io_to_children_attached_to_ex + * @ioc: per adapter object + * @sas_expander: the sas_device object + * + * This routine set sdev state to SDEV_BLOCK for all devices + * attached to this expander. This function called when expander is + * pulled. + */ +static void +_scsih_block_io_to_children_attached_to_ex(struct MPT2SAS_ADAPTER *ioc, + struct _sas_node *sas_expander) +{ + struct _sas_port *mpt2sas_port; + struct _sas_device *sas_device; + struct _sas_node *expander_sibling; + unsigned long flags; + + if (!sas_expander) + return; + + list_for_each_entry(mpt2sas_port, + &sas_expander->sas_port_list, port_list) { + if (mpt2sas_port->remote_identify.device_type == + SAS_END_DEVICE) { + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = + mpt2sas_scsih_sas_device_find_by_sas_address(ioc, + mpt2sas_port->remote_identify.sas_address); + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + if (!sas_device) + continue; + _scsih_block_io_device(ioc, sas_device->handle); + } + } + + list_for_each_entry(mpt2sas_port, + &sas_expander->sas_port_list, port_list) { + + if (mpt2sas_port->remote_identify.device_type == + MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER || + mpt2sas_port->remote_identify.device_type == + MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) { + + spin_lock_irqsave(&ioc->sas_node_lock, flags); + expander_sibling = + mpt2sas_scsih_expander_find_by_sas_address( + ioc, mpt2sas_port->remote_identify.sas_address); + spin_unlock_irqrestore(&ioc->sas_node_lock, flags); + _scsih_block_io_to_children_attached_to_ex(ioc, + expander_sibling); + } + } +} + +/** + * _scsih_block_io_to_children_attached_directly + * @ioc: per adapter object + * @event_data: topology change event data + * + * This routine set sdev state to SDEV_BLOCK for all devices + * direct attached during device pull. + */ +static void +_scsih_block_io_to_children_attached_directly(struct MPT2SAS_ADAPTER *ioc, + Mpi2EventDataSasTopologyChangeList_t *event_data) +{ + int i; + u16 handle; + u16 reason_code; + u8 phy_number; + + for (i = 0; i < event_data->NumEntries; i++) { + handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); + if (!handle) + continue; + phy_number = event_data->StartPhyNum + i; + reason_code = event_data->PHY[i].PhyStatus & + MPI2_EVENT_SAS_TOPO_RC_MASK; + if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING) + _scsih_block_io_device(ioc, handle); + } +} + +/** + * _scsih_check_topo_delete_events - sanity check on topo events + * @ioc: per adapter object + * @event_data: the event data payload + * + * This routine added to better handle cable breaker. + * + * This handles the case where driver recieves multiple expander + * add and delete events in a single shot. When there is a delete event + * the routine will void any pending add events waiting in the event queue. + * + * Return nothing. + */ +static void +_scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc, + Mpi2EventDataSasTopologyChangeList_t *event_data) +{ + struct fw_event_work *fw_event; + Mpi2EventDataSasTopologyChangeList_t *local_event_data; + u16 expander_handle; + struct _sas_node *sas_expander; + unsigned long flags; + + expander_handle = le16_to_cpu(event_data->ExpanderDevHandle); + if (expander_handle < ioc->sas_hba.num_phys) { + _scsih_block_io_to_children_attached_directly(ioc, event_data); + return; + } + + if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING + || event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING) { + spin_lock_irqsave(&ioc->sas_node_lock, flags); + sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, + expander_handle); + spin_unlock_irqrestore(&ioc->sas_node_lock, flags); + _scsih_block_io_to_children_attached_to_ex(ioc, sas_expander); + } else if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_RESPONDING) + _scsih_block_io_to_children_attached_directly(ioc, event_data); + + if (event_data->ExpStatus != MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING) + return; + + /* mark ignore flag for pending events */ + spin_lock_irqsave(&ioc->fw_event_lock, flags); + list_for_each_entry(fw_event, &ioc->fw_event_list, list) { + if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST || + fw_event->ignore) + continue; + local_event_data = fw_event->event_data; + if (local_event_data->ExpStatus == + MPI2_EVENT_SAS_TOPO_ES_ADDED || + local_event_data->ExpStatus == + MPI2_EVENT_SAS_TOPO_ES_RESPONDING) { + if (le16_to_cpu(local_event_data->ExpanderDevHandle) == + expander_handle) { + dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT + "setting ignoring flag\n", ioc->name)); + fw_event->ignore = 1; + } + } + } + spin_unlock_irqrestore(&ioc->fw_event_lock, flags); +} + +/** + * _scsih_queue_rescan - queue a topology rescan from user context + * @ioc: per adapter object + * + * Return nothing. + */ +static void +_scsih_queue_rescan(struct MPT2SAS_ADAPTER *ioc) +{ + struct fw_event_work *fw_event; + + if (ioc->wait_for_port_enable_to_complete) + return; + fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); + if (!fw_event) + return; + fw_event->event = MPT2SAS_RESCAN_AFTER_HOST_RESET; + fw_event->ioc = ioc; + _scsih_fw_event_add(ioc, fw_event); +} + +/** + * _scsih_flush_running_cmds - completing outstanding commands. + * @ioc: per adapter object + * + * The flushing out of all pending scmd commands following host reset, + * where all IO is dropped to the floor. + * + * Return nothing. + */ +static void +_scsih_flush_running_cmds(struct MPT2SAS_ADAPTER *ioc) +{ + struct scsi_cmnd *scmd; + u16 smid; + u16 count = 0; + + for (smid = 1; smid <= ioc->request_depth; smid++) { + scmd = _scsih_scsi_lookup_getclear(ioc, smid); + if (!scmd) + continue; + count++; + mpt2sas_base_free_smid(ioc, smid); + scsi_dma_unmap(scmd); + scmd->result = DID_RESET << 16; + scmd->scsi_done(scmd); + } + dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "completing %d cmds\n", + ioc->name, count)); +} + +/** + * mpt2sas_scsih_reset_handler - reset callback handler (for scsih) + * @ioc: per adapter object + * @reset_phase: phase + * + * The handler for doing any required cleanup or initialization. + * + * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET, + * MPT2_IOC_DONE_RESET + * + * Return nothing. + */ +void +mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) +{ + switch (reset_phase) { + case MPT2_IOC_PRE_RESET: + dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + "MPT2_IOC_PRE_RESET\n", ioc->name, __func__)); + _scsih_fw_event_off(ioc); + break; + case MPT2_IOC_AFTER_RESET: + dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__)); + if (ioc->tm_cmds.status & MPT2_CMD_PENDING) { + ioc->tm_cmds.status |= MPT2_CMD_RESET; + mpt2sas_base_free_smid(ioc, ioc->tm_cmds.smid); + complete(&ioc->tm_cmds.done); + } + _scsih_fw_event_on(ioc); + _scsih_flush_running_cmds(ioc); + break; + case MPT2_IOC_DONE_RESET: + dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); + _scsih_queue_rescan(ioc); + break; + } +} + +/** + * scsih_qcmd - main scsi request entry point + * @scmd: pointer to scsi command object + * @done: function pointer to be invoked on completion + * + * The callback index is set inside `ioc->scsi_io_cb_idx`. + * + * Returns 0 on success. If there's a failure, return either: + * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or + * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full + */ +static int +scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *)) +{ + struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host); + struct MPT2SAS_DEVICE *sas_device_priv_data; + struct MPT2SAS_TARGET *sas_target_priv_data; + Mpi2SCSIIORequest_t *mpi_request; + u32 mpi_control; + u16 smid; + unsigned long flags; + + scmd->scsi_done = done; + sas_device_priv_data = scmd->device->hostdata; + if (!sas_device_priv_data) { + scmd->result = DID_NO_CONNECT << 16; + scmd->scsi_done(scmd); + return 0; + } + + sas_target_priv_data = sas_device_priv_data->sas_target; + if (!sas_target_priv_data || sas_target_priv_data->handle == + MPT2SAS_INVALID_DEVICE_HANDLE || sas_target_priv_data->deleted) { + scmd->result = DID_NO_CONNECT << 16; + scmd->scsi_done(scmd); + return 0; + } + + /* see if we are busy with task managment stuff */ + spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); + if (sas_target_priv_data->tm_busy || + ioc->shost_recovery || ioc->ioc_link_reset_in_progress) { + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + return SCSI_MLQUEUE_HOST_BUSY; + } + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + + if (scmd->sc_data_direction == DMA_FROM_DEVICE) + mpi_control = MPI2_SCSIIO_CONTROL_READ; + else if (scmd->sc_data_direction == DMA_TO_DEVICE) + mpi_control = MPI2_SCSIIO_CONTROL_WRITE; + else + mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER; + + /* set tags */ + if (!(sas_device_priv_data->flags & MPT_DEVICE_FLAGS_INIT)) { + if (scmd->device->tagged_supported) { + if (scmd->device->ordered_tags) + mpi_control |= MPI2_SCSIIO_CONTROL_ORDEREDQ; + else + mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ; + } else +/* MPI Revision I (UNIT = 0xA) - removed MPI2_SCSIIO_CONTROL_UNTAGGED */ +/* mpi_control |= MPI2_SCSIIO_CONTROL_UNTAGGED; + */ + mpi_control |= (0x500); + + } else + mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ; + + if ((sas_device_priv_data->flags & MPT_DEVICE_TLR_ON)) + mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON; + + smid = mpt2sas_base_get_smid(ioc, ioc->scsi_io_cb_idx); + if (!smid) { + printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", + ioc->name, __func__); + goto out; + } + mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); + memset(mpi_request, 0, sizeof(Mpi2SCSIIORequest_t)); + mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST; + if (sas_device_priv_data->sas_target->flags & + MPT_TARGET_FLAGS_RAID_COMPONENT) + mpi_request->Function = MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; + else + mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST; + mpi_request->DevHandle = + cpu_to_le16(sas_device_priv_data->sas_target->handle); + mpi_request->DataLength = cpu_to_le32(scsi_bufflen(scmd)); + mpi_request->Control = cpu_to_le32(mpi_control); + mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len); + mpi_request->MsgFlags = MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR; + mpi_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE; + mpi_request->SenseBufferLowAddress = + (u32)mpt2sas_base_get_sense_buffer_dma(ioc, smid); + mpi_request->SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4; + mpi_request->SGLFlags = cpu_to_le16(MPI2_SCSIIO_SGLFLAGS_TYPE_MPI + + MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR); + + int_to_scsilun(sas_device_priv_data->lun, (struct scsi_lun *) + mpi_request->LUN); + memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len); + + if (!mpi_request->DataLength) { + mpt2sas_base_build_zero_len_sge(ioc, &mpi_request->SGL); + } else { + if (_scsih_build_scatter_gather(ioc, scmd, smid)) { + mpt2sas_base_free_smid(ioc, smid); + goto out; + } + } + + _scsih_scsi_lookup_set(ioc, smid, scmd); + mpt2sas_base_put_smid_scsi_io(ioc, smid, 0, + sas_device_priv_data->sas_target->handle); + return 0; + + out: + return SCSI_MLQUEUE_HOST_BUSY; +} + +/** + * _scsih_normalize_sense - normalize descriptor and fixed format sense data + * @sense_buffer: sense data returned by target + * @data: normalized skey/asc/ascq + * + * Return nothing. + */ +static void +_scsih_normalize_sense(char *sense_buffer, struct sense_info *data) +{ + if ((sense_buffer[0] & 0x7F) >= 0x72) { + /* descriptor format */ + data->skey = sense_buffer[1] & 0x0F; + data->asc = sense_buffer[2]; + data->ascq = sense_buffer[3]; + } else { + /* fixed format */ + data->skey = sense_buffer[2] & 0x0F; + data->asc = sense_buffer[12]; + data->ascq = sense_buffer[13]; + } +} + +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING +/** + * _scsih_scsi_ioc_info - translated non-succesfull SCSI_IO request + * @ioc: per adapter object + * @scmd: pointer to scsi command object + * @mpi_reply: reply mf payload returned from firmware + * + * scsi_status - SCSI Status code returned from target device + * scsi_state - state info associated with SCSI_IO determined by ioc + * ioc_status - ioc supplied status info + * + * Return nothing. + */ +static void +_scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, + Mpi2SCSIIOReply_t *mpi_reply, u16 smid) +{ + u32 response_info; + u8 *response_bytes; + u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & + MPI2_IOCSTATUS_MASK; + u8 scsi_state = mpi_reply->SCSIState; + u8 scsi_status = mpi_reply->SCSIStatus; + char *desc_ioc_state = NULL; + char *desc_scsi_status = NULL; + char *desc_scsi_state = ioc->tmp_string; + + switch (ioc_status) { + case MPI2_IOCSTATUS_SUCCESS: + desc_ioc_state = "success"; + break; + case MPI2_IOCSTATUS_INVALID_FUNCTION: + desc_ioc_state = "invalid function"; + break; + case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: + desc_ioc_state = "scsi recovered error"; + break; + case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE: + desc_ioc_state = "scsi invalid dev handle"; + break; + case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: + desc_ioc_state = "scsi device not there"; + break; + case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: + desc_ioc_state = "scsi data overrun"; + break; + case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN: + desc_ioc_state = "scsi data underrun"; + break; + case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR: + desc_ioc_state = "scsi io data error"; + break; + case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: + desc_ioc_state = "scsi protocol error"; + break; + case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: + desc_ioc_state = "scsi task terminated"; + break; + case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: + desc_ioc_state = "scsi residual mismatch"; + break; + case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED: + desc_ioc_state = "scsi task mgmt failed"; + break; + case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: + desc_ioc_state = "scsi ioc terminated"; + break; + case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: + desc_ioc_state = "scsi ext terminated"; + break; + default: + desc_ioc_state = "unknown"; + break; + } + + switch (scsi_status) { + case MPI2_SCSI_STATUS_GOOD: + desc_scsi_status = "good"; + break; + case MPI2_SCSI_STATUS_CHECK_CONDITION: + desc_scsi_status = "check condition"; + break; + case MPI2_SCSI_STATUS_CONDITION_MET: + desc_scsi_status = "condition met"; + break; + case MPI2_SCSI_STATUS_BUSY: + desc_scsi_status = "busy"; + break; + case MPI2_SCSI_STATUS_INTERMEDIATE: + desc_scsi_status = "intermediate"; + break; + case MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET: + desc_scsi_status = "intermediate condmet"; + break; + case MPI2_SCSI_STATUS_RESERVATION_CONFLICT: + desc_scsi_status = "reservation conflict"; + break; + case MPI2_SCSI_STATUS_COMMAND_TERMINATED: + desc_scsi_status = "command terminated"; + break; + case MPI2_SCSI_STATUS_TASK_SET_FULL: + desc_scsi_status = "task set full"; + break; + case MPI2_SCSI_STATUS_ACA_ACTIVE: + desc_scsi_status = "aca active"; + break; + case MPI2_SCSI_STATUS_TASK_ABORTED: + desc_scsi_status = "task aborted"; + break; + default: + desc_scsi_status = "unknown"; + break; + } + + desc_scsi_state[0] = '\0'; + if (!scsi_state) + desc_scsi_state = " "; + if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) + strcat(desc_scsi_state, "response info "); + if (scsi_state & MPI2_SCSI_STATE_TERMINATED) + strcat(desc_scsi_state, "state terminated "); + if (scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS) + strcat(desc_scsi_state, "no status "); + if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_FAILED) + strcat(desc_scsi_state, "autosense failed "); + if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) + strcat(desc_scsi_state, "autosense valid "); + + scsi_print_command(scmd); + printk(MPT2SAS_WARN_FMT "\tdev handle(0x%04x), " + "ioc_status(%s)(0x%04x), smid(%d)\n", ioc->name, + le16_to_cpu(mpi_reply->DevHandle), desc_ioc_state, + ioc_status, smid); + printk(MPT2SAS_WARN_FMT "\trequest_len(%d), underflow(%d), " + "resid(%d)\n", ioc->name, scsi_bufflen(scmd), scmd->underflow, + scsi_get_resid(scmd)); + printk(MPT2SAS_WARN_FMT "\ttag(%d), transfer_count(%d), " + "sc->result(0x%08x)\n", ioc->name, le16_to_cpu(mpi_reply->TaskTag), + le32_to_cpu(mpi_reply->TransferCount), scmd->result); + printk(MPT2SAS_WARN_FMT "\tscsi_status(%s)(0x%02x), " + "scsi_state(%s)(0x%02x)\n", ioc->name, desc_scsi_status, + scsi_status, desc_scsi_state, scsi_state); + + if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { + struct sense_info data; + _scsih_normalize_sense(scmd->sense_buffer, &data); + printk(MPT2SAS_WARN_FMT "\t[sense_key,asc,ascq]: " + "[0x%02x,0x%02x,0x%02x]\n", ioc->name, data.skey, + data.asc, data.ascq); + } + + if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) { + response_info = le32_to_cpu(mpi_reply->ResponseInfo); + response_bytes = (u8 *)&response_info; + _scsih_response_code(ioc, response_bytes[3]); + } +} +#endif + +/** + * _scsih_smart_predicted_fault - illuminate Fault LED + * @ioc: per adapter object + * @handle: device handle + * + * Return nothing. + */ +static void +_scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle) +{ + Mpi2SepReply_t mpi_reply; + Mpi2SepRequest_t mpi_request; + struct scsi_target *starget; + struct MPT2SAS_TARGET *sas_target_priv_data; + Mpi2EventNotificationReply_t *event_reply; + Mpi2EventDataSasDeviceStatusChange_t *event_data; + struct _sas_device *sas_device; + ssize_t sz; + unsigned long flags; + + /* only handle non-raid devices */ + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = _scsih_sas_device_find_by_handle(ioc, handle); + if (!sas_device) { + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + return; + } + starget = sas_device->starget; + sas_target_priv_data = starget->hostdata; + + if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) || + ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))) { + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + return; + } + starget_printk(KERN_WARNING, starget, "predicted fault\n"); + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + + if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) { + memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t)); + mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR; + mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS; + mpi_request.SlotStatus = + MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT; + mpi_request.DevHandle = cpu_to_le16(handle); + mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS; + if ((mpt2sas_base_scsi_enclosure_processor(ioc, &mpi_reply, + &mpi_request)) != 0) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return; + } + + if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) { + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT + "enclosure_processor: ioc_status (0x%04x), " + "loginfo(0x%08x)\n", ioc->name, + le16_to_cpu(mpi_reply.IOCStatus), + le32_to_cpu(mpi_reply.IOCLogInfo))); + return; + } + } + + /* insert into event log */ + sz = offsetof(Mpi2EventNotificationReply_t, EventData) + + sizeof(Mpi2EventDataSasDeviceStatusChange_t); + event_reply = kzalloc(sz, GFP_KERNEL); + if (!event_reply) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return; + } + + event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION; + event_reply->Event = + cpu_to_le16(MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE); + event_reply->MsgLength = sz/4; + event_reply->EventDataLength = + cpu_to_le16(sizeof(Mpi2EventDataSasDeviceStatusChange_t)/4); + event_data = (Mpi2EventDataSasDeviceStatusChange_t *) + event_reply->EventData; + event_data->ReasonCode = MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA; + event_data->ASC = 0x5D; + event_data->DevHandle = cpu_to_le16(handle); + event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address); + mpt2sas_ctl_add_to_event_log(ioc, event_reply); + kfree(event_reply); +} + +/** + * scsih_io_done - scsi request callback + * @ioc: per adapter object + * @smid: system request message index + * @VF_ID: virtual function id + * @reply: reply message frame(lower 32bit addr) + * + * Callback handler when using scsih_qcmd. + * + * Return nothing. + */ +static void +scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) +{ + Mpi2SCSIIORequest_t *mpi_request; + Mpi2SCSIIOReply_t *mpi_reply; + struct scsi_cmnd *scmd; + u16 ioc_status; + u32 xfer_cnt; + u8 scsi_state; + u8 scsi_status; + u32 log_info; + struct MPT2SAS_DEVICE *sas_device_priv_data; + u32 response_code; + + mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); + scmd = _scsih_scsi_lookup_getclear(ioc, smid); + if (scmd == NULL) + return; + + mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); + + if (mpi_reply == NULL) { + scmd->result = DID_OK << 16; + goto out; + } + + sas_device_priv_data = scmd->device->hostdata; + if (!sas_device_priv_data || !sas_device_priv_data->sas_target || + sas_device_priv_data->sas_target->deleted) { + scmd->result = DID_NO_CONNECT << 16; + goto out; + } + + /* turning off TLR */ + if (!sas_device_priv_data->tlr_snoop_check) { + sas_device_priv_data->tlr_snoop_check++; + if (sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) { + response_code = (le32_to_cpu(mpi_reply->ResponseInfo) + >> 24); + if (response_code == + MPI2_SCSITASKMGMT_RSP_INVALID_FRAME) + sas_device_priv_data->flags &= + ~MPT_DEVICE_TLR_ON; + } + } + + xfer_cnt = le32_to_cpu(mpi_reply->TransferCount); + scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt); + ioc_status = le16_to_cpu(mpi_reply->IOCStatus); + if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) + log_info = le32_to_cpu(mpi_reply->IOCLogInfo); + else + log_info = 0; + ioc_status &= MPI2_IOCSTATUS_MASK; + scsi_state = mpi_reply->SCSIState; + scsi_status = mpi_reply->SCSIStatus; + + if (ioc_status == MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 && + (scsi_status == MPI2_SCSI_STATUS_BUSY || + scsi_status == MPI2_SCSI_STATUS_RESERVATION_CONFLICT || + scsi_status == MPI2_SCSI_STATUS_TASK_SET_FULL)) { + ioc_status = MPI2_IOCSTATUS_SUCCESS; + } + + if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { + struct sense_info data; + const void *sense_data = mpt2sas_base_get_sense_buffer(ioc, + smid); + memcpy(scmd->sense_buffer, sense_data, + le32_to_cpu(mpi_reply->SenseCount)); + _scsih_normalize_sense(scmd->sense_buffer, &data); + /* failure prediction threshold exceeded */ + if (data.asc == 0x5D) + _scsih_smart_predicted_fault(ioc, + le16_to_cpu(mpi_reply->DevHandle)); + } + + switch (ioc_status) { + case MPI2_IOCSTATUS_BUSY: + case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES: + scmd->result = SAM_STAT_BUSY; + break; + + case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: + scmd->result = DID_NO_CONNECT << 16; + break; + + case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: + if (sas_device_priv_data->block) { + scmd->result = (DID_BUS_BUSY << 16); + break; + } + + case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: + case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: + scmd->result = DID_RESET << 16; + break; + + case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: + if ((xfer_cnt == 0) || (scmd->underflow > xfer_cnt)) + scmd->result = DID_SOFT_ERROR << 16; + else + scmd->result = (DID_OK << 16) | scsi_status; + break; + + case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN: + scmd->result = (DID_OK << 16) | scsi_status; + + if ((scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID)) + break; + + if (xfer_cnt < scmd->underflow) { + if (scsi_status == SAM_STAT_BUSY) + scmd->result = SAM_STAT_BUSY; + else + scmd->result = DID_SOFT_ERROR << 16; + } else if (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED | + MPI2_SCSI_STATE_NO_SCSI_STATUS)) + scmd->result = DID_SOFT_ERROR << 16; + else if (scsi_state & MPI2_SCSI_STATE_TERMINATED) + scmd->result = DID_RESET << 16; + else if (!xfer_cnt && scmd->cmnd[0] == REPORT_LUNS) { + mpi_reply->SCSIState = MPI2_SCSI_STATE_AUTOSENSE_VALID; + mpi_reply->SCSIStatus = SAM_STAT_CHECK_CONDITION; + scmd->result = (DRIVER_SENSE << 24) | + SAM_STAT_CHECK_CONDITION; + scmd->sense_buffer[0] = 0x70; + scmd->sense_buffer[2] = ILLEGAL_REQUEST; + scmd->sense_buffer[12] = 0x20; + scmd->sense_buffer[13] = 0; + } + break; + + case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: + scsi_set_resid(scmd, 0); + case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: + case MPI2_IOCSTATUS_SUCCESS: + scmd->result = (DID_OK << 16) | scsi_status; + if (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED | + MPI2_SCSI_STATE_NO_SCSI_STATUS)) + scmd->result = DID_SOFT_ERROR << 16; + else if (scsi_state & MPI2_SCSI_STATE_TERMINATED) + scmd->result = DID_RESET << 16; + break; + + case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: + case MPI2_IOCSTATUS_INVALID_FUNCTION: + case MPI2_IOCSTATUS_INVALID_SGL: + case MPI2_IOCSTATUS_INTERNAL_ERROR: + case MPI2_IOCSTATUS_INVALID_FIELD: + case MPI2_IOCSTATUS_INVALID_STATE: + case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR: + case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED: + default: + scmd->result = DID_SOFT_ERROR << 16; + break; + + } + +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING + if (scmd->result && (ioc->logging_level & MPT_DEBUG_REPLY)) + _scsih_scsi_ioc_info(ioc , scmd, mpi_reply, smid); +#endif + + out: + scsi_dma_unmap(scmd); + scmd->scsi_done(scmd); +} + +/** + * _scsih_link_change - process phy link changes + * @ioc: per adapter object + * @handle: phy handle + * @attached_handle: valid for devices attached to link + * @phy_number: phy number + * @link_rate: new link rate + * Context: user. + * + * Return nothing. + */ +static void +_scsih_link_change(struct MPT2SAS_ADAPTER *ioc, u16 handle, u16 attached_handle, + u8 phy_number, u8 link_rate) +{ + mpt2sas_transport_update_phy_link_change(ioc, handle, attached_handle, + phy_number, link_rate); +} + +/** + * _scsih_sas_host_refresh - refreshing sas host object contents + * @ioc: per adapter object + * @update: update link information + * Context: user + * + * During port enable, fw will send topology events for every device. Its + * possible that the handles may change from the previous setting, so this + * code keeping handles updating if changed. + * + * Return nothing. + */ +static void +_scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc, u8 update) +{ + u16 sz; + u16 ioc_status; + int i; + Mpi2ConfigReply_t mpi_reply; + Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; + + dtmprintk(ioc, printk(MPT2SAS_INFO_FMT + "updating handles for sas_host(0x%016llx)\n", + ioc->name, (unsigned long long)ioc->sas_hba.sas_address)); + + sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys + * sizeof(Mpi2SasIOUnit0PhyData_t)); + sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL); + if (!sas_iounit_pg0) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return; + } + if (!(mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply, + sas_iounit_pg0, sz))) { + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) + goto out; + for (i = 0; i < ioc->sas_hba.num_phys ; i++) { + ioc->sas_hba.phy[i].handle = + le16_to_cpu(sas_iounit_pg0->PhyData[i]. + ControllerDevHandle); + if (update) + _scsih_link_change(ioc, + ioc->sas_hba.phy[i].handle, + le16_to_cpu(sas_iounit_pg0->PhyData[i]. + AttachedDevHandle), i, + sas_iounit_pg0->PhyData[i]. + NegotiatedLinkRate >> 4); + } + } + + out: + kfree(sas_iounit_pg0); +} + +/** + * _scsih_sas_host_add - create sas host object + * @ioc: per adapter object + * + * Creating host side data object, stored in ioc->sas_hba + * + * Return nothing. + */ +static void +_scsih_sas_host_add(struct MPT2SAS_ADAPTER *ioc) +{ + int i; + Mpi2ConfigReply_t mpi_reply; + Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; + Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL; + Mpi2SasPhyPage0_t phy_pg0; + Mpi2SasDevicePage0_t sas_device_pg0; + Mpi2SasEnclosurePage0_t enclosure_pg0; + u16 ioc_status; + u16 sz; + u16 device_missing_delay; + + mpt2sas_config_get_number_hba_phys(ioc, &ioc->sas_hba.num_phys); + if (!ioc->sas_hba.num_phys) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return; + } + + /* sas_iounit page 0 */ + sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys * + sizeof(Mpi2SasIOUnit0PhyData_t)); + sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL); + if (!sas_iounit_pg0) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return; + } + if ((mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply, + sas_iounit_pg0, sz))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + goto out; + } + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + goto out; + } + + /* sas_iounit page 1 */ + sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys * + sizeof(Mpi2SasIOUnit1PhyData_t)); + sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL); + if (!sas_iounit_pg1) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + goto out; + } + if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply, + sas_iounit_pg1, sz))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + goto out; + } + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + goto out; + } + + ioc->io_missing_delay = + le16_to_cpu(sas_iounit_pg1->IODeviceMissingDelay); + device_missing_delay = + le16_to_cpu(sas_iounit_pg1->ReportDeviceMissingDelay); + if (device_missing_delay & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16) + ioc->device_missing_delay = (device_missing_delay & + MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16; + else + ioc->device_missing_delay = device_missing_delay & + MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK; + + ioc->sas_hba.parent_dev = &ioc->shost->shost_gendev; + ioc->sas_hba.phy = kcalloc(ioc->sas_hba.num_phys, + sizeof(struct _sas_phy), GFP_KERNEL); + if (!ioc->sas_hba.phy) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + goto out; + } + for (i = 0; i < ioc->sas_hba.num_phys ; i++) { + if ((mpt2sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0, + i))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + goto out; + } + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + goto out; + } + ioc->sas_hba.phy[i].handle = + le16_to_cpu(sas_iounit_pg0->PhyData[i].ControllerDevHandle); + ioc->sas_hba.phy[i].phy_id = i; + mpt2sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i], + phy_pg0, ioc->sas_hba.parent_dev); + } + if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, + MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, ioc->sas_hba.phy[0].handle))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + goto out; + } + ioc->sas_hba.handle = le16_to_cpu(sas_device_pg0.DevHandle); + ioc->sas_hba.enclosure_handle = + le16_to_cpu(sas_device_pg0.EnclosureHandle); + ioc->sas_hba.sas_address = le64_to_cpu(sas_device_pg0.SASAddress); + printk(MPT2SAS_INFO_FMT "host_add: handle(0x%04x), " + "sas_addr(0x%016llx), phys(%d)\n", ioc->name, ioc->sas_hba.handle, + (unsigned long long) ioc->sas_hba.sas_address, + ioc->sas_hba.num_phys) ; + + if (ioc->sas_hba.enclosure_handle) { + if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply, + &enclosure_pg0, + MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, + ioc->sas_hba.enclosure_handle))) { + ioc->sas_hba.enclosure_logical_id = + le64_to_cpu(enclosure_pg0.EnclosureLogicalID); + } + } + + out: + kfree(sas_iounit_pg1); + kfree(sas_iounit_pg0); +} + +/** + * _scsih_expander_add - creating expander object + * @ioc: per adapter object + * @handle: expander handle + * + * Creating expander object, stored in ioc->sas_expander_list. + * + * Return 0 for success, else error. + */ +static int +_scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) +{ + struct _sas_node *sas_expander; + Mpi2ConfigReply_t mpi_reply; + Mpi2ExpanderPage0_t expander_pg0; + Mpi2ExpanderPage1_t expander_pg1; + Mpi2SasEnclosurePage0_t enclosure_pg0; + u32 ioc_status; + u16 parent_handle; + __le64 sas_address; + int i; + unsigned long flags; + struct _sas_port *mpt2sas_port; + int rc = 0; + + if (!handle) + return -1; + + if ((mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0, + MPI2_SAS_EXPAND_PGAD_FORM_HNDL, handle))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return -1; + } + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return -1; + } + + /* handle out of order topology events */ + parent_handle = le16_to_cpu(expander_pg0.ParentDevHandle); + if (parent_handle >= ioc->sas_hba.num_phys) { + spin_lock_irqsave(&ioc->sas_node_lock, flags); + sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, + parent_handle); + spin_unlock_irqrestore(&ioc->sas_node_lock, flags); + if (!sas_expander) { + rc = _scsih_expander_add(ioc, parent_handle); + if (rc != 0) + return rc; + } + } + + sas_address = le64_to_cpu(expander_pg0.SASAddress); + + spin_lock_irqsave(&ioc->sas_node_lock, flags); + sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc, + sas_address); + spin_unlock_irqrestore(&ioc->sas_node_lock, flags); + + if (sas_expander) + return 0; + + sas_expander = kzalloc(sizeof(struct _sas_node), + GFP_KERNEL); + if (!sas_expander) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return -1; + } + + sas_expander->handle = handle; + sas_expander->num_phys = expander_pg0.NumPhys; + sas_expander->parent_handle = parent_handle; + sas_expander->enclosure_handle = + le16_to_cpu(expander_pg0.EnclosureHandle); + sas_expander->sas_address = sas_address; + + printk(MPT2SAS_INFO_FMT "expander_add: handle(0x%04x)," + " parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", ioc->name, + handle, sas_expander->parent_handle, (unsigned long long) + sas_expander->sas_address, sas_expander->num_phys); + + if (!sas_expander->num_phys) + goto out_fail; + sas_expander->phy = kcalloc(sas_expander->num_phys, + sizeof(struct _sas_phy), GFP_KERNEL); + if (!sas_expander->phy) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + rc = -1; + goto out_fail; + } + + INIT_LIST_HEAD(&sas_expander->sas_port_list); + mpt2sas_port = mpt2sas_transport_port_add(ioc, handle, + sas_expander->parent_handle); + if (!mpt2sas_port) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + rc = -1; + goto out_fail; + } + sas_expander->parent_dev = &mpt2sas_port->rphy->dev; + + for (i = 0 ; i < sas_expander->num_phys ; i++) { + if ((mpt2sas_config_get_expander_pg1(ioc, &mpi_reply, + &expander_pg1, i, handle))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + continue; + } + sas_expander->phy[i].handle = handle; + sas_expander->phy[i].phy_id = i; + mpt2sas_transport_add_expander_phy(ioc, &sas_expander->phy[i], + expander_pg1, sas_expander->parent_dev); + } + + if (sas_expander->enclosure_handle) { + if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply, + &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, + sas_expander->enclosure_handle))) { + sas_expander->enclosure_logical_id = + le64_to_cpu(enclosure_pg0.EnclosureLogicalID); + } + } + + _scsih_expander_node_add(ioc, sas_expander); + return 0; + + out_fail: + + if (sas_expander) + kfree(sas_expander->phy); + kfree(sas_expander); + return rc; +} + +/** + * _scsih_expander_remove - removing expander object + * @ioc: per adapter object + * @handle: expander handle + * + * Return nothing. + */ +static void +_scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u16 handle) +{ + struct _sas_node *sas_expander; + unsigned long flags; + + spin_lock_irqsave(&ioc->sas_node_lock, flags); + sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, handle); + spin_unlock_irqrestore(&ioc->sas_node_lock, flags); + _scsih_expander_node_remove(ioc, sas_expander); +} + +/** + * _scsih_add_device - creating sas device object + * @ioc: per adapter object + * @handle: sas device handle + * @phy_num: phy number end device attached to + * @is_pd: is this hidden raid component + * + * Creating end device object, stored in ioc->sas_device_list. + * + * Returns 0 for success, non-zero for failure. + */ +static int +_scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) +{ + Mpi2ConfigReply_t mpi_reply; + Mpi2SasDevicePage0_t sas_device_pg0; + Mpi2SasEnclosurePage0_t enclosure_pg0; + struct _sas_device *sas_device; + u32 ioc_status; + __le64 sas_address; + u32 device_info; + unsigned long flags; + + if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, + MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return -1; + } + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return -1; + } + + /* check if device is present */ + if (!(le16_to_cpu(sas_device_pg0.Flags) & + MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + printk(MPT2SAS_ERR_FMT "Flags = 0x%04x\n", + ioc->name, le16_to_cpu(sas_device_pg0.Flags)); + return -1; + } + + /* check if there were any issus with discovery */ + if (sas_device_pg0.AccessStatus == + MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + printk(MPT2SAS_ERR_FMT "AccessStatus = 0x%02x\n", + ioc->name, sas_device_pg0.AccessStatus); + return -1; + } + + /* check if this is end device */ + device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); + if (!(_scsih_is_end_device(device_info))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return -1; + } + + sas_address = le64_to_cpu(sas_device_pg0.SASAddress); + + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, + sas_address); + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + + if (sas_device) { + _scsih_ublock_io_device(ioc, handle); + return 0; + } + + sas_device = kzalloc(sizeof(struct _sas_device), + GFP_KERNEL); + if (!sas_device) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return -1; + } + + sas_device->handle = handle; + sas_device->parent_handle = + le16_to_cpu(sas_device_pg0.ParentDevHandle); + sas_device->enclosure_handle = + le16_to_cpu(sas_device_pg0.EnclosureHandle); + sas_device->slot = + le16_to_cpu(sas_device_pg0.Slot); + sas_device->device_info = device_info; + sas_device->sas_address = sas_address; + sas_device->hidden_raid_component = is_pd; + + /* get enclosure_logical_id */ + if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply, &enclosure_pg0, + MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, + sas_device->enclosure_handle))) { + sas_device->enclosure_logical_id = + le64_to_cpu(enclosure_pg0.EnclosureLogicalID); + } + + /* get device name */ + sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName); + + if (ioc->wait_for_port_enable_to_complete) + _scsih_sas_device_init_add(ioc, sas_device); + else + _scsih_sas_device_add(ioc, sas_device); + + return 0; +} + +/** + * _scsih_remove_device - removing sas device object + * @ioc: per adapter object + * @handle: sas device handle + * + * Return nothing. + */ +static void +_scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) +{ + struct MPT2SAS_TARGET *sas_target_priv_data; + struct _sas_device *sas_device; + unsigned long flags; + Mpi2SasIoUnitControlReply_t mpi_reply; + Mpi2SasIoUnitControlRequest_t mpi_request; + u16 device_handle; + + /* lookup sas_device */ + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = _scsih_sas_device_find_by_handle(ioc, handle); + if (!sas_device) { + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + return; + } + + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: handle" + "(0x%04x)\n", ioc->name, __func__, handle)); + + if (sas_device->starget && sas_device->starget->hostdata) { + sas_target_priv_data = sas_device->starget->hostdata; + sas_target_priv_data->deleted = 1; + } + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + + if (ioc->remove_host) + goto out; + + /* Target Reset to flush out all the outstanding IO */ + device_handle = (sas_device->hidden_raid_component) ? + sas_device->volume_handle : handle; + if (device_handle) { + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "issue target reset: " + "handle(0x%04x)\n", ioc->name, device_handle)); + mutex_lock(&ioc->tm_cmds.mutex); + mpt2sas_scsih_issue_tm(ioc, device_handle, 0, + MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 10); + ioc->tm_cmds.status = MPT2_CMD_NOT_USED; + mutex_unlock(&ioc->tm_cmds.mutex); + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "issue target reset " + "done: handle(0x%04x)\n", ioc->name, device_handle)); + } + + /* SAS_IO_UNIT_CNTR - send REMOVE_DEVICE */ + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "sas_iounit: handle" + "(0x%04x)\n", ioc->name, handle)); + memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t)); + mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; + mpi_request.Operation = MPI2_SAS_OP_REMOVE_DEVICE; + mpi_request.DevHandle = handle; + mpi_request.VF_ID = 0; + if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, + &mpi_request)) != 0) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + } + + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "sas_iounit: ioc_status" + "(0x%04x), loginfo(0x%08x)\n", ioc->name, + le16_to_cpu(mpi_reply.IOCStatus), + le32_to_cpu(mpi_reply.IOCLogInfo))); + + out: + mpt2sas_transport_port_remove(ioc, sas_device->sas_address, + sas_device->parent_handle); + + printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), sas_addr" + "(0x%016llx)\n", ioc->name, sas_device->handle, + (unsigned long long) sas_device->sas_address); + _scsih_sas_device_remove(ioc, sas_device); + + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit: handle" + "(0x%04x)\n", ioc->name, __func__, handle)); +} + +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING +/** + * _scsih_sas_topology_change_event_debug - debug for topology event + * @ioc: per adapter object + * @event_data: event data payload + * Context: user. + */ +static void +_scsih_sas_topology_change_event_debug(struct MPT2SAS_ADAPTER *ioc, + Mpi2EventDataSasTopologyChangeList_t *event_data) +{ + int i; + u16 handle; + u16 reason_code; + u8 phy_number; + char *status_str = NULL; + char link_rate[25]; + + switch (event_data->ExpStatus) { + case MPI2_EVENT_SAS_TOPO_ES_ADDED: + status_str = "add"; + break; + case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING: + status_str = "remove"; + break; + case MPI2_EVENT_SAS_TOPO_ES_RESPONDING: + status_str = "responding"; + break; + case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING: + status_str = "remove delay"; + break; + default: + status_str = "unknown status"; + break; + } + printk(MPT2SAS_DEBUG_FMT "sas topology change: (%s)\n", + ioc->name, status_str); + printk(KERN_DEBUG "\thandle(0x%04x), enclosure_handle(0x%04x) " + "start_phy(%02d), count(%d)\n", + le16_to_cpu(event_data->ExpanderDevHandle), + le16_to_cpu(event_data->EnclosureHandle), + event_data->StartPhyNum, event_data->NumEntries); + for (i = 0; i < event_data->NumEntries; i++) { + handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); + if (!handle) + continue; + phy_number = event_data->StartPhyNum + i; + reason_code = event_data->PHY[i].PhyStatus & + MPI2_EVENT_SAS_TOPO_RC_MASK; + switch (reason_code) { + case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: + snprintf(link_rate, 25, ": add, link(0x%02x)", + (event_data->PHY[i].LinkRate >> 4)); + status_str = link_rate; + break; + case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING: + status_str = ": remove"; + break; + case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING: + status_str = ": remove_delay"; + break; + case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: + snprintf(link_rate, 25, ": link(0x%02x)", + (event_data->PHY[i].LinkRate >> 4)); + status_str = link_rate; + break; + case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE: + status_str = ": responding"; + break; + default: + status_str = ": unknown"; + break; + } + printk(KERN_DEBUG "\tphy(%02d), attached_handle(0x%04x)%s\n", + phy_number, handle, status_str); + } +} +#endif + +/** + * _scsih_sas_topology_change_event - handle topology changes + * @ioc: per adapter object + * @VF_ID: + * @event_data: event data payload + * fw_event: + * Context: user. + * + */ +static void +_scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, + Mpi2EventDataSasTopologyChangeList_t *event_data, + struct fw_event_work *fw_event) +{ + int i; + u16 parent_handle, handle; + u16 reason_code; + u8 phy_number; + struct _sas_node *sas_expander; + unsigned long flags; + u8 link_rate_; + +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING + if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) + _scsih_sas_topology_change_event_debug(ioc, event_data); +#endif + + if (!ioc->sas_hba.num_phys) + _scsih_sas_host_add(ioc); + else + _scsih_sas_host_refresh(ioc, 0); + + if (fw_event->ignore) { + dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "ignoring expander " + "event\n", ioc->name)); + return; + } + + parent_handle = le16_to_cpu(event_data->ExpanderDevHandle); + + /* handle expander add */ + if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED) + if (_scsih_expander_add(ioc, parent_handle) != 0) + return; + + /* handle siblings events */ + for (i = 0; i < event_data->NumEntries; i++) { + if (fw_event->ignore) { + dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "ignoring " + "expander event\n", ioc->name)); + return; + } + if (event_data->PHY[i].PhyStatus & + MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) + continue; + handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); + if (!handle) + continue; + phy_number = event_data->StartPhyNum + i; + reason_code = event_data->PHY[i].PhyStatus & + MPI2_EVENT_SAS_TOPO_RC_MASK; + link_rate_ = event_data->PHY[i].LinkRate >> 4; + switch (reason_code) { + case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: + case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: + if (!parent_handle) { + if (phy_number < ioc->sas_hba.num_phys) + _scsih_link_change(ioc, + ioc->sas_hba.phy[phy_number].handle, + handle, phy_number, link_rate_); + } else { + spin_lock_irqsave(&ioc->sas_node_lock, flags); + sas_expander = + mpt2sas_scsih_expander_find_by_handle(ioc, + parent_handle); + spin_unlock_irqrestore(&ioc->sas_node_lock, + flags); + if (sas_expander) { + if (phy_number < sas_expander->num_phys) + _scsih_link_change(ioc, + sas_expander-> + phy[phy_number].handle, + handle, phy_number, + link_rate_); + } + } + if (reason_code == MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED) { + if (link_rate_ >= MPI2_SAS_NEG_LINK_RATE_1_5) + _scsih_ublock_io_device(ioc, handle); + } + if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED) { + if (link_rate_ < MPI2_SAS_NEG_LINK_RATE_1_5) + break; + _scsih_add_device(ioc, handle, phy_number, 0); + } + break; + case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING: + _scsih_remove_device(ioc, handle); + break; + } + } + + /* handle expander removal */ + if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING) + _scsih_expander_remove(ioc, parent_handle); + +} + +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING +/** + * _scsih_sas_device_status_change_event_debug - debug for device event + * @event_data: event data payload + * Context: user. + * + * Return nothing. + */ +static void +_scsih_sas_device_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc, + Mpi2EventDataSasDeviceStatusChange_t *event_data) +{ + char *reason_str = NULL; + + switch (event_data->ReasonCode) { + case MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA: + reason_str = "smart data"; + break; + case MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED: + reason_str = "unsupported device discovered"; + break; + case MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: + reason_str = "internal device reset"; + break; + case MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL: + reason_str = "internal task abort"; + break; + case MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL: + reason_str = "internal task abort set"; + break; + case MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL: + reason_str = "internal clear task set"; + break; + case MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL: + reason_str = "internal query task"; + break; + case MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE: + reason_str = "sata init failure"; + break; + case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET: + reason_str = "internal device reset complete"; + break; + case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL: + reason_str = "internal task abort complete"; + break; + case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION: + reason_str = "internal async notification"; + break; + default: + reason_str = "unknown reason"; + break; + } + printk(MPT2SAS_DEBUG_FMT "device status change: (%s)\n" + "\thandle(0x%04x), sas address(0x%016llx)", ioc->name, + reason_str, le16_to_cpu(event_data->DevHandle), + (unsigned long long)le64_to_cpu(event_data->SASAddress)); + if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA) + printk(MPT2SAS_DEBUG_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name, + event_data->ASC, event_data->ASCQ); + printk(KERN_INFO "\n"); +} +#endif + +/** + * _scsih_sas_device_status_change_event - handle device status change + * @ioc: per adapter object + * @VF_ID: + * @event_data: event data payload + * Context: user. + * + * Return nothing. + */ +static void +_scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, + Mpi2EventDataSasDeviceStatusChange_t *event_data) +{ +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING + if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) + _scsih_sas_device_status_change_event_debug(ioc, event_data); +#endif +} + +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING +/** + * _scsih_sas_enclosure_dev_status_change_event_debug - debug for enclosure event + * @ioc: per adapter object + * @event_data: event data payload + * Context: user. + * + * Return nothing. + */ +static void +_scsih_sas_enclosure_dev_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc, + Mpi2EventDataSasEnclDevStatusChange_t *event_data) +{ + char *reason_str = NULL; + + switch (event_data->ReasonCode) { + case MPI2_EVENT_SAS_ENCL_RC_ADDED: + reason_str = "enclosure add"; + break; + case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING: + reason_str = "enclosure remove"; + break; + default: + reason_str = "unknown reason"; + break; + } + + printk(MPT2SAS_DEBUG_FMT "enclosure status change: (%s)\n" + "\thandle(0x%04x), enclosure logical id(0x%016llx)" + " number slots(%d)\n", ioc->name, reason_str, + le16_to_cpu(event_data->EnclosureHandle), + (unsigned long long)le64_to_cpu(event_data->EnclosureLogicalID), + le16_to_cpu(event_data->StartSlot)); +} +#endif + +/** + * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events + * @ioc: per adapter object + * @VF_ID: + * @event_data: event data payload + * Context: user. + * + * Return nothing. + */ +static void +_scsih_sas_enclosure_dev_status_change_event(struct MPT2SAS_ADAPTER *ioc, + u8 VF_ID, Mpi2EventDataSasEnclDevStatusChange_t *event_data) +{ +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING + if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) + _scsih_sas_enclosure_dev_status_change_event_debug(ioc, + event_data); +#endif +} + +/** + * _scsih_sas_broadcast_primative_event - handle broadcast events + * @ioc: per adapter object + * @event_data: event data payload + * Context: user. + * + * Return nothing. + */ +static void +_scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, + Mpi2EventDataSasBroadcastPrimitive_t *event_data) +{ + struct scsi_cmnd *scmd; + u16 smid, handle; + u32 lun; + struct MPT2SAS_DEVICE *sas_device_priv_data; + u32 termination_count; + u32 query_count; + Mpi2SCSITaskManagementReply_t *mpi_reply; + + dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "broadcast primative: " + "phy number(%d), width(%d)\n", ioc->name, event_data->PhyNum, + event_data->PortWidth)); + + dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, + __func__)); + + mutex_lock(&ioc->tm_cmds.mutex); + termination_count = 0; + query_count = 0; + mpi_reply = ioc->tm_cmds.reply; + for (smid = 1; smid <= ioc->request_depth; smid++) { + scmd = _scsih_scsi_lookup_get(ioc, smid); + if (!scmd) + continue; + sas_device_priv_data = scmd->device->hostdata; + if (!sas_device_priv_data || !sas_device_priv_data->sas_target) + continue; + /* skip hidden raid components */ + if (sas_device_priv_data->sas_target->flags & + MPT_TARGET_FLAGS_RAID_COMPONENT) + continue; + /* skip volumes */ + if (sas_device_priv_data->sas_target->flags & + MPT_TARGET_FLAGS_VOLUME) + continue; + + handle = sas_device_priv_data->sas_target->handle; + lun = sas_device_priv_data->lun; + query_count++; + + mpt2sas_scsih_issue_tm(ioc, handle, lun, + MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30); + termination_count += le32_to_cpu(mpi_reply->TerminationCount); + + if ((mpi_reply->IOCStatus == MPI2_IOCSTATUS_SUCCESS) && + (mpi_reply->ResponseCode == + MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED || + mpi_reply->ResponseCode == + MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC)) + continue; + + mpt2sas_scsih_issue_tm(ioc, handle, lun, + MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET, smid, 30); + termination_count += le32_to_cpu(mpi_reply->TerminationCount); + } + ioc->tm_cmds.status = MPT2_CMD_NOT_USED; + ioc->broadcast_aen_busy = 0; + mutex_unlock(&ioc->tm_cmds.mutex); + + dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT + "%s - exit, query_count = %d termination_count = %d\n", + ioc->name, __func__, query_count, termination_count)); +} + +/** + * _scsih_sas_discovery_event - handle discovery events + * @ioc: per adapter object + * @event_data: event data payload + * Context: user. + * + * Return nothing. + */ +static void +_scsih_sas_discovery_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, + Mpi2EventDataSasDiscovery_t *event_data) +{ +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING + if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) { + printk(MPT2SAS_DEBUG_FMT "discovery event: (%s)", ioc->name, + (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ? + "start" : "stop"); + if (event_data->DiscoveryStatus) + printk(MPT2SAS_DEBUG_FMT ", discovery_status(0x%08x)", + ioc->name, le32_to_cpu(event_data->DiscoveryStatus)); + printk("\n"); + } +#endif + + if (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED && + !ioc->sas_hba.num_phys) + _scsih_sas_host_add(ioc); +} + +/** + * _scsih_reprobe_lun - reprobing lun + * @sdev: scsi device struct + * @no_uld_attach: sdev->no_uld_attach flag setting + * + **/ +static void +_scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach) +{ + int rc; + + sdev->no_uld_attach = no_uld_attach ? 1 : 0; + sdev_printk(KERN_INFO, sdev, "%s raid component\n", + sdev->no_uld_attach ? "hidding" : "exposing"); + rc = scsi_device_reprobe(sdev); +} + +/** + * _scsih_reprobe_target - reprobing target + * @starget: scsi target struct + * @no_uld_attach: sdev->no_uld_attach flag setting + * + * Note: no_uld_attach flag determines whether the disk device is attached + * to block layer. A value of `1` means to not attach. + **/ +static void +_scsih_reprobe_target(struct scsi_target *starget, int no_uld_attach) +{ + struct MPT2SAS_TARGET *sas_target_priv_data = starget->hostdata; + + if (no_uld_attach) + sas_target_priv_data->flags |= MPT_TARGET_FLAGS_RAID_COMPONENT; + else + sas_target_priv_data->flags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT; + + starget_for_each_device(starget, no_uld_attach ? (void *)1 : NULL, + _scsih_reprobe_lun); +} +/** + * _scsih_sas_volume_add - add new volume + * @ioc: per adapter object + * @element: IR config element data + * Context: user. + * + * Return nothing. + */ +static void +_scsih_sas_volume_add(struct MPT2SAS_ADAPTER *ioc, + Mpi2EventIrConfigElement_t *element) +{ + struct _raid_device *raid_device; + unsigned long flags; + u64 wwid; + u16 handle = le16_to_cpu(element->VolDevHandle); + int rc; + +#if 0 /* RAID_HACKS */ + if (le32_to_cpu(event_data->Flags) & + MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) + return; +#endif + + mpt2sas_config_get_volume_wwid(ioc, handle, &wwid); + if (!wwid) { + printk(MPT2SAS_ERR_FMT + "failure at %s:%d/%s()!\n", ioc->name, + __FILE__, __LINE__, __func__); + return; + } + + spin_lock_irqsave(&ioc->raid_device_lock, flags); + raid_device = _scsih_raid_device_find_by_wwid(ioc, wwid); + spin_unlock_irqrestore(&ioc->raid_device_lock, flags); + + if (raid_device) + return; + + raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL); + if (!raid_device) { + printk(MPT2SAS_ERR_FMT + "failure at %s:%d/%s()!\n", ioc->name, + __FILE__, __LINE__, __func__); + return; + } + + raid_device->id = ioc->sas_id++; + raid_device->channel = RAID_CHANNEL; + raid_device->handle = handle; + raid_device->wwid = wwid; + _scsih_raid_device_add(ioc, raid_device); + if (!ioc->wait_for_port_enable_to_complete) { + rc = scsi_add_device(ioc->shost, RAID_CHANNEL, + raid_device->id, 0); + if (rc) + _scsih_raid_device_remove(ioc, raid_device); + } else + _scsih_determine_boot_device(ioc, raid_device, 1); +} + +/** + * _scsih_sas_volume_delete - delete volume + * @ioc: per adapter object + * @element: IR config element data + * Context: user. + * + * Return nothing. + */ +static void +_scsih_sas_volume_delete(struct MPT2SAS_ADAPTER *ioc, + Mpi2EventIrConfigElement_t *element) +{ + struct _raid_device *raid_device; + u16 handle = le16_to_cpu(element->VolDevHandle); + unsigned long flags; + struct MPT2SAS_TARGET *sas_target_priv_data; + +#if 0 /* RAID_HACKS */ + if (le32_to_cpu(event_data->Flags) & + MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) + return; +#endif + + spin_lock_irqsave(&ioc->raid_device_lock, flags); + raid_device = _scsih_raid_device_find_by_handle(ioc, handle); + spin_unlock_irqrestore(&ioc->raid_device_lock, flags); + if (!raid_device) + return; + if (raid_device->starget) { + sas_target_priv_data = raid_device->starget->hostdata; + sas_target_priv_data->deleted = 1; + scsi_remove_target(&raid_device->starget->dev); + } + _scsih_raid_device_remove(ioc, raid_device); +} + +/** + * _scsih_sas_pd_expose - expose pd component to /dev/sdX + * @ioc: per adapter object + * @element: IR config element data + * Context: user. + * + * Return nothing. + */ +static void +_scsih_sas_pd_expose(struct MPT2SAS_ADAPTER *ioc, + Mpi2EventIrConfigElement_t *element) +{ + struct _sas_device *sas_device; + unsigned long flags; + u16 handle = le16_to_cpu(element->PhysDiskDevHandle); + + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = _scsih_sas_device_find_by_handle(ioc, handle); + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + if (!sas_device) + return; + + /* exposing raid component */ + sas_device->volume_handle = 0; + sas_device->volume_wwid = 0; + sas_device->hidden_raid_component = 0; + _scsih_reprobe_target(sas_device->starget, 0); +} + +/** + * _scsih_sas_pd_hide - hide pd component from /dev/sdX + * @ioc: per adapter object + * @element: IR config element data + * Context: user. + * + * Return nothing. + */ +static void +_scsih_sas_pd_hide(struct MPT2SAS_ADAPTER *ioc, + Mpi2EventIrConfigElement_t *element) +{ + struct _sas_device *sas_device; + unsigned long flags; + u16 handle = le16_to_cpu(element->PhysDiskDevHandle); + + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = _scsih_sas_device_find_by_handle(ioc, handle); + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + if (!sas_device) + return; + + /* hiding raid component */ + mpt2sas_config_get_volume_handle(ioc, handle, + &sas_device->volume_handle); + mpt2sas_config_get_volume_wwid(ioc, sas_device->volume_handle, + &sas_device->volume_wwid); + sas_device->hidden_raid_component = 1; + _scsih_reprobe_target(sas_device->starget, 1); +} + +/** + * _scsih_sas_pd_delete - delete pd component + * @ioc: per adapter object + * @element: IR config element data + * Context: user. + * + * Return nothing. + */ +static void +_scsih_sas_pd_delete(struct MPT2SAS_ADAPTER *ioc, + Mpi2EventIrConfigElement_t *element) +{ + struct _sas_device *sas_device; + unsigned long flags; + u16 handle = le16_to_cpu(element->PhysDiskDevHandle); + + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = _scsih_sas_device_find_by_handle(ioc, handle); + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + if (!sas_device) + return; + _scsih_remove_device(ioc, handle); +} + +/** + * _scsih_sas_pd_add - remove pd component + * @ioc: per adapter object + * @element: IR config element data + * Context: user. + * + * Return nothing. + */ +static void +_scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc, + Mpi2EventIrConfigElement_t *element) +{ + struct _sas_device *sas_device; + unsigned long flags; + u16 handle = le16_to_cpu(element->PhysDiskDevHandle); + + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = _scsih_sas_device_find_by_handle(ioc, handle); + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + if (sas_device) + sas_device->hidden_raid_component = 1; + else + _scsih_add_device(ioc, handle, 0, 1); +} + +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING +/** + * _scsih_sas_ir_config_change_event_debug - debug for IR Config Change events + * @ioc: per adapter object + * @event_data: event data payload + * Context: user. + * + * Return nothing. + */ +static void +_scsih_sas_ir_config_change_event_debug(struct MPT2SAS_ADAPTER *ioc, + Mpi2EventDataIrConfigChangeList_t *event_data) +{ + Mpi2EventIrConfigElement_t *element; + u8 element_type; + int i; + char *reason_str = NULL, *element_str = NULL; + + element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; + + printk(MPT2SAS_DEBUG_FMT "raid config change: (%s), elements(%d)\n", + ioc->name, (le32_to_cpu(event_data->Flags) & + MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? + "foreign" : "native", event_data->NumElements); + for (i = 0; i < event_data->NumElements; i++, element++) { + switch (element->ReasonCode) { + case MPI2_EVENT_IR_CHANGE_RC_ADDED: + reason_str = "add"; + break; + case MPI2_EVENT_IR_CHANGE_RC_REMOVED: + reason_str = "remove"; + break; + case MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE: + reason_str = "no change"; + break; + case MPI2_EVENT_IR_CHANGE_RC_HIDE: + reason_str = "hide"; + break; + case MPI2_EVENT_IR_CHANGE_RC_UNHIDE: + reason_str = "unhide"; + break; + case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED: + reason_str = "volume_created"; + break; + case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED: + reason_str = "volume_deleted"; + break; + case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED: + reason_str = "pd_created"; + break; + case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED: + reason_str = "pd_deleted"; + break; + default: + reason_str = "unknown reason"; + break; + } + element_type = le16_to_cpu(element->ElementFlags) & + MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK; + switch (element_type) { + case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT: + element_str = "volume"; + break; + case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT: + element_str = "phys disk"; + break; + case MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT: + element_str = "hot spare"; + break; + default: + element_str = "unknown element"; + break; + } + printk(KERN_DEBUG "\t(%s:%s), vol handle(0x%04x), " + "pd handle(0x%04x), pd num(0x%02x)\n", element_str, + reason_str, le16_to_cpu(element->VolDevHandle), + le16_to_cpu(element->PhysDiskDevHandle), + element->PhysDiskNum); + } +} +#endif + +/** + * _scsih_sas_ir_config_change_event - handle ir configuration change events + * @ioc: per adapter object + * @VF_ID: + * @event_data: event data payload + * Context: user. + * + * Return nothing. + */ +static void +_scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, + Mpi2EventDataIrConfigChangeList_t *event_data) +{ + Mpi2EventIrConfigElement_t *element; + int i; + +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING + if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) + _scsih_sas_ir_config_change_event_debug(ioc, event_data); + +#endif + + element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; + for (i = 0; i < event_data->NumElements; i++, element++) { + + switch (element->ReasonCode) { + case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED: + case MPI2_EVENT_IR_CHANGE_RC_ADDED: + _scsih_sas_volume_add(ioc, element); + break; + case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED: + case MPI2_EVENT_IR_CHANGE_RC_REMOVED: + _scsih_sas_volume_delete(ioc, element); + break; + case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED: + _scsih_sas_pd_hide(ioc, element); + break; + case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED: + _scsih_sas_pd_expose(ioc, element); + break; + case MPI2_EVENT_IR_CHANGE_RC_HIDE: + _scsih_sas_pd_add(ioc, element); + break; + case MPI2_EVENT_IR_CHANGE_RC_UNHIDE: + _scsih_sas_pd_delete(ioc, element); + break; + } + } +} + +/** + * _scsih_sas_ir_volume_event - IR volume event + * @ioc: per adapter object + * @event_data: event data payload + * Context: user. + * + * Return nothing. + */ +static void +_scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, + Mpi2EventDataIrVolume_t *event_data) +{ + u64 wwid; + unsigned long flags; + struct _raid_device *raid_device; + u16 handle; + u32 state; + int rc; + struct MPT2SAS_TARGET *sas_target_priv_data; + + if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED) + return; + + handle = le16_to_cpu(event_data->VolDevHandle); + state = le32_to_cpu(event_data->NewValue); + dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle(0x%04x), " + "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle, + le32_to_cpu(event_data->PreviousValue), state)); + + spin_lock_irqsave(&ioc->raid_device_lock, flags); + raid_device = _scsih_raid_device_find_by_handle(ioc, handle); + spin_unlock_irqrestore(&ioc->raid_device_lock, flags); + + switch (state) { + case MPI2_RAID_VOL_STATE_MISSING: + case MPI2_RAID_VOL_STATE_FAILED: + if (!raid_device) + break; + if (raid_device->starget) { + sas_target_priv_data = raid_device->starget->hostdata; + sas_target_priv_data->deleted = 1; + scsi_remove_target(&raid_device->starget->dev); + } + _scsih_raid_device_remove(ioc, raid_device); + break; + + case MPI2_RAID_VOL_STATE_ONLINE: + case MPI2_RAID_VOL_STATE_DEGRADED: + case MPI2_RAID_VOL_STATE_OPTIMAL: + if (raid_device) + break; + + mpt2sas_config_get_volume_wwid(ioc, handle, &wwid); + if (!wwid) { + printk(MPT2SAS_ERR_FMT + "failure at %s:%d/%s()!\n", ioc->name, + __FILE__, __LINE__, __func__); + break; + } + + raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL); + if (!raid_device) { + printk(MPT2SAS_ERR_FMT + "failure at %s:%d/%s()!\n", ioc->name, + __FILE__, __LINE__, __func__); + break; + } + + raid_device->id = ioc->sas_id++; + raid_device->channel = RAID_CHANNEL; + raid_device->handle = handle; + raid_device->wwid = wwid; + _scsih_raid_device_add(ioc, raid_device); + rc = scsi_add_device(ioc->shost, RAID_CHANNEL, + raid_device->id, 0); + if (rc) + _scsih_raid_device_remove(ioc, raid_device); + break; + + case MPI2_RAID_VOL_STATE_INITIALIZING: + default: + break; + } +} + +/** + * _scsih_sas_ir_physical_disk_event - PD event + * @ioc: per adapter object + * @event_data: event data payload + * Context: user. + * + * Return nothing. + */ +static void +_scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, + Mpi2EventDataIrPhysicalDisk_t *event_data) +{ + u16 handle; + u32 state; + struct _sas_device *sas_device; + unsigned long flags; + + if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED) + return; + + handle = le16_to_cpu(event_data->PhysDiskDevHandle); + state = le32_to_cpu(event_data->NewValue); + + dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle(0x%04x), " + "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle, + le32_to_cpu(event_data->PreviousValue), state)); + + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = _scsih_sas_device_find_by_handle(ioc, handle); + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + + switch (state) { +#if 0 + case MPI2_RAID_PD_STATE_OFFLINE: + if (sas_device) + _scsih_remove_device(ioc, handle); + break; +#endif + case MPI2_RAID_PD_STATE_ONLINE: + case MPI2_RAID_PD_STATE_DEGRADED: + case MPI2_RAID_PD_STATE_REBUILDING: + case MPI2_RAID_PD_STATE_OPTIMAL: + if (sas_device) + sas_device->hidden_raid_component = 1; + else + _scsih_add_device(ioc, handle, 0, 1); + break; + + case MPI2_RAID_PD_STATE_NOT_CONFIGURED: + case MPI2_RAID_PD_STATE_NOT_COMPATIBLE: + case MPI2_RAID_PD_STATE_HOT_SPARE: + default: + break; + } +} + +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING +/** + * _scsih_sas_ir_operation_status_event_debug - debug for IR op event + * @ioc: per adapter object + * @event_data: event data payload + * Context: user. + * + * Return nothing. + */ +static void +_scsih_sas_ir_operation_status_event_debug(struct MPT2SAS_ADAPTER *ioc, + Mpi2EventDataIrOperationStatus_t *event_data) +{ + char *reason_str = NULL; + + switch (event_data->RAIDOperation) { + case MPI2_EVENT_IR_RAIDOP_RESYNC: + reason_str = "resync"; + break; + case MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION: + reason_str = "online capacity expansion"; + break; + case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK: + reason_str = "consistency check"; + break; + default: + reason_str = "unknown reason"; + break; + } + + printk(MPT2SAS_INFO_FMT "raid operational status: (%s)" + "\thandle(0x%04x), percent complete(%d)\n", + ioc->name, reason_str, + le16_to_cpu(event_data->VolDevHandle), + event_data->PercentComplete); +} +#endif + +/** + * _scsih_sas_ir_operation_status_event - handle RAID operation events + * @ioc: per adapter object + * @VF_ID: + * @event_data: event data payload + * Context: user. + * + * Return nothing. + */ +static void +_scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, + Mpi2EventDataIrOperationStatus_t *event_data) +{ +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING + if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) + _scsih_sas_ir_operation_status_event_debug(ioc, event_data); +#endif +} + +/** + * _scsih_task_set_full - handle task set full + * @ioc: per adapter object + * @event_data: event data payload + * Context: user. + * + * Throttle back qdepth. + */ +static void +_scsih_task_set_full(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, + Mpi2EventDataTaskSetFull_t *event_data) +{ + unsigned long flags; + struct _sas_device *sas_device; + static struct _raid_device *raid_device; + struct scsi_device *sdev; + int depth; + u16 current_depth; + u16 handle; + int id, channel; + u64 sas_address; + + current_depth = le16_to_cpu(event_data->CurrentDepth); + handle = le16_to_cpu(event_data->DevHandle); + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = _scsih_sas_device_find_by_handle(ioc, handle); + if (!sas_device) { + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + return; + } + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + id = sas_device->id; + channel = sas_device->channel; + sas_address = sas_device->sas_address; + + /* if hidden raid component, then change to volume characteristics */ + if (sas_device->hidden_raid_component && sas_device->volume_handle) { + spin_lock_irqsave(&ioc->raid_device_lock, flags); + raid_device = _scsih_raid_device_find_by_handle( + ioc, sas_device->volume_handle); + spin_unlock_irqrestore(&ioc->raid_device_lock, flags); + if (raid_device) { + id = raid_device->id; + channel = raid_device->channel; + handle = raid_device->handle; + sas_address = raid_device->wwid; + } + } + + if (ioc->logging_level & MPT_DEBUG_TASK_SET_FULL) + starget_printk(KERN_DEBUG, sas_device->starget, "task set " + "full: handle(0x%04x), sas_addr(0x%016llx), depth(%d)\n", + handle, (unsigned long long)sas_address, current_depth); + + shost_for_each_device(sdev, ioc->shost) { + if (sdev->id == id && sdev->channel == channel) { + if (current_depth > sdev->queue_depth) { + if (ioc->logging_level & + MPT_DEBUG_TASK_SET_FULL) + sdev_printk(KERN_INFO, sdev, "strange " + "observation, the queue depth is" + " (%d) meanwhile fw queue depth " + "is (%d)\n", sdev->queue_depth, + current_depth); + continue; + } + depth = scsi_track_queue_full(sdev, + current_depth - 1); + if (depth > 0) + sdev_printk(KERN_INFO, sdev, "Queue depth " + "reduced to (%d)\n", depth); + else if (depth < 0) + sdev_printk(KERN_INFO, sdev, "Tagged Command " + "Queueing is being disabled\n"); + else if (depth == 0) + if (ioc->logging_level & + MPT_DEBUG_TASK_SET_FULL) + sdev_printk(KERN_INFO, sdev, + "Queue depth not changed yet\n"); + } + } +} + +/** + * _scsih_mark_responding_sas_device - mark a sas_devices as responding + * @ioc: per adapter object + * @sas_address: sas address + * @slot: enclosure slot id + * @handle: device handle + * + * After host reset, find out whether devices are still responding. + * Used in _scsi_remove_unresponsive_sas_devices. + * + * Return nothing. + */ +static void +_scsih_mark_responding_sas_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address, + u16 slot, u16 handle) +{ + struct MPT2SAS_TARGET *sas_target_priv_data; + struct scsi_target *starget; + struct _sas_device *sas_device; + unsigned long flags; + + spin_lock_irqsave(&ioc->sas_device_lock, flags); + list_for_each_entry(sas_device, &ioc->sas_device_list, list) { + if (sas_device->sas_address == sas_address && + sas_device->slot == slot && sas_device->starget) { + sas_device->responding = 1; + starget_printk(KERN_INFO, sas_device->starget, + "handle(0x%04x), sas_addr(0x%016llx), enclosure " + "logical id(0x%016llx), slot(%d)\n", handle, + (unsigned long long)sas_device->sas_address, + (unsigned long long) + sas_device->enclosure_logical_id, + sas_device->slot); + if (sas_device->handle == handle) + goto out; + printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n", + sas_device->handle); + sas_device->handle = handle; + starget = sas_device->starget; + sas_target_priv_data = starget->hostdata; + sas_target_priv_data->handle = handle; + goto out; + } + } + out: + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); +} + +/** + * _scsih_search_responding_sas_devices - + * @ioc: per adapter object + * + * After host reset, find out whether devices are still responding. + * If not remove. + * + * Return nothing. + */ +static void +_scsih_search_responding_sas_devices(struct MPT2SAS_ADAPTER *ioc) +{ + Mpi2SasDevicePage0_t sas_device_pg0; + Mpi2ConfigReply_t mpi_reply; + u16 ioc_status; + __le64 sas_address; + u16 handle; + u32 device_info; + u16 slot; + + printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__); + + if (list_empty(&ioc->sas_device_list)) + return; + + handle = 0xFFFF; + while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, + &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE, + handle))) { + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) + break; + handle = le16_to_cpu(sas_device_pg0.DevHandle); + device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); + if (!(_scsih_is_end_device(device_info))) + continue; + sas_address = le64_to_cpu(sas_device_pg0.SASAddress); + slot = le16_to_cpu(sas_device_pg0.Slot); + _scsih_mark_responding_sas_device(ioc, sas_address, slot, + handle); + } +} + +/** + * _scsih_mark_responding_raid_device - mark a raid_device as responding + * @ioc: per adapter object + * @wwid: world wide identifier for raid volume + * @handle: device handle + * + * After host reset, find out whether devices are still responding. + * Used in _scsi_remove_unresponsive_raid_devices. + * + * Return nothing. + */ +static void +_scsih_mark_responding_raid_device(struct MPT2SAS_ADAPTER *ioc, u64 wwid, + u16 handle) +{ + struct MPT2SAS_TARGET *sas_target_priv_data; + struct scsi_target *starget; + struct _raid_device *raid_device; + unsigned long flags; + + spin_lock_irqsave(&ioc->raid_device_lock, flags); + list_for_each_entry(raid_device, &ioc->raid_device_list, list) { + if (raid_device->wwid == wwid && raid_device->starget) { + raid_device->responding = 1; + starget_printk(KERN_INFO, raid_device->starget, + "handle(0x%04x), wwid(0x%016llx)\n", handle, + (unsigned long long)raid_device->wwid); + if (raid_device->handle == handle) + goto out; + printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n", + raid_device->handle); + raid_device->handle = handle; + starget = raid_device->starget; + sas_target_priv_data = starget->hostdata; + sas_target_priv_data->handle = handle; + goto out; + } + } + out: + spin_unlock_irqrestore(&ioc->raid_device_lock, flags); +} + +/** + * _scsih_search_responding_raid_devices - + * @ioc: per adapter object + * + * After host reset, find out whether devices are still responding. + * If not remove. + * + * Return nothing. + */ +static void +_scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc) +{ + Mpi2RaidVolPage1_t volume_pg1; + Mpi2ConfigReply_t mpi_reply; + u16 ioc_status; + u16 handle; + + printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__); + + if (list_empty(&ioc->raid_device_list)) + return; + + handle = 0xFFFF; + while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply, + &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) { + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) + break; + handle = le16_to_cpu(volume_pg1.DevHandle); + _scsih_mark_responding_raid_device(ioc, + le64_to_cpu(volume_pg1.WWID), handle); + } +} + +/** + * _scsih_mark_responding_expander - mark a expander as responding + * @ioc: per adapter object + * @sas_address: sas address + * @handle: + * + * After host reset, find out whether devices are still responding. + * Used in _scsi_remove_unresponsive_expanders. + * + * Return nothing. + */ +static void +_scsih_mark_responding_expander(struct MPT2SAS_ADAPTER *ioc, u64 sas_address, + u16 handle) +{ + struct _sas_node *sas_expander; + unsigned long flags; + + spin_lock_irqsave(&ioc->sas_node_lock, flags); + list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { + if (sas_expander->sas_address == sas_address) { + sas_expander->responding = 1; + if (sas_expander->handle != handle) { + printk(KERN_INFO "old handle(0x%04x)\n", + sas_expander->handle); + sas_expander->handle = handle; + } + goto out; + } + } + out: + spin_unlock_irqrestore(&ioc->sas_node_lock, flags); +} + +/** + * _scsih_search_responding_expanders - + * @ioc: per adapter object + * + * After host reset, find out whether devices are still responding. + * If not remove. + * + * Return nothing. + */ +static void +_scsih_search_responding_expanders(struct MPT2SAS_ADAPTER *ioc) +{ + Mpi2ExpanderPage0_t expander_pg0; + Mpi2ConfigReply_t mpi_reply; + u16 ioc_status; + __le64 sas_address; + u16 handle; + + printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__); + + if (list_empty(&ioc->sas_expander_list)) + return; + + handle = 0xFFFF; + while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0, + MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) { + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) + break; + + handle = le16_to_cpu(expander_pg0.DevHandle); + sas_address = le64_to_cpu(expander_pg0.SASAddress); + printk(KERN_INFO "\texpander present: handle(0x%04x), " + "sas_addr(0x%016llx)\n", handle, + (unsigned long long)sas_address); + _scsih_mark_responding_expander(ioc, sas_address, handle); + } + +} + +/** + * _scsih_remove_unresponding_devices - removing unresponding devices + * @ioc: per adapter object + * + * Return nothing. + */ +static void +_scsih_remove_unresponding_devices(struct MPT2SAS_ADAPTER *ioc) +{ + struct _sas_device *sas_device, *sas_device_next; + struct _sas_node *sas_expander, *sas_expander_next; + struct _raid_device *raid_device, *raid_device_next; + unsigned long flags; + + _scsih_search_responding_sas_devices(ioc); + _scsih_search_responding_raid_devices(ioc); + _scsih_search_responding_expanders(ioc); + + spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); + ioc->shost_recovery = 0; + if (ioc->shost->shost_state == SHOST_RECOVERY) { + printk(MPT2SAS_INFO_FMT "putting controller into " + "SHOST_RUNNING\n", ioc->name); + scsi_host_set_state(ioc->shost, SHOST_RUNNING); + } + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + + list_for_each_entry_safe(sas_device, sas_device_next, + &ioc->sas_device_list, list) { + if (sas_device->responding) { + sas_device->responding = 0; + continue; + } + if (sas_device->starget) + starget_printk(KERN_INFO, sas_device->starget, + "removing: handle(0x%04x), sas_addr(0x%016llx), " + "enclosure logical id(0x%016llx), slot(%d)\n", + sas_device->handle, + (unsigned long long)sas_device->sas_address, + (unsigned long long) + sas_device->enclosure_logical_id, + sas_device->slot); + _scsih_remove_device(ioc, sas_device->handle); + } + + list_for_each_entry_safe(raid_device, raid_device_next, + &ioc->raid_device_list, list) { + if (raid_device->responding) { + raid_device->responding = 0; + continue; + } + if (raid_device->starget) { + starget_printk(KERN_INFO, raid_device->starget, + "removing: handle(0x%04x), wwid(0x%016llx)\n", + raid_device->handle, + (unsigned long long)raid_device->wwid); + scsi_remove_target(&raid_device->starget->dev); + } + _scsih_raid_device_remove(ioc, raid_device); + } + + list_for_each_entry_safe(sas_expander, sas_expander_next, + &ioc->sas_expander_list, list) { + if (sas_expander->responding) { + sas_expander->responding = 0; + continue; + } + printk("\tremoving expander: handle(0x%04x), " + " sas_addr(0x%016llx)\n", sas_expander->handle, + (unsigned long long)sas_expander->sas_address); + _scsih_expander_remove(ioc, sas_expander->handle); + } +} + +/** + * _firmware_event_work - delayed task for processing firmware events + * @ioc: per adapter object + * @work: equal to the fw_event_work object + * Context: user. + * + * Return nothing. + */ +static void +_firmware_event_work(struct work_struct *work) +{ + struct fw_event_work *fw_event = container_of(work, + struct fw_event_work, work.work); + unsigned long flags; + struct MPT2SAS_ADAPTER *ioc = fw_event->ioc; + + /* This is invoked by calling _scsih_queue_rescan(). */ + if (fw_event->event == MPT2SAS_RESCAN_AFTER_HOST_RESET) { + _scsih_fw_event_free(ioc, fw_event); + _scsih_sas_host_refresh(ioc, 1); + _scsih_remove_unresponding_devices(ioc); + return; + } + + /* the queue is being flushed so ignore this event */ + spin_lock_irqsave(&ioc->fw_event_lock, flags); + if (ioc->fw_events_off || ioc->remove_host) { + spin_unlock_irqrestore(&ioc->fw_event_lock, flags); + _scsih_fw_event_free(ioc, fw_event); + return; + } + spin_unlock_irqrestore(&ioc->fw_event_lock, flags); + + spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); + if (ioc->shost_recovery) { + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + _scsih_fw_event_requeue(ioc, fw_event, 1000); + return; + } + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + + switch (fw_event->event) { + case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: + _scsih_sas_topology_change_event(ioc, fw_event->VF_ID, + fw_event->event_data, fw_event); + break; + case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: + _scsih_sas_device_status_change_event(ioc, fw_event->VF_ID, + fw_event->event_data); + break; + case MPI2_EVENT_SAS_DISCOVERY: + _scsih_sas_discovery_event(ioc, fw_event->VF_ID, + fw_event->event_data); + break; + case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE: + _scsih_sas_broadcast_primative_event(ioc, fw_event->VF_ID, + fw_event->event_data); + break; + case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: + _scsih_sas_enclosure_dev_status_change_event(ioc, + fw_event->VF_ID, fw_event->event_data); + break; + case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: + _scsih_sas_ir_config_change_event(ioc, fw_event->VF_ID, + fw_event->event_data); + break; + case MPI2_EVENT_IR_VOLUME: + _scsih_sas_ir_volume_event(ioc, fw_event->VF_ID, + fw_event->event_data); + break; + case MPI2_EVENT_IR_PHYSICAL_DISK: + _scsih_sas_ir_physical_disk_event(ioc, fw_event->VF_ID, + fw_event->event_data); + break; + case MPI2_EVENT_IR_OPERATION_STATUS: + _scsih_sas_ir_operation_status_event(ioc, fw_event->VF_ID, + fw_event->event_data); + break; + case MPI2_EVENT_TASK_SET_FULL: + _scsih_task_set_full(ioc, fw_event->VF_ID, + fw_event->event_data); + break; + } + _scsih_fw_event_free(ioc, fw_event); +} + +/** + * mpt2sas_scsih_event_callback - firmware event handler (called at ISR time) + * @ioc: per adapter object + * @VF_ID: virtual function id + * @reply: reply message frame(lower 32bit addr) + * Context: interrupt. + * + * This function merely adds a new work task into ioc->firmware_event_thread. + * The tasks are worked from _firmware_event_work in user context. + * + * Return nothing. + */ +void +mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply) +{ + struct fw_event_work *fw_event; + Mpi2EventNotificationReply_t *mpi_reply; + unsigned long flags; + u16 event; + + /* events turned off due to host reset or driver unloading */ + spin_lock_irqsave(&ioc->fw_event_lock, flags); + if (ioc->fw_events_off || ioc->remove_host) { + spin_unlock_irqrestore(&ioc->fw_event_lock, flags); + return; + } + spin_unlock_irqrestore(&ioc->fw_event_lock, flags); + + mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); + event = le16_to_cpu(mpi_reply->Event); + + switch (event) { + /* handle these */ + case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE: + { + Mpi2EventDataSasBroadcastPrimitive_t *baen_data = + (Mpi2EventDataSasBroadcastPrimitive_t *) + mpi_reply->EventData; + + if (baen_data->Primitive != + MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT || + ioc->broadcast_aen_busy) + return; + ioc->broadcast_aen_busy = 1; + break; + } + + case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: + _scsih_check_topo_delete_events(ioc, + (Mpi2EventDataSasTopologyChangeList_t *) + mpi_reply->EventData); + break; + + case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: + case MPI2_EVENT_IR_OPERATION_STATUS: + case MPI2_EVENT_SAS_DISCOVERY: + case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: + case MPI2_EVENT_IR_VOLUME: + case MPI2_EVENT_IR_PHYSICAL_DISK: + case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: + case MPI2_EVENT_TASK_SET_FULL: + break; + + default: /* ignore the rest */ + return; + } + + fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); + if (!fw_event) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return; + } + fw_event->event_data = + kzalloc(mpi_reply->EventDataLength*4, GFP_ATOMIC); + if (!fw_event->event_data) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + kfree(fw_event); + return; + } + + memcpy(fw_event->event_data, mpi_reply->EventData, + mpi_reply->EventDataLength*4); + fw_event->ioc = ioc; + fw_event->VF_ID = VF_ID; + fw_event->event = event; + _scsih_fw_event_add(ioc, fw_event); +} + +/* shost template */ +static struct scsi_host_template scsih_driver_template = { + .module = THIS_MODULE, + .name = "Fusion MPT SAS Host", + .proc_name = MPT2SAS_DRIVER_NAME, + .queuecommand = scsih_qcmd, + .target_alloc = scsih_target_alloc, + .slave_alloc = scsih_slave_alloc, + .slave_configure = scsih_slave_configure, + .target_destroy = scsih_target_destroy, + .slave_destroy = scsih_slave_destroy, + .change_queue_depth = scsih_change_queue_depth, + .change_queue_type = scsih_change_queue_type, + .eh_abort_handler = scsih_abort, + .eh_device_reset_handler = scsih_dev_reset, + .eh_host_reset_handler = scsih_host_reset, + .bios_param = scsih_bios_param, + .can_queue = 1, + .this_id = -1, + .sg_tablesize = MPT2SAS_SG_DEPTH, + .max_sectors = 8192, + .cmd_per_lun = 7, + .use_clustering = ENABLE_CLUSTERING, + .shost_attrs = mpt2sas_host_attrs, + .sdev_attrs = mpt2sas_dev_attrs, +}; + +/** + * _scsih_expander_node_remove - removing expander device from list. + * @ioc: per adapter object + * @sas_expander: the sas_device object + * Context: Calling function should acquire ioc->sas_node_lock. + * + * Removing object and freeing associated memory from the + * ioc->sas_expander_list. + * + * Return nothing. + */ +static void +_scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc, + struct _sas_node *sas_expander) +{ + struct _sas_port *mpt2sas_port; + struct _sas_device *sas_device; + struct _sas_node *expander_sibling; + unsigned long flags; + + if (!sas_expander) + return; + + /* remove sibling ports attached to this expander */ + retry_device_search: + list_for_each_entry(mpt2sas_port, + &sas_expander->sas_port_list, port_list) { + if (mpt2sas_port->remote_identify.device_type == + SAS_END_DEVICE) { + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = + mpt2sas_scsih_sas_device_find_by_sas_address(ioc, + mpt2sas_port->remote_identify.sas_address); + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + if (!sas_device) + continue; + _scsih_remove_device(ioc, sas_device->handle); + goto retry_device_search; + } + } + + retry_expander_search: + list_for_each_entry(mpt2sas_port, + &sas_expander->sas_port_list, port_list) { + + if (mpt2sas_port->remote_identify.device_type == + MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER || + mpt2sas_port->remote_identify.device_type == + MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) { + + spin_lock_irqsave(&ioc->sas_node_lock, flags); + expander_sibling = + mpt2sas_scsih_expander_find_by_sas_address( + ioc, mpt2sas_port->remote_identify.sas_address); + spin_unlock_irqrestore(&ioc->sas_node_lock, flags); + if (!expander_sibling) + continue; + _scsih_expander_remove(ioc, expander_sibling->handle); + goto retry_expander_search; + } + } + + mpt2sas_transport_port_remove(ioc, sas_expander->sas_address, + sas_expander->parent_handle); + + printk(MPT2SAS_INFO_FMT "expander_remove: handle" + "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, + sas_expander->handle, (unsigned long long) + sas_expander->sas_address); + + list_del(&sas_expander->list); + kfree(sas_expander->phy); + kfree(sas_expander); +} + +/** + * scsih_remove - detach and remove add host + * @pdev: PCI device struct + * + * Return nothing. + */ +static void __devexit +scsih_remove(struct pci_dev *pdev) +{ + struct Scsi_Host *shost = pci_get_drvdata(pdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + struct _sas_port *mpt2sas_port; + struct _sas_device *sas_device; + struct _sas_node *expander_sibling; + struct workqueue_struct *wq; + unsigned long flags; + + ioc->remove_host = 1; + _scsih_fw_event_off(ioc); + + spin_lock_irqsave(&ioc->fw_event_lock, flags); + wq = ioc->firmware_event_thread; + ioc->firmware_event_thread = NULL; + spin_unlock_irqrestore(&ioc->fw_event_lock, flags); + if (wq) + destroy_workqueue(wq); + + /* free ports attached to the sas_host */ + retry_again: + list_for_each_entry(mpt2sas_port, + &ioc->sas_hba.sas_port_list, port_list) { + if (mpt2sas_port->remote_identify.device_type == + SAS_END_DEVICE) { + sas_device = + mpt2sas_scsih_sas_device_find_by_sas_address(ioc, + mpt2sas_port->remote_identify.sas_address); + if (sas_device) { + _scsih_remove_device(ioc, sas_device->handle); + goto retry_again; + } + } else { + expander_sibling = + mpt2sas_scsih_expander_find_by_sas_address(ioc, + mpt2sas_port->remote_identify.sas_address); + if (expander_sibling) { + _scsih_expander_remove(ioc, + expander_sibling->handle); + goto retry_again; + } + } + } + + /* free phys attached to the sas_host */ + if (ioc->sas_hba.num_phys) { + kfree(ioc->sas_hba.phy); + ioc->sas_hba.phy = NULL; + ioc->sas_hba.num_phys = 0; + } + + sas_remove_host(shost); + mpt2sas_base_detach(ioc); + list_del(&ioc->list); + scsi_remove_host(shost); + scsi_host_put(shost); +} + +/** + * _scsih_probe_boot_devices - reports 1st device + * @ioc: per adapter object + * + * If specified in bios page 2, this routine reports the 1st + * device scsi-ml or sas transport for persistent boot device + * purposes. Please refer to function _scsih_determine_boot_device() + */ +static void +_scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc) +{ + u8 is_raid; + void *device; + struct _sas_device *sas_device; + struct _raid_device *raid_device; + u16 handle, parent_handle; + u64 sas_address; + unsigned long flags; + int rc; + + device = NULL; + if (ioc->req_boot_device.device) { + device = ioc->req_boot_device.device; + is_raid = ioc->req_boot_device.is_raid; + } else if (ioc->req_alt_boot_device.device) { + device = ioc->req_alt_boot_device.device; + is_raid = ioc->req_alt_boot_device.is_raid; + } else if (ioc->current_boot_device.device) { + device = ioc->current_boot_device.device; + is_raid = ioc->current_boot_device.is_raid; + } + + if (!device) + return; + + if (is_raid) { + raid_device = device; + rc = scsi_add_device(ioc->shost, RAID_CHANNEL, + raid_device->id, 0); + if (rc) + _scsih_raid_device_remove(ioc, raid_device); + } else { + sas_device = device; + handle = sas_device->handle; + parent_handle = sas_device->parent_handle; + sas_address = sas_device->sas_address; + spin_lock_irqsave(&ioc->sas_device_lock, flags); + list_move_tail(&sas_device->list, &ioc->sas_device_list); + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + if (!mpt2sas_transport_port_add(ioc, sas_device->handle, + sas_device->parent_handle)) { + _scsih_sas_device_remove(ioc, sas_device); + } else if (!sas_device->starget) { + mpt2sas_transport_port_remove(ioc, sas_address, + parent_handle); + _scsih_sas_device_remove(ioc, sas_device); + } + } +} + +/** + * _scsih_probe_raid - reporting raid volumes to scsi-ml + * @ioc: per adapter object + * + * Called during initial loading of the driver. + */ +static void +_scsih_probe_raid(struct MPT2SAS_ADAPTER *ioc) +{ + struct _raid_device *raid_device, *raid_next; + int rc; + + list_for_each_entry_safe(raid_device, raid_next, + &ioc->raid_device_list, list) { + if (raid_device->starget) + continue; + rc = scsi_add_device(ioc->shost, RAID_CHANNEL, + raid_device->id, 0); + if (rc) + _scsih_raid_device_remove(ioc, raid_device); + } +} + +/** + * _scsih_probe_sas - reporting raid volumes to sas transport + * @ioc: per adapter object + * + * Called during initial loading of the driver. + */ +static void +_scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc) +{ + struct _sas_device *sas_device, *next; + unsigned long flags; + u16 handle, parent_handle; + u64 sas_address; + + /* SAS Device List */ + list_for_each_entry_safe(sas_device, next, &ioc->sas_device_init_list, + list) { + spin_lock_irqsave(&ioc->sas_device_lock, flags); + list_move_tail(&sas_device->list, &ioc->sas_device_list); + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + + handle = sas_device->handle; + parent_handle = sas_device->parent_handle; + sas_address = sas_device->sas_address; + if (!mpt2sas_transport_port_add(ioc, handle, parent_handle)) { + _scsih_sas_device_remove(ioc, sas_device); + } else if (!sas_device->starget) { + mpt2sas_transport_port_remove(ioc, sas_address, + parent_handle); + _scsih_sas_device_remove(ioc, sas_device); + } + } +} + +/** + * _scsih_probe_devices - probing for devices + * @ioc: per adapter object + * + * Called during initial loading of the driver. + */ +static void +_scsih_probe_devices(struct MPT2SAS_ADAPTER *ioc) +{ + u16 volume_mapping_flags = + le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) & + MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; + + if (!(ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR)) + return; /* return when IOC doesn't support initiator mode */ + + _scsih_probe_boot_devices(ioc); + + if (ioc->ir_firmware) { + if ((volume_mapping_flags & + MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING)) { + _scsih_probe_sas(ioc); + _scsih_probe_raid(ioc); + } else { + _scsih_probe_raid(ioc); + _scsih_probe_sas(ioc); + } + } else + _scsih_probe_sas(ioc); +} + +/** + * scsih_probe - attach and add scsi host + * @pdev: PCI device struct + * @id: pci device id + * + * Returns 0 success, anything else error. + */ +static int +scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct MPT2SAS_ADAPTER *ioc; + struct Scsi_Host *shost; + + shost = scsi_host_alloc(&scsih_driver_template, + sizeof(struct MPT2SAS_ADAPTER)); + if (!shost) + return -ENODEV; + + /* init local params */ + ioc = shost_priv(shost); + memset(ioc, 0, sizeof(struct MPT2SAS_ADAPTER)); + INIT_LIST_HEAD(&ioc->list); + list_add_tail(&ioc->list, &ioc_list); + ioc->shost = shost; + ioc->id = mpt_ids++; + sprintf(ioc->name, "%s%d", MPT2SAS_DRIVER_NAME, ioc->id); + ioc->pdev = pdev; + ioc->scsi_io_cb_idx = scsi_io_cb_idx; + ioc->tm_cb_idx = tm_cb_idx; + ioc->ctl_cb_idx = ctl_cb_idx; + ioc->base_cb_idx = base_cb_idx; + ioc->transport_cb_idx = transport_cb_idx; + ioc->config_cb_idx = config_cb_idx; + ioc->logging_level = logging_level; + /* misc semaphores and spin locks */ + spin_lock_init(&ioc->ioc_reset_in_progress_lock); + spin_lock_init(&ioc->scsi_lookup_lock); + spin_lock_init(&ioc->sas_device_lock); + spin_lock_init(&ioc->sas_node_lock); + spin_lock_init(&ioc->fw_event_lock); + spin_lock_init(&ioc->raid_device_lock); + + INIT_LIST_HEAD(&ioc->sas_device_list); + INIT_LIST_HEAD(&ioc->sas_device_init_list); + INIT_LIST_HEAD(&ioc->sas_expander_list); + INIT_LIST_HEAD(&ioc->fw_event_list); + INIT_LIST_HEAD(&ioc->raid_device_list); + INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list); + + /* init shost parameters */ + shost->max_cmd_len = 16; + shost->max_lun = max_lun; + shost->transportt = mpt2sas_transport_template; + shost->unique_id = ioc->id; + + if ((scsi_add_host(shost, &pdev->dev))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + list_del(&ioc->list); + goto out_add_shost_fail; + } + + /* event thread */ + snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name), + "fw_event%d", ioc->id); + ioc->firmware_event_thread = create_singlethread_workqueue( + ioc->firmware_event_name); + if (!ioc->firmware_event_thread) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + goto out_thread_fail; + } + + ioc->wait_for_port_enable_to_complete = 1; + if ((mpt2sas_base_attach(ioc))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + goto out_attach_fail; + } + + ioc->wait_for_port_enable_to_complete = 0; + _scsih_probe_devices(ioc); + return 0; + + out_attach_fail: + destroy_workqueue(ioc->firmware_event_thread); + out_thread_fail: + list_del(&ioc->list); + scsi_remove_host(shost); + out_add_shost_fail: + return -ENODEV; +} + +#ifdef CONFIG_PM +/** + * scsih_suspend - power management suspend main entry point + * @pdev: PCI device struct + * @state: PM state change to (usually PCI_D3) + * + * Returns 0 success, anything else error. + */ +static int +scsih_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct Scsi_Host *shost = pci_get_drvdata(pdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + u32 device_state; + + flush_scheduled_work(); + scsi_block_requests(shost); + device_state = pci_choose_state(pdev, state); + printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, entering " + "operating state [D%d]\n", ioc->name, pdev, + pci_name(pdev), device_state); + + mpt2sas_base_free_resources(ioc); + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, device_state); + return 0; +} + +/** + * scsih_resume - power management resume main entry point + * @pdev: PCI device struct + * + * Returns 0 success, anything else error. + */ +static int +scsih_resume(struct pci_dev *pdev) +{ + struct Scsi_Host *shost = pci_get_drvdata(pdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + u32 device_state = pdev->current_state; + int r; + + printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, previous " + "operating state [D%d]\n", ioc->name, pdev, + pci_name(pdev), device_state); + + pci_set_power_state(pdev, PCI_D0); + pci_enable_wake(pdev, PCI_D0, 0); + pci_restore_state(pdev); + ioc->pdev = pdev; + r = mpt2sas_base_map_resources(ioc); + if (r) + return r; + + mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET); + scsi_unblock_requests(shost); + return 0; +} +#endif /* CONFIG_PM */ + + +static struct pci_driver scsih_driver = { + .name = MPT2SAS_DRIVER_NAME, + .id_table = scsih_pci_table, + .probe = scsih_probe, + .remove = __devexit_p(scsih_remove), +#ifdef CONFIG_PM + .suspend = scsih_suspend, + .resume = scsih_resume, +#endif +}; + + +/** + * scsih_init - main entry point for this driver. + * + * Returns 0 success, anything else error. + */ +static int __init +scsih_init(void) +{ + int error; + + mpt_ids = 0; + printk(KERN_INFO "%s version %s loaded\n", MPT2SAS_DRIVER_NAME, + MPT2SAS_DRIVER_VERSION); + + mpt2sas_transport_template = + sas_attach_transport(&mpt2sas_transport_functions); + if (!mpt2sas_transport_template) + return -ENODEV; + + mpt2sas_base_initialize_callback_handler(); + + /* queuecommand callback hander */ + scsi_io_cb_idx = mpt2sas_base_register_callback_handler(scsih_io_done); + + /* task managment callback handler */ + tm_cb_idx = mpt2sas_base_register_callback_handler(scsih_tm_done); + + /* base internal commands callback handler */ + base_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_base_done); + + /* transport internal commands callback handler */ + transport_cb_idx = mpt2sas_base_register_callback_handler( + mpt2sas_transport_done); + + /* configuration page API internal commands callback handler */ + config_cb_idx = mpt2sas_base_register_callback_handler( + mpt2sas_config_done); + + /* ctl module callback handler */ + ctl_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_ctl_done); + + mpt2sas_ctl_init(); + + error = pci_register_driver(&scsih_driver); + if (error) + sas_release_transport(mpt2sas_transport_template); + + return error; +} + +/** + * scsih_exit - exit point for this driver (when it is a module). + * + * Returns 0 success, anything else error. + */ +static void __exit +scsih_exit(void) +{ + printk(KERN_INFO "mpt2sas version %s unloading\n", + MPT2SAS_DRIVER_VERSION); + + pci_unregister_driver(&scsih_driver); + + sas_release_transport(mpt2sas_transport_template); + mpt2sas_base_release_callback_handler(scsi_io_cb_idx); + mpt2sas_base_release_callback_handler(tm_cb_idx); + mpt2sas_base_release_callback_handler(base_cb_idx); + mpt2sas_base_release_callback_handler(transport_cb_idx); + mpt2sas_base_release_callback_handler(config_cb_idx); + mpt2sas_base_release_callback_handler(ctl_cb_idx); + + mpt2sas_ctl_exit(); +} + +module_init(scsih_init); +module_exit(scsih_exit); diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c new file mode 100644 index 00000000000..e03dc0b1e1a --- /dev/null +++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c @@ -0,0 +1,1211 @@ +/* + * SAS Transport Layer for MPT (Message Passing Technology) based controllers + * + * This code is based on drivers/scsi/mpt2sas/mpt2_transport.c + * Copyright (C) 2007-2008 LSI Corporation + * (mailto:DL-MPTFusionLinux@lsi.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * NO WARRANTY + * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT + * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is + * solely responsible for determining the appropriateness of using and + * distributing the Program and assumes all risks associated with its + * exercise of rights under this Agreement, including but not limited to + * the risks and costs of program errors, damage to or loss of data, + * programs or equipment, and unavailability or interruption of operations. + + * DISCLAIMER OF LIABILITY + * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED + * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "mpt2sas_base.h" +/** + * _transport_sas_node_find_by_handle - sas node search + * @ioc: per adapter object + * @handle: expander or hba handle (assigned by firmware) + * Context: Calling function should acquire ioc->sas_node_lock. + * + * Search for either hba phys or expander device based on handle, then returns + * the sas_node object. + */ +static struct _sas_node * +_transport_sas_node_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) +{ + int i; + + for (i = 0; i < ioc->sas_hba.num_phys; i++) + if (ioc->sas_hba.phy[i].handle == handle) + return &ioc->sas_hba; + + return mpt2sas_scsih_expander_find_by_handle(ioc, handle); +} + +/** + * _transport_convert_phy_link_rate - + * @link_rate: link rate returned from mpt firmware + * + * Convert link_rate from mpi fusion into sas_transport form. + */ +static enum sas_linkrate +_transport_convert_phy_link_rate(u8 link_rate) +{ + enum sas_linkrate rc; + + switch (link_rate) { + case MPI2_SAS_NEG_LINK_RATE_1_5: + rc = SAS_LINK_RATE_1_5_GBPS; + break; + case MPI2_SAS_NEG_LINK_RATE_3_0: + rc = SAS_LINK_RATE_3_0_GBPS; + break; + case MPI2_SAS_NEG_LINK_RATE_6_0: + rc = SAS_LINK_RATE_6_0_GBPS; + break; + case MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED: + rc = SAS_PHY_DISABLED; + break; + case MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED: + rc = SAS_LINK_RATE_FAILED; + break; + case MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR: + rc = SAS_SATA_PORT_SELECTOR; + break; + case MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS: + rc = SAS_PHY_RESET_IN_PROGRESS; + break; + default: + case MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE: + case MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE: + rc = SAS_LINK_RATE_UNKNOWN; + break; + } + return rc; +} + +/** + * _transport_set_identify - set identify for phys and end devices + * @ioc: per adapter object + * @handle: device handle + * @identify: sas identify info + * + * Populates sas identify info. + * + * Returns 0 for success, non-zero for failure. + */ +static int +_transport_set_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle, + struct sas_identify *identify) +{ + Mpi2SasDevicePage0_t sas_device_pg0; + Mpi2ConfigReply_t mpi_reply; + u32 device_info; + u32 ioc_status; + + if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, + MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return -1; + } + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x)" + "\nfailure at %s:%d/%s()!\n", ioc->name, handle, ioc_status, + __FILE__, __LINE__, __func__); + return -1; + } + + memset(identify, 0, sizeof(identify)); + device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); + + /* sas_address */ + identify->sas_address = le64_to_cpu(sas_device_pg0.SASAddress); + + /* device_type */ + switch (device_info & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) { + case MPI2_SAS_DEVICE_INFO_NO_DEVICE: + identify->device_type = SAS_PHY_UNUSED; + break; + case MPI2_SAS_DEVICE_INFO_END_DEVICE: + identify->device_type = SAS_END_DEVICE; + break; + case MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER: + identify->device_type = SAS_EDGE_EXPANDER_DEVICE; + break; + case MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER: + identify->device_type = SAS_FANOUT_EXPANDER_DEVICE; + break; + } + + /* initiator_port_protocols */ + if (device_info & MPI2_SAS_DEVICE_INFO_SSP_INITIATOR) + identify->initiator_port_protocols |= SAS_PROTOCOL_SSP; + if (device_info & MPI2_SAS_DEVICE_INFO_STP_INITIATOR) + identify->initiator_port_protocols |= SAS_PROTOCOL_STP; + if (device_info & MPI2_SAS_DEVICE_INFO_SMP_INITIATOR) + identify->initiator_port_protocols |= SAS_PROTOCOL_SMP; + if (device_info & MPI2_SAS_DEVICE_INFO_SATA_HOST) + identify->initiator_port_protocols |= SAS_PROTOCOL_SATA; + + /* target_port_protocols */ + if (device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) + identify->target_port_protocols |= SAS_PROTOCOL_SSP; + if (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET) + identify->target_port_protocols |= SAS_PROTOCOL_STP; + if (device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET) + identify->target_port_protocols |= SAS_PROTOCOL_SMP; + if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) + identify->target_port_protocols |= SAS_PROTOCOL_SATA; + + return 0; +} + +/** + * mpt2sas_transport_done - internal transport layer callback handler. + * @ioc: per adapter object + * @smid: system request message index + * @VF_ID: virtual function id + * @reply: reply message frame(lower 32bit addr) + * + * Callback handler when sending internal generated transport cmds. + * The callback index passed is `ioc->transport_cb_idx` + * + * Return nothing. + */ +void +mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, + u32 reply) +{ + MPI2DefaultReply_t *mpi_reply; + + mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); + if (ioc->transport_cmds.status == MPT2_CMD_NOT_USED) + return; + if (ioc->transport_cmds.smid != smid) + return; + ioc->transport_cmds.status |= MPT2_CMD_COMPLETE; + if (mpi_reply) { + memcpy(ioc->transport_cmds.reply, mpi_reply, + mpi_reply->MsgLength*4); + ioc->transport_cmds.status |= MPT2_CMD_REPLY_VALID; + } + ioc->transport_cmds.status &= ~MPT2_CMD_PENDING; + complete(&ioc->transport_cmds.done); +} + +/* report manufacture request structure */ +struct rep_manu_request{ + u8 smp_frame_type; + u8 function; + u8 reserved; + u8 request_length; +}; + +/* report manufacture reply structure */ +struct rep_manu_reply{ + u8 smp_frame_type; /* 0x41 */ + u8 function; /* 0x01 */ + u8 function_result; + u8 response_length; + u16 expander_change_count; + u8 reserved0[2]; + u8 sas_format:1; + u8 reserved1:7; + u8 reserved2[3]; + u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN]; + u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN]; + u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN]; + u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN]; + u16 component_id; + u8 component_revision_id; + u8 reserved3; + u8 vendor_specific[8]; +}; + +/** + * transport_expander_report_manufacture - obtain SMP report_manufacture + * @ioc: per adapter object + * @sas_address: expander sas address + * @edev: the sas_expander_device object + * + * Fills in the sas_expander_device object when SMP port is created. + * + * Returns 0 for success, non-zero for failure. + */ +static int +transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc, + u64 sas_address, struct sas_expander_device *edev) +{ + Mpi2SmpPassthroughRequest_t *mpi_request; + Mpi2SmpPassthroughReply_t *mpi_reply; + struct rep_manu_reply *manufacture_reply; + struct rep_manu_request *manufacture_request; + int rc; + u16 smid; + u32 ioc_state; + unsigned long timeleft; + void *psge; + u32 sgl_flags; + u8 issue_reset = 0; + unsigned long flags; + void *data_out = NULL; + dma_addr_t data_out_dma; + u32 sz; + u64 *sas_address_le; + u16 wait_state_count; + + spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); + if (ioc->ioc_reset_in_progress) { + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n", + __func__, ioc->name); + return -EFAULT; + } + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + + mutex_lock(&ioc->transport_cmds.mutex); + + if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) { + printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n", + ioc->name, __func__); + rc = -EAGAIN; + goto out; + } + ioc->transport_cmds.status = MPT2_CMD_PENDING; + + wait_state_count = 0; + ioc_state = mpt2sas_base_get_iocstate(ioc, 1); + while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { + if (wait_state_count++ == 10) { + printk(MPT2SAS_ERR_FMT + "%s: failed due to ioc not operational\n", + ioc->name, __func__); + rc = -EFAULT; + goto out; + } + ssleep(1); + ioc_state = mpt2sas_base_get_iocstate(ioc, 1); + printk(MPT2SAS_INFO_FMT "%s: waiting for " + "operational state(count=%d)\n", ioc->name, + __func__, wait_state_count); + } + if (wait_state_count) + printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n", + ioc->name, __func__); + + smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx); + if (!smid) { + printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", + ioc->name, __func__); + rc = -EAGAIN; + goto out; + } + + rc = 0; + mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); + ioc->transport_cmds.smid = smid; + + sz = sizeof(struct rep_manu_request) + sizeof(struct rep_manu_reply); + data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma); + + if (!data_out) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, + __LINE__, __func__); + rc = -ENOMEM; + mpt2sas_base_free_smid(ioc, smid); + goto out; + } + + manufacture_request = data_out; + manufacture_request->smp_frame_type = 0x40; + manufacture_request->function = 1; + manufacture_request->reserved = 0; + manufacture_request->request_length = 0; + + memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); + mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; + mpi_request->PhysicalPort = 0xFF; + sas_address_le = (u64 *)&mpi_request->SASAddress; + *sas_address_le = cpu_to_le64(sas_address); + mpi_request->RequestDataLength = sizeof(struct rep_manu_request); + psge = &mpi_request->SGL; + + /* WRITE sgel first */ + sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | + MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC); + sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; + ioc->base_add_sg_single(psge, sgl_flags | + sizeof(struct rep_manu_request), data_out_dma); + + /* incr sgel */ + psge += ioc->sge_size; + + /* READ sgel last */ + sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | + MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | + MPI2_SGE_FLAGS_END_OF_LIST); + sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; + ioc->base_add_sg_single(psge, sgl_flags | + sizeof(struct rep_manu_reply), data_out_dma + + sizeof(struct rep_manu_request)); + + dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "report_manufacture - " + "send to sas_addr(0x%016llx)\n", ioc->name, + (unsigned long long)sas_address)); + mpt2sas_base_put_smid_default(ioc, smid, 0 /* VF_ID */); + timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, + 10*HZ); + + if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) { + printk(MPT2SAS_ERR_FMT "%s: timeout\n", + ioc->name, __func__); + _debug_dump_mf(mpi_request, + sizeof(Mpi2SmpPassthroughRequest_t)/4); + if (!(ioc->transport_cmds.status & MPT2_CMD_RESET)) + issue_reset = 1; + goto issue_host_reset; + } + + dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "report_manufacture - " + "complete\n", ioc->name)); + + if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) { + u8 *tmp; + + mpi_reply = ioc->transport_cmds.reply; + + dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT + "report_manufacture - reply data transfer size(%d)\n", + ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength))); + + if (le16_to_cpu(mpi_reply->ResponseDataLength) != + sizeof(struct rep_manu_reply)) + goto out; + + manufacture_reply = data_out + sizeof(struct rep_manu_request); + strncpy(edev->vendor_id, manufacture_reply->vendor_id, + SAS_EXPANDER_VENDOR_ID_LEN); + strncpy(edev->product_id, manufacture_reply->product_id, + SAS_EXPANDER_PRODUCT_ID_LEN); + strncpy(edev->product_rev, manufacture_reply->product_rev, + SAS_EXPANDER_PRODUCT_REV_LEN); + edev->level = manufacture_reply->sas_format; + if (manufacture_reply->sas_format) { + strncpy(edev->component_vendor_id, + manufacture_reply->component_vendor_id, + SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN); + tmp = (u8 *)&manufacture_reply->component_id; + edev->component_id = tmp[0] << 8 | tmp[1]; + edev->component_revision_id = + manufacture_reply->component_revision_id; + } + } else + dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT + "report_manufacture - no reply\n", ioc->name)); + + issue_host_reset: + if (issue_reset) + mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, + FORCE_BIG_HAMMER); + out: + ioc->transport_cmds.status = MPT2_CMD_NOT_USED; + if (data_out) + pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma); + + mutex_unlock(&ioc->transport_cmds.mutex); + return rc; +} + +/** + * mpt2sas_transport_port_add - insert port to the list + * @ioc: per adapter object + * @handle: handle of attached device + * @parent_handle: parent handle(either hba or expander) + * Context: This function will acquire ioc->sas_node_lock. + * + * Adding new port object to the sas_node->sas_port_list. + * + * Returns mpt2sas_port. + */ +struct _sas_port * +mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle, + u16 parent_handle) +{ + struct _sas_phy *mpt2sas_phy, *next; + struct _sas_port *mpt2sas_port; + unsigned long flags; + struct _sas_node *sas_node; + struct sas_rphy *rphy; + int i; + struct sas_port *port; + + if (!parent_handle) + return NULL; + + mpt2sas_port = kzalloc(sizeof(struct _sas_port), + GFP_KERNEL); + if (!mpt2sas_port) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return NULL; + } + + INIT_LIST_HEAD(&mpt2sas_port->port_list); + INIT_LIST_HEAD(&mpt2sas_port->phy_list); + spin_lock_irqsave(&ioc->sas_node_lock, flags); + sas_node = _transport_sas_node_find_by_handle(ioc, parent_handle); + spin_unlock_irqrestore(&ioc->sas_node_lock, flags); + + if (!sas_node) { + printk(MPT2SAS_ERR_FMT "%s: Could not find parent(0x%04x)!\n", + ioc->name, __func__, parent_handle); + goto out_fail; + } + + mpt2sas_port->handle = parent_handle; + mpt2sas_port->sas_address = sas_node->sas_address; + if ((_transport_set_identify(ioc, handle, + &mpt2sas_port->remote_identify))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + goto out_fail; + } + + if (mpt2sas_port->remote_identify.device_type == SAS_PHY_UNUSED) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + goto out_fail; + } + + for (i = 0; i < sas_node->num_phys; i++) { + if (sas_node->phy[i].remote_identify.sas_address != + mpt2sas_port->remote_identify.sas_address) + continue; + list_add_tail(&sas_node->phy[i].port_siblings, + &mpt2sas_port->phy_list); + mpt2sas_port->num_phys++; + } + + if (!mpt2sas_port->num_phys) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + goto out_fail; + } + + port = sas_port_alloc_num(sas_node->parent_dev); + if ((sas_port_add(port))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + goto out_fail; + } + + list_for_each_entry(mpt2sas_phy, &mpt2sas_port->phy_list, + port_siblings) { + if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) + dev_printk(KERN_INFO, &port->dev, "add: handle(0x%04x)" + ", sas_addr(0x%016llx), phy(%d)\n", handle, + (unsigned long long) + mpt2sas_port->remote_identify.sas_address, + mpt2sas_phy->phy_id); + sas_port_add_phy(port, mpt2sas_phy->phy); + } + + mpt2sas_port->port = port; + if (mpt2sas_port->remote_identify.device_type == SAS_END_DEVICE) + rphy = sas_end_device_alloc(port); + else + rphy = sas_expander_alloc(port, + mpt2sas_port->remote_identify.device_type); + + rphy->identify = mpt2sas_port->remote_identify; + if ((sas_rphy_add(rphy))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + } + if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) + dev_printk(KERN_INFO, &rphy->dev, "add: handle(0x%04x), " + "sas_addr(0x%016llx)\n", handle, + (unsigned long long) + mpt2sas_port->remote_identify.sas_address); + mpt2sas_port->rphy = rphy; + spin_lock_irqsave(&ioc->sas_node_lock, flags); + list_add_tail(&mpt2sas_port->port_list, &sas_node->sas_port_list); + spin_unlock_irqrestore(&ioc->sas_node_lock, flags); + + /* fill in report manufacture */ + if (mpt2sas_port->remote_identify.device_type == + MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER || + mpt2sas_port->remote_identify.device_type == + MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) + transport_expander_report_manufacture(ioc, + mpt2sas_port->remote_identify.sas_address, + rphy_to_expander_device(rphy)); + + return mpt2sas_port; + + out_fail: + list_for_each_entry_safe(mpt2sas_phy, next, &mpt2sas_port->phy_list, + port_siblings) + list_del(&mpt2sas_phy->port_siblings); + kfree(mpt2sas_port); + return NULL; +} + +/** + * mpt2sas_transport_port_remove - remove port from the list + * @ioc: per adapter object + * @sas_address: sas address of attached device + * @parent_handle: handle to the upstream parent(either hba or expander) + * Context: This function will acquire ioc->sas_node_lock. + * + * Removing object and freeing associated memory from the + * ioc->sas_port_list. + * + * Return nothing. + */ +void +mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address, + u16 parent_handle) +{ + int i; + unsigned long flags; + struct _sas_port *mpt2sas_port, *next; + struct _sas_node *sas_node; + u8 found = 0; + struct _sas_phy *mpt2sas_phy, *next_phy; + + spin_lock_irqsave(&ioc->sas_node_lock, flags); + sas_node = _transport_sas_node_find_by_handle(ioc, parent_handle); + spin_unlock_irqrestore(&ioc->sas_node_lock, flags); + if (!sas_node) + return; + list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list, + port_list) { + if (mpt2sas_port->remote_identify.sas_address != sas_address) + continue; + found = 1; + list_del(&mpt2sas_port->port_list); + goto out; + } + out: + if (!found) + return; + + for (i = 0; i < sas_node->num_phys; i++) { + if (sas_node->phy[i].remote_identify.sas_address == sas_address) + memset(&sas_node->phy[i].remote_identify, 0 , + sizeof(struct sas_identify)); + } + + list_for_each_entry_safe(mpt2sas_phy, next_phy, + &mpt2sas_port->phy_list, port_siblings) { + if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) + dev_printk(KERN_INFO, &mpt2sas_port->port->dev, + "remove: parent_handle(0x%04x), " + "sas_addr(0x%016llx), phy(%d)\n", parent_handle, + (unsigned long long) + mpt2sas_port->remote_identify.sas_address, + mpt2sas_phy->phy_id); + sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy); + list_del(&mpt2sas_phy->port_siblings); + } + sas_port_delete(mpt2sas_port->port); + kfree(mpt2sas_port); +} + +/** + * mpt2sas_transport_add_host_phy - report sas_host phy to transport + * @ioc: per adapter object + * @mpt2sas_phy: mpt2sas per phy object + * @phy_pg0: sas phy page 0 + * @parent_dev: parent device class object + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy + *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev) +{ + struct sas_phy *phy; + int phy_index = mpt2sas_phy->phy_id; + + + INIT_LIST_HEAD(&mpt2sas_phy->port_siblings); + phy = sas_phy_alloc(parent_dev, phy_index); + if (!phy) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return -1; + } + if ((_transport_set_identify(ioc, mpt2sas_phy->handle, + &mpt2sas_phy->identify))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return -1; + } + phy->identify = mpt2sas_phy->identify; + mpt2sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle); + if (mpt2sas_phy->attached_handle) + _transport_set_identify(ioc, mpt2sas_phy->attached_handle, + &mpt2sas_phy->remote_identify); + phy->identify.phy_identifier = mpt2sas_phy->phy_id; + phy->negotiated_linkrate = _transport_convert_phy_link_rate( + phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL); + phy->minimum_linkrate_hw = _transport_convert_phy_link_rate( + phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK); + phy->maximum_linkrate_hw = _transport_convert_phy_link_rate( + phy_pg0.HwLinkRate >> 4); + phy->minimum_linkrate = _transport_convert_phy_link_rate( + phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK); + phy->maximum_linkrate = _transport_convert_phy_link_rate( + phy_pg0.ProgrammedLinkRate >> 4); + + if ((sas_phy_add(phy))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + sas_phy_free(phy); + return -1; + } + if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) + dev_printk(KERN_INFO, &phy->dev, + "add: handle(0x%04x), sas_addr(0x%016llx)\n" + "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n", + mpt2sas_phy->handle, (unsigned long long) + mpt2sas_phy->identify.sas_address, + mpt2sas_phy->attached_handle, + (unsigned long long) + mpt2sas_phy->remote_identify.sas_address); + mpt2sas_phy->phy = phy; + return 0; +} + + +/** + * mpt2sas_transport_add_expander_phy - report expander phy to transport + * @ioc: per adapter object + * @mpt2sas_phy: mpt2sas per phy object + * @expander_pg1: expander page 1 + * @parent_dev: parent device class object + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy + *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev) +{ + struct sas_phy *phy; + int phy_index = mpt2sas_phy->phy_id; + + INIT_LIST_HEAD(&mpt2sas_phy->port_siblings); + phy = sas_phy_alloc(parent_dev, phy_index); + if (!phy) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return -1; + } + if ((_transport_set_identify(ioc, mpt2sas_phy->handle, + &mpt2sas_phy->identify))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return -1; + } + phy->identify = mpt2sas_phy->identify; + mpt2sas_phy->attached_handle = + le16_to_cpu(expander_pg1.AttachedDevHandle); + if (mpt2sas_phy->attached_handle) + _transport_set_identify(ioc, mpt2sas_phy->attached_handle, + &mpt2sas_phy->remote_identify); + phy->identify.phy_identifier = mpt2sas_phy->phy_id; + phy->negotiated_linkrate = _transport_convert_phy_link_rate( + expander_pg1.NegotiatedLinkRate & + MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL); + phy->minimum_linkrate_hw = _transport_convert_phy_link_rate( + expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK); + phy->maximum_linkrate_hw = _transport_convert_phy_link_rate( + expander_pg1.HwLinkRate >> 4); + phy->minimum_linkrate = _transport_convert_phy_link_rate( + expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK); + phy->maximum_linkrate = _transport_convert_phy_link_rate( + expander_pg1.ProgrammedLinkRate >> 4); + + if ((sas_phy_add(phy))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + sas_phy_free(phy); + return -1; + } + if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) + dev_printk(KERN_INFO, &phy->dev, + "add: handle(0x%04x), sas_addr(0x%016llx)\n" + "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n", + mpt2sas_phy->handle, (unsigned long long) + mpt2sas_phy->identify.sas_address, + mpt2sas_phy->attached_handle, + (unsigned long long) + mpt2sas_phy->remote_identify.sas_address); + mpt2sas_phy->phy = phy; + return 0; +} + +/** + * mpt2sas_transport_update_phy_link_change - refreshing phy link changes and attached devices + * @ioc: per adapter object + * @handle: handle to sas_host or expander + * @attached_handle: attached device handle + * @phy_numberv: phy number + * @link_rate: new link rate + * + * Returns nothing. + */ +void +mpt2sas_transport_update_phy_link_change(struct MPT2SAS_ADAPTER *ioc, + u16 handle, u16 attached_handle, u8 phy_number, u8 link_rate) +{ + unsigned long flags; + struct _sas_node *sas_node; + struct _sas_phy *mpt2sas_phy; + + spin_lock_irqsave(&ioc->sas_node_lock, flags); + sas_node = _transport_sas_node_find_by_handle(ioc, handle); + spin_unlock_irqrestore(&ioc->sas_node_lock, flags); + if (!sas_node) + return; + + mpt2sas_phy = &sas_node->phy[phy_number]; + mpt2sas_phy->attached_handle = attached_handle; + if (attached_handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) + _transport_set_identify(ioc, mpt2sas_phy->attached_handle, + &mpt2sas_phy->remote_identify); + else + memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct + sas_identify)); + + if (mpt2sas_phy->phy) + mpt2sas_phy->phy->negotiated_linkrate = + _transport_convert_phy_link_rate(link_rate); + + if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) + dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev, + "refresh: handle(0x%04x), sas_addr(0x%016llx),\n" + "\tlink_rate(0x%02x), phy(%d)\n" + "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n", + handle, (unsigned long long) + mpt2sas_phy->identify.sas_address, link_rate, + phy_number, attached_handle, + (unsigned long long) + mpt2sas_phy->remote_identify.sas_address); +} + +static inline void * +phy_to_ioc(struct sas_phy *phy) +{ + struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); + return shost_priv(shost); +} + +static inline void * +rphy_to_ioc(struct sas_rphy *rphy) +{ + struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); + return shost_priv(shost); +} + +/** + * transport_get_linkerrors - + * @phy: The sas phy object + * + * Only support sas_host direct attached phys. + * Returns 0 for success, non-zero for failure. + * + */ +static int +transport_get_linkerrors(struct sas_phy *phy) +{ + struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy); + struct _sas_phy *mpt2sas_phy; + Mpi2ConfigReply_t mpi_reply; + Mpi2SasPhyPage1_t phy_pg1; + int i; + + for (i = 0, mpt2sas_phy = NULL; i < ioc->sas_hba.num_phys && + !mpt2sas_phy; i++) { + if (ioc->sas_hba.phy[i].phy != phy) + continue; + mpt2sas_phy = &ioc->sas_hba.phy[i]; + } + + if (!mpt2sas_phy) /* this phy not on sas_host */ + return -EINVAL; + + if ((mpt2sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1, + mpt2sas_phy->phy_id))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return -ENXIO; + } + + if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) + printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status" + "(0x%04x), loginfo(0x%08x)\n", ioc->name, + mpt2sas_phy->phy_id, + le16_to_cpu(mpi_reply.IOCStatus), + le32_to_cpu(mpi_reply.IOCLogInfo)); + + phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount); + phy->running_disparity_error_count = + le32_to_cpu(phy_pg1.RunningDisparityErrorCount); + phy->loss_of_dword_sync_count = + le32_to_cpu(phy_pg1.LossDwordSynchCount); + phy->phy_reset_problem_count = + le32_to_cpu(phy_pg1.PhyResetProblemCount); + return 0; +} + +/** + * transport_get_enclosure_identifier - + * @phy: The sas phy object + * + * Obtain the enclosure logical id for an expander. + * Returns 0 for success, non-zero for failure. + */ +static int +transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier) +{ + struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy); + struct _sas_node *sas_expander; + unsigned long flags; + + spin_lock_irqsave(&ioc->sas_node_lock, flags); + sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc, + rphy->identify.sas_address); + spin_unlock_irqrestore(&ioc->sas_node_lock, flags); + + if (!sas_expander) + return -ENXIO; + + *identifier = sas_expander->enclosure_logical_id; + return 0; +} + +/** + * transport_get_bay_identifier - + * @phy: The sas phy object + * + * Returns the slot id for a device that resides inside an enclosure. + */ +static int +transport_get_bay_identifier(struct sas_rphy *rphy) +{ + struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy); + struct _sas_device *sas_device; + unsigned long flags; + + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, + rphy->identify.sas_address); + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + + if (!sas_device) + return -ENXIO; + + return sas_device->slot; +} + +/** + * transport_phy_reset - + * @phy: The sas phy object + * @hard_reset: + * + * Only support sas_host direct attached phys. + * Returns 0 for success, non-zero for failure. + */ +static int +transport_phy_reset(struct sas_phy *phy, int hard_reset) +{ + struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy); + struct _sas_phy *mpt2sas_phy; + Mpi2SasIoUnitControlReply_t mpi_reply; + Mpi2SasIoUnitControlRequest_t mpi_request; + int i; + + for (i = 0, mpt2sas_phy = NULL; i < ioc->sas_hba.num_phys && + !mpt2sas_phy; i++) { + if (ioc->sas_hba.phy[i].phy != phy) + continue; + mpt2sas_phy = &ioc->sas_hba.phy[i]; + } + + if (!mpt2sas_phy) /* this phy not on sas_host */ + return -EINVAL; + + memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t)); + mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; + mpi_request.Operation = hard_reset ? + MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET; + mpi_request.PhyNum = mpt2sas_phy->phy_id; + + if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return -ENXIO; + } + + if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) + printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status" + "(0x%04x), loginfo(0x%08x)\n", ioc->name, + mpt2sas_phy->phy_id, + le16_to_cpu(mpi_reply.IOCStatus), + le32_to_cpu(mpi_reply.IOCLogInfo)); + + return 0; +} + +/** + * transport_smp_handler - transport portal for smp passthru + * @shost: shost object + * @rphy: sas transport rphy object + * @req: + * + * This used primarily for smp_utils. + * Example: + * smp_rep_general /sys/class/bsg/expander-5:0 + */ +static int +transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, + struct request *req) +{ + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + Mpi2SmpPassthroughRequest_t *mpi_request; + Mpi2SmpPassthroughReply_t *mpi_reply; + int rc; + u16 smid; + u32 ioc_state; + unsigned long timeleft; + void *psge; + u32 sgl_flags; + u8 issue_reset = 0; + unsigned long flags; + dma_addr_t dma_addr_in = 0; + dma_addr_t dma_addr_out = 0; + u16 wait_state_count; + struct request *rsp = req->next_rq; + + if (!rsp) { + printk(MPT2SAS_ERR_FMT "%s: the smp response space is " + "missing\n", ioc->name, __func__); + return -EINVAL; + } + + /* do we need to support multiple segments? */ + if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) { + printk(MPT2SAS_ERR_FMT "%s: multiple segments req %u %u, " + "rsp %u %u\n", ioc->name, __func__, req->bio->bi_vcnt, + req->data_len, rsp->bio->bi_vcnt, rsp->data_len); + return -EINVAL; + } + + spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); + if (ioc->ioc_reset_in_progress) { + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n", + __func__, ioc->name); + return -EFAULT; + } + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + + rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex); + if (rc) + return rc; + + if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) { + printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n", ioc->name, + __func__); + rc = -EAGAIN; + goto out; + } + ioc->transport_cmds.status = MPT2_CMD_PENDING; + + wait_state_count = 0; + ioc_state = mpt2sas_base_get_iocstate(ioc, 1); + while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { + if (wait_state_count++ == 10) { + printk(MPT2SAS_ERR_FMT + "%s: failed due to ioc not operational\n", + ioc->name, __func__); + rc = -EFAULT; + goto out; + } + ssleep(1); + ioc_state = mpt2sas_base_get_iocstate(ioc, 1); + printk(MPT2SAS_INFO_FMT "%s: waiting for " + "operational state(count=%d)\n", ioc->name, + __func__, wait_state_count); + } + if (wait_state_count) + printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n", + ioc->name, __func__); + + smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx); + if (!smid) { + printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", + ioc->name, __func__); + rc = -EAGAIN; + goto out; + } + + rc = 0; + mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); + ioc->transport_cmds.smid = smid; + + memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); + mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; + mpi_request->PhysicalPort = 0xFF; + *((u64 *)&mpi_request->SASAddress) = (rphy) ? + cpu_to_le64(rphy->identify.sas_address) : + cpu_to_le64(ioc->sas_hba.sas_address); + mpi_request->RequestDataLength = cpu_to_le16(req->data_len - 4); + psge = &mpi_request->SGL; + + /* WRITE sgel first */ + sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | + MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC); + sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; + dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio), + req->data_len, PCI_DMA_BIDIRECTIONAL); + if (!dma_addr_out) { + mpt2sas_base_free_smid(ioc, le16_to_cpu(smid)); + goto unmap; + } + + ioc->base_add_sg_single(psge, sgl_flags | (req->data_len - 4), + dma_addr_out); + + /* incr sgel */ + psge += ioc->sge_size; + + /* READ sgel last */ + sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | + MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | + MPI2_SGE_FLAGS_END_OF_LIST); + sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; + dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio), + rsp->data_len, PCI_DMA_BIDIRECTIONAL); + if (!dma_addr_in) { + mpt2sas_base_free_smid(ioc, le16_to_cpu(smid)); + goto unmap; + } + + ioc->base_add_sg_single(psge, sgl_flags | (rsp->data_len + 4), + dma_addr_in); + + dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - " + "sending smp request\n", ioc->name, __func__)); + + mpt2sas_base_put_smid_default(ioc, smid, 0 /* VF_ID */); + timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, + 10*HZ); + + if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) { + printk(MPT2SAS_ERR_FMT "%s : timeout\n", + __func__, ioc->name); + _debug_dump_mf(mpi_request, + sizeof(Mpi2SmpPassthroughRequest_t)/4); + if (!(ioc->transport_cmds.status & MPT2_CMD_RESET)) + issue_reset = 1; + goto issue_host_reset; + } + + dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - " + "complete\n", ioc->name, __func__)); + + if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) { + + mpi_reply = ioc->transport_cmds.reply; + + dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT + "%s - reply data transfer size(%d)\n", + ioc->name, __func__, + le16_to_cpu(mpi_reply->ResponseDataLength))); + + memcpy(req->sense, mpi_reply, sizeof(*mpi_reply)); + req->sense_len = sizeof(*mpi_reply); + req->data_len = 0; + rsp->data_len -= mpi_reply->ResponseDataLength; + + } else { + dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT + "%s - no reply\n", ioc->name, __func__)); + rc = -ENXIO; + } + + issue_host_reset: + if (issue_reset) { + mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, + FORCE_BIG_HAMMER); + rc = -ETIMEDOUT; + } + + unmap: + if (dma_addr_out) + pci_unmap_single(ioc->pdev, dma_addr_out, req->data_len, + PCI_DMA_BIDIRECTIONAL); + if (dma_addr_in) + pci_unmap_single(ioc->pdev, dma_addr_in, rsp->data_len, + PCI_DMA_BIDIRECTIONAL); + + out: + ioc->transport_cmds.status = MPT2_CMD_NOT_USED; + mutex_unlock(&ioc->transport_cmds.mutex); + return rc; +} + +struct sas_function_template mpt2sas_transport_functions = { + .get_linkerrors = transport_get_linkerrors, + .get_enclosure_identifier = transport_get_enclosure_identifier, + .get_bay_identifier = transport_get_bay_identifier, + .phy_reset = transport_phy_reset, + .smp_handler = transport_smp_handler, +}; + +struct scsi_transport_template *mpt2sas_transport_template; -- GitLab From 34cd347cec6dba8075ceca06efd4fb0c6574cb75 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Fri, 13 Mar 2009 14:17:16 -0700 Subject: [PATCH 3391/4982] bmac: remove unused variable bp in bmac_misc_intr() From: Pavel Roskin Signed-off-by: David S. Miller --- drivers/net/bmac.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index 1ab58375d06..44d015f70d1 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c @@ -1062,7 +1062,6 @@ static int miscintcount; static irqreturn_t bmac_misc_intr(int irq, void *dev_id) { struct net_device *dev = (struct net_device *) dev_id; - struct bmac_data *bp = netdev_priv(dev); unsigned int status = bmread(dev, STATUS); if (miscintcount++ < 10) { XXDEBUG(("bmac_misc_intr\n")); -- GitLab From 08ec9af1c0622b0858099a8644a33af02dd3019f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 13 Mar 2009 14:22:40 -0700 Subject: [PATCH 3392/4982] xfrm: Fix xfrm_state_find() wrt. wildcard source address. The change to make xfrm_state objects hash on source address broke the case where such source addresses are wildcarded. Fix this by doing a two phase lookup, first with fully specified source address, next using saddr wildcarded. Reported-by: Nicolas Dichtel Signed-off-by: David S. Miller --- net/xfrm/xfrm_state.c | 90 ++++++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 32 deletions(-) diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index e25ff62ab2a..62a5425cc6a 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -748,12 +748,51 @@ static void xfrm_hash_grow_check(struct net *net, int have_hash_collision) schedule_work(&net->xfrm.state_hash_work); } +static void xfrm_state_look_at(struct xfrm_policy *pol, struct xfrm_state *x, + struct flowi *fl, unsigned short family, + xfrm_address_t *daddr, xfrm_address_t *saddr, + struct xfrm_state **best, int *acq_in_progress, + int *error) +{ + /* Resolution logic: + * 1. There is a valid state with matching selector. Done. + * 2. Valid state with inappropriate selector. Skip. + * + * Entering area of "sysdeps". + * + * 3. If state is not valid, selector is temporary, it selects + * only session which triggered previous resolution. Key + * manager will do something to install a state with proper + * selector. + */ + if (x->km.state == XFRM_STATE_VALID) { + if ((x->sel.family && + !xfrm_selector_match(&x->sel, fl, x->sel.family)) || + !security_xfrm_state_pol_flow_match(x, pol, fl)) + return; + + if (!*best || + (*best)->km.dying > x->km.dying || + ((*best)->km.dying == x->km.dying && + (*best)->curlft.add_time < x->curlft.add_time)) + *best = x; + } else if (x->km.state == XFRM_STATE_ACQ) { + *acq_in_progress = 1; + } else if (x->km.state == XFRM_STATE_ERROR || + x->km.state == XFRM_STATE_EXPIRED) { + if (xfrm_selector_match(&x->sel, fl, x->sel.family) && + security_xfrm_state_pol_flow_match(x, pol, fl)) + *error = -ESRCH; + } +} + struct xfrm_state * xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, struct flowi *fl, struct xfrm_tmpl *tmpl, struct xfrm_policy *pol, int *err, unsigned short family) { + static xfrm_address_t saddr_wildcard = { }; struct net *net = xp_net(pol); unsigned int h; struct hlist_node *entry; @@ -773,40 +812,27 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, xfrm_state_addr_check(x, daddr, saddr, family) && tmpl->mode == x->props.mode && tmpl->id.proto == x->id.proto && - (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) { - /* Resolution logic: - 1. There is a valid state with matching selector. - Done. - 2. Valid state with inappropriate selector. Skip. - - Entering area of "sysdeps". - - 3. If state is not valid, selector is temporary, - it selects only session which triggered - previous resolution. Key manager will do - something to install a state with proper - selector. - */ - if (x->km.state == XFRM_STATE_VALID) { - if ((x->sel.family && !xfrm_selector_match(&x->sel, fl, x->sel.family)) || - !security_xfrm_state_pol_flow_match(x, pol, fl)) - continue; - if (!best || - best->km.dying > x->km.dying || - (best->km.dying == x->km.dying && - best->curlft.add_time < x->curlft.add_time)) - best = x; - } else if (x->km.state == XFRM_STATE_ACQ) { - acquire_in_progress = 1; - } else if (x->km.state == XFRM_STATE_ERROR || - x->km.state == XFRM_STATE_EXPIRED) { - if (xfrm_selector_match(&x->sel, fl, x->sel.family) && - security_xfrm_state_pol_flow_match(x, pol, fl)) - error = -ESRCH; - } - } + (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) + xfrm_state_look_at(pol, x, fl, family, daddr, saddr, + &best, &acquire_in_progress, &error); + } + if (best) + goto found; + + h = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, family); + hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { + if (x->props.family == family && + x->props.reqid == tmpl->reqid && + !(x->props.flags & XFRM_STATE_WILDRECV) && + xfrm_state_addr_check(x, daddr, saddr, family) && + tmpl->mode == x->props.mode && + tmpl->id.proto == x->id.proto && + (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) + xfrm_state_look_at(pol, x, fl, family, daddr, saddr, + &best, &acquire_in_progress, &error); } +found: x = best; if (!x && !error && !acquire_in_progress) { if (tmpl->id.spi && -- GitLab From 1c339eb183bb48095feaa46057ac4f4f0603dbf9 Mon Sep 17 00:00:00 2001 From: Scott James Remnant Date: Fri, 13 Mar 2009 14:30:08 -0700 Subject: [PATCH 3393/4982] sbus: Auto-load openprom module when device opened. The openprom module is missing the char-major-10-139 alias that would cause it to be auto-loaded when a device of that type is opened. This patch adds the alias. Signed-off-by: Scott James Remnant Signed-off-by: Tim Gardner Signed-off-by: David S. Miller --- drivers/sbus/char/openprom.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c index 29dc735e1a2..124f660a038 100644 --- a/drivers/sbus/char/openprom.c +++ b/drivers/sbus/char/openprom.c @@ -51,6 +51,7 @@ MODULE_AUTHOR("Thomas K. Dyas (tdyas@noc.rutgers.edu) and Eddie C. Dost (ecd@sk MODULE_DESCRIPTION("OPENPROM Configuration Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION("1.0"); +MODULE_ALIAS_MISCDEV(SUN_OPENPROM_MINOR); /* Private data kept by the driver for each descriptor. */ typedef struct openprom_private_data -- GitLab From 3b289d6e35a1a535c19a5b079f0500526754e650 Mon Sep 17 00:00:00 2001 From: Zhang Le Date: Thu, 12 Mar 2009 18:00:50 +0800 Subject: [PATCH 3394/4982] MIPS: Fix TIF_32BIT undefined problem when seccomp is disabled Signed-off-by: Zhang Le Signed-off-by: Ralf Baechle --- arch/mips/include/asm/seccomp.h | 4 ---- arch/mips/include/asm/thread_info.h | 6 ++++++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/mips/include/asm/seccomp.h b/arch/mips/include/asm/seccomp.h index a6772e9507f..ae6306ebdca 100644 --- a/arch/mips/include/asm/seccomp.h +++ b/arch/mips/include/asm/seccomp.h @@ -15,8 +15,6 @@ */ #ifdef CONFIG_MIPS32_O32 -#define TIF_32BIT TIF_32BIT_REGS - #define __NR_seccomp_read_32 4003 #define __NR_seccomp_write_32 4004 #define __NR_seccomp_exit_32 4001 @@ -24,8 +22,6 @@ #elif defined(CONFIG_MIPS32_N32) -#define TIF_32BIT _TIF_32BIT_ADDR - #define __NR_seccomp_read_32 6000 #define __NR_seccomp_write_32 6001 #define __NR_seccomp_exit_32 6058 diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h index 3f76de73c94..676aa2ae191 100644 --- a/arch/mips/include/asm/thread_info.h +++ b/arch/mips/include/asm/thread_info.h @@ -127,6 +127,12 @@ register struct thread_info *__current_thread_info __asm__("$28"); #define TIF_LOAD_WATCH 25 /* If set, load watch registers */ #define TIF_SYSCALL_TRACE 31 /* syscall trace active */ +#ifdef CONFIG_MIPS32_O32 +#define TIF_32BIT TIF_32BIT_REGS +#elif defined(CONFIG_MIPS32_N32) +#define TIF_32BIT _TIF_32BIT_ADDR +#endif /* CONFIG_MIPS32_O32 */ + #define _TIF_SYSCALL_TRACE (1< Date: Fri, 13 Mar 2009 21:17:57 +0100 Subject: [PATCH 3395/4982] MIPS: Mark Eins: Fix configuration. Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 26 +++++++++---- arch/mips/Makefile | 2 +- .../{emma2rh_defconfig => markeins_defconfig} | 10 ++--- arch/mips/emma/Kconfig | 29 -------------- arch/mips/emma/markeins/platform.c | 39 ++++++++++++++----- 5 files changed, 54 insertions(+), 52 deletions(-) rename arch/mips/configs/{emma2rh_defconfig => markeins_defconfig} (99%) delete mode 100644 arch/mips/emma/Kconfig diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index e61465a18c7..206cb7953b0 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -238,8 +238,12 @@ config MIPS_SIM This option enables support for MIPS Technologies MIPSsim software emulator. -config MACH_EMMA - bool "NEC EMMA series based machines" +config NEC_MARKEINS + bool "NEC EMMA2RH Mark-eins board" + select SOC_EMMA2RH + select HW_HAS_PCI + help + This enables support for the NEC Electronics Mark-eins boards. config MACH_VR41XX bool "NEC VR4100 series based machines" @@ -637,7 +641,6 @@ endchoice source "arch/mips/alchemy/Kconfig" source "arch/mips/basler/excite/Kconfig" -source "arch/mips/emma/Kconfig" source "arch/mips/jazz/Kconfig" source "arch/mips/lasat/Kconfig" source "arch/mips/pmc-sierra/Kconfig" @@ -895,6 +898,18 @@ config MIPS_RM9122 bool select SERIAL_RM9000 +config SOC_EMMA2RH + bool + select CEVT_R4K + select CSRC_R4K + select DMA_NONCOHERENT + select IRQ_CPU + select SWAP_IO_SPACE + select SYS_HAS_CPU_R5500 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + config SOC_PNX833X bool select CEVT_R4K @@ -930,11 +945,6 @@ config SOC_PNX8550 config SWAP_IO_SPACE bool -config EMMA2RH - bool - depends on MARKEINS - default y - config SERIAL_RM9000 bool diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 21b00e95dae..22dab2e1434 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -416,7 +416,7 @@ load-$(CONFIG_PNX8550_STB810) += 0xffffffff80060000 # # Common NEC EMMAXXX # -core-$(CONFIG_SOC_EMMA) += arch/mips/emma/common/ +core-$(CONFIG_SOC_EMMA2RH) += arch/mips/emma/common/ cflags-$(CONFIG_SOC_EMMA2RH) += -I$(srctree)/arch/mips/include/asm/mach-emma2rh # diff --git a/arch/mips/configs/emma2rh_defconfig b/arch/mips/configs/markeins_defconfig similarity index 99% rename from arch/mips/configs/emma2rh_defconfig rename to arch/mips/configs/markeins_defconfig index fea9bc9865a..bad8901f8f3 100644 --- a/arch/mips/configs/emma2rh_defconfig +++ b/arch/mips/configs/markeins_defconfig @@ -35,7 +35,7 @@ CONFIG_ZONE_DMA=y # CONFIG_PNX8550_STB810 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set -CONFIG_MARKEINS=y +CONFIG_NEC_MARKEINS=y # CONFIG_SGI_IP22 is not set # CONFIG_SGI_IP27 is not set # CONFIG_SGI_IP32 is not set @@ -68,7 +68,7 @@ CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y CONFIG_IRQ_CPU=y CONFIG_SWAP_IO_SPACE=y -CONFIG_EMMA2RH=y +CONFIG_SOC_EMMA2RH=y CONFIG_MIPS_L1_CACHE_SHIFT=5 # @@ -574,9 +574,9 @@ CONFIG_MTD_CFI_UTIL=y # # CONFIG_MTD_COMPLEX_MAPPINGS is not set CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_PHYSMAP_START=0x1e000000 -CONFIG_MTD_PHYSMAP_LEN=0x02000000 -CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +CONFIG_MTD_PHYSMAP_START=0x0 +CONFIG_MTD_PHYSMAP_LEN=0x0 +CONFIG_MTD_PHYSMAP_BANKWIDTH=0 # CONFIG_MTD_PLATRAM is not set # diff --git a/arch/mips/emma/Kconfig b/arch/mips/emma/Kconfig deleted file mode 100644 index 9669c72123c..00000000000 --- a/arch/mips/emma/Kconfig +++ /dev/null @@ -1,29 +0,0 @@ -choice - prompt "Machine type" - depends on MACH_EMMA - default NEC_MARKEINS - -config NEC_MARKEINS - bool "NEC EMMA2RH Mark-eins board" - select SOC_EMMA2RH - select HW_HAS_PCI - help - This enables support for the NEC Electronics Mark-eins boards. - -endchoice - -config SOC_EMMA2RH - bool - select SOC_EMMA - select SYS_HAS_CPU_R5500 - select SYS_SUPPORTS_32BIT_KERNEL - select SYS_SUPPORTS_64BIT_KERNEL - -config SOC_EMMA - bool - select CEVT_R4K - select CSRC_R4K - select DMA_NONCOHERENT - select IRQ_CPU - select SWAP_IO_SPACE - select SYS_SUPPORTS_BIG_ENDIAN diff --git a/arch/mips/emma/markeins/platform.c b/arch/mips/emma/markeins/platform.c index 88e87f6b344..d5f47e4f0d1 100644 --- a/arch/mips/emma/markeins/platform.c +++ b/arch/mips/emma/markeins/platform.c @@ -141,13 +141,6 @@ static struct platform_device serial_emma = { }, }; -static struct platform_device *devices[] = { - &i2c_emma_devices[0], - &i2c_emma_devices[1], - &i2c_emma_devices[2], - &serial_emma, -}; - static struct mtd_partition markeins_parts[] = { [0] = { .name = "RootFS", @@ -181,11 +174,39 @@ static struct mtd_partition markeins_parts[] = { }, }; +static struct physmap_flash_data markeins_flash_data = { + .width = 2, + .nr_parts = ARRAY_SIZE(markeins_parts), + .parts = markeins_parts +}; + +static struct resource markeins_flash_resource = { + .start = 0x1e000000, + .end = 0x02000000, + .flags = IORESOURCE_MEM +}; + +static struct platform_device markeins_flash_device = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &markeins_flash_data, + }, + .num_resources = 1, + .resource = &markeins_flash_resource, +}; + +static struct platform_device *devices[] = { + i2c_emma_devices, + i2c_emma_devices + 1, + i2c_emma_devices + 2, + &serial_emma, + &markeins_flash_device, +}; + static int __init platform_devices_setup(void) { - physmap_set_partitions(markeins_parts, ARRAY_SIZE(markeins_parts)); return platform_add_devices(devices, ARRAY_SIZE(devices)); } arch_initcall(platform_devices_setup); - -- GitLab From a390d1f379cf821248b735f43d2e1147ebb8241d Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Fri, 13 Mar 2009 15:41:19 -0700 Subject: [PATCH 3396/4982] phylib: convert state_queue work to delayed_work It closes a race in phy_stop_machine when reprogramming of phy_timer (from phy_state_machine) happens between del_timer_sync and cancel_work_sync. Without this change it could lead to crash if phy_device would be freed after phy_stop_machine (timer would fire and schedule freed work). Signed-off-by: Marcin Slusarz Acked-by: Jean Delvare Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 41 +++++++++++------------------------------ include/linux/phy.h | 3 +-- 2 files changed, 12 insertions(+), 32 deletions(-) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index e4ede6080c9..58b73b08dde 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -414,7 +414,6 @@ EXPORT_SYMBOL(phy_start_aneg); static void phy_change(struct work_struct *work); static void phy_state_machine(struct work_struct *work); -static void phy_timer(unsigned long data); /** * phy_start_machine - start PHY state machine tracking @@ -434,11 +433,8 @@ void phy_start_machine(struct phy_device *phydev, { phydev->adjust_state = handler; - INIT_WORK(&phydev->state_queue, phy_state_machine); - init_timer(&phydev->phy_timer); - phydev->phy_timer.function = &phy_timer; - phydev->phy_timer.data = (unsigned long) phydev; - mod_timer(&phydev->phy_timer, jiffies + HZ); + INIT_DELAYED_WORK(&phydev->state_queue, phy_state_machine); + schedule_delayed_work(&phydev->state_queue, jiffies + HZ); } /** @@ -451,8 +447,7 @@ void phy_start_machine(struct phy_device *phydev, */ void phy_stop_machine(struct phy_device *phydev) { - del_timer_sync(&phydev->phy_timer); - cancel_work_sync(&phydev->state_queue); + cancel_delayed_work_sync(&phydev->state_queue); mutex_lock(&phydev->lock); if (phydev->state > PHY_UP) @@ -680,11 +675,9 @@ static void phy_change(struct work_struct *work) if (err) goto irq_enable_err; - /* Stop timer and run the state queue now. The work function for - * state_queue will start the timer up again. - */ - del_timer(&phydev->phy_timer); - schedule_work(&phydev->state_queue); + /* reschedule state queue work to run as soon as possible */ + cancel_delayed_work_sync(&phydev->state_queue); + schedule_delayed_work(&phydev->state_queue, 0); return; @@ -761,14 +754,13 @@ EXPORT_SYMBOL(phy_start); /** * phy_state_machine - Handle the state machine * @work: work_struct that describes the work to be done - * - * Description: Scheduled by the state_queue workqueue each time - * phy_timer is triggered. */ static void phy_state_machine(struct work_struct *work) { + struct delayed_work *dwork = + container_of(work, struct delayed_work, work); struct phy_device *phydev = - container_of(work, struct phy_device, state_queue); + container_of(dwork, struct phy_device, state_queue); int needs_aneg = 0; int err = 0; @@ -946,17 +938,6 @@ static void phy_state_machine(struct work_struct *work) if (err < 0) phy_error(phydev); - mod_timer(&phydev->phy_timer, jiffies + PHY_STATE_TIME * HZ); -} - -/* PHY timer which schedules the state machine work */ -static void phy_timer(unsigned long data) -{ - struct phy_device *phydev = (struct phy_device *)data; - - /* - * PHY I/O operations can potentially sleep so we ensure that - * it's done from a process context - */ - schedule_work(&phydev->state_queue); + schedule_delayed_work(&phydev->state_queue, + jiffies + PHY_STATE_TIME * HZ); } diff --git a/include/linux/phy.h b/include/linux/phy.h index d7e54d98869..32cf14a4b03 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -315,8 +315,7 @@ struct phy_device { /* Interrupt and Polling infrastructure */ struct work_struct phy_queue; - struct work_struct state_queue; - struct timer_list phy_timer; + struct delayed_work state_queue; atomic_t irq_disable; struct mutex lock; -- GitLab From 1f8ae0a21d83f43006d7f6d2862e921dbf2eeddd Mon Sep 17 00:00:00 2001 From: Tomasz Lemiech Date: Fri, 13 Mar 2009 15:43:38 -0700 Subject: [PATCH 3397/4982] tulip: Fix for MTU problems with 802.1q tagged frames The original patch was submitted last year but wasn't discussed or applied because of missing maintainer's CCs. I only fixed some formatting errors, but as I saw tulip is very badly formatted and needs further work. Original description: This patch fixes MTU problem, which occurs when using 802.1q VLANs. We should allow receiving frames of up to 1518 bytes in length, instead of 1514. Based on patch written by Ben McKeegan for 2.4.x kernels. It is archived at http://www.candelatech.com/~greear/vlan/howto.html#tulip I've adjusted a few things to make it apply on 2.6.x kernels. Tested on D-Link DFE-570TX quad-fastethernet card. Signed-off-by: Tomasz Lemiech Signed-off-by: Ivan Vecera Signed-off-by: Ben McKeegan Acked-by: Grant Grundler Signed-off-by: David S. Miller --- drivers/net/tulip/interrupt.c | 84 +++++++++++++++++++++++------------ drivers/net/tulip/tulip.h | 32 ++++++++++++- 2 files changed, 86 insertions(+), 30 deletions(-) diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c index 9f946d42108..c8d220cf2cc 100644 --- a/drivers/net/tulip/interrupt.c +++ b/drivers/net/tulip/interrupt.c @@ -140,6 +140,7 @@ int tulip_poll(struct napi_struct *napi, int budget) /* If we own the next entry, it is a new packet. Send it up. */ while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) { s32 status = le32_to_cpu(tp->rx_ring[entry].status); + short pkt_len; if (tp->dirty_rx + RX_RING_SIZE == tp->cur_rx) break; @@ -151,8 +152,28 @@ int tulip_poll(struct napi_struct *napi, int budget) if (++work_done >= budget) goto not_done; - if ((status & 0x38008300) != 0x0300) { - if ((status & 0x38000300) != 0x0300) { + /* + * Omit the four octet CRC from the length. + * (May not be considered valid until we have + * checked status for RxLengthOver2047 bits) + */ + pkt_len = ((status >> 16) & 0x7ff) - 4; + + /* + * Maximum pkt_len is 1518 (1514 + vlan header) + * Anything higher than this is always invalid + * regardless of RxLengthOver2047 bits + */ + + if ((status & (RxLengthOver2047 | + RxDescCRCError | + RxDescCollisionSeen | + RxDescRunt | + RxDescDescErr | + RxWholePkt)) != RxWholePkt + || pkt_len > 1518) { + if ((status & (RxLengthOver2047 | + RxWholePkt)) != RxWholePkt) { /* Ingore earlier buffers. */ if ((status & 0xffff) != 0x7fff) { if (tulip_debug > 1) @@ -161,30 +182,23 @@ int tulip_poll(struct napi_struct *napi, int budget) dev->name, status); tp->stats.rx_length_errors++; } - } else if (status & RxDescFatalErr) { + } else { /* There was a fatal error. */ if (tulip_debug > 2) printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n", dev->name, status); tp->stats.rx_errors++; /* end of a packet.*/ - if (status & 0x0890) tp->stats.rx_length_errors++; + if (pkt_len > 1518 || + (status & RxDescRunt)) + tp->stats.rx_length_errors++; + if (status & 0x0004) tp->stats.rx_frame_errors++; if (status & 0x0002) tp->stats.rx_crc_errors++; if (status & 0x0001) tp->stats.rx_fifo_errors++; } } else { - /* Omit the four octet CRC from the length. */ - short pkt_len = ((status >> 16) & 0x7ff) - 4; struct sk_buff *skb; -#ifndef final_version - if (pkt_len > 1518) { - printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n", - dev->name, pkt_len, pkt_len); - pkt_len = 1518; - tp->stats.rx_length_errors++; - } -#endif /* Check if the packet is long enough to accept without copying to a minimally-sized skbuff. */ if (pkt_len < tulip_rx_copybreak @@ -356,14 +370,35 @@ static int tulip_rx(struct net_device *dev) /* If we own the next entry, it is a new packet. Send it up. */ while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) { s32 status = le32_to_cpu(tp->rx_ring[entry].status); + short pkt_len; if (tulip_debug > 5) printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %8.8x.\n", dev->name, entry, status); if (--rx_work_limit < 0) break; - if ((status & 0x38008300) != 0x0300) { - if ((status & 0x38000300) != 0x0300) { + + /* + Omit the four octet CRC from the length. + (May not be considered valid until we have + checked status for RxLengthOver2047 bits) + */ + pkt_len = ((status >> 16) & 0x7ff) - 4; + /* + Maximum pkt_len is 1518 (1514 + vlan header) + Anything higher than this is always invalid + regardless of RxLengthOver2047 bits + */ + + if ((status & (RxLengthOver2047 | + RxDescCRCError | + RxDescCollisionSeen | + RxDescRunt | + RxDescDescErr | + RxWholePkt)) != RxWholePkt + || pkt_len > 1518) { + if ((status & (RxLengthOver2047 | + RxWholePkt)) != RxWholePkt) { /* Ingore earlier buffers. */ if ((status & 0xffff) != 0x7fff) { if (tulip_debug > 1) @@ -372,31 +407,22 @@ static int tulip_rx(struct net_device *dev) dev->name, status); tp->stats.rx_length_errors++; } - } else if (status & RxDescFatalErr) { + } else { /* There was a fatal error. */ if (tulip_debug > 2) printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n", dev->name, status); tp->stats.rx_errors++; /* end of a packet.*/ - if (status & 0x0890) tp->stats.rx_length_errors++; + if (pkt_len > 1518 || + (status & RxDescRunt)) + tp->stats.rx_length_errors++; if (status & 0x0004) tp->stats.rx_frame_errors++; if (status & 0x0002) tp->stats.rx_crc_errors++; if (status & 0x0001) tp->stats.rx_fifo_errors++; } } else { - /* Omit the four octet CRC from the length. */ - short pkt_len = ((status >> 16) & 0x7ff) - 4; struct sk_buff *skb; -#ifndef final_version - if (pkt_len > 1518) { - printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n", - dev->name, pkt_len, pkt_len); - pkt_len = 1518; - tp->stats.rx_length_errors++; - } -#endif - /* Check if the packet is long enough to accept without copying to a minimally-sized skbuff. */ if (pkt_len < tulip_rx_copybreak diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h index 19abbc36b60..0afa2d4f947 100644 --- a/drivers/net/tulip/tulip.h +++ b/drivers/net/tulip/tulip.h @@ -201,8 +201,38 @@ enum desc_status_bits { DescStartPkt = 0x20000000, DescEndRing = 0x02000000, DescUseLink = 0x01000000, - RxDescFatalErr = 0x008000, + + /* + * Error summary flag is logical or of 'CRC Error', 'Collision Seen', + * 'Frame Too Long', 'Runt' and 'Descriptor Error' flags generated + * within tulip chip. + */ + RxDescErrorSummary = 0x8000, + RxDescCRCError = 0x0002, + RxDescCollisionSeen = 0x0040, + + /* + * 'Frame Too Long' flag is set if packet length including CRC exceeds + * 1518. However, a full sized VLAN tagged frame is 1522 bytes + * including CRC. + * + * The tulip chip does not block oversized frames, and if this flag is + * set on a receive descriptor it does not indicate the frame has been + * truncated. The receive descriptor also includes the actual length. + * Therefore we can safety ignore this flag and check the length + * ourselves. + */ + RxDescFrameTooLong = 0x0080, + RxDescRunt = 0x0800, + RxDescDescErr = 0x4000, RxWholePkt = 0x00000300, + /* + * Top three bits of 14 bit frame length (status bits 27-29) should + * never be set as that would make frame over 2047 bytes. The Receive + * Watchdog flag (bit 4) may indicate the length is over 2048 and the + * length field is invalid. + */ + RxLengthOver2047 = 0x38000010 }; -- GitLab From 5a89392225c6147d10328a64b06b756561e97edf Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 13 Mar 2009 15:48:02 -0700 Subject: [PATCH 3398/4982] mv643xx_eth: fix unicast address filter corruption on mtu change When mv643xx_eth_open() is called to up an interface, port_start() will first re-program the unicast address filter, and then re-initialise the PORT_CONFIG register, but that will disable unicast promiscuous mode if it was enabled by the unicast address filter setup. This isn't a problem on ifconfig up, as ->set_rx_mode() will be called shortly afterwards which will program the filters again, but it does trigger when changing the MTU, which calls mv643xx_eth_stop() and then mv643xx_eth_open() by hand to repopulate the receive rings with skbuffs of the new size. Swap the initialisation of the PORT_START register and the call to the unicast filter setup function to fix this. Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller --- drivers/net/mv643xx_eth.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 13f11f402a9..b0bc3bc18e9 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -2029,11 +2029,6 @@ static void port_start(struct mv643xx_eth_private *mp) txq_set_fixed_prio_mode(txq); } - /* - * Add configured unicast address to address filter table. - */ - mv643xx_eth_program_unicast_filter(mp->dev); - /* * Receive all unmatched unicast, TCP, UDP, BPDU and broadcast * frames to RX queue #0, and include the pseudo-header when @@ -2046,6 +2041,11 @@ static void port_start(struct mv643xx_eth_private *mp) */ wrlp(mp, PORT_CONFIG_EXT, 0x00000000); + /* + * Add configured unicast addresses to address filter table. + */ + mv643xx_eth_program_unicast_filter(mp->dev); + /* * Enable the receive queues. */ -- GitLab From 73ce7b01b4496a5fbf9caf63033c874be692333f Mon Sep 17 00:00:00 2001 From: Denys Fedoryshchenko Date: Fri, 13 Mar 2009 16:02:07 -0700 Subject: [PATCH 3399/4982] ipv4: arp announce, arp_proxy and windows ip conflict verification Windows (XP at least) hosts on boot, with configured static ip, performing address conflict detection, which is defined in RFC3927. Here is quote of important information: " An ARP announcement is identical to the ARP Probe described above, except that now the sender and target IP addresses are both set to the host's newly selected IPv4 address. " But it same time this goes wrong with RFC5227. " The 'sender IP address' field MUST be set to all zeroes; this is to avoid polluting ARP caches in other hosts on the same link in the case where the address turns out to be already in use by another host. " When ARP proxy configured, it must not answer to both cases, because it is address conflict verification in any case. For Windows it is just causing to detect false "ip conflict". Already there is code for RFC5227, so just trivially we just check also if source ip == target ip. Signed-off-by: Denys Fedoryshchenko Signed-off-by: David S. Miller --- net/ipv4/arp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 9c220323f35..f11931c1838 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -801,8 +801,11 @@ static int arp_process(struct sk_buff *skb) * cache. */ - /* Special case: IPv4 duplicate address detection packet (RFC2131) */ - if (sip == 0) { + /* + * Special case: IPv4 duplicate address detection packet (RFC2131) + * and Gratuitous ARP/ARP Announce. (RFC3927, Section 2.4) + */ + if (sip == 0 || tip == sip) { if (arp->ar_op == htons(ARPOP_REQUEST) && inet_addr_type(net, tip) == RTN_LOCAL && !arp_ignore(in_dev, sip, tip)) -- GitLab From 8db09f26f912f7c90c764806e804b558da520d4f Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Fri, 13 Mar 2009 16:04:12 -0700 Subject: [PATCH 3400/4982] x25: '< 0' and '>= 0' test on unsigned skb->len is an unsigned int, so the test in x25_rx_call_request() always evaluates to true. len in x25_sendmsg() is unsigned as well. so -ERRORS returned by x25_output() are not noticed. Signed-off-by: Roel Kluin Signed-off-by: David S. Miller --- net/x25/af_x25.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 1000e9a26fd..9ca17b1ce52 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -951,10 +951,8 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, /* * Incoming Call User Data. */ - if (skb->len >= 0) { - skb_copy_from_linear_data(skb, makex25->calluserdata.cuddata, skb->len); - makex25->calluserdata.cudlength = skb->len; - } + skb_copy_from_linear_data(skb, makex25->calluserdata.cuddata, skb->len); + makex25->calluserdata.cudlength = skb->len; sk->sk_ack_backlog++; @@ -1122,8 +1120,9 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock, if (msg->msg_flags & MSG_OOB) skb_queue_tail(&x25->interrupt_out_queue, skb); else { - len = x25_output(sk, skb); - if (len < 0) + rc = x25_output(sk, skb); + len = rc; + if (rc < 0) kfree_skb(skb); else if (x25->qbitincl) len++; -- GitLab From a2025b8b1039e5abaa38319b2eaab3b17867479a Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Fri, 13 Mar 2009 16:05:14 -0700 Subject: [PATCH 3401/4982] tcp: '< 0' test on unsigned promote 'cnt' to size_t, to match 'len'. Signed-off-by: Roel Kluin Signed-off-by: David S. Miller --- net/ipv4/tcp_probe.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c index 25524d4e372..59f5b5e7c56 100644 --- a/net/ipv4/tcp_probe.c +++ b/net/ipv4/tcp_probe.c @@ -165,9 +165,10 @@ static int tcpprobe_sprint(char *tbuf, int n) static ssize_t tcpprobe_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) { - int error = 0, cnt = 0; + int error = 0; + size_t cnt = 0; - if (!buf || len < 0) + if (!buf) return -EINVAL; while (cnt < len) { -- GitLab From 9c705260feea6ae329bc6b6d5f6d2ef0227eda0a Mon Sep 17 00:00:00 2001 From: Gabriele Paoloni Date: Fri, 13 Mar 2009 16:09:12 -0700 Subject: [PATCH 3402/4982] ppp: ppp_mp_explode() redesign I found the PPP subsystem to not work properly when connecting channels with different speeds to the same bundle. Problem Description: As the "ppp_mp_explode" function fragments the sk_buff buffer evenly among the PPP channels that are connected to a certain PPP unit to make up a bundle, if we are transmitting using an upper layer protocol that requires an Ack before sending the next packet (like TCP/IP for example), we will have a bandwidth bottleneck on the slowest channel of the bundle. Let's clarify by an example. Let's consider a scenario where we have two PPP links making up a bundle: a slow link (10KB/sec) and a fast link (1000KB/sec) working at the best (full bandwidth). On the top we have a TCP/IP stack sending a 1000 Bytes sk_buff buffer down to the PPP subsystem. The "ppp_mp_explode" function will divide the buffer in two fragments of 500B each (we are neglecting all the headers, crc, flags etc?.). Before the TCP/IP stack sends out the next buffer, it will have to wait for the ACK response from the remote peer, so it will have to wait for both fragments to have been sent over the two PPP links, received by the remote peer and reconstructed. The resulting behaviour is that, rather than having a bundle working @1010KB/sec (the sum of the channels bandwidths), we'll have a bundle working @20KB/sec (the double of the slowest channels bandwidth). Problem Solution: The problem has been solved by redesigning the "ppp_mp_explode" function in such a way to make it split the sk_buff buffer according to the speeds of the underlying PPP channels (the speeds of the serial interfaces respectively attached to the PPP channels). Referring to the above example, the redesigned "ppp_mp_explode" function will now divide the 1000 Bytes buffer into two fragments whose sizes are set according to the speeds of the channels where they are going to be sent on (e.g . 10 Byets on 10KB/sec channel and 990 Bytes on 1000KB/sec channel). The reworked function grants the same performances of the original one in optimal working conditions (i.e. a bundle made up of PPP links all working at the same speed), while greatly improving performances on the bundles made up of channels working at different speeds. Signed-off-by: Gabriele Paoloni Signed-off-by: David S. Miller --- drivers/net/ppp_async.c | 3 + drivers/net/ppp_generic.c | 211 ++++++++++++++++++++---------------- drivers/net/ppp_synctty.c | 3 + include/linux/ppp_channel.h | 2 +- 4 files changed, 127 insertions(+), 92 deletions(-) diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c index 5de6fedd1d7..6de8399d6dd 100644 --- a/drivers/net/ppp_async.c +++ b/drivers/net/ppp_async.c @@ -157,6 +157,7 @@ ppp_asynctty_open(struct tty_struct *tty) { struct asyncppp *ap; int err; + int speed; if (tty->ops->write == NULL) return -EOPNOTSUPP; @@ -187,6 +188,8 @@ ppp_asynctty_open(struct tty_struct *tty) ap->chan.private = ap; ap->chan.ops = &async_ops; ap->chan.mtu = PPP_MRU; + speed = tty_get_baud_rate(tty); + ap->chan.speed = speed; err = ppp_register_channel(&ap->chan); if (err) goto out_free; diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 42d45557845..8ee91421db1 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -167,6 +167,7 @@ struct channel { u8 avail; /* flag used in multilink stuff */ u8 had_frag; /* >= 1 fragments have been sent */ u32 lastseq; /* MP: last sequence # received */ + int speed; /* speed of the corresponding ppp channel*/ #endif /* CONFIG_PPP_MULTILINK */ }; @@ -1307,138 +1308,181 @@ ppp_push(struct ppp *ppp) */ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) { - int len, fragsize; - int i, bits, hdrlen, mtu; - int flen; - int navail, nfree; - int nbigger; + int len, totlen; + int i, bits, hdrlen, mtu; + int flen; + int navail, nfree, nzero; + int nbigger; + int totspeed; + int totfree; unsigned char *p, *q; struct list_head *list; struct channel *pch; struct sk_buff *frag; struct ppp_channel *chan; - nfree = 0; /* # channels which have no packet already queued */ + totspeed = 0; /*total bitrate of the bundle*/ + nfree = 0; /* # channels which have no packet already queued */ navail = 0; /* total # of usable channels (not deregistered) */ + nzero = 0; /* number of channels with zero speed associated*/ + totfree = 0; /*total # of channels available and + *having no queued packets before + *starting the fragmentation*/ + hdrlen = (ppp->flags & SC_MP_XSHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN; - i = 0; - list_for_each_entry(pch, &ppp->channels, clist) { + i = 0; + list_for_each_entry(pch, &ppp->channels, clist) { navail += pch->avail = (pch->chan != NULL); - if (pch->avail) { + pch->speed = pch->chan->speed; + if (pch->avail) { if (skb_queue_empty(&pch->file.xq) || - !pch->had_frag) { - pch->avail = 2; - ++nfree; - } - if (!pch->had_frag && i < ppp->nxchan) - ppp->nxchan = i; + !pch->had_frag) { + if (pch->speed == 0) + nzero++; + else + totspeed += pch->speed; + + pch->avail = 2; + ++nfree; + ++totfree; + } + if (!pch->had_frag && i < ppp->nxchan) + ppp->nxchan = i; } ++i; } - /* - * Don't start sending this packet unless at least half of - * the channels are free. This gives much better TCP - * performance if we have a lot of channels. + * Don't start sending this packet unless at least half of + * the channels are free. This gives much better TCP + * performance if we have a lot of channels. */ - if (nfree == 0 || nfree < navail / 2) - return 0; /* can't take now, leave it in xmit_pending */ + if (nfree == 0 || nfree < navail / 2) + return 0; /* can't take now, leave it in xmit_pending */ /* Do protocol field compression (XXX this should be optional) */ - p = skb->data; - len = skb->len; + p = skb->data; + len = skb->len; if (*p == 0) { ++p; --len; } - /* - * Decide on fragment size. - * We create a fragment for each free channel regardless of - * how small they are (i.e. even 0 length) in order to minimize - * the time that it will take to detect when a channel drops - * a fragment. - */ - fragsize = len; - if (nfree > 1) - fragsize = DIV_ROUND_UP(fragsize, nfree); - /* nbigger channels get fragsize bytes, the rest get fragsize-1, - except if nbigger==0, then they all get fragsize. */ - nbigger = len % nfree; - - /* skip to the channel after the one we last used - and start at that one */ + totlen = len; + nbigger = len % nfree; + + /* skip to the channel after the one we last used + and start at that one */ list = &ppp->channels; - for (i = 0; i < ppp->nxchan; ++i) { + for (i = 0; i < ppp->nxchan; ++i) { list = list->next; - if (list == &ppp->channels) { - i = 0; + if (list == &ppp->channels) { + i = 0; break; } } - /* create a fragment for each channel */ + /* create a fragment for each channel */ bits = B; - while (nfree > 0 || len > 0) { + while (nfree > 0 && len > 0) { list = list->next; - if (list == &ppp->channels) { - i = 0; + if (list == &ppp->channels) { + i = 0; continue; } - pch = list_entry(list, struct channel, clist); + pch = list_entry(list, struct channel, clist); ++i; if (!pch->avail) continue; /* - * Skip this channel if it has a fragment pending already and - * we haven't given a fragment to all of the free channels. + * Skip this channel if it has a fragment pending already and + * we haven't given a fragment to all of the free channels. */ if (pch->avail == 1) { - if (nfree > 0) + if (nfree > 0) continue; } else { - --nfree; pch->avail = 1; } /* check the channel's mtu and whether it is still attached. */ spin_lock_bh(&pch->downl); if (pch->chan == NULL) { - /* can't use this channel, it's being deregistered */ + /* can't use this channel, it's being deregistered */ + if (pch->speed == 0) + nzero--; + else + totspeed -= pch->speed; + spin_unlock_bh(&pch->downl); pch->avail = 0; - if (--navail == 0) + totlen = len; + totfree--; + nfree--; + if (--navail == 0) break; continue; } /* - * Create a fragment for this channel of - * min(max(mtu+2-hdrlen, 4), fragsize, len) bytes. - * If mtu+2-hdrlen < 4, that is a ridiculously small - * MTU, so we use mtu = 2 + hdrlen. + *if the channel speed is not set divide + *the packet evenly among the free channels; + *otherwise divide it according to the speed + *of the channel we are going to transmit on + */ + if (pch->speed == 0) { + flen = totlen/nfree ; + if (nbigger > 0) { + flen++; + nbigger--; + } + } else { + flen = (((totfree - nzero)*(totlen + hdrlen*totfree)) / + ((totspeed*totfree)/pch->speed)) - hdrlen; + if (nbigger > 0) { + flen += ((totfree - nzero)*pch->speed)/totspeed; + nbigger -= ((totfree - nzero)*pch->speed)/ + totspeed; + } + } + nfree--; + + /* + *check if we are on the last channel or + *we exceded the lenght of the data to + *fragment + */ + if ((nfree == 0) || (flen > len)) + flen = len; + /* + *it is not worth to tx on slow channels: + *in that case from the resulting flen according to the + *above formula will be equal or less than zero. + *Skip the channel in this case */ - if (fragsize > len) - fragsize = len; - flen = fragsize; - mtu = pch->chan->mtu + 2 - hdrlen; - if (mtu < 4) - mtu = 4; + if (flen <= 0) { + pch->avail = 2; + spin_unlock_bh(&pch->downl); + continue; + } + + mtu = pch->chan->mtu + 2 - hdrlen; + if (mtu < 4) + mtu = 4; if (flen > mtu) flen = mtu; - if (flen == len && nfree == 0) - bits |= E; - frag = alloc_skb(flen + hdrlen + (flen == 0), GFP_ATOMIC); + if (flen == len) + bits |= E; + frag = alloc_skb(flen + hdrlen + (flen == 0), GFP_ATOMIC); if (!frag) goto noskb; - q = skb_put(frag, flen + hdrlen); + q = skb_put(frag, flen + hdrlen); - /* make the MP header */ + /* make the MP header */ q[0] = PPP_MP >> 8; q[1] = PPP_MP; if (ppp->flags & SC_MP_XSHORTSEQ) { - q[2] = bits + ((ppp->nxseq >> 8) & 0xf); + q[2] = bits + ((ppp->nxseq >> 8) & 0xf); q[3] = ppp->nxseq; } else { q[2] = bits; @@ -1447,43 +1491,28 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) q[5] = ppp->nxseq; } - /* - * Copy the data in. - * Unfortunately there is a bug in older versions of - * the Linux PPP multilink reconstruction code where it - * drops 0-length fragments. Therefore we make sure the - * fragment has at least one byte of data. Any bytes - * we add in this situation will end up as padding on the - * end of the reconstructed packet. - */ - if (flen == 0) - *skb_put(frag, 1) = 0; - else - memcpy(q + hdrlen, p, flen); + memcpy(q + hdrlen, p, flen); /* try to send it down the channel */ chan = pch->chan; - if (!skb_queue_empty(&pch->file.xq) || - !chan->ops->start_xmit(chan, frag)) + if (!skb_queue_empty(&pch->file.xq) || + !chan->ops->start_xmit(chan, frag)) skb_queue_tail(&pch->file.xq, frag); - pch->had_frag = 1; + pch->had_frag = 1; p += flen; - len -= flen; + len -= flen; ++ppp->nxseq; bits = 0; spin_unlock_bh(&pch->downl); - - if (--nbigger == 0 && fragsize > 0) - --fragsize; } - ppp->nxchan = i; + ppp->nxchan = i; return 1; noskb: spin_unlock_bh(&pch->downl); if (ppp->debug & 1) - printk(KERN_ERR "PPP: no memory (fragment)\n"); + printk(KERN_ERR "PPP: no memory (fragment)\n"); ++ppp->dev->stats.tx_errors; ++ppp->nxseq; return 1; /* abandon the frame */ diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c index 3ea791d16b0..d2fa2db1358 100644 --- a/drivers/net/ppp_synctty.c +++ b/drivers/net/ppp_synctty.c @@ -206,6 +206,7 @@ ppp_sync_open(struct tty_struct *tty) { struct syncppp *ap; int err; + int speed; if (tty->ops->write == NULL) return -EOPNOTSUPP; @@ -234,6 +235,8 @@ ppp_sync_open(struct tty_struct *tty) ap->chan.ops = &sync_ops; ap->chan.mtu = PPP_MRU; ap->chan.hdrlen = 2; /* for A/C bytes */ + speed = tty_get_baud_rate(tty); + ap->chan.speed = speed; err = ppp_register_channel(&ap->chan); if (err) goto out_free; diff --git a/include/linux/ppp_channel.h b/include/linux/ppp_channel.h index 9d64bdf1477..0d3fa63e90e 100644 --- a/include/linux/ppp_channel.h +++ b/include/linux/ppp_channel.h @@ -40,8 +40,8 @@ struct ppp_channel { int mtu; /* max transmit packet size */ int hdrlen; /* amount of headroom channel needs */ void *ppp; /* opaque to channel */ - /* the following are not used at present */ int speed; /* transfer rate (bytes/second) */ + /* the following is not used at present */ int latency; /* overhead time in milliseconds */ }; -- GitLab From 0ce36c5f7f87632f26c8fbefe68b5116eda152d2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 13 Mar 2009 14:26:08 +0000 Subject: [PATCH 3403/4982] ASoC: Fix non-networked I2S mode for PXA SSP Two issues are fixed here: - I2S transmits the left frame with the clock low but I don't seem to get LRCLK out without SFRMDLY being set so invert SFRMP and set a delay. - I2S has a clock cycle prior to the first data byte in each channel so we need to delay the data by one cycle. Tested-by: Daniel Mack Signed-off-by: Mark Brown --- sound/soc/pxa/pxa-ssp.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 4dd0d7c5722..b0bf40973d5 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -1,4 +1,3 @@ -#define DEBUG /* * pxa-ssp.c -- ALSA Soc Audio Layer * @@ -561,14 +560,15 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, sscr0 |= SSCR0_PSP; sscr1 |= SSCR1_RWOT | SSCR1_TRAIL; + /* See hw_params() */ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: + sspsp |= SSPSP_SFRMP; break; case SND_SOC_DAIFMT_NB_IF: - sspsp |= SSPSP_SFRMP; break; case SND_SOC_DAIFMT_IB_IF: - sspsp |= SSPSP_SFRMP | SSPSP_SCMODE(3); + sspsp |= SSPSP_SCMODE(3); break; default: return -EINVAL; @@ -691,8 +691,17 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, #else return -EINVAL; #endif - } else - sspsp |= SSPSP_SFRMWDTH(width); + } else { + /* The frame width is the width the LRCLK is + * asserted for; the delay is expressed in + * half cycle units. We need the extra cycle + * because the data starts clocking out one BCLK + * after LRCLK changes polarity. + */ + sspsp |= SSPSP_SFRMWDTH(width + 1); + sspsp |= SSPSP_SFRMDLY((width + 1) * 2); + sspsp |= SSPSP_DMYSTRT(1); + } ssp_write_reg(ssp, SSPSP, sspsp); break; -- GitLab From 85fab7802a4bc00cc752f430e22a0d9fc41fe199 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 13 Mar 2009 14:27:08 +0000 Subject: [PATCH 3404/4982] ASoC: Fix Zylonite for non-networked SSP mode This also simplifies the code a bit. Signed-off-by: Mark Brown --- sound/soc/pxa/zylonite.c | 55 ++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index 9f6116edbb8..9a386b4c4ed 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c @@ -96,42 +96,35 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; unsigned int pll_out = 0; - unsigned int acds = 0; unsigned int wm9713_div = 0; int ret = 0; - - switch (params_rate(params)) { + int rate = params_rate(params); + int width = snd_pcm_format_physical_width(params_format(params)); + + /* Only support ratios that we can generate neatly from the AC97 + * based master clock - in particular, this excludes 44.1kHz. + * In most applications the voice DAC will be used for telephony + * data so multiples of 8kHz will be the common case. + */ + switch (rate) { case 8000: wm9713_div = 12; - pll_out = 2048000; break; case 16000: wm9713_div = 6; - pll_out = 4096000; break; case 48000: - default: wm9713_div = 2; - pll_out = 12288000; - acds = 1; break; + default: + /* Don't support OSS emulation */ + return -EINVAL; } - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - if (ret < 0) - return ret; - - ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - if (ret < 0) - return ret; + /* Add 1 to the width for the leading clock cycle */ + pll_out = rate * (width + 1) * 8; - /* Use network mode for stereo, one slot per channel. */ - if (params_channels(params) > 1) - ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 2); - else - ret = snd_soc_dai_set_tdm_slot(cpu_dai, 1, 1); + ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0, 1); if (ret < 0) return ret; @@ -139,14 +132,6 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_AUDIO_DIV_ACDS, acds); - if (ret < 0) - return ret; - - ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0, 1); - if (ret < 0) - return ret; - if (clk_pout) ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_PLL_DIV, WM9713_PCMDIV(wm9713_div)); @@ -156,6 +141,16 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + if (ret < 0) + return ret; + + ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + if (ret < 0) + return ret; + return 0; } -- GitLab From 0da205e01bc58cfad660659e3c901223d3596c57 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 12 Mar 2009 14:20:29 -0400 Subject: [PATCH 3405/4982] [SCSI] sd: Refactor sd_read_capacity() The sd_read_capacity() function was about 180 lines long and included a backwards goto and a tricky state variable. Splitting out read_capacity_10() and read_capacity_16() (about 50 lines each) reduces sd_read_capacity to about 100 lines and gets rid of the backwards goto and the state variable. I've tried to avoid any behaviour change with this patch. [jejb: upped transfer request to standard recommended 32 for RC16] Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 241 +++++++++++++++++++++++++++++----------------- 1 file changed, 155 insertions(+), 86 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index e744ee40be6..dcff84abcde 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1273,42 +1273,61 @@ disable: sdkp->capacity = 0; } -/* - * read disk capacity - */ -static void -sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer) +static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp, + struct scsi_sense_hdr *sshdr, int sense_valid, + int the_result) +{ + sd_print_result(sdkp, the_result); + if (driver_byte(the_result) & DRIVER_SENSE) + sd_print_sense_hdr(sdkp, sshdr); + else + sd_printk(KERN_NOTICE, sdkp, "Sense not available.\n"); + + /* + * Set dirty bit for removable devices if not ready - + * sometimes drives will not report this properly. + */ + if (sdp->removable && + sense_valid && sshdr->sense_key == NOT_READY) + sdp->changed = 1; + + /* + * We used to set media_present to 0 here to indicate no media + * in the drive, but some drives fail read capacity even with + * media present, so we can't do that. + */ + sdkp->capacity = 0; /* unknown mapped to zero - as usual */ +} + +#define RC16_LEN 32 +#if RC16_LEN > SD_BUF_SIZE +#error RC16_LEN must not be more than SD_BUF_SIZE +#endif + +static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, + unsigned char *buffer) { unsigned char cmd[16]; - int the_result, retries; - int sector_size = 0; - /* Force READ CAPACITY(16) when PROTECT=1 */ - int longrc = scsi_device_protection(sdkp->device) ? 1 : 0; struct scsi_sense_hdr sshdr; int sense_valid = 0; - struct scsi_device *sdp = sdkp->device; + int the_result; + int retries = 3; + unsigned long long lba; + unsigned sector_size; -repeat: - retries = 3; do { - if (longrc) { - memset((void *) cmd, 0, 16); - cmd[0] = SERVICE_ACTION_IN; - cmd[1] = SAI_READ_CAPACITY_16; - cmd[13] = 13; - memset((void *) buffer, 0, 13); - } else { - cmd[0] = READ_CAPACITY; - memset((void *) &cmd[1], 0, 9); - memset((void *) buffer, 0, 8); - } - + memset(cmd, 0, 16); + cmd[0] = SERVICE_ACTION_IN; + cmd[1] = SAI_READ_CAPACITY_16; + cmd[13] = RC16_LEN; + memset(buffer, 0, RC16_LEN); + the_result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE, - buffer, longrc ? 13 : 8, &sshdr, - SD_TIMEOUT, SD_MAX_RETRIES, NULL); + buffer, RC16_LEN, &sshdr, + SD_TIMEOUT, SD_MAX_RETRIES, NULL); if (media_not_present(sdkp, &sshdr)) - return; + return -ENODEV; if (the_result) sense_valid = scsi_sense_valid(&sshdr); @@ -1316,72 +1335,122 @@ repeat: } while (the_result && retries); - if (the_result && !longrc) { + if (the_result) { + sd_printk(KERN_NOTICE, sdkp, "READ CAPACITY(16) failed\n"); + read_capacity_error(sdkp, sdp, &sshdr, sense_valid, the_result); + return -EINVAL; + } + + sector_size = (buffer[8] << 24) | (buffer[9] << 16) | + (buffer[10] << 8) | buffer[11]; + lba = (((u64)buffer[0] << 56) | ((u64)buffer[1] << 48) | + ((u64)buffer[2] << 40) | ((u64)buffer[3] << 32) | + ((u64)buffer[4] << 24) | ((u64)buffer[5] << 16) | + ((u64)buffer[6] << 8) | (u64)buffer[7]); + + sd_read_protection_type(sdkp, buffer); + + if ((sizeof(sdkp->capacity) == 4) && (lba >= 0xffffffffULL)) { + sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a " + "kernel compiled with support for large block " + "devices.\n"); + sdkp->capacity = 0; + return -EOVERFLOW; + } + + sdkp->capacity = lba + 1; + return sector_size; +} + +static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp, + unsigned char *buffer) +{ + unsigned char cmd[16]; + struct scsi_sense_hdr sshdr; + int sense_valid = 0; + int the_result; + int retries = 3; + sector_t lba; + unsigned sector_size; + + do { + cmd[0] = READ_CAPACITY; + memset(&cmd[1], 0, 9); + memset(buffer, 0, 8); + + the_result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE, + buffer, 8, &sshdr, + SD_TIMEOUT, SD_MAX_RETRIES, NULL); + + if (media_not_present(sdkp, &sshdr)) + return -ENODEV; + + if (the_result) + sense_valid = scsi_sense_valid(&sshdr); + retries--; + + } while (the_result && retries); + + if (the_result) { sd_printk(KERN_NOTICE, sdkp, "READ CAPACITY failed\n"); - sd_print_result(sdkp, the_result); - if (driver_byte(the_result) & DRIVER_SENSE) - sd_print_sense_hdr(sdkp, &sshdr); - else - sd_printk(KERN_NOTICE, sdkp, "Sense not available.\n"); + read_capacity_error(sdkp, sdp, &sshdr, sense_valid, the_result); + return -EINVAL; + } - /* Set dirty bit for removable devices if not ready - - * sometimes drives will not report this properly. */ - if (sdp->removable && - sense_valid && sshdr.sense_key == NOT_READY) - sdp->changed = 1; + sector_size = (buffer[4] << 24) | (buffer[5] << 16) | + (buffer[6] << 8) | buffer[7]; + lba = (buffer[0] << 24) | (buffer[1] << 16) | + (buffer[2] << 8) | buffer[3]; - /* Either no media are present but the drive didn't tell us, - or they are present but the read capacity command fails */ - /* sdkp->media_present = 0; -- not always correct */ - sdkp->capacity = 0; /* unknown mapped to zero - as usual */ + if ((sizeof(sdkp->capacity) == 4) && (lba == 0xffffffff)) { + sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a " + "kernel compiled with support for large block " + "devices.\n"); + sdkp->capacity = 0; + return -EOVERFLOW; + } - return; - } else if (the_result && longrc) { - /* READ CAPACITY(16) has been failed */ - sd_printk(KERN_NOTICE, sdkp, "READ CAPACITY(16) failed\n"); - sd_print_result(sdkp, the_result); - sd_printk(KERN_NOTICE, sdkp, "Use 0xffffffff as device size\n"); + sdkp->capacity = lba + 1; + return sector_size; +} - sdkp->capacity = 1 + (sector_t) 0xffffffff; - goto got_data; - } - - if (!longrc) { - sector_size = (buffer[4] << 24) | - (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]; - if (buffer[0] == 0xff && buffer[1] == 0xff && - buffer[2] == 0xff && buffer[3] == 0xff) { - if(sizeof(sdkp->capacity) > 4) { - sd_printk(KERN_NOTICE, sdkp, "Very big device. " - "Trying to use READ CAPACITY(16).\n"); - longrc = 1; - goto repeat; - } - sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use " - "a kernel compiled with support for large " - "block devices.\n"); - sdkp->capacity = 0; +/* + * read disk capacity + */ +static void +sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer) +{ + int sector_size; + struct scsi_device *sdp = sdkp->device; + + /* Force READ CAPACITY(16) when PROTECT=1 */ + if (scsi_device_protection(sdp)) { + sector_size = read_capacity_16(sdkp, sdp, buffer); + if (sector_size == -EOVERFLOW) goto got_data; - } - sdkp->capacity = 1 + (((sector_t)buffer[0] << 24) | - (buffer[1] << 16) | - (buffer[2] << 8) | - buffer[3]); + if (sector_size < 0) + return; } else { - sdkp->capacity = 1 + (((u64)buffer[0] << 56) | - ((u64)buffer[1] << 48) | - ((u64)buffer[2] << 40) | - ((u64)buffer[3] << 32) | - ((sector_t)buffer[4] << 24) | - ((sector_t)buffer[5] << 16) | - ((sector_t)buffer[6] << 8) | - (sector_t)buffer[7]); - - sector_size = (buffer[8] << 24) | - (buffer[9] << 16) | (buffer[10] << 8) | buffer[11]; - - sd_read_protection_type(sdkp, buffer); - } + sector_size = read_capacity_10(sdkp, sdp, buffer); + if (sector_size == -EOVERFLOW) + goto got_data; + if (sector_size < 0) + return; + if ((sizeof(sdkp->capacity) > 4) && + (sdkp->capacity > 0xffffffffULL)) { + int old_sector_size = sector_size; + sd_printk(KERN_NOTICE, sdkp, "Very big device. " + "Trying to use READ CAPACITY(16).\n"); + sector_size = read_capacity_16(sdkp, sdp, buffer); + if (sector_size < 0) { + sd_printk(KERN_NOTICE, sdkp, + "Using 0xffffffff as device size\n"); + sdkp->capacity = 1 + (sector_t) 0xffffffff; + sector_size = old_sector_size; + goto got_data; + } + } + } /* Some devices are known to return the total number of blocks, * not the highest block number. Some devices have versions -- GitLab From 8d03c7a0c550e7ab24cadcef5e66656bfadec8b9 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Sat, 14 Mar 2009 11:51:46 -0400 Subject: [PATCH 3406/4982] ext4: fix bogus BUG_ONs in in mballoc code Thiemo Nagel reported that: # dd if=/dev/zero of=image.ext4 bs=1M count=2 # mkfs.ext4 -v -F -b 1024 -m 0 -g 512 -G 4 -I 128 -N 1 \ -O large_file,dir_index,flex_bg,extent,sparse_super image.ext4 # mount -o loop image.ext4 mnt/ # dd if=/dev/zero of=mnt/file oopsed, with a BUG_ON in ext4_mb_normalize_request because size == EXT4_BLOCKS_PER_GROUP It appears to me (esp. after talking to Andreas) that the BUG_ON is bogus; a request of exactly EXT4_BLOCKS_PER_GROUP should be allowed, though larger sizes do indicate a problem. Fix that an another (apparently rare) codepath with a similar check. Reported-by: Thiemo Nagel Signed-off-by: Eric Sandeen Signed-off-by: "Theodore Ts'o" --- fs/ext4/mballoc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 4415beeb0b6..41f4348b62f 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -1447,7 +1447,7 @@ static void ext4_mb_measure_extent(struct ext4_allocation_context *ac, struct ext4_free_extent *gex = &ac->ac_g_ex; BUG_ON(ex->fe_len <= 0); - BUG_ON(ex->fe_len >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); + BUG_ON(ex->fe_len > EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); BUG_ON(ex->fe_start >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); BUG_ON(ac->ac_status != AC_STATUS_CONTINUE); @@ -3292,7 +3292,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac, } BUG_ON(start + size <= ac->ac_o_ex.fe_logical && start > ac->ac_o_ex.fe_logical); - BUG_ON(size <= 0 || size >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); + BUG_ON(size <= 0 || size > EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); /* now prepare goal request */ -- GitLab From de9307c68624b03d2922a02a661ce31e20f078cc Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Fri, 6 Mar 2009 14:52:12 +0000 Subject: [PATCH 3407/4982] netxen: remove old flash check. Remove flash size check which made sense only for ancient boards with 1MB flash. The check is based on values read from specific locations and fails with firmware size changes. This prevents driver from getting right mac addresses. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 1 - drivers/net/netxen/netxen_nic_hw.c | 22 ---------------------- drivers/net/netxen/netxen_nic_main.c | 3 --- 3 files changed, 26 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index f4dd9acb687..1ff066b2281 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -1595,7 +1595,6 @@ dma_watchdog_wakeup(struct netxen_adapter *adapter) } -int netxen_is_flash_supported(struct netxen_adapter *adapter); int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 *mac); int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac); extern void netxen_change_ringparam(struct netxen_adapter *adapter); diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 821cff68b3f..7fea7708810 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -706,28 +706,6 @@ int netxen_nic_change_mtu(struct net_device *netdev, int mtu) return rc; } -int netxen_is_flash_supported(struct netxen_adapter *adapter) -{ - const int locs[] = { 0, 0x4, 0x100, 0x4000, 0x4128 }; - int addr, val01, val02, i, j; - - /* if the flash size less than 4Mb, make huge war cry and die */ - for (j = 1; j < 4; j++) { - addr = j * NETXEN_NIC_WINDOW_MARGIN; - for (i = 0; i < ARRAY_SIZE(locs); i++) { - if (netxen_rom_fast_read(adapter, locs[i], &val01) == 0 - && netxen_rom_fast_read(adapter, (addr + locs[i]), - &val02) == 0) { - if (val01 == val02) - return -1; - } else - return -1; - } - } - - return 0; -} - static int netxen_get_flash_block(struct netxen_adapter *adapter, int base, int size, __le32 * buf) { diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 13087782ac4..c172b6e24a9 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -405,9 +405,6 @@ netxen_read_mac_addr(struct netxen_adapter *adapter) struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; - if (netxen_is_flash_supported(adapter) != 0) - return -EIO; - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { if (netxen_p3_get_mac_addr(adapter, &mac_addr) != 0) return -EIO; -- GitLab From 020fe22ff14320927f394de222cbb11708bcc7a8 Mon Sep 17 00:00:00 2001 From: Enrik Berkhan Date: Fri, 13 Mar 2009 13:51:56 -0700 Subject: [PATCH 3408/4982] nommu: ramfs: pages allocated to an inode's pagecache may get wrongly discarded The pages attached to a ramfs inode's pagecache by truncation from nothing - as done by SYSV SHM for example - may get discarded under memory pressure. The problem is that the pages are not marked dirty. Anything that creates data in an MMU-based ramfs will cause the pages holding that data will cause the set_page_dirty() aop to be called. For the NOMMU-based mmap, set_page_dirty() may be called by write(), but it won't be called by page-writing faults on writable mmaps, and it isn't called by ramfs_nommu_expand_for_mapping() when a file is being truncated from nothing to allocate a contiguous run. The solution is to mark the pages dirty at the point of allocation by the truncation code. Signed-off-by: Enrik Berkhan Signed-off-by: David Howells Cc: Peter Zijlstra Cc: Nick Piggin Cc: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ramfs/file-nommu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index b9b567a2837..90d72bead55 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c @@ -114,6 +114,9 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) if (!pagevec_add(&lru_pvec, page)) __pagevec_lru_add_file(&lru_pvec); + /* prevent the page from being discarded on memory pressure */ + SetPageDirty(page); + unlock_page(page); } -- GitLab From 15e7b8767605dc0cb9bd4594caabfec392385210 Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Fri, 13 Mar 2009 13:51:58 -0700 Subject: [PATCH 3409/4982] nommu: ramfs: don't leak pages when adding to page cache fails When a ramfs nommu mapping is expanded, contiguous pages are allocated and added to the pagecache. The caller's reference is then passed on by moving whole pagevecs to the file lru list. If the page cache adding fails, make sure that the error path also moves the pagevec contents which might still contain up to PAGEVEC_SIZE successfully added pages, of which we would leak references otherwise. Signed-off-by: Johannes Weiner Cc: David Howells Cc: Enrik Berkhan Cc: Nick Piggin Cc: Peter Zijlstra Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ramfs/file-nommu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index 90d72bead55..5d7c7ececa6 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c @@ -129,6 +129,7 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) return -EFBIG; add_error: + pagevec_lru_add_file(&lru_pvec); page_cache_release(pages + loop); for (loop++; loop < npages; loop++) __free_page(pages + loop); -- GitLab From 84814d642a4f1f294bd675ab11aae1ca54c6cedb Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Fri, 13 Mar 2009 13:51:59 -0700 Subject: [PATCH 3410/4982] eCryptfs: don't encrypt file key with filename key eCryptfs has file encryption keys (FEK), file encryption key encryption keys (FEKEK), and filename encryption keys (FNEK). The per-file FEK is encrypted with one or more FEKEKs and stored in the header of the encrypted file. I noticed that the FEK is also being encrypted by the FNEK. This is a problem if a user wants to use a different FNEK than their FEKEK, as their file contents will still be accessible with the FNEK. This is a minimalistic patch which prevents the FNEKs signatures from being copied to the inode signatures list. Ultimately, it keeps the FEK from being encrypted with a FNEK. Signed-off-by: Tyler Hicks Cc: Serge Hallyn Acked-by: Dustin Kirkland Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ecryptfs/crypto.c | 2 ++ fs/ecryptfs/ecryptfs_kernel.h | 3 ++- fs/ecryptfs/keystore.c | 3 ++- fs/ecryptfs/main.c | 5 +++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index f6caeb1d110..bdca1f4b3a3 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -946,6 +946,8 @@ static int ecryptfs_copy_mount_wide_sigs_to_inode_sigs( list_for_each_entry(global_auth_tok, &mount_crypt_stat->global_auth_tok_list, mount_crypt_stat_list) { + if (global_auth_tok->flags & ECRYPTFS_AUTH_TOK_FNEK) + continue; rc = ecryptfs_add_keysig(crypt_stat, global_auth_tok->sig); if (rc) { printk(KERN_ERR "Error adding keysig; rc = [%d]\n", rc); diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index c11fc95714a..eb2267eca1f 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -328,6 +328,7 @@ struct ecryptfs_dentry_info { */ struct ecryptfs_global_auth_tok { #define ECRYPTFS_AUTH_TOK_INVALID 0x00000001 +#define ECRYPTFS_AUTH_TOK_FNEK 0x00000002 u32 flags; struct list_head mount_crypt_stat_list; struct key *global_auth_tok_key; @@ -696,7 +697,7 @@ ecryptfs_write_header_metadata(char *virt, int ecryptfs_add_keysig(struct ecryptfs_crypt_stat *crypt_stat, char *sig); int ecryptfs_add_global_auth_tok(struct ecryptfs_mount_crypt_stat *mount_crypt_stat, - char *sig); + char *sig, u32 global_auth_tok_flags); int ecryptfs_get_global_auth_tok_for_sig( struct ecryptfs_global_auth_tok **global_auth_tok, struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig); diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index ff539420cc6..e4a6223c314 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -2375,7 +2375,7 @@ struct kmem_cache *ecryptfs_global_auth_tok_cache; int ecryptfs_add_global_auth_tok(struct ecryptfs_mount_crypt_stat *mount_crypt_stat, - char *sig) + char *sig, u32 global_auth_tok_flags) { struct ecryptfs_global_auth_tok *new_auth_tok; int rc = 0; @@ -2389,6 +2389,7 @@ ecryptfs_add_global_auth_tok(struct ecryptfs_mount_crypt_stat *mount_crypt_stat, goto out; } memcpy(new_auth_tok->sig, sig, ECRYPTFS_SIG_SIZE_HEX); + new_auth_tok->flags = global_auth_tok_flags; new_auth_tok->sig[ECRYPTFS_SIG_SIZE_HEX] = '\0'; mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex); list_add(&new_auth_tok->mount_crypt_stat_list, diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 789cf2e1be1..aed56c25539 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -319,7 +319,7 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options) case ecryptfs_opt_ecryptfs_sig: sig_src = args[0].from; rc = ecryptfs_add_global_auth_tok(mount_crypt_stat, - sig_src); + sig_src, 0); if (rc) { printk(KERN_ERR "Error attempting to register " "global sig; rc = [%d]\n", rc); @@ -370,7 +370,8 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options) ECRYPTFS_SIG_SIZE_HEX] = '\0'; rc = ecryptfs_add_global_auth_tok( mount_crypt_stat, - mount_crypt_stat->global_default_fnek_sig); + mount_crypt_stat->global_default_fnek_sig, + ECRYPTFS_AUTH_TOK_FNEK); if (rc) { printk(KERN_ERR "Error attempting to register " "global fnek sig [%s]; rc = [%d]\n", -- GitLab From 1d885526f2f3fffacee2ecb541270bd00168adff Mon Sep 17 00:00:00 2001 From: Daisuke Nishimura Date: Fri, 13 Mar 2009 13:52:00 -0700 Subject: [PATCH 3411/4982] vmscan: pgmoved should be cleared after updating recent_rotated pgmoved should be cleared after updating recent_rotated. Signed-off-by: Daisuke Nishimura Cc: Rik van Riel Cc: Lee Schermerhorn Acked-by: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmscan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index e8951714165..56ddf41149e 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1262,7 +1262,6 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone, * Move the pages to the [file or anon] inactive list. */ pagevec_init(&pvec, 1); - pgmoved = 0; lru = LRU_BASE + file * LRU_FILE; spin_lock_irq(&zone->lru_lock); @@ -1274,6 +1273,7 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone, */ reclaim_stat->recent_rotated[!!file] += pgmoved; + pgmoved = 0; while (!list_empty(&l_inactive)) { page = lru_to_page(&l_inactive); prefetchw_prev_lru_page(page, &l_inactive, flags); -- GitLab From 92be791759945a9170394e92c03a2e75175d6bbe Mon Sep 17 00:00:00 2001 From: Maciej Sosnowski Date: Fri, 13 Mar 2009 20:40:21 +0000 Subject: [PATCH 3412/4982] igb: switch to new dca API With the new DCA API, the driver should use dca3_get_tag() instead of the obsolete dca_get_tag(). Signed-off-by: Maciej Sosnowski < maciej.sosnowski@intel.com> Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 78558f840fd..2cb267fc9c7 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3670,11 +3670,11 @@ static void igb_update_rx_dca(struct igb_ring *rx_ring) dca_rxctrl = rd32(E1000_DCA_RXCTRL(q)); if (hw->mac.type == e1000_82576) { dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK_82576; - dca_rxctrl |= dca_get_tag(cpu) << + dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) << E1000_DCA_RXCTRL_CPUID_SHIFT; } else { dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK; - dca_rxctrl |= dca_get_tag(cpu); + dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); } dca_rxctrl |= E1000_DCA_RXCTRL_DESC_DCA_EN; dca_rxctrl |= E1000_DCA_RXCTRL_HEAD_DCA_EN; @@ -3697,11 +3697,11 @@ static void igb_update_tx_dca(struct igb_ring *tx_ring) dca_txctrl = rd32(E1000_DCA_TXCTRL(q)); if (hw->mac.type == e1000_82576) { dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK_82576; - dca_txctrl |= dca_get_tag(cpu) << + dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) << E1000_DCA_TXCTRL_CPUID_SHIFT; } else { dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK; - dca_txctrl |= dca_get_tag(cpu); + dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); } dca_txctrl |= E1000_DCA_TXCTRL_DESC_DCA_EN; wr32(E1000_DCA_TXCTRL(q), dca_txctrl); -- GitLab From 5e6d5b17db099dd575490545a4f0af9a99fa8bbe Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 13 Mar 2009 20:40:38 +0000 Subject: [PATCH 3413/4982] igb: remove netif running call from igb_poll The netif_running check in igb poll is a hold over from the use of fake netdevs to use multiple queues with NAPI prior to 2.6.24. It is no longer necessary to have the call there and it currently can cause errors if work_done == budget. Signed-off-by: Alexander Duyck Acked-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 2cb267fc9c7..4ff242de981 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -4187,7 +4187,6 @@ static int igb_poll(struct napi_struct *napi, int budget) { struct igb_ring *rx_ring = container_of(napi, struct igb_ring, napi); struct igb_adapter *adapter = rx_ring->adapter; - struct net_device *netdev = adapter->netdev; int work_done = 0; #ifdef CONFIG_IGB_DCA @@ -4206,7 +4205,7 @@ static int igb_poll(struct napi_struct *napi, int budget) } /* If not enough Rx work done, exit the polling mode */ - if ((work_done < budget) || !netif_running(netdev)) { + if (work_done < budget) { napi_complete(napi); igb_rx_irq_enable(rx_ring); } -- GitLab From bd38e5d124ddd11c457c5ae7242cd039045d80e0 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 13 Mar 2009 20:40:58 +0000 Subject: [PATCH 3414/4982] igb: resolve warning of unused adapter struct If DCA is undefined then the adapter struct becomes unnecessary. To resolve this issue the DCA calls can simply make a call to the adapter struct through the rx_ring adapter struct member. Signed-off-by: Alexander Duyck Acked-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 4ff242de981..5277d56e989 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -4186,18 +4186,17 @@ static inline void igb_rx_irq_enable(struct igb_ring *rx_ring) static int igb_poll(struct napi_struct *napi, int budget) { struct igb_ring *rx_ring = container_of(napi, struct igb_ring, napi); - struct igb_adapter *adapter = rx_ring->adapter; int work_done = 0; #ifdef CONFIG_IGB_DCA - if (adapter->flags & IGB_FLAG_DCA_ENABLED) + if (rx_ring->adapter->flags & IGB_FLAG_DCA_ENABLED) igb_update_rx_dca(rx_ring); #endif igb_clean_rx_irq_adv(rx_ring, &work_done, budget); if (rx_ring->buddy) { #ifdef CONFIG_IGB_DCA - if (adapter->flags & IGB_FLAG_DCA_ENABLED) + if (rx_ring->adapter->flags & IGB_FLAG_DCA_ENABLED) igb_update_tx_dca(rx_ring->buddy); #endif if (!igb_clean_tx_irq(rx_ring->buddy)) -- GitLab From a2cf8b6ce17415fc84f51300fd6be372d95bfcea Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 13 Mar 2009 20:41:17 +0000 Subject: [PATCH 3415/4982] igb: support wol on second port We need to support wol on the second port for situations such as when the lan ports are on the motherboard itself. Signed-off-by: Alexander Duyck Acked-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_defines.h | 1 + drivers/net/igb/igb_main.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index 62e378b6461..ad2d319d0f8 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -512,6 +512,7 @@ #define NVM_ID_LED_SETTINGS 0x0004 /* For SERDES output amplitude adjustment. */ #define NVM_INIT_CONTROL2_REG 0x000F +#define NVM_INIT_CONTROL3_PORT_B 0x0014 #define NVM_INIT_CONTROL3_PORT_A 0x0024 #define NVM_ALT_MAC_ADDR_PTR 0x0037 #define NVM_CHECKSUM_REG 0x003F diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 5277d56e989..f0c3a01452c 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1351,9 +1351,10 @@ static int __devinit igb_probe(struct pci_dev *pdev, * enable the ACPI Magic Packet filter */ - if (hw->bus.func == 0 || - hw->device_id == E1000_DEV_ID_82575EB_COPPER) + if (hw->bus.func == 0) hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); + else if (hw->bus.func == 1) + hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); if (eeprom_data & eeprom_apme_mask) adapter->eeprom_wol |= E1000_WUFC_MAG; -- GitLab From cad6d05f5676d879bb2a48154aea26cd81ebf1bb Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 13 Mar 2009 20:41:37 +0000 Subject: [PATCH 3416/4982] igb: add PF to pool Add Pf to pool if adding a VLVF register value and the VFTA bit is already set. This patch addresses the unlikely situation that the PF adds a vlan entry when the vlvf is full, and a vf later adds the vlan to the vlvf. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_mac.c | 21 ++++++++++++++------- drivers/net/igb/e1000_mac.h | 2 +- drivers/net/igb/igb_main.c | 9 +++++++-- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c index 2804db03e9d..f11592fe137 100644 --- a/drivers/net/igb/e1000_mac.c +++ b/drivers/net/igb/e1000_mac.c @@ -126,19 +126,26 @@ void igb_write_vfta(struct e1000_hw *hw, u32 offset, u32 value) * Sets or clears a bit in the VLAN filter table array based on VLAN id * and if we are adding or removing the filter **/ -void igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add) +s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add) { u32 index = (vid >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK; u32 mask = 1 < (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK); - u32 vfta; + u32 vfta = array_rd32(E1000_VFTA, index); + s32 ret_val = 0; - vfta = array_rd32(E1000_VFTA, index); - if (add) - vfta |= mask; - else - vfta &= ~mask; + /* bit was set/cleared before we started */ + if ((!!(vfta & mask)) == add) { + ret_val = -E1000_ERR_CONFIG; + } else { + if (add) + vfta |= mask; + else + vfta &= ~mask; + } igb_write_vfta(hw, index, vfta); + + return ret_val; } /** diff --git a/drivers/net/igb/e1000_mac.h b/drivers/net/igb/e1000_mac.h index eccc3536a56..a34de526963 100644 --- a/drivers/net/igb/e1000_mac.h +++ b/drivers/net/igb/e1000_mac.h @@ -58,7 +58,7 @@ s32 igb_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, void igb_clear_hw_cntrs_base(struct e1000_hw *hw); void igb_clear_vfta(struct e1000_hw *hw); -void igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add); +s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add); void igb_config_collision_dist(struct e1000_hw *hw); void igb_mta_set(struct e1000_hw *hw, u32 hash_value); void igb_put_hw_semaphore(struct e1000_hw *hw); diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index f0c3a01452c..a3c2f83fb49 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3895,10 +3895,15 @@ static s32 igb_vlvf_set(struct igb_adapter *adapter, u32 vid, bool add, u32 vf) /* if !enabled we need to set this up in vfta */ if (!(reg & E1000_VLVF_VLANID_ENABLE)) { - /* add VID to filter table */ - igb_vfta_set(hw, vid, true); + /* add VID to filter table, if bit already set + * PF must have added it outside of table */ + if (igb_vfta_set(hw, vid, true)) + reg |= 1 << (E1000_VLVF_POOLSEL_SHIFT + + adapter->vfs_allocated_count); reg |= E1000_VLVF_VLANID_ENABLE; } + reg &= ~E1000_VLVF_VLANID_MASK; + reg |= vid; wr32(E1000_VLVF(i), reg); return 0; -- GitLab From 75f4f382e3f92d1d2fcb77fe6ed7beda19185f0f Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 13 Mar 2009 20:41:55 +0000 Subject: [PATCH 3417/4982] igb: correct typo that was setting vfta mask to 1 This patch corrects a typo that was doing a less than comparison instead of a left shift due to the fact that I didn't get enough <'s in there. This resolves an issue in which vlans were not functioning correctly. Signed-off-by: Alexander Duyck Acked-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_mac.c | 2 +- drivers/net/igb/igb_main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c index f11592fe137..f4c315b5a90 100644 --- a/drivers/net/igb/e1000_mac.c +++ b/drivers/net/igb/e1000_mac.c @@ -129,7 +129,7 @@ void igb_write_vfta(struct e1000_hw *hw, u32 offset, u32 value) s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add) { u32 index = (vid >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK; - u32 mask = 1 < (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK); + u32 mask = 1 << (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK); u32 vfta = array_rd32(E1000_VFTA, index); s32 ret_val = 0; diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index a3c2f83fb49..ff1cd4a1ec1 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3828,7 +3828,7 @@ static void igb_restore_vf_multicasts(struct igb_adapter *adapter) for (i = 0; i < adapter->vfs_allocated_count; i++) { vf_data = &adapter->vf_data[i]; - for (j = 0; j < vf_data[i].num_vf_mc_hashes; j++) + for (j = 0; j < vf_data->num_vf_mc_hashes; j++) igb_mta_set(hw, vf_data->vf_mc_hashes[j]); } } -- GitLab From 9eb2341d0df6e5d33508008879987bf5bb146804 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 13 Mar 2009 20:42:15 +0000 Subject: [PATCH 3418/4982] igb: add support for another dual port 82576 non-security nic Adding device id to support 82576NS dual port copper NIC. Signed-off-by: Alexander Duyck Acked-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_82575.c | 1 + drivers/net/igb/e1000_hw.h | 1 + drivers/net/igb/igb_main.c | 1 + 3 files changed, 3 insertions(+) diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index ea63a215c90..adfe2e18ede 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -80,6 +80,7 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) mac->type = e1000_82575; break; case E1000_DEV_ID_82576: + case E1000_DEV_ID_82576_NS: case E1000_DEV_ID_82576_FIBER: case E1000_DEV_ID_82576_SERDES: mac->type = e1000_82576; diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h index d793dca1eef..4db36026f82 100644 --- a/drivers/net/igb/e1000_hw.h +++ b/drivers/net/igb/e1000_hw.h @@ -40,6 +40,7 @@ struct e1000_hw; #define E1000_DEV_ID_82576 0x10C9 #define E1000_DEV_ID_82576_FIBER 0x10E6 #define E1000_DEV_ID_82576_SERDES 0x10E7 +#define E1000_DEV_ID_82576_NS 0x150A #define E1000_DEV_ID_82575EB_COPPER 0x10A7 #define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9 #define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6 diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index ff1cd4a1ec1..e464dc024ee 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -62,6 +62,7 @@ static const struct e1000_info *igb_info_tbl[] = { static struct pci_device_id igb_pci_tbl[] = { { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576), board_82575 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_FIBER), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_COPPER), board_82575 }, -- GitLab From c8ea5ea9da338d6af015148105f07fc35eda8a92 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 13 Mar 2009 20:42:35 +0000 Subject: [PATCH 3419/4982] igb: add support for 82576 quad copper adapter Add support for 82576 copper adapter and necessary code to restrict wol for quad port adapter to first port. Signed-off-by: Alexander Duyck Acked-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_82575.c | 1 + drivers/net/igb/e1000_hw.h | 1 + drivers/net/igb/igb_ethtool.c | 9 +++++++++ drivers/net/igb/igb_main.c | 11 +++++++++++ 4 files changed, 22 insertions(+) diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index adfe2e18ede..efd9be21488 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -83,6 +83,7 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) case E1000_DEV_ID_82576_NS: case E1000_DEV_ID_82576_FIBER: case E1000_DEV_ID_82576_SERDES: + case E1000_DEV_ID_82576_QUAD_COPPER: mac->type = e1000_82576; break; default: diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h index 4db36026f82..68aac20c31c 100644 --- a/drivers/net/igb/e1000_hw.h +++ b/drivers/net/igb/e1000_hw.h @@ -40,6 +40,7 @@ struct e1000_hw; #define E1000_DEV_ID_82576 0x10C9 #define E1000_DEV_ID_82576_FIBER 0x10E6 #define E1000_DEV_ID_82576_SERDES 0x10E7 +#define E1000_DEV_ID_82576_QUAD_COPPER 0x10E8 #define E1000_DEV_ID_82576_NS 0x150A #define E1000_DEV_ID_82575EB_COPPER 0x10A7 #define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9 diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 34a8a0fadf2..fb09c8ad9f0 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -1779,6 +1779,15 @@ static int igb_wol_exclusion(struct igb_adapter *adapter, /* return success for non excluded adapter ports */ retval = 0; break; + case E1000_DEV_ID_82576_QUAD_COPPER: + /* quad port adapters only support WoL on port A */ + if (!(adapter->flags & IGB_FLAG_QUAD_PORT_A)) { + wol->supported = 0; + break; + } + /* return success for non excluded adapter ports */ + retval = 0; + break; default: /* dual port cards only support WoL on port A from now on * unless it was enabled in the eeprom for port B diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index e464dc024ee..7124f59fb99 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -65,6 +65,7 @@ static struct pci_device_id igb_pci_tbl[] = { { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_FIBER), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES), board_82575 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_QUAD_COPPER), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_COPPER), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_FIBER_SERDES), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575GB_QUAD_COPPER), board_82575 }, @@ -1375,6 +1376,16 @@ static int __devinit igb_probe(struct pci_dev *pdev, if (rd32(E1000_STATUS) & E1000_STATUS_FUNC_1) adapter->eeprom_wol = 0; break; + case E1000_DEV_ID_82576_QUAD_COPPER: + /* if quad port adapter, disable WoL on all but port A */ + if (global_quad_port_a != 0) + adapter->eeprom_wol = 0; + else + adapter->flags |= IGB_FLAG_QUAD_PORT_A; + /* Reset for multiple quad port adapters */ + if (++global_quad_port_a == 4) + global_quad_port_a = 0; + break; } /* initialize the wol settings based on the eeprom settings */ -- GitLab From 1339b9e975902dcb8ef81ace678cfb6626d4bf3f Mon Sep 17 00:00:00 2001 From: PJ Waskiewicz Date: Fri, 13 Mar 2009 22:12:29 +0000 Subject: [PATCH 3420/4982] ixgbe: Fix get_supported_physical_layer() due to new 82599 PHY types A purely cosmetic change. Report which physical layer is present, instead of PHY unknown. 82599 added new PHY types for the SFP+ devices, and this was missed getting updated. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_82599.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index cc3bfa195b7..56efa98fe3b 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -1130,6 +1130,7 @@ s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw) u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw) { u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; + u8 comp_codes_10g = 0; switch (hw->device_id) { case IXGBE_DEV_ID_82599: @@ -1143,6 +1144,8 @@ u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw) switch (hw->phy.sfp_type) { case ixgbe_sfp_type_da_cu: + case ixgbe_sfp_type_da_cu_core0: + case ixgbe_sfp_type_da_cu_core1: physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU; break; case ixgbe_sfp_type_sr: @@ -1151,6 +1154,19 @@ u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw) case ixgbe_sfp_type_lr: physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR; break; + case ixgbe_sfp_type_srlr_core0: + case ixgbe_sfp_type_srlr_core1: + hw->phy.ops.read_i2c_eeprom(hw, + IXGBE_SFF_10GBE_COMP_CODES, + &comp_codes_10g); + if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE) + physical_layer = + IXGBE_PHYSICAL_LAYER_10GBASE_SR; + else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE) + physical_layer = + IXGBE_PHYSICAL_LAYER_10GBASE_LR; + else + physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; default: physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; break; -- GitLab From d51019a4daac885ac4dead9d45d3a2a61189d9fd Mon Sep 17 00:00:00 2001 From: PJ Waskiewicz Date: Fri, 13 Mar 2009 22:12:48 +0000 Subject: [PATCH 3421/4982] ixgbe: Fix an accounting problem when the Rx FIFO is full The rx_no_dma_resources counter reported by ethtool -S ethX is not counting correctly. In 82599, the queue mappings for the counters need to be mapped properly, and accounted for properly. Signed-off-by: Peter P Waskiewicz Jr Acked-by: Mallikarjuna R Chilakala Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index d0b98708e6c..86c8bad609b 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3629,6 +3629,12 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) u64 total_mpc = 0; u32 i, missed_rx = 0, mpc, bprc, lxon, lxoff, xon_off_tot; + if (hw->mac.type == ixgbe_mac_82599EB) { + for (i = 0; i < 16; i++) + adapter->hw_rx_no_dma_resources += + IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); + } + adapter->stats.crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS); for (i = 0; i < 8; i++) { /* for packet buffers not used, the register should read 0 */ @@ -3648,7 +3654,6 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) adapter->stats.pxoffrxc[i] += IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i)); adapter->stats.qprdc[i] += IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); - adapter->hw_rx_no_dma_resources += adapter->stats.qprdc[i]; } else { adapter->stats.pxonrxc[i] += IXGBE_READ_REG(hw, IXGBE_PXONRXC(i)); -- GitLab From 40dcd79a7bd2e0d6bf4680db4bc0268c9f149a1d Mon Sep 17 00:00:00 2001 From: PJ Waskiewicz Date: Fri, 13 Mar 2009 22:13:08 +0000 Subject: [PATCH 3422/4982] ixgbe: Disable DROP_EN for Rx queues 82599 mistakenly enabled drop on Rx queues in the packet buffer. The default mode should be store-and-forward from the FIFO. Signed-off-by: Peter P Waskiewicz Jr Acked-by: Mallikarjuna R Chilakala Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 86c8bad609b..881bbf97ff0 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1679,8 +1679,6 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, int index) srrctl |= rx_ring->rx_buf_len >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; } - if (adapter->hw.mac.type == ixgbe_mac_82599EB) - srrctl |= IXGBE_SRRCTL_DROP_EN; IXGBE_WRITE_REG(&adapter->hw, IXGBE_SRRCTL(index), srrctl); } -- GitLab From 509ee935ec0828e534e4d48d08d4d0b4bc17ea92 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 13 Mar 2009 22:13:28 +0000 Subject: [PATCH 3423/4982] ixgbe: Fix interrupt configuration for 82599 The interrupt models using EITR have changed in 82599. The way the register is laid out, the change is transparent to some of the existing code. However, some of it isn't. This patch fixes all the cases where EITR handling is different than 82598. Signed-off-by: Jesse Brandeburg Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe.h | 6 ++- drivers/net/ixgbe/ixgbe_ethtool.c | 21 ++++++---- drivers/net/ixgbe/ixgbe_main.c | 64 +++++++++++++++++++++---------- drivers/net/ixgbe/ixgbe_type.h | 11 +++++- 4 files changed, 71 insertions(+), 31 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 0b54717f707..c26433d1460 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -189,10 +189,11 @@ struct ixgbe_q_vector { }; /* Helper macros to switch between ints/sec and what the register uses. - * And yes, it's the same math going both ways. + * And yes, it's the same math going both ways. The lowest value + * supported by all of the ixgbe hardware is 8. */ #define EITR_INTS_PER_SEC_TO_REG(_eitr) \ - ((_eitr) ? (1000000000 / ((_eitr) * 256)) : 0) + ((_eitr) ? (1000000000 / ((_eitr) * 256)) : 8) #define EITR_REG_TO_INTS_PER_SEC EITR_INTS_PER_SEC_TO_REG #define IXGBE_DESC_UNUSED(R) \ @@ -366,5 +367,6 @@ extern void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter); extern int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter); void ixgbe_napi_add_all(struct ixgbe_adapter *adapter); void ixgbe_napi_del_all(struct ixgbe_adapter *adapter); +extern void ixgbe_write_eitr(struct ixgbe_adapter *, int, u32); #endif /* _IXGBE_H_ */ diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index ae38bcaa7ca..3a99781794d 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -977,40 +977,47 @@ static int ixgbe_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) { struct ixgbe_adapter *adapter = netdev_priv(netdev); - struct ixgbe_hw *hw = &adapter->hw; int i; if (ec->tx_max_coalesced_frames_irq) adapter->tx_ring[0].work_limit = ec->tx_max_coalesced_frames_irq; if (ec->rx_coalesce_usecs > 1) { + /* check the limits */ + if ((1000000/ec->rx_coalesce_usecs > IXGBE_MAX_INT_RATE) || + (1000000/ec->rx_coalesce_usecs < IXGBE_MIN_INT_RATE)) + return -EINVAL; + /* store the value in ints/second */ adapter->eitr_param = 1000000/ec->rx_coalesce_usecs; /* static value of interrupt rate */ adapter->itr_setting = adapter->eitr_param; - /* clear the lower bit */ + /* clear the lower bit as its used for dynamic state */ adapter->itr_setting &= ~1; } else if (ec->rx_coalesce_usecs == 1) { /* 1 means dynamic mode */ adapter->eitr_param = 20000; adapter->itr_setting = 1; } else { - /* any other value means disable eitr, which is best - * served by setting the interrupt rate very high */ - adapter->eitr_param = 3000000; + /* + * any other value means disable eitr, which is best + * served by setting the interrupt rate very high + */ + adapter->eitr_param = IXGBE_MAX_INT_RATE; adapter->itr_setting = 0; } for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) { struct ixgbe_q_vector *q_vector = &adapter->q_vector[i]; if (q_vector->txr_count && !q_vector->rxr_count) + /* tx vector gets half the rate */ q_vector->eitr = (adapter->eitr_param >> 1); else /* rx only or mixed */ q_vector->eitr = adapter->eitr_param; - IXGBE_WRITE_REG(hw, IXGBE_EITR(i), - EITR_INTS_PER_SEC_TO_REG(q_vector->eitr)); + ixgbe_write_eitr(adapter, i, + EITR_INTS_PER_SEC_TO_REG(q_vector->eitr)); } return 0; diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 881bbf97ff0..76fd5c6db02 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -808,10 +808,14 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) /* if this is a tx only vector halve the interrupt rate */ if (q_vector->txr_count && !q_vector->rxr_count) q_vector->eitr = (adapter->eitr_param >> 1); - else + else if (q_vector->rxr_count) /* rx only */ q_vector->eitr = adapter->eitr_param; + /* + * since ths is initial set up don't need to call + * ixgbe_write_eitr helper + */ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(v_idx), EITR_INTS_PER_SEC_TO_REG(q_vector->eitr)); } @@ -896,10 +900,35 @@ update_itr_done: return retval; } +/** + * ixgbe_write_eitr - write EITR register in hardware specific way + * @adapter: pointer to adapter struct + * @v_idx: vector index into q_vector array + * @itr_reg: new value to be written in *register* format, not ints/s + * + * This function is made to be called by ethtool and by the driver + * when it needs to update EITR registers at runtime. Hardware + * specific quirks/differences are taken care of here. + */ +void ixgbe_write_eitr(struct ixgbe_adapter *adapter, int v_idx, u32 itr_reg) +{ + struct ixgbe_hw *hw = &adapter->hw; + if (adapter->hw.mac.type == ixgbe_mac_82598EB) { + /* must write high and low 16 bits to reset counter */ + itr_reg |= (itr_reg << 16); + } else if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + /* + * set the WDIS bit to not clear the timer bits and cause an + * immediate assertion of the interrupt + */ + itr_reg |= IXGBE_EITR_CNT_WDIS; + } + IXGBE_WRITE_REG(hw, IXGBE_EITR(v_idx), itr_reg); +} + static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) { struct ixgbe_adapter *adapter = q_vector->adapter; - struct ixgbe_hw *hw = &adapter->hw; u32 new_itr; u8 current_itr, ret_itr; int i, r_idx, v_idx = ((void *)q_vector - (void *)(adapter->q_vector)) / @@ -954,17 +983,13 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) if (new_itr != q_vector->eitr) { u32 itr_reg; + + /* save the algorithm value here, not the smoothed one */ + q_vector->eitr = new_itr; /* do an exponential smoothing */ new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100); - q_vector->eitr = new_itr; itr_reg = EITR_INTS_PER_SEC_TO_REG(new_itr); - if (adapter->hw.mac.type == ixgbe_mac_82599EB) - /* Resolution is 2 usec on 82599, so halve the rate */ - itr_reg >>= 1; - /* must write high and low 16 bits to reset counter */ - DPRINTK(TX_ERR, DEBUG, "writing eitr(%d): %08X\n", v_idx, - itr_reg); - IXGBE_WRITE_REG(hw, IXGBE_EITR(v_idx), itr_reg | (itr_reg)<<16); + ixgbe_write_eitr(adapter, v_idx, itr_reg); } return; @@ -1141,7 +1166,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget) /* If all Rx work done, exit the polling mode */ if (work_done < budget) { napi_complete(napi); - if (adapter->itr_setting & 3) + if (adapter->itr_setting & 1) ixgbe_set_itr_msix(q_vector); if (!test_bit(__IXGBE_DOWN, &adapter->state)) IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, rx_ring->v_idx); @@ -1190,7 +1215,7 @@ static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget) /* If all Rx work done, exit the polling mode */ if (work_done < budget) { napi_complete(napi); - if (adapter->itr_setting & 3) + if (adapter->itr_setting & 1) ixgbe_set_itr_msix(q_vector); if (!test_bit(__IXGBE_DOWN, &adapter->state)) IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, enable_mask); @@ -1360,7 +1385,6 @@ out: static void ixgbe_set_itr(struct ixgbe_adapter *adapter) { - struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_q_vector *q_vector = adapter->q_vector; u8 current_itr; u32 new_itr = q_vector->eitr; @@ -1395,15 +1419,13 @@ static void ixgbe_set_itr(struct ixgbe_adapter *adapter) if (new_itr != q_vector->eitr) { u32 itr_reg; + + /* save the algorithm value here, not the smoothed one */ + q_vector->eitr = new_itr; /* do an exponential smoothing */ new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100); - q_vector->eitr = new_itr; itr_reg = EITR_INTS_PER_SEC_TO_REG(new_itr); - if (adapter->hw.mac.type == ixgbe_mac_82599EB) - /* Resolution is 2 usec on 82599, so halve the rate */ - itr_reg >>= 1; - /* must write high and low 16 bits to reset counter */ - IXGBE_WRITE_REG(hw, IXGBE_EITR(0), itr_reg | (itr_reg)<<16); + ixgbe_write_eitr(adapter, 0, itr_reg); } return; @@ -1701,7 +1723,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) 0xA54F2BEC, 0xEA49AF7C, 0xE214AD3D, 0xB855AABE, 0x6A3E67EA, 0x14364D17, 0x3BED200D}; u32 fctrl, hlreg0; - u32 reta = 0, mrqc; + u32 reta = 0, mrqc = 0; u32 rdrxctl; int rx_buf_len; @@ -2589,7 +2611,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget) /* If budget not fully consumed, exit the polling mode */ if (work_done < budget) { napi_complete(napi); - if (adapter->itr_setting & 3) + if (adapter->itr_setting & 1) ixgbe_set_itr(adapter); if (!test_bit(__IXGBE_DOWN, &adapter->state)) ixgbe_irq_enable(adapter); diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 60905936d92..95fc36cff26 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -98,9 +98,18 @@ #define IXGBE_EIMS_EX(_i) (0x00AA0 + (_i) * 4) #define IXGBE_EIMC_EX(_i) (0x00AB0 + (_i) * 4) #define IXGBE_EIAM_EX(_i) (0x00AD0 + (_i) * 4) +/* + * 82598 EITR is 16 bits but set the limits based on the max + * supported by all ixgbe hardware. 82599 EITR is only 12 bits, + * with the lower 3 always zero. + */ +#define IXGBE_MAX_INT_RATE 488281 +#define IXGBE_MIN_INT_RATE 956 +#define IXGBE_MAX_EITR 0x00000FF8 +#define IXGBE_MIN_EITR 8 #define IXGBE_EITR(_i) (((_i) <= 23) ? (0x00820 + ((_i) * 4)) : \ (0x012300 + (((_i) - 24) * 4))) -#define IXGBE_EITR_ITR_INT_MASK 0x00000FFF +#define IXGBE_EITR_ITR_INT_MASK 0x00000FF8 #define IXGBE_EITR_LLI_MOD 0x00008000 #define IXGBE_EITR_CNT_WDIS 0x80000000 #define IXGBE_IVAR(_i) (0x00900 + ((_i) * 4)) /* 24 at 0x900-0x960 */ -- GitLab From 4dd64df8954cc6d485f7c98ab18e0480f0c7d865 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 13 Mar 2009 22:13:49 +0000 Subject: [PATCH 3424/4982] ixgbe: fix bug with napi add before request_irq Occasionally if the driver was loaded in a system that didn't support MSI-X or MSI and was on a shared interrupt, the driver would then panic in NAPI on the first shared interrupt because we hadn't called napi_add yet. Solution: call napi_add before calling request_irq Signed-off-by: Jesse Brandeburg Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 76fd5c6db02..cd215200b0e 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2339,8 +2339,6 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) else ixgbe_configure_msi_and_legacy(adapter); - ixgbe_napi_add_all(adapter); - clear_bit(__IXGBE_DOWN, &adapter->state); ixgbe_napi_enable_all(adapter); @@ -2397,6 +2395,8 @@ int ixgbe_up(struct ixgbe_adapter *adapter) /* hardware has been reset, we need to reload some things */ ixgbe_configure(adapter); + ixgbe_napi_add_all(adapter); + return ixgbe_up_complete(adapter); } @@ -3426,6 +3426,8 @@ static int ixgbe_open(struct net_device *netdev) ixgbe_configure(adapter); + ixgbe_napi_add_all(adapter); + err = ixgbe_request_irq(adapter); if (err) goto err_req_irq; @@ -3480,6 +3482,7 @@ static int ixgbe_close(struct net_device *netdev) /** * ixgbe_napi_add_all - prep napi structs for use * @adapter: private struct + * * helper function to napi_add each possible q_vector->napi */ void ixgbe_napi_add_all(struct ixgbe_adapter *adapter) @@ -3552,7 +3555,6 @@ static int ixgbe_resume(struct pci_dev *pdev) return err; } - ixgbe_napi_add_all(adapter); ixgbe_reset(adapter); if (netif_running(netdev)) { -- GitLab From 9a1a69adad69ce4e85c9cbb40a3f960a7cb015cf Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 13 Mar 2009 22:14:10 +0000 Subject: [PATCH 3425/4982] ixgbe: Fix the Tx clean logic to return proper status The Tx accounting when cleaning during NAPI was not completely properly. We should use the work_limit to determine when to finish cleaning, and use the same to return the cleaned status. The impact of running like this causes the NAPI clean for this Tx to get stuck in a scheduling loop, and can result in Tx not getting cleaned, ending with a Tx hang and device reset. Signed-off-by: Jesse Brandeburg Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index cd215200b0e..d5563e4d3b3 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -251,6 +251,8 @@ static void ixgbe_tx_timeout(struct net_device *netdev); * ixgbe_clean_tx_irq - Reclaim resources after transmit completes * @adapter: board private structure * @tx_ring: tx ring to clean + * + * returns true if transmit work is done **/ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter, struct ixgbe_ring *tx_ring) @@ -266,7 +268,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter, eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); while ((eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) && - (count < tx_ring->count)) { + (count < tx_ring->work_limit)) { bool cleaned = false; for ( ; !cleaned; count++) { struct sk_buff *skb; @@ -328,8 +330,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter, } /* re-arm the interrupt */ - if ((total_packets >= tx_ring->work_limit) || - (count == tx_ring->count)) + if (count >= tx_ring->work_limit) IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, tx_ring->v_idx); tx_ring->total_bytes += total_bytes; @@ -338,7 +339,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter, tx_ring->stats.bytes += total_bytes; adapter->net_stats.tx_bytes += total_bytes; adapter->net_stats.tx_packets += total_packets; - return (total_packets ? true : false); + return (count < tx_ring->work_limit); } #ifdef CONFIG_IXGBE_DCA @@ -2590,10 +2591,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter) **/ static int ixgbe_poll(struct napi_struct *napi, int budget) { - struct ixgbe_q_vector *q_vector = container_of(napi, - struct ixgbe_q_vector, napi); + struct ixgbe_q_vector *q_vector = + container_of(napi, struct ixgbe_q_vector, napi); struct ixgbe_adapter *adapter = q_vector->adapter; - int tx_cleaned, work_done = 0; + int tx_clean_complete, work_done = 0; #ifdef CONFIG_IXGBE_DCA if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) { @@ -2602,10 +2603,10 @@ static int ixgbe_poll(struct napi_struct *napi, int budget) } #endif - tx_cleaned = ixgbe_clean_tx_irq(adapter, adapter->tx_ring); + tx_clean_complete = ixgbe_clean_tx_irq(adapter, adapter->tx_ring); ixgbe_clean_rx_irq(q_vector, adapter->rx_ring, &work_done, budget); - if (tx_cleaned) + if (!tx_clean_complete) work_done = budget; /* If budget not fully consumed, exit the polling mode */ -- GitLab From 2a41ff81162c7c406bb2a04e425a7ed51c85d89d Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 13 Mar 2009 22:14:30 +0000 Subject: [PATCH 3426/4982] ixgbe: Cleanup on the Rx init path This cleans up the following pieces of the Rx initialization path: - Enable the ECC memory fault interrupt in OTHER causes. - Fix an 82598 initialization of RDRXCTL when depending on RSS and VMDq to be enabled. We don't need these features enabled to safely set the MVMEN bit to allow multiple SRRCTL register mappings into the RXDCTL registers. - Fix the RSS initialization path to not stomp on DCB accidentally. When configuring the MRQC (multiple Rx queue contol) register, we want to make sure we only OR in features as necessary, instead of full assignment. Signed-off-by: Jesse Brandeburg Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index d5563e4d3b3..39781c84daf 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1464,6 +1464,7 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) mask |= IXGBE_EIMS_GPI_SDP1; if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + mask |= IXGBE_EIMS_ECC; mask |= IXGBE_EIMS_GPI_SDP1; mask |= IXGBE_EIMS_GPI_SDP2; } @@ -1795,12 +1796,9 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) * effects of setting this bit are only that SRRCTL must be * fully programmed [0..15] */ - if (adapter->flags & - (IXGBE_FLAG_RSS_ENABLED | IXGBE_FLAG_VMDQ_ENABLED)) { - rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); - rdrxctl |= IXGBE_RDRXCTL_MVMEN; - IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl); - } + rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); + rdrxctl |= IXGBE_RDRXCTL_MVMEN; + IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl); } /* Program MRQC for the distribution of queues */ @@ -1837,16 +1835,17 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) for (i = 0; i < 10; i++) IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), seed[i]); - mrqc = IXGBE_MRQC_RSSEN + if (hw->mac.type == ixgbe_mac_82598EB) + mrqc |= IXGBE_MRQC_RSSEN; /* Perform hash on these packet types */ - | IXGBE_MRQC_RSS_FIELD_IPV4 - | IXGBE_MRQC_RSS_FIELD_IPV4_TCP - | IXGBE_MRQC_RSS_FIELD_IPV4_UDP - | IXGBE_MRQC_RSS_FIELD_IPV6 - | IXGBE_MRQC_RSS_FIELD_IPV6_TCP - | IXGBE_MRQC_RSS_FIELD_IPV6_UDP; - IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); - } + mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4 + | IXGBE_MRQC_RSS_FIELD_IPV4_TCP + | IXGBE_MRQC_RSS_FIELD_IPV4_UDP + | IXGBE_MRQC_RSS_FIELD_IPV6 + | IXGBE_MRQC_RSS_FIELD_IPV6_TCP + | IXGBE_MRQC_RSS_FIELD_IPV6_UDP; + } + IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM); -- GitLab From 9891ca7cdc42354ec48c0f76256fdcc9808ffc7e Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 13 Mar 2009 22:14:50 +0000 Subject: [PATCH 3427/4982] ixgbe: Add a few safety nets for register writes and descriptor cleanups There are possible times that a driver may fail to completely initialize, due to a buggy platform or a buggy kernel. In those cases, we'd rather fail gracefully instead of a panic. Add a few safety checks to some critical paths to try and prevent a panic in these corner-case situations. Signed-off-by: Jesse Brandeburg Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 39781c84daf..892195f2ad9 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2458,8 +2458,10 @@ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter, rx_ring->next_to_clean = 0; rx_ring->next_to_use = 0; - writel(0, adapter->hw.hw_addr + rx_ring->head); - writel(0, adapter->hw.hw_addr + rx_ring->tail); + if (rx_ring->head) + writel(0, adapter->hw.hw_addr + rx_ring->head); + if (rx_ring->tail) + writel(0, adapter->hw.hw_addr + rx_ring->tail); } /** @@ -2490,8 +2492,10 @@ static void ixgbe_clean_tx_ring(struct ixgbe_adapter *adapter, tx_ring->next_to_use = 0; tx_ring->next_to_clean = 0; - writel(0, adapter->hw.hw_addr + tx_ring->head); - writel(0, adapter->hw.hw_addr + tx_ring->tail); + if (tx_ring->head) + writel(0, adapter->hw.hw_addr + tx_ring->head); + if (tx_ring->tail) + writel(0, adapter->hw.hw_addr + tx_ring->tail); } /** @@ -3327,7 +3331,8 @@ static void ixgbe_free_all_tx_resources(struct ixgbe_adapter *adapter) int i; for (i = 0; i < adapter->num_tx_queues; i++) - ixgbe_free_tx_resources(adapter, &adapter->tx_ring[i]); + if (adapter->tx_ring[i].desc) + ixgbe_free_tx_resources(adapter, &adapter->tx_ring[i]); } /** @@ -3363,7 +3368,8 @@ static void ixgbe_free_all_rx_resources(struct ixgbe_adapter *adapter) int i; for (i = 0; i < adapter->num_rx_queues; i++) - ixgbe_free_rx_resources(adapter, &adapter->rx_ring[i]); + if (adapter->rx_ring[i].desc) + ixgbe_free_rx_resources(adapter, &adapter->rx_ring[i]); } /** -- GitLab From 885125399e2c72b6466cfd2fbcb755be499b53a2 Mon Sep 17 00:00:00 2001 From: PJ Waskiewicz Date: Fri, 13 Mar 2009 22:15:10 +0000 Subject: [PATCH 3428/4982] ixgbe: Two small fixes for 82599 when bringing the device down and for WoL The Tx DMA unit should be disabled when bringing the device down. Also, the KX4 device with 82599 supports WoL, so we should clear the Wake Up Status (WUS) after a PCIe slot reset. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jesse Brandeburg Acked-by: Mallikarjuna R Chilakala Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 892195f2ad9..3e981a1b0cd 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2558,6 +2558,11 @@ void ixgbe_down(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), (txdctl & ~IXGBE_TXDCTL_ENABLE)); } + /* Disable the Tx DMA engine on 82599 */ + if (hw->mac.type == ixgbe_mac_82599EB) + IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, + (IXGBE_READ_REG(hw, IXGBE_DMATXCTL) & + ~IXGBE_DMATXCTL_TE)); netif_carrier_off(netdev); @@ -4794,7 +4799,7 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev) pci_enable_wake(pdev, PCI_D3cold, 0); ixgbe_reset(adapter); - + IXGBE_WRITE_REG(&adapter->hw, IXGBE_WUS, ~0); result = PCI_ERS_RESULT_RECOVERED; } -- GitLab From 4df1046622797804150327bada9fdc564c090417 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 13 Mar 2009 22:15:31 +0000 Subject: [PATCH 3429/4982] ixgbe: Cleanup some whitespace issues, fixup and add some comments Cleanup a bit of whitespace, add some function header comments, and fix a few comments around the driver. Signed-off-by: Jesse Brandeburg Signed-off-by: Peter P Waskiewicz Jr Acked-by: Mallikarjuna R Chilakala Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_82599.c | 5 ++--- drivers/net/ixgbe/ixgbe_main.c | 31 +++++++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index 56efa98fe3b..beae7e01260 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -404,8 +404,7 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw) { s32 status = 0; ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_82599_AUTONEG; - status = ixgbe_setup_mac_link_speed_multispeed_fiber(hw, - link_speed, + status = ixgbe_setup_mac_link_speed_multispeed_fiber(hw, link_speed, true, true); return status; } @@ -759,7 +758,7 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw) hw->mac.orig_autoc = autoc; hw->mac.orig_autoc2 = autoc2; hw->mac.orig_link_settings_stored = true; - } else { + } else { if (autoc != hw->mac.orig_autoc) IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (hw->mac.orig_autoc | IXGBE_AUTOC_AN_RESTART)); diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 3e981a1b0cd..0b2b609fad8 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -779,7 +779,8 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; - /* Populate the IVAR table and set the ITR values to the + /* + * Populate the IVAR table and set the ITR values to the * corresponding register. */ for (v_idx = 0; v_idx < q_vectors; v_idx++) { @@ -814,7 +815,7 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) q_vector->eitr = adapter->eitr_param; /* - * since ths is initial set up don't need to call + * since this is initial set up don't need to call * ixgbe_write_eitr helper */ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(v_idx), @@ -2675,6 +2676,14 @@ static inline bool ixgbe_set_dcb_queues(struct ixgbe_adapter *adapter) } #endif +/** + * ixgbe_set_rss_queues: Allocate queues for RSS + * @adapter: board private structure to initialize + * + * This is our "base" multiqueue mode. RSS (Receive Side Scaling) will try + * to allocate one Rx queue per CPU, and if available, one Tx queue per CPU. + * + **/ static inline bool ixgbe_set_rss_queues(struct ixgbe_adapter *adapter) { bool ret = false; @@ -2693,6 +2702,17 @@ static inline bool ixgbe_set_rss_queues(struct ixgbe_adapter *adapter) return ret; } +/* + * ixgbe_set_num_queues: Allocate queues for device, feature dependant + * @adapter: board private structure to initialize + * + * This is the top level queue allocation routine. The order here is very + * important, starting with the "most" number of features turned on at once, + * and ending with the smallest set of features. This way large combinations + * can be allocated if they're turned on, and smaller combinations are the + * fallthrough conditions. + * + **/ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter) { /* Start with base case */ @@ -2856,7 +2876,8 @@ static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter) * @adapter: board private structure to initialize * * We allocate one ring per queue at run-time since we don't know the - * number of queues at compile-time. + * number of queues at compile-time. The polling_netdev array is + * intended for Multiqueue, but should work fine with a single queue. **/ static int ixgbe_alloc_queues(struct ixgbe_adapter *adapter) { @@ -3035,7 +3056,8 @@ static void ixgbe_sfp_timer(unsigned long data) { struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)data; - /* Do the sfp_timer outside of interrupt context due to the + /* + * Do the sfp_timer outside of interrupt context due to the * delays that sfp+ detection requires */ schedule_work(&adapter->sfp_task); @@ -3609,6 +3631,7 @@ static int ixgbe_suspend(struct pci_dev *pdev, pm_message_t state) retval = pci_save_state(pdev); if (retval) return retval; + #endif if (wufc) { ixgbe_set_rx_mode(netdev); -- GitLab From 09e1c061484005aa26264c3f82f2c83a273c4094 Mon Sep 17 00:00:00 2001 From: PJ Waskiewicz Date: Fri, 13 Mar 2009 22:15:54 +0000 Subject: [PATCH 3430/4982] ixgbe: Add documentation for the driver Documentation for the ixgbe driver in the kernel docs area is missing. This adds that documentation. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- Documentation/networking/ixgbe.txt | 199 +++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 Documentation/networking/ixgbe.txt diff --git a/Documentation/networking/ixgbe.txt b/Documentation/networking/ixgbe.txt new file mode 100644 index 00000000000..eeb68685c78 --- /dev/null +++ b/Documentation/networking/ixgbe.txt @@ -0,0 +1,199 @@ +Linux Base Driver for 10 Gigabit PCI Express Intel(R) Network Connection +======================================================================== + +March 10, 2009 + + +Contents +======== + +- In This Release +- Identifying Your Adapter +- Building and Installation +- Additional Configurations +- Support + + + +In This Release +=============== + +This file describes the ixgbe Linux Base Driver for the 10 Gigabit PCI +Express Intel(R) Network Connection. This driver includes support for +Itanium(R)2-based systems. + +For questions related to hardware requirements, refer to the documentation +supplied with your 10 Gigabit adapter. All hardware requirements listed apply +to use with Linux. + +The following features are available in this kernel: + - Native VLANs + - Channel Bonding (teaming) + - SNMP + - Generic Receive Offload + - Data Center Bridging + +Channel Bonding documentation can be found in the Linux kernel source: +/Documentation/networking/bonding.txt + +Ethtool, lspci, and ifconfig can be used to display device and driver +specific information. + + +Identifying Your Adapter +======================== + +This driver supports devices based on the 82598 controller and the 82599 +controller. + +For specific information on identifying which adapter you have, please visit: + + http://support.intel.com/support/network/sb/CS-008441.htm + + +Building and Installation +========================= + +select m for "Intel(R) 10GbE PCI Express adapters support" located at: + Location: + -> Device Drivers + -> Network device support (NETDEVICES [=y]) + -> Ethernet (10000 Mbit) (NETDEV_10000 [=y]) + +1. make modules & make modules_install + +2. Load the module: + +# modprobe ixgbe + + The insmod command can be used if the full + path to the driver module is specified. For example: + + insmod /lib/modules//kernel/drivers/net/ixgbe/ixgbe.ko + + With 2.6 based kernels also make sure that older ixgbe drivers are + removed from the kernel, before loading the new module: + + rmmod ixgbe; modprobe ixgbe + +3. Assign an IP address to the interface by entering the following, where + x is the interface number: + + ifconfig ethx + +4. Verify that the interface works. Enter the following, where + is the IP address for another machine on the same subnet as the interface + that is being tested: + + ping + + +Additional Configurations +========================= + + Viewing Link Messages + --------------------- + Link messages will not be displayed to the console if the distribution is + restricting system messages. In order to see network driver link messages on + your console, set dmesg to eight by entering the following: + + dmesg -n 8 + + NOTE: This setting is not saved across reboots. + + + Jumbo Frames + ------------ + The driver supports Jumbo Frames for all adapters. Jumbo Frames support is + enabled by changing the MTU to a value larger than the default of 1500. + The maximum value for the MTU is 16110. Use the ifconfig command to + increase the MTU size. For example: + + ifconfig ethx mtu 9000 up + + The maximum MTU setting for Jumbo Frames is 16110. This value coincides + with the maximum Jumbo Frames size of 16128. + + Generic Receive Offload, aka GRO + -------------------------------- + The driver supports the in-kernel software implementation of GRO. GRO has + shown that by coalescing Rx traffic into larger chunks of data, CPU + utilization can be significantly reduced when under large Rx load. GRO is an + evolution of the previously-used LRO interface. GRO is able to coalesce + other protocols besides TCP. It's also safe to use with configurations that + are problematic for LRO, namely bridging and iSCSI. + + GRO is enabled by default in the driver. Future versions of ethtool will + support disabling and re-enabling GRO on the fly. + + + Data Center Bridging, aka DCB + ----------------------------- + + DCB is a configuration Quality of Service implementation in hardware. + It uses the VLAN priority tag (802.1p) to filter traffic. That means + that there are 8 different priorities that traffic can be filtered into. + It also enables priority flow control which can limit or eliminate the + number of dropped packets during network stress. Bandwidth can be + allocated to each of these priorities, which is enforced at the hardware + level. + + To enable DCB support in ixgbe, you must enable the DCB netlink layer to + allow the userspace tools (see below) to communicate with the driver. + This can be found in the kernel configuration here: + + -> Networking support + -> Networking options + -> Data Center Bridging support + + Once this is selected, DCB support must be selected for ixgbe. This can + be found here: + + -> Device Drivers + -> Network device support (NETDEVICES [=y]) + -> Ethernet (10000 Mbit) (NETDEV_10000 [=y]) + -> Intel(R) 10GbE PCI Express adapters support + -> Data Center Bridging (DCB) Support + + After these options are selected, you must rebuild your kernel and your + modules. + + In order to use DCB, userspace tools must be downloaded and installed. + The dcbd tools can be found at: + + http://e1000.sf.net + + + Ethtool + ------- + The driver utilizes the ethtool interface for driver configuration and + diagnostics, as well as displaying statistical information. Ethtool + version 3.0 or later is required for this functionality. + + The latest release of ethtool can be found from + http://sourceforge.net/projects/gkernel. + + + NAPI + ---- + + NAPI (Rx polling mode) is supported in the ixgbe driver. NAPI is enabled + by default in the driver. + + See www.cyberus.ca/~hadi/usenix-paper.tgz for more information on NAPI. + + +Support +======= + +For general information, go to the Intel support website at: + + http://support.intel.com + +or the Intel Wired Networking project hosted by Sourceforge at: + + http://e1000.sourceforge.net + +If an issue is identified with the released source code on the supported +kernel with a supported adapter, email the specific information related +to the issue to e1000-devel@lists.sf.net -- GitLab From 87092698c665e0a358caf9825ae13114343027e8 Mon Sep 17 00:00:00 2001 From: un'ichi Nomura Date: Mon, 9 Mar 2009 10:40:52 +0100 Subject: [PATCH 3431/4982] block: Add gfp_mask parameter to bio_integrity_clone() Stricter gfp_mask might be required for clone allocation. For example, request-based dm may clone bio in interrupt context so it has to use GFP_ATOMIC. Signed-off-by: Kiyoshi Ueda Signed-off-by: Jun'ichi Nomura Acked-by: Martin K. Petersen Cc: Alasdair G Kergon Signed-off-by: Jens Axboe --- fs/bio-integrity.c | 5 +++-- fs/bio.c | 2 +- include/linux/bio.h | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index 549b0144da1..fe2b1aa2464 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c @@ -685,19 +685,20 @@ EXPORT_SYMBOL(bio_integrity_split); * bio_integrity_clone - Callback for cloning bios with integrity metadata * @bio: New bio * @bio_src: Original bio + * @gfp_mask: Memory allocation mask * @bs: bio_set to allocate bip from * * Description: Called to allocate a bip when cloning a bio */ int bio_integrity_clone(struct bio *bio, struct bio *bio_src, - struct bio_set *bs) + gfp_t gfp_mask, struct bio_set *bs) { struct bio_integrity_payload *bip_src = bio_src->bi_integrity; struct bio_integrity_payload *bip; BUG_ON(bip_src == NULL); - bip = bio_integrity_alloc_bioset(bio, GFP_NOIO, bip_src->bip_vcnt, bs); + bip = bio_integrity_alloc_bioset(bio, gfp_mask, bip_src->bip_vcnt, bs); if (bip == NULL) return -EIO; diff --git a/fs/bio.c b/fs/bio.c index 124b95c4d58..cf747378b97 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -463,7 +463,7 @@ struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask) if (bio_integrity(bio)) { int ret; - ret = bio_integrity_clone(b, bio, fs_bio_set); + ret = bio_integrity_clone(b, bio, gfp_mask, fs_bio_set); if (ret < 0) return NULL; diff --git a/include/linux/bio.h b/include/linux/bio.h index 1b16108a541..d8bd43bfdcf 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -531,7 +531,7 @@ extern void bio_integrity_endio(struct bio *, int); extern void bio_integrity_advance(struct bio *, unsigned int); extern void bio_integrity_trim(struct bio *, unsigned int, unsigned int); extern void bio_integrity_split(struct bio *, struct bio_pair *, int); -extern int bio_integrity_clone(struct bio *, struct bio *, struct bio_set *); +extern int bio_integrity_clone(struct bio *, struct bio *, gfp_t, struct bio_set *); extern int bioset_integrity_create(struct bio_set *, int); extern void bioset_integrity_free(struct bio_set *); extern void bio_integrity_init_slab(void); @@ -542,7 +542,7 @@ extern void bio_integrity_init_slab(void); #define bioset_integrity_create(a, b) (0) #define bio_integrity_prep(a) (0) #define bio_integrity_enabled(a) (0) -#define bio_integrity_clone(a, b, c) (0) +#define bio_integrity_clone(a, b, c,d ) (0) #define bioset_integrity_free(a) do { } while (0) #define bio_integrity_free(a, b) do { } while (0) #define bio_integrity_endio(a, b) do { } while (0) -- GitLab From 059ea3318c8ede71851a52b4359fbf1ab0cec301 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 9 Mar 2009 10:42:45 +0100 Subject: [PATCH 3432/4982] block: fix memory leak in bio_clone() If bio_integrity_clone() fails, bio_clone() returns NULL without freeing the newly allocated bio. Signed-off-by: Li Zefan Signed-off-by: Jens Axboe --- fs/bio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/bio.c b/fs/bio.c index cf747378b97..d4f06327c81 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -465,8 +465,10 @@ struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask) ret = bio_integrity_clone(b, bio, gfp_mask, fs_bio_set); - if (ret < 0) + if (ret < 0) { + bio_put(b); return NULL; + } } return b; -- GitLab From bfbd442f69ec9c58590ffc6e93ac8d6809caa48b Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 9 Mar 2009 13:42:24 +0100 Subject: [PATCH 3433/4982] Fix Xilinx SystemACE driver to handle empty CF slot The SystemACE driver does not handle an empty CF slot gracefully. An empty CF slot ends up hanging the system. This patch adds a check for the CF state and stops trying to process requests if the slot is empty. Signed-off-by: Grant Likely Signed-off-by: Jens Axboe --- drivers/block/xsysace.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 381d686fc1a..119be3442f2 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -489,6 +489,28 @@ static void ace_fsm_dostate(struct ace_device *ace) ace->fsm_state, ace->id_req_count); #endif + /* Verify that there is actually a CF in the slot. If not, then + * bail out back to the idle state and wake up all the waiters */ + status = ace_in32(ace, ACE_STATUS); + if ((status & ACE_STATUS_CFDETECT) == 0) { + ace->fsm_state = ACE_FSM_STATE_IDLE; + ace->media_change = 1; + set_capacity(ace->gd, 0); + dev_info(ace->dev, "No CF in slot\n"); + + /* Drop all pending requests */ + while ((req = elv_next_request(ace->queue)) != NULL) + end_request(req, 0); + + /* Drop back to IDLE state and notify waiters */ + ace->fsm_state = ACE_FSM_STATE_IDLE; + ace->id_result = -EIO; + while (ace->id_req_count) { + complete(&ace->id_completion); + ace->id_req_count--; + } + } + switch (ace->fsm_state) { case ACE_FSM_STATE_IDLE: /* See if there is anything to do */ -- GitLab From fbb52f2272e6265295f0e5f6187b628e4c162eca Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Fri, 13 Mar 2009 14:52:01 +0000 Subject: [PATCH 3434/4982] netxen: fix endianness in serial number Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_hw.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index a93ab589d9c..8db4ac34414 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -2268,7 +2268,7 @@ void netxen_nic_get_firmware_info(struct netxen_adapter *adapter) u32 fw_major, fw_minor, fw_build; char brd_name[NETXEN_MAX_SHORT_NAME]; char serial_num[32]; - int i, addr; + int i, addr, val; int *ptr32; struct pci_dev *pdev = adapter->pdev; @@ -2278,14 +2278,12 @@ void netxen_nic_get_firmware_info(struct netxen_adapter *adapter) addr = NETXEN_USER_START + offsetof(struct netxen_new_user_info, serial_num); for (i = 0; i < 8; i++) { - if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) { - printk("%s: ERROR reading %s board userarea.\n", - netxen_nic_driver_name, - netxen_nic_driver_name); + if (netxen_rom_fast_read(adapter, addr, &val) == -1) { + dev_err(&pdev->dev, "error reading board info\n"); adapter->driver_mismatch = 1; return; } - ptr32++; + ptr32[i] = cpu_to_le32(val); addr += sizeof(u32); } -- GitLab From 0b72e659a10ec50acbef90756bf04177b66c8266 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Fri, 13 Mar 2009 14:52:02 +0000 Subject: [PATCH 3435/4982] netxen: add suspend resume support Detach network interface on PCI suspend and recreate hardware context after resumes. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 1 + drivers/net/netxen/netxen_nic_hw.c | 17 +++++ drivers/net/netxen/netxen_nic_main.c | 102 ++++++++++++++++++++++----- 3 files changed, 102 insertions(+), 18 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 618507074bd..75cb30f27ae 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -1389,6 +1389,7 @@ void netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index, u32 *value); int netxen_nic_get_board_info(struct netxen_adapter *adapter); void netxen_nic_get_firmware_info(struct netxen_adapter *adapter); +int netxen_nic_wol_supported(struct netxen_adapter *adapter); int netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, ulong off, void *data, int len); diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 8db4ac34414..c8faa53d27a 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -2320,3 +2320,20 @@ void netxen_nic_get_firmware_info(struct netxen_adapter *adapter) } } +int +netxen_nic_wol_supported(struct netxen_adapter *adapter) +{ + u32 wol_cfg; + + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) + return 0; + + wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG_NV); + if (wol_cfg & (1UL << adapter->portnum)) { + wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG); + if (wol_cfg & (1 << adapter->portnum)) + return 1; + } + + return 0; +} diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 9445277321d..555b4596b0f 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -643,6 +643,18 @@ netxen_start_firmware(struct netxen_adapter *adapter) int val, err, first_boot; struct pci_dev *pdev = adapter->pdev; + int first_driver = 0; + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { + if (adapter->ahw.pci_func == 0) + first_driver = 1; + } else { + if (adapter->portnum == 0) + first_driver = 1; + } + + if (!first_driver) + return 0; + first_boot = adapter->pci_read_normalize(adapter, NETXEN_CAM_RAM(0x1fc)); @@ -859,7 +871,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct net_device *netdev = NULL; struct netxen_adapter *adapter = NULL; int i = 0, err; - int first_driver; int pci_func_id = PCI_FUNC(pdev->devfn); uint8_t revision_id; @@ -978,20 +989,9 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) */ netxen_check_options(adapter); - first_driver = 0; - if (NX_IS_REVISION_P3(revision_id)) { - if (adapter->ahw.pci_func == 0) - first_driver = 1; - } else { - if (adapter->portnum == 0) - first_driver = 1; - } - - if (first_driver) { - err = netxen_start_firmware(adapter); - if (err) - goto err_out_iounmap; - } + err = netxen_start_firmware(adapter); + if (err) + goto err_out_iounmap; nx_update_dma_mask(adapter); @@ -1062,8 +1062,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err_out_disable_msi: netxen_teardown_intr(adapter); - if (first_driver) - netxen_free_adapter_offload(adapter); + netxen_free_adapter_offload(adapter); err_out_iounmap: netxen_cleanup_pci_map(adapter); @@ -1114,6 +1113,71 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) free_netdev(netdev); } +static int +netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state) +{ + + struct netxen_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; + + netif_device_detach(netdev); + + if (netif_running(netdev)) + netxen_nic_down(adapter, netdev); + + if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) + netxen_nic_detach(adapter); + + pci_save_state(pdev); + + if (netxen_nic_wol_supported(adapter)) { + pci_enable_wake(pdev, PCI_D3cold, 1); + pci_enable_wake(pdev, PCI_D3hot, 1); + } + + pci_disable_device(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + + return 0; +} + +static int +netxen_nic_resume(struct pci_dev *pdev) +{ + struct netxen_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; + int err; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + err = pci_enable_device(pdev); + if (err) + return err; + + adapter->curr_window = 255; + + err = netxen_start_firmware(adapter); + if (err) { + dev_err(&pdev->dev, "failed to start firmware\n"); + return err; + } + + if (netif_running(netdev)) { + err = netxen_nic_attach(adapter); + if (err) + return err; + + err = netxen_nic_up(adapter, netdev); + if (err) + return err; + + netif_device_attach(netdev); + } + + return 0; +} + static int netxen_nic_open(struct net_device *netdev) { struct netxen_adapter *adapter = netdev_priv(netdev); @@ -1649,7 +1713,9 @@ static struct pci_driver netxen_driver = { .name = netxen_nic_driver_name, .id_table = netxen_pci_tbl, .probe = netxen_nic_probe, - .remove = __devexit_p(netxen_nic_remove) + .remove = __devexit_p(netxen_nic_remove), + .suspend = netxen_nic_suspend, + .resume = netxen_nic_resume }; /* Driver Registration on NetXen card */ -- GitLab From 438627c77b877e445a4b918a50ff910a5ea2a12d Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Fri, 13 Mar 2009 14:52:03 +0000 Subject: [PATCH 3436/4982] netxen: sanitize variable names o remove max_ prefix from ring sizes, since they don't really represent max possible sizes. o cleanup naming of rx ring types (normal, jumbo, lro). o simplify logic to choose rx ring size, gig ports get half rx ring of 10 gig ports. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 47 ++++++---------- drivers/net/netxen/netxen_nic_ctx.c | 16 +++--- drivers/net/netxen/netxen_nic_ethtool.c | 6 +- drivers/net/netxen/netxen_nic_hw.c | 2 +- drivers/net/netxen/netxen_nic_init.c | 54 ++++++++---------- drivers/net/netxen/netxen_nic_main.c | 73 ++++--------------------- 6 files changed, 62 insertions(+), 136 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 75cb30f27ae..f00efe84744 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -79,15 +79,15 @@ #define PHAN_VENDOR_ID 0x4040 #define RCV_DESC_RINGSIZE \ - (sizeof(struct rcv_desc) * adapter->max_rx_desc_count) + (sizeof(struct rcv_desc) * adapter->num_rxd) #define STATUS_DESC_RINGSIZE \ - (sizeof(struct status_desc)* adapter->max_rx_desc_count) + (sizeof(struct status_desc) * adapter->num_rxd) #define LRO_DESC_RINGSIZE \ - (sizeof(rcvDesc_t) * adapter->max_lro_rx_desc_count) + (sizeof(rcvDesc_t) * adapter->num_lro_rxd) #define TX_RINGSIZE \ - (sizeof(struct netxen_cmd_buffer) * adapter->max_tx_desc_count) + (sizeof(struct netxen_cmd_buffer) * adapter->num_txd) #define RCV_BUFFSIZE \ - (sizeof(struct netxen_rx_buffer) * rds_ring->max_rx_desc_count) + (sizeof(struct netxen_rx_buffer) * rds_ring->num_desc) #define find_diff_among(a,b,range) ((a)<(b)?((b)-(a)):((b)+(range)-(a))) #define NETXEN_RCV_PRODUCER_OFFSET 0 @@ -190,20 +190,9 @@ #define NUM_RCV_DESC_RINGS 3 /* No of Rcv Descriptor contexts */ -/* descriptor types */ -#define RCV_DESC_NORMAL 0x01 -#define RCV_DESC_JUMBO 0x02 -#define RCV_DESC_LRO 0x04 -#define RCV_DESC_NORMAL_CTXID 0 -#define RCV_DESC_JUMBO_CTXID 1 -#define RCV_DESC_LRO_CTXID 2 - -#define RCV_DESC_TYPE(ID) \ - ((ID == RCV_DESC_JUMBO_CTXID) \ - ? RCV_DESC_JUMBO \ - : ((ID == RCV_DESC_LRO_CTXID) \ - ? RCV_DESC_LRO : \ - (RCV_DESC_NORMAL))) +#define RCV_RING_NORMAL 0 +#define RCV_RING_JUMBO 1 +#define RCV_RING_LRO 2 #define MAX_CMD_DESCRIPTORS 4096 #define MAX_RCV_DESCRIPTORS 16384 @@ -815,8 +804,6 @@ struct netxen_hardware_context { int pci_func; }; -#define RCV_RING_LRO RCV_DESC_LRO - #define MINIMUM_ETHERNET_FRAME_SIZE 64 /* With FCS */ #define ETHERNET_FCS_SIZE 4 @@ -842,16 +829,16 @@ struct netxen_adapter_stats { * be one Rcv Descriptor for normal packets, one for jumbo and may be others. */ struct nx_host_rds_ring { - u32 flags; u32 producer; - dma_addr_t phys_addr; u32 crb_rcv_producer; /* reg offset */ struct rcv_desc *desc_head; /* address of rx ring in Phantom */ - u32 max_rx_desc_count; - u32 dma_size; - u32 skb_size; struct netxen_rx_buffer *rx_buf_arr; /* rx buffers for receive */ struct list_head free_list; + u32 num_desc; + u32 dma_size; + u32 skb_size; + u32 flags; + dma_addr_t phys_addr; }; /* @@ -1244,10 +1231,10 @@ struct netxen_adapter { u32 crb_addr_cmd_producer; u32 crb_addr_cmd_consumer; - u32 max_tx_desc_count; - u32 max_rx_desc_count; - u32 max_jumbo_rx_desc_count; - u32 max_lro_rx_desc_count; + u32 num_txd; + u32 num_rxd; + u32 num_jumbo_rxd; + u32 num_lro_rxd; int max_rds_rings; diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c index d125dca0131..2e66335bd00 100644 --- a/drivers/net/netxen/netxen_nic_ctx.c +++ b/drivers/net/netxen/netxen_nic_ctx.c @@ -231,7 +231,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) rds_ring = &recv_ctx->rds_rings[i]; prq_rds[i].host_phys_addr = cpu_to_le64(rds_ring->phys_addr); - prq_rds[i].ring_size = cpu_to_le32(rds_ring->max_rx_desc_count); + prq_rds[i].ring_size = cpu_to_le32(rds_ring->num_desc); prq_rds[i].ring_kind = cpu_to_le32(i); prq_rds[i].buff_size = cpu_to_le64(rds_ring->dma_size); } @@ -241,7 +241,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) prq_sds[0].host_phys_addr = cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr); - prq_sds[0].ring_size = cpu_to_le32(adapter->max_rx_desc_count); + prq_sds[0].ring_size = cpu_to_le32(adapter->num_rxd); /* only one msix vector for now */ prq_sds[0].msi_index = cpu_to_le16(0); @@ -362,7 +362,7 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter) prq_cds->host_phys_addr = cpu_to_le64(adapter->ahw.cmd_desc_phys_addr); - prq_cds->ring_size = cpu_to_le32(adapter->max_tx_desc_count); + prq_cds->ring_size = cpu_to_le32(adapter->num_txd); phys_addr = rq_phys_addr; err = netxen_issue_cmd(adapter, @@ -494,7 +494,7 @@ netxen_init_old_ctx(struct netxen_adapter *adapter) adapter->ctx_desc->cmd_ring_addr = cpu_to_le64(adapter->ahw.cmd_desc_phys_addr); adapter->ctx_desc->cmd_ring_size = - cpu_to_le32(adapter->max_tx_desc_count); + cpu_to_le32(adapter->num_txd); recv_ctx = &adapter->recv_ctx; @@ -504,12 +504,12 @@ netxen_init_old_ctx(struct netxen_adapter *adapter) adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr = cpu_to_le64(rds_ring->phys_addr); adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size = - cpu_to_le32(rds_ring->max_rx_desc_count); + cpu_to_le32(rds_ring->num_desc); } adapter->ctx_desc->sts_ring_addr = cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr); adapter->ctx_desc->sts_ring_size = - cpu_to_le32(adapter->max_rx_desc_count); + cpu_to_le32(adapter->num_rxd); adapter->pci_write_normalize(adapter, CRB_CTX_ADDR_REG_LO(func_id), lower32(adapter->ctx_desc_phys_addr)); @@ -562,7 +562,7 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) /* cmd desc ring */ addr = pci_alloc_consistent(adapter->pdev, sizeof(struct cmd_desc_type0) * - adapter->max_tx_desc_count, + adapter->num_txd, &hw->cmd_desc_phys_addr); if (addr == NULL) { @@ -669,7 +669,7 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter) if (adapter->ahw.cmd_desc_head != NULL) { pci_free_consistent(adapter->pdev, sizeof(struct cmd_desc_type0) * - adapter->max_tx_desc_count, + adapter->num_txd, adapter->ahw.cmd_desc_head, adapter->ahw.cmd_desc_phys_addr); adapter->ahw.cmd_desc_head = NULL; diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index 8b4bdfd6a11..a677ff89518 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -477,10 +477,10 @@ netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring) ring->rx_pending = 0; ring->rx_jumbo_pending = 0; ring->rx_pending += adapter->recv_ctx. - rds_rings[RCV_DESC_NORMAL_CTXID].max_rx_desc_count; + rds_rings[RCV_RING_NORMAL].num_desc; ring->rx_jumbo_pending += adapter->recv_ctx. - rds_rings[RCV_DESC_JUMBO_CTXID].max_rx_desc_count; - ring->tx_pending = adapter->max_tx_desc_count; + rds_rings[RCV_RING_JUMBO].num_desc; + ring->tx_pending = adapter->num_txd; if (adapter->ahw.port_type == NETXEN_NIC_GBE) ring->rx_max_pending = MAX_RCV_DESCRIPTORS_1G; diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index c8faa53d27a..cea7300426b 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -515,7 +515,7 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter, &cmd_desc_arr[i], sizeof(struct cmd_desc_type0)); producer = get_next_index(producer, - adapter->max_tx_desc_count); + adapter->num_txd); i++; } while (i != nr_elements); diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 120b480c1e8..d722589b1ce 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -153,7 +153,7 @@ void netxen_release_rx_buffers(struct netxen_adapter *adapter) recv_ctx = &adapter->recv_ctx; for (ring = 0; ring < adapter->max_rds_rings; ring++) { rds_ring = &recv_ctx->rds_rings[ring]; - for (i = 0; i < rds_ring->max_rx_desc_count; ++i) { + for (i = 0; i < rds_ring->num_desc; ++i) { rx_buf = &(rds_ring->rx_buf_arr[i]); if (rx_buf->state == NETXEN_BUFFER_FREE) continue; @@ -174,7 +174,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter) int i, j; cmd_buf = adapter->cmd_buf_arr; - for (i = 0; i < adapter->max_tx_desc_count; i++) { + for (i = 0; i < adapter->num_txd; i++) { buffrag = cmd_buf->frag_array; if (buffrag->dma) { pci_unmap_single(adapter->pdev, buffrag->dma, @@ -190,7 +190,6 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter) buffrag->dma = 0ULL; } } - /* Free the skb we received in netxen_nic_xmit_frame */ if (cmd_buf->skb) { dev_kfree_skb_any(cmd_buf->skb); cmd_buf->skb = NULL; @@ -241,11 +240,9 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) recv_ctx = &adapter->recv_ctx; for (ring = 0; ring < adapter->max_rds_rings; ring++) { rds_ring = &recv_ctx->rds_rings[ring]; - switch (RCV_DESC_TYPE(ring)) { - case RCV_DESC_NORMAL: - rds_ring->max_rx_desc_count = - adapter->max_rx_desc_count; - rds_ring->flags = RCV_DESC_NORMAL; + switch (ring) { + case RCV_RING_NORMAL: + rds_ring->num_desc = adapter->num_rxd; if (adapter->ahw.cut_through) { rds_ring->dma_size = NX_CT_DEFAULT_RX_BUF_LEN; @@ -258,10 +255,8 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) } break; - case RCV_DESC_JUMBO: - rds_ring->max_rx_desc_count = - adapter->max_jumbo_rx_desc_count; - rds_ring->flags = RCV_DESC_JUMBO; + case RCV_RING_JUMBO: + rds_ring->num_desc = adapter->num_jumbo_rxd; if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) rds_ring->dma_size = NX_P3_RX_JUMBO_BUF_MAX_LEN; @@ -273,9 +268,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) break; case RCV_RING_LRO: - rds_ring->max_rx_desc_count = - adapter->max_lro_rx_desc_count; - rds_ring->flags = RCV_DESC_LRO; + rds_ring->num_desc = adapter->num_lro_rxd; rds_ring->dma_size = RX_LRO_DMA_MAP_LEN; rds_ring->skb_size = MAX_RX_LRO_BUFFER_LENGTH; break; @@ -296,7 +289,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) * Now go through all of them, set reference handles * and put them in the queues. */ - num_rx_bufs = rds_ring->max_rx_desc_count; + num_rx_bufs = rds_ring->num_desc; rx_buf = rds_ring->rx_buf_arr; for (i = 0; i < num_rx_bufs; i++) { list_add_tail(&rx_buf->list, @@ -848,16 +841,15 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, struct nx_host_rds_ring *rds_ring; desc_ctx = netxen_get_sts_type(sts_data); - if (unlikely(desc_ctx >= NUM_RCV_DESC_RINGS)) { + if (unlikely(desc_ctx >= adapter->max_rds_rings)) return; - } rds_ring = &recv_ctx->rds_rings[desc_ctx]; - if (unlikely(index > rds_ring->max_rx_desc_count)) { + if (unlikely(index > rds_ring->num_desc)) return; - } + buffer = &rds_ring->rx_buf_arr[index]; - if (desc_ctx == RCV_DESC_LRO_CTXID) { + if (desc_ctx == RCV_RING_LRO) { buffer->lro_current_frags++; if (netxen_get_sts_desc_lro_last_frag(desc)) { buffer->lro_expected_frags = @@ -875,7 +867,7 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, if (!skb) return; - if (desc_ctx == RCV_DESC_LRO_CTXID) { + if (desc_ctx == RCV_RING_LRO) { /* True length was only available on the last pkt */ skb_put(skb, buffer->lro_length); } else { @@ -921,8 +913,7 @@ netxen_process_rcv_ring(struct netxen_adapter *adapter, int max) desc->status_desc_data = cpu_to_le64(STATUS_OWNER_PHANTOM); - consumer = get_next_index(consumer, - adapter->max_rx_desc_count); + consumer = get_next_index(consumer, adapter->num_rxd); count++; } @@ -973,7 +964,7 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter) } last_consumer = get_next_index(last_consumer, - adapter->max_tx_desc_count); + adapter->num_txd); if (++count >= MAX_STATUS_HANDLE) break; } @@ -1060,7 +1051,7 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid) pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); - producer = get_next_index(producer, rds_ring->max_rx_desc_count); + producer = get_next_index(producer, rds_ring->num_desc); } /* if we did allocate buffers, then write the count to Phantom */ if (count) { @@ -1068,7 +1059,7 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid) /* Window = 1 */ adapter->pci_write_normalize(adapter, rds_ring->crb_rcv_producer, - (producer-1) & (rds_ring->max_rx_desc_count-1)); + (producer-1) & (rds_ring->num_desc-1)); if (adapter->fw_major < 4) { /* @@ -1079,9 +1070,8 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid) netxen_set_msg_peg_id(msg, NETXEN_RCV_PEG_DB_ID); netxen_set_msg_privid(msg); netxen_set_msg_count(msg, - ((producer - - 1) & (rds_ring-> - max_rx_desc_count - 1))); + ((producer - 1) & + (rds_ring->num_desc - 1))); netxen_set_msg_ctxid(msg, adapter->portnum); netxen_set_msg_opcode(msg, NETXEN_RCV_PRODUCER(ringid)); writel(msg, @@ -1141,7 +1131,7 @@ netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, uint32_t ringid) pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); pdesc->addr_buffer = cpu_to_le64(buffer->dma); - producer = get_next_index(producer, rds_ring->max_rx_desc_count); + producer = get_next_index(producer, rds_ring->num_desc); } /* if we did allocate buffers, then write the count to Phantom */ @@ -1150,7 +1140,7 @@ netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, uint32_t ringid) /* Window = 1 */ adapter->pci_write_normalize(adapter, rds_ring->crb_rcv_producer, - (producer-1) & (rds_ring->max_rx_desc_count-1)); + (producer - 1) & (rds_ring->num_desc - 1)); wmb(); } } diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 555b4596b0f..00eaeee235e 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -212,62 +212,19 @@ nx_update_dma_mask(struct netxen_adapter *adapter) static void netxen_check_options(struct netxen_adapter *adapter) { - switch (adapter->ahw.board_type) { - case NETXEN_BRDTYPE_P3_HMEZ: - case NETXEN_BRDTYPE_P3_XG_LOM: - case NETXEN_BRDTYPE_P3_10G_CX4: - case NETXEN_BRDTYPE_P3_10G_CX4_LP: - case NETXEN_BRDTYPE_P3_IMEZ: - case NETXEN_BRDTYPE_P3_10G_SFP_PLUS: - case NETXEN_BRDTYPE_P3_10G_SFP_QT: - case NETXEN_BRDTYPE_P3_10G_SFP_CT: - case NETXEN_BRDTYPE_P3_10G_XFP: - case NETXEN_BRDTYPE_P3_10000_BASE_T: - adapter->msix_supported = !!use_msi_x; - adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G; - break; - - case NETXEN_BRDTYPE_P2_SB31_10G: - case NETXEN_BRDTYPE_P2_SB31_10G_CX4: - case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ: - case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ: - adapter->msix_supported = 0; - adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G; - break; + if (adapter->ahw.port_type == NETXEN_NIC_XGBE) + adapter->num_rxd = MAX_RCV_DESCRIPTORS_10G; + else if (adapter->ahw.port_type == NETXEN_NIC_GBE) + adapter->num_rxd = MAX_RCV_DESCRIPTORS_1G; - case NETXEN_BRDTYPE_P3_REF_QG: - case NETXEN_BRDTYPE_P3_4_GB: - case NETXEN_BRDTYPE_P3_4_GB_MM: - adapter->msix_supported = !!use_msi_x; - adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G; - break; - - case NETXEN_BRDTYPE_P2_SB35_4G: - case NETXEN_BRDTYPE_P2_SB31_2G: - adapter->msix_supported = 0; - adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G; - break; - - case NETXEN_BRDTYPE_P3_10G_TP: + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) adapter->msix_supported = !!use_msi_x; - if (adapter->ahw.port_type == NETXEN_NIC_XGBE) - adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G; - else - adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G; - break; - - default: + else adapter->msix_supported = 0; - adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G; - - printk(KERN_WARNING "Unknown board type(0x%x)\n", - adapter->ahw.board_type); - break; - } - adapter->max_tx_desc_count = MAX_CMD_DESCRIPTORS_HOST; - adapter->max_jumbo_rx_desc_count = MAX_JUMBO_RCV_DESCRIPTORS; - adapter->max_lro_rx_desc_count = MAX_LRO_RCV_DESCRIPTORS; + adapter->num_txd = MAX_CMD_DESCRIPTORS_HOST; + adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS; + adapter->num_lro_rxd = MAX_LRO_RCV_DESCRIPTORS; adapter->max_possible_rss_rings = 1; return; @@ -983,12 +940,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) break; } - /* - * This call will setup various max rx/tx counts. - * It must be done before any buffer/ring allocations. - */ - netxen_check_options(adapter); - err = netxen_start_firmware(adapter); if (err) goto err_out_iounmap; @@ -1008,9 +959,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->physical_port = i; } - adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED); - - netxen_set_msix_bit(pdev, 0); + netxen_check_options(adapter); netxen_setup_intr(adapter); @@ -1307,7 +1256,7 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) u32 producer, consumer; int frag_count, no_of_desc; - u32 num_txd = adapter->max_tx_desc_count; + u32 num_txd = adapter->num_txd; bool is_tso = false; frag_count = skb_shinfo(skb)->nr_frags + 1; -- GitLab From 9b3ef55c6ddbe8c7b76707eae9a77d874fe2cec0 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Fri, 13 Mar 2009 14:52:04 +0000 Subject: [PATCH 3437/4982] netxen: remove old lro code Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 3 -- drivers/net/netxen/netxen_nic_init.c | 74 ++++++++++------------------ 2 files changed, 25 insertions(+), 52 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index f00efe84744..56fad22fed9 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -766,9 +766,6 @@ struct netxen_rx_buffer { u64 dma; u16 ref_handle; u16 state; - u32 lro_expected_frags; - u32 lro_current_frags; - u32 lro_length; }; /* Board types */ diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index d722589b1ce..1b8f79f7f8c 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -820,66 +820,37 @@ static struct sk_buff *netxen_process_rxbuf(struct netxen_adapter *adapter, no_skb: buffer->state = NETXEN_BUFFER_FREE; - buffer->lro_current_frags = 0; - buffer->lro_expected_frags = 0; list_add_tail(&buffer->list, &rds_ring->free_list); return skb; } -static void netxen_process_rcv(struct netxen_adapter *adapter, - struct status_desc *desc) +static void +netxen_process_rcv(struct netxen_adapter *adapter, + int ring, int index, int length, int cksum, int pkt_offset) { struct net_device *netdev = adapter->netdev; - u64 sts_data = le64_to_cpu(desc->status_desc_data); - int index = netxen_get_sts_refhandle(sts_data); struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; struct netxen_rx_buffer *buffer; struct sk_buff *skb; - u32 length = netxen_get_sts_totallength(sts_data); - u32 desc_ctx; - u16 pkt_offset = 0, cksum; - struct nx_host_rds_ring *rds_ring; + struct nx_host_rds_ring *rds_ring = &recv_ctx->rds_rings[ring]; - desc_ctx = netxen_get_sts_type(sts_data); - if (unlikely(desc_ctx >= adapter->max_rds_rings)) - return; - - rds_ring = &recv_ctx->rds_rings[desc_ctx]; if (unlikely(index > rds_ring->num_desc)) return; buffer = &rds_ring->rx_buf_arr[index]; - if (desc_ctx == RCV_RING_LRO) { - buffer->lro_current_frags++; - if (netxen_get_sts_desc_lro_last_frag(desc)) { - buffer->lro_expected_frags = - netxen_get_sts_desc_lro_cnt(desc); - buffer->lro_length = length; - } - if (buffer->lro_current_frags != buffer->lro_expected_frags) { - return; - } - } - - cksum = netxen_get_sts_status(sts_data); skb = netxen_process_rxbuf(adapter, rds_ring, index, cksum); if (!skb) return; - if (desc_ctx == RCV_RING_LRO) { - /* True length was only available on the last pkt */ - skb_put(skb, buffer->lro_length); - } else { - if (length > rds_ring->skb_size) - skb_put(skb, rds_ring->skb_size); - else - skb_put(skb, length); + if (length > rds_ring->skb_size) + skb_put(skb, rds_ring->skb_size); + else + skb_put(skb, length); - pkt_offset = netxen_get_sts_pkt_offset(sts_data); - if (pkt_offset) - skb_pull(skb, pkt_offset); - } + + if (pkt_offset) + skb_pull(skb, pkt_offset); skb->protocol = eth_type_trans(skb, netdev); @@ -896,9 +867,9 @@ netxen_process_rcv_ring(struct netxen_adapter *adapter, int max) struct status_desc *desc_head = recv_ctx->rcv_status_desc_head; struct status_desc *desc; u32 consumer = recv_ctx->status_rx_consumer; - int count = 0, ring; + int count = 0; u64 sts_data; - u16 opcode; + int opcode, ring, index, length, cksum, pkt_offset; while (count < max) { desc = &desc_head[consumer]; @@ -907,9 +878,19 @@ netxen_process_rcv_ring(struct netxen_adapter *adapter, int max) if (!(sts_data & STATUS_OWNER_HOST)) break; + ring = netxen_get_sts_type(sts_data); + if (ring > RCV_RING_JUMBO) + continue; + opcode = netxen_get_sts_opcode(sts_data); - netxen_process_rcv(adapter, desc); + index = netxen_get_sts_refhandle(sts_data); + length = netxen_get_sts_totallength(sts_data); + cksum = netxen_get_sts_status(sts_data); + pkt_offset = netxen_get_sts_pkt_offset(sts_data); + + netxen_process_rcv(adapter, ring, index, + length, cksum, pkt_offset); desc->status_desc_data = cpu_to_le64(STATUS_OWNER_PHANTOM); @@ -1019,7 +1000,6 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid) producer = rds_ring->producer; head = &rds_ring->free_list; - /* We can start writing rx descriptors into the phantom memory. */ while (!list_empty(head)) { skb = dev_alloc_skb(rds_ring->skb_size); @@ -1053,10 +1033,9 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid) producer = get_next_index(producer, rds_ring->num_desc); } - /* if we did allocate buffers, then write the count to Phantom */ + if (count) { rds_ring->producer = producer; - /* Window = 1 */ adapter->pci_write_normalize(adapter, rds_ring->crb_rcv_producer, (producer-1) & (rds_ring->num_desc-1)); @@ -1099,7 +1078,6 @@ netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, uint32_t ringid) producer = rds_ring->producer; head = &rds_ring->free_list; - /* We can start writing rx descriptors into the phantom memory. */ while (!list_empty(head)) { skb = dev_alloc_skb(rds_ring->skb_size); @@ -1134,10 +1112,8 @@ netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, uint32_t ringid) producer = get_next_index(producer, rds_ring->num_desc); } - /* if we did allocate buffers, then write the count to Phantom */ if (count) { rds_ring->producer = producer; - /* Window = 1 */ adapter->pci_write_normalize(adapter, rds_ring->crb_rcv_producer, (producer - 1) & (rds_ring->num_desc - 1)); -- GitLab From d8b100c5da003b6f8c410453e1e6e74ced8d1cc1 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Fri, 13 Mar 2009 14:52:05 +0000 Subject: [PATCH 3438/4982] netxen: add receive side scaling (rss) support This patch enables the load balancing capability of firmware and hardware to spray traffic into different cpus through separate rx msix interrupts. The feature is being enabled for NX3031, NX2031 (old) will be enabled later. This depends on msi-x and compatibility with msi and legacy is maintained by enabling single rx ring. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 74 ++++++---- drivers/net/netxen/netxen_nic_ctx.c | 117 +++++++++------- drivers/net/netxen/netxen_nic_hw.c | 47 +++++++ drivers/net/netxen/netxen_nic_init.c | 201 +++++++++++++++++---------- drivers/net/netxen/netxen_nic_main.c | 157 +++++++++++++++------ 5 files changed, 404 insertions(+), 192 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 56fad22fed9..595171d943f 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -78,16 +78,17 @@ #define PHAN_VENDOR_ID 0x4040 -#define RCV_DESC_RINGSIZE \ - (sizeof(struct rcv_desc) * adapter->num_rxd) -#define STATUS_DESC_RINGSIZE \ - (sizeof(struct status_desc) * adapter->num_rxd) -#define LRO_DESC_RINGSIZE \ - (sizeof(rcvDesc_t) * adapter->num_lro_rxd) -#define TX_RINGSIZE \ - (sizeof(struct netxen_cmd_buffer) * adapter->num_txd) -#define RCV_BUFFSIZE \ +#define RCV_DESC_RINGSIZE(rds_ring) \ + (sizeof(struct rcv_desc) * (rds_ring)->num_desc) +#define RCV_BUFF_RINGSIZE(rds_ring) \ (sizeof(struct netxen_rx_buffer) * rds_ring->num_desc) +#define STATUS_DESC_RINGSIZE(sds_ring) \ + (sizeof(struct status_desc) * (sds_ring)->num_desc) +#define TX_BUFF_RINGSIZE(adapter) \ + (sizeof(struct netxen_cmd_buffer) * adapter->num_txd) +#define TX_DESC_RINGSIZE(adapter) \ + (sizeof(struct cmd_desc_type0) * adapter->num_txd) + #define find_diff_among(a,b,range) ((a)<(b)?((b)-(a)):((b)+(range)-(a))) #define NETXEN_RCV_PRODUCER_OFFSET 0 @@ -188,7 +189,8 @@ /* Host writes the following to notify that it has done the init-handshake */ #define PHAN_INITIALIZE_ACK 0xf00f -#define NUM_RCV_DESC_RINGS 3 /* No of Rcv Descriptor contexts */ +#define NUM_RCV_DESC_RINGS 3 +#define NUM_STS_DESC_RINGS 4 #define RCV_RING_NORMAL 0 #define RCV_RING_JUMBO 1 @@ -722,7 +724,7 @@ extern char netxen_nic_driver_name[]; #endif /* Number of status descriptors to handle per interrupt */ -#define MAX_STATUS_HANDLE (128) +#define MAX_STATUS_HANDLE (64) /* * netxen_skb_frag{} is to contain mapping info for each SG list. This @@ -827,17 +829,37 @@ struct netxen_adapter_stats { */ struct nx_host_rds_ring { u32 producer; - u32 crb_rcv_producer; /* reg offset */ - struct rcv_desc *desc_head; /* address of rx ring in Phantom */ - struct netxen_rx_buffer *rx_buf_arr; /* rx buffers for receive */ - struct list_head free_list; + u32 crb_rcv_producer; u32 num_desc; u32 dma_size; u32 skb_size; u32 flags; + struct rcv_desc *desc_head; + struct netxen_rx_buffer *rx_buf_arr; + struct list_head free_list; + spinlock_t lock; dma_addr_t phys_addr; }; +struct nx_host_sds_ring { + u32 consumer; + u32 crb_sts_consumer; + u32 crb_intr_mask; + u32 num_desc; + + struct status_desc *desc_head; + struct netxen_adapter *adapter; + struct napi_struct napi; + struct list_head free_list[NUM_RCV_DESC_RINGS]; + + u16 clean_tx; + u16 post_rxd; + int irq; + + dma_addr_t phys_addr; + char name[IFNAMSIZ+4]; +}; + /* * Receive context. There is one such structure per instance of the * receive processing. Any state information that is relevant to @@ -850,10 +872,7 @@ struct netxen_recv_context { u16 virt_port; struct nx_host_rds_ring rds_rings[NUM_RCV_DESC_RINGS]; - u32 status_rx_consumer; - u32 crb_sts_consumer; /* reg offset */ - dma_addr_t rcv_status_desc_phys_addr; - struct status_desc *rcv_status_desc_head; + struct nx_host_sds_ring sds_rings[NUM_STS_DESC_RINGS]; }; /* New HW context creation */ @@ -1179,13 +1198,13 @@ typedef struct { #define NETXEN_IS_MSI_FAMILY(adapter) \ ((adapter)->flags & (NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED)) -#define MSIX_ENTRIES_PER_ADAPTER 1 +#define MSIX_ENTRIES_PER_ADAPTER NUM_STS_DESC_RINGS #define NETXEN_MSIX_TBL_SPACE 8192 #define NETXEN_PCI_REG_MSIX_TBL 0x44 #define NETXEN_DB_MAPSIZE_BYTES 0x1000 -#define NETXEN_NETDEV_WEIGHT 120 +#define NETXEN_NETDEV_WEIGHT 128 #define NETXEN_ADAPTER_UP_MAGIC 777 #define NETXEN_NIC_PEG_TUNE 0 @@ -1200,7 +1219,6 @@ struct netxen_adapter { struct net_device *netdev; struct pci_dev *pdev; int pci_using_dac; - struct napi_struct napi; struct net_device_stats net_stats; int mtu; int portnum; @@ -1212,7 +1230,6 @@ struct netxen_adapter { nx_mac_list_t *mac_list; struct netxen_legacy_intr_set legacy_intr; - u32 crb_intr_mask; struct work_struct watchdog_task; struct timer_list watchdog_timer; @@ -1227,6 +1244,7 @@ struct netxen_adapter { u32 last_cmd_consumer; u32 crb_addr_cmd_producer; u32 crb_addr_cmd_consumer; + spinlock_t tx_clean_lock; u32 num_txd; u32 num_rxd; @@ -1234,6 +1252,7 @@ struct netxen_adapter { u32 num_lro_rxd; int max_rds_rings; + int max_sds_rings; u32 flags; u32 irq; @@ -1243,8 +1262,7 @@ struct netxen_adapter { u32 fw_major; u32 fw_version; - u8 msix_supported; - u8 max_possible_rss_rings; + int msix_supported; struct msix_entry msix_entries[MSIX_ENTRIES_PER_ADAPTER]; struct netxen_adapter_stats stats; @@ -1447,14 +1465,16 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter); int netxen_init_firmware(struct netxen_adapter *adapter); void netxen_nic_clear_stats(struct netxen_adapter *adapter); void netxen_watchdog_task(struct work_struct *work); -void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid); +void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid, + struct nx_host_rds_ring *rds_ring); int netxen_process_cmd_ring(struct netxen_adapter *adapter); -int netxen_process_rcv_ring(struct netxen_adapter *adapter, int max); +int netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max); void netxen_p2_nic_set_multi(struct net_device *netdev); void netxen_p3_nic_set_multi(struct net_device *netdev); void netxen_p3_free_mac_list(struct netxen_adapter *adapter); int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32); int netxen_config_intr_coalesce(struct netxen_adapter *adapter); +int netxen_config_rss(struct netxen_adapter *adapter, int enable); int nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu); int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu); diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c index 2e66335bd00..9234473bc08 100644 --- a/drivers/net/netxen/netxen_nic_ctx.c +++ b/drivers/net/netxen/netxen_nic_ctx.c @@ -169,6 +169,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) nx_cardrsp_rds_ring_t *prsp_rds; nx_cardrsp_sds_ring_t *prsp_sds; struct nx_host_rds_ring *rds_ring; + struct nx_host_sds_ring *sds_ring; dma_addr_t hostrq_phys_addr, cardrsp_phys_addr; u64 phys_addr; @@ -181,9 +182,8 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; - /* only one sds ring for now */ nrds_rings = adapter->max_rds_rings; - nsds_rings = 1; + nsds_rings = adapter->max_sds_rings; rq_size = SIZEOF_HOSTRQ_RX(nx_hostrq_rx_ctx_t, nrds_rings, nsds_rings); @@ -239,11 +239,14 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) prq_sds = (nx_hostrq_sds_ring_t *)(prq->data + le32_to_cpu(prq->sds_ring_offset)); - prq_sds[0].host_phys_addr = - cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr); - prq_sds[0].ring_size = cpu_to_le32(adapter->num_rxd); - /* only one msix vector for now */ - prq_sds[0].msi_index = cpu_to_le16(0); + for (i = 0; i < nsds_rings; i++) { + + sds_ring = &recv_ctx->sds_rings[i]; + + prq_sds[i].host_phys_addr = cpu_to_le64(sds_ring->phys_addr); + prq_sds[i].ring_size = cpu_to_le32(sds_ring->num_desc); + prq_sds[i].msi_index = cpu_to_le16(i); + } phys_addr = hostrq_phys_addr; err = netxen_issue_cmd(adapter, @@ -272,11 +275,16 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) prsp_sds = ((nx_cardrsp_sds_ring_t *) &prsp->data[le32_to_cpu(prsp->sds_ring_offset)]); - reg = le32_to_cpu(prsp_sds[0].host_consumer_crb); - recv_ctx->crb_sts_consumer = NETXEN_NIC_REG(reg - 0x200); - reg = le32_to_cpu(prsp_sds[0].interrupt_crb); - adapter->crb_intr_mask = NETXEN_NIC_REG(reg - 0x200); + for (i = 0; i < le16_to_cpu(prsp->num_sds_rings); i++) { + sds_ring = &recv_ctx->sds_rings[i]; + + reg = le32_to_cpu(prsp_sds[i].host_consumer_crb); + sds_ring->crb_sts_consumer = NETXEN_NIC_REG(reg - 0x200); + + reg = le32_to_cpu(prsp_sds[i].interrupt_crb); + sds_ring->crb_intr_mask = NETXEN_NIC_REG(reg - 0x200); + } recv_ctx->state = le32_to_cpu(prsp->host_ctx_state); recv_ctx->context_id = le16_to_cpu(prsp->context_id); @@ -488,6 +496,7 @@ netxen_init_old_ctx(struct netxen_adapter *adapter) { struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; + struct nx_host_sds_ring *sds_ring; int ring; int func_id = adapter->portnum; @@ -506,10 +515,9 @@ netxen_init_old_ctx(struct netxen_adapter *adapter) adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size = cpu_to_le32(rds_ring->num_desc); } - adapter->ctx_desc->sts_ring_addr = - cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr); - adapter->ctx_desc->sts_ring_size = - cpu_to_le32(adapter->num_rxd); + sds_ring = &recv_ctx->sds_rings[0]; + adapter->ctx_desc->sts_ring_addr = cpu_to_le64(sds_ring->phys_addr); + adapter->ctx_desc->sts_ring_size = cpu_to_le32(sds_ring->num_desc); adapter->pci_write_normalize(adapter, CRB_CTX_ADDR_REG_LO(func_id), lower32(adapter->ctx_desc_phys_addr)); @@ -534,6 +542,10 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) int ring; struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; + struct nx_host_sds_ring *sds_ring; + + struct pci_dev *pdev = adapter->pdev; + struct net_device *netdev = adapter->netdev; err = netxen_receive_peg_ready(adapter); if (err) { @@ -542,12 +554,12 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) return err; } - addr = pci_alloc_consistent(adapter->pdev, + addr = pci_alloc_consistent(pdev, sizeof(struct netxen_ring_ctx) + sizeof(uint32_t), &adapter->ctx_desc_phys_addr); if (addr == NULL) { - DPRINTK(ERR, "failed to allocate hw context\n"); + dev_err(&pdev->dev, "failed to allocate hw context\n"); return -ENOMEM; } memset(addr, 0, sizeof(struct netxen_ring_ctx)); @@ -560,14 +572,13 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) (__le32 *)(((char *)addr) + sizeof(struct netxen_ring_ctx)); /* cmd desc ring */ - addr = pci_alloc_consistent(adapter->pdev, - sizeof(struct cmd_desc_type0) * - adapter->num_txd, + addr = pci_alloc_consistent(pdev, + TX_DESC_RINGSIZE(adapter), &hw->cmd_desc_phys_addr); if (addr == NULL) { - printk(KERN_ERR "%s failed to allocate tx desc ring\n", - netxen_nic_driver_name); + dev_err(&pdev->dev, "%s: failed to allocate tx desc ring\n", + netdev->name); return -ENOMEM; } @@ -576,15 +587,14 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) recv_ctx = &adapter->recv_ctx; for (ring = 0; ring < adapter->max_rds_rings; ring++) { - /* rx desc ring */ rds_ring = &recv_ctx->rds_rings[ring]; addr = pci_alloc_consistent(adapter->pdev, - RCV_DESC_RINGSIZE, + RCV_DESC_RINGSIZE(rds_ring), &rds_ring->phys_addr); if (addr == NULL) { - printk(KERN_ERR "%s failed to allocate rx " - "desc ring[%d]\n", - netxen_nic_driver_name, ring); + dev_err(&pdev->dev, + "%s: failed to allocate rds ring [%d]\n", + netdev->name, ring); err = -ENOMEM; goto err_out_free; } @@ -596,22 +606,22 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) crb_rcv_producer[ring]; } - /* status desc ring */ - addr = pci_alloc_consistent(adapter->pdev, - STATUS_DESC_RINGSIZE, - &recv_ctx->rcv_status_desc_phys_addr); - if (addr == NULL) { - printk(KERN_ERR "%s failed to allocate sts desc ring\n", - netxen_nic_driver_name); - err = -ENOMEM; - goto err_out_free; + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + + addr = pci_alloc_consistent(adapter->pdev, + STATUS_DESC_RINGSIZE(sds_ring), + &sds_ring->phys_addr); + if (addr == NULL) { + dev_err(&pdev->dev, + "%s: failed to allocate sds ring [%d]\n", + netdev->name, ring); + err = -ENOMEM; + goto err_out_free; + } + sds_ring->desc_head = (struct status_desc *)addr; } - recv_ctx->rcv_status_desc_head = (struct status_desc *)addr; - if (adapter->fw_major < 4) - recv_ctx->crb_sts_consumer = - recv_crb_registers[adapter->portnum]. - crb_sts_consumer; if (adapter->fw_major >= 4) { adapter->intr_scheme = INTR_SCHEME_PERPORT; @@ -624,12 +634,16 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) if (err) goto err_out_free; } else { + sds_ring = &recv_ctx->sds_rings[0]; + sds_ring->crb_sts_consumer = + recv_crb_registers[adapter->portnum].crb_sts_consumer; adapter->intr_scheme = adapter->pci_read_normalize(adapter, CRB_NIC_CAPABILITIES_FW); adapter->msi_mode = adapter->pci_read_normalize(adapter, CRB_NIC_MSI_MODE_FW); - adapter->crb_intr_mask = sw_int_mask[adapter->portnum]; + recv_ctx->sds_rings[0].crb_intr_mask = + sw_int_mask[adapter->portnum]; err = netxen_init_old_ctx(adapter); if (err) { @@ -650,6 +664,7 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter) { struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; + struct nx_host_sds_ring *sds_ring; int ring; if (adapter->fw_major >= 4) { @@ -681,19 +696,23 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter) if (rds_ring->desc_head != NULL) { pci_free_consistent(adapter->pdev, - RCV_DESC_RINGSIZE, + RCV_DESC_RINGSIZE(rds_ring), rds_ring->desc_head, rds_ring->phys_addr); rds_ring->desc_head = NULL; } } - if (recv_ctx->rcv_status_desc_head != NULL) { - pci_free_consistent(adapter->pdev, - STATUS_DESC_RINGSIZE, - recv_ctx->rcv_status_desc_head, - recv_ctx->rcv_status_desc_phys_addr); - recv_ctx->rcv_status_desc_head = NULL; + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + + if (sds_ring->desc_head != NULL) { + pci_free_consistent(adapter->pdev, + STATUS_DESC_RINGSIZE(sds_ring), + sds_ring->desc_head, + sds_ring->phys_addr); + sds_ring->desc_head = NULL; + } } } diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index cea7300426b..c89c791e281 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -670,6 +670,53 @@ int netxen_config_intr_coalesce(struct netxen_adapter *adapter) return rv; } +#define RSS_HASHTYPE_IP_TCP 0x3 + +int netxen_config_rss(struct netxen_adapter *adapter, int enable) +{ + nx_nic_req_t req; + u64 word; + int i, rv; + + u64 key[] = { 0xbeac01fa6a42b73bULL, 0x8030f20c77cb2da3ULL, + 0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL, + 0x255b0ec26d5a56daULL }; + + + memset(&req, 0, sizeof(nx_nic_req_t)); + req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); + + word = NX_NIC_H2C_OPCODE_CONFIG_RSS | ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word); + + /* + * RSS request: + * bits 3-0: hash_method + * 5-4: hash_type_ipv4 + * 7-6: hash_type_ipv6 + * 8: enable + * 9: use indirection table + * 47-10: reserved + * 63-48: indirection table mask + */ + word = ((u64)(RSS_HASHTYPE_IP_TCP & 0x3) << 4) | + ((u64)(RSS_HASHTYPE_IP_TCP & 0x3) << 6) | + ((u64)(enable & 0x1) << 8) | + ((0x7ULL) << 48); + req.words[0] = cpu_to_le64(word); + for (i = 0; i < 5; i++) + req.words[i+1] = cpu_to_le64(key[i]); + + + rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); + if (rv != 0) { + printk(KERN_ERR "%s: could not configure RSS\n", + adapter->netdev->name); + } + + return rv; +} + /* * netxen_nic_change_mtu - Change the Maximum Transfer Unit * @returns 0 on success, negative on failure diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 1b8f79f7f8c..0759c35f16a 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -50,7 +50,8 @@ static unsigned int crb_addr_xform[NETXEN_MAX_CRB_XFORM]; #define NETXEN_NIC_XDMA_RESET 0x8000ff static void -netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, uint32_t ringid); +netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, + struct nx_host_rds_ring *rds_ring); static void crb_addr_transform_setup(void) { @@ -222,19 +223,21 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) { struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; + struct nx_host_sds_ring *sds_ring; struct netxen_rx_buffer *rx_buf; int ring, i, num_rx_bufs; struct netxen_cmd_buffer *cmd_buf_arr; struct net_device *netdev = adapter->netdev; - cmd_buf_arr = (struct netxen_cmd_buffer *)vmalloc(TX_RINGSIZE); + cmd_buf_arr = + (struct netxen_cmd_buffer *)vmalloc(TX_BUFF_RINGSIZE(adapter)); if (cmd_buf_arr == NULL) { printk(KERN_ERR "%s: Failed to allocate cmd buffer ring\n", netdev->name); return -ENOMEM; } - memset(cmd_buf_arr, 0, TX_RINGSIZE); + memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(adapter)); adapter->cmd_buf_arr = cmd_buf_arr; recv_ctx = &adapter->recv_ctx; @@ -275,7 +278,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) } rds_ring->rx_buf_arr = (struct netxen_rx_buffer *) - vmalloc(RCV_BUFFSIZE); + vmalloc(RCV_BUFF_RINGSIZE(rds_ring)); if (rds_ring->rx_buf_arr == NULL) { printk(KERN_ERR "%s: Failed to allocate " "rx buffer ring %d\n", @@ -283,7 +286,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) /* free whatever was already allocated */ goto err_out; } - memset(rds_ring->rx_buf_arr, 0, RCV_BUFFSIZE); + memset(rds_ring->rx_buf_arr, 0, RCV_BUFF_RINGSIZE(rds_ring)); INIT_LIST_HEAD(&rds_ring->free_list); /* * Now go through all of them, set reference handles @@ -298,6 +301,19 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) rx_buf->state = NETXEN_BUFFER_FREE; rx_buf++; } + spin_lock_init(&rds_ring->lock); + } + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + sds_ring->irq = adapter->msix_entries[ring].vector; + sds_ring->clean_tx = (ring == 0); + sds_ring->post_rxd = (ring == 0); + sds_ring->adapter = adapter; + sds_ring->num_desc = adapter->num_rxd; + + for (i = 0; i < NUM_RCV_DESC_RINGS; i++) + INIT_LIST_HEAD(&sds_ring->free_list[i]); } return 0; @@ -793,6 +809,40 @@ int netxen_receive_peg_ready(struct netxen_adapter *adapter) return 0; } +static int +netxen_alloc_rx_skb(struct netxen_adapter *adapter, + struct nx_host_rds_ring *rds_ring, + struct netxen_rx_buffer *buffer) +{ + struct sk_buff *skb; + dma_addr_t dma; + struct pci_dev *pdev = adapter->pdev; + + buffer->skb = dev_alloc_skb(rds_ring->skb_size); + if (!buffer->skb) + return 1; + + skb = buffer->skb; + + if (!adapter->ahw.cut_through) + skb_reserve(skb, 2); + + dma = pci_map_single(pdev, skb->data, + rds_ring->dma_size, PCI_DMA_FROMDEVICE); + + if (pci_dma_mapping_error(pdev, dma)) { + dev_kfree_skb_any(skb); + buffer->skb = NULL; + return 1; + } + + buffer->skb = skb; + buffer->dma = dma; + buffer->state = NETXEN_BUFFER_BUSY; + + return 0; +} + static struct sk_buff *netxen_process_rxbuf(struct netxen_adapter *adapter, struct nx_host_rds_ring *rds_ring, u16 index, u16 cksum) { @@ -817,14 +867,12 @@ static struct sk_buff *netxen_process_rxbuf(struct netxen_adapter *adapter, skb->dev = adapter->netdev; buffer->skb = NULL; - no_skb: buffer->state = NETXEN_BUFFER_FREE; - list_add_tail(&buffer->list, &rds_ring->free_list); return skb; } -static void +static struct netxen_rx_buffer * netxen_process_rcv(struct netxen_adapter *adapter, int ring, int index, int length, int cksum, int pkt_offset) { @@ -835,13 +883,13 @@ netxen_process_rcv(struct netxen_adapter *adapter, struct nx_host_rds_ring *rds_ring = &recv_ctx->rds_rings[ring]; if (unlikely(index > rds_ring->num_desc)) - return; + return NULL; buffer = &rds_ring->rx_buf_arr[index]; skb = netxen_process_rxbuf(adapter, rds_ring, index, cksum); if (!skb) - return; + return buffer; if (length > rds_ring->skb_size) skb_put(skb, rds_ring->skb_size); @@ -858,21 +906,31 @@ netxen_process_rcv(struct netxen_adapter *adapter, adapter->stats.no_rcv++; adapter->stats.rxbytes += length; + + return buffer; } +#define netxen_merge_rx_buffers(list, head) \ + do { list_splice_tail_init(list, head); } while (0); + int -netxen_process_rcv_ring(struct netxen_adapter *adapter, int max) +netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max) { - struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; - struct status_desc *desc_head = recv_ctx->rcv_status_desc_head; + struct netxen_adapter *adapter = sds_ring->adapter; + + struct list_head *cur; + struct status_desc *desc; - u32 consumer = recv_ctx->status_rx_consumer; + struct netxen_rx_buffer *rxbuf; + + u32 consumer = sds_ring->consumer; + int count = 0; u64 sts_data; int opcode, ring, index, length, cksum, pkt_offset; while (count < max) { - desc = &desc_head[consumer]; + desc = &sds_ring->desc_head[consumer]; sts_data = le64_to_cpu(desc->status_desc_data); if (!(sts_data & STATUS_OWNER_HOST)) @@ -889,22 +947,41 @@ netxen_process_rcv_ring(struct netxen_adapter *adapter, int max) cksum = netxen_get_sts_status(sts_data); pkt_offset = netxen_get_sts_pkt_offset(sts_data); - netxen_process_rcv(adapter, ring, index, + rxbuf = netxen_process_rcv(adapter, ring, index, length, cksum, pkt_offset); + if (rxbuf) + list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); + desc->status_desc_data = cpu_to_le64(STATUS_OWNER_PHANTOM); - consumer = get_next_index(consumer, adapter->num_rxd); + consumer = get_next_index(consumer, sds_ring->num_desc); count++; } - for (ring = 0; ring < adapter->max_rds_rings; ring++) - netxen_post_rx_buffers_nodb(adapter, ring); + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + struct nx_host_rds_ring *rds_ring = + &adapter->recv_ctx.rds_rings[ring]; + + if (!list_empty(&sds_ring->free_list[ring])) { + list_for_each(cur, &sds_ring->free_list[ring]) { + rxbuf = list_entry(cur, + struct netxen_rx_buffer, list); + netxen_alloc_rx_skb(adapter, rds_ring, rxbuf); + } + spin_lock(&rds_ring->lock); + netxen_merge_rx_buffers(&sds_ring->free_list[ring], + &rds_ring->free_list); + spin_unlock(&rds_ring->lock); + } + + netxen_post_rx_buffers_nodb(adapter, rds_ring); + } if (count) { - recv_ctx->status_rx_consumer = consumer; + sds_ring->consumer = consumer; adapter->pci_write_normalize(adapter, - recv_ctx->crb_sts_consumer, consumer); + sds_ring->crb_sts_consumer, consumer); } return count; @@ -921,6 +998,9 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter) struct netxen_skb_frag *frag; int done = 0; + if (!spin_trylock(&adapter->tx_clean_lock)) + return 1; + last_consumer = adapter->last_cmd_consumer; barrier(); /* cmd_consumer can change underneath */ consumer = le32_to_cpu(*(adapter->cmd_consumer)); @@ -976,63 +1056,46 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter) barrier(); /* cmd_consumer can change underneath */ consumer = le32_to_cpu(*(adapter->cmd_consumer)); done = (last_consumer == consumer); + spin_unlock(&adapter->tx_clean_lock); return (done); } void -netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid) +netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid, + struct nx_host_rds_ring *rds_ring) { - struct pci_dev *pdev = adapter->pdev; - struct sk_buff *skb; - struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; - struct nx_host_rds_ring *rds_ring = NULL; - uint producer; struct rcv_desc *pdesc; struct netxen_rx_buffer *buffer; - int count = 0; + int producer, count = 0; netxen_ctx_msg msg = 0; - dma_addr_t dma; struct list_head *head; - rds_ring = &recv_ctx->rds_rings[ringid]; - producer = rds_ring->producer; - head = &rds_ring->free_list; + spin_lock(&rds_ring->lock); + head = &rds_ring->free_list; while (!list_empty(head)) { - skb = dev_alloc_skb(rds_ring->skb_size); - if (unlikely(!skb)) { - break; - } - - if (!adapter->ahw.cut_through) - skb_reserve(skb, 2); + buffer = list_entry(head->next, struct netxen_rx_buffer, list); - dma = pci_map_single(pdev, skb->data, - rds_ring->dma_size, PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(pdev, dma)) { - dev_kfree_skb_any(skb); - break; + if (!buffer->skb) { + if (netxen_alloc_rx_skb(adapter, rds_ring, buffer)) + break; } count++; - buffer = list_entry(head->next, struct netxen_rx_buffer, list); list_del(&buffer->list); - buffer->skb = skb; - buffer->state = NETXEN_BUFFER_BUSY; - buffer->dma = dma; - /* make a rcv descriptor */ pdesc = &rds_ring->desc_head[producer]; - pdesc->addr_buffer = cpu_to_le64(dma); + pdesc->addr_buffer = cpu_to_le64(buffer->dma); pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); producer = get_next_index(producer, rds_ring->num_desc); } + spin_unlock(&rds_ring->lock); if (count) { rds_ring->producer = producer; @@ -1061,48 +1124,31 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid) } static void -netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, uint32_t ringid) +netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, + struct nx_host_rds_ring *rds_ring) { - struct pci_dev *pdev = adapter->pdev; - struct sk_buff *skb; - struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; - struct nx_host_rds_ring *rds_ring = NULL; - u32 producer; struct rcv_desc *pdesc; struct netxen_rx_buffer *buffer; - int count = 0; + int producer, count = 0; struct list_head *head; - dma_addr_t dma; - - rds_ring = &recv_ctx->rds_rings[ringid]; producer = rds_ring->producer; + if (!spin_trylock(&rds_ring->lock)) + return; + head = &rds_ring->free_list; while (!list_empty(head)) { - skb = dev_alloc_skb(rds_ring->skb_size); - if (unlikely(!skb)) { - break; - } - - if (!adapter->ahw.cut_through) - skb_reserve(skb, 2); + buffer = list_entry(head->next, struct netxen_rx_buffer, list); - dma = pci_map_single(pdev, skb->data, - rds_ring->dma_size, PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(pdev, dma)) { - dev_kfree_skb_any(skb); - break; + if (!buffer->skb) { + if (netxen_alloc_rx_skb(adapter, rds_ring, buffer)) + break; } count++; - buffer = list_entry(head->next, struct netxen_rx_buffer, list); list_del(&buffer->list); - buffer->skb = skb; - buffer->state = NETXEN_BUFFER_BUSY; - buffer->dma = dma; - /* make a rcv descriptor */ pdesc = &rds_ring->desc_head[producer]; pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); @@ -1119,6 +1165,7 @@ netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, uint32_t ringid) (producer - 1) & (rds_ring->num_desc - 1)); wmb(); } + spin_unlock(&rds_ring->lock); } void netxen_nic_clear_stats(struct netxen_adapter *adapter) diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 00eaeee235e..274d1e0c893 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -135,20 +135,71 @@ static uint32_t msi_tgt_status[8] = { static struct netxen_legacy_intr_set legacy_intr[] = NX_LEGACY_INTR_CONFIG; -static inline void netxen_nic_disable_int(struct netxen_adapter *adapter) +static inline void netxen_nic_disable_int(struct nx_host_sds_ring *sds_ring) { - adapter->pci_write_normalize(adapter, adapter->crb_intr_mask, 0); + struct netxen_adapter *adapter = sds_ring->adapter; + + adapter->pci_write_normalize(adapter, sds_ring->crb_intr_mask, 0); } -static inline void netxen_nic_enable_int(struct netxen_adapter *adapter) +static inline void netxen_nic_enable_int(struct nx_host_sds_ring *sds_ring) { - adapter->pci_write_normalize(adapter, adapter->crb_intr_mask, 0x1); + struct netxen_adapter *adapter = sds_ring->adapter; + + adapter->pci_write_normalize(adapter, sds_ring->crb_intr_mask, 0x1); if (!NETXEN_IS_MSI_FAMILY(adapter)) adapter->pci_write_immediate(adapter, adapter->legacy_intr.tgt_mask_reg, 0xfbff); } +static void +netxen_napi_add(struct netxen_adapter *adapter, struct net_device *netdev) +{ + int ring; + struct nx_host_sds_ring *sds_ring; + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; + + if (adapter->flags & NETXEN_NIC_MSIX_ENABLED) + adapter->max_sds_rings = (num_online_cpus() >= 4) ? 4 : 2; + else + adapter->max_sds_rings = 1; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + netif_napi_add(netdev, &sds_ring->napi, + netxen_nic_poll, NETXEN_NETDEV_WEIGHT); + } +} + +static void +netxen_napi_enable(struct netxen_adapter *adapter) +{ + int ring; + struct nx_host_sds_ring *sds_ring; + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + napi_enable(&sds_ring->napi); + netxen_nic_enable_int(sds_ring); + } +} + +static void +netxen_napi_disable(struct netxen_adapter *adapter) +{ + int ring; + struct nx_host_sds_ring *sds_ring; + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + netxen_nic_disable_int(sds_ring); + napi_disable(&sds_ring->napi); + } +} + static int nx_set_dma_mask(struct netxen_adapter *adapter, uint8_t revision_id) { struct pci_dev *pdev = adapter->pdev; @@ -226,7 +277,6 @@ static void netxen_check_options(struct netxen_adapter *adapter) adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS; adapter->num_lro_rxd = MAX_LRO_RCV_DESCRIPTORS; - adapter->max_possible_rss_rings = 1; return; } @@ -447,6 +497,7 @@ request_msi: dev_info(&pdev->dev, "using msi interrupts\n"); } else dev_info(&pdev->dev, "using legacy interrupts\n"); + adapter->msix_entries[0].vector = pdev->irq; } } @@ -671,8 +722,12 @@ static int netxen_nic_request_irq(struct netxen_adapter *adapter) { irq_handler_t handler; + struct nx_host_sds_ring *sds_ring; + int err, ring; + unsigned long flags = IRQF_SAMPLE_RANDOM; struct net_device *netdev = adapter->netdev; + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; if ((adapter->msi_mode != MSI_MODE_MULTIFUNC) || (adapter->intr_scheme != INTR_SCHEME_PERPORT)) { @@ -693,8 +748,30 @@ netxen_nic_request_irq(struct netxen_adapter *adapter) } adapter->irq = netdev->irq; - return request_irq(adapter->irq, handler, - flags, netdev->name, adapter); + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + sprintf(sds_ring->name, "%16s[%d]", netdev->name, ring); + err = request_irq(sds_ring->irq, handler, + flags, sds_ring->name, sds_ring); + if (err) + return err; + } + + return 0; +} + +static void +netxen_nic_free_irq(struct netxen_adapter *adapter) +{ + int ring; + struct nx_host_sds_ring *sds_ring; + + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + free_irq(sds_ring->irq, sds_ring); + } } static int @@ -719,8 +796,10 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) adapter->ahw.linkup = 0; mod_timer(&adapter->watchdog_timer, jiffies); - napi_enable(&adapter->napi); - netxen_nic_enable_int(adapter); + netxen_napi_enable(adapter); + + if (adapter->max_sds_rings > 1) + netxen_config_rss(adapter, 1); return 0; } @@ -730,13 +809,11 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) { netif_carrier_off(netdev); netif_stop_queue(netdev); - napi_disable(&adapter->napi); + netxen_napi_disable(adapter); if (adapter->stop_port) adapter->stop_port(adapter); - netxen_nic_disable_int(adapter); - netxen_release_tx_buffers(adapter); FLUSH_SCHEDULED_WORK(); @@ -750,6 +827,7 @@ netxen_nic_attach(struct netxen_adapter *adapter) struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; int err, ring; + struct nx_host_rds_ring *rds_ring; err = netxen_init_firmware(adapter); if (err != 0) { @@ -788,8 +866,10 @@ netxen_nic_attach(struct netxen_adapter *adapter) netxen_nic_update_cmd_consumer(adapter, 0); } - for (ring = 0; ring < adapter->max_rds_rings; ring++) - netxen_post_rx_buffers(adapter, ring); + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + rds_ring = &adapter->recv_ctx.rds_rings[ring]; + netxen_post_rx_buffers(adapter, ring, rds_ring); + } err = netxen_nic_request_irq(adapter); if (err) { @@ -812,8 +892,7 @@ err_out_free_sw: static void netxen_nic_detach(struct netxen_adapter *adapter) { - if (adapter->irq) - free_irq(adapter->irq, adapter); + netxen_nic_free_irq(adapter); netxen_release_rx_buffers(adapter); netxen_free_hw_resources(adapter); @@ -883,14 +962,12 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_free_netdev; rwlock_init(&adapter->adapter_lock); + spin_lock_init(&adapter->tx_clean_lock); err = netxen_setup_pci_map(adapter); if (err) goto err_out_free_netdev; - netif_napi_add(netdev, &adapter->napi, - netxen_nic_poll, NETXEN_NETDEV_WEIGHT); - /* This will be reset for mezz cards */ adapter->portnum = pci_func_id; adapter->rx_csum = 1; @@ -963,10 +1040,9 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netxen_setup_intr(adapter); - if (adapter->flags & NETXEN_NIC_MSIX_ENABLED) - netdev->irq = adapter->msix_entries[0].vector; - else - netdev->irq = pdev->irq; + netdev->irq = adapter->msix_entries[0].vector; + + netxen_napi_add(adapter, netdev); err = netxen_receive_peg_ready(adapter); if (err) @@ -1520,13 +1596,11 @@ static void netxen_tx_timeout_task(struct work_struct *work) printk(KERN_ERR "%s %s: transmit timeout, resetting.\n", netxen_nic_driver_name, adapter->netdev->name); - netxen_nic_disable_int(adapter); - napi_disable(&adapter->napi); + netxen_napi_disable(adapter); adapter->netdev->trans_start = jiffies; - napi_enable(&adapter->napi); - netxen_nic_enable_int(adapter); + netxen_napi_enable(adapter); netif_wake_queue(adapter->netdev); } @@ -1564,7 +1638,8 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) static irqreturn_t netxen_intr(int irq, void *data) { - struct netxen_adapter *adapter = data; + struct nx_host_sds_ring *sds_ring = data; + struct netxen_adapter *adapter = sds_ring->adapter; u32 status = 0; status = adapter->pci_read_immediate(adapter, ISR_INT_VECTOR); @@ -1595,7 +1670,7 @@ static irqreturn_t netxen_intr(int irq, void *data) /* clear interrupt */ if (adapter->fw_major < 4) - netxen_nic_disable_int(adapter); + netxen_nic_disable_int(sds_ring); adapter->pci_write_immediate(adapter, adapter->legacy_intr.tgt_status_reg, @@ -1604,45 +1679,49 @@ static irqreturn_t netxen_intr(int irq, void *data) adapter->pci_read_immediate(adapter, ISR_INT_VECTOR); adapter->pci_read_immediate(adapter, ISR_INT_VECTOR); - napi_schedule(&adapter->napi); + napi_schedule(&sds_ring->napi); return IRQ_HANDLED; } static irqreturn_t netxen_msi_intr(int irq, void *data) { - struct netxen_adapter *adapter = data; + struct nx_host_sds_ring *sds_ring = data; + struct netxen_adapter *adapter = sds_ring->adapter; /* clear interrupt */ adapter->pci_write_immediate(adapter, msi_tgt_status[adapter->ahw.pci_func], 0xffffffff); - napi_schedule(&adapter->napi); + napi_schedule(&sds_ring->napi); return IRQ_HANDLED; } static irqreturn_t netxen_msix_intr(int irq, void *data) { - struct netxen_adapter *adapter = data; + struct nx_host_sds_ring *sds_ring = data; - napi_schedule(&adapter->napi); + napi_schedule(&sds_ring->napi); return IRQ_HANDLED; } static int netxen_nic_poll(struct napi_struct *napi, int budget) { - struct netxen_adapter *adapter = - container_of(napi, struct netxen_adapter, napi); + struct nx_host_sds_ring *sds_ring = + container_of(napi, struct nx_host_sds_ring, napi); + + struct netxen_adapter *adapter = sds_ring->adapter; + int tx_complete; int work_done; tx_complete = netxen_process_cmd_ring(adapter); - work_done = netxen_process_rcv_ring(adapter, budget); + work_done = netxen_process_rcv_ring(sds_ring, budget); if ((work_done < budget) && tx_complete) { - napi_complete(&adapter->napi); - netxen_nic_enable_int(adapter); + napi_complete(&sds_ring->napi); + netxen_nic_enable_int(sds_ring); } return work_done; -- GitLab From ff4fbd43fe82de28710761f2cc2ed122d716483a Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Fri, 13 Mar 2009 14:52:06 +0000 Subject: [PATCH 3439/4982] netxen: update version to 4.0.30 To mark all features and bugfixes submitted since 4.0.11. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 4 ++-- drivers/net/netxen/netxen_nic_main.c | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 595171d943f..2544129768f 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -66,8 +66,8 @@ #define _NETXEN_NIC_LINUX_MAJOR 4 #define _NETXEN_NIC_LINUX_MINOR 0 -#define _NETXEN_NIC_LINUX_SUBVERSION 11 -#define NETXEN_NIC_LINUX_VERSIONID "4.0.11" +#define _NETXEN_NIC_LINUX_SUBVERSION 30 +#define NETXEN_NIC_LINUX_VERSIONID "4.0.30" #define NETXEN_VERSION_CODE(a, b, c) (((a) << 16) + ((b) << 8) + (c)) diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 274d1e0c893..1fb9bcf504e 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -910,9 +910,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) int pci_func_id = PCI_FUNC(pdev->devfn); uint8_t revision_id; - if (pci_func_id == 0) - printk(KERN_INFO "%s\n", netxen_nic_driver_string); - if (pdev->class != 0x020000) { printk(KERN_DEBUG "NetXen function %d, class %x will not " "be enabled.\n",pci_func_id, pdev->class); @@ -1750,6 +1747,8 @@ static struct pci_driver netxen_driver = { static int __init netxen_init_module(void) { + printk(KERN_INFO "%s\n", netxen_nic_driver_string); + if ((netxen_workq = create_singlethread_workqueue("netxen")) == NULL) return -ENOMEM; -- GitLab From 682337fe062e939578d933c74157ae9a36baa4ce Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Sat, 14 Mar 2009 22:26:40 -0700 Subject: [PATCH 3440/4982] igb: remove ASPM L0s workaround The L0s workaround should be moved into a pci quirk and so it is not necessary in the driver. This update removes the L0s workaround from the igb driver. This was the second half of the PCI quirk patch that Matthew Wilcox did not pick up when he picked up the quirk patch. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index a50db5398fa..9dd13ad12ce 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1023,11 +1023,10 @@ static int __devinit igb_probe(struct pci_dev *pdev, struct net_device *netdev; struct igb_adapter *adapter; struct e1000_hw *hw; - struct pci_dev *us_dev; const struct e1000_info *ei = igb_info_tbl[ent->driver_data]; unsigned long mmio_start, mmio_len; - int i, err, pci_using_dac, pos; - u16 eeprom_data = 0, state = 0; + int i, err, pci_using_dac; + u16 eeprom_data = 0; u16 eeprom_apme_mask = IGB_EEPROM_APME; u32 part_num; int bars, need_ioport; @@ -1062,27 +1061,6 @@ static int __devinit igb_probe(struct pci_dev *pdev, } } - /* 82575 requires that the pci-e link partner disable the L0s state */ - switch (pdev->device) { - case E1000_DEV_ID_82575EB_COPPER: - case E1000_DEV_ID_82575EB_FIBER_SERDES: - case E1000_DEV_ID_82575GB_QUAD_COPPER: - us_dev = pdev->bus->self; - pos = pci_find_capability(us_dev, PCI_CAP_ID_EXP); - if (pos) { - pci_read_config_word(us_dev, pos + PCI_EXP_LNKCTL, - &state); - state &= ~PCIE_LINK_STATE_L0S; - pci_write_config_word(us_dev, pos + PCI_EXP_LNKCTL, - state); - dev_info(&pdev->dev, - "Disabling ASPM L0s upstream switch port %s\n", - pci_name(us_dev)); - } - default: - break; - } - err = pci_request_selected_regions(pdev, bars, igb_driver_name); if (err) goto err_pci_reg; -- GitLab From f84e85ef3ccedd450d2dd266798c97b05b7b3563 Mon Sep 17 00:00:00 2001 From: Dmitry Artamonow Date: Sun, 15 Mar 2009 19:04:56 +0100 Subject: [PATCH 3441/4982] [ARM] 5423/1: SA1100: remove unused H3600_SLEEVE Kconfig option There's no actual code for iPAQ sleeves support in kernel that depends on this config option. Signed-off-by: Dmitry Artamonow Signed-off-by: Russell King --- arch/arm/configs/h3600_defconfig | 1 - arch/arm/mach-sa1100/Kconfig | 9 --------- 2 files changed, 10 deletions(-) diff --git a/arch/arm/configs/h3600_defconfig b/arch/arm/configs/h3600_defconfig index f2e16fd0a6b..1502957db2c 100644 --- a/arch/arm/configs/h3600_defconfig +++ b/arch/arm/configs/h3600_defconfig @@ -99,7 +99,6 @@ CONFIG_SA1100_H3XXX=y # CONFIG_SA1100_SHANNON is not set # CONFIG_SA1100_SIMPAD is not set # CONFIG_SA1100_SSP is not set -# CONFIG_H3600_SLEEVE is not set # # Processor Type diff --git a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig index bfc38e31518..81ffff7ed49 100644 --- a/arch/arm/mach-sa1100/Kconfig +++ b/arch/arm/mach-sa1100/Kconfig @@ -147,15 +147,6 @@ config SA1100_SSP This isn't for audio support, but for attached sensors and other devices, eg for BadgePAD 4 sensor support. -config H3600_SLEEVE - tristate "Compaq iPAQ Handheld sleeve support" - depends on SA1100_H3100 || SA1100_H3600 - help - Choose this option to enable support for extension packs (sleeves) - for the Compaq iPAQ H3XXX series of handheld computers. This option - is required for the CF, PCMCIA, Bluetooth and GSM/GPRS extension - packs. - endmenu endif -- GitLab From f110b3f2a61d26329290036dac3d70a6733099de Mon Sep 17 00:00:00 2001 From: Dmitry Artamonow Date: Sun, 15 Mar 2009 19:09:50 +0100 Subject: [PATCH 3442/4982] [ARM] 5424/1: h3600: clean up mtd partitions table Right now iPaq h3600's default MTD partitions table is a mess. It has two #ifdefs with #else, giving total 3 variants, depending on your kernel config. Replace all this with simple two-partitions scheme (bootloader + rootfs), that used by both shipped WindowsCE and most of the linux distributions (Familiar, Angstrom) Signed-off-by: Dmitry Artamonow Signed-off-by: Russell King --- arch/arm/mach-sa1100/h3600.c | 34 +--------------------------------- 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c index b9aaa45c6ca..4920b89d149 100644 --- a/arch/arm/mach-sa1100/h3600.c +++ b/arch/arm/mach-sa1100/h3600.c @@ -56,41 +56,9 @@ static struct mtd_partition h3xxx_partitions[] = { .offset = 0, .mask_flags = MTD_WRITEABLE, /* force read-only */ }, { -#ifdef CONFIG_MTD_2PARTS_IPAQ - .name = "H3XXX root jffs2", + .name = "H3XXX rootfs", .size = MTDPART_SIZ_FULL, .offset = 0x00040000, -#else - .name = "H3XXX kernel", - .size = 0x00080000, - .offset = 0x00040000, - }, { - .name = "H3XXX params", - .size = 0x00040000, - .offset = 0x000C0000, - }, { -#ifdef CONFIG_JFFS2_FS - .name = "H3XXX root jffs2", - .size = MTDPART_SIZ_FULL, - .offset = 0x00100000, -#else - .name = "H3XXX initrd", - .size = 0x00100000, - .offset = 0x00100000, - }, { - .name = "H3XXX root cramfs", - .size = 0x00300000, - .offset = 0x00200000, - }, { - .name = "H3XXX usr cramfs", - .size = 0x00800000, - .offset = 0x00500000, - }, { - .name = "H3XXX usr local", - .size = MTDPART_SIZ_FULL, - .offset = 0x00d00000, -#endif -#endif } }; -- GitLab From ddcd8c09001e66f78488bfc238ed5bd8441d4496 Mon Sep 17 00:00:00 2001 From: Dmitry Artamonow Date: Sun, 15 Mar 2009 19:11:21 +0100 Subject: [PATCH 3443/4982] [ARM] 5425/1: h3600: first stage of ipaq_model_ops cleanup Remove unused fields and associated funtions-accesors. Signed-off-by: Dmitry Artamonow Signed-off-by: Russell King --- arch/arm/mach-sa1100/h3600.c | 38 ------------------- arch/arm/mach-sa1100/include/mach/h3600.h | 46 ----------------------- 2 files changed, 84 deletions(-) diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c index 4920b89d149..9f13f5bd57a 100644 --- a/arch/arm/mach-sa1100/h3600.c +++ b/arch/arm/mach-sa1100/h3600.c @@ -227,12 +227,6 @@ static void __init h3xxx_map_io(void) sa1100fb_lcd_power = h3xxx_lcd_power; } -static __inline__ void do_blank(int setp) -{ - if (ipaq_model_ops.blank_callback) - ipaq_model_ops.blank_callback(1-setp); -} - /************************* H3100 *************************/ #ifdef CONFIG_SA1100_H3100 @@ -250,7 +244,6 @@ static void h3100_control_egpio(enum ipaq_egpio_type x, int setp) case IPAQ_EGPIO_LCD_POWER: egpio |= EGPIO_H3600_LCD_ON; gpio |= GPIO_H3100_LCD_3V_ON; - do_blank(setp); break; case IPAQ_EGPIO_LCD_ENABLE: break; @@ -304,23 +297,8 @@ static void h3100_control_egpio(enum ipaq_egpio_type x, int setp) } } -static unsigned long h3100_read_egpio(void) -{ - return h3100_egpio; -} - -static int h3100_pm_callback(int req) -{ - if (ipaq_model_ops.pm_callback_aux) - return ipaq_model_ops.pm_callback_aux(req); - return 0; -} - static struct ipaq_model_ops h3100_model_ops __initdata = { - .generic_name = "3100", .control = h3100_control_egpio, - .read = h3100_read_egpio, - .pm_callback = h3100_pm_callback }; #define H3100_DIRECT_EGPIO (GPIO_H3100_BT_ON \ @@ -381,7 +359,6 @@ static void h3600_control_egpio(enum ipaq_egpio_type x, int setp) EGPIO_H3600_LCD_PCI | EGPIO_H3600_LCD_5V_ON | EGPIO_H3600_LVDD_ON; - do_blank(setp); break; case IPAQ_EGPIO_LCD_ENABLE: break; @@ -432,23 +409,8 @@ static void h3600_control_egpio(enum ipaq_egpio_type x, int setp) } } -static unsigned long h3600_read_egpio(void) -{ - return h3600_egpio; -} - -static int h3600_pm_callback(int req) -{ - if (ipaq_model_ops.pm_callback_aux) - return ipaq_model_ops.pm_callback_aux(req); - return 0; -} - static struct ipaq_model_ops h3600_model_ops __initdata = { - .generic_name = "3600", .control = h3600_control_egpio, - .read = h3600_read_egpio, - .pm_callback = h3600_pm_callback }; static void __init h3600_map_io(void) diff --git a/arch/arm/mach-sa1100/include/mach/h3600.h b/arch/arm/mach-sa1100/include/mach/h3600.h index e692ab3dd79..8e8ccfc2f46 100644 --- a/arch/arm/mach-sa1100/include/mach/h3600.h +++ b/arch/arm/mach-sa1100/include/mach/h3600.h @@ -94,21 +94,11 @@ enum ipaq_egpio_type { }; struct ipaq_model_ops { - const char *generic_name; void (*control)(enum ipaq_egpio_type, int); - unsigned long (*read)(void); - void (*blank_callback)(int blank); - int (*pm_callback)(int req); /* Primary model callback */ - int (*pm_callback_aux)(int req); /* Secondary callback (used by HAL modules) */ }; extern struct ipaq_model_ops ipaq_model_ops; -static __inline__ const char * h3600_generic_name(void) -{ - return ipaq_model_ops.generic_name; -} - static __inline__ void assign_h3600_egpio(enum ipaq_egpio_type x, int level) { if (ipaq_model_ops.control) @@ -127,42 +117,6 @@ static __inline__ void set_h3600_egpio(enum ipaq_egpio_type x) ipaq_model_ops.control(x,1); } -static __inline__ unsigned long read_h3600_egpio(void) -{ - if (ipaq_model_ops.read) - return ipaq_model_ops.read(); - return 0; -} - -static __inline__ int h3600_register_blank_callback(void (*f)(int)) -{ - ipaq_model_ops.blank_callback = f; - return 0; -} - -static __inline__ void h3600_unregister_blank_callback(void (*f)(int)) -{ - ipaq_model_ops.blank_callback = NULL; -} - - -static __inline__ int h3600_register_pm_callback(int (*f)(int)) -{ - ipaq_model_ops.pm_callback_aux = f; - return 0; -} - -static __inline__ void h3600_unregister_pm_callback(int (*f)(int)) -{ - ipaq_model_ops.pm_callback_aux = NULL; -} - -static __inline__ int h3600_power_management(int req) -{ - if (ipaq_model_ops.pm_callback) - return ipaq_model_ops.pm_callback(req); - return 0; -} #endif /* ASSEMBLY */ -- GitLab From 104a416d80fca22284319b06eff87b6f632a3649 Mon Sep 17 00:00:00 2001 From: Dmitry Artamonow Date: Sun, 15 Mar 2009 19:13:16 +0100 Subject: [PATCH 3444/4982] [ARM] 5426/1: h3600: remove clr_h3600_egpio/set_h3600_egpio helpers Replace all occurences with assign_h3600_egpio. Also simplify code a bit by replacing couple of if-else statements with one-line equivalents. Signed-off-by: Dmitry Artamonow Signed-off-by: Russell King --- arch/arm/mach-sa1100/h3600.c | 6 +----- arch/arm/mach-sa1100/include/mach/h3600.h | 13 ------------- drivers/pcmcia/sa1100_h3600.c | 23 ++++++++++------------- 3 files changed, 11 insertions(+), 31 deletions(-) diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c index 9f13f5bd57a..1fa0f58c07b 100644 --- a/arch/arm/mach-sa1100/h3600.c +++ b/arch/arm/mach-sa1100/h3600.c @@ -92,11 +92,7 @@ static int h3600_irda_set_power(struct device *dev, unsigned int state) static void h3600_irda_set_speed(struct device *dev, unsigned int speed) { - if (speed < 4000000) { - clr_h3600_egpio(IPAQ_EGPIO_IR_FSEL); - } else { - set_h3600_egpio(IPAQ_EGPIO_IR_FSEL); - } + assign_h3600_egpio(IPAQ_EGPIO_IR_FSEL, !(speed < 4000000)); } static struct irda_platform_data h3600_irda_data = { diff --git a/arch/arm/mach-sa1100/include/mach/h3600.h b/arch/arm/mach-sa1100/include/mach/h3600.h index 8e8ccfc2f46..33fc4bcfd3e 100644 --- a/arch/arm/mach-sa1100/include/mach/h3600.h +++ b/arch/arm/mach-sa1100/include/mach/h3600.h @@ -105,19 +105,6 @@ static __inline__ void assign_h3600_egpio(enum ipaq_egpio_type x, int level) ipaq_model_ops.control(x,level); } -static __inline__ void clr_h3600_egpio(enum ipaq_egpio_type x) -{ - if (ipaq_model_ops.control) - ipaq_model_ops.control(x,0); -} - -static __inline__ void set_h3600_egpio(enum ipaq_egpio_type x) -{ - if (ipaq_model_ops.control) - ipaq_model_ops.control(x,1); -} - - #endif /* ASSEMBLY */ #endif /* _INCLUDE_H3600_H_ */ diff --git a/drivers/pcmcia/sa1100_h3600.c b/drivers/pcmcia/sa1100_h3600.c index 6de4e1b41d6..0cc3748f375 100644 --- a/drivers/pcmcia/sa1100_h3600.c +++ b/drivers/pcmcia/sa1100_h3600.c @@ -37,9 +37,9 @@ static void h3600_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); /* Disable CF bus: */ - clr_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON); - clr_h3600_egpio(IPAQ_EGPIO_OPT_ON); - set_h3600_egpio(IPAQ_EGPIO_OPT_RESET); + assign_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON, 0); + assign_h3600_egpio(IPAQ_EGPIO_OPT_ON, 0); + assign_h3600_egpio(IPAQ_EGPIO_OPT_RESET, 1); } static void @@ -79,10 +79,7 @@ h3600_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_ return -1; } - if (state->flags & SS_RESET) - set_h3600_egpio(IPAQ_EGPIO_CARD_RESET); - else - clr_h3600_egpio(IPAQ_EGPIO_CARD_RESET); + assign_h3600_egpio(IPAQ_EGPIO_CARD_RESET, !!(state->flags & SS_RESET)); /* Silently ignore Vpp, output enable, speaker enable. */ @@ -92,9 +89,9 @@ h3600_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_ static void h3600_pcmcia_socket_init(struct soc_pcmcia_socket *skt) { /* Enable CF bus: */ - set_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON); - set_h3600_egpio(IPAQ_EGPIO_OPT_ON); - clr_h3600_egpio(IPAQ_EGPIO_OPT_RESET); + assign_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON, 1); + assign_h3600_egpio(IPAQ_EGPIO_OPT_ON, 1); + assign_h3600_egpio(IPAQ_EGPIO_OPT_RESET, 0); msleep(10); @@ -112,10 +109,10 @@ static void h3600_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) * socket 0 then socket 1. */ if (skt->nr == 1) { - clr_h3600_egpio(IPAQ_EGPIO_OPT_ON); - clr_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON); + assign_h3600_egpio(IPAQ_EGPIO_OPT_ON, 0); + assign_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON, 0); /* hmm, does this suck power? */ - set_h3600_egpio(IPAQ_EGPIO_OPT_RESET); + assign_h3600_egpio(IPAQ_EGPIO_OPT_RESET, 1); } } -- GitLab From 607b067e161185d5c441aa366ff9fccd4fd676cb Mon Sep 17 00:00:00 2001 From: Dmitry Artamonow Date: Sun, 15 Mar 2009 19:14:27 +0100 Subject: [PATCH 3445/4982] [ARM] 5427/1: h3600: ipaq_model_ops final cleanup Since now ipaq_model_ops used only for accessing h3600 EGPIOs, drop it completely and use assign_h3600_egpio() directly. Signed-off-by: Dmitry Artamonow Signed-off-by: Russell King --- arch/arm/mach-sa1100/h3600.c | 16 ++++------------ arch/arm/mach-sa1100/include/mach/h3600.h | 12 +----------- 2 files changed, 5 insertions(+), 23 deletions(-) diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c index 1fa0f58c07b..0eb2f159578 100644 --- a/arch/arm/mach-sa1100/h3600.c +++ b/arch/arm/mach-sa1100/h3600.c @@ -46,8 +46,8 @@ #include "generic.h" -struct ipaq_model_ops ipaq_model_ops; -EXPORT_SYMBOL(ipaq_model_ops); +void (*assign_h3600_egpio)(enum ipaq_egpio_type x, int level); +EXPORT_SYMBOL(assign_h3600_egpio); static struct mtd_partition h3xxx_partitions[] = { { @@ -293,10 +293,6 @@ static void h3100_control_egpio(enum ipaq_egpio_type x, int setp) } } -static struct ipaq_model_ops h3100_model_ops __initdata = { - .control = h3100_control_egpio, -}; - #define H3100_DIRECT_EGPIO (GPIO_H3100_BT_ON \ | GPIO_H3100_GPIO3 \ | GPIO_H3100_QMUTE \ @@ -322,7 +318,7 @@ static void __init h3100_map_io(void) GAFR &= ~H3100_DIRECT_EGPIO; H3100_EGPIO = h3100_egpio; - ipaq_model_ops = h3100_model_ops; + assign_h3600_egpio = h3100_control_egpio; } MACHINE_START(H3100, "Compaq iPAQ H3100") @@ -405,10 +401,6 @@ static void h3600_control_egpio(enum ipaq_egpio_type x, int setp) } } -static struct ipaq_model_ops h3600_model_ops __initdata = { - .control = h3600_control_egpio, -}; - static void __init h3600_map_io(void) { h3xxx_map_io(); @@ -423,7 +415,7 @@ static void __init h3600_map_io(void) GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8; H3600_EGPIO = h3600_egpio; /* Maintains across sleep? */ - ipaq_model_ops = h3600_model_ops; + assign_h3600_egpio = h3600_control_egpio; } MACHINE_START(H3600, "Compaq iPAQ H3600") diff --git a/arch/arm/mach-sa1100/include/mach/h3600.h b/arch/arm/mach-sa1100/include/mach/h3600.h index 33fc4bcfd3e..2827faa4742 100644 --- a/arch/arm/mach-sa1100/include/mach/h3600.h +++ b/arch/arm/mach-sa1100/include/mach/h3600.h @@ -93,17 +93,7 @@ enum ipaq_egpio_type { IPAQ_EGPIO_LCD_ENABLE, /* Enable/disable LCD controller */ }; -struct ipaq_model_ops { - void (*control)(enum ipaq_egpio_type, int); -}; - -extern struct ipaq_model_ops ipaq_model_ops; - -static __inline__ void assign_h3600_egpio(enum ipaq_egpio_type x, int level) -{ - if (ipaq_model_ops.control) - ipaq_model_ops.control(x,level); -} +extern void (*assign_h3600_egpio)(enum ipaq_egpio_type x, int level); #endif /* ASSEMBLY */ -- GitLab From 26ade896b6ba3fd017ef4a26e71e7b7569222cb6 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sun, 15 Mar 2009 14:10:54 +0100 Subject: [PATCH 3446/4982] ASoC: Allow choice of ac97 gpio reset line As the PXA27x series allow 2 gpios to reset the ac97 bus, allow through platform data configuration the definition of the correct gpio which will reset the AC97 bus. This comes from a silicon defect on the PXA27x series, where the gpio must be manually controlled in warm reset cases. Signed-off-by: Robert Jarzmik Signed-off-by: Mark Brown --- include/sound/pxa2xx-lib.h | 15 ++++++++ sound/arm/pxa2xx-ac97-lib.c | 71 ++++++++++++++++++++++++++++++++++--- 2 files changed, 81 insertions(+), 5 deletions(-) diff --git a/include/sound/pxa2xx-lib.h b/include/sound/pxa2xx-lib.h index 2fd3d251d9a..2c894b600e5 100644 --- a/include/sound/pxa2xx-lib.h +++ b/include/sound/pxa2xx-lib.h @@ -42,4 +42,19 @@ extern int pxa2xx_ac97_hw_resume(void); extern int pxa2xx_ac97_hw_probe(struct platform_device *dev); extern void pxa2xx_ac97_hw_remove(struct platform_device *dev); +/* AC97 platform_data */ +/** + * struct pxa2xx_ac97_platform_data - pxa ac97 platform data + * @reset_gpio: AC97 reset gpio (normally gpio113 or gpio95) + * a -1 value means no gpio will be used for reset + * + * Platform data should only be specified for pxa27x CPUs where a silicon bug + * prevents correct operation of the reset line. If not specified, the default + * behaviour is to consider gpio 113 as the AC97 reset line, which is the + * default on most boards. + */ +struct pxa2xx_ac97_platform_data { + int reset_gpio; +}; + #endif diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c index 35afd0c33be..d721ea7cae8 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c @@ -31,6 +31,7 @@ static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); static volatile long gsr_bits; static struct clk *ac97_clk; static struct clk *ac97conf_clk; +static int reset_gpio; /* * Beware PXA27x bugs: @@ -42,6 +43,45 @@ static struct clk *ac97conf_clk; * 1 jiffy timeout if interrupt never comes). */ +enum { + RESETGPIO_FORCE_HIGH, + RESETGPIO_FORCE_LOW, + RESETGPIO_NORMAL_ALTFUNC +}; + +/** + * set_resetgpio_mode - computes and sets the AC97_RESET gpio mode on PXA + * @mode: chosen action + * + * As the PXA27x CPUs suffer from a AC97 bug, a manual control of the reset line + * must be done to insure proper work of AC97 reset line. This function + * computes the correct gpio_mode for further use by reset functions, and + * applied the change through pxa_gpio_mode. + */ +static void set_resetgpio_mode(int resetgpio_action) +{ + int mode = 0; + + if (reset_gpio) + switch (resetgpio_action) { + case RESETGPIO_NORMAL_ALTFUNC: + if (reset_gpio == 113) + mode = 113 | GPIO_OUT | GPIO_DFLT_LOW; + if (reset_gpio == 95) + mode = 95 | GPIO_ALT_FN_1_OUT; + break; + case RESETGPIO_FORCE_LOW: + mode = reset_gpio | GPIO_OUT | GPIO_DFLT_LOW; + break; + case RESETGPIO_FORCE_HIGH: + mode = reset_gpio | GPIO_OUT | GPIO_DFLT_HIGH; + break; + }; + + if (mode) + pxa_gpio_mode(mode); +} + unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg) { unsigned short val = -1; @@ -137,10 +177,10 @@ static inline void pxa_ac97_warm_pxa27x(void) /* warm reset broken on Bulverde, so manually keep AC97 reset high */ - pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH); + set_resetgpio_mode(RESETGPIO_FORCE_HIGH); udelay(10); GCR |= GCR_WARM_RST; - pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); + set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC); udelay(500); } @@ -308,8 +348,8 @@ int pxa2xx_ac97_hw_resume(void) pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD); } if (cpu_is_pxa27x()) { - /* Use GPIO 113 as AC97 Reset on Bulverde */ - pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); + /* Use GPIO 113 or 95 as AC97 Reset on Bulverde */ + set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC); } clk_enable(ac97_clk); return 0; @@ -320,6 +360,27 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume); int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) { int ret; + struct pxa2xx_ac97_platform_data *pdata = dev->dev.platform_data; + + if (pdata) { + switch (pdata->reset_gpio) { + case 95: + case 113: + reset_gpio = pdata->reset_gpio; + break; + case 0: + reset_gpio = 113; + break; + case -1: + break; + default: + dev_err(dev, "Invalid reset GPIO %d\n", + pdata->reset_gpio); + } + } else { + if (cpu_is_pxa27x()) + reset_gpio = 113; + } if (cpu_is_pxa25x() || cpu_is_pxa27x()) { pxa_gpio_mode(GPIO31_SYNC_AC97_MD); @@ -330,7 +391,7 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) if (cpu_is_pxa27x()) { /* Use GPIO 113 as AC97 Reset on Bulverde */ - pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); + set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC); ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK"); if (IS_ERR(ac97conf_clk)) { ret = PTR_ERR(ac97conf_clk); -- GitLab From 5bee17f18b595937e6beafeee5197868a3f74a06 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Sat, 14 Mar 2009 19:40:59 -0400 Subject: [PATCH 3447/4982] parisc: sba_iommu: fix build bug when CONFIG_PARISC_AGP=y CC drivers/parisc/sba_iommu.o drivers/parisc/sba_iommu.c:1373: error: expected identifier or '(' before '}' token make[2]: *** [drivers/parisc/sba_iommu.o] Error 1 make[1]: *** [drivers/parisc] Error 2 make: *** [drivers] Error 2 Don't know how this has gone missed for so long... clearly I need to do builds on my C8000 more often. Signed-off-by: Kyle McMartin Signed-off-by: Linus Torvalds --- drivers/parisc/sba_iommu.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index 6aad8546fd2..e5999c4cedc 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -1367,9 +1367,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ioc->pdir_size /= 2; ioc->pdir_base[PDIR_INDEX(iova_space_size/2)] = SBA_AGPGART_COOKIE; } -} #endif /*SBA_AGP_SUPPORT*/ - } static void -- GitLab From 184832c981fd38b1052f2dfa0262e793fa6c67d3 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 15 Mar 2009 11:05:12 +0100 Subject: [PATCH 3448/4982] kconfig: fix randconfig for choice blocks Ingo Molnar reported that 'make randconfig' was not covering choice blocks properly, resulting in certain config options being left out of randconfig testing altogether. With the following patch we: - properly randomize choice value for normal choice blocks - properly randomize for multi choice blocks - added several comments to explain what is going on The root cause of the bug was that SYMBOL_VALID was set on the symbol representing the choice block so clearing this did the trick initially. But testign revealed a few more issues that is now fixed. Reported-by: Ingo Molnar Cc: Ingo Molnar Cc: Roman Zippel Signed-off-by: Sam Ravnborg --- scripts/kconfig/confdata.c | 51 +++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 830d9eae11f..273d73888f9 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -843,7 +843,7 @@ void conf_set_all_new_symbols(enum conf_def_mode mode) default: continue; } - if (!sym_is_choice(sym) || mode != def_random) + if (!(sym_is_choice(sym) && mode == def_random)) sym->flags |= SYMBOL_DEF_USER; break; default: @@ -856,28 +856,49 @@ void conf_set_all_new_symbols(enum conf_def_mode mode) if (mode != def_random) return; - + /* + * We have different type of choice blocks. + * If curr.tri equal to mod then we can select several + * choice symbols in one block. + * In this case we do nothing. + * If curr.tri equal yes then only one symbol can be + * selected in a choice block and we set it to yes, + * and the rest to no. + */ for_all_symbols(i, csym) { if (sym_has_value(csym) || !sym_is_choice(csym)) continue; sym_calc_value(csym); + + if (csym->curr.tri != yes) + continue; + prop = sym_get_choice_prop(csym); - def = -1; - while (1) { - cnt = 0; - expr_list_for_each_sym(prop->expr, e, sym) { - if (sym->visible == no) - continue; - if (def == cnt++) { - csym->def[S_DEF_USER].val = sym; - break; - } + + /* count entries in choice block */ + cnt = 0; + expr_list_for_each_sym(prop->expr, e, sym) + cnt++; + + /* + * find a random value and set it to yes, + * set the rest to no so we have only one set + */ + def = (rand() % cnt); + + cnt = 0; + expr_list_for_each_sym(prop->expr, e, sym) { + if (def == cnt++) { + sym->def[S_DEF_USER].tri = yes; + csym->def[S_DEF_USER].val = sym; + } + else { + sym->def[S_DEF_USER].tri = no; } - if (def >= 0 || cnt < 2) - break; - def = (rand() % cnt) + 1; } csym->flags |= SYMBOL_DEF_USER; + /* clear VALID to get value calculated */ + csym->flags &= ~(SYMBOL_VALID); } } -- GitLab From b0fe551000179c868d46266278a890eab878baca Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 12 Mar 2009 15:15:31 +0100 Subject: [PATCH 3449/4982] kconfig: improve seed in randconfig 'make randconfig' uses glibc's rand function, and the seed of that PRNG is set via: srand(time(NULL)); But 'time()' only increases once every second - freezing the randconfig result within a single second. My Nehalem testbox does randconfig much faster than 1 second and i have a few scripts that do 'randconfig until condition X' loops. Those scripts currently waste a lot of CPU time due to randconfig changing its seed only once per second currently. Change the seed to be micrseconds based. (I checked the statistical spread of the seed - the now.tv_sec*now.tv_usec multiplication there further improves it.) Signed-off-by: Ingo Molnar Cc: Roman Zippel [sam: fix for systems where usec is zero - noticed by Geert Uytterhoeven] Signed-off-by: Sam Ravnborg --- scripts/kconfig/conf.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index 3e1057f885c..d190092c3b6 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c @@ -11,6 +11,7 @@ #include #include #include +#include #define LKC_DIRECT_LINK #include "lkc.h" @@ -464,9 +465,22 @@ int main(int ac, char **av) input_mode = set_yes; break; case 'r': + { + struct timeval now; + unsigned int seed; + + /* + * Use microseconds derived seed, + * compensate for systems where it may be zero + */ + gettimeofday(&now, NULL); + + seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1)); + srand(seed); + input_mode = set_random; - srand(time(NULL)); break; + } case 'h': printf(_("See README for usage info\n")); exit(0); -- GitLab From 5f0fbf9ecaf354fa4bbf266fffdea2ea3d14a0ed Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 16 Sep 2008 13:05:53 -0400 Subject: [PATCH 3450/4982] [ARM] fixmap support This is the minimum fixmap interface expected to be implemented by architectures supporting highmem. We have a second level page table already allocated and covering 0xfff00000-0xffffffff because the exception vector page is located at 0xffff0000, and various cache tricks already use some entries above 0xffff0000. Therefore the PTEs covering 0xfff00000-0xfffeffff are free to be used. However the XScale cache flushing code already uses virtual addresses between 0xfffe0000 and 0xfffeffff. So this reserves the 0xfff00000-0xfffdffff range for fixmap stuff. The Documentation/arm/memory.txt information is updated accordingly, including the information about the actual top of DMA memory mapping region which didn't match the code. Signed-off-by: Nicolas Pitre --- Documentation/arm/memory.txt | 9 +++++++- arch/arm/include/asm/fixmap.h | 41 +++++++++++++++++++++++++++++++++++ arch/arm/mm/mm.h | 3 +-- 3 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 arch/arm/include/asm/fixmap.h diff --git a/Documentation/arm/memory.txt b/Documentation/arm/memory.txt index dc6045577a8..43cb1004d35 100644 --- a/Documentation/arm/memory.txt +++ b/Documentation/arm/memory.txt @@ -29,7 +29,14 @@ ffff0000 ffff0fff CPU vector page. CPU supports vector relocation (control register V bit.) -ffc00000 fffeffff DMA memory mapping region. Memory returned +fffe0000 fffeffff XScale cache flush area. This is used + in proc-xscale.S to flush the whole data + cache. Free for other usage on non-XScale. + +fff00000 fffdffff Fixmap mapping region. Addresses provided + by fix_to_virt() will be located here. + +ffc00000 ffefffff DMA memory mapping region. Memory returned by the dma_alloc_xxx functions will be dynamically mapped here. diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h new file mode 100644 index 00000000000..bbae919bceb --- /dev/null +++ b/arch/arm/include/asm/fixmap.h @@ -0,0 +1,41 @@ +#ifndef _ASM_FIXMAP_H +#define _ASM_FIXMAP_H + +/* + * Nothing too fancy for now. + * + * On ARM we already have well known fixed virtual addresses imposed by + * the architecture such as the vector page which is located at 0xffff0000, + * therefore a second level page table is already allocated covering + * 0xfff00000 upwards. + * + * The cache flushing code in proc-xscale.S uses the virtual area between + * 0xfffe0000 and 0xfffeffff. + */ + +#define FIXADDR_START 0xfff00000UL +#define FIXADDR_TOP 0xfffe0000UL +#define FIXADDR_SIZE (FIXADDR_TOP - FIXADDR_START) + +#define FIX_KMAP_BEGIN 0 +#define FIX_KMAP_END (FIXADDR_SIZE >> PAGE_SHIFT) + +#define __fix_to_virt(x) (FIXADDR_START + ((x) << PAGE_SHIFT)) +#define __virt_to_fix(x) (((x) - FIXADDR_START) >> PAGE_SHIFT) + +extern void __this_fixmap_does_not_exist(void); + +static inline unsigned long fix_to_virt(const unsigned int idx) +{ + if (idx >= FIX_KMAP_END) + __this_fixmap_does_not_exist(); + return __fix_to_virt(idx); +} + +static inline unsigned int virt_to_fix(const unsigned long vaddr) +{ + BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START); + return __virt_to_fix(vaddr); +} + +#endif diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index 95bbe112965..c4f6f05198e 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h @@ -1,7 +1,6 @@ -/* the upper-most page table pointer */ - #ifdef CONFIG_MMU +/* the upper-most page table pointer */ extern pmd_t *top_pmd; #define TOP_PTE(x) pte_offset_kernel(top_pmd, x) -- GitLab From d73cd42893f4cdc06e6829fea2347bb92cb789d1 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 15 Sep 2008 16:44:55 -0400 Subject: [PATCH 3451/4982] [ARM] kmap support The kmap virtual area borrows a 2MB range at the top of the 16MB area below PAGE_OFFSET currently reserved for kernel modules and/or the XIP kernel. This 2MB corresponds to the range covered by 2 consecutive second-level page tables, or a single pmd entry as seen by the Linux page table abstraction. Because XIP kernels are unlikely to be seen on systems needing highmem support, there shouldn't be any shortage of VM space for modules (14 MB for modules is still way more than twice the typical usage). Because the virtual mapping of highmem pages can go away at any moment after kunmap() is called on them, we need to bypass the delayed cache flushing provided by flush_dcache_page() in that case. The atomic kmap versions are based on fixmaps, and __cpuc_flush_dcache_page() is used directly in that case. Signed-off-by: Nicolas Pitre --- arch/arm/include/asm/highmem.h | 28 ++++++++ arch/arm/include/asm/memory.h | 13 +++- arch/arm/mm/Makefile | 1 + arch/arm/mm/flush.c | 2 +- arch/arm/mm/highmem.c | 116 +++++++++++++++++++++++++++++++++ arch/arm/mm/mmu.c | 13 ++++ 6 files changed, 169 insertions(+), 4 deletions(-) create mode 100644 arch/arm/include/asm/highmem.h create mode 100644 arch/arm/mm/highmem.c diff --git a/arch/arm/include/asm/highmem.h b/arch/arm/include/asm/highmem.h new file mode 100644 index 00000000000..023d5b37454 --- /dev/null +++ b/arch/arm/include/asm/highmem.h @@ -0,0 +1,28 @@ +#ifndef _ASM_HIGHMEM_H +#define _ASM_HIGHMEM_H + +#include + +#define PKMAP_BASE (PAGE_OFFSET - PMD_SIZE) +#define LAST_PKMAP PTRS_PER_PTE +#define LAST_PKMAP_MASK (LAST_PKMAP - 1) +#define PKMAP_NR(virt) (((virt) - PKMAP_BASE) >> PAGE_SHIFT) +#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) + +#define kmap_prot PAGE_KERNEL + +#define flush_cache_kmaps() flush_cache_all() + +extern pte_t *pkmap_page_table; + +extern void *kmap_high(struct page *page); +extern void kunmap_high(struct page *page); + +extern void *kmap(struct page *page); +extern void kunmap(struct page *page); +extern void *kmap_atomic(struct page *page, enum km_type type); +extern void kunmap_atomic(void *kvaddr, enum km_type type); +extern void *kmap_atomic_pfn(unsigned long pfn, enum km_type type); +extern struct page *kmap_atomic_to_page(const void *ptr); + +#endif diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index 0202a7c20e6..ae472bc376d 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -44,13 +44,20 @@ * The module space lives between the addresses given by TASK_SIZE * and PAGE_OFFSET - it must be within 32MB of the kernel text. */ -#define MODULES_END (PAGE_OFFSET) -#define MODULES_VADDR (MODULES_END - 16*1048576) - +#define MODULES_VADDR (PAGE_OFFSET - 16*1024*1024) #if TASK_SIZE > MODULES_VADDR #error Top of user space clashes with start of module space #endif +/* + * The highmem pkmap virtual space shares the end of the module area. + */ +#ifdef CONFIG_HIGHMEM +#define MODULES_END (PAGE_OFFSET - PMD_SIZE) +#else +#define MODULES_END (PAGE_OFFSET) +#endif + /* * The XIP kernel gets mapped at the bottom of the module vm area. * Since we use sections to map it, this macro replaces the physical address diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index 480f78a3611..185e7dc7dcf 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_MODULES) += proc-syms.o obj-$(CONFIG_ALIGNMENT_TRAP) += alignment.o obj-$(CONFIG_DISCONTIGMEM) += discontig.o +obj-$(CONFIG_HIGHMEM) += highmem.o obj-$(CONFIG_CPU_ABRT_NOMMU) += abort-nommu.o obj-$(CONFIG_CPU_ABRT_EV4) += abort-ev4.o diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 0fa9bf388f0..4e283481cee 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c @@ -192,7 +192,7 @@ void flush_dcache_page(struct page *page) struct address_space *mapping = page_mapping(page); #ifndef CONFIG_SMP - if (mapping && !mapping_mapped(mapping)) + if (!PageHighMem(page) && mapping && !mapping_mapped(mapping)) set_bit(PG_dcache_dirty, &page->flags); else #endif diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c new file mode 100644 index 00000000000..a34954d9df7 --- /dev/null +++ b/arch/arm/mm/highmem.c @@ -0,0 +1,116 @@ +/* + * arch/arm/mm/highmem.c -- ARM highmem support + * + * Author: Nicolas Pitre + * Created: september 8, 2008 + * Copyright: Marvell Semiconductors Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include "mm.h" + +void *kmap(struct page *page) +{ + might_sleep(); + if (!PageHighMem(page)) + return page_address(page); + return kmap_high(page); +} +EXPORT_SYMBOL(kmap); + +void kunmap(struct page *page) +{ + BUG_ON(in_interrupt()); + if (!PageHighMem(page)) + return; + kunmap_high(page); +} +EXPORT_SYMBOL(kunmap); + +void *kmap_atomic(struct page *page, enum km_type type) +{ + unsigned int idx; + unsigned long vaddr; + + pagefault_disable(); + if (!PageHighMem(page)) + return page_address(page); + + idx = type + KM_TYPE_NR * smp_processor_id(); + vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); +#ifdef CONFIG_DEBUG_HIGHMEM + /* + * With debugging enabled, kunmap_atomic forces that entry to 0. + * Make sure it was indeed properly unmapped. + */ + BUG_ON(!pte_none(*(TOP_PTE(vaddr)))); +#endif + set_pte_ext(TOP_PTE(vaddr), mk_pte(page, kmap_prot), 0); + /* + * When debugging is off, kunmap_atomic leaves the previous mapping + * in place, so this TLB flush ensures the TLB is updated with the + * new mapping. + */ + local_flush_tlb_kernel_page(vaddr); + + return (void *)vaddr; +} +EXPORT_SYMBOL(kmap_atomic); + +void kunmap_atomic(void *kvaddr, enum km_type type) +{ + unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; + unsigned int idx = type + KM_TYPE_NR * smp_processor_id(); + + if (kvaddr >= (void *)FIXADDR_START) { + __cpuc_flush_dcache_page((void *)vaddr); +#ifdef CONFIG_DEBUG_HIGHMEM + BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx)); + set_pte_ext(TOP_PTE(vaddr), __pte(0), 0); + local_flush_tlb_kernel_page(vaddr); +#else + (void) idx; /* to kill a warning */ +#endif + } + pagefault_enable(); +} +EXPORT_SYMBOL(kunmap_atomic); + +void *kmap_atomic_pfn(unsigned long pfn, enum km_type type) +{ + unsigned int idx; + unsigned long vaddr; + + pagefault_disable(); + + idx = type + KM_TYPE_NR * smp_processor_id(); + vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); +#ifdef CONFIG_DEBUG_HIGHMEM + BUG_ON(!pte_none(*(TOP_PTE(vaddr)))); +#endif + set_pte_ext(TOP_PTE(vaddr), pfn_pte(pfn, kmap_prot), 0); + local_flush_tlb_kernel_page(vaddr); + + return (void *)vaddr; +} + +struct page *kmap_atomic_to_page(const void *ptr) +{ + unsigned long vaddr = (unsigned long)ptr; + pte_t *pte; + + if (vaddr < FIXADDR_START) + return virt_to_page(ptr); + + pte = TOP_PTE(vaddr); + return pte_page(*pte); +} diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index d4d082c5c2d..4810a4c9ffc 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -895,6 +896,17 @@ static void __init devicemaps_init(struct machine_desc *mdesc) flush_cache_all(); } +static void __init kmap_init(void) +{ +#ifdef CONFIG_HIGHMEM + pmd_t *pmd = pmd_off_k(PKMAP_BASE); + pte_t *pte = alloc_bootmem_low_pages(2 * PTRS_PER_PTE * sizeof(pte_t)); + BUG_ON(!pmd_none(*pmd) || !pte); + __pmd_populate(pmd, __pa(pte) | _PAGE_KERNEL_TABLE); + pkmap_page_table = pte + PTRS_PER_PTE; +#endif +} + /* * paging_init() sets up the page tables, initialises the zone memory * maps, and sets up the zero page, bad page and bad page tables. @@ -908,6 +920,7 @@ void __init paging_init(struct machine_desc *mdesc) prepare_page_table(); bootmem_init(); devicemaps_init(mdesc); + kmap_init(); top_pmd = pmd_off_k(0xffff0000); -- GitLab From 3835f6cb645bdb9a58aa6e062fe1d5777f1a9748 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 17 Sep 2008 15:21:55 -0400 Subject: [PATCH 3452/4982] [ARM] mem_init(): make highmem pages available for use Signed-off-by: Nicolas Pitre --- arch/arm/mm/init.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 80fd3b69ae1..8277802ec85 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -485,7 +486,7 @@ void __init mem_init(void) int i, node; #ifndef CONFIG_DISCONTIGMEM - max_mapnr = virt_to_page(high_memory) - mem_map; + max_mapnr = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map; #endif /* this will put all unused low memory onto the freelists */ @@ -504,6 +505,19 @@ void __init mem_init(void) __phys_to_pfn(__pa(swapper_pg_dir)), NULL); #endif +#ifdef CONFIG_HIGHMEM + /* set highmem page free */ + for_each_online_node(node) { + for_each_nodebank (i, &meminfo, node) { + unsigned long start = bank_pfn_start(&meminfo.bank[i]); + unsigned long end = bank_pfn_end(&meminfo.bank[i]); + if (start >= max_low_pfn + PHYS_PFN_OFFSET) + totalhigh_pages += free_area(start, end, NULL); + } + } + totalram_pages += totalhigh_pages; +#endif + /* * Since our memory may not be contiguous, calculate the * real number of pages we have in this system @@ -521,9 +535,10 @@ void __init mem_init(void) initsize = __init_end - __init_begin; printk(KERN_NOTICE "Memory: %luKB available (%dK code, " - "%dK data, %dK init)\n", + "%dK data, %dK init, %luK highmem)\n", (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), - codesize >> 10, datasize >> 10, initsize >> 10); + codesize >> 10, datasize >> 10, initsize >> 10, + (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))); if (PAGE_SIZE >= 16384 && num_physpages <= 128) { extern int sysctl_overcommit_memory; -- GitLab From 3297e760776af18a26bf30046cbaaae2e730c5c2 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 4 Mar 2009 22:49:41 -0500 Subject: [PATCH 3453/4982] highmem: atomic highmem kmap page pinning Most ARM machines have a non IO coherent cache, meaning that the dma_map_*() set of functions must clean and/or invalidate the affected memory manually before DMA occurs. And because the majority of those machines have a VIVT cache, the cache maintenance operations must be performed using virtual addresses. When a highmem page is kunmap'd, its mapping (and cache) remains in place in case it is kmap'd again. However if dma_map_page() is then called with such a page, some cache maintenance on the remaining mapping must be performed. In that case, page_address(page) is non null and we can use that to synchronize the cache. It is unlikely but still possible for kmap() to race and recycle the virtual address obtained above, and use it for another page before some on-going cache invalidation loop in dma_map_page() is done. In that case, the new mapping could end up with dirty cache lines for another page, and the unsuspecting cache invalidation loop in dma_map_page() might simply discard those dirty cache lines resulting in data loss. For example, let's consider this sequence of events: - dma_map_page(..., DMA_FROM_DEVICE) is called on a highmem page. --> - vaddr = page_address(page) is non null. In this case it is likely that the page has valid cache lines associated with vaddr. Remember that the cache is VIVT. --> for (i = vaddr; i < vaddr + PAGE_SIZE; i += 32) invalidate_cache_line(i); *** preemption occurs in the middle of the loop above *** - kmap_high() is called for a different page. --> - last_pkmap_nr wraps to zero and flush_all_zero_pkmaps() is called. The pkmap_count value for the page passed to dma_map_page() above happens to be 1, so the page is unmapped. But prior to that, flush_cache_kmaps() cleared the cache for it. So far so good. - A fresh pkmap entry is assigned for this kmap request. The Murphy law says this pkmap entry will eventually happen to use the same vaddr as the one which used to belong to the other page being processed by dma_map_page() in the preempted thread above. - The kmap_high() caller start dirtying the cache using the just assigned virtual mapping for its page. *** the first thread is rescheduled *** - The for(...) loop is resumed, but now cached data belonging to a different physical page is being discarded ! And this is not only a preemption issue as ARM can be SMP as well, making the above scenario just as likely. Hence the need for some kind of pkmap page pinning which can be used in any context, primarily for the benefit of dma_map_page() on ARM. This provides the necessary interface to cope with the above issue if ARCH_NEEDS_KMAP_HIGH_GET is defined, otherwise the resulting code is unchanged. Signed-off-by: Nicolas Pitre Reviewed-by: MinChan Kim Acked-by: Andrew Morton --- mm/highmem.c | 65 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 57 insertions(+), 8 deletions(-) diff --git a/mm/highmem.c b/mm/highmem.c index b36b83b920f..910198037bf 100644 --- a/mm/highmem.c +++ b/mm/highmem.c @@ -67,6 +67,25 @@ pte_t * pkmap_page_table; static DECLARE_WAIT_QUEUE_HEAD(pkmap_map_wait); +/* + * Most architectures have no use for kmap_high_get(), so let's abstract + * the disabling of IRQ out of the locking in that case to save on a + * potential useless overhead. + */ +#ifdef ARCH_NEEDS_KMAP_HIGH_GET +#define lock_kmap() spin_lock_irq(&kmap_lock) +#define unlock_kmap() spin_unlock_irq(&kmap_lock) +#define lock_kmap_any(flags) spin_lock_irqsave(&kmap_lock, flags) +#define unlock_kmap_any(flags) spin_unlock_irqrestore(&kmap_lock, flags) +#else +#define lock_kmap() spin_lock(&kmap_lock) +#define unlock_kmap() spin_unlock(&kmap_lock) +#define lock_kmap_any(flags) \ + do { spin_lock(&kmap_lock); (void)(flags); } while (0) +#define unlock_kmap_any(flags) \ + do { spin_unlock(&kmap_lock); (void)(flags); } while (0) +#endif + static void flush_all_zero_pkmaps(void) { int i; @@ -113,9 +132,9 @@ static void flush_all_zero_pkmaps(void) */ void kmap_flush_unused(void) { - spin_lock(&kmap_lock); + lock_kmap(); flush_all_zero_pkmaps(); - spin_unlock(&kmap_lock); + unlock_kmap(); } static inline unsigned long map_new_virtual(struct page *page) @@ -145,10 +164,10 @@ start: __set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(&pkmap_map_wait, &wait); - spin_unlock(&kmap_lock); + unlock_kmap(); schedule(); remove_wait_queue(&pkmap_map_wait, &wait); - spin_lock(&kmap_lock); + lock_kmap(); /* Somebody else might have mapped it while we slept */ if (page_address(page)) @@ -184,29 +203,59 @@ void *kmap_high(struct page *page) * For highmem pages, we can't trust "virtual" until * after we have the lock. */ - spin_lock(&kmap_lock); + lock_kmap(); vaddr = (unsigned long)page_address(page); if (!vaddr) vaddr = map_new_virtual(page); pkmap_count[PKMAP_NR(vaddr)]++; BUG_ON(pkmap_count[PKMAP_NR(vaddr)] < 2); - spin_unlock(&kmap_lock); + unlock_kmap(); return (void*) vaddr; } EXPORT_SYMBOL(kmap_high); +#ifdef ARCH_NEEDS_KMAP_HIGH_GET +/** + * kmap_high_get - pin a highmem page into memory + * @page: &struct page to pin + * + * Returns the page's current virtual memory address, or NULL if no mapping + * exists. When and only when a non null address is returned then a + * matching call to kunmap_high() is necessary. + * + * This can be called from any context. + */ +void *kmap_high_get(struct page *page) +{ + unsigned long vaddr, flags; + + lock_kmap_any(flags); + vaddr = (unsigned long)page_address(page); + if (vaddr) { + BUG_ON(pkmap_count[PKMAP_NR(vaddr)] < 1); + pkmap_count[PKMAP_NR(vaddr)]++; + } + unlock_kmap_any(flags); + return (void*) vaddr; +} +#endif + /** * kunmap_high - map a highmem page into memory * @page: &struct page to unmap + * + * If ARCH_NEEDS_KMAP_HIGH_GET is not defined then this may be called + * only from user context. */ void kunmap_high(struct page *page) { unsigned long vaddr; unsigned long nr; + unsigned long flags; int need_wakeup; - spin_lock(&kmap_lock); + lock_kmap_any(flags); vaddr = (unsigned long)page_address(page); BUG_ON(!vaddr); nr = PKMAP_NR(vaddr); @@ -232,7 +281,7 @@ void kunmap_high(struct page *page) */ need_wakeup = waitqueue_active(&pkmap_map_wait); } - spin_unlock(&kmap_lock); + unlock_kmap_any(flags); /* do wake-up, if needed, race-free outside of the spin lock */ if (need_wakeup) -- GitLab From 43377453af83b8ff8c1c731da1508bd6b84ebfea Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 12 Mar 2009 22:52:09 -0400 Subject: [PATCH 3454/4982] [ARM] introduce dma_cache_maint_page() This is a helper to be used by the DMA mapping API to handle cache maintenance for memory identified by a page structure instead of a virtual address. Those pages may or may not be highmem pages, and when they're highmem pages, they may or may not be virtually mapped. When they're not mapped then there is no L1 cache to worry about. But even in that case the L2 cache must be processed since unmapped highmem pages can still be L2 cached. Signed-off-by: Nicolas Pitre --- arch/arm/include/asm/dma-mapping.h | 4 +- arch/arm/include/asm/highmem.h | 3 ++ arch/arm/mm/dma-mapping.c | 72 +++++++++++++++++++++++++++++- 3 files changed, 77 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index 22cb14ec343..59fa762e9c6 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h @@ -57,6 +57,8 @@ static inline dma_addr_t virt_to_dma(struct device *dev, void *addr) * Use the driver DMA support - see dma-mapping.h (dma_sync_*) */ extern void dma_cache_maint(const void *kaddr, size_t size, int rw); +extern void dma_cache_maint_page(struct page *page, unsigned long offset, + size_t size, int rw); /* * Return whether the given device DMA address mask can be supported @@ -316,7 +318,7 @@ static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, BUG_ON(!valid_dma_direction(dir)); if (!arch_is_coherent()) - dma_cache_maint(page_address(page) + offset, size, dir); + dma_cache_maint_page(page, offset, size, dir); return page_to_dma(dev, page) + offset; } diff --git a/arch/arm/include/asm/highmem.h b/arch/arm/include/asm/highmem.h index 023d5b37454..7f36d00600b 100644 --- a/arch/arm/include/asm/highmem.h +++ b/arch/arm/include/asm/highmem.h @@ -15,7 +15,10 @@ extern pte_t *pkmap_page_table; +#define ARCH_NEEDS_KMAP_HIGH_GET + extern void *kmap_high(struct page *page); +extern void *kmap_high_get(struct page *page); extern void kunmap_high(struct page *page); extern void *kmap(struct page *page); diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index f1ef5613ccd..510c179b0ac 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -517,6 +518,74 @@ void dma_cache_maint(const void *start, size_t size, int direction) } EXPORT_SYMBOL(dma_cache_maint); +static void dma_cache_maint_contiguous(struct page *page, unsigned long offset, + size_t size, int direction) +{ + void *vaddr; + unsigned long paddr; + void (*inner_op)(const void *, const void *); + void (*outer_op)(unsigned long, unsigned long); + + switch (direction) { + case DMA_FROM_DEVICE: /* invalidate only */ + inner_op = dmac_inv_range; + outer_op = outer_inv_range; + break; + case DMA_TO_DEVICE: /* writeback only */ + inner_op = dmac_clean_range; + outer_op = outer_clean_range; + break; + case DMA_BIDIRECTIONAL: /* writeback and invalidate */ + inner_op = dmac_flush_range; + outer_op = outer_flush_range; + break; + default: + BUG(); + } + + if (!PageHighMem(page)) { + vaddr = page_address(page) + offset; + inner_op(vaddr, vaddr + size); + } else { + vaddr = kmap_high_get(page); + if (vaddr) { + vaddr += offset; + inner_op(vaddr, vaddr + size); + kunmap_high(page); + } + } + + paddr = page_to_phys(page) + offset; + outer_op(paddr, paddr + size); +} + +void dma_cache_maint_page(struct page *page, unsigned long offset, + size_t size, int dir) +{ + /* + * A single sg entry may refer to multiple physically contiguous + * pages. But we still need to process highmem pages individually. + * If highmem is not configured then the bulk of this loop gets + * optimized out. + */ + size_t left = size; + do { + size_t len = left; + if (PageHighMem(page) && len + offset > PAGE_SIZE) { + if (offset >= PAGE_SIZE) { + page += offset / PAGE_SIZE; + offset %= PAGE_SIZE; + } + len = PAGE_SIZE - offset; + } + dma_cache_maint_contiguous(page, offset, len, dir); + offset = 0; + page++; + left -= len; + } while (left); +} +EXPORT_SYMBOL(dma_cache_maint_page); + /** * dma_map_sg - map a set of SG buffers for streaming mode DMA * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices @@ -614,7 +683,8 @@ void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, continue; if (!arch_is_coherent()) - dma_cache_maint(sg_virt(s), s->length, dir); + dma_cache_maint_page(sg_page(s), s->offset, + s->length, dir); } } EXPORT_SYMBOL(dma_sync_sg_for_device); -- GitLab From 58edb515724f9e63e569536d01ac8d8f8ddb367a Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 9 Sep 2008 15:54:13 -0400 Subject: [PATCH 3455/4982] [ARM] make page_to_dma() highmem aware If a machine class has a custom __virt_to_bus() implementation then it must provide a __arch_page_to_dma() implementation as well which is _not_ based on page_address() to support highmem. This patch fixes existing __arch_page_to_dma() and provide a default implementation otherwise. The default implementation for highmem is based on __pfn_to_bus() which is defined only when no custom __virt_to_bus() is provided by the machine class. That leaves only ebsa110 and footbridge which cannot support highmem until they provide their own __arch_page_to_dma() implementation. But highmem support on those legacy platforms with limited memory is certainly not a priority. Signed-off-by: Nicolas Pitre --- arch/arm/common/dmabounce.c | 7 +++++++ arch/arm/include/asm/dma-mapping.h | 10 ++++++++++ arch/arm/include/asm/memory.h | 1 + arch/arm/mach-iop13xx/include/mach/memory.h | 5 ++++- arch/arm/mach-ks8695/include/mach/memory.h | 6 +++++- arch/arm/plat-omap/include/mach/memory.h | 8 +++++--- 6 files changed, 32 insertions(+), 5 deletions(-) diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index f030f0775be..734ac913599 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -349,6 +350,12 @@ dma_addr_t dma_map_page(struct device *dev, struct page *page, BUG_ON(!valid_dma_direction(dir)); + if (PageHighMem(page)) { + dev_err(dev, "DMA buffer bouncing of HIGHMEM pages " + "is not supported\n"); + return ~0; + } + return map_single(dev, page_address(page) + offset, size, dir); } EXPORT_SYMBOL(dma_map_page); diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index 59fa762e9c6..ff46dfa68a9 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h @@ -15,10 +15,20 @@ * must not be used by drivers. */ #ifndef __arch_page_to_dma + +#if !defined(CONFIG_HIGHMEM) static inline dma_addr_t page_to_dma(struct device *dev, struct page *page) { return (dma_addr_t)__virt_to_bus((unsigned long)page_address(page)); } +#elif defined(__pfn_to_bus) +static inline dma_addr_t page_to_dma(struct device *dev, struct page *page) +{ + return (dma_addr_t)__pfn_to_bus(page_to_pfn(page)); +} +#else +#error "this machine class needs to define __arch_page_to_dma to use HIGHMEM" +#endif static inline void *dma_to_virt(struct device *dev, dma_addr_t addr) { diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index ae472bc376d..85763db8744 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -188,6 +188,7 @@ static inline void *phys_to_virt(unsigned long x) #ifndef __virt_to_bus #define __virt_to_bus __virt_to_phys #define __bus_to_virt __phys_to_virt +#define __pfn_to_bus(x) ((x) << PAGE_SHIFT) #endif static inline __deprecated unsigned long virt_to_bus(void *x) diff --git a/arch/arm/mach-iop13xx/include/mach/memory.h b/arch/arm/mach-iop13xx/include/mach/memory.h index e012bf13c95..42ae29b288a 100644 --- a/arch/arm/mach-iop13xx/include/mach/memory.h +++ b/arch/arm/mach-iop13xx/include/mach/memory.h @@ -59,7 +59,10 @@ static inline unsigned long __lbus_to_virt(dma_addr_t x) }) #define __arch_page_to_dma(dev, page) \ - __arch_virt_to_dma(dev, page_address(page)) + ({ \ + /* __is_lbus_virt() can never be true for RAM pages */ \ + (dma_addr_t)page_to_phys(page); \ + }) #endif /* CONFIG_ARCH_IOP13XX */ #endif /* !ASSEMBLY */ diff --git a/arch/arm/mach-ks8695/include/mach/memory.h b/arch/arm/mach-ks8695/include/mach/memory.h index 6d5887cf574..76e5308685a 100644 --- a/arch/arm/mach-ks8695/include/mach/memory.h +++ b/arch/arm/mach-ks8695/include/mach/memory.h @@ -35,7 +35,11 @@ extern struct bus_type platform_bus_type; __phys_to_virt(x) : __bus_to_virt(x)); }) #define __arch_virt_to_dma(dev, x) ({ is_lbus_device(dev) ? \ (dma_addr_t)__virt_to_phys(x) : (dma_addr_t)__virt_to_bus(x); }) -#define __arch_page_to_dma(dev, x) __arch_virt_to_dma(dev, page_address(x)) +#define __arch_page_to_dma(dev, x) \ + ({ dma_addr_t __dma = page_to_phys(page); \ + if (!is_lbus_device(dev)) \ + __dma = __dma - PHYS_OFFSET + KS8695_PCIMEM_PA; \ + __dma; }) #endif diff --git a/arch/arm/plat-omap/include/mach/memory.h b/arch/arm/plat-omap/include/mach/memory.h index d6b5ca6c7da..99ed564d927 100644 --- a/arch/arm/plat-omap/include/mach/memory.h +++ b/arch/arm/plat-omap/include/mach/memory.h @@ -61,9 +61,11 @@ #define lbus_to_virt(x) ((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET) #define is_lbus_device(dev) (cpu_is_omap15xx() && dev && (strncmp(dev_name(dev), "ohci", 4) == 0)) -#define __arch_page_to_dma(dev, page) ({is_lbus_device(dev) ? \ - (dma_addr_t)virt_to_lbus(page_address(page)) : \ - (dma_addr_t)__virt_to_phys(page_address(page));}) +#define __arch_page_to_dma(dev, page) \ + ({ dma_addr_t __dma = page_to_phys(page); \ + if (is_lbus_device(dev)) \ + __dma = __dma - PHYS_OFFSET + OMAP1510_LB_OFFSET; \ + __dma; }) #define __arch_dma_to_virt(dev, addr) ({ (void *) (is_lbus_device(dev) ? \ lbus_to_virt(addr) : \ -- GitLab From 1bb772679ffb0ba1ff1d40d8c6b855ab029f177d Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 12 Sep 2008 16:11:51 -0400 Subject: [PATCH 3456/4982] [ARM] Feroceon: add highmem support to L2 cache handling code The choice is between looping over the physical range and performing single cache line operations, or to map highmem pages somewhere, as cache range ops are possible only on virtual addresses. Because L2 range ops are much faster, we go with the later by factoring the physical-to-virtual address conversion and use a fixmap entry for it in the HIGHMEM case. Possible future optimizations to avoid the pte setup cost: - do the pte setup for highmem pages only - determine a threshold for doing a line-by-line processing on physical addresses when the range is small Signed-off-by: Nicolas Pitre --- arch/arm/include/asm/kmap_types.h | 1 + arch/arm/mm/cache-feroceon-l2.c | 54 +++++++++++++++++++++---------- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/arch/arm/include/asm/kmap_types.h b/arch/arm/include/asm/kmap_types.h index 45def13ee17..d16ec97ec9a 100644 --- a/arch/arm/include/asm/kmap_types.h +++ b/arch/arm/include/asm/kmap_types.h @@ -18,6 +18,7 @@ enum km_type { KM_IRQ1, KM_SOFTIRQ0, KM_SOFTIRQ1, + KM_L2_CACHE, KM_TYPE_NR }; diff --git a/arch/arm/mm/cache-feroceon-l2.c b/arch/arm/mm/cache-feroceon-l2.c index 80cd207cbae..d6dd83826f8 100644 --- a/arch/arm/mm/cache-feroceon-l2.c +++ b/arch/arm/mm/cache-feroceon-l2.c @@ -14,8 +14,12 @@ #include #include +#include +#include +#include +#include #include - +#include "mm.h" /* * Low-level cache maintenance operations. @@ -34,14 +38,36 @@ * The range operations require two successive cp15 writes, in * between which we don't want to be preempted. */ + +static inline unsigned long l2_start_va(unsigned long paddr) +{ +#ifdef CONFIG_HIGHMEM + /* + * Let's do our own fixmap stuff in a minimal way here. + * Because range ops can't be done on physical addresses, + * we simply install a virtual mapping for it only for the + * TLB lookup to occur, hence no need to flush the untouched + * memory mapping. This is protected with the disabling of + * interrupts by the caller. + */ + unsigned long idx = KM_L2_CACHE + KM_TYPE_NR * smp_processor_id(); + unsigned long vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); + set_pte_ext(TOP_PTE(vaddr), pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL), 0); + local_flush_tlb_kernel_page(vaddr); + return vaddr + (paddr & ~PAGE_MASK); +#else + return __phys_to_virt(paddr); +#endif +} + static inline void l2_clean_pa(unsigned long addr) { __asm__("mcr p15, 1, %0, c15, c9, 3" : : "r" (addr)); } -static inline void l2_clean_mva_range(unsigned long start, unsigned long end) +static inline void l2_clean_pa_range(unsigned long start, unsigned long end) { - unsigned long flags; + unsigned long va_start, va_end, flags; /* * Make sure 'start' and 'end' reference the same page, as @@ -51,17 +77,14 @@ static inline void l2_clean_mva_range(unsigned long start, unsigned long end) BUG_ON((start ^ end) >> PAGE_SHIFT); raw_local_irq_save(flags); + va_start = l2_start_va(start); + va_end = va_start + (end - start); __asm__("mcr p15, 1, %0, c15, c9, 4\n\t" "mcr p15, 1, %1, c15, c9, 5" - : : "r" (start), "r" (end)); + : : "r" (va_start), "r" (va_end)); raw_local_irq_restore(flags); } -static inline void l2_clean_pa_range(unsigned long start, unsigned long end) -{ - l2_clean_mva_range(__phys_to_virt(start), __phys_to_virt(end)); -} - static inline void l2_clean_inv_pa(unsigned long addr) { __asm__("mcr p15, 1, %0, c15, c10, 3" : : "r" (addr)); @@ -72,9 +95,9 @@ static inline void l2_inv_pa(unsigned long addr) __asm__("mcr p15, 1, %0, c15, c11, 3" : : "r" (addr)); } -static inline void l2_inv_mva_range(unsigned long start, unsigned long end) +static inline void l2_inv_pa_range(unsigned long start, unsigned long end) { - unsigned long flags; + unsigned long va_start, va_end, flags; /* * Make sure 'start' and 'end' reference the same page, as @@ -84,17 +107,14 @@ static inline void l2_inv_mva_range(unsigned long start, unsigned long end) BUG_ON((start ^ end) >> PAGE_SHIFT); raw_local_irq_save(flags); + va_start = l2_start_va(start); + va_end = va_start + (end - start); __asm__("mcr p15, 1, %0, c15, c11, 4\n\t" "mcr p15, 1, %1, c15, c11, 5" - : : "r" (start), "r" (end)); + : : "r" (va_start), "r" (va_end)); raw_local_irq_restore(flags); } -static inline void l2_inv_pa_range(unsigned long start, unsigned long end) -{ - l2_inv_mva_range(__phys_to_virt(start), __phys_to_virt(end)); -} - /* * Linux primitives. -- GitLab From 3902a15e784e9b1efa8e6ad246489c609e0ef880 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 18 Sep 2008 22:55:47 -0400 Subject: [PATCH 3457/4982] [ARM] xsc3: add highmem support to L2 cache handling code On xsc3, L2 cache ops are possible only on virtual addresses. The code is rearranged so to have a linear progression requiring the least amount of pte setups in the highmem case. To protect the virtual mapping so created, interrupts must be disabled currently up to a page worth of address range. The interrupt disabling is done in a way to minimize the overhead within the inner loop. The alternative would consist in separate code for the highmem and non highmem compilation which is less preferable. Signed-off-by: Nicolas Pitre --- arch/arm/mm/cache-xsc3l2.c | 107 +++++++++++++++++++++++++++---------- 1 file changed, 80 insertions(+), 27 deletions(-) diff --git a/arch/arm/mm/cache-xsc3l2.c b/arch/arm/mm/cache-xsc3l2.c index 464de893a98..5d180cb0bd9 100644 --- a/arch/arm/mm/cache-xsc3l2.c +++ b/arch/arm/mm/cache-xsc3l2.c @@ -17,12 +17,14 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include -#include -#include - #include #include #include +#include +#include +#include +#include +#include "mm.h" #define CR_L2 (1 << 26) @@ -47,21 +49,11 @@ static inline void xsc3_l2_clean_mva(unsigned long addr) __asm__("mcr p15, 1, %0, c7, c11, 1" : : "r" (addr)); } -static inline void xsc3_l2_clean_pa(unsigned long addr) -{ - xsc3_l2_clean_mva(__phys_to_virt(addr)); -} - static inline void xsc3_l2_inv_mva(unsigned long addr) { __asm__("mcr p15, 1, %0, c7, c7, 1" : : "r" (addr)); } -static inline void xsc3_l2_inv_pa(unsigned long addr) -{ - xsc3_l2_inv_mva(__phys_to_virt(addr)); -} - static inline void xsc3_l2_inv_all(void) { unsigned long l2ctype, set_way; @@ -79,50 +71,103 @@ static inline void xsc3_l2_inv_all(void) dsb(); } +#ifdef CONFIG_HIGHMEM +#define l2_map_save_flags(x) raw_local_save_flags(x) +#define l2_map_restore_flags(x) raw_local_irq_restore(x) +#else +#define l2_map_save_flags(x) ((x) = 0) +#define l2_map_restore_flags(x) ((void)(x)) +#endif + +static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va, + unsigned long flags) +{ +#ifdef CONFIG_HIGHMEM + unsigned long va = prev_va & PAGE_MASK; + unsigned long pa_offset = pa << (32 - PAGE_SHIFT); + if (unlikely(pa_offset < (prev_va << (32 - PAGE_SHIFT)))) { + /* + * Switching to a new page. Because cache ops are + * using virtual addresses only, we must put a mapping + * in place for it. We also enable interrupts for a + * short while and disable them again to protect this + * mapping. + */ + unsigned long idx; + raw_local_irq_restore(flags); + idx = KM_L2_CACHE + KM_TYPE_NR * smp_processor_id(); + va = __fix_to_virt(FIX_KMAP_BEGIN + idx); + raw_local_irq_restore(flags | PSR_I_BIT); + set_pte_ext(TOP_PTE(va), pfn_pte(pa >> PAGE_SHIFT, PAGE_KERNEL), 0); + local_flush_tlb_kernel_page(va); + } + return va + (pa_offset >> (32 - PAGE_SHIFT)); +#else + return __phys_to_virt(pa); +#endif +} + static void xsc3_l2_inv_range(unsigned long start, unsigned long end) { + unsigned long vaddr, flags; + if (start == 0 && end == -1ul) { xsc3_l2_inv_all(); return; } + vaddr = -1; /* to force the first mapping */ + l2_map_save_flags(flags); + /* * Clean and invalidate partial first cache line. */ if (start & (CACHE_LINE_SIZE - 1)) { - xsc3_l2_clean_pa(start & ~(CACHE_LINE_SIZE - 1)); - xsc3_l2_inv_pa(start & ~(CACHE_LINE_SIZE - 1)); + vaddr = l2_map_va(start & ~(CACHE_LINE_SIZE - 1), vaddr, flags); + xsc3_l2_clean_mva(vaddr); + xsc3_l2_inv_mva(vaddr); start = (start | (CACHE_LINE_SIZE - 1)) + 1; } /* - * Clean and invalidate partial last cache line. + * Invalidate all full cache lines between 'start' and 'end'. */ - if (start < end && (end & (CACHE_LINE_SIZE - 1))) { - xsc3_l2_clean_pa(end & ~(CACHE_LINE_SIZE - 1)); - xsc3_l2_inv_pa(end & ~(CACHE_LINE_SIZE - 1)); - end &= ~(CACHE_LINE_SIZE - 1); + while (start < (end & ~(CACHE_LINE_SIZE - 1))) { + vaddr = l2_map_va(start, vaddr, flags); + xsc3_l2_inv_mva(vaddr); + start += CACHE_LINE_SIZE; } /* - * Invalidate all full cache lines between 'start' and 'end'. + * Clean and invalidate partial last cache line. */ - while (start < end) { - xsc3_l2_inv_pa(start); - start += CACHE_LINE_SIZE; + if (start < end) { + vaddr = l2_map_va(start, vaddr, flags); + xsc3_l2_clean_mva(vaddr); + xsc3_l2_inv_mva(vaddr); } + l2_map_restore_flags(flags); + dsb(); } static void xsc3_l2_clean_range(unsigned long start, unsigned long end) { + unsigned long vaddr, flags; + + vaddr = -1; /* to force the first mapping */ + l2_map_save_flags(flags); + start &= ~(CACHE_LINE_SIZE - 1); while (start < end) { - xsc3_l2_clean_pa(start); + vaddr = l2_map_va(start, vaddr, flags); + xsc3_l2_clean_mva(vaddr); start += CACHE_LINE_SIZE; } + l2_map_restore_flags(flags); + dsb(); } @@ -148,18 +193,26 @@ static inline void xsc3_l2_flush_all(void) static void xsc3_l2_flush_range(unsigned long start, unsigned long end) { + unsigned long vaddr, flags; + if (start == 0 && end == -1ul) { xsc3_l2_flush_all(); return; } + vaddr = -1; /* to force the first mapping */ + l2_map_save_flags(flags); + start &= ~(CACHE_LINE_SIZE - 1); while (start < end) { - xsc3_l2_clean_pa(start); - xsc3_l2_inv_pa(start); + vaddr = l2_map_va(start, vaddr, flags); + xsc3_l2_clean_mva(vaddr); + xsc3_l2_inv_mva(vaddr); start += CACHE_LINE_SIZE; } + l2_map_restore_flags(flags); + dsb(); } -- GitLab From 3f973e22160257c5bda85815be5b1540d391a671 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 4 Nov 2008 00:48:42 -0500 Subject: [PATCH 3458/4982] [ARM] ignore high memory with VIPT aliasing caches VIPT aliasing caches have issues of their own which are not yet handled. Usage of discard_old_kernel_data() in copypage-v6.c is not highmem ready, kmap/fixmap stuff doesn't take account of cache colouring, etc. If/when those issues are handled then this could be reverted. Signed-off-by: Nicolas Pitre --- arch/arm/mm/mmu.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 4810a4c9ffc..cf504885a5f 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -678,6 +679,10 @@ static void __init sanity_check_meminfo(void) if (meminfo.nr_banks >= NR_BANKS) { printk(KERN_CRIT "NR_BANKS too low, " "ignoring high memory\n"); + } else if (cache_is_vipt_aliasing()) { + printk(KERN_CRIT "HIGHMEM is not yet supported " + "with VIPT aliasing cache, " + "ignoring high memory\n"); } else { memmove(bank + 1, bank, (meminfo.nr_banks - i) * sizeof(*bank)); -- GitLab From 053a96ca11a9785a7e63fc89eed4514a6446ec58 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 19 Sep 2008 00:36:12 -0400 Subject: [PATCH 3459/4982] [ARM] add CONFIG_HIGHMEM option Here it is... HIGHMEM for the ARM architecture. :-) If you don't have enough ram for highmem pages to be allocated and still want to test this, then the cmdline option "vmalloc=" can be used with a value large enough to force the highmem threshold down. Successfully tested on a Marvell DB-78x00-BP Development Board with 2 GB of RAM. Signed-off-by: Nicolas Pitre --- arch/arm/Kconfig | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index dbfdf87f993..2b28786b387 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -915,6 +915,23 @@ config NODES_SHIFT default "2" depends on NEED_MULTIPLE_NODES +config HIGHMEM + bool "High Memory Support (EXPERIMENTAL)" + depends on MMU && EXPERIMENTAL + help + The address space of ARM processors is only 4 Gigabytes large + and it has to accommodate user address space, kernel address + space as well as some memory mapped IO. That means that, if you + have a large amount of physical memory and/or IO, not all of the + memory can be "permanently mapped" by the kernel. The physical + memory that is not permanently mapped is called "high memory". + + Depending on the selected kernel/user memory split, minimum + vmalloc space and actual amount of RAM, you may not need this + option which should result in a slightly faster kernel. + + If unsure, say n. + source "mm/Kconfig" config LEDS -- GitLab From 4640fa606bf996d275a6e208e3654e9e943afe60 Mon Sep 17 00:00:00 2001 From: Shadi Ammouri Date: Tue, 24 Feb 2009 15:26:23 -0500 Subject: [PATCH 3460/4982] [ARM] Kirkwood: Marvell SheevaPlug support Signed-off-by: Nicolas Pitre --- arch/arm/mach-kirkwood/Kconfig | 6 ++ arch/arm/mach-kirkwood/Makefile | 1 + arch/arm/mach-kirkwood/sheevaplug-setup.c | 98 +++++++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 arch/arm/mach-kirkwood/sheevaplug-setup.c diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig index 3600cd9f051..532443622a1 100644 --- a/arch/arm/mach-kirkwood/Kconfig +++ b/arch/arm/mach-kirkwood/Kconfig @@ -20,6 +20,12 @@ config MACH_RD88F6281 Say 'Y' here if you want your kernel to support the Marvell RD-88F6281 Reference Board. +config MACH_SHEEVAPLUG + bool "Marvell SheevaPlug Reference Board" + help + Say 'Y' here if you want your kernel to support the + Marvell SheevaPlug Reference Board. + endmenu endif diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile index fdff35cc8d5..de81b4b5bd3 100644 --- a/arch/arm/mach-kirkwood/Makefile +++ b/arch/arm/mach-kirkwood/Makefile @@ -3,3 +3,4 @@ obj-y += common.o addr-map.o irq.o pcie.o mpp.o obj-$(CONFIG_MACH_DB88F6281_BP) += db88f6281-bp-setup.o obj-$(CONFIG_MACH_RD88F6192_NAS) += rd88f6192-nas-setup.o obj-$(CONFIG_MACH_RD88F6281) += rd88f6281-setup.o +obj-$(CONFIG_MACH_SHEEVAPLUG) += sheevaplug-setup.o diff --git a/arch/arm/mach-kirkwood/sheevaplug-setup.c b/arch/arm/mach-kirkwood/sheevaplug-setup.c new file mode 100644 index 00000000000..d48989dfe4d --- /dev/null +++ b/arch/arm/mach-kirkwood/sheevaplug-setup.c @@ -0,0 +1,98 @@ +/* + * arch/arm/mach-kirkwood/sheevaplug-setup.c + * + * Marvell SheevaPlug Reference Board Setup + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" + +static struct mtd_partition sheevaplug_nand_parts[] = { + { + .name = "u-boot", + .offset = 0, + .size = SZ_1M + }, { + .name = "uImage", + .offset = MTDPART_OFS_NXTBLK, + .size = SZ_4M + }, { + .name = "root", + .offset = MTDPART_OFS_NXTBLK, + .size = MTDPART_SIZ_FULL + }, +}; + +static struct resource sheevaplug_nand_resource = { + .flags = IORESOURCE_MEM, + .start = KIRKWOOD_NAND_MEM_PHYS_BASE, + .end = KIRKWOOD_NAND_MEM_PHYS_BASE + + KIRKWOOD_NAND_MEM_SIZE - 1, +}; + +static struct orion_nand_data sheevaplug_nand_data = { + .parts = sheevaplug_nand_parts, + .nr_parts = ARRAY_SIZE(sheevaplug_nand_parts), + .cle = 0, + .ale = 1, + .width = 8, + .chip_delay = 25, +}; + +static struct platform_device sheevaplug_nand_flash = { + .name = "orion_nand", + .id = -1, + .dev = { + .platform_data = &sheevaplug_nand_data, + }, + .resource = &sheevaplug_nand_resource, + .num_resources = 1, +}; + +static struct mv643xx_eth_platform_data sheevaplug_ge00_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(0), +}; + +static struct mvsdio_platform_data sheevaplug_mvsdio_data = { + // unfortunately the CD signal has not been connected */ +}; + +static void __init sheevaplug_init(void) +{ + /* + * Basic setup. Needs to be called early. + */ + kirkwood_init(); + + kirkwood_uart0_init(); + kirkwood_ehci_init(); + kirkwood_ge00_init(&sheevaplug_ge00_data); + kirkwood_sdio_init(&sheevaplug_mvsdio_data); + + platform_device_register(&sheevaplug_nand_flash); +} + +MACHINE_START(SHEEVAPLUG, "Marvell SheevaPlug Reference Board") + /* Maintainer: shadi Ammouri */ + .phys_io = KIRKWOOD_REGS_PHYS_BASE, + .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .init_machine = sheevaplug_init, + .map_io = kirkwood_map_io, + .init_irq = kirkwood_init_irq, + .timer = &kirkwood_timer, +MACHINE_END -- GitLab From 3ec0d47427be9ff5b82ba5c5e853c691a942ed65 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 2 Mar 2009 23:44:41 -0500 Subject: [PATCH 3461/4982] [ARM] Kirkwood: SheevaPlug USB Power Enable setup Ideally, the default should be set to 0 and let the EHCI driver turn it on as needed. This makes USB usable in the mean time. Signed-off-by: Nicolas Pitre --- arch/arm/mach-kirkwood/sheevaplug-setup.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm/mach-kirkwood/sheevaplug-setup.c b/arch/arm/mach-kirkwood/sheevaplug-setup.c index d48989dfe4d..c1cb9f4d346 100644 --- a/arch/arm/mach-kirkwood/sheevaplug-setup.c +++ b/arch/arm/mach-kirkwood/sheevaplug-setup.c @@ -14,12 +14,14 @@ #include #include #include +#include #include #include #include #include #include #include "common.h" +#include "mpp.h" static struct mtd_partition sheevaplug_nand_parts[] = { { @@ -71,15 +73,26 @@ static struct mvsdio_platform_data sheevaplug_mvsdio_data = { // unfortunately the CD signal has not been connected */ }; +static unsigned int sheevaplug_mpp_config[] __initdata = { + MPP29_GPIO, /* USB Power Enable */ + 0 +}; + static void __init sheevaplug_init(void) { /* * Basic setup. Needs to be called early. */ kirkwood_init(); + kirkwood_mpp_conf(sheevaplug_mpp_config); kirkwood_uart0_init(); + + if (gpio_request(29, "USB Power Enable") != 0 || + gpio_direction_output(29, 1) != 0) + printk(KERN_ERR "can't set up GPIO 29 (USB Power Enable)\n"); kirkwood_ehci_init(); + kirkwood_ge00_init(&sheevaplug_ge00_data); kirkwood_sdio_init(&sheevaplug_mvsdio_data); -- GitLab From e96c33d9eddcea86ffd39a592eaca8bb21792002 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 3 Mar 2009 01:16:07 -0500 Subject: [PATCH 3462/4982] [ARM] Kirkwood: SheevaPlug LED support Signed-off-by: Nicolas Pitre --- arch/arm/mach-kirkwood/sheevaplug-setup.c | 25 +++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/arch/arm/mach-kirkwood/sheevaplug-setup.c b/arch/arm/mach-kirkwood/sheevaplug-setup.c index c1cb9f4d346..831e4a56cae 100644 --- a/arch/arm/mach-kirkwood/sheevaplug-setup.c +++ b/arch/arm/mach-kirkwood/sheevaplug-setup.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -73,8 +74,31 @@ static struct mvsdio_platform_data sheevaplug_mvsdio_data = { // unfortunately the CD signal has not been connected */ }; +static struct gpio_led sheevaplug_led_pins[] = { + { + .name = "plug:green:health", + .default_trigger = "default-on", + .gpio = 49, + .active_low = 1, + }, +}; + +static struct gpio_led_platform_data sheevaplug_led_data = { + .leds = sheevaplug_led_pins, + .num_leds = ARRAY_SIZE(sheevaplug_led_pins), +}; + +static struct platform_device sheevaplug_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &sheevaplug_led_data, + } +}; + static unsigned int sheevaplug_mpp_config[] __initdata = { MPP29_GPIO, /* USB Power Enable */ + MPP49_GPIO, /* LED */ 0 }; @@ -97,6 +121,7 @@ static void __init sheevaplug_init(void) kirkwood_sdio_init(&sheevaplug_mvsdio_data); platform_device_register(&sheevaplug_nand_flash); + platform_device_register(&sheevaplug_leds); } MACHINE_START(SHEEVAPLUG, "Marvell SheevaPlug Reference Board") -- GitLab From 698fe13b215ec6b956e867dcbc4a4c0992a61ca2 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 3 Mar 2009 22:19:03 -0500 Subject: [PATCH 3463/4982] [ARM] Kirkwood: update defconfig Signed-off-by: Nicolas Pitre --- arch/arm/configs/kirkwood_defconfig | 225 ++++++++++++++++++++-------- 1 file changed, 163 insertions(+), 62 deletions(-) diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig index 4bc38078d58..9ed4e1b8667 100644 --- a/arch/arm/configs/kirkwood_defconfig +++ b/arch/arm/configs/kirkwood_defconfig @@ -1,11 +1,11 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.28-rc7 -# Thu Dec 4 15:27:39 2008 +# Linux kernel version: 2.6.29-rc5 +# Tue Mar 3 21:45:57 2009 # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y -# CONFIG_GENERIC_GPIO is not set +CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_MMU=y @@ -42,10 +42,19 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set # CONFIG_IKCONFIG is not set -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CGROUPS is not set +CONFIG_LOG_BUF_SHIFT=19 # CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set # CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set CONFIG_NAMESPACES=y @@ -53,6 +62,7 @@ CONFIG_NAMESPACES=y # CONFIG_IPC_NS is not set # CONFIG_USER_NS is not set # CONFIG_PID_NS is not set +# CONFIG_NET_NS is not set # CONFIG_BLK_DEV_INITRD is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y @@ -83,6 +93,7 @@ CONFIG_SLUB_DEBUG=y CONFIG_SLUB=y # CONFIG_SLOB is not set CONFIG_PROFILING=y +CONFIG_TRACEPOINTS=y # CONFIG_MARKERS is not set CONFIG_OPROFILE=y CONFIG_HAVE_OPROFILE=y @@ -93,7 +104,6 @@ CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 CONFIG_MODULES=y # CONFIG_MODULE_FORCE_LOAD is not set @@ -101,11 +111,9 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y CONFIG_BLOCK=y # CONFIG_LBD is not set # CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_INTEGRITY is not set @@ -121,7 +129,6 @@ CONFIG_IOSCHED_CFQ=y CONFIG_DEFAULT_CFQ=y # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="cfq" -CONFIG_CLASSIC_RCU=y # CONFIG_FREEZER is not set # @@ -132,7 +139,6 @@ CONFIG_CLASSIC_RCU=y # CONFIG_ARCH_REALVIEW is not set # CONFIG_ARCH_VERSATILE is not set # CONFIG_ARCH_AT91 is not set -# CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_EP93XX is not set @@ -159,11 +165,13 @@ CONFIG_ARCH_KIRKWOOD=y # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set # CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set # CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP is not set # CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_W90X900 is not set # # Marvell Kirkwood Implementations @@ -171,14 +179,7 @@ CONFIG_ARCH_KIRKWOOD=y CONFIG_MACH_DB88F6281_BP=y CONFIG_MACH_RD88F6192_NAS=y CONFIG_MACH_RD88F6281=y - -# -# Boot options -# - -# -# Power management -# +CONFIG_MACH_SHEEVAPLUG=y CONFIG_PLAT_ORION=y # @@ -214,6 +215,7 @@ CONFIG_PCI_SYSCALL=y # CONFIG_ARCH_SUPPORTS_MSI is not set CONFIG_PCI_LEGACY=y # CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_STUB is not set # CONFIG_PCCARD is not set # @@ -242,7 +244,6 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4096 -# CONFIG_RESOURCES_64BIT is not set # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 CONFIG_VIRT_TO_BUS=y @@ -291,6 +292,7 @@ CONFIG_NET=y # # Networking options # +CONFIG_COMPAT_NET_DEV_OPS=y CONFIG_PACKET=y CONFIG_PACKET_MMAP=y CONFIG_UNIX=y @@ -355,6 +357,7 @@ CONFIG_NET_DSA_MV88E6123_61_65=y # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set # # Network testing @@ -368,12 +371,27 @@ CONFIG_NET_PKTGEN=m # CONFIG_AF_RXRPC is not set # CONFIG_PHONET is not set CONFIG_WIRELESS=y -# CONFIG_CFG80211 is not set +CONFIG_CFG80211=y +# CONFIG_CFG80211_REG_DEBUG is not set +# CONFIG_NL80211 is not set CONFIG_WIRELESS_OLD_REGULATORY=y CONFIG_WIRELESS_EXT=y CONFIG_WIRELESS_EXT_SYSFS=y -# CONFIG_MAC80211 is not set -# CONFIG_IEEE80211 is not set +CONFIG_LIB80211=y +CONFIG_MAC80211=y + +# +# Rate control algorithm selection +# +CONFIG_MAC80211_RC_MINSTREL=y +# CONFIG_MAC80211_RC_DEFAULT_PID is not set +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel" +# CONFIG_MAC80211_MESH is not set +# CONFIG_MAC80211_LEDS is not set +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +# CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set @@ -398,6 +416,7 @@ CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set # CONFIG_MTD_CONCAT is not set CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set # CONFIG_MTD_REDBOOT_PARTS is not set CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_AFS_PARTS is not set @@ -451,9 +470,7 @@ CONFIG_MTD_CFI_UTIL=y # # CONFIG_MTD_COMPLEX_MAPPINGS is not set CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_PHYSMAP_START=0x0 -CONFIG_MTD_PHYSMAP_LEN=0x0 -CONFIG_MTD_PHYSMAP_BANKWIDTH=0 +# CONFIG_MTD_PHYSMAP_COMPAT is not set # CONFIG_MTD_ARM_INTEGRATOR is not set # CONFIG_MTD_IMPA7 is not set # CONFIG_MTD_INTEL_VR_NOR is not set @@ -481,6 +498,7 @@ CONFIG_MTD_NAND=y # CONFIG_MTD_NAND_VERIFY_WRITE is not set # CONFIG_MTD_NAND_ECC_SMC is not set # CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set CONFIG_MTD_NAND_IDS=y # CONFIG_MTD_NAND_DISKONCHIP is not set # CONFIG_MTD_NAND_CAFE is not set @@ -490,6 +508,12 @@ CONFIG_MTD_NAND_IDS=y CONFIG_MTD_NAND_ORION=y # CONFIG_MTD_ONENAND is not set +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_QINFO_PROBE is not set + # # UBI - Unsorted block images # @@ -568,6 +592,8 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set # CONFIG_SCSI_HPTIOP is not set +# CONFIG_LIBFC is not set +# CONFIG_FCOE is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_IPS is not set @@ -682,6 +708,9 @@ CONFIG_MARVELL_PHY=y # CONFIG_BROADCOM_PHY is not set # CONFIG_ICPLUS_PHY is not set # CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set # CONFIG_FIXED_PHY is not set # CONFIG_MDIO_BITBANG is not set CONFIG_NET_ETHERNET=y @@ -695,6 +724,7 @@ CONFIG_MII=y # CONFIG_DM9000 is not set # CONFIG_ENC28J60 is not set # CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set # CONFIG_IBM_NEW_EMAC_ZMII is not set @@ -710,7 +740,6 @@ CONFIG_NET_PCI=y # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set -# CONFIG_EEPRO100 is not set # CONFIG_E100 is not set # CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set @@ -720,6 +749,7 @@ CONFIG_NET_PCI=y # CONFIG_R6040 is not set # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set +# CONFIG_SMSC9420 is not set # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set @@ -754,8 +784,39 @@ CONFIG_MV643XX_ETH=y # Wireless LAN # # CONFIG_WLAN_PRE80211 is not set -# CONFIG_WLAN_80211 is not set +CONFIG_WLAN_80211=y +CONFIG_LIBERTAS=y +# CONFIG_LIBERTAS_USB is not set +CONFIG_LIBERTAS_SDIO=y +# CONFIG_LIBERTAS_DEBUG is not set +# CONFIG_LIBERTAS_THINFIRM is not set +# CONFIG_HERMES is not set +# CONFIG_ATMEL is not set +# CONFIG_PRISM54 is not set +# CONFIG_USB_ZD1201 is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_RTL8180 is not set +# CONFIG_RTL8187 is not set +# CONFIG_ADM8211 is not set +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_P54_COMMON is not set +# CONFIG_ATH5K is not set +# CONFIG_ATH9K is not set +# CONFIG_IPW2100 is not set +# CONFIG_IPW2200 is not set +# CONFIG_IWLCORE is not set # CONFIG_IWLWIFI_LEDS is not set +# CONFIG_IWLAGN is not set +# CONFIG_IWL3945 is not set +# CONFIG_HOSTAP is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +# CONFIG_ZD1211RW is not set +# CONFIG_RT2X00 is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# # # USB Network Adapters @@ -839,11 +900,11 @@ CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=16 # CONFIG_IPMI_HANDLER is not set # CONFIG_HW_RANDOM is not set -# CONFIG_NVRAM is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set # CONFIG_RAW_DRIVER is not set @@ -879,6 +940,7 @@ CONFIG_I2C_HELPER_AUTO=y # # I2C system bus drivers (mostly embedded / system-on-chip) # +# CONFIG_I2C_GPIO is not set CONFIG_I2C_MV64XXX=y # CONFIG_I2C_OCORES is not set # CONFIG_I2C_SIMTEC is not set @@ -905,8 +967,6 @@ CONFIG_I2C_MV64XXX=y # Miscellaneous I2C Chip support # # CONFIG_DS1682 is not set -# CONFIG_EEPROM_AT24 is not set -# CONFIG_EEPROM_LEGACY is not set # CONFIG_SENSORS_PCF8574 is not set # CONFIG_PCF8575 is not set # CONFIG_SENSORS_PCA9539 is not set @@ -925,12 +985,12 @@ CONFIG_SPI_MASTER=y # SPI Master Controller Drivers # # CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_GPIO is not set CONFIG_SPI_ORION=y # # SPI Protocol Masters # -# CONFIG_EEPROM_AT25 is not set # CONFIG_SPI_SPIDEV is not set # CONFIG_SPI_TLE62X0 is not set # CONFIG_W1 is not set @@ -952,10 +1012,12 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_TWL4030_CORE is not set # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set # # Multimedia devices @@ -1012,11 +1074,9 @@ CONFIG_HID_COMPAT=y CONFIG_HID_A4TECH=y CONFIG_HID_APPLE=y CONFIG_HID_BELKIN=y -CONFIG_HID_BRIGHT=y CONFIG_HID_CHERRY=y CONFIG_HID_CHICONY=y CONFIG_HID_CYPRESS=y -CONFIG_HID_DELL=y CONFIG_HID_EZKEY=y CONFIG_HID_GYRATION=y CONFIG_HID_LOGITECH=y @@ -1024,12 +1084,15 @@ CONFIG_HID_LOGITECH=y # CONFIG_LOGIRUMBLEPAD2_FF is not set CONFIG_HID_MICROSOFT=y CONFIG_HID_MONTEREY=y +CONFIG_HID_NTRIG=y CONFIG_HID_PANTHERLORD=y # CONFIG_PANTHERLORD_FF is not set CONFIG_HID_PETALYNX=y CONFIG_HID_SAMSUNG=y CONFIG_HID_SONY=y CONFIG_HID_SUNPLUS=y +# CONFIG_GREENASIA_FF is not set +CONFIG_HID_TOPSEED=y # CONFIG_THRUSTMASTER_FF is not set # CONFIG_ZEROPLUS_FF is not set CONFIG_USB_SUPPORT=y @@ -1058,6 +1121,7 @@ CONFIG_USB_DEVICE_CLASS=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y +# CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set # CONFIG_USB_OHCI_HCD is not set @@ -1087,7 +1151,6 @@ CONFIG_USB_STORAGE=y CONFIG_USB_STORAGE_DATAFAB=y CONFIG_USB_STORAGE_FREECOM=y # CONFIG_USB_STORAGE_ISD200 is not set -CONFIG_USB_STORAGE_DPCM=y # CONFIG_USB_STORAGE_USBAT is not set CONFIG_USB_STORAGE_SDDR09=y CONFIG_USB_STORAGE_SDDR55=y @@ -1135,21 +1198,51 @@ CONFIG_USB_STORAGE_JUMPSHOT=y # CONFIG_USB_ISIGHTFW is not set # CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_USB_GPIO_VBUS is not set # CONFIG_UWB is not set -# CONFIG_MMC is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +CONFIG_SDIO_UART=y +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_TIFM_SD is not set +CONFIG_MMC_MVSDIO=y +# CONFIG_MMC_SPI is not set # CONFIG_MEMSTICK is not set # CONFIG_ACCESSIBILITY is not set CONFIG_NEW_LEDS=y -# CONFIG_LEDS_CLASS is not set +CONFIG_LEDS_CLASS=y # # LED drivers # +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_PCA955X is not set # # LED Triggers # -# CONFIG_LEDS_TRIGGERS is not set +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y CONFIG_RTC_LIB=y CONFIG_RTC_CLASS=y CONFIG_RTC_HCTOSYS=y @@ -1227,6 +1320,7 @@ CONFIG_DMA_ENGINE=y # CONFIG_DMATEST is not set # CONFIG_REGULATOR is not set # CONFIG_UIO is not set +# CONFIG_STAGING is not set # # File systems @@ -1238,16 +1332,14 @@ CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set # CONFIG_EXT4_FS is not set CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set CONFIG_FILE_LOCKING=y -CONFIG_XFS_FS=y -# CONFIG_XFS_QUOTA is not set -# CONFIG_XFS_POSIX_ACL is not set -# CONFIG_XFS_RT is not set -# CONFIG_XFS_DEBUG is not set +# CONFIG_XFS_FS is not set # CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y @@ -1268,9 +1360,9 @@ CONFIG_UDF_NLS=y # # DOS/FAT/NT Filesystems # -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y CONFIG_FAT_DEFAULT_CODEPAGE=437 CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_NTFS_FS is not set @@ -1286,10 +1378,7 @@ CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set # CONFIG_CONFIGFS_FS is not set - -# -# Miscellaneous filesystems -# +CONFIG_MISC_FILESYSTEMS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set @@ -1309,6 +1398,7 @@ CONFIG_JFFS2_ZLIB=y CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set CONFIG_CRAMFS=y +# CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_OMFS_FS is not set @@ -1393,7 +1483,7 @@ CONFIG_ENABLE_MUST_CHECK=y CONFIG_FRAME_WARN=1024 CONFIG_MAGIC_SYSRQ=y # CONFIG_UNUSED_SYMBOLS is not set -# CONFIG_DEBUG_FS is not set +CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SHIRQ is not set @@ -1416,6 +1506,7 @@ CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 # CONFIG_LOCK_STAT is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +CONFIG_STACKTRACE=y # CONFIG_DEBUG_KOBJECT is not set CONFIG_DEBUG_BUGVERBOSE=y CONFIG_DEBUG_INFO=y @@ -1424,7 +1515,7 @@ CONFIG_DEBUG_INFO=y CONFIG_DEBUG_MEMORY_INIT=y # CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_SG is not set -CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_NOTIFIERS is not set # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set @@ -1435,7 +1526,10 @@ CONFIG_FRAME_POINTER=y # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_RING_BUFFER=y +CONFIG_TRACING=y # # Tracers @@ -1446,11 +1540,14 @@ CONFIG_HAVE_FUNCTION_TRACER=y # CONFIG_SCHED_TRACER is not set # CONFIG_CONTEXT_SWITCH_TRACER is not set # CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set # CONFIG_STACK_TRACER is not set +# CONFIG_FTRACE_STARTUP_TEST is not set # CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set +CONFIG_ARM_UNWIND=y CONFIG_DEBUG_USER=y CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_STACK_USAGE is not set @@ -1464,19 +1561,22 @@ CONFIG_DEBUG_LL=y # CONFIG_SECURITY is not set # CONFIG_SECURITYFS is not set # CONFIG_SECURITY_FILE_CAPABILITIES is not set -CONFIG_ASYNC_CORE=y CONFIG_CRYPTO=y # # Crypto core or helper # # CONFIG_CRYPTO_FIPS is not set -CONFIG_CRYPTO_ALGAPI=m -CONFIG_CRYPTO_AEAD=m -CONFIG_CRYPTO_BLKCIPHER=m -CONFIG_CRYPTO_HASH=m -CONFIG_CRYPTO_RNG=m -CONFIG_CRYPTO_MANAGER=m +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_CRYPTD is not set @@ -1496,7 +1596,7 @@ CONFIG_CRYPTO_MANAGER=m CONFIG_CRYPTO_CBC=m # CONFIG_CRYPTO_CTR is not set # CONFIG_CRYPTO_CTS is not set -CONFIG_CRYPTO_ECB=m +CONFIG_CRYPTO_ECB=y # CONFIG_CRYPTO_LRW is not set CONFIG_CRYPTO_PCBC=m # CONFIG_CRYPTO_XTS is not set @@ -1510,7 +1610,7 @@ CONFIG_CRYPTO_PCBC=m # # Digest # -# CONFIG_CRYPTO_CRC32C is not set +CONFIG_CRYPTO_CRC32C=y # CONFIG_CRYPTO_MD4 is not set # CONFIG_CRYPTO_MD5 is not set # CONFIG_CRYPTO_MICHAEL_MIC is not set @@ -1527,9 +1627,9 @@ CONFIG_CRYPTO_PCBC=m # # Ciphers # -# CONFIG_CRYPTO_AES is not set +CONFIG_CRYPTO_AES=y # CONFIG_CRYPTO_ANUBIS is not set -# CONFIG_CRYPTO_ARC4 is not set +CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_CAST5 is not set @@ -1560,6 +1660,7 @@ CONFIG_CRYPTO_HW=y # Library routines # CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y CONFIG_CRC_CCITT=y CONFIG_CRC16=y # CONFIG_CRC_T10DIF is not set -- GitLab From 569106c70e49ad67c69fa7d43a2a5218e63a4619 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 12 Mar 2009 09:48:37 +0100 Subject: [PATCH 3464/4982] [ARM] mv78xx0: Add Marvell RD-78x00-mASA Reference Design support Signed-off-by: Lennert Buytenhek Acked-by: Stanislav Samsonov Signed-off-by: Nicolas Pitre --- arch/arm/configs/mv78xx0_defconfig | 1 + arch/arm/mach-mv78xx0/Kconfig | 6 ++ arch/arm/mach-mv78xx0/Makefile | 1 + arch/arm/mach-mv78xx0/rd78x00-masa-setup.c | 88 ++++++++++++++++++++++ 4 files changed, 96 insertions(+) create mode 100644 arch/arm/mach-mv78xx0/rd78x00-masa-setup.c diff --git a/arch/arm/configs/mv78xx0_defconfig b/arch/arm/configs/mv78xx0_defconfig index 83c817f31bc..b0698722e0c 100644 --- a/arch/arm/configs/mv78xx0_defconfig +++ b/arch/arm/configs/mv78xx0_defconfig @@ -165,6 +165,7 @@ CONFIG_ARCH_MV78XX0=y # Marvell MV78xx0 Implementations # CONFIG_MACH_DB78X00_BP=y +CONFIG_MACH_RD78X00_MASA=y # # Boot options diff --git a/arch/arm/mach-mv78xx0/Kconfig b/arch/arm/mach-mv78xx0/Kconfig index d83cb86837d..6fbe68fe441 100644 --- a/arch/arm/mach-mv78xx0/Kconfig +++ b/arch/arm/mach-mv78xx0/Kconfig @@ -8,6 +8,12 @@ config MACH_DB78X00_BP Say 'Y' here if you want your kernel to support the Marvell DB-78x00-BP Development Board. +config MACH_RD78X00_MASA + bool "Marvell RD-78x00-mASA Reference Design" + help + Say 'Y' here if you want your kernel to support the + Marvell RD-78x00-mASA Reference Design. + endmenu endif diff --git a/arch/arm/mach-mv78xx0/Makefile b/arch/arm/mach-mv78xx0/Makefile index ec16c05c3b1..da628b7f3bb 100644 --- a/arch/arm/mach-mv78xx0/Makefile +++ b/arch/arm/mach-mv78xx0/Makefile @@ -1,2 +1,3 @@ obj-y += common.o addr-map.o irq.o pcie.o obj-$(CONFIG_MACH_DB78X00_BP) += db78x00-bp-setup.o +obj-$(CONFIG_MACH_RD78X00_MASA) += rd78x00-masa-setup.o diff --git a/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c b/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c new file mode 100644 index 00000000000..e136b7a0335 --- /dev/null +++ b/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c @@ -0,0 +1,88 @@ +/* + * arch/arm/mach-mv78x00/rd78x00-masa-setup.c + * + * Marvell RD-78x00-mASA Development Board Setup + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" + +static struct mv643xx_eth_platform_data rd78x00_masa_ge00_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(8), +}; + +static struct mv643xx_eth_platform_data rd78x00_masa_ge01_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(9), +}; + +static struct mv643xx_eth_platform_data rd78x00_masa_ge10_data = { +}; + +static struct mv643xx_eth_platform_data rd78x00_masa_ge11_data = { +}; + +static struct mv_sata_platform_data rd78x00_masa_sata_data = { + .n_ports = 2, +}; + +static void __init rd78x00_masa_init(void) +{ + /* + * Basic MV78x00 setup. Needs to be called early. + */ + mv78xx0_init(); + + /* + * Partition on-chip peripherals between the two CPU cores. + */ + if (mv78xx0_core_index() == 0) { + mv78xx0_ehci0_init(); + mv78xx0_ehci1_init(); + mv78xx0_ge00_init(&rd78x00_masa_ge00_data); + mv78xx0_ge10_init(&rd78x00_masa_ge10_data); + mv78xx0_sata_init(&rd78x00_masa_sata_data); + mv78xx0_uart0_init(); + mv78xx0_uart2_init(); + } else { + mv78xx0_ehci2_init(); + mv78xx0_ge01_init(&rd78x00_masa_ge01_data); + mv78xx0_ge11_init(&rd78x00_masa_ge11_data); + mv78xx0_uart1_init(); + mv78xx0_uart3_init(); + } +} + +static int __init rd78x00_pci_init(void) +{ + /* + * Assign all PCIe devices to CPU core #0. + */ + if (machine_is_rd78x00_masa() && mv78xx0_core_index() == 0) + mv78xx0_pcie_init(1, 1); + + return 0; +} +subsys_initcall(rd78x00_pci_init); + +MACHINE_START(RD78X00_MASA, "Marvell RD-78x00-MASA Development Board") + /* Maintainer: Lennert Buytenhek */ + .phys_io = MV78XX0_REGS_PHYS_BASE, + .io_pg_offst = ((MV78XX0_REGS_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .init_machine = rd78x00_masa_init, + .map_io = mv78xx0_map_io, + .init_irq = mv78xx0_init_irq, + .timer = &mv78xx0_timer, +MACHINE_END -- GitLab From 8bdd663aba341c15cd2fa9dbd7061b8b387964dc Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 15 Mar 2009 19:59:13 -0700 Subject: [PATCH 3465/4982] net: reorder fields of struct socket On x86_64, its rather unfortunate that "wait_queue_head_t wait" field of "struct socket" spans two cache lines (assuming a 64 bytes cache line in current cpus) offsetof(struct socket, wait)=0x30 sizeof(wait_queue_head_t)=0x18 This might explain why Kenny Chang noticed that his multicast workload was performing bad with 64 bit kernels, since more cache lines ping pongs were involved. This litle patch moves "wait" field next "fasync_list" so that both fields share a single cache line, to speedup sock_def_readable() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/net.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/linux/net.h b/include/linux/net.h index 4515efae4c3..4fc2ffd527f 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -129,11 +129,15 @@ struct socket { socket_state state; short type; unsigned long flags; - const struct proto_ops *ops; + /* + * Please keep fasync_list & wait fields in the same cache line + */ struct fasync_struct *fasync_list; + wait_queue_head_t wait; + struct file *file; struct sock *sk; - wait_queue_head_t wait; + const struct proto_ops *ops; }; struct vm_area_struct; -- GitLab From 7cd0a63872ac6ef97265f07adc367ca4f984468e Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Sun, 15 Mar 2009 20:00:19 -0700 Subject: [PATCH 3466/4982] pkt_sched: Change misleading code in class delete. While looking for a possible reason of bugzilla report on HTB oops: http://bugzilla.kernel.org/show_bug.cgi?id=12858 I found the code in htb_delete calling htb_destroy_class on zero refcount is very misleading: it can suggest this is a common path, and destroy is called under sch_tree_lock. Actually, this can never happen like this because before deletion cops->get() is done, and after delete a class is still used by tclass_notify. The class destroy is always called from cops->put(), so without sch_tree_lock. This doesn't mean much now (since 2.6.27) because all vulnerable calls were moved from htb_destroy_class to htb_delete, but there was a bug in older kernels. The same change is done for other classful scheds, which, it seems, didn't have similar locking problems here. Reported-by: m0sia Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- net/sched/sch_cbq.c | 7 +++++-- net/sched/sch_drr.c | 7 +++++-- net/sched/sch_hfsc.c | 7 +++++-- net/sched/sch_htb.c | 7 +++++-- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 9e43ed94916..d728d811173 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -1960,8 +1960,11 @@ static int cbq_delete(struct Qdisc *sch, unsigned long arg) cbq_rmprio(q, cl); sch_tree_unlock(sch); - if (--cl->refcnt == 0) - cbq_destroy_class(sch, cl); + BUG_ON(--cl->refcnt == 0); + /* + * This shouldn't happen: we "hold" one cops->get() when called + * from tc_ctl_tclass; the destroy method is done from cops->put(). + */ return 0; } diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c index e36e94ab4e1..7597fe14686 100644 --- a/net/sched/sch_drr.c +++ b/net/sched/sch_drr.c @@ -155,8 +155,11 @@ static int drr_delete_class(struct Qdisc *sch, unsigned long arg) drr_purge_queue(cl); qdisc_class_hash_remove(&q->clhash, &cl->common); - if (--cl->refcnt == 0) - drr_destroy_class(sch, cl); + BUG_ON(--cl->refcnt == 0); + /* + * This shouldn't happen: we "hold" one cops->get() when called + * from tc_ctl_tclass; the destroy method is done from cops->put(). + */ sch_tree_unlock(sch); return 0; diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 74226b26552..5022f9c1f34 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -1139,8 +1139,11 @@ hfsc_delete_class(struct Qdisc *sch, unsigned long arg) hfsc_purge_queue(sch, cl); qdisc_class_hash_remove(&q->clhash, &cl->cl_common); - if (--cl->refcnt == 0) - hfsc_destroy_class(sch, cl); + BUG_ON(--cl->refcnt == 0); + /* + * This shouldn't happen: we "hold" one cops->get() when called + * from tc_ctl_tclass; the destroy method is done from cops->put(). + */ sch_tree_unlock(sch); return 0; diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 355974f610c..88cd0262662 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -1275,8 +1275,11 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg) if (last_child) htb_parent_to_leaf(q, cl, new_q); - if (--cl->refcnt == 0) - htb_destroy_class(sch, cl); + BUG_ON(--cl->refcnt == 0); + /* + * This shouldn't happen: we "hold" one cops->get() when called + * from tc_ctl_tclass; the destroy method is done from cops->put(). + */ sch_tree_unlock(sch); return 0; -- GitLab From 97d477a914b146e7e6722ded21afa79886ae8ccd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?fran=C3=A7ois=20romieu?= Date: Sun, 15 Mar 2009 01:09:54 +0000 Subject: [PATCH 3467/4982] r8169: use hardware auto-padding. It shortens the code and fixes the current pci_unmap leak with padded skb reported by Dave Jones. Signed-off-by: Francois Romieu Signed-off-by: David S. Miller --- drivers/net/r8169.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index b3473401c83..352da2a43c9 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -3363,13 +3363,6 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) opts1 |= FirstFrag; } else { len = skb->len; - - if (unlikely(len < ETH_ZLEN)) { - if (skb_padto(skb, ETH_ZLEN)) - goto err_update_stats; - len = ETH_ZLEN; - } - opts1 |= FirstFrag | LastFrag; tp->tx_skb[entry].skb = skb; } @@ -3407,7 +3400,6 @@ out: err_stop: netif_stop_queue(dev); ret = NETDEV_TX_BUSY; -err_update_stats: dev->stats.tx_dropped++; goto out; } -- GitLab From ea8dbdd17099a9a5864ebd4c87e01e657b19c7ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?fran=C3=A7ois=20romieu?= Date: Sun, 15 Mar 2009 01:10:50 +0000 Subject: [PATCH 3468/4982] r8169: revert "r8169: read MAC address from EEPROM on init (2nd attempt)" It fails on the following systems: - RTL8169sc/8110sc (XID 18000000) reported by Tim Durack (x86) - RTL8169sb/8110sb (XID 10000000) reported by Mikael Pettersson (ARM) The patch appeared to work on x86 for the following systems: RTL8169sb/8110sb 10000000 PCI (EXT) RTL8110s 04000000 PCI (EXT) RTL8102e 24a00000 PCI-E (LOM) RTL8168c/8111c 3c2000c0 PCI-E (LOM) RTL8168b/8111b 38000000 PCI-E (LOM) RTL8168b/8111b 38000000 PCI-E (EXT) The patch exposes two problems: 1) while not completely wrong, mac addresses are not read correctly from the EEPROM 2) the MAC address registers are not correctly set Signed-off-by: Francois Romieu Tested-by: Mikael Pettersson Signed-off-by: David S. Miller --- drivers/net/r8169.c | 114 +------------------------------------------- 1 file changed, 2 insertions(+), 112 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 352da2a43c9..43fedb9eced 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -81,9 +81,9 @@ static const int multicast_filter_limit = 32; #define RTL8169_TX_TIMEOUT (6*HZ) #define RTL8169_PHY_TIMEOUT (10*HZ) -#define RTL_EEPROM_SIG 0x8129 +#define RTL_EEPROM_SIG cpu_to_le32(0x8129) +#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) #define RTL_EEPROM_SIG_ADDR 0x0000 -#define RTL_EEPROM_MAC_ADDR 0x0007 /* write/read MMIO register */ #define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) @@ -293,11 +293,6 @@ enum rtl_register_content { /* Cfg9346Bits */ Cfg9346_Lock = 0x00, Cfg9346_Unlock = 0xc0, - Cfg9346_Program = 0x80, /* Programming mode */ - Cfg9346_EECS = 0x08, /* Chip select */ - Cfg9346_EESK = 0x04, /* Serial data clock */ - Cfg9346_EEDI = 0x02, /* Data input */ - Cfg9346_EEDO = 0x01, /* Data output */ /* rx_mode_bits */ AcceptErr = 0x20, @@ -310,7 +305,6 @@ enum rtl_register_content { /* RxConfigBits */ RxCfgFIFOShift = 13, RxCfgDMAShift = 8, - RxCfg9356SEL = 6, /* EEPROM type: 0 = 9346, 1 = 9356 */ /* TxConfigBits */ TxInterFrameGapShift = 24, @@ -1969,108 +1963,6 @@ static const struct net_device_ops rtl8169_netdev_ops = { }; -/* Delay between EEPROM clock transitions. Force out buffered PCI writes. */ -#define RTL_EEPROM_DELAY() RTL_R8(Cfg9346) -#define RTL_EEPROM_READ_CMD 6 - -/* read 16bit word stored in EEPROM. EEPROM is addressed by words. */ -static u16 rtl_eeprom_read(void __iomem *ioaddr, int addr) -{ - u16 result = 0; - int cmd, cmd_len, i; - - /* check for EEPROM address size (in bits) */ - if (RTL_R32(RxConfig) & (1 << RxCfg9356SEL)) { - /* EEPROM is 93C56 */ - cmd_len = 3 + 8; /* 3 bits for command id and 8 for address */ - cmd = (RTL_EEPROM_READ_CMD << 8) | (addr & 0xff); - } else { - /* EEPROM is 93C46 */ - cmd_len = 3 + 6; /* 3 bits for command id and 6 for address */ - cmd = (RTL_EEPROM_READ_CMD << 6) | (addr & 0x3f); - } - - /* enter programming mode */ - RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS); - RTL_EEPROM_DELAY(); - - /* write command and requested address */ - while (cmd_len--) { - u8 x = Cfg9346_Program | Cfg9346_EECS; - - x |= (cmd & (1 << cmd_len)) ? Cfg9346_EEDI : 0; - - /* write a bit */ - RTL_W8(Cfg9346, x); - RTL_EEPROM_DELAY(); - - /* raise clock */ - RTL_W8(Cfg9346, x | Cfg9346_EESK); - RTL_EEPROM_DELAY(); - } - - /* lower clock */ - RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS); - RTL_EEPROM_DELAY(); - - /* read back 16bit value */ - for (i = 16; i > 0; i--) { - /* raise clock */ - RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS | Cfg9346_EESK); - RTL_EEPROM_DELAY(); - - result <<= 1; - result |= (RTL_R8(Cfg9346) & Cfg9346_EEDO) ? 1 : 0; - - /* lower clock */ - RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS); - RTL_EEPROM_DELAY(); - } - - RTL_W8(Cfg9346, Cfg9346_Program); - /* leave programming mode */ - RTL_W8(Cfg9346, Cfg9346_Lock); - - return result; -} - -static void rtl_init_mac_address(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - struct pci_dev *pdev = tp->pci_dev; - u16 x; - u8 mac[8]; - - /* read EEPROM signature */ - x = rtl_eeprom_read(ioaddr, RTL_EEPROM_SIG_ADDR); - - if (x != RTL_EEPROM_SIG) { - dev_info(&pdev->dev, "Missing EEPROM signature: %04x\n", x); - return; - } - - /* read MAC address */ - x = rtl_eeprom_read(ioaddr, RTL_EEPROM_MAC_ADDR); - mac[0] = x & 0xff; - mac[1] = x >> 8; - x = rtl_eeprom_read(ioaddr, RTL_EEPROM_MAC_ADDR + 1); - mac[2] = x & 0xff; - mac[3] = x >> 8; - x = rtl_eeprom_read(ioaddr, RTL_EEPROM_MAC_ADDR + 2); - mac[4] = x & 0xff; - mac[5] = x >> 8; - - if (netif_msg_probe(tp)) { - DECLARE_MAC_BUF(buf); - - dev_info(&pdev->dev, "MAC address found in EEPROM: %s\n", - print_mac(buf, mac)); - } - - if (is_valid_ether_addr(mac)) - rtl_rar_set(tp, mac); -} - static int __devinit rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -2249,8 +2141,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->mmio_addr = ioaddr; - rtl_init_mac_address(tp, ioaddr); - /* Get MAC address */ for (i = 0; i < MAC_ADDR_LEN; i++) dev->dev_addr[i] = RTL_R8(MAC0 + i); -- GitLab From 5861f8e58dd84fc34b691c2e8d4824dea68c360e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Sat, 14 Mar 2009 14:23:01 +0000 Subject: [PATCH 3469/4982] tcp: remove pointless .dsack/.num_sacks code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the pure assignment case, the earlier zeroing is still in effect. David S. Miller raised concerns if the ifs are there to avoid dirtying cachelines. I came to these conclusions: > We'll be dirty it anyway (now that I check), the first "real" statement > in tcp_rcv_established is: > > tp->rx_opt.saw_tstamp = 0; > > ...that'll land on the same dword. :-/ > > I suppose the blocks are there just because they had more complexity > inside when they had to calculate the eff_sacks too (maybe it would > have been better to just remove them in that drop-patch so you would > have had less head-ache :-)). Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 7 ++----- net/ipv4/tcp_output.c | 3 +-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 5ecd7aa2597..cd39d1d02dc 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -4248,8 +4248,7 @@ static void tcp_sack_remove(struct tcp_sock *tp) this_sack++; sp++; } - if (num_sacks != tp->rx_opt.num_sacks) - tp->rx_opt.num_sacks = num_sacks; + tp->rx_opt.num_sacks = num_sacks; } /* This one checks to see if we can put data from the @@ -4325,8 +4324,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) TCP_ECN_accept_cwr(tp, skb); - if (tp->rx_opt.dsack) - tp->rx_opt.dsack = 0; + tp->rx_opt.dsack = 0; /* Queue data for delivery to the user. * Packets in sequence go to the receive queue. @@ -4445,7 +4443,6 @@ drop: /* Initial out of order segment, build 1 SACK. */ if (tcp_is_sack(tp)) { tp->rx_opt.num_sacks = 1; - tp->rx_opt.dsack = 0; tp->selective_acks[0].start_seq = TCP_SKB_CB(skb)->seq; tp->selective_acks[0].end_seq = TCP_SKB_CB(skb)->end_seq; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index eb285befdf3..32565803913 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -441,8 +441,7 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, *ptr++ = htonl(sp[this_sack].end_seq); } - if (tp->rx_opt.dsack) - tp->rx_opt.dsack = 0; + tp->rx_opt.dsack = 0; } } -- GitLab From c43d558a5139a3b22dcac3f19f64ecb39130b02e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Sat, 14 Mar 2009 14:23:02 +0000 Subject: [PATCH 3470/4982] tcp: kill dead end_seq variable in clean_rtx_queue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I've already forgotten what for this was necessary, anyway it's no longer used (if it ever was). Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index cd39d1d02dc..f527a16a7b3 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3201,7 +3201,6 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, while ((skb = tcp_write_queue_head(sk)) && skb != tcp_send_head(sk)) { struct tcp_skb_cb *scb = TCP_SKB_CB(skb); - u32 end_seq; u32 acked_pcount; u8 sacked = scb->sacked; @@ -3216,10 +3215,8 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, break; fully_acked = 0; - end_seq = tp->snd_una; } else { acked_pcount = tcp_skb_pcount(skb); - end_seq = scb->end_seq; } /* MTU probing checks */ -- GitLab From c887e6d2d9aee56ee7c9f2af4cec3a5efdcc4c72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Sat, 14 Mar 2009 14:23:03 +0000 Subject: [PATCH 3471/4982] tcp: consolidate paws check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wow, it was quite tricky to merge that stream of negations but I think I finally got it right: check & replace_ts_recent: (s32)(rcv_tsval - ts_recent) >= 0 => 0 (s32)(ts_recent - rcv_tsval) <= 0 => 0 discard: (s32)(ts_recent - rcv_tsval) > TCP_PAWS_WINDOW => 1 (s32)(ts_recent - rcv_tsval) <= TCP_PAWS_WINDOW => 0 I toggled the return values of tcp_paws_check around since the old encoding added yet-another negation making tracking of truth-values really complicated. Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- include/net/tcp.h | 18 ++++++++++++++---- net/ipv4/tcp_input.c | 11 +++++------ net/ipv4/tcp_minisocks.c | 4 ++-- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index d74ac301e6b..255ca35bea0 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -997,11 +997,21 @@ static inline int tcp_fin_time(const struct sock *sk) return fin_timeout; } -static inline int tcp_paws_check(const struct tcp_options_received *rx_opt, int rst) +static inline int tcp_paws_check(const struct tcp_options_received *rx_opt, + int paws_win) { - if ((s32)(rx_opt->rcv_tsval - rx_opt->ts_recent) >= 0) - return 0; - if (get_seconds() >= rx_opt->ts_recent_stamp + TCP_PAWS_24DAYS) + if ((s32)(rx_opt->ts_recent - rx_opt->rcv_tsval) <= paws_win) + return 1; + if (unlikely(get_seconds() >= rx_opt->ts_recent_stamp + TCP_PAWS_24DAYS)) + return 1; + + return 0; +} + +static inline int tcp_paws_reject(const struct tcp_options_received *rx_opt, + int rst) +{ + if (tcp_paws_check(rx_opt, 0)) return 0; /* RST segments are not recommended to carry timestamp, diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index f527a16a7b3..b7d02c5dd6d 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3883,8 +3883,7 @@ static inline void tcp_replace_ts_recent(struct tcp_sock *tp, u32 seq) * Not only, also it occurs for expired timestamps. */ - if ((s32)(tp->rx_opt.rcv_tsval - tp->rx_opt.ts_recent) >= 0 || - get_seconds() >= tp->rx_opt.ts_recent_stamp + TCP_PAWS_24DAYS) + if (tcp_paws_check(&tp->rx_opt, 0)) tcp_store_ts_recent(tp); } } @@ -3936,9 +3935,9 @@ static inline int tcp_paws_discard(const struct sock *sk, const struct sk_buff *skb) { const struct tcp_sock *tp = tcp_sk(sk); - return ((s32)(tp->rx_opt.ts_recent - tp->rx_opt.rcv_tsval) > TCP_PAWS_WINDOW && - get_seconds() < tp->rx_opt.ts_recent_stamp + TCP_PAWS_24DAYS && - !tcp_disordered_ack(sk, skb)); + + return !tcp_paws_check(&tp->rx_opt, TCP_PAWS_WINDOW) && + !tcp_disordered_ack(sk, skb); } /* Check segment sequence number for validity. @@ -5513,7 +5512,7 @@ discard: /* PAWS check. */ if (tp->rx_opt.ts_recent_stamp && tp->rx_opt.saw_tstamp && - tcp_paws_check(&tp->rx_opt, 0)) + tcp_paws_reject(&tp->rx_opt, 0)) goto discard_and_undo; if (th->syn) { diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 4b0df3e6b60..43bbba7926e 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -107,7 +107,7 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb, if (tmp_opt.saw_tstamp) { tmp_opt.ts_recent = tcptw->tw_ts_recent; tmp_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp; - paws_reject = tcp_paws_check(&tmp_opt, th->rst); + paws_reject = tcp_paws_reject(&tmp_opt, th->rst); } } @@ -511,7 +511,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, * from another data. */ tmp_opt.ts_recent_stamp = get_seconds() - ((TCP_TIMEOUT_INIT/HZ)<retrans); - paws_reject = tcp_paws_check(&tmp_opt, th->rst); + paws_reject = tcp_paws_reject(&tmp_opt, th->rst); } } -- GitLab From 72211e90501f954f586481c25521c3724cda3cc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Sat, 14 Mar 2009 14:23:04 +0000 Subject: [PATCH 3472/4982] tcp: don't check mtu probe completion in the loop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It seems that no variables clash such that we couldn't do the check just once later on. Therefore move it. Also kill dead obvious comment, dead argument and add unlikely since this mtu probe does not happen too often. Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index b7d02c5dd6d..311c30f73ee 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2836,7 +2836,7 @@ static void tcp_mtup_probe_failed(struct sock *sk) icsk->icsk_mtup.probe_size = 0; } -static void tcp_mtup_probe_success(struct sock *sk, struct sk_buff *skb) +static void tcp_mtup_probe_success(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); struct inet_connection_sock *icsk = inet_csk(sk); @@ -3219,12 +3219,6 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, acked_pcount = tcp_skb_pcount(skb); } - /* MTU probing checks */ - if (fully_acked && icsk->icsk_mtup.probe_size && - !after(tp->mtu_probe.probe_seq_end, scb->end_seq)) { - tcp_mtup_probe_success(sk, skb); - } - if (sacked & TCPCB_RETRANS) { if (sacked & TCPCB_SACKED_RETRANS) tp->retrans_out -= acked_pcount; @@ -3287,6 +3281,11 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, const struct tcp_congestion_ops *ca_ops = inet_csk(sk)->icsk_ca_ops; + if (unlikely(icsk->icsk_mtup.probe_size && + !after(tp->mtu_probe.probe_seq_end, tp->snd_una))) { + tcp_mtup_probe_success(sk); + } + tcp_ack_update_rtt(sk, flag, seq_rtt); tcp_rearm_rto(sk); -- GitLab From 0c54b85f2828128274f319a1eb3ce7f604fe2a53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Sat, 14 Mar 2009 14:23:05 +0000 Subject: [PATCH 3473/4982] tcp: simplify tcp_current_mss MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's very little need for most of the callsites to get tp->xmit_goal_size updated. That will cost us divide as is, so slice the function in two. Also, the only users of the tp->xmit_goal_size are directly behind tcp_current_mss(), so there's no need to store that variable into tcp_sock at all! The drop of xmit_goal_size currently leaves 16-bit hole and some reorganization would again be necessary to change that (but I'm aiming to fill that hole with u16 xmit_goal_size_segs to cache the results of the remaining divide to get that tso on regression). Bring xmit_goal_size parts into tcp.c Signed-off-by: Ilpo Järvinen Cc: Evgeniy Polyakov Cc: Ingo Molnar Signed-off-by: David S. Miller --- include/linux/tcp.h | 1 - include/net/tcp.h | 13 +++++++++++-- net/ipv4/tcp.c | 43 +++++++++++++++++++++++++++++++++++-------- net/ipv4/tcp_input.c | 2 +- net/ipv4/tcp_output.c | 41 +++++++---------------------------------- 5 files changed, 54 insertions(+), 46 deletions(-) diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 4b86ad71e05..ad2021ccc55 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -248,7 +248,6 @@ struct tcp_sock { /* inet_connection_sock has to be the first member of tcp_sock */ struct inet_connection_sock inet_conn; u16 tcp_header_len; /* Bytes of tcp header to send */ - u16 xmit_size_goal; /* Goal for segmenting output packets */ /* * Header prediction flags diff --git a/include/net/tcp.h b/include/net/tcp.h index 255ca35bea0..e54c76d7549 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -481,7 +481,16 @@ static inline void tcp_clear_xmit_timers(struct sock *sk) } extern unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu); -extern unsigned int tcp_current_mss(struct sock *sk, int large); +extern unsigned int tcp_current_mss(struct sock *sk); + +/* Bound MSS / TSO packet size with the half of the window */ +static inline int tcp_bound_to_half_wnd(struct tcp_sock *tp, int pktsize) +{ + if (tp->max_window && pktsize > (tp->max_window >> 1)) + return max(tp->max_window >> 1, 68U - tp->tcp_header_len); + else + return pktsize; +} /* tcp.c */ extern void tcp_get_info(struct sock *, struct tcp_info *); @@ -822,7 +831,7 @@ static inline void tcp_push_pending_frames(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); - __tcp_push_pending_frames(sk, tcp_current_mss(sk, 1), tp->nonagle); + __tcp_push_pending_frames(sk, tcp_current_mss(sk), tp->nonagle); } static inline void tcp_init_wl(struct tcp_sock *tp, u32 seq) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index d3f9beee74c..886596ff0aa 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -661,6 +661,37 @@ struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp) return NULL; } +static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now, + int large_allowed) +{ + struct tcp_sock *tp = tcp_sk(sk); + u32 xmit_size_goal; + + xmit_size_goal = mss_now; + + if (large_allowed && sk_can_gso(sk)) { + xmit_size_goal = ((sk->sk_gso_max_size - 1) - + inet_csk(sk)->icsk_af_ops->net_header_len - + inet_csk(sk)->icsk_ext_hdr_len - + tp->tcp_header_len); + + xmit_size_goal = tcp_bound_to_half_wnd(tp, xmit_size_goal); + xmit_size_goal -= (xmit_size_goal % mss_now); + } + + return xmit_size_goal; +} + +static int tcp_send_mss(struct sock *sk, int *size_goal, int flags) +{ + int mss_now; + + mss_now = tcp_current_mss(sk); + *size_goal = tcp_xmit_size_goal(sk, mss_now, !(flags & MSG_OOB)); + + return mss_now; +} + static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset, size_t psize, int flags) { @@ -677,8 +708,7 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffse clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); - mss_now = tcp_current_mss(sk, !(flags&MSG_OOB)); - size_goal = tp->xmit_size_goal; + mss_now = tcp_send_mss(sk, &size_goal, flags); copied = 0; err = -EPIPE; @@ -761,8 +791,7 @@ wait_for_memory: if ((err = sk_stream_wait_memory(sk, &timeo)) != 0) goto do_error; - mss_now = tcp_current_mss(sk, !(flags&MSG_OOB)); - size_goal = tp->xmit_size_goal; + mss_now = tcp_send_mss(sk, &size_goal, flags); } out: @@ -844,8 +873,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, /* This should be in poll */ clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); - mss_now = tcp_current_mss(sk, !(flags&MSG_OOB)); - size_goal = tp->xmit_size_goal; + mss_now = tcp_send_mss(sk, &size_goal, flags); /* Ok commence sending. */ iovlen = msg->msg_iovlen; @@ -1007,8 +1035,7 @@ wait_for_memory: if ((err = sk_stream_wait_memory(sk, &timeo)) != 0) goto do_error; - mss_now = tcp_current_mss(sk, !(flags&MSG_OOB)); - size_goal = tp->xmit_size_goal; + mss_now = tcp_send_mss(sk, &size_goal, flags); } } diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 311c30f73ee..fae78e3eccc 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2864,7 +2864,7 @@ void tcp_simple_retransmit(struct sock *sk) const struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); struct sk_buff *skb; - unsigned int mss = tcp_current_mss(sk, 0); + unsigned int mss = tcp_current_mss(sk); u32 prior_lost = tp->lost_out; tcp_for_write_queue(skb, sk) { diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 32565803913..c1f259d2d33 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -921,7 +921,7 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len) * factor and mss. */ if (tcp_skb_pcount(skb) > 1) - tcp_set_skb_tso_segs(sk, skb, tcp_current_mss(sk, 1)); + tcp_set_skb_tso_segs(sk, skb, tcp_current_mss(sk)); return 0; } @@ -982,15 +982,6 @@ void tcp_mtup_init(struct sock *sk) icsk->icsk_mtup.probe_size = 0; } -/* Bound MSS / TSO packet size with the half of the window */ -static int tcp_bound_to_half_wnd(struct tcp_sock *tp, int pktsize) -{ - if (tp->max_window && pktsize > (tp->max_window >> 1)) - return max(tp->max_window >> 1, 68U - tp->tcp_header_len); - else - return pktsize; -} - /* This function synchronize snd mss to current pmtu/exthdr set. tp->rx_opt.user_mss is mss set by user by TCP_MAXSEG. It does NOT counts @@ -1037,22 +1028,17 @@ unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu) /* Compute the current effective MSS, taking SACKs and IP options, * and even PMTU discovery events into account. */ -unsigned int tcp_current_mss(struct sock *sk, int large_allowed) +unsigned int tcp_current_mss(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); struct dst_entry *dst = __sk_dst_get(sk); u32 mss_now; - u16 xmit_size_goal; - int doing_tso = 0; unsigned header_len; struct tcp_out_options opts; struct tcp_md5sig_key *md5; mss_now = tp->mss_cache; - if (large_allowed && sk_can_gso(sk)) - doing_tso = 1; - if (dst) { u32 mtu = dst_mtu(dst); if (mtu != inet_csk(sk)->icsk_pmtu_cookie) @@ -1070,19 +1056,6 @@ unsigned int tcp_current_mss(struct sock *sk, int large_allowed) mss_now -= delta; } - xmit_size_goal = mss_now; - - if (doing_tso) { - xmit_size_goal = ((sk->sk_gso_max_size - 1) - - inet_csk(sk)->icsk_af_ops->net_header_len - - inet_csk(sk)->icsk_ext_hdr_len - - tp->tcp_header_len); - - xmit_size_goal = tcp_bound_to_half_wnd(tp, xmit_size_goal); - xmit_size_goal -= (xmit_size_goal % mss_now); - } - tp->xmit_size_goal = xmit_size_goal; - return mss_now; } @@ -1264,7 +1237,7 @@ int tcp_may_send_now(struct sock *sk) struct sk_buff *skb = tcp_send_head(sk); return (skb && - tcp_snd_test(sk, skb, tcp_current_mss(sk, 1), + tcp_snd_test(sk, skb, tcp_current_mss(sk), (tcp_skb_is_last(sk, skb) ? tp->nonagle : TCP_NAGLE_PUSH))); } @@ -1421,7 +1394,7 @@ static int tcp_mtu_probe(struct sock *sk) return -1; /* Very simple search strategy: just double the MSS. */ - mss_now = tcp_current_mss(sk, 0); + mss_now = tcp_current_mss(sk); probe_size = 2 * tp->mss_cache; size_needed = probe_size + (tp->reordering + 1) * tp->mss_cache; if (probe_size > tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_high)) { @@ -1903,7 +1876,7 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk)) return -EHOSTUNREACH; /* Routing failure or similar. */ - cur_mss = tcp_current_mss(sk, 0); + cur_mss = tcp_current_mss(sk); /* If receiver has shrunk his window, and skb is out of * new window, do not retransmit it. The exception is the @@ -2111,7 +2084,7 @@ void tcp_send_fin(struct sock *sk) * unsent frames. But be careful about outgoing SACKS * and IP options. */ - mss_now = tcp_current_mss(sk, 1); + mss_now = tcp_current_mss(sk); if (tcp_send_head(sk) != NULL) { TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_FIN; @@ -2523,7 +2496,7 @@ int tcp_write_wakeup(struct sock *sk) if ((skb = tcp_send_head(sk)) != NULL && before(TCP_SKB_CB(skb)->seq, tcp_wnd_end(tp))) { int err; - unsigned int mss = tcp_current_mss(sk, 0); + unsigned int mss = tcp_current_mss(sk); unsigned int seg_size = tcp_wnd_end(tp) - TCP_SKB_CB(skb)->seq; if (before(tp->pushed_seq, TCP_SKB_CB(skb)->end_seq)) -- GitLab From 2a3a041c4e2c1685e668b280c121a5a40a029a03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Sat, 14 Mar 2009 22:45:16 +0000 Subject: [PATCH 3474/4982] tcp: cache result of earlier divides when mss-aligning things MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The results is very unlikely change every so often so we hardly need to divide again after doing that once for a connection. Yet, if divide still becomes necessary we detect that and do the right thing and again settle for non-divide state. Takes the u16 space which was previously taken by the plain xmit_size_goal. This should take care part of the tso vs non-tso difference we found earlier. Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- include/linux/tcp.h | 1 + net/ipv4/tcp.c | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/include/linux/tcp.h b/include/linux/tcp.h index ad2021ccc55..9d5078bd23a 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -248,6 +248,7 @@ struct tcp_sock { /* inet_connection_sock has to be the first member of tcp_sock */ struct inet_connection_sock inet_conn; u16 tcp_header_len; /* Bytes of tcp header to send */ + u16 xmit_size_goal_segs; /* Goal for segmenting output packets */ /* * Header prediction flags diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 886596ff0aa..0db9f3b984f 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -665,7 +665,7 @@ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now, int large_allowed) { struct tcp_sock *tp = tcp_sk(sk); - u32 xmit_size_goal; + u32 xmit_size_goal, old_size_goal; xmit_size_goal = mss_now; @@ -676,7 +676,17 @@ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now, tp->tcp_header_len); xmit_size_goal = tcp_bound_to_half_wnd(tp, xmit_size_goal); - xmit_size_goal -= (xmit_size_goal % mss_now); + + /* We try hard to avoid divides here */ + old_size_goal = tp->xmit_size_goal_segs * mss_now; + + if (likely(old_size_goal <= xmit_size_goal && + old_size_goal + mss_now > xmit_size_goal)) { + xmit_size_goal = old_size_goal; + } else { + tp->xmit_size_goal_segs = xmit_size_goal / mss_now; + xmit_size_goal = tp->xmit_size_goal_segs * mss_now; + } } return xmit_size_goal; -- GitLab From afece1c6587010cc81d1a43045c855774e8234a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Sat, 14 Mar 2009 14:23:07 +0000 Subject: [PATCH 3475/4982] tcp: make sure xmit goal size never becomes zero MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's not too likely to happen, would basically require crafted packets (must hit the max guard in tcp_bound_to_half_wnd()). It seems that nothing that bad would happen as there's tcp_mems and congestion window that prevent runaway at some point from hurting all too much (I'm not that sure what all those zero sized segments we would generate do though in write queue). Preventing it regardless is certainly the best way to go. Signed-off-by: Ilpo Järvinen Cc: Evgeniy Polyakov Cc: Ingo Molnar Signed-off-by: David S. Miller --- net/ipv4/tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 0db9f3b984f..1c4d42ff72b 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -689,7 +689,7 @@ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now, } } - return xmit_size_goal; + return max(xmit_size_goal, mss_now); } static int tcp_send_mss(struct sock *sk, int *size_goal, int flags) -- GitLab From a140449584522c3eea1bb381f746d40939e6f62a Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Wed, 11 Feb 2009 18:11:22 +0000 Subject: [PATCH 3476/4982] suspend: switch the Asus Pundit P1-AH2 to old ACPI sleep ordering Switch the Asus Pundit P1-AH2 (M2N8L motherboard) to the old ACPI 1.0 sleep ordering by default. Without this it will not suspend/resume correctly. Signed-off-by: Andy Whitcroft Tested-by: Dustin Kirkland Signed-off-by: Len Brown --- drivers/acpi/sleep.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 519266654f0..3ca98686f28 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -378,6 +378,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"), }, }, + { + .callback = init_old_suspend_ordering, + .ident = "Asus Pundit P1-AH2 (M2N8L motherboard)", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "M2N8L"), + }, + }, {}, }; #endif /* CONFIG_SUSPEND */ -- GitLab From 7b46ecd5fcebf381a7bde966db352d8fb1b8e944 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 25 Feb 2009 18:00:18 -0500 Subject: [PATCH 3477/4982] Revert "ACPI: make some IO ports off-limits to AML" This reverts commit 5ec5d38a1c8af255ffc481c81eef13e9155524b3. because it caused spurious dmesg warmings. We'll implement the check for off-limit ports in a more clever way in the future. http://bugzilla.kernel.org/show_bug.cgi?id=12758 Signed-off-by: Len Brown --- drivers/acpi/osl.c | 50 ---------------------------------------------- 1 file changed, 50 deletions(-) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index b3193ec0a2e..1e35f342957 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1317,54 +1317,6 @@ acpi_os_validate_interface (char *interface) return AE_SUPPORT; } -#ifdef CONFIG_X86 - -struct aml_port_desc { - uint start; - uint end; - char* name; - char warned; -}; - -static struct aml_port_desc aml_invalid_port_list[] = { - {0x20, 0x21, "PIC0", 0}, - {0xA0, 0xA1, "PIC1", 0}, - {0x4D0, 0x4D1, "ELCR", 0} -}; - -/* - * valid_aml_io_address() - * - * if valid, return true - * else invalid, warn once, return false - */ -static bool valid_aml_io_address(uint address, uint length) -{ - int i; - int entries = sizeof(aml_invalid_port_list) / sizeof(struct aml_port_desc); - - for (i = 0; i < entries; ++i) { - if ((address >= aml_invalid_port_list[i].start && - address <= aml_invalid_port_list[i].end) || - (address + length >= aml_invalid_port_list[i].start && - address + length <= aml_invalid_port_list[i].end)) - { - if (!aml_invalid_port_list[i].warned) - { - printk(KERN_ERR "ACPI: Denied BIOS AML access" - " to invalid port 0x%x+0x%x (%s)\n", - address, length, - aml_invalid_port_list[i].name); - aml_invalid_port_list[i].warned = 1; - } - return false; /* invalid */ - } - } - return true; /* valid */ -} -#else -static inline bool valid_aml_io_address(uint address, uint length) { return true; } -#endif /****************************************************************************** * * FUNCTION: acpi_os_validate_address @@ -1394,8 +1346,6 @@ acpi_os_validate_address ( switch (space_id) { case ACPI_ADR_SPACE_SYSTEM_IO: - if (!valid_aml_io_address(address, length)) - return AE_AML_ILLEGAL_ADDRESS; case ACPI_ADR_SPACE_SYSTEM_MEMORY: /* Only interference checks against SystemIO and SytemMemory are needed */ -- GitLab From 45e7798886af101c4a908a896bbba5a84ee5cc32 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 15 Mar 2009 22:13:44 -0400 Subject: [PATCH 3478/4982] ACPI suspend: Blacklist Toshiba Satellite L300 that requires to set SCI_EN directly on resume This is a supplement of commit 65df78473ffbf3bff5e2034df1638acc4f3ddd50. http://bugzilla.kernel.org/show_bug.cgi?id=12798 Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/sleep.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 3ca98686f28..00456fccfa3 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -386,6 +386,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "M2N8L"), }, }, + { + .callback = init_set_sci_en_on_resume, + .ident = "Toshiba Satellite L300", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L300"), + }, + }, {}, }; #endif /* CONFIG_SUSPEND */ -- GitLab From 176f9c1804df09f3e9b998c0642e212592ac6283 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 4 Mar 2009 11:55:27 -0800 Subject: [PATCH 3479/4982] ACPI: remove doubled status checking There was a misplaced status test (two consequent tests without a statement in between) in acpi_bus_init for ages. Remove it, since the function which should be checked (acpi_os_initialize1) has BUG_ONs on failure paths. Signed-off-by: Jiri Slaby Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/bus.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 765fd1c56cd..bee64b73c91 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -758,8 +758,7 @@ static int __init acpi_bus_init(void) acpi_status status = AE_OK; extern acpi_status acpi_os_initialize1(void); - - status = acpi_os_initialize1(); + acpi_os_initialize1(); status = acpi_enable_subsystem(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE); @@ -769,12 +768,6 @@ static int __init acpi_bus_init(void) goto error1; } - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX - "Unable to initialize ACPI OS objects\n"); - goto error1; - } - /* * ACPI 2.0 requires the EC driver to be loaded and work before * the EC device is found in the namespace (i.e. before acpi_initialize_objects() -- GitLab From 27ce34198345886854643b9572f9a06d2e7500d2 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Wed, 4 Mar 2009 11:55:29 -0800 Subject: [PATCH 3480/4982] acpi: check for pxm_to_node_map overflow It is hardly (if ever) possible but in case of broken _PXM entry we could reach out of pxm_to_node_map array bounds in acpi_map_pxm_to_node() call. Signed-off-by: Cyrill Gorcunov Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/numa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index c5e292aab0e..3a0d8ef25c7 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -277,7 +277,7 @@ int acpi_get_node(acpi_handle *handle) int pxm, node = -1; pxm = acpi_get_pxm(handle); - if (pxm >= 0) + if (pxm >= 0 && pxm < MAX_PXM_DOMAINS) node = acpi_map_pxm_to_node(pxm); return node; -- GitLab From 6050c8dd70b21a9d927983aeb6357fecffa7fb23 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Sun, 15 Feb 2009 19:30:19 +0100 Subject: [PATCH 3481/4982] asus-laptop: restore acpi_generate_proc_event() Restore acpi_generate_proc_event() for backward compatibility with old acpi scripts. Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/asus-laptop.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 56af6cf385b..eeafc6c0160 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -815,6 +815,7 @@ static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode) static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) { static struct key_entry *key; + u16 count; /* TODO Find a better way to handle events count. */ if (!hotk) @@ -832,9 +833,11 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) lcd_blank(FB_BLANK_POWERDOWN); } + count = hotk->event_count[event % 128]++; + acpi_bus_generate_proc_event(hotk->device, event, count); acpi_bus_generate_netlink_event(hotk->device->pnp.device_class, dev_name(&hotk->device->dev), event, - hotk->event_count[event % 128]++); + count); if (hotk->inputdev) { key = asus_get_entry_by_scancode(event); -- GitLab From 7950b71c3bd7b27b2874088a6c4efe3e13579f8b Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Sun, 15 Feb 2009 19:30:20 +0100 Subject: [PATCH 3482/4982] eeepc-laptop: restore acpi_generate_proc_event() Restore acpi_generate_proc_event() for backward compatibility with old acpi scripts. Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/eeepc-laptop.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 786ed8661cb..6f54fd1757c 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -557,13 +557,17 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) { static struct key_entry *key; + u16 count; + if (!ehotk) return; if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) notify_brn(); + count = ehotk->event_count[event % 128]++; + acpi_bus_generate_proc_event(ehotk->device, event, count); acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class, dev_name(&ehotk->device->dev), event, - ehotk->event_count[event % 128]++); + count); if (ehotk->inputdev) { key = eepc_get_entry_by_scancode(event); if (key) { -- GitLab From e73e2c62f7646d54e30ef8863ac0be0b8e4ef0eb Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Sun, 15 Feb 2009 19:30:21 +0100 Subject: [PATCH 3483/4982] asus-laptop: use select instead of depends on Like thinkpad_acpi or eeepc-laptop, asus-laptop will now use "select" instead of "depends on" for LEDS_CLASS, NEW_LEDS and BACKLIGHT_CLASS_DEVICE Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index b3866ad5022..fede8f327bb 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -39,9 +39,9 @@ config ASUS_LAPTOP tristate "Asus Laptop Extras (EXPERIMENTAL)" depends on ACPI depends on EXPERIMENTAL && !ACPI_ASUS - depends on LEDS_CLASS - depends on NEW_LEDS - depends on BACKLIGHT_CLASS_DEVICE + select LEDS_CLASS + select NEW_LEDS + select BACKLIGHT_CLASS_DEVICE depends on INPUT ---help--- This is the new Linux driver for Asus laptops. It may also support some -- GitLab From d263da311ab403e3a84fa24920edc826147a550c Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Wed, 25 Feb 2009 09:37:09 +0100 Subject: [PATCH 3484/4982] platform/x86: depends instead of select for laptop platform drivers "I hate `select' and will gleefully leap on any s/select/depends/ patch, whether it works or not :)" Andrew Morton select INPUT is not needed here, because if someone doesn't want INPUT, he won't want these drivers either. Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index fede8f327bb..f3ab40188e6 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -185,11 +185,11 @@ config SONYPI_COMPAT config THINKPAD_ACPI tristate "ThinkPad ACPI Laptop Extras" depends on ACPI + depends on INPUT select BACKLIGHT_LCD_SUPPORT select BACKLIGHT_CLASS_DEVICE select HWMON select NVRAM - select INPUT select NEW_LEDS select LEDS_CLASS select NET -- GitLab From 013d67fd4f0da8f6af60a376f1a254266ab658ef Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 14 Feb 2009 09:53:48 +0000 Subject: [PATCH 3485/4982] acer-wmi: double free in acer_rfkill_exit() This is acer_rfkill_exit() from drivers/platform/x86/acer-wmi.c. The code frees wireless_rfkill->data again instead of bluetooth_rfkill->data. This was found using a code checker (http://repo.or.cz/w/smatch.git/). Signed-off-by: Dan Carpenter Signed-off-by: Carlos Corbacho Signed-off-by: Len Brown --- drivers/platform/x86/acer-wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 6bcca616a70..a6a42e8c060 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -1026,7 +1026,7 @@ static void acer_rfkill_exit(void) kfree(wireless_rfkill->data); rfkill_unregister(wireless_rfkill); if (has_cap(ACER_CAP_BLUETOOTH)) { - kfree(wireless_rfkill->data); + kfree(bluetooth_rfkill->data); rfkill_unregister(bluetooth_rfkill); } return; -- GitLab From 5fcdd177d063f1d8d569d746ab1bf206b0dfb2e8 Mon Sep 17 00:00:00 2001 From: Carlos Corbacho Date: Sat, 14 Feb 2009 09:53:53 +0000 Subject: [PATCH 3486/4982] acpi-wmi: Unmark as 'experimental' ACPI-WMI isn't experimental anymore, and there are other drivers that now depend on it that aren't either. Signed-off-by: Carlos Corbacho Signed-off-by: Len Brown --- drivers/platform/x86/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index f3ab40188e6..c2319d97f51 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -315,9 +315,8 @@ config EEEPC_LAPTOP config ACPI_WMI - tristate "WMI (EXPERIMENTAL)" + tristate "WMI" depends on ACPI - depends on EXPERIMENTAL help This driver adds support for the ACPI-WMI (Windows Management Instrumentation) mapper device (PNP0C14) found on some systems. -- GitLab From 54b1ec893e869c815d390afa42aacf1499858112 Mon Sep 17 00:00:00 2001 From: Carlos Corbacho Date: Sat, 14 Feb 2009 09:53:59 +0000 Subject: [PATCH 3487/4982] acer-wmi: Unmark as 'experimental' This driver has been around and used long enough that we can drop the 'experimental'. Signed-off-by: Carlos Corbacho Signed-off-by: Len Brown --- drivers/platform/x86/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index c2319d97f51..3608081bc3e 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -15,8 +15,7 @@ menuconfig X86_PLATFORM_DEVICES if X86_PLATFORM_DEVICES config ACER_WMI - tristate "Acer WMI Laptop Extras (EXPERIMENTAL)" - depends on EXPERIMENTAL + tristate "Acer WMI Laptop Extras" depends on ACPI depends on LEDS_CLASS depends on NEW_LEDS -- GitLab From b36a50f92d1c4300a88f606b4d2bbdc4f442a2d7 Mon Sep 17 00:00:00 2001 From: Mathieu Chouquet-Stringer Date: Sat, 14 Mar 2009 16:35:26 +0100 Subject: [PATCH 3488/4982] thinkpad-acpi: fix module autoloading for older models Looking at the source, there seems to be a missing * to match my DMI string. I mean for newer IBM and Lenovo's laptops you match either one of the following: MODULE_ALIAS("dmi:bvnIBM:*:svnIBM:*:pvrThinkPad*:rvnIBM:*"); MODULE_ALIAS("dmi:bvnLENOVO:*:svnLENOVO:*:pvrThinkPad*:rvnLENOVO:*"); While for older Thinkpads, you do this (for instance): IBM_BIOS_MODULE_ALIAS("1[0,3,6,8,A-G,I,K,M-P,S,T]"); with IBM_BIOS_MODULE_ALIAS being MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW") Note there's no * terminating the string. As result, udev doesn't load anything because modprobe cannot find anything matching this (my machine actually): udevtest: run: '/sbin/modprobe dmi:bvnIBM:bvr1IET71WW(2.10):bd06/16/2006:svnIBM:pn236621U:pvrNotAv Signed-off-by: Mathieu Chouquet-Stringer Acked-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- drivers/platform/x86/thinkpad_acpi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index bcbc05107ba..d2433204a40 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -7532,7 +7532,7 @@ MODULE_ALIAS(TPACPI_DRVR_SHORTNAME); * if it is not there yet. */ #define IBM_BIOS_MODULE_ALIAS(__type) \ - MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW") + MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW*") /* Non-ancient thinkpads */ MODULE_ALIAS("dmi:bvnIBM:*:svnIBM:*:pvrThinkPad*:rvnIBM:*"); @@ -7541,9 +7541,9 @@ MODULE_ALIAS("dmi:bvnLENOVO:*:svnLENOVO:*:pvrThinkPad*:rvnLENOVO:*"); /* Ancient thinkpad BIOSes have to be identified by * BIOS type or model number, and there are far less * BIOS types than model numbers... */ -IBM_BIOS_MODULE_ALIAS("I[B,D,H,I,M,N,O,T,W,V,Y,Z]"); -IBM_BIOS_MODULE_ALIAS("1[0,3,6,8,A-G,I,K,M-P,S,T]"); -IBM_BIOS_MODULE_ALIAS("K[U,X-Z]"); +IBM_BIOS_MODULE_ALIAS("I[BDHIMNOTWVYZ]"); +IBM_BIOS_MODULE_ALIAS("1[0368A-GIKM-PST]"); +IBM_BIOS_MODULE_ALIAS("K[UX-Z]"); MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh"); MODULE_DESCRIPTION(TPACPI_DESC); -- GitLab From da511997d2bbc09f5e39385e0ed209578db07c91 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Wed, 4 Mar 2009 11:55:30 -0800 Subject: [PATCH 3489/4982] acpi-wmi: unsigned cannot be less than 0 include/linux/pci-acpi.h:74: typedef u32 acpi_status; result is unsigned, so an error returned by acpi_bus_register_driver() will not be noticed. Signed-off-by: Roel Kluin Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/platform/x86/wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 8a8b377712c..2f269e117b8 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -708,7 +708,7 @@ static int __init acpi_wmi_add(struct acpi_device *device) static int __init acpi_wmi_init(void) { - acpi_status result; + int result; INIT_LIST_HEAD(&wmi_blocks.list); -- GitLab From 9f5d790d1b0af8e3705df12fd5d49a1df2a45c47 Mon Sep 17 00:00:00 2001 From: Giuliano Pochini Date: Sun, 15 Mar 2009 21:33:34 +0100 Subject: [PATCH 3490/4982] ALSA: echoaudio: remove line-out volume from vmixer cards There is a long standing bug in the drivers for cards with a vmixer because I overlooked a detail in the c++ generic driver by echoaudio. Those cards do not have a line-out volume control. It is a virtual control provided by the generic driver. The bug is harmless because the DSP just ignores the command to change the volume. *NB:* It breaks alsa-tools/echomixer. A patch for it will follow. This patch removes the line-out volume control from vmixer-equipped cards. Signed-off-by: Giuliano Pochini Signed-off-by: Takashi Iwai --- sound/pci/echoaudio/echoaudio.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index 8dbc5c4ba42..4b70ea1e4c9 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c @@ -950,6 +950,8 @@ static int __devinit snd_echo_new_pcm(struct echoaudio *chip) Control interface ******************************************************************************/ +#ifndef ECHOCARD_HAS_VMIXER + /******************* PCM output volume *******************/ static int snd_echo_output_gain_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) @@ -1001,18 +1003,6 @@ static int snd_echo_output_gain_put(struct snd_kcontrol *kcontrol, return changed; } -#ifdef ECHOCARD_HAS_VMIXER -/* On Vmixer cards this one controls the line-out volume */ -static struct snd_kcontrol_new snd_echo_line_output_gain __devinitdata = { - .name = "Line Playback Volume", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = snd_echo_output_gain_info, - .get = snd_echo_output_gain_get, - .put = snd_echo_output_gain_put, - .tlv = {.p = db_scale_output_gain}, -}; -#else static struct snd_kcontrol_new snd_echo_pcm_output_gain __devinitdata = { .name = "PCM Playback Volume", .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1022,6 +1012,7 @@ static struct snd_kcontrol_new snd_echo_pcm_output_gain __devinitdata = { .put = snd_echo_output_gain_put, .tlv = {.p = db_scale_output_gain}, }; + #endif @@ -2037,8 +2028,6 @@ static int __devinit snd_echo_probe(struct pci_dev *pci, #ifdef ECHOCARD_HAS_VMIXER snd_echo_vmixer.count = num_pipes_out(chip) * num_busses_out(chip); - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_line_output_gain, chip))) < 0) - goto ctl_error; if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vmixer, chip))) < 0) goto ctl_error; #else -- GitLab From 4c55bb0149b604901e4989d1ee0fddc53df8eb0c Mon Sep 17 00:00:00 2001 From: Giuliano Pochini Date: Sun, 15 Mar 2009 21:33:55 +0100 Subject: [PATCH 3491/4982] ALSA: echoaudio: remove line-out volume from vmixer cards With this patch the drivers do not set the vmixer volume anymore at startup because it is actually the output volume of the voices and ALSA mandates that the volume must be 0 by default. Signed-off-by: Giuliano Pochini Signed-off-by: Takashi Iwai --- sound/pci/echoaudio/indigo_dsp.c | 12 ------------ sound/pci/echoaudio/indigodj_dsp.c | 12 ------------ sound/pci/echoaudio/indigoio_dsp.c | 12 ------------ sound/pci/echoaudio/mia_dsp.c | 12 ------------ 4 files changed, 48 deletions(-) diff --git a/sound/pci/echoaudio/indigo_dsp.c b/sound/pci/echoaudio/indigo_dsp.c index f05e39f7aad..0b2cd9c8627 100644 --- a/sound/pci/echoaudio/indigo_dsp.c +++ b/sound/pci/echoaudio/indigo_dsp.c @@ -63,18 +63,6 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) if ((err = init_line_levels(chip)) < 0) return err; - /* Default routing of the virtual channels: all vchannels are routed - to the stereo output */ - set_vmixer_gain(chip, 0, 0, 0); - set_vmixer_gain(chip, 1, 1, 0); - set_vmixer_gain(chip, 0, 2, 0); - set_vmixer_gain(chip, 1, 3, 0); - set_vmixer_gain(chip, 0, 4, 0); - set_vmixer_gain(chip, 1, 5, 0); - set_vmixer_gain(chip, 0, 6, 0); - set_vmixer_gain(chip, 1, 7, 0); - err = update_vmixer_level(chip); - DE_INIT(("init_hw done\n")); return err; } diff --git a/sound/pci/echoaudio/indigodj_dsp.c b/sound/pci/echoaudio/indigodj_dsp.c index 90730a5ecb4..08392916691 100644 --- a/sound/pci/echoaudio/indigodj_dsp.c +++ b/sound/pci/echoaudio/indigodj_dsp.c @@ -63,18 +63,6 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) if ((err = init_line_levels(chip)) < 0) return err; - /* Default routing of the virtual channels: vchannels 0-3 and - vchannels 4-7 are routed to real channels 0-4 */ - set_vmixer_gain(chip, 0, 0, 0); - set_vmixer_gain(chip, 1, 1, 0); - set_vmixer_gain(chip, 2, 2, 0); - set_vmixer_gain(chip, 3, 3, 0); - set_vmixer_gain(chip, 0, 4, 0); - set_vmixer_gain(chip, 1, 5, 0); - set_vmixer_gain(chip, 2, 6, 0); - set_vmixer_gain(chip, 3, 7, 0); - err = update_vmixer_level(chip); - DE_INIT(("init_hw done\n")); return err; } diff --git a/sound/pci/echoaudio/indigoio_dsp.c b/sound/pci/echoaudio/indigoio_dsp.c index a7e09ec2107..0604c8a8522 100644 --- a/sound/pci/echoaudio/indigoio_dsp.c +++ b/sound/pci/echoaudio/indigoio_dsp.c @@ -63,18 +63,6 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) if ((err = init_line_levels(chip)) < 0) return err; - /* Default routing of the virtual channels: all vchannels are routed - to the stereo output */ - set_vmixer_gain(chip, 0, 0, 0); - set_vmixer_gain(chip, 1, 1, 0); - set_vmixer_gain(chip, 0, 2, 0); - set_vmixer_gain(chip, 1, 3, 0); - set_vmixer_gain(chip, 0, 4, 0); - set_vmixer_gain(chip, 1, 5, 0); - set_vmixer_gain(chip, 0, 6, 0); - set_vmixer_gain(chip, 1, 7, 0); - err = update_vmixer_level(chip); - DE_INIT(("init_hw done\n")); return err; } diff --git a/sound/pci/echoaudio/mia_dsp.c b/sound/pci/echoaudio/mia_dsp.c index 227386602f9..f7abe1b60a1 100644 --- a/sound/pci/echoaudio/mia_dsp.c +++ b/sound/pci/echoaudio/mia_dsp.c @@ -69,18 +69,6 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) if ((err = init_line_levels(chip))) return err; - /* Default routing of the virtual channels: vchannels 0-3 go to analog - outputs and vchannels 4-7 go to S/PDIF outputs */ - set_vmixer_gain(chip, 0, 0, 0); - set_vmixer_gain(chip, 1, 1, 0); - set_vmixer_gain(chip, 0, 2, 0); - set_vmixer_gain(chip, 1, 3, 0); - set_vmixer_gain(chip, 2, 4, 0); - set_vmixer_gain(chip, 3, 5, 0); - set_vmixer_gain(chip, 2, 6, 0); - set_vmixer_gain(chip, 3, 7, 0); - err = update_vmixer_level(chip); - DE_INIT(("init_hw done\n")); return err; } -- GitLab From f9847004bf94ba5457738cb5e0f868821864ff50 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 16 Mar 2009 17:52:16 +1000 Subject: [PATCH 3492/4982] m68k: merge the non-MMU and MMU versions of param.h It is trivial to merge the non-MMU and MMU versions of param.h. Without a single file "make headers_install" is broken for m68k (since each of the sub-varients of param.h are not installed). Signed-off-by: Greg Ungerer --- arch/m68k/include/asm/param.h | 25 +++++++++++++++++++++++-- arch/m68k/include/asm/param_mm.h | 22 ---------------------- arch/m68k/include/asm/param_no.h | 22 ---------------------- 3 files changed, 23 insertions(+), 46 deletions(-) delete mode 100644 arch/m68k/include/asm/param_mm.h delete mode 100644 arch/m68k/include/asm/param_no.h diff --git a/arch/m68k/include/asm/param.h b/arch/m68k/include/asm/param.h index 40d1112a458..85c41b75aa7 100644 --- a/arch/m68k/include/asm/param.h +++ b/arch/m68k/include/asm/param.h @@ -1,5 +1,26 @@ +#ifndef _M68K_PARAM_H +#define _M68K_PARAM_H + +#ifdef __KERNEL__ +# define HZ CONFIG_HZ /* Internal kernel timer frequency */ +# define USER_HZ 100 /* .. some user interfaces are in "ticks" */ +# define CLOCKS_PER_SEC (USER_HZ) /* like times() */ +#endif + +#ifndef HZ +#define HZ 100 +#endif + #ifdef __uClinux__ -#include "param_no.h" +#define EXEC_PAGESIZE 4096 #else -#include "param_mm.h" +#define EXEC_PAGESIZE 8192 +#endif + +#ifndef NOGROUP +#define NOGROUP (-1) #endif + +#define MAXHOSTNAMELEN 64 /* max length of hostname */ + +#endif /* _M68K_PARAM_H */ diff --git a/arch/m68k/include/asm/param_mm.h b/arch/m68k/include/asm/param_mm.h deleted file mode 100644 index 536a2788835..00000000000 --- a/arch/m68k/include/asm/param_mm.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _M68K_PARAM_H -#define _M68K_PARAM_H - -#ifdef __KERNEL__ -# define HZ CONFIG_HZ /* Internal kernel timer frequency */ -# define USER_HZ 100 /* .. some user interfaces are in "ticks" */ -# define CLOCKS_PER_SEC (USER_HZ) /* like times() */ -#endif - -#ifndef HZ -#define HZ 100 -#endif - -#define EXEC_PAGESIZE 8192 - -#ifndef NOGROUP -#define NOGROUP (-1) -#endif - -#define MAXHOSTNAMELEN 64 /* max length of hostname */ - -#endif /* _M68K_PARAM_H */ diff --git a/arch/m68k/include/asm/param_no.h b/arch/m68k/include/asm/param_no.h deleted file mode 100644 index 6044397adb6..00000000000 --- a/arch/m68k/include/asm/param_no.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _M68KNOMMU_PARAM_H -#define _M68KNOMMU_PARAM_H - -#ifdef __KERNEL__ -#define HZ CONFIG_HZ -#define USER_HZ HZ -#define CLOCKS_PER_SEC (USER_HZ) -#endif - -#ifndef HZ -#define HZ 100 -#endif - -#define EXEC_PAGESIZE 4096 - -#ifndef NOGROUP -#define NOGROUP (-1) -#endif - -#define MAXHOSTNAMELEN 64 /* max length of hostname */ - -#endif /* _M68KNOMMU_PARAM_H */ -- GitLab From 9863a0babc2f0d920dfb4ddecf4e5b5342cb986b Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 16 Mar 2009 17:54:49 +1000 Subject: [PATCH 3493/4982] m68k: merge the non-MMU and MMU versions of swab.h It is trivial to merge the non-MMU and MMU versions of swab.h. Without a single file "make headers_install" is broken for m68k (since each of the sub-varients of swab.h are not installed). Signed-off-by: Greg Ungerer --- arch/m68k/include/asm/swab.h | 30 ++++++++++++++++++++++++++---- arch/m68k/include/asm/swab_mm.h | 16 ---------------- arch/m68k/include/asm/swab_no.h | 24 ------------------------ 3 files changed, 26 insertions(+), 44 deletions(-) delete mode 100644 arch/m68k/include/asm/swab_mm.h delete mode 100644 arch/m68k/include/asm/swab_no.h diff --git a/arch/m68k/include/asm/swab.h b/arch/m68k/include/asm/swab.h index 7d7dde1c73e..9e3054ea59e 100644 --- a/arch/m68k/include/asm/swab.h +++ b/arch/m68k/include/asm/swab.h @@ -1,5 +1,27 @@ -#ifdef __uClinux__ -#include "swab_no.h" -#else -#include "swab_mm.h" +#ifndef _M68K_SWAB_H +#define _M68K_SWAB_H + +#include +#include + +#define __SWAB_64_THRU_32__ + +#if defined (__mcfisaaplus__) || defined (__mcfisac__) +static inline __attribute_const__ __u32 __arch_swab32(__u32 val) +{ + __asm__("byterev %0" : "=d" (val) : "0" (val)); + return val; +} + +#define __arch_swab32 __arch_swab32 +#elif !defined(__uClinux__) + +static inline __attribute_const__ __u32 __arch_swab32(__u32 val) +{ + __asm__("rolw #8,%0; swap %0; rolw #8,%0" : "=d" (val) : "0" (val)); + return val; +} +#define __arch_swab32 __arch_swab32 #endif + +#endif /* _M68K_SWAB_H */ diff --git a/arch/m68k/include/asm/swab_mm.h b/arch/m68k/include/asm/swab_mm.h deleted file mode 100644 index 7221e306682..00000000000 --- a/arch/m68k/include/asm/swab_mm.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _M68K_SWAB_H -#define _M68K_SWAB_H - -#include -#include - -#define __SWAB_64_THRU_32__ - -static inline __attribute_const__ __u32 __arch_swab32(__u32 val) -{ - __asm__("rolw #8,%0; swap %0; rolw #8,%0" : "=d" (val) : "0" (val)); - return val; -} -#define __arch_swab32 __arch_swab32 - -#endif /* _M68K_SWAB_H */ diff --git a/arch/m68k/include/asm/swab_no.h b/arch/m68k/include/asm/swab_no.h deleted file mode 100644 index e582257db30..00000000000 --- a/arch/m68k/include/asm/swab_no.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _M68KNOMMU_SWAB_H -#define _M68KNOMMU_SWAB_H - -#include - -#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__) -# define __SWAB_64_THRU_32__ -#endif - -#if defined (__mcfisaaplus__) || defined (__mcfisac__) -static inline __attribute_const__ __u32 __arch_swab32(__u32 val) -{ - asm( - "byterev %0" - : "=d" (val) - : "0" (val) - ); - return val; -} - -#define __arch_swab32 __arch_swab32 -#endif - -#endif /* _M68KNOMMU_SWAB_H */ -- GitLab From a05ef46731a1953590062e09a92c2c83ed32a086 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 16 Mar 2009 18:00:25 +1000 Subject: [PATCH 3494/4982] m68k: merge the non-MMU and MMU versions of sigcontext.h It is trivial to merge the non-MMU and MMU versions of sigcontext.h. Without a single file "make headers_install" is broken for m68k (since each of the sub-varients of sigconext.h are not installed). Signed-off-by: Greg Ungerer --- arch/m68k/include/asm/sigcontext.h | 25 ++++++++++++++++++++++--- arch/m68k/include/asm/sigcontext_mm.h | 19 ------------------- arch/m68k/include/asm/sigcontext_no.h | 17 ----------------- 3 files changed, 22 insertions(+), 39 deletions(-) delete mode 100644 arch/m68k/include/asm/sigcontext_mm.h delete mode 100644 arch/m68k/include/asm/sigcontext_no.h diff --git a/arch/m68k/include/asm/sigcontext.h b/arch/m68k/include/asm/sigcontext.h index bff6d40345a..523db2a51cf 100644 --- a/arch/m68k/include/asm/sigcontext.h +++ b/arch/m68k/include/asm/sigcontext.h @@ -1,5 +1,24 @@ +#ifndef _ASM_M68k_SIGCONTEXT_H +#define _ASM_M68k_SIGCONTEXT_H + +struct sigcontext { + unsigned long sc_mask; /* old sigmask */ + unsigned long sc_usp; /* old user stack pointer */ + unsigned long sc_d0; + unsigned long sc_d1; + unsigned long sc_a0; + unsigned long sc_a1; #ifdef __uClinux__ -#include "sigcontext_no.h" -#else -#include "sigcontext_mm.h" + unsigned long sc_a5; +#endif + unsigned short sc_sr; + unsigned long sc_pc; + unsigned short sc_formatvec; +#ifndef __uClinux__ + unsigned long sc_fpregs[2*3]; /* room for two fp registers */ + unsigned long sc_fpcntl[3]; + unsigned char sc_fpstate[216]; +#endif +}; + #endif diff --git a/arch/m68k/include/asm/sigcontext_mm.h b/arch/m68k/include/asm/sigcontext_mm.h deleted file mode 100644 index 64fbe34cf26..00000000000 --- a/arch/m68k/include/asm/sigcontext_mm.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _ASM_M68k_SIGCONTEXT_H -#define _ASM_M68k_SIGCONTEXT_H - -struct sigcontext { - unsigned long sc_mask; /* old sigmask */ - unsigned long sc_usp; /* old user stack pointer */ - unsigned long sc_d0; - unsigned long sc_d1; - unsigned long sc_a0; - unsigned long sc_a1; - unsigned short sc_sr; - unsigned long sc_pc; - unsigned short sc_formatvec; - unsigned long sc_fpregs[2*3]; /* room for two fp registers */ - unsigned long sc_fpcntl[3]; - unsigned char sc_fpstate[216]; -}; - -#endif diff --git a/arch/m68k/include/asm/sigcontext_no.h b/arch/m68k/include/asm/sigcontext_no.h deleted file mode 100644 index 36c293fc133..00000000000 --- a/arch/m68k/include/asm/sigcontext_no.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _ASM_M68KNOMMU_SIGCONTEXT_H -#define _ASM_M68KNOMMU_SIGCONTEXT_H - -struct sigcontext { - unsigned long sc_mask; /* old sigmask */ - unsigned long sc_usp; /* old user stack pointer */ - unsigned long sc_d0; - unsigned long sc_d1; - unsigned long sc_a0; - unsigned long sc_a1; - unsigned long sc_a5; - unsigned short sc_sr; - unsigned long sc_pc; - unsigned short sc_formatvec; -}; - -#endif -- GitLab From a6bc3262c561780d2a6587aa3d5715b1e7d8fa13 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 16 Mar 2009 18:52:56 +1100 Subject: [PATCH 3495/4982] sparseirq, powerpc/cell: fix unused variable warning in interrupt.c This new compiler warning: arch/powerpc/platforms/cell/interrupt.c: In function 'handle_iic_irq': arch/powerpc/platforms/cell/interrupt.c:240: warning: unused variable 'cpu' Triggers because the local variable 'cpu' became unused due to commit: dee4102: sparseirq: use kstat_irqs_cpu instead Remove the variable. Signed-off-by: Stephen Rothwell Cc: Yinghai Lu Cc: ppc-dev LKML-Reference: <20090316185256.4a160374.sfr@canb.auug.org.au> Signed-off-by: Ingo Molnar --- arch/powerpc/platforms/cell/interrupt.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 1f0d774ad92..882e47080e7 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -237,8 +237,6 @@ extern int noirqdebug; static void handle_iic_irq(unsigned int irq, struct irq_desc *desc) { - const unsigned int cpu = smp_processor_id(); - spin_lock(&desc->lock); desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); -- GitLab From 4c3f450ba4e4c00df91f98664b58f9a98dc049fd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 12 Mar 2009 08:40:15 +0000 Subject: [PATCH 3496/4982] sh: Add OHCI USB support for SH7786 Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/setup-sh7786.c | 83 ++++++++++++++++++++++++++ drivers/usb/Kconfig | 1 + drivers/usb/host/ohci-hcd.c | 3 +- 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c index 249b99e1adb..5a47e1cf442 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c @@ -18,6 +18,7 @@ #include #include #include +#include #include static struct plat_sci_port sci_platform_data[] = { @@ -68,12 +69,94 @@ static struct platform_device sci_device = { }, }; +static struct resource usb_ohci_resources[] = { + [0] = { + .start = 0xffe70400, + .end = 0xffe704ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 77, + .end = 77, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 usb_ohci_dma_mask = DMA_BIT_MASK(32); +static struct platform_device usb_ohci_device = { + .name = "sh_ohci", + .id = -1, + .dev = { + .dma_mask = &usb_ohci_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = ARRAY_SIZE(usb_ohci_resources), + .resource = usb_ohci_resources, +}; + static struct platform_device *sh7786_devices[] __initdata = { &sci_device, + &usb_ohci_device, }; + +/* + * Please call this function if your platform board + * use external clock for USB + * */ +#define USBCTL0 0xffe70858 +#define CLOCK_MODE_MASK 0xffffff7f +#define EXT_CLOCK_MODE 0x00000080 +void __init sh7786_usb_use_exclock(void) +{ + u32 val = __raw_readl(USBCTL0) & CLOCK_MODE_MASK; + __raw_writel(val | EXT_CLOCK_MODE, USBCTL0); +} + +#define USBINITREG1 0xffe70094 +#define USBINITREG2 0xffe7009c +#define USBINITVAL1 0x00ff0040 +#define USBINITVAL2 0x00000001 + +#define USBPCTL1 0xffe70804 +#define USBST 0xffe70808 +#define PHY_ENB 0x00000001 +#define PLL_ENB 0x00000002 +#define PHY_RST 0x00000004 +#define ACT_PLL_STATUS 0xc0000000 +static void __init sh7786_usb_setup(void) +{ + int i = 1000000; + + /* + * USB initial settings + * + * The following settings are necessary + * for using the USB modules. + * + * see "USB Inital Settings" for detail + */ + __raw_writel(USBINITVAL1, USBINITREG1); + __raw_writel(USBINITVAL2, USBINITREG2); + + /* + * Set the PHY and PLL enable bit + */ + __raw_writel(PHY_ENB | PLL_ENB, USBPCTL1); + while (i-- && + ((__raw_readl(USBST) & ACT_PLL_STATUS) != ACT_PLL_STATUS)) + cpu_relax(); + + if (i) { + /* Set the PHY RST bit */ + __raw_writel(PHY_ENB | PLL_ENB | PHY_RST, USBPCTL1); + printk(KERN_INFO "sh7786 usb setup done\n"); + } +} + static int __init sh7786_devices_setup(void) { + sh7786_usb_setup(); return platform_add_devices(sh7786_devices, ARRAY_SIZE(sh7786_devices)); } diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 83babb0a1df..c6c816b7ecb 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -47,6 +47,7 @@ config USB_ARCH_HAS_OHCI default y if CPU_SUBTYPE_SH7720 default y if CPU_SUBTYPE_SH7721 default y if CPU_SUBTYPE_SH7763 + default y if CPU_SUBTYPE_SH7786 # more: default PCI diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 5cf5f1eca4f..7658589edb1 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1049,7 +1049,8 @@ MODULE_LICENSE ("GPL"); #if defined(CONFIG_CPU_SUBTYPE_SH7720) || \ defined(CONFIG_CPU_SUBTYPE_SH7721) || \ - defined(CONFIG_CPU_SUBTYPE_SH7763) + defined(CONFIG_CPU_SUBTYPE_SH7763) || \ + defined(CONFIG_CPU_SUBTYPE_SH7786) #include "ohci-sh.c" #define PLATFORM_DRIVER ohci_hcd_sh_driver #endif -- GitLab From 039a718ebb37298de87801288673859ac40b6fc4 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Thu, 12 Mar 2009 06:34:39 +0000 Subject: [PATCH 3497/4982] sh: Revert CONFIG_NR_ONCHIP_DMA_CHANNELS to MAX_DMA_CHANNELS Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: Paul Mundt --- arch/sh/include/asm/dma-sh.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/arch/sh/include/asm/dma-sh.h b/arch/sh/include/asm/dma-sh.h index e873ecaa506..0c8f8e14622 100644 --- a/arch/sh/include/asm/dma-sh.h +++ b/arch/sh/include/asm/dma-sh.h @@ -11,6 +11,7 @@ #ifndef __DMA_SH_H #define __DMA_SH_H +#include #include /* DMAOR contorl: The DMAOR access size is different by CPU.*/ @@ -29,21 +30,21 @@ #endif static int dmte_irq_map[] __maybe_unused = { -#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 4) +#if (MAX_DMA_CHANNELS >= 4) DMTE0_IRQ, DMTE0_IRQ + 1, DMTE0_IRQ + 2, DMTE0_IRQ + 3, #endif -#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 6) +#if (MAX_DMA_CHANNELS >= 6) DMTE4_IRQ, DMTE4_IRQ + 1, #endif -#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 8) +#if (MAX_DMA_CHANNELS >= 8) DMTE6_IRQ, DMTE6_IRQ + 1, #endif -#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 12) +#if (MAX_DMA_CHANNELS >= 12) DMTE8_IRQ, DMTE9_IRQ, DMTE10_IRQ, @@ -85,21 +86,21 @@ static int dmte_irq_map[] __maybe_unused = { /* DMA base address */ static u32 dma_base_addr[] __maybe_unused = { -#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 4) +#if (MAX_DMA_CHANNELS >= 4) SH_DMAC_BASE0 + 0x00, /* channel 0 */ SH_DMAC_BASE0 + 0x10, SH_DMAC_BASE0 + 0x20, SH_DMAC_BASE0 + 0x30, #endif -#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 6) +#if (MAX_DMA_CHANNELS >= 6) SH_DMAC_BASE0 + 0x50, SH_DMAC_BASE0 + 0x60, #endif -#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 8) +#if (MAX_DMA_CHANNELS >= 8) SH_DMAC_BASE1 + 0x00, SH_DMAC_BASE1 + 0x10, #endif -#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 12) +#if (MAX_DMA_CHANNELS >= 12) SH_DMAC_BASE1 + 0x20, SH_DMAC_BASE1 + 0x30, SH_DMAC_BASE1 + 0x50, -- GitLab From a83c0b739f3ad1887704cfa9f1ee5ee208cf1532 Mon Sep 17 00:00:00 2001 From: Francesco VIRLINZI Date: Wed, 11 Mar 2009 10:39:02 +0000 Subject: [PATCH 3498/4982] sh: PMB hibernation support This implements preliminary suspend/resume support for the PMB. Signed-off-by: Francesco Virlinzi Signed-off-by: Paul Mundt --- arch/sh/mm/pmb.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c index 84241676265..b1a714a92b1 100644 --- a/arch/sh/mm/pmb.c +++ b/arch/sh/mm/pmb.c @@ -15,6 +15,8 @@ */ #include #include +#include +#include #include #include #include @@ -402,3 +404,39 @@ static int __init pmb_debugfs_init(void) return 0; } postcore_initcall(pmb_debugfs_init); + +#ifdef CONFIG_PM +static int pmb_sysdev_suspend(struct sys_device *dev, pm_message_t state) +{ + static pm_message_t prev_state; + + /* Restore the PMB after a resume from hibernation */ + if (state.event == PM_EVENT_ON && + prev_state.event == PM_EVENT_FREEZE) { + struct pmb_entry *pmbe; + spin_lock_irq(&pmb_list_lock); + for (pmbe = pmb_list; pmbe; pmbe = pmbe->next) + set_pmb_entry(pmbe); + spin_unlock_irq(&pmb_list_lock); + } + prev_state = state; + return 0; +} + +static int pmb_sysdev_resume(struct sys_device *dev) +{ + return pmb_sysdev_suspend(dev, PMSG_ON); +} + +static struct sysdev_driver pmb_sysdev_driver = { + .suspend = pmb_sysdev_suspend, + .resume = pmb_sysdev_resume, +}; + +static int __init pmb_sysdev_init(void) +{ + return sysdev_driver_register(&cpu_sysdev_class, &pmb_sysdev_driver); +} + +subsys_initcall(pmb_sysdev_init); +#endif -- GitLab From 02ebd32f52c10f90f810e85d0281e9e81dd6e741 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Fri, 13 Mar 2009 04:31:34 +0000 Subject: [PATCH 3499/4982] sh: Disable get_dma_error_irq for non-SH4 targets. dma-sh's get_dma_error_irq() is only used by SH4, as the SH3 doesn't have the DMA Error interrupt. Disable it out for non-SH4 builds. Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: Paul Mundt --- arch/sh/drivers/dma/dma-sh.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c index ab7b18dcbab..31c2930f2f5 100644 --- a/arch/sh/drivers/dma/dma-sh.c +++ b/arch/sh/drivers/dma/dma-sh.c @@ -280,6 +280,7 @@ static struct dma_info sh_dmac_info = { .flags = DMAC_CHANNELS_TEI_CAPABLE, }; +#ifdef CONFIG_CPU_SH4 static unsigned int get_dma_error_irq(int n) { #if defined(DMAC_IRQ_MULTI) @@ -293,6 +294,7 @@ static unsigned int get_dma_error_irq(int n) #endif #endif } +#endif static int __init sh_dmac_init(void) { -- GitLab From 7a516280b6a99634933b417834e178bde8659da1 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Fri, 13 Mar 2009 05:03:37 +0000 Subject: [PATCH 3500/4982] sh: Fix compile error by operands(mov.l) in sh3/entry.S -- log -- arch/sh/kernel/cpu/sh4/../sh3/entry.S:365: Error: invalid operands for opcode make[4]: *** [arch/sh/kernel/cpu/sh4/../sh3/entry.o] Error 1 make[3]: *** [arch/sh/kernel/cpu/sh4] Error 2 -- log -- Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh3/entry.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S index fba6ac20bb1..55da0ff9848 100644 --- a/arch/sh/kernel/cpu/sh3/entry.S +++ b/arch/sh/kernel/cpu/sh3/entry.S @@ -362,7 +362,7 @@ general_exception: nop ! Save registers / Switch to bank 0 - mov.l k4, k2 ! keep vector in k2 + mov k4, k2 ! keep vector in k2 mov.l 1f, k4 ! SR bits to clear in k4 bsr save_regs ! needs original pr value in k3 nop -- GitLab From 7759491274bc5ba7cd72b3b9cc5ec8247b937efb Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 13 Mar 2009 15:23:04 +0000 Subject: [PATCH 3501/4982] sh: SuperH Mobile suspend support This patch contains CONFIG_SUSPEND support to the SuperH architecture. If enabled, SuperH Mobile processors will register their suspend callbacks during boot. To suspend, use "echo mem > /sys/power/state". To allow wakeup, make sure "/sys/device/platform/../power/wakeup" contains "enabled". Additional per-device driver patches are most likely needed. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 1 + arch/sh/include/asm/suspend.h | 9 ++ arch/sh/kernel/cpu/sh4a/Makefile | 4 + arch/sh/kernel/cpu/sh4a/pm-sh_mobile.c | 92 ++++++++++++++++ arch/sh/kernel/cpu/sh4a/sleep-sh_mobile.S | 125 ++++++++++++++++++++++ 5 files changed, 231 insertions(+) create mode 100644 arch/sh/kernel/cpu/sh4a/pm-sh_mobile.c create mode 100644 arch/sh/kernel/cpu/sh4a/sleep-sh_mobile.S diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index adffbf4048b..a0c879d17fd 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -181,6 +181,7 @@ config CPU_SHX3 config ARCH_SHMOBILE bool + select ARCH_SUSPEND_POSSIBLE choice prompt "Processor sub-type selection" diff --git a/arch/sh/include/asm/suspend.h b/arch/sh/include/asm/suspend.h index 5d6d8aba568..b1b995370e7 100644 --- a/arch/sh/include/asm/suspend.h +++ b/arch/sh/include/asm/suspend.h @@ -1,6 +1,7 @@ #ifndef _ASM_SH_SUSPEND_H #define _ASM_SH_SUSPEND_H +#ifndef __ASSEMBLY__ static inline int arch_prepare_suspend(void) { return 0; } #include @@ -9,5 +10,13 @@ struct swsusp_arch_regs { struct pt_regs user_regs; unsigned long bank1_regs[8]; }; +#endif + +/* flags passed to assembly suspend code */ +#define SUSP_SH_SLEEP (1 << 0) /* Regular sleep mode */ +#define SUSP_SH_STANDBY (1 << 1) /* SH-Mobile Software standby mode */ +#define SUSP_SH_RSTANDBY (1 << 2) /* SH-Mobile R-standby mode */ +#define SUSP_SH_USTANDBY (1 << 3) /* SH-Mobile U-standby mode */ +#define SUSP_SH_SF (1 << 4) /* Enable self-refresh */ #endif /* _ASM_SH_SUSPEND_H */ diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile index 1a92361feeb..09967dc0065 100644 --- a/arch/sh/kernel/cpu/sh4a/Makefile +++ b/arch/sh/kernel/cpu/sh4a/Makefile @@ -35,6 +35,10 @@ pinmux-$(CONFIG_CPU_SUBTYPE_SH7723) := pinmux-sh7723.o pinmux-$(CONFIG_CPU_SUBTYPE_SH7785) := pinmux-sh7785.o pinmux-$(CONFIG_CPU_SUBTYPE_SH7786) := pinmux-sh7786.o +# Power Mangement & Sleep mode +pm-$(CONFIG_ARCH_SHMOBILE) := pm-sh_mobile.o sleep-sh_mobile.o + obj-y += $(clock-y) obj-$(CONFIG_SMP) += $(smp-y) obj-$(CONFIG_GENERIC_GPIO) += $(pinmux-y) +obj-$(CONFIG_PM) += $(pm-y) diff --git a/arch/sh/kernel/cpu/sh4a/pm-sh_mobile.c b/arch/sh/kernel/cpu/sh4a/pm-sh_mobile.c new file mode 100644 index 00000000000..8c067adf683 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4a/pm-sh_mobile.c @@ -0,0 +1,92 @@ +/* + * arch/sh/kernel/cpu/sh4a/pm-sh_mobile.c + * + * Power management support code for SuperH Mobile + * + * Copyright (C) 2009 Magnus Damm + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include + +/* + * Sleep modes available on SuperH Mobile: + * + * Sleep mode is just plain "sleep" instruction + * Sleep Self-Refresh mode is above plus RAM put in Self-Refresh + * Standby Self-Refresh mode is above plus stopped clocks + */ +#define SUSP_MODE_SLEEP (SUSP_SH_SLEEP) +#define SUSP_MODE_SLEEP_SF (SUSP_SH_SLEEP | SUSP_SH_SF) +#define SUSP_MODE_STANDBY_SF (SUSP_SH_STANDBY | SUSP_SH_SF) + +/* + * The following modes are not there yet: + * + * R-standby mode is unsupported, but will be added in the future + * U-standby mode is low priority since it needs bootloader hacks + * + * All modes should be tied in with cpuidle. But before that can + * happen we need to keep track of enabled hardware blocks so we + * can avoid entering sleep modes that stop clocks to hardware + * blocks that are in use even though the cpu core is idle. + */ + +extern const unsigned char sh_mobile_standby[]; +extern const unsigned int sh_mobile_standby_size; + +static void sh_mobile_call_standby(unsigned long mode) +{ + extern void *vbr_base; + void *onchip_mem = (void *)0xe5200000; /* ILRAM */ + void (*standby_onchip_mem)(unsigned long) = onchip_mem; + + /* Note: Wake up from sleep may generate exceptions! + * Setup VBR to point to on-chip ram if self-refresh is + * going to be used. + */ + if (mode & SUSP_SH_SF) + asm volatile("ldc %0, vbr" : : "r" (onchip_mem) : "memory"); + + /* Copy the assembly snippet to the otherwise ununsed ILRAM */ + memcpy(onchip_mem, sh_mobile_standby, sh_mobile_standby_size); + wmb(); + ctrl_barrier(); + + /* Let assembly snippet in on-chip memory handle the rest */ + standby_onchip_mem(mode); + + /* Put VBR back in System RAM again */ + if (mode & SUSP_SH_SF) + asm volatile("ldc %0, vbr" : : "r" (&vbr_base) : "memory"); +} + +static int sh_pm_enter(suspend_state_t state) +{ + local_irq_disable(); + set_bl_bit(); + sh_mobile_call_standby(SUSP_MODE_STANDBY_SF); + local_irq_disable(); + clear_bl_bit(); + return 0; +} + +static struct platform_suspend_ops sh_pm_ops = { + .enter = sh_pm_enter, + .valid = suspend_valid_only_mem, +}; + +static int __init sh_pm_init(void) +{ + suspend_set_ops(&sh_pm_ops); + return 0; +} + +late_initcall(sh_pm_init); diff --git a/arch/sh/kernel/cpu/sh4a/sleep-sh_mobile.S b/arch/sh/kernel/cpu/sh4a/sleep-sh_mobile.S new file mode 100644 index 00000000000..5d888ef53d8 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4a/sleep-sh_mobile.S @@ -0,0 +1,125 @@ +/* + * arch/sh/kernel/cpu/sh4a/sleep-sh_mobile.S + * + * Sleep mode and Standby modes support for SuperH Mobile + * + * Copyright (C) 2009 Magnus Damm + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include + +/* manage self-refresh and enter standby mode. + * this code will be copied to on-chip memory and executed from there. + */ + + .balign 4096,0,4096 +ENTRY(sh_mobile_standby) + mov r4, r0 + + tst #SUSP_SH_SF, r0 + bt skip_set_sf + + /* SDRAM: disable power down and put in self-refresh mode */ + mov.l 1f, r4 + mov.l 2f, r1 + mov.l @r4, r2 + or r1, r2 + mov.l 3f, r3 + and r3, r2 + mov.l r2, @r4 + +skip_set_sf: + tst #SUSP_SH_SLEEP, r0 + bt test_standby + + /* set mode to "sleep mode" */ + bra do_sleep + mov #0x00, r1 + +test_standby: + tst #SUSP_SH_STANDBY, r0 + bt test_rstandby + + /* set mode to "software standby mode" */ + bra do_sleep + mov #0x80, r1 + +test_rstandby: + tst #SUSP_SH_RSTANDBY, r0 + bt test_ustandby + + /* set mode to "r-standby mode" */ + bra do_sleep + mov #0x20, r1 + +test_ustandby: + tst #SUSP_SH_USTANDBY, r0 + bt done_sleep + + /* set mode to "u-standby mode" */ + mov #0x10, r1 + + /* fall-through */ + +do_sleep: + /* setup and enter selected standby mode */ + mov.l 5f, r4 + mov.l r1, @r4 + sleep + +done_sleep: + /* reset standby mode to sleep mode */ + mov.l 5f, r4 + mov #0x00, r1 + mov.l r1, @r4 + + tst #SUSP_SH_SF, r0 + bt skip_restore_sf + + /* SDRAM: set auto-refresh mode */ + mov.l 1f, r4 + mov.l @r4, r2 + mov.l 4f, r3 + and r3, r2 + mov.l r2, @r4 + mov.l 6f, r4 + mov.l 7f, r1 + mov.l 8f, r2 + mov.l @r4, r3 + mov #-1, r4 + add r4, r3 + or r2, r3 + mov.l r3, @r1 +skip_restore_sf: + rts + nop + + .balign 4 +1: .long 0xfe400008 /* SDCR0 */ +2: .long 0x00000400 +3: .long 0xffff7fff +4: .long 0xfffffbff +5: .long 0xa4150020 /* STBCR */ +6: .long 0xfe40001c /* RTCOR */ +7: .long 0xfe400018 /* RTCNT */ +8: .long 0xa55a0000 + +/* interrupt vector @ 0x600 */ + .balign 0x400,0,0x400 + .long 0xdeadbeef + .balign 0x200,0,0x200 + /* sh7722 will end up here in sleep mode */ + rte + nop +sh_mobile_standby_end: + +ENTRY(sh_mobile_standby_size) + .long sh_mobile_standby_end - sh_mobile_standby -- GitLab From 93356d07474b1f16f25e79e81597c2a6b8c2a783 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 13 Mar 2009 15:27:14 +0000 Subject: [PATCH 3502/4982] sh: add ap325 lcd power off support Improve the ap325 board code to allow the lcd panel and backlight to be powered off. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/boards/board-ap325rxa.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/sh/boards/board-ap325rxa.c b/arch/sh/boards/board-ap325rxa.c index 15b6d450fbf..a64e38841c4 100644 --- a/arch/sh/boards/board-ap325rxa.c +++ b/arch/sh/boards/board-ap325rxa.c @@ -166,6 +166,16 @@ static void ap320_wvga_power_on(void *board_data) ctrl_outw(0x100, FPGA_BKLREG); } +static void ap320_wvga_power_off(void *board_data) +{ + /* backlight */ + ctrl_outw(0, FPGA_BKLREG); + gpio_set_value(GPIO_PTS3, 1); + + /* ASD AP-320/325 LCD OFF */ + ctrl_outw(0, FPGA_LCDREG); +} + static struct sh_mobile_lcdc_info lcdc_info = { .clock_source = LCDC_CLK_EXTERNAL, .ch[0] = { @@ -191,6 +201,7 @@ static struct sh_mobile_lcdc_info lcdc_info = { }, .board_cfg = { .display_on = ap320_wvga_power_on, + .display_off = ap320_wvga_power_off, }, } }; -- GitLab From 2feb075a33905c2f6ef6be484c75ba6a35f6d12d Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 13 Mar 2009 15:36:55 +0000 Subject: [PATCH 3503/4982] video: sh_mobile_lcdcfb suspend/resume support This patch adds suspend/resume support to the LCDC driver for SuperH Mobile - sh_mobile_lcdcfb. We simply stop hardware on suspend and start it again on resume. For RGB panels this is trivial, but for SYS panels in deferred io mode this becomes a bit more difficult - we need to wait for a frame end interrupt to make sure the clocks are balanced before stopping the actual hardware. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/video/sh_mobile_lcdcfb.c | 66 ++++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 7 deletions(-) diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 2c5d069e5f0..b433b8ac76d 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -33,6 +33,8 @@ struct sh_mobile_lcdc_chan { struct fb_info info; dma_addr_t dma_handle; struct fb_deferred_io defio; + unsigned long frame_end; + wait_queue_head_t frame_end_wait; }; struct sh_mobile_lcdc_priv { @@ -226,7 +228,10 @@ static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info) static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data) { struct sh_mobile_lcdc_priv *priv = data; + struct sh_mobile_lcdc_chan *ch; unsigned long tmp; + int is_sub; + int k; /* acknowledge interrupt */ tmp = lcdc_read(priv, _LDINTR); @@ -234,8 +239,24 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data) tmp |= 0x000000ff ^ LDINTR_FS; /* status in low 8 */ lcdc_write(priv, _LDINTR, tmp); - /* disable clocks */ - sh_mobile_lcdc_clk_off(priv); + /* figure out if this interrupt is for main or sub lcd */ + is_sub = (lcdc_read(priv, _LDSR) & (1 << 10)) ? 1 : 0; + + /* wake up channel and disable clocks*/ + for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { + ch = &priv->ch[k]; + + if (!ch->enabled) + continue; + + if (is_sub == lcdc_chan_is_sublcd(ch)) { + ch->frame_end = 1; + wake_up(&ch->frame_end_wait); + + sh_mobile_lcdc_clk_off(priv); + } + } + return IRQ_HANDLED; } @@ -448,18 +469,27 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) struct sh_mobile_lcdc_board_cfg *board_cfg; int k; - /* tell the board code to disable the panel */ + /* clean up deferred io and ask board code to disable panel */ for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { ch = &priv->ch[k]; - board_cfg = &ch->cfg.board_cfg; - if (board_cfg->display_off) - board_cfg->display_off(board_cfg->board_data); - /* cleanup deferred io if enabled */ + /* deferred io mode: + * flush frame, and wait for frame end interrupt + * clean up deferred io and enable clock + */ if (ch->info.fbdefio) { + ch->frame_end = 0; + schedule_delayed_work(&ch->info.deferred_work, 0); + wait_event(ch->frame_end_wait, ch->frame_end); fb_deferred_io_cleanup(&ch->info); ch->info.fbdefio = NULL; + sh_mobile_lcdc_clk_on(priv); } + + board_cfg = &ch->cfg.board_cfg; + if (board_cfg->display_off) + board_cfg->display_off(board_cfg->board_data); + } /* stop the lcdc */ @@ -652,6 +682,26 @@ static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp) return 0; } +static int sh_mobile_lcdc_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + + sh_mobile_lcdc_stop(platform_get_drvdata(pdev)); + return 0; +} + +static int sh_mobile_lcdc_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + + return sh_mobile_lcdc_start(platform_get_drvdata(pdev)); +} + +static struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = { + .suspend = sh_mobile_lcdc_suspend, + .resume = sh_mobile_lcdc_resume, +}; + static int sh_mobile_lcdc_remove(struct platform_device *pdev); static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) @@ -707,6 +757,7 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "unsupported interface type\n"); goto err1; } + init_waitqueue_head(&priv->ch[i].frame_end_wait); switch (pdata->ch[i].chan) { case LCDC_CHAN_MAINLCD: @@ -860,6 +911,7 @@ static struct platform_driver sh_mobile_lcdc_driver = { .driver = { .name = "sh_mobile_lcdc_fb", .owner = THIS_MODULE, + .pm = &sh_mobile_lcdc_dev_pm_ops, }, .probe = sh_mobile_lcdc_probe, .remove = sh_mobile_lcdc_remove, -- GitLab From e9edb3fec2260b5a64e9ca9e09160b74f1b106e3 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 16 Mar 2009 20:00:17 +0900 Subject: [PATCH 3504/4982] sh: Consolidate SH-Mobile CPU code in arch/sh/kernel/cpu/shmobile/. Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/Makefile | 1 + arch/sh/kernel/cpu/sh4a/Makefile | 4 ---- arch/sh/kernel/cpu/shmobile/Makefile | 6 ++++++ arch/sh/kernel/cpu/{sh4a/pm-sh_mobile.c => shmobile/pm.c} | 0 .../kernel/cpu/{sh4a/sleep-sh_mobile.S => shmobile/sleep.S} | 0 5 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 arch/sh/kernel/cpu/shmobile/Makefile rename arch/sh/kernel/cpu/{sh4a/pm-sh_mobile.c => shmobile/pm.c} (100%) rename arch/sh/kernel/cpu/{sh4a/sleep-sh_mobile.S => shmobile/sleep.S} (100%) diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile index f471d242774..2600641a483 100644 --- a/arch/sh/kernel/cpu/Makefile +++ b/arch/sh/kernel/cpu/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_CPU_SH5) = sh5/ # Special cases for family ancestry. obj-$(CONFIG_CPU_SH4A) += sh4a/ +obj-$(CONFIG_ARCH_SHMOBILE) += shmobile/ # Common interfaces. diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile index 09967dc0065..1a92361feeb 100644 --- a/arch/sh/kernel/cpu/sh4a/Makefile +++ b/arch/sh/kernel/cpu/sh4a/Makefile @@ -35,10 +35,6 @@ pinmux-$(CONFIG_CPU_SUBTYPE_SH7723) := pinmux-sh7723.o pinmux-$(CONFIG_CPU_SUBTYPE_SH7785) := pinmux-sh7785.o pinmux-$(CONFIG_CPU_SUBTYPE_SH7786) := pinmux-sh7786.o -# Power Mangement & Sleep mode -pm-$(CONFIG_ARCH_SHMOBILE) := pm-sh_mobile.o sleep-sh_mobile.o - obj-y += $(clock-y) obj-$(CONFIG_SMP) += $(smp-y) obj-$(CONFIG_GENERIC_GPIO) += $(pinmux-y) -obj-$(CONFIG_PM) += $(pm-y) diff --git a/arch/sh/kernel/cpu/shmobile/Makefile b/arch/sh/kernel/cpu/shmobile/Makefile new file mode 100644 index 00000000000..08bfa7c7db2 --- /dev/null +++ b/arch/sh/kernel/cpu/shmobile/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for the Linux/SuperH SH-Mobile backends. +# + +# Power Management & Sleep mode +obj-$(CONFIG_PM) += pm.o sleep.o diff --git a/arch/sh/kernel/cpu/sh4a/pm-sh_mobile.c b/arch/sh/kernel/cpu/shmobile/pm.c similarity index 100% rename from arch/sh/kernel/cpu/sh4a/pm-sh_mobile.c rename to arch/sh/kernel/cpu/shmobile/pm.c diff --git a/arch/sh/kernel/cpu/sh4a/sleep-sh_mobile.S b/arch/sh/kernel/cpu/shmobile/sleep.S similarity index 100% rename from arch/sh/kernel/cpu/sh4a/sleep-sh_mobile.S rename to arch/sh/kernel/cpu/shmobile/sleep.S -- GitLab From 50cca715a64b66ccf173767d94d4020ea0a6129c Mon Sep 17 00:00:00 2001 From: Francesco VIRLINZI Date: Fri, 13 Mar 2009 08:08:01 +0000 Subject: [PATCH 3505/4982] sh: clkfwk: Safer resume from hibernation. This patch fixes a possible problem in the resume from hibenration. It temporaneally saves the clk->rate on the stack to avoid any possible change during the clk->set_parent(..) call. Signed-off-by: Francesco Virlinzi Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/clock.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c index 3209a8740fa..1dc896483b5 100644 --- a/arch/sh/kernel/cpu/clock.c +++ b/arch/sh/kernel/cpu/clock.c @@ -372,12 +372,14 @@ static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state) if (prev_state.event == PM_EVENT_FREEZE) { list_for_each_entry(clkp, &clock_list, node) if (likely(clkp->ops)) { + unsigned long rate = clkp->rate; + if (likely(clkp->ops->set_parent)) clkp->ops->set_parent(clkp, clkp->parent); if (likely(clkp->ops->set_rate)) clkp->ops->set_rate(clkp, - clkp->rate, NO_CHANGE); + rate, NO_CHANGE); else if (likely(clkp->ops->recalc)) clkp->ops->recalc(clkp); } -- GitLab From 988f831df398ff36f67b095245060c24c354e9e9 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Mon, 16 Mar 2009 03:22:07 +0000 Subject: [PATCH 3506/4982] sh: Move IRQ multi definition of DMAC to defconfig When SuperH CPU has IRQ multi of DMAC, SH_DMA_IRQ_MULTI becomes enable. The following CPU's are Multi IRQ of DMAC now. - SH775X and SH7091 - SH776X - SH7780 - SH7785 If SH_DMA_IRQ_MULTI becomes enable, dma-sh api driver is optimized for Multi IRQ. Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: Paul Mundt --- arch/sh/drivers/dma/Kconfig | 8 ++++++++ arch/sh/drivers/dma/dma-sh.c | 17 +++++------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/arch/sh/drivers/dma/Kconfig b/arch/sh/drivers/dma/Kconfig index 57d95fce046..32bb8fa605c 100644 --- a/arch/sh/drivers/dma/Kconfig +++ b/arch/sh/drivers/dma/Kconfig @@ -9,6 +9,14 @@ config SH_DMA select SH_DMA_API default n +config SH_DMA_IRQ_MULTI + bool + depends on SH_DMA + default y if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7751 || \ + CPU_SUBTYPE_SH7750S || CPU_SUBTYPE_SH7750R || CPU_SUBTYPE_SH7751R || \ + CPU_SUBTYPE_SH7091 || CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7764 || \ + CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785 + config NR_ONCHIP_DMA_CHANNELS int depends on SH_DMA diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c index 31c2930f2f5..37fb5b8bbc3 100644 --- a/arch/sh/drivers/dma/dma-sh.c +++ b/arch/sh/drivers/dma/dma-sh.c @@ -19,13 +19,6 @@ #include #include -#if defined(CONFIG_CPU_SUBTYPE_SH7763) || \ - defined(CONFIG_CPU_SUBTYPE_SH7764) || \ - defined(CONFIG_CPU_SUBTYPE_SH7780) || \ - defined(CONFIG_CPU_SUBTYPE_SH7785) -#define DMAC_IRQ_MULTI 1 -#endif - #if defined(DMAE1_IRQ) #define NR_DMAE 2 #else @@ -42,7 +35,7 @@ static inline unsigned int get_dmte_irq(unsigned int chan) if (chan < ARRAY_SIZE(dmte_irq_map)) irq = dmte_irq_map[chan]; -#if defined(DMAC_IRQ_MULTI) +#if defined(CONFIG_SH_DMA_IRQ_MULTI) if (irq > DMTE6_IRQ) return DMTE6_IRQ; return DMTE0_IRQ; @@ -96,7 +89,7 @@ static int sh_dmac_request_dma(struct dma_channel *chan) return 0; return request_irq(get_dmte_irq(chan->chan), dma_tei, -#if defined(DMAC_IRQ_MULTI) +#if defined(CONFIG_SH_DMA_IRQ_MULTI) IRQF_SHARED, #else IRQF_DISABLED, @@ -235,7 +228,7 @@ static inline int dmaor_reset(int no) #if defined(CONFIG_CPU_SH4) static irqreturn_t dma_err(int irq, void *dummy) { -#if defined(DMAC_IRQ_MULTI) +#if defined(CONFIG_SH_DMA_IRQ_MULTI) int cnt = 0; switch (irq) { #if defined(DMTE6_IRQ) && defined(DMAE1_IRQ) @@ -283,7 +276,7 @@ static struct dma_info sh_dmac_info = { #ifdef CONFIG_CPU_SH4 static unsigned int get_dma_error_irq(int n) { -#if defined(DMAC_IRQ_MULTI) +#if defined(CONFIG_SH_DMA_IRQ_MULTI) return (n == 0) ? get_dmte_irq(0) : get_dmte_irq(6); #else return (n == 0) ? DMAE0_IRQ : @@ -306,7 +299,7 @@ static int __init sh_dmac_init(void) for (n = 0; n < NR_DMAE; n++) { i = request_irq(get_dma_error_irq(n), dma_err, -#if defined(DMAC_IRQ_MULTI) +#if defined(CONFIG_SH_DMA_IRQ_MULTI) IRQF_SHARED, #else IRQF_DISABLED, -- GitLab From ca735b3aaa945626ba65a3e51145bfe4ecd9e222 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Mon, 16 Mar 2009 14:54:21 +0100 Subject: [PATCH 3507/4982] netfilter: use a linked list of loggers This patch modifies nf_log to use a linked list of loggers for each protocol. This list of loggers is read and write protected with a mutex. This patch separates registration and binding. To be used as logging module, a module has to register calling nf_log_register() and to bind to a protocol it has to call nf_log_bind_pf(). This patch also converts the logging modules to the new API. For nfnetlink_log, it simply switchs call to register functions to call to bind function and adds a call to nf_log_register() during init. For other modules, it just remove a const flag from the logger structure and replace it with a __read_mostly. Signed-off-by: Eric Leblond Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_log.h | 11 +++-- net/ipv4/netfilter/ipt_LOG.c | 2 +- net/ipv4/netfilter/ipt_ULOG.c | 2 +- net/ipv6/netfilter/ip6t_LOG.c | 2 +- net/netfilter/nf_log.c | 90 ++++++++++++++++++++++------------ net/netfilter/nfnetlink_log.c | 18 +++++-- 6 files changed, 84 insertions(+), 41 deletions(-) diff --git a/include/net/netfilter/nf_log.h b/include/net/netfilter/nf_log.h index 7182c06974f..920997f1aff 100644 --- a/include/net/netfilter/nf_log.h +++ b/include/net/netfilter/nf_log.h @@ -1,6 +1,8 @@ #ifndef _NF_LOG_H #define _NF_LOG_H +#include + /* those NF_LOG_* defines and struct nf_loginfo are legacy definitios that will * disappear once iptables is replaced with pkttables. Please DO NOT use them * for any new code! */ @@ -40,12 +42,15 @@ struct nf_logger { struct module *me; nf_logfn *logfn; char *name; + struct list_head list[NFPROTO_NUMPROTO]; }; /* Function to register/unregister log function. */ -int nf_log_register(u_int8_t pf, const struct nf_logger *logger); -void nf_log_unregister(const struct nf_logger *logger); -void nf_log_unregister_pf(u_int8_t pf); +int nf_log_register(u_int8_t pf, struct nf_logger *logger); +void nf_log_unregister(struct nf_logger *logger); + +int nf_log_bind_pf(u_int8_t pf, const struct nf_logger *logger); +void nf_log_unbind_pf(u_int8_t pf); /* Calls the registered backend logging function */ void nf_log_packet(u_int8_t pf, diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c index 27a78fbbd92..acc44c69eb6 100644 --- a/net/ipv4/netfilter/ipt_LOG.c +++ b/net/ipv4/netfilter/ipt_LOG.c @@ -464,7 +464,7 @@ static struct xt_target log_tg_reg __read_mostly = { .me = THIS_MODULE, }; -static const struct nf_logger ipt_log_logger ={ +static struct nf_logger ipt_log_logger __read_mostly = { .name = "ipt_LOG", .logfn = &ipt_log_packet, .me = THIS_MODULE, diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index 18a2826b57c..d32cc4bb328 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c @@ -379,7 +379,7 @@ static struct xt_target ulog_tg_reg __read_mostly = { .me = THIS_MODULE, }; -static struct nf_logger ipt_ulog_logger = { +static struct nf_logger ipt_ulog_logger __read_mostly = { .name = "ipt_ULOG", .logfn = ipt_logfn, .me = THIS_MODULE, diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index 37adf5abc51..7018cac4fdd 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c @@ -477,7 +477,7 @@ static struct xt_target log_tg6_reg __read_mostly = { .me = THIS_MODULE, }; -static const struct nf_logger ip6t_logger = { +static struct nf_logger ip6t_logger __read_mostly = { .name = "ip6t_LOG", .logfn = &ip6t_log_packet, .me = THIS_MODULE, diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index fa8ae5d2659..a228b5fbcf7 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c @@ -16,56 +16,60 @@ #define NF_LOG_PREFIXLEN 128 static const struct nf_logger *nf_loggers[NFPROTO_NUMPROTO] __read_mostly; +static struct list_head nf_loggers_l[NFPROTO_NUMPROTO] __read_mostly; static DEFINE_MUTEX(nf_log_mutex); -/* return EBUSY if somebody else is registered, EEXIST if the same logger - * is registred, 0 on success. */ -int nf_log_register(u_int8_t pf, const struct nf_logger *logger) +static struct nf_logger *__find_logger(int pf, const char *str_logger) { - int ret; + struct nf_logger *t; - if (pf >= ARRAY_SIZE(nf_loggers)) - return -EINVAL; - - /* Any setup of logging members must be done before - * substituting pointer. */ - ret = mutex_lock_interruptible(&nf_log_mutex); - if (ret < 0) - return ret; - - if (!nf_loggers[pf]) - rcu_assign_pointer(nf_loggers[pf], logger); - else if (nf_loggers[pf] == logger) - ret = -EEXIST; - else - ret = -EBUSY; + list_for_each_entry(t, &nf_loggers_l[pf], list[pf]) { + if (!strnicmp(str_logger, t->name, strlen(t->name))) + return t; + } - mutex_unlock(&nf_log_mutex); - return ret; + return NULL; } -EXPORT_SYMBOL(nf_log_register); -void nf_log_unregister_pf(u_int8_t pf) +/* return EEXIST if the same logger is registred, 0 on success. */ +int nf_log_register(u_int8_t pf, struct nf_logger *logger) { + const struct nf_logger *llog; + if (pf >= ARRAY_SIZE(nf_loggers)) - return; + return -EINVAL; + mutex_lock(&nf_log_mutex); - rcu_assign_pointer(nf_loggers[pf], NULL); + + if (pf == NFPROTO_UNSPEC) { + int i; + for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) + list_add_tail(&(logger->list[i]), &(nf_loggers_l[i])); + } else { + /* register at end of list to honor first register win */ + list_add_tail(&logger->list[pf], &nf_loggers_l[pf]); + llog = rcu_dereference(nf_loggers[pf]); + if (llog == NULL) + rcu_assign_pointer(nf_loggers[pf], logger); + } + mutex_unlock(&nf_log_mutex); - /* Give time to concurrent readers. */ - synchronize_rcu(); + return 0; } -EXPORT_SYMBOL(nf_log_unregister_pf); +EXPORT_SYMBOL(nf_log_register); -void nf_log_unregister(const struct nf_logger *logger) +void nf_log_unregister(struct nf_logger *logger) { + const struct nf_logger *c_logger; int i; mutex_lock(&nf_log_mutex); for (i = 0; i < ARRAY_SIZE(nf_loggers); i++) { - if (nf_loggers[i] == logger) + c_logger = rcu_dereference(nf_loggers[i]); + if (c_logger == logger) rcu_assign_pointer(nf_loggers[i], NULL); + list_del(&logger->list[i]); } mutex_unlock(&nf_log_mutex); @@ -73,6 +77,27 @@ void nf_log_unregister(const struct nf_logger *logger) } EXPORT_SYMBOL(nf_log_unregister); +int nf_log_bind_pf(u_int8_t pf, const struct nf_logger *logger) +{ + mutex_lock(&nf_log_mutex); + if (__find_logger(pf, logger->name) == NULL) { + mutex_unlock(&nf_log_mutex); + return -ENOENT; + } + rcu_assign_pointer(nf_loggers[pf], logger); + mutex_unlock(&nf_log_mutex); + return 0; +} +EXPORT_SYMBOL(nf_log_bind_pf); + +void nf_log_unbind_pf(u_int8_t pf) +{ + mutex_lock(&nf_log_mutex); + rcu_assign_pointer(nf_loggers[pf], NULL); + mutex_unlock(&nf_log_mutex); +} +EXPORT_SYMBOL(nf_log_unbind_pf); + void nf_log_packet(u_int8_t pf, unsigned int hooknum, const struct sk_buff *skb, @@ -163,10 +188,15 @@ static const struct file_operations nflog_file_ops = { int __init netfilter_log_init(void) { + int i; #ifdef CONFIG_PROC_FS if (!proc_create("nf_log", S_IRUGO, proc_net_netfilter, &nflog_file_ops)) return -1; #endif + + for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) + INIT_LIST_HEAD(&(nf_loggers_l[i])); + return 0; } diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index fa49dc7fe10..3eae3fca29d 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -691,7 +691,7 @@ nfulnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb, return -ENOTSUPP; } -static const struct nf_logger nfulnl_logger = { +static struct nf_logger nfulnl_logger __read_mostly = { .name = "nfnetlink_log", .logfn = &nfulnl_log_packet, .me = THIS_MODULE, @@ -723,9 +723,9 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, /* Commands without queue context */ switch (cmd->command) { case NFULNL_CFG_CMD_PF_BIND: - return nf_log_register(pf, &nfulnl_logger); + return nf_log_bind_pf(pf, &nfulnl_logger); case NFULNL_CFG_CMD_PF_UNBIND: - nf_log_unregister_pf(pf); + nf_log_unbind_pf(pf); return 0; } } @@ -950,17 +950,25 @@ static int __init nfnetlink_log_init(void) goto cleanup_netlink_notifier; } + status = nf_log_register(NFPROTO_UNSPEC, &nfulnl_logger); + if (status < 0) { + printk(KERN_ERR "log: failed to register logger\n"); + goto cleanup_subsys; + } + #ifdef CONFIG_PROC_FS if (!proc_create("nfnetlink_log", 0440, proc_net_netfilter, &nful_file_ops)) - goto cleanup_subsys; + goto cleanup_logger; #endif return status; #ifdef CONFIG_PROC_FS +cleanup_logger: + nf_log_unregister(&nfulnl_logger); +#endif cleanup_subsys: nfnetlink_subsys_unregister(&nfulnl_subsys); -#endif cleanup_netlink_notifier: netlink_unregister_notifier(&nfulnl_rtnl_notifier); return status; -- GitLab From c7a913cd5535554d6f5d5e1f5ef46c4307cf2afc Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Mon, 16 Mar 2009 14:55:27 +0100 Subject: [PATCH 3508/4982] netfilter: print the list of register loggers This patch modifies the proc output to add display of registered loggers. The content of /proc/net/netfilter/nf_log is modified. Instead of displaying a protocol per line with format: proto:logger it now displays: proto:logger (comma_separated_list_of_loggers) NONE is used as keyword if no logger is used. Signed-off-by: Eric Leblond Signed-off-by: Patrick McHardy --- net/netfilter/nf_log.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index a228b5fbcf7..4fcbcc71aa3 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c @@ -154,13 +154,37 @@ static int seq_show(struct seq_file *s, void *v) { loff_t *pos = v; const struct nf_logger *logger; + struct nf_logger *t; + int ret; logger = rcu_dereference(nf_loggers[*pos]); if (!logger) - return seq_printf(s, "%2lld NONE\n", *pos); + ret = seq_printf(s, "%2lld NONE (", *pos); + else + ret = seq_printf(s, "%2lld %s (", *pos, logger->name); + + if (ret < 0) + return ret; + + mutex_lock(&nf_log_mutex); + list_for_each_entry(t, &nf_loggers_l[*pos], list[*pos]) { + ret = seq_printf(s, "%s", t->name); + if (ret < 0) { + mutex_unlock(&nf_log_mutex); + return ret; + } + if (&t->list[*pos] != nf_loggers_l[*pos].prev) { + ret = seq_printf(s, ","); + if (ret < 0) { + mutex_unlock(&nf_log_mutex); + return ret; + } + } + } + mutex_unlock(&nf_log_mutex); - return seq_printf(s, "%2lld %s\n", *pos, logger->name); + return seq_printf(s, ")\n"); } static const struct seq_operations nflog_seq_ops = { -- GitLab From b1e93a68ca41e7e73766f95ba32ca05cf9052e15 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 16 Mar 2009 15:06:42 +0100 Subject: [PATCH 3509/4982] netfilter: conntrack: don't deliver events for racy packets This patch skips the delivery of conntrack events if the packet was drop due to a race condition in the conntrack insertion. Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_conntrack_core.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index c25068e3851..5a449b44ba3 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h @@ -62,7 +62,8 @@ static inline int nf_conntrack_confirm(struct sk_buff *skb) if (ct && ct != &nf_conntrack_untracked) { if (!nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) ret = __nf_conntrack_confirm(skb); - nf_ct_deliver_cached_events(ct); + if (likely(ret == NF_ACCEPT)) + nf_ct_deliver_cached_events(ct); } return ret; } -- GitLab From 10d9e3d99ee8332bb73a3d7f12a8cd8ffab8b136 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Mon, 16 Mar 2009 21:23:35 +0900 Subject: [PATCH 3510/4982] ASoC: twl4030 - Fix build error CC sound/soc/codecs/twl4030.o sound/soc/codecs/twl4030.c:1400: warning: braces around scalar initializer sound/soc/codecs/twl4030.c:1400: warning: (near initialization for 'twl4030_dai.ops') sound/soc/codecs/twl4030.c:1401: error: field name not in record or union initializer sound/soc/codecs/twl4030.c:1401: error: (near initialization for 'twl4030_dai.ops') sound/soc/codecs/twl4030.c:1401: warning: initialization from incompatible pointer type sound/soc/codecs/twl4030.c:1402: error: field name not in record or union initializer sound/soc/codecs/twl4030.c:1402: error: (near initialization for 'twl4030_dai.ops') sound/soc/codecs/twl4030.c:1402: warning: excess elements in scalar initializer sound/soc/codecs/twl4030.c:1402: warning: (near initialization for 'twl4030_dai.ops') sound/soc/codecs/twl4030.c:1403: error: field name not in record or union initializer sound/soc/codecs/twl4030.c:1403: error: (near initialization for 'twl4030_dai.ops') sound/soc/codecs/twl4030.c:1403: warning: excess elements in scalar initializer sound/soc/codecs/twl4030.c:1403: warning: (near initialization for 'twl4030_dai.ops') Signed-off-by: Joonyoung Shim Signed-off-by: Mark Brown --- sound/soc/codecs/twl4030.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 86bb15cc82c..97738e2ece0 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -1383,6 +1383,12 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai, #define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000) #define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE) +static struct snd_soc_dai_ops twl4030_dai_ops = { + .hw_params = twl4030_hw_params, + .set_sysclk = twl4030_set_dai_sysclk, + .set_fmt = twl4030_set_dai_fmt, +}; + struct snd_soc_dai twl4030_dai = { .name = "twl4030", .playback = { @@ -1397,11 +1403,7 @@ struct snd_soc_dai twl4030_dai = { .channels_max = 2, .rates = TWL4030_RATES, .formats = TWL4030_FORMATS,}, - .ops = { - .hw_params = twl4030_hw_params, - .set_sysclk = twl4030_set_dai_sysclk, - .set_fmt = twl4030_set_dai_fmt, - } + .ops = &twl4030_dai_ops, }; EXPORT_SYMBOL_GPL(twl4030_dai); -- GitLab From f2a5d6a2ea2fa24573a8ce7ea7a7a2cce42e3588 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 16 Mar 2009 14:02:07 +0000 Subject: [PATCH 3511/4982] ASoC: Fix some missing dai_ops conversions Signed-off-by: Mark Brown --- sound/soc/s3c24xx/s3c64xx-i2s.c | 8 +++++--- sound/soc/sh/hac.c | 12 ++++++------ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c index 6e1e85dc1ff..33c5de7e255 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s.c +++ b/sound/soc/s3c24xx/s3c64xx-i2s.c @@ -177,6 +177,10 @@ static int s3c64xx_i2s_probe(struct platform_device *pdev, #define S3C64XX_I2S_FMTS \ (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE) +static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops = { + .set_sysclk = s3c64xx_i2s_set_sysclk, +}; + struct snd_soc_dai s3c64xx_i2s_dai = { .name = "s3c64xx-i2s", .id = 0, @@ -193,9 +197,7 @@ struct snd_soc_dai s3c64xx_i2s_dai = { .rates = S3C64XX_I2S_RATES, .formats = S3C64XX_I2S_FMTS, }, - .ops = { - .set_sysclk = s3c64xx_i2s_set_sysclk, - }, + .ops = &s3c64xx_i2s_dai_ops, }; EXPORT_SYMBOL_GPL(s3c64xx_i2s_dai); diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c index eab31838bad..41db75af3c6 100644 --- a/sound/soc/sh/hac.c +++ b/sound/soc/sh/hac.c @@ -267,6 +267,10 @@ static int hac_hw_params(struct snd_pcm_substream *substream, #define AC97_FMTS \ SNDRV_PCM_FMTBIT_S16_LE +static struct snd_soc_dai_ops hac_dai_ops = { + .hw_params = hac_hw_params, +}; + struct snd_soc_dai sh4_hac_dai[] = { { .name = "HAC0", @@ -284,9 +288,7 @@ struct snd_soc_dai sh4_hac_dai[] = { .channels_min = 2, .channels_max = 2, }, - .ops = { - .hw_params = hac_hw_params, - }, + .ops = &hac_dai_ops, }, #ifdef CONFIG_CPU_SUBTYPE_SH7760 { @@ -305,9 +307,7 @@ struct snd_soc_dai sh4_hac_dai[] = { .channels_min = 2, .channels_max = 2, }, - .ops = { - .hw_params = hac_hw_params, - }, + .ops = &hac_dai_ops, }, #endif -- GitLab From 852fd9e50f62b4ea7afe26eee0710464de4801b8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 16 Mar 2009 14:13:12 +0000 Subject: [PATCH 3512/4982] ASoC: Each PXA AC97 DAI needs a separate ops Signed-off-by: Mark Brown --- sound/soc/pxa/pxa2xx-ac97.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index cf809049272..01c21c6cdbb 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c @@ -164,10 +164,18 @@ static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream, SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ SNDRV_PCM_RATE_48000) -static struct snd_soc_dai_ops pxa_ac97_dai_ops = { +static struct snd_soc_dai_ops pxa_ac97_hifi_dai_ops = { .hw_params = pxa2xx_ac97_hw_params, }; +static struct snd_soc_dai_ops pxa_ac97_aux_dai_ops = { + .hw_params = pxa2xx_ac97_hw_aux_params, +}; + +static struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = { + .hw_params = pxa2xx_ac97_hw_mic_params, +}; + /* * There is only 1 physical AC97 interface for pxa2xx, but it * has extra fifo's that can be used for aux DACs and ADCs. @@ -193,7 +201,7 @@ struct snd_soc_dai pxa_ac97_dai[] = { .channels_max = 2, .rates = PXA2XX_AC97_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = &pxa_ac97_dai_ops, + .ops = &pxa_ac97_hifi_dai_ops, }, { .name = "pxa2xx-ac97-aux", @@ -211,7 +219,7 @@ struct snd_soc_dai pxa_ac97_dai[] = { .channels_max = 1, .rates = PXA2XX_AC97_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = &pxa_ac97_dai_ops, + .ops = &pxa_ac97_aux_dai_ops, }, { .name = "pxa2xx-ac97-mic", @@ -223,7 +231,7 @@ struct snd_soc_dai pxa_ac97_dai[] = { .channels_max = 1, .rates = PXA2XX_AC97_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = &pxa_ac97_dai_ops, + .ops = &pxa_ac97_mic_dai_ops, }, }; -- GitLab From 9d2493f88f846b391a15a736efc7f4b97d6c4046 Mon Sep 17 00:00:00 2001 From: Christoph Paasch Date: Mon, 16 Mar 2009 15:15:35 +0100 Subject: [PATCH 3513/4982] netfilter: remove IPvX specific parts from nf_conntrack_l4proto.h Moving the structure definitions to the corresponding IPvX specific header files. Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_conntrack_l4proto.h | 5 +---- net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 1 + net/netfilter/nf_conntrack_proto_tcp.c | 2 ++ net/netfilter/nf_conntrack_proto_udp.c | 2 ++ 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h index debdaf75cec..16ab604659e 100644 --- a/include/net/netfilter/nf_conntrack_l4proto.h +++ b/include/net/netfilter/nf_conntrack_l4proto.h @@ -90,10 +90,7 @@ struct nf_conntrack_l4proto struct module *me; }; -/* Existing built-in protocols */ -extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6; -extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4; -extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6; +/* Existing built-in generic protocol */ extern struct nf_conntrack_l4proto nf_conntrack_l4proto_generic; #define MAX_NF_CT_PROTO 256 diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 727b9530448..e6852f61721 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -26,6 +26,7 @@ #include #include #include +#include static bool ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, struct nf_conntrack_tuple *tuple) diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index a1edb9c1ade..7d3944f02ea 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include /* Protects ct->proto.tcp */ static DEFINE_RWLOCK(tcp_lock); diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index 2b8b1f579f9..d4021179e24 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include static unsigned int nf_ct_udp_timeout __read_mostly = 30*HZ; static unsigned int nf_ct_udp_timeout_stream __read_mostly = 180*HZ; -- GitLab From 67c0d57930ff9a24c6c34abee1b01f7716a9b0e2 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 16 Mar 2009 15:17:23 +0100 Subject: [PATCH 3514/4982] netfilter: Kconfig spelling fixes (trivial) Signed-off-by: Stephen Hemminger Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index f8d6180938d..1833bdbf980 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -31,7 +31,7 @@ config NF_CONNTRACK_PROC_COMPAT default y help This option enables /proc and sysctl compatibility with the old - layer 3 dependant connection tracking. This is needed to keep + layer 3 dependent connection tracking. This is needed to keep old programs that have not been adapted to the new names working. If unsure, say Y. @@ -99,7 +99,7 @@ config IP_NF_MATCH_TTL ---help--- This is a backwards-compat option for the user's convenience (e.g. when running oldconfig). It selects - COFNIG_NETFILTER_XT_MATCH_HL. + CONFIG_NETFILTER_XT_MATCH_HL. # `filter', generic and specific targets config IP_NF_FILTER @@ -329,7 +329,7 @@ config IP_NF_TARGET_TTL ---help--- This is a backwards-compat option for the user's convenience (e.g. when running oldconfig). It selects - COFNIG_NETFILTER_XT_TARGET_HL. + CONFIG_NETFILTER_XT_TARGET_HL. # raw + specific targets config IP_NF_RAW -- GitLab From 1db7a748dfd50d7615913730763c024444900030 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 16 Mar 2009 15:18:50 +0100 Subject: [PATCH 3515/4982] netfilter: conntrack: increase drop stats if sequence adjustment fails This patch increases the statistics of packets drop if the sequence adjustment fails in ipv4_confirm(). Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 4beb04fac58..8b681f24e27 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -120,8 +120,10 @@ static unsigned int ipv4_confirm(unsigned int hooknum, typeof(nf_nat_seq_adjust_hook) seq_adjust; seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook); - if (!seq_adjust || !seq_adjust(skb, ct, ctinfo)) + if (!seq_adjust || !seq_adjust(skb, ct, ctinfo)) { + NF_CT_STAT_INC_ATOMIC(nf_ct_net(ct), drop); return NF_DROP; + } } out: /* We've seen it coming out the other side: confirm it */ -- GitLab From b8dbed0f095263b9ced5bd2e6d54743a7fa13f1b Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 16 Mar 2009 14:56:58 +0100 Subject: [PATCH 3516/4982] ALSA: snd-hda-intel: Fix ALC662/ALC663 Beep Amplifier Index ALC662/663 codecs have Beep Amplifier Index 0x04 not 0x05 in 0x0b NID. Confirmed by testing on real hardware. Signed-off-by: Jaroslav Kysela Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b794cba494c..672103d84ff 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -16951,7 +16951,7 @@ static int patch_alc662(struct hda_codec *codec) if (!spec->cap_mixer) set_capture_mixer(spec); - set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); + set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); spec->vmaster_nid = 0x02; -- GitLab From 7ec4749675bf33ea639bbcca8a5365ccc5091a6a Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 16 Mar 2009 15:25:46 +0100 Subject: [PATCH 3517/4982] netfilter: ctnetlink: cleanup master conntrack assignation This patch moves the assignation of the master conntrack to ctnetlink_create_conntrack(), which is where it really belongs. This patch is a cleanup. Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_netlink.c | 49 ++++++++++++---------------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index cb78aa00399..cca22d55382 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1128,9 +1128,9 @@ static int ctnetlink_create_conntrack(struct nlattr *cda[], struct nf_conntrack_tuple *otuple, struct nf_conntrack_tuple *rtuple, - struct nf_conn *master_ct, u32 pid, - int report) + int report, + u8 u3) { struct nf_conn *ct; int err = -EINVAL; @@ -1241,7 +1241,22 @@ ctnetlink_create_conntrack(struct nlattr *cda[], #endif /* setup master conntrack: this is a confirmed expectation */ - if (master_ct) { + if (cda[CTA_TUPLE_MASTER]) { + struct nf_conntrack_tuple master; + struct nf_conntrack_tuple_hash *master_h; + struct nf_conn *master_ct; + + err = ctnetlink_parse_tuple(cda, &master, CTA_TUPLE_MASTER, u3); + if (err < 0) + goto err; + + master_h = __nf_conntrack_find(&init_net, &master); + if (master_h == NULL) { + err = -ENOENT; + goto err; + } + master_ct = nf_ct_tuplehash_to_ctrack(master_h); + nf_conntrack_get(&master_ct->ct_general); __set_bit(IPS_EXPECTED_BIT, &ct->status); ct->master = master_ct; } @@ -1289,39 +1304,15 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, h = __nf_conntrack_find(&init_net, &rtuple); if (h == NULL) { - struct nf_conntrack_tuple master; - struct nf_conntrack_tuple_hash *master_h = NULL; - struct nf_conn *master_ct = NULL; - - if (cda[CTA_TUPLE_MASTER]) { - err = ctnetlink_parse_tuple(cda, - &master, - CTA_TUPLE_MASTER, - u3); - if (err < 0) - goto out_unlock; - - master_h = __nf_conntrack_find(&init_net, &master); - if (master_h == NULL) { - err = -ENOENT; - goto out_unlock; - } - master_ct = nf_ct_tuplehash_to_ctrack(master_h); - nf_conntrack_get(&master_ct->ct_general); - } - err = -ENOENT; if (nlh->nlmsg_flags & NLM_F_CREATE) err = ctnetlink_create_conntrack(cda, &otuple, &rtuple, - master_ct, NETLINK_CB(skb).pid, - nlmsg_report(nlh)); + nlmsg_report(nlh), + u3); spin_unlock_bh(&nf_conntrack_lock); - if (err < 0 && master_ct) - nf_ct_put(master_ct); - return err; } /* implicit 'else' */ -- GitLab From b9591448e5160ccd353d8547ade018cfdf2b3e09 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 16 Mar 2009 15:25:00 +0100 Subject: [PATCH 3518/4982] ALSA: hda - Fix ALC662 beep again The previous commit breaks the (digital-) beep on ALC662. ALC662 has the connection index 0x05 while ALC662 and ALC272 have the index 0x04 for the beep widget. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 672103d84ff..5ad0f8d72dd 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -16951,7 +16951,10 @@ static int patch_alc662(struct hda_codec *codec) if (!spec->cap_mixer) set_capture_mixer(spec); - set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); + if (codec->vendor_id == 0x10ec0662) + set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); + else + set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); spec->vmaster_nid = 0x02; -- GitLab From e098360f159b3358f085543eb6dc2eb500d6667c Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 16 Mar 2009 15:27:22 +0100 Subject: [PATCH 3519/4982] netfilter: ctnetlink: cleanup conntrack update preliminary checkings This patch moves the preliminary checkings that must be fulfilled to update a conntrack, which are the following: * NAT manglings cannot be updated * Changing the master conntrack is not allowed. This patch is a cleanup. Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_netlink.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index cca22d55382..b67db695d83 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1062,6 +1062,10 @@ ctnetlink_change_conntrack(struct nf_conn *ct, struct nlattr *cda[]) { int err; + /* only allow NAT changes and master assignation for new conntracks */ + if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST] || cda[CTA_TUPLE_MASTER]) + return -EOPNOTSUPP; + if (cda[CTA_HELP]) { err = ctnetlink_change_helper(ct, cda); if (err < 0) @@ -1323,17 +1327,6 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, if (!(nlh->nlmsg_flags & NLM_F_EXCL)) { struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); - /* we only allow nat config for new conntracks */ - if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) { - err = -EOPNOTSUPP; - goto out_unlock; - } - /* can't link an existing conntrack to a master */ - if (cda[CTA_TUPLE_MASTER]) { - err = -EOPNOTSUPP; - goto out_unlock; - } - err = ctnetlink_change_conntrack(ct, cda); if (err == 0) { nf_conntrack_get(&ct->ct_general); -- GitLab From f0a3c0869f3b0ef93d9df044e9a41e40086d4c97 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 16 Mar 2009 15:28:09 +0100 Subject: [PATCH 3520/4982] netfilter: ctnetlink: move event reporting for new entries outside the lock This patch moves the event reporting outside the lock section. With this patch, the creation and update of entries is homogeneous from the event reporting perspective. Moreover, as the event reporting is done outside the lock section, the netlink broadcast delivery can benefit of the yield() call under congestion. Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_netlink.c | 41 ++++++++++++++++------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index b67db695d83..9fb7cf7504f 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1128,12 +1128,10 @@ ctnetlink_event_report(struct nf_conn *ct, u32 pid, int report) report); } -static int +static struct nf_conn * ctnetlink_create_conntrack(struct nlattr *cda[], struct nf_conntrack_tuple *otuple, struct nf_conntrack_tuple *rtuple, - u32 pid, - int report, u8 u3) { struct nf_conn *ct; @@ -1142,7 +1140,7 @@ ctnetlink_create_conntrack(struct nlattr *cda[], ct = nf_conntrack_alloc(&init_net, otuple, rtuple, GFP_ATOMIC); if (IS_ERR(ct)) - return -ENOMEM; + return ERR_PTR(-ENOMEM); if (!cda[CTA_TIMEOUT]) goto err; @@ -1265,18 +1263,14 @@ ctnetlink_create_conntrack(struct nlattr *cda[], ct->master = master_ct; } - nf_conntrack_get(&ct->ct_general); add_timer(&ct->timeout); nf_conntrack_hash_insert(ct); rcu_read_unlock(); - ctnetlink_event_report(ct, pid, report); - nf_ct_put(ct); - - return 0; + return ct; err: nf_conntrack_free(ct); - return err; + return ERR_PTR(err); } static int @@ -1309,14 +1303,25 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, if (h == NULL) { err = -ENOENT; - if (nlh->nlmsg_flags & NLM_F_CREATE) - err = ctnetlink_create_conntrack(cda, - &otuple, - &rtuple, - NETLINK_CB(skb).pid, - nlmsg_report(nlh), - u3); - spin_unlock_bh(&nf_conntrack_lock); + if (nlh->nlmsg_flags & NLM_F_CREATE) { + struct nf_conn *ct; + + ct = ctnetlink_create_conntrack(cda, &otuple, + &rtuple, u3); + if (IS_ERR(ct)) { + err = PTR_ERR(ct); + goto out_unlock; + } + err = 0; + nf_conntrack_get(&ct->ct_general); + spin_unlock_bh(&nf_conntrack_lock); + ctnetlink_event_report(ct, + NETLINK_CB(skb).pid, + nlmsg_report(nlh)); + nf_ct_put(ct); + } else + spin_unlock_bh(&nf_conntrack_lock); + return err; } /* implicit 'else' */ -- GitLab From 26c3b6780618f09abb5f7e03b09b13dbb8e8aa24 Mon Sep 17 00:00:00 2001 From: Scott James Remnant Date: Mon, 16 Mar 2009 15:30:14 +0100 Subject: [PATCH 3521/4982] netfilter: auto-load ip6_queue module when socket opened The ip6_queue module is missing the net-pf-16-proto-13 alias that would cause it to be auto-loaded when a socket of that type is opened. This patch adds the alias. Signed-off-by: Scott James Remnant Signed-off-by: Tim Gardner Signed-off-by: Patrick McHardy --- net/ipv6/netfilter/ip6_queue.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 5859c046cbc..b693f841aeb 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -643,6 +643,7 @@ static void __exit ip6_queue_fini(void) MODULE_DESCRIPTION("IPv6 packet queue handler"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_IP6_FW); module_init(ip6_queue_init); module_exit(ip6_queue_fini); -- GitLab From 95ba434f898c3cb5c7457dce265bf0ab72ba8ce9 Mon Sep 17 00:00:00 2001 From: Scott James Remnant Date: Mon, 16 Mar 2009 15:31:10 +0100 Subject: [PATCH 3522/4982] netfilter: auto-load ip_queue module when socket opened The ip_queue module is missing the net-pf-16-proto-3 alias that would causae it to be auto-loaded when a socket of that type is opened. This patch adds the alias. Signed-off-by: Scott James Remnant Signed-off-by: Tim Gardner Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/ip_queue.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 432ce9d1c11..5f22c91c6e1 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -640,6 +641,7 @@ static void __exit ip_queue_fini(void) MODULE_DESCRIPTION("IPv4 packet queue handler"); MODULE_AUTHOR("James Morris "); MODULE_LICENSE("GPL"); +MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_FIREWALL); module_init(ip_queue_init); module_exit(ip_queue_fini); -- GitLab From 684999149002dd046269666a390458e0acb38280 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 6 Feb 2009 13:52:43 -0700 Subject: [PATCH 3523/4982] Rename struct file->f_ep_lock This lock moves out of the CONFIG_EPOLL ifdef and becomes f_lock. For now, epoll remains the only user, but a future patch will use it to protect f_flags as well. Cc: Davide Libenzi Reviewed-by: Christoph Hellwig Signed-off-by: Jonathan Corbet --- fs/eventpoll.c | 12 +++++++----- fs/file_table.c | 1 + include/linux/eventpoll.h | 1 - include/linux/fs.h | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 011b9b8c90c..c5c424f23fd 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -417,10 +417,10 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi) ep_unregister_pollwait(ep, epi); /* Remove the current item from the list of epoll hooks */ - spin_lock(&file->f_ep_lock); + spin_lock(&file->f_lock); if (ep_is_linked(&epi->fllink)) list_del_init(&epi->fllink); - spin_unlock(&file->f_ep_lock); + spin_unlock(&file->f_lock); rb_erase(&epi->rbn, &ep->rbr); @@ -538,7 +538,7 @@ void eventpoll_release_file(struct file *file) struct epitem *epi; /* - * We don't want to get "file->f_ep_lock" because it is not + * We don't want to get "file->f_lock" because it is not * necessary. It is not necessary because we're in the "struct file" * cleanup path, and this means that noone is using this file anymore. * So, for example, epoll_ctl() cannot hit here sicne if we reach this @@ -547,6 +547,8 @@ void eventpoll_release_file(struct file *file) * will correctly serialize the operation. We do need to acquire * "ep->mtx" after "epmutex" because ep_remove() requires it when called * from anywhere but ep_free(). + * + * Besides, ep_remove() acquires the lock, so we can't hold it here. */ mutex_lock(&epmutex); @@ -785,9 +787,9 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, goto error_unregister; /* Add the current item to the list of active epoll hook for this file */ - spin_lock(&tfile->f_ep_lock); + spin_lock(&tfile->f_lock); list_add_tail(&epi->fllink, &tfile->f_ep_links); - spin_unlock(&tfile->f_ep_lock); + spin_unlock(&tfile->f_lock); /* * Add the current item to the RB tree. All RB tree operations are diff --git a/fs/file_table.c b/fs/file_table.c index bbeeac6efa1..aa1e1805028 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -127,6 +127,7 @@ struct file *get_empty_filp(void) atomic_long_set(&f->f_count, 1); rwlock_init(&f->f_owner.lock); f->f_cred = get_cred(cred); + spin_lock_init(&f->f_lock); eventpoll_init_file(f); /* f->f_version: 0 */ return f; diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h index f1e1d3c4712..f6856a5a1d4 100644 --- a/include/linux/eventpoll.h +++ b/include/linux/eventpoll.h @@ -61,7 +61,6 @@ struct file; static inline void eventpoll_init_file(struct file *file) { INIT_LIST_HEAD(&file->f_ep_links); - spin_lock_init(&file->f_ep_lock); } diff --git a/include/linux/fs.h b/include/linux/fs.h index 92734c0012e..2011600d12c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -848,6 +848,7 @@ struct file { #define f_dentry f_path.dentry #define f_vfsmnt f_path.mnt const struct file_operations *f_op; + spinlock_t f_lock; /* f_ep_links */ atomic_long_t f_count; unsigned int f_flags; fmode_t f_mode; @@ -866,7 +867,6 @@ struct file { #ifdef CONFIG_EPOLL /* Used by fs/eventpoll.c to link all the hooks to this file */ struct list_head f_ep_links; - spinlock_t f_ep_lock; #endif /* #ifdef CONFIG_EPOLL */ struct address_space *f_mapping; #ifdef CONFIG_DEBUG_WRITECOUNT -- GitLab From db1dd4d376134eba0e08af523b61cc566a4ea1cd Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 6 Feb 2009 15:25:24 -0700 Subject: [PATCH 3524/4982] Use f_lock to protect f_flags Traditionally, changes to struct file->f_flags have been done under BKL protection, or with no protection at all. This patch causes all f_flags changes after file open/creation time to be done under protection of f_lock. This allows the removal of some BKL usage and fixes a number of longstanding (if microscopic) races. Reviewed-by: Christoph Hellwig Cc: Al Viro Signed-off-by: Jonathan Corbet --- drivers/char/tty_io.c | 5 ++--- drivers/usb/gadget/file_storage.c | 7 ++++++- fs/fcntl.c | 2 ++ fs/ioctl.c | 7 ++++--- fs/nfsd/vfs.c | 5 ++++- include/linux/fs.h | 2 +- ipc/mqueue.c | 2 ++ sound/core/oss/pcm_oss.c | 2 ++ sound/oss/au1550_ac97.c | 2 ++ sound/oss/audio.c | 2 ++ sound/oss/sh_dac_audio.c | 2 ++ sound/oss/swarm_cs4297a.c | 2 ++ sound/oss/vwsnd.c | 2 ++ 13 files changed, 33 insertions(+), 9 deletions(-) diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index bc84e125c6b..224f271d8cb 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -2162,13 +2162,12 @@ static int fionbio(struct file *file, int __user *p) if (get_user(nonblock, p)) return -EFAULT; - /* file->f_flags is still BKL protected in the fs layer - vomit */ - lock_kernel(); + spin_lock(&file->f_lock); if (nonblock) file->f_flags |= O_NONBLOCK; else file->f_flags &= ~O_NONBLOCK; - unlock_kernel(); + spin_unlock(&file->f_lock); return 0; } diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 1ab9dac7e12..33bb76cef33 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -1711,7 +1711,9 @@ static int do_write(struct fsg_dev *fsg) curlun->sense_data = SS_WRITE_PROTECTED; return -EINVAL; } + spin_lock(&curlun->filp->f_lock); curlun->filp->f_flags &= ~O_SYNC; // Default is not to wait + spin_unlock(&curlun->filp->f_lock); /* Get the starting Logical Block Address and check that it's * not too big */ @@ -1728,8 +1730,11 @@ static int do_write(struct fsg_dev *fsg) curlun->sense_data = SS_INVALID_FIELD_IN_CDB; return -EINVAL; } - if (fsg->cmnd[1] & 0x08) // FUA + if (fsg->cmnd[1] & 0x08) { // FUA + spin_lock(&curlun->filp->f_lock); curlun->filp->f_flags |= O_SYNC; + spin_unlock(&curlun->filp->f_lock); + } } if (lba >= curlun->num_sectors) { curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; diff --git a/fs/fcntl.c b/fs/fcntl.c index bd215cc791d..04df8570a2d 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -189,7 +189,9 @@ static int setfl(int fd, struct file * filp, unsigned long arg) } } + spin_lock(&filp->f_lock); filp->f_flags = (arg & SETFL_MASK) | (filp->f_flags & ~SETFL_MASK); + spin_unlock(&filp->f_lock); out: unlock_kernel(); return error; diff --git a/fs/ioctl.c b/fs/ioctl.c index 240ec63984c..421aab465da 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -404,10 +404,12 @@ static int ioctl_fionbio(struct file *filp, int __user *argp) if (O_NONBLOCK != O_NDELAY) flag |= O_NDELAY; #endif + spin_lock(&filp->f_lock); if (on) filp->f_flags |= flag; else filp->f_flags &= ~flag; + spin_unlock(&filp->f_lock); return error; } @@ -432,10 +434,12 @@ static int ioctl_fioasync(unsigned int fd, struct file *filp, if (error) return error; + spin_lock(&filp->f_lock); if (on) filp->f_flags |= FASYNC; else filp->f_flags &= ~FASYNC; + spin_unlock(&filp->f_lock); return error; } @@ -499,10 +503,7 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, break; case FIONBIO: - /* BKL needed to avoid races tweaking f_flags */ - lock_kernel(); error = ioctl_fionbio(filp, argp); - unlock_kernel(); break; case FIOASYNC: diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 6e50aaa56ca..c165a6403df 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -998,8 +998,11 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, if (!EX_ISSYNC(exp)) stable = 0; - if (stable && !EX_WGATHER(exp)) + if (stable && !EX_WGATHER(exp)) { + spin_lock(&file->f_lock); file->f_flags |= O_SYNC; + spin_unlock(&file->f_lock); + } /* Write the data. */ oldfs = get_fs(); set_fs(KERNEL_DS); diff --git a/include/linux/fs.h b/include/linux/fs.h index 2011600d12c..7428c6d35e6 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -848,7 +848,7 @@ struct file { #define f_dentry f_path.dentry #define f_vfsmnt f_path.mnt const struct file_operations *f_op; - spinlock_t f_lock; /* f_ep_links */ + spinlock_t f_lock; /* f_ep_links, f_flags */ atomic_long_t f_count; unsigned int f_flags; fmode_t f_mode; diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 54b4077fed7..a8ddadbc745 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -1156,10 +1156,12 @@ SYSCALL_DEFINE3(mq_getsetattr, mqd_t, mqdes, omqstat.mq_flags = filp->f_flags & O_NONBLOCK; if (u_mqstat) { audit_mq_getsetattr(mqdes, &mqstat); + spin_lock(&filp->f_lock); if (mqstat.mq_flags & O_NONBLOCK) filp->f_flags |= O_NONBLOCK; else filp->f_flags &= ~O_NONBLOCK; + spin_unlock(&filp->f_lock); inode->i_atime = inode->i_ctime = CURRENT_TIME; } diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 0a1798eafb0..d4460f18e76 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -1895,7 +1895,9 @@ static int snd_pcm_oss_set_fragment(struct snd_pcm_oss_file *pcm_oss_file, unsig static int snd_pcm_oss_nonblock(struct file * file) { + spin_lock(&file->f_lock); file->f_flags |= O_NONBLOCK; + spin_unlock(&file->f_lock); return 0; } diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c index 81e1f443d09..4191acccbcd 100644 --- a/sound/oss/au1550_ac97.c +++ b/sound/oss/au1550_ac97.c @@ -1627,7 +1627,9 @@ au1550_ioctl(struct inode *inode, struct file *file, unsigned int cmd, sizeof(abinfo)) ? -EFAULT : 0; case SNDCTL_DSP_NONBLOCK: + spin_lock(&file->f_lock); file->f_flags |= O_NONBLOCK; + spin_unlock(&file->f_lock); return 0; case SNDCTL_DSP_GETODELAY: diff --git a/sound/oss/audio.c b/sound/oss/audio.c index 89bd27a5e86..b69c05b7ea7 100644 --- a/sound/oss/audio.c +++ b/sound/oss/audio.c @@ -433,7 +433,9 @@ int audio_ioctl(int dev, struct file *file, unsigned int cmd, void __user *arg) return dma_ioctl(dev, cmd, arg); case SNDCTL_DSP_NONBLOCK: + spin_lock(&file->f_lock); file->f_flags |= O_NONBLOCK; + spin_unlock(&file->f_lock); return 0; case SNDCTL_DSP_GETCAPS: diff --git a/sound/oss/sh_dac_audio.c b/sound/oss/sh_dac_audio.c index e5d42399491..78cfb66e4c5 100644 --- a/sound/oss/sh_dac_audio.c +++ b/sound/oss/sh_dac_audio.c @@ -135,7 +135,9 @@ static int dac_audio_ioctl(struct inode *inode, struct file *file, return put_user(AFMT_U8, (int *)arg); case SNDCTL_DSP_NONBLOCK: + spin_lock(&file->f_lock); file->f_flags |= O_NONBLOCK; + spin_unlock(&file->f_lock); return 0; case SNDCTL_DSP_GETCAPS: diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c index 41562ecde5b..1edab7b4ea8 100644 --- a/sound/oss/swarm_cs4297a.c +++ b/sound/oss/swarm_cs4297a.c @@ -2200,7 +2200,9 @@ static int cs4297a_ioctl(struct inode *inode, struct file *file, sizeof(abinfo)) ? -EFAULT : 0; case SNDCTL_DSP_NONBLOCK: + spin_lock(&file->f_lock); file->f_flags |= O_NONBLOCK; + spin_unlock(&file->f_lock); return 0; case SNDCTL_DSP_GETODELAY: diff --git a/sound/oss/vwsnd.c b/sound/oss/vwsnd.c index 78b8acc7c3b..187f72750e8 100644 --- a/sound/oss/vwsnd.c +++ b/sound/oss/vwsnd.c @@ -2673,7 +2673,9 @@ static int vwsnd_audio_do_ioctl(struct inode *inode, case SNDCTL_DSP_NONBLOCK: /* _SIO ('P',14) */ DBGX("SNDCTL_DSP_NONBLOCK\n"); + spin_lock(&file->f_lock); file->f_flags |= O_NONBLOCK; + spin_unlock(&file->f_lock); return 0; case SNDCTL_DSP_RESET: /* _SIO ('P', 0) */ -- GitLab From 76398425bb06b07cc3a3b1ce169c67dc9d6874ed Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Sun, 1 Feb 2009 14:26:59 -0700 Subject: [PATCH 3525/4982] Move FASYNC bit handling to f_op->fasync() Removing the BKL from FASYNC handling ran into the challenge of keeping the setting of the FASYNC bit in filp->f_flags atomic with regard to calls to the underlying fasync() function. Andi Kleen suggested moving the handling of that bit into fasync(); this patch does exactly that. As a result, we have a couple of internal API changes: fasync() must now manage the FASYNC bit, and it will be called without the BKL held. As it happens, every fasync() implementation in the kernel with one exception calls fasync_helper(). So, if we make fasync_helper() set the FASYNC bit, we can avoid making any changes to the other fasync() functions - as long as those functions, themselves, have proper locking. Most fasync() implementations do nothing but call fasync_helper() - which has its own lock - so they are easily verified as correct. The BKL had already been pushed down into the rest. The networking code has its own version of fasync_helper(), so that code has been augmented with explicit FASYNC bit handling. Cc: Al Viro Cc: David Miller Reviewed-by: Christoph Hellwig Signed-off-by: Jonathan Corbet --- Documentation/filesystems/Locking | 7 +++++-- fs/fcntl.c | 29 ++++++++++++++++------------- fs/ioctl.c | 13 +------------ net/socket.c | 7 +++++++ 4 files changed, 29 insertions(+), 27 deletions(-) diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index ec6a9392a17..4e78ce67784 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -437,8 +437,11 @@ grab BKL for cases when we close a file that had been opened r/w, but that can and should be done using the internal locking with smaller critical areas). Current worst offender is ext2_get_block()... -->fasync() is a mess. This area needs a big cleanup and that will probably -affect locking. +->fasync() is called without BKL protection, and is responsible for +maintaining the FASYNC bit in filp->f_flags. Most instances call +fasync_helper(), which does that maintenance, so it's not normally +something one needs to worry about. Return values > 0 will be mapped to +zero in the VFS layer. ->readdir() and ->ioctl() on directories must be changed. Ideally we would move ->readdir() to inode_operations and use a separate method for directory diff --git a/fs/fcntl.c b/fs/fcntl.c index 04df8570a2d..431bb645927 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -141,7 +141,7 @@ SYSCALL_DEFINE1(dup, unsigned int, fildes) return ret; } -#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC | O_DIRECT | O_NOATIME) +#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME) static int setfl(int fd, struct file * filp, unsigned long arg) { @@ -177,23 +177,19 @@ static int setfl(int fd, struct file * filp, unsigned long arg) return error; /* - * We still need a lock here for now to keep multiple FASYNC calls - * from racing with each other. + * ->fasync() is responsible for setting the FASYNC bit. */ - lock_kernel(); - if ((arg ^ filp->f_flags) & FASYNC) { - if (filp->f_op && filp->f_op->fasync) { - error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0); - if (error < 0) - goto out; - } + if (((arg ^ filp->f_flags) & FASYNC) && filp->f_op && + filp->f_op->fasync) { + error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0); + if (error < 0) + goto out; } - spin_lock(&filp->f_lock); filp->f_flags = (arg & SETFL_MASK) | (filp->f_flags & ~SETFL_MASK); spin_unlock(&filp->f_lock); + out: - unlock_kernel(); return error; } @@ -518,7 +514,7 @@ static DEFINE_RWLOCK(fasync_lock); static struct kmem_cache *fasync_cache __read_mostly; /* - * fasync_helper() is used by some character device drivers (mainly mice) + * fasync_helper() is used by almost all character device drivers * to set up the fasync queue. It returns negative on error, 0 if it did * no changes and positive if it added/deleted the entry. */ @@ -557,6 +553,13 @@ int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fap result = 1; } out: + /* Fix up FASYNC bit while still holding fasync_lock */ + spin_lock(&filp->f_lock); + if (on) + filp->f_flags |= FASYNC; + else + filp->f_flags &= ~FASYNC; + spin_unlock(&filp->f_lock); write_unlock_irq(&fasync_lock); return result; } diff --git a/fs/ioctl.c b/fs/ioctl.c index 421aab465da..e8e89edba57 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -427,19 +427,11 @@ static int ioctl_fioasync(unsigned int fd, struct file *filp, /* Did FASYNC state change ? */ if ((flag ^ filp->f_flags) & FASYNC) { if (filp->f_op && filp->f_op->fasync) + /* fasync() adjusts filp->f_flags */ error = filp->f_op->fasync(fd, filp, on); else error = -ENOTTY; } - if (error) - return error; - - spin_lock(&filp->f_lock); - if (on) - filp->f_flags |= FASYNC; - else - filp->f_flags &= ~FASYNC; - spin_unlock(&filp->f_lock); return error; } @@ -507,10 +499,7 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, break; case FIOASYNC: - /* BKL needed to avoid races tweaking f_flags */ - lock_kernel(); error = ioctl_fioasync(fd, filp, argp); - unlock_kernel(); break; case FIOQSIZE: diff --git a/net/socket.c b/net/socket.c index 35dd7371752..0f75746ab06 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1030,6 +1030,13 @@ static int sock_fasync(int fd, struct file *filp, int on) lock_sock(sk); + spin_lock(&filp->f_lock); + if (on) + filp->f_flags |= FASYNC; + else + filp->f_flags &= ~FASYNC; + spin_unlock(&filp->f_lock); + prev = &(sock->fasync_list); for (fa = *prev; fa != NULL; prev = &fa->fa_next, fa = *prev) -- GitLab From 60aa49243d09afc873f082567d2e3c16634ced84 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Sun, 1 Feb 2009 14:52:56 -0700 Subject: [PATCH 3526/4982] Rationalize fasync return values Most fasync implementations do something like: return fasync_helper(...); But fasync_helper() will return a positive value at times - a feature used in at least one place. Thus, a number of other drivers do: err = fasync_helper(...); if (err < 0) return err; return 0; In the interests of consistency and more concise code, it makes sense to map positive return values onto zero where ->fasync() is called. Cc: Al Viro Signed-off-by: Jonathan Corbet --- drivers/char/sonypi.c | 7 +------ drivers/gpu/drm/drm_fops.c | 6 +----- drivers/hid/usbhid/hiddev.c | 5 +---- drivers/ieee1394/dv1394.c | 6 +----- drivers/input/evdev.c | 5 +---- drivers/input/joydev.c | 5 +---- drivers/input/mousedev.c | 5 +---- drivers/input/serio/serio_raw.c | 4 +--- drivers/net/wan/cosa.c | 4 ++-- drivers/platform/x86/sony-laptop.c | 7 +------ drivers/scsi/sg.c | 4 +--- fs/fcntl.c | 2 ++ fs/ioctl.c | 2 +- fs/pipe.c | 16 +++------------- sound/core/control.c | 7 ++----- sound/core/pcm_native.c | 4 +--- sound/core/timer.c | 6 +----- 17 files changed, 22 insertions(+), 73 deletions(-) diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index f4374437a03..fd3dced9777 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -888,12 +888,7 @@ found: static int sonypi_misc_fasync(int fd, struct file *filp, int on) { - int retval; - - retval = fasync_helper(fd, filp, on, &sonypi_device.fifo_async); - if (retval < 0) - return retval; - return 0; + return fasync_helper(fd, filp, on, &sonypi_device.fifo_async); } static int sonypi_misc_release(struct inode *inode, struct file *file) diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index f52663ebe01..e13cb62bbae 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -337,14 +337,10 @@ int drm_fasync(int fd, struct file *filp, int on) { struct drm_file *priv = filp->private_data; struct drm_device *dev = priv->minor->dev; - int retcode; DRM_DEBUG("fd = %d, device = 0x%lx\n", fd, (long)old_encode_dev(priv->minor->device)); - retcode = fasync_helper(fd, filp, on, &dev->buf_async); - if (retcode < 0) - return retcode; - return 0; + return fasync_helper(fd, filp, on, &dev->buf_async); } EXPORT_SYMBOL(drm_fasync); diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 4940e4d70c2..3a7b4fe192a 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -227,12 +227,9 @@ void hiddev_report_event(struct hid_device *hid, struct hid_report *report) */ static int hiddev_fasync(int fd, struct file *file, int on) { - int retval; struct hiddev_list *list = file->private_data; - retval = fasync_helper(fd, file, on, &list->fasync); - - return retval < 0 ? retval : 0; + return fasync_helper(fd, file, on, &list->fasync); } diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index 3838bc4acab..cb15bfa38d7 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c @@ -1325,11 +1325,7 @@ static int dv1394_fasync(int fd, struct file *file, int on) struct video_card *video = file_to_video_card(file); - int retval = fasync_helper(fd, file, on, &video->fasync); - - if (retval < 0) - return retval; - return 0; + return fasync_helper(fd, file, on, &video->fasync); } static ssize_t dv1394_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index ed8baa0aec3..7a7a026ba71 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -94,11 +94,8 @@ static void evdev_event(struct input_handle *handle, static int evdev_fasync(int fd, struct file *file, int on) { struct evdev_client *client = file->private_data; - int retval; - - retval = fasync_helper(fd, file, on, &client->fasync); - return retval < 0 ? retval : 0; + return fasync_helper(fd, file, on, &client->fasync); } static int evdev_flush(struct file *file, fl_owner_t id) diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 6f2366220a5..4224f011284 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -159,12 +159,9 @@ static void joydev_event(struct input_handle *handle, static int joydev_fasync(int fd, struct file *file, int on) { - int retval; struct joydev_client *client = file->private_data; - retval = fasync_helper(fd, file, on, &client->fasync); - - return retval < 0 ? retval : 0; + return fasync_helper(fd, file, on, &client->fasync); } static void joydev_free(struct device *dev) diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index ef99a7e6d40..17fd6d46d08 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -403,12 +403,9 @@ static void mousedev_event(struct input_handle *handle, static int mousedev_fasync(int fd, struct file *file, int on) { - int retval; struct mousedev_client *client = file->private_data; - retval = fasync_helper(fd, file, on, &client->fasync); - - return retval < 0 ? retval : 0; + return fasync_helper(fd, file, on, &client->fasync); } static void mousedev_free(struct device *dev) diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 06bbd0e74c6..b03009bb746 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c @@ -58,10 +58,8 @@ static unsigned int serio_raw_no; static int serio_raw_fasync(int fd, struct file *file, int on) { struct serio_raw_list *list = file->private_data; - int retval; - retval = fasync_helper(fd, file, on, &list->fasync); - return retval < 0 ? retval : 0; + return fasync_helper(fd, file, on, &list->fasync); } static struct serio_raw *serio_raw_locate(int minor) diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index d80b72e22de..ce753e9c576 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c @@ -993,8 +993,8 @@ static struct fasync_struct *fasync[256] = { NULL, }; static int cosa_fasync(struct inode *inode, struct file *file, int on) { int port = iminor(inode); - int rv = fasync_helper(inode, file, on, &fasync[port]); - return rv < 0 ? rv : 0; + + return fasync_helper(inode, file, on, &fasync[port]); } #endif diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 537959d0714..bc8996c849a 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -1917,12 +1917,7 @@ static struct sonypi_compat_s sonypi_compat = { static int sonypi_misc_fasync(int fd, struct file *filp, int on) { - int retval; - - retval = fasync_helper(fd, filp, on, &sonypi_compat.fifo_async); - if (retval < 0) - return retval; - return 0; + return fasync_helper(fd, filp, on, &sonypi_compat.fifo_async); } static int sonypi_misc_release(struct inode *inode, struct file *file) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 516925d8b57..b4ef2f84ea3 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1154,7 +1154,6 @@ sg_poll(struct file *filp, poll_table * wait) static int sg_fasync(int fd, struct file *filp, int mode) { - int retval; Sg_device *sdp; Sg_fd *sfp; @@ -1163,8 +1162,7 @@ sg_fasync(int fd, struct file *filp, int mode) SCSI_LOG_TIMEOUT(3, printk("sg_fasync: %s, mode=%d\n", sdp->disk->disk_name, mode)); - retval = fasync_helper(fd, filp, mode, &sfp->async_qp); - return (retval < 0) ? retval : 0; + return fasync_helper(fd, filp, mode, &sfp->async_qp); } static int diff --git a/fs/fcntl.c b/fs/fcntl.c index 431bb645927..d865ca66ccb 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -184,6 +184,8 @@ static int setfl(int fd, struct file * filp, unsigned long arg) error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0); if (error < 0) goto out; + if (error > 0) + error = 0; } spin_lock(&filp->f_lock); filp->f_flags = (arg & SETFL_MASK) | (filp->f_flags & ~SETFL_MASK); diff --git a/fs/ioctl.c b/fs/ioctl.c index e8e89edba57..ac2d47e4392 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -432,7 +432,7 @@ static int ioctl_fioasync(unsigned int fd, struct file *filp, else error = -ENOTTY; } - return error; + return error < 0 ? error : 0; } static int ioctl_fsfreeze(struct file *filp) diff --git a/fs/pipe.c b/fs/pipe.c index 14f502b89cf..94ad15967cf 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -667,10 +667,7 @@ pipe_read_fasync(int fd, struct file *filp, int on) retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_readers); mutex_unlock(&inode->i_mutex); - if (retval < 0) - return retval; - - return 0; + return retval; } @@ -684,10 +681,7 @@ pipe_write_fasync(int fd, struct file *filp, int on) retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_writers); mutex_unlock(&inode->i_mutex); - if (retval < 0) - return retval; - - return 0; + return retval; } @@ -706,11 +700,7 @@ pipe_rdwr_fasync(int fd, struct file *filp, int on) fasync_helper(-1, filp, 0, &pipe->fasync_readers); } mutex_unlock(&inode->i_mutex); - - if (retval < 0) - return retval; - - return 0; + return retval; } diff --git a/sound/core/control.c b/sound/core/control.c index 636b3b52ef8..4b20fa2b7e6 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -1373,12 +1373,9 @@ EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat); static int snd_ctl_fasync(int fd, struct file * file, int on) { struct snd_ctl_file *ctl; - int err; + ctl = file->private_data; - err = fasync_helper(fd, file, on, &ctl->fasync); - if (err < 0) - return err; - return 0; + return fasync_helper(fd, file, on, &ctl->fasync); } /* diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index a789efc9df3..a75c194e629 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -3246,9 +3246,7 @@ static int snd_pcm_fasync(int fd, struct file * file, int on) err = fasync_helper(fd, file, on, &runtime->fasync); out: unlock_kernel(); - if (err < 0) - return err; - return 0; + return err; } /* diff --git a/sound/core/timer.c b/sound/core/timer.c index 796532081e8..3f0050d0b71 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -1825,13 +1825,9 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, static int snd_timer_user_fasync(int fd, struct file * file, int on) { struct snd_timer_user *tu; - int err; tu = file->private_data; - err = fasync_helper(fd, file, on, &tu->fasync); - if (err < 0) - return err; - return 0; + return fasync_helper(fd, file, on, &tu->fasync); } static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, -- GitLab From acc738fec03bdaa5b77340c32a82fbfedaaabef0 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 16 Mar 2009 15:35:29 +0100 Subject: [PATCH 3527/4982] netfilter: xtables: avoid pointer to self Commit 784544739a25c30637397ace5489eeb6e15d7d49 (netfilter: iptables: lock free counters) broke a number of modules whose rule data referenced itself. A reallocation would not reestablish the correct references, so it is best to use a separate struct that does not fall under RCU. Signed-off-by: Jan Engelhardt Signed-off-by: Patrick McHardy --- include/linux/netfilter/xt_limit.h | 9 +++--- include/linux/netfilter/xt_quota.h | 4 ++- include/linux/netfilter/xt_statistic.h | 7 +++-- net/netfilter/xt_limit.c | 40 +++++++++++++++++++------- net/netfilter/xt_quota.c | 31 +++++++++++++++----- net/netfilter/xt_statistic.c | 28 ++++++++++++++---- 6 files changed, 88 insertions(+), 31 deletions(-) diff --git a/include/linux/netfilter/xt_limit.h b/include/linux/netfilter/xt_limit.h index b3ce65375ec..fda222c7953 100644 --- a/include/linux/netfilter/xt_limit.h +++ b/include/linux/netfilter/xt_limit.h @@ -4,6 +4,8 @@ /* timings are in milliseconds. */ #define XT_LIMIT_SCALE 10000 +struct xt_limit_priv; + /* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490 seconds, or one every 59 hours. */ struct xt_rateinfo { @@ -11,11 +13,10 @@ struct xt_rateinfo { u_int32_t burst; /* Period multiplier for upper limit. */ /* Used internally by the kernel */ - unsigned long prev; - u_int32_t credit; + unsigned long prev; /* moved to xt_limit_priv */ + u_int32_t credit; /* moved to xt_limit_priv */ u_int32_t credit_cap, cost; - /* Ugly, ugly fucker. */ - struct xt_rateinfo *master; + struct xt_limit_priv *master; }; #endif /*_XT_RATE_H*/ diff --git a/include/linux/netfilter/xt_quota.h b/include/linux/netfilter/xt_quota.h index 4c8368d781e..8dc89dfc136 100644 --- a/include/linux/netfilter/xt_quota.h +++ b/include/linux/netfilter/xt_quota.h @@ -6,13 +6,15 @@ enum xt_quota_flags { }; #define XT_QUOTA_MASK 0x1 +struct xt_quota_priv; + struct xt_quota_info { u_int32_t flags; u_int32_t pad; /* Used internally by the kernel */ aligned_u64 quota; - struct xt_quota_info *master; + struct xt_quota_priv *master; }; #endif /* _XT_QUOTA_H */ diff --git a/include/linux/netfilter/xt_statistic.h b/include/linux/netfilter/xt_statistic.h index 3d38bc97504..8f521ab49ef 100644 --- a/include/linux/netfilter/xt_statistic.h +++ b/include/linux/netfilter/xt_statistic.h @@ -13,6 +13,8 @@ enum xt_statistic_flags { }; #define XT_STATISTIC_MASK 0x1 +struct xt_statistic_priv; + struct xt_statistic_info { u_int16_t mode; u_int16_t flags; @@ -23,11 +25,10 @@ struct xt_statistic_info { struct { u_int32_t every; u_int32_t packet; - /* Used internally by the kernel */ - u_int32_t count; + u_int32_t count; /* unused */ } nth; } u; - struct xt_statistic_info *master __attribute__((aligned(8))); + struct xt_statistic_priv *master __attribute__((aligned(8))); }; #endif /* _XT_STATISTIC_H */ diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c index c908d69a559..2e8089ecd0a 100644 --- a/net/netfilter/xt_limit.c +++ b/net/netfilter/xt_limit.c @@ -14,6 +14,11 @@ #include #include +struct xt_limit_priv { + unsigned long prev; + uint32_t credit; +}; + MODULE_LICENSE("GPL"); MODULE_AUTHOR("Herve Eychenne "); MODULE_DESCRIPTION("Xtables: rate-limit match"); @@ -60,18 +65,18 @@ static DEFINE_SPINLOCK(limit_lock); static bool limit_mt(const struct sk_buff *skb, const struct xt_match_param *par) { - struct xt_rateinfo *r = - ((const struct xt_rateinfo *)par->matchinfo)->master; + const struct xt_rateinfo *r = par->matchinfo; + struct xt_limit_priv *priv = r->master; unsigned long now = jiffies; spin_lock_bh(&limit_lock); - r->credit += (now - xchg(&r->prev, now)) * CREDITS_PER_JIFFY; - if (r->credit > r->credit_cap) - r->credit = r->credit_cap; + priv->credit += (now - xchg(&priv->prev, now)) * CREDITS_PER_JIFFY; + if (priv->credit > r->credit_cap) + priv->credit = r->credit_cap; - if (r->credit >= r->cost) { + if (priv->credit >= r->cost) { /* We're not limited. */ - r->credit -= r->cost; + priv->credit -= r->cost; spin_unlock_bh(&limit_lock); return true; } @@ -95,6 +100,7 @@ user2credits(u_int32_t user) static bool limit_mt_check(const struct xt_mtchk_param *par) { struct xt_rateinfo *r = par->matchinfo; + struct xt_limit_priv *priv; /* Check for overflow. */ if (r->burst == 0 @@ -104,19 +110,30 @@ static bool limit_mt_check(const struct xt_mtchk_param *par) return false; } - /* For SMP, we only want to use one set of counters. */ - r->master = r; + priv = kmalloc(sizeof(*priv), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + + /* For SMP, we only want to use one set of state. */ + r->master = priv; if (r->cost == 0) { /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies * 128. */ - r->prev = jiffies; - r->credit = user2credits(r->avg * r->burst); /* Credits full. */ + priv->prev = jiffies; + priv->credit = user2credits(r->avg * r->burst); /* Credits full. */ r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */ r->cost = user2credits(r->avg); } return true; } +static void limit_mt_destroy(const struct xt_mtdtor_param *par) +{ + const struct xt_rateinfo *info = par->matchinfo; + + kfree(info->master); +} + #ifdef CONFIG_COMPAT struct compat_xt_rateinfo { u_int32_t avg; @@ -167,6 +184,7 @@ static struct xt_match limit_mt_reg __read_mostly = { .family = NFPROTO_UNSPEC, .match = limit_mt, .checkentry = limit_mt_check, + .destroy = limit_mt_destroy, .matchsize = sizeof(struct xt_rateinfo), #ifdef CONFIG_COMPAT .compatsize = sizeof(struct compat_xt_rateinfo), diff --git a/net/netfilter/xt_quota.c b/net/netfilter/xt_quota.c index c84fce5e0f3..01dd07b764e 100644 --- a/net/netfilter/xt_quota.c +++ b/net/netfilter/xt_quota.c @@ -9,6 +9,10 @@ #include #include +struct xt_quota_priv { + uint64_t quota; +}; + MODULE_LICENSE("GPL"); MODULE_AUTHOR("Sam Johnston "); MODULE_DESCRIPTION("Xtables: countdown quota match"); @@ -20,18 +24,20 @@ static DEFINE_SPINLOCK(quota_lock); static bool quota_mt(const struct sk_buff *skb, const struct xt_match_param *par) { - struct xt_quota_info *q = - ((const struct xt_quota_info *)par->matchinfo)->master; + struct xt_quota_info *q = (void *)par->matchinfo; + struct xt_quota_priv *priv = q->master; bool ret = q->flags & XT_QUOTA_INVERT; spin_lock_bh("a_lock); - if (q->quota >= skb->len) { - q->quota -= skb->len; + if (priv->quota >= skb->len) { + priv->quota -= skb->len; ret = !ret; } else { /* we do not allow even small packets from now on */ - q->quota = 0; + priv->quota = 0; } + /* Copy quota back to matchinfo so that iptables can display it */ + q->quota = priv->quota; spin_unlock_bh("a_lock); return ret; @@ -43,17 +49,28 @@ static bool quota_mt_check(const struct xt_mtchk_param *par) if (q->flags & ~XT_QUOTA_MASK) return false; - /* For SMP, we only want to use one set of counters. */ - q->master = q; + + q->master = kmalloc(sizeof(*q->master), GFP_KERNEL); + if (q->master == NULL) + return -ENOMEM; + return true; } +static void quota_mt_destroy(const struct xt_mtdtor_param *par) +{ + const struct xt_quota_info *q = par->matchinfo; + + kfree(q->master); +} + static struct xt_match quota_mt_reg __read_mostly = { .name = "quota", .revision = 0, .family = NFPROTO_UNSPEC, .match = quota_mt, .checkentry = quota_mt_check, + .destroy = quota_mt_destroy, .matchsize = sizeof(struct xt_quota_info), .me = THIS_MODULE, }; diff --git a/net/netfilter/xt_statistic.c b/net/netfilter/xt_statistic.c index 0d75141139d..d8c0f8f1a78 100644 --- a/net/netfilter/xt_statistic.c +++ b/net/netfilter/xt_statistic.c @@ -16,6 +16,10 @@ #include #include +struct xt_statistic_priv { + uint32_t count; +}; + MODULE_LICENSE("GPL"); MODULE_AUTHOR("Patrick McHardy "); MODULE_DESCRIPTION("Xtables: statistics-based matching (\"Nth\", random)"); @@ -27,7 +31,7 @@ static DEFINE_SPINLOCK(nth_lock); static bool statistic_mt(const struct sk_buff *skb, const struct xt_match_param *par) { - struct xt_statistic_info *info = (void *)par->matchinfo; + const struct xt_statistic_info *info = par->matchinfo; bool ret = info->flags & XT_STATISTIC_INVERT; switch (info->mode) { @@ -36,10 +40,9 @@ statistic_mt(const struct sk_buff *skb, const struct xt_match_param *par) ret = !ret; break; case XT_STATISTIC_MODE_NTH: - info = info->master; spin_lock_bh(&nth_lock); - if (info->u.nth.count++ == info->u.nth.every) { - info->u.nth.count = 0; + if (info->master->count++ == info->u.nth.every) { + info->master->count = 0; ret = !ret; } spin_unlock_bh(&nth_lock); @@ -56,16 +59,31 @@ static bool statistic_mt_check(const struct xt_mtchk_param *par) if (info->mode > XT_STATISTIC_MODE_MAX || info->flags & ~XT_STATISTIC_MASK) return false; - info->master = info; + + info->master = kzalloc(sizeof(*info->master), GFP_KERNEL); + if (info->master == NULL) { + printk(KERN_ERR KBUILD_MODNAME ": Out of memory\n"); + return false; + } + info->master->count = info->u.nth.count; + return true; } +static void statistic_mt_destroy(const struct xt_mtdtor_param *par) +{ + const struct xt_statistic_info *info = par->matchinfo; + + kfree(info->master); +} + static struct xt_match xt_statistic_mt_reg __read_mostly = { .name = "statistic", .revision = 0, .family = NFPROTO_UNSPEC, .match = statistic_mt, .checkentry = statistic_mt_check, + .destroy = statistic_mt_destroy, .matchsize = sizeof(struct xt_statistic_info), .me = THIS_MODULE, }; -- GitLab From 626ba8fbac9156a94a80be46ffd2f2ce9e4e89a0 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 16 Mar 2009 15:50:51 +0100 Subject: [PATCH 3528/4982] netfilter: ctnetlink: fix crash during expectation creation This patch fixes a possible crash due to the missing initialization of the expectation class when nf_ct_expect_related() is called. Reported-by: BORBELY Zoltan Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_netlink.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index cb78aa00399..ed6d873ad38 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1780,6 +1780,7 @@ ctnetlink_create_expect(struct nlattr *cda[], u_int8_t u3, u32 pid, int report) goto out; } + exp->class = 0; exp->expectfn = NULL; exp->flags = 0; exp->master = ct; -- GitLab From ec8d540969da9a70790e9028d57b5b577dd7aa77 Mon Sep 17 00:00:00 2001 From: Christoph Paasch Date: Mon, 16 Mar 2009 15:51:29 +0100 Subject: [PATCH 3529/4982] netfilter: conntrack: fix dropping packet after l4proto->packet() We currently use the negative value in the conntrack code to encode the packet verdict in the error. As NF_DROP is equal to 0, inverting NF_DROP makes no sense and, as a result, no packets are ever dropped. Signed-off-by: Christoph Paasch Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_core.c | 2 +- net/netfilter/nf_conntrack_proto_tcp.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 90ce9ddb945..f4935e344b6 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -726,7 +726,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, NF_CT_ASSERT(skb->nfct); ret = l4proto->packet(ct, skb, dataoff, ctinfo, pf, hooknum); - if (ret < 0) { + if (ret <= 0) { /* Invalid: inverse of the return code tells * the netfilter core what to do */ pr_debug("nf_conntrack_in: Can't track with proto module\n"); diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index a1edb9c1ade..f3fd154d1dd 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -859,7 +859,7 @@ static int tcp_packet(struct nf_conn *ct, */ if (nf_ct_kill(ct)) return -NF_REPEAT; - return -NF_DROP; + return NF_DROP; } /* Fall through */ case TCP_CONNTRACK_IGNORE: @@ -892,7 +892,7 @@ static int tcp_packet(struct nf_conn *ct, nf_log_packet(pf, 0, skb, NULL, NULL, NULL, "nf_ct_tcp: killing out of sync session "); nf_ct_kill(ct); - return -NF_DROP; + return NF_DROP; } ct->proto.tcp.last_index = index; ct->proto.tcp.last_dir = dir; -- GitLab From ee6f779b9e0851e2f7da292a9f58e0095edf615a Mon Sep 17 00:00:00 2001 From: Zhang Le Date: Mon, 16 Mar 2009 14:44:31 +0800 Subject: [PATCH 3530/4982] filp->f_pos not correctly updated in proc_task_readdir filp->f_pos only get updated at the end of the function. Thus d_off of those dirents who are in the middle will be 0, and this will cause a problem in glibc's readdir implementation, specifically endless loop. Because when overflow occurs, f_pos will be set to next dirent to read, however it will be 0, unless the next one is the last one. So it will start over again and again. There is a sample program in man 2 gendents. This is the output of the program running on a multithread program's task dir before this patch is applied: $ ./a.out /proc/3807/task --------------- nread=128 --------------- i-node# file type d_reclen d_off d_name 506442 directory 16 1 . 506441 directory 16 0 .. 506443 directory 16 0 3807 506444 directory 16 0 3809 506445 directory 16 0 3812 506446 directory 16 0 3861 506447 directory 16 0 3862 506448 directory 16 8 3863 This is the output after this patch is applied $ ./a.out /proc/3807/task --------------- nread=128 --------------- i-node# file type d_reclen d_off d_name 506442 directory 16 1 . 506441 directory 16 2 .. 506443 directory 16 3 3807 506444 directory 16 4 3809 506445 directory 16 5 3812 506446 directory 16 6 3861 506447 directory 16 7 3862 506448 directory 16 8 3863 Signed-off-by: Zhang Le Acked-by: Al Viro Signed-off-by: Linus Torvalds --- fs/proc/base.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 0c9de19a163..cc6ea2329e7 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -3066,7 +3066,6 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi int retval = -ENOENT; ino_t ino; int tid; - unsigned long pos = filp->f_pos; /* avoiding "long long" filp->f_pos */ struct pid_namespace *ns; task = get_proc_task(inode); @@ -3083,18 +3082,18 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi goto out_no_task; retval = 0; - switch (pos) { + switch (filp->f_pos) { case 0: ino = inode->i_ino; - if (filldir(dirent, ".", 1, pos, ino, DT_DIR) < 0) + if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) < 0) goto out; - pos++; + filp->f_pos++; /* fall through */ case 1: ino = parent_ino(dentry); - if (filldir(dirent, "..", 2, pos, ino, DT_DIR) < 0) + if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) < 0) goto out; - pos++; + filp->f_pos++; /* fall through */ } @@ -3104,9 +3103,9 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi ns = filp->f_dentry->d_sb->s_fs_info; tid = (int)filp->f_version; filp->f_version = 0; - for (task = first_tid(leader, tid, pos - 2, ns); + for (task = first_tid(leader, tid, filp->f_pos - 2, ns); task; - task = next_tid(task), pos++) { + task = next_tid(task), filp->f_pos++) { tid = task_pid_nr_ns(task, ns); if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) { /* returning this tgid failed, save it as the first @@ -3117,7 +3116,6 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi } } out: - filp->f_pos = pos; put_task_struct(leader); out_no_task: return retval; -- GitLab From d1238d5337e8e53cddea77c2a26d26b6eb5a982f Mon Sep 17 00:00:00 2001 From: Christoph Paasch Date: Mon, 16 Mar 2009 15:52:11 +0100 Subject: [PATCH 3531/4982] netfilter: conntrack: check for NEXTHDR_NONE before header sanity checking NEXTHDR_NONE doesn't has an IPv6 option header, so the first check for the length will always fail and results in a confusing message "too short" if debugging enabled. With this patch, we check for NEXTHDR_NONE before length sanity checkings are done. Signed-off-by: Christoph Paasch Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy --- net/ipv6/netfilter/nf_conntrack_reasm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index ed4d79a9e4a..058a5e4a60c 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -528,14 +528,14 @@ find_prev_fhdr(struct sk_buff *skb, u8 *prevhdrp, int *prevhoff, int *fhoff) if (!ipv6_ext_hdr(nexthdr)) { return -1; } - if (len < (int)sizeof(struct ipv6_opt_hdr)) { - pr_debug("too short\n"); - return -1; - } if (nexthdr == NEXTHDR_NONE) { pr_debug("next header is none\n"); return -1; } + if (len < (int)sizeof(struct ipv6_opt_hdr)) { + pr_debug("too short\n"); + return -1; + } if (skb_copy_bits(skb, start, &hdr, sizeof(hdr))) BUG(); if (nexthdr == NEXTHDR_AUTH) -- GitLab From 8032b526d1a3bd91ad633dd3a3b5fdbc47ad54f1 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 16 Mar 2009 09:05:07 +1030 Subject: [PATCH 3532/4982] linux.conf.au 2009: Tuz Impact: help prevent extinction of species The Tasmanian Devil is a shy iconic Australian creature named for its spine-chilling screech. It is threatened with extinction due to a scientifically interesting but horrific transmissible facial cancer. This one is standing in for Tux for one release using the far less-known Devil Facial Tux Disguise. Save The Tasmanian Devil http://tassiedevil.com.au Signed-off-by: Linux.conf.au Hobart Team Signed-off-by: Rusty Russell Signed-off-by: Linus Torvalds --- Documentation/logo.gif | Bin 16335 -> 0 bytes Documentation/logo.svg | 2911 ++++++++++++++ Documentation/logo.txt | 15 +- drivers/video/logo/logo_linux_clut224.ppm | 4428 +++++++++++++-------- drivers/video/logo/logo_linux_vga16.ppm | 4339 ++++++++++++-------- 5 files changed, 8477 insertions(+), 3216 deletions(-) delete mode 100644 Documentation/logo.gif create mode 100644 Documentation/logo.svg diff --git a/Documentation/logo.gif b/Documentation/logo.gif deleted file mode 100644 index 2eae75fecfb965f49065c680063a40c594736ee5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16335 zcmWk!c|6nqAOGyI4Ks7kJ-l`WUeEXOc)wiTT?l)^KpU)?Kn0W7l>r?R9$-;{Xg37E2u;Ex=Bm-OAYf|}zr`akX;6OC zziDV440N&@Ef~N~vViF5XjZBchXLg>(9HZKS`fkw4=fE}t7+D5cm&xKx-m&wVWY`p zay0`QO$5l~ATAA!#XysSpez<^jswt0Kr{(2n8dJHOd1J+MMIfP=Ej&C5f2R_0AwOS zB>_P}L4rvFg+gIcfH@9=U0cne0*oMFg@C&CLlW5ok1evItGo0f;&XCbKr5jOUmAGl5uYL6?#L(IoK85R+v9 z0s#~SL9tluWD$Z*1rPv~P5I|81eHSO^ZC&vs6enHSXpCJ|8cZNAP}9^Ns~-~NWi)2 zK<8KhK?gd?L=do0E|J ztP*;%3^B)r(rD!ZHkwI=3RWf!a8L#bx;2StDub>J0B&w14u>P)ASNeQ1YE=x8!^d3 z=;#prouC{lqO+-*UkzR1B6vLBWUX0g5_F4&5OC029CRo1ADB4+0JgXYfk3d)!T^BO zf1`g*ZAT(0ItuIRzK?`W2|J06j!KLI)P6xh0I&lX{96M2Unl@#2ly+jh1@rm-`;hN_;6Sd;xq?up^NOFDk{Lwk2c_FlznG?%+Sy7TG= zB4TwW=h5Av+eEo_r2~mT7t`&MUVwX(?obV>%EOt!WsN?--;JHUF8v^|1Tx55@@S6l zH{Jj8zGh5w-J8O=#UtnTK1pzR8bmKv7eY>kKBs+JICcMOG1mSO=IdWYj>+pbFL#sc zQAckoS|uNOrM@}Ruzas5=ZEI*z5Hi{`tpp1@-ovmL+s)#S;K3I6$IPFs$>nfhIhpc z=|9W&yRgbHyY{zSGm5tvV>CJ6Q)O47=Sj_|^*I!&Ljr6%^|8nsj9 zPq%(dSuEbOS}hkPod`hTXSSFJ@|Vg z@7cwr{m(E zCO_4Wf3dwC7xAlFruIUIHKG~L~ z$YLRSO5};`PTNPspiGJtfI!hoI zpK_|sFj09EG${FVCcA@{BF5sfop-&D2c`2Qd?u1!r^RiK7@VmN%Kq@aG~H2oc3B^9q*b*S1w8iu~4lK$e=EZ9FW69r7L+M zN)zo|7OxL=mF#(|7P?P~4BN7u6Mp8AW9o8z{mPP7_79 zF^&1XnN;Ym^fk9P$kjl0cd;?v{=8#LB_@v}{;{_}*ef+WP_G?XTQIm&wR%1@gK@F6A^MCW5mH7xB z5uAw&rnO02lhW3vhUeR2uRE<{+)duL2|uEQC^h3<4wC7axBe{g$RxN%qXZ&6AFixj zc{K+OE-B(v=HX!Zcna51iJysi!tLe0|EB#5ExLUsxbwnpQ&cs&6Z6aE!3)fHiLJRV z2|7{3Y6&H(-Jgvsp!Vk+9MzWD35KI`sqmfmC`5jA@vbi$ibBpAXcnT&tdK<{Z(&nT z5mezNr=2iK-)<4^F|7V;xTvzLpCVDf*!BH{c8U5C^&m#io_ZGX$R4$nzXRDa7YV|s zNvSFed3RiaoaOz~4%MIX`H`3gly*^iHN0*?;u=X0%QaFrwF%#qkUM&vZIb$5^gV6! zUim037t@43u|32T&zSARfH0OLhN;(m@4%z`=J$98u(I*oYHW)B%v}jO4bwH|9-#z* z>0cz^t^RyKN$;)Ym=9c)+3v84eMgA?V92}Yhw=NIw})ghuy1psWxM{vf7Ph z#`#0dmTku*&>BL@aff6%JCgPBCOX-lWIz5`s zdCs#3e&TTSB|F-W5_K)6=uI@Bg`cNGSwuijhb{7qEgC_YllZQjoAjUk!Ohte&0m-A zD6%8-a#|c!u`aIC1|V@Y)}r$2q$A@~1I%+ET{&}32$$uMOC9@JC+8*X-b|jrI~{%c ztH?o-<8$#$8K`rcoGBmF0H?0mg9->-p-Kwv3~Lc#jL(v`RFZmBBHOd4+t__&`=X2& zP8OpB-Vv$)nymq-cdpQ~%P(UuLIyTU_XIi>_iw)}8*3f*K zp7cE|?(h~^T1O|*rl|JfUN{yQ(n*$?cqL*P7zP#WcaUB{ij#12LdIon_!fiiovG*#~J1)o-0ckow~CvFabE2?_A^IyTS zK)D8?2Midt-d;$W>8M%;Ghst0A0f=&;3}qlmkblgk(-mZGbXnDvIc9i7ZzO!?bZmZ z#FC%c(=E(yy#qil(hVZ?VrTb2|FML;EMB??~^|P5h9Q_{t8dO za$|j?pd}L6FX)n}Y|BBiTU5ANPi;0T=!sQUK-h6;3*9J*Y1h6s$J_5u zCAN#QV5~X%LC#P8aL~CG*M&6o(pI7VxeT)dD(iJuZ){$jfG+Ibso2U}KL4}jw)Jq2 z*G_{R4crEITCS`6la~*b_a>wn@Bd1VS6WoiL0HTQ{g-$$4!j0Oqn>D=xClS5fj(Ut zcs@2T>4+=n2nodCp8vdzmI*_CTNYL3gD+E%quJnbGKzadd~v_{_2h&h;@O#$vq#|P zi55x1LFY@3Ci@hDP-H-EH(lCIB7&LHiWXB903&G7R-pI?8j72Rs+Bw2l${2roPbi3 zqqR>jE}u|z;UTSn%&Pd-^sJnBvAQlK#_fBvk2(M(zB>?QflxsuTg$zF_s)Cut&@p zLv53de{@&4j{@xDY32p0KTz|bLq9#GTA85)vmaHw|P zF*(rws~0{nPrYo;^O?(&BW8cxLL%JGuknud>Yx^AqTi@u7+o>>qSM1$r+@PA z5KD3`h1g4QDMH;e&cR;j@ zg0%TqhUqPsnMD2~NG=I9&fs;gOkI(wfFPMdNn~VX5iml`s0*ax<$zE=B8fv2;T?6s zqO`~&>P(o}4i`SfEW`Y|ISNNGDOs+>Ynlx=>`H_z!$e=Yqj43GeOQn+SwsyBbkVM2 zlM_PmAUlC*Cn7hsJGPsK>}CoL=pY{oL|zjwzUxg~m;!%$B5Wa$wA;{#lJe7RyY*QY zt)V6~P$XiE6-ALnjEQ1j*cb2?;R+P6HvSU&9#oDE2a~~;G*BR4xO5KGLo554U0k$P zRt_LkDbR=&pw$nx98-~avLYD0SEHihv%4g94t9?Zi^PJ|xv2d#(FfY$O>#ma0#RGn zOR`u%jRxGIh#cU;9v8vx&*eX4Ua|_l=wAf70EqapMWz@K%WBd0Bt4n?)kl|vcf9nJ z6)h!)s~qp~ky&W46&8GhC{`vwIgp_qOtEQVeAgZ55EH707l#r7Yqsz~K2TP~JaJv@ z{{2fzR3uFRzknAqM2qnSh+#j}7Ny!fwxZ<>JX231w7DX5m&8C3l0_3=G8I2YMr2_@ z2hjJk@Zz&rU{(PAE&zuMz?x){504>|XyM#B#BkC52iL{Q$@Non$xHzptsvGWK=3ae z9PZfjRUjG0e<0g;n0r9urMtwW!0KGCNIVxt{UGX17TTH+6UG9s1mIVE-01TD~B9{ z*e;mbe$RbuV5+9y53MIjlJzCD6c3mCp|IRq04;p<_c7gOSXs!$sMAk8pCgBvPtcat zI6PD81LVOxzo#|MpNbJRm%r9Cs?SwqkG!cE#_xNS5*6$z*{>c}v2jEZmB3XRo z^Srprv@=sgQ5sRy^EYtoQ#w!oLXVXYPJn1l7isf*mQxc{eiCJU z%7V|s-^C0|&c>PAazDt^epVe{L}do`fRAb|YO%9^8hy4IAW`^eq*i>b?jI}t8rT1@ zwnz3~d-s4lAJVA#z_FJGdHS3sIU{nF@;sj1!FeMR(b7>&Dsi8&{CcXZ2q*I0%q8G~ zsNs8=vp!uK65@O-Tbam?^*PiI0RTs0+v54K{@CWMf!ZuC4B&%s09ft!lU9v~Tu2Wo z-YLMUE6zuow4JGWqBbiDrRii>@WAmRsiuFmD_|OVkBlhv1mj2$M`l-z)x*n5J*3db zv%h5|FL5;`T7Lt=mH58z2T(oJmh})JtboTx_V@omv^)}0SA2NJ;5n#Tw308%L3S-O zMe((=IrF{7CI{Neol=z?v@^teiT&McobMXX)yz0dYdc8kt2e2=-CcgMCi2yIx(Qu` zfg8a6=3Gz|XU5m2oqcf3y1ADIf9W_hZz^1gcDZWc`krfXN=bfx=KN@QBFKhcqICEf z)(#LIx)|3!e0Jy6B??Na?$yuG;s3BA`BHM%hliNj@^!uvy?F26Z1GX7NTK4$Hw`;x z`Lpmw#YUaYFePE5UfS~4Ms@*)uEb+wqBeG}FZd;YtTwHOTliyMVh3+{ ziriF+EA!R5u}k8{%{qo9hoW9L4PRn9ezCmtK{#pD!^{whL>1`HoKH|BEe#jr+Sgw50?8{zAo zU11Z$H)NDqf+?AE52`+ocOk7y3Z~D!5Fa;H%$C(_lC(`d<|Je|{aDGNXm<2j!E}h= zmE+S8?&pcGJJ>h)gDw*xGl8Pk4rVj`hAx-*H(Jjf{x1~u-={H~gO6R6iPO%*vvqG? zD8Ic^BSoONKQrV*lir=KoB2FD`@H1}rbbGx>D_xJkqY$G%!_wdYn?kK-kopX2ex$@ zWxhkSzPrdAsx9y{u}5sozCCL*ud*Y)O!5}|eP_}zs(OAwrBLMW=XbHyQW>PTIx35- zI#K<>1w(166tpRzDZ7qjgG9#A`od1Am6+dxPBfefL zO(2A)x$c}WT8=WDw?zpbZvEh3D*cHIC6G|hxNoK2E-R@F6y0(=D<*tppZXz3X(bBb zM#Pe8!d&8^!S=O}N-{2QF5~nZrK`E1*{YQ*GqY#KR%t4WHa1S})&m^|!=5i*S5mkc z35NUB5EB0I-RwPC(w}6+R*P@0RWe^I+fF@H`PkRG_T>CK9B#Nzd0_Cx-1>sF7mYxb za+o;(`Kr>u6Qj?M&%f(mUn@5JytR)Ak>)Inc9LgTe;0w<7d|r?dCsqC**fsPIVGVSRPuCPDa~5e6)H_VM6NI+kP+Nna``s zDz@Smce+O6zPVMo%k`kIrd`0_usg6XM zl)2CT)wB7wQ@w8&t?fRimTxwvzS<}dDFGwVRYo&ixn~n)^4S|PhrfR|TqW)NSii*& zRBEmBcj|ER)WvFEn^%i?$a#_|bBji}Q6(x=|Gld9N2d3Bhv&C%hZ-gKZDApSl7XYRj`Nh;fc)*JuPUYJzuZ2K{QdG9%5nvj@^QyFRAAxrGLO$I_DsGQ*C z<~-nS|9qg?Idkw^ zq-(UNn|Z_At{WEbZLdCyOuo4aF?4cCfWES{B1DID7s!jgT8Pwfdw$07@ZfXtk^YyL zY}0m>MGQ`a*?Y+tCzl`Cbg0N*=ZWP8|5$sTx@Yu-uD_Y?@Gn~3$*3P@tK(e-zePm` z_Fd`3#MouGraXE_{Yp&hM&wIttXESNDdE{Z-{-|I-cGSLLk><3&%PADcUs@Is6-=n z**0#%`)&2aQ_%eu24ADdumYNs-jc1C{;+L%OR~oDAn`iR%J;|bA=HlB33b9K)Bx{P zopxOlIhmMgf$8=C+}Bz+Q&p>JV`x*?8wQDH!!<>s$CS_Y5jD=_o8&ClG$i~GdJ;h zaI~ix(xN`zOjbM9m(<|?1ldSc{c3EuM6mx-8bNohiP8RN1q!e8$( z*S2@^X)vM~zR^~B)bxEY@Ll5r^Fp`&xYx7g9?}MP@wxFa17{zm;ka)bI~W}&KDRuY zTS!VgJL7b%P;a9;}UZpl+t1LUkE1 zcGMbPZ%FspHJg#p6PLD7mp<}b%dJ&IEE9%eE3JN(rbbM<=4A+j2CG)0y^KUDSy@$Jf~PIaANH`U=C&fS-n zaE`>}Ah|zK!pkMky7;X(v)koAxg!9c2A0kpTf6iWT3<-ll^_MXxUhv+d-t;RgRhxK zv`gJ`B6@MJK(#TlE?km&wyEUst{_LnEAVW6s1hQ3K@|&iPJcA@7Mw$ntRNd{p8ynq z6kZ3u>5Ce-O!!)cPM2;LPUrF?^)U8In|NOWKJ{6;S39P2wzwhxKb;|ijUs15FK?54 ztgF&VNhy;LUkd$|P-$B%#|7Oi$3v++r99~_?dE#x{SNA)vs*o<%uWZU9C83hcLy}xy=?HzFObHR8j?~mUL{%MOYg`Sx?^a!G39vZ zrN;~0<`dl`_RSSXcK_$27B#YR{9LH!f$KPg#n#+4c4@D%{>SGQCI3=$AZj$rR5UOn zO!QWMwT*Jqi_8PN44S39wI0blwSLwnwvZp`5RfuRu58-@wqx@c*TW& zZ|K5CqE5b!6KZOuXFj?Ig?R;6>sq;1sF#pYccQ~2zy{s+pmlMj12jX0(j0()*8eodt+kLC+n9M#&42mOIRZ{gEbp@z@wJJP;OZRn*>DhJXJE?e9-^r--Kw=~)!9h*cg%B1TL&Az&xm;(4 z|8_62^kj)=-3QxH^O@1>BPath7#_aCS+dQLD(BR~j1=DhO|Mnle8EEr2W& z_2C*M8SfPmI$qHhGJ7*jHQXW;)#RO}CQciQySM{PIx46hsXr5!AAHVfE~cKfo>SG) zq5zxZfeK;x&@h1UqsXN&@9Tzn=pw+9d)B0kKNh!lfx%Hnt#7TJ706F}9;3cEiV`5P z)7ASA>1r#W@M$%m@Tu^pFVtEMEIG(xc0#rNH{I*s2OmH+^O^iCl{N%1KUj*yX&>J1 zbu0%j1A85tLj{7$PsoE3Z)DXQbbR)-x2Ox11e3}cL}|paXon{UhCyzbRUNxR{{kJr z0IMhJvs#pf)TGMlIK1HK-lO22=AO|4h?Kv_sR*< z%bFj!0|FbF`*y!5bhrxzh*7i@N&Mc`(Q|M;Tn^KJvU~03X(gfkp^M}MS{sgO+J8pw zep;|sk-8_;S(4#^r+>Nlu_!fXYwS0 z@rWe|Ue!8)xlykk!&G>ucFXc*jeVLWQCi)1(wWdcj0g-=ju+qJc05uO)2sf=4Hz^@ zN?H5VFFCs++y0sS5Uh6n^p2Ox`G?u`n)+DhqcrFm?~KeoW}yo+_1&L@>&BHnIUfGc zzJUl9X@oR;B!PskG@B*8UOzPch4cMLP>0FLmb38kmAn4EATM@{wIke=Yeyu2 zJysxcRlEyLuEY6Z!97MA}L97byab=@H6szZnCtrs8*=$wS%}be+ z{cMtG@cjgs*62=-$~3rUZ(GSE{J0Jf&4%kS8&D5gE3IH&L9oMAu!O)?yaepXfPreW zU812;q^wQLr#fzF$zO#I)3Rh4uxzXLIEtM#3;t8&nN`U1{!jRd=LQOVIJN9Ke-0%* z>8J;7-&hW1&v}EYA zGVFj1jcTxinNx7-ORW}DML%Q6+4g=*nrNBBDR#SLM(cGtbaf@yxZDtu-gZXN86T7t zJ=yApg-CE|$0X5YB8*`DFoN6_m|=g8n7#VQAf&w1)*2jL25vk{h{1N^O1r=(>-%@E zzjTRrl6Yj0#7G115Ix+*oUdXoIxp6~<(07tWuUhGjoD|oyf_Xlp))g?nS~7k3*+g^ z9Qu6+SOh6un~@bbml21DP>I=Pwb?k{V;t4>^o-=0HQ>yQ^X6y|V$Std$itlemM4BM zR`s7!$U>%DPIPeAfBjcii*iL`~D?rSHRM%@?I9lOemv z=>b8#5j2Q29+F?1o!kUJ$O$Q`w4 zY2GV8;~;BVMzupCQq31(=6gM3wTM?A)V8n1?Ie*NTa*<~6(UhGb^=(L538ZO_+SZQ zmbrB9aUv`^2<*YkIuMlUT-LIi1%sHupQrYa_ohLtP>$3z+ciKE$V37{q_Q+|MwU2w z01jj%jdA0Mpagt2>rF%W#?#7tI~7s$-WFPhb;l@|9$Q&>uiE2Q6>!}Qp1^_?48Q__ z%zx!1;~PS;RIoW73dN)={(;F6VRBnABpwDQLt?Scu>zsy)XWGzFP7+e^4}&w>FHnX zS)itAYym_f$XEcDW`gy2fESP<^J36+tVb#UEnZvU*3ojPdE~X4ye4J_EjD<{YRbdoXSeCjY|EVT>0?9sXfDyt`i!M6od|F_-+L(f&_+ zT$Ff%HTGuT` zwQ%!H*ZepqaEQNEN6^7jqhHzz(L8x=*hjt%yi%*iDlR^LPB#J+kl#QUel$;h-U)Vob+DB%4 zosJGJi}EFKvcidhqoFW&s+TQh+~@t2xLdk7H?#BHU=)xcTodrLb~5zjfD_WBnFecg zoJ8PJ^$D#==1<(6QQk-FY^zeE<06u6b*x`Hso$5KqV=mp;(&%?ZAbK%;Q75Cm9>GSZ5r z@YjAS;j!zXYSPKwfdpzg_i|Q5+0^gU%=Tk%KRrJ5sq5|9_@U2Ebn}9`?ePY*qAesO zPqz%55fJp_@+2ek@LfYUFGZINp-q$L4*q>L$<*gr=cS3d+3GR;UxLA~*rCBtdvV_D z2r2|#zmpZtce9)G3u8@PcRsLo?5*fTcy&$afx0aFfHxm1IUh<)MX*C(ZF02%3uY)J z0pry@wi|VMae8{PscSx|iu0v*@$oC`-Z5xWQJWsJAUrHXef`#}q@h(TD0&MTN(wwh zgB)c<5@_LVo9V*0g0DXgA6;4!ewEekKRxW^SrPhV5^S!d9A@gWSV;5+IzF`uA1|a}(%Hj22q09Z(5p5yPZ{5YY8N!?C@I&c{ ztOf3SzZkc-b=6Y|A3lgr@P_|{YgX5FA-%13TvZ%%2amaDzwr5e&PrLa6K7{Ov%l%@spkr^5qX-9K^v30Em_jD z5?I1YL5W8Wj((c@4}6AjW;mfJ`Y5mOL2Fjt+gNU9`h)$Wb4~pzM$4RurX2+>TU1kR zB_~5hsE>>rD%N5b%HTH{%AR}@Vaqi7<>c=OK zJ{|rL_jr>XJQ3%azF%^EIJldmBRKq2YVD$AeJXxs-F;>6KB2B3LgGR00ZhKT`5~{% zR$04WfBX>(KN?h42R8;nxgT%$4*tMICPhj-UpetKpa2?2+>LY~+|_l#gCPwl{VKc=iJ4G(7| z!c|}GtD}V6?46JN!ZC`meiQb%YuC3>1hFg)$qeZ190y5K0~Jd_ zKYkFO8+j|jr?|F9x>g84w(vazx;Y~Q;S3?o?R)p4>h_jtM%WhvF%^Cgupeq1ov5?OuncbA#sZ^~U~_+Ea7C_c?Q-(Q!HwnwB> z(d!eSEHgSF_LBaq&7WxGQ}Z;ZGWS@KdlrERdD(SWKj7b<)L7?izFRbCk}K zI19r*EADSE+~k{xF?$g$5#ogRzmIO}P1GKElK6RNb@RdN)bO5Zy*48!+~LB?7rv*~ z${xjz4-7v(`cvB{11^5VU|K>wGZR&#ImZ0@{&2Rk35*|XsxwrGyZh(b{gNn~!dx56 z=IG($4%Iexww^&{Ot0H_W3s$ruh07?fee)KjagDUUgVVT>z}PYP0smxe${FJAZ0`< zX;juvuDdRGa#(b>f{IN zaEa~DsWH-_t$@4XUQ;sTfv(tdE{EMP1ui~bJH{0j0WiIW@T&)ZgWRja=VkoW9b`?i zifwQ2o~n$UcCYr^>)9p+_{TYMdo`~*ZE2Q;d^WA1sADOJ-M6b7c=}WElvj%5WhOVz zBIKJCBHV4VB8!Qeoxw#JvqICiRMZ};linA&jHqhgyDMpd6X}cePJO?r?FhLZC{_7I z2&3YZop>PJX4@bNW*MkO^@NU8OKR1UOZLoLAfxSJyB`o5J+rZWG6!wknI~Vfd=xU5 zybGeHr*qBc<%4oiLP3}mIU(~B_ZrX3k}|a%i^&|b*zTn`yMs$>o(8*~`W4>03=5&( ztNiYHWi?XZuGp~p=1tk7k|+^S1jeCYN1bD^c*Sh+)o$h6zYX^U9W@i`E-Ljk_n$5< zGgmy8ms#ka+f1|eaISu*J{{@oB<$RlD`mH5uD?PdN%{1JR>X~aBfW7>X|E}XPKpQD ztjq$7w)WmZSZ?H{o6s{1NY8@pdKYxJKTGS+*3YUZ7=4B$~-USO{MCUGRW*YMlv!=8mg znPmg+JMc$MVvCPQ^X^=?Ja}Kg{l0^=7D*ei$0ZVMlU^2kN9SU06xsJ4xZg4|v)lLi zlhPuqsm0}+3kO{jXt#@>*I$s6G8Wru92yk%XgEB2Xs?oaQBn0LFH=2_uT0?%BD7=Aa0RL%yj?yr zrdz{c^hS80Yu)XE0d1vU*DKaeSp9jGfLoQALYw%hzv^_;$!;G7u6F5u#gf$iyEfHC z&{S=8bG1CORry^SiU=ijppVho;Zd3nySmcO+K|(Y`Lvv<77fM0`Ow{I0r#~|FX!OF zv+Mh>Jj-7*JYc@d`J#)jVl9 z!b5nZz`JWfS&KgA<|;d!{3Il2xjg9R^Hc4O46t-9T}H&W z$K+5$t~PI8#FQ3wyw85`1+i?nB-zoh&R<-|IDV+o@*T{jcQ^}pm7{8+KC=uEtXH!F}<-bvUqf0 zW$lin)gPOqPLA7oGCoVVBPz$e*TAze+fJ%nVz-LSQkLgyiWpS|f@ZRW6wgqE{1`%# zc3mEO%CKX+r!5V1(j=M!SVS z&=?}8|E#=0?0KReF6p6_d8dH~aXYczbc|6-mJFe53$*lip6c>JTX@E( zfl%ZcS<0CTRw$_w`JfXYHmvR)w(E}XjHGC;uUBadry?STmE9x%{`SS1ul@h^)(jsi z+gm--;EL6)4*u*oOc(Zy+RVfmpE&2fSLN^QLaVw0hvkgJ0WgUfY+`P5p3`vLoi*!LQ4>uc?&$;rQL}LVY>xh>K;F%r;sOOpDSW;vwAzy0Zm) z2r;7gF=+68SVwgdPs`GHTxZ~lezet_YnW+gtdu*v;;#F?xG&x|Q#&R_bY$h1UC)Nw zY@SjyWOS2?^!%W|W;#tj<3`EayYcSw_wIwTVGq7RVuGA;xp){jC}_?F-hg5>q)EcU zp0|2pmJ9RAquc;n&beJhYmU4#wSG2+9B9w!0lVU;4vzb)ZYw9-Z(mkhhRZv47A<>T z6`Z)C;hTJK^wQ@PUx&2Fms#$rPL;IRU-T3#wtomIj^VSESLRj< z-)?ZsAc5Km*33u4MTIkx3GAbLS3hzkEYZmguh(VDshLw(!$OHIn!ML!HO55i(`8Bm zukF2M{E&zf#>YCzzJeN%c~&fD(*ND>BaRYFSeS&_&ew^H<*53&bj?VFT*vt?5h<;! zmO_16=R@8d8rlB#yyHjJ;vj(AGfYozirAbu5A0n1N{d>#AkUn8`RVD~^qN-}$KOtW zeEXs4W+;=$x$JpYxh%OQkJiOVkrq1ixjdcTKJNqG*d(fk+7BPRjqu{>?x2bC8-RSI z1JSwTz08}GS-Bjh%PD3SJ+pfjl=ItUj$?wA;l6{EwoBJKSg~&Xojq)}q^e_06uCD2 z-`{uo0ugDg@mLuq=sZHSc;<=lYs+!RbpbqC$y?np#Ahs>^`h&Ob2@t40T}3+=yQPe_(~Mle@=fzvXut$nrL;fpF3p^Tr zi6rrbi;DVwQNpTX)V>(rmY?v_1==lC?5#?<1lbCCc?Y>B2b^^qdgS)r#ziZabnola z+Jja9y;_vIb@0a6+iX?`@5G?JbAMxbUJV){H<7NlK7JwwYt)o(+YXlX5n2iAQr!{SMiu{Q$~rhQN{sq}vp#Y}YW=XU^84($ z;o@E~x`AYX`Lyjq#Jzh*tk%MDY><2gQJlar+D%SC;QHv21l)uXJVf<^9WIe>vcy-4Fe zx@;|Xqd@bnf-c>E z*RIVzB9}o_T#J2Z6fbd^hGEbl@eT;YgWR{(UCmkm<{ zomXEnOwyOffC)UJ6qbg;)96OB9a*!r{)hwhG$mfUq_loZvt!8MgP%3%8w8Dqj3Iru zwEsYBR(kDvV`)aVbhQi`W1@CkwisevtK??T)eP=J#Wl$4Ymzz|)9yxYMv9zple%-v zjNA?<+}^(pj%?mJqHjPqkftN!(_}Y5i+k?93^mNj%{(T_6^U+BD{9lkwLe#n6^?W8g}}Xzjf3l#3p-`l5KMlX5s#ju;=n$C3^&k`>jG}vS@Wu2 zENZQST~{zl1*qM1Mn}Lk&Fy_2G_eh$JVSpIG!vA%-oB~_V$fyXfT3pz>NDV$ZHL9~ zYd!t#RAo z5jZygzD8eSTwLyPeN0;5G*K#=4iNwtC*87~%wIq5(|2)E*p+z~2Q4N2G2btdm3l^m zcB`F40W5D>FZH1@uKj$U17d)4S6QQ!ZaO6@aSSn4sz8-HMyU=cRh$aVg$IY z8Z{sJ0;5O($3YJPu%9YS>5ItAd-N*+$nzdjsb0ol#mLKe3|2R~qoly88MQTZ@C6Gi zwyU|RN*XlC4;9iB(lP9gj&}U2@7g|vd)-G2A`?F~_{M&@6)mwRr&At z>DR%~HLghQ1A`?kp>z|Bahzdvje2#&Bd^4k)o_*g1Vlba64`;h@NKQ!0UO#T!)QYq zB(4rV>{<`kvbNV>{CYm&u9`u$@eiU@K3(GMHG0~va)p(pH2`d8FMY{ge+jg+QCKIV zu_Sa@U`TSrEwyc_q>1H&c9ohKAAV$q)`Eu8A)MoiP&T{oVebC5*D!(FS_2aLP&My? z<0?&;Y?@Pf{0AKbj<%N$T#~kObTlY}a$K-u+*j~nv zOdV31926ae2{Z_oEtWy_Rt1ybkHw(J1>qZS!Mj}FY%tC@IgPZTJnzX)5}oU7W!UyA z#FGIbbQ#1~%zw*?IUuOc<9(m*)2@8;y4a@0qaO%qQrh4;$Bnjme*Y)47`41p)^D`j z^0+eCUErq2Vr3itKh>T0(wx84VQ3%>((%{yDTk_0x}}Yw8eGfSB^AmM9!bpV6c zg`gqZM$N~(wf!!cLqb7Nb_dqlKzxH9sv$t>qzFU7yQEW2ulYPv-<912+d58@^GU;qFB diff --git a/Documentation/logo.svg b/Documentation/logo.svg new file mode 100644 index 00000000000..cb9e4851d8c --- /dev/null +++ b/Documentation/logo.svg @@ -0,0 +1,2911 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Documentation/logo.txt b/Documentation/logo.txt index 296f0f7f67e..a2e62445e28 100644 --- a/Documentation/logo.txt +++ b/Documentation/logo.txt @@ -1,13 +1,4 @@ -This is the full-colour version of the currently unofficial Linux logo -("currently unofficial" just means that there has been no paperwork and -that I have not really announced it yet). It was created by Larry Ewing, -and is freely usable as long as you acknowledge Larry as the original -artist. - -Note that there are black-and-white versions of this available that -scale down to smaller sizes and are better for letterheads or whatever -you want to use it for: for the full range of logos take a look at -Larry's web-page: - - http://www.isc.tamu.edu/~lewing/linux/ +Tux is taking a three month sabbatical to work as a barber, so Tuz is +standing in. He's taken pains to ensure you'll hardly notice. +Image by Andrew McGown and Josh Bush. Image is licensed CC BY-SA. diff --git a/drivers/video/logo/logo_linux_clut224.ppm b/drivers/video/logo/logo_linux_clut224.ppm index 3c14e43b82f..de93ff3fc1a 100644 --- a/drivers/video/logo/logo_linux_clut224.ppm +++ b/drivers/video/logo/logo_linux_clut224.ppm @@ -1,1604 +1,2828 @@ P3 -# Standard 224-color Linux logo -80 80 +145 113 255 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 6 6 6 10 10 10 10 10 10 - 10 10 10 6 6 6 6 6 6 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 10 10 10 14 14 14 - 22 22 22 26 26 26 30 30 30 34 34 34 - 30 30 30 30 30 30 26 26 26 18 18 18 - 14 14 14 10 10 10 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 14 14 14 26 26 26 42 42 42 - 54 54 54 66 66 66 78 78 78 78 78 78 - 78 78 78 74 74 74 66 66 66 54 54 54 - 42 42 42 26 26 26 18 18 18 10 10 10 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 22 22 22 42 42 42 66 66 66 86 86 86 - 66 66 66 38 38 38 38 38 38 22 22 22 - 26 26 26 34 34 34 54 54 54 66 66 66 - 86 86 86 70 70 70 46 46 46 26 26 26 - 14 14 14 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 10 10 10 26 26 26 - 50 50 50 82 82 82 58 58 58 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 6 6 6 54 54 54 86 86 86 66 66 66 - 38 38 38 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 22 22 22 50 50 50 - 78 78 78 34 34 34 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 6 6 6 70 70 70 - 78 78 78 46 46 46 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 18 18 18 42 42 42 82 82 82 - 26 26 26 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 14 14 14 - 46 46 46 34 34 34 6 6 6 2 2 6 - 42 42 42 78 78 78 42 42 42 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 0 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 10 10 10 30 30 30 66 66 66 58 58 58 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 26 26 26 - 86 86 86 101 101 101 46 46 46 10 10 10 - 2 2 6 58 58 58 70 70 70 34 34 34 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 14 14 14 42 42 42 86 86 86 10 10 10 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 30 30 30 - 94 94 94 94 94 94 58 58 58 26 26 26 - 2 2 6 6 6 6 78 78 78 54 54 54 - 22 22 22 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 22 22 22 62 62 62 62 62 62 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 26 26 26 - 54 54 54 38 38 38 18 18 18 10 10 10 - 2 2 6 2 2 6 34 34 34 82 82 82 - 38 38 38 14 14 14 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 30 30 30 78 78 78 30 30 30 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 10 10 10 - 10 10 10 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 78 78 78 - 50 50 50 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 86 86 86 14 14 14 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 54 54 54 - 66 66 66 26 26 26 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 42 42 42 82 82 82 2 2 6 2 2 6 - 2 2 6 6 6 6 10 10 10 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 6 6 6 - 14 14 14 10 10 10 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 18 18 18 - 82 82 82 34 34 34 10 10 10 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 86 86 86 2 2 6 2 2 6 - 6 6 6 6 6 6 22 22 22 34 34 34 - 6 6 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 18 18 18 34 34 34 - 10 10 10 50 50 50 22 22 22 2 2 6 - 2 2 6 2 2 6 2 2 6 10 10 10 - 86 86 86 42 42 42 14 14 14 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 86 86 86 2 2 6 2 2 6 - 38 38 38 116 116 116 94 94 94 22 22 22 - 22 22 22 2 2 6 2 2 6 2 2 6 - 14 14 14 86 86 86 138 138 138 162 162 162 -154 154 154 38 38 38 26 26 26 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 86 86 86 46 46 46 14 14 14 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 86 86 86 2 2 6 14 14 14 -134 134 134 198 198 198 195 195 195 116 116 116 - 10 10 10 2 2 6 2 2 6 6 6 6 -101 98 89 187 187 187 210 210 210 218 218 218 -214 214 214 134 134 134 14 14 14 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 86 86 86 50 50 50 18 18 18 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 1 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 86 86 86 2 2 6 54 54 54 -218 218 218 195 195 195 226 226 226 246 246 246 - 58 58 58 2 2 6 2 2 6 30 30 30 -210 210 210 253 253 253 174 174 174 123 123 123 -221 221 221 234 234 234 74 74 74 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 70 70 70 58 58 58 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 82 82 82 2 2 6 106 106 106 -170 170 170 26 26 26 86 86 86 226 226 226 -123 123 123 10 10 10 14 14 14 46 46 46 -231 231 231 190 190 190 6 6 6 70 70 70 - 90 90 90 238 238 238 158 158 158 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 70 70 70 58 58 58 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 1 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 42 42 42 86 86 86 6 6 6 116 116 116 -106 106 106 6 6 6 70 70 70 149 149 149 -128 128 128 18 18 18 38 38 38 54 54 54 -221 221 221 106 106 106 2 2 6 14 14 14 - 46 46 46 190 190 190 198 198 198 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 74 74 74 62 62 62 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 1 0 0 0 - 0 0 1 0 0 0 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 42 42 42 94 94 94 14 14 14 101 101 101 -128 128 128 2 2 6 18 18 18 116 116 116 -118 98 46 121 92 8 121 92 8 98 78 10 -162 162 162 106 106 106 2 2 6 2 2 6 - 2 2 6 195 195 195 195 195 195 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 74 74 74 62 62 62 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 1 0 0 1 - 0 0 1 0 0 0 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 90 90 90 14 14 14 58 58 58 -210 210 210 26 26 26 54 38 6 154 114 10 -226 170 11 236 186 11 225 175 15 184 144 12 -215 174 15 175 146 61 37 26 9 2 2 6 - 70 70 70 246 246 246 138 138 138 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 70 70 70 66 66 66 26 26 26 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 86 86 86 14 14 14 10 10 10 -195 195 195 188 164 115 192 133 9 225 175 15 -239 182 13 234 190 10 232 195 16 232 200 30 -245 207 45 241 208 19 232 195 16 184 144 12 -218 194 134 211 206 186 42 42 42 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 50 50 50 74 74 74 30 30 30 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 34 34 34 86 86 86 14 14 14 2 2 6 -121 87 25 192 133 9 219 162 10 239 182 13 -236 186 11 232 195 16 241 208 19 244 214 54 -246 218 60 246 218 38 246 215 20 241 208 19 -241 208 19 226 184 13 121 87 25 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 50 50 50 82 82 82 34 34 34 10 10 10 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 34 34 34 82 82 82 30 30 30 61 42 6 -180 123 7 206 145 10 230 174 11 239 182 13 -234 190 10 238 202 15 241 208 19 246 218 74 -246 218 38 246 215 20 246 215 20 246 215 20 -226 184 13 215 174 15 184 144 12 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 26 26 26 94 94 94 42 42 42 14 14 14 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 78 78 78 50 50 50 104 69 6 -192 133 9 216 158 10 236 178 12 236 186 11 -232 195 16 241 208 19 244 214 54 245 215 43 -246 215 20 246 215 20 241 208 19 198 155 10 -200 144 11 216 158 10 156 118 10 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 6 6 6 90 90 90 54 54 54 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 78 78 78 46 46 46 22 22 22 -137 92 6 210 162 10 239 182 13 238 190 10 -238 202 15 241 208 19 246 215 20 246 215 20 -241 208 19 203 166 17 185 133 11 210 150 10 -216 158 10 210 150 10 102 78 10 2 2 6 - 6 6 6 54 54 54 14 14 14 2 2 6 - 2 2 6 62 62 62 74 74 74 30 30 30 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 34 34 34 78 78 78 50 50 50 6 6 6 - 94 70 30 139 102 15 190 146 13 226 184 13 -232 200 30 232 195 16 215 174 15 190 146 13 -168 122 10 192 133 9 210 150 10 213 154 11 -202 150 34 182 157 106 101 98 89 2 2 6 - 2 2 6 78 78 78 116 116 116 58 58 58 - 2 2 6 22 22 22 90 90 90 46 46 46 - 18 18 18 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 86 86 86 50 50 50 6 6 6 -128 128 128 174 154 114 156 107 11 168 122 10 -198 155 10 184 144 12 197 138 11 200 144 11 -206 145 10 206 145 10 197 138 11 188 164 115 -195 195 195 198 198 198 174 174 174 14 14 14 - 2 2 6 22 22 22 116 116 116 116 116 116 - 22 22 22 2 2 6 74 74 74 70 70 70 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 50 50 50 101 101 101 26 26 26 10 10 10 -138 138 138 190 190 190 174 154 114 156 107 11 -197 138 11 200 144 11 197 138 11 192 133 9 -180 123 7 190 142 34 190 178 144 187 187 187 -202 202 202 221 221 221 214 214 214 66 66 66 - 2 2 6 2 2 6 50 50 50 62 62 62 - 6 6 6 2 2 6 10 10 10 90 90 90 - 50 50 50 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 10 10 10 34 34 34 - 74 74 74 74 74 74 2 2 6 6 6 6 -144 144 144 198 198 198 190 190 190 178 166 146 -154 121 60 156 107 11 156 107 11 168 124 44 -174 154 114 187 187 187 190 190 190 210 210 210 -246 246 246 253 253 253 253 253 253 182 182 182 - 6 6 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 62 62 62 - 74 74 74 34 34 34 14 14 14 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 10 10 10 22 22 22 54 54 54 - 94 94 94 18 18 18 2 2 6 46 46 46 -234 234 234 221 221 221 190 190 190 190 190 190 -190 190 190 187 187 187 187 187 187 190 190 190 -190 190 190 195 195 195 214 214 214 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 - 82 82 82 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 14 14 14 - 86 86 86 54 54 54 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 18 18 18 46 46 46 90 90 90 - 46 46 46 18 18 18 6 6 6 182 182 182 -253 253 253 246 246 246 206 206 206 190 190 190 -190 190 190 190 190 190 190 190 190 190 190 190 -206 206 206 231 231 231 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -202 202 202 14 14 14 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 42 42 42 86 86 86 42 42 42 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 14 14 14 38 38 38 74 74 74 66 66 66 - 2 2 6 6 6 6 90 90 90 250 250 250 -253 253 253 253 253 253 238 238 238 198 198 198 -190 190 190 190 190 190 195 195 195 221 221 221 -246 246 246 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 82 82 82 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 78 78 78 70 70 70 34 34 34 - 14 14 14 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 34 34 34 66 66 66 78 78 78 6 6 6 - 2 2 6 18 18 18 218 218 218 253 253 253 -253 253 253 253 253 253 253 253 253 246 246 246 -226 226 226 231 231 231 246 246 246 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 178 178 178 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 18 18 18 90 90 90 62 62 62 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 10 10 10 26 26 26 - 58 58 58 90 90 90 18 18 18 2 2 6 - 2 2 6 110 110 110 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 231 231 231 18 18 18 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 18 18 18 94 94 94 - 54 54 54 26 26 26 10 10 10 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 22 22 22 50 50 50 - 90 90 90 26 26 26 2 2 6 2 2 6 - 14 14 14 195 195 195 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 242 242 242 54 54 54 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 38 38 38 - 86 86 86 50 50 50 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 14 14 14 38 38 38 82 82 82 - 34 34 34 2 2 6 2 2 6 2 2 6 - 42 42 42 195 195 195 246 246 246 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -242 242 242 242 242 242 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 250 250 250 246 246 246 238 238 238 -226 226 226 231 231 231 101 101 101 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 38 38 38 82 82 82 42 42 42 14 14 14 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 10 10 10 26 26 26 62 62 62 66 66 66 - 2 2 6 2 2 6 2 2 6 6 6 6 - 70 70 70 170 170 170 206 206 206 234 234 234 -246 246 246 250 250 250 250 250 250 238 238 238 -226 226 226 231 231 231 238 238 238 250 250 250 -250 250 250 250 250 250 246 246 246 231 231 231 -214 214 214 206 206 206 202 202 202 202 202 202 -198 198 198 202 202 202 182 182 182 18 18 18 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 62 62 62 66 66 66 30 30 30 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 14 14 14 42 42 42 82 82 82 18 18 18 - 2 2 6 2 2 6 2 2 6 10 10 10 - 94 94 94 182 182 182 218 218 218 242 242 242 -250 250 250 253 253 253 253 253 253 250 250 250 -234 234 234 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 246 246 246 -238 238 238 226 226 226 210 210 210 202 202 202 -195 195 195 195 195 195 210 210 210 158 158 158 - 6 6 6 14 14 14 50 50 50 14 14 14 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 86 86 86 46 46 46 - 18 18 18 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 22 22 22 54 54 54 70 70 70 2 2 6 - 2 2 6 10 10 10 2 2 6 22 22 22 -166 166 166 231 231 231 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -242 242 242 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 246 246 246 -231 231 231 206 206 206 198 198 198 226 226 226 - 94 94 94 2 2 6 6 6 6 38 38 38 - 30 30 30 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 62 62 62 66 66 66 - 26 26 26 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 74 74 74 50 50 50 2 2 6 - 26 26 26 26 26 26 2 2 6 106 106 106 -238 238 238 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 246 246 246 218 218 218 202 202 202 -210 210 210 14 14 14 2 2 6 2 2 6 - 30 30 30 22 22 22 2 2 6 2 2 6 - 2 2 6 2 2 6 18 18 18 86 86 86 - 42 42 42 14 14 14 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 42 42 42 90 90 90 22 22 22 2 2 6 - 42 42 42 2 2 6 18 18 18 218 218 218 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 250 250 250 221 221 221 -218 218 218 101 101 101 2 2 6 14 14 14 - 18 18 18 38 38 38 10 10 10 2 2 6 - 2 2 6 2 2 6 2 2 6 78 78 78 - 58 58 58 22 22 22 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 54 54 54 82 82 82 2 2 6 26 26 26 - 22 22 22 2 2 6 123 123 123 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -238 238 238 198 198 198 6 6 6 38 38 38 - 58 58 58 26 26 26 38 38 38 2 2 6 - 2 2 6 2 2 6 2 2 6 46 46 46 - 78 78 78 30 30 30 10 10 10 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 10 10 10 30 30 30 - 74 74 74 58 58 58 2 2 6 42 42 42 - 2 2 6 22 22 22 231 231 231 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 246 246 246 46 46 46 38 38 38 - 42 42 42 14 14 14 38 38 38 14 14 14 - 2 2 6 2 2 6 2 2 6 6 6 6 - 86 86 86 46 46 46 14 14 14 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 14 14 14 42 42 42 - 90 90 90 18 18 18 18 18 18 26 26 26 - 2 2 6 116 116 116 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 250 250 250 238 238 238 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 94 94 94 6 6 6 - 2 2 6 2 2 6 10 10 10 34 34 34 - 2 2 6 2 2 6 2 2 6 2 2 6 - 74 74 74 58 58 58 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 10 10 10 26 26 26 66 66 66 - 82 82 82 2 2 6 38 38 38 6 6 6 - 14 14 14 210 210 210 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 246 246 246 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 144 144 144 2 2 6 - 2 2 6 2 2 6 2 2 6 46 46 46 - 2 2 6 2 2 6 2 2 6 2 2 6 - 42 42 42 74 74 74 30 30 30 10 10 10 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 14 14 14 42 42 42 90 90 90 - 26 26 26 6 6 6 42 42 42 2 2 6 - 74 74 74 250 250 250 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 242 242 242 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 182 182 182 2 2 6 - 2 2 6 2 2 6 2 2 6 46 46 46 - 2 2 6 2 2 6 2 2 6 2 2 6 - 10 10 10 86 86 86 38 38 38 10 10 10 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 10 10 10 26 26 26 66 66 66 82 82 82 - 2 2 6 22 22 22 18 18 18 2 2 6 -149 149 149 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 206 206 206 2 2 6 - 2 2 6 2 2 6 2 2 6 38 38 38 - 2 2 6 2 2 6 2 2 6 2 2 6 - 6 6 6 86 86 86 46 46 46 14 14 14 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 18 18 18 46 46 46 86 86 86 18 18 18 - 2 2 6 34 34 34 10 10 10 6 6 6 -210 210 210 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 221 221 221 6 6 6 - 2 2 6 2 2 6 6 6 6 30 30 30 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 82 82 82 54 54 54 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 26 26 26 66 66 66 62 62 62 2 2 6 - 2 2 6 38 38 38 10 10 10 26 26 26 -238 238 238 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 238 238 238 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 6 6 6 - 2 2 6 2 2 6 10 10 10 30 30 30 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 58 58 58 22 22 22 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 78 78 78 6 6 6 2 2 6 - 2 2 6 46 46 46 14 14 14 42 42 42 -246 246 246 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 10 10 10 - 2 2 6 2 2 6 22 22 22 14 14 14 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 62 62 62 22 22 22 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 50 50 50 74 74 74 2 2 6 2 2 6 - 14 14 14 70 70 70 34 34 34 62 62 62 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 14 14 14 - 2 2 6 2 2 6 30 30 30 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 62 62 62 22 22 22 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 54 54 54 62 62 62 2 2 6 2 2 6 - 2 2 6 30 30 30 46 46 46 70 70 70 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 226 226 226 10 10 10 - 2 2 6 6 6 6 30 30 30 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 58 58 58 22 22 22 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 22 22 22 - 58 58 58 62 62 62 2 2 6 2 2 6 - 2 2 6 2 2 6 30 30 30 78 78 78 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 206 206 206 2 2 6 - 22 22 22 34 34 34 18 14 6 22 22 22 - 26 26 26 18 18 18 6 6 6 2 2 6 - 2 2 6 82 82 82 54 54 54 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 26 26 26 - 62 62 62 106 106 106 74 54 14 185 133 11 -210 162 10 121 92 8 6 6 6 62 62 62 -238 238 238 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 158 158 158 18 18 18 - 14 14 14 2 2 6 2 2 6 2 2 6 - 6 6 6 18 18 18 66 66 66 38 38 38 - 6 6 6 94 94 94 50 50 50 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 10 10 10 10 10 10 18 18 18 38 38 38 - 78 78 78 142 134 106 216 158 10 242 186 14 -246 190 14 246 190 14 156 118 10 10 10 10 - 90 90 90 238 238 238 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 250 250 250 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 246 230 190 -238 204 91 238 204 91 181 142 44 37 26 9 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 38 38 38 46 46 46 - 26 26 26 106 106 106 54 54 54 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 14 14 14 22 22 22 - 30 30 30 38 38 38 50 50 50 70 70 70 -106 106 106 190 142 34 226 170 11 242 186 14 -246 190 14 246 190 14 246 190 14 154 114 10 - 6 6 6 74 74 74 226 226 226 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 250 250 250 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 228 184 62 -241 196 14 241 208 19 232 195 16 38 30 10 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 30 30 30 26 26 26 -203 166 17 154 142 90 66 66 66 26 26 26 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 18 18 18 38 38 38 58 58 58 - 78 78 78 86 86 86 101 101 101 123 123 123 -175 146 61 210 150 10 234 174 13 246 186 14 -246 190 14 246 190 14 246 190 14 238 190 10 -102 78 10 2 2 6 46 46 46 198 198 198 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 224 178 62 -242 186 14 241 196 14 210 166 10 22 18 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 6 6 6 121 92 8 -238 202 15 232 195 16 82 82 82 34 34 34 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 14 14 14 38 38 38 70 70 70 154 122 46 -190 142 34 200 144 11 197 138 11 197 138 11 -213 154 11 226 170 11 242 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -225 175 15 46 32 6 2 2 6 22 22 22 -158 158 158 250 250 250 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 250 250 250 242 242 242 224 178 62 -239 182 13 236 186 11 213 154 11 46 32 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 61 42 6 225 175 15 -238 190 10 236 186 11 112 100 78 42 42 42 - 14 14 14 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 22 22 22 54 54 54 154 122 46 213 154 11 -226 170 11 230 174 11 226 170 11 226 170 11 -236 178 12 242 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -241 196 14 184 144 12 10 10 10 2 2 6 - 6 6 6 116 116 116 242 242 242 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 231 231 231 198 198 198 214 170 54 -236 178 12 236 178 12 210 150 10 137 92 6 - 18 14 6 2 2 6 2 2 6 2 2 6 - 6 6 6 70 47 6 200 144 11 236 178 12 -239 182 13 239 182 13 124 112 88 58 58 58 - 22 22 22 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 70 70 70 180 133 36 226 170 11 -239 182 13 242 186 14 242 186 14 246 186 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 232 195 16 98 70 6 2 2 6 - 2 2 6 2 2 6 66 66 66 221 221 221 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 206 206 206 198 198 198 214 166 58 -230 174 11 230 174 11 216 158 10 192 133 9 -163 110 8 116 81 8 102 78 10 116 81 8 -167 114 7 197 138 11 226 170 11 239 182 13 -242 186 14 242 186 14 162 146 94 78 78 78 - 34 34 34 14 14 14 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 30 30 30 78 78 78 190 142 34 226 170 11 -239 182 13 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 241 196 14 203 166 17 22 18 6 - 2 2 6 2 2 6 2 2 6 38 38 38 -218 218 218 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 206 206 206 198 198 198 202 162 69 -226 170 11 236 178 12 224 166 10 210 150 10 -200 144 11 197 138 11 192 133 9 197 138 11 -210 150 10 226 170 11 242 186 14 246 190 14 -246 190 14 246 186 14 225 175 15 124 112 88 - 62 62 62 30 30 30 14 14 14 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 78 78 78 174 135 50 224 166 10 -239 182 13 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 241 196 14 139 102 15 - 2 2 6 2 2 6 2 2 6 2 2 6 - 78 78 78 250 250 250 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 214 214 214 198 198 198 190 150 46 -219 162 10 236 178 12 234 174 13 224 166 10 -216 158 10 213 154 11 213 154 11 216 158 10 -226 170 11 239 182 13 246 190 14 246 190 14 -246 190 14 246 190 14 242 186 14 206 162 42 -101 101 101 58 58 58 30 30 30 14 14 14 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 74 74 74 174 135 50 216 158 10 -236 178 12 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 241 196 14 226 184 13 - 61 42 6 2 2 6 2 2 6 2 2 6 - 22 22 22 238 238 238 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 226 226 226 187 187 187 180 133 36 -216 158 10 236 178 12 239 182 13 236 178 12 -230 174 11 226 170 11 226 170 11 230 174 11 -236 178 12 242 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 186 14 239 182 13 -206 162 42 106 106 106 66 66 66 34 34 34 - 14 14 14 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 26 26 26 70 70 70 163 133 67 213 154 11 -236 178 12 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 241 196 14 -190 146 13 18 14 6 2 2 6 2 2 6 - 46 46 46 246 246 246 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 221 221 221 86 86 86 156 107 11 -216 158 10 236 178 12 242 186 14 246 186 14 -242 186 14 239 182 13 239 182 13 242 186 14 -242 186 14 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -242 186 14 225 175 15 142 122 72 66 66 66 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 26 26 26 70 70 70 163 133 67 210 150 10 -236 178 12 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -232 195 16 121 92 8 34 34 34 106 106 106 -221 221 221 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -242 242 242 82 82 82 18 14 6 163 110 8 -216 158 10 236 178 12 242 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 242 186 14 163 133 67 - 46 46 46 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 78 78 78 163 133 67 210 150 10 -236 178 12 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -241 196 14 215 174 15 190 178 144 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 218 218 218 - 58 58 58 2 2 6 22 18 6 167 114 7 -216 158 10 236 178 12 246 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 186 14 242 186 14 190 150 46 - 54 54 54 22 22 22 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 38 38 38 86 86 86 180 133 36 213 154 11 -236 178 12 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 232 195 16 190 146 13 214 214 214 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 250 250 250 170 170 170 26 26 26 - 2 2 6 2 2 6 37 26 9 163 110 8 -219 162 10 239 182 13 246 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 186 14 236 178 12 224 166 10 142 122 72 - 46 46 46 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 50 50 50 109 106 95 192 133 9 224 166 10 -242 186 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -242 186 14 226 184 13 210 162 10 142 110 46 -226 226 226 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -198 198 198 66 66 66 2 2 6 2 2 6 - 2 2 6 2 2 6 50 34 6 156 107 11 -219 162 10 239 182 13 246 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 242 186 14 -234 174 13 213 154 11 154 122 46 66 66 66 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 22 22 22 - 58 58 58 154 121 60 206 145 10 234 174 13 -242 186 14 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 186 14 236 178 12 210 162 10 163 110 8 - 61 42 6 138 138 138 218 218 218 250 250 250 -253 253 253 253 253 253 253 253 253 250 250 250 -242 242 242 210 210 210 144 144 144 66 66 66 - 6 6 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 61 42 6 163 110 8 -216 158 10 236 178 12 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 239 182 13 230 174 11 216 158 10 -190 142 34 124 112 88 70 70 70 38 38 38 - 18 18 18 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 22 22 22 - 62 62 62 168 124 44 206 145 10 224 166 10 -236 178 12 239 182 13 242 186 14 242 186 14 -246 186 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 236 178 12 216 158 10 175 118 6 - 80 54 7 2 2 6 6 6 6 30 30 30 - 54 54 54 62 62 62 50 50 50 38 38 38 - 14 14 14 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 80 54 7 167 114 7 -213 154 11 236 178 12 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 242 186 14 239 182 13 239 182 13 -230 174 11 210 150 10 174 135 50 124 112 88 - 82 82 82 54 54 54 34 34 34 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 50 50 50 158 118 36 192 133 9 200 144 11 -216 158 10 219 162 10 224 166 10 226 170 11 -230 174 11 236 178 12 239 182 13 239 182 13 -242 186 14 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 186 14 230 174 11 210 150 10 163 110 8 -104 69 6 10 10 10 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 91 60 6 167 114 7 -206 145 10 230 174 11 242 186 14 246 190 14 -246 190 14 246 190 14 246 186 14 242 186 14 -239 182 13 230 174 11 224 166 10 213 154 11 -180 133 36 124 112 88 86 86 86 58 58 58 - 38 38 38 22 22 22 10 10 10 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 34 34 34 70 70 70 138 110 50 158 118 36 -167 114 7 180 123 7 192 133 9 197 138 11 -200 144 11 206 145 10 213 154 11 219 162 10 -224 166 10 230 174 11 239 182 13 242 186 14 -246 186 14 246 186 14 246 186 14 246 186 14 -239 182 13 216 158 10 185 133 11 152 99 6 -104 69 6 18 14 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 80 54 7 152 99 6 -192 133 9 219 162 10 236 178 12 239 182 13 -246 186 14 242 186 14 239 182 13 236 178 12 -224 166 10 206 145 10 192 133 9 154 121 60 - 94 94 94 62 62 62 42 42 42 22 22 22 - 14 14 14 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 18 18 18 34 34 34 58 58 58 78 78 78 -101 98 89 124 112 88 142 110 46 156 107 11 -163 110 8 167 114 7 175 118 6 180 123 7 -185 133 11 197 138 11 210 150 10 219 162 10 -226 170 11 236 178 12 236 178 12 234 174 13 -219 162 10 197 138 11 163 110 8 130 83 6 - 91 60 6 10 10 10 2 2 6 2 2 6 - 18 18 18 38 38 38 38 38 38 38 38 38 - 38 38 38 38 38 38 38 38 38 38 38 38 - 38 38 38 38 38 38 26 26 26 2 2 6 - 2 2 6 6 6 6 70 47 6 137 92 6 -175 118 6 200 144 11 219 162 10 230 174 11 -234 174 13 230 174 11 219 162 10 210 150 10 -192 133 9 163 110 8 124 112 88 82 82 82 - 50 50 50 30 30 30 14 14 14 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 14 14 14 22 22 22 34 34 34 - 42 42 42 58 58 58 74 74 74 86 86 86 -101 98 89 122 102 70 130 98 46 121 87 25 -137 92 6 152 99 6 163 110 8 180 123 7 -185 133 11 197 138 11 206 145 10 200 144 11 -180 123 7 156 107 11 130 83 6 104 69 6 - 50 34 6 54 54 54 110 110 110 101 98 89 - 86 86 86 82 82 82 78 78 78 78 78 78 - 78 78 78 78 78 78 78 78 78 78 78 78 - 78 78 78 82 82 82 86 86 86 94 94 94 -106 106 106 101 101 101 86 66 34 124 80 6 -156 107 11 180 123 7 192 133 9 200 144 11 -206 145 10 200 144 11 192 133 9 175 118 6 -139 102 15 109 106 95 70 70 70 42 42 42 - 22 22 22 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 10 10 10 - 14 14 14 22 22 22 30 30 30 38 38 38 - 50 50 50 62 62 62 74 74 74 90 90 90 -101 98 89 112 100 78 121 87 25 124 80 6 -137 92 6 152 99 6 152 99 6 152 99 6 -138 86 6 124 80 6 98 70 6 86 66 30 -101 98 89 82 82 82 58 58 58 46 46 46 - 38 38 38 34 34 34 34 34 34 34 34 34 - 34 34 34 34 34 34 34 34 34 34 34 34 - 34 34 34 34 34 34 38 38 38 42 42 42 - 54 54 54 82 82 82 94 86 76 91 60 6 -134 86 6 156 107 11 167 114 7 175 118 6 -175 118 6 167 114 7 152 99 6 121 87 25 -101 98 89 62 62 62 34 34 34 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 6 6 6 10 10 10 - 18 18 18 22 22 22 30 30 30 42 42 42 - 50 50 50 66 66 66 86 86 86 101 98 89 -106 86 58 98 70 6 104 69 6 104 69 6 -104 69 6 91 60 6 82 62 34 90 90 90 - 62 62 62 38 38 38 22 22 22 14 14 14 - 10 10 10 10 10 10 10 10 10 10 10 10 - 10 10 10 10 10 10 6 6 6 10 10 10 - 10 10 10 10 10 10 10 10 10 14 14 14 - 22 22 22 42 42 42 70 70 70 89 81 66 - 80 54 7 104 69 6 124 80 6 137 92 6 -134 86 6 116 81 8 100 82 52 86 86 86 - 58 58 58 30 30 30 14 14 14 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 10 10 10 14 14 14 - 18 18 18 26 26 26 38 38 38 54 54 54 - 70 70 70 86 86 86 94 86 76 89 81 66 - 89 81 66 86 86 86 74 74 74 50 50 50 - 30 30 30 14 14 14 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 18 18 18 34 34 34 58 58 58 - 82 82 82 89 81 66 89 81 66 89 81 66 - 94 86 66 94 86 76 74 74 74 50 50 50 - 26 26 26 14 14 14 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 6 6 6 14 14 14 18 18 18 - 30 30 30 38 38 38 46 46 46 54 54 54 - 50 50 50 42 42 42 30 30 30 18 18 18 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 14 14 14 26 26 26 - 38 38 38 50 50 50 58 58 58 58 58 58 - 54 54 54 42 42 42 30 30 30 18 18 18 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 6 6 6 10 10 10 14 14 14 18 18 18 - 18 18 18 14 14 14 10 10 10 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 14 14 14 18 18 18 22 22 22 22 22 22 - 18 18 18 14 14 14 10 10 10 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 3 4 4 6 7 7 +8 10 10 8 10 10 6 8 8 6 7 7 3 4 4 2 2 2 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 4 5 5 17 18 17 +27 29 28 35 37 36 40 43 41 43 45 43 40 43 41 37 39 37 +32 34 33 27 30 29 23 25 24 17 21 21 15 18 18 12 15 15 +11 13 13 8 10 10 6 7 7 3 4 4 1 1 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 13 13 13 32 34 33 49 51 48 60 60 56 58 59 55 +55 57 54 55 56 53 49 51 48 43 45 43 39 40 39 33 37 35 +28 31 30 23 27 26 20 23 23 17 20 20 14 17 17 13 16 16 +11 14 14 10 13 13 10 12 12 9 11 11 8 10 10 6 7 7 +2 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 6 7 7 12 15 15 +12 15 15 8 9 9 2 3 3 0 0 0 1 1 1 25 27 26 +55 56 53 68 70 65 65 66 61 65 66 61 63 64 60 63 64 60 +58 59 55 51 52 50 47 48 46 41 42 42 35 37 36 30 32 31 +26 28 27 20 24 24 18 22 22 16 19 19 14 17 17 13 16 16 +12 15 15 11 14 14 10 13 13 10 12 12 9 11 11 8 10 10 +8 9 9 6 8 8 3 3 3 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 6 7 7 20 24 24 23 27 26 +23 27 26 18 22 22 11 13 13 23 24 24 61 63 57 72 73 67 +72 73 67 68 70 65 68 70 65 68 70 65 63 64 60 58 59 55 +55 56 53 47 48 46 41 42 42 35 37 36 30 32 31 26 28 27 +20 24 24 18 22 22 16 20 20 15 19 19 14 17 17 13 16 16 +12 15 15 12 15 15 11 14 14 10 13 13 10 12 12 9 11 11 +8 10 10 8 9 9 7 9 9 6 7 7 1 2 2 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 4 5 5 5 6 5 4 5 5 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 15 19 19 40 41 39 53 55 47 +33 36 34 27 30 29 51 52 50 72 73 67 72 73 67 72 73 67 +72 73 67 68 70 65 68 70 65 63 64 60 58 59 55 51 52 50 +47 48 46 40 43 41 33 37 35 30 32 31 26 28 27 20 24 24 +18 22 22 17 21 21 16 19 19 14 18 18 14 17 17 13 17 17 +13 16 16 12 15 15 12 15 15 11 14 14 10 13 13 10 12 12 +9 11 11 8 10 10 8 9 9 7 9 9 6 8 8 3 4 4 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +2 2 2 6 8 8 10 12 12 10 12 12 10 12 12 10 12 12 +6 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 20 23 23 71 71 57 131 127 93 +115 113 82 63 64 60 72 73 67 72 73 67 72 73 67 72 73 67 +68 70 65 65 66 61 61 63 57 55 57 54 49 51 48 43 45 43 +39 40 39 33 36 34 28 31 30 23 27 26 20 24 24 20 23 23 +17 21 21 16 20 20 15 19 19 15 18 18 14 18 18 14 17 17 +13 17 17 13 16 16 12 15 15 12 15 15 11 14 14 10 13 13 +10 12 12 9 11 11 8 10 10 7 9 9 7 9 9 6 8 8 +4 5 5 0 0 0 0 0 0 0 0 0 1 1 1 6 7 7 +10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 +10 12 12 3 4 4 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 18 22 22 71 71 57 144 139 99 +84 83 72 68 70 65 72 73 67 72 73 67 68 70 65 65 66 61 +63 64 60 55 57 54 51 52 50 47 48 46 40 43 41 35 37 36 +30 32 31 27 29 28 23 27 26 20 24 24 18 22 22 17 21 21 +16 20 20 15 19 19 15 19 19 15 19 19 15 18 18 14 18 18 +14 17 17 13 17 17 13 16 16 12 15 15 12 15 15 11 14 14 +10 13 13 9 12 12 9 11 11 8 10 10 7 9 9 6 8 8 +6 8 8 3 4 4 0 0 0 2 2 2 8 10 10 10 12 12 +10 12 12 10 12 12 11 13 13 36 38 35 61 61 53 48 49 45 +10 12 12 7 9 9 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 15 19 19 61 61 53 84 83 72 +68 70 65 72 73 67 68 70 65 68 70 65 63 64 60 58 59 55 +51 52 50 47 48 46 41 42 42 37 39 37 32 35 33 28 31 30 +23 27 26 20 24 24 20 23 23 18 22 22 17 21 21 17 21 21 +17 21 21 17 21 21 17 20 20 16 20 20 16 20 20 16 19 19 +15 18 18 14 18 18 13 17 17 13 16 16 12 15 15 12 15 15 +11 14 14 10 13 13 9 12 12 9 11 11 8 10 10 7 9 9 +6 8 8 6 8 8 5 6 5 9 11 11 10 12 12 10 12 12 +19 20 18 82 81 62 149 145 103 160 154 106 142 137 94 96 95 69 +10 12 12 10 12 12 1 1 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 10 12 12 44 46 43 68 70 65 +72 73 67 68 70 65 68 70 65 63 64 60 55 57 54 49 51 48 +43 45 43 39 40 39 33 37 35 30 32 31 26 28 27 23 27 26 +20 24 24 18 22 22 18 22 22 18 22 22 18 22 22 20 23 23 +20 24 24 23 25 24 23 25 24 22 24 23 20 23 23 18 22 22 +17 20 20 15 19 19 15 18 18 14 17 17 13 16 16 12 15 15 +11 14 14 11 13 13 10 12 12 9 11 11 8 10 10 8 9 9 +7 9 9 7 9 9 10 12 12 10 12 12 10 12 12 71 71 57 +164 159 111 186 182 128 186 182 128 171 165 117 151 147 98 96 95 69 +10 12 12 10 12 12 3 3 3 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 8 10 10 63 64 60 68 70 65 +72 73 67 68 70 65 63 64 60 55 57 54 47 48 46 40 43 41 +33 37 35 30 32 31 27 29 28 23 27 26 20 24 24 20 23 23 +18 22 22 18 22 22 20 23 22 21 25 23 23 27 26 27 29 28 +28 31 30 31 33 31 31 33 31 31 33 31 28 31 30 26 28 27 +23 25 24 20 23 22 16 20 20 15 18 18 14 17 17 13 16 16 +12 15 15 11 14 14 10 13 13 10 12 12 9 11 11 8 10 10 +10 12 12 10 13 13 10 12 12 12 14 14 96 95 69 165 161 109 +186 182 128 192 187 134 192 187 134 176 171 126 160 154 106 103 101 77 +10 12 12 10 12 12 5 6 5 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 35 37 36 68 70 65 72 73 67 +68 70 65 65 66 61 58 59 55 49 51 48 40 43 41 33 37 35 +28 31 30 23 27 26 20 24 24 20 23 23 18 22 22 18 22 22 +18 22 22 20 23 23 23 27 26 27 30 29 32 35 33 37 39 37 +40 43 41 44 46 43 46 47 43 44 46 43 40 43 41 36 38 35 +31 33 31 27 29 28 22 24 23 17 21 21 15 18 18 14 17 17 +13 16 16 12 15 15 11 14 14 11 14 14 11 13 13 13 16 16 +13 16 16 11 14 14 10 12 12 79 78 62 142 137 94 164 159 111 +178 174 128 192 187 134 192 187 134 176 171 126 160 154 106 96 95 69 +10 12 12 10 12 12 6 7 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 55 57 54 68 70 65 72 73 67 +68 70 65 63 64 60 55 56 53 43 45 43 35 37 36 28 31 30 +23 27 26 20 24 24 18 22 22 17 21 21 17 21 21 17 21 21 +20 24 24 25 27 26 31 33 31 38 39 37 46 47 43 53 55 47 +61 61 53 66 65 55 66 65 55 66 65 55 61 61 53 53 55 47 +46 47 43 37 39 37 30 33 30 24 26 24 17 21 21 15 18 18 +13 17 17 12 15 15 12 15 15 13 16 16 14 18 18 14 18 18 +14 17 17 12 15 15 30 31 28 118 116 76 134 131 96 160 154 106 +174 170 121 178 174 128 178 174 128 171 165 117 151 147 98 96 95 69 +10 12 12 10 12 12 6 8 8 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 63 64 60 68 70 65 68 70 65 +65 66 61 58 59 55 49 51 48 39 40 39 30 32 31 23 27 26 +20 24 24 18 22 22 17 21 21 16 20 20 17 21 21 20 23 23 +25 27 26 32 35 33 43 44 41 53 55 47 66 65 55 75 75 61 +82 81 62 84 83 72 87 86 72 87 86 72 82 81 62 75 75 61 +66 65 55 53 55 47 40 41 39 31 33 31 23 25 24 17 20 20 +14 18 18 13 16 16 12 15 15 12 15 15 13 17 17 14 18 18 +14 18 18 13 16 16 46 47 43 96 95 69 125 122 87 142 137 94 +160 154 106 165 161 109 164 159 111 155 149 109 142 137 94 75 75 61 +10 12 12 10 12 12 6 8 8 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 60 60 56 68 70 65 68 70 65 +63 64 60 55 57 54 46 47 45 35 37 36 27 30 29 23 25 24 +18 22 22 17 21 21 16 20 20 17 21 21 18 22 22 23 27 26 +31 33 31 43 44 41 55 56 53 71 71 57 84 83 72 92 91 72 +103 101 77 92 91 72 82 81 62 82 81 62 87 86 72 92 91 72 +84 83 72 71 71 57 55 56 53 43 44 41 30 33 30 22 24 23 +16 19 19 14 17 17 12 15 15 12 15 15 13 16 16 14 18 18 +14 18 18 14 17 17 43 44 41 82 81 62 118 116 76 125 122 87 +142 137 94 144 139 99 144 139 99 134 131 96 118 116 76 53 55 47 +10 12 12 10 12 12 6 8 8 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 47 48 46 63 64 60 63 64 60 +55 57 54 49 51 48 40 43 41 32 34 33 26 28 27 20 24 24 +18 22 22 16 20 20 16 20 20 17 21 21 20 24 24 28 31 30 +40 41 39 53 55 47 75 75 61 90 89 73 87 86 72 48 49 45 +14 14 13 2 2 2 1 2 2 1 1 1 1 1 1 2 2 2 +19 20 18 43 44 41 66 65 55 53 55 47 38 39 37 26 28 27 +18 22 22 14 18 18 13 16 16 12 15 15 12 15 15 13 17 17 +14 18 18 14 18 18 30 31 28 66 65 55 96 95 69 103 101 77 +118 116 76 118 116 76 118 116 76 118 116 76 103 101 77 36 38 35 +10 12 12 10 12 12 6 7 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 28 31 30 55 57 54 51 52 50 +49 51 48 41 42 42 35 37 36 28 31 30 23 27 26 20 23 23 +17 21 21 16 20 20 16 20 20 18 22 22 23 27 26 33 36 34 +48 49 45 71 71 57 82 81 62 43 44 41 8 9 9 6 7 7 +6 7 7 6 7 7 6 7 7 5 6 5 4 5 5 3 4 4 +2 3 3 1 2 2 4 5 4 36 38 35 48 49 45 32 35 33 +21 25 23 16 19 19 13 17 17 12 15 15 12 15 15 13 16 16 +14 18 18 14 18 18 16 18 16 36 38 35 61 61 53 82 81 62 +96 95 69 96 95 69 96 95 69 96 95 69 79 78 62 19 20 18 +10 12 12 10 12 12 4 5 5 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 13 13 13 46 47 45 43 45 43 +40 43 41 35 37 36 30 32 31 23 27 26 20 24 24 18 22 22 +17 21 21 16 20 20 17 21 21 20 23 23 27 30 29 40 41 39 +61 61 53 53 55 47 16 17 16 9 11 11 10 12 12 10 12 12 +10 12 12 10 12 12 10 12 12 9 11 11 8 10 10 8 9 9 +6 8 8 5 6 5 4 5 5 2 3 3 19 20 18 38 39 37 +26 28 27 17 21 21 14 17 17 13 16 16 12 15 15 12 15 15 +13 17 17 14 18 18 12 15 15 13 12 7 30 31 28 46 47 43 +53 55 47 66 65 55 66 65 55 53 55 47 36 38 35 10 12 12 +10 12 12 10 12 12 2 3 3 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 1 33 37 35 35 37 36 +32 35 33 28 31 30 23 27 26 20 24 24 18 22 22 17 21 21 +16 20 20 16 20 20 17 21 21 21 25 23 31 33 31 44 46 43 +31 33 31 11 13 13 12 14 14 12 15 15 13 16 16 14 17 17 +14 17 17 14 17 17 14 17 17 13 16 16 12 15 15 12 14 14 +11 13 13 9 11 11 8 10 10 6 8 8 4 5 5 17 18 17 +30 33 30 20 23 22 15 18 18 13 16 16 12 15 15 12 14 14 +13 16 16 14 17 17 14 18 18 11 12 11 7 7 5 16 17 12 +21 22 20 30 31 28 25 27 25 21 22 20 14 14 13 10 12 12 +10 12 12 9 11 11 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 18 22 22 27 30 29 +27 29 28 40 41 39 53 55 47 53 55 47 53 55 47 46 47 43 +25 27 25 16 20 20 17 21 21 23 25 24 31 33 31 20 20 20 +12 15 15 14 17 17 15 19 19 16 20 20 17 21 21 18 22 22 +18 22 22 18 22 22 18 22 22 17 21 21 17 21 21 16 19 19 +15 18 18 13 16 16 12 15 15 10 12 12 8 10 10 6 8 8 +21 22 21 22 24 23 15 19 19 13 17 17 13 16 16 12 15 15 +12 15 15 13 17 17 14 18 18 14 18 18 13 15 14 10 9 6 +7 7 5 7 7 5 7 7 5 9 11 11 10 12 12 10 12 12 +10 12 12 6 7 7 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 16 17 12 82 81 62 +118 116 76 118 116 76 161 156 96 161 156 96 161 156 96 118 116 76 +118 116 76 96 95 69 53 55 47 22 24 23 14 17 17 13 16 16 +15 19 19 17 21 21 18 22 22 20 24 24 20 24 24 23 27 26 +23 27 26 23 27 26 23 27 26 23 27 26 23 27 26 20 24 24 +20 23 23 17 21 21 16 19 19 14 17 17 12 15 15 10 12 12 +9 11 11 20 23 22 16 19 19 14 17 17 13 16 16 12 15 15 +11 14 14 13 16 16 14 17 17 14 18 18 14 17 17 12 15 15 +10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 +9 11 11 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 53 55 47 161 156 96 +161 156 96 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 161 156 96 118 116 76 96 95 69 21 22 20 16 19 19 +18 22 22 20 24 24 23 27 26 23 27 26 26 28 27 27 30 29 +27 30 29 18 22 22 12 14 14 8 10 10 9 11 11 17 21 21 +23 27 26 23 27 26 20 24 24 18 22 22 16 20 20 14 17 17 +12 14 14 14 17 17 16 20 20 14 17 17 13 17 17 13 16 16 +12 15 15 12 15 15 13 17 17 14 18 18 14 17 17 13 16 16 +11 13 13 10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 +4 5 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 13 12 7 118 116 76 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 161 156 96 118 116 76 30 31 28 +20 24 24 23 27 26 27 30 29 28 31 30 30 32 31 23 27 26 +16 19 19 17 21 21 12 15 15 9 11 11 10 12 12 9 11 11 +20 24 24 28 31 30 26 28 27 23 27 26 20 24 24 17 21 21 +15 19 19 13 16 16 16 19 19 14 18 18 14 17 17 13 16 16 +12 15 15 11 14 14 13 16 16 14 17 17 14 18 18 14 17 17 +12 15 15 10 12 12 10 12 12 10 12 12 10 12 12 8 9 9 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 82 81 62 161 156 96 230 229 82 +230 229 82 233 233 100 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 118 116 76 +27 29 28 27 30 29 30 32 31 30 32 31 23 27 26 20 24 24 +26 28 27 17 21 21 6 7 7 72 73 67 145 141 105 15 15 15 +14 17 17 33 37 35 30 32 31 28 31 30 26 28 27 23 27 26 +20 23 23 16 20 20 15 19 19 14 18 18 14 17 17 13 16 16 +12 15 15 11 14 14 12 15 15 13 17 17 14 18 18 14 17 17 +13 16 16 11 13 13 10 12 12 10 12 12 9 11 11 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 16 17 12 161 156 96 230 229 82 230 229 82 +243 242 120 235 234 117 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 +82 81 62 28 31 30 28 31 30 27 30 29 28 31 30 30 32 31 +33 37 35 13 16 16 3 3 3 105 104 92 210 208 158 12 14 14 +17 21 21 33 37 35 33 37 35 32 35 33 30 32 31 27 30 29 +23 27 26 20 23 23 17 20 20 15 18 18 14 18 18 13 17 17 +13 16 16 12 15 15 11 14 14 13 16 16 14 17 17 14 18 18 +13 17 17 12 15 15 10 12 12 10 12 12 3 4 4 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 96 95 69 230 229 82 230 229 82 244 244 132 +241 241 143 243 242 120 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +161 156 96 46 47 43 32 35 33 33 37 35 33 37 35 33 37 35 +40 43 41 23 27 26 1 1 1 2 2 2 24 26 24 14 17 17 +23 27 26 33 37 35 33 37 35 33 37 35 33 37 35 30 32 31 +27 30 29 23 27 26 20 23 23 15 18 18 14 18 18 14 17 17 +13 16 16 12 15 15 11 14 14 12 15 15 13 17 17 14 17 17 +14 17 17 13 16 16 11 13 13 6 8 8 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 16 17 12 161 156 96 230 229 82 235 234 117 239 239 170 +239 239 170 236 236 101 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 118 116 76 33 37 35 33 37 35 37 39 37 37 39 37 +43 45 43 49 51 48 20 24 24 8 10 10 17 20 20 35 37 36 +33 37 35 40 43 41 37 39 37 35 37 36 33 37 35 33 37 35 +30 32 31 27 30 29 23 27 26 15 19 19 14 18 18 14 17 17 +13 17 17 13 16 16 12 15 15 11 14 14 13 16 16 14 17 17 +14 17 17 13 17 17 11 14 14 4 5 5 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 96 95 69 230 229 82 230 229 82 239 239 170 251 251 187 +241 241 143 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 161 156 96 36 38 35 33 37 35 33 37 35 33 37 35 +37 39 37 47 48 46 55 57 54 55 57 54 49 51 48 43 45 43 +43 45 43 43 45 43 40 43 41 40 43 41 37 39 37 33 37 35 +33 37 35 28 31 30 26 28 27 16 20 20 15 18 18 14 18 18 +14 17 17 13 16 16 12 15 15 11 14 14 12 15 15 13 17 17 +14 17 17 14 17 17 8 10 10 5 7 7 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +16 17 12 230 229 82 230 229 82 243 242 120 251 251 187 251 251 187 +246 246 123 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 66 65 55 30 32 31 32 35 33 33 37 35 +33 37 35 37 39 37 40 43 41 47 48 46 49 51 48 51 52 50 +55 57 54 55 57 54 51 52 50 47 48 46 43 45 43 39 40 39 +33 37 35 30 32 31 26 28 27 17 21 21 15 19 19 14 18 18 +14 17 17 13 16 16 12 15 15 12 14 14 11 14 14 13 16 16 +14 17 17 12 15 15 7 9 9 6 8 8 1 1 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +96 95 69 230 229 82 230 229 82 239 239 170 251 251 187 239 239 170 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 96 95 69 27 30 29 28 31 30 30 32 31 +33 37 35 40 43 41 46 47 45 55 57 54 63 64 60 72 73 67 +72 73 67 72 73 67 72 73 67 65 66 61 55 57 54 47 48 46 +39 40 39 32 35 33 27 30 29 17 21 21 15 19 19 15 18 18 +14 18 18 13 17 17 13 16 16 12 15 15 11 14 14 12 14 14 +13 16 16 9 11 11 7 9 9 9 11 11 66 65 55 115 113 82 +21 22 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 12 7 +230 229 82 230 229 82 236 236 101 251 251 187 251 251 187 246 246 123 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 118 116 76 23 27 26 26 28 27 32 35 33 +51 52 50 90 89 73 110 109 94 145 141 105 168 163 120 177 172 135 +177 172 135 188 184 146 188 184 146 181 176 137 194 191 148 188 184 146 +184 179 149 188 184 146 188 184 146 156 151 111 177 172 135 181 176 137 +177 172 135 168 163 120 168 163 120 158 153 112 156 151 111 158 153 112 +156 151 111 158 153 112 177 172 135 188 184 146 188 184 146 194 189 146 +36 38 35 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 82 81 62 +230 229 82 230 229 82 244 244 132 251 251 187 244 244 132 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 82 81 62 +96 95 69 230 229 82 181 178 103 110 109 94 156 151 111 188 184 146 +188 184 146 197 193 154 188 184 146 184 181 136 188 184 146 168 163 120 +168 163 120 178 174 128 156 151 111 158 153 112 174 170 121 156 151 111 +156 151 111 158 153 112 156 151 111 168 163 120 178 174 128 181 176 137 +176 171 126 178 174 128 184 181 136 176 171 126 178 174 128 184 181 136 +176 171 126 178 174 128 184 181 136 164 159 111 155 149 109 96 95 69 +1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 161 156 96 +230 229 82 230 229 82 244 244 132 244 244 132 236 236 101 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 46 47 43 82 81 62 +158 153 112 197 193 154 194 189 146 184 181 136 188 184 146 168 163 120 +156 151 111 137 133 100 131 127 93 137 133 100 137 133 100 158 153 112 +121 119 87 137 133 100 156 151 111 145 141 105 99 98 80 84 83 72 +63 64 60 52 53 49 40 43 41 33 36 34 36 38 35 36 38 35 +38 39 37 43 44 41 43 44 41 46 47 43 48 49 45 48 49 45 +46 47 43 36 38 35 30 31 28 19 20 18 6 7 7 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 36 38 35 230 229 82 +230 229 82 230 229 82 246 246 123 236 236 101 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 53 55 47 121 119 87 +176 171 126 171 165 117 161 156 96 82 81 62 53 55 47 33 37 35 +39 40 39 63 64 60 99 98 80 121 119 87 137 133 100 177 172 135 +176 171 126 184 181 136 131 127 93 131 127 93 110 109 94 84 83 72 +51 52 50 39 40 39 27 29 28 18 22 22 16 19 19 15 19 19 +15 19 19 14 18 18 14 17 17 13 16 16 12 15 15 11 14 14 +10 13 13 9 12 12 9 11 11 8 9 9 7 9 9 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 118 116 76 230 229 82 +230 229 82 230 229 82 236 236 101 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 96 95 69 71 71 57 +36 38 35 118 116 76 118 116 76 12 15 15 15 18 18 20 24 24 +33 37 35 55 56 53 84 83 72 110 109 94 145 141 105 110 109 94 +168 163 120 121 119 87 156 151 111 131 127 93 87 86 72 61 63 57 +47 48 46 28 31 30 18 22 22 15 19 19 15 18 18 15 19 19 +15 19 19 14 18 18 14 17 17 13 17 17 13 16 16 12 15 15 +11 13 13 10 12 12 9 11 11 8 10 10 7 9 9 3 3 3 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 0 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 +161 156 96 230 229 82 118 116 76 11 14 14 14 17 17 18 22 22 +27 30 29 40 43 41 60 60 56 84 83 72 105 104 92 110 109 94 +110 109 94 110 109 94 99 98 80 90 89 73 68 70 65 47 48 46 +32 34 33 23 25 24 20 23 23 17 21 21 15 19 19 14 17 17 +15 19 19 15 18 18 14 18 18 13 17 17 13 16 16 12 15 15 +11 14 14 10 12 12 9 11 11 8 10 10 7 9 9 4 5 5 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 16 17 12 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 161 156 96 118 116 76 11 13 13 13 16 16 15 19 19 +20 24 24 30 32 31 40 43 41 51 52 50 63 64 60 72 73 67 +65 66 61 65 66 61 65 66 61 55 57 54 46 47 45 33 37 35 +27 29 28 20 24 24 17 21 21 16 20 20 16 20 20 15 19 19 +15 19 19 15 19 19 14 18 18 14 17 17 13 16 16 12 15 15 +11 14 14 10 13 13 9 12 12 8 10 10 7 9 9 6 7 7 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 53 55 47 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +161 156 96 118 116 76 53 55 47 10 13 13 12 15 15 14 17 17 +17 20 20 20 24 24 27 29 28 32 34 33 37 39 37 40 43 41 +43 45 43 41 42 42 35 37 36 30 32 31 28 31 30 23 27 26 +20 23 23 17 21 21 16 20 20 16 20 20 16 20 20 16 19 19 +15 19 19 15 19 19 14 18 18 14 17 17 13 16 16 12 15 15 +11 14 14 10 13 13 9 12 12 9 11 11 8 10 10 10 12 12 +1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 82 81 62 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 161 156 96 +118 116 76 82 81 62 13 14 12 10 13 13 12 15 15 13 17 17 +15 19 19 16 20 20 20 23 23 20 24 24 23 27 26 26 28 27 +26 28 27 26 28 27 23 27 26 18 22 22 20 23 23 17 21 21 +17 21 21 16 20 20 16 20 20 16 20 20 16 20 20 16 19 19 +15 19 19 15 19 19 15 18 18 14 17 17 13 17 17 13 16 16 +12 15 15 12 14 14 12 14 14 12 14 14 12 14 14 23 24 24 +6 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 118 116 76 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 161 156 96 161 156 96 118 116 76 +71 71 57 13 14 12 9 12 12 10 13 13 12 15 15 13 17 17 +15 18 18 15 19 19 16 20 20 17 21 21 17 21 21 18 22 22 +18 22 22 18 22 22 17 21 21 16 19 19 15 18 18 14 18 18 +16 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +15 19 19 15 19 19 15 18 18 14 18 18 16 20 20 23 25 24 +17 21 21 25 27 26 47 48 46 47 48 46 51 52 50 72 73 67 +33 36 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 118 116 76 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 161 156 96 118 116 76 118 116 76 46 47 43 +9 11 11 9 11 11 10 12 12 11 13 13 12 15 15 14 17 17 +15 18 18 15 19 19 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +15 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +15 19 19 16 20 20 20 24 24 55 56 53 32 34 33 84 83 72 +90 89 73 110 109 94 110 109 94 105 104 92 110 109 94 110 109 94 +72 73 67 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 96 95 69 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 161 156 96 118 116 76 82 81 62 16 17 12 9 11 11 +9 11 11 9 12 12 10 13 13 12 14 14 13 16 16 14 18 18 +15 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 19 19 33 36 34 99 98 80 156 151 111 145 141 105 184 179 149 +168 163 120 184 179 149 177 172 135 156 151 111 145 141 105 110 109 94 +90 89 73 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 71 71 57 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 161 156 96 230 229 82 230 229 82 230 229 82 161 156 96 +118 116 76 82 81 62 30 31 28 9 11 11 9 11 11 9 11 11 +10 12 12 10 13 13 11 14 14 13 16 16 14 17 17 15 18 18 +15 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +18 22 22 58 59 55 137 133 100 197 193 154 214 212 158 210 208 158 +197 193 154 184 179 149 184 179 149 137 133 100 110 109 94 99 98 80 +84 83 72 10 10 9 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 16 17 12 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 +161 156 96 161 156 96 161 156 96 161 156 96 118 116 76 71 71 57 +21 22 20 12 14 14 11 13 13 10 12 12 10 12 12 10 13 13 +11 13 13 12 15 15 13 16 16 14 17 17 14 18 18 15 19 19 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 17 21 21 +23 27 26 84 83 72 184 179 149 251 251 187 210 208 158 184 179 149 +184 179 149 156 151 111 110 109 94 84 83 72 63 64 60 51 52 50 +18 22 22 6 8 8 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 118 116 76 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 161 156 96 +161 156 96 161 156 96 118 116 76 53 55 47 20 23 22 16 19 19 +13 16 16 12 15 15 12 14 14 11 14 14 11 14 14 11 14 14 +12 15 15 13 16 16 14 17 17 15 19 19 16 20 20 17 21 21 +23 27 26 18 22 22 20 24 24 23 27 26 30 32 31 17 21 21 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +23 27 26 33 37 35 137 133 100 156 151 111 158 153 112 105 104 92 +105 104 92 68 70 65 39 40 39 18 22 22 12 14 14 12 15 15 +9 11 11 4 5 5 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 16 17 12 230 229 82 +230 229 82 230 229 82 230 229 82 161 156 96 118 116 76 118 116 76 +118 116 76 66 65 55 43 45 43 32 34 33 25 27 26 20 23 22 +17 20 20 15 18 18 14 17 17 15 18 18 13 16 16 14 17 17 +14 18 18 16 20 20 32 34 33 55 57 54 58 59 55 72 73 67 +105 104 92 55 57 54 65 66 61 63 64 60 40 43 41 33 37 35 +41 42 42 20 24 24 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +17 21 21 26 28 27 30 32 31 35 37 36 68 70 65 39 40 39 +23 27 26 15 18 18 13 16 16 11 14 14 9 12 12 8 10 10 +7 9 9 6 7 7 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 36 38 35 +230 229 82 230 229 82 230 229 82 96 95 69 30 31 28 49 51 48 +90 89 73 68 70 65 55 57 54 47 48 46 47 48 46 43 45 43 +32 34 33 43 45 43 43 45 43 23 27 26 25 27 26 40 43 41 +40 43 41 90 89 73 110 109 94 145 141 105 156 151 111 156 151 111 +184 179 149 184 179 149 177 172 135 184 179 149 137 133 100 84 83 72 +105 104 92 63 64 60 49 51 48 47 48 46 28 31 30 18 22 22 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 15 19 19 15 19 19 15 19 19 18 22 22 15 19 19 +13 16 16 12 15 15 11 14 14 10 13 13 9 12 12 9 11 11 +8 10 10 6 8 8 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +30 31 28 230 229 82 71 71 57 2 2 1 0 0 0 58 59 55 +105 104 92 84 83 72 65 66 61 84 83 72 110 109 94 110 109 94 +145 141 105 105 104 92 110 109 94 110 109 94 84 83 72 110 109 94 +158 153 112 197 193 154 197 193 154 239 239 170 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 210 208 158 197 193 154 +197 193 154 184 179 149 145 141 105 137 133 100 105 104 92 47 48 46 +20 23 23 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 19 19 15 19 19 15 19 19 14 18 18 14 17 17 +13 17 17 13 16 16 12 14 14 12 14 14 13 13 13 13 13 13 +13 13 13 12 12 12 10 10 9 6 7 7 2 2 2 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 65 66 61 +105 104 92 84 83 72 84 83 72 110 109 94 184 179 149 210 208 158 +210 208 158 210 208 158 214 212 158 197 193 154 214 212 158 210 208 158 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 239 239 170 251 251 187 184 179 149 84 83 72 +26 28 27 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 15 19 19 15 19 19 15 18 18 14 18 18 +13 17 17 13 16 16 15 15 15 14 14 13 14 14 13 14 14 13 +13 13 13 13 13 13 12 12 12 12 12 12 12 12 12 3 4 4 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 72 73 67 +105 104 92 99 98 80 84 83 72 99 98 80 177 172 135 197 193 154 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 214 212 158 197 193 154 99 98 80 +23 27 26 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 15 19 19 15 19 19 15 18 18 14 18 18 +14 17 17 16 16 16 16 16 16 16 16 16 15 15 15 14 14 13 +14 14 13 13 13 13 13 13 13 12 12 12 12 12 12 12 12 12 +3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 84 83 72 +110 109 94 99 98 80 72 73 67 63 64 60 99 98 80 177 172 135 +184 179 149 210 208 158 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 210 208 158 184 179 149 177 172 135 110 109 94 33 37 35 +17 21 21 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 15 19 19 15 19 19 15 19 19 14 18 18 +15 18 18 18 19 18 18 19 18 17 17 17 16 16 16 15 15 15 +14 14 13 13 13 13 13 13 13 12 12 12 12 12 12 12 12 12 +10 10 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 105 104 92 +108 107 93 99 98 80 72 73 67 63 64 60 51 52 50 87 86 72 +105 104 92 110 109 94 108 107 93 156 151 111 184 179 149 184 179 149 +197 193 154 197 193 154 197 193 154 184 179 149 184 179 149 177 172 135 +197 193 154 156 151 111 177 172 135 184 179 149 168 163 120 137 133 100 +145 141 105 110 109 94 99 98 80 47 48 46 55 57 54 15 19 19 +16 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +17 20 20 17 21 21 16 20 20 16 19 19 15 19 19 16 19 19 +20 20 20 21 22 21 20 20 20 19 20 19 18 19 18 16 16 16 +15 15 15 14 14 13 13 13 13 13 13 13 12 12 12 12 12 12 +12 12 12 4 5 5 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 58 59 55 110 109 94 +105 104 92 90 89 73 72 73 67 55 57 54 43 45 43 39 40 39 +43 45 43 46 47 45 43 45 43 68 70 65 65 66 61 63 64 60 +108 107 93 72 73 67 105 104 92 90 89 73 72 73 67 40 43 41 +72 73 67 68 70 65 68 70 65 58 59 55 63 64 60 49 51 48 +43 45 43 33 36 34 27 30 29 20 24 24 16 20 20 15 19 19 +15 19 19 15 19 19 15 19 19 16 19 19 16 20 20 16 20 20 +17 21 21 20 24 24 20 23 22 17 21 21 17 20 20 20 20 20 +21 22 21 21 22 21 21 22 21 21 22 21 20 20 20 18 19 18 +16 16 16 15 15 15 13 13 13 13 13 13 12 12 12 12 12 12 +12 12 12 10 10 9 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 21 22 21 110 109 94 110 109 94 +105 104 92 84 83 72 68 70 65 51 52 50 41 42 42 33 37 35 +28 31 30 23 27 26 20 23 23 18 22 22 17 20 20 25 27 26 +26 28 27 27 30 29 25 27 26 20 23 23 23 27 26 30 32 31 +20 24 24 17 21 21 18 22 22 15 19 19 26 28 27 20 23 23 +14 18 18 15 19 19 15 18 18 15 19 19 15 19 19 15 19 19 +15 19 19 15 19 19 15 19 19 15 19 19 15 19 19 16 19 19 +16 20 20 22 24 23 24 26 24 22 24 23 20 23 22 22 24 23 +24 26 24 24 26 24 23 24 24 22 24 23 21 22 21 19 20 19 +17 17 17 15 15 15 14 14 13 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 2 2 2 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 2 2 2 99 98 80 110 109 94 108 107 93 +105 104 92 84 83 72 63 64 60 49 51 48 39 40 39 32 34 33 +27 30 29 23 25 24 20 23 23 17 20 20 15 19 19 14 18 18 +14 17 17 13 17 17 13 17 17 13 17 17 13 17 17 13 17 17 +14 17 17 14 17 17 14 17 17 14 17 17 14 17 17 14 17 17 +14 18 18 14 18 18 14 18 18 14 18 18 15 18 18 15 19 19 +15 19 19 15 19 19 15 19 19 15 19 19 15 19 19 15 19 19 +15 19 19 17 21 21 27 29 28 26 28 27 25 27 26 25 27 26 +27 29 28 27 29 28 26 28 27 24 26 24 21 22 21 20 20 20 +18 19 18 16 16 16 14 14 13 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 4 5 5 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 51 52 50 110 109 94 110 109 94 105 104 92 +90 89 73 72 73 67 55 57 54 43 45 43 35 37 36 30 32 31 +26 28 27 20 24 24 17 21 21 16 19 19 15 18 18 14 17 17 +13 16 16 13 16 16 13 16 16 13 16 16 13 16 16 13 16 16 +13 16 16 13 16 16 13 16 16 13 17 17 13 17 17 14 17 17 +14 17 17 14 17 17 14 17 17 14 18 18 14 18 18 14 18 18 +15 18 18 15 18 18 15 19 19 15 19 19 15 19 19 15 19 19 +15 19 19 15 19 19 27 29 28 32 34 33 28 31 30 27 29 28 +30 32 31 30 32 31 30 31 28 26 28 27 23 24 24 21 22 21 +19 20 19 16 16 16 14 14 13 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 6 7 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 3 3 3 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 10 10 9 108 107 93 110 109 94 108 107 93 99 98 80 +84 83 72 63 64 60 49 51 48 40 43 41 33 36 34 27 30 29 +23 27 26 18 22 22 17 20 20 15 18 18 14 17 17 13 16 16 +13 16 16 13 16 16 12 15 15 12 15 15 12 15 15 12 15 15 +13 16 16 13 16 16 13 16 16 13 16 16 13 16 16 13 16 16 +13 17 17 13 17 17 14 17 17 14 17 17 14 17 17 14 18 18 +14 18 18 14 18 18 15 18 18 15 18 18 15 19 19 15 19 19 +15 19 19 15 19 19 17 21 21 33 36 34 32 34 33 31 33 31 +33 36 34 33 36 34 31 33 31 27 29 28 25 27 26 21 22 21 +19 20 19 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 8 8 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 63 64 60 137 133 100 43 45 43 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 68 70 65 110 109 94 110 109 94 105 104 92 84 83 72 +68 70 65 55 57 54 43 45 43 35 37 36 30 32 31 26 28 27 +20 24 24 17 21 21 16 19 19 14 17 17 13 16 16 12 15 15 +12 15 15 12 15 15 12 15 15 12 15 15 12 15 15 12 15 15 +12 15 15 12 15 15 12 15 15 12 15 15 12 15 15 13 16 16 +13 16 16 13 16 16 13 16 16 13 17 17 13 17 17 14 17 17 +14 17 17 14 17 17 14 18 18 14 18 18 14 18 18 15 18 18 +15 19 19 15 19 19 15 19 19 20 24 24 32 34 33 35 37 36 +37 39 37 35 37 36 33 36 34 30 32 31 26 28 27 22 24 23 +20 20 20 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 8 8 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 99 98 80 184 179 149 184 179 149 68 70 65 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +15 15 15 110 109 94 110 109 94 108 107 93 99 98 80 72 73 67 +61 63 57 49 51 48 39 40 39 33 36 34 27 30 29 23 25 24 +18 22 22 16 19 19 14 17 17 13 16 16 12 15 15 12 15 15 +11 14 14 11 14 14 11 14 14 11 14 14 11 14 14 11 14 14 +11 14 14 11 14 14 12 14 14 12 15 15 12 15 15 12 15 15 +12 15 15 13 16 16 13 16 16 13 16 16 13 16 16 13 16 16 +13 17 17 14 17 17 14 17 17 14 17 17 14 18 18 14 18 18 +14 18 18 15 18 18 15 19 19 15 19 19 30 32 31 38 39 37 +39 40 39 39 40 39 35 37 36 31 33 31 27 29 28 22 24 23 +20 20 20 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 8 8 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3 3 +110 109 94 197 193 154 210 208 158 184 179 149 68 70 65 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +68 70 65 110 109 94 110 109 94 105 104 92 84 83 72 65 66 61 +51 52 50 43 45 43 35 37 36 30 32 31 25 27 26 20 23 23 +17 20 20 15 18 18 13 16 16 12 15 15 12 15 15 11 14 14 +11 14 14 11 14 14 11 13 13 11 13 13 11 13 13 11 13 13 +11 14 14 11 14 14 11 14 14 11 14 14 11 14 14 11 14 14 +12 15 15 12 15 15 12 15 15 12 15 15 13 16 16 13 16 16 +13 16 16 13 16 16 13 17 17 13 17 17 14 17 17 14 17 17 +14 18 18 14 18 18 14 18 18 16 19 19 37 39 37 41 42 42 +41 42 42 41 42 42 38 39 37 32 34 33 27 29 28 23 24 24 +21 22 21 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 8 8 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 11 11 11 137 133 100 +197 193 154 251 251 187 239 239 170 184 179 149 31 33 31 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 12 12 +110 109 94 110 109 94 105 104 92 90 89 73 72 73 67 58 59 55 +46 47 45 37 39 37 31 33 31 26 28 27 20 24 24 17 21 21 +15 18 18 13 16 16 12 15 15 12 14 14 11 13 13 11 13 13 +10 13 13 10 13 13 10 13 13 10 13 13 10 13 13 10 13 13 +10 13 13 10 13 13 11 13 13 11 13 13 11 14 14 11 14 14 +11 14 14 11 14 14 12 14 14 12 15 15 12 15 15 12 15 15 +13 16 16 13 16 16 13 16 16 13 16 16 13 17 17 13 17 17 +14 17 17 14 17 17 14 18 18 23 27 26 41 42 42 41 42 42 +43 45 43 41 42 42 39 40 39 33 36 34 27 29 28 23 24 24 +21 22 21 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 6 7 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 27 29 28 168 163 120 210 208 158 +251 251 187 251 251 187 210 208 158 137 133 100 1 1 1 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 60 60 56 +110 109 94 105 104 92 105 104 92 84 83 72 65 66 61 51 52 50 +40 43 41 33 36 34 27 30 29 23 25 24 18 22 22 16 19 19 +14 17 17 12 15 15 11 14 14 11 14 14 10 13 13 10 13 13 +10 13 13 10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 +10 12 12 10 12 12 10 13 13 10 13 13 10 13 13 11 13 13 +11 13 13 11 14 14 11 14 14 11 14 14 11 14 14 12 15 15 +12 15 15 12 15 15 12 15 15 13 16 16 13 16 16 13 16 16 +13 17 17 13 17 17 14 17 17 32 34 33 43 45 43 43 45 43 +43 45 43 43 45 43 39 40 39 33 36 34 27 29 28 23 24 24 +21 22 21 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 6 7 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 1 1 68 70 65 184 179 149 210 208 158 251 251 187 +251 251 187 214 212 158 184 179 149 37 39 37 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 6 7 7 105 104 92 +105 104 92 105 104 92 99 98 80 72 73 67 58 59 55 46 47 45 +35 37 36 30 32 31 25 27 26 20 23 23 16 19 19 14 17 17 +12 15 15 12 14 14 11 13 13 10 13 13 10 12 12 10 12 12 +10 12 12 10 12 12 9 12 12 9 12 12 9 12 12 9 12 12 +10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 10 13 13 +10 13 13 10 13 13 11 13 13 11 13 13 11 14 14 11 14 14 +11 14 14 12 15 15 12 15 15 12 15 15 12 15 15 13 16 16 +13 16 16 13 16 16 17 20 20 41 42 42 46 47 45 46 47 45 +46 47 45 43 45 43 40 41 39 33 36 34 27 29 28 23 24 24 +20 20 20 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 4 5 5 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +15 15 15 110 109 94 197 193 154 214 212 158 251 251 187 251 251 187 +239 239 170 184 179 149 84 83 72 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 47 48 46 105 104 92 +105 104 92 99 98 80 84 83 72 68 70 65 51 52 50 40 43 41 +32 34 33 27 29 28 22 24 23 17 21 21 15 18 18 13 16 16 +12 15 15 11 13 13 10 13 13 10 12 12 9 12 12 9 12 12 +9 12 12 9 12 12 9 11 11 9 11 11 9 11 11 9 11 11 +9 12 12 9 12 12 9 12 12 9 12 12 10 12 12 10 12 12 +10 12 12 10 12 12 10 13 13 10 13 13 10 13 13 11 13 13 +11 14 14 11 14 14 11 14 14 12 14 14 12 15 15 12 15 15 +12 15 15 13 16 16 28 31 30 43 45 43 47 48 46 47 48 46 +47 48 46 43 45 43 40 41 39 33 36 34 27 29 28 22 24 23 +20 20 20 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 3 4 4 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 60 60 56 +177 172 135 197 193 154 251 251 187 251 251 187 251 251 187 251 251 187 +184 179 149 110 109 94 3 4 4 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 1 99 98 80 105 104 92 +99 98 80 87 86 72 84 83 72 63 64 60 46 47 45 35 37 36 +30 32 31 25 27 26 18 22 22 16 19 19 14 17 17 12 15 15 +11 14 14 10 13 13 9 12 12 9 12 12 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 12 12 9 12 12 +9 12 12 10 12 12 10 12 12 10 12 12 10 13 13 10 13 13 +10 13 13 11 13 13 11 14 14 11 14 14 11 14 14 12 15 15 +12 15 15 14 17 17 41 42 42 47 48 46 49 51 48 51 52 50 +47 48 46 43 45 43 40 41 39 33 36 34 27 29 28 22 24 23 +19 20 19 16 16 16 14 14 13 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 2 2 2 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 23 24 24 137 133 100 184 179 149 +210 208 158 251 251 187 251 251 187 251 251 187 251 251 187 184 179 149 +110 109 94 13 13 13 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 30 32 31 105 104 92 99 98 80 +84 83 72 84 83 72 72 73 67 55 57 54 41 42 42 32 34 33 +27 29 28 20 24 24 17 20 20 14 17 17 13 16 16 12 14 14 +10 13 13 10 12 12 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 12 12 9 12 12 10 12 12 10 12 12 10 12 12 +10 13 13 10 13 13 10 13 13 11 13 13 11 14 14 11 14 14 +11 14 14 27 29 28 55 56 53 72 73 67 51 52 50 51 52 50 +49 51 48 43 45 43 39 40 39 32 34 33 26 28 27 21 22 21 +19 20 19 16 16 16 18 19 17 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 1 1 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 8 8 7 84 83 72 184 179 149 197 193 154 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 184 179 149 145 141 105 +19 20 19 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 14 14 13 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 72 73 67 105 104 92 84 83 72 +72 73 67 84 83 72 68 70 65 49 51 48 39 40 39 30 32 31 +25 27 26 18 22 22 15 18 18 13 16 16 12 15 15 11 13 13 +10 12 12 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 12 12 9 12 12 9 12 12 +10 12 12 10 12 12 10 12 12 10 13 13 10 13 13 11 13 13 +13 16 16 41 42 42 99 98 80 158 153 112 65 66 61 51 52 50 +49 51 48 43 45 43 39 40 39 31 33 31 25 27 26 21 22 21 +21 22 21 68 70 65 55 56 53 13 13 13 12 12 12 12 12 12 +12 12 12 11 11 11 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3 3 +63 64 60 158 153 112 184 179 149 210 208 158 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 184 179 149 137 133 100 27 29 28 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +21 22 21 110 109 94 5 6 5 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 13 13 13 105 104 92 90 89 73 72 73 67 +68 70 65 84 83 72 63 64 60 46 47 45 35 37 36 27 29 28 +22 24 23 17 20 20 14 17 17 12 15 15 11 14 14 10 12 12 +10 12 12 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 12 12 9 12 12 10 12 12 10 12 12 10 13 13 10 13 13 +30 32 31 47 48 46 177 172 135 210 208 158 137 133 100 55 56 53 +49 51 48 43 45 43 38 39 37 31 33 31 25 27 26 22 24 23 +110 109 94 184 179 149 63 64 60 13 13 13 12 12 12 12 12 12 +12 12 12 8 9 9 0 0 0 1 1 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 21 22 21 105 104 92 +184 179 149 210 208 158 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 184 179 149 145 141 105 23 24 24 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +68 70 65 184 179 149 105 104 92 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 51 52 50 99 98 80 84 83 72 63 64 60 +68 70 65 72 73 67 55 57 54 41 42 42 32 34 33 25 27 26 +20 23 23 16 19 19 13 16 16 12 14 14 10 13 13 10 12 12 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 12 12 9 12 12 10 12 12 17 20 20 +46 47 45 72 73 67 210 208 158 251 251 187 210 208 158 63 64 60 +49 51 48 43 45 43 37 39 37 30 32 31 24 26 24 105 104 92 +210 208 158 197 193 154 47 48 46 13 13 13 12 12 12 12 12 12 +12 12 12 6 7 7 33 36 34 48 49 45 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 8 8 7 23 24 24 55 56 53 110 109 94 +210 208 158 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 184 179 149 110 109 94 20 20 20 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +110 109 94 251 251 187 210 208 158 47 48 46 0 0 0 0 0 0 +0 0 0 1 1 1 90 89 73 90 89 73 72 73 67 55 56 53 +72 73 67 68 70 65 51 52 50 37 39 37 28 31 30 23 25 24 +17 21 21 15 18 18 12 15 15 11 14 14 10 13 13 9 12 12 +9 11 11 9 11 11 9 11 11 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 12 12 13 16 16 41 42 42 +49 51 48 110 109 94 251 251 187 251 251 187 251 251 187 105 104 92 +49 51 48 43 45 43 35 37 36 30 31 28 47 48 46 197 193 154 +251 251 187 197 193 154 31 33 31 12 12 12 12 12 12 12 12 12 +12 12 12 51 52 50 184 179 149 72 73 67 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 +11 11 11 21 22 21 30 32 31 40 41 39 60 60 56 145 141 105 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 214 212 158 +184 179 149 110 109 94 13 13 13 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 4 5 4 61 61 53 48 49 45 3 4 3 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +156 151 111 251 251 187 251 251 187 184 179 149 11 11 11 0 0 0 +0 0 0 26 28 27 99 98 80 84 83 72 60 60 56 43 45 43 +72 73 67 65 66 61 49 51 48 35 37 36 27 29 28 20 24 24 +17 20 20 14 17 17 12 15 15 11 13 13 10 12 12 9 11 11 +9 11 11 9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 11 13 13 37 39 37 47 48 46 +51 52 50 184 179 149 251 251 187 251 251 187 251 251 187 145 141 105 +47 48 46 41 42 42 35 37 36 27 29 28 137 133 100 251 251 187 +251 251 187 197 193 154 19 20 19 12 12 12 12 12 12 12 12 12 +27 29 28 184 179 149 214 212 158 63 64 60 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 6 7 7 16 16 16 24 26 24 +30 32 31 38 39 37 47 48 46 55 57 54 68 70 65 110 109 94 +197 193 154 251 251 187 251 251 187 251 251 187 210 208 158 184 179 149 +105 104 92 8 8 7 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 65 66 61 184 179 149 156 151 111 +30 32 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +168 163 120 251 251 187 251 251 187 251 251 187 110 109 94 0 0 0 +0 0 0 60 60 56 84 83 72 68 70 65 51 52 50 38 39 37 +84 83 72 63 64 60 43 45 43 33 36 34 25 27 26 20 23 22 +15 18 18 13 16 16 12 14 14 10 13 13 9 12 12 9 11 11 +9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +9 11 11 9 11 11 10 12 12 33 36 34 46 47 45 51 52 50 +72 73 67 210 208 158 251 251 187 251 251 187 251 251 187 177 172 135 +47 48 46 41 42 42 35 37 36 37 39 37 184 179 149 251 251 187 +251 251 187 197 193 154 13 13 13 12 12 12 12 12 12 12 12 12 +110 109 94 251 251 187 251 251 187 37 39 37 0 0 0 0 0 0 +0 0 0 21 22 20 2 2 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +4 5 5 12 12 12 21 22 21 25 27 26 30 32 31 38 39 37 +46 47 45 55 56 53 60 60 56 65 66 61 68 70 65 105 104 92 +110 109 94 197 193 154 210 208 158 197 193 154 184 179 149 84 83 72 +2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 13 13 13 184 179 149 251 251 187 +197 193 154 43 44 41 0 0 0 0 0 0 0 0 0 0 0 0 +145 141 105 251 251 187 251 251 187 251 251 187 214 212 158 43 45 43 +2 2 2 84 83 72 72 73 67 58 59 55 41 42 42 38 39 37 +72 73 67 58 59 55 41 42 42 31 33 31 25 27 26 18 22 22 +14 17 17 12 15 15 12 14 14 10 12 12 9 12 12 9 11 11 +9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 9 12 12 31 33 31 43 45 43 49 51 48 55 56 53 +110 109 94 251 251 187 251 251 187 251 251 187 251 251 187 168 163 120 +47 48 46 41 42 42 33 36 34 63 64 60 197 193 154 251 251 187 +251 251 187 184 179 149 13 13 13 12 12 12 12 12 12 16 16 16 +197 193 154 251 251 187 239 239 170 20 20 20 0 0 0 2 2 1 +108 107 93 110 109 94 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 4 5 5 11 11 11 18 19 18 +22 24 23 26 28 27 32 34 33 39 40 39 46 47 45 51 52 50 +55 57 54 60 60 56 63 64 60 63 64 60 63 64 60 58 59 55 +63 64 60 99 98 80 145 141 105 137 133 100 43 45 43 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 3 4 3 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 110 109 94 251 251 187 +251 251 187 184 179 149 25 27 26 0 0 0 0 0 0 0 0 0 +99 98 80 251 251 187 251 251 187 251 251 187 251 251 187 156 151 111 +25 27 26 84 83 72 65 66 61 47 48 46 32 34 33 39 40 39 +72 73 67 55 57 54 40 41 39 30 32 31 23 25 24 18 22 22 +14 17 17 12 15 15 11 13 13 10 12 12 9 11 11 9 11 11 +9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +9 11 11 28 31 30 41 42 42 47 48 46 55 56 53 58 59 55 +137 133 100 251 251 187 251 251 187 251 251 187 210 208 158 137 133 100 +47 48 46 40 41 39 32 34 33 75 75 61 184 179 149 239 239 170 +251 251 187 177 172 135 13 13 13 12 12 12 12 12 12 43 44 41 +197 193 154 251 251 187 210 208 158 10 10 9 0 0 0 84 83 72 +251 251 187 84 83 72 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 +6 7 7 11 11 11 17 17 17 20 20 20 23 24 24 27 29 28 +32 34 33 38 39 37 43 45 43 47 48 46 51 52 50 55 56 53 +58 59 55 58 59 55 55 57 54 55 56 53 47 48 46 41 42 42 +35 37 36 31 33 31 47 48 46 14 14 13 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 66 65 55 99 98 80 20 20 20 +0 0 0 0 0 0 0 0 0 0 0 0 43 45 43 214 212 158 +251 251 187 251 251 187 145 141 105 3 3 3 0 0 0 0 0 0 +48 49 45 184 179 149 239 239 170 251 251 187 239 239 170 177 172 135 +84 83 72 72 73 67 55 56 53 39 40 39 26 28 27 39 40 39 +68 70 65 51 52 50 39 40 39 28 31 30 22 24 23 17 20 20 +14 17 17 12 14 14 10 13 13 9 11 11 9 11 11 9 11 11 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +27 29 28 40 41 39 46 47 45 51 52 50 55 57 54 63 64 60 +131 127 93 197 193 154 210 208 158 197 193 154 168 163 120 96 95 69 +47 48 46 40 41 39 32 34 33 71 71 57 145 141 105 184 179 149 +184 179 149 131 127 93 13 13 13 12 12 12 12 12 12 48 49 45 +168 163 120 184 179 149 156 151 111 6 7 7 14 14 13 177 172 135 +239 239 170 40 41 39 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 3 3 3 6 7 7 11 11 11 16 16 16 +18 19 18 21 22 21 23 24 24 27 29 28 32 34 33 37 39 37 +41 42 42 43 45 43 47 48 46 51 52 50 51 52 50 51 52 50 +51 52 50 49 51 48 46 47 45 40 41 39 32 34 33 25 27 26 +20 20 20 14 14 13 2 2 2 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 33 36 34 197 193 154 184 179 149 +41 42 42 0 0 0 0 0 0 0 0 0 3 3 3 184 179 149 +251 251 187 251 251 187 184 179 149 48 49 45 0 0 0 0 0 0 +16 17 12 121 119 87 177 172 135 194 189 146 188 184 146 145 141 105 +82 81 62 63 64 60 46 47 45 31 33 31 21 22 21 35 37 36 +68 70 65 51 52 50 37 39 37 27 30 29 22 24 23 17 20 20 +13 16 16 12 14 14 10 13 13 9 11 11 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 25 27 26 +38 39 37 43 45 43 51 52 50 55 56 53 60 60 56 63 64 60 +92 91 72 158 153 112 176 171 126 171 165 117 149 143 98 82 81 62 +44 46 43 38 39 37 30 32 31 71 71 57 131 127 93 160 154 106 +149 143 98 82 81 62 13 13 13 12 12 12 12 12 12 46 47 43 +121 119 87 134 131 96 96 95 69 7 7 6 38 39 37 131 127 93 +145 141 105 12 13 12 0 0 0 1 1 1 3 3 3 6 7 7 +10 10 9 12 12 12 14 14 13 16 16 16 18 19 18 21 22 21 +22 24 23 26 28 27 30 31 28 33 36 34 37 39 37 40 41 39 +41 42 42 43 45 43 46 47 45 46 47 45 46 47 45 43 45 43 +41 42 42 37 39 37 31 33 31 26 28 27 21 22 21 16 16 16 +6 7 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 177 172 135 251 251 187 +197 193 154 27 29 28 0 0 0 0 0 0 0 0 0 110 109 94 +239 239 170 239 239 170 184 179 149 87 86 72 2 2 1 0 0 0 +1 1 1 82 81 62 142 137 94 165 161 109 165 161 109 131 127 93 +75 75 61 55 56 53 37 39 37 25 27 26 19 20 19 32 34 33 +65 66 61 49 51 48 35 37 36 27 29 28 20 23 23 16 19 19 +13 16 16 13 13 13 10 12 12 9 11 11 8 10 10 8 10 10 +8 9 9 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 22 24 23 35 37 36 +41 42 42 47 48 46 55 56 53 58 59 55 63 64 60 65 66 61 +71 71 57 131 127 93 160 154 106 160 154 106 142 137 94 82 81 62 +46 47 43 40 41 39 33 36 34 66 65 55 125 122 87 149 143 98 +142 137 94 82 81 62 17 17 17 18 19 17 14 14 13 46 47 43 +118 116 76 125 122 87 96 95 69 16 17 12 71 71 57 103 101 77 +82 81 62 11 11 11 11 11 11 13 13 13 14 14 13 14 14 13 +15 15 15 16 16 16 17 17 17 19 20 19 21 22 21 23 24 24 +26 28 27 27 29 28 31 33 31 33 36 34 35 37 36 38 39 37 +39 40 39 39 40 39 38 39 37 37 39 37 35 37 36 31 33 31 +27 29 28 24 26 24 21 22 21 17 17 17 12 12 12 2 2 2 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 68 70 65 251 251 187 +251 251 187 156 151 111 2 2 1 0 0 0 0 0 0 43 44 41 +177 172 135 184 179 149 158 153 112 103 101 77 19 20 18 0 0 0 +0 0 0 46 47 43 131 127 93 160 154 106 160 154 106 131 127 93 +71 71 57 43 45 43 30 32 31 21 22 21 16 16 16 26 28 27 +63 64 60 47 48 46 35 37 36 26 28 27 20 23 23 16 19 19 +13 16 16 13 13 13 10 12 12 9 11 11 8 10 10 8 10 10 +7 9 9 7 9 9 8 9 9 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 20 20 20 33 36 34 40 41 39 +46 47 45 51 52 50 55 57 54 60 60 56 63 64 60 65 66 61 +66 65 55 118 116 76 151 147 98 165 161 109 151 147 98 121 119 87 +96 95 69 96 95 69 96 95 69 103 101 77 142 137 94 151 147 98 +142 137 94 103 101 77 82 81 62 82 81 62 82 81 62 96 95 69 +131 127 93 142 137 94 103 101 77 46 47 43 96 95 69 118 116 76 +71 71 57 14 14 13 14 14 13 15 15 15 15 15 15 16 16 16 +16 16 16 17 17 17 18 19 18 20 20 20 21 22 21 23 24 24 +25 27 26 27 29 28 30 31 28 30 32 31 31 33 31 31 33 31 +31 33 31 31 33 31 30 31 28 27 29 28 25 27 26 22 24 23 +20 20 20 16 16 16 13 13 13 6 7 7 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +58 59 55 68 70 65 8 8 7 0 0 0 10 10 9 210 208 158 +251 251 187 184 179 149 38 39 37 0 0 0 0 0 0 8 8 7 +103 101 77 149 143 98 149 143 98 118 116 76 40 41 39 25 27 25 +53 55 47 82 81 62 144 139 99 165 161 109 165 161 109 142 137 94 +71 71 57 35 37 36 24 26 24 18 19 18 15 15 15 22 24 23 +63 64 60 46 47 45 33 36 34 26 28 27 20 23 22 17 18 17 +12 15 15 11 13 13 10 12 12 9 11 11 8 10 10 8 10 10 +7 9 9 7 9 9 7 9 9 7 9 9 8 9 9 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 16 16 16 30 31 28 35 37 36 41 42 42 +47 48 46 55 56 53 58 59 55 63 64 60 65 66 61 65 66 61 +61 61 53 103 101 77 151 147 98 171 165 117 171 165 117 168 163 120 +158 153 112 158 153 112 155 149 109 151 147 98 151 147 98 160 154 106 +151 147 98 149 143 98 142 137 94 149 143 98 149 143 98 149 143 98 +155 149 109 151 147 98 131 127 93 103 101 77 125 122 87 118 116 76 +71 71 57 16 16 16 16 16 16 16 16 16 17 17 17 17 17 17 +17 17 17 17 17 17 18 19 18 19 20 19 20 20 20 21 22 21 +23 24 24 24 26 24 25 27 26 26 28 27 26 28 27 26 28 27 +25 27 26 24 26 24 22 24 23 21 22 21 19 20 19 16 16 16 +14 14 13 8 8 7 1 1 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +20 20 20 184 179 149 168 163 120 21 22 21 0 0 0 105 104 92 +177 172 135 145 141 105 71 71 57 0 0 0 0 0 0 0 0 0 +66 65 55 131 127 93 151 147 98 142 137 94 118 116 76 121 119 87 +145 141 105 158 153 112 176 171 126 178 174 128 176 171 126 149 145 103 +96 95 69 31 33 31 21 22 21 16 16 16 14 14 13 18 19 18 +60 60 56 46 47 45 33 36 34 25 27 26 21 22 21 15 18 18 +12 15 15 11 13 13 9 11 11 8 10 10 8 10 10 8 9 9 +7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 8 9 9 +8 9 9 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 10 12 12 26 28 27 31 33 31 38 39 37 43 45 43 +51 52 50 55 56 53 60 60 56 63 64 60 65 66 61 68 70 65 +63 64 60 96 95 69 158 153 112 178 174 128 188 184 146 194 189 146 +194 189 146 188 184 146 184 181 136 176 171 126 171 165 117 173 167 111 +173 167 111 165 161 109 171 165 117 174 170 121 176 171 126 178 174 128 +178 174 128 174 170 121 160 154 106 149 143 98 149 143 98 125 122 87 +71 71 57 16 16 16 16 16 16 17 17 17 17 17 17 17 17 17 +17 17 17 17 17 17 17 17 17 18 19 18 19 20 19 20 20 20 +21 22 21 21 22 21 21 22 21 22 24 23 21 22 21 21 22 21 +21 22 21 19 20 19 18 19 18 16 16 16 14 14 13 11 11 11 +3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 105 104 92 197 193 154 110 109 94 9 9 8 36 38 35 +121 119 87 131 127 93 96 95 69 18 19 17 30 31 28 66 65 55 +96 95 69 142 137 94 160 154 106 160 154 106 160 154 106 168 163 120 +184 181 136 194 191 148 197 193 154 197 193 154 194 189 146 168 163 120 +125 122 87 46 47 43 18 19 18 15 15 15 13 13 13 14 14 13 +55 57 54 43 45 43 32 34 33 25 27 26 18 22 22 17 17 17 +12 14 14 10 12 12 9 11 11 8 10 10 8 9 9 7 9 9 +6 8 8 7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 +7 9 9 8 9 9 8 9 9 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 32 34 33 41 42 42 35 37 36 39 40 39 37 39 37 +35 37 36 55 57 54 60 60 56 63 64 60 65 66 61 65 66 61 +61 63 57 115 113 82 168 163 120 194 191 148 204 201 155 210 208 158 +210 208 158 210 208 158 197 193 154 194 189 146 186 182 128 176 171 126 +174 170 121 176 171 126 186 182 128 190 186 136 194 191 148 197 193 154 +197 193 154 188 184 146 181 176 137 174 170 121 165 161 109 142 137 94 +82 81 62 24 26 24 16 16 16 16 16 16 16 16 16 16 16 16 +17 17 17 17 17 17 17 17 17 17 17 17 18 19 18 19 20 19 +19 20 19 19 20 19 20 20 20 19 20 19 19 20 19 18 19 18 +17 17 17 15 15 15 13 13 13 12 12 12 6 7 7 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 17 18 17 137 133 100 115 113 82 53 55 47 19 20 18 +103 101 77 144 139 99 137 133 100 115 113 82 137 133 100 156 151 111 +158 153 112 164 159 111 171 165 117 174 170 121 178 174 128 194 189 146 +204 201 155 214 212 158 214 212 158 214 212 158 210 208 158 188 184 146 +158 153 112 87 86 72 17 17 17 13 13 13 13 13 13 15 15 15 +55 56 53 43 45 43 32 34 33 24 26 24 17 20 20 16 16 16 +12 14 14 10 12 12 8 10 10 8 10 10 7 9 9 6 8 8 +6 8 8 6 8 8 6 8 8 7 9 9 7 9 9 7 9 9 +7 9 9 7 9 9 7 9 9 7 9 9 8 9 9 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 110 109 94 84 83 72 49 51 48 26 28 27 8 10 10 +8 9 9 51 52 50 58 59 55 63 64 60 63 64 60 63 64 60 +66 65 55 134 131 96 181 176 137 210 208 158 214 212 158 239 239 170 +239 239 170 224 223 159 210 208 158 204 201 155 194 189 146 186 182 128 +186 182 128 184 181 136 194 189 146 204 201 155 210 208 158 210 208 158 +210 208 158 210 208 158 197 193 154 190 186 136 176 171 126 155 149 109 +118 116 76 36 38 35 15 15 15 16 16 16 16 16 16 16 16 16 +16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 17 17 17 +17 17 17 17 17 17 17 17 17 16 16 16 16 16 16 15 15 15 +13 13 13 12 12 12 8 8 7 2 2 2 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 53 55 47 103 101 77 96 95 69 53 55 47 +103 101 77 158 153 112 177 172 135 184 179 149 188 184 146 197 193 154 +194 189 146 190 186 136 184 181 136 184 181 136 194 189 146 210 208 158 +214 212 158 239 239 170 251 251 187 251 251 187 224 223 159 204 201 155 +177 172 135 121 119 87 30 31 28 13 13 13 12 12 12 39 40 39 +60 60 56 43 45 43 32 34 33 23 25 24 18 19 18 13 16 16 +13 13 13 9 11 11 8 10 10 8 9 9 6 8 8 6 8 8 +6 8 8 6 8 8 6 8 8 6 8 8 6 8 8 7 9 9 +7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 +7 9 9 8 9 9 8 9 9 8 10 10 8 10 10 8 10 10 +14 17 17 197 193 154 158 153 112 55 57 54 7 9 9 7 9 9 +8 10 10 51 52 50 58 59 55 60 60 56 63 64 60 63 64 60 +71 71 57 155 149 109 194 191 148 214 212 158 251 251 187 251 251 187 +251 251 187 251 251 187 239 239 170 210 208 158 197 193 154 190 186 136 +190 186 136 194 189 146 204 201 155 210 208 158 224 223 159 239 239 170 +239 239 170 224 223 159 210 208 158 204 201 155 190 186 136 164 159 111 +125 122 87 40 41 39 15 15 15 15 15 15 15 15 15 15 15 15 +16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 +16 16 16 16 16 16 15 15 15 14 14 13 13 13 13 12 12 12 +8 9 9 3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 21 22 20 96 95 69 125 122 87 121 119 87 +144 139 99 177 172 135 197 193 154 210 208 158 214 212 158 214 212 158 +210 208 158 204 201 155 194 191 148 194 189 146 204 201 155 214 212 158 +239 239 170 251 251 187 251 251 187 251 251 187 251 251 187 214 212 158 +188 184 146 145 141 105 53 55 47 12 12 12 15 15 15 63 64 60 +63 64 60 41 42 42 31 33 31 23 24 24 17 18 17 12 15 15 +11 13 13 9 11 11 8 9 9 7 9 9 6 8 8 6 8 8 +6 7 7 6 7 7 6 8 8 6 8 8 6 8 8 6 8 8 +6 8 8 7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 +7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 8 8 7 +43 45 43 251 251 187 156 151 111 8 10 10 7 9 9 7 9 9 +21 22 21 51 52 50 55 56 53 55 57 54 58 59 55 58 59 55 +75 75 61 158 153 112 197 193 154 224 223 159 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 214 212 158 204 201 155 194 189 146 +190 186 136 197 193 154 210 208 158 224 223 159 251 251 187 251 251 187 +251 251 187 251 251 187 239 239 170 210 208 158 197 193 154 176 171 126 +125 122 87 36 38 35 14 14 13 14 14 13 15 15 15 15 15 15 +15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 +15 15 15 14 14 13 13 13 13 12 12 12 10 10 9 3 4 4 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 7 7 5 71 71 57 131 127 93 158 153 112 +177 172 135 197 193 154 214 212 158 239 239 170 251 251 187 251 251 187 +238 237 168 210 208 158 204 201 155 197 193 154 204 201 155 214 212 158 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 214 212 158 +197 193 154 156 151 111 66 65 55 12 12 12 37 39 37 58 59 55 +58 59 55 41 42 42 31 33 31 22 24 23 17 17 17 12 14 14 +10 12 12 8 10 10 6 8 8 6 8 8 6 7 7 6 7 7 +6 7 7 5 7 7 6 7 7 6 7 7 6 8 8 6 8 8 +6 8 8 6 8 8 6 8 8 7 9 9 7 9 9 7 9 9 +7 9 9 6 8 8 6 8 8 6 8 8 6 8 8 6 8 8 +61 63 57 197 193 154 16 19 19 6 8 8 6 8 8 8 9 9 +41 42 42 47 48 46 51 52 50 51 52 50 55 56 53 55 56 53 +71 71 57 158 153 112 197 193 154 224 223 159 251 251 187 251 251 187 +251 251 187 251 251 187 239 239 170 214 212 158 204 201 155 194 189 146 +190 186 136 197 193 154 210 208 158 239 239 170 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 224 223 159 204 201 155 177 172 135 +121 119 87 30 31 28 13 13 13 14 14 13 14 14 13 14 14 13 +14 14 13 14 14 13 15 15 15 15 15 15 14 14 13 13 13 13 +12 12 12 12 12 12 10 10 9 4 5 5 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 48 49 45 131 127 93 174 170 121 +194 189 146 210 208 158 239 239 170 251 251 187 251 251 187 251 251 187 +251 251 187 214 212 158 204 201 155 197 193 154 204 201 155 210 208 158 +239 239 170 251 251 187 251 251 187 251 251 187 239 239 170 214 212 158 +194 191 148 156 151 111 71 71 57 19 20 19 51 52 50 51 52 50 +51 52 50 41 42 42 30 32 31 21 22 21 17 17 17 13 13 13 +9 11 11 8 9 9 6 8 8 6 7 7 6 7 7 5 7 7 +5 6 5 5 6 5 5 7 7 5 7 7 6 7 7 6 7 7 +6 8 8 6 8 8 6 8 8 6 7 7 6 7 7 6 7 7 +6 7 7 6 8 8 6 8 8 6 8 8 6 8 8 6 8 8 +55 56 53 43 45 43 6 8 8 6 8 8 6 8 8 47 48 46 +60 60 56 47 48 46 46 47 45 47 48 46 38 39 37 10 12 12 +66 65 55 145 141 105 197 193 154 214 212 158 251 251 187 251 251 187 +251 251 187 251 251 187 224 223 159 210 208 158 194 191 148 184 181 136 +184 181 136 194 189 146 204 201 155 224 223 159 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 239 239 170 210 208 158 181 176 137 +115 113 82 21 22 20 13 13 13 13 13 13 13 13 13 13 13 13 +14 14 13 13 13 13 13 13 13 13 13 13 12 12 12 11 11 11 +10 10 9 6 7 7 1 1 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 2 2 1 66 65 55 144 139 99 178 174 128 +204 201 155 214 212 158 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 214 212 158 204 201 155 194 191 148 197 193 154 204 201 155 +214 212 158 239 239 170 239 239 170 239 239 170 214 212 158 210 208 158 +184 181 136 149 145 103 66 65 55 41 42 42 47 48 46 46 47 45 +43 45 43 39 40 39 28 31 30 21 22 21 16 16 16 10 12 12 +8 10 10 6 8 8 6 7 7 6 7 7 5 6 5 5 6 5 +5 6 5 5 6 5 5 6 5 5 6 5 5 7 7 5 7 7 +6 7 7 6 7 7 6 7 7 5 7 7 5 7 7 5 7 7 +5 7 7 6 7 7 6 7 7 6 7 7 6 7 7 6 8 8 +6 8 8 6 8 8 6 7 7 6 7 7 46 47 45 156 151 111 +105 104 92 58 59 55 43 45 43 32 34 33 6 8 8 6 8 8 +49 51 48 125 122 87 181 176 137 204 201 155 214 212 158 239 239 170 +239 239 170 214 212 158 210 208 158 197 193 154 181 176 137 176 171 126 +176 171 126 184 181 136 197 193 154 210 208 158 239 239 170 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 210 208 158 177 172 135 +99 98 80 13 13 13 12 12 12 12 12 12 13 13 13 12 12 12 +12 12 12 12 12 12 11 11 11 11 11 11 8 9 9 4 5 5 +1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 1 1 0 61 61 53 142 137 94 181 176 137 +204 201 155 224 223 159 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 214 212 158 197 193 154 190 186 136 184 181 136 188 184 146 +197 193 154 204 201 155 210 208 158 210 208 158 204 201 155 194 189 146 +176 171 126 134 131 96 66 65 55 43 45 43 41 42 42 39 40 39 +35 37 36 33 36 34 27 29 28 20 20 20 15 15 15 9 11 11 +8 9 9 6 7 7 5 6 5 5 6 5 4 5 5 4 5 5 +4 5 5 4 5 5 4 5 5 4 5 5 5 6 5 4 5 5 +4 5 5 5 6 5 4 5 5 5 6 5 5 6 5 5 6 5 +5 7 7 5 7 7 5 7 7 5 7 7 5 7 7 5 7 7 +6 7 7 6 7 7 6 7 7 28 31 30 184 179 149 184 179 149 +145 141 105 84 83 72 27 29 28 5 7 7 5 6 5 16 16 16 +43 44 41 96 95 69 158 153 112 188 184 146 204 201 155 210 208 158 +204 201 155 197 193 154 184 179 149 177 172 135 168 163 120 164 159 111 +164 159 111 174 170 121 184 181 136 197 193 154 214 212 158 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 210 208 158 177 172 135 +71 71 57 11 11 11 12 12 12 11 11 11 11 11 11 11 11 11 +10 10 9 10 10 9 8 8 7 3 4 4 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 31 33 31 121 119 87 176 171 126 +197 193 154 214 212 158 251 251 187 251 251 187 251 251 187 251 251 187 +239 239 170 210 208 158 194 189 146 178 174 128 174 170 121 176 171 126 +177 172 135 181 176 137 184 179 149 184 179 149 181 176 137 178 174 128 +158 153 112 121 119 87 53 55 47 37 39 37 33 36 34 30 32 31 +27 29 28 25 27 26 24 26 24 19 20 19 13 13 13 8 10 10 +6 8 8 6 7 7 5 6 5 4 5 5 4 5 5 4 5 5 +4 5 5 4 5 5 4 5 5 3 4 4 3 4 4 4 5 5 +4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 +5 6 5 5 6 5 5 6 5 5 6 5 5 6 5 5 6 5 +5 6 5 5 6 5 12 14 14 145 141 105 184 179 149 177 172 135 +90 89 73 21 22 21 5 6 5 5 6 5 4 5 5 37 39 37 +38 39 37 61 61 53 134 131 96 168 163 120 184 181 136 188 184 146 +184 179 149 177 172 135 168 163 120 164 159 111 155 149 109 151 147 98 +151 147 98 164 159 111 176 171 126 184 179 149 210 208 158 239 239 170 +251 251 187 251 251 187 251 251 187 239 239 170 210 208 158 158 153 112 +46 47 43 10 10 9 10 10 9 10 10 9 8 9 9 8 9 9 +6 7 7 3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 13 12 7 82 81 62 158 153 112 +188 184 146 210 208 158 239 239 170 251 251 187 251 251 187 251 251 187 +224 223 159 204 201 155 184 181 136 171 165 117 164 159 111 160 154 106 +158 153 112 164 159 111 168 163 120 168 163 120 168 163 120 164 159 111 +142 137 94 96 95 69 43 44 41 27 29 28 26 28 27 23 24 24 +21 22 21 18 19 18 17 17 17 18 19 18 13 13 13 8 8 7 +6 7 7 5 6 5 4 5 5 3 4 4 3 4 4 3 4 4 +3 4 4 3 4 4 3 3 3 3 3 3 3 4 4 3 4 4 +3 4 4 3 4 4 4 5 5 4 5 5 4 5 5 4 5 5 +4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 +4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 +4 5 5 4 5 5 4 5 5 4 5 5 31 33 31 65 66 61 +37 39 37 38 39 37 96 95 69 144 139 99 168 163 120 174 170 121 +168 163 120 164 159 111 155 149 109 149 145 103 149 143 98 142 137 94 +149 143 98 151 147 98 164 159 111 177 172 135 197 193 154 210 208 158 +251 251 187 251 251 187 251 251 187 239 239 170 197 193 154 137 133 100 +24 26 24 8 9 9 8 9 9 8 8 7 6 7 7 2 2 2 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 46 47 43 125 122 87 +176 171 126 197 193 154 210 208 158 239 239 170 251 251 187 239 239 170 +214 212 158 197 193 154 181 176 137 164 159 111 151 147 98 149 143 98 +149 143 98 149 143 98 149 145 103 155 149 109 160 154 106 149 143 98 +118 116 76 82 81 62 30 31 28 21 22 21 19 20 19 17 17 17 +14 14 13 12 12 12 10 10 9 12 12 12 10 12 12 6 8 8 +4 5 5 3 4 4 3 4 4 3 4 4 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 2 3 3 2 3 3 +3 4 4 3 4 4 3 4 4 3 4 4 3 4 4 4 5 5 +4 5 5 3 4 4 3 4 4 3 4 4 3 4 4 3 4 4 +4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 +4 5 5 3 4 4 3 4 4 23 24 24 110 109 94 72 73 67 +39 40 39 22 24 23 46 47 43 103 101 77 142 137 94 155 149 109 +160 154 106 155 149 109 149 143 98 142 137 94 142 137 94 142 137 94 +142 137 94 149 143 98 155 149 109 176 171 126 184 179 149 210 208 158 +239 239 170 251 251 187 251 251 187 214 212 158 184 179 149 105 104 92 +10 10 9 6 7 7 3 4 4 1 1 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 12 12 9 82 81 62 +149 145 103 181 176 137 197 193 154 210 208 158 214 212 158 214 212 158 +210 208 158 197 193 154 177 172 135 158 153 112 149 143 98 142 137 94 +142 137 94 142 137 94 149 143 98 151 147 98 151 147 98 131 127 93 +103 101 77 71 71 57 22 24 23 15 15 15 13 13 13 11 11 11 +8 9 9 6 7 7 6 7 7 4 5 5 8 9 9 6 7 7 +4 5 5 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 +2 3 3 2 3 3 2 3 3 3 4 4 3 4 4 3 4 4 +3 4 4 3 4 4 3 3 3 3 4 4 3 4 4 3 4 4 +3 4 4 3 4 4 3 4 4 3 4 4 3 4 4 3 4 4 +3 4 4 3 4 4 21 22 21 145 141 105 145 141 105 72 73 67 +17 18 17 3 4 4 21 22 20 66 65 55 118 116 76 142 137 94 +149 143 98 151 147 98 149 143 98 142 137 94 142 137 94 142 137 94 +142 137 94 149 143 98 155 149 109 168 163 120 184 179 149 210 208 158 +239 239 170 251 251 187 251 251 187 210 208 158 177 172 135 71 71 57 +3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 36 38 35 +115 113 82 158 153 112 181 176 137 197 193 154 204 201 155 210 208 158 +204 201 155 188 184 146 177 172 135 164 159 111 149 145 103 142 137 94 +142 137 94 142 137 94 149 143 98 151 147 98 149 143 98 125 122 87 +96 95 69 61 61 53 16 17 12 8 9 9 8 8 7 6 7 7 +4 5 5 3 4 4 3 3 3 3 3 3 3 3 3 5 6 5 +3 4 4 2 3 3 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 +2 2 2 2 2 2 2 3 3 2 3 3 2 3 3 2 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 2 3 3 2 3 3 3 4 4 3 4 4 3 4 4 +3 4 4 3 4 4 3 4 4 8 9 9 8 8 7 3 3 3 +3 3 3 3 3 3 9 9 8 36 38 35 82 81 62 118 116 76 +142 137 94 151 147 98 151 147 98 151 147 98 149 143 98 149 143 98 +149 143 98 151 147 98 160 154 106 176 171 126 188 184 146 210 208 158 +239 239 170 251 251 187 239 239 170 210 208 158 156 151 111 31 33 31 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 7 5 +66 65 55 125 122 87 158 153 112 181 176 137 194 189 146 197 193 154 +197 193 154 184 179 149 177 172 135 168 163 120 156 151 111 151 147 98 +151 147 98 151 147 98 151 147 98 161 156 96 149 143 98 118 116 76 +82 81 62 53 55 47 12 12 9 4 5 5 3 4 4 3 3 3 +3 3 3 3 3 3 2 2 2 2 2 2 1 1 1 1 2 2 +3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 1 2 2 +1 2 2 1 2 2 1 2 2 2 2 2 2 2 2 2 3 3 +2 3 3 2 3 3 2 3 3 2 3 3 2 2 2 2 2 2 +2 3 3 2 3 3 2 3 3 2 3 3 2 3 3 2 3 3 +2 3 3 2 3 3 2 3 3 2 3 3 2 3 3 3 3 3 +3 3 3 3 3 3 72 73 67 61 61 53 53 55 47 96 95 69 +131 127 93 151 147 98 161 156 96 161 156 96 151 147 98 151 147 98 +161 156 96 160 154 106 164 159 111 177 172 135 197 193 154 210 208 158 +239 239 170 251 251 187 224 223 159 197 193 154 131 127 93 9 9 8 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +24 26 24 82 81 62 131 127 93 164 159 111 178 174 128 188 184 146 +188 184 146 188 184 146 181 176 137 176 171 126 168 163 120 164 159 111 +160 154 106 160 154 106 160 154 106 160 154 106 151 147 98 125 122 87 +82 81 62 61 61 53 12 12 9 3 3 3 3 3 3 2 2 2 +2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +0 0 0 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 2 2 1 2 2 1 2 2 1 2 2 +1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 3 3 2 3 3 2 3 3 2 3 3 2 3 3 2 3 3 +2 3 3 30 32 31 72 73 67 31 33 31 36 38 35 82 81 62 +118 116 76 149 143 98 161 156 96 161 156 96 161 156 96 160 154 106 +165 161 109 165 161 109 176 171 126 188 184 146 204 201 155 214 212 158 +239 239 170 239 239 170 214 212 158 184 179 149 82 81 62 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +2 2 2 43 44 41 96 95 69 131 127 93 160 154 106 176 171 126 +184 181 136 184 181 136 184 181 136 181 176 137 178 174 128 174 170 121 +171 165 117 173 167 111 173 167 111 173 167 111 160 154 106 131 127 93 +96 95 69 66 65 55 16 17 12 2 2 2 1 1 1 1 1 1 +1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 2 2 1 2 2 1 2 2 1 2 2 1 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 10 9 6 30 31 28 71 71 57 +118 116 76 149 143 98 165 161 109 165 161 109 165 161 109 173 167 111 +173 167 111 176 171 126 184 181 136 197 193 154 210 208 158 224 223 159 +251 251 187 239 239 170 210 208 158 168 163 120 40 41 39 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 13 12 7 61 61 53 96 95 69 131 127 93 160 154 106 +176 171 126 184 181 136 184 181 136 188 184 146 184 181 136 184 181 136 +184 181 136 186 182 128 186 182 128 178 174 128 174 170 121 149 145 103 +118 116 76 82 81 62 21 22 20 1 1 1 1 1 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 +1 2 2 1 2 2 1 2 2 1 2 2 1 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 3 3 3 30 31 28 66 65 55 +118 116 76 149 143 98 165 161 109 173 167 111 173 167 111 174 170 121 +186 182 128 190 186 136 197 193 154 210 208 158 224 223 159 251 251 187 +251 251 187 239 239 170 197 193 154 137 133 100 12 12 9 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 30 31 28 71 71 57 103 101 77 134 131 96 +164 159 111 176 171 126 184 181 136 188 184 146 194 189 146 197 193 154 +197 193 154 197 193 154 194 191 148 194 189 146 190 186 136 176 171 126 +145 141 105 103 101 77 40 41 39 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 1 2 2 +1 2 2 1 2 2 1 2 2 1 2 2 1 2 2 1 2 2 +1 2 2 1 2 2 1 2 2 1 2 2 30 31 28 71 71 57 +118 116 76 160 154 106 173 167 111 178 174 128 186 182 128 190 186 136 +194 191 148 204 201 155 210 208 158 224 223 159 251 251 187 251 251 187 +251 251 187 214 212 158 184 179 149 84 83 72 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 5 5 3 43 44 41 82 81 62 103 101 77 +142 137 94 165 161 109 178 174 128 190 186 136 197 193 154 204 201 155 +210 208 158 210 208 158 210 208 158 210 208 158 210 208 158 197 193 154 +177 172 135 145 141 105 79 78 62 5 4 3 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 2 2 1 2 2 30 31 28 82 81 62 +142 137 94 165 161 109 178 174 128 190 186 136 194 191 148 204 201 155 +210 208 158 214 212 158 239 239 170 251 251 187 251 251 187 251 251 187 +251 251 187 210 208 158 168 163 120 36 38 35 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 16 17 12 53 55 47 82 81 62 +118 116 76 151 147 98 171 165 117 184 181 136 194 191 148 210 208 158 +214 212 158 224 223 159 239 239 170 239 239 170 224 223 159 214 212 158 +197 193 154 176 171 126 115 113 82 24 26 24 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 40 41 39 103 101 77 +151 147 98 176 171 126 190 186 136 197 193 154 210 208 158 214 212 158 +239 239 170 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +239 239 170 197 193 154 110 109 94 3 4 3 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 30 31 28 66 65 55 +96 95 69 125 122 87 160 154 106 178 174 128 194 189 146 204 201 155 +214 212 158 239 239 170 251 251 187 251 251 187 251 251 187 239 239 170 +210 208 158 188 184 146 149 145 103 61 61 53 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 61 61 53 131 127 93 +164 159 111 184 181 136 197 193 154 210 208 158 224 223 159 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +210 208 158 168 163 120 43 44 41 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 4 3 2 36 38 35 +71 71 57 96 95 69 142 137 94 165 161 109 184 181 136 197 193 154 +210 208 158 239 239 170 251 251 187 251 251 187 251 251 187 251 251 187 +214 212 158 197 193 154 168 163 120 103 101 77 7 7 5 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 0 0 0 0 0 0 0 0 0 82 81 62 142 137 94 +174 170 121 194 189 146 210 208 158 224 223 159 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 224 223 159 +184 179 149 99 98 80 3 3 3 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 7 5 +43 44 41 82 81 62 118 116 76 142 137 94 171 165 117 190 186 136 +204 201 155 224 223 159 251 251 187 251 251 187 251 251 187 251 251 187 +214 212 158 197 193 154 174 170 121 125 122 87 30 31 28 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 3 4 3 82 81 62 149 143 98 +176 171 126 194 191 148 210 208 158 239 239 170 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 239 239 170 204 201 155 +145 141 105 30 31 28 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +10 9 6 46 47 43 82 81 62 118 116 76 149 143 98 174 170 121 +194 189 146 210 208 158 224 223 159 251 251 187 251 251 187 224 223 159 +210 208 158 194 191 148 174 170 121 134 131 96 53 55 47 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 7 7 5 96 95 69 149 143 98 +176 171 126 194 191 148 210 208 158 239 239 170 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 239 239 170 210 208 158 177 172 135 +75 75 61 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 10 9 6 46 47 43 82 81 62 118 116 76 149 143 98 +176 171 126 194 191 148 210 208 158 214 212 158 214 212 158 210 208 158 +197 193 154 184 181 136 164 159 111 131 127 93 53 55 47 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 7 7 5 96 95 69 149 143 98 +174 170 121 194 189 146 204 201 155 214 212 158 239 239 170 251 251 187 +251 251 187 251 251 187 239 239 170 210 208 158 184 179 149 110 109 94 +12 12 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 10 9 6 43 44 41 82 81 62 115 113 82 +144 139 99 168 163 120 188 184 146 197 193 154 197 193 154 194 189 146 +184 181 136 174 170 121 151 147 98 118 116 76 36 38 35 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 4 3 2 82 81 62 142 137 94 +171 165 117 186 182 128 194 191 148 210 208 158 214 212 158 224 223 159 +239 239 170 224 223 159 210 208 158 184 179 149 137 133 100 36 38 35 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 7 7 5 36 38 35 71 71 57 +103 101 77 131 127 93 155 149 109 168 163 120 168 163 120 168 163 120 +164 159 111 149 143 98 125 122 87 82 81 62 13 12 7 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 61 61 53 125 122 87 +160 154 106 174 170 121 184 181 136 194 189 146 204 201 155 210 208 158 +210 208 158 204 201 155 184 179 149 145 141 105 61 61 53 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 3 3 2 30 31 28 +61 61 53 82 81 62 103 101 77 121 119 87 125 122 87 125 122 87 +118 116 76 103 101 77 79 78 62 24 26 24 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 25 27 25 96 95 69 +142 137 94 160 154 106 171 165 117 178 174 128 184 181 136 184 181 136 +181 176 137 177 172 135 145 141 105 75 75 61 5 5 3 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +16 17 12 40 41 39 61 61 53 71 71 57 71 71 57 71 71 57 +66 65 55 43 44 41 12 12 9 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 46 47 43 +96 95 69 125 122 87 142 137 94 149 145 103 155 149 109 155 149 109 +145 141 105 121 119 87 66 65 55 7 7 5 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 1 1 16 17 12 24 26 24 25 27 25 19 20 18 +7 7 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 +25 27 25 61 61 53 82 81 62 96 95 69 96 95 69 82 81 62 +61 61 53 25 27 25 2 2 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 5 6 5 13 12 7 10 9 6 3 4 3 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 diff --git a/drivers/video/logo/logo_linux_vga16.ppm b/drivers/video/logo/logo_linux_vga16.ppm index 1850c15e6fe..12ac3a5454c 100644 --- a/drivers/video/logo/logo_linux_vga16.ppm +++ b/drivers/video/logo/logo_linux_vga16.ppm @@ -1,1604 +1,2739 @@ P3 -# Standard 16-color Linux logo -80 80 +142 114 255 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 85 85 85 85 85 85 85 85 85 - 85 85 85 85 85 85 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 85 85 85 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 85 85 85 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 170 170 170 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 -170 170 170 170 170 170 85 85 85 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 85 85 85 170 170 170 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 170 170 170 170 170 -170 170 170 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 85 85 85 170 170 170 170 170 170 170 170 170 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 170 170 170 255 255 255 255 255 255 -255 255 255 170 170 170 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 -170 170 170 170 170 170 255 255 255 255 255 255 - 0 0 0 0 0 0 0 0 0 0 0 0 -170 170 170 255 255 255 170 170 170 170 170 170 -255 255 255 170 170 170 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 -170 170 170 0 0 0 0 0 0 255 255 255 - 85 85 85 0 0 0 0 0 0 0 0 0 -255 255 255 170 170 170 0 0 0 85 85 85 -170 170 170 255 255 255 170 170 170 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 - 85 85 85 0 0 0 0 0 0 170 170 170 - 85 85 85 0 0 0 0 0 0 0 0 0 -255 255 255 85 85 85 0 0 0 0 0 0 - 85 85 85 255 255 255 170 170 170 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 -170 170 170 0 0 0 0 0 0 170 170 170 - 85 85 85 85 85 85 85 85 85 85 85 85 -255 255 255 85 85 85 0 0 0 0 0 0 - 85 85 85 255 255 255 170 170 170 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 -255 255 255 0 0 0 0 0 0 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 0 0 0 0 0 0 - 85 85 85 255 255 255 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 -170 170 170 170 170 170 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 170 170 170 170 170 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 85 85 85 0 0 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 85 85 85 0 0 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 170 85 0 -170 85 0 170 85 0 85 85 85 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 85 85 85 0 0 0 - 85 85 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 85 85 85 0 0 0 - 0 0 0 85 85 85 170 170 170 85 85 85 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 85 85 85 0 0 0 - 85 85 85 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 170 170 170 170 170 170 170 170 0 0 0 - 0 0 0 0 0 0 170 170 170 170 170 170 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 85 85 85 170 170 170 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 85 85 85 - 0 0 0 0 0 0 85 85 85 85 85 85 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 85 85 85 170 170 170 170 170 170 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 170 170 170 170 170 170 170 170 170 170 170 -255 255 255 255 255 255 255 255 255 170 170 170 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 85 85 85 -255 255 255 255 255 255 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 170 170 170 -170 170 170 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 170 170 170 -255 255 255 255 255 255 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 170 170 170 -170 170 170 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -170 170 170 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 85 85 85 255 255 255 -255 255 255 255 255 255 255 255 255 170 170 170 -170 170 170 170 170 170 170 170 170 170 170 170 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 85 85 85 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 85 85 85 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 85 85 85 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 85 85 85 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 170 170 170 170 170 170 170 170 170 -255 255 255 255 255 255 255 255 255 170 170 170 -170 170 170 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -170 170 170 170 170 170 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 -170 170 170 170 170 170 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -170 170 170 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 85 85 85 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 -170 170 170 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 170 170 170 170 170 170 - 0 0 0 0 0 0 0 0 0 85 85 85 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 85 85 85 0 0 0 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 170 170 170 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 170 170 170 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -170 170 170 85 85 85 0 0 0 0 0 0 - 0 0 0 85 85 85 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 - 0 0 0 0 0 0 85 85 85 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 0 0 0 85 85 85 - 85 85 85 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 - 0 0 0 85 85 85 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 0 0 0 85 85 85 - 85 85 85 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 85 85 85 - 0 0 0 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 85 85 85 0 0 0 - 0 0 0 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 85 85 85 0 0 0 - 85 85 85 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 85 85 85 0 0 0 0 0 0 -170 170 170 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 0 0 0 - 85 85 85 85 85 85 85 85 85 85 85 85 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 170 85 0 -255 255 85 170 85 0 0 0 0 0 0 0 - 85 85 85 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 85 85 85 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 0 0 0 - 0 0 0 85 85 85 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 85 170 85 0 255 255 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 85 85 85 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 - 0 0 0 0 0 0 85 85 85 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 85 -170 85 0 255 255 85 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 -170 85 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 0 0 0 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 170 85 0 -255 255 85 170 85 0 255 255 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 170 85 0 -255 255 85 170 85 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 0 0 0 0 0 0 0 0 0 - 85 85 85 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 85 -170 85 0 255 255 85 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 255 255 85 -170 85 0 255 255 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 0 0 0 0 0 0 - 0 0 0 85 85 85 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 0 0 0 - 0 0 0 0 0 0 85 85 85 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 170 170 170 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 170 170 170 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 170 170 170 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 0 0 0 0 0 0 0 0 0 - 0 0 0 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 170 170 170 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 0 0 0 0 0 0 0 0 0 - 85 85 85 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 85 85 85 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 85 85 85 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -170 170 170 85 85 85 85 85 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 170 170 170 - 85 85 85 0 0 0 0 0 0 170 85 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 85 85 85 - 0 0 0 0 0 0 0 0 0 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -170 170 170 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -170 170 170 85 85 85 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 170 85 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 170 85 0 -170 85 0 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 85 85 85 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -170 85 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 170 85 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 170 85 0 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 170 85 0 -170 85 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -170 85 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -170 85 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 170 85 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 170 85 0 170 85 0 170 85 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 170 85 0 -170 85 0 0 0 0 0 0 0 0 0 0 - 85 85 85 85 85 85 85 85 85 85 85 85 - 85 85 85 85 85 85 85 85 85 85 85 85 - 85 85 85 85 85 85 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 170 85 0 -170 85 0 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -170 85 0 170 85 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 170 85 0 170 85 0 - 85 85 85 85 85 85 85 85 85 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 85 85 85 85 85 85 85 85 85 170 85 0 -170 85 0 170 85 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 170 85 0 -170 85 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 170 170 170 170 85 0 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +255 255 85 170 170 170 170 170 170 170 85 0 85 255 85 170 85 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 170 170 170 170 85 0 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 170 85 0 170 170 170 +170 170 170 170 85 0 170 170 170 170 170 170 170 85 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 255 85 +255 85 85 85 255 85 170 170 170 170 85 0 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 170 85 0 85 85 85 85 85 85 +170 170 170 170 85 0 170 170 170 85 85 85 170 85 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 85 85 85 170 85 0 +85 85 85 85 85 85 170 85 0 85 255 85 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 170 85 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 170 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 85 0 85 255 85 170 85 0 170 85 0 170 85 0 85 255 85 +170 85 0 170 85 0 0 170 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 170 0 170 85 0 +255 255 85 170 85 0 255 255 85 255 255 85 255 255 85 170 85 0 +255 255 85 85 255 85 170 85 0 170 85 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 85 0 255 255 85 +85 255 85 255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 +255 255 85 170 85 0 255 255 85 85 255 85 170 85 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 255 255 85 170 85 0 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 +255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 85 255 85 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 85 0 255 255 85 255 255 85 +255 255 85 255 255 85 170 85 0 255 255 85 85 255 85 255 255 85 +255 255 85 170 85 0 255 255 85 170 85 0 255 255 85 170 85 0 +170 85 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 170 170 170 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 85 0 255 255 85 85 255 85 255 255 85 +170 170 170 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 85 255 85 255 255 85 255 255 85 255 255 85 +85 255 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 85 0 255 255 85 255 255 85 255 255 85 +255 255 255 255 255 85 255 255 85 170 85 0 255 255 85 170 85 0 +255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 255 255 85 +170 85 0 170 85 0 0 170 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 170 85 0 85 255 85 255 255 85 170 170 170 255 255 255 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 170 85 0 255 255 85 85 255 85 255 255 85 +255 255 85 85 255 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 255 255 85 255 255 85 255 255 85 255 255 255 255 255 85 +255 255 85 255 255 85 85 255 85 255 255 85 255 255 85 85 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 +255 255 85 170 85 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 85 0 170 85 0 255 255 85 255 255 85 255 255 255 170 170 170 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +170 85 0 255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 +255 255 85 85 255 85 170 85 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 85 85 255 85 255 255 85 170 170 170 255 255 255 255 255 85 +255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 85 255 85 170 85 0 +255 255 85 170 85 0 170 85 0 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 85 85 85 170 170 170 170 170 170 170 170 170 +85 255 85 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 170 0 +170 85 0 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 85 255 85 255 255 85 170 85 0 170 85 0 +170 85 0 85 255 85 255 255 85 85 85 85 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 85 255 85 170 170 170 170 170 170 +85 85 85 170 170 170 170 170 170 170 85 0 170 170 170 170 170 170 +85 255 85 170 170 170 170 85 0 170 170 170 85 255 85 255 85 85 +85 255 85 170 170 170 255 255 85 85 85 85 255 255 85 170 170 170 +85 255 85 170 170 170 255 255 85 170 170 170 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 255 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 +255 255 85 255 255 85 255 255 85 170 85 0 0 170 0 85 85 85 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 85 255 85 +255 85 85 85 255 85 85 85 85 255 85 85 85 85 85 170 170 170 +170 85 0 170 170 170 85 85 85 85 255 85 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 85 +170 85 0 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 170 85 0 255 255 85 85 85 85 85 85 85 +255 255 85 170 170 170 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 85 85 85 170 170 170 170 85 0 170 170 170 +170 170 170 255 255 85 170 170 170 85 85 85 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 85 0 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 170 85 0 170 85 0 0 170 0 +0 0 0 170 85 0 170 85 0 0 170 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 85 85 85 170 170 170 85 85 85 +170 170 170 85 85 85 85 85 85 170 170 170 170 85 0 85 85 85 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 255 255 85 170 85 0 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 +255 255 85 255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 +170 85 0 255 255 85 85 255 85 255 255 85 255 255 85 170 85 0 +170 85 0 255 255 85 170 85 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 255 255 85 255 255 85 +255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 +85 255 85 170 85 0 0 170 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 170 0 170 85 0 255 255 85 +85 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +170 85 0 255 255 85 85 255 85 255 255 85 255 255 85 170 85 0 +85 255 85 170 85 0 170 85 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 85 0 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 170 85 0 255 255 85 85 255 85 255 255 85 170 85 0 +255 255 85 255 255 85 170 85 0 255 255 85 170 85 0 85 255 85 +170 85 0 170 85 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 255 255 85 170 85 0 +255 255 85 170 85 0 255 255 85 170 85 0 255 255 85 85 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 170 85 0 255 255 85 85 255 85 170 85 0 170 85 0 +0 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 85 0 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 170 85 0 255 255 85 170 85 0 85 255 85 +255 255 85 85 255 85 170 85 0 170 85 0 85 255 85 170 85 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 255 255 85 85 255 85 +255 255 85 255 255 85 85 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 170 85 0 255 255 85 85 255 85 255 255 85 255 255 85 +170 85 0 170 85 0 85 255 85 170 85 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 85 85 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 255 255 85 255 255 85 +170 85 0 255 255 85 255 255 85 170 85 0 255 255 85 170 85 0 +255 255 85 85 255 85 170 85 0 255 255 85 170 85 0 85 255 85 +170 85 0 170 85 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 85 0 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 85 255 85 +170 85 0 255 255 85 170 85 0 85 255 85 170 85 0 170 85 0 +0 170 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 170 170 170 170 170 170 255 255 255 170 170 170 +170 170 170 170 170 170 85 85 85 85 85 85 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 255 85 255 255 85 +170 85 0 255 255 85 255 255 85 170 85 0 85 255 85 170 85 0 +255 255 85 170 85 0 0 170 0 170 85 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 170 170 170 170 170 170 170 170 170 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 170 85 0 +0 170 0 85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 85 255 255 85 170 85 0 0 170 0 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 170 170 170 170 170 170 85 85 85 +170 170 170 170 170 170 170 170 170 170 170 170 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 170 85 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 85 85 85 170 170 170 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +170 170 170 170 170 170 170 170 170 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 170 170 170 +170 170 170 170 170 170 170 170 170 85 85 85 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 170 170 170 170 170 170 +255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 170 170 170 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 170 170 170 255 255 255 170 170 170 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 170 170 170 170 170 170 +255 255 255 170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 +255 255 255 255 255 255 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 170 170 170 +170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 +255 255 255 170 170 170 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 255 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 85 85 85 170 170 170 +170 170 170 170 170 170 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +170 170 170 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 170 170 170 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 170 170 170 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 255 255 255 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 +170 170 170 255 255 255 170 170 170 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 170 170 170 +255 255 255 255 255 255 170 170 170 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 170 170 170 170 170 170 255 255 255 +255 255 255 170 170 170 170 170 170 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 255 255 255 255 255 255 255 255 255 +170 170 170 170 170 170 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 +170 170 170 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 170 170 170 +170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 +170 170 170 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 170 170 170 170 170 170 170 170 170 +255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 170 170 170 255 255 255 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 170 170 170 255 255 255 170 170 170 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +255 255 255 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 255 255 255 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 255 255 255 255 255 255 255 255 255 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 +255 255 255 170 170 170 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 +170 170 170 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 170 170 170 255 255 255 255 255 255 255 255 255 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 255 255 255 +255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 85 85 85 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 +0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 255 255 255 +255 255 255 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 +170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 +0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 +85 85 85 0 0 0 0 0 0 85 85 85 170 170 170 255 255 255 +255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 170 170 170 85 85 85 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 +0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 255 255 255 +170 170 170 170 170 170 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 255 255 255 255 255 255 0 0 0 0 0 0 85 85 85 +255 255 255 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 255 255 255 +255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 255 255 255 170 170 170 170 170 170 170 170 170 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 170 170 170 255 255 255 170 170 170 170 170 170 85 85 85 +85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 170 170 170 +170 170 170 85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 +170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 170 170 170 +170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 +255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 170 170 170 255 255 85 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 +85 85 85 170 170 170 170 170 170 170 170 170 170 85 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 170 85 0 +170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +170 85 0 170 170 170 85 85 85 0 0 0 85 85 85 85 85 85 +170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 +170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 170 85 0 170 170 170 170 170 170 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 170 85 0 85 255 85 170 85 0 170 170 170 85 85 85 +85 85 85 0 0 0 0 0 0 85 85 85 170 85 0 85 255 85 +170 85 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 85 85 85 170 85 0 0 0 0 85 85 85 85 85 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 255 255 255 +255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 170 85 0 170 170 170 170 85 0 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 255 85 85 170 170 170 85 255 85 170 85 0 +85 85 85 85 85 85 170 85 0 85 85 85 170 170 170 85 85 85 +170 170 170 170 85 0 85 85 85 85 85 85 85 85 85 85 85 85 +170 85 0 85 255 85 85 85 85 85 85 85 85 85 85 170 85 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 170 170 170 +255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 85 0 170 170 170 170 85 0 85 85 85 0 0 0 +85 85 85 85 85 85 85 255 85 170 170 170 170 170 170 170 85 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 255 85 255 85 85 170 170 170 170 170 170 +170 170 170 85 255 85 170 170 170 170 85 0 170 170 170 170 85 0 +170 170 170 85 85 85 85 255 85 170 85 0 170 170 170 170 85 0 +170 170 170 170 170 170 170 85 0 85 85 85 85 85 85 85 255 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 170 170 170 170 170 170 0 0 0 0 0 0 85 85 85 +170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 255 255 85 85 85 85 85 85 85 85 85 85 +85 255 85 255 85 85 170 170 170 170 85 0 170 170 170 85 255 85 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 170 85 0 170 170 170 170 170 170 255 255 85 +170 170 170 255 85 85 170 170 170 170 170 170 255 255 85 170 170 170 +85 255 85 170 170 170 255 85 85 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 85 0 170 170 170 170 85 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 85 85 85 0 0 0 85 85 85 +85 85 85 170 85 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 255 85 85 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 170 85 0 +170 170 170 255 255 85 170 170 170 255 255 85 170 170 170 255 255 85 +170 170 170 255 255 85 170 170 170 170 170 170 85 255 85 170 85 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 170 170 170 85 85 85 170 170 170 170 85 0 +170 170 170 85 255 85 170 170 170 170 85 0 170 170 170 170 170 170 +255 255 85 170 170 170 170 170 170 255 255 255 255 255 85 170 170 170 +255 255 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 170 85 0 170 170 170 170 170 170 170 170 170 255 255 255 +170 170 170 255 255 255 255 255 85 170 170 170 255 255 85 170 170 170 +255 255 85 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 255 85 85 170 170 170 170 170 170 +85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 170 85 0 85 85 85 +85 85 85 255 255 85 170 170 170 170 170 170 170 170 170 170 170 170 +255 255 85 170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 255 255 255 255 255 255 170 170 170 255 255 255 170 170 170 +170 170 170 85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 255 85 170 170 170 255 255 85 255 255 255 255 255 255 +255 255 255 170 170 170 255 255 255 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 255 255 85 170 170 170 255 255 85 255 255 255 +255 255 85 255 255 255 255 255 85 170 170 170 170 170 170 170 85 0 +170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 170 170 170 255 255 85 170 170 170 255 255 85 170 170 170 +170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 255 255 85 +255 255 255 255 255 255 255 255 85 255 255 255 255 255 255 170 170 170 +255 255 85 85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 170 170 170 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 170 170 170 170 170 170 170 170 170 255 255 255 170 170 170 +255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 85 170 170 170 255 255 255 170 170 170 255 255 255 +255 255 255 255 255 255 170 170 170 255 255 85 170 170 170 255 255 85 +85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 170 85 0 170 170 170 +255 255 85 170 170 170 170 170 170 255 255 255 255 255 255 255 255 255 +170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 +255 255 255 170 170 170 255 255 255 255 255 255 170 170 170 255 255 255 +170 170 170 170 170 170 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 +85 85 85 170 85 0 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 85 255 255 255 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 255 255 85 255 255 255 255 255 255 +170 170 170 255 255 255 255 255 255 170 170 170 170 170 170 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 255 85 170 170 170 +170 170 170 255 255 85 170 170 170 255 255 255 170 170 170 255 255 255 +255 255 255 255 255 255 255 255 85 170 170 170 170 170 170 255 255 255 +170 170 170 255 255 255 255 255 255 170 170 170 255 255 255 255 255 85 +170 170 170 170 85 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 170 170 170 170 170 170 255 255 85 170 170 170 255 255 255 +255 255 255 170 170 170 255 255 255 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 85 170 170 170 255 255 255 170 170 170 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 255 255 85 +85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 170 85 0 170 170 170 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 +255 255 85 255 255 255 170 170 170 255 255 255 170 170 170 170 170 170 +170 170 170 170 170 170 85 85 85 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 85 85 85 170 170 170 170 170 170 255 255 255 170 170 170 +255 255 255 170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 +255 85 85 170 170 170 170 170 170 170 170 170 255 255 255 255 255 255 +170 170 170 255 255 255 255 255 255 170 170 170 255 255 255 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 170 170 170 +255 255 85 170 170 170 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 85 255 255 255 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 255 255 85 +170 170 170 170 85 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 170 170 170 +170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 255 255 85 170 170 170 170 170 170 +255 255 85 170 170 170 170 170 170 170 170 170 170 170 170 255 85 85 +85 255 85 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 +255 255 255 255 255 255 255 255 255 255 255 85 170 170 170 170 170 170 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 255 255 85 +170 170 170 170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 +255 255 255 170 170 170 170 170 170 170 170 170 170 170 170 255 85 85 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 170 170 170 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 170 85 0 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 85 0 170 170 170 85 255 85 +255 85 85 170 170 170 255 255 85 170 170 170 170 170 170 255 255 255 +255 255 255 170 170 170 255 255 255 255 255 255 170 170 170 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +170 170 170 255 255 85 170 170 170 255 255 85 255 255 255 255 255 255 +170 170 170 170 170 170 255 255 85 170 170 170 255 85 85 85 255 85 +170 170 170 170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 +170 85 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 85 85 85 85 85 85 170 170 170 255 255 85 +170 170 170 170 85 0 170 170 170 170 170 170 170 85 0 85 85 85 +170 170 170 170 85 0 85 85 85 170 170 170 170 170 170 170 170 170 +170 170 170 255 255 255 255 255 255 255 255 85 170 170 170 170 170 170 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 85 0 +170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 +255 255 255 170 170 170 170 170 170 170 85 0 170 170 170 85 85 85 +170 170 170 170 170 170 170 85 0 170 170 170 170 85 0 85 85 85 +85 255 85 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 170 85 0 85 85 85 170 170 170 +170 85 0 170 170 170 85 255 85 170 85 0 170 170 170 85 85 85 +170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 255 255 255 +255 255 85 255 255 255 170 170 170 170 170 170 170 170 170 170 85 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 85 170 170 170 170 170 170 85 255 85 170 170 170 +170 85 0 170 85 0 170 170 170 85 255 85 85 85 85 170 170 170 +170 85 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 170 85 0 85 85 85 +170 170 170 170 85 0 170 170 170 85 85 85 170 170 170 170 85 0 +170 170 170 85 255 85 170 85 0 170 170 170 170 170 170 170 170 170 +255 255 255 170 170 170 255 255 255 255 255 255 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 85 0 170 170 170 255 255 85 170 170 170 255 255 255 170 170 170 +170 170 170 170 170 170 170 170 170 170 85 0 170 170 170 170 85 0 +170 170 170 85 255 85 170 85 0 170 170 170 170 85 0 85 85 85 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 255 85 170 170 170 170 85 0 170 170 170 170 85 0 85 255 85 +170 170 170 170 85 0 170 170 170 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 255 170 170 170 170 170 170 170 170 170 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 85 0 85 85 85 170 170 170 255 255 85 170 170 170 +170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 170 85 0 +170 170 170 85 85 85 170 170 170 170 85 0 170 170 170 85 85 85 +170 85 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 170 85 0 +85 85 85 255 85 85 85 255 85 170 85 0 170 170 170 170 170 170 +170 85 0 170 170 170 85 85 85 255 255 85 170 170 170 170 170 170 +255 255 255 170 170 170 255 255 255 255 255 85 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 170 85 0 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 255 255 85 85 85 85 170 170 170 +85 255 85 255 85 85 170 170 170 85 255 85 255 85 85 85 255 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 +85 85 85 85 255 85 255 85 85 170 170 170 85 255 85 170 85 0 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 255 255 255 +170 170 170 255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 170 170 170 85 85 85 255 255 85 +170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 255 255 85 +85 85 85 255 255 85 170 170 170 170 85 0 170 170 170 85 85 85 +170 85 0 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 170 85 0 170 170 170 170 85 0 170 170 170 170 170 170 +170 85 0 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 +255 255 85 255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 170 85 0 85 85 85 170 170 170 +170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 170 85 0 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +170 85 0 85 255 85 170 170 170 170 170 170 255 255 85 170 170 170 +255 255 85 170 170 170 170 170 170 170 170 170 255 255 255 255 255 255 +255 255 255 170 170 170 255 255 85 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 170 85 0 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 170 85 0 170 170 170 170 85 0 170 170 170 170 170 170 +170 170 170 255 255 85 170 170 170 255 255 85 170 170 170 255 255 255 +170 170 170 255 255 255 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +170 85 0 170 170 170 170 85 0 255 255 85 170 170 170 170 170 170 +170 170 170 170 170 170 255 255 85 170 170 170 255 255 85 170 170 170 +255 255 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 170 170 170 255 255 85 170 170 170 255 255 85 170 170 170 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +170 170 170 170 170 170 170 170 170 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 170 0 85 85 85 +170 85 0 85 255 85 170 170 170 170 170 170 170 170 170 255 255 85 +255 255 255 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 +170 170 170 255 255 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 85 0 170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 255 255 255 +255 255 255 255 255 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 +170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 +170 170 170 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 255 85 +170 170 170 255 255 85 170 170 170 255 255 85 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 +170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 170 85 0 170 170 170 170 170 170 +255 255 85 170 170 170 255 255 255 255 255 85 255 255 255 255 255 255 +170 170 170 255 255 85 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 85 0 +170 170 170 170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 +170 170 170 255 255 255 170 170 170 255 255 255 255 255 85 255 255 255 +170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 85 0 85 85 85 170 170 170 170 170 170 170 170 170 +170 170 170 255 255 255 170 170 170 255 255 255 255 255 255 170 170 170 +255 255 85 170 170 170 170 170 170 170 85 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +255 255 85 170 170 170 255 255 85 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 +170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 170 85 0 170 170 170 +255 255 85 170 170 170 255 255 85 255 255 255 170 170 170 255 255 255 +170 170 170 170 170 170 170 170 170 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +170 85 0 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 +255 255 255 255 255 255 170 170 170 255 255 255 255 255 85 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 170 85 0 85 85 85 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 +255 255 85 170 170 170 170 85 0 85 255 85 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 85 0 +170 170 170 170 170 170 255 255 85 170 170 170 255 255 255 255 255 255 +255 255 85 255 255 255 170 170 170 255 255 255 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 85 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +255 255 85 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 +255 255 255 170 170 170 255 255 85 170 170 170 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 170 85 0 170 170 170 170 170 170 170 170 170 170 170 170 +170 85 0 170 170 170 170 85 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 +170 170 170 255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 170 85 0 85 85 85 170 85 0 +85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 170 85 0 +85 85 85 170 85 0 170 170 170 170 170 170 170 170 170 255 255 85 +170 170 170 170 170 170 170 85 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 255 85 170 85 0 170 170 170 170 85 0 170 170 170 +85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 -- GitLab From 81a1d3c31e3517f9939b3e04d21cf4a6b0997419 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 16 Mar 2009 16:23:30 +0100 Subject: [PATCH 3533/4982] net: sysctl_net - use net_eq to compare nets Signed-off-by: Cyrill Gorcunov Acked-by: Daniel Lezcano Signed-off-by: Patrick McHardy --- net/sysctl_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sysctl_net.c b/net/sysctl_net.c index 972201cd5fa..0b15d7250c4 100644 --- a/net/sysctl_net.c +++ b/net/sysctl_net.c @@ -61,7 +61,7 @@ static struct ctl_table_root net_sysctl_root = { static int net_ctl_ro_header_perms(struct ctl_table_root *root, struct nsproxy *namespaces, struct ctl_table *table) { - if (namespaces->net_ns == &init_net) + if (net_eq(namespaces->net_ns, &init_net)) return table->mode; else return table->mode & ~0222; -- GitLab From 1546000fe8db0d3f47b0ef1dd487ec23fbd95313 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 16 Mar 2009 16:30:49 +0100 Subject: [PATCH 3534/4982] net: netfilter conntrack - add per-net functionality for DCCP protocol Module specific data moved into per-net site and being allocated/freed during net namespace creation/deletion. Signed-off-by: Cyrill Gorcunov Acked-by: Daniel Lezcano Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_proto_dccp.c | 145 ++++++++++++++++++------ 1 file changed, 108 insertions(+), 37 deletions(-) diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index 8fcf1762fab..d3d5a7fd73c 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c @@ -16,6 +16,9 @@ #include #include +#include +#include + #include #include #include @@ -23,8 +26,6 @@ static DEFINE_RWLOCK(dccp_lock); -static int nf_ct_dccp_loose __read_mostly = 1; - /* Timeouts are based on values from RFC4340: * * - REQUEST: @@ -72,16 +73,6 @@ static int nf_ct_dccp_loose __read_mostly = 1; #define DCCP_MSL (2 * 60 * HZ) -static unsigned int dccp_timeout[CT_DCCP_MAX + 1] __read_mostly = { - [CT_DCCP_REQUEST] = 2 * DCCP_MSL, - [CT_DCCP_RESPOND] = 4 * DCCP_MSL, - [CT_DCCP_PARTOPEN] = 4 * DCCP_MSL, - [CT_DCCP_OPEN] = 12 * 3600 * HZ, - [CT_DCCP_CLOSEREQ] = 64 * HZ, - [CT_DCCP_CLOSING] = 64 * HZ, - [CT_DCCP_TIMEWAIT] = 2 * DCCP_MSL, -}; - static const char * const dccp_state_names[] = { [CT_DCCP_NONE] = "NONE", [CT_DCCP_REQUEST] = "REQUEST", @@ -393,6 +384,22 @@ dccp_state_table[CT_DCCP_ROLE_MAX + 1][DCCP_PKT_SYNCACK + 1][CT_DCCP_MAX + 1] = }, }; +/* this module per-net specifics */ +static int dccp_net_id; +struct dccp_net { + int dccp_loose; + unsigned int dccp_timeout[CT_DCCP_MAX + 1]; +#ifdef CONFIG_SYSCTL + struct ctl_table_header *sysctl_header; + struct ctl_table *sysctl_table; +#endif +}; + +static inline struct dccp_net *dccp_pernet(struct net *net) +{ + return net_generic(net, dccp_net_id); +} + static bool dccp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, struct nf_conntrack_tuple *tuple) { @@ -419,6 +426,7 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb, unsigned int dataoff) { struct net *net = nf_ct_net(ct); + struct dccp_net *dn; struct dccp_hdr _dh, *dh; const char *msg; u_int8_t state; @@ -429,7 +437,8 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb, state = dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE]; switch (state) { default: - if (nf_ct_dccp_loose == 0) { + dn = dccp_pernet(net); + if (dn->dccp_loose == 0) { msg = "nf_ct_dccp: not picking up existing connection "; goto out_invalid; } @@ -465,6 +474,7 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, u_int8_t pf, unsigned int hooknum) { struct net *net = nf_ct_net(ct); + struct dccp_net *dn; enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); struct dccp_hdr _dh, *dh; u_int8_t type, old_state, new_state; @@ -542,7 +552,9 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, ct->proto.dccp.last_pkt = type; ct->proto.dccp.state = new_state; write_unlock_bh(&dccp_lock); - nf_ct_refresh_acct(ct, ctinfo, skb, dccp_timeout[new_state]); + + dn = dccp_pernet(net); + nf_ct_refresh_acct(ct, ctinfo, skb, dn->dccp_timeout[new_state]); return NF_ACCEPT; } @@ -660,13 +672,11 @@ static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct) #endif #ifdef CONFIG_SYSCTL -static unsigned int dccp_sysctl_table_users; -static struct ctl_table_header *dccp_sysctl_header; -static ctl_table dccp_sysctl_table[] = { +/* template, data assigned later */ +static struct ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_timeout_request", - .data = &dccp_timeout[CT_DCCP_REQUEST], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, @@ -674,7 +684,6 @@ static ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_timeout_respond", - .data = &dccp_timeout[CT_DCCP_RESPOND], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, @@ -682,7 +691,6 @@ static ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_timeout_partopen", - .data = &dccp_timeout[CT_DCCP_PARTOPEN], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, @@ -690,7 +698,6 @@ static ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_timeout_open", - .data = &dccp_timeout[CT_DCCP_OPEN], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, @@ -698,7 +705,6 @@ static ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_timeout_closereq", - .data = &dccp_timeout[CT_DCCP_CLOSEREQ], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, @@ -706,7 +712,6 @@ static ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_timeout_closing", - .data = &dccp_timeout[CT_DCCP_CLOSING], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, @@ -714,7 +719,6 @@ static ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_timeout_timewait", - .data = &dccp_timeout[CT_DCCP_TIMEWAIT], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, @@ -722,8 +726,7 @@ static ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_loose", - .data = &nf_ct_dccp_loose, - .maxlen = sizeof(nf_ct_dccp_loose), + .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec, }, @@ -751,11 +754,6 @@ static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = { .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy, #endif -#ifdef CONFIG_SYSCTL - .ctl_table_users = &dccp_sysctl_table_users, - .ctl_table_header = &dccp_sysctl_header, - .ctl_table = dccp_sysctl_table, -#endif }; static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = { @@ -776,34 +774,107 @@ static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = { .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy, #endif +}; + +static __net_init int dccp_net_init(struct net *net) +{ + struct dccp_net *dn; + int err; + + dn = kmalloc(sizeof(*dn), GFP_KERNEL); + if (!dn) + return -ENOMEM; + + /* default values */ + dn->dccp_loose = 1; + dn->dccp_timeout[CT_DCCP_REQUEST] = 2 * DCCP_MSL; + dn->dccp_timeout[CT_DCCP_RESPOND] = 4 * DCCP_MSL; + dn->dccp_timeout[CT_DCCP_PARTOPEN] = 4 * DCCP_MSL; + dn->dccp_timeout[CT_DCCP_OPEN] = 12 * 3600 * HZ; + dn->dccp_timeout[CT_DCCP_CLOSEREQ] = 64 * HZ; + dn->dccp_timeout[CT_DCCP_CLOSING] = 64 * HZ; + dn->dccp_timeout[CT_DCCP_TIMEWAIT] = 2 * DCCP_MSL; + + err = net_assign_generic(net, dccp_net_id, dn); + if (err) + goto out; + #ifdef CONFIG_SYSCTL - .ctl_table_users = &dccp_sysctl_table_users, - .ctl_table_header = &dccp_sysctl_header, - .ctl_table = dccp_sysctl_table, + err = -ENOMEM; + dn->sysctl_table = kmemdup(dccp_sysctl_table, + sizeof(dccp_sysctl_table), GFP_KERNEL); + if (!dn->sysctl_table) + goto out; + + dn->sysctl_table[0].data = &dn->dccp_timeout[CT_DCCP_REQUEST]; + dn->sysctl_table[1].data = &dn->dccp_timeout[CT_DCCP_RESPOND]; + dn->sysctl_table[2].data = &dn->dccp_timeout[CT_DCCP_PARTOPEN]; + dn->sysctl_table[3].data = &dn->dccp_timeout[CT_DCCP_OPEN]; + dn->sysctl_table[4].data = &dn->dccp_timeout[CT_DCCP_CLOSEREQ]; + dn->sysctl_table[5].data = &dn->dccp_timeout[CT_DCCP_CLOSING]; + dn->sysctl_table[6].data = &dn->dccp_timeout[CT_DCCP_TIMEWAIT]; + dn->sysctl_table[7].data = &dn->dccp_loose; + + dn->sysctl_header = register_net_sysctl_table(net, + nf_net_netfilter_sysctl_path, dn->sysctl_table); + if (!dn->sysctl_header) { + kfree(dn->sysctl_table); + goto out; + } #endif + + return 0; + +out: + kfree(dn); + return err; +} + +static __net_exit void dccp_net_exit(struct net *net) +{ + struct dccp_net *dn = dccp_pernet(net); +#ifdef CONFIG_SYSCTL + unregister_net_sysctl_table(dn->sysctl_header); + kfree(dn->sysctl_table); +#endif + kfree(dn); + + net_assign_generic(net, dccp_net_id, NULL); +} + +static struct pernet_operations dccp_net_ops = { + .init = dccp_net_init, + .exit = dccp_net_exit, }; static int __init nf_conntrack_proto_dccp_init(void) { int err; - err = nf_conntrack_l4proto_register(&dccp_proto4); + err = register_pernet_gen_subsys(&dccp_net_id, &dccp_net_ops); if (err < 0) goto err1; - err = nf_conntrack_l4proto_register(&dccp_proto6); + err = nf_conntrack_l4proto_register(&dccp_proto4); if (err < 0) goto err2; + + err = nf_conntrack_l4proto_register(&dccp_proto6); + if (err < 0) + goto err3; return 0; -err2: +err3: nf_conntrack_l4proto_unregister(&dccp_proto4); +err2: + unregister_pernet_gen_subsys(dccp_net_id, &dccp_net_ops); err1: return err; } static void __exit nf_conntrack_proto_dccp_fini(void) { + unregister_pernet_gen_subsys(dccp_net_id, &dccp_net_ops); nf_conntrack_l4proto_unregister(&dccp_proto6); nf_conntrack_l4proto_unregister(&dccp_proto4); } -- GitLab From 0269ea4937343536ec7e85649932bc8c9686ea78 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 16 Mar 2009 17:10:36 +0100 Subject: [PATCH 3535/4982] netfilter: xtables: add cluster match This patch adds the iptables cluster match. This match can be used to deploy gateway and back-end load-sharing clusters. The cluster can be composed of 32 nodes maximum (although I have only tested this with two nodes, so I cannot tell what is the real scalability limit of this solution in terms of cluster nodes). Assuming that all the nodes see all packets (see below for an example on how to do that if your switch does not allow this), the cluster match decides if this node has to handle a packet given: (jhash(source IP) % total_nodes) & node_mask For related connections, the master conntrack is used. The following is an example of its use to deploy a gateway cluster composed of two nodes (where this is the node 1): iptables -I PREROUTING -t mangle -i eth1 -m cluster \ --cluster-total-nodes 2 --cluster-local-node 1 \ --cluster-proc-name eth1 -j MARK --set-mark 0xffff iptables -A PREROUTING -t mangle -i eth1 \ -m mark ! --mark 0xffff -j DROP iptables -A PREROUTING -t mangle -i eth2 -m cluster \ --cluster-total-nodes 2 --cluster-local-node 1 \ --cluster-proc-name eth2 -j MARK --set-mark 0xffff iptables -A PREROUTING -t mangle -i eth2 \ -m mark ! --mark 0xffff -j DROP And the following commands to make all nodes see the same packets: ip maddr add 01:00:5e:00:01:01 dev eth1 ip maddr add 01:00:5e:00:01:02 dev eth2 arptables -I OUTPUT -o eth1 --h-length 6 \ -j mangle --mangle-mac-s 01:00:5e:00:01:01 arptables -I INPUT -i eth1 --h-length 6 \ --destination-mac 01:00:5e:00:01:01 \ -j mangle --mangle-mac-d 00:zz:yy:xx:5a:27 arptables -I OUTPUT -o eth2 --h-length 6 \ -j mangle --mangle-mac-s 01:00:5e:00:01:02 arptables -I INPUT -i eth2 --h-length 6 \ --destination-mac 01:00:5e:00:01:02 \ -j mangle --mangle-mac-d 00:zz:yy:xx:5a:27 In the case of TCP connections, pickup facility has to be disabled to avoid marking TCP ACK packets coming in the reply direction as valid. echo 0 > /proc/sys/net/netfilter/nf_conntrack_tcp_loose BTW, some final notes: * This match mangles the skbuff pkt_type in case that it detects PACKET_MULTICAST for a non-multicast address. This may be done in a PKTTYPE target for this sole purpose. * This match supersedes the CLUSTERIP target. Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy --- include/linux/netfilter/Kbuild | 1 + include/linux/netfilter/xt_cluster.h | 15 +++ net/netfilter/Kconfig | 16 +++ net/netfilter/Makefile | 1 + net/netfilter/xt_cluster.c | 164 +++++++++++++++++++++++++++ 5 files changed, 197 insertions(+) create mode 100644 include/linux/netfilter/xt_cluster.h create mode 100644 net/netfilter/xt_cluster.c diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild index 947b47d7f6c..af9d2fb9721 100644 --- a/include/linux/netfilter/Kbuild +++ b/include/linux/netfilter/Kbuild @@ -21,6 +21,7 @@ header-y += xt_connbytes.h header-y += xt_connlimit.h header-y += xt_connmark.h header-y += xt_conntrack.h +header-y += xt_cluster.h header-y += xt_dccp.h header-y += xt_dscp.h header-y += xt_esp.h diff --git a/include/linux/netfilter/xt_cluster.h b/include/linux/netfilter/xt_cluster.h new file mode 100644 index 00000000000..5e0a0d07b52 --- /dev/null +++ b/include/linux/netfilter/xt_cluster.h @@ -0,0 +1,15 @@ +#ifndef _XT_CLUSTER_MATCH_H +#define _XT_CLUSTER_MATCH_H + +enum xt_cluster_flags { + XT_CLUSTER_F_INV = (1 << 0) +}; + +struct xt_cluster_match_info { + u_int32_t total_nodes; + u_int32_t node_mask; + u_int32_t hash_seed; + u_int32_t flags; +}; + +#endif /* _XT_CLUSTER_MATCH_H */ diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index cdbaaff6d0d..2562d05dbaf 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -527,6 +527,22 @@ config NETFILTER_XT_TARGET_TCPOPTSTRIP This option adds a "TCPOPTSTRIP" target, which allows you to strip TCP options from TCP packets. +config NETFILTER_XT_MATCH_CLUSTER + tristate '"cluster" match support' + depends on NF_CONNTRACK + depends on NETFILTER_ADVANCED + ---help--- + This option allows you to build work-load-sharing clusters of + network servers/stateful firewalls without having a dedicated + load-balancing router/server/switch. Basically, this match returns + true when the packet must be handled by this cluster node. Thus, + all nodes see all packets and this match decides which node handles + what packets. The work-load sharing algorithm is based on source + address hashing. + + If you say Y or M here, try `iptables -m cluster --help` for + more information. + config NETFILTER_XT_MATCH_COMMENT tristate '"comment" match support' depends on NETFILTER_ADVANCED diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 7a9b8397573..6282060fbda 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -59,6 +59,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP) += xt_TCPOPTSTRIP.o obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o # matches +obj-$(CONFIG_NETFILTER_XT_MATCH_CLUSTER) += xt_cluster.o obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o obj-$(CONFIG_NETFILTER_XT_MATCH_CONNLIMIT) += xt_connlimit.o diff --git a/net/netfilter/xt_cluster.c b/net/netfilter/xt_cluster.c new file mode 100644 index 00000000000..ad5bd890e4e --- /dev/null +++ b/net/netfilter/xt_cluster.c @@ -0,0 +1,164 @@ +/* + * (C) 2008-2009 Pablo Neira Ayuso + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include + +#include +#include +#include + +static inline u_int32_t nf_ct_orig_ipv4_src(const struct nf_conn *ct) +{ + return ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip; +} + +static inline const void *nf_ct_orig_ipv6_src(const struct nf_conn *ct) +{ + return ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip6; +} + +static inline u_int32_t +xt_cluster_hash_ipv4(u_int32_t ip, const struct xt_cluster_match_info *info) +{ + return jhash_1word(ip, info->hash_seed); +} + +static inline u_int32_t +xt_cluster_hash_ipv6(const void *ip, const struct xt_cluster_match_info *info) +{ + return jhash2(ip, NF_CT_TUPLE_L3SIZE / sizeof(__u32), info->hash_seed); +} + +static inline u_int32_t +xt_cluster_hash(const struct nf_conn *ct, + const struct xt_cluster_match_info *info) +{ + u_int32_t hash = 0; + + switch(nf_ct_l3num(ct)) { + case AF_INET: + hash = xt_cluster_hash_ipv4(nf_ct_orig_ipv4_src(ct), info); + break; + case AF_INET6: + hash = xt_cluster_hash_ipv6(nf_ct_orig_ipv6_src(ct), info); + break; + default: + WARN_ON(1); + break; + } + return (((u64)hash * info->total_nodes) >> 32); +} + +static inline bool +xt_cluster_is_multicast_addr(const struct sk_buff *skb, u_int8_t family) +{ + bool is_multicast = false; + + switch(family) { + case NFPROTO_IPV4: + is_multicast = ipv4_is_multicast(ip_hdr(skb)->daddr); + break; + case NFPROTO_IPV6: + is_multicast = ipv6_addr_type(&ipv6_hdr(skb)->daddr) & + IPV6_ADDR_MULTICAST; + break; + default: + WARN_ON(1); + break; + } + return is_multicast; +} + +static bool +xt_cluster_mt(const struct sk_buff *skb, const struct xt_match_param *par) +{ + struct sk_buff *pskb = (struct sk_buff *)skb; + const struct xt_cluster_match_info *info = par->matchinfo; + const struct nf_conn *ct; + enum ip_conntrack_info ctinfo; + unsigned long hash; + + /* This match assumes that all nodes see the same packets. This can be + * achieved if the switch that connects the cluster nodes support some + * sort of 'port mirroring'. However, if your switch does not support + * this, your cluster nodes can reply ARP request using a multicast MAC + * address. Thus, your switch will flood the same packets to the + * cluster nodes with the same multicast MAC address. Using a multicast + * link address is a RFC 1812 (section 3.3.2) violation, but this works + * fine in practise. + * + * Unfortunately, if you use the multicast MAC address, the link layer + * sets skbuff's pkt_type to PACKET_MULTICAST, which is not accepted + * by TCP and others for packets coming to this node. For that reason, + * this match mangles skbuff's pkt_type if it detects a packet + * addressed to a unicast address but using PACKET_MULTICAST. Yes, I + * know, matches should not alter packets, but we are doing this here + * because we would need to add a PKTTYPE target for this sole purpose. + */ + if (!xt_cluster_is_multicast_addr(skb, par->family) && + skb->pkt_type == PACKET_MULTICAST) { + pskb->pkt_type = PACKET_HOST; + } + + ct = nf_ct_get(skb, &ctinfo); + if (ct == NULL) + return false; + + if (ct == &nf_conntrack_untracked) + return false; + + if (ct->master) + hash = xt_cluster_hash(ct->master, info); + else + hash = xt_cluster_hash(ct, info); + + return !!((1 << hash) & info->node_mask) ^ + !!(info->flags & XT_CLUSTER_F_INV); +} + +static bool xt_cluster_mt_checkentry(const struct xt_mtchk_param *par) +{ + struct xt_cluster_match_info *info = par->matchinfo; + + if (info->node_mask >= (1 << info->total_nodes)) { + printk(KERN_ERR "xt_cluster: this node mask cannot be " + "higher than the total number of nodes\n"); + return false; + } + return true; +} + +static struct xt_match xt_cluster_match __read_mostly = { + .name = "cluster", + .family = NFPROTO_UNSPEC, + .match = xt_cluster_mt, + .checkentry = xt_cluster_mt_checkentry, + .matchsize = sizeof(struct xt_cluster_match_info), + .me = THIS_MODULE, +}; + +static int __init xt_cluster_mt_init(void) +{ + return xt_register_match(&xt_cluster_match); +} + +static void __exit xt_cluster_mt_fini(void) +{ + xt_unregister_match(&xt_cluster_match); +} + +MODULE_AUTHOR("Pablo Neira Ayuso "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Xtables: hash-based cluster match"); +MODULE_ALIAS("ipt_cluster"); +MODULE_ALIAS("ip6t_cluster"); +module_init(xt_cluster_mt_init); +module_exit(xt_cluster_mt_fini); -- GitLab From bc0fd67feba2e0770aad85393500ba77c6489f1c Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Mon, 16 Mar 2009 16:56:01 +0000 Subject: [PATCH 3536/4982] dm ioctl: validate name length when renaming When renaming a mapped device validate the length of the new name. The rename ioctl accepted any correctly-terminated string enclosed within the data passed from userspace. The other ioctls enforce a size limit of DM_NAME_LEN. If the name is changed and becomes longer than that, the device can no longer be addressed by name. Fix it by properly checking for device name length (including terminating zero). Cc: stable@kernel.org Signed-off-by: Milan Broz Reviewed-by: Jonathan Brassow Reviewed-by: Alasdair G Kergon Signed-off-by: Alasdair G Kergon --- drivers/md/dm-ioctl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 54d0588fc1f..977f36612e8 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -704,7 +704,8 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size) char *new_name = (char *) param + param->data_start; if (new_name < param->data || - invalid_str(new_name, (void *) param + param_size)) { + invalid_str(new_name, (void *) param + param_size) || + strlen(new_name) > DM_NAME_LEN - 1) { DMWARN("Invalid new logical volume name supplied."); return -EINVAL; } -- GitLab From f80a557008462a0a4adef25407f1872e793d8dd5 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Mon, 16 Mar 2009 17:44:26 +0000 Subject: [PATCH 3537/4982] dm table: rework reference counting fix Fix an error introduced in dm-table-rework-reference-counting.patch. When there is failure after table initialization, we need to use dm_table_destroy, not dm_table_put, to free the table. dm_table_put may be used only after dm_table_get. Cc: Kiyoshi Ueda Signed-off-by: Mikulas Patocka Reviewed-by: Jonathan Brassow Reviewed-by: Alasdair G Kergon Signed-off-by: Alasdair G Kergon --- drivers/md/dm-ioctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 977f36612e8..f01096549a9 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1064,7 +1064,7 @@ static int table_load(struct dm_ioctl *param, size_t param_size) r = populate_table(t, param, param_size); if (r) { - dm_table_put(t); + dm_table_destroy(t); goto out; } @@ -1072,7 +1072,7 @@ static int table_load(struct dm_ioctl *param, size_t param_size) hc = dm_get_mdptr(md); if (!hc || hc->md != md) { DMWARN("device has been removed from the dev hash table."); - dm_table_put(t); + dm_table_destroy(t); up_write(&_hash_lock); r = -ENXIO; goto out; -- GitLab From d659e6cc98766a1a61d6bdd283f95d149abd7719 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Mon, 16 Mar 2009 17:44:30 +0000 Subject: [PATCH 3538/4982] dm io: respect BIO_MAX_PAGES limit dm-io calls bio_get_nr_vecs to get the maximum number of pages to use for a given device. It allocates one additional bio_vec to use internally but failed to respect BIO_MAX_PAGES, so fix this. This was the likely cause of: https://bugzilla.redhat.com/show_bug.cgi?id=173153 Cc: stable@kernel.org Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon --- drivers/md/dm-io.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index f14813be4ef..36e2b5e46a6 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -292,6 +292,8 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, (PAGE_SIZE >> SECTOR_SHIFT)); num_bvecs = 1 + min_t(int, bio_get_nr_vecs(where->bdev), num_bvecs); + if (unlikely(num_bvecs > BIO_MAX_PAGES)) + num_bvecs = BIO_MAX_PAGES; bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, io->client->bios); bio->bi_sector = where->sector + (where->count - remaining); bio->bi_bdev = where->bdev; -- GitLab From b2174eebd1fadb76454dad09a1dacbc17081e6b0 Mon Sep 17 00:00:00 2001 From: Huang Ying Date: Mon, 16 Mar 2009 17:44:33 +0000 Subject: [PATCH 3539/4982] dm crypt: fix kcryptd_async_done parameter In the async encryption-complete function (kcryptd_async_done), the crypto_async_request passed in may be different from the one passed to crypto_ablkcipher_encrypt/decrypt. Only crypto_async_request->data is guaranteed to be same as the one passed in. The current kcryptd_async_done uses the passed-in crypto_async_request directly which may cause the AES-NI-based AES algorithm implementation to panic. This patch fixes this bug by only using crypto_async_request->data, which points to dm_crypt_request, the crypto_async_request passed in. The original data (convert_context) is gotten from dm_crypt_request. [mbroz@redhat.com: reworked] Cc: stable@kernel.org Signed-off-by: Huang Ying Cc: Herbert Xu Signed-off-by: Milan Broz Signed-off-by: Andrew Morton Signed-off-by: Alasdair G Kergon --- drivers/md/dm-crypt.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 35bda49796f..ebab49f8cc1 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -60,6 +60,7 @@ struct dm_crypt_io { }; struct dm_crypt_request { + struct convert_context *ctx; struct scatterlist sg_in; struct scatterlist sg_out; }; @@ -335,6 +336,18 @@ static void crypt_convert_init(struct crypt_config *cc, init_completion(&ctx->restart); } +static struct dm_crypt_request *dmreq_of_req(struct crypt_config *cc, + struct ablkcipher_request *req) +{ + return (struct dm_crypt_request *)((char *)req + cc->dmreq_start); +} + +static struct ablkcipher_request *req_of_dmreq(struct crypt_config *cc, + struct dm_crypt_request *dmreq) +{ + return (struct ablkcipher_request *)((char *)dmreq - cc->dmreq_start); +} + static int crypt_convert_block(struct crypt_config *cc, struct convert_context *ctx, struct ablkcipher_request *req) @@ -345,10 +358,11 @@ static int crypt_convert_block(struct crypt_config *cc, u8 *iv; int r = 0; - dmreq = (struct dm_crypt_request *)((char *)req + cc->dmreq_start); + dmreq = dmreq_of_req(cc, req); iv = (u8 *)ALIGN((unsigned long)(dmreq + 1), crypto_ablkcipher_alignmask(cc->tfm) + 1); + dmreq->ctx = ctx; sg_init_table(&dmreq->sg_in, 1); sg_set_page(&dmreq->sg_in, bv_in->bv_page, 1 << SECTOR_SHIFT, bv_in->bv_offset + ctx->offset_in); @@ -395,8 +409,9 @@ static void crypt_alloc_req(struct crypt_config *cc, cc->req = mempool_alloc(cc->req_pool, GFP_NOIO); ablkcipher_request_set_tfm(cc->req, cc->tfm); ablkcipher_request_set_callback(cc->req, CRYPTO_TFM_REQ_MAY_BACKLOG | - CRYPTO_TFM_REQ_MAY_SLEEP, - kcryptd_async_done, ctx); + CRYPTO_TFM_REQ_MAY_SLEEP, + kcryptd_async_done, + dmreq_of_req(cc, cc->req)); } /* @@ -821,7 +836,8 @@ static void kcryptd_crypt_read_convert(struct dm_crypt_io *io) static void kcryptd_async_done(struct crypto_async_request *async_req, int error) { - struct convert_context *ctx = async_req->data; + struct dm_crypt_request *dmreq = async_req->data; + struct convert_context *ctx = dmreq->ctx; struct dm_crypt_io *io = container_of(ctx, struct dm_crypt_io, ctx); struct crypt_config *cc = io->target->private; @@ -830,7 +846,7 @@ static void kcryptd_async_done(struct crypto_async_request *async_req, return; } - mempool_free(ablkcipher_request_cast(async_req), cc->req_pool); + mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool); if (!atomic_dec_and_test(&ctx->pending)) return; -- GitLab From b35f8caa0890169000fec22902290d9a15274cbd Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Mon, 16 Mar 2009 17:44:36 +0000 Subject: [PATCH 3540/4982] dm crypt: wait for endio to complete before destruction The following oops has been reported when dm-crypt runs over a loop device. ... [ 70.381058] Process loop0 (pid: 4268, ti=cf3b2000 task=cf1cc1f0 task.ti=cf3b2000) ... [ 70.381058] Call Trace: [ 70.381058] [] ? crypt_dec_pending+0x5e/0x62 [dm_crypt] [ 70.381058] [] ? crypt_endio+0xa2/0xaa [dm_crypt] [ 70.381058] [] ? crypt_endio+0x0/0xaa [dm_crypt] [ 70.381058] [] ? bio_endio+0x2b/0x2e [ 70.381058] [] ? dec_pending+0x224/0x23b [dm_mod] [ 70.381058] [] ? clone_endio+0x79/0xa4 [dm_mod] [ 70.381058] [] ? clone_endio+0x0/0xa4 [dm_mod] [ 70.381058] [] ? bio_endio+0x2b/0x2e [ 70.381058] [] ? loop_thread+0x380/0x3b7 [ 70.381058] [] ? do_lo_send_aops+0x0/0x165 [ 70.381058] [] ? autoremove_wake_function+0x0/0x33 [ 70.381058] [] ? loop_thread+0x0/0x3b7 When a table is being replaced, it waits for I/O to complete before destroying the mempool, but the endio function doesn't call mempool_free() until after completing the bio. Fix it by swapping the order of those two operations. The same problem occurs in dm.c with md referenced after dec_pending. Again, we swap the order. Cc: stable@kernel.org Signed-off-by: Milan Broz Signed-off-by: Alasdair G Kergon --- drivers/md/dm-crypt.c | 17 ++++++++++------- drivers/md/dm.c | 32 +++++++++++++++++++------------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index ebab49f8cc1..bfefd079a95 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -568,19 +568,22 @@ static void crypt_inc_pending(struct dm_crypt_io *io) static void crypt_dec_pending(struct dm_crypt_io *io) { struct crypt_config *cc = io->target->private; + struct bio *base_bio = io->base_bio; + struct dm_crypt_io *base_io = io->base_io; + int error = io->error; if (!atomic_dec_and_test(&io->pending)) return; - if (likely(!io->base_io)) - bio_endio(io->base_bio, io->error); + mempool_free(io, cc->io_pool); + + if (likely(!base_io)) + bio_endio(base_bio, error); else { - if (io->error && !io->base_io->error) - io->base_io->error = io->error; - crypt_dec_pending(io->base_io); + if (error && !base_io->error) + base_io->error = error; + crypt_dec_pending(base_io); } - - mempool_free(io, cc->io_pool); } /* diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 51ba1db4b3e..8d40f27cce8 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -525,9 +525,12 @@ static int __noflush_suspending(struct mapped_device *md) static void dec_pending(struct dm_io *io, int error) { unsigned long flags; + int io_error; + struct bio *bio; + struct mapped_device *md = io->md; /* Push-back supersedes any I/O errors */ - if (error && !(io->error > 0 && __noflush_suspending(io->md))) + if (error && !(io->error > 0 && __noflush_suspending(md))) io->error = error; if (atomic_dec_and_test(&io->io_count)) { @@ -537,24 +540,27 @@ static void dec_pending(struct dm_io *io, int error) * This must be handled before the sleeper on * suspend queue merges the pushback list. */ - spin_lock_irqsave(&io->md->pushback_lock, flags); - if (__noflush_suspending(io->md)) - bio_list_add(&io->md->pushback, io->bio); + spin_lock_irqsave(&md->pushback_lock, flags); + if (__noflush_suspending(md)) + bio_list_add(&md->pushback, io->bio); else /* noflush suspend was interrupted. */ io->error = -EIO; - spin_unlock_irqrestore(&io->md->pushback_lock, flags); + spin_unlock_irqrestore(&md->pushback_lock, flags); } end_io_acct(io); - if (io->error != DM_ENDIO_REQUEUE) { - trace_block_bio_complete(io->md->queue, io->bio); + io_error = io->error; + bio = io->bio; - bio_endio(io->bio, io->error); - } + free_io(md, io); + + if (io_error != DM_ENDIO_REQUEUE) { + trace_block_bio_complete(md->queue, bio); - free_io(io->md, io); + bio_endio(bio, io_error); + } } } @@ -562,6 +568,7 @@ static void clone_endio(struct bio *bio, int error) { int r = 0; struct dm_target_io *tio = bio->bi_private; + struct dm_io *io = tio->io; struct mapped_device *md = tio->io->md; dm_endio_fn endio = tio->ti->type->end_io; @@ -585,15 +592,14 @@ static void clone_endio(struct bio *bio, int error) } } - dec_pending(tio->io, error); - /* * Store md for cleanup instead of tio which is about to get freed. */ bio->bi_private = md->bs; - bio_put(bio); free_tio(md, tio); + bio_put(bio); + dec_pending(io, error); } static sector_t max_io_len(struct mapped_device *md, -- GitLab From d1c76af9e2434fac3add561e26c61b06503de986 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 16 Mar 2009 10:50:02 -0700 Subject: [PATCH 3541/4982] GRO: Move netpoll checks to correct location As my netpoll fix for net doesn't really work for net-next, we need this update to move the checks into the right place. As it stands we may pass freed skbs to netpoll_receive_skb. This patch also introduces a netpoll_rx_on function to avoid GRO completely if we're invoked through netpoll. This might seem paranoid but as netpoll may have an external receive hook it's better to be safe than sorry. I don't think we need this for 2.6.29 though since there's nothing immediately broken by it. This patch also moves the GRO_* return values to netdevice.h since VLAN needs them too (I tried to avoid this originally but alas this seems to be the easiest way out). This fixes a bug in VLAN where it continued to use the old return value 2 instead of the correct GRO_DROP. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- include/linux/netdevice.h | 8 ++++++++ include/linux/netpoll.h | 11 +++++++++++ net/8021q/vlan_core.c | 11 ++++------- net/core/dev.c | 17 +++-------------- 4 files changed, 26 insertions(+), 21 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 493b065f76d..be3ebd7e8ce 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -330,6 +330,14 @@ enum NAPI_STATE_NPSVC, /* Netpoll - don't dequeue from poll_list */ }; +enum { + GRO_MERGED, + GRO_MERGED_FREE, + GRO_HELD, + GRO_NORMAL, + GRO_DROP, +}; + extern void __napi_schedule(struct napi_struct *n); static inline int napi_disable_pending(struct napi_struct *n) diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index e38d3c9dccd..de99025f2c5 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -63,6 +63,13 @@ static inline int netpoll_rx(struct sk_buff *skb) return ret; } +static inline int netpoll_rx_on(struct sk_buff *skb) +{ + struct netpoll_info *npinfo = skb->dev->npinfo; + + return npinfo && (npinfo->rx_np || npinfo->rx_flags); +} + static inline int netpoll_receive_skb(struct sk_buff *skb) { if (!list_empty(&skb->dev->napi_list)) @@ -99,6 +106,10 @@ static inline int netpoll_rx(struct sk_buff *skb) { return 0; } +static inline int netpoll_rx_on(struct sk_buff *skb) +{ + return 0; +} static inline int netpoll_receive_skb(struct sk_buff *skb) { return 0; diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 2d6e405fc49..6227248597c 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -79,6 +79,9 @@ static int vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp, { struct sk_buff *p; + if (netpoll_rx_on(skb)) + return GRO_NORMAL; + if (skb_bond_should_drop(skb)) goto drop; @@ -98,7 +101,7 @@ static int vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp, return dev_gro_receive(napi, skb); drop: - return 2; + return GRO_DROP; } int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, @@ -106,9 +109,6 @@ int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, { skb_gro_reset_offset(skb); - if (netpoll_receive_skb(skb)) - return NET_RX_DROP; - return napi_skb_finish(vlan_gro_common(napi, grp, vlan_tci, skb), skb); } EXPORT_SYMBOL(vlan_gro_receive); @@ -121,9 +121,6 @@ int vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, if (!skb) return NET_RX_DROP; - if (netpoll_receive_skb(skb)) - return NET_RX_DROP; - return napi_frags_finish(napi, skb, vlan_gro_common(napi, grp, vlan_tci, skb)); } diff --git a/net/core/dev.c b/net/core/dev.c index 033d7ca28e6..7bd3c29c5a7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -135,14 +135,6 @@ /* This should be increased if a protocol with a bigger head is added. */ #define GRO_MAX_HEAD (MAX_HEADER + 128) -enum { - GRO_MERGED, - GRO_MERGED_FREE, - GRO_HELD, - GRO_NORMAL, - GRO_DROP, -}; - /* * The list of packet types we will receive (as opposed to discard) * and the routines to invoke. @@ -2474,6 +2466,9 @@ static int __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) { struct sk_buff *p; + if (netpoll_rx_on(skb)) + return GRO_NORMAL; + for (p = napi->gro_list; p; p = p->next) { NAPI_GRO_CB(p)->same_flow = !compare_ether_header( skb_mac_header(p), skb_gro_mac_header(skb)); @@ -2487,9 +2482,6 @@ int napi_skb_finish(int ret, struct sk_buff *skb) { int err = NET_RX_SUCCESS; - if (netpoll_receive_skb(skb)) - return NET_RX_DROP; - switch (ret) { case GRO_NORMAL: return netif_receive_skb(skb); @@ -2587,9 +2579,6 @@ int napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb, int ret) { int err = NET_RX_SUCCESS; - if (netpoll_receive_skb(skb)) - return NET_RX_DROP; - switch (ret) { case GRO_NORMAL: case GRO_HELD: -- GitLab From 6f16bf3bdb94b567e2b6663378efb2dbf40db133 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 11 Mar 2009 11:05:25 -0400 Subject: [PATCH 3542/4982] lib80211: silence excessive crypto debugging messages When they were part of the now defunct ieee80211 component, these messages were only visible when special debugging settings were enabled. Let's mirror that with a new lib80211 debugging Kconfig option. Signed-off-by: John W. Linville --- net/wireless/Kconfig | 10 ++++++++++ net/wireless/lib80211_crypt_ccmp.c | 2 ++ net/wireless/lib80211_crypt_tkip.c | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index e28e2b8fa43..092ae6faccc 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig @@ -102,3 +102,13 @@ config LIB80211_CRYPT_CCMP config LIB80211_CRYPT_TKIP tristate + +config LIB80211_DEBUG + bool "lib80211 debugging messages" + depends on LIB80211 + default n + ---help--- + You can enable this if you want verbose debugging messages + from lib80211. + + If unsure, say N. diff --git a/net/wireless/lib80211_crypt_ccmp.c b/net/wireless/lib80211_crypt_ccmp.c index db428194c16..2301dc1edc4 100644 --- a/net/wireless/lib80211_crypt_ccmp.c +++ b/net/wireless/lib80211_crypt_ccmp.c @@ -337,6 +337,7 @@ static int lib80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) pos += 8; if (ccmp_replay_check(pn, key->rx_pn)) { +#ifdef CONFIG_LIB80211_DEBUG if (net_ratelimit()) { printk(KERN_DEBUG "CCMP: replay detected: STA=%pM " "previous PN %02x%02x%02x%02x%02x%02x " @@ -346,6 +347,7 @@ static int lib80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) key->rx_pn[3], key->rx_pn[4], key->rx_pn[5], pn[0], pn[1], pn[2], pn[3], pn[4], pn[5]); } +#endif key->dot11RSNAStatsCCMPReplays++; return -4; } diff --git a/net/wireless/lib80211_crypt_tkip.c b/net/wireless/lib80211_crypt_tkip.c index 7e8e22bfed9..c36287399d7 100644 --- a/net/wireless/lib80211_crypt_tkip.c +++ b/net/wireless/lib80211_crypt_tkip.c @@ -465,12 +465,14 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) pos += 8; if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) { +#ifdef CONFIG_LIB80211_DEBUG if (net_ratelimit()) { printk(KERN_DEBUG "TKIP: replay detected: STA=%pM" " previous TSC %08x%04x received TSC " "%08x%04x\n", hdr->addr2, tkey->rx_iv32, tkey->rx_iv16, iv32, iv16); } +#endif tkey->dot11RSNAStatsTKIPReplays++; return -4; } @@ -505,10 +507,12 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) * it needs to be recalculated for the next packet. */ tkey->rx_phase1_done = 0; } +#ifdef CONFIG_LIB80211_DEBUG if (net_ratelimit()) { printk(KERN_DEBUG "TKIP: ICV error detected: STA=" "%pM\n", hdr->addr2); } +#endif tkey->dot11RSNAStatsTKIPICVErrors++; return -5; } -- GitLab From 6158425be398936af1fd04451f78ffad01529cb0 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 12 Mar 2009 18:18:49 -0400 Subject: [PATCH 3543/4982] ath9k: implement IO serialization All 802.11n PCI devices (Cardbus, PCI, mini-PCI) require serialization of IO when on non-uniprocessor systems. PCI express devices not not require this. This should fix our only last standing open ath9k kernel.org bugzilla bug report: http://bugzilla.kernel.org/show_bug.cgi?id=12110 A port is probably required to older kernels and I can work on that. Cc: stable@kernel.org Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ath9k.h | 4 ++-- drivers/net/wireless/ath9k/core.h | 33 ++++++++++++++++++++++++++++++ drivers/net/wireless/ath9k/hw.c | 19 +++++++++++++++++ drivers/net/wireless/ath9k/main.c | 1 + 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index d2781350295..6650f609ece 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -587,8 +587,8 @@ struct ath9k_country_entry { u8 iso[3]; }; -#define REG_WRITE(_ah, _reg, _val) iowrite32(_val, _ah->ah_sh + _reg) -#define REG_READ(_ah, _reg) ioread32(_ah->ah_sh + _reg) +#define REG_WRITE(_ah, _reg, _val) ath9k_iowrite32((_ah), (_reg), (_val)) +#define REG_READ(_ah, _reg) ath9k_ioread32((_ah), (_reg)) #define SM(_v, _f) (((_v) << _f##_S) & _f) #define MS(_v, _f) (((_v) & _f) >> _f##_S) diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index 4ca2aed236e..139566cbbf6 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -701,6 +701,7 @@ struct ath_softc { struct ath_hal *sc_ah; void __iomem *mem; spinlock_t sc_resetlock; + spinlock_t sc_serial_rw; struct mutex mutex; u8 sc_curbssid[ETH_ALEN]; @@ -751,4 +752,36 @@ int ath_get_hal_qnum(u16 queue, struct ath_softc *sc); int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); int ath_cabq_update(struct ath_softc *); +/* + * Read and write, they both share the same lock. We do this to serialize + * reads and writes on Atheros 802.11n PCI devices only. This is required + * as the FIFO on these devices can only accept sanely 2 requests. After + * that the device goes bananas. Serializing the reads/writes prevents this + * from happening. + */ + +static inline void ath9k_iowrite32(struct ath_hal *ah, u32 reg_offset, u32 val) +{ + if (ah->ah_config.serialize_regmode == SER_REG_MODE_ON) { + unsigned long flags; + spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); + iowrite32(val, ah->ah_sc->mem + reg_offset); + spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); + } else + iowrite32(val, ah->ah_sc->mem + reg_offset); +} + +static inline unsigned int ath9k_ioread32(struct ath_hal *ah, u32 reg_offset) +{ + u32 val; + if (ah->ah_config.serialize_regmode == SER_REG_MODE_ON) { + unsigned long flags; + spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); + val = ioread32(ah->ah_sc->mem + reg_offset); + spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); + } else + val = ioread32(ah->ah_sc->mem + reg_offset); + return val; +} + #endif /* CORE_H */ diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 34474edefc9..5c870436fc5 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -437,6 +437,25 @@ static void ath9k_hw_set_defaults(struct ath_hal *ah) } ah->ah_config.intr_mitigation = 1; + + /* + * We need this for PCI devices only (Cardbus, PCI, miniPCI) + * _and_ if on non-uniprocessor systems (Multiprocessor/HT). + * This means we use it for all AR5416 devices, and the few + * minor PCI AR9280 devices out there. + * + * Serialization is required because these devices do not handle + * well the case of two concurrent reads/writes due to the latency + * involved. During one read/write another read/write can be issued + * on another CPU while the previous read/write may still be working + * on our hardware, if we hit this case the hardware poops in a loop. + * We prevent this by serializing reads and writes. + * + * This issue is not present on PCI-Express devices or pre-AR5416 + * devices (legacy, 802.11abg). + */ + if (num_possible_cpus() > 1) + ah->ah_config.serialize_regmode = SER_REG_MODE_AUTO; } static struct ath_hal_5416 *ath9k_hw_newstate(u16 devid, diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 0e80990d8e8..3c04044a60b 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1336,6 +1336,7 @@ static int ath_init(u16 devid, struct ath_softc *sc) printk(KERN_ERR "Unable to create debugfs files\n"); spin_lock_init(&sc->sc_resetlock); + spin_lock_init(&sc->sc_serial_rw); mutex_init(&sc->mutex); tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, -- GitLab From 5ec905a8df3fa877566ba98298433fbfb3d688cc Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 12 Mar 2009 18:18:50 -0400 Subject: [PATCH 3544/4982] ath9k: AR9280 PCI devices must serialize IO as well Cc: stable@kernel.org Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/hw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 5c870436fc5..c38a00bbce6 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -687,7 +687,8 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, } if (ah->ah_config.serialize_regmode == SER_REG_MODE_AUTO) { - if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) { + if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCI || + (AR_SREV_9280(ah) && !ah->ah_isPciExpress)) { ah->ah_config.serialize_regmode = SER_REG_MODE_ON; } else { -- GitLab From 055249d20de06c290fe7625be0a7164bef3958f5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 13 Mar 2009 13:59:39 +0200 Subject: [PATCH 3545/4982] mac80211: Fix panic on fragmentation with power saving It was possible to hit a kernel panic on NULL pointer dereference in dev_queue_xmit() when sending power save buffered frames to a STA that woke up from sleep. This happened when the buffered frame was requeued for transmission in ap_sta_ps_end(). In order to avoid the panic, copy the skb->dev and skb->iif values from the first fragment to all other fragments. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/mac80211/tx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 94de5033f0b..37e3d5ef7e3 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -752,6 +752,8 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) skb_copy_queue_mapping(frag, first); frag->do_not_encrypt = first->do_not_encrypt; + frag->dev = first->dev; + frag->iif = first->iif; pos += copylen; left -= copylen; -- GitLab From 640c65eae673d2caf6e7bf61c1eb4e9513b88fda Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 16 Mar 2009 21:47:33 +0200 Subject: [PATCH 3546/4982] zd1211rw: Do not panic on device eject when associated zd_op_tx() must not return an arbitrary error value since that can leave mac80211 trying to retransmit the frame and with the extra data pushed into the beginning of the skb on every attempt, this will end up causing a kernel panic (skb_under_panic from skb_push call). This can happen, e.g., when ejecting the device when associated. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_mac.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index a611ad85798..847057d682b 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -575,13 +575,17 @@ static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) r = fill_ctrlset(mac, skb); if (r) - return r; + goto fail; info->rate_driver_data[0] = hw; r = zd_usb_tx(&mac->chip.usb, skb); if (r) - return r; + goto fail; + return 0; + +fail: + dev_kfree_skb(skb); return 0; } -- GitLab From 2bfc5cb57b55ed2204bca7668e082f7bf485760a Mon Sep 17 00:00:00 2001 From: Andrey Borzenkov Date: Sat, 28 Feb 2009 23:09:09 +0300 Subject: [PATCH 3547/4982] orinoco: firmware: consistently compile out fw cache support if not requested Currently part of support for FW caching is unconditionally compiled in even if it is never used. Consistently remove caching support if not requested by user. Signed-off-by: Andrey Borzenkov Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/fw.c | 37 +++++++++++++++++--------- drivers/net/wireless/orinoco/fw.h | 5 ++++ drivers/net/wireless/orinoco/main.c | 2 ++ drivers/net/wireless/orinoco/orinoco.h | 2 ++ 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/orinoco/fw.c b/drivers/net/wireless/orinoco/fw.c index e7abb45d675..1084b43e04b 100644 --- a/drivers/net/wireless/orinoco/fw.c +++ b/drivers/net/wireless/orinoco/fw.c @@ -70,6 +70,19 @@ static const char *validate_fw(const struct orinoco_fw_header *hdr, size_t len) return NULL; } +#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP) +static inline const struct firmware * +orinoco_cached_fw_get(struct orinoco_private *priv, bool primary) +{ + if (primary) + return priv->cached_pri_fw; + else + return priv->cached_fw; +} +#else +#define orinoco_cached_fw_get(priv, primary) (NULL) +#endif + /* Download either STA or AP firmware into the card. */ static int orinoco_dl_firmware(struct orinoco_private *priv, @@ -107,7 +120,7 @@ orinoco_dl_firmware(struct orinoco_private *priv, if (err) goto free; - if (!priv->cached_fw) { + if (!orinoco_cached_fw_get(priv, false)) { err = request_firmware(&fw_entry, firmware, priv->dev); if (err) { @@ -117,7 +130,7 @@ orinoco_dl_firmware(struct orinoco_private *priv, goto free; } } else - fw_entry = priv->cached_fw; + fw_entry = orinoco_cached_fw_get(priv, false); hdr = (const struct orinoco_fw_header *) fw_entry->data; @@ -170,7 +183,7 @@ orinoco_dl_firmware(struct orinoco_private *priv, abort: /* If we requested the firmware, release it. */ - if (!priv->cached_fw) + if (!orinoco_cached_fw_get(priv, false)) release_firmware(fw_entry); free: @@ -273,20 +286,20 @@ symbol_dl_firmware(struct orinoco_private *priv, int ret; const struct firmware *fw_entry; - if (!priv->cached_pri_fw) { + if (!orinoco_cached_fw_get(priv, true)) { if (request_firmware(&fw_entry, fw->pri_fw, priv->dev) != 0) { printk(KERN_ERR "%s: Cannot find firmware: %s\n", dev->name, fw->pri_fw); return -ENOENT; } } else - fw_entry = priv->cached_pri_fw; + fw_entry = orinoco_cached_fw_get(priv, true); /* Load primary firmware */ ret = symbol_dl_image(priv, fw, fw_entry->data, fw_entry->data + fw_entry->size, 0); - if (!priv->cached_pri_fw) + if (!orinoco_cached_fw_get(priv, true)) release_firmware(fw_entry); if (ret) { printk(KERN_ERR "%s: Primary firmware download failed\n", @@ -294,19 +307,19 @@ symbol_dl_firmware(struct orinoco_private *priv, return ret; } - if (!priv->cached_fw) { + if (!orinoco_cached_fw_get(priv, false)) { if (request_firmware(&fw_entry, fw->sta_fw, priv->dev) != 0) { printk(KERN_ERR "%s: Cannot find firmware: %s\n", dev->name, fw->sta_fw); return -ENOENT; } } else - fw_entry = priv->cached_fw; + fw_entry = orinoco_cached_fw_get(priv, false); /* Load secondary firmware */ ret = symbol_dl_image(priv, fw, fw_entry->data, fw_entry->data + fw_entry->size, 1); - if (!priv->cached_fw) + if (!orinoco_cached_fw_get(priv, false)) release_firmware(fw_entry); if (ret) { printk(KERN_ERR "%s: Secondary firmware download failed\n", @@ -340,9 +353,9 @@ int orinoco_download(struct orinoco_private *priv) return err; } +#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP) void orinoco_cache_fw(struct orinoco_private *priv, int ap) { -#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP) const struct firmware *fw_entry = NULL; const char *pri_fw; const char *fw; @@ -362,12 +375,10 @@ void orinoco_cache_fw(struct orinoco_private *priv, int ap) if (request_firmware(&fw_entry, fw, priv->dev) == 0) priv->cached_fw = fw_entry; } -#endif } void orinoco_uncache_fw(struct orinoco_private *priv) { -#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP) if (priv->cached_pri_fw) release_firmware(priv->cached_pri_fw); if (priv->cached_fw) @@ -375,5 +386,5 @@ void orinoco_uncache_fw(struct orinoco_private *priv) priv->cached_pri_fw = NULL; priv->cached_fw = NULL; -#endif } +#endif diff --git a/drivers/net/wireless/orinoco/fw.h b/drivers/net/wireless/orinoco/fw.h index 2290f0845d5..89fc26d25b0 100644 --- a/drivers/net/wireless/orinoco/fw.h +++ b/drivers/net/wireless/orinoco/fw.h @@ -10,7 +10,12 @@ struct orinoco_private; int orinoco_download(struct orinoco_private *priv); +#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP) void orinoco_cache_fw(struct orinoco_private *priv, int ap); void orinoco_uncache_fw(struct orinoco_private *priv); +#else +#define orinoco_cache_fw(priv, ap) do { } while(0) +#define orinoco_uncache_fw(priv) do { } while (0) +#endif #endif /* _ORINOCO_FW_H_ */ diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index e9b1db77a73..345593c4acc 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -2580,8 +2580,10 @@ struct net_device netif_carrier_off(dev); priv->last_linkstatus = 0xffff; +#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP) priv->cached_pri_fw = NULL; priv->cached_fw = NULL; +#endif /* Register PM notifiers */ orinoco_register_pm_notifier(priv); diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h index f3f94b28ce6..8e5a72cc297 100644 --- a/drivers/net/wireless/orinoco/orinoco.h +++ b/drivers/net/wireless/orinoco/orinoco.h @@ -159,9 +159,11 @@ struct orinoco_private { unsigned int tkip_cm_active:1; unsigned int key_mgmt:3; +#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP) /* Cached in memory firmware to use during ->resume. */ const struct firmware *cached_pri_fw; const struct firmware *cached_fw; +#endif struct notifier_block pm_notifier; }; -- GitLab From 0eeb59fe2cd84b62f374874a59e62402e13f48b3 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 5 Mar 2009 17:23:46 +0200 Subject: [PATCH 3548/4982] mac80211: Fix WMM ACM parsing and AC downgrade operation Incorrect local->wmm_acm bits were set for AC_BK and AC_BE. Fix this and add some comments to make it easier to understand the AC-to-UP(pair) mapping. Set the wmm_acm bits (and show WMM debug) even if the driver does not implement conf_tx() handler. In addition, fix the ACM-based AC downgrade code to not use the highest priority in error cases. We need to break the loop to get the correct AC_BK value (3) instead of returning 0 (which would indicate AC_VO). The comment here was not really very useful either, so let's provide somewhat more helpful description of the situation. Since it is very unlikely that the ACM flag would be set for AC_BK and AC_BE, these bugs are not likely to be seen in real life networks. Anyway, better do these things correctly should someone really use silly AP configuration (and to pass some functionality tests, too). Remove the TODO comment about handling ACM. Downgrading AC is perfectly valid mechanism for ACM. Eventually, we may add support for WMM-AC and send a request for a TS, but anyway, that functionality won't be here at the location of this TODO comment. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 24 ++++++++++-------------- net/mac80211/wme.c | 9 ++++++--- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 391445c6b89..eeb6da8505c 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -417,9 +417,6 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, memset(¶ms, 0, sizeof(params)); - if (!local->ops->conf_tx) - return; - local->wmm_acm = 0; for (; left >= 4; left -= 4, pos += 4) { int aci = (pos[0] >> 5) & 0x03; @@ -427,26 +424,26 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, int queue; switch (aci) { - case 1: + case 1: /* AC_BK */ queue = 3; if (acm) - local->wmm_acm |= BIT(0) | BIT(3); + local->wmm_acm |= BIT(1) | BIT(2); /* BK/- */ break; - case 2: + case 2: /* AC_VI */ queue = 1; if (acm) - local->wmm_acm |= BIT(4) | BIT(5); + local->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */ break; - case 3: + case 3: /* AC_VO */ queue = 0; if (acm) - local->wmm_acm |= BIT(6) | BIT(7); + local->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */ break; - case 0: + case 0: /* AC_BE */ default: queue = 2; if (acm) - local->wmm_acm |= BIT(1) | BIT(2); + local->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */ break; } @@ -460,9 +457,8 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, local->mdev->name, queue, aci, acm, params.aifs, params.cw_min, params.cw_max, params.txop); #endif - /* TODO: handle ACM (block TX, fallback to next lowest allowed - * AC for now) */ - if (local->ops->conf_tx(local_to_hw(local), queue, ¶ms)) { + if (local->ops->conf_tx && + local->ops->conf_tx(local_to_hw(local), queue, ¶ms)) { printk(KERN_DEBUG "%s: failed to set TX queue " "parameters for queue %d\n", local->mdev->name, queue); } diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 093a4ab7f28..0b8ad1f4ecd 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c @@ -99,10 +99,13 @@ static u16 classify80211(struct ieee80211_local *local, struct sk_buff *skb) /* in case we are a client verify acm is not set for this ac */ while (unlikely(local->wmm_acm & BIT(skb->priority))) { if (wme_downgrade_ac(skb)) { - /* The old code would drop the packet in this - * case. + /* + * This should not really happen. The AP has marked all + * lower ACs to require admission control which is not + * a reasonable configuration. Allow the frame to be + * transmitted using AC_BK as a workaround. */ - return 0; + break; } } -- GitLab From 19d8bc22bcea749da2ba065a1ff9e054fadb556e Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Thu, 5 Mar 2009 16:55:18 +0100 Subject: [PATCH 3549/4982] ath9k: create a common debugfs_root for all device instances The driver are trying to create an 'ath9k' directory in debugfs for each device currently. If there are more than one device in the system, the second try will always fail. Changes-licensed-under: ISC Signed-off-by: Gabor Juhos Signed-off-by: Imre Kaloz Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/debug.c | 24 ++++++++++++++++++------ drivers/net/wireless/ath9k/debug.h | 12 +++++++++++- drivers/net/wireless/ath9k/main.c | 13 ++++++++++++- 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath9k/debug.c b/drivers/net/wireless/ath9k/debug.c index 8d91422106d..0f7e249d2d2 100644 --- a/drivers/net/wireless/ath9k/debug.c +++ b/drivers/net/wireless/ath9k/debug.c @@ -19,6 +19,8 @@ static unsigned int ath9k_debug = DBG_DEFAULT; module_param_named(debug, ath9k_debug, uint, 0); +static struct dentry *ath9k_debugfs_root; + void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...) { if (!sc) @@ -491,12 +493,8 @@ int ath9k_init_debug(struct ath_softc *sc) { sc->debug.debug_mask = ath9k_debug; - sc->debug.debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); - if (!sc->debug.debugfs_root) - goto err; - sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy), - sc->debug.debugfs_root); + ath9k_debugfs_root); if (!sc->debug.debugfs_phy) goto err; @@ -538,5 +536,19 @@ void ath9k_exit_debug(struct ath_softc *sc) debugfs_remove(sc->debug.debugfs_interrupt); debugfs_remove(sc->debug.debugfs_dma); debugfs_remove(sc->debug.debugfs_phy); - debugfs_remove(sc->debug.debugfs_root); +} + +int ath9k_debug_create_root(void) +{ + ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); + if (!ath9k_debugfs_root) + return -ENOENT; + + return 0; +} + +void ath9k_debug_remove_root(void) +{ + debugfs_remove(ath9k_debugfs_root); + ath9k_debugfs_root = NULL; } diff --git a/drivers/net/wireless/ath9k/debug.h b/drivers/net/wireless/ath9k/debug.h index 2a33d74fdbe..065268b8568 100644 --- a/drivers/net/wireless/ath9k/debug.h +++ b/drivers/net/wireless/ath9k/debug.h @@ -102,7 +102,6 @@ struct ath_stats { struct ath9k_debug { int debug_mask; - struct dentry *debugfs_root; struct dentry *debugfs_phy; struct dentry *debugfs_dma; struct dentry *debugfs_interrupt; @@ -114,6 +113,8 @@ struct ath9k_debug { void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...); int ath9k_init_debug(struct ath_softc *sc); void ath9k_exit_debug(struct ath_softc *sc); +int ath9k_debug_create_root(void); +void ath9k_debug_remove_root(void); void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb); void ath_debug_stat_retries(struct ath_softc *sc, int rix, @@ -135,6 +136,15 @@ static inline void ath9k_exit_debug(struct ath_softc *sc) { } +static inline int ath9k_debug_create_root(void) +{ + return 0; +} + +static inline void ath9k_debug_remove_root(void) +{ +} + static inline void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) { diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index f473fee72a2..bb30ccca184 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -2858,12 +2858,20 @@ static int __init ath9k_init(void) goto err_out; } + error = ath9k_debug_create_root(); + if (error) { + printk(KERN_ERR + "ath9k: Unable to create debugfs root: %d\n", + error); + goto err_rate_unregister; + } + error = ath_pci_init(); if (error < 0) { printk(KERN_ERR "ath9k: No PCI devices found, driver not installed.\n"); error = -ENODEV; - goto err_rate_unregister; + goto err_remove_root; } error = ath_ahb_init(); @@ -2877,6 +2885,8 @@ static int __init ath9k_init(void) err_pci_exit: ath_pci_exit(); + err_remove_root: + ath9k_debug_remove_root(); err_rate_unregister: ath_rate_control_unregister(); err_out: @@ -2888,6 +2898,7 @@ static void __exit ath9k_exit(void) { ath_ahb_exit(); ath_pci_exit(); + ath9k_debug_remove_root(); ath_rate_control_unregister(); printk(KERN_INFO "%s: Driver unloaded\n", dev_info); } -- GitLab From fbf95296c1c8b1ba09bdea0438ce2c61e0e3be5d Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 5 Mar 2009 21:29:51 +0100 Subject: [PATCH 3550/4982] p54usb: stop USB core interference in exit path The patch fixes a problem when the (Soft)LED stayed on after the module was unloaded. It turned out that the USB core disables all endpoints before calling the disconnect method. So it was impossible to switch off the radio & LEDs. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 9539ddcf379..3b5e54e6793 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -1024,6 +1024,7 @@ static struct usb_driver p54u_driver = { .disconnect = p54u_disconnect, .pre_reset = p54u_pre_reset, .post_reset = p54u_post_reset, + .soft_unbind = 1, }; static int __init p54u_init(void) -- GitLab From 2ac710720c523dd243662746da4381dd4f1772f8 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 5 Mar 2009 21:30:10 +0100 Subject: [PATCH 3551/4982] p54: unify ieee80211 device registration All three drivers (p54pci, p54usb and p54spi) are implementing the same functionality three times. So, why not put it into the shared library?! Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54.h | 1 + drivers/net/wireless/p54/p54common.c | 15 +++++++++++++++ drivers/net/wireless/p54/p54pci.c | 7 ++----- drivers/net/wireless/p54/p54spi.c | 9 ++------- drivers/net/wireless/p54/p54usb.c | 6 ++---- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 94c3acd1fca..071cbe96537 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -165,6 +165,7 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw); int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len); int p54_read_eeprom(struct ieee80211_hw *dev); struct ieee80211_hw *p54_init_common(size_t priv_data_len); +int p54_register_common(struct ieee80211_hw *dev, struct device *pdev); void p54_free_common(struct ieee80211_hw *dev); #endif /* P54_H */ diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 14438a642fd..42d1cac609a 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -2489,6 +2489,21 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) } EXPORT_SYMBOL_GPL(p54_init_common); +int p54_register_common(struct ieee80211_hw *dev, struct device *pdev) +{ + int err; + + err = ieee80211_register_hw(dev); + if (err) { + dev_err(pdev, "Cannot register device (%d).\n", err); + return err; + } + + dev_info(pdev, "is registered as '%s'\n", wiphy_name(dev->wiphy)); + return 0; +} +EXPORT_SYMBOL_GPL(p54_register_common); + void p54_free_common(struct ieee80211_hw *dev) { struct p54_common *priv = dev->priv; diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 3f9a6b04ea9..46626e5dcbb 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -565,12 +565,9 @@ static int __devinit p54p_probe(struct pci_dev *pdev, if (err) goto err_free_common; - err = ieee80211_register_hw(dev); - if (err) { - printk(KERN_ERR "%s (p54pci): Cannot register netdevice\n", - pci_name(pdev)); + err = p54_register_common(dev, &pdev->dev); + if (err) goto err_free_common; - } return 0; diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index 7fde243b3d5..2b222aaa6f0 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c @@ -694,15 +694,10 @@ static int __devinit p54spi_probe(struct spi_device *spi) if (ret) goto err_free_common; - ret = ieee80211_register_hw(hw); - if (ret) { - dev_err(&priv->spi->dev, "unable to register " - "mac80211 hw: %d", ret); + ret = p54_register_common(hw, &priv->spi->dev); + if (ret) goto err_free_common; - } - dev_info(&priv->spi->dev, "device is bound to %s\n", - wiphy_name(hw->wiphy)); return 0; err_free_common: diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 3b5e54e6793..da6640afc83 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -976,11 +976,9 @@ static int __devinit p54u_probe(struct usb_interface *intf, if (err) goto err_free_dev; - err = ieee80211_register_hw(dev); - if (err) { - dev_err(&udev->dev, "(p54usb) Cannot register netdevice\n"); + err = p54_register_common(dev, &udev->dev); + if (err) goto err_free_dev; - } return 0; -- GitLab From ad5e72ee81ed074cfe6bb2a1ca231b5413efa41f Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 5 Mar 2009 21:30:37 +0100 Subject: [PATCH 3552/4982] p54pci: convert printk(KERN_* to dev_* This patch replaces most printk(KERN_* "") with their by dev_* analogue. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54pci.c | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 46626e5dcbb..e3569a0a952 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -413,8 +413,7 @@ static int p54p_open(struct ieee80211_hw *dev) err = request_irq(priv->pdev->irq, &p54p_interrupt, IRQF_SHARED, "p54pci", dev); if (err) { - printk(KERN_ERR "%s: failed to register IRQ handler\n", - wiphy_name(dev->wiphy)); + dev_err(&priv->pdev->dev, "failed to register IRQ handler\n"); return err; } @@ -476,30 +475,26 @@ static int __devinit p54p_probe(struct pci_dev *pdev, err = pci_enable_device(pdev); if (err) { - printk(KERN_ERR "%s (p54pci): Cannot enable new PCI device\n", - pci_name(pdev)); + dev_err(&pdev->dev, "Cannot enable new PCI device\n"); return err; } mem_addr = pci_resource_start(pdev, 0); mem_len = pci_resource_len(pdev, 0); if (mem_len < sizeof(struct p54p_csr)) { - printk(KERN_ERR "%s (p54pci): Too short PCI resources\n", - pci_name(pdev)); + dev_err(&pdev->dev, "Too short PCI resources\n"); goto err_disable_dev; } err = pci_request_regions(pdev, "p54pci"); if (err) { - printk(KERN_ERR "%s (p54pci): Cannot obtain PCI resources\n", - pci_name(pdev)); + dev_err(&pdev->dev, "Cannot obtain PCI resources\n"); goto err_disable_dev; } if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) || pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) { - printk(KERN_ERR "%s (p54pci): No suitable DMA available\n", - pci_name(pdev)); + dev_err(&pdev->dev, "No suitable DMA available\n"); goto err_free_reg; } @@ -511,8 +506,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev, dev = p54_init_common(sizeof(*priv)); if (!dev) { - printk(KERN_ERR "%s (p54pci): ieee80211 alloc failed\n", - pci_name(pdev)); + dev_err(&pdev->dev, "ieee80211 alloc failed\n"); err = -ENOMEM; goto err_free_reg; } @@ -525,17 +519,15 @@ static int __devinit p54p_probe(struct pci_dev *pdev, priv->map = ioremap(mem_addr, mem_len); if (!priv->map) { - printk(KERN_ERR "%s (p54pci): Cannot map device memory\n", - pci_name(pdev)); - err = -EINVAL; // TODO: use a better error code? + dev_err(&pdev->dev, "Cannot map device memory\n"); + err = -ENOMEM; goto err_free_dev; } priv->ring_control = pci_alloc_consistent(pdev, sizeof(*priv->ring_control), &priv->ring_control_dma); if (!priv->ring_control) { - printk(KERN_ERR "%s (p54pci): Cannot allocate rings\n", - pci_name(pdev)); + dev_err(&pdev->dev, "Cannot allocate rings\n"); err = -ENOMEM; goto err_iounmap; } @@ -549,8 +541,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev, err = request_firmware(&priv->firmware, "isl3886pci", &priv->pdev->dev); if (err) { - printk(KERN_ERR "%s (p54pci): cannot find firmware " - "(isl3886pci)\n", pci_name(priv->pdev)); + dev_err(&pdev->dev, "Cannot find firmware (isl3886pci)\n"); err = request_firmware(&priv->firmware, "isl3886", &priv->pdev->dev); if (err) -- GitLab From efeada2c0aa1219b15787da48cfa282803e9d99e Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 5 Mar 2009 21:31:05 +0100 Subject: [PATCH 3553/4982] p54: fix iwconfig txpower off Disabling the receiver logic with P54_FILTER_TYPE_RX_DISABLED is not supported by all firmwares. However we have an alternative: hibernation. And the only side effect - so far - is a bit less power consumption. WIN! Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 42d1cac609a..f7636505717 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -1680,7 +1680,7 @@ static int p54_setup_mac(struct ieee80211_hw *dev) mode = P54_FILTER_TYPE_PROMISCUOUS; break; default: - mode = P54_FILTER_TYPE_NONE; + mode = P54_FILTER_TYPE_HIBERNATE; break; } @@ -1693,7 +1693,7 @@ static int p54_setup_mac(struct ieee80211_hw *dev) (mode != P54_FILTER_TYPE_PROMISCUOUS)) mode |= P54_FILTER_TYPE_TRANSPARENT; } else - mode = P54_FILTER_TYPE_RX_DISABLED; + mode = P54_FILTER_TYPE_HIBERNATE; setup->mac_mode = cpu_to_le16(mode); memcpy(setup->mac_addr, priv->mac_addr, ETH_ALEN); -- GitLab From d0b45aef4f628e69f8da8c670d6879a8a02fe0f2 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 6 Mar 2009 01:02:04 +0100 Subject: [PATCH 3554/4982] p54: initial SoftLED support This patch adds SoftLED support for all p54 devices. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54.h | 25 ++++++ drivers/net/wireless/p54/p54common.c | 124 +++++++++++++++++++++++++-- drivers/net/wireless/p54/p54common.h | 7 +- 3 files changed, 143 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 071cbe96537..2dda5fe418b 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -14,6 +14,10 @@ * published by the Free Software Foundation. */ +#ifdef CONFIG_MAC80211_LEDS +#include +#endif /* CONFIG_MAC80211_LEDS */ + enum p54_control_frame_types { P54_CONTROL_TYPE_SETUP = 0, P54_CONTROL_TYPE_SCAN, @@ -112,6 +116,21 @@ enum fw_state { FW_STATE_RESETTING, }; +#ifdef CONFIG_MAC80211_LEDS + +#define P54_LED_MAX_NAME_LEN 31 + +struct p54_led_dev { + struct ieee80211_hw *hw_dev; + struct led_classdev led_dev; + char name[P54_LED_MAX_NAME_LEN + 1]; + + unsigned int index; + unsigned int registered; +}; + +#endif /* CONFIG_MAC80211_LEDS */ + struct p54_common { struct ieee80211_hw *hw; u32 rx_start; @@ -157,6 +176,12 @@ struct p54_common { struct completion eeprom_comp; u8 privacy_caps; u8 rx_keycache_size; + /* LED management */ + #ifdef CONFIG_MAC80211_LEDS + struct p54_led_dev assoc_led; + struct p54_led_dev tx_led; + #endif /* CONFIG_MAC80211_LEDS */ + u16 softled_state; /* bit field of glowing LEDs */ }; int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb); diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index f7636505717..93abe49f4bd 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -21,6 +21,9 @@ #include #include +#ifdef CONFIG_MAC80211_LEDS +#include +#endif /* CONFIG_MAC80211_LEDS */ #include "p54.h" #include "p54common.h" @@ -1871,7 +1874,7 @@ static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell) return -EINVAL; } -static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act) +static int p54_set_leds(struct ieee80211_hw *dev) { struct p54_common *priv = dev->priv; struct sk_buff *skb; @@ -1882,11 +1885,11 @@ static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act) if (!skb) return -ENOMEM; - led = (struct p54_led *)skb_put(skb, sizeof(*led)); - led->mode = cpu_to_le16(mode); - led->led_permanent = cpu_to_le16(link); - led->led_temporary = cpu_to_le16(act); - led->duration = cpu_to_le16(1000); + led = (struct p54_led *) skb_put(skb, sizeof(*led)); + led->flags = cpu_to_le16(0x0003); + led->mask[0] = led->mask[1] = cpu_to_le16(priv->softled_state); + led->delay[0] = cpu_to_le16(1); + led->delay[1] = cpu_to_le16(0); priv->tx(dev, skb); return 0; } @@ -2070,6 +2073,9 @@ static int p54_start(struct ieee80211_hw *dev) queue_delayed_work(dev->workqueue, &priv->work, 0); + priv->softled_state = 0; + err = p54_set_leds(dev); + out: mutex_unlock(&priv->conf_mutex); return err; @@ -2082,6 +2088,9 @@ static void p54_stop(struct ieee80211_hw *dev) mutex_lock(&priv->conf_mutex); priv->mode = NL80211_IFTYPE_UNSPECIFIED; + priv->softled_state = 0; + p54_set_leds(dev); + cancel_delayed_work_sync(&priv->work); if (priv->cached_beacon) p54_tx_cancel(dev, priv->cached_beacon); @@ -2119,7 +2128,6 @@ static int p54_add_interface(struct ieee80211_hw *dev, memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); p54_setup_mac(dev); - p54_set_leds(dev, 1, 0, 0); mutex_unlock(&priv->conf_mutex); return 0; } @@ -2199,8 +2207,6 @@ static int p54_config_interface(struct ieee80211_hw *dev, goto out; } - ret = p54_set_leds(dev, 1, !is_multicast_ether_addr(priv->bssid), 0); - out: mutex_unlock(&priv->conf_mutex); return ret; @@ -2419,6 +2425,96 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, return 0; } +#ifdef CONFIG_MAC80211_LEDS +static void p54_led_brightness_set(struct led_classdev *led_dev, + enum led_brightness brightness) +{ + struct p54_led_dev *led = container_of(led_dev, struct p54_led_dev, + led_dev); + struct ieee80211_hw *dev = led->hw_dev; + struct p54_common *priv = dev->priv; + int err; + + /* Don't toggle the LED, when the device is down. */ + if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) + return ; + + if (brightness != LED_OFF) + priv->softled_state |= BIT(led->index); + else + priv->softled_state &= ~BIT(led->index); + + err = p54_set_leds(dev); + if (err && net_ratelimit()) + printk(KERN_ERR "%s: failed to update %s LED.\n", + wiphy_name(dev->wiphy), led_dev->name); +} + +static int p54_register_led(struct ieee80211_hw *dev, + struct p54_led_dev *led, + unsigned int led_index, + char *name, char *trigger) +{ + int err; + + if (led->registered) + return -EEXIST; + + snprintf(led->name, sizeof(led->name), "p54-%s::%s", + wiphy_name(dev->wiphy), name); + led->hw_dev = dev; + led->index = led_index; + led->led_dev.name = led->name; + led->led_dev.default_trigger = trigger; + led->led_dev.brightness_set = p54_led_brightness_set; + + err = led_classdev_register(wiphy_dev(dev->wiphy), &led->led_dev); + if (err) + printk(KERN_ERR "%s: Failed to register %s LED.\n", + wiphy_name(dev->wiphy), name); + else + led->registered = 1; + + return err; +} + +static int p54_init_leds(struct ieee80211_hw *dev) +{ + struct p54_common *priv = dev->priv; + int err; + + /* + * TODO: + * Figure out if the EEPROM contains some hints about the number + * of available/programmable LEDs of the device. + * But for now, we can assume that we have two programmable LEDs. + */ + + err = p54_register_led(dev, &priv->assoc_led, 0, "assoc", + ieee80211_get_assoc_led_name(dev)); + if (err) + return err; + + err = p54_register_led(dev, &priv->tx_led, 1, "tx", + ieee80211_get_tx_led_name(dev)); + if (err) + return err; + + err = p54_set_leds(dev); + return err; +} + +static void p54_unregister_leds(struct ieee80211_hw *dev) +{ + struct p54_common *priv = dev->priv; + + if (priv->tx_led.registered) + led_classdev_unregister(&priv->tx_led.led_dev); + if (priv->assoc_led.registered) + led_classdev_unregister(&priv->assoc_led.led_dev); +} +#endif /* CONFIG_MAC80211_LEDS */ + static const struct ieee80211_ops p54_ops = { .tx = p54_tx, .start = p54_start, @@ -2499,6 +2595,12 @@ int p54_register_common(struct ieee80211_hw *dev, struct device *pdev) return err; } + #ifdef CONFIG_MAC80211_LEDS + err = p54_init_leds(dev); + if (err) + return err; + #endif /* CONFIG_MAC80211_LEDS */ + dev_info(pdev, "is registered as '%s'\n", wiphy_name(dev->wiphy)); return 0; } @@ -2510,6 +2612,10 @@ void p54_free_common(struct ieee80211_hw *dev) kfree(priv->iq_autocal); kfree(priv->output_limit); kfree(priv->curve_data); + + #ifdef CONFIG_MAC80211_LEDS + p54_unregister_leds(dev); + #endif /* CONFIG_MAC80211_LEDS */ } EXPORT_SYMBOL_GPL(p54_free_common); diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h index def23b1f49e..75ead7a150f 100644 --- a/drivers/net/wireless/p54/p54common.h +++ b/drivers/net/wireless/p54/p54common.h @@ -515,10 +515,9 @@ struct p54_scan_tail_rate { } __attribute__ ((packed)); struct p54_led { - __le16 mode; - __le16 led_temporary; - __le16 led_permanent; - __le16 duration; + __le16 flags; + __le16 mask[2]; + __le16 delay[2]; } __attribute__ ((packed)); struct p54_edcf { -- GitLab From 94041b294094bbd9fbbe11aa71278fdc70d29d6d Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 6 Mar 2009 02:15:08 +0100 Subject: [PATCH 3555/4982] p54: enable power save support This patch enables power save support on all p54 devices. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 93abe49f4bd..b6905357a2e 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -2548,6 +2548,8 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) priv->basic_rate_mask = 0x15f; skb_queue_head_init(&priv->tx_queue); dev->flags = IEEE80211_HW_RX_INCLUDES_FCS | + IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_PS_NULLFUNC_STACK | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; -- GitLab From 22cad73587ac85e2e9d1f52aae62023aec093654 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 5 Mar 2009 21:13:06 -0800 Subject: [PATCH 3556/4982] mac80211_hwsim: add support for 5 GHz ACME Inc. is now selling a dual band radio. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 138 +++++++++++++++++++------- 1 file changed, 102 insertions(+), 36 deletions(-) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index fce49ba061d..d8716bed5e4 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -10,7 +10,6 @@ /* * TODO: * - IBSS mode simulation (Beacon transmission with competition for "air time") - * - IEEE 802.11a and 802.11n modes * - RX filtering based on filter configuration (data->rx_filter) */ @@ -86,22 +85,65 @@ static struct class *hwsim_class; static struct net_device *hwsim_mon; /* global monitor netdev */ +#define CHAN2G(_freq) { \ + .band = IEEE80211_BAND_2GHZ, \ + .center_freq = (_freq), \ + .hw_value = (_freq), \ + .max_power = 20, \ +} + +#define CHAN5G(_freq) { \ + .band = IEEE80211_BAND_5GHZ, \ + .center_freq = (_freq), \ + .hw_value = (_freq), \ + .max_power = 20, \ +} + +static const struct ieee80211_channel hwsim_channels_2ghz[] = { + CHAN2G(2412), /* Channel 1 */ + CHAN2G(2417), /* Channel 2 */ + CHAN2G(2422), /* Channel 3 */ + CHAN2G(2427), /* Channel 4 */ + CHAN2G(2432), /* Channel 5 */ + CHAN2G(2437), /* Channel 6 */ + CHAN2G(2442), /* Channel 7 */ + CHAN2G(2447), /* Channel 8 */ + CHAN2G(2452), /* Channel 9 */ + CHAN2G(2457), /* Channel 10 */ + CHAN2G(2462), /* Channel 11 */ + CHAN2G(2467), /* Channel 12 */ + CHAN2G(2472), /* Channel 13 */ + CHAN2G(2484), /* Channel 14 */ +}; -static const struct ieee80211_channel hwsim_channels[] = { - { .center_freq = 2412 }, - { .center_freq = 2417 }, - { .center_freq = 2422 }, - { .center_freq = 2427 }, - { .center_freq = 2432 }, - { .center_freq = 2437 }, - { .center_freq = 2442 }, - { .center_freq = 2447 }, - { .center_freq = 2452 }, - { .center_freq = 2457 }, - { .center_freq = 2462 }, - { .center_freq = 2467 }, - { .center_freq = 2472 }, - { .center_freq = 2484 }, +static const struct ieee80211_channel hwsim_channels_5ghz[] = { + CHAN5G(5180), /* Channel 36 */ + CHAN5G(5200), /* Channel 40 */ + CHAN5G(5220), /* Channel 44 */ + CHAN5G(5240), /* Channel 48 */ + + CHAN5G(5260), /* Channel 52 */ + CHAN5G(5280), /* Channel 56 */ + CHAN5G(5300), /* Channel 60 */ + CHAN5G(5320), /* Channel 64 */ + + CHAN5G(5500), /* Channel 100 */ + CHAN5G(5520), /* Channel 104 */ + CHAN5G(5540), /* Channel 108 */ + CHAN5G(5560), /* Channel 112 */ + CHAN5G(5580), /* Channel 116 */ + CHAN5G(5600), /* Channel 120 */ + CHAN5G(5620), /* Channel 124 */ + CHAN5G(5640), /* Channel 128 */ + CHAN5G(5660), /* Channel 132 */ + CHAN5G(5680), /* Channel 136 */ + CHAN5G(5700), /* Channel 140 */ + + CHAN5G(5745), /* Channel 149 */ + CHAN5G(5765), /* Channel 153 */ + CHAN5G(5785), /* Channel 157 */ + CHAN5G(5805), /* Channel 161 */ + CHAN5G(5825), /* Channel 165 */ }; static const struct ieee80211_rate hwsim_rates[] = { @@ -126,8 +168,9 @@ struct mac80211_hwsim_data { struct list_head list; struct ieee80211_hw *hw; struct device *dev; - struct ieee80211_supported_band band; - struct ieee80211_channel channels[ARRAY_SIZE(hwsim_channels)]; + struct ieee80211_supported_band bands[2]; + struct ieee80211_channel channels_2ghz[ARRAY_SIZE(hwsim_channels_2ghz)]; + struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)]; struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; struct ieee80211_channel *channel; @@ -728,6 +771,7 @@ static int __init init_mac80211_hwsim(void) u8 addr[ETH_ALEN]; struct mac80211_hwsim_data *data; struct ieee80211_hw *hw; + enum ieee80211_band band; if (radios < 1 || radios > 100) return -EINVAL; @@ -785,25 +829,47 @@ static int __init init_mac80211_hwsim(void) hw->vif_data_size = sizeof(struct hwsim_vif_priv); hw->sta_data_size = sizeof(struct hwsim_sta_priv); - memcpy(data->channels, hwsim_channels, sizeof(hwsim_channels)); + memcpy(data->channels_2ghz, hwsim_channels_2ghz, + sizeof(hwsim_channels_2ghz)); + memcpy(data->channels_5ghz, hwsim_channels_5ghz, + sizeof(hwsim_channels_5ghz)); memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates)); - data->band.channels = data->channels; - data->band.n_channels = ARRAY_SIZE(hwsim_channels); - data->band.bitrates = data->rates; - data->band.n_bitrates = ARRAY_SIZE(hwsim_rates); - data->band.ht_cap.ht_supported = true; - data->band.ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | - IEEE80211_HT_CAP_GRN_FLD | - IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_DSSSCCK40; - data->band.ht_cap.ampdu_factor = 0x3; - data->band.ht_cap.ampdu_density = 0x6; - memset(&data->band.ht_cap.mcs, 0, - sizeof(data->band.ht_cap.mcs)); - data->band.ht_cap.mcs.rx_mask[0] = 0xff; - data->band.ht_cap.mcs.rx_mask[1] = 0xff; - data->band.ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &data->band; + + for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) { + struct ieee80211_supported_band *sband = &data->bands[band]; + switch (band) { + case IEEE80211_BAND_2GHZ: + sband->channels = data->channels_2ghz; + sband->n_channels = + ARRAY_SIZE(hwsim_channels_2ghz); + break; + case IEEE80211_BAND_5GHZ: + sband->channels = data->channels_5ghz; + sband->n_channels = + ARRAY_SIZE(hwsim_channels_5ghz); + break; + default: + break; + } + + sband->bitrates = data->rates; + sband->n_bitrates = ARRAY_SIZE(hwsim_rates); + + sband->ht_cap.ht_supported = true; + sband->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | + IEEE80211_HT_CAP_GRN_FLD | + IEEE80211_HT_CAP_SGI_40 | + IEEE80211_HT_CAP_DSSSCCK40; + sband->ht_cap.ampdu_factor = 0x3; + sband->ht_cap.ampdu_density = 0x6; + memset(&sband->ht_cap.mcs, 0, + sizeof(sband->ht_cap.mcs)); + sband->ht_cap.mcs.rx_mask[0] = 0xff; + sband->ht_cap.mcs.rx_mask[1] = 0xff; + sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; + + hw->wiphy->bands[band] = sband; + } err = ieee80211_register_hw(hw); if (err < 0) { -- GitLab From 611b6a82aaae33a4d3a274fd6cccbdcd1c7cef4d Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 5 Mar 2009 21:19:21 -0800 Subject: [PATCH 3557/4982] cfg80211: Enable passive scan on channels 12-14 for world roaming Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 58df98f1099..25eb1554f8a 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -86,15 +86,26 @@ struct reg_beacon { /* We keep a static world regulatory domain in case of the absence of CRDA */ static const struct ieee80211_regdomain world_regdom = { - .n_reg_rules = 3, + .n_reg_rules = 5, .alpha2 = "00", .reg_rules = { /* IEEE 802.11b/g, channels 1..11 */ REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), - /* IEEE 802.11a, channel 36..48 */ - REG_RULE(5180-10, 5240+10, 40, 6, 23, + /* IEEE 802.11b/g, channels 12..13. No HT40 + * channel fits here. */ + REG_RULE(2467-10, 2472+10, 20, 6, 20, NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), + /* IEEE 802.11 channel 14 - Only JP enables + * this and for 802.11b only */ + REG_RULE(2484-10, 2484+10, 20, 6, 20, + NL80211_RRF_PASSIVE_SCAN | + NL80211_RRF_NO_IBSS | + NL80211_RRF_NO_OFDM), + /* IEEE 802.11a, channel 36..48 */ + REG_RULE(5180-10, 5240+10, 40, 6, 23, + NL80211_RRF_PASSIVE_SCAN | + NL80211_RRF_NO_IBSS), /* NB: 5260 MHz - 5700 MHz requies DFS */ -- GitLab From ec329acef99ded8dad59e1ef8a5a02b823083353 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 5 Mar 2009 21:19:22 -0800 Subject: [PATCH 3558/4982] cfg80211: fix max tx power for world regdom on 5 GHz to 20dBm This is the lowest value amongst countries which do enable 5 GHz operation. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 25eb1554f8a..fa738be897a 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -103,14 +103,14 @@ static const struct ieee80211_regdomain world_regdom = { NL80211_RRF_NO_IBSS | NL80211_RRF_NO_OFDM), /* IEEE 802.11a, channel 36..48 */ - REG_RULE(5180-10, 5240+10, 40, 6, 23, + REG_RULE(5180-10, 5240+10, 40, 6, 20, NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), /* NB: 5260 MHz - 5700 MHz requies DFS */ /* IEEE 802.11a, channel 149..165 */ - REG_RULE(5745-10, 5825+10, 40, 6, 23, + REG_RULE(5745-10, 5825+10, 40, 6, 20, NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), } -- GitLab From f0e6ce13c17afd74a49e0ef043d72581562f73ae Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Fri, 6 Mar 2009 11:24:08 +0530 Subject: [PATCH 3559/4982] ath9k: Get rid of unnecessary ATOMIC memory alloc during init time We can sleep for memory during init time and so allocating rx buffers, descriptro buffers with GFP_KERNEL should help us to get rid of transient alloc fails. Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 5 ++--- drivers/net/wireless/ath9k/recv.c | 8 ++++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index bb30ccca184..4bc43db9ab2 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1804,7 +1804,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, /* allocate descriptors */ dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len, - &dd->dd_desc_paddr, GFP_ATOMIC); + &dd->dd_desc_paddr, GFP_KERNEL); if (dd->dd_desc == NULL) { error = -ENOMEM; goto fail; @@ -1816,12 +1816,11 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, /* allocate buffers */ bsize = sizeof(struct ath_buf) * nbuf; - bf = kmalloc(bsize, GFP_KERNEL); + bf = kzalloc(bsize, GFP_KERNEL); if (bf == NULL) { error = -ENOMEM; goto fail2; } - memset(bf, 0, bsize); dd->dd_bufptr = bf; INIT_LIST_HEAD(head); diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c index 3df5c782436..9439cb35111 100644 --- a/drivers/net/wireless/ath9k/recv.c +++ b/drivers/net/wireless/ath9k/recv.c @@ -100,7 +100,7 @@ static u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp) return (tsf & ~0x7fff) | rstamp; } -static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, u32 len) +static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, u32 len, gfp_t gfp_mask) { struct sk_buff *skb; u32 off; @@ -118,7 +118,7 @@ static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, u32 len) * Unfortunately this means we may get 8 KB here from the * kernel... and that is actually what is observed on some * systems :( */ - skb = dev_alloc_skb(len + sc->cachelsz - 1); + skb = __dev_alloc_skb(len + sc->cachelsz - 1, gfp_mask); if (skb != NULL) { off = ((unsigned long) skb->data) % sc->cachelsz; if (off != 0) @@ -306,7 +306,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) } list_for_each_entry(bf, &sc->rx.rxbuf, list) { - skb = ath_rxbuf_alloc(sc, sc->rx.bufsize); + skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_KERNEL); if (skb == NULL) { error = -ENOMEM; break; @@ -580,7 +580,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) /* Ensure we always have an skb to requeue once we are done * processing the current buffer's skb */ - requeue_skb = ath_rxbuf_alloc(sc, sc->rx.bufsize); + requeue_skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_ATOMIC); /* If there is no memory we ignore the current RX'd frame, * tell hardware it can give us a new frame using the old -- GitLab From b03a9db95a285e13a5e4f2913e9d22a84bf50cc6 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Fri, 6 Mar 2009 11:24:09 +0530 Subject: [PATCH 3560/4982] ath9k: RX buffers may be accessed/freed even before initialized/alloced. accessing RXBUF list in ath_rx_cleanup may cause panic if ath_descdma_setup fails even before RXBUF list is initialized. Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 4bc43db9ab2..7d9c060704b 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1773,6 +1773,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n", name, nbuf, ndesc); + INIT_LIST_HEAD(head); /* ath_desc must be a multiple of DWORDs */ if ((sizeof(struct ath_desc) % 4) != 0) { DPRINTF(sc, ATH_DBG_FATAL, "ath_desc not DWORD aligned\n"); @@ -1823,7 +1824,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, } dd->dd_bufptr = bf; - INIT_LIST_HEAD(head); for (i = 0; i < nbuf; i++, bf++, ds += ndesc) { bf->bf_desc = ds; bf->bf_daddr = DS2PHYS(dd, ds); -- GitLab From 4e845168380a5954dd8702be5229e3e1b477ed81 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Fri, 6 Mar 2009 11:24:10 +0530 Subject: [PATCH 3561/4982] ath9k: INI update for AR9285 and periodic PA offset caliberation This patch updates the initvalues for AR9285 chipset and also adds periodic PA offset caliberation. Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/calib.c | 145 +++++++++++++++++--------- drivers/net/wireless/ath9k/eeprom.h | 2 +- drivers/net/wireless/ath9k/hw.c | 20 +++- drivers/net/wireless/ath9k/initvals.h | 107 +++++++++++++------ drivers/net/wireless/ath9k/phy.h | 4 + 5 files changed, 195 insertions(+), 83 deletions(-) diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c index 1c074c059b5..a652e9bb16d 100644 --- a/drivers/net/wireless/ath9k/calib.c +++ b/drivers/net/wireless/ath9k/calib.c @@ -745,43 +745,6 @@ static void ath9k_olc_temp_compensation(struct ath_hw *ah) } } -bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, - u8 rxchainmask, bool longcal, - bool *isCalDone) -{ - struct hal_cal_list *currCal = ah->cal_list_curr; - - *isCalDone = true; - - if (currCal && - (currCal->calState == CAL_RUNNING || - currCal->calState == CAL_WAITING)) { - ath9k_hw_per_calibration(ah, chan, rxchainmask, currCal, - isCalDone); - if (*isCalDone) { - ah->cal_list_curr = currCal = currCal->calNext; - - if (currCal->calState == CAL_WAITING) { - *isCalDone = false; - ath9k_hw_reset_calibration(ah, currCal); - } - } - } - - if (longcal) { - if (OLC_FOR_AR9280_20_LATER) - ath9k_olc_temp_compensation(ah); - ath9k_hw_getnf(ah, chan); - ath9k_hw_loadnf(ah, ah->curchan); - ath9k_hw_start_nfcal(ah); - - if (chan->channelFlags & CHANNEL_CW_INT) - chan->channelFlags &= ~CHANNEL_CW_INT; - } - - return true; -} - static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah) { @@ -877,22 +840,104 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah) } +bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, + u8 rxchainmask, bool longcal, + bool *isCalDone) +{ + struct hal_cal_list *currCal = ah->cal_list_curr; + + *isCalDone = true; + + if (currCal && + (currCal->calState == CAL_RUNNING || + currCal->calState == CAL_WAITING)) { + ath9k_hw_per_calibration(ah, chan, rxchainmask, currCal, + isCalDone); + if (*isCalDone) { + ah->cal_list_curr = currCal = currCal->calNext; + + if (currCal->calState == CAL_WAITING) { + *isCalDone = false; + ath9k_hw_reset_calibration(ah, currCal); + } + } + } + + if (longcal) { + if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah)) + ath9k_hw_9285_pa_cal(ah); + + if (OLC_FOR_AR9280_20_LATER) + ath9k_olc_temp_compensation(ah); + ath9k_hw_getnf(ah, chan); + ath9k_hw_loadnf(ah, ah->curchan); + ath9k_hw_start_nfcal(ah); + + if (chan->channelFlags & CHANNEL_CW_INT) + chan->channelFlags &= ~CHANNEL_CW_INT; + } + + return true; +} + +bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) +{ + REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); + if (chan->channelFlags & CHANNEL_HT20) { + REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); + REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); + REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_FLTR_CAL); + REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); + if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset " + "calibration failed to complete in " + "1ms; noisy ??\n"); + return false; + } + REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); + REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); + REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); + } + REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); + REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); + if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, + 0, AH_WAIT_TIMEOUT)) { + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset calibration " + "failed to complete in 1ms; noisy ??\n"); + return false; + } + + REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); + REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); + REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); + + return true; +} + bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) { - if (AR_SREV_9280_10_OR_LATER(ah)) { + if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) { + if (!ar9285_clc(ah, chan)) + return false; + } else if (AR_SREV_9280_10_OR_LATER(ah)) { REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); /* Kick off the cal */ REG_WRITE(ah, AR_PHY_AGC_CONTROL, - REG_READ(ah, AR_PHY_AGC_CONTROL) | - AR_PHY_AGC_CONTROL_CAL); + REG_READ(ah, AR_PHY_AGC_CONTROL) | + AR_PHY_AGC_CONTROL_CAL); if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_CAL, 0, - AH_WAIT_TIMEOUT)) { + AR_PHY_AGC_CONTROL_CAL, 0, + AH_WAIT_TIMEOUT)) { DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset calibration failed to complete in 1ms; " "noisy environment?\n"); @@ -906,11 +951,11 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, /* Calibrate the AGC */ REG_WRITE(ah, AR_PHY_AGC_CONTROL, - REG_READ(ah, AR_PHY_AGC_CONTROL) | - AR_PHY_AGC_CONTROL_CAL); + REG_READ(ah, AR_PHY_AGC_CONTROL) | + AR_PHY_AGC_CONTROL_CAL); if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, - 0, AH_WAIT_TIMEOUT)) { + 0, AH_WAIT_TIMEOUT)) { DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset calibration failed to complete in 1ms; " "noisy environment?\n"); @@ -928,8 +973,8 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, /* Do NF Calibration */ REG_WRITE(ah, AR_PHY_AGC_CONTROL, - REG_READ(ah, AR_PHY_AGC_CONTROL) | - AR_PHY_AGC_CONTROL_NF); + REG_READ(ah, AR_PHY_AGC_CONTROL) | + AR_PHY_AGC_CONTROL_NF); ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; @@ -938,19 +983,19 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, INIT_CAL(&ah->adcgain_caldata); INSERT_CAL(ah, &ah->adcgain_caldata); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "enabling ADC Gain Calibration.\n"); + "enabling ADC Gain Calibration.\n"); } if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) { INIT_CAL(&ah->adcdc_caldata); INSERT_CAL(ah, &ah->adcdc_caldata); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "enabling ADC DC Calibration.\n"); + "enabling ADC DC Calibration.\n"); } if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { INIT_CAL(&ah->iq_caldata); INSERT_CAL(ah, &ah->iq_caldata); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "enabling IQ Calibration.\n"); + "enabling IQ Calibration.\n"); } ah->cal_list_curr = ah->cal_list; diff --git a/drivers/net/wireless/ath9k/eeprom.h b/drivers/net/wireless/ath9k/eeprom.h index 6296e3eff10..d6f6108f63c 100644 --- a/drivers/net/wireless/ath9k/eeprom.h +++ b/drivers/net/wireless/ath9k/eeprom.h @@ -261,7 +261,7 @@ struct base_eep_header_4k { u16 deviceCap; u32 binBuildNumber; u8 deviceType; - u8 futureBase[1]; + u8 txGainType; } __packed; diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index eb750a50399..cdc9d15e841 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -678,6 +678,7 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, ah->hw_version.macVersion, ah->hw_version.macRev); if (AR_SREV_9285_12_OR_LATER(ah)) { + INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2, ARRAY_SIZE(ar9285Modes_9285_1_2), 6); INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2, @@ -817,6 +818,22 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, if (ecode != 0) goto bad; + if (AR_SREV_9285_12_OR_LATER(ah)) { + u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE); + + /* txgain table */ + if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) { + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9285Modes_high_power_tx_gain_9285_1_2, + ARRAY_SIZE(ar9285Modes_high_power_tx_gain_9285_1_2), 6); + } else { + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9285Modes_original_tx_gain_9285_1_2, + ARRAY_SIZE(ar9285Modes_original_tx_gain_9285_1_2), 6); + } + + } + /* rxgain table */ if (AR_SREV_9280_20(ah)) ath9k_hw_init_rxgain_ini(ah); @@ -1293,7 +1310,8 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, if (AR_SREV_9280(ah)) REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites); - if (AR_SREV_9280(ah)) + if (AR_SREV_9280(ah) || (AR_SREV_9285(ah) && + AR_SREV_9285_12_OR_LATER(ah))) REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); for (i = 0; i < ah->iniCommon.ia_rows; i++) { diff --git a/drivers/net/wireless/ath9k/initvals.h b/drivers/net/wireless/ath9k/initvals.h index d49236368a1..c32bc3b00d9 100644 --- a/drivers/net/wireless/ath9k/initvals.h +++ b/drivers/net/wireless/ath9k/initvals.h @@ -4121,6 +4121,7 @@ static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285[][2] = { {0x00004044, 0x00000000 }, }; +/* AR9285 v1_2 PCI Register Writes. Created: 03/04/09 */ static const u_int32_t ar9285Modes_9285_1_2[][6] = { { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, @@ -4155,7 +4156,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, + { 0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329 }, { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, @@ -4421,25 +4422,6 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 }, - { 0x0000a274, 0x0a81c652, 0x0a81c652, 0x0a820652, 0x0a820652, 0x0a82a652 }, - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000 }, - { 0x0000a308, 0x00000000, 0x00000000, 0x00010408, 0x00010408, 0x00000000 }, - { 0x0000a30c, 0x00000000, 0x00000000, 0x0001860a, 0x0001860a, 0x00000000 }, - { 0x0000a310, 0x00000000, 0x00000000, 0x00020818, 0x00020818, 0x00000000 }, - { 0x0000a314, 0x00000000, 0x00000000, 0x00024858, 0x00024858, 0x00000000 }, - { 0x0000a318, 0x00000000, 0x00000000, 0x00026859, 0x00026859, 0x00000000 }, - { 0x0000a31c, 0x00000000, 0x00000000, 0x0002985b, 0x0002985b, 0x00000000 }, - { 0x0000a320, 0x00000000, 0x00000000, 0x0002b89a, 0x0002b89a, 0x00000000 }, - { 0x0000a324, 0x00000000, 0x00000000, 0x0002d89b, 0x0002d89b, 0x00000000 }, - { 0x0000a328, 0x00000000, 0x00000000, 0x0002f89c, 0x0002f89c, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x0003189d, 0x0003189d, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x0003389e, 0x0003389e, 0x00000000 }, - { 0x0000a334, 0x00000000, 0x00000000, 0x000368de, 0x000368de, 0x00000000 }, - { 0x0000a338, 0x00000000, 0x00000000, 0x0003891e, 0x0003891e, 0x00000000 }, - { 0x0000a33c, 0x00000000, 0x00000000, 0x0003a95e, 0x0003a95e, 0x00000000 }, - { 0x0000a340, 0x00000000, 0x00000000, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, }; @@ -4569,7 +4551,7 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { { 0x00008110, 0x00000168 }, { 0x00008118, 0x000100aa }, { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04800 }, + { 0x00008120, 0x08f04810 }, { 0x00008124, 0x00000000 }, { 0x00008128, 0x00000000 }, { 0x0000812c, 0x00000000 }, @@ -4585,7 +4567,7 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { { 0x00008178, 0x00000100 }, { 0x0000817c, 0x00000000 }, { 0x000081c0, 0x00000000 }, - { 0x000081d0, 0x00003210 }, + { 0x000081d0, 0x0000320a }, { 0x000081ec, 0x00000000 }, { 0x000081f0, 0x00000000 }, { 0x000081f4, 0x00000000 }, @@ -4709,8 +4691,6 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { { 0x0000a268, 0x00000000 }, { 0x0000a26c, 0x0ebae9e6 }, { 0x0000d270, 0x0d820820 }, - { 0x0000a278, 0x318c6318 }, - { 0x0000a27c, 0x050c0318 }, { 0x0000d35c, 0x07ffffef }, { 0x0000d360, 0x0fffffe7 }, { 0x0000d364, 0x17ffffe5 }, @@ -4725,8 +4705,6 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { { 0x0000a388, 0x0c000000 }, { 0x0000a38c, 0x20202020 }, { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x318c6318 }, - { 0x0000a398, 0x00000318 }, { 0x0000a39c, 0x00000001 }, { 0x0000a3a0, 0x00000000 }, { 0x0000a3a4, 0x00000000 }, @@ -4741,8 +4719,6 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { { 0x0000a3cc, 0x20202020 }, { 0x0000a3d0, 0x20202020 }, { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x318c6318 }, - { 0x0000a3e0, 0x00000318 }, { 0x0000a3e4, 0x00000000 }, { 0x0000a3e8, 0x18c43433 }, { 0x0000a3ec, 0x00f70081 }, @@ -4753,13 +4729,11 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { { 0x00007810, 0x71c0d388 }, { 0x00007814, 0x924934a8 }, { 0x0000781c, 0x00000000 }, - { 0x00007820, 0x00000c04 }, { 0x00007824, 0x00d86fff }, { 0x00007828, 0x26d2491b }, { 0x0000782c, 0x6e36d97b }, { 0x00007830, 0xedb6d96e }, { 0x00007834, 0x71400087 }, - { 0x00007838, 0xfac68801 }, { 0x0000783c, 0x0001fffe }, { 0x00007840, 0xffeb1a20 }, { 0x00007844, 0x000c0db6 }, @@ -4772,10 +4746,81 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { { 0x00007860, 0x21084210 }, { 0x00007864, 0xf7d7ffde }, { 0x00007868, 0xc2034080 }, - { 0x0000786c, 0x48609eb4 }, { 0x00007870, 0x10142c00 }, }; +static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00005200, 0x00005200, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000 }, + { 0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x0000f440, 0x0000f440, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00014640, 0x00014640, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x00018680, 0x00018680, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x00019841, 0x00019841, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x0001ca40, 0x0001ca40, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x0001fa80, 0x0001fa80, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x00023ac0, 0x00023ac0, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000 }, + { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, + { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, + { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803 }, + { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, + { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, + { 0x0000a278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce }, + { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce }, + { 0x0000a394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce }, + { 0x0000a398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce }, + { 0x0000a3dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce }, + { 0x0000a3e0, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce }, +}; + +static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 }, + { 0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000 }, + { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, + { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, + { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801 }, + { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, + { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, + { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, + { 0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c }, + { 0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, + { 0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, +}; + static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = { {0x00004040, 0x9248fd00 }, {0x00004040, 0x24924924 }, diff --git a/drivers/net/wireless/ath9k/phy.h b/drivers/net/wireless/ath9k/phy.h index 6222e32c774..1eac8c70734 100644 --- a/drivers/net/wireless/ath9k/phy.h +++ b/drivers/net/wireless/ath9k/phy.h @@ -446,6 +446,9 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, #define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000 #define AR_PHY_TPCRG1_PD_GAIN_3_S 20 +#define AR_PHY_TPCRG1_PD_CAL_ENABLE 0x00400000 +#define AR_PHY_TPCRG1_PD_CAL_ENABLE_S 22 + #define AR_PHY_TX_PWRCTRL4 0xa264 #define AR_PHY_TX_PWRCTRL_PD_AVG_VALID 0x00000001 #define AR_PHY_TX_PWRCTRL_PD_AVG_VALID_S 0 @@ -513,6 +516,7 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, /* Carrier leak calibration control, do it after AGC calibration */ #define AR_PHY_CL_CAL_CTL 0xA358 #define AR_PHY_CL_CAL_ENABLE 0x00000002 +#define AR_PHY_PARALLEL_CAL_ENABLE 0x00000001 #define AR_PHY_POWER_TX_RATE5 0xA38C #define AR_PHY_POWER_TX_RATE6 0xA390 -- GitLab From 978b53264235eef1d2d2e9fd16ae26b3471c0b57 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Fri, 6 Mar 2009 11:24:11 +0530 Subject: [PATCH 3562/4982] ath9k: Incorrect AR9285 version check macro Fix AR9285 1.1 and 1.2 version check macro. Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/reg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath9k/reg.h b/drivers/net/wireless/ath9k/reg.h index 91442da1818..d7b8c571e91 100644 --- a/drivers/net/wireless/ath9k/reg.h +++ b/drivers/net/wireless/ath9k/reg.h @@ -778,14 +778,14 @@ #define AR_SREV_9285_10_OR_LATER(_ah) \ (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9285)) #define AR_SREV_9285_11(_ah) \ - (AR_SREV_9280(ah) && \ + (AR_SREV_9285(ah) && \ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_11)) #define AR_SREV_9285_11_OR_LATER(_ah) \ (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \ (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \ AR_SREV_REVISION_9285_11))) #define AR_SREV_9285_12(_ah) \ - (AR_SREV_9280(ah) && \ + (AR_SREV_9285(ah) && \ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_12)) #define AR_SREV_9285_12_OR_LATER(_ah) \ (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \ -- GitLab From a8c96d3b225d4c9e6ff341923e3f76de401c75b2 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Fri, 6 Mar 2009 09:08:51 +0100 Subject: [PATCH 3563/4982] ath9k: cleanup AR5416 version checking macros Currently we have two different versions of this macros. Because they would have to do the same thing, we should simplify and merge them. Changes-licensed-under: ISC Signed-off-by: Gabor Juhos Signed-off-by: Imre Kaloz Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/eeprom.c | 16 ++++++++-------- drivers/net/wireless/ath9k/hw.c | 4 ++-- drivers/net/wireless/ath9k/mac.h | 2 +- drivers/net/wireless/ath9k/reg.h | 19 +++++++++++-------- 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/ath9k/eeprom.c b/drivers/net/wireless/ath9k/eeprom.c index f935341bc5c..5a5ab23a2ba 100644 --- a/drivers/net/wireless/ath9k/eeprom.c +++ b/drivers/net/wireless/ath9k/eeprom.c @@ -640,7 +640,7 @@ static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah, pPdGainBoundaries[i] = min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); - if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah)) { + if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { minDelta = pPdGainBoundaries[0] - 23; pPdGainBoundaries[0] = 23; } else { @@ -755,7 +755,7 @@ static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0); for (i = 0; i < AR5416_MAX_CHAINS; i++) { - if (AR_SREV_5416_V20_OR_LATER(ah) && + if (AR_SREV_5416_20_OR_LATER(ah) && (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0)) { regChainOffset = (i == 1) ? 0x2000 : 0x1000; @@ -771,7 +771,7 @@ static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, &tMinCalPower, gainBoundaries, pdadcValues, numXpdGain); - if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) { + if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) @@ -1707,7 +1707,7 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, break; } - if (AR_SREV_5416_V20_OR_LATER(ah) && + if (AR_SREV_5416_20_OR_LATER(ah) && (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0)) regChainOffset = (i == 1) ? 0x2000 : 0x1000; @@ -1728,7 +1728,7 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, SM(pModal->iqCalQCh[i], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); - if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) { + if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { txRxAttenLocal = pModal->txRxAttenCh[i]; if (AR_SREV_9280_10_OR_LATER(ah)) { @@ -2094,7 +2094,7 @@ static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah, pPdGainBoundaries[i] = min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); - if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah)) { + if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { minDelta = pPdGainBoundaries[0] - 23; pPdGainBoundaries[0] = 23; } else { @@ -2228,7 +2228,7 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, xpdGainValues[2]); for (i = 0; i < AR5416_MAX_CHAINS; i++) { - if (AR_SREV_5416_V20_OR_LATER(ah) && + if (AR_SREV_5416_20_OR_LATER(ah) && (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0)) { regChainOffset = (i == 1) ? 0x2000 : 0x1000; @@ -2262,7 +2262,7 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, numXpdGain); } - if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) { + if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { if (OLC_FOR_AR9280_20_LATER) { REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index cdc9d15e841..c10b33b1b67 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -1170,7 +1170,7 @@ static void ath9k_hw_override_ini(struct ath_hw *ah, REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); - if (!AR_SREV_5416_V20_OR_LATER(ah) || + if (!AR_SREV_5416_20_OR_LATER(ah) || AR_SREV_9280_10_OR_LATER(ah)) return; @@ -1272,7 +1272,7 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO); ah->eep_ops->set_addac(ah, chan); - if (AR_SREV_5416_V22_OR_LATER(ah)) { + if (AR_SREV_5416_22_OR_LATER(ah)) { REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites); } else { struct ar5416IniArray temp; diff --git a/drivers/net/wireless/ath9k/mac.h b/drivers/net/wireless/ath9k/mac.h index 37e3948ddc2..a75f65dae1d 100644 --- a/drivers/net/wireless/ath9k/mac.h +++ b/drivers/net/wireless/ath9k/mac.h @@ -17,7 +17,7 @@ #ifndef MAC_H #define MAC_H -#define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_V20_OR_LATER(ah) ? \ +#define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_20_OR_LATER(ah) ? \ MS(ads->ds_rxstatus0, AR_RxRate) : \ (ads->ds_rxstatus3 >> 2) & 0xFF) diff --git a/drivers/net/wireless/ath9k/reg.h b/drivers/net/wireless/ath9k/reg.h index d7b8c571e91..0609e2e5eba 100644 --- a/drivers/net/wireless/ath9k/reg.h +++ b/drivers/net/wireless/ath9k/reg.h @@ -161,10 +161,6 @@ #define AR_SREV_VERSION_9100 0x014 #define AR_SREV_9100(ah) ((ah->hw_version.macVersion) == AR_SREV_VERSION_9100) -#define AR_SREV_5416_V20_OR_LATER(_ah) \ - (AR_SREV_9100((_ah)) || AR_SREV_5416_20_OR_LATER(_ah)) -#define AR_SREV_5416_V22_OR_LATER(_ah) \ - (AR_SREV_9100((_ah)) || AR_SREV_5416_22_OR_LATER(_ah)) #define AR_ISR 0x0080 #define AR_ISR_RXOK 0x00000001 @@ -748,12 +744,19 @@ #define AR_SREV_9100_OR_LATER(_ah) \ (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_5416_PCIE)) + +#define AR_SREV_5416(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ + ((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE)) #define AR_SREV_5416_20_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9160) || \ - ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_20)) + (((AR_SREV_5416(_ah)) && \ + ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_20)) || \ + ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100)) #define AR_SREV_5416_22_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9160) || \ - ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_22)) + (((AR_SREV_5416(_ah)) && \ + ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_22)) || \ + ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100)) + #define AR_SREV_9160(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9160)) #define AR_SREV_9160_10_OR_LATER(_ah) \ -- GitLab From d4376ebe168024695f15bfdf603ea6f083dc80f8 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Fri, 6 Mar 2009 09:08:52 +0100 Subject: [PATCH 3564/4982] ath9k: move ar9100 version checking macros into a more appropriate place All other version checking macros are in a common location within the reg.h file. The AR_SREV_9100_OR_LATER macro is wrong currently, but will be fixed with the next patch. Changes-licensed-under: ISC Signed-off-by: Gabor Juhos Signed-off-by: Imre Kaloz Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/reg.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath9k/reg.h b/drivers/net/wireless/ath9k/reg.h index 0609e2e5eba..1be4c71935e 100644 --- a/drivers/net/wireless/ath9k/reg.h +++ b/drivers/net/wireless/ath9k/reg.h @@ -158,10 +158,6 @@ #define AR_CST_TIMEOUT_LIMIT 0xFFFF0000 #define AR_CST_TIMEOUT_LIMIT_S 16 -#define AR_SREV_VERSION_9100 0x014 - -#define AR_SREV_9100(ah) ((ah->hw_version.macVersion) == AR_SREV_VERSION_9100) - #define AR_ISR 0x0080 #define AR_ISR_RXOK 0x00000001 #define AR_ISR_RXDESC 0x00000002 @@ -730,6 +726,7 @@ #define AR_SREV_REVISION_5416_10 0 #define AR_SREV_REVISION_5416_20 1 #define AR_SREV_REVISION_5416_22 2 +#define AR_SREV_VERSION_9100 0x14 #define AR_SREV_VERSION_9160 0x40 #define AR_SREV_REVISION_9160_10 0 #define AR_SREV_REVISION_9160_11 1 @@ -742,9 +739,6 @@ #define AR_SREV_REVISION_9285_11 1 #define AR_SREV_REVISION_9285_12 2 -#define AR_SREV_9100_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_5416_PCIE)) - #define AR_SREV_5416(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ ((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE)) @@ -757,6 +751,11 @@ ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_22)) || \ ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100)) +#define AR_SREV_9100(ah) \ + ((ah->hw_version.macVersion) == AR_SREV_VERSION_9100) +#define AR_SREV_9100_OR_LATER(_ah) \ + (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_5416_PCIE)) + #define AR_SREV_9160(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9160)) #define AR_SREV_9160_10_OR_LATER(_ah) \ -- GitLab From 6b765deb01dd076e64a4b01d2101d74206e7df84 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Fri, 6 Mar 2009 09:08:53 +0100 Subject: [PATCH 3565/4982] ath9k: fix AR_SREV_9100_OR_LATER macro The current macro is wrong, because detects some AR5416 devices as an AR9100 device. The AR5416 devices would have performance issues after this change, because the contents of the ar5416 specific and of the ar9100 specificinitval arrays are swapped. Fortunately we can correct this with the rename of the arrays simply. Changes-licesed-under: ISC Signed-off-by: Gabor Juhos Signed-off-by: Imre Kaloz Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/initvals.h | 44 +++++++++++++-------------- drivers/net/wireless/ath9k/reg.h | 2 +- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/ath9k/initvals.h b/drivers/net/wireless/ath9k/initvals.h index c32bc3b00d9..1d60c3706f1 100644 --- a/drivers/net/wireless/ath9k/initvals.h +++ b/drivers/net/wireless/ath9k/initvals.h @@ -14,7 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -static const u32 ar5416Modes_9100[][6] = { +static const u32 ar5416Modes[][6] = { { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, @@ -78,7 +78,7 @@ static const u32 ar5416Modes_9100[][6] = { { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, }; -static const u32 ar5416Common_9100[][2] = { +static const u32 ar5416Common[][2] = { { 0x0000000c, 0x00000000 }, { 0x00000030, 0x00020015 }, { 0x00000034, 0x00000005 }, @@ -456,12 +456,12 @@ static const u32 ar5416Common_9100[][2] = { { 0x0000a3e0, 0x000001ce }, }; -static const u32 ar5416Bank0_9100[][2] = { +static const u32 ar5416Bank0[][2] = { { 0x000098b0, 0x1e5795e5 }, { 0x000098e0, 0x02008020 }, }; -static const u32 ar5416BB_RfGain_9100[][3] = { +static const u32 ar5416BB_RfGain[][3] = { { 0x00009a00, 0x00000000, 0x00000000 }, { 0x00009a04, 0x00000040, 0x00000040 }, { 0x00009a08, 0x00000080, 0x00000080 }, @@ -528,21 +528,21 @@ static const u32 ar5416BB_RfGain_9100[][3] = { { 0x00009afc, 0x000000f9, 0x000000f9 }, }; -static const u32 ar5416Bank1_9100[][2] = { +static const u32 ar5416Bank1[][2] = { { 0x000098b0, 0x02108421 }, { 0x000098ec, 0x00000008 }, }; -static const u32 ar5416Bank2_9100[][2] = { +static const u32 ar5416Bank2[][2] = { { 0x000098b0, 0x0e73ff17 }, { 0x000098e0, 0x00000420 }, }; -static const u32 ar5416Bank3_9100[][3] = { +static const u32 ar5416Bank3[][3] = { { 0x000098f0, 0x01400018, 0x01c00018 }, }; -static const u32 ar5416Bank6_9100[][3] = { +static const u32 ar5416Bank6[][3] = { { 0x0000989c, 0x00000000, 0x00000000 }, { 0x0000989c, 0x00000000, 0x00000000 }, @@ -579,7 +579,7 @@ static const u32 ar5416Bank6_9100[][3] = { { 0x000098d0, 0x0000000f, 0x0010000f }, }; -static const u32 ar5416Bank6TPC_9100[][3] = { +static const u32 ar5416Bank6TPC[][3] = { { 0x0000989c, 0x00000000, 0x00000000 }, { 0x0000989c, 0x00000000, 0x00000000 }, { 0x0000989c, 0x00000000, 0x00000000 }, @@ -615,13 +615,13 @@ static const u32 ar5416Bank6TPC_9100[][3] = { { 0x000098d0, 0x0000000f, 0x0010000f }, }; -static const u32 ar5416Bank7_9100[][2] = { +static const u32 ar5416Bank7[][2] = { { 0x0000989c, 0x00000500 }, { 0x0000989c, 0x00000800 }, { 0x000098cc, 0x0000000e }, }; -static const u32 ar5416Addac_9100[][2] = { +static const u32 ar5416Addac[][2] = { {0x0000989c, 0x00000000 }, {0x0000989c, 0x00000003 }, {0x0000989c, 0x00000000 }, @@ -661,7 +661,7 @@ static const u32 ar5416Addac_9100[][2] = { {0x000098cc, 0x00000000 }, }; -static const u32 ar5416Modes[][6] = { +static const u32 ar5416Modes_9100[][6] = { { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, @@ -735,7 +735,7 @@ static const u32 ar5416Modes[][6] = { { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, }; -static const u32 ar5416Common[][2] = { +static const u32 ar5416Common_9100[][2] = { { 0x0000000c, 0x00000000 }, { 0x00000030, 0x00020015 }, { 0x00000034, 0x00000005 }, @@ -1109,12 +1109,12 @@ static const u32 ar5416Common[][2] = { { 0x0000a3e0, 0x000001ce }, }; -static const u32 ar5416Bank0[][2] = { +static const u32 ar5416Bank0_9100[][2] = { { 0x000098b0, 0x1e5795e5 }, { 0x000098e0, 0x02008020 }, }; -static const u32 ar5416BB_RfGain[][3] = { +static const u32 ar5416BB_RfGain_9100[][3] = { { 0x00009a00, 0x00000000, 0x00000000 }, { 0x00009a04, 0x00000040, 0x00000040 }, { 0x00009a08, 0x00000080, 0x00000080 }, @@ -1181,21 +1181,21 @@ static const u32 ar5416BB_RfGain[][3] = { { 0x00009afc, 0x000000f9, 0x000000f9 }, }; -static const u32 ar5416Bank1[][2] = { +static const u32 ar5416Bank1_9100[][2] = { { 0x000098b0, 0x02108421}, { 0x000098ec, 0x00000008}, }; -static const u32 ar5416Bank2[][2] = { +static const u32 ar5416Bank2_9100[][2] = { { 0x000098b0, 0x0e73ff17}, { 0x000098e0, 0x00000420}, }; -static const u32 ar5416Bank3[][3] = { +static const u32 ar5416Bank3_9100[][3] = { { 0x000098f0, 0x01400018, 0x01c00018 }, }; -static const u32 ar5416Bank6[][3] = { +static const u32 ar5416Bank6_9100[][3] = { { 0x0000989c, 0x00000000, 0x00000000 }, { 0x0000989c, 0x00000000, 0x00000000 }, @@ -1233,7 +1233,7 @@ static const u32 ar5416Bank6[][3] = { }; -static const u32 ar5416Bank6TPC[][3] = { +static const u32 ar5416Bank6TPC_9100[][3] = { { 0x0000989c, 0x00000000, 0x00000000 }, { 0x0000989c, 0x00000000, 0x00000000 }, @@ -1270,13 +1270,13 @@ static const u32 ar5416Bank6TPC[][3] = { { 0x000098d0, 0x0000000f, 0x0010000f }, }; -static const u32 ar5416Bank7[][2] = { +static const u32 ar5416Bank7_9100[][2] = { { 0x0000989c, 0x00000500 }, { 0x0000989c, 0x00000800 }, { 0x000098cc, 0x0000000e }, }; -static const u32 ar5416Addac[][2] = { +static const u32 ar5416Addac_9100[][2] = { {0x0000989c, 0x00000000 }, {0x0000989c, 0x00000000 }, {0x0000989c, 0x00000000 }, diff --git a/drivers/net/wireless/ath9k/reg.h b/drivers/net/wireless/ath9k/reg.h index 1be4c71935e..d86e90e3817 100644 --- a/drivers/net/wireless/ath9k/reg.h +++ b/drivers/net/wireless/ath9k/reg.h @@ -754,7 +754,7 @@ #define AR_SREV_9100(ah) \ ((ah->hw_version.macVersion) == AR_SREV_VERSION_9100) #define AR_SREV_9100_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_5416_PCIE)) + (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100)) #define AR_SREV_9160(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9160)) -- GitLab From 9251f0b418b202e2712c3408a5c6a5904ce4f453 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Fri, 6 Mar 2009 09:57:38 +0100 Subject: [PATCH 3566/4982] ath9k: fix compile error in ahb.c drivers/net/wireless/ath9k/ahb.c: In function 'ath_ahb_probe': drivers/net/wireless/ath9k/ahb.c:136: error: 'aphy' undeclared (first use in this function) Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ahb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath9k/ahb.c b/drivers/net/wireless/ath9k/ahb.c index bc562bd8889..00cc7bb01f2 100644 --- a/drivers/net/wireless/ath9k/ahb.c +++ b/drivers/net/wireless/ath9k/ahb.c @@ -60,6 +60,7 @@ static struct ath_bus_ops ath_ahb_bus_ops = { static int ath_ahb_probe(struct platform_device *pdev) { void __iomem *mem; + struct ath_wiphy *aphy; struct ath_softc *sc; struct ieee80211_hw *hw; struct resource *res; -- GitLab From 521031154365062ce334e05384139777db23d526 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Fri, 6 Mar 2009 09:57:39 +0100 Subject: [PATCH 3567/4982] ath9k: fix compile error in debug.c drivers/net/wireless/ath9k/debug.c: In function 'read_file_wiphy': drivers/net/wireless/ath9k/debug.c:377: error: implicit declaration of function 'put_unaligned_le32' drivers/net/wireless/ath9k/debug.c:378: error: implicit declaration of function 'put_unaligned_le16' Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/debug.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath9k/debug.c b/drivers/net/wireless/ath9k/debug.c index 0f7e249d2d2..b0ff4792546 100644 --- a/drivers/net/wireless/ath9k/debug.c +++ b/drivers/net/wireless/ath9k/debug.c @@ -14,6 +14,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include + #include "ath9k.h" static unsigned int ath9k_debug = DBG_DEFAULT; -- GitLab From 5077fd358b652b8ec33ae7158f99e08d29ad65c0 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Fri, 6 Mar 2009 11:17:55 +0100 Subject: [PATCH 3568/4982] ath9k: always compile ath_radio_{en,dis}able ath_radio_{en,dis}able is only compiled if RFKILL is enabled, but it is required by the 'ath9k_wiphy_select' function. Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 7d9c060704b..5268697be79 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1084,12 +1084,6 @@ fail: ath_deinit_leds(sc); } -#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) - -/*******************/ -/* Rfkill */ -/*******************/ - void ath_radio_enable(struct ath_softc *sc) { struct ath_hw *ah = sc->sc_ah; @@ -1166,6 +1160,12 @@ void ath_radio_disable(struct ath_softc *sc) ath9k_ps_restore(sc); } +#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) + +/*******************/ +/* Rfkill */ +/*******************/ + static bool ath_is_rfkill_set(struct ath_softc *sc) { struct ath_hw *ah = sc->sc_ah; -- GitLab From 3756162b06001d122ce31c716f9784636c592c9c Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Fri, 6 Mar 2009 12:02:25 +0100 Subject: [PATCH 3569/4982] libipw: fix debug output Replace all remaining occurrences of CONFIG_IEEE80211_DEBUG with CONFIG_LIBIPW_DEBUG in libipw to allow debug output again. Signed-off-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ieee80211.h | 6 +++--- drivers/net/wireless/ipw2x00/libipw_module.c | 16 ++++++++-------- drivers/net/wireless/ipw2x00/libipw_rx.c | 16 ++++++++-------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/ipw2x00/ieee80211.h b/drivers/net/wireless/ipw2x00/ieee80211.h index 7515fad00f9..97c7cfce543 100644 --- a/drivers/net/wireless/ipw2x00/ieee80211.h +++ b/drivers/net/wireless/ipw2x00/ieee80211.h @@ -112,7 +112,7 @@ /* debug macros */ -#ifdef CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG extern u32 ieee80211_debug_level; #define IEEE80211_DEBUG(level, fmt, args...) \ do { if (ieee80211_debug_level & (level)) \ @@ -128,7 +128,7 @@ static inline bool ieee80211_ratelimit_debug(u32 level) { return false; } -#endif /* CONFIG_IEEE80211_DEBUG */ +#endif /* CONFIG_LIBIPW_DEBUG */ /* * To use the debug system: @@ -152,7 +152,7 @@ static inline bool ieee80211_ratelimit_debug(u32 level) * you simply need to add your entry to the ieee80211_debug_level array. * * If you do not see debug_level in /proc/net/ieee80211 then you do not have - * CONFIG_IEEE80211_DEBUG defined in your kernel configuration + * CONFIG_LIBIPW_DEBUG defined in your kernel configuration * */ diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c index ec7753446bd..f4803fc0541 100644 --- a/drivers/net/wireless/ipw2x00/libipw_module.c +++ b/drivers/net/wireless/ipw2x00/libipw_module.c @@ -221,7 +221,7 @@ void free_ieee80211(struct net_device *dev) free_netdev(dev); } -#ifdef CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG static int debug = 0; u32 ieee80211_debug_level = 0; @@ -252,11 +252,11 @@ static int store_debug_level(struct file *file, const char __user * buffer, return strnlen(buf, len); } -#endif /* CONFIG_IEEE80211_DEBUG */ +#endif /* CONFIG_LIBIPW_DEBUG */ static int __init ieee80211_init(void) { -#ifdef CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG struct proc_dir_entry *e; ieee80211_debug_level = debug; @@ -276,7 +276,7 @@ static int __init ieee80211_init(void) e->read_proc = show_debug_level; e->write_proc = store_debug_level; e->data = NULL; -#endif /* CONFIG_IEEE80211_DEBUG */ +#endif /* CONFIG_LIBIPW_DEBUG */ printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); @@ -286,20 +286,20 @@ static int __init ieee80211_init(void) static void __exit ieee80211_exit(void) { -#ifdef CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG if (ieee80211_proc) { remove_proc_entry("debug_level", ieee80211_proc); remove_proc_entry(DRV_NAME, init_net.proc_net); ieee80211_proc = NULL; } -#endif /* CONFIG_IEEE80211_DEBUG */ +#endif /* CONFIG_LIBIPW_DEBUG */ } -#ifdef CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG #include module_param(debug, int, 0444); MODULE_PARM_DESC(debug, "debug output mask"); -#endif /* CONFIG_IEEE80211_DEBUG */ +#endif /* CONFIG_LIBIPW_DEBUG */ module_exit(ieee80211_exit); module_init(ieee80211_init); diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c index 8d9e96f9eb2..794d2fc0581 100644 --- a/drivers/net/wireless/ipw2x00/libipw_rx.c +++ b/drivers/net/wireless/ipw2x00/libipw_rx.c @@ -1080,7 +1080,7 @@ static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element return rc; } -#ifdef CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG #define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x static const char *get_info_element_string(u16 id) @@ -1125,7 +1125,7 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element { DECLARE_SSID_BUF(ssid); u8 i; -#ifdef CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG char rates_str[64]; char *p; #endif @@ -1161,14 +1161,14 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element break; case MFIE_TYPE_RATES: -#ifdef CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG p = rates_str; #endif network->rates_len = min(info_element->len, MAX_RATES_LENGTH); for (i = 0; i < network->rates_len; i++) { network->rates[i] = info_element->data[i]; -#ifdef CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]); @@ -1188,14 +1188,14 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element break; case MFIE_TYPE_RATES_EX: -#ifdef CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG p = rates_str; #endif network->rates_ex_len = min(info_element->len, MAX_RATES_EX_LENGTH); for (i = 0; i < network->rates_ex_len; i++) { network->rates_ex[i] = info_element->data[i]; -#ifdef CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]); @@ -1562,7 +1562,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device }; struct ieee80211_network *target; struct ieee80211_network *oldest = NULL; -#ifdef CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG struct ieee80211_info_element *info_element = beacon->info_element; #endif unsigned long flags; @@ -1640,7 +1640,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device list_del(ieee->network_free_list.next); } -#ifdef CONFIG_IEEE80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n", print_ssid(ssid, network.ssid, network.ssid_len), -- GitLab From 30e1863ccb2eb8052eb134abe51d6884cac50e29 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Fri, 6 Mar 2009 15:32:20 +0100 Subject: [PATCH 3570/4982] ipw2x00: remove duplicated defines Remove several duplicated defines from ipw2x00/ieee80211.h which are also available in linux/ieee80211.h. Signed-off-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ieee80211.h | 53 ------------------------ 1 file changed, 53 deletions(-) diff --git a/drivers/net/wireless/ipw2x00/ieee80211.h b/drivers/net/wireless/ipw2x00/ieee80211.h index 97c7cfce543..e292114629d 100644 --- a/drivers/net/wireless/ipw2x00/ieee80211.h +++ b/drivers/net/wireless/ipw2x00/ieee80211.h @@ -54,59 +54,6 @@ #define MIN_FRAG_THRESHOLD 256U #define MAX_FRAG_THRESHOLD 2346U -/* Frame control field constants */ -#define IEEE80211_FCTL_VERS 0x0003 -#define IEEE80211_FCTL_FTYPE 0x000c -#define IEEE80211_FCTL_STYPE 0x00f0 -#define IEEE80211_FCTL_TODS 0x0100 -#define IEEE80211_FCTL_FROMDS 0x0200 -#define IEEE80211_FCTL_MOREFRAGS 0x0400 -#define IEEE80211_FCTL_RETRY 0x0800 -#define IEEE80211_FCTL_PM 0x1000 -#define IEEE80211_FCTL_MOREDATA 0x2000 -#define IEEE80211_FCTL_PROTECTED 0x4000 -#define IEEE80211_FCTL_ORDER 0x8000 - -#define IEEE80211_FTYPE_MGMT 0x0000 -#define IEEE80211_FTYPE_CTL 0x0004 -#define IEEE80211_FTYPE_DATA 0x0008 - -/* management */ -#define IEEE80211_STYPE_ASSOC_REQ 0x0000 -#define IEEE80211_STYPE_ASSOC_RESP 0x0010 -#define IEEE80211_STYPE_REASSOC_REQ 0x0020 -#define IEEE80211_STYPE_REASSOC_RESP 0x0030 -#define IEEE80211_STYPE_PROBE_REQ 0x0040 -#define IEEE80211_STYPE_PROBE_RESP 0x0050 -#define IEEE80211_STYPE_BEACON 0x0080 -#define IEEE80211_STYPE_ATIM 0x0090 -#define IEEE80211_STYPE_DISASSOC 0x00A0 -#define IEEE80211_STYPE_AUTH 0x00B0 -#define IEEE80211_STYPE_DEAUTH 0x00C0 -#define IEEE80211_STYPE_ACTION 0x00D0 - -/* control */ -#define IEEE80211_STYPE_PSPOLL 0x00A0 -#define IEEE80211_STYPE_RTS 0x00B0 -#define IEEE80211_STYPE_CTS 0x00C0 -#define IEEE80211_STYPE_ACK 0x00D0 -#define IEEE80211_STYPE_CFEND 0x00E0 -#define IEEE80211_STYPE_CFENDACK 0x00F0 - -/* data */ -#define IEEE80211_STYPE_DATA 0x0000 -#define IEEE80211_STYPE_DATA_CFACK 0x0010 -#define IEEE80211_STYPE_DATA_CFPOLL 0x0020 -#define IEEE80211_STYPE_DATA_CFACKPOLL 0x0030 -#define IEEE80211_STYPE_NULLFUNC 0x0040 -#define IEEE80211_STYPE_CFACK 0x0050 -#define IEEE80211_STYPE_CFPOLL 0x0060 -#define IEEE80211_STYPE_CFACKPOLL 0x0070 -#define IEEE80211_STYPE_QOS_DATA 0x0080 - -#define IEEE80211_SCTL_FRAG 0x000F -#define IEEE80211_SCTL_SEQ 0xFFF0 - /* QOS control */ #define IEEE80211_QCTL_TID 0x000F -- GitLab From d74cc9a7a317cc173fb522252fdff9e4cdd282a0 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Fri, 6 Mar 2009 15:32:26 +0100 Subject: [PATCH 3571/4982] ipw2x00: Use IE definitions from linux/ieee80211.h Use IE definitions from linux/ieee80211.h and drop the appropriate enum from ipw2x00/ieee80211.h Signed-off-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ieee80211.h | 31 --------- drivers/net/wireless/ipw2x00/libipw_rx.c | 84 ++++++++++++------------ 2 files changed, 42 insertions(+), 73 deletions(-) diff --git a/drivers/net/wireless/ipw2x00/ieee80211.h b/drivers/net/wireless/ipw2x00/ieee80211.h index e292114629d..299e29fa290 100644 --- a/drivers/net/wireless/ipw2x00/ieee80211.h +++ b/drivers/net/wireless/ipw2x00/ieee80211.h @@ -358,37 +358,6 @@ Total: 28-2340 bytes #define BEACON_PROBE_SSID_ID_POSITION 12 -/* Management Frame Information Element Types */ -enum ieee80211_mfie { - MFIE_TYPE_SSID = 0, - MFIE_TYPE_RATES = 1, - MFIE_TYPE_FH_SET = 2, - MFIE_TYPE_DS_SET = 3, - MFIE_TYPE_CF_SET = 4, - MFIE_TYPE_TIM = 5, - MFIE_TYPE_IBSS_SET = 6, - MFIE_TYPE_COUNTRY = 7, - MFIE_TYPE_HOP_PARAMS = 8, - MFIE_TYPE_HOP_TABLE = 9, - MFIE_TYPE_REQUEST = 10, - MFIE_TYPE_CHALLENGE = 16, - MFIE_TYPE_POWER_CONSTRAINT = 32, - MFIE_TYPE_POWER_CAPABILITY = 33, - MFIE_TYPE_TPC_REQUEST = 34, - MFIE_TYPE_TPC_REPORT = 35, - MFIE_TYPE_SUPP_CHANNELS = 36, - MFIE_TYPE_CSA = 37, - MFIE_TYPE_MEASURE_REQUEST = 38, - MFIE_TYPE_MEASURE_REPORT = 39, - MFIE_TYPE_QUIET = 40, - MFIE_TYPE_IBSS_DFS = 41, - MFIE_TYPE_ERP_INFO = 42, - MFIE_TYPE_RSN = 48, - MFIE_TYPE_RATES_EX = 50, - MFIE_TYPE_GENERIC = 221, - MFIE_TYPE_QOS_PARAMETER = 222, -}; - struct ieee80211_hdr_1addr { __le16 frame_ctl; __le16 duration_id; diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c index 794d2fc0581..079007936d8 100644 --- a/drivers/net/wireless/ipw2x00/libipw_rx.c +++ b/drivers/net/wireless/ipw2x00/libipw_rx.c @@ -1081,36 +1081,36 @@ static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element } #ifdef CONFIG_LIBIPW_DEBUG -#define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x +#define MFIE_STRING(x) case WLAN_EID_ ##x: return #x static const char *get_info_element_string(u16 id) { switch (id) { MFIE_STRING(SSID); - MFIE_STRING(RATES); - MFIE_STRING(FH_SET); - MFIE_STRING(DS_SET); - MFIE_STRING(CF_SET); + MFIE_STRING(SUPP_RATES); + MFIE_STRING(FH_PARAMS); + MFIE_STRING(DS_PARAMS); + MFIE_STRING(CF_PARAMS); MFIE_STRING(TIM); - MFIE_STRING(IBSS_SET); + MFIE_STRING(IBSS_PARAMS); MFIE_STRING(COUNTRY); - MFIE_STRING(HOP_PARAMS); - MFIE_STRING(HOP_TABLE); + MFIE_STRING(HP_PARAMS); + MFIE_STRING(HP_TABLE); MFIE_STRING(REQUEST); MFIE_STRING(CHALLENGE); - MFIE_STRING(POWER_CONSTRAINT); - MFIE_STRING(POWER_CAPABILITY); + MFIE_STRING(PWR_CONSTRAINT); + MFIE_STRING(PWR_CAPABILITY); MFIE_STRING(TPC_REQUEST); MFIE_STRING(TPC_REPORT); - MFIE_STRING(SUPP_CHANNELS); - MFIE_STRING(CSA); + MFIE_STRING(SUPPORTED_CHANNELS); + MFIE_STRING(CHANNEL_SWITCH); MFIE_STRING(MEASURE_REQUEST); MFIE_STRING(MEASURE_REPORT); MFIE_STRING(QUIET); MFIE_STRING(IBSS_DFS); MFIE_STRING(ERP_INFO); MFIE_STRING(RSN); - MFIE_STRING(RATES_EX); + MFIE_STRING(EXT_SUPP_RATES); MFIE_STRING(GENERIC); MFIE_STRING(QOS_PARAMETER); default: @@ -1145,7 +1145,7 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element } switch (info_element->id) { - case MFIE_TYPE_SSID: + case WLAN_EID_SSID: network->ssid_len = min(info_element->len, (u8) IW_ESSID_MAX_SIZE); memcpy(network->ssid, info_element->data, @@ -1154,13 +1154,13 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element memset(network->ssid + network->ssid_len, 0, IW_ESSID_MAX_SIZE - network->ssid_len); - IEEE80211_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n", + IEEE80211_DEBUG_MGMT("WLAN_EID_SSID: '%s' len=%d.\n", print_ssid(ssid, network->ssid, network->ssid_len), network->ssid_len); break; - case MFIE_TYPE_RATES: + case WLAN_EID_SUPP_RATES: #ifdef CONFIG_LIBIPW_DEBUG p = rates_str; #endif @@ -1183,11 +1183,11 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element } } - IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n", + IEEE80211_DEBUG_MGMT("WLAN_EID_SUPP_RATES: '%s' (%d)\n", rates_str, network->rates_len); break; - case MFIE_TYPE_RATES_EX: + case WLAN_EID_EXT_SUPP_RATES: #ifdef CONFIG_LIBIPW_DEBUG p = rates_str; #endif @@ -1210,49 +1210,49 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element } } - IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n", + IEEE80211_DEBUG_MGMT("WLAN_EID_EXT_SUPP_RATES: '%s' (%d)\n", rates_str, network->rates_ex_len); break; - case MFIE_TYPE_DS_SET: - IEEE80211_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n", + case WLAN_EID_DS_PARAMS: + IEEE80211_DEBUG_MGMT("WLAN_EID_DS_PARAMS: %d\n", info_element->data[0]); network->channel = info_element->data[0]; break; - case MFIE_TYPE_FH_SET: - IEEE80211_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n"); + case WLAN_EID_FH_PARAMS: + IEEE80211_DEBUG_MGMT("WLAN_EID_FH_PARAMS: ignored\n"); break; - case MFIE_TYPE_CF_SET: - IEEE80211_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n"); + case WLAN_EID_CF_PARAMS: + IEEE80211_DEBUG_MGMT("WLAN_EID_CF_PARAMS: ignored\n"); break; - case MFIE_TYPE_TIM: + case WLAN_EID_TIM: network->tim.tim_count = info_element->data[0]; network->tim.tim_period = info_element->data[1]; - IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: partially ignored\n"); + IEEE80211_DEBUG_MGMT("WLAN_EID_TIM: partially ignored\n"); break; - case MFIE_TYPE_ERP_INFO: + case WLAN_EID_ERP_INFO: network->erp_value = info_element->data[0]; network->flags |= NETWORK_HAS_ERP_VALUE; IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n", network->erp_value); break; - case MFIE_TYPE_IBSS_SET: + case WLAN_EID_IBSS_PARAMS: network->atim_window = info_element->data[0]; - IEEE80211_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n", + IEEE80211_DEBUG_MGMT("WLAN_EID_IBSS_PARAMS: %d\n", network->atim_window); break; - case MFIE_TYPE_CHALLENGE: - IEEE80211_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n"); + case WLAN_EID_CHALLENGE: + IEEE80211_DEBUG_MGMT("WLAN_EID_CHALLENGE: ignored\n"); break; - case MFIE_TYPE_GENERIC: - IEEE80211_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n", + case WLAN_EID_GENERIC: + IEEE80211_DEBUG_MGMT("WLAN_EID_GENERIC: %d bytes\n", info_element->len); if (!ieee80211_parse_qos_info_param_IE(info_element, network)) @@ -1270,8 +1270,8 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element } break; - case MFIE_TYPE_RSN: - IEEE80211_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n", + case WLAN_EID_RSN: + IEEE80211_DEBUG_MGMT("WLAN_EID_RSN: %d bytes\n", info_element->len); network->rsn_ie_len = min(info_element->len + 2, MAX_WPA_IE_LEN); @@ -1279,22 +1279,22 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element network->rsn_ie_len); break; - case MFIE_TYPE_QOS_PARAMETER: + case WLAN_EID_QOS_PARAMETER: printk(KERN_ERR "QoS Error need to parse QOS_PARAMETER IE\n"); break; /* 802.11h */ - case MFIE_TYPE_POWER_CONSTRAINT: + case WLAN_EID_PWR_CONSTRAINT: network->power_constraint = info_element->data[0]; network->flags |= NETWORK_HAS_POWER_CONSTRAINT; break; - case MFIE_TYPE_CSA: + case WLAN_EID_CHANNEL_SWITCH: network->power_constraint = info_element->data[0]; network->flags |= NETWORK_HAS_CSA; break; - case MFIE_TYPE_QUIET: + case WLAN_EID_QUIET: network->quiet.count = info_element->data[0]; network->quiet.period = info_element->data[1]; network->quiet.duration = info_element->data[2]; @@ -1302,7 +1302,7 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element network->flags |= NETWORK_HAS_QUIET; break; - case MFIE_TYPE_IBSS_DFS: + case WLAN_EID_IBSS_DFS: if (network->ibss_dfs) break; network->ibss_dfs = kmemdup(info_element->data, @@ -1313,7 +1313,7 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element network->flags |= NETWORK_HAS_IBSS_DFS; break; - case MFIE_TYPE_TPC_REPORT: + case WLAN_EID_TPC_REPORT: network->tpc_report.transmit_power = info_element->data[0]; network->tpc_report.link_margin = info_element->data[1]; -- GitLab From cc88aff0732132e496d1c93a468a4577e93390ea Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Fri, 6 Mar 2009 15:32:31 +0100 Subject: [PATCH 3572/4982] ipw2x00: remove obsolete enums Remove obsolete enums from ipw2x00/ieee80211.h, they are not used anymore. Signed-off-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ieee80211.h | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/drivers/net/wireless/ipw2x00/ieee80211.h b/drivers/net/wireless/ipw2x00/ieee80211.h index 299e29fa290..f82435eae49 100644 --- a/drivers/net/wireless/ipw2x00/ieee80211.h +++ b/drivers/net/wireless/ipw2x00/ieee80211.h @@ -164,23 +164,6 @@ struct ieee80211_snap_hdr { #define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG) #define WLAN_GET_SEQ_SEQ(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) -/* Action categories - 802.11h */ -enum ieee80211_actioncategories { - WLAN_ACTION_SPECTRUM_MGMT = 0, - /* Reserved 1-127 */ - /* Error 128-255 */ -}; - -/* Action details - 802.11h */ -enum ieee80211_actiondetails { - WLAN_ACTION_CATEGORY_MEASURE_REQUEST = 0, - WLAN_ACTION_CATEGORY_MEASURE_REPORT = 1, - WLAN_ACTION_CATEGORY_TPC_REQUEST = 2, - WLAN_ACTION_CATEGORY_TPC_REPORT = 3, - WLAN_ACTION_CATEGORY_CHANNEL_SWITCH = 4, - /* 5 - 255 Reserved */ -}; - #define IEEE80211_STATMASK_SIGNAL (1<<0) #define IEEE80211_STATMASK_RSSI (1<<1) #define IEEE80211_STATMASK_NOISE (1<<2) -- GitLab From be1b08af61379be23d9975eaab29054e9166b13c Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Fri, 6 Mar 2009 20:38:36 +0530 Subject: [PATCH 3573/4982] ath9k: Use suitable macros with 4k eeprom data This patch improves range and connection stability in AR9285. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/eeprom.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath9k/eeprom.c b/drivers/net/wireless/ath9k/eeprom.c index 5a5ab23a2ba..183c949bcca 100644 --- a/drivers/net/wireless/ath9k/eeprom.c +++ b/drivers/net/wireless/ath9k/eeprom.c @@ -679,7 +679,7 @@ static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah, vpdTableI[i][sizeCurrVpdTable - 2]); vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); - if (tgtIndex > maxIndex) { + if (tgtIndex >= maxIndex) { while ((ss <= tgtIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { tmpVal = (int16_t) TMP_VAL_VPD_TABLE; @@ -713,11 +713,11 @@ static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, u8 *pCalBChans = NULL; u16 pdGainOverlap_t2; static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; - u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK]; + u16 gainBoundaries[AR5416_EEP4K_PD_GAINS_IN_MASK]; u16 numPiers, i, j; int16_t tMinCalPower; u16 numXpdGain, xpdMask; - u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 }; + u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 }; u32 reg32, regOffset, regChainOffset; xpdMask = pEepData->modalHeader.xpdGain; @@ -732,16 +732,16 @@ static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, } pCalBChans = pEepData->calFreqPier2G; - numPiers = AR5416_NUM_2G_CAL_PIERS; + numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS; numXpdGain = 0; - for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { - if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { - if (numXpdGain >= AR5416_NUM_PD_GAINS) + for (i = 1; i <= AR5416_EEP4K_PD_GAINS_IN_MASK; i++) { + if ((xpdMask >> (AR5416_EEP4K_PD_GAINS_IN_MASK - i)) & 1) { + if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS) break; xpdGainValues[numXpdGain] = - (u16)(AR5416_PD_GAINS_IN_MASK - i); + (u16)(AR5416_EEP4K_PD_GAINS_IN_MASK - i); numXpdGain++; } } @@ -754,7 +754,7 @@ static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, xpdGainValues[1]); REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0); - for (i = 0; i < AR5416_MAX_CHAINS; i++) { + for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) { if (AR_SREV_5416_20_OR_LATER(ah) && (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0)) { -- GitLab From 05c9a4cfe41f44abd5e73964fc734f01e2981442 Mon Sep 17 00:00:00 2001 From: John Daiker Date: Fri, 6 Mar 2009 07:09:41 -0800 Subject: [PATCH 3574/4982] airo_cs: checkpatch.pl cleanups Hopefully nothing controversial here, since the driver hasn't been touched in a while! Before: 36 errors, 6 warnings, 482 lines checked After: 0 errors, 3 warnings, 485 lines checked This was nearly all trailing whitespace, * and parenthesis spacing, and code indent changes. md5sum of object file before and after are identical. Signed-off-by: John Daiker Signed-off-by: John W. Linville --- drivers/net/wireless/airo_cs.c | 73 ++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index 27696c20f4c..d0593ed9170 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c @@ -16,8 +16,8 @@ In addition this module was derived from dummy_cs. The initial developer of dummy_cs is David A. Hinds . Portions created by David A. Hinds - are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - + are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + ======================================================================*/ #ifdef __IN_PCMCIA_PACKAGE__ @@ -38,7 +38,7 @@ #include #include -#include +#include #include #include "airo.h" @@ -54,7 +54,7 @@ static int pc_debug = PCMCIA_DEBUG; module_param(pc_debug, int, 0); static char *version = "$Revision: 1.2 $"; -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); +#define DEBUG(n, args...) if (pc_debug > (n)) printk(KERN_DEBUG args); #else #define DEBUG(n, args...) #endif @@ -62,9 +62,9 @@ static char *version = "$Revision: 1.2 $"; /*====================================================================*/ MODULE_AUTHOR("Benjamin Reed"); -MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet \ - cards. This is the module that links the PCMCIA card \ - with the airo module."); +MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet " + "cards. This is the module that links the PCMCIA card " + "with the airo module."); MODULE_LICENSE("Dual BSD/GPL"); MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards"); @@ -76,7 +76,7 @@ MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards"); event is received. The config() and release() entry points are used to configure or release a socket, in response to card insertion and ejection events. They are invoked from the airo_cs - event handler. + event handler. */ static int airo_config(struct pcmcia_device *link); @@ -103,8 +103,9 @@ static void airo_detach(struct pcmcia_device *p_dev); by one struct pcmcia_device structure (defined in ds.h). You may not want to use a linked list for this -- for example, the - memory card driver uses an array of struct pcmcia_device pointers, where minor - device numbers are used to derive the corresponding array index. + memory card driver uses an array of struct pcmcia_device pointers, + where minor device numbers are used to derive the corresponding + array index. */ /* @@ -122,22 +123,22 @@ static void airo_detach(struct pcmcia_device *p_dev); device IO routines can use a flag like this to throttle IO to a card that is not ready to accept it. */ - + typedef struct local_info_t { dev_node_t node; struct net_device *eth_dev; } local_info_t; /*====================================================================== - + airo_attach() creates an "instance" of the driver, allocating local data structures for one device. The device is registered with Card Services. - + The dev_link structure is initialized, but we don't actually configure the card at this point -- we wait until we receive a card insertion event. - + ======================================================================*/ static int airo_probe(struct pcmcia_device *p_dev) @@ -150,7 +151,7 @@ static int airo_probe(struct pcmcia_device *p_dev) p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; p_dev->irq.Handler = NULL; - + /* General socket configuration defaults can go here. In this client, we assume very little, and rely on the CIS for almost @@ -160,7 +161,7 @@ static int airo_probe(struct pcmcia_device *p_dev) */ p_dev->conf.Attributes = 0; p_dev->conf.IntType = INT_MEMORY_AND_IO; - + /* Allocate space for private device-specific data */ local = kzalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) { @@ -173,12 +174,12 @@ static int airo_probe(struct pcmcia_device *p_dev) } /* airo_attach */ /*====================================================================== - + This deletes a driver "instance". The device is de-registered with Card Services. If it has been released, all local data structures are freed. Otherwise, the structures will be freed when the device is released. - + ======================================================================*/ static void airo_detach(struct pcmcia_device *link) @@ -187,20 +188,20 @@ static void airo_detach(struct pcmcia_device *link) airo_release(link); - if ( ((local_info_t*)link->priv)->eth_dev ) { - stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 ); + if (((local_info_t *)link->priv)->eth_dev) { + stop_airo_card(((local_info_t *)link->priv)->eth_dev, 0); } - ((local_info_t*)link->priv)->eth_dev = NULL; + ((local_info_t *)link->priv)->eth_dev = NULL; kfree(link->priv); } /* airo_detach */ /*====================================================================== - + airo_config() is scheduled to run after a CARD_INSERTION event is received, to configure the PCMCIA socket, and to make the device available to the system. - + ======================================================================*/ #define CS_CHECK(fn, ret) \ @@ -325,26 +326,28 @@ static int airo_config(struct pcmcia_device *link) */ if (link->conf.Attributes & CONF_ENABLE_IRQ) CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); - + /* This actually configures the PCMCIA socket -- setting up the I/O windows and the interrupt mapping, and putting the card and host interface into "Memory and IO" mode. */ - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); - ((local_info_t*)link->priv)->eth_dev = - init_airo_card( link->irq.AssignedIRQ, - link->io.BasePort1, 1, &handle_to_dev(link) ); - if (!((local_info_t*)link->priv)->eth_dev) goto cs_failed; - + CS_CHECK(RequestConfiguration, + pcmcia_request_configuration(link, &link->conf)); + ((local_info_t *)link->priv)->eth_dev = + init_airo_card(link->irq.AssignedIRQ, + link->io.BasePort1, 1, &handle_to_dev(link)); + if (!((local_info_t *)link->priv)->eth_dev) + goto cs_failed; + /* At this point, the dev_node_t structure(s) need to be initialized and arranged in a linked list at link->dev_node. */ - strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name ); + strcpy(dev->node.dev_name, ((local_info_t *)link->priv)->eth_dev->name); dev->node.major = dev->node.minor = 0; link->dev_node = &dev->node; - + /* Finally, report what we've done */ printk(KERN_INFO "%s: index 0x%02x: ", dev->node.dev_name, link->conf.ConfigIndex); @@ -374,11 +377,11 @@ static int airo_config(struct pcmcia_device *link) } /* airo_config */ /*====================================================================== - + After a card is removed, airo_release() will unregister the device, and release the PCMCIA configuration. If the device is still open, this will be postponed until it is closed. - + ======================================================================*/ static void airo_release(struct pcmcia_device *link) @@ -475,7 +478,7 @@ static void airo_cs_cleanup(void) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. + POSSIBILITY OF SUCH DAMAGE. */ module_init(airo_cs_init); -- GitLab From 346de732cbd11bdc364ae80def2380a5002d7e6b Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 5 Mar 2009 21:28:57 +0100 Subject: [PATCH 3575/4982] p54: completely ignore rx'd frames with bad FCS Passing frames with a bad FCS to the user is an optional feature. However it doesn't work reliable and strangely not in the native monitor mode?! Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index b6905357a2e..0a989834b70 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -738,10 +738,7 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb) return 0; if (!(hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_IN_FCS_GOOD))) { - if (priv->filter_flags & FIF_FCSFAIL) - rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; - else - return 0; + return 0; } if (hdr->decrypt_status == P54_DECRYPT_OK) @@ -2220,9 +2217,7 @@ static void p54_configure_filter(struct ieee80211_hw *dev, struct p54_common *priv = dev->priv; *total_flags &= FIF_PROMISC_IN_BSS | - FIF_OTHER_BSS | - (*total_flags & FIF_PROMISC_IN_BSS ? - FIF_FCSFAIL : 0); + FIF_OTHER_BSS; priv->filter_flags = *total_flags; -- GitLab From 8337031ef393c8c4f9a25049fd4edd32c9911edc Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Fri, 6 Mar 2009 13:52:54 -0800 Subject: [PATCH 3576/4982] iwl3945: add test for new association Add check for new association to ease reading. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index d37679c69a5..12166cea386 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -328,6 +328,8 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon; struct iwl3945_rxon_cmd *staging_rxon = (void *)&priv->staging_rxon; int rc = 0; + bool new_assoc = + !!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK); if (!iwl_is_alive(priv)) return -1; @@ -366,8 +368,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) * an RXON_ASSOC and the new config wants the associated mask enabled, * we must clear the associated from the active configuration * before we apply the new config */ - if (iwl_is_associated(priv) && - (staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK)) { + if (iwl_is_associated(priv) && new_assoc) { IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n"); active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; @@ -395,8 +396,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) "* with%s RXON_FILTER_ASSOC_MSK\n" "* channel = %d\n" "* bssid = %pM\n", - ((priv->staging_rxon.filter_flags & - RXON_FILTER_ASSOC_MSK) ? "" : "out"), + (new_assoc ? "" : "out"), le16_to_cpu(staging_rxon->channel), staging_rxon->bssid_addr); -- GitLab From 77dcb6a9526b1e0d159a9300e512c7271bff3163 Mon Sep 17 00:00:00 2001 From: Jay Sternberg Date: Fri, 6 Mar 2009 13:52:55 -0800 Subject: [PATCH 3577/4982] iwlwifi: correct device name for 1000 series device name was changed from 100 to 1000 Signed-off-by: Jay Sternberg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Kconfig | 2 +- drivers/net/wireless/iwlwifi/Makefile | 2 +- .../iwlwifi/{iwl-100.c => iwl-1000.c} | 20 +++++++++---------- drivers/net/wireless/iwlwifi/iwl-agn.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-csr.h | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- 6 files changed, 17 insertions(+), 17 deletions(-) rename drivers/net/wireless/iwlwifi/{iwl-100.c => iwl-1000.c} (82%) diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 6cc5a54d35c..a894deb065d 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -87,7 +87,7 @@ config IWL4965 This option enables support for Intel Wireless WiFi Link 4965AGN config IWL5000 - bool "Intel Wireless WiFi 5000AGN; Intel WiFi Link 100, 6000, and 6050 Series" + bool "Intel Wireless WiFi 5000AGN; Intel WiFi Link 1000, 6000, and 6050 Series" depends on IWLAGN ---help--- This option enables support for Intel Wireless WiFi Link 5000AGN Family diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 48af523ceab..d5f8009c5ab 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -13,7 +13,7 @@ iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwlagn-$(CONFIG_IWL4965) += iwl-4965.o iwlagn-$(CONFIG_IWL5000) += iwl-5000.o iwlagn-$(CONFIG_IWL5000) += iwl-6000.o -iwlagn-$(CONFIG_IWL5000) += iwl-100.o +iwlagn-$(CONFIG_IWL5000) += iwl-1000.o obj-$(CONFIG_IWL3945) += iwl3945.o iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o diff --git a/drivers/net/wireless/iwlwifi/iwl-100.c b/drivers/net/wireless/iwlwifi/iwl-1000.c similarity index 82% rename from drivers/net/wireless/iwlwifi/iwl-100.c rename to drivers/net/wireless/iwlwifi/iwl-1000.c index 11d206abb71..7da52f1cc1d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-100.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -46,20 +46,20 @@ #include "iwl-5000-hw.h" /* Highest firmware API version supported */ -#define IWL100_UCODE_API_MAX 2 +#define IWL1000_UCODE_API_MAX 2 /* Lowest firmware API version supported */ -#define IWL100_UCODE_API_MIN 1 +#define IWL1000_UCODE_API_MIN 1 -#define IWL100_FW_PRE "iwlwifi-100-" -#define _IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE #api ".ucode" -#define IWL100_MODULE_FIRMWARE(api) _IWL100_MODULE_FIRMWARE(api) +#define IWL1000_FW_PRE "iwlwifi-1000-" +#define _IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE #api ".ucode" +#define IWL1000_MODULE_FIRMWARE(api) _IWL1000_MODULE_FIRMWARE(api) -struct iwl_cfg iwl100_bgn_cfg = { - .name = "100 Series BGN", - .fw_name_pre = IWL100_FW_PRE, - .ucode_api_max = IWL100_UCODE_API_MAX, - .ucode_api_min = IWL100_UCODE_API_MIN, +struct iwl_cfg iwl1000_bgn_cfg = { + .name = "1000 Series BGN", + .fw_name_pre = IWL1000_FW_PRE, + .ucode_api_max = IWL1000_UCODE_API_MAX, + .ucode_api_min = IWL1000_UCODE_API_MIN, .sku = IWL_SKU_G|IWL_SKU_N, .ops = &iwl5000_ops, .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 7902d22da66..da988860df1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3643,9 +3643,9 @@ static struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x0087, PCI_ANY_ID, iwl6050_2agn_cfg)}, {IWL_PCI_DEVICE(0x0088, PCI_ANY_ID, iwl6050_3agn_cfg)}, {IWL_PCI_DEVICE(0x0089, PCI_ANY_ID, iwl6050_2agn_cfg)}, -/* 100 Series WiFi */ - {IWL_PCI_DEVICE(0x0083, PCI_ANY_ID, iwl100_bgn_cfg)}, - {IWL_PCI_DEVICE(0x0084, PCI_ANY_ID, iwl100_bgn_cfg)}, +/* 1000 Series WiFi */ + {IWL_PCI_DEVICE(0x0083, PCI_ANY_ID, iwl1000_bgn_cfg)}, + {IWL_PCI_DEVICE(0x0084, PCI_ANY_ID, iwl1000_bgn_cfg)}, #endif /* CONFIG_IWL5000 */ {0} diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 5028c781275..2f1242447b3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -211,7 +211,7 @@ #define CSR_HW_REV_TYPE_5350 (0x0000030) #define CSR_HW_REV_TYPE_5100 (0x0000050) #define CSR_HW_REV_TYPE_5150 (0x0000040) -#define CSR_HW_REV_TYPE_100 (0x0000060) +#define CSR_HW_REV_TYPE_1000 (0x0000060) #define CSR_HW_REV_TYPE_6x00 (0x0000070) #define CSR_HW_REV_TYPE_6x50 (0x0000080) #define CSR_HW_REV_TYPE_NONE (0x00000F0) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index b3e23abb911..21764948833 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -62,7 +62,7 @@ extern struct iwl_cfg iwl6000_2agn_cfg; extern struct iwl_cfg iwl6000_3agn_cfg; extern struct iwl_cfg iwl6050_2agn_cfg; extern struct iwl_cfg iwl6050_3agn_cfg; -extern struct iwl_cfg iwl100_bgn_cfg; +extern struct iwl_cfg iwl1000_bgn_cfg; /* shared structures from iwl-5000.c */ extern struct iwl_mod_params iwl50_mod_params; -- GitLab From 2c91108c55477334f6854a587ec6e9111d8f1407 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Sat, 7 Mar 2009 10:26:41 +0100 Subject: [PATCH 3578/4982] ath5k: constify stuff Make some structures const to place them in .rodata, since we won't change them. Most important parts of objdump -h: - 0 .text 00011170 + 0 .text 00011140 - 5 .rodata 0000828e + 5 .rodata 0000895e - 13 .data 00000560 + 13 .data 00000110 - 14 .devinit.data 00000260 Signed-off-by: Jiri Slaby Acked-by: Nick Kossifidis Cc: Luis R. Rodriguez Cc: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/attach.c | 13 ++++++------- drivers/net/wireless/ath5k/base.c | 8 ++++---- drivers/net/wireless/ath5k/debug.c | 10 +++++----- drivers/net/wireless/ath5k/reset.c | 2 +- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/ath5k/attach.c b/drivers/net/wireless/ath5k/attach.c index 05bc5cb44e8..656cb9dc833 100644 --- a/drivers/net/wireless/ath5k/attach.c +++ b/drivers/net/wireless/ath5k/attach.c @@ -34,14 +34,14 @@ static int ath5k_hw_post(struct ath5k_hw *ah) { - int i, c; - u16 cur_reg; - u16 regs[2] = {AR5K_STA_ID0, AR5K_PHY(8)}; - u32 var_pattern; - u32 static_pattern[4] = { + static const u32 static_pattern[4] = { 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 }; + static const u16 regs[2] = { AR5K_STA_ID0, AR5K_PHY(8) }; + int i, c; + u16 cur_reg; + u32 var_pattern; u32 init_val; u32 cur_val; @@ -106,7 +106,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) { struct ath5k_hw *ah; struct pci_dev *pdev = sc->pdev; - u8 mac[ETH_ALEN] = {}; int ret; u32 srev; @@ -312,7 +311,7 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) } /* MAC address is cleared until add_interface */ - ath5k_hw_set_lladdr(ah, mac); + ath5k_hw_set_lladdr(ah, (u8[ETH_ALEN]){}); /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ memset(ah->ah_bssid, 0xff, ETH_ALEN); diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index f7c424dcac6..f2e5c3936f0 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -79,7 +79,7 @@ MODULE_VERSION("0.6.0 (EXPERIMENTAL)"); /* Known PCI ids */ -static struct pci_device_id ath5k_pci_id_table[] __devinitdata = { +static const struct pci_device_id ath5k_pci_id_table[] = { { PCI_VDEVICE(ATHEROS, 0x0207), .driver_data = AR5K_AR5210 }, /* 5210 early */ { PCI_VDEVICE(ATHEROS, 0x0007), .driver_data = AR5K_AR5210 }, /* 5210 */ { PCI_VDEVICE(ATHEROS, 0x0011), .driver_data = AR5K_AR5211 }, /* 5311 - this is on AHB bus !*/ @@ -103,7 +103,7 @@ static struct pci_device_id ath5k_pci_id_table[] __devinitdata = { MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); /* Known SREVs */ -static struct ath5k_srev_name srev_names[] = { +static const struct ath5k_srev_name srev_names[] = { { "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 }, { "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 }, { "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A }, @@ -142,7 +142,7 @@ static struct ath5k_srev_name srev_names[] = { { "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN }, }; -static struct ieee80211_rate ath5k_rates[] = { +static const struct ieee80211_rate ath5k_rates[] = { { .bitrate = 10, .hw_value = ATH5K_RATE_CODE_1M, }, { .bitrate = 20, @@ -248,7 +248,7 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_bss_conf *bss_conf, u32 changes); -static struct ieee80211_ops ath5k_hw_ops = { +static const struct ieee80211_ops ath5k_hw_ops = { .tx = ath5k_tx, .start = ath5k_start, .stop = ath5k_stop, diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c index 413ed689cd5..9770bb3d40f 100644 --- a/drivers/net/wireless/ath5k/debug.c +++ b/drivers/net/wireless/ath5k/debug.c @@ -82,14 +82,14 @@ static int ath5k_debugfs_open(struct inode *inode, struct file *file) /* debugfs: registers */ struct reg { - char *name; + const char *name; int addr; }; #define REG_STRUCT_INIT(r) { #r, r } /* just a few random registers, might want to add more */ -static struct reg regs[] = { +static const struct reg regs[] = { REG_STRUCT_INIT(AR5K_CR), REG_STRUCT_INIT(AR5K_RXDP), REG_STRUCT_INIT(AR5K_CFG), @@ -142,7 +142,7 @@ static struct reg regs[] = { static void *reg_start(struct seq_file *seq, loff_t *pos) { - return *pos < ARRAY_SIZE(regs) ? ®s[*pos] : NULL; + return *pos < ARRAY_SIZE(regs) ? (void *)®s[*pos] : NULL; } static void reg_stop(struct seq_file *seq, void *p) @@ -153,7 +153,7 @@ static void reg_stop(struct seq_file *seq, void *p) static void *reg_next(struct seq_file *seq, void *p, loff_t *pos) { ++*pos; - return *pos < ARRAY_SIZE(regs) ? ®s[*pos] : NULL; + return *pos < ARRAY_SIZE(regs) ? (void *)®s[*pos] : NULL; } static int reg_show(struct seq_file *seq, void *p) @@ -290,7 +290,7 @@ static const struct file_operations fops_reset = { /* debugfs: debug level */ -static struct { +static const struct { enum ath5k_debug_level level; const char *name; const char *desc; diff --git a/drivers/net/wireless/ath5k/reset.c b/drivers/net/wireless/ath5k/reset.c index 1531ccd3506..685dc213eda 100644 --- a/drivers/net/wireless/ath5k/reset.c +++ b/drivers/net/wireless/ath5k/reset.c @@ -102,7 +102,7 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, * index into rates for control rates, we can set it up like this because * this is only used for AR5212 and we know it supports G mode */ -static int control_rates[] = +static const unsigned int control_rates[] = { 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 }; /** -- GitLab From 8d6c39efed5987d3c1ade96e93753125a099f512 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Sat, 7 Mar 2009 10:26:42 +0100 Subject: [PATCH 3579/4982] ath5k: don't change mac in eeprom_read_mac on error Do not touch mac parameter passed to ath5k_eeprom_read_mac unless we are sure we have correct address. I.e. when returning error, do not change it. While at it, use '= {}' compiler trick for memsetting mac_d. Signed-off-by: Jiri Slaby Acked-by: Nick Kossifidis Cc: Luis R. Rodriguez Acked-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/eeprom.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath5k/eeprom.c b/drivers/net/wireless/ath5k/eeprom.c index a54ee7e4967..ac45ca47ca8 100644 --- a/drivers/net/wireless/ath5k/eeprom.c +++ b/drivers/net/wireless/ath5k/eeprom.c @@ -1418,14 +1418,11 @@ ath5k_eeprom_init(struct ath5k_hw *ah) */ int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) { - u8 mac_d[ETH_ALEN]; + u8 mac_d[ETH_ALEN] = {}; u32 total, offset; u16 data; int octet, ret; - memset(mac, 0, ETH_ALEN); - memset(mac_d, 0, ETH_ALEN); - ret = ath5k_hw_eeprom_read(ah, 0x20, &data); if (ret) return ret; @@ -1441,11 +1438,11 @@ int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) octet += 2; } - memcpy(mac, mac_d, ETH_ALEN); - if (!total || total == 3 * 0xffff) return -EINVAL; + memcpy(mac, mac_d, ETH_ALEN); + return 0; } -- GitLab From 0ed4548f81b69363a6257dbc23086fc9fe4a23cb Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sun, 8 Mar 2009 00:10:20 -0500 Subject: [PATCH 3580/4982] ath5k: extract LED code into a separate file Move LED code out of base.c for clarity. Changes-licensed-under: 3-Clause-BSD Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/Makefile | 1 + drivers/net/wireless/ath5k/ath5k.h | 6 + drivers/net/wireless/ath5k/base.c | 140 ----------------------- drivers/net/wireless/ath5k/led.c | 169 ++++++++++++++++++++++++++++ 4 files changed, 176 insertions(+), 140 deletions(-) create mode 100644 drivers/net/wireless/ath5k/led.c diff --git a/drivers/net/wireless/ath5k/Makefile b/drivers/net/wireless/ath5k/Makefile index 719cfaef708..84a74c5248e 100644 --- a/drivers/net/wireless/ath5k/Makefile +++ b/drivers/net/wireless/ath5k/Makefile @@ -10,5 +10,6 @@ ath5k-y += phy.o ath5k-y += reset.o ath5k-y += attach.o ath5k-y += base.o +ath5k-y += led.o ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o obj-$(CONFIG_ATH5K) += ath5k.o diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index b9af2b84c05..0dc2c7321c8 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h @@ -1129,6 +1129,12 @@ struct ath5k_hw { extern struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version); extern void ath5k_hw_detach(struct ath5k_hw *ah); +/* LED functions */ +extern int ath5k_init_leds(struct ath5k_softc *sc); +extern void ath5k_led_enable(struct ath5k_softc *sc); +extern void ath5k_led_off(struct ath5k_softc *sc); +extern void ath5k_unregister_leds(struct ath5k_softc *sc); + /* Reset Functions */ extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); extern int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel); diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index f2e5c3936f0..cad3ccf61b0 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -370,11 +370,6 @@ static irqreturn_t ath5k_intr(int irq, void *dev_id); static void ath5k_tasklet_reset(unsigned long data); static void ath5k_calibrate(unsigned long data); -/* LED functions */ -static int ath5k_init_leds(struct ath5k_softc *sc); -static void ath5k_led_enable(struct ath5k_softc *sc); -static void ath5k_led_off(struct ath5k_softc *sc); -static void ath5k_unregister_leds(struct ath5k_softc *sc); /* * Module init/exit functions @@ -2530,141 +2525,6 @@ ath5k_calibrate(unsigned long data) } - -/***************\ -* LED functions * -\***************/ - -static void -ath5k_led_enable(struct ath5k_softc *sc) -{ - if (test_bit(ATH_STAT_LEDSOFT, sc->status)) { - ath5k_hw_set_gpio_output(sc->ah, sc->led_pin); - ath5k_led_off(sc); - } -} - -static void -ath5k_led_on(struct ath5k_softc *sc) -{ - if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) - return; - ath5k_hw_set_gpio(sc->ah, sc->led_pin, sc->led_on); -} - -static void -ath5k_led_off(struct ath5k_softc *sc) -{ - if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) - return; - ath5k_hw_set_gpio(sc->ah, sc->led_pin, !sc->led_on); -} - -static void -ath5k_led_brightness_set(struct led_classdev *led_dev, - enum led_brightness brightness) -{ - struct ath5k_led *led = container_of(led_dev, struct ath5k_led, - led_dev); - - if (brightness == LED_OFF) - ath5k_led_off(led->sc); - else - ath5k_led_on(led->sc); -} - -static int -ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led, - const char *name, char *trigger) -{ - int err; - - led->sc = sc; - strncpy(led->name, name, sizeof(led->name)); - led->led_dev.name = led->name; - led->led_dev.default_trigger = trigger; - led->led_dev.brightness_set = ath5k_led_brightness_set; - - err = led_classdev_register(&sc->pdev->dev, &led->led_dev); - if (err) { - ATH5K_WARN(sc, "could not register LED %s\n", name); - led->sc = NULL; - } - return err; -} - -static void -ath5k_unregister_led(struct ath5k_led *led) -{ - if (!led->sc) - return; - led_classdev_unregister(&led->led_dev); - ath5k_led_off(led->sc); - led->sc = NULL; -} - -static void -ath5k_unregister_leds(struct ath5k_softc *sc) -{ - ath5k_unregister_led(&sc->rx_led); - ath5k_unregister_led(&sc->tx_led); -} - - -static int -ath5k_init_leds(struct ath5k_softc *sc) -{ - int ret = 0; - struct ieee80211_hw *hw = sc->hw; - struct pci_dev *pdev = sc->pdev; - char name[ATH5K_LED_MAX_NAME_LEN + 1]; - - /* - * Auto-enable soft led processing for IBM cards and for - * 5211 minipci cards. - */ - if (pdev->device == PCI_DEVICE_ID_ATHEROS_AR5212_IBM || - pdev->device == PCI_DEVICE_ID_ATHEROS_AR5211) { - __set_bit(ATH_STAT_LEDSOFT, sc->status); - sc->led_pin = 0; - sc->led_on = 0; /* active low */ - } - /* Enable softled on PIN1 on HP Compaq nc6xx, nc4000 & nx5000 laptops */ - if (pdev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ) { - __set_bit(ATH_STAT_LEDSOFT, sc->status); - sc->led_pin = 1; - sc->led_on = 1; /* active high */ - } - /* - * Pin 3 on Foxconn chips used in Acer Aspire One (0x105b:e008) and - * in emachines notebooks with AMBIT subsystem. - */ - if (pdev->subsystem_vendor == PCI_VENDOR_ID_FOXCONN || - pdev->subsystem_vendor == PCI_VENDOR_ID_AMBIT) { - __set_bit(ATH_STAT_LEDSOFT, sc->status); - sc->led_pin = 3; - sc->led_on = 0; /* active low */ - } - - if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) - goto out; - - ath5k_led_enable(sc); - - snprintf(name, sizeof(name), "ath5k-%s::rx", wiphy_name(hw->wiphy)); - ret = ath5k_register_led(sc, &sc->rx_led, name, - ieee80211_get_rx_led_name(hw)); - if (ret) - goto out; - - snprintf(name, sizeof(name), "ath5k-%s::tx", wiphy_name(hw->wiphy)); - ret = ath5k_register_led(sc, &sc->tx_led, name, - ieee80211_get_tx_led_name(hw)); -out: - return ret; -} - - /********************\ * Mac80211 functions * \********************/ diff --git a/drivers/net/wireless/ath5k/led.c b/drivers/net/wireless/ath5k/led.c new file mode 100644 index 00000000000..7cef2bb408d --- /dev/null +++ b/drivers/net/wireless/ath5k/led.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting + * Copyright (c) 2004-2005 Atheros Communications, Inc. + * Copyright (c) 2007 Jiri Slaby + * Copyright (c) 2009 Bob Copeland + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +#include +#include "ath5k.h" +#include "base.h" + +void ath5k_led_enable(struct ath5k_softc *sc) +{ + if (test_bit(ATH_STAT_LEDSOFT, sc->status)) { + ath5k_hw_set_gpio_output(sc->ah, sc->led_pin); + ath5k_led_off(sc); + } +} + +void ath5k_led_on(struct ath5k_softc *sc) +{ + if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) + return; + ath5k_hw_set_gpio(sc->ah, sc->led_pin, sc->led_on); +} + +void ath5k_led_off(struct ath5k_softc *sc) +{ + if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) + return; + ath5k_hw_set_gpio(sc->ah, sc->led_pin, !sc->led_on); +} + +static void +ath5k_led_brightness_set(struct led_classdev *led_dev, + enum led_brightness brightness) +{ + struct ath5k_led *led = container_of(led_dev, struct ath5k_led, + led_dev); + + if (brightness == LED_OFF) + ath5k_led_off(led->sc); + else + ath5k_led_on(led->sc); +} + +static int +ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led, + const char *name, char *trigger) +{ + int err; + + led->sc = sc; + strncpy(led->name, name, sizeof(led->name)); + led->led_dev.name = led->name; + led->led_dev.default_trigger = trigger; + led->led_dev.brightness_set = ath5k_led_brightness_set; + + err = led_classdev_register(&sc->pdev->dev, &led->led_dev); + if (err) { + ATH5K_WARN(sc, "could not register LED %s\n", name); + led->sc = NULL; + } + return err; +} + +static void +ath5k_unregister_led(struct ath5k_led *led) +{ + if (!led->sc) + return; + led_classdev_unregister(&led->led_dev); + ath5k_led_off(led->sc); + led->sc = NULL; +} + +void ath5k_unregister_leds(struct ath5k_softc *sc) +{ + ath5k_unregister_led(&sc->rx_led); + ath5k_unregister_led(&sc->tx_led); +} + + +int ath5k_init_leds(struct ath5k_softc *sc) +{ + int ret = 0; + struct ieee80211_hw *hw = sc->hw; + struct pci_dev *pdev = sc->pdev; + char name[ATH5K_LED_MAX_NAME_LEN + 1]; + + /* + * Auto-enable soft led processing for IBM cards and for + * 5211 minipci cards. + */ + if (pdev->device == PCI_DEVICE_ID_ATHEROS_AR5212_IBM || + pdev->device == PCI_DEVICE_ID_ATHEROS_AR5211) { + __set_bit(ATH_STAT_LEDSOFT, sc->status); + sc->led_pin = 0; + sc->led_on = 0; /* active low */ + } + /* Enable softled on PIN1 on HP Compaq nc6xx, nc4000 & nx5000 laptops */ + if (pdev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ) { + __set_bit(ATH_STAT_LEDSOFT, sc->status); + sc->led_pin = 1; + sc->led_on = 1; /* active high */ + } + /* + * Pin 3 on Foxconn chips used in Acer Aspire One (0x105b:e008) and + * in emachines notebooks with AMBIT subsystem. + */ + if (pdev->subsystem_vendor == PCI_VENDOR_ID_FOXCONN || + pdev->subsystem_vendor == PCI_VENDOR_ID_AMBIT) { + __set_bit(ATH_STAT_LEDSOFT, sc->status); + sc->led_pin = 3; + sc->led_on = 0; /* active low */ + } + + if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) + goto out; + + ath5k_led_enable(sc); + + snprintf(name, sizeof(name), "ath5k-%s::rx", wiphy_name(hw->wiphy)); + ret = ath5k_register_led(sc, &sc->rx_led, name, + ieee80211_get_rx_led_name(hw)); + if (ret) + goto out; + + snprintf(name, sizeof(name), "ath5k-%s::tx", wiphy_name(hw->wiphy)); + ret = ath5k_register_led(sc, &sc->tx_led, name, + ieee80211_get_tx_led_name(hw)); +out: + return ret; +} + -- GitLab From cdb02dc6146950155e79a4e3225e1b58cf2b0c54 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sun, 8 Mar 2009 00:10:21 -0500 Subject: [PATCH 3581/4982] ath5k: use a table for LED parameters Put the device id-to-gpio mapping in a table to make it easier to add new devices. The list of supported devices is unchanged. Signed-off-by: Bob Copeland Acked-by: Jiri Slaby Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/led.c | 53 +++++++++++++++++--------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/drivers/net/wireless/ath5k/led.c b/drivers/net/wireless/ath5k/led.c index 7cef2bb408d..e365fbd3423 100644 --- a/drivers/net/wireless/ath5k/led.c +++ b/drivers/net/wireless/ath5k/led.c @@ -43,6 +43,29 @@ #include "ath5k.h" #include "base.h" +#define ATH_SDEVICE(subv,subd) \ + .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \ + .subvendor = (subv), .subdevice = (subd) + +#define ATH_LED(pin,polarity) .driver_data = (((pin) << 8) | (polarity)) +#define ATH_PIN(data) ((data) >> 8) +#define ATH_POLARITY(data) ((data) & 0xff) + +/* Devices we match on for LED config info (typically laptops) */ +static const struct pci_device_id ath5k_led_devices[] = { + /* IBM-specific AR5212 */ + { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) }, + /* AR5211 */ + { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5211), ATH_LED(0, 0) }, + /* HP Compaq nc6xx, nc4000, nx6000 */ + { ATH_SDEVICE(PCI_VENDOR_ID_COMPAQ, PCI_ANY_ID), ATH_LED(1, 1) }, + /* Acer Aspire One A150 (maximlevitsky@gmail.com) */ + { ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, PCI_ANY_ID), ATH_LED(3, 0) }, + /* E-machines E510 (tuliom@gmail.com) */ + { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, PCI_ANY_ID), ATH_LED(3, 0) }, + { } +}; + void ath5k_led_enable(struct ath5k_softc *sc) { if (test_bit(ATH_STAT_LEDSOFT, sc->status)) { @@ -114,39 +137,19 @@ void ath5k_unregister_leds(struct ath5k_softc *sc) ath5k_unregister_led(&sc->tx_led); } - int ath5k_init_leds(struct ath5k_softc *sc) { int ret = 0; struct ieee80211_hw *hw = sc->hw; struct pci_dev *pdev = sc->pdev; char name[ATH5K_LED_MAX_NAME_LEN + 1]; + const struct pci_device_id *match; - /* - * Auto-enable soft led processing for IBM cards and for - * 5211 minipci cards. - */ - if (pdev->device == PCI_DEVICE_ID_ATHEROS_AR5212_IBM || - pdev->device == PCI_DEVICE_ID_ATHEROS_AR5211) { - __set_bit(ATH_STAT_LEDSOFT, sc->status); - sc->led_pin = 0; - sc->led_on = 0; /* active low */ - } - /* Enable softled on PIN1 on HP Compaq nc6xx, nc4000 & nx5000 laptops */ - if (pdev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ) { - __set_bit(ATH_STAT_LEDSOFT, sc->status); - sc->led_pin = 1; - sc->led_on = 1; /* active high */ - } - /* - * Pin 3 on Foxconn chips used in Acer Aspire One (0x105b:e008) and - * in emachines notebooks with AMBIT subsystem. - */ - if (pdev->subsystem_vendor == PCI_VENDOR_ID_FOXCONN || - pdev->subsystem_vendor == PCI_VENDOR_ID_AMBIT) { + match = pci_match_id(&ath5k_led_devices[0], pdev); + if (match) { __set_bit(ATH_STAT_LEDSOFT, sc->status); - sc->led_pin = 3; - sc->led_on = 0; /* active low */ + sc->led_pin = ATH_PIN(match->driver_data); + sc->led_on = ATH_POLARITY(match->driver_data); } if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) -- GitLab From 22e5b08585f7282060c464a36908b19cb4809fde Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sun, 8 Mar 2009 00:10:22 -0500 Subject: [PATCH 3582/4982] ath5k: update LED table with reported devices This patch adds support for Acer Ferrari 5000, and also specifies the subsystem device ids for previously reported e-machines e510 and Acer Aspire One A150. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/led.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath5k/led.c b/drivers/net/wireless/ath5k/led.c index e365fbd3423..0686e12738b 100644 --- a/drivers/net/wireless/ath5k/led.c +++ b/drivers/net/wireless/ath5k/led.c @@ -60,9 +60,11 @@ static const struct pci_device_id ath5k_led_devices[] = { /* HP Compaq nc6xx, nc4000, nx6000 */ { ATH_SDEVICE(PCI_VENDOR_ID_COMPAQ, PCI_ANY_ID), ATH_LED(1, 1) }, /* Acer Aspire One A150 (maximlevitsky@gmail.com) */ - { ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, PCI_ANY_ID), ATH_LED(3, 0) }, + { ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe008), ATH_LED(3, 0) }, + /* Acer Ferrari 5000 (russ.dill@gmail.com) */ + { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0422), ATH_LED(1, 1) }, /* E-machines E510 (tuliom@gmail.com) */ - { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, PCI_ANY_ID), ATH_LED(3, 0) }, + { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0428), ATH_LED(3, 0) }, { } }; -- GitLab From 9c81e8be236b7f1c94f9d055a97a83f84c81890f Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 9 Mar 2009 09:31:49 +0530 Subject: [PATCH 3583/4982] ath9k: Initialize ANI properly ANI was not being initialized correctly for all HW variants. This patch fixes it. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/hw.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index c10b33b1b67..ea550cc6435 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -662,16 +662,9 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; } - if (AR_SREV_9160(ah)) { - ah->config.enable_ani = 1; - ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL | - ATH9K_ANI_FIRSTEP_LEVEL); - } else { - ah->ani_function = ATH9K_ANI_ALL; - if (AR_SREV_9280_10_OR_LATER(ah)) { - ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; - } - } + ah->ani_function = ATH9K_ANI_ALL; + if (AR_SREV_9280_10_OR_LATER(ah)) + ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; DPRINTF(sc, ATH_DBG_RESET, "This Mac Chip Rev 0x%02x.%x is \n", -- GitLab From c37452b0687e5c8942dd4866f7c614105e6050c3 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 9 Mar 2009 09:31:57 +0530 Subject: [PATCH 3584/4982] ath9k: Fix bug in TX aggregation mac80211 expects the driver to fill in the starting sequence number of an ADDBA request to initiate TX aggregation. IEEE80211_TX_CTL_AMPDU would be set for frames only after a successful ADDBA exchange, but we have to increment the internal sequence counter for the normal(non-AMPDU) data frames proerly. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/xmit.c | 49 +++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index a82d2ab7c3a..f61ba2b7de7 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -55,9 +55,9 @@ static u32 bits_per_symbol[][2] = { #define IS_HT_RATE(_rate) ((_rate) & 0x80) -static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid, - struct list_head *bf_head); +static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, + struct ath_atx_tid *tid, + struct list_head *bf_head); static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, struct list_head *bf_q, int txok, int sendbar); @@ -152,7 +152,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) bf = list_first_entry(&tid->buf_q, struct ath_buf, list); ASSERT(!bf_isretried(bf)); list_move_tail(&bf->list, &bf_head); - ath_tx_send_normal(sc, txq, tid, &bf_head); + ath_tx_send_ht_normal(sc, txq, tid, &bf_head); } spin_unlock_bh(&txq->axq_lock); @@ -1238,9 +1238,9 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, ath_tx_txqaddbuf(sc, txctl->txq, bf_head); } -static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid, - struct list_head *bf_head) +static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, + struct ath_atx_tid *tid, + struct list_head *bf_head) { struct ath_buf *bf; @@ -1256,6 +1256,19 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, ath_tx_txqaddbuf(sc, txq, bf_head); } +static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, + struct list_head *bf_head) +{ + struct ath_buf *bf; + + bf = list_first_entry(bf_head, struct ath_buf, list); + + bf->bf_lastbf = bf; + bf->bf_nframes = 1; + ath_buf_set_rate(sc, bf); + ath_tx_txqaddbuf(sc, txq, bf_head); +} + static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) { struct ieee80211_hdr *hdr; @@ -1522,8 +1535,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3); - if ((conf_is_ht(&sc->hw->conf) && !is_pae(skb) && - (tx_info->flags & IEEE80211_TX_CTL_AMPDU))) + if (conf_is_ht(&sc->hw->conf) && !is_pae(skb)) bf->bf_state.bf_type |= BUF_HT; bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq); @@ -1560,14 +1572,17 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, { struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ath_node *an = NULL; struct list_head bf_head; struct ath_desc *ds; struct ath_atx_tid *tid; struct ath_hw *ah = sc->sc_ah; int frm_type; + __le16 fc; frm_type = get_hw_packet_type(skb); + fc = hdr->frame_control; INIT_LIST_HEAD(&bf_head); list_add_tail(&bf->list, &bf_head); @@ -1592,6 +1607,11 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, an = (struct ath_node *)tx_info->control.sta->drv_priv; tid = ATH_AN_2_TID(an, bf->bf_tidno); + if (!ieee80211_is_data_qos(fc)) { + ath_tx_send_normal(sc, txctl->txq, &bf_head); + goto tx_done; + } + if (ath_aggr_query(sc, an, bf->bf_tidno)) { /* * Try aggregation if it's a unicast data frame @@ -1603,17 +1623,14 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, * Send this frame as regular when ADDBA * exchange is neither complete nor pending. */ - ath_tx_send_normal(sc, txctl->txq, - tid, &bf_head); + ath_tx_send_ht_normal(sc, txctl->txq, + tid, &bf_head); } } else { - bf->bf_lastbf = bf; - bf->bf_nframes = 1; - - ath_buf_set_rate(sc, bf); - ath_tx_txqaddbuf(sc, txctl->txq, &bf_head); + ath_tx_send_normal(sc, txctl->txq, &bf_head); } +tx_done: spin_unlock_bh(&txctl->txq->axq_lock); } -- GitLab From 62b4fb66c5611c4e2b9279810c2d037fb5b5fa68 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 9 Mar 2009 09:32:01 +0530 Subject: [PATCH 3585/4982] ath9k: Fix bug in reading debugfs file 'rcstat' The rate table would not have been chosen before the interface has been brought up. Reading 'rcstat' in this case would result in an oops, fix this. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/debug.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/ath9k/debug.c b/drivers/net/wireless/ath9k/debug.c index b0ff4792546..82573cadb1a 100644 --- a/drivers/net/wireless/ath9k/debug.c +++ b/drivers/net/wireless/ath9k/debug.c @@ -322,6 +322,9 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, { struct ath_softc *sc = file->private_data; + if (sc->cur_rate_table == NULL) + return 0; + if (conf_is_ht(&sc->hw->conf)) return ath_read_file_stat_11n_rc(file, user_buf, count, ppos); else -- GitLab From 8830cb678b13004ab54f606345769f1e74e378c6 Mon Sep 17 00:00:00 2001 From: John Daiker Date: Sun, 8 Mar 2009 22:18:35 -0700 Subject: [PATCH 3586/4982] atmel: checkpatch.pl cleanups Before: 881 errors, 265 warnings, 4507 lines checked After: 114 errors, 273 warnings, 4548 lines checked This was mostly "space required after that ',' (ctx:VxV)". Also a fair number of whitespace, code indent, and C99 comment cleanups. New warnings introduced are all "line over 80 character" md5sums are identical, as I skipped any fixes which may have altered the resulting binary. Signed-off-by: John Daiker Signed-off-by: John W. Linville --- drivers/net/wireless/atmel.c | 443 +++++++++++++++++++---------------- 1 file changed, 242 insertions(+), 201 deletions(-) diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 91930a2c3c6..b06835a621a 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -2,8 +2,8 @@ Driver for Atmel at76c502 at76c504 and at76c506 wireless cards. - Copyright 2000-2001 ATMEL Corporation. - Copyright 2003-2004 Simon Kelley. + Copyright 2000-2001 ATMEL Corporation. + Copyright 2003-2004 Simon Kelley. This code was developed from version 2.1.1 of the Atmel drivers, released by Atmel corp. under the GPL in December 2002. It also @@ -89,15 +89,15 @@ static struct { const char *fw_file; const char *fw_file_ext; } fw_table[] = { - { ATMEL_FW_TYPE_502, "atmel_at76c502", "bin" }, - { ATMEL_FW_TYPE_502D, "atmel_at76c502d", "bin" }, - { ATMEL_FW_TYPE_502E, "atmel_at76c502e", "bin" }, - { ATMEL_FW_TYPE_502_3COM, "atmel_at76c502_3com", "bin" }, - { ATMEL_FW_TYPE_504, "atmel_at76c504", "bin" }, - { ATMEL_FW_TYPE_504_2958, "atmel_at76c504_2958", "bin" }, - { ATMEL_FW_TYPE_504A_2958,"atmel_at76c504a_2958","bin" }, - { ATMEL_FW_TYPE_506, "atmel_at76c506", "bin" }, - { ATMEL_FW_TYPE_NONE, NULL, NULL } + { ATMEL_FW_TYPE_502, "atmel_at76c502", "bin" }, + { ATMEL_FW_TYPE_502D, "atmel_at76c502d", "bin" }, + { ATMEL_FW_TYPE_502E, "atmel_at76c502e", "bin" }, + { ATMEL_FW_TYPE_502_3COM, "atmel_at76c502_3com", "bin" }, + { ATMEL_FW_TYPE_504, "atmel_at76c504", "bin" }, + { ATMEL_FW_TYPE_504_2958, "atmel_at76c504_2958", "bin" }, + { ATMEL_FW_TYPE_504A_2958, "atmel_at76c504a_2958", "bin" }, + { ATMEL_FW_TYPE_506, "atmel_at76c506", "bin" }, + { ATMEL_FW_TYPE_NONE, NULL, NULL } }; #define MAX_SSID_LENGTH 32 @@ -106,60 +106,60 @@ static struct { #define MAX_BSS_ENTRIES 64 /* registers */ -#define GCR 0x00 // (SIR0) General Configuration Register -#define BSR 0x02 // (SIR1) Bank Switching Select Register +#define GCR 0x00 /* (SIR0) General Configuration Register */ +#define BSR 0x02 /* (SIR1) Bank Switching Select Register */ #define AR 0x04 #define DR 0x08 -#define MR1 0x12 // Mirror Register 1 -#define MR2 0x14 // Mirror Register 2 -#define MR3 0x16 // Mirror Register 3 -#define MR4 0x18 // Mirror Register 4 +#define MR1 0x12 /* Mirror Register 1 */ +#define MR2 0x14 /* Mirror Register 2 */ +#define MR3 0x16 /* Mirror Register 3 */ +#define MR4 0x18 /* Mirror Register 4 */ #define GPR1 0x0c #define GPR2 0x0e #define GPR3 0x10 -// -// Constants for the GCR register. -// -#define GCR_REMAP 0x0400 // Remap internal SRAM to 0 -#define GCR_SWRES 0x0080 // BIU reset (ARM and PAI are NOT reset) -#define GCR_CORES 0x0060 // Core Reset (ARM and PAI are reset) -#define GCR_ENINT 0x0002 // Enable Interrupts -#define GCR_ACKINT 0x0008 // Acknowledge Interrupts - -#define BSS_SRAM 0x0200 // AMBA module selection --> SRAM -#define BSS_IRAM 0x0100 // AMBA module selection --> IRAM -// -// Constants for the MR registers. -// -#define MAC_INIT_COMPLETE 0x0001 // MAC init has been completed -#define MAC_BOOT_COMPLETE 0x0010 // MAC boot has been completed -#define MAC_INIT_OK 0x0002 // MAC boot has been completed +/* + * Constants for the GCR register. + */ +#define GCR_REMAP 0x0400 /* Remap internal SRAM to 0 */ +#define GCR_SWRES 0x0080 /* BIU reset (ARM and PAI are NOT reset) */ +#define GCR_CORES 0x0060 /* Core Reset (ARM and PAI are reset) */ +#define GCR_ENINT 0x0002 /* Enable Interrupts */ +#define GCR_ACKINT 0x0008 /* Acknowledge Interrupts */ + +#define BSS_SRAM 0x0200 /* AMBA module selection --> SRAM */ +#define BSS_IRAM 0x0100 /* AMBA module selection --> IRAM */ +/* + *Constants for the MR registers. + */ +#define MAC_INIT_COMPLETE 0x0001 /* MAC init has been completed */ +#define MAC_BOOT_COMPLETE 0x0010 /* MAC boot has been completed */ +#define MAC_INIT_OK 0x0002 /* MAC boot has been completed */ #define MIB_MAX_DATA_BYTES 212 #define MIB_HEADER_SIZE 4 /* first four fields */ struct get_set_mib { - u8 type; - u8 size; - u8 index; - u8 reserved; - u8 data[MIB_MAX_DATA_BYTES]; + u8 type; + u8 size; + u8 index; + u8 reserved; + u8 data[MIB_MAX_DATA_BYTES]; }; struct rx_desc { - u32 Next; - u16 MsduPos; - u16 MsduSize; - - u8 State; - u8 Status; - u8 Rate; - u8 Rssi; - u8 LinkQuality; - u8 PreambleType; - u16 Duration; - u32 RxTime; + u32 Next; + u16 MsduPos; + u16 MsduSize; + + u8 State; + u8 Status; + u8 Rate; + u8 Rssi; + u8 LinkQuality; + u8 PreambleType; + u16 Duration; + u32 RxTime; }; #define RX_DESC_FLAG_VALID 0x80 @@ -192,7 +192,7 @@ struct tx_desc { u8 KeyIndex; u8 ChiperType; u8 ChipreLength; - u8 Reserved1; + u8 Reserved1; u8 Reserved; u8 PacketType; @@ -212,9 +212,9 @@ struct tx_desc { #define TX_DESC_PACKET_TYPE_OFFSET 17 #define TX_DESC_HOST_LENGTH_OFFSET 18 -/////////////////////////////////////////////////////// -// Host-MAC interface -/////////////////////////////////////////////////////// +/* + * Host-MAC interface + */ #define TX_STATUS_SUCCESS 0x00 @@ -226,14 +226,14 @@ struct tx_desc { #define TX_PACKET_TYPE_DATA 0x01 #define TX_PACKET_TYPE_MGMT 0x02 -#define ISR_EMPTY 0x00 // no bits set in ISR -#define ISR_TxCOMPLETE 0x01 // packet transmitted -#define ISR_RxCOMPLETE 0x02 // packet received -#define ISR_RxFRAMELOST 0x04 // Rx Frame lost -#define ISR_FATAL_ERROR 0x08 // Fatal error -#define ISR_COMMAND_COMPLETE 0x10 // command completed -#define ISR_OUT_OF_RANGE 0x20 // command completed -#define ISR_IBSS_MERGE 0x40 // (4.1.2.30): IBSS merge +#define ISR_EMPTY 0x00 /* no bits set in ISR */ +#define ISR_TxCOMPLETE 0x01 /* packet transmitted */ +#define ISR_RxCOMPLETE 0x02 /* packet received */ +#define ISR_RxFRAMELOST 0x04 /* Rx Frame lost */ +#define ISR_FATAL_ERROR 0x08 /* Fatal error */ +#define ISR_COMMAND_COMPLETE 0x10 /* command completed */ +#define ISR_OUT_OF_RANGE 0x20 /* command completed */ +#define ISR_IBSS_MERGE 0x40 /* (4.1.2.30): IBSS merge */ #define ISR_GENERIC_IRQ 0x80 #define Local_Mib_Type 0x01 @@ -311,22 +311,22 @@ struct tx_desc { #define MAX_ENCRYPTION_KEYS 4 #define MAX_ENCRYPTION_KEY_SIZE 40 -/////////////////////////////////////////////////////////////////////////// -// 802.11 related definitions -/////////////////////////////////////////////////////////////////////////// +/* + * 802.11 related definitions + */ -// -// Regulatory Domains -// +/* + * Regulatory Domains + */ -#define REG_DOMAIN_FCC 0x10 //Channels 1-11 USA -#define REG_DOMAIN_DOC 0x20 //Channel 1-11 Canada -#define REG_DOMAIN_ETSI 0x30 //Channel 1-13 Europe (ex Spain/France) -#define REG_DOMAIN_SPAIN 0x31 //Channel 10-11 Spain -#define REG_DOMAIN_FRANCE 0x32 //Channel 10-13 France -#define REG_DOMAIN_MKK 0x40 //Channel 14 Japan -#define REG_DOMAIN_MKK1 0x41 //Channel 1-14 Japan(MKK1) -#define REG_DOMAIN_ISRAEL 0x50 //Channel 3-9 ISRAEL +#define REG_DOMAIN_FCC 0x10 /* Channels 1-11 USA */ +#define REG_DOMAIN_DOC 0x20 /* Channel 1-11 Canada */ +#define REG_DOMAIN_ETSI 0x30 /* Channel 1-13 Europe (ex Spain/France) */ +#define REG_DOMAIN_SPAIN 0x31 /* Channel 10-11 Spain */ +#define REG_DOMAIN_FRANCE 0x32 /* Channel 10-13 France */ +#define REG_DOMAIN_MKK 0x40 /* Channel 14 Japan */ +#define REG_DOMAIN_MKK1 0x41 /* Channel 1-14 Japan(MKK1) */ +#define REG_DOMAIN_ISRAEL 0x50 /* Channel 3-9 ISRAEL */ #define BSS_TYPE_AD_HOC 1 #define BSS_TYPE_INFRASTRUCTURE 2 @@ -364,13 +364,13 @@ struct tx_desc { #define CIPHER_SUITE_CCX 4 #define CIPHER_SUITE_WEP_128 5 -// -// IFACE MACROS & definitions -// -// +/* + * IFACE MACROS & definitions + */ -// FuncCtrl field: -// +/* + * FuncCtrl field: + */ #define FUNC_CTRL_TxENABLE 0x10 #define FUNC_CTRL_RxENABLE 0x20 #define FUNC_CTRL_INIT_COMPLETE 0x01 @@ -378,48 +378,48 @@ struct tx_desc { /* A stub firmware image which reads the MAC address from NVRAM on the card. For copyright information and source see the end of this file. */ static u8 mac_reader[] = { - 0x06,0x00,0x00,0xea,0x04,0x00,0x00,0xea,0x03,0x00,0x00,0xea,0x02,0x00,0x00,0xea, - 0x01,0x00,0x00,0xea,0x00,0x00,0x00,0xea,0xff,0xff,0xff,0xea,0xfe,0xff,0xff,0xea, - 0xd3,0x00,0xa0,0xe3,0x00,0xf0,0x21,0xe1,0x0e,0x04,0xa0,0xe3,0x00,0x10,0xa0,0xe3, - 0x81,0x11,0xa0,0xe1,0x00,0x10,0x81,0xe3,0x00,0x10,0x80,0xe5,0x1c,0x10,0x90,0xe5, - 0x10,0x10,0xc1,0xe3,0x1c,0x10,0x80,0xe5,0x01,0x10,0xa0,0xe3,0x08,0x10,0x80,0xe5, - 0x02,0x03,0xa0,0xe3,0x00,0x10,0xa0,0xe3,0xb0,0x10,0xc0,0xe1,0xb4,0x10,0xc0,0xe1, - 0xb8,0x10,0xc0,0xe1,0xbc,0x10,0xc0,0xe1,0x56,0xdc,0xa0,0xe3,0x21,0x00,0x00,0xeb, - 0x0a,0x00,0xa0,0xe3,0x1a,0x00,0x00,0xeb,0x10,0x00,0x00,0xeb,0x07,0x00,0x00,0xeb, - 0x02,0x03,0xa0,0xe3,0x02,0x14,0xa0,0xe3,0xb4,0x10,0xc0,0xe1,0x4c,0x10,0x9f,0xe5, - 0xbc,0x10,0xc0,0xe1,0x10,0x10,0xa0,0xe3,0xb8,0x10,0xc0,0xe1,0xfe,0xff,0xff,0xea, - 0x00,0x40,0x2d,0xe9,0x00,0x20,0xa0,0xe3,0x02,0x3c,0xa0,0xe3,0x00,0x10,0xa0,0xe3, - 0x28,0x00,0x9f,0xe5,0x37,0x00,0x00,0xeb,0x00,0x40,0xbd,0xe8,0x1e,0xff,0x2f,0xe1, - 0x00,0x40,0x2d,0xe9,0x12,0x2e,0xa0,0xe3,0x06,0x30,0xa0,0xe3,0x00,0x10,0xa0,0xe3, - 0x02,0x04,0xa0,0xe3,0x2f,0x00,0x00,0xeb,0x00,0x40,0xbd,0xe8,0x1e,0xff,0x2f,0xe1, - 0x00,0x02,0x00,0x02,0x80,0x01,0x90,0xe0,0x01,0x00,0x00,0x0a,0x01,0x00,0x50,0xe2, - 0xfc,0xff,0xff,0xea,0x1e,0xff,0x2f,0xe1,0x80,0x10,0xa0,0xe3,0xf3,0x06,0xa0,0xe3, - 0x00,0x10,0x80,0xe5,0x00,0x10,0xa0,0xe3,0x00,0x10,0x80,0xe5,0x01,0x10,0xa0,0xe3, - 0x04,0x10,0x80,0xe5,0x00,0x10,0x80,0xe5,0x0e,0x34,0xa0,0xe3,0x1c,0x10,0x93,0xe5, - 0x02,0x1a,0x81,0xe3,0x1c,0x10,0x83,0xe5,0x58,0x11,0x9f,0xe5,0x30,0x10,0x80,0xe5, - 0x54,0x11,0x9f,0xe5,0x34,0x10,0x80,0xe5,0x38,0x10,0x80,0xe5,0x3c,0x10,0x80,0xe5, - 0x10,0x10,0x90,0xe5,0x08,0x00,0x90,0xe5,0x1e,0xff,0x2f,0xe1,0xf3,0x16,0xa0,0xe3, - 0x08,0x00,0x91,0xe5,0x05,0x00,0xa0,0xe3,0x0c,0x00,0x81,0xe5,0x10,0x00,0x91,0xe5, - 0x02,0x00,0x10,0xe3,0xfc,0xff,0xff,0x0a,0xff,0x00,0xa0,0xe3,0x0c,0x00,0x81,0xe5, - 0x10,0x00,0x91,0xe5,0x02,0x00,0x10,0xe3,0xfc,0xff,0xff,0x0a,0x08,0x00,0x91,0xe5, - 0x10,0x00,0x91,0xe5,0x01,0x00,0x10,0xe3,0xfc,0xff,0xff,0x0a,0x08,0x00,0x91,0xe5, - 0xff,0x00,0x00,0xe2,0x1e,0xff,0x2f,0xe1,0x30,0x40,0x2d,0xe9,0x00,0x50,0xa0,0xe1, - 0x03,0x40,0xa0,0xe1,0xa2,0x02,0xa0,0xe1,0x08,0x00,0x00,0xe2,0x03,0x00,0x80,0xe2, - 0xd8,0x10,0x9f,0xe5,0x00,0x00,0xc1,0xe5,0x01,0x20,0xc1,0xe5,0xe2,0xff,0xff,0xeb, - 0x01,0x00,0x10,0xe3,0xfc,0xff,0xff,0x1a,0x14,0x00,0xa0,0xe3,0xc4,0xff,0xff,0xeb, - 0x04,0x20,0xa0,0xe1,0x05,0x10,0xa0,0xe1,0x02,0x00,0xa0,0xe3,0x01,0x00,0x00,0xeb, - 0x30,0x40,0xbd,0xe8,0x1e,0xff,0x2f,0xe1,0x70,0x40,0x2d,0xe9,0xf3,0x46,0xa0,0xe3, - 0x00,0x30,0xa0,0xe3,0x00,0x00,0x50,0xe3,0x08,0x00,0x00,0x9a,0x8c,0x50,0x9f,0xe5, - 0x03,0x60,0xd5,0xe7,0x0c,0x60,0x84,0xe5,0x10,0x60,0x94,0xe5,0x02,0x00,0x16,0xe3, - 0xfc,0xff,0xff,0x0a,0x01,0x30,0x83,0xe2,0x00,0x00,0x53,0xe1,0xf7,0xff,0xff,0x3a, - 0xff,0x30,0xa0,0xe3,0x0c,0x30,0x84,0xe5,0x08,0x00,0x94,0xe5,0x10,0x00,0x94,0xe5, - 0x01,0x00,0x10,0xe3,0xfc,0xff,0xff,0x0a,0x08,0x00,0x94,0xe5,0x00,0x00,0xa0,0xe3, - 0x00,0x00,0x52,0xe3,0x0b,0x00,0x00,0x9a,0x10,0x50,0x94,0xe5,0x02,0x00,0x15,0xe3, - 0xfc,0xff,0xff,0x0a,0x0c,0x30,0x84,0xe5,0x10,0x50,0x94,0xe5,0x01,0x00,0x15,0xe3, - 0xfc,0xff,0xff,0x0a,0x08,0x50,0x94,0xe5,0x01,0x50,0xc1,0xe4,0x01,0x00,0x80,0xe2, - 0x02,0x00,0x50,0xe1,0xf3,0xff,0xff,0x3a,0xc8,0x00,0xa0,0xe3,0x98,0xff,0xff,0xeb, - 0x70,0x40,0xbd,0xe8,0x1e,0xff,0x2f,0xe1,0x01,0x0c,0x00,0x02,0x01,0x02,0x00,0x02, - 0x00,0x01,0x00,0x02 + 0x06, 0x00, 0x00, 0xea, 0x04, 0x00, 0x00, 0xea, 0x03, 0x00, 0x00, 0xea, 0x02, 0x00, 0x00, 0xea, + 0x01, 0x00, 0x00, 0xea, 0x00, 0x00, 0x00, 0xea, 0xff, 0xff, 0xff, 0xea, 0xfe, 0xff, 0xff, 0xea, + 0xd3, 0x00, 0xa0, 0xe3, 0x00, 0xf0, 0x21, 0xe1, 0x0e, 0x04, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3, + 0x81, 0x11, 0xa0, 0xe1, 0x00, 0x10, 0x81, 0xe3, 0x00, 0x10, 0x80, 0xe5, 0x1c, 0x10, 0x90, 0xe5, + 0x10, 0x10, 0xc1, 0xe3, 0x1c, 0x10, 0x80, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 0x08, 0x10, 0x80, 0xe5, + 0x02, 0x03, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3, 0xb0, 0x10, 0xc0, 0xe1, 0xb4, 0x10, 0xc0, 0xe1, + 0xb8, 0x10, 0xc0, 0xe1, 0xbc, 0x10, 0xc0, 0xe1, 0x56, 0xdc, 0xa0, 0xe3, 0x21, 0x00, 0x00, 0xeb, + 0x0a, 0x00, 0xa0, 0xe3, 0x1a, 0x00, 0x00, 0xeb, 0x10, 0x00, 0x00, 0xeb, 0x07, 0x00, 0x00, 0xeb, + 0x02, 0x03, 0xa0, 0xe3, 0x02, 0x14, 0xa0, 0xe3, 0xb4, 0x10, 0xc0, 0xe1, 0x4c, 0x10, 0x9f, 0xe5, + 0xbc, 0x10, 0xc0, 0xe1, 0x10, 0x10, 0xa0, 0xe3, 0xb8, 0x10, 0xc0, 0xe1, 0xfe, 0xff, 0xff, 0xea, + 0x00, 0x40, 0x2d, 0xe9, 0x00, 0x20, 0xa0, 0xe3, 0x02, 0x3c, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3, + 0x28, 0x00, 0x9f, 0xe5, 0x37, 0x00, 0x00, 0xeb, 0x00, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, + 0x00, 0x40, 0x2d, 0xe9, 0x12, 0x2e, 0xa0, 0xe3, 0x06, 0x30, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3, + 0x02, 0x04, 0xa0, 0xe3, 0x2f, 0x00, 0x00, 0xeb, 0x00, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, + 0x00, 0x02, 0x00, 0x02, 0x80, 0x01, 0x90, 0xe0, 0x01, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x50, 0xe2, + 0xfc, 0xff, 0xff, 0xea, 0x1e, 0xff, 0x2f, 0xe1, 0x80, 0x10, 0xa0, 0xe3, 0xf3, 0x06, 0xa0, 0xe3, + 0x00, 0x10, 0x80, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x80, 0xe5, 0x01, 0x10, 0xa0, 0xe3, + 0x04, 0x10, 0x80, 0xe5, 0x00, 0x10, 0x80, 0xe5, 0x0e, 0x34, 0xa0, 0xe3, 0x1c, 0x10, 0x93, 0xe5, + 0x02, 0x1a, 0x81, 0xe3, 0x1c, 0x10, 0x83, 0xe5, 0x58, 0x11, 0x9f, 0xe5, 0x30, 0x10, 0x80, 0xe5, + 0x54, 0x11, 0x9f, 0xe5, 0x34, 0x10, 0x80, 0xe5, 0x38, 0x10, 0x80, 0xe5, 0x3c, 0x10, 0x80, 0xe5, + 0x10, 0x10, 0x90, 0xe5, 0x08, 0x00, 0x90, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 0xf3, 0x16, 0xa0, 0xe3, + 0x08, 0x00, 0x91, 0xe5, 0x05, 0x00, 0xa0, 0xe3, 0x0c, 0x00, 0x81, 0xe5, 0x10, 0x00, 0x91, 0xe5, + 0x02, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x0a, 0xff, 0x00, 0xa0, 0xe3, 0x0c, 0x00, 0x81, 0xe5, + 0x10, 0x00, 0x91, 0xe5, 0x02, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x0a, 0x08, 0x00, 0x91, 0xe5, + 0x10, 0x00, 0x91, 0xe5, 0x01, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x0a, 0x08, 0x00, 0x91, 0xe5, + 0xff, 0x00, 0x00, 0xe2, 0x1e, 0xff, 0x2f, 0xe1, 0x30, 0x40, 0x2d, 0xe9, 0x00, 0x50, 0xa0, 0xe1, + 0x03, 0x40, 0xa0, 0xe1, 0xa2, 0x02, 0xa0, 0xe1, 0x08, 0x00, 0x00, 0xe2, 0x03, 0x00, 0x80, 0xe2, + 0xd8, 0x10, 0x9f, 0xe5, 0x00, 0x00, 0xc1, 0xe5, 0x01, 0x20, 0xc1, 0xe5, 0xe2, 0xff, 0xff, 0xeb, + 0x01, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x1a, 0x14, 0x00, 0xa0, 0xe3, 0xc4, 0xff, 0xff, 0xeb, + 0x04, 0x20, 0xa0, 0xe1, 0x05, 0x10, 0xa0, 0xe1, 0x02, 0x00, 0xa0, 0xe3, 0x01, 0x00, 0x00, 0xeb, + 0x30, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, 0x70, 0x40, 0x2d, 0xe9, 0xf3, 0x46, 0xa0, 0xe3, + 0x00, 0x30, 0xa0, 0xe3, 0x00, 0x00, 0x50, 0xe3, 0x08, 0x00, 0x00, 0x9a, 0x8c, 0x50, 0x9f, 0xe5, + 0x03, 0x60, 0xd5, 0xe7, 0x0c, 0x60, 0x84, 0xe5, 0x10, 0x60, 0x94, 0xe5, 0x02, 0x00, 0x16, 0xe3, + 0xfc, 0xff, 0xff, 0x0a, 0x01, 0x30, 0x83, 0xe2, 0x00, 0x00, 0x53, 0xe1, 0xf7, 0xff, 0xff, 0x3a, + 0xff, 0x30, 0xa0, 0xe3, 0x0c, 0x30, 0x84, 0xe5, 0x08, 0x00, 0x94, 0xe5, 0x10, 0x00, 0x94, 0xe5, + 0x01, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x0a, 0x08, 0x00, 0x94, 0xe5, 0x00, 0x00, 0xa0, 0xe3, + 0x00, 0x00, 0x52, 0xe3, 0x0b, 0x00, 0x00, 0x9a, 0x10, 0x50, 0x94, 0xe5, 0x02, 0x00, 0x15, 0xe3, + 0xfc, 0xff, 0xff, 0x0a, 0x0c, 0x30, 0x84, 0xe5, 0x10, 0x50, 0x94, 0xe5, 0x01, 0x00, 0x15, 0xe3, + 0xfc, 0xff, 0xff, 0x0a, 0x08, 0x50, 0x94, 0xe5, 0x01, 0x50, 0xc1, 0xe4, 0x01, 0x00, 0x80, 0xe2, + 0x02, 0x00, 0x50, 0xe1, 0xf3, 0xff, 0xff, 0x3a, 0xc8, 0x00, 0xa0, 0xe3, 0x98, 0xff, 0xff, 0xeb, + 0x70, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, 0x01, 0x0c, 0x00, 0x02, 0x01, 0x02, 0x00, 0x02, + 0x00, 0x01, 0x00, 0x02 }; struct atmel_private { @@ -433,7 +433,7 @@ struct atmel_private { struct net_device *dev; struct device *sys_dev; struct iw_statistics wstats; - spinlock_t irqlock, timerlock; // spinlocks + spinlock_t irqlock, timerlock; /* spinlocks */ enum { BUS_TYPE_PCCARD, BUS_TYPE_PCI } bus_type; enum { CARD_TYPE_PARALLEL_FLASH, @@ -541,7 +541,7 @@ struct atmel_private { u8 rx_buf[MAX_WIRELESS_BODY]; }; -static u8 atmel_basic_rates[4] = {0x82,0x84,0x0b,0x16}; +static u8 atmel_basic_rates[4] = {0x82, 0x84, 0x0b, 0x16}; static const struct { int reg_domain; @@ -1283,17 +1283,17 @@ static struct iw_statistics *atmel_get_wireless_stats(struct net_device *dev) static int atmel_change_mtu(struct net_device *dev, int new_mtu) { - if ((new_mtu < 68) || (new_mtu > 2312)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; + if ((new_mtu < 68) || (new_mtu > 2312)) + return -EINVAL; + dev->mtu = new_mtu; + return 0; } static int atmel_set_mac_address(struct net_device *dev, void *p) { struct sockaddr *addr = p; - memcpy (dev->dev_addr, addr->sa_data, dev->addr_len); + memcpy (dev->dev_addr, addr->sa_data, dev->addr_len); return atmel_open(dev); } @@ -1420,10 +1420,17 @@ static int atmel_proc_output (char *buf, struct atmel_private *priv) priv->firmware_id); switch (priv->card_type) { - case CARD_TYPE_PARALLEL_FLASH: c = "Parallel flash"; break; - case CARD_TYPE_SPI_FLASH: c = "SPI flash\n"; break; - case CARD_TYPE_EEPROM: c = "EEPROM"; break; - default: c = ""; + case CARD_TYPE_PARALLEL_FLASH: + c = "Parallel flash"; + break; + case CARD_TYPE_SPI_FLASH: + c = "SPI flash\n"; + break; + case CARD_TYPE_EEPROM: + c = "EEPROM"; + break; + default: + c = ""; } r = ""; @@ -1439,16 +1446,33 @@ static int atmel_proc_output (char *buf, struct atmel_private *priv) priv->use_wpa ? "Yes" : "No"); } - switch(priv->station_state) { - case STATION_STATE_SCANNING: s = "Scanning"; break; - case STATION_STATE_JOINNING: s = "Joining"; break; - case STATION_STATE_AUTHENTICATING: s = "Authenticating"; break; - case STATION_STATE_ASSOCIATING: s = "Associating"; break; - case STATION_STATE_READY: s = "Ready"; break; - case STATION_STATE_REASSOCIATING: s = "Reassociating"; break; - case STATION_STATE_MGMT_ERROR: s = "Management error"; break; - case STATION_STATE_DOWN: s = "Down"; break; - default: s = ""; + switch (priv->station_state) { + case STATION_STATE_SCANNING: + s = "Scanning"; + break; + case STATION_STATE_JOINNING: + s = "Joining"; + break; + case STATION_STATE_AUTHENTICATING: + s = "Authenticating"; + break; + case STATION_STATE_ASSOCIATING: + s = "Associating"; + break; + case STATION_STATE_READY: + s = "Ready"; + break; + case STATION_STATE_REASSOCIATING: + s = "Reassociating"; + break; + case STATION_STATE_MGMT_ERROR: + s = "Management error"; + break; + case STATION_STATE_DOWN: + s = "Down"; + break; + default: + s = ""; } p += sprintf(p, "Current state:\t\t%s\n", s); @@ -1458,14 +1482,17 @@ static int atmel_proc_output (char *buf, struct atmel_private *priv) static int atmel_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { - struct atmel_private *priv = data; + struct atmel_private *priv = data; int len = atmel_proc_output (page, priv); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; + if (len <= off+count) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + return len; } struct net_device *init_atmel_card(unsigned short irq, unsigned long port, @@ -1479,11 +1506,11 @@ struct net_device *init_atmel_card(unsigned short irq, unsigned long port, int rc; /* Create the network device object. */ - dev = alloc_etherdev(sizeof(*priv)); - if (!dev) { + dev = alloc_etherdev(sizeof(*priv)); + if (!dev) { printk(KERN_ERR "atmel: Couldn't alloc_etherdev\n"); return NULL; - } + } if (dev_alloc_name(dev, dev->name) < 0) { printk(KERN_ERR "atmel: Couldn't get name!\n"); goto err_out_free; @@ -1577,7 +1604,7 @@ struct net_device *init_atmel_card(unsigned short irq, unsigned long port, if (register_netdev(dev)) goto err_out_res; - if (!probe_atmel_card(dev)){ + if (!probe_atmel_card(dev)) { unregister_netdev(dev); goto err_out_res; } @@ -1594,7 +1621,7 @@ struct net_device *init_atmel_card(unsigned short irq, unsigned long port, return dev; err_out_res: - release_region( dev->base_addr, 32); + release_region(dev->base_addr, 32); err_out_irq: free_irq(dev->irq, dev); err_out_free: @@ -1632,7 +1659,7 @@ static int atmel_set_essid(struct net_device *dev, struct atmel_private *priv = netdev_priv(dev); /* Check if we asked for `any' */ - if(dwrq->flags == 0) { + if (dwrq->flags == 0) { priv->connect_to_any_BSS = 1; } else { int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; @@ -1768,7 +1795,7 @@ static int atmel_set_encode(struct net_device *dev, } if (dwrq->flags & IW_ENCODE_RESTRICTED) priv->exclude_unencrypted = 1; - if(dwrq->flags & IW_ENCODE_OPEN) + if (dwrq->flags & IW_ENCODE_OPEN) priv->exclude_unencrypted = 0; return -EINPROGRESS; /* Call commit handler */ @@ -1797,7 +1824,7 @@ static int atmel_get_encode(struct net_device *dev, /* Copy the key to the user buffer */ dwrq->length = priv->wep_key_len[index]; if (dwrq->length > 16) { - dwrq->length=0; + dwrq->length = 0; } else { memset(extra, 0, 16); memcpy(extra, priv->wep_keys[index], dwrq->length); @@ -2013,11 +2040,20 @@ static int atmel_set_rate(struct net_device *dev, } else { /* Setting by frequency value */ switch (vwrq->value) { - case 1000000: priv->tx_rate = 0; break; - case 2000000: priv->tx_rate = 1; break; - case 5500000: priv->tx_rate = 2; break; - case 11000000: priv->tx_rate = 3; break; - default: return -EINVAL; + case 1000000: + priv->tx_rate = 0; + break; + case 2000000: + priv->tx_rate = 1; + break; + case 5500000: + priv->tx_rate = 2; + break; + case 11000000: + priv->tx_rate = 3; + break; + default: + return -EINVAL; } } } @@ -2062,11 +2098,19 @@ static int atmel_get_rate(struct net_device *dev, vwrq->value = 11000000; } else { vwrq->fixed = 1; - switch(priv->tx_rate) { - case 0: vwrq->value = 1000000; break; - case 1: vwrq->value = 2000000; break; - case 2: vwrq->value = 5500000; break; - case 3: vwrq->value = 11000000; break; + switch (priv->tx_rate) { + case 0: + vwrq->value = 1000000; + break; + case 1: + vwrq->value = 2000000; + break; + case 2: + vwrq->value = 5500000; + break; + case 3: + vwrq->value = 11000000; + break; } } return 0; @@ -2576,8 +2620,7 @@ static const struct iw_priv_args atmel_private_args[] = { }, }; -static const struct iw_handler_def atmel_handler_def = -{ +static const struct iw_handler_def atmel_handler_def = { .num_standard = ARRAY_SIZE(atmel_handler), .num_private = ARRAY_SIZE(atmel_private_handler), .num_private_args = ARRAY_SIZE(atmel_private_args), @@ -2834,7 +2877,7 @@ static void send_authentication_request(struct atmel_private *priv, u16 system, if (priv->wep_is_on && priv->CurrentAuthentTransactionSeqNum != 1) /* no WEP for authentication frames with TrSeqNo 1 */ - header.frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); + header.frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); auth.alg = cpu_to_le16(system); @@ -2969,7 +3012,7 @@ static void store_bss_info(struct atmel_private *priv, if (memcmp(bss, priv->BSSinfo[i].BSSID, 6) == 0) index = i; - /* If we process a probe and an entry from this BSS exists + /* If we process a probe and an entry from this BSS exists we will update the BSS entry with the info from this BSS. If we process a beacon we will only update RSSI */ @@ -2995,7 +3038,7 @@ static void store_bss_info(struct atmel_private *priv, if (capability & WLAN_CAPABILITY_IBSS) priv->BSSinfo[index].BSStype = IW_MODE_ADHOC; else if (capability & WLAN_CAPABILITY_ESS) - priv->BSSinfo[index].BSStype =IW_MODE_INFRA; + priv->BSSinfo[index].BSStype = IW_MODE_INFRA; priv->BSSinfo[index].preamble = capability & WLAN_CAPABILITY_SHORT_PREAMBLE ? SHORT_PREAMBLE : LONG_PREAMBLE; @@ -3042,7 +3085,7 @@ static void authenticate(struct atmel_private *priv, u16 frame_len) } if (should_associate) { - if(priv->station_was_associated) { + if (priv->station_was_associated) { atmel_enter_state(priv, STATION_STATE_REASSOCIATING); send_association_request(priv, 1); return; @@ -3063,8 +3106,8 @@ static void authenticate(struct atmel_private *priv, u16 frame_len) priv->exclude_unencrypted = 1; send_authentication_request(priv, WLAN_AUTH_SHARED_KEY, NULL, 0); return; - } else if ( system == WLAN_AUTH_SHARED_KEY - && priv->wep_is_on) { + } else if (system == WLAN_AUTH_SHARED_KEY + && priv->wep_is_on) { priv->CurrentAuthentTransactionSeqNum = 0x001; priv->exclude_unencrypted = 0; send_authentication_request(priv, WLAN_AUTH_OPEN, NULL, 0); @@ -3252,11 +3295,11 @@ static void smooth_rssi(struct atmel_private *priv, u8 rssi) u8 max_rssi = 42; /* 502-rmfd-revd max by experiment, default for now */ switch (priv->firmware_type) { - case ATMEL_FW_TYPE_502E: - max_rssi = 63; /* 502-rmfd-reve max by experiment */ - break; - default: - break; + case ATMEL_FW_TYPE_502E: + max_rssi = 63; /* 502-rmfd-reve max by experiment */ + break; + default: + break; } rssi = rssi * 100 / max_rssi; @@ -3473,8 +3516,7 @@ static void atmel_command_irq(struct atmel_private *priv) status == CMD_STATUS_IN_PROGRESS) return; - switch (command){ - + switch (command) { case CMD_Start: if (status == CMD_STATUS_COMPLETE) { priv->station_was_associated = priv->station_is_associated; @@ -3709,7 +3751,7 @@ static int probe_atmel_card(struct net_device *dev) if (rc) { if (dev->dev_addr[0] == 0xFF) { - u8 default_mac[] = {0x00,0x04, 0x25, 0x00, 0x00, 0x00}; + u8 default_mac[] = {0x00, 0x04, 0x25, 0x00, 0x00, 0x00}; printk(KERN_ALERT "%s: *** Invalid MAC address. UPGRADE Firmware ****\n", dev->name); memcpy(dev->dev_addr, default_mac, 6); } @@ -3803,7 +3845,7 @@ static void build_wpa_mib(struct atmel_private *priv) } else { mib.group_key = i; priv->group_cipher_suite = priv->pairwise_cipher_suite; - mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-1] = 1; + mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-1] = 1; mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-2] = priv->group_cipher_suite; } } @@ -3913,7 +3955,7 @@ static int reset_atmel_card(struct net_device *dev) len = fw_entry->size; } - if (len <= 0x6000) { + if (len <= 0x6000) { atmel_write16(priv->dev, BSR, BSS_IRAM); atmel_copy_to_card(priv->dev, 0, fw, len); atmel_set_gcr(priv->dev, GCR_REMAP); @@ -3942,7 +3984,7 @@ static int reset_atmel_card(struct net_device *dev) priv->use_wpa = (priv->host_info.major_version == 4); priv->radio_on_broken = (priv->host_info.major_version == 5); - /* unmask all irq sources */ + /* unmask all irq sources */ atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_MASK_OFFSET), 0xff); /* int Tx system and enable Tx */ @@ -3975,7 +4017,7 @@ static int reset_atmel_card(struct net_device *dev) CMD_STATUS_REJECTED_RADIO_OFF) { printk(KERN_INFO "%s: cannot turn the radio on.\n", dev->name); - return -EIO; + return -EIO; } } @@ -3999,8 +4041,7 @@ static int reset_atmel_card(struct net_device *dev) else build_wep_mib(priv); - if (old_state == STATION_STATE_READY) - { + if (old_state == STATION_STATE_READY) { union iwreq_data wrqu; wrqu.data.length = 0; @@ -4277,24 +4318,24 @@ static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data) .set NVRAM_LENGTH, 0x0200 .set MAC_ADDRESS_MIB, SRAM_BASE .set MAC_ADDRESS_LENGTH, 6 - .set MAC_BOOT_FLAG, 0x10 + .set MAC_BOOT_FLAG, 0x10 .set MR1, 0 .set MR2, 4 .set MR3, 8 .set MR4, 0xC RESET_VECTOR: - b RESET_HANDLER + b RESET_HANDLER UNDEF_VECTOR: - b HALT1 + b HALT1 SWI_VECTOR: - b HALT1 + b HALT1 IABORT_VECTOR: - b HALT1 + b HALT1 DABORT_VECTOR: RESERVED_VECTOR: - b HALT1 + b HALT1 IRQ_VECTOR: - b HALT1 + b HALT1 FIQ_VECTOR: b HALT1 HALT1: b HALT1 @@ -4306,7 +4347,7 @@ RESET_HANDLER: ldr r0, =SPI_CGEN_BASE mov r1, #0 mov r1, r1, lsl #3 - orr r1,r1, #0 + orr r1, r1, #0 str r1, [r0] ldr r1, [r0, #28] bic r1, r1, #16 -- GitLab From af88b9078d4aa31d667d2d82601ede9cae3bac37 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Mon, 9 Mar 2009 15:47:08 +0100 Subject: [PATCH 3587/4982] mac80211: handle failed scan requests in STA mode If cfg80211 requests a scan it awaits either a return code != 0 from the scan function or the cfg80211_scan_done to be called. In case of a STA mac80211's scan function ever returns 0 and queues the scan request. If ieee80211_sta_work is executed and ieee80211_start_scan fails for some reason cfg80211_scan_done will never be called but cfg80211 still thinks the scan was triggered successfully and will refuse any future scan requests due to drv->scan_req not being cleaned up. If a scan is triggered from within the MLME a similar problem appears. If ieee80211_start_scan returns an error, local->scan_req will not be reset and mac80211 will refuse any future scan requests. Hence, in both cases call ieee80211_scan_failed (which notifies cfg80211 and resets local->scan_req) if ieee80211_start_scan returns an error. Signed-off-by: Helmut Schaa Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 1 + net/mac80211/mlme.c | 14 ++++++++++++-- net/mac80211/scan.c | 12 ++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ecbc8e0cb3e..fbb91f1aebb 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -972,6 +972,7 @@ int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len); void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); +void ieee80211_scan_failed(struct ieee80211_local *local); int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, struct cfg80211_scan_request *req); struct ieee80211_bss * diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index eeb6da8505c..841b8450b3d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1720,7 +1720,10 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata) local->int_scan_req.ssids[0].ssid_len = 0; else local->int_scan_req.ssids[0].ssid_len = ifmgd->ssid_len; - ieee80211_start_scan(sdata, &local->int_scan_req); + + if (ieee80211_start_scan(sdata, &local->int_scan_req)) + ieee80211_scan_failed(local); + ifmgd->state = IEEE80211_STA_MLME_AUTHENTICATE; set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request); } else { @@ -1757,7 +1760,14 @@ static void ieee80211_sta_work(struct work_struct *work) ifmgd->state != IEEE80211_STA_MLME_AUTHENTICATE && ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE && test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request)) { - ieee80211_start_scan(sdata, local->scan_req); + /* + * The call to ieee80211_start_scan can fail but ieee80211_request_scan + * (which queued ieee80211_sta_work) did not return an error. Thus, call + * ieee80211_scan_failed here if ieee80211_start_scan fails in order to + * notify the scan requester. + */ + if (ieee80211_start_scan(sdata, local->scan_req)) + ieee80211_scan_failed(local); return; } diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 0e81e1633a6..5030a3c8750 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -202,6 +202,18 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, return RX_QUEUED; } +void ieee80211_scan_failed(struct ieee80211_local *local) +{ + if (WARN_ON(!local->scan_req)) + return; + + /* notify cfg80211 about the failed scan */ + if (local->scan_req != &local->int_scan_req) + cfg80211_scan_done(local->scan_req, true); + + local->scan_req = NULL; +} + void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) { struct ieee80211_local *local = hw_to_local(hw); -- GitLab From 1a28c78b46caec7628985728e7f0c4aef68e33e7 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Tue, 10 Mar 2009 10:11:09 -0300 Subject: [PATCH 3588/4982] mac80211: deauth before flushing STA information Even after commit "mac80211: deauth when interface is marked down" (e327b847 on Linus tree), userspace still isn't notified when interface goes down. There isn't a problem with this commit, but because of other code changes it doesn't work on kernels >= 2.6.28 (works if same/similar change applied on 2.6.27 for example). The issue is as follows: after commit "mac80211: restructure disassoc/deauth flows" in 2.6.28, the call to ieee80211_sta_deauthenticate added by commit e327b847 will not work: because we do sta_info_flush(local, sdata) inside ieee80211_stop (iface.c), all stations in interface are cleared, so when calling ieee80211_sta_deauthenticate->ieee80211_set_disassoc (mlme.c), inside ieee80211_set_disassoc we have this in the beginning: sta = sta_info_get(local, ifsta->bssid); if (!sta) { The !sta check triggers, thus the function returns early and ieee80211_sta_send_apinfo(sdata, ifsta) later isn't called, so wpa_supplicant/userspace isn't notified with SIOCGIWAP. This commit moves deauthentication to before flushing STA info (sta_info_flush), thus the above can't happen and userspace is really notified when interface goes down. Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: John W. Linville --- net/mac80211/iface.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 2acc416e77e..f9f27b9cadb 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -369,6 +369,18 @@ static int ieee80211_stop(struct net_device *dev) rcu_read_unlock(); + /* + * Announce that we are leaving the network, in case we are a + * station interface type. This must be done before removing + * all stations associated with sta_info_flush, otherwise STA + * information will be gone and no announce being done. + */ + if (sdata->vif.type == NL80211_IFTYPE_STATION) { + if (sdata->u.mgd.state != IEEE80211_STA_MLME_DISABLED) + ieee80211_sta_deauthenticate(sdata, + WLAN_REASON_DEAUTH_LEAVING); + } + /* * Remove all stations associated with this interface. * @@ -454,10 +466,6 @@ static int ieee80211_stop(struct net_device *dev) netif_addr_unlock_bh(local->mdev); break; case NL80211_IFTYPE_STATION: - /* Announce that we are leaving the network. */ - if (sdata->u.mgd.state != IEEE80211_STA_MLME_DISABLED) - ieee80211_sta_deauthenticate(sdata, - WLAN_REASON_DEAUTH_LEAVING); memset(sdata->u.mgd.bssid, 0, ETH_ALEN); del_timer_sync(&sdata->u.mgd.chswitch_timer); del_timer_sync(&sdata->u.mgd.timer); -- GitLab From 0fee54cab7d5ebc58fad8c6a0703c4ea016405e3 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 9 Mar 2009 22:07:40 -0400 Subject: [PATCH 3589/4982] cfg80211: remove REGDOM_SET_BY_INIT This is not used as we can always just assume the first regulatory domain set will _always_ be a static regulatory domain. REGDOM_SET_BY_CORE will be the first request from cfg80211 for a regdomain and that then populates the first regulatory request. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 2 +- drivers/net/wireless/ath9k/regd.c | 1 - include/net/cfg80211.h | 3 --- net/wireless/reg.c | 2 -- 4 files changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 5268697be79..1d6b05c0d80 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1670,7 +1670,7 @@ int ath_attach(u16 devid, struct ath_softc *sc) } wiphy_apply_custom_regulatory(hw->wiphy, regd); ath9k_reg_apply_radar_flags(hw->wiphy); - ath9k_reg_apply_world_flags(hw->wiphy, REGDOM_SET_BY_INIT); + ath9k_reg_apply_world_flags(hw->wiphy, REGDOM_SET_BY_DRIVER); INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); diff --git a/drivers/net/wireless/ath9k/regd.c b/drivers/net/wireless/ath9k/regd.c index 639da975bf5..ff0afc02f3c 100644 --- a/drivers/net/wireless/ath9k/regd.c +++ b/drivers/net/wireless/ath9k/regd.c @@ -341,7 +341,6 @@ int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) switch (request->initiator) { case REGDOM_SET_BY_DRIVER: - case REGDOM_SET_BY_INIT: case REGDOM_SET_BY_CORE: case REGDOM_SET_BY_USER: break; diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 75fa556728c..f195ea46081 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -350,8 +350,6 @@ struct bss_parameters { /** * enum reg_set_by - Indicates who is trying to set the regulatory domain - * @REGDOM_SET_BY_INIT: regulatory domain was set by initialization. We will be - * using a static world regulatory domain by default. * @REGDOM_SET_BY_CORE: Core queried CRDA for a dynamic world regulatory domain. * @REGDOM_SET_BY_USER: User asked the wireless core to set the * regulatory domain. @@ -362,7 +360,6 @@ struct bss_parameters { * should consider. */ enum reg_set_by { - REGDOM_SET_BY_INIT, REGDOM_SET_BY_CORE, REGDOM_SET_BY_USER, REGDOM_SET_BY_DRIVER, diff --git a/net/wireless/reg.c b/net/wireless/reg.c index fa738be897a..47ff44751b7 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1255,8 +1255,6 @@ static int ignore_request(struct wiphy *wiphy, return 0; switch (pending_request->initiator) { - case REGDOM_SET_BY_INIT: - return -EINVAL; case REGDOM_SET_BY_CORE: return -EINVAL; case REGDOM_SET_BY_COUNTRY_IE: -- GitLab From 7db90f4a25bd4184f3d36dfa4f512f53b0448da7 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 9 Mar 2009 22:07:41 -0400 Subject: [PATCH 3590/4982] cfg80211: move enum reg_set_by to nl80211.h We do this so we can later inform userspace who set the regulatory domain and provide details of the request. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 2 +- drivers/net/wireless/ath9k/regd.c | 31 ++++++------ drivers/net/wireless/ath9k/regd.h | 3 +- include/linux/nl80211.h | 19 +++++++ include/net/cfg80211.h | 24 ++------- net/wireless/core.c | 2 +- net/wireless/core.h | 3 +- net/wireless/reg.c | 82 +++++++++++++++++-------------- 8 files changed, 90 insertions(+), 76 deletions(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 1d6b05c0d80..e9b3f365f09 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1670,7 +1670,7 @@ int ath_attach(u16 devid, struct ath_softc *sc) } wiphy_apply_custom_regulatory(hw->wiphy, regd); ath9k_reg_apply_radar_flags(hw->wiphy); - ath9k_reg_apply_world_flags(hw->wiphy, REGDOM_SET_BY_DRIVER); + ath9k_reg_apply_world_flags(hw->wiphy, NL80211_REGDOM_SET_BY_DRIVER); INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); diff --git a/drivers/net/wireless/ath9k/regd.c b/drivers/net/wireless/ath9k/regd.c index ff0afc02f3c..b8f9b6d6bec 100644 --- a/drivers/net/wireless/ath9k/regd.c +++ b/drivers/net/wireless/ath9k/regd.c @@ -168,8 +168,9 @@ static bool ath9k_is_radar_freq(u16 center_freq) * received a beacon on a channel we can enable active scan and * adhoc (or beaconing). */ -static void ath9k_reg_apply_beaconing_flags(struct wiphy *wiphy, - enum reg_set_by setby) +static void ath9k_reg_apply_beaconing_flags( + struct wiphy *wiphy, + enum nl80211_reg_initiator initiator) { enum ieee80211_band band; struct ieee80211_supported_band *sband; @@ -194,7 +195,7 @@ static void ath9k_reg_apply_beaconing_flags(struct wiphy *wiphy, (ch->flags & IEEE80211_CHAN_RADAR)) continue; - if (setby == REGDOM_SET_BY_COUNTRY_IE) { + if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, ®_rule); if (r) @@ -226,8 +227,9 @@ static void ath9k_reg_apply_beaconing_flags(struct wiphy *wiphy, } /* Allows active scan scan on Ch 12 and 13 */ -static void ath9k_reg_apply_active_scan_flags(struct wiphy *wiphy, - enum reg_set_by setby) +static void ath9k_reg_apply_active_scan_flags( + struct wiphy *wiphy, + enum nl80211_reg_initiator initiator) { struct ieee80211_supported_band *sband; struct ieee80211_channel *ch; @@ -241,7 +243,7 @@ static void ath9k_reg_apply_active_scan_flags(struct wiphy *wiphy, * If no country IE has been received always enable active scan * on these channels. This is only done for specific regulatory SKUs */ - if (setby != REGDOM_SET_BY_COUNTRY_IE) { + if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { ch = &sband->channels[11]; /* CH 12 */ if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; @@ -308,7 +310,8 @@ void ath9k_reg_apply_radar_flags(struct wiphy *wiphy) } } -void ath9k_reg_apply_world_flags(struct wiphy *wiphy, enum reg_set_by setby) +void ath9k_reg_apply_world_flags(struct wiphy *wiphy, + enum nl80211_reg_initiator initiator) { struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); struct ath_wiphy *aphy = hw->priv; @@ -320,11 +323,11 @@ void ath9k_reg_apply_world_flags(struct wiphy *wiphy, enum reg_set_by setby) case 0x63: case 0x66: case 0x67: - ath9k_reg_apply_beaconing_flags(wiphy, setby); + ath9k_reg_apply_beaconing_flags(wiphy, initiator); break; case 0x68: - ath9k_reg_apply_beaconing_flags(wiphy, setby); - ath9k_reg_apply_active_scan_flags(wiphy, setby); + ath9k_reg_apply_beaconing_flags(wiphy, initiator); + ath9k_reg_apply_active_scan_flags(wiphy, initiator); break; } return; @@ -340,11 +343,11 @@ int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) ath9k_reg_apply_radar_flags(wiphy); switch (request->initiator) { - case REGDOM_SET_BY_DRIVER: - case REGDOM_SET_BY_CORE: - case REGDOM_SET_BY_USER: + case NL80211_REGDOM_SET_BY_DRIVER: + case NL80211_REGDOM_SET_BY_CORE: + case NL80211_REGDOM_SET_BY_USER: break; - case REGDOM_SET_BY_COUNTRY_IE: + case NL80211_REGDOM_SET_BY_COUNTRY_IE: if (ath9k_is_world_regd(sc->sc_ah)) ath9k_reg_apply_world_flags(wiphy, request->initiator); break; diff --git a/drivers/net/wireless/ath9k/regd.h b/drivers/net/wireless/ath9k/regd.h index d48160d0c0e..8f885f3bc8d 100644 --- a/drivers/net/wireless/ath9k/regd.h +++ b/drivers/net/wireless/ath9k/regd.h @@ -236,7 +236,8 @@ enum CountryCode { bool ath9k_is_world_regd(struct ath_hw *ah); const struct ieee80211_regdomain *ath9k_world_regdomain(struct ath_hw *ah); const struct ieee80211_regdomain *ath9k_default_world_regdomain(void); -void ath9k_reg_apply_world_flags(struct wiphy *wiphy, enum reg_set_by setby); +void ath9k_reg_apply_world_flags(struct wiphy *wiphy, + enum nl80211_reg_initiator initiator); void ath9k_reg_apply_radar_flags(struct wiphy *wiphy); int ath9k_regd_init(struct ath_hw *ah); bool ath9k_regd_is_eeprom_valid(struct ath_hw *ah); diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index f6e56370ea6..c0fd432b57d 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -672,6 +672,25 @@ enum nl80211_bitrate_attr { NL80211_BITRATE_ATTR_MAX = __NL80211_BITRATE_ATTR_AFTER_LAST - 1 }; +/** + * enum nl80211_initiator - Indicates the initiator of a reg domain request + * @NL80211_REGDOM_SET_BY_CORE: Core queried CRDA for a dynamic world + * regulatory domain. + * @NL80211_REGDOM_SET_BY_USER: User asked the wireless core to set the + * regulatory domain. + * @NL80211_REGDOM_SET_BY_DRIVER: a wireless drivers has hinted to the + * wireless core it thinks its knows the regulatory domain we should be in. + * @NL80211_REGDOM_SET_BY_COUNTRY_IE: the wireless core has received an + * 802.11 country information element with regulatory information it + * thinks we should consider. + */ +enum nl80211_reg_initiator { + NL80211_REGDOM_SET_BY_CORE, + NL80211_REGDOM_SET_BY_USER, + NL80211_REGDOM_SET_BY_DRIVER, + NL80211_REGDOM_SET_BY_COUNTRY_IE, +}; + /** * enum nl80211_reg_rule_attr - regulatory rule attributes * @NL80211_ATTR_REG_RULE_FLAGS: a set of flags which specify additional diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index f195ea46081..50f3fd9ff52 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -348,28 +348,10 @@ struct bss_parameters { u8 basic_rates_len; }; -/** - * enum reg_set_by - Indicates who is trying to set the regulatory domain - * @REGDOM_SET_BY_CORE: Core queried CRDA for a dynamic world regulatory domain. - * @REGDOM_SET_BY_USER: User asked the wireless core to set the - * regulatory domain. - * @REGDOM_SET_BY_DRIVER: a wireless drivers has hinted to the wireless core - * it thinks its knows the regulatory domain we should be in. - * @REGDOM_SET_BY_COUNTRY_IE: the wireless core has received an 802.11 country - * information element with regulatory information it thinks we - * should consider. - */ -enum reg_set_by { - REGDOM_SET_BY_CORE, - REGDOM_SET_BY_USER, - REGDOM_SET_BY_DRIVER, - REGDOM_SET_BY_COUNTRY_IE, -}; - /** * enum environment_cap - Environment parsed from country IE * @ENVIRON_ANY: indicates country IE applies to both indoor and - * outdoor operation. + * outdoor operation. * @ENVIRON_INDOOR: indicates country IE applies only to indoor operation * @ENVIRON_OUTDOOR: indicates country IE applies only to outdoor operation */ @@ -388,7 +370,7 @@ enum environment_cap { * and potentially inform users of which devices specifically * cased the conflicts. * @initiator: indicates who sent this request, could be any of - * of those set in reg_set_by, %REGDOM_SET_BY_* + * of those set in nl80211_reg_initiator (%NL80211_REGDOM_SET_BY_*) * @alpha2: the ISO / IEC 3166 alpha2 country code of the requested * regulatory domain. We have a few special codes: * 00 - World regulatory domain @@ -405,7 +387,7 @@ enum environment_cap { */ struct regulatory_request { int wiphy_idx; - enum reg_set_by initiator; + enum nl80211_reg_initiator initiator; char alpha2[2]; bool intersect; u32 country_ie_checksum; diff --git a/net/wireless/core.c b/net/wireless/core.c index dd7f222919f..c939f5ee065 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -350,7 +350,7 @@ int wiphy_register(struct wiphy *wiphy) mutex_lock(&cfg80211_mutex); /* set up regulatory info */ - wiphy_update_regulatory(wiphy, REGDOM_SET_BY_CORE); + wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE); res = device_add(&drv->wiphy.dev); if (res) diff --git a/net/wireless/core.h b/net/wireless/core.h index f6c53f5807f..6acd483a61f 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -136,7 +136,8 @@ extern int cfg80211_dev_rename(struct cfg80211_registered_device *drv, char *newname); void ieee80211_set_bitrate_flags(struct wiphy *wiphy); -void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby); +void wiphy_update_regulatory(struct wiphy *wiphy, + enum nl80211_reg_initiator setby); void cfg80211_bss_expire(struct cfg80211_registered_device *dev); void cfg80211_bss_age(struct cfg80211_registered_device *dev, diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 47ff44751b7..68fde6d33dc 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -857,8 +857,8 @@ static int freq_reg_info_regd(struct wiphy *wiphy, * Follow the driver's regulatory domain, if present, unless a country * IE has been processed or a user wants to help complaince further */ - if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE && - last_request->initiator != REGDOM_SET_BY_USER && + if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && + last_request->initiator != NL80211_REGDOM_SET_BY_USER && wiphy->regd) regd = wiphy->regd; @@ -943,7 +943,8 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, * http://tinyurl.com/11d-clarification */ if (r == -ERANGE && - last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) { + last_request->initiator == + NL80211_REGDOM_SET_BY_COUNTRY_IE) { #ifdef CONFIG_CFG80211_REG_DEBUG printk(KERN_DEBUG "cfg80211: Leaving channel %d MHz " "intact on %s - no rule found in band on " @@ -956,7 +957,8 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, * for the band so we respect its band definitions */ #ifdef CONFIG_CFG80211_REG_DEBUG - if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) + if (last_request->initiator == + NL80211_REGDOM_SET_BY_COUNTRY_IE) printk(KERN_DEBUG "cfg80211: Disabling " "channel %d MHz on %s due to " "Country IE\n", @@ -970,7 +972,7 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, power_rule = ®_rule->power_rule; - if (last_request->initiator == REGDOM_SET_BY_DRIVER && + if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && request_wiphy && request_wiphy == wiphy && request_wiphy->strict_regulatory) { /* @@ -1011,11 +1013,12 @@ static void handle_band(struct wiphy *wiphy, enum ieee80211_band band) handle_channel(wiphy, band, i); } -static bool ignore_reg_update(struct wiphy *wiphy, enum reg_set_by setby) +static bool ignore_reg_update(struct wiphy *wiphy, + enum nl80211_reg_initiator initiator) { if (!last_request) return true; - if (setby == REGDOM_SET_BY_CORE && + if (initiator == NL80211_REGDOM_SET_BY_CORE && wiphy->custom_regulatory) return true; /* @@ -1028,12 +1031,12 @@ static bool ignore_reg_update(struct wiphy *wiphy, enum reg_set_by setby) return false; } -static void update_all_wiphy_regulatory(enum reg_set_by setby) +static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) { struct cfg80211_registered_device *drv; list_for_each_entry(drv, &cfg80211_drv_list, list) - wiphy_update_regulatory(&drv->wiphy, setby); + wiphy_update_regulatory(&drv->wiphy, initiator); } static void handle_reg_beacon(struct wiphy *wiphy, @@ -1124,7 +1127,7 @@ static bool reg_is_world_roaming(struct wiphy *wiphy) if (is_world_regdom(cfg80211_regdomain->alpha2) || (wiphy->regd && is_world_regdom(wiphy->regd->alpha2))) return true; - if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE && + if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && wiphy->custom_regulatory) return true; return false; @@ -1138,11 +1141,12 @@ static void reg_process_beacons(struct wiphy *wiphy) wiphy_update_beacon_reg(wiphy); } -void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby) +void wiphy_update_regulatory(struct wiphy *wiphy, + enum nl80211_reg_initiator initiator) { enum ieee80211_band band; - if (ignore_reg_update(wiphy, setby)) + if (ignore_reg_update(wiphy, initiator)) goto out; for (band = 0; band < IEEE80211_NUM_BANDS; band++) { if (wiphy->bands[band]) @@ -1255,15 +1259,16 @@ static int ignore_request(struct wiphy *wiphy, return 0; switch (pending_request->initiator) { - case REGDOM_SET_BY_CORE: + case NL80211_REGDOM_SET_BY_CORE: return -EINVAL; - case REGDOM_SET_BY_COUNTRY_IE: + case NL80211_REGDOM_SET_BY_COUNTRY_IE: last_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); if (unlikely(!is_an_alpha2(pending_request->alpha2))) return -EINVAL; - if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) { + if (last_request->initiator == + NL80211_REGDOM_SET_BY_COUNTRY_IE) { if (last_wiphy != wiphy) { /* * Two cards with two APs claiming different @@ -1284,8 +1289,8 @@ static int ignore_request(struct wiphy *wiphy, return -EALREADY; } return REG_INTERSECT; - case REGDOM_SET_BY_DRIVER: - if (last_request->initiator == REGDOM_SET_BY_CORE) { + case NL80211_REGDOM_SET_BY_DRIVER: + if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE) { if (is_old_static_regdom(cfg80211_regdomain)) return 0; if (regdom_changes(pending_request->alpha2)) @@ -1298,28 +1303,28 @@ static int ignore_request(struct wiphy *wiphy, * back in or if you add a new device for which the previously * loaded card also agrees on the regulatory domain. */ - if (last_request->initiator == REGDOM_SET_BY_DRIVER && + if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && !regdom_changes(pending_request->alpha2)) return -EALREADY; return REG_INTERSECT; - case REGDOM_SET_BY_USER: - if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) + case NL80211_REGDOM_SET_BY_USER: + if (last_request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) return REG_INTERSECT; /* * If the user knows better the user should set the regdom * to their country before the IE is picked up */ - if (last_request->initiator == REGDOM_SET_BY_USER && + if (last_request->initiator == NL80211_REGDOM_SET_BY_USER && last_request->intersect) return -EOPNOTSUPP; /* * Process user requests only after previous user/driver/core * requests have been processed */ - if (last_request->initiator == REGDOM_SET_BY_CORE || - last_request->initiator == REGDOM_SET_BY_DRIVER || - last_request->initiator == REGDOM_SET_BY_USER) { + if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE || + last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER || + last_request->initiator == NL80211_REGDOM_SET_BY_USER) { if (regdom_changes(last_request->alpha2)) return -EAGAIN; } @@ -1359,7 +1364,8 @@ static int __regulatory_hint(struct wiphy *wiphy, r = ignore_request(wiphy, pending_request); if (r == REG_INTERSECT) { - if (pending_request->initiator == REGDOM_SET_BY_DRIVER) { + if (pending_request->initiator == + NL80211_REGDOM_SET_BY_DRIVER) { r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain); if (r) { kfree(pending_request); @@ -1374,7 +1380,8 @@ static int __regulatory_hint(struct wiphy *wiphy, * wiphy */ if (r == -EALREADY && - pending_request->initiator == REGDOM_SET_BY_DRIVER) { + pending_request->initiator == + NL80211_REGDOM_SET_BY_DRIVER) { r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain); if (r) { kfree(pending_request); @@ -1425,7 +1432,7 @@ static void reg_process_hint(struct regulatory_request *reg_request) if (wiphy_idx_valid(reg_request->wiphy_idx)) wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx); - if (reg_request->initiator == REGDOM_SET_BY_DRIVER && + if (reg_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && !wiphy) { kfree(reg_request); goto out; @@ -1439,7 +1446,7 @@ out: mutex_unlock(&cfg80211_mutex); } -/* Processes regulatory hints, this is all the REGDOM_SET_BY_* */ +/* Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_* */ static void reg_process_pending_hints(void) { struct regulatory_request *reg_request; @@ -1523,7 +1530,7 @@ static int regulatory_hint_core(const char *alpha2) request->alpha2[0] = alpha2[0]; request->alpha2[1] = alpha2[1]; - request->initiator = REGDOM_SET_BY_CORE; + request->initiator = NL80211_REGDOM_SET_BY_CORE; queue_regulatory_request(request); @@ -1544,7 +1551,7 @@ int regulatory_hint_user(const char *alpha2) request->wiphy_idx = WIPHY_IDX_STALE; request->alpha2[0] = alpha2[0]; request->alpha2[1] = alpha2[1]; - request->initiator = REGDOM_SET_BY_USER, + request->initiator = NL80211_REGDOM_SET_BY_USER, queue_regulatory_request(request); @@ -1570,7 +1577,7 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2) request->alpha2[0] = alpha2[0]; request->alpha2[1] = alpha2[1]; - request->initiator = REGDOM_SET_BY_DRIVER; + request->initiator = NL80211_REGDOM_SET_BY_DRIVER; queue_regulatory_request(request); @@ -1719,7 +1726,7 @@ void regulatory_hint_11d(struct wiphy *wiphy, request->wiphy_idx = get_wiphy_idx(wiphy); request->alpha2[0] = rd->alpha2[0]; request->alpha2[1] = rd->alpha2[1]; - request->initiator = REGDOM_SET_BY_COUNTRY_IE; + request->initiator = NL80211_REGDOM_SET_BY_COUNTRY_IE; request->country_ie_checksum = checksum; request->country_ie_env = env; @@ -1827,7 +1834,8 @@ static void print_regdomain(const struct ieee80211_regdomain *rd) if (is_intersected_alpha2(rd->alpha2)) { - if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) { + if (last_request->initiator == + NL80211_REGDOM_SET_BY_COUNTRY_IE) { struct cfg80211_registered_device *drv; drv = cfg80211_drv_by_wiphy_idx( last_request->wiphy_idx); @@ -1919,7 +1927,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) * rd is non static (it means CRDA was present and was used last) * and the pending request came in from a country IE */ - if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE) { + if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { /* * If someone else asked us to change the rd lets only bother * checking if the alpha2 changes if CRDA was already called @@ -1951,7 +1959,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) if (!last_request->intersect) { int r; - if (last_request->initiator != REGDOM_SET_BY_DRIVER) { + if (last_request->initiator != NL80211_REGDOM_SET_BY_DRIVER) { reset_regdomains(); cfg80211_regdomain = rd; return 0; @@ -1975,7 +1983,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) /* Intersection requires a bit more work */ - if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE) { + if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { intersected_rd = regdom_intersect(rd, cfg80211_regdomain); if (!intersected_rd) @@ -1986,7 +1994,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) * However if a driver requested this specific regulatory * domain we keep it for its private use */ - if (last_request->initiator == REGDOM_SET_BY_DRIVER) + if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER) request_wiphy->regd = rd; else kfree(rd); -- GitLab From 73d54c9e74c4d8ee8a41bc516f481f0f754eca32 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 9 Mar 2009 22:07:42 -0400 Subject: [PATCH 3591/4982] cfg80211: add regulatory netlink multicast group This allows us to send to userspace "regulatory" events. For now we just send an event when we change regulatory domains. We also notify userspace when devices are using their own custom world roaming regulatory domains. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- include/linux/nl80211.h | 48 +++++++++++++++++++++++++++++++ net/wireless/core.c | 11 ++++++++ net/wireless/nl80211.c | 62 +++++++++++++++++++++++++++++++++++++++++ net/wireless/nl80211.h | 5 ++++ net/wireless/reg.c | 13 ++++++++- 5 files changed, 138 insertions(+), 1 deletion(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index c0fd432b57d..f33aa08dd9b 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -150,6 +150,17 @@ * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons, * partial scan results may be available * + * @NL80211_CMD_REG_CHANGE: indicates to userspace the regulatory domain + * has been changed and provides details of the request information + * that caused the change such as who initiated the regulatory request + * (%NL80211_ATTR_REG_INITIATOR), the wiphy_idx + * (%NL80211_ATTR_REG_ALPHA2) on which the request was made from if + * the initiator was %NL80211_REGDOM_SET_BY_COUNTRY_IE or + * %NL80211_REGDOM_SET_BY_DRIVER, the type of regulatory domain + * set (%NL80211_ATTR_REG_TYPE), if the type of regulatory domain is + * %NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on + * to (%NL80211_ATTR_REG_ALPHA2). + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -204,6 +215,8 @@ enum nl80211_commands { NL80211_CMD_NEW_SCAN_RESULTS, NL80211_CMD_SCAN_ABORTED, + NL80211_CMD_REG_CHANGE, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -218,6 +231,8 @@ enum nl80211_commands { #define NL80211_CMD_SET_BSS NL80211_CMD_SET_BSS #define NL80211_CMD_SET_MGMT_EXTRA_IE NL80211_CMD_SET_MGMT_EXTRA_IE +#define NL80211_CMD_REG_CHANGE NL80211_CMD_REG_CHANGE + /** * enum nl80211_attrs - nl80211 netlink attributes * @@ -329,6 +344,11 @@ enum nl80211_commands { * messages carried the same generation number) * @NL80211_ATTR_BSS: scan result BSS * + * @NL80211_ATTR_REG_INITIATOR: indicates who requested the regulatory domain + * currently in effect. This could be any of the %NL80211_REGDOM_SET_BY_* + * @NL80211_ATTR_REG_TYPE: indicates the type of the regulatory domain currently + * set. This can be one of the nl80211_reg_type (%NL80211_REGDOM_TYPE_*) + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -403,6 +423,9 @@ enum nl80211_attrs { NL80211_ATTR_SCAN_GENERATION, NL80211_ATTR_BSS, + NL80211_ATTR_REG_INITIATOR, + NL80211_ATTR_REG_TYPE, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -420,6 +443,8 @@ enum nl80211_attrs { #define NL80211_ATTR_WIPHY_CHANNEL_TYPE NL80211_ATTR_WIPHY_CHANNEL_TYPE #define NL80211_ATTR_MGMT_SUBTYPE NL80211_ATTR_MGMT_SUBTYPE #define NL80211_ATTR_IE NL80211_ATTR_IE +#define NL80211_ATTR_REG_INITIATOR NL80211_ATTR_REG_INITIATOR +#define NL80211_ATTR_REG_TYPE NL80211_ATTR_REG_TYPE #define NL80211_MAX_SUPP_RATES 32 #define NL80211_MAX_SUPP_REG_RULES 32 @@ -691,6 +716,29 @@ enum nl80211_reg_initiator { NL80211_REGDOM_SET_BY_COUNTRY_IE, }; +/** + * enum nl80211_reg_type - specifies the type of regulatory domain + * @NL80211_REGDOM_TYPE_COUNTRY: the regulatory domain set is one that pertains + * to a specific country. When this is set you can count on the + * ISO / IEC 3166 alpha2 country code being valid. + * @NL80211_REGDOM_TYPE_WORLD: the regulatory set domain is the world regulatory + * domain. + * @NL80211_REGDOM_TYPE_CUSTOM_WORLD: the regulatory domain set is a custom + * driver specific world regulatory domain. These do not apply system-wide + * and are only applicable to the individual devices which have requested + * them to be applied. + * @NL80211_REGDOM_TYPE_INTERSECTION: the regulatory domain set is the product + * of an intersection between two regulatory domains -- the previously + * set regulatory domain on the system and the last accepted regulatory + * domain request to be processed. + */ +enum nl80211_reg_type { + NL80211_REGDOM_TYPE_COUNTRY, + NL80211_REGDOM_TYPE_WORLD, + NL80211_REGDOM_TYPE_CUSTOM_WORLD, + NL80211_REGDOM_TYPE_INTERSECTION, +}; + /** * enum nl80211_reg_rule_attr - regulatory rule attributes * @NL80211_ATTR_REG_RULE_FLAGS: a set of flags which specify additional diff --git a/net/wireless/core.c b/net/wireless/core.c index c939f5ee065..17fe3904974 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -365,6 +365,17 @@ int wiphy_register(struct wiphy *wiphy) if (IS_ERR(drv->wiphy.debugfsdir)) drv->wiphy.debugfsdir = NULL; + if (wiphy->custom_regulatory) { + struct regulatory_request request; + + request.wiphy_idx = get_wiphy_idx(wiphy); + request.initiator = NL80211_REGDOM_SET_BY_DRIVER; + request.alpha2[0] = '9'; + request.alpha2[1] = '9'; + + nl80211_send_reg_change_event(&request); + } + res = 0; out_unlock: mutex_unlock(&cfg80211_mutex); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 531bb67cf50..8ac3d26014a 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2739,6 +2739,9 @@ static struct genl_multicast_group nl80211_config_mcgrp = { static struct genl_multicast_group nl80211_scan_mcgrp = { .name = "scan", }; +static struct genl_multicast_group nl80211_regulatory_mcgrp = { + .name = "regulatory", +}; /* notification functions */ @@ -2818,6 +2821,61 @@ void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, genlmsg_multicast(msg, 0, nl80211_scan_mcgrp.id, GFP_KERNEL); } +/* + * This can happen on global regulatory changes or device specific settings + * based on custom world regulatory domains. + */ +void nl80211_send_reg_change_event(struct regulatory_request *request) +{ + struct sk_buff *msg; + void *hdr; + + msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!msg) + return; + + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_CHANGE); + if (!hdr) { + nlmsg_free(msg); + return; + } + + /* Userspace can always count this one always being set */ + NLA_PUT_U8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator); + + if (request->alpha2[0] == '0' && request->alpha2[1] == '0') + NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, + NL80211_REGDOM_TYPE_WORLD); + else if (request->alpha2[0] == '9' && request->alpha2[1] == '9') + NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, + NL80211_REGDOM_TYPE_CUSTOM_WORLD); + else if ((request->alpha2[0] == '9' && request->alpha2[1] == '8') || + request->intersect) + NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, + NL80211_REGDOM_TYPE_INTERSECTION); + else { + NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, + NL80211_REGDOM_TYPE_COUNTRY); + NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, request->alpha2); + } + + if (wiphy_idx_valid(request->wiphy_idx)) + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx); + + if (genlmsg_end(msg, hdr) < 0) { + nlmsg_free(msg); + return; + } + + genlmsg_multicast(msg, 0, nl80211_regulatory_mcgrp.id, GFP_KERNEL); + + return; + +nla_put_failure: + genlmsg_cancel(msg, hdr); + nlmsg_free(msg); +} + /* initialisation/exit functions */ int nl80211_init(void) @@ -2842,6 +2900,10 @@ int nl80211_init(void) if (err) goto err_out; + err = genl_register_mc_group(&nl80211_fam, &nl80211_regulatory_mcgrp); + if (err) + goto err_out; + return 0; err_out: genl_unregister_family(&nl80211_fam); diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 69787b62136..e65a3c38c52 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -11,6 +11,7 @@ extern void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, struct net_device *netdev); extern void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, struct net_device *netdev); +extern void nl80211_send_reg_change_event(struct regulatory_request *request); #else static inline int nl80211_init(void) { @@ -31,6 +32,10 @@ static inline void nl80211_send_scan_aborted( struct cfg80211_registered_device *rdev, struct net_device *netdev) {} +static inline void +nl80211_send_reg_change_event(struct regulatory_request *request) +{ +} #endif /* CONFIG_NL80211 */ #endif /* __NET_WIRELESS_NL80211_H */ diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 68fde6d33dc..eb8b8ed1615 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -41,6 +41,7 @@ #include #include "core.h" #include "reg.h" +#include "nl80211.h" /* Receipt of information from last regulatory request */ static struct regulatory_request *last_request; @@ -1403,8 +1404,16 @@ new_request: pending_request = NULL; /* When r == REG_INTERSECT we do need to call CRDA */ - if (r < 0) + if (r < 0) { + /* + * Since CRDA will not be called in this case as we already + * have applied the requested regulatory domain before we just + * inform userspace we have processed the request + */ + if (r == -EALREADY) + nl80211_send_reg_change_event(last_request); return r; + } /* * Note: When CONFIG_WIRELESS_OLD_REGULATORY is enabled @@ -2084,6 +2093,8 @@ int set_regdom(const struct ieee80211_regdomain *rd) print_regdomain(cfg80211_regdomain); + nl80211_send_reg_change_event(last_request); + return r; } -- GitLab From 4a5af9c2923b6d8ce31a7fe84d7dc5431cd844a0 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 9 Mar 2009 22:08:27 -0400 Subject: [PATCH 3592/4982] mac80211_hwsim: add regulatory testing options This adds a module parameter for mac80211_hwsim regulatory testing. This module parameter is designed specifically to help test the different possible types of driver specific regulatory requests and also helps to test world roaming, all without any hardware. If you want to just simply test different alpha2s just use the userspace regulatory request as this won't buy you anything new. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 210 ++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index d8716bed5e4..a15078bcad7 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -30,6 +30,112 @@ static int radios = 2; module_param(radios, int, 0444); MODULE_PARM_DESC(radios, "Number of simulated radios"); +/** + * enum hwsim_regtest - the type of regulatory tests we offer + * + * These are the different values you can use for the regtest + * module parameter. This is useful to help test world roaming + * and the driver regulatory_hint() call and combinations of these. + * If you want to do specific alpha2 regulatory domain tests simply + * use the userspace regulatory request as that will be respected as + * well without the need of this module parameter. This is designed + * only for testing the driver regulatory request, world roaming + * and all possible combinations. + * + * @HWSIM_REGTEST_DISABLED: No regulatory tests are performed, + * this is the default value. + * @HWSIM_REGTEST_DRIVER_REG_FOLLOW: Used for testing the driver regulatory + * hint, only one driver regulatory hint will be sent as such the + * secondary radios are expected to follow. + * @HWSIM_REGTEST_DRIVER_REG_ALL: Used for testing the driver regulatory + * request with all radios reporting the same regulatory domain. + * @HWSIM_REGTEST_DIFF_COUNTRY: Used for testing the drivers calling + * different regulatory domains requests. Expected behaviour is for + * an intersection to occur but each device will still use their + * respective regulatory requested domains. Subsequent radios will + * use the resulting intersection. + * @HWSIM_REGTEST_WORLD_ROAM: Used for testing the world roaming. We acomplish + * this by using a custom beacon-capable regulatory domain for the first + * radio. All other device world roam. + * @HWSIM_REGTEST_CUSTOM_WORLD: Used for testing the custom world regulatory + * domain requests. All radios will adhere to this custom world regulatory + * domain. + * @HWSIM_REGTEST_CUSTOM_WORLD_2: Used for testing 2 custom world regulatory + * domain requests. The first radio will adhere to the first custom world + * regulatory domain, the second one to the second custom world regulatory + * domain. All other devices will world roam. + * @HWSIM_REGTEST_STRICT_FOLLOW_: Used for testing strict regulatory domain + * settings, only the first radio will send a regulatory domain request + * and use strict settings. The rest of the radios are expected to follow. + * @HWSIM_REGTEST_STRICT_ALL: Used for testing strict regulatory domain + * settings. All radios will adhere to this. + * @HWSIM_REGTEST_STRICT_AND_DRIVER_REG: Used for testing strict regulatory + * domain settings, combined with secondary driver regulatory domain + * settings. The first radio will get a strict regulatory domain setting + * using the first driver regulatory request and the second radio will use + * non-strict settings using the second driver regulatory request. All + * other devices should follow the intersection created between the + * first two. + * @HWSIM_REGTEST_ALL: Used for testing every possible mix. You will need + * at least 6 radios for a complete test. We will test in this order: + * 1 - driver custom world regulatory domain + * 2 - second custom world regulatory domain + * 3 - first driver regulatory domain request + * 4 - second driver regulatory domain request + * 5 - strict regulatory domain settings using the third driver regulatory + * domain request + * 6 and on - should follow the intersection of the 3rd, 4rth and 5th radio + * regulatory requests. + */ +enum hwsim_regtest { + HWSIM_REGTEST_DISABLED = 0, + HWSIM_REGTEST_DRIVER_REG_FOLLOW = 1, + HWSIM_REGTEST_DRIVER_REG_ALL = 2, + HWSIM_REGTEST_DIFF_COUNTRY = 3, + HWSIM_REGTEST_WORLD_ROAM = 4, + HWSIM_REGTEST_CUSTOM_WORLD = 5, + HWSIM_REGTEST_CUSTOM_WORLD_2 = 6, + HWSIM_REGTEST_STRICT_FOLLOW = 7, + HWSIM_REGTEST_STRICT_ALL = 8, + HWSIM_REGTEST_STRICT_AND_DRIVER_REG = 9, + HWSIM_REGTEST_ALL = 10, +}; + +/* Set to one of the HWSIM_REGTEST_* values above */ +static int regtest = HWSIM_REGTEST_DISABLED; +module_param(regtest, int, 0444); +MODULE_PARM_DESC(regtest, "The type of regulatory test we want to run"); + +static const char *hwsim_alpha2s[] = { + "FI", + "AL", + "US", + "DE", + "JP", + "AL", +}; + +static const struct ieee80211_regdomain hwsim_world_regdom_custom_01 = { + .n_reg_rules = 4, + .alpha2 = "99", + .reg_rules = { + REG_RULE(2412-10, 2462+10, 40, 0, 20, 0), + REG_RULE(2484-10, 2484+10, 40, 0, 20, 0), + REG_RULE(5150-10, 5240+10, 40, 0, 30, 0), + REG_RULE(5745-10, 5825+10, 40, 0, 30, 0), + } +}; + +static const struct ieee80211_regdomain hwsim_world_regdom_custom_02 = { + .n_reg_rules = 2, + .alpha2 = "99", + .reg_rules = { + REG_RULE(2412-10, 2462+10, 40, 0, 20, 0), + REG_RULE(5725-10, 5850+10, 40, 0, 30, + NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), + } +}; + struct hwsim_vif_priv { u32 magic; u8 bssid[ETH_ALEN]; @@ -871,6 +977,64 @@ static int __init init_mac80211_hwsim(void) hw->wiphy->bands[band] = sband; } + /* Work to be done prior to ieee80211_register_hw() */ + switch (regtest) { + case HWSIM_REGTEST_DISABLED: + case HWSIM_REGTEST_DRIVER_REG_FOLLOW: + case HWSIM_REGTEST_DRIVER_REG_ALL: + case HWSIM_REGTEST_DIFF_COUNTRY: + /* + * Nothing to be done for driver regulatory domain + * hints prior to ieee80211_register_hw() + */ + break; + case HWSIM_REGTEST_WORLD_ROAM: + if (i == 0) { + hw->wiphy->custom_regulatory = true; + wiphy_apply_custom_regulatory(hw->wiphy, + &hwsim_world_regdom_custom_01); + } + break; + case HWSIM_REGTEST_CUSTOM_WORLD: + hw->wiphy->custom_regulatory = true; + wiphy_apply_custom_regulatory(hw->wiphy, + &hwsim_world_regdom_custom_01); + break; + case HWSIM_REGTEST_CUSTOM_WORLD_2: + if (i == 0) { + hw->wiphy->custom_regulatory = true; + wiphy_apply_custom_regulatory(hw->wiphy, + &hwsim_world_regdom_custom_01); + } else if (i == 1) { + hw->wiphy->custom_regulatory = true; + wiphy_apply_custom_regulatory(hw->wiphy, + &hwsim_world_regdom_custom_02); + } + break; + case HWSIM_REGTEST_STRICT_ALL: + hw->wiphy->strict_regulatory = true; + break; + case HWSIM_REGTEST_STRICT_FOLLOW: + case HWSIM_REGTEST_STRICT_AND_DRIVER_REG: + if (i == 0) + hw->wiphy->strict_regulatory = true; + break; + case HWSIM_REGTEST_ALL: + if (i == 0) { + hw->wiphy->custom_regulatory = true; + wiphy_apply_custom_regulatory(hw->wiphy, + &hwsim_world_regdom_custom_01); + } else if (i == 1) { + hw->wiphy->custom_regulatory = true; + wiphy_apply_custom_regulatory(hw->wiphy, + &hwsim_world_regdom_custom_02); + } else if (i == 4) + hw->wiphy->strict_regulatory = true; + break; + default: + break; + } + err = ieee80211_register_hw(hw); if (err < 0) { printk(KERN_DEBUG "mac80211_hwsim: " @@ -878,6 +1042,52 @@ static int __init init_mac80211_hwsim(void) goto failed_hw; } + /* Work to be done after to ieee80211_register_hw() */ + switch (regtest) { + case HWSIM_REGTEST_WORLD_ROAM: + case HWSIM_REGTEST_DISABLED: + break; + case HWSIM_REGTEST_DRIVER_REG_FOLLOW: + if (!i) + regulatory_hint(hw->wiphy, hwsim_alpha2s[0]); + break; + case HWSIM_REGTEST_DRIVER_REG_ALL: + case HWSIM_REGTEST_STRICT_ALL: + regulatory_hint(hw->wiphy, hwsim_alpha2s[0]); + break; + case HWSIM_REGTEST_DIFF_COUNTRY: + if (i < ARRAY_SIZE(hwsim_alpha2s)) + regulatory_hint(hw->wiphy, hwsim_alpha2s[i]); + break; + case HWSIM_REGTEST_CUSTOM_WORLD: + case HWSIM_REGTEST_CUSTOM_WORLD_2: + /* + * Nothing to be done for custom world regulatory + * domains after to ieee80211_register_hw + */ + break; + case HWSIM_REGTEST_STRICT_FOLLOW: + if (i == 0) + regulatory_hint(hw->wiphy, hwsim_alpha2s[0]); + break; + case HWSIM_REGTEST_STRICT_AND_DRIVER_REG: + if (i == 0) + regulatory_hint(hw->wiphy, hwsim_alpha2s[0]); + else if (i == 1) + regulatory_hint(hw->wiphy, hwsim_alpha2s[1]); + break; + case HWSIM_REGTEST_ALL: + if (i == 2) + regulatory_hint(hw->wiphy, hwsim_alpha2s[0]); + else if (i == 3) + regulatory_hint(hw->wiphy, hwsim_alpha2s[1]); + else if (i == 4) + regulatory_hint(hw->wiphy, hwsim_alpha2s[2]); + break; + default: + break; + } + printk(KERN_DEBUG "%s: hwaddr %pM registered\n", wiphy_name(hw->wiphy), hw->wiphy->perm_addr); -- GitLab From c117fa0bf5f5b3d362b590ed6e80499defe14505 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 9 Mar 2009 22:09:41 -0400 Subject: [PATCH 3593/4982] ath9k: downgrade xmit queue full message to xmit debug This is not a fatal message, hitting it simply means we're going to tell the upper layers to slow their horses down but as we make more descriptors available we let the show continue by waking up the queues in ath_wake_mac80211_queue(). We downgrade this as otherwise we fill up your kernel log with messages which can be common under heavy traffic. Cc: stable@kernel.org Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/xmit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index f61ba2b7de7..e3f376611f8 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -891,7 +891,7 @@ struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb) spin_lock_bh(&txq->axq_lock); if (txq->axq_depth >= (ATH_TXBUF - 20)) { - DPRINTF(sc, ATH_DBG_FATAL, + DPRINTF(sc, ATH_DBG_XMIT, "TX queue: %d is full, depth: %d\n", qnum, txq->axq_depth); ieee80211_stop_queue(sc->hw, skb_get_queue_mapping(skb)); -- GitLab From 15cc0f1ac670d9ff59cbcddb668900e8824b372a Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 9 Mar 2009 22:09:42 -0400 Subject: [PATCH 3594/4982] ath9k: make few eeprom and calib items static This fixes the sparse complaints: drivers/net/wireless/ath9k/eeprom.c:1407:5: warning: symbol 'ath9k_hw_4k_get_spur_channel' was not declared. Should it be static? drivers/net/wireless/ath9k/eeprom.c:1436:19: warning: symbol 'eep_4k_ops' was not declared. Should it be static? drivers/net/wireless/ath9k/eeprom.c:2808:5: warning: symbol 'ath9k_hw_def_get_spur_channel' was not declared. Should it be static? drivers/net/wireless/ath9k/eeprom.c:2837:19: warning: symbol 'eep_def_ops' was not declared. Should it be static? CC [M] drivers/net/wireless/ath9k/eeprom.o CHECK drivers/net/wireless/ath9k/mac.c CC [M] drivers/net/wireless/ath9k/mac.o CHECK drivers/net/wireless/ath9k/calib.c drivers/net/wireless/ath9k/calib.c:883:6: warning: symbol 'ar9285_clc' was not declared. Should it be static? Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/calib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c index a652e9bb16d..c9446fb6b15 100644 --- a/drivers/net/wireless/ath9k/calib.c +++ b/drivers/net/wireless/ath9k/calib.c @@ -880,7 +880,7 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, return true; } -bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) +static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) { REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); if (chan->channelFlags & CHANNEL_HT20) { -- GitLab From eeee1320b768a18822691126becc802c706aab5a Mon Sep 17 00:00:00 2001 From: Sujith Date: Tue, 10 Mar 2009 10:39:53 +0530 Subject: [PATCH 3595/4982] ath9k: Add spectrum management to HW capabilities Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index e9b3f365f09..a2f5af634f6 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1582,7 +1582,8 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION | IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_PS_NULLFUNC_STACK; + IEEE80211_HW_PS_NULLFUNC_STACK | + IEEE80211_HW_SPECTRUM_MGMT; if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt) hw->flags |= IEEE80211_HW_MFP_CAPABLE; -- GitLab From 217ba9da8ea6bb270a1f463367083cc5d99f2493 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 10 Mar 2009 10:55:50 +0200 Subject: [PATCH 3596/4982] ath9k: Fix FIF_PROMISC_IN_BSS processing in station mode We must not disable ACK sending in this case since it would break normal station operations. In addition, clarify the comment about AP mode to make more sense. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/recv.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c index 9439cb35111..0bba17662a1 100644 --- a/drivers/net/wireless/ath9k/recv.c +++ b/drivers/net/wireless/ath9k/recv.c @@ -385,14 +385,15 @@ u32 ath_calcrxfilter(struct ath_softc *sc) if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION) rfilt |= ATH9K_RX_FILTER_PROBEREQ; - /* Can't set HOSTAP into promiscous mode */ + /* + * Set promiscuous mode when FIF_PROMISC_IN_BSS is enabled for station + * mode interface or when in monitor mode. AP mode does not need this + * since it receives all in-BSS frames anyway. + */ if (((sc->sc_ah->opmode != NL80211_IFTYPE_AP) && (sc->rx.rxfilter & FIF_PROMISC_IN_BSS)) || - (sc->sc_ah->opmode == NL80211_IFTYPE_MONITOR)) { + (sc->sc_ah->opmode == NL80211_IFTYPE_MONITOR)) rfilt |= ATH9K_RX_FILTER_PROM; - /* ??? To prevent from sending ACK */ - rfilt &= ~ATH9K_RX_FILTER_UCAST; - } if (sc->rx.rxfilter & FIF_CONTROL) rfilt |= ATH9K_RX_FILTER_CONTROL; -- GitLab From a66098daacee2f354dab311b58011e7076aa248c Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 10 Mar 2009 10:13:33 +0100 Subject: [PATCH 3597/4982] mwl8k: Marvell TOPDOG wireless driver Add a driver for Marvell 88w8xxx TOPDOG PCI/PCIe wireless parts. This initial version supports the 88w8687 802.11b/g PCIe part on channels 1-11, and only STA mode is currently implemented. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 9 + drivers/net/wireless/Makefile | 2 + drivers/net/wireless/mwl8k.c | 3789 +++++++++++++++++++++++++++++++++ 3 files changed, 3800 insertions(+) create mode 100644 drivers/net/wireless/mwl8k.c diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 1294175cab2..612fffe100a 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -473,6 +473,15 @@ config MAC80211_HWSIM To compile this driver as a module, choose M here: the module will be called mac80211_hwsim. If unsure, say N. +config MWL8K + tristate "Marvell 88W8xxx PCI/PCIe Wireless support" + depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL + ---help--- + This driver supports Marvell TOPDOG 802.11 wireless cards. + + To compile this driver as a module, choose M here: the module + will be called mwl8k. If unsure, say N. + source "drivers/net/wireless/p54/Kconfig" source "drivers/net/wireless/ath5k/Kconfig" source "drivers/net/wireless/ath9k/Kconfig" diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index e2574cafe05..d780487c420 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -48,6 +48,8 @@ obj-$(CONFIG_LIBERTAS_THINFIRM) += libertas_tf/ obj-$(CONFIG_ADM8211) += adm8211.o +obj-$(CONFIG_MWL8K) += mwl8k.o + obj-$(CONFIG_IWLWIFI) += iwlwifi/ obj-$(CONFIG_RT2X00) += rt2x00/ diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c new file mode 100644 index 00000000000..57a0268d1ba --- /dev/null +++ b/drivers/net/wireless/mwl8k.c @@ -0,0 +1,3789 @@ +/* + * drivers/net/wireless/mwl8k.c driver for Marvell TOPDOG 802.11 Wireless cards + * + * Copyright (C) 2008 Marvell Semiconductor Inc. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MWL8K_DESC "Marvell TOPDOG(R) 802.11 Wireless Network Driver" +#define MWL8K_NAME KBUILD_MODNAME +#define MWL8K_VERSION "0.9.1" + +MODULE_DESCRIPTION(MWL8K_DESC); +MODULE_VERSION(MWL8K_VERSION); +MODULE_AUTHOR("Lennert Buytenhek "); +MODULE_LICENSE("GPL"); + +static DEFINE_PCI_DEVICE_TABLE(mwl8k_table) = { + { PCI_VDEVICE(MARVELL, 0x2a2b), .driver_data = 8687, }, + { PCI_VDEVICE(MARVELL, 0x2a30), .driver_data = 8687, }, + { } +}; +MODULE_DEVICE_TABLE(pci, mwl8k_table); + +#define IEEE80211_ADDR_LEN ETH_ALEN + +/* Register definitions */ +#define MWL8K_HIU_GEN_PTR 0x00000c10 +#define MWL8K_MODE_STA 0x0000005a +#define MWL8K_MODE_AP 0x000000a5 +#define MWL8K_HIU_INT_CODE 0x00000c14 +#define MWL8K_FWSTA_READY 0xf0f1f2f4 +#define MWL8K_FWAP_READY 0xf1f2f4a5 +#define MWL8K_INT_CODE_CMD_FINISHED 0x00000005 +#define MWL8K_HIU_SCRATCH 0x00000c40 + +/* Host->device communications */ +#define MWL8K_HIU_H2A_INTERRUPT_EVENTS 0x00000c18 +#define MWL8K_HIU_H2A_INTERRUPT_STATUS 0x00000c1c +#define MWL8K_HIU_H2A_INTERRUPT_MASK 0x00000c20 +#define MWL8K_HIU_H2A_INTERRUPT_CLEAR_SEL 0x00000c24 +#define MWL8K_HIU_H2A_INTERRUPT_STATUS_MASK 0x00000c28 +#define MWL8K_H2A_INT_DUMMY (1 << 20) +#define MWL8K_H2A_INT_RESET (1 << 15) +#define MWL8K_H2A_INT_PS (1 << 2) +#define MWL8K_H2A_INT_DOORBELL (1 << 1) +#define MWL8K_H2A_INT_PPA_READY (1 << 0) + +/* Device->host communications */ +#define MWL8K_HIU_A2H_INTERRUPT_EVENTS 0x00000c2c +#define MWL8K_HIU_A2H_INTERRUPT_STATUS 0x00000c30 +#define MWL8K_HIU_A2H_INTERRUPT_MASK 0x00000c34 +#define MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL 0x00000c38 +#define MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK 0x00000c3c +#define MWL8K_A2H_INT_DUMMY (1 << 20) +#define MWL8K_A2H_INT_CHNL_SWITCHED (1 << 11) +#define MWL8K_A2H_INT_QUEUE_EMPTY (1 << 10) +#define MWL8K_A2H_INT_RADAR_DETECT (1 << 7) +#define MWL8K_A2H_INT_RADIO_ON (1 << 6) +#define MWL8K_A2H_INT_RADIO_OFF (1 << 5) +#define MWL8K_A2H_INT_MAC_EVENT (1 << 3) +#define MWL8K_A2H_INT_OPC_DONE (1 << 2) +#define MWL8K_A2H_INT_RX_READY (1 << 1) +#define MWL8K_A2H_INT_TX_DONE (1 << 0) + +#define MWL8K_A2H_EVENTS (MWL8K_A2H_INT_DUMMY | \ + MWL8K_A2H_INT_CHNL_SWITCHED | \ + MWL8K_A2H_INT_QUEUE_EMPTY | \ + MWL8K_A2H_INT_RADAR_DETECT | \ + MWL8K_A2H_INT_RADIO_ON | \ + MWL8K_A2H_INT_RADIO_OFF | \ + MWL8K_A2H_INT_MAC_EVENT | \ + MWL8K_A2H_INT_OPC_DONE | \ + MWL8K_A2H_INT_RX_READY | \ + MWL8K_A2H_INT_TX_DONE) + +/* WME stream classes */ +#define WME_AC_BE 0 /* best effort */ +#define WME_AC_BK 1 /* background */ +#define WME_AC_VI 2 /* video */ +#define WME_AC_VO 3 /* voice */ + +#define MWL8K_RX_QUEUES 1 +#define MWL8K_TX_QUEUES 4 + +struct mwl8k_rx_queue { + int rx_desc_count; + + /* hw receives here */ + int rx_head; + + /* refill descs here */ + int rx_tail; + + struct mwl8k_rx_desc *rx_desc_area; + dma_addr_t rx_desc_dma; + struct sk_buff **rx_skb; +}; + +struct mwl8k_skb { + /* + * The DMA engine requires a modification to the payload. + * If the skbuff is shared/cloned, it needs to be unshared. + * This method is used to ensure the stack always gets back + * the skbuff it sent for transmission. + */ + struct sk_buff *clone; + struct sk_buff *skb; +}; + +struct mwl8k_tx_queue { + /* hw transmits here */ + int tx_head; + + /* sw appends here */ + int tx_tail; + + struct ieee80211_tx_queue_stats tx_stats; + struct mwl8k_tx_desc *tx_desc_area; + dma_addr_t tx_desc_dma; + struct mwl8k_skb *tx_skb; +}; + +/* Pointers to the firmware data and meta information about it. */ +struct mwl8k_firmware { + /* Microcode */ + struct firmware *ucode; + + /* Boot helper code */ + struct firmware *helper; +}; + +struct mwl8k_priv { + void __iomem *regs; + struct ieee80211_hw *hw; + + struct pci_dev *pdev; + u8 name[16]; + /* firmware access lock */ + spinlock_t fw_lock; + + /* firmware files and meta data */ + struct mwl8k_firmware fw; + u32 part_num; + + /* lock held over TX and TX reap */ + spinlock_t tx_lock; + u32 int_mask; + + struct ieee80211_vif *vif; + struct list_head vif_list; + + struct ieee80211_channel *current_channel; + + /* power management status cookie from firmware */ + u32 *cookie; + dma_addr_t cookie_dma; + + u16 num_mcaddrs; + u16 region_code; + u8 hw_rev; + __le32 fw_rev; + u32 wep_enabled; + + /* + * Running count of TX packets in flight, to avoid + * iterating over the transmit rings each time. + */ + int pending_tx_pkts; + + struct mwl8k_rx_queue rxq[MWL8K_RX_QUEUES]; + struct mwl8k_tx_queue txq[MWL8K_TX_QUEUES]; + + /* PHY parameters */ + struct ieee80211_supported_band band; + struct ieee80211_channel channels[14]; + struct ieee80211_rate rates[12]; + + /* RF preamble: Short, Long or Auto */ + u8 radio_preamble; + u8 radio_state; + + /* WMM MODE 1 for enabled; 0 for disabled */ + bool wmm_mode; + + /* Set if PHY config is in progress */ + bool inconfig; + + /* XXX need to convert this to handle multiple interfaces */ + bool capture_beacon; + u8 capture_bssid[IEEE80211_ADDR_LEN]; + struct sk_buff *beacon_skb; + + /* + * This FJ worker has to be global as it is scheduled from the + * RX handler. At this point we don't know which interface it + * belongs to until the list of bssids waiting to complete join + * is checked. + */ + struct work_struct finalize_join_worker; + + /* Tasklet to reclaim TX descriptors and buffers after tx */ + struct tasklet_struct tx_reclaim_task; + + /* Work thread to serialize configuration requests */ + struct workqueue_struct *config_wq; + struct completion *hostcmd_wait; + struct completion *tx_wait; +}; + +/* Per interface specific private data */ +struct mwl8k_vif { + struct list_head node; + + /* backpointer to parent config block */ + struct mwl8k_priv *priv; + + /* BSS config of AP or IBSS from mac80211*/ + struct ieee80211_bss_conf bss_info; + + /* BSSID of AP or IBSS */ + u8 bssid[IEEE80211_ADDR_LEN]; + u8 mac_addr[IEEE80211_ADDR_LEN]; + + /* + * Subset of supported legacy rates. + * Intersection of AP and STA supported rates. + */ + struct ieee80211_rate legacy_rates[12]; + + /* number of supported legacy rates */ + u8 legacy_nrates; + + /* Number of supported MCS rates. Work in progress */ + u8 mcs_nrates; + + /* Index into station database.Returned by update_sta_db call */ + u8 peer_id; + + /* Non AMPDU sequence number assigned by driver */ + u16 seqno; + + /* Note:There is no channel info, + * refer to the master channel info in priv + */ +}; + +#define MWL8K_VIF(_vif) (struct mwl8k_vif *)(&((_vif)->drv_priv)) + +static const struct ieee80211_channel mwl8k_channels[] = { + { .center_freq = 2412, .hw_value = 1, }, + { .center_freq = 2417, .hw_value = 2, }, + { .center_freq = 2422, .hw_value = 3, }, + { .center_freq = 2427, .hw_value = 4, }, + { .center_freq = 2432, .hw_value = 5, }, + { .center_freq = 2437, .hw_value = 6, }, + { .center_freq = 2442, .hw_value = 7, }, + { .center_freq = 2447, .hw_value = 8, }, + { .center_freq = 2452, .hw_value = 9, }, + { .center_freq = 2457, .hw_value = 10, }, + { .center_freq = 2462, .hw_value = 11, }, +}; + +static const struct ieee80211_rate mwl8k_rates[] = { + { .bitrate = 10, .hw_value = 2, }, + { .bitrate = 20, .hw_value = 4, }, + { .bitrate = 55, .hw_value = 11, }, + { .bitrate = 60, .hw_value = 12, }, + { .bitrate = 90, .hw_value = 18, }, + { .bitrate = 110, .hw_value = 22, }, + { .bitrate = 120, .hw_value = 24, }, + { .bitrate = 180, .hw_value = 36, }, + { .bitrate = 240, .hw_value = 48, }, + { .bitrate = 360, .hw_value = 72, }, + { .bitrate = 480, .hw_value = 96, }, + { .bitrate = 540, .hw_value = 108, }, +}; + +/* Radio settings */ +#define MWL8K_RADIO_FORCE 0x2 +#define MWL8K_RADIO_ENABLE 0x1 +#define MWL8K_RADIO_DISABLE 0x0 +#define MWL8K_RADIO_AUTO_PREAMBLE 0x0005 +#define MWL8K_RADIO_SHORT_PREAMBLE 0x0003 +#define MWL8K_RADIO_LONG_PREAMBLE 0x0001 + +/* WMM */ +#define MWL8K_WMM_ENABLE 1 +#define MWL8K_WMM_DISABLE 0 + +#define MWL8K_RADIO_DEFAULT_PREAMBLE MWL8K_RADIO_LONG_PREAMBLE + +/* Slot time */ + +/* Short Slot: 9us slot time */ +#define MWL8K_SHORT_SLOTTIME 1 + +/* Long slot: 20us slot time */ +#define MWL8K_LONG_SLOTTIME 0 + +/* Set or get info from Firmware */ +#define MWL8K_CMD_SET 0x0001 +#define MWL8K_CMD_GET 0x0000 + +/* Firmware command codes */ +#define MWL8K_CMD_CODE_DNLD 0x0001 +#define MWL8K_CMD_GET_HW_SPEC 0x0003 +#define MWL8K_CMD_MAC_MULTICAST_ADR 0x0010 +#define MWL8K_CMD_GET_STAT 0x0014 +#define MWL8K_CMD_RADIO_CONTROL 0x001C +#define MWL8K_CMD_RF_TX_POWER 0x001E +#define MWL8K_CMD_SET_PRE_SCAN 0x0107 +#define MWL8K_CMD_SET_POST_SCAN 0x0108 +#define MWL8K_CMD_SET_RF_CHANNEL 0x010A +#define MWL8K_CMD_SET_SLOT 0x0114 +#define MWL8K_CMD_MIMO_CONFIG 0x0125 +#define MWL8K_CMD_ENABLE_SNIFFER 0x0150 +#define MWL8K_CMD_SET_WMM_MODE 0x0123 +#define MWL8K_CMD_SET_EDCA_PARAMS 0x0115 +#define MWL8K_CMD_SET_FINALIZE_JOIN 0x0111 +#define MWL8K_CMD_UPDATE_STADB 0x1123 +#define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203 +#define MWL8K_CMD_SET_LINKADAPT_MODE 0x0129 +#define MWL8K_CMD_SET_AID 0x010d +#define MWL8K_CMD_SET_RATE 0x0110 +#define MWL8K_CMD_USE_FIXED_RATE 0x0126 +#define MWL8K_CMD_RTS_THRESHOLD 0x0113 +#define MWL8K_CMD_ENCRYPTION 0x1122 + +static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) +{ +#define MWL8K_CMDNAME(x) case MWL8K_CMD_##x: do {\ + snprintf(buf, bufsize, "%s", #x);\ + return buf;\ + } while (0) + switch (cmd & (~0x8000)) { + MWL8K_CMDNAME(CODE_DNLD); + MWL8K_CMDNAME(GET_HW_SPEC); + MWL8K_CMDNAME(MAC_MULTICAST_ADR); + MWL8K_CMDNAME(GET_STAT); + MWL8K_CMDNAME(RADIO_CONTROL); + MWL8K_CMDNAME(RF_TX_POWER); + MWL8K_CMDNAME(SET_PRE_SCAN); + MWL8K_CMDNAME(SET_POST_SCAN); + MWL8K_CMDNAME(SET_RF_CHANNEL); + MWL8K_CMDNAME(SET_SLOT); + MWL8K_CMDNAME(MIMO_CONFIG); + MWL8K_CMDNAME(ENABLE_SNIFFER); + MWL8K_CMDNAME(SET_WMM_MODE); + MWL8K_CMDNAME(SET_EDCA_PARAMS); + MWL8K_CMDNAME(SET_FINALIZE_JOIN); + MWL8K_CMDNAME(UPDATE_STADB); + MWL8K_CMDNAME(SET_RATEADAPT_MODE); + MWL8K_CMDNAME(SET_LINKADAPT_MODE); + MWL8K_CMDNAME(SET_AID); + MWL8K_CMDNAME(SET_RATE); + MWL8K_CMDNAME(USE_FIXED_RATE); + MWL8K_CMDNAME(RTS_THRESHOLD); + MWL8K_CMDNAME(ENCRYPTION); + default: + snprintf(buf, bufsize, "0x%x", cmd); + } +#undef MWL8K_CMDNAME + + return buf; +} + +/* Hardware and firmware reset */ +static void mwl8k_hw_reset(struct mwl8k_priv *priv) +{ + iowrite32(MWL8K_H2A_INT_RESET, + priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); + iowrite32(MWL8K_H2A_INT_RESET, + priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); + msleep(20); +} + +/* Release fw image */ +static void mwl8k_release_fw(struct firmware **fw) +{ + if (*fw == NULL) + return; + release_firmware(*fw); + *fw = NULL; +} + +static void mwl8k_release_firmware(struct mwl8k_priv *priv) +{ + mwl8k_release_fw(&priv->fw.ucode); + mwl8k_release_fw(&priv->fw.helper); +} + +/* Request fw image */ +static int mwl8k_request_fw(struct mwl8k_priv *priv, + const char *fname, struct firmware **fw) +{ + /* release current image */ + if (*fw != NULL) + mwl8k_release_fw(fw); + + return request_firmware((const struct firmware **)fw, + fname, &priv->pdev->dev); +} + +static int mwl8k_request_firmware(struct mwl8k_priv *priv, u32 part_num) +{ + u8 filename[64]; + int rc; + + priv->part_num = part_num; + + snprintf(filename, sizeof(filename), + "mwl8k/helper_%u.fw", priv->part_num); + + rc = mwl8k_request_fw(priv, filename, &priv->fw.helper); + if (rc) { + printk(KERN_ERR + "%s Error requesting helper firmware file %s\n", + pci_name(priv->pdev), filename); + return rc; + } + + snprintf(filename, sizeof(filename), + "mwl8k/fmimage_%u.fw", priv->part_num); + + rc = mwl8k_request_fw(priv, filename, &priv->fw.ucode); + if (rc) { + printk(KERN_ERR "%s Error requesting firmware file %s\n", + pci_name(priv->pdev), filename); + mwl8k_release_fw(&priv->fw.helper); + return rc; + } + + return 0; +} + +struct mwl8k_cmd_pkt { + __le16 code; + __le16 length; + __le16 seq_num; + __le16 result; + char payload[0]; +} __attribute__((packed)); + +/* + * Firmware loading. + */ +static int +mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length) +{ + void __iomem *regs = priv->regs; + dma_addr_t dma_addr; + int rc; + int loops; + + dma_addr = pci_map_single(priv->pdev, data, length, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(priv->pdev, dma_addr)) + return -ENOMEM; + + iowrite32(dma_addr, regs + MWL8K_HIU_GEN_PTR); + iowrite32(0, regs + MWL8K_HIU_INT_CODE); + iowrite32(MWL8K_H2A_INT_DOORBELL, + regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); + iowrite32(MWL8K_H2A_INT_DUMMY, + regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); + + rc = -ETIMEDOUT; + loops = 1000; + do { + u32 int_code; + + int_code = ioread32(regs + MWL8K_HIU_INT_CODE); + if (int_code == MWL8K_INT_CODE_CMD_FINISHED) { + iowrite32(0, regs + MWL8K_HIU_INT_CODE); + rc = 0; + break; + } + + udelay(1); + } while (--loops); + + pci_unmap_single(priv->pdev, dma_addr, length, PCI_DMA_TODEVICE); + + /* + * Clear 'command done' interrupt bit. + */ + loops = 1000; + do { + u32 status; + + status = ioread32(priv->regs + + MWL8K_HIU_A2H_INTERRUPT_STATUS); + if (status & MWL8K_A2H_INT_OPC_DONE) { + iowrite32(~MWL8K_A2H_INT_OPC_DONE, + priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); + ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); + break; + } + + udelay(1); + } while (--loops); + + return rc; +} + +static int mwl8k_load_fw_image(struct mwl8k_priv *priv, + const u8 *data, size_t length) +{ + struct mwl8k_cmd_pkt *cmd; + int done; + int rc = 0; + + cmd = kmalloc(sizeof(*cmd) + 256, GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->code = cpu_to_le16(MWL8K_CMD_CODE_DNLD); + cmd->seq_num = 0; + cmd->result = 0; + + done = 0; + while (length) { + int block_size = length > 256 ? 256 : length; + + memcpy(cmd->payload, data + done, block_size); + cmd->length = cpu_to_le16(block_size); + + rc = mwl8k_send_fw_load_cmd(priv, cmd, + sizeof(*cmd) + block_size); + if (rc) + break; + + done += block_size; + length -= block_size; + } + + if (!rc) { + cmd->length = 0; + rc = mwl8k_send_fw_load_cmd(priv, cmd, sizeof(*cmd)); + } + + kfree(cmd); + + return rc; +} + +static int mwl8k_feed_fw_image(struct mwl8k_priv *priv, + const u8 *data, size_t length) +{ + unsigned char *buffer; + int may_continue, rc = 0; + u32 done, prev_block_size; + + buffer = kmalloc(1024, GFP_KERNEL); + if (buffer == NULL) + return -ENOMEM; + + done = 0; + prev_block_size = 0; + may_continue = 1000; + while (may_continue > 0) { + u32 block_size; + + block_size = ioread32(priv->regs + MWL8K_HIU_SCRATCH); + if (block_size & 1) { + block_size &= ~1; + may_continue--; + } else { + done += prev_block_size; + length -= prev_block_size; + } + + if (block_size > 1024 || block_size > length) { + rc = -EOVERFLOW; + break; + } + + if (length == 0) { + rc = 0; + break; + } + + if (block_size == 0) { + rc = -EPROTO; + may_continue--; + udelay(1); + continue; + } + + prev_block_size = block_size; + memcpy(buffer, data + done, block_size); + + rc = mwl8k_send_fw_load_cmd(priv, buffer, block_size); + if (rc) + break; + } + + if (!rc && length != 0) + rc = -EREMOTEIO; + + kfree(buffer); + + return rc; +} + +static int mwl8k_load_firmware(struct mwl8k_priv *priv) +{ + int loops, rc; + + const u8 *ucode = priv->fw.ucode->data; + size_t ucode_len = priv->fw.ucode->size; + const u8 *helper = priv->fw.helper->data; + size_t helper_len = priv->fw.helper->size; + + if (!memcmp(ucode, "\x01\x00\x00\x00", 4)) { + rc = mwl8k_load_fw_image(priv, helper, helper_len); + if (rc) { + printk(KERN_ERR "%s: unable to load firmware " + "helper image\n", pci_name(priv->pdev)); + return rc; + } + msleep(1); + + rc = mwl8k_feed_fw_image(priv, ucode, ucode_len); + } else { + rc = mwl8k_load_fw_image(priv, ucode, ucode_len); + } + + if (rc) { + printk(KERN_ERR "%s: unable to load firmware data\n", + pci_name(priv->pdev)); + return rc; + } + + iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR); + msleep(1); + + loops = 200000; + do { + if (ioread32(priv->regs + MWL8K_HIU_INT_CODE) + == MWL8K_FWSTA_READY) + break; + udelay(1); + } while (--loops); + + return loops ? 0 : -ETIMEDOUT; +} + + +/* + * Defines shared between transmission and reception. + */ +/* HT control fields for firmware */ +struct ewc_ht_info { + __le16 control1; + __le16 control2; + __le16 control3; +} __attribute__((packed)); + +/* Firmware Station database operations */ +#define MWL8K_STA_DB_ADD_ENTRY 0 +#define MWL8K_STA_DB_MODIFY_ENTRY 1 +#define MWL8K_STA_DB_DEL_ENTRY 2 +#define MWL8K_STA_DB_FLUSH 3 + +/* Peer Entry flags - used to define the type of the peer node */ +#define MWL8K_PEER_TYPE_ACCESSPOINT 2 +#define MWL8K_PEER_TYPE_ADHOC_STATION 4 + +#define MWL8K_IEEE_LEGACY_DATA_RATES 12 +#define MWL8K_MCS_BITMAP_SIZE 16 +#define pad_size 16 + +struct peer_capability_info { + /* Peer type - AP vs. STA. */ + __u8 peer_type; + + /* Basic 802.11 capabilities from assoc resp. */ + __le16 basic_caps; + + /* Set if peer supports 802.11n high throughput (HT). */ + __u8 ht_support; + + /* Valid if HT is supported. */ + __le16 ht_caps; + __u8 extended_ht_caps; + struct ewc_ht_info ewc_info; + + /* Legacy rate table. Intersection of our rates and peer rates. */ + __u8 legacy_rates[MWL8K_IEEE_LEGACY_DATA_RATES]; + + /* HT rate table. Intersection of our rates and peer rates. */ + __u8 ht_rates[MWL8K_MCS_BITMAP_SIZE]; + __u8 pad[pad_size]; + + /* If set, interoperability mode, no proprietary extensions. */ + __u8 interop; + __u8 pad2; + __u8 station_id; + __le16 amsdu_enabled; +} __attribute__((packed)); + +/* Inline functions to manipulate QoS field in data descriptor. */ +static inline u16 mwl8k_qos_setbit_tid(u16 qos, u8 tid) +{ + u16 val_mask = 0x000f; + u16 qos_mask = ~val_mask; + + /* TID bits 0-3 */ + return (qos & qos_mask) | (tid & val_mask); +} + +static inline u16 mwl8k_qos_setbit_eosp(u16 qos) +{ + u16 val_mask = 1 << 4; + + /* End of Service Period Bit 4 */ + return qos | val_mask; +} + +static inline u16 mwl8k_qos_setbit_ack(u16 qos, u8 ack_policy) +{ + u16 val_mask = 0x3; + u8 shift = 5; + u16 qos_mask = ~(val_mask << shift); + + /* Ack Policy Bit 5-6 */ + return (qos & qos_mask) | ((ack_policy & val_mask) << shift); +} + +static inline u16 mwl8k_qos_setbit_amsdu(u16 qos) +{ + u16 val_mask = 1 << 7; + + /* AMSDU present Bit 7 */ + return qos | val_mask; +} + +static inline u16 mwl8k_qos_setbit_qlen(u16 qos, u8 len) +{ + u16 val_mask = 0xff; + u8 shift = 8; + u16 qos_mask = ~(val_mask << shift); + + /* Queue Length Bits 8-15 */ + return (qos & qos_mask) | ((len & val_mask) << shift); +} + +/* DMA header used by firmware and hardware. */ +struct mwl8k_dma_data { + __le16 fwlen; + struct ieee80211_hdr wh; +} __attribute__((packed)); + +/* Routines to add/remove DMA header from skb. */ +static inline int mwl8k_remove_dma_header(struct sk_buff *skb) +{ + struct mwl8k_dma_data *tr = (struct mwl8k_dma_data *)(skb->data); + void *dst, *src = &tr->wh; + __le16 fc = tr->wh.frame_control; + int hdrlen = ieee80211_hdrlen(fc); + u16 space = sizeof(struct mwl8k_dma_data) - hdrlen; + + dst = (void *)tr + space; + if (dst != src) { + memmove(dst, src, hdrlen); + skb_pull(skb, space); + } + + return 0; +} + +static inline struct sk_buff *mwl8k_add_dma_header(struct sk_buff *skb) +{ + struct ieee80211_hdr *wh; + u32 hdrlen, pktlen; + struct mwl8k_dma_data *tr; + + wh = (struct ieee80211_hdr *)skb->data; + hdrlen = ieee80211_hdrlen(wh->frame_control); + pktlen = skb->len; + + /* + * Copy up/down the 802.11 header; the firmware requires + * we present a 2-byte payload length followed by a + * 4-address header (w/o QoS), followed (optionally) by + * any WEP/ExtIV header (but only filled in for CCMP). + */ + if (hdrlen != sizeof(struct mwl8k_dma_data)) + skb_push(skb, sizeof(struct mwl8k_dma_data) - hdrlen); + + tr = (struct mwl8k_dma_data *)skb->data; + if (wh != &tr->wh) + memmove(&tr->wh, wh, hdrlen); + + /* Clear addr4 */ + memset(tr->wh.addr4, 0, IEEE80211_ADDR_LEN); + + /* + * Firmware length is the length of the fully formed "802.11 + * payload". That is, everything except for the 802.11 header. + * This includes all crypto material including the MIC. + */ + tr->fwlen = cpu_to_le16(pktlen - hdrlen); + + return skb; +} + + +/* + * Packet reception. + */ +#define MWL8K_RX_CTRL_KEY_INDEX_MASK 0x30 +#define MWL8K_RX_CTRL_OWNED_BY_HOST 0x02 +#define MWL8K_RX_CTRL_AMPDU 0x01 + +struct mwl8k_rx_desc { + __le16 pkt_len; + __u8 link_quality; + __u8 noise_level; + __le32 pkt_phys_addr; + __le32 next_rx_desc_phys_addr; + __le16 qos_control; + __le16 rate_info; + __le32 pad0[4]; + __u8 rssi; + __u8 channel; + __le16 pad1; + __u8 rx_ctrl; + __u8 rx_status; + __u8 pad2[2]; +} __attribute__((packed)); + +#define MWL8K_RX_DESCS 256 +#define MWL8K_RX_MAXSZ 3800 + +static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index) +{ + struct mwl8k_priv *priv = hw->priv; + struct mwl8k_rx_queue *rxq = priv->rxq + index; + int size; + int i; + + rxq->rx_desc_count = 0; + rxq->rx_head = 0; + rxq->rx_tail = 0; + + size = MWL8K_RX_DESCS * sizeof(struct mwl8k_rx_desc); + + rxq->rx_desc_area = + pci_alloc_consistent(priv->pdev, size, &rxq->rx_desc_dma); + if (rxq->rx_desc_area == NULL) { + printk(KERN_ERR "%s: failed to alloc RX descriptors\n", + priv->name); + return -ENOMEM; + } + memset(rxq->rx_desc_area, 0, size); + + rxq->rx_skb = kmalloc(MWL8K_RX_DESCS * + sizeof(*rxq->rx_skb), GFP_KERNEL); + if (rxq->rx_skb == NULL) { + printk(KERN_ERR "%s: failed to alloc RX skbuff list\n", + priv->name); + pci_free_consistent(priv->pdev, size, + rxq->rx_desc_area, rxq->rx_desc_dma); + return -ENOMEM; + } + memset(rxq->rx_skb, 0, MWL8K_RX_DESCS * sizeof(*rxq->rx_skb)); + + for (i = 0; i < MWL8K_RX_DESCS; i++) { + struct mwl8k_rx_desc *rx_desc; + int nexti; + + rx_desc = rxq->rx_desc_area + i; + nexti = (i + 1) % MWL8K_RX_DESCS; + + rx_desc->next_rx_desc_phys_addr = + cpu_to_le32(rxq->rx_desc_dma + + nexti * sizeof(*rx_desc)); + rx_desc->rx_ctrl = + cpu_to_le32(MWL8K_RX_CTRL_OWNED_BY_HOST); + } + + return 0; +} + +static int rxq_refill(struct ieee80211_hw *hw, int index, int limit) +{ + struct mwl8k_priv *priv = hw->priv; + struct mwl8k_rx_queue *rxq = priv->rxq + index; + int refilled; + + refilled = 0; + while (rxq->rx_desc_count < MWL8K_RX_DESCS && limit--) { + struct sk_buff *skb; + int rx; + + skb = dev_alloc_skb(MWL8K_RX_MAXSZ); + if (skb == NULL) + break; + + rxq->rx_desc_count++; + + rx = rxq->rx_tail; + rxq->rx_tail = (rx + 1) % MWL8K_RX_DESCS; + + rxq->rx_desc_area[rx].pkt_phys_addr = + cpu_to_le32(pci_map_single(priv->pdev, skb->data, + MWL8K_RX_MAXSZ, DMA_FROM_DEVICE)); + + rxq->rx_desc_area[rx].pkt_len = cpu_to_le16(MWL8K_RX_MAXSZ); + rxq->rx_skb[rx] = skb; + wmb(); + rxq->rx_desc_area[rx].rx_ctrl = 0; + + refilled++; + } + + return refilled; +} + +/* Must be called only when the card's reception is completely halted */ +static void mwl8k_rxq_deinit(struct ieee80211_hw *hw, int index) +{ + struct mwl8k_priv *priv = hw->priv; + struct mwl8k_rx_queue *rxq = priv->rxq + index; + int i; + + for (i = 0; i < MWL8K_RX_DESCS; i++) { + if (rxq->rx_skb[i] != NULL) { + unsigned long addr; + + addr = le32_to_cpu(rxq->rx_desc_area[i].pkt_phys_addr); + pci_unmap_single(priv->pdev, addr, MWL8K_RX_MAXSZ, + PCI_DMA_FROMDEVICE); + kfree_skb(rxq->rx_skb[i]); + rxq->rx_skb[i] = NULL; + } + } + + kfree(rxq->rx_skb); + rxq->rx_skb = NULL; + + pci_free_consistent(priv->pdev, + MWL8K_RX_DESCS * sizeof(struct mwl8k_rx_desc), + rxq->rx_desc_area, rxq->rx_desc_dma); + rxq->rx_desc_area = NULL; +} + + +/* + * Scan a list of BSSIDs to process for finalize join. + * Allows for extension to process multiple BSSIDs. + */ +static inline int +mwl8k_capture_bssid(struct mwl8k_priv *priv, struct ieee80211_hdr *wh) +{ + return priv->capture_beacon && + ieee80211_is_beacon(wh->frame_control) && + !compare_ether_addr(wh->addr3, priv->capture_bssid); +} + +static inline void mwl8k_save_beacon(struct mwl8k_priv *priv, + struct sk_buff *skb) +{ + priv->capture_beacon = false; + memset(priv->capture_bssid, 0, IEEE80211_ADDR_LEN); + + /* + * Use GFP_ATOMIC as rxq_process is called from + * the primary interrupt handler, memory allocation call + * must not sleep. + */ + priv->beacon_skb = skb_copy(skb, GFP_ATOMIC); + if (priv->beacon_skb != NULL) + queue_work(priv->config_wq, + &priv->finalize_join_worker); +} + +static int rxq_process(struct ieee80211_hw *hw, int index, int limit) +{ + struct mwl8k_priv *priv = hw->priv; + struct mwl8k_rx_queue *rxq = priv->rxq + index; + int processed; + + processed = 0; + while (rxq->rx_desc_count && limit--) { + struct mwl8k_rx_desc *rx_desc; + struct sk_buff *skb; + struct ieee80211_rx_status status; + unsigned long addr; + struct ieee80211_hdr *wh; + + rx_desc = rxq->rx_desc_area + rxq->rx_head; + if (!(rx_desc->rx_ctrl & MWL8K_RX_CTRL_OWNED_BY_HOST)) + break; + rmb(); + + skb = rxq->rx_skb[rxq->rx_head]; + rxq->rx_skb[rxq->rx_head] = NULL; + + rxq->rx_head = (rxq->rx_head + 1) % MWL8K_RX_DESCS; + rxq->rx_desc_count--; + + addr = le32_to_cpu(rx_desc->pkt_phys_addr); + pci_unmap_single(priv->pdev, addr, + MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE); + + skb_put(skb, le16_to_cpu(rx_desc->pkt_len)); + if (mwl8k_remove_dma_header(skb)) { + dev_kfree_skb(skb); + continue; + } + + wh = (struct ieee80211_hdr *)skb->data; + + /* + * Check for pending join operation. save a copy of + * the beacon and schedule a tasklet to send finalize + * join command to the firmware. + */ + if (mwl8k_capture_bssid(priv, wh)) + mwl8k_save_beacon(priv, skb); + + memset(&status, 0, sizeof(status)); + status.mactime = 0; + status.signal = -rx_desc->rssi; + status.noise = -rx_desc->noise_level; + status.qual = rx_desc->link_quality; + status.antenna = 1; + status.rate_idx = 1; + status.flag = 0; + status.band = IEEE80211_BAND_2GHZ; + status.freq = ieee80211_channel_to_frequency(rx_desc->channel); + ieee80211_rx_irqsafe(hw, skb, &status); + + processed++; + } + + return processed; +} + + +/* + * Packet transmission. + */ + +/* Transmit queue assignment. */ +enum { + MWL8K_WME_AC_BK = 0, /* background access */ + MWL8K_WME_AC_BE = 1, /* best effort access */ + MWL8K_WME_AC_VI = 2, /* video access */ + MWL8K_WME_AC_VO = 3, /* voice access */ +}; + +/* Transmit packet ACK policy */ +#define MWL8K_TXD_ACK_POLICY_NORMAL 0 +#define MWL8K_TXD_ACK_POLICY_NONE 1 +#define MWL8K_TXD_ACK_POLICY_NO_EXPLICIT 2 +#define MWL8K_TXD_ACK_POLICY_BLOCKACK 3 + +#define GET_TXQ(_ac) (\ + ((_ac) == WME_AC_VO) ? MWL8K_WME_AC_VO : \ + ((_ac) == WME_AC_VI) ? MWL8K_WME_AC_VI : \ + ((_ac) == WME_AC_BK) ? MWL8K_WME_AC_BK : \ + MWL8K_WME_AC_BE) + +#define MWL8K_TXD_STATUS_IDLE 0x00000000 +#define MWL8K_TXD_STATUS_USED 0x00000001 +#define MWL8K_TXD_STATUS_OK 0x00000001 +#define MWL8K_TXD_STATUS_OK_RETRY 0x00000002 +#define MWL8K_TXD_STATUS_OK_MORE_RETRY 0x00000004 +#define MWL8K_TXD_STATUS_MULTICAST_TX 0x00000008 +#define MWL8K_TXD_STATUS_BROADCAST_TX 0x00000010 +#define MWL8K_TXD_STATUS_FAILED_LINK_ERROR 0x00000020 +#define MWL8K_TXD_STATUS_FAILED_EXCEED_LIMIT 0x00000040 +#define MWL8K_TXD_STATUS_FAILED_AGING 0x00000080 +#define MWL8K_TXD_STATUS_HOST_CMD 0x40000000 +#define MWL8K_TXD_STATUS_FW_OWNED 0x80000000 +#define MWL8K_TXD_SOFTSTALE 0x80 +#define MWL8K_TXD_SOFTSTALE_MGMT_RETRY 0x01 + +struct mwl8k_tx_desc { + __le32 status; + __u8 data_rate; + __u8 tx_priority; + __le16 qos_control; + __le32 pkt_phys_addr; + __le16 pkt_len; + __u8 dest_MAC_addr[IEEE80211_ADDR_LEN]; + __le32 next_tx_desc_phys_addr; + __le32 reserved; + __le16 rate_info; + __u8 peer_id; + __u8 tx_frag_cnt; +} __attribute__((packed)); + +#define MWL8K_TX_DESCS 128 + +static int mwl8k_txq_init(struct ieee80211_hw *hw, int index) +{ + struct mwl8k_priv *priv = hw->priv; + struct mwl8k_tx_queue *txq = priv->txq + index; + int size; + int i; + + memset(&txq->tx_stats, 0, + sizeof(struct ieee80211_tx_queue_stats)); + txq->tx_stats.limit = MWL8K_TX_DESCS; + txq->tx_head = 0; + txq->tx_tail = 0; + + size = MWL8K_TX_DESCS * sizeof(struct mwl8k_tx_desc); + + txq->tx_desc_area = + pci_alloc_consistent(priv->pdev, size, &txq->tx_desc_dma); + if (txq->tx_desc_area == NULL) { + printk(KERN_ERR "%s: failed to alloc TX descriptors\n", + priv->name); + return -ENOMEM; + } + memset(txq->tx_desc_area, 0, size); + + txq->tx_skb = kmalloc(MWL8K_TX_DESCS * sizeof(*txq->tx_skb), + GFP_KERNEL); + if (txq->tx_skb == NULL) { + printk(KERN_ERR "%s: failed to alloc TX skbuff list\n", + priv->name); + pci_free_consistent(priv->pdev, size, + txq->tx_desc_area, txq->tx_desc_dma); + return -ENOMEM; + } + memset(txq->tx_skb, 0, MWL8K_TX_DESCS * sizeof(*txq->tx_skb)); + + for (i = 0; i < MWL8K_TX_DESCS; i++) { + struct mwl8k_tx_desc *tx_desc; + int nexti; + + tx_desc = txq->tx_desc_area + i; + nexti = (i + 1) % MWL8K_TX_DESCS; + + tx_desc->status = 0; + tx_desc->next_tx_desc_phys_addr = + cpu_to_le32(txq->tx_desc_dma + + nexti * sizeof(*tx_desc)); + } + + return 0; +} + +static inline void mwl8k_tx_start(struct mwl8k_priv *priv) +{ + iowrite32(MWL8K_H2A_INT_PPA_READY, + priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); + iowrite32(MWL8K_H2A_INT_DUMMY, + priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); + ioread32(priv->regs + MWL8K_HIU_INT_CODE); +} + +static inline int mwl8k_txq_busy(struct mwl8k_priv *priv) +{ + return priv->pending_tx_pkts; +} + +struct mwl8k_txq_info { + u32 fw_owned; + u32 drv_owned; + u32 unused; + u32 len; + u32 head; + u32 tail; +}; + +static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv, + struct mwl8k_txq_info txinfo[], + u32 num_queues) +{ + int count, desc, status; + struct mwl8k_tx_queue *txq; + struct mwl8k_tx_desc *tx_desc; + int ndescs = 0; + + memset(txinfo, 0, num_queues * sizeof(struct mwl8k_txq_info)); + spin_lock_bh(&priv->tx_lock); + for (count = 0; count < num_queues; count++) { + txq = priv->txq + count; + txinfo[count].len = txq->tx_stats.len; + txinfo[count].head = txq->tx_head; + txinfo[count].tail = txq->tx_tail; + for (desc = 0; desc < MWL8K_TX_DESCS; desc++) { + tx_desc = txq->tx_desc_area + desc; + status = le32_to_cpu(tx_desc->status); + + if (status & MWL8K_TXD_STATUS_FW_OWNED) + txinfo[count].fw_owned++; + else + txinfo[count].drv_owned++; + + if (tx_desc->pkt_len == 0) + txinfo[count].unused++; + } + } + spin_unlock_bh(&priv->tx_lock); + + return ndescs; +} + +static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms) +{ + u32 count = 0; + unsigned long timeout = 0; + struct mwl8k_priv *priv = hw->priv; + DECLARE_COMPLETION_ONSTACK(cmd_wait); + + might_sleep(); + + if (priv->tx_wait != NULL) + printk(KERN_ERR "WARNING Previous TXWaitEmpty instance\n"); + + spin_lock_bh(&priv->tx_lock); + count = mwl8k_txq_busy(priv); + if (count) { + priv->tx_wait = &cmd_wait; + if (priv->radio_state) + mwl8k_tx_start(priv); + } + spin_unlock_bh(&priv->tx_lock); + + if (count) { + struct mwl8k_txq_info txinfo[4]; + int index; + int newcount; + + timeout = wait_for_completion_timeout(&cmd_wait, + msecs_to_jiffies(delay_ms)); + if (timeout) + return 0; + + spin_lock_bh(&priv->tx_lock); + priv->tx_wait = NULL; + newcount = mwl8k_txq_busy(priv); + spin_unlock_bh(&priv->tx_lock); + + printk(KERN_ERR "%s(%u) TIMEDOUT:%ums Pend:%u-->%u\n", + __func__, __LINE__, delay_ms, count, newcount); + + mwl8k_scan_tx_ring(priv, txinfo, 4); + for (index = 0 ; index < 4; index++) + printk(KERN_ERR + "TXQ:%u L:%u H:%u T:%u FW:%u DRV:%u U:%u\n", + index, + txinfo[index].len, + txinfo[index].head, + txinfo[index].tail, + txinfo[index].fw_owned, + txinfo[index].drv_owned, + txinfo[index].unused); + return -ETIMEDOUT; + } + + return 0; +} + +#define MWL8K_TXD_OK (MWL8K_TXD_STATUS_OK | \ + MWL8K_TXD_STATUS_OK_RETRY | \ + MWL8K_TXD_STATUS_OK_MORE_RETRY) +#define MWL8K_TXD_SUCCESS(stat) ((stat) & MWL8K_TXD_OK) +#define MWL8K_TXD_FAIL_RETRY(stat) \ + ((stat) & (MWL8K_TXD_STATUS_FAILED_EXCEED_LIMIT)) + +static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) +{ + struct mwl8k_priv *priv = hw->priv; + struct mwl8k_tx_queue *txq = priv->txq + index; + int wake = 0; + + while (txq->tx_stats.len > 0) { + int tx; + int rc; + struct mwl8k_tx_desc *tx_desc; + unsigned long addr; + size_t size; + struct sk_buff *skb; + struct ieee80211_tx_info *info; + u32 status; + + rc = 0; + tx = txq->tx_head; + tx_desc = txq->tx_desc_area + tx; + + status = le32_to_cpu(tx_desc->status); + + if (status & MWL8K_TXD_STATUS_FW_OWNED) { + if (!force) + break; + tx_desc->status &= + ~cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED); + } + + txq->tx_head = (tx + 1) % MWL8K_TX_DESCS; + BUG_ON(txq->tx_stats.len == 0); + txq->tx_stats.len--; + priv->pending_tx_pkts--; + + addr = le32_to_cpu(tx_desc->pkt_phys_addr); + size = (u32)(le16_to_cpu(tx_desc->pkt_len)); + skb = txq->tx_skb[tx].skb; + txq->tx_skb[tx].skb = NULL; + + BUG_ON(skb == NULL); + pci_unmap_single(priv->pdev, addr, size, PCI_DMA_TODEVICE); + + rc = mwl8k_remove_dma_header(skb); + + /* Mark descriptor as unused */ + tx_desc->pkt_phys_addr = 0; + tx_desc->pkt_len = 0; + + if (txq->tx_skb[tx].clone) { + /* Replace with original skb + * before returning to stack + * as buffer has been cloned + */ + dev_kfree_skb(skb); + skb = txq->tx_skb[tx].clone; + txq->tx_skb[tx].clone = NULL; + } + + if (rc) { + /* Something has gone wrong here. + * Failed to remove DMA header. + * Print error message and drop packet. + */ + printk(KERN_ERR "%s: Error removing DMA header from " + "tx skb 0x%p.\n", priv->name, skb); + + dev_kfree_skb(skb); + continue; + } + + info = IEEE80211_SKB_CB(skb); + ieee80211_tx_info_clear_status(info); + + /* Convert firmware status stuff into tx_status */ + if (MWL8K_TXD_SUCCESS(status)) { + /* Transmit OK */ + info->flags |= IEEE80211_TX_STAT_ACK; + } + + ieee80211_tx_status_irqsafe(hw, skb); + + wake = !priv->inconfig && priv->radio_state; + } + + if (wake) + ieee80211_wake_queue(hw, index); +} + +/* must be called only when the card's transmit is completely halted */ +static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index) +{ + struct mwl8k_priv *priv = hw->priv; + struct mwl8k_tx_queue *txq = priv->txq + index; + + mwl8k_txq_reclaim(hw, index, 1); + + kfree(txq->tx_skb); + txq->tx_skb = NULL; + + pci_free_consistent(priv->pdev, + MWL8K_TX_DESCS * sizeof(struct mwl8k_tx_desc), + txq->tx_desc_area, txq->tx_desc_dma); + txq->tx_desc_area = NULL; +} + +static int +mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) +{ + struct mwl8k_priv *priv = hw->priv; + struct ieee80211_tx_info *tx_info; + struct ieee80211_hdr *wh; + struct mwl8k_tx_queue *txq; + struct mwl8k_tx_desc *tx; + struct mwl8k_dma_data *tr; + struct mwl8k_vif *mwl8k_vif; + struct sk_buff *org_skb = skb; + dma_addr_t dma; + u16 qos = 0; + bool qosframe = false, ampduframe = false; + bool mcframe = false, eapolframe = false; + bool amsduframe = false; + __le16 fc; + + txq = priv->txq + index; + tx = txq->tx_desc_area + txq->tx_tail; + + BUG_ON(txq->tx_skb[txq->tx_tail].skb != NULL); + + /* + * Append HW DMA header to start of packet. Drop packet if + * there is not enough space or a failure to unshare/unclone + * the skb. + */ + skb = mwl8k_add_dma_header(skb); + + if (skb == NULL) { + printk(KERN_DEBUG "%s: failed to prepend HW DMA " + "header, dropping TX frame.\n", priv->name); + dev_kfree_skb(org_skb); + return NETDEV_TX_OK; + } + + tx_info = IEEE80211_SKB_CB(skb); + mwl8k_vif = MWL8K_VIF(tx_info->control.vif); + tr = (struct mwl8k_dma_data *)skb->data; + wh = &tr->wh; + fc = wh->frame_control; + qosframe = ieee80211_is_data_qos(fc); + mcframe = is_multicast_ether_addr(wh->addr1); + ampduframe = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU); + + if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { + u16 seqno = mwl8k_vif->seqno; + wh->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); + wh->seq_ctrl |= cpu_to_le16(seqno << 4); + mwl8k_vif->seqno = seqno++ % 4096; + } + + if (qosframe) + qos = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(wh))); + + dma = pci_map_single(priv->pdev, skb->data, + skb->len, PCI_DMA_TODEVICE); + + if (pci_dma_mapping_error(priv->pdev, dma)) { + printk(KERN_DEBUG "%s: failed to dma map skb, " + "dropping TX frame.\n", priv->name); + + if (org_skb != NULL) + dev_kfree_skb(org_skb); + if (skb != NULL) + dev_kfree_skb(skb); + return NETDEV_TX_OK; + } + + /* Set desc header, cpu bit order. */ + tx->status = 0; + tx->data_rate = 0; + tx->tx_priority = index; + tx->qos_control = 0; + tx->rate_info = 0; + tx->peer_id = mwl8k_vif->peer_id; + + amsduframe = !!(qos & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT); + + /* Setup firmware control bit fields for each frame type. */ + if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) { + tx->data_rate = 0; + qos = mwl8k_qos_setbit_eosp(qos); + /* Set Queue size to unspecified */ + qos = mwl8k_qos_setbit_qlen(qos, 0xff); + } else if (ieee80211_is_data(fc)) { + tx->data_rate = 1; + if (mcframe) + tx->status |= MWL8K_TXD_STATUS_MULTICAST_TX; + + /* + * Tell firmware to not send EAPOL pkts in an + * aggregate. Verify against mac80211 tx path. If + * stack turns off AMPDU for an EAPOL frame this + * check will be removed. + */ + if (eapolframe) { + qos = mwl8k_qos_setbit_ack(qos, + MWL8K_TXD_ACK_POLICY_NORMAL); + } else { + /* Send pkt in an aggregate if AMPDU frame. */ + if (ampduframe) + qos = mwl8k_qos_setbit_ack(qos, + MWL8K_TXD_ACK_POLICY_BLOCKACK); + else + qos = mwl8k_qos_setbit_ack(qos, + MWL8K_TXD_ACK_POLICY_NORMAL); + + if (amsduframe) + qos = mwl8k_qos_setbit_amsdu(qos); + } + } + + /* Convert to little endian */ + tx->qos_control = cpu_to_le16(qos); + tx->status = cpu_to_le32(tx->status); + tx->pkt_phys_addr = cpu_to_le32(dma); + tx->pkt_len = cpu_to_le16(skb->len); + + txq->tx_skb[txq->tx_tail].skb = skb; + txq->tx_skb[txq->tx_tail].clone = + skb == org_skb ? NULL : org_skb; + + spin_lock_bh(&priv->tx_lock); + + tx->status = cpu_to_le32(MWL8K_TXD_STATUS_OK | + MWL8K_TXD_STATUS_FW_OWNED); + wmb(); + txq->tx_stats.len++; + priv->pending_tx_pkts++; + txq->tx_stats.count++; + txq->tx_tail++; + + if (txq->tx_tail == MWL8K_TX_DESCS) + txq->tx_tail = 0; + if (txq->tx_head == txq->tx_tail) + ieee80211_stop_queue(hw, index); + + if (priv->inconfig) { + /* + * Silently queue packet when we are in the middle of + * a config cycle. Notify firmware only if we are + * waiting for TXQs to empty. If a packet is sent + * before .config() is complete, perhaps it is better + * to drop the packet, as the channel is being changed + * and the packet will end up on the wrong channel. + */ + printk(KERN_ERR "%s(): WARNING TX activity while " + "in config\n", __func__); + + if (priv->tx_wait != NULL) + mwl8k_tx_start(priv); + } else + mwl8k_tx_start(priv); + + spin_unlock_bh(&priv->tx_lock); + + return NETDEV_TX_OK; +} + + +/* + * Command processing. + */ + +/* Timeout firmware commands after 2000ms */ +#define MWL8K_CMD_TIMEOUT_MS 2000 + +static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) +{ + DECLARE_COMPLETION_ONSTACK(cmd_wait); + struct mwl8k_priv *priv = hw->priv; + void __iomem *regs = priv->regs; + dma_addr_t dma_addr; + unsigned int dma_size; + int rc; + u16 __iomem *result; + unsigned long timeout = 0; + u8 buf[32]; + + cmd->result = 0xFFFF; + dma_size = le16_to_cpu(cmd->length); + dma_addr = pci_map_single(priv->pdev, cmd, dma_size, + PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(priv->pdev, dma_addr)) + return -ENOMEM; + + if (priv->hostcmd_wait != NULL) + printk(KERN_ERR "WARNING host command in progress\n"); + + spin_lock_irq(&priv->fw_lock); + priv->hostcmd_wait = &cmd_wait; + iowrite32(dma_addr, regs + MWL8K_HIU_GEN_PTR); + iowrite32(MWL8K_H2A_INT_DOORBELL, + regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); + iowrite32(MWL8K_H2A_INT_DUMMY, + regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); + spin_unlock_irq(&priv->fw_lock); + + timeout = wait_for_completion_timeout(&cmd_wait, + msecs_to_jiffies(MWL8K_CMD_TIMEOUT_MS)); + + result = &cmd->result; + if (!timeout) { + spin_lock_irq(&priv->fw_lock); + priv->hostcmd_wait = NULL; + spin_unlock_irq(&priv->fw_lock); + printk(KERN_ERR "%s: Command %s timeout after %u ms\n", + priv->name, + mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), + MWL8K_CMD_TIMEOUT_MS); + rc = -ETIMEDOUT; + } else { + rc = *result ? -EINVAL : 0; + if (rc) + printk(KERN_ERR "%s: Command %s error 0x%x\n", + priv->name, + mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), + *result); + } + + pci_unmap_single(priv->pdev, dma_addr, dma_size, + PCI_DMA_BIDIRECTIONAL); + return rc; +} + +/* + * GET_HW_SPEC. + */ +struct mwl8k_cmd_get_hw_spec { + struct mwl8k_cmd_pkt header; + __u8 hw_rev; + __u8 host_interface; + __le16 num_mcaddrs; + __u8 perm_addr[IEEE80211_ADDR_LEN]; + __le16 region_code; + __le32 fw_rev; + __le32 ps_cookie; + __le32 caps; + __u8 mcs_bitmap[16]; + __le32 rx_queue_ptr; + __le32 num_tx_queues; + __le32 tx_queue_ptrs[MWL8K_TX_QUEUES]; + __le32 caps2; + __le32 num_tx_desc_per_queue; + __le32 total_rx_desc; +} __attribute__((packed)); + +static int mwl8k_cmd_get_hw_spec(struct ieee80211_hw *hw) +{ + struct mwl8k_priv *priv = hw->priv; + struct mwl8k_cmd_get_hw_spec *cmd; + int rc; + int i; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_HW_SPEC); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + + memset(cmd->perm_addr, 0xff, sizeof(cmd->perm_addr)); + cmd->ps_cookie = cpu_to_le32(priv->cookie_dma); + cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rx_desc_dma); + cmd->num_tx_queues = MWL8K_TX_QUEUES; + for (i = 0; i < MWL8K_TX_QUEUES; i++) + cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].tx_desc_dma); + cmd->num_tx_desc_per_queue = MWL8K_TX_DESCS; + cmd->total_rx_desc = MWL8K_RX_DESCS; + + rc = mwl8k_post_cmd(hw, &cmd->header); + + if (!rc) { + SET_IEEE80211_PERM_ADDR(hw, cmd->perm_addr); + priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); + priv->fw_rev = cmd->fw_rev; + priv->hw_rev = cmd->hw_rev; + priv->region_code = le16_to_cpu(cmd->region_code); + } + + kfree(cmd); + return rc; +} + +/* + * CMD_MAC_MULTICAST_ADR. + */ +struct mwl8k_cmd_mac_multicast_adr { + struct mwl8k_cmd_pkt header; + __le16 action; + __le16 numaddr; + __u8 addr[1][IEEE80211_ADDR_LEN]; +}; + +#define MWL8K_ENABLE_RX_MULTICAST 0x000F +static int mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, + int mc_count, + struct dev_addr_list *mclist) +{ + struct mwl8k_cmd_mac_multicast_adr *cmd; + int index = 0; + int rc; + int size = sizeof(*cmd) + ((mc_count - 1) * IEEE80211_ADDR_LEN); + cmd = kzalloc(size, GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_MAC_MULTICAST_ADR); + cmd->header.length = cpu_to_le16(size); + cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST); + cmd->numaddr = cpu_to_le16(mc_count); + while ((index < mc_count) && mclist) { + if (mclist->da_addrlen != IEEE80211_ADDR_LEN) { + rc = -EINVAL; + goto mwl8k_cmd_mac_multicast_adr_exit; + } + memcpy(cmd->addr[index], mclist->da_addr, IEEE80211_ADDR_LEN); + index++; + mclist = mclist->next; + } + + rc = mwl8k_post_cmd(hw, &cmd->header); + +mwl8k_cmd_mac_multicast_adr_exit: + kfree(cmd); + return rc; +} + +/* + * CMD_802_11_GET_STAT. + */ +struct mwl8k_cmd_802_11_get_stat { + struct mwl8k_cmd_pkt header; + __le16 action; + __le32 stats[64]; +} __attribute__((packed)); + +#define MWL8K_STAT_ACK_FAILURE 9 +#define MWL8K_STAT_RTS_FAILURE 12 +#define MWL8K_STAT_FCS_ERROR 24 +#define MWL8K_STAT_RTS_SUCCESS 11 + +static int mwl8k_cmd_802_11_get_stat(struct ieee80211_hw *hw, + struct ieee80211_low_level_stats *stats) +{ + struct mwl8k_cmd_802_11_get_stat *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_STAT); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + cmd->action = cpu_to_le16(MWL8K_CMD_GET); + + rc = mwl8k_post_cmd(hw, &cmd->header); + if (!rc) { + stats->dot11ACKFailureCount = + le32_to_cpu(cmd->stats[MWL8K_STAT_ACK_FAILURE]); + stats->dot11RTSFailureCount = + le32_to_cpu(cmd->stats[MWL8K_STAT_RTS_FAILURE]); + stats->dot11FCSErrorCount = + le32_to_cpu(cmd->stats[MWL8K_STAT_FCS_ERROR]); + stats->dot11RTSSuccessCount = + le32_to_cpu(cmd->stats[MWL8K_STAT_RTS_SUCCESS]); + } + kfree(cmd); + + return rc; +} + +/* + * CMD_802_11_RADIO_CONTROL. + */ +struct mwl8k_cmd_802_11_radio_control { + struct mwl8k_cmd_pkt header; + __le16 action; + __le16 control; + __le16 radio_on; +} __attribute__((packed)); + +static int mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, int enable) +{ + struct mwl8k_priv *priv = hw->priv; + struct mwl8k_cmd_802_11_radio_control *cmd; + int rc; + + if (((enable & MWL8K_RADIO_ENABLE) == priv->radio_state) && + !(enable & MWL8K_RADIO_FORCE)) + return 0; + + enable &= MWL8K_RADIO_ENABLE; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_RADIO_CONTROL); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + cmd->action = cpu_to_le16(MWL8K_CMD_SET); + cmd->control = cpu_to_le16(priv->radio_preamble); + cmd->radio_on = cpu_to_le16(enable ? 0x0001 : 0x0000); + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + if (!rc) + priv->radio_state = enable; + + return rc; +} + +static int +mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble) +{ + struct mwl8k_priv *priv; + + if (hw == NULL || hw->priv == NULL) + return -EINVAL; + priv = hw->priv; + + priv->radio_preamble = (short_preamble ? + MWL8K_RADIO_SHORT_PREAMBLE : + MWL8K_RADIO_LONG_PREAMBLE); + + return mwl8k_cmd_802_11_radio_control(hw, + MWL8K_RADIO_ENABLE | MWL8K_RADIO_FORCE); +} + +/* + * CMD_802_11_RF_TX_POWER. + */ +#define MWL8K_TX_POWER_LEVEL_TOTAL 8 + +struct mwl8k_cmd_802_11_rf_tx_power { + struct mwl8k_cmd_pkt header; + __le16 action; + __le16 support_level; + __le16 current_level; + __le16 reserved; + __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL]; +} __attribute__((packed)); + +static int mwl8k_cmd_802_11_rf_tx_power(struct ieee80211_hw *hw, int dBm) +{ + struct mwl8k_cmd_802_11_rf_tx_power *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_RF_TX_POWER); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + cmd->action = cpu_to_le16(MWL8K_CMD_SET); + cmd->support_level = cpu_to_le16(dBm); + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + +/* + * CMD_SET_PRE_SCAN. + */ +struct mwl8k_cmd_set_pre_scan { + struct mwl8k_cmd_pkt header; +} __attribute__((packed)); + +static int mwl8k_cmd_set_pre_scan(struct ieee80211_hw *hw) +{ + struct mwl8k_cmd_set_pre_scan *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_PRE_SCAN); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + +/* + * CMD_SET_POST_SCAN. + */ +struct mwl8k_cmd_set_post_scan { + struct mwl8k_cmd_pkt header; + __le32 isibss; + __u8 bssid[IEEE80211_ADDR_LEN]; +} __attribute__((packed)); + +static int +mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 mac[IEEE80211_ADDR_LEN]) +{ + struct mwl8k_cmd_set_post_scan *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_POST_SCAN); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + cmd->isibss = 0; + memcpy(cmd->bssid, mac, IEEE80211_ADDR_LEN); + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + +/* + * CMD_SET_RF_CHANNEL. + */ +struct mwl8k_cmd_set_rf_channel { + struct mwl8k_cmd_pkt header; + __le16 action; + __u8 current_channel; + __le32 channel_flags; +} __attribute__((packed)); + +static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw, + struct ieee80211_channel *channel) +{ + struct mwl8k_cmd_set_rf_channel *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RF_CHANNEL); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + cmd->action = cpu_to_le16(MWL8K_CMD_SET); + cmd->current_channel = channel->hw_value; + if (channel->band == IEEE80211_BAND_2GHZ) + cmd->channel_flags = cpu_to_le32(0x00000081); + else + cmd->channel_flags = cpu_to_le32(0x00000000); + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + +/* + * CMD_SET_SLOT. + */ +struct mwl8k_cmd_set_slot { + struct mwl8k_cmd_pkt header; + __le16 action; + __u8 short_slot; +} __attribute__((packed)); + +static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, int slot_time) +{ + struct mwl8k_cmd_set_slot *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_SLOT); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + cmd->action = cpu_to_le16(MWL8K_CMD_SET); + cmd->short_slot = slot_time == MWL8K_SHORT_SLOTTIME ? 1 : 0; + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + +/* + * CMD_MIMO_CONFIG. + */ +struct mwl8k_cmd_mimo_config { + struct mwl8k_cmd_pkt header; + __le32 action; + __u8 rx_antenna_map; + __u8 tx_antenna_map; +} __attribute__((packed)); + +static int mwl8k_cmd_mimo_config(struct ieee80211_hw *hw, __u8 rx, __u8 tx) +{ + struct mwl8k_cmd_mimo_config *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_MIMO_CONFIG); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + cmd->action = cpu_to_le32((u32)MWL8K_CMD_SET); + cmd->rx_antenna_map = rx; + cmd->tx_antenna_map = tx; + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + +/* + * CMD_ENABLE_SNIFFER. + */ +struct mwl8k_cmd_enable_sniffer { + struct mwl8k_cmd_pkt header; + __le32 action; +} __attribute__((packed)); + +static int mwl8k_enable_sniffer(struct ieee80211_hw *hw, bool enable) +{ + struct mwl8k_cmd_enable_sniffer *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_ENABLE_SNIFFER); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + cmd->action = enable ? cpu_to_le32((u32)MWL8K_CMD_SET) : 0; + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + +/* + * CMD_SET_RATE_ADAPT_MODE. + */ +struct mwl8k_cmd_set_rate_adapt_mode { + struct mwl8k_cmd_pkt header; + __le16 action; + __le16 mode; +} __attribute__((packed)); + +static int mwl8k_cmd_setrateadaptmode(struct ieee80211_hw *hw, __u16 mode) +{ + struct mwl8k_cmd_set_rate_adapt_mode *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATEADAPT_MODE); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + cmd->action = cpu_to_le16(MWL8K_CMD_SET); + cmd->mode = cpu_to_le16(mode); + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + +/* + * CMD_SET_WMM_MODE. + */ +struct mwl8k_cmd_set_wmm { + struct mwl8k_cmd_pkt header; + __le16 action; +} __attribute__((packed)); + +static int mwl8k_set_wmm(struct ieee80211_hw *hw, bool enable) +{ + struct mwl8k_priv *priv = hw->priv; + struct mwl8k_cmd_set_wmm *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_WMM_MODE); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + cmd->action = enable ? cpu_to_le16(MWL8K_CMD_SET) : 0; + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + if (!rc) + priv->wmm_mode = enable; + + return rc; +} + +/* + * CMD_SET_RTS_THRESHOLD. + */ +struct mwl8k_cmd_rts_threshold { + struct mwl8k_cmd_pkt header; + __le16 action; + __le16 threshold; +} __attribute__((packed)); + +static int mwl8k_rts_threshold(struct ieee80211_hw *hw, + u16 action, u16 *threshold) +{ + struct mwl8k_cmd_rts_threshold *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_RTS_THRESHOLD); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + cmd->action = cpu_to_le16(action); + cmd->threshold = cpu_to_le16(*threshold); + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + +/* + * CMD_SET_EDCA_PARAMS. + */ +struct mwl8k_cmd_set_edca_params { + struct mwl8k_cmd_pkt header; + + /* See MWL8K_SET_EDCA_XXX below */ + __le16 action; + + /* TX opportunity in units of 32 us */ + __le16 txop; + + /* Log exponent of max contention period: 0...15*/ + __u8 log_cw_max; + + /* Log exponent of min contention period: 0...15 */ + __u8 log_cw_min; + + /* Adaptive interframe spacing in units of 32us */ + __u8 aifs; + + /* TX queue to configure */ + __u8 txq; +} __attribute__((packed)); + +#define MWL8K_GET_EDCA_ALL 0 +#define MWL8K_SET_EDCA_CW 0x01 +#define MWL8K_SET_EDCA_TXOP 0x02 +#define MWL8K_SET_EDCA_AIFS 0x04 + +#define MWL8K_SET_EDCA_ALL (MWL8K_SET_EDCA_CW | \ + MWL8K_SET_EDCA_TXOP | \ + MWL8K_SET_EDCA_AIFS) + +static int +mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, + __u16 cw_min, __u16 cw_max, + __u8 aifs, __u16 txop) +{ + struct mwl8k_cmd_set_edca_params *cmd; + u32 log_cw_min, log_cw_max; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + log_cw_min = ilog2(cw_min+1); + log_cw_max = ilog2(cw_max+1); + cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_EDCA_PARAMS); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + + cmd->action = cpu_to_le16(MWL8K_SET_EDCA_ALL); + cmd->txop = cpu_to_le16(txop); + cmd->log_cw_max = (u8)log_cw_max; + cmd->log_cw_min = (u8)log_cw_min; + cmd->aifs = aifs; + cmd->txq = qnum; + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + +/* + * CMD_FINALIZE_JOIN. + */ + +/* FJ beacon buffer size is compiled into the firmware. */ +#define MWL8K_FJ_BEACON_MAXLEN 128 + +struct mwl8k_cmd_finalize_join { + struct mwl8k_cmd_pkt header; + __le32 sleep_interval; /* Number of beacon periods to sleep */ + __u8 beacon_data[MWL8K_FJ_BEACON_MAXLEN]; +} __attribute__((packed)); + +static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame, + __u16 framelen, __u16 dtim) +{ + struct mwl8k_cmd_finalize_join *cmd; + struct ieee80211_mgmt *payload = frame; + u16 hdrlen; + u32 payload_len; + int rc; + + if (frame == NULL) + return -EINVAL; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_FINALIZE_JOIN); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + + if (dtim) + cmd->sleep_interval = cpu_to_le32(dtim); + else + cmd->sleep_interval = cpu_to_le32(1); + + hdrlen = ieee80211_hdrlen(payload->frame_control); + + payload_len = framelen > hdrlen ? framelen - hdrlen : 0; + + /* XXX TBD Might just have to abort and return an error */ + if (payload_len > MWL8K_FJ_BEACON_MAXLEN) + printk(KERN_ERR "%s(): WARNING: Incomplete beacon " + "sent to firmware. Sz=%u MAX=%u\n", __func__, + payload_len, MWL8K_FJ_BEACON_MAXLEN); + + payload_len = payload_len > MWL8K_FJ_BEACON_MAXLEN ? + MWL8K_FJ_BEACON_MAXLEN : payload_len; + + if (payload && payload_len) + memcpy(cmd->beacon_data, &payload->u.beacon, payload_len); + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + return rc; +} + +/* + * CMD_UPDATE_STADB. + */ +struct mwl8k_cmd_update_sta_db { + struct mwl8k_cmd_pkt header; + + /* See STADB_ACTION_TYPE */ + __le32 action; + + /* Peer MAC address */ + __u8 peer_addr[IEEE80211_ADDR_LEN]; + + __le32 reserved; + + /* Peer info - valid during add/update. */ + struct peer_capability_info peer_info; +} __attribute__((packed)); + +static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, __u32 action) +{ + struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); + struct ieee80211_bss_conf *info = &mv_vif->bss_info; + struct mwl8k_cmd_update_sta_db *cmd; + struct peer_capability_info *peer_info; + struct ieee80211_rate *bitrates = mv_vif->legacy_rates; + DECLARE_MAC_BUF(mac); + int rc; + __u8 count, *rates; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + + cmd->action = cpu_to_le32(action); + peer_info = &cmd->peer_info; + memcpy(cmd->peer_addr, mv_vif->bssid, IEEE80211_ADDR_LEN); + + switch (action) { + case MWL8K_STA_DB_ADD_ENTRY: + case MWL8K_STA_DB_MODIFY_ENTRY: + /* Build peer_info block */ + peer_info->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT; + peer_info->basic_caps = cpu_to_le16(info->assoc_capability); + peer_info->interop = 1; + peer_info->amsdu_enabled = 0; + + rates = peer_info->legacy_rates; + for (count = 0 ; count < mv_vif->legacy_nrates; count++) + rates[count] = bitrates[count].hw_value; + + rc = mwl8k_post_cmd(hw, &cmd->header); + if (rc == 0) + mv_vif->peer_id = peer_info->station_id; + + break; + + case MWL8K_STA_DB_DEL_ENTRY: + case MWL8K_STA_DB_FLUSH: + default: + rc = mwl8k_post_cmd(hw, &cmd->header); + if (rc == 0) + mv_vif->peer_id = 0; + break; + } + kfree(cmd); + + return rc; +} + +/* + * CMD_SET_AID. + */ +#define IEEE80211_OPMODE_DISABLED 0x00 +#define IEEE80211_OPMODE_NON_MEMBER_PROT_MODE 0x01 +#define IEEE80211_OPMODE_ONE_20MHZ_STA_PROT_MODE 0x02 +#define IEEE80211_OPMODE_HTMIXED_PROT_MODE 0x03 + +#define MWL8K_RATE_INDEX_MAX_ARRAY 14 + +#define MWL8K_FRAME_PROT_DISABLED 0x00 +#define MWL8K_FRAME_PROT_11G 0x07 +#define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02 +#define MWL8K_FRAME_PROT_11N_HT_ALL 0x06 +#define MWL8K_FRAME_PROT_MASK 0x07 + +struct mwl8k_cmd_update_set_aid { + struct mwl8k_cmd_pkt header; + __le16 aid; + + /* AP's MAC address (BSSID) */ + __u8 bssid[IEEE80211_ADDR_LEN]; + __le16 protection_mode; + __u8 supp_rates[MWL8K_RATE_INDEX_MAX_ARRAY]; +} __attribute__((packed)); + +static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); + struct ieee80211_bss_conf *info = &mv_vif->bss_info; + struct mwl8k_cmd_update_set_aid *cmd; + struct ieee80211_rate *bitrates = mv_vif->legacy_rates; + int count; + u16 prot_mode; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_AID); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + cmd->aid = cpu_to_le16(info->aid); + + memcpy(cmd->bssid, mv_vif->bssid, IEEE80211_ADDR_LEN); + + prot_mode = MWL8K_FRAME_PROT_DISABLED; + + if (info->use_cts_prot) { + prot_mode = MWL8K_FRAME_PROT_11G; + } else { + switch (info->ht.operation_mode & + IEEE80211_HT_OP_MODE_PROTECTION) { + case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ: + prot_mode = MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY; + break; + case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED: + prot_mode = MWL8K_FRAME_PROT_11N_HT_ALL; + break; + default: + prot_mode = MWL8K_FRAME_PROT_DISABLED; + break; + } + } + + cmd->protection_mode = cpu_to_le16(prot_mode); + + for (count = 0; count < mv_vif->legacy_nrates; count++) + cmd->supp_rates[count] = bitrates[count].hw_value; + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + +/* + * CMD_SET_RATE. + */ +struct mwl8k_cmd_update_rateset { + struct mwl8k_cmd_pkt header; + __u8 legacy_rates[MWL8K_RATE_INDEX_MAX_ARRAY]; + + /* Bitmap for supported MCS codes. */ + __u8 mcs_set[MWL8K_IEEE_LEGACY_DATA_RATES]; + __u8 reserved[MWL8K_IEEE_LEGACY_DATA_RATES]; +} __attribute__((packed)); + +static int mwl8k_update_rateset(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); + struct mwl8k_cmd_update_rateset *cmd; + struct ieee80211_rate *bitrates = mv_vif->legacy_rates; + int count; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + + for (count = 0; count < mv_vif->legacy_nrates; count++) + cmd->legacy_rates[count] = bitrates[count].hw_value; + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + +/* + * CMD_USE_FIXED_RATE. + */ +#define MWL8K_RATE_TABLE_SIZE 8 +#define MWL8K_UCAST_RATE 0 +#define MWL8K_MCAST_RATE 1 +#define MWL8K_BCAST_RATE 2 + +#define MWL8K_USE_FIXED_RATE 0x0001 +#define MWL8K_USE_AUTO_RATE 0x0002 + +struct mwl8k_rate_entry { + /* Set to 1 if HT rate, 0 if legacy. */ + __le32 is_ht_rate; + + /* Set to 1 to use retry_count field. */ + __le32 enable_retry; + + /* Specified legacy rate or MCS. */ + __le32 rate; + + /* Number of allowed retries. */ + __le32 retry_count; +} __attribute__((packed)); + +struct mwl8k_rate_table { + /* 1 to allow specified rate and below */ + __le32 allow_rate_drop; + __le32 num_rates; + struct mwl8k_rate_entry rate_entry[MWL8K_RATE_TABLE_SIZE]; +} __attribute__((packed)); + +struct mwl8k_cmd_use_fixed_rate { + struct mwl8k_cmd_pkt header; + __le32 action; + struct mwl8k_rate_table rate_table; + + /* Unicast, Broadcast or Multicast */ + __le32 rate_type; + __le32 reserved1; + __le32 reserved2; +} __attribute__((packed)); + +static int mwl8k_cmd_use_fixed_rate(struct ieee80211_hw *hw, + u32 action, u32 rate_type, struct mwl8k_rate_table *rate_table) +{ + struct mwl8k_cmd_use_fixed_rate *cmd; + int count; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_USE_FIXED_RATE); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + + cmd->action = cpu_to_le32(action); + cmd->rate_type = cpu_to_le32(rate_type); + + if (rate_table != NULL) { + /* Copy over each field manually so + * that bitflipping can be done + */ + cmd->rate_table.allow_rate_drop = + cpu_to_le32(rate_table->allow_rate_drop); + cmd->rate_table.num_rates = + cpu_to_le32(rate_table->num_rates); + + for (count = 0; count < rate_table->num_rates; count++) { + struct mwl8k_rate_entry *dst = + &cmd->rate_table.rate_entry[count]; + struct mwl8k_rate_entry *src = + &rate_table->rate_entry[count]; + + dst->is_ht_rate = cpu_to_le32(src->is_ht_rate); + dst->enable_retry = cpu_to_le32(src->enable_retry); + dst->rate = cpu_to_le32(src->rate); + dst->retry_count = cpu_to_le32(src->retry_count); + } + } + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + + +/* + * Interrupt handling. + */ +static irqreturn_t mwl8k_interrupt(int irq, void *dev_id) +{ + struct ieee80211_hw *hw = dev_id; + struct mwl8k_priv *priv = hw->priv; + u32 status; + + status = ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); + iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); + + status &= priv->int_mask; + if (!status) + return IRQ_NONE; + + if (status & MWL8K_A2H_INT_TX_DONE) + tasklet_schedule(&priv->tx_reclaim_task); + + if (status & MWL8K_A2H_INT_RX_READY) { + while (rxq_process(hw, 0, 1)) + rxq_refill(hw, 0, 1); + } + + if (status & MWL8K_A2H_INT_OPC_DONE) { + if (priv->hostcmd_wait != NULL) { + complete(priv->hostcmd_wait); + priv->hostcmd_wait = NULL; + } + } + + if (status & MWL8K_A2H_INT_QUEUE_EMPTY) { + if (!priv->inconfig && + priv->radio_state && + mwl8k_txq_busy(priv)) + mwl8k_tx_start(priv); + } + + return IRQ_HANDLED; +} + + +/* + * Core driver operations. + */ +static int mwl8k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct mwl8k_priv *priv = hw->priv; + int index = skb_get_queue_mapping(skb); + int rc; + + if (priv->current_channel == NULL) { + printk(KERN_DEBUG "%s: dropped TX frame since radio " + "disabled\n", priv->name); + dev_kfree_skb(skb); + return NETDEV_TX_OK; + } + + rc = mwl8k_txq_xmit(hw, index, skb); + + return rc; +} + +struct mwl8k_work_struct { + /* Initialized by mwl8k_queue_work(). */ + struct work_struct wt; + + /* Required field passed in to mwl8k_queue_work(). */ + struct ieee80211_hw *hw; + + /* Required field passed in to mwl8k_queue_work(). */ + int (*wfunc)(struct work_struct *w); + + /* Initialized by mwl8k_queue_work(). */ + struct completion *cmd_wait; + + /* Result code. */ + int rc; + + /* + * Optional field. Refer to explanation of MWL8K_WQ_XXX_XXX + * flags for explanation. Defaults to MWL8K_WQ_DEFAULT_OPTIONS. + */ + u32 options; + + /* Optional field. Defaults to MWL8K_CONFIG_TIMEOUT_MS. */ + unsigned long timeout_ms; + + /* Optional field. Defaults to MWL8K_WQ_TXWAIT_ATTEMPTS. */ + u32 txwait_attempts; + + /* Optional field. Defaults to MWL8K_TXWAIT_MS. */ + u32 tx_timeout_ms; + u32 step; +}; + +/* Flags controlling behavior of config queue requests */ + +/* Caller spins while waiting for completion. */ +#define MWL8K_WQ_SPIN 0x00000001 + +/* Wait for TX queues to empty before proceeding with configuration. */ +#define MWL8K_WQ_TX_WAIT_EMPTY 0x00000002 + +/* Queue request and return immediately. */ +#define MWL8K_WQ_POST_REQUEST 0x00000004 + +/* + * Caller sleeps and waits for task complete notification. + * Do not use in atomic context. + */ +#define MWL8K_WQ_SLEEP 0x00000008 + +/* Free work struct when task is done. */ +#define MWL8K_WQ_FREE_WORKSTRUCT 0x00000010 + +/* + * Config request is queued and returns to caller imediately. Use + * this in atomic context. Work struct is freed by mwl8k_queue_work() + * when this flag is set. + */ +#define MWL8K_WQ_QUEUE_ONLY (MWL8K_WQ_POST_REQUEST | \ + MWL8K_WQ_FREE_WORKSTRUCT) + +/* Default work queue behavior is to sleep and wait for tx completion. */ +#define MWL8K_WQ_DEFAULT_OPTIONS (MWL8K_WQ_SLEEP | MWL8K_WQ_TX_WAIT_EMPTY) + +/* + * Default config request timeout. Add adjustments to make sure the + * config thread waits long enough for both tx wait and cmd wait before + * timing out. + */ + +/* Time to wait for all TXQs to drain. TX Doorbell is pressed each time. */ +#define MWL8K_TXWAIT_TIMEOUT_MS 1000 + +/* Default number of TX wait attempts. */ +#define MWL8K_WQ_TXWAIT_ATTEMPTS 4 + +/* Total time to wait for TXQ to drain. */ +#define MWL8K_TXWAIT_MS (MWL8K_TXWAIT_TIMEOUT_MS * \ + MWL8K_WQ_TXWAIT_ATTEMPTS) + +/* Scheduling slop. */ +#define MWL8K_OS_SCHEDULE_OVERHEAD_MS 200 + +#define MWL8K_CONFIG_TIMEOUT_MS (MWL8K_CMD_TIMEOUT_MS + \ + MWL8K_TXWAIT_MS + \ + MWL8K_OS_SCHEDULE_OVERHEAD_MS) + +static void mwl8k_config_thread(struct work_struct *wt) +{ + struct mwl8k_work_struct *worker = (struct mwl8k_work_struct *)wt; + struct ieee80211_hw *hw = worker->hw; + struct mwl8k_priv *priv = hw->priv; + int rc = 0; + + spin_lock_irq(&priv->tx_lock); + priv->inconfig = true; + spin_unlock_irq(&priv->tx_lock); + + ieee80211_stop_queues(hw); + + /* + * Wait for host queues to drain before doing PHY + * reconfiguration. This avoids interrupting any in-flight + * DMA transfers to the hardware. + */ + if (worker->options & MWL8K_WQ_TX_WAIT_EMPTY) { + u32 timeout; + u32 time_remaining; + u32 iter; + u32 tx_wait_attempts = worker->txwait_attempts; + + time_remaining = worker->tx_timeout_ms; + if (!tx_wait_attempts) + tx_wait_attempts = 1; + + timeout = worker->tx_timeout_ms/tx_wait_attempts; + if (!timeout) + timeout = 1; + + iter = tx_wait_attempts; + do { + int wait_time; + + if (time_remaining > timeout) { + time_remaining -= timeout; + wait_time = timeout; + } else + wait_time = time_remaining; + + if (!wait_time) + wait_time = 1; + + rc = mwl8k_tx_wait_empty(hw, wait_time); + if (rc) + printk(KERN_ERR "%s() txwait timeout=%ums " + "Retry:%u/%u\n", __func__, timeout, + tx_wait_attempts - iter + 1, + tx_wait_attempts); + + } while (rc && --iter); + + rc = iter ? 0 : -ETIMEDOUT; + } + if (!rc) + rc = worker->wfunc(wt); + + spin_lock_irq(&priv->tx_lock); + priv->inconfig = false; + if (priv->pending_tx_pkts && priv->radio_state) + mwl8k_tx_start(priv); + spin_unlock_irq(&priv->tx_lock); + ieee80211_wake_queues(hw); + + worker->rc = rc; + if (worker->options & MWL8K_WQ_SLEEP) + complete(worker->cmd_wait); + + if (worker->options & MWL8K_WQ_FREE_WORKSTRUCT) + kfree(wt); +} + +static int mwl8k_queue_work(struct ieee80211_hw *hw, + struct mwl8k_work_struct *worker, + struct workqueue_struct *wqueue, + int (*wfunc)(struct work_struct *w)) +{ + unsigned long timeout = 0; + int rc = 0; + + DECLARE_COMPLETION_ONSTACK(cmd_wait); + + if (!worker->timeout_ms) + worker->timeout_ms = MWL8K_CONFIG_TIMEOUT_MS; + + if (!worker->options) + worker->options = MWL8K_WQ_DEFAULT_OPTIONS; + + if (!worker->txwait_attempts) + worker->txwait_attempts = MWL8K_WQ_TXWAIT_ATTEMPTS; + + if (!worker->tx_timeout_ms) + worker->tx_timeout_ms = MWL8K_TXWAIT_MS; + + worker->hw = hw; + worker->cmd_wait = &cmd_wait; + worker->rc = 1; + worker->wfunc = wfunc; + + INIT_WORK(&worker->wt, mwl8k_config_thread); + queue_work(wqueue, &worker->wt); + + if (worker->options & MWL8K_WQ_POST_REQUEST) { + rc = 0; + } else { + if (worker->options & MWL8K_WQ_SPIN) { + timeout = worker->timeout_ms; + while (timeout && (worker->rc > 0)) { + mdelay(1); + timeout--; + } + } else if (worker->options & MWL8K_WQ_SLEEP) + timeout = wait_for_completion_timeout(&cmd_wait, + msecs_to_jiffies(worker->timeout_ms)); + + if (timeout) + rc = worker->rc; + else { + cancel_work_sync(&worker->wt); + rc = -ETIMEDOUT; + } + } + + return rc; +} + +struct mwl8k_start_worker { + struct mwl8k_work_struct header; +}; + +static int mwl8k_start_wt(struct work_struct *wt) +{ + struct mwl8k_start_worker *worker = (struct mwl8k_start_worker *)wt; + struct ieee80211_hw *hw = worker->header.hw; + struct mwl8k_priv *priv = hw->priv; + int rc = 0; + + if (priv->vif != NULL) { + rc = -EIO; + goto mwl8k_start_exit; + } + + /* Turn on radio */ + if (mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_ENABLE)) { + rc = -EIO; + goto mwl8k_start_exit; + } + + /* Purge TX/RX HW queues */ + if (mwl8k_cmd_set_pre_scan(hw)) { + rc = -EIO; + goto mwl8k_start_exit; + } + + if (mwl8k_cmd_set_post_scan(hw, "\x00\x00\x00\x00\x00\x00")) { + rc = -EIO; + goto mwl8k_start_exit; + } + + /* Enable firmware rate adaptation */ + if (mwl8k_cmd_setrateadaptmode(hw, 0)) { + rc = -EIO; + goto mwl8k_start_exit; + } + + /* Disable WMM. WMM gets enabled when stack sends WMM parms */ + if (mwl8k_set_wmm(hw, MWL8K_WMM_DISABLE)) { + rc = -EIO; + goto mwl8k_start_exit; + } + + /* Disable sniffer mode */ + if (mwl8k_enable_sniffer(hw, 0)) + rc = -EIO; + +mwl8k_start_exit: + return rc; +} + +static int mwl8k_start(struct ieee80211_hw *hw) +{ + struct mwl8k_start_worker *worker; + struct mwl8k_priv *priv = hw->priv; + int rc; + + /* Enable tx reclaim tasklet */ + tasklet_enable(&priv->tx_reclaim_task); + + rc = request_irq(priv->pdev->irq, &mwl8k_interrupt, + IRQF_SHARED, MWL8K_NAME, hw); + if (rc) { + printk(KERN_ERR "%s: failed to register IRQ handler\n", + priv->name); + rc = -EIO; + goto mwl8k_start_disable_tasklet; + } + + /* Enable interrupts */ + iowrite32(priv->int_mask, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); + + worker = kzalloc(sizeof(*worker), GFP_KERNEL); + if (worker == NULL) { + rc = -ENOMEM; + goto mwl8k_start_disable_irq; + } + + rc = mwl8k_queue_work(hw, &worker->header, + priv->config_wq, mwl8k_start_wt); + kfree(worker); + if (!rc) + return rc; + + if (rc == -ETIMEDOUT) + printk(KERN_ERR "%s() timed out\n", __func__); + + rc = -EIO; + +mwl8k_start_disable_irq: + spin_lock_irq(&priv->tx_lock); + iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); + spin_unlock_irq(&priv->tx_lock); + free_irq(priv->pdev->irq, hw); + +mwl8k_start_disable_tasklet: + tasklet_disable(&priv->tx_reclaim_task); + + return rc; +} + +struct mwl8k_stop_worker { + struct mwl8k_work_struct header; +}; + +static int mwl8k_stop_wt(struct work_struct *wt) +{ + struct mwl8k_stop_worker *worker = (struct mwl8k_stop_worker *)wt; + struct ieee80211_hw *hw = worker->header.hw; + int rc; + + rc = mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_DISABLE); + + return rc; +} + +static void mwl8k_stop(struct ieee80211_hw *hw) +{ + int rc; + struct mwl8k_stop_worker *worker; + struct mwl8k_priv *priv = hw->priv; + int i; + + if (priv->vif != NULL) + return; + + ieee80211_stop_queues(hw); + + worker = kzalloc(sizeof(*worker), GFP_KERNEL); + if (worker == NULL) + return; + + rc = mwl8k_queue_work(hw, &worker->header, + priv->config_wq, mwl8k_stop_wt); + kfree(worker); + if (rc == -ETIMEDOUT) + printk(KERN_ERR "%s() timed out\n", __func__); + + /* Disable interrupts */ + spin_lock_irq(&priv->tx_lock); + iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); + spin_unlock_irq(&priv->tx_lock); + free_irq(priv->pdev->irq, hw); + + /* Stop finalize join worker */ + cancel_work_sync(&priv->finalize_join_worker); + if (priv->beacon_skb != NULL) + dev_kfree_skb(priv->beacon_skb); + + /* Stop tx reclaim tasklet */ + tasklet_disable(&priv->tx_reclaim_task); + + /* Stop config thread */ + flush_workqueue(priv->config_wq); + + /* Return all skbs to mac80211 */ + for (i = 0; i < MWL8K_TX_QUEUES; i++) + mwl8k_txq_reclaim(hw, i, 1); +} + +static int mwl8k_add_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf) +{ + struct mwl8k_priv *priv = hw->priv; + struct mwl8k_vif *mwl8k_vif; + + /* + * We only support one active interface at a time. + */ + if (priv->vif != NULL) + return -EBUSY; + + /* + * We only support managed interfaces for now. + */ + if (conf->type != NL80211_IFTYPE_STATION && + conf->type != NL80211_IFTYPE_MONITOR) + return -EINVAL; + + /* Clean out driver private area */ + mwl8k_vif = MWL8K_VIF(conf->vif); + memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); + + /* Save the mac address */ + memcpy(mwl8k_vif->mac_addr, conf->mac_addr, IEEE80211_ADDR_LEN); + + /* Back pointer to parent config block */ + mwl8k_vif->priv = priv; + + /* Setup initial PHY parameters */ + memcpy(mwl8k_vif->legacy_rates , + priv->rates, sizeof(mwl8k_vif->legacy_rates)); + mwl8k_vif->legacy_nrates = ARRAY_SIZE(priv->rates); + + /* Set Initial sequence number to zero */ + mwl8k_vif->seqno = 0; + + priv->vif = conf->vif; + priv->current_channel = NULL; + + return 0; +} + +static void mwl8k_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf) +{ + struct mwl8k_priv *priv = hw->priv; + + if (priv->vif == NULL) + return; + + priv->vif = NULL; +} + +struct mwl8k_config_worker { + struct mwl8k_work_struct header; + u32 changed; +}; + +static int mwl8k_config_wt(struct work_struct *wt) +{ + struct mwl8k_config_worker *worker = + (struct mwl8k_config_worker *)wt; + struct ieee80211_hw *hw = worker->header.hw; + struct ieee80211_conf *conf = &hw->conf; + struct mwl8k_priv *priv = hw->priv; + int rc = 0; + + if (!conf->radio_enabled) { + mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_DISABLE); + priv->current_channel = NULL; + rc = 0; + goto mwl8k_config_exit; + } + + if (mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_ENABLE)) { + rc = -EINVAL; + goto mwl8k_config_exit; + } + + priv->current_channel = conf->channel; + + if (mwl8k_cmd_set_rf_channel(hw, conf->channel)) { + rc = -EINVAL; + goto mwl8k_config_exit; + } + + if (conf->power_level > 18) + conf->power_level = 18; + if (mwl8k_cmd_802_11_rf_tx_power(hw, conf->power_level)) { + rc = -EINVAL; + goto mwl8k_config_exit; + } + + if (mwl8k_cmd_mimo_config(hw, 0x7, 0x7)) + rc = -EINVAL; + +mwl8k_config_exit: + return rc; +} + +static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) +{ + int rc = 0; + struct mwl8k_config_worker *worker; + struct mwl8k_priv *priv = hw->priv; + + worker = kzalloc(sizeof(*worker), GFP_KERNEL); + if (worker == NULL) + return -ENOMEM; + + worker->changed = changed; + rc = mwl8k_queue_work(hw, &worker->header, + priv->config_wq, mwl8k_config_wt); + if (rc == -ETIMEDOUT) { + printk(KERN_ERR "%s() timed out.\n", __func__); + rc = -EINVAL; + } + + kfree(worker); + + /* + * mac80211 will crash on anything other than -EINVAL on + * error. Looks like wireless extensions which calls mac80211 + * may be the actual culprit... + */ + return rc ? -EINVAL : 0; +} + +static int mwl8k_config_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_if_conf *conf) +{ + struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); + u32 changed = conf->changed; + + if (changed & IEEE80211_IFCC_BSSID) + memcpy(mv_vif->bssid, conf->bssid, IEEE80211_ADDR_LEN); + + return 0; +} + +struct mwl8k_bss_info_changed_worker { + struct mwl8k_work_struct header; + struct ieee80211_vif *vif; + struct ieee80211_bss_conf *info; + u32 changed; +}; + +static int mwl8k_bss_info_changed_wt(struct work_struct *wt) +{ + struct mwl8k_bss_info_changed_worker *worker = + (struct mwl8k_bss_info_changed_worker *)wt; + struct ieee80211_hw *hw = worker->header.hw; + struct ieee80211_vif *vif = worker->vif; + struct ieee80211_bss_conf *info = worker->info; + u32 changed; + int rc; + + struct mwl8k_priv *priv = hw->priv; + struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); + + changed = worker->changed; + priv->capture_beacon = false; + + if (info->assoc) { + memcpy(&mwl8k_vif->bss_info, info, + sizeof(struct ieee80211_bss_conf)); + + /* Install rates */ + if (mwl8k_update_rateset(hw, vif)) + goto mwl8k_bss_info_changed_exit; + + /* Turn on rate adaptation */ + if (mwl8k_cmd_use_fixed_rate(hw, MWL8K_USE_AUTO_RATE, + MWL8K_UCAST_RATE, NULL)) + goto mwl8k_bss_info_changed_exit; + + /* Set radio preamble */ + if (mwl8k_set_radio_preamble(hw, + info->use_short_preamble)) + goto mwl8k_bss_info_changed_exit; + + /* Set slot time */ + if (mwl8k_cmd_set_slot(hw, info->use_short_slot ? + MWL8K_SHORT_SLOTTIME : MWL8K_LONG_SLOTTIME)) + goto mwl8k_bss_info_changed_exit; + + /* Update peer rate info */ + if (mwl8k_cmd_update_sta_db(hw, vif, + MWL8K_STA_DB_MODIFY_ENTRY)) + goto mwl8k_bss_info_changed_exit; + + /* Set AID */ + if (mwl8k_cmd_set_aid(hw, vif)) + goto mwl8k_bss_info_changed_exit; + + /* + * Finalize the join. Tell rx handler to process + * next beacon from our BSSID. + */ + memcpy(priv->capture_bssid, + mwl8k_vif->bssid, IEEE80211_ADDR_LEN); + priv->capture_beacon = true; + } else { + mwl8k_cmd_update_sta_db(hw, vif, MWL8K_STA_DB_DEL_ENTRY); + memset(&mwl8k_vif->bss_info, 0, + sizeof(struct ieee80211_bss_conf)); + memset(mwl8k_vif->bssid, 0, IEEE80211_ADDR_LEN); + } + +mwl8k_bss_info_changed_exit: + rc = 0; + return rc; +} + +static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, + u32 changed) +{ + struct mwl8k_bss_info_changed_worker *worker; + struct mwl8k_priv *priv = hw->priv; + int rc; + + if ((changed & BSS_CHANGED_ASSOC) == 0) + return; + + worker = kzalloc(sizeof(*worker), GFP_KERNEL); + if (worker == NULL) + return; + + worker->vif = vif; + worker->info = info; + worker->changed = changed; + rc = mwl8k_queue_work(hw, &worker->header, + priv->config_wq, + mwl8k_bss_info_changed_wt); + kfree(worker); + if (rc == -ETIMEDOUT) + printk(KERN_ERR "%s() timed out\n", __func__); +} + +struct mwl8k_configure_filter_worker { + struct mwl8k_work_struct header; + unsigned int changed_flags; + unsigned int *total_flags; + int mc_count; + struct dev_addr_list *mclist; +}; + +#define MWL8K_SUPPORTED_IF_FLAGS FIF_BCN_PRBRESP_PROMISC + +static int mwl8k_configure_filter_wt(struct work_struct *wt) +{ + struct mwl8k_configure_filter_worker *worker = + (struct mwl8k_configure_filter_worker *)wt; + + struct ieee80211_hw *hw = worker->header.hw; + unsigned int changed_flags = worker->changed_flags; + unsigned int *total_flags = worker->total_flags; + int mc_count = worker->mc_count; + struct dev_addr_list *mclist = worker->mclist; + + struct mwl8k_priv *priv = hw->priv; + struct mwl8k_vif *mv_vif; + int rc = 0; + + if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { + if (*total_flags & FIF_BCN_PRBRESP_PROMISC) + rc = mwl8k_cmd_set_pre_scan(hw); + else { + mv_vif = MWL8K_VIF(priv->vif); + rc = mwl8k_cmd_set_post_scan(hw, mv_vif->bssid); + } + } + + if (rc) + goto mwl8k_configure_filter_exit; + if (mc_count) { + mc_count = mc_count < priv->num_mcaddrs ? + mc_count : priv->num_mcaddrs; + rc = mwl8k_cmd_mac_multicast_adr(hw, mc_count, mclist); + if (rc) + printk(KERN_ERR + "%s()Error setting multicast addresses\n", + __func__); + } + +mwl8k_configure_filter_exit: + return rc; +} + +static void mwl8k_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + int mc_count, + struct dev_addr_list *mclist) +{ + + struct mwl8k_configure_filter_worker *worker; + struct mwl8k_priv *priv = hw->priv; + + /* Clear unsupported feature flags */ + *total_flags &= MWL8K_SUPPORTED_IF_FLAGS; + + if (!(changed_flags & MWL8K_SUPPORTED_IF_FLAGS) && !mc_count) + return; + + worker = kzalloc(sizeof(*worker), GFP_ATOMIC); + if (worker == NULL) + return; + + worker->header.options = MWL8K_WQ_QUEUE_ONLY | MWL8K_WQ_TX_WAIT_EMPTY; + worker->changed_flags = changed_flags; + worker->total_flags = total_flags; + worker->mc_count = mc_count; + worker->mclist = mclist; + + mwl8k_queue_work(hw, &worker->header, priv->config_wq, + mwl8k_configure_filter_wt); +} + +struct mwl8k_set_rts_threshold_worker { + struct mwl8k_work_struct header; + u32 value; +}; + +static int mwl8k_set_rts_threshold_wt(struct work_struct *wt) +{ + struct mwl8k_set_rts_threshold_worker *worker = + (struct mwl8k_set_rts_threshold_worker *)wt; + + struct ieee80211_hw *hw = worker->header.hw; + u16 threshold = (u16)(worker->value); + int rc; + + rc = mwl8k_rts_threshold(hw, MWL8K_CMD_SET, &threshold); + + return rc; +} + +static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) +{ + int rc; + struct mwl8k_set_rts_threshold_worker *worker; + struct mwl8k_priv *priv = hw->priv; + + worker = kzalloc(sizeof(*worker), GFP_KERNEL); + if (worker == NULL) + return -ENOMEM; + + worker->value = value; + + rc = mwl8k_queue_work(hw, &worker->header, + priv->config_wq, + mwl8k_set_rts_threshold_wt); + kfree(worker); + + if (rc == -ETIMEDOUT) { + printk(KERN_ERR "%s() timed out\n", __func__); + rc = -EINVAL; + } + + return rc; +} + +struct mwl8k_conf_tx_worker { + struct mwl8k_work_struct header; + u16 queue; + const struct ieee80211_tx_queue_params *params; +}; + +static int mwl8k_conf_tx_wt(struct work_struct *wt) +{ + struct mwl8k_conf_tx_worker *worker = + (struct mwl8k_conf_tx_worker *)wt; + + struct ieee80211_hw *hw = worker->header.hw; + u16 queue = worker->queue; + const struct ieee80211_tx_queue_params *params = worker->params; + + struct mwl8k_priv *priv = hw->priv; + int rc = 0; + + if (priv->wmm_mode == MWL8K_WMM_DISABLE) + if (mwl8k_set_wmm(hw, MWL8K_WMM_ENABLE)) { + rc = -EINVAL; + goto mwl8k_conf_tx_exit; + } + + if (mwl8k_set_edca_params(hw, GET_TXQ(queue), params->cw_min, + params->cw_max, params->aifs, params->txop)) + rc = -EINVAL; +mwl8k_conf_tx_exit: + return rc; +} + +static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, + const struct ieee80211_tx_queue_params *params) +{ + int rc; + struct mwl8k_conf_tx_worker *worker; + struct mwl8k_priv *priv = hw->priv; + + worker = kzalloc(sizeof(*worker), GFP_KERNEL); + if (worker == NULL) + return -ENOMEM; + + worker->queue = queue; + worker->params = params; + rc = mwl8k_queue_work(hw, &worker->header, + priv->config_wq, mwl8k_conf_tx_wt); + kfree(worker); + if (rc == -ETIMEDOUT) { + printk(KERN_ERR "%s() timed out\n", __func__); + rc = -EINVAL; + } + return rc; +} + +static int mwl8k_get_tx_stats(struct ieee80211_hw *hw, + struct ieee80211_tx_queue_stats *stats) +{ + struct mwl8k_priv *priv = hw->priv; + struct mwl8k_tx_queue *txq; + int index; + + spin_lock_bh(&priv->tx_lock); + for (index = 0; index < MWL8K_TX_QUEUES; index++) { + txq = priv->txq + index; + memcpy(&stats[index], &txq->tx_stats, + sizeof(struct ieee80211_tx_queue_stats)); + } + spin_unlock_bh(&priv->tx_lock); + return 0; +} + +struct mwl8k_get_stats_worker { + struct mwl8k_work_struct header; + struct ieee80211_low_level_stats *stats; +}; + +static int mwl8k_get_stats_wt(struct work_struct *wt) +{ + struct mwl8k_get_stats_worker *worker = + (struct mwl8k_get_stats_worker *)wt; + + return mwl8k_cmd_802_11_get_stat(worker->header.hw, worker->stats); +} + +static int mwl8k_get_stats(struct ieee80211_hw *hw, + struct ieee80211_low_level_stats *stats) +{ + int rc; + struct mwl8k_get_stats_worker *worker; + struct mwl8k_priv *priv = hw->priv; + + worker = kzalloc(sizeof(*worker), GFP_KERNEL); + if (worker == NULL) + return -ENOMEM; + + worker->stats = stats; + rc = mwl8k_queue_work(hw, &worker->header, + priv->config_wq, mwl8k_get_stats_wt); + + kfree(worker); + if (rc == -ETIMEDOUT) { + printk(KERN_ERR "%s() timed out\n", __func__); + rc = -EINVAL; + } + + return rc; +} + +static const struct ieee80211_ops mwl8k_ops = { + .tx = mwl8k_tx, + .start = mwl8k_start, + .stop = mwl8k_stop, + .add_interface = mwl8k_add_interface, + .remove_interface = mwl8k_remove_interface, + .config = mwl8k_config, + .config_interface = mwl8k_config_interface, + .bss_info_changed = mwl8k_bss_info_changed, + .configure_filter = mwl8k_configure_filter, + .set_rts_threshold = mwl8k_set_rts_threshold, + .conf_tx = mwl8k_conf_tx, + .get_tx_stats = mwl8k_get_tx_stats, + .get_stats = mwl8k_get_stats, +}; + +static void mwl8k_tx_reclaim_handler(unsigned long data) +{ + int i; + struct ieee80211_hw *hw = (struct ieee80211_hw *) data; + struct mwl8k_priv *priv = hw->priv; + + spin_lock_bh(&priv->tx_lock); + for (i = 0; i < MWL8K_TX_QUEUES; i++) + mwl8k_txq_reclaim(hw, i, 0); + + if (priv->tx_wait != NULL) { + int count = mwl8k_txq_busy(priv); + if (count == 0) { + complete(priv->tx_wait); + priv->tx_wait = NULL; + } + } + spin_unlock_bh(&priv->tx_lock); +} + +static void mwl8k_finalize_join_worker(struct work_struct *work) +{ + struct mwl8k_priv *priv = + container_of(work, struct mwl8k_priv, finalize_join_worker); + struct sk_buff *skb = priv->beacon_skb; + u8 dtim = (MWL8K_VIF(priv->vif))->bss_info.dtim_period; + + mwl8k_finalize_join(priv->hw, skb->data, skb->len, dtim); + dev_kfree_skb(skb); + + priv->beacon_skb = NULL; +} + +static int __devinit mwl8k_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct ieee80211_hw *hw; + struct mwl8k_priv *priv; + DECLARE_MAC_BUF(mac); + int rc; + int i; + u8 *fw; + + rc = pci_enable_device(pdev); + if (rc) { + printk(KERN_ERR "%s: Cannot enable new PCI device\n", + MWL8K_NAME); + return rc; + } + + rc = pci_request_regions(pdev, MWL8K_NAME); + if (rc) { + printk(KERN_ERR "%s: Cannot obtain PCI resources\n", + MWL8K_NAME); + return rc; + } + + pci_set_master(pdev); + + hw = ieee80211_alloc_hw(sizeof(*priv), &mwl8k_ops); + if (hw == NULL) { + printk(KERN_ERR "%s: ieee80211 alloc failed\n", MWL8K_NAME); + rc = -ENOMEM; + goto err_free_reg; + } + + priv = hw->priv; + priv->hw = hw; + priv->pdev = pdev; + priv->hostcmd_wait = NULL; + priv->tx_wait = NULL; + priv->inconfig = false; + priv->wep_enabled = 0; + priv->wmm_mode = false; + priv->pending_tx_pkts = 0; + strncpy(priv->name, MWL8K_NAME, sizeof(priv->name)); + + spin_lock_init(&priv->fw_lock); + + SET_IEEE80211_DEV(hw, &pdev->dev); + pci_set_drvdata(pdev, hw); + + priv->regs = pci_iomap(pdev, 1, 0x10000); + if (priv->regs == NULL) { + printk(KERN_ERR "%s: Cannot map device memory\n", priv->name); + goto err_iounmap; + } + + memcpy(priv->channels, mwl8k_channels, sizeof(mwl8k_channels)); + priv->band.band = IEEE80211_BAND_2GHZ; + priv->band.channels = priv->channels; + priv->band.n_channels = ARRAY_SIZE(mwl8k_channels); + priv->band.bitrates = priv->rates; + priv->band.n_bitrates = ARRAY_SIZE(mwl8k_rates); + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + + BUILD_BUG_ON(sizeof(priv->rates) != sizeof(mwl8k_rates)); + memcpy(priv->rates, mwl8k_rates, sizeof(mwl8k_rates)); + + /* + * Extra headroom is the size of the required DMA header + * minus the size of the smallest 802.11 frame (CTS frame). + */ + hw->extra_tx_headroom = + sizeof(struct mwl8k_dma_data) - sizeof(struct ieee80211_cts); + + hw->channel_change_time = 10; + + hw->queues = MWL8K_TX_QUEUES; + + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_MONITOR); + + /* Set rssi and noise values to dBm */ + hw->flags |= (IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM); + hw->vif_data_size = sizeof(struct mwl8k_vif); + priv->vif = NULL; + + /* Set default radio state and preamble */ + priv->radio_preamble = MWL8K_RADIO_DEFAULT_PREAMBLE; + priv->radio_state = MWL8K_RADIO_DISABLE; + + /* Finalize join worker */ + INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); + + /* TX reclaim tasklet */ + tasklet_init(&priv->tx_reclaim_task, + mwl8k_tx_reclaim_handler, (unsigned long)hw); + tasklet_disable(&priv->tx_reclaim_task); + + /* Config workthread */ + priv->config_wq = create_singlethread_workqueue("mwl8k_config"); + if (priv->config_wq == NULL) + goto err_iounmap; + + /* Power management cookie */ + priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma); + if (priv->cookie == NULL) + goto err_iounmap; + + rc = mwl8k_rxq_init(hw, 0); + if (rc) + goto err_iounmap; + rxq_refill(hw, 0, INT_MAX); + + spin_lock_init(&priv->tx_lock); + + for (i = 0; i < MWL8K_TX_QUEUES; i++) { + rc = mwl8k_txq_init(hw, i); + if (rc) + goto err_free_queues; + } + + iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); + priv->int_mask = 0; + iowrite32(priv->int_mask, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); + iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL); + iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); + + rc = request_irq(priv->pdev->irq, &mwl8k_interrupt, + IRQF_SHARED, MWL8K_NAME, hw); + if (rc) { + printk(KERN_ERR "%s: failed to register IRQ handler\n", + priv->name); + goto err_free_queues; + } + + /* Reset firmware and hardware */ + mwl8k_hw_reset(priv); + + /* Ask userland hotplug daemon for the device firmware */ + rc = mwl8k_request_firmware(priv, (u32)id->driver_data); + if (rc) { + printk(KERN_ERR "%s: Firmware files not found\n", priv->name); + goto err_free_irq; + } + + /* Load firmware into hardware */ + rc = mwl8k_load_firmware(priv); + if (rc) { + printk(KERN_ERR "%s: Cannot start firmware\n", priv->name); + goto err_stop_firmware; + } + + /* Reclaim memory once firmware is successfully loaded */ + mwl8k_release_firmware(priv); + + /* + * Temporarily enable interrupts. Initial firmware host + * commands use interrupts and avoids polling. Disable + * interrupts when done. + */ + priv->int_mask |= MWL8K_A2H_EVENTS; + + iowrite32(priv->int_mask, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); + + /* Get config data, mac addrs etc */ + rc = mwl8k_cmd_get_hw_spec(hw); + if (rc) { + printk(KERN_ERR "%s: Cannot initialise firmware\n", priv->name); + goto err_stop_firmware; + } + + /* Turn radio off */ + rc = mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_DISABLE); + if (rc) { + printk(KERN_ERR "%s: Cannot disable\n", priv->name); + goto err_stop_firmware; + } + + /* Disable interrupts */ + spin_lock_irq(&priv->tx_lock); + iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); + spin_unlock_irq(&priv->tx_lock); + free_irq(priv->pdev->irq, hw); + + rc = ieee80211_register_hw(hw); + if (rc) { + printk(KERN_ERR "%s: Cannot register device\n", priv->name); + goto err_stop_firmware; + } + + fw = (u8 *)&priv->fw_rev; + printk(KERN_INFO "%s: 88W%u %s\n", priv->name, priv->part_num, + MWL8K_DESC); + printk(KERN_INFO "%s: Driver Ver:%s Firmware Ver:%u.%u.%u.%u\n", + priv->name, MWL8K_VERSION, fw[3], fw[2], fw[1], fw[0]); + printk(KERN_INFO "%s: MAC Address: %s\n", priv->name, + print_mac(mac, hw->wiphy->perm_addr)); + + return 0; + +err_stop_firmware: + mwl8k_hw_reset(priv); + mwl8k_release_firmware(priv); + +err_free_irq: + spin_lock_irq(&priv->tx_lock); + iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); + spin_unlock_irq(&priv->tx_lock); + free_irq(priv->pdev->irq, hw); + +err_free_queues: + for (i = 0; i < MWL8K_TX_QUEUES; i++) + mwl8k_txq_deinit(hw, i); + mwl8k_rxq_deinit(hw, 0); + +err_iounmap: + if (priv->cookie != NULL) + pci_free_consistent(priv->pdev, 4, + priv->cookie, priv->cookie_dma); + + if (priv->regs != NULL) + pci_iounmap(pdev, priv->regs); + + if (priv->config_wq != NULL) + destroy_workqueue(priv->config_wq); + + pci_set_drvdata(pdev, NULL); + ieee80211_free_hw(hw); + +err_free_reg: + pci_release_regions(pdev); + pci_disable_device(pdev); + + return rc; +} + +static void __devexit mwl8k_remove(struct pci_dev *pdev) +{ + printk(KERN_ERR "===>%s(%u)\n", __func__, __LINE__); +} + +static void __devexit mwl8k_shutdown(struct pci_dev *pdev) +{ + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct mwl8k_priv *priv; + int i; + + if (hw == NULL) + return; + priv = hw->priv; + + ieee80211_stop_queues(hw); + + /* Remove tx reclaim tasklet */ + tasklet_kill(&priv->tx_reclaim_task); + + /* Stop config thread */ + destroy_workqueue(priv->config_wq); + + /* Stop hardware */ + mwl8k_hw_reset(priv); + + /* Return all skbs to mac80211 */ + for (i = 0; i < MWL8K_TX_QUEUES; i++) + mwl8k_txq_reclaim(hw, i, 1); + + ieee80211_unregister_hw(hw); + + for (i = 0; i < MWL8K_TX_QUEUES; i++) + mwl8k_txq_deinit(hw, i); + + mwl8k_rxq_deinit(hw, 0); + + pci_free_consistent(priv->pdev, 4, + priv->cookie, priv->cookie_dma); + + pci_iounmap(pdev, priv->regs); + pci_set_drvdata(pdev, NULL); + ieee80211_free_hw(hw); + pci_release_regions(pdev); + pci_disable_device(pdev); +} + +static struct pci_driver mwl8k_driver = { + .name = MWL8K_NAME, + .id_table = mwl8k_table, + .probe = mwl8k_probe, + .remove = __devexit_p(mwl8k_remove), + .shutdown = __devexit_p(mwl8k_shutdown), +}; + +static int __init mwl8k_init(void) +{ + return pci_register_driver(&mwl8k_driver); +} + +static void __exit mwl8k_exit(void) +{ + pci_unregister_driver(&mwl8k_driver); +} + +module_init(mwl8k_init); +module_exit(mwl8k_exit); -- GitLab From 141fa61f10c419cb9b47a042eed79df621db75c6 Mon Sep 17 00:00:00 2001 From: John Daiker Date: Tue, 10 Mar 2009 06:59:54 -0700 Subject: [PATCH 3598/4982] ray_cs: checkpatch.pl and Lindent cleanups Before: 1099 errors, 93 warnings, 2854 lines checked After: 19 errors, 47 warnings, 2976 lines checked The big bulk of this is code indent and over 80 character lines (Lindent did this part) Other changes are foo * bar spacing, and trailing whitespace. v2: Cleans up ill-indented comments. Subsequently, this reduces the number of warnings, too. Thanks to Joe Perches for pointing this out! v3: Ran the whole file through Lindent first... which does most of the work for me. :) Again, thanks to Joe Perches for this. This is my final answer! Signed-off-by: John Daiker Signed-off-by: John W. Linville --- drivers/net/wireless/ray_cs.c | 3808 +++++++++++++++++---------------- 1 file changed, 1965 insertions(+), 1843 deletions(-) diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 99ec7d62251..7370edb4e0c 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -8,7 +8,7 @@ * Copyright (c) 1998 Corey Thomas (corey@world.std.com) * * This driver is free software; you can redistribute it and/or modify - * it under the terms of version 2 only of the GNU General Public License as + * it under the terms of version 2 only of the GNU General Public License as * published by the Free Software Foundation. * * It is distributed in the hope that it will be useful, @@ -27,7 +27,7 @@ * * Daniele Bellucci - 07/10/2003 * - Audit copy_to_user in ioctl(SIOCGIWESSID) - * + * =============================================================================*/ #include @@ -65,8 +65,8 @@ /* Warning : these stuff will slow down the driver... */ #define WIRELESS_SPY /* Enable spying addresses */ /* Definitions we need for spy */ -typedef struct iw_statistics iw_stats; -typedef u_char mac_addr[ETH_ALEN]; /* Hardware address */ +typedef struct iw_statistics iw_stats; +typedef u_char mac_addr[ETH_ALEN]; /* Hardware address */ #include "rayctl.h" #include "ray_cs.h" @@ -86,7 +86,7 @@ static int ray_debug; static int pc_debug = PCMCIA_DEBUG; module_param(pc_debug, int, 0); /* #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); */ -#define DEBUG(n, args...) if (pc_debug>(n)) printk(args); +#define DEBUG(n, args...) if (pc_debug > (n)) printk(args); #else #define DEBUG(n, args...) #endif @@ -108,12 +108,12 @@ static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev); static void set_multicast_list(struct net_device *dev); static void ray_update_multi_list(struct net_device *dev, int all); static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx, - unsigned char *data, int len); -static void ray_build_header(ray_dev_t *local, struct tx_msg __iomem *ptx, UCHAR msg_type, - unsigned char *data); + unsigned char *data, int len); +static void ray_build_header(ray_dev_t *local, struct tx_msg __iomem *ptx, + UCHAR msg_type, unsigned char *data); static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len); -static iw_stats * ray_get_wireless_stats(struct net_device * dev); -static const struct iw_handler_def ray_handler_def; +static iw_stats *ray_get_wireless_stats(struct net_device *dev); +static const struct iw_handler_def ray_handler_def; /***** Prototypes for raylink functions **************************************/ static int asc_to_int(char a); @@ -124,7 +124,7 @@ static int get_free_ccs(ray_dev_t *local); static int get_free_tx_ccs(ray_dev_t *local); static void init_startup_params(ray_dev_t *local); static int parse_addr(char *in_str, UCHAR *out); -static int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev, UCHAR type); +static int ray_hw_xmit(unsigned char *data, int len, struct net_device *dev, UCHAR type); static int ray_init(struct net_device *dev); static int interrupt_ecf(ray_dev_t *local, int ccs); static void ray_reset(struct net_device *dev); @@ -132,17 +132,17 @@ static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, i static void verify_dl_startup(u_long); /* Prototypes for interrpt time functions **********************************/ -static irqreturn_t ray_interrupt (int reg, void *dev_id); +static irqreturn_t ray_interrupt(int reg, void *dev_id); static void clear_interrupt(ray_dev_t *local); -static void rx_deauthenticate(ray_dev_t *local, struct rcs __iomem *prcs, - unsigned int pkt_addr, int rx_len); +static void rx_deauthenticate(ray_dev_t *local, struct rcs __iomem *prcs, + unsigned int pkt_addr, int rx_len); static int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int len); static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs __iomem *prcs); static void release_frag_chain(ray_dev_t *local, struct rcs __iomem *prcs); static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs, - unsigned int pkt_addr, int rx_len); -static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, unsigned int pkt_addr, - int rx_len); + unsigned int pkt_addr, int rx_len); +static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, + unsigned int pkt_addr, int rx_len); static void associate(ray_dev_t *local); /* Card command functions */ @@ -219,82 +219,84 @@ module_param(phy_addr, charp, 0); module_param(ray_mem_speed, int, 0); static UCHAR b5_default_startup_parms[] = { - 0, 0, /* Adhoc station */ - 'L','I','N','U','X', 0, 0, 0, /* 32 char ESSID */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, /* Active scan, CA Mode */ - 0, 0, 0, 0, 0, 0, /* No default MAC addr */ - 0x7f, 0xff, /* Frag threshold */ - 0x00, 0x80, /* Hop time 128 Kus*/ - 0x01, 0x00, /* Beacon period 256 Kus */ - 0x01, 0x07, 0xa3, /* DTIM, retries, ack timeout*/ - 0x1d, 0x82, 0x4e, /* SIFS, DIFS, PIFS */ - 0x7f, 0xff, /* RTS threshold */ - 0x04, 0xe2, 0x38, 0xA4, /* scan_dwell, max_scan_dwell */ - 0x05, /* assoc resp timeout thresh */ - 0x08, 0x02, 0x08, /* adhoc, infra, super cycle max*/ - 0, /* Promiscuous mode */ - 0x0c, 0x0bd, /* Unique word */ - 0x32, /* Slot time */ - 0xff, 0xff, /* roam-low snr, low snr count */ - 0x05, 0xff, /* Infra, adhoc missed bcn thresh */ - 0x01, 0x0b, 0x4f, /* USA, hop pattern, hop pat length */ + 0, 0, /* Adhoc station */ + 'L', 'I', 'N', 'U', 'X', 0, 0, 0, /* 32 char ESSID */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, /* Active scan, CA Mode */ + 0, 0, 0, 0, 0, 0, /* No default MAC addr */ + 0x7f, 0xff, /* Frag threshold */ + 0x00, 0x80, /* Hop time 128 Kus */ + 0x01, 0x00, /* Beacon period 256 Kus */ + 0x01, 0x07, 0xa3, /* DTIM, retries, ack timeout */ + 0x1d, 0x82, 0x4e, /* SIFS, DIFS, PIFS */ + 0x7f, 0xff, /* RTS threshold */ + 0x04, 0xe2, 0x38, 0xA4, /* scan_dwell, max_scan_dwell */ + 0x05, /* assoc resp timeout thresh */ + 0x08, 0x02, 0x08, /* adhoc, infra, super cycle max */ + 0, /* Promiscuous mode */ + 0x0c, 0x0bd, /* Unique word */ + 0x32, /* Slot time */ + 0xff, 0xff, /* roam-low snr, low snr count */ + 0x05, 0xff, /* Infra, adhoc missed bcn thresh */ + 0x01, 0x0b, 0x4f, /* USA, hop pattern, hop pat length */ /* b4 - b5 differences start here */ - 0x00, 0x3f, /* CW max */ - 0x00, 0x0f, /* CW min */ - 0x04, 0x08, /* Noise gain, limit offset */ - 0x28, 0x28, /* det rssi, med busy offsets */ - 7, /* det sync thresh */ - 0, 2, 2, /* test mode, min, max */ - 0, /* allow broadcast SSID probe resp */ - 0, 0, /* privacy must start, can join */ - 2, 0, 0, 0, 0, 0, 0, 0 /* basic rate set */ + 0x00, 0x3f, /* CW max */ + 0x00, 0x0f, /* CW min */ + 0x04, 0x08, /* Noise gain, limit offset */ + 0x28, 0x28, /* det rssi, med busy offsets */ + 7, /* det sync thresh */ + 0, 2, 2, /* test mode, min, max */ + 0, /* allow broadcast SSID probe resp */ + 0, 0, /* privacy must start, can join */ + 2, 0, 0, 0, 0, 0, 0, 0 /* basic rate set */ }; static UCHAR b4_default_startup_parms[] = { - 0, 0, /* Adhoc station */ - 'L','I','N','U','X', 0, 0, 0, /* 32 char ESSID */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, /* Active scan, CA Mode */ - 0, 0, 0, 0, 0, 0, /* No default MAC addr */ - 0x7f, 0xff, /* Frag threshold */ - 0x02, 0x00, /* Hop time */ - 0x00, 0x01, /* Beacon period */ - 0x01, 0x07, 0xa3, /* DTIM, retries, ack timeout*/ - 0x1d, 0x82, 0xce, /* SIFS, DIFS, PIFS */ - 0x7f, 0xff, /* RTS threshold */ - 0xfb, 0x1e, 0xc7, 0x5c, /* scan_dwell, max_scan_dwell */ - 0x05, /* assoc resp timeout thresh */ - 0x04, 0x02, 0x4, /* adhoc, infra, super cycle max*/ - 0, /* Promiscuous mode */ - 0x0c, 0x0bd, /* Unique word */ - 0x4e, /* Slot time (TBD seems wrong)*/ - 0xff, 0xff, /* roam-low snr, low snr count */ - 0x05, 0xff, /* Infra, adhoc missed bcn thresh */ - 0x01, 0x0b, 0x4e, /* USA, hop pattern, hop pat length */ + 0, 0, /* Adhoc station */ + 'L', 'I', 'N', 'U', 'X', 0, 0, 0, /* 32 char ESSID */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, /* Active scan, CA Mode */ + 0, 0, 0, 0, 0, 0, /* No default MAC addr */ + 0x7f, 0xff, /* Frag threshold */ + 0x02, 0x00, /* Hop time */ + 0x00, 0x01, /* Beacon period */ + 0x01, 0x07, 0xa3, /* DTIM, retries, ack timeout */ + 0x1d, 0x82, 0xce, /* SIFS, DIFS, PIFS */ + 0x7f, 0xff, /* RTS threshold */ + 0xfb, 0x1e, 0xc7, 0x5c, /* scan_dwell, max_scan_dwell */ + 0x05, /* assoc resp timeout thresh */ + 0x04, 0x02, 0x4, /* adhoc, infra, super cycle max */ + 0, /* Promiscuous mode */ + 0x0c, 0x0bd, /* Unique word */ + 0x4e, /* Slot time (TBD seems wrong) */ + 0xff, 0xff, /* roam-low snr, low snr count */ + 0x05, 0xff, /* Infra, adhoc missed bcn thresh */ + 0x01, 0x0b, 0x4e, /* USA, hop pattern, hop pat length */ /* b4 - b5 differences start here */ - 0x3f, 0x0f, /* CW max, min */ - 0x04, 0x08, /* Noise gain, limit offset */ - 0x28, 0x28, /* det rssi, med busy offsets */ - 7, /* det sync thresh */ - 0, 2, 2 /* test mode, min, max*/ + 0x3f, 0x0f, /* CW max, min */ + 0x04, 0x08, /* Noise gain, limit offset */ + 0x28, 0x28, /* det rssi, med busy offsets */ + 7, /* det sync thresh */ + 0, 2, 2 /* test mode, min, max */ }; + /*===========================================================================*/ -static unsigned char eth2_llc[] = {0xaa, 0xaa, 3, 0, 0, 0}; +static unsigned char eth2_llc[] = { 0xaa, 0xaa, 3, 0, 0, 0 }; static char hop_pattern_length[] = { 1, - USA_HOP_MOD, EUROPE_HOP_MOD, - JAPAN_HOP_MOD, KOREA_HOP_MOD, - SPAIN_HOP_MOD, FRANCE_HOP_MOD, - ISRAEL_HOP_MOD, AUSTRALIA_HOP_MOD, - JAPAN_TEST_HOP_MOD + USA_HOP_MOD, EUROPE_HOP_MOD, + JAPAN_HOP_MOD, KOREA_HOP_MOD, + SPAIN_HOP_MOD, FRANCE_HOP_MOD, + ISRAEL_HOP_MOD, AUSTRALIA_HOP_MOD, + JAPAN_TEST_HOP_MOD }; -static char rcsid[] = "Raylink/WebGear wireless LAN - Corey "; +static char rcsid[] = + "Raylink/WebGear wireless LAN - Corey "; /*============================================================================= ray_attach() creates an "instance" of the driver, allocating @@ -306,71 +308,72 @@ static char rcsid[] = "Raylink/WebGear wireless LAN - Corey finder = p_dev; - - /* The io structure describes IO port mapping. None used here */ - p_dev->io.NumPorts1 = 0; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = 5; - - /* Interrupt setup. For PCMCIA, driver takes what's given */ - p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; - p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; - p_dev->irq.Handler = &ray_interrupt; - - /* General socket configuration */ - p_dev->conf.Attributes = CONF_ENABLE_IRQ; - p_dev->conf.IntType = INT_MEMORY_AND_IO; - p_dev->conf.ConfigIndex = 1; - - p_dev->priv = dev; - p_dev->irq.Instance = dev; - - local->finder = p_dev; - local->card_status = CARD_INSERTED; - local->authentication_state = UNAUTHENTICATED; - local->num_multi = 0; - DEBUG(2,"ray_attach p_dev = %p, dev = %p, local = %p, intr = %p\n", - p_dev,dev,local,&ray_interrupt); - - /* Raylink entries in the device structure */ - dev->hard_start_xmit = &ray_dev_start_xmit; - dev->set_config = &ray_dev_config; - dev->get_stats = &ray_get_stats; - SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); - dev->wireless_handlers = &ray_handler_def; + ray_dev_t *local; + struct net_device *dev; + + DEBUG(1, "ray_attach()\n"); + + /* Allocate space for private device-specific data */ + dev = alloc_etherdev(sizeof(ray_dev_t)); + if (!dev) + goto fail_alloc_dev; + + local = netdev_priv(dev); + local->finder = p_dev; + + /* The io structure describes IO port mapping. None used here */ + p_dev->io.NumPorts1 = 0; + p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + p_dev->io.IOAddrLines = 5; + + /* Interrupt setup. For PCMCIA, driver takes what's given */ + p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; + p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; + p_dev->irq.Handler = &ray_interrupt; + + /* General socket configuration */ + p_dev->conf.Attributes = CONF_ENABLE_IRQ; + p_dev->conf.IntType = INT_MEMORY_AND_IO; + p_dev->conf.ConfigIndex = 1; + + p_dev->priv = dev; + p_dev->irq.Instance = dev; + + local->finder = p_dev; + local->card_status = CARD_INSERTED; + local->authentication_state = UNAUTHENTICATED; + local->num_multi = 0; + DEBUG(2, "ray_attach p_dev = %p, dev = %p, local = %p, intr = %p\n", + p_dev, dev, local, &ray_interrupt); + + /* Raylink entries in the device structure */ + dev->hard_start_xmit = &ray_dev_start_xmit; + dev->set_config = &ray_dev_config; + dev->get_stats = &ray_get_stats; + SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); + dev->wireless_handlers = &ray_handler_def; #ifdef WIRELESS_SPY - local->wireless_data.spy_data = &local->spy_data; - dev->wireless_data = &local->wireless_data; -#endif /* WIRELESS_SPY */ + local->wireless_data.spy_data = &local->spy_data; + dev->wireless_data = &local->wireless_data; +#endif /* WIRELESS_SPY */ - dev->set_multicast_list = &set_multicast_list; + dev->set_multicast_list = &set_multicast_list; - DEBUG(2,"ray_cs ray_attach calling ether_setup.)\n"); - dev->init = &ray_dev_init; - dev->open = &ray_open; - dev->stop = &ray_dev_close; - netif_stop_queue(dev); + DEBUG(2, "ray_cs ray_attach calling ether_setup.)\n"); + dev->init = &ray_dev_init; + dev->open = &ray_open; + dev->stop = &ray_dev_close; + netif_stop_queue(dev); - init_timer(&local->timer); + init_timer(&local->timer); - this_device = p_dev; - return ray_config(p_dev); + this_device = p_dev; + return ray_config(p_dev); fail_alloc_dev: - return -ENOMEM; + return -ENOMEM; } /* ray_attach */ + /*============================================================================= This deletes a driver "instance". The device is de-registered with Card Services. If it has been released, all local data @@ -379,25 +382,27 @@ fail_alloc_dev: =============================================================================*/ static void ray_detach(struct pcmcia_device *link) { - struct net_device *dev; - ray_dev_t *local; + struct net_device *dev; + ray_dev_t *local; - DEBUG(1, "ray_detach(0x%p)\n", link); + DEBUG(1, "ray_detach(0x%p)\n", link); - this_device = NULL; - dev = link->priv; + this_device = NULL; + dev = link->priv; - ray_release(link); + ray_release(link); - local = netdev_priv(dev); - del_timer(&local->timer); + local = netdev_priv(dev); + del_timer(&local->timer); - if (link->priv) { - if (link->dev_node) unregister_netdev(dev); - free_netdev(dev); - } - DEBUG(2,"ray_cs ray_detach ending\n"); + if (link->priv) { + if (link->dev_node) + unregister_netdev(dev); + free_netdev(dev); + } + DEBUG(2, "ray_cs ray_detach ending\n"); } /* ray_detach */ + /*============================================================================= ray_config() is run after a CARD_INSERTION event is received, to configure the PCMCIA socket, and to make the @@ -408,92 +413,101 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) #define MAX_TUPLE_SIZE 128 static int ray_config(struct pcmcia_device *link) { - int last_fn = 0, last_ret = 0; - int i; - win_req_t req; - memreq_t mem; - struct net_device *dev = (struct net_device *)link->priv; - ray_dev_t *local = netdev_priv(dev); - - DEBUG(1, "ray_config(0x%p)\n", link); - - /* Determine card type and firmware version */ - printk(KERN_INFO "ray_cs Detected: %s%s%s%s\n", - link->prod_id[0] ? link->prod_id[0] : " ", - link->prod_id[1] ? link->prod_id[1] : " ", - link->prod_id[2] ? link->prod_id[2] : " ", - link->prod_id[3] ? link->prod_id[3] : " "); - - /* Now allocate an interrupt line. Note that this does not - actually assign a handler to the interrupt. - */ - CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); - dev->irq = link->irq.AssignedIRQ; - - /* This actually configures the PCMCIA socket -- setting up - the I/O windows and the interrupt mapping. - */ - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); + int last_fn = 0, last_ret = 0; + int i; + win_req_t req; + memreq_t mem; + struct net_device *dev = (struct net_device *)link->priv; + ray_dev_t *local = netdev_priv(dev); + + DEBUG(1, "ray_config(0x%p)\n", link); + + /* Determine card type and firmware version */ + printk(KERN_INFO "ray_cs Detected: %s%s%s%s\n", + link->prod_id[0] ? link->prod_id[0] : " ", + link->prod_id[1] ? link->prod_id[1] : " ", + link->prod_id[2] ? link->prod_id[2] : " ", + link->prod_id[3] ? link->prod_id[3] : " "); + + /* Now allocate an interrupt line. Note that this does not + actually assign a handler to the interrupt. + */ + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); + dev->irq = link->irq.AssignedIRQ; + + /* This actually configures the PCMCIA socket -- setting up + the I/O windows and the interrupt mapping. + */ + CS_CHECK(RequestConfiguration, + pcmcia_request_configuration(link, &link->conf)); /*** Set up 32k window for shared memory (transmit and control) ************/ - req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT; - req.Base = 0; - req.Size = 0x8000; - req.AccessSpeed = ray_mem_speed; - CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win)); - mem.CardOffset = 0x0000; mem.Page = 0; - CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem)); - local->sram = ioremap(req.Base,req.Size); + req.Attributes = + WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT; + req.Base = 0; + req.Size = 0x8000; + req.AccessSpeed = ray_mem_speed; + CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win)); + mem.CardOffset = 0x0000; + mem.Page = 0; + CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem)); + local->sram = ioremap(req.Base, req.Size); /*** Set up 16k window for shared memory (receive buffer) ***************/ - req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT; - req.Base = 0; - req.Size = 0x4000; - req.AccessSpeed = ray_mem_speed; - CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &local->rmem_handle)); - mem.CardOffset = 0x8000; mem.Page = 0; - CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->rmem_handle, &mem)); - local->rmem = ioremap(req.Base,req.Size); + req.Attributes = + WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT; + req.Base = 0; + req.Size = 0x4000; + req.AccessSpeed = ray_mem_speed; + CS_CHECK(RequestWindow, + pcmcia_request_window(&link, &req, &local->rmem_handle)); + mem.CardOffset = 0x8000; + mem.Page = 0; + CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->rmem_handle, &mem)); + local->rmem = ioremap(req.Base, req.Size); /*** Set up window for attribute memory ***********************************/ - req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM | WIN_ENABLE | WIN_USE_WAIT; - req.Base = 0; - req.Size = 0x1000; - req.AccessSpeed = ray_mem_speed; - CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &local->amem_handle)); - mem.CardOffset = 0x0000; mem.Page = 0; - CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->amem_handle, &mem)); - local->amem = ioremap(req.Base,req.Size); - - DEBUG(3,"ray_config sram=%p\n",local->sram); - DEBUG(3,"ray_config rmem=%p\n",local->rmem); - DEBUG(3,"ray_config amem=%p\n",local->amem); - if (ray_init(dev) < 0) { - ray_release(link); - return -ENODEV; - } - - SET_NETDEV_DEV(dev, &handle_to_dev(link)); - i = register_netdev(dev); - if (i != 0) { - printk("ray_config register_netdev() failed\n"); - ray_release(link); - return i; - } - - strcpy(local->node.dev_name, dev->name); - link->dev_node = &local->node; - - printk(KERN_INFO "%s: RayLink, irq %d, hw_addr %pM\n", - dev->name, dev->irq, dev->dev_addr); - - return 0; + req.Attributes = + WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM | WIN_ENABLE | WIN_USE_WAIT; + req.Base = 0; + req.Size = 0x1000; + req.AccessSpeed = ray_mem_speed; + CS_CHECK(RequestWindow, + pcmcia_request_window(&link, &req, &local->amem_handle)); + mem.CardOffset = 0x0000; + mem.Page = 0; + CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->amem_handle, &mem)); + local->amem = ioremap(req.Base, req.Size); + + DEBUG(3, "ray_config sram=%p\n", local->sram); + DEBUG(3, "ray_config rmem=%p\n", local->rmem); + DEBUG(3, "ray_config amem=%p\n", local->amem); + if (ray_init(dev) < 0) { + ray_release(link); + return -ENODEV; + } + + SET_NETDEV_DEV(dev, &handle_to_dev(link)); + i = register_netdev(dev); + if (i != 0) { + printk("ray_config register_netdev() failed\n"); + ray_release(link); + return i; + } + + strcpy(local->node.dev_name, dev->name); + link->dev_node = &local->node; + + printk(KERN_INFO "%s: RayLink, irq %d, hw_addr %pM\n", + dev->name, dev->irq, dev->dev_addr); + + return 0; cs_failed: - cs_error(link, last_fn, last_ret); + cs_error(link, last_fn, last_ret); - ray_release(link); - return -ENODEV; + ray_release(link); + return -ENODEV; } /* ray_config */ static inline struct ccs __iomem *ccs_base(ray_dev_t *dev) @@ -516,267 +530,278 @@ static inline struct rcs __iomem *rcs_base(ray_dev_t *dev) /*===========================================================================*/ static int ray_init(struct net_device *dev) { - int i; - UCHAR *p; - struct ccs __iomem *pccs; - ray_dev_t *local = netdev_priv(dev); - struct pcmcia_device *link = local->finder; - DEBUG(1, "ray_init(0x%p)\n", dev); - if (!(pcmcia_dev_present(link))) { - DEBUG(0,"ray_init - device not present\n"); - return -1; - } - - local->net_type = net_type; - local->sta_type = TYPE_STA; - - /* Copy the startup results to local memory */ - memcpy_fromio(&local->startup_res, local->sram + ECF_TO_HOST_BASE,\ - sizeof(struct startup_res_6)); - - /* Check Power up test status and get mac address from card */ - if (local->startup_res.startup_word != 0x80) { - printk(KERN_INFO "ray_init ERROR card status = %2x\n", - local->startup_res.startup_word); - local->card_status = CARD_INIT_ERROR; - return -1; - } - - local->fw_ver = local->startup_res.firmware_version[0]; - local->fw_bld = local->startup_res.firmware_version[1]; - local->fw_var = local->startup_res.firmware_version[2]; - DEBUG(1,"ray_init firmware version %d.%d \n",local->fw_ver, local->fw_bld); - - local->tib_length = 0x20; - if ((local->fw_ver == 5) && (local->fw_bld >= 30)) - local->tib_length = local->startup_res.tib_length; - DEBUG(2,"ray_init tib_length = 0x%02x\n", local->tib_length); - /* Initialize CCS's to buffer free state */ - pccs = ccs_base(local); - for (i=0; ibuffer_status); - } - init_startup_params(local); - - /* copy mac address to startup parameters */ - if (parse_addr(phy_addr, local->sparm.b4.a_mac_addr)) - { - p = local->sparm.b4.a_mac_addr; - } - else - { - memcpy(&local->sparm.b4.a_mac_addr, - &local->startup_res.station_addr, ADDRLEN); - p = local->sparm.b4.a_mac_addr; - } - - clear_interrupt(local); /* Clear any interrupt from the card */ - local->card_status = CARD_AWAITING_PARAM; - DEBUG(2,"ray_init ending\n"); - return 0; + int i; + UCHAR *p; + struct ccs __iomem *pccs; + ray_dev_t *local = netdev_priv(dev); + struct pcmcia_device *link = local->finder; + DEBUG(1, "ray_init(0x%p)\n", dev); + if (!(pcmcia_dev_present(link))) { + DEBUG(0, "ray_init - device not present\n"); + return -1; + } + + local->net_type = net_type; + local->sta_type = TYPE_STA; + + /* Copy the startup results to local memory */ + memcpy_fromio(&local->startup_res, local->sram + ECF_TO_HOST_BASE, + sizeof(struct startup_res_6)); + + /* Check Power up test status and get mac address from card */ + if (local->startup_res.startup_word != 0x80) { + printk(KERN_INFO "ray_init ERROR card status = %2x\n", + local->startup_res.startup_word); + local->card_status = CARD_INIT_ERROR; + return -1; + } + + local->fw_ver = local->startup_res.firmware_version[0]; + local->fw_bld = local->startup_res.firmware_version[1]; + local->fw_var = local->startup_res.firmware_version[2]; + DEBUG(1, "ray_init firmware version %d.%d \n", local->fw_ver, + local->fw_bld); + + local->tib_length = 0x20; + if ((local->fw_ver == 5) && (local->fw_bld >= 30)) + local->tib_length = local->startup_res.tib_length; + DEBUG(2, "ray_init tib_length = 0x%02x\n", local->tib_length); + /* Initialize CCS's to buffer free state */ + pccs = ccs_base(local); + for (i = 0; i < NUMBER_OF_CCS; i++) { + writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); + } + init_startup_params(local); + + /* copy mac address to startup parameters */ + if (parse_addr(phy_addr, local->sparm.b4.a_mac_addr)) { + p = local->sparm.b4.a_mac_addr; + } else { + memcpy(&local->sparm.b4.a_mac_addr, + &local->startup_res.station_addr, ADDRLEN); + p = local->sparm.b4.a_mac_addr; + } + + clear_interrupt(local); /* Clear any interrupt from the card */ + local->card_status = CARD_AWAITING_PARAM; + DEBUG(2, "ray_init ending\n"); + return 0; } /* ray_init */ + /*===========================================================================*/ /* Download startup parameters to the card and command it to read them */ static int dl_startup_params(struct net_device *dev) { - int ccsindex; - ray_dev_t *local = netdev_priv(dev); - struct ccs __iomem *pccs; - struct pcmcia_device *link = local->finder; - - DEBUG(1,"dl_startup_params entered\n"); - if (!(pcmcia_dev_present(link))) { - DEBUG(2,"ray_cs dl_startup_params - device not present\n"); - return -1; - } - - /* Copy parameters to host to ECF area */ - if (local->fw_ver == 0x55) - memcpy_toio(local->sram + HOST_TO_ECF_BASE, &local->sparm.b4, - sizeof(struct b4_startup_params)); - else - memcpy_toio(local->sram + HOST_TO_ECF_BASE, &local->sparm.b5, - sizeof(struct b5_startup_params)); - - - /* Fill in the CCS fields for the ECF */ - if ((ccsindex = get_free_ccs(local)) < 0) return -1; - local->dl_param_ccs = ccsindex; - pccs = ccs_base(local) + ccsindex; - writeb(CCS_DOWNLOAD_STARTUP_PARAMS, &pccs->cmd); - DEBUG(2,"dl_startup_params start ccsindex = %d\n", local->dl_param_ccs); - /* Interrupt the firmware to process the command */ - if (interrupt_ecf(local, ccsindex)) { - printk(KERN_INFO "ray dl_startup_params failed - " - "ECF not ready for intr\n"); - local->card_status = CARD_DL_PARAM_ERROR; - writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); - return -2; - } - local->card_status = CARD_DL_PARAM; - /* Start kernel timer to wait for dl startup to complete. */ - local->timer.expires = jiffies + HZ/2; - local->timer.data = (long)local; - local->timer.function = &verify_dl_startup; - add_timer(&local->timer); - DEBUG(2,"ray_cs dl_startup_params started timer for verify_dl_startup\n"); - return 0; + int ccsindex; + ray_dev_t *local = netdev_priv(dev); + struct ccs __iomem *pccs; + struct pcmcia_device *link = local->finder; + + DEBUG(1, "dl_startup_params entered\n"); + if (!(pcmcia_dev_present(link))) { + DEBUG(2, "ray_cs dl_startup_params - device not present\n"); + return -1; + } + + /* Copy parameters to host to ECF area */ + if (local->fw_ver == 0x55) + memcpy_toio(local->sram + HOST_TO_ECF_BASE, &local->sparm.b4, + sizeof(struct b4_startup_params)); + else + memcpy_toio(local->sram + HOST_TO_ECF_BASE, &local->sparm.b5, + sizeof(struct b5_startup_params)); + + /* Fill in the CCS fields for the ECF */ + if ((ccsindex = get_free_ccs(local)) < 0) + return -1; + local->dl_param_ccs = ccsindex; + pccs = ccs_base(local) + ccsindex; + writeb(CCS_DOWNLOAD_STARTUP_PARAMS, &pccs->cmd); + DEBUG(2, "dl_startup_params start ccsindex = %d\n", + local->dl_param_ccs); + /* Interrupt the firmware to process the command */ + if (interrupt_ecf(local, ccsindex)) { + printk(KERN_INFO "ray dl_startup_params failed - " + "ECF not ready for intr\n"); + local->card_status = CARD_DL_PARAM_ERROR; + writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); + return -2; + } + local->card_status = CARD_DL_PARAM; + /* Start kernel timer to wait for dl startup to complete. */ + local->timer.expires = jiffies + HZ / 2; + local->timer.data = (long)local; + local->timer.function = &verify_dl_startup; + add_timer(&local->timer); + DEBUG(2, + "ray_cs dl_startup_params started timer for verify_dl_startup\n"); + return 0; } /* dl_startup_params */ + /*===========================================================================*/ static void init_startup_params(ray_dev_t *local) { - int i; - - if (country > JAPAN_TEST) country = USA; - else - if (country < USA) country = USA; - /* structure for hop time and beacon period is defined here using - * New 802.11D6.1 format. Card firmware is still using old format - * until version 6. - * Before After - * a_hop_time ms byte a_hop_time ms byte - * a_hop_time 2s byte a_hop_time ls byte - * a_hop_time ls byte a_beacon_period ms byte - * a_beacon_period a_beacon_period ls byte - * - * a_hop_time = uS a_hop_time = KuS - * a_beacon_period = hops a_beacon_period = KuS - */ /* 64ms = 010000 */ - if (local->fw_ver == 0x55) { - memcpy((UCHAR *)&local->sparm.b4, b4_default_startup_parms, - sizeof(struct b4_startup_params)); - /* Translate sane kus input values to old build 4/5 format */ - /* i = hop time in uS truncated to 3 bytes */ - i = (hop_dwell * 1024) & 0xffffff; - local->sparm.b4.a_hop_time[0] = (i >> 16) & 0xff; - local->sparm.b4.a_hop_time[1] = (i >> 8) & 0xff; - local->sparm.b4.a_beacon_period[0] = 0; - local->sparm.b4.a_beacon_period[1] = - ((beacon_period/hop_dwell) - 1) & 0xff; - local->sparm.b4.a_curr_country_code = country; - local->sparm.b4.a_hop_pattern_length = - hop_pattern_length[(int)country] - 1; - if (bc) - { - local->sparm.b4.a_ack_timeout = 0x50; - local->sparm.b4.a_sifs = 0x3f; - } - } - else { /* Version 5 uses real kus values */ - memcpy((UCHAR *)&local->sparm.b5, b5_default_startup_parms, - sizeof(struct b5_startup_params)); - - local->sparm.b5.a_hop_time[0] = (hop_dwell >> 8) & 0xff; - local->sparm.b5.a_hop_time[1] = hop_dwell & 0xff; - local->sparm.b5.a_beacon_period[0] = (beacon_period >> 8) & 0xff; - local->sparm.b5.a_beacon_period[1] = beacon_period & 0xff; - if (psm) - local->sparm.b5.a_power_mgt_state = 1; - local->sparm.b5.a_curr_country_code = country; - local->sparm.b5.a_hop_pattern_length = - hop_pattern_length[(int)country]; - } - - local->sparm.b4.a_network_type = net_type & 0x01; - local->sparm.b4.a_acting_as_ap_status = TYPE_STA; - - if (essid != NULL) - strncpy(local->sparm.b4.a_current_ess_id, essid, ESSID_SIZE); -} /* init_startup_params */ + int i; + + if (country > JAPAN_TEST) + country = USA; + else if (country < USA) + country = USA; + /* structure for hop time and beacon period is defined here using + * New 802.11D6.1 format. Card firmware is still using old format + * until version 6. + * Before After + * a_hop_time ms byte a_hop_time ms byte + * a_hop_time 2s byte a_hop_time ls byte + * a_hop_time ls byte a_beacon_period ms byte + * a_beacon_period a_beacon_period ls byte + * + * a_hop_time = uS a_hop_time = KuS + * a_beacon_period = hops a_beacon_period = KuS + *//* 64ms = 010000 */ + if (local->fw_ver == 0x55) { + memcpy((UCHAR *) &local->sparm.b4, b4_default_startup_parms, + sizeof(struct b4_startup_params)); + /* Translate sane kus input values to old build 4/5 format */ + /* i = hop time in uS truncated to 3 bytes */ + i = (hop_dwell * 1024) & 0xffffff; + local->sparm.b4.a_hop_time[0] = (i >> 16) & 0xff; + local->sparm.b4.a_hop_time[1] = (i >> 8) & 0xff; + local->sparm.b4.a_beacon_period[0] = 0; + local->sparm.b4.a_beacon_period[1] = + ((beacon_period / hop_dwell) - 1) & 0xff; + local->sparm.b4.a_curr_country_code = country; + local->sparm.b4.a_hop_pattern_length = + hop_pattern_length[(int)country] - 1; + if (bc) { + local->sparm.b4.a_ack_timeout = 0x50; + local->sparm.b4.a_sifs = 0x3f; + } + } else { /* Version 5 uses real kus values */ + memcpy((UCHAR *) &local->sparm.b5, b5_default_startup_parms, + sizeof(struct b5_startup_params)); + + local->sparm.b5.a_hop_time[0] = (hop_dwell >> 8) & 0xff; + local->sparm.b5.a_hop_time[1] = hop_dwell & 0xff; + local->sparm.b5.a_beacon_period[0] = + (beacon_period >> 8) & 0xff; + local->sparm.b5.a_beacon_period[1] = beacon_period & 0xff; + if (psm) + local->sparm.b5.a_power_mgt_state = 1; + local->sparm.b5.a_curr_country_code = country; + local->sparm.b5.a_hop_pattern_length = + hop_pattern_length[(int)country]; + } + + local->sparm.b4.a_network_type = net_type & 0x01; + local->sparm.b4.a_acting_as_ap_status = TYPE_STA; + + if (essid != NULL) + strncpy(local->sparm.b4.a_current_ess_id, essid, ESSID_SIZE); +} /* init_startup_params */ + /*===========================================================================*/ static void verify_dl_startup(u_long data) { - ray_dev_t *local = (ray_dev_t *)data; - struct ccs __iomem *pccs = ccs_base(local) + local->dl_param_ccs; - UCHAR status; - struct pcmcia_device *link = local->finder; + ray_dev_t *local = (ray_dev_t *) data; + struct ccs __iomem *pccs = ccs_base(local) + local->dl_param_ccs; + UCHAR status; + struct pcmcia_device *link = local->finder; - if (!(pcmcia_dev_present(link))) { - DEBUG(2,"ray_cs verify_dl_startup - device not present\n"); - return; - } + if (!(pcmcia_dev_present(link))) { + DEBUG(2, "ray_cs verify_dl_startup - device not present\n"); + return; + } #ifdef PCMCIA_DEBUG - if (pc_debug > 2) { - int i; - printk(KERN_DEBUG "verify_dl_startup parameters sent via ccs %d:\n", - local->dl_param_ccs); - for (i=0; isram + HOST_TO_ECF_BASE + i)); - } - printk("\n"); - } + if (pc_debug > 2) { + int i; + printk(KERN_DEBUG + "verify_dl_startup parameters sent via ccs %d:\n", + local->dl_param_ccs); + for (i = 0; i < sizeof(struct b5_startup_params); i++) { + printk(" %2x", + (unsigned int)readb(local->sram + + HOST_TO_ECF_BASE + i)); + } + printk("\n"); + } #endif - status = readb(&pccs->buffer_status); - if (status!= CCS_BUFFER_FREE) - { - printk(KERN_INFO "Download startup params failed. Status = %d\n", - status); - local->card_status = CARD_DL_PARAM_ERROR; - return; - } - if (local->sparm.b4.a_network_type == ADHOC) - start_net((u_long)local); - else - join_net((u_long)local); - - return; + status = readb(&pccs->buffer_status); + if (status != CCS_BUFFER_FREE) { + printk(KERN_INFO + "Download startup params failed. Status = %d\n", + status); + local->card_status = CARD_DL_PARAM_ERROR; + return; + } + if (local->sparm.b4.a_network_type == ADHOC) + start_net((u_long) local); + else + join_net((u_long) local); + + return; } /* end verify_dl_startup */ + /*===========================================================================*/ /* Command card to start a network */ static void start_net(u_long data) { - ray_dev_t *local = (ray_dev_t *)data; - struct ccs __iomem *pccs; - int ccsindex; - struct pcmcia_device *link = local->finder; - if (!(pcmcia_dev_present(link))) { - DEBUG(2,"ray_cs start_net - device not present\n"); - return; - } - /* Fill in the CCS fields for the ECF */ - if ((ccsindex = get_free_ccs(local)) < 0) return; - pccs = ccs_base(local) + ccsindex; - writeb(CCS_START_NETWORK, &pccs->cmd); - writeb(0, &pccs->var.start_network.update_param); - /* Interrupt the firmware to process the command */ - if (interrupt_ecf(local, ccsindex)) { - DEBUG(1,"ray start net failed - card not ready for intr\n"); - writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); - return; - } - local->card_status = CARD_DOING_ACQ; - return; + ray_dev_t *local = (ray_dev_t *) data; + struct ccs __iomem *pccs; + int ccsindex; + struct pcmcia_device *link = local->finder; + if (!(pcmcia_dev_present(link))) { + DEBUG(2, "ray_cs start_net - device not present\n"); + return; + } + /* Fill in the CCS fields for the ECF */ + if ((ccsindex = get_free_ccs(local)) < 0) + return; + pccs = ccs_base(local) + ccsindex; + writeb(CCS_START_NETWORK, &pccs->cmd); + writeb(0, &pccs->var.start_network.update_param); + /* Interrupt the firmware to process the command */ + if (interrupt_ecf(local, ccsindex)) { + DEBUG(1, "ray start net failed - card not ready for intr\n"); + writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); + return; + } + local->card_status = CARD_DOING_ACQ; + return; } /* end start_net */ + /*===========================================================================*/ /* Command card to join a network */ static void join_net(u_long data) { - ray_dev_t *local = (ray_dev_t *)data; - - struct ccs __iomem *pccs; - int ccsindex; - struct pcmcia_device *link = local->finder; - - if (!(pcmcia_dev_present(link))) { - DEBUG(2,"ray_cs join_net - device not present\n"); - return; - } - /* Fill in the CCS fields for the ECF */ - if ((ccsindex = get_free_ccs(local)) < 0) return; - pccs = ccs_base(local) + ccsindex; - writeb(CCS_JOIN_NETWORK, &pccs->cmd); - writeb(0, &pccs->var.join_network.update_param); - writeb(0, &pccs->var.join_network.net_initiated); - /* Interrupt the firmware to process the command */ - if (interrupt_ecf(local, ccsindex)) { - DEBUG(1,"ray join net failed - card not ready for intr\n"); - writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); - return; - } - local->card_status = CARD_DOING_ACQ; - return; + ray_dev_t *local = (ray_dev_t *) data; + + struct ccs __iomem *pccs; + int ccsindex; + struct pcmcia_device *link = local->finder; + + if (!(pcmcia_dev_present(link))) { + DEBUG(2, "ray_cs join_net - device not present\n"); + return; + } + /* Fill in the CCS fields for the ECF */ + if ((ccsindex = get_free_ccs(local)) < 0) + return; + pccs = ccs_base(local) + ccsindex; + writeb(CCS_JOIN_NETWORK, &pccs->cmd); + writeb(0, &pccs->var.join_network.update_param); + writeb(0, &pccs->var.join_network.net_initiated); + /* Interrupt the firmware to process the command */ + if (interrupt_ecf(local, ccsindex)) { + DEBUG(1, "ray join net failed - card not ready for intr\n"); + writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); + return; + } + local->card_status = CARD_DOING_ACQ; + return; } + /*============================================================================ After a card is removed, ray_release() will unregister the net device, and release the PCMCIA configuration. If the device is @@ -784,25 +809,27 @@ static void join_net(u_long data) =============================================================================*/ static void ray_release(struct pcmcia_device *link) { - struct net_device *dev = link->priv; - ray_dev_t *local = netdev_priv(dev); - int i; - - DEBUG(1, "ray_release(0x%p)\n", link); - - del_timer(&local->timer); - - iounmap(local->sram); - iounmap(local->rmem); - iounmap(local->amem); - /* Do bother checking to see if these succeed or not */ - i = pcmcia_release_window(local->amem_handle); - if ( i != 0 ) DEBUG(0,"ReleaseWindow(local->amem) ret = %x\n",i); - i = pcmcia_release_window(local->rmem_handle); - if ( i != 0 ) DEBUG(0,"ReleaseWindow(local->rmem) ret = %x\n",i); - pcmcia_disable_device(link); - - DEBUG(2,"ray_release ending\n"); + struct net_device *dev = link->priv; + ray_dev_t *local = netdev_priv(dev); + int i; + + DEBUG(1, "ray_release(0x%p)\n", link); + + del_timer(&local->timer); + + iounmap(local->sram); + iounmap(local->rmem); + iounmap(local->amem); + /* Do bother checking to see if these succeed or not */ + i = pcmcia_release_window(local->amem_handle); + if (i != 0) + DEBUG(0, "ReleaseWindow(local->amem) ret = %x\n", i); + i = pcmcia_release_window(local->rmem_handle); + if (i != 0) + DEBUG(0, "ReleaseWindow(local->rmem) ret = %x\n", i); + pcmcia_disable_device(link); + + DEBUG(2, "ray_release ending\n"); } static int ray_suspend(struct pcmcia_device *link) @@ -831,237 +858,243 @@ static int ray_resume(struct pcmcia_device *link) static int ray_dev_init(struct net_device *dev) { #ifdef RAY_IMMEDIATE_INIT - int i; -#endif /* RAY_IMMEDIATE_INIT */ - ray_dev_t *local = netdev_priv(dev); - struct pcmcia_device *link = local->finder; - - DEBUG(1,"ray_dev_init(dev=%p)\n",dev); - if (!(pcmcia_dev_present(link))) { - DEBUG(2,"ray_dev_init - device not present\n"); - return -1; - } + int i; +#endif /* RAY_IMMEDIATE_INIT */ + ray_dev_t *local = netdev_priv(dev); + struct pcmcia_device *link = local->finder; + + DEBUG(1, "ray_dev_init(dev=%p)\n", dev); + if (!(pcmcia_dev_present(link))) { + DEBUG(2, "ray_dev_init - device not present\n"); + return -1; + } #ifdef RAY_IMMEDIATE_INIT - /* Download startup parameters */ - if ( (i = dl_startup_params(dev)) < 0) - { - printk(KERN_INFO "ray_dev_init dl_startup_params failed - " - "returns 0x%x\n",i); - return -1; - } -#else /* RAY_IMMEDIATE_INIT */ - /* Postpone the card init so that we can still configure the card, - * for example using the Wireless Extensions. The init will happen - * in ray_open() - Jean II */ - DEBUG(1,"ray_dev_init: postponing card init to ray_open() ; Status = %d\n", - local->card_status); -#endif /* RAY_IMMEDIATE_INIT */ - - /* copy mac and broadcast addresses to linux device */ - memcpy(&dev->dev_addr, &local->sparm.b4.a_mac_addr, ADDRLEN); - memset(dev->broadcast, 0xff, ETH_ALEN); - - DEBUG(2,"ray_dev_init ending\n"); - return 0; + /* Download startup parameters */ + if ((i = dl_startup_params(dev)) < 0) { + printk(KERN_INFO "ray_dev_init dl_startup_params failed - " + "returns 0x%x\n", i); + return -1; + } +#else /* RAY_IMMEDIATE_INIT */ + /* Postpone the card init so that we can still configure the card, + * for example using the Wireless Extensions. The init will happen + * in ray_open() - Jean II */ + DEBUG(1, + "ray_dev_init: postponing card init to ray_open() ; Status = %d\n", + local->card_status); +#endif /* RAY_IMMEDIATE_INIT */ + + /* copy mac and broadcast addresses to linux device */ + memcpy(&dev->dev_addr, &local->sparm.b4.a_mac_addr, ADDRLEN); + memset(dev->broadcast, 0xff, ETH_ALEN); + + DEBUG(2, "ray_dev_init ending\n"); + return 0; } + /*===========================================================================*/ static int ray_dev_config(struct net_device *dev, struct ifmap *map) { - ray_dev_t *local = netdev_priv(dev); - struct pcmcia_device *link = local->finder; - /* Dummy routine to satisfy device structure */ - DEBUG(1,"ray_dev_config(dev=%p,ifmap=%p)\n",dev,map); - if (!(pcmcia_dev_present(link))) { - DEBUG(2,"ray_dev_config - device not present\n"); - return -1; - } + ray_dev_t *local = netdev_priv(dev); + struct pcmcia_device *link = local->finder; + /* Dummy routine to satisfy device structure */ + DEBUG(1, "ray_dev_config(dev=%p,ifmap=%p)\n", dev, map); + if (!(pcmcia_dev_present(link))) { + DEBUG(2, "ray_dev_config - device not present\n"); + return -1; + } - return 0; + return 0; } + /*===========================================================================*/ static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev) { - ray_dev_t *local = netdev_priv(dev); - struct pcmcia_device *link = local->finder; - short length = skb->len; - - if (!(pcmcia_dev_present(link))) { - DEBUG(2,"ray_dev_start_xmit - device not present\n"); - return -1; - } - DEBUG(3,"ray_dev_start_xmit(skb=%p, dev=%p)\n",skb,dev); - if (local->authentication_state == NEED_TO_AUTH) { - DEBUG(0,"ray_cs Sending authentication request.\n"); - if (!build_auth_frame (local, local->auth_id, OPEN_AUTH_REQUEST)) { - local->authentication_state = AUTHENTICATED; - netif_stop_queue(dev); - return 1; - } - } - - if (length < ETH_ZLEN) - { - if (skb_padto(skb, ETH_ZLEN)) - return 0; - length = ETH_ZLEN; - } - switch (ray_hw_xmit( skb->data, length, dev, DATA_TYPE)) { - case XMIT_NO_CCS: - case XMIT_NEED_AUTH: - netif_stop_queue(dev); - return 1; - case XMIT_NO_INTR: - case XMIT_MSG_BAD: - case XMIT_OK: - default: - dev->trans_start = jiffies; - dev_kfree_skb(skb); - return 0; - } - return 0; + ray_dev_t *local = netdev_priv(dev); + struct pcmcia_device *link = local->finder; + short length = skb->len; + + if (!(pcmcia_dev_present(link))) { + DEBUG(2, "ray_dev_start_xmit - device not present\n"); + return -1; + } + DEBUG(3, "ray_dev_start_xmit(skb=%p, dev=%p)\n", skb, dev); + if (local->authentication_state == NEED_TO_AUTH) { + DEBUG(0, "ray_cs Sending authentication request.\n"); + if (!build_auth_frame(local, local->auth_id, OPEN_AUTH_REQUEST)) { + local->authentication_state = AUTHENTICATED; + netif_stop_queue(dev); + return 1; + } + } + + if (length < ETH_ZLEN) { + if (skb_padto(skb, ETH_ZLEN)) + return 0; + length = ETH_ZLEN; + } + switch (ray_hw_xmit(skb->data, length, dev, DATA_TYPE)) { + case XMIT_NO_CCS: + case XMIT_NEED_AUTH: + netif_stop_queue(dev); + return 1; + case XMIT_NO_INTR: + case XMIT_MSG_BAD: + case XMIT_OK: + default: + dev->trans_start = jiffies; + dev_kfree_skb(skb); + return 0; + } + return 0; } /* ray_dev_start_xmit */ + /*===========================================================================*/ -static int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev, - UCHAR msg_type) -{ - ray_dev_t *local = netdev_priv(dev); - struct ccs __iomem *pccs; - int ccsindex; - int offset; - struct tx_msg __iomem *ptx; /* Address of xmit buffer in PC space */ - short int addr; /* Address of xmit buffer in card space */ - - DEBUG(3,"ray_hw_xmit(data=%p, len=%d, dev=%p)\n",data,len,dev); - if (len + TX_HEADER_LENGTH > TX_BUF_SIZE) - { - printk(KERN_INFO "ray_hw_xmit packet too large: %d bytes\n",len); - return XMIT_MSG_BAD; - } +static int ray_hw_xmit(unsigned char *data, int len, struct net_device *dev, + UCHAR msg_type) +{ + ray_dev_t *local = netdev_priv(dev); + struct ccs __iomem *pccs; + int ccsindex; + int offset; + struct tx_msg __iomem *ptx; /* Address of xmit buffer in PC space */ + short int addr; /* Address of xmit buffer in card space */ + + DEBUG(3, "ray_hw_xmit(data=%p, len=%d, dev=%p)\n", data, len, dev); + if (len + TX_HEADER_LENGTH > TX_BUF_SIZE) { + printk(KERN_INFO "ray_hw_xmit packet too large: %d bytes\n", + len); + return XMIT_MSG_BAD; + } switch (ccsindex = get_free_tx_ccs(local)) { case ECCSBUSY: - DEBUG(2,"ray_hw_xmit tx_ccs table busy\n"); + DEBUG(2, "ray_hw_xmit tx_ccs table busy\n"); case ECCSFULL: - DEBUG(2,"ray_hw_xmit No free tx ccs\n"); + DEBUG(2, "ray_hw_xmit No free tx ccs\n"); case ECARDGONE: - netif_stop_queue(dev); - return XMIT_NO_CCS; + netif_stop_queue(dev); + return XMIT_NO_CCS; default: break; } - addr = TX_BUF_BASE + (ccsindex << 11); - - if (msg_type == DATA_TYPE) { - local->stats.tx_bytes += len; - local->stats.tx_packets++; - } - - ptx = local->sram + addr; - - ray_build_header(local, ptx, msg_type, data); - if (translate) { - offset = translate_frame(local, ptx, data, len); - } - else { /* Encapsulate frame */ - /* TBD TIB length will move address of ptx->var */ - memcpy_toio(&ptx->var, data, len); - offset = 0; - } - - /* fill in the CCS */ - pccs = ccs_base(local) + ccsindex; - len += TX_HEADER_LENGTH + offset; - writeb(CCS_TX_REQUEST, &pccs->cmd); - writeb(addr >> 8, &pccs->var.tx_request.tx_data_ptr[0]); - writeb(local->tib_length, &pccs->var.tx_request.tx_data_ptr[1]); - writeb(len >> 8, &pccs->var.tx_request.tx_data_length[0]); - writeb(len & 0xff, &pccs->var.tx_request.tx_data_length[1]); + addr = TX_BUF_BASE + (ccsindex << 11); + + if (msg_type == DATA_TYPE) { + local->stats.tx_bytes += len; + local->stats.tx_packets++; + } + + ptx = local->sram + addr; + + ray_build_header(local, ptx, msg_type, data); + if (translate) { + offset = translate_frame(local, ptx, data, len); + } else { /* Encapsulate frame */ + /* TBD TIB length will move address of ptx->var */ + memcpy_toio(&ptx->var, data, len); + offset = 0; + } + + /* fill in the CCS */ + pccs = ccs_base(local) + ccsindex; + len += TX_HEADER_LENGTH + offset; + writeb(CCS_TX_REQUEST, &pccs->cmd); + writeb(addr >> 8, &pccs->var.tx_request.tx_data_ptr[0]); + writeb(local->tib_length, &pccs->var.tx_request.tx_data_ptr[1]); + writeb(len >> 8, &pccs->var.tx_request.tx_data_length[0]); + writeb(len & 0xff, &pccs->var.tx_request.tx_data_length[1]); /* TBD still need psm_cam? */ - writeb(PSM_CAM, &pccs->var.tx_request.pow_sav_mode); - writeb(local->net_default_tx_rate, &pccs->var.tx_request.tx_rate); - writeb(0, &pccs->var.tx_request.antenna); - DEBUG(3,"ray_hw_xmit default_tx_rate = 0x%x\n",\ - local->net_default_tx_rate); - - /* Interrupt the firmware to process the command */ - if (interrupt_ecf(local, ccsindex)) { - DEBUG(2,"ray_hw_xmit failed - ECF not ready for intr\n"); + writeb(PSM_CAM, &pccs->var.tx_request.pow_sav_mode); + writeb(local->net_default_tx_rate, &pccs->var.tx_request.tx_rate); + writeb(0, &pccs->var.tx_request.antenna); + DEBUG(3, "ray_hw_xmit default_tx_rate = 0x%x\n", + local->net_default_tx_rate); + + /* Interrupt the firmware to process the command */ + if (interrupt_ecf(local, ccsindex)) { + DEBUG(2, "ray_hw_xmit failed - ECF not ready for intr\n"); /* TBD very inefficient to copy packet to buffer, and then not send it, but the alternative is to queue the messages and that won't be done for a while. Maybe set tbusy until a CCS is free? */ - writeb(CCS_BUFFER_FREE, &pccs->buffer_status); - return XMIT_NO_INTR; - } - return XMIT_OK; + writeb(CCS_BUFFER_FREE, &pccs->buffer_status); + return XMIT_NO_INTR; + } + return XMIT_OK; } /* end ray_hw_xmit */ + /*===========================================================================*/ -static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx, unsigned char *data, - int len) -{ - __be16 proto = ((struct ethhdr *)data)->h_proto; - if (ntohs(proto) >= 1536) { /* DIX II ethernet frame */ - DEBUG(3,"ray_cs translate_frame DIX II\n"); - /* Copy LLC header to card buffer */ - memcpy_toio(&ptx->var, eth2_llc, sizeof(eth2_llc)); - memcpy_toio( ((void __iomem *)&ptx->var) + sizeof(eth2_llc), (UCHAR *)&proto, 2); - if (proto == htons(ETH_P_AARP) || proto == htons(ETH_P_IPX)) { - /* This is the selective translation table, only 2 entries */ - writeb(0xf8, &((struct snaphdr_t __iomem *)ptx->var)->org[3]); - } - /* Copy body of ethernet packet without ethernet header */ - memcpy_toio((void __iomem *)&ptx->var + sizeof(struct snaphdr_t), \ - data + ETH_HLEN, len - ETH_HLEN); - return (int) sizeof(struct snaphdr_t) - ETH_HLEN; - } - else { /* already 802 type, and proto is length */ - DEBUG(3,"ray_cs translate_frame 802\n"); - if (proto == htons(0xffff)) { /* evil netware IPX 802.3 without LLC */ - DEBUG(3,"ray_cs translate_frame evil IPX\n"); - memcpy_toio(&ptx->var, data + ETH_HLEN, len - ETH_HLEN); - return 0 - ETH_HLEN; - } - memcpy_toio(&ptx->var, data + ETH_HLEN, len - ETH_HLEN); - return 0 - ETH_HLEN; - } - /* TBD do other frame types */ +static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx, + unsigned char *data, int len) +{ + __be16 proto = ((struct ethhdr *)data)->h_proto; + if (ntohs(proto) >= 1536) { /* DIX II ethernet frame */ + DEBUG(3, "ray_cs translate_frame DIX II\n"); + /* Copy LLC header to card buffer */ + memcpy_toio(&ptx->var, eth2_llc, sizeof(eth2_llc)); + memcpy_toio(((void __iomem *)&ptx->var) + sizeof(eth2_llc), + (UCHAR *) &proto, 2); + if (proto == htons(ETH_P_AARP) || proto == htons(ETH_P_IPX)) { + /* This is the selective translation table, only 2 entries */ + writeb(0xf8, + &((struct snaphdr_t __iomem *)ptx->var)->org[3]); + } + /* Copy body of ethernet packet without ethernet header */ + memcpy_toio((void __iomem *)&ptx->var + + sizeof(struct snaphdr_t), data + ETH_HLEN, + len - ETH_HLEN); + return (int)sizeof(struct snaphdr_t) - ETH_HLEN; + } else { /* already 802 type, and proto is length */ + DEBUG(3, "ray_cs translate_frame 802\n"); + if (proto == htons(0xffff)) { /* evil netware IPX 802.3 without LLC */ + DEBUG(3, "ray_cs translate_frame evil IPX\n"); + memcpy_toio(&ptx->var, data + ETH_HLEN, len - ETH_HLEN); + return 0 - ETH_HLEN; + } + memcpy_toio(&ptx->var, data + ETH_HLEN, len - ETH_HLEN); + return 0 - ETH_HLEN; + } + /* TBD do other frame types */ } /* end translate_frame */ + /*===========================================================================*/ -static void ray_build_header(ray_dev_t *local, struct tx_msg __iomem *ptx, UCHAR msg_type, - unsigned char *data) +static void ray_build_header(ray_dev_t *local, struct tx_msg __iomem *ptx, + UCHAR msg_type, unsigned char *data) { - writeb(PROTOCOL_VER | msg_type, &ptx->mac.frame_ctl_1); + writeb(PROTOCOL_VER | msg_type, &ptx->mac.frame_ctl_1); /*** IEEE 802.11 Address field assignments ************* - TODS FROMDS addr_1 addr_2 addr_3 addr_4 -Adhoc 0 0 dest src (terminal) BSSID N/A -AP to Terminal 0 1 dest AP(BSSID) source N/A -Terminal to AP 1 0 AP(BSSID) src (terminal) dest N/A -AP to AP 1 1 dest AP src AP dest source + TODS FROMDS addr_1 addr_2 addr_3 addr_4 +Adhoc 0 0 dest src (terminal) BSSID N/A +AP to Terminal 0 1 dest AP(BSSID) source N/A +Terminal to AP 1 0 AP(BSSID) src (terminal) dest N/A +AP to AP 1 1 dest AP src AP dest source *******************************************************/ - if (local->net_type == ADHOC) { - writeb(0, &ptx->mac.frame_ctl_2); - memcpy_toio(ptx->mac.addr_1, ((struct ethhdr *)data)->h_dest, 2 * ADDRLEN); - memcpy_toio(ptx->mac.addr_3, local->bss_id, ADDRLEN); - } - else /* infrastructure */ - { - if (local->sparm.b4.a_acting_as_ap_status) - { - writeb(FC2_FROM_DS, &ptx->mac.frame_ctl_2); - memcpy_toio(ptx->mac.addr_1, ((struct ethhdr *)data)->h_dest, ADDRLEN); - memcpy_toio(ptx->mac.addr_2, local->bss_id, 6); - memcpy_toio(ptx->mac.addr_3, ((struct ethhdr *)data)->h_source, ADDRLEN); - } - else /* Terminal */ - { - writeb(FC2_TO_DS, &ptx->mac.frame_ctl_2); - memcpy_toio(ptx->mac.addr_1, local->bss_id, ADDRLEN); - memcpy_toio(ptx->mac.addr_2, ((struct ethhdr *)data)->h_source, ADDRLEN); - memcpy_toio(ptx->mac.addr_3, ((struct ethhdr *)data)->h_dest, ADDRLEN); - } - } + if (local->net_type == ADHOC) { + writeb(0, &ptx->mac.frame_ctl_2); + memcpy_toio(ptx->mac.addr_1, ((struct ethhdr *)data)->h_dest, + 2 * ADDRLEN); + memcpy_toio(ptx->mac.addr_3, local->bss_id, ADDRLEN); + } else { /* infrastructure */ + + if (local->sparm.b4.a_acting_as_ap_status) { + writeb(FC2_FROM_DS, &ptx->mac.frame_ctl_2); + memcpy_toio(ptx->mac.addr_1, + ((struct ethhdr *)data)->h_dest, ADDRLEN); + memcpy_toio(ptx->mac.addr_2, local->bss_id, 6); + memcpy_toio(ptx->mac.addr_3, + ((struct ethhdr *)data)->h_source, ADDRLEN); + } else { /* Terminal */ + + writeb(FC2_TO_DS, &ptx->mac.frame_ctl_2); + memcpy_toio(ptx->mac.addr_1, local->bss_id, ADDRLEN); + memcpy_toio(ptx->mac.addr_2, + ((struct ethhdr *)data)->h_source, ADDRLEN); + memcpy_toio(ptx->mac.addr_3, + ((struct ethhdr *)data)->h_dest, ADDRLEN); + } + } } /* end encapsulate_frame */ - /*===========================================================================*/ static void netdev_get_drvinfo(struct net_device *dev, @@ -1071,7 +1104,7 @@ static void netdev_get_drvinfo(struct net_device *dev, } static const struct ethtool_ops netdev_ethtool_ops = { - .get_drvinfo = netdev_get_drvinfo, + .get_drvinfo = netdev_get_drvinfo, }; /*====================================================================*/ @@ -1081,9 +1114,7 @@ static const struct ethtool_ops netdev_ethtool_ops = { * Wireless Handler : get protocol name */ static int ray_get_name(struct net_device *dev, - struct iw_request_info *info, - char *cwrq, - char *extra) + struct iw_request_info *info, char *cwrq, char *extra) { strcpy(cwrq, "IEEE 802.11-FH"); return 0; @@ -1095,14 +1126,13 @@ static int ray_get_name(struct net_device *dev, */ static int ray_set_freq(struct net_device *dev, struct iw_request_info *info, - struct iw_freq *fwrq, - char *extra) + struct iw_freq *fwrq, char *extra) { ray_dev_t *local = netdev_priv(dev); - int err = -EINPROGRESS; /* Call commit handler */ + int err = -EINPROGRESS; /* Call commit handler */ /* Reject if card is already initialised */ - if(local->card_status != CARD_AWAITING_PARAM) + if (local->card_status != CARD_AWAITING_PARAM) return -EBUSY; /* Setting by channel number */ @@ -1113,15 +1143,14 @@ static int ray_set_freq(struct net_device *dev, return err; } - + /*------------------------------------------------------------------*/ /* * Wireless Handler : get frequency */ static int ray_get_freq(struct net_device *dev, struct iw_request_info *info, - struct iw_freq *fwrq, - char *extra) + struct iw_freq *fwrq, char *extra) { ray_dev_t *local = netdev_priv(dev); @@ -1136,22 +1165,21 @@ static int ray_get_freq(struct net_device *dev, */ static int ray_set_essid(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) + struct iw_point *dwrq, char *extra) { ray_dev_t *local = netdev_priv(dev); /* Reject if card is already initialised */ - if(local->card_status != CARD_AWAITING_PARAM) + if (local->card_status != CARD_AWAITING_PARAM) return -EBUSY; /* Check if we asked for `any' */ - if(dwrq->flags == 0) { + if (dwrq->flags == 0) { /* Corey : can you do that ? */ return -EOPNOTSUPP; } else { /* Check the size of the string */ - if(dwrq->length > IW_ESSID_MAX_SIZE) { + if (dwrq->length > IW_ESSID_MAX_SIZE) { return -E2BIG; } @@ -1160,7 +1188,7 @@ static int ray_set_essid(struct net_device *dev, memcpy(local->sparm.b5.a_current_ess_id, extra, dwrq->length); } - return -EINPROGRESS; /* Call commit handler */ + return -EINPROGRESS; /* Call commit handler */ } /*------------------------------------------------------------------*/ @@ -1169,8 +1197,7 @@ static int ray_set_essid(struct net_device *dev, */ static int ray_get_essid(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) + struct iw_point *dwrq, char *extra) { ray_dev_t *local = netdev_priv(dev); @@ -1179,7 +1206,7 @@ static int ray_get_essid(struct net_device *dev, /* Push it out ! */ dwrq->length = strlen(extra); - dwrq->flags = 1; /* active */ + dwrq->flags = 1; /* active */ return 0; } @@ -1189,9 +1216,8 @@ static int ray_get_essid(struct net_device *dev, * Wireless Handler : get AP address */ static int ray_get_wap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *awrq, - char *extra) + struct iw_request_info *info, + struct sockaddr *awrq, char *extra) { ray_dev_t *local = netdev_priv(dev); @@ -1207,25 +1233,24 @@ static int ray_get_wap(struct net_device *dev, */ static int ray_set_rate(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) + struct iw_param *vwrq, char *extra) { ray_dev_t *local = netdev_priv(dev); /* Reject if card is already initialised */ - if(local->card_status != CARD_AWAITING_PARAM) + if (local->card_status != CARD_AWAITING_PARAM) return -EBUSY; /* Check if rate is in range */ - if((vwrq->value != 1000000) && (vwrq->value != 2000000)) + if ((vwrq->value != 1000000) && (vwrq->value != 2000000)) return -EINVAL; /* Hack for 1.5 Mb/s instead of 2 Mb/s */ - if((local->fw_ver == 0x55) && /* Please check */ - (vwrq->value == 2000000)) + if ((local->fw_ver == 0x55) && /* Please check */ + (vwrq->value == 2000000)) local->net_default_tx_rate = 3; else - local->net_default_tx_rate = vwrq->value/500000; + local->net_default_tx_rate = vwrq->value / 500000; return 0; } @@ -1236,16 +1261,15 @@ static int ray_set_rate(struct net_device *dev, */ static int ray_get_rate(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) + struct iw_param *vwrq, char *extra) { ray_dev_t *local = netdev_priv(dev); - if(local->net_default_tx_rate == 3) - vwrq->value = 2000000; /* Hum... */ + if (local->net_default_tx_rate == 3) + vwrq->value = 2000000; /* Hum... */ else vwrq->value = local->net_default_tx_rate * 500000; - vwrq->fixed = 0; /* We are in auto mode */ + vwrq->fixed = 0; /* We are in auto mode */ return 0; } @@ -1256,43 +1280,40 @@ static int ray_get_rate(struct net_device *dev, */ static int ray_set_rts(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) + struct iw_param *vwrq, char *extra) { ray_dev_t *local = netdev_priv(dev); int rthr = vwrq->value; /* Reject if card is already initialised */ - if(local->card_status != CARD_AWAITING_PARAM) + if (local->card_status != CARD_AWAITING_PARAM) return -EBUSY; /* if(wrq->u.rts.fixed == 0) we should complain */ - if(vwrq->disabled) + if (vwrq->disabled) rthr = 32767; else { - if((rthr < 0) || (rthr > 2347)) /* What's the max packet size ??? */ + if ((rthr < 0) || (rthr > 2347)) /* What's the max packet size ??? */ return -EINVAL; } local->sparm.b5.a_rts_threshold[0] = (rthr >> 8) & 0xFF; local->sparm.b5.a_rts_threshold[1] = rthr & 0xFF; - return -EINPROGRESS; /* Call commit handler */ + return -EINPROGRESS; /* Call commit handler */ } - /*------------------------------------------------------------------*/ /* * Wireless Handler : get RTS threshold */ static int ray_get_rts(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) + struct iw_param *vwrq, char *extra) { ray_dev_t *local = netdev_priv(dev); vwrq->value = (local->sparm.b5.a_rts_threshold[0] << 8) - + local->sparm.b5.a_rts_threshold[1]; + + local->sparm.b5.a_rts_threshold[1]; vwrq->disabled = (vwrq->value == 32767); vwrq->fixed = 1; @@ -1305,27 +1326,26 @@ static int ray_get_rts(struct net_device *dev, */ static int ray_set_frag(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) + struct iw_param *vwrq, char *extra) { ray_dev_t *local = netdev_priv(dev); int fthr = vwrq->value; /* Reject if card is already initialised */ - if(local->card_status != CARD_AWAITING_PARAM) + if (local->card_status != CARD_AWAITING_PARAM) return -EBUSY; /* if(wrq->u.frag.fixed == 0) should complain */ - if(vwrq->disabled) + if (vwrq->disabled) fthr = 32767; else { - if((fthr < 256) || (fthr > 2347)) /* To check out ! */ + if ((fthr < 256) || (fthr > 2347)) /* To check out ! */ return -EINVAL; } local->sparm.b5.a_frag_threshold[0] = (fthr >> 8) & 0xFF; local->sparm.b5.a_frag_threshold[1] = fthr & 0xFF; - return -EINPROGRESS; /* Call commit handler */ + return -EINPROGRESS; /* Call commit handler */ } /*------------------------------------------------------------------*/ @@ -1334,13 +1354,12 @@ static int ray_set_frag(struct net_device *dev, */ static int ray_get_frag(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) + struct iw_param *vwrq, char *extra) { ray_dev_t *local = netdev_priv(dev); vwrq->value = (local->sparm.b5.a_frag_threshold[0] << 8) - + local->sparm.b5.a_frag_threshold[1]; + + local->sparm.b5.a_frag_threshold[1]; vwrq->disabled = (vwrq->value == 32767); vwrq->fixed = 1; @@ -1352,23 +1371,20 @@ static int ray_get_frag(struct net_device *dev, * Wireless Handler : set Mode of Operation */ static int ray_set_mode(struct net_device *dev, - struct iw_request_info *info, - __u32 *uwrq, - char *extra) + struct iw_request_info *info, __u32 *uwrq, char *extra) { ray_dev_t *local = netdev_priv(dev); - int err = -EINPROGRESS; /* Call commit handler */ + int err = -EINPROGRESS; /* Call commit handler */ char card_mode = 1; /* Reject if card is already initialised */ - if(local->card_status != CARD_AWAITING_PARAM) + if (local->card_status != CARD_AWAITING_PARAM) return -EBUSY; - switch (*uwrq) - { + switch (*uwrq) { case IW_MODE_ADHOC: card_mode = 0; - // Fall through + /* Fall through */ case IW_MODE_INFRA: local->sparm.b5.a_network_type = card_mode; break; @@ -1384,13 +1400,11 @@ static int ray_set_mode(struct net_device *dev, * Wireless Handler : get Mode of Operation */ static int ray_get_mode(struct net_device *dev, - struct iw_request_info *info, - __u32 *uwrq, - char *extra) + struct iw_request_info *info, __u32 *uwrq, char *extra) { ray_dev_t *local = netdev_priv(dev); - if(local->sparm.b5.a_network_type) + if (local->sparm.b5.a_network_type) *uwrq = IW_MODE_INFRA; else *uwrq = IW_MODE_ADHOC; @@ -1404,12 +1418,11 @@ static int ray_get_mode(struct net_device *dev, */ static int ray_get_range(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) + struct iw_point *dwrq, char *extra) { - struct iw_range *range = (struct iw_range *) extra; + struct iw_range *range = (struct iw_range *)extra; - memset((char *) range, 0, sizeof(struct iw_range)); + memset((char *)range, 0, sizeof(struct iw_range)); /* Set the length (very important for backward compatibility) */ dwrq->length = sizeof(struct iw_range); @@ -1420,7 +1433,7 @@ static int ray_get_range(struct net_device *dev, /* Set information in the range struct */ range->throughput = 1.1 * 1000 * 1000; /* Put the right number here */ - range->num_channels = hop_pattern_length[(int)country]; + range->num_channels = hop_pattern_length[(int)country]; range->num_frequency = 0; range->max_qual.qual = 0; range->max_qual.level = 255; /* What's the correct value ? */ @@ -1437,8 +1450,7 @@ static int ray_get_range(struct net_device *dev, */ static int ray_set_framing(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) + union iwreq_data *wrqu, char *extra) { translate = *(extra); /* Set framing mode */ @@ -1451,8 +1463,7 @@ static int ray_set_framing(struct net_device *dev, */ static int ray_get_framing(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) + union iwreq_data *wrqu, char *extra) { *(extra) = translate; @@ -1465,8 +1476,7 @@ static int ray_get_framing(struct net_device *dev, */ static int ray_get_country(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) + union iwreq_data *wrqu, char *extra) { *(extra) = country; @@ -1477,11 +1487,10 @@ static int ray_get_country(struct net_device *dev, /* * Commit handler : called after a bunch of SET operations */ -static int ray_commit(struct net_device *dev, - struct iw_request_info *info, /* NULL */ - void *zwrq, /* NULL */ - char *extra) /* NULL */ -{ +static int ray_commit(struct net_device *dev, struct iw_request_info *info, /* NULL */ + void *zwrq, /* NULL */ + char *extra) +{ /* NULL */ return 0; } @@ -1489,33 +1498,34 @@ static int ray_commit(struct net_device *dev, /* * Stats handler : return Wireless Stats */ -static iw_stats * ray_get_wireless_stats(struct net_device * dev) +static iw_stats *ray_get_wireless_stats(struct net_device *dev) { - ray_dev_t * local = netdev_priv(dev); - struct pcmcia_device *link = local->finder; - struct status __iomem *p = local->sram + STATUS_BASE; + ray_dev_t *local = netdev_priv(dev); + struct pcmcia_device *link = local->finder; + struct status __iomem *p = local->sram + STATUS_BASE; - if(local == (ray_dev_t *) NULL) - return (iw_stats *) NULL; + if (local == (ray_dev_t *) NULL) + return (iw_stats *) NULL; - local->wstats.status = local->card_status; + local->wstats.status = local->card_status; #ifdef WIRELESS_SPY - if((local->spy_data.spy_number > 0) && (local->sparm.b5.a_network_type == 0)) - { - /* Get it from the first node in spy list */ - local->wstats.qual.qual = local->spy_data.spy_stat[0].qual; - local->wstats.qual.level = local->spy_data.spy_stat[0].level; - local->wstats.qual.noise = local->spy_data.spy_stat[0].noise; - local->wstats.qual.updated = local->spy_data.spy_stat[0].updated; - } + if ((local->spy_data.spy_number > 0) + && (local->sparm.b5.a_network_type == 0)) { + /* Get it from the first node in spy list */ + local->wstats.qual.qual = local->spy_data.spy_stat[0].qual; + local->wstats.qual.level = local->spy_data.spy_stat[0].level; + local->wstats.qual.noise = local->spy_data.spy_stat[0].noise; + local->wstats.qual.updated = + local->spy_data.spy_stat[0].updated; + } #endif /* WIRELESS_SPY */ - if(pcmcia_dev_present(link)) { - local->wstats.qual.noise = readb(&p->rxnoise); - local->wstats.qual.updated |= 4; - } + if (pcmcia_dev_present(link)) { + local->wstats.qual.noise = readb(&p->rxnoise); + local->wstats.qual.updated |= 4; + } - return &local->wstats; + return &local->wstats; } /* end ray_get_wireless_stats */ /*------------------------------------------------------------------*/ @@ -1523,1159 +1533,1264 @@ static iw_stats * ray_get_wireless_stats(struct net_device * dev) * Structures to export the Wireless Handlers */ -static const iw_handler ray_handler[] = { - [SIOCSIWCOMMIT-SIOCIWFIRST] = (iw_handler) ray_commit, - [SIOCGIWNAME -SIOCIWFIRST] = (iw_handler) ray_get_name, - [SIOCSIWFREQ -SIOCIWFIRST] = (iw_handler) ray_set_freq, - [SIOCGIWFREQ -SIOCIWFIRST] = (iw_handler) ray_get_freq, - [SIOCSIWMODE -SIOCIWFIRST] = (iw_handler) ray_set_mode, - [SIOCGIWMODE -SIOCIWFIRST] = (iw_handler) ray_get_mode, - [SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) ray_get_range, +static const iw_handler ray_handler[] = { + [SIOCSIWCOMMIT - SIOCIWFIRST] = (iw_handler) ray_commit, + [SIOCGIWNAME - SIOCIWFIRST] = (iw_handler) ray_get_name, + [SIOCSIWFREQ - SIOCIWFIRST] = (iw_handler) ray_set_freq, + [SIOCGIWFREQ - SIOCIWFIRST] = (iw_handler) ray_get_freq, + [SIOCSIWMODE - SIOCIWFIRST] = (iw_handler) ray_set_mode, + [SIOCGIWMODE - SIOCIWFIRST] = (iw_handler) ray_get_mode, + [SIOCGIWRANGE - SIOCIWFIRST] = (iw_handler) ray_get_range, #ifdef WIRELESS_SPY - [SIOCSIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_set_spy, - [SIOCGIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_get_spy, - [SIOCSIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy, - [SIOCGIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy, -#endif /* WIRELESS_SPY */ - [SIOCGIWAP -SIOCIWFIRST] = (iw_handler) ray_get_wap, - [SIOCSIWESSID -SIOCIWFIRST] = (iw_handler) ray_set_essid, - [SIOCGIWESSID -SIOCIWFIRST] = (iw_handler) ray_get_essid, - [SIOCSIWRATE -SIOCIWFIRST] = (iw_handler) ray_set_rate, - [SIOCGIWRATE -SIOCIWFIRST] = (iw_handler) ray_get_rate, - [SIOCSIWRTS -SIOCIWFIRST] = (iw_handler) ray_set_rts, - [SIOCGIWRTS -SIOCIWFIRST] = (iw_handler) ray_get_rts, - [SIOCSIWFRAG -SIOCIWFIRST] = (iw_handler) ray_set_frag, - [SIOCGIWFRAG -SIOCIWFIRST] = (iw_handler) ray_get_frag, + [SIOCSIWSPY - SIOCIWFIRST] = (iw_handler) iw_handler_set_spy, + [SIOCGIWSPY - SIOCIWFIRST] = (iw_handler) iw_handler_get_spy, + [SIOCSIWTHRSPY - SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy, + [SIOCGIWTHRSPY - SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy, +#endif /* WIRELESS_SPY */ + [SIOCGIWAP - SIOCIWFIRST] = (iw_handler) ray_get_wap, + [SIOCSIWESSID - SIOCIWFIRST] = (iw_handler) ray_set_essid, + [SIOCGIWESSID - SIOCIWFIRST] = (iw_handler) ray_get_essid, + [SIOCSIWRATE - SIOCIWFIRST] = (iw_handler) ray_set_rate, + [SIOCGIWRATE - SIOCIWFIRST] = (iw_handler) ray_get_rate, + [SIOCSIWRTS - SIOCIWFIRST] = (iw_handler) ray_set_rts, + [SIOCGIWRTS - SIOCIWFIRST] = (iw_handler) ray_get_rts, + [SIOCSIWFRAG - SIOCIWFIRST] = (iw_handler) ray_set_frag, + [SIOCGIWFRAG - SIOCIWFIRST] = (iw_handler) ray_get_frag, }; -#define SIOCSIPFRAMING SIOCIWFIRSTPRIV /* Set framing mode */ +#define SIOCSIPFRAMING SIOCIWFIRSTPRIV /* Set framing mode */ #define SIOCGIPFRAMING SIOCIWFIRSTPRIV + 1 /* Get framing mode */ #define SIOCGIPCOUNTRY SIOCIWFIRSTPRIV + 3 /* Get country code */ -static const iw_handler ray_private_handler[] = { +static const iw_handler ray_private_handler[] = { [0] = (iw_handler) ray_set_framing, [1] = (iw_handler) ray_get_framing, [3] = (iw_handler) ray_get_country, }; -static const struct iw_priv_args ray_private_args[] = { +static const struct iw_priv_args ray_private_args[] = { /* cmd, set_args, get_args, name */ -{ SIOCSIPFRAMING, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "set_framing" }, -{ SIOCGIPFRAMING, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "get_framing" }, -{ SIOCGIPCOUNTRY, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "get_country" }, + {SIOCSIPFRAMING, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, + "set_framing"}, + {SIOCGIPFRAMING, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, + "get_framing"}, + {SIOCGIPCOUNTRY, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, + "get_country"}, }; -static const struct iw_handler_def ray_handler_def = -{ - .num_standard = ARRAY_SIZE(ray_handler), - .num_private = ARRAY_SIZE(ray_private_handler), +static const struct iw_handler_def ray_handler_def = { + .num_standard = ARRAY_SIZE(ray_handler), + .num_private = ARRAY_SIZE(ray_private_handler), .num_private_args = ARRAY_SIZE(ray_private_args), - .standard = ray_handler, - .private = ray_private_handler, - .private_args = ray_private_args, + .standard = ray_handler, + .private = ray_private_handler, + .private_args = ray_private_args, .get_wireless_stats = ray_get_wireless_stats, }; /*===========================================================================*/ static int ray_open(struct net_device *dev) { - ray_dev_t *local = netdev_priv(dev); - struct pcmcia_device *link; - link = local->finder; - - DEBUG(1, "ray_open('%s')\n", dev->name); + ray_dev_t *local = netdev_priv(dev); + struct pcmcia_device *link; + link = local->finder; - if (link->open == 0) - local->num_multi = 0; - link->open++; + DEBUG(1, "ray_open('%s')\n", dev->name); - /* If the card is not started, time to start it ! - Jean II */ - if(local->card_status == CARD_AWAITING_PARAM) { - int i; + if (link->open == 0) + local->num_multi = 0; + link->open++; - DEBUG(1,"ray_open: doing init now !\n"); + /* If the card is not started, time to start it ! - Jean II */ + if (local->card_status == CARD_AWAITING_PARAM) { + int i; - /* Download startup parameters */ - if ( (i = dl_startup_params(dev)) < 0) - { - printk(KERN_INFO "ray_dev_init dl_startup_params failed - " - "returns 0x%x\n",i); - return -1; - } - } - - if (sniffer) netif_stop_queue(dev); - else netif_start_queue(dev); - - DEBUG(2,"ray_open ending\n"); - return 0; + DEBUG(1, "ray_open: doing init now !\n"); + + /* Download startup parameters */ + if ((i = dl_startup_params(dev)) < 0) { + printk(KERN_INFO + "ray_dev_init dl_startup_params failed - " + "returns 0x%x\n", i); + return -1; + } + } + + if (sniffer) + netif_stop_queue(dev); + else + netif_start_queue(dev); + + DEBUG(2, "ray_open ending\n"); + return 0; } /* end ray_open */ + /*===========================================================================*/ static int ray_dev_close(struct net_device *dev) { - ray_dev_t *local = netdev_priv(dev); - struct pcmcia_device *link; - link = local->finder; + ray_dev_t *local = netdev_priv(dev); + struct pcmcia_device *link; + link = local->finder; - DEBUG(1, "ray_dev_close('%s')\n", dev->name); + DEBUG(1, "ray_dev_close('%s')\n", dev->name); - link->open--; - netif_stop_queue(dev); + link->open--; + netif_stop_queue(dev); - /* In here, we should stop the hardware (stop card from beeing active) - * and set local->card_status to CARD_AWAITING_PARAM, so that while the - * card is closed we can chage its configuration. - * Probably also need a COR reset to get sane state - Jean II */ + /* In here, we should stop the hardware (stop card from beeing active) + * and set local->card_status to CARD_AWAITING_PARAM, so that while the + * card is closed we can chage its configuration. + * Probably also need a COR reset to get sane state - Jean II */ - return 0; + return 0; } /* end ray_dev_close */ + /*===========================================================================*/ -static void ray_reset(struct net_device *dev) { - DEBUG(1,"ray_reset entered\n"); - return; +static void ray_reset(struct net_device *dev) +{ + DEBUG(1, "ray_reset entered\n"); + return; } + /*===========================================================================*/ /* Cause a firmware interrupt if it is ready for one */ /* Return nonzero if not ready */ static int interrupt_ecf(ray_dev_t *local, int ccs) { - int i = 50; - struct pcmcia_device *link = local->finder; - - if (!(pcmcia_dev_present(link))) { - DEBUG(2,"ray_cs interrupt_ecf - device not present\n"); - return -1; - } - DEBUG(2,"interrupt_ecf(local=%p, ccs = 0x%x\n",local,ccs); - - while ( i && - (readb(local->amem + CIS_OFFSET + ECF_INTR_OFFSET) & ECF_INTR_SET)) - i--; - if (i == 0) { - DEBUG(2,"ray_cs interrupt_ecf card not ready for interrupt\n"); - return -1; - } + int i = 50; + struct pcmcia_device *link = local->finder; + + if (!(pcmcia_dev_present(link))) { + DEBUG(2, "ray_cs interrupt_ecf - device not present\n"); + return -1; + } + DEBUG(2, "interrupt_ecf(local=%p, ccs = 0x%x\n", local, ccs); + + while (i && + (readb(local->amem + CIS_OFFSET + ECF_INTR_OFFSET) & + ECF_INTR_SET)) + i--; + if (i == 0) { + DEBUG(2, "ray_cs interrupt_ecf card not ready for interrupt\n"); + return -1; + } /* Fill the mailbox, then kick the card */ - writeb(ccs, local->sram + SCB_BASE); - writeb(ECF_INTR_SET, local->amem + CIS_OFFSET + ECF_INTR_OFFSET); - return 0; + writeb(ccs, local->sram + SCB_BASE); + writeb(ECF_INTR_SET, local->amem + CIS_OFFSET + ECF_INTR_OFFSET); + return 0; } /* interrupt_ecf */ + /*===========================================================================*/ /* Get next free transmit CCS */ /* Return - index of current tx ccs */ static int get_free_tx_ccs(ray_dev_t *local) { - int i; - struct ccs __iomem *pccs = ccs_base(local); - struct pcmcia_device *link = local->finder; + int i; + struct ccs __iomem *pccs = ccs_base(local); + struct pcmcia_device *link = local->finder; - if (!(pcmcia_dev_present(link))) { - DEBUG(2,"ray_cs get_free_tx_ccs - device not present\n"); - return ECARDGONE; - } + if (!(pcmcia_dev_present(link))) { + DEBUG(2, "ray_cs get_free_tx_ccs - device not present\n"); + return ECARDGONE; + } - if (test_and_set_bit(0,&local->tx_ccs_lock)) { - DEBUG(1,"ray_cs tx_ccs_lock busy\n"); - return ECCSBUSY; - } + if (test_and_set_bit(0, &local->tx_ccs_lock)) { + DEBUG(1, "ray_cs tx_ccs_lock busy\n"); + return ECCSBUSY; + } - for (i=0; i < NUMBER_OF_TX_CCS; i++) { - if (readb(&(pccs+i)->buffer_status) == CCS_BUFFER_FREE) { - writeb(CCS_BUFFER_BUSY, &(pccs+i)->buffer_status); - writeb(CCS_END_LIST, &(pccs+i)->link); + for (i = 0; i < NUMBER_OF_TX_CCS; i++) { + if (readb(&(pccs + i)->buffer_status) == CCS_BUFFER_FREE) { + writeb(CCS_BUFFER_BUSY, &(pccs + i)->buffer_status); + writeb(CCS_END_LIST, &(pccs + i)->link); local->tx_ccs_lock = 0; - return i; - } - } + return i; + } + } local->tx_ccs_lock = 0; - DEBUG(2,"ray_cs ERROR no free tx CCS for raylink card\n"); - return ECCSFULL; + DEBUG(2, "ray_cs ERROR no free tx CCS for raylink card\n"); + return ECCSFULL; } /* get_free_tx_ccs */ + /*===========================================================================*/ /* Get next free CCS */ /* Return - index of current ccs */ static int get_free_ccs(ray_dev_t *local) { - int i; - struct ccs __iomem *pccs = ccs_base(local); - struct pcmcia_device *link = local->finder; - - if (!(pcmcia_dev_present(link))) { - DEBUG(2,"ray_cs get_free_ccs - device not present\n"); - return ECARDGONE; - } - if (test_and_set_bit(0,&local->ccs_lock)) { - DEBUG(1,"ray_cs ccs_lock busy\n"); - return ECCSBUSY; - } - - for (i = NUMBER_OF_TX_CCS; i < NUMBER_OF_CCS; i++) { - if (readb(&(pccs+i)->buffer_status) == CCS_BUFFER_FREE) { - writeb(CCS_BUFFER_BUSY, &(pccs+i)->buffer_status); - writeb(CCS_END_LIST, &(pccs+i)->link); + int i; + struct ccs __iomem *pccs = ccs_base(local); + struct pcmcia_device *link = local->finder; + + if (!(pcmcia_dev_present(link))) { + DEBUG(2, "ray_cs get_free_ccs - device not present\n"); + return ECARDGONE; + } + if (test_and_set_bit(0, &local->ccs_lock)) { + DEBUG(1, "ray_cs ccs_lock busy\n"); + return ECCSBUSY; + } + + for (i = NUMBER_OF_TX_CCS; i < NUMBER_OF_CCS; i++) { + if (readb(&(pccs + i)->buffer_status) == CCS_BUFFER_FREE) { + writeb(CCS_BUFFER_BUSY, &(pccs + i)->buffer_status); + writeb(CCS_END_LIST, &(pccs + i)->link); local->ccs_lock = 0; - return i; - } - } + return i; + } + } local->ccs_lock = 0; - DEBUG(1,"ray_cs ERROR no free CCS for raylink card\n"); - return ECCSFULL; + DEBUG(1, "ray_cs ERROR no free CCS for raylink card\n"); + return ECCSFULL; } /* get_free_ccs */ + /*===========================================================================*/ static void authenticate_timeout(u_long data) { - ray_dev_t *local = (ray_dev_t *)data; - del_timer(&local->timer); - printk(KERN_INFO "ray_cs Authentication with access point failed" - " - timeout\n"); - join_net((u_long)local); + ray_dev_t *local = (ray_dev_t *) data; + del_timer(&local->timer); + printk(KERN_INFO "ray_cs Authentication with access point failed" + " - timeout\n"); + join_net((u_long) local); } + /*===========================================================================*/ static int asc_to_int(char a) { - if (a < '0') return -1; - if (a <= '9') return (a - '0'); - if (a < 'A') return -1; - if (a <= 'F') return (10 + a - 'A'); - if (a < 'a') return -1; - if (a <= 'f') return (10 + a - 'a'); - return -1; + if (a < '0') + return -1; + if (a <= '9') + return (a - '0'); + if (a < 'A') + return -1; + if (a <= 'F') + return (10 + a - 'A'); + if (a < 'a') + return -1; + if (a <= 'f') + return (10 + a - 'a'); + return -1; } + /*===========================================================================*/ static int parse_addr(char *in_str, UCHAR *out) { - int len; - int i,j,k; - int status; - - if (in_str == NULL) return 0; - if ((len = strlen(in_str)) < 2) return 0; - memset(out, 0, ADDRLEN); - - status = 1; - j = len - 1; - if (j > 12) j = 12; - i = 5; - - while (j > 0) - { - if ((k = asc_to_int(in_str[j--])) != -1) out[i] = k; - else return 0; - - if (j == 0) break; - if ((k = asc_to_int(in_str[j--])) != -1) out[i] += k << 4; - else return 0; - if (!i--) break; - } - return status; + int len; + int i, j, k; + int status; + + if (in_str == NULL) + return 0; + if ((len = strlen(in_str)) < 2) + return 0; + memset(out, 0, ADDRLEN); + + status = 1; + j = len - 1; + if (j > 12) + j = 12; + i = 5; + + while (j > 0) { + if ((k = asc_to_int(in_str[j--])) != -1) + out[i] = k; + else + return 0; + + if (j == 0) + break; + if ((k = asc_to_int(in_str[j--])) != -1) + out[i] += k << 4; + else + return 0; + if (!i--) + break; + } + return status; } + /*===========================================================================*/ static struct net_device_stats *ray_get_stats(struct net_device *dev) { - ray_dev_t *local = netdev_priv(dev); - struct pcmcia_device *link = local->finder; - struct status __iomem *p = local->sram + STATUS_BASE; - if (!(pcmcia_dev_present(link))) { - DEBUG(2,"ray_cs net_device_stats - device not present\n"); - return &local->stats; - } - if (readb(&p->mrx_overflow_for_host)) - { - local->stats.rx_over_errors += swab16(readw(&p->mrx_overflow)); - writeb(0,&p->mrx_overflow); - writeb(0,&p->mrx_overflow_for_host); - } - if (readb(&p->mrx_checksum_error_for_host)) - { - local->stats.rx_crc_errors += swab16(readw(&p->mrx_checksum_error)); - writeb(0,&p->mrx_checksum_error); - writeb(0,&p->mrx_checksum_error_for_host); - } - if (readb(&p->rx_hec_error_for_host)) - { - local->stats.rx_frame_errors += swab16(readw(&p->rx_hec_error)); - writeb(0,&p->rx_hec_error); - writeb(0,&p->rx_hec_error_for_host); - } - return &local->stats; + ray_dev_t *local = netdev_priv(dev); + struct pcmcia_device *link = local->finder; + struct status __iomem *p = local->sram + STATUS_BASE; + if (!(pcmcia_dev_present(link))) { + DEBUG(2, "ray_cs net_device_stats - device not present\n"); + return &local->stats; + } + if (readb(&p->mrx_overflow_for_host)) { + local->stats.rx_over_errors += swab16(readw(&p->mrx_overflow)); + writeb(0, &p->mrx_overflow); + writeb(0, &p->mrx_overflow_for_host); + } + if (readb(&p->mrx_checksum_error_for_host)) { + local->stats.rx_crc_errors += + swab16(readw(&p->mrx_checksum_error)); + writeb(0, &p->mrx_checksum_error); + writeb(0, &p->mrx_checksum_error_for_host); + } + if (readb(&p->rx_hec_error_for_host)) { + local->stats.rx_frame_errors += swab16(readw(&p->rx_hec_error)); + writeb(0, &p->rx_hec_error); + writeb(0, &p->rx_hec_error_for_host); + } + return &local->stats; } + /*===========================================================================*/ -static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len) -{ - ray_dev_t *local = netdev_priv(dev); - struct pcmcia_device *link = local->finder; - int ccsindex; - int i; - struct ccs __iomem *pccs; - - if (!(pcmcia_dev_present(link))) { - DEBUG(2,"ray_update_parm - device not present\n"); - return; - } - - if ((ccsindex = get_free_ccs(local)) < 0) - { - DEBUG(0,"ray_update_parm - No free ccs\n"); - return; - } - pccs = ccs_base(local) + ccsindex; - writeb(CCS_UPDATE_PARAMS, &pccs->cmd); - writeb(objid, &pccs->var.update_param.object_id); - writeb(1, &pccs->var.update_param.number_objects); - writeb(0, &pccs->var.update_param.failure_cause); - for (i=0; isram + HOST_TO_ECF_BASE); - } - /* Interrupt the firmware to process the command */ - if (interrupt_ecf(local, ccsindex)) { - DEBUG(0,"ray_cs associate failed - ECF not ready for intr\n"); - writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); - } +static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, + int len) +{ + ray_dev_t *local = netdev_priv(dev); + struct pcmcia_device *link = local->finder; + int ccsindex; + int i; + struct ccs __iomem *pccs; + + if (!(pcmcia_dev_present(link))) { + DEBUG(2, "ray_update_parm - device not present\n"); + return; + } + + if ((ccsindex = get_free_ccs(local)) < 0) { + DEBUG(0, "ray_update_parm - No free ccs\n"); + return; + } + pccs = ccs_base(local) + ccsindex; + writeb(CCS_UPDATE_PARAMS, &pccs->cmd); + writeb(objid, &pccs->var.update_param.object_id); + writeb(1, &pccs->var.update_param.number_objects); + writeb(0, &pccs->var.update_param.failure_cause); + for (i = 0; i < len; i++) { + writeb(value[i], local->sram + HOST_TO_ECF_BASE); + } + /* Interrupt the firmware to process the command */ + if (interrupt_ecf(local, ccsindex)) { + DEBUG(0, "ray_cs associate failed - ECF not ready for intr\n"); + writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); + } } + /*===========================================================================*/ static void ray_update_multi_list(struct net_device *dev, int all) { - struct dev_mc_list *dmi, **dmip; - int ccsindex; - struct ccs __iomem *pccs; - int i = 0; - ray_dev_t *local = netdev_priv(dev); - struct pcmcia_device *link = local->finder; - void __iomem *p = local->sram + HOST_TO_ECF_BASE; - - if (!(pcmcia_dev_present(link))) { - DEBUG(2,"ray_update_multi_list - device not present\n"); - return; - } - else - DEBUG(2,"ray_update_multi_list(%p)\n",dev); - if ((ccsindex = get_free_ccs(local)) < 0) - { - DEBUG(1,"ray_update_multi - No free ccs\n"); - return; - } - pccs = ccs_base(local) + ccsindex; - writeb(CCS_UPDATE_MULTICAST_LIST, &pccs->cmd); - - if (all) { - writeb(0xff, &pccs->var); - local->num_multi = 0xff; - } - else { - /* Copy the kernel's list of MC addresses to card */ - for (dmip=&dev->mc_list; (dmi=*dmip)!=NULL; dmip=&dmi->next) { - memcpy_toio(p, dmi->dmi_addr, ETH_ALEN); - DEBUG(1,"ray_update_multi add addr %02x%02x%02x%02x%02x%02x\n",dmi->dmi_addr[0],dmi->dmi_addr[1],dmi->dmi_addr[2],dmi->dmi_addr[3],dmi->dmi_addr[4],dmi->dmi_addr[5]); - p += ETH_ALEN; - i++; - } - if (i > 256/ADDRLEN) i = 256/ADDRLEN; - writeb((UCHAR)i, &pccs->var); - DEBUG(1,"ray_cs update_multi %d addresses in list\n", i); - /* Interrupt the firmware to process the command */ - local->num_multi = i; - } - if (interrupt_ecf(local, ccsindex)) { - DEBUG(1,"ray_cs update_multi failed - ECF not ready for intr\n"); - writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); - } + struct dev_mc_list *dmi, **dmip; + int ccsindex; + struct ccs __iomem *pccs; + int i = 0; + ray_dev_t *local = netdev_priv(dev); + struct pcmcia_device *link = local->finder; + void __iomem *p = local->sram + HOST_TO_ECF_BASE; + + if (!(pcmcia_dev_present(link))) { + DEBUG(2, "ray_update_multi_list - device not present\n"); + return; + } else + DEBUG(2, "ray_update_multi_list(%p)\n", dev); + if ((ccsindex = get_free_ccs(local)) < 0) { + DEBUG(1, "ray_update_multi - No free ccs\n"); + return; + } + pccs = ccs_base(local) + ccsindex; + writeb(CCS_UPDATE_MULTICAST_LIST, &pccs->cmd); + + if (all) { + writeb(0xff, &pccs->var); + local->num_multi = 0xff; + } else { + /* Copy the kernel's list of MC addresses to card */ + for (dmip = &dev->mc_list; (dmi = *dmip) != NULL; + dmip = &dmi->next) { + memcpy_toio(p, dmi->dmi_addr, ETH_ALEN); + DEBUG(1, + "ray_update_multi add addr %02x%02x%02x%02x%02x%02x\n", + dmi->dmi_addr[0], dmi->dmi_addr[1], + dmi->dmi_addr[2], dmi->dmi_addr[3], + dmi->dmi_addr[4], dmi->dmi_addr[5]); + p += ETH_ALEN; + i++; + } + if (i > 256 / ADDRLEN) + i = 256 / ADDRLEN; + writeb((UCHAR) i, &pccs->var); + DEBUG(1, "ray_cs update_multi %d addresses in list\n", i); + /* Interrupt the firmware to process the command */ + local->num_multi = i; + } + if (interrupt_ecf(local, ccsindex)) { + DEBUG(1, + "ray_cs update_multi failed - ECF not ready for intr\n"); + writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); + } } /* end ray_update_multi_list */ + /*===========================================================================*/ static void set_multicast_list(struct net_device *dev) { - ray_dev_t *local = netdev_priv(dev); - UCHAR promisc; - - DEBUG(2,"ray_cs set_multicast_list(%p)\n",dev); - - if (dev->flags & IFF_PROMISC) - { - if (local->sparm.b5.a_promiscuous_mode == 0) { - DEBUG(1,"ray_cs set_multicast_list promisc on\n"); - local->sparm.b5.a_promiscuous_mode = 1; - promisc = 1; - ray_update_parm(dev, OBJID_promiscuous_mode, \ - &promisc, sizeof(promisc)); - } - } - else { - if (local->sparm.b5.a_promiscuous_mode == 1) { - DEBUG(1,"ray_cs set_multicast_list promisc off\n"); - local->sparm.b5.a_promiscuous_mode = 0; - promisc = 0; - ray_update_parm(dev, OBJID_promiscuous_mode, \ - &promisc, sizeof(promisc)); - } - } - - if (dev->flags & IFF_ALLMULTI) ray_update_multi_list(dev, 1); - else - { - if (local->num_multi != dev->mc_count) ray_update_multi_list(dev, 0); - } + ray_dev_t *local = netdev_priv(dev); + UCHAR promisc; + + DEBUG(2, "ray_cs set_multicast_list(%p)\n", dev); + + if (dev->flags & IFF_PROMISC) { + if (local->sparm.b5.a_promiscuous_mode == 0) { + DEBUG(1, "ray_cs set_multicast_list promisc on\n"); + local->sparm.b5.a_promiscuous_mode = 1; + promisc = 1; + ray_update_parm(dev, OBJID_promiscuous_mode, + &promisc, sizeof(promisc)); + } + } else { + if (local->sparm.b5.a_promiscuous_mode == 1) { + DEBUG(1, "ray_cs set_multicast_list promisc off\n"); + local->sparm.b5.a_promiscuous_mode = 0; + promisc = 0; + ray_update_parm(dev, OBJID_promiscuous_mode, + &promisc, sizeof(promisc)); + } + } + + if (dev->flags & IFF_ALLMULTI) + ray_update_multi_list(dev, 1); + else { + if (local->num_multi != dev->mc_count) + ray_update_multi_list(dev, 0); + } } /* end set_multicast_list */ + /*============================================================================= * All routines below here are run at interrupt time. =============================================================================*/ static irqreturn_t ray_interrupt(int irq, void *dev_id) { - struct net_device *dev = (struct net_device *)dev_id; - struct pcmcia_device *link; - ray_dev_t *local; - struct ccs __iomem *pccs; - struct rcs __iomem *prcs; - UCHAR rcsindex; - UCHAR tmp; - UCHAR cmd; - UCHAR status; - - if (dev == NULL) /* Note that we want interrupts with dev->start == 0 */ - return IRQ_NONE; - - DEBUG(4,"ray_cs: interrupt for *dev=%p\n",dev); - - local = netdev_priv(dev); - link = (struct pcmcia_device *)local->finder; - if (!pcmcia_dev_present(link)) { - DEBUG(2,"ray_cs interrupt from device not present or suspended.\n"); - return IRQ_NONE; - } - rcsindex = readb(&((struct scb __iomem *)(local->sram))->rcs_index); - - if (rcsindex >= (NUMBER_OF_CCS + NUMBER_OF_RCS)) - { - DEBUG(1,"ray_cs interrupt bad rcsindex = 0x%x\n",rcsindex); - clear_interrupt(local); - return IRQ_HANDLED; - } - if (rcsindex < NUMBER_OF_CCS) /* If it's a returned CCS */ - { - pccs = ccs_base(local) + rcsindex; - cmd = readb(&pccs->cmd); - status = readb(&pccs->buffer_status); - switch (cmd) - { - case CCS_DOWNLOAD_STARTUP_PARAMS: /* Happens in firmware someday */ - del_timer(&local->timer); - if (status == CCS_COMMAND_COMPLETE) { - DEBUG(1,"ray_cs interrupt download_startup_parameters OK\n"); - } - else { - DEBUG(1,"ray_cs interrupt download_startup_parameters fail\n"); - } - break; - case CCS_UPDATE_PARAMS: - DEBUG(1,"ray_cs interrupt update params done\n"); - if (status != CCS_COMMAND_COMPLETE) { - tmp = readb(&pccs->var.update_param.failure_cause); - DEBUG(0,"ray_cs interrupt update params failed - reason %d\n",tmp); - } - break; - case CCS_REPORT_PARAMS: - DEBUG(1,"ray_cs interrupt report params done\n"); - break; - case CCS_UPDATE_MULTICAST_LIST: /* Note that this CCS isn't returned */ - DEBUG(1,"ray_cs interrupt CCS Update Multicast List done\n"); - break; - case CCS_UPDATE_POWER_SAVINGS_MODE: - DEBUG(1,"ray_cs interrupt update power save mode done\n"); - break; - case CCS_START_NETWORK: - case CCS_JOIN_NETWORK: - if (status == CCS_COMMAND_COMPLETE) { - if (readb(&pccs->var.start_network.net_initiated) == 1) { - DEBUG(0,"ray_cs interrupt network \"%s\" started\n",\ - local->sparm.b4.a_current_ess_id); - } - else { - DEBUG(0,"ray_cs interrupt network \"%s\" joined\n",\ - local->sparm.b4.a_current_ess_id); - } - memcpy_fromio(&local->bss_id,pccs->var.start_network.bssid,ADDRLEN); - - if (local->fw_ver == 0x55) local->net_default_tx_rate = 3; - else local->net_default_tx_rate = - readb(&pccs->var.start_network.net_default_tx_rate); - local->encryption = readb(&pccs->var.start_network.encryption); - if (!sniffer && (local->net_type == INFRA) - && !(local->sparm.b4.a_acting_as_ap_status)) { - authenticate(local); - } - local->card_status = CARD_ACQ_COMPLETE; - } - else { - local->card_status = CARD_ACQ_FAILED; - - del_timer(&local->timer); - local->timer.expires = jiffies + HZ*5; - local->timer.data = (long)local; - if (status == CCS_START_NETWORK) { - DEBUG(0,"ray_cs interrupt network \"%s\" start failed\n",\ - local->sparm.b4.a_current_ess_id); - local->timer.function = &start_net; - } - else { - DEBUG(0,"ray_cs interrupt network \"%s\" join failed\n",\ - local->sparm.b4.a_current_ess_id); - local->timer.function = &join_net; - } - add_timer(&local->timer); - } - break; - case CCS_START_ASSOCIATION: - if (status == CCS_COMMAND_COMPLETE) { - local->card_status = CARD_ASSOC_COMPLETE; - DEBUG(0,"ray_cs association successful\n"); - } - else - { - DEBUG(0,"ray_cs association failed,\n"); - local->card_status = CARD_ASSOC_FAILED; - join_net((u_long)local); - } - break; - case CCS_TX_REQUEST: - if (status == CCS_COMMAND_COMPLETE) { - DEBUG(3,"ray_cs interrupt tx request complete\n"); - } - else { - DEBUG(1,"ray_cs interrupt tx request failed\n"); - } - if (!sniffer) netif_start_queue(dev); - netif_wake_queue(dev); - break; - case CCS_TEST_MEMORY: - DEBUG(1,"ray_cs interrupt mem test done\n"); - break; - case CCS_SHUTDOWN: - DEBUG(1,"ray_cs interrupt Unexpected CCS returned - Shutdown\n"); - break; - case CCS_DUMP_MEMORY: - DEBUG(1,"ray_cs interrupt dump memory done\n"); - break; - case CCS_START_TIMER: - DEBUG(2,"ray_cs interrupt DING - raylink timer expired\n"); - break; - default: - DEBUG(1,"ray_cs interrupt Unexpected CCS 0x%x returned 0x%x\n",\ - rcsindex, cmd); - } - writeb(CCS_BUFFER_FREE, &pccs->buffer_status); - } - else /* It's an RCS */ - { - prcs = rcs_base(local) + rcsindex; - - switch (readb(&prcs->interrupt_id)) - { - case PROCESS_RX_PACKET: - ray_rx(dev, local, prcs); - break; - case REJOIN_NET_COMPLETE: - DEBUG(1,"ray_cs interrupt rejoin net complete\n"); - local->card_status = CARD_ACQ_COMPLETE; - /* do we need to clear tx buffers CCS's? */ - if (local->sparm.b4.a_network_type == ADHOC) { - if (!sniffer) netif_start_queue(dev); - } - else { - memcpy_fromio(&local->bss_id, prcs->var.rejoin_net_complete.bssid, ADDRLEN); - DEBUG(1,"ray_cs new BSSID = %02x%02x%02x%02x%02x%02x\n",\ - local->bss_id[0], local->bss_id[1], local->bss_id[2],\ - local->bss_id[3], local->bss_id[4], local->bss_id[5]); - if (!sniffer) authenticate(local); - } - break; - case ROAMING_INITIATED: - DEBUG(1,"ray_cs interrupt roaming initiated\n"); - netif_stop_queue(dev); - local->card_status = CARD_DOING_ACQ; - break; - case JAPAN_CALL_SIGN_RXD: - DEBUG(1,"ray_cs interrupt japan call sign rx\n"); - break; - default: - DEBUG(1,"ray_cs Unexpected interrupt for RCS 0x%x cmd = 0x%x\n",\ - rcsindex, (unsigned int) readb(&prcs->interrupt_id)); - break; - } - writeb(CCS_BUFFER_FREE, &prcs->buffer_status); - } - clear_interrupt(local); - return IRQ_HANDLED; + struct net_device *dev = (struct net_device *)dev_id; + struct pcmcia_device *link; + ray_dev_t *local; + struct ccs __iomem *pccs; + struct rcs __iomem *prcs; + UCHAR rcsindex; + UCHAR tmp; + UCHAR cmd; + UCHAR status; + + if (dev == NULL) /* Note that we want interrupts with dev->start == 0 */ + return IRQ_NONE; + + DEBUG(4, "ray_cs: interrupt for *dev=%p\n", dev); + + local = netdev_priv(dev); + link = (struct pcmcia_device *)local->finder; + if (!pcmcia_dev_present(link)) { + DEBUG(2, + "ray_cs interrupt from device not present or suspended.\n"); + return IRQ_NONE; + } + rcsindex = readb(&((struct scb __iomem *)(local->sram))->rcs_index); + + if (rcsindex >= (NUMBER_OF_CCS + NUMBER_OF_RCS)) { + DEBUG(1, "ray_cs interrupt bad rcsindex = 0x%x\n", rcsindex); + clear_interrupt(local); + return IRQ_HANDLED; + } + if (rcsindex < NUMBER_OF_CCS) { /* If it's a returned CCS */ + pccs = ccs_base(local) + rcsindex; + cmd = readb(&pccs->cmd); + status = readb(&pccs->buffer_status); + switch (cmd) { + case CCS_DOWNLOAD_STARTUP_PARAMS: /* Happens in firmware someday */ + del_timer(&local->timer); + if (status == CCS_COMMAND_COMPLETE) { + DEBUG(1, + "ray_cs interrupt download_startup_parameters OK\n"); + } else { + DEBUG(1, + "ray_cs interrupt download_startup_parameters fail\n"); + } + break; + case CCS_UPDATE_PARAMS: + DEBUG(1, "ray_cs interrupt update params done\n"); + if (status != CCS_COMMAND_COMPLETE) { + tmp = + readb(&pccs->var.update_param. + failure_cause); + DEBUG(0, + "ray_cs interrupt update params failed - reason %d\n", + tmp); + } + break; + case CCS_REPORT_PARAMS: + DEBUG(1, "ray_cs interrupt report params done\n"); + break; + case CCS_UPDATE_MULTICAST_LIST: /* Note that this CCS isn't returned */ + DEBUG(1, + "ray_cs interrupt CCS Update Multicast List done\n"); + break; + case CCS_UPDATE_POWER_SAVINGS_MODE: + DEBUG(1, + "ray_cs interrupt update power save mode done\n"); + break; + case CCS_START_NETWORK: + case CCS_JOIN_NETWORK: + if (status == CCS_COMMAND_COMPLETE) { + if (readb + (&pccs->var.start_network.net_initiated) == + 1) { + DEBUG(0, + "ray_cs interrupt network \"%s\" started\n", + local->sparm.b4.a_current_ess_id); + } else { + DEBUG(0, + "ray_cs interrupt network \"%s\" joined\n", + local->sparm.b4.a_current_ess_id); + } + memcpy_fromio(&local->bss_id, + pccs->var.start_network.bssid, + ADDRLEN); + + if (local->fw_ver == 0x55) + local->net_default_tx_rate = 3; + else + local->net_default_tx_rate = + readb(&pccs->var.start_network. + net_default_tx_rate); + local->encryption = + readb(&pccs->var.start_network.encryption); + if (!sniffer && (local->net_type == INFRA) + && !(local->sparm.b4.a_acting_as_ap_status)) { + authenticate(local); + } + local->card_status = CARD_ACQ_COMPLETE; + } else { + local->card_status = CARD_ACQ_FAILED; + + del_timer(&local->timer); + local->timer.expires = jiffies + HZ * 5; + local->timer.data = (long)local; + if (status == CCS_START_NETWORK) { + DEBUG(0, + "ray_cs interrupt network \"%s\" start failed\n", + local->sparm.b4.a_current_ess_id); + local->timer.function = &start_net; + } else { + DEBUG(0, + "ray_cs interrupt network \"%s\" join failed\n", + local->sparm.b4.a_current_ess_id); + local->timer.function = &join_net; + } + add_timer(&local->timer); + } + break; + case CCS_START_ASSOCIATION: + if (status == CCS_COMMAND_COMPLETE) { + local->card_status = CARD_ASSOC_COMPLETE; + DEBUG(0, "ray_cs association successful\n"); + } else { + DEBUG(0, "ray_cs association failed,\n"); + local->card_status = CARD_ASSOC_FAILED; + join_net((u_long) local); + } + break; + case CCS_TX_REQUEST: + if (status == CCS_COMMAND_COMPLETE) { + DEBUG(3, + "ray_cs interrupt tx request complete\n"); + } else { + DEBUG(1, + "ray_cs interrupt tx request failed\n"); + } + if (!sniffer) + netif_start_queue(dev); + netif_wake_queue(dev); + break; + case CCS_TEST_MEMORY: + DEBUG(1, "ray_cs interrupt mem test done\n"); + break; + case CCS_SHUTDOWN: + DEBUG(1, + "ray_cs interrupt Unexpected CCS returned - Shutdown\n"); + break; + case CCS_DUMP_MEMORY: + DEBUG(1, "ray_cs interrupt dump memory done\n"); + break; + case CCS_START_TIMER: + DEBUG(2, + "ray_cs interrupt DING - raylink timer expired\n"); + break; + default: + DEBUG(1, + "ray_cs interrupt Unexpected CCS 0x%x returned 0x%x\n", + rcsindex, cmd); + } + writeb(CCS_BUFFER_FREE, &pccs->buffer_status); + } else { /* It's an RCS */ + + prcs = rcs_base(local) + rcsindex; + + switch (readb(&prcs->interrupt_id)) { + case PROCESS_RX_PACKET: + ray_rx(dev, local, prcs); + break; + case REJOIN_NET_COMPLETE: + DEBUG(1, "ray_cs interrupt rejoin net complete\n"); + local->card_status = CARD_ACQ_COMPLETE; + /* do we need to clear tx buffers CCS's? */ + if (local->sparm.b4.a_network_type == ADHOC) { + if (!sniffer) + netif_start_queue(dev); + } else { + memcpy_fromio(&local->bss_id, + prcs->var.rejoin_net_complete. + bssid, ADDRLEN); + DEBUG(1, + "ray_cs new BSSID = %02x%02x%02x%02x%02x%02x\n", + local->bss_id[0], local->bss_id[1], + local->bss_id[2], local->bss_id[3], + local->bss_id[4], local->bss_id[5]); + if (!sniffer) + authenticate(local); + } + break; + case ROAMING_INITIATED: + DEBUG(1, "ray_cs interrupt roaming initiated\n"); + netif_stop_queue(dev); + local->card_status = CARD_DOING_ACQ; + break; + case JAPAN_CALL_SIGN_RXD: + DEBUG(1, "ray_cs interrupt japan call sign rx\n"); + break; + default: + DEBUG(1, + "ray_cs Unexpected interrupt for RCS 0x%x cmd = 0x%x\n", + rcsindex, + (unsigned int)readb(&prcs->interrupt_id)); + break; + } + writeb(CCS_BUFFER_FREE, &prcs->buffer_status); + } + clear_interrupt(local); + return IRQ_HANDLED; } /* ray_interrupt */ + /*===========================================================================*/ -static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs __iomem *prcs) -{ - int rx_len; - unsigned int pkt_addr; - void __iomem *pmsg; - DEBUG(4,"ray_rx process rx packet\n"); - - /* Calculate address of packet within Rx buffer */ - pkt_addr = ((readb(&prcs->var.rx_packet.rx_data_ptr[0]) << 8) - + readb(&prcs->var.rx_packet.rx_data_ptr[1])) & RX_BUFF_END; - /* Length of first packet fragment */ - rx_len = (readb(&prcs->var.rx_packet.rx_data_length[0]) << 8) - + readb(&prcs->var.rx_packet.rx_data_length[1]); - - local->last_rsl = readb(&prcs->var.rx_packet.rx_sig_lev); - pmsg = local->rmem + pkt_addr; - switch(readb(pmsg)) - { - case DATA_TYPE: - DEBUG(4,"ray_rx data type\n"); - rx_data(dev, prcs, pkt_addr, rx_len); - break; - case AUTHENTIC_TYPE: - DEBUG(4,"ray_rx authentic type\n"); - if (sniffer) rx_data(dev, prcs, pkt_addr, rx_len); - else rx_authenticate(local, prcs, pkt_addr, rx_len); - break; - case DEAUTHENTIC_TYPE: - DEBUG(4,"ray_rx deauth type\n"); - if (sniffer) rx_data(dev, prcs, pkt_addr, rx_len); - else rx_deauthenticate(local, prcs, pkt_addr, rx_len); - break; - case NULL_MSG_TYPE: - DEBUG(3,"ray_cs rx NULL msg\n"); - break; - case BEACON_TYPE: - DEBUG(4,"ray_rx beacon type\n"); - if (sniffer) rx_data(dev, prcs, pkt_addr, rx_len); - - copy_from_rx_buff(local, (UCHAR *)&local->last_bcn, pkt_addr, - rx_len < sizeof(struct beacon_rx) ? - rx_len : sizeof(struct beacon_rx)); - - local->beacon_rxed = 1; - /* Get the statistics so the card counters never overflow */ - ray_get_stats(dev); - break; - default: - DEBUG(0,"ray_cs unknown pkt type %2x\n", (unsigned int) readb(pmsg)); - break; - } +static void ray_rx(struct net_device *dev, ray_dev_t *local, + struct rcs __iomem *prcs) +{ + int rx_len; + unsigned int pkt_addr; + void __iomem *pmsg; + DEBUG(4, "ray_rx process rx packet\n"); + + /* Calculate address of packet within Rx buffer */ + pkt_addr = ((readb(&prcs->var.rx_packet.rx_data_ptr[0]) << 8) + + readb(&prcs->var.rx_packet.rx_data_ptr[1])) & RX_BUFF_END; + /* Length of first packet fragment */ + rx_len = (readb(&prcs->var.rx_packet.rx_data_length[0]) << 8) + + readb(&prcs->var.rx_packet.rx_data_length[1]); + + local->last_rsl = readb(&prcs->var.rx_packet.rx_sig_lev); + pmsg = local->rmem + pkt_addr; + switch (readb(pmsg)) { + case DATA_TYPE: + DEBUG(4, "ray_rx data type\n"); + rx_data(dev, prcs, pkt_addr, rx_len); + break; + case AUTHENTIC_TYPE: + DEBUG(4, "ray_rx authentic type\n"); + if (sniffer) + rx_data(dev, prcs, pkt_addr, rx_len); + else + rx_authenticate(local, prcs, pkt_addr, rx_len); + break; + case DEAUTHENTIC_TYPE: + DEBUG(4, "ray_rx deauth type\n"); + if (sniffer) + rx_data(dev, prcs, pkt_addr, rx_len); + else + rx_deauthenticate(local, prcs, pkt_addr, rx_len); + break; + case NULL_MSG_TYPE: + DEBUG(3, "ray_cs rx NULL msg\n"); + break; + case BEACON_TYPE: + DEBUG(4, "ray_rx beacon type\n"); + if (sniffer) + rx_data(dev, prcs, pkt_addr, rx_len); + + copy_from_rx_buff(local, (UCHAR *) &local->last_bcn, pkt_addr, + rx_len < sizeof(struct beacon_rx) ? + rx_len : sizeof(struct beacon_rx)); + + local->beacon_rxed = 1; + /* Get the statistics so the card counters never overflow */ + ray_get_stats(dev); + break; + default: + DEBUG(0, "ray_cs unknown pkt type %2x\n", + (unsigned int)readb(pmsg)); + break; + } } /* end ray_rx */ + /*===========================================================================*/ -static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, unsigned int pkt_addr, - int rx_len) -{ - struct sk_buff *skb = NULL; - struct rcs __iomem *prcslink = prcs; - ray_dev_t *local = netdev_priv(dev); - UCHAR *rx_ptr; - int total_len; - int tmp; +static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, + unsigned int pkt_addr, int rx_len) +{ + struct sk_buff *skb = NULL; + struct rcs __iomem *prcslink = prcs; + ray_dev_t *local = netdev_priv(dev); + UCHAR *rx_ptr; + int total_len; + int tmp; #ifdef WIRELESS_SPY - int siglev = local->last_rsl; - u_char linksrcaddr[ETH_ALEN]; /* Other end of the wireless link */ + int siglev = local->last_rsl; + u_char linksrcaddr[ETH_ALEN]; /* Other end of the wireless link */ #endif - if (!sniffer) { - if (translate) { + if (!sniffer) { + if (translate) { /* TBD length needs fixing for translated header */ - if (rx_len < (ETH_HLEN + RX_MAC_HEADER_LENGTH) || - rx_len > (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN + FCS_LEN)) - { - DEBUG(0,"ray_cs invalid packet length %d received \n",rx_len); - return; - } - } - else /* encapsulated ethernet */ { - if (rx_len < (ETH_HLEN + RX_MAC_HEADER_LENGTH) || - rx_len > (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN + FCS_LEN)) - { - DEBUG(0,"ray_cs invalid packet length %d received \n",rx_len); - return; - } - } - } - DEBUG(4,"ray_cs rx_data packet\n"); - /* If fragmented packet, verify sizes of fragments add up */ - if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF) { - DEBUG(1,"ray_cs rx'ed fragment\n"); - tmp = (readb(&prcs->var.rx_packet.totalpacketlength[0]) << 8) - + readb(&prcs->var.rx_packet.totalpacketlength[1]); - total_len = tmp; - prcslink = prcs; - do { - tmp -= (readb(&prcslink->var.rx_packet.rx_data_length[0]) << 8) - + readb(&prcslink->var.rx_packet.rx_data_length[1]); - if (readb(&prcslink->var.rx_packet.next_frag_rcs_index) == 0xFF - || tmp < 0) break; - prcslink = rcs_base(local) - + readb(&prcslink->link_field); - } while (1); - - if (tmp < 0) - { - DEBUG(0,"ray_cs rx_data fragment lengths don't add up\n"); - local->stats.rx_dropped++; - release_frag_chain(local, prcs); - return; - } - } - else { /* Single unfragmented packet */ - total_len = rx_len; - } - - skb = dev_alloc_skb( total_len+5 ); - if (skb == NULL) - { - DEBUG(0,"ray_cs rx_data could not allocate skb\n"); - local->stats.rx_dropped++; - if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF) - release_frag_chain(local, prcs); - return; - } - skb_reserve( skb, 2); /* Align IP on 16 byte (TBD check this)*/ - - DEBUG(4,"ray_cs rx_data total_len = %x, rx_len = %x\n",total_len,rx_len); + if (rx_len < (ETH_HLEN + RX_MAC_HEADER_LENGTH) || + rx_len > + (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN + + FCS_LEN)) { + DEBUG(0, + "ray_cs invalid packet length %d received \n", + rx_len); + return; + } + } else { /* encapsulated ethernet */ + + if (rx_len < (ETH_HLEN + RX_MAC_HEADER_LENGTH) || + rx_len > + (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN + + FCS_LEN)) { + DEBUG(0, + "ray_cs invalid packet length %d received \n", + rx_len); + return; + } + } + } + DEBUG(4, "ray_cs rx_data packet\n"); + /* If fragmented packet, verify sizes of fragments add up */ + if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF) { + DEBUG(1, "ray_cs rx'ed fragment\n"); + tmp = (readb(&prcs->var.rx_packet.totalpacketlength[0]) << 8) + + readb(&prcs->var.rx_packet.totalpacketlength[1]); + total_len = tmp; + prcslink = prcs; + do { + tmp -= + (readb(&prcslink->var.rx_packet.rx_data_length[0]) + << 8) + + readb(&prcslink->var.rx_packet.rx_data_length[1]); + if (readb(&prcslink->var.rx_packet.next_frag_rcs_index) + == 0xFF || tmp < 0) + break; + prcslink = rcs_base(local) + + readb(&prcslink->link_field); + } while (1); + + if (tmp < 0) { + DEBUG(0, + "ray_cs rx_data fragment lengths don't add up\n"); + local->stats.rx_dropped++; + release_frag_chain(local, prcs); + return; + } + } else { /* Single unfragmented packet */ + total_len = rx_len; + } + + skb = dev_alloc_skb(total_len + 5); + if (skb == NULL) { + DEBUG(0, "ray_cs rx_data could not allocate skb\n"); + local->stats.rx_dropped++; + if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF) + release_frag_chain(local, prcs); + return; + } + skb_reserve(skb, 2); /* Align IP on 16 byte (TBD check this) */ + + DEBUG(4, "ray_cs rx_data total_len = %x, rx_len = %x\n", total_len, + rx_len); /************************/ - /* Reserve enough room for the whole damn packet. */ - rx_ptr = skb_put( skb, total_len); - /* Copy the whole packet to sk_buff */ - rx_ptr += copy_from_rx_buff(local, rx_ptr, pkt_addr & RX_BUFF_END, rx_len); - /* Get source address */ + /* Reserve enough room for the whole damn packet. */ + rx_ptr = skb_put(skb, total_len); + /* Copy the whole packet to sk_buff */ + rx_ptr += + copy_from_rx_buff(local, rx_ptr, pkt_addr & RX_BUFF_END, rx_len); + /* Get source address */ #ifdef WIRELESS_SPY - skb_copy_from_linear_data_offset(skb, offsetof(struct mac_header, addr_2), - linksrcaddr, ETH_ALEN); + skb_copy_from_linear_data_offset(skb, + offsetof(struct mac_header, addr_2), + linksrcaddr, ETH_ALEN); #endif - /* Now, deal with encapsulation/translation/sniffer */ - if (!sniffer) { - if (!translate) { - /* Encapsulated ethernet, so just lop off 802.11 MAC header */ + /* Now, deal with encapsulation/translation/sniffer */ + if (!sniffer) { + if (!translate) { + /* Encapsulated ethernet, so just lop off 802.11 MAC header */ /* TBD reserve skb_reserve( skb, RX_MAC_HEADER_LENGTH); */ - skb_pull( skb, RX_MAC_HEADER_LENGTH); - } - else { - /* Do translation */ - untranslate(local, skb, total_len); - } - } - else - { /* sniffer mode, so just pass whole packet */ }; + skb_pull(skb, RX_MAC_HEADER_LENGTH); + } else { + /* Do translation */ + untranslate(local, skb, total_len); + } + } else { /* sniffer mode, so just pass whole packet */ + }; /************************/ - /* Now pick up the rest of the fragments if any */ - tmp = 17; - if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF) { - prcslink = prcs; - DEBUG(1,"ray_cs rx_data in fragment loop\n"); - do { - prcslink = rcs_base(local) - + readb(&prcslink->var.rx_packet.next_frag_rcs_index); - rx_len = (( readb(&prcslink->var.rx_packet.rx_data_length[0]) << 8) - + readb(&prcslink->var.rx_packet.rx_data_length[1])) - & RX_BUFF_END; - pkt_addr = (( readb(&prcslink->var.rx_packet.rx_data_ptr[0]) << 8) - + readb(&prcslink->var.rx_packet.rx_data_ptr[1])) - & RX_BUFF_END; - - rx_ptr += copy_from_rx_buff(local, rx_ptr, pkt_addr, rx_len); - - } while (tmp-- && - readb(&prcslink->var.rx_packet.next_frag_rcs_index) != 0xFF); - release_frag_chain(local, prcs); - } - - skb->protocol = eth_type_trans(skb,dev); - netif_rx(skb); - local->stats.rx_packets++; - local->stats.rx_bytes += total_len; - - /* Gather signal strength per address */ + /* Now pick up the rest of the fragments if any */ + tmp = 17; + if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF) { + prcslink = prcs; + DEBUG(1, "ray_cs rx_data in fragment loop\n"); + do { + prcslink = rcs_base(local) + + + readb(&prcslink->var.rx_packet.next_frag_rcs_index); + rx_len = + ((readb(&prcslink->var.rx_packet.rx_data_length[0]) + << 8) + + + readb(&prcslink->var.rx_packet.rx_data_length[1])) + & RX_BUFF_END; + pkt_addr = + ((readb(&prcslink->var.rx_packet.rx_data_ptr[0]) << + 8) + + readb(&prcslink->var.rx_packet.rx_data_ptr[1])) + & RX_BUFF_END; + + rx_ptr += + copy_from_rx_buff(local, rx_ptr, pkt_addr, rx_len); + + } while (tmp-- && + readb(&prcslink->var.rx_packet.next_frag_rcs_index) != + 0xFF); + release_frag_chain(local, prcs); + } + + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + local->stats.rx_packets++; + local->stats.rx_bytes += total_len; + + /* Gather signal strength per address */ #ifdef WIRELESS_SPY - /* For the Access Point or the node having started the ad-hoc net - * note : ad-hoc work only in some specific configurations, but we - * kludge in ray_get_wireless_stats... */ - if(!memcmp(linksrcaddr, local->bss_id, ETH_ALEN)) - { - /* Update statistics */ - /*local->wstats.qual.qual = none ? */ - local->wstats.qual.level = siglev; - /*local->wstats.qual.noise = none ? */ - local->wstats.qual.updated = 0x2; - } - /* Now, update the spy stuff */ - { - struct iw_quality wstats; - wstats.level = siglev; - /* wstats.noise = none ? */ - /* wstats.qual = none ? */ - wstats.updated = 0x2; - /* Update spy records */ - wireless_spy_update(dev, linksrcaddr, &wstats); - } -#endif /* WIRELESS_SPY */ + /* For the Access Point or the node having started the ad-hoc net + * note : ad-hoc work only in some specific configurations, but we + * kludge in ray_get_wireless_stats... */ + if (!memcmp(linksrcaddr, local->bss_id, ETH_ALEN)) { + /* Update statistics */ + /*local->wstats.qual.qual = none ? */ + local->wstats.qual.level = siglev; + /*local->wstats.qual.noise = none ? */ + local->wstats.qual.updated = 0x2; + } + /* Now, update the spy stuff */ + { + struct iw_quality wstats; + wstats.level = siglev; + /* wstats.noise = none ? */ + /* wstats.qual = none ? */ + wstats.updated = 0x2; + /* Update spy records */ + wireless_spy_update(dev, linksrcaddr, &wstats); + } +#endif /* WIRELESS_SPY */ } /* end rx_data */ + /*===========================================================================*/ static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len) { - snaphdr_t *psnap = (snaphdr_t *)(skb->data + RX_MAC_HEADER_LENGTH); - struct ieee80211_hdr *pmac = (struct ieee80211_hdr *)skb->data; - __be16 type = *(__be16 *)psnap->ethertype; - int delta; - struct ethhdr *peth; - UCHAR srcaddr[ADDRLEN]; - UCHAR destaddr[ADDRLEN]; - static UCHAR org_bridge[3] = {0, 0, 0xf8}; - static UCHAR org_1042[3] = {0, 0, 0}; + snaphdr_t *psnap = (snaphdr_t *) (skb->data + RX_MAC_HEADER_LENGTH); + struct ieee80211_hdr *pmac = (struct ieee80211_hdr *)skb->data; + __be16 type = *(__be16 *) psnap->ethertype; + int delta; + struct ethhdr *peth; + UCHAR srcaddr[ADDRLEN]; + UCHAR destaddr[ADDRLEN]; + static UCHAR org_bridge[3] = { 0, 0, 0xf8 }; + static UCHAR org_1042[3] = { 0, 0, 0 }; - memcpy(destaddr, ieee80211_get_DA(pmac), ADDRLEN); - memcpy(srcaddr, ieee80211_get_SA(pmac), ADDRLEN); + memcpy(destaddr, ieee80211_get_DA(pmac), ADDRLEN); + memcpy(srcaddr, ieee80211_get_SA(pmac), ADDRLEN); #ifdef PCMCIA_DEBUG - if (pc_debug > 3) { - int i; - printk(KERN_DEBUG "skb->data before untranslate"); - for (i=0;i<64;i++) - printk("%02x ",skb->data[i]); - printk("\n" KERN_DEBUG "type = %08x, xsap = %02x%02x%02x, org = %02x02x02x\n", - ntohs(type), - psnap->dsap, psnap->ssap, psnap->ctrl, - psnap->org[0], psnap->org[1], psnap->org[2]); - printk(KERN_DEBUG "untranslate skb->data = %p\n",skb->data); - } + if (pc_debug > 3) { + int i; + printk(KERN_DEBUG "skb->data before untranslate"); + for (i = 0; i < 64; i++) + printk("%02x ", skb->data[i]); + printk("\n" KERN_DEBUG + "type = %08x, xsap = %02x%02x%02x, org = %02x02x02x\n", + ntohs(type), psnap->dsap, psnap->ssap, psnap->ctrl, + psnap->org[0], psnap->org[1], psnap->org[2]); + printk(KERN_DEBUG "untranslate skb->data = %p\n", skb->data); + } #endif - if (psnap->dsap != 0xaa || psnap->ssap != 0xaa || psnap->ctrl != 3) { - /* not a snap type so leave it alone */ - DEBUG(3,"ray_cs untranslate NOT SNAP %02x %02x %02x\n", - psnap->dsap, psnap->ssap, psnap->ctrl); - - delta = RX_MAC_HEADER_LENGTH - ETH_HLEN; - peth = (struct ethhdr *)(skb->data + delta); - peth->h_proto = htons(len - RX_MAC_HEADER_LENGTH); - } - else { /* Its a SNAP */ - if (memcmp(psnap->org, org_bridge, 3) == 0) { /* EtherII and nuke the LLC */ - DEBUG(3,"ray_cs untranslate Bridge encap\n"); - delta = RX_MAC_HEADER_LENGTH - + sizeof(struct snaphdr_t) - ETH_HLEN; - peth = (struct ethhdr *)(skb->data + delta); - peth->h_proto = type; - } else if (memcmp(psnap->org, org_1042, 3) == 0) { - switch (ntohs(type)) { - case ETH_P_IPX: - case ETH_P_AARP: - DEBUG(3,"ray_cs untranslate RFC IPX/AARP\n"); - delta = RX_MAC_HEADER_LENGTH - ETH_HLEN; - peth = (struct ethhdr *)(skb->data + delta); - peth->h_proto = htons(len - RX_MAC_HEADER_LENGTH); - break; - default: - DEBUG(3,"ray_cs untranslate RFC default\n"); - delta = RX_MAC_HEADER_LENGTH + - sizeof(struct snaphdr_t) - ETH_HLEN; - peth = (struct ethhdr *)(skb->data + delta); - peth->h_proto = type; - break; - } - } else { - printk("ray_cs untranslate very confused by packet\n"); - delta = RX_MAC_HEADER_LENGTH - ETH_HLEN; - peth = (struct ethhdr *)(skb->data + delta); - peth->h_proto = type; + if (psnap->dsap != 0xaa || psnap->ssap != 0xaa || psnap->ctrl != 3) { + /* not a snap type so leave it alone */ + DEBUG(3, "ray_cs untranslate NOT SNAP %02x %02x %02x\n", + psnap->dsap, psnap->ssap, psnap->ctrl); + + delta = RX_MAC_HEADER_LENGTH - ETH_HLEN; + peth = (struct ethhdr *)(skb->data + delta); + peth->h_proto = htons(len - RX_MAC_HEADER_LENGTH); + } else { /* Its a SNAP */ + if (memcmp(psnap->org, org_bridge, 3) == 0) { + /* EtherII and nuke the LLC */ + DEBUG(3, "ray_cs untranslate Bridge encap\n"); + delta = RX_MAC_HEADER_LENGTH + + sizeof(struct snaphdr_t) - ETH_HLEN; + peth = (struct ethhdr *)(skb->data + delta); + peth->h_proto = type; + } else if (memcmp(psnap->org, org_1042, 3) == 0) { + switch (ntohs(type)) { + case ETH_P_IPX: + case ETH_P_AARP: + DEBUG(3, "ray_cs untranslate RFC IPX/AARP\n"); + delta = RX_MAC_HEADER_LENGTH - ETH_HLEN; + peth = (struct ethhdr *)(skb->data + delta); + peth->h_proto = + htons(len - RX_MAC_HEADER_LENGTH); + break; + default: + DEBUG(3, "ray_cs untranslate RFC default\n"); + delta = RX_MAC_HEADER_LENGTH + + sizeof(struct snaphdr_t) - ETH_HLEN; + peth = (struct ethhdr *)(skb->data + delta); + peth->h_proto = type; + break; + } + } else { + printk("ray_cs untranslate very confused by packet\n"); + delta = RX_MAC_HEADER_LENGTH - ETH_HLEN; + peth = (struct ethhdr *)(skb->data + delta); + peth->h_proto = type; + } } - } /* TBD reserve skb_reserve(skb, delta); */ - skb_pull(skb, delta); - DEBUG(3,"untranslate after skb_pull(%d), skb->data = %p\n",delta,skb->data); - memcpy(peth->h_dest, destaddr, ADDRLEN); - memcpy(peth->h_source, srcaddr, ADDRLEN); + skb_pull(skb, delta); + DEBUG(3, "untranslate after skb_pull(%d), skb->data = %p\n", delta, + skb->data); + memcpy(peth->h_dest, destaddr, ADDRLEN); + memcpy(peth->h_source, srcaddr, ADDRLEN); #ifdef PCMCIA_DEBUG - if (pc_debug > 3) { - int i; - printk(KERN_DEBUG "skb->data after untranslate:"); - for (i=0;i<64;i++) - printk("%02x ",skb->data[i]); - printk("\n"); - } + if (pc_debug > 3) { + int i; + printk(KERN_DEBUG "skb->data after untranslate:"); + for (i = 0; i < 64; i++) + printk("%02x ", skb->data[i]); + printk("\n"); + } #endif } /* end untranslate */ + /*===========================================================================*/ /* Copy data from circular receive buffer to PC memory. * dest = destination address in PC memory * pkt_addr = source address in receive buffer * len = length of packet to copy */ -static int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int length) -{ - int wrap_bytes = (pkt_addr + length) - (RX_BUFF_END + 1); - if (wrap_bytes <= 0) - { - memcpy_fromio(dest,local->rmem + pkt_addr,length); - } - else /* Packet wrapped in circular buffer */ - { - memcpy_fromio(dest,local->rmem+pkt_addr,length - wrap_bytes); - memcpy_fromio(dest + length - wrap_bytes, local->rmem, wrap_bytes); - } - return length; +static int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, + int length) +{ + int wrap_bytes = (pkt_addr + length) - (RX_BUFF_END + 1); + if (wrap_bytes <= 0) { + memcpy_fromio(dest, local->rmem + pkt_addr, length); + } else { /* Packet wrapped in circular buffer */ + + memcpy_fromio(dest, local->rmem + pkt_addr, + length - wrap_bytes); + memcpy_fromio(dest + length - wrap_bytes, local->rmem, + wrap_bytes); + } + return length; } + /*===========================================================================*/ -static void release_frag_chain(ray_dev_t *local, struct rcs __iomem * prcs) -{ - struct rcs __iomem *prcslink = prcs; - int tmp = 17; - unsigned rcsindex = readb(&prcs->var.rx_packet.next_frag_rcs_index); - - while (tmp--) { - writeb(CCS_BUFFER_FREE, &prcslink->buffer_status); - if (rcsindex >= (NUMBER_OF_CCS + NUMBER_OF_RCS)) { - DEBUG(1,"ray_cs interrupt bad rcsindex = 0x%x\n",rcsindex); - break; - } - prcslink = rcs_base(local) + rcsindex; - rcsindex = readb(&prcslink->var.rx_packet.next_frag_rcs_index); - } - writeb(CCS_BUFFER_FREE, &prcslink->buffer_status); +static void release_frag_chain(ray_dev_t *local, struct rcs __iomem *prcs) +{ + struct rcs __iomem *prcslink = prcs; + int tmp = 17; + unsigned rcsindex = readb(&prcs->var.rx_packet.next_frag_rcs_index); + + while (tmp--) { + writeb(CCS_BUFFER_FREE, &prcslink->buffer_status); + if (rcsindex >= (NUMBER_OF_CCS + NUMBER_OF_RCS)) { + DEBUG(1, "ray_cs interrupt bad rcsindex = 0x%x\n", + rcsindex); + break; + } + prcslink = rcs_base(local) + rcsindex; + rcsindex = readb(&prcslink->var.rx_packet.next_frag_rcs_index); + } + writeb(CCS_BUFFER_FREE, &prcslink->buffer_status); } + /*===========================================================================*/ static void authenticate(ray_dev_t *local) { - struct pcmcia_device *link = local->finder; - DEBUG(0,"ray_cs Starting authentication.\n"); - if (!(pcmcia_dev_present(link))) { - DEBUG(2,"ray_cs authenticate - device not present\n"); - return; - } - - del_timer(&local->timer); - if (build_auth_frame(local, local->bss_id, OPEN_AUTH_REQUEST)) { - local->timer.function = &join_net; - } - else { - local->timer.function = &authenticate_timeout; - } - local->timer.expires = jiffies + HZ*2; - local->timer.data = (long)local; - add_timer(&local->timer); - local->authentication_state = AWAITING_RESPONSE; + struct pcmcia_device *link = local->finder; + DEBUG(0, "ray_cs Starting authentication.\n"); + if (!(pcmcia_dev_present(link))) { + DEBUG(2, "ray_cs authenticate - device not present\n"); + return; + } + + del_timer(&local->timer); + if (build_auth_frame(local, local->bss_id, OPEN_AUTH_REQUEST)) { + local->timer.function = &join_net; + } else { + local->timer.function = &authenticate_timeout; + } + local->timer.expires = jiffies + HZ * 2; + local->timer.data = (long)local; + add_timer(&local->timer); + local->authentication_state = AWAITING_RESPONSE; } /* end authenticate */ + /*===========================================================================*/ static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs, - unsigned int pkt_addr, int rx_len) -{ - UCHAR buff[256]; - struct rx_msg *msg = (struct rx_msg *)buff; - - del_timer(&local->timer); - - copy_from_rx_buff(local, buff, pkt_addr, rx_len & 0xff); - /* if we are trying to get authenticated */ - if (local->sparm.b4.a_network_type == ADHOC) { - DEBUG(1,"ray_cs rx_auth var= %02x %02x %02x %02x %02x %02x\n", msg->var[0],msg->var[1],msg->var[2],msg->var[3],msg->var[4],msg->var[5]); - if (msg->var[2] == 1) { - DEBUG(0,"ray_cs Sending authentication response.\n"); - if (!build_auth_frame (local, msg->mac.addr_2, OPEN_AUTH_RESPONSE)) { - local->authentication_state = NEED_TO_AUTH; - memcpy(local->auth_id, msg->mac.addr_2, ADDRLEN); - } - } - } - else /* Infrastructure network */ - { - if (local->authentication_state == AWAITING_RESPONSE) { - /* Verify authentication sequence #2 and success */ - if (msg->var[2] == 2) { - if ((msg->var[3] | msg->var[4]) == 0) { - DEBUG(1,"Authentication successful\n"); - local->card_status = CARD_AUTH_COMPLETE; - associate(local); - local->authentication_state = AUTHENTICATED; - } - else { - DEBUG(0,"Authentication refused\n"); - local->card_status = CARD_AUTH_REFUSED; - join_net((u_long)local); - local->authentication_state = UNAUTHENTICATED; - } - } - } - } + unsigned int pkt_addr, int rx_len) +{ + UCHAR buff[256]; + struct rx_msg *msg = (struct rx_msg *)buff; + + del_timer(&local->timer); + + copy_from_rx_buff(local, buff, pkt_addr, rx_len & 0xff); + /* if we are trying to get authenticated */ + if (local->sparm.b4.a_network_type == ADHOC) { + DEBUG(1, "ray_cs rx_auth var= %02x %02x %02x %02x %02x %02x\n", + msg->var[0], msg->var[1], msg->var[2], msg->var[3], + msg->var[4], msg->var[5]); + if (msg->var[2] == 1) { + DEBUG(0, "ray_cs Sending authentication response.\n"); + if (!build_auth_frame + (local, msg->mac.addr_2, OPEN_AUTH_RESPONSE)) { + local->authentication_state = NEED_TO_AUTH; + memcpy(local->auth_id, msg->mac.addr_2, + ADDRLEN); + } + } + } else { /* Infrastructure network */ + + if (local->authentication_state == AWAITING_RESPONSE) { + /* Verify authentication sequence #2 and success */ + if (msg->var[2] == 2) { + if ((msg->var[3] | msg->var[4]) == 0) { + DEBUG(1, "Authentication successful\n"); + local->card_status = CARD_AUTH_COMPLETE; + associate(local); + local->authentication_state = + AUTHENTICATED; + } else { + DEBUG(0, "Authentication refused\n"); + local->card_status = CARD_AUTH_REFUSED; + join_net((u_long) local); + local->authentication_state = + UNAUTHENTICATED; + } + } + } + } } /* end rx_authenticate */ + /*===========================================================================*/ static void associate(ray_dev_t *local) { - struct ccs __iomem *pccs; - struct pcmcia_device *link = local->finder; - struct net_device *dev = link->priv; - int ccsindex; - if (!(pcmcia_dev_present(link))) { - DEBUG(2,"ray_cs associate - device not present\n"); - return; - } - /* If no tx buffers available, return*/ - if ((ccsindex = get_free_ccs(local)) < 0) - { + struct ccs __iomem *pccs; + struct pcmcia_device *link = local->finder; + struct net_device *dev = link->priv; + int ccsindex; + if (!(pcmcia_dev_present(link))) { + DEBUG(2, "ray_cs associate - device not present\n"); + return; + } + /* If no tx buffers available, return */ + if ((ccsindex = get_free_ccs(local)) < 0) { /* TBD should never be here but... what if we are? */ - DEBUG(1,"ray_cs associate - No free ccs\n"); - return; - } - DEBUG(1,"ray_cs Starting association with access point\n"); - pccs = ccs_base(local) + ccsindex; - /* fill in the CCS */ - writeb(CCS_START_ASSOCIATION, &pccs->cmd); - /* Interrupt the firmware to process the command */ - if (interrupt_ecf(local, ccsindex)) { - DEBUG(1,"ray_cs associate failed - ECF not ready for intr\n"); - writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); - - del_timer(&local->timer); - local->timer.expires = jiffies + HZ*2; - local->timer.data = (long)local; - local->timer.function = &join_net; - add_timer(&local->timer); - local->card_status = CARD_ASSOC_FAILED; - return; - } - if (!sniffer) netif_start_queue(dev); + DEBUG(1, "ray_cs associate - No free ccs\n"); + return; + } + DEBUG(1, "ray_cs Starting association with access point\n"); + pccs = ccs_base(local) + ccsindex; + /* fill in the CCS */ + writeb(CCS_START_ASSOCIATION, &pccs->cmd); + /* Interrupt the firmware to process the command */ + if (interrupt_ecf(local, ccsindex)) { + DEBUG(1, "ray_cs associate failed - ECF not ready for intr\n"); + writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); + + del_timer(&local->timer); + local->timer.expires = jiffies + HZ * 2; + local->timer.data = (long)local; + local->timer.function = &join_net; + add_timer(&local->timer); + local->card_status = CARD_ASSOC_FAILED; + return; + } + if (!sniffer) + netif_start_queue(dev); } /* end associate */ + /*===========================================================================*/ -static void rx_deauthenticate(ray_dev_t *local, struct rcs __iomem *prcs, - unsigned int pkt_addr, int rx_len) +static void rx_deauthenticate(ray_dev_t *local, struct rcs __iomem *prcs, + unsigned int pkt_addr, int rx_len) { /* UCHAR buff[256]; struct rx_msg *msg = (struct rx_msg *)buff; */ - DEBUG(0,"Deauthentication frame received\n"); - local->authentication_state = UNAUTHENTICATED; - /* Need to reauthenticate or rejoin depending on reason code */ + DEBUG(0, "Deauthentication frame received\n"); + local->authentication_state = UNAUTHENTICATED; + /* Need to reauthenticate or rejoin depending on reason code */ /* copy_from_rx_buff(local, buff, pkt_addr, rx_len & 0xff); */ } + /*===========================================================================*/ static void clear_interrupt(ray_dev_t *local) { - writeb(0, local->amem + CIS_OFFSET + HCS_INTR_OFFSET); + writeb(0, local->amem + CIS_OFFSET + HCS_INTR_OFFSET); } + /*===========================================================================*/ #ifdef CONFIG_PROC_FS #define MAXDATA (PAGE_SIZE - 80) static char *card_status[] = { - "Card inserted - uninitialized", /* 0 */ - "Card not downloaded", /* 1 */ - "Waiting for download parameters", /* 2 */ - "Card doing acquisition", /* 3 */ - "Acquisition complete", /* 4 */ - "Authentication complete", /* 5 */ - "Association complete", /* 6 */ - "???", "???", "???", "???", /* 7 8 9 10 undefined */ - "Card init error", /* 11 */ - "Download parameters error", /* 12 */ - "???", /* 13 */ - "Acquisition failed", /* 14 */ - "Authentication refused", /* 15 */ - "Association failed" /* 16 */ + "Card inserted - uninitialized", /* 0 */ + "Card not downloaded", /* 1 */ + "Waiting for download parameters", /* 2 */ + "Card doing acquisition", /* 3 */ + "Acquisition complete", /* 4 */ + "Authentication complete", /* 5 */ + "Association complete", /* 6 */ + "???", "???", "???", "???", /* 7 8 9 10 undefined */ + "Card init error", /* 11 */ + "Download parameters error", /* 12 */ + "???", /* 13 */ + "Acquisition failed", /* 14 */ + "Authentication refused", /* 15 */ + "Association failed" /* 16 */ }; -static char *nettype[] = {"Adhoc", "Infra "}; -static char *framing[] = {"Encapsulation", "Translation"} +static char *nettype[] = { "Adhoc", "Infra " }; +static char *framing[] = { "Encapsulation", "Translation" } + ; /*===========================================================================*/ static int ray_cs_proc_show(struct seq_file *m, void *v) { /* Print current values which are not available via other means - * eg ifconfig + * eg ifconfig */ - int i; - struct pcmcia_device *link; - struct net_device *dev; - ray_dev_t *local; - UCHAR *p; - struct freq_hop_element *pfh; - UCHAR c[33]; - - link = this_device; - if (!link) - return 0; - dev = (struct net_device *)link->priv; - if (!dev) - return 0; - local = netdev_priv(dev); - if (!local) - return 0; - - seq_puts(m, "Raylink Wireless LAN driver status\n"); - seq_printf(m, "%s\n", rcsid); - /* build 4 does not report version, and field is 0x55 after memtest */ - seq_puts(m, "Firmware version = "); - if (local->fw_ver == 0x55) - seq_puts(m, "4 - Use dump_cis for more details\n"); - else - seq_printf(m, "%2d.%02d.%02d\n", - local->fw_ver, local->fw_bld, local->fw_var); - - for (i=0; i<32; i++) c[i] = local->sparm.b5.a_current_ess_id[i]; - c[32] = 0; - seq_printf(m, "%s network ESSID = \"%s\"\n", - nettype[local->sparm.b5.a_network_type], c); - - p = local->bss_id; - seq_printf(m, "BSSID = %pM\n", p); - - seq_printf(m, "Country code = %d\n", - local->sparm.b5.a_curr_country_code); - - i = local->card_status; - if (i < 0) i = 10; - if (i > 16) i = 10; - seq_printf(m, "Card status = %s\n", card_status[i]); - - seq_printf(m, "Framing mode = %s\n",framing[translate]); - - seq_printf(m, "Last pkt signal lvl = %d\n", local->last_rsl); - - if (local->beacon_rxed) { - /* Pull some fields out of last beacon received */ - seq_printf(m, "Beacon Interval = %d Kus\n", - local->last_bcn.beacon_intvl[0] - + 256 * local->last_bcn.beacon_intvl[1]); - - p = local->last_bcn.elements; - if (p[0] == C_ESSID_ELEMENT_ID) p += p[1] + 2; - else { - seq_printf(m, "Parse beacon failed at essid element id = %d\n",p[0]); - return 0; - } - - if (p[0] == C_SUPPORTED_RATES_ELEMENT_ID) { - seq_puts(m, "Supported rate codes = "); - for (i=2; idwell_time[0] + 256 * pfh->dwell_time[1]); - seq_printf(m, "Hop set = %d \n", pfh->hop_set); - seq_printf(m, "Hop pattern = %d \n", pfh->hop_pattern); - seq_printf(m, "Hop index = %d \n", pfh->hop_index); - p += p[1] + 2; - } - else { - seq_puts(m, "Parse beacon failed at FH param element\n"); - return 0; + int i; + struct pcmcia_device *link; + struct net_device *dev; + ray_dev_t *local; + UCHAR *p; + struct freq_hop_element *pfh; + UCHAR c[33]; + + link = this_device; + if (!link) + return 0; + dev = (struct net_device *)link->priv; + if (!dev) + return 0; + local = netdev_priv(dev); + if (!local) + return 0; + + seq_puts(m, "Raylink Wireless LAN driver status\n"); + seq_printf(m, "%s\n", rcsid); + /* build 4 does not report version, and field is 0x55 after memtest */ + seq_puts(m, "Firmware version = "); + if (local->fw_ver == 0x55) + seq_puts(m, "4 - Use dump_cis for more details\n"); + else + seq_printf(m, "%2d.%02d.%02d\n", + local->fw_ver, local->fw_bld, local->fw_var); + + for (i = 0; i < 32; i++) + c[i] = local->sparm.b5.a_current_ess_id[i]; + c[32] = 0; + seq_printf(m, "%s network ESSID = \"%s\"\n", + nettype[local->sparm.b5.a_network_type], c); + + p = local->bss_id; + seq_printf(m, "BSSID = %pM\n", p); + + seq_printf(m, "Country code = %d\n", + local->sparm.b5.a_curr_country_code); + + i = local->card_status; + if (i < 0) + i = 10; + if (i > 16) + i = 10; + seq_printf(m, "Card status = %s\n", card_status[i]); + + seq_printf(m, "Framing mode = %s\n", framing[translate]); + + seq_printf(m, "Last pkt signal lvl = %d\n", local->last_rsl); + + if (local->beacon_rxed) { + /* Pull some fields out of last beacon received */ + seq_printf(m, "Beacon Interval = %d Kus\n", + local->last_bcn.beacon_intvl[0] + + 256 * local->last_bcn.beacon_intvl[1]); + + p = local->last_bcn.elements; + if (p[0] == C_ESSID_ELEMENT_ID) + p += p[1] + 2; + else { + seq_printf(m, + "Parse beacon failed at essid element id = %d\n", + p[0]); + return 0; + } + + if (p[0] == C_SUPPORTED_RATES_ELEMENT_ID) { + seq_puts(m, "Supported rate codes = "); + for (i = 2; i < p[1] + 2; i++) + seq_printf(m, "0x%02x ", p[i]); + seq_putc(m, '\n'); + p += p[1] + 2; + } else { + seq_puts(m, "Parse beacon failed at rates element\n"); + return 0; + } + + if (p[0] == C_FH_PARAM_SET_ELEMENT_ID) { + pfh = (struct freq_hop_element *)p; + seq_printf(m, "Hop dwell = %d Kus\n", + pfh->dwell_time[0] + + 256 * pfh->dwell_time[1]); + seq_printf(m, "Hop set = %d \n", + pfh->hop_set); + seq_printf(m, "Hop pattern = %d \n", + pfh->hop_pattern); + seq_printf(m, "Hop index = %d \n", + pfh->hop_index); + p += p[1] + 2; + } else { + seq_puts(m, + "Parse beacon failed at FH param element\n"); + return 0; + } + } else { + seq_puts(m, "No beacons received\n"); } - } else { - seq_puts(m, "No beacons received\n"); - } - return 0; + return 0; } static int ray_cs_proc_open(struct inode *inode, struct file *file) @@ -2684,74 +2799,77 @@ static int ray_cs_proc_open(struct inode *inode, struct file *file) } static const struct file_operations ray_cs_proc_fops = { - .owner = THIS_MODULE, - .open = ray_cs_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, + .owner = THIS_MODULE, + .open = ray_cs_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, }; #endif /*===========================================================================*/ static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type) { - int addr; - struct ccs __iomem *pccs; - struct tx_msg __iomem *ptx; - int ccsindex; - - /* If no tx buffers available, return */ - if ((ccsindex = get_free_tx_ccs(local)) < 0) - { - DEBUG(1,"ray_cs send authenticate - No free tx ccs\n"); - return -1; - } - - pccs = ccs_base(local) + ccsindex; - - /* Address in card space */ - addr = TX_BUF_BASE + (ccsindex << 11); - /* fill in the CCS */ - writeb(CCS_TX_REQUEST, &pccs->cmd); - writeb(addr >> 8, pccs->var.tx_request.tx_data_ptr); - writeb(0x20, pccs->var.tx_request.tx_data_ptr + 1); - writeb(TX_AUTHENTICATE_LENGTH_MSB, pccs->var.tx_request.tx_data_length); - writeb(TX_AUTHENTICATE_LENGTH_LSB,pccs->var.tx_request.tx_data_length + 1); - writeb(0, &pccs->var.tx_request.pow_sav_mode); - - ptx = local->sram + addr; - /* fill in the mac header */ - writeb(PROTOCOL_VER | AUTHENTIC_TYPE, &ptx->mac.frame_ctl_1); - writeb(0, &ptx->mac.frame_ctl_2); - - memcpy_toio(ptx->mac.addr_1, dest, ADDRLEN); - memcpy_toio(ptx->mac.addr_2, local->sparm.b4.a_mac_addr, ADDRLEN); - memcpy_toio(ptx->mac.addr_3, local->bss_id, ADDRLEN); - - /* Fill in msg body with protocol 00 00, sequence 01 00 ,status 00 00 */ - memset_io(ptx->var, 0, 6); - writeb(auth_type & 0xff, ptx->var + 2); - - /* Interrupt the firmware to process the command */ - if (interrupt_ecf(local, ccsindex)) { - DEBUG(1,"ray_cs send authentication request failed - ECF not ready for intr\n"); - writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); - return -1; - } - return 0; + int addr; + struct ccs __iomem *pccs; + struct tx_msg __iomem *ptx; + int ccsindex; + + /* If no tx buffers available, return */ + if ((ccsindex = get_free_tx_ccs(local)) < 0) { + DEBUG(1, "ray_cs send authenticate - No free tx ccs\n"); + return -1; + } + + pccs = ccs_base(local) + ccsindex; + + /* Address in card space */ + addr = TX_BUF_BASE + (ccsindex << 11); + /* fill in the CCS */ + writeb(CCS_TX_REQUEST, &pccs->cmd); + writeb(addr >> 8, pccs->var.tx_request.tx_data_ptr); + writeb(0x20, pccs->var.tx_request.tx_data_ptr + 1); + writeb(TX_AUTHENTICATE_LENGTH_MSB, pccs->var.tx_request.tx_data_length); + writeb(TX_AUTHENTICATE_LENGTH_LSB, + pccs->var.tx_request.tx_data_length + 1); + writeb(0, &pccs->var.tx_request.pow_sav_mode); + + ptx = local->sram + addr; + /* fill in the mac header */ + writeb(PROTOCOL_VER | AUTHENTIC_TYPE, &ptx->mac.frame_ctl_1); + writeb(0, &ptx->mac.frame_ctl_2); + + memcpy_toio(ptx->mac.addr_1, dest, ADDRLEN); + memcpy_toio(ptx->mac.addr_2, local->sparm.b4.a_mac_addr, ADDRLEN); + memcpy_toio(ptx->mac.addr_3, local->bss_id, ADDRLEN); + + /* Fill in msg body with protocol 00 00, sequence 01 00 ,status 00 00 */ + memset_io(ptx->var, 0, 6); + writeb(auth_type & 0xff, ptx->var + 2); + + /* Interrupt the firmware to process the command */ + if (interrupt_ecf(local, ccsindex)) { + DEBUG(1, + "ray_cs send authentication request failed - ECF not ready for intr\n"); + writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); + return -1; + } + return 0; } /* End build_auth_frame */ /*===========================================================================*/ #ifdef CONFIG_PROC_FS static void raycs_write(const char *name, write_proc_t *w, void *data) { - struct proc_dir_entry * entry = create_proc_entry(name, S_IFREG | S_IWUSR, NULL); + struct proc_dir_entry *entry = + create_proc_entry(name, S_IFREG | S_IWUSR, NULL); if (entry) { entry->write_proc = w; entry->data = data; } } -static int write_essid(struct file *file, const char __user *buffer, unsigned long count, void *data) +static int write_essid(struct file *file, const char __user *buffer, + unsigned long count, void *data) { static char proc_essid[33]; int len = count; @@ -2765,7 +2883,8 @@ static int write_essid(struct file *file, const char __user *buffer, unsigned lo return count; } -static int write_int(struct file *file, const char __user *buffer, unsigned long count, void *data) +static int write_int(struct file *file, const char __user *buffer, + unsigned long count, void *data) { static char proc_number[10]; char *p; @@ -2785,7 +2904,7 @@ static int write_int(struct file *file, const char __user *buffer, unsigned long unsigned int c = *p - '0'; if (c > 9) return -EINVAL; - nr = nr*10 + c; + nr = nr * 10 + c; p++; } while (--len); *(int *)data = nr; @@ -2797,55 +2916,58 @@ static struct pcmcia_device_id ray_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x01a6, 0x0000), PCMCIA_DEVICE_NULL, }; + MODULE_DEVICE_TABLE(pcmcia, ray_ids); static struct pcmcia_driver ray_driver = { - .owner = THIS_MODULE, - .drv = { - .name = "ray_cs", - }, - .probe = ray_probe, - .remove = ray_detach, - .id_table = ray_ids, - .suspend = ray_suspend, - .resume = ray_resume, + .owner = THIS_MODULE, + .drv = { + .name = "ray_cs", + }, + .probe = ray_probe, + .remove = ray_detach, + .id_table = ray_ids, + .suspend = ray_suspend, + .resume = ray_resume, }; static int __init init_ray_cs(void) { - int rc; - - DEBUG(1, "%s\n", rcsid); - rc = pcmcia_register_driver(&ray_driver); - DEBUG(1, "raylink init_module register_pcmcia_driver returns 0x%x\n",rc); + int rc; + + DEBUG(1, "%s\n", rcsid); + rc = pcmcia_register_driver(&ray_driver); + DEBUG(1, "raylink init_module register_pcmcia_driver returns 0x%x\n", + rc); #ifdef CONFIG_PROC_FS - proc_mkdir("driver/ray_cs", NULL); + proc_mkdir("driver/ray_cs", NULL); - proc_create("driver/ray_cs/ray_cs", 0, NULL, &ray_cs_proc_fops); - raycs_write("driver/ray_cs/essid", write_essid, NULL); - raycs_write("driver/ray_cs/net_type", write_int, &net_type); - raycs_write("driver/ray_cs/translate", write_int, &translate); + proc_create("driver/ray_cs/ray_cs", 0, NULL, &ray_cs_proc_fops); + raycs_write("driver/ray_cs/essid", write_essid, NULL); + raycs_write("driver/ray_cs/net_type", write_int, &net_type); + raycs_write("driver/ray_cs/translate", write_int, &translate); #endif - if (translate != 0) translate = 1; - return 0; + if (translate != 0) + translate = 1; + return 0; } /* init_ray_cs */ /*===========================================================================*/ static void __exit exit_ray_cs(void) { - DEBUG(0, "ray_cs: cleanup_module\n"); + DEBUG(0, "ray_cs: cleanup_module\n"); #ifdef CONFIG_PROC_FS - remove_proc_entry("driver/ray_cs/ray_cs", NULL); - remove_proc_entry("driver/ray_cs/essid", NULL); - remove_proc_entry("driver/ray_cs/net_type", NULL); - remove_proc_entry("driver/ray_cs/translate", NULL); - remove_proc_entry("driver/ray_cs", NULL); + remove_proc_entry("driver/ray_cs/ray_cs", NULL); + remove_proc_entry("driver/ray_cs/essid", NULL); + remove_proc_entry("driver/ray_cs/net_type", NULL); + remove_proc_entry("driver/ray_cs/translate", NULL); + remove_proc_entry("driver/ray_cs", NULL); #endif - pcmcia_unregister_driver(&ray_driver); + pcmcia_unregister_driver(&ray_driver); } /* exit_ray_cs */ module_init(init_ray_cs); -- GitLab From d8ae4f52d8244cc4a0f0983e65dfc31739739de9 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 10 Mar 2009 14:35:07 -0700 Subject: [PATCH 3599/4982] iwlwifi: add valid tx antenna information in rate_scale_table debugfs when display rate_scale_table debugfs information, also display valid tx antenna information, this will help user to select correct antenna when issue fixed rate debugfs command Signed-off-by: Wey-Yi Guy Acked-by: Ben Cahill Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 99da4067887..039ad5769d3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2526,7 +2526,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, ssize_t ret; struct iwl_lq_sta *lq_sta = file->private_data; + struct iwl_priv *priv; + priv = lq_sta->drv; buff = kmalloc(1024, GFP_KERNEL); if (!buff) return -ENOMEM; @@ -2537,6 +2539,10 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, lq_sta->active_legacy_rate); desc += sprintf(buff+desc, "fixed rate 0x%X\n", lq_sta->dbg_fixed_rate); + desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", + (priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "", + (priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "", + (priv->hw_params.valid_tx_ant & ANT_C) ? "ANT_C" : ""); desc += sprintf(buff+desc, "general:" "flags=0x%X mimo-d=%d s-ant0x%x d-ant=0x%x\n", lq_sta->lq.general_params.flags, -- GitLab From adb7b5e62ba84b57692ebfa12f4b80d6cf0801a9 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 10 Mar 2009 14:35:08 -0700 Subject: [PATCH 3600/4982] iwlwifi: add rf information in rate_scale debugfs command Adding more Radio information when displaying rate_scale_table. This can help to understand how many antenna and the current RF condition such as SISO, MIMO2, MIMO3. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 039ad5769d3..9bcebf2f460 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2527,6 +2527,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, struct iwl_lq_sta *lq_sta = file->private_data; struct iwl_priv *priv; + struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); priv = lq_sta->drv; buff = kmalloc(1024, GFP_KERNEL); @@ -2543,6 +2544,16 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, (priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "", (priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "", (priv->hw_params.valid_tx_ant & ANT_C) ? "ANT_C" : ""); + desc += sprintf(buff+desc, "lq type %s\n", + (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); + if (is_Ht(tbl->lq_type)) { + desc += sprintf(buff+desc, " %s", + (is_siso(tbl->lq_type)) ? "SISO" : + ((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3")); + desc += sprintf(buff+desc, " %s", + (tbl->is_fat) ? "40MHz" : "20MHz"); + desc += sprintf(buff+desc, " %s\n", (tbl->is_SGI) ? "SGI" : ""); + } desc += sprintf(buff+desc, "general:" "flags=0x%X mimo-d=%d s-ant0x%x d-ant=0x%x\n", lq_sta->lq.general_params.flags, -- GitLab From 86b4766b059e071c5e8d680be48cf730355dca5a Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 10 Mar 2009 14:35:09 -0700 Subject: [PATCH 3601/4982] iwlwifi: remove un-necessary rs_tl_turn_on_agg() after agg enabled After the MLME handshaking complete and tx aggregation started for the tid. Do not send unnecessary turn on aggregation request to mac80211. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 9bcebf2f460..a6f4c74ff2b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -1700,6 +1700,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, u16 high_low; s32 sr; u8 tid = MAX_TID_COUNT; + struct iwl_tid_data *tid_data; IWL_DEBUG_RATE(priv, "rate scale calculate new rate for skb\n"); @@ -2035,8 +2036,15 @@ lq_update: if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) && (lq_sta->tx_agg_tid_en & (1 << tid)) && (tid != MAX_TID_COUNT)) { - IWL_DEBUG_RATE(priv, "try to aggregate tid %d\n", tid); - rs_tl_turn_on_agg(priv, tid, lq_sta, sta); + tid_data = + &priv->stations[lq_sta->lq.sta_id].tid[tid]; + if (tid_data->agg.state == IWL_AGG_OFF) { + IWL_DEBUG_RATE(priv, + "try to aggregate tid %d\n", + tid); + rs_tl_turn_on_agg(priv, tid, + lq_sta, sta); + } } lq_sta->action_counter = 0; rs_set_stay_in_table(priv, 0, lq_sta); -- GitLab From 8fe723117a8ef543b6e68ba24e50e1c15250f6c5 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 10 Mar 2009 14:35:10 -0700 Subject: [PATCH 3602/4982] iwlwifi: HT performance improvement changes During rate scaling, checking for 0 retry count before decrement the count by 1, this can avoid the retry count to become 255 (0xff), which will cause the rate to drop faster than what we expect during good condition (receive 0 retry packet). also change the algorithm to make the rate not drop faster than what we like. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 11 ++++++----- drivers/net/wireless/iwlwifi/iwl-agn-rs.h | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index a6f4c74ff2b..0929f310b2d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -801,7 +801,10 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, !(info->flags & IEEE80211_TX_STAT_AMPDU)) return; - retries = info->status.rates[0].count - 1; + if (info->flags & IEEE80211_TX_STAT_AMPDU) + retries = 0; + else + retries = info->status.rates[0].count - 1; if (retries > 15) retries = 15; @@ -1897,7 +1900,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) scale_action = 1; else if (low != IWL_RATE_INVALID) - scale_action = -1; + scale_action = 0; } /* Both adjacent throughputs are measured, but neither one has better @@ -1918,9 +1921,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, sr >= IWL_RATE_INCREASE_TH) { scale_action = 1; } else { - IWL_DEBUG_RATE(priv, - "decrease rate because of high tpt\n"); - scale_action = -1; + scale_action = 0; } /* Lower adjacent rate's throughput is measured */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index 345806dd887..ab59acc405d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h @@ -231,7 +231,7 @@ enum { #define IWL_RS_GOOD_RATIO 12800 /* 100% */ #define IWL_RATE_SCALE_SWITCH 10880 /* 85% */ #define IWL_RATE_HIGH_TH 10880 /* 85% */ -#define IWL_RATE_INCREASE_TH 8960 /* 70% */ +#define IWL_RATE_INCREASE_TH 6400 /* 50% */ #define IWL_RATE_DECREASE_TH 1920 /* 15% */ /* possible actions when in legacy mode */ -- GitLab From df36c044f51ba6889c2d8b0efd285303bf2a0fbe Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 10 Mar 2009 14:35:11 -0700 Subject: [PATCH 3603/4982] iwlwifi: check IEEE80211_TX_STAT_AMPDU for agg pkt when perform rate scaling, in tx status function, checking for IEEE80211_TX_STAT_AMPDU flag instead of IEEE_TX_CTL_AMPDU flag to perform AMPDU rate scaling operation. IEEE80211_TX_CTL_AMPDU was set by mac80211 for aggregation pkt. But when iwlwifi receive the tx status reply, it reset the flag to following info->flags = IEEE80211_TX_STAT_ACK; info->flags |= IEEE80211_TX_STAT_AMPDU; it causes the rate-scaling to not work for aggregation pkt if we checking for IEEE80211_TX_CTL_AMPDU flag. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 0929f310b2d..43c796bb580 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -916,7 +916,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, tpt = search_tbl->expected_tpt[rs_index]; else tpt = 0; - if (info->flags & IEEE80211_TX_CTL_AMPDU) + if (info->flags & IEEE80211_TX_STAT_AMPDU) rs_collect_tx_data(search_win, rs_index, tpt, info->status.ampdu_ack_len, info->status.ampdu_ack_map); @@ -932,7 +932,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, tpt = curr_tbl->expected_tpt[rs_index]; else tpt = 0; - if (info->flags & IEEE80211_TX_CTL_AMPDU) + if (info->flags & IEEE80211_TX_STAT_AMPDU) rs_collect_tx_data(window, rs_index, tpt, info->status.ampdu_ack_len, info->status.ampdu_ack_map); @@ -944,7 +944,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, /* If not searching for new mode, increment success/failed counter * ... these help determine when to start searching again */ if (lq_sta->stay_in_tbl) { - if (info->flags & IEEE80211_TX_CTL_AMPDU) { + if (info->flags & IEEE80211_TX_STAT_AMPDU) { lq_sta->total_success += info->status.ampdu_ack_map; lq_sta->total_failed += (info->status.ampdu_ack_len - info->status.ampdu_ack_map); -- GitLab From 3c4955f8d9b706231d226d7a73877cb7d786277f Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 10 Mar 2009 14:35:12 -0700 Subject: [PATCH 3604/4982] iwlwifi: verify the antenna selection when receive fixed rate debugfs When iwlwifi driver receive fixed rate debugfs command, validate the antenna selection, if the selection is invalid, report the valid antenna choice and do not set the rate scale table to fixed rate. Otherwise, set the entire rate scale table to the fixed rate request by the user. this validation can prevent sysassert happen in uCode Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 43c796bb580..cab7842a73a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2473,18 +2473,25 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, u32 *rate_n_flags, int index) { struct iwl_priv *priv; + u8 valid_tx_ant; + u8 ant_sel_tx; priv = lq_sta->drv; + valid_tx_ant = priv->hw_params.valid_tx_ant; if (lq_sta->dbg_fixed_rate) { - if (index < 12) { + ant_sel_tx = + ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) + >> RATE_MCS_ANT_POS); + if ((valid_tx_ant & ant_sel_tx) == ant_sel_tx) { *rate_n_flags = lq_sta->dbg_fixed_rate; + IWL_DEBUG_RATE(priv, "Fixed rate ON\n"); } else { - if (lq_sta->band == IEEE80211_BAND_5GHZ) - *rate_n_flags = 0x800D; - else - *rate_n_flags = 0x820A; + lq_sta->dbg_fixed_rate = 0; + IWL_ERR(priv, + "Invalid antenna selection 0x%X, Valid is 0x%X\n", + ant_sel_tx, valid_tx_ant); + IWL_DEBUG_RATE(priv, "Fixed rate OFF\n"); } - IWL_DEBUG_RATE(priv, "Fixed rate ON\n"); } else { IWL_DEBUG_RATE(priv, "Fixed rate OFF\n"); } -- GitLab From fa11d525ef9e4870a080868a7588d27ca8e87c5e Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 11 Mar 2009 11:17:54 -0700 Subject: [PATCH 3605/4982] iwl3945: fix sparse error error is: iwl3945-base.c:545:5: warning: symbol 'iwl3945_set_dynamic_key' was not declared. Should it be static? Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 12166cea386..6b44c1f13c5 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -542,7 +542,7 @@ static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) return 0; } -int iwl3945_set_dynamic_key(struct iwl_priv *priv, +static int iwl3945_set_dynamic_key(struct iwl_priv *priv, struct ieee80211_key_conf *keyconf, u8 sta_id) { int ret = 0; -- GitLab From 5c8df2d56a160a31386ee7807adfc1c74e826535 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 11 Mar 2009 11:17:55 -0700 Subject: [PATCH 3606/4982] iwl3945: use iwl_led structure 3945 can now use iwl_led's structure from iwlwifi. Patch also removes CONFIG_IWL3945_LEDS flag from Kconfig as 3945's led support will now be enabled if user selects CONFIG_IWLWIFI_LEDS. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Kconfig | 10 +--- drivers/net/wireless/iwlwifi/Makefile | 3 +- drivers/net/wireless/iwlwifi/iwl-3945-led.c | 66 +++++++++++---------- drivers/net/wireless/iwlwifi/iwl-3945-led.h | 18 +----- drivers/net/wireless/iwlwifi/iwl-3945.c | 4 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 9 +-- drivers/net/wireless/iwlwifi/iwl-led.h | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 8 files changed, 43 insertions(+), 71 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index a894deb065d..8304f6406a1 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -6,11 +6,9 @@ config IWLWIFI select MAC80211_LEDS if IWLWIFI_LEDS select LEDS_CLASS if IWLWIFI_LEDS select RFKILL if IWLWIFI_RFKILL - select MAC80211_LEDS if IWL3945_LEDS - select LEDS_CLASS if IWL3945_LEDS config IWLWIFI_LEDS - bool "Enable LED support in iwlagn driver" + bool "Enable LED support in iwlagn and iwl3945 drivers" depends on IWLWIFI config IWLWIFI_RFKILL @@ -122,9 +120,3 @@ config IWL3945_SPECTRUM_MEASUREMENT depends on IWL3945 ---help--- This option will enable spectrum measurement for the iwl3945 driver. - -config IWL3945_LEDS - bool "Enable LEDS features in iwl3945 driver" - depends on IWL3945 - ---help--- - This option enables LEDS for the iwl3945 driver. diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index d5f8009c5ab..d79d97ad61a 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -16,7 +16,6 @@ iwlagn-$(CONFIG_IWL5000) += iwl-6000.o iwlagn-$(CONFIG_IWL5000) += iwl-1000.o obj-$(CONFIG_IWL3945) += iwl3945.o -iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o -iwl3945-$(CONFIG_IWL3945_LEDS) += iwl-3945-led.o +iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index a973ac13a1d..ac22f59be9e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -24,6 +24,7 @@ * *****************************************************************************/ +#ifdef CONFIG_IWLWIFI_LEDS #include #include @@ -163,8 +164,8 @@ static int iwl3945_led_associated(struct iwl_priv *priv, int led_id) static void iwl3945_led_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness) { - struct iwl3945_led *led = container_of(led_cdev, - struct iwl3945_led, led_dev); + struct iwl_led *led = container_of(led_cdev, + struct iwl_led, led_dev); struct iwl_priv *priv = led->priv; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) @@ -202,7 +203,7 @@ static void iwl3945_led_brightness_set(struct led_classdev *led_cdev, * Register led class with the system */ static int iwl3945_led_register_led(struct iwl_priv *priv, - struct iwl3945_led *led, + struct iwl_led *led, enum led_type type, u8 set_led, char *trigger) { @@ -315,66 +316,66 @@ int iwl3945_led_register(struct iwl_priv *priv) priv->allow_blinking = 0; trigger = ieee80211_get_radio_led_name(priv->hw); - snprintf(priv->led39[IWL_LED_TRG_RADIO].name, - sizeof(priv->led39[IWL_LED_TRG_RADIO].name), "iwl-%s::radio", + snprintf(priv->led[IWL_LED_TRG_RADIO].name, + sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s::radio", wiphy_name(priv->hw->wiphy)); - priv->led39[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on; - priv->led39[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off; - priv->led39[IWL_LED_TRG_RADIO].led_pattern = NULL; + priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on; + priv->led[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off; + priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; ret = iwl3945_led_register_led(priv, - &priv->led39[IWL_LED_TRG_RADIO], + &priv->led[IWL_LED_TRG_RADIO], IWL_LED_TRG_RADIO, 1, trigger); if (ret) goto exit_fail; trigger = ieee80211_get_assoc_led_name(priv->hw); - snprintf(priv->led39[IWL_LED_TRG_ASSOC].name, - sizeof(priv->led39[IWL_LED_TRG_ASSOC].name), "iwl-%s::assoc", + snprintf(priv->led[IWL_LED_TRG_ASSOC].name, + sizeof(priv->led[IWL_LED_TRG_ASSOC].name), "iwl-%s::assoc", wiphy_name(priv->hw->wiphy)); ret = iwl3945_led_register_led(priv, - &priv->led39[IWL_LED_TRG_ASSOC], + &priv->led[IWL_LED_TRG_ASSOC], IWL_LED_TRG_ASSOC, 0, trigger); /* for assoc always turn led on */ - priv->led39[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on; - priv->led39[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on; - priv->led39[IWL_LED_TRG_ASSOC].led_pattern = NULL; + priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on; + priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on; + priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL; if (ret) goto exit_fail; trigger = ieee80211_get_rx_led_name(priv->hw); - snprintf(priv->led39[IWL_LED_TRG_RX].name, - sizeof(priv->led39[IWL_LED_TRG_RX].name), "iwl-%s::RX", + snprintf(priv->led[IWL_LED_TRG_RX].name, + sizeof(priv->led[IWL_LED_TRG_RX].name), "iwl-%s::RX", wiphy_name(priv->hw->wiphy)); ret = iwl3945_led_register_led(priv, - &priv->led39[IWL_LED_TRG_RX], + &priv->led[IWL_LED_TRG_RX], IWL_LED_TRG_RX, 0, trigger); - priv->led39[IWL_LED_TRG_RX].led_on = iwl3945_led_associated; - priv->led39[IWL_LED_TRG_RX].led_off = iwl3945_led_associated; - priv->led39[IWL_LED_TRG_RX].led_pattern = iwl3945_led_pattern; + priv->led[IWL_LED_TRG_RX].led_on = iwl3945_led_associated; + priv->led[IWL_LED_TRG_RX].led_off = iwl3945_led_associated; + priv->led[IWL_LED_TRG_RX].led_pattern = iwl3945_led_pattern; if (ret) goto exit_fail; trigger = ieee80211_get_tx_led_name(priv->hw); - snprintf(priv->led39[IWL_LED_TRG_TX].name, - sizeof(priv->led39[IWL_LED_TRG_TX].name), "iwl-%s::TX", + snprintf(priv->led[IWL_LED_TRG_TX].name, + sizeof(priv->led[IWL_LED_TRG_TX].name), "iwl-%s::TX", wiphy_name(priv->hw->wiphy)); ret = iwl3945_led_register_led(priv, - &priv->led39[IWL_LED_TRG_TX], + &priv->led[IWL_LED_TRG_TX], IWL_LED_TRG_TX, 0, trigger); - priv->led39[IWL_LED_TRG_TX].led_on = iwl3945_led_associated; - priv->led39[IWL_LED_TRG_TX].led_off = iwl3945_led_associated; - priv->led39[IWL_LED_TRG_TX].led_pattern = iwl3945_led_pattern; + priv->led[IWL_LED_TRG_TX].led_on = iwl3945_led_associated; + priv->led[IWL_LED_TRG_TX].led_off = iwl3945_led_associated; + priv->led[IWL_LED_TRG_TX].led_pattern = iwl3945_led_pattern; if (ret) goto exit_fail; @@ -388,7 +389,7 @@ exit_fail: /* unregister led class */ -static void iwl3945_led_unregister_led(struct iwl3945_led *led, u8 set_led) +static void iwl3945_led_unregister_led(struct iwl_led *led, u8 set_led) { if (!led->registered) return; @@ -403,9 +404,10 @@ static void iwl3945_led_unregister_led(struct iwl3945_led *led, u8 set_led) /* Unregister all led handlers */ void iwl3945_led_unregister(struct iwl_priv *priv) { - iwl3945_led_unregister_led(&priv->led39[IWL_LED_TRG_ASSOC], 0); - iwl3945_led_unregister_led(&priv->led39[IWL_LED_TRG_RX], 0); - iwl3945_led_unregister_led(&priv->led39[IWL_LED_TRG_TX], 0); - iwl3945_led_unregister_led(&priv->led39[IWL_LED_TRG_RADIO], 1); + iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_ASSOC], 0); + iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RX], 0); + iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_TX], 0); + iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RADIO], 1); } +#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.h b/drivers/net/wireless/iwlwifi/iwl-3945-led.h index 88185a6ccd6..3b65642258c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.h @@ -29,24 +29,10 @@ struct iwl_priv; -#ifdef CONFIG_IWL3945_LEDS +#ifdef CONFIG_IWLWIFI_LEDS #include "iwl-led.h" -struct iwl3945_led { - struct iwl_priv *priv; - struct led_classdev led_dev; - char name[32]; - - int (*led_on) (struct iwl_priv *priv, int led_id); - int (*led_off) (struct iwl_priv *priv, int led_id); - int (*led_pattern) (struct iwl_priv *priv, int led_id, - unsigned int idx); - - enum led_type type; - unsigned int registered; -}; - extern int iwl3945_led_register(struct iwl_priv *priv); extern void iwl3945_led_unregister(struct iwl_priv *priv); extern void iwl3945_led_background(struct iwl_priv *priv); @@ -55,6 +41,6 @@ extern void iwl3945_led_background(struct iwl_priv *priv); static inline int iwl3945_led_register(struct iwl_priv *priv) { return 0; } static inline void iwl3945_led_unregister(struct iwl_priv *priv) {} static inline void iwl3945_led_background(struct iwl_priv *priv) {} -#endif /* CONFIG_IWL3945_LEDS */ +#endif /* IWLWIFI_LEDS*/ #endif /* IWL3945_LEDS_H */ diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 0a750534ddf..9e6f9ec1a2b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -554,7 +554,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, struct ieee80211_rx_status *stats) { struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; -#ifdef CONFIG_IWL3945_LEDS +#ifdef CONFIG_IWLWIFI_LEDS struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); #endif struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); @@ -583,7 +583,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, (struct ieee80211_hdr *)rxb->skb->data, le32_to_cpu(rx_end->status), stats); -#ifdef CONFIG_IWL3945_LEDS +#ifdef CONFIG_IWLWIFI_LEDS if (ieee80211_is_data(hdr->frame_control)) priv->rxtxpackets += len; #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 21764948833..0baae802282 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -926,19 +926,12 @@ struct iwl_priv { struct rfkill *rfkill; #endif -#if defined(CONFIG_IWLWIFI_LEDS) || defined(CONFIG_IWL3945_LEDS) +#ifdef CONFIG_IWLWIFI_LEDS unsigned long last_blink_time; u8 last_blink_rate; u8 allow_blinking; u64 led_tpt; -#endif - -#ifdef CONFIG_IWLWIFI_LEDS struct iwl_led led[IWL_LED_TRG_MAX]; -#endif - -#ifdef CONFIG_IWL3945_LEDS - struct iwl3945_led led39[IWL_LED_TRG_MAX]; unsigned int rxtxpackets; #endif u16 active_rate; diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h index 140fd8fa485..ef9b174c37f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-led.h @@ -30,7 +30,7 @@ struct iwl_priv; -#if defined(CONFIG_IWLWIFI_LEDS) || defined(CONFIG_IWL3945_LEDS) +#ifdef CONFIG_IWLWIFI_LEDS #include #define IWL_LED_SOLID 11 diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 6b44c1f13c5..ae4c89625e5 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -890,7 +890,7 @@ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv, tx->timeout.pm_frame_timeout = cpu_to_le16(2); } else { tx->timeout.pm_frame_timeout = 0; -#ifdef CONFIG_IWL3945_LEDS +#ifdef CONFIG_IWLWIFI_LEDS priv->rxtxpackets += le16_to_cpu(cmd->cmd.tx.len); #endif } -- GitLab From dd5b687edacab6cfacf7b9983e86a60c0612e994 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 11 Mar 2009 11:17:56 -0700 Subject: [PATCH 3607/4982] iwl3945 : fix rate scaling Patch fixes the bug 1900 at http://www.intellinuxwireless.org/bugzilla/show_bug.cgi?id=1900 Issues: Throughput and success ratio calculations were not done properly. Number of retries were exceeding 16. Fix: Patch fixes above issues by doing window calculations inline with iwlwifi Patch adds sanity check to limit number of retries to 16. Signed-off-by: Abhijeet Kolekar Acked-by: Mohamed Abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 127 ++++++++++++++------- 1 file changed, 88 insertions(+), 39 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index a2664589c88..f65c308a671 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -127,6 +127,7 @@ static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = { #define IWL_RATE_MIN_FAILURE_TH 8 #define IWL_RATE_MIN_SUCCESS_TH 8 #define IWL_RATE_DECREASE_TH 1920 +#define IWL_RATE_RETRY_TH 15 static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band) { @@ -298,37 +299,53 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, } spin_lock_irqsave(&rs_sta->lock, flags); - while (retries--) { - /* If we have filled up the window then subtract one from the - * success counter if the high-bit is counting toward - * success */ - if (window->counter == IWL_RATE_MAX_WINDOW) { - if (window->data & (1ULL << (IWL_RATE_MAX_WINDOW - 1))) + /* + * Keep track of only the latest 62 tx frame attempts in this rate's + * history window; anything older isn't really relevant any more. + * If we have filled up the sliding window, drop the oldest attempt; + * if the oldest attempt (highest bit in bitmap) shows "success", + * subtract "1" from the success counter (this is the main reason + * we keep these bitmaps!). + * */ + while (retries > 0) { + if (window->counter >= IWL_RATE_MAX_WINDOW) { + + /* remove earliest */ + window->counter = IWL_RATE_MAX_WINDOW - 1; + + if (window->data & (1ULL << (IWL_RATE_MAX_WINDOW - 1))) { + window->data &= ~(1ULL << (IWL_RATE_MAX_WINDOW - 1)); window->success_counter--; - } else - window->counter++; + } + } - /* Slide the window to the left one bit */ - window->data = (window->data << 1); + /* Increment frames-attempted counter */ + window->counter++; - /* If this packet was a success then set the low bit high */ - if (success) { + /* Shift bitmap by one frame (throw away oldest history), + * OR in "1", and increment "success" if this + * frame was successful. */ + window->data <<= 1; + if (success > 0) { window->success_counter++; - window->data |= 1; + window->data |= 0x1; + success--; } - /* window->counter can't be 0 -- it is either >0 or - * IWL_RATE_MAX_WINDOW */ - window->success_ratio = 12800 * window->success_counter / - window->counter; - - /* Tag this window as having been updated */ - window->stamp = jiffies; - + retries--; } + /* Calculate current success ratio, avoid divide-by-0! */ + if (window->counter > 0) + window->success_ratio = 128 * (100 * window->success_counter) + / window->counter; + else + window->success_ratio = IWL_INVALID_VALUE; + fail_count = window->counter - window->success_counter; + + /* Calculate average throughput, if we have enough history. */ if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) || (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH)) window->average_tpt = ((window->success_ratio * @@ -336,6 +353,9 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, else window->average_tpt = IWL_INVALID_VALUE; + /* Tag this window as having been updated */ + window->stamp = jiffies; + spin_unlock_irqrestore(&rs_sta->lock, flags); } @@ -468,7 +488,10 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband IWL_DEBUG_RATE(priv, "enter\n"); - retries = info->status.rates[0].count; + retries = info->status.rates[0].count - 1; + /* Sanity Check for retries */ + if (retries > IWL_RATE_RETRY_TH) + retries = IWL_RATE_RETRY_TH; first_index = sband->bitrates[info->status.rates[0].idx].hw_value; if ((first_index < 0) || (first_index >= IWL_RATE_COUNT_3945)) { @@ -724,7 +747,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, fail_count = window->counter - window->success_counter; - if (((fail_count <= IWL_RATE_MIN_FAILURE_TH) && + if (((fail_count < IWL_RATE_MIN_FAILURE_TH) && (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) { spin_unlock_irqrestore(&rs_sta->lock, flags); @@ -735,6 +758,9 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, window->counter, window->success_counter, rs_sta->expected_tpt ? "not " : ""); + + /* Can't calculate this yet; not enough history */ + window->average_tpt = IWL_INVALID_VALUE; goto out; } @@ -750,6 +776,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, if ((max_rate_idx != -1) && (max_rate_idx < high)) high = IWL_RATE_INVALID; + /* Collect Measured throughputs of adjacent rates */ if (low != IWL_RATE_INVALID) low_tpt = rs_sta->win[low].average_tpt; @@ -758,24 +785,43 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, spin_unlock_irqrestore(&rs_sta->lock, flags); - scale_action = 1; + scale_action = 0; + /* Low success ratio , need to drop the rate */ if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) { IWL_DEBUG_RATE(priv, "decrease rate because of low success_ratio\n"); scale_action = -1; + + /* No throughput measured yet for adjacent rates, + * try increase */ } else if ((low_tpt == IWL_INVALID_VALUE) && - (high_tpt == IWL_INVALID_VALUE)) - scale_action = 1; - else if ((low_tpt != IWL_INVALID_VALUE) && + (high_tpt == IWL_INVALID_VALUE)) { + + if (high != IWL_RATE_INVALID && window->success_counter >= IWL_RATE_INCREASE_TH) + scale_action = 1; + else if (low != IWL_RATE_INVALID) + scale_action = -1; + + /* Both adjacent throughputs are measured, but neither one has + * better throughput; we're using the best rate, don't change + * it! */ + } else if ((low_tpt != IWL_INVALID_VALUE) && (high_tpt != IWL_INVALID_VALUE) && (low_tpt < current_tpt) && (high_tpt < current_tpt)) { + IWL_DEBUG_RATE(priv, "No action -- low [%d] & high [%d] < " "current_tpt [%d]\n", low_tpt, high_tpt, current_tpt); scale_action = 0; + + /* At least one of the rates has better throughput */ } else { if (high_tpt != IWL_INVALID_VALUE) { - if (high_tpt > current_tpt) + + /* High rate has better throughput, Increase + * rate */ + if (high_tpt > current_tpt && + window->success_ratio >= IWL_RATE_INCREASE_TH) scale_action = 1; else { IWL_DEBUG_RATE(priv, @@ -787,29 +833,31 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, IWL_DEBUG_RATE(priv, "decrease rate because of low tpt\n"); scale_action = -1; - } else + } else if (window->success_counter >= IWL_RATE_INCREASE_TH) { + /* Lower rate has better + * throughput,decrease rate */ scale_action = 1; + } } } - if (scale_action == -1) { - if (window->success_ratio > IWL_SUCCESS_DOWN_TH) - scale_action = 0; - } else if (scale_action == 1) { - if (window->success_ratio < IWL_SUCCESS_UP_TH) { - IWL_DEBUG_RATE(priv, "No action -- success_ratio [%d] < " - "SUCCESS UP\n", window->success_ratio); - scale_action = 0; - } - } + /* Sanity check; asked for decrease, but success rate or throughput + * has been good at old rate. Don't change it. */ + if ((scale_action == -1) && (low != IWL_RATE_INVALID) && + ((window->success_ratio > IWL_RATE_HIGH_TH) || + (current_tpt > (100 * rs_sta->expected_tpt[low])))) + scale_action = 0; switch (scale_action) { case -1: + + /* Decrese rate */ if (low != IWL_RATE_INVALID) index = low; break; case 1: + /* Increase rate */ if (high != IWL_RATE_INVALID) index = high; @@ -817,6 +865,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, case 0: default: + /* No change */ break; } -- GitLab From 732587ab438d7528e38df7ceb2c46db9774dcf08 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 11 Mar 2009 11:17:57 -0700 Subject: [PATCH 3608/4982] iwl3945: use iwl_tx_cmd_complete iwl3945 uses iwl_tx_cmd_complete to reclaim the unused buffers of the queue. iwl_tx_cmd_complete in turn call the iwl_hcmd_queue_reclaim which will unmap the dma mapping to tx_cmd and frees the memory. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 81 +-------------------- 1 file changed, 1 insertion(+), 80 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index ae4c89625e5..4465320f273 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1479,85 +1479,6 @@ static void iwl3945_setup_rx_handlers(struct iwl_priv *priv) iwl3945_hw_rx_handler_setup(priv); } -/** - * iwl3945_cmd_queue_reclaim - Reclaim CMD queue entries - * When FW advances 'R' index, all entries between old and new 'R' index - * need to be reclaimed. - */ -static void iwl3945_cmd_queue_reclaim(struct iwl_priv *priv, - int txq_id, int index) -{ - struct iwl_tx_queue *txq = &priv->txq[txq_id]; - struct iwl_queue *q = &txq->q; - int nfreed = 0; - - if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { - IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, " - "is out of range [0-%d] %d %d.\n", txq_id, - index, q->n_bd, q->write_ptr, q->read_ptr); - return; - } - - for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index; - q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { - if (nfreed > 1) { - IWL_ERR(priv, "HCMD skipped: index (%d) %d %d\n", index, - q->write_ptr, q->read_ptr); - queue_work(priv->workqueue, &priv->restart); - break; - } - nfreed++; - } -} - - -/** - * iwl3945_tx_cmd_complete - Pull unused buffers off the queue and reclaim them - * @rxb: Rx buffer to reclaim - * - * If an Rx buffer has an async callback associated with it the callback - * will be executed. The attached skb (if present) will only be freed - * if the callback returns 1 - */ -static void iwl3945_tx_cmd_complete(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - u16 sequence = le16_to_cpu(pkt->hdr.sequence); - int txq_id = SEQ_TO_QUEUE(sequence); - int index = SEQ_TO_INDEX(sequence); - int huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME); - int cmd_index; - struct iwl_cmd *cmd; - - if (WARN(txq_id != IWL_CMD_QUEUE_NUM, - "wrong command queue %d, sequence 0x%X readp=%d writep=%d\n", - txq_id, sequence, - priv->txq[IWL_CMD_QUEUE_NUM].q.read_ptr, - priv->txq[IWL_CMD_QUEUE_NUM].q.write_ptr)) { - iwl_print_hex_dump(priv, IWL_DL_INFO , rxb, 32); - return; - } - - cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); - cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; - - /* Input error checking is done when commands are added to queue. */ - if (cmd->meta.flags & CMD_WANT_SKB) { - cmd->meta.source->u.skb = rxb->skb; - rxb->skb = NULL; - } else if (cmd->meta.u.callback && - !cmd->meta.u.callback(priv, cmd, rxb->skb)) - rxb->skb = NULL; - - iwl3945_cmd_queue_reclaim(priv, txq_id, index); - - if (!(cmd->meta.flags & CMD_ASYNC)) { - clear_bit(STATUS_HCMD_ACTIVE, &priv->status); - wake_up_interruptible(&priv->wait_command_queue); - } -} - /************************** RX-FUNCTIONS ****************************/ /* * Rx theory of operation @@ -1917,7 +1838,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) * fire off the (possibly) blocking iwl_send_cmd() * as we reclaim the driver command queue */ if (rxb && rxb->skb) - iwl3945_tx_cmd_complete(priv, rxb); + iwl_tx_cmd_complete(priv, rxb); else IWL_WARN(priv, "Claim null rxb?\n"); } -- GitLab From fd9377ee6c351b3fd27bcc56fd5e24622df180bb Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Wed, 11 Mar 2009 11:17:58 -0700 Subject: [PATCH 3609/4982] iwl3945: unmap previously mapped memory During preparation of TX we create DMA mapping to TX command as part of preparing the TFD. This mapping needs to be cleared at the time TFD is freed. Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 9e6f9ec1a2b..ba7e720e73c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -741,7 +741,8 @@ int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) { struct iwl3945_tfd *tfd_tmp = (struct iwl3945_tfd *)txq->tfds; - struct iwl3945_tfd *tfd = &tfd_tmp[txq->q.read_ptr]; + int index = txq->q.read_ptr; + struct iwl3945_tfd *tfd = &tfd_tmp[index]; struct pci_dev *dev = priv->pci_dev; int i; int counter; @@ -759,6 +760,13 @@ void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) return; } + /* Unmap tx_cmd */ + if (counter) + pci_unmap_single(dev, + pci_unmap_addr(&txq->cmd[index]->meta, mapping), + pci_unmap_len(&txq->cmd[index]->meta, len), + PCI_DMA_TODEVICE); + /* unmap chunks if any */ for (i = 1; i < counter; i++) { -- GitLab From 48676eb3c3de9013de7d9a63fb8ffb70cd540d95 Mon Sep 17 00:00:00 2001 From: Mohamed Abbas Date: Wed, 11 Mar 2009 11:17:59 -0700 Subject: [PATCH 3610/4982] iwlagn: fix warning when set WEP key iwl_clear_station_table will be called every time rxon called. In this function ucode_key_table is set to 0 even though a static WEP security is set. This will cause in many warning and might be an issue if dynamic WEP is set. This patch make sure we keep track of all existing static WEP when this function is called. Signed-off-by: Mohamed Abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-sta.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 0ea08d08092..1684490d93c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -472,6 +472,7 @@ EXPORT_SYMBOL(iwl_remove_station); void iwl_clear_stations_table(struct iwl_priv *priv) { unsigned long flags; + int i; spin_lock_irqsave(&priv->sta_lock, flags); @@ -486,6 +487,12 @@ void iwl_clear_stations_table(struct iwl_priv *priv) /* clean ucode key table bit map */ priv->ucode_key_table = 0; + /* keep track of static keys */ + for (i = 0; i < WEP_KEYS_MAX ; i++) { + if (priv->wep_keys[i].key_size) + test_and_set_bit(i, &priv->ucode_key_table); + } + spin_unlock_irqrestore(&priv->sta_lock, flags); } EXPORT_SYMBOL(iwl_clear_stations_table); -- GitLab From 18d426c4a8991d1d6c0dc33a62b610b8a6ffc1d2 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Wed, 11 Mar 2009 11:18:00 -0700 Subject: [PATCH 3611/4982] iwlwifi: print contents of control register when error occurs hopefully the register contents will guide us to why this failure occured Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-io.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index c7b8e5bb4e4..083ea1ffbe8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -156,6 +156,7 @@ static inline void __iwl_clear_bit(const char *f, u32 l, static inline int _iwl_grab_nic_access(struct iwl_priv *priv) { int ret; + u32 val; #ifdef CONFIG_IWLWIFI_DEBUG if (atomic_read(&priv->restrict_refcnt)) return 0; @@ -167,7 +168,8 @@ static inline int _iwl_grab_nic_access(struct iwl_priv *priv) (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); if (ret < 0) { - IWL_ERR(priv, "MAC is in deep sleep!\n"); + val = _iwl_read32(priv, CSR_GP_CNTRL); + IWL_ERR(priv, "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); return -EIO; } -- GitLab From 808ff697b357cee54e214efd27921a9ec6461a94 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Wed, 11 Mar 2009 11:18:01 -0700 Subject: [PATCH 3612/4982] iwlwifi: correct log level when error occurs user needs to see this message even if debugging disabled Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index da988860df1..0db3bc011ac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3359,7 +3359,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* amp init */ err = priv->cfg->ops->lib->apm_ops.init(priv); if (err < 0) { - IWL_DEBUG_INFO(priv, "Failed to init APMG\n"); + IWL_ERR(priv, "Failed to init APMG\n"); goto out_iounmap; } /***************** -- GitLab From c5f5d3e6ed4405999d5becaffe18415182fa8eb5 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 16 Mar 2009 22:03:25 +1000 Subject: [PATCH 3613/4982] m68k: use MMU version of setup.h for both MMU and non-MMU The MMU version of setup.h can be used for all m68k platforms. Without a single file "make headers_install" is broken for m68k (since each of the sub-varients of setup.h are not installed). Signed-off-by: Greg Ungerer --- arch/m68k/include/asm/setup.h | 377 ++++++++++++++++++++++++++++++- arch/m68k/include/asm/setup_mm.h | 376 ------------------------------ arch/m68k/include/asm/setup_no.h | 10 - 3 files changed, 374 insertions(+), 389 deletions(-) delete mode 100644 arch/m68k/include/asm/setup_mm.h delete mode 100644 arch/m68k/include/asm/setup_no.h diff --git a/arch/m68k/include/asm/setup.h b/arch/m68k/include/asm/setup.h index 842f86f75cc..4dfb3952b37 100644 --- a/arch/m68k/include/asm/setup.h +++ b/arch/m68k/include/asm/setup.h @@ -1,5 +1,376 @@ -#ifdef __uClinux__ -#include "setup_no.h" +/* +** asm/setup.h -- Definition of the Linux/m68k setup information +** +** Copyright 1992 by Greg Harp +** +** This file is subject to the terms and conditions of the GNU General Public +** License. See the file COPYING in the main directory of this archive +** for more details. +** +** Created 09/29/92 by Greg Harp +** +** 5/2/94 Roman Hodek: +** Added bi_atari part of the machine dependent union bi_un; for now it +** contains just a model field to distinguish between TT and Falcon. +** 26/7/96 Roman Zippel: +** Renamed to setup.h; added some useful macros to allow gcc some +** optimizations if possible. +** 5/10/96 Geert Uytterhoeven: +** Redesign of the boot information structure; moved boot information +** structure to bootinfo.h +*/ + +#ifndef _M68K_SETUP_H +#define _M68K_SETUP_H + + + + /* + * Linux/m68k Architectures + */ + +#define MACH_AMIGA 1 +#define MACH_ATARI 2 +#define MACH_MAC 3 +#define MACH_APOLLO 4 +#define MACH_SUN3 5 +#define MACH_MVME147 6 +#define MACH_MVME16x 7 +#define MACH_BVME6000 8 +#define MACH_HP300 9 +#define MACH_Q40 10 +#define MACH_SUN3X 11 + +#define COMMAND_LINE_SIZE 256 + +#ifdef __KERNEL__ + +#define CL_SIZE COMMAND_LINE_SIZE + +#ifndef __ASSEMBLY__ +extern unsigned long m68k_machtype; +#endif /* !__ASSEMBLY__ */ + +#if !defined(CONFIG_AMIGA) +# define MACH_IS_AMIGA (0) +#elif defined(CONFIG_ATARI) || defined(CONFIG_MAC) || defined(CONFIG_APOLLO) \ + || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) \ + || defined(CONFIG_HP300) || defined(CONFIG_Q40) \ + || defined(CONFIG_SUN3X) || defined(CONFIG_MVME147) +# define MACH_IS_AMIGA (m68k_machtype == MACH_AMIGA) #else -#include "setup_mm.h" +# define MACH_AMIGA_ONLY +# define MACH_IS_AMIGA (1) +# define MACH_TYPE (MACH_AMIGA) #endif + +#if !defined(CONFIG_ATARI) +# define MACH_IS_ATARI (0) +#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_APOLLO) \ + || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) \ + || defined(CONFIG_HP300) || defined(CONFIG_Q40) \ + || defined(CONFIG_SUN3X) || defined(CONFIG_MVME147) +# define MACH_IS_ATARI (m68k_machtype == MACH_ATARI) +#else +# define MACH_ATARI_ONLY +# define MACH_IS_ATARI (1) +# define MACH_TYPE (MACH_ATARI) +#endif + +#if !defined(CONFIG_MAC) +# define MACH_IS_MAC (0) +#elif defined(CONFIG_AMIGA) || defined(CONFIG_ATARI) || defined(CONFIG_APOLLO) \ + || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) \ + || defined(CONFIG_HP300) || defined(CONFIG_Q40) \ + || defined(CONFIG_SUN3X) || defined(CONFIG_MVME147) +# define MACH_IS_MAC (m68k_machtype == MACH_MAC) +#else +# define MACH_MAC_ONLY +# define MACH_IS_MAC (1) +# define MACH_TYPE (MACH_MAC) +#endif + +#if defined(CONFIG_SUN3) +#define MACH_IS_SUN3 (1) +#define MACH_SUN3_ONLY (1) +#define MACH_TYPE (MACH_SUN3) +#else +#define MACH_IS_SUN3 (0) +#endif + +#if !defined (CONFIG_APOLLO) +# define MACH_IS_APOLLO (0) +#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \ + || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) \ + || defined(CONFIG_HP300) || defined(CONFIG_Q40) \ + || defined(CONFIG_SUN3X) || defined(CONFIG_MVME147) +# define MACH_IS_APOLLO (m68k_machtype == MACH_APOLLO) +#else +# define MACH_APOLLO_ONLY +# define MACH_IS_APOLLO (1) +# define MACH_TYPE (MACH_APOLLO) +#endif + +#if !defined (CONFIG_MVME147) +# define MACH_IS_MVME147 (0) +#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \ + || defined(CONFIG_APOLLO) || defined(CONFIG_BVME6000) \ + || defined(CONFIG_HP300) || defined(CONFIG_Q40) \ + || defined(CONFIG_SUN3X) || defined(CONFIG_MVME16x) +# define MACH_IS_MVME147 (m68k_machtype == MACH_MVME147) +#else +# define MACH_MVME147_ONLY +# define MACH_IS_MVME147 (1) +# define MACH_TYPE (MACH_MVME147) +#endif + +#if !defined (CONFIG_MVME16x) +# define MACH_IS_MVME16x (0) +#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \ + || defined(CONFIG_APOLLO) || defined(CONFIG_BVME6000) \ + || defined(CONFIG_HP300) || defined(CONFIG_Q40) \ + || defined(CONFIG_SUN3X) || defined(CONFIG_MVME147) +# define MACH_IS_MVME16x (m68k_machtype == MACH_MVME16x) +#else +# define MACH_MVME16x_ONLY +# define MACH_IS_MVME16x (1) +# define MACH_TYPE (MACH_MVME16x) +#endif + +#if !defined (CONFIG_BVME6000) +# define MACH_IS_BVME6000 (0) +#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \ + || defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x) \ + || defined(CONFIG_HP300) || defined(CONFIG_Q40) \ + || defined(CONFIG_SUN3X) || defined(CONFIG_MVME147) +# define MACH_IS_BVME6000 (m68k_machtype == MACH_BVME6000) +#else +# define MACH_BVME6000_ONLY +# define MACH_IS_BVME6000 (1) +# define MACH_TYPE (MACH_BVME6000) +#endif + +#if !defined (CONFIG_HP300) +# define MACH_IS_HP300 (0) +#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \ + || defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x) \ + || defined(CONFIG_BVME6000) || defined(CONFIG_Q40) \ + || defined(CONFIG_SUN3X) || defined(CONFIG_MVME147) +# define MACH_IS_HP300 (m68k_machtype == MACH_HP300) +#else +# define MACH_HP300_ONLY +# define MACH_IS_HP300 (1) +# define MACH_TYPE (MACH_HP300) +#endif + +#if !defined (CONFIG_Q40) +# define MACH_IS_Q40 (0) +#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \ + || defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x) \ + || defined(CONFIG_BVME6000) || defined(CONFIG_HP300) \ + || defined(CONFIG_SUN3X) || defined(CONFIG_MVME147) +# define MACH_IS_Q40 (m68k_machtype == MACH_Q40) +#else +# define MACH_Q40_ONLY +# define MACH_IS_Q40 (1) +# define MACH_TYPE (MACH_Q40) +#endif + +#if !defined (CONFIG_SUN3X) +# define MACH_IS_SUN3X (0) +#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \ + || defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x) \ + || defined(CONFIG_BVME6000) || defined(CONFIG_HP300) \ + || defined(CONFIG_Q40) || defined(CONFIG_MVME147) +# define MACH_IS_SUN3X (m68k_machtype == MACH_SUN3X) +#else +# define CONFIG_SUN3X_ONLY +# define MACH_IS_SUN3X (1) +# define MACH_TYPE (MACH_SUN3X) +#endif + +#ifndef MACH_TYPE +# define MACH_TYPE (m68k_machtype) +#endif + +#endif /* __KERNEL__ */ + + + /* + * CPU, FPU and MMU types + * + * Note: we may rely on the following equalities: + * + * CPU_68020 == MMU_68851 + * CPU_68030 == MMU_68030 + * CPU_68040 == FPU_68040 == MMU_68040 + * CPU_68060 == FPU_68060 == MMU_68060 + */ + +#define CPUB_68020 0 +#define CPUB_68030 1 +#define CPUB_68040 2 +#define CPUB_68060 3 + +#define CPU_68020 (1< - -/* We have a bigger command line buffer. */ -#undef COMMAND_LINE_SIZE - -#endif /* __KERNEL__ */ - -#define COMMAND_LINE_SIZE 512 -- GitLab From 230d1866a9f9b08c2ab4cb1b60f33fe230ee0a87 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 16 Mar 2009 22:07:39 +1000 Subject: [PATCH 3614/4982] m68k: merge the non-MMU and MMU versions of ptrace.h It is trivial to merge the non-MMU and MMU versions of ptrace.h. Without a single file "make headers_install" is broken for m68k (since each of the sub-varients of ptrace.h are not installed). Signed-off-by: Greg Ungerer --- arch/m68k/include/asm/ptrace.h | 88 +++++++++++++++++++++++++++++-- arch/m68k/include/asm/ptrace_mm.h | 80 ---------------------------- arch/m68k/include/asm/ptrace_no.h | 87 ------------------------------ 3 files changed, 85 insertions(+), 170 deletions(-) delete mode 100644 arch/m68k/include/asm/ptrace_mm.h delete mode 100644 arch/m68k/include/asm/ptrace_no.h diff --git a/arch/m68k/include/asm/ptrace.h b/arch/m68k/include/asm/ptrace.h index e83cd2f6610..8c9194b9854 100644 --- a/arch/m68k/include/asm/ptrace.h +++ b/arch/m68k/include/asm/ptrace.h @@ -1,5 +1,87 @@ -#ifdef __uClinux__ -#include "ptrace_no.h" +#ifndef _M68K_PTRACE_H +#define _M68K_PTRACE_H + +#define PT_D1 0 +#define PT_D2 1 +#define PT_D3 2 +#define PT_D4 3 +#define PT_D5 4 +#define PT_D6 5 +#define PT_D7 6 +#define PT_A0 7 +#define PT_A1 8 +#define PT_A2 9 +#define PT_A3 10 +#define PT_A4 11 +#define PT_A5 12 +#define PT_A6 13 +#define PT_D0 14 +#define PT_USP 15 +#define PT_ORIG_D0 16 +#define PT_SR 17 +#define PT_PC 18 + +#ifndef __ASSEMBLY__ + +/* this struct defines the way the registers are stored on the + stack during a system call. */ + +struct pt_regs { + long d1; + long d2; + long d3; + long d4; + long d5; + long a0; + long a1; + long a2; + long d0; + long orig_d0; + long stkadj; +#ifdef CONFIG_COLDFIRE + unsigned format : 4; /* frame format specifier */ + unsigned vector : 12; /* vector offset */ + unsigned short sr; + unsigned long pc; #else -#include "ptrace_mm.h" + unsigned short sr; + unsigned long pc; + unsigned format : 4; /* frame format specifier */ + unsigned vector : 12; /* vector offset */ #endif +}; + +/* + * This is the extended stack used by signal handlers and the context + * switcher: it's pushed after the normal "struct pt_regs". + */ +struct switch_stack { + unsigned long d6; + unsigned long d7; + unsigned long a3; + unsigned long a4; + unsigned long a5; + unsigned long a6; + unsigned long retpc; +}; + +/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ +#define PTRACE_GETREGS 12 +#define PTRACE_SETREGS 13 +#define PTRACE_GETFPREGS 14 +#define PTRACE_SETFPREGS 15 + +#ifdef __KERNEL__ + +#ifndef PS_S +#define PS_S (0x2000) +#define PS_M (0x1000) +#endif + +#define user_mode(regs) (!((regs)->sr & PS_S)) +#define instruction_pointer(regs) ((regs)->pc) +#define profile_pc(regs) instruction_pointer(regs) +extern void show_regs(struct pt_regs *); +#endif /* __KERNEL__ */ +#endif /* __ASSEMBLY__ */ +#endif /* _M68K_PTRACE_H */ diff --git a/arch/m68k/include/asm/ptrace_mm.h b/arch/m68k/include/asm/ptrace_mm.h deleted file mode 100644 index 57e763d79bf..00000000000 --- a/arch/m68k/include/asm/ptrace_mm.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef _M68K_PTRACE_H -#define _M68K_PTRACE_H - -#define PT_D1 0 -#define PT_D2 1 -#define PT_D3 2 -#define PT_D4 3 -#define PT_D5 4 -#define PT_D6 5 -#define PT_D7 6 -#define PT_A0 7 -#define PT_A1 8 -#define PT_A2 9 -#define PT_A3 10 -#define PT_A4 11 -#define PT_A5 12 -#define PT_A6 13 -#define PT_D0 14 -#define PT_USP 15 -#define PT_ORIG_D0 16 -#define PT_SR 17 -#define PT_PC 18 - -#ifndef __ASSEMBLY__ - -/* this struct defines the way the registers are stored on the - stack during a system call. */ - -struct pt_regs { - long d1; - long d2; - long d3; - long d4; - long d5; - long a0; - long a1; - long a2; - long d0; - long orig_d0; - long stkadj; - unsigned short sr; - unsigned long pc; - unsigned format : 4; /* frame format specifier */ - unsigned vector : 12; /* vector offset */ -}; - -/* - * This is the extended stack used by signal handlers and the context - * switcher: it's pushed after the normal "struct pt_regs". - */ -struct switch_stack { - unsigned long d6; - unsigned long d7; - unsigned long a3; - unsigned long a4; - unsigned long a5; - unsigned long a6; - unsigned long retpc; -}; - -/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ -#define PTRACE_GETREGS 12 -#define PTRACE_SETREGS 13 -#define PTRACE_GETFPREGS 14 -#define PTRACE_SETFPREGS 15 - -#ifdef __KERNEL__ - -#ifndef PS_S -#define PS_S (0x2000) -#define PS_M (0x1000) -#endif - -#define user_mode(regs) (!((regs)->sr & PS_S)) -#define instruction_pointer(regs) ((regs)->pc) -#define profile_pc(regs) instruction_pointer(regs) -extern void show_regs(struct pt_regs *); -#endif /* __KERNEL__ */ -#endif /* __ASSEMBLY__ */ -#endif /* _M68K_PTRACE_H */ diff --git a/arch/m68k/include/asm/ptrace_no.h b/arch/m68k/include/asm/ptrace_no.h deleted file mode 100644 index 8c9194b9854..00000000000 --- a/arch/m68k/include/asm/ptrace_no.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef _M68K_PTRACE_H -#define _M68K_PTRACE_H - -#define PT_D1 0 -#define PT_D2 1 -#define PT_D3 2 -#define PT_D4 3 -#define PT_D5 4 -#define PT_D6 5 -#define PT_D7 6 -#define PT_A0 7 -#define PT_A1 8 -#define PT_A2 9 -#define PT_A3 10 -#define PT_A4 11 -#define PT_A5 12 -#define PT_A6 13 -#define PT_D0 14 -#define PT_USP 15 -#define PT_ORIG_D0 16 -#define PT_SR 17 -#define PT_PC 18 - -#ifndef __ASSEMBLY__ - -/* this struct defines the way the registers are stored on the - stack during a system call. */ - -struct pt_regs { - long d1; - long d2; - long d3; - long d4; - long d5; - long a0; - long a1; - long a2; - long d0; - long orig_d0; - long stkadj; -#ifdef CONFIG_COLDFIRE - unsigned format : 4; /* frame format specifier */ - unsigned vector : 12; /* vector offset */ - unsigned short sr; - unsigned long pc; -#else - unsigned short sr; - unsigned long pc; - unsigned format : 4; /* frame format specifier */ - unsigned vector : 12; /* vector offset */ -#endif -}; - -/* - * This is the extended stack used by signal handlers and the context - * switcher: it's pushed after the normal "struct pt_regs". - */ -struct switch_stack { - unsigned long d6; - unsigned long d7; - unsigned long a3; - unsigned long a4; - unsigned long a5; - unsigned long a6; - unsigned long retpc; -}; - -/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ -#define PTRACE_GETREGS 12 -#define PTRACE_SETREGS 13 -#define PTRACE_GETFPREGS 14 -#define PTRACE_SETFPREGS 15 - -#ifdef __KERNEL__ - -#ifndef PS_S -#define PS_S (0x2000) -#define PS_M (0x1000) -#endif - -#define user_mode(regs) (!((regs)->sr & PS_S)) -#define instruction_pointer(regs) ((regs)->pc) -#define profile_pc(regs) instruction_pointer(regs) -extern void show_regs(struct pt_regs *); -#endif /* __KERNEL__ */ -#endif /* __ASSEMBLY__ */ -#endif /* _M68K_PTRACE_H */ -- GitLab From 8dba99e077ae999c85b41c4567c852313528c7a7 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 16 Mar 2009 22:10:08 +1000 Subject: [PATCH 3615/4982] m68k: merge the non-MMU and MMU versions of signal.h It is trivial to merge the non-MMU and MMU versions of signal.h. Without a single file "make headers_install" is broken for m68k (since each of the sub-varients of signal.h are not installed). Signed-off-by: Greg Ungerer --- arch/m68k/include/asm/signal.h | 216 +++++++++++++++++++++++++++++- arch/m68k/include/asm/signal_mm.h | 206 ---------------------------- arch/m68k/include/asm/signal_no.h | 159 ---------------------- 3 files changed, 212 insertions(+), 369 deletions(-) delete mode 100644 arch/m68k/include/asm/signal_mm.h delete mode 100644 arch/m68k/include/asm/signal_no.h diff --git a/arch/m68k/include/asm/signal.h b/arch/m68k/include/asm/signal.h index 3c19988bd93..08788fdefde 100644 --- a/arch/m68k/include/asm/signal.h +++ b/arch/m68k/include/asm/signal.h @@ -1,5 +1,213 @@ -#ifdef __uClinux__ -#include "signal_no.h" +#ifndef _M68K_SIGNAL_H +#define _M68K_SIGNAL_H + +#include + +/* Avoid too many header ordering problems. */ +struct siginfo; + +#ifdef __KERNEL__ +/* Most things should be clean enough to redefine this at will, if care + is taken to make libc match. */ + +#define _NSIG 64 +#define _NSIG_BPW 32 +#define _NSIG_WORDS (_NSIG / _NSIG_BPW) + +typedef unsigned long old_sigset_t; /* at least 32 bits */ + +typedef struct { + unsigned long sig[_NSIG_WORDS]; +} sigset_t; + #else -#include "signal_mm.h" -#endif +/* Here we must cater to libcs that poke about in kernel headers. */ + +#define NSIG 32 +typedef unsigned long sigset_t; + +#endif /* __KERNEL__ */ + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGIOT 6 +#define SIGBUS 7 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGUSR1 10 +#define SIGSEGV 11 +#define SIGUSR2 12 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGSTKFLT 16 +#define SIGCHLD 17 +#define SIGCONT 18 +#define SIGSTOP 19 +#define SIGTSTP 20 +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGURG 23 +#define SIGXCPU 24 +#define SIGXFSZ 25 +#define SIGVTALRM 26 +#define SIGPROF 27 +#define SIGWINCH 28 +#define SIGIO 29 +#define SIGPOLL SIGIO +/* +#define SIGLOST 29 +*/ +#define SIGPWR 30 +#define SIGSYS 31 +#define SIGUNUSED 31 + +/* These should not be considered constants from userland. */ +#define SIGRTMIN 32 +#define SIGRTMAX _NSIG + +/* + * SA_FLAGS values: + * + * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_RESTART flag to get restarting signals (which were the default long ago) + * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. + * SA_RESETHAND clears the handler when the signal is delivered. + * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. + * SA_NODEFER prevents the current signal from being masked in the handler. + * + * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single + * Unix names RESETHAND and NODEFER respectively. + */ +#define SA_NOCLDSTOP 0x00000001 +#define SA_NOCLDWAIT 0x00000002 +#define SA_SIGINFO 0x00000004 +#define SA_ONSTACK 0x08000000 +#define SA_RESTART 0x10000000 +#define SA_NODEFER 0x40000000 +#define SA_RESETHAND 0x80000000 + +#define SA_NOMASK SA_NODEFER +#define SA_ONESHOT SA_RESETHAND + +/* + * sigaltstack controls + */ +#define SS_ONSTACK 1 +#define SS_DISABLE 2 + +#define MINSIGSTKSZ 2048 +#define SIGSTKSZ 8192 + +#include + +#ifdef __KERNEL__ +struct old_sigaction { + __sighandler_t sa_handler; + old_sigset_t sa_mask; + unsigned long sa_flags; + __sigrestore_t sa_restorer; +}; + +struct sigaction { + __sighandler_t sa_handler; + unsigned long sa_flags; + __sigrestore_t sa_restorer; + sigset_t sa_mask; /* mask last for extensibility */ +}; + +struct k_sigaction { + struct sigaction sa; +}; +#else +/* Here we must cater to libcs that poke about in kernel headers. */ + +struct sigaction { + union { + __sighandler_t _sa_handler; + void (*_sa_sigaction)(int, struct siginfo *, void *); + } _u; + sigset_t sa_mask; + unsigned long sa_flags; + void (*sa_restorer)(void); +}; + +#define sa_handler _u._sa_handler +#define sa_sigaction _u._sa_sigaction + +#endif /* __KERNEL__ */ + +typedef struct sigaltstack { + void __user *ss_sp; + int ss_flags; + size_t ss_size; +} stack_t; + +#ifdef __KERNEL__ +#include + +#ifndef __uClinux__ +#define __HAVE_ARCH_SIG_BITOPS + +static inline void sigaddset(sigset_t *set, int _sig) +{ + asm ("bfset %0{%1,#1}" + : "+od" (*set) + : "id" ((_sig - 1) ^ 31) + : "cc"); +} + +static inline void sigdelset(sigset_t *set, int _sig) +{ + asm ("bfclr %0{%1,#1}" + : "+od" (*set) + : "id" ((_sig - 1) ^ 31) + : "cc"); +} + +static inline int __const_sigismember(sigset_t *set, int _sig) +{ + unsigned long sig = _sig - 1; + return 1 & (set->sig[sig / _NSIG_BPW] >> (sig % _NSIG_BPW)); +} + +static inline int __gen_sigismember(sigset_t *set, int _sig) +{ + int ret; + asm ("bfextu %1{%2,#1},%0" + : "=d" (ret) + : "od" (*set), "id" ((_sig-1) ^ 31) + : "cc"); + return ret; +} + +#define sigismember(set,sig) \ + (__builtin_constant_p(sig) ? \ + __const_sigismember(set,sig) : \ + __gen_sigismember(set,sig)) + +static inline int sigfindinword(unsigned long word) +{ + asm ("bfffo %1{#0,#0},%0" + : "=d" (word) + : "d" (word & -word) + : "cc"); + return word ^ 31; +} + +struct pt_regs; +extern void ptrace_signal_deliver(struct pt_regs *regs, void *cookie); + +#else + +#undef __HAVE_ARCH_SIG_BITOPS +#define ptrace_signal_deliver(regs, cookie) do { } while (0) + +#endif /* __uClinux__ */ +#endif /* __KERNEL__ */ + +#endif /* _M68K_SIGNAL_H */ diff --git a/arch/m68k/include/asm/signal_mm.h b/arch/m68k/include/asm/signal_mm.h deleted file mode 100644 index 3db8a81942f..00000000000 --- a/arch/m68k/include/asm/signal_mm.h +++ /dev/null @@ -1,206 +0,0 @@ -#ifndef _M68K_SIGNAL_H -#define _M68K_SIGNAL_H - -#include - -/* Avoid too many header ordering problems. */ -struct siginfo; - -#ifdef __KERNEL__ -/* Most things should be clean enough to redefine this at will, if care - is taken to make libc match. */ - -#define _NSIG 64 -#define _NSIG_BPW 32 -#define _NSIG_WORDS (_NSIG / _NSIG_BPW) - -typedef unsigned long old_sigset_t; /* at least 32 bits */ - -typedef struct { - unsigned long sig[_NSIG_WORDS]; -} sigset_t; - -#else -/* Here we must cater to libcs that poke about in kernel headers. */ - -#define NSIG 32 -typedef unsigned long sigset_t; - -#endif /* __KERNEL__ */ - -#define SIGHUP 1 -#define SIGINT 2 -#define SIGQUIT 3 -#define SIGILL 4 -#define SIGTRAP 5 -#define SIGABRT 6 -#define SIGIOT 6 -#define SIGBUS 7 -#define SIGFPE 8 -#define SIGKILL 9 -#define SIGUSR1 10 -#define SIGSEGV 11 -#define SIGUSR2 12 -#define SIGPIPE 13 -#define SIGALRM 14 -#define SIGTERM 15 -#define SIGSTKFLT 16 -#define SIGCHLD 17 -#define SIGCONT 18 -#define SIGSTOP 19 -#define SIGTSTP 20 -#define SIGTTIN 21 -#define SIGTTOU 22 -#define SIGURG 23 -#define SIGXCPU 24 -#define SIGXFSZ 25 -#define SIGVTALRM 26 -#define SIGPROF 27 -#define SIGWINCH 28 -#define SIGIO 29 -#define SIGPOLL SIGIO -/* -#define SIGLOST 29 -*/ -#define SIGPWR 30 -#define SIGSYS 31 -#define SIGUNUSED 31 - -/* These should not be considered constants from userland. */ -#define SIGRTMIN 32 -#define SIGRTMAX _NSIG - -/* - * SA_FLAGS values: - * - * SA_ONSTACK indicates that a registered stack_t will be used. - * SA_RESTART flag to get restarting signals (which were the default long ago) - * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. - * SA_RESETHAND clears the handler when the signal is delivered. - * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. - * SA_NODEFER prevents the current signal from being masked in the handler. - * - * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single - * Unix names RESETHAND and NODEFER respectively. - */ -#define SA_NOCLDSTOP 0x00000001 -#define SA_NOCLDWAIT 0x00000002 -#define SA_SIGINFO 0x00000004 -#define SA_ONSTACK 0x08000000 -#define SA_RESTART 0x10000000 -#define SA_NODEFER 0x40000000 -#define SA_RESETHAND 0x80000000 - -#define SA_NOMASK SA_NODEFER -#define SA_ONESHOT SA_RESETHAND - -/* - * sigaltstack controls - */ -#define SS_ONSTACK 1 -#define SS_DISABLE 2 - -#define MINSIGSTKSZ 2048 -#define SIGSTKSZ 8192 - -#include - -#ifdef __KERNEL__ -struct old_sigaction { - __sighandler_t sa_handler; - old_sigset_t sa_mask; - unsigned long sa_flags; - __sigrestore_t sa_restorer; -}; - -struct sigaction { - __sighandler_t sa_handler; - unsigned long sa_flags; - __sigrestore_t sa_restorer; - sigset_t sa_mask; /* mask last for extensibility */ -}; - -struct k_sigaction { - struct sigaction sa; -}; -#else -/* Here we must cater to libcs that poke about in kernel headers. */ - -struct sigaction { - union { - __sighandler_t _sa_handler; - void (*_sa_sigaction)(int, struct siginfo *, void *); - } _u; - sigset_t sa_mask; - unsigned long sa_flags; - void (*sa_restorer)(void); -}; - -#define sa_handler _u._sa_handler -#define sa_sigaction _u._sa_sigaction - -#endif /* __KERNEL__ */ - -typedef struct sigaltstack { - void __user *ss_sp; - int ss_flags; - size_t ss_size; -} stack_t; - -#ifdef __KERNEL__ -#include - -#define __HAVE_ARCH_SIG_BITOPS - -static inline void sigaddset(sigset_t *set, int _sig) -{ - asm ("bfset %0{%1,#1}" - : "+od" (*set) - : "id" ((_sig - 1) ^ 31) - : "cc"); -} - -static inline void sigdelset(sigset_t *set, int _sig) -{ - asm ("bfclr %0{%1,#1}" - : "+od" (*set) - : "id" ((_sig - 1) ^ 31) - : "cc"); -} - -static inline int __const_sigismember(sigset_t *set, int _sig) -{ - unsigned long sig = _sig - 1; - return 1 & (set->sig[sig / _NSIG_BPW] >> (sig % _NSIG_BPW)); -} - -static inline int __gen_sigismember(sigset_t *set, int _sig) -{ - int ret; - asm ("bfextu %1{%2,#1},%0" - : "=d" (ret) - : "od" (*set), "id" ((_sig-1) ^ 31) - : "cc"); - return ret; -} - -#define sigismember(set,sig) \ - (__builtin_constant_p(sig) ? \ - __const_sigismember(set,sig) : \ - __gen_sigismember(set,sig)) - -static inline int sigfindinword(unsigned long word) -{ - asm ("bfffo %1{#0,#0},%0" - : "=d" (word) - : "d" (word & -word) - : "cc"); - return word ^ 31; -} - -struct pt_regs; -extern void ptrace_signal_deliver(struct pt_regs *regs, void *cookie); - -#endif /* __KERNEL__ */ - -#endif /* _M68K_SIGNAL_H */ diff --git a/arch/m68k/include/asm/signal_no.h b/arch/m68k/include/asm/signal_no.h deleted file mode 100644 index 216c08be54a..00000000000 --- a/arch/m68k/include/asm/signal_no.h +++ /dev/null @@ -1,159 +0,0 @@ -#ifndef _M68KNOMMU_SIGNAL_H -#define _M68KNOMMU_SIGNAL_H - -#include - -/* Avoid too many header ordering problems. */ -struct siginfo; - -#ifdef __KERNEL__ -/* Most things should be clean enough to redefine this at will, if care - is taken to make libc match. */ - -#define _NSIG 64 -#define _NSIG_BPW 32 -#define _NSIG_WORDS (_NSIG / _NSIG_BPW) - -typedef unsigned long old_sigset_t; /* at least 32 bits */ - -typedef struct { - unsigned long sig[_NSIG_WORDS]; -} sigset_t; - -#else -/* Here we must cater to libcs that poke about in kernel headers. */ - -#define NSIG 32 -typedef unsigned long sigset_t; - -#endif /* __KERNEL__ */ - -#define SIGHUP 1 -#define SIGINT 2 -#define SIGQUIT 3 -#define SIGILL 4 -#define SIGTRAP 5 -#define SIGABRT 6 -#define SIGIOT 6 -#define SIGBUS 7 -#define SIGFPE 8 -#define SIGKILL 9 -#define SIGUSR1 10 -#define SIGSEGV 11 -#define SIGUSR2 12 -#define SIGPIPE 13 -#define SIGALRM 14 -#define SIGTERM 15 -#define SIGSTKFLT 16 -#define SIGCHLD 17 -#define SIGCONT 18 -#define SIGSTOP 19 -#define SIGTSTP 20 -#define SIGTTIN 21 -#define SIGTTOU 22 -#define SIGURG 23 -#define SIGXCPU 24 -#define SIGXFSZ 25 -#define SIGVTALRM 26 -#define SIGPROF 27 -#define SIGWINCH 28 -#define SIGIO 29 -#define SIGPOLL SIGIO -/* -#define SIGLOST 29 -*/ -#define SIGPWR 30 -#define SIGSYS 31 -#define SIGUNUSED 31 - -/* These should not be considered constants from userland. */ -#define SIGRTMIN 32 -#define SIGRTMAX _NSIG - -/* - * SA_FLAGS values: - * - * SA_ONSTACK indicates that a registered stack_t will be used. - * SA_RESTART flag to get restarting signals (which were the default long ago) - * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. - * SA_RESETHAND clears the handler when the signal is delivered. - * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. - * SA_NODEFER prevents the current signal from being masked in the handler. - * - * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single - * Unix names RESETHAND and NODEFER respectively. - */ -#define SA_NOCLDSTOP 0x00000001 -#define SA_NOCLDWAIT 0x00000002 -#define SA_SIGINFO 0x00000004 -#define SA_ONSTACK 0x08000000 -#define SA_RESTART 0x10000000 -#define SA_NODEFER 0x40000000 -#define SA_RESETHAND 0x80000000 - -#define SA_NOMASK SA_NODEFER -#define SA_ONESHOT SA_RESETHAND - -/* - * sigaltstack controls - */ -#define SS_ONSTACK 1 -#define SS_DISABLE 2 - -#define MINSIGSTKSZ 2048 -#define SIGSTKSZ 8192 - -#include - -#ifdef __KERNEL__ -struct old_sigaction { - __sighandler_t sa_handler; - old_sigset_t sa_mask; - unsigned long sa_flags; - void (*sa_restorer)(void); -}; - -struct sigaction { - __sighandler_t sa_handler; - unsigned long sa_flags; - void (*sa_restorer)(void); - sigset_t sa_mask; /* mask last for extensibility */ -}; - -struct k_sigaction { - struct sigaction sa; -}; -#else -/* Here we must cater to libcs that poke about in kernel headers. */ - -struct sigaction { - union { - __sighandler_t _sa_handler; - void (*_sa_sigaction)(int, struct siginfo *, void *); - } _u; - sigset_t sa_mask; - unsigned long sa_flags; - void (*sa_restorer)(void); -}; - -#define sa_handler _u._sa_handler -#define sa_sigaction _u._sa_sigaction - -#endif /* __KERNEL__ */ - -typedef struct sigaltstack { - void *ss_sp; - int ss_flags; - size_t ss_size; -} stack_t; - -#ifdef __KERNEL__ - -#include -#undef __HAVE_ARCH_SIG_BITOPS - -#define ptrace_signal_deliver(regs, cookie) do { } while (0) - -#endif /* __KERNEL__ */ - -#endif /* _M68KNOMMU_SIGNAL_H */ -- GitLab From 9df3d51b59bd6aa48aee76e0cde4b89d854f3694 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 16 Mar 2009 22:12:28 +1000 Subject: [PATCH 3616/4982] m68k: use the MMU version of unistd.h for all m68k platforms The MMU version of unistd.h can be use on non-MMU platrorms as well. Without a single file "make headers_install" is broken for m68k (since each of the sub-varients of unistd.h are not installed). Signed-off-by: Greg Ungerer --- arch/m68k/include/asm/unistd.h | 377 +++++++++++++++++++++++++++++- arch/m68k/include/asm/unistd_mm.h | 372 ----------------------------- arch/m68k/include/asm/unistd_no.h | 372 ----------------------------- 3 files changed, 372 insertions(+), 749 deletions(-) delete mode 100644 arch/m68k/include/asm/unistd_mm.h delete mode 100644 arch/m68k/include/asm/unistd_no.h diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h index df1d9d4cb1f..3c19027331f 100644 --- a/arch/m68k/include/asm/unistd.h +++ b/arch/m68k/include/asm/unistd.h @@ -1,5 +1,372 @@ -#ifdef __uClinux__ -#include "unistd_no.h" -#else -#include "unistd_mm.h" -#endif +#ifndef _ASM_M68K_UNISTD_H_ +#define _ASM_M68K_UNISTD_H_ + +/* + * This file contains the system call numbers. + */ + +#define __NR_restart_syscall 0 +#define __NR_exit 1 +#define __NR_fork 2 +#define __NR_read 3 +#define __NR_write 4 +#define __NR_open 5 +#define __NR_close 6 +#define __NR_waitpid 7 +#define __NR_creat 8 +#define __NR_link 9 +#define __NR_unlink 10 +#define __NR_execve 11 +#define __NR_chdir 12 +#define __NR_time 13 +#define __NR_mknod 14 +#define __NR_chmod 15 +#define __NR_chown 16 +#define __NR_break 17 +#define __NR_oldstat 18 +#define __NR_lseek 19 +#define __NR_getpid 20 +#define __NR_mount 21 +#define __NR_umount 22 +#define __NR_setuid 23 +#define __NR_getuid 24 +#define __NR_stime 25 +#define __NR_ptrace 26 +#define __NR_alarm 27 +#define __NR_oldfstat 28 +#define __NR_pause 29 +#define __NR_utime 30 +#define __NR_stty 31 +#define __NR_gtty 32 +#define __NR_access 33 +#define __NR_nice 34 +#define __NR_ftime 35 +#define __NR_sync 36 +#define __NR_kill 37 +#define __NR_rename 38 +#define __NR_mkdir 39 +#define __NR_rmdir 40 +#define __NR_dup 41 +#define __NR_pipe 42 +#define __NR_times 43 +#define __NR_prof 44 +#define __NR_brk 45 +#define __NR_setgid 46 +#define __NR_getgid 47 +#define __NR_signal 48 +#define __NR_geteuid 49 +#define __NR_getegid 50 +#define __NR_acct 51 +#define __NR_umount2 52 +#define __NR_lock 53 +#define __NR_ioctl 54 +#define __NR_fcntl 55 +#define __NR_mpx 56 +#define __NR_setpgid 57 +#define __NR_ulimit 58 +#define __NR_oldolduname 59 +#define __NR_umask 60 +#define __NR_chroot 61 +#define __NR_ustat 62 +#define __NR_dup2 63 +#define __NR_getppid 64 +#define __NR_getpgrp 65 +#define __NR_setsid 66 +#define __NR_sigaction 67 +#define __NR_sgetmask 68 +#define __NR_ssetmask 69 +#define __NR_setreuid 70 +#define __NR_setregid 71 +#define __NR_sigsuspend 72 +#define __NR_sigpending 73 +#define __NR_sethostname 74 +#define __NR_setrlimit 75 +#define __NR_getrlimit 76 +#define __NR_getrusage 77 +#define __NR_gettimeofday 78 +#define __NR_settimeofday 79 +#define __NR_getgroups 80 +#define __NR_setgroups 81 +#define __NR_select 82 +#define __NR_symlink 83 +#define __NR_oldlstat 84 +#define __NR_readlink 85 +#define __NR_uselib 86 +#define __NR_swapon 87 +#define __NR_reboot 88 +#define __NR_readdir 89 +#define __NR_mmap 90 +#define __NR_munmap 91 +#define __NR_truncate 92 +#define __NR_ftruncate 93 +#define __NR_fchmod 94 +#define __NR_fchown 95 +#define __NR_getpriority 96 +#define __NR_setpriority 97 +#define __NR_profil 98 +#define __NR_statfs 99 +#define __NR_fstatfs 100 +#define __NR_ioperm 101 +#define __NR_socketcall 102 +#define __NR_syslog 103 +#define __NR_setitimer 104 +#define __NR_getitimer 105 +#define __NR_stat 106 +#define __NR_lstat 107 +#define __NR_fstat 108 +#define __NR_olduname 109 +#define __NR_iopl /* 110 */ not supported +#define __NR_vhangup 111 +#define __NR_idle /* 112 */ Obsolete +#define __NR_vm86 /* 113 */ not supported +#define __NR_wait4 114 +#define __NR_swapoff 115 +#define __NR_sysinfo 116 +#define __NR_ipc 117 +#define __NR_fsync 118 +#define __NR_sigreturn 119 +#define __NR_clone 120 +#define __NR_setdomainname 121 +#define __NR_uname 122 +#define __NR_cacheflush 123 +#define __NR_adjtimex 124 +#define __NR_mprotect 125 +#define __NR_sigprocmask 126 +#define __NR_create_module 127 +#define __NR_init_module 128 +#define __NR_delete_module 129 +#define __NR_get_kernel_syms 130 +#define __NR_quotactl 131 +#define __NR_getpgid 132 +#define __NR_fchdir 133 +#define __NR_bdflush 134 +#define __NR_sysfs 135 +#define __NR_personality 136 +#define __NR_afs_syscall 137 /* Syscall for Andrew File System */ +#define __NR_setfsuid 138 +#define __NR_setfsgid 139 +#define __NR__llseek 140 +#define __NR_getdents 141 +#define __NR__newselect 142 +#define __NR_flock 143 +#define __NR_msync 144 +#define __NR_readv 145 +#define __NR_writev 146 +#define __NR_getsid 147 +#define __NR_fdatasync 148 +#define __NR__sysctl 149 +#define __NR_mlock 150 +#define __NR_munlock 151 +#define __NR_mlockall 152 +#define __NR_munlockall 153 +#define __NR_sched_setparam 154 +#define __NR_sched_getparam 155 +#define __NR_sched_setscheduler 156 +#define __NR_sched_getscheduler 157 +#define __NR_sched_yield 158 +#define __NR_sched_get_priority_max 159 +#define __NR_sched_get_priority_min 160 +#define __NR_sched_rr_get_interval 161 +#define __NR_nanosleep 162 +#define __NR_mremap 163 +#define __NR_setresuid 164 +#define __NR_getresuid 165 +#define __NR_getpagesize 166 +#define __NR_query_module 167 +#define __NR_poll 168 +#define __NR_nfsservctl 169 +#define __NR_setresgid 170 +#define __NR_getresgid 171 +#define __NR_prctl 172 +#define __NR_rt_sigreturn 173 +#define __NR_rt_sigaction 174 +#define __NR_rt_sigprocmask 175 +#define __NR_rt_sigpending 176 +#define __NR_rt_sigtimedwait 177 +#define __NR_rt_sigqueueinfo 178 +#define __NR_rt_sigsuspend 179 +#define __NR_pread64 180 +#define __NR_pwrite64 181 +#define __NR_lchown 182 +#define __NR_getcwd 183 +#define __NR_capget 184 +#define __NR_capset 185 +#define __NR_sigaltstack 186 +#define __NR_sendfile 187 +#define __NR_getpmsg 188 /* some people actually want streams */ +#define __NR_putpmsg 189 /* some people actually want streams */ +#define __NR_vfork 190 +#define __NR_ugetrlimit 191 +#define __NR_mmap2 192 +#define __NR_truncate64 193 +#define __NR_ftruncate64 194 +#define __NR_stat64 195 +#define __NR_lstat64 196 +#define __NR_fstat64 197 +#define __NR_chown32 198 +#define __NR_getuid32 199 +#define __NR_getgid32 200 +#define __NR_geteuid32 201 +#define __NR_getegid32 202 +#define __NR_setreuid32 203 +#define __NR_setregid32 204 +#define __NR_getgroups32 205 +#define __NR_setgroups32 206 +#define __NR_fchown32 207 +#define __NR_setresuid32 208 +#define __NR_getresuid32 209 +#define __NR_setresgid32 210 +#define __NR_getresgid32 211 +#define __NR_lchown32 212 +#define __NR_setuid32 213 +#define __NR_setgid32 214 +#define __NR_setfsuid32 215 +#define __NR_setfsgid32 216 +#define __NR_pivot_root 217 +#define __NR_getdents64 220 +#define __NR_gettid 221 +#define __NR_tkill 222 +#define __NR_setxattr 223 +#define __NR_lsetxattr 224 +#define __NR_fsetxattr 225 +#define __NR_getxattr 226 +#define __NR_lgetxattr 227 +#define __NR_fgetxattr 228 +#define __NR_listxattr 229 +#define __NR_llistxattr 230 +#define __NR_flistxattr 231 +#define __NR_removexattr 232 +#define __NR_lremovexattr 233 +#define __NR_fremovexattr 234 +#define __NR_futex 235 +#define __NR_sendfile64 236 +#define __NR_mincore 237 +#define __NR_madvise 238 +#define __NR_fcntl64 239 +#define __NR_readahead 240 +#define __NR_io_setup 241 +#define __NR_io_destroy 242 +#define __NR_io_getevents 243 +#define __NR_io_submit 244 +#define __NR_io_cancel 245 +#define __NR_fadvise64 246 +#define __NR_exit_group 247 +#define __NR_lookup_dcookie 248 +#define __NR_epoll_create 249 +#define __NR_epoll_ctl 250 +#define __NR_epoll_wait 251 +#define __NR_remap_file_pages 252 +#define __NR_set_tid_address 253 +#define __NR_timer_create 254 +#define __NR_timer_settime 255 +#define __NR_timer_gettime 256 +#define __NR_timer_getoverrun 257 +#define __NR_timer_delete 258 +#define __NR_clock_settime 259 +#define __NR_clock_gettime 260 +#define __NR_clock_getres 261 +#define __NR_clock_nanosleep 262 +#define __NR_statfs64 263 +#define __NR_fstatfs64 264 +#define __NR_tgkill 265 +#define __NR_utimes 266 +#define __NR_fadvise64_64 267 +#define __NR_mbind 268 +#define __NR_get_mempolicy 269 +#define __NR_set_mempolicy 270 +#define __NR_mq_open 271 +#define __NR_mq_unlink 272 +#define __NR_mq_timedsend 273 +#define __NR_mq_timedreceive 274 +#define __NR_mq_notify 275 +#define __NR_mq_getsetattr 276 +#define __NR_waitid 277 +#define __NR_vserver 278 +#define __NR_add_key 279 +#define __NR_request_key 280 +#define __NR_keyctl 281 +#define __NR_ioprio_set 282 +#define __NR_ioprio_get 283 +#define __NR_inotify_init 284 +#define __NR_inotify_add_watch 285 +#define __NR_inotify_rm_watch 286 +#define __NR_migrate_pages 287 +#define __NR_openat 288 +#define __NR_mkdirat 289 +#define __NR_mknodat 290 +#define __NR_fchownat 291 +#define __NR_futimesat 292 +#define __NR_fstatat64 293 +#define __NR_unlinkat 294 +#define __NR_renameat 295 +#define __NR_linkat 296 +#define __NR_symlinkat 297 +#define __NR_readlinkat 298 +#define __NR_fchmodat 299 +#define __NR_faccessat 300 +#define __NR_pselect6 301 +#define __NR_ppoll 302 +#define __NR_unshare 303 +#define __NR_set_robust_list 304 +#define __NR_get_robust_list 305 +#define __NR_splice 306 +#define __NR_sync_file_range 307 +#define __NR_tee 308 +#define __NR_vmsplice 309 +#define __NR_move_pages 310 +#define __NR_sched_setaffinity 311 +#define __NR_sched_getaffinity 312 +#define __NR_kexec_load 313 +#define __NR_getcpu 314 +#define __NR_epoll_pwait 315 +#define __NR_utimensat 316 +#define __NR_signalfd 317 +#define __NR_timerfd_create 318 +#define __NR_eventfd 319 +#define __NR_fallocate 320 +#define __NR_timerfd_settime 321 +#define __NR_timerfd_gettime 322 +#define __NR_signalfd4 323 +#define __NR_eventfd2 324 +#define __NR_epoll_create1 325 +#define __NR_dup3 326 +#define __NR_pipe2 327 +#define __NR_inotify_init1 328 + +#ifdef __KERNEL__ + +#define NR_syscalls 329 + +#define __ARCH_WANT_IPC_PARSE_VERSION +#define __ARCH_WANT_OLD_READDIR +#define __ARCH_WANT_OLD_STAT +#define __ARCH_WANT_STAT64 +#define __ARCH_WANT_SYS_ALARM +#define __ARCH_WANT_SYS_GETHOSTNAME +#define __ARCH_WANT_SYS_PAUSE +#define __ARCH_WANT_SYS_SGETMASK +#define __ARCH_WANT_SYS_SIGNAL +#define __ARCH_WANT_SYS_TIME +#define __ARCH_WANT_SYS_UTIME +#define __ARCH_WANT_SYS_WAITPID +#define __ARCH_WANT_SYS_SOCKETCALL +#define __ARCH_WANT_SYS_FADVISE64 +#define __ARCH_WANT_SYS_GETPGRP +#define __ARCH_WANT_SYS_LLSEEK +#define __ARCH_WANT_SYS_NICE +#define __ARCH_WANT_SYS_OLD_GETRLIMIT +#define __ARCH_WANT_SYS_OLDUMOUNT +#define __ARCH_WANT_SYS_SIGPENDING +#define __ARCH_WANT_SYS_SIGPROCMASK +#define __ARCH_WANT_SYS_RT_SIGACTION + +/* + * "Conditional" syscalls + * + * What we want is __attribute__((weak,alias("sys_ni_syscall"))), + * but it doesn't work on all toolchains, so we just do it by hand + */ +#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") + +#endif /* __KERNEL__ */ +#endif /* _ASM_M68K_UNISTD_H_ */ diff --git a/arch/m68k/include/asm/unistd_mm.h b/arch/m68k/include/asm/unistd_mm.h deleted file mode 100644 index 3c19027331f..00000000000 --- a/arch/m68k/include/asm/unistd_mm.h +++ /dev/null @@ -1,372 +0,0 @@ -#ifndef _ASM_M68K_UNISTD_H_ -#define _ASM_M68K_UNISTD_H_ - -/* - * This file contains the system call numbers. - */ - -#define __NR_restart_syscall 0 -#define __NR_exit 1 -#define __NR_fork 2 -#define __NR_read 3 -#define __NR_write 4 -#define __NR_open 5 -#define __NR_close 6 -#define __NR_waitpid 7 -#define __NR_creat 8 -#define __NR_link 9 -#define __NR_unlink 10 -#define __NR_execve 11 -#define __NR_chdir 12 -#define __NR_time 13 -#define __NR_mknod 14 -#define __NR_chmod 15 -#define __NR_chown 16 -#define __NR_break 17 -#define __NR_oldstat 18 -#define __NR_lseek 19 -#define __NR_getpid 20 -#define __NR_mount 21 -#define __NR_umount 22 -#define __NR_setuid 23 -#define __NR_getuid 24 -#define __NR_stime 25 -#define __NR_ptrace 26 -#define __NR_alarm 27 -#define __NR_oldfstat 28 -#define __NR_pause 29 -#define __NR_utime 30 -#define __NR_stty 31 -#define __NR_gtty 32 -#define __NR_access 33 -#define __NR_nice 34 -#define __NR_ftime 35 -#define __NR_sync 36 -#define __NR_kill 37 -#define __NR_rename 38 -#define __NR_mkdir 39 -#define __NR_rmdir 40 -#define __NR_dup 41 -#define __NR_pipe 42 -#define __NR_times 43 -#define __NR_prof 44 -#define __NR_brk 45 -#define __NR_setgid 46 -#define __NR_getgid 47 -#define __NR_signal 48 -#define __NR_geteuid 49 -#define __NR_getegid 50 -#define __NR_acct 51 -#define __NR_umount2 52 -#define __NR_lock 53 -#define __NR_ioctl 54 -#define __NR_fcntl 55 -#define __NR_mpx 56 -#define __NR_setpgid 57 -#define __NR_ulimit 58 -#define __NR_oldolduname 59 -#define __NR_umask 60 -#define __NR_chroot 61 -#define __NR_ustat 62 -#define __NR_dup2 63 -#define __NR_getppid 64 -#define __NR_getpgrp 65 -#define __NR_setsid 66 -#define __NR_sigaction 67 -#define __NR_sgetmask 68 -#define __NR_ssetmask 69 -#define __NR_setreuid 70 -#define __NR_setregid 71 -#define __NR_sigsuspend 72 -#define __NR_sigpending 73 -#define __NR_sethostname 74 -#define __NR_setrlimit 75 -#define __NR_getrlimit 76 -#define __NR_getrusage 77 -#define __NR_gettimeofday 78 -#define __NR_settimeofday 79 -#define __NR_getgroups 80 -#define __NR_setgroups 81 -#define __NR_select 82 -#define __NR_symlink 83 -#define __NR_oldlstat 84 -#define __NR_readlink 85 -#define __NR_uselib 86 -#define __NR_swapon 87 -#define __NR_reboot 88 -#define __NR_readdir 89 -#define __NR_mmap 90 -#define __NR_munmap 91 -#define __NR_truncate 92 -#define __NR_ftruncate 93 -#define __NR_fchmod 94 -#define __NR_fchown 95 -#define __NR_getpriority 96 -#define __NR_setpriority 97 -#define __NR_profil 98 -#define __NR_statfs 99 -#define __NR_fstatfs 100 -#define __NR_ioperm 101 -#define __NR_socketcall 102 -#define __NR_syslog 103 -#define __NR_setitimer 104 -#define __NR_getitimer 105 -#define __NR_stat 106 -#define __NR_lstat 107 -#define __NR_fstat 108 -#define __NR_olduname 109 -#define __NR_iopl /* 110 */ not supported -#define __NR_vhangup 111 -#define __NR_idle /* 112 */ Obsolete -#define __NR_vm86 /* 113 */ not supported -#define __NR_wait4 114 -#define __NR_swapoff 115 -#define __NR_sysinfo 116 -#define __NR_ipc 117 -#define __NR_fsync 118 -#define __NR_sigreturn 119 -#define __NR_clone 120 -#define __NR_setdomainname 121 -#define __NR_uname 122 -#define __NR_cacheflush 123 -#define __NR_adjtimex 124 -#define __NR_mprotect 125 -#define __NR_sigprocmask 126 -#define __NR_create_module 127 -#define __NR_init_module 128 -#define __NR_delete_module 129 -#define __NR_get_kernel_syms 130 -#define __NR_quotactl 131 -#define __NR_getpgid 132 -#define __NR_fchdir 133 -#define __NR_bdflush 134 -#define __NR_sysfs 135 -#define __NR_personality 136 -#define __NR_afs_syscall 137 /* Syscall for Andrew File System */ -#define __NR_setfsuid 138 -#define __NR_setfsgid 139 -#define __NR__llseek 140 -#define __NR_getdents 141 -#define __NR__newselect 142 -#define __NR_flock 143 -#define __NR_msync 144 -#define __NR_readv 145 -#define __NR_writev 146 -#define __NR_getsid 147 -#define __NR_fdatasync 148 -#define __NR__sysctl 149 -#define __NR_mlock 150 -#define __NR_munlock 151 -#define __NR_mlockall 152 -#define __NR_munlockall 153 -#define __NR_sched_setparam 154 -#define __NR_sched_getparam 155 -#define __NR_sched_setscheduler 156 -#define __NR_sched_getscheduler 157 -#define __NR_sched_yield 158 -#define __NR_sched_get_priority_max 159 -#define __NR_sched_get_priority_min 160 -#define __NR_sched_rr_get_interval 161 -#define __NR_nanosleep 162 -#define __NR_mremap 163 -#define __NR_setresuid 164 -#define __NR_getresuid 165 -#define __NR_getpagesize 166 -#define __NR_query_module 167 -#define __NR_poll 168 -#define __NR_nfsservctl 169 -#define __NR_setresgid 170 -#define __NR_getresgid 171 -#define __NR_prctl 172 -#define __NR_rt_sigreturn 173 -#define __NR_rt_sigaction 174 -#define __NR_rt_sigprocmask 175 -#define __NR_rt_sigpending 176 -#define __NR_rt_sigtimedwait 177 -#define __NR_rt_sigqueueinfo 178 -#define __NR_rt_sigsuspend 179 -#define __NR_pread64 180 -#define __NR_pwrite64 181 -#define __NR_lchown 182 -#define __NR_getcwd 183 -#define __NR_capget 184 -#define __NR_capset 185 -#define __NR_sigaltstack 186 -#define __NR_sendfile 187 -#define __NR_getpmsg 188 /* some people actually want streams */ -#define __NR_putpmsg 189 /* some people actually want streams */ -#define __NR_vfork 190 -#define __NR_ugetrlimit 191 -#define __NR_mmap2 192 -#define __NR_truncate64 193 -#define __NR_ftruncate64 194 -#define __NR_stat64 195 -#define __NR_lstat64 196 -#define __NR_fstat64 197 -#define __NR_chown32 198 -#define __NR_getuid32 199 -#define __NR_getgid32 200 -#define __NR_geteuid32 201 -#define __NR_getegid32 202 -#define __NR_setreuid32 203 -#define __NR_setregid32 204 -#define __NR_getgroups32 205 -#define __NR_setgroups32 206 -#define __NR_fchown32 207 -#define __NR_setresuid32 208 -#define __NR_getresuid32 209 -#define __NR_setresgid32 210 -#define __NR_getresgid32 211 -#define __NR_lchown32 212 -#define __NR_setuid32 213 -#define __NR_setgid32 214 -#define __NR_setfsuid32 215 -#define __NR_setfsgid32 216 -#define __NR_pivot_root 217 -#define __NR_getdents64 220 -#define __NR_gettid 221 -#define __NR_tkill 222 -#define __NR_setxattr 223 -#define __NR_lsetxattr 224 -#define __NR_fsetxattr 225 -#define __NR_getxattr 226 -#define __NR_lgetxattr 227 -#define __NR_fgetxattr 228 -#define __NR_listxattr 229 -#define __NR_llistxattr 230 -#define __NR_flistxattr 231 -#define __NR_removexattr 232 -#define __NR_lremovexattr 233 -#define __NR_fremovexattr 234 -#define __NR_futex 235 -#define __NR_sendfile64 236 -#define __NR_mincore 237 -#define __NR_madvise 238 -#define __NR_fcntl64 239 -#define __NR_readahead 240 -#define __NR_io_setup 241 -#define __NR_io_destroy 242 -#define __NR_io_getevents 243 -#define __NR_io_submit 244 -#define __NR_io_cancel 245 -#define __NR_fadvise64 246 -#define __NR_exit_group 247 -#define __NR_lookup_dcookie 248 -#define __NR_epoll_create 249 -#define __NR_epoll_ctl 250 -#define __NR_epoll_wait 251 -#define __NR_remap_file_pages 252 -#define __NR_set_tid_address 253 -#define __NR_timer_create 254 -#define __NR_timer_settime 255 -#define __NR_timer_gettime 256 -#define __NR_timer_getoverrun 257 -#define __NR_timer_delete 258 -#define __NR_clock_settime 259 -#define __NR_clock_gettime 260 -#define __NR_clock_getres 261 -#define __NR_clock_nanosleep 262 -#define __NR_statfs64 263 -#define __NR_fstatfs64 264 -#define __NR_tgkill 265 -#define __NR_utimes 266 -#define __NR_fadvise64_64 267 -#define __NR_mbind 268 -#define __NR_get_mempolicy 269 -#define __NR_set_mempolicy 270 -#define __NR_mq_open 271 -#define __NR_mq_unlink 272 -#define __NR_mq_timedsend 273 -#define __NR_mq_timedreceive 274 -#define __NR_mq_notify 275 -#define __NR_mq_getsetattr 276 -#define __NR_waitid 277 -#define __NR_vserver 278 -#define __NR_add_key 279 -#define __NR_request_key 280 -#define __NR_keyctl 281 -#define __NR_ioprio_set 282 -#define __NR_ioprio_get 283 -#define __NR_inotify_init 284 -#define __NR_inotify_add_watch 285 -#define __NR_inotify_rm_watch 286 -#define __NR_migrate_pages 287 -#define __NR_openat 288 -#define __NR_mkdirat 289 -#define __NR_mknodat 290 -#define __NR_fchownat 291 -#define __NR_futimesat 292 -#define __NR_fstatat64 293 -#define __NR_unlinkat 294 -#define __NR_renameat 295 -#define __NR_linkat 296 -#define __NR_symlinkat 297 -#define __NR_readlinkat 298 -#define __NR_fchmodat 299 -#define __NR_faccessat 300 -#define __NR_pselect6 301 -#define __NR_ppoll 302 -#define __NR_unshare 303 -#define __NR_set_robust_list 304 -#define __NR_get_robust_list 305 -#define __NR_splice 306 -#define __NR_sync_file_range 307 -#define __NR_tee 308 -#define __NR_vmsplice 309 -#define __NR_move_pages 310 -#define __NR_sched_setaffinity 311 -#define __NR_sched_getaffinity 312 -#define __NR_kexec_load 313 -#define __NR_getcpu 314 -#define __NR_epoll_pwait 315 -#define __NR_utimensat 316 -#define __NR_signalfd 317 -#define __NR_timerfd_create 318 -#define __NR_eventfd 319 -#define __NR_fallocate 320 -#define __NR_timerfd_settime 321 -#define __NR_timerfd_gettime 322 -#define __NR_signalfd4 323 -#define __NR_eventfd2 324 -#define __NR_epoll_create1 325 -#define __NR_dup3 326 -#define __NR_pipe2 327 -#define __NR_inotify_init1 328 - -#ifdef __KERNEL__ - -#define NR_syscalls 329 - -#define __ARCH_WANT_IPC_PARSE_VERSION -#define __ARCH_WANT_OLD_READDIR -#define __ARCH_WANT_OLD_STAT -#define __ARCH_WANT_STAT64 -#define __ARCH_WANT_SYS_ALARM -#define __ARCH_WANT_SYS_GETHOSTNAME -#define __ARCH_WANT_SYS_PAUSE -#define __ARCH_WANT_SYS_SGETMASK -#define __ARCH_WANT_SYS_SIGNAL -#define __ARCH_WANT_SYS_TIME -#define __ARCH_WANT_SYS_UTIME -#define __ARCH_WANT_SYS_WAITPID -#define __ARCH_WANT_SYS_SOCKETCALL -#define __ARCH_WANT_SYS_FADVISE64 -#define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK -#define __ARCH_WANT_SYS_NICE -#define __ARCH_WANT_SYS_OLD_GETRLIMIT -#define __ARCH_WANT_SYS_OLDUMOUNT -#define __ARCH_WANT_SYS_SIGPENDING -#define __ARCH_WANT_SYS_SIGPROCMASK -#define __ARCH_WANT_SYS_RT_SIGACTION - -/* - * "Conditional" syscalls - * - * What we want is __attribute__((weak,alias("sys_ni_syscall"))), - * but it doesn't work on all toolchains, so we just do it by hand - */ -#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") - -#endif /* __KERNEL__ */ -#endif /* _ASM_M68K_UNISTD_H_ */ diff --git a/arch/m68k/include/asm/unistd_no.h b/arch/m68k/include/asm/unistd_no.h deleted file mode 100644 index b034a2f7b44..00000000000 --- a/arch/m68k/include/asm/unistd_no.h +++ /dev/null @@ -1,372 +0,0 @@ -#ifndef _ASM_M68K_UNISTD_H_ -#define _ASM_M68K_UNISTD_H_ - -/* - * This file contains the system call numbers. - */ - -#define __NR_restart_syscall 0 -#define __NR_exit 1 -#define __NR_fork 2 -#define __NR_read 3 -#define __NR_write 4 -#define __NR_open 5 -#define __NR_close 6 -#define __NR_waitpid 7 -#define __NR_creat 8 -#define __NR_link 9 -#define __NR_unlink 10 -#define __NR_execve 11 -#define __NR_chdir 12 -#define __NR_time 13 -#define __NR_mknod 14 -#define __NR_chmod 15 -#define __NR_chown 16 -#define __NR_break 17 -#define __NR_oldstat 18 -#define __NR_lseek 19 -#define __NR_getpid 20 -#define __NR_mount 21 -#define __NR_umount 22 -#define __NR_setuid 23 -#define __NR_getuid 24 -#define __NR_stime 25 -#define __NR_ptrace 26 -#define __NR_alarm 27 -#define __NR_oldfstat 28 -#define __NR_pause 29 -#define __NR_utime 30 -#define __NR_stty 31 -#define __NR_gtty 32 -#define __NR_access 33 -#define __NR_nice 34 -#define __NR_ftime 35 -#define __NR_sync 36 -#define __NR_kill 37 -#define __NR_rename 38 -#define __NR_mkdir 39 -#define __NR_rmdir 40 -#define __NR_dup 41 -#define __NR_pipe 42 -#define __NR_times 43 -#define __NR_prof 44 -#define __NR_brk 45 -#define __NR_setgid 46 -#define __NR_getgid 47 -#define __NR_signal 48 -#define __NR_geteuid 49 -#define __NR_getegid 50 -#define __NR_acct 51 -#define __NR_umount2 52 -#define __NR_lock 53 -#define __NR_ioctl 54 -#define __NR_fcntl 55 -#define __NR_mpx 56 -#define __NR_setpgid 57 -#define __NR_ulimit 58 -#define __NR_oldolduname 59 -#define __NR_umask 60 -#define __NR_chroot 61 -#define __NR_ustat 62 -#define __NR_dup2 63 -#define __NR_getppid 64 -#define __NR_getpgrp 65 -#define __NR_setsid 66 -#define __NR_sigaction 67 -#define __NR_sgetmask 68 -#define __NR_ssetmask 69 -#define __NR_setreuid 70 -#define __NR_setregid 71 -#define __NR_sigsuspend 72 -#define __NR_sigpending 73 -#define __NR_sethostname 74 -#define __NR_setrlimit 75 -#define __NR_getrlimit 76 -#define __NR_getrusage 77 -#define __NR_gettimeofday 78 -#define __NR_settimeofday 79 -#define __NR_getgroups 80 -#define __NR_setgroups 81 -#define __NR_select 82 -#define __NR_symlink 83 -#define __NR_oldlstat 84 -#define __NR_readlink 85 -#define __NR_uselib 86 -#define __NR_swapon 87 -#define __NR_reboot 88 -#define __NR_readdir 89 -#define __NR_mmap 90 -#define __NR_munmap 91 -#define __NR_truncate 92 -#define __NR_ftruncate 93 -#define __NR_fchmod 94 -#define __NR_fchown 95 -#define __NR_getpriority 96 -#define __NR_setpriority 97 -#define __NR_profil 98 -#define __NR_statfs 99 -#define __NR_fstatfs 100 -#define __NR_ioperm 101 -#define __NR_socketcall 102 -#define __NR_syslog 103 -#define __NR_setitimer 104 -#define __NR_getitimer 105 -#define __NR_stat 106 -#define __NR_lstat 107 -#define __NR_fstat 108 -#define __NR_olduname 109 -#define __NR_iopl /* 110 */ not supported -#define __NR_vhangup 111 -#define __NR_idle /* 112 */ Obsolete -#define __NR_vm86 /* 113 */ not supported -#define __NR_wait4 114 -#define __NR_swapoff 115 -#define __NR_sysinfo 116 -#define __NR_ipc 117 -#define __NR_fsync 118 -#define __NR_sigreturn 119 -#define __NR_clone 120 -#define __NR_setdomainname 121 -#define __NR_uname 122 -#define __NR_cacheflush 123 -#define __NR_adjtimex 124 -#define __NR_mprotect 125 -#define __NR_sigprocmask 126 -#define __NR_create_module 127 -#define __NR_init_module 128 -#define __NR_delete_module 129 -#define __NR_get_kernel_syms 130 -#define __NR_quotactl 131 -#define __NR_getpgid 132 -#define __NR_fchdir 133 -#define __NR_bdflush 134 -#define __NR_sysfs 135 -#define __NR_personality 136 -#define __NR_afs_syscall 137 /* Syscall for Andrew File System */ -#define __NR_setfsuid 138 -#define __NR_setfsgid 139 -#define __NR__llseek 140 -#define __NR_getdents 141 -#define __NR__newselect 142 -#define __NR_flock 143 -#define __NR_msync 144 -#define __NR_readv 145 -#define __NR_writev 146 -#define __NR_getsid 147 -#define __NR_fdatasync 148 -#define __NR__sysctl 149 -#define __NR_mlock 150 -#define __NR_munlock 151 -#define __NR_mlockall 152 -#define __NR_munlockall 153 -#define __NR_sched_setparam 154 -#define __NR_sched_getparam 155 -#define __NR_sched_setscheduler 156 -#define __NR_sched_getscheduler 157 -#define __NR_sched_yield 158 -#define __NR_sched_get_priority_max 159 -#define __NR_sched_get_priority_min 160 -#define __NR_sched_rr_get_interval 161 -#define __NR_nanosleep 162 -#define __NR_mremap 163 -#define __NR_setresuid 164 -#define __NR_getresuid 165 -#define __NR_getpagesize 166 -#define __NR_query_module 167 -#define __NR_poll 168 -#define __NR_nfsservctl 169 -#define __NR_setresgid 170 -#define __NR_getresgid 171 -#define __NR_prctl 172 -#define __NR_rt_sigreturn 173 -#define __NR_rt_sigaction 174 -#define __NR_rt_sigprocmask 175 -#define __NR_rt_sigpending 176 -#define __NR_rt_sigtimedwait 177 -#define __NR_rt_sigqueueinfo 178 -#define __NR_rt_sigsuspend 179 -#define __NR_pread64 180 -#define __NR_pwrite64 181 -#define __NR_lchown 182 -#define __NR_getcwd 183 -#define __NR_capget 184 -#define __NR_capset 185 -#define __NR_sigaltstack 186 -#define __NR_sendfile 187 -#define __NR_getpmsg 188 /* some people actually want streams */ -#define __NR_putpmsg 189 /* some people actually want streams */ -#define __NR_vfork 190 -#define __NR_ugetrlimit 191 -#define __NR_mmap2 192 -#define __NR_truncate64 193 -#define __NR_ftruncate64 194 -#define __NR_stat64 195 -#define __NR_lstat64 196 -#define __NR_fstat64 197 -#define __NR_chown32 198 -#define __NR_getuid32 199 -#define __NR_getgid32 200 -#define __NR_geteuid32 201 -#define __NR_getegid32 202 -#define __NR_setreuid32 203 -#define __NR_setregid32 204 -#define __NR_getgroups32 205 -#define __NR_setgroups32 206 -#define __NR_fchown32 207 -#define __NR_setresuid32 208 -#define __NR_getresuid32 209 -#define __NR_setresgid32 210 -#define __NR_getresgid32 211 -#define __NR_lchown32 212 -#define __NR_setuid32 213 -#define __NR_setgid32 214 -#define __NR_setfsuid32 215 -#define __NR_setfsgid32 216 -#define __NR_pivot_root 217 -#define __NR_getdents64 220 -#define __NR_gettid 221 -#define __NR_tkill 222 -#define __NR_setxattr 223 -#define __NR_lsetxattr 224 -#define __NR_fsetxattr 225 -#define __NR_getxattr 226 -#define __NR_lgetxattr 227 -#define __NR_fgetxattr 228 -#define __NR_listxattr 229 -#define __NR_llistxattr 230 -#define __NR_flistxattr 231 -#define __NR_removexattr 232 -#define __NR_lremovexattr 233 -#define __NR_fremovexattr 234 -#define __NR_futex 235 -#define __NR_sendfile64 236 -#define __NR_mincore 237 -#define __NR_madvise 238 -#define __NR_fcntl64 239 -#define __NR_readahead 240 -#define __NR_io_setup 241 -#define __NR_io_destroy 242 -#define __NR_io_getevents 243 -#define __NR_io_submit 244 -#define __NR_io_cancel 245 -#define __NR_fadvise64 246 -#define __NR_exit_group 247 -#define __NR_lookup_dcookie 248 -#define __NR_epoll_create 249 -#define __NR_epoll_ctl 250 -#define __NR_epoll_wait 251 -#define __NR_remap_file_pages 252 -#define __NR_set_tid_address 253 -#define __NR_timer_create 254 -#define __NR_timer_settime 255 -#define __NR_timer_gettime 256 -#define __NR_timer_getoverrun 257 -#define __NR_timer_delete 258 -#define __NR_clock_settime 259 -#define __NR_clock_gettime 260 -#define __NR_clock_getres 261 -#define __NR_clock_nanosleep 262 -#define __NR_statfs64 263 -#define __NR_fstatfs64 264 -#define __NR_tgkill 265 -#define __NR_utimes 266 -#define __NR_fadvise64_64 267 -#define __NR_mbind 268 -#define __NR_get_mempolicy 269 -#define __NR_set_mempolicy 270 -#define __NR_mq_open 271 -#define __NR_mq_unlink 272 -#define __NR_mq_timedsend 273 -#define __NR_mq_timedreceive 274 -#define __NR_mq_notify 275 -#define __NR_mq_getsetattr 276 -#define __NR_waitid 277 -#define __NR_vserver 278 -#define __NR_add_key 279 -#define __NR_request_key 280 -#define __NR_keyctl 281 -#define __NR_ioprio_set 282 -#define __NR_ioprio_get 283 -#define __NR_inotify_init 284 -#define __NR_inotify_add_watch 285 -#define __NR_inotify_rm_watch 286 -#define __NR_migrate_pages 287 -#define __NR_openat 288 -#define __NR_mkdirat 289 -#define __NR_mknodat 290 -#define __NR_fchownat 291 -#define __NR_futimesat 292 -#define __NR_fstatat64 293 -#define __NR_unlinkat 294 -#define __NR_renameat 295 -#define __NR_linkat 296 -#define __NR_symlinkat 297 -#define __NR_readlinkat 298 -#define __NR_fchmodat 299 -#define __NR_faccessat 300 -#define __NR_pselect6 301 -#define __NR_ppoll 302 -#define __NR_unshare 303 -#define __NR_set_robust_list 304 -#define __NR_get_robust_list 305 -#define __NR_splice 306 -#define __NR_sync_file_range 307 -#define __NR_tee 308 -#define __NR_vmsplice 309 -#define __NR_move_pages 310 -#define __NR_sched_setaffinity 311 -#define __NR_sched_getaffinity 312 -#define __NR_kexec_load 313 -#define __NR_getcpu 314 -#define __NR_epoll_pwait 315 -#define __NR_utimensat 316 -#define __NR_signalfd 317 -#define __NR_timerfd_create 318 -#define __NR_eventfd 319 -#define __NR_fallocate 320 -#define __NR_timerfd_settime 321 -#define __NR_timerfd_gettime 322 -#define __NR_signalfd4 323 -#define __NR_eventfd2 324 -#define __NR_epoll_create1 325 -#define __NR_dup3 326 -#define __NR_pipe2 327 -#define __NR_inotify_init1 328 - -#ifdef __KERNEL__ - -#define NR_syscalls 329 - -#define __ARCH_WANT_IPC_PARSE_VERSION -#define __ARCH_WANT_OLD_READDIR -#define __ARCH_WANT_OLD_STAT -#define __ARCH_WANT_STAT64 -#define __ARCH_WANT_SYS_ALARM -#define __ARCH_WANT_SYS_GETHOSTNAME -#define __ARCH_WANT_SYS_PAUSE -#define __ARCH_WANT_SYS_SGETMASK -#define __ARCH_WANT_SYS_SIGNAL -#define __ARCH_WANT_SYS_TIME -#define __ARCH_WANT_SYS_UTIME -#define __ARCH_WANT_SYS_WAITPID -#define __ARCH_WANT_SYS_SOCKETCALL -#define __ARCH_WANT_SYS_FADVISE64 -#define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK -#define __ARCH_WANT_SYS_NICE -#define __ARCH_WANT_SYS_OLD_GETRLIMIT -#define __ARCH_WANT_SYS_OLDUMOUNT -#define __ARCH_WANT_SYS_SIGPENDING -#define __ARCH_WANT_SYS_SIGPROCMASK -#define __ARCH_WANT_SYS_RT_SIGACTION - -/* - * "Conditional" syscalls - * - * What we want is __attribute__((weak,alias("sys_ni_syscall"))), - * but it doesn't work on all toolchains, so we just do it by hand - */ -#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") - -#endif /* __KERNEL__ */ -#endif /* _ASM_M68K_UNISTD_H_ */ -- GitLab From 7a2cf4af1554d891b440cc3a649d01ed222206c3 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Tue, 17 Mar 2009 08:47:11 +1000 Subject: [PATCH 3617/4982] m68k: merge the non-MMU and MMU versions of siginfo.h It is trivial to merge the non-MMU and MMU versions of siginfo.h. Without a single file "make headers_install" is broken for m68k (since each of the sub-varients of siginfo.h are not installed). Signed-off-by: Greg Ungerer --- arch/m68k/include/asm/siginfo.h | 98 +++++++++++++++++++++++++++++- arch/m68k/include/asm/siginfo_mm.h | 92 ---------------------------- arch/m68k/include/asm/siginfo_no.h | 6 -- 3 files changed, 95 insertions(+), 101 deletions(-) delete mode 100644 arch/m68k/include/asm/siginfo_mm.h delete mode 100644 arch/m68k/include/asm/siginfo_no.h diff --git a/arch/m68k/include/asm/siginfo.h b/arch/m68k/include/asm/siginfo.h index 61219d7affc..ca7dde8fd22 100644 --- a/arch/m68k/include/asm/siginfo.h +++ b/arch/m68k/include/asm/siginfo.h @@ -1,5 +1,97 @@ -#ifdef __uClinux__ -#include "siginfo_no.h" +#ifndef _M68K_SIGINFO_H +#define _M68K_SIGINFO_H + +#ifndef __uClinux__ +#define HAVE_ARCH_SIGINFO_T +#define HAVE_ARCH_COPY_SIGINFO +#endif + +#include + +#ifndef __uClinux__ + +typedef struct siginfo { + int si_signo; + int si_errno; + int si_code; + + union { + int _pad[SI_PAD_SIZE]; + + /* kill() */ + struct { + __kernel_pid_t _pid; /* sender's pid */ + __kernel_uid_t _uid; /* backwards compatibility */ + __kernel_uid32_t _uid32; /* sender's uid */ + } _kill; + + /* POSIX.1b timers */ + struct { + timer_t _tid; /* timer id */ + int _overrun; /* overrun count */ + char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)]; + sigval_t _sigval; /* same as below */ + int _sys_private; /* not to be passed to user */ + } _timer; + + /* POSIX.1b signals */ + struct { + __kernel_pid_t _pid; /* sender's pid */ + __kernel_uid_t _uid; /* backwards compatibility */ + sigval_t _sigval; + __kernel_uid32_t _uid32; /* sender's uid */ + } _rt; + + /* SIGCHLD */ + struct { + __kernel_pid_t _pid; /* which child */ + __kernel_uid_t _uid; /* backwards compatibility */ + int _status; /* exit code */ + clock_t _utime; + clock_t _stime; + __kernel_uid32_t _uid32; /* sender's uid */ + } _sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ + struct { + void *_addr; /* faulting insn/memory ref. */ + } _sigfault; + + /* SIGPOLL */ + struct { + int _band; /* POLL_IN, POLL_OUT, POLL_MSG */ + int _fd; + } _sigpoll; + } _sifields; +} siginfo_t; + +#define UID16_SIGINFO_COMPAT_NEEDED + +/* + * How these fields are to be accessed. + */ +#undef si_uid +#ifdef __KERNEL__ +#define si_uid _sifields._kill._uid32 +#define si_uid16 _sifields._kill._uid #else -#include "siginfo_mm.h" +#define si_uid _sifields._kill._uid +#endif + +#ifdef __KERNEL__ + +#include + +static inline void copy_siginfo(struct siginfo *to, struct siginfo *from) +{ + if (from->si_code < 0) + memcpy(to, from, sizeof(*to)); + else + /* _sigchld is currently the largest know union member */ + memcpy(to, from, 3*sizeof(int) + sizeof(from->_sifields._sigchld)); +} + +#endif /* __KERNEL__ */ +#endif /* !__uClinux__ */ + #endif diff --git a/arch/m68k/include/asm/siginfo_mm.h b/arch/m68k/include/asm/siginfo_mm.h deleted file mode 100644 index 05a8d6d90b5..00000000000 --- a/arch/m68k/include/asm/siginfo_mm.h +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef _M68K_SIGINFO_H -#define _M68K_SIGINFO_H - -#define HAVE_ARCH_SIGINFO_T -#define HAVE_ARCH_COPY_SIGINFO - -#include - -typedef struct siginfo { - int si_signo; - int si_errno; - int si_code; - - union { - int _pad[SI_PAD_SIZE]; - - /* kill() */ - struct { - __kernel_pid_t _pid; /* sender's pid */ - __kernel_uid_t _uid; /* backwards compatibility */ - __kernel_uid32_t _uid32; /* sender's uid */ - } _kill; - - /* POSIX.1b timers */ - struct { - timer_t _tid; /* timer id */ - int _overrun; /* overrun count */ - char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)]; - sigval_t _sigval; /* same as below */ - int _sys_private; /* not to be passed to user */ - } _timer; - - /* POSIX.1b signals */ - struct { - __kernel_pid_t _pid; /* sender's pid */ - __kernel_uid_t _uid; /* backwards compatibility */ - sigval_t _sigval; - __kernel_uid32_t _uid32; /* sender's uid */ - } _rt; - - /* SIGCHLD */ - struct { - __kernel_pid_t _pid; /* which child */ - __kernel_uid_t _uid; /* backwards compatibility */ - int _status; /* exit code */ - clock_t _utime; - clock_t _stime; - __kernel_uid32_t _uid32; /* sender's uid */ - } _sigchld; - - /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ - struct { - void *_addr; /* faulting insn/memory ref. */ - } _sigfault; - - /* SIGPOLL */ - struct { - int _band; /* POLL_IN, POLL_OUT, POLL_MSG */ - int _fd; - } _sigpoll; - } _sifields; -} siginfo_t; - -#define UID16_SIGINFO_COMPAT_NEEDED - -/* - * How these fields are to be accessed. - */ -#undef si_uid -#ifdef __KERNEL__ -#define si_uid _sifields._kill._uid32 -#define si_uid16 _sifields._kill._uid -#else -#define si_uid _sifields._kill._uid -#endif - -#ifdef __KERNEL__ - -#include - -static inline void copy_siginfo(struct siginfo *to, struct siginfo *from) -{ - if (from->si_code < 0) - memcpy(to, from, sizeof(*to)); - else - /* _sigchld is currently the largest know union member */ - memcpy(to, from, 3*sizeof(int) + sizeof(from->_sifields._sigchld)); -} - -#endif /* __KERNEL__ */ - -#endif diff --git a/arch/m68k/include/asm/siginfo_no.h b/arch/m68k/include/asm/siginfo_no.h deleted file mode 100644 index b18e5f4064a..00000000000 --- a/arch/m68k/include/asm/siginfo_no.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _M68KNOMMU_SIGINFO_H -#define _M68KNOMMU_SIGINFO_H - -#include - -#endif -- GitLab From da62e71d13ad0b76011491e36cb58999c464516a Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 17 Mar 2009 09:30:36 +0900 Subject: [PATCH 3618/4982] sh: dma: Make PVR2 DMA configurable. With arch/sh/drivers/dma/ always being built, the Dreamcast DMA engines are being unconditionally built in, regardless of whether the DMA API is enabled or not. This is a regression from previous behaviour, but there is not much advantage in building them all in unconditionally regardless. Add a new config option to make it optional, and update the only user of it to reflect that. Signed-off-by: Paul Mundt --- arch/sh/drivers/dma/Kconfig | 13 +++++++++++++ arch/sh/drivers/dma/Makefile | 3 ++- drivers/video/pvr2fb.c | 16 ++++++++-------- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/arch/sh/drivers/dma/Kconfig b/arch/sh/drivers/dma/Kconfig index 32bb8fa605c..ae26610837b 100644 --- a/arch/sh/drivers/dma/Kconfig +++ b/arch/sh/drivers/dma/Kconfig @@ -54,4 +54,17 @@ config SH_DMABRG of the SH7760. Say Y if you want to use Audio/USB DMA on your SH7760 board. +config PVR2_DMA + tristate "PowerVR 2 DMAC support" + depends on SH_DREAMCAST && SH_DMA + help + Selecting this will enable support for the PVR2 DMA controller. + As this chains off of the on-chip DMAC, that must also be + enabled by default. + + This is primarily used by the pvr2fb framebuffer driver for + certain optimizations, but is not necessary for functionality. + + If in doubt, say N. + endmenu diff --git a/arch/sh/drivers/dma/Makefile b/arch/sh/drivers/dma/Makefile index ab956adacb4..cff52cb6ac7 100644 --- a/arch/sh/drivers/dma/Makefile +++ b/arch/sh/drivers/dma/Makefile @@ -4,5 +4,6 @@ obj-$(CONFIG_SH_DMA_API) += dma-api.o dma-sysfs.o obj-$(CONFIG_SH_DMA) += dma-sh.o -obj-$(CONFIG_SH_DREAMCAST) += dma-pvr2.o dma-g2.o +obj-$(CONFIG_SH_DREAMCAST) += dma-g2.o +obj-$(CONFIG_PVR2_DMA) += dma-pvr2.o obj-$(CONFIG_SH_DMABRG) += dmabrg.o diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c index 0a0fd48a856..53f8f1100e8 100644 --- a/drivers/video/pvr2fb.c +++ b/drivers/video/pvr2fb.c @@ -61,7 +61,7 @@ #include #endif -#ifdef CONFIG_SH_DMA +#ifdef CONFIG_PVR2_DMA #include #include #include @@ -188,7 +188,7 @@ static unsigned int is_blanked = 0; /* Is the screen blanked? */ static unsigned long pvr2fb_map; #endif -#ifdef CONFIG_SH_DMA +#ifdef CONFIG_PVR2_DMA static unsigned int shdma = PVR2_CASCADE_CHAN; static unsigned int pvr2dma = ONCHIP_NR_DMA_CHANNELS; #endif @@ -207,7 +207,7 @@ static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id); static int pvr2_init_cable(void); static int pvr2_get_param(const struct pvr2_params *p, const char *s, int val, int size); -#ifdef CONFIG_SH_DMA +#ifdef CONFIG_PVR2_DMA static ssize_t pvr2fb_write(struct fb_info *info, const char *buf, size_t count, loff_t *ppos); #endif @@ -218,7 +218,7 @@ static struct fb_ops pvr2fb_ops = { .fb_blank = pvr2fb_blank, .fb_check_var = pvr2fb_check_var, .fb_set_par = pvr2fb_set_par, -#ifdef CONFIG_SH_DMA +#ifdef CONFIG_PVR2_DMA .fb_write = pvr2fb_write, #endif .fb_fillrect = cfb_fillrect, @@ -671,7 +671,7 @@ static int pvr2_init_cable(void) return cable_type; } -#ifdef CONFIG_SH_DMA +#ifdef CONFIG_PVR2_DMA static ssize_t pvr2fb_write(struct fb_info *info, const char *buf, size_t count, loff_t *ppos) { @@ -743,7 +743,7 @@ out_unmap: return ret; } -#endif /* CONFIG_SH_DMA */ +#endif /* CONFIG_PVR2_DMA */ /** * pvr2fb_common_init @@ -893,7 +893,7 @@ static int __init pvr2fb_dc_init(void) return -EBUSY; } -#ifdef CONFIG_SH_DMA +#ifdef CONFIG_PVR2_DMA if (request_dma(pvr2dma, "pvr2") != 0) { free_irq(HW_EVENT_VSYNC, 0); return -EBUSY; @@ -915,7 +915,7 @@ static void __exit pvr2fb_dc_exit(void) } free_irq(HW_EVENT_VSYNC, 0); -#ifdef CONFIG_SH_DMA +#ifdef CONFIG_PVR2_DMA free_dma(pvr2dma); #endif } -- GitLab From d33a1976fbee1ee321d6f014333d8f03a39d526c Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Mon, 16 Mar 2009 23:25:40 -0400 Subject: [PATCH 3619/4982] ext4: fix bb_prealloc_list corruption due to wrong group locking This is for Red Hat bug 490026: EXT4 panic, list corruption in ext4_mb_new_inode_pa ext4_lock_group(sb, group) is supposed to protect this list for each group, and a common code flow to remove an album is like this: ext4_get_group_no_and_offset(sb, pa->pa_pstart, &grp, NULL); ext4_lock_group(sb, grp); list_del(&pa->pa_group_list); ext4_unlock_group(sb, grp); so it's critical that we get the right group number back for this prealloc context, to lock the right group (the one associated with this pa) and prevent concurrent list manipulation. however, ext4_mb_put_pa() passes in (pa->pa_pstart - 1) with a comment, "-1 is to protect from crossing allocation group". This makes sense for the group_pa, where pa_pstart is advanced by the length which has been used (in ext4_mb_release_context()), and when the entire length has been used, pa_pstart has been advanced to the first block of the next group. However, for inode_pa, pa_pstart is never advanced; it's just set once to the first block in the group and not moved after that. So in this case, if we subtract one in ext4_mb_put_pa(), we are actually locking the *previous* group, and opening the race with the other threads which do not subtract off the extra block. Signed-off-by: Eric Sandeen Signed-off-by: "Theodore Ts'o" --- fs/ext4/mballoc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 41f4348b62f..9f61e62f435 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -3589,6 +3589,7 @@ static void ext4_mb_put_pa(struct ext4_allocation_context *ac, struct super_block *sb, struct ext4_prealloc_space *pa) { ext4_group_t grp; + ext4_fsblk_t grp_blk; if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0) return; @@ -3603,8 +3604,12 @@ static void ext4_mb_put_pa(struct ext4_allocation_context *ac, pa->pa_deleted = 1; spin_unlock(&pa->pa_lock); - /* -1 is to protect from crossing allocation group */ - ext4_get_group_no_and_offset(sb, pa->pa_pstart - 1, &grp, NULL); + grp_blk = pa->pa_pstart; + /* If linear, pa_pstart may be in the next group when pa is used up */ + if (pa->pa_linear) + grp_blk--; + + ext4_get_group_no_and_offset(sb, grp_blk, &grp, NULL); /* * possible race: -- GitLab From 40f49e7ed77f1b753a7243c0137e4767a50ea8bd Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 17 Mar 2009 12:47:56 +0900 Subject: [PATCH 3620/4982] sh: dma: Make G2 DMA configurable. Follow the PVR2 DMAC change for G2 DMA. Signed-off-by: Paul Mundt --- arch/sh/drivers/dma/Kconfig | 11 +++++++++++ arch/sh/drivers/dma/Makefile | 2 +- sound/sh/Kconfig | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/sh/drivers/dma/Kconfig b/arch/sh/drivers/dma/Kconfig index ae26610837b..f13a05285a9 100644 --- a/arch/sh/drivers/dma/Kconfig +++ b/arch/sh/drivers/dma/Kconfig @@ -67,4 +67,15 @@ config PVR2_DMA If in doubt, say N. +config G2_DMA + tristate "G2 Bus DMA support" + depends on SH_DREAMCAST + select SH_DMA_API + help + This enables support for the DMA controller for the Dreamcast's + G2 bus. Drivers that want this will generally enable this on + their own. + + If in doubt, say N. + endmenu diff --git a/arch/sh/drivers/dma/Makefile b/arch/sh/drivers/dma/Makefile index cff52cb6ac7..c6068137b46 100644 --- a/arch/sh/drivers/dma/Makefile +++ b/arch/sh/drivers/dma/Makefile @@ -4,6 +4,6 @@ obj-$(CONFIG_SH_DMA_API) += dma-api.o dma-sysfs.o obj-$(CONFIG_SH_DMA) += dma-sh.o -obj-$(CONFIG_SH_DREAMCAST) += dma-g2.o obj-$(CONFIG_PVR2_DMA) += dma-pvr2.o +obj-$(CONFIG_G2_DMA) += dma-g2.o obj-$(CONFIG_SH_DMABRG) += dmabrg.o diff --git a/sound/sh/Kconfig b/sound/sh/Kconfig index cfc14398580..aed0f90c391 100644 --- a/sound/sh/Kconfig +++ b/sound/sh/Kconfig @@ -15,6 +15,7 @@ config SND_AICA tristate "Dreamcast Yamaha AICA sound" depends on SH_DREAMCAST select SND_PCM + select G2_DMA help ALSA Sound driver for the SEGA Dreamcast console. -- GitLab From 32910e2c52cae552f2651c5360bae8033adb8aac Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Tue, 17 Mar 2009 05:54:37 +0000 Subject: [PATCH 3621/4982] sh: espt-giga board support This adds support for the ESPT-Giga (Ethernet Serial Parallel Translator) SH7763-based reference board. Board support is relatively sparse, presently supporting serial, gigabit ethernet, USB host, and MTD. More information (in Japanese) available at: http://www.cente.jp/product/cente_hard/ESPT-Giga.html Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: Paul Mundt --- arch/sh/boards/Kconfig | 7 + arch/sh/boards/Makefile | 1 + arch/sh/boards/board-espt.c | 102 +++ arch/sh/configs/espt_defconfig | 1190 ++++++++++++++++++++++++++++++++ arch/sh/tools/mach-types | 1 + 5 files changed, 1301 insertions(+) create mode 100644 arch/sh/boards/board-espt.c create mode 100644 arch/sh/configs/espt_defconfig diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig index bd3569a9934..48c043bf45c 100644 --- a/arch/sh/boards/Kconfig +++ b/arch/sh/boards/Kconfig @@ -190,6 +190,13 @@ config SH_SH7763RDP Select SH7763RDP if configuring for a Renesas SH7763 evaluation board. +config SH_ESPT + bool "ESPT" + depends on CPU_SUBTYPE_SH7763 + help + Select ESPT if configuring for a Renesas SH7763 + with gigabit ether evaluation board. + config SH_EDOSK7705 bool "EDOSK7705" depends on CPU_SUBTYPE_SH7705 diff --git a/arch/sh/boards/Makefile b/arch/sh/boards/Makefile index 6f101a8161f..d0daebce8b3 100644 --- a/arch/sh/boards/Makefile +++ b/arch/sh/boards/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_SH_SH7785LCR) += board-sh7785lcr.o obj-$(CONFIG_SH_URQUELL) += board-urquell.o obj-$(CONFIG_SH_SHMIN) += board-shmin.o obj-$(CONFIG_SH_EDOSK7760) += board-edosk7760.o +obj-$(CONFIG_SH_ESPT) += board-espt.o diff --git a/arch/sh/boards/board-espt.c b/arch/sh/boards/board-espt.c new file mode 100644 index 00000000000..d5ce5e18eb3 --- /dev/null +++ b/arch/sh/boards/board-espt.c @@ -0,0 +1,102 @@ +/* + * Data Technology Inc. ESPT-GIGA board suport + * + * Copyright (C) 2008, 2009 Renesas Solutions Corp. + * Copyright (C) 2008, 2009 Nobuhiro Iwamatsu + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* NOR Flash */ +static struct mtd_partition espt_nor_flash_partitions[] = { + { + .name = "U-Boot", + .offset = 0, + .size = (2 * SZ_128K), + .mask_flags = MTD_WRITEABLE, /* Read-only */ + }, { + .name = "Linux-Kernel", + .offset = MTDPART_OFS_APPEND, + .size = (20 * SZ_128K), + }, { + .name = "Root Filesystem", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct physmap_flash_data espt_nor_flash_data = { + .width = 2, + .parts = espt_nor_flash_partitions, + .nr_parts = ARRAY_SIZE(espt_nor_flash_partitions), +}; + +static struct resource espt_nor_flash_resources[] = { + [0] = { + .name = "NOR Flash", + .start = 0, + .end = SZ_8M - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device espt_nor_flash_device = { + .name = "physmap-flash", + .resource = espt_nor_flash_resources, + .num_resources = ARRAY_SIZE(espt_nor_flash_resources), + .dev = { + .platform_data = &espt_nor_flash_data, + }, +}; + +/* SH-Ether */ +static struct resource sh_eth_resources[] = { + { + .start = 0xFEE00800, /* use eth1 */ + .end = 0xFEE00F7C - 1, + .flags = IORESOURCE_MEM, + }, { + .start = 57, /* irq number */ + .flags = IORESOURCE_IRQ, + }, +}; + +static struct sh_eth_plat_data sh7763_eth_pdata = { + .phy = 0, + .edmac_endian = EDMAC_LITTLE_ENDIAN, +}; + +static struct platform_device espt_eth_device = { + .name = "sh-eth", + .resource = sh_eth_resources, + .num_resources = ARRAY_SIZE(sh_eth_resources), + .dev = { + .platform_data = &sh7763_eth_pdata, + }, +}; + +static struct platform_device *espt_devices[] __initdata = { + &espt_nor_flash_device, + &espt_eth_device, +}; + +static int __init espt_devices_setup(void) +{ + return platform_add_devices(espt_devices, + ARRAY_SIZE(espt_devices)); +} +device_initcall(espt_devices_setup); + +static struct sh_machine_vector mv_espt __initmv = { + .mv_name = "ESPT-GIGA", +}; diff --git a/arch/sh/configs/espt_defconfig b/arch/sh/configs/espt_defconfig new file mode 100644 index 00000000000..873ec42c6e6 --- /dev/null +++ b/arch/sh/configs/espt_defconfig @@ -0,0 +1,1190 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.29-rc7 +# Tue Mar 17 13:25:58 2009 +# +CONFIG_SUPERH=y +CONFIG_SUPERH32=y +CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig" +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_GENERIC_IRQ_PROBE=y +# CONFIG_GENERIC_GPIO is not set +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +# CONFIG_ARCH_SUSPEND_POSSIBLE is not set +# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_NO_VIRT_TO_BUS=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set +# CONFIG_CGROUPS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +CONFIG_UTS_NS=y +CONFIG_IPC_NS=y +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_NET_NS is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +CONFIG_PROFILING=y +CONFIG_TRACEPOINTS=y +# CONFIG_MARKERS is not set +CONFIG_OPROFILE=y +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_IOREMAP_PROT=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +# CONFIG_MODULE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +# CONFIG_FREEZER is not set + +# +# System type +# +CONFIG_CPU_SH4=y +CONFIG_CPU_SH4A=y +# CONFIG_CPU_SUBTYPE_SH7619 is not set +# CONFIG_CPU_SUBTYPE_SH7201 is not set +# CONFIG_CPU_SUBTYPE_SH7203 is not set +# CONFIG_CPU_SUBTYPE_SH7206 is not set +# CONFIG_CPU_SUBTYPE_SH7263 is not set +# CONFIG_CPU_SUBTYPE_MXG is not set +# CONFIG_CPU_SUBTYPE_SH7705 is not set +# CONFIG_CPU_SUBTYPE_SH7706 is not set +# CONFIG_CPU_SUBTYPE_SH7707 is not set +# CONFIG_CPU_SUBTYPE_SH7708 is not set +# CONFIG_CPU_SUBTYPE_SH7709 is not set +# CONFIG_CPU_SUBTYPE_SH7710 is not set +# CONFIG_CPU_SUBTYPE_SH7712 is not set +# CONFIG_CPU_SUBTYPE_SH7720 is not set +# CONFIG_CPU_SUBTYPE_SH7721 is not set +# CONFIG_CPU_SUBTYPE_SH7750 is not set +# CONFIG_CPU_SUBTYPE_SH7091 is not set +# CONFIG_CPU_SUBTYPE_SH7750R is not set +# CONFIG_CPU_SUBTYPE_SH7750S is not set +# CONFIG_CPU_SUBTYPE_SH7751 is not set +# CONFIG_CPU_SUBTYPE_SH7751R is not set +# CONFIG_CPU_SUBTYPE_SH7760 is not set +# CONFIG_CPU_SUBTYPE_SH4_202 is not set +# CONFIG_CPU_SUBTYPE_SH7723 is not set +CONFIG_CPU_SUBTYPE_SH7763=y +# CONFIG_CPU_SUBTYPE_SH7770 is not set +# CONFIG_CPU_SUBTYPE_SH7780 is not set +# CONFIG_CPU_SUBTYPE_SH7785 is not set +# CONFIG_CPU_SUBTYPE_SH7786 is not set +# CONFIG_CPU_SUBTYPE_SHX3 is not set +# CONFIG_CPU_SUBTYPE_SH7343 is not set +# CONFIG_CPU_SUBTYPE_SH7722 is not set +# CONFIG_CPU_SUBTYPE_SH7366 is not set +# CONFIG_CPU_SUBTYPE_SH5_101 is not set +# CONFIG_CPU_SUBTYPE_SH5_103 is not set + +# +# Memory management options +# +CONFIG_QUICKLIST=y +CONFIG_MMU=y +CONFIG_PAGE_OFFSET=0x80000000 +CONFIG_MEMORY_START=0x0c000000 +CONFIG_MEMORY_SIZE=0x04000000 +CONFIG_29BIT=y +CONFIG_VSYSCALL=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_MAX_ACTIVE_REGIONS=1 +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_ENTRY_OFFSET=0x00001000 +CONFIG_SELECT_MEMORY_MODEL=y +# CONFIG_FLATMEM_MANUAL is not set +# CONFIG_DISCONTIGMEM_MANUAL is not set +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM=y +CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_SPARSEMEM_STATIC=y +# CONFIG_MEMORY_HOTPLUG is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_MIGRATION=y +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_NR_QUICK=2 +CONFIG_UNEVICTABLE_LRU=y + +# +# Cache configuration +# +# CONFIG_SH_DIRECT_MAPPED is not set +CONFIG_CACHE_WRITEBACK=y +# CONFIG_CACHE_WRITETHROUGH is not set +# CONFIG_CACHE_OFF is not set + +# +# Processor features +# +CONFIG_CPU_LITTLE_ENDIAN=y +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_SH_FPU=y +# CONFIG_SH_STORE_QUEUES is not set +CONFIG_CPU_HAS_INTEVT=y +CONFIG_CPU_HAS_SR_RB=y +CONFIG_CPU_HAS_FPU=y + +# +# Board support +# +# CONFIG_SH_SH7763RDP is not set +CONFIG_SH_ESPT=y + +# +# Timer and clock configuration +# +CONFIG_SH_TMU=y +CONFIG_SH_TIMER_IRQ=28 +CONFIG_SH_PCLK_FREQ=66666666 +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set + +# +# DMA support +# +# CONFIG_SH_DMA is not set + +# +# Companion Chips +# + +# +# Additional SuperH Device Drivers +# +# CONFIG_HEARTBEAT is not set +# CONFIG_PUSH_SWITCH is not set + +# +# Kernel features +# +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +# CONFIG_SCHED_HRTICK is not set +# CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set +CONFIG_SECCOMP=y +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_GUSA=y + +# +# Boot options +# +CONFIG_ZERO_PAGE_OFFSET=0x00001000 +CONFIG_BOOT_LINK_OFFSET=0x00800000 +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/nfs ip=bootp" + +# +# Bus options +# +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options (EXPERIMENTAL) +# +# CONFIG_PM is not set +# CONFIG_CPU_IDLE is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_COMPAT_NET_DEV_OPS=y +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_PHONET is not set +# CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=y +# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set +CONFIG_MTD_MAP_BANK_WIDTH_2=y +# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_HD is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_LIBFC is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_FIXED_PHY is not set +CONFIG_MDIO_BITBANG=y +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +# CONFIG_STNIC is not set +CONFIG_SH_ETH=y +# CONFIG_SMC91X is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_SH_SCI=y +CONFIG_SERIAL_SH_SCI_NR_UARTS=3 +CONFIG_SERIAL_SH_SCI_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_REGULATOR is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +CONFIG_FB_FOREIGN_ENDIAN=y +CONFIG_FB_BOTH_ENDIAN=y +# CONFIG_FB_BIG_ENDIAN is not set +# CONFIG_FB_LITTLE_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_SH_MOBILE_LCDC is not set +CONFIG_FB_SH7760=y +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_LOGO_SUPERH_MONO=y +CONFIG_LOGO_SUPERH_VGA16=y +CONFIG_LOGO_SUPERH_CLUT224=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +CONFIG_USB_MON=y +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; +# + +# +# see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set +# CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y +# CONFIG_FUSE_FS is not set +CONFIG_GENERIC_ACL=y + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS2_FS is not set +CONFIG_CRAMFS=y +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +CONFIG_ROMFS_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_REGISTER_V4 is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=y +CONFIG_NLS_CODEPAGE_775=y +CONFIG_NLS_CODEPAGE_850=y +CONFIG_NLS_CODEPAGE_852=y +CONFIG_NLS_CODEPAGE_855=y +CONFIG_NLS_CODEPAGE_857=y +CONFIG_NLS_CODEPAGE_860=y +CONFIG_NLS_CODEPAGE_861=y +CONFIG_NLS_CODEPAGE_862=y +CONFIG_NLS_CODEPAGE_863=y +CONFIG_NLS_CODEPAGE_864=y +CONFIG_NLS_CODEPAGE_865=y +CONFIG_NLS_CODEPAGE_866=y +CONFIG_NLS_CODEPAGE_869=y +CONFIG_NLS_CODEPAGE_936=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_CODEPAGE_932=y +CONFIG_NLS_CODEPAGE_949=y +CONFIG_NLS_CODEPAGE_874=y +CONFIG_NLS_ISO8859_8=y +CONFIG_NLS_CODEPAGE_1250=y +CONFIG_NLS_CODEPAGE_1251=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_2=y +CONFIG_NLS_ISO8859_3=y +CONFIG_NLS_ISO8859_4=y +CONFIG_NLS_ISO8859_5=y +CONFIG_NLS_ISO8859_6=y +CONFIG_NLS_ISO8859_7=y +CONFIG_NLS_ISO8859_9=y +CONFIG_NLS_ISO8859_13=y +CONFIG_NLS_ISO8859_14=y +CONFIG_NLS_ISO8859_15=y +CONFIG_NLS_KOI8_R=y +CONFIG_NLS_KOI8_U=y +CONFIG_NLS_UTF8=y +# CONFIG_DLM is not set + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LATENCYTOP is not set +CONFIG_NOP_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_RING_BUFFER=y +CONFIG_TRACING=y + +# +# Tracers +# +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_SH_STANDARD_BIOS is not set +# CONFIG_EARLY_SCIF_CONSOLE is not set +# CONFIG_MORE_COMPILE_OPTIONS is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_HW=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC_T10DIF=y +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types index 8f9e1662fa9..4932705603b 100644 --- a/arch/sh/tools/mach-types +++ b/arch/sh/tools/mach-types @@ -53,3 +53,4 @@ AP325RXA SH_AP325RXA SH7763RDP SH_SH7763RDP SH7785LCR SH_SH7785LCR URQUELL SH_URQUELL +ESPT SH_ESPT -- GitLab From da78800632197ac12adcdefbf09991d82adb8201 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Tue, 17 Mar 2009 05:53:26 +0000 Subject: [PATCH 3622/4982] sh: sh7763rdp: Change IRQ number for sh_eth of sh7763rdp IRQ for sh_eth of sh7763rdp became multi handling. Therefore, the IRQ number of sh_eth is changed, too. Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: Paul Mundt --- arch/sh/boards/mach-sh7763rdp/setup.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/sh/boards/mach-sh7763rdp/setup.c b/arch/sh/boards/mach-sh7763rdp/setup.c index 6f926fd2162..390534a0b35 100644 --- a/arch/sh/boards/mach-sh7763rdp/setup.c +++ b/arch/sh/boards/mach-sh7763rdp/setup.c @@ -63,15 +63,19 @@ static struct platform_device sh7763rdp_nor_flash_device = { }, }; -/* SH-Ether */ +/* + * SH-Ether + * + * SH Ether of SH7763 has multi IRQ handling. + * (57,58,59 -> 57) + */ static struct resource sh_eth_resources[] = { { .start = 0xFEE00800, /* use eth1 */ .end = 0xFEE00F7C - 1, .flags = IORESOURCE_MEM, }, { - .start = 58, /* irq number */ - .end = 58, + .start = 57, /* irq number */ .flags = IORESOURCE_IRQ, }, }; -- GitLab From dde332b660cf0bc2baaba678b52768a0fb6e6da2 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Mon, 16 Mar 2009 21:32:25 +0100 Subject: [PATCH 3623/4982] ALSA: opl3sa2 - Fix NULL dereference when suspending snd_opl3sa2 Fix the OOPS during a opl3sa2 card suspend and resume if the driver is loaded but the card is not found. Signed-off-by: Krzysztof Helt Cc: Signed-off-by: Takashi Iwai --- sound/isa/opl3sa2.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index 58c972b2af0..b848d100186 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c @@ -550,21 +550,27 @@ static int __devinit snd_opl3sa2_mixer(struct snd_card *card) #ifdef CONFIG_PM static int snd_opl3sa2_suspend(struct snd_card *card, pm_message_t state) { - struct snd_opl3sa2 *chip = card->private_data; + if (card) { + struct snd_opl3sa2 *chip = card->private_data; - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - chip->wss->suspend(chip->wss); - /* power down */ - snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D3); + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + chip->wss->suspend(chip->wss); + /* power down */ + snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D3); + } return 0; } static int snd_opl3sa2_resume(struct snd_card *card) { - struct snd_opl3sa2 *chip = card->private_data; + struct snd_opl3sa2 *chip; int i; + if (!card) + return 0; + + chip = card->private_data; /* power up */ snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D0); -- GitLab From 8263a67e169fdf0d06d172acbf6c03ae172a69d4 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 17 Mar 2009 17:49:49 +0900 Subject: [PATCH 3624/4982] sh: Support for extended ASIDs on PTEAEX-capable SH-X3 cores. This adds support for extended ASIDs (up to 16-bits) on newer SH-X3 cores that implement the PTAEX register and respective functionality. Presently only the 65nm SH7786 (90nm only supports legacy 8-bit ASIDs). The main change is in how the PTE is written out when loading the entry in to the TLB, as well as in how the TLB entry is selectively flushed. While SH-X2 extended mode splits out the memory-mapped U and I-TLB data arrays for extra bits, extended ASID mode splits out the address arrays. While we don't use the memory-mapped data array access, the address array accesses are necessary for selective TLB flushes, so these are implemented newly and replace the generic SH-4 implementation. With this, TLB flushes in switch_mm() are almost non-existent on newer parts. Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 1 + arch/sh/Kconfig.cpu | 3 + arch/sh/include/asm/cpu-features.h | 1 + arch/sh/include/asm/mmu_context.h | 15 ++-- arch/sh/include/asm/mmu_context_32.h | 12 +++ arch/sh/include/cpu-sh4/cpu/mmu_context.h | 35 ++++---- arch/sh/kernel/cpu/sh4/probe.c | 2 +- arch/sh/kernel/setup.c | 2 +- arch/sh/mm/Makefile_32 | 6 +- arch/sh/mm/tlb-pteaex.c | 99 +++++++++++++++++++++++ 10 files changed, 148 insertions(+), 28 deletions(-) create mode 100644 arch/sh/mm/tlb-pteaex.c diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index a0c879d17fd..6c56495fd15 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -365,6 +365,7 @@ config CPU_SUBTYPE_SH7786 bool "Support SH7786 processor" select CPU_SH4A select CPU_SHX3 + select CPU_HAS_PTEAEX select ARCH_SPARSEMEM_ENABLE select SYS_SUPPORTS_NUMA diff --git a/arch/sh/Kconfig.cpu b/arch/sh/Kconfig.cpu index 0e27fe3b182..c7d704381a6 100644 --- a/arch/sh/Kconfig.cpu +++ b/arch/sh/Kconfig.cpu @@ -104,6 +104,9 @@ config CPU_HAS_SR_RB config CPU_HAS_PTEA bool +config CPU_HAS_PTEAEX + bool + config CPU_HAS_DSP bool diff --git a/arch/sh/include/asm/cpu-features.h b/arch/sh/include/asm/cpu-features.h index 86308aa3973..694abe490ed 100644 --- a/arch/sh/include/asm/cpu-features.h +++ b/arch/sh/include/asm/cpu-features.h @@ -21,5 +21,6 @@ #define CPU_HAS_LLSC 0x0040 /* movli.l/movco.l */ #define CPU_HAS_L2_CACHE 0x0080 /* Secondary cache / URAM */ #define CPU_HAS_OP32 0x0100 /* 32-bit instruction support */ +#define CPU_HAS_PTEAEX 0x0200 /* PTE ASID Extension support */ #endif /* __ASM_SH_CPU_FEATURES_H */ diff --git a/arch/sh/include/asm/mmu_context.h b/arch/sh/include/asm/mmu_context.h index 5d9157bd474..2a9c55f1a83 100644 --- a/arch/sh/include/asm/mmu_context.h +++ b/arch/sh/include/asm/mmu_context.h @@ -19,13 +19,18 @@ * (a) TLB cache version (or round, cycle whatever expression you like) * (b) ASID (Address Space IDentifier) */ +#ifdef CONFIG_CPU_HAS_PTEAEX +#define MMU_CONTEXT_ASID_MASK 0x0000ffff +#else #define MMU_CONTEXT_ASID_MASK 0x000000ff -#define MMU_CONTEXT_VERSION_MASK 0xffffff00 -#define MMU_CONTEXT_FIRST_VERSION 0x00000100 -#define NO_CONTEXT 0UL +#endif -/* ASID is 8-bit value, so it can't be 0x100 */ -#define MMU_NO_ASID 0x100 +#define MMU_CONTEXT_VERSION_MASK (~0UL & ~MMU_CONTEXT_ASID_MASK) +#define MMU_CONTEXT_FIRST_VERSION (MMU_CONTEXT_ASID_MASK + 1) + +/* Impossible ASID value, to differentiate from NO_CONTEXT. */ +#define MMU_NO_ASID MMU_CONTEXT_FIRST_VERSION +#define NO_CONTEXT 0UL #define asid_cache(cpu) (cpu_data[cpu].asid_cache) diff --git a/arch/sh/include/asm/mmu_context_32.h b/arch/sh/include/asm/mmu_context_32.h index f4f9aebd68b..8ef800c549a 100644 --- a/arch/sh/include/asm/mmu_context_32.h +++ b/arch/sh/include/asm/mmu_context_32.h @@ -10,6 +10,17 @@ static inline void destroy_context(struct mm_struct *mm) /* Do nothing */ } +#ifdef CONFIG_CPU_HAS_PTEAEX +static inline void set_asid(unsigned long asid) +{ + __raw_writel(asid, MMU_PTEAEX); +} + +static inline unsigned long get_asid(void) +{ + return __raw_readl(MMU_PTEAEX) & MMU_CONTEXT_ASID_MASK; +} +#else static inline void set_asid(unsigned long asid) { unsigned long __dummy; @@ -33,6 +44,7 @@ static inline unsigned long get_asid(void) asid &= MMU_CONTEXT_ASID_MASK; return asid; } +#endif /* CONFIG_CPU_HAS_PTEAEX */ /* MMU_TTB is used for optimizing the fault handling. */ static inline void set_TTB(pgd_t *pgd) diff --git a/arch/sh/include/cpu-sh4/cpu/mmu_context.h b/arch/sh/include/cpu-sh4/cpu/mmu_context.h index 9ea8eb27b18..3ce7ef6c297 100644 --- a/arch/sh/include/cpu-sh4/cpu/mmu_context.h +++ b/arch/sh/include/cpu-sh4/cpu/mmu_context.h @@ -14,28 +14,35 @@ #define MMU_PTEL 0xFF000004 /* Page table entry register LOW */ #define MMU_TTB 0xFF000008 /* Translation table base register */ #define MMU_TEA 0xFF00000C /* TLB Exception Address */ -#define MMU_PTEA 0xFF000034 /* Page table entry assistance register */ +#define MMU_PTEA 0xFF000034 /* PTE assistance register */ +#define MMU_PTEAEX 0xFF00007C /* PTE ASID extension register */ #define MMUCR 0xFF000010 /* MMU Control Register */ -#define MMU_ITLB_ADDRESS_ARRAY 0xF2000000 #define MMU_UTLB_ADDRESS_ARRAY 0xF6000000 +#define MMU_UTLB_ADDRESS_ARRAY2 0xF6800000 #define MMU_PAGE_ASSOC_BIT 0x80 #define MMUCR_TI (1<<2) -#ifdef CONFIG_X2TLB -#define MMUCR_ME (1 << 7) -#else -#define MMUCR_ME (0) -#endif - #if defined(CONFIG_32BIT) && defined(CONFIG_CPU_SUBTYPE_ST40) #define MMUCR_SE (1 << 4) #else #define MMUCR_SE (0) #endif +#ifdef CONFIG_CPU_HAS_PTEAEX +#define MMUCR_AEX (1 << 6) +#else +#define MMUCR_AEX (0) +#endif + +#ifdef CONFIG_X2TLB +#define MMUCR_ME (1 << 7) +#else +#define MMUCR_ME (0) +#endif + #ifdef CONFIG_SH_STORE_QUEUES #define MMUCR_SQMD (1 << 9) #else @@ -43,17 +50,7 @@ #endif #define MMU_NTLB_ENTRIES 64 -#define MMU_CONTROL_INIT (0x05|MMUCR_SQMD|MMUCR_ME|MMUCR_SE) - -#define MMU_ITLB_DATA_ARRAY 0xF3000000 -#define MMU_UTLB_DATA_ARRAY 0xF7000000 - -#define MMU_UTLB_ENTRIES 64 -#define MMU_U_ENTRY_SHIFT 8 -#define MMU_UTLB_VALID 0x100 -#define MMU_ITLB_ENTRIES 4 -#define MMU_I_ENTRY_SHIFT 8 -#define MMU_ITLB_VALID 0x100 +#define MMU_CONTROL_INIT (0x05|MMUCR_SQMD|MMUCR_ME|MMUCR_SE|MMUCR_AEX) #define TRA 0xff000020 #define EXPEVT 0xff000024 diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c index 2bd0ec96263..3d3a3c4425a 100644 --- a/arch/sh/kernel/cpu/sh4/probe.c +++ b/arch/sh/kernel/cpu/sh4/probe.c @@ -134,7 +134,7 @@ int __init detect_cpu_and_cache_system(void) boot_cpu_data.icache.ways = 4; boot_cpu_data.dcache.ways = 4; boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER | - CPU_HAS_LLSC; + CPU_HAS_LLSC | CPU_HAS_PTEAEX; break; case 0x3008: boot_cpu_data.icache.ways = 4; diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 61ab2a7f864..24c60251f68 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -449,7 +449,7 @@ EXPORT_SYMBOL(get_cpu_subtype); /* Symbolic CPU flags, keep in sync with asm/cpu-features.h */ static const char *cpu_flags[] = { "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr", - "ptea", "llsc", "l2", "op32", NULL + "ptea", "llsc", "l2", "op32", "pteaex", NULL }; static void show_cpuflags(struct seq_file *m, struct sh_cpuinfo *c) diff --git a/arch/sh/mm/Makefile_32 b/arch/sh/mm/Makefile_32 index 469ff167245..986a1e05583 100644 --- a/arch/sh/mm/Makefile_32 +++ b/arch/sh/mm/Makefile_32 @@ -25,8 +25,10 @@ obj-$(CONFIG_CPU_SH4) += cache-debugfs.o endif ifdef CONFIG_MMU -obj-$(CONFIG_CPU_SH3) += tlb-sh3.o -obj-$(CONFIG_CPU_SH4) += tlb-sh4.o +tlb-$(CONFIG_CPU_SH3) := tlb-sh3.o +tlb-$(CONFIG_CPU_SH4) := tlb-sh4.o +tlb-$(CONFIG_CPU_HAS_PTEAEX) := tlb-pteaex.o +obj-y += $(tlb-y) ifndef CONFIG_CACHE_OFF obj-$(CONFIG_CPU_SH4) += pg-sh4.o obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh7705.o diff --git a/arch/sh/mm/tlb-pteaex.c b/arch/sh/mm/tlb-pteaex.c new file mode 100644 index 00000000000..5c9b2d781e0 --- /dev/null +++ b/arch/sh/mm/tlb-pteaex.c @@ -0,0 +1,99 @@ +/* + * arch/sh/mm/tlb-pteaex.c + * + * TLB operations for SH-X3 CPUs featuring PTE ASID Extensions. + * + * Copyright (C) 2009 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include + +void update_mmu_cache(struct vm_area_struct * vma, + unsigned long address, pte_t pte) +{ + unsigned long flags; + unsigned long pteval; + unsigned long vpn; + + /* Ptrace may call this routine. */ + if (vma && current->active_mm != vma->vm_mm) + return; + +#ifndef CONFIG_CACHE_OFF + { + unsigned long pfn = pte_pfn(pte); + + if (pfn_valid(pfn)) { + struct page *page = pfn_to_page(pfn); + + if (!test_bit(PG_mapped, &page->flags)) { + unsigned long phys = pte_val(pte) & PTE_PHYS_MASK; + __flush_wback_region((void *)P1SEGADDR(phys), + PAGE_SIZE); + __set_bit(PG_mapped, &page->flags); + } + } + } +#endif + + local_irq_save(flags); + + /* Set PTEH register */ + vpn = address & MMU_VPN_MASK; + __raw_writel(vpn, MMU_PTEH); + + /* Set PTEAEX */ + __raw_writel(get_asid(), MMU_PTEAEX); + + pteval = pte.pte_low; + + /* Set PTEA register */ +#ifdef CONFIG_X2TLB + /* + * For the extended mode TLB this is trivial, only the ESZ and + * EPR bits need to be written out to PTEA, with the remainder of + * the protection bits (with the exception of the compat-mode SZ + * and PR bits, which are cleared) being written out in PTEL. + */ + __raw_writel(pte.pte_high, MMU_PTEA); +#else + /* TODO: make this look less hacky */ + __raw_writel(((pteval >> 28) & 0xe) | (pteval & 0x1), MMU_PTEA); +#endif + + /* Set PTEL register */ + pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */ +#ifdef CONFIG_CACHE_WRITETHROUGH + pteval |= _PAGE_WT; +#endif + /* conveniently, we want all the software flags to be 0 anyway */ + __raw_writel(pteval, MMU_PTEL); + + /* Load the TLB */ + asm volatile("ldtlb": /* no output */ : /* no input */ : "memory"); + local_irq_restore(flags); +} + +/* + * While SH-X2 extended TLB mode splits out the memory-mapped I/UTLB + * data arrays, SH-X3 cores with PTEAEX split out the memory-mapped + * address arrays. In compat mode the second array is inaccessible, while + * in extended mode, the legacy 8-bit ASID field in address array 1 has + * undefined behaviour. + */ +void __uses_jump_to_uncached local_flush_tlb_one(unsigned long asid, + unsigned long page) +{ + jump_to_uncached(); + __raw_writel(page, MMU_UTLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT); + __raw_writel(asid, MMU_UTLB_ADDRESS_ARRAY2 | MMU_PAGE_ASSOC_BIT); + back_to_cached(); +} -- GitLab From c54a43e90b80993b2e0772d678563cb2bc6a1b3b Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 17 Mar 2009 17:58:33 +0900 Subject: [PATCH 3625/4982] sh: tlb-pteaex: Kill off legacy PTEA updates. While harmless, PTEA has different semantics on these parts, and is only used in extended TLB mode. Kill off the legacy support. Signed-off-by: Paul Mundt --- arch/sh/mm/tlb-pteaex.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/sh/mm/tlb-pteaex.c b/arch/sh/mm/tlb-pteaex.c index 5c9b2d781e0..2aab3ea934d 100644 --- a/arch/sh/mm/tlb-pteaex.c +++ b/arch/sh/mm/tlb-pteaex.c @@ -64,9 +64,6 @@ void update_mmu_cache(struct vm_area_struct * vma, * and PR bits, which are cleared) being written out in PTEL. */ __raw_writel(pte.pte_high, MMU_PTEA); -#else - /* TODO: make this look less hacky */ - __raw_writel(((pteval >> 28) & 0xe) | (pteval & 0x1), MMU_PTEA); #endif /* Set PTEL register */ -- GitLab From 3a3b311ca375a37b29bb78b030f96bf97dee97f5 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 17 Mar 2009 17:59:31 +0900 Subject: [PATCH 3626/4982] sh: Update debugfs ASID dumping for 16-bit ASID support. Signed-off-by: Paul Mundt --- arch/sh/mm/asids-debugfs.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/sh/mm/asids-debugfs.c b/arch/sh/mm/asids-debugfs.c index 8e912a15e94..cd8c3bf39b5 100644 --- a/arch/sh/mm/asids-debugfs.c +++ b/arch/sh/mm/asids-debugfs.c @@ -37,10 +37,8 @@ static int asids_seq_show(struct seq_file *file, void *iter) continue; if (p->mm) - seq_printf(file, "%5d : %02lx\n", pid, + seq_printf(file, "%5d : %04lx\n", pid, cpu_asid(smp_processor_id(), p->mm)); - else - seq_printf(file, "%5d : (none)\n", pid); } read_unlock(&tasklist_lock); -- GitLab From 80dd99b368cf6501be88ab517bbbb5bf352b75b8 Mon Sep 17 00:00:00 2001 From: Luis Henriques Date: Mon, 16 Mar 2009 19:58:09 +0000 Subject: [PATCH 3627/4982] sched: fix typos in documentation Fixed typos in function documentation. Signed-off-by: Luis Henriques LKML-Reference: <20090316195809.GA6073@hades.domain.com> Signed-off-by: Ingo Molnar --- kernel/sched.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 2f28351892c..489e7d92640 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2082,7 +2082,7 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state) * it must be off the runqueue _entirely_, and not * preempted! * - * So if it wa still runnable (but just not actively + * So if it was still runnable (but just not actively * running right now), it's preempted, and we should * yield - it could be a while. */ @@ -2574,7 +2574,7 @@ void wake_up_new_task(struct task_struct *p, unsigned long clone_flags) #ifdef CONFIG_PREEMPT_NOTIFIERS /** - * preempt_notifier_register - tell me when current is being being preempted & rescheduled + * preempt_notifier_register - tell me when current is being preempted & rescheduled * @notifier: notifier struct to register */ void preempt_notifier_register(struct preempt_notifier *notifier) -- GitLab From 708dc5125309cd33c5daaad3026cc4ae6ef39c8b Mon Sep 17 00:00:00 2001 From: Luis Henriques Date: Mon, 16 Mar 2009 19:59:02 +0000 Subject: [PATCH 3628/4982] sched: small optimisation of can_migrate_task() There were 3 invocations of task_hot() in can_migrate_task(). Replace these 3 invocations by only one invocation, cached in a local variable. Signed-off-by: Luis Henriques LKML-Reference: <20090316195902.GA6197@hades.domain.com> Signed-off-by: Ingo Molnar --- kernel/sched.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 489e7d92640..d2dfe4c1a22 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3002,6 +3002,7 @@ int can_migrate_task(struct task_struct *p, struct rq *rq, int this_cpu, struct sched_domain *sd, enum cpu_idle_type idle, int *all_pinned) { + int tsk_cache_hot = 0; /* * We do not migrate tasks that are: * 1) running (obviously), or @@ -3025,10 +3026,11 @@ int can_migrate_task(struct task_struct *p, struct rq *rq, int this_cpu, * 2) too many balance attempts have failed. */ - if (!task_hot(p, rq->clock, sd) || - sd->nr_balance_failed > sd->cache_nice_tries) { + tsk_cache_hot = task_hot(p, rq->clock, sd); + if (!tsk_cache_hot || + sd->nr_balance_failed > sd->cache_nice_tries) { #ifdef CONFIG_SCHEDSTATS - if (task_hot(p, rq->clock, sd)) { + if (tsk_cache_hot) { schedstat_inc(sd, lb_hot_gained[idle]); schedstat_inc(p, se.nr_forced_migrations); } @@ -3036,7 +3038,7 @@ int can_migrate_task(struct task_struct *p, struct rq *rq, int this_cpu, return 1; } - if (task_hot(p, rq->clock, sd)) { + if (tsk_cache_hot) { schedstat_inc(p, se.nr_failed_migrations_hot); return 0; } -- GitLab From c20351846efcb755ba849d9fb701fbd9a1ffb7c2 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 17 Mar 2009 21:19:49 +0900 Subject: [PATCH 3629/4982] sh: Flush only the needed range when unmapping a VMA. This follows the ARM change from Aaro Koskinen: When unmapping N pages (e.g. shared memory) the amount of TLB flushes done can be (N*PAGE_SIZE/ZAP_BLOCK_SIZE)*N although it should be N at maximum. With PREEMPT kernel ZAP_BLOCK_SIZE is 8 pages, so there is a noticeable performance penalty when unmapping a large VMA and the system is spending its time in flush_tlb_range(). The problem is that tlb_end_vma() is always flushing the full VMA range. The subrange that needs to be flushed can be calculated by tlb_remove_tlb_entry(). This approach was suggested by Hugh Dickins, and is also used by other arches. The speed increase is roughly 3x for 8M mappings and for larger mappings even more. Bits and peices are taken from the ARM patch as well as the existing arch/um implementation that is quite similar. The end result is a significant reduction in both partial and full TLB flushes initiated through flush_tlb_range(). At the same time, the nommu implementation was broken, had a superfluous cache flush, and subsequently would have triggered a BUG_ON() if a code-path had triggered it. Tidy this up for correctness and provide a nopped-out implementation there. More background on the initial discussion can be found at: http://marc.info/?t=123609820900002&r=1&w=2 http://marc.info/?t=123660375800003&r=1&w=2 Signed-off-by: Paul Mundt --- arch/sh/include/asm/tlb.h | 100 +++++++++++++++++++++++++++++++++++--- 1 file changed, 92 insertions(+), 8 deletions(-) diff --git a/arch/sh/include/asm/tlb.h b/arch/sh/include/asm/tlb.h index 88ff1ae8a6b..9c16f737074 100644 --- a/arch/sh/include/asm/tlb.h +++ b/arch/sh/include/asm/tlb.h @@ -6,22 +6,106 @@ #endif #ifndef __ASSEMBLY__ +#include + +#ifdef CONFIG_MMU +#include +#include + +/* + * TLB handling. This allows us to remove pages from the page + * tables, and efficiently handle the TLB issues. + */ +struct mmu_gather { + struct mm_struct *mm; + unsigned int fullmm; + unsigned long start, end; +}; -#define tlb_start_vma(tlb, vma) \ - flush_cache_range(vma, vma->vm_start, vma->vm_end) +DECLARE_PER_CPU(struct mmu_gather, mmu_gathers); -#define tlb_end_vma(tlb, vma) \ - flush_tlb_range(vma, vma->vm_start, vma->vm_end) +static inline void init_tlb_gather(struct mmu_gather *tlb) +{ + tlb->start = TASK_SIZE; + tlb->end = 0; -#define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0) + if (tlb->fullmm) { + tlb->start = 0; + tlb->end = TASK_SIZE; + } +} + +static inline struct mmu_gather * +tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush) +{ + struct mmu_gather *tlb = &get_cpu_var(mmu_gathers); + + tlb->mm = mm; + tlb->fullmm = full_mm_flush; + + init_tlb_gather(tlb); + + return tlb; +} + +static inline void +tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) +{ + if (tlb->fullmm) + flush_tlb_mm(tlb->mm); + + /* keep the page table cache within bounds */ + check_pgt_cache(); + + put_cpu_var(mmu_gathers); +} + +static inline void +tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long address) +{ + if (tlb->start > address) + tlb->start = address; + if (tlb->end < address + PAGE_SIZE) + tlb->end = address + PAGE_SIZE; +} /* - * Flush whole TLBs for MM + * In the case of tlb vma handling, we can optimise these away in the + * case where we're doing a full MM flush. When we're doing a munmap, + * the vmas are adjusted to only cover the region to be torn down. */ -#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm) +static inline void +tlb_start_vma(struct mmu_gather *tlb, struct vm_area_struct *vma) +{ + if (!tlb->fullmm) + flush_cache_range(vma, vma->vm_start, vma->vm_end); +} + +static inline void +tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma) +{ + if (!tlb->fullmm && tlb->end) { + flush_tlb_range(vma, tlb->start, tlb->end); + init_tlb_gather(tlb); + } +} + +#define tlb_remove_page(tlb,page) free_page_and_swap_cache(page) +#define pte_free_tlb(tlb, ptep) pte_free((tlb)->mm, ptep) +#define pmd_free_tlb(tlb, pmdp) pmd_free((tlb)->mm, pmdp) +#define pud_free_tlb(tlb, pudp) pud_free((tlb)->mm, pudp) + +#define tlb_migrate_finish(mm) do { } while (0) + +#else /* CONFIG_MMU */ + +#define tlb_start_vma(tlb, vma) do { } while (0) +#define tlb_end_vma(tlb, vma) do { } while (0) +#define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0) +#define tlb_flush(tlb) do { } while (0) -#include #include +#endif /* CONFIG_MMU */ #endif /* __ASSEMBLY__ */ #endif /* __ASM_SH_TLB_H */ -- GitLab From d2314e0e27566f8830ebed3587cc049e07e6a4ee Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Mon, 16 Mar 2009 23:26:20 +0900 Subject: [PATCH 3630/4982] ASoC: Only deregister AC97 dev if it's name was not "AC97" The commit 14fa43f53ff3a9c3d8b9662574b7369812a31a97 ("ASoC: Only register AC97 bus if it's not done already") added a condition for calling of soc_ac97_dev_register() but not added for calling of soc_ac97_dev_unregister(). This patch adds same condition for soc_ac97_dev_unregister(). Without this fix, kernel crashes when unloading an asoc driver. Signed-off-by: Atsushi Nemoto Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 16518329f6b..6e710f705a7 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1432,7 +1432,8 @@ void snd_soc_free_pcms(struct snd_soc_device *socdev) #ifdef CONFIG_SND_SOC_AC97_BUS for (i = 0; i < codec->num_dai; i++) { codec_dai = &codec->dai[i]; - if (codec_dai->ac97_control && codec->ac97) { + if (codec_dai->ac97_control && codec->ac97 && + strcmp(codec->name, "AC97") != 0) { soc_ac97_dev_unregister(codec); goto free_card; } -- GitLab From 0a07232ff62d1523c5fa7292180890f4de670b95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Ha=C5=82asa?= Date: Fri, 13 Mar 2009 17:57:04 +0100 Subject: [PATCH 3631/4982] IXP4xx: workaround for PCI prefetch problems near 64 MB boundary. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Map unused registers at the end of DMA region at 64 MB to allow PCI masters to cross the boundary when prefetching data from SDRAM. Signed-off-by: Krzysztof HaÅ‚asa --- arch/arm/include/asm/sizes.h | 1 + arch/arm/mach-ixp4xx/common-pci.c | 23 ++++++++++++----------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/arch/arm/include/asm/sizes.h b/arch/arm/include/asm/sizes.h index 503843db156..c10d1aa4b48 100644 --- a/arch/arm/include/asm/sizes.h +++ b/arch/arm/include/asm/sizes.h @@ -43,6 +43,7 @@ #define SZ_8M 0x00800000 #define SZ_16M 0x01000000 #define SZ_32M 0x02000000 +#define SZ_48M 0x03000000 #define SZ_64M 0x04000000 #define SZ_128M 0x08000000 #define SZ_256M 0x10000000 diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c index d816c51320c..2d0f09e9819 100644 --- a/arch/arm/mach-ixp4xx/common-pci.c +++ b/arch/arm/mach-ixp4xx/common-pci.c @@ -366,7 +366,7 @@ void __init ixp4xx_adjust_zones(int node, unsigned long *zone_size, } void __init ixp4xx_pci_preinit(void) -{ +{ unsigned long cpuid = read_cpuid_id(); /* @@ -386,17 +386,17 @@ void __init ixp4xx_pci_preinit(void) pr_debug("setup PCI-AHB(inbound) and AHB-PCI(outbound) address mappings\n"); - /* + /* * We use identity AHB->PCI address translation * in the 0x48000000 to 0x4bffffff address space */ *PCI_PCIMEMBASE = 0x48494A4B; - /* + /* * We also use identity PCI->AHB address translation * in 4 16MB BARs that begin at the physical memory start */ - *PCI_AHBMEMBASE = (PHYS_OFFSET & 0xFF000000) + + *PCI_AHBMEMBASE = (PHYS_OFFSET & 0xFF000000) + ((PHYS_OFFSET & 0xFF000000) >> 8) + ((PHYS_OFFSET & 0xFF000000) >> 16) + ((PHYS_OFFSET & 0xFF000000) >> 24) + @@ -408,18 +408,19 @@ void __init ixp4xx_pci_preinit(void) pr_debug("setup BARs in controller\n"); /* - * We configure the PCI inbound memory windows to be + * We configure the PCI inbound memory windows to be * 1:1 mapped to SDRAM */ - local_write_config(PCI_BASE_ADDRESS_0, 4, PHYS_OFFSET + 0x00000000); - local_write_config(PCI_BASE_ADDRESS_1, 4, PHYS_OFFSET + 0x01000000); - local_write_config(PCI_BASE_ADDRESS_2, 4, PHYS_OFFSET + 0x02000000); - local_write_config(PCI_BASE_ADDRESS_3, 4, PHYS_OFFSET + 0x03000000); + local_write_config(PCI_BASE_ADDRESS_0, 4, PHYS_OFFSET); + local_write_config(PCI_BASE_ADDRESS_1, 4, PHYS_OFFSET + SZ_16M); + local_write_config(PCI_BASE_ADDRESS_2, 4, PHYS_OFFSET + SZ_32M); + local_write_config(PCI_BASE_ADDRESS_3, 4, PHYS_OFFSET + SZ_48M); /* - * Enable CSR window at 0xff000000. + * Enable CSR window at 64 MiB to allow PCI masters + * to continue prefetching past 64 MiB boundary. */ - local_write_config(PCI_BASE_ADDRESS_4, 4, 0xff000008); + local_write_config(PCI_BASE_ADDRESS_4, 4, PHYS_OFFSET + SZ_64M); /* * Enable the IO window to be way up high, at 0xfffffc00 -- GitLab From 5ca328d24d25fa2c8d2aa33cb85116695be11070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Ha=C5=82asa?= Date: Fri, 13 Mar 2009 19:09:00 +0100 Subject: [PATCH 3632/4982] IXP4xx: add Ethernet and NPE support for IXP43x CPU. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Krzysztof HaÅ‚asa --- arch/arm/mach-ixp4xx/ixp4xx_npe.c | 6 +++--- drivers/net/arm/ixp4xx_eth.c | 20 +++++++++++++------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-ixp4xx/ixp4xx_npe.c b/arch/arm/mach-ixp4xx/ixp4xx_npe.c index c73a94d0ca2..25231023490 100644 --- a/arch/arm/mach-ixp4xx/ixp4xx_npe.c +++ b/arch/arm/mach-ixp4xx/ixp4xx_npe.c @@ -575,8 +575,8 @@ int npe_load_firmware(struct npe *npe, const char *name, struct device *dev) for (i = 0; i < image->size; i++) image->data[i] = swab32(image->data[i]); - if (!cpu_is_ixp46x() && ((image->id >> 28) & 0xF /* device ID */)) { - print_npe(KERN_INFO, npe, "IXP46x firmware ignored on " + if (cpu_is_ixp42x() && ((image->id >> 28) & 0xF /* device ID */)) { + print_npe(KERN_INFO, npe, "IXP43x/IXP46x firmware ignored on " "IXP42x\n"); goto err; } @@ -596,7 +596,7 @@ int npe_load_firmware(struct npe *npe, const char *name, struct device *dev) "revision 0x%X:%X\n", (image->id >> 16) & 0xFF, (image->id >> 8) & 0xFF, image->id & 0xFF); - if (!cpu_is_ixp46x()) { + if (cpu_is_ixp42x()) { if (!npe->id) instr_size = NPE_A_42X_INSTR_SIZE; else diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index 5fce1d5c1a1..9cc43476bfa 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -335,11 +335,20 @@ static int ixp4xx_mdio_register(void) if (!(mdio_bus = mdiobus_alloc())) return -ENOMEM; - /* All MII PHY accesses use NPE-B Ethernet registers */ - spin_lock_init(&mdio_lock); - mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT; - __raw_writel(DEFAULT_CORE_CNTRL, &mdio_regs->core_control); + if (cpu_is_ixp43x()) { + /* IXP43x lacks NPE-B and uses NPE-C for MII PHY access */ + if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEC_ETH)) + return -ENOSYS; + mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthC_BASE_VIRT; + } else { + /* All MII PHY accesses use NPE-B Ethernet registers */ + if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEB_ETH0)) + return -ENOSYS; + mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT; + } + __raw_writel(DEFAULT_CORE_CNTRL, &mdio_regs->core_control); + spin_lock_init(&mdio_lock); mdio_bus->name = "IXP4xx MII Bus"; mdio_bus->read = &ixp4xx_mdio_read; mdio_bus->write = &ixp4xx_mdio_write; @@ -1250,9 +1259,6 @@ static struct platform_driver ixp4xx_eth_driver = { static int __init eth_init_module(void) { int err; - if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEB_ETH0)) - return -ENOSYS; - if ((err = ixp4xx_mdio_register())) return err; return platform_driver_register(&ixp4xx_eth_driver); -- GitLab From de3ce856d67b770f7d546e3f3e6a3972deb319a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Ha=C5=82asa?= Date: Tue, 17 Mar 2009 13:51:52 +0100 Subject: [PATCH 3633/4982] IXP4xx: cpu_is_ixp4*() now recognizes all IXP4xx processors. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Krzysztof HaÅ‚asa --- arch/arm/mach-ixp4xx/include/mach/cpu.h | 35 +++++++++------- .../mach-ixp4xx/include/mach/ixp4xx-regs.h | 42 ++++++++++++++----- 2 files changed, 52 insertions(+), 25 deletions(-) diff --git a/arch/arm/mach-ixp4xx/include/mach/cpu.h b/arch/arm/mach-ixp4xx/include/mach/cpu.h index 51bd69c46d9..def7773be67 100644 --- a/arch/arm/mach-ixp4xx/include/mach/cpu.h +++ b/arch/arm/mach-ixp4xx/include/mach/cpu.h @@ -17,26 +17,31 @@ #include /* Processor id value in CP15 Register 0 */ -#define IXP425_PROCESSOR_ID_VALUE 0x690541c0 -#define IXP435_PROCESSOR_ID_VALUE 0x69054040 -#define IXP465_PROCESSOR_ID_VALUE 0x69054200 -#define IXP4XX_PROCESSOR_ID_MASK 0xfffffff0 - -#define cpu_is_ixp42x() ((read_cpuid_id() & IXP4XX_PROCESSOR_ID_MASK) == \ - IXP425_PROCESSOR_ID_VALUE) -#define cpu_is_ixp43x() ((read_cpuid_id() & IXP4XX_PROCESSOR_ID_MASK) == \ - IXP435_PROCESSOR_ID_VALUE) -#define cpu_is_ixp46x() ((read_cpuid_id() & IXP4XX_PROCESSOR_ID_MASK) == \ - IXP465_PROCESSOR_ID_VALUE) +#define IXP42X_PROCESSOR_ID_VALUE 0x690541c0 /* including unused 0x690541Ex */ +#define IXP42X_PROCESSOR_ID_MASK 0xffffffc0 + +#define IXP43X_PROCESSOR_ID_VALUE 0x69054040 +#define IXP43X_PROCESSOR_ID_MASK 0xfffffff0 + +#define IXP46X_PROCESSOR_ID_VALUE 0x69054200 /* including IXP455 */ +#define IXP46X_PROCESSOR_ID_MASK 0xfffffff0 + +#define cpu_is_ixp42x() ((read_cpuid_id() & IXP42X_PROCESSOR_ID_MASK) == \ + IXP42X_PROCESSOR_ID_VALUE) +#define cpu_is_ixp43x() ((read_cpuid_id() & IXP43X_PROCESSOR_ID_MASK) == \ + IXP43X_PROCESSOR_ID_VALUE) +#define cpu_is_ixp46x() ((read_cpuid_id() & IXP46X_PROCESSOR_ID_MASK) == \ + IXP46X_PROCESSOR_ID_VALUE) static inline u32 ixp4xx_read_feature_bits(void) { unsigned int val = ~*IXP4XX_EXP_CFG2; - val &= ~IXP4XX_FEATURE_RESERVED; - if (!cpu_is_ixp46x()) - val &= ~IXP4XX_FEATURE_IXP46X_ONLY; - return val; + if (cpu_is_ixp42x()) + return val & IXP42X_FEATURE_MASK; + if (cpu_is_ixp43x()) + return val & IXP43X_FEATURE_MASK; + return val & IXP46X_FEATURE_MASK; } static inline void ixp4xx_write_feature_bits(u32 value) diff --git a/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h b/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h index ad9c888dd85..97c530f66e7 100644 --- a/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h +++ b/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h @@ -604,6 +604,7 @@ #define DCMD_LENGTH 0x01fff /* length mask (max = 8K - 1) */ /* "fuse" bits of IXP_EXP_CFG2 */ +/* All IXP4xx CPUs */ #define IXP4XX_FEATURE_RCOMP (1 << 0) #define IXP4XX_FEATURE_USB_DEVICE (1 << 1) #define IXP4XX_FEATURE_HASH (1 << 2) @@ -619,20 +620,41 @@ #define IXP4XX_FEATURE_RESET_NPEB (1 << 12) #define IXP4XX_FEATURE_RESET_NPEC (1 << 13) #define IXP4XX_FEATURE_PCI (1 << 14) -#define IXP4XX_FEATURE_ECC_TIMESYNC (1 << 15) #define IXP4XX_FEATURE_UTOPIA_PHY_LIMIT (3 << 16) +#define IXP4XX_FEATURE_XSCALE_MAX_FREQ (3 << 22) +#define IXP42X_FEATURE_MASK (IXP4XX_FEATURE_RCOMP | \ + IXP4XX_FEATURE_USB_DEVICE | \ + IXP4XX_FEATURE_HASH | \ + IXP4XX_FEATURE_AES | \ + IXP4XX_FEATURE_DES | \ + IXP4XX_FEATURE_HDLC | \ + IXP4XX_FEATURE_AAL | \ + IXP4XX_FEATURE_HSS | \ + IXP4XX_FEATURE_UTOPIA | \ + IXP4XX_FEATURE_NPEB_ETH0 | \ + IXP4XX_FEATURE_NPEC_ETH | \ + IXP4XX_FEATURE_RESET_NPEA | \ + IXP4XX_FEATURE_RESET_NPEB | \ + IXP4XX_FEATURE_RESET_NPEC | \ + IXP4XX_FEATURE_PCI | \ + IXP4XX_FEATURE_UTOPIA_PHY_LIMIT | \ + IXP4XX_FEATURE_XSCALE_MAX_FREQ) + + +/* IXP43x/46x CPUs */ +#define IXP4XX_FEATURE_ECC_TIMESYNC (1 << 15) #define IXP4XX_FEATURE_USB_HOST (1 << 18) #define IXP4XX_FEATURE_NPEA_ETH (1 << 19) +#define IXP43X_FEATURE_MASK (IXP42X_FEATURE_MASK | \ + IXP4XX_FEATURE_ECC_TIMESYNC | \ + IXP4XX_FEATURE_USB_HOST | \ + IXP4XX_FEATURE_NPEA_ETH) + +/* IXP46x CPU (including IXP455) only */ #define IXP4XX_FEATURE_NPEB_ETH_1_TO_3 (1 << 20) #define IXP4XX_FEATURE_RSA (1 << 21) -#define IXP4XX_FEATURE_XSCALE_MAX_FREQ (3 << 22) -#define IXP4XX_FEATURE_RESERVED (0xFF << 24) - -#define IXP4XX_FEATURE_IXP46X_ONLY (IXP4XX_FEATURE_ECC_TIMESYNC | \ - IXP4XX_FEATURE_USB_HOST | \ - IXP4XX_FEATURE_NPEA_ETH | \ - IXP4XX_FEATURE_NPEB_ETH_1_TO_3 | \ - IXP4XX_FEATURE_RSA | \ - IXP4XX_FEATURE_XSCALE_MAX_FREQ) +#define IXP46X_FEATURE_MASK (IXP43X_FEATURE_MASK | \ + IXP4XX_FEATURE_NPEB_ETH_1_TO_3 | \ + IXP4XX_FEATURE_RSA) #endif -- GitLab From 7f3ccb5a22c945916390a9bd7101d0f553fa0fbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Ha=C5=82asa?= Date: Tue, 17 Mar 2009 14:39:30 +0100 Subject: [PATCH 3634/4982] IXP4xx: PCI ixp4xx_scan_bus() is __devinit. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Krzysztof HaÅ‚asa --- arch/arm/mach-ixp4xx/common-pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c index 2d0f09e9819..70afcfe5b88 100644 --- a/arch/arm/mach-ixp4xx/common-pci.c +++ b/arch/arm/mach-ixp4xx/common-pci.c @@ -501,7 +501,7 @@ int ixp4xx_setup(int nr, struct pci_sys_data *sys) return 1; } -struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys) +struct pci_bus * __devinit ixp4xx_scan_bus(int nr, struct pci_sys_data *sys) { return pci_scan_bus(sys->busnr, &ixp4xx_ops, sys); } -- GitLab From a6a80e1d8cf82b46a69f88e659da02749231eb36 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 17 Mar 2009 07:58:26 -0700 Subject: [PATCH 3635/4982] Fix potential fast PIT TSC calibration startup glitch During bootup, when we reprogram the PIT (programmable interval timer) to start counting down from 0xffff in order to use it for the fast TSC calibration, we should also make sure to delay a bit afterwards to allow the PIT hardware to actually start counting with the new value. That will happens at the next CLK pulse (1.193182 MHz), so the easiest way to do that is to just wait at least one microsecond after programming the new PIT counter value. We do that by just reading the counter value back once - which will take about 2us on PC hardware. Reported-and-tested-by: john stultz Signed-off-by: Linus Torvalds --- arch/x86/kernel/tsc.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 599e5816863..9e80207c96a 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -315,6 +315,15 @@ static unsigned long quick_pit_calibrate(void) outb(0xff, 0x42); outb(0xff, 0x42); + /* + * The PIT starts counting at the next edge, so we + * need to delay for a microsecond. The easiest way + * to do that is to just read back the 16-bit counter + * once from the PIT. + */ + inb(0x42); + inb(0x42); + if (pit_expect_msb(0xff)) { int i; u64 t1, t2, delta; -- GitLab From 97d759d3e86f9c7ced094352838e7e4d1cf8cddf Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 17 Mar 2009 14:59:34 +0000 Subject: [PATCH 3636/4982] solos: Reset device on unload, free pending skbs Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index eef920a9c44..1ff73049721 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -1206,10 +1206,28 @@ static void atm_remove(struct solos_card *card) for (i = 0; i < card->nr_ports; i++) { if (card->atmdev[i]) { + struct sk_buff *skb; + dev_info(&card->dev->dev, "Unregistering ATM device %d\n", card->atmdev[i]->number); sysfs_remove_group(&card->atmdev[i]->class_dev.kobj, &solos_attr_group); atm_dev_deregister(card->atmdev[i]); + + skb = card->rx_skb[i]; + if (skb) { + pci_unmap_single(card->dev, SKB_CB(skb)->dma_addr, + RX_DMA_SIZE, PCI_DMA_FROMDEVICE); + dev_kfree_skb(skb); + } + skb = card->tx_skb[i]; + if (skb) { + pci_unmap_single(card->dev, SKB_CB(skb)->dma_addr, + skb->len, PCI_DMA_TODEVICE); + dev_kfree_skb(skb); + } + while ((skb = skb_dequeue(&card->tx_queue[i]))) + dev_kfree_skb(skb); + } } } @@ -1217,13 +1235,23 @@ static void atm_remove(struct solos_card *card) static void fpga_remove(struct pci_dev *dev) { struct solos_card *card = pci_get_drvdata(dev); + + /* Disable IRQs */ + iowrite32(0, card->config_regs + IRQ_EN_ADDR); + + /* Reset FPGA */ + iowrite32(1, card->config_regs + FPGA_MODE); + (void)ioread32(card->config_regs + FPGA_MODE); atm_remove(card); - iowrite32(0, card->config_regs + IRQ_EN_ADDR); free_irq(dev->irq, card); tasklet_kill(&card->tlet); + /* Release device from reset */ + iowrite32(0, card->config_regs + FPGA_MODE); + (void)ioread32(card->config_regs + FPGA_MODE); + pci_iounmap(dev, card->buffers); pci_iounmap(dev, card->config_regs); -- GitLab From 0fc36aa52a602bfe2aeb7ded7e90b0fa70df24c2 Mon Sep 17 00:00:00 2001 From: Nathan Williams Date: Sat, 7 Feb 2009 10:19:13 +1100 Subject: [PATCH 3637/4982] solos: Automatically determine number of ports Signed-off-by: Nathan Williams Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 1ff73049721..6fe8f8fc855 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -1104,7 +1104,8 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) iowrite32(0xF0, card->config_regs + FLAGS_ADDR); } - card->nr_ports = 2; /* FIXME: Detect daughterboard */ + data32 = ioread32(card->config_regs + PORTS); + card->nr_ports = (data32 & 0x000000FF); pci_set_drvdata(dev, card); -- GitLab From 1329f4550f8ee141437f3b5f4db0f2add7639e29 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 17 Mar 2009 15:10:51 +0000 Subject: [PATCH 3638/4982] solos: Disable DMA until we have an FPGA update with it actually implemented. Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 6fe8f8fc855..bc3079d1787 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -1097,7 +1097,7 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) dev_info(&dev->dev, "Solos FPGA Version %d.%02d svn-%d\n", major_ver, minor_ver, fpga_ver); - if (fpga_ver > 27) + if (0 && fpga_ver > 27) card->using_dma = 1; else { /* Set RX empty flag for all ports */ -- GitLab From 9e8912e04e612b43897b4b722205408b92f423e5 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 17 Mar 2009 08:13:17 -0700 Subject: [PATCH 3639/4982] Fast TSC calibration: calculate proper frequency error bounds In order for ntpd to correctly synchronize the clocks, the frequency of the system clock must not be off by more than 500 ppm (or, put another way, 1:2000), or ntpd will end up giving up on trying to synchronize properly, and ends up reseting the clock in jumps instead. The fast TSC PIT calibration sometimes failed this test - it was assuming that the PIT reads always took about one microsecond each (2us for the two reads to get a 16-bit timer), and that calibrating TSC to the PIT over 15ms should thus be sufficient to get much closer than 500ppm (max 2us error on both sides giving 4us over 15ms: a 270 ppm error value). However, that assumption does not always hold: apparently some hardware is either very much slower at reading the PIT registers, or there was other noise causing at least one machine to get 700+ ppm errors. So instead of using a fixed 15ms timing loop, this changes the fast PIT calibration to read the TSC delta over the individual PIT timer reads, and use the result to calculate the error bars on the PIT read timing properly. We then successfully calibrate the TSC only if the maximum error bars fall below 500ppm. In the process, we also relax the timing to allow up to 25ms for the calibration, although it can happen much faster depending on hardware. Reported-and-tested-by: Jesper Krogh Cc: john stultz Cc: Thomas Gleixner Acked-by: Ingo Molnar Signed-off-by: Linus Torvalds --- arch/x86/kernel/tsc.c | 101 +++++++++++++++++++++++------------------- 1 file changed, 56 insertions(+), 45 deletions(-) diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 9e80207c96a..d5cebb52d45 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -273,30 +273,43 @@ static unsigned long pit_calibrate_tsc(u32 latch, unsigned long ms, int loopmin) * use the TSC value at the transitions to calculate a pretty * good value for the TSC frequencty. */ -static inline int pit_expect_msb(unsigned char val) +static inline int pit_expect_msb(unsigned char val, u64 *tscp, unsigned long *deltap) { - int count = 0; + int count; + u64 tsc = 0; for (count = 0; count < 50000; count++) { /* Ignore LSB */ inb(0x42); if (inb(0x42) != val) break; + tsc = get_cycles(); } - return count > 50; + *deltap = get_cycles() - tsc; + *tscp = tsc; + + /* + * We require _some_ success, but the quality control + * will be based on the error terms on the TSC values. + */ + return count > 5; } /* - * How many MSB values do we want to see? We aim for a - * 15ms calibration, which assuming a 2us counter read - * error should give us roughly 150 ppm precision for - * the calibration. + * How many MSB values do we want to see? We aim for + * a maximum error rate of 500ppm (in practice the + * real error is much smaller), but refuse to spend + * more than 25ms on it. */ -#define QUICK_PIT_MS 15 -#define QUICK_PIT_ITERATIONS (QUICK_PIT_MS * PIT_TICK_RATE / 1000 / 256) +#define MAX_QUICK_PIT_MS 25 +#define MAX_QUICK_PIT_ITERATIONS (MAX_QUICK_PIT_MS * PIT_TICK_RATE / 1000 / 256) static unsigned long quick_pit_calibrate(void) { + int i; + u64 tsc, delta; + unsigned long d1, d2; + /* Set the Gate high, disable speaker */ outb((inb(0x61) & ~0x02) | 0x01, 0x61); @@ -324,45 +337,43 @@ static unsigned long quick_pit_calibrate(void) inb(0x42); inb(0x42); - if (pit_expect_msb(0xff)) { - int i; - u64 t1, t2, delta; - unsigned char expect = 0xfe; - - t1 = get_cycles(); - for (i = 0; i < QUICK_PIT_ITERATIONS; i++, expect--) { - if (!pit_expect_msb(expect)) - goto failed; + if (pit_expect_msb(0xff, &tsc, &d1)) { + for (i = 1; i <= MAX_QUICK_PIT_ITERATIONS; i++) { + if (!pit_expect_msb(0xff-i, &delta, &d2)) + break; + + /* + * Iterate until the error is less than 500 ppm + */ + delta -= tsc; + if (d1+d2 < delta >> 11) + goto success; } - t2 = get_cycles(); - - /* - * Make sure we can rely on the second TSC timestamp: - */ - if (!pit_expect_msb(expect)) - goto failed; - - /* - * Ok, if we get here, then we've seen the - * MSB of the PIT decrement QUICK_PIT_ITERATIONS - * times, and each MSB had many hits, so we never - * had any sudden jumps. - * - * As a result, we can depend on there not being - * any odd delays anywhere, and the TSC reads are - * reliable. - * - * kHz = ticks / time-in-seconds / 1000; - * kHz = (t2 - t1) / (QPI * 256 / PIT_TICK_RATE) / 1000 - * kHz = ((t2 - t1) * PIT_TICK_RATE) / (QPI * 256 * 1000) - */ - delta = (t2 - t1)*PIT_TICK_RATE; - do_div(delta, QUICK_PIT_ITERATIONS*256*1000); - printk("Fast TSC calibration using PIT\n"); - return delta; } -failed: + printk("Fast TSC calibration failed\n"); return 0; + +success: + /* + * Ok, if we get here, then we've seen the + * MSB of the PIT decrement 'i' times, and the + * error has shrunk to less than 500 ppm. + * + * As a result, we can depend on there not being + * any odd delays anywhere, and the TSC reads are + * reliable (within the error). We also adjust the + * delta to the middle of the error bars, just + * because it looks nicer. + * + * kHz = ticks / time-in-seconds / 1000; + * kHz = (t2 - t1) / (I * 256 / PIT_TICK_RATE) / 1000 + * kHz = ((t2 - t1) * PIT_TICK_RATE) / (I * 256 * 1000) + */ + delta += (long)(d2 - d1)/2; + delta *= PIT_TICK_RATE; + do_div(delta, i*256*1000); + printk("Fast TSC calibration using PIT\n"); + return delta; } /** -- GitLab From c9310920e6e7ae0a5c0accbd57d34c194cb31780 Mon Sep 17 00:00:00 2001 From: Piotr Ziecik Date: Tue, 17 Mar 2009 09:17:50 -0600 Subject: [PATCH 3640/4982] powerpc/5200: Enable CPU_FTR_NEED_COHERENT for MPC52xx BestComm, a DMA engine in MPC52xx SoC, requires snooping when CPU caches are enabled to work properly. Adding CPU_FTR_NEED_COHERENT fixes NFS problems on MPC52xx machines introduced by 'powerpc/mm: Fix handling of _PAGE_COHERENT in BAT setup code' (sha1: 4c456a67f501b8b15542c7c21c28812bf88f484b). Signed-off-by: Piotr Ziecik Signed-off-by: Grant Likely --- arch/powerpc/include/asm/cputable.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index 4911104791c..21172badd70 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h @@ -241,9 +241,11 @@ extern const char *powerpc_base_platform; /* We need to mark all pages as being coherent if we're SMP or we have a * 74[45]x and an MPC107 host bridge. Also 83xx and PowerQUICC II * require it for PCI "streaming/prefetch" to work properly. + * This is also required by 52xx family. */ #if defined(CONFIG_SMP) || defined(CONFIG_MPC10X_BRIDGE) \ - || defined(CONFIG_PPC_83xx) || defined(CONFIG_8260) + || defined(CONFIG_PPC_83xx) || defined(CONFIG_8260) \ + || defined(CONFIG_PPC_MPC52xx) #define CPU_FTR_COMMON CPU_FTR_NEED_COHERENT #else #define CPU_FTR_COMMON 0 -- GitLab From a4bd6a93c3f14691c8a29e53eb04dc734b27f0db Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Tue, 17 Mar 2009 09:17:50 -0600 Subject: [PATCH 3641/4982] powerpc/mm: Respect _PAGE_COHERENT on classic ppc32 SW Since we now set _PAGE_COHERENT in the Linux PTE we shouldn't be clearing it out before we setup the SW TLB. Today all the SW TLB machines (603/e300) that we support are non-SMP, however there are some errata on some devices that cause us to set _PAGE_COHERENT via CPU_FTR_NEED_COHERENT. Signed-off-by: Kumar Gala Signed-off-by: Grant Likely --- arch/powerpc/kernel/head_32.S | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S index a1c4cfd25de..7db2e42d97a 100644 --- a/arch/powerpc/kernel/head_32.S +++ b/arch/powerpc/kernel/head_32.S @@ -511,7 +511,7 @@ InstructionTLBMiss: and r1,r1,r2 /* writable if _RW and _DIRTY */ rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */ rlwimi r3,r3,32-1,31,31 /* _PAGE_USER -> PP lsb */ - ori r1,r1,0xe14 /* clear out reserved bits and M */ + ori r1,r1,0xe04 /* clear out reserved bits */ andc r1,r3,r1 /* PP = user? (rw&dirty? 2: 3): 0 */ mtspr SPRN_RPA,r1 mfspr r3,SPRN_IMISS @@ -585,7 +585,7 @@ DataLoadTLBMiss: and r1,r1,r2 /* writable if _RW and _DIRTY */ rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */ rlwimi r3,r3,32-1,31,31 /* _PAGE_USER -> PP lsb */ - ori r1,r1,0xe14 /* clear out reserved bits and M */ + ori r1,r1,0xe04 /* clear out reserved bits */ andc r1,r3,r1 /* PP = user? (rw&dirty? 2: 3): 0 */ mtspr SPRN_RPA,r1 mfspr r3,SPRN_DMISS @@ -653,7 +653,7 @@ DataStoreTLBMiss: stw r3,0(r2) /* update PTE (accessed/dirty bits) */ /* Convert linux-style PTE to low word of PPC-style PTE */ rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */ - li r1,0xe15 /* clear out reserved bits and M */ + li r1,0xe05 /* clear out reserved bits & PP lsb */ andc r1,r3,r1 /* PP = user? 2: 0 */ mtspr SPRN_RPA,r1 mfspr r3,SPRN_DMISS -- GitLab From 30390880debce4a68fd23e87a787f27609e4bf4a Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 16 Mar 2009 18:57:22 -0400 Subject: [PATCH 3642/4982] prevent boosting kprobes on exception address Don't boost at the addresses which are listed on exception tables, because major page fault will occur on those addresses. In that case, kprobes can not ensure that when instruction buffer can be freed since some processes will sleep on the buffer. kprobes-ia64 already has same check. Signed-off-by: Masami Hiramatsu Cc: Ananth N Mavinakayanahalli Signed-off-by: Linus Torvalds --- arch/x86/kernel/kprobes.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c index e948b28a5a9..4558dd3918c 100644 --- a/arch/x86/kernel/kprobes.c +++ b/arch/x86/kernel/kprobes.c @@ -193,6 +193,9 @@ static int __kprobes can_boost(kprobe_opcode_t *opcodes) kprobe_opcode_t opcode; kprobe_opcode_t *orig_opcodes = opcodes; + if (search_exception_tables(opcodes)) + return 0; /* Page fault may occur on this address. */ + retry: if (opcodes - orig_opcodes > MAX_INSN_SIZE - 1) return 0; -- GitLab From 323a59613e5be6094c93261486de48a08d3a53f2 Mon Sep 17 00:00:00 2001 From: Dmitry Artamonow Date: Fri, 13 Mar 2009 01:03:49 +0100 Subject: [PATCH 3643/4982] ALSA: drop outdated and broken sa11xx-uda1341 driver It depends on L3 support from 2.4 kernel (CONFIG_L3) that never got merged into mainline. Since there's no way to use it on any of supported machines (iPaq h3100 or h3600), better drop it for now. It can be reimplemented later using ASoC infrastructure (there's already a driver for uda1341 codec in mainline, so only CPU and machine parts need to be written). Signed-off-by: Dmitry Artamonow Cc: Russell King Signed-off-by: Takashi Iwai --- include/sound/uda1341.h | 126 ----- sound/arm/Kconfig | 11 - sound/arm/Makefile | 3 - sound/arm/sa11xx-uda1341.c | 984 ------------------------------------- sound/i2c/Makefile | 2 - sound/i2c/l3/Makefile | 8 - sound/i2c/l3/uda1341.c | 935 ----------------------------------- 7 files changed, 2069 deletions(-) delete mode 100644 include/sound/uda1341.h delete mode 100644 sound/arm/sa11xx-uda1341.c delete mode 100644 sound/i2c/l3/Makefile delete mode 100644 sound/i2c/l3/uda1341.c diff --git a/include/sound/uda1341.h b/include/sound/uda1341.h deleted file mode 100644 index 110d5dc3a2b..00000000000 --- a/include/sound/uda1341.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * linux/include/linux/l3/uda1341.h - * - * Philips UDA1341 mixer device driver for ALSA - * - * Copyright (c) 2002 Tomas Kasparek - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License. - * - * History: - * - * 2002-03-13 Tomas Kasparek Initial release - based on uda1341.h from OSS - * 2002-03-30 Tomas Kasparek Proc filesystem support, complete mixer and DSP - * features support - */ - -#define UDA1341_ALSA_NAME "snd-uda1341" - -/* - * Default rate set after inicialization - */ -#define AUDIO_RATE_DEFAULT 44100 - -/* - * UDA1341 L3 address and command types - */ -#define UDA1341_L3ADDR 5 -#define UDA1341_DATA0 (UDA1341_L3ADDR << 2 | 0) -#define UDA1341_DATA1 (UDA1341_L3ADDR << 2 | 1) -#define UDA1341_STATUS (UDA1341_L3ADDR << 2 | 2) - -enum uda1341_onoff { - OFF=0, - ON, -}; - -enum uda1341_format { - I2S=0, - LSB16, - LSB18, - LSB20, - MSB, - LSB16MSB, - LSB18MSB, - LSB20MSB, -}; - -enum uda1341_fs { - F512=0, - F384, - F256, - Funused, -}; - -enum uda1341_peak { - BEFORE=0, - AFTER, -}; - -enum uda1341_filter { - FLAT=0, - MIN, - MIN2, - MAX, -}; - -enum uda1341_mixer { - DOUBLE, - LINE, - MIC, - MIXER, -}; - -enum uda1341_deemp { - NONE, - D32, - D44, - D48, -}; - -enum uda1341_config { - CMD_READ_REG = 0, - CMD_RESET, - CMD_FS, - CMD_FORMAT, - CMD_OGAIN, - CMD_IGAIN, - CMD_DAC, - CMD_ADC, - CMD_VOLUME, - CMD_BASS, - CMD_TREBBLE, - CMD_PEAK, - CMD_DEEMP, - CMD_MUTE, - CMD_FILTER, - CMD_CH1, - CMD_CH2, - CMD_MIC, - CMD_MIXER, - CMD_AGC, - CMD_IG, - CMD_AGC_TIME, - CMD_AGC_LEVEL, -#ifdef CONFIG_PM - CMD_SUSPEND, - CMD_RESUME, -#endif - CMD_LAST, -}; - -enum write_through { - //used in update_bits (write_cfg) to avoid l3_write - just update local copy of regs. - REGS_ONLY=0, - //update local regs and write value to uda1341 - do l3_write - FLUSH, -}; - -int __init snd_chip_uda1341_mixer_new(struct snd_card *card, struct l3_client **clnt); - -/* - * Local variables: - * indent-tabs-mode: t - * End: - */ diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig index f8e6de48d81..885683a3b0b 100644 --- a/sound/arm/Kconfig +++ b/sound/arm/Kconfig @@ -11,17 +11,6 @@ menuconfig SND_ARM if SND_ARM -config SND_SA11XX_UDA1341 - tristate "SA11xx UDA1341TS driver (iPaq H3600)" - depends on ARCH_SA1100 && L3 - select SND_PCM - help - Say Y here if you have a Compaq iPaq H3x00 handheld computer - and want to use its Philips UDA 1341 audio chip. - - To compile this driver as a module, choose M here: the module - will be called snd-sa11xx-uda1341. - config SND_ARMAACI tristate "ARM PrimeCell PL041 AC Link support" depends on ARM_AMBA diff --git a/sound/arm/Makefile b/sound/arm/Makefile index 2054de11de8..5a549ed6c8a 100644 --- a/sound/arm/Makefile +++ b/sound/arm/Makefile @@ -2,9 +2,6 @@ # Makefile for ALSA # -obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-sa11xx-uda1341.o -snd-sa11xx-uda1341-objs := sa11xx-uda1341.o - obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o snd-aaci-objs := aaci.o devdma.o diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c deleted file mode 100644 index 7101d3d8bae..00000000000 --- a/sound/arm/sa11xx-uda1341.c +++ /dev/null @@ -1,984 +0,0 @@ -/* - * Driver for Philips UDA1341TS on Compaq iPAQ H3600 soundcard - * Copyright (C) 2002 Tomas Kasparek - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License. - * - * History: - * - * 2002-03-13 Tomas Kasparek initial release - based on h3600-uda1341.c from OSS - * 2002-03-20 Tomas Kasparek playback over ALSA is working - * 2002-03-28 Tomas Kasparek playback over OSS emulation is working - * 2002-03-29 Tomas Kasparek basic capture is working (native ALSA) - * 2002-03-29 Tomas Kasparek capture is working (OSS emulation) - * 2002-04-04 Tomas Kasparek better rates handling (allow non-standard rates) - * 2003-02-14 Brian Avery fixed full duplex mode, other updates - * 2003-02-20 Tomas Kasparek merged updates by Brian (except HAL) - * 2003-04-19 Jaroslav Kysela recoded DMA stuff to follow 2.4.18rmk3-hh24 kernel - * working suspend and resume - * 2003-04-28 Tomas Kasparek updated work by Jaroslav to compile it under 2.5.x again - * merged HAL layer (patches from Brian) - */ - -/*************************************************************************************************** -* -* To understand what Alsa Drivers should be doing look at "Writing an Alsa Driver" by Takashi Iwai -* available in the Alsa doc section on the website -* -* A few notes to make things clearer. The UDA1341 is hooked up to Serial port 4 on the SA1100. -* We are using SSP mode to talk to the UDA1341. The UDA1341 bit & wordselect clocks are generated -* by this UART. Unfortunately, the clock only runs if the transmit buffer has something in it. -* So, if we are just recording, we feed the transmit DMA stream a bunch of 0x0000 so that the -* transmit buffer is full and the clock keeps going. The zeroes come from FLUSH_BASE_PHYS which -* is a mem loc that always decodes to 0's w/ no off chip access. -* -* Some alsa terminology: -* frame => num_channels * sample_size e.g stereo 16 bit is 2 * 16 = 32 bytes -* period => the least number of bytes that will generate an interrupt e.g. we have a 1024 byte -* buffer and 4 periods in the runtime structure this means we'll get an int every 256 -* bytes or 4 times per buffer. -* A number of the sizes are in frames rather than bytes, use frames_to_bytes and -* bytes_to_frames to convert. The easiest way to tell the units is to look at the -* type i.e. runtime-> buffer_size is in frames and its type is snd_pcm_uframes_t -* -* Notes about the pointer fxn: -* The pointer fxn needs to return the offset into the dma buffer in frames. -* Interrupts must be blocked before calling the dma_get_pos fxn to avoid race with interrupts. -* -* Notes about pause/resume -* Implementing this would be complicated so it's skipped. The problem case is: -* A full duplex connection is going, then play is paused. At this point you need to start xmitting -* 0's to keep the record active which means you cant just freeze the dma and resume it later you'd -* need to save off the dma info, and restore it properly on a resume. Yeach! -* -* Notes about transfer methods: -* The async write calls fail. I probably need to implement something else to support them? -* -***************************************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_PM -#include -#endif - -#include -#include -#include -#include - -#include -#include -#include - -#include - -#undef DEBUG_MODE -#undef DEBUG_FUNCTION_NAMES -#include - -/* - * FIXME: Is this enough as autodetection of 2.4.X-rmkY-hhZ kernels? - * We use DMA stuff from 2.4.18-rmk3-hh24 here to be able to compile this - * module for Familiar 0.6.1 - */ - -/* {{{ Type definitions */ - -MODULE_AUTHOR("Tomas Kasparek "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("SA1100/SA1111 + UDA1341TS driver for ALSA"); -MODULE_SUPPORTED_DEVICE("{{UDA1341,iPAQ H3600 UDA1341TS}}"); - -static char *id; /* ID for this card */ - -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for SA1100/SA1111 + UDA1341TS soundcard."); - -struct audio_stream { - char *id; /* identification string */ - int stream_id; /* numeric identification */ - dma_device_t dma_dev; /* device identifier for DMA */ -#ifdef HH_VERSION - dmach_t dmach; /* dma channel identification */ -#else - dma_regs_t *dma_regs; /* points to our DMA registers */ -#endif - unsigned int active:1; /* we are using this stream for transfer now */ - int period; /* current transfer period */ - int periods; /* current count of periods registerd in the DMA engine */ - int tx_spin; /* are we recoding - flag used to do DMA trans. for sync */ - unsigned int old_offset; - spinlock_t dma_lock; /* for locking in DMA operations (see dma-sa1100.c in the kernel) */ - struct snd_pcm_substream *stream; -}; - -struct sa11xx_uda1341 { - struct snd_card *card; - struct l3_client *uda1341; - struct snd_pcm *pcm; - long samplerate; - struct audio_stream s[2]; /* playback & capture */ -}; - -static unsigned int rates[] = { - 8000, 10666, 10985, 14647, - 16000, 21970, 22050, 24000, - 29400, 32000, 44100, 48000, -}; - -static struct snd_pcm_hw_constraint_list hw_constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, -}; - -static struct platform_device *device; - -/* }}} */ - -/* {{{ Clock and sample rate stuff */ - -/* - * Stop-gap solution until rest of hh.org HAL stuff is merged. - */ -#define GPIO_H3600_CLK_SET0 GPIO_GPIO (12) -#define GPIO_H3600_CLK_SET1 GPIO_GPIO (13) - -#ifdef CONFIG_SA1100_H3XXX -#define clr_sa11xx_uda1341_egpio(x) clr_h3600_egpio(x) -#define set_sa11xx_uda1341_egpio(x) set_h3600_egpio(x) -#else -#error This driver could serve H3x00 handhelds only! -#endif - -static void sa11xx_uda1341_set_audio_clock(long val) -{ - switch (val) { - case 24000: case 32000: case 48000: /* 00: 12.288 MHz */ - GPCR = GPIO_H3600_CLK_SET0 | GPIO_H3600_CLK_SET1; - break; - - case 22050: case 29400: case 44100: /* 01: 11.2896 MHz */ - GPSR = GPIO_H3600_CLK_SET0; - GPCR = GPIO_H3600_CLK_SET1; - break; - - case 8000: case 10666: case 16000: /* 10: 4.096 MHz */ - GPCR = GPIO_H3600_CLK_SET0; - GPSR = GPIO_H3600_CLK_SET1; - break; - - case 10985: case 14647: case 21970: /* 11: 5.6245 MHz */ - GPSR = GPIO_H3600_CLK_SET0 | GPIO_H3600_CLK_SET1; - break; - } -} - -static void sa11xx_uda1341_set_samplerate(struct sa11xx_uda1341 *sa11xx_uda1341, long rate) -{ - int clk_div = 0; - int clk=0; - - /* We don't want to mess with clocks when frames are in flight */ - Ser4SSCR0 &= ~SSCR0_SSE; - /* wait for any frame to complete */ - udelay(125); - - /* - * We have the following clock sources: - * 4.096 MHz, 5.6245 MHz, 11.2896 MHz, 12.288 MHz - * Those can be divided either by 256, 384 or 512. - * This makes up 12 combinations for the following samplerates... - */ - if (rate >= 48000) - rate = 48000; - else if (rate >= 44100) - rate = 44100; - else if (rate >= 32000) - rate = 32000; - else if (rate >= 29400) - rate = 29400; - else if (rate >= 24000) - rate = 24000; - else if (rate >= 22050) - rate = 22050; - else if (rate >= 21970) - rate = 21970; - else if (rate >= 16000) - rate = 16000; - else if (rate >= 14647) - rate = 14647; - else if (rate >= 10985) - rate = 10985; - else if (rate >= 10666) - rate = 10666; - else - rate = 8000; - - /* Set the external clock generator */ - - sa11xx_uda1341_set_audio_clock(rate); - - /* Select the clock divisor */ - switch (rate) { - case 8000: - case 10985: - case 22050: - case 24000: - clk = F512; - clk_div = SSCR0_SerClkDiv(16); - break; - case 16000: - case 21970: - case 44100: - case 48000: - clk = F256; - clk_div = SSCR0_SerClkDiv(8); - break; - case 10666: - case 14647: - case 29400: - case 32000: - clk = F384; - clk_div = SSCR0_SerClkDiv(12); - break; - } - - /* FMT setting should be moved away when other FMTs are added (FIXME) */ - l3_command(sa11xx_uda1341->uda1341, CMD_FORMAT, (void *)LSB16); - - l3_command(sa11xx_uda1341->uda1341, CMD_FS, (void *)clk); - Ser4SSCR0 = (Ser4SSCR0 & ~0xff00) + clk_div + SSCR0_SSE; - sa11xx_uda1341->samplerate = rate; -} - -/* }}} */ - -/* {{{ HW init and shutdown */ - -static void sa11xx_uda1341_audio_init(struct sa11xx_uda1341 *sa11xx_uda1341) -{ - unsigned long flags; - - /* Setup DMA stuff */ - sa11xx_uda1341->s[SNDRV_PCM_STREAM_PLAYBACK].id = "UDA1341 out"; - sa11xx_uda1341->s[SNDRV_PCM_STREAM_PLAYBACK].stream_id = SNDRV_PCM_STREAM_PLAYBACK; - sa11xx_uda1341->s[SNDRV_PCM_STREAM_PLAYBACK].dma_dev = DMA_Ser4SSPWr; - - sa11xx_uda1341->s[SNDRV_PCM_STREAM_CAPTURE].id = "UDA1341 in"; - sa11xx_uda1341->s[SNDRV_PCM_STREAM_CAPTURE].stream_id = SNDRV_PCM_STREAM_CAPTURE; - sa11xx_uda1341->s[SNDRV_PCM_STREAM_CAPTURE].dma_dev = DMA_Ser4SSPRd; - - /* Initialize the UDA1341 internal state */ - - /* Setup the uarts */ - local_irq_save(flags); - GAFR |= (GPIO_SSP_CLK); - GPDR &= ~(GPIO_SSP_CLK); - Ser4SSCR0 = 0; - Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI + SSCR0_SerClkDiv(8); - Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk; - Ser4SSCR0 |= SSCR0_SSE; - local_irq_restore(flags); - - /* Enable the audio power */ - - clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_CODEC_NRESET); - set_sa11xx_uda1341_egpio(IPAQ_EGPIO_AUDIO_ON); - set_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE); - - /* Wait for the UDA1341 to wake up */ - mdelay(1); //FIXME - was removed by Perex - Why? - - /* Initialize the UDA1341 internal state */ - l3_open(sa11xx_uda1341->uda1341); - - /* external clock configuration (after l3_open - regs must be initialized */ - sa11xx_uda1341_set_samplerate(sa11xx_uda1341, sa11xx_uda1341->samplerate); - - /* Wait for the UDA1341 to wake up */ - set_sa11xx_uda1341_egpio(IPAQ_EGPIO_CODEC_NRESET); - mdelay(1); - - /* make the left and right channels unswapped (flip the WS latch) */ - Ser4SSDR = 0; - - clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE); -} - -static void sa11xx_uda1341_audio_shutdown(struct sa11xx_uda1341 *sa11xx_uda1341) -{ - /* mute on */ - set_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE); - - /* disable the audio power and all signals leading to the audio chip */ - l3_close(sa11xx_uda1341->uda1341); - Ser4SSCR0 = 0; - clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_CODEC_NRESET); - - /* power off and mute off */ - /* FIXME - is muting off necesary??? */ - - clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_AUDIO_ON); - clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE); -} - -/* }}} */ - -/* {{{ DMA staff */ - -/* - * these are the address and sizes used to fill the xmit buffer - * so we can get a clock in record only mode - */ -#define FORCE_CLOCK_ADDR (dma_addr_t)FLUSH_BASE_PHYS -#define FORCE_CLOCK_SIZE 4096 // was 2048 - -// FIXME Why this value exactly - wrote comment -#define DMA_BUF_SIZE 8176 /* <= MAX_DMA_SIZE from asm/arch-sa1100/dma.h */ - -#ifdef HH_VERSION - -static int audio_dma_request(struct audio_stream *s, void (*callback)(void *, int)) -{ - int ret; - - ret = sa1100_request_dma(&s->dmach, s->id, s->dma_dev); - if (ret < 0) { - printk(KERN_ERR "unable to grab audio dma 0x%x\n", s->dma_dev); - return ret; - } - sa1100_dma_set_callback(s->dmach, callback); - return 0; -} - -static inline void audio_dma_free(struct audio_stream *s) -{ - sa1100_free_dma(s->dmach); - s->dmach = -1; -} - -#else - -static int audio_dma_request(struct audio_stream *s, void (*callback)(void *)) -{ - int ret; - - ret = sa1100_request_dma(s->dma_dev, s->id, callback, s, &s->dma_regs); - if (ret < 0) - printk(KERN_ERR "unable to grab audio dma 0x%x\n", s->dma_dev); - return ret; -} - -static void audio_dma_free(struct audio_stream *s) -{ - sa1100_free_dma(s->dma_regs); - s->dma_regs = 0; -} - -#endif - -static u_int audio_get_dma_pos(struct audio_stream *s) -{ - struct snd_pcm_substream *substream = s->stream; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int offset; - unsigned long flags; - dma_addr_t addr; - - // this must be called w/ interrupts locked out see dma-sa1100.c in the kernel - spin_lock_irqsave(&s->dma_lock, flags); -#ifdef HH_VERSION - sa1100_dma_get_current(s->dmach, NULL, &addr); -#else - addr = sa1100_get_dma_pos((s)->dma_regs); -#endif - offset = addr - runtime->dma_addr; - spin_unlock_irqrestore(&s->dma_lock, flags); - - offset = bytes_to_frames(runtime,offset); - if (offset >= runtime->buffer_size) - offset = 0; - - return offset; -} - -/* - * this stops the dma and clears the dma ptrs - */ -static void audio_stop_dma(struct audio_stream *s) -{ - unsigned long flags; - - spin_lock_irqsave(&s->dma_lock, flags); - s->active = 0; - s->period = 0; - /* this stops the dma channel and clears the buffer ptrs */ -#ifdef HH_VERSION - sa1100_dma_flush_all(s->dmach); -#else - sa1100_clear_dma(s->dma_regs); -#endif - spin_unlock_irqrestore(&s->dma_lock, flags); -} - -static void audio_process_dma(struct audio_stream *s) -{ - struct snd_pcm_substream *substream = s->stream; - struct snd_pcm_runtime *runtime; - unsigned int dma_size; - unsigned int offset; - int ret; - - /* we are requested to process synchronization DMA transfer */ - if (s->tx_spin) { - if (snd_BUG_ON(s->stream_id != SNDRV_PCM_STREAM_PLAYBACK)) - return; - /* fill the xmit dma buffers and return */ -#ifdef HH_VERSION - sa1100_dma_set_spin(s->dmach, FORCE_CLOCK_ADDR, FORCE_CLOCK_SIZE); -#else - while (1) { - ret = sa1100_start_dma(s->dma_regs, FORCE_CLOCK_ADDR, FORCE_CLOCK_SIZE); - if (ret) - return; - } -#endif - return; - } - - /* must be set here - only valid for running streams, not for forced_clock dma fills */ - runtime = substream->runtime; - while (s->active && s->periods < runtime->periods) { - dma_size = frames_to_bytes(runtime, runtime->period_size); - if (s->old_offset) { - /* a little trick, we need resume from old position */ - offset = frames_to_bytes(runtime, s->old_offset - 1); - s->old_offset = 0; - s->periods = 0; - s->period = offset / dma_size; - offset %= dma_size; - dma_size = dma_size - offset; - if (!dma_size) - continue; /* special case */ - } else { - offset = dma_size * s->period; - snd_BUG_ON(dma_size > DMA_BUF_SIZE); - } -#ifdef HH_VERSION - ret = sa1100_dma_queue_buffer(s->dmach, s, runtime->dma_addr + offset, dma_size); - if (ret) - return; //FIXME -#else - ret = sa1100_start_dma((s)->dma_regs, runtime->dma_addr + offset, dma_size); - if (ret) { - printk(KERN_ERR "audio_process_dma: cannot queue DMA buffer (%i)\n", ret); - return; - } -#endif - - s->period++; - s->period %= runtime->periods; - s->periods++; - } -} - -#ifdef HH_VERSION -static void audio_dma_callback(void *data, int size) -#else -static void audio_dma_callback(void *data) -#endif -{ - struct audio_stream *s = data; - - /* - * If we are getting a callback for an active stream then we inform - * the PCM middle layer we've finished a period - */ - if (s->active) - snd_pcm_period_elapsed(s->stream); - - spin_lock(&s->dma_lock); - if (!s->tx_spin && s->periods > 0) - s->periods--; - audio_process_dma(s); - spin_unlock(&s->dma_lock); -} - -/* }}} */ - -/* {{{ PCM setting */ - -/* {{{ trigger & timer */ - -static int snd_sa11xx_uda1341_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream); - int stream_id = substream->pstr->stream; - struct audio_stream *s = &chip->s[stream_id]; - struct audio_stream *s1 = &chip->s[stream_id ^ 1]; - int err = 0; - - /* note local interrupts are already disabled in the midlevel code */ - spin_lock(&s->dma_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - /* now we need to make sure a record only stream has a clock */ - if (stream_id == SNDRV_PCM_STREAM_CAPTURE && !s1->active) { - /* we need to force fill the xmit DMA with zeros */ - s1->tx_spin = 1; - audio_process_dma(s1); - } - /* this case is when you were recording then you turn on a - * playback stream so we stop (also clears it) the dma first, - * clear the sync flag and then we let it turned on - */ - else { - s->tx_spin = 0; - } - - /* requested stream startup */ - s->active = 1; - audio_process_dma(s); - break; - case SNDRV_PCM_TRIGGER_STOP: - /* requested stream shutdown */ - audio_stop_dma(s); - - /* - * now we need to make sure a record only stream has a clock - * so if we're stopping a playback with an active capture - * we need to turn the 0 fill dma on for the xmit side - */ - if (stream_id == SNDRV_PCM_STREAM_PLAYBACK && s1->active) { - /* we need to force fill the xmit DMA with zeros */ - s->tx_spin = 1; - audio_process_dma(s); - } - /* - * we killed a capture only stream, so we should also kill - * the zero fill transmit - */ - else { - if (s1->tx_spin) { - s1->tx_spin = 0; - audio_stop_dma(s1); - } - } - - break; - case SNDRV_PCM_TRIGGER_SUSPEND: - s->active = 0; -#ifdef HH_VERSION - sa1100_dma_stop(s->dmach); -#else - //FIXME - DMA API -#endif - s->old_offset = audio_get_dma_pos(s) + 1; -#ifdef HH_VERSION - sa1100_dma_flush_all(s->dmach); -#else - //FIXME - DMA API -#endif - s->periods = 0; - break; - case SNDRV_PCM_TRIGGER_RESUME: - s->active = 1; - s->tx_spin = 0; - audio_process_dma(s); - if (stream_id == SNDRV_PCM_STREAM_CAPTURE && !s1->active) { - s1->tx_spin = 1; - audio_process_dma(s1); - } - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: -#ifdef HH_VERSION - sa1100_dma_stop(s->dmach); -#else - //FIXME - DMA API -#endif - s->active = 0; - if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) { - if (s1->active) { - s->tx_spin = 1; - s->old_offset = audio_get_dma_pos(s) + 1; -#ifdef HH_VERSION - sa1100_dma_flush_all(s->dmach); -#else - //FIXME - DMA API -#endif - audio_process_dma(s); - } - } else { - if (s1->tx_spin) { - s1->tx_spin = 0; -#ifdef HH_VERSION - sa1100_dma_flush_all(s1->dmach); -#else - //FIXME - DMA API -#endif - } - } - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - s->active = 1; - if (s->old_offset) { - s->tx_spin = 0; - audio_process_dma(s); - break; - } - if (stream_id == SNDRV_PCM_STREAM_CAPTURE && !s1->active) { - s1->tx_spin = 1; - audio_process_dma(s1); - } -#ifdef HH_VERSION - sa1100_dma_resume(s->dmach); -#else - //FIXME - DMA API -#endif - break; - default: - err = -EINVAL; - break; - } - spin_unlock(&s->dma_lock); - return err; -} - -static int snd_sa11xx_uda1341_prepare(struct snd_pcm_substream *substream) -{ - struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct audio_stream *s = &chip->s[substream->pstr->stream]; - - /* set requested samplerate */ - sa11xx_uda1341_set_samplerate(chip, runtime->rate); - - /* set requestd format when available */ - /* set FMT here !!! FIXME */ - - s->period = 0; - s->periods = 0; - - return 0; -} - -static snd_pcm_uframes_t snd_sa11xx_uda1341_pointer(struct snd_pcm_substream *substream) -{ - struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream); - return audio_get_dma_pos(&chip->s[substream->pstr->stream]); -} - -/* }}} */ - -static struct snd_pcm_hardware snd_sa11xx_uda1341_capture = -{ - .info = (SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ - SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |\ - SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ - SNDRV_PCM_RATE_KNOT), - .rate_min = 8000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 64*1024, - .period_bytes_min = 64, - .period_bytes_max = DMA_BUF_SIZE, - .periods_min = 2, - .periods_max = 255, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_sa11xx_uda1341_playback = -{ - .info = (SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ - SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |\ - SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ - SNDRV_PCM_RATE_KNOT), - .rate_min = 8000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 64*1024, - .period_bytes_min = 64, - .period_bytes_max = DMA_BUF_SIZE, - .periods_min = 2, - .periods_max = 255, - .fifo_size = 0, -}; - -static int snd_card_sa11xx_uda1341_open(struct snd_pcm_substream *substream) -{ - struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int stream_id = substream->pstr->stream; - int err; - - chip->s[stream_id].stream = substream; - - if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) - runtime->hw = snd_sa11xx_uda1341_playback; - else - runtime->hw = snd_sa11xx_uda1341_capture; - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - if ((err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates)) < 0) - return err; - - return 0; -} - -static int snd_card_sa11xx_uda1341_close(struct snd_pcm_substream *substream) -{ - struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream); - - chip->s[substream->pstr->stream].stream = NULL; - return 0; -} - -/* {{{ HW params & free */ - -static int snd_sa11xx_uda1341_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static int snd_sa11xx_uda1341_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -/* }}} */ - -static struct snd_pcm_ops snd_card_sa11xx_uda1341_playback_ops = { - .open = snd_card_sa11xx_uda1341_open, - .close = snd_card_sa11xx_uda1341_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_sa11xx_uda1341_hw_params, - .hw_free = snd_sa11xx_uda1341_hw_free, - .prepare = snd_sa11xx_uda1341_prepare, - .trigger = snd_sa11xx_uda1341_trigger, - .pointer = snd_sa11xx_uda1341_pointer, -}; - -static struct snd_pcm_ops snd_card_sa11xx_uda1341_capture_ops = { - .open = snd_card_sa11xx_uda1341_open, - .close = snd_card_sa11xx_uda1341_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_sa11xx_uda1341_hw_params, - .hw_free = snd_sa11xx_uda1341_hw_free, - .prepare = snd_sa11xx_uda1341_prepare, - .trigger = snd_sa11xx_uda1341_trigger, - .pointer = snd_sa11xx_uda1341_pointer, -}; - -static int __init snd_card_sa11xx_uda1341_pcm(struct sa11xx_uda1341 *sa11xx_uda1341, int device) -{ - struct snd_pcm *pcm; - int err; - - if ((err = snd_pcm_new(sa11xx_uda1341->card, "UDA1341 PCM", device, 1, 1, &pcm)) < 0) - return err; - - /* - * this sets up our initial buffers and sets the dma_type to isa. - * isa works but I'm not sure why (or if) it's the right choice - * this may be too large, trying it for now - */ - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_isa_data(), - 64*1024, 64*1024); - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_sa11xx_uda1341_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_sa11xx_uda1341_capture_ops); - pcm->private_data = sa11xx_uda1341; - pcm->info_flags = 0; - strcpy(pcm->name, "UDA1341 PCM"); - - sa11xx_uda1341_audio_init(sa11xx_uda1341); - - /* setup DMA controller */ - audio_dma_request(&sa11xx_uda1341->s[SNDRV_PCM_STREAM_PLAYBACK], audio_dma_callback); - audio_dma_request(&sa11xx_uda1341->s[SNDRV_PCM_STREAM_CAPTURE], audio_dma_callback); - - sa11xx_uda1341->pcm = pcm; - - return 0; -} - -/* }}} */ - -/* {{{ module init & exit */ - -#ifdef CONFIG_PM - -static int snd_sa11xx_uda1341_suspend(struct platform_device *devptr, - pm_message_t state) -{ - struct snd_card *card = platform_get_drvdata(devptr); - struct sa11xx_uda1341 *chip = card->private_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm); -#ifdef HH_VERSION - sa1100_dma_sleep(chip->s[SNDRV_PCM_STREAM_PLAYBACK].dmach); - sa1100_dma_sleep(chip->s[SNDRV_PCM_STREAM_CAPTURE].dmach); -#else - //FIXME -#endif - l3_command(chip->uda1341, CMD_SUSPEND, NULL); - sa11xx_uda1341_audio_shutdown(chip); - - return 0; -} - -static int snd_sa11xx_uda1341_resume(struct platform_device *devptr) -{ - struct snd_card *card = platform_get_drvdata(devptr); - struct sa11xx_uda1341 *chip = card->private_data; - - sa11xx_uda1341_audio_init(chip); - l3_command(chip->uda1341, CMD_RESUME, NULL); -#ifdef HH_VERSION - sa1100_dma_wakeup(chip->s[SNDRV_PCM_STREAM_PLAYBACK].dmach); - sa1100_dma_wakeup(chip->s[SNDRV_PCM_STREAM_CAPTURE].dmach); -#else - //FIXME -#endif - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif /* COMFIG_PM */ - -void snd_sa11xx_uda1341_free(struct snd_card *card) -{ - struct sa11xx_uda1341 *chip = card->private_data; - - audio_dma_free(&chip->s[SNDRV_PCM_STREAM_PLAYBACK]); - audio_dma_free(&chip->s[SNDRV_PCM_STREAM_CAPTURE]); -} - -static int __devinit sa11xx_uda1341_probe(struct platform_device *devptr) -{ - int err; - struct snd_card *card; - struct sa11xx_uda1341 *chip; - - /* register the soundcard */ - err = snd_card_create(-1, id, THIS_MODULE, - sizeof(struct sa11xx_uda1341), &card); - if (err < 0) - return err; - - chip = card->private_data; - spin_lock_init(&chip->s[0].dma_lock); - spin_lock_init(&chip->s[1].dma_lock); - - card->private_free = snd_sa11xx_uda1341_free; - chip->card = card; - chip->samplerate = AUDIO_RATE_DEFAULT; - - // mixer - if ((err = snd_chip_uda1341_mixer_new(card, &chip->uda1341))) - goto nodev; - - // PCM - if ((err = snd_card_sa11xx_uda1341_pcm(chip, 0)) < 0) - goto nodev; - - strcpy(card->driver, "UDA1341"); - strcpy(card->shortname, "H3600 UDA1341TS"); - sprintf(card->longname, "Compaq iPAQ H3600 with Philips UDA1341TS"); - - snd_card_set_dev(card, &devptr->dev); - - if ((err = snd_card_register(card)) == 0) { - printk(KERN_INFO "iPAQ audio support initialized\n"); - platform_set_drvdata(devptr, card); - return 0; - } - - nodev: - snd_card_free(card); - return err; -} - -static int __devexit sa11xx_uda1341_remove(struct platform_device *devptr) -{ - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); - return 0; -} - -#define SA11XX_UDA1341_DRIVER "sa11xx_uda1341" - -static struct platform_driver sa11xx_uda1341_driver = { - .probe = sa11xx_uda1341_probe, - .remove = __devexit_p(sa11xx_uda1341_remove), -#ifdef CONFIG_PM - .suspend = snd_sa11xx_uda1341_suspend, - .resume = snd_sa11xx_uda1341_resume, -#endif - .driver = { - .name = SA11XX_UDA1341_DRIVER, - }, -}; - -static int __init sa11xx_uda1341_init(void) -{ - int err; - - if (!machine_is_h3xxx()) - return -ENODEV; - if ((err = platform_driver_register(&sa11xx_uda1341_driver)) < 0) - return err; - device = platform_device_register_simple(SA11XX_UDA1341_DRIVER, -1, NULL, 0); - if (!IS_ERR(device)) { - if (platform_get_drvdata(device)) - return 0; - platform_device_unregister(device); - err = -ENODEV; - } else - err = PTR_ERR(device); - platform_driver_unregister(&sa11xx_uda1341_driver); - return err; -} - -static void __exit sa11xx_uda1341_exit(void) -{ - platform_device_unregister(device); - platform_driver_unregister(&sa11xx_uda1341_driver); -} - -module_init(sa11xx_uda1341_init); -module_exit(sa11xx_uda1341_exit); - -/* }}} */ - -/* - * Local variables: - * indent-tabs-mode: t - * End: - */ diff --git a/sound/i2c/Makefile b/sound/i2c/Makefile index 37970666a45..36879bf8870 100644 --- a/sound/i2c/Makefile +++ b/sound/i2c/Makefile @@ -7,8 +7,6 @@ snd-i2c-objs := i2c.o snd-cs8427-objs := cs8427.o snd-tea6330t-objs := tea6330t.o -obj-$(CONFIG_L3) += l3/ - obj-$(CONFIG_SND) += other/ # Toplevel Module Dependency diff --git a/sound/i2c/l3/Makefile b/sound/i2c/l3/Makefile deleted file mode 100644 index 49455b8dcc0..00000000000 --- a/sound/i2c/l3/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Makefile for ALSA -# - -snd-uda1341-objs := uda1341.o - -# Module Dependency -obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-uda1341.o diff --git a/sound/i2c/l3/uda1341.c b/sound/i2c/l3/uda1341.c deleted file mode 100644 index 9840eb43648..00000000000 --- a/sound/i2c/l3/uda1341.c +++ /dev/null @@ -1,935 +0,0 @@ -/* - * Philips UDA1341 mixer device driver - * Copyright (c) 2002 Tomas Kasparek - * - * Portions are Copyright (C) 2000 Lernout & Hauspie Speech Products, N.V. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License. - * - * History: - * - * 2002-03-13 Tomas Kasparek initial release - based on uda1341.c from OSS - * 2002-03-28 Tomas Kasparek basic mixer is working (volume, bass, treble) - * 2002-03-30 Tomas Kasparek proc filesystem support, complete mixer and DSP - * features support - * 2002-04-12 Tomas Kasparek proc interface update, code cleanup - * 2002-05-12 Tomas Kasparek another code cleanup - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include - -#include - -/* {{{ HW regs definition */ - -#define STAT0 0x00 -#define STAT1 0x80 -#define STAT_MASK 0x80 - -#define DATA0_0 0x00 -#define DATA0_1 0x40 -#define DATA0_2 0x80 -#define DATA_MASK 0xc0 - -#define IS_DATA0(x) ((x) >= data0_0 && (x) <= data0_2) -#define IS_DATA1(x) ((x) == data1) -#define IS_STATUS(x) ((x) == stat0 || (x) == stat1) -#define IS_EXTEND(x) ((x) >= ext0 && (x) <= ext6) - -/* }}} */ - - -static const char *peak_names[] = { - "before", - "after", -}; - -static const char *filter_names[] = { - "flat", - "min", - "min", - "max", -}; - -static const char *mixer_names[] = { - "double differential", - "input channel 1 (line in)", - "input channel 2 (microphone)", - "digital mixer", -}; - -static const char *deemp_names[] = { - "none", - "32 kHz", - "44.1 kHz", - "48 kHz", -}; - -enum uda1341_regs_names { - stat0, - stat1, - data0_0, - data0_1, - data0_2, - data1, - ext0, - ext1, - ext2, - empty, - ext4, - ext5, - ext6, - uda1341_reg_last, -}; - -static const char *uda1341_reg_names[] = { - "stat 0 ", - "stat 1 ", - "data 00", - "data 01", - "data 02", - "data 1 ", - "ext 0", - "ext 1", - "ext 2", - "empty", - "ext 4", - "ext 5", - "ext 6", -}; - -static const int uda1341_enum_items[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2, //peak - before/after - 4, //deemp - none/32/44.1/48 - 0, - 4, //filter - flat/min/min/max - 0, 0, 0, - 4, //mixer - differ/line/mic/mixer - 0, 0, 0, 0, 0, -}; - -static const char ** uda1341_enum_names[] = { - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - peak_names, //peak - before/after - deemp_names, //deemp - none/32/44.1/48 - NULL, - filter_names, //filter - flat/min/min/max - NULL, NULL, NULL, - mixer_names, //mixer - differ/line/mic/mixer - NULL, NULL, NULL, NULL, NULL, -}; - -typedef int uda1341_cfg[CMD_LAST]; - -struct uda1341 { - int (*write) (struct l3_client *uda1341, unsigned short reg, unsigned short val); - int (*read) (struct l3_client *uda1341, unsigned short reg); - unsigned char regs[uda1341_reg_last]; - int active; - spinlock_t reg_lock; - struct snd_card *card; - uda1341_cfg cfg; -#ifdef CONFIG_PM - unsigned char suspend_regs[uda1341_reg_last]; - uda1341_cfg suspend_cfg; -#endif -}; - -/* transfer 8bit integer into string with binary representation */ -static void int2str_bin8(uint8_t val, char *buf) -{ - const int size = sizeof(val) * 8; - int i; - - for (i= 0; i < size; i++){ - *(buf++) = (val >> (size - 1)) ? '1' : '0'; - val <<= 1; - } - *buf = '\0'; //end the string with zero -} - -/* {{{ HW manipulation routines */ - -static int snd_uda1341_codec_write(struct l3_client *clnt, unsigned short reg, unsigned short val) -{ - struct uda1341 *uda = clnt->driver_data; - unsigned char buf[2] = { 0xc0, 0xe0 }; // for EXT addressing - int err = 0; - - uda->regs[reg] = val; - - if (uda->active) { - if (IS_DATA0(reg)) { - err = l3_write(clnt, UDA1341_DATA0, (const unsigned char *)&val, 1); - } else if (IS_DATA1(reg)) { - err = l3_write(clnt, UDA1341_DATA1, (const unsigned char *)&val, 1); - } else if (IS_STATUS(reg)) { - err = l3_write(clnt, UDA1341_STATUS, (const unsigned char *)&val, 1); - } else if (IS_EXTEND(reg)) { - buf[0] |= (reg - ext0) & 0x7; //EXT address - buf[1] |= val; //EXT data - err = l3_write(clnt, UDA1341_DATA0, (const unsigned char *)buf, 2); - } - } else - printk(KERN_ERR "UDA1341 codec not active!\n"); - return err; -} - -static int snd_uda1341_codec_read(struct l3_client *clnt, unsigned short reg) -{ - unsigned char val; - int err; - - err = l3_read(clnt, reg, &val, 1); - if (err == 1) - // use just 6bits - the rest is address of the reg - return val & 63; - return err < 0 ? err : -EIO; -} - -static inline int snd_uda1341_valid_reg(struct l3_client *clnt, unsigned short reg) -{ - return reg < uda1341_reg_last; -} - -static int snd_uda1341_update_bits(struct l3_client *clnt, unsigned short reg, - unsigned short mask, unsigned short shift, - unsigned short value, int flush) -{ - int change; - unsigned short old, new; - struct uda1341 *uda = clnt->driver_data; - -#if 0 - printk(KERN_DEBUG "update_bits: reg: %s mask: %d shift: %d val: %d\n", - uda1341_reg_names[reg], mask, shift, value); -#endif - - if (!snd_uda1341_valid_reg(clnt, reg)) - return -EINVAL; - spin_lock(&uda->reg_lock); - old = uda->regs[reg]; - new = (old & ~(mask << shift)) | (value << shift); - change = old != new; - if (change) { - if (flush) uda->write(clnt, reg, new); - uda->regs[reg] = new; - } - spin_unlock(&uda->reg_lock); - return change; -} - -static int snd_uda1341_cfg_write(struct l3_client *clnt, unsigned short what, - unsigned short value, int flush) -{ - struct uda1341 *uda = clnt->driver_data; - int ret = 0; -#ifdef CONFIG_PM - int reg; -#endif - -#if 0 - printk(KERN_DEBUG "cfg_write what: %d value: %d\n", what, value); -#endif - - uda->cfg[what] = value; - - switch(what) { - case CMD_RESET: - ret = snd_uda1341_update_bits(clnt, data0_2, 1, 2, 1, flush); // MUTE - ret = snd_uda1341_update_bits(clnt, stat0, 1, 6, 1, flush); // RESET - ret = snd_uda1341_update_bits(clnt, stat0, 1, 6, 0, flush); // RESTORE - uda->cfg[CMD_RESET]=0; - break; - case CMD_FS: - ret = snd_uda1341_update_bits(clnt, stat0, 3, 4, value, flush); - break; - case CMD_FORMAT: - ret = snd_uda1341_update_bits(clnt, stat0, 7, 1, value, flush); - break; - case CMD_OGAIN: - ret = snd_uda1341_update_bits(clnt, stat1, 1, 6, value, flush); - break; - case CMD_IGAIN: - ret = snd_uda1341_update_bits(clnt, stat1, 1, 5, value, flush); - break; - case CMD_DAC: - ret = snd_uda1341_update_bits(clnt, stat1, 1, 0, value, flush); - break; - case CMD_ADC: - ret = snd_uda1341_update_bits(clnt, stat1, 1, 1, value, flush); - break; - case CMD_VOLUME: - ret = snd_uda1341_update_bits(clnt, data0_0, 63, 0, value, flush); - break; - case CMD_BASS: - ret = snd_uda1341_update_bits(clnt, data0_1, 15, 2, value, flush); - break; - case CMD_TREBBLE: - ret = snd_uda1341_update_bits(clnt, data0_1, 3, 0, value, flush); - break; - case CMD_PEAK: - ret = snd_uda1341_update_bits(clnt, data0_2, 1, 5, value, flush); - break; - case CMD_DEEMP: - ret = snd_uda1341_update_bits(clnt, data0_2, 3, 3, value, flush); - break; - case CMD_MUTE: - ret = snd_uda1341_update_bits(clnt, data0_2, 1, 2, value, flush); - break; - case CMD_FILTER: - ret = snd_uda1341_update_bits(clnt, data0_2, 3, 0, value, flush); - break; - case CMD_CH1: - ret = snd_uda1341_update_bits(clnt, ext0, 31, 0, value, flush); - break; - case CMD_CH2: - ret = snd_uda1341_update_bits(clnt, ext1, 31, 0, value, flush); - break; - case CMD_MIC: - ret = snd_uda1341_update_bits(clnt, ext2, 7, 2, value, flush); - break; - case CMD_MIXER: - ret = snd_uda1341_update_bits(clnt, ext2, 3, 0, value, flush); - break; - case CMD_AGC: - ret = snd_uda1341_update_bits(clnt, ext4, 1, 4, value, flush); - break; - case CMD_IG: - ret = snd_uda1341_update_bits(clnt, ext4, 3, 0, value & 0x3, flush); - ret = snd_uda1341_update_bits(clnt, ext5, 31, 0, value >> 2, flush); - break; - case CMD_AGC_TIME: - ret = snd_uda1341_update_bits(clnt, ext6, 7, 2, value, flush); - break; - case CMD_AGC_LEVEL: - ret = snd_uda1341_update_bits(clnt, ext6, 3, 0, value, flush); - break; -#ifdef CONFIG_PM - case CMD_SUSPEND: - for (reg = stat0; reg < uda1341_reg_last; reg++) - uda->suspend_regs[reg] = uda->regs[reg]; - for (reg = 0; reg < CMD_LAST; reg++) - uda->suspend_cfg[reg] = uda->cfg[reg]; - break; - case CMD_RESUME: - for (reg = stat0; reg < uda1341_reg_last; reg++) - snd_uda1341_codec_write(clnt, reg, uda->suspend_regs[reg]); - for (reg = 0; reg < CMD_LAST; reg++) - uda->cfg[reg] = uda->suspend_cfg[reg]; - break; -#endif - default: - ret = -EINVAL; - break; - } - - if (!uda->active) - printk(KERN_ERR "UDA1341 codec not active!\n"); - return ret; -} - -/* }}} */ - -/* {{{ Proc interface */ -#ifdef CONFIG_PROC_FS - -static const char *format_names[] = { - "I2S-bus", - "LSB 16bits", - "LSB 18bits", - "LSB 20bits", - "MSB", - "in LSB 16bits/out MSB", - "in LSB 18bits/out MSB", - "in LSB 20bits/out MSB", -}; - -static const char *fs_names[] = { - "512*fs", - "384*fs", - "256*fs", - "Unused - bad value!", -}; - -static const char* bass_values[][16] = { - {"0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", - "0 dB", "0 dB", "0 dB", "0 dB", "undefined", }, //flat - {"0 dB", "2 dB", "4 dB", "6 dB", "8 dB", "10 dB", "12 dB", "14 dB", "16 dB", "18 dB", "18 dB", - "18 dB", "18 dB", "18 dB", "18 dB", "undefined",}, // min - {"0 dB", "2 dB", "4 dB", "6 dB", "8 dB", "10 dB", "12 dB", "14 dB", "16 dB", "18 dB", "18 dB", - "18 dB", "18 dB", "18 dB", "18 dB", "undefined",}, // min - {"0 dB", "2 dB", "4 dB", "6 dB", "8 dB", "10 dB", "12 dB", "14 dB", "16 dB", "18 dB", "20 dB", - "22 dB", "24 dB", "24 dB", "24 dB", "undefined",}, // max -}; - -static const char *mic_sens_value[] = { - "-3 dB", "0 dB", "3 dB", "9 dB", "15 dB", "21 dB", "27 dB", "not used", -}; - -static const unsigned short AGC_atime[] = { - 11, 16, 11, 16, 21, 11, 16, 21, -}; - -static const unsigned short AGC_dtime[] = { - 100, 100, 200, 200, 200, 400, 400, 400, -}; - -static const char *AGC_level[] = { - "-9.0", "-11.5", "-15.0", "-17.5", -}; - -static const char *ig_small_value[] = { - "-3.0", "-2.5", "-2.0", "-1.5", "-1.0", "-0.5", -}; - -/* - * this was computed as peak_value[i] = pow((63-i)*1.42,1.013) - * - * UDA1341 datasheet on page 21: Peak value (dB) = (Peak level - 63.5)*5*log2 - * There is an table with these values [level]=value: [3]=-90.31, [7]=-84.29 - * [61]=-2.78, [62] = -1.48, [63] = 0.0 - * I tried to compute it, but using but even using logarithm with base either 10 or 2 - * i was'n able to get values in the table from the formula. So I constructed another - * formula (see above) to interpolate the values as good as possible. If there is some - * mistake, please contact me on tomas.kasparek@seznam.cz. Thanks. - * UDA1341TS datasheet is available at: - * http://www-us9.semiconductors.com/acrobat/datasheets/UDA1341TS_3.pdf - */ -static const char *peak_value[] = { - "-INF dB", "N.A.", "N.A", "90.31 dB", "N.A.", "N.A.", "N.A.", "-84.29 dB", - "-82.65 dB", "-81.13 dB", "-79.61 dB", "-78.09 dB", "-76.57 dB", "-75.05 dB", "-73.53 dB", - "-72.01 dB", "-70.49 dB", "-68.97 dB", "-67.45 dB", "-65.93 dB", "-64.41 dB", "-62.90 dB", - "-61.38 dB", "-59.86 dB", "-58.35 dB", "-56.83 dB", "-55.32 dB", "-53.80 dB", "-52.29 dB", - "-50.78 dB", "-49.26 dB", "-47.75 dB", "-46.24 dB", "-44.73 dB", "-43.22 dB", "-41.71 dB", - "-40.20 dB", "-38.69 dB", "-37.19 dB", "-35.68 dB", "-34.17 dB", "-32.67 dB", "-31.17 dB", - "-29.66 dB", "-28.16 dB", "-26.66 dB", "-25.16 dB", "-23.66 dB", "-22.16 dB", "-20.67 dB", - "-19.17 dB", "-17.68 dB", "-16.19 dB", "-14.70 dB", "-13.21 dB", "-11.72 dB", "-10.24 dB", - "-8.76 dB", "-7.28 dB", "-5.81 dB", "-4.34 dB", "-2.88 dB", "-1.43 dB", "0.00 dB", -}; - -static void snd_uda1341_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct l3_client *clnt = entry->private_data; - struct uda1341 *uda = clnt->driver_data; - int peak; - - peak = snd_uda1341_codec_read(clnt, UDA1341_DATA1); - if (peak < 0) - peak = 0; - - snd_iprintf(buffer, "%s\n\n", uda->card->longname); - - // for information about computed values see UDA1341TS datasheet pages 15 - 21 - snd_iprintf(buffer, "DAC power : %s\n", uda->cfg[CMD_DAC] ? "on" : "off"); - snd_iprintf(buffer, "ADC power : %s\n", uda->cfg[CMD_ADC] ? "on" : "off"); - snd_iprintf(buffer, "Clock frequency : %s\n", fs_names[uda->cfg[CMD_FS]]); - snd_iprintf(buffer, "Data format : %s\n\n", format_names[uda->cfg[CMD_FORMAT]]); - - snd_iprintf(buffer, "Filter mode : %s\n", filter_names[uda->cfg[CMD_FILTER]]); - snd_iprintf(buffer, "Mixer mode : %s\n", mixer_names[uda->cfg[CMD_MIXER]]); - snd_iprintf(buffer, "De-emphasis : %s\n", deemp_names[uda->cfg[CMD_DEEMP]]); - snd_iprintf(buffer, "Peak detection pos. : %s\n", uda->cfg[CMD_PEAK] ? "after" : "before"); - snd_iprintf(buffer, "Peak value : %s\n\n", peak_value[peak]); - - snd_iprintf(buffer, "Automatic Gain Ctrl : %s\n", uda->cfg[CMD_AGC] ? "on" : "off"); - snd_iprintf(buffer, "AGC attack time : %d ms\n", AGC_atime[uda->cfg[CMD_AGC_TIME]]); - snd_iprintf(buffer, "AGC decay time : %d ms\n", AGC_dtime[uda->cfg[CMD_AGC_TIME]]); - snd_iprintf(buffer, "AGC output level : %s dB\n\n", AGC_level[uda->cfg[CMD_AGC_LEVEL]]); - - snd_iprintf(buffer, "Mute : %s\n", uda->cfg[CMD_MUTE] ? "on" : "off"); - - if (uda->cfg[CMD_VOLUME] == 0) - snd_iprintf(buffer, "Volume : 0 dB\n"); - else if (uda->cfg[CMD_VOLUME] < 62) - snd_iprintf(buffer, "Volume : %d dB\n", -1*uda->cfg[CMD_VOLUME] +1); - else - snd_iprintf(buffer, "Volume : -INF dB\n"); - snd_iprintf(buffer, "Bass : %s\n", bass_values[uda->cfg[CMD_FILTER]][uda->cfg[CMD_BASS]]); - snd_iprintf(buffer, "Trebble : %d dB\n", uda->cfg[CMD_FILTER] ? 2*uda->cfg[CMD_TREBBLE] : 0); - snd_iprintf(buffer, "Input Gain (6dB) : %s\n", uda->cfg[CMD_IGAIN] ? "on" : "off"); - snd_iprintf(buffer, "Output Gain (6dB) : %s\n", uda->cfg[CMD_OGAIN] ? "on" : "off"); - snd_iprintf(buffer, "Mic sensitivity : %s\n", mic_sens_value[uda->cfg[CMD_MIC]]); - - - if(uda->cfg[CMD_CH1] < 31) - snd_iprintf(buffer, "Mixer gain channel 1: -%d.%c dB\n", - ((uda->cfg[CMD_CH1] >> 1) * 3) + (uda->cfg[CMD_CH1] & 1), - uda->cfg[CMD_CH1] & 1 ? '5' : '0'); - else - snd_iprintf(buffer, "Mixer gain channel 1: -INF dB\n"); - if(uda->cfg[CMD_CH2] < 31) - snd_iprintf(buffer, "Mixer gain channel 2: -%d.%c dB\n", - ((uda->cfg[CMD_CH2] >> 1) * 3) + (uda->cfg[CMD_CH2] & 1), - uda->cfg[CMD_CH2] & 1 ? '5' : '0'); - else - snd_iprintf(buffer, "Mixer gain channel 2: -INF dB\n"); - - if(uda->cfg[CMD_IG] > 5) - snd_iprintf(buffer, "Input Amp. Gain ch 2: %d.%c dB\n", - (uda->cfg[CMD_IG] >> 1) -3, uda->cfg[CMD_IG] & 1 ? '5' : '0'); - else - snd_iprintf(buffer, "Input Amp. Gain ch 2: %s dB\n", ig_small_value[uda->cfg[CMD_IG]]); -} - -static void snd_uda1341_proc_regs_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct l3_client *clnt = entry->private_data; - struct uda1341 *uda = clnt->driver_data; - int reg; - char buf[12]; - - for (reg = 0; reg < uda1341_reg_last; reg ++) { - if (reg == empty) - continue; - int2str_bin8(uda->regs[reg], buf); - snd_iprintf(buffer, "%s = %s\n", uda1341_reg_names[reg], buf); - } - - int2str_bin8(snd_uda1341_codec_read(clnt, UDA1341_DATA1), buf); - snd_iprintf(buffer, "DATA1 = %s\n", buf); -} -#endif /* CONFIG_PROC_FS */ - -static void __devinit snd_uda1341_proc_init(struct snd_card *card, struct l3_client *clnt) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(card, "uda1341", &entry)) - snd_info_set_text_ops(entry, clnt, snd_uda1341_proc_read); - if (! snd_card_proc_new(card, "uda1341-regs", &entry)) - snd_info_set_text_ops(entry, clnt, snd_uda1341_proc_regs_read); -} - -/* }}} */ - -/* {{{ Mixer controls setting */ - -/* {{{ UDA1341 single functions */ - -#define UDA1341_SINGLE(xname, where, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_uda1341_info_single, \ - .get = snd_uda1341_get_single, .put = snd_uda1341_put_single, \ - .private_value = where | (reg << 5) | (shift << 9) | (mask << 12) | (invert << 18) \ -} - -static int snd_uda1341_info_single(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 12) & 63; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_uda1341_get_single(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct l3_client *clnt = snd_kcontrol_chip(kcontrol); - struct uda1341 *uda = clnt->driver_data; - int where = kcontrol->private_value & 31; - int mask = (kcontrol->private_value >> 12) & 63; - int invert = (kcontrol->private_value >> 18) & 1; - - ucontrol->value.integer.value[0] = uda->cfg[where]; - if (invert) - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - - return 0; -} - -static int snd_uda1341_put_single(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct l3_client *clnt = snd_kcontrol_chip(kcontrol); - struct uda1341 *uda = clnt->driver_data; - int where = kcontrol->private_value & 31; - int reg = (kcontrol->private_value >> 5) & 15; - int shift = (kcontrol->private_value >> 9) & 7; - int mask = (kcontrol->private_value >> 12) & 63; - int invert = (kcontrol->private_value >> 18) & 1; - unsigned short val; - - val = (ucontrol->value.integer.value[0] & mask); - if (invert) - val = mask - val; - - uda->cfg[where] = val; - return snd_uda1341_update_bits(clnt, reg, mask, shift, val, FLUSH); -} - -/* }}} */ - -/* {{{ UDA1341 enum functions */ - -#define UDA1341_ENUM(xname, where, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_uda1341_info_enum, \ - .get = snd_uda1341_get_enum, .put = snd_uda1341_put_enum, \ - .private_value = where | (reg << 5) | (shift << 9) | (mask << 12) | (invert << 18) \ -} - -static int snd_uda1341_info_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int where = kcontrol->private_value & 31; - const char **texts; - - // this register we don't handle this way - if (!uda1341_enum_items[where]) - return -EINVAL; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = uda1341_enum_items[where]; - - if (uinfo->value.enumerated.item >= uda1341_enum_items[where]) - uinfo->value.enumerated.item = uda1341_enum_items[where] - 1; - - texts = uda1341_enum_names[where]; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_uda1341_get_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct l3_client *clnt = snd_kcontrol_chip(kcontrol); - struct uda1341 *uda = clnt->driver_data; - int where = kcontrol->private_value & 31; - - ucontrol->value.enumerated.item[0] = uda->cfg[where]; - return 0; -} - -static int snd_uda1341_put_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct l3_client *clnt = snd_kcontrol_chip(kcontrol); - struct uda1341 *uda = clnt->driver_data; - int where = kcontrol->private_value & 31; - int reg = (kcontrol->private_value >> 5) & 15; - int shift = (kcontrol->private_value >> 9) & 7; - int mask = (kcontrol->private_value >> 12) & 63; - - uda->cfg[where] = (ucontrol->value.enumerated.item[0] & mask); - - return snd_uda1341_update_bits(clnt, reg, mask, shift, uda->cfg[where], FLUSH); -} - -/* }}} */ - -/* {{{ UDA1341 2regs functions */ - -#define UDA1341_2REGS(xname, where, reg_1, reg_2, shift_1, shift_2, mask_1, mask_2, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .info = snd_uda1341_info_2regs, \ - .get = snd_uda1341_get_2regs, .put = snd_uda1341_put_2regs, \ - .private_value = where | (reg_1 << 5) | (reg_2 << 9) | (shift_1 << 13) | (shift_2 << 16) | \ - (mask_1 << 19) | (mask_2 << 25) | (invert << 31) \ -} - - -static int snd_uda1341_info_2regs(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int mask_1 = (kcontrol->private_value >> 19) & 63; - int mask_2 = (kcontrol->private_value >> 25) & 63; - int mask; - - mask = (mask_2 + 1) * (mask_1 + 1) - 1; - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_uda1341_get_2regs(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct l3_client *clnt = snd_kcontrol_chip(kcontrol); - struct uda1341 *uda = clnt->driver_data; - int where = kcontrol->private_value & 31; - int mask_1 = (kcontrol->private_value >> 19) & 63; - int mask_2 = (kcontrol->private_value >> 25) & 63; - int invert = (kcontrol->private_value >> 31) & 1; - int mask; - - mask = (mask_2 + 1) * (mask_1 + 1) - 1; - - ucontrol->value.integer.value[0] = uda->cfg[where]; - if (invert) - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - return 0; -} - -static int snd_uda1341_put_2regs(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct l3_client *clnt = snd_kcontrol_chip(kcontrol); - struct uda1341 *uda = clnt->driver_data; - int where = kcontrol->private_value & 31; - int reg_1 = (kcontrol->private_value >> 5) & 15; - int reg_2 = (kcontrol->private_value >> 9) & 15; - int shift_1 = (kcontrol->private_value >> 13) & 7; - int shift_2 = (kcontrol->private_value >> 16) & 7; - int mask_1 = (kcontrol->private_value >> 19) & 63; - int mask_2 = (kcontrol->private_value >> 25) & 63; - int invert = (kcontrol->private_value >> 31) & 1; - int mask; - unsigned short val1, val2, val; - - val = ucontrol->value.integer.value[0]; - - mask = (mask_2 + 1) * (mask_1 + 1) - 1; - - val1 = val & mask_1; - val2 = (val / (mask_1 + 1)) & mask_2; - - if (invert) { - val1 = mask_1 - val1; - val2 = mask_2 - val2; - } - - uda->cfg[where] = invert ? mask - val : val; - - //FIXME - return value - snd_uda1341_update_bits(clnt, reg_1, mask_1, shift_1, val1, FLUSH); - return snd_uda1341_update_bits(clnt, reg_2, mask_2, shift_2, val2, FLUSH); -} - -/* }}} */ - -static struct snd_kcontrol_new snd_uda1341_controls[] = { - UDA1341_SINGLE("Master Playback Switch", CMD_MUTE, data0_2, 2, 1, 1), - UDA1341_SINGLE("Master Playback Volume", CMD_VOLUME, data0_0, 0, 63, 1), - - UDA1341_SINGLE("Bass Playback Volume", CMD_BASS, data0_1, 2, 15, 0), - UDA1341_SINGLE("Treble Playback Volume", CMD_TREBBLE, data0_1, 0, 3, 0), - - UDA1341_SINGLE("Input Gain Switch", CMD_IGAIN, stat1, 5, 1, 0), - UDA1341_SINGLE("Output Gain Switch", CMD_OGAIN, stat1, 6, 1, 0), - - UDA1341_SINGLE("Mixer Gain Channel 1 Volume", CMD_CH1, ext0, 0, 31, 1), - UDA1341_SINGLE("Mixer Gain Channel 2 Volume", CMD_CH2, ext1, 0, 31, 1), - - UDA1341_SINGLE("Mic Sensitivity Volume", CMD_MIC, ext2, 2, 7, 0), - - UDA1341_SINGLE("AGC Output Level", CMD_AGC_LEVEL, ext6, 0, 3, 0), - UDA1341_SINGLE("AGC Time Constant", CMD_AGC_TIME, ext6, 2, 7, 0), - UDA1341_SINGLE("AGC Time Constant Switch", CMD_AGC, ext4, 4, 1, 0), - - UDA1341_SINGLE("DAC Power", CMD_DAC, stat1, 0, 1, 0), - UDA1341_SINGLE("ADC Power", CMD_ADC, stat1, 1, 1, 0), - - UDA1341_ENUM("Peak detection", CMD_PEAK, data0_2, 5, 1, 0), - UDA1341_ENUM("De-emphasis", CMD_DEEMP, data0_2, 3, 3, 0), - UDA1341_ENUM("Mixer mode", CMD_MIXER, ext2, 0, 3, 0), - UDA1341_ENUM("Filter mode", CMD_FILTER, data0_2, 0, 3, 0), - - UDA1341_2REGS("Gain Input Amplifier Gain (channel 2)", CMD_IG, ext4, ext5, 0, 0, 3, 31, 0), -}; - -static void uda1341_free(struct l3_client *clnt) -{ - l3_detach_client(clnt); // calls kfree for driver_data (struct uda1341) - kfree(clnt); -} - -static int uda1341_dev_free(struct snd_device *device) -{ - struct l3_client *clnt = device->device_data; - uda1341_free(clnt); - return 0; -} - -int __init snd_chip_uda1341_mixer_new(struct snd_card *card, struct l3_client **clntp) -{ - static struct snd_device_ops ops = { - .dev_free = uda1341_dev_free, - }; - struct l3_client *clnt; - int idx, err; - - if (snd_BUG_ON(!card)) - return -EINVAL; - - clnt = kzalloc(sizeof(*clnt), GFP_KERNEL); - if (clnt == NULL) - return -ENOMEM; - - if ((err = l3_attach_client(clnt, "l3-bit-sa1100-gpio", UDA1341_ALSA_NAME))) { - kfree(clnt); - return err; - } - - for (idx = 0; idx < ARRAY_SIZE(snd_uda1341_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_uda1341_controls[idx], clnt))) < 0) { - uda1341_free(clnt); - return err; - } - } - - if ((err = snd_device_new(card, SNDRV_DEV_CODEC, clnt, &ops)) < 0) { - uda1341_free(clnt); - return err; - } - - *clntp = clnt; - strcpy(card->mixername, "UDA1341TS Mixer"); - ((struct uda1341 *)clnt->driver_data)->card = card; - - snd_uda1341_proc_init(card, clnt); - - return 0; -} - -/* }}} */ - -/* {{{ L3 operations */ - -static int uda1341_attach(struct l3_client *clnt) -{ - struct uda1341 *uda; - - uda = kzalloc(sizeof(*uda), 0, GFP_KERNEL); - if (!uda) - return -ENOMEM; - - /* init fixed parts of my copy of registers */ - uda->regs[stat0] = STAT0; - uda->regs[stat1] = STAT1; - - uda->regs[data0_0] = DATA0_0; - uda->regs[data0_1] = DATA0_1; - uda->regs[data0_2] = DATA0_2; - - uda->write = snd_uda1341_codec_write; - uda->read = snd_uda1341_codec_read; - - spin_lock_init(&uda->reg_lock); - - clnt->driver_data = uda; - return 0; -} - -static void uda1341_detach(struct l3_client *clnt) -{ - kfree(clnt->driver_data); -} - -static int -uda1341_command(struct l3_client *clnt, int cmd, void *arg) -{ - if (cmd != CMD_READ_REG) - return snd_uda1341_cfg_write(clnt, cmd, (int) arg, FLUSH); - - return snd_uda1341_codec_read(clnt, (int) arg); -} - -static int uda1341_open(struct l3_client *clnt) -{ - struct uda1341 *uda = clnt->driver_data; - - uda->active = 1; - - /* init default configuration */ - snd_uda1341_cfg_write(clnt, CMD_RESET, 0, REGS_ONLY); - snd_uda1341_cfg_write(clnt, CMD_FS, F256, FLUSH); // unknown state after reset - snd_uda1341_cfg_write(clnt, CMD_FORMAT, LSB16, FLUSH); // unknown state after reset - snd_uda1341_cfg_write(clnt, CMD_OGAIN, ON, FLUSH); // default off after reset - snd_uda1341_cfg_write(clnt, CMD_IGAIN, ON, FLUSH); // default off after reset - snd_uda1341_cfg_write(clnt, CMD_DAC, ON, FLUSH); // ??? default value after reset - snd_uda1341_cfg_write(clnt, CMD_ADC, ON, FLUSH); // ??? default value after reset - snd_uda1341_cfg_write(clnt, CMD_VOLUME, 20, FLUSH); // default 0dB after reset - snd_uda1341_cfg_write(clnt, CMD_BASS, 0, REGS_ONLY); // default value after reset - snd_uda1341_cfg_write(clnt, CMD_TREBBLE, 0, REGS_ONLY); // default value after reset - snd_uda1341_cfg_write(clnt, CMD_PEAK, AFTER, REGS_ONLY);// default value after reset - snd_uda1341_cfg_write(clnt, CMD_DEEMP, NONE, REGS_ONLY);// default value after reset - //at this moment should be QMUTED by h3600_audio_init - snd_uda1341_cfg_write(clnt, CMD_MUTE, OFF, REGS_ONLY); // default value after reset - snd_uda1341_cfg_write(clnt, CMD_FILTER, MAX, FLUSH); // defaul flat after reset - snd_uda1341_cfg_write(clnt, CMD_CH1, 31, FLUSH); // default value after reset - snd_uda1341_cfg_write(clnt, CMD_CH2, 4, FLUSH); // default value after reset - snd_uda1341_cfg_write(clnt, CMD_MIC, 4, FLUSH); // default 0dB after reset - snd_uda1341_cfg_write(clnt, CMD_MIXER, MIXER, FLUSH); // default doub.dif.mode - snd_uda1341_cfg_write(clnt, CMD_AGC, OFF, FLUSH); // default value after reset - snd_uda1341_cfg_write(clnt, CMD_IG, 0, FLUSH); // unknown state after reset - snd_uda1341_cfg_write(clnt, CMD_AGC_TIME, 0, FLUSH); // default value after reset - snd_uda1341_cfg_write(clnt, CMD_AGC_LEVEL, 0, FLUSH); // default value after reset - - return 0; -} - -static void uda1341_close(struct l3_client *clnt) -{ - struct uda1341 *uda = clnt->driver_data; - - uda->active = 0; -} - -/* }}} */ - -/* {{{ Module and L3 initialization */ - -static struct l3_ops uda1341_ops = { - .open = uda1341_open, - .command = uda1341_command, - .close = uda1341_close, -}; - -static struct l3_driver uda1341_driver = { - .name = UDA1341_ALSA_NAME, - .attach_client = uda1341_attach, - .detach_client = uda1341_detach, - .ops = &uda1341_ops, - .owner = THIS_MODULE, -}; - -static int __init uda1341_init(void) -{ - return l3_add_driver(&uda1341_driver); -} - -static void __exit uda1341_exit(void) -{ - l3_del_driver(&uda1341_driver); -} - -module_init(uda1341_init); -module_exit(uda1341_exit); - -MODULE_AUTHOR("Tomas Kasparek "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Philips UDA1341 CODEC driver for ALSA"); -MODULE_SUPPORTED_DEVICE("{{UDA1341,UDA1341TS}}"); - -EXPORT_SYMBOL(snd_chip_uda1341_mixer_new); - -/* }}} */ - -/* - * Local variables: - * indent-tabs-mode: t - * End: - */ -- GitLab From ee568b25ee9e160b32d1aef73d8b2ee9c05d34db Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 17 Mar 2009 10:02:35 -0700 Subject: [PATCH 3644/4982] Avoid 64-bit "switch()" statements on 32-bit architectures Commit ee6f779b9e0851e2f7da292a9f58e0095edf615a ("filp->f_pos not correctly updated in proc_task_readdir") changed the proc code to use filp->f_pos directly, rather than through a temporary variable. In the process, that caused the operations to be done on the full 64 bits, even though the offset is never that big. That's all fine and dandy per se, but for some unfathomable reason gcc generates absolutely horrid code when using 64-bit values in switch() statements. To the point of actually calling out to gcc helper functions like __cmpdi2 rather than just doing the trivial comparisons directly the way gcc does for normal compares. At which point we get link failures, because we really don't want to support that kind of crazy code. Fix this by just casting the f_pos value to "unsigned long", which is plenty big enough for /proc, and avoids the gcc code generation issue. Reported-by: Alexey Dobriyan Cc: Zhang Le Signed-off-by: Linus Torvalds --- fs/proc/base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index cc6ea2329e7..beaa0ce3b82 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -3082,7 +3082,7 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi goto out_no_task; retval = 0; - switch (filp->f_pos) { + switch ((unsigned long)filp->f_pos) { case 0: ino = inode->i_ino; if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) < 0) -- GitLab From 84f09f46b4ee9e4e9b6381f8af31817516d2091b Mon Sep 17 00:00:00 2001 From: Benny Halevy Date: Wed, 4 Mar 2009 23:05:35 +0200 Subject: [PATCH 3645/4982] NFSD: provide encode routine for OP_OPENATTR Although this operation is unsupported by our implementation we still need to provide an encode routine for it to merely encode its (error) status back in the compound reply. Thanks for Bill Baker at sun.com for testing with the Sun OpenSolaris' client, finding, and reporting this bug at Connectathon 2009. This bug was introduced in 2.6.27 Signed-off-by: Benny Halevy Cc: stable@kernel.org Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4xdr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index f65953be39c..9250067943d 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -2596,6 +2596,7 @@ static nfsd4_enc nfsd4_enc_ops[] = { [OP_LOOKUPP] = (nfsd4_enc)nfsd4_encode_noop, [OP_NVERIFY] = (nfsd4_enc)nfsd4_encode_noop, [OP_OPEN] = (nfsd4_enc)nfsd4_encode_open, + [OP_OPENATTR] = (nfsd4_enc)nfsd4_encode_noop, [OP_OPEN_CONFIRM] = (nfsd4_enc)nfsd4_encode_open_confirm, [OP_OPEN_DOWNGRADE] = (nfsd4_enc)nfsd4_encode_open_downgrade, [OP_PUTFH] = (nfsd4_enc)nfsd4_encode_noop, -- GitLab From 76a67ec6fb79ff3570dcb5342142c16098299911 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 16 Mar 2009 18:34:20 -0400 Subject: [PATCH 3646/4982] nfsd: nfsd should drop CAP_MKNOD for non-root Since creating a device node is normally an operation requiring special privilege, Igor Zhbanov points out that it is surprising (to say the least) that a client can, for example, create a device node on a filesystem exported with root_squash. So, make sure CAP_MKNOD is among the capabilities dropped when an nfsd thread handles a request from a non-root user. Reported-by: Igor Zhbanov Cc: stable@kernel.org Signed-off-by: J. Bruce Fields --- include/linux/capability.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/linux/capability.h b/include/linux/capability.h index 1b987255613..4864a43b2b4 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -393,8 +393,10 @@ struct cpu_vfs_cap_data { # define CAP_FULL_SET ((kernel_cap_t){{ ~0, ~0 }}) # define CAP_INIT_EFF_SET ((kernel_cap_t){{ ~CAP_TO_MASK(CAP_SETPCAP), ~0 }}) # define CAP_FS_SET ((kernel_cap_t){{ CAP_FS_MASK_B0, CAP_FS_MASK_B1 } }) -# define CAP_NFSD_SET ((kernel_cap_t){{ CAP_FS_MASK_B0|CAP_TO_MASK(CAP_SYS_RESOURCE), \ - CAP_FS_MASK_B1 } }) +# define CAP_NFSD_SET ((kernel_cap_t){{ CAP_FS_MASK_B0 \ + | CAP_TO_MASK(CAP_SYS_RESOURCE) \ + | CAP_TO_MASK(CAP_MKNOD), \ + CAP_FS_MASK_B1 } }) #endif /* _KERNEL_CAPABILITY_U32S != 2 */ -- GitLab From 2ffb4558194037133121e260022baa0d21590473 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 17 Mar 2009 13:10:52 -0700 Subject: [PATCH 3647/4982] gro: Fix vlan/netpoll check again Jarek Poplawski pointed out that my previous fix is broken for VLAN+netpoll as if netpoll is enabled we'd end up in the normal receive path instead of the VLAN receive path. This patch fixes it by calling the VLAN receive hook. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/8021q/vlan_core.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 6227248597c..654e45f5719 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -79,9 +79,6 @@ static int vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp, { struct sk_buff *p; - if (netpoll_rx_on(skb)) - return GRO_NORMAL; - if (skb_bond_should_drop(skb)) goto drop; @@ -107,6 +104,9 @@ drop: int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, unsigned int vlan_tci, struct sk_buff *skb) { + if (netpoll_rx_on(skb)) + return vlan_hwaccel_receive_skb(skb, grp, vlan_tci); + skb_gro_reset_offset(skb); return napi_skb_finish(vlan_gro_common(napi, grp, vlan_tci, skb), skb); @@ -121,6 +121,9 @@ int vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, if (!skb) return NET_RX_DROP; + if (netpoll_rx_on(skb)) + return vlan_hwaccel_receive_skb(skb, grp, vlan_tci); + return napi_frags_finish(napi, skb, vlan_gro_common(napi, grp, vlan_tci, skb)); } -- GitLab From 303c6a0251852ecbdc5c15e466dcaff5971f7517 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 17 Mar 2009 13:11:29 -0700 Subject: [PATCH 3648/4982] gro: Fix legacy path napi_complete crash On the legacy netif_rx path, I incorrectly tried to optimise the napi_complete call by using __napi_complete before we reenable IRQs. This simply doesn't work since we need to flush the held GRO packets first. This patch fixes it by doing the obvious thing of reenabling IRQs first and then calling napi_complete. Reported-by: Frank Blaschka Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/core/dev.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index f1129706ce7..2565f6d1d66 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2588,9 +2588,9 @@ static int process_backlog(struct napi_struct *napi, int quota) local_irq_disable(); skb = __skb_dequeue(&queue->input_pkt_queue); if (!skb) { - __napi_complete(napi); local_irq_enable(); - break; + napi_complete(napi); + goto out; } local_irq_enable(); @@ -2599,6 +2599,7 @@ static int process_backlog(struct napi_struct *napi, int quota) napi_gro_flush(napi); +out: return work; } -- GitLab From bd257ed9f1d129b4e881f513a406b435c8852565 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Tue, 17 Mar 2009 13:14:22 -0700 Subject: [PATCH 3649/4982] netxen: fix firmware download warnings Fix following warnings, by using integer firmware types. drivers/net/netxen/netxen_nic_hw.c: In function 'netxen_load_firmware': drivers/net/netxen/netxen_nic_hw.c:1146: warning: comparison with string literal results in unspecified behavior drivers/net/netxen/netxen_nic_hw.c:1146: warning: comparison with string literal results in unspecified behavior drivers/net/netxen/netxen_nic_hw.c:1146: warning: comparison with string literal results in unspecified behavior drivers/net/netxen/netxen_nic_hw.c:1159: warning: comparison with string literal results in unspecified behavior drivers/net/netxen/netxen_nic_hw.c:1159: warning: comparison with string literal results in unspecified behavior drivers/net/netxen/netxen_nic_hw.c:1159: warning: comparison with string literal results in unspecified behavior Reported-by: Stephen Rothwell Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 6 +++--- drivers/net/netxen/netxen_nic_hw.c | 24 ++++++++++++------------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 2544129768f..78e6228937f 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -693,9 +693,9 @@ typedef enum { #define NX_BIOS_VERSION_OFFSET (NETXEN_USER_START+0x83c) #define NX_FW_MAGIC_OFFSET (NETXEN_BRDCFG_START+0x128) #define NX_FW_MIN_SIZE (0x3fffff) -#define NX_P2_MN_ROMIMAGE "nxromimg.bin" -#define NX_P3_CT_ROMIMAGE "nx3fwct.bin" -#define NX_P3_MN_ROMIMAGE "nx3fwmn.bin" +#define NX_P2_MN_ROMIMAGE 0 +#define NX_P3_CT_ROMIMAGE 1 +#define NX_P3_MN_ROMIMAGE 2 #define NETXEN_USER_START_OLD NETXEN_PXE_START /* for backward compatibility */ diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index c89c791e281..b24cfddd619 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -1130,21 +1130,21 @@ netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname, return 0; } +static char *fw_name[] = { "nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin" }; + int netxen_load_firmware(struct netxen_adapter *adapter) { u32 capability, flashed_ver; const struct firmware *fw; - char *fw_name = NULL; + int fw_type; struct pci_dev *pdev = adapter->pdev; int rc = 0; if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { - fw_name = NX_P2_MN_ROMIMAGE; + fw_type = NX_P2_MN_ROMIMAGE; goto request_fw; - } - - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { - fw_name = NX_P3_CT_ROMIMAGE; + } else { + fw_type = NX_P3_CT_ROMIMAGE; goto request_fw; } @@ -1157,15 +1157,15 @@ request_mn: adapter->hw_read_wx(adapter, NX_PEG_TUNE_CAPABILITY, &capability, 4); if (capability & NX_PEG_TUNE_MN_PRESENT) { - fw_name = NX_P3_MN_ROMIMAGE; + fw_type = NX_P3_MN_ROMIMAGE; goto request_fw; } } request_fw: - rc = request_firmware(&fw, fw_name, &pdev->dev); + rc = request_firmware(&fw, fw_name[fw_type], &pdev->dev); if (rc != 0) { - if (fw_name == NX_P3_CT_ROMIMAGE) { + if (fw_type == NX_P3_CT_ROMIMAGE) { msleep(1); goto request_mn; } @@ -1174,11 +1174,11 @@ request_fw: goto load_fw; } - rc = netxen_validate_firmware(adapter, fw_name, fw); + rc = netxen_validate_firmware(adapter, fw_name[fw_type], fw); if (rc != 0) { release_firmware(fw); - if (fw_name == NX_P3_CT_ROMIMAGE) { + if (fw_type == NX_P3_CT_ROMIMAGE) { msleep(1); goto request_mn; } @@ -1187,7 +1187,7 @@ request_fw: } load_fw: - rc = netxen_do_load_firmware(adapter, fw_name, fw); + rc = netxen_do_load_firmware(adapter, fw_name[fw_type], fw); if (fw) release_firmware(fw); -- GitLab From 5b10916ea0a62920204517e1c4ce14560b4f96ab Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 10 Mar 2009 20:42:55 -0700 Subject: [PATCH 3650/4982] USB: usbtmc: fix stupid bug in open() open() will never succeed, as we always return -ENODEV. Fix this obvious bug. Thanks to Jouni Ryno for reporting it. Reported-by: Jouni Ryno Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 0f5c05f6f9d..895a0983900 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -106,12 +106,13 @@ static int usbtmc_open(struct inode *inode, struct file *filp) { struct usb_interface *intf; struct usbtmc_device_data *data; - int retval = -ENODEV; + int retval = 0; intf = usb_find_interface(&usbtmc_driver, iminor(inode)); if (!intf) { printk(KERN_ERR KBUILD_MODNAME ": can not find device for minor %d", iminor(inode)); + retval = -ENODEV; goto exit; } -- GitLab From 228dd05dbfdd0fced8ab1a28ed73b500ba6bb0a6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Mar 2009 13:51:42 -0700 Subject: [PATCH 3651/4982] USB: usbtmc: add protocol 1 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver already supports the 1 protocol support, so just add it to the MODULE_DEVICE_TABLE entry so it properly picks up these devices. Thanks to Jouni Rynö for pointing this out. Reported-by: Jouni Ryno Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 895a0983900..c40a9b284cc 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -50,6 +50,7 @@ static struct usb_device_id usbtmc_devices[] = { { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 0), }, + { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 1), }, { 0, } /* terminating entry */ }; MODULE_DEVICE_TABLE(usb, usbtmc_devices); -- GitLab From 6ff10464096540e14d7575a72c50d0316d003714 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 9 Mar 2009 13:44:02 -0400 Subject: [PATCH 3652/4982] USB: usbfs: keep async URBs until the device file is closed The usbfs driver manages a list of completed asynchronous URBs. But it is too eager to free the entries on this list: destroy_async() gets called whenever an interface is unbound or a device is removed, and it deallocates the outstanding struct async entries for all URBs on that interface or device. This is wrong; the user program should be able to reap an URB any time after it has completed, regardless of whether or not the interface is still bound or the device is still present. This patch (as1222) moves the code for deallocating the completed list entries from destroy_async() to usbdev_release(). The outstanding entries won't be freed until the user program has closed the device file, thereby eliminating any possibility that the remaining URBs might still be reaped. This fixes a bug in which a program can hang in the USBDEVFS_REAPURB ioctl when the device is unplugged. Reported-and-tested-by: Martin Poupe Signed-off-by: Alan Stern Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 7513bb083c1..6585f527e38 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -359,11 +359,6 @@ static void destroy_async(struct dev_state *ps, struct list_head *list) spin_lock_irqsave(&ps->lock, flags); } spin_unlock_irqrestore(&ps->lock, flags); - as = async_getcompleted(ps); - while (as) { - free_async(as); - as = async_getcompleted(ps); - } } static void destroy_async_on_interface(struct dev_state *ps, @@ -643,6 +638,7 @@ static int usbdev_release(struct inode *inode, struct file *file) struct dev_state *ps = file->private_data; struct usb_device *dev = ps->dev; unsigned int ifnum; + struct async *as; usb_lock_device(dev); @@ -661,6 +657,12 @@ static int usbdev_release(struct inode *inode, struct file *file) usb_unlock_device(dev); usb_put_dev(dev); put_pid(ps->disc_pid); + + as = async_getcompleted(ps); + while (as) { + free_async(as); + as = async_getcompleted(ps); + } kfree(ps); return 0; } -- GitLab From 7f82b6dd7015aabca2fd55fb690248f742cd67f3 Mon Sep 17 00:00:00 2001 From: Axel Wachtler Date: Thu, 5 Mar 2009 14:09:22 -0800 Subject: [PATCH 3653/4982] USB: serial: add FTDI USB/Serial converter devices Add the following devices to the USB FTDI SIO device table: Bus 001 Device 009: ID 03eb:2109 Atmel Corp. http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4187 Bus 001 Device 008: ID 1cf1:0001 http://www.dresden-elektronik.de/shop/prod75.html Bus 001 Device 007: ID 1c1f:0004 http://www.dresden-elektronik.de/shop/prod64.html Signed-off-by: Axel Wachtler Signed-off-by: Robert Richter Signed-off-by: Andrew Morton Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 3 +++ drivers/usb/serial/ftdi_sio.h | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index f92f4d77337..f77339265ee 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -663,6 +663,9 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(ALTI2_VID, ALTI2_N3_PID) }, { USB_DEVICE(FTDI_VID, DIEBOLD_BCS_SE923_PID) }, { USB_DEVICE(FTDI_VID, FTDI_NDI_HUC_PID) }, + { USB_DEVICE(ATMEL_VID, STK541_PID) }, + { USB_DEVICE(DE_VID, STB_PID) }, + { USB_DEVICE(DE_VID, WHT_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index e300c840f8c..f2745edabcd 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -892,6 +892,19 @@ */ #define DIEBOLD_BCS_SE923_PID 0xfb99 +/* + * Atmel STK541 + */ +#define ATMEL_VID 0x03eb /* Vendor ID */ +#define STK541_PID 0x2109 /* Zigbee Controller */ + +/* + * Dresden Elektronic Sensor Terminal Board + */ +#define DE_VID 0x1cf1 /* Vendor ID */ +#define STB_PID 0x0001 /* Sensor Terminal Board */ +#define WHT_PID 0x0004 /* Wireless Handheld Terminal */ + /* * BmRequestType: 1100 0000b * bRequest: FTDI_E2_READ -- GitLab From b0d659002168146ec6b03d1ef062d8dcf05ff510 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 6 Mar 2009 14:07:43 -0800 Subject: [PATCH 3654/4982] USB: serial: ftdi: enable UART detection on gnICE JTAG adaptors blacklist interface0 Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu Signed-off-by: Andrew Morton Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 2 ++ drivers/usb/serial/ftdi_sio.h | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index f77339265ee..ae84c326a54 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -666,6 +666,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(ATMEL_VID, STK541_PID) }, { USB_DEVICE(DE_VID, STB_PID) }, { USB_DEVICE(DE_VID, WHT_PID) }, + { USB_DEVICE(ADI_VID, ADI_GNICE_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index f2745edabcd..daaf63db0b5 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -905,6 +905,13 @@ #define STB_PID 0x0001 /* Sensor Terminal Board */ #define WHT_PID 0x0004 /* Wireless Handheld Terminal */ +/* + * Blackfin gnICE JTAG + * http://docs.blackfin.uclinux.org/doku.php?id=hw:jtag:gnice + */ +#define ADI_VID 0x0456 +#define ADI_GNICE_PID 0xF000 + /* * BmRequestType: 1100 0000b * bRequest: FTDI_E2_READ -- GitLab From c6535668798b0644e1af5934c2aec0e912280449 Mon Sep 17 00:00:00 2001 From: "Robert M. Kenney" Date: Thu, 26 Feb 2009 14:58:39 -0500 Subject: [PATCH 3655/4982] USB: serial: new cp2101 device id From: Robert M. Kenney Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp2101.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 027f4b7dde8..9b4082b58c5 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -79,6 +79,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */ { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ + { USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */ { USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */ { USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */ { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ -- GitLab From c497e715f93d148d751c055401568684eea0bf6b Mon Sep 17 00:00:00 2001 From: Jan Dumon Date: Tue, 10 Mar 2009 17:29:47 +0100 Subject: [PATCH 3656/4982] USB: unusual_devs: Add support for GI 0431 SD-Card interface Enable the SD-Card interface on the GI 0431 HSUPA stick from Option. The unusual_devs.h entry is necessary because the device descriptor is vendor-specific. That prevents usb-storage from binding to it as an interface driver. T: Bus=07 Lev=01 Prnt=01 Port=01 Cnt=02 Dev#= 15 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=ff(vend.) Sub=ff Prot=ff MxPS=64 #Cfgs= 1 P: Vendor=0af0 ProdID=7501 Rev= 0.00 S: Manufacturer=Option N.V. S: Product=Globetrotter HSUPA Modem C:* #Ifs=11 Cfg#= 1 Atr=a0 MxPwr=500mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=hso E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=hso E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 6 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=hso E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=07(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 7 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=hso E: Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=08(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 8 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=89(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=09(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 9 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=hso E: Ad=8a(I) Atr=03(Int.) MxPS= 64 Ivl=2ms E: Ad=8b(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=0a(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#=10 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage E: Ad=0b(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8c(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms Signed-off-by: Jan Dumon Signed-off-by: Phil Dibowitz Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 6f59c8e510e..bfa8db0d8aa 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1390,6 +1390,16 @@ UNUSUAL_DEV( 0x0af0, 0x7401, 0x0000, 0x0000, US_SC_DEVICE, US_PR_DEVICE, NULL, 0 ), +/* Reported by Jan Dumon + * This device (wrongly) has a vendor-specific device descriptor. + * The entry is needed so usb-storage can bind to it's mass-storage + * interface as an interface driver */ +UNUSUAL_DEV( 0x0af0, 0x7501, 0x0000, 0x0000, + "Option", + "GI 0431 SD-Card", + US_SC_DEVICE, US_PR_DEVICE, NULL, + 0 ), + /* Reported by Ben Efros */ UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000, "Seagate", -- GitLab From eeafa64b7a4134da24d48ed944e48541f8171152 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 11 Mar 2009 21:47:36 +0100 Subject: [PATCH 3657/4982] USB: atm/cxacru, fix lock imbalance We do not hold mutex in one place in cxacru_cm, but unlock it on fail path. Fix this. Signed-off-by: Jiri Slaby Cc: Simon Arlott Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/cxacru.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 5ed4ae07bac..6789089e246 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -485,7 +485,7 @@ static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm, usb_err(instance->usbatm, "requested transfer size too large (%d, %d)\n", wbuflen, rbuflen); ret = -ENOMEM; - goto fail; + goto err; } mutex_lock(&instance->cm_serialize); @@ -565,6 +565,7 @@ static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm, dbg("cm %#x", cm); fail: mutex_unlock(&instance->cm_serialize); +err: return ret; } -- GitLab From 909b6c3fc20ea772dc63a03986d74148fcbb1a1d Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 11 Mar 2009 21:47:37 +0100 Subject: [PATCH 3658/4982] USB: image/mdc800, fix lock imbalance There is an omitted unlock in mdc800_usb_probe's fail path. Add it. Signed-off-by: Jiri Slaby Cc: Henning Zabel Signed-off-by: Greg Kroah-Hartman --- drivers/usb/image/mdc800.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c index 878c77ca086..972f20b3406 100644 --- a/drivers/usb/image/mdc800.c +++ b/drivers/usb/image/mdc800.c @@ -499,6 +499,7 @@ static int mdc800_usb_probe (struct usb_interface *intf, retval = usb_register_dev(intf, &mdc800_class); if (retval) { dev_err(&intf->dev, "Not able to get a minor for this device.\n"); + mutex_unlock(&mdc800->io_lock); return -ENODEV; } -- GitLab From 46c9844c4014be53c67622dcd3ba4302f36e9cac Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 11 Mar 2009 21:47:38 +0100 Subject: [PATCH 3659/4982] USB: misc/adutux, fix lock imbalance Don't unlock adutux_mutex when not held. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/adutux.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index 7b6922e08ed..20352654201 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -376,7 +376,7 @@ static int adu_release(struct inode *inode, struct file *file) if (dev->open_count <= 0) { dbg(1," %s : device not opened", __func__); retval = -ENODEV; - goto exit; + goto unlock; } adu_release_internal(dev); @@ -385,9 +385,9 @@ static int adu_release(struct inode *inode, struct file *file) if (!dev->open_count) /* ... and we're the last user */ adu_delete(dev); } - -exit: +unlock: mutex_unlock(&adutux_mutex); +exit: dbg(2," %s : leave, return value %d", __func__, retval); return retval; } -- GitLab From a08b43aee46ed4272ad7bee2c785edcf313339b3 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 11 Mar 2009 21:47:39 +0100 Subject: [PATCH 3660/4982] USB: misc/vstusb, fix lock imbalance Make sure we don't leak locked vstdev->lock in vstusb_write. Unlock properly on one fail path. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/vstusb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/misc/vstusb.c b/drivers/usb/misc/vstusb.c index 63dff9ba73c..f26ea8dc157 100644 --- a/drivers/usb/misc/vstusb.c +++ b/drivers/usb/misc/vstusb.c @@ -401,6 +401,7 @@ static ssize_t vstusb_write(struct file *file, const char __user *buffer, } if (copy_from_user(buf, buffer, count)) { + mutex_unlock(&vstdev->lock); dev_err(&dev->dev, "%s: can't copy_from_user\n", __func__); retval = -EFAULT; goto exit; -- GitLab From 49fa09215c03116449184057f062c6aea2f1d0b4 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 11 Mar 2009 21:47:40 +0100 Subject: [PATCH 3661/4982] USB: wusbcore/wa-xfer, fix lock imbalance Fix locking on one wa_urb_enqueue_b's fail path. There was omitted unlock. Signed-off-by: Jiri Slaby Cc: Inaky Perez-Gonzalez Signed-off-by: Greg Kroah-Hartman --- drivers/usb/wusbcore/wa-xfer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c index 238a96aee3a..613a5fc490d 100644 --- a/drivers/usb/wusbcore/wa-xfer.c +++ b/drivers/usb/wusbcore/wa-xfer.c @@ -921,8 +921,10 @@ static void wa_urb_enqueue_b(struct wa_xfer *xfer) result = -ENODEV; /* FIXME: segmentation broken -- kills DWA */ mutex_lock(&wusbhc->mutex); /* get a WUSB dev */ - if (urb->dev == NULL) + if (urb->dev == NULL) { + mutex_unlock(&wusbhc->mutex); goto error_dev_gone; + } wusb_dev = __wusb_dev_get_by_usb_dev(wusbhc, urb->dev); if (wusb_dev == NULL) { mutex_unlock(&wusbhc->mutex); -- GitLab From 9ea19b82f3126da4e47d6b94563a3c2cd586f6e2 Mon Sep 17 00:00:00 2001 From: Albert Pauw Date: Sun, 1 Mar 2009 09:37:52 +0100 Subject: [PATCH 3662/4982] USB: option.c: add ZTE 622 modem device Please consider this small patch for the usb option-card driver. This patch adds the ZTE 622 usb modem device. Signed-off-by: Albert Pauw Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index b7c132bded7..ddd0a0b7e1a 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -288,6 +288,7 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po /* ZTE PRODUCTS */ #define ZTE_VENDOR_ID 0x19d2 +#define ZTE_PRODUCT_MF622 0x0001 #define ZTE_PRODUCT_MF628 0x0015 #define ZTE_PRODUCT_MF626 0x0031 #define ZTE_PRODUCT_CDMA_TECH 0xfffe @@ -510,6 +511,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ { USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) }, + { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622) }, { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626) }, { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) }, { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) }, -- GitLab From 508db8c954d55ed30f870d2c24d741ba6269d13c Mon Sep 17 00:00:00 2001 From: Karsten Wiese Date: Thu, 26 Feb 2009 01:47:48 +0100 Subject: [PATCH 3663/4982] USB: EHCI: Fix isochronous URB leak ehci-hcd uses usb_get_urb() and usb_put_urb() in an unbalanced way causing isochronous URB's kref.counts incrementing once per usb_submit_urb() call. The culprit is *usb being set to NULL when usb_put_urb() is called after URB is given back. Due to other fixes there is no need for ehci-hcd to deal with usb_get_urb() nor usb_put_urb() anymore, so patch removes their usages in ehci-hcd. Patch also makes ehci_to_hcd(ehci)->self.bandwidth_allocated adjust, if a stream finishes. Signed-off-by: Karsten Wiese Cc: David Brownell Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 07bcb931021..1d0b49e3f19 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1536,7 +1536,7 @@ itd_link_urb ( struct ehci_itd, itd_list); list_move_tail (&itd->itd_list, &stream->td_list); itd->stream = iso_stream_get (stream); - itd->urb = usb_get_urb (urb); + itd->urb = urb; itd_init (ehci, stream, itd); } @@ -1645,7 +1645,7 @@ itd_complete ( (void) disable_periodic(ehci); ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; - if (unlikely (list_empty (&stream->td_list))) { + if (unlikely(list_is_singular(&stream->td_list))) { ehci_to_hcd(ehci)->self.bandwidth_allocated -= stream->bandwidth; ehci_vdbg (ehci, @@ -1656,7 +1656,6 @@ itd_complete ( iso_stream_put (ehci, stream); done: - usb_put_urb(urb); itd->urb = NULL; if (ehci->clock_frame != itd->frame || itd->index[7] != -1) { /* OK to recycle this ITD now. */ @@ -1949,7 +1948,7 @@ sitd_link_urb ( struct ehci_sitd, sitd_list); list_move_tail (&sitd->sitd_list, &stream->td_list); sitd->stream = iso_stream_get (stream); - sitd->urb = usb_get_urb (urb); + sitd->urb = urb; sitd_patch(ehci, stream, sitd, sched, packet); sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size, @@ -2034,7 +2033,7 @@ sitd_complete ( (void) disable_periodic(ehci); ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; - if (list_empty (&stream->td_list)) { + if (list_is_singular(&stream->td_list)) { ehci_to_hcd(ehci)->self.bandwidth_allocated -= stream->bandwidth; ehci_vdbg (ehci, @@ -2045,7 +2044,6 @@ sitd_complete ( iso_stream_put (ehci, stream); /* OK to recycle this SITD now that its completion callback ran. */ done: - usb_put_urb(urb); sitd->urb = NULL; sitd->stream = NULL; list_move(&sitd->sitd_list, &stream->free_list); -- GitLab From 391016f6e2fe3b9979b4c6880a76e5e434d6947c Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 16 Mar 2009 14:21:56 -0400 Subject: [PATCH 3664/4982] USB: EHCI: expedite unlinks when the root hub is suspended This patch (as1225) fixes a bug in ehci-hcd. The condition for whether unlinked QHs can become IDLE should not be that the controller is halted, but rather that the controller isn't running. In other words when the root hub is suspended, the hardware doesn't own any QHs. This fixes a problem that can show up during hibernation: If a QH is only partially unlinked when the root hub is frozen, then when the root hub is thawed the QH won't be in the IDLE state. As a result it can't be used properly for new URB submissions. Signed-off-by: Alan Stern Reported-by: Brandon Philips Tested-by: Brandon Philips Acked-by: David Brownell Cc: Stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-q.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 3712b925b31..ecc9b66c03c 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1095,7 +1095,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) prev->qh_next = qh->qh_next; wmb (); - if (unlikely (ehci_to_hcd(ehci)->state == HC_STATE_HALT)) { + /* If the controller isn't running, we don't have to wait for it */ + if (unlikely(!HC_IS_RUNNING(ehci_to_hcd(ehci)->state))) { /* if (unlikely (qh->reclaim != 0)) * this will recurse, probably not much */ -- GitLab From 0cc6bfe901b946df125d8e37186d8e45f876457d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 12 Mar 2009 06:53:00 -0400 Subject: [PATCH 3665/4982] USB: Option: let cdc-acm handle Sony Ericsson F3507g / Dell 5530 The generic cdc-acm driver is now the best one to handle Sony Ericsson F3507g-based devices (which the Dell 5530 is a rebrand of), now that all the pieces are in place (ie, cac477e8f1038c41b6f29d3161ce351462ef3df7). Removing the IDs from option allows cdc-acm to handle the device. Signed-off-by: Dan Williams Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index ddd0a0b7e1a..3cf765b0bed 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -293,11 +293,6 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po #define ZTE_PRODUCT_MF626 0x0031 #define ZTE_PRODUCT_CDMA_TECH 0xfffe -/* Ericsson products */ -#define ERICSSON_VENDOR_ID 0x0bdb -#define ERICSSON_PRODUCT_F3507G_1 0x1900 -#define ERICSSON_PRODUCT_F3507G_2 0x1902 - #define BENQ_VENDOR_ID 0x04a5 #define BENQ_PRODUCT_H10 0x4068 @@ -443,7 +438,6 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5520_MINICARD_CINGULAR) }, /* Dell Wireless HSDPA 5520 == Novatel Expedite EU860D */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5520_MINICARD_GENERIC_L) }, /* Dell Wireless HSDPA 5520 */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5520_MINICARD_GENERIC_I) }, /* Dell Wireless 5520 Voda I Mobile Broadband (3G HSDPA) Minicard */ - { USB_DEVICE(DELL_VENDOR_ID, 0x8147) }, /* Dell Wireless 5530 Mobile Broadband (3G HSPA) Mini-Card */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_SPRINT) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_TELUS) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_VZW) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ @@ -515,8 +509,6 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626) }, { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) }, { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) }, - { USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G_1) }, - { USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G_2) }, { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, { USB_DEVICE(0x1da5, 0x4515) }, /* BenQ H20 */ { } /* Terminating entry */ -- GitLab From 716a9c8561d9c50ec454f4fbd39a265892feda2c Mon Sep 17 00:00:00 2001 From: Moritz Muehlenhoff Date: Sat, 14 Mar 2009 00:43:21 +0100 Subject: [PATCH 3666/4982] USB: Updated unusual-devs entry for USB mass storage on Nokia 6233 Current firmware revision 5.60 still behaves the same, so update the quirk up a (non-existing) 99.99 revision. http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=493415 Signed-off-by: Moritz Muehlenhoff Tested-by: Jan Heitkoetter Cc: stable Signed-off-by: Phil Dibowitz --- drivers/usb/storage/unusual_devs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index bfa8db0d8aa..84ca4332e6b 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -226,7 +226,7 @@ UNUSUAL_DEV( 0x0421, 0x047c, 0x0370, 0x0610, US_FL_MAX_SECTORS_64 ), /* Reported by Manuel Osdoba */ -UNUSUAL_DEV( 0x0421, 0x0492, 0x0452, 0x0452, +UNUSUAL_DEV( 0x0421, 0x0492, 0x0452, 0x9999, "Nokia", "Nokia 6233", US_SC_DEVICE, US_PR_DEVICE, NULL, -- GitLab From 56a21827439a4d715b510bfaf488534e6f4ad2f8 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sat, 14 Mar 2009 20:47:39 -0700 Subject: [PATCH 3667/4982] USB: Add Vendor/Product ID for new CDMA U727 to option driver * newer versions of the Novatel Wireless U727 CDMA 3G USB stick have a different Product ID (0x5010); adding this ID makes them work just fine with the option driver Signed-off-by: Dirk Hohndel Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 3cf765b0bed..d31fc2bcf77 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -197,6 +197,7 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po /* OVATION PRODUCTS */ #define NOVATELWIRELESS_PRODUCT_MC727 0x4100 #define NOVATELWIRELESS_PRODUCT_MC950D 0x4400 +#define NOVATELWIRELESS_PRODUCT_U727 0x5010 /* FUTURE NOVATEL PRODUCTS */ #define NOVATELWIRELESS_PRODUCT_EVDO_FULLSPEED 0X6000 @@ -411,6 +412,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU870D) }, /* Novatel EU850D/EU860D/EU870D */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC950D) }, /* Novatel MC930D/MC950D */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */ + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U727) }, /* Novatel MC727/U727/USB727 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_FULLSPEED) }, /* Novatel EVDO product */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED) }, /* Novatel HSPA product */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, /* Novatel EVDO Embedded product */ -- GitLab From e7f2f0d77a7b483a26054f29ba8393831b25a8a4 Mon Sep 17 00:00:00 2001 From: Achilleas Kotsis Date: Mon, 16 Mar 2009 16:35:02 +0200 Subject: [PATCH 3668/4982] USB: Add device id for Option GTM380 to option driver Option GTM380 in Modem mode uses Product ID 0x7201. This has been tested and works on production systems for over 6 months. Signed-off-by: Achilleas Kotsis Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index d31fc2bcf77..61ebddc4849 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -89,6 +89,7 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po #define OPTION_PRODUCT_ETNA_MODEM_GT 0x7041 #define OPTION_PRODUCT_ETNA_MODEM_EX 0x7061 #define OPTION_PRODUCT_ETNA_KOI_MODEM 0x7100 +#define OPTION_PRODUCT_GTM380_MODEM 0x7201 #define HUAWEI_VENDOR_ID 0x12D1 #define HUAWEI_PRODUCT_E600 0x1001 @@ -322,6 +323,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_GT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_EX) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_MODEM) }, + { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTM380_MODEM) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_Q101) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_Q111) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) }, -- GitLab From 8a0845c51b2e300f5204a323b874f7f58ea0eff7 Mon Sep 17 00:00:00 2001 From: Thomas Bartosik Date: Mon, 16 Mar 2009 16:04:38 +0100 Subject: [PATCH 3669/4982] USB: storage: Unusual USB device Prolific 2507 variation added The "c-enter" USB to Toshiba 1.8" IDE enclosure needs special treatment to work flawlessly. This patch is absolutely trivial, as the integrated USB-IDE bridge is already identified to be an "unusual" device, only the bcdDevice is different (lower) to the bcdDeviceMin already included in the kernel. It is a Prolific 2507 bridge. T: Bus=02 Lev=01 Prnt=01 Port=02 Cnt=01 Dev#= 4 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=067b ProdID=2507 Rev= 0.01 S: Manufacturer=Prolific Technology Inc. S: Product=ATAPI-6 Bridge Controller S: SerialNumber=00000272 C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr=100mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms Signed-off-by: Thomas Bartosik Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 84ca4332e6b..cfde74a6faa 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -951,7 +951,9 @@ UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001, US_FL_FIX_CAPACITY ), /* Reported by Richard -=[]=- */ -UNUSUAL_DEV( 0x067b, 0x2507, 0x0100, 0x0100, +/* Change to bcdDeviceMin (0x0100 to 0x0001) reported by + * Thomas Bartosik */ +UNUSUAL_DEV( 0x067b, 0x2507, 0x0001, 0x0100, "Prolific Technology Inc.", "Mass Storage Device", US_SC_DEVICE, US_PR_DEVICE, NULL, -- GitLab From 6e2b75740bed35df98b8113300579e13ed2ce848 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 16 Mar 2009 18:13:36 -0400 Subject: [PATCH 3670/4982] module: fix refptr allocation and release order Impact: fix ref-after-free crash on failed module load Fix refptr bug: Change refptr allocation and release order not to access a module data structure pointed by 'mod' after freeing mod->module_core. This bug will cause kernel panic(e.g. failed to find undefined symbols). This bug was reported on systemtap bugzilla. http://sources.redhat.com/bugzilla/show_bug.cgi?id=9927 Signed-off-by: Masami Hiramatsu Cc: Eric Dumazet Signed-off-by: Rusty Russell --- kernel/module.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/kernel/module.c b/kernel/module.c index ba22484a987..1196f5d1170 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2015,14 +2015,6 @@ static noinline struct module *load_module(void __user *umod, if (err < 0) goto free_mod; -#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) - mod->refptr = percpu_modalloc(sizeof(local_t), __alignof__(local_t), - mod->name); - if (!mod->refptr) { - err = -ENOMEM; - goto free_mod; - } -#endif if (pcpuindex) { /* We have a special allocation for this section. */ percpu = percpu_modalloc(sechdrs[pcpuindex].sh_size, @@ -2030,7 +2022,7 @@ static noinline struct module *load_module(void __user *umod, mod->name); if (!percpu) { err = -ENOMEM; - goto free_percpu; + goto free_mod; } sechdrs[pcpuindex].sh_flags &= ~(unsigned long)SHF_ALLOC; mod->percpu = percpu; @@ -2082,6 +2074,14 @@ static noinline struct module *load_module(void __user *umod, /* Module has been moved. */ mod = (void *)sechdrs[modindex].sh_addr; +#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) + mod->refptr = percpu_modalloc(sizeof(local_t), __alignof__(local_t), + mod->name); + if (!mod->refptr) { + err = -ENOMEM; + goto free_init; + } +#endif /* Now we've moved module, initialize linked lists, etc. */ module_unload_init(mod); @@ -2288,15 +2288,17 @@ static noinline struct module *load_module(void __user *umod, ftrace_release(mod->module_core, mod->core_size); free_unload: module_unload_free(mod); + free_init: +#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) + percpu_modfree(mod->refptr); +#endif module_free(mod, mod->module_init); free_core: module_free(mod, mod->module_core); + /* mod will be freed with core. Don't access it beyond this line! */ free_percpu: if (percpu) percpu_modfree(percpu); -#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) - percpu_modfree(mod->refptr); -#endif free_mod: kfree(args); free_hdr: -- GitLab From 2b301307f63dbecf06d91f58f003c7fb7addee24 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 12 Mar 2009 14:20:30 -0400 Subject: [PATCH 3671/4982] [SCSI] sd: Try READ CAPACITY 16 first for SBC-2 devices New features are being added to the READ CAPACITY 16 results, so we want to issue it in preference to READ CAPACITY 10. Unfortunately, some devices misbehave when they see a READ CAPACITY 16, so we restrict this command to devices which claim conformance to SPC-3 (aka SBC-2), or claim they have features which are only reported in the READ CAPACITY 16 data. The READ CAPACITY 16 command is optional, even for SBC-2 devices, so we fall back to READ CAPACITY 10 if READ CAPACITY 16 fails. [jejb: don't error if device supports SBC-2 but doesn't support RC16] Signed-off-by: Matthew Wilcox Tested-by: Martin K. Petersen Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index dcff84abcde..8eebaa8c6f5 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1329,8 +1329,17 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, if (media_not_present(sdkp, &sshdr)) return -ENODEV; - if (the_result) + if (the_result) { sense_valid = scsi_sense_valid(&sshdr); + if (sense_valid && + sshdr.sense_key == ILLEGAL_REQUEST && + (sshdr.asc == 0x20 || sshdr.asc == 0x24) && + sshdr.ascq == 0x00) + /* Invalid Command Operation Code or + * Invalid Field in CDB, just retry + * silently with RC10 */ + return -EINVAL; + } retries--; } while (the_result && retries); @@ -1414,6 +1423,15 @@ static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp, return sector_size; } +static int sd_try_rc16_first(struct scsi_device *sdp) +{ + if (sdp->scsi_level > SCSI_SPC_2) + return 1; + if (scsi_device_protection(sdp)) + return 1; + return 0; +} + /* * read disk capacity */ @@ -1423,11 +1441,14 @@ sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer) int sector_size; struct scsi_device *sdp = sdkp->device; - /* Force READ CAPACITY(16) when PROTECT=1 */ - if (scsi_device_protection(sdp)) { + if (sd_try_rc16_first(sdp)) { sector_size = read_capacity_16(sdkp, sdp, buffer); if (sector_size == -EOVERFLOW) goto got_data; + if (sector_size == -ENODEV) + return; + if (sector_size < 0) + sector_size = read_capacity_10(sdkp, sdp, buffer); if (sector_size < 0) return; } else { -- GitLab From 70a9b8734660698eb91efb8947a9e691d40235e1 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Mon, 9 Mar 2009 11:33:31 -0400 Subject: [PATCH 3672/4982] [SCSI] sd: Make revalidate less chatty sd_revalidate ends up being called several times during device setup. With this patch we print everything during the first scan. Subsequent invocations will only print a message if the parameter in question has actually changed (LUN capacity has increased, etc.). Signed-off-by: Martin K. Petersen Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 61 ++++++++++++++++++++++++++++------------------- drivers/scsi/sd.h | 1 + 2 files changed, 38 insertions(+), 24 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 8eebaa8c6f5..aeab5d9dff2 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1440,6 +1440,7 @@ sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer) { int sector_size; struct scsi_device *sdp = sdkp->device; + sector_t old_capacity = sdkp->capacity; if (sd_try_rc16_first(sdp)) { sector_size = read_capacity_16(sdkp, sdp, buffer); @@ -1531,10 +1532,11 @@ got_data: string_get_size(sz, STRING_UNITS_10, cap_str_10, sizeof(cap_str_10)); - sd_printk(KERN_NOTICE, sdkp, - "%llu %d-byte hardware sectors: (%s/%s)\n", - (unsigned long long)sdkp->capacity, - sector_size, cap_str_10, cap_str_2); + if (sdkp->first_scan || old_capacity != sdkp->capacity) + sd_printk(KERN_NOTICE, sdkp, + "%llu %d-byte hardware sectors: (%s/%s)\n", + (unsigned long long)sdkp->capacity, + sector_size, cap_str_10, cap_str_2); } /* Rescale capacity to 512-byte units */ @@ -1571,6 +1573,7 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer) int res; struct scsi_device *sdp = sdkp->device; struct scsi_mode_data data; + int old_wp = sdkp->write_prot; set_disk_ro(sdkp->disk, 0); if (sdp->skip_ms_page_3f) { @@ -1611,11 +1614,13 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer) } else { sdkp->write_prot = ((data.device_specific & 0x80) != 0); set_disk_ro(sdkp->disk, sdkp->write_prot); - sd_printk(KERN_NOTICE, sdkp, "Write Protect is %s\n", - sdkp->write_prot ? "on" : "off"); - sd_printk(KERN_DEBUG, sdkp, - "Mode Sense: %02x %02x %02x %02x\n", - buffer[0], buffer[1], buffer[2], buffer[3]); + if (sdkp->first_scan || old_wp != sdkp->write_prot) { + sd_printk(KERN_NOTICE, sdkp, "Write Protect is %s\n", + sdkp->write_prot ? "on" : "off"); + sd_printk(KERN_DEBUG, sdkp, + "Mode Sense: %02x %02x %02x %02x\n", + buffer[0], buffer[1], buffer[2], buffer[3]); + } } } @@ -1633,6 +1638,9 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) int modepage; struct scsi_mode_data data; struct scsi_sense_hdr sshdr; + int old_wce = sdkp->WCE; + int old_rcd = sdkp->RCD; + int old_dpofua = sdkp->DPOFUA; if (sdp->skip_ms_page_8) goto defaults; @@ -1704,12 +1712,14 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) sdkp->DPOFUA = 0; } - sd_printk(KERN_NOTICE, sdkp, - "Write cache: %s, read cache: %s, %s\n", - sdkp->WCE ? "enabled" : "disabled", - sdkp->RCD ? "disabled" : "enabled", - sdkp->DPOFUA ? "supports DPO and FUA" - : "doesn't support DPO or FUA"); + if (sdkp->first_scan || old_wce != sdkp->WCE || + old_rcd != sdkp->RCD || old_dpofua != sdkp->DPOFUA) + sd_printk(KERN_NOTICE, sdkp, + "Write cache: %s, read cache: %s, %s\n", + sdkp->WCE ? "enabled" : "disabled", + sdkp->RCD ? "disabled" : "enabled", + sdkp->DPOFUA ? "supports DPO and FUA" + : "doesn't support DPO or FUA"); return; } @@ -1805,15 +1815,6 @@ static int sd_revalidate_disk(struct gendisk *disk) goto out; } - /* defaults, until the device tells us otherwise */ - sdp->sector_size = 512; - sdkp->capacity = 0; - sdkp->media_present = 1; - sdkp->write_prot = 0; - sdkp->WCE = 0; - sdkp->RCD = 0; - sdkp->ATO = 0; - sd_spinup_disk(sdkp); /* @@ -1827,6 +1828,8 @@ static int sd_revalidate_disk(struct gendisk *disk) sd_read_app_tag_own(sdkp, buffer); } + sdkp->first_scan = 0; + /* * We now have all cache related info, determine how we deal * with ordered requests. Note that as the current SCSI @@ -1937,6 +1940,16 @@ static void sd_probe_async(void *data, async_cookie_t cookie) gd->private_data = &sdkp->driver; gd->queue = sdkp->device->request_queue; + /* defaults, until the device tells us otherwise */ + sdp->sector_size = 512; + sdkp->capacity = 0; + sdkp->media_present = 1; + sdkp->write_prot = 0; + sdkp->WCE = 0; + sdkp->RCD = 0; + sdkp->ATO = 0; + sdkp->first_scan = 1; + sd_revalidate_disk(gd); blk_queue_prep_rq(sdp->request_queue, sd_prep_fn); diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 75638e7d3f6..708778cf5f0 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -53,6 +53,7 @@ struct scsi_disk { unsigned WCE : 1; /* state of disk WCE bit */ unsigned RCD : 1; /* state of disk RCD bit, unused */ unsigned DPOFUA : 1; /* state of disk DPOFUA bit */ + unsigned first_scan : 1; }; #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev) -- GitLab From ba33fadfabe88e838e73c76a6ff59546f5f6b92b Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Sun, 15 Mar 2009 21:37:18 -0600 Subject: [PATCH 3673/4982] [SCSI] mpt2sas: make global symbols unique The ioc_list global symbol is already used in 1st generation mpt fusion drivers, so this patch makes it unique in the 2nd generation driver. I've checked the entire sources, and I don't see any other global system missing the mpt2sas_xxx prefix. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.h | 6 +++--- drivers/scsi/mpt2sas/mpt2sas_ctl.c | 6 +++--- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index 11fc17f218c..6945ff4d382 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -68,11 +68,11 @@ #define MPT2SAS_DRIVER_NAME "mpt2sas" #define MPT2SAS_AUTHOR "LSI Corporation " #define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver" -#define MPT2SAS_DRIVER_VERSION "00.100.11.15" +#define MPT2SAS_DRIVER_VERSION "00.100.11.16" #define MPT2SAS_MAJOR_VERSION 00 #define MPT2SAS_MINOR_VERSION 100 #define MPT2SAS_BUILD_VERSION 11 -#define MPT2SAS_RELEASE_VERSION 15 +#define MPT2SAS_RELEASE_VERSION 16 /* * Set MPT2SAS_SG_DEPTH value based on user input. @@ -647,7 +647,7 @@ typedef void (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, /* base shared API */ -extern struct list_head ioc_list; +extern struct list_head mpt2sas_ioc_list; int mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc); void mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc); diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index 4fbe3f83319..2d4f85c9d7a 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c @@ -355,7 +355,7 @@ _ctl_verify_adapter(int ioc_number, struct MPT2SAS_ADAPTER **iocpp) { struct MPT2SAS_ADAPTER *ioc; - list_for_each_entry(ioc, &ioc_list, list) { + list_for_each_entry(ioc, &mpt2sas_ioc_list, list) { if (ioc->id != ioc_number) continue; *iocpp = ioc; @@ -439,7 +439,7 @@ _ctl_poll(struct file *filep, poll_table *wait) poll_wait(filep, &ctl_poll_wait, wait); - list_for_each_entry(ioc, &ioc_list, list) { + list_for_each_entry(ioc, &mpt2sas_ioc_list, list) { if (ioc->aen_event_read_flag) return POLLIN | POLLRDNORM; } @@ -2497,7 +2497,7 @@ mpt2sas_ctl_exit(void) struct MPT2SAS_ADAPTER *ioc; int i; - list_for_each_entry(ioc, &ioc_list, list) { + list_for_each_entry(ioc, &mpt2sas_ioc_list, list) { /* free memory associated to diag buffers */ for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) { diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 50865a8e1a4..0c463c483c0 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -68,10 +68,9 @@ static void _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc, static void _firmware_event_work(struct work_struct *work); /* global parameters */ -LIST_HEAD(ioc_list); +LIST_HEAD(mpt2sas_ioc_list); /* local parameters */ -static u32 logging_level; static u8 scsi_io_cb_idx = -1; static u8 tm_cb_idx = -1; static u8 ctl_cb_idx = -1; @@ -81,6 +80,7 @@ static u8 config_cb_idx = -1; static int mpt_ids; /* command line options */ +static u32 logging_level; MODULE_PARM_DESC(logging_level, " bits for enabling additional logging info " "(default=0)"); @@ -211,7 +211,7 @@ scsih_set_debug_level(const char *val, struct kernel_param *kp) return ret; printk(KERN_INFO "setting logging_level(0x%08x)\n", logging_level); - list_for_each_entry(ioc, &ioc_list, list) + list_for_each_entry(ioc, &mpt2sas_ioc_list, list) ioc->logging_level = logging_level; return 0; } @@ -5464,7 +5464,7 @@ scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc = shost_priv(shost); memset(ioc, 0, sizeof(struct MPT2SAS_ADAPTER)); INIT_LIST_HEAD(&ioc->list); - list_add_tail(&ioc->list, &ioc_list); + list_add_tail(&ioc->list, &mpt2sas_ioc_list); ioc->shost = shost; ioc->id = mpt_ids++; sprintf(ioc->name, "%s%d", MPT2SAS_DRIVER_NAME, ioc->id); -- GitLab From af50bb993dfa673cf21ab812efe620d7e0c36319 Mon Sep 17 00:00:00 2001 From: "Chauhan, Vijay" Date: Tue, 17 Mar 2009 18:51:40 +0530 Subject: [PATCH 3674/4982] [SCSI] scsi_dh_rdac: Retry for NOT_READY check condition This patch adds retry for NOT_READY check condition - Quiesce in progress (02/A1/02) Signed-off-by: Vijay Chauhan Signed-off-by: James Bottomley --- drivers/scsi/device_handler/scsi_dh_rdac.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 07962f675fe..43b8c51e98d 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -574,6 +574,12 @@ static int rdac_check_sense(struct scsi_device *sdev, * Just retry and wait. */ return ADD_TO_MLQUEUE; + if (sense_hdr->asc == 0xA1 && sense_hdr->ascq == 0x02) + /* LUN Not Ready - Quiescense in progress + * or has been achieved + * Just retry. + */ + return ADD_TO_MLQUEUE; break; case ILLEGAL_REQUEST: if (sense_hdr->asc == 0x94 && sense_hdr->ascq == 0x01) { -- GitLab From 9aac397525dc7945b1582a80cef5860516bca452 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Fri, 13 Mar 2009 06:52:22 +0000 Subject: [PATCH 3675/4982] powerpc/ps3: ps3_defconfig updates Update ps3_defconfig. Sets these options: CONFIG_PS3_VRAM=m CONFIG_BLK_DEV_DM=m CONFIG_USB_HIDDEV=y CONFIG_EXT4_FS=y Signed-off-by: Geoff Levand Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/configs/ps3_defconfig | 250 ++++++++++++++++++++++------- 1 file changed, 190 insertions(+), 60 deletions(-) diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig index b6eee7c93cd..ac14f5245d2 100644 --- a/arch/powerpc/configs/ps3_defconfig +++ b/arch/powerpc/configs/ps3_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.27-rc3 -# Wed Aug 20 08:16:53 2008 +# Linux kernel version: 2.6.29-rc8 +# Fri Mar 13 09:28:45 2009 # CONFIG_PPC64=y @@ -16,13 +16,14 @@ CONFIG_PPC_FPU=y CONFIG_ALTIVEC=y # CONFIG_VSX is not set CONFIG_PPC_STD_MMU=y +CONFIG_PPC_STD_MMU_64=y CONFIG_PPC_MM_SLICES=y CONFIG_VIRT_CPU_ACCOUNTING=y CONFIG_SMP=y CONFIG_NR_CPUS=2 CONFIG_64BIT=y CONFIG_WORD_SIZE=64 -CONFIG_PPC_MERGE=y +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y CONFIG_MMU=y CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_GENERIC_TIME=y @@ -46,7 +47,7 @@ CONFIG_PPC=y CONFIG_EARLY_PRINTK=y CONFIG_COMPAT=y CONFIG_SYSVIPC_COMPAT=y -CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_PPC_OF=y CONFIG_OF=y @@ -74,10 +75,19 @@ CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=17 -# CONFIG_CGROUPS is not set # CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set @@ -86,11 +96,13 @@ CONFIG_NAMESPACES=y # CONFIG_IPC_NS is not set # CONFIG_USER_NS is not set # CONFIG_PID_NS is not set +# CONFIG_NET_NS is not set CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y -# CONFIG_EMBEDDED is not set +CONFIG_ANON_INODES=y +CONFIG_EMBEDDED=y CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y @@ -99,37 +111,36 @@ CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y -# CONFIG_COMPAT_BRK is not set CONFIG_BASE_FULL=y CONFIG_FUTEX=y -CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y +CONFIG_AIO=y CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_COMPAT_BRK is not set CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_PROFILING=y -# CONFIG_MARKERS is not set +CONFIG_TRACEPOINTS=y +CONFIG_MARKERS=y CONFIG_OPROFILE=m CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_HAVE_SYSCALL_WRAPPERS=y CONFIG_HAVE_IOREMAP_PROT=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_USE_GENERIC_SMP_HELPERS=y -# CONFIG_HAVE_CLK is not set -CONFIG_PROC_PAGE_MONITOR=y # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 CONFIG_MODULES=y # CONFIG_MODULE_FORCE_LOAD is not set @@ -137,7 +148,6 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y CONFIG_STOP_MACHINE=y CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set @@ -157,7 +167,7 @@ CONFIG_DEFAULT_AS=y # CONFIG_DEFAULT_CFQ is not set # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="anticipatory" -CONFIG_CLASSIC_RCU=y +# CONFIG_FREEZER is not set # # Platform support @@ -183,18 +193,20 @@ CONFIG_PS3_STORAGE=y CONFIG_PS3_DISK=y CONFIG_PS3_ROM=y CONFIG_PS3_FLASH=y -CONFIG_OPROFILE_PS3=y +CONFIG_PS3_VRAM=m CONFIG_PS3_LPM=m CONFIG_PPC_CELL=y # CONFIG_PPC_CELL_NATIVE is not set # CONFIG_PPC_IBM_CELL_BLADE is not set # CONFIG_PPC_CELLEB is not set +# CONFIG_PPC_CELL_QPACE is not set # # Cell Broadband Engine options # CONFIG_SPU_FS=y CONFIG_SPU_FS_64K_LS=y +# CONFIG_SPU_TRACE is not set CONFIG_SPU_BASE=y # CONFIG_PQ2ADS is not set # CONFIG_IPIC is not set @@ -210,6 +222,7 @@ CONFIG_SPU_BASE=y # CONFIG_GENERIC_IOMAP is not set # CONFIG_CPU_FREQ is not set # CONFIG_FSL_ULI1575 is not set +# CONFIG_SIMPLE_GPIO is not set # # Kernel options @@ -229,6 +242,8 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT is not set CONFIG_BINFMT_ELF=y CONFIG_COMPAT_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set CONFIG_BINFMT_MISC=y CONFIG_HUGETLB_PAGE_SIZE_VARIABLE=y # CONFIG_IOMMU_VMERGE is not set @@ -251,7 +266,6 @@ CONFIG_SELECT_MEMORY_MODEL=y CONFIG_SPARSEMEM_MANUAL=y CONFIG_SPARSEMEM=y CONFIG_HAVE_MEMORY_PRESENT=y -# CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPARSEMEM_EXTREME=y CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y # CONFIG_SPARSEMEM_VMEMMAP is not set @@ -261,11 +275,14 @@ CONFIG_MEMORY_HOTPLUG_SPARSE=y CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y -CONFIG_RESOURCES_64BIT=y +CONFIG_PHYS_ADDR_T_64BIT=y CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y +CONFIG_UNEVICTABLE_LRU=y CONFIG_ARCH_MEMORY_PROBE=y CONFIG_PPC_HAS_HASH_64K=y +CONFIG_PPC_4K_PAGES=y +# CONFIG_PPC_16K_PAGES is not set # CONFIG_PPC_64K_PAGES is not set CONFIG_FORCE_MAX_ZONEORDER=13 CONFIG_SCHED_SMT=y @@ -299,6 +316,7 @@ CONFIG_NET=y # # Networking options # +CONFIG_COMPAT_NET_DEV_OPS=y CONFIG_PACKET=y CONFIG_PACKET_MMAP=y CONFIG_UNIX=y @@ -361,6 +379,7 @@ CONFIG_IPV6_NDISC_NODETYPE=y # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set # CONFIG_LLC2 is not set @@ -371,6 +390,7 @@ CONFIG_IPV6_NDISC_NODETYPE=y # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set # # Network testing @@ -392,39 +412,37 @@ CONFIG_BT_HIDP=m # # Bluetooth device drivers # -CONFIG_BT_HCIUSB=m -CONFIG_BT_HCIUSB_SCO=y +CONFIG_BT_HCIBTUSB=m # CONFIG_BT_HCIUART is not set # CONFIG_BT_HCIBCM203X is not set # CONFIG_BT_HCIBPA10X is not set # CONFIG_BT_HCIBFUSB is not set # CONFIG_BT_HCIVHCI is not set # CONFIG_AF_RXRPC is not set - -# -# Wireless -# +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y CONFIG_CFG80211=m +# CONFIG_CFG80211_REG_DEBUG is not set CONFIG_NL80211=y +# CONFIG_WIRELESS_OLD_REGULATORY is not set CONFIG_WIRELESS_EXT=y # CONFIG_WIRELESS_EXT_SYSFS is not set +# CONFIG_LIB80211 is not set CONFIG_MAC80211=m # # Rate control algorithm selection # CONFIG_MAC80211_RC_PID=y +# CONFIG_MAC80211_RC_MINSTREL is not set CONFIG_MAC80211_RC_DEFAULT_PID=y +# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set CONFIG_MAC80211_RC_DEFAULT="pid" # CONFIG_MAC80211_MESH is not set # CONFIG_MAC80211_LEDS is not set # CONFIG_MAC80211_DEBUGFS is not set # CONFIG_MAC80211_DEBUG_MENU is not set -CONFIG_IEEE80211=m -# CONFIG_IEEE80211_DEBUG is not set -CONFIG_IEEE80211_CRYPT_WEP=m -CONFIG_IEEE80211_CRYPT_CCMP=m -CONFIG_IEEE80211_CRYPT_TKIP=m +# CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set @@ -450,6 +468,7 @@ CONFIG_MTD_DEBUG=y CONFIG_MTD_DEBUG_VERBOSE=0 # CONFIG_MTD_CONCAT is not set # CONFIG_MTD_PARTITIONS is not set +# CONFIG_MTD_TESTS is not set # # User Modules And Translation Layers @@ -494,7 +513,6 @@ CONFIG_MTD_CFI_I2=y # # CONFIG_MTD_SLRAM is not set # CONFIG_MTD_PHRAM is not set -CONFIG_MTD_PS3VRAM=y # CONFIG_MTD_MTDRAM is not set # CONFIG_MTD_BLOCK2MTD is not set @@ -507,6 +525,11 @@ CONFIG_MTD_PS3VRAM=y # CONFIG_MTD_NAND is not set # CONFIG_MTD_ONENAND is not set +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + # # UBI - Unsorted block images # @@ -528,8 +551,13 @@ CONFIG_BLK_DEV_RAM_SIZE=65535 # CONFIG_ATA_OVER_ETH is not set # CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y -# CONFIG_EEPROM_93CX6 is not set # CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_93CX6 is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -575,7 +603,17 @@ CONFIG_SCSI_WAIT_SCAN=m # CONFIG_SCSI_LOWLEVEL is not set # CONFIG_SCSI_DH is not set # CONFIG_ATA is not set -# CONFIG_MD is not set +CONFIG_MD=y +# CONFIG_BLK_DEV_MD is not set +CONFIG_BLK_DEV_DM=m +# CONFIG_DM_DEBUG is not set +# CONFIG_DM_CRYPT is not set +# CONFIG_DM_SNAPSHOT is not set +# CONFIG_DM_MIRROR is not set +# CONFIG_DM_ZERO is not set +# CONFIG_DM_MULTIPATH is not set +# CONFIG_DM_DELAY is not set +# CONFIG_DM_UEVENT is not set # CONFIG_MACINTOSH_DRIVERS is not set CONFIG_NETDEVICES=y # CONFIG_DUMMY is not set @@ -591,6 +629,9 @@ CONFIG_MII=m # CONFIG_IBM_NEW_EMAC_RGMII is not set # CONFIG_IBM_NEW_EMAC_TAH is not set # CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set # CONFIG_B44 is not set CONFIG_NETDEV_1000=y CONFIG_GELIC_NET=y @@ -604,6 +645,7 @@ CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE=y # CONFIG_WLAN_PRE80211 is not set CONFIG_WLAN_80211=y # CONFIG_LIBERTAS is not set +# CONFIG_LIBERTAS_THINFIRM is not set # CONFIG_USB_ZD1201 is not set # CONFIG_USB_NET_RNDIS_WLAN is not set # CONFIG_RTL8187 is not set @@ -615,13 +657,11 @@ CONFIG_WLAN_80211=y # CONFIG_B43LEGACY is not set CONFIG_ZD1211RW=m # CONFIG_ZD1211RW_DEBUG is not set -CONFIG_RT2X00=m -CONFIG_RT2X00_LIB=m -CONFIG_RT2X00_LIB_USB=m -CONFIG_RT2X00_LIB_FIRMWARE=y -# CONFIG_RT2500USB is not set -CONFIG_RT73USB=m -# CONFIG_RT2X00_DEBUG is not set +# CONFIG_RT2X00 is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# # # USB Network Adapters @@ -634,6 +674,7 @@ CONFIG_USB_USBNET=m CONFIG_USB_NET_AX8817X=m # CONFIG_USB_NET_CDCETHER is not set # CONFIG_USB_NET_DM9601 is not set +# CONFIG_USB_NET_SMSC95XX is not set # CONFIG_USB_NET_GL620A is not set # CONFIG_USB_NET_NET1080 is not set # CONFIG_USB_NET_PLUSB is not set @@ -664,7 +705,7 @@ CONFIG_SLHC=m # Input device support # CONFIG_INPUT=y -# CONFIG_INPUT_FF_MEMLESS is not set +CONFIG_INPUT_FF_MEMLESS=m # CONFIG_INPUT_POLLDEV is not set # @@ -735,8 +776,10 @@ CONFIG_DEVKMEM=y # Non-8250 serial port support # CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_HVC_UDBG is not set # CONFIG_IPMI_HANDLER is not set # CONFIG_HW_RANDOM is not set # CONFIG_R3964 is not set @@ -753,11 +796,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y # CONFIG_THERMAL is not set # CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y # # Sonics Silicon Backplane # -CONFIG_SSB_POSSIBLE=y # CONFIG_SSB is not set # @@ -767,6 +810,7 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_MFD_TMIO is not set +# CONFIG_REGULATOR is not set # # Multimedia devices @@ -792,6 +836,7 @@ CONFIG_VIDEO_OUTPUT_CONTROL=m CONFIG_FB=y # CONFIG_FIRMWARE_EDID is not set # CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set # CONFIG_FB_CFB_FILLRECT is not set # CONFIG_FB_CFB_COPYAREA is not set # CONFIG_FB_CFB_IMAGEBLIT is not set @@ -817,6 +862,8 @@ CONFIG_FB_SYS_FOPS=y CONFIG_FB_PS3=y CONFIG_FB_PS3_DEFAULT_SIZE_M=9 # CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set # CONFIG_BACKLIGHT_LCD_SUPPORT is not set # @@ -841,6 +888,7 @@ CONFIG_FB_LOGO_EXTRA=y # CONFIG_LOGO_LINUX_VGA16 is not set CONFIG_LOGO_LINUX_CLUT224=y CONFIG_SOUND=m +# CONFIG_SOUND_OSS_CORE is not set CONFIG_SND=m CONFIG_SND_TIMER=m CONFIG_SND_PCM=m @@ -849,6 +897,7 @@ CONFIG_SND_RAWMIDI=m # CONFIG_SND_SEQUENCER is not set # CONFIG_SND_MIXER_OSS is not set # CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_HRTIMER is not set # CONFIG_SND_DYNAMIC_MINORS is not set CONFIG_SND_SUPPORT_OLD_API=y CONFIG_SND_VERBOSE_PROCFS=y @@ -873,15 +922,40 @@ CONFIG_HIDRAW=y # USB Input Devices # CONFIG_USB_HID=m -# CONFIG_USB_HIDINPUT_POWERBOOK is not set -# CONFIG_HID_FF is not set -# CONFIG_USB_HIDDEV is not set +# CONFIG_HID_PID is not set +CONFIG_USB_HIDDEV=y # # USB HID Boot Protocol drivers # # CONFIG_USB_KBD is not set # CONFIG_USB_MOUSE is not set + +# +# Special HID drivers +# +# CONFIG_HID_COMPAT is not set +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_LOGITECH is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_GREENASIA_FF is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_THRUSTMASTER_FF is not set +# CONFIG_ZEROPLUS_FF is not set CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y @@ -898,7 +972,11 @@ CONFIG_USB_DEVICEFS=y # CONFIG_USB_DYNAMIC_MINORS is not set CONFIG_USB_SUSPEND=y # CONFIG_USB_OTG is not set -CONFIG_USB_MON=y +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +CONFIG_USB_MON=m +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set # # USB Host Controller Drivers @@ -909,6 +987,7 @@ CONFIG_USB_EHCI_HCD=m # CONFIG_USB_EHCI_TT_NEWSCHED is not set CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y # CONFIG_USB_EHCI_HCD_PPC_OF is not set +# CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set CONFIG_USB_OHCI_HCD=m @@ -918,6 +997,7 @@ CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set # # Enable Host or Gadget support to see Inventra options @@ -929,20 +1009,20 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set # CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; # # -# may also be needed; see USB_STORAGE Help for more information +# see USB_STORAGE Help for more information # CONFIG_USB_STORAGE=m # CONFIG_USB_STORAGE_DEBUG is not set # CONFIG_USB_STORAGE_DATAFAB is not set # CONFIG_USB_STORAGE_FREECOM is not set # CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set # CONFIG_USB_STORAGE_USBAT is not set # CONFIG_USB_STORAGE_SDDR09 is not set # CONFIG_USB_STORAGE_SDDR55 is not set @@ -950,7 +1030,6 @@ CONFIG_USB_STORAGE=m # CONFIG_USB_STORAGE_ALAUDA is not set # CONFIG_USB_STORAGE_ONETOUCH is not set # CONFIG_USB_STORAGE_KARMA is not set -# CONFIG_USB_STORAGE_SIERRA is not set # CONFIG_USB_STORAGE_CYPRESS_ATACB is not set # CONFIG_USB_LIBUSUAL is not set @@ -971,6 +1050,7 @@ CONFIG_USB_STORAGE=m # CONFIG_USB_EMI62 is not set # CONFIG_USB_EMI26 is not set # CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set @@ -988,7 +1068,12 @@ CONFIG_USB_STORAGE=m # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# # CONFIG_MMC is not set # CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set @@ -1014,12 +1099,15 @@ CONFIG_RTC_INTF_DEV=y # Platform RTC drivers # # CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set # CONFIG_RTC_DRV_DS1511 is not set # CONFIG_RTC_DRV_DS1553 is not set # CONFIG_RTC_DRV_DS1742 is not set # CONFIG_RTC_DRV_STK17TA8 is not set # CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set # CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set # CONFIG_RTC_DRV_V3020 is not set # @@ -1028,6 +1116,7 @@ CONFIG_RTC_INTF_DEV=y CONFIG_RTC_DRV_PPC=m # CONFIG_DMADEVICES is not set # CONFIG_UIO is not set +# CONFIG_STAGING is not set # # File systems @@ -1035,26 +1124,35 @@ CONFIG_RTC_DRV_PPC=m CONFIG_EXT2_FS=m # CONFIG_EXT2_FS_XATTR is not set # CONFIG_EXT2_FS_XIP is not set -CONFIG_EXT3_FS=y +CONFIG_EXT3_FS=m CONFIG_EXT3_FS_XATTR=y # CONFIG_EXT3_FS_POSIX_ACL is not set # CONFIG_EXT3_FS_SECURITY is not set -# CONFIG_EXT4DEV_FS is not set -CONFIG_JBD=y +CONFIG_EXT4_FS=y +# CONFIG_EXT4DEV_COMPAT is not set +CONFIG_EXT4_FS_XATTR=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +CONFIG_JBD=m # CONFIG_JBD_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set # CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y CONFIG_QUOTA=y # CONFIG_QUOTA_NETLINK_INTERFACE is not set CONFIG_PRINT_QUOTA_WARNING=y +CONFIG_QUOTA_TREE=y # CONFIG_QFMT_V1 is not set CONFIG_QFMT_V2=y CONFIG_QUOTACTL=y @@ -1087,16 +1185,14 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y # CONFIG_CONFIGFS_FS is not set - -# -# Miscellaneous filesystems -# +CONFIG_MISC_FILESYSTEMS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set @@ -1106,6 +1202,7 @@ CONFIG_HUGETLB_PAGE=y # CONFIG_EFS_FS is not set # CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_OMFS_FS is not set @@ -1126,6 +1223,7 @@ CONFIG_LOCKD_V4=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y +# CONFIG_SUNRPC_REGISTER_V4 is not set CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set @@ -1190,9 +1288,9 @@ CONFIG_NLS_ISO8859_1=y # Library routines # CONFIG_BITREVERSE=y -# CONFIG_GENERIC_FIND_FIRST_BIT is not set +CONFIG_GENERIC_FIND_LAST_BIT=y CONFIG_CRC_CCITT=m -# CONFIG_CRC16 is not set +CONFIG_CRC16=y CONFIG_CRC_T10DIF=y CONFIG_CRC_ITU_T=m CONFIG_CRC32=y @@ -1250,27 +1348,44 @@ CONFIG_DEBUG_WRITECOUNT=y CONFIG_DEBUG_MEMORY_INIT=y CONFIG_DEBUG_LIST=y # CONFIG_DEBUG_SG is not set -CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_NOTIFIERS is not set # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set CONFIG_SYSCTL_SYSCALL_CHECK=y -CONFIG_HAVE_FTRACE=y +CONFIG_NOP_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_DYNAMIC_FTRACE=y -# CONFIG_FTRACE is not set +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_RING_BUFFER=y +CONFIG_TRACING=y + +# +# Tracers +# +# CONFIG_FUNCTION_TRACER is not set # CONFIG_IRQSOFF_TRACER is not set # CONFIG_SCHED_TRACER is not set # CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_FTRACE_STARTUP_TEST is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set +CONFIG_PRINT_STACK_DEPTH=64 CONFIG_DEBUG_STACKOVERFLOW=y # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_PAGEALLOC is not set # CONFIG_CODE_PATCHING_SELFTEST is not set # CONFIG_FTR_FIXUP_SELFTEST is not set +# CONFIG_MSI_BITMAP_SELFTEST is not set # CONFIG_XMON is not set CONFIG_IRQSTACKS=y # CONFIG_VIRQ_DEBUG is not set @@ -1282,16 +1397,26 @@ CONFIG_IRQSTACKS=y # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set # CONFIG_SECURITY_FILE_CAPABILITIES is not set CONFIG_CRYPTO=y # # Crypto core or helper # +# CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y CONFIG_CRYPTO_AEAD=m +CONFIG_CRYPTO_AEAD2=y CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=m +CONFIG_CRYPTO_RNG2=y CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y CONFIG_CRYPTO_GF128MUL=m # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_CRYPTD is not set @@ -1363,6 +1488,11 @@ CONFIG_CRYPTO_SALSA20=m # # CONFIG_CRYPTO_DEFLATE is not set CONFIG_CRYPTO_LZO=m + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y # CONFIG_PPC_CLOCK is not set # CONFIG_VIRTUALIZATION is not set -- GitLab From c6c00919ab16717f228aac20ee72dc83c4430537 Mon Sep 17 00:00:00 2001 From: Steve French Date: Wed, 18 Mar 2009 05:50:07 +0000 Subject: [PATCH 3676/4982] [CIFS] Rename compose_mount_options to cifs_compose_mount_options. Make it available to others for reuse. Signed-off-by: Igor Mammedov Signed-off-by: Steve French --- fs/cifs/cifs_dfs_ref.c | 36 ++++++++++++++++-------------------- fs/cifs/cifsproto.h | 3 +++ 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index 85c0a74d034..5fdbf8a1447 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -104,9 +104,9 @@ static char *cifs_get_share_name(const char *node_name) /** - * compose_mount_options - creates mount options for refferral + * cifs_compose_mount_options - creates mount options for refferral * @sb_mountdata: parent/root DFS mount options (template) - * @dentry: point where we are going to mount + * @fullpath: full path in UNC format * @ref: server's referral * @devname: pointer for saving device name * @@ -116,8 +116,8 @@ static char *cifs_get_share_name(const char *node_name) * Returns: pointer to new mount options or ERR_PTR. * Caller is responcible for freeing retunrned value if it is not error. */ -static char *compose_mount_options(const char *sb_mountdata, - struct dentry *dentry, +char *cifs_compose_mount_options(const char *sb_mountdata, + const char *fullpath, const struct dfs_info3_param *ref, char **devname) { @@ -128,7 +128,6 @@ static char *compose_mount_options(const char *sb_mountdata, char *srvIP = NULL; char sep = ','; int off, noff; - char *fullpath; if (sb_mountdata == NULL) return ERR_PTR(-EINVAL); @@ -202,17 +201,6 @@ static char *compose_mount_options(const char *sb_mountdata, goto compose_mount_options_err; } - /* - * this function gives us a path with a double backslash prefix. We - * require a single backslash for DFS. Temporarily increment fullpath - * to put it in the proper form and decrement before freeing it. - */ - fullpath = build_path_from_dentry(dentry); - if (!fullpath) { - rc = -ENOMEM; - goto compose_mount_options_err; - } - ++fullpath; tkn_e = strchr(tkn_e + 1, '\\'); if (tkn_e || (strlen(fullpath) - ref->path_consumed)) { strncat(mountdata, &sep, 1); @@ -221,8 +209,6 @@ static char *compose_mount_options(const char *sb_mountdata, strcat(mountdata, tkn_e + 1); strcat(mountdata, fullpath + ref->path_consumed); } - --fullpath; - kfree(fullpath); /*cFYI(1,("%s: parent mountdata: %s", __func__,sb_mountdata));*/ /*cFYI(1, ("%s: submount mountdata: %s", __func__, mountdata ));*/ @@ -245,10 +231,20 @@ static struct vfsmount *cifs_dfs_do_refmount(const struct vfsmount *mnt_parent, struct vfsmount *mnt; char *mountdata; char *devname = NULL; + char *fullpath; cifs_sb = CIFS_SB(dentry->d_inode->i_sb); - mountdata = compose_mount_options(cifs_sb->mountdata, - dentry, ref, &devname); + /* + * this function gives us a path with a double backslash prefix. We + * require a single backslash for DFS. + */ + fullpath = build_path_from_dentry(dentry); + if (!fullpath) + return ERR_PTR(-ENOMEM); + + mountdata = cifs_compose_mount_options(cifs_sb->mountdata, + fullpath + 1, ref, &devname); + kfree(fullpath); if (IS_ERR(mountdata)) return (struct vfsmount *)mountdata; diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index a069e7bfd2d..4167716d32f 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -44,6 +44,9 @@ extern void _FreeXid(unsigned int); extern char *build_path_from_dentry(struct dentry *); extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb); extern char *build_wildcard_path_from_dentry(struct dentry *direntry); +extern char *cifs_compose_mount_options(const char *sb_mountdata, + const char *fullpath, const struct dfs_info3_param *ref, + char **devname); /* extern void renew_parental_timestamps(struct dentry *direntry);*/ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, struct smb_hdr * /* input */ , -- GitLab From b363b3304bcf68c4541683b2eff70b29f0446a5b Mon Sep 17 00:00:00 2001 From: Steve French Date: Wed, 18 Mar 2009 05:57:22 +0000 Subject: [PATCH 3677/4982] [CIFS] Fix memory overwrite when saving nativeFileSystem field during mount CIFS can allocate a few bytes to little for the nativeFileSystem field during tree connect response processing during mount. This can result in a "Redzone overwritten" message to be logged. Signed-off-by: Sridhar Vinay Acked-by: Shirish Pargaonkar CC: Stable Signed-off-by: Steve French --- fs/cifs/CHANGES | 3 +++ fs/cifs/connect.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index fc977dfe959..65984006192 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -13,6 +13,9 @@ parameter to allow user to disable sending the (slow) SMB flush on fsync if desired (fsync still flushes all cached write data to the server). Posix file open support added (turned off after one attempt if server fails to support it properly, as with Samba server versions prior to 3.3.2) +Fix "redzone overwritten" bug in cifs_put_tcon (CIFSTcon may allocate too +little memory for the "nativeFileSystem" field returned by the server +during mount). Version 1.56 ------------ diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index cd4ccc8ce47..0de3b5615a2 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3674,7 +3674,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, BCC(smb_buffer_response)) { kfree(tcon->nativeFileSystem); tcon->nativeFileSystem = - kzalloc(length + 2, GFP_KERNEL); + kzalloc(2*(length + 1), GFP_KERNEL); if (tcon->nativeFileSystem) cifs_strfromUCS_le( tcon->nativeFileSystem, -- GitLab From 09240cf429505891d6123ce14a29f58f2a60121e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 17 Mar 2009 07:47:18 +0100 Subject: [PATCH 3678/4982] ALSA: hda - Fix DMA mask for ATI controllers ATI controllers (at least some SB0600 models) appear buggy to handle 64bit DMA. As a workaround, reset GCAP bit0 and let the driver to use only 32bit DMA on these controllers. Cc: Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 5e909e0da04..643f0e49929 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2210,9 +2210,17 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, gcap = azx_readw(chip, GCAP); snd_printdd("chipset global capabilities = 0x%x\n", gcap); + /* ATI chips seems buggy about 64bit DMA addresses */ + if (chip->driver_type == AZX_DRIVER_ATI) + gcap &= ~0x01; + /* allow 64bit DMA address if supported by H/W */ if ((gcap & 0x01) && !pci_set_dma_mask(pci, DMA_64BIT_MASK)) pci_set_consistent_dma_mask(pci, DMA_64BIT_MASK); + else { + pci_set_dma_mask(pci, DMA_32BIT_MASK); + pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK); + } /* read number of streams from GCAP register instead of using * hardcoded value -- GitLab From c673ba1c23941173c16ff24c7cb34199e826c8b5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 17 Mar 2009 07:49:14 +0100 Subject: [PATCH 3679/4982] ALSA: hda - Workaround for buggy DMA position on ATI controllers The position-buffer on ATI controllers are unreliable as well as on VIA chips, thus the same workaround for DMA position reading as VIA is useful for ATI. Cc: Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 643f0e49929..f3b5723c285 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2059,26 +2059,31 @@ static int __devinit check_position_fix(struct azx *chip, int fix) { const struct snd_pci_quirk *q; - /* Check VIA HD Audio Controller exist */ - if (chip->pci->vendor == PCI_VENDOR_ID_VIA && - chip->pci->device == VIA_HDAC_DEVICE_ID) { + switch (fix) { + case POS_FIX_LPIB: + case POS_FIX_POSBUF: + return fix; + } + + /* Check VIA/ATI HD Audio Controller exist */ + switch (chip->driver_type) { + case AZX_DRIVER_VIA: + case AZX_DRIVER_ATI: chip->via_dmapos_patch = 1; /* Use link position directly, avoid any transfer problem. */ return POS_FIX_LPIB; } chip->via_dmapos_patch = 0; - if (fix == POS_FIX_AUTO) { - q = snd_pci_quirk_lookup(chip->pci, position_fix_list); - if (q) { - printk(KERN_INFO - "hda_intel: position_fix set to %d " - "for device %04x:%04x\n", - q->value, q->subvendor, q->subdevice); - return q->value; - } + q = snd_pci_quirk_lookup(chip->pci, position_fix_list); + if (q) { + printk(KERN_INFO + "hda_intel: position_fix set to %d " + "for device %04x:%04x\n", + q->value, q->subvendor, q->subdevice); + return q->value; } - return fix; + return POS_FIX_AUTO; } /* -- GitLab From ee5047102cf632351c418060bfbe3b6eb5c42e7b Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 17 Mar 2009 14:30:31 +0100 Subject: [PATCH 3680/4982] ALSA: snd-hda-intel - add checks for invalid values to *query_supported_pcm() If ratesp or formatsp values are zero, wrong values are passed to ALSA's the PCM midlevel code. The bug is showed more later than expected. Also, clean a bit the code. Signed-off-by: Jaroslav Kysela Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index cf6339436de..b90a2400f53 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -2539,12 +2539,11 @@ EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format); static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, u32 *ratesp, u64 *formatsp, unsigned int *bpsp) { - int i; - unsigned int val, streams; + unsigned int i, val, wcaps; val = 0; - if (nid != codec->afg && - (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) { + wcaps = get_wcaps(codec, nid); + if (nid != codec->afg && (wcaps & AC_WCAP_FORMAT_OVRD)) { val = snd_hda_param_read(codec, nid, AC_PAR_PCM); if (val == -1) return -EIO; @@ -2558,15 +2557,20 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, if (val & (1 << i)) rates |= rate_bits[i].alsa_bits; } + if (rates == 0) { + snd_printk(KERN_ERR "hda_codec: rates == 0 " + "(nid=0x%x, val=0x%x, ovrd=%i)\n", + nid, val, + (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0); + return -EIO; + } *ratesp = rates; } if (formatsp || bpsp) { u64 formats = 0; - unsigned int bps; - unsigned int wcaps; + unsigned int streams, bps; - wcaps = get_wcaps(codec, nid); streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM); if (streams == -1) return -EIO; @@ -2619,6 +2623,15 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, formats |= SNDRV_PCM_FMTBIT_U8; bps = 8; } + if (formats == 0) { + snd_printk(KERN_ERR "hda_codec: formats == 0 " + "(nid=0x%x, val=0x%x, ovrd=%i, " + "streams=0x%x)\n", + nid, val, + (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0, + streams); + return -EIO; + } if (formatsp) *formatsp = formats; if (bpsp) @@ -2734,12 +2747,16 @@ static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo, static int set_pcm_default_values(struct hda_codec *codec, struct hda_pcm_stream *info) { + int err; + /* query support PCM information from the given NID */ if (info->nid && (!info->rates || !info->formats)) { - snd_hda_query_supported_pcm(codec, info->nid, + err = snd_hda_query_supported_pcm(codec, info->nid, info->rates ? NULL : &info->rates, info->formats ? NULL : &info->formats, info->maxbps ? NULL : &info->maxbps); + if (err < 0) + return err; } if (info->ops.open == NULL) info->ops.open = hda_pcm_default_open_close; -- GitLab From 36c7b833e5d2501142a371e4e75281d3a29fbd6b Mon Sep 17 00:00:00 2001 From: Viral Mehta Date: Tue, 10 Mar 2009 15:43:18 +0100 Subject: [PATCH 3681/4982] ALSA: oss-mixer - Fixes recording gain control At the time of initialization, SNDRV_MIXER_OSS_PRESENT_PVOLUME bit is not set for MIC (slot 7). So, the same should not be checked when an application tries to do gain control for audio recording devices. Just check slot->present for SNDRV_MIXER_OSS_PRESENT_CVOLUME independently. Verified with a simple application which opens /dev/dsp for recording and /dev/mixer for volume control. Have tested two usb audio mic devices. Signed-off-by: Viral Mehta Signed-off-by: Takashi Iwai --- sound/core/oss/mixer_oss.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 4690b8b5681..e570649184e 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -692,6 +692,9 @@ static int snd_mixer_oss_put_volume1(struct snd_mixer_oss_file *fmixer, snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PVOLUME], left, right); if (slot->present & SNDRV_MIXER_OSS_PRESENT_CVOLUME) snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CVOLUME], left, right); + } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_CVOLUME) { + snd_mixer_oss_put_volume1_vol(fmixer, pslot, + slot->numid[SNDRV_MIXER_OSS_ITEM_CVOLUME], left, right); } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GVOLUME) { snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GVOLUME], left, right); } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GLOBAL) { -- GitLab From 91054598f794fb5d8a0b1e747ff8e2e8fc2115b3 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 11 Mar 2009 20:11:40 +0100 Subject: [PATCH 3682/4982] ALSA: pcm_oss, fix locking typo s/mutex_lock/mutex_unlock/ on 2 fail paths in snd_pcm_oss_proc_write. Probably a typo, lock should be unlocked when leaving the function. Signed-off-by: Jiri Slaby Cc: Signed-off-by: Takashi Iwai --- sound/core/oss/pcm_oss.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 0a1798eafb0..699d2890535 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2872,7 +2872,7 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry, setup = kmalloc(sizeof(*setup), GFP_KERNEL); if (! setup) { buffer->error = -ENOMEM; - mutex_lock(&pstr->oss.setup_mutex); + mutex_unlock(&pstr->oss.setup_mutex); return; } if (pstr->oss.setup_list == NULL) @@ -2886,7 +2886,7 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry, if (! template.task_name) { kfree(setup); buffer->error = -ENOMEM; - mutex_lock(&pstr->oss.setup_mutex); + mutex_unlock(&pstr->oss.setup_mutex); return; } } -- GitLab From 82f5d57163abed2e5ff271d03217b6f90c616eb8 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 11 Mar 2009 20:11:41 +0100 Subject: [PATCH 3683/4982] ALSA: mixart, fix lock imbalance There is an omitted unlock in one snd_mixart_hw_params fail path. Fix it. Signed-off-by: Jiri Slaby Cc: Signed-off-by: Takashi Iwai --- sound/pci/mixart/mixart.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index f23a73577c2..bb162507fe6 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -607,6 +607,7 @@ static int snd_mixart_hw_params(struct snd_pcm_substream *subs, /* set the format to the board */ err = mixart_set_format(stream, format); if(err < 0) { + mutex_unlock(&mgr->setup_mutex); return err; } -- GitLab From 6af845e4eb36fb91b322aaf77ec1cab2220a48ad Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 17 Mar 2009 14:00:06 +0100 Subject: [PATCH 3684/4982] ALSA: Fix vunmap and free order in snd_free_sgbuf_pages() In snd_free_sgbuf_pags(), vunmap() is called after releasing the SG pages, and it causes errors on Xen as Xen manages the pages differently. Although no significant errors have been reported on the actual hardware, this order should be fixed other way round, first vunmap() then free pages. Cc: Jan Beulich Cc: Signed-off-by: Takashi Iwai --- sound/core/sgbuf.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c index d4564edd61d..4e7ec2b4987 100644 --- a/sound/core/sgbuf.c +++ b/sound/core/sgbuf.c @@ -38,6 +38,10 @@ int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab) if (! sgbuf) return -EINVAL; + if (dmab->area) + vunmap(dmab->area); + dmab->area = NULL; + tmpb.dev.type = SNDRV_DMA_TYPE_DEV; tmpb.dev.dev = sgbuf->dev; for (i = 0; i < sgbuf->pages; i++) { @@ -48,9 +52,6 @@ int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab) tmpb.bytes = (sgbuf->table[i].addr & ~PAGE_MASK) << PAGE_SHIFT; snd_dma_free_pages(&tmpb); } - if (dmab->area) - vunmap(dmab->area); - dmab->area = NULL; kfree(sgbuf->table); kfree(sgbuf->page_table); -- GitLab From af66df5ecf9c9e2d2ff86e8203510c1c4519d64c Mon Sep 17 00:00:00 2001 From: Luis Henriques Date: Wed, 18 Mar 2009 00:04:25 +0000 Subject: [PATCH 3685/4982] sched: jiffies not printed per CPU The jiffies value was being printed for each CPU, which does not seem to make sense. Moved jiffies to system section. Signed-off-by: Luis Henriques Acked-by: Peter Zijlstra LKML-Reference: <20090318000425.GA2228@hades.domain.com> Signed-off-by: Ingo Molnar --- kernel/sched_debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c index 2b1260f0e80..4daebffa056 100644 --- a/kernel/sched_debug.c +++ b/kernel/sched_debug.c @@ -272,7 +272,6 @@ static void print_cpu(struct seq_file *m, int cpu) P(nr_switches); P(nr_load_updates); P(nr_uninterruptible); - SEQ_printf(m, " .%-30s: %lu\n", "jiffies", jiffies); PN(next_balance); P(curr->pid); PN(clock); @@ -325,6 +324,7 @@ static int sched_debug_show(struct seq_file *m, void *v) SEQ_printf(m, " .%-40s: %Ld\n", #x, (long long)(x)) #define PN(x) \ SEQ_printf(m, " .%-40s: %Ld.%06ld\n", #x, SPLIT_NS(x)) + P(jiffies); PN(sysctl_sched_latency); PN(sysctl_sched_min_granularity); PN(sysctl_sched_wakeup_granularity); -- GitLab From 7be5c55af0cc58e54e42e1702d837527e15b8414 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 18 Mar 2009 08:47:31 +0000 Subject: [PATCH 3686/4982] sh: simplify kexec vbr code Setup the vbr register in machine_kexec(). This instead of passing values to the assembly snippet. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/machine_kexec.c | 17 ++++++++--------- arch/sh/kernel/relocate_kernel.S | 4 ---- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c index 94df56b0d1f..d3318f99256 100644 --- a/arch/sh/kernel/machine_kexec.c +++ b/arch/sh/kernel/machine_kexec.c @@ -23,8 +23,7 @@ typedef NORET_TYPE void (*relocate_new_kernel_t)( unsigned long indirection_page, unsigned long reboot_code_buffer, - unsigned long start_address, - unsigned long vbr_reg) ATTRIB_NORET; + unsigned long start_address) ATTRIB_NORET; extern const unsigned char relocate_new_kernel[]; extern const unsigned int relocate_new_kernel_size; @@ -76,14 +75,8 @@ void machine_kexec(struct kimage *image) unsigned long page_list; unsigned long reboot_code_buffer; - unsigned long vbr_reg; relocate_new_kernel_t rnk; -#if defined(CONFIG_SH_STANDARD_BIOS) - vbr_reg = ((unsigned long )gdb_vbr_vector) - 0x100; -#else - vbr_reg = 0x80000000; // dummy -#endif /* Interrupts aren't acceptable while we reboot */ local_irq_disable(); @@ -100,9 +93,15 @@ void machine_kexec(struct kimage *image) kexec_info(image); flush_cache_all(); + set_bl_bit(); +#if defined(CONFIG_SH_STANDARD_BIOS) + asm volatile("ldc %0, vbr" : + : "r" (((unsigned long) gdb_vbr_vector) - 0x100) + : "memory"); +#endif /* now call it */ rnk = (relocate_new_kernel_t) reboot_code_buffer; - (*rnk)(page_list, reboot_code_buffer, P2SEGADDR(image->start), vbr_reg); + (*rnk)(page_list, reboot_code_buffer, P2SEGADDR(image->start)); } void arch_crash_save_vmcoreinfo(void) diff --git a/arch/sh/kernel/relocate_kernel.S b/arch/sh/kernel/relocate_kernel.S index c66cb3209db..8b50b2c873a 100644 --- a/arch/sh/kernel/relocate_kernel.S +++ b/arch/sh/kernel/relocate_kernel.S @@ -16,7 +16,6 @@ relocate_new_kernel: /* r4 = indirection_page */ /* r5 = reboot_code_buffer */ /* r6 = start_address */ - /* r7 = vbr_reg */ mov.l 10f,r8 /* PAGE_SIZE */ mov.l 11f,r9 /* P2SEG */ @@ -80,9 +79,6 @@ relocate_new_kernel: bra 0b nop 6: -#ifdef CONFIG_SH_STANDARD_BIOS - ldc r7, vbr -#endif jmp @r6 nop -- GitLab From e4e063d0c288bd65c56dd855337780a541ed928d Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 18 Mar 2009 08:49:45 +0000 Subject: [PATCH 3687/4982] sh: rework kexec segment code Rework the kexec code to avoid using P2SEG. Instead we walk the page list in machine_kexec() and convert the addresses from physical to virtual using C. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/machine_kexec.c | 17 ++++++++++++++++- arch/sh/kernel/relocate_kernel.S | 6 +----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c index d3318f99256..25b4748fdc7 100644 --- a/arch/sh/kernel/machine_kexec.c +++ b/arch/sh/kernel/machine_kexec.c @@ -76,6 +76,21 @@ void machine_kexec(struct kimage *image) unsigned long page_list; unsigned long reboot_code_buffer; relocate_new_kernel_t rnk; + unsigned long entry; + unsigned long *ptr; + + /* + * Nicked from the mips version of machine_kexec(): + * The generic kexec code builds a page list with physical + * addresses. Use phys_to_virt() to convert them to virtual. + */ + for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); + ptr = (entry & IND_INDIRECTION) ? + phys_to_virt(entry & PAGE_MASK) : ptr + 1) { + if (*ptr & IND_SOURCE || *ptr & IND_INDIRECTION || + *ptr & IND_DESTINATION) + *ptr = (unsigned long) phys_to_virt(*ptr); + } /* Interrupts aren't acceptable while we reboot */ local_irq_disable(); @@ -101,7 +116,7 @@ void machine_kexec(struct kimage *image) #endif /* now call it */ rnk = (relocate_new_kernel_t) reboot_code_buffer; - (*rnk)(page_list, reboot_code_buffer, P2SEGADDR(image->start)); + (*rnk)(page_list, reboot_code_buffer, image->start); } void arch_crash_save_vmcoreinfo(void) diff --git a/arch/sh/kernel/relocate_kernel.S b/arch/sh/kernel/relocate_kernel.S index 8b50b2c873a..2a6630be668 100644 --- a/arch/sh/kernel/relocate_kernel.S +++ b/arch/sh/kernel/relocate_kernel.S @@ -18,7 +18,6 @@ relocate_new_kernel: /* r6 = start_address */ mov.l 10f,r8 /* PAGE_SIZE */ - mov.l 11f,r9 /* P2SEG */ /* stack setting */ add r8,r5 @@ -29,9 +28,8 @@ relocate_new_kernel: 0: mov.l @r4+,r0 /* cmd = *ind++ */ -1: /* addr = (cmd | P2SEG) & 0xfffffff0 */ +1: /* addr = cmd & 0xfffffff0 */ mov r0,r2 - or r9,r2 mov #-16,r1 and r1,r2 @@ -85,8 +83,6 @@ relocate_new_kernel: .align 2 10: .long PAGE_SIZE -11: - .long P2SEG relocate_new_kernel_end: -- GitLab From b7cf6ddc13186f9272438a97aa75972d496d0b0a Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 18 Mar 2009 08:51:29 +0000 Subject: [PATCH 3688/4982] sh: add kexec jump support Add kexec jump support to the SuperH architecture. Similar to the x86 implementation, with the following exceptions: - Instead of separating the assembly code flow into two parts for regular kexec and kexec jump we use a single code path. In the assembly snippet regular kexec is just kexec jump that never comes back. - Instead of using a swap page when moving data between pages the page copy assembly routine has been modified to exchange the data between the pages using registers. - We walk the page list twice in machine_kexec() to do and undo physical to virtual address conversion. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 7 ++ arch/sh/kernel/machine_kexec.c | 32 ++++- arch/sh/kernel/relocate_kernel.S | 195 ++++++++++++++++++++++++++----- 3 files changed, 202 insertions(+), 32 deletions(-) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 6c56495fd15..8d50d527c59 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -559,6 +559,13 @@ config CRASH_DUMP For more details see Documentation/kdump/kdump.txt +config KEXEC_JUMP + bool "kexec jump (EXPERIMENTAL)" + depends on SUPERH32 && KEXEC && HIBERNATION && EXPERIMENTAL + help + Jump between original kernel and kexeced kernel and invoke + code via KEXEC + config SECCOMP bool "Enable seccomp to safely compute untrusted bytecode" depends on PROC_FS diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c index 25b4748fdc7..c44efb73ab1 100644 --- a/arch/sh/kernel/machine_kexec.c +++ b/arch/sh/kernel/machine_kexec.c @@ -14,20 +14,21 @@ #include #include #include +#include #include #include #include #include #include -typedef NORET_TYPE void (*relocate_new_kernel_t)( - unsigned long indirection_page, - unsigned long reboot_code_buffer, - unsigned long start_address) ATTRIB_NORET; +typedef void (*relocate_new_kernel_t)(unsigned long indirection_page, + unsigned long reboot_code_buffer, + unsigned long start_address); extern const unsigned char relocate_new_kernel[]; extern const unsigned int relocate_new_kernel_size; extern void *gdb_vbr_vector; +extern void *vbr_base; void machine_shutdown(void) { @@ -72,7 +73,6 @@ static void kexec_info(struct kimage *image) */ void machine_kexec(struct kimage *image) { - unsigned long page_list; unsigned long reboot_code_buffer; relocate_new_kernel_t rnk; @@ -92,6 +92,11 @@ void machine_kexec(struct kimage *image) *ptr = (unsigned long) phys_to_virt(*ptr); } +#ifdef CONFIG_KEXEC_JUMP + if (image->preserve_context) + save_processor_state(); +#endif + /* Interrupts aren't acceptable while we reboot */ local_irq_disable(); @@ -117,6 +122,23 @@ void machine_kexec(struct kimage *image) /* now call it */ rnk = (relocate_new_kernel_t) reboot_code_buffer; (*rnk)(page_list, reboot_code_buffer, image->start); + +#ifdef CONFIG_KEXEC_JUMP + asm volatile("ldc %0, vbr" : : "r" (&vbr_base) : "memory"); + local_irq_disable(); + clear_bl_bit(); + if (image->preserve_context) + restore_processor_state(); + + /* Convert page list back to physical addresses, what a mess. */ + for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); + ptr = (*ptr & IND_INDIRECTION) ? + phys_to_virt(*ptr & PAGE_MASK) : ptr + 1) { + if (*ptr & IND_SOURCE || *ptr & IND_INDIRECTION || + *ptr & IND_DESTINATION) + *ptr = virt_to_phys(*ptr); + } +#endif } void arch_crash_save_vmcoreinfo(void) diff --git a/arch/sh/kernel/relocate_kernel.S b/arch/sh/kernel/relocate_kernel.S index 2a6630be668..fcc9934fb97 100644 --- a/arch/sh/kernel/relocate_kernel.S +++ b/arch/sh/kernel/relocate_kernel.S @@ -4,6 +4,8 @@ * * LANDISK/sh4 is supported. Maybe, SH archtecture works well. * + * 2009-03-18 Magnus Damm - Added Kexec Jump support + * * This source code is licensed under the GNU General Public License, * Version 2. See the file COPYING for more details. */ @@ -17,14 +19,135 @@ relocate_new_kernel: /* r5 = reboot_code_buffer */ /* r6 = start_address */ - mov.l 10f,r8 /* PAGE_SIZE */ + mov.l 10f, r0 /* PAGE_SIZE */ + add r5, r0 /* setup new stack at end of control page */ + + /* save r15->r8 to new stack */ + mov.l r15, @-r0 + mov r0, r15 + mov.l r14, @-r15 + mov.l r13, @-r15 + mov.l r12, @-r15 + mov.l r11, @-r15 + mov.l r10, @-r15 + mov.l r9, @-r15 + mov.l r8, @-r15 + + /* save other random registers */ + sts.l macl, @-r15 + sts.l mach, @-r15 + stc.l gbr, @-r15 + stc.l ssr, @-r15 + stc.l sr, @-r15 + sts.l pr, @-r15 + stc.l spc, @-r15 + + /* switch to bank1 and save r7->r0 */ + mov.l 12f, r9 + stc sr, r8 + or r9, r8 + ldc r8, sr + mov.l r7, @-r15 + mov.l r6, @-r15 + mov.l r5, @-r15 + mov.l r4, @-r15 + mov.l r3, @-r15 + mov.l r2, @-r15 + mov.l r1, @-r15 + mov.l r0, @-r15 + + /* switch to bank0 and save r7->r0 */ + mov.l 12f, r9 + not r9, r9 + stc sr, r8 + and r9, r8 + ldc r8, sr + mov.l r7, @-r15 + mov.l r6, @-r15 + mov.l r5, @-r15 + mov.l r4, @-r15 + mov.l r3, @-r15 + mov.l r2, @-r15 + mov.l r1, @-r15 + mov.l r0, @-r15 + + mov.l r4, @-r15 /* save indirection page again */ + + bsr swap_pages /* swap pages before jumping to new kernel */ + nop + + mova 11f, r0 + mov.l r15, @r0 /* save pointer to stack */ + + jsr @r6 /* hand over control to new kernel */ + nop + + mov.l 11f, r15 /* get pointer to stack */ + mov.l @r15+, r4 /* restore r4 to get indirection page */ - /* stack setting */ - add r8,r5 - mov r5,r15 + bsr swap_pages /* swap pages back to previous state */ + nop + /* make sure bank0 is active and restore r0->r7 */ + mov.l 12f, r9 + not r9, r9 + stc sr, r8 + and r9, r8 + ldc r8, sr + mov.l @r15+, r0 + mov.l @r15+, r1 + mov.l @r15+, r2 + mov.l @r15+, r3 + mov.l @r15+, r4 + mov.l @r15+, r5 + mov.l @r15+, r6 + mov.l @r15+, r7 + + /* switch to bank1 and restore r0->r7 */ + mov.l 12f, r9 + stc sr, r8 + or r9, r8 + ldc r8, sr + mov.l @r15+, r0 + mov.l @r15+, r1 + mov.l @r15+, r2 + mov.l @r15+, r3 + mov.l @r15+, r4 + mov.l @r15+, r5 + mov.l @r15+, r6 + mov.l @r15+, r7 + + /* switch back to bank0 */ + mov.l 12f, r9 + not r9, r9 + stc sr, r8 + and r9, r8 + ldc r8, sr + + /* restore other random registers */ + ldc.l @r15+, spc + lds.l @r15+, pr + ldc.l @r15+, sr + ldc.l @r15+, ssr + ldc.l @r15+, gbr + lds.l @r15+, mach + lds.l @r15+, macl + + /* restore r8->r15 */ + mov.l @r15+, r8 + mov.l @r15+, r9 + mov.l @r15+, r10 + mov.l @r15+, r11 + mov.l @r15+, r12 + mov.l @r15+, r13 + mov.l @r15+, r14 + mov.l @r15+, r15 + rts + nop + +swap_pages: bra 1f - mov r4,r0 /* cmd = indirection_page */ + mov r4,r0 /* cmd = indirection_page */ 0: mov.l @r4+,r0 /* cmd = *ind++ */ @@ -37,52 +160,70 @@ relocate_new_kernel: tst #1,r0 bt 2f bra 0b - mov r2,r5 + mov r2,r5 2: /* else if(cmd & IND_INDIRECTION) ind = addr */ tst #2,r0 bt 3f bra 0b - mov r2,r4 + mov r2,r4 -3: /* else if(cmd & IND_DONE) goto 6 */ +3: /* else if(cmd & IND_DONE) return */ tst #4,r0 bt 4f - bra 6f - nop + rts + nop 4: /* else if(cmd & IND_SOURCE) memcpy(dst,addr,PAGE_SIZE) */ tst #8,r0 bt 0b - mov r8,r3 + mov.l 10f,r3 /* PAGE_SIZE */ shlr2 r3 shlr2 r3 5: dt r3 - mov.l @r2+,r1 /* 16n+0 */ - mov.l r1,@r5 - add #4,r5 - mov.l @r2+,r1 /* 16n+4 */ - mov.l r1,@r5 - add #4,r5 - mov.l @r2+,r1 /* 16n+8 */ - mov.l r1,@r5 - add #4,r5 - mov.l @r2+,r1 /* 16n+12 */ - mov.l r1,@r5 - add #4,r5 + + /* regular kexec just overwrites the destination page + * with the contents of the source page. + * for the kexec jump case we need to swap the contents + * of the pages. + * to keep it simple swap the contents for both cases. + */ + mov.l @(0, r2), r8 + mov.l @(0, r5), r1 + mov.l r8, @(0, r5) + mov.l r1, @(0, r2) + + mov.l @(4, r2), r8 + mov.l @(4, r5), r1 + mov.l r8, @(4, r5) + mov.l r1, @(4, r2) + + mov.l @(8, r2), r8 + mov.l @(8, r5), r1 + mov.l r8, @(8, r5) + mov.l r1, @(8, r2) + + mov.l @(12, r2), r8 + mov.l @(12, r5), r1 + mov.l r8, @(12, r5) + mov.l r1, @(12, r2) + + add #16,r5 + add #16,r2 bf 5b bra 0b - nop -6: - jmp @r6 - nop + nop .align 2 10: .long PAGE_SIZE +11: + .long 0 +12: + .long 0x20000000 ! RB=1 relocate_new_kernel_end: -- GitLab From a6bab7b5c18501e4dd3201ae8ac1dc6da5f07acc Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 18 Mar 2009 19:06:15 +0900 Subject: [PATCH 3689/4982] sh: kexec: Drop SR.BL bit toggling. For the time being, this creates far more problems than it solves, evident by the second local_irq_disable(). Kill all of this off and rely on IRQ disabling to protect against the VBR reload. Signed-off-by: Paul Mundt --- arch/sh/kernel/machine_kexec.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c index c44efb73ab1..69268c0d806 100644 --- a/arch/sh/kernel/machine_kexec.c +++ b/arch/sh/kernel/machine_kexec.c @@ -110,23 +110,22 @@ void machine_kexec(struct kimage *image) memcpy((void *)reboot_code_buffer, relocate_new_kernel, relocate_new_kernel_size); - kexec_info(image); + kexec_info(image); flush_cache_all(); - set_bl_bit(); #if defined(CONFIG_SH_STANDARD_BIOS) asm volatile("ldc %0, vbr" : : "r" (((unsigned long) gdb_vbr_vector) - 0x100) : "memory"); #endif + /* now call it */ rnk = (relocate_new_kernel_t) reboot_code_buffer; (*rnk)(page_list, reboot_code_buffer, image->start); #ifdef CONFIG_KEXEC_JUMP asm volatile("ldc %0, vbr" : : "r" (&vbr_base) : "memory"); - local_irq_disable(); - clear_bl_bit(); + if (image->preserve_context) restore_processor_state(); -- GitLab From 7e6b6f2b949a52382f59a93ecbe86e32e4fcec7c Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 18 Mar 2009 19:07:16 +0900 Subject: [PATCH 3690/4982] sh: kexec jump: fix for ftrace. Save and restore ftrace state when returning from kexec jump in machine_kexec(). Follows the x86 change. Signed-off-by: Paul Mundt --- arch/sh/kernel/machine_kexec.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c index 69268c0d806..cc7c29b0dc8 100644 --- a/arch/sh/kernel/machine_kexec.c +++ b/arch/sh/kernel/machine_kexec.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -78,6 +79,7 @@ void machine_kexec(struct kimage *image) relocate_new_kernel_t rnk; unsigned long entry; unsigned long *ptr; + int save_ftrace_enabled; /* * Nicked from the mips version of machine_kexec(): @@ -97,6 +99,8 @@ void machine_kexec(struct kimage *image) save_processor_state(); #endif + save_ftrace_enabled = __ftrace_enabled_save(); + /* Interrupts aren't acceptable while we reboot */ local_irq_disable(); @@ -138,6 +142,8 @@ void machine_kexec(struct kimage *image) *ptr = virt_to_phys(*ptr); } #endif + + __ftrace_enabled_restore(save_ftrace_enabled); } void arch_crash_save_vmcoreinfo(void) -- GitLab From 1313e7041480f523a09dedc7ef2185d8ee94c163 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 18 Mar 2009 11:03:53 +0100 Subject: [PATCH 3691/4982] ALSA: snd-usb-caiaq: only warn once on streaming errors Limit the number of printed warnings to one in case of streaming errors. printk() happens to be expensive, especially in code called as often as here. Signed-off-by: Daniel Mack Signed-off-by: Takashi Iwai --- sound/usb/caiaq/caiaq-audio.c | 4 +++- sound/usb/caiaq/caiaq-device.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/usb/caiaq/caiaq-audio.c b/sound/usb/caiaq/caiaq-audio.c index fc6d571eeac..577b1129de0 100644 --- a/sound/usb/caiaq/caiaq-audio.c +++ b/sound/usb/caiaq/caiaq-audio.c @@ -114,6 +114,7 @@ static int stream_start(struct snd_usb_caiaqdev *dev) dev->output_panic = 0; dev->first_packet = 1; dev->streaming = 1; + dev->warned = 0; for (i = 0; i < N_URBS; i++) { ret = usb_submit_urb(dev->data_urbs_in[i], GFP_ATOMIC); @@ -406,10 +407,11 @@ static void read_in_urb(struct snd_usb_caiaqdev *dev, break; } - if (dev->input_panic || dev->output_panic) { + if ((dev->input_panic || dev->output_panic) && !dev->warned) { debug("streaming error detected %s %s\n", dev->input_panic ? "(input)" : "", dev->output_panic ? "(output)" : ""); + dev->warned = 1; } } diff --git a/sound/usb/caiaq/caiaq-device.h b/sound/usb/caiaq/caiaq-device.h index 0560c327d99..098b194f725 100644 --- a/sound/usb/caiaq/caiaq-device.h +++ b/sound/usb/caiaq/caiaq-device.h @@ -89,7 +89,7 @@ struct snd_usb_caiaqdev { int audio_out_buf_pos[MAX_STREAMS]; int period_in_count[MAX_STREAMS]; int period_out_count[MAX_STREAMS]; - int input_panic, output_panic; + int input_panic, output_panic, warned; char *audio_in_buf, *audio_out_buf; unsigned int samplerates; -- GitLab From 9311c9b4f12218b588e51806c44d290cfec678a3 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 18 Mar 2009 11:03:54 +0100 Subject: [PATCH 3692/4982] ALSA: snd-usb-caiaq: drop bogus iso packets Drop inbound packets that are smaller than expected. This has been observed at the very beginning of the streaming transaction. And when the hardware is in panic mode (which can only very rarely happen in case of massive EMI chaos), mute the input channels. Signed-off-by: Daniel Mack Tested-by: Mark Hills Signed-off-by: Takashi Iwai --- sound/usb/caiaq/caiaq-audio.c | 6 ++++++ sound/usb/caiaq/caiaq-device.c | 2 ++ sound/usb/caiaq/caiaq-device.h | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/sound/usb/caiaq/caiaq-audio.c b/sound/usb/caiaq/caiaq-audio.c index 577b1129de0..08d51e0c9fe 100644 --- a/sound/usb/caiaq/caiaq-audio.c +++ b/sound/usb/caiaq/caiaq-audio.c @@ -377,6 +377,9 @@ static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev, for (stream = 0; stream < dev->n_streams; stream++, i++) { sub = dev->sub_capture[stream]; + if (dev->input_panic) + usb_buf[i] = 0; + if (sub) { struct snd_pcm_runtime *rt = sub->runtime; char *audio_buf = rt->dma_area; @@ -398,6 +401,9 @@ static void read_in_urb(struct snd_usb_caiaqdev *dev, if (!dev->streaming) return; + if (iso->actual_length < dev->bpp) + return; + switch (dev->spec.data_alignment) { case 0: read_in_urb_mode0(dev, urb, iso); diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c index 5736669df2d..336a93de0b3 100644 --- a/sound/usb/caiaq/caiaq-device.c +++ b/sound/usb/caiaq/caiaq-device.c @@ -251,6 +251,8 @@ int snd_usb_caiaq_set_audio_params (struct snd_usb_caiaqdev *dev, if (dev->audio_parm_answer != 1) debug("unable to set the device's audio params\n"); + else + dev->bpp = bpp; return dev->audio_parm_answer == 1 ? 0 : -EINVAL; } diff --git a/sound/usb/caiaq/caiaq-device.h b/sound/usb/caiaq/caiaq-device.h index 098b194f725..4cce1ad7493 100644 --- a/sound/usb/caiaq/caiaq-device.h +++ b/sound/usb/caiaq/caiaq-device.h @@ -91,7 +91,7 @@ struct snd_usb_caiaqdev { int period_out_count[MAX_STREAMS]; int input_panic, output_panic, warned; char *audio_in_buf, *audio_out_buf; - unsigned int samplerates; + unsigned int samplerates, bpp; struct snd_pcm_substream *sub_playback[MAX_STREAMS]; struct snd_pcm_substream *sub_capture[MAX_STREAMS]; -- GitLab From 28514fe5bbbdbc0f7c9700569378d55cafd061ea Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 18 Mar 2009 11:03:55 +0100 Subject: [PATCH 3693/4982] ALSA: snd-usb-caiaq: bump version number Signed-off-by: Daniel Mack Signed-off-by: Takashi Iwai --- sound/usb/caiaq/caiaq-device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c index 336a93de0b3..771c523b3fc 100644 --- a/sound/usb/caiaq/caiaq-device.c +++ b/sound/usb/caiaq/caiaq-device.c @@ -42,7 +42,7 @@ #endif MODULE_AUTHOR("Daniel Mack "); -MODULE_DESCRIPTION("caiaq USB audio, version 1.3.12"); +MODULE_DESCRIPTION("caiaq USB audio, version 1.3.13"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," "{Native Instruments, RigKontrol3}," -- GitLab From 4fa81ed27781a12f6303b9263056635ae74e3e21 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Wed, 18 Mar 2009 13:27:32 +0100 Subject: [PATCH 3694/4982] [S390] __div64_31 broken for CONFIG_MARCH_G5 The implementation of __div64_31 for G5 machines is broken. The comments in __div64_31 are correct, only the code does not do what the comments say. The part "If the remainder has overflown subtract base and increase the quotient" is only partially realized, the base is subtracted correctly but the quotient is only increased if the dividend had the last bit set. Using the correct instruction fixes the problem. Cc: stable@kernel.org Reported-by: Frans Pop Tested-by: Frans Pop Signed-off-by: Martin Schwidefsky --- arch/s390/lib/div64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/lib/div64.c b/arch/s390/lib/div64.c index a5f8300bf3e..d9e62c0b576 100644 --- a/arch/s390/lib/div64.c +++ b/arch/s390/lib/div64.c @@ -61,7 +61,7 @@ static uint32_t __div64_31(uint64_t *n, uint32_t base) " clr %0,%3\n" " jl 0f\n" " slr %0,%3\n" - " alr %1,%2\n" + " ahi %1,1\n" "0:\n" : "+d" (reg2), "+d" (reg3), "=d" (tmp) : "d" (base), "2" (1UL) : "cc" ); -- GitLab From f55d63854e426e95d7858c2662c2353262a5af70 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 18 Mar 2009 13:27:33 +0100 Subject: [PATCH 3695/4982] [S390] topology: define SD_MC_INIT to fix performance regression The default values for SD_MC_INIT cause an additional cpu usage of up to 40% on some network benchmarks compared to the plain SD_CPU_INIT values. So just define SD_MC_INIT to SD_CPU_INIT. More tuning needs to be done. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/topology.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h index c93eb50e1d0..c979c3b56ab 100644 --- a/arch/s390/include/asm/topology.h +++ b/arch/s390/include/asm/topology.h @@ -30,6 +30,8 @@ static inline void s390_init_cpu_topology(void) }; #endif +#define SD_MC_INIT SD_CPU_INIT + #include #endif /* _ASM_S390_TOPOLOGY_H */ -- GitLab From cf087343805ebfea2b1234b06fd5f12273e865b1 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 18 Mar 2009 13:27:34 +0100 Subject: [PATCH 3696/4982] [S390] ftrace/mcount: fix kernel stack backchain With packed stack the backchain is at a different location. Just use __SF_BACKCHAIN as an offset to store the backchain. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/mcount.S | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S index 397d131a345..80641224a09 100644 --- a/arch/s390/kernel/mcount.S +++ b/arch/s390/kernel/mcount.S @@ -5,6 +5,8 @@ * */ +#include + #ifndef CONFIG_64BIT .globl _mcount _mcount: @@ -14,7 +16,7 @@ _mcount: ahi %r15,-96 l %r3,100(%r15) la %r2,0(%r14) - st %r1,0(%r15) + st %r1,__SF_BACKCHAIN(%r15) la %r3,0(%r3) bras %r14,0f .long ftrace_trace_function @@ -38,7 +40,7 @@ _mcount: stg %r14,112(%r15) lgr %r1,%r15 aghi %r15,-160 - stg %r1,0(%r15) + stg %r1,__SF_BACKCHAIN(%r15) lgr %r2,%r14 lg %r3,168(%r15) larl %r14,ftrace_trace_function -- GitLab From 2887fc5aa60803b9d6d38c79248805f08d8b0e28 Mon Sep 17 00:00:00 2001 From: Gerald Schaefer Date: Wed, 18 Mar 2009 13:27:35 +0100 Subject: [PATCH 3697/4982] [S390] Dont check for pfn_valid() in uaccess_pt.c pfn_valid() actually checks for a valid struct page and not for a valid pfn. Using xip mappings w/o struct pages, this will result in -EFAULT returned by the (page table walk) user copy functions, even though there is valid memory. Those user copy functions don't need a struct page, so this patch just removes the pfn_valid() check. Signed-off-by: Gerald Schaefer Signed-off-by: Martin Schwidefsky --- arch/s390/lib/uaccess_pt.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c index d66215b0fde..b0b84c35b0a 100644 --- a/arch/s390/lib/uaccess_pt.c +++ b/arch/s390/lib/uaccess_pt.c @@ -119,8 +119,6 @@ retry: goto fault; pfn = pte_pfn(*pte); - if (!pfn_valid(pfn)) - goto out; offset = uaddr & (PAGE_SIZE - 1); size = min(n - done, PAGE_SIZE - offset); @@ -135,7 +133,6 @@ retry: done += size; uaddr += size; } while (done < n); -out: spin_unlock(&mm->page_table_lock); return n - done; fault: @@ -163,9 +160,6 @@ retry: goto fault; pfn = pte_pfn(*pte); - if (!pfn_valid(pfn)) - goto out; - ret = (pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE - 1)); out: return ret; @@ -244,11 +238,6 @@ retry: goto fault; pfn = pte_pfn(*pte); - if (!pfn_valid(pfn)) { - done = -1; - goto out; - } - offset = uaddr & (PAGE_SIZE-1); addr = (char *)(pfn << PAGE_SHIFT) + offset; len = min(count - done, PAGE_SIZE - offset); @@ -256,7 +245,6 @@ retry: done += len_str; uaddr += len_str; } while ((len_str == len) && (done < count)); -out: spin_unlock(&mm->page_table_lock); return done + 1; fault: @@ -325,12 +313,7 @@ retry: } pfn_from = pte_pfn(*pte_from); - if (!pfn_valid(pfn_from)) - goto out; pfn_to = pte_pfn(*pte_to); - if (!pfn_valid(pfn_to)) - goto out; - offset_from = uaddr_from & (PAGE_SIZE-1); offset_to = uaddr_from & (PAGE_SIZE-1); offset_max = max(offset_from, offset_to); @@ -342,7 +325,6 @@ retry: uaddr_from += size; uaddr_to += size; } while (done < n); -out: spin_unlock(&mm->page_table_lock); return n - done; fault: -- GitLab From f481bfafd36e621d6cbc62d4b25f74811410aef7 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Wed, 18 Mar 2009 13:27:36 +0100 Subject: [PATCH 3698/4982] [S390] make page table walking more robust Make page table walking on s390 more robust. The current code requires that the pgd/pud/pmd/pte loop is only done for address ranges that are below the end address of the last vma of the address space. But this is not always true, e.g. the generic page table walker does not guarantee this. Change TASK_SIZE/TASK_SIZE_OF to reflect the current size of the address space. This makes the generic page table walker happy but it breaks the upgrade of a 3 level page table to a 4 level page table. To make the upgrade work again another fix is required. Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/processor.h | 5 ++--- arch/s390/mm/mmap.c | 4 ++-- arch/s390/mm/pgtable.c | 2 ++ 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index 066b99502e0..db4523fe38a 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h @@ -61,7 +61,7 @@ extern void print_cpu_info(struct cpuinfo_S390 *); extern int get_cpu_capability(unsigned int *); /* - * User space process size: 2GB for 31 bit, 4TB for 64 bit. + * User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit. */ #ifndef __s390x__ @@ -70,8 +70,7 @@ extern int get_cpu_capability(unsigned int *); #else /* __s390x__ */ -#define TASK_SIZE_OF(tsk) (test_tsk_thread_flag(tsk,TIF_31BIT) ? \ - (1UL << 31) : (1UL << 53)) +#define TASK_SIZE_OF(tsk) ((tsk)->mm->context.asce_limit) #define TASK_UNMAPPED_BASE (test_thread_flag(TIF_31BIT) ? \ (1UL << 30) : (1UL << 41)) #define TASK_SIZE TASK_SIZE_OF(current) diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c index 5932a824547..346dd0c5cbd 100644 --- a/arch/s390/mm/mmap.c +++ b/arch/s390/mm/mmap.c @@ -35,7 +35,7 @@ * Leave an at least ~128 MB hole. */ #define MIN_GAP (128*1024*1024) -#define MAX_GAP (TASK_SIZE/6*5) +#define MAX_GAP (STACK_TOP/6*5) static inline unsigned long mmap_base(void) { @@ -46,7 +46,7 @@ static inline unsigned long mmap_base(void) else if (gap > MAX_GAP) gap = MAX_GAP; - return TASK_SIZE - (gap & PAGE_MASK); + return STACK_TOP - (gap & PAGE_MASK); } static inline int mmap_is_legacy(void) diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 0767827540b..6b6ddc4ea02 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -117,6 +117,7 @@ repeat: crst_table_init(table, entry); pgd_populate(mm, (pgd_t *) table, (pud_t *) pgd); mm->pgd = (pgd_t *) table; + mm->task_size = mm->context.asce_limit; table = NULL; } spin_unlock(&mm->page_table_lock); @@ -154,6 +155,7 @@ void crst_table_downgrade(struct mm_struct *mm, unsigned long limit) BUG(); } mm->pgd = (pgd_t *) (pgd_val(*pgd) & _REGION_ENTRY_ORIGIN); + mm->task_size = mm->context.asce_limit; crst_table_free(mm, (unsigned long *) pgd); } update_mm(mm, current); -- GitLab From 0fb1d9bcbcf701a45835aa150c57ca54ea685bfa Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Wed, 18 Mar 2009 13:27:37 +0100 Subject: [PATCH 3699/4982] [S390] make page table upgrade work again After TASK_SIZE now gives the current size of the address space the upgrade of a 64 bit process from 3 to 4 levels of page table needs to use the arch_mmap_check hook to catch large mmap lengths. The get_unmapped_area* functions need to check for -ENOMEM from the arch_get_unmapped_area*, upgrade the page table and retry. Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/mman.h | 5 ++++ arch/s390/mm/mmap.c | 44 ++++++++++++++++++++++++------------ 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/arch/s390/include/asm/mman.h b/arch/s390/include/asm/mman.h index 7839767d837..da01432e8f4 100644 --- a/arch/s390/include/asm/mman.h +++ b/arch/s390/include/asm/mman.h @@ -22,4 +22,9 @@ #define MCL_CURRENT 1 /* lock all current mappings */ #define MCL_FUTURE 2 /* lock all future mappings */ +#if defined(__KERNEL__) && !defined(__ASSEMBLY__) && defined(CONFIG_64BIT) +int s390_mmap_check(unsigned long addr, unsigned long len); +#define arch_mmap_check(addr,len,flags) s390_mmap_check(addr,len) +#endif + #endif /* __S390_MMAN_H__ */ diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c index 346dd0c5cbd..e008d236cc1 100644 --- a/arch/s390/mm/mmap.c +++ b/arch/s390/mm/mmap.c @@ -89,42 +89,58 @@ EXPORT_SYMBOL_GPL(arch_pick_mmap_layout); #else +int s390_mmap_check(unsigned long addr, unsigned long len) +{ + if (!test_thread_flag(TIF_31BIT) && + len >= TASK_SIZE && TASK_SIZE < (1UL << 53)) + return crst_table_upgrade(current->mm, 1UL << 53); + return 0; +} + static unsigned long s390_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) { struct mm_struct *mm = current->mm; + unsigned long area; int rc; - addr = arch_get_unmapped_area(filp, addr, len, pgoff, flags); - if (addr & ~PAGE_MASK) - return addr; - if (unlikely(mm->context.asce_limit < addr + len)) { - rc = crst_table_upgrade(mm, addr + len); + area = arch_get_unmapped_area(filp, addr, len, pgoff, flags); + if (!(area & ~PAGE_MASK)) + return area; + if (area == -ENOMEM && + !test_thread_flag(TIF_31BIT) && TASK_SIZE < (1UL << 53)) { + /* Upgrade the page table to 4 levels and retry. */ + rc = crst_table_upgrade(mm, 1UL << 53); if (rc) return (unsigned long) rc; + area = arch_get_unmapped_area(filp, addr, len, pgoff, flags); } - return addr; + return area; } static unsigned long -s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, +s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr, const unsigned long len, const unsigned long pgoff, const unsigned long flags) { struct mm_struct *mm = current->mm; - unsigned long addr = addr0; + unsigned long area; int rc; - addr = arch_get_unmapped_area_topdown(filp, addr, len, pgoff, flags); - if (addr & ~PAGE_MASK) - return addr; - if (unlikely(mm->context.asce_limit < addr + len)) { - rc = crst_table_upgrade(mm, addr + len); + area = arch_get_unmapped_area_topdown(filp, addr, len, pgoff, flags); + if (!(area & ~PAGE_MASK)) + return area; + if (area == -ENOMEM && + !test_thread_flag(TIF_31BIT) && TASK_SIZE < (1UL << 53)) { + /* Upgrade the page table to 4 levels and retry. */ + rc = crst_table_upgrade(mm, 1UL << 53); if (rc) return (unsigned long) rc; + area = arch_get_unmapped_area_topdown(filp, addr, len, + pgoff, flags); } - return addr; + return area; } /* * This function, called very early during the creation of a new -- GitLab From d0573facf21d1e5cfbc1ddac272b7592722e6c01 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Mar 2009 09:22:17 -0700 Subject: [PATCH 3700/4982] Staging: benet: remove driver now that it is merged in drivers/net/ The benet driver is now in the proper place in drivers/net/benet, so we can remove the staging version. Acked-by: Sathya Perla Cc: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/benet/Kconfig | 7 - drivers/staging/benet/MAINTAINERS | 6 - drivers/staging/benet/Makefile | 14 - drivers/staging/benet/TODO | 6 - drivers/staging/benet/asyncmesg.h | 82 -- drivers/staging/benet/be_cm.h | 134 -- drivers/staging/benet/be_common.h | 53 - drivers/staging/benet/be_ethtool.c | 348 ------ drivers/staging/benet/be_init.c | 1382 --------------------- drivers/staging/benet/be_int.c | 863 ------------- drivers/staging/benet/be_netif.c | 705 ----------- drivers/staging/benet/benet.h | 429 ------- drivers/staging/benet/bestatus.h | 103 -- drivers/staging/benet/cev.h | 243 ---- drivers/staging/benet/cq.c | 211 ---- drivers/staging/benet/descriptors.h | 71 -- drivers/staging/benet/doorbells.h | 179 --- drivers/staging/benet/ep.h | 66 - drivers/staging/benet/eq.c | 299 ----- drivers/staging/benet/eth.c | 1273 ------------------- drivers/staging/benet/etx_context.h | 55 - drivers/staging/benet/funcobj.c | 565 --------- drivers/staging/benet/fwcmd_common.h | 222 ---- drivers/staging/benet/fwcmd_common_bmap.h | 717 ----------- drivers/staging/benet/fwcmd_eth_bmap.h | 280 ----- drivers/staging/benet/fwcmd_hdr_bmap.h | 54 - drivers/staging/benet/fwcmd_mcc.h | 94 -- drivers/staging/benet/fwcmd_opcodes.h | 244 ---- drivers/staging/benet/fwcmd_types_bmap.h | 29 - drivers/staging/benet/host_struct.h | 182 --- drivers/staging/benet/hwlib.h | 830 ------------- drivers/staging/benet/mpu.c | 1364 -------------------- drivers/staging/benet/mpu.h | 74 -- drivers/staging/benet/mpu_context.h | 46 - drivers/staging/benet/pcicfg.h | 825 ------------ drivers/staging/benet/post_codes.h | 111 -- drivers/staging/benet/regmap.h | 68 - 39 files changed, 12237 deletions(-) delete mode 100644 drivers/staging/benet/Kconfig delete mode 100644 drivers/staging/benet/MAINTAINERS delete mode 100644 drivers/staging/benet/Makefile delete mode 100644 drivers/staging/benet/TODO delete mode 100644 drivers/staging/benet/asyncmesg.h delete mode 100644 drivers/staging/benet/be_cm.h delete mode 100644 drivers/staging/benet/be_common.h delete mode 100644 drivers/staging/benet/be_ethtool.c delete mode 100644 drivers/staging/benet/be_init.c delete mode 100644 drivers/staging/benet/be_int.c delete mode 100644 drivers/staging/benet/be_netif.c delete mode 100644 drivers/staging/benet/benet.h delete mode 100644 drivers/staging/benet/bestatus.h delete mode 100644 drivers/staging/benet/cev.h delete mode 100644 drivers/staging/benet/cq.c delete mode 100644 drivers/staging/benet/descriptors.h delete mode 100644 drivers/staging/benet/doorbells.h delete mode 100644 drivers/staging/benet/ep.h delete mode 100644 drivers/staging/benet/eq.c delete mode 100644 drivers/staging/benet/eth.c delete mode 100644 drivers/staging/benet/etx_context.h delete mode 100644 drivers/staging/benet/funcobj.c delete mode 100644 drivers/staging/benet/fwcmd_common.h delete mode 100644 drivers/staging/benet/fwcmd_common_bmap.h delete mode 100644 drivers/staging/benet/fwcmd_eth_bmap.h delete mode 100644 drivers/staging/benet/fwcmd_hdr_bmap.h delete mode 100644 drivers/staging/benet/fwcmd_mcc.h delete mode 100644 drivers/staging/benet/fwcmd_opcodes.h delete mode 100644 drivers/staging/benet/fwcmd_types_bmap.h delete mode 100644 drivers/staging/benet/host_struct.h delete mode 100644 drivers/staging/benet/hwlib.h delete mode 100644 drivers/staging/benet/mpu.c delete mode 100644 drivers/staging/benet/mpu.h delete mode 100644 drivers/staging/benet/mpu_context.h delete mode 100644 drivers/staging/benet/pcicfg.h delete mode 100644 drivers/staging/benet/post_codes.h delete mode 100644 drivers/staging/benet/regmap.h diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index ce6badded47..211af86a6c5 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -73,8 +73,6 @@ source "drivers/staging/rt2860/Kconfig" source "drivers/staging/rt2870/Kconfig" -source "drivers/staging/benet/Kconfig" - source "drivers/staging/comedi/Kconfig" source "drivers/staging/asus_oled/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 9ddcc2bb336..47a56f5ffab 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -19,7 +19,6 @@ obj-$(CONFIG_AGNX) += agnx/ obj-$(CONFIG_OTUS) += otus/ obj-$(CONFIG_RT2860) += rt2860/ obj-$(CONFIG_RT2870) += rt2870/ -obj-$(CONFIG_BENET) += benet/ obj-$(CONFIG_COMEDI) += comedi/ obj-$(CONFIG_ASUS_OLED) += asus_oled/ obj-$(CONFIG_PANEL) += panel/ diff --git a/drivers/staging/benet/Kconfig b/drivers/staging/benet/Kconfig deleted file mode 100644 index f6806074f99..00000000000 --- a/drivers/staging/benet/Kconfig +++ /dev/null @@ -1,7 +0,0 @@ -config BENET - tristate "ServerEngines 10Gb NIC - BladeEngine" - depends on PCI && INET - select INET_LRO - help - This driver implements the NIC functionality for ServerEngines - 10Gb network adapter BladeEngine (EC 3210). diff --git a/drivers/staging/benet/MAINTAINERS b/drivers/staging/benet/MAINTAINERS deleted file mode 100644 index d5ce340218b..00000000000 --- a/drivers/staging/benet/MAINTAINERS +++ /dev/null @@ -1,6 +0,0 @@ -SERVER ENGINES 10Gbe NIC - BLADE-ENGINE -P: Subbu Seetharaman -M: subbus@serverengines.com -L: netdev@vger.kernel.org -W: http://www.serverengines.com -S: Supported diff --git a/drivers/staging/benet/Makefile b/drivers/staging/benet/Makefile deleted file mode 100644 index 460b923b99b..00000000000 --- a/drivers/staging/benet/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# -# Makefile to build the network driver for ServerEngine's BladeEngine -# -obj-$(CONFIG_BENET) += benet.o - -benet-y := be_init.o \ - be_int.o \ - be_netif.o \ - be_ethtool.o \ - funcobj.o \ - cq.o \ - eq.o \ - mpu.o \ - eth.o diff --git a/drivers/staging/benet/TODO b/drivers/staging/benet/TODO deleted file mode 100644 index a51dfb59a62..00000000000 --- a/drivers/staging/benet/TODO +++ /dev/null @@ -1,6 +0,0 @@ -TODO: - - remove wrappers around common iowrite functions - - full netdev audit of common problems/issues - -Please send all patches and questions to Subbu Seetharaman - and Greg Kroah-Hartman diff --git a/drivers/staging/benet/asyncmesg.h b/drivers/staging/benet/asyncmesg.h deleted file mode 100644 index d1e779adb84..00000000000 --- a/drivers/staging/benet/asyncmesg.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __asyncmesg_amap_h__ -#define __asyncmesg_amap_h__ -#include "fwcmd_common.h" - -/* --- ASYNC_EVENT_CODES --- */ -#define ASYNC_EVENT_CODE_LINK_STATE (1) -#define ASYNC_EVENT_CODE_ISCSI (2) - -/* --- ASYNC_LINK_STATES --- */ -#define ASYNC_EVENT_LINK_DOWN (0) /* Link Down on a port */ -#define ASYNC_EVENT_LINK_UP (1) /* Link Up on a port */ - -/* - * The last 4 bytes of the async events have this common format. It allows - * the driver to distinguish [link]MCC_CQ_ENTRY[/link] structs from - * asynchronous events. Both arrive on the same completion queue. This - * structure also contains the common fields used to decode the async event. - */ -struct BE_ASYNC_EVENT_TRAILER_AMAP { - u8 rsvd0[8]; /* DWORD 0 */ - u8 event_code[8]; /* DWORD 0 */ - u8 event_type[8]; /* DWORD 0 */ - u8 rsvd1[6]; /* DWORD 0 */ - u8 async_event; /* DWORD 0 */ - u8 valid; /* DWORD 0 */ -} __packed; -struct ASYNC_EVENT_TRAILER_AMAP { - u32 dw[1]; -}; - -/* - * Applicable in Initiator, Target and NIC modes. - * A link state async event is seen by all device drivers as soon they - * create an MCC ring. Thereafter, anytime the link status changes the - * drivers will receive a link state async event. Notifications continue to - * be sent until a driver destroys its MCC ring. A link down event is - * reported when either port loses link. A link up event is reported - * when either port regains link. When BE's failover mechanism is enabled, a - * link down on the active port causes traffic to be diverted to the standby - * port by the BE's ARM firmware (assuming the standby port has link). In - * this case, the standy port assumes the active status. Note: when link is - * restored on the failed port, traffic continues on the currently active - * port. The ARM firmware does not attempt to 'fail back' traffic to - * the restored port. - */ -struct BE_ASYNC_EVENT_LINK_STATE_AMAP { - u8 port0_link_status[8]; - u8 port1_link_status[8]; - u8 active_port[8]; - u8 rsvd0[8]; /* DWORD 0 */ - u8 port0_duplex[8]; - u8 port0_speed[8]; - u8 port1_duplex[8]; - u8 port1_speed[8]; - u8 port0_fault[8]; - u8 port1_fault[8]; - u8 rsvd1[2][8]; /* DWORD 2 */ - struct BE_ASYNC_EVENT_TRAILER_AMAP trailer; -} __packed; -struct ASYNC_EVENT_LINK_STATE_AMAP { - u32 dw[4]; -}; -#endif /* __asyncmesg_amap_h__ */ diff --git a/drivers/staging/benet/be_cm.h b/drivers/staging/benet/be_cm.h deleted file mode 100644 index b7a1dfd20c3..00000000000 --- a/drivers/staging/benet/be_cm.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __be_cm_amap_h__ -#define __be_cm_amap_h__ -#include "be_common.h" -#include "etx_context.h" -#include "mpu_context.h" - -/* - * --- CEV_WATERMARK_ENUM --- - * CQ/EQ Watermark Encodings. Encoded as number of free entries in - * Queue when Watermark is reached. - */ -#define CEV_WMARK_0 (0) /* Watermark when Queue full */ -#define CEV_WMARK_16 (1) /* Watermark at 16 free entries */ -#define CEV_WMARK_32 (2) /* Watermark at 32 free entries */ -#define CEV_WMARK_48 (3) /* Watermark at 48 free entries */ -#define CEV_WMARK_64 (4) /* Watermark at 64 free entries */ -#define CEV_WMARK_80 (5) /* Watermark at 80 free entries */ -#define CEV_WMARK_96 (6) /* Watermark at 96 free entries */ -#define CEV_WMARK_112 (7) /* Watermark at 112 free entries */ -#define CEV_WMARK_128 (8) /* Watermark at 128 free entries */ -#define CEV_WMARK_144 (9) /* Watermark at 144 free entries */ -#define CEV_WMARK_160 (10) /* Watermark at 160 free entries */ -#define CEV_WMARK_176 (11) /* Watermark at 176 free entries */ -#define CEV_WMARK_192 (12) /* Watermark at 192 free entries */ -#define CEV_WMARK_208 (13) /* Watermark at 208 free entries */ -#define CEV_WMARK_224 (14) /* Watermark at 224 free entries */ -#define CEV_WMARK_240 (15) /* Watermark at 240 free entries */ - -/* - * --- CQ_CNT_ENUM --- - * Completion Queue Count Encodings. - */ -#define CEV_CQ_CNT_256 (0) /* CQ has 256 entries */ -#define CEV_CQ_CNT_512 (1) /* CQ has 512 entries */ -#define CEV_CQ_CNT_1024 (2) /* CQ has 1024 entries */ - -/* - * --- EQ_CNT_ENUM --- - * Event Queue Count Encodings. - */ -#define CEV_EQ_CNT_256 (0) /* EQ has 256 entries (16-byte EQEs only) */ -#define CEV_EQ_CNT_512 (1) /* EQ has 512 entries (16-byte EQEs only) */ -#define CEV_EQ_CNT_1024 (2) /* EQ has 1024 entries (4-byte or */ - /* 16-byte EQEs only) */ -#define CEV_EQ_CNT_2048 (3) /* EQ has 2048 entries (4-byte or */ - /* 16-byte EQEs only) */ -#define CEV_EQ_CNT_4096 (4) /* EQ has 4096 entries (4-byte EQEs only) */ - -/* - * --- EQ_SIZE_ENUM --- - * Event Queue Entry Size Encoding. - */ -#define CEV_EQ_SIZE_4 (0) /* EQE is 4 bytes */ -#define CEV_EQ_SIZE_16 (1) /* EQE is 16 bytes */ - -/* - * Completion Queue Context Table Entry. Contains the state of a CQ. - * Located in RAM within the CEV block. - */ -struct BE_CQ_CONTEXT_AMAP { - u8 Cidx[11]; /* DWORD 0 */ - u8 Watermark[4]; /* DWORD 0 */ - u8 NoDelay; /* DWORD 0 */ - u8 EPIdx[11]; /* DWORD 0 */ - u8 Count[2]; /* DWORD 0 */ - u8 valid; /* DWORD 0 */ - u8 SolEvent; /* DWORD 0 */ - u8 Eventable; /* DWORD 0 */ - u8 Pidx[11]; /* DWORD 1 */ - u8 PD[10]; /* DWORD 1 */ - u8 EQID[7]; /* DWORD 1 */ - u8 Func; /* DWORD 1 */ - u8 WME; /* DWORD 1 */ - u8 Stalled; /* DWORD 1 */ - u8 Armed; /* DWORD 1 */ -} __packed; -struct CQ_CONTEXT_AMAP { - u32 dw[2]; -}; - -/* - * Event Queue Context Table Entry. Contains the state of an EQ. - * Located in RAM in the CEV block. - */ -struct BE_EQ_CONTEXT_AMAP { - u8 Cidx[13]; /* DWORD 0 */ - u8 rsvd0[2]; /* DWORD 0 */ - u8 Func; /* DWORD 0 */ - u8 EPIdx[13]; /* DWORD 0 */ - u8 valid; /* DWORD 0 */ - u8 rsvd1; /* DWORD 0 */ - u8 Size; /* DWORD 0 */ - u8 Pidx[13]; /* DWORD 1 */ - u8 rsvd2[3]; /* DWORD 1 */ - u8 PD[10]; /* DWORD 1 */ - u8 Count[3]; /* DWORD 1 */ - u8 SolEvent; /* DWORD 1 */ - u8 Stalled; /* DWORD 1 */ - u8 Armed; /* DWORD 1 */ - u8 Watermark[4]; /* DWORD 2 */ - u8 WME; /* DWORD 2 */ - u8 rsvd3[3]; /* DWORD 2 */ - u8 EventVect[6]; /* DWORD 2 */ - u8 rsvd4[2]; /* DWORD 2 */ - u8 Delay[8]; /* DWORD 2 */ - u8 rsvd5[6]; /* DWORD 2 */ - u8 TMR; /* DWORD 2 */ - u8 rsvd6; /* DWORD 2 */ - u8 rsvd7[32]; /* DWORD 3 */ -} __packed; -struct EQ_CONTEXT_AMAP { - u32 dw[4]; -}; - -#endif /* __be_cm_amap_h__ */ diff --git a/drivers/staging/benet/be_common.h b/drivers/staging/benet/be_common.h deleted file mode 100644 index 7e63dc5e334..00000000000 --- a/drivers/staging/benet/be_common.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __be_common_amap_h__ -#define __be_common_amap_h__ - -/* Physical Address. */ -struct BE_PHYS_ADDR_AMAP { - u8 lo[32]; /* DWORD 0 */ - u8 hi[32]; /* DWORD 1 */ -} __packed; -struct PHYS_ADDR_AMAP { - u32 dw[2]; -}; - -/* Virtual Address. */ -struct BE_VIRT_ADDR_AMAP { - u8 lo[32]; /* DWORD 0 */ - u8 hi[32]; /* DWORD 1 */ -} __packed; -struct VIRT_ADDR_AMAP { - u32 dw[2]; -}; - -/* Scatter gather element. */ -struct BE_SGE_AMAP { - u8 addr_hi[32]; /* DWORD 0 */ - u8 addr_lo[32]; /* DWORD 1 */ - u8 rsvd0[32]; /* DWORD 2 */ - u8 len[16]; /* DWORD 3 */ - u8 rsvd1[16]; /* DWORD 3 */ -} __packed; -struct SGE_AMAP { - u32 dw[4]; -}; - -#endif /* __be_common_amap_h__ */ diff --git a/drivers/staging/benet/be_ethtool.c b/drivers/staging/benet/be_ethtool.c deleted file mode 100644 index 027af85707a..00000000000 --- a/drivers/staging/benet/be_ethtool.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * be_ethtool.c - * - * This file contains various functions that ethtool can use - * to talk to the driver and the BE H/W. - */ - -#include "benet.h" - -#include - -static const char benet_gstrings_stats[][ETH_GSTRING_LEN] = { -/* net_device_stats */ - "rx_packets", - "tx_packets", - "rx_bytes", - "tx_bytes", - "rx_errors", - "tx_errors", - "rx_dropped", - "tx_dropped", - "multicast", - "collisions", - "rx_length_errors", - "rx_over_errors", - "rx_crc_errors", - "rx_frame_errors", - "rx_fifo_errors", - "rx_missed_errors", - "tx_aborted_errors", - "tx_carrier_errors", - "tx_fifo_errors", - "tx_heartbeat_errors", - "tx_window_errors", - "rx_compressed", - "tc_compressed", -/* BE driver Stats */ - "bes_tx_reqs", - "bes_tx_fails", - "bes_fwd_reqs", - "bes_tx_wrbs", - "bes_interrupts", - "bes_events", - "bes_tx_events", - "bes_rx_events", - "bes_tx_compl", - "bes_rx_compl", - "bes_ethrx_post_fail", - "bes_802_3_dropped_frames", - "bes_802_3_malformed_frames", - "bes_rx_misc_pkts", - "bes_eth_tx_rate", - "bes_eth_rx_rate", - "Num Packets collected", - "Num Times Flushed", -}; - -#define NET_DEV_STATS_LEN \ - (sizeof(struct net_device_stats)/sizeof(unsigned long)) - -#define BENET_STATS_LEN ARRAY_SIZE(benet_gstrings_stats) - -static void -be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - - strncpy(drvinfo->driver, be_driver_name, 32); - strncpy(drvinfo->version, be_drvr_ver, 32); - strncpy(drvinfo->fw_version, be_fw_ver, 32); - strcpy(drvinfo->bus_info, pci_name(adapter->pdev)); - drvinfo->testinfo_len = 0; - drvinfo->regdump_len = 0; - drvinfo->eedump_len = 0; -} - -static int -be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - - coalesce->rx_max_coalesced_frames = adapter->max_rx_coal; - - coalesce->rx_coalesce_usecs = adapter->cur_eqd; - coalesce->rx_coalesce_usecs_high = adapter->max_eqd; - coalesce->rx_coalesce_usecs_low = adapter->min_eqd; - - coalesce->tx_coalesce_usecs = adapter->cur_eqd; - coalesce->tx_coalesce_usecs_high = adapter->max_eqd; - coalesce->tx_coalesce_usecs_low = adapter->min_eqd; - - coalesce->use_adaptive_rx_coalesce = adapter->enable_aic; - coalesce->use_adaptive_tx_coalesce = adapter->enable_aic; - - return 0; -} - -/* - * This routine is used to set interrup coalescing delay *as well as* - * the number of pkts to coalesce for LRO. - */ -static int -be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - struct be_eq_object *eq_objectp; - u32 max, min, cur; - int status; - - adapter->max_rx_coal = coalesce->rx_max_coalesced_frames; - if (adapter->max_rx_coal >= BE_LRO_MAX_PKTS) - adapter->max_rx_coal = BE_LRO_MAX_PKTS; - - if (adapter->enable_aic == 0 && - coalesce->use_adaptive_rx_coalesce == 1) { - /* if AIC is being turned on now, start with an EQD of 0 */ - adapter->cur_eqd = 0; - } - adapter->enable_aic = coalesce->use_adaptive_rx_coalesce; - - /* round off to nearest multiple of 8 */ - max = (((coalesce->rx_coalesce_usecs_high + 4) >> 3) << 3); - min = (((coalesce->rx_coalesce_usecs_low + 4) >> 3) << 3); - cur = (((coalesce->rx_coalesce_usecs + 4) >> 3) << 3); - - if (adapter->enable_aic) { - /* accept low and high if AIC is enabled */ - if (max > MAX_EQD) - max = MAX_EQD; - if (min > max) - min = max; - adapter->max_eqd = max; - adapter->min_eqd = min; - if (adapter->cur_eqd > max) - adapter->cur_eqd = max; - if (adapter->cur_eqd < min) - adapter->cur_eqd = min; - } else { - /* accept specified coalesce_usecs only if AIC is disabled */ - if (cur > MAX_EQD) - cur = MAX_EQD; - eq_objectp = &pnob->event_q_obj; - status = - be_eq_modify_delay(&pnob->fn_obj, 1, &eq_objectp, &cur, - NULL, NULL, NULL); - if (status == BE_SUCCESS) - adapter->cur_eqd = cur; - } - return 0; -} - -static u32 be_get_rx_csum(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - return adapter->rx_csum; -} - -static int be_set_rx_csum(struct net_device *netdev, uint32_t data) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - - if (data) - adapter->rx_csum = 1; - else - adapter->rx_csum = 0; - - return 0; -} - -static void -be_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data) -{ - switch (stringset) { - case ETH_SS_STATS: - memcpy(data, *benet_gstrings_stats, - sizeof(benet_gstrings_stats)); - break; - } -} - -static int be_get_stats_count(struct net_device *netdev) -{ - return BENET_STATS_LEN; -} - -static void -be_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, uint64_t *data) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - int i; - - benet_get_stats(netdev); - - for (i = 0; i <= NET_DEV_STATS_LEN; i++) - data[i] = ((unsigned long *)&adapter->benet_stats)[i]; - - data[i] = adapter->be_stat.bes_tx_reqs; - data[i++] = adapter->be_stat.bes_tx_fails; - data[i++] = adapter->be_stat.bes_fwd_reqs; - data[i++] = adapter->be_stat.bes_tx_wrbs; - - data[i++] = adapter->be_stat.bes_ints; - data[i++] = adapter->be_stat.bes_events; - data[i++] = adapter->be_stat.bes_tx_events; - data[i++] = adapter->be_stat.bes_rx_events; - data[i++] = adapter->be_stat.bes_tx_compl; - data[i++] = adapter->be_stat.bes_rx_compl; - data[i++] = adapter->be_stat.bes_ethrx_post_fail; - data[i++] = adapter->be_stat.bes_802_3_dropped_frames; - data[i++] = adapter->be_stat.bes_802_3_malformed_frames; - data[i++] = adapter->be_stat.bes_rx_misc_pkts; - data[i++] = adapter->be_stat.bes_eth_tx_rate; - data[i++] = adapter->be_stat.bes_eth_rx_rate; - data[i++] = adapter->be_stat.bes_rx_coal; - data[i++] = adapter->be_stat.bes_rx_flush; - -} - -static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) -{ - ecmd->speed = SPEED_10000; - ecmd->duplex = DUPLEX_FULL; - ecmd->autoneg = AUTONEG_DISABLE; - return 0; -} - -/* Get the Ring parameters from the pnob */ -static void -be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) -{ - struct be_net_object *pnob = netdev_priv(netdev); - - /* Pre Set Maxims */ - ring->rx_max_pending = pnob->rx_q_len; - ring->rx_mini_max_pending = ring->rx_mini_max_pending; - ring->rx_jumbo_max_pending = ring->rx_jumbo_max_pending; - ring->tx_max_pending = pnob->tx_q_len; - - /* Current hardware Settings */ - ring->rx_pending = atomic_read(&pnob->rx_q_posted); - ring->rx_mini_pending = ring->rx_mini_pending; - ring->rx_jumbo_pending = ring->rx_jumbo_pending; - ring->tx_pending = atomic_read(&pnob->tx_q_used); - -} - -static void -be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) -{ - struct be_net_object *pnob = netdev_priv(netdev); - bool rxfc, txfc; - int status; - - status = be_eth_get_flow_control(&pnob->fn_obj, &txfc, &rxfc); - if (status != BE_SUCCESS) { - dev_info(&netdev->dev, "Unable to get pause frame settings\n"); - /* return defaults */ - ecmd->rx_pause = 1; - ecmd->tx_pause = 0; - ecmd->autoneg = AUTONEG_ENABLE; - return; - } - - if (txfc == true) - ecmd->tx_pause = 1; - else - ecmd->tx_pause = 0; - - if (rxfc == true) - ecmd->rx_pause = 1; - else - ecmd->rx_pause = 0; - - ecmd->autoneg = AUTONEG_ENABLE; -} - -static int -be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) -{ - struct be_net_object *pnob = netdev_priv(netdev); - bool txfc, rxfc; - int status; - - if (ecmd->autoneg != AUTONEG_ENABLE) - return -EINVAL; - - if (ecmd->tx_pause) - txfc = true; - else - txfc = false; - - if (ecmd->rx_pause) - rxfc = true; - else - rxfc = false; - - status = be_eth_set_flow_control(&pnob->fn_obj, txfc, rxfc); - if (status != BE_SUCCESS) { - dev_info(&netdev->dev, "Unable to set pause frame settings\n"); - return -1; - } - return 0; -} - -struct ethtool_ops be_ethtool_ops = { - .get_settings = be_get_settings, - .get_drvinfo = be_get_drvinfo, - .get_link = ethtool_op_get_link, - .get_coalesce = be_get_coalesce, - .set_coalesce = be_set_coalesce, - .get_ringparam = be_get_ringparam, - .get_pauseparam = be_get_pauseparam, - .set_pauseparam = be_set_pauseparam, - .get_rx_csum = be_get_rx_csum, - .set_rx_csum = be_set_rx_csum, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, - .get_tso = ethtool_op_get_tso, - .set_tso = ethtool_op_set_tso, - .get_strings = be_get_strings, - .get_stats_count = be_get_stats_count, - .get_ethtool_stats = be_get_ethtool_stats, -}; diff --git a/drivers/staging/benet/be_init.c b/drivers/staging/benet/be_init.c deleted file mode 100644 index 12a026c3f9e..00000000000 --- a/drivers/staging/benet/be_init.c +++ /dev/null @@ -1,1382 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include -#include "benet.h" - -#define DRVR_VERSION "1.0.728" - -static const struct pci_device_id be_device_id_table[] = { - {PCI_DEVICE(0x19a2, 0x0201)}, - {0} -}; - -MODULE_DEVICE_TABLE(pci, be_device_id_table); - -MODULE_VERSION(DRVR_VERSION); - -#define DRV_DESCRIPTION "ServerEngines BladeEngine Network Driver Version " - -MODULE_DESCRIPTION(DRV_DESCRIPTION DRVR_VERSION); -MODULE_AUTHOR("ServerEngines"); -MODULE_LICENSE("GPL"); - -static unsigned int msix = 1; -module_param(msix, uint, S_IRUGO); -MODULE_PARM_DESC(msix, "Use MSI-x interrupts"); - -static unsigned int rxbuf_size = 2048; /* Default RX frag size */ -module_param(rxbuf_size, uint, S_IRUGO); -MODULE_PARM_DESC(rxbuf_size, "Size of buffers to hold Rx data"); - -const char be_drvr_ver[] = DRVR_VERSION; -char be_fw_ver[32]; /* F/W version filled in by be_probe */ -char be_driver_name[] = "benet"; - -/* - * Number of entries in each queue. - */ -#define EVENT_Q_LEN 1024 -#define ETH_TXQ_LEN 2048 -#define ETH_TXCQ_LEN 1024 -#define ETH_RXQ_LEN 1024 /* Does not support any other value */ -#define ETH_UC_RXCQ_LEN 1024 -#define ETH_BC_RXCQ_LEN 256 -#define MCC_Q_LEN 64 /* total size not to exceed 8 pages */ -#define MCC_CQ_LEN 256 - -/* Bit mask describing events of interest to be traced */ -unsigned int trace_level; - -static int -init_pci_be_function(struct be_adapter *adapter, struct pci_dev *pdev) -{ - u64 pa; - - /* CSR */ - pa = pci_resource_start(pdev, 2); - adapter->csr_va = ioremap_nocache(pa, pci_resource_len(pdev, 2)); - if (adapter->csr_va == NULL) - return -ENOMEM; - - /* Door Bell */ - pa = pci_resource_start(pdev, 4); - adapter->db_va = ioremap_nocache(pa, (128 * 1024)); - if (adapter->db_va == NULL) { - iounmap(adapter->csr_va); - return -ENOMEM; - } - - /* PCI */ - pa = pci_resource_start(pdev, 1); - adapter->pci_va = ioremap_nocache(pa, pci_resource_len(pdev, 1)); - if (adapter->pci_va == NULL) { - iounmap(adapter->csr_va); - iounmap(adapter->db_va); - return -ENOMEM; - } - return 0; -} - -/* - This function enables the interrupt corresponding to the Event - queue ID for the given NetObject -*/ -void be_enable_eq_intr(struct be_net_object *pnob) -{ - struct CQ_DB_AMAP cqdb; - cqdb.dw[0] = 0; - AMAP_SET_BITS_PTR(CQ_DB, event, &cqdb, 1); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &cqdb, 1); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &cqdb, 0); - AMAP_SET_BITS_PTR(CQ_DB, qid, &cqdb, pnob->event_q_id); - PD_WRITE(&pnob->fn_obj, cq_db, cqdb.dw[0]); -} - -/* - This function disables the interrupt corresponding to the Event - queue ID for the given NetObject -*/ -void be_disable_eq_intr(struct be_net_object *pnob) -{ - struct CQ_DB_AMAP cqdb; - cqdb.dw[0] = 0; - AMAP_SET_BITS_PTR(CQ_DB, event, &cqdb, 1); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &cqdb, 0); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &cqdb, 0); - AMAP_SET_BITS_PTR(CQ_DB, qid, &cqdb, pnob->event_q_id); - PD_WRITE(&pnob->fn_obj, cq_db, cqdb.dw[0]); -} - -/* - This function enables the interrupt from the network function - of the BladeEngine. Use the function be_disable_eq_intr() - to enable the interrupt from the event queue of only one specific - NetObject -*/ -void be_enable_intr(struct be_net_object *pnob) -{ - struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP ctrl; - u32 host_intr; - - ctrl.dw[0] = PCICFG1_READ(&pnob->fn_obj, host_timer_int_ctrl); - host_intr = AMAP_GET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR, - hostintr, ctrl.dw); - if (!host_intr) { - AMAP_SET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR, - hostintr, ctrl.dw, 1); - PCICFG1_WRITE(&pnob->fn_obj, host_timer_int_ctrl, - ctrl.dw[0]); - } -} - -/* - This function disables the interrupt from the network function of - the BladeEngine. Use the function be_disable_eq_intr() to - disable the interrupt from the event queue of only one specific NetObject -*/ -void be_disable_intr(struct be_net_object *pnob) -{ - - struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP ctrl; - u32 host_intr; - ctrl.dw[0] = PCICFG1_READ(&pnob->fn_obj, host_timer_int_ctrl); - host_intr = AMAP_GET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR, - hostintr, ctrl.dw); - if (host_intr) { - AMAP_SET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR, hostintr, - ctrl.dw, 0); - PCICFG1_WRITE(&pnob->fn_obj, host_timer_int_ctrl, - ctrl.dw[0]); - } -} - -static int be_enable_msix(struct be_adapter *adapter) -{ - int i, ret; - - if (!msix) - return -1; - - for (i = 0; i < BE_MAX_REQ_MSIX_VECTORS; i++) - adapter->msix_entries[i].entry = i; - - ret = pci_enable_msix(adapter->pdev, adapter->msix_entries, - BE_MAX_REQ_MSIX_VECTORS); - - if (ret == 0) - adapter->msix_enabled = 1; - return ret; -} - -static int be_register_isr(struct be_adapter *adapter, - struct be_net_object *pnob) -{ - struct net_device *netdev = pnob->netdev; - int intx = 0, r; - - netdev->irq = adapter->pdev->irq; - r = be_enable_msix(adapter); - - if (r == 0) { - r = request_irq(adapter->msix_entries[0].vector, - be_int, IRQF_SHARED, netdev->name, netdev); - if (r) { - printk(KERN_WARNING - "MSIX Request IRQ failed - Errno %d\n", r); - intx = 1; - pci_disable_msix(adapter->pdev); - adapter->msix_enabled = 0; - } - } else { - intx = 1; - } - - if (intx) { - r = request_irq(netdev->irq, be_int, IRQF_SHARED, - netdev->name, netdev); - if (r) { - printk(KERN_WARNING - "INTx Request IRQ failed - Errno %d\n", r); - return -1; - } - } - adapter->isr_registered = 1; - return 0; -} - -static void be_unregister_isr(struct be_adapter *adapter) -{ - struct net_device *netdev = adapter->netdevp; - if (adapter->isr_registered) { - if (adapter->msix_enabled) { - free_irq(adapter->msix_entries[0].vector, netdev); - pci_disable_msix(adapter->pdev); - adapter->msix_enabled = 0; - } else { - free_irq(netdev->irq, netdev); - } - adapter->isr_registered = 0; - } -} - -/* - This function processes the Flush Completions that are issued by the - ARM F/W, when a Recv Ring is destroyed. A flush completion is - identified when a Rx COmpl descriptor has the tcpcksum and udpcksum - set and the pktsize is 32. These completions are received on the - Rx Completion Queue. -*/ -static u32 be_process_rx_flush_cmpl(struct be_net_object *pnob) -{ - struct ETH_RX_COMPL_AMAP *rxcp; - unsigned int i = 0; - while ((rxcp = be_get_rx_cmpl(pnob)) != NULL) { - be_notify_cmpl(pnob, 1, pnob->rx_cq_id, 1); - i++; - } - return i; -} - -static void be_tx_q_clean(struct be_net_object *pnob) -{ - while (atomic_read(&pnob->tx_q_used)) - process_one_tx_compl(pnob, tx_compl_lastwrb_idx_get(pnob)); -} - -static void be_rx_q_clean(struct be_net_object *pnob) -{ - if (pnob->rx_ctxt) { - int i; - struct be_rx_page_info *rx_page_info; - for (i = 0; i < pnob->rx_q_len; i++) { - rx_page_info = &(pnob->rx_page_info[i]); - if (!pnob->rx_pg_shared || rx_page_info->page_offset) { - pci_unmap_page(pnob->adapter->pdev, - pci_unmap_addr(rx_page_info, bus), - pnob->rx_buf_size, - PCI_DMA_FROMDEVICE); - } - if (rx_page_info->page) - put_page(rx_page_info->page); - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - } - pnob->rx_pg_info_hd = 0; - } -} - -static void be_destroy_netobj(struct be_net_object *pnob) -{ - int status; - - if (pnob->tx_q_created) { - status = be_eth_sq_destroy(&pnob->tx_q_obj); - pnob->tx_q_created = 0; - } - - if (pnob->rx_q_created) { - status = be_eth_rq_destroy(&pnob->rx_q_obj); - if (status != 0) { - status = be_eth_rq_destroy_options(&pnob->rx_q_obj, 0, - NULL, NULL); - BUG_ON(status); - } - pnob->rx_q_created = 0; - } - - be_process_rx_flush_cmpl(pnob); - - if (pnob->tx_cq_created) { - status = be_cq_destroy(&pnob->tx_cq_obj); - pnob->tx_cq_created = 0; - } - - if (pnob->rx_cq_created) { - status = be_cq_destroy(&pnob->rx_cq_obj); - pnob->rx_cq_created = 0; - } - - if (pnob->mcc_q_created) { - status = be_mcc_ring_destroy(&pnob->mcc_q_obj); - pnob->mcc_q_created = 0; - } - if (pnob->mcc_cq_created) { - status = be_cq_destroy(&pnob->mcc_cq_obj); - pnob->mcc_cq_created = 0; - } - - if (pnob->event_q_created) { - status = be_eq_destroy(&pnob->event_q_obj); - pnob->event_q_created = 0; - } - be_function_cleanup(&pnob->fn_obj); -} - -/* - * free all resources associated with a pnob - * Called at the time of module cleanup as well a any error during - * module init. Some resources may be partially allocated in a NetObj. - */ -static void netobject_cleanup(struct be_adapter *adapter, - struct be_net_object *pnob) -{ - struct net_device *netdev = adapter->netdevp; - - if (netif_running(netdev)) { - netif_stop_queue(netdev); - be_wait_nic_tx_cmplx_cmpl(pnob); - be_disable_eq_intr(pnob); - } - - be_unregister_isr(adapter); - - if (adapter->tasklet_started) { - tasklet_kill(&(adapter->sts_handler)); - adapter->tasklet_started = 0; - } - if (pnob->fn_obj_created) - be_disable_intr(pnob); - - if (adapter->dev_state != BE_DEV_STATE_NONE) - unregister_netdev(netdev); - - if (pnob->fn_obj_created) - be_destroy_netobj(pnob); - - adapter->net_obj = NULL; - adapter->netdevp = NULL; - - be_rx_q_clean(pnob); - if (pnob->rx_ctxt) { - kfree(pnob->rx_page_info); - kfree(pnob->rx_ctxt); - } - - be_tx_q_clean(pnob); - kfree(pnob->tx_ctxt); - - if (pnob->mcc_q) - pci_free_consistent(adapter->pdev, pnob->mcc_q_size, - pnob->mcc_q, pnob->mcc_q_bus); - - if (pnob->mcc_wrb_ctxt) - free_pages((unsigned long)pnob->mcc_wrb_ctxt, - get_order(pnob->mcc_wrb_ctxt_size)); - - if (pnob->mcc_cq) - pci_free_consistent(adapter->pdev, pnob->mcc_cq_size, - pnob->mcc_cq, pnob->mcc_cq_bus); - - if (pnob->event_q) - pci_free_consistent(adapter->pdev, pnob->event_q_size, - pnob->event_q, pnob->event_q_bus); - - if (pnob->tx_cq) - pci_free_consistent(adapter->pdev, pnob->tx_cq_size, - pnob->tx_cq, pnob->tx_cq_bus); - - if (pnob->tx_q) - pci_free_consistent(adapter->pdev, pnob->tx_q_size, - pnob->tx_q, pnob->tx_q_bus); - - if (pnob->rx_q) - pci_free_consistent(adapter->pdev, pnob->rx_q_size, - pnob->rx_q, pnob->rx_q_bus); - - if (pnob->rx_cq) - pci_free_consistent(adapter->pdev, pnob->rx_cq_size, - pnob->rx_cq, pnob->rx_cq_bus); - - - if (pnob->mb_ptr) - pci_free_consistent(adapter->pdev, pnob->mb_size, pnob->mb_ptr, - pnob->mb_bus); - - free_netdev(netdev); -} - - -static int be_nob_ring_alloc(struct be_adapter *adapter, - struct be_net_object *pnob) -{ - u32 size; - - /* Mail box rd; mailbox pointer needs to be 16 byte aligned */ - pnob->mb_size = sizeof(struct MCC_MAILBOX_AMAP) + 16; - pnob->mb_ptr = pci_alloc_consistent(adapter->pdev, pnob->mb_size, - &pnob->mb_bus); - if (!pnob->mb_bus) - return -1; - memset(pnob->mb_ptr, 0, pnob->mb_size); - pnob->mb_rd.va = PTR_ALIGN(pnob->mb_ptr, 16); - pnob->mb_rd.pa = PTR_ALIGN(pnob->mb_bus, 16); - pnob->mb_rd.length = sizeof(struct MCC_MAILBOX_AMAP); - /* - * Event queue - */ - pnob->event_q_len = EVENT_Q_LEN; - pnob->event_q_size = pnob->event_q_len * sizeof(struct EQ_ENTRY_AMAP); - pnob->event_q = pci_alloc_consistent(adapter->pdev, pnob->event_q_size, - &pnob->event_q_bus); - if (!pnob->event_q_bus) - return -1; - memset(pnob->event_q, 0, pnob->event_q_size); - /* - * Eth TX queue - */ - pnob->tx_q_len = ETH_TXQ_LEN; - pnob->tx_q_port = 0; - pnob->tx_q_size = pnob->tx_q_len * sizeof(struct ETH_WRB_AMAP); - pnob->tx_q = pci_alloc_consistent(adapter->pdev, pnob->tx_q_size, - &pnob->tx_q_bus); - if (!pnob->tx_q_bus) - return -1; - memset(pnob->tx_q, 0, pnob->tx_q_size); - /* - * Eth TX Compl queue - */ - pnob->txcq_len = ETH_TXCQ_LEN; - pnob->tx_cq_size = pnob->txcq_len * sizeof(struct ETH_TX_COMPL_AMAP); - pnob->tx_cq = pci_alloc_consistent(adapter->pdev, pnob->tx_cq_size, - &pnob->tx_cq_bus); - if (!pnob->tx_cq_bus) - return -1; - memset(pnob->tx_cq, 0, pnob->tx_cq_size); - /* - * Eth RX queue - */ - pnob->rx_q_len = ETH_RXQ_LEN; - pnob->rx_q_size = pnob->rx_q_len * sizeof(struct ETH_RX_D_AMAP); - pnob->rx_q = pci_alloc_consistent(adapter->pdev, pnob->rx_q_size, - &pnob->rx_q_bus); - if (!pnob->rx_q_bus) - return -1; - memset(pnob->rx_q, 0, pnob->rx_q_size); - /* - * Eth Unicast RX Compl queue - */ - pnob->rx_cq_len = ETH_UC_RXCQ_LEN; - pnob->rx_cq_size = pnob->rx_cq_len * - sizeof(struct ETH_RX_COMPL_AMAP); - pnob->rx_cq = pci_alloc_consistent(adapter->pdev, pnob->rx_cq_size, - &pnob->rx_cq_bus); - if (!pnob->rx_cq_bus) - return -1; - memset(pnob->rx_cq, 0, pnob->rx_cq_size); - - /* TX resources */ - size = pnob->tx_q_len * sizeof(void **); - pnob->tx_ctxt = kzalloc(size, GFP_KERNEL); - if (pnob->tx_ctxt == NULL) - return -1; - - /* RX resources */ - size = pnob->rx_q_len * sizeof(void *); - pnob->rx_ctxt = kzalloc(size, GFP_KERNEL); - if (pnob->rx_ctxt == NULL) - return -1; - - size = (pnob->rx_q_len * sizeof(struct be_rx_page_info)); - pnob->rx_page_info = kzalloc(size, GFP_KERNEL); - if (pnob->rx_page_info == NULL) - return -1; - - adapter->eth_statsp = kzalloc(sizeof(struct FWCMD_ETH_GET_STATISTICS), - GFP_KERNEL); - if (adapter->eth_statsp == NULL) - return -1; - pnob->rx_buf_size = rxbuf_size; - return 0; -} - -/* - This function initializes the be_net_object for subsequent - network operations. - - Before calling this function, the driver must have allocated - space for the NetObject structure, initialized the structure, - allocated DMAable memory for all the network queues that form - part of the NetObject and populated the start address (virtual) - and number of entries allocated for each queue in the NetObject structure. - - The driver must also have allocated memory to hold the - mailbox structure (MCC_MAILBOX) and post the physical address, - virtual addresses and the size of the mailbox memory in the - NetObj.mb_rd. This structure is used by BECLIB for - initial communication with the embedded MCC processor. BECLIB - uses the mailbox until MCC rings are created for more efficient - communication with the MCC processor. - - If the driver wants to create multiple network interface for more - than one protection domain, it can call be_create_netobj() - multiple times once for each protection domain. A Maximum of - 32 protection domains are supported. - -*/ -static int -be_create_netobj(struct be_net_object *pnob, u8 __iomem *csr_va, - u8 __iomem *db_va, u8 __iomem *pci_va) -{ - int status = 0; - bool eventable = false, tx_no_delay = false, rx_no_delay = false; - struct be_eq_object *eq_objectp = NULL; - struct be_function_object *pfob = &pnob->fn_obj; - struct ring_desc rd; - u32 set_rxbuf_size; - u32 tx_cmpl_wm = CEV_WMARK_96; /* 0xffffffff to disable */ - u32 rx_cmpl_wm = CEV_WMARK_160; /* 0xffffffff to disable */ - u32 eq_delay = 0; /* delay in 8usec units. 0xffffffff to disable */ - - memset(&rd, 0, sizeof(struct ring_desc)); - - status = be_function_object_create(csr_va, db_va, pci_va, - BE_FUNCTION_TYPE_NETWORK, &pnob->mb_rd, pfob); - if (status != BE_SUCCESS) - return status; - pnob->fn_obj_created = true; - - if (tx_cmpl_wm == 0xffffffff) - tx_no_delay = true; - if (rx_cmpl_wm == 0xffffffff) - rx_no_delay = true; - /* - * now create the necessary rings - * Event Queue first. - */ - if (pnob->event_q_len) { - rd.va = pnob->event_q; - rd.pa = pnob->event_q_bus; - rd.length = pnob->event_q_size; - - status = be_eq_create(pfob, &rd, 4, pnob->event_q_len, - (u32) -1, /* CEV_WMARK_* or -1 */ - eq_delay, /* in 8us units, or -1 */ - &pnob->event_q_obj); - if (status != BE_SUCCESS) - goto error_ret; - pnob->event_q_id = pnob->event_q_obj.eq_id; - pnob->event_q_created = 1; - eventable = true; - eq_objectp = &pnob->event_q_obj; - } - /* - * Now Eth Tx Compl. queue. - */ - if (pnob->txcq_len) { - rd.va = pnob->tx_cq; - rd.pa = pnob->tx_cq_bus; - rd.length = pnob->tx_cq_size; - - status = be_cq_create(pfob, &rd, - pnob->txcq_len * sizeof(struct ETH_TX_COMPL_AMAP), - false, /* solicted events, */ - tx_no_delay, /* nodelay */ - tx_cmpl_wm, /* Watermark encodings */ - eq_objectp, &pnob->tx_cq_obj); - if (status != BE_SUCCESS) - goto error_ret; - - pnob->tx_cq_id = pnob->tx_cq_obj.cq_id; - pnob->tx_cq_created = 1; - } - /* - * Eth Tx queue - */ - if (pnob->tx_q_len) { - struct be_eth_sq_parameters ex_params = { 0 }; - u32 type; - - if (pnob->tx_q_port) { - /* TXQ to be bound to a specific port */ - type = BE_ETH_TX_RING_TYPE_BOUND; - ex_params.port = pnob->tx_q_port - 1; - } else - type = BE_ETH_TX_RING_TYPE_STANDARD; - - rd.va = pnob->tx_q; - rd.pa = pnob->tx_q_bus; - rd.length = pnob->tx_q_size; - - status = be_eth_sq_create_ex(pfob, &rd, - pnob->tx_q_len * sizeof(struct ETH_WRB_AMAP), - type, 2, &pnob->tx_cq_obj, - &ex_params, &pnob->tx_q_obj); - - if (status != BE_SUCCESS) - goto error_ret; - - pnob->tx_q_id = pnob->tx_q_obj.bid; - pnob->tx_q_created = 1; - } - /* - * Now Eth Rx compl. queue. Always needed. - */ - rd.va = pnob->rx_cq; - rd.pa = pnob->rx_cq_bus; - rd.length = pnob->rx_cq_size; - - status = be_cq_create(pfob, &rd, - pnob->rx_cq_len * sizeof(struct ETH_RX_COMPL_AMAP), - false, /* solicted events, */ - rx_no_delay, /* nodelay */ - rx_cmpl_wm, /* Watermark encodings */ - eq_objectp, &pnob->rx_cq_obj); - if (status != BE_SUCCESS) - goto error_ret; - - pnob->rx_cq_id = pnob->rx_cq_obj.cq_id; - pnob->rx_cq_created = 1; - - status = be_eth_rq_set_frag_size(pfob, pnob->rx_buf_size, - (u32 *) &set_rxbuf_size); - if (status != BE_SUCCESS) { - be_eth_rq_get_frag_size(pfob, (u32 *) &pnob->rx_buf_size); - if ((pnob->rx_buf_size != 2048) && (pnob->rx_buf_size != 4096) - && (pnob->rx_buf_size != 8192)) - goto error_ret; - } else { - if (pnob->rx_buf_size != set_rxbuf_size) - pnob->rx_buf_size = set_rxbuf_size; - } - /* - * Eth RX queue. be_eth_rq_create() always assumes 2 pages size - */ - rd.va = pnob->rx_q; - rd.pa = pnob->rx_q_bus; - rd.length = pnob->rx_q_size; - - status = be_eth_rq_create(pfob, &rd, &pnob->rx_cq_obj, - &pnob->rx_cq_obj, &pnob->rx_q_obj); - - if (status != BE_SUCCESS) - goto error_ret; - - pnob->rx_q_id = pnob->rx_q_obj.rid; - pnob->rx_q_created = 1; - - return BE_SUCCESS; /* All required queues created. */ - -error_ret: - be_destroy_netobj(pnob); - return status; -} - -static int be_nob_ring_init(struct be_adapter *adapter, - struct be_net_object *pnob) -{ - int status; - - pnob->event_q_tl = 0; - - pnob->tx_q_hd = 0; - pnob->tx_q_tl = 0; - - pnob->tx_cq_tl = 0; - - pnob->rx_cq_tl = 0; - - memset(pnob->event_q, 0, pnob->event_q_size); - memset(pnob->tx_cq, 0, pnob->tx_cq_size); - memset(pnob->tx_ctxt, 0, pnob->tx_q_len * sizeof(void **)); - memset(pnob->rx_ctxt, 0, pnob->rx_q_len * sizeof(void *)); - pnob->rx_pg_info_hd = 0; - pnob->rx_q_hd = 0; - atomic_set(&pnob->rx_q_posted, 0); - - status = be_create_netobj(pnob, adapter->csr_va, adapter->db_va, - adapter->pci_va); - if (status != BE_SUCCESS) - return -1; - - be_post_eth_rx_buffs(pnob); - return 0; -} - -/* This function handles async callback for link status */ -static void -be_link_status_async_callback(void *context, u32 event_code, void *event) -{ - struct ASYNC_EVENT_LINK_STATE_AMAP *link_status = event; - struct be_adapter *adapter = context; - bool link_enable = false; - struct be_net_object *pnob; - struct ASYNC_EVENT_TRAILER_AMAP *async_trailer; - struct net_device *netdev; - u32 async_event_code, async_event_type, active_port; - u32 port0_link_status, port1_link_status, port0_duplex, port1_duplex; - u32 port0_speed, port1_speed; - - if (event_code != ASYNC_EVENT_CODE_LINK_STATE) { - /* Not our event to handle */ - return; - } - async_trailer = (struct ASYNC_EVENT_TRAILER_AMAP *) - ((u8 *) event + sizeof(struct MCC_CQ_ENTRY_AMAP) - - sizeof(struct ASYNC_EVENT_TRAILER_AMAP)); - - async_event_code = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, event_code, - async_trailer); - BUG_ON(async_event_code != ASYNC_EVENT_CODE_LINK_STATE); - - pnob = adapter->net_obj; - netdev = pnob->netdev; - - /* Determine if this event is a switch VLD or a physical link event */ - async_event_type = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, event_type, - async_trailer); - active_port = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - active_port, link_status); - port0_link_status = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port0_link_status, link_status); - port1_link_status = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port1_link_status, link_status); - port0_duplex = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port0_duplex, link_status); - port1_duplex = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port1_duplex, link_status); - port0_speed = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port0_speed, link_status); - port1_speed = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port1_speed, link_status); - if (async_event_type == NTWK_LINK_TYPE_VIRTUAL) { - adapter->be_stat.bes_link_change_virtual++; - if (adapter->be_link_sts->active_port != active_port) { - dev_notice(&netdev->dev, - "Active port changed due to VLD on switch\n"); - } else { - dev_notice(&netdev->dev, "Link status update\n"); - } - - } else { - adapter->be_stat.bes_link_change_physical++; - if (adapter->be_link_sts->active_port != active_port) { - dev_notice(&netdev->dev, - "Active port changed due to port link" - " status change\n"); - } else { - dev_notice(&netdev->dev, "Link status update\n"); - } - } - - memset(adapter->be_link_sts, 0, sizeof(adapter->be_link_sts)); - - if ((port0_link_status == ASYNC_EVENT_LINK_UP) || - (port1_link_status == ASYNC_EVENT_LINK_UP)) { - if ((adapter->port0_link_sts == BE_PORT_LINK_DOWN) && - (adapter->port1_link_sts == BE_PORT_LINK_DOWN)) { - /* Earlier both the ports are down So link is up */ - link_enable = true; - } - - if (port0_link_status == ASYNC_EVENT_LINK_UP) { - adapter->port0_link_sts = BE_PORT_LINK_UP; - adapter->be_link_sts->mac0_duplex = port0_duplex; - adapter->be_link_sts->mac0_speed = port0_speed; - if (active_port == NTWK_PORT_A) - adapter->be_link_sts->active_port = 0; - } else - adapter->port0_link_sts = BE_PORT_LINK_DOWN; - - if (port1_link_status == ASYNC_EVENT_LINK_UP) { - adapter->port1_link_sts = BE_PORT_LINK_UP; - adapter->be_link_sts->mac1_duplex = port1_duplex; - adapter->be_link_sts->mac1_speed = port1_speed; - if (active_port == NTWK_PORT_B) - adapter->be_link_sts->active_port = 1; - } else - adapter->port1_link_sts = BE_PORT_LINK_DOWN; - - printk(KERN_INFO "Link Properties for %s:\n", netdev->name); - dev_info(&netdev->dev, "Link Properties:\n"); - be_print_link_info(adapter->be_link_sts); - - if (!link_enable) - return; - /* - * Both ports were down previously, but atleast one of - * them has come up if this netdevice's carrier is not up, - * then indicate to stack - */ - if (!netif_carrier_ok(netdev)) { - netif_start_queue(netdev); - netif_carrier_on(netdev); - } - return; - } - - /* Now both the ports are down. Tell the stack about it */ - dev_info(&netdev->dev, "Both ports are down\n"); - adapter->port0_link_sts = BE_PORT_LINK_DOWN; - adapter->port1_link_sts = BE_PORT_LINK_DOWN; - if (netif_carrier_ok(netdev)) { - netif_carrier_off(netdev); - netif_stop_queue(netdev); - } - return; -} - -static int be_mcc_create(struct be_adapter *adapter) -{ - struct be_net_object *pnob; - - pnob = adapter->net_obj; - /* - * Create the MCC ring so that all further communication with - * MCC can go thru the ring. we do this at the end since - * we do not want to be dealing with interrupts until the - * initialization is complete. - */ - pnob->mcc_q_len = MCC_Q_LEN; - pnob->mcc_q_size = pnob->mcc_q_len * sizeof(struct MCC_WRB_AMAP); - pnob->mcc_q = pci_alloc_consistent(adapter->pdev, pnob->mcc_q_size, - &pnob->mcc_q_bus); - if (!pnob->mcc_q_bus) - return -1; - /* - * space for MCC WRB context - */ - pnob->mcc_wrb_ctxtLen = MCC_Q_LEN; - pnob->mcc_wrb_ctxt_size = pnob->mcc_wrb_ctxtLen * - sizeof(struct be_mcc_wrb_context); - pnob->mcc_wrb_ctxt = (void *)__get_free_pages(GFP_KERNEL, - get_order(pnob->mcc_wrb_ctxt_size)); - if (pnob->mcc_wrb_ctxt == NULL) - return -1; - /* - * Space for MCC compl. ring - */ - pnob->mcc_cq_len = MCC_CQ_LEN; - pnob->mcc_cq_size = pnob->mcc_cq_len * sizeof(struct MCC_CQ_ENTRY_AMAP); - pnob->mcc_cq = pci_alloc_consistent(adapter->pdev, pnob->mcc_cq_size, - &pnob->mcc_cq_bus); - if (!pnob->mcc_cq_bus) - return -1; - return 0; -} - -/* - This function creates the MCC request and completion ring required - for communicating with the ARM processor. The caller must have - allocated required amount of memory for the MCC ring and MCC - completion ring and posted the virtual address and number of - entries in the corresponding members (mcc_q and mcc_cq) in the - NetObject struture. - - When this call is completed, all further communication with - ARM will switch from mailbox to this ring. - - pnob - Pointer to the NetObject structure. This NetObject should - have been created using a previous call to be_create_netobj() -*/ -int be_create_mcc_rings(struct be_net_object *pnob) -{ - int status = 0; - struct ring_desc rd; - struct be_function_object *pfob = &pnob->fn_obj; - - memset(&rd, 0, sizeof(struct ring_desc)); - if (pnob->mcc_cq_len) { - rd.va = pnob->mcc_cq; - rd.pa = pnob->mcc_cq_bus; - rd.length = pnob->mcc_cq_size; - - status = be_cq_create(pfob, &rd, - pnob->mcc_cq_len * sizeof(struct MCC_CQ_ENTRY_AMAP), - false, /* solicted events, */ - true, /* nodelay */ - 0, /* 0 Watermark since Nodelay is true */ - &pnob->event_q_obj, - &pnob->mcc_cq_obj); - - if (status != BE_SUCCESS) - return status; - - pnob->mcc_cq_id = pnob->mcc_cq_obj.cq_id; - pnob->mcc_cq_created = 1; - } - if (pnob->mcc_q_len) { - rd.va = pnob->mcc_q; - rd.pa = pnob->mcc_q_bus; - rd.length = pnob->mcc_q_size; - - status = be_mcc_ring_create(pfob, &rd, - pnob->mcc_q_len * sizeof(struct MCC_WRB_AMAP), - pnob->mcc_wrb_ctxt, pnob->mcc_wrb_ctxtLen, - &pnob->mcc_cq_obj, &pnob->mcc_q_obj); - - if (status != BE_SUCCESS) - return status; - - pnob->mcc_q_created = 1; - } - return BE_SUCCESS; -} - -static int be_mcc_init(struct be_adapter *adapter) -{ - u32 r; - struct be_net_object *pnob; - - pnob = adapter->net_obj; - memset(pnob->mcc_q, 0, pnob->mcc_q_size); - pnob->mcc_q_hd = 0; - - memset(pnob->mcc_wrb_ctxt, 0, pnob->mcc_wrb_ctxt_size); - - memset(pnob->mcc_cq, 0, pnob->mcc_cq_size); - pnob->mcc_cq_tl = 0; - - r = be_create_mcc_rings(adapter->net_obj); - if (r != BE_SUCCESS) - return -1; - - return 0; -} - -static void be_remove(struct pci_dev *pdev) -{ - struct be_net_object *pnob; - struct be_adapter *adapter; - - adapter = pci_get_drvdata(pdev); - if (!adapter) - return; - - pci_set_drvdata(pdev, NULL); - pnob = (struct be_net_object *)adapter->net_obj; - - flush_scheduled_work(); - - if (pnob) { - /* Unregister async callback function for link status updates */ - if (pnob->mcc_q_created) - be_mcc_add_async_event_callback(&pnob->mcc_q_obj, - NULL, NULL); - netobject_cleanup(adapter, pnob); - } - - if (adapter->csr_va) - iounmap(adapter->csr_va); - if (adapter->db_va) - iounmap(adapter->db_va); - if (adapter->pci_va) - iounmap(adapter->pci_va); - - pci_release_regions(adapter->pdev); - pci_disable_device(adapter->pdev); - - kfree(adapter->be_link_sts); - kfree(adapter->eth_statsp); - - if (adapter->timer_ctxt.get_stats_timer.function) - del_timer_sync(&adapter->timer_ctxt.get_stats_timer); - kfree(adapter); -} - -/* - * This function is called by the PCI sub-system when it finds a PCI - * device with dev/vendor IDs that match with one of our devices. - * All of the driver initialization is done in this function. - */ -static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id) -{ - int status = 0; - struct be_adapter *adapter; - struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD get_fwv; - struct be_net_object *pnob; - struct net_device *netdev; - - status = pci_enable_device(pdev); - if (status) - goto error; - - status = pci_request_regions(pdev, be_driver_name); - if (status) - goto error_pci_req; - - pci_set_master(pdev); - adapter = kzalloc(sizeof(struct be_adapter), GFP_KERNEL); - if (adapter == NULL) { - status = -ENOMEM; - goto error_adapter; - } - adapter->dev_state = BE_DEV_STATE_NONE; - adapter->pdev = pdev; - pci_set_drvdata(pdev, adapter); - - adapter->enable_aic = 1; - adapter->max_eqd = MAX_EQD; - adapter->min_eqd = 0; - adapter->cur_eqd = 0; - - status = pci_set_dma_mask(pdev, DMA_64BIT_MASK); - if (!status) { - adapter->dma_64bit_cap = true; - } else { - adapter->dma_64bit_cap = false; - status = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (status != 0) { - printk(KERN_ERR "Could not set PCI DMA Mask\n"); - goto cleanup; - } - } - - status = init_pci_be_function(adapter, pdev); - if (status != 0) { - printk(KERN_ERR "Failed to map PCI BARS\n"); - status = -ENOMEM; - goto cleanup; - } - - be_trace_set_level(DL_ALWAYS | DL_ERR); - - adapter->be_link_sts = kmalloc(sizeof(struct BE_LINK_STATUS), - GFP_KERNEL); - if (adapter->be_link_sts == NULL) { - printk(KERN_ERR "Memory allocation for link status " - "buffer failed\n"); - goto cleanup; - } - spin_lock_init(&adapter->txq_lock); - - netdev = alloc_etherdev(sizeof(struct be_net_object)); - if (netdev == NULL) { - status = -ENOMEM; - goto cleanup; - } - pnob = netdev_priv(netdev); - adapter->net_obj = pnob; - adapter->netdevp = netdev; - pnob->adapter = adapter; - pnob->netdev = netdev; - - status = be_nob_ring_alloc(adapter, pnob); - if (status != 0) - goto cleanup; - - status = be_nob_ring_init(adapter, pnob); - if (status != 0) - goto cleanup; - - be_rxf_mac_address_read_write(&pnob->fn_obj, false, false, false, - false, false, netdev->dev_addr, NULL, NULL); - - netdev->init = &benet_init; - netif_carrier_off(netdev); - netif_stop_queue(netdev); - - SET_NETDEV_DEV(netdev, &(adapter->pdev->dev)); - - netif_napi_add(netdev, &pnob->napi, be_poll, 64); - - /* if the rx_frag size if 2K, one page is shared as two RX frags */ - pnob->rx_pg_shared = - (pnob->rx_buf_size <= PAGE_SIZE / 2) ? true : false; - if (pnob->rx_buf_size != rxbuf_size) { - printk(KERN_WARNING - "Could not set Rx buffer size to %d. Using %d\n", - rxbuf_size, pnob->rx_buf_size); - rxbuf_size = pnob->rx_buf_size; - } - - tasklet_init(&(adapter->sts_handler), be_process_intr, - (unsigned long)adapter); - adapter->tasklet_started = 1; - spin_lock_init(&(adapter->int_lock)); - - status = be_register_isr(adapter, pnob); - if (status != 0) - goto cleanup; - - adapter->rx_csum = 1; - adapter->max_rx_coal = BE_LRO_MAX_PKTS; - - memset(&get_fwv, 0, - sizeof(struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD)); - printk(KERN_INFO "BladeEngine Driver version:%s. " - "Copyright ServerEngines, Corporation 2005 - 2008\n", - be_drvr_ver); - status = be_function_get_fw_version(&pnob->fn_obj, &get_fwv, NULL, - NULL); - if (status == BE_SUCCESS) { - strncpy(be_fw_ver, get_fwv.firmware_version_string, 32); - printk(KERN_INFO "BladeEngine Firmware Version:%s\n", - get_fwv.firmware_version_string); - } else { - printk(KERN_WARNING "Unable to get BE Firmware Version\n"); - } - - sema_init(&adapter->get_eth_stat_sem, 0); - init_timer(&adapter->timer_ctxt.get_stats_timer); - atomic_set(&adapter->timer_ctxt.get_stat_flag, 0); - adapter->timer_ctxt.get_stats_timer.function = - &be_get_stats_timer_handler; - - status = be_mcc_create(adapter); - if (status < 0) - goto cleanup; - status = be_mcc_init(adapter); - if (status < 0) - goto cleanup; - - - status = be_mcc_add_async_event_callback(&adapter->net_obj->mcc_q_obj, - be_link_status_async_callback, (void *)adapter); - if (status != BE_SUCCESS) { - printk(KERN_WARNING "add_async_event_callback failed"); - printk(KERN_WARNING - "Link status changes may not be reflected\n"); - } - - status = register_netdev(netdev); - if (status != 0) - goto cleanup; - be_update_link_status(adapter); - adapter->dev_state = BE_DEV_STATE_INIT; - return 0; - -cleanup: - be_remove(pdev); - return status; -error_adapter: - pci_release_regions(pdev); -error_pci_req: - pci_disable_device(pdev); -error: - printk(KERN_ERR "BladeEngine initalization failed\n"); - return status; -} - -/* - * Get the current link status and print the status on console - */ -void be_update_link_status(struct be_adapter *adapter) -{ - int status; - struct be_net_object *pnob = adapter->net_obj; - - status = be_rxf_link_status(&pnob->fn_obj, adapter->be_link_sts, NULL, - NULL, NULL); - if (status == BE_SUCCESS) { - if (adapter->be_link_sts->mac0_speed && - adapter->be_link_sts->mac0_duplex) - adapter->port0_link_sts = BE_PORT_LINK_UP; - else - adapter->port0_link_sts = BE_PORT_LINK_DOWN; - - if (adapter->be_link_sts->mac1_speed && - adapter->be_link_sts->mac1_duplex) - adapter->port1_link_sts = BE_PORT_LINK_UP; - else - adapter->port1_link_sts = BE_PORT_LINK_DOWN; - - dev_info(&pnob->netdev->dev, "Link Properties:\n"); - be_print_link_info(adapter->be_link_sts); - return; - } - dev_info(&pnob->netdev->dev, "Could not get link status\n"); - return; -} - - -#ifdef CONFIG_PM -static void -be_pm_cleanup(struct be_adapter *adapter, - struct be_net_object *pnob, struct net_device *netdev) -{ - netif_carrier_off(netdev); - netif_stop_queue(netdev); - - be_wait_nic_tx_cmplx_cmpl(pnob); - be_disable_eq_intr(pnob); - - if (adapter->tasklet_started) { - tasklet_kill(&adapter->sts_handler); - adapter->tasklet_started = 0; - } - - be_unregister_isr(adapter); - be_disable_intr(pnob); - - be_tx_q_clean(pnob); - be_rx_q_clean(pnob); - - be_destroy_netobj(pnob); -} - -static int be_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct be_adapter *adapter = pci_get_drvdata(pdev); - struct net_device *netdev = adapter->netdevp; - struct be_net_object *pnob = netdev_priv(netdev); - - adapter->dev_pm_state = adapter->dev_state; - adapter->dev_state = BE_DEV_STATE_SUSPEND; - - netif_device_detach(netdev); - if (netif_running(netdev)) - be_pm_cleanup(adapter, pnob, netdev); - - pci_enable_wake(pdev, 3, 1); - pci_enable_wake(pdev, 4, 1); /* D3 Cold = 4 */ - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - return 0; -} - -static void be_up(struct be_adapter *adapter) -{ - struct be_net_object *pnob = adapter->net_obj; - - if (pnob->num_vlans != 0) - be_rxf_vlan_config(&pnob->fn_obj, false, pnob->num_vlans, - pnob->vlan_tag, NULL, NULL, NULL); - -} - -static int be_resume(struct pci_dev *pdev) -{ - int status = 0; - struct be_adapter *adapter = pci_get_drvdata(pdev); - struct net_device *netdev = adapter->netdevp; - struct be_net_object *pnob = netdev_priv(netdev); - - netif_device_detach(netdev); - - status = pci_enable_device(pdev); - if (status) - return status; - - pci_set_power_state(pdev, 0); - pci_restore_state(pdev); - pci_enable_wake(pdev, 3, 0); - pci_enable_wake(pdev, 4, 0); /* 4 is D3 cold */ - - netif_carrier_on(netdev); - netif_start_queue(netdev); - - if (netif_running(netdev)) { - be_rxf_mac_address_read_write(&pnob->fn_obj, false, false, - false, true, false, netdev->dev_addr, NULL, NULL); - - status = be_nob_ring_init(adapter, pnob); - if (status < 0) - return status; - - tasklet_init(&(adapter->sts_handler), be_process_intr, - (unsigned long)adapter); - adapter->tasklet_started = 1; - - if (be_register_isr(adapter, pnob) != 0) { - printk(KERN_ERR "be_register_isr failed\n"); - return status; - } - - - status = be_mcc_init(adapter); - if (status < 0) { - printk(KERN_ERR "be_mcc_init failed\n"); - return status; - } - be_update_link_status(adapter); - /* - * Register async call back function to handle link - * status updates - */ - status = be_mcc_add_async_event_callback( - &adapter->net_obj->mcc_q_obj, - be_link_status_async_callback, (void *)adapter); - if (status != BE_SUCCESS) { - printk(KERN_WARNING "add_async_event_callback failed"); - printk(KERN_WARNING - "Link status changes may not be reflected\n"); - } - be_enable_intr(pnob); - be_enable_eq_intr(pnob); - be_up(adapter); - } - netif_device_attach(netdev); - adapter->dev_state = adapter->dev_pm_state; - return 0; - -} - -#endif - -/* Wait until no more pending transmits */ -void be_wait_nic_tx_cmplx_cmpl(struct be_net_object *pnob) -{ - int i; - - /* Wait for 20us * 50000 (= 1s) and no more */ - i = 0; - while ((pnob->tx_q_tl != pnob->tx_q_hd) && (i < 50000)) { - ++i; - udelay(20); - } - - /* Check for no more pending transmits */ - if (i >= 50000) { - printk(KERN_WARNING - "Did not receive completions for all TX requests\n"); - } -} - -static struct pci_driver be_driver = { - .name = be_driver_name, - .id_table = be_device_id_table, - .probe = be_probe, -#ifdef CONFIG_PM - .suspend = be_suspend, - .resume = be_resume, -#endif - .remove = be_remove -}; - -/* - * Module init entry point. Registers our our device and return. - * Our probe will be called if the device is found. - */ -static int __init be_init_module(void) -{ - int ret; - - if (rxbuf_size != 8192 && rxbuf_size != 4096 && rxbuf_size != 2048) { - printk(KERN_WARNING - "Unsupported receive buffer size (%d) requested\n", - rxbuf_size); - printk(KERN_WARNING - "Must be 2048, 4096 or 8192. Defaulting to 2048\n"); - rxbuf_size = 2048; - } - - ret = pci_register_driver(&be_driver); - - return ret; -} - -module_init(be_init_module); - -/* - * be_exit_module - Driver Exit Cleanup Routine - */ -static void __exit be_exit_module(void) -{ - pci_unregister_driver(&be_driver); -} - -module_exit(be_exit_module); diff --git a/drivers/staging/benet/be_int.c b/drivers/staging/benet/be_int.c deleted file mode 100644 index cba95d09a8b..00000000000 --- a/drivers/staging/benet/be_int.c +++ /dev/null @@ -1,863 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include -#include - -#include "benet.h" - -/* number of bytes of RX frame that are copied to skb->data */ -#define BE_HDR_LEN 64 - -#define NETIF_RX(skb) netif_receive_skb(skb) -#define VLAN_ACCEL_RX(skb, pnob, vt) \ - vlan_hwaccel_rx(skb, pnob->vlan_grp, vt) - -/* - This function notifies BladeEngine of the number of completion - entries processed from the specified completion queue by writing - the number of popped entries to the door bell. - - pnob - Pointer to the NetObject structure - n - Number of completion entries processed - cq_id - Queue ID of the completion queue for which notification - is being done. - re_arm - 1 - rearm the completion ring to generate an event. - - 0 - dont rearm the completion ring to generate an event -*/ -void be_notify_cmpl(struct be_net_object *pnob, int n, int cq_id, int re_arm) -{ - struct CQ_DB_AMAP cqdb; - - cqdb.dw[0] = 0; - AMAP_SET_BITS_PTR(CQ_DB, qid, &cqdb, cq_id); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &cqdb, re_arm); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &cqdb, n); - PD_WRITE(&pnob->fn_obj, cq_db, cqdb.dw[0]); -} - -/* - * adds additional receive frags indicated by BE starting from given - * frag index (fi) to specified skb's frag list - */ -static void -add_skb_frags(struct be_net_object *pnob, struct sk_buff *skb, - u32 nresid, u32 fi) -{ - struct be_adapter *adapter = pnob->adapter; - u32 sk_frag_idx, n; - struct be_rx_page_info *rx_page_info; - u32 frag_sz = pnob->rx_buf_size; - - sk_frag_idx = skb_shinfo(skb)->nr_frags; - while (nresid) { - index_inc(&fi, pnob->rx_q_len); - - rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi]; - pnob->rx_ctxt[fi] = NULL; - if ((rx_page_info->page_offset) || - (pnob->rx_pg_shared == false)) { - pci_unmap_page(adapter->pdev, - pci_unmap_addr(rx_page_info, bus), - frag_sz, PCI_DMA_FROMDEVICE); - } - - n = min(nresid, frag_sz); - skb_shinfo(skb)->frags[sk_frag_idx].page = rx_page_info->page; - skb_shinfo(skb)->frags[sk_frag_idx].page_offset - = rx_page_info->page_offset; - skb_shinfo(skb)->frags[sk_frag_idx].size = n; - - sk_frag_idx++; - skb->len += n; - skb->data_len += n; - skb_shinfo(skb)->nr_frags++; - nresid -= n; - - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - atomic_dec(&pnob->rx_q_posted); - } -} - -/* - * This function processes incoming nic packets over various Rx queues. - * This function takes the adapter, the current Rx status descriptor - * entry and the Rx completion queue ID as argument. - */ -static inline int process_nic_rx_completion(struct be_net_object *pnob, - struct ETH_RX_COMPL_AMAP *rxcp) -{ - struct be_adapter *adapter = pnob->adapter; - struct sk_buff *skb; - int udpcksm, tcpcksm; - int n; - u32 nresid, fi; - u32 frag_sz = pnob->rx_buf_size; - u8 *va; - struct be_rx_page_info *rx_page_info; - u32 numfrags, vtp, vtm, vlan_tag, pktsize; - - fi = AMAP_GET_BITS_PTR(ETH_RX_COMPL, fragndx, rxcp); - BUG_ON(fi >= (int)pnob->rx_q_len); - BUG_ON(fi < 0); - - rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi]; - BUG_ON(!rx_page_info->page); - pnob->rx_ctxt[fi] = NULL; - - /* - * If one page is used per fragment or if this is the second half of - * of the page, unmap the page here - */ - if ((rx_page_info->page_offset) || (pnob->rx_pg_shared == false)) { - pci_unmap_page(adapter->pdev, - pci_unmap_addr(rx_page_info, bus), frag_sz, - PCI_DMA_FROMDEVICE); - } - - atomic_dec(&pnob->rx_q_posted); - udpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, udpcksm, rxcp); - tcpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, tcpcksm, rxcp); - pktsize = AMAP_GET_BITS_PTR(ETH_RX_COMPL, pktsize, rxcp); - /* - * get rid of RX flush completions first. - */ - if ((tcpcksm) && (udpcksm) && (pktsize == 32)) { - put_page(rx_page_info->page); - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - return 0; - } - skb = netdev_alloc_skb(pnob->netdev, BE_HDR_LEN + NET_IP_ALIGN); - if (skb == NULL) { - dev_info(&pnob->netdev->dev, "alloc_skb() failed\n"); - put_page(rx_page_info->page); - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - goto free_frags; - } - skb_reserve(skb, NET_IP_ALIGN); - - skb->dev = pnob->netdev; - - n = min(pktsize, frag_sz); - - va = page_address(rx_page_info->page) + rx_page_info->page_offset; - prefetch(va); - - skb->len = n; - skb->data_len = n; - if (n <= BE_HDR_LEN) { - memcpy(skb->data, va, n); - put_page(rx_page_info->page); - skb->data_len -= n; - skb->tail += n; - } else { - - /* Setup the SKB with page buffer information */ - skb_shinfo(skb)->frags[0].page = rx_page_info->page; - skb_shinfo(skb)->nr_frags++; - - /* Copy the header into the skb_data */ - memcpy(skb->data, va, BE_HDR_LEN); - skb_shinfo(skb)->frags[0].page_offset = - rx_page_info->page_offset + BE_HDR_LEN; - skb_shinfo(skb)->frags[0].size = n - BE_HDR_LEN; - skb->data_len -= BE_HDR_LEN; - skb->tail += BE_HDR_LEN; - } - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - nresid = pktsize - n; - - skb->protocol = eth_type_trans(skb, pnob->netdev); - - if ((tcpcksm || udpcksm) && adapter->rx_csum) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; - /* - * if we have more bytes left, the frame has been - * given to us in multiple fragments. This happens - * with Jumbo frames. Add the remaining fragments to - * skb->frags[] array. - */ - if (nresid) - add_skb_frags(pnob, skb, nresid, fi); - - /* update the the true size of the skb. */ - skb->truesize = skb->len + sizeof(struct sk_buff); - - /* - * If a 802.3 frame or 802.2 LLC frame - * (i.e) contains length field in MAC Hdr - * and frame len is greater than 64 bytes - */ - if (((skb->protocol == ntohs(ETH_P_802_2)) || - (skb->protocol == ntohs(ETH_P_802_3))) - && (pktsize > BE_HDR_LEN)) { - /* - * If the length given in Mac Hdr is less than frame size - * Erraneous frame, Drop it - */ - if ((ntohs(*(u16 *) (va + 12)) + ETH_HLEN) < pktsize) { - /* Increment Non Ether type II frames dropped */ - adapter->be_stat.bes_802_3_dropped_frames++; - - kfree_skb(skb); - return 0; - } - /* - * else if the length given in Mac Hdr is greater than - * frame size, should not be seeing this sort of frames - * dump the pkt and pass to stack - */ - else if ((ntohs(*(u16 *) (va + 12)) + ETH_HLEN) > pktsize) { - /* Increment Non Ether type II frames malformed */ - adapter->be_stat.bes_802_3_malformed_frames++; - } - } - - vtp = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtp, rxcp); - vtm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtm, rxcp); - if (vtp && vtm) { - /* Vlan tag present in pkt and BE found - * that the tag matched an entry in VLAN table - */ - if (!pnob->vlan_grp || pnob->num_vlans == 0) { - /* But we have no VLANs configured. - * This should never happen. Drop the packet. - */ - dev_info(&pnob->netdev->dev, - "BladeEngine: Unexpected vlan tagged packet\n"); - kfree_skb(skb); - return 0; - } - /* pass the VLAN packet to stack */ - vlan_tag = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vlan_tag, rxcp); - VLAN_ACCEL_RX(skb, pnob, be16_to_cpu(vlan_tag)); - - } else { - NETIF_RX(skb); - } - return 0; - -free_frags: - /* free all frags associated with the current rxcp */ - numfrags = AMAP_GET_BITS_PTR(ETH_RX_COMPL, numfrags, rxcp); - while (numfrags-- > 1) { - index_inc(&fi, pnob->rx_q_len); - - rx_page_info = (struct be_rx_page_info *) - pnob->rx_ctxt[fi]; - pnob->rx_ctxt[fi] = (void *)NULL; - if (rx_page_info->page_offset || !pnob->rx_pg_shared) { - pci_unmap_page(adapter->pdev, - pci_unmap_addr(rx_page_info, bus), - frag_sz, PCI_DMA_FROMDEVICE); - } - - put_page(rx_page_info->page); - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - atomic_dec(&pnob->rx_q_posted); - } - return -ENOMEM; -} - -static void process_nic_rx_completion_lro(struct be_net_object *pnob, - struct ETH_RX_COMPL_AMAP *rxcp) -{ - struct be_adapter *adapter = pnob->adapter; - struct skb_frag_struct rx_frags[BE_MAX_FRAGS_PER_FRAME]; - unsigned int udpcksm, tcpcksm; - u32 numfrags, vlanf, vtm, vlan_tag, nresid; - u16 vlant; - unsigned int fi, idx, n; - struct be_rx_page_info *rx_page_info; - u32 frag_sz = pnob->rx_buf_size, pktsize; - bool rx_coal = (adapter->max_rx_coal <= 1) ? 0 : 1; - u8 err, *va; - __wsum csum = 0; - - if (AMAP_GET_BITS_PTR(ETH_RX_COMPL, ipsec, rxcp)) { - /* Drop the pkt and move to the next completion. */ - adapter->be_stat.bes_rx_misc_pkts++; - return; - } - err = AMAP_GET_BITS_PTR(ETH_RX_COMPL, err, rxcp); - if (err || !rx_coal) { - /* We won't coalesce Rx pkts if the err bit set. - * take the path of normal completion processing */ - process_nic_rx_completion(pnob, rxcp); - return; - } - - fi = AMAP_GET_BITS_PTR(ETH_RX_COMPL, fragndx, rxcp); - BUG_ON(fi >= (int)pnob->rx_q_len); - BUG_ON(fi < 0); - rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi]; - BUG_ON(!rx_page_info->page); - pnob->rx_ctxt[fi] = (void *)NULL; - /* If one page is used per fragment or if this is the - * second half of the page, unmap the page here - */ - if (rx_page_info->page_offset || !pnob->rx_pg_shared) { - pci_unmap_page(adapter->pdev, - pci_unmap_addr(rx_page_info, bus), - frag_sz, PCI_DMA_FROMDEVICE); - } - - numfrags = AMAP_GET_BITS_PTR(ETH_RX_COMPL, numfrags, rxcp); - udpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, udpcksm, rxcp); - tcpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, tcpcksm, rxcp); - vlan_tag = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vlan_tag, rxcp); - vlant = be16_to_cpu(vlan_tag); - vlanf = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtp, rxcp); - vtm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtm, rxcp); - pktsize = AMAP_GET_BITS_PTR(ETH_RX_COMPL, pktsize, rxcp); - - atomic_dec(&pnob->rx_q_posted); - - if (tcpcksm && udpcksm && pktsize == 32) { - /* flush completion entries */ - put_page(rx_page_info->page); - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - return; - } - /* Only one of udpcksum and tcpcksum can be set */ - BUG_ON(udpcksm && tcpcksm); - - /* jumbo frames could come in multiple fragments */ - BUG_ON(numfrags != ((pktsize + (frag_sz - 1)) / frag_sz)); - n = min(pktsize, frag_sz); - nresid = pktsize - n; /* will be useful for jumbo pkts */ - idx = 0; - - va = page_address(rx_page_info->page) + rx_page_info->page_offset; - prefetch(va); - rx_frags[idx].page = rx_page_info->page; - rx_frags[idx].page_offset = (rx_page_info->page_offset); - rx_frags[idx].size = n; - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - - /* If we got multiple fragments, we have more data. */ - while (nresid) { - idx++; - index_inc(&fi, pnob->rx_q_len); - - rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi]; - pnob->rx_ctxt[fi] = (void *)NULL; - if (rx_page_info->page_offset || !pnob->rx_pg_shared) { - pci_unmap_page(adapter->pdev, - pci_unmap_addr(rx_page_info, bus), - frag_sz, PCI_DMA_FROMDEVICE); - } - - n = min(nresid, frag_sz); - rx_frags[idx].page = rx_page_info->page; - rx_frags[idx].page_offset = (rx_page_info->page_offset); - rx_frags[idx].size = n; - - nresid -= n; - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - atomic_dec(&pnob->rx_q_posted); - } - - if (likely(!(vlanf && vtm))) { - lro_receive_frags(&pnob->lro_mgr, rx_frags, - pktsize, pktsize, - (void *)(unsigned long)csum, csum); - } else { - /* Vlan tag present in pkt and BE found - * that the tag matched an entry in VLAN table - */ - if (unlikely(!pnob->vlan_grp || pnob->num_vlans == 0)) { - /* But we have no VLANs configured. - * This should never happen. Drop the packet. - */ - dev_info(&pnob->netdev->dev, - "BladeEngine: Unexpected vlan tagged packet\n"); - return; - } - /* pass the VLAN packet to stack */ - lro_vlan_hwaccel_receive_frags(&pnob->lro_mgr, - rx_frags, pktsize, pktsize, - pnob->vlan_grp, vlant, - (void *)(unsigned long)csum, - csum); - } - - adapter->be_stat.bes_rx_coal++; -} - -struct ETH_RX_COMPL_AMAP *be_get_rx_cmpl(struct be_net_object *pnob) -{ - struct ETH_RX_COMPL_AMAP *rxcp = &pnob->rx_cq[pnob->rx_cq_tl]; - u32 valid, ct; - - valid = AMAP_GET_BITS_PTR(ETH_RX_COMPL, valid, rxcp); - if (valid == 0) - return NULL; - - ct = AMAP_GET_BITS_PTR(ETH_RX_COMPL, ct, rxcp); - if (ct != 0) { - /* Invalid chute #. treat as error */ - AMAP_SET_BITS_PTR(ETH_RX_COMPL, err, rxcp, 1); - } - - be_adv_rxcq_tl(pnob); - AMAP_SET_BITS_PTR(ETH_RX_COMPL, valid, rxcp, 0); - return rxcp; -} - -static void update_rx_rate(struct be_adapter *adapter) -{ - /* update the rate once in two seconds */ - if ((jiffies - adapter->eth_rx_jiffies) > 2 * (HZ)) { - u32 r; - r = adapter->eth_rx_bytes / - ((jiffies - adapter->eth_rx_jiffies) / (HZ)); - r = (r / 1000000); /* MB/Sec */ - - /* Mega Bits/Sec */ - adapter->be_stat.bes_eth_rx_rate = (r * 8); - adapter->eth_rx_jiffies = jiffies; - adapter->eth_rx_bytes = 0; - } -} - -static int process_rx_completions(struct be_net_object *pnob, int max_work) -{ - struct be_adapter *adapter = pnob->adapter; - struct ETH_RX_COMPL_AMAP *rxcp; - u32 nc = 0; - unsigned int pktsize; - - while (max_work && (rxcp = be_get_rx_cmpl(pnob))) { - prefetch(rxcp); - pktsize = AMAP_GET_BITS_PTR(ETH_RX_COMPL, pktsize, rxcp); - process_nic_rx_completion_lro(pnob, rxcp); - adapter->eth_rx_bytes += pktsize; - update_rx_rate(adapter); - nc++; - max_work--; - adapter->be_stat.bes_rx_compl++; - } - if (likely(adapter->max_rx_coal > 1)) { - adapter->be_stat.bes_rx_flush++; - lro_flush_all(&pnob->lro_mgr); - } - - /* Refill the queue */ - if (atomic_read(&pnob->rx_q_posted) < 900) - be_post_eth_rx_buffs(pnob); - - return nc; -} - -static struct ETH_TX_COMPL_AMAP *be_get_tx_cmpl(struct be_net_object *pnob) -{ - struct ETH_TX_COMPL_AMAP *txcp = &pnob->tx_cq[pnob->tx_cq_tl]; - u32 valid; - - valid = AMAP_GET_BITS_PTR(ETH_TX_COMPL, valid, txcp); - if (valid == 0) - return NULL; - - AMAP_SET_BITS_PTR(ETH_TX_COMPL, valid, txcp, 0); - be_adv_txcq_tl(pnob); - return txcp; - -} - -void process_one_tx_compl(struct be_net_object *pnob, u32 end_idx) -{ - struct be_adapter *adapter = pnob->adapter; - int cur_index, tx_wrbs_completed = 0; - struct sk_buff *skb; - u64 busaddr, pa, pa_lo, pa_hi; - struct ETH_WRB_AMAP *wrb; - u32 frag_len, last_index, j; - - last_index = tx_compl_lastwrb_idx_get(pnob); - BUG_ON(last_index != end_idx); - pnob->tx_ctxt[pnob->tx_q_tl] = NULL; - do { - cur_index = pnob->tx_q_tl; - wrb = &pnob->tx_q[cur_index]; - pa_hi = AMAP_GET_BITS_PTR(ETH_WRB, frag_pa_hi, wrb); - pa_lo = AMAP_GET_BITS_PTR(ETH_WRB, frag_pa_lo, wrb); - frag_len = AMAP_GET_BITS_PTR(ETH_WRB, frag_len, wrb); - busaddr = (pa_hi << 32) | pa_lo; - if (busaddr != 0) { - pa = le64_to_cpu(busaddr); - pci_unmap_single(adapter->pdev, pa, - frag_len, PCI_DMA_TODEVICE); - } - if (cur_index == last_index) { - skb = (struct sk_buff *)pnob->tx_ctxt[cur_index]; - BUG_ON(!skb); - for (j = 0; j < skb_shinfo(skb)->nr_frags; j++) { - struct skb_frag_struct *frag; - frag = &skb_shinfo(skb)->frags[j]; - pci_unmap_page(adapter->pdev, - (ulong) frag->page, frag->size, - PCI_DMA_TODEVICE); - } - kfree_skb(skb); - pnob->tx_ctxt[cur_index] = NULL; - } else { - BUG_ON(pnob->tx_ctxt[cur_index]); - } - tx_wrbs_completed++; - be_adv_txq_tl(pnob); - } while (cur_index != last_index); - atomic_sub(tx_wrbs_completed, &pnob->tx_q_used); -} - -/* there is no need to take an SMP lock here since currently - * we have only one instance of the tasklet that does completion - * processing. - */ -static void process_nic_tx_completions(struct be_net_object *pnob) -{ - struct be_adapter *adapter = pnob->adapter; - struct ETH_TX_COMPL_AMAP *txcp; - struct net_device *netdev = pnob->netdev; - u32 end_idx, num_processed = 0; - - adapter->be_stat.bes_tx_events++; - - while ((txcp = be_get_tx_cmpl(pnob))) { - end_idx = AMAP_GET_BITS_PTR(ETH_TX_COMPL, wrb_index, txcp); - process_one_tx_compl(pnob, end_idx); - num_processed++; - adapter->be_stat.bes_tx_compl++; - } - be_notify_cmpl(pnob, num_processed, pnob->tx_cq_id, 1); - /* - * We got Tx completions and have usable WRBs. - * If the netdev's queue has been stopped - * because we had run out of WRBs, wake it now. - */ - spin_lock(&adapter->txq_lock); - if (netif_queue_stopped(netdev) - && atomic_read(&pnob->tx_q_used) < pnob->tx_q_len / 2) { - netif_wake_queue(netdev); - } - spin_unlock(&adapter->txq_lock); -} - -static u32 post_rx_buffs(struct be_net_object *pnob, struct list_head *rxbl) -{ - u32 nposted = 0; - struct ETH_RX_D_AMAP *rxd = NULL; - struct be_recv_buffer *rxbp; - void **rx_ctxp; - struct RQ_DB_AMAP rqdb; - - rx_ctxp = pnob->rx_ctxt; - - while (!list_empty(rxbl) && - (rx_ctxp[pnob->rx_q_hd] == NULL) && nposted < 255) { - - rxbp = list_first_entry(rxbl, struct be_recv_buffer, rxb_list); - list_del(&rxbp->rxb_list); - rxd = pnob->rx_q + pnob->rx_q_hd; - AMAP_SET_BITS_PTR(ETH_RX_D, fragpa_lo, rxd, rxbp->rxb_pa_lo); - AMAP_SET_BITS_PTR(ETH_RX_D, fragpa_hi, rxd, rxbp->rxb_pa_hi); - - rx_ctxp[pnob->rx_q_hd] = rxbp->rxb_ctxt; - be_adv_rxq_hd(pnob); - nposted++; - } - - if (nposted) { - /* Now press the door bell to notify BladeEngine. */ - rqdb.dw[0] = 0; - AMAP_SET_BITS_PTR(RQ_DB, numPosted, &rqdb, nposted); - AMAP_SET_BITS_PTR(RQ_DB, rq, &rqdb, pnob->rx_q_id); - PD_WRITE(&pnob->fn_obj, erx_rq_db, rqdb.dw[0]); - } - atomic_add(nposted, &pnob->rx_q_posted); - return nposted; -} - -void be_post_eth_rx_buffs(struct be_net_object *pnob) -{ - struct be_adapter *adapter = pnob->adapter; - u32 num_bufs, r; - u64 busaddr = 0, tmp_pa; - u32 max_bufs, pg_hd; - u32 frag_size; - struct be_recv_buffer *rxbp; - struct list_head rxbl; - struct be_rx_page_info *rx_page_info; - struct page *page = NULL; - u32 page_order = 0; - gfp_t alloc_flags = GFP_ATOMIC; - - BUG_ON(!adapter); - - max_bufs = 64; /* should be even # <= 255. */ - - frag_size = pnob->rx_buf_size; - page_order = get_order(frag_size); - - if (frag_size == 8192) - alloc_flags |= (gfp_t) __GFP_COMP; - /* - * Form a linked list of RECV_BUFFFER structure to be be posted. - * We will post even number of buffer so that pages can be - * shared. - */ - INIT_LIST_HEAD(&rxbl); - - for (num_bufs = 0; num_bufs < max_bufs && - !pnob->rx_page_info[pnob->rx_pg_info_hd].page; ++num_bufs) { - - rxbp = &pnob->eth_rx_bufs[num_bufs]; - pg_hd = pnob->rx_pg_info_hd; - rx_page_info = &pnob->rx_page_info[pg_hd]; - - if (!page) { - page = alloc_pages(alloc_flags, page_order); - if (unlikely(page == NULL)) { - adapter->be_stat.bes_ethrx_post_fail++; - pnob->rxbuf_post_fail++; - break; - } - pnob->rxbuf_post_fail = 0; - busaddr = pci_map_page(adapter->pdev, page, 0, - frag_size, PCI_DMA_FROMDEVICE); - rx_page_info->page_offset = 0; - rx_page_info->page = page; - /* - * If we are sharing a page among two skbs, - * alloc a new one on the next iteration - */ - if (pnob->rx_pg_shared == false) - page = NULL; - } else { - get_page(page); - rx_page_info->page_offset += frag_size; - rx_page_info->page = page; - /* - * We are finished with the alloced page, - * Alloc a new one on the next iteration - */ - page = NULL; - } - rxbp->rxb_ctxt = (void *)rx_page_info; - index_inc(&pnob->rx_pg_info_hd, pnob->rx_q_len); - - pci_unmap_addr_set(rx_page_info, bus, busaddr); - tmp_pa = busaddr + rx_page_info->page_offset; - rxbp->rxb_pa_lo = (tmp_pa & 0xFFFFFFFF); - rxbp->rxb_pa_hi = (tmp_pa >> 32); - rxbp->rxb_len = frag_size; - list_add_tail(&rxbp->rxb_list, &rxbl); - } /* End of for */ - - r = post_rx_buffs(pnob, &rxbl); - BUG_ON(r != num_bufs); - return; -} - -/* - * Interrupt service for network function. We just schedule the - * tasklet which does all completion processing. - */ -irqreturn_t be_int(int irq, void *dev) -{ - struct net_device *netdev = dev; - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - u32 isr; - - isr = CSR_READ(&pnob->fn_obj, cev.isr1); - if (unlikely(!isr)) - return IRQ_NONE; - - spin_lock(&adapter->int_lock); - adapter->isr |= isr; - spin_unlock(&adapter->int_lock); - - adapter->be_stat.bes_ints++; - - tasklet_schedule(&adapter->sts_handler); - return IRQ_HANDLED; -} - -/* - * Poll function called by NAPI with a work budget. - * We process as many UC. BC and MC receive completions - * as the budget allows and return the actual number of - * RX ststutses processed. - */ -int be_poll(struct napi_struct *napi, int budget) -{ - struct be_net_object *pnob = - container_of(napi, struct be_net_object, napi); - u32 work_done; - - pnob->adapter->be_stat.bes_polls++; - work_done = process_rx_completions(pnob, budget); - BUG_ON(work_done > budget); - - /* All consumed */ - if (work_done < budget) { - netif_rx_complete(napi); - /* enable intr */ - be_notify_cmpl(pnob, work_done, pnob->rx_cq_id, 1); - } else { - /* More to be consumed; continue with interrupts disabled */ - be_notify_cmpl(pnob, work_done, pnob->rx_cq_id, 0); - } - return work_done; -} - -static struct EQ_ENTRY_AMAP *get_event(struct be_net_object *pnob) -{ - struct EQ_ENTRY_AMAP *eqp = &(pnob->event_q[pnob->event_q_tl]); - if (!AMAP_GET_BITS_PTR(EQ_ENTRY, Valid, eqp)) - return NULL; - be_adv_eq_tl(pnob); - return eqp; -} - -/* - * Processes all valid events in the event ring associated with given - * NetObject. Also, notifies BE the number of events processed. - */ -static inline u32 process_events(struct be_net_object *pnob) -{ - struct be_adapter *adapter = pnob->adapter; - struct EQ_ENTRY_AMAP *eqp; - u32 rid, num_events = 0; - struct net_device *netdev = pnob->netdev; - - while ((eqp = get_event(pnob)) != NULL) { - adapter->be_stat.bes_events++; - rid = AMAP_GET_BITS_PTR(EQ_ENTRY, ResourceID, eqp); - if (rid == pnob->rx_cq_id) { - adapter->be_stat.bes_rx_events++; - netif_rx_schedule(&pnob->napi); - } else if (rid == pnob->tx_cq_id) { - process_nic_tx_completions(pnob); - } else if (rid == pnob->mcc_cq_id) { - be_mcc_process_cq(&pnob->mcc_q_obj, 1); - } else { - dev_info(&netdev->dev, - "Invalid EQ ResourceID %d\n", rid); - } - AMAP_SET_BITS_PTR(EQ_ENTRY, Valid, eqp, 0); - AMAP_SET_BITS_PTR(EQ_ENTRY, ResourceID, eqp, 0); - num_events++; - } - return num_events; -} - -static void update_eqd(struct be_adapter *adapter, struct be_net_object *pnob) -{ - int status; - struct be_eq_object *eq_objectp; - - /* update once a second */ - if ((jiffies - adapter->ips_jiffies) > 1 * (HZ)) { - /* One second elapsed since last update */ - u32 r, new_eqd = -1; - r = adapter->be_stat.bes_ints - adapter->be_stat.bes_prev_ints; - r = r / ((jiffies - adapter->ips_jiffies) / (HZ)); - adapter->be_stat.bes_ips = r; - adapter->ips_jiffies = jiffies; - adapter->be_stat.bes_prev_ints = adapter->be_stat.bes_ints; - if (r > IPS_HI_WM && adapter->cur_eqd < adapter->max_eqd) - new_eqd = (adapter->cur_eqd + 8); - if (r < IPS_LO_WM && adapter->cur_eqd > adapter->min_eqd) - new_eqd = (adapter->cur_eqd - 8); - if (adapter->enable_aic && new_eqd != -1) { - eq_objectp = &pnob->event_q_obj; - status = be_eq_modify_delay(&pnob->fn_obj, 1, - &eq_objectp, &new_eqd, NULL, - NULL, NULL); - if (status == BE_SUCCESS) - adapter->cur_eqd = new_eqd; - } - } -} - -/* - This function notifies BladeEngine of how many events were processed - from the event queue by ringing the corresponding door bell and - optionally re-arms the event queue. - n - number of events processed - re_arm - 1 - re-arm the EQ, 0 - do not re-arm the EQ - -*/ -static void be_notify_event(struct be_net_object *pnob, int n, int re_arm) -{ - struct CQ_DB_AMAP eqdb; - eqdb.dw[0] = 0; - - AMAP_SET_BITS_PTR(CQ_DB, qid, &eqdb, pnob->event_q_id); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &eqdb, re_arm); - AMAP_SET_BITS_PTR(CQ_DB, event, &eqdb, 1); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &eqdb, n); - /* - * Under some situations we see an interrupt and no valid - * EQ entry. To keep going, we need to ring the DB even if - * numPOsted is 0. - */ - PD_WRITE(&pnob->fn_obj, cq_db, eqdb.dw[0]); - return; -} - -/* - * Called from the tasklet scheduled by ISR. All real interrupt processing - * is done here. - */ -void be_process_intr(unsigned long context) -{ - struct be_adapter *adapter = (struct be_adapter *)context; - struct be_net_object *pnob = adapter->net_obj; - u32 isr, n; - ulong flags = 0; - - isr = adapter->isr; - - /* - * we create only one NIC event queue in Linux. Event is - * expected only in the first event queue - */ - BUG_ON(isr & 0xfffffffe); - if ((isr & 1) == 0) - return; /* not our interrupt */ - n = process_events(pnob); - /* - * Clear the event bit. adapter->isr is set by - * hard interrupt. Prevent race with lock. - */ - spin_lock_irqsave(&adapter->int_lock, flags); - adapter->isr &= ~1; - spin_unlock_irqrestore(&adapter->int_lock, flags); - be_notify_event(pnob, n, 1); - /* - * If previous allocation attempts had failed and - * BE has used up all posted buffers, post RX buffers here - */ - if (pnob->rxbuf_post_fail && atomic_read(&pnob->rx_q_posted) == 0) - be_post_eth_rx_buffs(pnob); - update_eqd(adapter, pnob); - return; -} diff --git a/drivers/staging/benet/be_netif.c b/drivers/staging/benet/be_netif.c deleted file mode 100644 index 2b8daf63dc7..00000000000 --- a/drivers/staging/benet/be_netif.c +++ /dev/null @@ -1,705 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * be_netif.c - * - * This file contains various entry points of drivers seen by tcp/ip stack. - */ - -#include -#include -#include "benet.h" -#include -#include - -/* Strings to print Link properties */ -static const char *link_speed[] = { - "Invalid link Speed Value", - "10 Mbps", - "100 Mbps", - "1 Gbps", - "10 Gbps" -}; - -static const char *link_duplex[] = { - "Invalid Duplex Value", - "Half Duplex", - "Full Duplex" -}; - -static const char *link_state[] = { - "", - "(active)" -}; - -void be_print_link_info(struct BE_LINK_STATUS *lnk_status) -{ - u16 si, di, ai; - - /* Port 0 */ - if (lnk_status->mac0_speed && lnk_status->mac0_duplex) { - /* Port is up and running */ - si = (lnk_status->mac0_speed < 5) ? lnk_status->mac0_speed : 0; - di = (lnk_status->mac0_duplex < 3) ? - lnk_status->mac0_duplex : 0; - ai = (lnk_status->active_port == 0) ? 1 : 0; - printk(KERN_INFO "PortNo. 0: Speed - %s %s %s\n", - link_speed[si], link_duplex[di], link_state[ai]); - } else - printk(KERN_INFO "PortNo. 0: Down\n"); - - /* Port 1 */ - if (lnk_status->mac1_speed && lnk_status->mac1_duplex) { - /* Port is up and running */ - si = (lnk_status->mac1_speed < 5) ? lnk_status->mac1_speed : 0; - di = (lnk_status->mac1_duplex < 3) ? - lnk_status->mac1_duplex : 0; - ai = (lnk_status->active_port == 0) ? 1 : 0; - printk(KERN_INFO "PortNo. 1: Speed - %s %s %s\n", - link_speed[si], link_duplex[di], link_state[ai]); - } else - printk(KERN_INFO "PortNo. 1: Down\n"); - - return; -} - -static int -be_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr, - void **ip_hdr, void **tcpudp_hdr, - u64 *hdr_flags, void *priv) -{ - struct ethhdr *eh; - struct vlan_ethhdr *veh; - struct iphdr *iph; - u8 *va = page_address(frag->page) + frag->page_offset; - unsigned long ll_hlen; - - /* find the mac header, abort if not IPv4 */ - - prefetch(va); - eh = (struct ethhdr *)va; - *mac_hdr = eh; - ll_hlen = ETH_HLEN; - if (eh->h_proto != htons(ETH_P_IP)) { - if (eh->h_proto == htons(ETH_P_8021Q)) { - veh = (struct vlan_ethhdr *)va; - if (veh->h_vlan_encapsulated_proto != htons(ETH_P_IP)) - return -1; - - ll_hlen += VLAN_HLEN; - - } else { - return -1; - } - } - *hdr_flags = LRO_IPV4; - - iph = (struct iphdr *)(va + ll_hlen); - *ip_hdr = iph; - if (iph->protocol != IPPROTO_TCP) - return -1; - *hdr_flags |= LRO_TCP; - *tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2); - - return 0; -} - -static int benet_open(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - struct net_lro_mgr *lro_mgr; - - if (adapter->dev_state < BE_DEV_STATE_INIT) - return -EAGAIN; - - lro_mgr = &pnob->lro_mgr; - lro_mgr->dev = netdev; - - lro_mgr->features = LRO_F_NAPI; - lro_mgr->ip_summed = CHECKSUM_UNNECESSARY; - lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY; - lro_mgr->max_desc = BE_MAX_LRO_DESCRIPTORS; - lro_mgr->lro_arr = pnob->lro_desc; - lro_mgr->get_frag_header = be_get_frag_header; - lro_mgr->max_aggr = adapter->max_rx_coal; - lro_mgr->frag_align_pad = 2; - if (lro_mgr->max_aggr > MAX_SKB_FRAGS) - lro_mgr->max_aggr = MAX_SKB_FRAGS; - - adapter->max_rx_coal = BE_LRO_MAX_PKTS; - - be_update_link_status(adapter); - - /* - * Set carrier on only if Physical Link up - * Either of the port link status up signifies this - */ - if ((adapter->port0_link_sts == BE_PORT_LINK_UP) || - (adapter->port1_link_sts == BE_PORT_LINK_UP)) { - netif_start_queue(netdev); - netif_carrier_on(netdev); - } - - adapter->dev_state = BE_DEV_STATE_OPEN; - napi_enable(&pnob->napi); - be_enable_intr(pnob); - be_enable_eq_intr(pnob); - /* - * RX completion queue may be in dis-armed state. Arm it. - */ - be_notify_cmpl(pnob, 0, pnob->rx_cq_id, 1); - - return 0; -} - -static int benet_close(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - - netif_stop_queue(netdev); - synchronize_irq(netdev->irq); - - be_wait_nic_tx_cmplx_cmpl(pnob); - adapter->dev_state = BE_DEV_STATE_INIT; - netif_carrier_off(netdev); - - adapter->port0_link_sts = BE_PORT_LINK_DOWN; - adapter->port1_link_sts = BE_PORT_LINK_DOWN; - be_disable_intr(pnob); - be_disable_eq_intr(pnob); - napi_disable(&pnob->napi); - - return 0; -} - -/* - * Setting a Mac Address for BE - * Takes netdev and a void pointer as arguments. - * The pointer holds the new addres to be used. - */ -static int benet_set_mac_addr(struct net_device *netdev, void *p) -{ - struct sockaddr *addr = p; - struct be_net_object *pnob = netdev_priv(netdev); - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - be_rxf_mac_address_read_write(&pnob->fn_obj, 0, 0, false, true, false, - netdev->dev_addr, NULL, NULL); - /* - * Since we are doing Active-Passive failover, both - * ports should have matching MAC addresses everytime. - */ - be_rxf_mac_address_read_write(&pnob->fn_obj, 1, 0, false, true, false, - netdev->dev_addr, NULL, NULL); - - return 0; -} - -void be_get_stats_timer_handler(unsigned long context) -{ - struct be_timer_ctxt *ctxt = (struct be_timer_ctxt *)context; - - if (atomic_read(&ctxt->get_stat_flag)) { - atomic_dec(&ctxt->get_stat_flag); - up((void *)ctxt->get_stat_sem_addr); - } - del_timer(&ctxt->get_stats_timer); - return; -} - -void be_get_stat_cb(void *context, int status, - struct MCC_WRB_AMAP *optional_wrb) -{ - struct be_timer_ctxt *ctxt = (struct be_timer_ctxt *)context; - /* - * just up the semaphore if the get_stat_flag - * reads 1. so that the waiter can continue. - * If it is 0, then it was handled by the timer handler. - */ - del_timer(&ctxt->get_stats_timer); - if (atomic_read(&ctxt->get_stat_flag)) { - atomic_dec(&ctxt->get_stat_flag); - up((void *)ctxt->get_stat_sem_addr); - } -} - -struct net_device_stats *benet_get_stats(struct net_device *dev) -{ - struct be_net_object *pnob = netdev_priv(dev); - struct be_adapter *adapter = pnob->adapter; - u64 pa; - struct be_timer_ctxt *ctxt = &adapter->timer_ctxt; - - if (adapter->dev_state != BE_DEV_STATE_OPEN) { - /* Return previously read stats */ - return &(adapter->benet_stats); - } - /* Get Physical Addr */ - pa = pci_map_single(adapter->pdev, adapter->eth_statsp, - sizeof(struct FWCMD_ETH_GET_STATISTICS), - PCI_DMA_FROMDEVICE); - ctxt->get_stat_sem_addr = (unsigned long)&adapter->get_eth_stat_sem; - atomic_inc(&ctxt->get_stat_flag); - - be_rxf_query_eth_statistics(&pnob->fn_obj, adapter->eth_statsp, - cpu_to_le64(pa), be_get_stat_cb, ctxt, - NULL); - - ctxt->get_stats_timer.data = (unsigned long)ctxt; - mod_timer(&ctxt->get_stats_timer, (jiffies + (HZ * 2))); - down((void *)ctxt->get_stat_sem_addr); /* callback will unblock us */ - - /* Adding port0 and port1 stats. */ - adapter->benet_stats.rx_packets = - adapter->eth_statsp->params.response.p0recvdtotalframes + - adapter->eth_statsp->params.response.p1recvdtotalframes; - adapter->benet_stats.tx_packets = - adapter->eth_statsp->params.response.p0xmitunicastframes + - adapter->eth_statsp->params.response.p1xmitunicastframes; - adapter->benet_stats.tx_bytes = - adapter->eth_statsp->params.response.p0xmitbyteslsd + - adapter->eth_statsp->params.response.p1xmitbyteslsd; - adapter->benet_stats.rx_errors = - adapter->eth_statsp->params.response.p0crcerrors + - adapter->eth_statsp->params.response.p1crcerrors; - adapter->benet_stats.rx_errors += - adapter->eth_statsp->params.response.p0alignmentsymerrs + - adapter->eth_statsp->params.response.p1alignmentsymerrs; - adapter->benet_stats.rx_errors += - adapter->eth_statsp->params.response.p0inrangelenerrors + - adapter->eth_statsp->params.response.p1inrangelenerrors; - adapter->benet_stats.rx_bytes = - adapter->eth_statsp->params.response.p0recvdtotalbytesLSD + - adapter->eth_statsp->params.response.p1recvdtotalbytesLSD; - adapter->benet_stats.rx_crc_errors = - adapter->eth_statsp->params.response.p0crcerrors + - adapter->eth_statsp->params.response.p1crcerrors; - - adapter->benet_stats.tx_packets += - adapter->eth_statsp->params.response.p0xmitmulticastframes + - adapter->eth_statsp->params.response.p1xmitmulticastframes; - adapter->benet_stats.tx_packets += - adapter->eth_statsp->params.response.p0xmitbroadcastframes + - adapter->eth_statsp->params.response.p1xmitbroadcastframes; - adapter->benet_stats.tx_errors = 0; - - adapter->benet_stats.multicast = - adapter->eth_statsp->params.response.p0xmitmulticastframes + - adapter->eth_statsp->params.response.p1xmitmulticastframes; - - adapter->benet_stats.rx_fifo_errors = - adapter->eth_statsp->params.response.p0rxfifooverflowdropped + - adapter->eth_statsp->params.response.p1rxfifooverflowdropped; - adapter->benet_stats.rx_frame_errors = - adapter->eth_statsp->params.response.p0alignmentsymerrs + - adapter->eth_statsp->params.response.p1alignmentsymerrs; - adapter->benet_stats.rx_length_errors = - adapter->eth_statsp->params.response.p0inrangelenerrors + - adapter->eth_statsp->params.response.p1inrangelenerrors; - adapter->benet_stats.rx_length_errors += - adapter->eth_statsp->params.response.p0outrangeerrors + - adapter->eth_statsp->params.response.p1outrangeerrors; - adapter->benet_stats.rx_length_errors += - adapter->eth_statsp->params.response.p0frametoolongerrors + - adapter->eth_statsp->params.response.p1frametoolongerrors; - - pci_unmap_single(adapter->pdev, (ulong) adapter->eth_statsp, - sizeof(struct FWCMD_ETH_GET_STATISTICS), - PCI_DMA_FROMDEVICE); - return &(adapter->benet_stats); - -} - -static void be_start_tx(struct be_net_object *pnob, u32 nposted) -{ -#define CSR_ETH_MAX_SQPOSTS 255 - struct SQ_DB_AMAP sqdb; - - sqdb.dw[0] = 0; - - AMAP_SET_BITS_PTR(SQ_DB, cid, &sqdb, pnob->tx_q_id); - while (nposted) { - if (nposted > CSR_ETH_MAX_SQPOSTS) { - AMAP_SET_BITS_PTR(SQ_DB, numPosted, &sqdb, - CSR_ETH_MAX_SQPOSTS); - nposted -= CSR_ETH_MAX_SQPOSTS; - } else { - AMAP_SET_BITS_PTR(SQ_DB, numPosted, &sqdb, nposted); - nposted = 0; - } - PD_WRITE(&pnob->fn_obj, etx_sq_db, sqdb.dw[0]); - } - - return; -} - -static void update_tx_rate(struct be_adapter *adapter) -{ - /* update the rate once in two seconds */ - if ((jiffies - adapter->eth_tx_jiffies) > 2 * (HZ)) { - u32 r; - r = adapter->eth_tx_bytes / - ((jiffies - adapter->eth_tx_jiffies) / (HZ)); - r = (r / 1000000); /* M bytes/s */ - adapter->be_stat.bes_eth_tx_rate = (r * 8); /* M bits/s */ - adapter->eth_tx_jiffies = jiffies; - adapter->eth_tx_bytes = 0; - } -} - -static int wrb_cnt_in_skb(struct sk_buff *skb) -{ - int cnt = 0; - while (skb) { - if (skb->len > skb->data_len) - cnt++; - cnt += skb_shinfo(skb)->nr_frags; - skb = skb_shinfo(skb)->frag_list; - } - BUG_ON(cnt > BE_MAX_TX_FRAG_COUNT); - return cnt; -} - -static void wrb_fill(struct ETH_WRB_AMAP *wrb, u64 addr, int len) -{ - AMAP_SET_BITS_PTR(ETH_WRB, frag_pa_hi, wrb, addr >> 32); - AMAP_SET_BITS_PTR(ETH_WRB, frag_pa_lo, wrb, addr & 0xFFFFFFFF); - AMAP_SET_BITS_PTR(ETH_WRB, frag_len, wrb, len); -} - -static void wrb_fill_extra(struct ETH_WRB_AMAP *wrb, struct sk_buff *skb, - struct be_net_object *pnob) -{ - wrb->dw[2] = 0; - wrb->dw[3] = 0; - AMAP_SET_BITS_PTR(ETH_WRB, crc, wrb, 1); - if (skb_shinfo(skb)->gso_segs > 1 && skb_shinfo(skb)->gso_size) { - AMAP_SET_BITS_PTR(ETH_WRB, lso, wrb, 1); - AMAP_SET_BITS_PTR(ETH_WRB, lso_mss, wrb, - skb_shinfo(skb)->gso_size); - } else if (skb->ip_summed == CHECKSUM_PARTIAL) { - u8 proto = ((struct iphdr *)ip_hdr(skb))->protocol; - if (proto == IPPROTO_TCP) - AMAP_SET_BITS_PTR(ETH_WRB, tcpcs, wrb, 1); - else if (proto == IPPROTO_UDP) - AMAP_SET_BITS_PTR(ETH_WRB, udpcs, wrb, 1); - } - if (pnob->vlan_grp && vlan_tx_tag_present(skb)) { - AMAP_SET_BITS_PTR(ETH_WRB, vlan, wrb, 1); - AMAP_SET_BITS_PTR(ETH_WRB, vlan_tag, wrb, vlan_tx_tag_get(skb)); - } -} - -static inline void wrb_copy_extra(struct ETH_WRB_AMAP *to, - struct ETH_WRB_AMAP *from) -{ - - to->dw[2] = from->dw[2]; - to->dw[3] = from->dw[3]; -} - -/* Returns the actual count of wrbs used including a possible dummy */ -static int copy_skb_to_txq(struct be_net_object *pnob, struct sk_buff *skb, - u32 wrb_cnt, u32 *copied) -{ - u64 busaddr; - struct ETH_WRB_AMAP *wrb = NULL, *first = NULL; - u32 i; - bool dummy = true; - struct pci_dev *pdev = pnob->adapter->pdev; - - if (wrb_cnt & 1) - wrb_cnt++; - else - dummy = false; - - atomic_add(wrb_cnt, &pnob->tx_q_used); - - while (skb) { - if (skb->len > skb->data_len) { - int len = skb->len - skb->data_len; - busaddr = pci_map_single(pdev, skb->data, len, - PCI_DMA_TODEVICE); - busaddr = cpu_to_le64(busaddr); - wrb = &pnob->tx_q[pnob->tx_q_hd]; - if (first == NULL) { - wrb_fill_extra(wrb, skb, pnob); - first = wrb; - } else { - wrb_copy_extra(wrb, first); - } - wrb_fill(wrb, busaddr, len); - be_adv_txq_hd(pnob); - *copied += len; - } - - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - struct skb_frag_struct *frag = - &skb_shinfo(skb)->frags[i]; - busaddr = pci_map_page(pdev, frag->page, - frag->page_offset, frag->size, - PCI_DMA_TODEVICE); - busaddr = cpu_to_le64(busaddr); - wrb = &pnob->tx_q[pnob->tx_q_hd]; - if (first == NULL) { - wrb_fill_extra(wrb, skb, pnob); - first = wrb; - } else { - wrb_copy_extra(wrb, first); - } - wrb_fill(wrb, busaddr, frag->size); - be_adv_txq_hd(pnob); - *copied += frag->size; - } - skb = skb_shinfo(skb)->frag_list; - } - - if (dummy) { - wrb = &pnob->tx_q[pnob->tx_q_hd]; - BUG_ON(first == NULL); - wrb_copy_extra(wrb, first); - wrb_fill(wrb, 0, 0); - be_adv_txq_hd(pnob); - } - AMAP_SET_BITS_PTR(ETH_WRB, complete, wrb, 1); - AMAP_SET_BITS_PTR(ETH_WRB, last, wrb, 1); - return wrb_cnt; -} - -/* For each skb transmitted, tx_ctxt stores the num of wrbs in the - * start index and skb pointer in the end index - */ -static inline void be_tx_wrb_info_remember(struct be_net_object *pnob, - struct sk_buff *skb, int wrb_cnt, - u32 start) -{ - *(u32 *) (&pnob->tx_ctxt[start]) = wrb_cnt; - index_adv(&start, wrb_cnt - 1, pnob->tx_q_len); - pnob->tx_ctxt[start] = skb; -} - -static int benet_xmit(struct sk_buff *skb, struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - u32 wrb_cnt, copied = 0; - u32 start = pnob->tx_q_hd; - - adapter->be_stat.bes_tx_reqs++; - - wrb_cnt = wrb_cnt_in_skb(skb); - spin_lock_bh(&adapter->txq_lock); - if ((pnob->tx_q_len - 2 - atomic_read(&pnob->tx_q_used)) <= wrb_cnt) { - netif_stop_queue(pnob->netdev); - spin_unlock_bh(&adapter->txq_lock); - adapter->be_stat.bes_tx_fails++; - return NETDEV_TX_BUSY; - } - spin_unlock_bh(&adapter->txq_lock); - - wrb_cnt = copy_skb_to_txq(pnob, skb, wrb_cnt, &copied); - be_tx_wrb_info_remember(pnob, skb, wrb_cnt, start); - - be_start_tx(pnob, wrb_cnt); - - adapter->eth_tx_bytes += copied; - adapter->be_stat.bes_tx_wrbs += wrb_cnt; - update_tx_rate(adapter); - netdev->trans_start = jiffies; - - return NETDEV_TX_OK; -} - -/* - * This is the driver entry point to change the mtu of the device - * Returns 0 for success and errno for failure. - */ -static int benet_change_mtu(struct net_device *netdev, int new_mtu) -{ - /* - * BE supports jumbo frame size upto 9000 bytes including the link layer - * header. Considering the different variants of frame formats possible - * like VLAN, SNAP/LLC, the maximum possible value for MTU is 8974 bytes - */ - - if (new_mtu < (ETH_ZLEN + ETH_FCS_LEN) || (new_mtu > BE_MAX_MTU)) { - dev_info(&netdev->dev, "Invalid MTU requested. " - "Must be between %d and %d bytes\n", - (ETH_ZLEN + ETH_FCS_LEN), BE_MAX_MTU); - return -EINVAL; - } - dev_info(&netdev->dev, "MTU changed from %d to %d\n", - netdev->mtu, new_mtu); - netdev->mtu = new_mtu; - return 0; -} - -/* - * This is the driver entry point to register a vlan with the device - */ -static void benet_vlan_register(struct net_device *netdev, - struct vlan_group *grp) -{ - struct be_net_object *pnob = netdev_priv(netdev); - - be_disable_eq_intr(pnob); - pnob->vlan_grp = grp; - pnob->num_vlans = 0; - be_enable_eq_intr(pnob); -} - -/* - * This is the driver entry point to add a vlan vlan_id - * with the device netdev - */ -static void benet_vlan_add_vid(struct net_device *netdev, u16 vlan_id) -{ - struct be_net_object *pnob = netdev_priv(netdev); - - if (pnob->num_vlans == (BE_NUM_VLAN_SUPPORTED - 1)) { - /* no way to return an error */ - dev_info(&netdev->dev, - "BladeEngine: Cannot configure more than %d Vlans\n", - BE_NUM_VLAN_SUPPORTED); - return; - } - /* The new vlan tag will be in the slot indicated by num_vlans. */ - pnob->vlan_tag[pnob->num_vlans++] = vlan_id; - be_rxf_vlan_config(&pnob->fn_obj, false, pnob->num_vlans, - pnob->vlan_tag, NULL, NULL, NULL); -} - -/* - * This is the driver entry point to remove a vlan vlan_id - * with the device netdev - */ -static void benet_vlan_rem_vid(struct net_device *netdev, u16 vlan_id) -{ - struct be_net_object *pnob = netdev_priv(netdev); - - u32 i, value; - - /* - * In Blade Engine, we support 32 vlan tag filters across both ports. - * To program a vlan tag, the RXF_RTPR_CSR register is used. - * Each 32-bit value of RXF_RTDR_CSR can address 2 vlan tag entries. - * The Vlan table is of depth 16. thus we support 32 tags. - */ - - value = vlan_id | VLAN_VALID_BIT; - for (i = 0; i < BE_NUM_VLAN_SUPPORTED; i++) { - if (pnob->vlan_tag[i] == vlan_id) - break; - } - - if (i == BE_NUM_VLAN_SUPPORTED) - return; - /* Now compact the vlan tag array by removing hole created. */ - while ((i + 1) < BE_NUM_VLAN_SUPPORTED) { - pnob->vlan_tag[i] = pnob->vlan_tag[i + 1]; - i++; - } - if ((i + 1) == BE_NUM_VLAN_SUPPORTED) - pnob->vlan_tag[i] = (u16) 0x0; - pnob->num_vlans--; - be_rxf_vlan_config(&pnob->fn_obj, false, pnob->num_vlans, - pnob->vlan_tag, NULL, NULL, NULL); -} - -/* - * This function is called to program multicast - * address in the multicast filter of the ASIC. - */ -static void be_set_multicast_filter(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct dev_mc_list *mc_ptr; - u8 mac_addr[32][ETH_ALEN]; - int i; - - if (netdev->flags & IFF_ALLMULTI) { - /* set BE in Multicast promiscuous */ - be_rxf_multicast_config(&pnob->fn_obj, true, 0, NULL, NULL, - NULL, NULL); - return; - } - - for (mc_ptr = netdev->mc_list, i = 0; mc_ptr; - mc_ptr = mc_ptr->next, i++) { - memcpy(&mac_addr[i][0], mc_ptr->dmi_addr, ETH_ALEN); - } - - /* reset the promiscuous mode also. */ - be_rxf_multicast_config(&pnob->fn_obj, false, i, - &mac_addr[0][0], NULL, NULL, NULL); -} - -/* - * This is the driver entry point to set multicast list - * with the device netdev. This function will be used to - * set promiscuous mode or multicast promiscuous mode - * or multicast mode.... - */ -static void benet_set_multicast_list(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - - if (netdev->flags & IFF_PROMISC) { - be_rxf_promiscuous(&pnob->fn_obj, 1, 1, NULL, NULL, NULL); - } else { - be_rxf_promiscuous(&pnob->fn_obj, 0, 0, NULL, NULL, NULL); - be_set_multicast_filter(netdev); - } -} - -int benet_init(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - - ether_setup(netdev); - - netdev->open = &benet_open; - netdev->stop = &benet_close; - netdev->hard_start_xmit = &benet_xmit; - - netdev->get_stats = &benet_get_stats; - - netdev->set_multicast_list = &benet_set_multicast_list; - - netdev->change_mtu = &benet_change_mtu; - netdev->set_mac_address = &benet_set_mac_addr; - - netdev->vlan_rx_register = benet_vlan_register; - netdev->vlan_rx_add_vid = benet_vlan_add_vid; - netdev->vlan_rx_kill_vid = benet_vlan_rem_vid; - - netdev->features = - NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_HW_VLAN_RX | NETIF_F_TSO | - NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_IP_CSUM; - - netdev->flags |= IFF_MULTICAST; - - /* If device is DAC Capable, set the HIGHDMA flag for netdevice. */ - if (adapter->dma_64bit_cap) - netdev->features |= NETIF_F_HIGHDMA; - - SET_ETHTOOL_OPS(netdev, &be_ethtool_ops); - return 0; -} diff --git a/drivers/staging/benet/benet.h b/drivers/staging/benet/benet.h deleted file mode 100644 index 09a1f081772..00000000000 --- a/drivers/staging/benet/benet.h +++ /dev/null @@ -1,429 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#ifndef _BENET_H_ -#define _BENET_H_ - -#include -#include -#include -#include "hwlib.h" - -#define _SA_MODULE_NAME "net-driver" - -#define VLAN_VALID_BIT 0x8000 -#define BE_NUM_VLAN_SUPPORTED 32 -#define BE_PORT_LINK_DOWN 0000 -#define BE_PORT_LINK_UP 0001 -#define BE_MAX_TX_FRAG_COUNT (30) - -/* Flag bits for send operation */ -#define IPCS (1 << 0) /* Enable IP checksum offload */ -#define UDPCS (1 << 1) /* Enable UDP checksum offload */ -#define TCPCS (1 << 2) /* Enable TCP checksum offload */ -#define LSO (1 << 3) /* Enable Large Segment offload */ -#define ETHVLAN (1 << 4) /* Enable VLAN insert */ -#define ETHEVENT (1 << 5) /* Generate event on completion */ -#define ETHCOMPLETE (1 << 6) /* Generate completion when done */ -#define IPSEC (1 << 7) /* Enable IPSEC */ -#define FORWARD (1 << 8) /* Send the packet in forwarding path */ -#define FIN (1 << 9) /* Issue FIN segment */ - -#define BE_MAX_MTU 8974 - -#define BE_MAX_LRO_DESCRIPTORS 8 -#define BE_LRO_MAX_PKTS 64 -#define BE_MAX_FRAGS_PER_FRAME 6 - -extern const char be_drvr_ver[]; -extern char be_fw_ver[]; -extern char be_driver_name[]; - -extern struct ethtool_ops be_ethtool_ops; - -#define BE_DEV_STATE_NONE 0 -#define BE_DEV_STATE_INIT 1 -#define BE_DEV_STATE_OPEN 2 -#define BE_DEV_STATE_SUSPEND 3 - -/* This structure is used to describe physical fragments to use - * for DMAing data from NIC. - */ -struct be_recv_buffer { - struct list_head rxb_list; /* for maintaining a linked list */ - void *rxb_va; /* buffer virtual address */ - u32 rxb_pa_lo; /* low part of physical address */ - u32 rxb_pa_hi; /* high part of physical address */ - u32 rxb_len; /* length of recv buffer */ - void *rxb_ctxt; /* context for OSM driver to use */ -}; - -/* - * fragment list to describe scattered data. - */ -struct be_tx_frag_list { - u32 txb_len; /* Size of this fragment */ - u32 txb_pa_lo; /* Lower 32 bits of 64 bit physical addr */ - u32 txb_pa_hi; /* Higher 32 bits of 64 bit physical addr */ -}; - -struct be_rx_page_info { - struct page *page; - dma_addr_t bus; - u16 page_offset; -}; - -/* - * This structure is the main tracking structure for a NIC interface. - */ -struct be_net_object { - /* MCC Ring - used to send fwcmds to embedded ARM processor */ - struct MCC_WRB_AMAP *mcc_q; /* VA of the start of the ring */ - u32 mcc_q_len; /* # of WRB entries in this ring */ - u32 mcc_q_size; - u32 mcc_q_hd; /* MCC ring head */ - u8 mcc_q_created; /* flag to help cleanup */ - struct be_mcc_object mcc_q_obj; /* BECLIB's MCC ring Object */ - dma_addr_t mcc_q_bus; /* DMA'ble bus address */ - - /* MCC Completion Ring - FW responses to fwcmds sent from MCC ring */ - struct MCC_CQ_ENTRY_AMAP *mcc_cq; /* VA of the start of the ring */ - u32 mcc_cq_len; /* # of compl. entries in this ring */ - u32 mcc_cq_size; - u32 mcc_cq_tl; /* compl. ring tail */ - u8 mcc_cq_created; /* flag to help cleanup */ - struct be_cq_object mcc_cq_obj; /* BECLIB's MCC compl. ring object */ - u32 mcc_cq_id; /* MCC ring ID */ - dma_addr_t mcc_cq_bus; /* DMA'ble bus address */ - - struct ring_desc mb_rd; /* RD for MCC_MAIL_BOX */ - void *mb_ptr; /* mailbox ptr to be freed */ - dma_addr_t mb_bus; /* DMA'ble bus address */ - u32 mb_size; - - /* BEClib uses an array of context objects to track outstanding - * requests to the MCC. We need allocate the same number of - * conext entries as the number of entries in the MCC WRB ring - */ - u32 mcc_wrb_ctxt_size; - void *mcc_wrb_ctxt; /* pointer to the context area */ - u32 mcc_wrb_ctxtLen; /* Number of entries in the context */ - /* - * NIC send request ring - used for xmitting raw ether frames. - */ - struct ETH_WRB_AMAP *tx_q; /* VA of the start of the ring */ - u32 tx_q_len; /* # if entries in the send ring */ - u32 tx_q_size; - u32 tx_q_hd; /* Head index. Next req. goes here */ - u32 tx_q_tl; /* Tail indx. oldest outstanding req. */ - u8 tx_q_created; /* flag to help cleanup */ - struct be_ethsq_object tx_q_obj;/* BECLIB's send Q handle */ - dma_addr_t tx_q_bus; /* DMA'ble bus address */ - u32 tx_q_id; /* send queue ring ID */ - u32 tx_q_port; /* 0 no binding, 1 port A, 2 port B */ - atomic_t tx_q_used; /* # of WRBs used */ - /* ptr to an array in which we store context info for each send req. */ - void **tx_ctxt; - /* - * NIC Send compl. ring - completion status for all NIC frames xmitted. - */ - struct ETH_TX_COMPL_AMAP *tx_cq;/* VA of start of the ring */ - u32 txcq_len; /* # of entries in the ring */ - u32 tx_cq_size; - /* - * index into compl ring where the host expects next completion entry - */ - u32 tx_cq_tl; - u32 tx_cq_id; /* completion queue id */ - u8 tx_cq_created; /* flag to help cleanup */ - struct be_cq_object tx_cq_obj; - dma_addr_t tx_cq_bus; /* DMA'ble bus address */ - /* - * Event Queue - all completion entries post events here. - */ - struct EQ_ENTRY_AMAP *event_q; /* VA of start of event queue */ - u32 event_q_len; /* # of entries */ - u32 event_q_size; - u32 event_q_tl; /* Tail of the event queue */ - u32 event_q_id; /* Event queue ID */ - u8 event_q_created; /* flag to help cleanup */ - struct be_eq_object event_q_obj; /* Queue handle */ - dma_addr_t event_q_bus; /* DMA'ble bus address */ - /* - * NIC receive queue - Data buffers to be used for receiving unicast, - * broadcast and multi-cast frames are posted here. - */ - struct ETH_RX_D_AMAP *rx_q; /* VA of start of the queue */ - u32 rx_q_len; /* # of entries */ - u32 rx_q_size; - u32 rx_q_hd; /* Head of the queue */ - atomic_t rx_q_posted; /* number of posted buffers */ - u32 rx_q_id; /* queue ID */ - u8 rx_q_created; /* flag to help cleanup */ - struct be_ethrq_object rx_q_obj; /* NIC RX queue handle */ - dma_addr_t rx_q_bus; /* DMA'ble bus address */ - /* - * Pointer to an array of opaque context object for use by OSM driver - */ - void **rx_ctxt; - /* - * NIC unicast RX completion queue - all unicast ether frame completion - * statuses from BE come here. - */ - struct ETH_RX_COMPL_AMAP *rx_cq; /* VA of start of the queue */ - u32 rx_cq_len; /* # of entries */ - u32 rx_cq_size; - u32 rx_cq_tl; /* Tail of the queue */ - u32 rx_cq_id; /* queue ID */ - u8 rx_cq_created; /* flag to help cleanup */ - struct be_cq_object rx_cq_obj; /* queue handle */ - dma_addr_t rx_cq_bus; /* DMA'ble bus address */ - struct be_function_object fn_obj; /* function object */ - bool fn_obj_created; - u32 rx_buf_size; /* Size of the RX buffers */ - - struct net_device *netdev; - struct be_recv_buffer eth_rx_bufs[256]; /* to pass Rx buffer - addresses */ - struct be_adapter *adapter; /* Pointer to OSM adapter */ - u32 devno; /* OSM, network dev no. */ - u32 use_port; /* Current active port */ - struct be_rx_page_info *rx_page_info; /* Array of Rx buf pages */ - u32 rx_pg_info_hd; /* Head of queue */ - int rxbuf_post_fail; /* RxBuff posting fail count */ - bool rx_pg_shared; /* Is an allocsted page shared as two frags ? */ - struct vlan_group *vlan_grp; - u32 num_vlans; /* Number of vlans in BE's filter */ - u16 vlan_tag[BE_NUM_VLAN_SUPPORTED]; /* vlans currently configured */ - struct napi_struct napi; - struct net_lro_mgr lro_mgr; - struct net_lro_desc lro_desc[BE_MAX_LRO_DESCRIPTORS]; -}; - -#define NET_FH(np) (&(np)->fn_obj) - -/* - * BE driver statistics. - */ -struct be_drvr_stat { - u32 bes_tx_reqs; /* number of TX requests initiated */ - u32 bes_tx_fails; /* number of TX requests that failed */ - u32 bes_fwd_reqs; /* number of send reqs through forwarding i/f */ - u32 bes_tx_wrbs; /* number of tx WRBs used */ - - u32 bes_ints; /* number of interrupts */ - u32 bes_polls; /* number of times NAPI called poll function */ - u32 bes_events; /* total evet entries processed */ - u32 bes_tx_events; /* number of tx completion events */ - u32 bes_rx_events; /* number of ucast rx completion events */ - u32 bes_tx_compl; /* number of tx completion entries processed */ - u32 bes_rx_compl; /* number of rx completion entries - processed */ - u32 bes_ethrx_post_fail; /* number of ethrx buffer alloc - failures */ - /* - * number of non ether type II frames dropped where - * frame len > length field of Mac Hdr - */ - u32 bes_802_3_dropped_frames; - /* - * number of non ether type II frames malformed where - * in frame len < length field of Mac Hdr - */ - u32 bes_802_3_malformed_frames; - u32 bes_ips; /* interrupts / sec */ - u32 bes_prev_ints; /* bes_ints at last IPS calculation */ - u16 bes_eth_tx_rate; /* ETH TX rate - Mb/sec */ - u16 bes_eth_rx_rate; /* ETH RX rate - Mb/sec */ - u32 bes_rx_coal; /* Num pkts coalasced */ - u32 bes_rx_flush; /* Num times coalasced */ - u32 bes_link_change_physical; /*Num of times physical link changed */ - u32 bes_link_change_virtual; /*Num of times virtual link changed */ - u32 bes_rx_misc_pkts; /* Misc pkts received */ -}; - -/* Maximum interrupt delay (in microseconds) allowed */ -#define MAX_EQD 120 - -/* - * timer to prevent system shutdown hang for ever if h/w stops responding - */ -struct be_timer_ctxt { - atomic_t get_stat_flag; - struct timer_list get_stats_timer; - unsigned long get_stat_sem_addr; -} ; - -/* This structure is the main BladeEngine driver context. */ -struct be_adapter { - struct net_device *netdevp; - struct be_drvr_stat be_stat; - struct net_device_stats benet_stats; - - /* PCI BAR mapped addresses */ - u8 __iomem *csr_va; /* CSR */ - u8 __iomem *db_va; /* Door Bell */ - u8 __iomem *pci_va; /* PCI Config */ - - struct tasklet_struct sts_handler; - struct timer_list cq_timer; - spinlock_t int_lock; /* to protect the isr field in adapter */ - - struct FWCMD_ETH_GET_STATISTICS *eth_statsp; - /* - * This will enable the use of ethtool to enable or disable - * Checksum on Rx pkts to be obeyed or disobeyed. - * If this is true = 1, then whatever is the checksum on the - * Received pkt as per BE, it will be given to the stack. - * Else the stack will re calculate it. - */ - bool rx_csum; - /* - * This will enable the use of ethtool to enable or disable - * Coalese on Rx pkts to be obeyed or disobeyed. - * If this is grater than 0 and less than 16 then coalascing - * is enabled else it is disabled - */ - u32 max_rx_coal; - struct pci_dev *pdev; /* Pointer to OS's PCI dvice */ - - spinlock_t txq_lock; /* to stop/wake queue based on tx_q_used */ - - u32 isr; /* copy of Intr status reg. */ - - u32 port0_link_sts; /* Port 0 link status */ - u32 port1_link_sts; /* port 1 list status */ - struct BE_LINK_STATUS *be_link_sts; - - /* pointer to the first netobject of this adapter */ - struct be_net_object *net_obj; - - /* Flags to indicate what to clean up */ - bool tasklet_started; - bool isr_registered; - /* - * adaptive interrupt coalescing (AIC) related - */ - bool enable_aic; /* 1 if AIC is enabled */ - u16 min_eqd; /* minimum EQ delay in usec */ - u16 max_eqd; /* minimum EQ delay in usec */ - u16 cur_eqd; /* current EQ delay in usec */ - /* - * book keeping for interrupt / sec and TX/RX rate calculation - */ - ulong ips_jiffies; /* jiffies at last IPS calc */ - u32 eth_tx_bytes; - ulong eth_tx_jiffies; - u32 eth_rx_bytes; - ulong eth_rx_jiffies; - - struct semaphore get_eth_stat_sem; - - /* timer ctxt to prevent shutdown hanging due to un-responsive BE */ - struct be_timer_ctxt timer_ctxt; - -#define BE_MAX_MSIX_VECTORS 32 -#define BE_MAX_REQ_MSIX_VECTORS 1 /* only one EQ in Linux driver */ - struct msix_entry msix_entries[BE_MAX_MSIX_VECTORS]; - bool msix_enabled; - bool dma_64bit_cap; /* the Device DAC capable or not */ - u8 dev_state; /* The current state of the device */ - u8 dev_pm_state; /* The State of device before going to suspend */ -}; - -/* - * Every second we look at the ints/sec and adjust eq_delay - * between adapter->min_eqd and adapter->max_eqd to keep the ints/sec between - * IPS_HI_WM and IPS_LO_WM. - */ -#define IPS_HI_WM 18000 -#define IPS_LO_WM 8000 - - -static inline void index_adv(u32 *index, u32 val, u32 limit) -{ - BUG_ON(limit & (limit-1)); - *index = (*index + val) & (limit - 1); -} - -static inline void index_inc(u32 *index, u32 limit) -{ - BUG_ON(limit & (limit-1)); - *index = (*index + 1) & (limit - 1); -} - -static inline void be_adv_eq_tl(struct be_net_object *pnob) -{ - index_inc(&pnob->event_q_tl, pnob->event_q_len); -} - -static inline void be_adv_txq_hd(struct be_net_object *pnob) -{ - index_inc(&pnob->tx_q_hd, pnob->tx_q_len); -} - -static inline void be_adv_txq_tl(struct be_net_object *pnob) -{ - index_inc(&pnob->tx_q_tl, pnob->tx_q_len); -} - -static inline void be_adv_txcq_tl(struct be_net_object *pnob) -{ - index_inc(&pnob->tx_cq_tl, pnob->txcq_len); -} - -static inline void be_adv_rxq_hd(struct be_net_object *pnob) -{ - index_inc(&pnob->rx_q_hd, pnob->rx_q_len); -} - -static inline void be_adv_rxcq_tl(struct be_net_object *pnob) -{ - index_inc(&pnob->rx_cq_tl, pnob->rx_cq_len); -} - -static inline u32 tx_compl_lastwrb_idx_get(struct be_net_object *pnob) -{ - return (pnob->tx_q_tl + *(u32 *)&pnob->tx_ctxt[pnob->tx_q_tl] - 1) - & (pnob->tx_q_len - 1); -} - -int benet_init(struct net_device *); -int be_ethtool_ioctl(struct net_device *, struct ifreq *); -struct net_device_stats *benet_get_stats(struct net_device *); -void be_process_intr(unsigned long context); -irqreturn_t be_int(int irq, void *dev); -void be_post_eth_rx_buffs(struct be_net_object *); -void be_get_stat_cb(void *, int, struct MCC_WRB_AMAP *); -void be_get_stats_timer_handler(unsigned long); -void be_wait_nic_tx_cmplx_cmpl(struct be_net_object *); -void be_print_link_info(struct BE_LINK_STATUS *); -void be_update_link_status(struct be_adapter *); -void be_init_procfs(struct be_adapter *); -void be_cleanup_procfs(struct be_adapter *); -int be_poll(struct napi_struct *, int); -struct ETH_RX_COMPL_AMAP *be_get_rx_cmpl(struct be_net_object *); -void be_notify_cmpl(struct be_net_object *, int, int, int); -void be_enable_intr(struct be_net_object *); -void be_enable_eq_intr(struct be_net_object *); -void be_disable_intr(struct be_net_object *); -void be_disable_eq_intr(struct be_net_object *); -int be_set_uc_mac_adr(struct be_net_object *, u8, u8, u8, - u8 *, mcc_wrb_cqe_callback, void *); -int be_get_flow_ctl(struct be_function_object *pFnObj, bool *, bool *); -void process_one_tx_compl(struct be_net_object *pnob, u32 end_idx); - -#endif /* _BENET_H_ */ diff --git a/drivers/staging/benet/bestatus.h b/drivers/staging/benet/bestatus.h deleted file mode 100644 index 59c7a4b6222..00000000000 --- a/drivers/staging/benet/bestatus.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#ifndef _BESTATUS_H_ -#define _BESTATUS_H_ - -#define BE_SUCCESS (0x00000000L) -/* - * MessageId: BE_PENDING - * The BladeEngine Driver call succeeded, and pended operation. - */ -#define BE_PENDING (0x20070001L) -#define BE_STATUS_PENDING (BE_PENDING) -/* - * MessageId: BE_NOT_OK - * An error occurred. - */ -#define BE_NOT_OK (0xE0070002L) -/* - * MessageId: BE_STATUS_SYSTEM_RESOURCES - * Insufficient host system resources exist to complete the API. - */ -#define BE_STATUS_SYSTEM_RESOURCES (0xE0070003L) -/* - * MessageId: BE_STATUS_CHIP_RESOURCES - * Insufficient chip resources exist to complete the API. - */ -#define BE_STATUS_CHIP_RESOURCES (0xE0070004L) -/* - * MessageId: BE_STATUS_NO_RESOURCE - * Insufficient resources to complete request. - */ -#define BE_STATUS_NO_RESOURCE (0xE0070005L) -/* - * MessageId: BE_STATUS_BUSY - * Resource is currently busy. - */ -#define BE_STATUS_BUSY (0xE0070006L) -/* - * MessageId: BE_STATUS_INVALID_PARAMETER - * Invalid Parameter in request. - */ -#define BE_STATUS_INVALID_PARAMETER (0xE0000007L) -/* - * MessageId: BE_STATUS_NOT_SUPPORTED - * Requested operation is not supported. - */ -#define BE_STATUS_NOT_SUPPORTED (0xE000000DL) - -/* - * *************************************************************************** - * E T H E R N E T S T A T U S - * *************************************************************************** - */ - -/* - * MessageId: BE_ETH_TX_ERROR - * The Ethernet device driver failed to transmit a packet. - */ -#define BE_ETH_TX_ERROR (0xE0070101L) - -/* - * *************************************************************************** - * S H A R E D S T A T U S - * *************************************************************************** - */ - -/* - * MessageId: BE_STATUS_VBD_INVALID_VERSION - * The device driver is not compatible with this version of the VBD. - */ -#define BE_STATUS_INVALID_VERSION (0xE0070402L) -/* - * MessageId: BE_STATUS_DOMAIN_DENIED - * The operation failed to complete due to insufficient access - * rights for the requesting domain. - */ -#define BE_STATUS_DOMAIN_DENIED (0xE0070403L) -/* - * MessageId: BE_STATUS_TCP_NOT_STARTED - * The embedded TCP/IP stack has not been started. - */ -#define BE_STATUS_TCP_NOT_STARTED (0xE0070409L) -/* - * MessageId: BE_STATUS_NO_MCC_WRB - * No free MCC WRB are available for posting the request. - */ -#define BE_STATUS_NO_MCC_WRB (0xE0070414L) - -#endif /* _BESTATUS_ */ diff --git a/drivers/staging/benet/cev.h b/drivers/staging/benet/cev.h deleted file mode 100644 index 30996920a54..00000000000 --- a/drivers/staging/benet/cev.h +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __cev_amap_h__ -#define __cev_amap_h__ -#include "ep.h" - -/* - * Host Interrupt Status Register 0. The first of four application - * interrupt status registers. This register contains the interrupts - * for Event Queues EQ0 through EQ31. - */ -struct BE_CEV_ISR0_CSR_AMAP { - u8 interrupt0; /* DWORD 0 */ - u8 interrupt1; /* DWORD 0 */ - u8 interrupt2; /* DWORD 0 */ - u8 interrupt3; /* DWORD 0 */ - u8 interrupt4; /* DWORD 0 */ - u8 interrupt5; /* DWORD 0 */ - u8 interrupt6; /* DWORD 0 */ - u8 interrupt7; /* DWORD 0 */ - u8 interrupt8; /* DWORD 0 */ - u8 interrupt9; /* DWORD 0 */ - u8 interrupt10; /* DWORD 0 */ - u8 interrupt11; /* DWORD 0 */ - u8 interrupt12; /* DWORD 0 */ - u8 interrupt13; /* DWORD 0 */ - u8 interrupt14; /* DWORD 0 */ - u8 interrupt15; /* DWORD 0 */ - u8 interrupt16; /* DWORD 0 */ - u8 interrupt17; /* DWORD 0 */ - u8 interrupt18; /* DWORD 0 */ - u8 interrupt19; /* DWORD 0 */ - u8 interrupt20; /* DWORD 0 */ - u8 interrupt21; /* DWORD 0 */ - u8 interrupt22; /* DWORD 0 */ - u8 interrupt23; /* DWORD 0 */ - u8 interrupt24; /* DWORD 0 */ - u8 interrupt25; /* DWORD 0 */ - u8 interrupt26; /* DWORD 0 */ - u8 interrupt27; /* DWORD 0 */ - u8 interrupt28; /* DWORD 0 */ - u8 interrupt29; /* DWORD 0 */ - u8 interrupt30; /* DWORD 0 */ - u8 interrupt31; /* DWORD 0 */ -} __packed; -struct CEV_ISR0_CSR_AMAP { - u32 dw[1]; -}; - -/* - * Host Interrupt Status Register 1. The second of four application - * interrupt status registers. This register contains the interrupts - * for Event Queues EQ32 through EQ63. - */ -struct BE_CEV_ISR1_CSR_AMAP { - u8 interrupt32; /* DWORD 0 */ - u8 interrupt33; /* DWORD 0 */ - u8 interrupt34; /* DWORD 0 */ - u8 interrupt35; /* DWORD 0 */ - u8 interrupt36; /* DWORD 0 */ - u8 interrupt37; /* DWORD 0 */ - u8 interrupt38; /* DWORD 0 */ - u8 interrupt39; /* DWORD 0 */ - u8 interrupt40; /* DWORD 0 */ - u8 interrupt41; /* DWORD 0 */ - u8 interrupt42; /* DWORD 0 */ - u8 interrupt43; /* DWORD 0 */ - u8 interrupt44; /* DWORD 0 */ - u8 interrupt45; /* DWORD 0 */ - u8 interrupt46; /* DWORD 0 */ - u8 interrupt47; /* DWORD 0 */ - u8 interrupt48; /* DWORD 0 */ - u8 interrupt49; /* DWORD 0 */ - u8 interrupt50; /* DWORD 0 */ - u8 interrupt51; /* DWORD 0 */ - u8 interrupt52; /* DWORD 0 */ - u8 interrupt53; /* DWORD 0 */ - u8 interrupt54; /* DWORD 0 */ - u8 interrupt55; /* DWORD 0 */ - u8 interrupt56; /* DWORD 0 */ - u8 interrupt57; /* DWORD 0 */ - u8 interrupt58; /* DWORD 0 */ - u8 interrupt59; /* DWORD 0 */ - u8 interrupt60; /* DWORD 0 */ - u8 interrupt61; /* DWORD 0 */ - u8 interrupt62; /* DWORD 0 */ - u8 interrupt63; /* DWORD 0 */ -} __packed; -struct CEV_ISR1_CSR_AMAP { - u32 dw[1]; -}; -/* - * Host Interrupt Status Register 2. The third of four application - * interrupt status registers. This register contains the interrupts - * for Event Queues EQ64 through EQ95. - */ -struct BE_CEV_ISR2_CSR_AMAP { - u8 interrupt64; /* DWORD 0 */ - u8 interrupt65; /* DWORD 0 */ - u8 interrupt66; /* DWORD 0 */ - u8 interrupt67; /* DWORD 0 */ - u8 interrupt68; /* DWORD 0 */ - u8 interrupt69; /* DWORD 0 */ - u8 interrupt70; /* DWORD 0 */ - u8 interrupt71; /* DWORD 0 */ - u8 interrupt72; /* DWORD 0 */ - u8 interrupt73; /* DWORD 0 */ - u8 interrupt74; /* DWORD 0 */ - u8 interrupt75; /* DWORD 0 */ - u8 interrupt76; /* DWORD 0 */ - u8 interrupt77; /* DWORD 0 */ - u8 interrupt78; /* DWORD 0 */ - u8 interrupt79; /* DWORD 0 */ - u8 interrupt80; /* DWORD 0 */ - u8 interrupt81; /* DWORD 0 */ - u8 interrupt82; /* DWORD 0 */ - u8 interrupt83; /* DWORD 0 */ - u8 interrupt84; /* DWORD 0 */ - u8 interrupt85; /* DWORD 0 */ - u8 interrupt86; /* DWORD 0 */ - u8 interrupt87; /* DWORD 0 */ - u8 interrupt88; /* DWORD 0 */ - u8 interrupt89; /* DWORD 0 */ - u8 interrupt90; /* DWORD 0 */ - u8 interrupt91; /* DWORD 0 */ - u8 interrupt92; /* DWORD 0 */ - u8 interrupt93; /* DWORD 0 */ - u8 interrupt94; /* DWORD 0 */ - u8 interrupt95; /* DWORD 0 */ -} __packed; -struct CEV_ISR2_CSR_AMAP { - u32 dw[1]; -}; - -/* - * Host Interrupt Status Register 3. The fourth of four application - * interrupt status registers. This register contains the interrupts - * for Event Queues EQ96 through EQ127. - */ -struct BE_CEV_ISR3_CSR_AMAP { - u8 interrupt96; /* DWORD 0 */ - u8 interrupt97; /* DWORD 0 */ - u8 interrupt98; /* DWORD 0 */ - u8 interrupt99; /* DWORD 0 */ - u8 interrupt100; /* DWORD 0 */ - u8 interrupt101; /* DWORD 0 */ - u8 interrupt102; /* DWORD 0 */ - u8 interrupt103; /* DWORD 0 */ - u8 interrupt104; /* DWORD 0 */ - u8 interrupt105; /* DWORD 0 */ - u8 interrupt106; /* DWORD 0 */ - u8 interrupt107; /* DWORD 0 */ - u8 interrupt108; /* DWORD 0 */ - u8 interrupt109; /* DWORD 0 */ - u8 interrupt110; /* DWORD 0 */ - u8 interrupt111; /* DWORD 0 */ - u8 interrupt112; /* DWORD 0 */ - u8 interrupt113; /* DWORD 0 */ - u8 interrupt114; /* DWORD 0 */ - u8 interrupt115; /* DWORD 0 */ - u8 interrupt116; /* DWORD 0 */ - u8 interrupt117; /* DWORD 0 */ - u8 interrupt118; /* DWORD 0 */ - u8 interrupt119; /* DWORD 0 */ - u8 interrupt120; /* DWORD 0 */ - u8 interrupt121; /* DWORD 0 */ - u8 interrupt122; /* DWORD 0 */ - u8 interrupt123; /* DWORD 0 */ - u8 interrupt124; /* DWORD 0 */ - u8 interrupt125; /* DWORD 0 */ - u8 interrupt126; /* DWORD 0 */ - u8 interrupt127; /* DWORD 0 */ -} __packed; -struct CEV_ISR3_CSR_AMAP { - u32 dw[1]; -}; - -/* Completions and Events block Registers. */ -struct BE_CEV_CSRMAP_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[32]; /* DWORD 1 */ - u8 rsvd2[32]; /* DWORD 2 */ - u8 rsvd3[32]; /* DWORD 3 */ - struct BE_CEV_ISR0_CSR_AMAP isr0; - struct BE_CEV_ISR1_CSR_AMAP isr1; - struct BE_CEV_ISR2_CSR_AMAP isr2; - struct BE_CEV_ISR3_CSR_AMAP isr3; - u8 rsvd4[32]; /* DWORD 8 */ - u8 rsvd5[32]; /* DWORD 9 */ - u8 rsvd6[32]; /* DWORD 10 */ - u8 rsvd7[32]; /* DWORD 11 */ - u8 rsvd8[32]; /* DWORD 12 */ - u8 rsvd9[32]; /* DWORD 13 */ - u8 rsvd10[32]; /* DWORD 14 */ - u8 rsvd11[32]; /* DWORD 15 */ - u8 rsvd12[32]; /* DWORD 16 */ - u8 rsvd13[32]; /* DWORD 17 */ - u8 rsvd14[32]; /* DWORD 18 */ - u8 rsvd15[32]; /* DWORD 19 */ - u8 rsvd16[32]; /* DWORD 20 */ - u8 rsvd17[32]; /* DWORD 21 */ - u8 rsvd18[32]; /* DWORD 22 */ - u8 rsvd19[32]; /* DWORD 23 */ - u8 rsvd20[32]; /* DWORD 24 */ - u8 rsvd21[32]; /* DWORD 25 */ - u8 rsvd22[32]; /* DWORD 26 */ - u8 rsvd23[32]; /* DWORD 27 */ - u8 rsvd24[32]; /* DWORD 28 */ - u8 rsvd25[32]; /* DWORD 29 */ - u8 rsvd26[32]; /* DWORD 30 */ - u8 rsvd27[32]; /* DWORD 31 */ - u8 rsvd28[32]; /* DWORD 32 */ - u8 rsvd29[32]; /* DWORD 33 */ - u8 rsvd30[192]; /* DWORD 34 */ - u8 rsvd31[192]; /* DWORD 40 */ - u8 rsvd32[160]; /* DWORD 46 */ - u8 rsvd33[160]; /* DWORD 51 */ - u8 rsvd34[160]; /* DWORD 56 */ - u8 rsvd35[96]; /* DWORD 61 */ - u8 rsvd36[192][32]; /* DWORD 64 */ -} __packed; -struct CEV_CSRMAP_AMAP { - u32 dw[256]; -}; - -#endif /* __cev_amap_h__ */ diff --git a/drivers/staging/benet/cq.c b/drivers/staging/benet/cq.c deleted file mode 100644 index 65045864543..00000000000 --- a/drivers/staging/benet/cq.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include "hwlib.h" -#include "bestatus.h" - -/* - * Completion Queue Objects - */ -/* - *============================================================================ - * P U B L I C R O U T I N E S - *============================================================================ - */ - -/* - This routine creates a completion queue based on the client completion - queue configuration information. - - - FunctionObject - Handle to a function object - CqBaseVa - Base VA for a the CQ ring - NumEntries - CEV_CQ_CNT_* values - solEventEnable - 0 = All CQEs can generate Events if CQ is eventable - 1 = only CQEs with solicited bit set are eventable - eventable - Eventable CQ, generates interrupts. - nodelay - 1 = Force interrupt, relevent if CQ eventable. - Interrupt is asserted immediately after EQE - write is confirmed, regardless of EQ Timer - or watermark settings. - wme - Enable watermark based coalescing - wmThresh - High watermark(CQ fullness at which event - or interrupt should be asserted). These are the - CEV_WATERMARK encoded values. - EqObject - EQ Handle to assign to this CQ - ppCqObject - Internal CQ Handle returned. - - Returns BE_SUCCESS if successfull, otherwise a useful error code is - returned. - - IRQL < DISPATCH_LEVEL - -*/ -int be_cq_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 length, bool solicited_eventable, - bool no_delay, u32 wm_thresh, - struct be_eq_object *eq_object, struct be_cq_object *cq_object) -{ - int status = BE_SUCCESS; - u32 num_entries_encoding; - u32 num_entries = length / sizeof(struct MCC_CQ_ENTRY_AMAP); - struct FWCMD_COMMON_CQ_CREATE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - u32 n; - unsigned long irql; - - ASSERT(rd); - ASSERT(cq_object); - ASSERT(length % sizeof(struct MCC_CQ_ENTRY_AMAP) == 0); - - switch (num_entries) { - case 256: - num_entries_encoding = CEV_CQ_CNT_256; - break; - case 512: - num_entries_encoding = CEV_CQ_CNT_512; - break; - case 1024: - num_entries_encoding = CEV_CQ_CNT_1024; - break; - default: - ASSERT(0); - return BE_STATUS_INVALID_PARAMETER; - } - - /* - * All cq entries all the same size. Use iSCSI version - * as a test for the proper rd length. - */ - memset(cq_object, 0, sizeof(*cq_object)); - - atomic_set(&cq_object->ref_count, 0); - cq_object->parent_function = pfob; - cq_object->eq_object = eq_object; - cq_object->num_entries = num_entries; - /* save for MCC cq processing */ - cq_object->va = rd->va; - - /* map into UT. */ - length = num_entries * sizeof(struct MCC_CQ_ENTRY_AMAP); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in create EQ."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_CQ_CREATE); - - fwcmd->params.request.num_pages = PAGES_SPANNED(OFFSET_IN_PAGE(rd->va), - length); - - AMAP_SET_BITS_PTR(CQ_CONTEXT, valid, &fwcmd->params.request.context, 1); - n = pfob->pci_function_number; - AMAP_SET_BITS_PTR(CQ_CONTEXT, Func, &fwcmd->params.request.context, n); - - n = (eq_object != NULL); - AMAP_SET_BITS_PTR(CQ_CONTEXT, Eventable, - &fwcmd->params.request.context, n); - AMAP_SET_BITS_PTR(CQ_CONTEXT, Armed, &fwcmd->params.request.context, 1); - - n = eq_object ? eq_object->eq_id : 0; - AMAP_SET_BITS_PTR(CQ_CONTEXT, EQID, &fwcmd->params.request.context, n); - AMAP_SET_BITS_PTR(CQ_CONTEXT, Count, - &fwcmd->params.request.context, num_entries_encoding); - - n = 0; /* Protection Domain is always 0 in Linux driver */ - AMAP_SET_BITS_PTR(CQ_CONTEXT, PD, &fwcmd->params.request.context, n); - AMAP_SET_BITS_PTR(CQ_CONTEXT, NoDelay, - &fwcmd->params.request.context, no_delay); - AMAP_SET_BITS_PTR(CQ_CONTEXT, SolEvent, - &fwcmd->params.request.context, solicited_eventable); - - n = (wm_thresh != 0xFFFFFFFF); - AMAP_SET_BITS_PTR(CQ_CONTEXT, WME, &fwcmd->params.request.context, n); - - n = (n ? wm_thresh : 0); - AMAP_SET_BITS_PTR(CQ_CONTEXT, Watermark, - &fwcmd->params.request.context, n); - /* Create a page list for the FWCMD. */ - be_rd_to_pa_list(rd, fwcmd->params.request.pages, - ARRAY_SIZE(fwcmd->params.request.pages)); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "MCC to create CQ failed."); - goto Error; - } - /* Remember the CQ id. */ - cq_object->cq_id = fwcmd->params.response.cq_id; - - /* insert this cq into eq_object reference */ - if (eq_object) { - atomic_inc(&eq_object->ref_count); - list_add_tail(&cq_object->cqlist_for_eq, - &eq_object->cq_list_head); - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - - Deferences the given object. Once the object's reference count drops to - zero, the object is destroyed and all resources that are held by this object - are released. The on-chip context is also destroyed along with the queue - ID, and any mappings made into the UT. - - cq_object - CQ handle returned from cq_object_create. - - returns the current reference count on the object - - IRQL: IRQL < DISPATCH_LEVEL -*/ -int be_cq_destroy(struct be_cq_object *cq_object) -{ - int status = 0; - - /* Nothing should reference this CQ at this point. */ - ASSERT(atomic_read(&cq_object->ref_count) == 0); - - /* Send fwcmd to destroy the CQ. */ - status = be_function_ring_destroy(cq_object->parent_function, - cq_object->cq_id, FWCMD_RING_TYPE_CQ, - NULL, NULL, NULL, NULL); - ASSERT(status == 0); - - /* Remove reference if this is an eventable CQ. */ - if (cq_object->eq_object) { - atomic_dec(&cq_object->eq_object->ref_count); - list_del(&cq_object->cqlist_for_eq); - } - return BE_SUCCESS; -} - diff --git a/drivers/staging/benet/descriptors.h b/drivers/staging/benet/descriptors.h deleted file mode 100644 index 8da438c407d..00000000000 --- a/drivers/staging/benet/descriptors.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __descriptors_amap_h__ -#define __descriptors_amap_h__ - -/* - * --- IPC_NODE_ID_ENUM --- - * IPC processor id values - */ -#define TPOST_NODE_ID (0) /* TPOST ID */ -#define TPRE_NODE_ID (1) /* TPRE ID */ -#define TXULP0_NODE_ID (2) /* TXULP0 ID */ -#define TXULP1_NODE_ID (3) /* TXULP1 ID */ -#define TXULP2_NODE_ID (4) /* TXULP2 ID */ -#define RXULP0_NODE_ID (5) /* RXULP0 ID */ -#define RXULP1_NODE_ID (6) /* RXULP1 ID */ -#define RXULP2_NODE_ID (7) /* RXULP2 ID */ -#define MPU_NODE_ID (15) /* MPU ID */ - -/* - * --- MAC_ID_ENUM --- - * Meaning of the mac_id field in rxpp_eth_d - */ -#define PORT0_HOST_MAC0 (0) /* PD 0, Port 0, host networking, MAC 0. */ -#define PORT0_HOST_MAC1 (1) /* PD 0, Port 0, host networking, MAC 1. */ -#define PORT0_STORAGE_MAC0 (2) /* PD 0, Port 0, host storage, MAC 0. */ -#define PORT0_STORAGE_MAC1 (3) /* PD 0, Port 0, host storage, MAC 1. */ -#define PORT1_HOST_MAC0 (4) /* PD 0, Port 1 host networking, MAC 0. */ -#define PORT1_HOST_MAC1 (5) /* PD 0, Port 1 host networking, MAC 1. */ -#define PORT1_STORAGE_MAC0 (6) /* PD 0, Port 1 host storage, MAC 0. */ -#define PORT1_STORAGE_MAC1 (7) /* PD 0, Port 1 host storage, MAC 1. */ -#define FIRST_VM_MAC (8) /* PD 1 MAC. Protection domains have IDs */ - /* from 0x8-0x26, one per PD. */ -#define LAST_VM_MAC (38) /* PD 31 MAC. */ -#define MGMT_MAC (39) /* Management port MAC. */ -#define MARBLE_MAC0 (59) /* Used for flushing function 0 receive */ - /* - * queues before re-using a torn-down - * receive ring. the DA = - * 00-00-00-00-00-00, and the MSB of the - * SA = 00 - */ -#define MARBLE_MAC1 (60) /* Used for flushing function 1 receive */ - /* - * queues before re-using a torn-down - * receive ring. the DA = - * 00-00-00-00-00-00, and the MSB of the - * SA != 00 - */ -#define NULL_MAC (61) /* Promiscuous mode, indicates no match */ -#define MCAST_MAC (62) /* Multicast match. */ -#define BCAST_MATCH (63) /* Broadcast match. */ - -#endif /* __descriptors_amap_h__ */ diff --git a/drivers/staging/benet/doorbells.h b/drivers/staging/benet/doorbells.h deleted file mode 100644 index 550cc4d5d6f..00000000000 --- a/drivers/staging/benet/doorbells.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __doorbells_amap_h__ -#define __doorbells_amap_h__ - -/* The TX/RDMA send queue doorbell. */ -struct BE_SQ_DB_AMAP { - u8 cid[11]; /* DWORD 0 */ - u8 rsvd0[5]; /* DWORD 0 */ - u8 numPosted[14]; /* DWORD 0 */ - u8 rsvd1[2]; /* DWORD 0 */ -} __packed; -struct SQ_DB_AMAP { - u32 dw[1]; -}; - -/* The receive queue doorbell. */ -struct BE_RQ_DB_AMAP { - u8 rq[10]; /* DWORD 0 */ - u8 rsvd0[13]; /* DWORD 0 */ - u8 Invalidate; /* DWORD 0 */ - u8 numPosted[8]; /* DWORD 0 */ -} __packed; -struct RQ_DB_AMAP { - u32 dw[1]; -}; - -/* - * The CQ/EQ doorbell. Software MUST set reserved fields in this - * descriptor to zero, otherwise (CEV) hardware will not execute the - * doorbell (flagging a bad_db_qid error instead). - */ -struct BE_CQ_DB_AMAP { - u8 qid[10]; /* DWORD 0 */ - u8 rsvd0[4]; /* DWORD 0 */ - u8 rearm; /* DWORD 0 */ - u8 event; /* DWORD 0 */ - u8 num_popped[13]; /* DWORD 0 */ - u8 rsvd1[3]; /* DWORD 0 */ -} __packed; -struct CQ_DB_AMAP { - u32 dw[1]; -}; - -struct BE_TPM_RQ_DB_AMAP { - u8 qid[10]; /* DWORD 0 */ - u8 rsvd0[6]; /* DWORD 0 */ - u8 numPosted[11]; /* DWORD 0 */ - u8 mss_cnt[5]; /* DWORD 0 */ -} __packed; -struct TPM_RQ_DB_AMAP { - u32 dw[1]; -}; - -/* - * Post WRB Queue Doorbell Register used by the host Storage stack - * to notify the controller of a posted Work Request Block - */ -struct BE_WRB_POST_DB_AMAP { - u8 wrb_cid[10]; /* DWORD 0 */ - u8 rsvd0[6]; /* DWORD 0 */ - u8 wrb_index[8]; /* DWORD 0 */ - u8 numberPosted[8]; /* DWORD 0 */ -} __packed; -struct WRB_POST_DB_AMAP { - u32 dw[1]; -}; - -/* - * Update Default PDU Queue Doorbell Register used to communicate - * to the controller that the driver has stopped processing the queue - * and where in the queue it stopped, this is - * a CQ Entry Type. Used by storage driver. - */ -struct BE_DEFAULT_PDU_DB_AMAP { - u8 qid[10]; /* DWORD 0 */ - u8 rsvd0[4]; /* DWORD 0 */ - u8 rearm; /* DWORD 0 */ - u8 event; /* DWORD 0 */ - u8 cqproc[14]; /* DWORD 0 */ - u8 rsvd1[2]; /* DWORD 0 */ -} __packed; -struct DEFAULT_PDU_DB_AMAP { - u32 dw[1]; -}; - -/* Management Command and Controller default fragment ring */ -struct BE_MCC_DB_AMAP { - u8 rid[11]; /* DWORD 0 */ - u8 rsvd0[5]; /* DWORD 0 */ - u8 numPosted[14]; /* DWORD 0 */ - u8 rsvd1[2]; /* DWORD 0 */ -} __packed; -struct MCC_DB_AMAP { - u32 dw[1]; -}; - -/* - * Used for bootstrapping the Host interface. This register is - * used for driver communication with the MPU when no MCC Rings exist. - * The software must write this register twice to post any MCC - * command. First, it writes the register with hi=1 and the upper bits of - * the physical address for the MCC_MAILBOX structure. Software must poll - * the ready bit until this is acknowledged. Then, sotware writes the - * register with hi=0 with the lower bits in the address. It must - * poll the ready bit until the MCC command is complete. Upon completion, - * the MCC_MAILBOX will contain a valid completion queue entry. - */ -struct BE_MPU_MAILBOX_DB_AMAP { - u8 ready; /* DWORD 0 */ - u8 hi; /* DWORD 0 */ - u8 address[30]; /* DWORD 0 */ -} __packed; -struct MPU_MAILBOX_DB_AMAP { - u32 dw[1]; -}; - -/* - * This is the protection domain doorbell register map. Note that - * while this map shows doorbells for all Blade Engine supported - * protocols, not all of these may be valid in a given function or - * protection domain. It is the responsibility of the application - * accessing the doorbells to know which are valid. Each doorbell - * occupies 32 bytes of space, but unless otherwise specified, - * only the first 4 bytes should be written. There are 32 instances - * of these doorbells for the host and 31 virtual machines respectively. - * The host and VMs will only map the doorbell pages belonging to its - * protection domain. It will not be able to touch the doorbells for - * another VM. The doorbells are the only registers directly accessible - * by a virtual machine. Similarly, there are 511 additional - * doorbells for RDMA protection domains. PD 0 for RDMA shares - * the same physical protection domain doorbell page as ETH/iSCSI. - * - */ -struct BE_PROTECTION_DOMAIN_DBMAP_AMAP { - u8 rsvd0[512]; /* DWORD 0 */ - struct BE_SQ_DB_AMAP rdma_sq_db; - u8 rsvd1[7][32]; /* DWORD 17 */ - struct BE_WRB_POST_DB_AMAP iscsi_wrb_post_db; - u8 rsvd2[7][32]; /* DWORD 25 */ - struct BE_SQ_DB_AMAP etx_sq_db; - u8 rsvd3[7][32]; /* DWORD 33 */ - struct BE_RQ_DB_AMAP rdma_rq_db; - u8 rsvd4[7][32]; /* DWORD 41 */ - struct BE_DEFAULT_PDU_DB_AMAP iscsi_default_pdu_db; - u8 rsvd5[7][32]; /* DWORD 49 */ - struct BE_TPM_RQ_DB_AMAP tpm_rq_db; - u8 rsvd6[7][32]; /* DWORD 57 */ - struct BE_RQ_DB_AMAP erx_rq_db; - u8 rsvd7[7][32]; /* DWORD 65 */ - struct BE_CQ_DB_AMAP cq_db; - u8 rsvd8[7][32]; /* DWORD 73 */ - struct BE_MCC_DB_AMAP mpu_mcc_db; - u8 rsvd9[7][32]; /* DWORD 81 */ - struct BE_MPU_MAILBOX_DB_AMAP mcc_bootstrap_db; - u8 rsvd10[935][32]; /* DWORD 89 */ -} __packed; -struct PROTECTION_DOMAIN_DBMAP_AMAP { - u32 dw[1024]; -}; - -#endif /* __doorbells_amap_h__ */ diff --git a/drivers/staging/benet/ep.h b/drivers/staging/benet/ep.h deleted file mode 100644 index 72fcf64a9ff..00000000000 --- a/drivers/staging/benet/ep.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __ep_amap_h__ -#define __ep_amap_h__ - -/* General Control and Status Register. */ -struct BE_EP_CONTROL_CSR_AMAP { - u8 m0_RxPbuf; /* DWORD 0 */ - u8 m1_RxPbuf; /* DWORD 0 */ - u8 m2_RxPbuf; /* DWORD 0 */ - u8 ff_en; /* DWORD 0 */ - u8 rsvd0[27]; /* DWORD 0 */ - u8 CPU_reset; /* DWORD 0 */ -} __packed; -struct EP_CONTROL_CSR_AMAP { - u32 dw[1]; -}; - -/* Semaphore Register. */ -struct BE_EP_SEMAPHORE_CSR_AMAP { - u8 value[32]; /* DWORD 0 */ -} __packed; -struct EP_SEMAPHORE_CSR_AMAP { - u32 dw[1]; -}; - -/* Embedded Processor Specific Registers. */ -struct BE_EP_CSRMAP_AMAP { - struct BE_EP_CONTROL_CSR_AMAP ep_control; - u8 rsvd0[32]; /* DWORD 1 */ - u8 rsvd1[32]; /* DWORD 2 */ - u8 rsvd2[32]; /* DWORD 3 */ - u8 rsvd3[32]; /* DWORD 4 */ - u8 rsvd4[32]; /* DWORD 5 */ - u8 rsvd5[8][128]; /* DWORD 6 */ - u8 rsvd6[32]; /* DWORD 38 */ - u8 rsvd7[32]; /* DWORD 39 */ - u8 rsvd8[32]; /* DWORD 40 */ - u8 rsvd9[32]; /* DWORD 41 */ - u8 rsvd10[32]; /* DWORD 42 */ - struct BE_EP_SEMAPHORE_CSR_AMAP ep_semaphore; - u8 rsvd11[32]; /* DWORD 44 */ - u8 rsvd12[19][32]; /* DWORD 45 */ -} __packed; -struct EP_CSRMAP_AMAP { - u32 dw[64]; -}; - -#endif /* __ep_amap_h__ */ diff --git a/drivers/staging/benet/eq.c b/drivers/staging/benet/eq.c deleted file mode 100644 index db92ccd8fed..00000000000 --- a/drivers/staging/benet/eq.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include "hwlib.h" -#include "bestatus.h" -/* - This routine creates an event queue based on the client completion - queue configuration information. - - FunctionObject - Handle to a function object - EqBaseVa - Base VA for a the EQ ring - SizeEncoding - The encoded size for the EQ entries. This value is - either CEV_EQ_SIZE_4 or CEV_EQ_SIZE_16 - NumEntries - CEV_CQ_CNT_* values. - Watermark - Enables watermark based coalescing. This parameter - must be of the type CEV_WMARK_* if watermarks - are enabled. If watermarks to to be disabled - this value should be-1. - TimerDelay - If a timer delay is enabled this value should be the - time of the delay in 8 microsecond units. If - delays are not used this parameter should be - set to -1. - ppEqObject - Internal EQ Handle returned. - - Returns BE_SUCCESS if successfull,, otherwise a useful error code - is returned. - - IRQL < DISPATCH_LEVEL -*/ -int -be_eq_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 eqe_size, u32 num_entries, - u32 watermark, /* CEV_WMARK_* or -1 */ - u32 timer_delay, /* in 8us units, or -1 */ - struct be_eq_object *eq_object) -{ - int status = BE_SUCCESS; - u32 num_entries_encoding, eqe_size_encoding, length; - struct FWCMD_COMMON_EQ_CREATE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - u32 n; - unsigned long irql; - - ASSERT(rd); - ASSERT(eq_object); - - switch (num_entries) { - case 256: - num_entries_encoding = CEV_EQ_CNT_256; - break; - case 512: - num_entries_encoding = CEV_EQ_CNT_512; - break; - case 1024: - num_entries_encoding = CEV_EQ_CNT_1024; - break; - case 2048: - num_entries_encoding = CEV_EQ_CNT_2048; - break; - case 4096: - num_entries_encoding = CEV_EQ_CNT_4096; - break; - default: - ASSERT(0); - return BE_STATUS_INVALID_PARAMETER; - } - - switch (eqe_size) { - case 4: - eqe_size_encoding = CEV_EQ_SIZE_4; - break; - case 16: - eqe_size_encoding = CEV_EQ_SIZE_16; - break; - default: - ASSERT(0); - return BE_STATUS_INVALID_PARAMETER; - } - - if ((eqe_size == 4 && num_entries < 1024) || - (eqe_size == 16 && num_entries == 4096)) { - TRACE(DL_ERR, "Bad EQ size. eqe_size:%d num_entries:%d", - eqe_size, num_entries); - ASSERT(0); - return BE_STATUS_INVALID_PARAMETER; - } - - memset(eq_object, 0, sizeof(*eq_object)); - - atomic_set(&eq_object->ref_count, 0); - eq_object->parent_function = pfob; - eq_object->eq_id = 0xFFFFFFFF; - - INIT_LIST_HEAD(&eq_object->cq_list_head); - - length = num_entries * eqe_size; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in create EQ."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_EQ_CREATE); - - fwcmd->params.request.num_pages = PAGES_SPANNED(OFFSET_IN_PAGE(rd->va), - length); - n = pfob->pci_function_number; - AMAP_SET_BITS_PTR(EQ_CONTEXT, Func, &fwcmd->params.request.context, n); - - AMAP_SET_BITS_PTR(EQ_CONTEXT, valid, &fwcmd->params.request.context, 1); - - AMAP_SET_BITS_PTR(EQ_CONTEXT, Size, - &fwcmd->params.request.context, eqe_size_encoding); - - n = 0; /* Protection Domain is always 0 in Linux driver */ - AMAP_SET_BITS_PTR(EQ_CONTEXT, PD, &fwcmd->params.request.context, n); - - /* Let the caller ARM the EQ with the doorbell. */ - AMAP_SET_BITS_PTR(EQ_CONTEXT, Armed, &fwcmd->params.request.context, 0); - - AMAP_SET_BITS_PTR(EQ_CONTEXT, Count, &fwcmd->params.request.context, - num_entries_encoding); - - n = pfob->pci_function_number * 32; - AMAP_SET_BITS_PTR(EQ_CONTEXT, EventVect, - &fwcmd->params.request.context, n); - if (watermark != -1) { - AMAP_SET_BITS_PTR(EQ_CONTEXT, WME, - &fwcmd->params.request.context, 1); - AMAP_SET_BITS_PTR(EQ_CONTEXT, Watermark, - &fwcmd->params.request.context, watermark); - ASSERT(watermark <= CEV_WMARK_240); - } else - AMAP_SET_BITS_PTR(EQ_CONTEXT, WME, - &fwcmd->params.request.context, 0); - if (timer_delay != -1) { - AMAP_SET_BITS_PTR(EQ_CONTEXT, TMR, - &fwcmd->params.request.context, 1); - - ASSERT(timer_delay <= 250); /* max value according to EAS */ - timer_delay = min(timer_delay, (u32)250); - - AMAP_SET_BITS_PTR(EQ_CONTEXT, Delay, - &fwcmd->params.request.context, timer_delay); - } else { - AMAP_SET_BITS_PTR(EQ_CONTEXT, TMR, - &fwcmd->params.request.context, 0); - } - /* Create a page list for the FWCMD. */ - be_rd_to_pa_list(rd, fwcmd->params.request.pages, - ARRAY_SIZE(fwcmd->params.request.pages)); - - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "MCC to create EQ failed."); - goto Error; - } - /* Get the EQ id. The MPU allocates the IDs. */ - eq_object->eq_id = fwcmd->params.response.eq_id; - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - Deferences the given object. Once the object's reference count drops to - zero, the object is destroyed and all resources that are held by this - object are released. The on-chip context is also destroyed along with - the queue ID, and any mappings made into the UT. - - eq_object - EQ handle returned from eq_object_create. - - Returns BE_SUCCESS if successfull, otherwise a useful error code - is returned. - - IRQL: IRQL < DISPATCH_LEVEL -*/ -int be_eq_destroy(struct be_eq_object *eq_object) -{ - int status = 0; - - ASSERT(atomic_read(&eq_object->ref_count) == 0); - /* no CQs should reference this EQ now */ - ASSERT(list_empty(&eq_object->cq_list_head)); - - /* Send fwcmd to destroy the EQ. */ - status = be_function_ring_destroy(eq_object->parent_function, - eq_object->eq_id, FWCMD_RING_TYPE_EQ, - NULL, NULL, NULL, NULL); - ASSERT(status == 0); - - return BE_SUCCESS; -} -/* - *--------------------------------------------------------------------------- - * Function: be_eq_modify_delay - * Changes the EQ delay for a group of EQs. - * num_eq - The number of EQs in the eq_array to adjust. - * This also is the number of delay values in - * the eq_delay_array. - * eq_array - Array of struct be_eq_object pointers to adjust. - * eq_delay_array - Array of "num_eq" timer delays in units - * of microseconds. The be_eq_query_delay_range - * fwcmd returns the resolution and range of - * legal EQ delays. - * cb - - * cb_context - - * q_ctxt - Optional. Pointer to a previously allocated - * struct. If the MCC WRB ring is full, this - * structure is used to queue the operation. It - * will be posted to the MCC ring when space - * becomes available. All queued commands will - * be posted to the ring in the order they are - * received. It is always valid to pass a pointer to - * a generic be_generic_q_cntxt. However, - * the specific context structs - * are generally smaller than the generic struct. - * return pend_status - BE_SUCCESS (0) on success. - * BE_PENDING (postive value) if the FWCMD - * completion is pending. Negative error code on failure. - *------------------------------------------------------------------------- - */ -int -be_eq_modify_delay(struct be_function_object *pfob, - u32 num_eq, struct be_eq_object **eq_array, - u32 *eq_delay_array, mcc_wrb_cqe_callback cb, - void *cb_context, struct be_eq_modify_delay_q_ctxt *q_ctxt) -{ - struct FWCMD_COMMON_MODIFY_EQ_DELAY *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - struct be_generic_q_ctxt *gen_ctxt = NULL; - u32 i; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - gen_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - gen_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_MODIFY_EQ_DELAY); - - ASSERT(num_eq > 0); - ASSERT(num_eq <= ARRAY_SIZE(fwcmd->params.request.delay)); - fwcmd->params.request.num_eq = num_eq; - for (i = 0; i < num_eq; i++) { - fwcmd->params.request.delay[i].eq_id = eq_array[i]->eq_id; - fwcmd->params.request.delay[i].delay_in_microseconds = - eq_delay_array[i]; - } - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, gen_ctxt, - cb, cb_context, NULL, NULL, fwcmd, NULL); - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - diff --git a/drivers/staging/benet/eth.c b/drivers/staging/benet/eth.c deleted file mode 100644 index f641b6260d0..00000000000 --- a/drivers/staging/benet/eth.c +++ /dev/null @@ -1,1273 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include -#include "hwlib.h" -#include "bestatus.h" - -/* - *--------------------------------------------------------- - * Function: be_eth_sq_create_ex - * Creates an ethernet send ring - extended version with - * additional parameters. - * pfob - - * rd - ring address - * length_in_bytes - - * type - The type of ring to create. - * ulp - The requested ULP number for the ring. - * This should be zero based, i.e. 0,1,2. This must - * be valid NIC ULP based on the firmware config. - * All doorbells for this ring must be sent to - * this ULP. The first network ring allocated for - * each ULP are higher performance than subsequent rings. - * cq_object - cq object for completions - * ex_parameters - Additional parameters (that may increase in - * future revisions). These parameters are only used - * for certain ring types -- see - * struct be_eth_sq_parameters for details. - * eth_sq - - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *--------------------------------------------------------- - */ -int -be_eth_sq_create_ex(struct be_function_object *pfob, struct ring_desc *rd, - u32 length, u32 type, u32 ulp, struct be_cq_object *cq_object, - struct be_eth_sq_parameters *ex_parameters, - struct be_ethsq_object *eth_sq) -{ - struct FWCMD_COMMON_ETH_TX_CREATE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - u32 n; - unsigned long irql; - - ASSERT(rd); - ASSERT(eth_sq); - ASSERT(ex_parameters); - - spin_lock_irqsave(&pfob->post_lock, irql); - - memset(eth_sq, 0, sizeof(*eth_sq)); - - eth_sq->parent_function = pfob; - eth_sq->bid = 0xFFFFFFFF; - eth_sq->cq_object = cq_object; - - /* Translate hwlib interface to arm interface. */ - switch (type) { - case BE_ETH_TX_RING_TYPE_FORWARDING: - type = ETH_TX_RING_TYPE_FORWARDING; - break; - case BE_ETH_TX_RING_TYPE_STANDARD: - type = ETH_TX_RING_TYPE_STANDARD; - break; - case BE_ETH_TX_RING_TYPE_BOUND: - ASSERT(ex_parameters->port < 2); - type = ETH_TX_RING_TYPE_BOUND; - break; - default: - TRACE(DL_ERR, "Invalid eth tx ring type:%d", type); - return BE_NOT_OK; - break; - } - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in create EQ."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* NIC must be supported by the current config. */ - ASSERT(pfob->fw_config.nic_ulp_mask); - - /* - * The ulp parameter must select a valid NIC ULP - * for the current config. - */ - ASSERT((1 << ulp) & pfob->fw_config.nic_ulp_mask); - - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_ETH_TX_CREATE); - fwcmd->header.request.port_number = ex_parameters->port; - - AMAP_SET_BITS_PTR(ETX_CONTEXT, pd_id, - &fwcmd->params.request.context, 0); - - n = be_ring_length_to_encoding(length, sizeof(struct ETH_WRB_AMAP)); - AMAP_SET_BITS_PTR(ETX_CONTEXT, tx_ring_size, - &fwcmd->params.request.context, n); - - AMAP_SET_BITS_PTR(ETX_CONTEXT, cq_id_send, - &fwcmd->params.request.context, cq_object->cq_id); - - n = pfob->pci_function_number; - AMAP_SET_BITS_PTR(ETX_CONTEXT, func, &fwcmd->params.request.context, n); - - fwcmd->params.request.type = type; - fwcmd->params.request.ulp_num = (1 << ulp); - fwcmd->params.request.num_pages = DIV_ROUND_UP(length, PAGE_SIZE); - ASSERT(PAGES_SPANNED(rd->va, rd->length) >= - fwcmd->params.request.num_pages); - - /* Create a page list for the FWCMD. */ - be_rd_to_pa_list(rd, fwcmd->params.request.pages, - ARRAY_SIZE(fwcmd->params.request.pages)); - - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "MCC to create etx queue failed."); - goto Error; - } - /* save the butler ID */ - eth_sq->bid = fwcmd->params.response.cid; - - /* add a reference to the corresponding CQ */ - atomic_inc(&cq_object->ref_count); - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - - -/* - This routine destroys an ethernet send queue - - EthSq - EthSq Handle returned from EthSqCreate - - This function always return BE_SUCCESS. - - This function frees memory allocated by EthSqCreate for the EthSq Object. - -*/ -int be_eth_sq_destroy(struct be_ethsq_object *eth_sq) -{ - int status = 0; - - /* Send fwcmd to destroy the queue. */ - status = be_function_ring_destroy(eth_sq->parent_function, eth_sq->bid, - FWCMD_RING_TYPE_ETH_TX, NULL, NULL, NULL, NULL); - ASSERT(status == 0); - - /* Derefence any associated CQs. */ - atomic_dec(ð_sq->cq_object->ref_count); - return status; -} -/* - This routine attempts to set the transmit flow control parameters. - - FunctionObject - Handle to a function object - - txfc_enable - transmit flow control enable - true for - enable, false for disable - - rxfc_enable - receive flow control enable - true for - enable, false for disable - - Returns BE_SUCCESS if successfull, otherwise a useful int error - code is returned. - - IRQL: < DISPATCH_LEVEL - - This function always fails in non-privileged machine context. -*/ -int -be_eth_set_flow_control(struct be_function_object *pfob, - bool txfc_enable, bool rxfc_enable) -{ - struct FWCMD_COMMON_SET_FLOW_CONTROL *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_SET_FLOW_CONTROL); - - fwcmd->params.request.rx_flow_control = rxfc_enable; - fwcmd->params.request.tx_flow_control = txfc_enable; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "set flow control fwcmd failed."); - goto error; - } - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine attempts to get the transmit flow control parameters. - - pfob - Handle to a function object - - txfc_enable - transmit flow control enable - true for - enable, false for disable - - rxfc_enable - receive flow control enable - true for enable, - false for disable - - Returns BE_SUCCESS if successfull, otherwise a useful int error code - is returned. - - IRQL: < DISPATCH_LEVEL - - This function always fails in non-privileged machine context. -*/ -int -be_eth_get_flow_control(struct be_function_object *pfob, - bool *txfc_enable, bool *rxfc_enable) -{ - struct FWCMD_COMMON_GET_FLOW_CONTROL *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_GET_FLOW_CONTROL); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "get flow control fwcmd failed."); - goto error; - } - - *txfc_enable = fwcmd->params.response.tx_flow_control; - *rxfc_enable = fwcmd->params.response.rx_flow_control; - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - *--------------------------------------------------------- - * Function: be_eth_set_qos - * This function sets the ethernet transmit Quality of Service (QoS) - * characteristics of BladeEngine for the domain. All ethernet - * transmit rings of the domain will evenly share the bandwidth. - * The exeception to sharing is the host primary (super) ethernet - * transmit ring as well as the host ethernet forwarding ring - * for missed offload data. - * pfob - - * max_bps - the maximum bits per second in units of - * 10 Mbps (valid 0-100) - * max_pps - the maximum packets per second in units - * of 1 Kpps (0 indicates no limit) - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *--------------------------------------------------------- - */ -int -be_eth_set_qos(struct be_function_object *pfob, u32 max_bps, u32 max_pps) -{ - struct FWCMD_COMMON_SET_QOS *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_SET_QOS); - - /* Set fields in fwcmd */ - fwcmd->params.request.max_bits_per_second_NIC = max_bps; - fwcmd->params.request.max_packets_per_second_NIC = max_pps; - fwcmd->params.request.valid_flags = QOS_BITS_NIC | QOS_PKTS_NIC; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) - TRACE(DL_ERR, "network set qos fwcmd failed."); - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - *--------------------------------------------------------- - * Function: be_eth_get_qos - * This function retrieves the ethernet transmit Quality of Service (QoS) - * characteristics for the domain. - * max_bps - the maximum bits per second in units of - * 10 Mbps (valid 0-100) - * max_pps - the maximum packets per second in units of - * 1 Kpps (0 indicates no limit) - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *--------------------------------------------------------- - */ -int -be_eth_get_qos(struct be_function_object *pfob, u32 *max_bps, u32 *max_pps) -{ - struct FWCMD_COMMON_GET_QOS *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_GET_QOS); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "network get qos fwcmd failed."); - goto error; - } - - *max_bps = fwcmd->params.response.max_bits_per_second_NIC; - *max_pps = fwcmd->params.response.max_packets_per_second_NIC; - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - *--------------------------------------------------------- - * Function: be_eth_set_frame_size - * This function sets the ethernet maximum frame size. The previous - * values are returned. - * pfob - - * tx_frame_size - maximum transmit frame size in bytes - * rx_frame_size - maximum receive frame size in bytes - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *--------------------------------------------------------- - */ -int -be_eth_set_frame_size(struct be_function_object *pfob, - u32 *tx_frame_size, u32 *rx_frame_size) -{ - struct FWCMD_COMMON_SET_FRAME_SIZE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_SET_FRAME_SIZE); - fwcmd->params.request.max_tx_frame_size = *tx_frame_size; - fwcmd->params.request.max_rx_frame_size = *rx_frame_size; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "network set frame size fwcmd failed."); - goto error; - } - - *tx_frame_size = fwcmd->params.response.chip_max_tx_frame_size; - *rx_frame_size = fwcmd->params.response.chip_max_rx_frame_size; - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - - -/* - This routine creates a Ethernet receive ring. - - pfob - handle to a function object - rq_base_va - base VA for the default receive ring. this must be - exactly 8K in length and continguous physical memory. - cq_object - handle to a previously created CQ to be associated - with the RQ. - pp_eth_rq - pointer to an opqaue handle where an eth - receive object is returned. - Returns BE_SUCCESS if successfull, , otherwise a useful - int error code is returned. - - IRQL: < DISPATCH_LEVEL - this function allocates a struct be_ethrq_object *object. - there must be no more than 1 of these per function object, unless the - function object supports RSS (is networking and on the host). - the rq_base_va must point to a buffer of exactly 8K. - the erx::host_cqid (or host_stor_cqid) register and erx::ring_page registers - will be updated as appropriate on return -*/ -int -be_eth_rq_create(struct be_function_object *pfob, - struct ring_desc *rd, struct be_cq_object *cq_object, - struct be_cq_object *bcmc_cq_object, - struct be_ethrq_object *eth_rq) -{ - int status = 0; - struct MCC_WRB_AMAP *wrb = NULL; - struct FWCMD_COMMON_ETH_RX_CREATE *fwcmd = NULL; - unsigned long irql; - - /* MPU will set the */ - ASSERT(rd); - ASSERT(eth_rq); - - spin_lock_irqsave(&pfob->post_lock, irql); - - eth_rq->parent_function = pfob; - eth_rq->cq_object = cq_object; - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_ETH_RX_CREATE); - - fwcmd->params.request.num_pages = 2; /* required length */ - fwcmd->params.request.cq_id = cq_object->cq_id; - - if (bcmc_cq_object) - fwcmd->params.request.bcmc_cq_id = bcmc_cq_object->cq_id; - else - fwcmd->params.request.bcmc_cq_id = 0xFFFF; - - /* Create a page list for the FWCMD. */ - be_rd_to_pa_list(rd, fwcmd->params.request.pages, - ARRAY_SIZE(fwcmd->params.request.pages)); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "fwcmd to map eth rxq frags failed."); - goto Error; - } - /* Save the ring ID for cleanup. */ - eth_rq->rid = fwcmd->params.response.id; - - atomic_inc(&cq_object->ref_count); - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine destroys an Ethernet receive queue - - eth_rq - ethernet receive queue handle returned from eth_rq_create - - Returns BE_SUCCESS on success and an appropriate int on failure. - - This function frees resourcs allocated by EthRqCreate. - The erx::host_cqid (or host_stor_cqid) register and erx::ring_page - registers will be updated as appropriate on return - IRQL: < DISPATCH_LEVEL -*/ - -static void be_eth_rq_destroy_internal_cb(void *context, int status, - struct MCC_WRB_AMAP *wrb) -{ - struct be_ethrq_object *eth_rq = (struct be_ethrq_object *) context; - - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "Destroy eth rq failed in internal callback.\n"); - } else { - /* Dereference any CQs associated with this queue. */ - atomic_dec(ð_rq->cq_object->ref_count); - } - - return; -} - -int be_eth_rq_destroy(struct be_ethrq_object *eth_rq) -{ - int status = BE_SUCCESS; - - /* Send fwcmd to destroy the RQ. */ - status = be_function_ring_destroy(eth_rq->parent_function, - eth_rq->rid, FWCMD_RING_TYPE_ETH_RX, NULL, NULL, - be_eth_rq_destroy_internal_cb, eth_rq); - - return status; -} - -/* - *--------------------------------------------------------------------------- - * Function: be_eth_rq_destroy_options - * Destroys an ethernet receive ring with finer granularity options - * than the standard be_eth_rq_destroy() API function. - * eth_rq - - * flush - Set to 1 to flush the ring, set to 0 to bypass the flush - * cb - Callback function on completion - * cb_context - Callback context - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *---------------------------------------------------------------------------- - */ -int -be_eth_rq_destroy_options(struct be_ethrq_object *eth_rq, bool flush, - mcc_wrb_cqe_callback cb, void *cb_context) -{ - struct FWCMD_COMMON_RING_DESTROY *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = BE_SUCCESS; - struct be_function_object *pfob = NULL; - unsigned long irql; - - pfob = eth_rq->parent_function; - - spin_lock_irqsave(&pfob->post_lock, irql); - - TRACE(DL_INFO, "Destroy eth_rq ring id:%d, flush:%d", eth_rq->rid, - flush); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in destroy eth_rq ring."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_RING_DESTROY); - - fwcmd->params.request.id = eth_rq->rid; - fwcmd->params.request.ring_type = FWCMD_RING_TYPE_ETH_RX; - fwcmd->params.request.bypass_flush = ((0 == flush) ? 1 : 0); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb, cb_context, - be_eth_rq_destroy_internal_cb, eth_rq, fwcmd, NULL); - - if (status != BE_SUCCESS && status != BE_PENDING) { - TRACE(DL_ERR, "eth_rq ring destroy failed. id:%d, flush:%d", - eth_rq->rid, flush); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine queries the frag size for erx. - - pfob - handle to a function object - - frag_size_bytes - erx frag size in bytes that is/was set. - - Returns BE_SUCCESS if successfull, otherwise a useful int error - code is returned. - - IRQL: < DISPATCH_LEVEL - -*/ -int -be_eth_rq_get_frag_size(struct be_function_object *pfob, u32 *frag_size_bytes) -{ - struct FWCMD_ETH_GET_RX_FRAG_SIZE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - ASSERT(frag_size_bytes); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - return BE_STATUS_NO_MCC_WRB; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, ETH_GET_RX_FRAG_SIZE); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "get frag size fwcmd failed."); - goto error; - } - - *frag_size_bytes = 1 << fwcmd->params.response.actual_fragsize_log2; - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine attempts to set the frag size for erx. If the frag size is - already set, the attempt fails and the current frag size is returned. - - pfob - Handle to a function object - - frag_size - Erx frag size in bytes that is/was set. - - current_frag_size_bytes - Pointer to location where currrent frag - is to be rturned - - Returns BE_SUCCESS if successfull, otherwise a useful int error - code is returned. - - IRQL: < DISPATCH_LEVEL - - This function always fails in non-privileged machine context. -*/ -int -be_eth_rq_set_frag_size(struct be_function_object *pfob, - u32 frag_size, u32 *frag_size_bytes) -{ - struct FWCMD_ETH_SET_RX_FRAG_SIZE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - ASSERT(frag_size_bytes); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, ETH_SET_RX_FRAG_SIZE); - - ASSERT(frag_size >= 128 && frag_size <= 16 * 1024); - - /* This is the log2 of the fragsize. This is not the exact - * ERX encoding. */ - fwcmd->params.request.new_fragsize_log2 = __ilog2_u32(frag_size); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "set frag size fwcmd failed."); - goto error; - } - - *frag_size_bytes = 1 << fwcmd->params.response.actual_fragsize_log2; -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - - -/* - This routine gets or sets a mac address for a domain - given the port and mac. - - FunctionObject - Function object handle. - port1 - Set to TRUE if this function will set/get the Port 1 - address. Only the host may set this to TRUE. - mac1 - Set to TRUE if this function will set/get the - MAC 1 address. Only the host may set this to TRUE. - write - Set to TRUE if this function should write the mac address. - mac_address - Buffer of the mac address to read or write. - - Returns BE_SUCCESS if successfull, otherwise a useful int is returned. - - IRQL: < DISPATCH_LEVEL -*/ -int be_rxf_mac_address_read_write(struct be_function_object *pfob, - bool port1, /* VM must always set to false */ - bool mac1, /* VM must always set to false */ - bool mgmt, bool write, - bool permanent, u8 *mac_address, - mcc_wrb_cqe_callback cb, /* optional */ - void *cb_context) /* optional */ -{ - int status = BE_SUCCESS; - union { - struct FWCMD_COMMON_NTWK_MAC_QUERY *query; - struct FWCMD_COMMON_NTWK_MAC_SET *set; - } fwcmd = {NULL}; - struct MCC_WRB_AMAP *wrb = NULL; - u32 type = 0; - unsigned long irql; - struct be_mcc_wrb_response_copy rc; - - spin_lock_irqsave(&pfob->post_lock, irql); - - ASSERT(mac_address); - - ASSERT(port1 == false); - ASSERT(mac1 == false); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - - if (mgmt) { - type = MAC_ADDRESS_TYPE_MANAGEMENT; - } else { - if (pfob->type == BE_FUNCTION_TYPE_NETWORK) - type = MAC_ADDRESS_TYPE_NETWORK; - else - type = MAC_ADDRESS_TYPE_STORAGE; - } - - if (write) { - /* Prepares an embedded fwcmd, including - * request/response sizes. - */ - fwcmd.set = BE_PREPARE_EMBEDDED_FWCMD(pfob, - wrb, COMMON_NTWK_MAC_SET); - - fwcmd.set->params.request.invalidate = 0; - fwcmd.set->params.request.mac1 = (mac1 ? 1 : 0); - fwcmd.set->params.request.port = (port1 ? 1 : 0); - fwcmd.set->params.request.type = type; - - /* Copy the mac address to set. */ - fwcmd.set->params.request.mac.SizeOfStructure = - sizeof(fwcmd.set->params.request.mac); - memcpy(fwcmd.set->params.request.mac.MACAddress, - mac_address, ETH_ALEN); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, - cb, cb_context, NULL, NULL, fwcmd.set, NULL); - - } else { - - /* - * Prepares an embedded fwcmd, including - * request/response sizes. - */ - fwcmd.query = BE_PREPARE_EMBEDDED_FWCMD(pfob, - wrb, COMMON_NTWK_MAC_QUERY); - - fwcmd.query->params.request.mac1 = (mac1 ? 1 : 0); - fwcmd.query->params.request.port = (port1 ? 1 : 0); - fwcmd.query->params.request.type = type; - fwcmd.query->params.request.permanent = permanent; - - rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_NTWK_MAC_QUERY, - params.response.mac.MACAddress); - rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_NTWK_MAC_QUERY, - params.response.mac.MACAddress); - rc.va = mac_address; - /* Post the f/w command (with a copy for the response) */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb, - cb_context, NULL, NULL, fwcmd.query, &rc); - } - - if (status < 0) { - TRACE(DL_ERR, "mac set/query failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine writes data to context memory. - - pfob - Function object handle. - mac_table - Set to the 128-bit multicast address hash table. - - Returns BE_SUCCESS if successfull, otherwise a useful int is returned. - - IRQL: < DISPATCH_LEVEL -*/ - -int be_rxf_multicast_config(struct be_function_object *pfob, - bool promiscuous, u32 num, u8 *mac_table, - mcc_wrb_cqe_callback cb, /* optional */ - void *cb_context, - struct be_multicast_q_ctxt *q_ctxt) -{ - int status = BE_SUCCESS; - struct FWCMD_COMMON_NTWK_MULTICAST_SET *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - - ASSERT(num <= ARRAY_SIZE(fwcmd->params.request.mac)); - - if (num > ARRAY_SIZE(fwcmd->params.request.mac)) { - TRACE(DL_ERR, "Too many multicast addresses. BE supports %d.", - (int) ARRAY_SIZE(fwcmd->params.request.mac)); - return BE_NOT_OK; - } - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_NTWK_MULTICAST_SET); - - fwcmd->params.request.promiscuous = promiscuous; - if (!promiscuous) { - fwcmd->params.request.num_mac = num; - if (num > 0) { - ASSERT(mac_table); - memcpy(fwcmd->params.request.mac, - mac_table, ETH_ALEN * num); - } - } - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, fwcmd, NULL); - if (status < 0) { - TRACE(DL_ERR, "multicast fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine adds or removes a vlan tag from the rxf table. - - FunctionObject - Function object handle. - VLanTag - VLan tag to add or remove. - Add - Set to TRUE if this will add a vlan tag - - Returns BE_SUCCESS if successfull, otherwise a useful int is returned. - - IRQL: < DISPATCH_LEVEL -*/ -int be_rxf_vlan_config(struct be_function_object *pfob, - bool promiscuous, u32 num, u16 *vlan_tag_array, - mcc_wrb_cqe_callback cb, /* optional */ - void *cb_context, - struct be_vlan_q_ctxt *q_ctxt) /* optional */ -{ - int status = BE_SUCCESS; - struct FWCMD_COMMON_NTWK_VLAN_CONFIG *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - - if (num > ARRAY_SIZE(fwcmd->params.request.vlan_tag)) { - TRACE(DL_ERR, "Too many VLAN tags."); - return BE_NOT_OK; - } - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_NTWK_VLAN_CONFIG); - - fwcmd->params.request.promiscuous = promiscuous; - if (!promiscuous) { - fwcmd->params.request.num_vlan = num; - - if (num > 0) { - ASSERT(vlan_tag_array); - memcpy(fwcmd->params.request.vlan_tag, vlan_tag_array, - num * sizeof(vlan_tag_array[0])); - } - } - - /* Post the commadn */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, fwcmd, NULL); - if (status < 0) { - TRACE(DL_ERR, "vlan fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - - -int be_rxf_link_status(struct be_function_object *pfob, - struct BE_LINK_STATUS *link_status, - mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_link_status_q_ctxt *q_ctxt) -{ - struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - struct be_mcc_wrb_response_copy rc; - - ASSERT(link_status); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, - COMMON_NTWK_LINK_STATUS_QUERY); - - rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY, - params.response); - rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY, - params.response); - rc.va = link_status; - /* Post or queue the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, fwcmd, &rc); - - if (status < 0) { - TRACE(DL_ERR, "link status fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -int -be_rxf_query_eth_statistics(struct be_function_object *pfob, - struct FWCMD_ETH_GET_STATISTICS *va_for_fwcmd, - u64 pa_for_fwcmd, mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_nonembedded_q_ctxt *q_ctxt) -{ - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - - ASSERT(va_for_fwcmd); - ASSERT(pa_for_fwcmd); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - - TRACE(DL_INFO, "Query eth stats. fwcmd va:%p pa:0x%08x_%08x", - va_for_fwcmd, upper_32_bits(pa_for_fwcmd), (u32)pa_for_fwcmd); - - /* Prepares an embedded fwcmd, including request/response sizes. */ - va_for_fwcmd = BE_PREPARE_NONEMBEDDED_FWCMD(pfob, wrb, - va_for_fwcmd, pa_for_fwcmd, ETH_GET_STATISTICS); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, va_for_fwcmd, NULL); - if (status < 0) { - TRACE(DL_ERR, "eth stats fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -int -be_rxf_promiscuous(struct be_function_object *pfob, - bool enable_port0, bool enable_port1, - mcc_wrb_cqe_callback cb, void *cb_context, - struct be_promiscuous_q_ctxt *q_ctxt) -{ - struct FWCMD_ETH_PROMISCUOUS *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, ETH_PROMISCUOUS); - - fwcmd->params.request.port0_promiscuous = enable_port0; - fwcmd->params.request.port1_promiscuous = enable_port1; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, fwcmd, NULL); - - if (status < 0) { - TRACE(DL_ERR, "promiscuous fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - - -/* - *------------------------------------------------------------------------- - * Function: be_rxf_filter_config - * Configures BladeEngine ethernet receive filter settings. - * pfob - - * settings - Pointer to the requested filter settings. - * The response from BladeEngine will be placed back - * in this structure. - * cb - optional - * cb_context - optional - * q_ctxt - Optional. Pointer to a previously allocated struct. - * If the MCC WRB ring is full, this structure is - * used to queue the operation. It will be posted - * to the MCC ring when space becomes available. All - * queued commands will be posted to the ring in - * the order they are received. It is always valid - * to pass a pointer to a generic - * be_generic_q_ctxt. However, the specific - * context structs are generally smaller than - * the generic struct. - * return pend_status - BE_SUCCESS (0) on success. - * BE_PENDING (postive value) if the FWCMD - * completion is pending. Negative error code on failure. - *--------------------------------------------------------------------------- - */ -int -be_rxf_filter_config(struct be_function_object *pfob, - struct NTWK_RX_FILTER_SETTINGS *settings, - mcc_wrb_cqe_callback cb, void *cb_context, - struct be_rxf_filter_q_ctxt *q_ctxt) -{ - struct FWCMD_COMMON_NTWK_RX_FILTER *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - struct be_mcc_wrb_response_copy rc; - - ASSERT(settings); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_NTWK_RX_FILTER); - memcpy(&fwcmd->params.request, settings, sizeof(*settings)); - - rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_NTWK_RX_FILTER, - params.response); - rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_NTWK_RX_FILTER, - params.response); - rc.va = settings; - /* Post or queue the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, fwcmd, &rc); - - if (status < 0) { - TRACE(DL_ERR, "RXF/ERX filter config fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} diff --git a/drivers/staging/benet/etx_context.h b/drivers/staging/benet/etx_context.h deleted file mode 100644 index 554fbe5d127..00000000000 --- a/drivers/staging/benet/etx_context.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __etx_context_amap_h__ -#define __etx_context_amap_h__ - -/* ETX ring context structure. */ -struct BE_ETX_CONTEXT_AMAP { - u8 tx_cidx[11]; /* DWORD 0 */ - u8 rsvd0[5]; /* DWORD 0 */ - u8 rsvd1[16]; /* DWORD 0 */ - u8 tx_pidx[11]; /* DWORD 1 */ - u8 rsvd2; /* DWORD 1 */ - u8 tx_ring_size[4]; /* DWORD 1 */ - u8 pd_id[5]; /* DWORD 1 */ - u8 pd_id_not_valid; /* DWORD 1 */ - u8 cq_id_send[10]; /* DWORD 1 */ - u8 rsvd3[32]; /* DWORD 2 */ - u8 rsvd4[32]; /* DWORD 3 */ - u8 cur_bytes[32]; /* DWORD 4 */ - u8 max_bytes[32]; /* DWORD 5 */ - u8 time_stamp[32]; /* DWORD 6 */ - u8 rsvd5[11]; /* DWORD 7 */ - u8 func; /* DWORD 7 */ - u8 rsvd6[20]; /* DWORD 7 */ - u8 cur_txd_count[32]; /* DWORD 8 */ - u8 max_txd_count[32]; /* DWORD 9 */ - u8 rsvd7[32]; /* DWORD 10 */ - u8 rsvd8[32]; /* DWORD 11 */ - u8 rsvd9[32]; /* DWORD 12 */ - u8 rsvd10[32]; /* DWORD 13 */ - u8 rsvd11[32]; /* DWORD 14 */ - u8 rsvd12[32]; /* DWORD 15 */ -} __packed; -struct ETX_CONTEXT_AMAP { - u32 dw[16]; -}; - -#endif /* __etx_context_amap_h__ */ diff --git a/drivers/staging/benet/funcobj.c b/drivers/staging/benet/funcobj.c deleted file mode 100644 index 0f57eb58dae..00000000000 --- a/drivers/staging/benet/funcobj.c +++ /dev/null @@ -1,565 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include "hwlib.h" -#include "bestatus.h" - - -int -be_function_internal_query_firmware_config(struct be_function_object *pfob, - struct BE_FIRMWARE_CONFIG *config) -{ - struct FWCMD_COMMON_FIRMWARE_CONFIG *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - struct be_mcc_wrb_response_copy rc; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_FIRMWARE_CONFIG); - - rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_FIRMWARE_CONFIG, - params.response); - rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_FIRMWARE_CONFIG, - params.response); - rc.va = config; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, - NULL, NULL, NULL, fwcmd, &rc); -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This allocates and initializes a function object based on the information - provided by upper layer drivers. - - Returns BE_SUCCESS on success and an appropriate int on failure. - - A function object represents a single BladeEngine (logical) PCI function. - That is a function object either represents - the networking side of BladeEngine or the iSCSI side of BladeEngine. - - This routine will also detect and create an appropriate PD object for the - PCI function as needed. -*/ -int -be_function_object_create(u8 __iomem *csr_va, u8 __iomem *db_va, - u8 __iomem *pci_va, u32 function_type, - struct ring_desc *mailbox, struct be_function_object *pfob) -{ - int status; - - ASSERT(pfob); /* not a magic assert */ - ASSERT(function_type <= 2); - - TRACE(DL_INFO, "Create function object. type:%s object:0x%p", - (function_type == BE_FUNCTION_TYPE_ISCSI ? "iSCSI" : - (function_type == BE_FUNCTION_TYPE_NETWORK ? "Network" : - "Arm")), pfob); - - memset(pfob, 0, sizeof(*pfob)); - - pfob->type = function_type; - pfob->csr_va = csr_va; - pfob->db_va = db_va; - pfob->pci_va = pci_va; - - spin_lock_init(&pfob->cq_lock); - spin_lock_init(&pfob->post_lock); - spin_lock_init(&pfob->mcc_context_lock); - - - pfob->pci_function_number = 1; - - - pfob->emulate = false; - TRACE(DL_NOTE, "Non-emulation mode"); - status = be_drive_POST(pfob); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "BladeEngine POST failed."); - goto error; - } - - /* Initialize the mailbox */ - status = be_mpu_init_mailbox(pfob, mailbox); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "Failed to initialize mailbox."); - goto error; - } - /* - * Cache the firmware config for ASSERTs in hwclib and later - * driver queries. - */ - status = be_function_internal_query_firmware_config(pfob, - &pfob->fw_config); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "Failed to query firmware config."); - goto error; - } - -error: - if (status != BE_SUCCESS) { - /* No cleanup necessary */ - TRACE(DL_ERR, "Failed to create function."); - memset(pfob, 0, sizeof(*pfob)); - } - return status; -} - -/* - This routine drops the reference count on a given function object. Once - the reference count falls to zero, the function object is destroyed and all - resources held are freed. - - FunctionObject - The function object to drop the reference to. -*/ -int be_function_object_destroy(struct be_function_object *pfob) -{ - TRACE(DL_INFO, "Destroy pfob. Object:0x%p", - pfob); - - - ASSERT(pfob->mcc == NULL); - - return BE_SUCCESS; -} - -int be_function_cleanup(struct be_function_object *pfob) -{ - int status = 0; - u32 isr; - u32 host_intr; - struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP ctrl; - - - if (pfob->type == BE_FUNCTION_TYPE_NETWORK) { - status = be_rxf_multicast_config(pfob, false, 0, - NULL, NULL, NULL, NULL); - ASSERT(status == BE_SUCCESS); - } - /* VLAN */ - status = be_rxf_vlan_config(pfob, false, 0, NULL, NULL, NULL, NULL); - ASSERT(status == BE_SUCCESS); - /* - * MCC Queue -- Switches to mailbox mode. May want to destroy - * all but the MCC CQ before this call if polling CQ is much better - * performance than polling mailbox register. - */ - if (pfob->mcc) - status = be_mcc_ring_destroy(pfob->mcc); - /* - * If interrupts are disabled, clear any CEV interrupt assertions that - * fired after we stopped processing EQs. - */ - ctrl.dw[0] = PCICFG1_READ(pfob, host_timer_int_ctrl); - host_intr = AMAP_GET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR, - hostintr, ctrl.dw); - if (!host_intr) - if (pfob->type == BE_FUNCTION_TYPE_NETWORK) - isr = CSR_READ(pfob, cev.isr1); - else - isr = CSR_READ(pfob, cev.isr0); - else - /* This should never happen... */ - TRACE(DL_ERR, "function_cleanup called with interrupt enabled"); - /* Function object destroy */ - status = be_function_object_destroy(pfob); - ASSERT(status == BE_SUCCESS); - - return status; -} - - -void * -be_function_prepare_embedded_fwcmd(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, u32 payld_len, u32 request_length, - u32 response_length, u32 opcode, u32 subsystem) -{ - struct FWCMD_REQUEST_HEADER *header = NULL; - u32 n; - - ASSERT(wrb); - - n = offsetof(struct BE_MCC_WRB_AMAP, payload)/8; - AMAP_SET_BITS_PTR(MCC_WRB, embedded, wrb, 1); - AMAP_SET_BITS_PTR(MCC_WRB, payload_length, wrb, min(payld_len, n)); - header = (struct FWCMD_REQUEST_HEADER *)((u8 *)wrb + n); - - header->timeout = 0; - header->domain = 0; - header->request_length = max(request_length, response_length); - header->opcode = opcode; - header->subsystem = subsystem; - - return header; -} - -void * -be_function_prepare_nonembedded_fwcmd(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, - void *fwcmd_va, u64 fwcmd_pa, - u32 payld_len, - u32 request_length, - u32 response_length, - u32 opcode, u32 subsystem) -{ - struct FWCMD_REQUEST_HEADER *header = NULL; - u32 n; - struct MCC_WRB_PAYLOAD_AMAP *plp; - - ASSERT(wrb); - ASSERT(fwcmd_va); - - header = (struct FWCMD_REQUEST_HEADER *) fwcmd_va; - - AMAP_SET_BITS_PTR(MCC_WRB, embedded, wrb, 0); - AMAP_SET_BITS_PTR(MCC_WRB, payload_length, wrb, payld_len); - - /* - * Assume one fragment. The caller may override the SGL by - * rewriting the 0th length and adding more entries. They - * will also need to update the sge_count. - */ - AMAP_SET_BITS_PTR(MCC_WRB, sge_count, wrb, 1); - - n = offsetof(struct BE_MCC_WRB_AMAP, payload)/8; - plp = (struct MCC_WRB_PAYLOAD_AMAP *)((u8 *)wrb + n); - AMAP_SET_BITS_PTR(MCC_WRB_PAYLOAD, sgl[0].length, plp, payld_len); - AMAP_SET_BITS_PTR(MCC_WRB_PAYLOAD, sgl[0].pa_lo, plp, (u32)fwcmd_pa); - AMAP_SET_BITS_PTR(MCC_WRB_PAYLOAD, sgl[0].pa_hi, plp, - upper_32_bits(fwcmd_pa)); - - header->timeout = 0; - header->domain = 0; - header->request_length = max(request_length, response_length); - header->opcode = opcode; - header->subsystem = subsystem; - - return header; -} - -struct MCC_WRB_AMAP * -be_function_peek_mcc_wrb(struct be_function_object *pfob) -{ - struct MCC_WRB_AMAP *wrb = NULL; - u32 offset; - - if (pfob->mcc) - wrb = _be_mpu_peek_ring_wrb(pfob->mcc, false); - else { - offset = offsetof(struct BE_MCC_MAILBOX_AMAP, wrb)/8; - wrb = (struct MCC_WRB_AMAP *) ((u8 *) pfob->mailbox.va + - offset); - } - - if (wrb) - memset(wrb, 0, sizeof(struct MCC_WRB_AMAP)); - - return wrb; -} - -#if defined(BE_DEBUG) -void be_function_debug_print_wrb(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, void *optional_fwcmd_va, - struct be_mcc_wrb_context *wrb_context) -{ - - struct FWCMD_REQUEST_HEADER *header = NULL; - u8 embedded; - u32 n; - - embedded = AMAP_GET_BITS_PTR(MCC_WRB, embedded, wrb); - - if (embedded) { - n = offsetof(struct BE_MCC_WRB_AMAP, payload)/8; - header = (struct FWCMD_REQUEST_HEADER *)((u8 *)wrb + n); - } else { - header = (struct FWCMD_REQUEST_HEADER *) optional_fwcmd_va; - } - - /* Save the completed count before posting for a debug assert. */ - - if (header) { - wrb_context->opcode = header->opcode; - wrb_context->subsystem = header->subsystem; - - } else { - wrb_context->opcode = 0; - wrb_context->subsystem = 0; - } -} -#else -#define be_function_debug_print_wrb(a_, b_, c_, d_) -#endif - -int -be_function_post_mcc_wrb(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, - struct be_generic_q_ctxt *q_ctxt, - mcc_wrb_cqe_callback cb, void *cb_context, - mcc_wrb_cqe_callback internal_cb, - void *internal_cb_context, void *optional_fwcmd_va, - struct be_mcc_wrb_response_copy *rc) -{ - int status; - struct be_mcc_wrb_context *wrb_context = NULL; - u64 *p; - - if (q_ctxt) { - /* Initialize context. */ - q_ctxt->context.internal_cb = internal_cb; - q_ctxt->context.internal_cb_context = internal_cb_context; - q_ctxt->context.cb = cb; - q_ctxt->context.cb_context = cb_context; - if (rc) { - q_ctxt->context.copy.length = rc->length; - q_ctxt->context.copy.fwcmd_offset = rc->fwcmd_offset; - q_ctxt->context.copy.va = rc->va; - } else - q_ctxt->context.copy.length = 0; - - q_ctxt->context.optional_fwcmd_va = optional_fwcmd_va; - - /* Queue this request */ - status = be_function_queue_mcc_wrb(pfob, q_ctxt); - - goto Error; - } - /* - * Allocate a WRB context struct to hold the callback pointers, - * status, etc. This is required if commands complete out of order. - */ - wrb_context = _be_mcc_allocate_wrb_context(pfob); - if (!wrb_context) { - TRACE(DL_WARN, "Failed to allocate MCC WRB context."); - status = BE_STATUS_SYSTEM_RESOURCES; - goto Error; - } - /* Initialize context. */ - memset(wrb_context, 0, sizeof(*wrb_context)); - wrb_context->internal_cb = internal_cb; - wrb_context->internal_cb_context = internal_cb_context; - wrb_context->cb = cb; - wrb_context->cb_context = cb_context; - if (rc) { - wrb_context->copy.length = rc->length; - wrb_context->copy.fwcmd_offset = rc->fwcmd_offset; - wrb_context->copy.va = rc->va; - } else - wrb_context->copy.length = 0; - wrb_context->wrb = wrb; - - /* - * Copy the context pointer into the WRB opaque tag field. - * Verify assumption of 64-bit tag with a compile time assert. - */ - p = (u64 *) ((u8 *)wrb + offsetof(struct BE_MCC_WRB_AMAP, tag)/8); - *p = (u64)(size_t)wrb_context; - - /* Print info about this FWCMD for debug builds. */ - be_function_debug_print_wrb(pfob, wrb, optional_fwcmd_va, wrb_context); - - /* - * issue the WRB to the MPU as appropriate - */ - if (pfob->mcc) { - /* - * we're in WRB mode, pass to the mcc layer - */ - status = _be_mpu_post_wrb_ring(pfob->mcc, wrb, wrb_context); - } else { - /* - * we're in mailbox mode - */ - status = _be_mpu_post_wrb_mailbox(pfob, wrb, wrb_context); - - /* mailbox mode always completes synchronously */ - ASSERT(status != BE_STATUS_PENDING); - } - -Error: - - return status; -} - -int -be_function_ring_destroy(struct be_function_object *pfob, - u32 id, u32 ring_type, mcc_wrb_cqe_callback cb, - void *cb_context, mcc_wrb_cqe_callback internal_cb, - void *internal_cb_context) -{ - - struct FWCMD_COMMON_RING_DESTROY *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - TRACE(DL_INFO, "Destroy ring id:%d type:%d", id, ring_type); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in destroy ring."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_RING_DESTROY); - - fwcmd->params.request.id = id; - fwcmd->params.request.ring_type = ring_type; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb, cb_context, - internal_cb, internal_cb_context, fwcmd, NULL); - if (status != BE_SUCCESS && status != BE_PENDING) { - TRACE(DL_ERR, "Ring destroy fwcmd failed. id:%d ring_type:%d", - id, ring_type); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -void -be_rd_to_pa_list(struct ring_desc *rd, struct PHYS_ADDR *pa_list, u32 max_num) -{ - u32 num_pages = PAGES_SPANNED(rd->va, rd->length); - u32 i = 0; - u64 pa = rd->pa; - __le64 lepa; - - ASSERT(pa_list); - ASSERT(pa); - - for (i = 0; i < min(num_pages, max_num); i++) { - lepa = cpu_to_le64(pa); - pa_list[i].lo = (u32)lepa; - pa_list[i].hi = upper_32_bits(lepa); - pa += PAGE_SIZE; - } -} - - - -/*----------------------------------------------------------------------------- - * Function: be_function_get_fw_version - * Retrieves the firmware version on the adpater. If the callback is - * NULL this call executes synchronously. If the callback is not NULL, - * the returned status will be BE_PENDING if the command was issued - * successfully. - * pfob - - * fwv - Pointer to response buffer if callback is NULL. - * cb - Callback function invoked when the FWCMD completes. - * cb_context - Passed to the callback function. - * return pend_status - BE_SUCCESS (0) on success. - * BE_PENDING (postive value) if the FWCMD - * completion is pending. Negative error code on failure. - *--------------------------------------------------------------------------- - */ -int -be_function_get_fw_version(struct be_function_object *pfob, - struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD *fwv, - mcc_wrb_cqe_callback cb, void *cb_context) -{ - int status = BE_SUCCESS; - struct MCC_WRB_AMAP *wrb = NULL; - struct FWCMD_COMMON_GET_FW_VERSION *fwcmd = NULL; - unsigned long irql; - struct be_mcc_wrb_response_copy rc; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - - if (!cb && !fwv) { - TRACE(DL_ERR, "callback and response buffer NULL!"); - status = BE_NOT_OK; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_GET_FW_VERSION); - - rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_GET_FW_VERSION, - params.response); - rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_GET_FW_VERSION, - params.response); - rc.va = fwv; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb, - cb_context, NULL, NULL, fwcmd, &rc); - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -int -be_function_queue_mcc_wrb(struct be_function_object *pfob, - struct be_generic_q_ctxt *q_ctxt) -{ - int status; - - ASSERT(q_ctxt); - - /* - * issue the WRB to the MPU as appropriate - */ - if (pfob->mcc) { - - /* We're in ring mode. Queue this item. */ - pfob->mcc->backlog_length++; - list_add_tail(&q_ctxt->context.list, &pfob->mcc->backlog); - status = BE_PENDING; - } else { - status = BE_NOT_OK; - } - return status; -} - diff --git a/drivers/staging/benet/fwcmd_common.h b/drivers/staging/benet/fwcmd_common.h deleted file mode 100644 index 406e0d6fa98..00000000000 --- a/drivers/staging/benet/fwcmd_common.h +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_common_amap_h__ -#define __fwcmd_common_amap_h__ -#include "host_struct.h" - -/* --- PHY_LINK_DUPLEX_ENUM --- */ -#define PHY_LINK_DUPLEX_NONE (0) -#define PHY_LINK_DUPLEX_HALF (1) -#define PHY_LINK_DUPLEX_FULL (2) - -/* --- PHY_LINK_SPEED_ENUM --- */ -#define PHY_LINK_SPEED_ZERO (0) /* No link. */ -#define PHY_LINK_SPEED_10MBPS (1) /* 10 Mbps */ -#define PHY_LINK_SPEED_100MBPS (2) /* 100 Mbps */ -#define PHY_LINK_SPEED_1GBPS (3) /* 1 Gbps */ -#define PHY_LINK_SPEED_10GBPS (4) /* 10 Gbps */ - -/* --- PHY_LINK_FAULT_ENUM --- */ -#define PHY_LINK_FAULT_NONE (0) /* No fault status - available or detected */ -#define PHY_LINK_FAULT_LOCAL (1) /* Local fault detected */ -#define PHY_LINK_FAULT_REMOTE (2) /* Remote fault detected */ - -/* --- BE_ULP_MASK --- */ -#define BE_ULP0_MASK (1) -#define BE_ULP1_MASK (2) -#define BE_ULP2_MASK (4) - -/* --- NTWK_ACTIVE_PORT --- */ -#define NTWK_PORT_A (0) /* Port A is currently active */ -#define NTWK_PORT_B (1) /* Port B is currently active */ -#define NTWK_NO_ACTIVE_PORT (15) /* Both ports have lost link */ - -/* --- NTWK_LINK_TYPE --- */ -#define NTWK_LINK_TYPE_PHYSICAL (0) /* link up/down event - applies to BladeEngine's - Physical Ports - */ -#define NTWK_LINK_TYPE_VIRTUAL (1) /* Virtual link up/down event - reported by BladeExchange. - This applies only when the - VLD feature is enabled - */ - -/* - * --- FWCMD_MAC_TYPE_ENUM --- - * This enum defines the types of MAC addresses in the RXF MAC Address Table. - */ -#define MAC_ADDRESS_TYPE_STORAGE (0) /* Storage MAC Address */ -#define MAC_ADDRESS_TYPE_NETWORK (1) /* Network MAC Address */ -#define MAC_ADDRESS_TYPE_PD (2) /* Protection Domain MAC Addr */ -#define MAC_ADDRESS_TYPE_MANAGEMENT (3) /* Managment MAC Address */ - - -/* --- FWCMD_RING_TYPE_ENUM --- */ -#define FWCMD_RING_TYPE_ETH_RX (1) /* Ring created with */ - /* FWCMD_COMMON_ETH_RX_CREATE. */ -#define FWCMD_RING_TYPE_ETH_TX (2) /* Ring created with */ - /* FWCMD_COMMON_ETH_TX_CREATE. */ -#define FWCMD_RING_TYPE_ISCSI_WRBQ (3) /* Ring created with */ - /* FWCMD_COMMON_ISCSI_WRBQ_CREATE. */ -#define FWCMD_RING_TYPE_ISCSI_DEFQ (4) /* Ring created with */ - /* FWCMD_COMMON_ISCSI_DEFQ_CREATE. */ -#define FWCMD_RING_TYPE_TPM_WRBQ (5) /* Ring created with */ - /* FWCMD_COMMON_TPM_WRBQ_CREATE. */ -#define FWCMD_RING_TYPE_TPM_DEFQ (6) /* Ring created with */ - /* FWCMD_COMMONTPM_TDEFQ_CREATE. */ -#define FWCMD_RING_TYPE_TPM_RQ (7) /* Ring created with */ - /* FWCMD_COMMON_TPM_RQ_CREATE. */ -#define FWCMD_RING_TYPE_MCC (8) /* Ring created with */ - /* FWCMD_COMMON_MCC_CREATE. */ -#define FWCMD_RING_TYPE_CQ (9) /* Ring created with */ - /* FWCMD_COMMON_CQ_CREATE. */ -#define FWCMD_RING_TYPE_EQ (10) /* Ring created with */ - /* FWCMD_COMMON_EQ_CREATE. */ -#define FWCMD_RING_TYPE_QP (11) /* Ring created with */ - /* FWCMD_RDMA_QP_CREATE. */ - - -/* --- ETH_TX_RING_TYPE_ENUM --- */ -#define ETH_TX_RING_TYPE_FORWARDING (1) /* Ethernet ring for - forwarding packets */ -#define ETH_TX_RING_TYPE_STANDARD (2) /* Ethernet ring for sending - network packets. */ -#define ETH_TX_RING_TYPE_BOUND (3) /* Ethernet ring bound to the - port specified in the command - header.port_number field. - Rings of this type are - NOT subject to the - failover logic implemented - in the BladeEngine. - */ - -/* --- FWCMD_COMMON_QOS_TYPE_ENUM --- */ -#define QOS_BITS_NIC (1) /* max_bits_per_second_NIC */ - /* field is valid. */ -#define QOS_PKTS_NIC (2) /* max_packets_per_second_NIC */ - /* field is valid. */ -#define QOS_IOPS_ISCSI (4) /* max_ios_per_second_iSCSI */ - /*field is valid. */ -#define QOS_VLAN_TAG (8) /* domain_VLAN_tag field - is valid. */ -#define QOS_FABRIC_ID (16) /* fabric_domain_ID field - is valid. */ -#define QOS_OEM_PARAMS (32) /* qos_params_oem field - is valid. */ -#define QOS_TPUT_ISCSI (64) /* max_bytes_per_second_iSCSI - field is valid. */ - - -/* - * --- FAILOVER_CONFIG_ENUM --- - * Failover configuration setting used in FWCMD_COMMON_FORCE_FAILOVER - */ -#define FAILOVER_CONFIG_NO_CHANGE (0) /* No change to automatic */ - /* port failover setting. */ -#define FAILOVER_CONFIG_ON (1) /* Automatic port failover - on link down is enabled. */ -#define FAILOVER_CONFIG_OFF (2) /* Automatic port failover - on link down is disabled. */ - -/* - * --- FAILOVER_PORT_ENUM --- - * Failover port setting used in FWCMD_COMMON_FORCE_FAILOVER - */ -#define FAILOVER_PORT_A (0) /* Selects port A. */ -#define FAILOVER_PORT_B (1) /* Selects port B. */ -#define FAILOVER_PORT_NONE (15) /* No port change requested. */ - - -/* - * --- MGMT_FLASHROM_OPCODE --- - * Flash ROM operation code - */ -#define MGMT_FLASHROM_OPCODE_FLASH (1) /* Commit downloaded data - to Flash ROM */ -#define MGMT_FLASHROM_OPCODE_SAVE (2) /* Save downloaded data to - ARM's DDR - do not flash */ -#define MGMT_FLASHROM_OPCODE_CLEAR (3) /* Erase specified component - from FlashROM */ -#define MGMT_FLASHROM_OPCODE_REPORT (4) /* Read specified component - from Flash ROM */ -#define MGMT_FLASHROM_OPCODE_IMAGE_INFO (5) /* Returns size of a - component */ - -/* - * --- MGMT_FLASHROM_OPTYPE --- - * Flash ROM operation type - */ -#define MGMT_FLASHROM_OPTYPE_CODE_FIRMWARE (0) /* Includes ARM firmware, - IPSec (optional) and EP - firmware */ -#define MGMT_FLASHROM_OPTYPE_CODE_REDBOOT (1) -#define MGMT_FLASHROM_OPTYPE_CODE_BIOS (2) -#define MGMT_FLASHROM_OPTYPE_CODE_PXE_BIOS (3) -#define MGMT_FLASHROM_OPTYPE_CODE_CTRLS (4) -#define MGMT_FLASHROM_OPTYPE_CFG_IPSEC (5) -#define MGMT_FLASHROM_OPTYPE_CFG_INI (6) -#define MGMT_FLASHROM_OPTYPE_ROM_OFFSET_SPECIFIED (7) - -/* - * --- FLASHROM_TYPE --- - * Flash ROM manufacturers supported in the f/w - */ -#define INTEL (0) -#define SPANSION (1) -#define MICRON (2) - -/* --- DDR_CAS_TYPE --- */ -#define CAS_3 (0) -#define CAS_4 (1) -#define CAS_5 (2) - -/* --- DDR_SIZE_TYPE --- */ -#define SIZE_256MB (0) -#define SIZE_512MB (1) - -/* --- DDR_MODE_TYPE --- */ -#define DDR_NO_ECC (0) -#define DDR_ECC (1) - -/* --- INTERFACE_10GB_TYPE --- */ -#define CX4_TYPE (0) -#define XFP_TYPE (1) - -/* --- BE_CHIP_MAX_MTU --- */ -#define CHIP_MAX_MTU (9000) - -/* --- XAUI_STATE_ENUM --- */ -#define XAUI_STATE_ENABLE (0) /* This MUST be the default - value for all requests - which set/change - equalization parameter. */ -#define XAUI_STATE_DISABLE (255) /* The XAUI for both ports - may be disabled for EMI - tests. There is no - provision for turning off - individual ports. - */ -/* --- BE_ASIC_REVISION --- */ -#define BE_ASIC_REV_A0 (1) -#define BE_ASIC_REV_A1 (2) - -#endif /* __fwcmd_common_amap_h__ */ diff --git a/drivers/staging/benet/fwcmd_common_bmap.h b/drivers/staging/benet/fwcmd_common_bmap.h deleted file mode 100644 index a007cf27650..00000000000 --- a/drivers/staging/benet/fwcmd_common_bmap.h +++ /dev/null @@ -1,717 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_common_bmap_h__ -#define __fwcmd_common_bmap_h__ -#include "fwcmd_types_bmap.h" -#include "fwcmd_hdr_bmap.h" - -#if defined(__BIG_ENDIAN) - /* Physical Address. */ -struct PHYS_ADDR { - union { - struct { - u32 lo; /* DWORD 0 */ - u32 hi; /* DWORD 1 */ - } __packed; /* unnamed struct */ - u32 dw[2]; /* dword union */ - }; /* unnamed union */ -} __packed ; - - -#else - /* Physical Address. */ -struct PHYS_ADDR { - union { - struct { - u32 lo; /* DWORD 0 */ - u32 hi; /* DWORD 1 */ - } __packed; /* unnamed struct */ - u32 dw[2]; /* dword union */ - }; /* unnamed union */ -} __packed ; - -struct BE_LINK_STATUS { - u8 mac0_duplex; - u8 mac0_speed; - u8 mac1_duplex; - u8 mac1_speed; - u8 mgmt_mac_duplex; - u8 mgmt_mac_speed; - u8 active_port; - u8 rsvd0; - u8 mac0_fault; - u8 mac1_fault; - u16 rsvd1; -} __packed; -#endif - -struct FWCMD_COMMON_ANON_170_REQUEST { - u32 rsvd0; -} __packed; - -union LINK_STATUS_QUERY_PARAMS { - struct BE_LINK_STATUS response; - struct FWCMD_COMMON_ANON_170_REQUEST request; -} __packed; - -/* - * Queries the the link status for all ports. The valid values below - * DO NOT indicate that a particular duplex or speed is supported by - * BladeEngine. These enumerations simply list all possible duplexes - * and speeds for any port. Consult BladeEngine product documentation - * for the supported parameters. - */ -struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY { - union FWCMD_HEADER header; - union LINK_STATUS_QUERY_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_171_REQUEST { - u8 type; - u8 port; - u8 mac1; - u8 permanent; -} __packed; - -struct FWCMD_COMMON_ANON_172_RESPONSE { - struct MAC_ADDRESS_FORMAT mac; -} __packed; - -union NTWK_MAC_QUERY_PARAMS { - struct FWCMD_COMMON_ANON_171_REQUEST request; - struct FWCMD_COMMON_ANON_172_RESPONSE response; -} __packed; - -/* Queries one MAC address. */ -struct FWCMD_COMMON_NTWK_MAC_QUERY { - union FWCMD_HEADER header; - union NTWK_MAC_QUERY_PARAMS params; -} __packed; - -struct MAC_SET_PARAMS_IN { - u8 type; - u8 port; - u8 mac1; - u8 invalidate; - struct MAC_ADDRESS_FORMAT mac; -} __packed; - -struct MAC_SET_PARAMS_OUT { - u32 rsvd0; -} __packed; - -union MAC_SET_PARAMS { - struct MAC_SET_PARAMS_IN request; - struct MAC_SET_PARAMS_OUT response; -} __packed; - -/* Sets a MAC address. */ -struct FWCMD_COMMON_NTWK_MAC_SET { - union FWCMD_HEADER header; - union MAC_SET_PARAMS params; -} __packed; - -/* MAC address list. */ -struct NTWK_MULTICAST_MAC_LIST { - u8 byte[6]; -} __packed; - -struct FWCMD_COMMON_NTWK_MULTICAST_SET_REQUEST_PAYLOAD { - u16 num_mac; - u8 promiscuous; - u8 rsvd0; - struct NTWK_MULTICAST_MAC_LIST mac[32]; -} __packed; - -struct FWCMD_COMMON_ANON_174_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_173_PARAMS { - struct FWCMD_COMMON_NTWK_MULTICAST_SET_REQUEST_PAYLOAD request; - struct FWCMD_COMMON_ANON_174_RESPONSE response; -} __packed; - -/* - * Sets multicast address hash. The MPU will merge the MAC address lists - * from all clients, including the networking and storage functions. - * This command may fail if the final merged list of MAC addresses exceeds - * 32 entries. - */ -struct FWCMD_COMMON_NTWK_MULTICAST_SET { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_173_PARAMS params; -} __packed; - -struct FWCMD_COMMON_NTWK_VLAN_CONFIG_REQUEST_PAYLOAD { - u16 num_vlan; - u8 promiscuous; - u8 rsvd0; - u16 vlan_tag[32]; -} __packed; - -struct FWCMD_COMMON_ANON_176_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_175_PARAMS { - struct FWCMD_COMMON_NTWK_VLAN_CONFIG_REQUEST_PAYLOAD request; - struct FWCMD_COMMON_ANON_176_RESPONSE response; -} __packed; - -/* - * Sets VLAN tag filter. The MPU will merge the VLAN tag list from all - * clients, including the networking and storage functions. This command - * may fail if the final vlan_tag array (from all functions) is longer - * than 32 entries. - */ -struct FWCMD_COMMON_NTWK_VLAN_CONFIG { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_175_PARAMS params; -} __packed; - -struct RING_DESTROY_REQUEST { - u16 ring_type; - u16 id; - u8 bypass_flush; - u8 rsvd0; - u16 rsvd1; -} __packed; - -struct FWCMD_COMMON_ANON_190_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_189_PARAMS { - struct RING_DESTROY_REQUEST request; - struct FWCMD_COMMON_ANON_190_RESPONSE response; -} __packed; -/* - * Command for destroying any ring. The connection(s) using the ring should - * be quiesced before destroying the ring. - */ -struct FWCMD_COMMON_RING_DESTROY { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_189_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_192_REQUEST { - u16 num_pages; - u16 rsvd0; - struct CQ_CONTEXT_AMAP context; - struct PHYS_ADDR pages[4]; -} __packed ; - -struct FWCMD_COMMON_ANON_193_RESPONSE { - u16 cq_id; -} __packed ; - -union FWCMD_COMMON_ANON_191_PARAMS { - struct FWCMD_COMMON_ANON_192_REQUEST request; - struct FWCMD_COMMON_ANON_193_RESPONSE response; -} __packed ; - -/* - * Command for creating a completion queue. A Completion Queue must span - * at least 1 page and at most 4 pages. Each completion queue entry - * is 16 bytes regardless of CQ entry format. Thus the ring must be - * at least 256 entries deep (corresponding to 1 page) and can be at - * most 1024 entries deep (corresponding to 4 pages). The number of - * pages posted must contain the CQ ring size as encoded in the context. - * - */ -struct FWCMD_COMMON_CQ_CREATE { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_191_PARAMS params; -} __packed ; - -struct FWCMD_COMMON_ANON_198_REQUEST { - u16 num_pages; - u16 rsvd0; - struct EQ_CONTEXT_AMAP context; - struct PHYS_ADDR pages[8]; -} __packed ; - -struct FWCMD_COMMON_ANON_199_RESPONSE { - u16 eq_id; -} __packed ; - -union FWCMD_COMMON_ANON_197_PARAMS { - struct FWCMD_COMMON_ANON_198_REQUEST request; - struct FWCMD_COMMON_ANON_199_RESPONSE response; -} __packed ; - -/* - * Command for creating a event queue. An Event Queue must span at least - * 1 page and at most 8 pages. The number of pages posted must contain - * the EQ ring. The ring is defined by the size of the EQ entries (encoded - * in the context) and the number of EQ entries (also encoded in the - * context). - */ -struct FWCMD_COMMON_EQ_CREATE { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_197_PARAMS params; -} __packed ; - -struct FWCMD_COMMON_ANON_201_REQUEST { - u16 cq_id; - u16 bcmc_cq_id; - u16 num_pages; - u16 rsvd0; - struct PHYS_ADDR pages[2]; -} __packed; - -struct FWCMD_COMMON_ANON_202_RESPONSE { - u16 id; -} __packed; - -union FWCMD_COMMON_ANON_200_PARAMS { - struct FWCMD_COMMON_ANON_201_REQUEST request; - struct FWCMD_COMMON_ANON_202_RESPONSE response; -} __packed; - -/* - * Command for creating Ethernet receive ring. An ERX ring contains ETH_RX_D - * entries (8 bytes each). An ERX ring must be 1024 entries deep - * (corresponding to 2 pages). - */ -struct FWCMD_COMMON_ETH_RX_CREATE { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_200_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_204_REQUEST { - u16 num_pages; - u8 ulp_num; - u8 type; - struct ETX_CONTEXT_AMAP context; - struct PHYS_ADDR pages[8]; -} __packed ; - -struct FWCMD_COMMON_ANON_205_RESPONSE { - u16 cid; - u8 ulp_num; - u8 rsvd0; -} __packed ; - -union FWCMD_COMMON_ANON_203_PARAMS { - struct FWCMD_COMMON_ANON_204_REQUEST request; - struct FWCMD_COMMON_ANON_205_RESPONSE response; -} __packed ; - -/* - * Command for creating an Ethernet transmit ring. An ETX ring contains - * ETH_WRB entries (16 bytes each). An ETX ring must be at least 256 - * entries deep (corresponding to 1 page) and at most 2k entries deep - * (corresponding to 8 pages). - */ -struct FWCMD_COMMON_ETH_TX_CREATE { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_203_PARAMS params; -} __packed ; - -struct FWCMD_COMMON_ANON_222_REQUEST { - u16 num_pages; - u16 rsvd0; - struct MCC_RING_CONTEXT_AMAP context; - struct PHYS_ADDR pages[8]; -} __packed ; - -struct FWCMD_COMMON_ANON_223_RESPONSE { - u16 id; -} __packed ; - -union FWCMD_COMMON_ANON_221_PARAMS { - struct FWCMD_COMMON_ANON_222_REQUEST request; - struct FWCMD_COMMON_ANON_223_RESPONSE response; -} __packed ; - -/* - * Command for creating the MCC ring. An MCC ring must be at least 16 - * entries deep (corresponding to 1 page) and at most 128 entries deep - * (corresponding to 8 pages). - */ -struct FWCMD_COMMON_MCC_CREATE { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_221_PARAMS params; -} __packed ; - -struct GET_QOS_IN { - u32 qos_params_rsvd; -} __packed; - -struct GET_QOS_OUT { - u32 max_bits_per_second_NIC; - u32 max_packets_per_second_NIC; - u32 max_ios_per_second_iSCSI; - u32 max_bytes_per_second_iSCSI; - u16 domain_VLAN_tag; - u16 fabric_domain_ID; - u32 qos_params_oem[4]; -} __packed; - -union GET_QOS_PARAMS { - struct GET_QOS_IN request; - struct GET_QOS_OUT response; -} __packed; - -/* QOS/Bandwidth settings per domain. Applicable only in VMs. */ -struct FWCMD_COMMON_GET_QOS { - union FWCMD_HEADER header; - union GET_QOS_PARAMS params; -} __packed; - -struct SET_QOS_IN { - u32 valid_flags; - u32 max_bits_per_second_NIC; - u32 max_packets_per_second_NIC; - u32 max_ios_per_second_iSCSI; - u32 max_bytes_per_second_iSCSI; - u16 domain_VLAN_tag; - u16 fabric_domain_ID; - u32 qos_params_oem[4]; -} __packed; - -struct SET_QOS_OUT { - u32 qos_params_rsvd; -} __packed; - -union SET_QOS_PARAMS { - struct SET_QOS_IN request; - struct SET_QOS_OUT response; -} __packed; - -/* QOS/Bandwidth settings per domain. Applicable only in VMs. */ -struct FWCMD_COMMON_SET_QOS { - union FWCMD_HEADER header; - union SET_QOS_PARAMS params; -} __packed; - -struct SET_FRAME_SIZE_IN { - u32 max_tx_frame_size; - u32 max_rx_frame_size; -} __packed; - -struct SET_FRAME_SIZE_OUT { - u32 chip_max_tx_frame_size; - u32 chip_max_rx_frame_size; -} __packed; - -union SET_FRAME_SIZE_PARAMS { - struct SET_FRAME_SIZE_IN request; - struct SET_FRAME_SIZE_OUT response; -} __packed; - -/* Set frame size command. Only host domain may issue this command. */ -struct FWCMD_COMMON_SET_FRAME_SIZE { - union FWCMD_HEADER header; - union SET_FRAME_SIZE_PARAMS params; -} __packed; - -struct FORCE_FAILOVER_IN { - u32 move_to_port; - u32 failover_config; -} __packed; - -struct FWCMD_COMMON_ANON_231_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_230_PARAMS { - struct FORCE_FAILOVER_IN request; - struct FWCMD_COMMON_ANON_231_RESPONSE response; -} __packed; - -/* - * Use this command to control failover in BladeEngine. It may be used - * to failback to a restored port or to forcibly move traffic from - * one port to another. It may also be used to enable or disable the - * automatic failover feature. This command can only be issued by domain - * 0. - */ -struct FWCMD_COMMON_FORCE_FAILOVER { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_230_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_240_REQUEST { - u64 context; -} __packed; - -struct FWCMD_COMMON_ANON_241_RESPONSE { - u64 context; -} __packed; - -union FWCMD_COMMON_ANON_239_PARAMS { - struct FWCMD_COMMON_ANON_240_REQUEST request; - struct FWCMD_COMMON_ANON_241_RESPONSE response; -} __packed; - -/* - * This command can be used by clients as a no-operation request. Typical - * uses for drivers are as a heartbeat mechanism, or deferred processing - * catalyst. The ARM will always complete this command with a good completion. - * The 64-bit parameter is not touched by the ARM processor. - */ -struct FWCMD_COMMON_NOP { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_239_PARAMS params; -} __packed; - -struct NTWK_RX_FILTER_SETTINGS { - u8 promiscuous; - u8 ip_cksum; - u8 tcp_cksum; - u8 udp_cksum; - u8 pass_err; - u8 pass_ckerr; - u8 strip_crc; - u8 mcast_en; - u8 bcast_en; - u8 mcast_promiscuous_en; - u8 unicast_en; - u8 vlan_promiscuous; -} __packed; - -union FWCMD_COMMON_ANON_242_PARAMS { - struct NTWK_RX_FILTER_SETTINGS request; - struct NTWK_RX_FILTER_SETTINGS response; -} __packed; - -/* - * This command is used to modify the ethernet receive filter configuration. - * Only domain 0 network function drivers may issue this command. The - * applied configuration is returned in the response payload. Note: - * Some receive packet filter settings are global on BladeEngine and - * can affect both the storage and network function clients that the - * BladeEngine hardware and firmware serve. Additionaly, depending - * on the revision of BladeEngine, some ethernet receive filter settings - * are dependent on others. If a dependency exists between settings - * for the BladeEngine revision, and the command request settings do - * not meet the dependency requirement, the invalid settings will not - * be applied despite the comand succeeding. For example: a driver may - * request to enable broadcast packets, but not enable multicast packets. - * On early revisions of BladeEngine, there may be no distinction between - * broadcast and multicast filters, so broadcast could not be enabled - * without enabling multicast. In this scenario, the comand would still - * succeed, but the response payload would indicate the previously - * configured broadcast and multicast setting. - */ -struct FWCMD_COMMON_NTWK_RX_FILTER { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_242_PARAMS params; -} __packed; - - -struct FWCMD_COMMON_ANON_244_REQUEST { - u32 rsvd0; -} __packed; - -struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD { - u8 firmware_version_string[32]; - u8 fw_on_flash_version_string[32]; -} __packed; - -union FWCMD_COMMON_ANON_243_PARAMS { - struct FWCMD_COMMON_ANON_244_REQUEST request; - struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD response; -} __packed; - -/* This comand retrieves the firmware version. */ -struct FWCMD_COMMON_GET_FW_VERSION { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_243_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_246_REQUEST { - u16 tx_flow_control; - u16 rx_flow_control; -} __packed; - -struct FWCMD_COMMON_ANON_247_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_245_PARAMS { - struct FWCMD_COMMON_ANON_246_REQUEST request; - struct FWCMD_COMMON_ANON_247_RESPONSE response; -} __packed; - -/* - * This comand is used to program BladeEngine flow control behavior. - * Only the host networking driver is allowed to use this comand. - */ -struct FWCMD_COMMON_SET_FLOW_CONTROL { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_245_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_249_REQUEST { - u32 rsvd0; -} __packed; - -struct FWCMD_COMMON_ANON_250_RESPONSE { - u16 tx_flow_control; - u16 rx_flow_control; -} __packed; - -union FWCMD_COMMON_ANON_248_PARAMS { - struct FWCMD_COMMON_ANON_249_REQUEST request; - struct FWCMD_COMMON_ANON_250_RESPONSE response; -} __packed; - -/* This comand is used to read BladeEngine flow control settings. */ -struct FWCMD_COMMON_GET_FLOW_CONTROL { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_248_PARAMS params; -} __packed; - -struct EQ_DELAY_PARAMS { - u32 eq_id; - u32 delay_in_microseconds; -} __packed; - -struct FWCMD_COMMON_ANON_257_REQUEST { - u32 num_eq; - u32 rsvd0; - struct EQ_DELAY_PARAMS delay[16]; -} __packed; - -struct FWCMD_COMMON_ANON_258_RESPONSE { - u32 delay_resolution_in_microseconds; - u32 delay_max_in_microseconds; -} __packed; - -union MODIFY_EQ_DELAY_PARAMS { - struct FWCMD_COMMON_ANON_257_REQUEST request; - struct FWCMD_COMMON_ANON_258_RESPONSE response; -} __packed; - -/* This comand changes the EQ delay for a given set of EQs. */ -struct FWCMD_COMMON_MODIFY_EQ_DELAY { - union FWCMD_HEADER header; - union MODIFY_EQ_DELAY_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_260_REQUEST { - u32 rsvd0; -} __packed; - -struct BE_FIRMWARE_CONFIG { - u16 be_config_number; - u16 asic_revision; - u32 nic_ulp_mask; - u32 tulp_mask; - u32 iscsi_ulp_mask; - u32 rdma_ulp_mask; - u32 rsvd0[4]; - u32 eth_tx_id_start; - u32 eth_tx_id_count; - u32 eth_rx_id_start; - u32 eth_rx_id_count; - u32 tpm_wrbq_id_start; - u32 tpm_wrbq_id_count; - u32 tpm_defq_id_start; - u32 tpm_defq_id_count; - u32 iscsi_wrbq_id_start; - u32 iscsi_wrbq_id_count; - u32 iscsi_defq_id_start; - u32 iscsi_defq_id_count; - u32 rdma_qp_id_start; - u32 rdma_qp_id_count; - u32 rsvd1[8]; -} __packed; - -union FWCMD_COMMON_ANON_259_PARAMS { - struct FWCMD_COMMON_ANON_260_REQUEST request; - struct BE_FIRMWARE_CONFIG response; -} __packed; - -/* - * This comand queries the current firmware configuration parameters. - * The static configuration type is defined by be_config_number. This - * differentiates different BladeEngine builds, such as iSCSI Initiator - * versus iSCSI Target. For a given static configuration, the Upper - * Layer Protocol (ULP) processors may be reconfigured to support different - * protocols. Each ULP processor supports one or more protocols. The - * masks indicate which processors are configured for each protocol. - * For a given static configuration, the number of TCP connections - * supported for each protocol may vary. The *_id_start and *_id_count - * variables define a linear range of IDs that are available for each - * supported protocol. The *_id_count may be used by the driver to allocate - * the appropriate number of connection resources. The *_id_start may - * be used to map the arbitrary range of IDs to a zero-based range - * of indices. - */ -struct FWCMD_COMMON_FIRMWARE_CONFIG { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_259_PARAMS params; -} __packed; - -struct FWCMD_COMMON_PORT_EQUALIZATION_PARAMS { - u32 emph_lev_sel_port0; - u32 emph_lev_sel_port1; - u8 xaui_vo_sel; - u8 xaui_state; - u16 rsvd0; - u32 xaui_eq_vector; -} __packed; - -struct FWCMD_COMMON_ANON_262_REQUEST { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_261_PARAMS { - struct FWCMD_COMMON_ANON_262_REQUEST request; - struct FWCMD_COMMON_PORT_EQUALIZATION_PARAMS response; -} __packed; - -/* - * This comand can be used to read XAUI equalization parameters. The - * ARM firmware applies default equalization parameters during initialization. - * These parameters may be customer-specific when derived from the - * SEEPROM. See SEEPROM_DATA for equalization specific fields. - */ -struct FWCMD_COMMON_GET_PORT_EQUALIZATION { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_261_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_264_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_263_PARAMS { - struct FWCMD_COMMON_PORT_EQUALIZATION_PARAMS request; - struct FWCMD_COMMON_ANON_264_RESPONSE response; -} __packed; - -/* - * This comand can be used to set XAUI equalization parameters. The ARM - * firmware applies default equalization parameters during initialization. - * These parameters may be customer-specific when derived from the - * SEEPROM. See SEEPROM_DATA for equalization specific fields. - */ -struct FWCMD_COMMON_SET_PORT_EQUALIZATION { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_263_PARAMS params; -} __packed; - -#endif /* __fwcmd_common_bmap_h__ */ diff --git a/drivers/staging/benet/fwcmd_eth_bmap.h b/drivers/staging/benet/fwcmd_eth_bmap.h deleted file mode 100644 index 234b179eace..00000000000 --- a/drivers/staging/benet/fwcmd_eth_bmap.h +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_eth_bmap_h__ -#define __fwcmd_eth_bmap_h__ -#include "fwcmd_hdr_bmap.h" -#include "fwcmd_types_bmap.h" - -struct MIB_ETH_STATISTICS_PARAMS_IN { - u32 rsvd0; -} __packed; - -struct BE_RXF_STATS { - u32 p0recvdtotalbytesLSD; /* DWORD 0 */ - u32 p0recvdtotalbytesMSD; /* DWORD 1 */ - u32 p0recvdtotalframes; /* DWORD 2 */ - u32 p0recvdunicastframes; /* DWORD 3 */ - u32 p0recvdmulticastframes; /* DWORD 4 */ - u32 p0recvdbroadcastframes; /* DWORD 5 */ - u32 p0crcerrors; /* DWORD 6 */ - u32 p0alignmentsymerrs; /* DWORD 7 */ - u32 p0pauseframesrecvd; /* DWORD 8 */ - u32 p0controlframesrecvd; /* DWORD 9 */ - u32 p0inrangelenerrors; /* DWORD 10 */ - u32 p0outrangeerrors; /* DWORD 11 */ - u32 p0frametoolongerrors; /* DWORD 12 */ - u32 p0droppedaddressmatch; /* DWORD 13 */ - u32 p0droppedvlanmismatch; /* DWORD 14 */ - u32 p0ipdroppedtoosmall; /* DWORD 15 */ - u32 p0ipdroppedtooshort; /* DWORD 16 */ - u32 p0ipdroppedhdrtoosmall; /* DWORD 17 */ - u32 p0tcpdroppedlen; /* DWORD 18 */ - u32 p0droppedrunt; /* DWORD 19 */ - u32 p0recvd64; /* DWORD 20 */ - u32 p0recvd65_127; /* DWORD 21 */ - u32 p0recvd128_256; /* DWORD 22 */ - u32 p0recvd256_511; /* DWORD 23 */ - u32 p0recvd512_1023; /* DWORD 24 */ - u32 p0recvd1518_1522; /* DWORD 25 */ - u32 p0recvd1522_2047; /* DWORD 26 */ - u32 p0recvd2048_4095; /* DWORD 27 */ - u32 p0recvd4096_8191; /* DWORD 28 */ - u32 p0recvd8192_9216; /* DWORD 29 */ - u32 p0rcvdipcksmerrs; /* DWORD 30 */ - u32 p0recvdtcpcksmerrs; /* DWORD 31 */ - u32 p0recvdudpcksmerrs; /* DWORD 32 */ - u32 p0recvdnonrsspackets; /* DWORD 33 */ - u32 p0recvdippackets; /* DWORD 34 */ - u32 p0recvdchute1packets; /* DWORD 35 */ - u32 p0recvdchute2packets; /* DWORD 36 */ - u32 p0recvdchute3packets; /* DWORD 37 */ - u32 p0recvdipsecpackets; /* DWORD 38 */ - u32 p0recvdmanagementpackets; /* DWORD 39 */ - u32 p0xmitbyteslsd; /* DWORD 40 */ - u32 p0xmitbytesmsd; /* DWORD 41 */ - u32 p0xmitunicastframes; /* DWORD 42 */ - u32 p0xmitmulticastframes; /* DWORD 43 */ - u32 p0xmitbroadcastframes; /* DWORD 44 */ - u32 p0xmitpauseframes; /* DWORD 45 */ - u32 p0xmitcontrolframes; /* DWORD 46 */ - u32 p0xmit64; /* DWORD 47 */ - u32 p0xmit65_127; /* DWORD 48 */ - u32 p0xmit128_256; /* DWORD 49 */ - u32 p0xmit256_511; /* DWORD 50 */ - u32 p0xmit512_1023; /* DWORD 51 */ - u32 p0xmit1518_1522; /* DWORD 52 */ - u32 p0xmit1522_2047; /* DWORD 53 */ - u32 p0xmit2048_4095; /* DWORD 54 */ - u32 p0xmit4096_8191; /* DWORD 55 */ - u32 p0xmit8192_9216; /* DWORD 56 */ - u32 p0rxfifooverflowdropped; /* DWORD 57 */ - u32 p0ipseclookupfaileddropped; /* DWORD 58 */ - u32 p1recvdtotalbytesLSD; /* DWORD 59 */ - u32 p1recvdtotalbytesMSD; /* DWORD 60 */ - u32 p1recvdtotalframes; /* DWORD 61 */ - u32 p1recvdunicastframes; /* DWORD 62 */ - u32 p1recvdmulticastframes; /* DWORD 63 */ - u32 p1recvdbroadcastframes; /* DWORD 64 */ - u32 p1crcerrors; /* DWORD 65 */ - u32 p1alignmentsymerrs; /* DWORD 66 */ - u32 p1pauseframesrecvd; /* DWORD 67 */ - u32 p1controlframesrecvd; /* DWORD 68 */ - u32 p1inrangelenerrors; /* DWORD 69 */ - u32 p1outrangeerrors; /* DWORD 70 */ - u32 p1frametoolongerrors; /* DWORD 71 */ - u32 p1droppedaddressmatch; /* DWORD 72 */ - u32 p1droppedvlanmismatch; /* DWORD 73 */ - u32 p1ipdroppedtoosmall; /* DWORD 74 */ - u32 p1ipdroppedtooshort; /* DWORD 75 */ - u32 p1ipdroppedhdrtoosmall; /* DWORD 76 */ - u32 p1tcpdroppedlen; /* DWORD 77 */ - u32 p1droppedrunt; /* DWORD 78 */ - u32 p1recvd64; /* DWORD 79 */ - u32 p1recvd65_127; /* DWORD 80 */ - u32 p1recvd128_256; /* DWORD 81 */ - u32 p1recvd256_511; /* DWORD 82 */ - u32 p1recvd512_1023; /* DWORD 83 */ - u32 p1recvd1518_1522; /* DWORD 84 */ - u32 p1recvd1522_2047; /* DWORD 85 */ - u32 p1recvd2048_4095; /* DWORD 86 */ - u32 p1recvd4096_8191; /* DWORD 87 */ - u32 p1recvd8192_9216; /* DWORD 88 */ - u32 p1rcvdipcksmerrs; /* DWORD 89 */ - u32 p1recvdtcpcksmerrs; /* DWORD 90 */ - u32 p1recvdudpcksmerrs; /* DWORD 91 */ - u32 p1recvdnonrsspackets; /* DWORD 92 */ - u32 p1recvdippackets; /* DWORD 93 */ - u32 p1recvdchute1packets; /* DWORD 94 */ - u32 p1recvdchute2packets; /* DWORD 95 */ - u32 p1recvdchute3packets; /* DWORD 96 */ - u32 p1recvdipsecpackets; /* DWORD 97 */ - u32 p1recvdmanagementpackets; /* DWORD 98 */ - u32 p1xmitbyteslsd; /* DWORD 99 */ - u32 p1xmitbytesmsd; /* DWORD 100 */ - u32 p1xmitunicastframes; /* DWORD 101 */ - u32 p1xmitmulticastframes; /* DWORD 102 */ - u32 p1xmitbroadcastframes; /* DWORD 103 */ - u32 p1xmitpauseframes; /* DWORD 104 */ - u32 p1xmitcontrolframes; /* DWORD 105 */ - u32 p1xmit64; /* DWORD 106 */ - u32 p1xmit65_127; /* DWORD 107 */ - u32 p1xmit128_256; /* DWORD 108 */ - u32 p1xmit256_511; /* DWORD 109 */ - u32 p1xmit512_1023; /* DWORD 110 */ - u32 p1xmit1518_1522; /* DWORD 111 */ - u32 p1xmit1522_2047; /* DWORD 112 */ - u32 p1xmit2048_4095; /* DWORD 113 */ - u32 p1xmit4096_8191; /* DWORD 114 */ - u32 p1xmit8192_9216; /* DWORD 115 */ - u32 p1rxfifooverflowdropped; /* DWORD 116 */ - u32 p1ipseclookupfaileddropped; /* DWORD 117 */ - u32 pxdroppednopbuf; /* DWORD 118 */ - u32 pxdroppednotxpb; /* DWORD 119 */ - u32 pxdroppednoipsecbuf; /* DWORD 120 */ - u32 pxdroppednoerxdescr; /* DWORD 121 */ - u32 pxdroppednotpredescr; /* DWORD 122 */ - u32 pxrecvdmanagementportpackets; /* DWORD 123 */ - u32 pxrecvdmanagementportbytes; /* DWORD 124 */ - u32 pxrecvdmanagementportpauseframes; /* DWORD 125 */ - u32 pxrecvdmanagementporterrors; /* DWORD 126 */ - u32 pxxmitmanagementportpackets; /* DWORD 127 */ - u32 pxxmitmanagementportbytes; /* DWORD 128 */ - u32 pxxmitmanagementportpause; /* DWORD 129 */ - u32 pxxmitmanagementportrxfifooverflow; /* DWORD 130 */ - u32 pxrecvdipsecipcksmerrs; /* DWORD 131 */ - u32 pxrecvdtcpsecipcksmerrs; /* DWORD 132 */ - u32 pxrecvdudpsecipcksmerrs; /* DWORD 133 */ - u32 pxipsecrunt; /* DWORD 134 */ - u32 pxipsecaddressmismatchdropped; /* DWORD 135 */ - u32 pxipsecrxfifooverflowdropped; /* DWORD 136 */ - u32 pxipsecframestoolong; /* DWORD 137 */ - u32 pxipsectotalipframes; /* DWORD 138 */ - u32 pxipseciptoosmall; /* DWORD 139 */ - u32 pxipseciptooshort; /* DWORD 140 */ - u32 pxipseciphdrtoosmall; /* DWORD 141 */ - u32 pxipsectcphdrbad; /* DWORD 142 */ - u32 pxrecvdipsecchute1; /* DWORD 143 */ - u32 pxrecvdipsecchute2; /* DWORD 144 */ - u32 pxrecvdipsecchute3; /* DWORD 145 */ - u32 pxdropped7frags; /* DWORD 146 */ - u32 pxdroppedfrags; /* DWORD 147 */ - u32 pxdroppedinvalidfragring; /* DWORD 148 */ - u32 pxnumforwardedpackets; /* DWORD 149 */ -} __packed; - -union MIB_ETH_STATISTICS_PARAMS { - struct MIB_ETH_STATISTICS_PARAMS_IN request; - struct BE_RXF_STATS response; -} __packed; - -/* - * Query ethernet statistics. All domains may issue this command. The - * host domain drivers may optionally reset internal statistic counters - * with a query. - */ -struct FWCMD_ETH_GET_STATISTICS { - union FWCMD_HEADER header; - union MIB_ETH_STATISTICS_PARAMS params; -} __packed; - - -struct FWCMD_ETH_ANON_175_REQUEST { - u8 port0_promiscuous; - u8 port1_promiscuous; - u16 rsvd0; -} __packed; - -struct FWCMD_ETH_ANON_176_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_ETH_ANON_174_PARAMS { - struct FWCMD_ETH_ANON_175_REQUEST request; - struct FWCMD_ETH_ANON_176_RESPONSE response; -} __packed; - -/* Enables/Disables promiscuous ethernet receive mode. */ -struct FWCMD_ETH_PROMISCUOUS { - union FWCMD_HEADER header; - union FWCMD_ETH_ANON_174_PARAMS params; -} __packed; - -struct FWCMD_ETH_ANON_178_REQUEST { - u32 new_fragsize_log2; -} __packed; - -struct FWCMD_ETH_ANON_179_RESPONSE { - u32 actual_fragsize_log2; -} __packed; - -union FWCMD_ETH_ANON_177_PARAMS { - struct FWCMD_ETH_ANON_178_REQUEST request; - struct FWCMD_ETH_ANON_179_RESPONSE response; -} __packed; - -/* - * Sets the Ethernet RX fragment size. Only host (domain 0) networking - * drivers may issue this command. This call will fail for non-host - * protection domains. In this situation the MCC CQ status will indicate - * a failure due to insufficient priviledges. The response should be - * ignored, and the driver should use the FWCMD_ETH_GET_FRAG_SIZE to - * query the existing ethernet receive fragment size. It must use this - * fragment size for all fragments in the ethernet receive ring. If - * the command succeeds, the driver must use the frag size indicated - * in the command response since the requested frag size may not be applied - * until the next reboot. When the requested fragsize matches the response - * fragsize, this indicates the request was applied immediately. - */ -struct FWCMD_ETH_SET_RX_FRAG_SIZE { - union FWCMD_HEADER header; - union FWCMD_ETH_ANON_177_PARAMS params; -} __packed; - -struct FWCMD_ETH_ANON_181_REQUEST { - u32 rsvd0; -} __packed; - -struct FWCMD_ETH_ANON_182_RESPONSE { - u32 actual_fragsize_log2; -} __packed; - -union FWCMD_ETH_ANON_180_PARAMS { - struct FWCMD_ETH_ANON_181_REQUEST request; - struct FWCMD_ETH_ANON_182_RESPONSE response; -} __packed; - -/* - * Queries the Ethernet RX fragment size. All domains may issue this - * command. The driver should call this command to determine the minimum - * required fragment size for the ethernet RX ring buffers. Drivers - * may choose to use a larger size for each fragment buffer, but BladeEngine - * will use up to the configured minimum required fragsize in each ethernet - * receive fragment buffer. For example, if the ethernet receive fragment - * size is configured to 4kB, and a driver uses 8kB fragments, a 6kB - * ethernet packet received by BladeEngine will be split accross two - * of the driver's receive framgents (4kB in one fragment buffer, and - * 2kB in the subsequent fragment buffer). - */ -struct FWCMD_ETH_GET_RX_FRAG_SIZE { - union FWCMD_HEADER header; - union FWCMD_ETH_ANON_180_PARAMS params; -} __packed; - -#endif /* __fwcmd_eth_bmap_h__ */ diff --git a/drivers/staging/benet/fwcmd_hdr_bmap.h b/drivers/staging/benet/fwcmd_hdr_bmap.h deleted file mode 100644 index 28b45328fe7..00000000000 --- a/drivers/staging/benet/fwcmd_hdr_bmap.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_hdr_bmap_h__ -#define __fwcmd_hdr_bmap_h__ - -struct FWCMD_REQUEST_HEADER { - u8 opcode; - u8 subsystem; - u8 port_number; - u8 domain; - u32 timeout; - u32 request_length; - u32 rsvd0; -} __packed; - -struct FWCMD_RESPONSE_HEADER { - u8 opcode; - u8 subsystem; - u8 rsvd0; - u8 domain; - u8 status; - u8 additional_status; - u16 rsvd1; - u32 response_length; - u32 actual_response_length; -} __packed; - -/* - * The firmware/driver overwrites the input FWCMD_REQUEST_HEADER with - * the output FWCMD_RESPONSE_HEADER. - */ -union FWCMD_HEADER { - struct FWCMD_REQUEST_HEADER request; - struct FWCMD_RESPONSE_HEADER response; -} __packed; - -#endif /* __fwcmd_hdr_bmap_h__ */ diff --git a/drivers/staging/benet/fwcmd_mcc.h b/drivers/staging/benet/fwcmd_mcc.h deleted file mode 100644 index 9eeca878c1f..00000000000 --- a/drivers/staging/benet/fwcmd_mcc.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_mcc_amap_h__ -#define __fwcmd_mcc_amap_h__ -#include "fwcmd_opcodes.h" -/* - * Where applicable, a WRB, may contain a list of Scatter-gather elements. - * Each element supports a 64 bit address and a 32bit length field. - */ -struct BE_MCC_SGE_AMAP { - u8 pa_lo[32]; /* DWORD 0 */ - u8 pa_hi[32]; /* DWORD 1 */ - u8 length[32]; /* DWORD 2 */ -} __packed; -struct MCC_SGE_AMAP { - u32 dw[3]; -}; -/* - * The design of an MCC_SGE allows up to 19 elements to be embedded - * in a WRB, supporting 64KB data transfers (assuming a 4KB page size). - */ -struct BE_MCC_WRB_PAYLOAD_AMAP { - union { - struct BE_MCC_SGE_AMAP sgl[19]; - u8 embedded[59][32]; /* DWORD 0 */ - }; -} __packed; -struct MCC_WRB_PAYLOAD_AMAP { - u32 dw[59]; -}; - -/* - * This is the structure of the MCC Command WRB for commands - * sent to the Management Processing Unit (MPU). See section - * for usage in embedded and non-embedded modes. - */ -struct BE_MCC_WRB_AMAP { - u8 embedded; /* DWORD 0 */ - u8 rsvd0[2]; /* DWORD 0 */ - u8 sge_count[5]; /* DWORD 0 */ - u8 rsvd1[16]; /* DWORD 0 */ - u8 special[8]; /* DWORD 0 */ - u8 payload_length[32]; /* DWORD 1 */ - u8 tag[2][32]; /* DWORD 2 */ - u8 rsvd2[32]; /* DWORD 4 */ - struct BE_MCC_WRB_PAYLOAD_AMAP payload; -} __packed; -struct MCC_WRB_AMAP { - u32 dw[64]; -}; - -/* This is the structure of the MCC Completion queue entry */ -struct BE_MCC_CQ_ENTRY_AMAP { - u8 completion_status[16]; /* DWORD 0 */ - u8 extended_status[16]; /* DWORD 0 */ - u8 mcc_tag[2][32]; /* DWORD 1 */ - u8 rsvd0[27]; /* DWORD 3 */ - u8 consumed; /* DWORD 3 */ - u8 completed; /* DWORD 3 */ - u8 hpi_buffer_completion; /* DWORD 3 */ - u8 async_event; /* DWORD 3 */ - u8 valid; /* DWORD 3 */ -} __packed; -struct MCC_CQ_ENTRY_AMAP { - u32 dw[4]; -}; - -/* Mailbox structures used by the MPU during bootstrap */ -struct BE_MCC_MAILBOX_AMAP { - struct BE_MCC_WRB_AMAP wrb; - struct BE_MCC_CQ_ENTRY_AMAP cq; -} __packed; -struct MCC_MAILBOX_AMAP { - u32 dw[68]; -}; - -#endif /* __fwcmd_mcc_amap_h__ */ diff --git a/drivers/staging/benet/fwcmd_opcodes.h b/drivers/staging/benet/fwcmd_opcodes.h deleted file mode 100644 index 23d569386b4..00000000000 --- a/drivers/staging/benet/fwcmd_opcodes.h +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_opcodes_amap_h__ -#define __fwcmd_opcodes_amap_h__ - -/* - * --- FWCMD_SUBSYSTEMS --- - * The commands are grouped into the following subsystems. The subsystem - * code along with the opcode uniquely identify a particular fwcmd. - */ -#define FWCMD_SUBSYSTEM_RSVD (0) /* This subsystem is reserved. It is */ - /* never used. */ -#define FWCMD_SUBSYSTEM_COMMON (1) /* CMDs in this group are common to - * all subsystems. See - * COMMON_SUBSYSTEM_OPCODES for opcodes - * and Common Host Configuration CMDs - * for the FWCMD descriptions. - */ -#define FWCMD_SUBSYSTEM_COMMON_ISCSI (2) /* CMDs in this group are */ - /* - * common to Initiator and Target. See - * COMMON_ISCSI_SUBSYSTEM_OPCODES and - * Common iSCSI Initiator and Target - * CMDs for the command descriptions. - */ -#define FWCMD_SUBSYSTEM_ETH (3) /* This subsystem is used to - execute Ethernet commands. */ - -#define FWCMD_SUBSYSTEM_TPM (4) /* This subsystem is used - to execute TPM commands. */ -#define FWCMD_SUBSYSTEM_PXE_UNDI (5) /* This subsystem is used - * to execute PXE - * and UNDI specific commands. - */ - -#define FWCMD_SUBSYSTEM_ISCSI_INI (6) /* This subsystem is used to - execute ISCSI Initiator - specific commands. - */ -#define FWCMD_SUBSYSTEM_ISCSI_TGT (7) /* This subsystem is used - to execute iSCSI Target - specific commands.between - PTL and ARM firmware. - */ -#define FWCMD_SUBSYSTEM_MILI_PTL (8) /* This subsystem is used to - execute iSCSI Target specific - commands.between MILI - and PTL. */ -#define FWCMD_SUBSYSTEM_MILI_TMD (9) /* This subsystem is used to - execute iSCSI Target specific - commands between MILI - and TMD. */ -#define FWCMD_SUBSYSTEM_PROXY (11) /* This subsystem is used - to execute proxied commands - within the host at the - explicit request of a - non priviledged domain. - This 'subsystem' is entirely - virtual from the controller - and firmware perspective as - it is implemented in host - drivers. - */ - -/* - * --- COMMON_SUBSYSTEM_OPCODES --- - * These opcodes are common to both networking and storage PCI - * functions. They are used to reserve resources and configure - * BladeEngine. These opcodes all use the FWCMD_SUBSYSTEM_COMMON - * subsystem code. - */ -#define OPCODE_COMMON_NTWK_MAC_QUERY (1) -#define SUBSYSTEM_COMMON_NTWK_MAC_QUERY (1) -#define SUBSYSTEM_COMMON_NTWK_MAC_SET (1) -#define SUBSYSTEM_COMMON_NTWK_MULTICAST_SET (1) -#define SUBSYSTEM_COMMON_NTWK_VLAN_CONFIG (1) -#define SUBSYSTEM_COMMON_NTWK_LINK_STATUS_QUERY (1) -#define SUBSYSTEM_COMMON_READ_FLASHROM (1) -#define SUBSYSTEM_COMMON_WRITE_FLASHROM (1) -#define SUBSYSTEM_COMMON_QUERY_MAX_FWCMD_BUFFER_SIZE (1) -#define SUBSYSTEM_COMMON_ADD_PAGE_TABLES (1) -#define SUBSYSTEM_COMMON_REMOVE_PAGE_TABLES (1) -#define SUBSYSTEM_COMMON_RING_DESTROY (1) -#define SUBSYSTEM_COMMON_CQ_CREATE (1) -#define SUBSYSTEM_COMMON_EQ_CREATE (1) -#define SUBSYSTEM_COMMON_ETH_RX_CREATE (1) -#define SUBSYSTEM_COMMON_ETH_TX_CREATE (1) -#define SUBSYSTEM_COMMON_ISCSI_DEFQ_CREATE (1) -#define SUBSYSTEM_COMMON_ISCSI_WRBQ_CREATE (1) -#define SUBSYSTEM_COMMON_MCC_CREATE (1) -#define SUBSYSTEM_COMMON_JELL_CONFIG (1) -#define SUBSYSTEM_COMMON_FORCE_FAILOVER (1) -#define SUBSYSTEM_COMMON_ADD_TEMPLATE_HEADER_BUFFERS (1) -#define SUBSYSTEM_COMMON_REMOVE_TEMPLATE_HEADER_BUFFERS (1) -#define SUBSYSTEM_COMMON_POST_ZERO_BUFFER (1) -#define SUBSYSTEM_COMMON_GET_QOS (1) -#define SUBSYSTEM_COMMON_SET_QOS (1) -#define SUBSYSTEM_COMMON_TCP_GET_STATISTICS (1) -#define SUBSYSTEM_COMMON_SEEPROM_READ (1) -#define SUBSYSTEM_COMMON_TCP_STATE_QUERY (1) -#define SUBSYSTEM_COMMON_GET_CNTL_ATTRIBUTES (1) -#define SUBSYSTEM_COMMON_NOP (1) -#define SUBSYSTEM_COMMON_NTWK_RX_FILTER (1) -#define SUBSYSTEM_COMMON_GET_FW_VERSION (1) -#define SUBSYSTEM_COMMON_SET_FLOW_CONTROL (1) -#define SUBSYSTEM_COMMON_GET_FLOW_CONTROL (1) -#define SUBSYSTEM_COMMON_SET_TCP_PARAMETERS (1) -#define SUBSYSTEM_COMMON_SET_FRAME_SIZE (1) -#define SUBSYSTEM_COMMON_GET_FAT (1) -#define SUBSYSTEM_COMMON_MODIFY_EQ_DELAY (1) -#define SUBSYSTEM_COMMON_FIRMWARE_CONFIG (1) -#define SUBSYSTEM_COMMON_ENABLE_DISABLE_DOMAINS (1) -#define SUBSYSTEM_COMMON_GET_DOMAIN_CONFIG (1) -#define SUBSYSTEM_COMMON_SET_VLD_CONFIG (1) -#define SUBSYSTEM_COMMON_GET_VLD_CONFIG (1) -#define SUBSYSTEM_COMMON_GET_PORT_EQUALIZATION (1) -#define SUBSYSTEM_COMMON_SET_PORT_EQUALIZATION (1) -#define SUBSYSTEM_COMMON_RED_CONFIG (1) -#define OPCODE_COMMON_NTWK_MAC_SET (2) -#define OPCODE_COMMON_NTWK_MULTICAST_SET (3) -#define OPCODE_COMMON_NTWK_VLAN_CONFIG (4) -#define OPCODE_COMMON_NTWK_LINK_STATUS_QUERY (5) -#define OPCODE_COMMON_READ_FLASHROM (6) -#define OPCODE_COMMON_WRITE_FLASHROM (7) -#define OPCODE_COMMON_QUERY_MAX_FWCMD_BUFFER_SIZE (8) -#define OPCODE_COMMON_ADD_PAGE_TABLES (9) -#define OPCODE_COMMON_REMOVE_PAGE_TABLES (10) -#define OPCODE_COMMON_RING_DESTROY (11) -#define OPCODE_COMMON_CQ_CREATE (12) -#define OPCODE_COMMON_EQ_CREATE (13) -#define OPCODE_COMMON_ETH_RX_CREATE (14) -#define OPCODE_COMMON_ETH_TX_CREATE (15) -#define OPCODE_COMMON_NET_RESERVED0 (16) /* Reserved */ -#define OPCODE_COMMON_NET_RESERVED1 (17) /* Reserved */ -#define OPCODE_COMMON_NET_RESERVED2 (18) /* Reserved */ -#define OPCODE_COMMON_ISCSI_DEFQ_CREATE (19) -#define OPCODE_COMMON_ISCSI_WRBQ_CREATE (20) -#define OPCODE_COMMON_MCC_CREATE (21) -#define OPCODE_COMMON_JELL_CONFIG (22) -#define OPCODE_COMMON_FORCE_FAILOVER (23) -#define OPCODE_COMMON_ADD_TEMPLATE_HEADER_BUFFERS (24) -#define OPCODE_COMMON_REMOVE_TEMPLATE_HEADER_BUFFERS (25) -#define OPCODE_COMMON_POST_ZERO_BUFFER (26) -#define OPCODE_COMMON_GET_QOS (27) -#define OPCODE_COMMON_SET_QOS (28) -#define OPCODE_COMMON_TCP_GET_STATISTICS (29) -#define OPCODE_COMMON_SEEPROM_READ (30) -#define OPCODE_COMMON_TCP_STATE_QUERY (31) -#define OPCODE_COMMON_GET_CNTL_ATTRIBUTES (32) -#define OPCODE_COMMON_NOP (33) -#define OPCODE_COMMON_NTWK_RX_FILTER (34) -#define OPCODE_COMMON_GET_FW_VERSION (35) -#define OPCODE_COMMON_SET_FLOW_CONTROL (36) -#define OPCODE_COMMON_GET_FLOW_CONTROL (37) -#define OPCODE_COMMON_SET_TCP_PARAMETERS (38) -#define OPCODE_COMMON_SET_FRAME_SIZE (39) -#define OPCODE_COMMON_GET_FAT (40) -#define OPCODE_COMMON_MODIFY_EQ_DELAY (41) -#define OPCODE_COMMON_FIRMWARE_CONFIG (42) -#define OPCODE_COMMON_ENABLE_DISABLE_DOMAINS (43) -#define OPCODE_COMMON_GET_DOMAIN_CONFIG (44) -#define OPCODE_COMMON_SET_VLD_CONFIG (45) -#define OPCODE_COMMON_GET_VLD_CONFIG (46) -#define OPCODE_COMMON_GET_PORT_EQUALIZATION (47) -#define OPCODE_COMMON_SET_PORT_EQUALIZATION (48) -#define OPCODE_COMMON_RED_CONFIG (49) - - - -/* - * --- ETH_SUBSYSTEM_OPCODES --- - * These opcodes are used for configuring the Ethernet interfaces. These - * opcodes all use the FWCMD_SUBSYSTEM_ETH subsystem code. - */ -#define OPCODE_ETH_RSS_CONFIG (1) -#define OPCODE_ETH_ACPI_CONFIG (2) -#define SUBSYSTEM_ETH_RSS_CONFIG (3) -#define SUBSYSTEM_ETH_ACPI_CONFIG (3) -#define OPCODE_ETH_PROMISCUOUS (3) -#define SUBSYSTEM_ETH_PROMISCUOUS (3) -#define SUBSYSTEM_ETH_GET_STATISTICS (3) -#define SUBSYSTEM_ETH_GET_RX_FRAG_SIZE (3) -#define SUBSYSTEM_ETH_SET_RX_FRAG_SIZE (3) -#define OPCODE_ETH_GET_STATISTICS (4) -#define OPCODE_ETH_GET_RX_FRAG_SIZE (5) -#define OPCODE_ETH_SET_RX_FRAG_SIZE (6) - - - - - -/* - * --- MCC_STATUS_CODE --- - * These are the global status codes used by all subsystems - */ -#define MCC_STATUS_SUCCESS (0) /* Indicates a successful - completion of the command */ -#define MCC_STATUS_INSUFFICIENT_PRIVILEGES (1) /* The client does not have - sufficient privileges to - execute the command */ -#define MCC_STATUS_INVALID_PARAMETER (2) /* A parameter in the command - was invalid. The extended - status contains the index - of the parameter */ -#define MCC_STATUS_INSUFFICIENT_RESOURCES (3) /* There are insufficient - chip resources to execute - the command */ -#define MCC_STATUS_QUEUE_FLUSHING (4) /* The command is completing - because the queue was - getting flushed */ -#define MCC_STATUS_DMA_FAILED (5) /* The command is completing - with a DMA error */ - -/* - * --- MGMT_ERROR_CODES --- - * Error Codes returned in the status field of the FWCMD response header - */ -#define MGMT_STATUS_SUCCESS (0) /* The FWCMD completed - without errors */ -#define MGMT_STATUS_FAILED (1) /* Error status in the Status - field of the - struct FWCMD_RESPONSE_HEADER */ -#define MGMT_STATUS_ILLEGAL_REQUEST (2) /* Invalid FWCMD opcode */ -#define MGMT_STATUS_ILLEGAL_FIELD (3) /* Invalid parameter in - the FWCMD payload */ - -#endif /* __fwcmd_opcodes_amap_h__ */ diff --git a/drivers/staging/benet/fwcmd_types_bmap.h b/drivers/staging/benet/fwcmd_types_bmap.h deleted file mode 100644 index 92217aff3a1..00000000000 --- a/drivers/staging/benet/fwcmd_types_bmap.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_types_bmap_h__ -#define __fwcmd_types_bmap_h__ - -/* MAC address format */ -struct MAC_ADDRESS_FORMAT { - u16 SizeOfStructure; - u8 MACAddress[6]; -} __packed; - -#endif /* __fwcmd_types_bmap_h__ */ diff --git a/drivers/staging/benet/host_struct.h b/drivers/staging/benet/host_struct.h deleted file mode 100644 index 3de6722b980..00000000000 --- a/drivers/staging/benet/host_struct.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __host_struct_amap_h__ -#define __host_struct_amap_h__ -#include "be_cm.h" -#include "be_common.h" -#include "descriptors.h" - -/* --- EQ_COMPLETION_MAJOR_CODE_ENUM --- */ -#define EQ_MAJOR_CODE_COMPLETION (0) /* Completion event on a */ - /* qcompletion ueue. */ -#define EQ_MAJOR_CODE_ETH (1) /* Affiliated Ethernet Event. */ -#define EQ_MAJOR_CODE_RESERVED (2) /* Reserved */ -#define EQ_MAJOR_CODE_RDMA (3) /* Affiliated RDMA Event. */ -#define EQ_MAJOR_CODE_ISCSI (4) /* Affiliated ISCSI Event */ -#define EQ_MAJOR_CODE_UNAFFILIATED (5) /* Unaffiliated Event */ - -/* --- EQ_COMPLETION_MINOR_CODE_ENUM --- */ -#define EQ_MINOR_CODE_COMPLETION (0) /* Completion event on a */ - /* completion queue. */ -#define EQ_MINOR_CODE_OTHER (1) /* Other Event (TBD). */ - -/* Queue Entry Definition for all 4 byte event queue types. */ -struct BE_EQ_ENTRY_AMAP { - u8 Valid; /* DWORD 0 */ - u8 MajorCode[3]; /* DWORD 0 */ - u8 MinorCode[12]; /* DWORD 0 */ - u8 ResourceID[16]; /* DWORD 0 */ -} __packed; -struct EQ_ENTRY_AMAP { - u32 dw[1]; -}; - -/* - * --- ETH_EVENT_CODE --- - * These codes are returned by the MPU when one of these events has occurred, - * and the event is configured to report to an Event Queue when an event - * is detected. - */ -#define ETH_EQ_LINK_STATUS (0) /* Link status change event */ - /* detected. */ -#define ETH_EQ_WATERMARK (1) /* watermark event detected. */ -#define ETH_EQ_MAGIC_PKT (2) /* magic pkt event detected. */ -#define ETH_EQ_ACPI_PKT0 (3) /* ACPI interesting packet */ - /* detected. */ -#define ETH_EQ_ACPI_PKT1 (3) /* ACPI interesting packet */ - /* detected. */ -#define ETH_EQ_ACPI_PKT2 (3) /* ACPI interesting packet */ - /* detected. */ -#define ETH_EQ_ACPI_PKT3 (3) /* ACPI interesting packet */ - /* detected. */ - -/* - * --- ETH_TX_COMPL_STATUS_ENUM --- - * Status codes contained in Ethernet TX completion descriptors. - */ -#define ETH_COMP_VALID (0) -#define ETH_COMP_ERROR (1) -#define ETH_COMP_INVALID (15) - -/* - * --- ETH_TX_COMPL_PORT_ENUM --- - * Port indicator contained in Ethernet TX completion descriptors. - */ -#define ETH_COMP_PORT0 (0) -#define ETH_COMP_PORT1 (1) -#define ETH_COMP_MGMT (2) - -/* - * --- ETH_TX_COMPL_CT_ENUM --- - * Completion type indicator contained in Ethernet TX completion descriptors. - */ -#define ETH_COMP_ETH (0) - -/* - * Work request block that the driver issues to the chip for - * Ethernet transmissions. All control fields must be valid in each WRB for - * a message. The controller, as specified by the flags, optionally writes - * an entry to the Completion Ring and generate an event. - */ -struct BE_ETH_WRB_AMAP { - u8 frag_pa_hi[32]; /* DWORD 0 */ - u8 frag_pa_lo[32]; /* DWORD 1 */ - u8 complete; /* DWORD 2 */ - u8 event; /* DWORD 2 */ - u8 crc; /* DWORD 2 */ - u8 forward; /* DWORD 2 */ - u8 ipsec; /* DWORD 2 */ - u8 mgmt; /* DWORD 2 */ - u8 ipcs; /* DWORD 2 */ - u8 udpcs; /* DWORD 2 */ - u8 tcpcs; /* DWORD 2 */ - u8 lso; /* DWORD 2 */ - u8 last; /* DWORD 2 */ - u8 vlan; /* DWORD 2 */ - u8 dbg[3]; /* DWORD 2 */ - u8 hash_val[3]; /* DWORD 2 */ - u8 lso_mss[14]; /* DWORD 2 */ - u8 frag_len[16]; /* DWORD 3 */ - u8 vlan_tag[16]; /* DWORD 3 */ -} __packed; -struct ETH_WRB_AMAP { - u32 dw[4]; -}; - -/* This is an Ethernet transmit completion descriptor */ -struct BE_ETH_TX_COMPL_AMAP { - u8 user_bytes[16]; /* DWORD 0 */ - u8 nwh_bytes[8]; /* DWORD 0 */ - u8 lso; /* DWORD 0 */ - u8 rsvd0[7]; /* DWORD 0 */ - u8 wrb_index[16]; /* DWORD 1 */ - u8 ct[2]; /* DWORD 1 */ - u8 port[2]; /* DWORD 1 */ - u8 rsvd1[8]; /* DWORD 1 */ - u8 status[4]; /* DWORD 1 */ - u8 rsvd2[16]; /* DWORD 2 */ - u8 ringid[11]; /* DWORD 2 */ - u8 hash_val[4]; /* DWORD 2 */ - u8 valid; /* DWORD 2 */ - u8 rsvd3[32]; /* DWORD 3 */ -} __packed; -struct ETH_TX_COMPL_AMAP { - u32 dw[4]; -}; - -/* Ethernet Receive Buffer descriptor */ -struct BE_ETH_RX_D_AMAP { - u8 fragpa_hi[32]; /* DWORD 0 */ - u8 fragpa_lo[32]; /* DWORD 1 */ -} __packed; -struct ETH_RX_D_AMAP { - u32 dw[2]; -}; - -/* This is an Ethernet Receive Completion Descriptor */ -struct BE_ETH_RX_COMPL_AMAP { - u8 vlan_tag[16]; /* DWORD 0 */ - u8 pktsize[14]; /* DWORD 0 */ - u8 port; /* DWORD 0 */ - u8 rsvd0; /* DWORD 0 */ - u8 err; /* DWORD 1 */ - u8 rsshp; /* DWORD 1 */ - u8 ipf; /* DWORD 1 */ - u8 tcpf; /* DWORD 1 */ - u8 udpf; /* DWORD 1 */ - u8 ipcksm; /* DWORD 1 */ - u8 tcpcksm; /* DWORD 1 */ - u8 udpcksm; /* DWORD 1 */ - u8 macdst[6]; /* DWORD 1 */ - u8 vtp; /* DWORD 1 */ - u8 vtm; /* DWORD 1 */ - u8 fragndx[10]; /* DWORD 1 */ - u8 ct[2]; /* DWORD 1 */ - u8 ipsec; /* DWORD 1 */ - u8 numfrags[3]; /* DWORD 1 */ - u8 rsvd1[31]; /* DWORD 2 */ - u8 valid; /* DWORD 2 */ - u8 rsshash[32]; /* DWORD 3 */ -} __packed; -struct ETH_RX_COMPL_AMAP { - u32 dw[4]; -}; - -#endif /* __host_struct_amap_h__ */ diff --git a/drivers/staging/benet/hwlib.h b/drivers/staging/benet/hwlib.h deleted file mode 100644 index afedf4dc590..00000000000 --- a/drivers/staging/benet/hwlib.h +++ /dev/null @@ -1,830 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#ifndef __hwlib_h__ -#define __hwlib_h__ - -#include -#include -#include -#include - -#include "regmap.h" /* srcgen array map output */ - -#include "asyncmesg.h" -#include "fwcmd_opcodes.h" -#include "post_codes.h" -#include "fwcmd_mcc.h" - -#include "fwcmd_types_bmap.h" -#include "fwcmd_common_bmap.h" -#include "fwcmd_eth_bmap.h" -#include "bestatus.h" -/* - * - * Macros for reading/writing a protection domain or CSR registers - * in BladeEngine. - */ -#define PD_READ(fo, field) ioread32((fo)->db_va + \ - offsetof(struct BE_PROTECTION_DOMAIN_DBMAP_AMAP, field)/8) - -#define PD_WRITE(fo, field, val) iowrite32(val, (fo)->db_va + \ - offsetof(struct BE_PROTECTION_DOMAIN_DBMAP_AMAP, field)/8) - -#define CSR_READ(fo, field) ioread32((fo)->csr_va + \ - offsetof(struct BE_BLADE_ENGINE_CSRMAP_AMAP, field)/8) - -#define CSR_WRITE(fo, field, val) iowrite32(val, (fo)->csr_va + \ - offsetof(struct BE_BLADE_ENGINE_CSRMAP_AMAP, field)/8) - -#define PCICFG0_READ(fo, field) ioread32((fo)->pci_va + \ - offsetof(struct BE_PCICFG0_CSRMAP_AMAP, field)/8) - -#define PCICFG0_WRITE(fo, field, val) iowrite32(val, (fo)->pci_va + \ - offsetof(struct BE_PCICFG0_CSRMAP_AMAP, field)/8) - -#define PCICFG1_READ(fo, field) ioread32((fo)->pci_va + \ - offsetof(struct BE_PCICFG1_CSRMAP_AMAP, field)/8) - -#define PCICFG1_WRITE(fo, field, val) iowrite32(val, (fo)->pci_va + \ - offsetof(struct BE_PCICFG1_CSRMAP_AMAP, field)/8) - -#ifdef BE_DEBUG -#define ASSERT(c) BUG_ON(!(c)); -#else -#define ASSERT(c) -#endif - -/* debug levels */ -enum BE_DEBUG_LEVELS { - DL_ALWAYS = 0, /* cannot be masked */ - DL_ERR = 0x1, /* errors that should never happen */ - DL_WARN = 0x2, /* something questionable. - recoverable errors */ - DL_NOTE = 0x4, /* infrequent, important debug info */ - DL_INFO = 0x8, /* debug information */ - DL_VERBOSE = 0x10, /* detailed info, such as buffer traces */ - BE_DL_MIN_VALUE = 0x1, /* this is the min value used */ - BE_DL_MAX_VALUE = 0x80 /* this is the higheset value used */ -} ; - -extern unsigned int trace_level; - -#define TRACE(lm, fmt, args...) { \ - if (trace_level & lm) { \ - printk(KERN_NOTICE "BE: %s:%d \n" fmt, \ - __FILE__ , __LINE__ , ## args); \ - } \ - } - -static inline unsigned int be_trace_set_level(unsigned int level) -{ - unsigned int old_level = trace_level; - trace_level = level; - return old_level; -} - -#define be_trace_get_level() trace_level -/* - * Returns number of pages spanned by the size of data - * starting at the given address. - */ -#define PAGES_SPANNED(_address, _size) \ - ((u32)((((size_t)(_address) & (PAGE_SIZE - 1)) + \ - (_size) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)) -/* Byte offset into the page corresponding to given address */ -#define OFFSET_IN_PAGE(_addr_) ((size_t)(_addr_) & (PAGE_SIZE-1)) - -/* - * circular subtract. - * Returns a - b assuming a circular number system, where a and b are - * in range (0, maxValue-1). If a==b, zero is returned so the - * highest value possible with this subtraction is maxValue-1. - */ -static inline u32 be_subc(u32 a, u32 b, u32 max) -{ - ASSERT(a <= max && b <= max); - ASSERT(max > 0); - return a >= b ? (a - b) : (max - b + a); -} - -static inline u32 be_addc(u32 a, u32 b, u32 max) -{ - ASSERT(a < max); - ASSERT(max > 0); - return (max - a > b) ? (a + b) : (b + a - max); -} - -/* descriptor for a physically contiguous memory used for ring */ -struct ring_desc { - u32 length; /* length in bytes */ - void *va; /* virtual address */ - u64 pa; /* bus address */ -} ; - -/* - * This structure stores information about a ring shared between hardware - * and software. Each ring is allocated by the driver in the uncached - * extension and mapped into BladeEngine's unified table. - */ -struct mp_ring { - u32 pages; /* queue size in pages */ - u32 id; /* queue id assigned by beklib */ - u32 num; /* number of elements in queue */ - u32 cidx; /* consumer index */ - u32 pidx; /* producer index -- not used by most rings */ - u32 itemSize; /* size in bytes of one object */ - - void *va; /* The virtual address of the ring. - This should be last to allow 32 & 64 - bit debugger extensions to work. */ -} ; - -/*----------- amap bit filed get / set macros and functions -----*/ -/* - * Structures defined in the map header files (under fw/amap/) with names - * in the format BE__AMAP are pseudo structures with members - * of type u8. These structures are templates that are used in - * conjuntion with the structures with names in the format - * _AMAP to calculate the bit masks and bit offsets to get or set - * bit fields in structures. The structures _AMAP are arrays - * of 32 bits words and have the correct size. The following macros - * provide convenient ways to get and set the various members - * in the structures without using strucctures with bit fields. - * Always use the macros AMAP_GET_BITS_PTR and AMAP_SET_BITS_PTR - * macros to extract and set various members. - */ - -/* - * Returns the a bit mask for the register that is NOT shifted into location. - * That means return values always look like: 0x1, 0xFF, 0x7FF, etc... - */ -static inline u32 amap_mask(u32 bit_size) -{ - return bit_size == 32 ? 0xFFFFFFFF : (1 << bit_size) - 1; -} - -#define AMAP_BIT_MASK(_struct_, field) \ - amap_mask(AMAP_BIT_SIZE(_struct_, field)) - -/* - * non-optimized set bits function. First clears the bits and then assigns them. - * This does not require knowledge of the particular DWORD you are setting. - * e.g. AMAP_SET_BITS_PTR (struct, field1, &contextMemory, 123); - */ -static inline void -amap_set(void *ptr, u32 dw_offset, u32 mask, u32 offset, u32 value) -{ - u32 *dw = (u32 *)ptr; - *(dw + dw_offset) &= ~(mask << offset); - *(dw + dw_offset) |= (mask & value) << offset; -} - -#define AMAP_SET_BITS_PTR(_struct_, field, _structPtr_, val) \ - amap_set(_structPtr_, AMAP_WORD_OFFSET(_struct_, field),\ - AMAP_BIT_MASK(_struct_, field), \ - AMAP_BIT_OFFSET(_struct_, field), val) -/* - * Non-optimized routine that gets the bits without knowing the correct DWORD. - * e.g. fieldValue = AMAP_GET_BITS_PTR (struct, field1, &contextMemory); - */ -static inline u32 -amap_get(void *ptr, u32 dw_offset, u32 mask, u32 offset) -{ - u32 *dw = (u32 *)ptr; - return mask & (*(dw + dw_offset) >> offset); -} -#define AMAP_GET_BITS_PTR(_struct_, field, _structPtr_) \ - amap_get(_structPtr_, AMAP_WORD_OFFSET(_struct_, field), \ - AMAP_BIT_MASK(_struct_, field), \ - AMAP_BIT_OFFSET(_struct_, field)) - -/* Returns 0-31 representing bit offset within a DWORD of a bitfield. */ -#define AMAP_BIT_OFFSET(_struct_, field) \ - (offsetof(struct BE_ ## _struct_ ## _AMAP, field) % 32) - -/* Returns 0-n representing DWORD offset of bitfield within the structure. */ -#define AMAP_WORD_OFFSET(_struct_, field) \ - (offsetof(struct BE_ ## _struct_ ## _AMAP, field)/32) - -/* Returns size of bitfield in bits. */ -#define AMAP_BIT_SIZE(_struct_, field) \ - sizeof(((struct BE_ ## _struct_ ## _AMAP*)0)->field) - -struct be_mcc_wrb_response_copy { - u16 length; /* bytes in response */ - u16 fwcmd_offset; /* offset within the wrb of the response */ - void *va; /* user's va to copy response into */ - -} ; -typedef void (*mcc_wrb_cqe_callback) (void *context, int status, - struct MCC_WRB_AMAP *optional_wrb); -struct be_mcc_wrb_context { - - mcc_wrb_cqe_callback internal_cb; /* Function to call on - completion */ - void *internal_cb_context; /* Parameter to pass - to completion function */ - - mcc_wrb_cqe_callback cb; /* Function to call on completion */ - void *cb_context; /* Parameter to pass to completion function */ - - int *users_final_status; /* pointer to a local - variable for synchronous - commands */ - struct MCC_WRB_AMAP *wrb; /* pointer to original wrb for embedded - commands only */ - struct list_head next; /* links context structs together in - free list */ - - struct be_mcc_wrb_response_copy copy; /* Optional parameters to copy - embedded response to user's va */ - -#if defined(BE_DEBUG) - u16 subsystem, opcode; /* Track this FWCMD for debug builds. */ - struct MCC_WRB_AMAP *ring_wrb; - u32 consumed_count; -#endif -} ; - -/* - Represents a function object for network or storage. This - is used to manage per-function resources like MCC CQs, etc. -*/ -struct be_function_object { - - u32 magic; /*!< magic for detecting memory corruption. */ - - /* PCI BAR mapped addresses */ - u8 __iomem *csr_va; /* CSR */ - u8 __iomem *db_va; /* Door Bell */ - u8 __iomem *pci_va; /* PCI config space */ - u32 emulate; /* if set, MPU is not available. - Emulate everything. */ - u32 pend_queue_driving; /* if set, drive the queued WRBs - after releasing the WRB lock */ - - spinlock_t post_lock; /* lock for verifying one thread posting wrbs */ - spinlock_t cq_lock; /* lock for verifying one thread - processing cq */ - spinlock_t mcc_context_lock; /* lock for protecting mcc - context free list */ - unsigned long post_irq; - unsigned long cq_irq; - - u32 type; - u32 pci_function_number; - - struct be_mcc_object *mcc; /* mcc rings. */ - - struct { - struct MCC_MAILBOX_AMAP *va; /* VA to the mailbox */ - u64 pa; /* PA to the mailbox */ - u32 length; /* byte length of mailbox */ - - /* One default context struct used for posting at - * least one MCC_WRB - */ - struct be_mcc_wrb_context default_context; - bool default_context_allocated; - } mailbox; - - struct { - - /* Wake on lans configured. */ - u32 wol_bitmask; /* bits 0,1,2,3 are set if - corresponding index is enabled */ - } config; - - - struct BE_FIRMWARE_CONFIG fw_config; -} ; - -/* - Represents an Event Queue -*/ -struct be_eq_object { - u32 magic; - atomic_t ref_count; - - struct be_function_object *parent_function; - - struct list_head eq_list; - struct list_head cq_list_head; - - u32 eq_id; - void *cb_context; - -} ; - -/* - Manages a completion queue -*/ -struct be_cq_object { - u32 magic; - atomic_t ref_count; - - struct be_function_object *parent_function; - struct be_eq_object *eq_object; - - struct list_head cq_list; - struct list_head cqlist_for_eq; - - void *va; - u32 num_entries; - - void *cb_context; - - u32 cq_id; - -} ; - -/* - Manages an ethernet send queue -*/ -struct be_ethsq_object { - u32 magic; - - struct list_head list; - - struct be_function_object *parent_function; - struct be_cq_object *cq_object; - u32 bid; - -} ; - -/* -@brief - Manages an ethernet receive queue -*/ -struct be_ethrq_object { - u32 magic; - struct list_head list; - struct be_function_object *parent_function; - u32 rid; - struct be_cq_object *cq_object; - struct be_cq_object *rss_cq_object[4]; - -} ; - -/* - Manages an MCC -*/ -typedef void (*mcc_async_event_callback) (void *context, u32 event_code, - void *event); -struct be_mcc_object { - u32 magic; - - struct be_function_object *parent_function; - struct list_head mcc_list; - - struct be_cq_object *cq_object; - - /* Async event callback for MCC CQ. */ - mcc_async_event_callback async_cb; - void *async_context; - - struct { - struct be_mcc_wrb_context *base; - u32 num; - struct list_head list_head; - } wrb_context; - - struct { - struct ring_desc *rd; - struct mp_ring ring; - } sq; - - struct { - struct mp_ring ring; - } cq; - - u32 processing; /* flag indicating that one thread - is processing CQ */ - u32 rearm; /* doorbell rearm setting to make - sure the active processing thread */ - /* rearms the CQ if any of the threads requested it. */ - - struct list_head backlog; - u32 backlog_length; - u32 driving_backlog; - u32 consumed_index; - -} ; - - -/* Queue context header -- the required software information for - * queueing a WRB. - */ -struct be_queue_driver_context { - mcc_wrb_cqe_callback internal_cb; /* Function to call on - completion */ - void *internal_cb_context; /* Parameter to pass - to completion function */ - - mcc_wrb_cqe_callback cb; /* Function to call on completion */ - void *cb_context; /* Parameter to pass to completion function */ - - struct be_mcc_wrb_response_copy copy; /* Optional parameters to copy - embedded response to user's va */ - void *optional_fwcmd_va; - struct list_head list; - u32 bytes; -} ; - -/* - * Common MCC WRB header that all commands require. - */ -struct be_mcc_wrb_header { - u8 rsvd[offsetof(struct BE_MCC_WRB_AMAP, payload)/8]; -} ; - -/* - * All non embedded commands supported by hwlib functions only allow - * 1 SGE. This queue context handles them all. - */ -struct be_nonembedded_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct MCC_SGE_AMAP sge[1]; -} ; - -/* - * ------------------------------------------------------------------------ - * This section contains the specific queue struct for each command. - * The user could always provide a be_generic_q_ctxt but this is a - * rather large struct. By using the specific struct, memory consumption - * can be reduced. - * ------------------------------------------------------------------------ - */ - -struct be_link_status_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY fwcmd; -} ; - -struct be_multicast_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_NTWK_MULTICAST_SET fwcmd; -} ; - - -struct be_vlan_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_NTWK_VLAN_CONFIG fwcmd; -} ; - -struct be_promiscuous_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_ETH_PROMISCUOUS fwcmd; -} ; - -struct be_force_failover_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_FORCE_FAILOVER fwcmd; -} ; - - -struct be_rxf_filter_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_NTWK_RX_FILTER fwcmd; -} ; - -struct be_eq_modify_delay_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_MODIFY_EQ_DELAY fwcmd; -} ; - -/* - * The generic context is the largest size that would be required. - * It is the software context plus an entire WRB. - */ -struct be_generic_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct MCC_WRB_PAYLOAD_AMAP payload; -} ; - -/* - * Types for the BE_QUEUE_CONTEXT object. - */ -#define BE_QUEUE_INVALID (0) -#define BE_QUEUE_LINK_STATUS (0xA006) -#define BE_QUEUE_ETH_STATS (0xA007) -#define BE_QUEUE_TPM_STATS (0xA008) -#define BE_QUEUE_TCP_STATS (0xA009) -#define BE_QUEUE_MULTICAST (0xA00A) -#define BE_QUEUE_VLAN (0xA00B) -#define BE_QUEUE_RSS (0xA00C) -#define BE_QUEUE_FORCE_FAILOVER (0xA00D) -#define BE_QUEUE_PROMISCUOUS (0xA00E) -#define BE_QUEUE_WAKE_ON_LAN (0xA00F) -#define BE_QUEUE_NOP (0xA010) - -/* --- BE_FUNCTION_ENUM --- */ -#define BE_FUNCTION_TYPE_ISCSI (0) -#define BE_FUNCTION_TYPE_NETWORK (1) -#define BE_FUNCTION_TYPE_ARM (2) - -/* --- BE_ETH_TX_RING_TYPE_ENUM --- */ -#define BE_ETH_TX_RING_TYPE_FORWARDING (1) /* Ether ring for forwarding */ -#define BE_ETH_TX_RING_TYPE_STANDARD (2) /* Ether ring for sending */ - /* network packets. */ -#define BE_ETH_TX_RING_TYPE_BOUND (3) /* Ethernet ring for sending */ - /* network packets, bound */ - /* to a physical port. */ -/* - * ---------------------------------------------------------------------- - * API MACROS - * ---------------------------------------------------------------------- - */ -#define BE_FWCMD_NAME(_short_name_) struct FWCMD_##_short_name_ -#define BE_OPCODE_NAME(_short_name_) OPCODE_##_short_name_ -#define BE_SUBSYSTEM_NAME(_short_name_) SUBSYSTEM_##_short_name_ - - -#define BE_PREPARE_EMBEDDED_FWCMD(_pfob_, _wrb_, _short_name_) \ - ((BE_FWCMD_NAME(_short_name_) *) \ - be_function_prepare_embedded_fwcmd(_pfob_, _wrb_, \ - sizeof(BE_FWCMD_NAME(_short_name_)), \ - FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.request), \ - FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.response), \ - BE_OPCODE_NAME(_short_name_), \ - BE_SUBSYSTEM_NAME(_short_name_))); - -#define BE_PREPARE_NONEMBEDDED_FWCMD(_pfob_, _wrb_, _iva_, _ipa_, _short_name_)\ - ((BE_FWCMD_NAME(_short_name_) *) \ - be_function_prepare_nonembedded_fwcmd(_pfob_, _wrb_, (_iva_), (_ipa_), \ - sizeof(BE_FWCMD_NAME(_short_name_)), \ - FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.request), \ - FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.response), \ - BE_OPCODE_NAME(_short_name_), \ - BE_SUBSYSTEM_NAME(_short_name_))); - -int be_function_object_create(u8 __iomem *csr_va, u8 __iomem *db_va, - u8 __iomem *pci_va, u32 function_type, struct ring_desc *mailbox_rd, - struct be_function_object *pfob); - -int be_function_object_destroy(struct be_function_object *pfob); -int be_function_cleanup(struct be_function_object *pfob); - - -int be_function_get_fw_version(struct be_function_object *pfob, - struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD *fw_version, - mcc_wrb_cqe_callback cb, void *cb_context); - - -int be_eq_modify_delay(struct be_function_object *pfob, - u32 num_eq, struct be_eq_object **eq_array, - u32 *eq_delay_array, mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_eq_modify_delay_q_ctxt *q_ctxt); - - - -int be_eq_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 eqe_size, u32 num_entries, - u32 watermark, u32 timer_delay, struct be_eq_object *eq_object); - -int be_eq_destroy(struct be_eq_object *eq); - -int be_cq_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 length, - bool solicited_eventable, bool no_delay, - u32 wm_thresh, struct be_eq_object *eq_object, - struct be_cq_object *cq_object); - -int be_cq_destroy(struct be_cq_object *cq); - -int be_mcc_ring_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 length, - struct be_mcc_wrb_context *context_array, - u32 num_context_entries, - struct be_cq_object *cq, struct be_mcc_object *mcc); -int be_mcc_ring_destroy(struct be_mcc_object *mcc_object); - -int be_mcc_process_cq(struct be_mcc_object *mcc_object, bool rearm); - -int be_mcc_add_async_event_callback(struct be_mcc_object *mcc_object, - mcc_async_event_callback cb, void *cb_context); - -int be_pci_soft_reset(struct be_function_object *pfob); - - -int be_drive_POST(struct be_function_object *pfob); - - -int be_eth_sq_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 length_in_bytes, - u32 type, u32 ulp, struct be_cq_object *cq_object, - struct be_ethsq_object *eth_sq); - -struct be_eth_sq_parameters { - u32 port; - u32 rsvd0[2]; -} ; - -int be_eth_sq_create_ex(struct be_function_object *pfob, - struct ring_desc *rd, u32 length_in_bytes, - u32 type, u32 ulp, struct be_cq_object *cq_object, - struct be_eth_sq_parameters *ex_parameters, - struct be_ethsq_object *eth_sq); -int be_eth_sq_destroy(struct be_ethsq_object *eth_sq); - -int be_eth_set_flow_control(struct be_function_object *pfob, - bool txfc_enable, bool rxfc_enable); - -int be_eth_get_flow_control(struct be_function_object *pfob, - bool *txfc_enable, bool *rxfc_enable); -int be_eth_set_qos(struct be_function_object *pfob, u32 max_bps, u32 max_pps); - -int be_eth_get_qos(struct be_function_object *pfob, u32 *max_bps, u32 *max_pps); - -int be_eth_set_frame_size(struct be_function_object *pfob, - u32 *tx_frame_size, u32 *rx_frame_size); - -int be_eth_rq_create(struct be_function_object *pfob, - struct ring_desc *rd, struct be_cq_object *cq_object, - struct be_cq_object *bcmc_cq_object, - struct be_ethrq_object *eth_rq); - -int be_eth_rq_destroy(struct be_ethrq_object *eth_rq); - -int be_eth_rq_destroy_options(struct be_ethrq_object *eth_rq, bool flush, - mcc_wrb_cqe_callback cb, void *cb_context); -int be_eth_rq_set_frag_size(struct be_function_object *pfob, - u32 new_frag_size_bytes, u32 *actual_frag_size_bytes); -int be_eth_rq_get_frag_size(struct be_function_object *pfob, - u32 *frag_size_bytes); - -void *be_function_prepare_embedded_fwcmd(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, - u32 payload_length, u32 request_length, - u32 response_length, u32 opcode, u32 subsystem); -void *be_function_prepare_nonembedded_fwcmd(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, void *fwcmd_header_va, u64 fwcmd_header_pa, - u32 payload_length, u32 request_length, u32 response_length, - u32 opcode, u32 subsystem); - - -struct MCC_WRB_AMAP * -be_function_peek_mcc_wrb(struct be_function_object *pfob); - -int be_rxf_mac_address_read_write(struct be_function_object *pfob, - bool port1, bool mac1, bool mgmt, - bool write, bool permanent, u8 *mac_address, - mcc_wrb_cqe_callback cb, - void *cb_context); - -int be_rxf_multicast_config(struct be_function_object *pfob, - bool promiscuous, u32 num, u8 *mac_table, - mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_multicast_q_ctxt *q_ctxt); - -int be_rxf_vlan_config(struct be_function_object *pfob, - bool promiscuous, u32 num, u16 *vlan_tag_array, - mcc_wrb_cqe_callback cb, void *cb_context, - struct be_vlan_q_ctxt *q_ctxt); - - -int be_rxf_link_status(struct be_function_object *pfob, - struct BE_LINK_STATUS *link_status, - mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_link_status_q_ctxt *q_ctxt); - - -int be_rxf_query_eth_statistics(struct be_function_object *pfob, - struct FWCMD_ETH_GET_STATISTICS *va_for_fwcmd, - u64 pa_for_fwcmd, mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_nonembedded_q_ctxt *q_ctxt); - -int be_rxf_promiscuous(struct be_function_object *pfob, - bool enable_port0, bool enable_port1, - mcc_wrb_cqe_callback cb, void *cb_context, - struct be_promiscuous_q_ctxt *q_ctxt); - - -int be_rxf_filter_config(struct be_function_object *pfob, - struct NTWK_RX_FILTER_SETTINGS *settings, - mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_rxf_filter_q_ctxt *q_ctxt); - -/* - * ------------------------------------------------------ - * internal functions used by hwlib - * ------------------------------------------------------ - */ - - -int be_function_ring_destroy(struct be_function_object *pfob, - u32 id, u32 ring_type, mcc_wrb_cqe_callback cb, - void *cb_context, - mcc_wrb_cqe_callback internal_cb, - void *internal_callback_context); - -int be_function_post_mcc_wrb(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, - struct be_generic_q_ctxt *q_ctxt, - mcc_wrb_cqe_callback cb, void *cb_context, - mcc_wrb_cqe_callback internal_cb, - void *internal_cb_context, void *optional_fwcmd_va, - struct be_mcc_wrb_response_copy *response_copy); - -int be_function_queue_mcc_wrb(struct be_function_object *pfob, - struct be_generic_q_ctxt *q_ctxt); - -/* - * ------------------------------------------------------ - * MCC QUEUE - * ------------------------------------------------------ - */ - -int be_mpu_init_mailbox(struct be_function_object *pfob, struct ring_desc *rd); - - -struct MCC_WRB_AMAP * -_be_mpu_peek_ring_wrb(struct be_mcc_object *mcc, bool driving_queue); - -struct be_mcc_wrb_context * -_be_mcc_allocate_wrb_context(struct be_function_object *pfob); - -void _be_mcc_free_wrb_context(struct be_function_object *pfob, - struct be_mcc_wrb_context *context); - -int _be_mpu_post_wrb_mailbox(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, struct be_mcc_wrb_context *wrb_context); - -int _be_mpu_post_wrb_ring(struct be_mcc_object *mcc, - struct MCC_WRB_AMAP *wrb, struct be_mcc_wrb_context *wrb_context); - -void be_drive_mcc_wrb_queue(struct be_mcc_object *mcc); - - -/* - * ------------------------------------------------------ - * Ring Sizes - * ------------------------------------------------------ - */ -static inline u32 be_ring_encoding_to_length(u32 encoding, u32 object_size) -{ - - ASSERT(encoding != 1); /* 1 is rsvd */ - ASSERT(encoding < 16); - ASSERT(object_size > 0); - - if (encoding == 0) /* 32k deep */ - encoding = 16; - - return (1 << (encoding - 1)) * object_size; -} - -static inline -u32 be_ring_length_to_encoding(u32 length_in_bytes, u32 object_size) -{ - - u32 count, encoding; - - ASSERT(object_size > 0); - ASSERT(length_in_bytes % object_size == 0); - - count = length_in_bytes / object_size; - - ASSERT(count > 1); - ASSERT(count <= 32 * 1024); - ASSERT(length_in_bytes <= 8 * PAGE_SIZE); /* max ring size in UT */ - - encoding = __ilog2_u32(count) + 1; - - if (encoding == 16) - encoding = 0; /* 32k deep */ - - return encoding; -} - -void be_rd_to_pa_list(struct ring_desc *rd, struct PHYS_ADDR *pa_list, - u32 max_num); -#endif /* __hwlib_h__ */ diff --git a/drivers/staging/benet/mpu.c b/drivers/staging/benet/mpu.c deleted file mode 100644 index 269cc11d305..00000000000 --- a/drivers/staging/benet/mpu.c +++ /dev/null @@ -1,1364 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include -#include "hwlib.h" -#include "bestatus.h" - -static -inline void mp_ring_create(struct mp_ring *ring, u32 num, u32 size, void *va) -{ - ASSERT(ring); - memset(ring, 0, sizeof(struct mp_ring)); - ring->num = num; - ring->pages = DIV_ROUND_UP(num * size, PAGE_SIZE); - ring->itemSize = size; - ring->va = va; -} - -/* - * ----------------------------------------------------------------------- - * Interface for 2 index rings. i.e. consumer/producer rings - * -------------------------------------------------------------------------- - */ - -/* Returns number items pending on ring. */ -static inline u32 mp_ring_num_pending(struct mp_ring *ring) -{ - ASSERT(ring); - if (ring->num == 0) - return 0; - return be_subc(ring->pidx, ring->cidx, ring->num); -} - -/* Returns number items free on ring. */ -static inline u32 mp_ring_num_empty(struct mp_ring *ring) -{ - ASSERT(ring); - return ring->num - 1 - mp_ring_num_pending(ring); -} - -/* Consume 1 item */ -static inline void mp_ring_consume(struct mp_ring *ring) -{ - ASSERT(ring); - ASSERT(ring->pidx != ring->cidx); - - ring->cidx = be_addc(ring->cidx, 1, ring->num); -} - -/* Produce 1 item */ -static inline void mp_ring_produce(struct mp_ring *ring) -{ - ASSERT(ring); - ring->pidx = be_addc(ring->pidx, 1, ring->num); -} - -/* Consume count items */ -static inline void mp_ring_consume_multiple(struct mp_ring *ring, u32 count) -{ - ASSERT(ring); - ASSERT(mp_ring_num_pending(ring) >= count); - ring->cidx = be_addc(ring->cidx, count, ring->num); -} - -static inline void *mp_ring_item(struct mp_ring *ring, u32 index) -{ - ASSERT(ring); - ASSERT(index < ring->num); - ASSERT(ring->itemSize > 0); - return (u8 *) ring->va + index * ring->itemSize; -} - -/* Ptr to produce item */ -static inline void *mp_ring_producer_ptr(struct mp_ring *ring) -{ - ASSERT(ring); - return mp_ring_item(ring, ring->pidx); -} - -/* - * Returns a pointer to the current location in the ring. - * This is used for rings with 1 index. - */ -static inline void *mp_ring_current(struct mp_ring *ring) -{ - ASSERT(ring); - ASSERT(ring->pidx == 0); /* not used */ - - return mp_ring_item(ring, ring->cidx); -} - -/* - * Increment index for rings with only 1 index. - * This is used for rings with 1 index. - */ -static inline void *mp_ring_next(struct mp_ring *ring) -{ - ASSERT(ring); - ASSERT(ring->num > 0); - ASSERT(ring->pidx == 0); /* not used */ - - ring->cidx = be_addc(ring->cidx, 1, ring->num); - return mp_ring_current(ring); -} - -/* - This routine waits for a previously posted mailbox WRB to be completed. - Specifically it waits for the mailbox to say that it's ready to accept - more data by setting the LSB of the mailbox pd register to 1. - - pcontroller - The function object to post this data to - - IRQL < DISPATCH_LEVEL -*/ -static void be_mcc_mailbox_wait(struct be_function_object *pfob) -{ - struct MPU_MAILBOX_DB_AMAP mailbox_db; - u32 i = 0; - u32 ready; - - if (pfob->emulate) { - /* No waiting for mailbox in emulated mode. */ - return; - } - - mailbox_db.dw[0] = PD_READ(pfob, mcc_bootstrap_db); - ready = AMAP_GET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db); - - while (ready == false) { - if ((++i & 0x3FFFF) == 0) { - TRACE(DL_WARN, "Waiting for mailbox ready - %dk polls", - i / 1000); - } - udelay(1); - mailbox_db.dw[0] = PD_READ(pfob, mcc_bootstrap_db); - ready = AMAP_GET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db); - } -} - -/* - This routine tells the MCC mailbox that there is data to processed - in the mailbox. It does this by setting the physical address for the - mailbox location and clearing the LSB. This routine returns immediately - and does not wait for the WRB to be processed. - - pcontroller - The function object to post this data to - - IRQL < DISPATCH_LEVEL - -*/ -static void be_mcc_mailbox_notify(struct be_function_object *pfob) -{ - struct MPU_MAILBOX_DB_AMAP mailbox_db; - u32 pa; - - ASSERT(pfob->mailbox.pa); - ASSERT(pfob->mailbox.va); - - /* If emulated, do not ring the mailbox */ - if (pfob->emulate) { - TRACE(DL_WARN, "MPU disabled. Skipping mailbox notify."); - return; - } - - /* form the higher bits in the address */ - mailbox_db.dw[0] = 0; /* init */ - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, hi, &mailbox_db, 1); - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db, 0); - - /* bits 34 to 63 */ - pa = (u32) (pfob->mailbox.pa >> 34); - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, address, &mailbox_db, pa); - - /* Wait for the MPU to be ready */ - be_mcc_mailbox_wait(pfob); - - /* Ring doorbell 1st time */ - PD_WRITE(pfob, mcc_bootstrap_db, mailbox_db.dw[0]); - - /* Wait for 1st write to be acknowledged. */ - be_mcc_mailbox_wait(pfob); - - /* lower bits 30 bits from 4th bit (bits 4 to 33)*/ - pa = (u32) (pfob->mailbox.pa >> 4) & 0x3FFFFFFF; - - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, hi, &mailbox_db, 0); - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db, 0); - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, address, &mailbox_db, pa); - - /* Ring doorbell 2nd time */ - PD_WRITE(pfob, mcc_bootstrap_db, mailbox_db.dw[0]); -} - -/* - This routine tells the MCC mailbox that there is data to processed - in the mailbox. It does this by setting the physical address for the - mailbox location and clearing the LSB. This routine spins until the - MPU writes a 1 into the LSB indicating that the data has been received - and is ready to be processed. - - pcontroller - The function object to post this data to - - IRQL < DISPATCH_LEVEL -*/ -static void -be_mcc_mailbox_notify_and_wait(struct be_function_object *pfob) -{ - /* - * Notify it - */ - be_mcc_mailbox_notify(pfob); - /* - * Now wait for completion of WRB - */ - be_mcc_mailbox_wait(pfob); -} - -void -be_mcc_process_cqe(struct be_function_object *pfob, - struct MCC_CQ_ENTRY_AMAP *cqe) -{ - struct be_mcc_wrb_context *wrb_context = NULL; - u32 offset, status; - u8 *p; - - ASSERT(cqe); - /* - * A command completed. Commands complete out-of-order. - * Determine which command completed from the TAG. - */ - offset = offsetof(struct BE_MCC_CQ_ENTRY_AMAP, mcc_tag)/8; - p = (u8 *) cqe + offset; - wrb_context = (struct be_mcc_wrb_context *)(void *)(size_t)(*(u64 *)p); - ASSERT(wrb_context); - - /* - * Perform a response copy if requested. - * Only copy data if the FWCMD is successful. - */ - status = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, completion_status, cqe); - if (status == MGMT_STATUS_SUCCESS && wrb_context->copy.length > 0) { - ASSERT(wrb_context->wrb); - ASSERT(wrb_context->copy.va); - p = (u8 *)wrb_context->wrb + - offsetof(struct BE_MCC_WRB_AMAP, payload)/8; - memcpy(wrb_context->copy.va, - (u8 *)p + wrb_context->copy.fwcmd_offset, - wrb_context->copy.length); - } - - if (status) - status = BE_NOT_OK; - /* internal callback */ - if (wrb_context->internal_cb) { - wrb_context->internal_cb(wrb_context->internal_cb_context, - status, wrb_context->wrb); - } - - /* callback */ - if (wrb_context->cb) { - wrb_context->cb(wrb_context->cb_context, - status, wrb_context->wrb); - } - /* Free the context structure */ - _be_mcc_free_wrb_context(pfob, wrb_context); -} - -void be_drive_mcc_wrb_queue(struct be_mcc_object *mcc) -{ - struct be_function_object *pfob = NULL; - int status = BE_PENDING; - struct be_generic_q_ctxt *q_ctxt; - struct MCC_WRB_AMAP *wrb; - struct MCC_WRB_AMAP *queue_wrb; - u32 length, payload_length, sge_count, embedded; - unsigned long irql; - - BUILD_BUG_ON((sizeof(struct be_generic_q_ctxt) < - sizeof(struct be_queue_driver_context) + - sizeof(struct MCC_WRB_AMAP))); - pfob = mcc->parent_function; - - spin_lock_irqsave(&pfob->post_lock, irql); - - if (mcc->driving_backlog) { - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return; - } - /* Acquire the flag to limit 1 thread to redrive posts. */ - mcc->driving_backlog = 1; - - while (!list_empty(&mcc->backlog)) { - wrb = _be_mpu_peek_ring_wrb(mcc, true); /* Driving the queue */ - if (!wrb) - break; /* No space in the ring yet. */ - /* Get the next queued entry to process. */ - q_ctxt = list_first_entry(&mcc->backlog, - struct be_generic_q_ctxt, context.list); - list_del(&q_ctxt->context.list); - pfob->mcc->backlog_length--; - /* - * Compute the required length of the WRB. - * Since the queue element may be smaller than - * the complete WRB, copy only the required number of bytes. - */ - queue_wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - embedded = AMAP_GET_BITS_PTR(MCC_WRB, embedded, queue_wrb); - if (embedded) { - payload_length = AMAP_GET_BITS_PTR(MCC_WRB, - payload_length, queue_wrb); - length = sizeof(struct be_mcc_wrb_header) + - payload_length; - } else { - sge_count = AMAP_GET_BITS_PTR(MCC_WRB, sge_count, - queue_wrb); - ASSERT(sge_count == 1); /* only 1 frag. */ - length = sizeof(struct be_mcc_wrb_header) + - sge_count * sizeof(struct MCC_SGE_AMAP); - } - - /* - * Truncate the length based on the size of the - * queue element. Some elements that have output parameters - * can be smaller than the payload_length field would - * indicate. We really only need to copy the request - * parameters, not the response. - */ - length = min(length, (u32) (q_ctxt->context.bytes - - offsetof(struct be_generic_q_ctxt, wrb_header))); - - /* Copy the queue element WRB into the ring. */ - memcpy(wrb, &q_ctxt->wrb_header, length); - - /* Post the wrb. This should not fail assuming we have - * enough context structs. */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, - q_ctxt->context.cb, q_ctxt->context.cb_context, - q_ctxt->context.internal_cb, - q_ctxt->context.internal_cb_context, - q_ctxt->context.optional_fwcmd_va, - &q_ctxt->context.copy); - - if (status == BE_SUCCESS) { - /* - * Synchronous completion. Since it was queued, - * we will invoke the callback. - * To the user, this is an asynchronous request. - */ - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - - ASSERT(q_ctxt->context.cb); - - q_ctxt->context.cb( - q_ctxt->context.cb_context, - BE_SUCCESS, NULL); - - spin_lock_irqsave(&pfob->post_lock, irql); - - } else if (status != BE_PENDING) { - /* - * Another resource failed. Should never happen - * if we have sufficient MCC_WRB_CONTEXT structs. - * Return to head of the queue. - */ - TRACE(DL_WARN, "Failed to post a queued WRB. 0x%x", - status); - list_add(&q_ctxt->context.list, &mcc->backlog); - pfob->mcc->backlog_length++; - break; - } - } - - /* Free the flag to limit 1 thread to redrive posts. */ - mcc->driving_backlog = 0; - spin_unlock_irqrestore(&pfob->post_lock, irql); -} - -/* This function asserts that the WRB was consumed in order. */ -#ifdef BE_DEBUG -u32 be_mcc_wrb_consumed_in_order(struct be_mcc_object *mcc, - struct MCC_CQ_ENTRY_AMAP *cqe) -{ - struct be_mcc_wrb_context *wrb_context = NULL; - u32 wrb_index; - u32 wrb_consumed_in_order; - u32 offset; - u8 *p; - - ASSERT(cqe); - /* - * A command completed. Commands complete out-of-order. - * Determine which command completed from the TAG. - */ - offset = offsetof(struct BE_MCC_CQ_ENTRY_AMAP, mcc_tag)/8; - p = (u8 *) cqe + offset; - wrb_context = (struct be_mcc_wrb_context *)(void *)(size_t)(*(u64 *)p); - - ASSERT(wrb_context); - - wrb_index = (u32) (((u64)(size_t)wrb_context->ring_wrb - - (u64)(size_t)mcc->sq.ring.va) / sizeof(struct MCC_WRB_AMAP)); - - ASSERT(wrb_index < mcc->sq.ring.num); - - wrb_consumed_in_order = (u32) (wrb_index == mcc->consumed_index); - mcc->consumed_index = be_addc(mcc->consumed_index, 1, mcc->sq.ring.num); - return wrb_consumed_in_order; -} -#endif - -int be_mcc_process_cq(struct be_mcc_object *mcc, bool rearm) -{ - struct be_function_object *pfob = NULL; - struct MCC_CQ_ENTRY_AMAP *cqe; - struct CQ_DB_AMAP db; - struct mp_ring *cq_ring = &mcc->cq.ring; - struct mp_ring *mp_ring = &mcc->sq.ring; - u32 num_processed = 0; - u32 consumed = 0, valid, completed, cqe_consumed, async_event; - - pfob = mcc->parent_function; - - spin_lock_irqsave(&pfob->cq_lock, pfob->cq_irq); - - /* - * Verify that only one thread is processing the CQ at once. - * We cannot hold the lock while processing the CQ due to - * the callbacks into the OS. Therefore, this flag is used - * to control it. If any of the threads want to - * rearm the CQ, we need to honor that. - */ - if (mcc->processing != 0) { - mcc->rearm = mcc->rearm || rearm; - goto Error; - } else { - mcc->processing = 1; /* lock processing for this thread. */ - mcc->rearm = rearm; /* set our rearm setting */ - } - - spin_unlock_irqrestore(&pfob->cq_lock, pfob->cq_irq); - - cqe = mp_ring_current(cq_ring); - valid = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, valid, cqe); - while (valid) { - - if (num_processed >= 8) { - /* coalesce doorbells, but free space in cq - * ring while processing. */ - db.dw[0] = 0; /* clear */ - AMAP_SET_BITS_PTR(CQ_DB, qid, &db, cq_ring->id); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &db, false); - AMAP_SET_BITS_PTR(CQ_DB, event, &db, false); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &db, - num_processed); - num_processed = 0; - - PD_WRITE(pfob, cq_db, db.dw[0]); - } - - async_event = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, async_event, cqe); - if (async_event) { - /* This is an asynchronous event. */ - struct ASYNC_EVENT_TRAILER_AMAP *async_trailer = - (struct ASYNC_EVENT_TRAILER_AMAP *) - ((u8 *) cqe + sizeof(struct MCC_CQ_ENTRY_AMAP) - - sizeof(struct ASYNC_EVENT_TRAILER_AMAP)); - u32 event_code; - async_event = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, - async_event, async_trailer); - ASSERT(async_event == 1); - - - valid = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, - valid, async_trailer); - ASSERT(valid == 1); - - /* Call the async event handler if it is installed. */ - if (mcc->async_cb) { - event_code = - AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, - event_code, async_trailer); - mcc->async_cb(mcc->async_context, - (u32) event_code, (void *) cqe); - } - - } else { - /* This is a completion entry. */ - - /* No vm forwarding in this driver. */ - - cqe_consumed = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, - consumed, cqe); - if (cqe_consumed) { - /* - * A command on the MCC ring was consumed. - * Update the consumer index. - * These occur in order. - */ - ASSERT(be_mcc_wrb_consumed_in_order(mcc, cqe)); - consumed++; - } - - completed = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, - completed, cqe); - if (completed) { - /* A command completed. Use tag to - * determine which command. */ - be_mcc_process_cqe(pfob, cqe); - } - } - - /* Reset the CQE */ - AMAP_SET_BITS_PTR(MCC_CQ_ENTRY, valid, cqe, false); - num_processed++; - - /* Update our tracking for the CQ ring. */ - cqe = mp_ring_next(cq_ring); - valid = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, valid, cqe); - } - - TRACE(DL_INFO, "num_processed:0x%x, and consumed:0x%x", - num_processed, consumed); - /* - * Grab the CQ lock to synchronize the "rearm" setting for - * the doorbell, and for clearing the "processing" flag. - */ - spin_lock_irqsave(&pfob->cq_lock, pfob->cq_irq); - - /* - * Rearm the cq. This is done based on the global mcc->rearm - * flag which combines the rearm parameter from the current - * call to process_cq and any other threads - * that tried to process the CQ while this one was active. - * This handles the situation where a sync. fwcmd was processing - * the CQ while the interrupt/dpc tries to process it. - * The sync process gets to continue -- but it is now - * responsible for the rearming. - */ - if (num_processed > 0 || mcc->rearm == true) { - db.dw[0] = 0; /* clear */ - AMAP_SET_BITS_PTR(CQ_DB, qid, &db, cq_ring->id); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &db, mcc->rearm); - AMAP_SET_BITS_PTR(CQ_DB, event, &db, false); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &db, num_processed); - - PD_WRITE(pfob, cq_db, db.dw[0]); - } - /* - * Update the consumer index after ringing the CQ doorbell. - * We don't want another thread to post more WRBs before we - * have CQ space available. - */ - mp_ring_consume_multiple(mp_ring, consumed); - - /* Clear the processing flag. */ - mcc->processing = 0; - -Error: - spin_unlock_irqrestore(&pfob->cq_lock, pfob->cq_irq); - /* - * Use the local variable to detect if the current thread - * holds the WRB post lock. If rearm is false, this is - * either a synchronous command, or the upper layer driver is polling - * from a thread. We do not drive the queue from that - * context since the driver may hold the - * wrb post lock already. - */ - if (rearm) - be_drive_mcc_wrb_queue(mcc); - else - pfob->pend_queue_driving = 1; - - return BE_SUCCESS; -} - -/* - *============================================================================ - * P U B L I C R O U T I N E S - *============================================================================ - */ - -/* - This routine creates an MCC object. This object contains an MCC send queue - and a CQ private to the MCC. - - pcontroller - Handle to a function object - - EqObject - EQ object that will be used to dispatch this MCC - - ppMccObject - Pointer to an internal Mcc Object returned. - - Returns BE_SUCCESS if successfull,, otherwise a useful error code - is returned. - - IRQL < DISPATCH_LEVEL - -*/ -int -be_mcc_ring_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 length, - struct be_mcc_wrb_context *context_array, - u32 num_context_entries, - struct be_cq_object *cq, struct be_mcc_object *mcc) -{ - int status = 0; - - struct FWCMD_COMMON_MCC_CREATE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - u32 num_entries_encoded, n, i; - void *va = NULL; - unsigned long irql; - - if (length < sizeof(struct MCC_WRB_AMAP) * 2) { - TRACE(DL_ERR, "Invalid MCC ring length:%d", length); - return BE_NOT_OK; - } - /* - * Reduce the actual ring size to be less than the number - * of context entries. This ensures that we run out of - * ring WRBs first so the queuing works correctly. We never - * queue based on context structs. - */ - if (num_context_entries + 1 < - length / sizeof(struct MCC_WRB_AMAP) - 1) { - - u32 max_length = - (num_context_entries + 2) * sizeof(struct MCC_WRB_AMAP); - - if (is_power_of_2(max_length)) - length = __roundup_pow_of_two(max_length+1) / 2; - else - length = __roundup_pow_of_two(max_length) / 2; - - ASSERT(length <= max_length); - - TRACE(DL_WARN, - "MCC ring length reduced based on context entries." - " length:%d wrbs:%d context_entries:%d", length, - (int) (length / sizeof(struct MCC_WRB_AMAP)), - num_context_entries); - } - - spin_lock_irqsave(&pfob->post_lock, irql); - - num_entries_encoded = - be_ring_length_to_encoding(length, sizeof(struct MCC_WRB_AMAP)); - - /* Init MCC object. */ - memset(mcc, 0, sizeof(*mcc)); - mcc->parent_function = pfob; - mcc->cq_object = cq; - - INIT_LIST_HEAD(&mcc->backlog); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in create EQ."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_MCC_CREATE); - - fwcmd->params.request.num_pages = DIV_ROUND_UP(length, PAGE_SIZE); - /* - * Program MCC ring context - */ - AMAP_SET_BITS_PTR(MCC_RING_CONTEXT, pdid, - &fwcmd->params.request.context, 0); - AMAP_SET_BITS_PTR(MCC_RING_CONTEXT, invalid, - &fwcmd->params.request.context, false); - AMAP_SET_BITS_PTR(MCC_RING_CONTEXT, ring_size, - &fwcmd->params.request.context, num_entries_encoded); - - n = cq->cq_id; - AMAP_SET_BITS_PTR(MCC_RING_CONTEXT, - cq_id, &fwcmd->params.request.context, n); - be_rd_to_pa_list(rd, fwcmd->params.request.pages, - ARRAY_SIZE(fwcmd->params.request.pages)); - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "MCC to create CQ failed."); - goto error; - } - /* - * Create a linked list of context structures - */ - mcc->wrb_context.base = context_array; - mcc->wrb_context.num = num_context_entries; - INIT_LIST_HEAD(&mcc->wrb_context.list_head); - memset(context_array, 0, - sizeof(struct be_mcc_wrb_context) * num_context_entries); - for (i = 0; i < mcc->wrb_context.num; i++) { - list_add_tail(&context_array[i].next, - &mcc->wrb_context.list_head); - } - - /* - * - * Create an mcc_ring for tracking WRB hw ring - */ - va = rd->va; - ASSERT(va); - mp_ring_create(&mcc->sq.ring, length / sizeof(struct MCC_WRB_AMAP), - sizeof(struct MCC_WRB_AMAP), va); - mcc->sq.ring.id = fwcmd->params.response.id; - /* - * Init a mcc_ring for tracking the MCC CQ. - */ - ASSERT(cq->va); - mp_ring_create(&mcc->cq.ring, cq->num_entries, - sizeof(struct MCC_CQ_ENTRY_AMAP), cq->va); - mcc->cq.ring.id = cq->cq_id; - - /* Force zeroing of CQ. */ - memset(cq->va, 0, cq->num_entries * sizeof(struct MCC_CQ_ENTRY_AMAP)); - - /* Initialize debug index. */ - mcc->consumed_index = 0; - - atomic_inc(&cq->ref_count); - pfob->mcc = mcc; - - TRACE(DL_INFO, "MCC ring created. id:%d bytes:%d cq_id:%d cq_entries:%d" - " num_context:%d", mcc->sq.ring.id, length, - cq->cq_id, cq->num_entries, num_context_entries); - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine destroys an MCC send queue - - MccObject - Internal Mcc Object to be destroyed. - - Returns BE_SUCCESS if successfull, otherwise an error code is returned. - - IRQL < DISPATCH_LEVEL - - The caller of this routine must ensure that no other WRB may be posted - until this routine returns. - -*/ -int be_mcc_ring_destroy(struct be_mcc_object *mcc) -{ - int status = 0; - struct be_function_object *pfob = mcc->parent_function; - - - ASSERT(mcc->processing == 0); - - /* - * Remove the ring from the function object. - * This transitions back to mailbox mode. - */ - pfob->mcc = NULL; - - /* Send fwcmd to destroy the queue. (Using the mailbox.) */ - status = be_function_ring_destroy(mcc->parent_function, mcc->sq.ring.id, - FWCMD_RING_TYPE_MCC, NULL, NULL, NULL, NULL); - ASSERT(status == 0); - - /* Release the SQ reference to the CQ */ - atomic_dec(&mcc->cq_object->ref_count); - - return status; -} - -static void -mcc_wrb_sync_cb(void *context, int staus, struct MCC_WRB_AMAP *wrb) -{ - struct be_mcc_wrb_context *wrb_context = - (struct be_mcc_wrb_context *) context; - ASSERT(wrb_context); - *wrb_context->users_final_status = staus; -} - -/* - This routine posts a command to the MCC send queue - - mcc - Internal Mcc Object to be destroyed. - - wrb - wrb to post. - - Returns BE_SUCCESS if successfull, otherwise an error code is returned. - - IRQL < DISPATCH_LEVEL if CompletionCallback is not NULL - IRQL <=DISPATCH_LEVEL if CompletionCallback is NULL - - If this routine is called with CompletionCallback != NULL the - call is considered to be asynchronous and will return as soon - as the WRB is posted to the MCC with BE_PENDING. - - If CompletionCallback is NULL, then this routine will not return until - a completion for this MCC command has been processed. - If called at DISPATCH_LEVEL the CompletionCallback must be NULL. - - This routine should only be called if the MPU has been boostraped past - mailbox mode. - - -*/ -int -_be_mpu_post_wrb_ring(struct be_mcc_object *mcc, struct MCC_WRB_AMAP *wrb, - struct be_mcc_wrb_context *wrb_context) -{ - - struct MCC_WRB_AMAP *ring_wrb = NULL; - int status = BE_PENDING; - int final_status = BE_PENDING; - mcc_wrb_cqe_callback cb = NULL; - struct MCC_DB_AMAP mcc_db; - u32 embedded; - - ASSERT(mp_ring_num_empty(&mcc->sq.ring) > 0); - /* - * Input wrb is most likely the next wrb in the ring, since the client - * can peek at the address. - */ - ring_wrb = mp_ring_producer_ptr(&mcc->sq.ring); - if (wrb != ring_wrb) { - /* If not equal, copy it into the ring. */ - memcpy(ring_wrb, wrb, sizeof(struct MCC_WRB_AMAP)); - } -#ifdef BE_DEBUG - wrb_context->ring_wrb = ring_wrb; -#endif - embedded = AMAP_GET_BITS_PTR(MCC_WRB, embedded, ring_wrb); - if (embedded) { - /* embedded commands will have the response within the WRB. */ - wrb_context->wrb = ring_wrb; - } else { - /* - * non-embedded commands will not have the response - * within the WRB, and they may complete out-of-order. - * The WRB will not be valid to inspect - * during the completion. - */ - wrb_context->wrb = NULL; - } - cb = wrb_context->cb; - - if (cb == NULL) { - /* Assign our internal callback if this is a - * synchronous call. */ - wrb_context->cb = mcc_wrb_sync_cb; - wrb_context->cb_context = wrb_context; - wrb_context->users_final_status = &final_status; - } - /* Increment producer index */ - - mcc_db.dw[0] = 0; /* initialize */ - AMAP_SET_BITS_PTR(MCC_DB, rid, &mcc_db, mcc->sq.ring.id); - AMAP_SET_BITS_PTR(MCC_DB, numPosted, &mcc_db, 1); - - mp_ring_produce(&mcc->sq.ring); - PD_WRITE(mcc->parent_function, mpu_mcc_db, mcc_db.dw[0]); - TRACE(DL_INFO, "pidx: %x and cidx: %x.", mcc->sq.ring.pidx, - mcc->sq.ring.cidx); - - if (cb == NULL) { - int polls = 0; /* At >= 1 us per poll */ - /* Wait until this command completes, polling the CQ. */ - do { - TRACE(DL_INFO, "FWCMD submitted in the poll mode."); - /* Do not rearm CQ in this context. */ - be_mcc_process_cq(mcc, false); - - if (final_status == BE_PENDING) { - if ((++polls & 0x7FFFF) == 0) { - TRACE(DL_WARN, - "Warning : polling MCC CQ for %d" - "ms.", polls / 1000); - } - - udelay(1); - } - - /* final_status changed when the command completes */ - } while (final_status == BE_PENDING); - - status = final_status; - } - - return status; -} - -struct MCC_WRB_AMAP * -_be_mpu_peek_ring_wrb(struct be_mcc_object *mcc, bool driving_queue) -{ - /* If we have queued items, do not allow a post to bypass the queue. */ - if (!driving_queue && !list_empty(&mcc->backlog)) - return NULL; - - if (mp_ring_num_empty(&mcc->sq.ring) <= 0) - return NULL; - return (struct MCC_WRB_AMAP *) mp_ring_producer_ptr(&mcc->sq.ring); -} - -int -be_mpu_init_mailbox(struct be_function_object *pfob, struct ring_desc *mailbox) -{ - ASSERT(mailbox); - pfob->mailbox.va = mailbox->va; - pfob->mailbox.pa = cpu_to_le64(mailbox->pa); - pfob->mailbox.length = mailbox->length; - - ASSERT(((u32)(size_t)pfob->mailbox.va & 0xf) == 0); - ASSERT(((u32)(size_t)pfob->mailbox.pa & 0xf) == 0); - /* - * Issue the WRB to set MPU endianness - */ - { - u64 *endian_check = (u64 *) (pfob->mailbox.va + - offsetof(struct BE_MCC_MAILBOX_AMAP, wrb)/8); - *endian_check = 0xFF1234FFFF5678FFULL; - } - - be_mcc_mailbox_notify_and_wait(pfob); - - return BE_SUCCESS; -} - - -/* - This routine posts a command to the MCC mailbox. - - FuncObj - Function Object to post the WRB on behalf of. - wrb - wrb to post. - CompletionCallback - Address of a callback routine to invoke once the WRB - is completed. - CompletionCallbackContext - Opaque context to be passed during the call to - the CompletionCallback. - Returns BE_SUCCESS if successfull, otherwise an error code is returned. - - IRQL <=DISPATCH_LEVEL if CompletionCallback is NULL - - This routine will block until a completion for this MCC command has been - processed. If called at DISPATCH_LEVEL the CompletionCallback must be NULL. - - This routine should only be called if the MPU has not been boostraped past - mailbox mode. -*/ -int -_be_mpu_post_wrb_mailbox(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, struct be_mcc_wrb_context *wrb_context) -{ - struct MCC_MAILBOX_AMAP *mailbox = NULL; - struct MCC_WRB_AMAP *mb_wrb; - struct MCC_CQ_ENTRY_AMAP *mb_cq; - u32 offset, status; - - ASSERT(pfob->mcc == NULL); - mailbox = pfob->mailbox.va; - ASSERT(mailbox); - - offset = offsetof(struct BE_MCC_MAILBOX_AMAP, wrb)/8; - mb_wrb = (struct MCC_WRB_AMAP *) (u8 *)mailbox + offset; - if (mb_wrb != wrb) { - memset(mailbox, 0, sizeof(*mailbox)); - memcpy(mb_wrb, wrb, sizeof(struct MCC_WRB_AMAP)); - } - /* The callback can inspect the final WRB to get output parameters. */ - wrb_context->wrb = mb_wrb; - - be_mcc_mailbox_notify_and_wait(pfob); - - /* A command completed. Use tag to determine which command. */ - offset = offsetof(struct BE_MCC_MAILBOX_AMAP, cq)/8; - mb_cq = (struct MCC_CQ_ENTRY_AMAP *) ((u8 *)mailbox + offset); - be_mcc_process_cqe(pfob, mb_cq); - - status = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, completion_status, mb_cq); - if (status) - status = BE_NOT_OK; - return status; -} - -struct be_mcc_wrb_context * -_be_mcc_allocate_wrb_context(struct be_function_object *pfob) -{ - struct be_mcc_wrb_context *context = NULL; - unsigned long irq; - - spin_lock_irqsave(&pfob->mcc_context_lock, irq); - - if (!pfob->mailbox.default_context_allocated) { - /* Use the single default context that we - * always have allocated. */ - pfob->mailbox.default_context_allocated = true; - context = &pfob->mailbox.default_context; - } else if (pfob->mcc) { - /* Get a context from the free list. If any are available. */ - if (!list_empty(&pfob->mcc->wrb_context.list_head)) { - context = list_first_entry( - &pfob->mcc->wrb_context.list_head, - struct be_mcc_wrb_context, next); - } - } - - spin_unlock_irqrestore(&pfob->mcc_context_lock, irq); - - return context; -} - -void -_be_mcc_free_wrb_context(struct be_function_object *pfob, - struct be_mcc_wrb_context *context) -{ - unsigned long irq; - - ASSERT(context); - /* - * Zero during free to try and catch any bugs where the context - * is accessed after a free. - */ - memset(context, 0, sizeof(context)); - - spin_lock_irqsave(&pfob->mcc_context_lock, irq); - - if (context == &pfob->mailbox.default_context) { - /* Free the default context. */ - ASSERT(pfob->mailbox.default_context_allocated); - pfob->mailbox.default_context_allocated = false; - } else { - /* Add to free list. */ - ASSERT(pfob->mcc); - list_add_tail(&context->next, - &pfob->mcc->wrb_context.list_head); - } - - spin_unlock_irqrestore(&pfob->mcc_context_lock, irq); -} - -int -be_mcc_add_async_event_callback(struct be_mcc_object *mcc_object, - mcc_async_event_callback cb, void *cb_context) -{ - /* Lock against anyone trying to change the callback/context pointers - * while being used. */ - spin_lock_irqsave(&mcc_object->parent_function->cq_lock, - mcc_object->parent_function->cq_irq); - - /* Assign the async callback. */ - mcc_object->async_context = cb_context; - mcc_object->async_cb = cb; - - spin_unlock_irqrestore(&mcc_object->parent_function->cq_lock, - mcc_object->parent_function->cq_irq); - - return BE_SUCCESS; -} - -#define MPU_EP_CONTROL 0 -#define MPU_EP_SEMAPHORE 0xac - -/* - *------------------------------------------------------------------- - * Function: be_wait_for_POST_complete - * Waits until the BladeEngine POST completes (either in error or success). - * pfob - - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *------------------------------------------------------------------- - */ -static int be_wait_for_POST_complete(struct be_function_object *pfob) -{ - struct MGMT_HBA_POST_STATUS_STRUCT_AMAP status; - int s; - u32 post_error, post_stage; - - const u32 us_per_loop = 1000; /* 1000us */ - const u32 print_frequency_loops = 1000000 / us_per_loop; - const u32 max_loops = 60 * print_frequency_loops; - u32 loops = 0; - - /* - * Wait for arm fw indicating it is done or a fatal error happened. - * Note: POST can take some time to complete depending on configuration - * settings (consider ARM attempts to acquire an IP address - * over DHCP!!!). - * - */ - do { - status.dw[0] = ioread32(pfob->csr_va + MPU_EP_SEMAPHORE); - post_error = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, - error, &status); - post_stage = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, - stage, &status); - if (0 == (loops % print_frequency_loops)) { - /* Print current status */ - TRACE(DL_INFO, "POST status = 0x%x (stage = 0x%x)", - status.dw[0], post_stage); - } - udelay(us_per_loop); - } while ((post_error != 1) && - (post_stage != POST_STAGE_ARMFW_READY) && - (++loops < max_loops)); - - if (post_error == 1) { - TRACE(DL_ERR, "POST error! Status = 0x%x (stage = 0x%x)", - status.dw[0], post_stage); - s = BE_NOT_OK; - } else if (post_stage != POST_STAGE_ARMFW_READY) { - TRACE(DL_ERR, "POST time-out! Status = 0x%x (stage = 0x%x)", - status.dw[0], post_stage); - s = BE_NOT_OK; - } else { - s = BE_SUCCESS; - } - return s; -} - -/* - *------------------------------------------------------------------- - * Function: be_kickoff_and_wait_for_POST - * Interacts with the BladeEngine management processor to initiate POST, and - * subsequently waits until POST completes (either in error or success). - * The caller must acquire the reset semaphore before initiating POST - * to prevent multiple drivers interacting with the management processor. - * Once POST is complete the caller must release the reset semaphore. - * Callers who only want to wait for POST complete may call - * be_wait_for_POST_complete. - * pfob - - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *------------------------------------------------------------------- - */ -static int -be_kickoff_and_wait_for_POST(struct be_function_object *pfob) -{ - struct MGMT_HBA_POST_STATUS_STRUCT_AMAP status; - int s; - - const u32 us_per_loop = 1000; /* 1000us */ - const u32 print_frequency_loops = 1000000 / us_per_loop; - const u32 max_loops = 5 * print_frequency_loops; - u32 loops = 0; - u32 post_error, post_stage; - - /* Wait for arm fw awaiting host ready or a fatal error happened. */ - TRACE(DL_INFO, "Wait for BladeEngine ready to POST"); - do { - status.dw[0] = ioread32(pfob->csr_va + MPU_EP_SEMAPHORE); - post_error = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, - error, &status); - post_stage = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, - stage, &status); - if (0 == (loops % print_frequency_loops)) { - /* Print current status */ - TRACE(DL_INFO, "POST status = 0x%x (stage = 0x%x)", - status.dw[0], post_stage); - } - udelay(us_per_loop); - } while ((post_error != 1) && - (post_stage < POST_STAGE_AWAITING_HOST_RDY) && - (++loops < max_loops)); - - if (post_error == 1) { - TRACE(DL_ERR, "Pre-POST error! Status = 0x%x (stage = 0x%x)", - status.dw[0], post_stage); - s = BE_NOT_OK; - } else if (post_stage == POST_STAGE_AWAITING_HOST_RDY) { - iowrite32(POST_STAGE_HOST_RDY, pfob->csr_va + MPU_EP_SEMAPHORE); - - /* Wait for POST to complete */ - s = be_wait_for_POST_complete(pfob); - } else { - /* - * Either a timeout waiting for host ready signal or POST has - * moved ahead without requiring a host ready signal. - * Might as well give POST a chance to complete - * (or timeout again). - */ - s = be_wait_for_POST_complete(pfob); - } - return s; -} - -/* - *------------------------------------------------------------------- - * Function: be_pci_soft_reset - * This function is called to issue a BladeEngine soft reset. - * Callers should acquire the soft reset semaphore before calling this - * function. Additionaly, callers should ensure they cannot be pre-empted - * while the routine executes. Upon completion of this routine, callers - * should release the reset semaphore. This routine implicitly waits - * for BladeEngine POST to complete. - * pfob - - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *------------------------------------------------------------------- - */ -int be_pci_soft_reset(struct be_function_object *pfob) -{ - struct PCICFG_SOFT_RESET_CSR_AMAP soft_reset; - struct PCICFG_ONLINE0_CSR_AMAP pciOnline0; - struct PCICFG_ONLINE1_CSR_AMAP pciOnline1; - struct EP_CONTROL_CSR_AMAP epControlCsr; - int status = BE_SUCCESS; - u32 i, soft_reset_bit; - - TRACE(DL_NOTE, "PCI reset..."); - - /* Issue soft reset #1 to get BladeEngine into a known state. */ - soft_reset.dw[0] = PCICFG0_READ(pfob, soft_reset); - AMAP_SET_BITS_PTR(PCICFG_SOFT_RESET_CSR, softreset, soft_reset.dw, 1); - PCICFG0_WRITE(pfob, host_timer_int_ctrl, soft_reset.dw[0]); - /* - * wait til soft reset is deasserted - hardware - * deasserts after some time. - */ - i = 0; - do { - udelay(50); - soft_reset.dw[0] = PCICFG0_READ(pfob, soft_reset); - soft_reset_bit = AMAP_GET_BITS_PTR(PCICFG_SOFT_RESET_CSR, - softreset, soft_reset.dw); - } while (soft_reset_bit && (i++ < 1024)); - if (soft_reset_bit != 0) { - TRACE(DL_ERR, "Soft-reset #1 did not deassert as expected."); - status = BE_NOT_OK; - goto Error_label; - } - /* Mask everything */ - PCICFG0_WRITE(pfob, ue_status_low_mask, 0xFFFFFFFF); - PCICFG0_WRITE(pfob, ue_status_hi_mask, 0xFFFFFFFF); - /* - * Set everything offline except MPU IRAM (it is offline with - * the soft-reset, but soft-reset does not reset the PCICFG registers!) - */ - pciOnline0.dw[0] = 0; - pciOnline1.dw[0] = 0; - AMAP_SET_BITS_PTR(PCICFG_ONLINE1_CSR, mpu_iram_online, - pciOnline1.dw, 1); - PCICFG0_WRITE(pfob, online0, pciOnline0.dw[0]); - PCICFG0_WRITE(pfob, online1, pciOnline1.dw[0]); - - udelay(20000); - - /* Issue soft reset #2. */ - AMAP_SET_BITS_PTR(PCICFG_SOFT_RESET_CSR, softreset, soft_reset.dw, 1); - PCICFG0_WRITE(pfob, host_timer_int_ctrl, soft_reset.dw[0]); - /* - * wait til soft reset is deasserted - hardware - * deasserts after some time. - */ - i = 0; - do { - udelay(50); - soft_reset.dw[0] = PCICFG0_READ(pfob, soft_reset); - soft_reset_bit = AMAP_GET_BITS_PTR(PCICFG_SOFT_RESET_CSR, - softreset, soft_reset.dw); - } while (soft_reset_bit && (i++ < 1024)); - if (soft_reset_bit != 0) { - TRACE(DL_ERR, "Soft-reset #1 did not deassert as expected."); - status = BE_NOT_OK; - goto Error_label; - } - - - udelay(20000); - - /* Take MPU out of reset. */ - - epControlCsr.dw[0] = ioread32(pfob->csr_va + MPU_EP_CONTROL); - AMAP_SET_BITS_PTR(EP_CONTROL_CSR, CPU_reset, &epControlCsr, 0); - iowrite32((u32)epControlCsr.dw[0], pfob->csr_va + MPU_EP_CONTROL); - - /* Kickoff BE POST and wait for completion */ - status = be_kickoff_and_wait_for_POST(pfob); - -Error_label: - return status; -} - - -/* - *------------------------------------------------------------------- - * Function: be_pci_reset_required - * This private function is called to detect if a host entity is - * required to issue a PCI soft reset and subsequently drive - * BladeEngine POST. Scenarios where this is required: - * 1) BIOS-less configuration - * 2) Hot-swap/plug/power-on - * pfob - - * return true if a reset is required, false otherwise - *------------------------------------------------------------------- - */ -static bool be_pci_reset_required(struct be_function_object *pfob) -{ - struct MGMT_HBA_POST_STATUS_STRUCT_AMAP status; - bool do_reset = false; - u32 post_error, post_stage; - - /* - * Read the POST status register - */ - status.dw[0] = ioread32(pfob->csr_va + MPU_EP_SEMAPHORE); - post_error = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, error, - &status); - post_stage = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, stage, - &status); - if (post_stage <= POST_STAGE_AWAITING_HOST_RDY) { - /* - * If BladeEngine is waiting for host ready indication, - * we want to do a PCI reset. - */ - do_reset = true; - } - - return do_reset; -} - -/* - *------------------------------------------------------------------- - * Function: be_drive_POST - * This function is called to drive BladeEngine POST. The - * caller should ensure they cannot be pre-empted while this routine executes. - * pfob - - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *------------------------------------------------------------------- - */ -int be_drive_POST(struct be_function_object *pfob) -{ - int status; - - if (false != be_pci_reset_required(pfob)) { - /* PCI reset is needed (implicitly starts and waits for POST) */ - status = be_pci_soft_reset(pfob); - } else { - /* No PCI reset is needed, start POST */ - status = be_kickoff_and_wait_for_POST(pfob); - } - - return status; -} diff --git a/drivers/staging/benet/mpu.h b/drivers/staging/benet/mpu.h deleted file mode 100644 index 41f3f87516e..00000000000 --- a/drivers/staging/benet/mpu.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __mpu_amap_h__ -#define __mpu_amap_h__ -#include "ep.h" - -/* Provide control parameters for the Managment Processor Unit. */ -struct BE_MPU_CSRMAP_AMAP { - struct BE_EP_CSRMAP_AMAP ep; - u8 rsvd0[128]; /* DWORD 64 */ - u8 rsvd1[32]; /* DWORD 68 */ - u8 rsvd2[192]; /* DWORD 69 */ - u8 rsvd3[192]; /* DWORD 75 */ - u8 rsvd4[32]; /* DWORD 81 */ - u8 rsvd5[32]; /* DWORD 82 */ - u8 rsvd6[32]; /* DWORD 83 */ - u8 rsvd7[32]; /* DWORD 84 */ - u8 rsvd8[32]; /* DWORD 85 */ - u8 rsvd9[32]; /* DWORD 86 */ - u8 rsvd10[32]; /* DWORD 87 */ - u8 rsvd11[32]; /* DWORD 88 */ - u8 rsvd12[32]; /* DWORD 89 */ - u8 rsvd13[32]; /* DWORD 90 */ - u8 rsvd14[32]; /* DWORD 91 */ - u8 rsvd15[32]; /* DWORD 92 */ - u8 rsvd16[32]; /* DWORD 93 */ - u8 rsvd17[32]; /* DWORD 94 */ - u8 rsvd18[32]; /* DWORD 95 */ - u8 rsvd19[32]; /* DWORD 96 */ - u8 rsvd20[32]; /* DWORD 97 */ - u8 rsvd21[32]; /* DWORD 98 */ - u8 rsvd22[32]; /* DWORD 99 */ - u8 rsvd23[32]; /* DWORD 100 */ - u8 rsvd24[32]; /* DWORD 101 */ - u8 rsvd25[32]; /* DWORD 102 */ - u8 rsvd26[32]; /* DWORD 103 */ - u8 rsvd27[32]; /* DWORD 104 */ - u8 rsvd28[96]; /* DWORD 105 */ - u8 rsvd29[32]; /* DWORD 108 */ - u8 rsvd30[32]; /* DWORD 109 */ - u8 rsvd31[32]; /* DWORD 110 */ - u8 rsvd32[32]; /* DWORD 111 */ - u8 rsvd33[32]; /* DWORD 112 */ - u8 rsvd34[96]; /* DWORD 113 */ - u8 rsvd35[32]; /* DWORD 116 */ - u8 rsvd36[32]; /* DWORD 117 */ - u8 rsvd37[32]; /* DWORD 118 */ - u8 rsvd38[32]; /* DWORD 119 */ - u8 rsvd39[32]; /* DWORD 120 */ - u8 rsvd40[32]; /* DWORD 121 */ - u8 rsvd41[134][32]; /* DWORD 122 */ -} __packed; -struct MPU_CSRMAP_AMAP { - u32 dw[256]; -}; - -#endif /* __mpu_amap_h__ */ diff --git a/drivers/staging/benet/mpu_context.h b/drivers/staging/benet/mpu_context.h deleted file mode 100644 index 8ce90f9c46c..00000000000 --- a/drivers/staging/benet/mpu_context.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __mpu_context_amap_h__ -#define __mpu_context_amap_h__ - -/* - * Management command and control ring context. The MPUs BTLR_CTRL1 CSR - * controls the writeback behavior of the producer and consumer index values. - */ -struct BE_MCC_RING_CONTEXT_AMAP { - u8 con_index[16]; /* DWORD 0 */ - u8 ring_size[4]; /* DWORD 0 */ - u8 cq_id[11]; /* DWORD 0 */ - u8 rsvd0; /* DWORD 0 */ - u8 prod_index[16]; /* DWORD 1 */ - u8 pdid[15]; /* DWORD 1 */ - u8 invalid; /* DWORD 1 */ - u8 cmd_pending_current[7]; /* DWORD 2 */ - u8 rsvd1[25]; /* DWORD 2 */ - u8 hpi_port_cq_id[11]; /* DWORD 3 */ - u8 rsvd2[5]; /* DWORD 3 */ - u8 cmd_pending_max[7]; /* DWORD 3 */ - u8 rsvd3[9]; /* DWORD 3 */ -} __packed; -struct MCC_RING_CONTEXT_AMAP { - u32 dw[4]; -}; - -#endif /* __mpu_context_amap_h__ */ diff --git a/drivers/staging/benet/pcicfg.h b/drivers/staging/benet/pcicfg.h deleted file mode 100644 index 7c15684adf4..00000000000 --- a/drivers/staging/benet/pcicfg.h +++ /dev/null @@ -1,825 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __pcicfg_amap_h__ -#define __pcicfg_amap_h__ - -/* Vendor and Device ID Register. */ -struct BE_PCICFG_ID_CSR_AMAP { - u8 vendorid[16]; /* DWORD 0 */ - u8 deviceid[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_ID_CSR_AMAP { - u32 dw[1]; -}; - -/* IO Bar Register. */ -struct BE_PCICFG_IOBAR_CSR_AMAP { - u8 iospace; /* DWORD 0 */ - u8 rsvd0[7]; /* DWORD 0 */ - u8 iobar[24]; /* DWORD 0 */ -} __packed; -struct PCICFG_IOBAR_CSR_AMAP { - u32 dw[1]; -}; - -/* Memory BAR 0 Register. */ -struct BE_PCICFG_MEMBAR0_CSR_AMAP { - u8 memspace; /* DWORD 0 */ - u8 type[2]; /* DWORD 0 */ - u8 pf; /* DWORD 0 */ - u8 rsvd0[10]; /* DWORD 0 */ - u8 membar0[18]; /* DWORD 0 */ -} __packed; -struct PCICFG_MEMBAR0_CSR_AMAP { - u32 dw[1]; -}; - -/* Memory BAR 1 - Low Address Register. */ -struct BE_PCICFG_MEMBAR1_LO_CSR_AMAP { - u8 memspace; /* DWORD 0 */ - u8 type[2]; /* DWORD 0 */ - u8 pf; /* DWORD 0 */ - u8 rsvd0[13]; /* DWORD 0 */ - u8 membar1lo[15]; /* DWORD 0 */ -} __packed; -struct PCICFG_MEMBAR1_LO_CSR_AMAP { - u32 dw[1]; -}; - -/* Memory BAR 1 - High Address Register. */ -struct BE_PCICFG_MEMBAR1_HI_CSR_AMAP { - u8 membar1hi[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_MEMBAR1_HI_CSR_AMAP { - u32 dw[1]; -}; - -/* Memory BAR 2 - Low Address Register. */ -struct BE_PCICFG_MEMBAR2_LO_CSR_AMAP { - u8 memspace; /* DWORD 0 */ - u8 type[2]; /* DWORD 0 */ - u8 pf; /* DWORD 0 */ - u8 rsvd0[17]; /* DWORD 0 */ - u8 membar2lo[11]; /* DWORD 0 */ -} __packed; -struct PCICFG_MEMBAR2_LO_CSR_AMAP { - u32 dw[1]; -}; - -/* Memory BAR 2 - High Address Register. */ -struct BE_PCICFG_MEMBAR2_HI_CSR_AMAP { - u8 membar2hi[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_MEMBAR2_HI_CSR_AMAP { - u32 dw[1]; -}; - -/* Subsystem Vendor and ID (Function 0) Register. */ -struct BE_PCICFG_SUBSYSTEM_ID_F0_CSR_AMAP { - u8 subsys_vendor_id[16]; /* DWORD 0 */ - u8 subsys_id[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_SUBSYSTEM_ID_F0_CSR_AMAP { - u32 dw[1]; -}; - -/* Subsystem Vendor and ID (Function 1) Register. */ -struct BE_PCICFG_SUBSYSTEM_ID_F1_CSR_AMAP { - u8 subsys_vendor_id[16]; /* DWORD 0 */ - u8 subsys_id[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_SUBSYSTEM_ID_F1_CSR_AMAP { - u32 dw[1]; -}; - -/* Semaphore Register. */ -struct BE_PCICFG_SEMAPHORE_CSR_AMAP { - u8 locked; /* DWORD 0 */ - u8 rsvd0[31]; /* DWORD 0 */ -} __packed; -struct PCICFG_SEMAPHORE_CSR_AMAP { - u32 dw[1]; -}; - -/* Soft Reset Register. */ -struct BE_PCICFG_SOFT_RESET_CSR_AMAP { - u8 rsvd0[7]; /* DWORD 0 */ - u8 softreset; /* DWORD 0 */ - u8 rsvd1[16]; /* DWORD 0 */ - u8 nec_ll_rcvdetect_i[8]; /* DWORD 0 */ -} __packed; -struct PCICFG_SOFT_RESET_CSR_AMAP { - u32 dw[1]; -}; - -/* Unrecoverable Error Status (Low) Register. Each bit corresponds to - * an internal Unrecoverable Error. These are set by hardware and may be - * cleared by writing a one to the respective bit(s) to be cleared. Any - * bit being set that is also unmasked will result in Unrecoverable Error - * interrupt notification to the host CPU and/or Server Management chip - * and the transitioning of BladeEngine to an Offline state. - */ -struct BE_PCICFG_UE_STATUS_LOW_CSR_AMAP { - u8 cev_ue_status; /* DWORD 0 */ - u8 ctx_ue_status; /* DWORD 0 */ - u8 dbuf_ue_status; /* DWORD 0 */ - u8 erx_ue_status; /* DWORD 0 */ - u8 host_ue_status; /* DWORD 0 */ - u8 mpu_ue_status; /* DWORD 0 */ - u8 ndma_ue_status; /* DWORD 0 */ - u8 ptc_ue_status; /* DWORD 0 */ - u8 rdma_ue_status; /* DWORD 0 */ - u8 rxf_ue_status; /* DWORD 0 */ - u8 rxips_ue_status; /* DWORD 0 */ - u8 rxulp0_ue_status; /* DWORD 0 */ - u8 rxulp1_ue_status; /* DWORD 0 */ - u8 rxulp2_ue_status; /* DWORD 0 */ - u8 tim_ue_status; /* DWORD 0 */ - u8 tpost_ue_status; /* DWORD 0 */ - u8 tpre_ue_status; /* DWORD 0 */ - u8 txips_ue_status; /* DWORD 0 */ - u8 txulp0_ue_status; /* DWORD 0 */ - u8 txulp1_ue_status; /* DWORD 0 */ - u8 uc_ue_status; /* DWORD 0 */ - u8 wdma_ue_status; /* DWORD 0 */ - u8 txulp2_ue_status; /* DWORD 0 */ - u8 host1_ue_status; /* DWORD 0 */ - u8 p0_ob_link_ue_status; /* DWORD 0 */ - u8 p1_ob_link_ue_status; /* DWORD 0 */ - u8 host_gpio_ue_status; /* DWORD 0 */ - u8 mbox_netw_ue_status; /* DWORD 0 */ - u8 mbox_stor_ue_status; /* DWORD 0 */ - u8 axgmac0_ue_status; /* DWORD 0 */ - u8 axgmac1_ue_status; /* DWORD 0 */ - u8 mpu_intpend_ue_status; /* DWORD 0 */ -} __packed; -struct PCICFG_UE_STATUS_LOW_CSR_AMAP { - u32 dw[1]; -}; - -/* Unrecoverable Error Status (High) Register. Each bit corresponds to - * an internal Unrecoverable Error. These are set by hardware and may be - * cleared by writing a one to the respective bit(s) to be cleared. Any - * bit being set that is also unmasked will result in Unrecoverable Error - * interrupt notification to the host CPU and/or Server Management chip; - * and the transitioning of BladeEngine to an Offline state. - */ -struct BE_PCICFG_UE_STATUS_HI_CSR_AMAP { - u8 jtag_ue_status; /* DWORD 0 */ - u8 lpcmemhost_ue_status; /* DWORD 0 */ - u8 mgmt_mac_ue_status; /* DWORD 0 */ - u8 mpu_iram_ue_status; /* DWORD 0 */ - u8 pcs0online_ue_status; /* DWORD 0 */ - u8 pcs1online_ue_status; /* DWORD 0 */ - u8 pctl0_ue_status; /* DWORD 0 */ - u8 pctl1_ue_status; /* DWORD 0 */ - u8 pmem_ue_status; /* DWORD 0 */ - u8 rr_ue_status; /* DWORD 0 */ - u8 rxpp_ue_status; /* DWORD 0 */ - u8 txpb_ue_status; /* DWORD 0 */ - u8 txp_ue_status; /* DWORD 0 */ - u8 xaui_ue_status; /* DWORD 0 */ - u8 arm_ue_status; /* DWORD 0 */ - u8 ipc_ue_status; /* DWORD 0 */ - u8 rsvd0[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_UE_STATUS_HI_CSR_AMAP { - u32 dw[1]; -}; - -/* Unrecoverable Error Mask (Low) Register. Each bit, when set to one, - * will mask the associated Unrecoverable Error status bit from notification - * of Unrecoverable Error to the host CPU and/or Server Managment chip and the - * transitioning of all BladeEngine units to an Offline state. - */ -struct BE_PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP { - u8 cev_ue_mask; /* DWORD 0 */ - u8 ctx_ue_mask; /* DWORD 0 */ - u8 dbuf_ue_mask; /* DWORD 0 */ - u8 erx_ue_mask; /* DWORD 0 */ - u8 host_ue_mask; /* DWORD 0 */ - u8 mpu_ue_mask; /* DWORD 0 */ - u8 ndma_ue_mask; /* DWORD 0 */ - u8 ptc_ue_mask; /* DWORD 0 */ - u8 rdma_ue_mask; /* DWORD 0 */ - u8 rxf_ue_mask; /* DWORD 0 */ - u8 rxips_ue_mask; /* DWORD 0 */ - u8 rxulp0_ue_mask; /* DWORD 0 */ - u8 rxulp1_ue_mask; /* DWORD 0 */ - u8 rxulp2_ue_mask; /* DWORD 0 */ - u8 tim_ue_mask; /* DWORD 0 */ - u8 tpost_ue_mask; /* DWORD 0 */ - u8 tpre_ue_mask; /* DWORD 0 */ - u8 txips_ue_mask; /* DWORD 0 */ - u8 txulp0_ue_mask; /* DWORD 0 */ - u8 txulp1_ue_mask; /* DWORD 0 */ - u8 uc_ue_mask; /* DWORD 0 */ - u8 wdma_ue_mask; /* DWORD 0 */ - u8 txulp2_ue_mask; /* DWORD 0 */ - u8 host1_ue_mask; /* DWORD 0 */ - u8 p0_ob_link_ue_mask; /* DWORD 0 */ - u8 p1_ob_link_ue_mask; /* DWORD 0 */ - u8 host_gpio_ue_mask; /* DWORD 0 */ - u8 mbox_netw_ue_mask; /* DWORD 0 */ - u8 mbox_stor_ue_mask; /* DWORD 0 */ - u8 axgmac0_ue_mask; /* DWORD 0 */ - u8 axgmac1_ue_mask; /* DWORD 0 */ - u8 mpu_intpend_ue_mask; /* DWORD 0 */ -} __packed; -struct PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP { - u32 dw[1]; -}; - -/* Unrecoverable Error Mask (High) Register. Each bit, when set to one, - * will mask the associated Unrecoverable Error status bit from notification - * of Unrecoverable Error to the host CPU and/or Server Managment chip and the - * transitioning of all BladeEngine units to an Offline state. - */ -struct BE_PCICFG_UE_STATUS_HI_MASK_CSR_AMAP { - u8 jtag_ue_mask; /* DWORD 0 */ - u8 lpcmemhost_ue_mask; /* DWORD 0 */ - u8 mgmt_mac_ue_mask; /* DWORD 0 */ - u8 mpu_iram_ue_mask; /* DWORD 0 */ - u8 pcs0online_ue_mask; /* DWORD 0 */ - u8 pcs1online_ue_mask; /* DWORD 0 */ - u8 pctl0_ue_mask; /* DWORD 0 */ - u8 pctl1_ue_mask; /* DWORD 0 */ - u8 pmem_ue_mask; /* DWORD 0 */ - u8 rr_ue_mask; /* DWORD 0 */ - u8 rxpp_ue_mask; /* DWORD 0 */ - u8 txpb_ue_mask; /* DWORD 0 */ - u8 txp_ue_mask; /* DWORD 0 */ - u8 xaui_ue_mask; /* DWORD 0 */ - u8 arm_ue_mask; /* DWORD 0 */ - u8 ipc_ue_mask; /* DWORD 0 */ - u8 rsvd0[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_UE_STATUS_HI_MASK_CSR_AMAP { - u32 dw[1]; -}; - -/* Online Control Register 0. This register controls various units within - * BladeEngine being in an Online or Offline state. - */ -struct BE_PCICFG_ONLINE0_CSR_AMAP { - u8 cev_online; /* DWORD 0 */ - u8 ctx_online; /* DWORD 0 */ - u8 dbuf_online; /* DWORD 0 */ - u8 erx_online; /* DWORD 0 */ - u8 host_online; /* DWORD 0 */ - u8 mpu_online; /* DWORD 0 */ - u8 ndma_online; /* DWORD 0 */ - u8 ptc_online; /* DWORD 0 */ - u8 rdma_online; /* DWORD 0 */ - u8 rxf_online; /* DWORD 0 */ - u8 rxips_online; /* DWORD 0 */ - u8 rxulp0_online; /* DWORD 0 */ - u8 rxulp1_online; /* DWORD 0 */ - u8 rxulp2_online; /* DWORD 0 */ - u8 tim_online; /* DWORD 0 */ - u8 tpost_online; /* DWORD 0 */ - u8 tpre_online; /* DWORD 0 */ - u8 txips_online; /* DWORD 0 */ - u8 txulp0_online; /* DWORD 0 */ - u8 txulp1_online; /* DWORD 0 */ - u8 uc_online; /* DWORD 0 */ - u8 wdma_online; /* DWORD 0 */ - u8 txulp2_online; /* DWORD 0 */ - u8 host1_online; /* DWORD 0 */ - u8 p0_ob_link_online; /* DWORD 0 */ - u8 p1_ob_link_online; /* DWORD 0 */ - u8 host_gpio_online; /* DWORD 0 */ - u8 mbox_netw_online; /* DWORD 0 */ - u8 mbox_stor_online; /* DWORD 0 */ - u8 axgmac0_online; /* DWORD 0 */ - u8 axgmac1_online; /* DWORD 0 */ - u8 mpu_intpend_online; /* DWORD 0 */ -} __packed; -struct PCICFG_ONLINE0_CSR_AMAP { - u32 dw[1]; -}; - -/* Online Control Register 1. This register controls various units within - * BladeEngine being in an Online or Offline state. - */ -struct BE_PCICFG_ONLINE1_CSR_AMAP { - u8 jtag_online; /* DWORD 0 */ - u8 lpcmemhost_online; /* DWORD 0 */ - u8 mgmt_mac_online; /* DWORD 0 */ - u8 mpu_iram_online; /* DWORD 0 */ - u8 pcs0online_online; /* DWORD 0 */ - u8 pcs1online_online; /* DWORD 0 */ - u8 pctl0_online; /* DWORD 0 */ - u8 pctl1_online; /* DWORD 0 */ - u8 pmem_online; /* DWORD 0 */ - u8 rr_online; /* DWORD 0 */ - u8 rxpp_online; /* DWORD 0 */ - u8 txpb_online; /* DWORD 0 */ - u8 txp_online; /* DWORD 0 */ - u8 xaui_online; /* DWORD 0 */ - u8 arm_online; /* DWORD 0 */ - u8 ipc_online; /* DWORD 0 */ - u8 rsvd0[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_ONLINE1_CSR_AMAP { - u32 dw[1]; -}; - -/* Host Timer Register. */ -struct BE_PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP { - u8 hosttimer[24]; /* DWORD 0 */ - u8 hostintr; /* DWORD 0 */ - u8 rsvd0[7]; /* DWORD 0 */ -} __packed; -struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP { - u32 dw[1]; -}; - -/* Scratchpad Register (for software use). */ -struct BE_PCICFG_SCRATCHPAD_CSR_AMAP { - u8 scratchpad[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_SCRATCHPAD_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express Capabilities Register. */ -struct BE_PCICFG_PCIE_CAP_CSR_AMAP { - u8 capid[8]; /* DWORD 0 */ - u8 nextcap[8]; /* DWORD 0 */ - u8 capver[4]; /* DWORD 0 */ - u8 devport[4]; /* DWORD 0 */ - u8 rsvd0[6]; /* DWORD 0 */ - u8 rsvd1[2]; /* DWORD 0 */ -} __packed; -struct PCICFG_PCIE_CAP_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express Device Capabilities Register. */ -struct BE_PCICFG_PCIE_DEVCAP_CSR_AMAP { - u8 payload[3]; /* DWORD 0 */ - u8 rsvd0[3]; /* DWORD 0 */ - u8 lo_lat[3]; /* DWORD 0 */ - u8 l1_lat[3]; /* DWORD 0 */ - u8 rsvd1[3]; /* DWORD 0 */ - u8 rsvd2[3]; /* DWORD 0 */ - u8 pwr_value[8]; /* DWORD 0 */ - u8 pwr_scale[2]; /* DWORD 0 */ - u8 rsvd3[4]; /* DWORD 0 */ -} __packed; -struct PCICFG_PCIE_DEVCAP_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express Device Control/Status Registers. */ -struct BE_PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP { - u8 CorrErrReportEn; /* DWORD 0 */ - u8 NonFatalErrReportEn; /* DWORD 0 */ - u8 FatalErrReportEn; /* DWORD 0 */ - u8 UnsuppReqReportEn; /* DWORD 0 */ - u8 EnableRelaxOrder; /* DWORD 0 */ - u8 Max_Payload_Size[3]; /* DWORD 0 */ - u8 ExtendTagFieldEnable; /* DWORD 0 */ - u8 PhantomFnEnable; /* DWORD 0 */ - u8 AuxPwrPMEnable; /* DWORD 0 */ - u8 EnableNoSnoop; /* DWORD 0 */ - u8 Max_Read_Req_Size[3]; /* DWORD 0 */ - u8 rsvd0; /* DWORD 0 */ - u8 CorrErrDetect; /* DWORD 0 */ - u8 NonFatalErrDetect; /* DWORD 0 */ - u8 FatalErrDetect; /* DWORD 0 */ - u8 UnsuppReqDetect; /* DWORD 0 */ - u8 AuxPwrDetect; /* DWORD 0 */ - u8 TransPending; /* DWORD 0 */ - u8 rsvd1[10]; /* DWORD 0 */ -} __packed; -struct PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express Link Capabilities Register. */ -struct BE_PCICFG_PCIE_LINK_CAP_CSR_AMAP { - u8 MaxLinkSpeed[4]; /* DWORD 0 */ - u8 MaxLinkWidth[6]; /* DWORD 0 */ - u8 ASPMSupport[2]; /* DWORD 0 */ - u8 L0sExitLat[3]; /* DWORD 0 */ - u8 L1ExitLat[3]; /* DWORD 0 */ - u8 rsvd0[6]; /* DWORD 0 */ - u8 PortNum[8]; /* DWORD 0 */ -} __packed; -struct PCICFG_PCIE_LINK_CAP_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express Link Status Register. */ -struct BE_PCICFG_PCIE_LINK_STATUS_CSR_AMAP { - u8 ASPMCtl[2]; /* DWORD 0 */ - u8 rsvd0; /* DWORD 0 */ - u8 ReadCmplBndry; /* DWORD 0 */ - u8 LinkDisable; /* DWORD 0 */ - u8 RetrainLink; /* DWORD 0 */ - u8 CommonClkConfig; /* DWORD 0 */ - u8 ExtendSync; /* DWORD 0 */ - u8 rsvd1[8]; /* DWORD 0 */ - u8 LinkSpeed[4]; /* DWORD 0 */ - u8 NegLinkWidth[6]; /* DWORD 0 */ - u8 LinkTrainErr; /* DWORD 0 */ - u8 LinkTrain; /* DWORD 0 */ - u8 SlotClkConfig; /* DWORD 0 */ - u8 rsvd2[3]; /* DWORD 0 */ -} __packed; -struct PCICFG_PCIE_LINK_STATUS_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express MSI Configuration Register. */ -struct BE_PCICFG_MSI_CSR_AMAP { - u8 capid[8]; /* DWORD 0 */ - u8 nextptr[8]; /* DWORD 0 */ - u8 tablesize[11]; /* DWORD 0 */ - u8 rsvd0[3]; /* DWORD 0 */ - u8 funcmask; /* DWORD 0 */ - u8 en; /* DWORD 0 */ -} __packed; -struct PCICFG_MSI_CSR_AMAP { - u32 dw[1]; -}; - -/* MSI-X Table Offset Register. */ -struct BE_PCICFG_MSIX_TABLE_CSR_AMAP { - u8 tablebir[3]; /* DWORD 0 */ - u8 offset[29]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_TABLE_CSR_AMAP { - u32 dw[1]; -}; - -/* MSI-X PBA Offset Register. */ -struct BE_PCICFG_MSIX_PBA_CSR_AMAP { - u8 pbabir[3]; /* DWORD 0 */ - u8 offset[29]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_PBA_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express MSI-X Message Vector Control Register. */ -struct BE_PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP { - u8 vector_control; /* DWORD 0 */ - u8 rsvd0[31]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express MSI-X Message Data Register. */ -struct BE_PCICFG_MSIX_MSG_DATA_CSR_AMAP { - u8 data[16]; /* DWORD 0 */ - u8 rsvd0[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_MSG_DATA_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express MSI-X Message Address Register - High Part. */ -struct BE_PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP { - u8 addr[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express MSI-X Message Address Register - Low Part. */ -struct BE_PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP { - u8 rsvd0[2]; /* DWORD 0 */ - u8 addr[30]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_18_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_ANON_18_RSVD_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_19_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_ANON_19_RSVD_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_20_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[25][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_20_RSVD_AMAP { - u32 dw[26]; -}; - -struct BE_PCICFG_ANON_21_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[1919][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_21_RSVD_AMAP { - u32 dw[1920]; -}; - -struct BE_PCICFG_ANON_22_MESSAGE_AMAP { - struct BE_PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP vec_ctrl; - struct BE_PCICFG_MSIX_MSG_DATA_CSR_AMAP msg_data; - struct BE_PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP addr_hi; - struct BE_PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP addr_low; -} __packed; -struct PCICFG_ANON_22_MESSAGE_AMAP { - u32 dw[4]; -}; - -struct BE_PCICFG_ANON_23_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[895][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_23_RSVD_AMAP { - u32 dw[896]; -}; - -/* These PCI Configuration Space registers are for the Storage Function of - * BladeEngine (Function 0). In the memory map of the registers below their - * table, - */ -struct BE_PCICFG0_CSRMAP_AMAP { - struct BE_PCICFG_ID_CSR_AMAP id; - u8 rsvd0[32]; /* DWORD 1 */ - u8 rsvd1[32]; /* DWORD 2 */ - u8 rsvd2[32]; /* DWORD 3 */ - struct BE_PCICFG_IOBAR_CSR_AMAP iobar; - struct BE_PCICFG_MEMBAR0_CSR_AMAP membar0; - struct BE_PCICFG_MEMBAR1_LO_CSR_AMAP membar1_lo; - struct BE_PCICFG_MEMBAR1_HI_CSR_AMAP membar1_hi; - struct BE_PCICFG_MEMBAR2_LO_CSR_AMAP membar2_lo; - struct BE_PCICFG_MEMBAR2_HI_CSR_AMAP membar2_hi; - u8 rsvd3[32]; /* DWORD 10 */ - struct BE_PCICFG_SUBSYSTEM_ID_F0_CSR_AMAP subsystem_id; - u8 rsvd4[32]; /* DWORD 12 */ - u8 rsvd5[32]; /* DWORD 13 */ - u8 rsvd6[32]; /* DWORD 14 */ - u8 rsvd7[32]; /* DWORD 15 */ - struct BE_PCICFG_SEMAPHORE_CSR_AMAP semaphore[4]; - struct BE_PCICFG_SOFT_RESET_CSR_AMAP soft_reset; - u8 rsvd8[32]; /* DWORD 21 */ - struct BE_PCICFG_SCRATCHPAD_CSR_AMAP scratchpad; - u8 rsvd9[32]; /* DWORD 23 */ - u8 rsvd10[32]; /* DWORD 24 */ - u8 rsvd11[32]; /* DWORD 25 */ - u8 rsvd12[32]; /* DWORD 26 */ - u8 rsvd13[32]; /* DWORD 27 */ - u8 rsvd14[2][32]; /* DWORD 28 */ - u8 rsvd15[32]; /* DWORD 30 */ - u8 rsvd16[32]; /* DWORD 31 */ - u8 rsvd17[8][32]; /* DWORD 32 */ - struct BE_PCICFG_UE_STATUS_LOW_CSR_AMAP ue_status_low; - struct BE_PCICFG_UE_STATUS_HI_CSR_AMAP ue_status_hi; - struct BE_PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP ue_status_low_mask; - struct BE_PCICFG_UE_STATUS_HI_MASK_CSR_AMAP ue_status_hi_mask; - struct BE_PCICFG_ONLINE0_CSR_AMAP online0; - struct BE_PCICFG_ONLINE1_CSR_AMAP online1; - u8 rsvd18[32]; /* DWORD 46 */ - u8 rsvd19[32]; /* DWORD 47 */ - u8 rsvd20[32]; /* DWORD 48 */ - u8 rsvd21[32]; /* DWORD 49 */ - struct BE_PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP host_timer_int_ctrl; - u8 rsvd22[32]; /* DWORD 51 */ - struct BE_PCICFG_PCIE_CAP_CSR_AMAP pcie_cap; - struct BE_PCICFG_PCIE_DEVCAP_CSR_AMAP pcie_devcap; - struct BE_PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP pcie_control_status; - struct BE_PCICFG_PCIE_LINK_CAP_CSR_AMAP pcie_link_cap; - struct BE_PCICFG_PCIE_LINK_STATUS_CSR_AMAP pcie_link_status; - struct BE_PCICFG_MSI_CSR_AMAP msi; - struct BE_PCICFG_MSIX_TABLE_CSR_AMAP msix_table_offset; - struct BE_PCICFG_MSIX_PBA_CSR_AMAP msix_pba_offset; - u8 rsvd23[32]; /* DWORD 60 */ - u8 rsvd24[32]; /* DWORD 61 */ - u8 rsvd25[32]; /* DWORD 62 */ - u8 rsvd26[32]; /* DWORD 63 */ - u8 rsvd27[32]; /* DWORD 64 */ - u8 rsvd28[32]; /* DWORD 65 */ - u8 rsvd29[32]; /* DWORD 66 */ - u8 rsvd30[32]; /* DWORD 67 */ - u8 rsvd31[32]; /* DWORD 68 */ - u8 rsvd32[32]; /* DWORD 69 */ - u8 rsvd33[32]; /* DWORD 70 */ - u8 rsvd34[32]; /* DWORD 71 */ - u8 rsvd35[32]; /* DWORD 72 */ - u8 rsvd36[32]; /* DWORD 73 */ - u8 rsvd37[32]; /* DWORD 74 */ - u8 rsvd38[32]; /* DWORD 75 */ - u8 rsvd39[32]; /* DWORD 76 */ - u8 rsvd40[32]; /* DWORD 77 */ - u8 rsvd41[32]; /* DWORD 78 */ - u8 rsvd42[32]; /* DWORD 79 */ - u8 rsvd43[32]; /* DWORD 80 */ - u8 rsvd44[32]; /* DWORD 81 */ - u8 rsvd45[32]; /* DWORD 82 */ - u8 rsvd46[32]; /* DWORD 83 */ - u8 rsvd47[32]; /* DWORD 84 */ - u8 rsvd48[32]; /* DWORD 85 */ - u8 rsvd49[32]; /* DWORD 86 */ - u8 rsvd50[32]; /* DWORD 87 */ - u8 rsvd51[32]; /* DWORD 88 */ - u8 rsvd52[32]; /* DWORD 89 */ - u8 rsvd53[32]; /* DWORD 90 */ - u8 rsvd54[32]; /* DWORD 91 */ - u8 rsvd55[32]; /* DWORD 92 */ - u8 rsvd56[832]; /* DWORD 93 */ - u8 rsvd57[32]; /* DWORD 119 */ - u8 rsvd58[32]; /* DWORD 120 */ - u8 rsvd59[32]; /* DWORD 121 */ - u8 rsvd60[32]; /* DWORD 122 */ - u8 rsvd61[32]; /* DWORD 123 */ - u8 rsvd62[32]; /* DWORD 124 */ - u8 rsvd63[32]; /* DWORD 125 */ - u8 rsvd64[32]; /* DWORD 126 */ - u8 rsvd65[32]; /* DWORD 127 */ - u8 rsvd66[61440]; /* DWORD 128 */ - struct BE_PCICFG_ANON_22_MESSAGE_AMAP message[32]; - u8 rsvd67[28672]; /* DWORD 2176 */ - u8 rsvd68[32]; /* DWORD 3072 */ - u8 rsvd69[1023][32]; /* DWORD 3073 */ -} __packed; -struct PCICFG0_CSRMAP_AMAP { - u32 dw[4096]; -}; - -struct BE_PCICFG_ANON_24_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_ANON_24_RSVD_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_25_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_ANON_25_RSVD_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_26_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_ANON_26_RSVD_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_27_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_27_RSVD_AMAP { - u32 dw[2]; -}; - -struct BE_PCICFG_ANON_28_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[3][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_28_RSVD_AMAP { - u32 dw[4]; -}; - -struct BE_PCICFG_ANON_29_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[36][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_29_RSVD_AMAP { - u32 dw[37]; -}; - -struct BE_PCICFG_ANON_30_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[1930][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_30_RSVD_AMAP { - u32 dw[1931]; -}; - -struct BE_PCICFG_ANON_31_MESSAGE_AMAP { - struct BE_PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP vec_ctrl; - struct BE_PCICFG_MSIX_MSG_DATA_CSR_AMAP msg_data; - struct BE_PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP addr_hi; - struct BE_PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP addr_low; -} __packed; -struct PCICFG_ANON_31_MESSAGE_AMAP { - u32 dw[4]; -}; - -struct BE_PCICFG_ANON_32_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[895][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_32_RSVD_AMAP { - u32 dw[896]; -}; - -/* This PCI configuration space register map is for the Networking Function of - * BladeEngine (Function 1). - */ -struct BE_PCICFG1_CSRMAP_AMAP { - struct BE_PCICFG_ID_CSR_AMAP id; - u8 rsvd0[32]; /* DWORD 1 */ - u8 rsvd1[32]; /* DWORD 2 */ - u8 rsvd2[32]; /* DWORD 3 */ - struct BE_PCICFG_IOBAR_CSR_AMAP iobar; - struct BE_PCICFG_MEMBAR0_CSR_AMAP membar0; - struct BE_PCICFG_MEMBAR1_LO_CSR_AMAP membar1_lo; - struct BE_PCICFG_MEMBAR1_HI_CSR_AMAP membar1_hi; - struct BE_PCICFG_MEMBAR2_LO_CSR_AMAP membar2_lo; - struct BE_PCICFG_MEMBAR2_HI_CSR_AMAP membar2_hi; - u8 rsvd3[32]; /* DWORD 10 */ - struct BE_PCICFG_SUBSYSTEM_ID_F1_CSR_AMAP subsystem_id; - u8 rsvd4[32]; /* DWORD 12 */ - u8 rsvd5[32]; /* DWORD 13 */ - u8 rsvd6[32]; /* DWORD 14 */ - u8 rsvd7[32]; /* DWORD 15 */ - struct BE_PCICFG_SEMAPHORE_CSR_AMAP semaphore[4]; - struct BE_PCICFG_SOFT_RESET_CSR_AMAP soft_reset; - u8 rsvd8[32]; /* DWORD 21 */ - struct BE_PCICFG_SCRATCHPAD_CSR_AMAP scratchpad; - u8 rsvd9[32]; /* DWORD 23 */ - u8 rsvd10[32]; /* DWORD 24 */ - u8 rsvd11[32]; /* DWORD 25 */ - u8 rsvd12[32]; /* DWORD 26 */ - u8 rsvd13[32]; /* DWORD 27 */ - u8 rsvd14[2][32]; /* DWORD 28 */ - u8 rsvd15[32]; /* DWORD 30 */ - u8 rsvd16[32]; /* DWORD 31 */ - u8 rsvd17[8][32]; /* DWORD 32 */ - struct BE_PCICFG_UE_STATUS_LOW_CSR_AMAP ue_status_low; - struct BE_PCICFG_UE_STATUS_HI_CSR_AMAP ue_status_hi; - struct BE_PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP ue_status_low_mask; - struct BE_PCICFG_UE_STATUS_HI_MASK_CSR_AMAP ue_status_hi_mask; - struct BE_PCICFG_ONLINE0_CSR_AMAP online0; - struct BE_PCICFG_ONLINE1_CSR_AMAP online1; - u8 rsvd18[32]; /* DWORD 46 */ - u8 rsvd19[32]; /* DWORD 47 */ - u8 rsvd20[32]; /* DWORD 48 */ - u8 rsvd21[32]; /* DWORD 49 */ - struct BE_PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP host_timer_int_ctrl; - u8 rsvd22[32]; /* DWORD 51 */ - struct BE_PCICFG_PCIE_CAP_CSR_AMAP pcie_cap; - struct BE_PCICFG_PCIE_DEVCAP_CSR_AMAP pcie_devcap; - struct BE_PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP pcie_control_status; - struct BE_PCICFG_PCIE_LINK_CAP_CSR_AMAP pcie_link_cap; - struct BE_PCICFG_PCIE_LINK_STATUS_CSR_AMAP pcie_link_status; - struct BE_PCICFG_MSI_CSR_AMAP msi; - struct BE_PCICFG_MSIX_TABLE_CSR_AMAP msix_table_offset; - struct BE_PCICFG_MSIX_PBA_CSR_AMAP msix_pba_offset; - u8 rsvd23[64]; /* DWORD 60 */ - u8 rsvd24[32]; /* DWORD 62 */ - u8 rsvd25[32]; /* DWORD 63 */ - u8 rsvd26[32]; /* DWORD 64 */ - u8 rsvd27[32]; /* DWORD 65 */ - u8 rsvd28[32]; /* DWORD 66 */ - u8 rsvd29[32]; /* DWORD 67 */ - u8 rsvd30[32]; /* DWORD 68 */ - u8 rsvd31[32]; /* DWORD 69 */ - u8 rsvd32[32]; /* DWORD 70 */ - u8 rsvd33[32]; /* DWORD 71 */ - u8 rsvd34[32]; /* DWORD 72 */ - u8 rsvd35[32]; /* DWORD 73 */ - u8 rsvd36[32]; /* DWORD 74 */ - u8 rsvd37[128]; /* DWORD 75 */ - u8 rsvd38[32]; /* DWORD 79 */ - u8 rsvd39[1184]; /* DWORD 80 */ - u8 rsvd40[61792]; /* DWORD 117 */ - struct BE_PCICFG_ANON_31_MESSAGE_AMAP message[32]; - u8 rsvd41[28672]; /* DWORD 2176 */ - u8 rsvd42[32]; /* DWORD 3072 */ - u8 rsvd43[1023][32]; /* DWORD 3073 */ -} __packed; -struct PCICFG1_CSRMAP_AMAP { - u32 dw[4096]; -}; - -#endif /* __pcicfg_amap_h__ */ diff --git a/drivers/staging/benet/post_codes.h b/drivers/staging/benet/post_codes.h deleted file mode 100644 index 6d1621f5f5f..00000000000 --- a/drivers/staging/benet/post_codes.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __post_codes_amap_h__ -#define __post_codes_amap_h__ - -/* --- MGMT_HBA_POST_STAGE_ENUM --- */ -#define POST_STAGE_POWER_ON_RESET (0) /* State after a cold or warm boot. */ -#define POST_STAGE_AWAITING_HOST_RDY (1) /* ARM boot code awaiting a - go-ahed from the host. */ -#define POST_STAGE_HOST_RDY (2) /* Host has given go-ahed to ARM. */ -#define POST_STAGE_BE_RESET (3) /* Host wants to reset chip, this is a chip - workaround */ -#define POST_STAGE_SEEPROM_CS_START (256) /* SEEPROM checksum - test start. */ -#define POST_STAGE_SEEPROM_CS_DONE (257) /* SEEPROM checksum test - done. */ -#define POST_STAGE_DDR_CONFIG_START (512) /* DDR configuration start. */ -#define POST_STAGE_DDR_CONFIG_DONE (513) /* DDR configuration done. */ -#define POST_STAGE_DDR_CALIBRATE_START (768) /* DDR calibration start. */ -#define POST_STAGE_DDR_CALIBRATE_DONE (769) /* DDR calibration done. */ -#define POST_STAGE_DDR_TEST_START (1024) /* DDR memory test start. */ -#define POST_STAGE_DDR_TEST_DONE (1025) /* DDR memory test done. */ -#define POST_STAGE_REDBOOT_INIT_START (1536) /* Redboot starts execution. */ -#define POST_STAGE_REDBOOT_INIT_DONE (1537) /* Redboot done execution. */ -#define POST_STAGE_FW_IMAGE_LOAD_START (1792) /* Firmware image load to - DDR start. */ -#define POST_STAGE_FW_IMAGE_LOAD_DONE (1793) /* Firmware image load - to DDR done. */ -#define POST_STAGE_ARMFW_START (2048) /* ARMfw runtime code - starts execution. */ -#define POST_STAGE_DHCP_QUERY_START (2304) /* DHCP server query start. */ -#define POST_STAGE_DHCP_QUERY_DONE (2305) /* DHCP server query done. */ -#define POST_STAGE_BOOT_TARGET_DISCOVERY_START (2560) /* Boot Target - Discovery Start. */ -#define POST_STAGE_BOOT_TARGET_DISCOVERY_DONE (2561) /* Boot Target - Discovery Done. */ -#define POST_STAGE_RC_OPTION_SET (2816) /* Remote configuration - option is set in SEEPROM */ -#define POST_STAGE_SWITCH_LINK (2817) /* Wait for link up on switch */ -#define POST_STAGE_SEND_ICDS_MESSAGE (2818) /* Send the ICDS message - to switch */ -#define POST_STAGE_PERFROM_TFTP (2819) /* Download xml using TFTP */ -#define POST_STAGE_PARSE_XML (2820) /* Parse XML file */ -#define POST_STAGE_DOWNLOAD_IMAGE (2821) /* Download IMAGE from - TFTP server */ -#define POST_STAGE_FLASH_IMAGE (2822) /* Flash the IMAGE */ -#define POST_STAGE_RC_DONE (2823) /* Remote configuration - complete */ -#define POST_STAGE_REBOOT_SYSTEM (2824) /* Upgrade IMAGE done, - reboot required */ -#define POST_STAGE_MAC_ADDRESS (3072) /* MAC Address Check */ -#define POST_STAGE_ARMFW_READY (49152) /* ARMfw is done with POST - and ready. */ -#define POST_STAGE_ARMFW_UE (61440) /* ARMfw has asserted an - unrecoverable error. The - lower 3 hex digits of the - stage code identify the - unique error code. - */ - -/* This structure defines the format of the MPU semaphore - * register when used for POST. - */ -struct BE_MGMT_HBA_POST_STATUS_STRUCT_AMAP { - u8 stage[16]; /* DWORD 0 */ - u8 rsvd0[10]; /* DWORD 0 */ - u8 iscsi_driver_loaded; /* DWORD 0 */ - u8 option_rom_installed; /* DWORD 0 */ - u8 iscsi_ip_conflict; /* DWORD 0 */ - u8 iscsi_no_ip; /* DWORD 0 */ - u8 backup_fw; /* DWORD 0 */ - u8 error; /* DWORD 0 */ -} __packed; -struct MGMT_HBA_POST_STATUS_STRUCT_AMAP { - u32 dw[1]; -}; - -/* --- MGMT_HBA_POST_DUMMY_BITS_ENUM --- */ -#define POST_BIT_ISCSI_LOADED (26) -#define POST_BIT_OPTROM_INST (27) -#define POST_BIT_BAD_IP_ADDR (28) -#define POST_BIT_NO_IP_ADDR (29) -#define POST_BIT_BACKUP_FW (30) -#define POST_BIT_ERROR (31) - -/* --- MGMT_HBA_POST_DUMMY_VALUES_ENUM --- */ -#define POST_ISCSI_DRIVER_LOADED (67108864) -#define POST_OPTROM_INSTALLED (134217728) -#define POST_ISCSI_IP_ADDRESS_CONFLICT (268435456) -#define POST_ISCSI_NO_IP_ADDRESS (536870912) -#define POST_BACKUP_FW_LOADED (1073741824) -#define POST_FATAL_ERROR (2147483648) - -#endif /* __post_codes_amap_h__ */ diff --git a/drivers/staging/benet/regmap.h b/drivers/staging/benet/regmap.h deleted file mode 100644 index e816ba210e8..00000000000 --- a/drivers/staging/benet/regmap.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __regmap_amap_h__ -#define __regmap_amap_h__ -#include "pcicfg.h" -#include "ep.h" -#include "cev.h" -#include "mpu.h" -#include "doorbells.h" - -/* - * This is the control and status register map for BladeEngine, showing - * the relative size and offset of each sub-module. The CSR registers - * are identical for the network and storage PCI functions. The - * CSR map is shown below, followed by details of each block, - * in sub-sections. The sub-sections begin with a description - * of CSRs that are instantiated in multiple blocks. - */ -struct BE_BLADE_ENGINE_CSRMAP_AMAP { - struct BE_MPU_CSRMAP_AMAP mpu; - u8 rsvd0[8192]; /* DWORD 256 */ - u8 rsvd1[8192]; /* DWORD 512 */ - struct BE_CEV_CSRMAP_AMAP cev; - u8 rsvd2[8192]; /* DWORD 1024 */ - u8 rsvd3[8192]; /* DWORD 1280 */ - u8 rsvd4[8192]; /* DWORD 1536 */ - u8 rsvd5[8192]; /* DWORD 1792 */ - u8 rsvd6[8192]; /* DWORD 2048 */ - u8 rsvd7[8192]; /* DWORD 2304 */ - u8 rsvd8[8192]; /* DWORD 2560 */ - u8 rsvd9[8192]; /* DWORD 2816 */ - u8 rsvd10[8192]; /* DWORD 3072 */ - u8 rsvd11[8192]; /* DWORD 3328 */ - u8 rsvd12[8192]; /* DWORD 3584 */ - u8 rsvd13[8192]; /* DWORD 3840 */ - u8 rsvd14[8192]; /* DWORD 4096 */ - u8 rsvd15[8192]; /* DWORD 4352 */ - u8 rsvd16[8192]; /* DWORD 4608 */ - u8 rsvd17[8192]; /* DWORD 4864 */ - u8 rsvd18[8192]; /* DWORD 5120 */ - u8 rsvd19[8192]; /* DWORD 5376 */ - u8 rsvd20[8192]; /* DWORD 5632 */ - u8 rsvd21[8192]; /* DWORD 5888 */ - u8 rsvd22[8192]; /* DWORD 6144 */ - u8 rsvd23[17152][32]; /* DWORD 6400 */ -} __packed; -struct BLADE_ENGINE_CSRMAP_AMAP { - u32 dw[23552]; -}; - -#endif /* __regmap_amap_h__ */ -- GitLab From cd91566e4bdbcb8841385e4b2eacc8d0c29c9208 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Wed, 18 Mar 2009 17:28:37 +0100 Subject: [PATCH 3701/4982] netfilter: ctnetlink: remove remaining module refcounting Convert the remaining refcount users. As pointed out by Patrick McHardy, the protocols can be accessed safely using RCU. Signed-off-by: Florian Westphal Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_netlink.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 9fb7cf7504f..735ea9c1a96 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -599,7 +599,8 @@ ctnetlink_parse_tuple_ip(struct nlattr *attr, struct nf_conntrack_tuple *tuple) nla_parse_nested(tb, CTA_IP_MAX, attr, NULL); - l3proto = nf_ct_l3proto_find_get(tuple->src.l3num); + rcu_read_lock(); + l3proto = __nf_ct_l3proto_find(tuple->src.l3num); if (likely(l3proto->nlattr_to_tuple)) { ret = nla_validate_nested(attr, CTA_IP_MAX, @@ -608,7 +609,7 @@ ctnetlink_parse_tuple_ip(struct nlattr *attr, struct nf_conntrack_tuple *tuple) ret = l3proto->nlattr_to_tuple(tb, tuple); } - nf_ct_l3proto_put(l3proto); + rcu_read_unlock(); return ret; } @@ -633,7 +634,8 @@ ctnetlink_parse_tuple_proto(struct nlattr *attr, return -EINVAL; tuple->dst.protonum = nla_get_u8(tb[CTA_PROTO_NUM]); - l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum); + rcu_read_lock(); + l4proto = __nf_ct_l4proto_find(tuple->src.l3num, tuple->dst.protonum); if (likely(l4proto->nlattr_to_tuple)) { ret = nla_validate_nested(attr, CTA_PROTO_MAX, @@ -642,7 +644,7 @@ ctnetlink_parse_tuple_proto(struct nlattr *attr, ret = l4proto->nlattr_to_tuple(tb, tuple); } - nf_ct_l4proto_put(l4proto); + rcu_read_unlock(); return ret; } @@ -989,10 +991,11 @@ ctnetlink_change_protoinfo(struct nf_conn *ct, struct nlattr *cda[]) nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr, NULL); - l4proto = nf_ct_l4proto_find_get(nf_ct_l3num(ct), nf_ct_protonum(ct)); + rcu_read_lock(); + l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); if (l4proto->from_nlattr) err = l4proto->from_nlattr(tb, ct); - nf_ct_l4proto_put(l4proto); + rcu_read_unlock(); return err; } -- GitLab From 711d60a9e7f88e394ccca10f5fc83f95f0cea5b1 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Wed, 18 Mar 2009 17:30:50 +0100 Subject: [PATCH 3702/4982] netfilter: remove nf_ct_l4proto_find_get/nf_ct_l4proto_put users have been moved to __nf_ct_l4proto_find. Signed-off-by: Florian Westphal Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_conntrack_l4proto.h | 5 ----- net/netfilter/nf_conntrack_proto.c | 21 -------------------- 2 files changed, 26 deletions(-) diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h index 16ab604659e..b01070bf2f8 100644 --- a/include/net/netfilter/nf_conntrack_l4proto.h +++ b/include/net/netfilter/nf_conntrack_l4proto.h @@ -98,11 +98,6 @@ extern struct nf_conntrack_l4proto nf_conntrack_l4proto_generic; extern struct nf_conntrack_l4proto * __nf_ct_l4proto_find(u_int16_t l3proto, u_int8_t l4proto); -extern struct nf_conntrack_l4proto * -nf_ct_l4proto_find_get(u_int16_t l3proto, u_int8_t protocol); - -extern void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p); - /* Protocol registration. */ extern int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *proto); extern void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *proto); diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c index 592d73344d4..9a62b4efa0e 100644 --- a/net/netfilter/nf_conntrack_proto.c +++ b/net/netfilter/nf_conntrack_proto.c @@ -74,27 +74,6 @@ EXPORT_SYMBOL_GPL(__nf_ct_l4proto_find); /* this is guaranteed to always return a valid protocol helper, since * it falls back to generic_protocol */ -struct nf_conntrack_l4proto * -nf_ct_l4proto_find_get(u_int16_t l3proto, u_int8_t l4proto) -{ - struct nf_conntrack_l4proto *p; - - rcu_read_lock(); - p = __nf_ct_l4proto_find(l3proto, l4proto); - if (!try_module_get(p->me)) - p = &nf_conntrack_l4proto_generic; - rcu_read_unlock(); - - return p; -} -EXPORT_SYMBOL_GPL(nf_ct_l4proto_find_get); - -void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p) -{ - module_put(p->me); -} -EXPORT_SYMBOL_GPL(nf_ct_l4proto_put); - struct nf_conntrack_l3proto * nf_ct_l3proto_find_get(u_int16_t l3proto) { -- GitLab From 0f5b3e85a3716efebb0150ebb7c6d022e2bf17d7 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 18 Mar 2009 17:36:40 +0100 Subject: [PATCH 3703/4982] netfilter: ctnetlink: fix rcu context imbalance Introduced by 7ec47496 (netfilter: ctnetlink: cleanup master conntrack assignation): net/netfilter/nf_conntrack_netlink.c:1275:2: warning: context imbalance in 'ctnetlink_create_conntrack' - different lock contexts for basic block Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_netlink.c | 57 +++++++++++----------------- 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 735ea9c1a96..d1fe9d15ac5 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1146,7 +1146,7 @@ ctnetlink_create_conntrack(struct nlattr *cda[], return ERR_PTR(-ENOMEM); if (!cda[CTA_TIMEOUT]) - goto err; + goto err1; ct->timeout.expires = ntohl(nla_get_be32(cda[CTA_TIMEOUT])); ct->timeout.expires = jiffies + ct->timeout.expires * HZ; @@ -1157,10 +1157,8 @@ ctnetlink_create_conntrack(struct nlattr *cda[], char *helpname; err = ctnetlink_parse_help(cda[CTA_HELP], &helpname); - if (err < 0) { - rcu_read_unlock(); - goto err; - } + if (err < 0) + goto err2; helper = __nf_conntrack_helper_find_byname(helpname); if (helper == NULL) { @@ -1168,28 +1166,26 @@ ctnetlink_create_conntrack(struct nlattr *cda[], #ifdef CONFIG_MODULES if (request_module("nfct-helper-%s", helpname) < 0) { err = -EOPNOTSUPP; - goto err; + goto err1; } rcu_read_lock(); helper = __nf_conntrack_helper_find_byname(helpname); if (helper) { - rcu_read_unlock(); err = -EAGAIN; - goto err; + goto err2; } rcu_read_unlock(); #endif err = -EOPNOTSUPP; - goto err; + goto err1; } else { struct nf_conn_help *help; help = nf_ct_helper_ext_add(ct, GFP_ATOMIC); if (help == NULL) { - rcu_read_unlock(); err = -ENOMEM; - goto err; + goto err2; } /* not in hash table yet so not strictly necessary */ @@ -1198,44 +1194,34 @@ ctnetlink_create_conntrack(struct nlattr *cda[], } else { /* try an implicit helper assignation */ err = __nf_ct_try_assign_helper(ct, GFP_ATOMIC); - if (err < 0) { - rcu_read_unlock(); - goto err; - } + if (err < 0) + goto err2; } if (cda[CTA_STATUS]) { err = ctnetlink_change_status(ct, cda); - if (err < 0) { - rcu_read_unlock(); - goto err; - } + if (err < 0) + goto err2; } if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) { err = ctnetlink_change_nat(ct, cda); - if (err < 0) { - rcu_read_unlock(); - goto err; - } + if (err < 0) + goto err2; } #ifdef CONFIG_NF_NAT_NEEDED if (cda[CTA_NAT_SEQ_ADJ_ORIG] || cda[CTA_NAT_SEQ_ADJ_REPLY]) { err = ctnetlink_change_nat_seq_adj(ct, cda); - if (err < 0) { - rcu_read_unlock(); - goto err; - } + if (err < 0) + goto err2; } #endif if (cda[CTA_PROTOINFO]) { err = ctnetlink_change_protoinfo(ct, cda); - if (err < 0) { - rcu_read_unlock(); - goto err; - } + if (err < 0) + goto err2; } nf_ct_acct_ext_add(ct, GFP_ATOMIC); @@ -1253,12 +1239,12 @@ ctnetlink_create_conntrack(struct nlattr *cda[], err = ctnetlink_parse_tuple(cda, &master, CTA_TUPLE_MASTER, u3); if (err < 0) - goto err; + goto err2; master_h = __nf_conntrack_find(&init_net, &master); if (master_h == NULL) { err = -ENOENT; - goto err; + goto err2; } master_ct = nf_ct_tuplehash_to_ctrack(master_h); nf_conntrack_get(&master_ct->ct_general); @@ -1271,7 +1257,10 @@ ctnetlink_create_conntrack(struct nlattr *cda[], rcu_read_unlock(); return ct; -err: + +err2: + rcu_read_unlock(); +err1: nf_conntrack_free(ct); return ERR_PTR(err); } -- GitLab From e3598f6e4218d1aad3369c97217266b2375e6aca Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 18 Mar 2009 15:19:10 +0000 Subject: [PATCH 3704/4982] ASoC: Further optimise WM8400 bias configuration sequence The active discharge does not bring sufficient benefit to justify the lengthy times involved so don't do that. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8400.c | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index 744e0dc73be..462f8b0d9ac 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c @@ -1096,45 +1096,22 @@ static int wm8400_set_bias_level(struct snd_soc_codec *codec, wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, WM8400_CODEC_ENA | WM8400_SYSCLK_ENA); - /* Enable all output discharge bits */ - wm8400_write(codec, WM8400_ANTIPOP1, WM8400_DIS_LLINE | - WM8400_DIS_RLINE | WM8400_DIS_OUT3 | - WM8400_DIS_OUT4 | WM8400_DIS_LOUT | - WM8400_DIS_ROUT); - /* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */ wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST | WM8400_BUFDCOPEN | WM8400_POBCTRL); - msleep(500); - - /* Enable outputs */ - val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1); - val |= WM8400_SPK_ENA | WM8400_OUT3_ENA | - WM8400_OUT4_ENA | WM8400_LOUT_ENA | - WM8400_ROUT_ENA; - wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val); - - /* disable all output discharge bits */ - wm8400_write(codec, WM8400_ANTIPOP1, 0); + msleep(50); /* Enable VREF & VMID at 2x50k */ + val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1); val |= 0x2 | WM8400_VREF_ENA; wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val); - msleep(600); - /* Enable BUFIOEN */ wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST | WM8400_BUFDCOPEN | WM8400_POBCTRL | WM8400_BUFIOEN); - /* Disable outputs */ - val &= ~(WM8400_SPK_ENA | WM8400_OUT3_ENA | - WM8400_OUT4_ENA | WM8400_LOUT_ENA | - WM8400_ROUT_ENA); - wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val); - /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ wm8400_write(codec, WM8400_ANTIPOP2, WM8400_BUFIOEN); } -- GitLab From 24a51029fc3055f33684e650b5e3a59f77c9b05c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 18 Mar 2009 15:19:48 +0000 Subject: [PATCH 3705/4982] ASoC: Add separate AVDD for WM8400 There is an AVDD supply as well, normally one or more of the other upplies would be tied to it. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8400.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index 462f8b0d9ac..b7350c25b61 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c @@ -48,6 +48,9 @@ static struct regulator_bulk_data power[] = { { .supply = "DCVDD", }, + { + .supply = "AVDD", + }, { .supply = "FLLVDD", }, -- GitLab From 690103137267e9ed893febf7ff061af63e8235a9 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 18 Mar 2009 18:11:51 -0700 Subject: [PATCH 3706/4982] bnx2: Fix problem of using wrong IRQ handler. The MSI-X handler was chosen before the call to pci_enable_msix(). If MSI-X was not available, the wrong MSI-X handler would be used in INTA mode. This would cause a screaming interrupt problem because INTA would not be cleared by the MSI-X handler. Fixed by assigning MSI-X handler after pci_enable_msix() returns successfully. Also update version to 1.9.3. Thomas Chenault helped us find this problem. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 6500b7c4739..6b6530ffdf1 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -57,8 +57,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.9.2" -#define DRV_MODULE_RELDATE "Feb 11, 2009" +#define DRV_MODULE_VERSION "1.9.3" +#define DRV_MODULE_RELDATE "March 17, 2009" #define RUN_AT(x) (jiffies + (x)) @@ -5843,9 +5843,6 @@ bnx2_enable_msix(struct bnx2 *bp, int msix_vecs) for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) { msix_ent[i].entry = i; msix_ent[i].vector = 0; - - snprintf(bp->irq_tbl[i].name, len, "%s-%d", dev->name, i); - bp->irq_tbl[i].handler = bnx2_msi_1shot; } rc = pci_enable_msix(bp->pdev, msix_ent, BNX2_MAX_MSIX_VEC); @@ -5854,8 +5851,11 @@ bnx2_enable_msix(struct bnx2 *bp, int msix_vecs) bp->irq_nvecs = msix_vecs; bp->flags |= BNX2_FLAG_USING_MSIX | BNX2_FLAG_ONE_SHOT_MSI; - for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) + for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) { bp->irq_tbl[i].vector = msix_ent[i].vector; + snprintf(bp->irq_tbl[i].name, len, "%s-%d", dev->name, i); + bp->irq_tbl[i].handler = bnx2_msi_1shot; + } } static void -- GitLab From cedc1dba74f481a632c5d5aedad0068d6ad945d8 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 18 Mar 2009 18:17:48 -0700 Subject: [PATCH 3707/4982] a2065: skb_padto cleanups Remove unnecessary check (skb_padto does the same check) Remove unnecessary duplicate variable Remove unnecessary clearing of padded part of skb. Signed-off-by: Dave Jones Signed-off-by: David S. Miller --- drivers/net/a2065.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index 7a60bdd9a24..d0d0c2fee05 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -552,18 +552,13 @@ static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) struct lance_private *lp = netdev_priv(dev); volatile struct lance_regs *ll = lp->ll; volatile struct lance_init_block *ib = lp->init_block; - int entry, skblen, len; + int entry, skblen; int status = 0; unsigned long flags; - skblen = skb->len; - len = skblen; - - if (len < ETH_ZLEN) { - len = ETH_ZLEN; - if (skb_padto(skb, ETH_ZLEN)) - return 0; - } + if (skb_padto(skb, ETH_ZLEN)) + return 0; + skblen = max_t(unsigned, skb->len, ETH_ZLEN); local_irq_save(flags); @@ -586,15 +581,11 @@ static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) } #endif entry = lp->tx_new & lp->tx_ring_mod_mask; - ib->btx_ring [entry].length = (-len) | 0xf000; + ib->btx_ring [entry].length = (-skblen) | 0xf000; ib->btx_ring [entry].misc = 0; skb_copy_from_linear_data(skb, (void *)&ib->tx_buf [entry][0], skblen); - /* Clear the slack of the packet, do I need this? */ - if (len != skblen) - memset ((void *) &ib->tx_buf [entry][skblen], 0, len - skblen); - /* Now, give the packet to the lance */ ib->btx_ring [entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN); lp->tx_new = (lp->tx_new+1) & lp->tx_ring_mod_mask; -- GitLab From 9bdd8d40c8c59435664af6049dabe24b7779b203 Mon Sep 17 00:00:00 2001 From: Brian Haley Date: Wed, 18 Mar 2009 18:22:48 -0700 Subject: [PATCH 3708/4982] ipv6: Fix incorrect disable_ipv6 behavior Fix the behavior of allowing both sysctl and addrconf_dad_failure() to set the disable_ipv6 parameter without any bad side-effects. If DAD fails and accept_dad > 1, we will still set disable_ipv6=1, but then instead of allowing an RA to add an address then immediately fail DAD, we simply don't allow the address to be added in the first place. This also lets the user set this flag and disable all IPv6 addresses on the interface, or on the entire system. Signed-off-by: Brian Haley Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 4 +++- net/ipv6/addrconf.c | 21 ++++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 7185e4c41e5..ec5de02f543 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -1043,7 +1043,9 @@ max_addresses - INTEGER Default: 16 disable_ipv6 - BOOLEAN - Disable IPv6 operation. + Disable IPv6 operation. If accept_dad is set to 2, this value + will be dynamically set to TRUE if DAD fails for the link-local + address. Default: FALSE (enable IPv6 operation) accept_dad - INTEGER diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e83852ab4dc..717584bad02 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -590,6 +590,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, { struct inet6_ifaddr *ifa = NULL; struct rt6_info *rt; + struct net *net = dev_net(idev->dev); int hash; int err = 0; int addr_type = ipv6_addr_type(addr); @@ -606,6 +607,11 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, goto out2; } + if (idev->cnf.disable_ipv6 || net->ipv6.devconf_all->disable_ipv6) { + err = -EACCES; + goto out2; + } + write_lock(&addrconf_hash_lock); /* Ignore adding duplicate addresses on an interface */ @@ -1433,6 +1439,11 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp) void addrconf_dad_failure(struct inet6_ifaddr *ifp) { struct inet6_dev *idev = ifp->idev; + + if (net_ratelimit()) + printk(KERN_INFO "%s: IPv6 duplicate address detected!\n", + ifp->idev->dev->name); + if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6) { struct in6_addr addr; @@ -1443,11 +1454,12 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) ipv6_addr_equal(&ifp->addr, &addr)) { /* DAD failed for link-local based on MAC address */ idev->cnf.disable_ipv6 = 1; + + printk(KERN_INFO "%s: IPv6 being disabled!\n", + ifp->idev->dev->name); } } - if (net_ratelimit()) - printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name); addrconf_dad_stop(ifp); } @@ -2823,11 +2835,6 @@ static void addrconf_dad_timer(unsigned long data) read_unlock_bh(&idev->lock); goto out; } - if (idev->cnf.accept_dad > 1 && idev->cnf.disable_ipv6) { - read_unlock_bh(&idev->lock); - addrconf_dad_failure(ifp); - return; - } spin_lock_bh(&ifp->lock); if (ifp->probes == 0) { /* -- GitLab From 17d04500e2528217de5fe967599f98ee84348a9c Mon Sep 17 00:00:00 2001 From: Jay Vosburgh Date: Wed, 18 Mar 2009 18:38:25 -0700 Subject: [PATCH 3709/4982] bonding: Fix updating of speed/duplex changes This patch corrects an omission from the following commit: commit f0c76d61779b153dbfb955db3f144c62d02173c2 Author: Jay Vosburgh Date: Wed Jul 2 18:21:58 2008 -0700 bonding: refactor mii monitor The un-refactored code checked the link speed and duplex of every slave on every pass; the refactored code did not do so. The 802.3ad and balance-alb/tlb modes utilize the speed and duplex information, and require it to be kept up to date. This patch adds a notifier check to perform the appropriate updating when the slave device speed changes. Signed-off-by: Jay Vosburgh Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index e0578fe8c0d..3d76686dcec 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3537,11 +3537,26 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave } break; case NETDEV_CHANGE: - /* - * TODO: is this what we get if somebody - * sets up a hierarchical bond, then rmmod's - * one of the slave bonding devices? - */ + if (bond->params.mode == BOND_MODE_8023AD || bond_is_lb(bond)) { + struct slave *slave; + + slave = bond_get_slave_by_dev(bond, slave_dev); + if (slave) { + u16 old_speed = slave->speed; + u16 old_duplex = slave->duplex; + + bond_update_speed_duplex(slave); + + if (bond_is_lb(bond)) + break; + + if (old_speed != slave->speed) + bond_3ad_adapter_speed_changed(slave); + if (old_duplex != slave->duplex) + bond_3ad_adapter_duplex_changed(slave); + } + } + break; case NETDEV_DOWN: /* -- GitLab From 4783256ef92f5aecd6d54693b16386f2a0021c2a Mon Sep 17 00:00:00 2001 From: Pantelis Koukousoulas Date: Wed, 18 Mar 2009 18:40:02 -0700 Subject: [PATCH 3710/4982] virtio_net: Make virtio_net support carrier detection Impact: Make NetworkManager work with virtio_net For now the semantics are simple: There is always carrier. This allows a seamless experience with e.g., qemu/kvm where NetworkManager just configures and sets up everything automagically. If/when a generally agreed-upon way to control carrier on/off in the emulator/hypervisor level emerges, it will be trivial to extend the driver to support that too, but for now even this 2-liner makes user experience that much better. Signed-off-by: Pantelis Koukousoulas Signed-off-by: Rusty Russell Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index c68808336c8..e67d16c2e5f 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -612,6 +612,7 @@ static struct ethtool_ops virtnet_ethtool_ops = { .set_tx_csum = virtnet_set_tx_csum, .set_sg = ethtool_op_set_sg, .set_tso = ethtool_op_set_tso, + .get_link = ethtool_op_get_link, }; #define MIN_MTU 68 @@ -739,6 +740,8 @@ static int virtnet_probe(struct virtio_device *vdev) goto unregister; } + netif_carrier_on(dev); + pr_debug("virtnet: registered device %s\n", dev->name); return 0; -- GitLab From 69145635d4db0a0382885b14634aa5b721f3aa1a Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Wed, 18 Mar 2009 18:49:01 -0700 Subject: [PATCH 3711/4982] tulip: fix crash on iface up with shirq debug Tulip is currently doing request_irq before it has done its initialization. This is usually not a problem because it hasn't enable interrupts yet, but with DEBUG_SHIRQ on, we call the irq handler when registering the interrupt as a sanity check. This can result in a NULL ptr dereference, so call tulip_init_ring before request_irq, and add a free_ring function to do the freeing now shared with tulip_close. Tested with a shell loop running ifup, ifdown in a loop a few hundred times with DEBUG_SHIRQ on. Signed-off-by: Kyle McMartin Signed-off-by: David S. Miller --- drivers/net/tulip/tulip_core.c | 45 ++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index bee75fa87a9..2abb5d3becc 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -255,6 +255,7 @@ const char tulip_media_cap[32] = static void tulip_tx_timeout(struct net_device *dev); static void tulip_init_ring(struct net_device *dev); +static void tulip_free_ring(struct net_device *dev); static int tulip_start_xmit(struct sk_buff *skb, struct net_device *dev); static int tulip_open(struct net_device *dev); static int tulip_close(struct net_device *dev); @@ -502,16 +503,21 @@ tulip_open(struct net_device *dev) { int retval; - if ((retval = request_irq(dev->irq, &tulip_interrupt, IRQF_SHARED, dev->name, dev))) - return retval; - tulip_init_ring (dev); + retval = request_irq(dev->irq, &tulip_interrupt, IRQF_SHARED, dev->name, dev); + if (retval) + goto free_ring; + tulip_up (dev); netif_start_queue (dev); return 0; + +free_ring: + tulip_free_ring (dev); + return retval; } @@ -768,23 +774,11 @@ static void tulip_down (struct net_device *dev) tulip_set_power_state (tp, 0, 1); } - -static int tulip_close (struct net_device *dev) +static void tulip_free_ring (struct net_device *dev) { struct tulip_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->base_addr; int i; - netif_stop_queue (dev); - - tulip_down (dev); - - if (tulip_debug > 1) - printk (KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", - dev->name, ioread32 (ioaddr + CSR5)); - - free_irq (dev->irq, dev); - /* Free all the skbuffs in the Rx queue. */ for (i = 0; i < RX_RING_SIZE; i++) { struct sk_buff *skb = tp->rx_buffers[i].skb; @@ -803,6 +797,7 @@ static int tulip_close (struct net_device *dev) dev_kfree_skb (skb); } } + for (i = 0; i < TX_RING_SIZE; i++) { struct sk_buff *skb = tp->tx_buffers[i].skb; @@ -814,6 +809,24 @@ static int tulip_close (struct net_device *dev) tp->tx_buffers[i].skb = NULL; tp->tx_buffers[i].mapping = 0; } +} + +static int tulip_close (struct net_device *dev) +{ + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + + netif_stop_queue (dev); + + tulip_down (dev); + + if (tulip_debug > 1) + printk (KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", + dev->name, ioread32 (ioaddr + CSR5)); + + free_irq (dev->irq, dev); + + tulip_free_ring (dev); return 0; } -- GitLab From beedad923ad6237f03265fdf86eb8a1b50d14ae9 Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Wed, 18 Mar 2009 18:50:09 -0700 Subject: [PATCH 3712/4982] tcp: remove parameter from tcp_recv_urg(). This patch removes an unused parameter (addr_len) from tcp_recv_urg() method in net/ipv4/tcp.c. Signed-off-by: Rami Rosen Signed-off-by: David S. Miller --- net/ipv4/tcp.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 1c4d42ff72b..2451aeb5ac2 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1082,8 +1082,7 @@ out_err: */ static int tcp_recv_urg(struct sock *sk, long timeo, - struct msghdr *msg, int len, int flags, - int *addr_len) + struct msghdr *msg, int len, int flags) { struct tcp_sock *tp = tcp_sk(sk); @@ -1698,7 +1697,7 @@ out: return err; recv_urg: - err = tcp_recv_urg(sk, timeo, msg, len, flags, addr_len); + err = tcp_recv_urg(sk, timeo, msg, len, flags); goto out; } -- GitLab From e9c6a586f5335938b11be0a2554af58a2860e4ef Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 18 Mar 2009 18:51:06 -0700 Subject: [PATCH 3713/4982] net: Document /proc/sys/net/core/netdev_budget The NAPI poll parameter netdev_budget is not documented in kernel-docs. Since it may have a substantial effect on at least some network loads, it should be. Signed-off-by: Stanislaw Gruszka Signed-off-by: David S. Miller --- Documentation/filesystems/proc.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index a87be42f821..830bad7cce0 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -1478,6 +1478,13 @@ of problems on the network like duplicate address or bad checksums. Normally, this should be enabled, but if the problem persists the messages can be disabled. +netdev_budget +------------- + +Maximum number of packets taken from all interfaces in one polling cycle (NAPI +poll). In one polling cycle interfaces which are registered to polling are +probed in a round-robin manner. The limit of packets in one such probe can be +set per-device via sysfs class/net//weight . netdev_max_backlog ------------------ -- GitLab From 1b1d8f73a44fe1796a73a97ebcb08cad18b97f07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Wed, 18 Mar 2009 18:56:54 -0700 Subject: [PATCH 3714/4982] ipv6: fix display of local and remote sit endpoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes the regressions cause by commit 1326c3d5a4b792a2b15877feb7fb691f8945d203 (v2.6.28-rc6-461-g23a12b1) broke the display of local and remote addresses of an SIT tunnel in iproute2. nt->parms is used by ipip6_tunnel_init() and therefore need to be initialized first. Tracked as http://bugzilla.kernel.org/show_bug.cgi?id=12868 Reported-by: Jan Engelhardt Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- net/ipv6/sit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index d3467e563f0..5cee2bcbcec 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -188,9 +188,9 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct net *net, } nt = netdev_priv(dev); - ipip6_tunnel_init(dev); nt->parms = *parms; + ipip6_tunnel_init(dev); if (parms->i_flags & SIT_ISATAP) dev->priv_flags |= IFF_ISATAP; -- GitLab From 4b704d59d6fb152bcd0883b84af5936a29067f12 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 18 Mar 2009 19:11:29 -0700 Subject: [PATCH 3715/4982] tipc: fix non-const printf format arguments Fix warnings from current gcc about using non-const strings as printf args in TIPC. Compile tested only (not a TIPC user). Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/tipc/bcast.c | 4 ++-- net/tipc/bcast.h | 2 +- net/tipc/dbg.c | 2 +- net/tipc/node.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 3ddaff42d1b..a3bfd406491 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -119,7 +119,7 @@ static struct bclink *bclink = NULL; static struct link *bcl = NULL; static DEFINE_SPINLOCK(bc_lock); -char tipc_bclink_name[] = "multicast-link"; +const char tipc_bclink_name[] = "multicast-link"; static u32 buf_seqno(struct sk_buff *buf) @@ -800,7 +800,7 @@ int tipc_bclink_init(void) tipc_link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT); bcl->b_ptr = &bcbearer->bearer; bcl->state = WORKING_WORKING; - sprintf(bcl->name, tipc_bclink_name); + strlcpy(bcl->name, tipc_bclink_name, TIPC_MAX_LINK_NAME); if (BCLINK_LOG_BUF_SIZE) { char *pb = kmalloc(BCLINK_LOG_BUF_SIZE, GFP_ATOMIC); diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index 2f2d731bc1c..4c1771e95c9 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h @@ -70,7 +70,7 @@ struct port_list { struct tipc_node; -extern char tipc_bclink_name[]; +extern const char tipc_bclink_name[]; /** diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c index 29ecae85166..1885a7edb0c 100644 --- a/net/tipc/dbg.c +++ b/net/tipc/dbg.c @@ -258,7 +258,7 @@ void tipc_printf(struct print_buf *pb, const char *fmt, ...) } if (pb->echo) - printk(print_string); + printk("%s", print_string); spin_unlock_bh(&print_lock); } diff --git a/net/tipc/node.c b/net/tipc/node.c index 20d98c56e15..2c24e7d6d95 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -703,7 +703,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) link_info.dest = htonl(tipc_own_addr & 0xfffff00); link_info.up = htonl(1); - sprintf(link_info.str, tipc_bclink_name); + strlcpy(link_info.str, tipc_bclink_name, TIPC_MAX_LINK_NAME); tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info)); /* Add TLVs for any other links in scope */ -- GitLab From cb0dc77de0d23615a845e45844a2e22fc224d7fe Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 18 Mar 2009 19:12:42 -0700 Subject: [PATCH 3716/4982] net: fix sctp breakage broken by commit 5e739d1752aca4e8f3e794d431503bfca3162df4; AFAICS should be -stable fodder as well... Signed-off-by: Al Viro Aced-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/endpointola.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 4c8d9f45ce0..905fda582b9 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -111,7 +111,8 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, if (sctp_addip_enable) { auth_chunks->chunks[0] = SCTP_CID_ASCONF; auth_chunks->chunks[1] = SCTP_CID_ASCONF_ACK; - auth_chunks->param_hdr.length += htons(2); + auth_chunks->param_hdr.length = + htons(sizeof(sctp_paramhdr_t) + 2); } } -- GitLab From 27bf91d6a0d5a9c7224e8687754249bba67dd4cf Mon Sep 17 00:00:00 2001 From: Yevgeny Petrilin Date: Wed, 18 Mar 2009 19:45:11 -0700 Subject: [PATCH 3717/4982] mlx4_core: Add link type autosensing When a port's link is down (except to driver restart) and the port is configured for auto sensing, we try to sense port link type (Ethernet or InfiniBand) in order to determine how to initialize the port. If the port type needs to be changed, all mlx4 for the device interfaces are unregistered and then registered again with the new port types. Sensing is done with intervals of 3 seconds. Signed-off-by: Yevgeny Petrilin Signed-off-by: Roland Dreier --- drivers/net/mlx4/Makefile | 2 +- drivers/net/mlx4/catas.c | 16 +--- drivers/net/mlx4/eq.c | 16 ++-- drivers/net/mlx4/main.c | 104 +++++++++++++++++------- drivers/net/mlx4/mlx4.h | 27 ++++++- drivers/net/mlx4/sense.c | 156 ++++++++++++++++++++++++++++++++++++ include/linux/mlx4/cmd.h | 1 + include/linux/mlx4/device.h | 6 +- 8 files changed, 277 insertions(+), 51 deletions(-) create mode 100644 drivers/net/mlx4/sense.c diff --git a/drivers/net/mlx4/Makefile b/drivers/net/mlx4/Makefile index a7a97bf998f..21040a0d81f 100644 --- a/drivers/net/mlx4/Makefile +++ b/drivers/net/mlx4/Makefile @@ -1,7 +1,7 @@ obj-$(CONFIG_MLX4_CORE) += mlx4_core.o mlx4_core-y := alloc.o catas.o cmd.o cq.o eq.o fw.o icm.o intf.o main.o mcg.o \ - mr.o pd.o port.o profile.o qp.o reset.o srq.o + mr.o pd.o port.o profile.o qp.o reset.o sense.o srq.o obj-$(CONFIG_MLX4_EN) += mlx4_en.o diff --git a/drivers/net/mlx4/catas.c b/drivers/net/mlx4/catas.c index f094ee00c41..aa9674b7f19 100644 --- a/drivers/net/mlx4/catas.c +++ b/drivers/net/mlx4/catas.c @@ -42,7 +42,6 @@ enum { static DEFINE_SPINLOCK(catas_lock); static LIST_HEAD(catas_list); -static struct workqueue_struct *catas_wq; static struct work_struct catas_work; static int internal_err_reset = 1; @@ -77,7 +76,7 @@ static void poll_catas(unsigned long dev_ptr) list_add(&priv->catas_err.list, &catas_list); spin_unlock(&catas_lock); - queue_work(catas_wq, &catas_work); + queue_work(mlx4_wq, &catas_work); } } else mod_timer(&priv->catas_err.timer, @@ -146,18 +145,7 @@ void mlx4_stop_catas_poll(struct mlx4_dev *dev) spin_unlock_irq(&catas_lock); } -int __init mlx4_catas_init(void) +void __init mlx4_catas_init(void) { INIT_WORK(&catas_work, catas_reset); - - catas_wq = create_singlethread_workqueue("mlx4_err"); - if (!catas_wq) - return -ENOMEM; - - return 0; -} - -void mlx4_catas_cleanup(void) -{ - destroy_workqueue(catas_wq); } diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c index 2c19bff7cba..8830dcb92ec 100644 --- a/drivers/net/mlx4/eq.c +++ b/drivers/net/mlx4/eq.c @@ -163,6 +163,7 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) int cqn; int eqes_found = 0; int set_ci = 0; + int port; while ((eqe = next_eqe_sw(eq))) { /* @@ -203,11 +204,16 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) break; case MLX4_EVENT_TYPE_PORT_CHANGE: - mlx4_dispatch_event(dev, - eqe->subtype == MLX4_PORT_CHANGE_SUBTYPE_ACTIVE ? - MLX4_DEV_EVENT_PORT_UP : - MLX4_DEV_EVENT_PORT_DOWN, - be32_to_cpu(eqe->event.port_change.port) >> 28); + port = be32_to_cpu(eqe->event.port_change.port) >> 28; + if (eqe->subtype == MLX4_PORT_CHANGE_SUBTYPE_DOWN) { + mlx4_dispatch_event(dev, MLX4_DEV_EVENT_PORT_DOWN, + port); + mlx4_priv(dev)->sense.do_sense_port[port] = 1; + } else { + mlx4_dispatch_event(dev, MLX4_DEV_EVENT_PORT_UP, + port); + mlx4_priv(dev)->sense.do_sense_port[port] = 0; + } break; case MLX4_EVENT_TYPE_CQ_ERROR: diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c index 8480f034684..a66f5b2fd28 100644 --- a/drivers/net/mlx4/main.c +++ b/drivers/net/mlx4/main.c @@ -51,6 +51,8 @@ MODULE_DESCRIPTION("Mellanox ConnectX HCA low-level driver"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_VERSION(DRV_VERSION); +struct workqueue_struct *mlx4_wq; + #ifdef CONFIG_MLX4_DEBUG int mlx4_debug_level = 0; @@ -98,24 +100,23 @@ module_param_named(use_prio, use_prio, bool, 0444); MODULE_PARM_DESC(use_prio, "Enable steering by VLAN priority on ETH ports " "(0/1, default 0)"); -static int mlx4_check_port_params(struct mlx4_dev *dev, - enum mlx4_port_type *port_type) +int mlx4_check_port_params(struct mlx4_dev *dev, + enum mlx4_port_type *port_type) { int i; for (i = 0; i < dev->caps.num_ports - 1; i++) { - if (port_type[i] != port_type[i+1] && - !(dev->caps.flags & MLX4_DEV_CAP_FLAG_DPDP)) { - mlx4_err(dev, "Only same port types supported " - "on this HCA, aborting.\n"); - return -EINVAL; + if (port_type[i] != port_type[i + 1]) { + if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_DPDP)) { + mlx4_err(dev, "Only same port types supported " + "on this HCA, aborting.\n"); + return -EINVAL; + } + if (port_type[i] == MLX4_PORT_TYPE_ETH && + port_type[i + 1] == MLX4_PORT_TYPE_IB) + return -EINVAL; } } - if ((port_type[0] == MLX4_PORT_TYPE_ETH) && - (port_type[1] == MLX4_PORT_TYPE_IB)) { - mlx4_err(dev, "eth-ib configuration is not supported.\n"); - return -EINVAL; - } for (i = 0; i < dev->caps.num_ports; i++) { if (!(port_type[i] & dev->caps.supported_type[i+1])) { @@ -225,6 +226,9 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev->caps.port_type[i] = MLX4_PORT_TYPE_IB; else dev->caps.port_type[i] = MLX4_PORT_TYPE_ETH; + dev->caps.possible_type[i] = dev->caps.port_type[i]; + mlx4_priv(dev)->sense.sense_allowed[i] = + dev->caps.supported_type[i] == MLX4_PORT_TYPE_AUTO; if (dev->caps.log_num_macs > dev_cap->log_max_macs[i]) { dev->caps.log_num_macs = dev_cap->log_max_macs[i]; @@ -263,14 +267,16 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) * Change the port configuration of the device. * Every user of this function must hold the port mutex. */ -static int mlx4_change_port_types(struct mlx4_dev *dev, - enum mlx4_port_type *port_types) +int mlx4_change_port_types(struct mlx4_dev *dev, + enum mlx4_port_type *port_types) { int err = 0; int change = 0; int port; for (port = 0; port < dev->caps.num_ports; port++) { + /* Change the port type only if the new type is different + * from the current, and not set to Auto */ if (port_types[port] != dev->caps.port_type[port + 1]) { change = 1; dev->caps.port_type[port + 1] = port_types[port]; @@ -302,10 +308,17 @@ static ssize_t show_port_type(struct device *dev, struct mlx4_port_info *info = container_of(attr, struct mlx4_port_info, port_attr); struct mlx4_dev *mdev = info->dev; + char type[8]; + + sprintf(type, "%s", + (mdev->caps.port_type[info->port] == MLX4_PORT_TYPE_IB) ? + "ib" : "eth"); + if (mdev->caps.possible_type[info->port] == MLX4_PORT_TYPE_AUTO) + sprintf(buf, "auto (%s)\n", type); + else + sprintf(buf, "%s\n", type); - return sprintf(buf, "%s\n", - mdev->caps.port_type[info->port] == MLX4_PORT_TYPE_IB ? - "ib" : "eth"); + return strlen(buf); } static ssize_t set_port_type(struct device *dev, @@ -317,6 +330,7 @@ static ssize_t set_port_type(struct device *dev, struct mlx4_dev *mdev = info->dev; struct mlx4_priv *priv = mlx4_priv(mdev); enum mlx4_port_type types[MLX4_MAX_PORTS]; + enum mlx4_port_type new_types[MLX4_MAX_PORTS]; int i; int err = 0; @@ -324,26 +338,56 @@ static ssize_t set_port_type(struct device *dev, info->tmp_type = MLX4_PORT_TYPE_IB; else if (!strcmp(buf, "eth\n")) info->tmp_type = MLX4_PORT_TYPE_ETH; + else if (!strcmp(buf, "auto\n")) + info->tmp_type = MLX4_PORT_TYPE_AUTO; else { mlx4_err(mdev, "%s is not supported port type\n", buf); return -EINVAL; } + mlx4_stop_sense(mdev); mutex_lock(&priv->port_mutex); - for (i = 0; i < mdev->caps.num_ports; i++) + /* Possible type is always the one that was delivered */ + mdev->caps.possible_type[info->port] = info->tmp_type; + + for (i = 0; i < mdev->caps.num_ports; i++) { types[i] = priv->port[i+1].tmp_type ? priv->port[i+1].tmp_type : - mdev->caps.port_type[i+1]; + mdev->caps.possible_type[i+1]; + if (types[i] == MLX4_PORT_TYPE_AUTO) + types[i] = mdev->caps.port_type[i+1]; + } - err = mlx4_check_port_params(mdev, types); + if (!(mdev->caps.flags & MLX4_DEV_CAP_FLAG_DPDP)) { + for (i = 1; i <= mdev->caps.num_ports; i++) { + if (mdev->caps.possible_type[i] == MLX4_PORT_TYPE_AUTO) { + mdev->caps.possible_type[i] = mdev->caps.port_type[i]; + err = -EINVAL; + } + } + } + if (err) { + mlx4_err(mdev, "Auto sensing is not supported on this HCA. " + "Set only 'eth' or 'ib' for both ports " + "(should be the same)\n"); + goto out; + } + + mlx4_do_sense_ports(mdev, new_types, types); + + err = mlx4_check_port_params(mdev, new_types); if (err) goto out; - for (i = 1; i <= mdev->caps.num_ports; i++) - priv->port[i].tmp_type = 0; + /* We are about to apply the changes after the configuration + * was verified, no need to remember the temporary types + * any more */ + for (i = 0; i < mdev->caps.num_ports; i++) + priv->port[i + 1].tmp_type = 0; - err = mlx4_change_port_types(mdev, types); + err = mlx4_change_port_types(mdev, new_types); out: + mlx4_start_sense(mdev); mutex_unlock(&priv->port_mutex); return err ? err : count; } @@ -1117,6 +1161,9 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) if (err) goto err_port; + mlx4_sense_init(dev); + mlx4_start_sense(dev); + pci_set_drvdata(pdev, dev); return 0; @@ -1182,6 +1229,7 @@ static void mlx4_remove_one(struct pci_dev *pdev) int p; if (dev) { + mlx4_stop_sense(dev); mlx4_unregister_device(dev); for (p = 1; p <= dev->caps.num_ports; p++) { @@ -1266,9 +1314,11 @@ static int __init mlx4_init(void) if (mlx4_verify_params()) return -EINVAL; - ret = mlx4_catas_init(); - if (ret) - return ret; + mlx4_catas_init(); + + mlx4_wq = create_singlethread_workqueue("mlx4"); + if (!mlx4_wq) + return -ENOMEM; ret = pci_register_driver(&mlx4_driver); return ret < 0 ? ret : 0; @@ -1277,7 +1327,7 @@ static int __init mlx4_init(void) static void __exit mlx4_cleanup(void) { pci_unregister_driver(&mlx4_driver); - mlx4_catas_cleanup(); + destroy_workqueue(mlx4_wq); } module_init(mlx4_init); diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h index e0213bad61c..5bd79c2b184 100644 --- a/drivers/net/mlx4/mlx4.h +++ b/drivers/net/mlx4/mlx4.h @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -276,6 +277,13 @@ struct mlx4_port_info { struct mlx4_vlan_table vlan_table; }; +struct mlx4_sense { + struct mlx4_dev *dev; + u8 do_sense_port[MLX4_MAX_PORTS + 1]; + u8 sense_allowed[MLX4_MAX_PORTS + 1]; + struct delayed_work sense_poll; +}; + struct mlx4_priv { struct mlx4_dev dev; @@ -305,6 +313,7 @@ struct mlx4_priv { struct mlx4_uar driver_uar; void __iomem *kar; struct mlx4_port_info port[MLX4_MAX_PORTS + 1]; + struct mlx4_sense sense; struct mutex port_mutex; }; @@ -313,6 +322,10 @@ static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev) return container_of(dev, struct mlx4_priv, dev); } +#define MLX4_SENSE_RANGE (HZ * 3) + +extern struct workqueue_struct *mlx4_wq; + u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap); void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj); u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align); @@ -346,8 +359,7 @@ void mlx4_cleanup_mcg_table(struct mlx4_dev *dev); void mlx4_start_catas_poll(struct mlx4_dev *dev); void mlx4_stop_catas_poll(struct mlx4_dev *dev); -int mlx4_catas_init(void); -void mlx4_catas_cleanup(void); +void mlx4_catas_init(void); int mlx4_restart_one(struct pci_dev *pdev); int mlx4_register_device(struct mlx4_dev *dev); void mlx4_unregister_device(struct mlx4_dev *dev); @@ -379,6 +391,17 @@ void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type); void mlx4_handle_catas_err(struct mlx4_dev *dev); +void mlx4_do_sense_ports(struct mlx4_dev *dev, + enum mlx4_port_type *stype, + enum mlx4_port_type *defaults); +void mlx4_start_sense(struct mlx4_dev *dev); +void mlx4_stop_sense(struct mlx4_dev *dev); +void mlx4_sense_init(struct mlx4_dev *dev); +int mlx4_check_port_params(struct mlx4_dev *dev, + enum mlx4_port_type *port_type); +int mlx4_change_port_types(struct mlx4_dev *dev, + enum mlx4_port_type *port_types); + void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table); void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table); diff --git a/drivers/net/mlx4/sense.c b/drivers/net/mlx4/sense.c new file mode 100644 index 00000000000..6d5089ecb5a --- /dev/null +++ b/drivers/net/mlx4/sense.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2007 Mellanox Technologies. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#include +#include + +#include + +#include "mlx4.h" + +static int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port, + enum mlx4_port_type *type) +{ + u64 out_param; + int err = 0; + + err = mlx4_cmd_imm(dev, 0, &out_param, port, 0, + MLX4_CMD_SENSE_PORT, MLX4_CMD_TIME_CLASS_B); + if (err) { + mlx4_err(dev, "Sense command failed for port: %d\n", port); + return err; + } + + if (out_param > 2) { + mlx4_err(dev, "Sense returned illegal value: 0x%llx\n", out_param); + return EINVAL; + } + + *type = out_param; + return 0; +} + +void mlx4_do_sense_ports(struct mlx4_dev *dev, + enum mlx4_port_type *stype, + enum mlx4_port_type *defaults) +{ + struct mlx4_sense *sense = &mlx4_priv(dev)->sense; + int err; + int i; + + for (i = 1; i <= dev->caps.num_ports; i++) { + stype[i - 1] = 0; + if (sense->do_sense_port[i] && sense->sense_allowed[i] && + dev->caps.possible_type[i] == MLX4_PORT_TYPE_AUTO) { + err = mlx4_SENSE_PORT(dev, i, &stype[i - 1]); + if (err) + stype[i - 1] = defaults[i - 1]; + } else + stype[i - 1] = defaults[i - 1]; + } + + /* + * Adjust port configuration: + * If port 1 sensed nothing and port 2 is IB, set both as IB + * If port 2 sensed nothing and port 1 is Eth, set both as Eth + */ + if (stype[0] == MLX4_PORT_TYPE_ETH) { + for (i = 1; i < dev->caps.num_ports; i++) + stype[i] = stype[i] ? stype[i] : MLX4_PORT_TYPE_ETH; + } + if (stype[dev->caps.num_ports - 1] == MLX4_PORT_TYPE_IB) { + for (i = 0; i < dev->caps.num_ports - 1; i++) + stype[i] = stype[i] ? stype[i] : MLX4_PORT_TYPE_IB; + } + + /* + * If sensed nothing, remain in current configuration. + */ + for (i = 0; i < dev->caps.num_ports; i++) + stype[i] = stype[i] ? stype[i] : defaults[i]; + +} + +static void mlx4_sense_port(struct work_struct *work) +{ + struct delayed_work *delay = container_of(work, struct delayed_work, work); + struct mlx4_sense *sense = container_of(delay, struct mlx4_sense, + sense_poll); + struct mlx4_dev *dev = sense->dev; + struct mlx4_priv *priv = mlx4_priv(dev); + enum mlx4_port_type stype[MLX4_MAX_PORTS]; + + mutex_lock(&priv->port_mutex); + mlx4_do_sense_ports(dev, stype, &dev->caps.port_type[1]); + + if (mlx4_check_port_params(dev, stype)) + goto sense_again; + + if (mlx4_change_port_types(dev, stype)) + mlx4_err(dev, "Failed to change port_types\n"); + +sense_again: + mutex_unlock(&priv->port_mutex); + queue_delayed_work(mlx4_wq , &sense->sense_poll, + round_jiffies_relative(MLX4_SENSE_RANGE)); +} + +void mlx4_start_sense(struct mlx4_dev *dev) +{ + struct mlx4_priv *priv = mlx4_priv(dev); + struct mlx4_sense *sense = &priv->sense; + + if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_DPDP)) + return; + + queue_delayed_work(mlx4_wq , &sense->sense_poll, + round_jiffies_relative(MLX4_SENSE_RANGE)); +} + +void mlx4_stop_sense(struct mlx4_dev *dev) +{ + cancel_delayed_work_sync(&mlx4_priv(dev)->sense.sense_poll); +} + +void mlx4_sense_init(struct mlx4_dev *dev) +{ + struct mlx4_priv *priv = mlx4_priv(dev); + struct mlx4_sense *sense = &priv->sense; + int port; + + sense->dev = dev; + for (port = 1; port <= dev->caps.num_ports; port++) + sense->do_sense_port[port] = 1; + + INIT_DELAYED_WORK_DEFERRABLE(&sense->sense_poll, mlx4_sense_port); +} diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h index cf9c679ab38..0f82293a82e 100644 --- a/include/linux/mlx4/cmd.h +++ b/include/linux/mlx4/cmd.h @@ -55,6 +55,7 @@ enum { MLX4_CMD_CLOSE_PORT = 0xa, MLX4_CMD_QUERY_HCA = 0xb, MLX4_CMD_QUERY_PORT = 0x43, + MLX4_CMD_SENSE_PORT = 0x4d, MLX4_CMD_SET_PORT = 0xc, MLX4_CMD_ACCESS_DDR = 0x2e, MLX4_CMD_MAP_ICM = 0xffa, diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index 8f659cc2996..3aff8a6a389 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -155,8 +155,9 @@ enum mlx4_qp_region { }; enum mlx4_port_type { - MLX4_PORT_TYPE_IB = 1 << 0, - MLX4_PORT_TYPE_ETH = 1 << 1, + MLX4_PORT_TYPE_IB = 1, + MLX4_PORT_TYPE_ETH = 2, + MLX4_PORT_TYPE_AUTO = 3 }; enum mlx4_special_vlan_idx { @@ -237,6 +238,7 @@ struct mlx4_caps { enum mlx4_port_type port_type[MLX4_MAX_PORTS + 1]; u8 supported_type[MLX4_MAX_PORTS + 1]; u32 port_mask; + enum mlx4_port_type possible_type[MLX4_MAX_PORTS + 1]; }; struct mlx4_buf_list { -- GitLab From a6a47771b113be8e694aedd80f66ea94d05bd8df Mon Sep 17 00:00:00 2001 From: Yevgeny Petrilin Date: Wed, 18 Mar 2009 19:49:54 -0700 Subject: [PATCH 3718/4982] IB/mlx4: Unregister IB device prior to CLOSE PORT command According to the ConnectX programmer's reference manual, all operations should be stopped, all QPs should be torn down and all WQEs flushed before the CLOSE_PORT command is invoked. In some cases reversing the order of operations (as implemented now) could cause a loss of completions. Signed-off-by: Yevgeny Petrilin Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mlx4/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 61588bd273b..2ccb9d31771 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -699,11 +699,12 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr) struct mlx4_ib_dev *ibdev = ibdev_ptr; int p; + mlx4_ib_mad_cleanup(ibdev); + ib_unregister_device(&ibdev->ib_dev); + for (p = 1; p <= ibdev->num_ports; ++p) mlx4_CLOSE_PORT(dev, p); - mlx4_ib_mad_cleanup(ibdev); - ib_unregister_device(&ibdev->ib_dev); iounmap(ibdev->uar_map); mlx4_uar_free(dev, &ibdev->priv_uar); mlx4_pd_free(dev, ibdev->priv_pdn); -- GitLab From e4a389a9b5c892446b5de2038bdc0cca8703c615 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Wed, 18 Mar 2009 23:12:13 -0700 Subject: [PATCH 3719/4982] net: kfree(napi->skb) => kfree_skb struct sk_buff pointers should be freed with kfree_skb. Signed-off-by: Roel Kluin Signed-off-by: David S. Miller --- net/core/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index 2565f6d1d66..e3fe5c70560 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2672,7 +2672,7 @@ void netif_napi_del(struct napi_struct *napi) struct sk_buff *skb, *next; list_del_init(&napi->dev_list); - kfree(napi->skb); + kfree_skb(napi->skb); for (skb = napi->gro_list; skb; skb = next) { next = skb->next; -- GitLab From 2bad35b7c9588eb5e65c03bcae54e7eb6b1a6504 Mon Sep 17 00:00:00 2001 From: "Jorge Boncompte [DTI2]" Date: Wed, 18 Mar 2009 23:26:11 -0700 Subject: [PATCH 3720/4982] netns: oops in ip[6]_frag_reasm incrementing stats dev can be NULL in ip[6]_frag_reasm for skb's coming from RAW sockets. Quagga's OSPFD sends fragmented packets on a RAW socket, when netfilter conntrack reassembles them on the OUTPUT path you hit this code path. You can test it with something like "hping2 -0 -d 2000 -f AA.BB.CC.DD" With help from Jarek Poplawski. Signed-off-by: Jorge Boncompte [DTI2] Signed-off-by: David S. Miller --- net/ipv4/ip_fragment.c | 3 ++- net/ipv6/reassembly.c | 7 +++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 6659ac000ee..7985346653b 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -463,6 +463,7 @@ err: static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, struct net_device *dev) { + struct net *net = container_of(qp->q.net, struct net, ipv4.frags); struct iphdr *iph; struct sk_buff *fp, *head = qp->q.fragments; int len; @@ -548,7 +549,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, iph = ip_hdr(head); iph->frag_off = 0; iph->tot_len = htons(len); - IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_REASMOKS); + IP_INC_STATS_BH(net, IPSTATS_MIB_REASMOKS); qp->q.fragments = NULL; return 0; diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 3c575118fca..e9ac7a12f59 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -452,6 +452,7 @@ err: static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, struct net_device *dev) { + struct net *net = container_of(fq->q.net, struct net, ipv6.frags); struct sk_buff *fp, *head = fq->q.fragments; int payload_len; unsigned int nhoff; @@ -551,8 +552,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, head->csum); rcu_read_lock(); - IP6_INC_STATS_BH(dev_net(dev), - __in6_dev_get(dev), IPSTATS_MIB_REASMOKS); + IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMOKS); rcu_read_unlock(); fq->q.fragments = NULL; return 1; @@ -566,8 +566,7 @@ out_oom: printk(KERN_DEBUG "ip6_frag_reasm: no memory for reassembly\n"); out_fail: rcu_read_lock(); - IP6_INC_STATS_BH(dev_net(dev), - __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); + IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); rcu_read_unlock(); return -1; } -- GitLab From 4826857f1bf07f9c0f1495e9b05d125552c88a85 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 18 Mar 2009 23:28:22 -0700 Subject: [PATCH 3721/4982] gianfar: pass the proper dev to DMA ops We need to be passing the of_platform device struct into the DMA ops as its the one that has the archdata setup to know which low-level DMA ops we should be using (not the net_device one). This isn't an issue until we expect the archdata to be setup correctly. Signed-off-by: Kumar Gala Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 34 ++++++++++++++++++---------------- drivers/net/gianfar.h | 3 ++- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index bed30ef4379..8659833f28e 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -365,8 +365,10 @@ static int gfar_probe(struct of_device *ofdev, return -ENOMEM; priv = netdev_priv(dev); - priv->dev = dev; + priv->ndev = dev; + priv->ofdev = ofdev; priv->node = ofdev->node; + SET_NETDEV_DEV(dev, &ofdev->dev); err = gfar_of_init(dev); @@ -538,7 +540,7 @@ static int gfar_remove(struct of_device *ofdev) dev_set_drvdata(&ofdev->dev, NULL); iounmap(priv->regs); - free_netdev(priv->dev); + free_netdev(priv->ndev); return 0; } @@ -870,7 +872,7 @@ void stop_gfar(struct net_device *dev) free_skb_resources(priv); - dma_free_coherent(&dev->dev, + dma_free_coherent(&priv->ofdev->dev, sizeof(struct txbd8)*priv->tx_ring_size + sizeof(struct rxbd8)*priv->rx_ring_size, priv->tx_bd_base, @@ -892,12 +894,12 @@ static void free_skb_resources(struct gfar_private *priv) if (!priv->tx_skbuff[i]) continue; - dma_unmap_single(&priv->dev->dev, txbdp->bufPtr, + dma_unmap_single(&priv->ofdev->dev, txbdp->bufPtr, txbdp->length, DMA_TO_DEVICE); txbdp->lstatus = 0; for (j = 0; j < skb_shinfo(priv->tx_skbuff[i])->nr_frags; j++) { txbdp++; - dma_unmap_page(&priv->dev->dev, txbdp->bufPtr, + dma_unmap_page(&priv->ofdev->dev, txbdp->bufPtr, txbdp->length, DMA_TO_DEVICE); } txbdp++; @@ -914,7 +916,7 @@ static void free_skb_resources(struct gfar_private *priv) if(priv->rx_skbuff != NULL) { for (i = 0; i < priv->rx_ring_size; i++) { if (priv->rx_skbuff[i]) { - dma_unmap_single(&priv->dev->dev, rxbdp->bufPtr, + dma_unmap_single(&priv->ofdev->dev, rxbdp->bufPtr, priv->rx_buffer_size, DMA_FROM_DEVICE); @@ -980,7 +982,7 @@ int startup_gfar(struct net_device *dev) gfar_write(®s->imask, IMASK_INIT_CLEAR); /* Allocate memory for the buffer descriptors */ - vaddr = (unsigned long) dma_alloc_coherent(&dev->dev, + vaddr = (unsigned long) dma_alloc_coherent(&priv->ofdev->dev, sizeof (struct txbd8) * priv->tx_ring_size + sizeof (struct rxbd8) * priv->rx_ring_size, &addr, GFP_KERNEL); @@ -1192,7 +1194,7 @@ err_rxalloc_fail: rx_skb_fail: free_skb_resources(priv); tx_skb_fail: - dma_free_coherent(&dev->dev, + dma_free_coherent(&priv->ofdev->dev, sizeof(struct txbd8)*priv->tx_ring_size + sizeof(struct rxbd8)*priv->rx_ring_size, priv->tx_bd_base, @@ -1345,7 +1347,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) if (i == nr_frags - 1) lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT); - bufaddr = dma_map_page(&dev->dev, + bufaddr = dma_map_page(&priv->ofdev->dev, skb_shinfo(skb)->frags[i].page, skb_shinfo(skb)->frags[i].page_offset, length, @@ -1377,7 +1379,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) /* setup the TxBD length and buffer pointer for the first BD */ priv->tx_skbuff[priv->skb_curtx] = skb; - txbdp_start->bufPtr = dma_map_single(&dev->dev, skb->data, + txbdp_start->bufPtr = dma_map_single(&priv->ofdev->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE); lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | skb_headlen(skb); @@ -1563,7 +1565,7 @@ static void gfar_reset_task(struct work_struct *work) { struct gfar_private *priv = container_of(work, struct gfar_private, reset_task); - struct net_device *dev = priv->dev; + struct net_device *dev = priv->ndev; if (dev->flags & IFF_UP) { stop_gfar(dev); @@ -1610,7 +1612,7 @@ static int gfar_clean_tx_ring(struct net_device *dev) (lstatus & BD_LENGTH_MASK)) break; - dma_unmap_single(&dev->dev, + dma_unmap_single(&priv->ofdev->dev, bdp->bufPtr, bdp->length, DMA_TO_DEVICE); @@ -1619,7 +1621,7 @@ static int gfar_clean_tx_ring(struct net_device *dev) bdp = next_txbd(bdp, base, tx_ring_size); for (i = 0; i < frags; i++) { - dma_unmap_page(&dev->dev, + dma_unmap_page(&priv->ofdev->dev, bdp->bufPtr, bdp->length, DMA_TO_DEVICE); @@ -1696,7 +1698,7 @@ static void gfar_new_rxbdp(struct net_device *dev, struct rxbd8 *bdp, struct gfar_private *priv = netdev_priv(dev); u32 lstatus; - bdp->bufPtr = dma_map_single(&dev->dev, skb->data, + bdp->bufPtr = dma_map_single(&priv->ofdev->dev, skb->data, priv->rx_buffer_size, DMA_FROM_DEVICE); lstatus = BD_LFLAG(RXBD_EMPTY | RXBD_INTERRUPT); @@ -1856,7 +1858,7 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) skb = priv->rx_skbuff[priv->skb_currx]; - dma_unmap_single(&priv->dev->dev, bdp->bufPtr, + dma_unmap_single(&priv->ofdev->dev, bdp->bufPtr, priv->rx_buffer_size, DMA_FROM_DEVICE); /* We drop the frame if we failed to allocate a new buffer */ @@ -1916,7 +1918,7 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) static int gfar_poll(struct napi_struct *napi, int budget) { struct gfar_private *priv = container_of(napi, struct gfar_private, napi); - struct net_device *dev = priv->dev; + struct net_device *dev = priv->ndev; int tx_cleaned = 0; int rx_cleaned = 0; unsigned long flags; diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 54332b0059d..dd499d7cde2 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -738,7 +738,8 @@ struct gfar_private { spinlock_t rxlock; struct device_node *node; - struct net_device *dev; + struct net_device *ndev; + struct of_device *ofdev; struct napi_struct napi; /* skb array and index */ -- GitLab From 0e0fde3c8d65524b8dfd834332d6e4a92711a66a Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Mon, 16 Mar 2009 19:50:57 +0000 Subject: [PATCH 3722/4982] sh_eth: Change handling of IRQ Handling of IRQ of the SH7763/SH7764 CPU which sh_eth supported was changed. This revises it for this change. Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: David S. Miller --- drivers/net/sh_eth.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 7f8e514eb5e..7b1882765a0 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -687,6 +687,7 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) { struct net_device *ndev = netdev; struct sh_eth_private *mdp = netdev_priv(ndev); + irqreturn_t ret = IRQ_NONE; u32 ioaddr, boguscnt = RX_RING_SIZE; u32 intr_status = 0; @@ -696,7 +697,13 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) /* Get interrpt stat */ intr_status = ctrl_inl(ioaddr + EESR); /* Clear interrupt */ - ctrl_outl(intr_status, ioaddr + EESR); + if (intr_status & (EESR_FRC | EESR_RMAF | EESR_RRF | + EESR_RTLF | EESR_RTSF | EESR_PRE | EESR_CERF | + TX_CHECK | EESR_ERR_CHECK)) { + ctrl_outl(intr_status, ioaddr + EESR); + ret = IRQ_HANDLED; + } else + goto other_irq; if (intr_status & (EESR_FRC | /* Frame recv*/ EESR_RMAF | /* Multi cast address recv*/ @@ -723,9 +730,10 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) ndev->name, intr_status); } +other_irq: spin_unlock(&mdp->lock); - return IRQ_HANDLED; + return ret; } static void sh_eth_timer(unsigned long data) @@ -844,7 +852,13 @@ static int sh_eth_open(struct net_device *ndev) int ret = 0; struct sh_eth_private *mdp = netdev_priv(ndev); - ret = request_irq(ndev->irq, &sh_eth_interrupt, 0, ndev->name, ndev); + ret = request_irq(ndev->irq, &sh_eth_interrupt, +#if defined(CONFIG_CPU_SUBTYPE_SH7763) || defined(CONFIG_CPU_SUBTYPE_SH7764) + IRQF_SHARED, +#else + 0, +#endif + ndev->name, ndev); if (ret) { printk(KERN_ERR "Can not assign IRQ number to %s\n", CARDNAME); return ret; -- GitLab From 2e2a6a9f710255c87cef670fb71fc9e74bef1da2 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Mon, 16 Mar 2009 19:52:23 +0000 Subject: [PATCH 3723/4982] sh_eth: Fix mistake of the address of SH7763 Address of SH_TSU_ADDR and ARSTR of SH7763 was wrong. This revise it. Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: David S. Miller --- drivers/net/sh_eth.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/sh_eth.h b/drivers/net/sh_eth.h index 73bc7181cc1..1537e13e623 100644 --- a/drivers/net/sh_eth.h +++ b/drivers/net/sh_eth.h @@ -43,8 +43,8 @@ #define SH7763_SKB_ALIGN 32 /* Chip Base Address */ -# define SH_TSU_ADDR 0xFFE01800 -# define ARSTR 0xFFE01800 +# define SH_TSU_ADDR 0xFEE01800 +# define ARSTR SH_TSU_ADDR /* Chip Registers */ /* E-DMAC */ -- GitLab From 44c1d6f99d4c86638bffabf0b7a232d0fe7ae574 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Wed, 18 Mar 2009 23:37:18 -0700 Subject: [PATCH 3724/4982] smsc911x: reset last known duplex and carrier on open smsc911x_phy_adjust_link is called periodically by the phy layer (as it's run in polling mode), and it only updates the hardware when it sees a change in duplex or carrier. This patch clears the last known values every time the interface is brought up, instead of only when the module is loaded. Without this patch the adjust_link function never updates the hardware after an ifconfig down; ifconfig up. On a full duplex link this causes the tx error counter to increment, even though packets are correctly transmitted, as the default MAC_CR register setting is for half duplex. The tx errors are "no carrier" errors, which should be ignored in full-duplex mode. When MAC_CR is set to "full duplex" mode they are correctly ignored by the hardware. Note that even with this patch the tx error counter can increment if packets are transmitted between "ifconfig up" and the first phy poll interval. An improved solution would use the phy interrupt with phylib, but I haven't managed to make this work 100% robustly yet. Signed-off-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/smsc911x.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 9a78daec2fe..d1590ac55e4 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1225,6 +1225,10 @@ static int smsc911x_open(struct net_device *dev) dev_info(&dev->dev, "SMSC911x/921x identified at %#08lx, IRQ: %d\n", (unsigned long)pdata->ioaddr, dev->irq); + /* Reset the last known duplex and carrier */ + pdata->last_duplex = -1; + pdata->last_carrier = -1; + /* Bring the PHY up */ phy_start(pdata->phy_dev); -- GitLab From 170ebf85160dd128e1c4206cc197cce7d1424705 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Wed, 18 Mar 2009 23:44:23 -0700 Subject: [PATCH 3725/4982] bas_gigaset: correctly allocate USB interrupt transfer buffer Every USB transfer buffer has to be allocated individually by kmalloc. Impact: bugfix, no functional change Signed-off-by: Tilman Schmidt Tested-by: Kolja Waschk Signed-off-by: David S. Miller --- drivers/isdn/gigaset/bas-gigaset.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 18dd8aacbe8..831ddce1467 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -46,6 +46,9 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode"); /* length limit according to Siemens 3070usb-protokoll.doc ch. 2.1 */ #define IF_WRITEBUF 264 +/* interrupt pipe message size according to ibid. ch. 2.2 */ +#define IP_MSGSIZE 3 + /* Values for the Gigaset 307x */ #define USB_GIGA_VENDOR_ID 0x0681 #define USB_3070_PRODUCT_ID 0x0001 @@ -110,7 +113,7 @@ struct bas_cardstate { unsigned char *rcvbuf; /* AT reply receive buffer */ struct urb *urb_int_in; /* URB for interrupt pipe */ - unsigned char int_in_buf[3]; + unsigned char *int_in_buf; spinlock_t lock; /* locks all following */ int basstate; /* bitmap (BS_*) */ @@ -657,7 +660,7 @@ static void read_int_callback(struct urb *urb) } /* drop incomplete packets even if the missing bytes wouldn't matter */ - if (unlikely(urb->actual_length < 3)) { + if (unlikely(urb->actual_length < IP_MSGSIZE)) { dev_warn(cs->dev, "incomplete interrupt packet (%d bytes)\n", urb->actual_length); goto resubmit; @@ -2127,6 +2130,7 @@ static void gigaset_reinitbcshw(struct bc_state *bcs) static void gigaset_freecshw(struct cardstate *cs) { /* timers, URBs and rcvbuf are disposed of in disconnect */ + kfree(cs->hw.bas->int_in_buf); kfree(cs->hw.bas); cs->hw.bas = NULL; } @@ -2140,6 +2144,12 @@ static int gigaset_initcshw(struct cardstate *cs) pr_err("out of memory\n"); return 0; } + ucs->int_in_buf = kmalloc(IP_MSGSIZE, GFP_KERNEL); + if (!ucs->int_in_buf) { + kfree(ucs); + pr_err("out of memory\n"); + return 0; + } ucs->urb_cmd_in = NULL; ucs->urb_cmd_out = NULL; @@ -2292,7 +2302,7 @@ static int gigaset_probe(struct usb_interface *interface, usb_fill_int_urb(ucs->urb_int_in, udev, usb_rcvintpipe(udev, (endpoint->bEndpointAddress) & 0x0f), - ucs->int_in_buf, 3, read_int_callback, cs, + ucs->int_in_buf, IP_MSGSIZE, read_int_callback, cs, endpoint->bInterval); if ((rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL)) != 0) { dev_err(cs->dev, "could not submit interrupt URB: %s\n", -- GitLab From 42cc77c861e8e850e86252bb5b1e12e006261973 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 18 Mar 2009 23:51:57 -0700 Subject: [PATCH 3726/4982] sparc64: Reschedule KGDB capture to a software interrupt. Otherwise it might interrupt switch_to() midstream and use half-cooked register window state. Reported-by: Chris Torek Signed-off-by: David S. Miller --- arch/sparc/include/asm/pil.h | 1 + arch/sparc/kernel/kgdb_64.c | 2 +- arch/sparc/kernel/ttable.S | 7 ++++++- arch/sparc/mm/ultra.S | 24 ++---------------------- 4 files changed, 10 insertions(+), 24 deletions(-) diff --git a/arch/sparc/include/asm/pil.h b/arch/sparc/include/asm/pil.h index 32a7efe76d0..26693703054 100644 --- a/arch/sparc/include/asm/pil.h +++ b/arch/sparc/include/asm/pil.h @@ -24,6 +24,7 @@ #define PIL_DEVICE_IRQ 5 #define PIL_SMP_CALL_FUNC_SNGL 6 #define PIL_DEFERRED_PCR_WORK 7 +#define PIL_KGDB_CAPTURE 8 #define PIL_NORMAL_MAX 14 #define PIL_NMI 15 diff --git a/arch/sparc/kernel/kgdb_64.c b/arch/sparc/kernel/kgdb_64.c index fefbe6dc51b..f5a0fd490b5 100644 --- a/arch/sparc/kernel/kgdb_64.c +++ b/arch/sparc/kernel/kgdb_64.c @@ -108,7 +108,7 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) } #ifdef CONFIG_SMP -void smp_kgdb_capture_client(struct pt_regs *regs) +void smp_kgdb_capture_client(int irq, struct pt_regs *regs) { unsigned long flags; diff --git a/arch/sparc/kernel/ttable.S b/arch/sparc/kernel/ttable.S index d9bdfb9d5c1..76d837fc47d 100644 --- a/arch/sparc/kernel/ttable.S +++ b/arch/sparc/kernel/ttable.S @@ -64,7 +64,12 @@ tl0_irq6: TRAP_IRQ(smp_call_function_single_client, 6) tl0_irq6: BTRAP(0x46) #endif tl0_irq7: TRAP_IRQ(deferred_pcr_work_irq, 7) -tl0_irq8: BTRAP(0x48) BTRAP(0x49) +#ifdef CONFIG_KGDB +tl0_irq8: TRAP_IRQ(smp_kgdb_capture_client, 8) +#else +tl0_irq8: BTRAP(0x48) +#endif +tl0_irq9: BTRAP(0x49) tl0_irq10: BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d) tl0_irq14: TRAP_IRQ(timer_interrupt, 14) tl0_irq15: TRAP_NMI_IRQ(perfctr_irq, 15) diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S index 80c788ec7c3..b57a5942ba6 100644 --- a/arch/sparc/mm/ultra.S +++ b/arch/sparc/mm/ultra.S @@ -679,28 +679,8 @@ xcall_new_mmu_context_version: #ifdef CONFIG_KGDB .globl xcall_kgdb_capture xcall_kgdb_capture: -661: rdpr %pstate, %g2 - wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate - .section .sun4v_2insn_patch, "ax" - .word 661b - nop - nop - .previous - - rdpr %pil, %g2 - wrpr %g0, PIL_NORMAL_MAX, %pil - sethi %hi(109f), %g7 - ba,pt %xcc, etrap_irq -109: or %g7, %lo(109b), %g7 -#ifdef CONFIG_TRACE_IRQFLAGS - call trace_hardirqs_off - nop -#endif - call smp_kgdb_capture_client - add %sp, PTREGS_OFF, %o0 - /* Has to be a non-v9 branch due to the large distance. */ - ba rtrap_xcall - ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 + wr %g0, (1 << PIL_KGDB_CAPTURE), %set_softint + retry #endif #endif /* CONFIG_SMP */ -- GitLab From 192d7a4667c6d11d1a174ec4cad9a3c5d5f9043c Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Wed, 18 Mar 2009 23:53:16 -0700 Subject: [PATCH 3727/4982] sparc64: Fix crash with /proc/iomem When you compile kernel on Sparc64 with heap memory checking and type "cat /proc/iomem", you get a crash, because pointers in struct resource are uninitialized. Most code fills struct resource with zeros, so I assume that it is responsibility of the caller of request_resource to initialized it, not the responsibility of request_resource functuion. After 2.6.29 is out, there could be a check for uninitialized fields added to request_resource to avoid crashes like this. Signed-off-by: Mikulas Patocka Signed-off-by: David S. Miller --- arch/sparc/kernel/pci_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sparc/kernel/pci_common.c b/arch/sparc/kernel/pci_common.c index 64e6edf17b9..b775658a927 100644 --- a/arch/sparc/kernel/pci_common.c +++ b/arch/sparc/kernel/pci_common.c @@ -368,7 +368,7 @@ static void pci_register_iommu_region(struct pci_pbm_info *pbm) const u32 *vdma = of_get_property(pbm->op->node, "virtual-dma", NULL); if (vdma) { - struct resource *rp = kmalloc(sizeof(*rp), GFP_KERNEL); + struct resource *rp = kzalloc(sizeof(*rp), GFP_KERNEL); if (!rp) { prom_printf("Cannot allocate IOMMU resource.\n"); -- GitLab From a2328d0249fce44381289525bd580b37d2105963 Mon Sep 17 00:00:00 2001 From: Giuliano Pochini Date: Thu, 19 Mar 2009 00:09:03 +0100 Subject: [PATCH 3728/4982] ALSA: Echoaudio: add support for Indigo express cards This patch adds support for IndigoIOx and IndigoDJx. Signed-off-by: Giuliano Pochini Signed-off-by: Takashi Iwai --- sound/pci/Kconfig | 20 ++++ sound/pci/echoaudio/Makefile | 4 + sound/pci/echoaudio/echoaudio.h | 3 + sound/pci/echoaudio/echoaudio_dsp.h | 9 +- sound/pci/echoaudio/indigo_express_dsp.c | 119 +++++++++++++++++++++++ sound/pci/echoaudio/indigodjx.c | 107 ++++++++++++++++++++ sound/pci/echoaudio/indigodjx_dsp.c | 68 +++++++++++++ sound/pci/echoaudio/indigoiox.c | 109 +++++++++++++++++++++ sound/pci/echoaudio/indigoiox_dsp.c | 68 +++++++++++++ 9 files changed, 505 insertions(+), 2 deletions(-) create mode 100644 sound/pci/echoaudio/indigo_express_dsp.c create mode 100644 sound/pci/echoaudio/indigodjx.c create mode 100644 sound/pci/echoaudio/indigodjx_dsp.c create mode 100644 sound/pci/echoaudio/indigoiox.c create mode 100644 sound/pci/echoaudio/indigoiox_dsp.c diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 82b9bddcdcd..9387ab00a41 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig @@ -400,6 +400,26 @@ config SND_INDIGODJ To compile this driver as a module, choose M here: the module will be called snd-indigodj +config SND_INDIGOIOX + tristate "(Echoaudio) Indigo IOx" + select FW_LOADER + select SND_PCM + help + Say 'Y' or 'M' to include support for Echoaudio Indigo IOx. + + To compile this driver as a module, choose M here: the module + will be called snd-indigoiox + +config SND_INDIGODJX + tristate "(Echoaudio) Indigo DJx" + select FW_LOADER + select SND_PCM + help + Say 'Y' or 'M' to include support for Echoaudio Indigo DJx. + + To compile this driver as a module, choose M here: the module + will be called snd-indigodjx + config SND_EMU10K1 tristate "Emu10k1 (SB Live!, Audigy, E-mu APS)" select FW_LOADER diff --git a/sound/pci/echoaudio/Makefile b/sound/pci/echoaudio/Makefile index 7b576aeb3f8..1361de77e0c 100644 --- a/sound/pci/echoaudio/Makefile +++ b/sound/pci/echoaudio/Makefile @@ -15,6 +15,8 @@ snd-echo3g-objs := echo3g.o snd-indigo-objs := indigo.o snd-indigoio-objs := indigoio.o snd-indigodj-objs := indigodj.o +snd-indigoiox-objs := indigoiox.o +snd-indigodjx-objs := indigodjx.o obj-$(CONFIG_SND_DARLA20) += snd-darla20.o obj-$(CONFIG_SND_GINA20) += snd-gina20.o @@ -28,3 +30,5 @@ obj-$(CONFIG_SND_ECHO3G) += snd-echo3g.o obj-$(CONFIG_SND_INDIGO) += snd-indigo.o obj-$(CONFIG_SND_INDIGOIO) += snd-indigoio.o obj-$(CONFIG_SND_INDIGODJ) += snd-indigodj.o +obj-$(CONFIG_SND_INDIGOIOX) += snd-indigoiox.o +obj-$(CONFIG_SND_INDIGODJX) += snd-indigodjx.o diff --git a/sound/pci/echoaudio/echoaudio.h b/sound/pci/echoaudio/echoaudio.h index 1c88e051abf..f9490ae36c2 100644 --- a/sound/pci/echoaudio/echoaudio.h +++ b/sound/pci/echoaudio/echoaudio.h @@ -189,6 +189,9 @@ #define INDIGO 0x0090 #define INDIGO_IO 0x00a0 #define INDIGO_DJ 0x00b0 +#define DC8 0x00c0 +#define INDIGO_IOX 0x00d0 +#define INDIGO_DJX 0x00e0 #define ECHO3G 0x0100 diff --git a/sound/pci/echoaudio/echoaudio_dsp.h b/sound/pci/echoaudio/echoaudio_dsp.h index e352f3ae292..cb7d75a0a50 100644 --- a/sound/pci/echoaudio/echoaudio_dsp.h +++ b/sound/pci/echoaudio/echoaudio_dsp.h @@ -576,8 +576,13 @@ SET_LAYLA24_FREQUENCY_REG command. #define E3G_ASIC_NOT_LOADED 0xffff #define E3G_BOX_TYPE_MASK 0xf0 -#define EXT_3GBOX_NC 0x01 -#define EXT_3GBOX_NOT_SET 0x02 +/* Indigo express control register values */ +#define INDIGO_EXPRESS_32000 0x02 +#define INDIGO_EXPRESS_44100 0x01 +#define INDIGO_EXPRESS_48000 0x00 +#define INDIGO_EXPRESS_DOUBLE_SPEED 0x10 +#define INDIGO_EXPRESS_QUAD_SPEED 0x04 +#define INDIGO_EXPRESS_CLOCK_MASK 0x17 /* diff --git a/sound/pci/echoaudio/indigo_express_dsp.c b/sound/pci/echoaudio/indigo_express_dsp.c new file mode 100644 index 00000000000..9ab625e1565 --- /dev/null +++ b/sound/pci/echoaudio/indigo_express_dsp.c @@ -0,0 +1,119 @@ +/************************************************************************ + +This file is part of Echo Digital Audio's generic driver library. +Copyright Echo Digital Audio Corporation (c) 1998 - 2005 +All rights reserved +www.echoaudio.com + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +************************************************************************* + + Translation from C++ and adaptation for use in ALSA-Driver + were made by Giuliano Pochini + +*************************************************************************/ + +static int set_sample_rate(struct echoaudio *chip, u32 rate) +{ + u32 clock, control_reg, old_control_reg; + + if (wait_handshake(chip)) + return -EIO; + + old_control_reg = le32_to_cpu(chip->comm_page->control_register); + control_reg = old_control_reg & ~INDIGO_EXPRESS_CLOCK_MASK; + + switch (rate) { + case 32000: + clock = INDIGO_EXPRESS_32000; + break; + case 44100: + clock = INDIGO_EXPRESS_44100; + break; + case 48000: + clock = INDIGO_EXPRESS_48000; + break; + case 64000: + clock = INDIGO_EXPRESS_32000|INDIGO_EXPRESS_DOUBLE_SPEED; + break; + case 88200: + clock = INDIGO_EXPRESS_44100|INDIGO_EXPRESS_DOUBLE_SPEED; + break; + case 96000: + clock = INDIGO_EXPRESS_48000|INDIGO_EXPRESS_DOUBLE_SPEED; + break; + default: + return -EINVAL; + } + + control_reg |= clock; + if (control_reg != old_control_reg) { + chip->comm_page->control_register = cpu_to_le32(control_reg); + chip->sample_rate = rate; + clear_handshake(chip); + return send_vector(chip, DSP_VC_UPDATE_CLOCKS); + } + return 0; +} + + + +/* This function routes the sound from a virtual channel to a real output */ +static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, + int gain) +{ + int index; + + if (snd_BUG_ON(pipe >= num_pipes_out(chip) || + output >= num_busses_out(chip))) + return -EINVAL; + + if (wait_handshake(chip)) + return -EIO; + + chip->vmixer_gain[output][pipe] = gain; + index = output * num_pipes_out(chip) + pipe; + chip->comm_page->vmixer[index] = gain; + + DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain)); + return 0; +} + + + +/* Tell the DSP to read and update virtual mixer levels in comm page. */ +static int update_vmixer_level(struct echoaudio *chip) +{ + if (wait_handshake(chip)) + return -EIO; + clear_handshake(chip); + return send_vector(chip, DSP_VC_SET_VMIXER_GAIN); +} + + + +static u32 detect_input_clocks(const struct echoaudio *chip) +{ + return ECHO_CLOCK_BIT_INTERNAL; +} + + + +/* The IndigoIO has no ASIC. Just do nothing */ +static int load_asic(struct echoaudio *chip) +{ + return 0; +} diff --git a/sound/pci/echoaudio/indigodjx.c b/sound/pci/echoaudio/indigodjx.c new file mode 100644 index 00000000000..3482ef69f49 --- /dev/null +++ b/sound/pci/echoaudio/indigodjx.c @@ -0,0 +1,107 @@ +/* + * ALSA driver for Echoaudio soundcards. + * Copyright (C) 2009 Giuliano Pochini + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#define INDIGO_FAMILY +#define ECHOCARD_INDIGO_DJX +#define ECHOCARD_NAME "Indigo DJx" +#define ECHOCARD_HAS_SUPER_INTERLEAVE +#define ECHOCARD_HAS_VMIXER +#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 + +/* Pipe indexes */ +#define PX_ANALOG_OUT 0 /* 8 */ +#define PX_DIGITAL_OUT 8 /* 0 */ +#define PX_ANALOG_IN 8 /* 0 */ +#define PX_DIGITAL_IN 8 /* 0 */ +#define PX_NUM 8 + +/* Bus indexes */ +#define BX_ANALOG_OUT 0 /* 4 */ +#define BX_DIGITAL_OUT 4 /* 0 */ +#define BX_ANALOG_IN 4 /* 0 */ +#define BX_DIGITAL_IN 4 /* 0 */ +#define BX_NUM 4 + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "echoaudio.h" + +MODULE_FIRMWARE("ea/loader_dsp.fw"); +MODULE_FIRMWARE("ea/indigo_djx_dsp.fw"); + +#define FW_361_LOADER 0 +#define FW_INDIGO_DJX_DSP 1 + +static const struct firmware card_fw[] = { + {0, "loader_dsp.fw"}, + {0, "indigo_djx_dsp.fw"} +}; + +static struct pci_device_id snd_echo_ids[] = { + {0x1057, 0x3410, 0xECC0, 0x00E0, 0, 0, 0}, /* Indigo DJx*/ + {0,} +}; + +static struct snd_pcm_hardware pcm_hardware_skel = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_SYNC_START, + .formats = SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_S32_BE, + .rates = SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000, + .rate_min = 32000, + .rate_max = 96000, + .channels_min = 1, + .channels_max = 4, + .buffer_bytes_max = 262144, + .period_bytes_min = 32, + .period_bytes_max = 131072, + .periods_min = 2, + .periods_max = 220, +}; + +#include "indigodjx_dsp.c" +#include "indigo_express_dsp.c" +#include "echoaudio_dsp.c" +#include "echoaudio.c" diff --git a/sound/pci/echoaudio/indigodjx_dsp.c b/sound/pci/echoaudio/indigodjx_dsp.c new file mode 100644 index 00000000000..f591fc2ed96 --- /dev/null +++ b/sound/pci/echoaudio/indigodjx_dsp.c @@ -0,0 +1,68 @@ +/************************************************************************ + +This file is part of Echo Digital Audio's generic driver library. +Copyright Echo Digital Audio Corporation (c) 1998 - 2005 +All rights reserved +www.echoaudio.com + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +************************************************************************* + + Translation from C++ and adaptation for use in ALSA-Driver + were made by Giuliano Pochini + +*************************************************************************/ + +static int update_vmixer_level(struct echoaudio *chip); +static int set_vmixer_gain(struct echoaudio *chip, u16 output, + u16 pipe, int gain); + + +static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) +{ + int err; + + DE_INIT(("init_hw() - Indigo DJx\n")); + if (snd_BUG_ON((subdevice_id & 0xfff0) != INDIGO_DJX)) + return -ENODEV; + + err = init_dsp_comm_page(chip); + if (err < 0) { + DE_INIT(("init_hw - could not initialize DSP comm page\n")); + return err; + } + + chip->device_id = device_id; + chip->subdevice_id = subdevice_id; + chip->bad_board = TRUE; + chip->dsp_code_to_load = &card_fw[FW_INDIGO_DJX_DSP]; + /* Since this card has no ASIC, mark it as loaded so everything + works OK */ + chip->asic_loaded = TRUE; + chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; + + err = load_firmware(chip); + if (err < 0) + return err; + chip->bad_board = FALSE; + + err = init_line_levels(chip); + if (err < 0) + return err; + + DE_INIT(("init_hw done\n")); + return err; +} diff --git a/sound/pci/echoaudio/indigoiox.c b/sound/pci/echoaudio/indigoiox.c new file mode 100644 index 00000000000..aebee27a40f --- /dev/null +++ b/sound/pci/echoaudio/indigoiox.c @@ -0,0 +1,109 @@ +/* + * ALSA driver for Echoaudio soundcards. + * Copyright (C) 2009 Giuliano Pochini + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#define INDIGO_FAMILY +#define ECHOCARD_INDIGO_IOX +#define ECHOCARD_NAME "Indigo IOx" +#define ECHOCARD_HAS_MONITOR +#define ECHOCARD_HAS_SUPER_INTERLEAVE +#define ECHOCARD_HAS_VMIXER +#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 + +/* Pipe indexes */ +#define PX_ANALOG_OUT 0 /* 8 */ +#define PX_DIGITAL_OUT 8 /* 0 */ +#define PX_ANALOG_IN 8 /* 2 */ +#define PX_DIGITAL_IN 10 /* 0 */ +#define PX_NUM 10 + +/* Bus indexes */ +#define BX_ANALOG_OUT 0 /* 2 */ +#define BX_DIGITAL_OUT 2 /* 0 */ +#define BX_ANALOG_IN 2 /* 2 */ +#define BX_DIGITAL_IN 4 /* 0 */ +#define BX_NUM 4 + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "echoaudio.h" + +MODULE_FIRMWARE("ea/loader_dsp.fw"); +MODULE_FIRMWARE("ea/indigo_iox_dsp.fw"); + +#define FW_361_LOADER 0 +#define FW_INDIGO_IOX_DSP 1 + +static const struct firmware card_fw[] = { + {0, "loader_dsp.fw"}, + {0, "indigo_iox_dsp.fw"} +}; + +static struct pci_device_id snd_echo_ids[] = { + {0x1057, 0x3410, 0xECC0, 0x00D0, 0, 0, 0}, /* Indigo IOx */ + {0,} +}; + +static struct snd_pcm_hardware pcm_hardware_skel = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_SYNC_START, + .formats = SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_S32_BE, + .rates = SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000, + .rate_min = 32000, + .rate_max = 96000, + .channels_min = 1, + .channels_max = 8, + .buffer_bytes_max = 262144, + .period_bytes_min = 32, + .period_bytes_max = 131072, + .periods_min = 2, + .periods_max = 220, +}; + +#include "indigoiox_dsp.c" +#include "indigo_express_dsp.c" +#include "echoaudio_dsp.c" +#include "echoaudio.c" + diff --git a/sound/pci/echoaudio/indigoiox_dsp.c b/sound/pci/echoaudio/indigoiox_dsp.c new file mode 100644 index 00000000000..f357521c79e --- /dev/null +++ b/sound/pci/echoaudio/indigoiox_dsp.c @@ -0,0 +1,68 @@ +/************************************************************************ + +This file is part of Echo Digital Audio's generic driver library. +Copyright Echo Digital Audio Corporation (c) 1998 - 2005 +All rights reserved +www.echoaudio.com + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +************************************************************************* + + Translation from C++ and adaptation for use in ALSA-Driver + were made by Giuliano Pochini + +*************************************************************************/ + +static int update_vmixer_level(struct echoaudio *chip); +static int set_vmixer_gain(struct echoaudio *chip, u16 output, + u16 pipe, int gain); + + +static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) +{ + int err; + + DE_INIT(("init_hw() - Indigo IOx\n")); + if (snd_BUG_ON((subdevice_id & 0xfff0) != INDIGO_IOX)) + return -ENODEV; + + err = init_dsp_comm_page(chip); + if (err < 0) { + DE_INIT(("init_hw - could not initialize DSP comm page\n")); + return err; + } + + chip->device_id = device_id; + chip->subdevice_id = subdevice_id; + chip->bad_board = TRUE; + chip->dsp_code_to_load = &card_fw[FW_INDIGO_IOX_DSP]; + /* Since this card has no ASIC, mark it as loaded so everything + works OK */ + chip->asic_loaded = TRUE; + chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; + + err = load_firmware(chip); + if (err < 0) + return err; + chip->bad_board = FALSE; + + err = init_line_levels(chip); + if (err < 0) + return err; + + DE_INIT(("init_hw done\n")); + return err; +} -- GitLab From d1b95607e1dde59e2ffae661732c8da34aba445c Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 13 Mar 2009 15:17:32 +0100 Subject: [PATCH 3729/4982] [ARM] pxa: add missing pin function for CS2 on GPIO1 Signed-off-by: Daniel Mack Signed-off-by: Eric Miao --- arch/arm/mach-pxa/include/mach/mfp-pxa300.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa300.h b/arch/arm/mach-pxa/include/mach/mfp-pxa300.h index bc1fb33a6e7..928fbef9cbf 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa300.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa300.h @@ -41,6 +41,7 @@ #endif /* Chip Select */ +#define GPIO1_nCS2 MFP_CFG(GPIO1, AF1) #define GPIO2_nCS3 MFP_CFG(GPIO2, AF1) /* AC97 */ -- GitLab From c68ffddabcaaa64c6ea681d2944cbda50a8654ea Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Thu, 5 Mar 2009 18:17:53 +0300 Subject: [PATCH 3730/4982] [ARM] pxa: make second argument of clk_add_alias a name instead of the device clk_add_alias is commonly called for platform devices that are not yet registered in the device tree. Thus the clock alias is associated with NULL device name. Fix this by passing the device name instead of just device pointer. Signed-off-by: Dmitry Eremin-Solenikov Signed-off-by: Eric Miao --- arch/arm/mach-pxa/clock.c | 4 ++-- arch/arm/mach-pxa/clock.h | 2 +- arch/arm/mach-pxa/e740.c | 2 +- arch/arm/mach-pxa/e750.c | 2 +- arch/arm/mach-pxa/e800.c | 2 +- arch/arm/mach-pxa/tosa.c | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c index 40b77408451..db52d2c4791 100644 --- a/arch/arm/mach-pxa/clock.c +++ b/arch/arm/mach-pxa/clock.c @@ -87,7 +87,7 @@ void clks_register(struct clk_lookup *clks, size_t num) clkdev_add(&clks[i]); } -int clk_add_alias(char *alias, struct device *alias_dev, char *id, +int clk_add_alias(const char *alias, const char *alias_dev_name, char *id, struct device *dev) { struct clk *r = clk_get(dev, id); @@ -96,7 +96,7 @@ int clk_add_alias(char *alias, struct device *alias_dev, char *id, if (!r) return -ENODEV; - l = clkdev_alloc(r, alias, alias_dev ? dev_name(alias_dev) : NULL); + l = clkdev_alloc(r, alias, alias_dev_name); clk_put(r); if (!l) return -ENODEV; diff --git a/arch/arm/mach-pxa/clock.h b/arch/arm/mach-pxa/clock.h index 4e9c613c676..5599bceff73 100644 --- a/arch/arm/mach-pxa/clock.h +++ b/arch/arm/mach-pxa/clock.h @@ -69,6 +69,6 @@ extern void clk_pxa3xx_cken_disable(struct clk *); #endif void clks_register(struct clk_lookup *clks, size_t num); -int clk_add_alias(char *alias, struct device *alias_dev, char *id, +int clk_add_alias(const char *alias, const char *alias_name, char *id, struct device *dev); diff --git a/arch/arm/mach-pxa/e740.c b/arch/arm/mach-pxa/e740.c index 6d48e00f4f0..f2402f669b5 100644 --- a/arch/arm/mach-pxa/e740.c +++ b/arch/arm/mach-pxa/e740.c @@ -189,7 +189,7 @@ static void __init e740_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(e740_pin_config)); eseries_register_clks(); - clk_add_alias("CLK_CK48M", &e740_t7l66xb_device.dev, + clk_add_alias("CLK_CK48M", e740_t7l66xb_device.name, "UDCCLK", &pxa25x_device_udc.dev), eseries_get_tmio_gpios(); platform_add_devices(devices, ARRAY_SIZE(devices)); diff --git a/arch/arm/mach-pxa/e750.c b/arch/arm/mach-pxa/e750.c index be1ab8edb97..1379f9ad66a 100644 --- a/arch/arm/mach-pxa/e750.c +++ b/arch/arm/mach-pxa/e750.c @@ -190,7 +190,7 @@ static struct platform_device *devices[] __initdata = { static void __init e750_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(e750_pin_config)); - clk_add_alias("CLK_CK3P6MI", &e750_tc6393xb_device.dev, + clk_add_alias("CLK_CK3P6MI", e750_tc6393xb_device.name, "GPIO11_CLK", NULL), eseries_get_tmio_gpios(); platform_add_devices(devices, ARRAY_SIZE(devices)); diff --git a/arch/arm/mach-pxa/e800.c b/arch/arm/mach-pxa/e800.c index cc9b1293e86..0cc0062ea83 100644 --- a/arch/arm/mach-pxa/e800.c +++ b/arch/arm/mach-pxa/e800.c @@ -196,7 +196,7 @@ static struct platform_device *devices[] __initdata = { static void __init e800_init(void) { - clk_add_alias("CLK_CK3P6MI", &e800_tc6393xb_device.dev, + clk_add_alias("CLK_CK3P6MI", e800_tc6393xb_device.name, "GPIO11_CLK", NULL), eseries_get_tmio_gpios(); platform_add_devices(devices, ARRAY_SIZE(devices)); diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 3332e5d0356..3fe137fc72d 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -919,7 +919,7 @@ static void __init tosa_init(void) pxa2xx_set_spi_info(2, &pxa_ssp_master_info); spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); - clk_add_alias("CLK_CK3P6MI", &tc6393xb_device.dev, "GPIO11_CLK", NULL); + clk_add_alias("CLK_CK3P6MI", tc6393xb_device.name, "GPIO11_CLK", NULL); platform_add_devices(devices, ARRAY_SIZE(devices)); } -- GitLab From 782385ae176b304c7105051e1b06c68bc0b4a2ba Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Thu, 19 Mar 2009 15:24:30 +0800 Subject: [PATCH 3731/4982] [ARM] pxa: fix overlay being un-necessarily initialized on pxa25x pxa25x doesn't support overlay in its LCD controller, this patch adds pxafb_overlay_supported() functions to check the initialization is necessary. Signed-off-by: Eric Miao --- drivers/video/pxafb.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 48ff701d3a7..40a5d9d6675 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -883,10 +883,21 @@ static void __devinit init_pxafb_overlay(struct pxafb_info *fbi, init_completion(&ofb->branch_done); } +static inline int pxafb_overlay_supported(void) +{ + if (cpu_is_pxa27x() || cpu_is_pxa3xx()) + return 1; + + return 0; +} + static int __devinit pxafb_overlay_init(struct pxafb_info *fbi) { int i, ret; + if (!pxafb_overlay_supported()) + return 0; + for (i = 0; i < 2; i++) { init_pxafb_overlay(fbi, &fbi->overlay[i], i); ret = register_framebuffer(&fbi->overlay[i].fb); @@ -909,6 +920,9 @@ static void __devexit pxafb_overlay_exit(struct pxafb_info *fbi) { int i; + if (!pxafb_overlay_supported()) + return; + for (i = 0; i < 2; i++) unregister_framebuffer(&fbi->overlay[i].fb); } -- GitLab From cad377acf3d6af6279622048e96680e79e352183 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 19 Mar 2009 09:55:15 +0100 Subject: [PATCH 3732/4982] ALSA: pcm - Fix a typo in error messages Fix a typo in error messages; forgotten after a copy&paste error. Signed-off-by: Takashi Iwai --- sound/core/pcm_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 86ac9ae9460..2ff25ed4d83 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -194,7 +194,7 @@ static inline int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream do { \ if (xrun_debug(substream)) { \ if (printk_ratelimit()) { \ - snd_printd("hda_codec: " fmt, ##args); \ + snd_printd("PCM: " fmt, ##args); \ } \ dump_stack_on_xrun(substream); \ } \ -- GitLab From 98204646f2b15d368701265e4194b773a6f94600 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 19 Mar 2009 09:59:21 +0100 Subject: [PATCH 3733/4982] ALSA: pcm - avoid unnecessary inline Remove unnecessary explicit inlininig of internal functions. Let compiler optimize. Signed-off-by: Takashi Iwai --- sound/core/pcm_lib.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 2ff25ed4d83..302654769fa 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -148,8 +148,9 @@ static void xrun(struct snd_pcm_substream *substream) } } -static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(struct snd_pcm_substream *substream, - struct snd_pcm_runtime *runtime) +static snd_pcm_uframes_t +snd_pcm_update_hw_ptr_pos(struct snd_pcm_substream *substream, + struct snd_pcm_runtime *runtime) { snd_pcm_uframes_t pos; @@ -167,8 +168,8 @@ static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(struct snd_pcm_substre return pos; } -static inline int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream, - struct snd_pcm_runtime *runtime) +static int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream, + struct snd_pcm_runtime *runtime) { snd_pcm_uframes_t avail; @@ -200,7 +201,7 @@ static inline int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream } \ } while (0) -static inline int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) +static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_uframes_t pos; -- GitLab From 5f513e1197f27e9a0bcfec0feaac59f976f4a37e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 19 Mar 2009 10:01:47 +0100 Subject: [PATCH 3734/4982] ALSA: pcm - Reset invalid position even without debug option Always reset the invalind hw_ptr position returned by the pointer callback. The behavior should be consitent independently from the debug option. Also, add the printk_ratelimit() check to avoid flooding debug prints. Signed-off-by: Takashi Iwai --- sound/core/pcm_lib.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 302654769fa..92ed6d81922 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -159,11 +159,15 @@ snd_pcm_update_hw_ptr_pos(struct snd_pcm_substream *substream, pos = substream->ops->pointer(substream); if (pos == SNDRV_PCM_POS_XRUN) return pos; /* XRUN */ -#ifdef CONFIG_SND_DEBUG if (pos >= runtime->buffer_size) { - snd_printk(KERN_ERR "BUG: stream = %i, pos = 0x%lx, buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size); + if (printk_ratelimit()) { + snd_printd(KERN_ERR "BUG: stream = %i, pos = 0x%lx, " + "buffer size = 0x%lx, period size = 0x%lx\n", + substream->stream, pos, runtime->buffer_size, + runtime->period_size); + } + pos = 0; } -#endif pos -= pos % runtime->min_align; return pos; } -- GitLab From ded652f7024bc2d7b6118b561a44187af30841b0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 19 Mar 2009 10:08:49 +0100 Subject: [PATCH 3735/4982] ALSA: pcm - Fix delta calculation at boundary overlap When the hw_ptr_interrupt reaches the boundary, it must check whether the hw_base was already lapped and corret the delta value appropriately. Also, rebasing the hw_ptr needs a correction because buffer_size isn't always aligned to period_size. Signed-off-by: Takashi Iwai --- sound/core/pcm_lib.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 92ed6d81922..063c675177a 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -221,8 +221,11 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) new_hw_ptr = hw_base + pos; hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size; delta = new_hw_ptr - hw_ptr_interrupt; - if (hw_ptr_interrupt == runtime->boundary) - hw_ptr_interrupt = 0; + if (hw_ptr_interrupt >= runtime->boundary) { + hw_ptr_interrupt %= runtime->boundary; + if (!hw_base) /* hw_base was already lapped; recalc delta */ + delta = new_hw_ptr - hw_ptr_interrupt; + } if (delta < 0) { delta += runtime->buffer_size; if (delta < 0) { @@ -233,6 +236,8 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) (long)hw_ptr_interrupt); /* rebase to interrupt position */ hw_base = new_hw_ptr = hw_ptr_interrupt; + /* align hw_base to buffer_size */ + hw_base -= hw_base % runtime->buffer_size; delta = 0; } else { hw_base += runtime->buffer_size; -- GitLab From 97b71c94d691728b82052e9c4d6286fbc9965d7f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 18 Mar 2009 15:09:13 +0100 Subject: [PATCH 3736/4982] ALSA: hda - Don't reset BDL unnecessarily So far, the prepare callback is called multiple times, BDL entries are reset and re-programmed at each time. This patch adds the check to avoid the reset of BDL entries when the same parameters are used. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 46 +++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 6bcf5af6edc..ba97795d89c 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1076,8 +1076,7 @@ static int azx_setup_periods(struct azx *chip, azx_sd_writel(azx_dev, SD_BDLPL, 0); azx_sd_writel(azx_dev, SD_BDLPU, 0); - period_bytes = snd_pcm_lib_period_bytes(substream); - azx_dev->period_bytes = period_bytes; + period_bytes = azx_dev->period_bytes; periods = azx_dev->bufsize / period_bytes; /* program the initial BDL entries */ @@ -1124,9 +1123,6 @@ static int azx_setup_periods(struct azx *chip, error: snd_printk(KERN_ERR "Too many BDL entries: buffer=%d, period=%d\n", azx_dev->bufsize, period_bytes); - /* reset */ - azx_sd_writel(azx_dev, SD_BDLPL, 0); - azx_sd_writel(azx_dev, SD_BDLPU, 0); return -EINVAL; } @@ -1429,6 +1425,11 @@ static int azx_pcm_close(struct snd_pcm_substream *substream) static int azx_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { + struct azx_dev *azx_dev = get_azx_dev(substream); + + azx_dev->bufsize = 0; + azx_dev->period_bytes = 0; + azx_dev->format_val = 0; return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); } @@ -1443,6 +1444,9 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream) azx_sd_writel(azx_dev, SD_BDLPL, 0); azx_sd_writel(azx_dev, SD_BDLPU, 0); azx_sd_writel(azx_dev, SD_CTL, 0); + azx_dev->bufsize = 0; + azx_dev->period_bytes = 0; + azx_dev->format_val = 0; hinfo->ops.cleanup(hinfo, apcm->codec, substream); @@ -1456,23 +1460,37 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) struct azx_dev *azx_dev = get_azx_dev(substream); struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; struct snd_pcm_runtime *runtime = substream->runtime; + unsigned int bufsize, period_bytes, format_val; + int err; - azx_dev->bufsize = snd_pcm_lib_buffer_bytes(substream); - azx_dev->format_val = snd_hda_calc_stream_format(runtime->rate, - runtime->channels, - runtime->format, - hinfo->maxbps); - if (!azx_dev->format_val) { + format_val = snd_hda_calc_stream_format(runtime->rate, + runtime->channels, + runtime->format, + hinfo->maxbps); + if (!format_val) { snd_printk(KERN_ERR SFX "invalid format_val, rate=%d, ch=%d, format=%d\n", runtime->rate, runtime->channels, runtime->format); return -EINVAL; } + bufsize = snd_pcm_lib_buffer_bytes(substream); + period_bytes = snd_pcm_lib_period_bytes(substream); + snd_printdd("azx_pcm_prepare: bufsize=0x%x, format=0x%x\n", - azx_dev->bufsize, azx_dev->format_val); - if (azx_setup_periods(chip, substream, azx_dev) < 0) - return -EINVAL; + bufsize, format_val); + + if (bufsize != azx_dev->bufsize || + period_bytes != azx_dev->period_bytes || + format_val != azx_dev->format_val) { + azx_dev->bufsize = bufsize; + azx_dev->period_bytes = period_bytes; + azx_dev->format_val = format_val; + err = azx_setup_periods(chip, substream, azx_dev); + if (err < 0) + return err; + } + azx_setup_controller(chip, azx_dev); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; -- GitLab From 1dddab400b7ad028b21d7d5b060e4a068d6d3cd9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 18 Mar 2009 15:15:37 +0100 Subject: [PATCH 3737/4982] ALSA: hda - Don't reset stream at each prepare callback Don't reset the stream at each prepare callback but do it only once after the open. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index ba97795d89c..8b2e4160de8 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -859,13 +859,18 @@ static void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev) SD_CTL_DMA_START | SD_INT_MASK); } -/* stop a stream */ -static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev) +/* stop DMA */ +static void azx_stream_clear(struct azx *chip, struct azx_dev *azx_dev) { - /* stop DMA */ azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) & ~(SD_CTL_DMA_START | SD_INT_MASK)); azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */ +} + +/* stop a stream */ +static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev) +{ + azx_stream_clear(chip, azx_dev); /* disable SIE */ azx_writeb(chip, INTCTL, azx_readb(chip, INTCTL) & ~(1 << azx_dev->index)); @@ -1126,18 +1131,14 @@ static int azx_setup_periods(struct azx *chip, return -EINVAL; } -/* - * set up the SD for streaming - */ -static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) +/* reset stream */ +static void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev) { unsigned char val; int timeout; - /* make sure the run bit is zero for SD */ - azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) & - ~SD_CTL_DMA_START); - /* reset stream */ + azx_stream_clear(chip, azx_dev); + azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | SD_CTL_STREAM_RESET); udelay(3); @@ -1154,7 +1155,15 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) while (((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) && --timeout) ; +} +/* + * set up the SD for streaming + */ +static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) +{ + /* make sure the run bit is zero for SD */ + azx_stream_clear(chip, azx_dev); /* program the stream_tag */ azx_sd_writel(azx_dev, SD_CTL, (azx_sd_readl(azx_dev, SD_CTL) & ~SD_CTL_STREAM_TAG_MASK)| @@ -1399,6 +1408,8 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) runtime->private_data = azx_dev; snd_pcm_set_sync(substream); mutex_unlock(&chip->open_mutex); + + azx_stream_reset(chip, azx_dev); return 0; } -- GitLab From e8523b641cddedec754ae5e44ec579dbceea5ef4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 18 Mar 2009 18:28:01 +0000 Subject: [PATCH 3738/4982] ASoC: Add FLL support for WM8400 Signed-off-by: Mark Brown --- sound/soc/codecs/wm8400.c | 129 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index b7350c25b61..510efa60400 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c @@ -70,6 +70,7 @@ struct wm8400_priv { unsigned int sysclk; unsigned int pcmclk; struct work_struct work; + int fll_in, fll_out; }; static inline unsigned int wm8400_read(struct snd_soc_codec *codec, @@ -931,6 +932,133 @@ static int wm8400_set_dai_sysclk(struct snd_soc_dai *codec_dai, return 0; } +struct fll_factors { + u16 n; + u16 k; + u16 outdiv; + u16 fratio; + u16 freq_ref; +}; + +#define FIXED_FLL_SIZE ((1 << 16) * 10) + +static int fll_factors(struct wm8400_priv *wm8400, struct fll_factors *factors, + unsigned int Fref, unsigned int Fout) +{ + u64 Kpart; + unsigned int K, Nmod, target; + + factors->outdiv = 2; + while (Fout * factors->outdiv < 90000000 || + Fout * factors->outdiv > 100000000) { + factors->outdiv *= 2; + if (factors->outdiv > 32) { + dev_err(wm8400->wm8400->dev, + "Unsupported FLL output frequency %dHz\n", + Fout); + return -EINVAL; + } + } + target = Fout * factors->outdiv; + factors->outdiv = factors->outdiv >> 2; + + if (Fref < 48000) + factors->freq_ref = 1; + else + factors->freq_ref = 0; + + if (Fref < 1000000) + factors->fratio = 9; + else + factors->fratio = 0; + + /* Ensure we have a fractional part */ + do { + if (Fref < 1000000) + factors->fratio--; + else + factors->fratio++; + + if (factors->fratio < 1 || factors->fratio > 8) { + dev_err(wm8400->wm8400->dev, + "Unable to calculate FRATIO\n"); + return -EINVAL; + } + + factors->n = target / (Fref * factors->fratio); + Nmod = target % (Fref * factors->fratio); + } while (Nmod == 0); + + /* Calculate fractional part - scale up so we can round. */ + Kpart = FIXED_FLL_SIZE * (long long)Nmod; + + do_div(Kpart, (Fref * factors->fratio)); + + K = Kpart & 0xFFFFFFFF; + + if ((K % 10) >= 5) + K += 5; + + /* Move down to proper range now rounding is done */ + factors->k = K / 10; + + dev_dbg(wm8400->wm8400->dev, + "FLL: Fref=%d Fout=%d N=%x K=%x, FRATIO=%x OUTDIV=%x\n", + Fref, Fout, + factors->n, factors->k, factors->fratio, factors->outdiv); + + return 0; +} + +static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, + unsigned int freq_in, unsigned int freq_out) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct wm8400_priv *wm8400 = codec->private_data; + struct fll_factors factors; + int ret; + u16 reg; + + if (freq_in == wm8400->fll_in && freq_out == wm8400->fll_out) + return 0; + + if (freq_out != 0) { + ret = fll_factors(wm8400, &factors, freq_in, freq_out); + if (ret != 0) + return ret; + } + + wm8400->fll_out = freq_out; + wm8400->fll_in = freq_in; + + /* We *must* disable the FLL before any changes */ + reg = wm8400_read(codec, WM8400_POWER_MANAGEMENT_2); + reg &= ~WM8400_FLL_ENA; + wm8400_write(codec, WM8400_POWER_MANAGEMENT_2, reg); + + reg = wm8400_read(codec, WM8400_FLL_CONTROL_1); + reg &= ~WM8400_FLL_OSC_ENA; + wm8400_write(codec, WM8400_FLL_CONTROL_1, reg); + + if (freq_out == 0) + return 0; + + reg &= ~(WM8400_FLL_REF_FREQ | WM8400_FLL_FRATIO_MASK); + reg |= WM8400_FLL_FRAC | factors.fratio; + reg |= factors.freq_ref << WM8400_FLL_REF_FREQ_SHIFT; + wm8400_write(codec, WM8400_FLL_CONTROL_1, reg); + + wm8400_write(codec, WM8400_FLL_CONTROL_2, factors.k); + wm8400_write(codec, WM8400_FLL_CONTROL_3, factors.n); + + reg = wm8400_read(codec, WM8400_FLL_CONTROL_4); + reg &= WM8400_FLL_OUTDIV_MASK; + reg |= factors.outdiv; + wm8400_write(codec, WM8400_FLL_CONTROL_4, reg); + + return 0; +} + /* * Sets ADC and Voice DAC format. */ @@ -1188,6 +1316,7 @@ static struct snd_soc_dai_ops wm8400_dai_ops = { .set_fmt = wm8400_set_dai_fmt, .set_clkdiv = wm8400_set_dai_clkdiv, .set_sysclk = wm8400_set_dai_sysclk, + .set_pll = wm8400_set_dai_pll, }; /* -- GitLab From 13b9d2ab5921d77df5217a2104b687a1c729d521 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Wed, 18 Mar 2009 16:46:53 +0200 Subject: [PATCH 3739/4982] ASoC: OMAP: N810: Mark not connected input pins Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/omap/n810.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c index 86471fd6340..f203221d9cb 100644 --- a/sound/soc/omap/n810.c +++ b/sound/soc/omap/n810.c @@ -254,6 +254,11 @@ static int n810_aic33_init(struct snd_soc_codec *codec) snd_soc_dapm_nc_pin(codec, "MONO_LOUT"); snd_soc_dapm_nc_pin(codec, "HPLCOM"); snd_soc_dapm_nc_pin(codec, "HPRCOM"); + snd_soc_dapm_nc_pin(codec, "MIC3L"); + snd_soc_dapm_nc_pin(codec, "MIC3R"); + snd_soc_dapm_nc_pin(codec, "LINE1R"); + snd_soc_dapm_nc_pin(codec, "LINE2L"); + snd_soc_dapm_nc_pin(codec, "LINE2R"); /* Add N810 specific controls */ err = snd_soc_add_controls(codec, aic33_n810_controls, -- GitLab From f8d5fc924b1bec95f47b0a9e8f9a6e22fa1c7b05 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Wed, 18 Mar 2009 16:46:54 +0200 Subject: [PATCH 3740/4982] ASoC: OMAP: N810: Add more jack functions Add functions "Headset" and "Mic" to the control "Jack Function" for activating and de-activating codec input pin LINE1L which is connected to the mic pin of 4-pole Nokia AV connecter. Note there is no mic bias voltage management here since bias is coming from Nokia ASIC and driver for it is not in mainline. Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/omap/n810.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c index f203221d9cb..a6d1178ce12 100644 --- a/sound/soc/omap/n810.c +++ b/sound/soc/omap/n810.c @@ -40,6 +40,13 @@ #define N810_HEADSET_AMP_GPIO 10 #define N810_SPEAKER_AMP_GPIO 101 +enum { + N810_JACK_DISABLED, + N810_JACK_HP, + N810_JACK_HS, + N810_JACK_MIC, +}; + static struct clk *sys_clkout2; static struct clk *sys_clkout2_src; static struct clk *func96m_clk; @@ -50,15 +57,32 @@ static int n810_dmic_func; static void n810_ext_control(struct snd_soc_codec *codec) { + int hp = 0, line1l = 0; + + switch (n810_jack_func) { + case N810_JACK_HS: + line1l = 1; + case N810_JACK_HP: + hp = 1; + break; + case N810_JACK_MIC: + line1l = 1; + break; + } + if (n810_spk_func) snd_soc_dapm_enable_pin(codec, "Ext Spk"); else snd_soc_dapm_disable_pin(codec, "Ext Spk"); - if (n810_jack_func) + if (hp) snd_soc_dapm_enable_pin(codec, "Headphone Jack"); else snd_soc_dapm_disable_pin(codec, "Headphone Jack"); + if (line1l) + snd_soc_dapm_enable_pin(codec, "LINE1L"); + else + snd_soc_dapm_disable_pin(codec, "LINE1L"); if (n810_dmic_func) snd_soc_dapm_enable_pin(codec, "DMic"); @@ -229,7 +253,7 @@ static const struct snd_soc_dapm_route audio_map[] = { }; static const char *spk_function[] = {"Off", "On"}; -static const char *jack_function[] = {"Off", "Headphone"}; +static const char *jack_function[] = {"Off", "Headphone", "Headset", "Mic"}; static const char *input_function[] = {"ADC", "Digital Mic"}; static const struct soc_enum n810_enum[] = { SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function), -- GitLab From 632087748c3795a54d5631e640df65592774e045 Mon Sep 17 00:00:00 2001 From: "Lopez Cruz, Misael" Date: Thu, 19 Mar 2009 01:07:34 -0500 Subject: [PATCH 3741/4982] ASoC: Declare Headset as Mic and Headphone widgets for SDP3430 Headset was declared previously as a Headphone widget connecting HSMIC and HSOL/HSOR pins of TWL4030 codec in SDP430 machine driver. The capture path becomes invalid as the Headphone widget is not a valid input endpoint. Instead of that, the Headset is declared as separate Microphone and Headphone widgets. Current patch modifies audio map: - Headset Mic: HSMIC with bias - Headset Stereophone: HSOL, HSOR Signed-off-by: Misael Lopez Cruz Signed-off-by: Mark Brown --- sound/soc/omap/sdp3430.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c index 0a41de677e7..10f1c867f11 100644 --- a/sound/soc/omap/sdp3430.c +++ b/sound/soc/omap/sdp3430.c @@ -90,8 +90,12 @@ static struct snd_soc_jack hs_jack; /* Headset jack detection DAPM pins */ static struct snd_soc_jack_pin hs_jack_pins[] = { { - .pin = "Headset Jack", - .mask = SND_JACK_HEADSET, + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, + { + .pin = "Headset Stereophone", + .mask = SND_JACK_HEADPHONE, }, }; @@ -109,7 +113,8 @@ static struct snd_soc_jack_gpio hs_jack_gpios[] = { static const struct snd_soc_dapm_widget sdp3430_twl4030_dapm_widgets[] = { SND_SOC_DAPM_MIC("Ext Mic", NULL), SND_SOC_DAPM_SPK("Ext Spk", NULL), - SND_SOC_DAPM_HP("Headset Jack", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_HP("Headset Stereophone", NULL), }; static const struct snd_soc_dapm_route audio_map[] = { @@ -123,11 +128,13 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Ext Spk", NULL, "HFL"}, {"Ext Spk", NULL, "HFR"}, - /* Headset: HSMIC (with bias), HSOL, HSOR */ - {"Headset Jack", NULL, "HSOL"}, - {"Headset Jack", NULL, "HSOR"}, + /* Headset Mic: HSMIC with bias */ {"HSMIC", NULL, "Headset Mic Bias"}, - {"Headset Mic Bias", NULL, "Headset Jack"}, + {"Headset Mic Bias", NULL, "Headset Mic"}, + + /* Headset Stereophone (Headphone): HSOL, HSOR */ + {"Headset Stereophone", NULL, "HSOL"}, + {"Headset Stereophone", NULL, "HSOR"}, }; static int sdp3430_twl4030_init(struct snd_soc_codec *codec) @@ -146,7 +153,8 @@ static int sdp3430_twl4030_init(struct snd_soc_codec *codec) /* SDP3430 connected pins */ snd_soc_dapm_enable_pin(codec, "Ext Mic"); snd_soc_dapm_enable_pin(codec, "Ext Spk"); - snd_soc_dapm_disable_pin(codec, "Headset Jack"); + snd_soc_dapm_disable_pin(codec, "Headset Mic"); + snd_soc_dapm_disable_pin(codec, "Headset Stereophone"); /* TWL4030 not connected pins */ snd_soc_dapm_nc_pin(codec, "AUXL"); -- GitLab From 1f2186951e02f2a5bcda9459f63136918932385a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 19 Mar 2009 14:08:58 +0100 Subject: [PATCH 3742/4982] ALSA: Fix wrong pointer to dev_err() in arm/pxa2xx-ac97-lib.c Fix the wrong device pointer passed to dev_err(). Signed-off-by: Takashi Iwai --- sound/arm/pxa2xx-ac97-lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c index d721ea7cae8..2e6355f4cbb 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c @@ -374,7 +374,7 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) case -1: break; default: - dev_err(dev, "Invalid reset GPIO %d\n", + dev_err(&dev->dev, "Invalid reset GPIO %d\n", pdata->reset_gpio); } } else { -- GitLab From 07a1e81355245ca65ab16c7b4ae2332e52ed7acd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 19 Mar 2009 17:08:19 +0100 Subject: [PATCH 3743/4982] ALSA: hda - Don't show the current connection for power widgets The power-widgets have no connection selection, so skip the check in proc output, too. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_proc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 93b25ba4d00..639cf0edaa9 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -399,8 +399,10 @@ static void print_conn_list(struct snd_info_buffer *buffer, { int c, curr = -1; - if (conn_len > 1 && wid_type != AC_WID_AUD_MIX && - wid_type != AC_WID_VOL_KNB) + if (conn_len > 1 && + wid_type != AC_WID_AUD_MIX && + wid_type != AC_WID_VOL_KNB && + wid_type != AC_WID_POWER) curr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0); snd_iprintf(buffer, " Connection: %d\n", conn_len); -- GitLab From be093beb608edf821b45fe00a8a080fb5c6ed4af Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 19 Mar 2009 16:20:24 +0000 Subject: [PATCH 3744/4982] [ARM] pass reboot command line to arch_reset() OMAP wishes to pass state to the boot loader upon reboot in order to instruct it whether to wait for USB-based reflashing or not. There is already a facility to do this via the reboot() syscall, except we ignore the string passed to machine_restart(). This patch fixes things to pass this string to arch_reset(). This means that we keep the reboot mode limited to telling the kernel _how_ to perform the reboot which should be independent of what we request the boot loader to do. Acked-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/include/asm/system.h | 4 ++-- arch/arm/kernel/process.c | 10 +++++----- arch/arm/mach-aaec2000/include/mach/system.h | 2 +- arch/arm/mach-at91/include/mach/system.h | 2 +- arch/arm/mach-clps711x/include/mach/system.h | 2 +- arch/arm/mach-davinci/include/mach/system.h | 2 +- arch/arm/mach-ebsa110/include/mach/system.h | 2 +- arch/arm/mach-ep93xx/include/mach/system.h | 2 +- arch/arm/mach-footbridge/include/mach/system.h | 2 +- arch/arm/mach-h720x/include/mach/system.h | 2 +- arch/arm/mach-imx/include/mach/system.h | 2 +- arch/arm/mach-integrator/include/mach/system.h | 2 +- arch/arm/mach-iop13xx/include/mach/system.h | 2 +- arch/arm/mach-iop32x/include/mach/system.h | 2 +- arch/arm/mach-iop33x/include/mach/system.h | 2 +- arch/arm/mach-ixp2000/include/mach/system.h | 2 +- arch/arm/mach-ixp23xx/include/mach/system.h | 2 +- arch/arm/mach-ixp4xx/include/mach/system.h | 2 +- arch/arm/mach-kirkwood/include/mach/system.h | 2 +- arch/arm/mach-ks8695/include/mach/system.h | 2 +- arch/arm/mach-l7200/include/mach/system.h | 2 +- arch/arm/mach-lh7a40x/include/mach/system.h | 2 +- arch/arm/mach-loki/include/mach/system.h | 2 +- arch/arm/mach-msm/include/mach/system.h | 2 +- arch/arm/mach-mv78xx0/include/mach/system.h | 2 +- arch/arm/mach-mx2/system.c | 2 +- arch/arm/mach-netx/include/mach/system.h | 2 +- arch/arm/mach-ns9xxx/include/mach/system.h | 2 +- arch/arm/mach-orion5x/include/mach/system.h | 2 +- arch/arm/mach-orion5x/lsmini-setup.c | 2 +- arch/arm/mach-pnx4008/include/mach/system.h | 2 +- arch/arm/mach-pxa/corgi.c | 6 +++--- arch/arm/mach-pxa/include/mach/system.h | 2 +- arch/arm/mach-pxa/mioa701.c | 6 +++--- arch/arm/mach-pxa/poodle.c | 6 +++--- arch/arm/mach-pxa/reset.c | 2 +- arch/arm/mach-pxa/spitz.c | 4 ++-- arch/arm/mach-pxa/tosa.c | 4 ++-- arch/arm/mach-realview/include/mach/system.h | 2 +- arch/arm/mach-rpc/include/mach/system.h | 2 +- arch/arm/mach-s3c2410/include/mach/system-reset.h | 2 +- arch/arm/mach-s3c6400/include/mach/system.h | 2 +- arch/arm/mach-sa1100/include/mach/system.h | 2 +- arch/arm/mach-shark/core.c | 2 +- arch/arm/mach-shark/include/mach/system.h | 2 +- arch/arm/mach-versatile/include/mach/system.h | 2 +- arch/arm/mach-w90x900/include/mach/system.h | 2 +- arch/arm/plat-mxc/include/mach/system.h | 2 +- arch/arm/plat-omap/include/mach/system.h | 2 +- arch/arm/plat-s3c24xx/cpu.c | 6 +++--- 50 files changed, 65 insertions(+), 65 deletions(-) diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 811be55f338..0a0d49ae1e6 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -97,8 +97,8 @@ extern void __show_regs(struct pt_regs *); extern int cpu_architecture(void); extern void cpu_init(void); -void arm_machine_restart(char mode); -extern void (*arm_pm_restart)(char str); +void arm_machine_restart(char mode, const char *cmd); +extern void (*arm_pm_restart)(char str, const char *cmd); #define UDBG_UNDEFINED (1 << 0) #define UDBG_SYSCALL (1 << 1) diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index af377c73d90..2de14e2afdc 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -83,7 +83,7 @@ static int __init hlt_setup(char *__unused) __setup("nohlt", nohlt_setup); __setup("hlt", hlt_setup); -void arm_machine_restart(char mode) +void arm_machine_restart(char mode, const char *cmd) { /* * Clean and disable cache, and turn off interrupts @@ -100,7 +100,7 @@ void arm_machine_restart(char mode) /* * Now call the architecture specific reboot code. */ - arch_reset(mode); + arch_reset(mode, cmd); /* * Whoops - the architecture was unable to reboot. @@ -120,7 +120,7 @@ EXPORT_SYMBOL(pm_idle); void (*pm_power_off)(void); EXPORT_SYMBOL(pm_power_off); -void (*arm_pm_restart)(char str) = arm_machine_restart; +void (*arm_pm_restart)(char str, const char *cmd) = arm_machine_restart; EXPORT_SYMBOL_GPL(arm_pm_restart); @@ -195,9 +195,9 @@ void machine_power_off(void) pm_power_off(); } -void machine_restart(char * __unused) +void machine_restart(char *cmd) { - arm_pm_restart(reboot_mode); + arm_pm_restart(reboot_mode, cmd); } void __show_regs(struct pt_regs *regs) diff --git a/arch/arm/mach-aaec2000/include/mach/system.h b/arch/arm/mach-aaec2000/include/mach/system.h index 8f4115d734c..fe08ca1add6 100644 --- a/arch/arm/mach-aaec2000/include/mach/system.h +++ b/arch/arm/mach-aaec2000/include/mach/system.h @@ -16,7 +16,7 @@ static inline void arch_idle(void) cpu_do_idle(); } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { cpu_reset(0); } diff --git a/arch/arm/mach-at91/include/mach/system.h b/arch/arm/mach-at91/include/mach/system.h index e712658d966..5268af3933c 100644 --- a/arch/arm/mach-at91/include/mach/system.h +++ b/arch/arm/mach-at91/include/mach/system.h @@ -43,7 +43,7 @@ static inline void arch_idle(void) void (*at91_arch_reset)(void); -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { /* call the CPU-specific reset function */ if (at91_arch_reset) diff --git a/arch/arm/mach-clps711x/include/mach/system.h b/arch/arm/mach-clps711x/include/mach/system.h index 24e96159e3e..f916cd7a477 100644 --- a/arch/arm/mach-clps711x/include/mach/system.h +++ b/arch/arm/mach-clps711x/include/mach/system.h @@ -32,7 +32,7 @@ static inline void arch_idle(void) mov r0, r0"); } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { cpu_reset(0); } diff --git a/arch/arm/mach-davinci/include/mach/system.h b/arch/arm/mach-davinci/include/mach/system.h index 17ca41dc2c5..b7e7036674f 100644 --- a/arch/arm/mach-davinci/include/mach/system.h +++ b/arch/arm/mach-davinci/include/mach/system.h @@ -21,7 +21,7 @@ static void arch_idle(void) cpu_do_idle(); } -static void arch_reset(char mode) +static void arch_reset(char mode, const char *cmd) { davinci_watchdog_reset(); } diff --git a/arch/arm/mach-ebsa110/include/mach/system.h b/arch/arm/mach-ebsa110/include/mach/system.h index 350a028997e..9a26245bf1f 100644 --- a/arch/arm/mach-ebsa110/include/mach/system.h +++ b/arch/arm/mach-ebsa110/include/mach/system.h @@ -34,6 +34,6 @@ static inline void arch_idle(void) asm volatile ("mcr p15, 0, ip, c15, c1, 2" : : : "cc"); } -#define arch_reset(mode) cpu_reset(0x80000000) +#define arch_reset(mode, cmd) cpu_reset(0x80000000) #endif diff --git a/arch/arm/mach-ep93xx/include/mach/system.h b/arch/arm/mach-ep93xx/include/mach/system.h index 67789d0f329..ed8f35e4f06 100644 --- a/arch/arm/mach-ep93xx/include/mach/system.h +++ b/arch/arm/mach-ep93xx/include/mach/system.h @@ -9,7 +9,7 @@ static inline void arch_idle(void) cpu_do_idle(); } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { u32 devicecfg; diff --git a/arch/arm/mach-footbridge/include/mach/system.h b/arch/arm/mach-footbridge/include/mach/system.h index 2db7f36bd6c..0b293156620 100644 --- a/arch/arm/mach-footbridge/include/mach/system.h +++ b/arch/arm/mach-footbridge/include/mach/system.h @@ -18,7 +18,7 @@ static inline void arch_idle(void) cpu_do_idle(); } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { if (mode == 's') { /* diff --git a/arch/arm/mach-h720x/include/mach/system.h b/arch/arm/mach-h720x/include/mach/system.h index e4a7c760d52..a708d24ee46 100644 --- a/arch/arm/mach-h720x/include/mach/system.h +++ b/arch/arm/mach-h720x/include/mach/system.h @@ -25,7 +25,7 @@ static void arch_idle(void) } -static __inline__ void arch_reset(char mode) +static __inline__ void arch_reset(char mode, const char *cmd) { CPU_REG (PMU_BASE, PMU_STAT) |= PMU_WARMRESET; } diff --git a/arch/arm/mach-imx/include/mach/system.h b/arch/arm/mach-imx/include/mach/system.h index adee7e51bab..46d4ca91af7 100644 --- a/arch/arm/mach-imx/include/mach/system.h +++ b/arch/arm/mach-imx/include/mach/system.h @@ -32,7 +32,7 @@ arch_idle(void) } static inline void -arch_reset(char mode) +arch_reset(char mode, const char *cmd) { cpu_reset(0); } diff --git a/arch/arm/mach-integrator/include/mach/system.h b/arch/arm/mach-integrator/include/mach/system.h index c485345c8c7..e1551b8dab7 100644 --- a/arch/arm/mach-integrator/include/mach/system.h +++ b/arch/arm/mach-integrator/include/mach/system.h @@ -32,7 +32,7 @@ static inline void arch_idle(void) cpu_do_idle(); } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { /* * To reset, we hit the on-board reset register diff --git a/arch/arm/mach-iop13xx/include/mach/system.h b/arch/arm/mach-iop13xx/include/mach/system.h index c7127f416e1..d0c66ef450a 100644 --- a/arch/arm/mach-iop13xx/include/mach/system.h +++ b/arch/arm/mach-iop13xx/include/mach/system.h @@ -13,7 +13,7 @@ static inline void arch_idle(void) cpu_do_idle(); } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { /* * Reset the internal bus (warning both cores are reset) diff --git a/arch/arm/mach-iop32x/include/mach/system.h b/arch/arm/mach-iop32x/include/mach/system.h index 32d9e5b0a28..a4b808fe0d8 100644 --- a/arch/arm/mach-iop32x/include/mach/system.h +++ b/arch/arm/mach-iop32x/include/mach/system.h @@ -16,7 +16,7 @@ static inline void arch_idle(void) cpu_do_idle(); } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { local_irq_disable(); diff --git a/arch/arm/mach-iop33x/include/mach/system.h b/arch/arm/mach-iop33x/include/mach/system.h index 0cb3ad862ac..f192a34be07 100644 --- a/arch/arm/mach-iop33x/include/mach/system.h +++ b/arch/arm/mach-iop33x/include/mach/system.h @@ -14,7 +14,7 @@ static inline void arch_idle(void) cpu_do_idle(); } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { *IOP3XX_PCSR = 0x30; diff --git a/arch/arm/mach-ixp2000/include/mach/system.h b/arch/arm/mach-ixp2000/include/mach/system.h index 2e9c68f95a2..de370992c84 100644 --- a/arch/arm/mach-ixp2000/include/mach/system.h +++ b/arch/arm/mach-ixp2000/include/mach/system.h @@ -17,7 +17,7 @@ static inline void arch_idle(void) cpu_do_idle(); } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { local_irq_disable(); diff --git a/arch/arm/mach-ixp23xx/include/mach/system.h b/arch/arm/mach-ixp23xx/include/mach/system.h index d57c3fc10f1..8920ff2dff1 100644 --- a/arch/arm/mach-ixp23xx/include/mach/system.h +++ b/arch/arm/mach-ixp23xx/include/mach/system.h @@ -19,7 +19,7 @@ static inline void arch_idle(void) #endif } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { /* First try machine specific support */ if (machine_is_ixdp2351()) { diff --git a/arch/arm/mach-ixp4xx/include/mach/system.h b/arch/arm/mach-ixp4xx/include/mach/system.h index 92a7e8ddf69..d2aa26f5acd 100644 --- a/arch/arm/mach-ixp4xx/include/mach/system.h +++ b/arch/arm/mach-ixp4xx/include/mach/system.h @@ -20,7 +20,7 @@ static inline void arch_idle(void) } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { if ( 1 && mode == 's') { /* Jump into ROM at address 0 */ diff --git a/arch/arm/mach-kirkwood/include/mach/system.h b/arch/arm/mach-kirkwood/include/mach/system.h index 8510f6cfdab..23a1914c1da 100644 --- a/arch/arm/mach-kirkwood/include/mach/system.h +++ b/arch/arm/mach-kirkwood/include/mach/system.h @@ -17,7 +17,7 @@ static inline void arch_idle(void) cpu_do_idle(); } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { /* * Enable soft reset to assert RSTOUTn. diff --git a/arch/arm/mach-ks8695/include/mach/system.h b/arch/arm/mach-ks8695/include/mach/system.h index 5a9b032bdbe..fb1dda9be2d 100644 --- a/arch/arm/mach-ks8695/include/mach/system.h +++ b/arch/arm/mach-ks8695/include/mach/system.h @@ -27,7 +27,7 @@ static void arch_idle(void) } -static void arch_reset(char mode) +static void arch_reset(char mode, const char *cmd) { unsigned int reg; diff --git a/arch/arm/mach-l7200/include/mach/system.h b/arch/arm/mach-l7200/include/mach/system.h index 5272abee0d0..e0dd3b6ae4a 100644 --- a/arch/arm/mach-l7200/include/mach/system.h +++ b/arch/arm/mach-l7200/include/mach/system.h @@ -19,7 +19,7 @@ static inline void arch_idle(void) *(unsigned long *)(IO_BASE + 0x50004) = 1; /* idle mode */ } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { if (mode == 's') { cpu_reset(0); diff --git a/arch/arm/mach-lh7a40x/include/mach/system.h b/arch/arm/mach-lh7a40x/include/mach/system.h index fa46bb1ef07..45a56d3b93d 100644 --- a/arch/arm/mach-lh7a40x/include/mach/system.h +++ b/arch/arm/mach-lh7a40x/include/mach/system.h @@ -13,7 +13,7 @@ static inline void arch_idle(void) cpu_do_idle (); } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { cpu_reset (0); } diff --git a/arch/arm/mach-loki/include/mach/system.h b/arch/arm/mach-loki/include/mach/system.h index 8db1147d4ec..c1de36fe9b3 100644 --- a/arch/arm/mach-loki/include/mach/system.h +++ b/arch/arm/mach-loki/include/mach/system.h @@ -17,7 +17,7 @@ static inline void arch_idle(void) cpu_do_idle(); } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { /* * Enable soft reset to assert RSTOUTn. diff --git a/arch/arm/mach-msm/include/mach/system.h b/arch/arm/mach-msm/include/mach/system.h index f05ad2e0f23..574ccc493da 100644 --- a/arch/arm/mach-msm/include/mach/system.h +++ b/arch/arm/mach-msm/include/mach/system.h @@ -17,7 +17,7 @@ void arch_idle(void); -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { for (;;) ; /* depends on IPC w/ other core */ } diff --git a/arch/arm/mach-mv78xx0/include/mach/system.h b/arch/arm/mach-mv78xx0/include/mach/system.h index 7d517940883..1d6350b22d0 100644 --- a/arch/arm/mach-mv78xx0/include/mach/system.h +++ b/arch/arm/mach-mv78xx0/include/mach/system.h @@ -17,7 +17,7 @@ static inline void arch_idle(void) cpu_do_idle(); } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { /* * Enable soft reset to assert RSTOUTn. diff --git a/arch/arm/mach-mx2/system.c b/arch/arm/mach-mx2/system.c index 7b8269719d1..92c79d4bd16 100644 --- a/arch/arm/mach-mx2/system.c +++ b/arch/arm/mach-mx2/system.c @@ -46,7 +46,7 @@ void arch_idle(void) /* * Reset the system. It is called by machine_restart(). */ -void arch_reset(char mode) +void arch_reset(char mode, const char *cmd) { struct clk *clk; diff --git a/arch/arm/mach-netx/include/mach/system.h b/arch/arm/mach-netx/include/mach/system.h index 6c1023b8a9a..dc7b4bc003c 100644 --- a/arch/arm/mach-netx/include/mach/system.h +++ b/arch/arm/mach-netx/include/mach/system.h @@ -28,7 +28,7 @@ static inline void arch_idle(void) cpu_do_idle(); } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { writel(NETX_SYSTEM_RES_CR_FIRMW_RES_EN | NETX_SYSTEM_RES_CR_FIRMW_RES, NETX_SYSTEM_RES_CR); diff --git a/arch/arm/mach-ns9xxx/include/mach/system.h b/arch/arm/mach-ns9xxx/include/mach/system.h index e2068c57415..1561588ca36 100644 --- a/arch/arm/mach-ns9xxx/include/mach/system.h +++ b/arch/arm/mach-ns9xxx/include/mach/system.h @@ -20,7 +20,7 @@ static inline void arch_idle(void) cpu_do_idle(); } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { #ifdef CONFIG_PROCESSOR_NS9360 if (processor_is_ns9360()) diff --git a/arch/arm/mach-orion5x/include/mach/system.h b/arch/arm/mach-orion5x/include/mach/system.h index 08e43075789..9b8db1dcfa8 100644 --- a/arch/arm/mach-orion5x/include/mach/system.h +++ b/arch/arm/mach-orion5x/include/mach/system.h @@ -19,7 +19,7 @@ static inline void arch_idle(void) cpu_do_idle(); } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { /* * Enable and issue soft reset diff --git a/arch/arm/mach-orion5x/lsmini-setup.c b/arch/arm/mach-orion5x/lsmini-setup.c index e0c43b8beb7..c9bf6b81a80 100644 --- a/arch/arm/mach-orion5x/lsmini-setup.c +++ b/arch/arm/mach-orion5x/lsmini-setup.c @@ -186,7 +186,7 @@ static struct mv_sata_platform_data lsmini_sata_data = { static void lsmini_power_off(void) { - arch_reset(0); + arch_reset(0, NULL); } diff --git a/arch/arm/mach-pnx4008/include/mach/system.h b/arch/arm/mach-pnx4008/include/mach/system.h index e12e7abfcbc..5dda2bb55f8 100644 --- a/arch/arm/mach-pnx4008/include/mach/system.h +++ b/arch/arm/mach-pnx4008/include/mach/system.h @@ -30,7 +30,7 @@ static void arch_idle(void) cpu_do_idle(); } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { cpu_reset(0); } diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 3b89e5010fb..cdf21dd135b 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -635,16 +635,16 @@ static void corgi_poweroff(void) /* Green LED off tells the bootloader to halt */ gpio_set_value(CORGI_GPIO_LED_GREEN, 0); - arm_machine_restart('h'); + arm_machine_restart('h', NULL); } -static void corgi_restart(char mode) +static void corgi_restart(char mode, const char *cmd) { if (!machine_is_corgi()) /* Green LED on tells the bootloader to reboot */ gpio_set_value(CORGI_GPIO_LED_GREEN, 1); - arm_machine_restart('h'); + arm_machine_restart('h', cmd); } static void __init corgi_init(void) diff --git a/arch/arm/mach-pxa/include/mach/system.h b/arch/arm/mach-pxa/include/mach/system.h index 0a587c4ec70..d1fce8b6d10 100644 --- a/arch/arm/mach-pxa/include/mach/system.h +++ b/arch/arm/mach-pxa/include/mach/system.h @@ -20,4 +20,4 @@ static inline void arch_idle(void) } -void arch_reset(char mode); +void arch_reset(char mode, const char *cmd); diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c index 025772785d3..97c93a7a285 100644 --- a/arch/arm/mach-pxa/mioa701.c +++ b/arch/arm/mach-pxa/mioa701.c @@ -788,13 +788,13 @@ static void mioa701_machine_exit(void); static void mioa701_poweroff(void) { mioa701_machine_exit(); - arm_machine_restart('s'); + arm_machine_restart('s', NULL); } -static void mioa701_restart(char c) +static void mioa701_restart(char c, const char *cmd) { mioa701_machine_exit(); - arm_machine_restart('s'); + arm_machine_restart('s', cmd); } struct gpio_ress global_gpios[] = { diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index 572ddec2b3e..036bbde4d22 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -501,12 +501,12 @@ static struct platform_device *devices[] __initdata = { static void poodle_poweroff(void) { - arm_machine_restart('h'); + arm_machine_restart('h', NULL); } -static void poodle_restart(char mode) +static void poodle_restart(char mode, const char *cmd) { - arm_machine_restart('h'); + arm_machine_restart('h', cmd); } static void __init poodle_init(void) diff --git a/arch/arm/mach-pxa/reset.c b/arch/arm/mach-pxa/reset.c index 867c95c0961..df29d45fb4e 100644 --- a/arch/arm/mach-pxa/reset.c +++ b/arch/arm/mach-pxa/reset.c @@ -81,7 +81,7 @@ static void do_hw_reset(void) OSMR3 = OSCR + 368640; /* ... in 100 ms */ } -void arch_reset(char mode) +void arch_reset(char mode, const char *cmd) { clear_reset_status(RESET_STATUS_ALL); diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index f697c492b2a..7a0a430222c 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -701,10 +701,10 @@ static struct platform_device *devices[] __initdata = { static void spitz_poweroff(void) { - arm_machine_restart('g'); + arm_machine_restart('g', NULL); } -static void spitz_restart(char mode) +static void spitz_restart(char mode, const char *cmd) { /* Bootloader magic for a reboot */ if((MSC0 & 0xffff0000) == 0x7ff00000) diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 66b13802c99..4f6f5024884 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -876,10 +876,10 @@ static struct platform_device *devices[] __initdata = { static void tosa_poweroff(void) { - arm_machine_restart('g'); + arm_machine_restart('g', NULL); } -static void tosa_restart(char mode) +static void tosa_restart(char mode, const char *cmd) { /* Bootloader magic for a reboot */ if((MSC0 & 0xffff0000) == 0x7ff00000) diff --git a/arch/arm/mach-realview/include/mach/system.h b/arch/arm/mach-realview/include/mach/system.h index a2f61c78adb..1a15a441e02 100644 --- a/arch/arm/mach-realview/include/mach/system.h +++ b/arch/arm/mach-realview/include/mach/system.h @@ -34,7 +34,7 @@ static inline void arch_idle(void) cpu_do_idle(); } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { void __iomem *hdr_ctrl = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_RESETCTL_OFFSET; unsigned int val; diff --git a/arch/arm/mach-rpc/include/mach/system.h b/arch/arm/mach-rpc/include/mach/system.h index bd7268ba17e..45c7b935dc4 100644 --- a/arch/arm/mach-rpc/include/mach/system.h +++ b/arch/arm/mach-rpc/include/mach/system.h @@ -16,7 +16,7 @@ static inline void arch_idle(void) cpu_do_idle(); } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { iomd_writeb(0, IOMD_ROMCR0); diff --git a/arch/arm/mach-s3c2410/include/mach/system-reset.h b/arch/arm/mach-s3c2410/include/mach/system-reset.h index 7613d0a384b..b8687f71c30 100644 --- a/arch/arm/mach-s3c2410/include/mach/system-reset.h +++ b/arch/arm/mach-s3c2410/include/mach/system-reset.h @@ -22,7 +22,7 @@ extern void (*s3c24xx_reset_hook)(void); static void -arch_reset(char mode) +arch_reset(char mode, const char *cmd) { struct clk *wdtclk; diff --git a/arch/arm/mach-s3c6400/include/mach/system.h b/arch/arm/mach-s3c6400/include/mach/system.h index 652bbc403f0..090cfd969bc 100644 --- a/arch/arm/mach-s3c6400/include/mach/system.h +++ b/arch/arm/mach-s3c6400/include/mach/system.h @@ -16,7 +16,7 @@ static void arch_idle(void) /* nothing here yet */ } -static void arch_reset(char mode) +static void arch_reset(char mode, const char *cmd) { /* nothing here yet */ } diff --git a/arch/arm/mach-sa1100/include/mach/system.h b/arch/arm/mach-sa1100/include/mach/system.h index 63755ca5b1b..942b153e251 100644 --- a/arch/arm/mach-sa1100/include/mach/system.h +++ b/arch/arm/mach-sa1100/include/mach/system.h @@ -10,7 +10,7 @@ static inline void arch_idle(void) cpu_do_idle(); } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { if (mode == 's') { /* Jump into ROM at address 0 */ diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c index 4f3a2651259..358d875ace1 100644 --- a/arch/arm/mach-shark/core.c +++ b/arch/arm/mach-shark/core.c @@ -26,7 +26,7 @@ #define ROMCARD_SIZE 0x08000000 #define ROMCARD_START 0x10000000 -void arch_reset(char mode) +void arch_reset(char mode, const char *cmd) { short temp; local_irq_disable(); diff --git a/arch/arm/mach-shark/include/mach/system.h b/arch/arm/mach-shark/include/mach/system.h index 0752ca29971..21c373b30bb 100644 --- a/arch/arm/mach-shark/include/mach/system.h +++ b/arch/arm/mach-shark/include/mach/system.h @@ -7,7 +7,7 @@ #define __ASM_ARCH_SYSTEM_H /* Found in arch/mach-shark/core.c */ -extern void arch_reset(char mode); +extern void arch_reset(char mode, const char *cmd); static inline void arch_idle(void) { diff --git a/arch/arm/mach-versatile/include/mach/system.h b/arch/arm/mach-versatile/include/mach/system.h index c59e6100c7e..8ffc12a7cb2 100644 --- a/arch/arm/mach-versatile/include/mach/system.h +++ b/arch/arm/mach-versatile/include/mach/system.h @@ -34,7 +34,7 @@ static inline void arch_idle(void) cpu_do_idle(); } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { u32 val; diff --git a/arch/arm/mach-w90x900/include/mach/system.h b/arch/arm/mach-w90x900/include/mach/system.h index 93753f92261..94064006685 100644 --- a/arch/arm/mach-w90x900/include/mach/system.h +++ b/arch/arm/mach-w90x900/include/mach/system.h @@ -21,7 +21,7 @@ static void arch_idle(void) { } -static void arch_reset(char mode) +static void arch_reset(char mode, const char *cmd) { cpu_reset(0); } diff --git a/arch/arm/plat-mxc/include/mach/system.h b/arch/arm/plat-mxc/include/mach/system.h index bbfc37465fc..cd03ebaa49b 100644 --- a/arch/arm/plat-mxc/include/mach/system.h +++ b/arch/arm/plat-mxc/include/mach/system.h @@ -26,7 +26,7 @@ static inline void arch_idle(void) cpu_do_idle(); } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { cpu_reset(0); } diff --git a/arch/arm/plat-omap/include/mach/system.h b/arch/arm/plat-omap/include/mach/system.h index e9b95637f7f..cb8c0ef30fb 100644 --- a/arch/arm/plat-omap/include/mach/system.h +++ b/arch/arm/plat-omap/include/mach/system.h @@ -38,7 +38,7 @@ static inline void omap1_arch_reset(char mode) omap_writew(1, ARM_RSTCT1); } -static inline void arch_reset(char mode) +static inline void arch_reset(char mode, const char *cmd) { if (!cpu_class_is_omap2()) omap1_arch_reset(mode); diff --git a/arch/arm/plat-s3c24xx/cpu.c b/arch/arm/plat-s3c24xx/cpu.c index 542062f8cbc..1932b7e0da1 100644 --- a/arch/arm/plat-s3c24xx/cpu.c +++ b/arch/arm/plat-s3c24xx/cpu.c @@ -182,7 +182,7 @@ static unsigned long s3c24xx_read_idcode_v4(void) * with the caches enabled. It seems at least the S3C2440 has a problem * resetting if there is bus activity interrupted by the reset. */ -static void s3c24xx_pm_restart(char mode) +static void s3c24xx_pm_restart(char mode, const char *cmd) { if (mode != 's') { unsigned long flags; @@ -191,12 +191,12 @@ static void s3c24xx_pm_restart(char mode) __cpuc_flush_kern_all(); __cpuc_flush_user_all(); - arch_reset(mode); + arch_reset(mode, cmd); local_irq_restore(flags); } /* fallback, or unhandled */ - arm_machine_restart(mode); + arm_machine_restart(mode, cmd); } void __init s3c24xx_init_io(struct map_desc *mach_desc, int size) -- GitLab From 68df3755e383e6fecf2354a67b08f92f18536594 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 19 Mar 2009 11:10:17 -0700 Subject: [PATCH 3745/4982] Add '-fwrapv' to gcc CFLAGS This makes sure that gcc doesn't try to optimize away wrapping arithmetic, which the kernel occasionally uses for overflow testing, ie things like if (ptr + offset < ptr) which technically is undefined for non-unsigned types. See http://bugzilla.kernel.org/show_bug.cgi?id=12597 for details. Not all versions of gcc support it, so we need to make it conditional (it looks like it was introduced in gcc-3.4). Reminded-by: Alan Cox Signed-off-by: Linus Torvalds --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 2e2f4a4324a..f607658ac89 100644 --- a/Makefile +++ b/Makefile @@ -347,6 +347,7 @@ KBUILD_CPPFLAGS := -D__KERNEL__ KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ -fno-strict-aliasing -fno-common \ -Werror-implicit-function-declaration +KBUILD_CFLAGS += $(call cc-option,-fwrapv) KBUILD_AFLAGS := -D__ASSEMBLY__ # Read KERNELRELEASE from include/config/kernel.release (if it exists) -- GitLab From a8e7d49aa7be728c4ae241a75a2a124cdcabc0c5 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 19 Mar 2009 11:32:05 -0700 Subject: [PATCH 3746/4982] Fix race in create_empty_buffers() vs __set_page_dirty_buffers() Nick Piggin noticed this (very unlikely) race between setting a page dirty and creating the buffers for it - we need to hold the mapping private_lock until we've set the page dirty bit in order to make sure that create_empty_buffers() might not build up a set of buffers without the dirty bits set when the page is dirty. I doubt anybody has ever hit this race (and it didn't solve the issue Nick was looking at), but as Nick says: "Still, it does appear to solve a real race, which we should close." Acked-by: Nick Piggin Signed-off-by: Linus Torvalds --- fs/buffer.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/fs/buffer.c b/fs/buffer.c index 9f697419ed8..891e1c78e4f 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -760,15 +760,9 @@ EXPORT_SYMBOL(mark_buffer_dirty_inode); * If warn is true, then emit a warning if the page is not uptodate and has * not been truncated. */ -static int __set_page_dirty(struct page *page, +static void __set_page_dirty(struct page *page, struct address_space *mapping, int warn) { - if (unlikely(!mapping)) - return !TestSetPageDirty(page); - - if (TestSetPageDirty(page)) - return 0; - spin_lock_irq(&mapping->tree_lock); if (page->mapping) { /* Race with truncate? */ WARN_ON_ONCE(warn && !PageUptodate(page)); @@ -785,8 +779,6 @@ static int __set_page_dirty(struct page *page, } spin_unlock_irq(&mapping->tree_lock); __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); - - return 1; } /* @@ -816,6 +808,7 @@ static int __set_page_dirty(struct page *page, */ int __set_page_dirty_buffers(struct page *page) { + int newly_dirty; struct address_space *mapping = page_mapping(page); if (unlikely(!mapping)) @@ -831,9 +824,12 @@ int __set_page_dirty_buffers(struct page *page) bh = bh->b_this_page; } while (bh != head); } + newly_dirty = !TestSetPageDirty(page); spin_unlock(&mapping->private_lock); - return __set_page_dirty(page, mapping, 1); + if (newly_dirty) + __set_page_dirty(page, mapping, 1); + return newly_dirty; } EXPORT_SYMBOL(__set_page_dirty_buffers); @@ -1262,8 +1258,11 @@ void mark_buffer_dirty(struct buffer_head *bh) return; } - if (!test_set_buffer_dirty(bh)) - __set_page_dirty(bh->b_page, page_mapping(bh->b_page), 0); + if (!test_set_buffer_dirty(bh)) { + struct page *page = bh->b_page; + if (!TestSetPageDirty(page)) + __set_page_dirty(page, page_mapping(page), 0); + } } /* -- GitLab From d0115552cdb0b4d4146975889fee2e9355515c4b Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 19 Mar 2009 15:53:19 -0700 Subject: [PATCH 3747/4982] Move cc-option to below arch-specific setup Sam Ravnborg says: "We have several architectures that plays strange games with $(CC) and $(CROSS_COMPILE). So we need to postpone any use of $(call cc-option..) until we have included the arch specific Makefile so we try with the correct $(CC) version." Requested-by: Sam Ravnborg Signed-off-by: Linus Torvalds --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f607658ac89..a2c2efe9e82 100644 --- a/Makefile +++ b/Makefile @@ -347,7 +347,6 @@ KBUILD_CPPFLAGS := -D__KERNEL__ KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ -fno-strict-aliasing -fno-common \ -Werror-implicit-function-declaration -KBUILD_CFLAGS += $(call cc-option,-fwrapv) KBUILD_AFLAGS := -D__ASSEMBLY__ # Read KERNELRELEASE from include/config/kernel.release (if it exists) @@ -567,6 +566,9 @@ KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,) # disable pointer signed / unsigned warnings in gcc 4.0 KBUILD_CFLAGS += $(call cc-option,-Wno-pointer-sign,) +# disable invalid "can't wrap" optimzations for signed / pointers +KBUILD_CFLAGS += $(call cc-option,-fwrapv) + # Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments # But warn user when we do so warn-assign = \ -- GitLab From 87c3a86e1c220121d0ced59d1a71e78ed9abc6dd Mon Sep 17 00:00:00 2001 From: Davide Libenzi Date: Wed, 18 Mar 2009 17:04:19 -0700 Subject: [PATCH 3748/4982] eventfd: remove fput() call from possible IRQ context Remove a source of fput() call from inside IRQ context. Myself, like Eric, wasn't able to reproduce an fput() call from IRQ context, but Jeff said he was able to, with the attached test program. Independently from this, the bug is conceptually there, so we might be better off fixing it. This patch adds an optimization similar to the one we already do on ->ki_filp, on ->ki_eventfd. Playing with ->f_count directly is not pretty in general, but the alternative here would be to add a brand new delayed fput() infrastructure, that I'm not sure is worth it. Signed-off-by: Davide Libenzi Cc: Benjamin LaHaise Cc: Trond Myklebust Cc: Eric Dumazet Signed-off-by: Jeff Moyer Cc: Zach Brown Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/aio.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/fs/aio.c b/fs/aio.c index 8fa77e23394..4a9d4d641fb 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -443,7 +443,7 @@ static struct kiocb *__aio_get_req(struct kioctx *ctx) req->private = NULL; req->ki_iovec = NULL; INIT_LIST_HEAD(&req->ki_run_list); - req->ki_eventfd = ERR_PTR(-EINVAL); + req->ki_eventfd = NULL; /* Check if the completion queue has enough free space to * accept an event from this io. @@ -485,8 +485,6 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req) { assert_spin_locked(&ctx->ctx_lock); - if (!IS_ERR(req->ki_eventfd)) - fput(req->ki_eventfd); if (req->ki_dtor) req->ki_dtor(req); if (req->ki_iovec != &req->ki_inline_vec) @@ -508,8 +506,11 @@ static void aio_fput_routine(struct work_struct *data) list_del(&req->ki_list); spin_unlock_irq(&fput_lock); - /* Complete the fput */ - __fput(req->ki_filp); + /* Complete the fput(s) */ + if (req->ki_filp != NULL) + __fput(req->ki_filp); + if (req->ki_eventfd != NULL) + __fput(req->ki_eventfd); /* Link the iocb into the context's free list */ spin_lock_irq(&ctx->ctx_lock); @@ -527,12 +528,14 @@ static void aio_fput_routine(struct work_struct *data) */ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req) { + int schedule_putreq = 0; + dprintk(KERN_DEBUG "aio_put(%p): f_count=%ld\n", req, atomic_long_read(&req->ki_filp->f_count)); assert_spin_locked(&ctx->ctx_lock); - req->ki_users --; + req->ki_users--; BUG_ON(req->ki_users < 0); if (likely(req->ki_users)) return 0; @@ -540,10 +543,23 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req) req->ki_cancel = NULL; req->ki_retry = NULL; - /* Must be done under the lock to serialise against cancellation. - * Call this aio_fput as it duplicates fput via the fput_work. + /* + * Try to optimize the aio and eventfd file* puts, by avoiding to + * schedule work in case it is not __fput() time. In normal cases, + * we would not be holding the last reference to the file*, so + * this function will be executed w/out any aio kthread wakeup. */ - if (unlikely(atomic_long_dec_and_test(&req->ki_filp->f_count))) { + if (unlikely(atomic_long_dec_and_test(&req->ki_filp->f_count))) + schedule_putreq++; + else + req->ki_filp = NULL; + if (req->ki_eventfd != NULL) { + if (unlikely(atomic_long_dec_and_test(&req->ki_eventfd->f_count))) + schedule_putreq++; + else + req->ki_eventfd = NULL; + } + if (unlikely(schedule_putreq)) { get_ioctx(ctx); spin_lock(&fput_lock); list_add(&req->ki_list, &fput_head); @@ -1009,7 +1025,7 @@ int aio_complete(struct kiocb *iocb, long res, long res2) * eventfd. The eventfd_signal() function is safe to be called * from IRQ context. */ - if (!IS_ERR(iocb->ki_eventfd)) + if (iocb->ki_eventfd != NULL) eventfd_signal(iocb->ki_eventfd, 1); put_rq: @@ -1608,6 +1624,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, req->ki_eventfd = eventfd_fget((int) iocb->aio_resfd); if (IS_ERR(req->ki_eventfd)) { ret = PTR_ERR(req->ki_eventfd); + req->ki_eventfd = NULL; goto out_put_req; } } -- GitLab From 65c24491b4fef017c64e39ec64384fde5e05e0a0 Mon Sep 17 00:00:00 2001 From: Jeff Moyer Date: Wed, 18 Mar 2009 17:04:21 -0700 Subject: [PATCH 3749/4982] aio: lookup_ioctx can return the wrong value when looking up a bogus context The libaio test harness turned up a problem whereby lookup_ioctx on a bogus io context was returning the 1 valid io context from the list (harness/cases/3.p). Because of that, an extra put_iocontext was done, and when the process exited, it hit a BUG_ON in the put_iocontext macro called from exit_aio (since we expect a users count of 1 and instead get 0). The problem was introduced by "aio: make the lookup_ioctx() lockless" (commit abf137dd7712132ee56d5b3143c2ff61a72a5faa). Thanks to Zach for pointing out that hlist_for_each_entry_rcu will not return with a NULL tpos at the end of the loop, even if the entry was not found. Signed-off-by: Jeff Moyer Acked-by: Zach Brown Acked-by: Jens Axboe Cc: Benjamin LaHaise Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/aio.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/aio.c b/fs/aio.c index 4a9d4d641fb..76da1253795 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -587,7 +587,7 @@ int aio_put_req(struct kiocb *req) static struct kioctx *lookup_ioctx(unsigned long ctx_id) { struct mm_struct *mm = current->mm; - struct kioctx *ctx = NULL; + struct kioctx *ctx, *ret = NULL; struct hlist_node *n; rcu_read_lock(); @@ -595,12 +595,13 @@ static struct kioctx *lookup_ioctx(unsigned long ctx_id) hlist_for_each_entry_rcu(ctx, n, &mm->ioctx_list, list) { if (ctx->user_id == ctx_id && !ctx->dead) { get_ioctx(ctx); + ret = ctx; break; } } rcu_read_unlock(); - return ctx; + return ret; } /* -- GitLab From 2e1ab634bf013792d8803ec57c7a428a76f50028 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 19 Mar 2009 23:49:41 -0700 Subject: [PATCH 3750/4982] rtnetlink: add new value for DHCP added routes To improve manageability, it would be good to be able to disambiguate routes added by administrator from those added by DHCP client. The only necessary kernel change is to add value to rtnetlink include file so iproute2 utility can use it. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/linux/rtnetlink.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index 35a07c830f7..ba3254ecf7f 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -217,6 +217,7 @@ enum #define RTPROT_DNROUTED 13 /* DECnet routing daemon */ #define RTPROT_XORP 14 /* XORP */ #define RTPROT_NTK 15 /* Netsukuku */ +#define RTPROT_DHCP 16 /* DHCP client */ /* rtm_scope -- GitLab From ea1dae11e0baca5d633207fe50fc3cd30a5d68ee Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Thu, 19 Mar 2009 23:56:20 -0700 Subject: [PATCH 3751/4982] be2net: replenish when posting to rx-queue is starved in out of mem conditions This is a patch to replenish the rx-queue when it is in a starved state (due to out-of-mem conditions) Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 1 + drivers/net/benet/be_main.c | 50 +++++++++++++++++++++---------------- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 63d593d5315..f327be57ca9 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -194,6 +194,7 @@ struct be_adapter { struct be_eq_obj rx_eq; struct be_rx_obj rx_obj; u32 big_page_size; /* Compounded page size shared by rx wrbs */ + bool rx_post_starved; /* Zero rx frags have been posted to BE */ struct vlan_group *vlan_grp; u16 num_vlans; diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 897a63de5bd..80fe1e055d9 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -273,26 +273,6 @@ static void be_rx_eqd_update(struct be_adapter *adapter) rx_eq->cur_eqd = eqd; } -static void be_worker(struct work_struct *work) -{ - struct be_adapter *adapter = - container_of(work, struct be_adapter, work.work); - int status; - - /* Check link */ - be_link_status_update(adapter); - - /* Get Stats */ - status = be_cmd_get_stats(&adapter->ctrl, &adapter->stats.cmd); - if (!status) - netdev_stats_update(adapter); - - /* Set EQ delay */ - be_rx_eqd_update(adapter); - - schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); -} - static struct net_device_stats *be_get_stats(struct net_device *dev) { struct be_adapter *adapter = netdev_priv(dev); @@ -900,8 +880,11 @@ static void be_post_rx_frags(struct be_adapter *adapter) page_info->last_page_user = true; if (posted) { - be_rxq_notify(&adapter->ctrl, rxq->id, posted); atomic_add(posted, &rxq->used); + be_rxq_notify(&adapter->ctrl, rxq->id, posted); + } else if (atomic_read(&rxq->used) == 0) { + /* Let be_worker replenish when memory is available */ + adapter->rx_post_starved = true; } return; @@ -1305,6 +1288,31 @@ int be_poll_tx(struct napi_struct *napi, int budget) return 1; } +static void be_worker(struct work_struct *work) +{ + struct be_adapter *adapter = + container_of(work, struct be_adapter, work.work); + int status; + + /* Check link */ + be_link_status_update(adapter); + + /* Get Stats */ + status = be_cmd_get_stats(&adapter->ctrl, &adapter->stats.cmd); + if (!status) + netdev_stats_update(adapter); + + /* Set EQ delay */ + be_rx_eqd_update(adapter); + + if (adapter->rx_post_starved) { + adapter->rx_post_starved = false; + be_post_rx_frags(adapter); + } + + schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); +} + static void be_msix_enable(struct be_adapter *adapter) { int i, status; -- GitLab From 1ab1ab7543de53c945ea24140409ef67ed173eb4 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Thu, 19 Mar 2009 23:56:46 -0700 Subject: [PATCH 3752/4982] be2net: fix to restore vlan ids into BE2 during a IF DOWN->UP cycle This is a patch to reconfigure vlan-ids during an i/f down/up cycle Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 80fe1e055d9..0ecaffb70e5 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -473,7 +473,7 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu) * program them in BE. If more than BE_NUM_VLANS_SUPPORTED are configured, * set the BE in promiscuous VLAN mode. */ -static void be_vids_config(struct net_device *netdev) +static void be_vid_config(struct net_device *netdev) { struct be_adapter *adapter = netdev_priv(netdev); u16 vtag[BE_NUM_VLANS_SUPPORTED]; @@ -516,7 +516,7 @@ static void be_vlan_add_vid(struct net_device *netdev, u16 vid) adapter->num_vlans++; adapter->vlan_tag[vid] = 1; - be_vids_config(netdev); + be_vid_config(netdev); } static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) @@ -527,7 +527,7 @@ static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) adapter->vlan_tag[vid] = 0; vlan_group_set_device(adapter->vlan_grp, vid, NULL); - be_vids_config(netdev); + be_vid_config(netdev); } static void be_set_multicast_filter(struct net_device *netdev) @@ -1430,6 +1430,8 @@ static int be_open(struct net_device *netdev) if (status != 0) goto do_none; + be_vid_config(netdev); + status = be_cmd_set_flow_control(ctrl, true, true); if (status != 0) goto if_destroy; @@ -1864,8 +1866,6 @@ static int be_resume(struct pci_dev *pdev) pci_set_power_state(pdev, 0); pci_restore_state(pdev); - be_vids_config(netdev); - if (netif_running(netdev)) { rtnl_lock(); be_open(netdev); -- GitLab From 5ed0102fbf36f58091089907213b4bd191ca2e0c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 19 Mar 2009 23:58:01 -0700 Subject: [PATCH 3753/4982] sungem: missing net_device_ops Sungem driver only got partially converted to net_device_ops. Since this could cause bugs, please push this to 2.6.29 Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sungem.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 0fcb7503363..c9c7650826c 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -2998,8 +2998,11 @@ static const struct net_device_ops gem_netdev_ops = { .ndo_do_ioctl = gem_ioctl, .ndo_tx_timeout = gem_tx_timeout, .ndo_change_mtu = gem_change_mtu, - .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = gem_set_mac_address, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = gem_poll_controller, +#endif }; static int __devinit gem_init_one(struct pci_dev *pdev, @@ -3161,10 +3164,6 @@ static int __devinit gem_init_one(struct pci_dev *pdev, dev->watchdog_timeo = 5 * HZ; dev->irq = pdev->irq; dev->dma = 0; - dev->set_mac_address = gem_set_mac_address; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = gem_poll_controller; -#endif /* Set that now, in case PM kicks in now */ pci_set_drvdata(pdev, dev); -- GitLab From 785b6f977a89aaabc3dd3e3bfc87f36015cb8050 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Thu, 19 Mar 2009 00:24:44 +0000 Subject: [PATCH 3754/4982] smsc911x: define status word positions as constants The vast majority of bit constants in this driver are defined in the header file, but TX and RX status word bits are not. This patch (which should make no functional change) defines these, to make the driver slightly more readable. Signed-off-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/smsc911x.c | 18 ++++++++---------- drivers/net/smsc911x.h | 7 +++++++ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index ad15aab2137..0232292bd17 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -895,22 +895,22 @@ static void smsc911x_tx_update_txcounters(struct net_device *dev) SMSC_WARNING(HW, "Packet tag reserved bit is high"); } else { - if (unlikely(tx_stat & 0x00008000)) { + if (unlikely(tx_stat & TX_STS_ES_)) { dev->stats.tx_errors++; } else { dev->stats.tx_packets++; dev->stats.tx_bytes += (tx_stat >> 16); } - if (unlikely(tx_stat & 0x00000100)) { + if (unlikely(tx_stat & TX_STS_EXCESS_COL_)) { dev->stats.collisions += 16; dev->stats.tx_aborted_errors += 1; } else { dev->stats.collisions += ((tx_stat >> 3) & 0xF); } - if (unlikely(tx_stat & 0x00000800)) + if (unlikely(tx_stat & TX_STS_LOST_CARRIER_)) dev->stats.tx_carrier_errors += 1; - if (unlikely(tx_stat & 0x00000200)) { + if (unlikely(tx_stat & TX_STS_LATE_COL_)) { dev->stats.collisions++; dev->stats.tx_aborted_errors++; } @@ -924,19 +924,17 @@ smsc911x_rx_counterrors(struct net_device *dev, unsigned int rxstat) { int crc_err = 0; - if (unlikely(rxstat & 0x00008000)) { + if (unlikely(rxstat & RX_STS_ES_)) { dev->stats.rx_errors++; - if (unlikely(rxstat & 0x00000002)) { + if (unlikely(rxstat & RX_STS_CRC_ERR_)) { dev->stats.rx_crc_errors++; crc_err = 1; } } if (likely(!crc_err)) { - if (unlikely((rxstat & 0x00001020) == 0x00001020)) { - /* Frame type indicates length, - * and length error is set */ + if (unlikely((rxstat & RX_STS_FRAME_TYPE_) && + (rxstat & RX_STS_LENGTH_ERR_))) dev->stats.rx_length_errors++; - } if (rxstat & RX_STS_MCAST_) dev->stats.multicast++; } diff --git a/drivers/net/smsc911x.h b/drivers/net/smsc911x.h index 2b76654bb95..b5716bd8a59 100644 --- a/drivers/net/smsc911x.h +++ b/drivers/net/smsc911x.h @@ -81,12 +81,19 @@ #define RX_STATUS_FIFO 0x40 #define RX_STS_ES_ 0x00008000 +#define RX_STS_LENGTH_ERR_ 0x00001000 #define RX_STS_MCAST_ 0x00000400 +#define RX_STS_FRAME_TYPE_ 0x00000020 +#define RX_STS_CRC_ERR_ 0x00000002 #define RX_STATUS_FIFO_PEEK 0x44 #define TX_STATUS_FIFO 0x48 #define TX_STS_ES_ 0x00008000 +#define TX_STS_LOST_CARRIER_ 0x00000800 +#define TX_STS_NO_CARRIER_ 0x00000400 +#define TX_STS_LATE_COL_ 0x00000200 +#define TX_STS_EXCESS_COL_ 0x00000100 #define TX_STATUS_FIFO_PEEK 0x4C -- GitLab From 63a2ebb079d72f10ea7b89b85c2cd4ecc60edc61 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Thu, 19 Mar 2009 00:24:45 +0000 Subject: [PATCH 3755/4982] smsc911x: replace print_mac with %pM Signed-off-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/smsc911x.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 0232292bd17..7df8f6e4f86 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1910,7 +1910,6 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) unsigned int intcfg = 0; int res_size, irq_flags; int retval; - DECLARE_MAC_BUF(mac); pr_info("%s: Driver version %s.\n", SMSC_CHIPNAME, SMSC_DRV_VERSION); @@ -2045,8 +2044,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) spin_unlock_irq(&pdata->mac_lock); - dev_info(&dev->dev, "MAC Address: %s\n", - print_mac(mac, dev->dev_addr)); + dev_info(&dev->dev, "MAC Address: %pM\n", dev->dev_addr); return 0; -- GitLab From 225ddf498cc99ead1d11ed1aaf1887e24e1007fa Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Thu, 19 Mar 2009 00:24:46 +0000 Subject: [PATCH 3756/4982] smsc911x: allow setting of mac address This patch replaces the generic eth_mac_addr function with one that also updates the hardware mac address registers. It also renames the existing smsc911x_set_mac_address function to smsc911x_hw_set_mac_address for clarity. Newer LAN911x and all LAN921x devices also support changing the mac address while the device is running, which is useful for some bonding modes. Signed-off-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/smsc911x.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 7df8f6e4f86..d61514698bb 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1119,7 +1119,7 @@ static int smsc911x_soft_reset(struct smsc911x_data *pdata) /* Sets the device MAC address to dev_addr, called with mac_lock held */ static void -smsc911x_set_mac_address(struct smsc911x_data *pdata, u8 dev_addr[6]) +smsc911x_set_hw_mac_address(struct smsc911x_data *pdata, u8 dev_addr[6]) { u32 mac_high16 = (dev_addr[5] << 8) | dev_addr[4]; u32 mac_low32 = (dev_addr[3] << 24) | (dev_addr[2] << 16) | @@ -1174,7 +1174,7 @@ static int smsc911x_open(struct net_device *dev) /* The soft reset above cleared the device's MAC address, * restore it from local copy (set in probe) */ spin_lock_irq(&pdata->mac_lock); - smsc911x_set_mac_address(pdata, dev->dev_addr); + smsc911x_set_hw_mac_address(pdata, dev->dev_addr); spin_unlock_irq(&pdata->mac_lock); /* Initialise irqs, but leave all sources disabled */ @@ -1504,6 +1504,31 @@ static void smsc911x_poll_controller(struct net_device *dev) } #endif /* CONFIG_NET_POLL_CONTROLLER */ +static int smsc911x_set_mac_address(struct net_device *dev, void *p) +{ + struct smsc911x_data *pdata = netdev_priv(dev); + struct sockaddr *addr = p; + + /* On older hardware revisions we cannot change the mac address + * registers while receiving data. Newer devices can safely change + * this at any time. */ + if (pdata->generation <= 1 && netif_running(dev)) + return -EBUSY; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); + + spin_lock_irq(&pdata->mac_lock); + smsc911x_set_hw_mac_address(pdata, dev->dev_addr); + spin_unlock_irq(&pdata->mac_lock); + + dev_info(&dev->dev, "MAC Address: %pM\n", dev->dev_addr); + + return 0; +} + /* Standard ioctls for mii-tool */ static int smsc911x_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { @@ -1734,7 +1759,7 @@ static const struct net_device_ops smsc911x_netdev_ops = { .ndo_set_multicast_list = smsc911x_set_multicast_list, .ndo_do_ioctl = smsc911x_do_ioctl, .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, + .ndo_set_mac_address = smsc911x_set_mac_address, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = smsc911x_poll_controller, #endif @@ -2022,7 +2047,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) /* Check if mac address has been specified when bringing interface up */ if (is_valid_ether_addr(dev->dev_addr)) { - smsc911x_set_mac_address(pdata, dev->dev_addr); + smsc911x_set_hw_mac_address(pdata, dev->dev_addr); SMSC_TRACE(PROBE, "MAC Address is specified by configuration"); } else { /* Try reading mac address from device. if EEPROM is present @@ -2036,7 +2061,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) } else { /* eeprom values are invalid, generate random MAC */ random_ether_addr(dev->dev_addr); - smsc911x_set_mac_address(pdata, dev->dev_addr); + smsc911x_set_hw_mac_address(pdata, dev->dev_addr); SMSC_TRACE(PROBE, "MAC Address is set to random_ether_addr"); } -- GitLab From 8fd17f2e6c973efdb2e3fcb5026d204441dd01fd Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 20 Mar 2009 00:51:22 -0700 Subject: [PATCH 3757/4982] sunvnet: Convert to net_device_ops. Signed-off-by: David S. Miller --- drivers/net/sunvnet.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c index 611230fef2b..a82fb2aca4c 100644 --- a/drivers/net/sunvnet.c +++ b/drivers/net/sunvnet.c @@ -1012,6 +1012,16 @@ err_out: static LIST_HEAD(vnet_list); static DEFINE_MUTEX(vnet_list_mutex); +static const struct net_device_ops vnet_ops = { + .ndo_open = vnet_open, + .ndo_stop = vnet_close, + .ndo_set_multicast_list = vnet_set_rx_mode, + .ndo_set_mac_address = vnet_set_mac_addr, + .ndo_tx_timeout = vnet_tx_timeout, + .ndo_change_mtu = vnet_change_mtu, + .ndo_start_xmit = vnet_start_xmit, +}; + static struct vnet * __devinit vnet_new(const u64 *local_mac) { struct net_device *dev; @@ -1040,15 +1050,9 @@ static struct vnet * __devinit vnet_new(const u64 *local_mac) INIT_LIST_HEAD(&vp->list); vp->local_mac = *local_mac; - dev->open = vnet_open; - dev->stop = vnet_close; - dev->set_multicast_list = vnet_set_rx_mode; - dev->set_mac_address = vnet_set_mac_addr; - dev->tx_timeout = vnet_tx_timeout; + dev->netdev_ops = &vnet_ops; dev->ethtool_ops = &vnet_ethtool_ops; dev->watchdog_timeo = VNET_TX_TIMEOUT; - dev->change_mtu = vnet_change_mtu; - dev->hard_start_xmit = vnet_start_xmit; err = register_netdev(dev); if (err) { -- GitLab From cd7a3b75ba7af7d14a264fe3d414fcc74307f748 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Fri, 20 Mar 2009 01:14:53 -0700 Subject: [PATCH 3758/4982] smsc9420: fix big endian rx checksum offload The cpu_to_le16 here looks suspicious to me, I don't think we need it because put_unaligned_le16 also does this. I don't currently have any big endian hardware with a PCI bus available to test on, so I haven't been able to verify this. Signed-off-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/smsc9420.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c index 17560dbcc7a..5959ae86e57 100644 --- a/drivers/net/smsc9420.c +++ b/drivers/net/smsc9420.c @@ -807,7 +807,7 @@ static void smsc9420_rx_handoff(struct smsc9420_pdata *pd, const int index, if (pd->rx_csum) { u16 hw_csum = get_unaligned_le16(skb_tail_pointer(skb) + NET_IP_ALIGN + packet_length + 4); - put_unaligned_le16(cpu_to_le16(hw_csum), &skb->csum); + put_unaligned_le16(hw_csum, &skb->csum); skb->ip_summed = CHECKSUM_COMPLETE; } -- GitLab From 8c81c9c315b7e7e240906fab0e8dde1595101bd2 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Mar 2009 01:12:27 +0000 Subject: [PATCH 3759/4982] e1000e: add support for 82583 device id Add device ID and related support for 82583 mac. Signed-off-by: Alexander Duyck Acked-by: Radheka Godse Acked-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/82571.c | 129 +++++++++++++++++++++++++++++------ drivers/net/e1000e/e1000.h | 2 + drivers/net/e1000e/ethtool.c | 1 + drivers/net/e1000e/hw.h | 2 + drivers/net/e1000e/netdev.c | 4 +- 5 files changed, 116 insertions(+), 22 deletions(-) diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index 51f8e84bd4a..6c01a2072c8 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -40,6 +40,7 @@ * 82573E Gigabit Ethernet Controller (Copper) * 82573L Gigabit Ethernet Controller * 82574L Gigabit Network Connection + * 82583V Gigabit Network Connection */ #include @@ -100,6 +101,7 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw) phy->type = e1000_phy_m88; break; case e1000_82574: + case e1000_82583: phy->type = e1000_phy_bm; break; default: @@ -122,6 +124,7 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw) return -E1000_ERR_PHY; break; case e1000_82574: + case e1000_82583: if (phy->id != BME1000_E_PHY_ID_R2) return -E1000_ERR_PHY; break; @@ -165,6 +168,7 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw) switch (hw->mac.type) { case e1000_82573: case e1000_82574: + case e1000_82583: if (((eecd >> 15) & 0x3) == 0x3) { nvm->type = e1000_nvm_flash_hw; nvm->word_size = 2048; @@ -262,6 +266,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter) switch (hw->mac.type) { case e1000_82574: + case e1000_82583: func->check_mng_mode = e1000_check_mng_mode_82574; func->led_on = e1000_led_on_82574; break; @@ -375,6 +380,7 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw) return e1000e_get_phy_id(hw); break; case e1000_82574: + case e1000_82583: ret_val = e1e_rphy(hw, PHY_ID1, &phy_id); if (ret_val) return ret_val; @@ -464,8 +470,15 @@ static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw) if (ret_val) return ret_val; - if (hw->mac.type != e1000_82573 && hw->mac.type != e1000_82574) + switch (hw->mac.type) { + case e1000_82573: + case e1000_82574: + case e1000_82583: + break; + default: ret_val = e1000e_acquire_nvm(hw); + break; + } if (ret_val) e1000_put_hw_semaphore_82571(hw); @@ -505,6 +518,7 @@ static s32 e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset, u16 words, switch (hw->mac.type) { case e1000_82573: case e1000_82574: + case e1000_82583: ret_val = e1000_write_nvm_eewr_82571(hw, offset, words, data); break; case e1000_82571: @@ -779,7 +793,10 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) * Must acquire the MDIO ownership before MAC reset. * Ownership defaults to firmware after a reset. */ - if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) { + switch (hw->mac.type) { + case e1000_82573: + case e1000_82574: + case e1000_82583: extcnf_ctrl = er32(EXTCNF_CTRL); extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; @@ -795,6 +812,9 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) msleep(2); i++; } while (i < MDIO_OWNERSHIP_TIMEOUT); + break; + default: + break; } ctrl = er32(CTRL); @@ -820,8 +840,16 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) * Need to wait for Phy configuration completion before accessing * NVM and Phy. */ - if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) + + switch (hw->mac.type) { + case e1000_82573: + case e1000_82574: + case e1000_82583: msleep(25); + break; + default: + break; + } /* Clear any pending interrupt events. */ ew32(IMC, 0xffffffff); @@ -891,17 +919,22 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw) ew32(TXDCTL(0), reg_data); /* ...for both queues. */ - if (mac->type != e1000_82573 && mac->type != e1000_82574) { + switch (mac->type) { + case e1000_82573: + case e1000_82574: + case e1000_82583: + e1000e_enable_tx_pkt_filtering(hw); + reg_data = er32(GCR); + reg_data |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX; + ew32(GCR, reg_data); + break; + default: reg_data = er32(TXDCTL(1)); reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC; ew32(TXDCTL(1), reg_data); - } else { - e1000e_enable_tx_pkt_filtering(hw); - reg_data = er32(GCR); - reg_data |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX; - ew32(GCR, reg_data); + break; } /* @@ -966,18 +999,30 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) } /* Device Control */ - if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) { + switch (hw->mac.type) { + case e1000_82573: + case e1000_82574: + case e1000_82583: reg = er32(CTRL); reg &= ~(1 << 29); ew32(CTRL, reg); + break; + default: + break; } /* Extended Device Control */ - if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) { + switch (hw->mac.type) { + case e1000_82573: + case e1000_82574: + case e1000_82583: reg = er32(CTRL_EXT); reg &= ~(1 << 23); reg |= (1 << 22); ew32(CTRL_EXT, reg); + break; + default: + break; } if (hw->mac.type == e1000_82571) { @@ -999,7 +1044,9 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) /* PCI-Ex Control Registers */ - if (hw->mac.type == e1000_82574) { + switch (hw->mac.type) { + case e1000_82574: + case e1000_82583: reg = er32(GCR); reg |= (1 << 22); ew32(GCR, reg); @@ -1007,6 +1054,9 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) reg = er32(GCR2); reg |= 1; ew32(GCR2, reg); + break; + default: + break; } return; @@ -1026,7 +1076,10 @@ void e1000e_clear_vfta(struct e1000_hw *hw) u32 vfta_offset = 0; u32 vfta_bit_in_reg = 0; - if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) { + switch (hw->mac.type) { + case e1000_82573: + case e1000_82574: + case e1000_82583: if (hw->mng_cookie.vlan_id != 0) { /* * The VFTA is a 4096b bit-field, each identifying @@ -1041,6 +1094,9 @@ void e1000e_clear_vfta(struct e1000_hw *hw) vfta_bit_in_reg = 1 << (hw->mng_cookie.vlan_id & E1000_VFTA_ENTRY_BIT_SHIFT_MASK); } + break; + default: + break; } for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { /* @@ -1139,9 +1195,16 @@ static s32 e1000_setup_link_82571(struct e1000_hw *hw) * the default flow control setting, so we explicitly * set it to full. */ - if ((hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) && - hw->fc.requested_mode == e1000_fc_default) - hw->fc.requested_mode = e1000_fc_full; + switch (hw->mac.type) { + case e1000_82573: + case e1000_82574: + case e1000_82583: + if (hw->fc.requested_mode == e1000_fc_default) + hw->fc.requested_mode = e1000_fc_full; + break; + default: + break; + } return e1000e_setup_link(hw); } @@ -1362,11 +1425,19 @@ static s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data) return ret_val; } - if ((hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) && - *data == ID_LED_RESERVED_F746) - *data = ID_LED_DEFAULT_82573; - else if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) - *data = ID_LED_DEFAULT; + switch (hw->mac.type) { + case e1000_82573: + case e1000_82574: + case e1000_82583: + if (*data == ID_LED_RESERVED_F746) + *data = ID_LED_DEFAULT_82573; + break; + default: + if (*data == ID_LED_RESERVED_0000 || + *data == ID_LED_RESERVED_FFFF) + *data = ID_LED_DEFAULT; + break; + } return 0; } @@ -1659,3 +1730,19 @@ struct e1000_info e1000_82574_info = { .nvm_ops = &e82571_nvm_ops, }; +struct e1000_info e1000_82583_info = { + .mac = e1000_82583, + .flags = FLAG_HAS_HW_VLAN_FILTER + | FLAG_HAS_WOL + | FLAG_APME_IN_CTRL3 + | FLAG_RX_CSUM_ENABLED + | FLAG_HAS_SMART_POWER_DOWN + | FLAG_HAS_AMT + | FLAG_HAS_CTRLEXT_ON_LOAD, + .pba = 20, + .get_variants = e1000_get_variants_82571, + .mac_ops = &e82571_mac_ops, + .phy_ops = &e82_phy_ops_bm, + .nvm_ops = &e82571_nvm_ops, +}; + diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index 28bf9a51346..f37360aa12a 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -101,6 +101,7 @@ enum e1000_boards { board_82572, board_82573, board_82574, + board_82583, board_80003es2lan, board_ich8lan, board_ich9lan, @@ -399,6 +400,7 @@ extern struct e1000_info e1000_82571_info; extern struct e1000_info e1000_82572_info; extern struct e1000_info e1000_82573_info; extern struct e1000_info e1000_82574_info; +extern struct e1000_info e1000_82583_info; extern struct e1000_info e1000_ich8_info; extern struct e1000_info e1000_ich9_info; extern struct e1000_info e1000_ich10_info; diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index 2557aeef65e..4d25ede8836 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -790,6 +790,7 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) break; case e1000_82573: case e1000_82574: + case e1000_82583: case e1000_ich8lan: case e1000_ich9lan: case e1000_ich10lan: diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index 5cb428c2811..11a2f203a01 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -339,6 +339,7 @@ enum e1e_registers { #define E1000_DEV_ID_82573E_IAMT 0x108C #define E1000_DEV_ID_82573L 0x109A #define E1000_DEV_ID_82574L 0x10D3 +#define E1000_DEV_ID_82583V 0x150C #define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096 #define E1000_DEV_ID_80003ES2LAN_SERDES_DPT 0x1098 @@ -376,6 +377,7 @@ enum e1000_mac_type { e1000_82572, e1000_82573, e1000_82574, + e1000_82583, e1000_80003es2lan, e1000_ich8lan, e1000_ich9lan, diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index e74eb3c606e..402d2dd7d68 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -57,6 +57,7 @@ static const struct e1000_info *e1000_info_tbl[] = { [board_82572] = &e1000_82572_info, [board_82573] = &e1000_82573_info, [board_82574] = &e1000_82574_info, + [board_82583] = &e1000_82583_info, [board_80003es2lan] = &e1000_es2_info, [board_ich8lan] = &e1000_ich8_info, [board_ich9lan] = &e1000_ich9_info, @@ -3312,7 +3313,7 @@ void e1000e_update_stats(struct e1000_adapter *adapter) adapter->stats.algnerrc += er32(ALGNERRC); adapter->stats.rxerrc += er32(RXERRC); - if (hw->mac.type != e1000_82574) + if ((hw->mac.type != e1000_82574) && (hw->mac.type != e1000_82583)) adapter->stats.tncrs += er32(TNCRS); adapter->stats.cexterr += er32(CEXTERR); adapter->stats.tsctc += er32(TSCTC); @@ -5134,6 +5135,7 @@ static struct pci_device_id e1000_pci_tbl[] = { { PCI_VDEVICE(INTEL, E1000_DEV_ID_82573L), board_82573 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82574L), board_82574 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82583V), board_82583 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_COPPER_DPT), board_80003es2lan }, -- GitLab From 1b7719c4559dc1522065d4cfd033f8bb8f969159 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Mar 2009 01:12:50 +0000 Subject: [PATCH 3760/4982] e1000e: fix dma error handling issues There were a few issues I noticed in e1000e. These include a double free of the skb if mapping fails, and the fact that context descriptors appear to be left in the descriptor ring after the failure. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/netdev.c | 76 ++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 44 deletions(-) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 402d2dd7d68..da876d59a9c 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -574,6 +574,7 @@ static void e1000_put_txbuf(struct e1000_adapter *adapter, dev_kfree_skb_any(buffer_info->skb); buffer_info->skb = NULL; } + buffer_info->time_stamp = 0; } static void e1000_print_tx_hang(struct e1000_adapter *adapter) @@ -678,17 +679,10 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) } if (adapter->detect_tx_hung) { - /* - * Detect a transmit hang in hardware, this serializes the - * check with the clearing of time_stamp and movement of i - */ + /* Detect a transmit hang in hardware, this serializes the + * check with the clearing of time_stamp and movement of i */ adapter->detect_tx_hung = 0; - /* - * read barrier to make sure that the ->dma member and time - * stamp are updated fully - */ - smp_rmb(); - if (tx_ring->buffer_info[eop].dma && + if (tx_ring->buffer_info[eop].time_stamp && time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + (adapter->tx_timeout_factor * HZ)) && !(er32(STATUS) & E1000_STATUS_TXOFF)) { @@ -3824,39 +3818,41 @@ static int e1000_tx_map(struct e1000_adapter *adapter, unsigned int mss) { struct e1000_ring *tx_ring = adapter->tx_ring; + struct e1000_buffer *buffer_info; unsigned int len = skb_headlen(skb); unsigned int offset, size, count = 0, i; unsigned int f; - dma_addr_t map; + dma_addr_t *map; i = tx_ring->next_to_use; if (skb_dma_map(&adapter->pdev->dev, skb, DMA_TO_DEVICE)) { dev_err(&adapter->pdev->dev, "TX DMA map failed\n"); adapter->tx_dma_failed++; - dev_kfree_skb(skb); - return -2; + return 0; } - map = skb_shinfo(skb)->dma_maps[0]; + map = skb_shinfo(skb)->dma_maps; offset = 0; while (len) { - struct e1000_buffer *buffer_info = &tx_ring->buffer_info[i]; + buffer_info = &tx_ring->buffer_info[i]; size = min(len, max_per_txd); buffer_info->length = size; - /* set time_stamp *before* dma to help avoid a possible race */ buffer_info->time_stamp = jiffies; - buffer_info->dma = map + offset; buffer_info->next_to_watch = i; + buffer_info->dma = map[0] + offset; + count++; len -= size; offset += size; - count++; - i++; - if (i == tx_ring->count) - i = 0; + + if (len) { + i++; + if (i == tx_ring->count) + i = 0; + } } for (f = 0; f < nr_frags; f++) { @@ -3864,37 +3860,29 @@ static int e1000_tx_map(struct e1000_adapter *adapter, frag = &skb_shinfo(skb)->frags[f]; len = frag->size; - map = skb_shinfo(skb)->dma_maps[f + 1]; offset = 0; while (len) { - struct e1000_buffer *buffer_info; + i++; + if (i == tx_ring->count) + i = 0; + buffer_info = &tx_ring->buffer_info[i]; size = min(len, max_per_txd); buffer_info->length = size; buffer_info->time_stamp = jiffies; - buffer_info->dma = map + offset; buffer_info->next_to_watch = i; + buffer_info->dma = map[f + 1] + offset; len -= size; offset += size; count++; - - i++; - if (i == tx_ring->count) - i = 0; } } - if (i == 0) - i = tx_ring->count - 1; - else - i--; - tx_ring->buffer_info[i].skb = skb; tx_ring->buffer_info[first].next_to_watch = i; - smp_wmb(); return count; } @@ -4145,20 +4133,20 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if (skb->protocol == htons(ETH_P_IP)) tx_flags |= E1000_TX_FLAGS_IPV4; + /* if count is 0 then mapping error has occured */ count = e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss); - if (count < 0) { - /* handle pci_map_single() error in e1000_tx_map */ + if (count) { + e1000_tx_queue(adapter, tx_flags, count); + netdev->trans_start = jiffies; + /* Make sure there is space in the ring for the next send. */ + e1000_maybe_stop_tx(netdev, MAX_SKB_FRAGS + 2); + + } else { dev_kfree_skb_any(skb); - return NETDEV_TX_OK; + tx_ring->buffer_info[first].time_stamp = 0; + tx_ring->next_to_use = first; } - e1000_tx_queue(adapter, tx_flags, count); - - netdev->trans_start = jiffies; - - /* Make sure there is space in the ring for the next send. */ - e1000_maybe_stop_tx(netdev, MAX_SKB_FRAGS + 2); - return NETDEV_TX_OK; } -- GitLab From 5f66f208064f083aab5e55935d0575892e033b59 Mon Sep 17 00:00:00 2001 From: Arthur Jones Date: Thu, 19 Mar 2009 01:13:08 +0000 Subject: [PATCH 3761/4982] e1000e: allow tx of pre-formatted vlan tagged packets As with igb, when the e1000e driver is fed 802.1q packets with hardware checksum on, it chokes with an error of the form: checksum_partial proto=81! As the logic there was not smart enough to look into the vlan header to pick out the encapsulated protocol. There are times when we'd like to send these packets out without having to configure a vlan on the interface. Here we check for the vlan tag and allow the packet to go out wiht the correct hardware checksum. Thanks to Kand Ly for discovering the issue and the coming up with a solution. This patch is based upon his work. Fixups from Stephen Hemminger and Alexander Duyck Signed-off-by: Arthur Jones Signed-off-by: Jeff Kirsher CC: Stephen Hemminger CC: Alexander Duyck Signed-off-by: David S. Miller --- drivers/net/e1000e/netdev.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index da876d59a9c..d092eafde9b 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -3764,10 +3764,16 @@ static bool e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb) unsigned int i; u8 css; u32 cmd_len = E1000_TXD_CMD_DEXT; + __be16 protocol; if (skb->ip_summed != CHECKSUM_PARTIAL) return 0; + if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) + protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto; + else + protocol = skb->protocol; + switch (skb->protocol) { case cpu_to_be16(ETH_P_IP): if (ip_hdr(skb)->protocol == IPPROTO_TCP) @@ -3780,7 +3786,8 @@ static bool e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb) break; default: if (unlikely(net_ratelimit())) - e_warn("checksum_partial proto=%x!\n", skb->protocol); + e_warn("checksum_partial proto=%x!\n", + be16_to_cpu(protocol)); break; } -- GitLab From fe52eeb82b746de441ed27c54ace940efe86bc9a Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 19 Mar 2009 01:15:21 +0000 Subject: [PATCH 3762/4982] ixgb: refactor tx path to use skb_dma_map/unmap This code updates ixgb so that it can use the skb_dma_map/unmap functions to map the buffers. In addition it also updates the tx hang logic to use time_stamp instead of dma to determine if it has detected a tx hang. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgb/ixgb_main.c | 70 ++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index e2ef16b2970..4b0ea66d7a4 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -887,19 +887,13 @@ static void ixgb_unmap_and_free_tx_resource(struct ixgb_adapter *adapter, struct ixgb_buffer *buffer_info) { - struct pci_dev *pdev = adapter->pdev; - - if (buffer_info->dma) - pci_unmap_page(pdev, buffer_info->dma, buffer_info->length, - PCI_DMA_TODEVICE); - - /* okay to call kfree_skb here instead of kfree_skb_any because - * this is never called in interrupt context */ - if (buffer_info->skb) - dev_kfree_skb(buffer_info->skb); - - buffer_info->skb = NULL; buffer_info->dma = 0; + if (buffer_info->skb) { + skb_dma_unmap(&adapter->pdev->dev, buffer_info->skb, + DMA_TO_DEVICE); + dev_kfree_skb_any(buffer_info->skb); + buffer_info->skb = NULL; + } buffer_info->time_stamp = 0; /* these fields must always be initialized in tx * buffer_info->length = 0; @@ -1275,17 +1269,23 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb, { struct ixgb_desc_ring *tx_ring = &adapter->tx_ring; struct ixgb_buffer *buffer_info; - int len = skb->len; + int len = skb_headlen(skb); unsigned int offset = 0, size, count = 0, i; unsigned int mss = skb_shinfo(skb)->gso_size; unsigned int nr_frags = skb_shinfo(skb)->nr_frags; unsigned int f; - - len -= skb->data_len; + dma_addr_t *map; i = tx_ring->next_to_use; + if (skb_dma_map(&adapter->pdev->dev, skb, DMA_TO_DEVICE)) { + dev_err(&adapter->pdev->dev, "TX DMA map failed\n"); + return 0; + } + + map = skb_shinfo(skb)->dma_maps; + while (len) { buffer_info = &tx_ring->buffer_info[i]; size = min(len, IXGB_MAX_DATA_PER_TXD); @@ -1297,7 +1297,7 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb, buffer_info->length = size; WARN_ON(buffer_info->dma != 0); buffer_info->time_stamp = jiffies; - buffer_info->dma = + buffer_info->dma = map[0] + offset; pci_map_single(adapter->pdev, skb->data + offset, size, @@ -1307,7 +1307,11 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb, len -= size; offset += size; count++; - if (++i == tx_ring->count) i = 0; + if (len) { + i++; + if (i == tx_ring->count) + i = 0; + } } for (f = 0; f < nr_frags; f++) { @@ -1318,6 +1322,10 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb, offset = 0; while (len) { + i++; + if (i == tx_ring->count) + i = 0; + buffer_info = &tx_ring->buffer_info[i]; size = min(len, IXGB_MAX_DATA_PER_TXD); @@ -1329,21 +1337,14 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb, buffer_info->length = size; buffer_info->time_stamp = jiffies; - buffer_info->dma = - pci_map_page(adapter->pdev, - frag->page, - frag->page_offset + offset, - size, - PCI_DMA_TODEVICE); + buffer_info->dma = map[f + 1] + offset; buffer_info->next_to_watch = 0; len -= size; offset += size; count++; - if (++i == tx_ring->count) i = 0; } } - i = (i == 0) ? tx_ring->count - 1 : i - 1; tx_ring->buffer_info[i].skb = skb; tx_ring->buffer_info[first].next_to_watch = i; @@ -1445,6 +1446,7 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev) unsigned int first; unsigned int tx_flags = 0; int vlan_id = 0; + int count = 0; int tso; if (test_bit(__IXGB_DOWN, &adapter->flags)) { @@ -1479,13 +1481,19 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev) else if (ixgb_tx_csum(adapter, skb)) tx_flags |= IXGB_TX_FLAGS_CSUM; - ixgb_tx_queue(adapter, ixgb_tx_map(adapter, skb, first), vlan_id, - tx_flags); + count = ixgb_tx_map(adapter, skb, first); - netdev->trans_start = jiffies; + if (count) { + ixgb_tx_queue(adapter, count, vlan_id, tx_flags); + netdev->trans_start = jiffies; + /* Make sure there is space in the ring for the next send. */ + ixgb_maybe_stop_tx(netdev, &adapter->tx_ring, DESC_NEEDED); - /* Make sure there is space in the ring for the next send. */ - ixgb_maybe_stop_tx(netdev, &adapter->tx_ring, DESC_NEEDED); + } else { + dev_kfree_skb_any(skb); + adapter->tx_ring.buffer_info[first].time_stamp = 0; + adapter->tx_ring.next_to_use = first; + } return NETDEV_TX_OK; } @@ -1818,7 +1826,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter) /* detect a transmit hang in hardware, this serializes the * check with the clearing of time_stamp and movement of i */ adapter->detect_tx_hung = false; - if (tx_ring->buffer_info[eop].dma && + if (tx_ring->buffer_info[eop].time_stamp && time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + HZ) && !(IXGB_READ_REG(&adapter->hw, STATUS) & IXGB_STATUS_TXOFF)) { -- GitLab From 03cfa2054846a9902f0c10bea4680447050f03fa Mon Sep 17 00:00:00 2001 From: PJ Waskiewicz Date: Thu, 19 Mar 2009 01:23:29 +0000 Subject: [PATCH 3763/4982] ixgbe: Fix PCI bus reporting on driver load for 82598 after 82599 merge 82598's PCI bus reporting on driver load was broken after 82599 merged. This results in incorrect reporting, and an erroneous warning message that the 82598 is in a PCIe slot that isn't fast enough to run 10GbE. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_82598.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 623737fb719..ed265a7a898 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -79,6 +79,9 @@ static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw) s32 ret_val = 0; u16 list_offset, data_offset; + /* Set the bus information prior to PHY identification */ + mac->ops.get_bus_info(hw); + /* Call PHY identify routine to get the phy type */ ixgbe_identify_phy_generic(hw); -- GitLab From e63d9762929d9b86ac87cfb8047e7f7b1f2ed2dd Mon Sep 17 00:00:00 2001 From: PJ Waskiewicz Date: Thu, 19 Mar 2009 01:23:46 +0000 Subject: [PATCH 3764/4982] ixgbe: Correctly report Wake On LAN for 82599 KX4 devices ethtool isn't reporting the support level of WoL for 82599 KX4 devices. While the device does support WoL, ethtool was never updated to properly report the level of support, nor will it allow ethtool to modify the type of packets to listen for. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_ethtool.c | 41 ++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 3a99781794d..18ecba7f6ec 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -909,12 +909,50 @@ static void ixgbe_get_strings(struct net_device *netdev, u32 stringset, static void ixgbe_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { - wol->supported = 0; + struct ixgbe_adapter *adapter = netdev_priv(netdev); + + wol->supported = WAKE_UCAST | WAKE_MCAST | + WAKE_BCAST | WAKE_MAGIC; wol->wolopts = 0; + if (!device_can_wakeup(&adapter->pdev->dev)) + return; + + if (adapter->wol & IXGBE_WUFC_EX) + wol->wolopts |= WAKE_UCAST; + if (adapter->wol & IXGBE_WUFC_MC) + wol->wolopts |= WAKE_MCAST; + if (adapter->wol & IXGBE_WUFC_BC) + wol->wolopts |= WAKE_BCAST; + if (adapter->wol & IXGBE_WUFC_MAG) + wol->wolopts |= WAKE_MAGIC; + return; } +static int ixgbe_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) +{ + struct ixgbe_adapter *adapter = netdev_priv(netdev); + + if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) + return -EOPNOTSUPP; + + adapter->wol = 0; + + if (wol->wolopts & WAKE_UCAST) + adapter->wol |= IXGBE_WUFC_EX; + if (wol->wolopts & WAKE_MCAST) + adapter->wol |= IXGBE_WUFC_MC; + if (wol->wolopts & WAKE_BCAST) + adapter->wol |= IXGBE_WUFC_BC; + if (wol->wolopts & WAKE_MAGIC) + adapter->wol |= IXGBE_WUFC_MAG; + + device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); + + return 0; +} + static int ixgbe_nway_reset(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); @@ -1031,6 +1069,7 @@ static const struct ethtool_ops ixgbe_ethtool_ops = { .get_regs_len = ixgbe_get_regs_len, .get_regs = ixgbe_get_regs, .get_wol = ixgbe_get_wol, + .set_wol = ixgbe_set_wol, .nway_reset = ixgbe_nway_reset, .get_link = ethtool_op_get_link, .get_eeprom_len = ixgbe_get_eeprom_len, -- GitLab From 22d5a71b50df739abaee83e2fdb191f8aa6b037c Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 19 Mar 2009 01:24:04 +0000 Subject: [PATCH 3765/4982] ixgbe: Fixup the watchdog interrupt scheduling on 82599 The watchdog will schedule an interrupt to help make sure queues are cleaned in the case when an interrupt is missed, most likely due to very high load. On 82599, there are extra interrupt registers to account for the larger number of MSI-X vectors (64 total for 82599 vs. 18 total for 82598). These must be taken into account when performing this operation in the watchdog. Signed-off-by: Jesse Brandeburg Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 113 +++++++++++++++++++++++---------- 1 file changed, 81 insertions(+), 32 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 335119a5687..0956be7c748 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1433,27 +1433,6 @@ static void ixgbe_set_itr(struct ixgbe_adapter *adapter) return; } -/** - * ixgbe_irq_disable - Mask off interrupt generation on the NIC - * @adapter: board private structure - **/ -static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) -{ - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); - if (adapter->hw.mac.type == ixgbe_mac_82599EB) { - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(2), ~0); - } - IXGBE_WRITE_FLUSH(&adapter->hw); - if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { - int i; - for (i = 0; i < adapter->num_msix_vectors; i++) - synchronize_irq(adapter->msix_entries[i].vector); - } else { - synchronize_irq(adapter->pdev->irq); - } -} - /** * ixgbe_irq_enable - Enable default interrupt generation settings * @adapter: board private structure @@ -1596,6 +1575,39 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter) } } +/** + * ixgbe_irq_disable - Mask off interrupt generation on the NIC + * @adapter: board private structure + **/ +static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) +{ + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); + if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(2), ~0); + } + IXGBE_WRITE_FLUSH(&adapter->hw); + if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { + int i; + for (i = 0; i < adapter->num_msix_vectors; i++) + synchronize_irq(adapter->msix_entries[i].vector); + } else { + synchronize_irq(adapter->pdev->irq); + } +} + +static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter) +{ + u32 mask = IXGBE_EIMS_RTX_QUEUE; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask); + if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(1), mask << 16); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(2), + (mask << 16 | mask)); + } + /* skip the flush */ +} + /** * ixgbe_configure_msi_and_legacy - Initialize PIN (INTA...) and MSI interrupts * @@ -2624,7 +2636,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget) if (adapter->itr_setting & 1) ixgbe_set_itr(adapter); if (!test_bit(__IXGBE_DOWN, &adapter->state)) - ixgbe_irq_enable(adapter); + ixgbe_irq_enable_queues(adapter); } return work_done; } @@ -3806,17 +3818,54 @@ static void ixgbe_watchdog(unsigned long data) /* Do the watchdog outside of interrupt context due to the lovely * delays that some of the newer hardware requires */ if (!test_bit(__IXGBE_DOWN, &adapter->state)) { + u64 eics = 0; + int i; + + for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) + eics |= (1 << i); + /* Cause software interrupt to ensure rx rings are cleaned */ - if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { - u32 eics = - (1 << (adapter->num_msix_vectors - NON_Q_VECTORS)) - 1; - IXGBE_WRITE_REG(hw, IXGBE_EICS, eics); - } else { - /* For legacy and MSI interrupts don't set any bits that - * are enabled for EIAM, because this operation would - * set *both* EIMS and EICS for any bit in EIAM */ - IXGBE_WRITE_REG(hw, IXGBE_EICS, - (IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER)); + switch (hw->mac.type) { + case ixgbe_mac_82598EB: + if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { + IXGBE_WRITE_REG(hw, IXGBE_EICS, (u32)eics); + } else { + /* + * for legacy and MSI interrupts don't set any + * bits that are enabled for EIAM, because this + * operation would set *both* EIMS and EICS for + * any bit in EIAM + */ + IXGBE_WRITE_REG(hw, IXGBE_EICS, + (IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER)); + } + break; + case ixgbe_mac_82599EB: + if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { + /* + * EICS(0..15) first 0-15 q vectors + * EICS[1] (16..31) q vectors 16-31 + * EICS[2] (0..31) q vectors 32-63 + */ + IXGBE_WRITE_REG(hw, IXGBE_EICS, + (u32)(eics & 0xFFFF)); + IXGBE_WRITE_REG(hw, IXGBE_EICS_EX(1), + (u32)(eics & 0xFFFF0000)); + IXGBE_WRITE_REG(hw, IXGBE_EICS_EX(2), + (u32)(eics >> 32)); + } else { + /* + * for legacy and MSI interrupts don't set any + * bits that are enabled for EIAM, because this + * operation would set *both* EIMS and EICS for + * any bit in EIAM + */ + IXGBE_WRITE_REG(hw, IXGBE_EICS, + (IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER)); + } + break; + default: + break; } /* Reset the timer */ mod_timer(&adapter->watchdog_timer, -- GitLab From 408896d508794c98a2ac6b6e1dcd7a4888a4d32b Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Fri, 20 Mar 2009 01:32:58 -0700 Subject: [PATCH 3766/4982] dnet: remove duplicated #include Removed duplicated #include in drivers/net/dnet.c. Signed-off-by: Huang Weiyi Signed-off-by: David S. Miller --- drivers/net/dnet.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c index 5c347f70cb6..8a98d407692 100644 --- a/drivers/net/dnet.c +++ b/drivers/net/dnet.c @@ -21,7 +21,6 @@ #include #include #include -#include #include "dnet.h" -- GitLab From 5e140dfc1fe87eae27846f193086724806b33c7d Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 20 Mar 2009 01:33:32 -0700 Subject: [PATCH 3767/4982] net: reorder struct Qdisc for better SMP performance dev_queue_xmit() needs to dirty fields "state", "q", "bstats" and "qstats" On x86_64 arch, they currently span three cache lines, involving more cache line ping pongs than necessary, making longer holding of queue spinlock. We can reduce this to one cache line, by grouping all read-mostly fields at the beginning of structure. (Or should I say, all highly modified fields at the end :) ) Before patch : offsetof(struct Qdisc, state)=0x38 offsetof(struct Qdisc, q)=0x48 offsetof(struct Qdisc, bstats)=0x80 offsetof(struct Qdisc, qstats)=0x90 sizeof(struct Qdisc)=0xc8 After patch : offsetof(struct Qdisc, state)=0x80 offsetof(struct Qdisc, q)=0x88 offsetof(struct Qdisc, bstats)=0xa0 offsetof(struct Qdisc, qstats)=0xac sizeof(struct Qdisc)=0xc0 Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/gen_stats.h | 2 +- include/net/sch_generic.h | 21 ++++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/include/linux/gen_stats.h b/include/linux/gen_stats.h index 13f4e74609a..0ffa41df0ee 100644 --- a/include/linux/gen_stats.h +++ b/include/linux/gen_stats.h @@ -22,7 +22,7 @@ struct gnet_stats_basic { __u64 bytes; __u32 packets; -}; +} __attribute__ ((packed)); /** * struct gnet_stats_rate_est - rate estimator diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 3d78a4d2246..964ffa0d881 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -49,18 +49,10 @@ struct Qdisc int padded; struct Qdisc_ops *ops; struct qdisc_size_table *stab; + struct list_head list; u32 handle; u32 parent; atomic_t refcnt; - unsigned long state; - struct sk_buff *gso_skb; - struct sk_buff_head q; - struct netdev_queue *dev_queue; - struct Qdisc *next_sched; - struct list_head list; - - struct gnet_stats_basic bstats; - struct gnet_stats_queue qstats; struct gnet_stats_rate_est rate_est; int (*reshape_fail)(struct sk_buff *skb, struct Qdisc *q); @@ -71,6 +63,17 @@ struct Qdisc * and it will live until better solution will be invented. */ struct Qdisc *__parent; + struct netdev_queue *dev_queue; + struct Qdisc *next_sched; + + struct sk_buff *gso_skb; + /* + * For performance sake on SMP, we put highly modified fields at the end + */ + unsigned long state; + struct sk_buff_head q; + struct gnet_stats_basic bstats; + struct gnet_stats_queue qstats; }; struct Qdisc_class_ops -- GitLab From 615e73b3cd8876262f61ea28b4147c8de38a043a Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 19 Mar 2009 10:04:29 +0000 Subject: [PATCH 3768/4982] sh: disallow kexec virtual entry Older versions of kexec-tools has a zImage loader that passes a virtual address as entry point. The elf loader otoh it passes a physical address as entry point, and pages are always passed as physical addresses as well. Only allow physical addresses from now on. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/machine_kexec.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c index cc7c29b0dc8..7ea2704ea03 100644 --- a/arch/sh/kernel/machine_kexec.c +++ b/arch/sh/kernel/machine_kexec.c @@ -46,6 +46,12 @@ void machine_crash_shutdown(struct pt_regs *regs) */ int machine_kexec_prepare(struct kimage *image) { + /* older versions of kexec-tools are passing + * the zImage entry point as a virtual address. + */ + if (image->start != PHYSADDR(image->start)) + return -EINVAL; /* upgrade your kexec-tools */ + return 0; } @@ -125,7 +131,8 @@ void machine_kexec(struct kimage *image) /* now call it */ rnk = (relocate_new_kernel_t) reboot_code_buffer; - (*rnk)(page_list, reboot_code_buffer, image->start); + (*rnk)(page_list, reboot_code_buffer, + (unsigned long)phys_to_virt(image->start)); #ifdef CONFIG_KEXEC_JUMP asm volatile("ldc %0, vbr" : : "r" (&vbr_base) : "memory"); -- GitLab From 9cd88b90a6008b0d744187fab80ade4c81c6536f Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 19 Mar 2009 10:05:58 +0000 Subject: [PATCH 3769/4982] sh: sh-rtc carry interrupt rework This patch modifies the SuperH RTC driver to only enable carry interrupts when needed. So by default no interrupts are enabled with this patch. Without this patch a suspending system will most likely wake up by the carry interrupt regardless if the alarm interrupt has been enabled or not. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/rtc/rtc-sh.c | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index aeff2511197..21e7435daec 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c @@ -319,6 +319,25 @@ static int sh_rtc_proc(struct device *dev, struct seq_file *seq) return 0; } +static inline void sh_rtc_setcie(struct device *dev, unsigned int enable) +{ + struct sh_rtc *rtc = dev_get_drvdata(dev); + unsigned int tmp; + + spin_lock_irq(&rtc->lock); + + tmp = readb(rtc->regbase + RCR1); + + if (!enable) + tmp &= ~RCR1_CIE; + else + tmp |= RCR1_CIE; + + writeb(tmp, rtc->regbase + RCR1); + + spin_unlock_irq(&rtc->lock); +} + static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { struct sh_rtc *rtc = dev_get_drvdata(dev); @@ -335,9 +354,11 @@ static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) break; case RTC_UIE_OFF: rtc->periodic_freq &= ~PF_OXS; + sh_rtc_setcie(dev, 0); break; case RTC_UIE_ON: rtc->periodic_freq |= PF_OXS; + sh_rtc_setcie(dev, 1); break; case RTC_IRQP_READ: ret = put_user(rtc->rtc_dev->irq_freq, @@ -400,6 +421,10 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_sec--; #endif + /* only keep the carry interrupt enabled if UIE is on */ + if (!(rtc->periodic_freq & PF_OXS)) + sh_rtc_setcie(dev, 0); + dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " "mday=%d, mon=%d, year=%d, wday=%d\n", __func__, @@ -616,7 +641,6 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) { struct sh_rtc *rtc; struct resource *res; - unsigned int tmp; int ret; rtc = kzalloc(sizeof(struct sh_rtc), GFP_KERNEL); @@ -676,8 +700,6 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) } rtc->rtc_dev->max_user_freq = 256; - rtc->rtc_dev->irq_freq = 1; - rtc->periodic_freq = 0x60; platform_set_drvdata(pdev, rtc); @@ -724,11 +746,12 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) } } - tmp = readb(rtc->regbase + RCR1); - tmp &= ~RCR1_CF; - tmp |= RCR1_CIE; - writeb(tmp, rtc->regbase + RCR1); - + /* everything disabled by default */ + rtc->periodic_freq = 0; + rtc->rtc_dev->irq_freq = 0; + sh_rtc_setpie(&pdev->dev, 0); + sh_rtc_setaie(&pdev->dev, 0); + sh_rtc_setcie(&pdev->dev, 0); return 0; err_unmap: @@ -750,6 +773,7 @@ static int __devexit sh_rtc_remove(struct platform_device *pdev) sh_rtc_setpie(&pdev->dev, 0); sh_rtc_setaie(&pdev->dev, 0); + sh_rtc_setcie(&pdev->dev, 0); free_irq(rtc->periodic_irq, rtc); if (rtc->carry_irq > 0) { -- GitLab From edf22477dab5ff3be612af56ee4300ca63e11d06 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 19 Mar 2009 10:10:44 +0000 Subject: [PATCH 3770/4982] sh: sh-rtc invalid time rework This patch modifies invalid time handling in the SuperH RTC driver. Instead of zeroing the returned value at read-out time we just return an error code and reset invalid values during probe. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/rtc/rtc-sh.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 21e7435daec..9ab660c28fe 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c @@ -431,12 +431,7 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday); - if (rtc_valid_tm(tm) < 0) { - dev_err(dev, "invalid date\n"); - rtc_time_to_tm(0, tm); - } - - return 0; + return rtc_valid_tm(tm); } static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm) @@ -641,6 +636,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) { struct sh_rtc *rtc; struct resource *res; + struct rtc_time r; int ret; rtc = kzalloc(sizeof(struct sh_rtc), GFP_KERNEL); @@ -752,6 +748,13 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) sh_rtc_setpie(&pdev->dev, 0); sh_rtc_setaie(&pdev->dev, 0); sh_rtc_setcie(&pdev->dev, 0); + + /* reset rtc to epoch 0 if time is invalid */ + if (rtc_read_time(rtc->rtc_dev, &r) < 0) { + rtc_time_to_tm(0, &r); + rtc_set_time(rtc->rtc_dev, &r); + } + return 0; err_unmap: -- GitLab From 7a8fe8e320251d25274e89f610ffee936769250a Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 19 Mar 2009 10:14:41 +0000 Subject: [PATCH 3771/4982] sh: sh-rtc wakeup support Flag that the SuperH RTC supports wakeup. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/rtc/rtc-sh.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 9ab660c28fe..4898f7fe851 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c @@ -755,6 +755,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) rtc_set_time(rtc->rtc_dev, &r); } + device_init_wakeup(&pdev->dev, 1); return 0; err_unmap: -- GitLab From 3bf509230a626d11cba0e0145f552918092f586d Mon Sep 17 00:00:00 2001 From: Rafael Ignacio Zurita Date: Fri, 20 Mar 2009 02:08:22 +0000 Subject: [PATCH 3772/4982] sh: fix the HD64461 level-triggered interrupts handling Rework the hd64461 demuxer code to fix the HD64461 level-triggered interrupts handling, using handle_level_irq() as needed. Signed-off-by: Rafael Ignacio Zurita Signed-off-by: Paul Mundt --- arch/sh/boards/mach-hp6xx/setup.c | 1 - arch/sh/cchips/hd6446x/hd64461.c | 30 +++++++++++++++++------------- arch/sh/include/asm/hd64461.h | 1 - 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/arch/sh/boards/mach-hp6xx/setup.c b/arch/sh/boards/mach-hp6xx/setup.c index 746742bdc01..8f305b36358 100644 --- a/arch/sh/boards/mach-hp6xx/setup.c +++ b/arch/sh/boards/mach-hp6xx/setup.c @@ -115,7 +115,6 @@ static struct sh_machine_vector mv_hp6xx __initmv = { .mv_setup = hp6xx_setup, /* IRQ's : CPU(64) + CCHIP(16) + FREE_TO_USE(6) */ .mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM + 6, - .mv_irq_demux = hd64461_irq_demux, /* Enable IRQ0 -> IRQ3 in IRQ_MODE */ .mv_init_irq = hp6xx_init_irq, }; diff --git a/arch/sh/cchips/hd6446x/hd64461.c b/arch/sh/cchips/hd6446x/hd64461.c index 27ceeb948bb..25ef9106152 100644 --- a/arch/sh/cchips/hd6446x/hd64461.c +++ b/arch/sh/cchips/hd6446x/hd64461.c @@ -53,21 +53,22 @@ static struct irq_chip hd64461_irq_chip = { .unmask = hd64461_unmask_irq, }; -int hd64461_irq_demux(int irq) +static void hd64461_irq_demux(unsigned int irq, struct irq_desc *desc) { - if (irq == CONFIG_HD64461_IRQ) { - unsigned short bit; - unsigned short nirr = inw(HD64461_NIRR); - unsigned short nimr = inw(HD64461_NIMR); - int i; - - nirr &= ~nimr; - for (bit = 1, i = 0; i < 16; bit <<= 1, i++) - if (nirr & bit) - break; - irq = HD64461_IRQBASE + i; + unsigned short intv = ctrl_inw(HD64461_NIRR); + struct irq_desc *ext_desc; + unsigned int ext_irq = HD64461_IRQBASE; + + intv &= (1 << HD64461_IRQ_NUM) - 1; + + while (intv) { + if (intv & 1) { + ext_desc = irq_desc + ext_irq; + handle_level_irq(ext_irq, ext_desc); + } + intv >>= 1; + ext_irq++; } - return irq; } int __init setup_hd64461(void) @@ -93,6 +94,9 @@ int __init setup_hd64461(void) set_irq_chip_and_handler(i, &hd64461_irq_chip, handle_level_irq); + set_irq_chained_handler(CONFIG_HD64461_IRQ, hd64461_irq_demux); + set_irq_type(CONFIG_HD64461_IRQ, IRQ_TYPE_LEVEL_LOW); + #ifdef CONFIG_HD64461_ENABLER printk(KERN_INFO "HD64461: enabling PCMCIA devices\n"); __raw_writeb(0x4c, HD64461_PCC1CSCIER); diff --git a/arch/sh/include/asm/hd64461.h b/arch/sh/include/asm/hd64461.h index 8c1353baf00..52b4b623827 100644 --- a/arch/sh/include/asm/hd64461.h +++ b/arch/sh/include/asm/hd64461.h @@ -242,7 +242,6 @@ #include /* arch/sh/cchips/hd6446x/hd64461/setup.c */ -int hd64461_irq_demux(int irq); void hd64461_register_irq_demux(int irq, int (*demux) (int irq, void *dev), void *dev); void hd64461_unregister_irq_demux(int irq); -- GitLab From c468ac29e63b9927275a94379d00b367f0f97c43 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 20 Mar 2009 10:08:11 +0100 Subject: [PATCH 3773/4982] ALSA: sound/ali5451: typo: s/resouces/resources/ Signed-off-by: Wolfram Sang Signed-off-by: Takashi Iwai --- sound/pci/ali5451/ali5451.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 1a0fd65ec28..9069c78c2dc 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -2142,7 +2142,7 @@ static int __devinit snd_ali_resources(struct snd_ali *codec) { int err; - snd_ali_printk("resouces allocation ...\n"); + snd_ali_printk("resources allocation ...\n"); err = pci_request_regions(codec->pci, "ALI 5451"); if (err < 0) return err; @@ -2154,7 +2154,7 @@ static int __devinit snd_ali_resources(struct snd_ali *codec) return -EBUSY; } codec->irq = codec->pci->irq; - snd_ali_printk("resouces allocated.\n"); + snd_ali_printk("resources allocated.\n"); return 0; } static int snd_ali_dev_free(struct snd_device *device) -- GitLab From 2d864c499a77129dc6aa4f7552ddf2885e4a9c47 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 20 Mar 2009 12:52:47 +0100 Subject: [PATCH 3774/4982] ALSA: hda - Detect digital-mic inputs on ALC663 / ALC272 Fix the detection of digital-mic inputs on ALC663 / ALC272 codecs in the auto-detection mode. The automatic mic switch via plugging isn't implemented yet, though. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 63 ++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 5ad0f8d72dd..b69d9864f6f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -16725,26 +16725,58 @@ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, return 0; } +/* return the index of the src widget from the connection list of the nid. + * return -1 if not found + */ +static int alc662_input_pin_idx(struct hda_codec *codec, hda_nid_t nid, + hda_nid_t src) +{ + hda_nid_t conn_list[HDA_MAX_CONNECTIONS]; + int i, conns; + + conns = snd_hda_get_connections(codec, nid, conn_list, + ARRAY_SIZE(conn_list)); + if (conns < 0) + return -1; + for (i = 0; i < conns; i++) + if (conn_list[i] == src) + return i; + return -1; +} + +static int alc662_is_input_pin(struct hda_codec *codec, hda_nid_t nid) +{ + unsigned int pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); + return (pincap & AC_PINCAP_IN) != 0; +} + /* create playback/capture controls for input pins */ -static int alc662_auto_create_analog_input_ctls(struct alc_spec *spec, +static int alc662_auto_create_analog_input_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) { + struct alc_spec *spec = codec->spec; struct hda_input_mux *imux = &spec->private_imux[0]; int i, err, idx; for (i = 0; i < AUTO_PIN_LAST; i++) { - if (alc880_is_input_pin(cfg->input_pins[i])) { - idx = alc880_input_pin_idx(cfg->input_pins[i]); - err = new_analog_input(spec, cfg->input_pins[i], - auto_pin_cfg_labels[i], - idx, 0x0b); - if (err < 0) - return err; - imux->items[imux->num_items].label = - auto_pin_cfg_labels[i]; - imux->items[imux->num_items].index = - alc880_input_pin_idx(cfg->input_pins[i]); - imux->num_items++; + if (alc662_is_input_pin(codec, cfg->input_pins[i])) { + idx = alc662_input_pin_idx(codec, 0x0b, + cfg->input_pins[i]); + if (idx >= 0) { + err = new_analog_input(spec, cfg->input_pins[i], + auto_pin_cfg_labels[i], + idx, 0x0b); + if (err < 0) + return err; + } + idx = alc662_input_pin_idx(codec, 0x22, + cfg->input_pins[i]); + if (idx >= 0) { + imux->items[imux->num_items].label = + auto_pin_cfg_labels[i]; + imux->items[imux->num_items].index = idx; + imux->num_items++; + } } } return 0; @@ -16794,7 +16826,6 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec) alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); } -#define alc662_is_input_pin(nid) alc880_is_input_pin(nid) #define ALC662_PIN_CD_NID ALC880_PIN_CD_NID static void alc662_auto_init_analog_input(struct hda_codec *codec) @@ -16804,7 +16835,7 @@ static void alc662_auto_init_analog_input(struct hda_codec *codec) for (i = 0; i < AUTO_PIN_LAST; i++) { hda_nid_t nid = spec->autocfg.input_pins[i]; - if (alc662_is_input_pin(nid)) { + if (alc662_is_input_pin(codec, nid)) { alc_set_input_pin(codec, nid, i); if (nid != ALC662_PIN_CD_NID) snd_hda_codec_write(codec, nid, 0, @@ -16844,7 +16875,7 @@ static int alc662_parse_auto_config(struct hda_codec *codec) "Headphone"); if (err < 0) return err; - err = alc662_auto_create_analog_input_ctls(spec, &spec->autocfg); + err = alc662_auto_create_analog_input_ctls(codec, &spec->autocfg); if (err < 0) return err; -- GitLab From 8b22d943c34b616eefbd6d2f8f197a53b1f29fd0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 20 Mar 2009 16:26:15 +0100 Subject: [PATCH 3775/4982] ALSA: pcm - Safer boundary checks Make the boundary checks a bit safer. These caese are rare or theoretically won't happen, but nothing bad to keep the checks safer... Signed-off-by: Takashi Iwai --- sound/core/pcm_lib.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 063c675177a..fbb2e391591 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -222,8 +222,9 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size; delta = new_hw_ptr - hw_ptr_interrupt; if (hw_ptr_interrupt >= runtime->boundary) { - hw_ptr_interrupt %= runtime->boundary; - if (!hw_base) /* hw_base was already lapped; recalc delta */ + hw_ptr_interrupt -= runtime->boundary; + if (hw_base < runtime->boundary / 2) + /* hw_base was already lapped; recalc delta */ delta = new_hw_ptr - hw_ptr_interrupt; } if (delta < 0) { @@ -241,7 +242,7 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) delta = 0; } else { hw_base += runtime->buffer_size; - if (hw_base == runtime->boundary) + if (hw_base >= runtime->boundary) hw_base = 0; new_hw_ptr = hw_base + pos; } @@ -296,7 +297,7 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) return 0; } hw_base += runtime->buffer_size; - if (hw_base == runtime->boundary) + if (hw_base >= runtime->boundary) hw_base = 0; new_hw_ptr = hw_base + pos; } -- GitLab From eaeed5d31d8ded02fa0a4b608f57418cc0e65b07 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Fri, 20 Mar 2009 14:16:29 +0000 Subject: [PATCH 3776/4982] sh: add support for SMSC Polaris platform Polaris is an SMSC reference platform with a SH7709S CPU and LAN9118 ethernet controller. This patch adds support for it. Updated following feedback from Nobuhiro Iwamatsu. Signed-off-by: Steve Glendinning Reviewed-by: Nobuhiro Iwamatsu Signed-off-by: Paul Mundt --- arch/sh/boards/Kconfig | 7 + arch/sh/boards/Makefile | 1 + arch/sh/boards/board-polaris.c | 149 +++++ arch/sh/configs/polaris_defconfig | 969 ++++++++++++++++++++++++++++++ arch/sh/tools/mach-types | 1 + 5 files changed, 1127 insertions(+) create mode 100644 arch/sh/boards/board-polaris.c create mode 100644 arch/sh/configs/polaris_defconfig diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig index 48c043bf45c..dcc1af8a2cf 100644 --- a/arch/sh/boards/Kconfig +++ b/arch/sh/boards/Kconfig @@ -261,6 +261,13 @@ config SH_CAYMAN depends on CPU_SUBTYPE_SH5_101 || CPU_SUBTYPE_SH5_103 select SYS_SUPPORTS_PCI +config SH_POLARIS + bool "SMSC Polaris" + select CPU_HAS_IPR_IRQ + depends on CPU_SUBTYPE_SH7709 + help + Select if configuring for an SMSC Polaris development board + endmenu source "arch/sh/boards/mach-r2d/Kconfig" diff --git a/arch/sh/boards/Makefile b/arch/sh/boards/Makefile index d0daebce8b3..7baa2109023 100644 --- a/arch/sh/boards/Makefile +++ b/arch/sh/boards/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_SH_URQUELL) += board-urquell.o obj-$(CONFIG_SH_SHMIN) += board-shmin.o obj-$(CONFIG_SH_EDOSK7760) += board-edosk7760.o obj-$(CONFIG_SH_ESPT) += board-espt.o +obj-$(CONFIG_SH_POLARIS) += board-polaris.o diff --git a/arch/sh/boards/board-polaris.c b/arch/sh/boards/board-polaris.c new file mode 100644 index 00000000000..62607eb5100 --- /dev/null +++ b/arch/sh/boards/board-polaris.c @@ -0,0 +1,149 @@ +/* + * June 2006 steve.glendinning@smsc.com + * + * Polaris-specific resource declaration + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BCR2 (0xFFFFFF62) +#define WCR2 (0xFFFFFF66) +#define AREA5_WAIT_CTRL (0x1C00) +#define WAIT_STATES_10 (0x7) + +static struct resource smsc911x_resources[] = { + [0] = { + .name = "smsc911x-memory", + .start = PA_EXT5, + .end = PA_EXT5 + 0x1fff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .name = "smsc911x-irq", + .start = IRQ0_IRQ, + .end = IRQ0_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct smsc911x_platform_config smsc911x_config = { + .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, + .irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN, + .flags = SMSC911X_USE_32BIT, + .phy_interface = PHY_INTERFACE_MODE_MII, +}; + +static struct platform_device smsc911x_device = { + .name = "smsc911x", + .id = 0, + .num_resources = ARRAY_SIZE(smsc911x_resources), + .resource = smsc911x_resources, + .dev = { + .platform_data = &smsc911x_config, + }, +}; + +static unsigned char heartbeat_bit_pos[] = { 0, 1, 2, 3 }; + +static struct heartbeat_data heartbeat_data = { + .bit_pos = heartbeat_bit_pos, + .nr_bits = ARRAY_SIZE(heartbeat_bit_pos), + .regsize = 8, +}; + +static struct resource heartbeat_resources[] = { + [0] = { + .start = PORT_PCDR, + .end = PORT_PCDR, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device heartbeat_device = { + .name = "heartbeat", + .id = -1, + .dev = { + .platform_data = &heartbeat_data, + }, + .num_resources = ARRAY_SIZE(heartbeat_resources), + .resource = heartbeat_resources, +}; + +static struct platform_device *polaris_devices[] __initdata = { + &smsc911x_device, + &heartbeat_device, +}; + +static int __init polaris_initialise(void) +{ + u16 wcr, bcr_mask; + + printk(KERN_INFO "Configuring Polaris external bus\n"); + + /* Configure area 5 with 2 wait states */ + wcr = ctrl_inw(WCR2); + wcr &= (~AREA5_WAIT_CTRL); + wcr |= (WAIT_STATES_10 << 10); + ctrl_outw(wcr, WCR2); + + /* Configure area 5 for 32-bit access */ + bcr_mask = ctrl_inw(BCR2); + bcr_mask |= 1 << 10; + ctrl_outw(bcr_mask, BCR2); + + return platform_add_devices(polaris_devices, + ARRAY_SIZE(polaris_devices)); +} +arch_initcall(polaris_initialise); + +static struct ipr_data ipr_irq_table[] = { + /* External IRQs */ + { IRQ0_IRQ, 0, 0, 1, }, /* IRQ0 */ + { IRQ1_IRQ, 0, 4, 1, }, /* IRQ1 */ +}; + +static unsigned long ipr_offsets[] = { + INTC_IPRC +}; + +static struct ipr_desc ipr_irq_desc = { + .ipr_offsets = ipr_offsets, + .nr_offsets = ARRAY_SIZE(ipr_offsets), + + .ipr_data = ipr_irq_table, + .nr_irqs = ARRAY_SIZE(ipr_irq_table), + .chip = { + .name = "sh7709-ext", + }, +}; + +static void __init init_polaris_irq(void) +{ + /* Disable all interrupts */ + ctrl_outw(0, BCR_ILCRA); + ctrl_outw(0, BCR_ILCRB); + ctrl_outw(0, BCR_ILCRC); + ctrl_outw(0, BCR_ILCRD); + ctrl_outw(0, BCR_ILCRE); + ctrl_outw(0, BCR_ILCRF); + ctrl_outw(0, BCR_ILCRG); + + register_ipr_controller(&ipr_irq_desc); +} + +static struct sh_machine_vector mv_polaris __initmv = { + .mv_name = "Polaris", + .mv_nr_irqs = 61, + .mv_init_irq = init_polaris_irq, +}; diff --git a/arch/sh/configs/polaris_defconfig b/arch/sh/configs/polaris_defconfig new file mode 100644 index 00000000000..320def233b2 --- /dev/null +++ b/arch/sh/configs/polaris_defconfig @@ -0,0 +1,969 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.29-rc4 +# Wed Feb 11 18:41:59 2009 +# +CONFIG_SUPERH=y +CONFIG_SUPERH32=y +CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig" +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_GENERIC_IRQ_PROBE=y +# CONFIG_GENERIC_GPIO is not set +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +# CONFIG_ARCH_SUSPEND_POSSIBLE is not set +# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_NO_VIRT_TO_BUS=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +# CONFIG_TASKSTATS is not set +CONFIG_AUDIT=y +# CONFIG_AUDITSYSCALL is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set +# CONFIG_CGROUPS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_IOREMAP_PROT=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_FREEZER is not set + +# +# System type +# +CONFIG_CPU_SH3=y +# CONFIG_CPU_SUBTYPE_SH7619 is not set +# CONFIG_CPU_SUBTYPE_SH7201 is not set +# CONFIG_CPU_SUBTYPE_SH7203 is not set +# CONFIG_CPU_SUBTYPE_SH7206 is not set +# CONFIG_CPU_SUBTYPE_SH7263 is not set +# CONFIG_CPU_SUBTYPE_MXG is not set +# CONFIG_CPU_SUBTYPE_SH7705 is not set +# CONFIG_CPU_SUBTYPE_SH7706 is not set +# CONFIG_CPU_SUBTYPE_SH7707 is not set +# CONFIG_CPU_SUBTYPE_SH7708 is not set +CONFIG_CPU_SUBTYPE_SH7709=y +# CONFIG_CPU_SUBTYPE_SH7710 is not set +# CONFIG_CPU_SUBTYPE_SH7712 is not set +# CONFIG_CPU_SUBTYPE_SH7720 is not set +# CONFIG_CPU_SUBTYPE_SH7721 is not set +# CONFIG_CPU_SUBTYPE_SH7750 is not set +# CONFIG_CPU_SUBTYPE_SH7091 is not set +# CONFIG_CPU_SUBTYPE_SH7750R is not set +# CONFIG_CPU_SUBTYPE_SH7750S is not set +# CONFIG_CPU_SUBTYPE_SH7751 is not set +# CONFIG_CPU_SUBTYPE_SH7751R is not set +# CONFIG_CPU_SUBTYPE_SH7760 is not set +# CONFIG_CPU_SUBTYPE_SH4_202 is not set +# CONFIG_CPU_SUBTYPE_SH7723 is not set +# CONFIG_CPU_SUBTYPE_SH7763 is not set +# CONFIG_CPU_SUBTYPE_SH7770 is not set +# CONFIG_CPU_SUBTYPE_SH7780 is not set +# CONFIG_CPU_SUBTYPE_SH7785 is not set +# CONFIG_CPU_SUBTYPE_SHX3 is not set +# CONFIG_CPU_SUBTYPE_SH7343 is not set +# CONFIG_CPU_SUBTYPE_SH7722 is not set +# CONFIG_CPU_SUBTYPE_SH7366 is not set +# CONFIG_CPU_SUBTYPE_SH5_101 is not set +# CONFIG_CPU_SUBTYPE_SH5_103 is not set + +# +# Memory management options +# +CONFIG_QUICKLIST=y +CONFIG_MMU=y +CONFIG_PAGE_OFFSET=0x80000000 +CONFIG_MEMORY_START=0x0C000000 +CONFIG_MEMORY_SIZE=0x04000000 +CONFIG_29BIT=y +CONFIG_VSYSCALL=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_MAX_ACTIVE_REGIONS=1 +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_ENTRY_OFFSET=0x00001000 +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_SPARSEMEM_STATIC=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_NR_QUICK=2 +CONFIG_UNEVICTABLE_LRU=y + +# +# Cache configuration +# +# CONFIG_SH_DIRECT_MAPPED is not set +CONFIG_CACHE_WRITEBACK=y +# CONFIG_CACHE_WRITETHROUGH is not set +# CONFIG_CACHE_OFF is not set + +# +# Processor features +# +CONFIG_CPU_LITTLE_ENDIAN=y +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_SH_FPU_EMU=y +CONFIG_SH_ADC=y +CONFIG_CPU_HAS_INTEVT=y +CONFIG_CPU_HAS_IPR_IRQ=y +CONFIG_CPU_HAS_SR_RB=y + +# +# Board support +# +# CONFIG_SH_SOLUTION_ENGINE is not set +# CONFIG_SH_HP6XX is not set +CONFIG_SH_POLARIS=y + +# +# Timer and clock configuration +# +CONFIG_SH_TMU=y +CONFIG_SH_TIMER_IRQ=16 +CONFIG_SH_PCLK_FREQ=33000000 +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set + +# +# DMA support +# +CONFIG_SH_DMA_API=y +CONFIG_SH_DMA=y +CONFIG_NR_ONCHIP_DMA_CHANNELS=4 +# CONFIG_NR_DMA_CHANNELS_BOOL is not set + +# +# Companion Chips +# + +# +# Additional SuperH Device Drivers +# +CONFIG_HEARTBEAT=y +# CONFIG_PUSH_SWITCH is not set + +# +# Kernel features +# +CONFIG_HZ_100=y +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=100 +CONFIG_SCHED_HRTICK=y +# CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_SECCOMP is not set +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_GUSA=y +# CONFIG_GUSA_RB is not set + +# +# Boot options +# +CONFIG_ZERO_PAGE_OFFSET=0x00001000 +CONFIG_BOOT_LINK_OFFSET=0x00800000 +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttySC1,115200 root=/dev/mtdblock2 rootfstype=jffs2 mem=63M mtdparts=physmap-flash.0:0x00100000(bootloader)ro,0x00500000(Kernel)ro,0x00A00000(Filesystem)" + +# +# Bus options +# +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options (EXPERIMENTAL) +# +# CONFIG_PM is not set +# CONFIG_CPU_IDLE is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_COMPAT_NET_DEV_OPS=y +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_PHONET is not set +# CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_COMPAT=y +CONFIG_MTD_PHYSMAP_START=0x00000000 +CONFIG_MTD_PHYSMAP_LEN=0x01000000 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_QINFO_PROBE is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_MISC_DEVICES=y +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_93CX6 is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +CONFIG_SMSC_PHY=y +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +# CONFIG_STNIC is not set +# CONFIG_SMC91X is not set +# CONFIG_SMC911X is not set +CONFIG_SMSC911X=y +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_DEVKMEM=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_N_HDLC is not set +# CONFIG_RISCOM8 is not set +# CONFIG_SPECIALIX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_SH_SCI=y +CONFIG_SERIAL_SH_SCI_NR_UARTS=3 +CONFIG_SERIAL_SH_SCI_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_REGULATOR is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +CONFIG_RTC_DRV_SH=y +# CONFIG_DMADEVICES is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_DNOTIFY is not set +# CONFIG_INOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_JFFS2_FS_WRITEBUFFER is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_REGISTER_V4 is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_SHIRQ=y +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_PREEMPT=y +CONFIG_DEBUG_RT_MUTEXES=y +CONFIG_DEBUG_PI_LIST=y +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_LOCK_ALLOC=y +# CONFIG_PROVE_LOCKING is not set +CONFIG_LOCKDEP=y +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_LOCKDEP is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +CONFIG_DEBUG_SG=y +# CONFIG_DEBUG_NOTIFIERS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y + +# +# Tracers +# +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_SH_STANDARD_BIOS is not set +CONFIG_EARLY_SCIF_CONSOLE=y +CONFIG_EARLY_SCIF_CONSOLE_PORT=0x00000000 +CONFIG_EARLY_PRINTK=y +# CONFIG_DEBUG_BOOTMEM is not set +# CONFIG_DEBUG_STACKOVERFLOW is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_4KSTACKS is not set +# CONFIG_IRQSTACKS is not set +CONFIG_DUMP_CODE=y +# CONFIG_SH_NO_BSS_INIT is not set +# CONFIG_MORE_COMPILE_OPTIONS is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_AUDIT_GENERIC=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types index 4932705603b..8477b5d884f 100644 --- a/arch/sh/tools/mach-types +++ b/arch/sh/tools/mach-types @@ -54,3 +54,4 @@ SH7763RDP SH_SH7763RDP SH7785LCR SH_SH7785LCR URQUELL SH_URQUELL ESPT SH_ESPT +POLARIS SH_POLARIS -- GitLab From f3f9258678b081c3ef2f036aef450cd2053ef419 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 20 Mar 2009 17:57:36 +0200 Subject: [PATCH 3777/4982] nl80211: Check that function pointer != NULL before using it NL80211_CMD_GET_MESH_PARAMS and NL80211_CMD_SET_MESH_PARAMS handlers did not verify whether a function pointer is NULL (not supported by the driver) before trying to call the function. The former nl80211 command is available for unprivileged users, too, so this can potentially allow normal users to kill networking (or worse..) if mac80211 is built without CONFIG_MAC80211_MESH=y. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 1e728fff474..31b807af323 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1908,6 +1908,11 @@ static int nl80211_get_mesh_params(struct sk_buff *skb, if (err) return err; + if (!drv->ops->get_mesh_params) { + err = -EOPNOTSUPP; + goto out; + } + /* Get the mesh params */ rtnl_lock(); err = drv->ops->get_mesh_params(&drv->wiphy, dev, &cur_params); @@ -2017,6 +2022,11 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info) if (err) return err; + if (!drv->ops->set_mesh_params) { + err = -EOPNOTSUPP; + goto out; + } + /* This makes sure that there aren't more than 32 mesh config * parameters (otherwise our bitfield scheme would not work.) */ BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32); @@ -2061,6 +2071,7 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info) err = drv->ops->set_mesh_params(&drv->wiphy, dev, &cfg, mask); rtnl_unlock(); + out: /* cleanup */ cfg80211_put_dev(drv); dev_put(dev); -- GitLab From 3f518390ab1b65bc2e2bc01774eb2c5918c433ee Mon Sep 17 00:00:00 2001 From: Arthur Jones Date: Fri, 20 Mar 2009 15:56:35 -0700 Subject: [PATCH 3778/4982] e1000e: fixup merge error When merging into Jeff's tree: commit 5f66f208064f083aab5e55935d0575892e033b59 Author: Arthur Jones Date: Thu Mar 19 01:13:08 2009 +0000 e1000e: allow tx of pre-formatted vlan tagged packets We lost one line, this fixes that missing piece... Signed-off-by: Arthur Jones Signed-off-by: David S. Miller --- drivers/net/e1000e/netdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index d092eafde9b..f388a017932 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -3774,7 +3774,7 @@ static bool e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb) else protocol = skb->protocol; - switch (skb->protocol) { + switch (protocol) { case cpu_to_be16(ETH_P_IP): if (ip_hdr(skb)->protocol == IPPROTO_TCP) cmd_len |= E1000_TXD_CMD_TCP; -- GitLab From e88cd6ff2ce14ed7025d253b7f7f468d38415f77 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Sat, 21 Mar 2009 14:19:04 +0800 Subject: [PATCH 3779/4982] hwrng: timeriomem - Breaks an allyesconfig build on s390: CC drivers/char/hw_random/timeriomem-rng.o drivers/char/hw_random/timeriomem-rng.c: In function 'timeriomem_rng_data_read': drivers/char/hw_random/timeriomem-rng.c:60: error: implicit declaration of function 'readl' Signed-off-by: Heiko Carstens Signed-off-by: Herbert Xu --- drivers/char/hw_random/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index e86dd425a70..5fab6470f4b 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -22,7 +22,7 @@ config HW_RANDOM config HW_RANDOM_TIMERIOMEM tristate "Timer IOMEM HW Random Number Generator support" - depends on HW_RANDOM + depends on HW_RANDOM && HAS_IOMEM ---help--- This driver provides kernel-side support for a generic Random Number Generator used by reading a 'dumb' iomem address that -- GitLab From 4731f8b66dd34ebf0e67ca6ba9162b0e509bec06 Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Fri, 20 Mar 2009 11:11:43 +0100 Subject: [PATCH 3780/4982] [ARM] 5428/1: Module relocation update for R_ARM_V4BX It would seem when building kernel modules with modern binutils (required by modern GCC) for ARM v4T targets (specifically observed with the Samsung 24xx SoC which is an 920T) R_ARM_V4BX relocations are emitted for function epilogues. This manifests at module load time with an "unknown relocation: 40" error message. The following patch adds the R_ARM_V4BX relocation to the ARM kernel module loader. The relocation operation is taken from that within the binutils bfd library. Signed-off-by: Simtec Linux Team Signed-off-by: Vincent Sanders Signed-off-by: Russell King --- arch/arm/include/asm/elf.h | 1 + arch/arm/kernel/module.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h index a58378c343b..ce3b36e9df8 100644 --- a/arch/arm/include/asm/elf.h +++ b/arch/arm/include/asm/elf.h @@ -50,6 +50,7 @@ typedef struct user_fp elf_fpregset_t; #define R_ARM_ABS32 2 #define R_ARM_CALL 28 #define R_ARM_JUMP24 29 +#define R_ARM_V4BX 40 /* * These are used to set parameters in the core dumps. diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index dab48f27263..9f509fd00fd 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -132,6 +132,15 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, *(u32 *)loc |= offset & 0x00ffffff; break; + case R_ARM_V4BX: + /* Preserve Rm and the condition code. Alter + * other bits to re-code instruction as + * MOV PC,Rm. + */ + *(u32 *)loc &= 0xf000000f; + *(u32 *)loc |= 0x01a0f000; + break; + default: printk(KERN_ERR "%s: unknown relocation: %u\n", module->name, ELF32_R_TYPE(rel->r_info)); -- GitLab From 949abe574739848b1e68271fbac86c3cb4506aad Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 21 Mar 2009 21:12:19 +0800 Subject: [PATCH 3781/4982] crypto: sha512-s390 - Add missing block size I missed the block size when converting sha512-s390 to shash. Tested-by: Heiko Carstens Signed-off-by: Herbert Xu --- arch/s390/crypto/sha512_s390.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/s390/crypto/sha512_s390.c b/arch/s390/crypto/sha512_s390.c index 420acf41b72..83192bfc804 100644 --- a/arch/s390/crypto/sha512_s390.c +++ b/arch/s390/crypto/sha512_s390.c @@ -84,6 +84,7 @@ static struct shash_alg sha384_alg = { .cra_driver_name= "sha384-s390", .cra_priority = CRYPT_S390_PRIORITY, .cra_flags = CRYPTO_ALG_TYPE_SHASH, + .cra_blocksize = SHA384_BLOCK_SIZE, .cra_ctxsize = sizeof(struct s390_sha_ctx), .cra_module = THIS_MODULE, } -- GitLab From b55de80e49892002a1878013ab9aee1a30970be6 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Sat, 21 Mar 2009 13:25:25 -0700 Subject: [PATCH 3782/4982] e100: add support for 82552 10/100 adapter This patch enables support for the new Intel 82552 adapter (new PHY paired with the existing MAC in the ICH7 chipset). No new features are added to the driver, however there are minor changes due to updated registers and a few workarounds for hardware errata. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e100.c | 93 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 77 insertions(+), 16 deletions(-) diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 861d2eeaa43..0504db9ad64 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -167,7 +167,7 @@ #define DRV_NAME "e100" #define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.23-k6"DRV_EXT +#define DRV_VERSION "3.5.24-k2"DRV_EXT #define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" #define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" #define PFX DRV_NAME ": " @@ -240,6 +240,7 @@ static struct pci_device_id e100_id_table[] = { INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), + INTEL_8255X_ETHERNET_DEVICE(0x10fe, 7), INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), @@ -275,6 +276,7 @@ enum phy { phy_82562_em = 0x032002A8, phy_82562_ek = 0x031002A8, phy_82562_eh = 0x017002A8, + phy_82552_v = 0xd061004d, phy_unknown = 0xFFFFFFFF, }; @@ -943,6 +945,22 @@ static int mdio_read(struct net_device *netdev, int addr, int reg) static void mdio_write(struct net_device *netdev, int addr, int reg, int data) { + struct nic *nic = netdev_priv(netdev); + + if ((nic->phy == phy_82552_v) && (reg == MII_BMCR) && + (data & (BMCR_ANRESTART | BMCR_ANENABLE))) { + u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE); + + /* + * Workaround Si issue where sometimes the part will not + * autoneg to 100Mbps even when advertised. + */ + if (advert & ADVERTISE_100FULL) + data |= BMCR_SPEED100 | BMCR_FULLDPLX; + else if (advert & ADVERTISE_100HALF) + data |= BMCR_SPEED100; + } + mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data); } @@ -1276,16 +1294,12 @@ static int e100_phy_init(struct nic *nic) if (addr == 32) return -EAGAIN; - /* Selected the phy and isolate the rest */ - for (addr = 0; addr < 32; addr++) { - if (addr != nic->mii.phy_id) { - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - } else { - bmcr = mdio_read(netdev, addr, MII_BMCR); - mdio_write(netdev, addr, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - } - } + /* Isolate all the PHY ids */ + for (addr = 0; addr < 32; addr++) + mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); + /* Select the discovered PHY */ + bmcr &= ~BMCR_ISOLATE; + mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr); /* Get phy ID */ id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); @@ -1303,7 +1317,18 @@ static int e100_phy_init(struct nic *nic) mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); } - if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && + if (nic->phy == phy_82552_v) { + u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE); + + /* Workaround Si not advertising flow-control during autoneg */ + advert |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; + mdio_write(netdev, nic->mii.phy_id, MII_ADVERTISE, advert); + + /* Reset for the above changes to take effect */ + bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); + bmcr |= BMCR_RESET; + mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr); + } else if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { /* enable/disable MDI/MDI-X auto-switching. */ @@ -2134,6 +2159,9 @@ err_clean_rx: } #define MII_LED_CONTROL 0x1B +#define E100_82552_LED_OVERRIDE 0x19 +#define E100_82552_LED_ON 0x000F /* LEDTX and LED_RX both on */ +#define E100_82552_LED_OFF 0x000A /* LEDTX and LED_RX both off */ static void e100_blink_led(unsigned long data) { struct nic *nic = (struct nic *)data; @@ -2143,10 +2171,19 @@ static void e100_blink_led(unsigned long data) led_on_559 = 0x05, led_on_557 = 0x07, }; + u16 led_reg = MII_LED_CONTROL; + + if (nic->phy == phy_82552_v) { + led_reg = E100_82552_LED_OVERRIDE; - nic->leds = (nic->leds & led_on) ? led_off : - (nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559; - mdio_write(nic->netdev, nic->mii.phy_id, MII_LED_CONTROL, nic->leds); + nic->leds = (nic->leds == E100_82552_LED_ON) ? + E100_82552_LED_OFF : E100_82552_LED_ON; + } else { + nic->leds = (nic->leds & led_on) ? led_off : + (nic->mac < mac_82559_D101M) ? led_on_557 : + led_on_559; + } + mdio_write(nic->netdev, nic->mii.phy_id, led_reg, nic->leds); mod_timer(&nic->blink_timer, jiffies + HZ / 4); } @@ -2375,13 +2412,15 @@ static void e100_diag_test(struct net_device *netdev, static int e100_phys_id(struct net_device *netdev, u32 data) { struct nic *nic = netdev_priv(netdev); + u16 led_reg = (nic->phy == phy_82552_v) ? E100_82552_LED_OVERRIDE : + MII_LED_CONTROL; if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); mod_timer(&nic->blink_timer, jiffies); msleep_interruptible(data * 1000); del_timer_sync(&nic->blink_timer); - mdio_write(netdev, nic->mii.phy_id, MII_LED_CONTROL, 0); + mdio_write(netdev, nic->mii.phy_id, led_reg, 0); return 0; } @@ -2686,6 +2725,9 @@ static void __devexit e100_remove(struct pci_dev *pdev) } } +#define E100_82552_SMARTSPEED 0x14 /* SmartSpeed Ctrl register */ +#define E100_82552_REV_ANEG 0x0200 /* Reverse auto-negotiation */ +#define E100_82552_ANEG_NOW 0x0400 /* Auto-negotiate now */ static int e100_suspend(struct pci_dev *pdev, pm_message_t state) { struct net_device *netdev = pci_get_drvdata(pdev); @@ -2698,6 +2740,15 @@ static int e100_suspend(struct pci_dev *pdev, pm_message_t state) pci_save_state(pdev); if ((nic->flags & wol_magic) | e100_asf(nic)) { + /* enable reverse auto-negotiation */ + if (nic->phy == phy_82552_v) { + u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, + E100_82552_SMARTSPEED); + + mdio_write(netdev, nic->mii.phy_id, + E100_82552_SMARTSPEED, smartspeed | + E100_82552_REV_ANEG | E100_82552_ANEG_NOW); + } if (pci_enable_wake(pdev, PCI_D3cold, true)) pci_enable_wake(pdev, PCI_D3hot, true); } else { @@ -2721,6 +2772,16 @@ static int e100_resume(struct pci_dev *pdev) /* ack any pending wake events, disable PME */ pci_enable_wake(pdev, 0, 0); + /* disbale reverse auto-negotiation */ + if (nic->phy == phy_82552_v) { + u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, + E100_82552_SMARTSPEED); + + mdio_write(netdev, nic->mii.phy_id, + E100_82552_SMARTSPEED, + smartspeed & ~(E100_82552_REV_ANEG)); + } + netif_device_attach(netdev); if (netif_running(netdev)) e100_up(nic); -- GitLab From 29ded5f76ce3c41f43b64643b074b7c9c9ebd925 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sat, 21 Mar 2009 13:27:55 -0700 Subject: [PATCH 3783/4982] gianfar: Fix build with CONFIG_PM enabled commit 4826857f1bf07f9c0f1495e9b05d125552c88a85 ("gianfar: pass the proper dev to DMA ops") introduced this build breakage: CC drivers/net/gianfar.o drivers/net/gianfar.c: In function 'gfar_suspend': drivers/net/gianfar.c:552: error: 'struct gfar_private' has no member named 'dev' drivers/net/gianfar.c: In function 'gfar_resume': drivers/net/gianfar.c:601: error: 'struct gfar_private' has no member named 'dev' make[2]: *** [drivers/net/gianfar.o] Error 1 Fix this by converting suspend and resume routines to use gfar_private->ndev. Signed-off-by: Anton Vorontsov Acked-by: Kumar Gala Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 8659833f28e..8a51df045e8 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -549,7 +549,7 @@ static int gfar_remove(struct of_device *ofdev) static int gfar_suspend(struct of_device *ofdev, pm_message_t state) { struct gfar_private *priv = dev_get_drvdata(&ofdev->dev); - struct net_device *dev = priv->dev; + struct net_device *dev = priv->ndev; unsigned long flags; u32 tempval; @@ -598,7 +598,7 @@ static int gfar_suspend(struct of_device *ofdev, pm_message_t state) static int gfar_resume(struct of_device *ofdev) { struct gfar_private *priv = dev_get_drvdata(&ofdev->dev); - struct net_device *dev = priv->dev; + struct net_device *dev = priv->ndev; unsigned long flags; u32 tempval; int magic_packet = priv->wol_en && -- GitLab From 04ec5cfcfd9a69c16fc8adb9d7f4836eedb84e53 Mon Sep 17 00:00:00 2001 From: Richard Kennedy Date: Sat, 21 Mar 2009 13:29:05 -0700 Subject: [PATCH 3784/4982] ipv6: reorder struct inet6_ifaddr to remove padding on 64 bit builds reorder struct inet6_ifaddr to remove padding on 64 bit builds remove 8 bytes of padding so inet6_ifaddr becomes 192 bytes & fits into a smaller slab. Signed-off-by: Richard Kennedy Signed-off-by: David S. Miller --- include/net/if_inet6.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h index c8effa4b1fe..38b78132019 100644 --- a/include/net/if_inet6.h +++ b/include/net/if_inet6.h @@ -39,8 +39,6 @@ struct inet6_ifaddr __u32 valid_lft; __u32 prefered_lft; - unsigned long cstamp; /* created timestamp */ - unsigned long tstamp; /* updated timestamp */ atomic_t refcnt; spinlock_t lock; @@ -49,6 +47,9 @@ struct inet6_ifaddr __u16 scope; + unsigned long cstamp; /* created timestamp */ + unsigned long tstamp; /* updated timestamp */ + struct timer_list timer; struct inet6_dev *idev; -- GitLab From 301968451de7979f454b96a798869f8668ceab1a Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sat, 21 Mar 2009 13:30:05 -0700 Subject: [PATCH 3785/4982] fsl_pq_mdio: Revive Gianfar TBI PHY support commit 1577ecef766650a57fceb171acee2b13cbfaf1d3 ("netdev: Merge UCC and gianfar MDIO bus drivers") broke the TSEC TBI PHY support: the driver now refuses to probe TBI MDIO buses as it doesn't know about "fsl,gianfar-tbi" compatible entry, and thus _probe() fails with -ENODEV status. Fix this by adding "fsl,gianfar-tbi" to the list of known Gianfar MDIO buses. Signed-off-by: Anton Vorontsov Acked-by: Andy Fleming Signed-off-by: David S. Miller --- drivers/net/fsl_pq_mdio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/fsl_pq_mdio.c b/drivers/net/fsl_pq_mdio.c index b0ce1445d4a..6be36b9bc31 100644 --- a/drivers/net/fsl_pq_mdio.c +++ b/drivers/net/fsl_pq_mdio.c @@ -321,6 +321,7 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev, dev_set_drvdata(&ofdev->dev, new_bus); if (of_device_is_compatible(np, "fsl,gianfar-mdio") || + of_device_is_compatible(np, "fsl,gianfar-tbi") || of_device_is_compatible(np, "gianfar")) { #ifdef CONFIG_GIANFAR tbipa = get_gfar_tbipa(regs); -- GitLab From e2fc4d19292ef2eb208f76976ddc3320cc5839b6 Mon Sep 17 00:00:00 2001 From: Maciej Sosnowski Date: Sat, 21 Mar 2009 13:31:23 -0700 Subject: [PATCH 3786/4982] dca: add missing copyright/license headers In two dca files copyright and license headers are missing. This patch adds them there. Signed-off-by: Maciej Sosnowski Signed-off-by: David S. Miller --- drivers/dca/dca-sysfs.c | 21 +++++++++++++++++++++ include/linux/dca.h | 20 ++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/drivers/dca/dca-sysfs.c b/drivers/dca/dca-sysfs.c index bb538b9690e..ee916c9857e 100644 --- a/drivers/dca/dca-sysfs.c +++ b/drivers/dca/dca-sysfs.c @@ -1,3 +1,24 @@ +/* + * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + #include #include #include diff --git a/include/linux/dca.h b/include/linux/dca.h index b00a753eda5..9c20c7e87d0 100644 --- a/include/linux/dca.h +++ b/include/linux/dca.h @@ -1,3 +1,23 @@ +/* + * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ #ifndef DCA_H #define DCA_H /* DCA Provider API */ -- GitLab From 60784427ab331dc13c070ac4b0cc9a735bdfa9c0 Mon Sep 17 00:00:00 2001 From: Bernard Pidoux Date: Sat, 21 Mar 2009 13:33:18 -0700 Subject: [PATCH 3787/4982] ax25: SOCK_DEBUG message simplification This patch condenses two debug messages in one. Signed-off-by: Bernard Pidoux Signed-off-by: David S. Miller --- net/ax25/af_ax25.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 8f8f63ff656..fd9d06f291d 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1529,10 +1529,8 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock, dp = ax25->digipeat; } - SOCK_DEBUG(sk, "AX.25: sendto: Addresses built.\n"); - /* Build a packet */ - SOCK_DEBUG(sk, "AX.25: sendto: building packet.\n"); + SOCK_DEBUG(sk, "AX.25: sendto: Addresses built. Building packet.\n"); /* Assume the worst case */ size = len + ax25->ax25_dev->dev->hard_header_len; -- GitLab From f99bcff7a290768e035f3d4726e103c6ebe858bf Mon Sep 17 00:00:00 2001 From: Bernard Pidoux Date: Sat, 21 Mar 2009 13:33:55 -0700 Subject: [PATCH 3788/4982] ax25: zero length frame filtering in AX25 In previous commit 244f46ae6e9e18f6fc0be7d1f49febde4762c34b was introduced a zero length frame filter for ROSE protocole. This patch has the same purpose at AX25 frame level for the same reason. Empty frames have no meaning in AX25 protocole. Signed-off-by: Bernard Pidoux Signed-off-by: David S. Miller --- net/ax25/af_ax25.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index fd9d06f291d..7da5ebb84e9 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1435,6 +1435,11 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock, size_t size; int lv, err, addr_len = msg->msg_namelen; + /* AX.25 empty data frame has no meaning : don't send */ + if (len == 0) { + return (0); + } + if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_CMSG_COMPAT)) return -EINVAL; @@ -1634,6 +1639,13 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock, skb_reset_transport_header(skb); copied = skb->len; + /* AX.25 empty data frame has no meaning : ignore it */ + if (copied == 0) { + err = copied; + skb_free_datagram(sk, skb); + goto out; + } + if (copied > size) { copied = size; msg->msg_flags |= MSG_TRUNC; -- GitLab From a3ac80a130300573de351083cf4a5b46d233e8bf Mon Sep 17 00:00:00 2001 From: Bernard Pidoux Date: Sat, 21 Mar 2009 13:34:20 -0700 Subject: [PATCH 3789/4982] netrom: zero length frame filtering in NetRom A zero length frame filter was recently introduced in ROSE protocole. Previous commit makes the same at AX25 protocole level. This patch has the same purpose for NetRom protocole. The reason is that empty frames have no meaning in NetRom protocole. Signed-off-by: Bernard Pidoux Signed-off-by: David S. Miller --- net/netrom/af_netrom.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index cba7849de98..6d9c58ec56a 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -1037,6 +1037,10 @@ static int nr_sendmsg(struct kiocb *iocb, struct socket *sock, unsigned char *asmptr; int size; + /* Netrom empty data frame has no meaning : don't send */ + if (len == 0) + return 0; + if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_CMSG_COMPAT)) return -EINVAL; @@ -1167,6 +1171,11 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock, skb_reset_transport_header(skb); copied = skb->len; + /* NetRom empty data frame has no meaning : ignore it */ + if (copied == 0) { + goto out; + } + if (copied > size) { copied = size; msg->msg_flags |= MSG_TRUNC; @@ -1182,7 +1191,7 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock, msg->msg_namelen = sizeof(*sax); - skb_free_datagram(sk, skb); +out: skb_free_datagram(sk, skb); release_sock(sk); return copied; -- GitLab From a0bffffc148cd8e75a48a89ad2ddb74e4081a20a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Sat, 21 Mar 2009 13:36:17 -0700 Subject: [PATCH 3790/4982] net/*: use linux/kernel.h swap() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tcp_sack_swap seems unnecessary so I pushed swap to the caller. Also removed comment that seemed then pointless, and added include when not already there. Compile tested. Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/decnet/dn_route.c | 6 +----- net/ipv4/tcp_input.c | 23 +++-------------------- net/ipv6/addrconf.c | 7 ++----- net/sched/sch_tbf.c | 9 ++------- 4 files changed, 8 insertions(+), 37 deletions(-) diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 5130dee0b38..0cc4394117d 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -380,7 +380,6 @@ static int dn_return_short(struct sk_buff *skb) unsigned char *ptr; __le16 *src; __le16 *dst; - __le16 tmp; /* Add back headers */ skb_push(skb, skb->data - skb_network_header(skb)); @@ -399,10 +398,7 @@ static int dn_return_short(struct sk_buff *skb) ptr += 2; *ptr = 0; /* Zero hop count */ - /* Swap source and destination */ - tmp = *src; - *src = *dst; - *dst = tmp; + swap(*src, *dst); skb->pkt_type = PACKET_OUTGOING; dn_rt_finish_output(skb, NULL, NULL); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index fae78e3eccc..8ac82b3703a 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -64,6 +64,7 @@ #include #include #include +#include #include #include #include @@ -1802,11 +1803,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, for (i = used_sacks - 1; i > 0; i--) { for (j = 0; j < i; j++) { if (after(sp[j].start_seq, sp[j + 1].start_seq)) { - struct tcp_sack_block tmp; - - tmp = sp[j]; - sp[j] = sp[j + 1]; - sp[j + 1] = tmp; + swap(sp[j], sp[j + 1]); /* Track where the first SACK block goes to */ if (j == first_sack_index) @@ -4156,20 +4153,6 @@ static void tcp_sack_maybe_coalesce(struct tcp_sock *tp) } } -static inline void tcp_sack_swap(struct tcp_sack_block *sack1, - struct tcp_sack_block *sack2) -{ - __u32 tmp; - - tmp = sack1->start_seq; - sack1->start_seq = sack2->start_seq; - sack2->start_seq = tmp; - - tmp = sack1->end_seq; - sack1->end_seq = sack2->end_seq; - sack2->end_seq = tmp; -} - static void tcp_sack_new_ofo_skb(struct sock *sk, u32 seq, u32 end_seq) { struct tcp_sock *tp = tcp_sk(sk); @@ -4184,7 +4167,7 @@ static void tcp_sack_new_ofo_skb(struct sock *sk, u32 seq, u32 end_seq) if (tcp_sack_extend(sp, seq, end_seq)) { /* Rotate this_sack to the first one. */ for (; this_sack > 0; this_sack--, sp--) - tcp_sack_swap(sp, sp - 1); + swap(*sp, *(sp - 1)); if (cur_sacks > 1) tcp_sack_maybe_coalesce(tp); return; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 717584bad02..8499da9e76a 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -40,6 +40,7 @@ #include #include +#include #include #include #include @@ -1215,16 +1216,12 @@ int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev, } break; } else if (minihiscore < miniscore) { - struct ipv6_saddr_score *tmp; - if (hiscore->ifa) in6_ifa_put(hiscore->ifa); in6_ifa_hold(score->ifa); - tmp = hiscore; - hiscore = score; - score = tmp; + swap(hiscore, score); /* restore our iterator */ score->ifa = hiscore->ifa; diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index a2f93c09f3c..e22dfe85e43 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c @@ -236,7 +236,6 @@ static int tbf_change(struct Qdisc* sch, struct nlattr *opt) struct tc_tbf_qopt *qopt; struct qdisc_rate_table *rtab = NULL; struct qdisc_rate_table *ptab = NULL; - struct qdisc_rate_table *tmp; struct Qdisc *child = NULL; int max_size,n; @@ -295,13 +294,9 @@ static int tbf_change(struct Qdisc* sch, struct nlattr *opt) q->tokens = q->buffer; q->ptokens = q->mtu; - tmp = q->R_tab; - q->R_tab = rtab; - rtab = tmp; + swap(q->R_tab, rtab); + swap(q->P_tab, ptab); - tmp = q->P_tab; - q->P_tab = ptab; - ptab = tmp; sch_tree_unlock(sch); err = 0; done: -- GitLab From 1f1900f935e810d01c716fa2aaf8c9d25caa4151 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sat, 21 Mar 2009 13:37:28 -0700 Subject: [PATCH 3791/4982] atm: lec use dev_change_mtu Rather than calling device pointer directly (which is incorrect with net_device_ops), use the standard dev_change_mtu. Compile tested only. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/atm/lec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/atm/lec.c b/net/atm/lec.c index c0cba9a037e..199b6bb79f4 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -502,7 +502,7 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) priv->lane2_ops = NULL; if (priv->lane_version > 1) priv->lane2_ops = &lane2_ops; - if (dev->change_mtu(dev, mesg->content.config.mtu)) + if (dev_set_mtu(dev, mesg->content.config.mtu)) printk("%s: change_mtu to %d failed\n", dev->name, mesg->content.config.mtu); priv->is_proxy = mesg->content.config.is_proxy; -- GitLab From 9247744e5eaa29aecee5342a0c8694187a6aadcd Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sat, 21 Mar 2009 13:39:26 -0700 Subject: [PATCH 3792/4982] skb: expose and constify hash primitives Some minor changes to queue hashing: 1. Use const on accessor functions 2. Export skb_tx_hash for use in drivers (see ixgbe) Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/linux/skbuff.h | 9 ++++++--- net/core/dev.c | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 1fbab2ae613..bb1981fd60f 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1969,7 +1969,7 @@ static inline void skb_set_queue_mapping(struct sk_buff *skb, u16 queue_mapping) skb->queue_mapping = queue_mapping; } -static inline u16 skb_get_queue_mapping(struct sk_buff *skb) +static inline u16 skb_get_queue_mapping(const struct sk_buff *skb) { return skb->queue_mapping; } @@ -1984,16 +1984,19 @@ static inline void skb_record_rx_queue(struct sk_buff *skb, u16 rx_queue) skb->queue_mapping = rx_queue + 1; } -static inline u16 skb_get_rx_queue(struct sk_buff *skb) +static inline u16 skb_get_rx_queue(const struct sk_buff *skb) { return skb->queue_mapping - 1; } -static inline bool skb_rx_queue_recorded(struct sk_buff *skb) +static inline bool skb_rx_queue_recorded(const struct sk_buff *skb) { return (skb->queue_mapping != 0); } +extern u16 skb_tx_hash(const struct net_device *dev, + const struct sk_buff *skb); + #ifdef CONFIG_XFRM static inline struct sec_path *skb_sec_path(struct sk_buff *skb) { diff --git a/net/core/dev.c b/net/core/dev.c index ca212acd334..fdb9973b82a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1725,7 +1725,7 @@ out_kfree_skb: static u32 skb_tx_hashrnd; -static u16 skb_tx_hash(struct net_device *dev, struct sk_buff *skb) +u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb) { u32 hash; @@ -1740,6 +1740,7 @@ static u16 skb_tx_hash(struct net_device *dev, struct sk_buff *skb) return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32); } +EXPORT_SYMBOL(skb_tx_hash); static struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb) -- GitLab From 09a3b1f8b1af7220fd7a3caf18e6841a7f5a6c6e Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sat, 21 Mar 2009 13:40:01 -0700 Subject: [PATCH 3793/4982] ixgbe: fix select_queue management Convert ixgbe to use net_device_ops properly. Rather than changing the select_queue function pointer just check the flag. Signed-off-by: Stephen Hemminger Acked-by: Peter P Waskiewicz Jr Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_dcb_nl.c | 8 -------- drivers/net/ixgbe/ixgbe_main.c | 11 +++++++++++ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index 087cf886f2a..8a9939ee292 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c @@ -102,12 +102,6 @@ static u8 ixgbe_dcbnl_get_state(struct net_device *netdev) return !!(adapter->flags & IXGBE_FLAG_DCB_ENABLED); } -static u16 ixgbe_dcb_select_queue(struct net_device *dev, struct sk_buff *skb) -{ - /* All traffic should default to class 0 */ - return 0; -} - static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) { u8 err = 0; @@ -135,7 +129,6 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) kfree(adapter->rx_ring); adapter->tx_ring = NULL; adapter->rx_ring = NULL; - netdev->select_queue = &ixgbe_dcb_select_queue; adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; adapter->flags |= IXGBE_FLAG_DCB_ENABLED; @@ -154,7 +147,6 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) kfree(adapter->rx_ring); adapter->tx_ring = NULL; adapter->rx_ring = NULL; - netdev->select_queue = NULL; adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; adapter->flags |= IXGBE_FLAG_RSS_ENABLED; diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 0956be7c748..79aa811c403 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -4321,6 +4321,16 @@ static int ixgbe_maybe_stop_tx(struct net_device *netdev, return __ixgbe_maybe_stop_tx(netdev, tx_ring, size); } +static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb) +{ + struct ixgbe_adapter *adapter = netdev_priv(dev); + + if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) + return 0; /* All traffic should default to class 0 */ + + return skb_tx_hash(dev, skb); +} + static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); @@ -4450,6 +4460,7 @@ static const struct net_device_ops ixgbe_netdev_ops = { .ndo_open = ixgbe_open, .ndo_stop = ixgbe_close, .ndo_start_xmit = ixgbe_xmit_frame, + .ndo_select_queue = ixgbe_select_queue, .ndo_get_stats = ixgbe_get_stats, .ndo_set_rx_mode = ixgbe_set_rx_mode, .ndo_set_multicast_list = ixgbe_set_rx_mode, -- GitLab From 8d2f9e81169b8120cf2b4872930ae491b17c27b8 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Sat, 21 Mar 2009 13:41:09 -0700 Subject: [PATCH 3794/4982] sctp: Clean up TEST_FRAME hacks. Remove 2 TEST_FRAME hacks that are no longer needed. These allowed sctp regression tests to compile before, but are no longer needed. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/net/sctp/sctp.h | 7 ------- net/sctp/output.c | 5 +---- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 9e226be3be6..9f80a766828 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -62,13 +62,6 @@ * and will continue to evolve. */ - - -#ifdef TEST_FRAME -#undef CONFIG_SCTP_DBG_OBJCNT -#undef CONFIG_SYSCTL -#endif /* TEST_FRAME */ - #include #include #include diff --git a/net/sctp/output.c b/net/sctp/output.c index 07d58903a74..7d08f522ec8 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -49,13 +49,10 @@ #include #include #include +#include #include #include -#ifndef TEST_FRAME -#include -#endif /* TEST_FRAME (not defined) */ - #include /* for sa_family_t */ #include -- GitLab From ed734a97c6a81b644bd648afd7a337deb0ccd7e5 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 21 Mar 2009 13:42:55 -0700 Subject: [PATCH 3795/4982] net: remove useless prefetch() call There is no gain using prefetch() in dev_hard_start_xmit(), since we already had to read ops->ndo_select_queue pointer in dev_pick_tx(), and both pointers are probably located in the same cache line. This prefetch call slows down fast path because of a stall in address computation. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/dev.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index fdb9973b82a..052dd478d3e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1670,7 +1670,6 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, const struct net_device_ops *ops = dev->netdev_ops; int rc; - prefetch(&dev->netdev_ops->ndo_start_xmit); if (likely(!skb->next)) { if (!list_empty(&ptype_all)) dev_queue_xmit_nit(skb, dev); -- GitLab From 62f0c338d126fee75dc04bd23be30281a0e1e62f Mon Sep 17 00:00:00 2001 From: Mikhail Zolotaryov Date: Thu, 19 Mar 2009 22:28:02 +0000 Subject: [PATCH 3796/4982] powerpc 4xx EMAC driver: device name reported on timeout is not correct Hi, IBM EMAC driver performs device reset (drivers/net/ibm_newemac/core.c: emac_probe() -> emac_init_phy() -> emac_reset()) before registering appropriate net_device (emac_probe() -> register_netdev()), so net_device name contains raw format string during EMAC reset ("eth%d"). If the case of reset timeout, emac_report_timeout_error() function is called to report an error. The problem is this function uses net_device name to report device related, which is not correct, as a result in the kernel log buffer we see: eth%d: reset timeout The solution is to print device_node full_name instead. After applying the patch proposed, error string is like the following: /plb/opb/ethernet@ef600e00: reset timeout Signed-off-by: Mikhail Zolotaryov Acked-by: Benjamin Herrenschmidt Signed-off-by: David S. Miller --- drivers/net/ibm_newemac/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index 6fd7aa61736..a815e17a0ab 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -134,7 +134,7 @@ static inline void emac_report_timeout_error(struct emac_instance *dev, EMAC_FTR_440EP_PHY_CLK_FIX)) DBG(dev, "%s" NL, error); else if (net_ratelimit()) - printk(KERN_ERR "%s: %s\n", dev->ndev->name, error); + printk(KERN_ERR "%s: %s\n", dev->ofdev->node->full_name, error); } /* EMAC PHY clock workaround: -- GitLab From 6e06cb626229567629e1dc6eed9399bec549f3cf Mon Sep 17 00:00:00 2001 From: Yang Hongyang Date: Sat, 21 Mar 2009 16:52:17 -0700 Subject: [PATCH 3797/4982] spider_net: Convert to net_device_ops. Signed-off-by: Yang Hongyang Signed-off-by: David S. Miller --- drivers/net/spider_net.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 7f6b4a4052e..136d9f1c6ad 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -2259,6 +2259,22 @@ spider_net_tx_timeout(struct net_device *netdev) card->spider_stats.tx_timeouts++; } +static const struct net_device_ops spider_net_ops = { + .ndo_open = spider_net_open; + .ndo_stop = spider_net_stop; + .ndo_start_xmit = spider_net_xmit; + .ndo_set_multicast_list = spider_net_set_multi; + .ndo_set_mac_address = spider_net_set_mac; + .ndo_change_mtu = spider_net_change_mtu; + .ndo_do_ioctl = spider_net_do_ioctl; + .ndo_tx_timeout = spider_net_tx_timeout; + /* HW VLAN */ +#ifdef CONFIG_NET_POLL_CONTROLLER + /* poll controller */ + .ndo_poll_controller = spider_net_poll_controller; +#endif /* CONFIG_NET_POLL_CONTROLLER */ +}; + /** * spider_net_setup_netdev_ops - initialization of net_device operations * @netdev: net_device structure @@ -2268,21 +2284,8 @@ spider_net_tx_timeout(struct net_device *netdev) static void spider_net_setup_netdev_ops(struct net_device *netdev) { - netdev->open = &spider_net_open; - netdev->stop = &spider_net_stop; - netdev->hard_start_xmit = &spider_net_xmit; - netdev->set_multicast_list = &spider_net_set_multi; - netdev->set_mac_address = &spider_net_set_mac; - netdev->change_mtu = &spider_net_change_mtu; - netdev->do_ioctl = &spider_net_do_ioctl; - /* tx watchdog */ - netdev->tx_timeout = &spider_net_tx_timeout; + netdev->netdev_ops = &spider_net_ops; netdev->watchdog_timeo = SPIDER_NET_WATCHDOG_TIMEOUT; - /* HW VLAN */ -#ifdef CONFIG_NET_POLL_CONTROLLER - /* poll controller */ - netdev->poll_controller = &spider_net_poll_controller; -#endif /* CONFIG_NET_POLL_CONTROLLER */ /* ethtool ops */ netdev->ethtool_ops = &spider_net_ethtool_ops; } -- GitLab From fa4a7ef36ec834fee1719636b30d2f28f4cb0166 Mon Sep 17 00:00:00 2001 From: Arthur Jones Date: Sat, 21 Mar 2009 16:55:07 -0700 Subject: [PATCH 3798/4982] igb: allow tx of pre-formatted vlan tagged packets When the 82575 is fed 802.1q packets, it chokes with an error of the form: igb 0000:08:00.1 partial checksum but proto=81! As the logic there was not smart enough to look into the vlan header to pick out the encapsulated protocol. There are times when we'd like to send these packets out without having to configure a vlan on the interface. Here we check for the vlan tag and allow the packet to go out with the correct hardware checksum. Thanks to Kand Ly for discovering the issue and the coming up with a solution. This patch is based upon his work. Signed-off-by: Arthur Jones Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 7c4481b994a..39ac375487d 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3008,7 +3008,18 @@ static inline bool igb_tx_csum_adv(struct igb_adapter *adapter, tu_cmd |= (E1000_TXD_CMD_DEXT | E1000_ADVTXD_DTYP_CTXT); if (skb->ip_summed == CHECKSUM_PARTIAL) { - switch (skb->protocol) { + __be16 protocol; + + if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) { + const struct vlan_ethhdr *vhdr = + (const struct vlan_ethhdr*)skb->data; + + protocol = vhdr->h_vlan_encapsulated_proto; + } else { + protocol = skb->protocol; + } + + switch (protocol) { case cpu_to_be16(ETH_P_IP): tu_cmd |= E1000_ADVTXD_TUCMD_IPV4; if (ip_hdr(skb)->protocol == IPPROTO_TCP) -- GitLab From c493ea45a4251869fe7b820e0486b73b57df7c12 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 20 Mar 2009 00:16:50 +0000 Subject: [PATCH 3799/4982] igb: remove IGB_DESC_UNUSED since it is better handled by a function call This patch removes IGB_DESC_UNUSED and replaces it with a function call instead in order to cleanup some of the ugliness introduced by the macro. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb.h | 4 ---- drivers/net/igb/igb_main.c | 25 ++++++++++++++++++------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index e18ac1bf45f..4e8464b9df2 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -182,10 +182,6 @@ struct igb_ring { char name[IFNAMSIZ + 5]; }; -#define IGB_DESC_UNUSED(R) \ - ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \ - (R)->next_to_clean - (R)->next_to_use - 1) - #define E1000_RX_DESC_ADV(R, i) \ (&(((union e1000_adv_rx_desc *)((R).desc))[i])) #define E1000_TX_DESC_ADV(R, i) \ diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 39ac375487d..3fd2efa91cb 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -277,6 +277,17 @@ static char *igb_get_time_str(struct igb_adapter *adapter, } #endif +/** + * igb_desc_unused - calculate if we have unused descriptors + **/ +static int igb_desc_unused(struct igb_ring *ring) +{ + if (ring->next_to_clean > ring->next_to_use) + return ring->next_to_clean - ring->next_to_use - 1; + + return ring->count + ring->next_to_clean - ring->next_to_use - 1; +} + /** * igb_init_module - Driver Registration Routine * @@ -873,12 +884,12 @@ static void igb_configure(struct igb_adapter *adapter) igb_rx_fifo_flush_82575(&adapter->hw); - /* call IGB_DESC_UNUSED which always leaves + /* call igb_desc_unused which always leaves * at least 1 descriptor unused to make sure * next_to_use != next_to_clean */ for (i = 0; i < adapter->num_rx_queues; i++) { struct igb_ring *ring = &adapter->rx_ring[i]; - igb_alloc_rx_buffers_adv(ring, IGB_DESC_UNUSED(ring)); + igb_alloc_rx_buffers_adv(ring, igb_desc_unused(ring)); } @@ -2661,7 +2672,7 @@ link_up: igb_update_adaptive(&adapter->hw); if (!netif_carrier_ok(netdev)) { - if (IGB_DESC_UNUSED(tx_ring) + 1 < tx_ring->count) { + if (igb_desc_unused(tx_ring) + 1 < tx_ring->count) { /* We've lost link, so the controller stops DMA, * but we've got queued Tx work that's never going * to get done, so reset controller to flush Tx. @@ -3199,7 +3210,7 @@ static int __igb_maybe_stop_tx(struct net_device *netdev, /* We need to check again in a case another CPU has just * made room available. */ - if (IGB_DESC_UNUSED(tx_ring) < size) + if (igb_desc_unused(tx_ring) < size) return -EBUSY; /* A reprieve! */ @@ -3211,7 +3222,7 @@ static int __igb_maybe_stop_tx(struct net_device *netdev, static int igb_maybe_stop_tx(struct net_device *netdev, struct igb_ring *tx_ring, int size) { - if (IGB_DESC_UNUSED(tx_ring) >= size) + if (igb_desc_unused(tx_ring) >= size) return 0; return __igb_maybe_stop_tx(netdev, tx_ring, size); } @@ -4310,7 +4321,7 @@ static bool igb_clean_tx_irq(struct igb_ring *tx_ring) if (unlikely(count && netif_carrier_ok(netdev) && - IGB_DESC_UNUSED(tx_ring) >= IGB_TX_QUEUE_WAKE)) { + igb_desc_unused(tx_ring) >= IGB_TX_QUEUE_WAKE)) { /* Make sure that anybody stopping the queue after this * sees the new next_to_clean. */ @@ -4587,7 +4598,7 @@ next_desc: } rx_ring->next_to_clean = i; - cleaned_count = IGB_DESC_UNUSED(rx_ring); + cleaned_count = igb_desc_unused(rx_ring); if (cleaned_count) igb_alloc_rx_buffers_adv(rx_ring, cleaned_count); -- GitLab From 0e340485725ea35ca4e354cce5df09e86e31e20d Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 20 Mar 2009 00:17:08 +0000 Subject: [PATCH 3800/4982] igb: update driver to use setup_timer function igb was previously setting up all of the timer members itself. It is easier to just call setup_timer and reduce the calls to one line. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 3fd2efa91cb..4853a74843e 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1312,13 +1312,10 @@ static int __devinit igb_probe(struct pci_dev *pdev, goto err_eeprom; } - init_timer(&adapter->watchdog_timer); - adapter->watchdog_timer.function = &igb_watchdog; - adapter->watchdog_timer.data = (unsigned long) adapter; - - init_timer(&adapter->phy_info_timer); - adapter->phy_info_timer.function = &igb_update_phy_info; - adapter->phy_info_timer.data = (unsigned long) adapter; + setup_timer(&adapter->watchdog_timer, &igb_watchdog, + (unsigned long) adapter); + setup_timer(&adapter->phy_info_timer, &igb_update_phy_info, + (unsigned long) adapter); INIT_WORK(&adapter->reset_task, igb_reset_task); INIT_WORK(&adapter->watchdog_task, igb_watchdog_task); -- GitLab From c5cd11e380002d24fd4fd4c0fc38f59ab394e885 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 20 Mar 2009 00:17:25 +0000 Subject: [PATCH 3801/4982] igb: rework igb_set_multi so that vfs are properly updated Currently if there are no multicast addresses programmed into the PF then the VFs cannot have their multicast filters reset. This change makes it so the code path that updates vf multicast is always called along with the pf updates. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 4853a74843e..d6dda162116 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2464,7 +2464,7 @@ static void igb_set_multi(struct net_device *netdev) struct e1000_hw *hw = &adapter->hw; struct e1000_mac_info *mac = &hw->mac; struct dev_mc_list *mc_ptr; - u8 *mta_list; + u8 *mta_list = NULL; u32 rctl; int i; @@ -2485,17 +2485,15 @@ static void igb_set_multi(struct net_device *netdev) } wr32(E1000_RCTL, rctl); - if (!netdev->mc_count) { - /* nothing to program, so clear mc list */ - igb_update_mc_addr_list(hw, NULL, 0, 1, - mac->rar_entry_count); - return; + if (netdev->mc_count) { + mta_list = kzalloc(netdev->mc_count * 6, GFP_ATOMIC); + if (!mta_list) { + dev_err(&adapter->pdev->dev, + "failed to allocate multicast filter list\n"); + return; + } } - mta_list = kzalloc(netdev->mc_count * 6, GFP_ATOMIC); - if (!mta_list) - return; - /* The shared function expects a packed array of only addresses. */ mc_ptr = netdev->mc_list; -- GitLab From 65689fef7e484631e996541a6772706627b0991a Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 20 Mar 2009 00:17:43 +0000 Subject: [PATCH 3802/4982] igb: cleanup tx dma so map & unmap use matching calls The igb driver was using map_single to map the skbs and then unmap_page to unmap them. This update changes that so instead uses skb_dma_map and skb_dma_unmap. In addition the next_to_watch member of the buffer_info struct was being set uneccesarily. I removed the spots where it was set without being needed. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 66 ++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index d6dda162116..ca842163dce 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2257,19 +2257,14 @@ static void igb_free_all_tx_resources(struct igb_adapter *adapter) static void igb_unmap_and_free_tx_resource(struct igb_adapter *adapter, struct igb_buffer *buffer_info) { - if (buffer_info->dma) { - pci_unmap_page(adapter->pdev, - buffer_info->dma, - buffer_info->length, - PCI_DMA_TODEVICE); - buffer_info->dma = 0; - } + buffer_info->dma = 0; if (buffer_info->skb) { + skb_dma_unmap(&adapter->pdev->dev, buffer_info->skb, + DMA_TO_DEVICE); dev_kfree_skb_any(buffer_info->skb); buffer_info->skb = NULL; } buffer_info->time_stamp = 0; - buffer_info->next_to_watch = 0; /* buffer_info must be completely set up in the transmit path */ } @@ -3078,25 +3073,33 @@ static inline int igb_tx_map_adv(struct igb_adapter *adapter, unsigned int len = skb_headlen(skb); unsigned int count = 0, i; unsigned int f; + dma_addr_t *map; i = tx_ring->next_to_use; + if (skb_dma_map(&adapter->pdev->dev, skb, DMA_TO_DEVICE)) { + dev_err(&adapter->pdev->dev, "TX DMA map failed\n"); + return 0; + } + + map = skb_shinfo(skb)->dma_maps; + buffer_info = &tx_ring->buffer_info[i]; BUG_ON(len >= IGB_MAX_DATA_PER_TXD); buffer_info->length = len; /* set time_stamp *before* dma to help avoid a possible race */ buffer_info->time_stamp = jiffies; buffer_info->next_to_watch = i; - buffer_info->dma = pci_map_single(adapter->pdev, skb->data, len, - PCI_DMA_TODEVICE); + buffer_info->dma = map[count]; count++; - i++; - if (i == tx_ring->count) - i = 0; for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) { struct skb_frag_struct *frag; + i++; + if (i == tx_ring->count) + i = 0; + frag = &skb_shinfo(skb)->frags[f]; len = frag->size; @@ -3105,19 +3108,10 @@ static inline int igb_tx_map_adv(struct igb_adapter *adapter, buffer_info->length = len; buffer_info->time_stamp = jiffies; buffer_info->next_to_watch = i; - buffer_info->dma = pci_map_page(adapter->pdev, - frag->page, - frag->page_offset, - len, - PCI_DMA_TODEVICE); - + buffer_info->dma = map[count]; count++; - i++; - if (i == tx_ring->count) - i = 0; } - i = ((i == 0) ? tx_ring->count - 1 : i - 1); tx_ring->buffer_info[i].skb = skb; tx_ring->buffer_info[first].next_to_watch = i; @@ -3230,6 +3224,7 @@ static int igb_xmit_frame_ring_adv(struct sk_buff *skb, unsigned int first; unsigned int tx_flags = 0; u8 hdr_len = 0; + int count = 0; int tso = 0; union skb_shared_tx *shtx; @@ -3291,14 +3286,23 @@ static int igb_xmit_frame_ring_adv(struct sk_buff *skb, (skb->ip_summed == CHECKSUM_PARTIAL)) tx_flags |= IGB_TX_FLAGS_CSUM; - igb_tx_queue_adv(adapter, tx_ring, tx_flags, - igb_tx_map_adv(adapter, tx_ring, skb, first), - skb->len, hdr_len); - - netdev->trans_start = jiffies; - - /* Make sure there is space in the ring for the next send. */ - igb_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 4); + /* + * count reflects descriptors mapped, if 0 then mapping error + * has occured and we need to rewind the descriptor queue + */ + count = igb_tx_map_adv(adapter, tx_ring, skb, first); + + if (count) { + igb_tx_queue_adv(adapter, tx_ring, tx_flags, count, + skb->len, hdr_len); + netdev->trans_start = jiffies; + /* Make sure there is space in the ring for the next send. */ + igb_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 4); + } else { + dev_kfree_skb_any(skb); + tx_ring->buffer_info[first].time_stamp = 0; + tx_ring->next_to_use = first; + } return NETDEV_TX_OK; } -- GitLab From 4b97926ddf51b3919c859e2086fef3c8c3c46c61 Mon Sep 17 00:00:00 2001 From: Ilya Yanok Date: Sat, 21 Mar 2009 16:58:47 -0700 Subject: [PATCH 3803/4982] dnet: DNET should depend on HAS_IOMEM Signed-off-by: Ilya Yanok Signed-off-by: David S. Miller --- drivers/net/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 435e2e3a82c..62d732a886f 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1042,7 +1042,7 @@ config NI65 config DNET tristate "Dave ethernet support (DNET)" - depends on NET_ETHERNET + depends on NET_ETHERNET && HAS_IOMEM select PHYLIB help The Dave ethernet interface (DNET) is found on Qong Board FPGA. -- GitLab From 7ca98fa234afa096ec2a5e7195ad2d32555cca86 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 05:43:14 +0000 Subject: [PATCH 3804/4982] snap: use const for descriptor Protocols should be able to use constant value for the descriptor. Minor whitespace cleanup as well Signed-off-by: Stephen Hemminger Acked-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- include/net/psnap.h | 6 +++++- net/802/psnap.c | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/net/psnap.h b/include/net/psnap.h index b2e01cc3fc8..fe456c295b0 100644 --- a/include/net/psnap.h +++ b/include/net/psnap.h @@ -1,7 +1,11 @@ #ifndef _NET_PSNAP_H #define _NET_PSNAP_H -extern struct datalink_proto *register_snap_client(unsigned char *desc, int (*rcvfunc)(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *orig_dev)); +extern struct datalink_proto * +register_snap_client(const unsigned char *desc, + int (*rcvfunc)(struct sk_buff *, struct net_device *, + struct packet_type *, + struct net_device *orig_dev)); extern void unregister_snap_client(struct datalink_proto *proto); #endif diff --git a/net/802/psnap.c b/net/802/psnap.c index bdbffa3cb04..6fea0750662 100644 --- a/net/802/psnap.c +++ b/net/802/psnap.c @@ -29,7 +29,7 @@ static struct llc_sap *snap_sap; /* * Find a snap client by matching the 5 bytes. */ -static struct datalink_proto *find_snap_client(unsigned char *desc) +static struct datalink_proto *find_snap_client(const unsigned char *desc) { struct datalink_proto *proto = NULL, *p; @@ -122,7 +122,7 @@ module_exit(snap_exit); /* * Register SNAP clients. We don't yet use this for IP. */ -struct datalink_proto *register_snap_client(unsigned char *desc, +struct datalink_proto *register_snap_client(const unsigned char *desc, int (*rcvfunc)(struct sk_buff *, struct net_device *, struct packet_type *, @@ -137,7 +137,7 @@ struct datalink_proto *register_snap_client(unsigned char *desc, proto = kmalloc(sizeof(*proto), GFP_ATOMIC); if (proto) { - memcpy(proto->type, desc,5); + memcpy(proto->type, desc, 5); proto->rcvfunc = rcvfunc; proto->header_length = 5 + 3; /* snap + 802.2 */ proto->request = snap_request; -- GitLab From fa665ccf01440644a3956ed039e51e1088cd0f15 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 05:45:39 +0000 Subject: [PATCH 3805/4982] ipx: use constant for strings and desciptor Fix compiler warning about non-const format string. Signed-off-by: Stephen Hemminger Acked-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- net/ipx/af_ipx.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 30bd322b798..1627050e29f 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -1975,15 +1975,15 @@ static struct notifier_block ipx_dev_notifier = { extern struct datalink_proto *make_EII_client(void); extern void destroy_EII_client(struct datalink_proto *); -static unsigned char ipx_8022_type = 0xE0; -static unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 }; -static char ipx_EII_err_msg[] __initdata = +static const unsigned char ipx_8022_type = 0xE0; +static const unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 }; +static const char ipx_EII_err_msg[] __initconst = KERN_CRIT "IPX: Unable to register with Ethernet II\n"; -static char ipx_8023_err_msg[] __initdata = +static const char ipx_8023_err_msg[] __initconst = KERN_CRIT "IPX: Unable to register with 802.3\n"; -static char ipx_llc_err_msg[] __initdata = +static const char ipx_llc_err_msg[] __initconst = KERN_CRIT "IPX: Unable to register with 802.2\n"; -static char ipx_snap_err_msg[] __initdata = +static const char ipx_snap_err_msg[] __initconst = KERN_CRIT "IPX: Unable to register with SNAP\n"; static int __init ipx_init(void) -- GitLab From 32f3dde55ba1b28863c0f0611d2c9dcf2d728ec8 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 06:44:02 +0000 Subject: [PATCH 3806/4982] atm: fix non-const printk argument Change printk() argument to fix compiler warning. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/atm/iphase.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index e1c7611e914..78c9736c357 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -977,9 +977,7 @@ static void xdump( u_char* cp, int length, char* prefix ) else pBuf += sprintf( pBuf, "." ); } - sprintf( pBuf, "\n" ); - // SPrint(prntBuf); - printk(prntBuf); + printk("%s\n", prntBuf); count += col; pBuf = prntBuf; } -- GitLab From aec464bbee32e1d67cba0072c50774c5298ef762 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 07:14:14 +0000 Subject: [PATCH 3807/4982] eql: fix non-constant printk warning Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/eql.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/eql.c b/drivers/net/eql.c index 40125694bd9..51ead7941f8 100644 --- a/drivers/net/eql.c +++ b/drivers/net/eql.c @@ -159,7 +159,7 @@ static void eql_timer(unsigned long param) add_timer(&eql->timer); } -static char version[] __initdata = +static const char version[] __initconst = "Equalizer2002: Simon Janes (simon@ncm.com) and David S. Miller (davem@redhat.com)\n"; static const struct net_device_ops eql_netdev_ops = { -- GitLab From c084080151e1de92159f8437fde34b6e5bebe35e Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 20 Mar 2009 09:49:49 +0000 Subject: [PATCH 3808/4982] dsa: set ->iflink on slave interfaces to the ifindex of the parent ..so that we can parse the DSA topology from 'ip link' output: 1: lo: mtu 16436 qdisc noqueue 2: eth0: mtu 1500 qdisc pfifo_fast qlen 1000 3: eth1: mtu 1500 qdisc pfifo_fast qlen 1000 4: lan1@eth0: mtu 1500 qdisc noqueue 5: lan2@eth0: mtu 1500 qdisc noqueue 6: lan3@eth0: mtu 1500 qdisc noqueue 7: lan4@eth0: mtu 1500 qdisc noqueue Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller --- net/dsa/slave.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/net/dsa/slave.c b/net/dsa/slave.c index a68fd79e9ec..99114e5b32e 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -48,6 +48,16 @@ void dsa_slave_mii_bus_init(struct dsa_switch *ds) /* slave device handling ****************************************************/ +static int dsa_slave_init(struct net_device *dev) +{ + struct dsa_slave_priv *p = netdev_priv(dev); + struct net_device *master = p->parent->master_netdev; + + dev->iflink = master->ifindex; + + return 0; +} + static int dsa_slave_open(struct net_device *dev) { struct dsa_slave_priv *p = netdev_priv(dev); @@ -288,6 +298,7 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = { #ifdef CONFIG_NET_DSA_TAG_DSA static const struct net_device_ops dsa_netdev_ops = { + .ndo_init = dsa_slave_init, .ndo_open = dsa_slave_open, .ndo_stop = dsa_slave_close, .ndo_start_xmit = dsa_xmit, @@ -300,6 +311,7 @@ static const struct net_device_ops dsa_netdev_ops = { #endif #ifdef CONFIG_NET_DSA_TAG_EDSA static const struct net_device_ops edsa_netdev_ops = { + .ndo_init = dsa_slave_init, .ndo_open = dsa_slave_open, .ndo_stop = dsa_slave_close, .ndo_start_xmit = edsa_xmit, @@ -312,6 +324,7 @@ static const struct net_device_ops edsa_netdev_ops = { #endif #ifdef CONFIG_NET_DSA_TAG_TRAILER static const struct net_device_ops trailer_netdev_ops = { + .ndo_init = dsa_slave_init, .ndo_open = dsa_slave_open, .ndo_stop = dsa_slave_close, .ndo_start_xmit = trailer_xmit, -- GitLab From 076d3e10a54caa2c148de5732c126c7a31381d48 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 20 Mar 2009 09:50:39 +0000 Subject: [PATCH 3809/4982] dsa: add support for the Marvell 88E6095/6095F switch chips Add support for the Marvell 88E6095/6095F switch chips. These chips are similar to the 88e6131, so we can add the support to mv88e6131.c easily. Thanks to Gary Thomas and Jesper Dangaard Brouer for testing various patches. Signed-off-by: Lennert Buytenhek Tested-by: Gary Thomas Signed-off-by: David S. Miller --- net/dsa/Kconfig | 6 +++--- net/dsa/mv88e6131.c | 22 ++++++++++++++-------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig index 49211b35725..c51b55400dc 100644 --- a/net/dsa/Kconfig +++ b/net/dsa/Kconfig @@ -41,13 +41,13 @@ config NET_DSA_MV88E6XXX_NEED_PPU default n config NET_DSA_MV88E6131 - bool "Marvell 88E6131 ethernet switch chip support" + bool "Marvell 88E6095/6095F/6131 ethernet switch chip support" select NET_DSA_MV88E6XXX select NET_DSA_MV88E6XXX_NEED_PPU select NET_DSA_TAG_DSA ---help--- - This enables support for the Marvell 88E6131 ethernet switch - chip. + This enables support for the Marvell 88E6095/6095F/6131 + ethernet switch chips. config NET_DSA_MV88E6123_61_65 bool "Marvell 88E6123/6161/6165 ethernet switch chip support" diff --git a/net/dsa/mv88e6131.c b/net/dsa/mv88e6131.c index 70fae2444cb..002995721ec 100644 --- a/net/dsa/mv88e6131.c +++ b/net/dsa/mv88e6131.c @@ -1,6 +1,6 @@ /* - * net/dsa/mv88e6131.c - Marvell 88e6131 switch chip support - * Copyright (c) 2008 Marvell Semiconductor + * net/dsa/mv88e6131.c - Marvell 88e6095/6095f/6131 switch chip support + * Copyright (c) 2008-2009 Marvell Semiconductor * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,6 +21,8 @@ static char *mv88e6131_probe(struct mii_bus *bus, int sw_addr) ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03); if (ret >= 0) { ret &= 0xfff0; + if (ret == 0x0950) + return "Marvell 88E6095/88E6095F"; if (ret == 0x1060) return "Marvell 88E6131"; } @@ -36,7 +38,7 @@ static int mv88e6131_switch_reset(struct dsa_switch *ds) /* * Set all ports to the disabled state. */ - for (i = 0; i < 8; i++) { + for (i = 0; i < 11; i++) { ret = REG_READ(REG_PORT(i), 0x04); REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc); } @@ -136,7 +138,7 @@ static int mv88e6131_setup_global(struct dsa_switch *ds) * Clear all trunk masks. */ for (i = 0; i < 8; i++) - REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0xff); + REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0x7ff); /* * Clear all trunk mappings. @@ -159,9 +161,13 @@ static int mv88e6131_setup_port(struct dsa_switch *ds, int p) /* * MAC Forcing register: don't force link, speed, duplex - * or flow control state to any particular values. + * or flow control state to any particular values on physical + * ports, but force the CPU port to 1000 Mb/s full duplex. */ - REG_WRITE(addr, 0x01, 0x0003); + if (p == ds->cpu_port) + REG_WRITE(addr, 0x01, 0x003e); + else + REG_WRITE(addr, 0x01, 0x0003); /* * Port Control: disable Core Tag, disable Drop-on-Lock, @@ -268,7 +274,7 @@ static int mv88e6131_setup(struct dsa_switch *ds) if (ret < 0) return ret; - for (i = 0; i < 6; i++) { + for (i = 0; i < 11; i++) { ret = mv88e6131_setup_port(ds, i); if (ret < 0) return ret; @@ -279,7 +285,7 @@ static int mv88e6131_setup(struct dsa_switch *ds) static int mv88e6131_port_to_phy_addr(int port) { - if (port >= 0 && port != 3 && port <= 7) + if (port >= 0 && port <= 11) return port; return -1; } -- GitLab From e84665c9cb4db963393fafad6fefe5efdd7e4a09 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 20 Mar 2009 09:52:09 +0000 Subject: [PATCH 3810/4982] dsa: add switch chip cascading support The initial version of the DSA driver only supported a single switch chip per network interface, while DSA-capable switch chips can be interconnected to form a tree of switch chips. This patch adds support for multiple switch chips on a network interface. An example topology for a 16-port device with an embedded CPU is as follows: +-----+ +--------+ +--------+ | |eth0 10| switch |9 10| switch | | CPU +----------+ +-------+ | | | | chip 0 | | chip 1 | +-----+ +---++---+ +---++---+ || || || || ||1000baseT ||1000baseT ||ports 1-8 ||ports 9-16 This requires a couple of interdependent changes in the DSA layer: - The dsa platform driver data needs to be extended: there is still only one netdevice per DSA driver instance (eth0 in the example above), but each of the switch chips in the tree needs its own mii_bus device pointer, MII management bus address, and port name array. (include/net/dsa.h) The existing in-tree dsa users need some small changes to deal with this. (arch/arm) - The DSA and Ethertype DSA tagging modules need to be extended to use the DSA device ID field on receive and demultiplex the packet accordingly, and fill in the DSA device ID field on transmit according to which switch chip the packet is heading to. (net/dsa/tag_{dsa,edsa}.c) - The concept of "CPU port", which is the switch chip port that the CPU is connected to (port 10 on switch chip 0 in the example), needs to be extended with the concept of "upstream port", which is the port on the switch chip that will bring us one hop closer to the CPU (port 10 for both switch chips in the example above). - The dsa platform data needs to specify which ports on which switch chips are links to other switch chips, so that we can enable DSA tagging mode on them. (For inter-switch links, we always use non-EtherType DSA tagging, since it has lower overhead. The CPU link uses dsa or edsa tagging depending on what the 'root' switch chip supports.) This is done by specifying "dsa" for the given port in the port array. - The dsa platform data needs to be extended with information on via which port to reach any given switch chip from any given switch chip. This info is specified via the per-switch chip data struct ->rtable[] array, which gives the nexthop ports for each of the other switches in the tree. For the example topology above, the dsa platform data would look something like this: static struct dsa_chip_data sw[2] = { { .mii_bus = &foo, .sw_addr = 1, .port_names[0] = "p1", .port_names[1] = "p2", .port_names[2] = "p3", .port_names[3] = "p4", .port_names[4] = "p5", .port_names[5] = "p6", .port_names[6] = "p7", .port_names[7] = "p8", .port_names[9] = "dsa", .port_names[10] = "cpu", .rtable = (s8 []){ -1, 9, }, }, { .mii_bus = &foo, .sw_addr = 2, .port_names[0] = "p9", .port_names[1] = "p10", .port_names[2] = "p11", .port_names[3] = "p12", .port_names[4] = "p13", .port_names[5] = "p14", .port_names[6] = "p15", .port_names[7] = "p16", .port_names[10] = "dsa", .rtable = (s8 []){ 10, -1, }, }, }, static struct dsa_platform_data pd = { .netdev = &foo, .nr_switches = 2, .sw = sw, }; Signed-off-by: Lennert Buytenhek Tested-by: Gary Thomas Signed-off-by: David S. Miller --- arch/arm/mach-kirkwood/common.c | 5 +- arch/arm/mach-kirkwood/rd88f6281-setup.c | 13 +- arch/arm/mach-orion5x/common.c | 5 +- arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c | 9 +- arch/arm/mach-orion5x/rd88f5181l-ge-setup.c | 10 +- arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c | 10 +- arch/arm/mach-orion5x/wrt350n-v2-setup.c | 9 +- include/net/dsa.h | 42 ++++- net/dsa/dsa.c | 177 ++++++++++++------- net/dsa/dsa_priv.h | 97 ++++++++-- net/dsa/mv88e6060.c | 12 +- net/dsa/mv88e6123_61_65.c | 92 ++++++---- net/dsa/mv88e6131.c | 78 +++++--- net/dsa/slave.c | 25 ++- net/dsa/tag_dsa.c | 30 ++-- net/dsa/tag_edsa.c | 30 ++-- net/dsa/tag_trailer.c | 10 +- 17 files changed, 443 insertions(+), 211 deletions(-) diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c index b3404b7775b..0d2074f51a5 100644 --- a/arch/arm/mach-kirkwood/common.c +++ b/arch/arm/mach-kirkwood/common.c @@ -231,14 +231,17 @@ static struct platform_device kirkwood_switch_device = { void __init kirkwood_ge00_switch_init(struct dsa_platform_data *d, int irq) { + int i; + if (irq != NO_IRQ) { kirkwood_switch_resources[0].start = irq; kirkwood_switch_resources[0].end = irq; kirkwood_switch_device.num_resources = 1; } - d->mii_bus = &kirkwood_ge00_shared.dev; d->netdev = &kirkwood_ge00.dev; + for (i = 0; i < d->nr_chips; i++) + d->chip[i].mii_bus = &kirkwood_ge00_shared.dev; kirkwood_switch_device.dev.platform_data = d; platform_device_register(&kirkwood_switch_device); diff --git a/arch/arm/mach-kirkwood/rd88f6281-setup.c b/arch/arm/mach-kirkwood/rd88f6281-setup.c index 9a0e905d10c..e1c0516c4df 100644 --- a/arch/arm/mach-kirkwood/rd88f6281-setup.c +++ b/arch/arm/mach-kirkwood/rd88f6281-setup.c @@ -75,7 +75,7 @@ static struct mv643xx_eth_platform_data rd88f6281_ge00_data = { .duplex = DUPLEX_FULL, }; -static struct dsa_platform_data rd88f6281_switch_data = { +static struct dsa_chip_data rd88f6281_switch_chip_data = { .port_names[0] = "lan1", .port_names[1] = "lan2", .port_names[2] = "lan3", @@ -83,6 +83,11 @@ static struct dsa_platform_data rd88f6281_switch_data = { .port_names[5] = "cpu", }; +static struct dsa_platform_data rd88f6281_switch_plat_data = { + .nr_chips = 1, + .chip = &rd88f6281_switch_chip_data, +}; + static struct mv643xx_eth_platform_data rd88f6281_ge01_data = { .phy_addr = MV643XX_ETH_PHY_ADDR(11), }; @@ -105,12 +110,12 @@ static void __init rd88f6281_init(void) kirkwood_ge00_init(&rd88f6281_ge00_data); kirkwood_pcie_id(&dev, &rev); if (rev == MV88F6281_REV_A0) { - rd88f6281_switch_data.sw_addr = 10; + rd88f6281_switch_chip_data.sw_addr = 10; kirkwood_ge01_init(&rd88f6281_ge01_data); } else { - rd88f6281_switch_data.port_names[4] = "wan"; + rd88f6281_switch_chip_data.port_names[4] = "wan"; } - kirkwood_ge00_switch_init(&rd88f6281_switch_data, NO_IRQ); + kirkwood_ge00_switch_init(&rd88f6281_switch_plat_data, NO_IRQ); kirkwood_rtc_init(); kirkwood_sata_init(&rd88f6281_sata_data); diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c index 0a623379789..a4ecf625981 100644 --- a/arch/arm/mach-orion5x/common.c +++ b/arch/arm/mach-orion5x/common.c @@ -219,14 +219,17 @@ static struct platform_device orion5x_switch_device = { void __init orion5x_eth_switch_init(struct dsa_platform_data *d, int irq) { + int i; + if (irq != NO_IRQ) { orion5x_switch_resources[0].start = irq; orion5x_switch_resources[0].end = irq; orion5x_switch_device.num_resources = 1; } - d->mii_bus = &orion5x_eth_shared.dev; d->netdev = &orion5x_eth.dev; + for (i = 0; i < d->nr_chips; i++) + d->chip[i].mii_bus = &orion5x_eth_shared.dev; orion5x_switch_device.dev.platform_data = d; platform_device_register(&orion5x_switch_device); diff --git a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c index 15f53235ee3..9c1ca41730b 100644 --- a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c +++ b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c @@ -94,7 +94,7 @@ static struct mv643xx_eth_platform_data rd88f5181l_fxo_eth_data = { .duplex = DUPLEX_FULL, }; -static struct dsa_platform_data rd88f5181l_fxo_switch_data = { +static struct dsa_chip_data rd88f5181l_fxo_switch_chip_data = { .port_names[0] = "lan2", .port_names[1] = "lan1", .port_names[2] = "wan", @@ -103,6 +103,11 @@ static struct dsa_platform_data rd88f5181l_fxo_switch_data = { .port_names[7] = "lan3", }; +static struct dsa_platform_data rd88f5181l_fxo_switch_plat_data = { + .nr_chips = 1, + .chip = &rd88f5181l_fxo_switch_chip_data, +}; + static void __init rd88f5181l_fxo_init(void) { /* @@ -117,7 +122,7 @@ static void __init rd88f5181l_fxo_init(void) */ orion5x_ehci0_init(); orion5x_eth_init(&rd88f5181l_fxo_eth_data); - orion5x_eth_switch_init(&rd88f5181l_fxo_switch_data, NO_IRQ); + orion5x_eth_switch_init(&rd88f5181l_fxo_switch_plat_data, NO_IRQ); orion5x_uart0_init(); orion5x_setup_dev_boot_win(RD88F5181L_FXO_NOR_BOOT_BASE, diff --git a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c index 8ad3934399d..ee1399ff0ce 100644 --- a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c +++ b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c @@ -95,7 +95,7 @@ static struct mv643xx_eth_platform_data rd88f5181l_ge_eth_data = { .duplex = DUPLEX_FULL, }; -static struct dsa_platform_data rd88f5181l_ge_switch_data = { +static struct dsa_chip_data rd88f5181l_ge_switch_chip_data = { .port_names[0] = "lan2", .port_names[1] = "lan1", .port_names[2] = "wan", @@ -104,6 +104,11 @@ static struct dsa_platform_data rd88f5181l_ge_switch_data = { .port_names[7] = "lan3", }; +static struct dsa_platform_data rd88f5181l_ge_switch_plat_data = { + .nr_chips = 1, + .chip = &rd88f5181l_ge_switch_chip_data, +}; + static struct i2c_board_info __initdata rd88f5181l_ge_i2c_rtc = { I2C_BOARD_INFO("ds1338", 0x68), }; @@ -122,7 +127,8 @@ static void __init rd88f5181l_ge_init(void) */ orion5x_ehci0_init(); orion5x_eth_init(&rd88f5181l_ge_eth_data); - orion5x_eth_switch_init(&rd88f5181l_ge_switch_data, gpio_to_irq(8)); + orion5x_eth_switch_init(&rd88f5181l_ge_switch_plat_data, + gpio_to_irq(8)); orion5x_i2c_init(); orion5x_uart0_init(); diff --git a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c index 262e25e4dac..7737cf9a8f5 100644 --- a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c +++ b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c @@ -35,7 +35,7 @@ static struct mv643xx_eth_platform_data rd88f6183ap_ge_eth_data = { .duplex = DUPLEX_FULL, }; -static struct dsa_platform_data rd88f6183ap_ge_switch_data = { +static struct dsa_chip_data rd88f6183ap_ge_switch_chip_data = { .port_names[0] = "lan1", .port_names[1] = "lan2", .port_names[2] = "lan3", @@ -44,6 +44,11 @@ static struct dsa_platform_data rd88f6183ap_ge_switch_data = { .port_names[5] = "cpu", }; +static struct dsa_platform_data rd88f6183ap_ge_switch_plat_data = { + .nr_chips = 1, + .chip = &rd88f6183ap_ge_switch_chip_data, +}; + static struct mtd_partition rd88f6183ap_ge_partitions[] = { { .name = "kernel", @@ -89,7 +94,8 @@ static void __init rd88f6183ap_ge_init(void) */ orion5x_ehci0_init(); orion5x_eth_init(&rd88f6183ap_ge_eth_data); - orion5x_eth_switch_init(&rd88f6183ap_ge_switch_data, gpio_to_irq(3)); + orion5x_eth_switch_init(&rd88f6183ap_ge_switch_plat_data, + gpio_to_irq(3)); spi_register_board_info(rd88f6183ap_ge_spi_slave_info, ARRAY_SIZE(rd88f6183ap_ge_spi_slave_info)); orion5x_spi_init(); diff --git a/arch/arm/mach-orion5x/wrt350n-v2-setup.c b/arch/arm/mach-orion5x/wrt350n-v2-setup.c index cc8f8920086..1b4ad9d5e2e 100644 --- a/arch/arm/mach-orion5x/wrt350n-v2-setup.c +++ b/arch/arm/mach-orion5x/wrt350n-v2-setup.c @@ -106,7 +106,7 @@ static struct mv643xx_eth_platform_data wrt350n_v2_eth_data = { .duplex = DUPLEX_FULL, }; -static struct dsa_platform_data wrt350n_v2_switch_data = { +static struct dsa_chip_data wrt350n_v2_switch_chip_data = { .port_names[0] = "lan2", .port_names[1] = "lan1", .port_names[2] = "wan", @@ -115,6 +115,11 @@ static struct dsa_platform_data wrt350n_v2_switch_data = { .port_names[7] = "lan4", }; +static struct dsa_platform_data wrt350n_v2_switch_plat_data = { + .nr_chips = 1, + .chip = &wrt350n_v2_switch_chip_data, +}; + static void __init wrt350n_v2_init(void) { /* @@ -129,7 +134,7 @@ static void __init wrt350n_v2_init(void) */ orion5x_ehci0_init(); orion5x_eth_init(&wrt350n_v2_eth_data); - orion5x_eth_switch_init(&wrt350n_v2_switch_data, NO_IRQ); + orion5x_eth_switch_init(&wrt350n_v2_switch_plat_data, NO_IRQ); orion5x_uart0_init(); orion5x_setup_dev_boot_win(WRT350N_V2_NOR_BOOT_BASE, diff --git a/include/net/dsa.h b/include/net/dsa.h index 52e97bfca5a..839f768f9e3 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -1,6 +1,6 @@ /* * include/net/dsa.h - Driver for Distributed Switch Architecture switch chips - * Copyright (c) 2008 Marvell Semiconductor + * Copyright (c) 2008-2009 Marvell Semiconductor * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -11,23 +11,47 @@ #ifndef __LINUX_NET_DSA_H #define __LINUX_NET_DSA_H -#define DSA_MAX_PORTS 12 +#define DSA_MAX_SWITCHES 4 +#define DSA_MAX_PORTS 12 + +struct dsa_chip_data { + /* + * How to access the switch configuration registers. + */ + struct device *mii_bus; + int sw_addr; + + /* + * The names of the switch's ports. Use "cpu" to + * designate the switch port that the cpu is connected to, + * "dsa" to indicate that this port is a DSA link to + * another switch, NULL to indicate the port is unused, + * or any other string to indicate this is a physical port. + */ + char *port_names[DSA_MAX_PORTS]; + + /* + * An array (with nr_chips elements) of which element [a] + * indicates which port on this switch should be used to + * send packets to that are destined for switch a. Can be + * NULL if there is only one switch chip. + */ + s8 *rtable; +}; struct dsa_platform_data { /* * Reference to a Linux network interface that connects - * to the switch chip. + * to the root switch chip of the tree. */ struct device *netdev; /* - * How to access the switch configuration registers, and - * the names of the switch ports (use "cpu" to designate - * the switch port that the cpu is connected to). + * Info structs describing each of the switch chips + * connected via this network interface. */ - struct device *mii_bus; - int sw_addr; - char *port_names[DSA_MAX_PORTS]; + int nr_chips; + struct dsa_chip_data *chip; }; extern bool dsa_uses_dsa_tags(void *dsa_ptr); diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 33e99462023..71489f69a42 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -1,6 +1,6 @@ /* * net/dsa/dsa.c - Hardware switch handling - * Copyright (c) 2008 Marvell Semiconductor + * Copyright (c) 2008-2009 Marvell Semiconductor * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -67,12 +67,13 @@ dsa_switch_probe(struct mii_bus *bus, int sw_addr, char **_name) /* basic switch operations **************************************************/ static struct dsa_switch * -dsa_switch_setup(struct device *parent, struct dsa_platform_data *pd, - struct mii_bus *bus, struct net_device *dev) +dsa_switch_setup(struct dsa_switch_tree *dst, int index, + struct device *parent, struct mii_bus *bus) { + struct dsa_chip_data *pd = dst->pd->chip + index; + struct dsa_switch_driver *drv; struct dsa_switch *ds; int ret; - struct dsa_switch_driver *drv; char *name; int i; @@ -81,11 +82,12 @@ dsa_switch_setup(struct device *parent, struct dsa_platform_data *pd, */ drv = dsa_switch_probe(bus, pd->sw_addr, &name); if (drv == NULL) { - printk(KERN_ERR "%s: could not detect attached switch\n", - dev->name); + printk(KERN_ERR "%s[%d]: could not detect attached switch\n", + dst->master_netdev->name, index); return ERR_PTR(-EINVAL); } - printk(KERN_INFO "%s: detected a %s switch\n", dev->name, name); + printk(KERN_INFO "%s[%d]: detected a %s switch\n", + dst->master_netdev->name, index, name); /* @@ -95,18 +97,16 @@ dsa_switch_setup(struct device *parent, struct dsa_platform_data *pd, if (ds == NULL) return ERR_PTR(-ENOMEM); - ds->pd = pd; - ds->master_netdev = dev; - ds->master_mii_bus = bus; - + ds->dst = dst; + ds->index = index; + ds->pd = dst->pd->chip + index; ds->drv = drv; - ds->tag_protocol = drv->tag_protocol; + ds->master_mii_bus = bus; /* * Validate supplied switch configuration. */ - ds->cpu_port = -1; for (i = 0; i < DSA_MAX_PORTS; i++) { char *name; @@ -115,32 +115,28 @@ dsa_switch_setup(struct device *parent, struct dsa_platform_data *pd, continue; if (!strcmp(name, "cpu")) { - if (ds->cpu_port != -1) { + if (dst->cpu_switch != -1) { printk(KERN_ERR "multiple cpu ports?!\n"); ret = -EINVAL; goto out; } - ds->cpu_port = i; + dst->cpu_switch = index; + dst->cpu_port = i; + } else if (!strcmp(name, "dsa")) { + ds->dsa_port_mask |= 1 << i; } else { - ds->valid_port_mask |= 1 << i; + ds->phys_port_mask |= 1 << i; } } - if (ds->cpu_port == -1) { - printk(KERN_ERR "no cpu port?!\n"); - ret = -EINVAL; - goto out; - } - /* - * If we use a tagging format that doesn't have an ethertype - * field, make sure that all packets from this point on get - * sent to the tag format's receive function. (Which will - * discard received packets until we set ds->ports[] below.) + * If the CPU connects to this switch, set the switch tree + * tagging protocol to the preferred tagging format of this + * switch. */ - wmb(); - dev->dsa_ptr = (void *)ds; + if (ds->dst->cpu_switch == index) + ds->dst->tag_protocol = drv->tag_protocol; /* @@ -150,7 +146,7 @@ dsa_switch_setup(struct device *parent, struct dsa_platform_data *pd, if (ret < 0) goto out; - ret = drv->set_addr(ds, dev->dev_addr); + ret = drv->set_addr(ds, dst->master_netdev->dev_addr); if (ret < 0) goto out; @@ -169,18 +165,18 @@ dsa_switch_setup(struct device *parent, struct dsa_platform_data *pd, /* * Create network devices for physical switch ports. */ - wmb(); for (i = 0; i < DSA_MAX_PORTS; i++) { struct net_device *slave_dev; - if (!(ds->valid_port_mask & (1 << i))) + if (!(ds->phys_port_mask & (1 << i))) continue; slave_dev = dsa_slave_create(ds, parent, i, pd->port_names[i]); if (slave_dev == NULL) { - printk(KERN_ERR "%s: can't create dsa slave " - "device for port %d(%s)\n", - dev->name, i, pd->port_names[i]); + printk(KERN_ERR "%s[%d]: can't create dsa " + "slave device for port %d(%s)\n", + dst->master_netdev->name, + index, i, pd->port_names[i]); continue; } @@ -192,7 +188,6 @@ dsa_switch_setup(struct device *parent, struct dsa_platform_data *pd, out_free: mdiobus_free(ds->slave_mii_bus); out: - dev->dsa_ptr = NULL; kfree(ds); return ERR_PTR(ret); } @@ -212,35 +207,42 @@ static void dsa_switch_destroy(struct dsa_switch *ds) */ bool dsa_uses_dsa_tags(void *dsa_ptr) { - struct dsa_switch *ds = dsa_ptr; + struct dsa_switch_tree *dst = dsa_ptr; - return !!(ds->tag_protocol == htons(ETH_P_DSA)); + return !!(dst->tag_protocol == htons(ETH_P_DSA)); } bool dsa_uses_trailer_tags(void *dsa_ptr) { - struct dsa_switch *ds = dsa_ptr; + struct dsa_switch_tree *dst = dsa_ptr; - return !!(ds->tag_protocol == htons(ETH_P_TRAILER)); + return !!(dst->tag_protocol == htons(ETH_P_TRAILER)); } /* link polling *************************************************************/ static void dsa_link_poll_work(struct work_struct *ugly) { - struct dsa_switch *ds; + struct dsa_switch_tree *dst; + int i; + + dst = container_of(ugly, struct dsa_switch_tree, link_poll_work); - ds = container_of(ugly, struct dsa_switch, link_poll_work); + for (i = 0; i < dst->pd->nr_chips; i++) { + struct dsa_switch *ds = dst->ds[i]; - ds->drv->poll_link(ds); - mod_timer(&ds->link_poll_timer, round_jiffies(jiffies + HZ)); + if (ds != NULL && ds->drv->poll_link != NULL) + ds->drv->poll_link(ds); + } + + mod_timer(&dst->link_poll_timer, round_jiffies(jiffies + HZ)); } -static void dsa_link_poll_timer(unsigned long _ds) +static void dsa_link_poll_timer(unsigned long _dst) { - struct dsa_switch *ds = (void *)_ds; + struct dsa_switch_tree *dst = (void *)_dst; - schedule_work(&ds->link_poll_work); + schedule_work(&dst->link_poll_work); } @@ -303,18 +305,14 @@ static int dsa_probe(struct platform_device *pdev) static int dsa_version_printed; struct dsa_platform_data *pd = pdev->dev.platform_data; struct net_device *dev; - struct mii_bus *bus; - struct dsa_switch *ds; + struct dsa_switch_tree *dst; + int i; if (!dsa_version_printed++) printk(KERN_NOTICE "Distributed Switch Architecture " "driver version %s\n", dsa_driver_version); - if (pd == NULL || pd->mii_bus == NULL || pd->netdev == NULL) - return -EINVAL; - - bus = dev_to_mii_bus(pd->mii_bus); - if (bus == NULL) + if (pd == NULL || pd->netdev == NULL) return -EINVAL; dev = dev_to_net_device(pd->netdev); @@ -326,36 +324,79 @@ static int dsa_probe(struct platform_device *pdev) return -EEXIST; } - ds = dsa_switch_setup(&pdev->dev, pd, bus, dev); - if (IS_ERR(ds)) { + dst = kzalloc(sizeof(*dst), GFP_KERNEL); + if (dst == NULL) { dev_put(dev); - return PTR_ERR(ds); + return -ENOMEM; } - if (ds->drv->poll_link != NULL) { - INIT_WORK(&ds->link_poll_work, dsa_link_poll_work); - init_timer(&ds->link_poll_timer); - ds->link_poll_timer.data = (unsigned long)ds; - ds->link_poll_timer.function = dsa_link_poll_timer; - ds->link_poll_timer.expires = round_jiffies(jiffies + HZ); - add_timer(&ds->link_poll_timer); + platform_set_drvdata(pdev, dst); + + dst->pd = pd; + dst->master_netdev = dev; + dst->cpu_switch = -1; + dst->cpu_port = -1; + + for (i = 0; i < pd->nr_chips; i++) { + struct mii_bus *bus; + struct dsa_switch *ds; + + bus = dev_to_mii_bus(pd->chip[i].mii_bus); + if (bus == NULL) { + printk(KERN_ERR "%s[%d]: no mii bus found for " + "dsa switch\n", dev->name, i); + continue; + } + + ds = dsa_switch_setup(dst, i, &pdev->dev, bus); + if (IS_ERR(ds)) { + printk(KERN_ERR "%s[%d]: couldn't create dsa switch " + "instance (error %ld)\n", dev->name, i, + PTR_ERR(ds)); + continue; + } + + dst->ds[i] = ds; + if (ds->drv->poll_link != NULL) + dst->link_poll_needed = 1; } - platform_set_drvdata(pdev, ds); + /* + * If we use a tagging format that doesn't have an ethertype + * field, make sure that all packets from this point on get + * sent to the tag format's receive function. + */ + wmb(); + dev->dsa_ptr = (void *)dst; + + if (dst->link_poll_needed) { + INIT_WORK(&dst->link_poll_work, dsa_link_poll_work); + init_timer(&dst->link_poll_timer); + dst->link_poll_timer.data = (unsigned long)dst; + dst->link_poll_timer.function = dsa_link_poll_timer; + dst->link_poll_timer.expires = round_jiffies(jiffies + HZ); + add_timer(&dst->link_poll_timer); + } return 0; } static int dsa_remove(struct platform_device *pdev) { - struct dsa_switch *ds = platform_get_drvdata(pdev); + struct dsa_switch_tree *dst = platform_get_drvdata(pdev); + int i; - if (ds->drv->poll_link != NULL) - del_timer_sync(&ds->link_poll_timer); + if (dst->link_poll_needed) + del_timer_sync(&dst->link_poll_timer); flush_scheduled_work(); - dsa_switch_destroy(ds); + for (i = 0; i < dst->pd->nr_chips; i++) { + struct dsa_switch *ds = dst->ds[i]; + + if (ds != NULL) + dsa_switch_destroy(ds); + } return 0; } diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 7063378a1eb..41055f33d28 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -1,6 +1,6 @@ /* * net/dsa/dsa_priv.h - Hardware switch handling - * Copyright (c) 2008 Marvell Semiconductor + * Copyright (c) 2008-2009 Marvell Semiconductor * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,42 +19,107 @@ struct dsa_switch { /* - * Configuration data for the platform device that owns - * this dsa switch instance. + * Parent switch tree, and switch index. */ - struct dsa_platform_data *pd; + struct dsa_switch_tree *dst; + int index; /* - * References to network device and mii bus to use. + * Configuration data for this switch. */ - struct net_device *master_netdev; - struct mii_bus *master_mii_bus; + struct dsa_chip_data *pd; /* - * The used switch driver and frame tagging type. + * The used switch driver. */ struct dsa_switch_driver *drv; - __be16 tag_protocol; + + /* + * Reference to mii bus to use. + */ + struct mii_bus *master_mii_bus; /* * Slave mii_bus and devices for the individual ports. */ - int cpu_port; - u32 valid_port_mask; - struct mii_bus *slave_mii_bus; - struct net_device *ports[DSA_MAX_PORTS]; + u32 dsa_port_mask; + u32 phys_port_mask; + struct mii_bus *slave_mii_bus; + struct net_device *ports[DSA_MAX_PORTS]; +}; + +struct dsa_switch_tree { + /* + * Configuration data for the platform device that owns + * this dsa switch tree instance. + */ + struct dsa_platform_data *pd; + + /* + * Reference to network device to use, and which tagging + * protocol to use. + */ + struct net_device *master_netdev; + __be16 tag_protocol; + + /* + * The switch and port to which the CPU is attached. + */ + s8 cpu_switch; + s8 cpu_port; /* * Link state polling. */ - struct work_struct link_poll_work; - struct timer_list link_poll_timer; + int link_poll_needed; + struct work_struct link_poll_work; + struct timer_list link_poll_timer; + + /* + * Data for the individual switch chips. + */ + struct dsa_switch *ds[DSA_MAX_SWITCHES]; }; +static inline bool dsa_is_cpu_port(struct dsa_switch *ds, int p) +{ + return !!(ds->index == ds->dst->cpu_switch && p == ds->dst->cpu_port); +} + +static inline u8 dsa_upstream_port(struct dsa_switch *ds) +{ + struct dsa_switch_tree *dst = ds->dst; + + /* + * If this is the root switch (i.e. the switch that connects + * to the CPU), return the cpu port number on this switch. + * Else return the (DSA) port number that connects to the + * switch that is one hop closer to the cpu. + */ + if (dst->cpu_switch == ds->index) + return dst->cpu_port; + else + return ds->pd->rtable[dst->cpu_switch]; +} + struct dsa_slave_priv { + /* + * The linux network interface corresponding to this + * switch port. + */ struct net_device *dev; + + /* + * Which switch this port is a part of, and the port index + * for this port. + */ struct dsa_switch *parent; - int port; + u8 port; + + /* + * The phylib phy_device pointer for the PHY connected + * to this port. + */ struct phy_device *phy; }; diff --git a/net/dsa/mv88e6060.c b/net/dsa/mv88e6060.c index 85081ae9fe8..83277f463af 100644 --- a/net/dsa/mv88e6060.c +++ b/net/dsa/mv88e6060.c @@ -1,6 +1,6 @@ /* * net/dsa/mv88e6060.c - Driver for Marvell 88e6060 switch chips - * Copyright (c) 2008 Marvell Semiconductor + * Copyright (c) 2008-2009 Marvell Semiconductor * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -81,7 +81,7 @@ static int mv88e6060_switch_reset(struct dsa_switch *ds) /* * Reset the switch. */ - REG_WRITE(REG_GLOBAL, 0x0A, 0xa130); + REG_WRITE(REG_GLOBAL, 0x0a, 0xa130); /* * Wait up to one second for reset to complete. @@ -128,7 +128,7 @@ static int mv88e6060_setup_port(struct dsa_switch *ds, int p) * state to Forwarding. Additionally, if this is the CPU * port, enable Ingress and Egress Trailer tagging mode. */ - REG_WRITE(addr, 0x04, (p == ds->cpu_port) ? 0x4103 : 0x0003); + REG_WRITE(addr, 0x04, dsa_is_cpu_port(ds, p) ? 0x4103 : 0x0003); /* * Port based VLAN map: give each port its own address @@ -138,9 +138,9 @@ static int mv88e6060_setup_port(struct dsa_switch *ds, int p) */ REG_WRITE(addr, 0x06, ((p & 0xf) << 12) | - ((p == ds->cpu_port) ? - ds->valid_port_mask : - (1 << ds->cpu_port))); + (dsa_is_cpu_port(ds, p) ? + ds->phys_port_mask : + (1 << ds->dst->cpu_port))); /* * Port Association Vector: when learning source addresses diff --git a/net/dsa/mv88e6123_61_65.c b/net/dsa/mv88e6123_61_65.c index 10031872221..52faaa21a4d 100644 --- a/net/dsa/mv88e6123_61_65.c +++ b/net/dsa/mv88e6123_61_65.c @@ -1,6 +1,6 @@ /* * net/dsa/mv88e6123_61_65.c - Marvell 88e6123/6161/6165 switch chip support - * Copyright (c) 2008 Marvell Semiconductor + * Copyright (c) 2008-2009 Marvell Semiconductor * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -98,17 +98,17 @@ static int mv88e6123_61_65_setup_global(struct dsa_switch *ds) return ret; /* - * Configure the cpu port, and configure the cpu port as the - * port to which ingress and egress monitor frames are to be - * sent. + * Configure the upstream port, and configure the upstream + * port as the port to which ingress and egress monitor frames + * are to be sent. */ - REG_WRITE(REG_GLOBAL, 0x1a, (ds->cpu_port * 0x1110)); + REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1110)); /* * Disable remote management for now, and set the switch's - * DSA device number to zero. + * DSA device number. */ - REG_WRITE(REG_GLOBAL, 0x1c, 0x0000); + REG_WRITE(REG_GLOBAL, 0x1c, ds->index & 0x1f); /* * Send all frames with destination addresses matching @@ -133,10 +133,17 @@ static int mv88e6123_61_65_setup_global(struct dsa_switch *ds) REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff); /* - * Map all DSA device IDs to the CPU port. + * Program the DSA routing table. */ - for (i = 0; i < 32; i++) - REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | ds->cpu_port); + for (i = 0; i < 32; i++) { + int nexthop; + + nexthop = 0x1f; + if (i != ds->index && i < ds->dst->pd->nr_chips) + nexthop = ds->pd->rtable[i] & 0x1f; + + REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | nexthop); + } /* * Clear all trunk masks. @@ -176,12 +183,18 @@ static int mv88e6123_61_65_setup_global(struct dsa_switch *ds) static int mv88e6123_61_65_setup_port(struct dsa_switch *ds, int p) { int addr = REG_PORT(p); + u16 val; /* * MAC Forcing register: don't force link, speed, duplex - * or flow control state to any particular values. + * or flow control state to any particular values on physical + * ports, but force the CPU port and all DSA ports to 1000 Mb/s + * full duplex. */ - REG_WRITE(addr, 0x01, 0x0003); + if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p)) + REG_WRITE(addr, 0x01, 0x003e); + else + REG_WRITE(addr, 0x01, 0x0003); /* * Do not limit the period of time that this port can be @@ -192,37 +205,50 @@ static int mv88e6123_61_65_setup_port(struct dsa_switch *ds, int p) /* * Port Control: disable Drop-on-Unlock, disable Drop-on-Lock, - * configure the requested (DSA/EDSA) tagging mode if this is - * the CPU port, disable Header mode, enable IGMP/MLD snooping, - * disable VLAN tunneling, determine priority by looking at - * 802.1p and IP priority fields (IP prio has precedence), and - * set STP state to Forwarding. Finally, if this is the CPU - * port, additionally enable forwarding of unknown unicast and - * multicast addresses. - */ - REG_WRITE(addr, 0x04, - (p == ds->cpu_port) ? - (ds->tag_protocol == htons(ETH_P_DSA)) ? - 0x053f : 0x373f : - 0x0433); + * disable Header mode, enable IGMP/MLD snooping, disable VLAN + * tunneling, determine priority by looking at 802.1p and IP + * priority fields (IP prio has precedence), and set STP state + * to Forwarding. + * + * If this is the CPU link, use DSA or EDSA tagging depending + * on which tagging mode was configured. + * + * If this is a link to another switch, use DSA tagging mode. + * + * If this is the upstream port for this switch, enable + * forwarding of unknown unicasts and multicasts. + */ + val = 0x0433; + if (dsa_is_cpu_port(ds, p)) { + if (ds->dst->tag_protocol == htons(ETH_P_EDSA)) + val |= 0x3300; + else + val |= 0x0100; + } + if (ds->dsa_port_mask & (1 << p)) + val |= 0x0100; + if (p == dsa_upstream_port(ds)) + val |= 0x000c; + REG_WRITE(addr, 0x04, val); /* * Port Control 1: disable trunking. Also, if this is the * CPU port, enable learn messages to be sent to this port. */ - REG_WRITE(addr, 0x05, (p == ds->cpu_port) ? 0x8000 : 0x0000); + REG_WRITE(addr, 0x05, dsa_is_cpu_port(ds, p) ? 0x8000 : 0x0000); /* * Port based VLAN map: give each port its own address * database, allow the CPU port to talk to each of the 'real' * ports, and allow each of the 'real' ports to only talk to - * the CPU port. - */ - REG_WRITE(addr, 0x06, - ((p & 0xf) << 12) | - ((p == ds->cpu_port) ? - ds->valid_port_mask : - (1 << ds->cpu_port))); + * the upstream port. + */ + val = (p & 0xf) << 12; + if (dsa_is_cpu_port(ds, p)) + val |= ds->phys_port_mask; + else + val |= 1 << dsa_upstream_port(ds); + REG_WRITE(addr, 0x06, val); /* * Default VLAN ID and priority: don't set a default VLAN diff --git a/net/dsa/mv88e6131.c b/net/dsa/mv88e6131.c index 002995721ec..bb2b41bc854 100644 --- a/net/dsa/mv88e6131.c +++ b/net/dsa/mv88e6131.c @@ -102,17 +102,17 @@ static int mv88e6131_setup_global(struct dsa_switch *ds) REG_WRITE(REG_GLOBAL, 0x19, 0x8100); /* - * Disable ARP mirroring, and configure the cpu port as the - * port to which ingress and egress monitor frames are to be - * sent. + * Disable ARP mirroring, and configure the upstream port as + * the port to which ingress and egress monitor frames are to + * be sent. */ - REG_WRITE(REG_GLOBAL, 0x1a, (ds->cpu_port * 0x1100) | 0x00f0); + REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1100) | 0x00f0); /* * Disable cascade port functionality, and set the switch's - * DSA device number to zero. + * DSA device number. */ - REG_WRITE(REG_GLOBAL, 0x1c, 0xe000); + REG_WRITE(REG_GLOBAL, 0x1c, 0xe000 | (ds->index & 0x1f)); /* * Send all frames with destination addresses matching @@ -129,10 +129,17 @@ static int mv88e6131_setup_global(struct dsa_switch *ds) REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff); /* - * Map all DSA device IDs to the CPU port. + * Program the DSA routing table. */ - for (i = 0; i < 32; i++) - REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | ds->cpu_port); + for (i = 0; i < 32; i++) { + int nexthop; + + nexthop = 0x1f; + if (i != ds->index && i < ds->dst->pd->nr_chips) + nexthop = ds->pd->rtable[i] & 0x1f; + + REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | nexthop); + } /* * Clear all trunk masks. @@ -158,13 +165,15 @@ static int mv88e6131_setup_global(struct dsa_switch *ds) static int mv88e6131_setup_port(struct dsa_switch *ds, int p) { int addr = REG_PORT(p); + u16 val; /* * MAC Forcing register: don't force link, speed, duplex * or flow control state to any particular values on physical - * ports, but force the CPU port to 1000 Mb/s full duplex. + * ports, but force the CPU port and all DSA ports to 1000 Mb/s + * full duplex. */ - if (p == ds->cpu_port) + if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p)) REG_WRITE(addr, 0x01, 0x003e); else REG_WRITE(addr, 0x01, 0x0003); @@ -175,29 +184,40 @@ static int mv88e6131_setup_port(struct dsa_switch *ds, int p) * enable IGMP/MLD snoop, disable DoubleTag, disable VLAN * tunneling, determine priority by looking at 802.1p and * IP priority fields (IP prio has precedence), and set STP - * state to Forwarding. Finally, if this is the CPU port, - * additionally enable DSA tagging and forwarding of unknown - * unicast addresses. + * state to Forwarding. + * + * If this is the upstream port for this switch, enable + * forwarding of unknown unicasts, and enable DSA tagging + * mode. + * + * If this is the link to another switch, use DSA tagging + * mode, but do not enable forwarding of unknown unicasts. */ - REG_WRITE(addr, 0x04, (p == ds->cpu_port) ? 0x0537 : 0x0433); + val = 0x0433; + if (p == dsa_upstream_port(ds)) + val |= 0x0104; + if (ds->dsa_port_mask & (1 << p)) + val |= 0x0100; + REG_WRITE(addr, 0x04, val); /* * Port Control 1: disable trunking. Also, if this is the * CPU port, enable learn messages to be sent to this port. */ - REG_WRITE(addr, 0x05, (p == ds->cpu_port) ? 0x8000 : 0x0000); + REG_WRITE(addr, 0x05, dsa_is_cpu_port(ds, p) ? 0x8000 : 0x0000); /* * Port based VLAN map: give each port its own address * database, allow the CPU port to talk to each of the 'real' * ports, and allow each of the 'real' ports to only talk to - * the CPU port. + * the upstream port. */ - REG_WRITE(addr, 0x06, - ((p & 0xf) << 12) | - ((p == ds->cpu_port) ? - ds->valid_port_mask : - (1 << ds->cpu_port))); + val = (p & 0xf) << 12; + if (dsa_is_cpu_port(ds, p)) + val |= ds->phys_port_mask; + else + val |= 1 << dsa_upstream_port(ds); + REG_WRITE(addr, 0x06, val); /* * Default VLAN ID and priority: don't set a default VLAN @@ -213,13 +233,15 @@ static int mv88e6131_setup_port(struct dsa_switch *ds, int p) * untagged frames on this port, do a destination address * lookup on received packets as usual, don't send a copy * of all transmitted/received frames on this port to the - * CPU, and configure the CPU port number. Also, if this - * is the CPU port, enable forwarding of unknown multicast - * addresses. + * CPU, and configure the upstream port number. + * + * If this is the upstream port for this switch, enable + * forwarding of unknown multicast addresses. */ - REG_WRITE(addr, 0x08, - ((p == ds->cpu_port) ? 0x00c0 : 0x0080) | - ds->cpu_port); + val = 0x0080 | dsa_upstream_port(ds); + if (p == dsa_upstream_port(ds)) + val |= 0x0040; + REG_WRITE(addr, 0x08, val); /* * Rate Control: disable ingress rate limiting. diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 99114e5b32e..ed131181215 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -1,6 +1,6 @@ /* * net/dsa/slave.c - Slave device handling - * Copyright (c) 2008 Marvell Semiconductor + * Copyright (c) 2008-2009 Marvell Semiconductor * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,7 +19,7 @@ static int dsa_slave_phy_read(struct mii_bus *bus, int addr, int reg) { struct dsa_switch *ds = bus->priv; - if (ds->valid_port_mask & (1 << addr)) + if (ds->phys_port_mask & (1 << addr)) return ds->drv->phy_read(ds, addr, reg); return 0xffff; @@ -29,7 +29,7 @@ static int dsa_slave_phy_write(struct mii_bus *bus, int addr, int reg, u16 val) { struct dsa_switch *ds = bus->priv; - if (ds->valid_port_mask & (1 << addr)) + if (ds->phys_port_mask & (1 << addr)) return ds->drv->phy_write(ds, addr, reg, val); return 0; @@ -43,7 +43,7 @@ void dsa_slave_mii_bus_init(struct dsa_switch *ds) ds->slave_mii_bus->write = dsa_slave_phy_write; snprintf(ds->slave_mii_bus->id, MII_BUS_ID_SIZE, "%s:%.2x", ds->master_mii_bus->id, ds->pd->sw_addr); - ds->slave_mii_bus->parent = &(ds->master_mii_bus->dev); + ds->slave_mii_bus->parent = &ds->master_mii_bus->dev; } @@ -51,9 +51,8 @@ void dsa_slave_mii_bus_init(struct dsa_switch *ds) static int dsa_slave_init(struct net_device *dev) { struct dsa_slave_priv *p = netdev_priv(dev); - struct net_device *master = p->parent->master_netdev; - dev->iflink = master->ifindex; + dev->iflink = p->parent->dst->master_netdev->ifindex; return 0; } @@ -61,7 +60,7 @@ static int dsa_slave_init(struct net_device *dev) static int dsa_slave_open(struct net_device *dev) { struct dsa_slave_priv *p = netdev_priv(dev); - struct net_device *master = p->parent->master_netdev; + struct net_device *master = p->parent->dst->master_netdev; int err; if (!(master->flags & IFF_UP)) @@ -99,7 +98,7 @@ out: static int dsa_slave_close(struct net_device *dev) { struct dsa_slave_priv *p = netdev_priv(dev); - struct net_device *master = p->parent->master_netdev; + struct net_device *master = p->parent->dst->master_netdev; dev_mc_unsync(master, dev); dev_unicast_unsync(master, dev); @@ -117,7 +116,7 @@ static int dsa_slave_close(struct net_device *dev) static void dsa_slave_change_rx_flags(struct net_device *dev, int change) { struct dsa_slave_priv *p = netdev_priv(dev); - struct net_device *master = p->parent->master_netdev; + struct net_device *master = p->parent->dst->master_netdev; if (change & IFF_ALLMULTI) dev_set_allmulti(master, dev->flags & IFF_ALLMULTI ? 1 : -1); @@ -128,7 +127,7 @@ static void dsa_slave_change_rx_flags(struct net_device *dev, int change) static void dsa_slave_set_rx_mode(struct net_device *dev) { struct dsa_slave_priv *p = netdev_priv(dev); - struct net_device *master = p->parent->master_netdev; + struct net_device *master = p->parent->dst->master_netdev; dev_mc_sync(master, dev); dev_unicast_sync(master, dev); @@ -137,7 +136,7 @@ static void dsa_slave_set_rx_mode(struct net_device *dev) static int dsa_slave_set_mac_address(struct net_device *dev, void *a) { struct dsa_slave_priv *p = netdev_priv(dev); - struct net_device *master = p->parent->master_netdev; + struct net_device *master = p->parent->dst->master_netdev; struct sockaddr *addr = a; int err; @@ -341,7 +340,7 @@ struct net_device * dsa_slave_create(struct dsa_switch *ds, struct device *parent, int port, char *name) { - struct net_device *master = ds->master_netdev; + struct net_device *master = ds->dst->master_netdev; struct net_device *slave_dev; struct dsa_slave_priv *p; int ret; @@ -356,7 +355,7 @@ dsa_slave_create(struct dsa_switch *ds, struct device *parent, memcpy(slave_dev->dev_addr, master->dev_addr, ETH_ALEN); slave_dev->tx_queue_len = 0; - switch (ds->tag_protocol) { + switch (ds->dst->tag_protocol) { #ifdef CONFIG_NET_DSA_TAG_DSA case htons(ETH_P_DSA): slave_dev->netdev_ops = &dsa_netdev_ops; diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c index 0b8a91ddff4..8fa25bafe6c 100644 --- a/net/dsa/tag_dsa.c +++ b/net/dsa/tag_dsa.c @@ -1,6 +1,6 @@ /* * net/dsa/tag_dsa.c - (Non-ethertype) DSA tagging - * Copyright (c) 2008 Marvell Semiconductor + * Copyright (c) 2008-2009 Marvell Semiconductor * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,7 +36,7 @@ int dsa_xmit(struct sk_buff *skb, struct net_device *dev) * Construct tagged FROM_CPU DSA tag from 802.1q tag. */ dsa_header = skb->data + 2 * ETH_ALEN; - dsa_header[0] = 0x60; + dsa_header[0] = 0x60 | p->parent->index; dsa_header[1] = p->port << 3; /* @@ -57,7 +57,7 @@ int dsa_xmit(struct sk_buff *skb, struct net_device *dev) * Construct untagged FROM_CPU DSA tag. */ dsa_header = skb->data + 2 * ETH_ALEN; - dsa_header[0] = 0x40; + dsa_header[0] = 0x40 | p->parent->index; dsa_header[1] = p->port << 3; dsa_header[2] = 0x00; dsa_header[3] = 0x00; @@ -65,7 +65,7 @@ int dsa_xmit(struct sk_buff *skb, struct net_device *dev) skb->protocol = htons(ETH_P_DSA); - skb->dev = p->parent->master_netdev; + skb->dev = p->parent->dst->master_netdev; dev_queue_xmit(skb); return NETDEV_TX_OK; @@ -78,11 +78,13 @@ out_free: static int dsa_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) { - struct dsa_switch *ds = dev->dsa_ptr; + struct dsa_switch_tree *dst = dev->dsa_ptr; + struct dsa_switch *ds; u8 *dsa_header; + int source_device; int source_port; - if (unlikely(ds == NULL)) + if (unlikely(dst == NULL)) goto out_drop; skb = skb_unshare(skb, GFP_ATOMIC); @@ -98,16 +100,24 @@ static int dsa_rcv(struct sk_buff *skb, struct net_device *dev, dsa_header = skb->data - 2; /* - * Check that frame type is either TO_CPU or FORWARD, and - * that the source device is zero. + * Check that frame type is either TO_CPU or FORWARD. */ - if ((dsa_header[0] & 0xdf) != 0x00 && (dsa_header[0] & 0xdf) != 0xc0) + if ((dsa_header[0] & 0xc0) != 0x00 && (dsa_header[0] & 0xc0) != 0xc0) goto out_drop; /* - * Check that the source port is a registered DSA port. + * Determine source device and port. */ + source_device = dsa_header[0] & 0x1f; source_port = (dsa_header[1] >> 3) & 0x1f; + + /* + * Check that the source device exists and that the source + * port is a registered DSA port. + */ + if (source_device >= dst->pd->nr_chips) + goto out_drop; + ds = dst->ds[source_device]; if (source_port >= DSA_MAX_PORTS || ds->ports[source_port] == NULL) goto out_drop; diff --git a/net/dsa/tag_edsa.c b/net/dsa/tag_edsa.c index 16fcb6d196d..815607bd286 100644 --- a/net/dsa/tag_edsa.c +++ b/net/dsa/tag_edsa.c @@ -1,6 +1,6 @@ /* * net/dsa/tag_edsa.c - Ethertype DSA tagging - * Copyright (c) 2008 Marvell Semiconductor + * Copyright (c) 2008-2009 Marvell Semiconductor * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -45,7 +45,7 @@ int edsa_xmit(struct sk_buff *skb, struct net_device *dev) edsa_header[1] = ETH_P_EDSA & 0xff; edsa_header[2] = 0x00; edsa_header[3] = 0x00; - edsa_header[4] = 0x60; + edsa_header[4] = 0x60 | p->parent->index; edsa_header[5] = p->port << 3; /* @@ -70,7 +70,7 @@ int edsa_xmit(struct sk_buff *skb, struct net_device *dev) edsa_header[1] = ETH_P_EDSA & 0xff; edsa_header[2] = 0x00; edsa_header[3] = 0x00; - edsa_header[4] = 0x40; + edsa_header[4] = 0x40 | p->parent->index; edsa_header[5] = p->port << 3; edsa_header[6] = 0x00; edsa_header[7] = 0x00; @@ -78,7 +78,7 @@ int edsa_xmit(struct sk_buff *skb, struct net_device *dev) skb->protocol = htons(ETH_P_EDSA); - skb->dev = p->parent->master_netdev; + skb->dev = p->parent->dst->master_netdev; dev_queue_xmit(skb); return NETDEV_TX_OK; @@ -91,11 +91,13 @@ out_free: static int edsa_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) { - struct dsa_switch *ds = dev->dsa_ptr; + struct dsa_switch_tree *dst = dev->dsa_ptr; + struct dsa_switch *ds; u8 *edsa_header; + int source_device; int source_port; - if (unlikely(ds == NULL)) + if (unlikely(dst == NULL)) goto out_drop; skb = skb_unshare(skb, GFP_ATOMIC); @@ -111,16 +113,24 @@ static int edsa_rcv(struct sk_buff *skb, struct net_device *dev, edsa_header = skb->data + 2; /* - * Check that frame type is either TO_CPU or FORWARD, and - * that the source device is zero. + * Check that frame type is either TO_CPU or FORWARD. */ - if ((edsa_header[0] & 0xdf) != 0x00 && (edsa_header[0] & 0xdf) != 0xc0) + if ((edsa_header[0] & 0xc0) != 0x00 && (edsa_header[0] & 0xc0) != 0xc0) goto out_drop; /* - * Check that the source port is a registered DSA port. + * Determine source device and port. */ + source_device = edsa_header[0] & 0x1f; source_port = (edsa_header[1] >> 3) & 0x1f; + + /* + * Check that the source device exists and that the source + * port is a registered DSA port. + */ + if (source_device >= dst->pd->nr_chips) + goto out_drop; + ds = dst->ds[source_device]; if (source_port >= DSA_MAX_PORTS || ds->ports[source_port] == NULL) goto out_drop; diff --git a/net/dsa/tag_trailer.c b/net/dsa/tag_trailer.c index a6d959da678..1c3e30c38b8 100644 --- a/net/dsa/tag_trailer.c +++ b/net/dsa/tag_trailer.c @@ -1,6 +1,6 @@ /* * net/dsa/tag_trailer.c - Trailer tag format handling - * Copyright (c) 2008 Marvell Semiconductor + * Copyright (c) 2008-2009 Marvell Semiconductor * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -59,7 +59,7 @@ int trailer_xmit(struct sk_buff *skb, struct net_device *dev) nskb->protocol = htons(ETH_P_TRAILER); - nskb->dev = p->parent->master_netdev; + nskb->dev = p->parent->dst->master_netdev; dev_queue_xmit(nskb); return NETDEV_TX_OK; @@ -68,12 +68,14 @@ int trailer_xmit(struct sk_buff *skb, struct net_device *dev) static int trailer_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) { - struct dsa_switch *ds = dev->dsa_ptr; + struct dsa_switch_tree *dst = dev->dsa_ptr; + struct dsa_switch *ds; u8 *trailer; int source_port; - if (unlikely(ds == NULL)) + if (unlikely(dst == NULL)) goto out_drop; + ds = dst->ds[0]; skb = skb_unshare(skb, GFP_ATOMIC); if (skb == NULL) -- GitLab From bb145a9e28c32a37f35308bb32180b59e358a3a1 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 20 Mar 2009 13:25:39 +0000 Subject: [PATCH 3811/4982] sfc: Pad packets to 33 bytes to prevent TX packet parser lockup The packet parser used in the TX data path for locating checksum fields can lose synchronisation with the TX queue manager when handling packets that look like IPv4 but are too short (17-32 bytes). Work around this by padding to 33 bytes. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/tx.c | 8 ++++++++ drivers/net/sfc/workarounds.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c index b1e19077907..d6681edb701 100644 --- a/drivers/net/sfc/tx.c +++ b/drivers/net/sfc/tx.c @@ -162,6 +162,14 @@ static int efx_enqueue_skb(struct efx_tx_queue *tx_queue, /* Get size of the initial fragment */ len = skb_headlen(skb); + /* Pad if necessary */ + if (EFX_WORKAROUND_15592(efx) && skb->len <= 32) { + EFX_BUG_ON_PARANOID(skb->data_len); + len = 32 + 1; + if (skb_pad(skb, len - skb->len)) + return NETDEV_TX_OK; + } + fill_level = tx_queue->insert_count - tx_queue->old_read_count; q_space = efx->type->txd_ring_mask - 1 - fill_level; diff --git a/drivers/net/sfc/workarounds.h b/drivers/net/sfc/workarounds.h index 78de68f4a95..c821c15445a 100644 --- a/drivers/net/sfc/workarounds.h +++ b/drivers/net/sfc/workarounds.h @@ -36,6 +36,8 @@ #define EFX_WORKAROUND_11482 EFX_WORKAROUND_ALWAYS /* Flush events can take a very long time to appear */ #define EFX_WORKAROUND_11557 EFX_WORKAROUND_ALWAYS +/* Truncated IPv4 packets can confuse the TX packet parser */ +#define EFX_WORKAROUND_15592 EFX_WORKAROUND_ALWAYS /* Spurious parity errors in TSORT buffers */ #define EFX_WORKAROUND_5129 EFX_WORKAROUND_FALCON_A -- GitLab From a9de9a74c69f75e9456cd6b45ecab44ff4c81d04 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 20 Mar 2009 13:26:41 +0000 Subject: [PATCH 3812/4982] sfc: Work around unreliable legacy interrupt status In rare cases, reading the legacy interrupt status register can acknowledge an event queue whose attention flag has not yet been set in the register. Until we service this event queue it will not generate any more interrupts. Therefore, as a secondary check, poll the next slot in each active event queue whose flag is not set. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/falcon.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 2ae51fd6f9c..92ea6147b3f 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -1435,6 +1435,7 @@ static irqreturn_t falcon_legacy_interrupt_b0(int irq, void *dev_id) { struct efx_nic *efx = dev_id; efx_oword_t *int_ker = efx->irq_status.addr; + irqreturn_t result = IRQ_NONE; struct efx_channel *channel; efx_dword_t reg; u32 queues; @@ -1449,23 +1450,24 @@ static irqreturn_t falcon_legacy_interrupt_b0(int irq, void *dev_id) if (unlikely(syserr)) return falcon_fatal_interrupt(efx); - if (queues == 0) - return IRQ_NONE; - - efx->last_irq_cpu = raw_smp_processor_id(); - EFX_TRACE(efx, "IRQ %d on CPU %d status " EFX_DWORD_FMT "\n", - irq, raw_smp_processor_id(), EFX_DWORD_VAL(reg)); - /* Schedule processing of any interrupting queues */ - channel = &efx->channel[0]; - while (queues) { - if (queues & 0x01) + efx_for_each_channel(channel, efx) { + if ((queues & 1) || + falcon_event_present( + falcon_event(channel, channel->eventq_read_ptr))) { efx_schedule_channel(channel); - channel++; + result = IRQ_HANDLED; + } queues >>= 1; } - return IRQ_HANDLED; + if (result == IRQ_HANDLED) { + efx->last_irq_cpu = raw_smp_processor_id(); + EFX_TRACE(efx, "IRQ %d on CPU %d status " EFX_DWORD_FMT "\n", + irq, raw_smp_processor_id(), EFX_DWORD_VAL(reg)); + } + + return result; } -- GitLab From 28c4605826ab24d04102231fc1f3e8577bec376d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 20 Mar 2009 13:26:55 +0000 Subject: [PATCH 3813/4982] sfc: Remove unused private PCI register definitions Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/falcon.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 92ea6147b3f..f42fc60d1df 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -155,13 +155,6 @@ MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold"); /* Dummy SRAM size code */ #define SRM_NB_BSZ_ONCHIP_ONLY (-1) -/* Be nice if these (or equiv.) were in linux/pci_regs.h, but they're not. */ -#define PCI_EXP_DEVCAP_PWR_VAL_LBN 18 -#define PCI_EXP_DEVCAP_PWR_SCL_LBN 26 -#define PCI_EXP_DEVCTL_PAYLOAD_LBN 5 -#define PCI_EXP_LNKSTA_LNK_WID 0x3f0 -#define PCI_EXP_LNKSTA_LNK_WID_LBN 4 - #define FALCON_IS_DUAL_FUNC(efx) \ (falcon_rev(efx) < FALCON_REV_B0) -- GitLab From 85451a951b9511605475fadcc0a8d3aeccefded8 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 20 Mar 2009 13:27:13 +0000 Subject: [PATCH 3814/4982] sfc: Optimise falcon_writel_page_locked() for page > 0 The bug this function works around only applies to the first set of page-mapped registers; other pages can be written without locking. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/falcon_io.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/sfc/falcon_io.h b/drivers/net/sfc/falcon_io.h index c16da3149fa..8883092dae9 100644 --- a/drivers/net/sfc/falcon_io.h +++ b/drivers/net/sfc/falcon_io.h @@ -238,18 +238,21 @@ static inline void falcon_writel_page(struct efx_nic *efx, efx_dword_t *value, /* Write dword to Falcon page-mapped register with an extra lock. * * As for falcon_writel_page(), but for a register that suffers from - * SFC bug 3181. Take out a lock so the BIU collector cannot be - * confused. */ + * SFC bug 3181. If writing to page 0, take out a lock so the BIU + * collector cannot be confused. + */ static inline void falcon_writel_page_locked(struct efx_nic *efx, efx_dword_t *value, unsigned int reg, unsigned int page) { - unsigned long flags; + unsigned long flags = 0; - spin_lock_irqsave(&efx->biu_lock, flags); + if (page == 0) + spin_lock_irqsave(&efx->biu_lock, flags); falcon_writel(efx, value, FALCON_PAGED_REG(page, reg)); - spin_unlock_irqrestore(&efx->biu_lock, flags); + if (page == 0) + spin_unlock_irqrestore(&efx->biu_lock, flags); } #endif /* EFX_FALCON_IO_H */ -- GitLab From 6fb70fd1b57707a5c7b9fb167b7790b2cba13f04 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 20 Mar 2009 13:30:37 +0000 Subject: [PATCH 3815/4982] sfc: Implement adaptive IRQ moderation Calculate a score for each 1000 IRQs: - TX completions are worth 1 point - RX completions are worth 4 if merged using LRO or 2 otherwise Reduce moderation if the score is less than 10000, down to a minimum of 5 us. Increase moderation if the score is more than 20000, up to the specified maximum. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/efx.c | 46 ++++++++++++++++++++++++++++++++++-- drivers/net/sfc/efx.h | 2 +- drivers/net/sfc/ethtool.c | 19 +++++---------- drivers/net/sfc/falcon.c | 16 +++++++++---- drivers/net/sfc/falcon.h | 2 ++ drivers/net/sfc/net_driver.h | 9 +++++++ 6 files changed, 73 insertions(+), 21 deletions(-) diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 8fa68d82c02..6eff9ca6c6c 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -133,6 +133,16 @@ static int phy_flash_cfg; module_param(phy_flash_cfg, int, 0644); MODULE_PARM_DESC(phy_flash_cfg, "Set PHYs into reflash mode initially"); +static unsigned irq_adapt_low_thresh = 10000; +module_param(irq_adapt_low_thresh, uint, 0644); +MODULE_PARM_DESC(irq_adapt_low_thresh, + "Threshold score for reducing IRQ moderation"); + +static unsigned irq_adapt_high_thresh = 20000; +module_param(irq_adapt_high_thresh, uint, 0644); +MODULE_PARM_DESC(irq_adapt_high_thresh, + "Threshold score for increasing IRQ moderation"); + /************************************************************************** * * Utility functions and prototypes @@ -223,6 +233,35 @@ static int efx_poll(struct napi_struct *napi, int budget) rx_packets = efx_process_channel(channel, budget); if (rx_packets < budget) { + struct efx_nic *efx = channel->efx; + + if (channel->used_flags & EFX_USED_BY_RX && + efx->irq_rx_adaptive && + unlikely(++channel->irq_count == 1000)) { + unsigned old_irq_moderation = channel->irq_moderation; + + if (unlikely(channel->irq_mod_score < + irq_adapt_low_thresh)) { + channel->irq_moderation = + max_t(int, + channel->irq_moderation - + FALCON_IRQ_MOD_RESOLUTION, + FALCON_IRQ_MOD_RESOLUTION); + } else if (unlikely(channel->irq_mod_score > + irq_adapt_high_thresh)) { + channel->irq_moderation = + min(channel->irq_moderation + + FALCON_IRQ_MOD_RESOLUTION, + efx->irq_rx_moderation); + } + + if (channel->irq_moderation != old_irq_moderation) + falcon_set_int_moderation(channel); + + channel->irq_count = 0; + channel->irq_mod_score = 0; + } + /* There is no race here; although napi_disable() will * only wait for napi_complete(), this isn't a problem * since efx_channel_processed() will have no effect if @@ -991,7 +1030,7 @@ static int efx_probe_nic(struct efx_nic *efx) efx_set_channels(efx); /* Initialise the interrupt moderation settings */ - efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec); + efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec, true); return 0; } @@ -1188,7 +1227,8 @@ void efx_flush_queues(struct efx_nic *efx) **************************************************************************/ /* Set interrupt moderation parameters */ -void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs) +void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs, + bool rx_adaptive) { struct efx_tx_queue *tx_queue; struct efx_rx_queue *rx_queue; @@ -1198,6 +1238,8 @@ void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs) efx_for_each_tx_queue(tx_queue, efx) tx_queue->channel->irq_moderation = tx_usecs; + efx->irq_rx_adaptive = rx_adaptive; + efx->irq_rx_moderation = rx_usecs; efx_for_each_rx_queue(rx_queue, efx) rx_queue->channel->irq_moderation = rx_usecs; } diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h index 8bde1d2a21d..da157aa74b8 100644 --- a/drivers/net/sfc/efx.h +++ b/drivers/net/sfc/efx.h @@ -52,7 +52,7 @@ extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type); extern void efx_suspend(struct efx_nic *efx); extern void efx_resume(struct efx_nic *efx); extern void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, - int rx_usecs); + int rx_usecs, bool rx_adaptive); extern int efx_request_power(struct efx_nic *efx, int mw, const char *name); extern void efx_hex_dump(const u8 *, unsigned int, const char *); diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 589d1329296..64309f4e8b1 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c @@ -604,7 +604,6 @@ static int efx_ethtool_get_coalesce(struct net_device *net_dev, { struct efx_nic *efx = netdev_priv(net_dev); struct efx_tx_queue *tx_queue; - struct efx_rx_queue *rx_queue; struct efx_channel *channel; memset(coalesce, 0, sizeof(*coalesce)); @@ -622,14 +621,8 @@ static int efx_ethtool_get_coalesce(struct net_device *net_dev, } } - /* Find lowest IRQ moderation across all used RX queues */ - coalesce->rx_coalesce_usecs_irq = ~((u32) 0); - efx_for_each_rx_queue(rx_queue, efx) { - channel = rx_queue->channel; - if (channel->irq_moderation < coalesce->rx_coalesce_usecs_irq) - coalesce->rx_coalesce_usecs_irq = - channel->irq_moderation; - } + coalesce->use_adaptive_rx_coalesce = efx->irq_rx_adaptive; + coalesce->rx_coalesce_usecs_irq = efx->irq_rx_moderation; return 0; } @@ -643,10 +636,9 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev, struct efx_nic *efx = netdev_priv(net_dev); struct efx_channel *channel; struct efx_tx_queue *tx_queue; - unsigned tx_usecs, rx_usecs; + unsigned tx_usecs, rx_usecs, adaptive; - if (coalesce->use_adaptive_rx_coalesce || - coalesce->use_adaptive_tx_coalesce) + if (coalesce->use_adaptive_tx_coalesce) return -EOPNOTSUPP; if (coalesce->rx_coalesce_usecs || coalesce->tx_coalesce_usecs) { @@ -657,6 +649,7 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev, rx_usecs = coalesce->rx_coalesce_usecs_irq; tx_usecs = coalesce->tx_coalesce_usecs_irq; + adaptive = coalesce->use_adaptive_rx_coalesce; /* If the channel is shared only allow RX parameters to be set */ efx_for_each_tx_queue(tx_queue, efx) { @@ -668,7 +661,7 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev, } } - efx_init_irq_moderation(efx, tx_usecs, rx_usecs); + efx_init_irq_moderation(efx, tx_usecs, rx_usecs, adaptive); /* Reset channel to pick up new moderation value. Note that * this may change the value of the irq_moderation field diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index f42fc60d1df..23a1b148d5b 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -729,6 +729,9 @@ static void falcon_handle_tx_event(struct efx_channel *channel, tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, TX_EV_DESC_PTR); tx_ev_q_label = EFX_QWORD_FIELD(*event, TX_EV_Q_LABEL); tx_queue = &efx->tx_queue[tx_ev_q_label]; + channel->irq_mod_score += + (tx_ev_desc_ptr - tx_queue->read_count) & + efx->type->txd_ring_mask; efx_xmit_done(tx_queue, tx_ev_desc_ptr); } else if (EFX_QWORD_FIELD(*event, TX_EV_WQ_FF_FULL)) { /* Rewrite the FIFO write pointer */ @@ -898,6 +901,8 @@ static void falcon_handle_rx_event(struct efx_channel *channel, discard = true; } + channel->irq_mod_score += 2; + /* Handle received packet */ efx_rx_packet(rx_queue, rx_ev_desc_ptr, rx_ev_byte_cnt, checksummed, discard); @@ -1075,14 +1080,15 @@ void falcon_set_int_moderation(struct efx_channel *channel) * program is based at 0. So actual interrupt moderation * achieved is ((x + 1) * res). */ - unsigned int res = 5; - channel->irq_moderation -= (channel->irq_moderation % res); - if (channel->irq_moderation < res) - channel->irq_moderation = res; + channel->irq_moderation -= (channel->irq_moderation % + FALCON_IRQ_MOD_RESOLUTION); + if (channel->irq_moderation < FALCON_IRQ_MOD_RESOLUTION) + channel->irq_moderation = FALCON_IRQ_MOD_RESOLUTION; EFX_POPULATE_DWORD_2(timer_cmd, TIMER_MODE, TIMER_MODE_INT_HLDOFF, TIMER_VAL, - (channel->irq_moderation / res) - 1); + channel->irq_moderation / + FALCON_IRQ_MOD_RESOLUTION - 1); } else { EFX_POPULATE_DWORD_2(timer_cmd, TIMER_MODE, TIMER_MODE_DIS, diff --git a/drivers/net/sfc/falcon.h b/drivers/net/sfc/falcon.h index 7869c3d7438..77f2e0db7ca 100644 --- a/drivers/net/sfc/falcon.h +++ b/drivers/net/sfc/falcon.h @@ -85,6 +85,8 @@ extern void falcon_set_int_moderation(struct efx_channel *channel); extern void falcon_disable_interrupts(struct efx_nic *efx); extern void falcon_fini_interrupt(struct efx_nic *efx); +#define FALCON_IRQ_MOD_RESOLUTION 5 + /* Global Resources */ extern int falcon_probe_nic(struct efx_nic *efx); extern int falcon_probe_resources(struct efx_nic *efx); diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index b81fc727dff..e169e5dcd1e 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -336,6 +336,8 @@ enum efx_rx_alloc_method { * @eventq_read_ptr: Event queue read pointer * @last_eventq_read_ptr: Last event queue read pointer value. * @eventq_magic: Event queue magic value for driver-generated test events + * @irq_count: Number of IRQs since last adaptive moderation decision + * @irq_mod_score: IRQ moderation score * @rx_alloc_level: Watermark based heuristic counter for pushing descriptors * and diagnostic counters * @rx_alloc_push_pages: RX allocation method currently in use for pushing @@ -364,6 +366,9 @@ struct efx_channel { unsigned int last_eventq_read_ptr; unsigned int eventq_magic; + unsigned int irq_count; + unsigned int irq_mod_score; + int rx_alloc_level; int rx_alloc_push_pages; @@ -703,6 +708,8 @@ union efx_multicast_hash { * @membase: Memory BAR value * @biu_lock: BIU (bus interface unit) lock * @interrupt_mode: Interrupt mode + * @irq_rx_adaptive: Adaptive IRQ moderation enabled for RX event queues + * @irq_rx_moderation: IRQ moderation time for RX event queues * @i2c_adap: I2C adapter * @board_info: Board-level information * @state: Device state flag. Serialised by the rtnl_lock. @@ -784,6 +791,8 @@ struct efx_nic { void __iomem *membase; spinlock_t biu_lock; enum efx_int_mode interrupt_mode; + bool irq_rx_adaptive; + unsigned int irq_rx_moderation; struct i2c_adapter i2c_adap; struct efx_board board_info; -- GitLab From 788dee0a954745a182f9341539e5e0fe874b48fc Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:28 +0000 Subject: [PATCH 3816/4982] atm: convert mpc device to using netdev_ops This converts the mpc device to using new netdevice_ops. Compile tested only, needs more than usual review since device was swaping pointers around etc. Signed-off-by: Stephen Hemminger Acked-by: Chas Williams Signed-off-by: David S. Miller --- net/atm/mpc.c | 32 ++++++++++++++------------------ net/atm/mpc.h | 5 ++++- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/net/atm/mpc.c b/net/atm/mpc.c index 039d5cc72c3..e5bf11453a1 100644 --- a/net/atm/mpc.c +++ b/net/atm/mpc.c @@ -286,33 +286,32 @@ static void start_mpc(struct mpoa_client *mpc, struct net_device *dev) { dprintk("mpoa: (%s) start_mpc:\n", mpc->dev->name); - if (dev->hard_start_xmit == NULL) { - printk("mpoa: (%s) start_mpc: dev->hard_start_xmit == NULL, not starting\n", - dev->name); - return; + if (!dev->netdev_ops) + printk("mpoa: (%s) start_mpc not starting\n", dev->name); + else { + mpc->old_ops = dev->netdev_ops; + mpc->new_ops = *mpc->old_ops; + mpc->new_ops.ndo_start_xmit = mpc_send_packet; + dev->netdev_ops = &mpc->new_ops; } - mpc->old_hard_start_xmit = dev->hard_start_xmit; - dev->hard_start_xmit = mpc_send_packet; - - return; } static void stop_mpc(struct mpoa_client *mpc) { - + struct net_device *dev = mpc->dev; dprintk("mpoa: (%s) stop_mpc:", mpc->dev->name); /* Lets not nullify lec device's dev->hard_start_xmit */ - if (mpc->dev->hard_start_xmit != mpc_send_packet) { + if (dev->netdev_ops != &mpc->new_ops) { dprintk(" mpc already stopped, not fatal\n"); return; } dprintk("\n"); - mpc->dev->hard_start_xmit = mpc->old_hard_start_xmit; - mpc->old_hard_start_xmit = NULL; - /* close_shortcuts(mpc); ??? FIXME */ - return; + dev->netdev_ops = mpc->old_ops; + mpc->old_ops = NULL; + + /* close_shortcuts(mpc); ??? FIXME */ } static const char *mpoa_device_type_string(char type) __attribute__ ((unused)); @@ -531,7 +530,6 @@ static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc) */ static int mpc_send_packet(struct sk_buff *skb, struct net_device *dev) { - int retval; struct mpoa_client *mpc; struct ethhdr *eth; int i = 0; @@ -561,9 +559,7 @@ static int mpc_send_packet(struct sk_buff *skb, struct net_device *dev) } non_ip: - retval = mpc->old_hard_start_xmit(skb,dev); - - return retval; + return mpc->old_ops->ndo_start_xmit(skb,dev); } static int atm_mpoa_vcc_attach(struct atm_vcc *vcc, void __user *arg) diff --git a/net/atm/mpc.h b/net/atm/mpc.h index 24c386c35f5..0919a88bbc7 100644 --- a/net/atm/mpc.h +++ b/net/atm/mpc.h @@ -15,7 +15,7 @@ struct mpoa_client { struct mpoa_client *next; struct net_device *dev; /* lec in question */ int dev_num; /* e.g. 2 for lec2 */ - int (*old_hard_start_xmit)(struct sk_buff *skb, struct net_device *dev); + struct atm_vcc *mpoad_vcc; /* control channel to mpoad */ uint8_t mps_ctrl_addr[ATM_ESA_LEN]; /* MPS control ATM address */ uint8_t our_ctrl_addr[ATM_ESA_LEN]; /* MPC's control ATM address */ @@ -31,6 +31,9 @@ struct mpoa_client { uint8_t *mps_macs; /* array of MPS MAC addresses, >=1 */ int number_of_mps_macs; /* number of the above MAC addresses */ struct mpc_parameters parameters; /* parameters for this client */ + + const struct net_device_ops *old_ops; + struct net_device_ops new_ops; }; -- GitLab From dde09758557120cb71fb760cfeaed1b8e27209ef Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:29 +0000 Subject: [PATCH 3817/4982] atm: convert clip driver to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/atm/clip.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/net/atm/clip.c b/net/atm/clip.c index da42fd06b61..3dc0a3a42a5 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c @@ -552,10 +552,13 @@ static int clip_setentry(struct atm_vcc *vcc, __be32 ip) return error; } +static const struct net_device_ops clip_netdev_ops = { + .ndo_start_xmit = clip_start_xmit, +}; + static void clip_setup(struct net_device *dev) { - dev->hard_start_xmit = clip_start_xmit; - /* sg_xmit ... */ + dev->netdev_ops = &clip_netdev_ops; dev->type = ARPHRD_ATM; dev->hard_header_len = RFC1483LLC_LEN; dev->mtu = RFC1626_MTU; @@ -615,7 +618,7 @@ static int clip_device_event(struct notifier_block *this, unsigned long event, } /* ignore non-CLIP devices */ - if (dev->type != ARPHRD_ATM || dev->hard_start_xmit != clip_start_xmit) + if (dev->type != ARPHRD_ATM || dev->netdev_ops != &clip_netdev_ops) return NOTIFY_DONE; switch (event) { -- GitLab From 687c75dcf342f71329bd193af553e96a29581238 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:30 +0000 Subject: [PATCH 3818/4982] infiniband: convert c2 to net_device_ops Convert this driver to new net_device_ops infrastructure. Also use default net_device get-stats infrastructure Signed-off-by: Stephen Hemminger Reviewed-by: Steve Wise Signed-off-by: David S. Miller --- drivers/infiniband/hw/amso1100/c2.c | 41 +++++++++----------- drivers/infiniband/hw/amso1100/c2.h | 2 - drivers/infiniband/hw/amso1100/c2_provider.c | 22 +++++------ 3 files changed, 30 insertions(+), 35 deletions(-) diff --git a/drivers/infiniband/hw/amso1100/c2.c b/drivers/infiniband/hw/amso1100/c2.c index 113f3c03c5b..7d79aa361e2 100644 --- a/drivers/infiniband/hw/amso1100/c2.c +++ b/drivers/infiniband/hw/amso1100/c2.c @@ -76,7 +76,6 @@ static irqreturn_t c2_interrupt(int irq, void *dev_id); static void c2_tx_timeout(struct net_device *netdev); static int c2_change_mtu(struct net_device *netdev, int new_mtu); static void c2_reset(struct c2_port *c2_port); -static struct net_device_stats *c2_get_stats(struct net_device *netdev); static struct pci_device_id c2_pci_table[] = { { PCI_DEVICE(0x18b8, 0xb001) }, @@ -349,7 +348,7 @@ static void c2_tx_clean(struct c2_port *c2_port) elem->hw_desc + C2_TXP_ADDR); __raw_writew((__force u16) cpu_to_be16(TXP_HTXD_DONE), elem->hw_desc + C2_TXP_FLAGS); - c2_port->netstats.tx_dropped++; + c2_port->netdev->stats.tx_dropped++; break; } else { __raw_writew(0, @@ -457,7 +456,7 @@ static void c2_rx_error(struct c2_port *c2_port, struct c2_element *elem) elem->hw_desc + C2_RXP_FLAGS); pr_debug("packet dropped\n"); - c2_port->netstats.rx_dropped++; + c2_port->netdev->stats.rx_dropped++; } static void c2_rx_interrupt(struct net_device *netdev) @@ -532,8 +531,8 @@ static void c2_rx_interrupt(struct net_device *netdev) netif_rx(skb); netdev->last_rx = jiffies; - c2_port->netstats.rx_packets++; - c2_port->netstats.rx_bytes += buflen; + netdev->stats.rx_packets++; + netdev->stats.rx_bytes += buflen; } /* Save where we left off */ @@ -797,8 +796,8 @@ static int c2_xmit_frame(struct sk_buff *skb, struct net_device *netdev) __raw_writew((__force u16) cpu_to_be16(TXP_HTXD_READY), elem->hw_desc + C2_TXP_FLAGS); - c2_port->netstats.tx_packets++; - c2_port->netstats.tx_bytes += maplen; + netdev->stats.tx_packets++; + netdev->stats.tx_bytes += maplen; /* Loop thru additional data fragments and queue them */ if (skb_shinfo(skb)->nr_frags) { @@ -823,8 +822,8 @@ static int c2_xmit_frame(struct sk_buff *skb, struct net_device *netdev) __raw_writew((__force u16) cpu_to_be16(TXP_HTXD_READY), elem->hw_desc + C2_TXP_FLAGS); - c2_port->netstats.tx_packets++; - c2_port->netstats.tx_bytes += maplen; + netdev->stats.tx_packets++; + netdev->stats.tx_bytes += maplen; } } @@ -845,13 +844,6 @@ static int c2_xmit_frame(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_OK; } -static struct net_device_stats *c2_get_stats(struct net_device *netdev) -{ - struct c2_port *c2_port = netdev_priv(netdev); - - return &c2_port->netstats; -} - static void c2_tx_timeout(struct net_device *netdev) { struct c2_port *c2_port = netdev_priv(netdev); @@ -880,6 +872,16 @@ static int c2_change_mtu(struct net_device *netdev, int new_mtu) return ret; } +static const struct net_device_ops c2_netdev = { + .ndo_open = c2_up, + .ndo_stop = c2_down, + .ndo_start_xmit = c2_xmit_frame, + .ndo_tx_timeout = c2_tx_timeout, + .ndo_change_mtu = c2_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + /* Initialize network device */ static struct net_device *c2_devinit(struct c2_dev *c2dev, void __iomem * mmio_addr) @@ -894,12 +896,7 @@ static struct net_device *c2_devinit(struct c2_dev *c2dev, SET_NETDEV_DEV(netdev, &c2dev->pcidev->dev); - netdev->open = c2_up; - netdev->stop = c2_down; - netdev->hard_start_xmit = c2_xmit_frame; - netdev->get_stats = c2_get_stats; - netdev->tx_timeout = c2_tx_timeout; - netdev->change_mtu = c2_change_mtu; + netdev->netdev_ops = &c2_netdev; netdev->watchdog_timeo = C2_TX_TIMEOUT; netdev->irq = c2dev->pcidev->irq; diff --git a/drivers/infiniband/hw/amso1100/c2.h b/drivers/infiniband/hw/amso1100/c2.h index d12a24a84fd..f7ff66f9836 100644 --- a/drivers/infiniband/hw/amso1100/c2.h +++ b/drivers/infiniband/hw/amso1100/c2.h @@ -369,8 +369,6 @@ struct c2_port { unsigned long mem_size; u32 rx_buf_size; - - struct net_device_stats netstats; }; /* diff --git a/drivers/infiniband/hw/amso1100/c2_provider.c b/drivers/infiniband/hw/amso1100/c2_provider.c index 5119d650818..f1948fad85d 100644 --- a/drivers/infiniband/hw/amso1100/c2_provider.c +++ b/drivers/infiniband/hw/amso1100/c2_provider.c @@ -708,26 +708,27 @@ static int c2_pseudo_xmit_frame(struct sk_buff *skb, struct net_device *netdev) static int c2_pseudo_change_mtu(struct net_device *netdev, int new_mtu) { - int ret = 0; - if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) return -EINVAL; netdev->mtu = new_mtu; /* TODO: Tell rnic about new rmda interface mtu */ - return ret; + return 0; } +static const struct net_device_ops c2_pseudo_netdev_ops = { + .ndo_open = c2_pseudo_up, + .ndo_stop = c2_pseudo_down, + .ndo_start_xmit = c2_pseudo_xmit_frame, + .ndo_change_mtu = c2_pseudo_change_mtu, + .ndo_validate_addr = eth_validate_addr, +}; + static void setup(struct net_device *netdev) { - netdev->open = c2_pseudo_up; - netdev->stop = c2_pseudo_down; - netdev->hard_start_xmit = c2_pseudo_xmit_frame; - netdev->get_stats = NULL; - netdev->tx_timeout = NULL; - netdev->set_mac_address = NULL; - netdev->change_mtu = c2_pseudo_change_mtu; + netdev->netdev_ops = &c2_pseudo_netdev_ops; + netdev->watchdog_timeo = 0; netdev->type = ARPHRD_ETHER; netdev->mtu = 1500; @@ -735,7 +736,6 @@ static void setup(struct net_device *netdev) netdev->addr_len = ETH_ALEN; netdev->tx_queue_len = 0; netdev->flags |= IFF_NOARP; - return; } static struct net_device *c2_pseudo_netdev_init(struct c2_dev *c2dev) -- GitLab From d0929553bebcac828b612e7d6d239559e08feaf4 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:31 +0000 Subject: [PATCH 3819/4982] infiniband: convert nes driver to net_device_ops Also, removed unnecessary memset() since alloc_netdev returns zeroed memory. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/infiniband/hw/nes/nes_nic.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index f5484ad1279..ae8c6888b53 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -1568,6 +1568,19 @@ static void nes_netdev_vlan_rx_register(struct net_device *netdev, struct vlan_g spin_unlock_irqrestore(&nesadapter->phy_lock, flags); } +static const struct net_device_ops nes_netdev_ops = { + .ndo_open = nes_netdev_open, + .ndo_stop = nes_netdev_stop, + .ndo_start_xmit = nes_netdev_start_xmit, + .ndo_get_stats = nes_netdev_get_stats, + .ndo_tx_timeout = nes_netdev_tx_timeout, + .ndo_set_mac_address = nes_netdev_set_mac_address, + .ndo_set_multicast_list = nes_netdev_set_multicast_list, + .ndo_change_mtu = nes_netdev_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_vlan_rx_register = nes_netdev_vlan_rx_register, +}; /** * nes_netdev_init - initialize network device @@ -1593,17 +1606,6 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, SET_NETDEV_DEV(netdev, &nesdev->pcidev->dev); - nesvnic = netdev_priv(netdev); - memset(nesvnic, 0, sizeof(*nesvnic)); - - netdev->open = nes_netdev_open; - netdev->stop = nes_netdev_stop; - netdev->hard_start_xmit = nes_netdev_start_xmit; - netdev->get_stats = nes_netdev_get_stats; - netdev->tx_timeout = nes_netdev_tx_timeout; - netdev->set_mac_address = nes_netdev_set_mac_address; - netdev->set_multicast_list = nes_netdev_set_multicast_list; - netdev->change_mtu = nes_netdev_change_mtu; netdev->watchdog_timeo = NES_TX_TIMEOUT; netdev->irq = nesdev->pcidev->irq; netdev->mtu = ETH_DATA_LEN; @@ -1611,14 +1613,15 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, netdev->addr_len = ETH_ALEN; netdev->type = ARPHRD_ETHER; netdev->features = NETIF_F_HIGHDMA; + netdev->netdev_ops = &nes_netdev_ops; netdev->ethtool_ops = &nes_ethtool_ops; netif_napi_add(netdev, &nesvnic->napi, nes_netdev_poll, 128); nes_debug(NES_DBG_INIT, "Enabling VLAN Insert/Delete.\n"); netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - netdev->vlan_rx_register = nes_netdev_vlan_rx_register; netdev->features |= NETIF_F_LLTX; /* Fill in the port structure */ + nesvnic = netdev_priv(netdev); nesvnic->netdev = netdev; nesvnic->nesdev = nesdev; nesvnic->msg_enable = netif_msg_init(debug, default_msg); -- GitLab From fe8114e8e1d15ba07ddcaebc4741957a1546f307 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:32 +0000 Subject: [PATCH 3820/4982] infiniband: convert ipoib to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/infiniband/ulp/ipoib/ipoib_main.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 0bd2a4ff084..ca837b0a889 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -1016,18 +1016,22 @@ static void ipoib_lro_setup(struct ipoib_dev_priv *priv) priv->lro.lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY; } +static const struct net_device_ops ipoib_netdev_ops = { + .ndo_open = ipoib_open, + .ndo_stop = ipoib_stop, + .ndo_change_mtu = ipoib_change_mtu, + .ndo_start_xmit = ipoib_start_xmit, + .ndo_tx_timeout = ipoib_timeout, + .ndo_set_multicast_list = ipoib_set_mcast_list, + .ndo_neigh_setup = ipoib_neigh_setup_dev, +}; + static void ipoib_setup(struct net_device *dev) { struct ipoib_dev_priv *priv = netdev_priv(dev); - dev->open = ipoib_open; - dev->stop = ipoib_stop; - dev->change_mtu = ipoib_change_mtu; - dev->hard_start_xmit = ipoib_start_xmit; - dev->tx_timeout = ipoib_timeout; + dev->netdev_ops = &ipoib_netdev_ops; dev->header_ops = &ipoib_header_ops; - dev->set_multicast_list = ipoib_set_mcast_list; - dev->neigh_setup = ipoib_neigh_setup_dev; ipoib_set_ethtool_ops(dev); -- GitLab From 92bcd4fe9a63e8785a4f6ba4262ee601c271a70b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:33 +0000 Subject: [PATCH 3821/4982] irda: net_device_ops ioctl fix Need to reference net_device_ops not old pointer. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/irda/irda_device.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c index ea319e3ddc1..bf92e147344 100644 --- a/net/irda/irda_device.c +++ b/net/irda/irda_device.c @@ -149,13 +149,14 @@ int irda_device_is_receiving(struct net_device *dev) IRDA_DEBUG(2, "%s()\n", __func__); - if (!dev->do_ioctl) { + if (!dev->netdev_ops->ndo_do_ioctl) { IRDA_ERROR("%s: do_ioctl not impl. by device driver\n", __func__); return -1; } - ret = dev->do_ioctl(dev, (struct ifreq *) &req, SIOCGRECEIVING); + ret = (dev->netdev_ops->ndo_do_ioctl)(dev, (struct ifreq *) &req, + SIOCGRECEIVING); if (ret < 0) return ret; -- GitLab From 9cc8ba783d56b36259b2d610e97bcda8a6fe3b02 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:34 +0000 Subject: [PATCH 3822/4982] irlan: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/irda/irlan/irlan_eth.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c index 05112be9956..724bcf951b8 100644 --- a/net/irda/irlan/irlan_eth.c +++ b/net/irda/irlan/irlan_eth.c @@ -45,6 +45,16 @@ static int irlan_eth_xmit(struct sk_buff *skb, struct net_device *dev); static void irlan_eth_set_multicast_list( struct net_device *dev); static struct net_device_stats *irlan_eth_get_stats(struct net_device *dev); +static const struct net_device_ops irlan_eth_netdev_ops = { + .ndo_open = irlan_eth_open, + .ndo_stop = irlan_eth_close, + .ndo_start_xmit = irlan_eth_xmit, + .ndo_get_stats = irlan_eth_get_stats, + .ndo_set_multicast_list = irlan_eth_set_multicast_list, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, +}; + /* * Function irlan_eth_setup (dev) * @@ -53,14 +63,11 @@ static struct net_device_stats *irlan_eth_get_stats(struct net_device *dev); */ static void irlan_eth_setup(struct net_device *dev) { - dev->open = irlan_eth_open; - dev->stop = irlan_eth_close; - dev->hard_start_xmit = irlan_eth_xmit; - dev->get_stats = irlan_eth_get_stats; - dev->set_multicast_list = irlan_eth_set_multicast_list; + ether_setup(dev); + + dev->netdev_ops = &irlan_eth_netdev_ops; dev->destructor = free_netdev; - ether_setup(dev); /* * Lets do all queueing in IrTTP instead of this device driver. -- GitLab From d36733afd9b65546e1fe0def5d50d8c4519ee452 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:35 +0000 Subject: [PATCH 3823/4982] irda: convert irda_usb to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/irda/irda-usb.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index 3a22dc41b65..006ba23110d 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -1401,6 +1401,14 @@ static inline void irda_usb_init_qos(struct irda_usb_cb *self) } /*------------------------------------------------------------------*/ +static const struct net_device_ops irda_usb_netdev_ops = { + .ndo_open = irda_usb_net_open, + .ndo_stop = irda_usb_net_close, + .ndo_do_ioctl = irda_usb_net_ioctl, + .ndo_start_xmit = irda_usb_hard_xmit, + .ndo_tx_timeout = irda_usb_net_timeout, +}; + /* * Initialise the network side of the irda-usb instance * Called when a new USB instance is registered in irda_usb_probe() @@ -1411,15 +1419,9 @@ static inline int irda_usb_open(struct irda_usb_cb *self) IRDA_DEBUG(1, "%s()\n", __func__); - irda_usb_init_qos(self); + netdev->netdev_ops = &irda_usb_netdev_ops; - /* Override the network functions we need to use */ - netdev->hard_start_xmit = irda_usb_hard_xmit; - netdev->tx_timeout = irda_usb_net_timeout; - netdev->watchdog_timeo = 250*HZ/1000; /* 250 ms > USB timeout */ - netdev->open = irda_usb_net_open; - netdev->stop = irda_usb_net_close; - netdev->do_ioctl = irda_usb_net_ioctl; + irda_usb_init_qos(self); return register_netdev(netdev); } -- GitLab From ddc2a92d34ba20b47e1856375c68d25f51e86f53 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:36 +0000 Subject: [PATCH 3824/4982] irda: convert mcs driver to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/irda/mcs7780.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c index 85e88daab21..fac504d0cfd 100644 --- a/drivers/net/irda/mcs7780.c +++ b/drivers/net/irda/mcs7780.c @@ -873,6 +873,13 @@ static int mcs_hard_xmit(struct sk_buff *skb, struct net_device *ndev) return ret; } +static const struct net_device_ops mcs_netdev_ops = { + .ndo_open = mcs_net_open, + .ndo_stop = mcs_net_close, + .ndo_start_xmit = mcs_hard_xmit, + .ndo_do_ioctl = mcs_net_ioctl, +}; + /* * This function is called by the USB subsystem for each new device in the * system. Need to verify the device and if it is, then start handling it. @@ -919,11 +926,7 @@ static int mcs_probe(struct usb_interface *intf, /* Speed change work initialisation*/ INIT_WORK(&mcs->work, mcs_speed_work); - /* Override the network functions we need to use */ - ndev->hard_start_xmit = mcs_hard_xmit; - ndev->open = mcs_net_open; - ndev->stop = mcs_net_close; - ndev->do_ioctl = mcs_net_ioctl; + ndev->netdev_ops = &mcs_netdev_ops; if (!intf->cur_altsetting) goto error2; -- GitLab From 66ee279ff2747bd23f54886369133b1086b87252 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:37 +0000 Subject: [PATCH 3825/4982] stir4200: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/irda/stir4200.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c index 8b1658c6c92..8e5e45caf2f 100644 --- a/drivers/net/irda/stir4200.c +++ b/drivers/net/irda/stir4200.c @@ -1007,6 +1007,13 @@ static int stir_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) return ret; } +static const struct net_device_ops stir_netdev_ops = { + .ndo_open = stir_net_open, + .ndo_stop = stir_net_close, + .ndo_start_xmit = stir_hard_xmit, + .ndo_do_ioctl = stir_net_ioctl, +}; + /* * This routine is called by the USB subsystem for each new device * in the system. We need to check if the device is ours, and in @@ -1054,10 +1061,7 @@ static int stir_probe(struct usb_interface *intf, irda_qos_bits_to_value(&stir->qos); /* Override the network functions we need to use */ - net->hard_start_xmit = stir_hard_xmit; - net->open = stir_net_open; - net->stop = stir_net_close; - net->do_ioctl = stir_net_ioctl; + net->netdev_ops = &stir_netdev_ops; ret = register_netdev(net); if (ret != 0) -- GitLab From 4113a1a672e5b3f03fc99e7240d4c47e689af2c6 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:38 +0000 Subject: [PATCH 3826/4982] irda: convert w83977af_ir to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/irda/w83977af_ir.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c index dc0a2e4d830..d0883835b0c 100644 --- a/drivers/net/irda/w83977af_ir.c +++ b/drivers/net/irda/w83977af_ir.c @@ -140,6 +140,13 @@ static void __exit w83977af_cleanup(void) } } +static const struct net_device_ops w83977_netdev_ops = { + .ndo_open = w83977af_net_open, + .ndo_stop = w83977af_net_close, + .ndo_start_xmit = w83977af_hard_xmit, + .ndo_do_ioctl = w83977af_net_ioctl, +}; + /* * Function w83977af_open (iobase, irq) * @@ -231,11 +238,7 @@ static int w83977af_open(int i, unsigned int iobase, unsigned int irq, self->rx_buff.data = self->rx_buff.head; self->netdev = dev; - /* Override the network functions we need to use */ - dev->hard_start_xmit = w83977af_hard_xmit; - dev->open = w83977af_net_open; - dev->stop = w83977af_net_close; - dev->do_ioctl = w83977af_net_ioctl; + dev->netdev_ops = &w83977_netdev_ops; err = register_netdev(dev); if (err) { -- GitLab From c279b8c996e99a3fca7806986415263f840b2fa1 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:39 +0000 Subject: [PATCH 3827/4982] irda: convert nsc_ircc driver to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/irda/nsc-ircc.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c index 61e509cb712..45fd9c1eb34 100644 --- a/drivers/net/irda/nsc-ircc.c +++ b/drivers/net/irda/nsc-ircc.c @@ -331,6 +331,20 @@ static void __exit nsc_ircc_cleanup(void) pnp_registered = 0; } +static const struct net_device_ops nsc_ircc_sir_ops = { + .ndo_open = nsc_ircc_net_open, + .ndo_stop = nsc_ircc_net_close, + .ndo_start_xmit = nsc_ircc_hard_xmit_sir, + .ndo_do_ioctl = nsc_ircc_net_ioctl, +}; + +static const struct net_device_ops nsc_ircc_fir_ops = { + .ndo_open = nsc_ircc_net_open, + .ndo_stop = nsc_ircc_net_close, + .ndo_start_xmit = nsc_ircc_hard_xmit_fir, + .ndo_do_ioctl = nsc_ircc_net_ioctl, +}; + /* * Function nsc_ircc_open (iobase, irq) * @@ -441,10 +455,7 @@ static int __init nsc_ircc_open(chipio_t *info) self->tx_fifo.tail = self->tx_buff.head; /* Override the network functions we need to use */ - dev->hard_start_xmit = nsc_ircc_hard_xmit_sir; - dev->open = nsc_ircc_net_open; - dev->stop = nsc_ircc_net_close; - dev->do_ioctl = nsc_ircc_net_ioctl; + dev->netdev_ops = &nsc_ircc_sir_ops; err = register_netdev(dev); if (err) { @@ -1320,12 +1331,12 @@ static __u8 nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 speed) switch_bank(iobase, BANK0); if (speed > 115200) { /* Install FIR xmit handler */ - dev->hard_start_xmit = nsc_ircc_hard_xmit_fir; + dev->netdev_ops = &nsc_ircc_fir_ops; ier = IER_SFIF_IE; nsc_ircc_dma_receive(self); } else { /* Install SIR xmit handler */ - dev->hard_start_xmit = nsc_ircc_hard_xmit_sir; + dev->netdev_ops = &nsc_ircc_sir_ops; ier = IER_RXHDL_IE; } /* Set our current interrupt mask */ -- GitLab From 2d44a22254c1c4ad35a58e6d9d15a547d8841efc Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:40 +0000 Subject: [PATCH 3828/4982] irda: convert ali driver to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/irda/ali-ircc.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c index 17779f9bffc..ad179558002 100644 --- a/drivers/net/irda/ali-ircc.c +++ b/drivers/net/irda/ali-ircc.c @@ -259,6 +259,20 @@ static void __exit ali_ircc_cleanup(void) IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __func__); } +static const struct net_device_ops ali_ircc_sir_ops = { + .ndo_open = ali_ircc_net_open, + .ndo_stop = ali_ircc_net_close, + .ndo_start_xmit = ali_ircc_sir_hard_xmit, + .ndo_do_ioctl = ali_ircc_net_ioctl, +}; + +static const struct net_device_ops ali_ircc_fir_ops = { + .ndo_open = ali_ircc_net_open, + .ndo_stop = ali_ircc_net_close, + .ndo_start_xmit = ali_ircc_fir_hard_xmit, + .ndo_do_ioctl = ali_ircc_net_ioctl, +}; + /* * Function ali_ircc_open (int i, chipio_t *inf) * @@ -361,10 +375,7 @@ static int ali_ircc_open(int i, chipio_t *info) self->tx_fifo.tail = self->tx_buff.head; /* Override the network functions we need to use */ - dev->hard_start_xmit = ali_ircc_sir_hard_xmit; - dev->open = ali_ircc_net_open; - dev->stop = ali_ircc_net_close; - dev->do_ioctl = ali_ircc_net_ioctl; + dev->netdev_ops = &ali_ircc_sir_ops; err = register_netdev(dev); if (err) { @@ -974,7 +985,7 @@ static void ali_ircc_change_speed(struct ali_ircc_cb *self, __u32 baud) ali_ircc_fir_change_speed(self, baud); /* Install FIR xmit handler*/ - dev->hard_start_xmit = ali_ircc_fir_hard_xmit; + dev->netdev_ops = &ali_ircc_fir_ops; /* Enable Interuupt */ self->ier = IER_EOM; // benjamin 2000/11/20 07:24PM @@ -988,7 +999,7 @@ static void ali_ircc_change_speed(struct ali_ircc_cb *self, __u32 baud) ali_ircc_sir_change_speed(self, baud); /* Install SIR xmit handler*/ - dev->hard_start_xmit = ali_ircc_sir_hard_xmit; + dev->netdev_ops = &ali_ircc_sir_ops; } -- GitLab From 30a5d7f7e3c77e3b00b8c981b7af4e5adc331353 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:41 +0000 Subject: [PATCH 3829/4982] irda: convert vlsi driver to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/irda/vlsi_ir.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c index 723c4588c80..1243bc8e003 100644 --- a/drivers/net/irda/vlsi_ir.c +++ b/drivers/net/irda/vlsi_ir.c @@ -1573,6 +1573,14 @@ static int vlsi_close(struct net_device *ndev) return 0; } +static const struct net_device_ops vlsi_netdev_ops = { + .ndo_open = vlsi_open, + .ndo_stop = vlsi_close, + .ndo_start_xmit = vlsi_hard_start_xmit, + .ndo_do_ioctl = vlsi_ioctl, + .ndo_tx_timeout = vlsi_tx_timeout, +}; + static int vlsi_irda_init(struct net_device *ndev) { vlsi_irda_dev_t *idev = netdev_priv(ndev); @@ -1608,11 +1616,7 @@ static int vlsi_irda_init(struct net_device *ndev) ndev->flags |= IFF_PORTSEL | IFF_AUTOMEDIA; ndev->if_port = IF_PORT_UNKNOWN; - ndev->open = vlsi_open; - ndev->stop = vlsi_close; - ndev->hard_start_xmit = vlsi_hard_start_xmit; - ndev->do_ioctl = vlsi_ioctl; - ndev->tx_timeout = vlsi_tx_timeout; + ndev->netdev_ops = &vlsi_netdev_ops; ndev->watchdog_timeo = 500*HZ/1000; /* max. allowed turn time for IrLAP */ SET_NETDEV_DEV(ndev, &pdev->dev); -- GitLab From 02087be61af0e48eae42566d3c5783f2f44337c8 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:42 +0000 Subject: [PATCH 3830/4982] irda: convert smsc driver to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/irda/smsc-ircc2.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c index dd73cce1099..59d79807b4d 100644 --- a/drivers/net/irda/smsc-ircc2.c +++ b/drivers/net/irda/smsc-ircc2.c @@ -486,6 +486,26 @@ static int __init smsc_ircc_init(void) return ret; } +static int smsc_ircc_net_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct smsc_ircc_cb *self = netdev_priv(dev); + + if (self->io.speed > 115200) + return smsc_ircc_hard_xmit_fir(skb, dev); + else + return smsc_ircc_hard_xmit_sir(skb, dev); +} + +static const struct net_device_ops smsc_ircc_netdev_ops = { + .ndo_open = smsc_ircc_net_open, + .ndo_stop = smsc_ircc_net_close, + .ndo_do_ioctl = smsc_ircc_net_ioctl, + .ndo_start_xmit = smsc_ircc_net_xmit, +#if SMSC_IRCC2_C_NET_TIMEOUT + .ndo_tx_timeout = smsc_ircc_timeout, +#endif +}; + /* * Function smsc_ircc_open (firbase, sirbase, dma, irq) * @@ -519,14 +539,10 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u goto err_out1; } - dev->hard_start_xmit = smsc_ircc_hard_xmit_sir; #if SMSC_IRCC2_C_NET_TIMEOUT - dev->tx_timeout = smsc_ircc_timeout; dev->watchdog_timeo = HZ * 2; /* Allow enough time for speed change */ #endif - dev->open = smsc_ircc_net_open; - dev->stop = smsc_ircc_net_close; - dev->do_ioctl = smsc_ircc_net_ioctl; + dev->netdev_ops = &smsc_ircc_netdev_ops; self = netdev_priv(dev); self->netdev = dev; @@ -995,9 +1011,6 @@ static void smsc_ircc_fir_start(struct smsc_ircc_cb *self) /* Reset everything */ - /* Install FIR transmit handler */ - dev->hard_start_xmit = smsc_ircc_hard_xmit_fir; - /* Clear FIFO */ outb(inb(fir_base + IRCC_LCR_A) | IRCC_LCR_A_FIFO_RESET, fir_base + IRCC_LCR_A); @@ -1894,7 +1907,6 @@ static void smsc_ircc_sir_start(struct smsc_ircc_cb *self) IRDA_ASSERT(self != NULL, return;); dev = self->netdev; IRDA_ASSERT(dev != NULL, return;); - dev->hard_start_xmit = &smsc_ircc_hard_xmit_sir; fir_base = self->io.fir_base; sir_base = self->io.sir_base; -- GitLab From 0bd11f27ed3b3c04b1a753b6c8bdc79ffc1b8cef Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:43 +0000 Subject: [PATCH 3831/4982] irda: convert via-ircc to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/irda/via-ircc.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c index 8b3e545924c..864798502ff 100644 --- a/drivers/net/irda/via-ircc.c +++ b/drivers/net/irda/via-ircc.c @@ -310,6 +310,19 @@ static void __exit via_ircc_cleanup(void) pci_unregister_driver (&via_driver); } +static const struct net_device_ops via_ircc_sir_ops = { + .ndo_start_xmit = via_ircc_hard_xmit_sir, + .ndo_open = via_ircc_net_open, + .ndo_stop = via_ircc_net_close, + .ndo_do_ioctl = via_ircc_net_ioctl, +}; +static const struct net_device_ops via_ircc_fir_ops = { + .ndo_start_xmit = via_ircc_hard_xmit_fir, + .ndo_open = via_ircc_net_open, + .ndo_stop = via_ircc_net_close, + .ndo_do_ioctl = via_ircc_net_ioctl, +}; + /* * Function via_ircc_open (iobase, irq) * @@ -428,10 +441,7 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id) self->tx_fifo.tail = self->tx_buff.head; /* Override the network functions we need to use */ - dev->hard_start_xmit = via_ircc_hard_xmit_sir; - dev->open = via_ircc_net_open; - dev->stop = via_ircc_net_close; - dev->do_ioctl = via_ircc_net_ioctl; + dev->netdev_ops = &via_ircc_sir_ops; err = register_netdev(dev); if (err) @@ -798,11 +808,11 @@ static void via_ircc_change_speed(struct via_ircc_cb *self, __u32 speed) if (speed > 115200) { /* Install FIR xmit handler */ - dev->hard_start_xmit = via_ircc_hard_xmit_fir; + dev->netdev_ops = &via_ircc_fir_ops; via_ircc_dma_receive(self); } else { /* Install SIR xmit handler */ - dev->hard_start_xmit = via_ircc_hard_xmit_sir; + dev->netdev_ops = &via_ircc_sir_ops; } netif_wake_queue(dev); } -- GitLab From 2b023f46cbc6187f6ee88e778ed798745b5b2bfe Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:44 +0000 Subject: [PATCH 3832/4982] irda: convert sir device to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/irda/sir_dev.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c index 803c0be3fc7..d940809762e 100644 --- a/drivers/net/irda/sir_dev.c +++ b/drivers/net/irda/sir_dev.c @@ -865,6 +865,12 @@ out: return 0; } +static const struct net_device_ops sirdev_ops = { + .ndo_start_xmit = sirdev_hard_xmit, + .ndo_open = sirdev_open, + .ndo_stop = sirdev_close, + .ndo_do_ioctl = sirdev_ioctl, +}; /* ----------------------------------------------------------------------------- */ struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *name) @@ -908,10 +914,7 @@ struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *n dev->netdev = ndev; /* Override the network functions we need to use */ - ndev->hard_start_xmit = sirdev_hard_xmit; - ndev->open = sirdev_open; - ndev->stop = sirdev_close; - ndev->do_ioctl = sirdev_ioctl; + ndev->netdev_ops = &sirdev_ops; if (register_netdev(ndev)) { IRDA_ERROR("%s(), register_netdev() failed!\n", __func__); -- GitLab From 9b634007d5694178c4e142fbc5f9dbcd767eafbd Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:45 +0000 Subject: [PATCH 3833/4982] irda: convert kingsun device to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/irda/kingsun-sir.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/irda/kingsun-sir.c b/drivers/net/irda/kingsun-sir.c index b4a61717254..9d813bc4502 100644 --- a/drivers/net/irda/kingsun-sir.c +++ b/drivers/net/irda/kingsun-sir.c @@ -418,6 +418,12 @@ static int kingsun_net_ioctl(struct net_device *netdev, struct ifreq *rq, return ret; } +static const struct net_device_ops kingsun_ops = { + .ndo_start_xmit = kingsun_hard_xmit, + .ndo_open = kingsun_net_open, + .ndo_stop = kingsun_net_close, + .ndo_do_ioctl = kingsun_net_ioctl, +}; /* * This routine is called by the USB subsystem for each new device @@ -520,10 +526,7 @@ static int kingsun_probe(struct usb_interface *intf, irda_qos_bits_to_value(&kingsun->qos); /* Override the network functions we need to use */ - net->hard_start_xmit = kingsun_hard_xmit; - net->open = kingsun_net_open; - net->stop = kingsun_net_close; - net->do_ioctl = kingsun_net_ioctl; + net->netdev_ops = &kingsun_ops; ret = register_netdev(net); if (ret != 0) -- GitLab From 0c818a6273218f5a827fe5f41f01caeb679b469e Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:46 +0000 Subject: [PATCH 3834/4982] irda: convert ksdazzle device to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/irda/ksdazzle-sir.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/irda/ksdazzle-sir.c b/drivers/net/irda/ksdazzle-sir.c index 5b327b09acd..64df27f2bfd 100644 --- a/drivers/net/irda/ksdazzle-sir.c +++ b/drivers/net/irda/ksdazzle-sir.c @@ -562,6 +562,13 @@ static int ksdazzle_net_ioctl(struct net_device *netdev, struct ifreq *rq, return ret; } +static const struct net_device_ops ksdazzle_ops = { + .ndo_start_xmit = ksdazzle_hard_xmit, + .ndo_open = ksdazzle_net_open, + .ndo_stop = ksdazzle_net_close, + .ndo_do_ioctl = ksdazzle_net_ioctl, +}; + /* * This routine is called by the USB subsystem for each new device * in the system. We need to check if the device is ours, and in @@ -684,10 +691,7 @@ static int ksdazzle_probe(struct usb_interface *intf, irda_qos_bits_to_value(&kingsun->qos); /* Override the network functions we need to use */ - net->hard_start_xmit = ksdazzle_hard_xmit; - net->open = ksdazzle_net_open; - net->stop = ksdazzle_net_close; - net->do_ioctl = ksdazzle_net_ioctl; + net->netdev_ops = &ksdazzle_ops; ret = register_netdev(net); if (ret != 0) -- GitLab From 94ffab6d199ab36e5dfd2f2f0e4bb135728526c4 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:47 +0000 Subject: [PATCH 3835/4982] irda: convert ks959 driver to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/irda/ks959-sir.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/irda/ks959-sir.c b/drivers/net/irda/ks959-sir.c index 55322fb92cf..b6ffe9715b6 100644 --- a/drivers/net/irda/ks959-sir.c +++ b/drivers/net/irda/ks959-sir.c @@ -668,6 +668,12 @@ static int ks959_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) return ret; } +static const struct net_device_ops ks959_ops = { + .ndo_start_xmit = ks959_hard_xmit, + .ndo_open = ks959_net_open, + .ndo_stop = ks959_net_close, + .ndo_do_ioctl = ks959_net_ioctl, +}; /* * This routine is called by the USB subsystem for each new device * in the system. We need to check if the device is ours, and in @@ -780,10 +786,7 @@ static int ks959_probe(struct usb_interface *intf, irda_qos_bits_to_value(&kingsun->qos); /* Override the network functions we need to use */ - net->hard_start_xmit = ks959_hard_xmit; - net->open = ks959_net_open; - net->stop = ks959_net_close; - net->do_ioctl = ks959_net_ioctl; + net->netdev_ops = &ks959_ops; ret = register_netdev(net); if (ret != 0) -- GitLab From edc4ae08644045dc803dc519f96ff245cb80adad Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:48 +0000 Subject: [PATCH 3836/4982] usbnet: convert catc to internal net_device_stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/usb/catc.c | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c index cb7acbbb279..2fb4e3654d7 100644 --- a/drivers/net/usb/catc.c +++ b/drivers/net/usb/catc.c @@ -163,7 +163,6 @@ struct catc { struct net_device *netdev; struct usb_device *usbdev; - struct net_device_stats stats; unsigned long flags; unsigned int tx_ptr, tx_idx; @@ -245,8 +244,8 @@ static void catc_rx_done(struct urb *urb) if(!catc->is_f5u011) { pkt_len = le16_to_cpup((__le16*)pkt_start); if (pkt_len > urb->actual_length) { - catc->stats.rx_length_errors++; - catc->stats.rx_errors++; + catc->netdev->stats.rx_length_errors++; + catc->netdev->stats.rx_errors++; break; } } else { @@ -262,8 +261,8 @@ static void catc_rx_done(struct urb *urb) skb->protocol = eth_type_trans(skb, catc->netdev); netif_rx(skb); - catc->stats.rx_packets++; - catc->stats.rx_bytes += pkt_len; + catc->netdev->stats.rx_packets++; + catc->netdev->stats.rx_bytes += pkt_len; /* F5U011 only does one packet per RX */ if (catc->is_f5u011) @@ -386,7 +385,7 @@ static void catc_tx_done(struct urb *urb) dbg("Tx Reset."); urb->status = 0; catc->netdev->trans_start = jiffies; - catc->stats.tx_errors++; + catc->netdev->stats.tx_errors++; clear_bit(TX_RUNNING, &catc->flags); netif_wake_queue(catc->netdev); return; @@ -412,7 +411,7 @@ static void catc_tx_done(struct urb *urb) spin_unlock_irqrestore(&catc->tx_lock, flags); } -static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) +static int catc_start_xmit(struct sk_buff *skb, struct net_device *netdev) { struct catc *catc = netdev_priv(netdev); unsigned long flags; @@ -443,8 +442,8 @@ static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) spin_unlock_irqrestore(&catc->tx_lock, flags); if (r >= 0) { - catc->stats.tx_bytes += skb->len; - catc->stats.tx_packets++; + catc->netdev->stats.tx_bytes += skb->len; + catc->netdev->stats.tx_packets++; } dev_kfree_skb(skb); @@ -588,15 +587,15 @@ static void catc_stats_done(struct catc *catc, struct ctrl_queue *q) switch (index) { case TxSingleColl: case TxMultiColl: - catc->stats.collisions += data - last; + catc->netdev->stats.collisions += data - last; break; case TxExcessColl: - catc->stats.tx_aborted_errors += data - last; - catc->stats.tx_errors += data - last; + catc->netdev->stats.tx_aborted_errors += data - last; + catc->netdev->stats.tx_errors += data - last; break; case RxFramErr: - catc->stats.rx_frame_errors += data - last; - catc->stats.rx_errors += data - last; + catc->netdev->stats.rx_frame_errors += data - last; + catc->netdev->stats.rx_errors += data - last; break; } @@ -614,12 +613,6 @@ static void catc_stats_timer(unsigned long data) mod_timer(&catc->timer, jiffies + STATS_UPDATE); } -static struct net_device_stats *catc_get_stats(struct net_device *netdev) -{ - struct catc *catc = netdev_priv(netdev); - return &catc->stats; -} - /* * Receive modes. Broadcast, Multicast, Promisc. */ @@ -777,7 +770,6 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id netdev->open = catc_open; netdev->hard_start_xmit = catc_hard_start_xmit; netdev->stop = catc_stop; - netdev->get_stats = catc_get_stats; netdev->tx_timeout = catc_tx_timeout; netdev->watchdog_timeo = TX_TIMEOUT; netdev->set_multicast_list = catc_set_multicast_list; -- GitLab From 19b8f8f1a1cd9e31a1092a6841065471df8db00f Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:49 +0000 Subject: [PATCH 3837/4982] usbnet: convert catc device to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/usb/catc.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c index 2fb4e3654d7..b9dd4257428 100644 --- a/drivers/net/usb/catc.c +++ b/drivers/net/usb/catc.c @@ -743,6 +743,18 @@ static int catc_stop(struct net_device *netdev) return 0; } +static const struct net_device_ops catc_netdev_ops = { + .ndo_open = catc_open, + .ndo_stop = catc_stop, + .ndo_start_xmit = catc_start_xmit, + + .ndo_tx_timeout = catc_tx_timeout, + .ndo_set_multicast_list = catc_set_multicast_list, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + /* * USB probe, disconnect. */ @@ -767,12 +779,8 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id catc = netdev_priv(netdev); - netdev->open = catc_open; - netdev->hard_start_xmit = catc_hard_start_xmit; - netdev->stop = catc_stop; - netdev->tx_timeout = catc_tx_timeout; + netdev->netdev_ops = &catc_netdev_ops; netdev->watchdog_timeo = TX_TIMEOUT; - netdev->set_multicast_list = catc_set_multicast_list; SET_ETHTOOL_OPS(netdev, &ops); catc->usbdev = usbdev; -- GitLab From b7e41e23055f20be334c404b15373c8deb2262b9 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:50 +0000 Subject: [PATCH 3838/4982] usbnet: convert to internal net_device stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/usb/rtl8150.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index d8664bf18c0..67368ccdb15 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c @@ -155,7 +155,6 @@ struct rtl8150 { unsigned long flags; struct usb_device *udev; struct tasklet_struct tl; - struct net_device_stats stats; struct net_device *netdev; struct urb *rx_urb, *tx_urb, *intr_urb, *ctrl_urb; struct sk_buff *tx_skb, *rx_skb; @@ -463,8 +462,8 @@ static void read_bulk_callback(struct urb *urb) skb_put(dev->rx_skb, pkt_len); dev->rx_skb->protocol = eth_type_trans(dev->rx_skb, netdev); netif_rx(dev->rx_skb); - dev->stats.rx_packets++; - dev->stats.rx_bytes += pkt_len; + netdev->stats.rx_packets++; + netdev->stats.rx_bytes += pkt_len; spin_lock(&dev->rx_pool_lock); skb = pull_skb(dev); @@ -573,13 +572,13 @@ static void intr_callback(struct urb *urb) d = urb->transfer_buffer; if (d[0] & TSR_ERRORS) { - dev->stats.tx_errors++; + dev->netdev->stats.tx_errors++; if (d[INT_TSR] & (TSR_ECOL | TSR_JBR)) - dev->stats.tx_aborted_errors++; + dev->netdev->stats.tx_aborted_errors++; if (d[INT_TSR] & TSR_LCOL) - dev->stats.tx_window_errors++; + dev->netdev->stats.tx_window_errors++; if (d[INT_TSR] & TSR_LOSS_CRS) - dev->stats.tx_carrier_errors++; + dev->netdev->stats.tx_carrier_errors++; } /* Report link status changes to the network stack */ if ((d[INT_MSR] & MSR_LINK) == 0) { @@ -697,17 +696,12 @@ static void disable_net_traffic(rtl8150_t * dev) set_registers(dev, CR, 1, &cr); } -static struct net_device_stats *rtl8150_netdev_stats(struct net_device *dev) -{ - return &((rtl8150_t *)netdev_priv(dev))->stats; -} - static void rtl8150_tx_timeout(struct net_device *netdev) { rtl8150_t *dev = netdev_priv(netdev); dev_warn(&netdev->dev, "Tx timeout.\n"); usb_unlink_urb(dev->tx_urb); - dev->stats.tx_errors++; + netdev->stats.tx_errors++; } static void rtl8150_set_multicast(struct net_device *netdev) @@ -747,12 +741,12 @@ static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev) netif_device_detach(dev->netdev); else { dev_warn(&netdev->dev, "failed tx_urb %d\n", res); - dev->stats.tx_errors++; + netdev->stats.tx_errors++; netif_start_queue(netdev); } } else { - dev->stats.tx_packets++; - dev->stats.tx_bytes += skb->len; + netdev->stats.tx_packets++; + netdev->stats.tx_bytes += skb->len; netdev->trans_start = jiffies; } @@ -931,7 +925,7 @@ static int rtl8150_probe(struct usb_interface *intf, netdev->hard_start_xmit = rtl8150_start_xmit; netdev->set_multicast_list = rtl8150_set_multicast; netdev->set_mac_address = rtl8150_set_mac_address; - netdev->get_stats = rtl8150_netdev_stats; + SET_ETHTOOL_OPS(netdev, &ops); dev->intr_interval = 100; /* 100ms */ -- GitLab From d79f7ef48b0897458a4df30085338aeb7fb85ffc Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:51 +0000 Subject: [PATCH 3839/4982] usbnet: convert rtl driver to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/usb/rtl8150.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index 67368ccdb15..f9fb454ffa8 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c @@ -891,6 +891,19 @@ static int rtl8150_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) return res; } +static const struct net_device_ops rtl8150_netdev_ops = { + .ndo_open = rtl8150_open, + .ndo_stop = rtl8150_close, + .ndo_do_ioctl = rtl8150_ioctl, + .ndo_start_xmit = rtl8150_start_xmit, + .ndo_tx_timeout = rtl8150_tx_timeout, + .ndo_set_multicast_list = rtl8150_set_multicast, + .ndo_set_mac_address = rtl8150_set_mac_address, + + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, +}; + static int rtl8150_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -917,15 +930,8 @@ static int rtl8150_probe(struct usb_interface *intf, dev->udev = udev; dev->netdev = netdev; - netdev->open = rtl8150_open; - netdev->stop = rtl8150_close; - netdev->do_ioctl = rtl8150_ioctl; + netdev->netdev_ops = &rtl8150_netdev_ops; netdev->watchdog_timeo = RTL8150_TX_TIMEOUT; - netdev->tx_timeout = rtl8150_tx_timeout; - netdev->hard_start_xmit = rtl8150_start_xmit; - netdev->set_multicast_list = rtl8150_set_multicast; - netdev->set_mac_address = rtl8150_set_mac_address; - SET_ETHTOOL_OPS(netdev, &ops); dev->intr_interval = 100; /* 100ms */ -- GitLab From c266cb4ef2ef1f1e3f46d81022939feebe8fa54d Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:52 +0000 Subject: [PATCH 3840/4982] usbnet: convert hso driver to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/usb/hso.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index f49cc7b50c7..cde423c6d04 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -2428,6 +2428,13 @@ static void hso_free_net_device(struct hso_device *hso_dev) kfree(hso_dev); } +static const struct net_device_ops hso_netdev_ops = { + .ndo_open = hso_net_open, + .ndo_stop = hso_net_close, + .ndo_start_xmit = hso_net_start_xmit, + .ndo_tx_timeout = hso_net_tx_timeout, +}; + /* initialize the network interface */ static void hso_net_init(struct net_device *net) { @@ -2436,10 +2443,7 @@ static void hso_net_init(struct net_device *net) D1("sizeof hso_net is %d", (int)sizeof(*hso_net)); /* fill in the other fields */ - net->open = hso_net_open; - net->stop = hso_net_close; - net->hard_start_xmit = hso_net_start_xmit; - net->tx_timeout = hso_net_tx_timeout; + net->netdev_ops = &hso_netdev_ops; net->watchdog_timeo = HSO_NET_TX_TIMEOUT; net->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; net->type = ARPHRD_NONE; -- GitLab From 805aaa29fa3c5afb26cb42f440f40d3f7f5c4bdc Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:53 +0000 Subject: [PATCH 3841/4982] usbnet: convert to internal net_device_stats Default handler for net_device_stats already does same thing. Signed-off-by: Stephen Hemminger Acked-by: David Brownell Signed-off-by: David S. Miller --- drivers/net/usb/usbnet.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index c32284ff3f5..08414169224 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -249,14 +249,6 @@ static int usbnet_change_mtu (struct net_device *net, int new_mtu) /*-------------------------------------------------------------------------*/ -static struct net_device_stats *usbnet_get_stats (struct net_device *net) -{ - struct usbnet *dev = netdev_priv(net); - return &dev->stats; -} - -/*-------------------------------------------------------------------------*/ - /* some LK 2.4 HCDs oopsed if we freed or resubmitted urbs from * completion callbacks. 2.5 should have fixed those bugs... */ @@ -1180,7 +1172,6 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) #endif net->change_mtu = usbnet_change_mtu; - net->get_stats = usbnet_get_stats; net->hard_start_xmit = usbnet_start_xmit; net->open = usbnet_open; net->stop = usbnet_stop; -- GitLab From 777baa4711c6b8373f4e03a3a558d44a6b046d7a Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:54 +0000 Subject: [PATCH 3842/4982] usbnet: support net_device_ops Use net_device_ops for usbnet device, and export for use by other derived drivers. Signed-off-by: Stephen Hemminger Acked-by: David Brownell Signed-off-by: David S. Miller --- drivers/net/usb/usbnet.c | 31 +++++++++++++++++++++++-------- include/linux/usb/usbnet.h | 5 +++++ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 08414169224..659654f4588 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -223,7 +223,7 @@ EXPORT_SYMBOL_GPL(usbnet_skb_return); * *-------------------------------------------------------------------------*/ -static int usbnet_change_mtu (struct net_device *net, int new_mtu) +int usbnet_change_mtu (struct net_device *net, int new_mtu) { struct usbnet *dev = netdev_priv(net); int ll_mtu = new_mtu + net->hard_header_len; @@ -246,6 +246,7 @@ static int usbnet_change_mtu (struct net_device *net, int new_mtu) return 0; } +EXPORT_SYMBOL_GPL(usbnet_change_mtu); /*-------------------------------------------------------------------------*/ @@ -540,7 +541,7 @@ EXPORT_SYMBOL_GPL(usbnet_unlink_rx_urbs); // precondition: never called in_interrupt -static int usbnet_stop (struct net_device *net) +int usbnet_stop (struct net_device *net) { struct usbnet *dev = netdev_priv(net); int temp; @@ -584,6 +585,7 @@ static int usbnet_stop (struct net_device *net) return 0; } +EXPORT_SYMBOL_GPL(usbnet_stop); /*-------------------------------------------------------------------------*/ @@ -591,7 +593,7 @@ static int usbnet_stop (struct net_device *net) // precondition: never called in_interrupt -static int usbnet_open (struct net_device *net) +int usbnet_open (struct net_device *net) { struct usbnet *dev = netdev_priv(net); int retval; @@ -666,6 +668,7 @@ done: done_nopm: return retval; } +EXPORT_SYMBOL_GPL(usbnet_open); /*-------------------------------------------------------------------------*/ @@ -900,7 +903,7 @@ static void tx_complete (struct urb *urb) /*-------------------------------------------------------------------------*/ -static void usbnet_tx_timeout (struct net_device *net) +void usbnet_tx_timeout (struct net_device *net) { struct usbnet *dev = netdev_priv(net); @@ -909,10 +912,11 @@ static void usbnet_tx_timeout (struct net_device *net) // FIXME: device recovery -- reset? } +EXPORT_SYMBOL_GPL(usbnet_tx_timeout); /*-------------------------------------------------------------------------*/ -static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net) +int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net) { struct usbnet *dev = netdev_priv(net); int length; @@ -995,7 +999,7 @@ drop: } return retval; } - +EXPORT_SYMBOL_GPL(usbnet_start_xmit); /*-------------------------------------------------------------------------*/ @@ -1102,6 +1106,15 @@ void usbnet_disconnect (struct usb_interface *intf) } EXPORT_SYMBOL_GPL(usbnet_disconnect); +static const struct net_device_ops usbnet_netdev_ops = { + .ndo_open = usbnet_open, + .ndo_stop = usbnet_stop, + .ndo_start_xmit = usbnet_start_xmit, + .ndo_tx_timeout = usbnet_tx_timeout, + .ndo_change_mtu = usbnet_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; /*-------------------------------------------------------------------------*/ @@ -1171,12 +1184,14 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) net->features |= NETIF_F_HIGHDMA; #endif - net->change_mtu = usbnet_change_mtu; + net->netdev_ops = &usbnet_netdev_ops; +#ifdef CONFIG_COMPAT_NET_DEV_OPS net->hard_start_xmit = usbnet_start_xmit; net->open = usbnet_open; net->stop = usbnet_stop; - net->watchdog_timeo = TX_TIMEOUT_JIFFIES; net->tx_timeout = usbnet_tx_timeout; +#endif + net->watchdog_timeo = TX_TIMEOUT_JIFFIES; net->ethtool_ops = &usbnet_ethtool_ops; // allow device-specific bind/init procedures diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h index 7d382224307..36fabb95c7d 100644 --- a/include/linux/usb/usbnet.h +++ b/include/linux/usb/usbnet.h @@ -176,6 +176,11 @@ struct skb_data { /* skb->cb is one of these */ size_t length; }; +extern int usbnet_open (struct net_device *net); +extern int usbnet_stop (struct net_device *net); +extern int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net); +extern void usbnet_tx_timeout (struct net_device *net); +extern int usbnet_change_mtu (struct net_device *net, int new_mtu); extern int usbnet_get_endpoints(struct usbnet *, struct usb_interface *); extern void usbnet_defer_kevent (struct usbnet *, int); -- GitLab From 1703338c79f39178535fe54b5aeaebf9c42300f6 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:55 +0000 Subject: [PATCH 3843/4982] usbnet: convert asix driver to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/usb/asix.c | 47 +++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 396f821b5ff..87b4a028991 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -807,6 +807,18 @@ static int ax88172_link_reset(struct usbnet *dev) return 0; } +static const struct net_device_ops ax88172_netdev_ops = { + .ndo_open = usbnet_open, + .ndo_stop = usbnet_stop, + .ndo_start_xmit = usbnet_start_xmit, + .ndo_tx_timeout = usbnet_tx_timeout, + .ndo_change_mtu = usbnet_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_do_ioctl = asix_ioctl, + .ndo_set_multicast_list = ax88172_set_multicast, +}; + static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf) { int ret = 0; @@ -846,9 +858,8 @@ static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf) dev->mii.phy_id_mask = 0x3f; dev->mii.reg_num_mask = 0x1f; dev->mii.phy_id = asix_get_phy_addr(dev); - dev->net->do_ioctl = asix_ioctl; - dev->net->set_multicast_list = ax88172_set_multicast; + dev->net->netdev_ops = &ax88172_netdev_ops; dev->net->ethtool_ops = &ax88172_ethtool_ops; asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); @@ -898,6 +909,18 @@ static int ax88772_link_reset(struct usbnet *dev) return 0; } +static const struct net_device_ops ax88772_netdev_ops = { + .ndo_open = usbnet_open, + .ndo_stop = usbnet_stop, + .ndo_start_xmit = usbnet_start_xmit, + .ndo_tx_timeout = usbnet_tx_timeout, + .ndo_change_mtu = usbnet_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_do_ioctl = asix_ioctl, + .ndo_set_multicast_list = asix_set_multicast, +}; + static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) { int ret, embd_phy; @@ -962,7 +985,6 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) dev->mii.mdio_write = asix_mdio_write; dev->mii.phy_id_mask = 0x1f; dev->mii.reg_num_mask = 0x1f; - dev->net->do_ioctl = asix_ioctl; dev->mii.phy_id = asix_get_phy_addr(dev); phyid = asix_get_phyid(dev); @@ -978,7 +1000,7 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) msleep(150); - dev->net->set_multicast_list = asix_set_multicast; + dev->net->netdev_ops = &ax88772_netdev_ops; dev->net->ethtool_ops = &ax88772_ethtool_ops; asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); @@ -1181,6 +1203,18 @@ static int ax88178_change_mtu(struct net_device *net, int new_mtu) return 0; } +static const struct net_device_ops ax88178_netdev_ops = { + .ndo_open = usbnet_open, + .ndo_stop = usbnet_stop, + .ndo_start_xmit = usbnet_start_xmit, + .ndo_tx_timeout = usbnet_tx_timeout, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_multicast_list = asix_set_multicast, + .ndo_do_ioctl = asix_ioctl, + .ndo_change_mtu = ax88178_change_mtu, +}; + static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf) { struct asix_data *data = (struct asix_data *)&dev->data; @@ -1247,11 +1281,10 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf) dev->mii.phy_id_mask = 0x1f; dev->mii.reg_num_mask = 0xff; dev->mii.supports_gmii = 1; - dev->net->do_ioctl = asix_ioctl; dev->mii.phy_id = asix_get_phy_addr(dev); - dev->net->set_multicast_list = asix_set_multicast; + + dev->net->netdev_ops = &ax88178_netdev_ops; dev->net->ethtool_ops = &ax88178_ethtool_ops; - dev->net->change_mtu = &ax88178_change_mtu; phyid = asix_get_phyid(dev); dbg("PHYID=0x%08x", phyid); -- GitLab From fe85ff8299538c8488645e7d72539079dad5bae6 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:56 +0000 Subject: [PATCH 3844/4982] usbnet: convert dms9601 driver to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: Peter Korsgaard Signed-off-by: David S. Miller --- drivers/net/usb/dm9601.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 81682c6defa..6fc4f82b0be 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -419,6 +419,18 @@ static int dm9601_set_mac_address(struct net_device *net, void *p) return 0; } +static const struct net_device_ops dm9601_netdev_ops = { + .ndo_open = usbnet_open, + .ndo_stop = usbnet_stop, + .ndo_start_xmit = usbnet_start_xmit, + .ndo_tx_timeout = usbnet_tx_timeout, + .ndo_change_mtu = usbnet_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_do_ioctl = dm9601_ioctl, + .ndo_set_multicast_list = dm9601_set_multicast, + .ndo_set_mac_address = dm9601_set_mac_address, +}; + static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf) { int ret; @@ -428,9 +440,7 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf) if (ret) goto out; - dev->net->do_ioctl = dm9601_ioctl; - dev->net->set_multicast_list = dm9601_set_multicast; - dev->net->set_mac_address = dm9601_set_mac_address; + dev->net->netdev_ops = &dm9601_netdev_ops; dev->net->ethtool_ops = &dm9601_ethtool_ops; dev->net->hard_header_len += DM_TX_OVERHEAD; dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; -- GitLab From e12c4f83210b457e2969fbe1198357e66f044a93 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:57 +0000 Subject: [PATCH 3845/4982] usbnet: convert msc7830 driver to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/usb/mcs7830.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index ced8f36ebd0..7ae9afe99a4 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -486,6 +486,18 @@ static int mcs7830_set_mac_address(struct net_device *netdev, void *p) return 0; } +static const struct net_device_ops mcs7830_netdev_ops = { + .ndo_open = usbnet_open, + .ndo_stop = usbnet_stop, + .ndo_start_xmit = usbnet_start_xmit, + .ndo_tx_timeout = usbnet_tx_timeout, + .ndo_change_mtu = usbnet_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_do_ioctl = mcs7830_ioctl, + .ndo_set_multicast_list = mcs7830_set_multicast, + .ndo_set_mac_address = mcs7830_set_mac_address, +}; + static int mcs7830_bind(struct usbnet *dev, struct usb_interface *udev) { struct net_device *net = dev->net; @@ -495,11 +507,9 @@ static int mcs7830_bind(struct usbnet *dev, struct usb_interface *udev) if (ret) goto out; - net->do_ioctl = mcs7830_ioctl; net->ethtool_ops = &mcs7830_ethtool_ops; - net->set_multicast_list = mcs7830_set_multicast; + net->netdev_ops = &mcs7830_netdev_ops; mcs7830_set_multicast(net); - net->set_mac_address = mcs7830_set_mac_address; /* reserve space for the status byte on rx */ dev->rx_urb_size = ETH_FRAME_LEN + 1; -- GitLab From 63e77b391f7230ab87effbcaf7238e9b1e6d7404 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:58 +0000 Subject: [PATCH 3846/4982] usbnet: convert smsc95xx driver to net_device_ops Signed-off-by: Stephen Hemminger Acked-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/usb/smsc95xx.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 3e6155a38f0..dc166532659 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -1008,6 +1008,18 @@ static int smsc95xx_reset(struct usbnet *dev) return 0; } +static const struct net_device_ops smsc95xx_netdev_ops = { + .ndo_open = usbnet_open, + .ndo_stop = usbnet_stop, + .ndo_start_xmit = usbnet_start_xmit, + .ndo_tx_timeout = usbnet_tx_timeout, + .ndo_change_mtu = usbnet_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_do_ioctl = smsc95xx_ioctl, + .ndo_set_multicast_list = smsc95xx_set_multicast, +}; + static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) { struct smsc95xx_priv *pdata = NULL; @@ -1038,9 +1050,8 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) /* Init all registers */ ret = smsc95xx_reset(dev); - dev->net->do_ioctl = smsc95xx_ioctl; + dev->net->netdev_ops = &smsc95xx_netdev_ops; dev->net->ethtool_ops = &smsc95xx_ethtool_ops; - dev->net->set_multicast_list = smsc95xx_set_multicast; dev->net->flags |= IFF_MULTICAST; dev->net->hard_header_len += SMSC95XX_TX_OVERHEAD; return 0; -- GitLab From b5556498b60a237cca173dfd60109f3504ce25ca Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:35:59 +0000 Subject: [PATCH 3847/4982] usbnet: convert rndis driver to use dev_get_stats dev_get_stats() handles all issues with net_device_ops Signed-off-by: Stephen Hemminger Acked-by: David Brownell Signed-off-by: David S. Miller --- drivers/usb/gadget/rndis.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index d2860a82368..2b4660e08c4 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -170,7 +170,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, int i, count; rndis_query_cmplt_type *resp; struct net_device *net; - struct net_device_stats *stats; + const struct net_device_stats *stats; if (!r) return -ENOMEM; resp = (rndis_query_cmplt_type *) r->buf; @@ -193,10 +193,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, resp->InformationBufferOffset = cpu_to_le32 (16); net = rndis_per_dev_params[configNr].dev; - if (net->get_stats) - stats = net->get_stats(net); - else - stats = NULL; + stats = dev_get_stats(net); switch (OID) { -- GitLab From 0f2166dff6440bb6fb39e4fbe7bfca7cde95d650 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:00 +0000 Subject: [PATCH 3848/4982] usbnet: convert rndis driver to net_device_ops Signed-off-by: Stephen Hemminger Acked-by: David Brownell Signed-off-by: David S. Miller --- drivers/net/usb/rndis_host.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index b7f763e1298..1bf243ef950 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -266,6 +266,16 @@ response_error: return -EDOM; } +/* same as usbnet_netdev_ops but MTU change not allowed */ +static const struct net_device_ops rndis_netdev_ops = { + .ndo_open = usbnet_open, + .ndo_stop = usbnet_stop, + .ndo_start_xmit = usbnet_start_xmit, + .ndo_tx_timeout = usbnet_tx_timeout, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + int generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags) { @@ -327,7 +337,8 @@ generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags) dev->rx_urb_size &= ~(dev->maxpacket - 1); u.init->max_transfer_size = cpu_to_le32(dev->rx_urb_size); - net->change_mtu = NULL; + net->netdev_ops = &rndis_netdev_ops; + retval = rndis_command(dev, u.header, CONTROL_BUFFER_SIZE); if (unlikely(retval < 0)) { /* it might not even be an RNDIS device!! */ -- GitLab From 97161d4b2a28857f217b2035b2141cbb36f22f8b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:01 +0000 Subject: [PATCH 3849/4982] pcmcia: convert 3c589 to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/pcmcia/3c589_cs.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 1e01b8a6dbf..cdf661a6092 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -169,6 +169,19 @@ static void tc589_detach(struct pcmcia_device *p_dev); ======================================================================*/ +static const struct net_device_ops el3_netdev_ops = { + .ndo_open = el3_open, + .ndo_stop = el3_close, + .ndo_start_xmit = el3_start_xmit, + .ndo_tx_timeout = el3_tx_timeout, + .ndo_set_config = el3_config, + .ndo_get_stats = el3_get_stats, + .ndo_set_multicast_list = set_multicast_list, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + static int tc589_probe(struct pcmcia_device *link) { struct el3_private *lp; @@ -195,17 +208,9 @@ static int tc589_probe(struct pcmcia_device *link) link->conf.IntType = INT_MEMORY_AND_IO; link->conf.ConfigIndex = 1; - /* The EL3-specific entries in the device structure. */ - dev->hard_start_xmit = &el3_start_xmit; - dev->set_config = &el3_config; - dev->get_stats = &el3_get_stats; - dev->set_multicast_list = &set_multicast_list; - dev->open = &el3_open; - dev->stop = &el3_close; -#ifdef HAVE_TX_TIMEOUT - dev->tx_timeout = el3_tx_timeout; + dev->netdev_ops = &el3_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; -#endif + SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); return tc589_config(link); -- GitLab From fb72e2ff356e55b6a60c5883d4506175652c3e9d Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:02 +0000 Subject: [PATCH 3850/4982] pcmcia: convert 3c574 to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/pcmcia/3c574_cs.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 2404a838b1f..8f3872b8985 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -257,6 +257,18 @@ static void tc574_detach(struct pcmcia_device *p_dev); local data structures for one device. The device is registered with Card Services. */ +static const struct net_device_ops el3_netdev_ops = { + .ndo_open = el3_open, + .ndo_stop = el3_close, + .ndo_start_xmit = el3_start_xmit, + .ndo_tx_timeout = el3_tx_timeout, + .ndo_get_stats = el3_get_stats, + .ndo_do_ioctl = el3_ioctl, + .ndo_set_multicast_list = set_rx_mode, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; static int tc574_probe(struct pcmcia_device *link) { @@ -284,18 +296,9 @@ static int tc574_probe(struct pcmcia_device *link) link->conf.IntType = INT_MEMORY_AND_IO; link->conf.ConfigIndex = 1; - /* The EL3-specific entries in the device structure. */ - dev->hard_start_xmit = &el3_start_xmit; - dev->get_stats = &el3_get_stats; - dev->do_ioctl = &el3_ioctl; + dev->netdev_ops = &el3_netdev_ops; SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); - dev->set_multicast_list = &set_rx_mode; - dev->open = &el3_open; - dev->stop = &el3_close; -#ifdef HAVE_TX_TIMEOUT - dev->tx_timeout = el3_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; -#endif return tc574_config(link); } /* tc574_attach */ -- GitLab From d63cd426ba55a9e02ab745612357ee00158824a5 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:03 +0000 Subject: [PATCH 3851/4982] pcmcia: convert fmvj18x driver to internal net_device_stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/pcmcia/fmvj18x_cs.c | 36 +++++++++++---------------------- 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 69dcfbbabe8..6715188319d 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -100,7 +100,6 @@ static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev); static irqreturn_t fjn_interrupt(int irq, void *dev_id); static void fjn_rx(struct net_device *dev); static void fjn_reset(struct net_device *dev); -static struct net_device_stats *fjn_get_stats(struct net_device *dev); static void set_rx_mode(struct net_device *dev); static void fjn_tx_timeout(struct net_device *dev); static const struct ethtool_ops netdev_ethtool_ops; @@ -118,7 +117,6 @@ typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN, typedef struct local_info_t { struct pcmcia_device *p_dev; dev_node_t node; - struct net_device_stats stats; long open_time; uint tx_started:1; uint tx_queue; @@ -263,7 +261,6 @@ static int fmvj18x_probe(struct pcmcia_device *link) /* The FMVJ18x specific entries in the device structure. */ dev->hard_start_xmit = &fjn_start_xmit; dev->set_config = &fjn_config; - dev->get_stats = &fjn_get_stats; dev->set_multicast_list = &set_rx_mode; dev->open = &fjn_open; dev->stop = &fjn_close; @@ -793,7 +790,7 @@ static irqreturn_t fjn_interrupt(int dummy, void *dev_id) fjn_rx(dev); } if (tx_stat & F_TMT_RDY) { - lp->stats.tx_packets += lp->sent ; + dev->stats.tx_packets += lp->sent ; lp->sent = 0 ; if (lp->tx_queue) { outb(DO_TX | lp->tx_queue, ioaddr + TX_START); @@ -840,7 +837,7 @@ static void fjn_tx_timeout(struct net_device *dev) htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)), htons(inw(ioaddr +10)), htons(inw(ioaddr +12)), htons(inw(ioaddr +14))); - lp->stats.tx_errors++; + dev->stats.tx_errors++; /* ToDo: We should try to restart the adaptor... */ local_irq_disable(); fjn_reset(dev); @@ -880,7 +877,7 @@ static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev) DEBUG(4, "%s: Transmitting a packet of length %lu.\n", dev->name, (unsigned long)skb->len); - lp->stats.tx_bytes += skb->len; + dev->stats.tx_bytes += skb->len; /* Disable both interrupts. */ outw(0x0000, ioaddr + TX_INTR); @@ -1008,7 +1005,6 @@ static void fjn_reset(struct net_device *dev) static void fjn_rx(struct net_device *dev) { - struct local_info_t *lp = netdev_priv(dev); unsigned int ioaddr = dev->base_addr; int boguscount = 10; /* 5 -> 10: by agy 19940922 */ @@ -1027,11 +1023,11 @@ static void fjn_rx(struct net_device *dev) } #endif if ((status & 0xF0) != 0x20) { /* There was an error. */ - lp->stats.rx_errors++; - if (status & F_LEN_ERR) lp->stats.rx_length_errors++; - if (status & F_ALG_ERR) lp->stats.rx_frame_errors++; - if (status & F_CRC_ERR) lp->stats.rx_crc_errors++; - if (status & F_OVR_FLO) lp->stats.rx_over_errors++; + dev->stats.rx_errors++; + if (status & F_LEN_ERR) dev->stats.rx_length_errors++; + if (status & F_ALG_ERR) dev->stats.rx_frame_errors++; + if (status & F_CRC_ERR) dev->stats.rx_crc_errors++; + if (status & F_OVR_FLO) dev->stats.rx_over_errors++; } else { u_short pkt_len = inw(ioaddr + DATAPORT); /* Malloc up new buffer. */ @@ -1041,7 +1037,7 @@ static void fjn_rx(struct net_device *dev) printk(KERN_NOTICE "%s: The FMV-18x claimed a very " "large packet, size %d.\n", dev->name, pkt_len); outb(F_SKP_PKT, ioaddr + RX_SKIP); - lp->stats.rx_errors++; + dev->stats.rx_errors++; break; } skb = dev_alloc_skb(pkt_len+2); @@ -1049,7 +1045,7 @@ static void fjn_rx(struct net_device *dev) printk(KERN_NOTICE "%s: Memory squeeze, dropping " "packet (len %d).\n", dev->name, pkt_len); outb(F_SKP_PKT, ioaddr + RX_SKIP); - lp->stats.rx_dropped++; + dev->stats.rx_dropped++; break; } @@ -1070,8 +1066,8 @@ static void fjn_rx(struct net_device *dev) #endif netif_rx(skb); - lp->stats.rx_packets++; - lp->stats.rx_bytes += pkt_len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += pkt_len; } if (--boguscount <= 0) break; @@ -1191,14 +1187,6 @@ static int fjn_close(struct net_device *dev) /*====================================================================*/ -static struct net_device_stats *fjn_get_stats(struct net_device *dev) -{ - local_info_t *lp = netdev_priv(dev); - return &lp->stats; -} /* fjn_get_stats */ - -/*====================================================================*/ - /* Set the multicast/promiscuous mode for this adaptor. */ -- GitLab From 496f98cd5687770f4cb463c300510016dfbc81f6 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:04 +0000 Subject: [PATCH 3852/4982] pcmcia: convert fmvj18x driver to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/pcmcia/fmvj18x_cs.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 6715188319d..81e6660a433 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -227,6 +227,18 @@ typedef struct local_info_t { #define BANK_1U 0x24 /* bank 1 (CONFIG_1) */ #define BANK_2U 0x28 /* bank 2 (CONFIG_1) */ +static const struct net_device_ops fjn_netdev_ops = { + .ndo_open = fjn_open, + .ndo_stop = fjn_close, + .ndo_start_xmit = fjn_start_xmit, + .ndo_tx_timeout = fjn_tx_timeout, + .ndo_set_config = fjn_config, + .ndo_set_multicast_list = set_rx_mode, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + static int fmvj18x_probe(struct pcmcia_device *link) { local_info_t *lp; @@ -258,16 +270,9 @@ static int fmvj18x_probe(struct pcmcia_device *link) link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; - /* The FMVJ18x specific entries in the device structure. */ - dev->hard_start_xmit = &fjn_start_xmit; - dev->set_config = &fjn_config; - dev->set_multicast_list = &set_rx_mode; - dev->open = &fjn_open; - dev->stop = &fjn_close; -#ifdef HAVE_TX_TIMEOUT - dev->tx_timeout = fjn_tx_timeout; + dev->netdev_ops = &fjn_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; -#endif + SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); return fmvj18x_config(link); -- GitLab From 28b1801d5a367adaf3d02605c762a59781d99664 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:05 +0000 Subject: [PATCH 3853/4982] pcmcia: convert nmclan driver to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/pcmcia/nmclan_cs.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index ec7c588c9ae..02ef63ed1f9 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -436,6 +436,19 @@ static const struct ethtool_ops netdev_ethtool_ops; static void nmclan_detach(struct pcmcia_device *p_dev); +static const struct net_device_ops mace_netdev_ops = { + .ndo_open = mace_open, + .ndo_stop = mace_close, + .ndo_start_xmit = mace_start_xmit, + .ndo_tx_timeout = mace_tx_timeout, + .ndo_set_config = mace_config, + .ndo_get_stats = mace_get_stats, + .ndo_set_multicast_list = set_multicast_list, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + /* ---------------------------------------------------------------------------- nmclan_attach Creates an "instance" of the driver, allocating local data @@ -474,17 +487,9 @@ static int nmclan_probe(struct pcmcia_device *link) lp->tx_free_frames=AM2150_MAX_TX_FRAMES; - dev->hard_start_xmit = &mace_start_xmit; - dev->set_config = &mace_config; - dev->get_stats = &mace_get_stats; - dev->set_multicast_list = &set_multicast_list; + dev->netdev_ops = &mace_netdev_ops; SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); - dev->open = &mace_open; - dev->stop = &mace_close; -#ifdef HAVE_TX_TIMEOUT - dev->tx_timeout = mace_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; -#endif return nmclan_config(link); } /* nmclan_attach */ -- GitLab From 23169a402d6a2d55992e6b7f6157ae04b636545a Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:06 +0000 Subject: [PATCH 3854/4982] pcnet: convert driver to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/pcmcia/pcnet_cs.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index a6999403f37..2fbf9f9ddd3 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -39,6 +39,7 @@ #include #include #include +#include #include "../8390.h" #include @@ -233,6 +234,23 @@ static inline pcnet_dev_t *PRIV(struct net_device *dev) return (pcnet_dev_t *)(p + sizeof(struct ei_device)); } +static const struct net_device_ops pcnet_netdev_ops = { + .ndo_open = pcnet_open, + .ndo_stop = pcnet_close, + .ndo_set_config = set_config, + .ndo_start_xmit = ei_start_xmit, + .ndo_get_stats = ei_get_stats, + .ndo_do_ioctl = ei_ioctl, + .ndo_set_multicast_list = ei_set_multicast_list, + .ndo_tx_timeout = ei_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = ei_poll, +#endif +}; + /*====================================================================== pcnet_attach() creates an "instance" of the driver, allocating @@ -260,9 +278,7 @@ static int pcnet_probe(struct pcmcia_device *link) link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; - dev->open = &pcnet_open; - dev->stop = &pcnet_close; - dev->set_config = &set_config; + dev->netdev_ops = &pcnet_netdev_ops; return pcnet_config(link); } /* pcnet_attach */ @@ -640,18 +656,12 @@ static int pcnet_config(struct pcmcia_device *link) SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); - if (info->flags & (IS_DL10019|IS_DL10022)) { - dev->do_ioctl = &ei_ioctl; + if (info->flags & (IS_DL10019|IS_DL10022)) mii_phy_probe(dev); - } link->dev_node = &info->node; SET_NETDEV_DEV(dev, &handle_to_dev(link)); -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = ei_poll; -#endif - if (register_netdev(dev) != 0) { printk(KERN_NOTICE "pcnet_cs: register_netdev() failed\n"); link->dev_node = NULL; @@ -1183,6 +1193,10 @@ static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) pcnet_dev_t *info = PRIV(dev); u16 *data = (u16 *)&rq->ifr_ifru; unsigned int mii_addr = dev->base_addr + DLINK_GPIO; + + if (!(info->flags & (IS_DL10019|IS_DL10022))) + return -EINVAL; + switch (cmd) { case SIOCGMIIPHY: data[0] = info->phy_id; -- GitLab From 6394d7c9a2c4c5d729c1cdb69f96f9fff16ec232 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:07 +0000 Subject: [PATCH 3855/4982] xir2cps: convert to internal net_device stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/pcmcia/xirc2ps_cs.c | 41 ++++++++++++--------------------- 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index fef7e1861d6..f8fdf8997e0 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -335,7 +335,7 @@ typedef struct local_info_t { struct net_device *dev; struct pcmcia_device *p_dev; dev_node_t node; - struct net_device_stats stats; + int card_type; int probe_port; int silicon; /* silicon revision. 0=old CE2, 1=Scipper, 4=Mohawk */ @@ -355,7 +355,6 @@ typedef struct local_info_t { static int do_start_xmit(struct sk_buff *skb, struct net_device *dev); static void xirc_tx_timeout(struct net_device *dev); static void xirc2ps_tx_timeout_task(struct work_struct *work); -static struct net_device_stats *do_get_stats(struct net_device *dev); static void set_addresses(struct net_device *dev); static void set_multicast_list(struct net_device *dev); static int set_card_type(struct pcmcia_device *link, const void *s); @@ -583,7 +582,6 @@ xirc2ps_probe(struct pcmcia_device *link) /* Fill in card specific entries */ dev->hard_start_xmit = &do_start_xmit; dev->set_config = &do_config; - dev->get_stats = &do_get_stats; dev->do_ioctl = &do_ioctl; SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); dev->set_multicast_list = &set_multicast_list; @@ -1172,7 +1170,7 @@ xirc2ps_interrupt(int irq, void *dev_id) if (bytes_rcvd > maxrx_bytes && (rsr & PktRxOk)) { /* too many bytes received during this int, drop the rest of the * packets */ - lp->stats.rx_dropped++; + dev->stats.rx_dropped++; DEBUG(2, "%s: RX drop, too much done\n", dev->name); } else if (rsr & PktRxOk) { struct sk_buff *skb; @@ -1186,7 +1184,7 @@ xirc2ps_interrupt(int irq, void *dev_id) if (!skb) { printk(KNOT_XIRC "low memory, packet dropped (size=%u)\n", pktlen); - lp->stats.rx_dropped++; + dev->stats.rx_dropped++; } else { /* okay get the packet */ skb_reserve(skb, 2); if (lp->silicon == 0 ) { /* work around a hardware bug */ @@ -1242,24 +1240,24 @@ xirc2ps_interrupt(int irq, void *dev_id) } skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); - lp->stats.rx_packets++; - lp->stats.rx_bytes += pktlen; + dev->stats.rx_packets++; + dev->stats.rx_bytes += pktlen; if (!(rsr & PhyPkt)) - lp->stats.multicast++; + dev->stats.multicast++; } } else { /* bad packet */ DEBUG(5, "rsr=%#02x\n", rsr); } if (rsr & PktTooLong) { - lp->stats.rx_frame_errors++; + dev->stats.rx_frame_errors++; DEBUG(3, "%s: Packet too long\n", dev->name); } if (rsr & CRCErr) { - lp->stats.rx_crc_errors++; + dev->stats.rx_crc_errors++; DEBUG(3, "%s: CRC error\n", dev->name); } if (rsr & AlignErr) { - lp->stats.rx_fifo_errors++; /* okay ? */ + dev->stats.rx_fifo_errors++; /* okay ? */ DEBUG(3, "%s: Alignment error\n", dev->name); } @@ -1270,7 +1268,7 @@ xirc2ps_interrupt(int irq, void *dev_id) eth_status = GetByte(XIRCREG_ESR); } if (rx_status & 0x10) { /* Receive overrun */ - lp->stats.rx_over_errors++; + dev->stats.rx_over_errors++; PutByte(XIRCREG_CR, ClearRxOvrun); DEBUG(3, "receive overrun cleared\n"); } @@ -1283,11 +1281,11 @@ xirc2ps_interrupt(int irq, void *dev_id) nn = GetByte(XIRCREG0_PTR); lp->last_ptr_value = nn; if (nn < n) /* rollover */ - lp->stats.tx_packets += 256 - n; + dev->stats.tx_packets += 256 - n; else if (n == nn) { /* happens sometimes - don't know why */ DEBUG(0, "PTR not changed?\n"); } else - lp->stats.tx_packets += lp->last_ptr_value - n; + dev->stats.tx_packets += lp->last_ptr_value - n; netif_wake_queue(dev); } if (tx_status & 0x0002) { /* Execessive collissions */ @@ -1295,7 +1293,7 @@ xirc2ps_interrupt(int irq, void *dev_id) PutByte(XIRCREG_CR, RestartTx); /* restart transmitter process */ } if (tx_status & 0x0040) - lp->stats.tx_aborted_errors++; + dev->stats.tx_aborted_errors++; /* recalculate our work chunk so that we limit the duration of this * ISR to about 1/10 of a second. @@ -1353,7 +1351,7 @@ static void xirc_tx_timeout(struct net_device *dev) { local_info_t *lp = netdev_priv(dev); - lp->stats.tx_errors++; + dev->stats.tx_errors++; printk(KERN_NOTICE "%s: transmit timed out\n", dev->name); schedule_work(&lp->tx_timeout_task); } @@ -1409,20 +1407,11 @@ do_start_xmit(struct sk_buff *skb, struct net_device *dev) dev_kfree_skb (skb); dev->trans_start = jiffies; - lp->stats.tx_bytes += pktlen; + dev->stats.tx_bytes += pktlen; netif_start_queue(dev); return 0; } -static struct net_device_stats * -do_get_stats(struct net_device *dev) -{ - local_info_t *lp = netdev_priv(dev); - - /* lp->stats.rx_missed_errors = GetByte(?) */ - return &lp->stats; -} - /**************** * Set all addresses: This first one is the individual address, * the next 9 addresses are taken from the multicast list and -- GitLab From 0cd6e828a3cfb9c5bb71827ae6ee1564bf465f48 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:08 +0000 Subject: [PATCH 3856/4982] xirc2ps: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/pcmcia/xirc2ps_cs.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index f8fdf8997e0..a3685c0d22f 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -545,6 +545,19 @@ mii_wr(unsigned int ioaddr, u_char phyaddr, u_char phyreg, unsigned data, /*============= Main bulk of functions =========================*/ +static const struct net_device_ops netdev_ops = { + .ndo_open = do_open, + .ndo_stop = do_stop, + .ndo_start_xmit = do_start_xmit, + .ndo_tx_timeout = xirc_tx_timeout, + .ndo_set_config = do_config, + .ndo_do_ioctl = do_ioctl, + .ndo_set_multicast_list = set_multicast_list, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + /**************** * xirc2ps_attach() creates an "instance" of the driver, allocating * local data structures for one device. The device is registered @@ -580,18 +593,10 @@ xirc2ps_probe(struct pcmcia_device *link) link->irq.Instance = dev; /* Fill in card specific entries */ - dev->hard_start_xmit = &do_start_xmit; - dev->set_config = &do_config; - dev->do_ioctl = &do_ioctl; - SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); - dev->set_multicast_list = &set_multicast_list; - dev->open = &do_open; - dev->stop = &do_stop; -#ifdef HAVE_TX_TIMEOUT - dev->tx_timeout = xirc_tx_timeout; + dev->netdev_ops = &netdev_ops; + dev->ethtool_ops = &netdev_ethtool_ops; dev->watchdog_timeo = TX_TIMEOUT; INIT_WORK(&local->tx_timeout_task, xirc2ps_tx_timeout_task); -#endif return xirc2ps_config(link); } /* xirc2ps_attach */ -- GitLab From 6fb7298cdbe200b3b19cd59046785aecb0844198 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:09 +0000 Subject: [PATCH 3857/4982] smc91c92: convert to internal net_device_stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/pcmcia/smc91c92_cs.c | 56 +++++++++++++------------------- 1 file changed, 22 insertions(+), 34 deletions(-) diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index fccd53ef3c6..41de04162e9 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -108,7 +108,7 @@ struct smc_private { spinlock_t lock; u_short manfid; u_short cardid; - struct net_device_stats stats; + dev_node_t node; struct sk_buff *saved_skb; int packets_waiting; @@ -289,7 +289,6 @@ static void smc_tx_timeout(struct net_device *dev); static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev); static irqreturn_t smc_interrupt(int irq, void *dev_id); static void smc_rx(struct net_device *dev); -static struct net_device_stats *smc_get_stats(struct net_device *dev); static void set_rx_mode(struct net_device *dev); static int s9k_config(struct net_device *dev, struct ifmap *map); static void smc_set_xcvr(struct net_device *dev, int if_port); @@ -337,7 +336,6 @@ static int smc91c92_probe(struct pcmcia_device *link) /* The SMC91c92-specific entries in the device structure. */ dev->hard_start_xmit = &smc_start_xmit; - dev->get_stats = &smc_get_stats; dev->set_config = &s9k_config; dev->set_multicast_list = &set_rx_mode; dev->open = &smc_open; @@ -1291,7 +1289,7 @@ static void smc_hardware_send_packet(struct net_device * dev) return; } - smc->stats.tx_bytes += skb->len; + dev->stats.tx_bytes += skb->len; /* The card should use the just-allocated buffer. */ outw(packet_no, ioaddr + PNR_ARR); /* point to the beginning of the packet */ @@ -1340,7 +1338,7 @@ static void smc_tx_timeout(struct net_device *dev) printk(KERN_NOTICE "%s: SMC91c92 transmit timed out, " "Tx_status %2.2x status %4.4x.\n", dev->name, inw(ioaddr)&0xff, inw(ioaddr + 2)); - smc->stats.tx_errors++; + dev->stats.tx_errors++; smc_reset(dev); dev->trans_start = jiffies; smc->saved_skb = NULL; @@ -1362,7 +1360,7 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev) if (smc->saved_skb) { /* THIS SHOULD NEVER HAPPEN. */ - smc->stats.tx_aborted_errors++; + dev->stats.tx_aborted_errors++; printk(KERN_DEBUG "%s: Internal error -- sent packet while busy.\n", dev->name); return 1; @@ -1375,7 +1373,7 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev) printk(KERN_ERR "%s: Far too big packet error.\n", dev->name); dev_kfree_skb (skb); smc->saved_skb = NULL; - smc->stats.tx_dropped++; + dev->stats.tx_dropped++; return 0; /* Do not re-queue this packet. */ } /* A packet is now waiting. */ @@ -1433,11 +1431,11 @@ static void smc_tx_err(struct net_device * dev) tx_status = inw(ioaddr + DATA_1); - smc->stats.tx_errors++; - if (tx_status & TS_LOSTCAR) smc->stats.tx_carrier_errors++; - if (tx_status & TS_LATCOL) smc->stats.tx_window_errors++; + dev->stats.tx_errors++; + if (tx_status & TS_LOSTCAR) dev->stats.tx_carrier_errors++; + if (tx_status & TS_LATCOL) dev->stats.tx_window_errors++; if (tx_status & TS_16COL) { - smc->stats.tx_aborted_errors++; + dev->stats.tx_aborted_errors++; smc->tx_err++; } @@ -1474,10 +1472,10 @@ static void smc_eph_irq(struct net_device *dev) /* Could be a counter roll-over warning: update stats. */ card_stats = inw(ioaddr + COUNTER); /* single collisions */ - smc->stats.collisions += card_stats & 0xF; + dev->stats.collisions += card_stats & 0xF; card_stats >>= 4; /* multiple collisions */ - smc->stats.collisions += card_stats & 0xF; + dev->stats.collisions += card_stats & 0xF; #if 0 /* These are for when linux supports these statistics */ card_stats >>= 4; /* deferred */ card_stats >>= 4; /* excess deferred */ @@ -1551,7 +1549,7 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id) if (status & IM_TX_EMPTY_INT) { outw(IM_TX_EMPTY_INT, ioaddr + INTERRUPT); mask &= ~IM_TX_EMPTY_INT; - smc->stats.tx_packets += smc->packets_waiting; + dev->stats.tx_packets += smc->packets_waiting; smc->packets_waiting = 0; } if (status & IM_ALLOC_INT) { @@ -1567,8 +1565,8 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id) netif_wake_queue(dev); } if (status & IM_RX_OVRN_INT) { - smc->stats.rx_errors++; - smc->stats.rx_fifo_errors++; + dev->stats.rx_errors++; + dev->stats.rx_fifo_errors++; if (smc->duplex) smc->rx_ovrn = 1; /* need MC_RESET outside smc_interrupt */ outw(IM_RX_OVRN_INT, ioaddr + INTERRUPT); @@ -1618,7 +1616,6 @@ irq_done: static void smc_rx(struct net_device *dev) { - struct smc_private *smc = netdev_priv(dev); unsigned int ioaddr = dev->base_addr; int rx_status; int packet_length; /* Caution: not frame length, rather words @@ -1649,7 +1646,7 @@ static void smc_rx(struct net_device *dev) if (skb == NULL) { DEBUG(1, "%s: Low memory, packet dropped.\n", dev->name); - smc->stats.rx_dropped++; + dev->stats.rx_dropped++; outw(MC_RELEASE, ioaddr + MMU_CMD); return; } @@ -1662,18 +1659,18 @@ static void smc_rx(struct net_device *dev) netif_rx(skb); dev->last_rx = jiffies; - smc->stats.rx_packets++; - smc->stats.rx_bytes += packet_length; + dev->stats.rx_packets++; + dev->stats.rx_bytes += packet_length; if (rx_status & RS_MULTICAST) - smc->stats.multicast++; + dev->stats.multicast++; } else { /* error ... */ - smc->stats.rx_errors++; + dev->stats.rx_errors++; - if (rx_status & RS_ALGNERR) smc->stats.rx_frame_errors++; + if (rx_status & RS_ALGNERR) dev->stats.rx_frame_errors++; if (rx_status & (RS_TOOSHORT | RS_TOOLONG)) - smc->stats.rx_length_errors++; - if (rx_status & RS_BADCRC) smc->stats.rx_crc_errors++; + dev->stats.rx_length_errors++; + if (rx_status & RS_BADCRC) dev->stats.rx_crc_errors++; } /* Let the MMU free the memory of this packet. */ outw(MC_RELEASE, ioaddr + MMU_CMD); @@ -1681,15 +1678,6 @@ static void smc_rx(struct net_device *dev) return; } -/*====================================================================*/ - -static struct net_device_stats *smc_get_stats(struct net_device *dev) -{ - struct smc_private *smc = netdev_priv(dev); - /* Nothing to update - the 91c92 is a pretty primative chip. */ - return &smc->stats; -} - /*====================================================================== Calculate values for the hardware multicast filter hash table. -- GitLab From 9b31b6971f448796768860e3c9ee2d22f4511731 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:10 +0000 Subject: [PATCH 3858/4982] smc91c92: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/pcmcia/smc91c92_cs.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 41de04162e9..774232c13b3 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -300,6 +300,19 @@ static void mdio_write(struct net_device *dev, int phy_id, int loc, int value); static int smc_link_ok(struct net_device *dev); static const struct ethtool_ops ethtool_ops; +static const struct net_device_ops smc_netdev_ops = { + .ndo_open = smc_open, + .ndo_stop = smc_close, + .ndo_start_xmit = smc_start_xmit, + .ndo_tx_timeout = smc_tx_timeout, + .ndo_set_config = s9k_config, + .ndo_set_multicast_list = set_rx_mode, + .ndo_do_ioctl = &smc_ioctl, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + /*====================================================================== smc91c92_attach() creates an "instance" of the driver, allocating @@ -335,17 +348,9 @@ static int smc91c92_probe(struct pcmcia_device *link) link->conf.IntType = INT_MEMORY_AND_IO; /* The SMC91c92-specific entries in the device structure. */ - dev->hard_start_xmit = &smc_start_xmit; - dev->set_config = &s9k_config; - dev->set_multicast_list = &set_rx_mode; - dev->open = &smc_open; - dev->stop = &smc_close; - dev->do_ioctl = &smc_ioctl; + dev->netdev_ops = &smc_netdev_ops; SET_ETHTOOL_OPS(dev, ðtool_ops); -#ifdef HAVE_TX_TIMEOUT - dev->tx_timeout = smc_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; -#endif smc->mii_if.dev = dev; smc->mii_if.mdio_read = mdio_read; -- GitLab From 3dd205165e076eacf09575f0c90031e7c52bc5e1 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:11 +0000 Subject: [PATCH 3859/4982] axnet: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/pcmcia/axnet_cs.c | 68 ++++++++++++++--------------------- 1 file changed, 26 insertions(+), 42 deletions(-) diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 871ad2958ff..501a8d7ac2b 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include "../8390.h" @@ -91,6 +92,10 @@ static void axnet_release(struct pcmcia_device *link); static int axnet_open(struct net_device *dev); static int axnet_close(struct net_device *dev); static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +static int axnet_start_xmit(struct sk_buff *skb, struct net_device *dev); +static struct net_device_stats *get_stats(struct net_device *dev); +static void set_multicast_list(struct net_device *dev); +static void axnet_tx_timeout(struct net_device *dev); static const struct ethtool_ops netdev_ethtool_ops; static irqreturn_t ei_irq_wrapper(int irq, void *dev_id); static void ei_watchdog(u_long arg); @@ -108,7 +113,6 @@ static void block_output(struct net_device *dev, int count, static void axnet_detach(struct pcmcia_device *p_dev); -static void axdev_setup(struct net_device *dev); static void AX88190_init(struct net_device *dev, int startp); static int ax_open(struct net_device *dev); static int ax_close(struct net_device *dev); @@ -134,6 +138,19 @@ static inline axnet_dev_t *PRIV(struct net_device *dev) return p; } +static const struct net_device_ops axnet_netdev_ops = { + .ndo_open = axnet_open, + .ndo_stop = axnet_close, + .ndo_do_ioctl = axnet_ioctl, + .ndo_start_xmit = axnet_start_xmit, + .ndo_tx_timeout = axnet_tx_timeout, + .ndo_get_stats = get_stats, + .ndo_set_multicast_list = set_multicast_list, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + /*====================================================================== axnet_attach() creates an "instance" of the driver, allocating @@ -146,15 +163,17 @@ static int axnet_probe(struct pcmcia_device *link) { axnet_dev_t *info; struct net_device *dev; + struct ei_device *ei_local; DEBUG(0, "axnet_attach()\n"); - dev = alloc_netdev(sizeof(struct ei_device) + sizeof(axnet_dev_t), - "eth%d", axdev_setup); - + dev = alloc_etherdev(sizeof(struct ei_device) + sizeof(axnet_dev_t)); if (!dev) return -ENOMEM; + ei_local = netdev_priv(dev); + spin_lock_init(&ei_local->page_lock); + info = PRIV(dev); info->p_dev = link; link->priv = dev; @@ -163,10 +182,10 @@ static int axnet_probe(struct pcmcia_device *link) link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; - dev->open = &axnet_open; - dev->stop = &axnet_close; - dev->do_ioctl = &axnet_ioctl; + dev->netdev_ops = &axnet_netdev_ops; + SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); + dev->watchdog_timeo = TX_TIMEOUT; return axnet_config(link); } /* axnet_attach */ @@ -905,14 +924,12 @@ int ei_debug = 1; /* Index to functions. */ static void ei_tx_intr(struct net_device *dev); static void ei_tx_err(struct net_device *dev); -static void axnet_tx_timeout(struct net_device *dev); static void ei_receive(struct net_device *dev); static void ei_rx_overrun(struct net_device *dev); /* Routines generic to NS8390-based boards. */ static void NS8390_trigger_send(struct net_device *dev, unsigned int length, int start_page); -static void set_multicast_list(struct net_device *dev); static void do_set_multicast_list(struct net_device *dev); /* @@ -954,15 +971,6 @@ static int ax_open(struct net_device *dev) unsigned long flags; struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); -#ifdef HAVE_TX_TIMEOUT - /* The card I/O part of the driver (e.g. 3c503) can hook a Tx timeout - wrapper that does e.g. media check & then calls axnet_tx_timeout. */ - if (dev->tx_timeout == NULL) - dev->tx_timeout = axnet_tx_timeout; - if (dev->watchdog_timeo <= 0) - dev->watchdog_timeo = TX_TIMEOUT; -#endif - /* * Grab the page lock so we own the register set, then call * the init function. @@ -1701,30 +1709,6 @@ static void set_multicast_list(struct net_device *dev) spin_unlock_irqrestore(&dev_lock(dev), flags); } -/** - * axdev_setup - init rest of 8390 device struct - * @dev: network device structure to init - * - * Initialize the rest of the 8390 device structure. Do NOT __init - * this, as it is used by 8390 based modular drivers too. - */ - -static void axdev_setup(struct net_device *dev) -{ - struct ei_device *ei_local; - if (ei_debug > 1) - printk(version_8390); - - ei_local = (struct ei_device *)netdev_priv(dev); - spin_lock_init(&ei_local->page_lock); - - dev->hard_start_xmit = &axnet_start_xmit; - dev->get_stats = get_stats; - dev->set_multicast_list = &set_multicast_list; - - ether_setup(dev); -} - /* This page of functions should be 8390 generic */ /* Follow National Semi's recommendations for initializing the "NIC". */ -- GitLab From 6a8eba3bf4643fa4f0f62af29c47728d5296ed15 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:12 +0000 Subject: [PATCH 3860/4982] x25_asy: convert to internal net_device_stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wan/x25_asy.c | 30 +++++++++++------------------- drivers/net/wan/x25_asy.h | 4 ---- 2 files changed, 11 insertions(+), 23 deletions(-) diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index e6e2ce3e7bc..d62844d7e93 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -142,7 +142,7 @@ static int x25_asy_change_mtu(struct net_device *dev, int newmtu) memcpy(sl->xbuff, sl->xhead, sl->xleft); } else { sl->xleft = 0; - sl->stats.tx_dropped++; + dev->stats.tx_dropped++; } } sl->xhead = sl->xbuff; @@ -153,7 +153,7 @@ static int x25_asy_change_mtu(struct net_device *dev, int newmtu) memcpy(sl->rbuff, rbuff, sl->rcount); } else { sl->rcount = 0; - sl->stats.rx_over_errors++; + dev->stats.rx_over_errors++; set_bit(SLF_ERROR, &sl->flags); } } @@ -188,18 +188,19 @@ static inline void x25_asy_unlock(struct x25_asy *sl) static void x25_asy_bump(struct x25_asy *sl) { + struct net_device *dev = sl->dev; struct sk_buff *skb; int count; int err; count = sl->rcount; - sl->stats.rx_bytes += count; + dev->stats.rx_bytes += count; skb = dev_alloc_skb(count+1); if (skb == NULL) { printk(KERN_WARNING "%s: memory squeeze, dropping packet.\n", sl->dev->name); - sl->stats.rx_dropped++; + dev->stats.rx_dropped++; return; } skb_push(skb, 1); /* LAPB internal control */ @@ -211,7 +212,7 @@ static void x25_asy_bump(struct x25_asy *sl) printk(KERN_DEBUG "x25_asy: data received err - %d\n", err); } else { netif_rx(skb); - sl->stats.rx_packets++; + dev->stats.rx_packets++; } } @@ -226,7 +227,7 @@ static void x25_asy_encaps(struct x25_asy *sl, unsigned char *icp, int len) len = mtu; printk(KERN_DEBUG "%s: truncating oversized transmit packet!\n", sl->dev->name); - sl->stats.tx_dropped++; + sl->dev->stats.tx_dropped++; x25_asy_unlock(sl); return; } @@ -266,7 +267,7 @@ static void x25_asy_write_wakeup(struct tty_struct *tty) if (sl->xleft <= 0) { /* Now serial buffer is almost free & we can start * transmission of another packet */ - sl->stats.tx_packets++; + sl->dev->stats.tx_packets++; clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); x25_asy_unlock(sl); return; @@ -383,7 +384,7 @@ static void x25_asy_data_transmit(struct net_device *dev, struct sk_buff *skb) /* We were not busy, so we are now... :-) */ if (skb != NULL) { x25_asy_lock(sl); - sl->stats.tx_bytes += skb->len; + dev->stats.tx_bytes += skb->len; x25_asy_encaps(sl, skb->data, skb->len); dev_kfree_skb(skb); } @@ -533,7 +534,7 @@ static void x25_asy_receive_buf(struct tty_struct *tty, while (count--) { if (fp && *fp++) { if (!test_and_set_bit(SLF_ERROR, &sl->flags)) - sl->stats.rx_errors++; + sl->dev->stats.rx_errors++; cp++; continue; } @@ -608,14 +609,6 @@ static void x25_asy_close_tty(struct tty_struct *tty) x25_asy_free(sl); } - -static struct net_device_stats *x25_asy_get_stats(struct net_device *dev) -{ - struct x25_asy *sl = netdev_priv(dev); - return &sl->stats; -} - - /************************************************************************ * STANDARD X.25 ENCAPSULATION * ************************************************************************/ @@ -682,7 +675,7 @@ static void x25_asy_unesc(struct x25_asy *sl, unsigned char s) sl->rbuff[sl->rcount++] = s; return; } - sl->stats.rx_over_errors++; + sl->dev->stats.rx_over_errors++; set_bit(SLF_ERROR, &sl->flags); } } @@ -739,7 +732,6 @@ static void x25_asy_setup(struct net_device *dev) dev->watchdog_timeo = HZ*20; dev->open = x25_asy_open_dev; dev->stop = x25_asy_close; - dev->get_stats = x25_asy_get_stats; dev->change_mtu = x25_asy_change_mtu; dev->hard_header_len = 0; dev->addr_len = 0; diff --git a/drivers/net/wan/x25_asy.h b/drivers/net/wan/x25_asy.h index 41770200ceb..8f0fc2e57e2 100644 --- a/drivers/net/wan/x25_asy.h +++ b/drivers/net/wan/x25_asy.h @@ -28,10 +28,6 @@ struct x25_asy { unsigned char *xbuff; /* transmitter buffer */ unsigned char *xhead; /* pointer to next byte to XMIT */ int xleft; /* bytes left in XMIT queue */ - - /* X.25 interface statistics. */ - struct net_device_stats stats; - int buffsize; /* Max buffers sizes */ unsigned long flags; /* Flag values/ mode etc */ -- GitLab From 48f26ad5c097d751caef070ba057448d8a9c9a8d Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:13 +0000 Subject: [PATCH 3861/4982] x25_asy: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wan/x25_asy.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index d62844d7e93..d67e208ab37 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -712,6 +712,14 @@ static int x25_asy_open_dev(struct net_device *dev) return 0; } +static const struct net_device_ops x25_asy_netdev_ops = { + .ndo_open = x25_asy_open_dev, + .ndo_stop = x25_asy_close, + .ndo_start_xmit = x25_asy_xmit, + .ndo_tx_timeout = x25_asy_timeout, + .ndo_change_mtu = x25_asy_change_mtu, +}; + /* Initialise the X.25 driver. Called by the device init code */ static void x25_asy_setup(struct net_device *dev) { @@ -727,12 +735,8 @@ static void x25_asy_setup(struct net_device *dev) */ dev->mtu = SL_MTU; - dev->hard_start_xmit = x25_asy_xmit; - dev->tx_timeout = x25_asy_timeout; + dev->netdev_ops = &x25_asy_netdev_ops; dev->watchdog_timeo = HZ*20; - dev->open = x25_asy_open_dev; - dev->stop = x25_asy_close; - dev->change_mtu = x25_asy_change_mtu; dev->hard_header_len = 0; dev->addr_len = 0; dev->type = ARPHRD_X25; -- GitLab From 07d117cf0a2c71160d3fcc0068d1f1fe1237c47a Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:14 +0000 Subject: [PATCH 3862/4982] dlci: convert to internal net_device_stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wan/dlci.c | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c index a297e3efa05..a1b0b0d7391 100644 --- a/drivers/net/wan/dlci.c +++ b/drivers/net/wan/dlci.c @@ -114,7 +114,7 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev) if (!pskb_may_pull(skb, sizeof(*hdr))) { printk(KERN_NOTICE "%s: invalid data no header\n", dev->name); - dlp->stats.rx_errors++; + dev->stats.rx_errors++; kfree_skb(skb); return; } @@ -127,7 +127,7 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev) if (hdr->control != FRAD_I_UI) { printk(KERN_NOTICE "%s: Invalid header flag 0x%02X.\n", dev->name, hdr->control); - dlp->stats.rx_errors++; + dev->stats.rx_errors++; } else switch(hdr->IP_NLPID) @@ -136,14 +136,14 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev) if (hdr->NLPID != FRAD_P_SNAP) { printk(KERN_NOTICE "%s: Unsupported NLPID 0x%02X.\n", dev->name, hdr->NLPID); - dlp->stats.rx_errors++; + dev->stats.rx_errors++; break; } if (hdr->OUI[0] + hdr->OUI[1] + hdr->OUI[2] != 0) { printk(KERN_NOTICE "%s: Unsupported organizationally unique identifier 0x%02X-%02X-%02X.\n", dev->name, hdr->OUI[0], hdr->OUI[1], hdr->OUI[2]); - dlp->stats.rx_errors++; + dev->stats.rx_errors++; break; } @@ -164,12 +164,12 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev) case FRAD_P_Q933: case FRAD_P_CLNP: printk(KERN_NOTICE "%s: Unsupported NLPID 0x%02X.\n", dev->name, hdr->pad); - dlp->stats.rx_errors++; + dev->stats.rx_errors++; break; default: printk(KERN_NOTICE "%s: Invalid pad byte 0x%02X.\n", dev->name, hdr->pad); - dlp->stats.rx_errors++; + dev->stats.rx_errors++; break; } @@ -178,9 +178,9 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev) /* we've set up the protocol, so discard the header */ skb_reset_mac_header(skb); skb_pull(skb, header); - dlp->stats.rx_bytes += skb->len; + dev->stats.rx_bytes += skb->len; netif_rx(skb); - dlp->stats.rx_packets++; + dev->stats.rx_packets++; } else dev_kfree_skb(skb); @@ -204,15 +204,15 @@ static int dlci_transmit(struct sk_buff *skb, struct net_device *dev) switch (ret) { case DLCI_RET_OK: - dlp->stats.tx_packets++; + dev->stats.tx_packets++; ret = 0; break; case DLCI_RET_ERR: - dlp->stats.tx_errors++; + dev->stats.tx_errors++; ret = 0; break; case DLCI_RET_DROP: - dlp->stats.tx_dropped++; + dev->stats.tx_dropped++; ret = 1; break; } @@ -342,15 +342,6 @@ static int dlci_close(struct net_device *dev) return 0; } -static struct net_device_stats *dlci_get_stats(struct net_device *dev) -{ - struct dlci_local *dlp; - - dlp = netdev_priv(dev); - - return(&dlp->stats); -} - static int dlci_add(struct dlci_add *dlci) { struct net_device *master, *slave; @@ -498,7 +489,6 @@ static void dlci_setup(struct net_device *dev) dev->do_ioctl = dlci_dev_ioctl; dev->hard_start_xmit = dlci_transmit; dev->header_ops = &dlci_header_ops; - dev->get_stats = dlci_get_stats; dev->change_mtu = dlci_change_mtu; dev->destructor = free_netdev; -- GitLab From 49e8abaf62dc6403f11313e8fefbc0f5e7a9f50f Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:15 +0000 Subject: [PATCH 3863/4982] dlci: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wan/dlci.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c index a1b0b0d7391..e8d155c3e59 100644 --- a/drivers/net/wan/dlci.c +++ b/drivers/net/wan/dlci.c @@ -200,7 +200,7 @@ static int dlci_transmit(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); - ret = dlp->slave->hard_start_xmit(skb, dlp->slave); + ret = dlp->slave->netdev_ops->ndo_start_xmit(skb, dlp->slave); switch (ret) { case DLCI_RET_OK: @@ -295,11 +295,9 @@ static int dlci_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static int dlci_change_mtu(struct net_device *dev, int new_mtu) { - struct dlci_local *dlp; - - dlp = netdev_priv(dev); + struct dlci_local *dlp = netdev_priv(dev); - return((*dlp->slave->change_mtu)(dlp->slave, new_mtu)); + return dev_set_mtu(dlp->slave, new_mtu); } static int dlci_open(struct net_device *dev) @@ -479,17 +477,21 @@ static const struct header_ops dlci_header_ops = { .create = dlci_header, }; +static const struct net_device_ops dlci_netdev_ops = { + .ndo_open = dlci_open, + .ndo_stop = dlci_close, + .ndo_do_ioctl = dlci_dev_ioctl, + .ndo_start_xmit = dlci_transmit, + .ndo_change_mtu = dlci_change_mtu, +}; + static void dlci_setup(struct net_device *dev) { struct dlci_local *dlp = netdev_priv(dev); dev->flags = 0; - dev->open = dlci_open; - dev->stop = dlci_close; - dev->do_ioctl = dlci_dev_ioctl; - dev->hard_start_xmit = dlci_transmit; dev->header_ops = &dlci_header_ops; - dev->change_mtu = dlci_change_mtu; + dev->netdev_ops = &dlci_netdev_ops; dev->destructor = free_netdev; dlp->receive = dlci_receive; -- GitLab From d9b06c47a9eddef7d8829f6763bdf601c435c6f2 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:16 +0000 Subject: [PATCH 3864/4982] cycx: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wan/cycx_x25.c | 41 +++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c index 5fa52923efa..35dea3bea95 100644 --- a/drivers/net/wan/cycx_x25.c +++ b/drivers/net/wan/cycx_x25.c @@ -355,12 +355,6 @@ static int cycx_wan_update(struct wan_device *wandev) return 0; } -/* callback to initialize device */ -static void cycx_x25_chan_setup(struct net_device *dev) -{ - dev->init = cycx_netdevice_init; -} - /* Create new logical channel. * This routine is called by the router when ROUTER_IFNEW IOCTL is being * handled. @@ -476,6 +470,27 @@ static const struct header_ops cycx_header_ops = { .rebuild = cycx_netdevice_rebuild_header, }; +static const struct net_device_ops cycx_netdev_ops = { + .ndo_init = cycx_netdevice_init, + .ndo_open = cycx_netdevice_open, + .ndo_stop = cycx_netdevice_stop, + .ndo_start_xmit = cycx_netdevice_hard_start_xmit, + .ndo_get_stats = cycx_netdevice_get_stats, +}; + +static void cycx_x25_chan_setup(struct net_device *dev) +{ + /* Initialize device driver entry points */ + dev->netdev_ops = &cycx_netdev_ops; + dev->header_ops = &cycx_header_ops; + + /* Initialize media-specific parameters */ + dev->mtu = CYCX_X25_CHAN_MTU; + dev->type = ARPHRD_HWX25; /* ARP h/w type */ + dev->hard_header_len = 0; /* media header length */ + dev->addr_len = 0; /* hardware address length */ +} + /* Initialize Linux network interface. * * This routine is called only once for each interface, during Linux network @@ -487,20 +502,6 @@ static int cycx_netdevice_init(struct net_device *dev) struct cycx_device *card = chan->card; struct wan_device *wandev = &card->wandev; - /* Initialize device driver entry points */ - dev->open = cycx_netdevice_open; - dev->stop = cycx_netdevice_stop; - dev->header_ops = &cycx_header_ops; - - dev->hard_start_xmit = cycx_netdevice_hard_start_xmit; - dev->get_stats = cycx_netdevice_get_stats; - - /* Initialize media-specific parameters */ - dev->mtu = CYCX_X25_CHAN_MTU; - dev->type = ARPHRD_HWX25; /* ARP h/w type */ - dev->hard_header_len = 0; /* media header length */ - dev->addr_len = 0; /* hardware address length */ - if (!chan->svc) *(__be16*)dev->dev_addr = htons(chan->lcn); -- GitLab From ea2ebaf822ad7cf9d2a1aa5f579be34c8c840202 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:17 +0000 Subject: [PATCH 3865/4982] lapbether: convert to internal net_device_stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wan/lapbether.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c index f85ca1b27f9..d0b8d0299de 100644 --- a/drivers/net/wan/lapbether.c +++ b/drivers/net/wan/lapbether.c @@ -55,7 +55,6 @@ struct lapbethdev { struct list_head node; struct net_device *ethdev; /* link to ethernet device */ struct net_device *axdev; /* lapbeth device (lapb#) */ - struct net_device_stats stats; /* some statistics */ }; static LIST_HEAD(lapbeth_devices); @@ -107,10 +106,9 @@ static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packe if (!netif_running(lapbeth->axdev)) goto drop_unlock; - lapbeth->stats.rx_packets++; - len = skb->data[0] + skb->data[1] * 256; - lapbeth->stats.rx_bytes += len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += len; skb_pull(skb, 2); /* Remove the length bytes */ skb_trim(skb, len); /* Set the length of the data */ @@ -210,8 +208,8 @@ static void lapbeth_data_transmit(struct net_device *ndev, struct sk_buff *skb) *ptr++ = size % 256; *ptr++ = size / 256; - lapbeth->stats.tx_packets++; - lapbeth->stats.tx_bytes += size; + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += size; skb->dev = dev = lapbeth->ethdev; @@ -254,15 +252,6 @@ static void lapbeth_disconnected(struct net_device *dev, int reason) netif_rx(skb); } -/* - * Statistics - */ -static struct net_device_stats *lapbeth_get_stats(struct net_device *dev) -{ - struct lapbethdev *lapbeth = netdev_priv(dev); - return &lapbeth->stats; -} - /* * Set AX.25 callsign */ @@ -321,7 +310,6 @@ static void lapbeth_setup(struct net_device *dev) dev->stop = lapbeth_close; dev->destructor = free_netdev; dev->set_mac_address = lapbeth_set_mac_address; - dev->get_stats = lapbeth_get_stats; dev->type = ARPHRD_X25; dev->hard_header_len = 3; dev->mtu = 1000; -- GitLab From 39549b1e83e640907b0ed58f76d3331c2ae40e3d Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:18 +0000 Subject: [PATCH 3866/4982] labether: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wan/lapbether.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c index d0b8d0299de..2dd78d20eb0 100644 --- a/drivers/net/wan/lapbether.c +++ b/drivers/net/wan/lapbether.c @@ -303,13 +303,17 @@ static int lapbeth_close(struct net_device *dev) /* ------------------------------------------------------------------------ */ +static const struct net_device_ops lapbeth_netdev_ops = { + .ndo_open = lapbeth_open, + .ndo_stop = lapbeth_close, + .ndo_start_xmit = lapbeth_xmit, + .ndo_set_mac_address = lapbeth_set_mac_address, +}; + static void lapbeth_setup(struct net_device *dev) { - dev->hard_start_xmit = lapbeth_xmit; - dev->open = lapbeth_open; - dev->stop = lapbeth_close; + dev->netdev_ops = &lapbeth_netdev_ops; dev->destructor = free_netdev; - dev->set_mac_address = lapbeth_set_mac_address; dev->type = ARPHRD_X25; dev->hard_header_len = 3; dev->mtu = 1000; -- GitLab From fe6c6fbbcdd6675244fbbde62a9790ca57bd2785 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:19 +0000 Subject: [PATCH 3867/4982] sbni: use internal net_device_stats Convert to use existing net_device_stats. This driver, has bad style, of using commas, when brackets should be used... Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wan/sbni.c | 68 ++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 42 deletions(-) diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c index 78f7bc92cbe..e3031607eaf 100644 --- a/drivers/net/wan/sbni.c +++ b/drivers/net/wan/sbni.c @@ -68,7 +68,6 @@ /* device private data */ struct net_local { - struct net_device_stats stats; struct timer_list watchdog; spinlock_t lock; @@ -117,7 +116,6 @@ static int sbni_open( struct net_device * ); static int sbni_close( struct net_device * ); static int sbni_start_xmit( struct sk_buff *, struct net_device * ); static int sbni_ioctl( struct net_device *, struct ifreq *, int ); -static struct net_device_stats *sbni_get_stats( struct net_device * ); static void set_multicast_list( struct net_device * ); static irqreturn_t sbni_interrupt( int, void * ); @@ -723,13 +721,11 @@ upload_data( struct net_device *dev, unsigned framelen, unsigned frameno, nl->wait_frameno = 0, nl->inppos = 0, #ifdef CONFIG_SBNI_MULTILINE - ((struct net_local *)netdev_priv(nl->master)) - ->stats.rx_errors++, - ((struct net_local *)netdev_priv(nl->master)) - ->stats.rx_missed_errors++; + nl->master->stats.rx_errors++, + nl->master->stats.rx_missed_errors++; #else - nl->stats.rx_errors++, - nl->stats.rx_missed_errors++; + dev->stats.rx_errors++, + dev->stats.rx_missed_errors++; #endif /* now skip all frames until is_first != 0 */ } else @@ -742,13 +738,11 @@ upload_data( struct net_device *dev, unsigned framelen, unsigned frameno, */ nl->wait_frameno = 0, #ifdef CONFIG_SBNI_MULTILINE - ((struct net_local *)netdev_priv(nl->master)) - ->stats.rx_errors++, - ((struct net_local *)netdev_priv(nl->master)) - ->stats.rx_crc_errors++; + nl->master->stats.rx_errors++, + nl->master->stats.rx_crc_errors++; #else - nl->stats.rx_errors++, - nl->stats.rx_crc_errors++; + dev->stats.rx_errors++, + dev->stats.rx_crc_errors++; #endif return frame_ok; @@ -756,15 +750,16 @@ upload_data( struct net_device *dev, unsigned framelen, unsigned frameno, static inline void -send_complete( struct net_local *nl ) +send_complete( struct net_device *dev ) { + struct net_local *nl = netdev_priv(dev); + #ifdef CONFIG_SBNI_MULTILINE - ((struct net_local *)netdev_priv(nl->master))->stats.tx_packets++; - ((struct net_local *)netdev_priv(nl->master))->stats.tx_bytes - += nl->tx_buf_p->len; + nl->master->stats.tx_packets++; + nl->master->stats.tx_bytes += nl->tx_buf_p->len; #else - nl->stats.tx_packets++; - nl->stats.tx_bytes += nl->tx_buf_p->len; + dev->stats.tx_packets++; + dev->stats.tx_bytes += nl->tx_buf_p->len; #endif dev_kfree_skb_irq( nl->tx_buf_p ); @@ -792,7 +787,7 @@ interpret_ack( struct net_device *dev, unsigned ack ) nl->maxframe, nl->tx_buf_p->len - nl->outpos); else - send_complete( nl ), + send_complete( dev ), #ifdef CONFIG_SBNI_MULTILINE netif_wake_queue( nl->master ); #else @@ -881,13 +876,11 @@ drop_xmit_queue( struct net_device *dev ) dev_kfree_skb_any( nl->tx_buf_p ), nl->tx_buf_p = NULL, #ifdef CONFIG_SBNI_MULTILINE - ((struct net_local *)netdev_priv(nl->master)) - ->stats.tx_errors++, - ((struct net_local *)netdev_priv(nl->master)) - ->stats.tx_carrier_errors++; + nl->master->stats.tx_errors++, + nl->master->stats.tx_carrier_errors++; #else - nl->stats.tx_errors++, - nl->stats.tx_carrier_errors++; + dev->stats.tx_errors++, + dev->stats.tx_carrier_errors++; #endif nl->tx_frameno = 0; @@ -1017,14 +1010,13 @@ indicate_pkt( struct net_device *dev ) #ifdef CONFIG_SBNI_MULTILINE skb->protocol = eth_type_trans( skb, nl->master ); netif_rx( skb ); - ++((struct net_local *)netdev_priv(nl->master))->stats.rx_packets; - ((struct net_local *)netdev_priv(nl->master))->stats.rx_bytes += - nl->inppos; + ++nl->master->stats.rx_packets; + nl->master->stats.rx_bytes += nl->inppos; #else skb->protocol = eth_type_trans( skb, dev ); netif_rx( skb ); - ++nl->stats.rx_packets; - nl->stats.rx_bytes += nl->inppos; + ++dev->stats.rx_packets; + dev->stats.rx_bytes += nl->inppos; #endif nl->rx_buf_p = NULL; /* protocol driver will clear this sk_buff */ } @@ -1197,7 +1189,7 @@ sbni_open( struct net_device *dev ) handler_attached: spin_lock( &nl->lock ); - memset( &nl->stats, 0, sizeof(struct net_device_stats) ); + memset( &dev->stats, 0, sizeof(struct net_device_stats) ); memset( &nl->in_stats, 0, sizeof(struct sbni_in_stats) ); card_start( dev ); @@ -1413,7 +1405,7 @@ enslave( struct net_device *dev, struct net_device *slave_dev ) /* Summary statistics of MultiLine operation will be stored in master's counters */ - memset( &snl->stats, 0, sizeof(struct net_device_stats) ); + memset( &slave_dev->stats, 0, sizeof(struct net_device_stats) ); netif_stop_queue( slave_dev ); netif_wake_queue( dev ); /* Now we are able to transmit */ @@ -1464,14 +1456,6 @@ emancipate( struct net_device *dev ) #endif - -static struct net_device_stats * -sbni_get_stats( struct net_device *dev ) -{ - return &((struct net_local *)netdev_priv(dev))->stats; -} - - static void set_multicast_list( struct net_device *dev ) { -- GitLab From 7dd0b6e0feca6cd4269e120d63c46eeb63164ca2 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:20 +0000 Subject: [PATCH 3868/4982] sbni: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wan/sbni.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c index e3031607eaf..f4211fe0f44 100644 --- a/drivers/net/wan/sbni.c +++ b/drivers/net/wan/sbni.c @@ -206,15 +206,21 @@ sbni_isa_probe( struct net_device *dev ) } } +static const struct net_device_ops sbni_netdev_ops = { + .ndo_open = sbni_open, + .ndo_stop = sbni_close, + .ndo_start_xmit = sbni_start_xmit, + .ndo_set_multicast_list = set_multicast_list, + .ndo_do_ioctl = sbni_ioctl, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + static void __init sbni_devsetup(struct net_device *dev) { ether_setup( dev ); - dev->open = &sbni_open; - dev->stop = &sbni_close; - dev->hard_start_xmit = &sbni_start_xmit; - dev->get_stats = &sbni_get_stats; - dev->set_multicast_list = &set_multicast_list; - dev->do_ioctl = &sbni_ioctl; + dev->netdev_ops = &sbni_netdev_ops; } int __init sbni_probe(int unit) @@ -227,6 +233,8 @@ int __init sbni_probe(int unit) if (!dev) return -ENOMEM; + dev->netdev_ops = &sbni_netdev_ops; + sprintf(dev->name, "sbni%d", unit); netdev_boot_setup_check(dev); -- GitLab From f56ef16eb0c30bf76acf7c2ac9ee68781a7aef6a Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:21 +0000 Subject: [PATCH 3869/4982] netwave: convert to internal net_device_stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/netwave_cs.c | 72 ++++++------------------------- 1 file changed, 14 insertions(+), 58 deletions(-) diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index 24caec6caf1..9e7e37f5cdc 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c @@ -210,10 +210,6 @@ static int netwave_rx( struct net_device *dev); static irqreturn_t netwave_interrupt(int irq, void *dev_id); static void netwave_watchdog(struct net_device *); -/* Statistics */ -static void update_stats(struct net_device *dev); -static struct net_device_stats *netwave_get_stats(struct net_device *dev); - /* Wireless extensions */ static struct iw_statistics* netwave_get_wireless_stats(struct net_device *dev); @@ -275,14 +271,9 @@ typedef struct netwave_private { int lastExec; struct timer_list watchdog; /* To avoid blocking state */ struct site_survey nss; - struct net_device_stats stats; struct iw_statistics iw_stats; /* Wireless stats */ } netwave_private; -#ifdef NETWAVE_STATS -static struct net_device_stats *netwave_get_stats(struct net_device *dev); -#endif - /* * The Netwave card is little-endian, so won't work for big endian * systems. @@ -413,7 +404,6 @@ static int netwave_probe(struct pcmcia_device *link) /* Netwave specific entries in the device structure */ dev->hard_start_xmit = &netwave_start_xmit; - dev->get_stats = &netwave_get_stats; dev->set_multicast_list = &set_multicast_list; /* wireless extensions */ dev->wireless_handlers = (struct iw_handler_def *)&netwave_handler_def; @@ -988,7 +978,7 @@ static int netwave_hw_xmit(unsigned char* data, int len, return 1; } - priv->stats.tx_bytes += len; + dev->stats.tx_bytes += len; DEBUG(3, "Transmitting with SPCQ %x SPU %x LIF %x ISPLQ %x\n", readb(ramBase + NETWAVE_EREG_SPCQ), @@ -1107,11 +1097,11 @@ static irqreturn_t netwave_interrupt(int irq, void* dev_id) rser = readb(ramBase + NETWAVE_EREG_RSER); if (rser & 0x04) { - ++priv->stats.rx_dropped; - ++priv->stats.rx_crc_errors; + ++dev->stats.rx_dropped; + ++dev->stats.rx_crc_errors; } if (rser & 0x02) - ++priv->stats.rx_frame_errors; + ++dev->stats.rx_frame_errors; /* Clear the RxErr bit in RSER. RSER+4 is the * write part. Also clear the RxCRC (0x04) and @@ -1125,8 +1115,8 @@ static irqreturn_t netwave_interrupt(int irq, void* dev_id) wait_WOC(iobase); writeb(0x40, ramBase + NETWAVE_EREG_ASCC); - /* Remember to count up priv->stats on error packets */ - ++priv->stats.rx_errors; + /* Remember to count up dev->stats on error packets */ + ++dev->stats.rx_errors; } /* TxDN */ if (status & 0x20) { @@ -1140,17 +1130,17 @@ static irqreturn_t netwave_interrupt(int irq, void* dev_id) /* Transmitting was okay, clear bits */ wait_WOC(iobase); writeb(0x2f, ramBase + NETWAVE_EREG_TSER + 4); - ++priv->stats.tx_packets; + ++dev->stats.tx_packets; } if (txStatus & 0xd0) { if (txStatus & 0x80) { - ++priv->stats.collisions; /* Because of /proc/net/dev*/ - /* ++priv->stats.tx_aborted_errors; */ + ++dev->stats.collisions; /* Because of /proc/net/dev*/ + /* ++dev->stats.tx_aborted_errors; */ /* printk("Collision. %ld\n", jiffies - dev->trans_start); */ } if (txStatus & 0x40) - ++priv->stats.tx_carrier_errors; + ++dev->stats.tx_carrier_errors; /* 0x80 TxGU Transmit giveup - nine times and no luck * 0x40 TxNOAP No access point. Discarded packet. * 0x10 TxErr Transmit error. Always set when @@ -1163,7 +1153,7 @@ static irqreturn_t netwave_interrupt(int irq, void* dev_id) /* Clear out TxGU, TxNOAP, TxErr and TxTrys */ wait_WOC(iobase); writeb(0xdf & txStatus, ramBase+NETWAVE_EREG_TSER+4); - ++priv->stats.tx_errors; + ++dev->stats.tx_errors; } DEBUG(3, "New status is TSER %x ASR %x\n", readb(ramBase + NETWAVE_EREG_TSER), @@ -1197,40 +1187,6 @@ static void netwave_watchdog(struct net_device *dev) { netif_wake_queue(dev); } /* netwave_watchdog */ -static struct net_device_stats *netwave_get_stats(struct net_device *dev) { - netwave_private *priv = netdev_priv(dev); - - update_stats(dev); - - DEBUG(2, "netwave: SPCQ %x SPU %x LIF %x ISPLQ %x MHS %x rxtx %x" - " %x tx %x %x %x %x\n", - readb(priv->ramBase + NETWAVE_EREG_SPCQ), - readb(priv->ramBase + NETWAVE_EREG_SPU), - readb(priv->ramBase + NETWAVE_EREG_LIF), - readb(priv->ramBase + NETWAVE_EREG_ISPLQ), - readb(priv->ramBase + NETWAVE_EREG_MHS), - readb(priv->ramBase + NETWAVE_EREG_EC + 0xe), - readb(priv->ramBase + NETWAVE_EREG_EC + 0xf), - readb(priv->ramBase + NETWAVE_EREG_EC + 0x18), - readb(priv->ramBase + NETWAVE_EREG_EC + 0x19), - readb(priv->ramBase + NETWAVE_EREG_EC + 0x1a), - readb(priv->ramBase + NETWAVE_EREG_EC + 0x1b)); - - return &priv->stats; -} - -static void update_stats(struct net_device *dev) { - //unsigned long flags; -/* netwave_private *priv = netdev_priv(dev); */ - - //spin_lock_irqsave(&priv->spinlock, flags); - -/* priv->stats.rx_packets = readb(priv->ramBase + 0x18e); - priv->stats.tx_packets = readb(priv->ramBase + 0x18f); */ - - //spin_unlock_irqrestore(&priv->spinlock, flags); -} - static int netwave_rx(struct net_device *dev) { netwave_private *priv = netdev_priv(dev); @@ -1274,7 +1230,7 @@ static int netwave_rx(struct net_device *dev) if (skb == NULL) { DEBUG(1, "netwave_rx: Could not allocate an sk_buff of " "length %d\n", rcvLen); - ++priv->stats.rx_dropped; + ++dev->stats.rx_dropped; /* Tell the adapter to skip the packet */ wait_WOC(iobase); writeb(NETWAVE_CMD_SRP, ramBase + NETWAVE_EREG_CB + 0); @@ -1307,8 +1263,8 @@ static int netwave_rx(struct net_device *dev) /* Queue packet for network layer */ netif_rx(skb); - priv->stats.rx_packets++; - priv->stats.rx_bytes += rcvLen; + dev->stats.rx_packets++; + dev->stats.rx_bytes += rcvLen; /* Got the packet, tell the adapter to skip it */ wait_WOC(iobase); -- GitLab From 1964e0dedf98e2fdf3bfd3ac8cf02d9e9aa803fb Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:22 +0000 Subject: [PATCH 3870/4982] netwave: convert to net_device_ops Also get rid of unneeded cast Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/netwave_cs.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index 9e7e37f5cdc..d63c8992f22 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c @@ -355,6 +355,17 @@ static struct iw_statistics *netwave_get_wireless_stats(struct net_device *dev) return &priv->iw_stats; } +static const struct net_device_ops netwave_netdev_ops = { + .ndo_open = netwave_open, + .ndo_stop = netwave_close, + .ndo_start_xmit = netwave_start_xmit, + .ndo_set_multicast_list = set_multicast_list, + .ndo_tx_timeout = netwave_watchdog, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + /* * Function netwave_attach (void) * @@ -403,16 +414,12 @@ static int netwave_probe(struct pcmcia_device *link) spin_lock_init(&priv->spinlock); /* Netwave specific entries in the device structure */ - dev->hard_start_xmit = &netwave_start_xmit; - dev->set_multicast_list = &set_multicast_list; + dev->netdev_ops = &netwave_netdev_ops; /* wireless extensions */ - dev->wireless_handlers = (struct iw_handler_def *)&netwave_handler_def; + dev->wireless_handlers = &netwave_handler_def; - dev->tx_timeout = &netwave_watchdog; dev->watchdog_timeo = TX_TIMEOUT; - dev->open = &netwave_open; - dev->stop = &netwave_close; link->irq.Instance = dev; return netwave_pcmcia_config( link); -- GitLab From 1cc5920f0f6077e36e259e149548ef9a94335382 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:23 +0000 Subject: [PATCH 3871/4982] strip: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/strip.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c index 39f525efdc8..f9520463269 100644 --- a/drivers/net/wireless/strip.c +++ b/drivers/net/wireless/strip.c @@ -2477,6 +2477,16 @@ static const struct header_ops strip_header_ops = { .rebuild = strip_rebuild_header, }; + +static const struct net_device_ops strip_netdev_ops = { + .ndo_open = strip_open_low, + .ndo_stop = strip_close_low, + .ndo_start_xmit = strip_xmit, + .ndo_set_mac_address = strip_set_mac_address, + .ndo_get_stats = strip_get_stats, + .ndo_change_mtu = strip_change_mtu, +}; + /* * This routine is called by DDI when the * (dynamically assigned) device is registered @@ -2503,18 +2513,8 @@ static void strip_dev_setup(struct net_device *dev) dev->dev_addr[0] = 0; dev->addr_len = sizeof(MetricomAddress); - /* - * Pointers to interface service routines. - */ - - dev->open = strip_open_low; - dev->stop = strip_close_low; - dev->hard_start_xmit = strip_xmit; - dev->header_ops = &strip_header_ops; - - dev->set_mac_address = strip_set_mac_address; - dev->get_stats = strip_get_stats; - dev->change_mtu = strip_change_mtu; + dev->header_ops = &strip_header_ops, + dev->netdev_ops = &strip_netdev_ops; } /* -- GitLab From 385e63fb1e469739e90b32f4c07fed48baf2721a Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:24 +0000 Subject: [PATCH 3872/4982] wavelan: convert to internal net_device_stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/wavelan_cs.c | 50 ++++++++++------------------- drivers/net/wireless/wavelan_cs.p.h | 6 ---- 2 files changed, 17 insertions(+), 39 deletions(-) diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index 1565a0a6097..90235fb3d86 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -1352,21 +1352,6 @@ wv_init_info(struct net_device * dev) * or wireless extensions */ -/*------------------------------------------------------------------*/ -/* - * Get the current ethernet statistics. This may be called with the - * card open or closed. - * Used when the user read /proc/net/dev - */ -static en_stats * -wavelan_get_stats(struct net_device * dev) -{ -#ifdef DEBUG_IOCTL_TRACE - printk(KERN_DEBUG "%s: <>wavelan_get_stats()\n", dev->name); -#endif - - return(&((net_local *)netdev_priv(dev))->stats); -} /*------------------------------------------------------------------*/ /* @@ -2817,7 +2802,7 @@ wv_packet_read(struct net_device * dev, printk(KERN_INFO "%s: wv_packet_read(): could not alloc_skb(%d, GFP_ATOMIC)\n", dev->name, sksize); #endif - lp->stats.rx_dropped++; + dev->stats.rx_dropped++; /* * Not only do we want to return here, but we also need to drop the * packet on the floor to clear the interrupt. @@ -2877,8 +2862,8 @@ wv_packet_read(struct net_device * dev, netif_rx(skb); /* Keep stats up to date */ - lp->stats.rx_packets++; - lp->stats.rx_bytes += sksize; + dev->stats.rx_packets++; + dev->stats.rx_bytes += sksize; #ifdef DEBUG_RX_TRACE printk(KERN_DEBUG "%s: <-wv_packet_read()\n", dev->name); @@ -2980,13 +2965,13 @@ wv_packet_rcv(struct net_device * dev) /* Check status */ if((status & RX_RCV_OK) != RX_RCV_OK) { - lp->stats.rx_errors++; + dev->stats.rx_errors++; if(status & RX_NO_SFD) - lp->stats.rx_frame_errors++; + dev->stats.rx_frame_errors++; if(status & RX_CRC_ERR) - lp->stats.rx_crc_errors++; + dev->stats.rx_crc_errors++; if(status & RX_OVRRUN) - lp->stats.rx_over_errors++; + dev->stats.rx_over_errors++; #ifdef DEBUG_RX_FAIL printk(KERN_DEBUG "%s: wv_packet_rcv(): packet not received ok, status = 0x%x\n", @@ -3073,7 +3058,7 @@ wv_packet_write(struct net_device * dev, dev->trans_start = jiffies; /* Keep stats up to date */ - lp->stats.tx_bytes += length; + dev->stats.tx_bytes += length; spin_unlock_irqrestore(&lp->spinlock, flags); @@ -4106,7 +4091,7 @@ wavelan_interrupt(int irq, printk(KERN_INFO "%s: wv_interrupt(): receive buffer overflow\n", dev->name); #endif - lp->stats.rx_over_errors++; + dev->stats.rx_over_errors++; lp->overrunning = 1; } @@ -4155,7 +4140,7 @@ wavelan_interrupt(int irq, /* Check for possible errors */ if((tx_status & TX_OK) != TX_OK) { - lp->stats.tx_errors++; + dev->stats.tx_errors++; if(tx_status & TX_FRTL) { @@ -4170,14 +4155,14 @@ wavelan_interrupt(int irq, printk(KERN_DEBUG "%s: wv_interrupt(): DMA underrun\n", dev->name); #endif - lp->stats.tx_aborted_errors++; + dev->stats.tx_aborted_errors++; } if(tx_status & TX_LOST_CTS) { #ifdef DEBUG_TX_FAIL printk(KERN_DEBUG "%s: wv_interrupt(): no CTS\n", dev->name); #endif - lp->stats.tx_carrier_errors++; + dev->stats.tx_carrier_errors++; } if(tx_status & TX_LOST_CRS) { @@ -4185,14 +4170,14 @@ wavelan_interrupt(int irq, printk(KERN_DEBUG "%s: wv_interrupt(): no carrier\n", dev->name); #endif - lp->stats.tx_carrier_errors++; + dev->stats.tx_carrier_errors++; } if(tx_status & TX_HRT_BEAT) { #ifdef DEBUG_TX_FAIL printk(KERN_DEBUG "%s: wv_interrupt(): heart beat\n", dev->name); #endif - lp->stats.tx_heartbeat_errors++; + dev->stats.tx_heartbeat_errors++; } if(tx_status & TX_DEFER) { @@ -4216,14 +4201,14 @@ wavelan_interrupt(int irq, #endif if(!(tx_status & TX_NCOL_MASK)) { - lp->stats.collisions += 0x10; + dev->stats.collisions += 0x10; } } } } /* if(!(tx_status & TX_OK)) */ - lp->stats.collisions += (tx_status & TX_NCOL_MASK); - lp->stats.tx_packets++; + dev->stats.collisions += (tx_status & TX_NCOL_MASK); + dev->stats.tx_packets++; netif_wake_queue(dev); outb(CR0_INT_ACK | OP0_NOP, LCCR(base)); /* Acknowledge the interrupt */ @@ -4514,7 +4499,6 @@ wavelan_probe(struct pcmcia_device *p_dev) dev->open = &wavelan_open; dev->stop = &wavelan_close; dev->hard_start_xmit = &wavelan_packet_xmit; - dev->get_stats = &wavelan_get_stats; dev->set_multicast_list = &wavelan_set_multicast_list; #ifdef SET_MAC_ADDRESS dev->set_mac_address = &wavelan_set_mac_address; diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h index 628192d7248..706fd3007d2 100644 --- a/drivers/net/wireless/wavelan_cs.p.h +++ b/drivers/net/wireless/wavelan_cs.p.h @@ -576,7 +576,6 @@ struct wavepoint_table /****************************** TYPES ******************************/ /* Shortcuts */ -typedef struct net_device_stats en_stats; typedef struct iw_statistics iw_stats; typedef struct iw_quality iw_qual; typedef struct iw_freq iw_freq; @@ -592,8 +591,6 @@ typedef u_char mac_addr[WAVELAN_ADDR_SIZE]; /* Hardware address */ * For each network interface, Linux keep data in two structure. "device" * keep the generic data (same format for everybody) and "net_local" keep * the additional specific data. - * Note that some of this specific data is in fact generic (en_stats, for - * example). */ struct net_local { @@ -601,7 +598,6 @@ struct net_local struct net_device * dev; /* Reverse link... */ spinlock_t spinlock; /* Serialize access to the hardware (SMP) */ struct pcmcia_device * link; /* pcmcia structure */ - en_stats stats; /* Ethernet interface statistics */ int nresets; /* Number of hw resets */ u_char configured; /* If it is configured */ u_char reconfig_82593; /* Need to reconfigure the controller */ @@ -694,8 +690,6 @@ static void static void wv_init_info(struct net_device *); /* display startup info */ /* ------------------- IOCTL, STATS & RECONFIG ------------------- */ -static en_stats * - wavelan_get_stats(struct net_device *); /* Give stats /proc/net/dev */ static iw_stats * wavelan_get_wireless_stats(struct net_device *); /* ----------------------- PACKET RECEPTION ----------------------- */ -- GitLab From 9db0ba0a8b8bb0fd6606b4ac17073b2984b2d797 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:25 +0000 Subject: [PATCH 3873/4982] wavelan: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/wavelan_cs.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index 90235fb3d86..e55b33961ae 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -4436,6 +4436,19 @@ wavelan_close(struct net_device * dev) return 0; } +static const struct net_device_ops wavelan_netdev_ops = { + .ndo_open = wavelan_open, + .ndo_stop = wavelan_close, + .ndo_start_xmit = wavelan_packet_xmit, + .ndo_set_multicast_list = wavelan_set_multicast_list, +#ifdef SET_MAC_ADDRESS + .ndo_set_mac_address = wavelan_set_mac_address, +#endif + .ndo_tx_timeout = wavelan_watchdog, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, +}; + /*------------------------------------------------------------------*/ /* * wavelan_attach() creates an "instance" of the driver, allocating @@ -4496,16 +4509,7 @@ wavelan_probe(struct pcmcia_device *p_dev) lp->dev = dev; /* wavelan NET3 callbacks */ - dev->open = &wavelan_open; - dev->stop = &wavelan_close; - dev->hard_start_xmit = &wavelan_packet_xmit; - dev->set_multicast_list = &wavelan_set_multicast_list; -#ifdef SET_MAC_ADDRESS - dev->set_mac_address = &wavelan_set_mac_address; -#endif /* SET_MAC_ADDRESS */ - - /* Set the watchdog timer */ - dev->tx_timeout = &wavelan_watchdog; + dev->netdev_ops = &wavelan_netdev_ops; dev->watchdog_timeo = WATCHDOG_JIFFIES; SET_ETHTOOL_OPS(dev, &ops); -- GitLab From 7ae41cc3c04b0e79b7c9c3e5cbb5222f181e3ca1 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:26 +0000 Subject: [PATCH 3874/4982] airo: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/airo.c | 63 ++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index f5e2dca083c..7e80aba8a14 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -2646,17 +2646,21 @@ static const struct header_ops airo_header_ops = { .parse = wll_header_parse, }; +static const struct net_device_ops airo11_netdev_ops = { + .ndo_open = airo_open, + .ndo_stop = airo_close, + .ndo_start_xmit = airo_start_xmit11, + .ndo_get_stats = airo_get_stats, + .ndo_set_mac_address = airo_set_mac_address, + .ndo_do_ioctl = airo_ioctl, + .ndo_change_mtu = airo_change_mtu, +}; + static void wifi_setup(struct net_device *dev) { + dev->netdev_ops = &airo11_netdev_ops; dev->header_ops = &airo_header_ops; - dev->hard_start_xmit = &airo_start_xmit11; - dev->get_stats = &airo_get_stats; - dev->set_mac_address = &airo_set_mac_address; - dev->do_ioctl = &airo_ioctl; dev->wireless_handlers = &airo_handler_def; - dev->change_mtu = &airo_change_mtu; - dev->open = &airo_open; - dev->stop = &airo_close; dev->type = ARPHRD_IEEE80211; dev->hard_header_len = ETH_HLEN; @@ -2739,6 +2743,33 @@ static void airo_networks_initialize(struct airo_info *ai) &ai->network_free_list); } +static const struct net_device_ops airo_netdev_ops = { + .ndo_open = airo_open, + .ndo_stop = airo_close, + .ndo_start_xmit = airo_start_xmit, + .ndo_get_stats = airo_get_stats, + .ndo_set_multicast_list = airo_set_multicast_list, + .ndo_set_mac_address = airo_set_mac_address, + .ndo_do_ioctl = airo_ioctl, + .ndo_change_mtu = airo_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + +static const struct net_device_ops mpi_netdev_ops = { + .ndo_open = airo_open, + .ndo_stop = airo_close, + .ndo_start_xmit = mpi_start_xmit, + .ndo_get_stats = airo_get_stats, + .ndo_set_multicast_list = airo_set_multicast_list, + .ndo_set_mac_address = airo_set_mac_address, + .ndo_do_ioctl = airo_ioctl, + .ndo_change_mtu = airo_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + + static struct net_device *_init_airo_card( unsigned short irq, int port, int is_pcmcia, struct pci_dev *pci, struct device *dmdev ) @@ -2776,22 +2807,16 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, goto err_out_free; airo_networks_initialize (ai); + skb_queue_head_init (&ai->txq); + /* The Airo-specific entries in the device structure. */ - if (test_bit(FLAG_MPI,&ai->flags)) { - skb_queue_head_init (&ai->txq); - dev->hard_start_xmit = &mpi_start_xmit; - } else - dev->hard_start_xmit = &airo_start_xmit; - dev->get_stats = &airo_get_stats; - dev->set_multicast_list = &airo_set_multicast_list; - dev->set_mac_address = &airo_set_mac_address; - dev->do_ioctl = &airo_ioctl; + if (test_bit(FLAG_MPI,&ai->flags)) + dev->netdev_ops = &mpi_netdev_ops; + else + dev->netdev_ops = &airo_netdev_ops; dev->wireless_handlers = &airo_handler_def; ai->wireless_data.spy_data = &ai->spy_data; dev->wireless_data = &ai->wireless_data; - dev->change_mtu = &airo_change_mtu; - dev->open = &airo_open; - dev->stop = &airo_close; dev->irq = irq; dev->base_addr = port; -- GitLab From 824f1dfdbef72578272e9303dd9515399da57f28 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:27 +0000 Subject: [PATCH 3875/4982] atmel: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/atmel.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index b06835a621a..857d84148b1 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -1495,6 +1495,17 @@ static int atmel_read_proc(char *page, char **start, off_t off, return len; } +static const struct net_device_ops atmel_netdev_ops = { + .ndo_open = atmel_open, + .ndo_stop = atmel_close, + .ndo_change_mtu = atmel_change_mtu, + .ndo_set_mac_address = atmel_set_mac_address, + .ndo_start_xmit = start_tx, + .ndo_do_ioctl = atmel_ioctl, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, +}; + struct net_device *init_atmel_card(unsigned short irq, unsigned long port, const AtmelFWType fw_type, struct device *sys_dev, @@ -1579,13 +1590,8 @@ struct net_device *init_atmel_card(unsigned short irq, unsigned long port, priv->management_timer.function = atmel_management_timer; priv->management_timer.data = (unsigned long) dev; - dev->open = atmel_open; - dev->stop = atmel_close; - dev->change_mtu = atmel_change_mtu; - dev->set_mac_address = atmel_set_mac_address; - dev->hard_start_xmit = start_tx; - dev->wireless_handlers = (struct iw_handler_def *)&atmel_handler_def; - dev->do_ioctl = atmel_ioctl; + dev->netdev_ops = &atmel_netdev_ops; + dev->wireless_handlers = &atmel_handler_def; dev->irq = irq; dev->base_addr = port; -- GitLab From 32f5a330090fdf7d4d663ff5bd979e186fe6aab6 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:28 +0000 Subject: [PATCH 3876/4982] raylan: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/ray_cs.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 7370edb4e0c..fa90d1d8d82 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -298,6 +298,19 @@ static char hop_pattern_length[] = { 1, static char rcsid[] = "Raylink/WebGear wireless LAN - Corey "; +static const struct net_device_ops ray_netdev_ops = { + .ndo_init = ray_dev_init, + .ndo_open = ray_open, + .ndo_stop = ray_dev_close, + .ndo_start_xmit = ray_dev_start_xmit, + .ndo_set_config = ray_dev_config, + .ndo_get_stats = ray_get_stats, + .ndo_set_multicast_list = set_multicast_list, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + /*============================================================================= ray_attach() creates an "instance" of the driver, allocating local data structures for one device. The device is registered @@ -347,9 +360,7 @@ static int ray_probe(struct pcmcia_device *p_dev) p_dev, dev, local, &ray_interrupt); /* Raylink entries in the device structure */ - dev->hard_start_xmit = &ray_dev_start_xmit; - dev->set_config = &ray_dev_config; - dev->get_stats = &ray_get_stats; + dev->netdev_ops = &ray_netdev_ops; SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); dev->wireless_handlers = &ray_handler_def; #ifdef WIRELESS_SPY @@ -357,12 +368,8 @@ static int ray_probe(struct pcmcia_device *p_dev) dev->wireless_data = &local->wireless_data; #endif /* WIRELESS_SPY */ - dev->set_multicast_list = &set_multicast_list; DEBUG(2, "ray_cs ray_attach calling ether_setup.)\n"); - dev->init = &ray_dev_init; - dev->open = &ray_open; - dev->stop = &ray_dev_close; netif_stop_queue(dev); init_timer(&local->timer); -- GitLab From 4255d411452f1fe4dbcb2de4de35a7a028c5415a Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:29 +0000 Subject: [PATCH 3877/4982] wl3501: convert to internal net_device_stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/wl3501.h | 2 +- drivers/net/wireless/wl3501_cs.c | 25 ++++++++++--------------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/wl3501.h b/drivers/net/wireless/wl3501.h index 59bb3a55ab4..8bce1a550a2 100644 --- a/drivers/net/wireless/wl3501.h +++ b/drivers/net/wireless/wl3501.h @@ -606,7 +606,7 @@ struct wl3501_card { u8 reg_domain; u8 version[2]; struct wl3501_scan_confirm bss_set[20]; - struct net_device_stats stats; + struct iw_statistics wstats; struct iw_spy_data spy_data; struct iw_public_data wireless_data; diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index c8d5c34e8dd..433ff5bcabf 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -1000,7 +1000,7 @@ static inline void wl3501_md_ind_interrupt(struct net_device *dev, if (!skb) { printk(KERN_WARNING "%s: Can't alloc a sk_buff of size %d.\n", dev->name, pkt_len); - this->stats.rx_dropped++; + dev->stats.rx_dropped++; } else { skb->dev = dev; skb_reserve(skb, 2); /* IP headers on 16 bytes boundaries */ @@ -1008,8 +1008,8 @@ static inline void wl3501_md_ind_interrupt(struct net_device *dev, wl3501_receive(this, skb->data, pkt_len); skb_put(skb, pkt_len); skb->protocol = eth_type_trans(skb, dev); - this->stats.rx_packets++; - this->stats.rx_bytes += skb->len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; netif_rx(skb); } } @@ -1311,7 +1311,7 @@ out: static void wl3501_tx_timeout(struct net_device *dev) { struct wl3501_card *this = netdev_priv(dev); - struct net_device_stats *stats = &this->stats; + struct net_device_stats *stats = &dev->stats; unsigned long flags; int rc; @@ -1346,11 +1346,11 @@ static int wl3501_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) if (enabled) wl3501_unblock_interrupt(this); if (rc) { - ++this->stats.tx_dropped; + ++dev->stats.tx_dropped; netif_stop_queue(dev); } else { - ++this->stats.tx_packets; - this->stats.tx_bytes += skb->len; + ++dev->stats.tx_packets; + dev->stats.tx_bytes += skb->len; kfree_skb(skb); if (this->tx_buffer_cnt < 2) @@ -1400,13 +1400,6 @@ fail: goto out; } -static struct net_device_stats *wl3501_get_stats(struct net_device *dev) -{ - struct wl3501_card *this = netdev_priv(dev); - - return &this->stats; -} - static struct iw_statistics *wl3501_get_wireless_stats(struct net_device *dev) { struct wl3501_card *this = netdev_priv(dev); @@ -1922,12 +1915,14 @@ static int wl3501_probe(struct pcmcia_device *p_dev) dev = alloc_etherdev(sizeof(struct wl3501_card)); if (!dev) goto out_link; + + dev->open = wl3501_open; dev->stop = wl3501_close; dev->hard_start_xmit = wl3501_hard_start_xmit; dev->tx_timeout = wl3501_tx_timeout; dev->watchdog_timeo = 5 * HZ; - dev->get_stats = wl3501_get_stats; + this = netdev_priv(dev); this->wireless_data.spy_data = &this->spy_data; this->p_dev = p_dev; -- GitLab From 85a151b760348e4693e54bc8cece89ab9d3dc81d Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:30 +0000 Subject: [PATCH 3878/4982] wl3501: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/wl3501_cs.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 433ff5bcabf..1f64d6033ab 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -1883,6 +1883,16 @@ static const struct iw_handler_def wl3501_handler_def = { .get_wireless_stats = wl3501_get_wireless_stats, }; +static const struct net_device_ops wl3501_netdev_ops = { + .ndo_open = wl3501_open, + .ndo_stop = wl3501_close, + .ndo_start_xmit = wl3501_hard_start_xmit, + .ndo_tx_timeout = wl3501_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + /** * wl3501_attach - creates an "instance" of the driver * @@ -1917,17 +1927,14 @@ static int wl3501_probe(struct pcmcia_device *p_dev) goto out_link; - dev->open = wl3501_open; - dev->stop = wl3501_close; - dev->hard_start_xmit = wl3501_hard_start_xmit; - dev->tx_timeout = wl3501_tx_timeout; + dev->netdev_ops = &wl3501_netdev_ops; dev->watchdog_timeo = 5 * HZ; this = netdev_priv(dev); this->wireless_data.spy_data = &this->spy_data; this->p_dev = p_dev; dev->wireless_data = &this->wireless_data; - dev->wireless_handlers = (struct iw_handler_def *)&wl3501_handler_def; + dev->wireless_handlers = &wl3501_handler_def; SET_ETHTOOL_OPS(dev, &ops); netif_stop_queue(dev); p_dev->priv = p_dev->irq.Instance = dev; -- GitLab From 22bc1ce4f171f53c27052e1d74d312345487db16 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:31 +0000 Subject: [PATCH 3879/4982] zd1201: convert to internal net_device_stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/zd1201.c | 29 ++++++++++------------------- drivers/net/wireless/zd1201.h | 1 - 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index 6226ac2357f..4d5f143cd58 100644 --- a/drivers/net/wireless/zd1201.c +++ b/drivers/net/wireless/zd1201.c @@ -328,8 +328,8 @@ static void zd1201_usbrx(struct urb *urb) memcpy(skb_put(skb, 2), &data[datalen-24], 2); memcpy(skb_put(skb, len), data, len); skb->protocol = eth_type_trans(skb, zd->dev); - zd->stats.rx_packets++; - zd->stats.rx_bytes += skb->len; + zd->dev->stats.rx_packets++; + zd->dev->stats.rx_bytes += skb->len; netif_rx(skb); goto resubmit; } @@ -384,8 +384,8 @@ static void zd1201_usbrx(struct urb *urb) memcpy(skb_put(skb, len), data+8, len); } skb->protocol = eth_type_trans(skb, zd->dev); - zd->stats.rx_packets++; - zd->stats.rx_bytes += skb->len; + zd->dev->stats.rx_packets++; + zd->dev->stats.rx_bytes += skb->len; netif_rx(skb); } resubmit: @@ -787,7 +787,7 @@ static int zd1201_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) struct urb *urb = zd->tx_urb; if (!zd->mac_enabled || zd->monitor) { - zd->stats.tx_dropped++; + dev->stats.tx_dropped++; kfree_skb(skb); return 0; } @@ -817,12 +817,12 @@ static int zd1201_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) err = usb_submit_urb(zd->tx_urb, GFP_ATOMIC); if (err) { - zd->stats.tx_errors++; + dev->stats.tx_errors++; netif_start_queue(dev); return err; } - zd->stats.tx_packets++; - zd->stats.tx_bytes += skb->len; + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; dev->trans_start = jiffies; kfree_skb(skb); @@ -838,7 +838,7 @@ static void zd1201_tx_timeout(struct net_device *dev) dev_warn(&zd->usb->dev, "%s: TX timeout, shooting down urb\n", dev->name); usb_unlink_urb(zd->tx_urb); - zd->stats.tx_errors++; + dev->stats.tx_errors++; /* Restart the timeout to quiet the watchdog: */ dev->trans_start = jiffies; } @@ -861,13 +861,6 @@ static int zd1201_set_mac_address(struct net_device *dev, void *p) return zd1201_mac_reset(zd); } -static struct net_device_stats *zd1201_get_stats(struct net_device *dev) -{ - struct zd1201 *zd = netdev_priv(dev); - - return &zd->stats; -} - static struct iw_statistics *zd1201_get_wireless_stats(struct net_device *dev) { struct zd1201 *zd = netdev_priv(dev); @@ -1778,9 +1771,7 @@ static int zd1201_probe(struct usb_interface *interface, dev->open = zd1201_net_open; dev->stop = zd1201_net_stop; - dev->get_stats = zd1201_get_stats; - dev->wireless_handlers = - (struct iw_handler_def *)&zd1201_iw_handlers; + dev->wireless_handlers = &zd1201_iw_handlers; dev->hard_start_xmit = zd1201_hard_start_xmit; dev->watchdog_timeo = ZD1201_TX_TIMEOUT; dev->tx_timeout = zd1201_tx_timeout; diff --git a/drivers/net/wireless/zd1201.h b/drivers/net/wireless/zd1201.h index 235f0ee34b2..dd7ea1f35be 100644 --- a/drivers/net/wireless/zd1201.h +++ b/drivers/net/wireless/zd1201.h @@ -26,7 +26,6 @@ struct zd1201 { struct usb_device *usb; int removed; struct net_device *dev; - struct net_device_stats stats; struct iw_statistics iwstats; int endp_in; -- GitLab From 2bd9f54d46e28fdaa15240af6a97c953720ea5c1 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:32 +0000 Subject: [PATCH 3880/4982] zd1201: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/zd1201.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index 4d5f143cd58..9b244c96b22 100644 --- a/drivers/net/wireless/zd1201.c +++ b/drivers/net/wireless/zd1201.c @@ -1717,6 +1717,18 @@ static const struct iw_handler_def zd1201_iw_handlers = { .get_wireless_stats = zd1201_get_wireless_stats, }; +static const struct net_device_ops zd1201_netdev_ops = { + .ndo_open = zd1201_net_open, + .ndo_stop = zd1201_net_stop, + .ndo_start_xmit = zd1201_hard_start_xmit, + .ndo_tx_timeout = zd1201_tx_timeout, + .ndo_set_multicast_list = zd1201_set_multicast, + .ndo_set_mac_address = zd1201_set_mac_address, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + static int zd1201_probe(struct usb_interface *interface, const struct usb_device_id *id) { @@ -1769,14 +1781,9 @@ static int zd1201_probe(struct usb_interface *interface, if (err) goto err_start; - dev->open = zd1201_net_open; - dev->stop = zd1201_net_stop; + dev->netdev_ops = &zd1201_netdev_ops; dev->wireless_handlers = &zd1201_iw_handlers; - dev->hard_start_xmit = zd1201_hard_start_xmit; dev->watchdog_timeo = ZD1201_TX_TIMEOUT; - dev->tx_timeout = zd1201_tx_timeout; - dev->set_multicast_list = zd1201_set_multicast; - dev->set_mac_address = zd1201_set_mac_address; strcpy(dev->name, "wlan%d"); err = zd1201_getconfig(zd, ZD1201_RID_CNFOWNMACADDR, -- GitLab From 98d2faaeb72a2db4ea232263ca4ce9dbfe8e1f5a Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:33 +0000 Subject: [PATCH 3881/4982] mac80211_hwsim: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/mac80211_hwsim.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index a15078bcad7..2368b7f825a 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -739,10 +739,16 @@ static struct device_driver mac80211_hwsim_driver = { .name = "mac80211_hwsim" }; +static const struct net_device_ops hwsim_netdev_ops = { + .ndo_start_xmit = hwsim_mon_xmit, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; static void hwsim_mon_setup(struct net_device *dev) { - dev->hard_start_xmit = hwsim_mon_xmit; + dev->netdev_ops = &hwsim_netdev_ops; dev->destructor = free_netdev; ether_setup(dev); dev->tx_queue_len = 0; -- GitLab From 6685254f80cdca085cb1d53c45a6d0d5d01f911e Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:34 +0000 Subject: [PATCH 3882/4982] prism54: convert to net_device_ops Also, make ethtool_ops const as it should be, and get rid of useless cast. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/prism54/islpci_dev.c | 28 +++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index 9196825ed1b..6e7d71c5409 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c @@ -804,10 +804,23 @@ static void islpci_ethtool_get_drvinfo(struct net_device *dev, strcpy(info->version, DRV_VERSION); } -static struct ethtool_ops islpci_ethtool_ops = { +static const struct ethtool_ops islpci_ethtool_ops = { .get_drvinfo = islpci_ethtool_get_drvinfo, }; +static const struct net_device_ops islpci_netdev_ops = { + .ndo_open = islpci_open, + .ndo_stop = islpci_close, + .ndo_get_stats = islpci_statistics, + .ndo_do_ioctl = prism54_ioctl, + .ndo_start_xmit = islpci_eth_transmit, + .ndo_tx_timeout = islpci_eth_tx_timeout, + .ndo_set_mac_address = prism54_set_mac_address, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + struct net_device * islpci_setup(struct pci_dev *pdev) { @@ -827,25 +840,16 @@ islpci_setup(struct pci_dev *pdev) ndev->irq = pdev->irq; /* initialize the function pointers */ - ndev->open = &islpci_open; - ndev->stop = &islpci_close; - ndev->get_stats = &islpci_statistics; - ndev->do_ioctl = &prism54_ioctl; - ndev->wireless_handlers = - (struct iw_handler_def *) &prism54_handler_def; + ndev->netdev_ops = &islpci_netdev_ops; + ndev->wireless_handlers = &prism54_handler_def; ndev->ethtool_ops = &islpci_ethtool_ops; - ndev->hard_start_xmit = &islpci_eth_transmit; /* ndev->set_multicast_list = &islpci_set_multicast_list; */ ndev->addr_len = ETH_ALEN; - ndev->set_mac_address = &prism54_set_mac_address; /* Get a non-zero dummy MAC address for nameif. Jean II */ memcpy(ndev->dev_addr, dummy_mac, 6); -#ifdef HAVE_TX_TIMEOUT ndev->watchdog_timeo = ISLPCI_TX_TIMEOUT; - ndev->tx_timeout = &islpci_eth_tx_timeout; -#endif /* allocate a private device structure to the network device */ priv = netdev_priv(ndev); -- GitLab From 6456fffb09a281af2644e73fda26d1eeec325830 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:35 +0000 Subject: [PATCH 3883/4982] prism54: convert to internal net_device_stats Also, make ethtool_ops const as it should be, and get rid of useless cast. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/prism54/islpci_dev.c | 14 -------------- drivers/net/wireless/prism54/islpci_dev.h | 3 --- drivers/net/wireless/prism54/islpci_eth.c | 13 ++++++------- 3 files changed, 6 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index 6e7d71c5409..166ed958460 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c @@ -43,7 +43,6 @@ static int prism54_bring_down(islpci_private *); static int islpci_alloc_memory(islpci_private *); -static struct net_device_stats *islpci_statistics(struct net_device *); /* Temporary dummy MAC address to use until firmware is loaded. * The idea there is that some tools (such as nameif) may query @@ -614,18 +613,6 @@ islpci_reset(islpci_private *priv, int reload_firmware) return rc; } -static struct net_device_stats * -islpci_statistics(struct net_device *ndev) -{ - islpci_private *priv = netdev_priv(ndev); - -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_FUNCTION_CALLS, "islpci_statistics\n"); -#endif - - return &priv->statistics; -} - /****************************************************************************** Network device configuration functions ******************************************************************************/ @@ -811,7 +798,6 @@ static const struct ethtool_ops islpci_ethtool_ops = { static const struct net_device_ops islpci_netdev_ops = { .ndo_open = islpci_open, .ndo_stop = islpci_close, - .ndo_get_stats = islpci_statistics, .ndo_do_ioctl = prism54_ioctl, .ndo_start_xmit = islpci_eth_transmit, .ndo_tx_timeout = islpci_eth_tx_timeout, diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h index 8e55a5fcffa..c4d0f19b7cb 100644 --- a/drivers/net/wireless/prism54/islpci_dev.h +++ b/drivers/net/wireless/prism54/islpci_dev.h @@ -158,9 +158,6 @@ typedef struct { dma_addr_t pci_map_tx_address[ISL38XX_CB_TX_QSIZE]; dma_addr_t pci_map_rx_address[ISL38XX_CB_RX_QSIZE]; - /* driver network interface members */ - struct net_device_stats statistics; - /* wait for a reset interrupt */ wait_queue_head_t reset_done; diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index 88895bd9e49..ef3ef4551b3 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c @@ -231,8 +231,8 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev) /* set the transmission time */ ndev->trans_start = jiffies; - priv->statistics.tx_packets++; - priv->statistics.tx_bytes += skb->len; + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += skb->len; /* trigger the device */ islpci_trigger(priv); @@ -243,7 +243,7 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev) return 0; drop_free: - priv->statistics.tx_dropped++; + ndev->stats.tx_dropped++; spin_unlock_irqrestore(&priv->slock, flags); dev_kfree_skb(skb); return err; @@ -408,8 +408,8 @@ islpci_eth_receive(islpci_private *priv) skb->protocol = eth_type_trans(skb, ndev); } skb->ip_summed = CHECKSUM_NONE; - priv->statistics.rx_packets++; - priv->statistics.rx_bytes += size; + ndev->stats.rx_packets++; + ndev->stats.rx_bytes += size; /* deliver the skb to the network layer */ #ifdef ISLPCI_ETH_DEBUG @@ -497,10 +497,9 @@ void islpci_eth_tx_timeout(struct net_device *ndev) { islpci_private *priv = netdev_priv(ndev); - struct net_device_stats *statistics = &priv->statistics; /* increment the transmit error counter */ - statistics->tx_errors++; + ndev->stats.tx_errors++; if (!priv->reset_task_pending) { printk(KERN_WARNING -- GitLab From bbfc6b788f63f079fb8eeeb8d397bb1c0a8065a1 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:36 +0000 Subject: [PATCH 3884/4982] libertas: convert to internal net_device_stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/libertas/dev.h | 1 - drivers/net/wireless/libertas/if_cs.c | 2 +- drivers/net/wireless/libertas/main.c | 26 +------------------------- drivers/net/wireless/libertas/rx.c | 18 +++++++++--------- drivers/net/wireless/libertas/tx.c | 8 ++++---- drivers/net/wireless/libertas/wext.c | 2 +- 6 files changed, 16 insertions(+), 41 deletions(-) diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index dd682c4cfde..27e81fd97c9 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -109,7 +109,6 @@ struct lbs_private { void *card; struct net_device *dev; - struct net_device_stats stats; struct net_device *mesh_dev; /* Virtual device */ struct net_device *rtap_net_dev; diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 8f8934a5ba3..cedeac6322f 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c @@ -421,7 +421,7 @@ static struct sk_buff *if_cs_receive_data(struct lbs_private *priv) len = if_cs_read16(priv->card, IF_CS_READ_LEN); if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { lbs_pr_err("card data buffer has invalid # of bytes (%d)\n", len); - priv->stats.rx_dropped++; + priv->dev->stats.rx_dropped++; goto dat_err; } diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index d93553f15e9..c27088d0541 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -582,20 +582,6 @@ void lbs_host_to_card_done(struct lbs_private *priv) } EXPORT_SYMBOL_GPL(lbs_host_to_card_done); -/** - * @brief This function returns the network statistics - * - * @param dev A pointer to struct lbs_private structure - * @return A pointer to net_device_stats structure - */ -static struct net_device_stats *lbs_get_stats(struct net_device *dev) -{ - struct lbs_private *priv = dev->ml_priv; - - lbs_deb_enter(LBS_DEB_NET); - return &priv->stats; -} - static int lbs_set_mac_address(struct net_device *dev, void *addr) { int ret = 0; @@ -1201,7 +1187,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) dev->stop = lbs_eth_stop; dev->set_mac_address = lbs_set_mac_address; dev->tx_timeout = lbs_tx_timeout; - dev->get_stats = lbs_get_stats; + dev->watchdog_timeo = 5 * HZ; dev->ethtool_ops = &lbs_ethtool_ops; #ifdef WIRELESS_EXT @@ -1443,7 +1429,6 @@ static int lbs_add_mesh(struct lbs_private *priv) mesh_dev->open = lbs_dev_open; mesh_dev->hard_start_xmit = lbs_hard_start_xmit; mesh_dev->stop = lbs_mesh_stop; - mesh_dev->get_stats = lbs_get_stats; mesh_dev->set_mac_address = lbs_set_mac_address; mesh_dev->ethtool_ops = &lbs_ethtool_ops; memcpy(mesh_dev->dev_addr, priv->dev->dev_addr, @@ -1648,14 +1633,6 @@ static int lbs_rtap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_BUSY; } -static struct net_device_stats *lbs_rtap_get_stats(struct net_device *dev) -{ - struct lbs_private *priv = dev->ml_priv; - lbs_deb_enter(LBS_DEB_NET); - return &priv->stats; -} - - static void lbs_remove_rtap(struct lbs_private *priv) { lbs_deb_enter(LBS_DEB_MAIN); @@ -1689,7 +1666,6 @@ static int lbs_add_rtap(struct lbs_private *priv) rtap_dev->type = ARPHRD_IEEE80211_RADIOTAP; rtap_dev->open = lbs_rtap_open; rtap_dev->stop = lbs_rtap_stop; - rtap_dev->get_stats = lbs_rtap_get_stats; rtap_dev->hard_start_xmit = lbs_rtap_hard_start_xmit; rtap_dev->ml_priv = priv; SET_NETDEV_DEV(rtap_dev, priv->dev->dev.parent); diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 079e6aa874d..4f60948dde9 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c @@ -168,7 +168,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) { lbs_deb_rx("rx err: frame received with bad length\n"); - priv->stats.rx_length_errors++; + dev->stats.rx_length_errors++; ret = 0; goto done; } @@ -179,7 +179,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) if (!(p_rx_pd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) { lbs_deb_rx("rx err: frame received with bad status\n"); lbs_pr_alert("rxpd not ok\n"); - priv->stats.rx_errors++; + dev->stats.rx_errors++; ret = 0; goto done; } @@ -243,8 +243,8 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) lbs_compute_rssi(priv, p_rx_pd); lbs_deb_rx("rx data: size of actual packet %d\n", skb->len); - priv->stats.rx_bytes += skb->len; - priv->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; + dev->stats.rx_packets++; skb->protocol = eth_type_trans(skb, dev); if (in_interrupt()) @@ -311,7 +311,7 @@ static int process_rxed_802_11_packet(struct lbs_private *priv, struct sk_buff *skb) { int ret = 0; - + struct net_device *dev = priv->dev; struct rx80211packethdr *p_rx_pkt; struct rxpd *prxpd; struct rx_radiotap_hdr radiotap_hdr; @@ -326,7 +326,7 @@ static int process_rxed_802_11_packet(struct lbs_private *priv, if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) { lbs_deb_rx("rx err: frame received with bad length\n"); - priv->stats.rx_length_errors++; + dev->stats.rx_length_errors++; ret = -EINVAL; kfree_skb(skb); goto done; @@ -337,7 +337,7 @@ static int process_rxed_802_11_packet(struct lbs_private *priv, */ if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) { //lbs_deb_rx("rx err: frame received with bad status\n"); - priv->stats.rx_errors++; + dev->stats.rx_errors++; } lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n", @@ -389,8 +389,8 @@ static int process_rxed_802_11_packet(struct lbs_private *priv, lbs_compute_rssi(priv, prxpd); lbs_deb_rx("rx data: size of actual packet %d\n", skb->len); - priv->stats.rx_bytes += skb->len; - priv->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; + dev->stats.rx_packets++; skb->protocol = eth_type_trans(skb, priv->rtap_net_dev); netif_rx(skb); diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index 68bec31ae03..f10aa39a6b6 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c @@ -82,8 +82,8 @@ int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) skb->len, MRVDRV_ETH_TX_PACKET_BUFFER_SIZE); /* We'll never manage to send this one; drop it and return 'OK' */ - priv->stats.tx_dropped++; - priv->stats.tx_errors++; + dev->stats.tx_dropped++; + dev->stats.tx_errors++; goto free; } @@ -146,8 +146,8 @@ int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) lbs_deb_tx("%s lined up packet\n", __func__); - priv->stats.tx_packets++; - priv->stats.tx_bytes += skb->len; + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; dev->trans_start = jiffies; diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index f16d136ab4b..8bc1907458b 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -830,7 +830,7 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) quality = rssi_qual; /* Quality by TX errors */ - priv->wstats.discard.retries = priv->stats.tx_errors; + priv->wstats.discard.retries = dev->stats.tx_errors; memset(&log, 0, sizeof(log)); log.hdr.size = cpu_to_le16(sizeof(log)); -- GitLab From f02abf1010dfb9fa7f56788fb28bc63b0ea34968 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:37 +0000 Subject: [PATCH 3885/4982] libertas: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/libertas/main.c | 45 ++++++++++++++++++---------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index c27088d0541..8ae935ac32f 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -1148,6 +1148,17 @@ static void lbs_free_adapter(struct lbs_private *priv) lbs_deb_leave(LBS_DEB_MAIN); } +static const struct net_device_ops lbs_netdev_ops = { + .ndo_open = lbs_dev_open, + .ndo_stop = lbs_eth_stop, + .ndo_start_xmit = lbs_hard_start_xmit, + .ndo_set_mac_address = lbs_set_mac_address, + .ndo_tx_timeout = lbs_tx_timeout, + .ndo_set_multicast_list = lbs_set_multicast_list, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, +}; + /** * @brief This function adds the card. it will probe the * card, allocate the lbs_priv and initialize the device. @@ -1182,19 +1193,13 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) priv->infra_open = 0; /* Setup the OS Interface to our functions */ - dev->open = lbs_dev_open; - dev->hard_start_xmit = lbs_hard_start_xmit; - dev->stop = lbs_eth_stop; - dev->set_mac_address = lbs_set_mac_address; - dev->tx_timeout = lbs_tx_timeout; - + dev->netdev_ops = &lbs_netdev_ops; dev->watchdog_timeo = 5 * HZ; dev->ethtool_ops = &lbs_ethtool_ops; #ifdef WIRELESS_EXT - dev->wireless_handlers = (struct iw_handler_def *)&lbs_handler_def; + dev->wireless_handlers = &lbs_handler_def; #endif dev->flags |= IFF_BROADCAST | IFF_MULTICAST; - dev->set_multicast_list = lbs_set_multicast_list; SET_NETDEV_DEV(dev, dmdev); @@ -1404,6 +1409,14 @@ out: EXPORT_SYMBOL_GPL(lbs_stop_card); +static const struct net_device_ops mesh_netdev_ops = { + .ndo_open = lbs_dev_open, + .ndo_stop = lbs_mesh_stop, + .ndo_start_xmit = lbs_hard_start_xmit, + .ndo_set_mac_address = lbs_set_mac_address, + .ndo_set_multicast_list = lbs_set_multicast_list, +}; + /** * @brief This function adds mshX interface * @@ -1426,10 +1439,7 @@ static int lbs_add_mesh(struct lbs_private *priv) mesh_dev->ml_priv = priv; priv->mesh_dev = mesh_dev; - mesh_dev->open = lbs_dev_open; - mesh_dev->hard_start_xmit = lbs_hard_start_xmit; - mesh_dev->stop = lbs_mesh_stop; - mesh_dev->set_mac_address = lbs_set_mac_address; + mesh_dev->netdev_ops = &mesh_netdev_ops; mesh_dev->ethtool_ops = &lbs_ethtool_ops; memcpy(mesh_dev->dev_addr, priv->dev->dev_addr, sizeof(priv->dev->dev_addr)); @@ -1440,7 +1450,6 @@ static int lbs_add_mesh(struct lbs_private *priv) mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def; #endif mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST; - mesh_dev->set_multicast_list = lbs_set_multicast_list; /* Register virtual mesh interface */ ret = register_netdev(mesh_dev); if (ret) { @@ -1645,6 +1654,12 @@ out: lbs_deb_leave(LBS_DEB_MAIN); } +static const struct net_device_ops rtap_netdev_ops = { + .ndo_open = lbs_rtap_open, + .ndo_stop = lbs_rtap_stop, + .ndo_start_xmit = lbs_rtap_hard_start_xmit, +}; + static int lbs_add_rtap(struct lbs_private *priv) { int ret = 0; @@ -1664,9 +1679,7 @@ static int lbs_add_rtap(struct lbs_private *priv) memcpy(rtap_dev->dev_addr, priv->current_addr, ETH_ALEN); rtap_dev->type = ARPHRD_IEEE80211_RADIOTAP; - rtap_dev->open = lbs_rtap_open; - rtap_dev->stop = lbs_rtap_stop; - rtap_dev->hard_start_xmit = lbs_rtap_hard_start_xmit; + rtap_dev->netdev_ops = &rtap_netdev_ops; rtap_dev->ml_priv = priv; SET_NETDEV_DEV(rtap_dev, priv->dev->dev.parent); -- GitLab From ce55cbaf3a4498719bdb5a022a45d256b84749f5 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:38 +0000 Subject: [PATCH 3886/4982] ipw2x00: convert to internal net_device_stats Replace struct in ieee with current net_device_stats, so no longer need get_stats hook Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/ipw2x00/ieee80211.h | 1 - drivers/net/wireless/ipw2x00/ipw2100.c | 36 +++++++------- drivers/net/wireless/ipw2x00/ipw2200.c | 52 +++++++------------- drivers/net/wireless/ipw2x00/libipw_module.c | 11 ----- drivers/net/wireless/ipw2x00/libipw_rx.c | 17 +++---- drivers/net/wireless/ipw2x00/libipw_tx.c | 9 ++-- 6 files changed, 49 insertions(+), 77 deletions(-) diff --git a/drivers/net/wireless/ipw2x00/ieee80211.h b/drivers/net/wireless/ipw2x00/ieee80211.h index f82435eae49..1978fcd833d 100644 --- a/drivers/net/wireless/ipw2x00/ieee80211.h +++ b/drivers/net/wireless/ipw2x00/ieee80211.h @@ -786,7 +786,6 @@ struct ieee80211_device { struct ieee80211_security sec; /* Bookkeeping structures */ - struct net_device_stats stats; struct ieee80211_stats ieee_stats; struct ieee80211_geo geo; diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 3a6d810a760..425ba8b0b0f 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -2391,13 +2391,14 @@ static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i) #endif priv->fatal_error = IPW2100_ERR_C3_CORRUPTION; - priv->ieee->stats.rx_errors++; + priv->net_dev->stats.rx_errors++; schedule_reset(priv); } static void isr_rx(struct ipw2100_priv *priv, int i, struct ieee80211_rx_stats *stats) { + struct net_device *dev = priv->net_dev; struct ipw2100_status *status = &priv->status_queue.drv[i]; struct ipw2100_rx_packet *packet = &priv->rx_buffers[i]; @@ -2406,14 +2407,14 @@ static void isr_rx(struct ipw2100_priv *priv, int i, if (unlikely(status->frame_size > skb_tailroom(packet->skb))) { IPW_DEBUG_INFO("%s: frame_size (%u) > skb_tailroom (%u)!" " Dropping.\n", - priv->net_dev->name, + dev->name, status->frame_size, skb_tailroom(packet->skb)); - priv->ieee->stats.rx_errors++; + dev->stats.rx_errors++; return; } - if (unlikely(!netif_running(priv->net_dev))) { - priv->ieee->stats.rx_errors++; + if (unlikely(!netif_running(dev))) { + dev->stats.rx_errors++; priv->wstats.discard.misc++; IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); return; @@ -2443,10 +2444,10 @@ static void isr_rx(struct ipw2100_priv *priv, int i, if (!ieee80211_rx(priv->ieee, packet->skb, stats)) { #ifdef IPW2100_RX_DEBUG IPW_DEBUG_DROP("%s: Non consumed packet:\n", - priv->net_dev->name); + dev->name); printk_buf(IPW_DL_DROP, packet_data, status->frame_size); #endif - priv->ieee->stats.rx_errors++; + dev->stats.rx_errors++; /* ieee80211_rx failed, so it didn't free the SKB */ dev_kfree_skb_any(packet->skb); @@ -2457,7 +2458,7 @@ static void isr_rx(struct ipw2100_priv *priv, int i, if (unlikely(ipw2100_alloc_skb(priv, packet))) { printk(KERN_WARNING DRV_NAME ": " "%s: Unable to allocate SKB onto RBD ring - disabling " - "adapter.\n", priv->net_dev->name); + "adapter.\n", dev->name); /* TODO: schedule adapter shutdown */ IPW_DEBUG_INFO("TODO: Shutdown adapter...\n"); } @@ -2471,6 +2472,7 @@ static void isr_rx(struct ipw2100_priv *priv, int i, static void isr_rx_monitor(struct ipw2100_priv *priv, int i, struct ieee80211_rx_stats *stats) { + struct net_device *dev = priv->net_dev; struct ipw2100_status *status = &priv->status_queue.drv[i]; struct ipw2100_rx_packet *packet = &priv->rx_buffers[i]; @@ -2488,15 +2490,15 @@ static void isr_rx_monitor(struct ipw2100_priv *priv, int i, sizeof(struct ipw_rt_hdr))) { IPW_DEBUG_INFO("%s: frame_size (%u) > skb_tailroom (%u)!" " Dropping.\n", - priv->net_dev->name, + dev->name, status->frame_size, skb_tailroom(packet->skb)); - priv->ieee->stats.rx_errors++; + dev->stats.rx_errors++; return; } - if (unlikely(!netif_running(priv->net_dev))) { - priv->ieee->stats.rx_errors++; + if (unlikely(!netif_running(dev))) { + dev->stats.rx_errors++; priv->wstats.discard.misc++; IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); return; @@ -2505,7 +2507,7 @@ static void isr_rx_monitor(struct ipw2100_priv *priv, int i, if (unlikely(priv->config & CFG_CRC_CHECK && status->flags & IPW_STATUS_FLAG_CRC_ERROR)) { IPW_DEBUG_RX("CRC error in packet. Dropping.\n"); - priv->ieee->stats.rx_errors++; + dev->stats.rx_errors++; return; } @@ -2527,7 +2529,7 @@ static void isr_rx_monitor(struct ipw2100_priv *priv, int i, skb_put(packet->skb, status->frame_size + sizeof(struct ipw_rt_hdr)); if (!ieee80211_rx(priv->ieee, packet->skb, stats)) { - priv->ieee->stats.rx_errors++; + dev->stats.rx_errors++; /* ieee80211_rx failed, so it didn't free the SKB */ dev_kfree_skb_any(packet->skb); @@ -2538,7 +2540,7 @@ static void isr_rx_monitor(struct ipw2100_priv *priv, int i, if (unlikely(ipw2100_alloc_skb(priv, packet))) { IPW_DEBUG_WARNING( "%s: Unable to allocate SKB onto RBD ring - disabling " - "adapter.\n", priv->net_dev->name); + "adapter.\n", dev->name); /* TODO: schedule adapter shutdown */ IPW_DEBUG_INFO("TODO: Shutdown adapter...\n"); } @@ -3340,7 +3342,7 @@ static int ipw2100_tx(struct ieee80211_txb *txb, struct net_device *dev, if (!(priv->status & STATUS_ASSOCIATED)) { IPW_DEBUG_INFO("Can not transmit when not connected.\n"); - priv->ieee->stats.tx_carrier_errors++; + priv->net_dev->stats.tx_carrier_errors++; netif_stop_queue(dev); goto fail_unlock; } @@ -5836,7 +5838,7 @@ static void ipw2100_tx_timeout(struct net_device *dev) { struct ipw2100_priv *priv = ieee80211_priv(dev); - priv->ieee->stats.tx_errors++; + dev->stats.tx_errors++; #ifdef CONFIG_IPW2100_MONITOR if (priv->ieee->iw_mode == IW_MODE_MONITOR) diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index a7fb08aecf3..08b42948f2b 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -7731,22 +7731,23 @@ static void ipw_handle_data_packet(struct ipw_priv *priv, struct ipw_rx_mem_buffer *rxb, struct ieee80211_rx_stats *stats) { + struct net_device *dev = priv->net_dev; struct ieee80211_hdr_4addr *hdr; struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data; /* We received data from the HW, so stop the watchdog */ - priv->net_dev->trans_start = jiffies; + dev->trans_start = jiffies; /* We only process data packets if the * interface is open */ if (unlikely((le16_to_cpu(pkt->u.frame.length) + IPW_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) { - priv->ieee->stats.rx_errors++; + dev->stats.rx_errors++; priv->wstats.discard.misc++; IPW_DEBUG_DROP("Corruption detected! Oh no!\n"); return; } else if (unlikely(!netif_running(priv->net_dev))) { - priv->ieee->stats.rx_dropped++; + dev->stats.rx_dropped++; priv->wstats.discard.misc++; IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); return; @@ -7768,7 +7769,7 @@ static void ipw_handle_data_packet(struct ipw_priv *priv, ipw_rebuild_decrypted_skb(priv, rxb->skb); if (!ieee80211_rx(priv->ieee, rxb->skb, stats)) - priv->ieee->stats.rx_errors++; + dev->stats.rx_errors++; else { /* ieee80211_rx succeeded, so it now owns the SKB */ rxb->skb = NULL; __ipw_led_activity_on(priv); @@ -7780,6 +7781,7 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, struct ipw_rx_mem_buffer *rxb, struct ieee80211_rx_stats *stats) { + struct net_device *dev = priv->net_dev; struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data; struct ipw_rx_frame *frame = &pkt->u.frame; @@ -7797,18 +7799,18 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, short len = le16_to_cpu(pkt->u.frame.length); /* We received data from the HW, so stop the watchdog */ - priv->net_dev->trans_start = jiffies; + dev->trans_start = jiffies; /* We only process data packets if the * interface is open */ if (unlikely((le16_to_cpu(pkt->u.frame.length) + IPW_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) { - priv->ieee->stats.rx_errors++; + dev->stats.rx_errors++; priv->wstats.discard.misc++; IPW_DEBUG_DROP("Corruption detected! Oh no!\n"); return; } else if (unlikely(!netif_running(priv->net_dev))) { - priv->ieee->stats.rx_dropped++; + dev->stats.rx_dropped++; priv->wstats.discard.misc++; IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); return; @@ -7818,7 +7820,7 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, * that now */ if (len > IPW_RX_BUF_SIZE - sizeof(struct ipw_rt_hdr)) { /* FIXME: Should alloc bigger skb instead */ - priv->ieee->stats.rx_dropped++; + dev->stats.rx_dropped++; priv->wstats.discard.misc++; IPW_DEBUG_DROP("Dropping too large packet in monitor\n"); return; @@ -7924,7 +7926,7 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, IPW_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len); if (!ieee80211_rx(priv->ieee, rxb->skb, stats)) - priv->ieee->stats.rx_errors++; + dev->stats.rx_errors++; else { /* ieee80211_rx succeeded, so it now owns the SKB */ rxb->skb = NULL; /* no LED during capture */ @@ -7956,6 +7958,7 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, struct ipw_rx_mem_buffer *rxb, struct ieee80211_rx_stats *stats) { + struct net_device *dev = priv->prom_net_dev; struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data; struct ipw_rx_frame *frame = &pkt->u.frame; struct ipw_rt_hdr *ipw_rt; @@ -7978,17 +7981,17 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, return; /* We received data from the HW, so stop the watchdog */ - priv->prom_net_dev->trans_start = jiffies; + dev->trans_start = jiffies; if (unlikely((len + IPW_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) { - priv->prom_priv->ieee->stats.rx_errors++; + dev->stats.rx_errors++; IPW_DEBUG_DROP("Corruption detected! Oh no!\n"); return; } /* We only process data packets if the interface is open */ - if (unlikely(!netif_running(priv->prom_net_dev))) { - priv->prom_priv->ieee->stats.rx_dropped++; + if (unlikely(!netif_running(dev))) { + dev->stats.rx_dropped++; IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); return; } @@ -7997,7 +8000,7 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, * that now */ if (len > IPW_RX_BUF_SIZE - sizeof(struct ipw_rt_hdr)) { /* FIXME: Should alloc bigger skb instead */ - priv->prom_priv->ieee->stats.rx_dropped++; + dev->stats.rx_dropped++; IPW_DEBUG_DROP("Dropping too large packet in monitor\n"); return; } @@ -8129,7 +8132,7 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, IPW_DEBUG_RX("Rx packet of %d bytes.\n", skb->len); if (!ieee80211_rx(priv->prom_priv->ieee, skb, stats)) { - priv->prom_priv->ieee->stats.rx_errors++; + dev->stats.rx_errors++; dev_kfree_skb_any(skb); } } @@ -8413,7 +8416,7 @@ static void ipw_rx(struct ipw_priv *priv) IPW_DEBUG_DROP ("Received packet is too small. " "Dropping.\n"); - priv->ieee->stats.rx_errors++; + priv->net_dev->stats.rx_errors++; priv->wstats.discard.misc++; break; } @@ -10484,15 +10487,6 @@ static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb, return ret; } -static struct net_device_stats *ipw_net_get_stats(struct net_device *dev) -{ - struct ipw_priv *priv = ieee80211_priv(dev); - - priv->ieee->stats.tx_packets = priv->tx_packets; - priv->ieee->stats.rx_packets = priv->rx_packets; - return &priv->ieee->stats; -} - static void ipw_net_set_multicast_list(struct net_device *dev) { @@ -11535,12 +11529,6 @@ static int ipw_prom_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) return -EOPNOTSUPP; } -static struct net_device_stats *ipw_prom_get_stats(struct net_device *dev) -{ - struct ipw_prom_priv *prom_priv = ieee80211_priv(dev); - return &prom_priv->ieee->stats; -} - static int ipw_prom_alloc(struct ipw_priv *priv) { int rc = 0; @@ -11562,7 +11550,6 @@ static int ipw_prom_alloc(struct ipw_priv *priv) priv->prom_net_dev->type = ARPHRD_IEEE80211_RADIOTAP; priv->prom_net_dev->open = ipw_prom_open; priv->prom_net_dev->stop = ipw_prom_stop; - priv->prom_net_dev->get_stats = ipw_prom_get_stats; priv->prom_net_dev->hard_start_xmit = ipw_prom_hard_start_xmit; priv->prom_priv->ieee->iw_mode = IW_MODE_MONITOR; @@ -11695,7 +11682,6 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, net_dev->open = ipw_net_open; net_dev->stop = ipw_net_stop; net_dev->init = ipw_net_init; - net_dev->get_stats = ipw_net_get_stats; net_dev->set_multicast_list = ipw_net_set_multicast_list; net_dev->set_mac_address = ipw_net_set_mac_address; priv->wireless_data.spy_data = &priv->ieee->spy_data; diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c index f4803fc0541..b81df1ad190 100644 --- a/drivers/net/wireless/ipw2x00/libipw_module.c +++ b/drivers/net/wireless/ipw2x00/libipw_module.c @@ -139,13 +139,6 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) return 0; } -static struct net_device_stats *ieee80211_generic_get_stats( - struct net_device *dev) -{ - struct ieee80211_device *ieee = netdev_priv(dev); - return &ieee->stats; -} - struct net_device *alloc_ieee80211(int sizeof_priv) { struct ieee80211_device *ieee; @@ -163,10 +156,6 @@ struct net_device *alloc_ieee80211(int sizeof_priv) dev->hard_start_xmit = ieee80211_xmit; dev->change_mtu = ieee80211_change_mtu; - /* Drivers are free to override this if the generic implementation - * does not meet their needs. */ - dev->get_stats = ieee80211_generic_get_stats; - ieee->dev = dev; err = ieee80211_networks_allocate(ieee); diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c index 079007936d8..dae4b8e4d8e 100644 --- a/drivers/net/wireless/ipw2x00/libipw_rx.c +++ b/drivers/net/wireless/ipw2x00/libipw_rx.c @@ -335,7 +335,6 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_hdr_4addr *hdr; size_t hdrlen; u16 fc, type, stype, sc; - struct net_device_stats *stats; unsigned int frag; u8 *payload; u16 ethertype; @@ -354,8 +353,6 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, int can_be_decrypted = 0; hdr = (struct ieee80211_hdr_4addr *)skb->data; - stats = &ieee->stats; - if (skb->len < 10) { printk(KERN_INFO "%s: SKB length < 10\n", dev->name); goto rx_dropped; @@ -412,8 +409,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, #endif if (ieee->iw_mode == IW_MODE_MONITOR) { - stats->rx_packets++; - stats->rx_bytes += skb->len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; ieee80211_monitor_rx(ieee, skb, rx_stats); return 1; } @@ -769,8 +766,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, } #endif - stats->rx_packets++; - stats->rx_bytes += skb->len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; #ifdef NOT_YET if (ieee->iw_mode == IW_MODE_MASTER && !wds && ieee->ap->bridge_packets) { @@ -812,7 +809,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, * in our stats. */ IEEE80211_DEBUG_DROP ("RX: netif_rx dropped the packet\n"); - stats->rx_dropped++; + dev->stats.rx_dropped++; } } @@ -824,7 +821,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, return 1; rx_dropped: - stats->rx_dropped++; + dev->stats.rx_dropped++; /* Returning 0 indicates to caller that we have not handled the SKB-- * so it is still allocated and can be used again by underlying @@ -919,7 +916,7 @@ void ieee80211_rx_any(struct ieee80211_device *ieee, drop_free: dev_kfree_skb_irq(skb); - ieee->stats.rx_dropped++; + ieee->dev->stats.rx_dropped++; return; } diff --git a/drivers/net/wireless/ipw2x00/libipw_tx.c b/drivers/net/wireless/ipw2x00/libipw_tx.c index a874e909191..0da4a0a73a4 100644 --- a/drivers/net/wireless/ipw2x00/libipw_tx.c +++ b/drivers/net/wireless/ipw2x00/libipw_tx.c @@ -260,7 +260,6 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size, rts_required; unsigned long flags; - struct net_device_stats *stats = &ieee->stats; int encrypt, host_encrypt, host_encrypt_msdu, host_build_iv; __be16 ether_type; int bytes, fc, hdr_len; @@ -306,7 +305,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) if (!encrypt && ieee->ieee802_1x && ieee->drop_unencrypted && ether_type != htons(ETH_P_PAE)) { - stats->tx_dropped++; + dev->stats.tx_dropped++; goto success; } @@ -526,8 +525,8 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) if (txb) { int ret = (*ieee->hard_start_xmit) (txb, dev, priority); if (ret == 0) { - stats->tx_packets++; - stats->tx_bytes += txb->payload_size; + dev->stats.tx_packets++; + dev->stats.tx_bytes += txb->payload_size; return 0; } @@ -539,7 +538,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) failed: spin_unlock_irqrestore(&ieee->lock, flags); netif_stop_queue(dev); - stats->tx_errors++; + dev->stats.tx_errors++; return 1; } -- GitLab From d5b3b9ae065d093fe0e1588a07f3ebd71c815f0b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:39 +0000 Subject: [PATCH 3887/4982] ipw2x00: convert infrastructure for use by net_device_ops Expose routines so drivers can hook. Only set ptrs in netdev if using old compat code. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/ipw2x00/ieee80211.h | 1 + drivers/net/wireless/ipw2x00/libipw_module.c | 5 ++++- drivers/net/wireless/ipw2x00/libipw_tx.c | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ipw2x00/ieee80211.h b/drivers/net/wireless/ipw2x00/ieee80211.h index 1978fcd833d..70755c1336d 100644 --- a/drivers/net/wireless/ipw2x00/ieee80211.h +++ b/drivers/net/wireless/ipw2x00/ieee80211.h @@ -1016,6 +1016,7 @@ static inline int ieee80211_is_cck_rate(u8 rate) /* ieee80211.c */ extern void free_ieee80211(struct net_device *dev); extern struct net_device *alloc_ieee80211(int sizeof_priv); +extern int ieee80211_change_mtu(struct net_device *dev, int new_mtu); extern void ieee80211_networks_age(struct ieee80211_device *ieee, unsigned long age_secs); diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c index b81df1ad190..92a26922e79 100644 --- a/drivers/net/wireless/ipw2x00/libipw_module.c +++ b/drivers/net/wireless/ipw2x00/libipw_module.c @@ -131,13 +131,14 @@ static void ieee80211_networks_initialize(struct ieee80211_device *ieee) &ieee->network_free_list); } -static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) +int ieee80211_change_mtu(struct net_device *dev, int new_mtu) { if ((new_mtu < 68) || (new_mtu > IEEE80211_DATA_LEN)) return -EINVAL; dev->mtu = new_mtu; return 0; } +EXPORT_SYMBOL(ieee80211_change_mtu); struct net_device *alloc_ieee80211(int sizeof_priv) { @@ -153,8 +154,10 @@ struct net_device *alloc_ieee80211(int sizeof_priv) goto failed; } ieee = netdev_priv(dev); +#ifdef CONFIG_COMPAT_NET_DEV_OPS dev->hard_start_xmit = ieee80211_xmit; dev->change_mtu = ieee80211_change_mtu; +#endif ieee->dev = dev; diff --git a/drivers/net/wireless/ipw2x00/libipw_tx.c b/drivers/net/wireless/ipw2x00/libipw_tx.c index 0da4a0a73a4..65a8195b3d9 100644 --- a/drivers/net/wireless/ipw2x00/libipw_tx.c +++ b/drivers/net/wireless/ipw2x00/libipw_tx.c @@ -541,5 +541,6 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) dev->stats.tx_errors++; return 1; } +EXPORT_SYMBOL(ieee80211_xmit); EXPORT_SYMBOL(ieee80211_txb_free); -- GitLab From 3e47fcea201ba7b08f9f13cead6e3045a80fb279 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:40 +0000 Subject: [PATCH 3888/4982] ipw2100: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/ipw2x00/ipw2100.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 425ba8b0b0f..115b7048750 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -6008,6 +6008,17 @@ static void ipw2100_rf_kill(struct work_struct *work) static void ipw2100_irq_tasklet(struct ipw2100_priv *priv); +static const struct net_device_ops ipw2100_netdev_ops = { + .ndo_open = ipw2100_open, + .ndo_stop = ipw2100_close, + .ndo_start_xmit = ieee80211_xmit, + .ndo_change_mtu = ieee80211_change_mtu, + .ndo_init = ipw2100_net_init, + .ndo_tx_timeout = ipw2100_tx_timeout, + .ndo_set_mac_address = ipw2100_set_address, + .ndo_validate_addr = eth_validate_addr, +}; + /* Look into using netdev destructor to shutdown ieee80211? */ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, @@ -6032,15 +6043,11 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, priv->ieee->perfect_rssi = -20; priv->ieee->worst_rssi = -85; - dev->open = ipw2100_open; - dev->stop = ipw2100_close; - dev->init = ipw2100_net_init; + dev->netdev_ops = &ipw2100_netdev_ops; dev->ethtool_ops = &ipw2100_ethtool_ops; - dev->tx_timeout = ipw2100_tx_timeout; dev->wireless_handlers = &ipw2100_wx_handler_def; priv->wireless_data.ieee80211 = priv->ieee; dev->wireless_data = &priv->wireless_data; - dev->set_mac_address = ipw2100_set_address; dev->watchdog_timeo = 3 * HZ; dev->irq = 0; -- GitLab From 44e9ad0b5a9bd4de7ff3ac28b27d6577eb58fd91 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:41 +0000 Subject: [PATCH 3889/4982] ipw2200: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/ipw2x00/ipw2200.c | 30 +++++++++++++++++++------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 08b42948f2b..b3449948a25 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -11529,6 +11529,15 @@ static int ipw_prom_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) return -EOPNOTSUPP; } +static const struct net_device_ops ipw_prom_netdev_ops = { + .ndo_open = ipw_prom_open, + .ndo_stop = ipw_prom_stop, + .ndo_start_xmit = ipw_prom_hard_start_xmit, + .ndo_change_mtu = ieee80211_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + static int ipw_prom_alloc(struct ipw_priv *priv) { int rc = 0; @@ -11548,9 +11557,7 @@ static int ipw_prom_alloc(struct ipw_priv *priv) memcpy(priv->prom_net_dev->dev_addr, priv->mac_addr, ETH_ALEN); priv->prom_net_dev->type = ARPHRD_IEEE80211_RADIOTAP; - priv->prom_net_dev->open = ipw_prom_open; - priv->prom_net_dev->stop = ipw_prom_stop; - priv->prom_net_dev->hard_start_xmit = ipw_prom_hard_start_xmit; + priv->prom_net_dev->netdev_ops = &ipw_prom_netdev_ops; priv->prom_priv->ieee->iw_mode = IW_MODE_MONITOR; SET_NETDEV_DEV(priv->prom_net_dev, &priv->pci_dev->dev); @@ -11578,6 +11585,17 @@ static void ipw_prom_free(struct ipw_priv *priv) #endif +static const struct net_device_ops ipw_netdev_ops = { + .ndo_init = ipw_net_init, + .ndo_open = ipw_net_open, + .ndo_stop = ipw_net_stop, + .ndo_set_multicast_list = ipw_net_set_multicast_list, + .ndo_set_mac_address = ipw_net_set_mac_address, + .ndo_start_xmit = ieee80211_xmit, + .ndo_change_mtu = ieee80211_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; static int __devinit ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -11679,11 +11697,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, priv->ieee->perfect_rssi = -20; priv->ieee->worst_rssi = -85; - net_dev->open = ipw_net_open; - net_dev->stop = ipw_net_stop; - net_dev->init = ipw_net_init; - net_dev->set_multicast_list = ipw_net_set_multicast_list; - net_dev->set_mac_address = ipw_net_set_mac_address; + net_dev->netdev_ops = &ipw_netdev_ops; priv->wireless_data.spy_data = &priv->ieee->spy_data; net_dev->wireless_data = &priv->wireless_data; net_dev->wireless_handlers = &ipw_wx_handler_def; -- GitLab From 4cfa8e45f4bb26ff38155f94a810a876b739958d Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:42 +0000 Subject: [PATCH 3890/4982] hostap: convert to internal net_device_stats Use pre-existing net_device_stats in network_device struct. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/hostap/hostap_80211_rx.c | 19 ++++++------------- drivers/net/wireless/hostap/hostap_ap.c | 2 +- drivers/net/wireless/hostap/hostap_hw.c | 12 ++++-------- drivers/net/wireless/hostap/hostap_main.c | 10 ---------- drivers/net/wireless/hostap/hostap_wlan.h | 1 - 5 files changed, 11 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c index 7ba318e84de..3816df96a66 100644 --- a/drivers/net/wireless/hostap/hostap_80211_rx.c +++ b/drivers/net/wireless/hostap/hostap_80211_rx.c @@ -207,13 +207,11 @@ hdr->f.status = s; hdr->f.len = l; hdr->f.data = d static void monitor_rx(struct net_device *dev, struct sk_buff *skb, struct hostap_80211_rx_status *rx_stats) { - struct net_device_stats *stats; int len; len = prism2_rx_80211(dev, skb, rx_stats, PRISM2_RX_MONITOR); - stats = hostap_get_stats(dev); - stats->rx_packets++; - stats->rx_bytes += len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += len; } @@ -724,7 +722,6 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb, size_t hdrlen; u16 fc, type, stype, sc; struct net_device *wds = NULL; - struct net_device_stats *stats; unsigned int frag; u8 *payload; struct sk_buff *skb2 = NULL; @@ -748,7 +745,6 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb, iface = netdev_priv(dev); hdr = (struct ieee80211_hdr *) skb->data; - stats = hostap_get_stats(dev); if (skb->len < 10) goto rx_dropped; @@ -866,10 +862,8 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb, if (hostap_rx_frame_wds(local, hdr, fc, &wds)) goto rx_dropped; - if (wds) { + if (wds) skb->dev = dev = wds; - stats = hostap_get_stats(dev); - } if (local->iw_mode == IW_MODE_MASTER && !wds && (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == @@ -878,7 +872,6 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb, memcmp(hdr->addr2, local->assoc_ap_addr, ETH_ALEN) == 0) { /* Frame from BSSID of the AP for which we are a client */ skb->dev = dev = local->stadev; - stats = hostap_get_stats(dev); from_assoc_ap = 1; } @@ -1069,8 +1062,8 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb, skb_trim(skb, skb->len - ETH_ALEN); } - stats->rx_packets++; - stats->rx_bytes += skb->len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; if (local->iw_mode == IW_MODE_MASTER && !wds && local->ap->bridge_packets) { @@ -1115,7 +1108,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb, rx_dropped: dev_kfree_skb(skb); - stats->rx_dropped++; + dev->stats.rx_dropped++; goto rx_exit; } diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index 645862fd37d..a2a203c90ba 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c @@ -2262,7 +2262,7 @@ void hostap_rx(struct net_device *dev, struct sk_buff *skb, if (skb->len < 16) goto drop; - local->stats.rx_packets++; + dev->stats.rx_packets++; hdr = (struct ieee80211_hdr *) skb->data; diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index 3d9e7b7a17b..e80ff608dd2 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -1682,7 +1682,7 @@ static int prism2_get_txfid_idx(local_info_t *local) PDEBUG(DEBUG_EXTRA2, "prism2_get_txfid_idx: no room in txfid buf: " "packet dropped\n"); - local->stats.tx_dropped++; + local->dev->stats.tx_dropped++; return -1; } @@ -1787,11 +1787,9 @@ static int prism2_transmit(struct net_device *dev, int idx) prism2_transmit_cb, (long) idx); if (res) { - struct net_device_stats *stats; printk(KERN_DEBUG "%s: prism2_transmit: CMDCODE_TRANSMIT " "failed (res=%d)\n", dev->name, res); - stats = hostap_get_stats(dev); - stats->tx_dropped++; + dev->stats.tx_dropped++; netif_wake_queue(dev); return -1; } @@ -1939,12 +1937,10 @@ static void prism2_rx(local_info_t *local) struct net_device *dev = local->dev; int res, rx_pending = 0; u16 len, hdr_len, rxfid, status, macport; - struct net_device_stats *stats; struct hfa384x_rx_frame rxdesc; struct sk_buff *skb = NULL; prism2_callback(local, PRISM2_CALLBACK_RX_START); - stats = hostap_get_stats(dev); rxfid = prism2_read_fid_reg(dev, HFA384X_RXFID_OFF); #ifndef final_version @@ -2031,7 +2027,7 @@ static void prism2_rx(local_info_t *local) return; rx_dropped: - stats->rx_dropped++; + dev->stats.rx_dropped++; if (skb) dev_kfree_skb(skb); goto rx_exit; @@ -2335,7 +2331,7 @@ static void prism2_txexc(local_info_t *local) struct hfa384x_tx_frame txdesc; show_dump = local->frame_dump & PRISM2_DUMP_TXEXC_HDR; - local->stats.tx_errors++; + dev->stats.tx_errors++; res = hostap_tx_compl_read(local, 1, &txdesc, &payload); HFA384X_OUTW(HFA384X_EV_TXEXC, HFA384X_EVACK_OFF); diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c index 5d55f92f654..792dd14c894 100644 --- a/drivers/net/wireless/hostap/hostap_main.c +++ b/drivers/net/wireless/hostap/hostap_main.c @@ -607,14 +607,6 @@ int hostap_80211_get_hdrlen(__le16 fc) } -struct net_device_stats *hostap_get_stats(struct net_device *dev) -{ - struct hostap_interface *iface; - iface = netdev_priv(dev); - return &iface->stats; -} - - static int prism2_close(struct net_device *dev) { struct hostap_interface *iface; @@ -832,7 +824,6 @@ void hostap_setup_dev(struct net_device *dev, local_info_t *local, ether_setup(dev); /* kernel callbacks */ - dev->get_stats = hostap_get_stats; if (iface) { /* Currently, we point to the proper spy_data only on * the main_dev. This could be fixed. Jean II */ @@ -1112,7 +1103,6 @@ EXPORT_SYMBOL(hostap_set_auth_algs); EXPORT_SYMBOL(hostap_dump_rx_header); EXPORT_SYMBOL(hostap_dump_tx_header); EXPORT_SYMBOL(hostap_80211_get_hdrlen); -EXPORT_SYMBOL(hostap_get_stats); EXPORT_SYMBOL(hostap_setup_dev); EXPORT_SYMBOL(hostap_set_multicast_list_queue); EXPORT_SYMBOL(hostap_set_hostapd); diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h index 4d8d51a353c..3d238917af0 100644 --- a/drivers/net/wireless/hostap/hostap_wlan.h +++ b/drivers/net/wireless/hostap/hostap_wlan.h @@ -684,7 +684,6 @@ struct local_info { u16 channel_mask; /* mask of allowed channels */ u16 scan_channel_mask; /* mask of channels to be scanned */ struct comm_tallies_sums comm_tallies; - struct net_device_stats stats; struct proc_dir_entry *proc; int iw_mode; /* operating mode (IW_MODE_*) */ int pseudo_adhoc; /* 0: IW_MODE_ADHOC is real 802.11 compliant IBSS -- GitLab From 5ae4efbcd2611562a8b93596be034e63495706a5 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:43 +0000 Subject: [PATCH 3891/4982] hostap: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/hostap/hostap_hw.c | 1 - drivers/net/wireless/hostap/hostap_main.c | 69 +++++++++++++++++------ 2 files changed, 52 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index e80ff608dd2..3dad1cf8f24 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -3222,7 +3222,6 @@ while (0) hostap_setup_dev(dev, local, HOSTAP_INTERFACE_MASTER); - dev->hard_start_xmit = hostap_master_start_xmit; dev->type = ARPHRD_IEEE80211; dev->header_ops = &hostap_80211_ops; diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c index 792dd14c894..6fe122f18c0 100644 --- a/drivers/net/wireless/hostap/hostap_main.c +++ b/drivers/net/wireless/hostap/hostap_main.c @@ -815,6 +815,46 @@ const struct header_ops hostap_80211_ops = { }; EXPORT_SYMBOL(hostap_80211_ops); + +static const struct net_device_ops hostap_netdev_ops = { + .ndo_start_xmit = hostap_data_start_xmit, + + .ndo_open = prism2_open, + .ndo_stop = prism2_close, + .ndo_do_ioctl = hostap_ioctl, + .ndo_set_mac_address = prism2_set_mac_address, + .ndo_set_multicast_list = hostap_set_multicast_list, + .ndo_change_mtu = prism2_change_mtu, + .ndo_tx_timeout = prism2_tx_timeout, + .ndo_validate_addr = eth_validate_addr, +}; + +static const struct net_device_ops hostap_mgmt_netdev_ops = { + .ndo_start_xmit = hostap_mgmt_start_xmit, + + .ndo_open = prism2_open, + .ndo_stop = prism2_close, + .ndo_do_ioctl = hostap_ioctl, + .ndo_set_mac_address = prism2_set_mac_address, + .ndo_set_multicast_list = hostap_set_multicast_list, + .ndo_change_mtu = prism2_change_mtu, + .ndo_tx_timeout = prism2_tx_timeout, + .ndo_validate_addr = eth_validate_addr, +}; + +static const struct net_device_ops hostap_master_ops = { + .ndo_start_xmit = hostap_master_start_xmit, + + .ndo_open = prism2_open, + .ndo_stop = prism2_close, + .ndo_do_ioctl = hostap_ioctl, + .ndo_set_mac_address = prism2_set_mac_address, + .ndo_set_multicast_list = hostap_set_multicast_list, + .ndo_change_mtu = prism2_change_mtu, + .ndo_tx_timeout = prism2_tx_timeout, + .ndo_validate_addr = eth_validate_addr, +}; + void hostap_setup_dev(struct net_device *dev, local_info_t *local, int type) { @@ -830,30 +870,25 @@ void hostap_setup_dev(struct net_device *dev, local_info_t *local, iface->wireless_data.spy_data = &iface->spy_data; dev->wireless_data = &iface->wireless_data; } - dev->wireless_handlers = - (struct iw_handler_def *) &hostap_iw_handler_def; - dev->do_ioctl = hostap_ioctl; - dev->open = prism2_open; - dev->stop = prism2_close; - dev->set_mac_address = prism2_set_mac_address; - dev->set_multicast_list = hostap_set_multicast_list; - dev->change_mtu = prism2_change_mtu; - dev->tx_timeout = prism2_tx_timeout; + dev->wireless_handlers = &hostap_iw_handler_def; dev->watchdog_timeo = TX_TIMEOUT; - if (type == HOSTAP_INTERFACE_AP) { - dev->hard_start_xmit = hostap_mgmt_start_xmit; + switch(type) { + case HOSTAP_INTERFACE_AP: + dev->netdev_ops = &hostap_mgmt_netdev_ops; dev->type = ARPHRD_IEEE80211; dev->header_ops = &hostap_80211_ops; - } else { - dev->hard_start_xmit = hostap_data_start_xmit; + break; + case HOSTAP_INTERFACE_MASTER: + dev->tx_queue_len = 0; /* use main radio device queue */ + dev->netdev_ops = &hostap_master_ops; + break; + default: + dev->netdev_ops = &hostap_netdev_ops; } dev->mtu = local->mtu; - if (type != HOSTAP_INTERFACE_MASTER) { - /* use main radio device queue */ - dev->tx_queue_len = 0; - } + SET_ETHTOOL_OPS(dev, &prism2_ethtool_ops); -- GitLab From d44c3a2e0e5d2c75d22284462c66d166604b1f18 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Mar 2009 19:36:44 +0000 Subject: [PATCH 3892/4982] netdev: expose net_device_ops compat as config option Now that most network device drivers in (all but one in x86_64 allmodconfig) support net_device_ops. Expose it as a configuration parameter. Still need to address even older 32 bit drivers, and other arch before compatiablity can be scheduled for removal in some future release. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/Kconfig | 9 +++++++++ net/Kconfig | 3 --- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 6b1af549b2f..533cc411ee4 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -26,6 +26,15 @@ menuconfig NETDEVICES # that for each of the symbols. if NETDEVICES +config COMPAT_NET_DEV_OPS + default y + bool "Enable older network device API compatiablity" + ---help--- + This option enables kernel compatiability with older network devices + that do not use net_device_ops interface. + + If unsure, say Y. + config IFB tristate "Intermediate Functional Block support" depends on NET_CLS_ACT diff --git a/net/Kconfig b/net/Kconfig index c9fdcd7e71e..93998a9c39c 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -24,9 +24,6 @@ if NET menu "Networking options" -config COMPAT_NET_DEV_OPS - def_bool y - source "net/packet/Kconfig" source "net/unix/Kconfig" source "net/xfrm/Kconfig" -- GitLab From 18a0d89e54ca0f6f33582f99ae39867b2c975559 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 20 Mar 2009 09:22:30 +1100 Subject: [PATCH 3893/4982] radeonfb: Whack the PCI PM register until it sticks This fixes a regression introduced when we switched to using the core pci_set_power_state(). The chip seems to need the state to be written over and over again until it sticks, so we do that. Note that the code is a bit blunt, without timeout, etc... but that's pretty much because I put back in there the code exactly as it used to be before the regression. I still add a call to pci_set_power_state() at the end so that ACPI gets called appropriately on x86. Signed-off-by: Benjamin Herrenschmidt Tested-by: Raymond Wooninck Acked-by: Rafael J. Wysocki Cc: Jesse Barnes Cc: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/aty/radeon_pm.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index 81603f85e17..c6d7cc76516 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -2507,6 +2507,25 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo) #endif /* CONFIG_PPC_OF */ +static void radeonfb_whack_power_state(struct radeonfb_info *rinfo, pci_power_t state) +{ + u16 pwr_cmd; + + for (;;) { + pci_read_config_word(rinfo->pdev, + rinfo->pm_reg+PCI_PM_CTRL, + &pwr_cmd); + if (pwr_cmd & 2) + break; + pwr_cmd = (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | 2; + pci_write_config_word(rinfo->pdev, + rinfo->pm_reg+PCI_PM_CTRL, + pwr_cmd); + msleep(500); + } + rinfo->pdev->current_state = state; +} + static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) { u32 tmp; @@ -2558,6 +2577,11 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) /* Switch PCI power management to D2. */ pci_disable_device(rinfo->pdev); pci_save_state(rinfo->pdev); + /* The chip seems to need us to whack the PM register + * repeatedly until it sticks. We do that -prior- to + * calling pci_set_power_state() + */ + radeonfb_whack_power_state(rinfo, PCI_D2); pci_set_power_state(rinfo->pdev, PCI_D2); } else { printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n", -- GitLab From 8faece5f906725c10e7a1f6caf84452abadbdc7b Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Fri, 20 Mar 2009 01:25:09 -0500 Subject: [PATCH 3894/4982] eCryptfs: Allocate a variable number of pages for file headers When allocating the memory used to store the eCryptfs header contents, a single, zeroed page was being allocated with get_zeroed_page(). However, the size of an eCryptfs header is either PAGE_CACHE_SIZE or ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE (8192), whichever is larger, and is stored in the file's private_data->crypt_stat->num_header_bytes_at_front field. ecryptfs_write_metadata_to_contents() was using num_header_bytes_at_front to decide how many bytes should be written to the lower filesystem for the file header. Unfortunately, at least 8K was being written from the page, despite the chance of the single, zeroed page being smaller than 8K. This resulted in random areas of kernel memory being written between the 0x1000 and 0x1FFF bytes offsets in the eCryptfs file headers if PAGE_SIZE was 4K. This patch allocates a variable number of pages, calculated with num_header_bytes_at_front, and passes the number of allocated pages along to ecryptfs_write_metadata_to_contents(). Thanks to Florian Streibelt for reporting the data leak and working with me to find the problem. 2.6.28 is the only kernel release with this vulnerability. Corresponds to CVE-2009-0787 Signed-off-by: Tyler Hicks Acked-by: Dustin Kirkland Reviewed-by: Eric Sandeen Reviewed-by: Eugene Teo Cc: Greg KH Cc: dann frazier Cc: Serge E. Hallyn Cc: Florian Streibelt Cc: stable@kernel.org Signed-off-by: Linus Torvalds --- fs/ecryptfs/crypto.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index bdca1f4b3a3..75bee99de0f 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -1324,14 +1324,13 @@ static int ecryptfs_write_headers_virt(char *page_virt, size_t max, } static int -ecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat, - struct dentry *ecryptfs_dentry, - char *virt) +ecryptfs_write_metadata_to_contents(struct dentry *ecryptfs_dentry, + char *virt, size_t virt_len) { int rc; rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, virt, - 0, crypt_stat->num_header_bytes_at_front); + 0, virt_len); if (rc) printk(KERN_ERR "%s: Error attempting to write header " "information to lower file; rc = [%d]\n", __func__, @@ -1341,7 +1340,6 @@ ecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat, static int ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry, - struct ecryptfs_crypt_stat *crypt_stat, char *page_virt, size_t size) { int rc; @@ -1351,6 +1349,17 @@ ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry, return rc; } +static unsigned long ecryptfs_get_zeroed_pages(gfp_t gfp_mask, + unsigned int order) +{ + struct page *page; + + page = alloc_pages(gfp_mask | __GFP_ZERO, order); + if (page) + return (unsigned long) page_address(page); + return 0; +} + /** * ecryptfs_write_metadata * @ecryptfs_dentry: The eCryptfs dentry @@ -1367,7 +1376,9 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry) { struct ecryptfs_crypt_stat *crypt_stat = &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat; + unsigned int order; char *virt; + size_t virt_len; size_t size = 0; int rc = 0; @@ -1383,33 +1394,35 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry) rc = -EINVAL; goto out; } + virt_len = crypt_stat->num_header_bytes_at_front; + order = get_order(virt_len); /* Released in this function */ - virt = (char *)get_zeroed_page(GFP_KERNEL); + virt = (char *)ecryptfs_get_zeroed_pages(GFP_KERNEL, order); if (!virt) { printk(KERN_ERR "%s: Out of memory\n", __func__); rc = -ENOMEM; goto out; } - rc = ecryptfs_write_headers_virt(virt, PAGE_CACHE_SIZE, &size, - crypt_stat, ecryptfs_dentry); + rc = ecryptfs_write_headers_virt(virt, virt_len, &size, crypt_stat, + ecryptfs_dentry); if (unlikely(rc)) { printk(KERN_ERR "%s: Error whilst writing headers; rc = [%d]\n", __func__, rc); goto out_free; } if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) - rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry, - crypt_stat, virt, size); + rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry, virt, + size); else - rc = ecryptfs_write_metadata_to_contents(crypt_stat, - ecryptfs_dentry, virt); + rc = ecryptfs_write_metadata_to_contents(ecryptfs_dentry, virt, + virt_len); if (rc) { printk(KERN_ERR "%s: Error writing metadata out to lower file; " "rc = [%d]\n", __func__, rc); goto out_free; } out_free: - free_page((unsigned long)virt); + free_pages((unsigned long)virt, order); out: return rc; } -- GitLab From 2aac0cf88681bfa092f731553bc7fbd23516be73 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Fri, 20 Mar 2009 02:23:57 -0500 Subject: [PATCH 3895/4982] eCryptfs: NULL crypt_stat dereference during lookup If ecryptfs_encrypted_view or ecryptfs_xattr_metadata were being specified as mount options, a NULL pointer dereference of crypt_stat was possible during lookup. This patch moves the crypt_stat assignment into ecryptfs_lookup_and_interpose_lower(), ensuring that crypt_stat will not be NULL before we attempt to dereference it. Thanks to Dan Carpenter and his static analysis tool, smatch, for finding this bug. Signed-off-by: Tyler Hicks Acked-by: Dustin Kirkland Cc: Dan Carpenter Cc: Serge Hallyn Signed-off-by: Linus Torvalds --- fs/ecryptfs/crypto.c | 10 ++++++---- fs/ecryptfs/ecryptfs_kernel.h | 1 - fs/ecryptfs/inode.c | 32 ++++++++++++-------------------- 3 files changed, 18 insertions(+), 25 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 75bee99de0f..8b65f289ee0 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -2221,17 +2221,19 @@ int ecryptfs_decode_and_decrypt_filename(char **plaintext_name, struct dentry *ecryptfs_dir_dentry, const char *name, size_t name_size) { + struct ecryptfs_mount_crypt_stat *mount_crypt_stat = + &ecryptfs_superblock_to_private( + ecryptfs_dir_dentry->d_sb)->mount_crypt_stat; char *decoded_name; size_t decoded_name_size; size_t packet_size; int rc = 0; - if ((name_size > ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE) + if ((mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) + && !(mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) + && (name_size > ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE) && (strncmp(name, ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX, ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE) == 0)) { - struct ecryptfs_mount_crypt_stat *mount_crypt_stat = - &ecryptfs_superblock_to_private( - ecryptfs_dir_dentry->d_sb)->mount_crypt_stat; const char *orig_name = name; size_t orig_name_size = name_size; diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index eb2267eca1f..ac749d4d644 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -620,7 +620,6 @@ int ecryptfs_interpose(struct dentry *hidden_dentry, u32 flags); int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, struct dentry *lower_dentry, - struct ecryptfs_crypt_stat *crypt_stat, struct inode *ecryptfs_dir_inode, struct nameidata *ecryptfs_nd); int ecryptfs_decode_and_decrypt_filename(char **decrypted_name, diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 5697899a168..55b3145b807 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -246,7 +246,6 @@ out: */ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, struct dentry *lower_dentry, - struct ecryptfs_crypt_stat *crypt_stat, struct inode *ecryptfs_dir_inode, struct nameidata *ecryptfs_nd) { @@ -254,6 +253,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, struct vfsmount *lower_mnt; struct inode *lower_inode; struct ecryptfs_mount_crypt_stat *mount_crypt_stat; + struct ecryptfs_crypt_stat *crypt_stat; char *page_virt = NULL; u64 file_size; int rc = 0; @@ -314,6 +314,11 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, goto out_free_kmem; } } + crypt_stat = &ecryptfs_inode_to_private( + ecryptfs_dentry->d_inode)->crypt_stat; + /* TODO: lock for crypt_stat comparison */ + if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)) + ecryptfs_set_default_sizes(crypt_stat); rc = ecryptfs_read_and_validate_header_region(page_virt, ecryptfs_dentry->d_inode); if (rc) { @@ -362,9 +367,7 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, { char *encrypted_and_encoded_name = NULL; size_t encrypted_and_encoded_name_size; - struct ecryptfs_crypt_stat *crypt_stat = NULL; struct ecryptfs_mount_crypt_stat *mount_crypt_stat = NULL; - struct ecryptfs_inode_info *inode_info; struct dentry *lower_dir_dentry, *lower_dentry; int rc = 0; @@ -388,26 +391,15 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, } if (lower_dentry->d_inode) goto lookup_and_interpose; - inode_info = ecryptfs_inode_to_private(ecryptfs_dentry->d_inode); - if (inode_info) { - crypt_stat = &inode_info->crypt_stat; - /* TODO: lock for crypt_stat comparison */ - if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)) - ecryptfs_set_default_sizes(crypt_stat); - } - if (crypt_stat) - mount_crypt_stat = crypt_stat->mount_crypt_stat; - else - mount_crypt_stat = &ecryptfs_superblock_to_private( - ecryptfs_dentry->d_sb)->mount_crypt_stat; - if (!(crypt_stat && (crypt_stat->flags & ECRYPTFS_ENCRYPT_FILENAMES)) - && !(mount_crypt_stat && (mount_crypt_stat->flags - & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES))) + mount_crypt_stat = &ecryptfs_superblock_to_private( + ecryptfs_dentry->d_sb)->mount_crypt_stat; + if (!(mount_crypt_stat + && (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES))) goto lookup_and_interpose; dput(lower_dentry); rc = ecryptfs_encrypt_and_encode_filename( &encrypted_and_encoded_name, &encrypted_and_encoded_name_size, - crypt_stat, mount_crypt_stat, ecryptfs_dentry->d_name.name, + NULL, mount_crypt_stat, ecryptfs_dentry->d_name.name, ecryptfs_dentry->d_name.len); if (rc) { printk(KERN_ERR "%s: Error attempting to encrypt and encode " @@ -426,7 +418,7 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, } lookup_and_interpose: rc = ecryptfs_lookup_and_interpose_lower(ecryptfs_dentry, lower_dentry, - crypt_stat, ecryptfs_dir_inode, + ecryptfs_dir_inode, ecryptfs_nd); goto out; out_d_drop: -- GitLab From f762dd68218665bb87d4e4a0eeac86fde7530293 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sat, 21 Mar 2009 23:18:57 +0100 Subject: [PATCH 3896/4982] Update my email address Update all previous incarnations of my email address to the correct one. Signed-off-by: Gertjan van Wingerde Signed-off-by: Linus Torvalds --- CREDITS | 2 +- fs/minix/inode.c | 2 +- fs/ufs/super.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CREDITS b/CREDITS index 5e0736722af..e8b7d36611e 100644 --- a/CREDITS +++ b/CREDITS @@ -3738,7 +3738,7 @@ S: 93149 Nittenau S: Germany N: Gertjan van Wingerde -E: gwingerde@home.nl +E: gwingerde@gmail.com D: Ralink rt2x00 WLAN driver D: Minix V2 file-system D: Misc fixes diff --git a/fs/minix/inode.c b/fs/minix/inode.c index d1d1eb84679..618865b3128 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -3,7 +3,7 @@ * * Copyright (C) 1991, 1992 Linus Torvalds * - * Copyright (C) 1996 Gertjan van Wingerde (gertjan@cs.vu.nl) + * Copyright (C) 1996 Gertjan van Wingerde * Minix V2 fs support. * * Modified for 680x0 by Andreas Schwab diff --git a/fs/ufs/super.c b/fs/ufs/super.c index e65212dfb60..261a1c2f22d 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -41,7 +41,7 @@ * Stefan Reinauer * * Module usage counts added on 96/04/29 by - * Gertjan van Wingerde + * Gertjan van Wingerde * * Clean swab support on 19970406 by * Francois-Rene Rideau -- GitLab From 1efb71809fd47bc19b3ce05080e1d5085a8dfab1 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Thu, 19 Mar 2009 15:45:19 +0100 Subject: [PATCH 3897/4982] [ARM] pxa: add pxa320 missing pin function for CS2 on GPIO3 Signed-off-by: Daniel Mack Signed-off-by: Eric Miao --- arch/arm/mach-pxa/include/mach/mfp-pxa320.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa320.h b/arch/arm/mach-pxa/include/mach/mfp-pxa320.h index 67f8385ea54..80a0da9e092 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa320.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa320.h @@ -38,6 +38,7 @@ #define GPIO17_2_GPIO MFP_CFG(GPIO17_2, AF0) /* Chip Select */ +#define GPIO3_nCS2 MFP_CFG(GPIO3, AF1) #define GPIO4_nCS3 MFP_CFG(GPIO4, AF1) /* AC97 */ -- GitLab From 5c0dbb8fc2b36619684cbb7486491ecac950a595 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 13 Mar 2009 16:37:08 +0100 Subject: [PATCH 3898/4982] [ARM] pxa: rename colibri.c to colibri-pxa270.c Namespace cleanup: rename colibri.c to colibri-pxa270.c and change some names in colibri.h. Signed-off-by: Daniel Mack Signed-off-by: Eric Miao --- arch/arm/mach-pxa/Kconfig | 2 +- arch/arm/mach-pxa/Makefile | 2 +- .../mach-pxa/{colibri.c => colibri-pxa270.c} | 50 +++++++++++-------- arch/arm/mach-pxa/include/mach/colibri.h | 17 +++---- 4 files changed, 37 insertions(+), 34 deletions(-) rename arch/arm/mach-pxa/{colibri.c => colibri-pxa270.c} (68%) diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index d13282d773a..fd21bba6217 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -262,7 +262,7 @@ config MACH_EXEDA select PXA27x config MACH_COLIBRI - bool "Toradex Colibri PX27x" + bool "Toradex Colibri PXA270" select PXA27x config MACH_ZYLONITE diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 8da8e63d048..fbbda93b73a 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -35,7 +35,7 @@ obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o obj-$(CONFIG_MACH_MP900C) += mp900.o obj-$(CONFIG_ARCH_PXA_IDP) += idp.o obj-$(CONFIG_MACH_TRIZEPS4) += trizeps4.o -obj-$(CONFIG_MACH_COLIBRI) += colibri.o +obj-$(CONFIG_MACH_COLIBRI) += colibri-pxa270.o obj-$(CONFIG_MACH_H5000) += h5000.o obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o sharpsl_pm.o corgi_pm.o obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o sharpsl_pm.o spitz_pm.o diff --git a/arch/arm/mach-pxa/colibri.c b/arch/arm/mach-pxa/colibri-pxa270.c similarity index 68% rename from arch/arm/mach-pxa/colibri.c rename to arch/arm/mach-pxa/colibri-pxa270.c index 26493ae2889..01bcfaae75b 100644 --- a/arch/arm/mach-pxa/colibri.c +++ b/arch/arm/mach-pxa/colibri-pxa270.c @@ -1,7 +1,7 @@ /* - * linux/arch/arm/mach-pxa/colibri.c + * linux/arch/arm/mach-pxa/colibri-pxa270.c * - * Support for Toradex PXA27x based Colibri module + * Support for Toradex PXA270 based Colibri module * Daniel Mack * * This program is free software; you can redistribute it and/or modify @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -35,13 +36,16 @@ #include "generic.h" #include "devices.h" -static unsigned long colibri_pin_config[] __initdata = { +/* + * GPIO configuration + */ +static mfp_cfg_t colibri_pxa270_pin_config[] __initdata = { GPIO78_nCS_2, /* Ethernet CS */ GPIO114_GPIO, /* Ethernet IRQ */ }; /* - * Flash + * NOR flash */ static struct mtd_partition colibri_partitions[] = { { @@ -70,39 +74,40 @@ static struct physmap_flash_data colibri_flash_data[] = { } }; -static struct resource flash_resource = { +static struct resource colibri_pxa270_flash_resource = { .start = PXA_CS0_PHYS, .end = PXA_CS0_PHYS + SZ_32M - 1, .flags = IORESOURCE_MEM, }; -static struct platform_device flash_device = { +static struct platform_device colibri_pxa270_flash_device = { .name = "physmap-flash", .id = 0, .dev = { .platform_data = colibri_flash_data, }, - .resource = &flash_resource, + .resource = &colibri_pxa270_flash_resource, .num_resources = 1, }; /* * DM9000 Ethernet */ +#if defined(CONFIG_DM9000) static struct resource dm9000_resources[] = { [0] = { - .start = COLIBRI_ETH_PHYS, - .end = COLIBRI_ETH_PHYS + 3, + .start = COLIBRI_PXA270_ETH_PHYS, + .end = COLIBRI_PXA270_ETH_PHYS + 3, .flags = IORESOURCE_MEM, }, [1] = { - .start = COLIBRI_ETH_PHYS + 4, - .end = COLIBRI_ETH_PHYS + 4 + 500, + .start = COLIBRI_PXA270_ETH_PHYS + 4, + .end = COLIBRI_PXA270_ETH_PHYS + 4 + 500, .flags = IORESOURCE_MEM, }, [2] = { - .start = COLIBRI_ETH_IRQ, - .end = COLIBRI_ETH_IRQ, + .start = COLIBRI_PXA270_ETH_IRQ, + .end = COLIBRI_PXA270_ETH_IRQ, .flags = IORESOURCE_IRQ | IRQF_TRIGGER_RISING, }, }; @@ -113,25 +118,28 @@ static struct platform_device dm9000_device = { .num_resources = ARRAY_SIZE(dm9000_resources), .resource = dm9000_resources, }; +#endif /* CONFIG_DM9000 */ -static struct platform_device *colibri_devices[] __initdata = { - &flash_device, +static struct platform_device *colibri_pxa270_devices[] __initdata = { + &colibri_pxa270_flash_device, +#if defined(CONFIG_DM9000) &dm9000_device, +#endif }; -static void __init colibri_init(void) +static void __init colibri_pxa270_init(void) { - pxa2xx_mfp_config(ARRAY_AND_SIZE(colibri_pin_config)); - - platform_add_devices(colibri_devices, ARRAY_SIZE(colibri_devices)); + pxa2xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa270_pin_config)); + platform_add_devices(ARRAY_AND_SIZE(colibri_pxa270_devices)); } -MACHINE_START(COLIBRI, "Toradex Colibri PXA27x") +MACHINE_START(COLIBRI, "Toradex Colibri PXA270") .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = COLIBRI_SDRAM_BASE + 0x100, - .init_machine = colibri_init, + .init_machine = colibri_pxa270_init, .map_io = pxa_map_io, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, MACHINE_END + diff --git a/arch/arm/mach-pxa/include/mach/colibri.h b/arch/arm/mach-pxa/include/mach/colibri.h index 2ae373fb567..c7c99d07881 100644 --- a/arch/arm/mach-pxa/include/mach/colibri.h +++ b/arch/arm/mach-pxa/include/mach/colibri.h @@ -2,18 +2,13 @@ #define _COLIBRI_H_ /* physical memory regions */ -#define COLIBRI_FLASH_PHYS (PXA_CS0_PHYS) /* Flash region */ -#define COLIBRI_ETH_PHYS (PXA_CS2_PHYS) /* Ethernet DM9000 region */ #define COLIBRI_SDRAM_BASE 0xa0000000 /* SDRAM region */ -/* virtual memory regions */ -#define COLIBRI_DISK_VIRT 0xF0000000 /* Disk On Chip region */ - -/* size of flash */ -#define COLIBRI_FLASH_SIZE 0x02000000 /* Flash size 32 MB */ - -/* Ethernet Controller Davicom DM9000 */ -#define GPIO_DM9000 114 -#define COLIBRI_ETH_IRQ IRQ_GPIO(GPIO_DM9000) +#define COLIBRI_PXA270_FLASH_PHYS (PXA_CS0_PHYS) /* Flash region */ +#define COLIBRI_PXA270_ETH_PHYS (PXA_CS2_PHYS) /* Ethernet */ +#define COLIBRI_PXA270_ETH_IRQ_GPIO 114 +#define COLIBRI_PXA270_ETH_IRQ \ + gpio_to_irq(mfp_to_gpio(COLIBRI_PXA270_ETH_IRQ_GPIO)) #endif /* _COLIBRI_H_ */ + -- GitLab From 5fc9f9a1deefc9999af721fba249cd58ee7e273b Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 13 Mar 2009 16:37:09 +0100 Subject: [PATCH 3899/4982] [ARM] pxa: add basic support for Colibri PXA300 module This patch add basic support for Toradex' Colibri PXA300 module. Ethernet is enabled conditionally, depdending on CONFIG_AX88796. Signed-off-by: Daniel Mack Signed-off-by: Eric Miao --- arch/arm/mach-pxa/Kconfig | 5 ++ arch/arm/mach-pxa/Makefile | 1 + arch/arm/mach-pxa/colibri-pxa300.c | 99 ++++++++++++++++++++++++ arch/arm/mach-pxa/include/mach/colibri.h | 17 ++++ 4 files changed, 122 insertions(+) create mode 100644 arch/arm/mach-pxa/colibri-pxa300.c diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index fd21bba6217..1a93888c68a 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -265,6 +265,11 @@ config MACH_COLIBRI bool "Toradex Colibri PXA270" select PXA27x +config MACH_COLIBRI300 + bool "Toradex Colibri PXA300" + select PXA3xx + select CPU_PXA300 + config MACH_ZYLONITE bool "PXA3xx Development Platform (aka Zylonite)" select PXA3xx diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index fbbda93b73a..df6534b49e3 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_MACH_MP900C) += mp900.o obj-$(CONFIG_ARCH_PXA_IDP) += idp.o obj-$(CONFIG_MACH_TRIZEPS4) += trizeps4.o obj-$(CONFIG_MACH_COLIBRI) += colibri-pxa270.o +obj-$(CONFIG_MACH_COLIBRI300) += colibri-pxa300.o obj-$(CONFIG_MACH_H5000) += h5000.o obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o sharpsl_pm.o corgi_pm.o obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o sharpsl_pm.o spitz_pm.o diff --git a/arch/arm/mach-pxa/colibri-pxa300.c b/arch/arm/mach-pxa/colibri-pxa300.c new file mode 100644 index 00000000000..b271e028da3 --- /dev/null +++ b/arch/arm/mach-pxa/colibri-pxa300.c @@ -0,0 +1,99 @@ +/* + * arch/arm/mach-pxa/colibri-pxa300.c + * + * Support for Toradex PXA300 based Colibri module + * Daniel Mack + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "generic.h" +#include "devices.h" + +/* + * GPIO configuration + */ +static mfp_cfg_t colibri_pxa300_pin_config[] __initdata = { + GPIO1_nCS2, /* AX88796 chip select */ + GPIO26_GPIO | MFP_PULL_HIGH, /* AX88796 IRQ */ +}; + +#if defined(CONFIG_AX88796) +/* + * Asix AX88796 Ethernet + */ +static struct ax_plat_data colibri_asix_platdata = { + .flags = AXFLG_MAC_FROMDEV, + .wordlength = 2, + .dcr_val = 0x01, + .rcr_val = 0x0e, + .gpoc_val = 0x19 +}; + +static struct resource colibri_asix_resource[] = { + [0] = { + .start = PXA3xx_CS2_PHYS, + .end = PXA3xx_CS2_PHYS + (0x18 * 0x2) - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = PXA3xx_CS2_PHYS + (1 << 11), + .end = PXA3xx_CS2_PHYS + (1 << 11) + 0x3fff, + .flags = IORESOURCE_MEM, + }, + [2] = { + .start = COLIBRI_PXA300_ETH_IRQ, + .end = COLIBRI_PXA300_ETH_IRQ, + .flags = IORESOURCE_IRQ + } +}; + +static struct platform_device asix_device = { + .name = "ax88796", + .id = 0, + .num_resources = ARRAY_SIZE(colibri_asix_resource), + .resource = colibri_asix_resource, + .dev = { + .platform_data = &colibri_asix_platdata + } +}; +#endif /* CONFIG_AX88796 */ + +static struct platform_device *colibri_pxa300_devices[] __initdata = { +#if defined(CONFIG_AX88796) + &asix_device +#endif +}; + +static void __init colibri_pxa300_init(void) +{ + set_irq_type(COLIBRI_PXA300_ETH_IRQ, IRQ_TYPE_EDGE_FALLING); + pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa300_pin_config)); + platform_add_devices(ARRAY_AND_SIZE(colibri_pxa300_devices)); +} + +MACHINE_START(COLIBRI300, "Toradex Colibri PXA300") + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .boot_params = COLIBRI_SDRAM_BASE + 0x100, + .init_machine = colibri_pxa300_init, + .map_io = pxa_map_io, + .init_irq = pxa3xx_init_irq, + .timer = &pxa_timer, +MACHINE_END + diff --git a/arch/arm/mach-pxa/include/mach/colibri.h b/arch/arm/mach-pxa/include/mach/colibri.h index c7c99d07881..e295e8df8d6 100644 --- a/arch/arm/mach-pxa/include/mach/colibri.h +++ b/arch/arm/mach-pxa/include/mach/colibri.h @@ -1,14 +1,31 @@ #ifndef _COLIBRI_H_ #define _COLIBRI_H_ +/* + * common settings for all modules + */ /* physical memory regions */ #define COLIBRI_SDRAM_BASE 0xa0000000 /* SDRAM region */ +/* definitions for Colibri PXA270 */ + #define COLIBRI_PXA270_FLASH_PHYS (PXA_CS0_PHYS) /* Flash region */ #define COLIBRI_PXA270_ETH_PHYS (PXA_CS2_PHYS) /* Ethernet */ #define COLIBRI_PXA270_ETH_IRQ_GPIO 114 #define COLIBRI_PXA270_ETH_IRQ \ gpio_to_irq(mfp_to_gpio(COLIBRI_PXA270_ETH_IRQ_GPIO)) +/* definitions for Colibri PXA300 */ + +#define COLIBRI_PXA300_ETH_IRQ_GPIO 26 +#define COLIBRI_PXA300_ETH_IRQ \ + gpio_to_irq(mfp_to_gpio(COLIBRI_PXA300_ETH_IRQ_GPIO)) + +/* definitions for Colibri PXA320 */ + +#define COLIBRI_PXA320_ETH_IRQ_GPIO 36 +#define COLIBRI_PXA320_ETH_IRQ \ + gpio_to_irq(mfp_to_gpio(COLIBRI_PXA320_ETH_IRQ_GPIO)) + #endif /* _COLIBRI_H_ */ -- GitLab From ebc046c2a3544ba4f55512a218a4084522473bcd Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 13 Mar 2009 16:37:10 +0100 Subject: [PATCH 3900/4982] [ARM] pxa: add MMC support for Colibri PXA300 Added MMC support for Toradex' Colibri PXA300 module. Signed-off-by: Daniel Mack Signed-off-by: Eric Miao --- arch/arm/mach-pxa/colibri-pxa300.c | 58 ++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/arch/arm/mach-pxa/colibri-pxa300.c b/arch/arm/mach-pxa/colibri-pxa300.c index b271e028da3..7cc4249c770 100644 --- a/arch/arm/mach-pxa/colibri-pxa300.c +++ b/arch/arm/mach-pxa/colibri-pxa300.c @@ -21,6 +21,7 @@ #include #include +#include #include "generic.h" #include "devices.h" @@ -31,6 +32,15 @@ static mfp_cfg_t colibri_pxa300_pin_config[] __initdata = { GPIO1_nCS2, /* AX88796 chip select */ GPIO26_GPIO | MFP_PULL_HIGH, /* AX88796 IRQ */ + +#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE) + GPIO7_MMC1_CLK, + GPIO14_MMC1_CMD, + GPIO3_MMC1_DAT0, + GPIO4_MMC1_DAT1, + GPIO5_MMC1_DAT2, + GPIO6_MMC1_DAT3, +#endif }; #if defined(CONFIG_AX88796) @@ -80,11 +90,59 @@ static struct platform_device *colibri_pxa300_devices[] __initdata = { #endif }; +#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE) +#define MMC_DETECT_PIN mfp_to_gpio(MFP_PIN_GPIO13) + +static int colibri_pxa300_mci_init(struct device *dev, + irq_handler_t colibri_mmc_detect_int, + void *data) +{ + int ret; + + ret = gpio_request(MMC_DETECT_PIN, "mmc card detect"); + if (ret) + return ret; + + gpio_direction_input(MMC_DETECT_PIN); + ret = request_irq(gpio_to_irq(MMC_DETECT_PIN), colibri_mmc_detect_int, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + "MMC card detect", data); + if (ret) { + gpio_free(MMC_DETECT_PIN); + return ret; + } + + return 0; +} + +static void colibri_pxa300_mci_exit(struct device *dev, void *data) +{ + free_irq(MMC_DETECT_PIN, data); + gpio_free(gpio_to_irq(MMC_DETECT_PIN)); +} + +static struct pxamci_platform_data colibri_pxa300_mci_platform_data = { + .detect_delay = 20, + .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, + .init = colibri_pxa300_mci_init, + .exit = colibri_pxa300_mci_exit, +}; + +static void __init colibri_pxa300_init_mmc(void) +{ + pxa_set_mci_info(&colibri_pxa300_mci_platform_data); +} + +#else +static inline void colibri_pxa300_init_mmc(void) {} +#endif /* CONFIG_MMC_PXA */ + static void __init colibri_pxa300_init(void) { set_irq_type(COLIBRI_PXA300_ETH_IRQ, IRQ_TYPE_EDGE_FALLING); pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa300_pin_config)); platform_add_devices(ARRAY_AND_SIZE(colibri_pxa300_devices)); + colibri_pxa300_init_mmc(); } MACHINE_START(COLIBRI300, "Toradex Colibri PXA300") -- GitLab From 42e07ad7fc111bde5cd6c0e5bd7085b4cecf96b7 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 13 Mar 2009 16:37:11 +0100 Subject: [PATCH 3901/4982] [ARM] pxa: add USB support for Colibri PXA300 This adds support for USB OHCI for Toradex' Colibri PXA300 modules as connected on the evaluation board. Signed-off-by: Daniel Mack Signed-off-by: Eric Miao --- arch/arm/mach-pxa/colibri-pxa300.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/arch/arm/mach-pxa/colibri-pxa300.c b/arch/arm/mach-pxa/colibri-pxa300.c index 7cc4249c770..f1f24869c03 100644 --- a/arch/arm/mach-pxa/colibri-pxa300.c +++ b/arch/arm/mach-pxa/colibri-pxa300.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "generic.h" #include "devices.h" @@ -41,6 +42,11 @@ static mfp_cfg_t colibri_pxa300_pin_config[] __initdata = { GPIO5_MMC1_DAT2, GPIO6_MMC1_DAT3, #endif + +#if defined (CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) + GPIO0_2_USBH_PEN, + GPIO1_2_USBH_PWR, +#endif }; #if defined(CONFIG_AX88796) @@ -137,12 +143,27 @@ static void __init colibri_pxa300_init_mmc(void) static inline void colibri_pxa300_init_mmc(void) {} #endif /* CONFIG_MMC_PXA */ +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +static struct pxaohci_platform_data colibri_pxa300_ohci_info = { + .port_mode = PMM_GLOBAL_MODE, + .flags = ENABLE_PORT1 | POWER_CONTROL_LOW | POWER_SENSE_LOW, +}; + +static void __init colibri_pxa300_init_ohci(void) +{ + pxa_set_ohci_info(&colibri_pxa300_ohci_info); +} +#else +static inline void colibri_pxa300_init_ohci(void) {} +#endif /* CONFIG_USB_OHCI_HCD || CONFIG_USB_OHCI_HCD_MODULE */ + static void __init colibri_pxa300_init(void) { set_irq_type(COLIBRI_PXA300_ETH_IRQ, IRQ_TYPE_EDGE_FALLING); pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa300_pin_config)); platform_add_devices(ARRAY_AND_SIZE(colibri_pxa300_devices)); colibri_pxa300_init_mmc(); + colibri_pxa300_init_ohci(); } MACHINE_START(COLIBRI300, "Toradex Colibri PXA300") -- GitLab From b1701f1e09f8de37d3ab1c5452909632279d1972 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 13 Mar 2009 16:37:12 +0100 Subject: [PATCH 3902/4982] [ARM] pxa: rename and update Colibri PXA270 defconfig Signed-off-by: Daniel Mack Signed-off-by: Eric Miao --- ...bri_defconfig => colibri_pxa270_defconfig} | 594 +++++++++++++----- 1 file changed, 425 insertions(+), 169 deletions(-) rename arch/arm/configs/{colibri_defconfig => colibri_pxa270_defconfig} (76%) diff --git a/arch/arm/configs/colibri_defconfig b/arch/arm/configs/colibri_pxa270_defconfig similarity index 76% rename from arch/arm/configs/colibri_defconfig rename to arch/arm/configs/colibri_pxa270_defconfig index 744086fff41..4cf3bde1c52 100644 --- a/arch/arm/configs/colibri_defconfig +++ b/arch/arm/configs/colibri_pxa270_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.24-rc3 -# Mon Dec 3 13:36:09 2007 +# Linux kernel version: 2.6.29-rc8 +# Fri Mar 13 16:18:17 2009 # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y @@ -12,6 +12,7 @@ CONFIG_MMU=y # CONFIG_NO_IOPORT is not set CONFIG_GENERIC_HARDIRQS=y CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y CONFIG_LOCKDEP_SUPPORT=y CONFIG_TRACE_IRQFLAGS_SUPPORT=y CONFIG_HARDIRQS_SW_RESEND=y @@ -21,8 +22,8 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_ZONE_DMA=y CONFIG_ARCH_MTD_XIP=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_VECTORS_BASE=0xffff0000 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" @@ -42,22 +43,30 @@ CONFIG_POSIX_MQUEUE=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_BSD_PROCESS_ACCT_V3=y # CONFIG_TASKSTATS is not set -# CONFIG_USER_NS is not set -# CONFIG_PID_NS is not set # CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_FAIR_GROUP_SCHED=y -CONFIG_FAIR_USER_SCHED=y -# CONFIG_FAIR_CGROUP_SCHED is not set CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y @@ -70,29 +79,38 @@ CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y -CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y +CONFIG_AIO=y CONFIG_VM_EVENT_COUNTERS=y +CONFIG_COMPAT_BRK=y CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_MODVERSIONS=y CONFIG_MODULE_SRCVERSION_ALL=y -CONFIG_KMOD=y CONFIG_BLOCK=y CONFIG_LBD=y # CONFIG_BLK_DEV_IO_TRACE is not set -CONFIG_LSF=y # CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -106,6 +124,7 @@ CONFIG_DEFAULT_AS=y # CONFIG_DEFAULT_CFQ is not set # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_FREEZER=y # # System Type @@ -115,9 +134,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_REALVIEW is not set # CONFIG_ARCH_VERSATILE is not set # CONFIG_ARCH_AT91 is not set -# CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_EP93XX is not set # CONFIG_ARCH_FOOTBRIDGE is not set @@ -131,41 +148,58 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_IXP2000 is not set # CONFIG_ARCH_IXP4XX is not set # CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set # CONFIG_ARCH_KS8695 is not set # CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set # CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set # CONFIG_ARCH_PNX4008 is not set CONFIG_ARCH_PXA=y # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set # CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set # CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_W90X900 is not set # # Intel PXA2xx/PXA3xx Implementations # +# CONFIG_ARCH_GUMSTIX is not set +# CONFIG_MACH_INTELMOTE2 is not set # CONFIG_ARCH_LUBBOCK is not set # CONFIG_MACH_LOGICPD_PXA270 is not set # CONFIG_MACH_MAINSTONE is not set +# CONFIG_MACH_MP900C is not set # CONFIG_ARCH_PXA_IDP is not set # CONFIG_PXA_SHARPSL is not set -# CONFIG_MACH_TRIZEPS4 is not set +# CONFIG_ARCH_VIPER is not set +# CONFIG_ARCH_PXA_ESERIES is not set +# CONFIG_TRIZEPS_PXA is not set +# CONFIG_MACH_H5000 is not set # CONFIG_MACH_EM_X270 is not set CONFIG_MACH_COLIBRI=y +# CONFIG_MACH_COLIBRI300 is not set # CONFIG_MACH_ZYLONITE is not set +# CONFIG_MACH_LITTLETON is not set +# CONFIG_MACH_RAUMFELD_PROTO is not set +# CONFIG_MACH_TAVOREVB is not set +# CONFIG_MACH_SAAR is not set # CONFIG_MACH_ARMCORE is not set +# CONFIG_MACH_CM_X300 is not set +# CONFIG_MACH_MAGICIAN is not set +# CONFIG_MACH_MIOA701 is not set +# CONFIG_MACH_PCM027 is not set +# CONFIG_ARCH_PXA_PALM is not set +# CONFIG_PXA_EZX is not set CONFIG_PXA27x=y - -# -# Boot options -# - -# -# Power management -# +# CONFIG_PXA_PWM is not set # # Processor Type @@ -174,6 +208,7 @@ CONFIG_CPU_32=y CONFIG_CPU_XSCALE=y CONFIG_CPU_32v5=y CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_PABRT_NOIFAR=y CONFIG_CPU_CACHE_VIVT=y CONFIG_CPU_TLB_V4WBI=y CONFIG_CPU_CP15=y @@ -187,6 +222,7 @@ CONFIG_ARM_THUMB=y # CONFIG_OUTER_CACHE is not set CONFIG_IWMMXT=y CONFIG_XSCALE_PMU=y +CONFIG_COMMON_CLKDEV=y # # Bus support @@ -198,28 +234,33 @@ CONFIG_XSCALE_PMU=y # # Kernel Features # -# CONFIG_TICK_ONESHOT is not set +CONFIG_TICK_ONESHOT=y # CONFIG_NO_HZ is not set # CONFIG_HIGH_RES_TIMERS is not set CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 CONFIG_PREEMPT=y CONFIG_HZ=100 CONFIG_AEABI=y CONFIG_OABI_COMPAT=y -# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y # CONFIG_DISCONTIGMEM_MANUAL is not set # CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4096 -# CONFIG_RESOURCES_64BIT is not set -CONFIG_ZONE_DMA_FLAG=1 -CONFIG_BOUNCE=y +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y CONFIG_ALIGNMENT_TRAP=y # @@ -231,6 +272,12 @@ CONFIG_CMDLINE="" # CONFIG_XIP_KERNEL is not set # CONFIG_KEXEC is not set +# +# CPU Power Management +# +# CONFIG_CPU_FREQ is not set +# CONFIG_CPU_IDLE is not set + # # Floating point emulation # @@ -246,6 +293,8 @@ CONFIG_FPE_NWFPE=y # Userspace binary formats # CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y # CONFIG_BINFMT_AOUT is not set # CONFIG_BINFMT_MISC is not set @@ -253,21 +302,18 @@ CONFIG_BINFMT_ELF=y # Power management options # CONFIG_PM=y -# CONFIG_PM_LEGACY is not set # CONFIG_PM_DEBUG is not set CONFIG_PM_SLEEP=y -CONFIG_SUSPEND_UP_POSSIBLE=y CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y # CONFIG_APM_EMULATION is not set - -# -# Networking -# +CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_NET=y # # Networking options # +CONFIG_COMPAT_NET_DEV_OPS=y CONFIG_PACKET=y CONFIG_PACKET_MMAP=y CONFIG_UNIX=y @@ -275,6 +321,7 @@ CONFIG_XFRM=y CONFIG_XFRM_USER=m # CONFIG_XFRM_SUB_POLICY is not set # CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set CONFIG_NET_KEY=y # CONFIG_NET_KEY_MIGRATE is not set CONFIG_INET=y @@ -304,26 +351,26 @@ CONFIG_INET_TCP_DIAG=y CONFIG_TCP_CONG_CUBIC=y CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_TCP_MD5SIG is not set -# CONFIG_IP_VS is not set # CONFIG_IPV6 is not set -# CONFIG_INET6_XFRM_TUNNEL is not set -# CONFIG_INET6_TUNNEL is not set # CONFIG_NETLABEL is not set # CONFIG_NETWORK_SECMARK is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y # # Core Netfilter Configuration # -# CONFIG_NETFILTER_NETLINK is not set -# CONFIG_NF_CONNTRACK_ENABLED is not set +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set # CONFIG_NF_CONNTRACK is not set # CONFIG_NETFILTER_XTABLES is not set +# CONFIG_IP_VS is not set # # IP: Netfilter Configuration # +# CONFIG_NF_DEFRAG_IPV4 is not set CONFIG_IP_NF_QUEUE=m # CONFIG_IP_NF_IPTABLES is not set # CONFIG_IP_NF_ARPTABLES is not set @@ -332,7 +379,9 @@ CONFIG_IP_NF_QUEUE=m # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set CONFIG_VLAN_8021Q=m +# CONFIG_VLAN_8021Q_GVRP is not set # CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set @@ -342,12 +391,14 @@ CONFIG_VLAN_8021Q=m # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set # # Network testing # # CONFIG_NET_PKTGEN is not set # CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set CONFIG_IRDA=m # @@ -381,15 +432,6 @@ CONFIG_IRTTY_SIR=m # CONFIG_KSDAZZLE_DONGLE is not set # CONFIG_KS959_DONGLE is not set -# -# Old SIR device drivers -# -# CONFIG_IRPORT_SIR is not set - -# -# Old Serial dongle support -# - # # FIR device drivers # @@ -410,7 +452,6 @@ CONFIG_BT_HIDP=m # # Bluetooth device drivers # -# CONFIG_BT_HCIUSB is not set # CONFIG_BT_HCIBTUSB is not set # CONFIG_BT_HCIBTSDIO is not set # CONFIG_BT_HCIUART is not set @@ -419,21 +460,20 @@ CONFIG_BT_HIDP=m # CONFIG_BT_HCIBFUSB is not set # CONFIG_BT_HCIVHCI is not set # CONFIG_AF_RXRPC is not set - -# -# Wireless -# +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y CONFIG_CFG80211=y +# CONFIG_CFG80211_REG_DEBUG is not set CONFIG_NL80211=y +CONFIG_WIRELESS_OLD_REGULATORY=y CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +CONFIG_LIB80211=y +CONFIG_LIB80211_CRYPT_WEP=y +CONFIG_LIB80211_CRYPT_CCMP=y +CONFIG_LIB80211_CRYPT_TKIP=y # CONFIG_MAC80211 is not set -CONFIG_IEEE80211=y -# CONFIG_IEEE80211_DEBUG is not set -CONFIG_IEEE80211_CRYPT_WEP=y -CONFIG_IEEE80211_CRYPT_CCMP=m -CONFIG_IEEE80211_CRYPT_TKIP=m -CONFIG_IEEE80211_SOFTMAC=m -# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set +# CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set @@ -448,6 +488,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set @@ -457,9 +499,11 @@ CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set CONFIG_MTD_CONCAT=y CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set # CONFIG_MTD_REDBOOT_PARTS is not set # CONFIG_MTD_CMDLINE_PARTS is not set # CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set # # User Modules And Translation Layers @@ -510,9 +554,7 @@ CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_COMPLEX_MAPPINGS=y CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_PHYSMAP_START=0x0 -CONFIG_MTD_PHYSMAP_LEN=0x0 -CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +# CONFIG_MTD_PHYSMAP_COMPAT is not set CONFIG_MTD_PXA2XX=y # CONFIG_MTD_ARM_INTEGRATOR is not set # CONFIG_MTD_IMPA7 is not set @@ -538,6 +580,7 @@ CONFIG_MTD_NAND=y # CONFIG_MTD_NAND_ECC_SMC is not set # CONFIG_MTD_NAND_MUSEUM_IDS is not set # CONFIG_MTD_NAND_H1900 is not set +# CONFIG_MTD_NAND_GPIO is not set CONFIG_MTD_NAND_IDS=y CONFIG_MTD_NAND_DISKONCHIP=y CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED=y @@ -555,6 +598,11 @@ CONFIG_MTD_ONENAND=y # CONFIG_MTD_ONENAND_2X_PROGRAM is not set # CONFIG_MTD_ONENAND_SIM is not set +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + # # UBI - Unsorted block images # @@ -569,36 +617,41 @@ CONFIG_BLK_DEV_NBD=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=8 CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +# CONFIG_BLK_DEV_XIP is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set CONFIG_MISC_DEVICES=y +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_ISL29003 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_LEGACY is not set # CONFIG_EEPROM_93CX6 is not set +CONFIG_HAVE_IDE=y CONFIG_IDE=y -CONFIG_IDE_MAX_HWIFS=4 -CONFIG_BLK_DEV_IDE=y # -# Please see Documentation/ide.txt for help/info on IDE drives +# Please see Documentation/ide/ide.txt for help/info on IDE drives # # CONFIG_BLK_DEV_IDE_SATA is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_IDE_GD=y +CONFIG_IDE_GD_ATA=y +# CONFIG_IDE_GD_ATAPI is not set # CONFIG_BLK_DEV_IDECD is not set # CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_IDE_TASK_IOCTL is not set CONFIG_IDE_PROC_FS=y # # IDE chipset support/bugfixes # -CONFIG_IDE_GENERIC=y # CONFIG_BLK_DEV_PLATFORM is not set -# CONFIG_IDE_ARM is not set # CONFIG_BLK_DEV_IDEDMA is not set -CONFIG_IDE_ARCH_OBSOLETE_INIT=y -# CONFIG_BLK_DEV_HD is not set # # SCSI device support @@ -610,7 +663,6 @@ CONFIG_IDE_ARCH_OBSOLETE_INIT=y # CONFIG_ATA is not set # CONFIG_MD is not set CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_MACVLAN is not set @@ -631,6 +683,10 @@ CONFIG_PHYLIB=y # CONFIG_SMSC_PHY is not set # CONFIG_BROADCOM_PHY is not set # CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set # CONFIG_FIXED_PHY is not set # CONFIG_MDIO_BITBANG is not set CONFIG_NET_ETHERNET=y @@ -638,11 +694,17 @@ CONFIG_MII=y # CONFIG_AX88796 is not set # CONFIG_SMC91X is not set CONFIG_DM9000=y +CONFIG_DM9000_DEBUGLEVEL=4 +# CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL is not set # CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set # CONFIG_IBM_NEW_EMAC_ZMII is not set # CONFIG_IBM_NEW_EMAC_RGMII is not set # CONFIG_IBM_NEW_EMAC_TAH is not set # CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set # CONFIG_B44 is not set # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set @@ -654,10 +716,15 @@ CONFIG_DM9000=y CONFIG_WLAN_80211=y # CONFIG_LIBERTAS is not set # CONFIG_USB_ZD1201 is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_IWLWIFI_LEDS is not set CONFIG_HOSTAP=y CONFIG_HOSTAP_FIRMWARE=y CONFIG_HOSTAP_FIRMWARE_NVRAM=y -# CONFIG_ZD1211RW is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# # # USB Network Adapters @@ -670,7 +737,6 @@ CONFIG_HOSTAP_FIRMWARE_NVRAM=y # CONFIG_WAN is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set -# CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set @@ -710,6 +776,7 @@ CONFIG_INPUT_MOUSE=y # CONFIG_MOUSE_PS2 is not set CONFIG_MOUSE_SERIAL=m # CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set # CONFIG_MOUSE_VSXXXAA is not set # CONFIG_MOUSE_GPIO is not set # CONFIG_INPUT_JOYSTICK is not set @@ -718,20 +785,25 @@ CONFIG_INPUT_TOUCHSCREEN=y # CONFIG_TOUCHSCREEN_FUJITSU is not set # CONFIG_TOUCHSCREEN_GUNZE is not set # CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set # CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set # CONFIG_TOUCHSCREEN_MK712 is not set # CONFIG_TOUCHSCREEN_PENMOUNT is not set # CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set # CONFIG_TOUCHSCREEN_TOUCHWIN is not set -CONFIG_TOUCHSCREEN_UCB1400=y # CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set CONFIG_INPUT_MISC=y # CONFIG_INPUT_ATI_REMOTE is not set # CONFIG_INPUT_ATI_REMOTE2 is not set # CONFIG_INPUT_KEYSPAN_REMOTE is not set # CONFIG_INPUT_POWERMATE is not set # CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set CONFIG_INPUT_UINPUT=m +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set # # Hardware I/O ports @@ -746,9 +818,11 @@ CONFIG_SERIO_LIBPS2=y # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y # CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y # CONFIG_SERIAL_NONSTANDARD is not set # @@ -764,45 +838,50 @@ CONFIG_SERIAL_PXA_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_IPMI_HANDLER is not set CONFIG_HW_RANDOM=y -# CONFIG_NVRAM is not set # CONFIG_R3964 is not set # CONFIG_RAW_DRIVER is not set # CONFIG_TCG_TPM is not set CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y # -# I2C Algorithms +# I2C Hardware Bus support # -# CONFIG_I2C_ALGOBIT is not set -# CONFIG_I2C_ALGOPCF is not set -# CONFIG_I2C_ALGOPCA is not set # -# I2C Hardware Bus support +# I2C system bus drivers (mostly embedded / system-on-chip) # # CONFIG_I2C_GPIO is not set -# CONFIG_I2C_PXA is not set # CONFIG_I2C_OCORES is not set -# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PXA is not set # CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_TAOS_EVM is not set -# CONFIG_I2C_STUB is not set # CONFIG_I2C_TINY_USB is not set +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + # # Miscellaneous I2C Chip support # -# CONFIG_SENSORS_DS1337 is not set -# CONFIG_SENSORS_DS1374 is not set # CONFIG_DS1682 is not set -# CONFIG_EEPROM_LEGACY is not set # CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set # CONFIG_SENSORS_PCA9539 is not set # CONFIG_SENSORS_PCF8591 is not set # CONFIG_SENSORS_MAX6875 is not set @@ -811,16 +890,35 @@ CONFIG_I2C_CHARDEV=y # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_SPI is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_GPIO_SYSFS is not set # -# SPI support +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: # -# CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set CONFIG_HWMON=y # CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_AD7414 is not set # CONFIG_SENSORS_AD7418 is not set # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set @@ -828,7 +926,10 @@ CONFIG_HWMON=y # CONFIG_SENSORS_ADM1029 is not set # CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7462 is not set # CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7473 is not set +# CONFIG_SENSORS_ADT7475 is not set # CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_F71805F is not set @@ -848,6 +949,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_LM90 is not set # CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4245 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_PC87360 is not set @@ -856,6 +958,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_SMSC47M192 is not set # CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_ADS7828 is not set # CONFIG_SENSORS_THMC50 is not set # CONFIG_SENSORS_VT1211 is not set # CONFIG_SENSORS_W83781D is not set @@ -863,9 +966,12 @@ CONFIG_HWMON=y # CONFIG_SENSORS_W83792D is not set # CONFIG_SENSORS_W83793 is not set # CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set # CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627EHF is not set # CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set CONFIG_WATCHDOG=y # CONFIG_WATCHDOG_NOWAYOUT is not set @@ -879,23 +985,46 @@ CONFIG_WATCHDOG=y # USB-based Watchdog Cards # # CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y # # Sonics Silicon Backplane # -CONFIG_SSB_POSSIBLE=y # CONFIG_SSB is not set # # Multifunction device drivers # +# CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_TPS65010 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set # # Multimedia devices # + +# +# Multimedia core support +# # CONFIG_VIDEO_DEV is not set # CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# CONFIG_DAB=y # CONFIG_USB_DABUSB is not set @@ -907,6 +1036,7 @@ CONFIG_DAB=y CONFIG_FB=y CONFIG_FIRMWARE_EDID=y # CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y @@ -914,8 +1044,8 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_FILLRECT is not set # CONFIG_FB_SYS_COPYAREA is not set # CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set -CONFIG_FB_DEFERRED_IO=y # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -928,13 +1058,20 @@ CONFIG_FB_DEFERRED_IO=y # CONFIG_FB_UVESA is not set # CONFIG_FB_S1D13XXX is not set CONFIG_FB_PXA=y +# CONFIG_FB_PXA_OVERLAY is not set +# CONFIG_FB_PXA_SMARTPANEL is not set # CONFIG_FB_PXA_PARAMETERS is not set # CONFIG_FB_MBX is not set +# CONFIG_FB_W100 is not set # CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_LCD_CLASS_DEVICE=y +# CONFIG_LCD_ILI9320 is not set +# CONFIG_LCD_PLATFORM is not set CONFIG_BACKLIGHT_CLASS_DEVICE=y -# CONFIG_BACKLIGHT_CORGI is not set +CONFIG_BACKLIGHT_GENERIC=y # # Display device support @@ -964,12 +1101,7 @@ CONFIG_LOGO=y CONFIG_LOGO_LINUX_MONO=y CONFIG_LOGO_LINUX_VGA16=y CONFIG_LOGO_LINUX_CLUT224=y - -# -# Sound -# # CONFIG_SOUND is not set -CONFIG_AC97_BUS=y CONFIG_HID_SUPPORT=y CONFIG_HID=y # CONFIG_HID_DEBUG is not set @@ -979,18 +1111,26 @@ CONFIG_HID=y # USB Input Devices # # CONFIG_USB_HID is not set +# CONFIG_HID_PID is not set # # USB HID Boot Protocol drivers # # CONFIG_USB_KBD is not set # CONFIG_USB_MOUSE is not set + +# +# Special HID drivers +# +CONFIG_HID_COMPAT=y +# CONFIG_HID_APPLE is not set CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y # CONFIG_USB_ARCH_HAS_EHCI is not set CONFIG_USB=y # CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set # # Miscellaneous USB options @@ -999,29 +1139,40 @@ CONFIG_USB_DEVICEFS=y # CONFIG_USB_DEVICE_CLASS is not set # CONFIG_USB_DYNAMIC_MINORS is not set # CONFIG_USB_SUSPEND is not set -# CONFIG_USB_PERSIST is not set # CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set # # USB Host Controller Drivers # +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_OHCI_HCD is not set # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_GADGET_MUSB_HDRC is not set # # USB Device Class drivers # # CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; # # -# may also be needed; see USB_STORAGE Help for more information +# see USB_STORAGE Help for more information # # CONFIG_USB_LIBUSUAL is not set @@ -1029,19 +1180,14 @@ CONFIG_USB_DEVICEFS=y # USB Imaging devices # # CONFIG_USB_MDC800 is not set -# CONFIG_USB_MON is not set # # USB port drivers # - -# -# USB Serial Converter support -# CONFIG_USB_SERIAL=m +# CONFIG_USB_EZUSB is not set # CONFIG_USB_SERIAL_GENERIC is not set # CONFIG_USB_SERIAL_AIRCABLE is not set -# CONFIG_USB_SERIAL_AIRPRIME is not set # CONFIG_USB_SERIAL_ARK3116 is not set # CONFIG_USB_SERIAL_BELKIN is not set # CONFIG_USB_SERIAL_CH341 is not set @@ -1059,6 +1205,7 @@ CONFIG_USB_SERIAL=m # CONFIG_USB_SERIAL_EDGEPORT_TI is not set # CONFIG_USB_SERIAL_GARMIN is not set # CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_IUU is not set # CONFIG_USB_SERIAL_KEYSPAN_PDA is not set # CONFIG_USB_SERIAL_KEYSPAN is not set # CONFIG_USB_SERIAL_KLSI is not set @@ -1066,17 +1213,21 @@ CONFIG_USB_SERIAL=m # CONFIG_USB_SERIAL_MCT_U232 is not set # CONFIG_USB_SERIAL_MOS7720 is not set # CONFIG_USB_SERIAL_MOS7840 is not set +# CONFIG_USB_SERIAL_MOTOROLA is not set # CONFIG_USB_SERIAL_NAVMAN is not set # CONFIG_USB_SERIAL_PL2303 is not set # CONFIG_USB_SERIAL_OTI6858 is not set +# CONFIG_USB_SERIAL_SPCP8X5 is not set # CONFIG_USB_SERIAL_HP4X is not set # CONFIG_USB_SERIAL_SAFE is not set +# CONFIG_USB_SERIAL_SIEMENS_MPI is not set # CONFIG_USB_SERIAL_SIERRAWIRELESS is not set # CONFIG_USB_SERIAL_TI is not set # CONFIG_USB_SERIAL_CYBERJACK is not set # CONFIG_USB_SERIAL_XIRCOM is not set # CONFIG_USB_SERIAL_OPTION is not set # CONFIG_USB_SERIAL_OMNINET is not set +# CONFIG_USB_SERIAL_OPTICON is not set # CONFIG_USB_SERIAL_DEBUG is not set # @@ -1085,7 +1236,7 @@ CONFIG_USB_SERIAL=m # CONFIG_USB_EMI62 is not set # CONFIG_USB_EMI26 is not set # CONFIG_USB_ADUTUX is not set -# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_SEVSEG is not set # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set @@ -1101,30 +1252,29 @@ CONFIG_USB_SERIAL=m # CONFIG_USB_TRANCEVIBRATOR is not set # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set - -# -# USB DSL modem support -# - -# -# USB Gadget Support -# +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set CONFIG_USB_GADGET=m # CONFIG_USB_GADGET_DEBUG is not set # CONFIG_USB_GADGET_DEBUG_FILES is not set # CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 CONFIG_USB_GADGET_SELECTED=y -# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_AT91 is not set # CONFIG_USB_GADGET_ATMEL_USBA is not set # CONFIG_USB_GADGET_FSL_USB2 is not set -# CONFIG_USB_GADGET_NET2280 is not set -# CONFIG_USB_GADGET_PXA2XX is not set -# CONFIG_USB_GADGET_M66592 is not set -# CONFIG_USB_GADGET_GOKU is not set # CONFIG_USB_GADGET_LH7A40X is not set # CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_PXA27X is not set # CONFIG_USB_GADGET_S3C2410 is not set -# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_IMX is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_FSL_QE is not set +# CONFIG_USB_GADGET_CI13XXX is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_GOKU is not set CONFIG_USB_GADGET_DUMMY_HCD=y CONFIG_USB_DUMMY_HCD=m CONFIG_USB_GADGET_DUALSPEED=y @@ -1134,21 +1284,32 @@ CONFIG_USB_GADGET_DUALSPEED=y # CONFIG_USB_FILE_STORAGE is not set # CONFIG_USB_G_SERIAL is not set # CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set + +# +# OTG and related infrastructure +# +# CONFIG_USB_GPIO_VBUS is not set CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_UNSAFE_RESUME is not set # -# MMC/SD Card Drivers +# MMC/SD/SDIO Card Drivers # CONFIG_MMC_BLOCK=y CONFIG_MMC_BLOCK_BOUNCE=y # CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set # -# MMC/SD Host Controller Drivers +# MMC/SD/SDIO Host Controller Drivers # # CONFIG_MMC_PXA is not set +# CONFIG_MMC_SDHCI is not set +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set CONFIG_NEW_LEDS=y # CONFIG_LEDS_CLASS is not set @@ -1163,6 +1324,8 @@ CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y # CONFIG_LEDS_TRIGGER_IDE_DISK is not set CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set CONFIG_RTC_LIB=y CONFIG_RTC_CLASS=y # CONFIG_RTC_HCTOSYS is not set @@ -1190,6 +1353,9 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_PCF8563 is not set CONFIG_RTC_DRV_PCF8583=m # CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set # # SPI RTC drivers @@ -1199,36 +1365,45 @@ CONFIG_RTC_DRV_PCF8583=m # Platform RTC drivers # # CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set # CONFIG_RTC_DRV_DS1553 is not set -# CONFIG_RTC_DRV_STK17TA8 is not set # CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set # CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set # CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set # CONFIG_RTC_DRV_V3020 is not set # # on-CPU RTC drivers # # CONFIG_RTC_DRV_SA1100 is not set +# CONFIG_RTC_DRV_PXA is not set +# CONFIG_DMADEVICES is not set +# CONFIG_REGULATOR is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set # # File systems # # CONFIG_EXT2_FS is not set # CONFIG_EXT3_FS is not set -# CONFIG_EXT4DEV_FS is not set +# CONFIG_EXT4_FS is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set # CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set CONFIG_AUTOFS4_FS=y # CONFIG_FUSE_FS is not set @@ -1254,15 +1429,13 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-15" # CONFIG_PROC_FS=y CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_CONFIGFS_FS=y - -# -# Miscellaneous filesystems -# +CONFIG_MISC_FILESYSTEMS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_ECRYPT_FS is not set @@ -1283,9 +1456,13 @@ CONFIG_JFFS2_ZLIB=y CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set # CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set CONFIG_NETWORK_FILESYSTEMS=y @@ -1293,20 +1470,18 @@ CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set CONFIG_NFS_V4=y -# CONFIG_NFS_DIRECTIO is not set +CONFIG_ROOT_NFS=y CONFIG_NFSD=y CONFIG_NFSD_V3=y # CONFIG_NFSD_V3_ACL is not set CONFIG_NFSD_V4=y -CONFIG_NFSD_TCP=y -CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y -# CONFIG_SUNRPC_BIND34 is not set +# CONFIG_SUNRPC_REGISTER_V4 is not set CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set @@ -1361,9 +1536,6 @@ CONFIG_NLS_ISO8859_15=m # CONFIG_NLS_KOI8_U is not set CONFIG_NLS_UTF8=m # CONFIG_DLM is not set -CONFIG_INSTRUMENTATION=y -# CONFIG_PROFILING is not set -# CONFIG_MARKERS is not set # # Kernel hacking @@ -1371,6 +1543,7 @@ CONFIG_INSTRUMENTATION=y CONFIG_PRINTK_TIME=y CONFIG_ENABLE_WARN_DEPRECATED=y CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 CONFIG_MAGIC_SYSRQ=y # CONFIG_UNUSED_SYMBOLS is not set CONFIG_DEBUG_FS=y @@ -1378,9 +1551,12 @@ CONFIG_DEBUG_FS=y CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SHIRQ is not set CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_SLAB is not set CONFIG_DEBUG_PREEMPT=y # CONFIG_DEBUG_RT_MUTEXES is not set @@ -1396,16 +1572,40 @@ CONFIG_DEBUG_PREEMPT=y CONFIG_DEBUG_BUGVERBOSE=y CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set CONFIG_FRAME_POINTER=y -CONFIG_FORCED_INLINING=y # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_HAVE_FUNCTION_TRACER=y + +# +# Tracers +# +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set CONFIG_DEBUG_USER=y CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_STACK_USAGE is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set @@ -1415,58 +1615,114 @@ CONFIG_DEBUG_LL=y CONFIG_KEYS=y CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_SECURITY=y +# CONFIG_SECURITYFS is not set # CONFIG_SECURITY_NETWORK is not set -CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_PATH is not set # CONFIG_SECURITY_FILE_CAPABILITIES is not set # CONFIG_SECURITY_ROOTPLUG is not set +CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0 CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD2=y CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +CONFIG_CRYPTO_PCBC=m +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# # CONFIG_CRYPTO_HMAC is not set # CONFIG_CRYPTO_XCBC is not set -# CONFIG_CRYPTO_NULL is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y # CONFIG_CRYPTO_MD4 is not set CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=y +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=m CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m -# CONFIG_CRYPTO_WP512 is not set # CONFIG_CRYPTO_TGR192 is not set -# CONFIG_CRYPTO_GF128MUL is not set -CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_CBC=y -CONFIG_CRYPTO_PCBC=m -# CONFIG_CRYPTO_LRW is not set -# CONFIG_CRYPTO_XTS is not set -# CONFIG_CRYPTO_CRYPTD is not set -CONFIG_CRYPTO_DES=y -# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set -# CONFIG_CRYPTO_TWOFISH is not set -# CONFIG_CRYPTO_SERPENT is not set -CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set -# CONFIG_CRYPTO_TEA is not set -CONFIG_CRYPTO_ARC4=y +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set # CONFIG_CRYPTO_KHAZAD is not set -# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_SALSA20 is not set # CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# CONFIG_CRYPTO_DEFLATE=m -CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_CRC32C=y -# CONFIG_CRYPTO_CAMELLIA is not set -# CONFIG_CRYPTO_TEST is not set -# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y # # Library routines # CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y CONFIG_CRC_CCITT=y CONFIG_CRC16=y +# CONFIG_CRC_T10DIF is not set # CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y # CONFIG_CRC7 is not set -- GitLab From 71d361551265d90c8ab1dcdb223a15568d0026b3 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 13 Mar 2009 16:37:13 +0100 Subject: [PATCH 3903/4982] [ARM] pxa: add colibri PXA300 defconfig Signed-off-by: Daniel Mack Signed-off-by: Eric Miao --- arch/arm/configs/colibri_pxa300_defconfig | 1156 +++++++++++++++++++++ 1 file changed, 1156 insertions(+) create mode 100644 arch/arm/configs/colibri_pxa300_defconfig diff --git a/arch/arm/configs/colibri_pxa300_defconfig b/arch/arm/configs/colibri_pxa300_defconfig new file mode 100644 index 00000000000..4774a36fa74 --- /dev/null +++ b/arch/arm/configs/colibri_pxa300_defconfig @@ -0,0 +1,1156 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.29-rc8 +# Fri Mar 13 16:13:20 2009 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_MTD_XIP=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +# CONFIG_SYSVIPC is not set +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_NET_NS is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_FREEZER is not set + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +CONFIG_ARCH_PXA=y +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_W90X900 is not set + +# +# Intel PXA2xx/PXA3xx Implementations +# + +# +# Supported PXA3xx Processor Variants +# +CONFIG_CPU_PXA300=y +# CONFIG_CPU_PXA310 is not set +# CONFIG_CPU_PXA320 is not set +# CONFIG_CPU_PXA930 is not set +# CONFIG_CPU_PXA935 is not set +# CONFIG_ARCH_GUMSTIX is not set +# CONFIG_MACH_INTELMOTE2 is not set +# CONFIG_ARCH_LUBBOCK is not set +# CONFIG_MACH_LOGICPD_PXA270 is not set +# CONFIG_MACH_MAINSTONE is not set +# CONFIG_MACH_MP900C is not set +# CONFIG_ARCH_PXA_IDP is not set +# CONFIG_PXA_SHARPSL is not set +# CONFIG_ARCH_VIPER is not set +# CONFIG_ARCH_PXA_ESERIES is not set +# CONFIG_TRIZEPS_PXA is not set +# CONFIG_MACH_H5000 is not set +# CONFIG_MACH_EM_X270 is not set +# CONFIG_MACH_COLIBRI is not set +CONFIG_MACH_COLIBRI300=y +# CONFIG_MACH_ZYLONITE is not set +# CONFIG_MACH_LITTLETON is not set +# CONFIG_MACH_RAUMFELD_PROTO is not set +# CONFIG_MACH_TAVOREVB is not set +# CONFIG_MACH_SAAR is not set +# CONFIG_MACH_ARMCORE is not set +# CONFIG_MACH_CM_X300 is not set +# CONFIG_MACH_MAGICIAN is not set +# CONFIG_MACH_MIOA701 is not set +# CONFIG_MACH_PCM027 is not set +# CONFIG_ARCH_PXA_PALM is not set +# CONFIG_PXA_EZX is not set +CONFIG_PXA3xx=y +# CONFIG_PXA_PWM is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_XSC3=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y +CONFIG_IO_36=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_OUTER_CACHE=y +CONFIG_CACHE_XSC3L2=y +CONFIG_IWMMXT=y +CONFIG_COMMON_CLKDEV=y + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_CMDLINE="console=ttyS0,115200 rw" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_FREQ is not set +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_COMPAT_NET_DEV_OPS=y +# CONFIG_PACKET is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=y +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=y +CONFIG_INET6_XFRM_MODE_TUNNEL=y +CONFIG_INET6_XFRM_MODE_BEET=y +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=y +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_PHONET is not set +# CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_LIBFC is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_PHYLIB is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_AX88796=y +# CONFIG_AX88796_93CX6 is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_ATI_REMOTE is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +# CONFIG_INPUT_UINPUT is not set +CONFIG_INPUT_GPIO_ROTARY_ENCODER=y + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_PXA=y +CONFIG_SERIAL_PXA_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_DEBUG_GPIO=y +# CONFIG_GPIO_SYSFS is not set + +# +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_PXA=y +# CONFIG_FB_PXA_OVERLAY is not set +# CONFIG_FB_PXA_SMARTPANEL is not set +# CONFIG_FB_PXA_PARAMETERS is not set +# CONFIG_FB_MBX is not set +# CONFIG_FB_W100 is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_LCD_CLASS_DEVICE is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +# CONFIG_BACKLIGHT_GENERIC is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +CONFIG_USB_DEBUG=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +CONFIG_USB_MON=y +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +# CONFIG_USB_MUSB_HDRC is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; +# + +# +# see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set +# CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_USB_GPIO_VBUS is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +# CONFIG_MMC_BLOCK_BOUNCE is not set +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +CONFIG_MMC_PXA=y +# CONFIG_MMC_SDHCI is not set +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_REGULATOR is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_REGISTER_V4 is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +CONFIG_PRINTK_TIME=y +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_HAVE_FUNCTION_TRACER=y + +# +# Tracers +# +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_HW=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y -- GitLab From 626806d96fcfe355af5e1d299f651c774f68ead0 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 23 Mar 2009 02:04:16 +0100 Subject: [PATCH 3904/4982] [ARM] pxa: Fix Colibri AX88796 configuration Broaden the AX88796 register mask to allow access to the reset register. Remove unnecessary value definitions and the second resource block. Diagnosed-by: Matthias Meier Signed-off-by: Daniel Mack Signed-off-by: Eric Miao --- arch/arm/mach-pxa/colibri-pxa300.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-pxa/colibri-pxa300.c b/arch/arm/mach-pxa/colibri-pxa300.c index f1f24869c03..a5c1f72d88c 100644 --- a/arch/arm/mach-pxa/colibri-pxa300.c +++ b/arch/arm/mach-pxa/colibri-pxa300.c @@ -55,24 +55,16 @@ static mfp_cfg_t colibri_pxa300_pin_config[] __initdata = { */ static struct ax_plat_data colibri_asix_platdata = { .flags = AXFLG_MAC_FROMDEV, - .wordlength = 2, - .dcr_val = 0x01, - .rcr_val = 0x0e, - .gpoc_val = 0x19 + .wordlength = 2 }; static struct resource colibri_asix_resource[] = { [0] = { .start = PXA3xx_CS2_PHYS, - .end = PXA3xx_CS2_PHYS + (0x18 * 0x2) - 1, + .end = PXA3xx_CS2_PHYS + (0x20 * 2) - 1, .flags = IORESOURCE_MEM, }, [1] = { - .start = PXA3xx_CS2_PHYS + (1 << 11), - .end = PXA3xx_CS2_PHYS + (1 << 11) + 0x3fff, - .flags = IORESOURCE_MEM, - }, - [2] = { .start = COLIBRI_PXA300_ETH_IRQ, .end = COLIBRI_PXA300_ETH_IRQ, .flags = IORESOURCE_IRQ -- GitLab From acb3655973de30cb74549986e5e118a374967702 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 23 Mar 2009 02:04:17 +0100 Subject: [PATCH 3905/4982] [ARM] pxa: Refactor Colibri board support code - Move common function for all Colibri PXA3xx boards to the newly added colibri-pxa3xx.c - Drop some unnecessary defines from colibri.h - Make Kconfig reflect the fact that code for colibri 300 module does also work for the 310 model - Give up on the huge pin config table which was messed up with lots of #ifdefs and switch over to locally defined tables for configured functions Cc: Matthias Meier Signed-off-by: Daniel Mack Signed-off-by: Eric Miao --- arch/arm/mach-pxa/Kconfig | 2 +- arch/arm/mach-pxa/Makefile | 2 +- arch/arm/mach-pxa/colibri-pxa300.c | 116 +++++++---------------- arch/arm/mach-pxa/colibri-pxa3xx.c | 75 +++++++++++++++ arch/arm/mach-pxa/include/mach/colibri.h | 18 ++-- 5 files changed, 119 insertions(+), 94 deletions(-) create mode 100644 arch/arm/mach-pxa/colibri-pxa3xx.c diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 1a93888c68a..142fd59a40b 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -266,7 +266,7 @@ config MACH_COLIBRI select PXA27x config MACH_COLIBRI300 - bool "Toradex Colibri PXA300" + bool "Toradex Colibri PXA300/310" select PXA3xx select CPU_PXA300 diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index df6534b49e3..772569383b3 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -36,7 +36,7 @@ obj-$(CONFIG_MACH_MP900C) += mp900.o obj-$(CONFIG_ARCH_PXA_IDP) += idp.o obj-$(CONFIG_MACH_TRIZEPS4) += trizeps4.o obj-$(CONFIG_MACH_COLIBRI) += colibri-pxa270.o -obj-$(CONFIG_MACH_COLIBRI300) += colibri-pxa300.o +obj-$(CONFIG_MACH_COLIBRI300) += colibri-pxa3xx.o colibri-pxa300.o obj-$(CONFIG_MACH_H5000) += h5000.o obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o sharpsl_pm.o corgi_pm.o obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o sharpsl_pm.o spitz_pm.o diff --git a/arch/arm/mach-pxa/colibri-pxa300.c b/arch/arm/mach-pxa/colibri-pxa300.c index a5c1f72d88c..14ef9bf094f 100644 --- a/arch/arm/mach-pxa/colibri-pxa300.c +++ b/arch/arm/mach-pxa/colibri-pxa300.c @@ -1,8 +1,10 @@ /* * arch/arm/mach-pxa/colibri-pxa300.c * - * Support for Toradex PXA300 based Colibri module + * Support for Toradex PXA300/310 based Colibri module + * * Daniel Mack + * Matthias Meier * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -16,40 +18,19 @@ #include #include +#include #include #include #include #include -#include #include #include "generic.h" #include "devices.h" -/* - * GPIO configuration - */ -static mfp_cfg_t colibri_pxa300_pin_config[] __initdata = { - GPIO1_nCS2, /* AX88796 chip select */ - GPIO26_GPIO | MFP_PULL_HIGH, /* AX88796 IRQ */ - -#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE) - GPIO7_MMC1_CLK, - GPIO14_MMC1_CMD, - GPIO3_MMC1_DAT0, - GPIO4_MMC1_DAT1, - GPIO5_MMC1_DAT2, - GPIO6_MMC1_DAT3, -#endif - -#if defined (CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) - GPIO0_2_USBH_PEN, - GPIO1_2_USBH_PWR, -#endif -}; - #if defined(CONFIG_AX88796) +#define COLIBRI_ETH_IRQ_GPIO mfp_to_gpio(GPIO26_GPIO) /* * Asix AX88796 Ethernet */ @@ -65,8 +46,8 @@ static struct resource colibri_asix_resource[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = COLIBRI_PXA300_ETH_IRQ, - .end = COLIBRI_PXA300_ETH_IRQ, + .start = gpio_to_irq(COLIBRI_ETH_IRQ_GPIO), + .end = gpio_to_irq(COLIBRI_ETH_IRQ_GPIO), .flags = IORESOURCE_IRQ } }; @@ -80,82 +61,57 @@ static struct platform_device asix_device = { .platform_data = &colibri_asix_platdata } }; -#endif /* CONFIG_AX88796 */ - -static struct platform_device *colibri_pxa300_devices[] __initdata = { -#if defined(CONFIG_AX88796) - &asix_device -#endif -}; - -#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE) -#define MMC_DETECT_PIN mfp_to_gpio(MFP_PIN_GPIO13) - -static int colibri_pxa300_mci_init(struct device *dev, - irq_handler_t colibri_mmc_detect_int, - void *data) -{ - int ret; - - ret = gpio_request(MMC_DETECT_PIN, "mmc card detect"); - if (ret) - return ret; - - gpio_direction_input(MMC_DETECT_PIN); - ret = request_irq(gpio_to_irq(MMC_DETECT_PIN), colibri_mmc_detect_int, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "MMC card detect", data); - if (ret) { - gpio_free(MMC_DETECT_PIN); - return ret; - } - - return 0; -} - -static void colibri_pxa300_mci_exit(struct device *dev, void *data) -{ - free_irq(MMC_DETECT_PIN, data); - gpio_free(gpio_to_irq(MMC_DETECT_PIN)); -} -static struct pxamci_platform_data colibri_pxa300_mci_platform_data = { - .detect_delay = 20, - .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, - .init = colibri_pxa300_mci_init, - .exit = colibri_pxa300_mci_exit, +static mfp_cfg_t colibri_pxa300_eth_pin_config[] __initdata = { + GPIO1_nCS2, /* AX88796 chip select */ + GPIO26_GPIO | MFP_PULL_HIGH /* AX88796 IRQ */ }; -static void __init colibri_pxa300_init_mmc(void) +static void __init colibri_pxa300_init_eth(void) { - pxa_set_mci_info(&colibri_pxa300_mci_platform_data); + pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa300_eth_pin_config)); + set_irq_type(gpio_to_irq(COLIBRI_ETH_IRQ_GPIO), IRQ_TYPE_EDGE_FALLING); + platform_device_register(&asix_device); } - #else -static inline void colibri_pxa300_init_mmc(void) {} -#endif /* CONFIG_MMC_PXA */ +static inline void __init colibri_pxa300_init_eth(void) {} +#endif /* CONFIG_AX88796 */ #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +static mfp_cfg_t colibri_pxa300_usb_pin_config[] __initdata = { + GPIO0_2_USBH_PEN, + GPIO1_2_USBH_PWR, +}; + static struct pxaohci_platform_data colibri_pxa300_ohci_info = { .port_mode = PMM_GLOBAL_MODE, .flags = ENABLE_PORT1 | POWER_CONTROL_LOW | POWER_SENSE_LOW, }; -static void __init colibri_pxa300_init_ohci(void) +void __init colibri_pxa300_init_ohci(void) { + pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa300_usb_pin_config)); pxa_set_ohci_info(&colibri_pxa300_ohci_info); } #else static inline void colibri_pxa300_init_ohci(void) {} #endif /* CONFIG_USB_OHCI_HCD || CONFIG_USB_OHCI_HCD_MODULE */ -static void __init colibri_pxa300_init(void) +static mfp_cfg_t colibri_pxa300_mmc_pin_config[] __initdata = { + GPIO7_MMC1_CLK, + GPIO14_MMC1_CMD, + GPIO3_MMC1_DAT0, + GPIO4_MMC1_DAT1, + GPIO5_MMC1_DAT2, + GPIO6_MMC1_DAT3, +}; + +void __init colibri_pxa300_init(void) { - set_irq_type(COLIBRI_PXA300_ETH_IRQ, IRQ_TYPE_EDGE_FALLING); - pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa300_pin_config)); - platform_add_devices(ARRAY_AND_SIZE(colibri_pxa300_devices)); - colibri_pxa300_init_mmc(); + colibri_pxa300_init_eth(); colibri_pxa300_init_ohci(); + colibri_pxa3xx_init_mmc(ARRAY_AND_SIZE(colibri_pxa300_mmc_pin_config), + mfp_to_gpio(MFP_PIN_GPIO13)); } MACHINE_START(COLIBRI300, "Toradex Colibri PXA300") diff --git a/arch/arm/mach-pxa/colibri-pxa3xx.c b/arch/arm/mach-pxa/colibri-pxa3xx.c new file mode 100644 index 00000000000..cbaa8424fc8 --- /dev/null +++ b/arch/arm/mach-pxa/colibri-pxa3xx.c @@ -0,0 +1,75 @@ +/* + * arch/arm/mach-pxa/colibri-pxa3xx.c + * + * Common functions for all Toradex PXA3xx modules + * + * Daniel Mack + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "generic.h" +#include "devices.h" + +#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE) +static int mmc_detect_pin; + +static int colibri_pxa3xx_mci_init(struct device *dev, + irq_handler_t colibri_mmc_detect_int, + void *data) +{ + int ret; + + ret = gpio_request(mmc_detect_pin, "mmc card detect"); + if (ret) + return ret; + + gpio_direction_input(mmc_detect_pin); + ret = request_irq(gpio_to_irq(mmc_detect_pin), colibri_mmc_detect_int, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + "MMC card detect", data); + if (ret) { + gpio_free(mmc_detect_pin); + return ret; + } + + return 0; +} + +static void colibri_pxa3xx_mci_exit(struct device *dev, void *data) +{ + free_irq(mmc_detect_pin, data); + gpio_free(gpio_to_irq(mmc_detect_pin)); +} + +static struct pxamci_platform_data colibri_pxa3xx_mci_platform_data = { + .detect_delay = 20, + .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, + .init = colibri_pxa3xx_mci_init, + .exit = colibri_pxa3xx_mci_exit, +}; + +void __init colibri_pxa3xx_init_mmc(mfp_cfg_t *pins, int len, int detect_pin) +{ + pxa3xx_mfp_config(pins, len); + mmc_detect_pin = detect_pin; + pxa_set_mci_info(&colibri_pxa3xx_mci_platform_data); +} +#endif /* CONFIG_MMC_PXA || CONFIG_MMC_PXA_MODULE */ + diff --git a/arch/arm/mach-pxa/include/mach/colibri.h b/arch/arm/mach-pxa/include/mach/colibri.h index e295e8df8d6..0becf6215c1 100644 --- a/arch/arm/mach-pxa/include/mach/colibri.h +++ b/arch/arm/mach-pxa/include/mach/colibri.h @@ -4,6 +4,12 @@ * common settings for all modules */ +#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE) +extern void colibri_pxa3xx_init_mmc(mfp_cfg_t *pins, int len, int detect_pin); +#else +static inline void colibri_pxa3xx_init_mmc(mfp_cfg_t *, int, int) {} +#endif + /* physical memory regions */ #define COLIBRI_SDRAM_BASE 0xa0000000 /* SDRAM region */ @@ -15,17 +21,5 @@ #define COLIBRI_PXA270_ETH_IRQ \ gpio_to_irq(mfp_to_gpio(COLIBRI_PXA270_ETH_IRQ_GPIO)) -/* definitions for Colibri PXA300 */ - -#define COLIBRI_PXA300_ETH_IRQ_GPIO 26 -#define COLIBRI_PXA300_ETH_IRQ \ - gpio_to_irq(mfp_to_gpio(COLIBRI_PXA300_ETH_IRQ_GPIO)) - -/* definitions for Colibri PXA320 */ - -#define COLIBRI_PXA320_ETH_IRQ_GPIO 36 -#define COLIBRI_PXA320_ETH_IRQ \ - gpio_to_irq(mfp_to_gpio(COLIBRI_PXA320_ETH_IRQ_GPIO)) - #endif /* _COLIBRI_H_ */ -- GitLab From bac07ecd6c9b16656aced6dc4f9f070120153046 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 23 Mar 2009 02:04:18 +0100 Subject: [PATCH 3906/4982] [ARM] pxa: Colibri PXA320 module basics This adds basic support for Colibri PXA320 modules. The file colibri-320.c only contains settings specific to this module, such as the Ethernet interface. Cc: Matthias Meier Signed-off-by: Daniel Mack Signed-off-by: Eric Miao --- arch/arm/mach-pxa/Kconfig | 5 ++ arch/arm/mach-pxa/Makefile | 1 + arch/arm/mach-pxa/colibri-pxa320.c | 128 +++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 arch/arm/mach-pxa/colibri-pxa320.c diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 142fd59a40b..96a2006cb59 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -270,6 +270,11 @@ config MACH_COLIBRI300 select PXA3xx select CPU_PXA300 +config MACH_COLIBRI320 + bool "Toradex Colibri PXA320" + select PXA3xx + select CPU_PXA320 + config MACH_ZYLONITE bool "PXA3xx Development Platform (aka Zylonite)" select PXA3xx diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 772569383b3..fc96e7d454b 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_ARCH_PXA_IDP) += idp.o obj-$(CONFIG_MACH_TRIZEPS4) += trizeps4.o obj-$(CONFIG_MACH_COLIBRI) += colibri-pxa270.o obj-$(CONFIG_MACH_COLIBRI300) += colibri-pxa3xx.o colibri-pxa300.o +obj-$(CONFIG_MACH_COLIBRI320) += colibri-pxa3xx.o colibri-pxa320.o obj-$(CONFIG_MACH_H5000) += h5000.o obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o sharpsl_pm.o corgi_pm.o obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o sharpsl_pm.o spitz_pm.o diff --git a/arch/arm/mach-pxa/colibri-pxa320.c b/arch/arm/mach-pxa/colibri-pxa320.c new file mode 100644 index 00000000000..86cb202847e --- /dev/null +++ b/arch/arm/mach-pxa/colibri-pxa320.c @@ -0,0 +1,128 @@ +/* + * arch/arm/mach-pxa/colibri-pxa320.c + * + * Support for Toradex PXA320/310 based Colibri module + * + * Daniel Mack + * Matthias Meier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "generic.h" +#include "devices.h" + +#if defined(CONFIG_AX88796) +#define COLIBRI_ETH_IRQ_GPIO mfp_to_gpio(GPIO36_GPIO) + +/* + * Asix AX88796 Ethernet + */ +static struct ax_plat_data colibri_asix_platdata = { + .flags = AXFLG_MAC_FROMDEV, + .wordlength = 2 +}; + +static struct resource colibri_asix_resource[] = { + [0] = { + .start = PXA3xx_CS2_PHYS, + .end = PXA3xx_CS2_PHYS + (0x20 * 2) - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = gpio_to_irq(COLIBRI_ETH_IRQ_GPIO), + .end = gpio_to_irq(COLIBRI_ETH_IRQ_GPIO), + .flags = IORESOURCE_IRQ + } +}; + +static struct platform_device asix_device = { + .name = "ax88796", + .id = 0, + .num_resources = ARRAY_SIZE(colibri_asix_resource), + .resource = colibri_asix_resource, + .dev = { + .platform_data = &colibri_asix_platdata + } +}; + +static mfp_cfg_t colibri_pxa320_eth_pin_config[] __initdata = { + GPIO3_nCS2, /* AX88796 chip select */ + GPIO36_GPIO | MFP_PULL_HIGH /* AX88796 IRQ */ +}; + +static void __init colibri_pxa320_init_eth(void) +{ + pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa320_eth_pin_config)); + set_irq_type(gpio_to_irq(COLIBRI_ETH_IRQ_GPIO), IRQ_TYPE_EDGE_FALLING); + platform_device_register(&asix_device); +} +#else +static inline void __init colibri_pxa320_init_eth(void) {} +#endif /* CONFIG_AX88796 */ + +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +static mfp_cfg_t colibri_pxa320_usb_pin_config[] __initdata = { + GPIO2_2_USBH_PEN, + GPIO3_2_USBH_PWR, +}; + +static struct pxaohci_platform_data colibri_pxa320_ohci_info = { + .port_mode = PMM_GLOBAL_MODE, + .flags = ENABLE_PORT1 | POWER_CONTROL_LOW | POWER_SENSE_LOW, +}; + +void __init colibri_pxa320_init_ohci(void) +{ + pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa320_usb_pin_config)); + pxa_set_ohci_info(&colibri_pxa320_ohci_info); +} +#else +static inline void colibri_pxa320_init_ohci(void) {} +#endif /* CONFIG_USB_OHCI_HCD || CONFIG_USB_OHCI_HCD_MODULE */ + +static mfp_cfg_t colibri_pxa320_mmc_pin_config[] __initdata = { + GPIO22_MMC1_CLK, + GPIO23_MMC1_CMD, + GPIO18_MMC1_DAT0, + GPIO19_MMC1_DAT1, + GPIO20_MMC1_DAT2, + GPIO21_MMC1_DAT3 +}; + +void __init colibri_pxa320_init(void) +{ + colibri_pxa320_init_eth(); + colibri_pxa320_init_ohci(); + colibri_pxa3xx_init_mmc(ARRAY_AND_SIZE(colibri_pxa320_mmc_pin_config), + mfp_to_gpio(MFP_PIN_GPIO28)); +} + +MACHINE_START(COLIBRI320, "Toradex Colibri PXA320") + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .boot_params = COLIBRI_SDRAM_BASE + 0x100, + .init_machine = colibri_pxa320_init, + .map_io = pxa_map_io, + .init_irq = pxa3xx_init_irq, + .timer = &pxa_timer, +MACHINE_END + -- GitLab From 91fcfb908d62038c3c2cdecb7fb8aa2c98cb70a2 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 23 Mar 2009 02:04:19 +0100 Subject: [PATCH 3907/4982] [ARM] pxa: Add Colibri LCD functions This adds LCD functions for Colibri PXA300 and Colibri PXA320 and configures a LQ043T3DX02 panel. Original-code-by: Matthias Meier Signed-off-by: Daniel Mack Signed-off-by: Eric Miao --- arch/arm/mach-pxa/colibri-pxa300.c | 40 +++++++++++++++++++++ arch/arm/mach-pxa/colibri-pxa320.c | 39 ++++++++++++++++++++ arch/arm/mach-pxa/colibri-pxa3xx.c | 46 ++++++++++++++++++++++++ arch/arm/mach-pxa/include/mach/colibri.h | 6 ++++ 4 files changed, 131 insertions(+) diff --git a/arch/arm/mach-pxa/colibri-pxa300.c b/arch/arm/mach-pxa/colibri-pxa300.c index 14ef9bf094f..2858a597870 100644 --- a/arch/arm/mach-pxa/colibri-pxa300.c +++ b/arch/arm/mach-pxa/colibri-pxa300.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "generic.h" #include "devices.h" @@ -106,10 +107,49 @@ static mfp_cfg_t colibri_pxa300_mmc_pin_config[] __initdata = { GPIO6_MMC1_DAT3, }; +#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE) +static mfp_cfg_t colibri_pxa300_lcd_pin_config[] __initdata = { + GPIO54_LCD_LDD_0, + GPIO55_LCD_LDD_1, + GPIO56_LCD_LDD_2, + GPIO57_LCD_LDD_3, + GPIO58_LCD_LDD_4, + GPIO59_LCD_LDD_5, + GPIO60_LCD_LDD_6, + GPIO61_LCD_LDD_7, + GPIO62_LCD_LDD_8, + GPIO63_LCD_LDD_9, + GPIO64_LCD_LDD_10, + GPIO65_LCD_LDD_11, + GPIO66_LCD_LDD_12, + GPIO67_LCD_LDD_13, + GPIO68_LCD_LDD_14, + GPIO69_LCD_LDD_15, + GPIO70_LCD_LDD_16, + GPIO71_LCD_LDD_17, + GPIO62_LCD_CS_N, + GPIO72_LCD_FCLK, + GPIO73_LCD_LCLK, + GPIO74_LCD_PCLK, + GPIO75_LCD_BIAS, + GPIO76_LCD_VSYNC, +}; + +static void __init colibri_pxa300_init_lcd(void) +{ + pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa300_lcd_pin_config)); +} + +#else +static inline void colibri_pxa300_init_lcd(void) {} +#endif /* CONFIG_FB_PXA || CONFIG_FB_PXA_MODULE */ + void __init colibri_pxa300_init(void) { colibri_pxa300_init_eth(); colibri_pxa300_init_ohci(); + colibri_pxa300_init_lcd(); + colibri_pxa3xx_init_lcd(mfp_to_gpio(GPIO49_GPIO)); colibri_pxa3xx_init_mmc(ARRAY_AND_SIZE(colibri_pxa300_mmc_pin_config), mfp_to_gpio(MFP_PIN_GPIO13)); } diff --git a/arch/arm/mach-pxa/colibri-pxa320.c b/arch/arm/mach-pxa/colibri-pxa320.c index 86cb202847e..b6773674351 100644 --- a/arch/arm/mach-pxa/colibri-pxa320.c +++ b/arch/arm/mach-pxa/colibri-pxa320.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "generic.h" @@ -108,10 +109,48 @@ static mfp_cfg_t colibri_pxa320_mmc_pin_config[] __initdata = { GPIO21_MMC1_DAT3 }; +#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE) +static mfp_cfg_t colibri_pxa320_lcd_pin_config[] __initdata = { + GPIO6_2_LCD_LDD_0, + GPIO7_2_LCD_LDD_1, + GPIO8_2_LCD_LDD_2, + GPIO9_2_LCD_LDD_3, + GPIO10_2_LCD_LDD_4, + GPIO11_2_LCD_LDD_5, + GPIO12_2_LCD_LDD_6, + GPIO13_2_LCD_LDD_7, + GPIO63_LCD_LDD_8, + GPIO64_LCD_LDD_9, + GPIO65_LCD_LDD_10, + GPIO66_LCD_LDD_11, + GPIO67_LCD_LDD_12, + GPIO68_LCD_LDD_13, + GPIO69_LCD_LDD_14, + GPIO70_LCD_LDD_15, + GPIO71_LCD_LDD_16, + GPIO72_LCD_LDD_17, + GPIO73_LCD_CS_N, + GPIO74_LCD_VSYNC, + GPIO14_2_LCD_FCLK, + GPIO15_2_LCD_LCLK, + GPIO16_2_LCD_PCLK, + GPIO17_2_LCD_BIAS, +}; + +static void __init colibri_pxa320_init_lcd(void) +{ + pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa320_lcd_pin_config)); +} +#else +static inline void colibri_pxa320_init_lcd(void) {} +#endif + void __init colibri_pxa320_init(void) { colibri_pxa320_init_eth(); colibri_pxa320_init_ohci(); + colibri_pxa320_init_lcd(); + colibri_pxa3xx_init_lcd(mfp_to_gpio(GPIO39_GPIO)); colibri_pxa3xx_init_mmc(ARRAY_AND_SIZE(colibri_pxa320_mmc_pin_config), mfp_to_gpio(MFP_PIN_GPIO28)); } diff --git a/arch/arm/mach-pxa/colibri-pxa3xx.c b/arch/arm/mach-pxa/colibri-pxa3xx.c index cbaa8424fc8..12d0afc54aa 100644 --- a/arch/arm/mach-pxa/colibri-pxa3xx.c +++ b/arch/arm/mach-pxa/colibri-pxa3xx.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "generic.h" #include "devices.h" @@ -73,3 +74,48 @@ void __init colibri_pxa3xx_init_mmc(mfp_cfg_t *pins, int len, int detect_pin) } #endif /* CONFIG_MMC_PXA || CONFIG_MMC_PXA_MODULE */ +#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE) +static int lcd_bl_pin; + +/* + * LCD panel (Sharp LQ043T3DX02) + */ +static void colibri_lcd_backlight(int on) +{ + gpio_set_value(lcd_bl_pin, !!on); +} + +static struct pxafb_mode_info sharp_lq43_mode = { + .pixclock = 101936, + .xres = 480, + .yres = 272, + .bpp = 32, + .depth = 18, + .hsync_len = 41, + .left_margin = 2, + .right_margin = 2, + .vsync_len = 10, + .upper_margin = 2, + .lower_margin = 2, + .sync = 0, + .cmap_greyscale = 0, +}; + +static struct pxafb_mach_info sharp_lq43_info = { + .modes = &sharp_lq43_mode, + .num_modes = 1, + .cmap_inverse = 0, + .cmap_static = 0, + .lcd_conn = LCD_COLOR_TFT_18BPP, + .pxafb_backlight_power = colibri_lcd_backlight, +}; + +void __init colibri_pxa3xx_init_lcd(int bl_pin) +{ + lcd_bl_pin = bl_pin; + gpio_request(bl_pin, "lcd backlight"); + gpio_direction_output(bl_pin, 0); + set_pxa_fb_info(&sharp_lq43_info); +} +#endif + diff --git a/arch/arm/mach-pxa/include/mach/colibri.h b/arch/arm/mach-pxa/include/mach/colibri.h index 0becf6215c1..3f2a01d6a03 100644 --- a/arch/arm/mach-pxa/include/mach/colibri.h +++ b/arch/arm/mach-pxa/include/mach/colibri.h @@ -10,6 +10,12 @@ extern void colibri_pxa3xx_init_mmc(mfp_cfg_t *pins, int len, int detect_pin); static inline void colibri_pxa3xx_init_mmc(mfp_cfg_t *, int, int) {} #endif +#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE) +extern void colibri_pxa3xx_init_lcd(int bl_pin); +#else +static inline void colibri_pxa3xx_init_lcd(int) {} +#endif + /* physical memory regions */ #define COLIBRI_SDRAM_BASE 0xa0000000 /* SDRAM region */ -- GitLab From e2bb5befd7b0ae2d045f4413a97db52340edec13 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 23 Mar 2009 02:04:20 +0100 Subject: [PATCH 3908/4982] [ARM] pxa: AC97 pin functions for Colibri PXA310/320 Signed-off-by: Daniel Mack Cc: Matthias Meier Signed-off-by: Eric Miao --- arch/arm/mach-pxa/colibri-pxa300.c | 24 ++++++++++++++++++++++++ arch/arm/mach-pxa/colibri-pxa320.c | 20 ++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/arch/arm/mach-pxa/colibri-pxa300.c b/arch/arm/mach-pxa/colibri-pxa300.c index 2858a597870..169ab552c21 100644 --- a/arch/arm/mach-pxa/colibri-pxa300.c +++ b/arch/arm/mach-pxa/colibri-pxa300.c @@ -144,12 +144,36 @@ static void __init colibri_pxa300_init_lcd(void) static inline void colibri_pxa300_init_lcd(void) {} #endif /* CONFIG_FB_PXA || CONFIG_FB_PXA_MODULE */ +#if defined(SND_AC97_CODEC) || defined(SND_AC97_CODEC_MODULE) +static mfp_cfg_t colibri_pxa310_ac97_pin_config[] __initdata = { + GPIO24_AC97_SYSCLK, + GPIO23_AC97_nACRESET, + GPIO25_AC97_SDATA_IN_0, + GPIO27_AC97_SDATA_OUT, + GPIO28_AC97_SYNC, + GPIO29_AC97_BITCLK +}; + +static inline void __init colibri_pxa310_init_ac97(void) +{ + /* no AC97 codec on Colibri PXA300 */ + if (!cpu_is_pxa310()) + return; + + pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa310_ac97_pin_config)); + pxa_set_ac97_info(NULL); +} +#else +static inline void colibri_pxa310_init_ac97(void) {} +#endif + void __init colibri_pxa300_init(void) { colibri_pxa300_init_eth(); colibri_pxa300_init_ohci(); colibri_pxa300_init_lcd(); colibri_pxa3xx_init_lcd(mfp_to_gpio(GPIO49_GPIO)); + colibri_pxa310_init_ac97(); colibri_pxa3xx_init_mmc(ARRAY_AND_SIZE(colibri_pxa300_mmc_pin_config), mfp_to_gpio(MFP_PIN_GPIO13)); } diff --git a/arch/arm/mach-pxa/colibri-pxa320.c b/arch/arm/mach-pxa/colibri-pxa320.c index b6773674351..573a9a1dd52 100644 --- a/arch/arm/mach-pxa/colibri-pxa320.c +++ b/arch/arm/mach-pxa/colibri-pxa320.c @@ -145,12 +145,32 @@ static void __init colibri_pxa320_init_lcd(void) static inline void colibri_pxa320_init_lcd(void) {} #endif +#if defined(SND_AC97_CODEC) || defined(SND_AC97_CODEC_MODULE) +static mfp_cfg_t colibri_pxa320_ac97_pin_config[] __initdata = { + GPIO34_AC97_SYSCLK, + GPIO35_AC97_SDATA_IN_0, + GPIO37_AC97_SDATA_OUT, + GPIO38_AC97_SYNC, + GPIO39_AC97_BITCLK, + GPIO40_AC97_nACRESET +}; + +static inline void __init colibri_pxa320_init_ac97(void) +{ + pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa320_ac97_pin_config)); + pxa_set_ac97_info(NULL); +} +#else +static inline void colibri_pxa320_init_ac97(void) {} +#endif + void __init colibri_pxa320_init(void) { colibri_pxa320_init_eth(); colibri_pxa320_init_ohci(); colibri_pxa320_init_lcd(); colibri_pxa3xx_init_lcd(mfp_to_gpio(GPIO39_GPIO)); + colibri_pxa320_init_ac97(); colibri_pxa3xx_init_mmc(ARRAY_AND_SIZE(colibri_pxa320_mmc_pin_config), mfp_to_gpio(MFP_PIN_GPIO28)); } -- GitLab From bd5ce4332328c1fe473690a86b2e6a4157be038f Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 20 Jan 2009 12:06:01 +0800 Subject: [PATCH 3909/4982] [ARM] pxa: introduce plat-pxa for PXA common code and add DMA support 1. introduce folder of 'arch/arm/plat-pxa' for common code across different PXA processor families 2. initially moved DMA code into plat-pxa 3. common code in moved into , new processors should implement its own , provide the following required definitions and '#include ' in the end: - DMAC_REGS_VIRT for mapped virtual address of the DMA registers' physical I/O memory Signed-off-by: Eric Miao --- arch/arm/Kconfig | 5 ++ arch/arm/Makefile | 1 + arch/arm/mach-pxa/Makefile | 2 +- arch/arm/mach-pxa/include/mach/dma.h | 83 +------------------------- arch/arm/plat-pxa/Kconfig | 3 + arch/arm/plat-pxa/Makefile | 6 ++ arch/arm/{mach-pxa => plat-pxa}/dma.c | 6 +- arch/arm/plat-pxa/include/plat/dma.h | 85 +++++++++++++++++++++++++++ 8 files changed, 105 insertions(+), 86 deletions(-) create mode 100644 arch/arm/plat-pxa/Kconfig create mode 100644 arch/arm/plat-pxa/Makefile rename arch/arm/{mach-pxa => plat-pxa}/dma.c (97%) create mode 100644 arch/arm/plat-pxa/include/plat/dma.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 12abdd43201..5ba00358e80 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -481,6 +481,7 @@ config ARCH_PXA select GENERIC_TIME select GENERIC_CLOCKEVENTS select TICK_ONESHOT + select PLAT_PXA help Support for Intel/Marvell's PXA2xx/PXA3xx processor line. @@ -618,6 +619,7 @@ source "arch/arm/mach-loki/Kconfig" source "arch/arm/mach-mv78xx0/Kconfig" source "arch/arm/mach-pxa/Kconfig" +source "arch/arm/plat-pxa/Kconfig" source "arch/arm/mach-sa1100/Kconfig" @@ -687,6 +689,9 @@ config PLAT_IOP config PLAT_ORION bool +config PLAT_PXA + bool + source arch/arm/mm/Kconfig config IWMMXT diff --git a/arch/arm/Makefile b/arch/arm/Makefile index e7ef876e574..897f2830bc4 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -109,6 +109,7 @@ ifeq ($(CONFIG_ARCH_SA1100),y) textofs-$(CONFIG_SA1111) := 0x00208000 endif machine-$(CONFIG_ARCH_PXA) := pxa + plat-$(CONFIG_PLAT_PXA) := pxa machine-$(CONFIG_ARCH_L7200) := l7200 machine-$(CONFIG_ARCH_INTEGRATOR) := integrator textofs-$(CONFIG_ARCH_CLPS711X) := 0x00028000 diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index fc96e7d454b..70b46570c5c 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -3,7 +3,7 @@ # # Common support (must be linked before board specific support) -obj-y += clock.o devices.o generic.o irq.o dma.o \ +obj-y += clock.o devices.o generic.o irq.o \ time.o gpio.o reset.o obj-$(CONFIG_PM) += pm.o sleep.o standby.o diff --git a/arch/arm/mach-pxa/include/mach/dma.h b/arch/arm/mach-pxa/include/mach/dma.h index b0812f59d3f..5bd55894a48 100644 --- a/arch/arm/mach-pxa/include/mach/dma.h +++ b/arch/arm/mach-pxa/include/mach/dma.h @@ -16,87 +16,6 @@ /* DMA Controller Registers Definitions */ #define DMAC_REGS_VIRT io_p2v(0x40000000) -#define DMAC_REG(x) (*((volatile u32 *)(DMAC_REGS_VIRT + (x)))) - -#define DCSR(n) DMAC_REG((n) << 2) -#define DALGN DMAC_REG(0x00a0) /* DMA Alignment Register */ -#define DINT DMAC_REG(0x00f0) /* DMA Interrupt Register */ -#define DDADR(n) DMAC_REG(0x0200 + ((n) << 4)) -#define DSADR(n) DMAC_REG(0x0204 + ((n) << 4)) -#define DTADR(n) DMAC_REG(0x0208 + ((n) << 4)) -#define DCMD(n) DMAC_REG(0x020c + ((n) << 4)) -#define DRCMR(n) DMAC_REG((((n) < 64) ? 0x0100 : 0x1100) + \ - (((n) & 0x3f) << 2)) - -#define DCSR_RUN (1 << 31) /* Run Bit (read / write) */ -#define DCSR_NODESC (1 << 30) /* No-Descriptor Fetch (read / write) */ -#define DCSR_STOPIRQEN (1 << 29) /* Stop Interrupt Enable (read / write) */ -#define DCSR_REQPEND (1 << 8) /* Request Pending (read-only) */ -#define DCSR_STOPSTATE (1 << 3) /* Stop State (read-only) */ -#define DCSR_ENDINTR (1 << 2) /* End Interrupt (read / write) */ -#define DCSR_STARTINTR (1 << 1) /* Start Interrupt (read / write) */ -#define DCSR_BUSERR (1 << 0) /* Bus Error Interrupt (read / write) */ - -#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) -#define DCSR_EORIRQEN (1 << 28) /* End of Receive Interrupt Enable (R/W) */ -#define DCSR_EORJMPEN (1 << 27) /* Jump to next descriptor on EOR */ -#define DCSR_EORSTOPEN (1 << 26) /* STOP on an EOR */ -#define DCSR_SETCMPST (1 << 25) /* Set Descriptor Compare Status */ -#define DCSR_CLRCMPST (1 << 24) /* Clear Descriptor Compare Status */ -#define DCSR_CMPST (1 << 10) /* The Descriptor Compare Status */ -#define DCSR_EORINTR (1 << 9) /* The end of Receive */ -#endif - -#define DRCMR_MAPVLD (1 << 7) /* Map Valid (read / write) */ -#define DRCMR_CHLNUM 0x1f /* mask for Channel Number (read / write) */ - -#define DDADR_DESCADDR 0xfffffff0 /* Address of next descriptor (mask) */ -#define DDADR_STOP (1 << 0) /* Stop (read / write) */ - -#define DCMD_INCSRCADDR (1 << 31) /* Source Address Increment Setting. */ -#define DCMD_INCTRGADDR (1 << 30) /* Target Address Increment Setting. */ -#define DCMD_FLOWSRC (1 << 29) /* Flow Control by the source. */ -#define DCMD_FLOWTRG (1 << 28) /* Flow Control by the target. */ -#define DCMD_STARTIRQEN (1 << 22) /* Start Interrupt Enable */ -#define DCMD_ENDIRQEN (1 << 21) /* End Interrupt Enable */ -#define DCMD_ENDIAN (1 << 18) /* Device Endian-ness. */ -#define DCMD_BURST8 (1 << 16) /* 8 byte burst */ -#define DCMD_BURST16 (2 << 16) /* 16 byte burst */ -#define DCMD_BURST32 (3 << 16) /* 32 byte burst */ -#define DCMD_WIDTH1 (1 << 14) /* 1 byte width */ -#define DCMD_WIDTH2 (2 << 14) /* 2 byte width (HalfWord) */ -#define DCMD_WIDTH4 (3 << 14) /* 4 byte width (Word) */ -#define DCMD_LENGTH 0x01fff /* length mask (max = 8K - 1) */ - -/* - * Descriptor structure for PXA's DMA engine - * Note: this structure must always be aligned to a 16-byte boundary. - */ - -typedef struct pxa_dma_desc { - volatile u32 ddadr; /* Points to the next descriptor + flags */ - volatile u32 dsadr; /* DSADR value for the current transfer */ - volatile u32 dtadr; /* DTADR value for the current transfer */ - volatile u32 dcmd; /* DCMD value for the current transfer */ -} pxa_dma_desc; - -typedef enum { - DMA_PRIO_HIGH = 0, - DMA_PRIO_MEDIUM = 1, - DMA_PRIO_LOW = 2 -} pxa_dma_prio; - -/* - * DMA registration - */ - -int __init pxa_init_dma(int irq, int num_ch); - -int pxa_request_dma (char *name, - pxa_dma_prio prio, - void (*irq_handler)(int, void *), - void *data); - -void pxa_free_dma (int dma_ch); +#include #endif /* _ASM_ARCH_DMA_H */ diff --git a/arch/arm/plat-pxa/Kconfig b/arch/arm/plat-pxa/Kconfig new file mode 100644 index 00000000000..b158e98038e --- /dev/null +++ b/arch/arm/plat-pxa/Kconfig @@ -0,0 +1,3 @@ +if PLAT_PXA + +endif diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile new file mode 100644 index 00000000000..dcc3ceaf717 --- /dev/null +++ b/arch/arm/plat-pxa/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for code common across different PXA processor families +# + +obj-y := dma.o + diff --git a/arch/arm/mach-pxa/dma.c b/arch/arm/plat-pxa/dma.c similarity index 97% rename from arch/arm/mach-pxa/dma.c rename to arch/arm/plat-pxa/dma.c index 01217e01f7d..70aeee407f7 100644 --- a/arch/arm/mach-pxa/dma.c +++ b/arch/arm/plat-pxa/dma.c @@ -1,5 +1,5 @@ /* - * linux/arch/arm/mach-pxa/dma.c + * linux/arch/arm/plat-pxa/dma.c * * PXA DMA registration and IRQ dispatching * @@ -34,8 +34,8 @@ static struct dma_channel *dma_channels; static int num_dma_channels; int pxa_request_dma (char *name, pxa_dma_prio prio, - void (*irq_handler)(int, void *), - void *data) + void (*irq_handler)(int, void *), + void *data) { unsigned long flags; int i, found = 0; diff --git a/arch/arm/plat-pxa/include/plat/dma.h b/arch/arm/plat-pxa/include/plat/dma.h new file mode 100644 index 00000000000..a7b91dc0685 --- /dev/null +++ b/arch/arm/plat-pxa/include/plat/dma.h @@ -0,0 +1,85 @@ +#ifndef __PLAT_DMA_H +#define __PLAT_DMA_H + +#define DMAC_REG(x) (*((volatile u32 *)(DMAC_REGS_VIRT + (x)))) + +#define DCSR(n) DMAC_REG((n) << 2) +#define DALGN DMAC_REG(0x00a0) /* DMA Alignment Register */ +#define DINT DMAC_REG(0x00f0) /* DMA Interrupt Register */ +#define DDADR(n) DMAC_REG(0x0200 + ((n) << 4)) +#define DSADR(n) DMAC_REG(0x0204 + ((n) << 4)) +#define DTADR(n) DMAC_REG(0x0208 + ((n) << 4)) +#define DCMD(n) DMAC_REG(0x020c + ((n) << 4)) +#define DRCMR(n) DMAC_REG((((n) < 64) ? 0x0100 : 0x1100) + \ + (((n) & 0x3f) << 2)) + +#define DCSR_RUN (1 << 31) /* Run Bit (read / write) */ +#define DCSR_NODESC (1 << 30) /* No-Descriptor Fetch (read / write) */ +#define DCSR_STOPIRQEN (1 << 29) /* Stop Interrupt Enable (read / write) */ +#define DCSR_REQPEND (1 << 8) /* Request Pending (read-only) */ +#define DCSR_STOPSTATE (1 << 3) /* Stop State (read-only) */ +#define DCSR_ENDINTR (1 << 2) /* End Interrupt (read / write) */ +#define DCSR_STARTINTR (1 << 1) /* Start Interrupt (read / write) */ +#define DCSR_BUSERR (1 << 0) /* Bus Error Interrupt (read / write) */ + +#define DCSR_EORIRQEN (1 << 28) /* End of Receive Interrupt Enable (R/W) */ +#define DCSR_EORJMPEN (1 << 27) /* Jump to next descriptor on EOR */ +#define DCSR_EORSTOPEN (1 << 26) /* STOP on an EOR */ +#define DCSR_SETCMPST (1 << 25) /* Set Descriptor Compare Status */ +#define DCSR_CLRCMPST (1 << 24) /* Clear Descriptor Compare Status */ +#define DCSR_CMPST (1 << 10) /* The Descriptor Compare Status */ +#define DCSR_EORINTR (1 << 9) /* The end of Receive */ + +#define DRCMR_MAPVLD (1 << 7) /* Map Valid (read / write) */ +#define DRCMR_CHLNUM 0x1f /* mask for Channel Number (read / write) */ + +#define DDADR_DESCADDR 0xfffffff0 /* Address of next descriptor (mask) */ +#define DDADR_STOP (1 << 0) /* Stop (read / write) */ + +#define DCMD_INCSRCADDR (1 << 31) /* Source Address Increment Setting. */ +#define DCMD_INCTRGADDR (1 << 30) /* Target Address Increment Setting. */ +#define DCMD_FLOWSRC (1 << 29) /* Flow Control by the source. */ +#define DCMD_FLOWTRG (1 << 28) /* Flow Control by the target. */ +#define DCMD_STARTIRQEN (1 << 22) /* Start Interrupt Enable */ +#define DCMD_ENDIRQEN (1 << 21) /* End Interrupt Enable */ +#define DCMD_ENDIAN (1 << 18) /* Device Endian-ness. */ +#define DCMD_BURST8 (1 << 16) /* 8 byte burst */ +#define DCMD_BURST16 (2 << 16) /* 16 byte burst */ +#define DCMD_BURST32 (3 << 16) /* 32 byte burst */ +#define DCMD_WIDTH1 (1 << 14) /* 1 byte width */ +#define DCMD_WIDTH2 (2 << 14) /* 2 byte width (HalfWord) */ +#define DCMD_WIDTH4 (3 << 14) /* 4 byte width (Word) */ +#define DCMD_LENGTH 0x01fff /* length mask (max = 8K - 1) */ + +/* + * Descriptor structure for PXA's DMA engine + * Note: this structure must always be aligned to a 16-byte boundary. + */ + +typedef struct pxa_dma_desc { + volatile u32 ddadr; /* Points to the next descriptor + flags */ + volatile u32 dsadr; /* DSADR value for the current transfer */ + volatile u32 dtadr; /* DTADR value for the current transfer */ + volatile u32 dcmd; /* DCMD value for the current transfer */ +} pxa_dma_desc; + +typedef enum { + DMA_PRIO_HIGH = 0, + DMA_PRIO_MEDIUM = 1, + DMA_PRIO_LOW = 2 +} pxa_dma_prio; + +/* + * DMA registration + */ + +int __init pxa_init_dma(int irq, int num_ch); + +int pxa_request_dma (char *name, + pxa_dma_prio prio, + void (*irq_handler)(int, void *), + void *data); + +void pxa_free_dma (int dma_ch); + +#endif /* __PLAT_DMA_H */ -- GitLab From 38f539a608c9a3b40b30f1892bd5f9a38f4e5ffe Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 20 Jan 2009 12:09:06 +0800 Subject: [PATCH 3910/4982] [ARM] pxa: move common GPIO handling code into plat-pxa 1. add common GPIO handling code into [arch/arm/plat-pxa] 2. common code in moved into , new processors should implement its own , provide the following required definitions and '#include ' in the end: - GPIO_REGS_VIRT for mapped virtual address of the GPIO registers' physical I/O memory - macros of GPLR(), GPSR(), GPDR() for constant optimization for functions gpio_{set,get}_value() (so that bit-bang code can still have tolerable performance) - NR_BUILTIN_GPIO for the number of onchip GPIO - definitions of __gpio_is_inverted() and __gpio_is_occupied(), they can be either macros or inlined functions Signed-off-by: Eric Miao --- arch/arm/mach-pxa/Makefile | 2 +- arch/arm/mach-pxa/include/mach/gpio.h | 32 +------------ arch/arm/plat-pxa/Makefile | 1 + arch/arm/{mach-pxa => plat-pxa}/gpio.c | 30 +------------ arch/arm/plat-pxa/include/plat/gpio.h | 62 ++++++++++++++++++++++++++ 5 files changed, 66 insertions(+), 61 deletions(-) rename arch/arm/{mach-pxa => plat-pxa}/gpio.c (89%) create mode 100644 arch/arm/plat-pxa/include/plat/gpio.h diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 70b46570c5c..c80e1bac494 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -4,7 +4,7 @@ # Common support (must be linked before board specific support) obj-y += clock.o devices.o generic.o irq.o \ - time.o gpio.o reset.o + time.o reset.o obj-$(CONFIG_PM) += pm.o sleep.o standby.o ifeq ($(CONFIG_CPU_FREQ),y) diff --git a/arch/arm/mach-pxa/include/mach/gpio.h b/arch/arm/mach-pxa/include/mach/gpio.h index c72c89a2285..b024a8b3743 100644 --- a/arch/arm/mach-pxa/include/mach/gpio.h +++ b/arch/arm/mach-pxa/include/mach/gpio.h @@ -99,40 +99,12 @@ #define GAFR(x) GPIO_REG(0x54 + (((x) & 0x70) >> 2)) -/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85). - * Those cases currently cause holes in the GPIO number space, the - * actual number of the last GPIO is recorded by 'pxa_last_gpio'. - */ -extern int pxa_last_gpio; - #define NR_BUILTIN_GPIO 128 -static inline int gpio_get_value(unsigned gpio) -{ - if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO)) - return GPLR(gpio) & GPIO_bit(gpio); - else - return __gpio_get_value(gpio); -} - -static inline void gpio_set_value(unsigned gpio, int value) -{ - if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO)) { - if (value) - GPSR(gpio) = GPIO_bit(gpio); - else - GPCR(gpio) = GPIO_bit(gpio); - } else { - __gpio_set_value(gpio, value); - } -} - -#define gpio_cansleep __gpio_cansleep #define gpio_to_bank(gpio) ((gpio) >> 5) #define gpio_to_irq(gpio) IRQ_GPIO(gpio) #define irq_to_gpio(irq) IRQ_TO_GPIO(irq) - #ifdef CONFIG_CPU_PXA26x /* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted, * as well as their Alternate Function value being '1' for GPIO in GAFRx. @@ -165,7 +137,5 @@ static inline int __gpio_is_occupied(unsigned gpio) return GPDR(gpio) & GPIO_bit(gpio); } -typedef int (*set_wake_t)(unsigned int irq, unsigned int on); - -extern void pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn); +#include #endif diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile index dcc3ceaf717..b837df44048 100644 --- a/arch/arm/plat-pxa/Makefile +++ b/arch/arm/plat-pxa/Makefile @@ -4,3 +4,4 @@ obj-y := dma.o +obj-$(CONFIG_GENERIC_GPIO) += gpio.o diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/plat-pxa/gpio.c similarity index 89% rename from arch/arm/mach-pxa/gpio.c rename to arch/arm/plat-pxa/gpio.c index 7c2267036bf..af819bf21b6 100644 --- a/arch/arm/mach-pxa/gpio.c +++ b/arch/arm/plat-pxa/gpio.c @@ -1,5 +1,5 @@ /* - * linux/arch/arm/mach-pxa/gpio.c + * linux/arch/arm/plat-pxa/gpio.c * * Generic PXA GPIO handling * @@ -22,34 +22,6 @@ int pxa_last_gpio; -/* - * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with - * one set of registers. The register offsets are organized below: - * - * GPLR GPDR GPSR GPCR GRER GFER GEDR - * BANK 0 - 0x0000 0x000C 0x0018 0x0024 0x0030 0x003C 0x0048 - * BANK 1 - 0x0004 0x0010 0x001C 0x0028 0x0034 0x0040 0x004C - * BANK 2 - 0x0008 0x0014 0x0020 0x002C 0x0038 0x0044 0x0050 - * - * BANK 3 - 0x0100 0x010C 0x0118 0x0124 0x0130 0x013C 0x0148 - * BANK 4 - 0x0104 0x0110 0x011C 0x0128 0x0134 0x0140 0x014C - * BANK 5 - 0x0108 0x0114 0x0120 0x012C 0x0138 0x0144 0x0150 - * - * NOTE: - * BANK 3 is only available on PXA27x and later processors. - * BANK 4 and 5 are only available on PXA935 - */ - -#define GPIO_BANK(n) (GPIO_REGS_VIRT + BANK_OFF(n)) - -#define GPLR_OFFSET 0x00 -#define GPDR_OFFSET 0x0C -#define GPSR_OFFSET 0x18 -#define GPCR_OFFSET 0x24 -#define GRER_OFFSET 0x30 -#define GFER_OFFSET 0x3C -#define GEDR_OFFSET 0x48 - struct pxa_gpio_chip { struct gpio_chip chip; void __iomem *regbase; diff --git a/arch/arm/plat-pxa/include/plat/gpio.h b/arch/arm/plat-pxa/include/plat/gpio.h new file mode 100644 index 00000000000..44248cb926a --- /dev/null +++ b/arch/arm/plat-pxa/include/plat/gpio.h @@ -0,0 +1,62 @@ +#ifndef __PLAT_GPIO_H +#define __PLAT_GPIO_H + +/* + * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with + * one set of registers. The register offsets are organized below: + * + * GPLR GPDR GPSR GPCR GRER GFER GEDR + * BANK 0 - 0x0000 0x000C 0x0018 0x0024 0x0030 0x003C 0x0048 + * BANK 1 - 0x0004 0x0010 0x001C 0x0028 0x0034 0x0040 0x004C + * BANK 2 - 0x0008 0x0014 0x0020 0x002C 0x0038 0x0044 0x0050 + * + * BANK 3 - 0x0100 0x010C 0x0118 0x0124 0x0130 0x013C 0x0148 + * BANK 4 - 0x0104 0x0110 0x011C 0x0128 0x0134 0x0140 0x014C + * BANK 5 - 0x0108 0x0114 0x0120 0x012C 0x0138 0x0144 0x0150 + * + * NOTE: + * BANK 3 is only available on PXA27x and later processors. + * BANK 4 and 5 are only available on PXA935 + */ + +#define GPIO_BANK(n) (GPIO_REGS_VIRT + BANK_OFF(n)) + +#define GPLR_OFFSET 0x00 +#define GPDR_OFFSET 0x0C +#define GPSR_OFFSET 0x18 +#define GPCR_OFFSET 0x24 +#define GRER_OFFSET 0x30 +#define GFER_OFFSET 0x3C +#define GEDR_OFFSET 0x48 + +static inline int gpio_get_value(unsigned gpio) +{ + if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO)) + return GPLR(gpio) & GPIO_bit(gpio); + else + return __gpio_get_value(gpio); +} + +static inline void gpio_set_value(unsigned gpio, int value) +{ + if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO)) { + if (value) + GPSR(gpio) = GPIO_bit(gpio); + else + GPCR(gpio) = GPIO_bit(gpio); + } else + __gpio_set_value(gpio, value); +} + +#define gpio_cansleep __gpio_cansleep + +/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85). + * Those cases currently cause holes in the GPIO number space, the + * actual number of the last GPIO is recorded by 'pxa_last_gpio'. + */ +extern int pxa_last_gpio; + +typedef int (*set_wake_t)(unsigned int irq, unsigned int on); + +extern void pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn); +#endif /* __PLAT_GPIO_H */ -- GitLab From f8dec04d33b94a4cfa9358fd9666c01480bb164d Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Thu, 15 Jan 2009 16:42:56 +0800 Subject: [PATCH 3911/4982] [ARM] pxa: move common MFP handling code into plat-pxa Signed-off-by: Eric Miao --- arch/arm/mach-pxa/include/mach/mfp-pxa25x.h | 1 - arch/arm/mach-pxa/include/mach/mfp-pxa27x.h | 1 - arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h | 2 +- arch/arm/mach-pxa/include/mach/mfp-pxa300.h | 1 - arch/arm/mach-pxa/include/mach/mfp-pxa320.h | 1 - arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h | 130 +------ arch/arm/mach-pxa/include/mach/mfp-pxa930.h | 1 - arch/arm/mach-pxa/mfp-pxa3xx.c | 189 +--------- arch/arm/mach-pxa/pxa300.c | 10 +- arch/arm/mach-pxa/pxa320.c | 6 +- arch/arm/mach-pxa/pxa930.c | 6 +- arch/arm/plat-pxa/Makefile | 2 +- arch/arm/plat-pxa/include/plat/mfp.h | 369 ++++++++++++++++++++ arch/arm/plat-pxa/mfp.c | 278 +++++++++++++++ 14 files changed, 680 insertions(+), 317 deletions(-) create mode 100644 arch/arm/plat-pxa/include/plat/mfp.h create mode 100644 arch/arm/plat-pxa/mfp.c diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h index a72869b73ee..b13dc0269a6 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h @@ -1,7 +1,6 @@ #ifndef __ASM_ARCH_MFP_PXA25X_H #define __ASM_ARCH_MFP_PXA25X_H -#include #include /* GPIO */ diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h index da4f85a4f99..6543c05f47e 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h @@ -8,7 +8,6 @@ * specific controller, and this should work in most cases. */ -#include #include /* Note: GPIO3/GPIO4 will be driven by Power I2C when PCFR/PI2C_EN diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h b/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h index 3e9211591e2..658b28ed129 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h @@ -1,7 +1,7 @@ #ifndef __ASM_ARCH_MFP_PXA2XX_H #define __ASM_ARCH_MFP_PXA2XX_H -#include +#include /* * the following MFP_xxx bit definitions in mfp.h are re-used for pxa2xx: diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa300.h b/arch/arm/mach-pxa/include/mach/mfp-pxa300.h index 928fbef9cbf..ae8441192ef 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa300.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa300.h @@ -15,7 +15,6 @@ #ifndef __ASM_ARCH_MFP_PXA300_H #define __ASM_ARCH_MFP_PXA300_H -#include #include /* GPIO */ diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa320.h b/arch/arm/mach-pxa/include/mach/mfp-pxa320.h index 80a0da9e092..07897e61d05 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa320.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa320.h @@ -15,7 +15,6 @@ #ifndef __ASM_ARCH_MFP_PXA320_H #define __ASM_ARCH_MFP_PXA320_H -#include #include /* GPIO */ diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h b/arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h index 1f6b35c015d..d375195d982 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h @@ -1,68 +1,9 @@ #ifndef __ASM_ARCH_MFP_PXA3XX_H #define __ASM_ARCH_MFP_PXA3XX_H -#define MFPR_BASE (0x40e10000) -#define MFPR_SIZE (PAGE_SIZE) - -/* MFPR register bit definitions */ -#define MFPR_PULL_SEL (0x1 << 15) -#define MFPR_PULLUP_EN (0x1 << 14) -#define MFPR_PULLDOWN_EN (0x1 << 13) -#define MFPR_SLEEP_SEL (0x1 << 9) -#define MFPR_SLEEP_OE_N (0x1 << 7) -#define MFPR_EDGE_CLEAR (0x1 << 6) -#define MFPR_EDGE_FALL_EN (0x1 << 5) -#define MFPR_EDGE_RISE_EN (0x1 << 4) - -#define MFPR_SLEEP_DATA(x) ((x) << 8) -#define MFPR_DRIVE(x) (((x) & 0x7) << 10) -#define MFPR_AF_SEL(x) (((x) & 0x7) << 0) +#include -#define MFPR_EDGE_NONE (0) -#define MFPR_EDGE_RISE (MFPR_EDGE_RISE_EN) -#define MFPR_EDGE_FALL (MFPR_EDGE_FALL_EN) -#define MFPR_EDGE_BOTH (MFPR_EDGE_RISE | MFPR_EDGE_FALL) - -/* - * Table that determines the low power modes outputs, with actual settings - * used in parentheses for don't-care values. Except for the float output, - * the configured driven and pulled levels match, so if there is a need for - * non-LPM pulled output, the same configuration could probably be used. - * - * Output value sleep_oe_n sleep_data pullup_en pulldown_en pull_sel - * (bit 7) (bit 8) (bit 14) (bit 13) (bit 15) - * - * Input 0 X(0) X(0) X(0) 0 - * Drive 0 0 0 0 X(1) 0 - * Drive 1 0 1 X(1) 0 0 - * Pull hi (1) 1 X(1) 1 0 0 - * Pull lo (0) 1 X(0) 0 1 0 - * Z (float) 1 X(0) 0 0 0 - */ -#define MFPR_LPM_INPUT (0) -#define MFPR_LPM_DRIVE_LOW (MFPR_SLEEP_DATA(0) | MFPR_PULLDOWN_EN) -#define MFPR_LPM_DRIVE_HIGH (MFPR_SLEEP_DATA(1) | MFPR_PULLUP_EN) -#define MFPR_LPM_PULL_LOW (MFPR_LPM_DRIVE_LOW | MFPR_SLEEP_OE_N) -#define MFPR_LPM_PULL_HIGH (MFPR_LPM_DRIVE_HIGH | MFPR_SLEEP_OE_N) -#define MFPR_LPM_FLOAT (MFPR_SLEEP_OE_N) -#define MFPR_LPM_MASK (0xe080) - -/* - * The pullup and pulldown state of the MFP pin at run mode is by default - * determined by the selected alternate function. In case that some buggy - * devices need to override this default behavior, the definitions below - * indicates the setting of corresponding MFPR bits - * - * Definition pull_sel pullup_en pulldown_en - * MFPR_PULL_NONE 0 0 0 - * MFPR_PULL_LOW 1 0 1 - * MFPR_PULL_HIGH 1 1 0 - * MFPR_PULL_BOTH 1 1 1 - */ -#define MFPR_PULL_NONE (0) -#define MFPR_PULL_LOW (MFPR_PULL_SEL | MFPR_PULLDOWN_EN) -#define MFPR_PULL_BOTH (MFPR_PULL_LOW | MFPR_PULLUP_EN) -#define MFPR_PULL_HIGH (MFPR_PULL_SEL | MFPR_PULLUP_EN) +#define MFPR_BASE (0x40e10000) /* PXA3xx common MFP configurations - processor specific ones defined * in mfp-pxa300.h and mfp-pxa320.h @@ -197,56 +138,21 @@ #define GPIO5_2_GPIO MFP_CFG(GPIO5_2, AF0) #define GPIO6_2_GPIO MFP_CFG(GPIO6_2, AF0) -/* - * each MFP pin will have a MFPR register, since the offset of the - * register varies between processors, the processor specific code - * should initialize the pin offsets by pxa3xx_mfp_init_addr() - * - * pxa3xx_mfp_init_addr - accepts a table of "pxa3xx_mfp_addr_map" - * structure, which represents a range of MFP pins from "start" to - * "end", with the offset begining at "offset", to define a single - * pin, let "end" = -1 - * - * use - * - * MFP_ADDR_X() to define a range of pins - * MFP_ADDR() to define a single pin - * MFP_ADDR_END to signal the end of pin offset definitions - */ -struct pxa3xx_mfp_addr_map { - unsigned int start; - unsigned int end; - unsigned long offset; -}; - -#define MFP_ADDR_X(start, end, offset) \ - { MFP_PIN_##start, MFP_PIN_##end, offset } - -#define MFP_ADDR(pin, offset) \ - { MFP_PIN_##pin, -1, offset } - -#define MFP_ADDR_END { MFP_PIN_INVALID, 0 } - -/* - * pxa3xx_mfp_read()/pxa3xx_mfp_write() - for direct read/write access - * to the MFPR register - */ -unsigned long pxa3xx_mfp_read(int mfp); -void pxa3xx_mfp_write(int mfp, unsigned long mfpr_val); - -/* - * pxa3xx_mfp_config - configure the MFPR registers - * - * used by board specific initialization code - */ -void pxa3xx_mfp_config(unsigned long *mfp_cfgs, int num); - -/* - * pxa3xx_mfp_init_addr() - initialize the mapping between mfp pin - * index and MFPR register offset - * - * used by processor specific code +/* NOTE: usage of these two functions is not recommended, + * use pxa3xx_mfp_config() instead. */ -void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *); -void __init pxa3xx_init_mfp(void); +static inline unsigned long pxa3xx_mfp_read(int mfp) +{ + return mfp_read(mfp); +} + +static inline void pxa3xx_mfp_write(int mfp, unsigned long val) +{ + mfp_write(mfp, val); +} + +static inline void pxa3xx_mfp_config(unsigned long *mfp_cfg, int num) +{ + mfp_config(mfp_cfg, num); +} #endif /* __ASM_ARCH_MFP_PXA3XX_H */ diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa930.h b/arch/arm/mach-pxa/include/mach/mfp-pxa930.h index fa73f56a137..0d119d3b922 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa930.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa930.h @@ -13,7 +13,6 @@ #ifndef __ASM_ARCH_MFP_PXA9xx_H #define __ASM_ARCH_MFP_PXA9xx_H -#include #include /* GPIO */ diff --git a/arch/arm/mach-pxa/mfp-pxa3xx.c b/arch/arm/mach-pxa/mfp-pxa3xx.c index eb197a6e8e9..7a270eecd48 100644 --- a/arch/arm/mach-pxa/mfp-pxa3xx.c +++ b/arch/arm/mach-pxa/mfp-pxa3xx.c @@ -20,183 +20,9 @@ #include #include -#include #include #include -/* mfp_spin_lock is used to ensure that MFP register configuration - * (most likely a read-modify-write operation) is atomic, and that - * mfp_table[] is consistent - */ -static DEFINE_SPINLOCK(mfp_spin_lock); - -static void __iomem *mfpr_mmio_base = (void __iomem *)&__REG(MFPR_BASE); - -struct pxa3xx_mfp_pin { - unsigned long config; /* -1 for not configured */ - unsigned long mfpr_off; /* MFPRxx Register offset */ - unsigned long mfpr_run; /* Run-Mode Register Value */ - unsigned long mfpr_lpm; /* Low Power Mode Register Value */ -}; - -static struct pxa3xx_mfp_pin mfp_table[MFP_PIN_MAX]; - -/* mapping of MFP_LPM_* definitions to MFPR_LPM_* register bits */ -static const unsigned long mfpr_lpm[] = { - MFPR_LPM_INPUT, - MFPR_LPM_DRIVE_LOW, - MFPR_LPM_DRIVE_HIGH, - MFPR_LPM_PULL_LOW, - MFPR_LPM_PULL_HIGH, - MFPR_LPM_FLOAT, -}; - -/* mapping of MFP_PULL_* definitions to MFPR_PULL_* register bits */ -static const unsigned long mfpr_pull[] = { - MFPR_PULL_NONE, - MFPR_PULL_LOW, - MFPR_PULL_HIGH, - MFPR_PULL_BOTH, -}; - -/* mapping of MFP_LPM_EDGE_* definitions to MFPR_EDGE_* register bits */ -static const unsigned long mfpr_edge[] = { - MFPR_EDGE_NONE, - MFPR_EDGE_RISE, - MFPR_EDGE_FALL, - MFPR_EDGE_BOTH, -}; - -#define mfpr_readl(off) \ - __raw_readl(mfpr_mmio_base + (off)) - -#define mfpr_writel(off, val) \ - __raw_writel(val, mfpr_mmio_base + (off)) - -#define mfp_configured(p) ((p)->config != -1) - -/* - * perform a read-back of any MFPR register to make sure the - * previous writings are finished - */ -#define mfpr_sync() (void)__raw_readl(mfpr_mmio_base + 0) - -static inline void __mfp_config_run(struct pxa3xx_mfp_pin *p) -{ - if (mfp_configured(p)) - mfpr_writel(p->mfpr_off, p->mfpr_run); -} - -static inline void __mfp_config_lpm(struct pxa3xx_mfp_pin *p) -{ - if (mfp_configured(p)) { - unsigned long mfpr_clr = (p->mfpr_run & ~MFPR_EDGE_BOTH) | MFPR_EDGE_CLEAR; - if (mfpr_clr != p->mfpr_run) - mfpr_writel(p->mfpr_off, mfpr_clr); - if (p->mfpr_lpm != mfpr_clr) - mfpr_writel(p->mfpr_off, p->mfpr_lpm); - } -} - -void pxa3xx_mfp_config(unsigned long *mfp_cfgs, int num) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&mfp_spin_lock, flags); - - for (i = 0; i < num; i++, mfp_cfgs++) { - unsigned long tmp, c = *mfp_cfgs; - struct pxa3xx_mfp_pin *p; - int pin, af, drv, lpm, edge, pull; - - pin = MFP_PIN(c); - BUG_ON(pin >= MFP_PIN_MAX); - p = &mfp_table[pin]; - - af = MFP_AF(c); - drv = MFP_DS(c); - lpm = MFP_LPM_STATE(c); - edge = MFP_LPM_EDGE(c); - pull = MFP_PULL(c); - - /* run-mode pull settings will conflict with MFPR bits of - * low power mode state, calculate mfpr_run and mfpr_lpm - * individually if pull != MFP_PULL_NONE - */ - tmp = MFPR_AF_SEL(af) | MFPR_DRIVE(drv); - - if (likely(pull == MFP_PULL_NONE)) { - p->mfpr_run = tmp | mfpr_lpm[lpm] | mfpr_edge[edge]; - p->mfpr_lpm = p->mfpr_run; - } else { - p->mfpr_lpm = tmp | mfpr_lpm[lpm] | mfpr_edge[edge]; - p->mfpr_run = tmp | mfpr_pull[pull]; - } - - p->config = c; __mfp_config_run(p); - } - - mfpr_sync(); - spin_unlock_irqrestore(&mfp_spin_lock, flags); -} - -unsigned long pxa3xx_mfp_read(int mfp) -{ - unsigned long val, flags; - - BUG_ON(mfp >= MFP_PIN_MAX); - - spin_lock_irqsave(&mfp_spin_lock, flags); - val = mfpr_readl(mfp_table[mfp].mfpr_off); - spin_unlock_irqrestore(&mfp_spin_lock, flags); - - return val; -} - -void pxa3xx_mfp_write(int mfp, unsigned long val) -{ - unsigned long flags; - - BUG_ON(mfp >= MFP_PIN_MAX); - - spin_lock_irqsave(&mfp_spin_lock, flags); - mfpr_writel(mfp_table[mfp].mfpr_off, val); - mfpr_sync(); - spin_unlock_irqrestore(&mfp_spin_lock, flags); -} - -void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *map) -{ - struct pxa3xx_mfp_addr_map *p; - unsigned long offset, flags; - int i; - - spin_lock_irqsave(&mfp_spin_lock, flags); - - for (p = map; p->start != MFP_PIN_INVALID; p++) { - offset = p->offset; - i = p->start; - - do { - mfp_table[i].mfpr_off = offset; - mfp_table[i].mfpr_run = 0; - mfp_table[i].mfpr_lpm = 0; - offset += 4; i++; - } while ((i <= p->end) && (p->end != -1)); - } - - spin_unlock_irqrestore(&mfp_spin_lock, flags); -} - -void __init pxa3xx_init_mfp(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(mfp_table); i++) - mfp_table[i].config = -1; -} - #ifdef CONFIG_PM /* * Configure the MFPs appropriately for suspend/resume. @@ -207,23 +33,13 @@ void __init pxa3xx_init_mfp(void) */ static int pxa3xx_mfp_suspend(struct sys_device *d, pm_message_t state) { - int pin; - - for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) { - struct pxa3xx_mfp_pin *p = &mfp_table[pin]; - __mfp_config_lpm(p); - } + mfp_config_lpm(); return 0; } static int pxa3xx_mfp_resume(struct sys_device *d) { - int pin; - - for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) { - struct pxa3xx_mfp_pin *p = &mfp_table[pin]; - __mfp_config_run(p); - } + mfp_config_run(); /* clear RDH bit when MFP settings are restored * @@ -231,7 +47,6 @@ static int pxa3xx_mfp_resume(struct sys_device *d) * preserve them here in case they will be referenced later */ ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S); - return 0; } #else diff --git a/arch/arm/mach-pxa/pxa300.c b/arch/arm/mach-pxa/pxa300.c index 37bb12d13ca..4ba6d21f851 100644 --- a/arch/arm/mach-pxa/pxa300.c +++ b/arch/arm/mach-pxa/pxa300.c @@ -23,7 +23,7 @@ #include "devices.h" #include "clock.h" -static struct pxa3xx_mfp_addr_map pxa300_mfp_addr_map[] __initdata = { +static struct mfp_addr_map pxa300_mfp_addr_map[] __initdata = { MFP_ADDR_X(GPIO0, GPIO2, 0x00b4), MFP_ADDR_X(GPIO3, GPIO26, 0x027c), @@ -72,7 +72,7 @@ static struct pxa3xx_mfp_addr_map pxa300_mfp_addr_map[] __initdata = { }; /* override pxa300 MFP register addresses */ -static struct pxa3xx_mfp_addr_map pxa310_mfp_addr_map[] __initdata = { +static struct mfp_addr_map pxa310_mfp_addr_map[] __initdata = { MFP_ADDR_X(GPIO30, GPIO98, 0x0418), MFP_ADDR_X(GPIO7_2, GPIO12_2, 0x052C), @@ -98,13 +98,13 @@ static struct clk_lookup pxa310_clkregs[] = { static int __init pxa300_init(void) { if (cpu_is_pxa300() || cpu_is_pxa310()) { - pxa3xx_init_mfp(); - pxa3xx_mfp_init_addr(pxa300_mfp_addr_map); + mfp_init_base(io_p2v(MFPR_BASE)); + mfp_init_addr(pxa300_mfp_addr_map); clks_register(ARRAY_AND_SIZE(common_clkregs)); } if (cpu_is_pxa310()) { - pxa3xx_mfp_init_addr(pxa310_mfp_addr_map); + mfp_init_addr(pxa310_mfp_addr_map); clks_register(ARRAY_AND_SIZE(pxa310_clkregs)); } diff --git a/arch/arm/mach-pxa/pxa320.c b/arch/arm/mach-pxa/pxa320.c index e708f4e0eca..8b3d97efada 100644 --- a/arch/arm/mach-pxa/pxa320.c +++ b/arch/arm/mach-pxa/pxa320.c @@ -23,7 +23,7 @@ #include "devices.h" #include "clock.h" -static struct pxa3xx_mfp_addr_map pxa320_mfp_addr_map[] __initdata = { +static struct mfp_addr_map pxa320_mfp_addr_map[] __initdata = { MFP_ADDR_X(GPIO0, GPIO4, 0x0124), MFP_ADDR_X(GPIO5, GPIO9, 0x028C), @@ -86,8 +86,8 @@ static struct clk_lookup pxa320_clkregs[] = { static int __init pxa320_init(void) { if (cpu_is_pxa320()) { - pxa3xx_init_mfp(); - pxa3xx_mfp_init_addr(pxa320_mfp_addr_map); + mfp_init_base(io_p2v(MFPR_BASE)); + mfp_init_addr(pxa320_mfp_addr_map); clks_register(ARRAY_AND_SIZE(pxa320_clkregs)); } diff --git a/arch/arm/mach-pxa/pxa930.c b/arch/arm/mach-pxa/pxa930.c index f15dfa55f27..71131742fff 100644 --- a/arch/arm/mach-pxa/pxa930.c +++ b/arch/arm/mach-pxa/pxa930.c @@ -18,7 +18,7 @@ #include -static struct pxa3xx_mfp_addr_map pxa930_mfp_addr_map[] __initdata = { +static struct mfp_addr_map pxa930_mfp_addr_map[] __initdata = { MFP_ADDR(GPIO0, 0x02e0), MFP_ADDR(GPIO1, 0x02dc), @@ -179,8 +179,8 @@ static struct pxa3xx_mfp_addr_map pxa930_mfp_addr_map[] __initdata = { static int __init pxa930_init(void) { if (cpu_is_pxa930()) { - pxa3xx_init_mfp(); - pxa3xx_mfp_init_addr(pxa930_mfp_addr_map); + mfp_init_base(io_p2v(MFPR_BASE)); + mfp_init_addr(pxa930_mfp_addr_map); } return 0; diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile index b837df44048..4be37235f57 100644 --- a/arch/arm/plat-pxa/Makefile +++ b/arch/arm/plat-pxa/Makefile @@ -2,6 +2,6 @@ # Makefile for code common across different PXA processor families # -obj-y := dma.o +obj-y := dma.o mfp.o obj-$(CONFIG_GENERIC_GPIO) += gpio.o diff --git a/arch/arm/plat-pxa/include/plat/mfp.h b/arch/arm/plat-pxa/include/plat/mfp.h new file mode 100644 index 00000000000..a22229cde09 --- /dev/null +++ b/arch/arm/plat-pxa/include/plat/mfp.h @@ -0,0 +1,369 @@ +/* + * arch/arm/plat-pxa/include/plat/mfp.h + * + * Common Multi-Function Pin Definitions + * + * Copyright (C) 2007 Marvell International Ltd. + * + * 2007-8-21: eric miao + * initial version + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_PLAT_MFP_H +#define __ASM_PLAT_MFP_H + +#define mfp_to_gpio(m) ((m) % 128) + +/* list of all the configurable MFP pins */ +enum { + MFP_PIN_INVALID = -1, + + MFP_PIN_GPIO0 = 0, + MFP_PIN_GPIO1, + MFP_PIN_GPIO2, + MFP_PIN_GPIO3, + MFP_PIN_GPIO4, + MFP_PIN_GPIO5, + MFP_PIN_GPIO6, + MFP_PIN_GPIO7, + MFP_PIN_GPIO8, + MFP_PIN_GPIO9, + MFP_PIN_GPIO10, + MFP_PIN_GPIO11, + MFP_PIN_GPIO12, + MFP_PIN_GPIO13, + MFP_PIN_GPIO14, + MFP_PIN_GPIO15, + MFP_PIN_GPIO16, + MFP_PIN_GPIO17, + MFP_PIN_GPIO18, + MFP_PIN_GPIO19, + MFP_PIN_GPIO20, + MFP_PIN_GPIO21, + MFP_PIN_GPIO22, + MFP_PIN_GPIO23, + MFP_PIN_GPIO24, + MFP_PIN_GPIO25, + MFP_PIN_GPIO26, + MFP_PIN_GPIO27, + MFP_PIN_GPIO28, + MFP_PIN_GPIO29, + MFP_PIN_GPIO30, + MFP_PIN_GPIO31, + MFP_PIN_GPIO32, + MFP_PIN_GPIO33, + MFP_PIN_GPIO34, + MFP_PIN_GPIO35, + MFP_PIN_GPIO36, + MFP_PIN_GPIO37, + MFP_PIN_GPIO38, + MFP_PIN_GPIO39, + MFP_PIN_GPIO40, + MFP_PIN_GPIO41, + MFP_PIN_GPIO42, + MFP_PIN_GPIO43, + MFP_PIN_GPIO44, + MFP_PIN_GPIO45, + MFP_PIN_GPIO46, + MFP_PIN_GPIO47, + MFP_PIN_GPIO48, + MFP_PIN_GPIO49, + MFP_PIN_GPIO50, + MFP_PIN_GPIO51, + MFP_PIN_GPIO52, + MFP_PIN_GPIO53, + MFP_PIN_GPIO54, + MFP_PIN_GPIO55, + MFP_PIN_GPIO56, + MFP_PIN_GPIO57, + MFP_PIN_GPIO58, + MFP_PIN_GPIO59, + MFP_PIN_GPIO60, + MFP_PIN_GPIO61, + MFP_PIN_GPIO62, + MFP_PIN_GPIO63, + MFP_PIN_GPIO64, + MFP_PIN_GPIO65, + MFP_PIN_GPIO66, + MFP_PIN_GPIO67, + MFP_PIN_GPIO68, + MFP_PIN_GPIO69, + MFP_PIN_GPIO70, + MFP_PIN_GPIO71, + MFP_PIN_GPIO72, + MFP_PIN_GPIO73, + MFP_PIN_GPIO74, + MFP_PIN_GPIO75, + MFP_PIN_GPIO76, + MFP_PIN_GPIO77, + MFP_PIN_GPIO78, + MFP_PIN_GPIO79, + MFP_PIN_GPIO80, + MFP_PIN_GPIO81, + MFP_PIN_GPIO82, + MFP_PIN_GPIO83, + MFP_PIN_GPIO84, + MFP_PIN_GPIO85, + MFP_PIN_GPIO86, + MFP_PIN_GPIO87, + MFP_PIN_GPIO88, + MFP_PIN_GPIO89, + MFP_PIN_GPIO90, + MFP_PIN_GPIO91, + MFP_PIN_GPIO92, + MFP_PIN_GPIO93, + MFP_PIN_GPIO94, + MFP_PIN_GPIO95, + MFP_PIN_GPIO96, + MFP_PIN_GPIO97, + MFP_PIN_GPIO98, + MFP_PIN_GPIO99, + MFP_PIN_GPIO100, + MFP_PIN_GPIO101, + MFP_PIN_GPIO102, + MFP_PIN_GPIO103, + MFP_PIN_GPIO104, + MFP_PIN_GPIO105, + MFP_PIN_GPIO106, + MFP_PIN_GPIO107, + MFP_PIN_GPIO108, + MFP_PIN_GPIO109, + MFP_PIN_GPIO110, + MFP_PIN_GPIO111, + MFP_PIN_GPIO112, + MFP_PIN_GPIO113, + MFP_PIN_GPIO114, + MFP_PIN_GPIO115, + MFP_PIN_GPIO116, + MFP_PIN_GPIO117, + MFP_PIN_GPIO118, + MFP_PIN_GPIO119, + MFP_PIN_GPIO120, + MFP_PIN_GPIO121, + MFP_PIN_GPIO122, + MFP_PIN_GPIO123, + MFP_PIN_GPIO124, + MFP_PIN_GPIO125, + MFP_PIN_GPIO126, + MFP_PIN_GPIO127, + MFP_PIN_GPIO0_2, + MFP_PIN_GPIO1_2, + MFP_PIN_GPIO2_2, + MFP_PIN_GPIO3_2, + MFP_PIN_GPIO4_2, + MFP_PIN_GPIO5_2, + MFP_PIN_GPIO6_2, + MFP_PIN_GPIO7_2, + MFP_PIN_GPIO8_2, + MFP_PIN_GPIO9_2, + MFP_PIN_GPIO10_2, + MFP_PIN_GPIO11_2, + MFP_PIN_GPIO12_2, + MFP_PIN_GPIO13_2, + MFP_PIN_GPIO14_2, + MFP_PIN_GPIO15_2, + MFP_PIN_GPIO16_2, + MFP_PIN_GPIO17_2, + + MFP_PIN_ULPI_STP, + MFP_PIN_ULPI_NXT, + MFP_PIN_ULPI_DIR, + + MFP_PIN_nXCVREN, + MFP_PIN_DF_CLE_nOE, + MFP_PIN_DF_nADV1_ALE, + MFP_PIN_DF_SCLK_E, + MFP_PIN_DF_SCLK_S, + MFP_PIN_nBE0, + MFP_PIN_nBE1, + MFP_PIN_DF_nADV2_ALE, + MFP_PIN_DF_INT_RnB, + MFP_PIN_DF_nCS0, + MFP_PIN_DF_nCS1, + MFP_PIN_nLUA, + MFP_PIN_nLLA, + MFP_PIN_DF_nWE, + MFP_PIN_DF_ALE_nWE, + MFP_PIN_DF_nRE_nOE, + MFP_PIN_DF_ADDR0, + MFP_PIN_DF_ADDR1, + MFP_PIN_DF_ADDR2, + MFP_PIN_DF_ADDR3, + MFP_PIN_DF_IO0, + MFP_PIN_DF_IO1, + MFP_PIN_DF_IO2, + MFP_PIN_DF_IO3, + MFP_PIN_DF_IO4, + MFP_PIN_DF_IO5, + MFP_PIN_DF_IO6, + MFP_PIN_DF_IO7, + MFP_PIN_DF_IO8, + MFP_PIN_DF_IO9, + MFP_PIN_DF_IO10, + MFP_PIN_DF_IO11, + MFP_PIN_DF_IO12, + MFP_PIN_DF_IO13, + MFP_PIN_DF_IO14, + MFP_PIN_DF_IO15, + + /* additional pins on PXA930 */ + MFP_PIN_GSIM_UIO, + MFP_PIN_GSIM_UCLK, + MFP_PIN_GSIM_UDET, + MFP_PIN_GSIM_nURST, + MFP_PIN_PMIC_INT, + MFP_PIN_RDY, + + MFP_PIN_MAX, +}; + +/* + * a possible MFP configuration is represented by a 32-bit integer + * + * bit 0.. 9 - MFP Pin Number (1024 Pins Maximum) + * bit 10..12 - Alternate Function Selection + * bit 13..15 - Drive Strength + * bit 16..18 - Low Power Mode State + * bit 19..20 - Low Power Mode Edge Detection + * bit 21..22 - Run Mode Pull State + * + * to facilitate the definition, the following macros are provided + * + * MFP_CFG_DEFAULT - default MFP configuration value, with + * alternate function = 0, + * drive strength = fast 3mA (MFP_DS03X) + * low power mode = default + * edge detection = none + * + * MFP_CFG - default MFPR value with alternate function + * MFP_CFG_DRV - default MFPR value with alternate function and + * pin drive strength + * MFP_CFG_LPM - default MFPR value with alternate function and + * low power mode + * MFP_CFG_X - default MFPR value with alternate function, + * pin drive strength and low power mode + */ + +typedef unsigned long mfp_cfg_t; + +#define MFP_PIN(x) ((x) & 0x3ff) + +#define MFP_AF0 (0x0 << 10) +#define MFP_AF1 (0x1 << 10) +#define MFP_AF2 (0x2 << 10) +#define MFP_AF3 (0x3 << 10) +#define MFP_AF4 (0x4 << 10) +#define MFP_AF5 (0x5 << 10) +#define MFP_AF6 (0x6 << 10) +#define MFP_AF7 (0x7 << 10) +#define MFP_AF_MASK (0x7 << 10) +#define MFP_AF(x) (((x) >> 10) & 0x7) + +#define MFP_DS01X (0x0 << 13) +#define MFP_DS02X (0x1 << 13) +#define MFP_DS03X (0x2 << 13) +#define MFP_DS04X (0x3 << 13) +#define MFP_DS06X (0x4 << 13) +#define MFP_DS08X (0x5 << 13) +#define MFP_DS10X (0x6 << 13) +#define MFP_DS13X (0x7 << 13) +#define MFP_DS_MASK (0x7 << 13) +#define MFP_DS(x) (((x) >> 13) & 0x7) + +#define MFP_LPM_DEFAULT (0x0 << 16) +#define MFP_LPM_DRIVE_LOW (0x1 << 16) +#define MFP_LPM_DRIVE_HIGH (0x2 << 16) +#define MFP_LPM_PULL_LOW (0x3 << 16) +#define MFP_LPM_PULL_HIGH (0x4 << 16) +#define MFP_LPM_FLOAT (0x5 << 16) +#define MFP_LPM_INPUT (0x6 << 16) +#define MFP_LPM_STATE_MASK (0x7 << 16) +#define MFP_LPM_STATE(x) (((x) >> 16) & 0x7) + +#define MFP_LPM_EDGE_NONE (0x0 << 19) +#define MFP_LPM_EDGE_RISE (0x1 << 19) +#define MFP_LPM_EDGE_FALL (0x2 << 19) +#define MFP_LPM_EDGE_BOTH (0x3 << 19) +#define MFP_LPM_EDGE_MASK (0x3 << 19) +#define MFP_LPM_EDGE(x) (((x) >> 19) & 0x3) + +#define MFP_PULL_NONE (0x0 << 21) +#define MFP_PULL_LOW (0x1 << 21) +#define MFP_PULL_HIGH (0x2 << 21) +#define MFP_PULL_BOTH (0x3 << 21) +#define MFP_PULL_MASK (0x3 << 21) +#define MFP_PULL(x) (((x) >> 21) & 0x3) + +#define MFP_CFG_DEFAULT (MFP_AF0 | MFP_DS03X | MFP_LPM_DEFAULT |\ + MFP_LPM_EDGE_NONE | MFP_PULL_NONE) + +#define MFP_CFG(pin, af) \ + ((MFP_CFG_DEFAULT & ~MFP_AF_MASK) |\ + (MFP_PIN(MFP_PIN_##pin) | MFP_##af)) + +#define MFP_CFG_DRV(pin, af, drv) \ + ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DS_MASK)) |\ + (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_##drv)) + +#define MFP_CFG_LPM(pin, af, lpm) \ + ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_LPM_STATE_MASK)) |\ + (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_LPM_##lpm)) + +#define MFP_CFG_X(pin, af, drv, lpm) \ + ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DS_MASK | MFP_LPM_STATE_MASK)) |\ + (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_##drv | MFP_LPM_##lpm)) + +#if defined(CONFIG_PXA3xx) || defined(CONFIG_ARCH_MMP) +/* + * each MFP pin will have a MFPR register, since the offset of the + * register varies between processors, the processor specific code + * should initialize the pin offsets by mfp_init() + * + * mfp_init_base() - accepts a virtual base for all MFPR registers and + * initialize the MFP table to a default state + * + * mfp_init_addr() - accepts a table of "mfp_addr_map" structure, which + * represents a range of MFP pins from "start" to "end", with the offset + * begining at "offset", to define a single pin, let "end" = -1. + * + * use + * + * MFP_ADDR_X() to define a range of pins + * MFP_ADDR() to define a single pin + * MFP_ADDR_END to signal the end of pin offset definitions + */ +struct mfp_addr_map { + unsigned int start; + unsigned int end; + unsigned long offset; +}; + +#define MFP_ADDR_X(start, end, offset) \ + { MFP_PIN_##start, MFP_PIN_##end, offset } + +#define MFP_ADDR(pin, offset) \ + { MFP_PIN_##pin, -1, offset } + +#define MFP_ADDR_END { MFP_PIN_INVALID, 0 } + +void __init mfp_init_base(unsigned long mfpr_base); +void __init mfp_init_addr(struct mfp_addr_map *map); + +/* + * mfp_{read, write}() - for direct read/write access to the MFPR register + * mfp_config() - for configuring a group of MFPR registers + * mfp_config_lpm() - configuring all low power MFPR registers for suspend + * mfp_config_run() - configuring all run time MFPR registers after resume + */ +unsigned long mfp_read(int mfp); +void mfp_write(int mfp, unsigned long mfpr_val); +void mfp_config(unsigned long *mfp_cfgs, int num); +void mfp_config_run(void); +void mfp_config_lpm(void); +#endif /* CONFIG_PXA3xx || CONFIG_ARCH_MMP */ + +#endif /* __ASM_PLAT_MFP_H */ diff --git a/arch/arm/plat-pxa/mfp.c b/arch/arm/plat-pxa/mfp.c new file mode 100644 index 00000000000..e716c622a17 --- /dev/null +++ b/arch/arm/plat-pxa/mfp.c @@ -0,0 +1,278 @@ +/* + * linux/arch/arm/plat-pxa/mfp.c + * + * Multi-Function Pin Support + * + * Copyright (C) 2007 Marvell Internation Ltd. + * + * 2007-08-21: eric miao + * initial version + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include + +#define MFPR_SIZE (PAGE_SIZE) + +/* MFPR register bit definitions */ +#define MFPR_PULL_SEL (0x1 << 15) +#define MFPR_PULLUP_EN (0x1 << 14) +#define MFPR_PULLDOWN_EN (0x1 << 13) +#define MFPR_SLEEP_SEL (0x1 << 9) +#define MFPR_SLEEP_OE_N (0x1 << 7) +#define MFPR_EDGE_CLEAR (0x1 << 6) +#define MFPR_EDGE_FALL_EN (0x1 << 5) +#define MFPR_EDGE_RISE_EN (0x1 << 4) + +#define MFPR_SLEEP_DATA(x) ((x) << 8) +#define MFPR_DRIVE(x) (((x) & 0x7) << 10) +#define MFPR_AF_SEL(x) (((x) & 0x7) << 0) + +#define MFPR_EDGE_NONE (0) +#define MFPR_EDGE_RISE (MFPR_EDGE_RISE_EN) +#define MFPR_EDGE_FALL (MFPR_EDGE_FALL_EN) +#define MFPR_EDGE_BOTH (MFPR_EDGE_RISE | MFPR_EDGE_FALL) + +/* + * Table that determines the low power modes outputs, with actual settings + * used in parentheses for don't-care values. Except for the float output, + * the configured driven and pulled levels match, so if there is a need for + * non-LPM pulled output, the same configuration could probably be used. + * + * Output value sleep_oe_n sleep_data pullup_en pulldown_en pull_sel + * (bit 7) (bit 8) (bit 14) (bit 13) (bit 15) + * + * Input 0 X(0) X(0) X(0) 0 + * Drive 0 0 0 0 X(1) 0 + * Drive 1 0 1 X(1) 0 0 + * Pull hi (1) 1 X(1) 1 0 0 + * Pull lo (0) 1 X(0) 0 1 0 + * Z (float) 1 X(0) 0 0 0 + */ +#define MFPR_LPM_INPUT (0) +#define MFPR_LPM_DRIVE_LOW (MFPR_SLEEP_DATA(0) | MFPR_PULLDOWN_EN) +#define MFPR_LPM_DRIVE_HIGH (MFPR_SLEEP_DATA(1) | MFPR_PULLUP_EN) +#define MFPR_LPM_PULL_LOW (MFPR_LPM_DRIVE_LOW | MFPR_SLEEP_OE_N) +#define MFPR_LPM_PULL_HIGH (MFPR_LPM_DRIVE_HIGH | MFPR_SLEEP_OE_N) +#define MFPR_LPM_FLOAT (MFPR_SLEEP_OE_N) +#define MFPR_LPM_MASK (0xe080) + +/* + * The pullup and pulldown state of the MFP pin at run mode is by default + * determined by the selected alternate function. In case that some buggy + * devices need to override this default behavior, the definitions below + * indicates the setting of corresponding MFPR bits + * + * Definition pull_sel pullup_en pulldown_en + * MFPR_PULL_NONE 0 0 0 + * MFPR_PULL_LOW 1 0 1 + * MFPR_PULL_HIGH 1 1 0 + * MFPR_PULL_BOTH 1 1 1 + */ +#define MFPR_PULL_NONE (0) +#define MFPR_PULL_LOW (MFPR_PULL_SEL | MFPR_PULLDOWN_EN) +#define MFPR_PULL_BOTH (MFPR_PULL_LOW | MFPR_PULLUP_EN) +#define MFPR_PULL_HIGH (MFPR_PULL_SEL | MFPR_PULLUP_EN) + +/* mfp_spin_lock is used to ensure that MFP register configuration + * (most likely a read-modify-write operation) is atomic, and that + * mfp_table[] is consistent + */ +static DEFINE_SPINLOCK(mfp_spin_lock); + +static void __iomem *mfpr_mmio_base; + +struct mfp_pin { + unsigned long config; /* -1 for not configured */ + unsigned long mfpr_off; /* MFPRxx Register offset */ + unsigned long mfpr_run; /* Run-Mode Register Value */ + unsigned long mfpr_lpm; /* Low Power Mode Register Value */ +}; + +static struct mfp_pin mfp_table[MFP_PIN_MAX]; + +/* mapping of MFP_LPM_* definitions to MFPR_LPM_* register bits */ +static const unsigned long mfpr_lpm[] = { + MFPR_LPM_INPUT, + MFPR_LPM_DRIVE_LOW, + MFPR_LPM_DRIVE_HIGH, + MFPR_LPM_PULL_LOW, + MFPR_LPM_PULL_HIGH, + MFPR_LPM_FLOAT, +}; + +/* mapping of MFP_PULL_* definitions to MFPR_PULL_* register bits */ +static const unsigned long mfpr_pull[] = { + MFPR_PULL_NONE, + MFPR_PULL_LOW, + MFPR_PULL_HIGH, + MFPR_PULL_BOTH, +}; + +/* mapping of MFP_LPM_EDGE_* definitions to MFPR_EDGE_* register bits */ +static const unsigned long mfpr_edge[] = { + MFPR_EDGE_NONE, + MFPR_EDGE_RISE, + MFPR_EDGE_FALL, + MFPR_EDGE_BOTH, +}; + +#define mfpr_readl(off) \ + __raw_readl(mfpr_mmio_base + (off)) + +#define mfpr_writel(off, val) \ + __raw_writel(val, mfpr_mmio_base + (off)) + +#define mfp_configured(p) ((p)->config != -1) + +/* + * perform a read-back of any MFPR register to make sure the + * previous writings are finished + */ +#define mfpr_sync() (void)__raw_readl(mfpr_mmio_base + 0) + +static inline void __mfp_config_run(struct mfp_pin *p) +{ + if (mfp_configured(p)) + mfpr_writel(p->mfpr_off, p->mfpr_run); +} + +static inline void __mfp_config_lpm(struct mfp_pin *p) +{ + if (mfp_configured(p)) { + unsigned long mfpr_clr = (p->mfpr_run & ~MFPR_EDGE_BOTH) | MFPR_EDGE_CLEAR; + if (mfpr_clr != p->mfpr_run) + mfpr_writel(p->mfpr_off, mfpr_clr); + if (p->mfpr_lpm != mfpr_clr) + mfpr_writel(p->mfpr_off, p->mfpr_lpm); + } +} + +void mfp_config(unsigned long *mfp_cfgs, int num) +{ + unsigned long flags; + int i; + + spin_lock_irqsave(&mfp_spin_lock, flags); + + for (i = 0; i < num; i++, mfp_cfgs++) { + unsigned long tmp, c = *mfp_cfgs; + struct mfp_pin *p; + int pin, af, drv, lpm, edge, pull; + + pin = MFP_PIN(c); + BUG_ON(pin >= MFP_PIN_MAX); + p = &mfp_table[pin]; + + af = MFP_AF(c); + drv = MFP_DS(c); + lpm = MFP_LPM_STATE(c); + edge = MFP_LPM_EDGE(c); + pull = MFP_PULL(c); + + /* run-mode pull settings will conflict with MFPR bits of + * low power mode state, calculate mfpr_run and mfpr_lpm + * individually if pull != MFP_PULL_NONE + */ + tmp = MFPR_AF_SEL(af) | MFPR_DRIVE(drv); + + if (likely(pull == MFP_PULL_NONE)) { + p->mfpr_run = tmp | mfpr_lpm[lpm] | mfpr_edge[edge]; + p->mfpr_lpm = p->mfpr_run; + } else { + p->mfpr_lpm = tmp | mfpr_lpm[lpm] | mfpr_edge[edge]; + p->mfpr_run = tmp | mfpr_pull[pull]; + } + + p->config = c; __mfp_config_run(p); + } + + mfpr_sync(); + spin_unlock_irqrestore(&mfp_spin_lock, flags); +} + +unsigned long mfp_read(int mfp) +{ + unsigned long val, flags; + + BUG_ON(mfp >= MFP_PIN_MAX); + + spin_lock_irqsave(&mfp_spin_lock, flags); + val = mfpr_readl(mfp_table[mfp].mfpr_off); + spin_unlock_irqrestore(&mfp_spin_lock, flags); + + return val; +} + +void mfp_write(int mfp, unsigned long val) +{ + unsigned long flags; + + BUG_ON(mfp >= MFP_PIN_MAX); + + spin_lock_irqsave(&mfp_spin_lock, flags); + mfpr_writel(mfp_table[mfp].mfpr_off, val); + mfpr_sync(); + spin_unlock_irqrestore(&mfp_spin_lock, flags); +} + +void __init mfp_init_base(unsigned long mfpr_base) +{ + int i; + + /* initialize the table with default - unconfigured */ + for (i = 0; i < ARRAY_SIZE(mfp_table); i++) + mfp_table[i].config = -1; + + mfpr_mmio_base = (void __iomem *)mfpr_base; +} + +void __init mfp_init_addr(struct mfp_addr_map *map) +{ + struct mfp_addr_map *p; + unsigned long offset, flags; + int i; + + spin_lock_irqsave(&mfp_spin_lock, flags); + + for (p = map; p->start != MFP_PIN_INVALID; p++) { + offset = p->offset; + i = p->start; + + do { + mfp_table[i].mfpr_off = offset; + mfp_table[i].mfpr_run = 0; + mfp_table[i].mfpr_lpm = 0; + offset += 4; i++; + } while ((i <= p->end) && (p->end != -1)); + } + + spin_unlock_irqrestore(&mfp_spin_lock, flags); +} + +void mfp_config_lpm(void) +{ + struct mfp_pin *p = &mfp_table[0]; + int pin; + + for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++, p++) + __mfp_config_lpm(p); +} + +void mfp_config_run(void) +{ + struct mfp_pin *p = &mfp_table[0]; + int pin; + + for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++, p++) + __mfp_config_run(p); +} -- GitLab From 49cbe78637eb0503f45fc9b556ec08918a616534 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 20 Jan 2009 14:15:18 +0800 Subject: [PATCH 3912/4982] [ARM] pxa: add base support for Marvell's PXA168 processor line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit """The Marvell® PXA168 processor is the first in a family of application processors targeted at mass market opportunities in computing and consumer devices. It balances high computing and multimedia performance with low power consumption to support extended battery life, and includes a wealth of integrated peripherals to reduce overall BOM cost .... """ See http://www.marvell.com/featured/pxa168.jsp for more information. 1. Marvell Mohawk core is a hybrid of xscale3 and its own ARM core, there are many enhancements like instructions for flushing the whole D-cache, and so on 2. Clock reuses Russell's common clkdev, and added the basic support for UART1/2. 3. Devices are a bit different from the 'mach-pxa' way, the platform devices are now dynamically allocated only when necessary (i.e. when pxa_register_device() is called). Description for each device are stored in an array of 'struct pxa_device_desc'. Now that: a. this array of device description is marked with __initdata and can be freed up system is fully up b. which means board code has to add all needed devices early in his initializing function c. platform specific data can now be marked as __initdata since they are allocated and copied by platform_device_add_data() 4. only the basic UART1/2/3 are added, more devices will come later. Signed-off-by: Jason Chagas Signed-off-by: Eric Miao --- arch/arm/Kconfig | 16 + arch/arm/Makefile | 1 + arch/arm/boot/compressed/head.S | 12 + arch/arm/include/asm/cacheflush.h | 8 + arch/arm/include/asm/proc-fns.h | 8 + arch/arm/mach-mmp/Kconfig | 27 ++ arch/arm/mach-mmp/Makefile | 12 + arch/arm/mach-mmp/Makefile.boot | 1 + arch/arm/mach-mmp/aspenite.c | 42 ++ arch/arm/mach-mmp/clock.c | 83 ++++ arch/arm/mach-mmp/clock.h | 71 ++++ arch/arm/mach-mmp/common.c | 37 ++ arch/arm/mach-mmp/common.h | 11 + arch/arm/mach-mmp/devices.c | 69 +++ arch/arm/mach-mmp/include/mach/addr-map.h | 34 ++ arch/arm/mach-mmp/include/mach/clkdev.h | 7 + arch/arm/mach-mmp/include/mach/cputype.h | 21 + arch/arm/mach-mmp/include/mach/debug-macro.S | 23 + arch/arm/mach-mmp/include/mach/devices.h | 27 ++ arch/arm/mach-mmp/include/mach/dma.h | 13 + arch/arm/mach-mmp/include/mach/entry-macro.S | 25 ++ arch/arm/mach-mmp/include/mach/hardware.h | 4 + arch/arm/mach-mmp/include/mach/io.h | 21 + arch/arm/mach-mmp/include/mach/irqs.h | 58 +++ arch/arm/mach-mmp/include/mach/memory.h | 14 + arch/arm/mach-mmp/include/mach/pxa168.h | 23 + arch/arm/mach-mmp/include/mach/regs-apbc.h | 53 +++ arch/arm/mach-mmp/include/mach/regs-apmu.h | 36 ++ arch/arm/mach-mmp/include/mach/regs-icu.h | 31 ++ arch/arm/mach-mmp/include/mach/regs-timers.h | 44 ++ arch/arm/mach-mmp/include/mach/system.h | 21 + arch/arm/mach-mmp/include/mach/timex.h | 9 + arch/arm/mach-mmp/include/mach/uncompress.h | 41 ++ arch/arm/mach-mmp/include/mach/vmalloc.h | 5 + arch/arm/mach-mmp/irq.c | 55 +++ arch/arm/mach-mmp/pxa168.c | 77 ++++ arch/arm/mach-mmp/time.c | 199 +++++++++ arch/arm/mm/Kconfig | 15 +- arch/arm/mm/Makefile | 1 + arch/arm/mm/proc-mohawk.S | 416 +++++++++++++++++++ 40 files changed, 1669 insertions(+), 2 deletions(-) create mode 100644 arch/arm/mach-mmp/Kconfig create mode 100644 arch/arm/mach-mmp/Makefile create mode 100644 arch/arm/mach-mmp/Makefile.boot create mode 100644 arch/arm/mach-mmp/aspenite.c create mode 100644 arch/arm/mach-mmp/clock.c create mode 100644 arch/arm/mach-mmp/clock.h create mode 100644 arch/arm/mach-mmp/common.c create mode 100644 arch/arm/mach-mmp/common.h create mode 100644 arch/arm/mach-mmp/devices.c create mode 100644 arch/arm/mach-mmp/include/mach/addr-map.h create mode 100644 arch/arm/mach-mmp/include/mach/clkdev.h create mode 100644 arch/arm/mach-mmp/include/mach/cputype.h create mode 100644 arch/arm/mach-mmp/include/mach/debug-macro.S create mode 100644 arch/arm/mach-mmp/include/mach/devices.h create mode 100644 arch/arm/mach-mmp/include/mach/dma.h create mode 100644 arch/arm/mach-mmp/include/mach/entry-macro.S create mode 100644 arch/arm/mach-mmp/include/mach/hardware.h create mode 100644 arch/arm/mach-mmp/include/mach/io.h create mode 100644 arch/arm/mach-mmp/include/mach/irqs.h create mode 100644 arch/arm/mach-mmp/include/mach/memory.h create mode 100644 arch/arm/mach-mmp/include/mach/pxa168.h create mode 100644 arch/arm/mach-mmp/include/mach/regs-apbc.h create mode 100644 arch/arm/mach-mmp/include/mach/regs-apmu.h create mode 100644 arch/arm/mach-mmp/include/mach/regs-icu.h create mode 100644 arch/arm/mach-mmp/include/mach/regs-timers.h create mode 100644 arch/arm/mach-mmp/include/mach/system.h create mode 100644 arch/arm/mach-mmp/include/mach/timex.h create mode 100644 arch/arm/mach-mmp/include/mach/uncompress.h create mode 100644 arch/arm/mach-mmp/include/mach/vmalloc.h create mode 100644 arch/arm/mach-mmp/irq.c create mode 100644 arch/arm/mach-mmp/pxa168.c create mode 100644 arch/arm/mach-mmp/time.c create mode 100644 arch/arm/mm/proc-mohawk.S diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 5ba00358e80..fdcd2d54e93 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -478,6 +478,8 @@ config ARCH_PXA select HAVE_CLK select COMMON_CLKDEV select ARCH_REQUIRE_GPIOLIB + select HAVE_CLK + select COMMON_CLKDEV select GENERIC_TIME select GENERIC_CLOCKEVENTS select TICK_ONESHOT @@ -485,6 +487,18 @@ config ARCH_PXA help Support for Intel/Marvell's PXA2xx/PXA3xx processor line. +config ARCH_MMP + bool "Marvell PXA168" + depends on MMU + select HAVE_CLK + select COMMON_CLKDEV + select GENERIC_TIME + select GENERIC_CLOCKEVENTS + select TICK_ONESHOT + select PLAT_PXA + help + Support for Marvell's PXA168 processor line. + config ARCH_RPC bool "RiscPC" select ARCH_ACORN @@ -621,6 +635,8 @@ source "arch/arm/mach-mv78xx0/Kconfig" source "arch/arm/mach-pxa/Kconfig" source "arch/arm/plat-pxa/Kconfig" +source "arch/arm/mach-mmp/Kconfig" + source "arch/arm/mach-sa1100/Kconfig" source "arch/arm/plat-omap/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 897f2830bc4..95186ef17e1 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -109,6 +109,7 @@ ifeq ($(CONFIG_ARCH_SA1100),y) textofs-$(CONFIG_SA1111) := 0x00208000 endif machine-$(CONFIG_ARCH_PXA) := pxa + machine-$(CONFIG_ARCH_MMP) := mmp plat-$(CONFIG_PLAT_PXA) := pxa machine-$(CONFIG_ARCH_L7200) := l7200 machine-$(CONFIG_ARCH_INTEGRATOR) := integrator diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index d1b678dc120..d14b827adcd 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -636,6 +636,18 @@ proc_types: b __armv4_mmu_cache_off b __armv4_mmu_cache_flush + .word 0x56158000 @ PXA168 + .word 0xfffff000 + b __armv4_mmu_cache_on + b __armv4_mmu_cache_off + b __armv5tej_mmu_cache_flush + + .word 0x56056930 + .word 0xff0ffff0 @ PXA935 + b __armv4_mmu_cache_on + b __armv4_mmu_cache_off + b __armv4_mmu_cache_flush + .word 0x56050000 @ Feroceon .word 0xff0f0000 b __armv4_mmu_cache_on diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index 6cbd8fdc9f1..bfb0cb9aaa9 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -94,6 +94,14 @@ # endif #endif +#if defined(CONFIG_CPU_MOHAWK) +# ifdef _CACHE +# define MULTI_CACHE 1 +# else +# define _CACHE mohawk +# endif +#endif + #if defined(CONFIG_CPU_FEROCEON) # define MULTI_CACHE 1 #endif diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h index db80203b68e..c6250311550 100644 --- a/arch/arm/include/asm/proc-fns.h +++ b/arch/arm/include/asm/proc-fns.h @@ -185,6 +185,14 @@ # define CPU_NAME cpu_xsc3 # endif # endif +# ifdef CONFIG_CPU_MOHAWK +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_mohawk +# endif +# endif # ifdef CONFIG_CPU_FEROCEON # ifdef CPU_NAME # undef MULTI_CPU diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig new file mode 100644 index 00000000000..b5232676355 --- /dev/null +++ b/arch/arm/mach-mmp/Kconfig @@ -0,0 +1,27 @@ +if ARCH_MMP + +menu "Marvell PXA168 Implmentations" + +config MACH_ASPENITE + bool "Marvell's PXA168 Aspenite Development Board" + select CPU_PXA168 + help + Say 'Y' here if you want to support the Marvell PXA168-based + Aspenite Development Board. + +config MACH_ZYLONITE2 + bool "Marvell's PXA168 Zylonite2 Development Board" + select CPU_PXA168 + help + Say 'Y' here if you want to support the Marvell PXA168-based + Zylonite2 Development Board. + +endmenu + +config CPU_PXA168 + bool + select CPU_MOHAWK + help + Select code specific to PXA168 + +endif diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile new file mode 100644 index 00000000000..0ac7644ec99 --- /dev/null +++ b/arch/arm/mach-mmp/Makefile @@ -0,0 +1,12 @@ +# +# Makefile for Marvell's PXA168 processors line +# + +obj-y += common.o clock.o devices.o irq.o time.o + +# SoC support +obj-$(CONFIG_CPU_PXA168) += pxa168.o + +# board support +obj-$(CONFIG_MACH_ASPENITE) += aspenite.o +obj-$(CONFIG_MACH_ZYLONITE2) += aspenite.o diff --git a/arch/arm/mach-mmp/Makefile.boot b/arch/arm/mach-mmp/Makefile.boot new file mode 100644 index 00000000000..574a4aa8321 --- /dev/null +++ b/arch/arm/mach-mmp/Makefile.boot @@ -0,0 +1 @@ + zreladdr-y := 0x00008000 diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c new file mode 100644 index 00000000000..e8caf58e004 --- /dev/null +++ b/arch/arm/mach-mmp/aspenite.c @@ -0,0 +1,42 @@ +/* + * linux/arch/arm/mach-mmp/aspenite.c + * + * Support for the Marvell PXA168-based Aspenite and Zylonite2 + * Development Platform. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * publishhed by the Free Software Foundation. + */ + +#include + +#include +#include +#include + +#include "common.h" + +static void __init common_init(void) +{ +} + +MACHINE_START(ASPENITE, "PXA168-based Aspenite Development Platform") + .phys_io = APB_PHYS_BASE, + .boot_params = 0x00000100, + .io_pg_offst = (APB_VIRT_BASE >> 18) & 0xfffc, + .map_io = pxa_map_io, + .init_irq = pxa168_init_irq, + .timer = &pxa168_timer, + .init_machine = common_init, +MACHINE_END + +MACHINE_START(ZYLONITE2, "PXA168-based Zylonite2 Development Platform") + .phys_io = APB_PHYS_BASE, + .boot_params = 0x00000100, + .io_pg_offst = (APB_VIRT_BASE >> 18) & 0xfffc, + .map_io = pxa_map_io, + .init_irq = pxa168_init_irq, + .timer = &pxa168_timer, + .init_machine = common_init, +MACHINE_END diff --git a/arch/arm/mach-mmp/clock.c b/arch/arm/mach-mmp/clock.c new file mode 100644 index 00000000000..2d9cc5a7122 --- /dev/null +++ b/arch/arm/mach-mmp/clock.c @@ -0,0 +1,83 @@ +/* + * linux/arch/arm/mach-mmp/clock.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include "clock.h" + +static void apbc_clk_enable(struct clk *clk) +{ + uint32_t clk_rst; + + clk_rst = APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(clk->fnclksel); + __raw_writel(clk_rst, clk->clk_rst); +} + +static void apbc_clk_disable(struct clk *clk) +{ + __raw_writel(0, clk->clk_rst); +} + +struct clkops apbc_clk_ops = { + .enable = apbc_clk_enable, + .disable = apbc_clk_disable, +}; + +static DEFINE_SPINLOCK(clocks_lock); + +int clk_enable(struct clk *clk) +{ + unsigned long flags; + + spin_lock_irqsave(&clocks_lock, flags); + if (clk->enabled++ == 0) + clk->ops->enable(clk); + spin_unlock_irqrestore(&clocks_lock, flags); + return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ + unsigned long flags; + + WARN_ON(clk->enabled == 0); + + spin_lock_irqsave(&clocks_lock, flags); + if (--clk->enabled == 0) + clk->ops->disable(clk); + spin_unlock_irqrestore(&clocks_lock, flags); +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + unsigned long rate; + + if (clk->ops->getrate) + rate = clk->ops->getrate(clk); + else + rate = clk->rate; + + return rate; +} +EXPORT_SYMBOL(clk_get_rate); + +void clks_register(struct clk_lookup *clks, size_t num) +{ + int i; + + for (i = 0; i < num; i++) + clkdev_add(&clks[i]); +} diff --git a/arch/arm/mach-mmp/clock.h b/arch/arm/mach-mmp/clock.h new file mode 100644 index 00000000000..ed967e78e6a --- /dev/null +++ b/arch/arm/mach-mmp/clock.h @@ -0,0 +1,71 @@ +/* + * linux/arch/arm/mach-mmp/clock.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include + +struct clkops { + void (*enable)(struct clk *); + void (*disable)(struct clk *); + unsigned long (*getrate)(struct clk *); +}; + +struct clk { + const struct clkops *ops; + + void __iomem *clk_rst; /* clock reset control register */ + int fnclksel; /* functional clock select (APBC) */ + uint32_t enable_val; /* value for clock enable (APMU) */ + unsigned long rate; + int enabled; +}; + +extern struct clkops apbc_clk_ops; + +#define APBC_CLK(_name, _reg, _fnclksel, _rate) \ +struct clk clk_##_name = { \ + .clk_rst = (void __iomem *)APBC_##_reg, \ + .fnclksel = _fnclksel, \ + .rate = _rate, \ + .ops = &apbc_clk_ops, \ +} + +#define APBC_CLK_OPS(_name, _reg, _fnclksel, _rate, _ops) \ +struct clk clk_##_name = { \ + .clk_rst = (void __iomem *)APBC_##_reg, \ + .fnclksel = _fnclksel, \ + .rate = _rate, \ + .ops = _ops, \ +} + +#define APMU_CLK(_name, _reg, _eval, _rate) \ +struct clk clk_##_name = { \ + .clk_rst = (void __iomem *)APMU_##_reg, \ + .enable_val = _eval, \ + .rate = _rate, \ + .ops = &apmu_clk_ops, \ +} + +#define APMU_CLK_OPS(_name, _reg, _eval, _rate, _ops) \ +struct clk clk_##_name = { \ + .clk_rst = (void __iomem *)APMU_##_reg, \ + .enable_val = _eval, \ + .rate = _rate, \ + .ops = _ops, \ +} + +#define INIT_CLKREG(_clk, _devname, _conname) \ + { \ + .clk = _clk, \ + .dev_id = _devname, \ + .con_id = _conname, \ + } + +extern struct clk clk_pxa168_gpio; +extern struct clk clk_pxa168_timers; + +extern void clks_register(struct clk_lookup *, size_t); diff --git a/arch/arm/mach-mmp/common.c b/arch/arm/mach-mmp/common.c new file mode 100644 index 00000000000..e1e66c18b44 --- /dev/null +++ b/arch/arm/mach-mmp/common.c @@ -0,0 +1,37 @@ +/* + * linux/arch/arm/mach-mmp/common.c + * + * Code common to PXA168 processor lines + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include + +#include +#include +#include + +#include "common.h" + +static struct map_desc standard_io_desc[] __initdata = { + { + .pfn = __phys_to_pfn(APB_PHYS_BASE), + .virtual = APB_VIRT_BASE, + .length = APB_PHYS_SIZE, + .type = MT_DEVICE, + }, { + .pfn = __phys_to_pfn(AXI_PHYS_BASE), + .virtual = AXI_VIRT_BASE, + .length = AXI_PHYS_SIZE, + .type = MT_DEVICE, + }, +}; + +void __init pxa_map_io(void) +{ + iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc)); +} diff --git a/arch/arm/mach-mmp/common.h b/arch/arm/mach-mmp/common.h new file mode 100644 index 00000000000..bf7a6a492de --- /dev/null +++ b/arch/arm/mach-mmp/common.h @@ -0,0 +1,11 @@ +#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x) + +struct sys_timer; + +extern void timer_init(int irq); + +extern struct sys_timer pxa168_timer; +extern void __init pxa168_init_irq(void); + +extern void __init icu_init_irq(void); +extern void __init pxa_map_io(void); diff --git a/arch/arm/mach-mmp/devices.c b/arch/arm/mach-mmp/devices.c new file mode 100644 index 00000000000..191d9dea873 --- /dev/null +++ b/arch/arm/mach-mmp/devices.c @@ -0,0 +1,69 @@ +/* + * linux/arch/arm/mach-mmp/devices.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +#include +#include + +int __init pxa_register_device(struct pxa_device_desc *desc, + void *data, size_t size) +{ + struct platform_device *pdev; + struct resource res[2 + MAX_RESOURCE_DMA]; + int i, ret = 0, nres = 0; + + pdev = platform_device_alloc(desc->drv_name, desc->id); + if (pdev == NULL) + return -ENOMEM; + + pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); + + memset(res, 0, sizeof(res)); + + if (desc->start != -1ul && desc->size > 0) { + res[nres].start = desc->start; + res[nres].end = desc->start + desc->size - 1; + res[nres].flags = IORESOURCE_MEM; + nres++; + } + + if (desc->irq != NO_IRQ) { + res[nres].start = desc->irq; + res[nres].end = desc->irq; + res[nres].flags = IORESOURCE_IRQ; + nres++; + } + + for (i = 0; i < MAX_RESOURCE_DMA; i++, nres++) { + if (desc->dma[i] == 0) + break; + + res[nres].start = desc->dma[i]; + res[nres].end = desc->dma[i]; + res[nres].flags = IORESOURCE_DMA; + } + + ret = platform_device_add_resources(pdev, res, nres); + if (ret) { + platform_device_put(pdev); + return ret; + } + + if (data && size) { + ret = platform_device_add_data(pdev, data, size); + if (ret) { + platform_device_put(pdev); + return ret; + } + } + + return platform_device_add(pdev); +} diff --git a/arch/arm/mach-mmp/include/mach/addr-map.h b/arch/arm/mach-mmp/include/mach/addr-map.h new file mode 100644 index 00000000000..3254089a644 --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/addr-map.h @@ -0,0 +1,34 @@ +/* + * linux/arch/arm/mach-mmp/include/mach/addr-map.h + * + * Common address map definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_MACH_ADDR_MAP_H +#define __ASM_MACH_ADDR_MAP_H + +/* APB - Application Subsystem Peripheral Bus + * + * NOTE: the DMA controller registers are actually on the AXI fabric #1 + * slave port to AHB/APB bridge, due to its close relationship to those + * peripherals on APB, let's count it into the ABP mapping area. + */ +#define APB_PHYS_BASE 0xd4000000 +#define APB_VIRT_BASE 0xfe000000 +#define APB_PHYS_SIZE 0x00200000 + +#define AXI_PHYS_BASE 0xd4200000 +#define AXI_VIRT_BASE 0xfe200000 +#define AXI_PHYS_SIZE 0x00200000 + +/* Static Memory Controller - Chip Select 0 and 1 */ +#define SMC_CS0_PHYS_BASE 0x80000000 +#define SMC_CS0_PHYS_SIZE 0x10000000 +#define SMC_CS1_PHYS_BASE 0x90000000 +#define SMC_CS1_PHYS_SIZE 0x10000000 + +#endif /* __ASM_MACH_ADDR_MAP_H */ diff --git a/arch/arm/mach-mmp/include/mach/clkdev.h b/arch/arm/mach-mmp/include/mach/clkdev.h new file mode 100644 index 00000000000..2fb354e54e0 --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/clkdev.h @@ -0,0 +1,7 @@ +#ifndef __ASM_MACH_CLKDEV_H +#define __ASM_MACH_CLKDEV_H + +#define __clk_get(clk) ({ 1; }) +#define __clk_put(clk) do { } while (0) + +#endif /* __ASM_MACH_CLKDEV_H */ diff --git a/arch/arm/mach-mmp/include/mach/cputype.h b/arch/arm/mach-mmp/include/mach/cputype.h new file mode 100644 index 00000000000..4ceed7a5075 --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/cputype.h @@ -0,0 +1,21 @@ +#ifndef __ASM_MACH_CPUTYPE_H +#define __ASM_MACH_CPUTYPE_H + +#include + +/* + * CPU Stepping OLD_ID CPU_ID CHIP_ID + * + * PXA168 A0 0x41159263 0x56158400 0x00A0A333 + */ + +#ifdef CONFIG_CPU_PXA168 +# define __cpu_is_pxa168(id) \ + ({ unsigned int _id = ((id) >> 8) & 0xff; _id == 0x84; }) +#else +# define __cpu_is_pxa168(id) (0) +#endif + +#define cpu_is_pxa168() ({ __cpu_is_pxa168(read_cpuid_id()); }) + +#endif /* __ASM_MACH_CPUTYPE_H */ diff --git a/arch/arm/mach-mmp/include/mach/debug-macro.S b/arch/arm/mach-mmp/include/mach/debug-macro.S new file mode 100644 index 00000000000..a850f87de51 --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/debug-macro.S @@ -0,0 +1,23 @@ +/* arch/arm/mach-mmp/include/mach/debug-macro.S + * + * Debugging macro include header + * + * Copied from arch/arm/mach-pxa/include/mach/debug.S + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include + + .macro addruart,rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + ldreq \rx, =APB_PHYS_BASE @ physical + ldrne \rx, =APB_VIRT_BASE @ virtual + orr \rx, \rx, #0x00017000 + .endm + +#define UART_SHIFT 2 +#include diff --git a/arch/arm/mach-mmp/include/mach/devices.h b/arch/arm/mach-mmp/include/mach/devices.h new file mode 100644 index 00000000000..bc03388d5fd --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/devices.h @@ -0,0 +1,27 @@ +#include + +#define MAX_RESOURCE_DMA 2 + +/* structure for describing the on-chip devices */ +struct pxa_device_desc { + const char *dev_name; + const char *drv_name; + int id; + int irq; + unsigned long start; + unsigned long size; + int dma[MAX_RESOURCE_DMA]; +}; + +#define PXA168_DEVICE(_name, _drv, _id, _irq, _start, _size, _dma...) \ +struct pxa_device_desc pxa168_device_##_name __initdata = { \ + .dev_name = "pxa168-" #_name, \ + .drv_name = _drv, \ + .id = _id, \ + .irq = IRQ_PXA168_##_irq, \ + .start = _start, \ + .size = _size, \ + .dma = { _dma }, \ +}; + +extern int pxa_register_device(struct pxa_device_desc *, void *, size_t); diff --git a/arch/arm/mach-mmp/include/mach/dma.h b/arch/arm/mach-mmp/include/mach/dma.h new file mode 100644 index 00000000000..1d6914544da --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/dma.h @@ -0,0 +1,13 @@ +/* + * linux/arch/arm/mach-mmp/include/mach/dma.h + */ + +#ifndef __ASM_MACH_DMA_H +#define __ASM_MACH_DMA_H + +#include + +#define DMAC_REGS_VIRT (APB_VIRT_BASE + 0x00000) + +#include +#endif /* __ASM_MACH_DMA_H */ diff --git a/arch/arm/mach-mmp/include/mach/entry-macro.S b/arch/arm/mach-mmp/include/mach/entry-macro.S new file mode 100644 index 00000000000..6d3cd35478b --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/entry-macro.S @@ -0,0 +1,25 @@ +/* + * linux/arch/arm/mach-mmp/include/mach/entry-macro.S + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include + + .macro disable_fiq + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + .macro get_irqnr_preamble, base, tmp + ldr \base, =ICU_AP_IRQ_SEL_INT_NUM + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \tmp, [\base, #0] + and \irqnr, \tmp, #0x3f + tst \tmp, #(1 << 6) + .endm diff --git a/arch/arm/mach-mmp/include/mach/hardware.h b/arch/arm/mach-mmp/include/mach/hardware.h new file mode 100644 index 00000000000..99264a5ce5e --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/hardware.h @@ -0,0 +1,4 @@ +#ifndef __ASM_MACH_HARDWARE_H +#define __ASM_MACH_HARDWARE_H + +#endif /* __ASM_MACH_HARDWARE_H */ diff --git a/arch/arm/mach-mmp/include/mach/io.h b/arch/arm/mach-mmp/include/mach/io.h new file mode 100644 index 00000000000..e7adf3d012c --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/io.h @@ -0,0 +1,21 @@ +/* + * linux/arch/arm/mach-mmp/include/mach/io.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_MACH_IO_H +#define __ASM_MACH_IO_H + +#define IO_SPACE_LIMIT 0xffffffff + +/* + * We don't actually have real ISA nor PCI buses, but there is so many + * drivers out there that might just work if we fake them... + */ +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) + +#endif /* __ASM_MACH_IO_H */ diff --git a/arch/arm/mach-mmp/include/mach/irqs.h b/arch/arm/mach-mmp/include/mach/irqs.h new file mode 100644 index 00000000000..91ecb3fbca0 --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/irqs.h @@ -0,0 +1,58 @@ +#ifndef __ASM_MACH_IRQS_H +#define __ASM_MACH_IRQS_H + +/* + * Interrupt numbers for PXA168 + */ +#define IRQ_PXA168_NONE (-1) +#define IRQ_PXA168_SSP3 0 +#define IRQ_PXA168_SSP2 1 +#define IRQ_PXA168_SSP1 2 +#define IRQ_PXA168_SSP0 3 +#define IRQ_PXA168_PMIC_INT 4 +#define IRQ_PXA168_RTC_INT 5 +#define IRQ_PXA168_RTC_ALARM 6 +#define IRQ_PXA168_TWSI0 7 +#define IRQ_PXA168_GPU 8 +#define IRQ_PXA168_KEYPAD 9 +#define IRQ_PXA168_ONEWIRE 12 +#define IRQ_PXA168_TIMER1 13 +#define IRQ_PXA168_TIMER2 14 +#define IRQ_PXA168_TIMER3 15 +#define IRQ_PXA168_CMU 16 +#define IRQ_PXA168_SSP4 17 +#define IRQ_PXA168_MSP_WAKEUP 19 +#define IRQ_PXA168_CF_WAKEUP 20 +#define IRQ_PXA168_XD_WAKEUP 21 +#define IRQ_PXA168_MFU 22 +#define IRQ_PXA168_MSP 23 +#define IRQ_PXA168_CF 24 +#define IRQ_PXA168_XD 25 +#define IRQ_PXA168_DDR_INT 26 +#define IRQ_PXA168_UART1 27 +#define IRQ_PXA168_UART2 28 +#define IRQ_PXA168_WDT 35 +#define IRQ_PXA168_FRQ_CHANGE 38 +#define IRQ_PXA168_SDH1 39 +#define IRQ_PXA168_SDH2 40 +#define IRQ_PXA168_LCD 41 +#define IRQ_PXA168_CI 42 +#define IRQ_PXA168_USB1 44 +#define IRQ_PXA168_NAND 45 +#define IRQ_PXA168_HIFI_DMA 46 +#define IRQ_PXA168_DMA_INT0 47 +#define IRQ_PXA168_DMA_INT1 48 +#define IRQ_PXA168_GPIOX 49 +#define IRQ_PXA168_USB2 51 +#define IRQ_PXA168_AC97 57 +#define IRQ_PXA168_TWSI1 58 +#define IRQ_PXA168_PMU 60 +#define IRQ_PXA168_SM_INT 63 + +#define IRQ_GPIO_START 64 +#define IRQ_GPIO_NUM 128 +#define IRQ_GPIO(x) (IRQ_GPIO_START + (x)) + +#define NR_IRQS (IRQ_GPIO_START + IRQ_GPIO_NUM) + +#endif /* __ASM_MACH_IRQS_H */ diff --git a/arch/arm/mach-mmp/include/mach/memory.h b/arch/arm/mach-mmp/include/mach/memory.h new file mode 100644 index 00000000000..bdb21d70714 --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/memory.h @@ -0,0 +1,14 @@ +/* + * linux/arch/arm/mach-mmp/include/mach/memory.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_MACH_MEMORY_H +#define __ASM_MACH_MEMORY_H + +#define PHYS_OFFSET UL(0x00000000) + +#endif /* __ASM_MACH_MEMORY_H */ diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h new file mode 100644 index 00000000000..ef0a8a2076e --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/pxa168.h @@ -0,0 +1,23 @@ +#ifndef __ASM_MACH_PXA168_H +#define __ASM_MACH_PXA168_H + +#include + +extern struct pxa_device_desc pxa168_device_uart1; +extern struct pxa_device_desc pxa168_device_uart2; + +static inline int pxa168_add_uart(int id) +{ + struct pxa_device_desc *d = NULL; + + switch (id) { + case 1: d = &pxa168_device_uart1; break; + case 2: d = &pxa168_device_uart2; break; + } + + if (d == NULL) + return -EINVAL; + + return pxa_register_device(d, NULL, 0); +} +#endif /* __ASM_MACH_PXA168_H */ diff --git a/arch/arm/mach-mmp/include/mach/regs-apbc.h b/arch/arm/mach-mmp/include/mach/regs-apbc.h new file mode 100644 index 00000000000..e0ffae59487 --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/regs-apbc.h @@ -0,0 +1,53 @@ +/* + * linux/arch/arm/mach-mmp/include/mach/regs-apbc.h + * + * Application Peripheral Bus Clock Unit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_MACH_REGS_APBC_H +#define __ASM_MACH_REGS_APBC_H + +#include + +#define APBC_VIRT_BASE (APB_VIRT_BASE + 0x015000) +#define APBC_REG(x) (APBC_VIRT_BASE + (x)) + +/* + * APB clock register offsets for PXA168 + */ +#define APBC_PXA168_UART1 APBC_REG(0x000) +#define APBC_PXA168_UART2 APBC_REG(0x004) +#define APBC_PXA168_GPIO APBC_REG(0x008) +#define APBC_PXA168_PWM0 APBC_REG(0x00c) +#define APBC_PXA168_PWM1 APBC_REG(0x010) +#define APBC_PXA168_SSP1 APBC_REG(0x01c) +#define APBC_PXA168_SSP2 APBC_REG(0x020) +#define APBC_PXA168_RTC APBC_REG(0x028) +#define APBC_PXA168_TWSI0 APBC_REG(0x02c) +#define APBC_PXA168_KPC APBC_REG(0x030) +#define APBC_PXA168_TIMERS APBC_REG(0x034) +#define APBC_PXA168_AIB APBC_REG(0x03c) +#define APBC_PXA168_SW_JTAG APBC_REG(0x040) +#define APBC_PXA168_ONEWIRE APBC_REG(0x048) +#define APBC_PXA168_SSP3 APBC_REG(0x04c) +#define APBC_PXA168_ASFAR APBC_REG(0x050) +#define APBC_PXA168_ASSAR APBC_REG(0x054) +#define APBC_PXA168_SSP4 APBC_REG(0x058) +#define APBC_PXA168_SSP5 APBC_REG(0x05c) +#define APBC_PXA168_TWSI1 APBC_REG(0x06c) +#define APBC_PXA168_UART3 APBC_REG(0x070) +#define APBC_PXA168_AC97 APBC_REG(0x084) + +/* Common APB clock register bit definitions */ +#define APBC_APBCLK (1 << 0) /* APB Bus Clock Enable */ +#define APBC_FNCLK (1 << 1) /* Functional Clock Enable */ +#define APBC_RST (1 << 2) /* Reset Generation */ + +/* Functional Clock Selection Mask */ +#define APBC_FNCLKSEL(x) (((x) & 0xf) << 4) + +#endif /* __ASM_MACH_REGS_APBC_H */ diff --git a/arch/arm/mach-mmp/include/mach/regs-apmu.h b/arch/arm/mach-mmp/include/mach/regs-apmu.h new file mode 100644 index 00000000000..91903051412 --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/regs-apmu.h @@ -0,0 +1,36 @@ +/* + * linux/arch/arm/mach-mmp/include/mach/regs-apmu.h + * + * Application Subsystem Power Management Unit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_MACH_REGS_APMU_H +#define __ASM_MACH_REGS_APMU_H + +#include + +#define APMU_VIRT_BASE (AXI_VIRT_BASE + 0x82800) +#define APMU_REG(x) (APMU_VIRT_BASE + (x)) + +/* Clock Reset Control */ +#define APMU_IRE APMU_REG(0x048) +#define APMU_LCD APMU_REG(0x04c) +#define APMU_CCIC APMU_REG(0x050) +#define APMU_SDH0 APMU_REG(0x054) +#define APMU_SDH1 APMU_REG(0x058) +#define APMU_USB APMU_REG(0x05c) +#define APMU_NAND APMU_REG(0x060) +#define APMU_DMA APMU_REG(0x064) +#define APMU_GEU APMU_REG(0x068) +#define APMU_BUS APMU_REG(0x06c) + +#define APMU_FNCLK_EN (1 << 4) +#define APMU_AXICLK_EN (1 << 3) +#define APMU_FNRST_DIS (1 << 1) +#define APMU_AXIRST_DIS (1 << 0) + +#endif /* __ASM_MACH_REGS_APMU_H */ diff --git a/arch/arm/mach-mmp/include/mach/regs-icu.h b/arch/arm/mach-mmp/include/mach/regs-icu.h new file mode 100644 index 00000000000..e5f08723e0c --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/regs-icu.h @@ -0,0 +1,31 @@ +/* + * linux/arch/arm/mach-mmp/include/mach/regs-icu.h + * + * Interrupt Control Unit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_MACH_ICU_H +#define __ASM_MACH_ICU_H + +#include + +#define ICU_VIRT_BASE (AXI_VIRT_BASE + 0x82000) +#define ICU_REG(x) (ICU_VIRT_BASE + (x)) + +#define ICU_INT_CONF(n) ICU_REG((n) << 2) +#define ICU_INT_CONF_AP_INT (1 << 6) +#define ICU_INT_CONF_CP_INT (1 << 5) +#define ICU_INT_CONF_IRQ (1 << 4) +#define ICU_INT_CONF_MASK (0xf) + +#define ICU_AP_FIQ_SEL_INT_NUM ICU_REG(0x108) /* AP FIQ Selected Interrupt */ +#define ICU_AP_IRQ_SEL_INT_NUM ICU_REG(0x10C) /* AP IRQ Selected Interrupt */ +#define ICU_AP_GBL_IRQ_MSK ICU_REG(0x114) /* AP Global Interrupt Mask */ +#define ICU_INT_STATUS_0 ICU_REG(0x128) /* Interrupt Stuats 0 */ +#define ICU_INT_STATUS_1 ICU_REG(0x12C) /* Interrupt Status 1 */ + +#endif /* __ASM_MACH_ICU_H */ diff --git a/arch/arm/mach-mmp/include/mach/regs-timers.h b/arch/arm/mach-mmp/include/mach/regs-timers.h new file mode 100644 index 00000000000..45589fec9fc --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/regs-timers.h @@ -0,0 +1,44 @@ +/* + * linux/arch/arm/mach-mmp/include/mach/regs-timers.h + * + * Timers Module + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_MACH_REGS_TIMERS_H +#define __ASM_MACH_REGS_TIMERS_H + +#include + +#define TIMERS1_VIRT_BASE (APB_VIRT_BASE + 0x14000) +#define TIMERS2_VIRT_BASE (APB_VIRT_BASE + 0x16000) + +#define TMR_CCR (0x0000) +#define TMR_TN_MM(n, m) (0x0004 + ((n) << 3) + (((n) + (m)) << 2)) +#define TMR_CR(n) (0x0028 + ((n) << 2)) +#define TMR_SR(n) (0x0034 + ((n) << 2)) +#define TMR_IER(n) (0x0040 + ((n) << 2)) +#define TMR_PLVR(n) (0x004c + ((n) << 2)) +#define TMR_PLCR(n) (0x0058 + ((n) << 2)) +#define TMR_WMER (0x0064) +#define TMR_WMR (0x0068) +#define TMR_WVR (0x006c) +#define TMR_WSR (0x0070) +#define TMR_ICR(n) (0x0074 + ((n) << 2)) +#define TMR_WICR (0x0080) +#define TMR_CER (0x0084) +#define TMR_CMR (0x0088) +#define TMR_ILR(n) (0x008c + ((n) << 2)) +#define TMR_WCR (0x0098) +#define TMR_WFAR (0x009c) +#define TMR_WSAR (0x00A0) +#define TMR_CVWR(n) (0x00A4 + ((n) << 2)) + +#define TMR_CCR_CS_0(x) (((x) & 0x3) << 0) +#define TMR_CCR_CS_1(x) (((x) & 0x7) << 2) +#define TMR_CCR_CS_2(x) (((x) & 0x3) << 5) + +#endif /* __ASM_MACH_REGS_TIMERS_H */ diff --git a/arch/arm/mach-mmp/include/mach/system.h b/arch/arm/mach-mmp/include/mach/system.h new file mode 100644 index 00000000000..001edfefec1 --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/system.h @@ -0,0 +1,21 @@ +/* + * linux/arch/arm/mach-mmp/include/mach/system.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_MACH_SYSTEM_H +#define __ASM_MACH_SYSTEM_H + +static inline void arch_idle(void) +{ + cpu_do_idle(); +} + +static inline void arch_reset(char mode) +{ + cpu_reset(0); +} +#endif /* __ASM_MACH_SYSTEM_H */ diff --git a/arch/arm/mach-mmp/include/mach/timex.h b/arch/arm/mach-mmp/include/mach/timex.h new file mode 100644 index 00000000000..6cebbd0ca8f --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/timex.h @@ -0,0 +1,9 @@ +/* + * linux/arch/arm/mach-mmp/include/mach/timex.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define CLOCK_TICK_RATE 3250000 diff --git a/arch/arm/mach-mmp/include/mach/uncompress.h b/arch/arm/mach-mmp/include/mach/uncompress.h new file mode 100644 index 00000000000..c93d5fa5865 --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/uncompress.h @@ -0,0 +1,41 @@ +/* + * arch/arm/mach-mmp/include/mach/uncompress.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include + +#define UART1_BASE (APB_PHYS_BASE + 0x36000) +#define UART2_BASE (APB_PHYS_BASE + 0x17000) +#define UART3_BASE (APB_PHYS_BASE + 0x18000) + +static inline void putc(char c) +{ + volatile unsigned long *UART = (unsigned long *)UART2_BASE; + + /* UART enabled? */ + if (!(UART[UART_IER] & UART_IER_UUE)) + return; + + while (!(UART[UART_LSR] & UART_LSR_THRE)) + barrier(); + + UART[UART_TX] = c; +} + +/* + * This does not append a newline + */ +static inline void flush(void) +{ +} + +/* + * nothing to do + */ +#define arch_decomp_setup() +#define arch_decomp_wdog() diff --git a/arch/arm/mach-mmp/include/mach/vmalloc.h b/arch/arm/mach-mmp/include/mach/vmalloc.h new file mode 100644 index 00000000000..b60ccaf9fee --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/vmalloc.h @@ -0,0 +1,5 @@ +/* + * linux/arch/arm/mach-mmp/include/mach/vmalloc.h + */ + +#define VMALLOC_END 0xfe000000 diff --git a/arch/arm/mach-mmp/irq.c b/arch/arm/mach-mmp/irq.c new file mode 100644 index 00000000000..52ff2f065eb --- /dev/null +++ b/arch/arm/mach-mmp/irq.c @@ -0,0 +1,55 @@ +/* + * linux/arch/arm/mach-mmp/irq.c + * + * Generic IRQ handling, GPIO IRQ demultiplexing, etc. + * + * Author: Bin Yang + * Created: Sep 30, 2008 + * Copyright: Marvell International Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +#include + +#include "common.h" + +#define IRQ_ROUTE_TO_AP (ICU_INT_CONF_AP_INT | ICU_INT_CONF_IRQ) + +#define PRIORITY_DEFAULT 0x1 +#define PRIORITY_NONE 0x0 /* means IRQ disabled */ + +static void icu_mask_irq(unsigned int irq) +{ + __raw_writel(PRIORITY_NONE, ICU_INT_CONF(irq)); +} + +static void icu_unmask_irq(unsigned int irq) +{ + __raw_writel(IRQ_ROUTE_TO_AP | PRIORITY_DEFAULT, ICU_INT_CONF(irq)); +} + +static struct irq_chip icu_irq_chip = { + .name = "icu_irq", + .ack = icu_mask_irq, + .mask = icu_mask_irq, + .unmask = icu_unmask_irq, +}; + +void __init icu_init_irq(void) +{ + int irq; + + for (irq = 0; irq < 64; irq++) { + icu_mask_irq(irq); + set_irq_chip(irq, &icu_irq_chip); + set_irq_handler(irq, handle_level_irq); + set_irq_flags(irq, IRQF_VALID); + } +} diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c new file mode 100644 index 00000000000..1935c754511 --- /dev/null +++ b/arch/arm/mach-mmp/pxa168.c @@ -0,0 +1,77 @@ +/* + * linux/arch/arm/mach-mmp/pxa168.c + * + * Code specific to PXA168 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "clock.h" + +void __init pxa168_init_irq(void) +{ + icu_init_irq(); +} + +/* APB peripheral clocks */ +static APBC_CLK(uart1, PXA168_UART1, 1, 14745600); +static APBC_CLK(uart2, PXA168_UART2, 1, 14745600); + +/* device and clock bindings */ +static struct clk_lookup pxa168_clkregs[] = { + INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL), + INIT_CLKREG(&clk_uart2, "pxa2xx-uart.1", NULL), +}; + +static int __init pxa168_init(void) +{ + if (cpu_is_pxa168()) { + pxa_init_dma(IRQ_PXA168_DMA_INT0, 32); + clks_register(ARRAY_AND_SIZE(pxa168_clkregs)); + } + + return 0; +} +postcore_initcall(pxa168_init); + +/* system timer - clock enabled, 3.25MHz */ +#define TIMER_CLK_RST (APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(3)) + +static void __init pxa168_timer_init(void) +{ + /* this is early, we have to initialize the CCU registers by + * ourselves instead of using clk_* API. Clock rate is defined + * by APBC_TIMERS_CLK_RST (3.25MHz) and enabled free-running + */ + __raw_writel(APBC_APBCLK | APBC_RST, APBC_PXA168_TIMERS); + + /* 3.25MHz, bus/functional clock enabled, release reset */ + __raw_writel(TIMER_CLK_RST, APBC_PXA168_TIMERS); + + timer_init(IRQ_PXA168_TIMER1); +} + +struct sys_timer pxa168_timer = { + .init = pxa168_timer_init, +}; + +/* on-chip devices */ +PXA168_DEVICE(uart1, "pxa2xx-uart", 0, UART1, 0xd4017000, 0x30, 21, 22); +PXA168_DEVICE(uart2, "pxa2xx-uart", 1, UART2, 0xd4018000, 0x30, 23, 24); diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c new file mode 100644 index 00000000000..b03a6eda741 --- /dev/null +++ b/arch/arm/mach-mmp/time.c @@ -0,0 +1,199 @@ +/* + * linux/arch/arm/mach-mmp/time.c + * + * Support for clocksource and clockevents + * + * Copyright (C) 2008 Marvell International Ltd. + * All rights reserved. + * + * 2008-04-11: Jason Chagas + * 2008-10-08: Bin Yang + * + * The timers module actually includes three timers, each timer with upto + * three match comparators. Timer #0 is used here in free-running mode as + * the clock source, and match comparator #1 used as clock event device. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "clock.h" + +#define TIMERS_VIRT_BASE TIMERS1_VIRT_BASE + +#define MAX_DELTA (0xfffffffe) +#define MIN_DELTA (16) + +#define TCR2NS_SCALE_FACTOR 10 + +static unsigned long tcr2ns_scale; + +static void __init set_tcr2ns_scale(unsigned long tcr_rate) +{ + unsigned long long v = 1000000000ULL << TCR2NS_SCALE_FACTOR; + do_div(v, tcr_rate); + tcr2ns_scale = v; + /* + * We want an even value to automatically clear the top bit + * returned by cnt32_to_63() without an additional run time + * instruction. So if the LSB is 1 then round it up. + */ + if (tcr2ns_scale & 1) + tcr2ns_scale++; +} + +/* + * FIXME: the timer needs some delay to stablize the counter capture + */ +static inline uint32_t timer_read(void) +{ + int delay = 100; + + __raw_writel(1, TIMERS_VIRT_BASE + TMR_CVWR(0)); + + while (delay--) + cpu_relax(); + + return __raw_readl(TIMERS_VIRT_BASE + TMR_CVWR(0)); +} + +unsigned long long sched_clock(void) +{ + unsigned long long v = cnt32_to_63(timer_read()); + return (v * tcr2ns_scale) >> TCR2NS_SCALE_FACTOR; +} + +static irqreturn_t timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *c = dev_id; + + /* disable and clear pending interrupt status */ + __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_IER(0)); + __raw_writel(0x1, TIMERS_VIRT_BASE + TMR_ICR(0)); + c->event_handler(c); + return IRQ_HANDLED; +} + +static int timer_set_next_event(unsigned long delta, + struct clock_event_device *dev) +{ + unsigned long flags, next; + + local_irq_save(flags); + + /* clear pending interrupt status and enable */ + __raw_writel(0x01, TIMERS_VIRT_BASE + TMR_ICR(0)); + __raw_writel(0x01, TIMERS_VIRT_BASE + TMR_IER(0)); + + next = timer_read() + delta; + __raw_writel(next, TIMERS_VIRT_BASE + TMR_TN_MM(0, 0)); + + local_irq_restore(flags); + return 0; +} + +static void timer_set_mode(enum clock_event_mode mode, + struct clock_event_device *dev) +{ + unsigned long flags; + + local_irq_save(flags); + switch (mode) { + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + /* disable the matching interrupt */ + __raw_writel(0x00, TIMERS_VIRT_BASE + TMR_IER(0)); + break; + case CLOCK_EVT_MODE_RESUME: + case CLOCK_EVT_MODE_PERIODIC: + break; + } + local_irq_restore(flags); +} + +static struct clock_event_device ckevt = { + .name = "clockevent", + .features = CLOCK_EVT_FEAT_ONESHOT, + .shift = 32, + .rating = 200, + .set_next_event = timer_set_next_event, + .set_mode = timer_set_mode, +}; + +static cycle_t clksrc_read(void) +{ + return timer_read(); +} + +static struct clocksource cksrc = { + .name = "clocksource", + .shift = 20, + .rating = 200, + .read = clksrc_read, + .mask = CLOCKSOURCE_MASK(32), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static void __init timer_config(void) +{ + uint32_t ccr = __raw_readl(TIMERS_VIRT_BASE + TMR_CCR); + uint32_t cer = __raw_readl(TIMERS_VIRT_BASE + TMR_CER); + uint32_t cmr = __raw_readl(TIMERS_VIRT_BASE + TMR_CMR); + + __raw_writel(cer & ~0x1, TIMERS_VIRT_BASE + TMR_CER); /* disable */ + + ccr &= TMR_CCR_CS_0(0x3); + __raw_writel(ccr, TIMERS_VIRT_BASE + TMR_CCR); + + /* free-running mode */ + __raw_writel(cmr | 0x01, TIMERS_VIRT_BASE + TMR_CMR); + + __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_PLCR(0)); /* free-running */ + __raw_writel(0x7, TIMERS_VIRT_BASE + TMR_ICR(0)); /* clear status */ + __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_IER(0)); + + /* enable timer counter */ + __raw_writel(cer | 0x01, TIMERS_VIRT_BASE + TMR_CER); +} + +static struct irqaction timer_irq = { + .name = "timer", + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .handler = timer_interrupt, + .dev_id = &ckevt, +}; + +void __init timer_init(int irq) +{ + timer_config(); + + set_tcr2ns_scale(CLOCK_TICK_RATE); + + ckevt.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt.shift); + ckevt.max_delta_ns = clockevent_delta2ns(MAX_DELTA, &ckevt); + ckevt.min_delta_ns = clockevent_delta2ns(MIN_DELTA, &ckevt); + ckevt.cpumask = cpumask_of(0); + + cksrc.mult = clocksource_hz2mult(CLOCK_TICK_RATE, cksrc.shift); + + setup_irq(irq, &timer_irq); + + clocksource_register(&cksrc); + clockevents_register_device(&ckevt); +} diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index d490f3773c0..64086f4f5fc 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -340,6 +340,17 @@ config CPU_XSC3 select CPU_TLB_V4WBI if MMU select IO_36 +# Marvell PJ1 (Mohawk) +config CPU_MOHAWK + bool + select CPU_32v5 + select CPU_ABRT_EV5T + select CPU_PABRT_NOIFAR + select CPU_CACHE_VIVT + select CPU_CP15_MMU + select CPU_TLB_V4WBI if MMU + select CPU_COPY_V4WB if MMU + # Feroceon config CPU_FEROCEON bool @@ -569,7 +580,7 @@ comment "Processor Features" config ARM_THUMB bool "Support Thumb user binaries" - depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_V6 || CPU_V7 || CPU_FEROCEON + depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_V6 || CPU_V7 || CPU_FEROCEON default y help Say Y if you want to include kernel support for running user space @@ -653,7 +664,7 @@ config CPU_CACHE_ROUND_ROBIN config CPU_BPREDICT_DISABLE bool "Disable branch prediction" - depends on CPU_ARM1020 || CPU_V6 || CPU_XSC3 || CPU_V7 + depends on CPU_ARM1020 || CPU_V6 || CPU_MOHAWK || CPU_XSC3 || CPU_V7 help Say Y here to disable branch prediction. If unsure, say N. diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index 480f78a3611..64149d9e55a 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile @@ -70,6 +70,7 @@ obj-$(CONFIG_CPU_SA110) += proc-sa110.o obj-$(CONFIG_CPU_SA1100) += proc-sa1100.o obj-$(CONFIG_CPU_XSCALE) += proc-xscale.o obj-$(CONFIG_CPU_XSC3) += proc-xsc3.o +obj-$(CONFIG_CPU_MOHAWK) += proc-mohawk.o obj-$(CONFIG_CPU_FEROCEON) += proc-feroceon.o obj-$(CONFIG_CPU_V6) += proc-v6.o obj-$(CONFIG_CPU_V7) += proc-v7.o diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S new file mode 100644 index 00000000000..540f5078496 --- /dev/null +++ b/arch/arm/mm/proc-mohawk.S @@ -0,0 +1,416 @@ +/* + * linux/arch/arm/mm/proc-mohawk.S: MMU functions for Marvell PJ1 core + * + * PJ1 (codename Mohawk) is a hybrid of the xscale3 and Marvell's own core. + * + * Heavily based on proc-arm926.S and proc-xsc3.S + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "proc-macros.S" + +/* + * This is the maximum size of an area which will be flushed. If the + * area is larger than this, then we flush the whole cache. + */ +#define CACHE_DLIMIT 32768 + +/* + * The cache line size of the L1 D cache. + */ +#define CACHE_DLINESIZE 32 + +/* + * cpu_mohawk_proc_init() + */ +ENTRY(cpu_mohawk_proc_init) + mov pc, lr + +/* + * cpu_mohawk_proc_fin() + */ +ENTRY(cpu_mohawk_proc_fin) + stmfd sp!, {lr} + mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE + msr cpsr_c, ip + bl mohawk_flush_kern_cache_all + mrc p15, 0, r0, c1, c0, 0 @ ctrl register + bic r0, r0, #0x1800 @ ...iz........... + bic r0, r0, #0x0006 @ .............ca. + mcr p15, 0, r0, c1, c0, 0 @ disable caches + ldmfd sp!, {pc} + +/* + * cpu_mohawk_reset(loc) + * + * Perform a soft reset of the system. Put the CPU into the + * same state as it would be if it had been reset, and branch + * to what would be the reset vector. + * + * loc: location to jump to for soft reset + * + * (same as arm926) + */ + .align 5 +ENTRY(cpu_mohawk_reset) + mov ip, #0 + mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches + mcr p15, 0, ip, c7, c10, 4 @ drain WB + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs + mrc p15, 0, ip, c1, c0, 0 @ ctrl register + bic ip, ip, #0x0007 @ .............cam + bic ip, ip, #0x1100 @ ...i...s........ + mcr p15, 0, ip, c1, c0, 0 @ ctrl register + mov pc, r0 + +/* + * cpu_mohawk_do_idle() + * + * Called with IRQs disabled + */ + .align 5 +ENTRY(cpu_mohawk_do_idle) + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer + mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt + mov pc, lr + +/* + * flush_user_cache_all() + * + * Clean and invalidate all cache entries in a particular + * address space. + */ +ENTRY(mohawk_flush_user_cache_all) + /* FALLTHROUGH */ + +/* + * flush_kern_cache_all() + * + * Clean and invalidate the entire cache. + */ +ENTRY(mohawk_flush_kern_cache_all) + mov r2, #VM_EXEC + mov ip, #0 +__flush_whole_cache: + mcr p15, 0, ip, c7, c14, 0 @ clean & invalidate all D cache + tst r2, #VM_EXEC + mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache + mcrne p15, 0, ip, c7, c10, 0 @ drain write buffer + mov pc, lr + +/* + * flush_user_cache_range(start, end, flags) + * + * Clean and invalidate a range of cache entries in the + * specified address range. + * + * - start - start address (inclusive) + * - end - end address (exclusive) + * - flags - vm_flags describing address space + * + * (same as arm926) + */ +ENTRY(mohawk_flush_user_cache_range) + mov ip, #0 + sub r3, r1, r0 @ calculate total size + cmp r3, #CACHE_DLIMIT + bgt __flush_whole_cache +1: tst r2, #VM_EXEC + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #CACHE_DLINESIZE + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + tst r2, #VM_EXEC + mcrne p15, 0, ip, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * coherent_kern_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start, end. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(mohawk_coherent_kern_range) + /* FALLTHROUGH */ + +/* + * coherent_user_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start, end. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + * + * (same as arm926) + */ +ENTRY(mohawk_coherent_user_range) + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * flush_kern_dcache_page(void *page) + * + * Ensure no D cache aliasing occurs, either with itself or + * the I cache + * + * - addr - page aligned address + */ +ENTRY(mohawk_flush_kern_dcache_page) + add r1, r0, #PAGE_SZ +1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * dma_inv_range(start, end) + * + * Invalidate (discard) the specified virtual address range. + * May not write back any entries. If 'start' or 'end' + * are not cache line aligned, those lines must be written + * back. + * + * - start - virtual start address + * - end - virtual end address + * + * (same as v4wb) + */ +ENTRY(mohawk_dma_inv_range) + tst r0, #CACHE_DLINESIZE - 1 + mcrne p15, 0, r0, c7, c10, 1 @ clean D entry + tst r1, #CACHE_DLINESIZE - 1 + mcrne p15, 0, r1, c7, c10, 1 @ clean D entry + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * dma_clean_range(start, end) + * + * Clean the specified virtual address range. + * + * - start - virtual start address + * - end - virtual end address + * + * (same as v4wb) + */ +ENTRY(mohawk_dma_clean_range) + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * dma_flush_range(start, end) + * + * Clean and invalidate the specified virtual address range. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(mohawk_dma_flush_range) + bic r0, r0, #CACHE_DLINESIZE - 1 +1: + mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +ENTRY(mohawk_cache_fns) + .long mohawk_flush_kern_cache_all + .long mohawk_flush_user_cache_all + .long mohawk_flush_user_cache_range + .long mohawk_coherent_kern_range + .long mohawk_coherent_user_range + .long mohawk_flush_kern_dcache_page + .long mohawk_dma_inv_range + .long mohawk_dma_clean_range + .long mohawk_dma_flush_range + +ENTRY(cpu_mohawk_dcache_clean_area) +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #CACHE_DLINESIZE + subs r1, r1, #CACHE_DLINESIZE + bhi 1b + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * cpu_mohawk_switch_mm(pgd) + * + * Set the translation base pointer to be as described by pgd. + * + * pgd: new page tables + */ + .align 5 +ENTRY(cpu_mohawk_switch_mm) + mov ip, #0 + mcr p15, 0, ip, c7, c14, 0 @ clean & invalidate all D cache + mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache + mcr p15, 0, ip, c7, c10, 4 @ drain WB + orr r0, r0, #0x18 @ cache the page table in L2 + mcr p15, 0, r0, c2, c0, 0 @ load page table pointer + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs + mov pc, lr + +/* + * cpu_mohawk_set_pte_ext(ptep, pte, ext) + * + * Set a PTE and flush it out + */ + .align 5 +ENTRY(cpu_mohawk_set_pte_ext) + armv3_set_pte_ext + mov r0, r0 + mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + + __INIT + + .type __mohawk_setup, #function +__mohawk_setup: + mov r0, #0 + mcr p15, 0, r0, c7, c7 @ invalidate I,D caches + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer + mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs + orr r4, r4, #0x18 @ cache the page table in L2 + mcr p15, 0, r4, c2, c0, 0 @ load page table pointer + + mov r0, #0 @ don't allow CP access + mcr p15, 0, r0, c15, c1, 0 @ write CP access register + + adr r5, mohawk_crval + ldmia r5, {r5, r6} + mrc p15, 0, r0, c1, c0 @ get control register + bic r0, r0, r5 + orr r0, r0, r6 + mov pc, lr + + .size __mohawk_setup, . - __mohawk_setup + + /* + * R + * .RVI ZFRS BLDP WCAM + * .011 1001 ..00 0101 + * + */ + .type mohawk_crval, #object +mohawk_crval: + crval clear=0x00007f3f, mmuset=0x00003905, ucset=0x00001134 + + __INITDATA + +/* + * Purpose : Function pointers used to access above functions - all calls + * come through these + */ + .type mohawk_processor_functions, #object +mohawk_processor_functions: + .word v5t_early_abort + .word pabort_noifar + .word cpu_mohawk_proc_init + .word cpu_mohawk_proc_fin + .word cpu_mohawk_reset + .word cpu_mohawk_do_idle + .word cpu_mohawk_dcache_clean_area + .word cpu_mohawk_switch_mm + .word cpu_mohawk_set_pte_ext + .size mohawk_processor_functions, . - mohawk_processor_functions + + .section ".rodata" + + .type cpu_arch_name, #object +cpu_arch_name: + .asciz "armv5te" + .size cpu_arch_name, . - cpu_arch_name + + .type cpu_elf_name, #object +cpu_elf_name: + .asciz "v5" + .size cpu_elf_name, . - cpu_elf_name + + .type cpu_mohawk_name, #object +cpu_mohawk_name: + .asciz "Marvell 88SV331x" + .size cpu_mohawk_name, . - cpu_mohawk_name + + .align + + .section ".proc.info.init", #alloc, #execinstr + + .type __88sv331x_proc_info,#object +__88sv331x_proc_info: + .long 0x56158000 @ Marvell 88SV331x (MOHAWK) + .long 0xfffff000 + .long PMD_TYPE_SECT | \ + PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | \ + PMD_BIT4 | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_BIT4 | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ + b __mohawk_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP + .long cpu_mohawk_name + .long mohawk_processor_functions + .long v4wbi_tlb_fns + .long v4wb_user_fns + .long mohawk_cache_fns + .size __88sv331x_proc_info, . - __88sv331x_proc_info -- GitLab From 40305a583a3e080a8d1aa126fa810480ec8cbabd Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Thu, 26 Feb 2009 09:34:35 +0800 Subject: [PATCH 3913/4982] [ARM] pxa: add iWMMXt support for pxa168 Signed-off-by: Eric Miao --- arch/arm/Kconfig | 4 ++-- arch/arm/kernel/Makefile | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index fdcd2d54e93..5385d8743c6 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -712,8 +712,8 @@ source arch/arm/mm/Kconfig config IWMMXT bool "Enable iWMMXt support" - depends on CPU_XSCALE || CPU_XSC3 - default y if PXA27x || PXA3xx + depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK + default y if PXA27x || PXA3xx || ARCH_MMP help Enable support for iWMMXt context switching at run time if running on a CPU that supports it. diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index ca60d335e8f..11a5197a221 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -36,6 +36,7 @@ AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312 obj-$(CONFIG_CPU_XSCALE) += xscale-cp0.o obj-$(CONFIG_CPU_XSC3) += xscale-cp0.o +obj-$(CONFIG_CPU_MOHAWK) += xscale-cp0.o obj-$(CONFIG_IWMMXT) += iwmmxt.o AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt -- GitLab From e2bb6650ef94c64723e2dd35ab92410b9477bc64 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 20 Jan 2009 14:38:24 +0800 Subject: [PATCH 3914/4982] [ARM] pxa: add GPIO support for pxa168 Signed-off-by: Eric Miao --- arch/arm/Kconfig | 2 ++ arch/arm/mach-mmp/include/mach/gpio.h | 36 +++++++++++++++++++++++++++ arch/arm/mach-mmp/pxa168.c | 19 ++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 arch/arm/mach-mmp/include/mach/gpio.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 5385d8743c6..daf35d77820 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -490,6 +490,8 @@ config ARCH_PXA config ARCH_MMP bool "Marvell PXA168" depends on MMU + select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB select HAVE_CLK select COMMON_CLKDEV select GENERIC_TIME diff --git a/arch/arm/mach-mmp/include/mach/gpio.h b/arch/arm/mach-mmp/include/mach/gpio.h new file mode 100644 index 00000000000..ab26d13295c --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/gpio.h @@ -0,0 +1,36 @@ +#ifndef __ASM_MACH_GPIO_H +#define __ASM_MACH_GPIO_H + +#include +#include +#include + +#define GPIO_REGS_VIRT (APB_VIRT_BASE + 0x19000) + +#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) +#define GPIO_REG(x) (*((volatile u32 *)(GPIO_REGS_VIRT + (x)))) + +#define NR_BUILTIN_GPIO (128) + +#define gpio_to_bank(gpio) ((gpio) >> 5) +#define gpio_to_irq(gpio) (IRQ_GPIO_START + (gpio)) +#define irq_to_gpio(irq) ((irq) - IRQ_GPIO_START) + + +#define __gpio_is_inverted(gpio) (0) +#define __gpio_is_occupied(gpio) (0) + +/* NOTE: these macros are defined here to make optimization of + * gpio_{get,set}_value() to work when 'gpio' is a constant. + * Usage of these macros otherwise is no longer recommended, + * use generic GPIO API whenever possible. + */ +#define GPIO_bit(gpio) (1 << ((gpio) & 0x1f)) + +#define GPLR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x00) +#define GPDR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x0c) +#define GPSR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x18) +#define GPCR(x) GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x24) + +#include +#endif /* __ASM_MACH_GPIO_H */ diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c index 1935c754511..1774682e988 100644 --- a/arch/arm/mach-mmp/pxa168.c +++ b/arch/arm/mach-mmp/pxa168.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -19,15 +20,33 @@ #include #include #include +#include #include #include #include "common.h" #include "clock.h" +#define APMASK(i) (GPIO_REGS_VIRT + BANK_OFF(i) + 0x09c) + +static void __init pxa168_init_gpio(void) +{ + int i; + + /* enable GPIO clock */ + __raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_PXA168_GPIO); + + /* unmask GPIO edge detection for all 4 banks - APMASKx */ + for (i = 0; i < 4; i++) + __raw_writel(0xffffffff, APMASK(i)); + + pxa_init_gpio(IRQ_PXA168_GPIOX, 0, 127, NULL); +} + void __init pxa168_init_irq(void) { icu_init_irq(); + pxa168_init_gpio(); } /* APB peripheral clocks */ -- GitLab From a7a89d9621ba877ae45784cf7d000182075df9c1 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 20 Jan 2009 17:20:56 +0800 Subject: [PATCH 3915/4982] [ARM] pxa: add MFP support for pxa168 Signed-off-by: Eric Miao --- arch/arm/mach-mmp/include/mach/mfp-pxa168.h | 258 ++++++++++++++++++++ arch/arm/mach-mmp/include/mach/mfp.h | 37 +++ arch/arm/mach-mmp/pxa168.c | 15 ++ 3 files changed, 310 insertions(+) create mode 100644 arch/arm/mach-mmp/include/mach/mfp-pxa168.h create mode 100644 arch/arm/mach-mmp/include/mach/mfp.h diff --git a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h new file mode 100644 index 00000000000..d0bdb6e3682 --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h @@ -0,0 +1,258 @@ +#ifndef __ASM_MACH_MFP_PXA168_H +#define __ASM_MACH_MFP_PXA168_H + +#include + +/* GPIO */ +#define GPIO0_GPIO MFP_CFG(GPIO0, AF5) +#define GPIO1_GPIO MFP_CFG(GPIO1, AF5) +#define GPIO2_GPIO MFP_CFG(GPIO2, AF5) +#define GPIO3_GPIO MFP_CFG(GPIO3, AF5) +#define GPIO4_GPIO MFP_CFG(GPIO4, AF5) +#define GPIO5_GPIO MFP_CFG(GPIO5, AF5) +#define GPIO6_GPIO MFP_CFG(GPIO6, AF5) +#define GPIO7_GPIO MFP_CFG(GPIO7, AF5) +#define GPIO8_GPIO MFP_CFG(GPIO8, AF5) +#define GPIO9_GPIO MFP_CFG(GPIO9, AF5) +#define GPIO10_GPIO MFP_CFG(GPIO10, AF5) +#define GPIO11_GPIO MFP_CFG(GPIO11, AF5) +#define GPIO12_GPIO MFP_CFG(GPIO12, AF5) +#define GPIO13_GPIO MFP_CFG(GPIO13, AF5) +#define GPIO14_GPIO MFP_CFG(GPIO14, AF5) +#define GPIO15_GPIO MFP_CFG(GPIO15, AF5) +#define GPIO16_GPIO MFP_CFG(GPIO16, AF0) +#define GPIO17_GPIO MFP_CFG(GPIO17, AF5) +#define GPIO18_GPIO MFP_CFG(GPIO18, AF0) +#define GPIO19_GPIO MFP_CFG(GPIO19, AF5) +#define GPIO20_GPIO MFP_CFG(GPIO20, AF0) +#define GPIO21_GPIO MFP_CFG(GPIO21, AF5) +#define GPIO22_GPIO MFP_CFG(GPIO22, AF5) +#define GPIO23_GPIO MFP_CFG(GPIO23, AF5) +#define GPIO24_GPIO MFP_CFG(GPIO24, AF5) +#define GPIO25_GPIO MFP_CFG(GPIO25, AF5) +#define GPIO26_GPIO MFP_CFG(GPIO26, AF0) +#define GPIO27_GPIO MFP_CFG(GPIO27, AF5) +#define GPIO28_GPIO MFP_CFG(GPIO28, AF5) +#define GPIO29_GPIO MFP_CFG(GPIO29, AF5) +#define GPIO30_GPIO MFP_CFG(GPIO30, AF5) +#define GPIO31_GPIO MFP_CFG(GPIO31, AF5) +#define GPIO32_GPIO MFP_CFG(GPIO32, AF5) +#define GPIO33_GPIO MFP_CFG(GPIO33, AF5) +#define GPIO34_GPIO MFP_CFG(GPIO34, AF0) +#define GPIO35_GPIO MFP_CFG(GPIO35, AF0) +#define GPIO36_GPIO MFP_CFG(GPIO36, AF0) +#define GPIO37_GPIO MFP_CFG(GPIO37, AF0) +#define GPIO38_GPIO MFP_CFG(GPIO38, AF0) +#define GPIO39_GPIO MFP_CFG(GPIO39, AF0) +#define GPIO40_GPIO MFP_CFG(GPIO40, AF0) +#define GPIO41_GPIO MFP_CFG(GPIO41, AF0) +#define GPIO42_GPIO MFP_CFG(GPIO42, AF0) +#define GPIO43_GPIO MFP_CFG(GPIO43, AF0) +#define GPIO44_GPIO MFP_CFG(GPIO44, AF0) +#define GPIO45_GPIO MFP_CFG(GPIO45, AF0) +#define GPIO46_GPIO MFP_CFG(GPIO46, AF0) +#define GPIO47_GPIO MFP_CFG(GPIO47, AF0) +#define GPIO48_GPIO MFP_CFG(GPIO48, AF0) +#define GPIO49_GPIO MFP_CFG(GPIO49, AF0) +#define GPIO50_GPIO MFP_CFG(GPIO50, AF0) +#define GPIO51_GPIO MFP_CFG(GPIO51, AF0) +#define GPIO52_GPIO MFP_CFG(GPIO52, AF0) +#define GPIO53_GPIO MFP_CFG(GPIO53, AF0) +#define GPIO54_GPIO MFP_CFG(GPIO54, AF0) +#define GPIO55_GPIO MFP_CFG(GPIO55, AF0) +#define GPIO56_GPIO MFP_CFG(GPIO56, AF0) +#define GPIO57_GPIO MFP_CFG(GPIO57, AF0) +#define GPIO58_GPIO MFP_CFG(GPIO58, AF0) +#define GPIO59_GPIO MFP_CFG(GPIO59, AF0) +#define GPIO60_GPIO MFP_CFG(GPIO60, AF0) +#define GPIO61_GPIO MFP_CFG(GPIO61, AF0) +#define GPIO62_GPIO MFP_CFG(GPIO62, AF0) +#define GPIO63_GPIO MFP_CFG(GPIO63, AF0) +#define GPIO64_GPIO MFP_CFG(GPIO64, AF0) +#define GPIO65_GPIO MFP_CFG(GPIO65, AF0) +#define GPIO66_GPIO MFP_CFG(GPIO66, AF0) +#define GPIO67_GPIO MFP_CFG(GPIO67, AF0) +#define GPIO68_GPIO MFP_CFG(GPIO68, AF0) +#define GPIO69_GPIO MFP_CFG(GPIO69, AF0) +#define GPIO70_GPIO MFP_CFG(GPIO70, AF0) +#define GPIO71_GPIO MFP_CFG(GPIO71, AF0) +#define GPIO72_GPIO MFP_CFG(GPIO72, AF0) +#define GPIO73_GPIO MFP_CFG(GPIO73, AF0) +#define GPIO74_GPIO MFP_CFG(GPIO74, AF0) +#define GPIO75_GPIO MFP_CFG(GPIO75, AF0) +#define GPIO76_GPIO MFP_CFG(GPIO76, AF0) +#define GPIO77_GPIO MFP_CFG(GPIO77, AF0) +#define GPIO78_GPIO MFP_CFG(GPIO78, AF0) +#define GPIO79_GPIO MFP_CFG(GPIO79, AF0) +#define GPIO80_GPIO MFP_CFG(GPIO80, AF0) +#define GPIO81_GPIO MFP_CFG(GPIO81, AF0) +#define GPIO82_GPIO MFP_CFG(GPIO82, AF0) +#define GPIO83_GPIO MFP_CFG(GPIO83, AF0) +#define GPIO84_GPIO MFP_CFG(GPIO84, AF0) +#define GPIO85_GPIO MFP_CFG(GPIO85, AF0) +#define GPIO86_GPIO MFP_CFG(GPIO86, AF0) +#define GPIO87_GPIO MFP_CFG(GPIO87, AF0) +#define GPIO88_GPIO MFP_CFG(GPIO88, AF0) +#define GPIO89_GPIO MFP_CFG(GPIO89, AF0) +#define GPIO90_GPIO MFP_CFG(GPIO90, AF0) +#define GPIO91_GPIO MFP_CFG(GPIO91, AF0) +#define GPIO92_GPIO MFP_CFG(GPIO92, AF0) +#define GPIO93_GPIO MFP_CFG(GPIO93, AF0) +#define GPIO94_GPIO MFP_CFG(GPIO94, AF0) +#define GPIO95_GPIO MFP_CFG(GPIO95, AF0) +#define GPIO96_GPIO MFP_CFG(GPIO96, AF0) +#define GPIO97_GPIO MFP_CFG(GPIO97, AF0) +#define GPIO98_GPIO MFP_CFG(GPIO98, AF0) +#define GPIO99_GPIO MFP_CFG(GPIO99, AF0) +#define GPIO100_GPIO MFP_CFG(GPIO100, AF0) +#define GPIO101_GPIO MFP_CFG(GPIO101, AF0) +#define GPIO102_GPIO MFP_CFG(GPIO102, AF0) +#define GPIO103_GPIO MFP_CFG(GPIO103, AF0) +#define GPIO104_GPIO MFP_CFG(GPIO104, AF0) +#define GPIO105_GPIO MFP_CFG(GPIO105, AF0) +#define GPIO106_GPIO MFP_CFG(GPIO106, AF0) +#define GPIO107_GPIO MFP_CFG(GPIO107, AF0) +#define GPIO108_GPIO MFP_CFG(GPIO108, AF0) +#define GPIO109_GPIO MFP_CFG(GPIO109, AF0) +#define GPIO110_GPIO MFP_CFG(GPIO110, AF0) +#define GPIO111_GPIO MFP_CFG(GPIO111, AF0) +#define GPIO112_GPIO MFP_CFG(GPIO112, AF0) +#define GPIO113_GPIO MFP_CFG(GPIO113, AF0) +#define GPIO114_GPIO MFP_CFG(GPIO114, AF0) +#define GPIO115_GPIO MFP_CFG(GPIO115, AF0) +#define GPIO116_GPIO MFP_CFG(GPIO116, AF0) +#define GPIO117_GPIO MFP_CFG(GPIO117, AF0) +#define GPIO118_GPIO MFP_CFG(GPIO118, AF0) +#define GPIO119_GPIO MFP_CFG(GPIO119, AF0) +#define GPIO120_GPIO MFP_CFG(GPIO120, AF0) +#define GPIO121_GPIO MFP_CFG(GPIO121, AF0) +#define GPIO122_GPIO MFP_CFG(GPIO122, AF0) + +/* DFI */ +#define GPIO0_DFI_D15 MFP_CFG(GPIO0, AF0) +#define GPIO1_DFI_D14 MFP_CFG(GPIO1, AF0) +#define GPIO2_DFI_D13 MFP_CFG(GPIO2, AF0) +#define GPIO3_DFI_D12 MFP_CFG(GPIO3, AF0) +#define GPIO4_DFI_D11 MFP_CFG(GPIO4, AF0) +#define GPIO5_DFI_D10 MFP_CFG(GPIO5, AF0) +#define GPIO6_DFI_D9 MFP_CFG(GPIO6, AF0) +#define GPIO7_DFI_D8 MFP_CFG(GPIO7, AF0) +#define GPIO8_DFI_D7 MFP_CFG(GPIO8, AF0) +#define GPIO9_DFI_D6 MFP_CFG(GPIO9, AF0) +#define GPIO10_DFI_D5 MFP_CFG(GPIO10, AF0) +#define GPIO11_DFI_D4 MFP_CFG(GPIO11, AF0) +#define GPIO12_DFI_D3 MFP_CFG(GPIO12, AF0) +#define GPIO13_DFI_D2 MFP_CFG(GPIO13, AF0) +#define GPIO14_DFI_D1 MFP_CFG(GPIO14, AF0) +#define GPIO15_DFI_D0 MFP_CFG(GPIO15, AF0) + +#define GPIO30_DFI_ADDR0 MFP_CFG(GPIO30, AF0) +#define GPIO31_DFI_ADDR1 MFP_CFG(GPIO31, AF0) +#define GPIO32_DFI_ADDR2 MFP_CFG(GPIO32, AF0) +#define GPIO33_DFI_ADDR3 MFP_CFG(GPIO33, AF0) + +/* NAND */ +#define GPIO16_ND_nCS0 MFP_CFG(GPIO16, AF1) +#define GPIO17_ND_nWE MFP_CFG(GPIO17, AF0) +#define GPIO21_ND_ALE MFP_CFG(GPIO21, AF0) +#define GPIO22_ND_CLE MFP_CFG(GPIO22, AF0) +#define GPIO24_ND_nRE MFP_CFG(GPIO24, AF0) +#define GPIO26_ND_RnB1 MFP_CFG(GPIO26, AF1) +#define GPIO27_ND_RnB2 MFP_CFG(GPIO27, AF1) + +/* Static Memory Controller */ +#define GPIO18_SMC_nCS0 MFP_CFG(GPIO18, AF3) +#define GPIO18_SMC_nCS1 MFP_CFG(GPIO18, AF2) +#define GPIO16_SMC_nCS0 MFP_CFG(GPIO16, AF2) +#define GPIO16_SMC_nCS1 MFP_CFG(GPIO16, AF3) +#define GPIO19_SMC_nCS0 MFP_CFG(GPIO19, AF0) +#define GPIO20_SMC_nCS1 MFP_CFG(GPIO20, AF2) +#define GPIO23_SMC_nLUA MFP_CFG(GPIO23, AF0) +#define GPIO25_SMC_nLLA MFP_CFG(GPIO25, AF0) +#define GPIO27_SMC_IRQ MFP_CFG(GPIO27, AF0) +#define GPIO28_SMC_RDY MFP_CFG(GPIO28, AF0) +#define GPIO29_SMC_SCLK MFP_CFG(GPIO29, AF0) +#define GPIO34_SMC_nCS1 MFP_CFG(GPIO34, AF2) +#define GPIO35_SMC_BE1 MFP_CFG(GPIO35, AF2) +#define GPIO36_SMC_BE2 MFP_CFG(GPIO36, AF2) + +/* Compact Flash */ +#define GPIO19_CF_nCE1 MFP_CFG(GPIO19, AF3) +#define GPIO20_CF_nCE2 MFP_CFG(GPIO20, AF3) +#define GPIO23_CF_nALE MFP_CFG(GPIO23, AF3) +#define GPIO25_CF_nRESET MFP_CFG(GPIO25, AF3) +#define GPIO28_CF_RDY MFP_CFG(GPIO28, AF3) +#define GPIO29_CF_STSCH MFP_CFG(GPIO29, AF3) +#define GPIO30_CF_nREG MFP_CFG(GPIO30, AF3) +#define GPIO31_CF_nIOIS16 MFP_CFG(GPIO31, AF3) +#define GPIO32_CF_nCD1 MFP_CFG(GPIO32, AF3) +#define GPIO33_CF_nCD2 MFP_CFG(GPIO33, AF3) + +/* UART1 */ +#define GPIO107_UART1_TXD MFP_CFG_DRV(GPIO107, AF1, FAST) +#define GPIO107_UART1_RXD MFP_CFG_DRV(GPIO107, AF2, FAST) +#define GPIO108_UART1_RXD MFP_CFG_DRV(GPIO108, AF1, FAST) +#define GPIO108_UART1_TXD MFP_CFG_DRV(GPIO108, AF2, FAST) +#define GPIO109_UART1_CTS MFP_CFG(GPIO109, AF1) +#define GPIO109_UART1_RTS MFP_CFG(GPIO109, AF2) +#define GPIO110_UART1_RTS MFP_CFG(GPIO110, AF1) +#define GPIO110_UART1_CTS MFP_CFG(GPIO110, AF2) +#define GPIO111_UART1_RI MFP_CFG(GPIO111, AF1) +#define GPIO111_UART1_DSR MFP_CFG(GPIO111, AF2) +#define GPIO112_UART1_DTR MFP_CFG(GPIO111, AF1) +#define GPIO112_UART1_DCD MFP_CFG(GPIO112, AF2) + +/* MMC1 */ +#define GPIO37_MMC1_DAT7 MFP_CFG(GPIO37, AF1) +#define GPIO38_MMC1_DAT6 MFP_CFG(GPIO38, AF1) +#define GPIO54_MMC1_DAT5 MFP_CFG(GPIO54, AF1) +#define GPIO48_MMC1_DAT4 MFP_CFG(GPIO48, AF1) +#define GPIO51_MMC1_DAT3 MFP_CFG(GPIO51, AF1) +#define GPIO52_MMC1_DAT2 MFP_CFG(GPIO52, AF1) +#define GPIO40_MMC1_DAT1 MFP_CFG(GPIO40, AF1) +#define GPIO41_MMC1_DAT0 MFP_CFG(GPIO41, AF1) +#define GPIO49_MMC1_CMD MFP_CFG(GPIO49, AF1) +#define GPIO43_MMC1_CLK MFP_CFG(GPIO43, AF1) +#define GPIO53_MMC1_CD MFP_CFG(GPIO53, AF1) +#define GPIO46_MMC1_WP MFP_CFG(GPIO46, AF1) + +/* LCD */ +#define GPIO84_LCD_CS MFP_CFG(GPIO84, AF1) +#define GPIO60_LCD_DD0 MFP_CFG(GPIO60, AF1) +#define GPIO61_LCD_DD1 MFP_CFG(GPIO61, AF1) +#define GPIO70_LCD_DD10 MFP_CFG(GPIO70, AF1) +#define GPIO71_LCD_DD11 MFP_CFG(GPIO71, AF1) +#define GPIO72_LCD_DD12 MFP_CFG(GPIO72, AF1) +#define GPIO73_LCD_DD13 MFP_CFG(GPIO73, AF1) +#define GPIO74_LCD_DD14 MFP_CFG(GPIO74, AF1) +#define GPIO75_LCD_DD15 MFP_CFG(GPIO75, AF1) +#define GPIO76_LCD_DD16 MFP_CFG(GPIO76, AF1) +#define GPIO77_LCD_DD17 MFP_CFG(GPIO77, AF1) +#define GPIO78_LCD_DD18 MFP_CFG(GPIO78, AF1) +#define GPIO79_LCD_DD19 MFP_CFG(GPIO79, AF1) +#define GPIO62_LCD_DD2 MFP_CFG(GPIO62, AF1) +#define GPIO80_LCD_DD20 MFP_CFG(GPIO80, AF1) +#define GPIO81_LCD_DD21 MFP_CFG(GPIO81, AF1) +#define GPIO82_LCD_DD22 MFP_CFG(GPIO82, AF1) +#define GPIO83_LCD_DD23 MFP_CFG(GPIO83, AF1) +#define GPIO63_LCD_DD3 MFP_CFG(GPIO63, AF1) +#define GPIO64_LCD_DD4 MFP_CFG(GPIO64, AF1) +#define GPIO65_LCD_DD5 MFP_CFG(GPIO65, AF1) +#define GPIO66_LCD_DD6 MFP_CFG(GPIO66, AF1) +#define GPIO67_LCD_DD7 MFP_CFG(GPIO67, AF1) +#define GPIO68_LCD_DD8 MFP_CFG(GPIO68, AF1) +#define GPIO69_LCD_DD9 MFP_CFG(GPIO69, AF1) +#define GPIO59_LCD_DENA_BIAS MFP_CFG(GPIO59, AF1) +#define GPIO56_LCD_FCLK_RD MFP_CFG(GPIO56, AF1) +#define GPIO57_LCD_LCLK_A0 MFP_CFG(GPIO57, AF1) +#define GPIO58_LCD_PCLK_WR MFP_CFG(GPIO58, AF1) +#define GPIO85_LCD_VSYNC MFP_CFG(GPIO85, AF1) + +/* I2S */ +#define GPIO113_I2S_MCLK MFP_CFG(GPIO113,AF6) +#define GPIO114_I2S_FRM MFP_CFG(GPIO114,AF1) +#define GPIO115_I2S_BCLK MFP_CFG(GPIO115,AF1) +#define GPIO116_I2S_RXD MFP_CFG(GPIO116,AF2) +#define GPIO117_I2S_TXD MFP_CFG(GPIO117,AF2) + +#endif /* __ASM_MACH_MFP_PXA168_H */ diff --git a/arch/arm/mach-mmp/include/mach/mfp.h b/arch/arm/mach-mmp/include/mach/mfp.h new file mode 100644 index 00000000000..277ea4cd0f9 --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/mfp.h @@ -0,0 +1,37 @@ +#ifndef __ASM_MACH_MFP_H +#define __ASM_MACH_MFP_H + +#include + +/* + * NOTE: the MFPR register bit definitions on PXA168 processor lines are a + * bit different from those on PXA3xx. Bit [7:10] are now reserved, which + * were SLEEP_OE_N, SLEEP_DATA, SLEEP_SEL and the LSB of DRIVE bits. + * + * To cope with this difference and re-use the pxa3xx mfp code as much as + * possible, we make the following compromise: + * + * 1. SLEEP_OE_N will always be programmed to '1' (by MFP_LPM_FLOAT) + * 2. DRIVE strength definitions redefined to include the reserved bit10 + * 3. Override MFP_CFG() and MFP_CFG_DRV() + * 4. Drop the use of MFP_CFG_LPM() and MFP_CFG_X() + */ + +#define MFP_DRIVE_VERY_SLOW (0x0 << 13) +#define MFP_DRIVE_SLOW (0x2 << 13) +#define MFP_DRIVE_MEDIUM (0x4 << 13) +#define MFP_DRIVE_FAST (0x8 << 13) + +#undef MFP_CFG +#undef MFP_CFG_DRV +#undef MFP_CFG_LPM +#undef MFP_CFG_X +#undef MFP_CFG_DEFAULT + +#define MFP_CFG(pin, af) \ + (MFP_LPM_FLOAT | MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_DRIVE_MEDIUM) + +#define MFP_CFG_DRV(pin, af, drv) \ + (MFP_LPM_FLOAT | MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_DRIVE_##drv) + +#endif /* __ASM_MACH_MFP_H */ diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c index 1774682e988..ae924468658 100644 --- a/arch/arm/mach-mmp/pxa168.c +++ b/arch/arm/mach-mmp/pxa168.c @@ -23,10 +23,23 @@ #include #include #include +#include #include "common.h" #include "clock.h" +#define MFPR_VIRT_BASE (APB_VIRT_BASE + 0x1e000) + +static struct mfp_addr_map pxa168_mfp_addr_map[] __initdata = +{ + MFP_ADDR_X(GPIO0, GPIO36, 0x04c), + MFP_ADDR_X(GPIO37, GPIO55, 0x000), + MFP_ADDR_X(GPIO56, GPIO123, 0x0e0), + MFP_ADDR_X(GPIO124, GPIO127, 0x0f4), + + MFP_ADDR_END, +}; + #define APMASK(i) (GPIO_REGS_VIRT + BANK_OFF(i) + 0x09c) static void __init pxa168_init_gpio(void) @@ -62,6 +75,8 @@ static struct clk_lookup pxa168_clkregs[] = { static int __init pxa168_init(void) { if (cpu_is_pxa168()) { + mfp_init_base(MFPR_VIRT_BASE); + mfp_init_addr(pxa168_mfp_addr_map); pxa_init_dma(IRQ_PXA168_DMA_INT0, 32); clks_register(ARRAY_AND_SIZE(pxa168_clkregs)); } -- GitLab From 56422554d29e3761b095b3e27646e8ee03fae41a Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Thu, 5 Feb 2009 13:42:47 +0800 Subject: [PATCH 3916/4982] [ARM] pxa: allow reuse of serial driver for pxa168 Signed-off-by: Eric Miao --- drivers/serial/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 7d7f576da20..9be11b0963f 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -628,7 +628,7 @@ config SERIAL_MPSC_CONSOLE config SERIAL_PXA bool "PXA serial port support" - depends on ARM && ARCH_PXA + depends on ARCH_PXA || ARCH_MMP select SERIAL_CORE help If you have a machine based on an Intel XScale PXA2xx CPU you -- GitLab From 9c291f0f835dc8349afc21d6311cb531140f6977 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 10 Feb 2009 10:35:25 +0800 Subject: [PATCH 3917/4982] [ARM] pxa/aspenite: add support for console uart Signed-off-by: Eric Miao --- arch/arm/mach-mmp/aspenite.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c index e8caf58e004..a9efa5cadbe 100644 --- a/arch/arm/mach-mmp/aspenite.c +++ b/arch/arm/mach-mmp/aspenite.c @@ -10,15 +10,27 @@ */ #include +#include #include #include #include +#include +#include #include "common.h" +static unsigned long common_pin_config[] __initdata = { + /* UART1 */ + GPIO107_UART1_RXD, + GPIO108_UART1_TXD, +}; + static void __init common_init(void) { + mfp_config(ARRAY_AND_SIZE(common_pin_config)); + + pxa168_add_uart(1); } MACHINE_START(ASPENITE, "PXA168-based Aspenite Development Platform") -- GitLab From a6b993c6b5183fe2af98569cbb7dd8add01b8deb Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Wed, 18 Feb 2009 16:38:22 +0800 Subject: [PATCH 3918/4982] [ARM] pxa/aspenite: add support for debug ethernet Signed-off-by: Zhangfei Gao Signed-off-by: Eric Miao --- arch/arm/mach-mmp/aspenite.c | 63 ++++++++++++++++++++++++++++++++++++ drivers/net/smc91x.h | 1 + 2 files changed, 64 insertions(+) diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c index a9efa5cadbe..4562452d407 100644 --- a/arch/arm/mach-mmp/aspenite.c +++ b/arch/arm/mach-mmp/aspenite.c @@ -11,26 +11,89 @@ #include #include +#include +#include #include #include #include #include #include +#include #include "common.h" static unsigned long common_pin_config[] __initdata = { + /* Data Flash Interface */ + GPIO0_DFI_D15, + GPIO1_DFI_D14, + GPIO2_DFI_D13, + GPIO3_DFI_D12, + GPIO4_DFI_D11, + GPIO5_DFI_D10, + GPIO6_DFI_D9, + GPIO7_DFI_D8, + GPIO8_DFI_D7, + GPIO9_DFI_D6, + GPIO10_DFI_D5, + GPIO11_DFI_D4, + GPIO12_DFI_D3, + GPIO13_DFI_D2, + GPIO14_DFI_D1, + GPIO15_DFI_D0, + + /* Static Memory Controller */ + GPIO18_SMC_nCS0, + GPIO34_SMC_nCS1, + GPIO23_SMC_nLUA, + GPIO25_SMC_nLLA, + GPIO28_SMC_RDY, + GPIO29_SMC_SCLK, + GPIO35_SMC_BE1, + GPIO36_SMC_BE2, + GPIO27_GPIO, /* Ethernet IRQ */ + /* UART1 */ GPIO107_UART1_RXD, GPIO108_UART1_TXD, }; +static struct smc91x_platdata smc91x_info = { + .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT, +}; + +static struct resource smc91x_resources[] = { + [0] = { + .start = SMC_CS1_PHYS_BASE + 0x300, + .end = SMC_CS1_PHYS_BASE + 0xfffff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = gpio_to_irq(27), + .end = gpio_to_irq(27), + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, + } +}; + +static struct platform_device smc91x_device = { + .name = "smc91x", + .id = 0, + .dev = { + .platform_data = &smc91x_info, + }, + .num_resources = ARRAY_SIZE(smc91x_resources), + .resource = smc91x_resources, +}; + static void __init common_init(void) { mfp_config(ARRAY_AND_SIZE(common_pin_config)); + /* on-chip devices */ pxa168_add_uart(1); + + /* off-chip devices */ + platform_device_register(&smc91x_device); } MACHINE_START(ASPENITE, "PXA168-based Aspenite Development Platform") diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 4d689b59c58..1083e2c5dec 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -44,6 +44,7 @@ defined(CONFIG_MACH_MAINSTONE) ||\ defined(CONFIG_MACH_ZYLONITE) ||\ defined(CONFIG_MACH_LITTLETON) ||\ + defined(CONFIG_MACH_ZYLONITE2) ||\ defined(CONFIG_ARCH_VIPER) #include -- GitLab From 14c6b5e7add9ec393ad61bceb6106b47c7f14bd3 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Fri, 20 Mar 2009 12:50:22 +0800 Subject: [PATCH 3919/4982] [ARM] pxa: add base support for Marvell PXA910 Signed-off-by: Bin Yang Signed-off-by: Eric Miao --- arch/arm/Kconfig | 4 +- arch/arm/mach-mmp/Kconfig | 8 +- arch/arm/mach-mmp/Makefile | 1 + arch/arm/mach-mmp/common.h | 2 + arch/arm/mach-mmp/include/mach/cputype.h | 9 ++ arch/arm/mach-mmp/include/mach/devices.h | 10 ++ arch/arm/mach-mmp/include/mach/irqs.h | 61 ++++++++ arch/arm/mach-mmp/include/mach/mfp-pxa910.h | 157 +++++++++++++++++++ arch/arm/mach-mmp/include/mach/pxa910.h | 23 +++ arch/arm/mach-mmp/include/mach/regs-apbc.h | 25 ++++ arch/arm/mach-mmp/pxa910.c | 158 ++++++++++++++++++++ arch/arm/plat-pxa/include/plat/mfp.h | 30 ++++ 12 files changed, 485 insertions(+), 3 deletions(-) create mode 100644 arch/arm/mach-mmp/include/mach/mfp-pxa910.h create mode 100644 arch/arm/mach-mmp/include/mach/pxa910.h create mode 100644 arch/arm/mach-mmp/pxa910.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index daf35d77820..cb4486ad0f7 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -488,7 +488,7 @@ config ARCH_PXA Support for Intel/Marvell's PXA2xx/PXA3xx processor line. config ARCH_MMP - bool "Marvell PXA168" + bool "Marvell PXA168/910" depends on MMU select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB @@ -499,7 +499,7 @@ config ARCH_MMP select TICK_ONESHOT select PLAT_PXA help - Support for Marvell's PXA168 processor line. + Support for Marvell's PXA168/910 processor line. config ARCH_RPC bool "RiscPC" diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig index b5232676355..ba2e377484f 100644 --- a/arch/arm/mach-mmp/Kconfig +++ b/arch/arm/mach-mmp/Kconfig @@ -1,6 +1,6 @@ if ARCH_MMP -menu "Marvell PXA168 Implmentations" +menu "Marvell PXA168/910 Implmentations" config MACH_ASPENITE bool "Marvell's PXA168 Aspenite Development Board" @@ -24,4 +24,10 @@ config CPU_PXA168 help Select code specific to PXA168 +config CPU_PXA910 + bool + select CPU_MOHAWK + help + Select code specific to PXA910 + endif diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile index 0ac7644ec99..93d2bc7459d 100644 --- a/arch/arm/mach-mmp/Makefile +++ b/arch/arm/mach-mmp/Makefile @@ -6,6 +6,7 @@ obj-y += common.o clock.o devices.o irq.o time.o # SoC support obj-$(CONFIG_CPU_PXA168) += pxa168.o +obj-$(CONFIG_CPU_PXA910) += pxa910.o # board support obj-$(CONFIG_MACH_ASPENITE) += aspenite.o diff --git a/arch/arm/mach-mmp/common.h b/arch/arm/mach-mmp/common.h index bf7a6a492de..c33fbbc4941 100644 --- a/arch/arm/mach-mmp/common.h +++ b/arch/arm/mach-mmp/common.h @@ -5,7 +5,9 @@ struct sys_timer; extern void timer_init(int irq); extern struct sys_timer pxa168_timer; +extern struct sys_timer pxa910_timer; extern void __init pxa168_init_irq(void); +extern void __init pxa910_init_irq(void); extern void __init icu_init_irq(void); extern void __init pxa_map_io(void); diff --git a/arch/arm/mach-mmp/include/mach/cputype.h b/arch/arm/mach-mmp/include/mach/cputype.h index 4ceed7a5075..25e797b0908 100644 --- a/arch/arm/mach-mmp/include/mach/cputype.h +++ b/arch/arm/mach-mmp/include/mach/cputype.h @@ -7,6 +7,7 @@ * CPU Stepping OLD_ID CPU_ID CHIP_ID * * PXA168 A0 0x41159263 0x56158400 0x00A0A333 + * PXA910 Y0 0x41159262 0x56158000 0x00F0C910 */ #ifdef CONFIG_CPU_PXA168 @@ -16,6 +17,14 @@ # define __cpu_is_pxa168(id) (0) #endif +#ifdef CONFIG_CPU_PXA910 +# define __cpu_is_pxa910(id) \ + ({ unsigned int _id = ((id) >> 8) & 0xff; _id == 0x80; }) +#else +# define __cpu_is_pxa910(id) (0) +#endif + #define cpu_is_pxa168() ({ __cpu_is_pxa168(read_cpuid_id()); }) +#define cpu_is_pxa910() ({ __cpu_is_pxa910(read_cpuid_id()); }) #endif /* __ASM_MACH_CPUTYPE_H */ diff --git a/arch/arm/mach-mmp/include/mach/devices.h b/arch/arm/mach-mmp/include/mach/devices.h index bc03388d5fd..24585397217 100644 --- a/arch/arm/mach-mmp/include/mach/devices.h +++ b/arch/arm/mach-mmp/include/mach/devices.h @@ -24,4 +24,14 @@ struct pxa_device_desc pxa168_device_##_name __initdata = { \ .dma = { _dma }, \ }; +#define PXA910_DEVICE(_name, _drv, _id, _irq, _start, _size, _dma...) \ +struct pxa_device_desc pxa910_device_##_name __initdata = { \ + .dev_name = "pxa910-" #_name, \ + .drv_name = _drv, \ + .id = _id, \ + .irq = IRQ_PXA910_##_irq, \ + .start = _start, \ + .size = _size, \ + .dma = { _dma }, \ +}; extern int pxa_register_device(struct pxa_device_desc *, void *, size_t); diff --git a/arch/arm/mach-mmp/include/mach/irqs.h b/arch/arm/mach-mmp/include/mach/irqs.h index 91ecb3fbca0..e83e45ebf7a 100644 --- a/arch/arm/mach-mmp/include/mach/irqs.h +++ b/arch/arm/mach-mmp/include/mach/irqs.h @@ -49,6 +49,67 @@ #define IRQ_PXA168_PMU 60 #define IRQ_PXA168_SM_INT 63 +/* + * Interrupt numbers for PXA910 + */ +#define IRQ_PXA910_AIRQ 0 +#define IRQ_PXA910_SSP3 1 +#define IRQ_PXA910_SSP2 2 +#define IRQ_PXA910_SSP1 3 +#define IRQ_PXA910_PMIC_INT 4 +#define IRQ_PXA910_RTC_INT 5 +#define IRQ_PXA910_RTC_ALARM 6 +#define IRQ_PXA910_TWSI0 7 +#define IRQ_PXA910_GPU 8 +#define IRQ_PXA910_KEYPAD 9 +#define IRQ_PXA910_ROTARY 10 +#define IRQ_PXA910_TRACKBALL 11 +#define IRQ_PXA910_ONEWIRE 12 +#define IRQ_PXA910_AP1_TIMER1 13 +#define IRQ_PXA910_AP1_TIMER2 14 +#define IRQ_PXA910_AP1_TIMER3 15 +#define IRQ_PXA910_IPC_AP0 16 +#define IRQ_PXA910_IPC_AP1 17 +#define IRQ_PXA910_IPC_AP2 18 +#define IRQ_PXA910_IPC_AP3 19 +#define IRQ_PXA910_IPC_AP4 20 +#define IRQ_PXA910_IPC_CP0 21 +#define IRQ_PXA910_IPC_CP1 22 +#define IRQ_PXA910_IPC_CP2 23 +#define IRQ_PXA910_IPC_CP3 24 +#define IRQ_PXA910_IPC_CP4 25 +#define IRQ_PXA910_L2_DDR 26 +#define IRQ_PXA910_UART2 27 +#define IRQ_PXA910_UART3 28 +#define IRQ_PXA910_AP2_TIMER1 29 +#define IRQ_PXA910_AP2_TIMER2 30 +#define IRQ_PXA910_CP2_TIMER1 31 +#define IRQ_PXA910_CP2_TIMER2 32 +#define IRQ_PXA910_CP2_TIMER3 33 +#define IRQ_PXA910_GSSP 34 +#define IRQ_PXA910_CP2_WDT 35 +#define IRQ_PXA910_MAIN_PMU 36 +#define IRQ_PXA910_CP_FREQ_CHG 37 +#define IRQ_PXA910_AP_FREQ_CHG 38 +#define IRQ_PXA910_MMC 39 +#define IRQ_PXA910_AEU 40 +#define IRQ_PXA910_LCD 41 +#define IRQ_PXA910_CCIC 42 +#define IRQ_PXA910_IRE 43 +#define IRQ_PXA910_USB1 44 +#define IRQ_PXA910_NAND 45 +#define IRQ_PXA910_HIFI_DMA 46 +#define IRQ_PXA910_DMA_INT0 47 +#define IRQ_PXA910_DMA_INT1 48 +#define IRQ_PXA910_AP_GPIO 49 +#define IRQ_PXA910_AP2_TIMER3 50 +#define IRQ_PXA910_USB2 51 +#define IRQ_PXA910_TWSI1 54 +#define IRQ_PXA910_CP_GPIO 55 +#define IRQ_PXA910_UART1 59 /* Slow UART */ +#define IRQ_PXA910_AP_PMU 60 +#define IRQ_PXA910_SM_INT 63 /* from PinMux */ + #define IRQ_GPIO_START 64 #define IRQ_GPIO_NUM 128 #define IRQ_GPIO(x) (IRQ_GPIO_START + (x)) diff --git a/arch/arm/mach-mmp/include/mach/mfp-pxa910.h b/arch/arm/mach-mmp/include/mach/mfp-pxa910.h new file mode 100644 index 00000000000..48a1cbc7c56 --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/mfp-pxa910.h @@ -0,0 +1,157 @@ +#ifndef __ASM_MACH_MFP_PXA910_H +#define __ASM_MACH_MFP_PXA910_H + +#include + +/* UART2 */ +#define GPIO47_UART2_RXD MFP_CFG(GPIO47, AF6) +#define GPIO48_UART2_TXD MFP_CFG(GPIO48, AF6) + +/* UART3 */ +#define GPIO31_UART3_RXD MFP_CFG(GPIO31, AF4) +#define GPIO32_UART3_TXD MFP_CFG(GPIO32, AF4) + +/*IRDA*/ +#define GPIO51_IRDA_SHDN MFP_CFG(GPIO51, AF0) + +/* SMC */ +#define SM_nCS0_nCS0 MFP_CFG(SM_nCS0, AF0) +#define SM_ADV_SM_ADV MFP_CFG(SM_ADV, AF0) +#define SM_SCLK_SM_SCLK MFP_CFG(SM_SCLK, AF0) +#define SM_SCLK_SM_SCLK MFP_CFG(SM_SCLK, AF0) +#define SM_BE0_SM_BE0 MFP_CFG(SM_BE0, AF1) +#define SM_BE1_SM_BE1 MFP_CFG(SM_BE1, AF1) + +/* I2C */ +#define GPIO53_CI2C_SCL MFP_CFG(GPIO53, AF2) +#define GPIO54_CI2C_SDA MFP_CFG(GPIO54, AF2) + +/* SSP1 (I2S) */ +#define GPIO24_SSP1_SDATA_IN MFP_CFG_DRV(GPIO24, AF1, MEDIUM) +#define GPIO21_SSP1_BITCLK MFP_CFG_DRV(GPIO21, AF1, MEDIUM) +#define GPIO20_SSP1_SYSCLK MFP_CFG_DRV(GPIO20, AF1, MEDIUM) +#define GPIO22_SSP1_SYNC MFP_CFG_DRV(GPIO22, AF1, MEDIUM) +#define GPIO23_SSP1_DATA_OUT MFP_CFG_DRV(GPIO23, AF1, MEDIUM) +#define GPIO124_MN_CLK_OUT MFP_CFG_DRV(GPIO124, AF1, MEDIUM) +#define GPIO123_CLK_REQ MFP_CFG_DRV(GPIO123, AF0, MEDIUM) + +/* DFI */ +#define DF_IO0_ND_IO0 MFP_CFG(DF_IO0, AF0) +#define DF_IO1_ND_IO1 MFP_CFG(DF_IO1, AF0) +#define DF_IO2_ND_IO2 MFP_CFG(DF_IO2, AF0) +#define DF_IO3_ND_IO3 MFP_CFG(DF_IO3, AF0) +#define DF_IO4_ND_IO4 MFP_CFG(DF_IO4, AF0) +#define DF_IO5_ND_IO5 MFP_CFG(DF_IO5, AF0) +#define DF_IO6_ND_IO6 MFP_CFG(DF_IO6, AF0) +#define DF_IO7_ND_IO7 MFP_CFG(DF_IO7, AF0) +#define DF_IO8_ND_IO8 MFP_CFG(DF_IO8, AF0) +#define DF_IO9_ND_IO9 MFP_CFG(DF_IO9, AF0) +#define DF_IO10_ND_IO10 MFP_CFG(DF_IO10, AF0) +#define DF_IO11_ND_IO11 MFP_CFG(DF_IO11, AF0) +#define DF_IO12_ND_IO12 MFP_CFG(DF_IO12, AF0) +#define DF_IO13_ND_IO13 MFP_CFG(DF_IO13, AF0) +#define DF_IO14_ND_IO14 MFP_CFG(DF_IO14, AF0) +#define DF_IO15_ND_IO15 MFP_CFG(DF_IO15, AF0) +#define DF_nCS0_SM_nCS2_nCS0 MFP_CFG(DF_nCS0_SM_nCS2, AF0) +#define DF_ALE_SM_WEn_ND_ALE MFP_CFG(DF_ALE_SM_WEn, AF1) +#define DF_CLE_SM_OEn_ND_CLE MFP_CFG(DF_CLE_SM_OEn, AF0) +#define DF_WEn_DF_WEn MFP_CFG(DF_WEn, AF1) +#define DF_REn_DF_REn MFP_CFG(DF_REn, AF1) +#define DF_RDY0_DF_RDY0 MFP_CFG(DF_RDY0, AF0) + +/*keypad*/ +#define GPIO00_KP_MKIN0 MFP_CFG(GPIO0, AF1) +#define GPIO01_KP_MKOUT0 MFP_CFG(GPIO1, AF1) +#define GPIO02_KP_MKIN1 MFP_CFG(GPIO2, AF1) +#define GPIO03_KP_MKOUT1 MFP_CFG(GPIO3, AF1) +#define GPIO04_KP_MKIN2 MFP_CFG(GPIO4, AF1) +#define GPIO05_KP_MKOUT2 MFP_CFG(GPIO5, AF1) +#define GPIO06_KP_MKIN3 MFP_CFG(GPIO6, AF1) +#define GPIO07_KP_MKOUT3 MFP_CFG(GPIO7, AF1) +#define GPIO08_KP_MKIN4 MFP_CFG(GPIO8, AF1) +#define GPIO09_KP_MKOUT4 MFP_CFG(GPIO9, AF1) +#define GPIO10_KP_MKIN5 MFP_CFG(GPIO10, AF1) +#define GPIO11_KP_MKOUT5 MFP_CFG(GPIO11, AF1) +#define GPIO12_KP_MKIN6 MFP_CFG(GPIO12, AF1) +#define GPIO13_KP_MKOUT6 MFP_CFG(GPIO13, AF1) +#define GPIO14_KP_MKIN7 MFP_CFG(GPIO14, AF1) +#define GPIO15_KP_MKOUT7 MFP_CFG(GPIO15, AF1) +#define GPIO16_KP_DKIN0 MFP_CFG(GPIO16, AF1) +#define GPIO17_KP_DKIN1 MFP_CFG(GPIO17, AF1) +#define GPIO18_KP_DKIN2 MFP_CFG(GPIO18, AF1) +#define GPIO19_KP_DKIN3 MFP_CFG(GPIO19, AF1) + +/* LCD */ +#define GPIO81_LCD_FCLK MFP_CFG(GPIO81, AF1) +#define GPIO82_LCD_LCLK MFP_CFG(GPIO82, AF1) +#define GPIO83_LCD_PCLK MFP_CFG(GPIO83, AF1) +#define GPIO84_LCD_DENA MFP_CFG(GPIO84, AF1) +#define GPIO85_LCD_DD0 MFP_CFG(GPIO85, AF1) +#define GPIO86_LCD_DD1 MFP_CFG(GPIO86, AF1) +#define GPIO87_LCD_DD2 MFP_CFG(GPIO87, AF1) +#define GPIO88_LCD_DD3 MFP_CFG(GPIO88, AF1) +#define GPIO89_LCD_DD4 MFP_CFG(GPIO89, AF1) +#define GPIO90_LCD_DD5 MFP_CFG(GPIO90, AF1) +#define GPIO91_LCD_DD6 MFP_CFG(GPIO91, AF1) +#define GPIO92_LCD_DD7 MFP_CFG(GPIO92, AF1) +#define GPIO93_LCD_DD8 MFP_CFG(GPIO93, AF1) +#define GPIO94_LCD_DD9 MFP_CFG(GPIO94, AF1) +#define GPIO95_LCD_DD10 MFP_CFG(GPIO95, AF1) +#define GPIO96_LCD_DD11 MFP_CFG(GPIO96, AF1) +#define GPIO97_LCD_DD12 MFP_CFG(GPIO97, AF1) +#define GPIO98_LCD_DD13 MFP_CFG(GPIO98, AF1) +#define GPIO100_LCD_DD14 MFP_CFG(GPIO100, AF1) +#define GPIO101_LCD_DD15 MFP_CFG(GPIO101, AF1) +#define GPIO102_LCD_DD16 MFP_CFG(GPIO102, AF1) +#define GPIO103_LCD_DD17 MFP_CFG(GPIO103, AF1) +#define GPIO104_LCD_DD18 MFP_CFG(GPIO104, AF1) +#define GPIO105_LCD_DD19 MFP_CFG(GPIO105, AF1) +#define GPIO106_LCD_DD20 MFP_CFG(GPIO106, AF1) +#define GPIO107_LCD_DD21 MFP_CFG(GPIO107, AF1) +#define GPIO108_LCD_DD22 MFP_CFG(GPIO108, AF1) +#define GPIO109_LCD_DD23 MFP_CFG(GPIO109, AF1) + +#define GPIO104_LCD_SPIDOUT MFP_CFG(GPIO104, AF3) +#define GPIO105_LCD_SPIDIN MFP_CFG(GPIO105, AF3) +#define GPIO107_LCD_CS1 MFP_CFG(GPIO107, AF3) +#define GPIO108_LCD_DCLK MFP_CFG(GPIO108, AF3) + +#define GPIO106_LCD_RESET MFP_CFG(GPIO106, AF0) + +/*smart panel*/ +#define GPIO82_LCD_A0 MFP_CFG(GPIO82, AF0) +#define GPIO83_LCD_WR MFP_CFG(GPIO83, AF0) +#define GPIO103_LCD_CS MFP_CFG(GPIO103, AF0) + +/*1wire*/ +#define GPIO106_1WIRE MFP_CFG(GPIO106, AF3) + +/*CCIC*/ +#define GPIO67_CCIC_IN7 MFP_CFG_DRV(GPIO67, AF1, MEDIUM) +#define GPIO68_CCIC_IN6 MFP_CFG_DRV(GPIO68, AF1, MEDIUM) +#define GPIO69_CCIC_IN5 MFP_CFG_DRV(GPIO69, AF1, MEDIUM) +#define GPIO70_CCIC_IN4 MFP_CFG_DRV(GPIO70, AF1, MEDIUM) +#define GPIO71_CCIC_IN3 MFP_CFG_DRV(GPIO71, AF1, MEDIUM) +#define GPIO72_CCIC_IN2 MFP_CFG_DRV(GPIO72, AF1, MEDIUM) +#define GPIO73_CCIC_IN1 MFP_CFG_DRV(GPIO73, AF1, MEDIUM) +#define GPIO74_CCIC_IN0 MFP_CFG_DRV(GPIO74, AF1, MEDIUM) +#define GPIO75_CAM_HSYNC MFP_CFG_DRV(GPIO75, AF1, MEDIUM) +#define GPIO76_CAM_VSYNC MFP_CFG_DRV(GPIO76, AF1, MEDIUM) +#define GPIO77_CAM_MCLK MFP_CFG_DRV(GPIO77, AF1, MEDIUM) +#define GPIO78_CAM_PCLK MFP_CFG_DRV(GPIO78, AF1, MEDIUM) + +/* MMC1 */ +#define MMC1_DAT7_MMC1_DAT7 MFP_CFG_DRV(MMC1_DAT7, AF0, MEDIUM) +#define MMC1_DAT6_MMC1_DAT6 MFP_CFG_DRV(MMC1_DAT6, AF0, MEDIUM) +#define MMC1_DAT5_MMC1_DAT5 MFP_CFG_DRV(MMC1_DAT5, AF0, MEDIUM) +#define MMC1_DAT4_MMC1_DAT4 MFP_CFG_DRV(MMC1_DAT4, AF0, MEDIUM) +#define MMC1_DAT3_MMC1_DAT3 MFP_CFG_DRV(MMC1_DAT3, AF0, MEDIUM) +#define MMC1_DAT2_MMC1_DAT2 MFP_CFG_DRV(MMC1_DAT2, AF0, MEDIUM) +#define MMC1_DAT1_MMC1_DAT1 MFP_CFG_DRV(MMC1_DAT1, AF0, MEDIUM) +#define MMC1_DAT0_MMC1_DAT0 MFP_CFG_DRV(MMC1_DAT0, AF0, MEDIUM) +#define MMC1_CMD_MMC1_CMD MFP_CFG_DRV(MMC1_CMD, AF0, MEDIUM) +#define MMC1_CLK_MMC1_CLK MFP_CFG_DRV(MMC1_CLK, AF0, MEDIUM) +#define MMC1_CD_MMC1_CD MFP_CFG_DRV(MMC1_CD, AF0, MEDIUM) +#define MMC1_WP_MMC1_WP MFP_CFG_DRV(MMC1_WP, AF0, MEDIUM) + +#endif /* __ASM_MACH MFP_PXA910_H */ diff --git a/arch/arm/mach-mmp/include/mach/pxa910.h b/arch/arm/mach-mmp/include/mach/pxa910.h new file mode 100644 index 00000000000..b7aeaf574c3 --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/pxa910.h @@ -0,0 +1,23 @@ +#ifndef __ASM_MACH_PXA910_H +#define __ASM_MACH_PXA910_H + +#include + +extern struct pxa_device_desc pxa910_device_uart1; +extern struct pxa_device_desc pxa910_device_uart2; + +static inline int pxa910_add_uart(int id) +{ + struct pxa_device_desc *d = NULL; + + switch (id) { + case 1: d = &pxa910_device_uart1; break; + case 2: d = &pxa910_device_uart2; break; + } + + if (d == NULL) + return -EINVAL; + + return pxa_register_device(d, NULL, 0); +} +#endif /* __ASM_MACH_PXA910_H */ diff --git a/arch/arm/mach-mmp/include/mach/regs-apbc.h b/arch/arm/mach-mmp/include/mach/regs-apbc.h index e0ffae59487..c6b8c9dc202 100644 --- a/arch/arm/mach-mmp/include/mach/regs-apbc.h +++ b/arch/arm/mach-mmp/include/mach/regs-apbc.h @@ -42,6 +42,31 @@ #define APBC_PXA168_UART3 APBC_REG(0x070) #define APBC_PXA168_AC97 APBC_REG(0x084) +/* + * APB Clock register offsets for PXA910 + */ +#define APBC_PXA910_UART0 APBC_REG(0x000) +#define APBC_PXA910_UART1 APBC_REG(0x004) +#define APBC_PXA910_GPIO APBC_REG(0x008) +#define APBC_PXA910_PWM0 APBC_REG(0x00c) +#define APBC_PXA910_PWM1 APBC_REG(0x010) +#define APBC_PXA910_PWM2 APBC_REG(0x014) +#define APBC_PXA910_PWM3 APBC_REG(0x018) +#define APBC_PXA910_SSP1 APBC_REG(0x01c) +#define APBC_PXA910_SSP2 APBC_REG(0x020) +#define APBC_PXA910_IPC APBC_REG(0x024) +#define APBC_PXA910_TWSI0 APBC_REG(0x02c) +#define APBC_PXA910_KPC APBC_REG(0x030) +#define APBC_PXA910_TIMERS APBC_REG(0x034) +#define APBC_PXA910_TBROT APBC_REG(0x038) +#define APBC_PXA910_AIB APBC_REG(0x03c) +#define APBC_PXA910_SW_JTAG APBC_REG(0x040) +#define APBC_PXA910_TIMERS1 APBC_REG(0x044) +#define APBC_PXA910_ONEWIRE APBC_REG(0x048) +#define APBC_PXA910_SSP3 APBC_REG(0x04c) +#define APBC_PXA910_ASFAR APBC_REG(0x050) +#define APBC_PXA910_ASSAR APBC_REG(0x054) + /* Common APB clock register bit definitions */ #define APBC_APBCLK (1 << 0) /* APB Bus Clock Enable */ #define APBC_FNCLK (1 << 1) /* Functional Clock Enable */ diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c new file mode 100644 index 00000000000..453f8f7758b --- /dev/null +++ b/arch/arm/mach-mmp/pxa910.c @@ -0,0 +1,158 @@ +/* + * linux/arch/arm/mach-mmp/pxa910.c + * + * Code specific to PXA910 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "clock.h" + +#define MFPR_VIRT_BASE (APB_VIRT_BASE + 0x1e000) + +static struct mfp_addr_map pxa910_mfp_addr_map[] __initdata = +{ + MFP_ADDR_X(GPIO0, GPIO54, 0xdc), + MFP_ADDR_X(GPIO67, GPIO98, 0x1b8), + MFP_ADDR_X(GPIO100, GPIO109, 0x238), + + MFP_ADDR(GPIO123, 0xcc), + MFP_ADDR(GPIO124, 0xd0), + + MFP_ADDR(DF_IO0, 0x40), + MFP_ADDR(DF_IO1, 0x3c), + MFP_ADDR(DF_IO2, 0x38), + MFP_ADDR(DF_IO3, 0x34), + MFP_ADDR(DF_IO4, 0x30), + MFP_ADDR(DF_IO5, 0x2c), + MFP_ADDR(DF_IO6, 0x28), + MFP_ADDR(DF_IO7, 0x24), + MFP_ADDR(DF_IO8, 0x20), + MFP_ADDR(DF_IO9, 0x1c), + MFP_ADDR(DF_IO10, 0x18), + MFP_ADDR(DF_IO11, 0x14), + MFP_ADDR(DF_IO12, 0x10), + MFP_ADDR(DF_IO13, 0xc), + MFP_ADDR(DF_IO14, 0x8), + MFP_ADDR(DF_IO15, 0x4), + + MFP_ADDR(DF_nCS0_SM_nCS2, 0x44), + MFP_ADDR(DF_nCS1_SM_nCS3, 0x48), + MFP_ADDR(SM_nCS0, 0x4c), + MFP_ADDR(SM_nCS1, 0x50), + MFP_ADDR(DF_WEn, 0x54), + MFP_ADDR(DF_REn, 0x58), + MFP_ADDR(DF_CLE_SM_OEn, 0x5c), + MFP_ADDR(DF_ALE_SM_WEn, 0x60), + MFP_ADDR(SM_SCLK, 0x64), + MFP_ADDR(DF_RDY0, 0x68), + MFP_ADDR(SM_BE0, 0x6c), + MFP_ADDR(SM_BE1, 0x70), + MFP_ADDR(SM_ADV, 0x74), + MFP_ADDR(DF_RDY1, 0x78), + MFP_ADDR(SM_ADVMUX, 0x7c), + MFP_ADDR(SM_RDY, 0x80), + + MFP_ADDR_X(MMC1_DAT7, MMC1_WP, 0x84), + + MFP_ADDR_END, +}; + +#define APMASK(i) (GPIO_REGS_VIRT + BANK_OFF(i) + 0x09c) + +static void __init pxa910_init_gpio(void) +{ + int i; + + /* enable GPIO clock */ + __raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_PXA910_GPIO); + + /* unmask GPIO edge detection for all 4 banks - APMASKx */ + for (i = 0; i < 4; i++) + __raw_writel(0xffffffff, APMASK(i)); + + pxa_init_gpio(IRQ_PXA910_AP_GPIO, 0, 127, NULL); +} + +void __init pxa910_init_irq(void) +{ + icu_init_irq(); + pxa910_init_gpio(); +} + +/* APB peripheral clocks */ +static APBC_CLK(uart1, PXA910_UART0, 1, 14745600); +static APBC_CLK(uart2, PXA910_UART1, 1, 14745600); + +/* device and clock bindings */ +static struct clk_lookup pxa910_clkregs[] = { + INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL), + INIT_CLKREG(&clk_uart2, "pxa2xx-uart.1", NULL), +}; + +static int __init pxa910_init(void) +{ + if (cpu_is_pxa910()) { + mfp_init_base(MFPR_VIRT_BASE); + mfp_init_addr(pxa910_mfp_addr_map); + pxa_init_dma(IRQ_PXA910_DMA_INT0, 32); + clks_register(ARRAY_AND_SIZE(pxa910_clkregs)); + } + + return 0; +} +postcore_initcall(pxa910_init); + +/* system timer - clock enabled, 3.25MHz */ +#define TIMER_CLK_RST (APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(3)) + +static void __init pxa910_timer_init(void) +{ + /* reset and configure */ + __raw_writel(APBC_APBCLK | APBC_RST, APBC_PXA910_TIMERS); + __raw_writel(TIMER_CLK_RST, APBC_PXA910_TIMERS); + + timer_init(IRQ_PXA910_AP1_TIMER1); +} + +struct sys_timer pxa910_timer = { + .init = pxa910_timer_init, +}; + +/* on-chip devices */ + +/* NOTE: there are totally 3 UARTs on PXA910: + * + * UART1 - Slow UART (can be used both by AP and CP) + * UART2/3 - Fast UART + * + * To be backward compatible with the legacy FFUART/BTUART/STUART sequence, + * they are re-ordered as: + * + * pxa910_device_uart1 - UART2 as FFUART + * pxa910_device_uart2 - UART3 as BTUART + * + * UART1 is not used by AP for the moment. + */ +PXA910_DEVICE(uart1, "pxa2xx-uart", 0, UART2, 0xd4017000, 0x30, 21, 22); +PXA910_DEVICE(uart2, "pxa2xx-uart", 1, UART3, 0xd4018000, 0x30, 23, 24); diff --git a/arch/arm/plat-pxa/include/plat/mfp.h b/arch/arm/plat-pxa/include/plat/mfp.h index a22229cde09..64019464c8d 100644 --- a/arch/arm/plat-pxa/include/plat/mfp.h +++ b/arch/arm/plat-pxa/include/plat/mfp.h @@ -209,6 +209,36 @@ enum { MFP_PIN_DF_IO13, MFP_PIN_DF_IO14, MFP_PIN_DF_IO15, + MFP_PIN_DF_nCS0_SM_nCS2, + MFP_PIN_DF_nCS1_SM_nCS3, + MFP_PIN_SM_nCS0, + MFP_PIN_SM_nCS1, + MFP_PIN_DF_WEn, + MFP_PIN_DF_REn, + MFP_PIN_DF_CLE_SM_OEn, + MFP_PIN_DF_ALE_SM_WEn, + MFP_PIN_DF_RDY0, + MFP_PIN_DF_RDY1, + + MFP_PIN_SM_SCLK, + MFP_PIN_SM_BE0, + MFP_PIN_SM_BE1, + MFP_PIN_SM_ADV, + MFP_PIN_SM_ADVMUX, + MFP_PIN_SM_RDY, + + MFP_PIN_MMC1_DAT7, + MFP_PIN_MMC1_DAT6, + MFP_PIN_MMC1_DAT5, + MFP_PIN_MMC1_DAT4, + MFP_PIN_MMC1_DAT3, + MFP_PIN_MMC1_DAT2, + MFP_PIN_MMC1_DAT1, + MFP_PIN_MMC1_DAT0, + MFP_PIN_MMC1_CMD, + MFP_PIN_MMC1_CLK, + MFP_PIN_MMC1_CD, + MFP_PIN_MMC1_WP, /* additional pins on PXA930 */ MFP_PIN_GSIM_UIO, -- GitLab From a3929f31cb2300f1ab190a0168e55bb55222ee40 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Fri, 20 Mar 2009 13:27:30 +0800 Subject: [PATCH 3920/4982] [ARM] pxa: add base support for pxa910-based TavorEVB Signed-off-by: Bin Yang Signed-off-by: Eric Miao --- arch/arm/mach-mmp/Kconfig | 7 +++ arch/arm/mach-mmp/Makefile | 1 + arch/arm/mach-mmp/tavorevb.c | 109 +++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 arch/arm/mach-mmp/tavorevb.c diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig index ba2e377484f..e77db550907 100644 --- a/arch/arm/mach-mmp/Kconfig +++ b/arch/arm/mach-mmp/Kconfig @@ -16,6 +16,13 @@ config MACH_ZYLONITE2 Say 'Y' here if you want to support the Marvell PXA168-based Zylonite2 Development Board. +config MACH_TAVOREVB + bool "Marvell's PXA910 TavorEVB Development Board" + select CPU_PXA910 + help + Say 'Y' here if you want to support the Marvell PXA910-based + TavorEVB Development Board. + endmenu config CPU_PXA168 diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile index 93d2bc7459d..542aafae5b1 100644 --- a/arch/arm/mach-mmp/Makefile +++ b/arch/arm/mach-mmp/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_CPU_PXA910) += pxa910.o # board support obj-$(CONFIG_MACH_ASPENITE) += aspenite.o obj-$(CONFIG_MACH_ZYLONITE2) += aspenite.o +obj-$(CONFIG_MACH_TAVOREVB) += tavorevb.o diff --git a/arch/arm/mach-mmp/tavorevb.c b/arch/arm/mach-mmp/tavorevb.c new file mode 100644 index 00000000000..0e0c9220eab --- /dev/null +++ b/arch/arm/mach-mmp/tavorevb.c @@ -0,0 +1,109 @@ +/* + * linux/arch/arm/mach-mmp/tavorevb.c + * + * Support for the Marvell PXA910-based TavorEVB Development Platform. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * publishhed by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "common.h" + +static unsigned long tavorevb_pin_config[] __initdata = { + /* UART2 */ + GPIO47_UART2_RXD, + GPIO48_UART2_TXD, + + /* SMC */ + SM_nCS0_nCS0, + SM_ADV_SM_ADV, + SM_SCLK_SM_SCLK, + SM_SCLK_SM_SCLK, + SM_BE0_SM_BE0, + SM_BE1_SM_BE1, + + /* DFI */ + DF_IO0_ND_IO0, + DF_IO1_ND_IO1, + DF_IO2_ND_IO2, + DF_IO3_ND_IO3, + DF_IO4_ND_IO4, + DF_IO5_ND_IO5, + DF_IO6_ND_IO6, + DF_IO7_ND_IO7, + DF_IO8_ND_IO8, + DF_IO9_ND_IO9, + DF_IO10_ND_IO10, + DF_IO11_ND_IO11, + DF_IO12_ND_IO12, + DF_IO13_ND_IO13, + DF_IO14_ND_IO14, + DF_IO15_ND_IO15, + DF_nCS0_SM_nCS2_nCS0, + DF_ALE_SM_WEn_ND_ALE, + DF_CLE_SM_OEn_ND_CLE, + DF_WEn_DF_WEn, + DF_REn_DF_REn, + DF_RDY0_DF_RDY0, +}; + +static struct smc91x_platdata tavorevb_smc91x_info = { + .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT, +}; + +static struct resource smc91x_resources[] = { + [0] = { + .start = SMC_CS1_PHYS_BASE + 0x300, + .end = SMC_CS1_PHYS_BASE + 0xfffff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = gpio_to_irq(80), + .end = gpio_to_irq(80), + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, + } +}; + +static struct platform_device smc91x_device = { + .name = "smc91x", + .id = 0, + .dev = { + .platform_data = &tavorevb_smc91x_info, + }, + .num_resources = ARRAY_SIZE(smc91x_resources), + .resource = smc91x_resources, +}; + +static void __init tavorevb_init(void) +{ + mfp_config(ARRAY_AND_SIZE(tavorevb_pin_config)); + + /* on-chip devices */ + pxa910_add_uart(1); + + /* off-chip devices */ + platform_device_register(&smc91x_device); +} + +MACHINE_START(TAVOREVB, "PXA910 Evaluation Board (aka TavorEVB)") + .phys_io = APB_PHYS_BASE, + .boot_params = 0x00000100, + .io_pg_offst = (APB_VIRT_BASE >> 18) & 0xfffc, + .map_io = pxa_map_io, + .init_irq = pxa910_init_irq, + .timer = &pxa910_timer, + .init_machine = tavorevb_init, +MACHINE_END -- GitLab From 01215e35c28a719f38e2cafe90a2806f0e452de6 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Fri, 20 Mar 2009 13:33:49 +0800 Subject: [PATCH 3921/4982] [ARM] pxa: add base support for pxa910-based TTC_DKB Signed-off-by: Bin Yang Signed-off-by: Eric Miao --- arch/arm/mach-mmp/Kconfig | 7 ++++++ arch/arm/mach-mmp/Makefile | 1 + arch/arm/mach-mmp/ttc_dkb.c | 47 +++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 arch/arm/mach-mmp/ttc_dkb.c diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig index e77db550907..c6a564fc4a7 100644 --- a/arch/arm/mach-mmp/Kconfig +++ b/arch/arm/mach-mmp/Kconfig @@ -23,6 +23,13 @@ config MACH_TAVOREVB Say 'Y' here if you want to support the Marvell PXA910-based TavorEVB Development Board. +config MACH_TTC_DKB + bool "Marvell's PXA910 TavorEVB Development Board" + select CPU_PXA910 + help + Say 'Y' here if you want to support the Marvell PXA910-based + TTC_DKB Development Board. + endmenu config CPU_PXA168 diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile index 542aafae5b1..6883e658488 100644 --- a/arch/arm/mach-mmp/Makefile +++ b/arch/arm/mach-mmp/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_CPU_PXA910) += pxa910.o obj-$(CONFIG_MACH_ASPENITE) += aspenite.o obj-$(CONFIG_MACH_ZYLONITE2) += aspenite.o obj-$(CONFIG_MACH_TAVOREVB) += tavorevb.o +obj-$(CONFIG_MACH_TTC_DKB) += ttc_dkb.o diff --git a/arch/arm/mach-mmp/ttc_dkb.c b/arch/arm/mach-mmp/ttc_dkb.c new file mode 100644 index 00000000000..08cfef6c92a --- /dev/null +++ b/arch/arm/mach-mmp/ttc_dkb.c @@ -0,0 +1,47 @@ +/* + * linux/arch/arm/mach-mmp/ttc_dkb.c + * + * Support for the Marvell PXA910-based TTC_DKB Development Platform. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * publishhed by the Free Software Foundation. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "common.h" + +#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x) + +static unsigned long ttc_dkb_pin_config[] __initdata = { + /* UART2 */ + GPIO47_UART2_RXD, + GPIO48_UART2_TXD, +}; + +static void __init ttc_dkb_init(void) +{ + mfp_config(ARRAY_AND_SIZE(ttc_dkb_pin_config)); + + /* on-chip devices */ + pxa910_add_uart(1); +} + +MACHINE_START(TTC_DKB, "PXA910-based TTC_DKB Development Platform") + .phys_io = APB_PHYS_BASE, + .boot_params = 0x00000100, + .io_pg_offst = (APB_VIRT_BASE >> 18) & 0xfffc, + .map_io = pxa_map_io, + .init_irq = pxa910_init_irq, + .timer = &pxa910_timer, + .init_machine = ttc_dkb_init, +MACHINE_END -- GitLab From e78b4eccb75b3ed5e50fdb12bc835e27aef33784 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Thu, 19 Feb 2009 17:35:31 +0800 Subject: [PATCH 3922/4982] [ARM] pxa: add defconfig for pxa168-based platforms Instead of having various pieces of defconfig files for different platforms, let's group them into a single one. Signed-off-by: Eric Miao --- arch/arm/configs/pxa168_defconfig | 891 ++++++++++++++++++++++++++++++ 1 file changed, 891 insertions(+) create mode 100644 arch/arm/configs/pxa168_defconfig diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig new file mode 100644 index 00000000000..db5faeaec96 --- /dev/null +++ b/arch/arm/configs/pxa168_defconfig @@ -0,0 +1,891 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.29-rc3 +# Fri Mar 20 13:43:13 2009 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_NET_NS is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_FREEZER is not set + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +CONFIG_ARCH_MMP=y +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_MACH_TAVOREVB is not set + +# +# Marvell PXA168/910 Implmentations +# +CONFIG_MACH_ASPENITE=y +CONFIG_MACH_ZYLONITE2=y +# CONFIG_MACH_TTC_DKB is not set +CONFIG_CPU_PXA168=y +CONFIG_PLAT_PXA=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_MOHAWK=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +# CONFIG_OUTER_CACHE is not set +CONFIG_IWMMXT=y +CONFIG_COMMON_CLKDEV=y + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PREEMPT=y +CONFIG_HZ=100 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="root=/dev/nfs rootfstype=nfs nfsroot=192.168.2.100:/nfsroot/ ip=192.168.2.101:192.168.2.100::255.255.255.0::eth0:on console=ttyS0,115200 mem=128M" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_COMPAT_NET_DEV_OPS=y +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +CONFIG_WIRELESS_OLD_REGULATORY=y +# CONFIG_WIRELESS_EXT is not set +# CONFIG_LIB80211 is not set +# CONFIG_MAC80211 is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_STANDALONE is not set +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +# CONFIG_BLK_DEV is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_PHYLIB is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +CONFIG_SMC91X=y +# CONFIG_DM9000 is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_PXA=y +CONFIG_SERIAL_PXA_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_GPIO_SYSFS is not set + +# +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_REGULATOR is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set +CONFIG_GENERIC_ACL=y + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=y +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +# CONFIG_SUNRPC_REGISTER_V4 is not set +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +CONFIG_PRINTK_TIME=y +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_HAVE_FUNCTION_TRACER=y + +# +# Tracers +# +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_ARM_UNWIND=y +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_HW=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_CRC_CCITT=y +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y -- GitLab From 5a09f8916c20e4799b214349df371ff5d164778d Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Fri, 20 Mar 2009 14:55:11 +0800 Subject: [PATCH 3923/4982] [ARM] pxa: add defconfig for pxa910-based platforms Signed-off-by: Eric Miao --- arch/arm/configs/pxa910_defconfig | 891 ++++++++++++++++++++++++++++++ 1 file changed, 891 insertions(+) create mode 100644 arch/arm/configs/pxa910_defconfig diff --git a/arch/arm/configs/pxa910_defconfig b/arch/arm/configs/pxa910_defconfig new file mode 100644 index 00000000000..8c7e299f1d6 --- /dev/null +++ b/arch/arm/configs/pxa910_defconfig @@ -0,0 +1,891 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.29-rc3 +# Fri Mar 20 13:45:12 2009 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_NET_NS is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_FREEZER is not set + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +CONFIG_ARCH_MMP=y +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_W90X900 is not set +CONFIG_MACH_TAVOREVB=y + +# +# Marvell PXA168/910 Implmentations +# +# CONFIG_MACH_ASPENITE is not set +# CONFIG_MACH_ZYLONITE2 is not set +CONFIG_MACH_TTC_DKB=y +CONFIG_CPU_PXA910=y +CONFIG_PLAT_PXA=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_MOHAWK=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +# CONFIG_OUTER_CACHE is not set +CONFIG_IWMMXT=y +CONFIG_COMMON_CLKDEV=y + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PREEMPT=y +CONFIG_HZ=100 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="root=/dev/nfs rootfstype=nfs nfsroot=192.168.2.100:/nfsroot/ ip=192.168.2.101:192.168.2.100::255.255.255.0::eth0:on console=ttyS0,115200 mem=128M" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_COMPAT_NET_DEV_OPS=y +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +CONFIG_WIRELESS_OLD_REGULATORY=y +# CONFIG_WIRELESS_EXT is not set +# CONFIG_LIB80211 is not set +# CONFIG_MAC80211 is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_STANDALONE is not set +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +# CONFIG_BLK_DEV is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_PHYLIB is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +CONFIG_SMC91X=y +# CONFIG_DM9000 is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_PXA=y +CONFIG_SERIAL_PXA_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_GPIO_SYSFS is not set + +# +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_REGULATOR is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set +CONFIG_GENERIC_ACL=y + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=y +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +# CONFIG_SUNRPC_REGISTER_V4 is not set +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +CONFIG_PRINTK_TIME=y +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_HAVE_FUNCTION_TRACER=y + +# +# Tracers +# +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_ARM_UNWIND=y +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_HW=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_CRC_CCITT=y +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y -- GitLab From a6bb4bab1cda4793cfa78c995042ecdf91401329 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Thu, 19 Feb 2009 21:13:21 +0800 Subject: [PATCH 3924/4982] MAINTAINERS: update pxa168 maintainers Signed-off-by: Eric Miao Acked-by: Jason Chagas --- MAINTAINERS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 799f9d818d1..78ff730feaa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3534,6 +3534,15 @@ M: linux@arm.linux.org.uk L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained +PXA168 SUPPORT +P: Eric Miao +M: eric.miao@marvell.com +P: Jason Chagas +M: jason.chagas@marvell.com +L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +T: git kernel.org:/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git +S: Supported + PXA MMCI DRIVER S: Orphan -- GitLab From 5fa82eb8ff06cd3ac4d64c6875922ae1dfa003c5 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Fri, 20 Mar 2009 12:52:24 +0800 Subject: [PATCH 3925/4982] MAINTAINERS: update pxa910 maintainers Signed-off-by: Eric Miao --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 78ff730feaa..619ca0194ec 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3543,6 +3543,13 @@ L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) T: git kernel.org:/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git S: Supported +PXA910 SUPPORT +P: Eric Miao +M: eric.miao@marvell.com +L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +T: git kernel.org:/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git +S: Supported + PXA MMCI DRIVER S: Orphan -- GitLab From 6580f57d485f70851218813fa053d971915f61fb Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Sun, 22 Mar 2009 21:22:48 -0700 Subject: [PATCH 3926/4982] net: update dnet.c for bus_id removal Signed-off-by: Stephen Rothwell Signed-off-by: David S. Miller --- drivers/net/dnet.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c index 5c347f70cb6..1b4063222a8 100644 --- a/drivers/net/dnet.c +++ b/drivers/net/dnet.c @@ -280,11 +280,11 @@ static int dnet_mii_probe(struct net_device *dev) /* attach the mac to the phy */ if (bp->capabilities & DNET_HAS_RMII) { - phydev = phy_connect(dev, phydev->dev.bus_id, + phydev = phy_connect(dev, dev_name(&phydev->dev), &dnet_handle_link_change, 0, PHY_INTERFACE_MODE_RMII); } else { - phydev = phy_connect(dev, phydev->dev.bus_id, + phydev = phy_connect(dev, dev_name(&phydev->dev), &dnet_handle_link_change, 0, PHY_INTERFACE_MODE_MII); } @@ -927,7 +927,7 @@ static int __devinit dnet_probe(struct platform_device *pdev) phydev = bp->phy_dev; dev_info(&pdev->dev, "attached PHY driver [%s] " "(mii_bus:phy_addr=%s, irq=%d)\n", - phydev->drv->name, phydev->dev.bus_id, phydev->irq); + phydev->drv->name, dev_name(&phydev->dev), phydev->irq); return 0; -- GitLab From 763dccdc8e9775b247c3ea86ae8f5f592c12024e Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Sun, 22 Mar 2009 21:24:19 -0700 Subject: [PATCH 3927/4982] bnx2x: Adding licensing to bnx2x_init_values.h Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_init_values.h | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/net/bnx2x_init_values.h b/drivers/net/bnx2x_init_values.h index 6e18a556fb5..1f22c9ab66d 100644 --- a/drivers/net/bnx2x_init_values.h +++ b/drivers/net/bnx2x_init_values.h @@ -1,7 +1,23 @@ #ifndef __BNX2X_INIT_VALUES_H__ #define __BNX2X_INIT_VALUES_H__ -/* This array contains the list of operations needed to initialize the chip. +/* bnx2x_init_values.h: Broadcom NX2 10G network driver. + * + * Copyright (c) 2007-2009 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, except as noted below. + * + * This file contains firmware data derived from proprietary unpublished + * source code, Copyright (c) 2007-2009 Broadcom Corporation. + * + * Permission is hereby granted for the distribution of this firmware data + * in hexadecimal or equivalent format, provided this copyright notice is + * accompanying it. + * + * + * This array contains the list of operations needed to initialize the chip. * * For each block in the chip there are three init stages: * common - HW used by both ports, -- GitLab From e3162d381fc359ebe5c98a3e216888a7cb200051 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 22 Mar 2009 21:28:39 -0700 Subject: [PATCH 3928/4982] dm9000: locking bugfix This fixes a locking bug in the dm9000 driver. It calls request_irq() without setting IRQF_DISABLED ... which is correct for handlers that support IRQ sharing, since that behavior is not guaranteed for shared IRQs. However, its IRQ handler then wrongly assumes that IRQs are blocked. So the fix just uses the right spinlock primitives in the IRQ handler. NOTE: this is a classic example of the type of bug which lockdep currently masks by forcibly setting IRQF_DISABLED on IRQ handlers that did not request that flag. Signed-off-by: David Brownell Signed-off-by: David S. Miller --- drivers/net/dm9000.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index bcf92917bbf..254ec62b5f5 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -930,13 +930,15 @@ static irqreturn_t dm9000_interrupt(int irq, void *dev_id) struct net_device *dev = dev_id; board_info_t *db = netdev_priv(dev); int int_status; + unsigned long flags; u8 reg_save; dm9000_dbg(db, 3, "entering %s\n", __func__); /* A real interrupt coming */ - spin_lock(&db->lock); + /* holders of db->lock must always block IRQs */ + spin_lock_irqsave(&db->lock, flags); /* Save previous register address */ reg_save = readb(db->io_addr); @@ -972,7 +974,7 @@ static irqreturn_t dm9000_interrupt(int irq, void *dev_id) /* Restore previous register address */ writeb(reg_save, db->io_addr); - spin_unlock(&db->lock); + spin_unlock_irqrestore(&db->lock, flags); return IRQ_HANDLED; } -- GitLab From 61fa9dcf9329cb92c220f7b656410fbe5e72f933 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sun, 22 Mar 2009 21:30:52 -0700 Subject: [PATCH 3929/4982] ucc_geth: Fix oops when using fixed-link support commit b1c4a9dddf09fe99b8f88252718ac5b357363dc4 ("ucc_geth: Change uec phy id to the same format as gianfar's") introduced a regression in the ucc_geth driver that causes this oops when fixed-link is used: Unable to handle kernel paging request for data at address 0x00000000 Faulting instruction address: 0xc0151270 Oops: Kernel access of bad area, sig: 11 [#1] TMCUTU NIP: c0151270 LR: c0151270 CTR: c0017760 REGS: cf81fa60 TRAP: 0300 Not tainted (2.6.29-rc8) MSR: 00009032 CR: 24024042 XER: 20000000 DAR: 00000000, DSISR: 20000000 TASK = cf81cba0[1] 'swapper' THREAD: cf81e000 GPR00: c0151270 cf81fb10 cf81cba0 00000000 c0272e20 c025f354 00001e80 cf86b08c GPR08: d1068200 cffffb74 06000000 d106c200 42024042 10085148 0fffd000 0ffc81a0 GPR16: 00000001 00000001 00000000 007ffeb0 00000000 0000c000 cf83f36c cf83f000 GPR24: 00000030 cf83f360 cf81fb20 00000000 d106c200 20000000 00001e80 cf83f360 NIP [c0151270] ucc_geth_open+0x330/0x1efc LR [c0151270] ucc_geth_open+0x330/0x1efc Call Trace: [cf81fb10] [c0151270] ucc_geth_open+0x330/0x1efc (unreliable) [cf81fba0] [c0187638] dev_open+0xbc/0x12c [cf81fbc0] [c0187e38] dev_change_flags+0x8c/0x1b0 This patch fixes the issue by removing offending (and somewhat duplicate) code from init_phy() routine, and changes _probe() function to use uec_mdio_bus_name(). Also, since we fully construct phy_bus_id in the _probe() routine, we no longer need ->phy_address and ->mdio_bus fields in ucc_geth_info structure. I wish the patch would be a bit shorter, but it seems like the only way to fix the issue in a sane way. Luckily, the patch has been tested with real PHYs and fixed-link, so no further regressions expected. Reported-by: Joakim Tjernlund Signed-off-by: Anton Vorontsov Tested-by: Joakim Tjernlund Signed-off-by: David S. Miller --- drivers/net/ucc_geth.c | 34 ++++++++++------------------------ drivers/net/ucc_geth.h | 3 +-- 2 files changed, 11 insertions(+), 26 deletions(-) diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index e87986867ba..1f61e42c641 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -1536,32 +1536,15 @@ static void adjust_link(struct net_device *dev) static int init_phy(struct net_device *dev) { struct ucc_geth_private *priv = netdev_priv(dev); - struct device_node *np = priv->node; - struct device_node *phy, *mdio; - const phandle *ph; - char bus_name[MII_BUS_ID_SIZE]; - const unsigned int *id; + struct ucc_geth_info *ug_info = priv->ug_info; struct phy_device *phydev; - char phy_id[BUS_ID_SIZE]; priv->oldlink = 0; priv->oldspeed = 0; priv->oldduplex = -1; - ph = of_get_property(np, "phy-handle", NULL); - phy = of_find_node_by_phandle(*ph); - mdio = of_get_parent(phy); - - id = of_get_property(phy, "reg", NULL); - - of_node_put(phy); - of_node_put(mdio); - - uec_mdio_bus_name(bus_name, mdio); - snprintf(phy_id, sizeof(phy_id), "%s:%02x", - bus_name, *id); - - phydev = phy_connect(dev, phy_id, &adjust_link, 0, priv->phy_interface); + phydev = phy_connect(dev, ug_info->phy_bus_id, &adjust_link, 0, + priv->phy_interface); if (IS_ERR(phydev)) { printk("%s: Could not attach to PHY\n", dev->name); @@ -3629,10 +3612,12 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma ug_info->uf_info.irq = irq_of_parse_and_map(np, 0); fixed_link = of_get_property(np, "fixed-link", NULL); if (fixed_link) { - snprintf(ug_info->mdio_bus, MII_BUS_ID_SIZE, "0"); - ug_info->phy_address = fixed_link[0]; + snprintf(ug_info->phy_bus_id, sizeof(ug_info->phy_bus_id), + PHY_ID_FMT, "0", fixed_link[0]); phy = NULL; } else { + char bus_name[MII_BUS_ID_SIZE]; + ph = of_get_property(np, "phy-handle", NULL); phy = of_find_node_by_phandle(*ph); @@ -3643,7 +3628,6 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma prop = of_get_property(phy, "reg", NULL); if (prop == NULL) return -1; - ug_info->phy_address = *prop; /* Set the bus id */ mdio = of_get_parent(phy); @@ -3657,7 +3641,9 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma if (err) return -1; - snprintf(ug_info->mdio_bus, MII_BUS_ID_SIZE, "%x", res.start); + uec_mdio_bus_name(bus_name, mdio); + snprintf(ug_info->phy_bus_id, sizeof(ug_info->phy_bus_id), + "%s:%02x", bus_name, *prop); } /* get the phy interface type, or default to MII */ diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h index 16cbe42ba43..611bdef2402 100644 --- a/drivers/net/ucc_geth.h +++ b/drivers/net/ucc_geth.h @@ -1091,8 +1091,7 @@ struct ucc_geth_info { u32 eventRegMask; u16 pausePeriod; u16 extensionField; - u8 phy_address; - char mdio_bus[MII_BUS_ID_SIZE]; + char phy_bus_id[BUS_ID_SIZE]; u8 weightfactor[NUM_TX_QUEUES]; u8 interruptcoalescingmaxvalue[NUM_RX_QUEUES]; u8 l2qt[UCC_GETH_VLAN_PRIORITY_MAX]; -- GitLab From 96e0bf4b5193d0d97d139f99e2dd128763d55521 Mon Sep 17 00:00:00 2001 From: John Dykstra Date: Sun, 22 Mar 2009 21:49:57 -0700 Subject: [PATCH 3930/4982] tcp: Discard segments that ack data not yet sent Discard incoming packets whose ack field iincludes data not yet sent. This is consistent with RFC 793 Section 3.9. Change tcp_ack() to distinguish between too-small and too-large ack field values. Keep segments with too-large ack fields out of the fast path, and change slow path to discard them. Reported-by: Oliver Zheng Signed-off-by: John Dykstra Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 8ac82b3703a..2bc8e27a163 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3585,15 +3585,18 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag) int prior_packets; int frto_cwnd = 0; - /* If the ack is newer than sent or older than previous acks + /* If the ack is older than previous acks * then we can probably ignore it. */ - if (after(ack, tp->snd_nxt)) - goto uninteresting_ack; - if (before(ack, prior_snd_una)) goto old_ack; + /* If the ack includes data we haven't sent yet, discard + * this segment (RFC793 Section 3.9). + */ + if (after(ack, tp->snd_nxt)) + goto invalid_ack; + if (after(ack, prior_snd_una)) flag |= FLAG_SND_UNA_ADVANCED; @@ -3683,6 +3686,10 @@ no_queue: tcp_ack_probe(sk); return 1; +invalid_ack: + SOCK_DEBUG(sk, "Ack %u after %u:%u\n", ack, tp->snd_una, tp->snd_nxt); + return -1; + old_ack: if (TCP_SKB_CB(skb)->sacked) { tcp_sacktag_write_queue(sk, skb, prior_snd_una); @@ -3690,8 +3697,7 @@ old_ack: tcp_try_keep_open(sk); } -uninteresting_ack: - SOCK_DEBUG(sk, "Ack %u out of %u:%u\n", ack, tp->snd_una, tp->snd_nxt); + SOCK_DEBUG(sk, "Ack %u before %u:%u\n", ack, tp->snd_una, tp->snd_nxt); return 0; } @@ -5141,7 +5147,8 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, */ if ((tcp_flag_word(th) & TCP_HP_BITS) == tp->pred_flags && - TCP_SKB_CB(skb)->seq == tp->rcv_nxt) { + TCP_SKB_CB(skb)->seq == tp->rcv_nxt && + !after(TCP_SKB_CB(skb)->ack_seq, tp->snd_nxt)) { int tcp_header_len = tp->tcp_header_len; /* Timestamp header prediction: tcp_header_len @@ -5294,8 +5301,8 @@ slow_path: return -res; step5: - if (th->ack) - tcp_ack(sk, skb, FLAG_SLOWPATH); + if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0) + goto discard; tcp_rcv_rtt_measure_ts(sk, skb); @@ -5632,7 +5639,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, /* step 5: check the ACK field */ if (th->ack) { - int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH); + int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH) > 0; switch (sk->sk_state) { case TCP_SYN_RECV: -- GitLab From 1a00df4a2cc001dd9f45890e690548c24b2fa2d9 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 7 Mar 2009 00:36:21 +0900 Subject: [PATCH 3931/4982] slub: use get_track() Use get_track() in set_track() Signed-off-by: Akinobu Mita Cc: Christoph Lameter Cc: Pekka Enberg Signed-off-by: Pekka Enberg --- mm/slub.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index f21e25ad453..e150b5c0424 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -374,14 +374,8 @@ static struct track *get_track(struct kmem_cache *s, void *object, static void set_track(struct kmem_cache *s, void *object, enum track_item alloc, unsigned long addr) { - struct track *p; - - if (s->offset) - p = object + s->offset + sizeof(void *); - else - p = object + s->inuse; + struct track *p = get_track(s, object, alloc); - p += alloc; if (addr) { p->addr = addr; p->cpu = smp_processor_id(); -- GitLab From da4a99e397d4165c0b8d951e75adb095455614ec Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 23 Mar 2009 01:03:04 -0700 Subject: [PATCH 3932/4982] spider_net: Fix build. Based upon a report by Stephen Rothwell. Signed-off-by: David S. Miller --- drivers/net/spider_net.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 136d9f1c6ad..0288054249d 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -2260,18 +2260,18 @@ spider_net_tx_timeout(struct net_device *netdev) } static const struct net_device_ops spider_net_ops = { - .ndo_open = spider_net_open; - .ndo_stop = spider_net_stop; - .ndo_start_xmit = spider_net_xmit; - .ndo_set_multicast_list = spider_net_set_multi; - .ndo_set_mac_address = spider_net_set_mac; - .ndo_change_mtu = spider_net_change_mtu; - .ndo_do_ioctl = spider_net_do_ioctl; - .ndo_tx_timeout = spider_net_tx_timeout; + .ndo_open = spider_net_open, + .ndo_stop = spider_net_stop, + .ndo_start_xmit = spider_net_xmit, + .ndo_set_multicast_list = spider_net_set_multi, + .ndo_set_mac_address = spider_net_set_mac, + .ndo_change_mtu = spider_net_change_mtu, + .ndo_do_ioctl = spider_net_do_ioctl, + .ndo_tx_timeout = spider_net_tx_timeout, /* HW VLAN */ #ifdef CONFIG_NET_POLL_CONTROLLER /* poll controller */ - .ndo_poll_controller = spider_net_poll_controller; + .ndo_poll_controller = spider_net_poll_controller, #endif /* CONFIG_NET_POLL_CONTROLLER */ }; -- GitLab From 268ed76d67d658684d4b1e114d4da75ad360b4b1 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Mon, 23 Mar 2009 01:18:58 -0700 Subject: [PATCH 3933/4982] atl1c: remove duplicated #include Remove duplicated #include in drivers/net/atl1c/atl1c.h. Signed-off-by: Huang Weiyi Signed-off-by: David S. Miller --- drivers/net/atl1c/atl1c.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/atl1c/atl1c.h index ac11b84b837..e1658ef3fcd 100644 --- a/drivers/net/atl1c/atl1c.h +++ b/drivers/net/atl1c/atl1c.h @@ -45,7 +45,6 @@ #include #include #include -#include #include #include #include -- GitLab From 6fb8f424393025674fde7869b59f485d1e352182 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Mon, 16 Mar 2009 21:00:28 +1100 Subject: [PATCH 3934/4982] slob: fix lockup in slob_free() Don't hold SLOB lock when freeing the page. Reduces lock hold width. See the following thread for discussion of the bug: http://marc.info/?l=linux-kernel&m=123709983214143&w=2 Reported-by: Ingo Molnar Acked-by: Matt Mackall Signed-off-by: Nick Piggin Signed-off-by: Pekka Enberg --- mm/slob.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mm/slob.c b/mm/slob.c index bf7e8fc3aed..f901653707a 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -393,10 +393,11 @@ static void slob_free(void *block, int size) /* Go directly to page allocator. Do not pass slob allocator */ if (slob_page_free(sp)) clear_slob_page_free(sp); + spin_unlock_irqrestore(&slob_lock, flags); clear_slob_page(sp); free_slob_page(sp); free_page((unsigned long)b); - goto out; + return; } if (!slob_page_free(sp)) { -- GitLab From 234b4346a064f8a2a488da10b3c1e640fb778a17 Mon Sep 17 00:00:00 2001 From: Pascal de Bruijn Date: Mon, 23 Mar 2009 11:15:59 +0100 Subject: [PATCH 3935/4982] ALSA: hda - Add function id to proc output This patch does two things: Output Intel HDA Function Id in /proc/asound/cardX/codec#X Align Vendor/Subsystem/Revision Ids to 8 characters, front-padded with zeros Before: Vendor Id: 0x11d41884 Subsystem Id: 0x103c281a Revision Id: 0x100100 After: Function Id: 0x1 Vendor Id: 0x11d41884 Subsystem Id: 0x103c281a Revision Id: 0x0100100 As report on the Kernel Bugzilla #12888 Signed-off-by: Pascal de Bruijn Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 6 +++--- sound/pci/hda/hda_codec.h | 1 + sound/pci/hda/hda_proc.c | 5 +++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index b90a2400f53..1b5575ecb0a 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -647,9 +647,9 @@ static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec) total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid); for (i = 0; i < total_nodes; i++, nid++) { - unsigned int func; - func = snd_hda_param_read(codec, nid, AC_PAR_FUNCTION_TYPE); - switch (func & 0xff) { + codec->function_id = snd_hda_param_read(codec, nid, + AC_PAR_FUNCTION_TYPE) & 0xff; + switch (codec->function_id) { case AC_GRP_AUDIO_FUNCTION: codec->afg = nid; break; diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 079e1ab718d..2fdecf4b0eb 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -739,6 +739,7 @@ struct hda_codec { hda_nid_t mfg; /* MFG node id */ /* ids */ + u32 function_id; u32 vendor_id; u32 subsystem_id; u32 revision_id; diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 639cf0edaa9..93d7499350c 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -469,8 +469,9 @@ static void print_codec_info(struct snd_info_entry *entry, snd_iprintf(buffer, "Codec: %s\n", codec->name ? codec->name : "Not Set"); snd_iprintf(buffer, "Address: %d\n", codec->addr); - snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id); - snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id); + snd_iprintf(buffer, "Function Id: 0x%x\n", codec->function_id); + snd_iprintf(buffer, "Vendor Id: 0x%08x\n", codec->vendor_id); + snd_iprintf(buffer, "Subsystem Id: 0x%08x\n", codec->subsystem_id); snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id); if (codec->mfg) -- GitLab From 52ca15b7c0c711eb37f5e4b769e8488e5c516d43 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 23 Mar 2009 12:51:55 +0100 Subject: [PATCH 3936/4982] ALSA: hda - Avoid output amp manipulation to digital mic pins Don't set amp-out values to pins without PINCAP_OUT capability, which are usually assigned for digital mics on ALC663/ALC272. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b69d9864f6f..965a531d2fb 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -16750,6 +16750,12 @@ static int alc662_is_input_pin(struct hda_codec *codec, hda_nid_t nid) return (pincap & AC_PINCAP_IN) != 0; } +static int alc662_is_output_pin(struct hda_codec *codec, hda_nid_t nid) +{ + unsigned int pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); + return (pincap & AC_PINCAP_OUT) != 0; +} + /* create playback/capture controls for input pins */ static int alc662_auto_create_analog_input_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) @@ -16837,7 +16843,8 @@ static void alc662_auto_init_analog_input(struct hda_codec *codec) hda_nid_t nid = spec->autocfg.input_pins[i]; if (alc662_is_input_pin(codec, nid)) { alc_set_input_pin(codec, nid, i); - if (nid != ALC662_PIN_CD_NID) + if (nid != ALC662_PIN_CD_NID && + alc662_is_output_pin(codec, nid)) snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); -- GitLab From 1327a32b878b5ed2113c63557b6f4f949f821857 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 23 Mar 2009 13:07:47 +0100 Subject: [PATCH 3937/4982] ALSA: hda - Cache pin-cap values Added snd_hda_query_pin_caps() to read and cache pin-cap values to avoid too frequently issuing the same verbs. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 16 ++++++++++++++++ sound/pci/hda/hda_generic.c | 2 +- sound/pci/hda/hda_local.h | 1 + sound/pci/hda/patch_realtek.c | 6 +++--- sound/pci/hda/patch_sigmatel.c | 7 +++---- 5 files changed, 24 insertions(+), 8 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 1b5575ecb0a..0f70d2d102e 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1052,6 +1052,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream); /* FIXME: more better hash key? */ #define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) +#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24)) #define INFO_AMP_CAPS (1<<0) #define INFO_AMP_VOL(ch) (1 << (1 + (ch))) @@ -1142,6 +1143,21 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, } EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps); +u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid) +{ + struct hda_amp_info *info; + + info = get_alloc_amp_hash(codec, HDA_HASH_PINCAP_KEY(nid)); + if (!info) + return 0; + if (!info->head.val) { + info->amp_caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); + info->head.val |= INFO_AMP_CAPS; + } + return info->amp_caps; +} +EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps); + /* * read the current volume to info * if the cache exists, read the cache value. diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 2c81a683e8f..1d5797a9668 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -144,7 +144,7 @@ static int add_new_node(struct hda_codec *codec, struct hda_gspec *spec, hda_nid node->type = (node->wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; if (node->type == AC_WID_PIN) { - node->pin_caps = snd_hda_param_read(codec, node->nid, AC_PAR_PIN_CAP); + node->pin_caps = snd_hda_query_pin_caps(codec, node->nid); node->pin_ctl = snd_hda_codec_read(codec, node->nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); node->def_cfg = snd_hda_codec_get_pincfg(codec, node->nid); } diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 27428c718fd..83349013b4d 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -411,6 +411,7 @@ static inline u32 get_wcaps(struct hda_codec *codec, hda_nid_t nid) u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction); int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, unsigned int caps); +u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid); int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl); void snd_hda_ctls_clear(struct hda_codec *codec); diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 965a531d2fb..bf7e64e2c46 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -770,7 +770,7 @@ static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid, if (auto_pin_type <= AUTO_PIN_FRONT_MIC) { unsigned int pincap; - pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); + pincap = snd_hda_query_pin_caps(codec, nid); pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT; if (pincap & AC_PINCAP_VREF_80) val = PIN_VREF80; @@ -16746,13 +16746,13 @@ static int alc662_input_pin_idx(struct hda_codec *codec, hda_nid_t nid, static int alc662_is_input_pin(struct hda_codec *codec, hda_nid_t nid) { - unsigned int pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); + unsigned int pincap = snd_hda_query_pin_caps(codec, nid); return (pincap & AC_PINCAP_IN) != 0; } static int alc662_is_output_pin(struct hda_codec *codec, hda_nid_t nid) { - unsigned int pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); + unsigned int pincap = snd_hda_query_pin_caps(codec, nid); return (pincap & AC_PINCAP_OUT) != 0; } diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 4da72403fc8..b1c180a9e9b 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -2537,8 +2537,7 @@ static int stac92xx_build_pcms(struct hda_codec *codec) static unsigned int stac92xx_get_vref(struct hda_codec *codec, hda_nid_t nid) { - unsigned int pincap = snd_hda_param_read(codec, nid, - AC_PAR_PIN_CAP); + unsigned int pincap = snd_hda_query_pin_caps(codec, nid); pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT; if (pincap & AC_PINCAP_VREF_100) return AC_PINCTL_VREF_100; @@ -2799,7 +2798,7 @@ static hda_nid_t check_line_out_switch(struct hda_codec *codec) if (cfg->line_out_type != AUTO_PIN_LINE_OUT) return 0; nid = cfg->input_pins[AUTO_PIN_LINE]; - pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); + pincap = snd_hda_query_pin_caps(codec, nid); if (pincap & AC_PINCAP_OUT) return nid; return 0; @@ -2822,7 +2821,7 @@ static hda_nid_t check_mic_out_switch(struct hda_codec *codec) /* some laptops have an internal analog microphone * which can't be used as a output */ if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) { - pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); + pincap = snd_hda_query_pin_caps(codec, nid); if (pincap & AC_PINCAP_OUT) return nid; } -- GitLab From 176252746ebbc8db97e304345af1f2563c7dc139 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Mon, 23 Mar 2009 13:16:53 +0100 Subject: [PATCH 3938/4982] netfilter: sysctl support of logger choice This patchs adds support of modification of the used logger via sysctl. It can be used to change the logger to module that can not use the bind operation (ipt_LOG and ipt_ULOG). For this purpose, it creates a directory /proc/sys/net/netfilter/nf_log which contains a file per-protocol. The content of the file is the name current logger (NONE if not set) and a logger can be setup by simply echoing its name to the file. By echoing "NONE" to a /proc/sys/net/netfilter/nf_log/PROTO file, the logger corresponding to this PROTO is set to NULL. Signed-off-by: Eric Leblond Signed-off-by: Patrick McHardy --- net/netfilter/nf_log.c | 85 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index 4fcbcc71aa3..8bb998fe098 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c @@ -14,6 +14,7 @@ LOG target modules */ #define NF_LOG_PREFIXLEN 128 +#define NFLOGGER_NAME_LEN 64 static const struct nf_logger *nf_loggers[NFPROTO_NUMPROTO] __read_mostly; static struct list_head nf_loggers_l[NFPROTO_NUMPROTO] __read_mostly; @@ -207,18 +208,100 @@ static const struct file_operations nflog_file_ops = { .release = seq_release, }; + #endif /* PROC_FS */ +#ifdef CONFIG_SYSCTL +struct ctl_path nf_log_sysctl_path[] = { + { .procname = "net", .ctl_name = CTL_NET, }, + { .procname = "netfilter", .ctl_name = NET_NETFILTER, }, + { .procname = "nf_log", .ctl_name = CTL_UNNUMBERED, }, + { } +}; + +static char nf_log_sysctl_fnames[NFPROTO_NUMPROTO-NFPROTO_UNSPEC][3]; +static struct ctl_table nf_log_sysctl_table[NFPROTO_NUMPROTO+1]; +static struct ctl_table_header *nf_log_dir_header; -int __init netfilter_log_init(void) +static int nf_log_proc_dostring(ctl_table *table, int write, struct file *filp, + void *buffer, size_t *lenp, loff_t *ppos) +{ + const struct nf_logger *logger; + int r = 0; + int tindex = (unsigned long)table->extra1; + + if (write) { + if (!strcmp(buffer, "NONE")) { + nf_log_unbind_pf(tindex); + return 0; + } + mutex_lock(&nf_log_mutex); + logger = __find_logger(tindex, buffer); + if (logger == NULL) { + mutex_unlock(&nf_log_mutex); + return -ENOENT; + } + rcu_assign_pointer(nf_loggers[tindex], logger); + mutex_unlock(&nf_log_mutex); + } else { + rcu_read_lock(); + logger = rcu_dereference(nf_loggers[tindex]); + if (!logger) + table->data = "NONE"; + else + table->data = logger->name; + r = proc_dostring(table, write, filp, buffer, lenp, ppos); + rcu_read_unlock(); + } + + return r; +} + +static __init int netfilter_log_sysctl_init(void) { int i; + + for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) { + snprintf(nf_log_sysctl_fnames[i-NFPROTO_UNSPEC], 3, "%d", i); + nf_log_sysctl_table[i].ctl_name = CTL_UNNUMBERED; + nf_log_sysctl_table[i].procname = + nf_log_sysctl_fnames[i-NFPROTO_UNSPEC]; + nf_log_sysctl_table[i].data = NULL; + nf_log_sysctl_table[i].maxlen = + NFLOGGER_NAME_LEN * sizeof(char); + nf_log_sysctl_table[i].mode = 0644; + nf_log_sysctl_table[i].proc_handler = nf_log_proc_dostring; + nf_log_sysctl_table[i].extra1 = (void *)(unsigned long) i; + } + + nf_log_dir_header = register_sysctl_paths(nf_log_sysctl_path, + nf_log_sysctl_table); + if (!nf_log_dir_header) + return -ENOMEM; + + return 0; +} +#else +static __init int netfilter_log_sysctl_init(void) +{ + return 0; +} +#endif /* CONFIG_SYSCTL */ + +int __init netfilter_log_init(void) +{ + int i, r; #ifdef CONFIG_PROC_FS if (!proc_create("nf_log", S_IRUGO, proc_net_netfilter, &nflog_file_ops)) return -1; #endif + /* Errors will trigger panic, unroll on error is unnecessary. */ + r = netfilter_log_sysctl_init(); + if (r < 0) + return r; + for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) INIT_LIST_HEAD(&(nf_loggers_l[i])); -- GitLab From dd5b6ce6fd465eab90357711c8e8124dc3a31ff0 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 23 Mar 2009 13:21:06 +0100 Subject: [PATCH 3939/4982] nefilter: nfnetlink: add nfnetlink_set_err and use it in ctnetlink This patch adds nfnetlink_set_err() to propagate the error to netlink broadcast listener in case of memory allocation errors in the message building. Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy --- include/linux/netfilter/nfnetlink.h | 1 + net/netfilter/nf_conntrack_netlink.c | 2 ++ net/netfilter/nfnetlink.c | 6 ++++++ net/netlink/af_netlink.c | 1 + 4 files changed, 10 insertions(+) diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h index 7d8e0455cca..135e5cfe68a 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux/netfilter/nfnetlink.h @@ -76,6 +76,7 @@ extern int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n); extern int nfnetlink_has_listeners(unsigned int group); extern int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo); +extern void nfnetlink_set_err(u32 pid, u32 group, int error); extern int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags); extern void nfnl_lock(void); diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index d1fe9d15ac5..1b75c9efb0e 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -518,6 +518,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, nla_put_failure: rcu_read_unlock(); nlmsg_failure: + nfnetlink_set_err(0, group, -ENOBUFS); kfree_skb(skb); return NOTIFY_DONE; } @@ -1514,6 +1515,7 @@ static int ctnetlink_expect_event(struct notifier_block *this, nla_put_failure: rcu_read_unlock(); nlmsg_failure: + nfnetlink_set_err(0, 0, -ENOBUFS); kfree_skb(skb); return NOTIFY_DONE; } diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 9c0ba17a1dd..2785d66a7e3 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -113,6 +113,12 @@ int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo) } EXPORT_SYMBOL_GPL(nfnetlink_send); +void nfnetlink_set_err(u32 pid, u32 group, int error) +{ + netlink_set_err(nfnl, pid, group, error); +} +EXPORT_SYMBOL_GPL(nfnetlink_set_err); + int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags) { return netlink_unicast(nfnl, skb, pid, flags); diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 6ee69c27f80..5b33879c642 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1106,6 +1106,7 @@ void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) read_unlock(&nl_table_lock); } +EXPORT_SYMBOL(netlink_set_err); /* must be called with netlink table grabbed */ static void netlink_update_socket_mc(struct netlink_sock *nlk, -- GitLab From 534f81a5068799799e264fd162e9488a129f98d4 Mon Sep 17 00:00:00 2001 From: "Mark H. Weaver" Date: Mon, 23 Mar 2009 13:46:12 +0100 Subject: [PATCH 3940/4982] netfilter: nf_conntrack_tcp: fix unaligned memory access in tcp_sack This patch fixes an unaligned memory access in tcp_sack while reading sequence numbers from TCP selective acknowledgement options. Prior to applying this patch, upstream linux-2.6.27.20 was occasionally generating messages like this on my sparc64 system: [54678.532071] Kernel unaligned access at TPC[6b17d4] tcp_packet+0xcd4/0xd00 Acked-by: David S. Miller Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_proto_tcp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index f3fd154d1dd..56ac4ee77a1 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -466,7 +467,7 @@ static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff, for (i = 0; i < (opsize - TCPOLEN_SACK_BASE); i += TCPOLEN_SACK_PERBLOCK) { - tmp = ntohl(*((__be32 *)(ptr+i)+1)); + tmp = get_unaligned_be32((__be32 *)(ptr+i)+1); if (after(tmp, *sack)) *sack = tmp; -- GitLab From 345953cf9a44b19c98f8c0fe6ca7724202bcdb94 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Sat, 14 Mar 2009 09:23:03 -0500 Subject: [PATCH 3941/4982] powerpc/mm: Fix Respect _PAGE_COHERENT on classic ppc32 SW TLB load machines Grant picked up the wrong version of "Respect _PAGE_COHERENT on classic ppc32 SW" (commit a4bd6a93c3f14691c8a29e53eb04dc734b27f0db) It was missing the code to actually deal with the fixup of _PAGE_COHERENT based on the CPU feature. Signed-off-by: Kumar Gala --- arch/powerpc/kernel/head_32.S | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S index 7db2e42d97a..d794a637e42 100644 --- a/arch/powerpc/kernel/head_32.S +++ b/arch/powerpc/kernel/head_32.S @@ -513,6 +513,9 @@ InstructionTLBMiss: rlwimi r3,r3,32-1,31,31 /* _PAGE_USER -> PP lsb */ ori r1,r1,0xe04 /* clear out reserved bits */ andc r1,r3,r1 /* PP = user? (rw&dirty? 2: 3): 0 */ +BEGIN_FTR_SECTION + rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ +END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) mtspr SPRN_RPA,r1 mfspr r3,SPRN_IMISS tlbli r3 @@ -587,6 +590,9 @@ DataLoadTLBMiss: rlwimi r3,r3,32-1,31,31 /* _PAGE_USER -> PP lsb */ ori r1,r1,0xe04 /* clear out reserved bits */ andc r1,r3,r1 /* PP = user? (rw&dirty? 2: 3): 0 */ +BEGIN_FTR_SECTION + rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ +END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) mtspr SPRN_RPA,r1 mfspr r3,SPRN_DMISS tlbld r3 @@ -655,6 +661,9 @@ DataStoreTLBMiss: rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */ li r1,0xe05 /* clear out reserved bits & PP lsb */ andc r1,r3,r1 /* PP = user? 2: 0 */ +BEGIN_FTR_SECTION + rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ +END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) mtspr SPRN_RPA,r1 mfspr r3,SPRN_DMISS tlbld r3 -- GitLab From e82c025b501a1ca62dec40989817dbb17c0b9167 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 23 Mar 2009 15:17:38 +0100 Subject: [PATCH 3942/4982] ALSA: hda - Fix the wrong pin-cap check in patch_realtek.c The check for the amp-output must be done for widget-caps rather than pin-caps as implemented in the recent change... Simply a thinko. Also, add the similar checks to all places that put output-amp mutes in the initialization. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index bf7e64e2c46..8dcbb04e57b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4207,7 +4207,8 @@ static void alc880_auto_init_analog_input(struct hda_codec *codec) hda_nid_t nid = spec->autocfg.input_pins[i]; if (alc880_is_input_pin(nid)) { alc_set_input_pin(codec, nid, i); - if (nid != ALC880_PIN_CD_NID) + if (nid != ALC880_PIN_CD_NID && + (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); @@ -5673,7 +5674,8 @@ static void alc260_auto_init_analog_input(struct hda_codec *codec) hda_nid_t nid = spec->autocfg.input_pins[i]; if (nid >= 0x12) { alc_set_input_pin(codec, nid, i); - if (nid != ALC260_PIN_CD_NID) + if (nid != ALC260_PIN_CD_NID && + (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); @@ -9153,7 +9155,8 @@ static void alc883_auto_init_analog_input(struct hda_codec *codec) hda_nid_t nid = spec->autocfg.input_pins[i]; if (alc883_is_input_pin(nid)) { alc_set_input_pin(codec, nid, i); - if (nid != ALC883_PIN_CD_NID) + if (nid != ALC883_PIN_CD_NID && + (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); @@ -14880,7 +14883,8 @@ static void alc861vd_auto_init_analog_input(struct hda_codec *codec) hda_nid_t nid = spec->autocfg.input_pins[i]; if (alc861vd_is_input_pin(nid)) { alc_set_input_pin(codec, nid, i); - if (nid != ALC861VD_PIN_CD_NID) + if (nid != ALC861VD_PIN_CD_NID && + (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); @@ -16750,12 +16754,6 @@ static int alc662_is_input_pin(struct hda_codec *codec, hda_nid_t nid) return (pincap & AC_PINCAP_IN) != 0; } -static int alc662_is_output_pin(struct hda_codec *codec, hda_nid_t nid) -{ - unsigned int pincap = snd_hda_query_pin_caps(codec, nid); - return (pincap & AC_PINCAP_OUT) != 0; -} - /* create playback/capture controls for input pins */ static int alc662_auto_create_analog_input_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) @@ -16844,7 +16842,7 @@ static void alc662_auto_init_analog_input(struct hda_codec *codec) if (alc662_is_input_pin(codec, nid)) { alc_set_input_pin(codec, nid, i); if (nid != ALC662_PIN_CD_NID && - alc662_is_output_pin(codec, nid)) + (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); -- GitLab From a23b688f4d5c2490a50677b30011a677d8edf3d0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 23 Mar 2009 15:21:36 +0100 Subject: [PATCH 3943/4982] ALSA: hda - Don't create empty/single-item input source In patch_realtek.c, don't create empty or single-item "Input Source" control elements that are simply superfluous. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 47 ++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 8dcbb04e57b..7a3c6db6d5b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1595,8 +1595,7 @@ static int alc_cap_sw_put(struct snd_kcontrol *kcontrol, snd_hda_mixer_amp_switch_put); } -#define DEFINE_CAPMIX(num) \ -static struct snd_kcontrol_new alc_capture_mixer ## num[] = { \ +#define _DEFINE_CAPMIX(num) \ { \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ .name = "Capture Switch", \ @@ -1617,7 +1616,9 @@ static struct snd_kcontrol_new alc_capture_mixer ## num[] = { \ .get = alc_cap_vol_get, \ .put = alc_cap_vol_put, \ .tlv = { .c = alc_cap_vol_tlv }, \ - }, \ + } + +#define _DEFINE_CAPSRC(num) \ { \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ /* .name = "Capture Source", */ \ @@ -1626,15 +1627,28 @@ static struct snd_kcontrol_new alc_capture_mixer ## num[] = { \ .info = alc_mux_enum_info, \ .get = alc_mux_enum_get, \ .put = alc_mux_enum_put, \ - }, \ - { } /* end */ \ + } + +#define DEFINE_CAPMIX(num) \ +static struct snd_kcontrol_new alc_capture_mixer ## num[] = { \ + _DEFINE_CAPMIX(num), \ + _DEFINE_CAPSRC(num), \ + { } /* end */ \ +} + +#define DEFINE_CAPMIX_NOSRC(num) \ +static struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \ + _DEFINE_CAPMIX(num), \ + { } /* end */ \ } /* up to three ADCs */ DEFINE_CAPMIX(1); DEFINE_CAPMIX(2); DEFINE_CAPMIX(3); - +DEFINE_CAPMIX_NOSRC(1); +DEFINE_CAPMIX_NOSRC(2); +DEFINE_CAPMIX_NOSRC(3); /* * ALC880 5-stack model @@ -4298,13 +4312,22 @@ static void alc880_auto_init(struct hda_codec *codec) static void set_capture_mixer(struct alc_spec *spec) { - static struct snd_kcontrol_new *caps[3] = { - alc_capture_mixer1, - alc_capture_mixer2, - alc_capture_mixer3, + static struct snd_kcontrol_new *caps[2][3] = { + { alc_capture_mixer_nosrc1, + alc_capture_mixer_nosrc2, + alc_capture_mixer_nosrc3 }, + { alc_capture_mixer1, + alc_capture_mixer2, + alc_capture_mixer3 }, }; - if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) - spec->cap_mixer = caps[spec->num_adc_nids - 1]; + if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) { + int mux; + if (spec->input_mux && spec->input_mux->num_items > 1) + mux = 1; + else + mux = 0; + spec->cap_mixer = caps[mux][spec->num_adc_nids - 1]; + } } #define set_beep_amp(spec, nid, idx, dir) \ -- GitLab From 14bafe3278e5da952a6586a5a9a9d286566049ed Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 23 Mar 2009 16:35:39 +0100 Subject: [PATCH 3944/4982] ALSA: hda - Use cached calls to get widget caps and pin caps Replace with the standard function calls to use caches for reading the widget caps and pin caps. hda_proc.c is still using the direct verbs to get raw values as much as possible. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 3 +-- sound/pci/hda/patch_sigmatel.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 0f70d2d102e..a4e5e595211 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -2321,8 +2321,7 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, * don't power down the widget if it controls * eapd and EAPD_BTLENABLE is set. */ - pincap = snd_hda_param_read(codec, nid, - AC_PAR_PIN_CAP); + pincap = snd_hda_query_pin_caps(codec, nid); if (pincap & AC_PINCAP_EAPD) { int eapd = snd_hda_codec_read(codec, nid, 0, diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index b1c180a9e9b..b5e108aa8f6 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -2869,8 +2869,7 @@ static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid) conn_len = snd_hda_get_connections(codec, nid, conn, HDA_MAX_CONNECTIONS); for (j = 0; j < conn_len; j++) { - wcaps = snd_hda_param_read(codec, conn[j], - AC_PAR_AUDIO_WIDGET_CAP); + wcaps = get_wcaps(codec, conn[j]); wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* we check only analog outputs */ if (wtype != AC_WID_AUD_OUT || (wcaps & AC_WCAP_DIGITAL)) -- GitLab From 53da1d9456fe7f87a920a78fdbdcf1225d197cb7 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 23 Mar 2009 16:07:24 +0100 Subject: [PATCH 3945/4982] fix ptrace slowness This patch fixes bug #12208: Bug-Entry : http://bugzilla.kernel.org/show_bug.cgi?id=12208 Subject : uml is very slow on 2.6.28 host This turned out to be not a scheduler regression, but an already existing problem in ptrace being triggered by subtle scheduler changes. The problem is this: - task A is ptracing task B - task B stops on a trace event - task A is woken up and preempts task B - task A calls ptrace on task B, which does ptrace_check_attach() - this calls wait_task_inactive(), which sees that task B is still on the runq - task A goes to sleep for a jiffy - ... Since UML does lots of the above sequences, those jiffies quickly add up to make it slow as hell. This patch solves this by not rescheduling in read_unlock() after ptrace_stop() has woken up the tracer. Thanks to Oleg Nesterov and Ingo Molnar for the feedback. Signed-off-by: Miklos Szeredi CC: stable@kernel.org Signed-off-by: Linus Torvalds --- kernel/signal.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/kernel/signal.c b/kernel/signal.c index 2a74fe87c0d..1c8814481a1 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1575,7 +1575,15 @@ static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info) read_lock(&tasklist_lock); if (may_ptrace_stop()) { do_notify_parent_cldstop(current, CLD_TRAPPED); + /* + * Don't want to allow preemption here, because + * sys_ptrace() needs this task to be inactive. + * + * XXX: implement read_unlock_no_resched(). + */ + preempt_disable(); read_unlock(&tasklist_lock); + preempt_enable_no_resched(); schedule(); } else { /* -- GitLab From 6574e001b4bc616022ee706a338fbbac26a9cedd Mon Sep 17 00:00:00 2001 From: Martin Michlmayr Date: Mon, 23 Mar 2009 19:13:21 +0100 Subject: [PATCH 3946/4982] [ARM] Kirkwood: Hook up I2C Hook up I2C on Marvell Kirkwood. Tested on a QNAP TS-219 which has RTC connected through I2C. Signed-off-by: Martin Michlmayr Signed-off-by: Nicolas Pitre --- arch/arm/mach-kirkwood/common.c | 40 +++++++++++++++++++ arch/arm/mach-kirkwood/common.h | 1 + .../arm/mach-kirkwood/include/mach/kirkwood.h | 1 + 3 files changed, 42 insertions(+) diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c index 9f012551794..19b03f62c3f 100644 --- a/arch/arm/mach-kirkwood/common.c +++ b/arch/arm/mach-kirkwood/common.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -370,6 +371,45 @@ void __init kirkwood_spi_init() } +/***************************************************************************** + * I2C + ****************************************************************************/ +static struct mv64xxx_i2c_pdata kirkwood_i2c_pdata = { + .freq_m = 8, /* assumes 166 MHz TCLK */ + .freq_n = 3, + .timeout = 1000, /* Default timeout of 1 second */ +}; + +static struct resource kirkwood_i2c_resources[] = { + { + .name = "i2c", + .start = I2C_PHYS_BASE, + .end = I2C_PHYS_BASE + 0x1f, + .flags = IORESOURCE_MEM, + }, { + .name = "i2c", + .start = IRQ_KIRKWOOD_TWSI, + .end = IRQ_KIRKWOOD_TWSI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device kirkwood_i2c = { + .name = MV64XXX_I2C_CTLR_NAME, + .id = 0, + .num_resources = ARRAY_SIZE(kirkwood_i2c_resources), + .resource = kirkwood_i2c_resources, + .dev = { + .platform_data = &kirkwood_i2c_pdata, + }, +}; + +void __init kirkwood_i2c_init(void) +{ + platform_device_register(&kirkwood_i2c); +} + + /***************************************************************************** * UART0 ****************************************************************************/ diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h index 9e5282684d5..c66a25066ce 100644 --- a/arch/arm/mach-kirkwood/common.h +++ b/arch/arm/mach-kirkwood/common.h @@ -37,6 +37,7 @@ void kirkwood_pcie_init(void); void kirkwood_sata_init(struct mv_sata_platform_data *sata_data); void kirkwood_sdio_init(struct mvsdio_platform_data *mvsdio_data); void kirkwood_spi_init(void); +void kirkwood_i2c_init(void); void kirkwood_uart0_init(void); void kirkwood_uart1_init(void); diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h index d3db30fe763..38c98685359 100644 --- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h +++ b/arch/arm/mach-kirkwood/include/mach/kirkwood.h @@ -93,6 +93,7 @@ #define DEVICE_ID (DEV_BUS_VIRT_BASE | 0x0034) #define RTC_PHYS_BASE (DEV_BUS_PHYS_BASE | 0x0300) #define SPI_PHYS_BASE (DEV_BUS_PHYS_BASE | 0x0600) +#define I2C_PHYS_BASE (DEV_BUS_PHYS_BASE | 0x1000) #define UART0_PHYS_BASE (DEV_BUS_PHYS_BASE | 0x2000) #define UART0_VIRT_BASE (DEV_BUS_VIRT_BASE | 0x2000) #define UART1_PHYS_BASE (DEV_BUS_PHYS_BASE | 0x2100) -- GitLab From a441891f9dbd38e62f30caba2e9e9d43bdf37729 Mon Sep 17 00:00:00 2001 From: Martin Michlmayr Date: Sun, 22 Mar 2009 15:21:25 +0100 Subject: [PATCH 3947/4982] [ARM] Kirkwood: More consistency regarding MPP naming With the exception of UART0, all MPP names are uppercase. Signed-off-by: Martin Michlmayr Signed-off-by: Nicolas Pitre --- arch/arm/mach-kirkwood/mpp.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-kirkwood/mpp.h b/arch/arm/mach-kirkwood/mpp.h index 45cccb74310..e021a80c2ca 100644 --- a/arch/arm/mach-kirkwood/mpp.h +++ b/arch/arm/mach-kirkwood/mpp.h @@ -90,13 +90,13 @@ #define MPP10_GPO MPP( 10, 0x0, 0, 1, 1, 1, 1, 1 ) #define MPP10_SPI_SCK MPP( 10, 0x2, 0, 1, 1, 1, 1, 1 ) -#define MPP10_UArt0_TXD MPP( 10, 0X3, 0, 1, 1, 1, 1, 1 ) +#define MPP10_UART0_TXD MPP( 10, 0X3, 0, 1, 1, 1, 1, 1 ) #define MPP10_SATA1_ACTn MPP( 10, 0x5, 0, 1, 0, 0, 1, 1 ) #define MPP10_PTP_TRIG_GEN MPP( 10, 0xc, 0, 1, 1, 1, 1, 1 ) #define MPP11_GPIO MPP( 11, 0x0, 1, 1, 1, 1, 1, 1 ) #define MPP11_SPI_MISO MPP( 11, 0x2, 1, 0, 1, 1, 1, 1 ) -#define MPP11_UArt0_RXD MPP( 11, 0x3, 1, 0, 1, 1, 1, 1 ) +#define MPP11_UART0_RXD MPP( 11, 0x3, 1, 0, 1, 1, 1, 1 ) #define MPP11_PTP_EVENT_REQ MPP( 11, 0x4, 1, 0, 1, 1, 1, 1 ) #define MPP11_PTP_TRIG_GEN MPP( 11, 0xc, 0, 1, 1, 1, 1, 1 ) #define MPP11_PTP_CLK MPP( 11, 0xd, 1, 0, 1, 1, 1, 1 ) -- GitLab From 37bebc70d7ad4144c571d74500db3bb26ec0c0eb Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Mon, 23 Mar 2009 20:34:11 +0100 Subject: [PATCH 3948/4982] posix timers: fix RLIMIT_CPU && fork() See http://bugzilla.kernel.org/show_bug.cgi?id=12911 copy_signal() copies signal->rlim, but RLIMIT_CPU is "lost". Because posix_cpu_timers_init_group() sets cputime_expires.prof_exp = 0 and thus fastpath_timer_check() returns false unless we have other cpu timers. This is the minimal fix for 2.6.29 (tested) and 2.6.28. The patch is not optimal, we need further cleanups here. With this patch update_rlimit_cpu() is not really needed, but I don't think it should be removed. The proper fix (I think) is: - set_process_cpu_timer() should just start the cputimer->running logic (it does), no need to change cputime_expires.xxx_exp - posix_cpu_timers_init_group() should set ->running when needed - fastpath_timer_check() can check ->running instead of task_cputime_zero(signal->cputime_expires) Reported-by: Peter Lojkin Signed-off-by: Oleg Nesterov Cc: Peter Zijlstra Cc: Roland McGrath Cc: [for 2.6.29.x] LKML-Reference: <20090323193411.GA17514@redhat.com> Signed-off-by: Ingo Molnar --- kernel/posix-cpu-timers.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index e976e505648..8e5d9a68b02 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c @@ -1370,7 +1370,8 @@ static inline int fastpath_timer_check(struct task_struct *tsk) if (task_cputime_expired(&group_sample, &sig->cputime_expires)) return 1; } - return 0; + + return sig->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY; } /* -- GitLab From 99b36e68d3e9aa75439cbbcf04c78dc1b78f4049 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 23 Mar 2009 16:10:36 -0400 Subject: [PATCH 3949/4982] [ARM] update mach-types Signed-off-by: Nicolas Pitre --- arch/arm/tools/mach-types | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index b4211d8b2ac..945e0d237a1 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -12,7 +12,7 @@ # # http://www.arm.linux.org.uk/developer/machines/?action=new # -# Last update: Thu Mar 12 18:01:45 2009 +# Last update: Mon Mar 23 20:09:01 2009 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -2124,3 +2124,11 @@ mx27wallace MACH_MX27WALLACE MX27WALLACE 2133 fmzwebmodul MACH_FMZWEBMODUL FMZWEBMODUL 2134 rd78x00_masa MACH_RD78X00_MASA RD78X00_MASA 2135 smallogger MACH_SMALLOGGER SMALLOGGER 2136 +ccw9p9215 MACH_CCW9P9215 CCW9P9215 2137 +dm355_leopard MACH_DM355_LEOPARD DM355_LEOPARD 2138 +ts219 MACH_TS219 TS219 2139 +tny_a9263 MACH_TNY_A9263 TNY_A9263 2140 +apollo MACH_APOLLO APOLLO 2141 +at91cap9stk MACH_AT91CAP9STK AT91CAP9STK 2142 +spc300 MACH_SPC300 SPC300 2143 +eko MACH_EKO EKO 2144 -- GitLab From 586dcf279baebc18aca943cd44014e3679510d5b Mon Sep 17 00:00:00 2001 From: Martin Michlmayr Date: Sun, 22 Mar 2009 15:22:11 +0100 Subject: [PATCH 3950/4982] [ARM] Kirkwood: Add support for QNAP TS-119/TS-219 Turbo NAS Add support for the QNAP TS-119 and TS-219 Turbo NAS devices. Signed-off-by: Martin Michlmayr Signed-off-by: Nicolas Pitre --- arch/arm/configs/kirkwood_defconfig | 20 ++- arch/arm/mach-kirkwood/Kconfig | 6 + arch/arm/mach-kirkwood/Makefile | 1 + arch/arm/mach-kirkwood/common.h | 1 + arch/arm/mach-kirkwood/ts219-setup.c | 220 +++++++++++++++++++++++++++ 5 files changed, 244 insertions(+), 4 deletions(-) create mode 100644 arch/arm/mach-kirkwood/ts219-setup.c diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig index 9ed4e1b8667..c367ae44012 100644 --- a/arch/arm/configs/kirkwood_defconfig +++ b/arch/arm/configs/kirkwood_defconfig @@ -180,6 +180,7 @@ CONFIG_MACH_DB88F6281_BP=y CONFIG_MACH_RD88F6192_NAS=y CONFIG_MACH_RD88F6281=y CONFIG_MACH_SHEEVAPLUG=y +CONFIG_MACH_TS219=y CONFIG_PLAT_ORION=y # @@ -852,13 +853,20 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set +CONFIG_INPUT_EVDEV=y # CONFIG_INPUT_EVBUG is not set # # Input Device Drivers # -# CONFIG_INPUT_KEYBOARD is not set +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TABLET is not set @@ -868,7 +876,11 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # # Hardware I/O ports # -# CONFIG_SERIO is not set +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set # CONFIG_GAMEPORT is not set # @@ -1271,7 +1283,7 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_PCF8563 is not set # CONFIG_RTC_DRV_PCF8583 is not set # CONFIG_RTC_DRV_M41T80 is not set -# CONFIG_RTC_DRV_S35390A is not set +CONFIG_RTC_DRV_S35390A=y # CONFIG_RTC_DRV_FM3130 is not set # CONFIG_RTC_DRV_RX8581 is not set diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig index 532443622a1..b5421cccd7e 100644 --- a/arch/arm/mach-kirkwood/Kconfig +++ b/arch/arm/mach-kirkwood/Kconfig @@ -26,6 +26,12 @@ config MACH_SHEEVAPLUG Say 'Y' here if you want your kernel to support the Marvell SheevaPlug Reference Board. +config MACH_TS219 + bool "QNAP TS-119 and TS-219 Turbo NAS" + help + Say 'Y' here if you want your kernel to support the + QNAP TS-119 and TS-219 Turbo NAS devices. + endmenu endif diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile index de81b4b5bd3..8f03c9b9bdd 100644 --- a/arch/arm/mach-kirkwood/Makefile +++ b/arch/arm/mach-kirkwood/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_MACH_DB88F6281_BP) += db88f6281-bp-setup.o obj-$(CONFIG_MACH_RD88F6192_NAS) += rd88f6192-nas-setup.o obj-$(CONFIG_MACH_RD88F6281) += rd88f6281-setup.o obj-$(CONFIG_MACH_SHEEVAPLUG) += sheevaplug-setup.o +obj-$(CONFIG_MACH_TS219) += ts219-setup.o diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h index c66a25066ce..6ee88406f38 100644 --- a/arch/arm/mach-kirkwood/common.h +++ b/arch/arm/mach-kirkwood/common.h @@ -41,6 +41,7 @@ void kirkwood_i2c_init(void); void kirkwood_uart0_init(void); void kirkwood_uart1_init(void); +extern int kirkwood_tclk; extern struct sys_timer kirkwood_timer; diff --git a/arch/arm/mach-kirkwood/ts219-setup.c b/arch/arm/mach-kirkwood/ts219-setup.c new file mode 100644 index 00000000000..dda5743cf3e --- /dev/null +++ b/arch/arm/mach-kirkwood/ts219-setup.c @@ -0,0 +1,220 @@ +/* + * + * QNAP TS-119/TS-219 Turbo NAS Board Setup + * + * Copyright (C) 2009 Martin Michlmayr + * Copyright (C) 2008 Byron Bradley + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "mpp.h" + +/**************************************************************************** + * 16 MiB NOR flash. The struct mtd_partition is not in the same order as the + * partitions on the device because we want to keep compatability with + * the QNAP firmware. + * Layout as used by QNAP: + * 0x00000000-0x00080000 : "U-Boot" + * 0x00200000-0x00400000 : "Kernel" + * 0x00400000-0x00d00000 : "RootFS" + * 0x00d00000-0x01000000 : "RootFS2" + * 0x00080000-0x000c0000 : "U-Boot Config" + * 0x000c0000-0x00200000 : "NAS Config" + * + * We'll use "RootFS1" instead of "RootFS" to stay compatible with the layout + * used by the QNAP TS-109/TS-209. + * + ***************************************************************************/ + +static struct mtd_partition qnap_ts219_partitions[] = { + { + .name = "U-Boot", + .size = 0x00080000, + .offset = 0, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "Kernel", + .size = 0x00200000, + .offset = 0x00200000, + }, { + .name = "RootFS1", + .size = 0x00900000, + .offset = 0x00400000, + }, { + .name = "RootFS2", + .size = 0x00300000, + .offset = 0x00d00000, + }, { + .name = "U-Boot Config", + .size = 0x00040000, + .offset = 0x00080000, + }, { + .name = "NAS Config", + .size = 0x00140000, + .offset = 0x000c0000, + }, +}; + +static const struct flash_platform_data qnap_ts219_flash = { + .type = "m25p128", + .name = "spi_flash", + .parts = qnap_ts219_partitions, + .nr_parts = ARRAY_SIZE(qnap_ts219_partitions), +}; + +static struct spi_board_info __initdata qnap_ts219_spi_slave_info[] = { + { + .modalias = "m25p80", + .platform_data = &qnap_ts219_flash, + .irq = -1, + .max_speed_hz = 20000000, + .bus_num = 0, + .chip_select = 0, + }, +}; + +static struct i2c_board_info __initdata qnap_ts219_i2c_rtc = { + I2C_BOARD_INFO("s35390a", 0x30), +}; + +static struct mv643xx_eth_platform_data qnap_ts219_ge00_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(8), +}; + +static struct mv_sata_platform_data qnap_ts219_sata_data = { + .n_ports = 2, +}; + +static struct gpio_keys_button qnap_ts219_buttons[] = { + { + .code = KEY_COPY, + .gpio = 15, + .desc = "USB Copy", + .active_low = 1, + }, + { + .code = KEY_RESTART, + .gpio = 16, + .desc = "Reset", + .active_low = 1, + }, +}; + +static struct gpio_keys_platform_data qnap_ts219_button_data = { + .buttons = qnap_ts219_buttons, + .nbuttons = ARRAY_SIZE(qnap_ts219_buttons), +}; + +static struct platform_device qnap_ts219_button_device = { + .name = "gpio-keys", + .id = -1, + .num_resources = 0, + .dev = { + .platform_data = &qnap_ts219_button_data, + } +}; + +static unsigned int qnap_ts219_mpp_config[] __initdata = { + MPP0_SPI_SCn, + MPP1_SPI_MOSI, + MPP2_SPI_SCK, + MPP3_SPI_MISO, + MPP8_TW_SDA, + MPP9_TW_SCK, + MPP10_UART0_TXD, + MPP11_UART0_RXD, + MPP13_UART1_TXD, /* PIC controller */ + MPP14_UART1_RXD, /* PIC controller */ + MPP15_GPIO, /* USB Copy button */ + MPP16_GPIO, /* Reset button */ + MPP20_SATA1_ACTn, + MPP21_SATA0_ACTn, + MPP22_SATA1_PRESENTn, + MPP23_SATA0_PRESENTn, + 0 +}; + + +/***************************************************************************** + * QNAP TS-x19 specific power off method via UART1-attached PIC + ****************************************************************************/ + +#define UART1_REG(x) (UART1_VIRT_BASE + ((UART_##x) << 2)) + +void qnap_ts219_power_off(void) +{ + /* 19200 baud divisor */ + const unsigned divisor = ((kirkwood_tclk + (8 * 19200)) / (16 * 19200)); + + pr_info("%s: triggering power-off...\n", __func__); + + /* hijack UART1 and reset into sane state (19200,8n1) */ + writel(0x83, UART1_REG(LCR)); + writel(divisor & 0xff, UART1_REG(DLL)); + writel((divisor >> 8) & 0xff, UART1_REG(DLM)); + writel(0x03, UART1_REG(LCR)); + writel(0x00, UART1_REG(IER)); + writel(0x00, UART1_REG(FCR)); + writel(0x00, UART1_REG(MCR)); + + /* send the power-off command 'A' to PIC */ + writel('A', UART1_REG(TX)); +} + +static void __init qnap_ts219_init(void) +{ + /* + * Basic setup. Needs to be called early. + */ + kirkwood_init(); + kirkwood_mpp_conf(qnap_ts219_mpp_config); + + kirkwood_uart0_init(); + kirkwood_uart1_init(); /* A PIC controller is connected here. */ + spi_register_board_info(qnap_ts219_spi_slave_info, + ARRAY_SIZE(qnap_ts219_spi_slave_info)); + kirkwood_spi_init(); + kirkwood_i2c_init(); + i2c_register_board_info(0, &qnap_ts219_i2c_rtc, 1); + kirkwood_ge00_init(&qnap_ts219_ge00_data); + kirkwood_sata_init(&qnap_ts219_sata_data); + kirkwood_ehci_init(); + platform_device_register(&qnap_ts219_button_device); + + pm_power_off = qnap_ts219_power_off; + +} + +MACHINE_START(TS219, "QNAP TS-119/TS-219") + /* Maintainer: Martin Michlmayr */ + .phys_io = KIRKWOOD_REGS_PHYS_BASE, + .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .init_machine = qnap_ts219_init, + .map_io = kirkwood_map_io, + .init_irq = kirkwood_init_irq, + .timer = &kirkwood_timer, +MACHINE_END -- GitLab From adaa0db1da2d885f49dd2dcc357cdbe68e6dc283 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 23 Mar 2009 13:33:11 -0700 Subject: [PATCH 3951/4982] myri_sbus: Convert to net_device_ops. Signed-off-by: David S. Miller --- drivers/net/myri_sbus.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index 88b52883ace..4ced27f1830 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c @@ -896,6 +896,15 @@ static const struct header_ops myri_header_ops = { .cache_update = myri_header_cache_update, }; +static const struct net_device_ops myri_ops = { + .ndo_open = myri_open, + .ndo_stop = myri_close, + .ndo_start_xmit = myri_start_xmit, + .ndo_set_multicast_list = myri_set_multicast, + .ndo_tx_timeout = myri_tx_timeout, + .ndo_change_mtu = myri_change_mtu, +}; + static int __devinit myri_sbus_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; @@ -1048,13 +1057,9 @@ static int __devinit myri_sbus_probe(struct of_device *op, const struct of_devic sbus_writel((1 << i), mp->cregs + MYRICTRL_IRQLVL); mp->dev = dev; - dev->open = &myri_open; - dev->stop = &myri_close; - dev->hard_start_xmit = &myri_start_xmit; - dev->tx_timeout = &myri_tx_timeout; dev->watchdog_timeo = 5*HZ; - dev->set_multicast_list = &myri_set_multicast; dev->irq = op->irqs[0]; + dev->netdev_ops = &myri_ops; /* Register interrupt handler now. */ DET(("Requesting MYRIcom IRQ line.\n")); @@ -1065,7 +1070,6 @@ static int __devinit myri_sbus_probe(struct of_device *op, const struct of_devic } dev->mtu = MYRINET_MTU; - dev->change_mtu = myri_change_mtu; dev->header_ops = &myri_header_ops; dev->hard_header_len = (ETH_HLEN + MYRI_PAD_LEN); -- GitLab From 2199b87a94375befd574a58b7824551c1e285833 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 23 Mar 2009 13:33:21 -0700 Subject: [PATCH 3952/4982] sunbmac: Convert to net_device_ops. Signed-off-by: David S. Miller --- drivers/net/sunbmac.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index 7f69c7f176c..70d96b7d71a 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c @@ -1074,6 +1074,15 @@ static const struct ethtool_ops bigmac_ethtool_ops = { .get_link = bigmac_get_link, }; +static const struct net_device_ops bigmac_ops = { + .ndo_open = bigmac_open, + .ndo_stop = bigmac_close, + .ndo_start_xmit = bigmac_start_xmit, + .ndo_get_stats = bigmac_get_stats, + .ndo_set_multicast_list = bigmac_set_multicast, + .ndo_tx_timeout = bigmac_tx_timeout, +}; + static int __devinit bigmac_ether_init(struct of_device *op, struct of_device *qec_op) { @@ -1187,16 +1196,8 @@ static int __devinit bigmac_ether_init(struct of_device *op, bp->dev = dev; /* Set links to our BigMAC open and close routines. */ - dev->open = &bigmac_open; - dev->stop = &bigmac_close; - dev->hard_start_xmit = &bigmac_start_xmit; dev->ethtool_ops = &bigmac_ethtool_ops; - - /* Set links to BigMAC statistic and multi-cast loading code. */ - dev->get_stats = &bigmac_get_stats; - dev->set_multicast_list = &bigmac_set_multicast; - - dev->tx_timeout = &bigmac_tx_timeout; + dev->netdev_ops = &bigmac_ops; dev->watchdog_timeo = 5*HZ; /* Finish net device registration. */ -- GitLab From c7670718cbca7a2f3c8751076cb62e1691006be9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 23 Mar 2009 13:33:28 -0700 Subject: [PATCH 3953/4982] sunlance: Convert to net_device_ops. Signed-off-by: David S. Miller --- drivers/net/sunlance.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index 16c528db725..3a2bb968466 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c @@ -1311,6 +1311,14 @@ static const struct ethtool_ops sparc_lance_ethtool_ops = { .get_link = sparc_lance_get_link, }; +static const struct net_device_ops sparc_lance_ops = { + .ndo_open = lance_open, + .ndo_stop = lance_close, + .ndo_start_xmit = lance_start_xmit, + .ndo_set_multicast_list = lance_set_multicast, + .ndo_tx_timeout = lance_tx_timeout, +}; + static int __devinit sparc_lance_probe_one(struct of_device *op, struct of_device *ledma, struct of_device *lebuffer) @@ -1462,13 +1470,9 @@ no_link_test: lp->dev = dev; SET_NETDEV_DEV(dev, &op->dev); - dev->open = &lance_open; - dev->stop = &lance_close; - dev->hard_start_xmit = &lance_start_xmit; - dev->tx_timeout = &lance_tx_timeout; dev->watchdog_timeo = 5*HZ; - dev->set_multicast_list = &lance_set_multicast; dev->ethtool_ops = &sparc_lance_ethtool_ops; + dev->netdev_ops = &sparc_lance_ops; dev->irq = op->irqs[0]; -- GitLab From ecd4137320b59759bbe57eef89040ee3e5e66039 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 23 Mar 2009 13:33:37 -0700 Subject: [PATCH 3954/4982] sunqe: Convert to net_device_ops. Signed-off-by: David S. Miller --- drivers/net/sunqe.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index fe0c3f24456..dd4757d087e 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c @@ -829,6 +829,14 @@ fail: return NULL; } +static const struct net_device_ops qec_ops = { + .ndo_open = qe_open, + .ndo_stop = qe_close, + .ndo_start_xmit = qe_start_xmit, + .ndo_set_multicast_list = qe_set_multicast, + .ndo_tx_timeout = qe_tx_timeout, +}; + static int __devinit qec_ether_init(struct of_device *op) { static unsigned version_printed; @@ -893,15 +901,11 @@ static int __devinit qec_ether_init(struct of_device *op) SET_NETDEV_DEV(dev, &op->dev); - dev->open = qe_open; - dev->stop = qe_close; - dev->hard_start_xmit = qe_start_xmit; - dev->set_multicast_list = qe_set_multicast; - dev->tx_timeout = qe_tx_timeout; dev->watchdog_timeo = 5*HZ; dev->irq = op->irqs[0]; dev->dma = 0; dev->ethtool_ops = &qe_ethtool_ops; + dev->netdev_ops = &qec_ops; res = register_netdev(dev); if (res) -- GitLab From 0c1355e36fdc304b102851312d80a1e69c01f5a2 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Sat, 21 Mar 2009 11:09:25 +0000 Subject: [PATCH 3955/4982] [ARM] orion5x: update of FPGA ID's for the TS-78xx Received official word finally from Technological Systems on which FPGA ID's they have released unto the world. Also an additional of a dummy entry matching the FPGA ID of the Verilog template on our wiki. Signed-off-by: Alexander Clouter Signed-off-by: Nicolas Pitre --- arch/arm/mach-orion5x/ts78xx-fpga.h | 10 ++++++++-- arch/arm/mach-orion5x/ts78xx-setup.c | 7 +++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-orion5x/ts78xx-fpga.h b/arch/arm/mach-orion5x/ts78xx-fpga.h index 0a314ddef65..0f9cdf45895 100644 --- a/arch/arm/mach-orion5x/ts78xx-fpga.h +++ b/arch/arm/mach-orion5x/ts78xx-fpga.h @@ -6,8 +6,14 @@ */ enum fpga_ids { /* Technologic Systems */ - TS7800_REV_B2 = FPGAID(0x00b480, 0x02), - TS7800_REV_B3 = FPGAID(0x00b480, 0x03), + TS7800_REV_1 = FPGAID(0x00b480, 0x01), + TS7800_REV_2 = FPGAID(0x00b480, 0x02), + TS7800_REV_3 = FPGAID(0x00b480, 0x03), + TS7800_REV_4 = FPGAID(0x00b480, 0x04), + TS7800_REV_5 = FPGAID(0x00b480, 0x05), + + /* Unaffordable & Expensive */ + UAE_DUMMY = FPGAID(0xffffff, 0x01), }; struct fpga_device { diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c index f5191ddea08..9a6b397f972 100644 --- a/arch/arm/mach-orion5x/ts78xx-setup.c +++ b/arch/arm/mach-orion5x/ts78xx-setup.c @@ -282,8 +282,11 @@ static void ts78xx_fpga_supports(void) { /* TODO: put this 'table' into ts78xx-fpga.h */ switch (ts78xx_fpga.id) { - case TS7800_REV_B2: - case TS7800_REV_B3: + case TS7800_REV_1: + case TS7800_REV_2: + case TS7800_REV_3: + case TS7800_REV_4: + case TS7800_REV_5: ts78xx_fpga.supports.ts_rtc.present = 1; ts78xx_fpga.supports.ts_nand.present = 1; break; -- GitLab From 1db4b2d221f14b9715c717dbd9a476469a687080 Mon Sep 17 00:00:00 2001 From: Jody McIntyre Date: Mon, 23 Mar 2009 13:13:34 -0400 Subject: [PATCH 3956/4982] trivial: fix orphan dates in ext2 documentation Revert the change to the orphan dates of Windows 95, DOS, compression. Add a new orphan date for OS/2. Signed-off-by: Jody McIntyre Acked-by: Pavel Machek Signed-off-by: Linus Torvalds --- Documentation/filesystems/ext2.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/filesystems/ext2.txt b/Documentation/filesystems/ext2.txt index 23448551cab..e055acb6b2d 100644 --- a/Documentation/filesystems/ext2.txt +++ b/Documentation/filesystems/ext2.txt @@ -376,7 +376,8 @@ Implementations for: Windows 95/98/NT/2000 http://www.chrysocome.net/explore2fs Windows 95 (*) http://www.yipton.net/content.html#FSDEXT2 DOS client (*) ftp://metalab.unc.edu/pub/Linux/system/filesystems/ext2/ -OS/2 (*) ftp://metalab.unc.edu/pub/Linux/system/filesystems/ext2/ +OS/2 (+) ftp://metalab.unc.edu/pub/Linux/system/filesystems/ext2/ RISC OS client http://www.esw-heim.tu-clausthal.de/~marco/smorbrod/IscaFS/ -(*) no longer actively developed/supported (as of Mar 2009) +(*) no longer actively developed/supported (as of Apr 2001) +(+) no longer actively developed/supported (as of Mar 2009) -- GitLab From 003086497f07f7f1e67c0c295e261740f822b377 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 23 Mar 2009 15:25:49 -0400 Subject: [PATCH 3957/4982] Build with -fno-dwarf2-cfi-asm With a sufficiently new compiler and binutils, code which wasn't previously generating .eh_frame sections has begun to. Certain architectures (powerpc, in this case) may generate unexpected relocation formats in response to this, preventing modules from loading. While the new relocation types should probably be handled, revert to the previous behaviour with regards to generation of .eh_frame sections. (This was reported against Fedora, which appears to be the only distro doing any building against gcc-4.4 at present: RH bz#486545.) Signed-off-by: Kyle McMartin Acked-by: Roland McGrath Cc: Alexandre Oliva Cc: Sam Ravnborg Signed-off-by: Linus Torvalds --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index a2c2efe9e82..210107d3aa9 100644 --- a/Makefile +++ b/Makefile @@ -569,6 +569,9 @@ KBUILD_CFLAGS += $(call cc-option,-Wno-pointer-sign,) # disable invalid "can't wrap" optimzations for signed / pointers KBUILD_CFLAGS += $(call cc-option,-fwrapv) +# revert to pre-gcc-4.4 behaviour of .eh_frame +KBUILD_CFLAGS += $(call cc-option,-fno-dwarf2-cfi-asm) + # Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments # But warn user when we do so warn-assign = \ -- GitLab From dac4696a4b4f6823efda32f92dbc236a918c376f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 23 Mar 2009 14:29:24 -0700 Subject: [PATCH 3958/4982] myri_sbus/sunbmac/sunlance/sunqe: Add missing net_device_ops entries. Noticed by Stephen Hemminger. Signed-off-by: David S. Miller --- drivers/net/myri_sbus.c | 2 ++ drivers/net/sunbmac.c | 3 +++ drivers/net/sunlance.c | 3 +++ drivers/net/sunqe.c | 3 +++ 4 files changed, 11 insertions(+) diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index 4ced27f1830..08534c08d30 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c @@ -903,6 +903,8 @@ static const struct net_device_ops myri_ops = { .ndo_set_multicast_list = myri_set_multicast, .ndo_tx_timeout = myri_tx_timeout, .ndo_change_mtu = myri_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, }; static int __devinit myri_sbus_probe(struct of_device *op, const struct of_device_id *match) diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index 70d96b7d71a..5017d7fcb40 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c @@ -1081,6 +1081,9 @@ static const struct net_device_ops bigmac_ops = { .ndo_get_stats = bigmac_get_stats, .ndo_set_multicast_list = bigmac_set_multicast, .ndo_tx_timeout = bigmac_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, }; static int __devinit bigmac_ether_init(struct of_device *op, diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index 3a2bb968466..afc7b351e5e 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c @@ -1317,6 +1317,9 @@ static const struct net_device_ops sparc_lance_ops = { .ndo_start_xmit = lance_start_xmit, .ndo_set_multicast_list = lance_set_multicast, .ndo_tx_timeout = lance_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, }; static int __devinit sparc_lance_probe_one(struct of_device *op, diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index dd4757d087e..c6ec61e0acc 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c @@ -835,6 +835,9 @@ static const struct net_device_ops qec_ops = { .ndo_start_xmit = qe_start_xmit, .ndo_set_multicast_list = qe_set_multicast, .ndo_tx_timeout = qe_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, }; static int __devinit qec_ether_init(struct of_device *op) -- GitLab From 3e303dc1215714308e21a45e2c0fa6f701ad0eb4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 23 Mar 2009 14:42:09 -0700 Subject: [PATCH 3959/4982] spider_net: Add missing .ndo_validate_addr Signed-off-by: David S. Miller --- drivers/net/spider_net.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 0288054249d..90e663f4515 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -2268,6 +2268,7 @@ static const struct net_device_ops spider_net_ops = { .ndo_change_mtu = spider_net_change_mtu, .ndo_do_ioctl = spider_net_do_ioctl, .ndo_tx_timeout = spider_net_tx_timeout, + .ndo_validate_addr = eth_validate_addr, /* HW VLAN */ #ifdef CONFIG_NET_POLL_CONTROLLER /* poll controller */ -- GitLab From 9b6682ff4c69484b6955f89f7902e3dde2481bed Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 23 Mar 2009 22:50:52 +0100 Subject: [PATCH 3960/4982] ALSA: hda - Add quirk for Acer Ferrari 5000 Add a quirk model=acer-aspire for Acer Ferrari 5000 with ALC883 codec. Note that model=auto doesn't work for this laptop because of broken BIOS (that doesn't set the subsystem id properly). Tested-by: Russ Dill Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 7a3c6db6d5b..82097790f6f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -8677,6 +8677,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG), SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE), SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_ACER_ASPIRE), + SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_ACER_ASPIRE), SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE), SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE), SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE), -- GitLab From e072b639dc13b06b65be487633dad9bb3d2067d5 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Mon, 23 Mar 2009 15:17:31 -0700 Subject: [PATCH 3961/4982] phy: add new LAN8710 and LAN8720 device ids to smsc phy driver LAN8710 and LAN8720 are two new 10/100 ethernet PHY models. The two share the same phy id, this patch adds it to the smsc phy driver. Signed-off-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/phy/smsc.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c index 1387187543e..5123bb954dd 100644 --- a/drivers/net/phy/smsc.c +++ b/drivers/net/phy/smsc.c @@ -159,6 +159,30 @@ static struct phy_driver lan911x_int_driver = { .driver = { .owner = THIS_MODULE, } }; +static struct phy_driver lan8710_driver = { + .phy_id = 0x0007c0f0, /* OUI=0x00800f, Model#=0x0f */ + .phy_id_mask = 0xfffffff0, + .name = "SMSC LAN8710/LAN8720", + + .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause + | SUPPORTED_Asym_Pause), + .flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG, + + /* basic functions */ + .config_aneg = genphy_config_aneg, + .read_status = genphy_read_status, + .config_init = smsc_phy_config_init, + + /* IRQ related */ + .ack_interrupt = smsc_phy_ack_interrupt, + .config_intr = smsc_phy_config_intr, + + .suspend = genphy_suspend, + .resume = genphy_resume, + + .driver = { .owner = THIS_MODULE, } +}; + static int __init smsc_init(void) { int ret; @@ -179,8 +203,14 @@ static int __init smsc_init(void) if (ret) goto err4; + ret = phy_driver_register (&lan8710_driver); + if (ret) + goto err5; + return 0; +err5: + phy_driver_unregister (&lan911x_int_driver); err4: phy_driver_unregister (&lan8700_driver); err3: @@ -193,6 +223,7 @@ err1: static void __exit smsc_exit(void) { + phy_driver_unregister (&lan8710_driver); phy_driver_unregister (&lan911x_int_driver); phy_driver_unregister (&lan8700_driver); phy_driver_unregister (&lan8187_driver); -- GitLab From 30842f2989aacfaba3ccb39829b3417be9313dbe Mon Sep 17 00:00:00 2001 From: Vitaly Mayatskikh Date: Mon, 23 Mar 2009 15:22:33 -0700 Subject: [PATCH 3962/4982] udp: Wrong locking code in udp seq_file infrastructure Reading zero bytes from /proc/net/udp or other similar files which use the same seq_file udp infrastructure panics kernel in that way: ===================================== [ BUG: bad unlock balance detected! ] ------------------------------------- read/1985 is trying to release lock (&table->hash[i].lock) at: [] udp_seq_stop+0x27/0x29 but there are no more locks to release! other info that might help us debug this: 1 lock held by read/1985: #0: (&p->lock){--..}, at: [] seq_read+0x38/0x348 stack backtrace: Pid: 1985, comm: read Not tainted 2.6.29-rc8 #9 Call Trace: [] ? udp_seq_stop+0x27/0x29 [] print_unlock_inbalance_bug+0xd6/0xe1 [] lock_release_non_nested+0x9e/0x1c6 [] ? seq_read+0xb2/0x348 [] ? mark_held_locks+0x68/0x86 [] ? udp_seq_stop+0x27/0x29 [] lock_release+0x15d/0x189 [] _spin_unlock_bh+0x1e/0x34 [] udp_seq_stop+0x27/0x29 [] seq_read+0x2bb/0x348 [] ? seq_read+0x0/0x348 [] proc_reg_read+0x90/0xaf [] vfs_read+0xa6/0x103 [] ? trace_hardirqs_on_caller+0x12f/0x153 [] sys_read+0x45/0x69 [] system_call_fastpath+0x16/0x1b BUG: scheduling while atomic: read/1985/0xffffff00 INFO: lockdep is turned off. Modules linked in: cpufreq_ondemand acpi_cpufreq freq_table dm_multipath kvm ppdev snd_hda_codec_analog snd_hda_intel snd_hda_codec snd_hwdep snd_seq_dummy snd_seq_oss snd_seq_midi_event arc4 snd_s eq ecb thinkpad_acpi snd_seq_device iwl3945 hwmon sdhci_pci snd_pcm_oss sdhci rfkill mmc_core snd_mixer_oss i2c_i801 mac80211 yenta_socket ricoh_mmc i2c_core iTCO_wdt snd_pcm iTCO_vendor_support rs rc_nonstatic snd_timer snd lib80211 cfg80211 soundcore snd_page_alloc video parport_pc output parport e1000e [last unloaded: scsi_wait_scan] Pid: 1985, comm: read Not tainted 2.6.29-rc8 #9 Call Trace: [] ? __debug_show_held_locks+0x1b/0x24 [] __schedule_bug+0x7e/0x83 [] schedule+0xce/0x838 [] ? fsnotify_access+0x5f/0x67 [] ? sysret_careful+0xb/0x37 [] ? trace_hardirqs_on_caller+0x1f/0x153 [] ? trace_hardirqs_on_thunk+0x3a/0x3f [] sysret_careful+0x31/0x37 read[1985]: segfault at 7fffc479bfe8 ip 0000003e7420a180 sp 00007fffc479bfa0 error 6 Kernel panic - not syncing: Aiee, killing interrupt handler! udp_seq_stop() tries to unlock not yet locked spinlock. The lock was lost during splitting global udp_hash_lock to subsequent spinlocks. Signed-off by: Vitaly Mayatskikh Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/udp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index c47c989cb1f..c8bee189a19 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1614,7 +1614,8 @@ static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk) } while (sk && (!net_eq(sock_net(sk), net) || sk->sk_family != state->family)); if (!sk) { - spin_unlock_bh(&state->udp_table->hash[state->bucket].lock); + if (state->bucket < UDP_HTABLE_SIZE) + spin_unlock_bh(&state->udp_table->hash[state->bucket].lock); return udp_get_first(seq, state->bucket + 1); } return sk; @@ -1632,6 +1633,9 @@ static struct sock *udp_get_idx(struct seq_file *seq, loff_t pos) static void *udp_seq_start(struct seq_file *seq, loff_t *pos) { + struct udp_iter_state *state = seq->private; + state->bucket = UDP_HTABLE_SIZE; + return *pos ? udp_get_idx(seq, *pos-1) : SEQ_START_TOKEN; } -- GitLab From 18f27383d9bdcb985cc39599e99917bdad101a60 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Thu, 19 Mar 2009 06:48:08 +0000 Subject: [PATCH 3963/4982] fsl_pq_mdio: Use proper address translation Currently the driver just read "reg" property for constructing MDIO bus IDs, but this won't work when we'll start using "ranges = <>" in the device tree, so this will pop up: Freescale PowerQUICC MII Bus: probed sysfs: duplicate filename 'mdio@520' can not be created ------------[ cut here ]------------ Badness at c00cb6b8 [verbose debug info unavailable] NIP: c00cb6b8 LR: c00cb6b8 CTR: c001271c REGS: cf82fc10 TRAP: 0700 Not tainted (2.6.29-rc7-03702-g7ccd10f) MSR: 00029032 CR: 42044022 XER: 20000000 TASK = cf81fbd0[1] 'swapper' THREAD: cf82e000 GPR00: c00cb6b8 cf82fcc0 cf81fbd0 0000003b 00000e42 ffffffff 00004000 00000e42 GPR08: c03cb0fc c03bfbdc 00000e42 c03cac50 22044022 1006a2bc 0ffcb000 00000000 GPR16: 0ffc04b0 0ffc5a40 00000000 0ffc79a8 0f7863a8 00000004 00000000 00000000 GPR24: c033a6a8 d1014520 cf85e840 cf82fd08 cf87cf2c cf82fcd8 cf85dea8 ffffffef NIP [c00cb6b8] sysfs_add_one+0x4c/0x54 LR [c00cb6b8] sysfs_add_one+0x4c/0x54 Call Trace: [cf82fcc0] [c00cb6b8] sysfs_add_one+0x4c/0x54 (unreliable) [cf82fcd0] [c00cbc18] create_dir+0x58/0xc0 [cf82fd00] [c00cbcc0] sysfs_create_dir+0x40/0x70 [cf82fd20] [c0159388] create_dir+0x28/0x78 [cf82fd30] [c0159824] kobject_add_internal+0x98/0x13c [cf82fd50] [c0159e98] kobject_add+0x60/0x98 [cf82fd80] [c018a480] device_add+0x98/0x2ac [cf82fda0] [c01a2380] mdiobus_register+0xbc/0x1c0 [cf82fdc0] [c019f31c] fsl_pq_mdio_probe+0x284/0x2a0 [cf82fe00] [c0223814] of_platform_device_probe+0x5c/0x84 ... This patch fixes the issue by translating the "reg" property to a full address, and thus avoids the duplicate names. Signed-off-by: Anton Vorontsov Acked-by: Kumar Gala Signed-off-by: David S. Miller --- drivers/net/fsl_pq_mdio.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/fsl_pq_mdio.c b/drivers/net/fsl_pq_mdio.c index 6be36b9bc31..b3079a5a7f2 100644 --- a/drivers/net/fsl_pq_mdio.c +++ b/drivers/net/fsl_pq_mdio.c @@ -194,11 +194,15 @@ static int *create_irq_map(struct device_node *np) void fsl_pq_mdio_bus_name(char *name, struct device_node *np) { - const u32 *reg; + const u32 *addr; + u64 taddr = OF_BAD_ADDR; - reg = of_get_property(np, "reg", NULL); + addr = of_get_address(np, 0, NULL, NULL); + if (addr) + taddr = of_translate_address(np, addr); - snprintf(name, MII_BUS_ID_SIZE, "%s@%x", np->name, reg ? *reg : 0); + snprintf(name, MII_BUS_ID_SIZE, "%s@%llx", np->name, + (unsigned long long)taddr); } /* Scan the bus in reverse, looking for an empty spot */ -- GitLab From d7001198366bffce4506ba21b7b0fee2de194f73 Mon Sep 17 00:00:00 2001 From: Jan Nikitenko Date: Fri, 28 Nov 2008 08:52:58 +0100 Subject: [PATCH 3964/4982] MIPS: Fix oops in dma_unmap_page on not coherent mips platforms dma_cache_wback_inv() expects virtual address, but physical was provided due to translation via plat_dma_addr_to_phys(). If replaced with dma_addr_to_virt(), page fault oops from dma_unmap_page() is gone on au1550 platform. Signed-off-by: Jan Nikitenko Acked-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/mm/dma-default.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index 546e6977d4f..bed56f1ac83 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -225,7 +225,7 @@ void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, if (!plat_device_is_coherent(dev) && direction != DMA_TO_DEVICE) { unsigned long addr; - addr = plat_dma_addr_to_phys(dma_address); + addr = dma_addr_to_virt(dma_address); dma_cache_wback_inv(addr, size); } -- GitLab From 5864810bc50de57e1b4757850d3208f69579af7f Mon Sep 17 00:00:00 2001 From: Shinya Kuribayashi Date: Wed, 18 Mar 2009 09:04:01 +0900 Subject: [PATCH 3965/4982] MIPS: VR5500: Enable prefetch Signed-off-by: Shinya Kuribayashi Signed-off-by: Ralf Baechle --- arch/mips/mm/c-r4k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index c43f4b26a69..871e828bc62 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -780,7 +780,7 @@ static void __cpuinit probe_pcache(void) c->dcache.ways = 2; c->dcache.waybit = 0; - c->options |= MIPS_CPU_CACHE_CDEX_P; + c->options |= MIPS_CPU_CACHE_CDEX_P | MIPS_CPU_PREFETCH; break; case CPU_TX49XX: -- GitLab From 5484879c0a50de7f60d403d375faff41cbd4ab01 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Sat, 21 Mar 2009 13:50:48 +0800 Subject: [PATCH 3966/4982] MIPS: compat: Remove duplicated #include Remove duplicated #include in arch/mips/kernel/linux32.c. Signed-off-by: Huang Weiyi Signed-off-by: Ralf Baechle --- arch/mips/kernel/linux32.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index 1a86f84fa94..49aac6e17df 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include -- GitLab From 89e18eb331cc83fb4923bbc9a93beb5cb53eca0a Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 23 Mar 2009 22:14:55 +0100 Subject: [PATCH 3967/4982] MIPS: Change {set,clear,change}_c0_ to return old value. This is more standard and useful and need for the following fix to work correctly. Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mipsregs.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 0417516503f..526f327475c 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -1391,11 +1391,11 @@ static inline void tlb_write_random(void) static inline unsigned int \ set_c0_##name(unsigned int set) \ { \ - unsigned int res; \ + unsigned int res, new; \ \ res = read_c0_##name(); \ - res |= set; \ - write_c0_##name(res); \ + new = res | set; \ + write_c0_##name(new); \ \ return res; \ } \ @@ -1403,24 +1403,24 @@ set_c0_##name(unsigned int set) \ static inline unsigned int \ clear_c0_##name(unsigned int clear) \ { \ - unsigned int res; \ + unsigned int res, new; \ \ res = read_c0_##name(); \ - res &= ~clear; \ - write_c0_##name(res); \ + new = res & ~clear; \ + write_c0_##name(new); \ \ return res; \ } \ \ static inline unsigned int \ -change_c0_##name(unsigned int change, unsigned int new) \ +change_c0_##name(unsigned int change, unsigned int val) \ { \ - unsigned int res; \ + unsigned int res, new; \ \ res = read_c0_##name(); \ - res &= ~change; \ - res |= (new & change); \ - write_c0_##name(res); \ + new = res & ~change; \ + new |= (val & change); \ + write_c0_##name(new); \ \ return res; \ } -- GitLab From 9fb4c2b9e06c0a197d867b34865b113a47370bd5 Mon Sep 17 00:00:00 2001 From: Chris Dearman Date: Fri, 20 Mar 2009 15:33:55 -0700 Subject: [PATCH 3968/4982] MIPS: R2: Fix problem with code that incorrectly modifies ebase. Commit 566f74f6b2f8b85d5b8d6caaf97e5672cecd3e3e had a change that incorrectly modified ebase. This backs out the lines that modified ebase. In addition, the ebase exception vector is now allocated with correct alignment and the ebase register updated according to the architecture specification. Based on original patch by David VomLehn . Signed-off-by: David VomLehn Signed-off-by: Chris Dearman Signed-off-by: Ralf Baechle --- arch/mips/kernel/traps.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index b2d7041341b..29fadaccecd 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1520,7 +1520,9 @@ void __cpuinit per_cpu_trap_init(void) #endif /* CONFIG_MIPS_MT_SMTC */ if (cpu_has_veic || cpu_has_vint) { + unsigned long sr = set_c0_status(ST0_BEV); write_c0_ebase(ebase); + write_c0_status(sr); /* Setting vector spacing enables EI/VI mode */ change_c0_intctl(0x3e0, VECTORSPACING); } @@ -1602,8 +1604,6 @@ void __cpuinit set_uncached_handler(unsigned long offset, void *addr, #ifdef CONFIG_64BIT unsigned long uncached_ebase = TO_UNCAC(ebase); #endif - if (cpu_has_mips_r2) - uncached_ebase += (read_c0_ebase() & 0x3ffff000); if (!addr) panic(panic_null_cerr); @@ -1635,9 +1635,11 @@ void __init trap_init(void) return; /* Already done */ #endif - if (cpu_has_veic || cpu_has_vint) - ebase = (unsigned long) alloc_bootmem_low_pages(0x200 + VECTORSPACING*64); - else { + if (cpu_has_veic || cpu_has_vint) { + unsigned long size = 0x200 + VECTORSPACING*64; + ebase = (unsigned long) + __alloc_bootmem(size, 1 << fls(size), 0); + } else { ebase = CAC_BASE; if (cpu_has_mips_r2) ebase += (read_c0_ebase() & 0x3ffff000); -- GitLab From 8e0ee43bc2c3e19db56a4adaa9a9b04ce885cd84 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 23 Mar 2009 16:12:14 -0700 Subject: [PATCH 3969/4982] Linux 2.6.29 --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 210107d3aa9..1ab3ebfc909 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 29 -EXTRAVERSION = -rc8 -NAME = Erotic Pickled Herring +EXTRAVERSION = +NAME = Temporary Tasmanian Devil # *DOCUMENTATION* # To see a list of typical targets execute "make help" -- GitLab From 039a6f6a39d2aa30ee53afdb213ea6dd4482928b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 23 Mar 2009 16:21:16 -0700 Subject: [PATCH 3970/4982] ucc_geth: Fix merge error. I left a merge failure unresolved, noticed by Stephen Rothwell. Signed-off-by: David S. Miller --- drivers/net/ucc_geth.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 8f0ac442c90..5f866e276dd 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -3641,14 +3641,9 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma if (err) return -1; -<<<<<<< HEAD:drivers/net/ucc_geth.c - snprintf(ug_info->mdio_bus, MII_BUS_ID_SIZE, "%x", - res.start&0xfffff); -======= uec_mdio_bus_name(bus_name, mdio); snprintf(ug_info->phy_bus_id, sizeof(ug_info->phy_bus_id), "%s:%02x", bus_name, *prop); ->>>>>>> 61fa9dcf9329cb92c220f7b656410fbe5e72f933:drivers/net/ucc_geth.c } /* get the phy interface type, or default to MII */ -- GitLab From 733ecc5c06bb2892f04ab1881721d665644cd261 Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Mon, 23 Mar 2009 18:07:23 -0700 Subject: [PATCH 3971/4982] omap mailbox: cleanup omap2 register definition with macro Signed-off-by: Hiroshi DOYU --- arch/arm/mach-omap2/mailbox.c | 77 +++++++++++++---------------------- 1 file changed, 29 insertions(+), 48 deletions(-) diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c index 32b7af3c610..4487a4de52f 100644 --- a/arch/arm/mach-omap2/mailbox.c +++ b/arch/arm/mach-omap2/mailbox.c @@ -1,9 +1,9 @@ /* - * Mailbox reservation modules for OMAP2 + * Mailbox reservation modules for OMAP2/3 * - * Copyright (C) 2006 Nokia Corporation + * Copyright (C) 2006-2009 Nokia Corporation * Written by: Hiroshi DOYU - * and Paul Mundt + * and Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -18,40 +18,19 @@ #include #include -#define MAILBOX_REVISION 0x00 -#define MAILBOX_SYSCONFIG 0x10 -#define MAILBOX_SYSSTATUS 0x14 -#define MAILBOX_MESSAGE_0 0x40 -#define MAILBOX_MESSAGE_1 0x44 -#define MAILBOX_MESSAGE_2 0x48 -#define MAILBOX_MESSAGE_3 0x4c -#define MAILBOX_MESSAGE_4 0x50 -#define MAILBOX_MESSAGE_5 0x54 -#define MAILBOX_FIFOSTATUS_0 0x80 -#define MAILBOX_FIFOSTATUS_1 0x84 -#define MAILBOX_FIFOSTATUS_2 0x88 -#define MAILBOX_FIFOSTATUS_3 0x8c -#define MAILBOX_FIFOSTATUS_4 0x90 -#define MAILBOX_FIFOSTATUS_5 0x94 -#define MAILBOX_MSGSTATUS_0 0xc0 -#define MAILBOX_MSGSTATUS_1 0xc4 -#define MAILBOX_MSGSTATUS_2 0xc8 -#define MAILBOX_MSGSTATUS_3 0xcc -#define MAILBOX_MSGSTATUS_4 0xd0 -#define MAILBOX_MSGSTATUS_5 0xd4 -#define MAILBOX_IRQSTATUS_0 0x100 -#define MAILBOX_IRQENABLE_0 0x104 -#define MAILBOX_IRQSTATUS_1 0x108 -#define MAILBOX_IRQENABLE_1 0x10c -#define MAILBOX_IRQSTATUS_2 0x110 -#define MAILBOX_IRQENABLE_2 0x114 -#define MAILBOX_IRQSTATUS_3 0x118 -#define MAILBOX_IRQENABLE_3 0x11c +#define MAILBOX_REVISION 0x000 +#define MAILBOX_SYSCONFIG 0x010 +#define MAILBOX_SYSSTATUS 0x014 +#define MAILBOX_MESSAGE(m) (0x040 + 4 * (m)) +#define MAILBOX_FIFOSTATUS(m) (0x080 + 4 * (m)) +#define MAILBOX_MSGSTATUS(m) (0x0c0 + 4 * (m)) +#define MAILBOX_IRQSTATUS(u) (0x100 + 8 * (u)) +#define MAILBOX_IRQENABLE(u) (0x104 + 8 * (u)) -static unsigned long mbox_base; +#define MAILBOX_IRQ_NEWMSG(u) (1 << (2 * (u))) +#define MAILBOX_IRQ_NOTFULL(u) (1 << (2 * (u) + 1)) -#define MAILBOX_IRQ_NOTFULL(n) (1 << (2 * (n) + 1)) -#define MAILBOX_IRQ_NEWMSG(n) (1 << (2 * (n))) +static unsigned long mbox_base; struct omap_mbox2_fifo { unsigned long msg; @@ -209,15 +188,15 @@ static struct omap_mbox_ops omap2_mbox_ops = { /* DSP */ static struct omap_mbox2_priv omap2_mbox_dsp_priv = { .tx_fifo = { - .msg = MAILBOX_MESSAGE_0, - .fifo_stat = MAILBOX_FIFOSTATUS_0, + .msg = MAILBOX_MESSAGE(0), + .fifo_stat = MAILBOX_FIFOSTATUS(0), }, .rx_fifo = { - .msg = MAILBOX_MESSAGE_1, - .msg_stat = MAILBOX_MSGSTATUS_1, + .msg = MAILBOX_MESSAGE(1), + .msg_stat = MAILBOX_MSGSTATUS(1), }, - .irqenable = MAILBOX_IRQENABLE_0, - .irqstatus = MAILBOX_IRQSTATUS_0, + .irqenable = MAILBOX_IRQENABLE(0), + .irqstatus = MAILBOX_IRQSTATUS(0), .notfull_bit = MAILBOX_IRQ_NOTFULL(0), .newmsg_bit = MAILBOX_IRQ_NEWMSG(1), }; @@ -232,15 +211,15 @@ EXPORT_SYMBOL(mbox_dsp_info); /* IVA */ static struct omap_mbox2_priv omap2_mbox_iva_priv = { .tx_fifo = { - .msg = MAILBOX_MESSAGE_2, - .fifo_stat = MAILBOX_FIFOSTATUS_2, + .msg = MAILBOX_MESSAGE(2), + .fifo_stat = MAILBOX_FIFOSTATUS(2), }, .rx_fifo = { - .msg = MAILBOX_MESSAGE_3, - .msg_stat = MAILBOX_MSGSTATUS_3, + .msg = MAILBOX_MESSAGE(3), + .msg_stat = MAILBOX_MSGSTATUS(3), }, - .irqenable = MAILBOX_IRQENABLE_3, - .irqstatus = MAILBOX_IRQSTATUS_3, + .irqenable = MAILBOX_IRQENABLE(3), + .irqstatus = MAILBOX_IRQSTATUS(3), .notfull_bit = MAILBOX_IRQ_NOTFULL(2), .newmsg_bit = MAILBOX_IRQ_NEWMSG(3), }; @@ -320,4 +299,6 @@ static void __exit omap2_mbox_exit(void) module_init(omap2_mbox_init); module_exit(omap2_mbox_exit); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("omap mailbox: omap2/3 architecture specific functions"); +MODULE_AUTHOR("Hiroshi DOYU , Paul Mundt"); -- GitLab From 6c20a68372f158def0a29657ce11b3609ed24f9a Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Mon, 23 Mar 2009 18:07:23 -0700 Subject: [PATCH 3972/4982] omap mailbox: add initial omap3 support Signed-off-by: Hiroshi DOYU --- arch/arm/mach-omap2/devices.c | 37 +++++++++--- arch/arm/mach-omap2/mailbox.c | 70 +++++++++++++--------- arch/arm/plat-omap/Kconfig | 8 +++ arch/arm/plat-omap/include/mach/omap34xx.h | 1 + 4 files changed, 80 insertions(+), 36 deletions(-) diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index ce03fa75077..d5f2a8118df 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -28,13 +28,14 @@ #include #include -#if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) -#define OMAP2_MBOX_BASE IO_ADDRESS(OMAP24XX_MAILBOX_BASE) +#if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE) -static struct resource mbox_resources[] = { +#define MBOX_REG_SIZE 0x120 + +static struct resource omap2_mbox_resources[] = { { - .start = OMAP2_MBOX_BASE, - .end = OMAP2_MBOX_BASE + 0x11f, + .start = OMAP24XX_MAILBOX_BASE, + .end = OMAP24XX_MAILBOX_BASE + MBOX_REG_SIZE - 1, .flags = IORESOURCE_MEM, }, { @@ -47,20 +48,40 @@ static struct resource mbox_resources[] = { }, }; +static struct resource omap3_mbox_resources[] = { + { + .start = OMAP34XX_MAILBOX_BASE, + .end = OMAP34XX_MAILBOX_BASE + MBOX_REG_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_24XX_MAIL_U0_MPU, + .flags = IORESOURCE_IRQ, + }, +}; + static struct platform_device mbox_device = { .name = "mailbox", .id = -1, - .num_resources = ARRAY_SIZE(mbox_resources), - .resource = mbox_resources, }; static inline void omap_init_mbox(void) { + if (cpu_is_omap2420()) { + mbox_device.num_resources = ARRAY_SIZE(omap2_mbox_resources); + mbox_device.resource = omap2_mbox_resources; + } else if (cpu_is_omap3430()) { + mbox_device.num_resources = ARRAY_SIZE(omap3_mbox_resources); + mbox_device.resource = omap3_mbox_resources; + } else { + pr_err("%s: platform not supported\n", __func__); + return; + } platform_device_register(&mbox_device); } #else static inline void omap_init_mbox(void) { } -#endif +#endif /* CONFIG_OMAP_MBOX_FWK */ #if defined(CONFIG_OMAP_STI) diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c index 4487a4de52f..d925ef3d7d4 100644 --- a/arch/arm/mach-omap2/mailbox.c +++ b/arch/arm/mach-omap2/mailbox.c @@ -30,7 +30,7 @@ #define MAILBOX_IRQ_NEWMSG(u) (1 << (2 * (u))) #define MAILBOX_IRQ_NOTFULL(u) (1 << (2 * (u) + 1)) -static unsigned long mbox_base; +static void __iomem *mbox_base; struct omap_mbox2_fifo { unsigned long msg; @@ -52,14 +52,14 @@ static struct clk *mbox_ick_handle; static void omap2_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq); -static inline unsigned int mbox_read_reg(unsigned int reg) +static inline unsigned int mbox_read_reg(size_t ofs) { - return __raw_readl(mbox_base + reg); + return __raw_readl(mbox_base + ofs); } -static inline void mbox_write_reg(unsigned int val, unsigned int reg) +static inline void mbox_write_reg(u32 val, size_t ofs) { - __raw_writel(val, mbox_base + reg); + __raw_writel(val, mbox_base + ofs); } /* Mailbox H/W preparations */ @@ -208,7 +208,7 @@ struct omap_mbox mbox_dsp_info = { }; EXPORT_SYMBOL(mbox_dsp_info); -/* IVA */ +#if defined(CONFIG_ARCH_OMAP2420) /* IVA */ static struct omap_mbox2_priv omap2_mbox_iva_priv = { .tx_fifo = { .msg = MAILBOX_MESSAGE(2), @@ -229,17 +229,12 @@ static struct omap_mbox mbox_iva_info = { .ops = &omap2_mbox_ops, .priv = &omap2_mbox_iva_priv, }; +#endif static int __init omap2_mbox_probe(struct platform_device *pdev) { struct resource *res; - int ret = 0; - - if (pdev->num_resources != 3) { - dev_err(&pdev->dev, "invalid number of resources: %d\n", - pdev->num_resources); - return -ENODEV; - } + int ret; /* MBOX base */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -247,34 +242,53 @@ static int __init omap2_mbox_probe(struct platform_device *pdev) dev_err(&pdev->dev, "invalid mem resource\n"); return -ENODEV; } - mbox_base = res->start; + mbox_base = ioremap(res->start, res->end - res->start); + if (!mbox_base) + return -ENOMEM; - /* DSP IRQ */ - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (unlikely(!res)) { + /* DSP or IVA2 IRQ */ + mbox_dsp_info.irq = platform_get_irq(pdev, 0); + if (mbox_dsp_info.irq < 0) { dev_err(&pdev->dev, "invalid irq resource\n"); - return -ENODEV; + ret = -ENODEV; + goto err_dsp; } - mbox_dsp_info.irq = res->start; ret = omap_mbox_register(&mbox_dsp_info); - - /* IVA IRQ */ - res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); - if (unlikely(!res)) { - dev_err(&pdev->dev, "invalid irq resource\n"); - return -ENODEV; + if (ret) + goto err_dsp; + +#if defined(CONFIG_ARCH_OMAP2420) /* IVA */ + if (cpu_is_omap2420()) { + /* IVA IRQ */ + res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); + if (unlikely(!res)) { + dev_err(&pdev->dev, "invalid irq resource\n"); + ret = -ENODEV; + goto err_iva1; + } + mbox_iva_info.irq = res->start; + ret = omap_mbox_register(&mbox_iva_info); + if (ret) + goto err_iva1; } - mbox_iva_info.irq = res->start; - - ret = omap_mbox_register(&mbox_iva_info); +#endif + return 0; +err_iva1: + omap_mbox_unregister(&mbox_dsp_info); +err_dsp: + iounmap(mbox_base); return ret; } static int omap2_mbox_remove(struct platform_device *pdev) { +#if defined(CONFIG_ARCH_OMAP2420) + omap_mbox_unregister(&mbox_iva_info); +#endif omap_mbox_unregister(&mbox_dsp_info); + iounmap(mbox_base); return 0; } diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 46d3b0b9ce6..6b1d5061032 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -104,6 +104,14 @@ config OMAP_MCBSP Say Y here if you want support for the OMAP Multichannel Buffered Serial Port. +config OMAP_MBOX_FWK + tristate "Mailbox framework support" + depends on ARCH_OMAP + default n + help + Say Y here if you want to use OMAP Mailbox framework support for + DSP, IVA1.0 and IVA2 in OMAP1/2/3. + choice prompt "System timer" default OMAP_MPU_TIMER diff --git a/arch/arm/plat-omap/include/mach/omap34xx.h b/arch/arm/plat-omap/include/mach/omap34xx.h index 8e0479fff05..89173f16b9b 100644 --- a/arch/arm/plat-omap/include/mach/omap34xx.h +++ b/arch/arm/plat-omap/include/mach/omap34xx.h @@ -61,6 +61,7 @@ #define OMAP2_CM_BASE OMAP3430_CM_BASE #define OMAP2_PRM_BASE OMAP3430_PRM_BASE #define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP34XX_IC_BASE) +#define OMAP34XX_MAILBOX_BASE (L4_34XX_BASE + 0x94000) #endif -- GitLab From 94fc58c6da019257680ae711c061cb403582a362 Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Mon, 23 Mar 2009 18:07:24 -0700 Subject: [PATCH 3973/4982] omap mailbox: print hardware revision at startup Signed-off-by: Hiroshi DOYU --- arch/arm/mach-omap2/mailbox.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c index d925ef3d7d4..44e9101ab69 100644 --- a/arch/arm/mach-omap2/mailbox.c +++ b/arch/arm/mach-omap2/mailbox.c @@ -74,6 +74,9 @@ static int omap2_mbox_startup(struct omap_mbox *mbox) } clk_enable(mbox_ick_handle); + l = mbox_read_reg(MAILBOX_REVISION); + pr_info("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f)); + /* set smart-idle & autoidle */ l = mbox_read_reg(MAILBOX_SYSCONFIG); l |= 0x00000011; -- GitLab From f48cca87703a4f4c372f1519e72e0fd6acb70d54 Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Mon, 23 Mar 2009 18:07:24 -0700 Subject: [PATCH 3974/4982] omap mailbox: fix empty struct device for omap_mbox Since "mbox->dev" doesn't exist and isn't created either at registration, this patch will create "struct device", which belongs to "omap-mailbox" class and set this pointer for the member of "struct omap_mbox". Signed-off-by: Hiroshi DOYU --- arch/arm/plat-omap/include/mach/mailbox.h | 4 +- arch/arm/plat-omap/mailbox.c | 63 +++++++++++------------ 2 files changed, 33 insertions(+), 34 deletions(-) diff --git a/arch/arm/plat-omap/include/mach/mailbox.h b/arch/arm/plat-omap/include/mach/mailbox.h index 7cbed9332e1..577db6852f4 100644 --- a/arch/arm/plat-omap/include/mach/mailbox.h +++ b/arch/arm/plat-omap/include/mach/mailbox.h @@ -53,7 +53,7 @@ struct omap_mbox { mbox_msg_t seq_snd, seq_rcv; - struct device dev; + struct device *dev; struct omap_mbox *next; void *priv; @@ -67,7 +67,7 @@ void omap_mbox_init_seq(struct omap_mbox *); struct omap_mbox *omap_mbox_get(const char *); void omap_mbox_put(struct omap_mbox *); -int omap_mbox_register(struct omap_mbox *); +int omap_mbox_register(struct device *parent, struct omap_mbox *); int omap_mbox_unregister(struct omap_mbox *); #endif /* MAILBOX_H */ diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index b52ce053e6f..75ede474d84 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c @@ -1,10 +1,9 @@ /* * OMAP mailbox driver * - * Copyright (C) 2006 Nokia Corporation. All rights reserved. + * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved. * - * Contact: Toshihiro Kobayashi - * Restructured by Hiroshi DOYU + * Contact: Hiroshi DOYU * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -136,7 +135,7 @@ static void mbox_rx_work(struct work_struct *work) unsigned long flags; if (mbox->rxq->callback == NULL) { - sysfs_notify(&mbox->dev.kobj, NULL, "mbox"); + sysfs_notify(&mbox->dev->kobj, NULL, "mbox"); return; } @@ -204,7 +203,7 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox) /* no more messages in the fifo. clear IRQ source. */ ack_mbox_irq(mbox, IRQ_RX); enable_mbox_irq(mbox, IRQ_RX); - nomem: +nomem: schedule_work(&mbox->rxq->work); } @@ -286,7 +285,7 @@ static ssize_t mbox_show(struct class *class, char *buf) static CLASS_ATTR(mbox, S_IRUGO, mbox_show, NULL); static struct class omap_mbox_class = { - .name = "omap_mbox", + .name = "omap-mailbox", }; static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox, @@ -333,21 +332,6 @@ static int omap_mbox_init(struct omap_mbox *mbox) return ret; } - mbox->dev.class = &omap_mbox_class; - dev_set_name(&mbox->dev, "%s", mbox->name); - dev_set_drvdata(&mbox->dev, mbox); - - ret = device_register(&mbox->dev); - if (unlikely(ret)) - goto fail_device_reg; - - ret = device_create_file(&mbox->dev, &dev_attr_mbox); - if (unlikely(ret)) { - printk(KERN_ERR - "device_create_file failed: %d\n", ret); - goto fail_create_mbox; - } - ret = request_irq(mbox->irq, mbox_interrupt, IRQF_DISABLED, mbox->name, mbox); if (unlikely(ret)) { @@ -377,10 +361,6 @@ static int omap_mbox_init(struct omap_mbox *mbox) fail_alloc_txq: free_irq(mbox->irq, mbox); fail_request_irq: - device_remove_file(&mbox->dev, &dev_attr_mbox); - fail_create_mbox: - device_unregister(&mbox->dev); - fail_device_reg: if (unlikely(mbox->ops->shutdown)) mbox->ops->shutdown(mbox); @@ -393,8 +373,6 @@ static void omap_mbox_fini(struct omap_mbox *mbox) mbox_queue_free(mbox->rxq); free_irq(mbox->irq, mbox); - device_remove_file(&mbox->dev, &dev_attr_mbox); - class_unregister(&omap_mbox_class); if (unlikely(mbox->ops->shutdown)) mbox->ops->shutdown(mbox); @@ -440,7 +418,7 @@ void omap_mbox_put(struct omap_mbox *mbox) } EXPORT_SYMBOL(omap_mbox_put); -int omap_mbox_register(struct omap_mbox *mbox) +int omap_mbox_register(struct device *parent, struct omap_mbox *mbox) { int ret = 0; struct omap_mbox **tmp; @@ -450,14 +428,31 @@ int omap_mbox_register(struct omap_mbox *mbox) if (mbox->next) return -EBUSY; + mbox->dev = device_create(&omap_mbox_class, + parent, 0, mbox, "%s", mbox->name); + if (IS_ERR(mbox->dev)) + return PTR_ERR(mbox->dev); + + ret = device_create_file(mbox->dev, &dev_attr_mbox); + if (ret) + goto err_sysfs; + write_lock(&mboxes_lock); tmp = find_mboxes(mbox->name); - if (*tmp) + if (*tmp) { ret = -EBUSY; - else - *tmp = mbox; + write_unlock(&mboxes_lock); + goto err_find; + } + *tmp = mbox; write_unlock(&mboxes_lock); + return 0; + +err_find: + device_remove_file(mbox->dev, &dev_attr_mbox); +err_sysfs: + device_unregister(mbox->dev); return ret; } EXPORT_SYMBOL(omap_mbox_register); @@ -473,6 +468,8 @@ int omap_mbox_unregister(struct omap_mbox *mbox) *tmp = mbox->next; mbox->next = NULL; write_unlock(&mboxes_lock); + device_remove_file(mbox->dev, &dev_attr_mbox); + device_unregister(mbox->dev); return 0; } tmp = &(*tmp)->next; @@ -501,4 +498,6 @@ static void __exit omap_mbox_class_exit(void) subsys_initcall(omap_mbox_class_init); module_exit(omap_mbox_class_exit); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("omap mailbox: interrupt driven messaging"); +MODULE_AUTHOR("Toshihiro Kobayashi and Hiroshi DOYU"); -- GitLab From f98d67a07e90f3ed7a6c351ae70bcd6bf8bcf478 Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Mon, 23 Mar 2009 18:07:25 -0700 Subject: [PATCH 3975/4982] omap mailbox: fix empty struct device for omap1 Signed-off-by: Hiroshi DOYU --- arch/arm/mach-omap1/devices.c | 2 +- arch/arm/mach-omap1/mailbox.c | 29 +++++++++++++++-------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c index ba5d7c08dc1..bbbaeb0abcd 100644 --- a/arch/arm/mach-omap1/devices.c +++ b/arch/arm/mach-omap1/devices.c @@ -86,7 +86,7 @@ static struct resource mbox_resources[] = { }; static struct platform_device mbox_device = { - .name = "mailbox", + .name = "omap1-mailbox", .id = -1, .num_resources = ARRAY_SIZE(mbox_resources), .resource = mbox_resources, diff --git a/arch/arm/mach-omap1/mailbox.c b/arch/arm/mach-omap1/mailbox.c index 59abbf331a9..0af4d6c85b4 100644 --- a/arch/arm/mach-omap1/mailbox.c +++ b/arch/arm/mach-omap1/mailbox.c @@ -1,7 +1,7 @@ /* * Mailbox reservation modules for DSP * - * Copyright (C) 2006 Nokia Corporation + * Copyright (C) 2006-2009 Nokia Corporation * Written by: Hiroshi DOYU * * This file is subject to the terms and conditions of the GNU General Public @@ -27,7 +27,7 @@ #define MAILBOX_DSP2ARM1_Flag 0x1c #define MAILBOX_DSP2ARM2_Flag 0x20 -unsigned long mbox_base; +static void __iomem *mbox_base; struct omap_mbox1_fifo { unsigned long cmd; @@ -40,14 +40,14 @@ struct omap_mbox1_priv { struct omap_mbox1_fifo rx_fifo; }; -static inline int mbox_read_reg(unsigned int reg) +static inline int mbox_read_reg(size_t ofs) { - return __raw_readw(mbox_base + reg); + return __raw_readw(mbox_base + ofs); } -static inline void mbox_write_reg(unsigned int val, unsigned int reg) +static inline void mbox_write_reg(u32 val, size_t ofs) { - __raw_writew(val, mbox_base + reg); + __raw_writew(val, mbox_base + ofs); } /* msg */ @@ -143,7 +143,7 @@ struct omap_mbox mbox_dsp_info = { }; EXPORT_SYMBOL(mbox_dsp_info); -static int __init omap1_mbox_probe(struct platform_device *pdev) +static int __devinit omap1_mbox_probe(struct platform_device *pdev) { struct resource *res; int ret = 0; @@ -170,12 +170,10 @@ static int __init omap1_mbox_probe(struct platform_device *pdev) } mbox_dsp_info.irq = res->start; - ret = omap_mbox_register(&mbox_dsp_info); - - return ret; + return omap_mbox_register(&pdev->dev, &mbox_dsp_info); } -static int omap1_mbox_remove(struct platform_device *pdev) +static int __devexit omap1_mbox_remove(struct platform_device *pdev) { omap_mbox_unregister(&mbox_dsp_info); @@ -184,9 +182,9 @@ static int omap1_mbox_remove(struct platform_device *pdev) static struct platform_driver omap1_mbox_driver = { .probe = omap1_mbox_probe, - .remove = omap1_mbox_remove, + .remove = __devexit_p(omap1_mbox_remove), .driver = { - .name = "mailbox", + .name = "omap1-mailbox", }, }; @@ -203,4 +201,7 @@ static void __exit omap1_mbox_exit(void) module_init(omap1_mbox_init); module_exit(omap1_mbox_exit); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("omap mailbox: omap1 architecture specific functions"); +MODULE_AUTHOR("Hiroshi DOYU" ); +MODULE_ALIAS("platform:omap1-mailbox"); -- GitLab From da8cfe03a461fe759041e7f130f96913b262aa6b Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Mon, 23 Mar 2009 18:07:25 -0700 Subject: [PATCH 3976/4982] omap mailbox: fix empty struct device for omap2 Signed-off-by: Hiroshi DOYU --- arch/arm/mach-omap2/devices.c | 2 +- arch/arm/mach-omap2/mailbox.c | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index d5f2a8118df..14537ffd8af 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -61,7 +61,7 @@ static struct resource omap3_mbox_resources[] = { }; static struct platform_device mbox_device = { - .name = "mailbox", + .name = "omap2-mailbox", .id = -1, }; diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c index 44e9101ab69..0b8476ba95f 100644 --- a/arch/arm/mach-omap2/mailbox.c +++ b/arch/arm/mach-omap2/mailbox.c @@ -234,7 +234,7 @@ static struct omap_mbox mbox_iva_info = { }; #endif -static int __init omap2_mbox_probe(struct platform_device *pdev) +static int __devinit omap2_mbox_probe(struct platform_device *pdev) { struct resource *res; int ret; @@ -257,7 +257,7 @@ static int __init omap2_mbox_probe(struct platform_device *pdev) goto err_dsp; } - ret = omap_mbox_register(&mbox_dsp_info); + ret = omap_mbox_register(&pdev->dev, &mbox_dsp_info); if (ret) goto err_dsp; @@ -271,7 +271,7 @@ static int __init omap2_mbox_probe(struct platform_device *pdev) goto err_iva1; } mbox_iva_info.irq = res->start; - ret = omap_mbox_register(&mbox_iva_info); + ret = omap_mbox_register(&pdev->dev, &mbox_iva_info); if (ret) goto err_iva1; } @@ -285,7 +285,7 @@ err_dsp: return ret; } -static int omap2_mbox_remove(struct platform_device *pdev) +static int __devexit omap2_mbox_remove(struct platform_device *pdev) { #if defined(CONFIG_ARCH_OMAP2420) omap_mbox_unregister(&mbox_iva_info); @@ -297,9 +297,9 @@ static int omap2_mbox_remove(struct platform_device *pdev) static struct platform_driver omap2_mbox_driver = { .probe = omap2_mbox_probe, - .remove = omap2_mbox_remove, + .remove = __devexit_p(omap2_mbox_remove), .driver = { - .name = "mailbox", + .name = "omap2-mailbox", }, }; @@ -319,3 +319,4 @@ module_exit(omap2_mbox_exit); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("omap mailbox: omap2/3 architecture specific functions"); MODULE_AUTHOR("Hiroshi DOYU , Paul Mundt"); +MODULE_ALIAS("platform:omap2-mailbox"); -- GitLab From c75ee7520b4ad48a6948f51ca43b2e46ebd3696a Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Mon, 23 Mar 2009 18:07:26 -0700 Subject: [PATCH 3977/4982] omap mailbox: add save_/restore_ctx() for PM To preserve the registers during off-mode Signed-off-by: Hiroshi DOYU --- arch/arm/mach-omap2/mailbox.c | 32 +++++++++++++++++++++++ arch/arm/plat-omap/include/mach/mailbox.h | 23 ++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c index 0b8476ba95f..fd5b8a5925c 100644 --- a/arch/arm/mach-omap2/mailbox.c +++ b/arch/arm/mach-omap2/mailbox.c @@ -30,6 +30,9 @@ #define MAILBOX_IRQ_NEWMSG(u) (1 << (2 * (u))) #define MAILBOX_IRQ_NOTFULL(u) (1 << (2 * (u) + 1)) +#define MBOX_REG_SIZE 0x120 +#define MBOX_NR_REGS (MBOX_REG_SIZE / sizeof(u32)) + static void __iomem *mbox_base; struct omap_mbox2_fifo { @@ -45,6 +48,7 @@ struct omap_mbox2_priv { unsigned long irqstatus; u32 newmsg_bit; u32 notfull_bit; + u32 ctx[MBOX_NR_REGS]; }; static struct clk *mbox_ick_handle; @@ -165,6 +169,32 @@ static int omap2_mbox_is_irq(struct omap_mbox *mbox, return (enable & status & bit); } +static void omap2_mbox_save_ctx(struct omap_mbox *mbox) +{ + int i; + struct omap_mbox2_priv *p = mbox->priv; + + for (i = 0; i < MBOX_NR_REGS; i++) { + p->ctx[i] = mbox_read_reg(i * sizeof(u32)); + + dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, + i, p->ctx[i]); + } +} + +static void omap2_mbox_restore_ctx(struct omap_mbox *mbox) +{ + int i; + struct omap_mbox2_priv *p = mbox->priv; + + for (i = 0; i < MBOX_NR_REGS; i++) { + mbox_write_reg(p->ctx[i], i * sizeof(u32)); + + dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, + i, p->ctx[i]); + } +} + static struct omap_mbox_ops omap2_mbox_ops = { .type = OMAP_MBOX_TYPE2, .startup = omap2_mbox_startup, @@ -177,6 +207,8 @@ static struct omap_mbox_ops omap2_mbox_ops = { .disable_irq = omap2_mbox_disable_irq, .ack_irq = omap2_mbox_ack_irq, .is_irq = omap2_mbox_is_irq, + .save_ctx = omap2_mbox_save_ctx, + .restore_ctx = omap2_mbox_restore_ctx, }; /* diff --git a/arch/arm/plat-omap/include/mach/mailbox.h b/arch/arm/plat-omap/include/mach/mailbox.h index 577db6852f4..b7a6991814e 100644 --- a/arch/arm/plat-omap/include/mach/mailbox.h +++ b/arch/arm/plat-omap/include/mach/mailbox.h @@ -33,6 +33,9 @@ struct omap_mbox_ops { void (*disable_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq); void (*ack_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq); int (*is_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq); + /* ctx */ + void (*save_ctx)(struct omap_mbox *mbox); + void (*restore_ctx)(struct omap_mbox *mbox); }; struct omap_mbox_queue { @@ -70,4 +73,24 @@ void omap_mbox_put(struct omap_mbox *); int omap_mbox_register(struct device *parent, struct omap_mbox *); int omap_mbox_unregister(struct omap_mbox *); +static inline void omap_mbox_save_ctx(struct omap_mbox *mbox) +{ + if (!mbox->ops->save_ctx) { + dev_err(mbox->dev, "%s:\tno save\n", __func__); + return; + } + + mbox->ops->save_ctx(mbox); +} + +static inline void omap_mbox_restore_ctx(struct omap_mbox *mbox) +{ + if (!mbox->ops->restore_ctx) { + dev_err(mbox->dev, "%s:\tno restore\n", __func__); + return; + } + + mbox->ops->restore_ctx(mbox); +} + #endif /* MAILBOX_H */ -- GitLab From 9ae0ee0076d51d9017e89004643825a67d852910 Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Mon, 23 Mar 2009 18:07:26 -0700 Subject: [PATCH 3978/4982] omap mailbox: move mailbox.h into mailbox.c no need to keep mailbox.h separately. Signed-off-by: Hiroshi DOYU --- arch/arm/plat-omap/mailbox.c | 86 +++++++++++++++++++++++++++++- arch/arm/plat-omap/mailbox.h | 100 ----------------------------------- 2 files changed, 85 insertions(+), 101 deletions(-) delete mode 100644 arch/arm/plat-omap/mailbox.h diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index 75ede474d84..fcac60dedc8 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c @@ -31,11 +31,95 @@ #include #include #include -#include "mailbox.h" static struct omap_mbox *mboxes; static DEFINE_RWLOCK(mboxes_lock); +/* + * Mailbox sequence bit API + */ +#if defined(CONFIG_ARCH_OMAP1) +# define MBOX_USE_SEQ_BIT +#elif defined(CONFIG_ARCH_OMAP2) +# define MBOX_USE_SEQ_BIT +#endif + +#ifdef MBOX_USE_SEQ_BIT +/* seq_rcv should be initialized with any value other than + * 0 and 1 << 31, to allow either value for the first + * message. */ +static inline void mbox_seq_init(struct omap_mbox *mbox) +{ + /* any value other than 0 and 1 << 31 */ + mbox->seq_rcv = 0xffffffff; +} + +static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg) +{ + /* add seq_snd to msg */ + *msg = (*msg & 0x7fffffff) | mbox->seq_snd; + /* flip seq_snd */ + mbox->seq_snd ^= 1 << 31; +} + +static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg) +{ + mbox_msg_t seq = msg & (1 << 31); + if (seq == mbox->seq_rcv) + return -1; + mbox->seq_rcv = seq; + return 0; +} +#else +static inline void mbox_seq_init(struct omap_mbox *mbox) +{ +} +static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg) +{ +} +static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg) +{ + return 0; +} +#endif + +/* Mailbox FIFO handle functions */ +static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) +{ + return mbox->ops->fifo_read(mbox); +} +static inline void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) +{ + mbox->ops->fifo_write(mbox, msg); +} +static inline int mbox_fifo_empty(struct omap_mbox *mbox) +{ + return mbox->ops->fifo_empty(mbox); +} +static inline int mbox_fifo_full(struct omap_mbox *mbox) +{ + return mbox->ops->fifo_full(mbox); +} + +/* Mailbox IRQ handle functions */ +static inline void enable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) +{ + mbox->ops->enable_irq(mbox, irq); +} +static inline void disable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) +{ + mbox->ops->disable_irq(mbox, irq); +} +static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) +{ + if (mbox->ops->ack_irq) + mbox->ops->ack_irq(mbox, irq); +} +static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) +{ + return mbox->ops->is_irq(mbox, irq); +} + /* Mailbox Sequence Bit function */ void omap_mbox_init_seq(struct omap_mbox *mbox) { diff --git a/arch/arm/plat-omap/mailbox.h b/arch/arm/plat-omap/mailbox.h deleted file mode 100644 index 67c6740b8ad..00000000000 --- a/arch/arm/plat-omap/mailbox.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Mailbox internal functions - * - * Copyright (C) 2006 Nokia Corporation - * Written by: Hiroshi DOYU - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef __ARCH_ARM_PLAT_MAILBOX_H -#define __ARCH_ARM_PLAT_MAILBOX_H - -/* - * Mailbox sequence bit API - */ -#if defined(CONFIG_ARCH_OMAP1) -# define MBOX_USE_SEQ_BIT -#elif defined(CONFIG_ARCH_OMAP2) -# define MBOX_USE_SEQ_BIT -#endif - -#ifdef MBOX_USE_SEQ_BIT -/* seq_rcv should be initialized with any value other than - * 0 and 1 << 31, to allow either value for the first - * message. */ -static inline void mbox_seq_init(struct omap_mbox *mbox) -{ - /* any value other than 0 and 1 << 31 */ - mbox->seq_rcv = 0xffffffff; -} - -static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg) -{ - /* add seq_snd to msg */ - *msg = (*msg & 0x7fffffff) | mbox->seq_snd; - /* flip seq_snd */ - mbox->seq_snd ^= 1 << 31; -} - -static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg) -{ - mbox_msg_t seq = msg & (1 << 31); - if (seq == mbox->seq_rcv) - return -1; - mbox->seq_rcv = seq; - return 0; -} -#else -static inline void mbox_seq_init(struct omap_mbox *mbox) -{ -} -static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg) -{ -} -static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg) -{ - return 0; -} -#endif - -/* Mailbox FIFO handle functions */ -static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) -{ - return mbox->ops->fifo_read(mbox); -} -static inline void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) -{ - mbox->ops->fifo_write(mbox, msg); -} -static inline int mbox_fifo_empty(struct omap_mbox *mbox) -{ - return mbox->ops->fifo_empty(mbox); -} -static inline int mbox_fifo_full(struct omap_mbox *mbox) -{ - return mbox->ops->fifo_full(mbox); -} - -/* Mailbox IRQ handle functions */ -static inline void enable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) -{ - mbox->ops->enable_irq(mbox, irq); -} -static inline void disable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) -{ - mbox->ops->disable_irq(mbox, irq); -} -static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) -{ - if (mbox->ops->ack_irq) - mbox->ops->ack_irq(mbox, irq); -} -static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) -{ - return mbox->ops->is_irq(mbox, irq); -} - -#endif /* __ARCH_ARM_PLAT_MAILBOX_H */ -- GitLab From 7a781afde63adf5d75042be8ada509c913a94afe Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Mon, 23 Mar 2009 18:07:31 -0700 Subject: [PATCH 3979/4982] omap mailbox: convert sequence bit checking to module paramter Signed-off-by: Hiroshi DOYU --- arch/arm/plat-omap/mailbox.c | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index fcac60dedc8..10f240558d9 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c @@ -32,30 +32,34 @@ #include #include +static int enable_seq_bit; +module_param(enable_seq_bit, bool, 0); +MODULE_PARM_DESC(enable_seq_bit, "Enable sequence bit checking."); + static struct omap_mbox *mboxes; static DEFINE_RWLOCK(mboxes_lock); /* * Mailbox sequence bit API */ -#if defined(CONFIG_ARCH_OMAP1) -# define MBOX_USE_SEQ_BIT -#elif defined(CONFIG_ARCH_OMAP2) -# define MBOX_USE_SEQ_BIT -#endif -#ifdef MBOX_USE_SEQ_BIT /* seq_rcv should be initialized with any value other than * 0 and 1 << 31, to allow either value for the first * message. */ static inline void mbox_seq_init(struct omap_mbox *mbox) { + if (!enable_seq_bit) + return; + /* any value other than 0 and 1 << 31 */ mbox->seq_rcv = 0xffffffff; } static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg) { + if (!enable_seq_bit) + return; + /* add seq_snd to msg */ *msg = (*msg & 0x7fffffff) | mbox->seq_snd; /* flip seq_snd */ @@ -64,24 +68,17 @@ static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg) static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg) { - mbox_msg_t seq = msg & (1 << 31); + mbox_msg_t seq; + + if (!enable_seq_bit) + return 0; + + seq = msg & (1 << 31); if (seq == mbox->seq_rcv) return -1; mbox->seq_rcv = seq; return 0; } -#else -static inline void mbox_seq_init(struct omap_mbox *mbox) -{ -} -static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg) -{ -} -static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg) -{ - return 0; -} -#endif /* Mailbox FIFO handle functions */ static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) -- GitLab From 8dff0fa55dfc22bfee6601c2552f89c52d2948f6 Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Mon, 23 Mar 2009 18:07:32 -0700 Subject: [PATCH 3980/4982] omap mailbox: remove unnecessary header file inclusion Signed-off-by: Hiroshi DOYU --- arch/arm/plat-omap/mailbox.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index 10f240558d9..0abfbaa5987 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c @@ -21,15 +21,11 @@ * */ -#include #include -#include #include #include -#include -#include #include -#include + #include static int enable_seq_bit; -- GitLab From d9558b19f2d1f01f6a11e148405cd3af63b8d6a8 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 23 Mar 2009 18:07:32 -0700 Subject: [PATCH 3981/4982] ARM: OMAP: No need to include board-perseus2.h or board-fsample.h from hardware.h Move defines to the board file and remove the now unnecessary headers. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/board-fsample.c | 34 ++++++++++++- .../plat-omap/include/mach/board-fsample.h | 51 ------------------- .../plat-omap/include/mach/board-perseus2.h | 39 -------------- arch/arm/plat-omap/include/mach/hardware.h | 8 --- 4 files changed, 33 insertions(+), 99 deletions(-) delete mode 100644 arch/arm/plat-omap/include/mach/board-fsample.h delete mode 100644 arch/arm/plat-omap/include/mach/board-perseus2.h diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c index 30308294e7c..19e0e923233 100644 --- a/arch/arm/mach-omap1/board-fsample.c +++ b/arch/arm/mach-omap1/board-fsample.c @@ -34,7 +34,39 @@ #include #include #include -#include + +/* fsample is pretty close to p2-sample */ + +#define fsample_cpld_read(reg) __raw_readb(reg) +#define fsample_cpld_write(val, reg) __raw_writeb(val, reg) + +#define FSAMPLE_CPLD_BASE 0xE8100000 +#define FSAMPLE_CPLD_SIZE SZ_4K +#define FSAMPLE_CPLD_START 0x05080000 + +#define FSAMPLE_CPLD_REG_A (FSAMPLE_CPLD_BASE + 0x00) +#define FSAMPLE_CPLD_SWITCH (FSAMPLE_CPLD_BASE + 0x02) +#define FSAMPLE_CPLD_UART (FSAMPLE_CPLD_BASE + 0x02) +#define FSAMPLE_CPLD_REG_B (FSAMPLE_CPLD_BASE + 0x04) +#define FSAMPLE_CPLD_VERSION (FSAMPLE_CPLD_BASE + 0x06) +#define FSAMPLE_CPLD_SET_CLR (FSAMPLE_CPLD_BASE + 0x06) + +#define FSAMPLE_CPLD_BIT_BT_RESET 0 +#define FSAMPLE_CPLD_BIT_LCD_RESET 1 +#define FSAMPLE_CPLD_BIT_CAM_PWDN 2 +#define FSAMPLE_CPLD_BIT_CHARGER_ENABLE 3 +#define FSAMPLE_CPLD_BIT_SD_MMC_EN 4 +#define FSAMPLE_CPLD_BIT_aGPS_PWREN 5 +#define FSAMPLE_CPLD_BIT_BACKLIGHT 6 +#define FSAMPLE_CPLD_BIT_aGPS_EN_RESET 7 +#define FSAMPLE_CPLD_BIT_aGPS_SLEEPx_N 8 +#define FSAMPLE_CPLD_BIT_OTG_RESET 9 + +#define fsample_cpld_set(bit) \ + fsample_cpld_write((((bit) & 15) << 4) | 0x0f, FSAMPLE_CPLD_SET_CLR) + +#define fsample_cpld_clear(bit) \ + fsample_cpld_write(0xf0 | ((bit) & 15), FSAMPLE_CPLD_SET_CLR) static int fsample_keymap[] = { KEY(0,0,KEY_UP), diff --git a/arch/arm/plat-omap/include/mach/board-fsample.h b/arch/arm/plat-omap/include/mach/board-fsample.h deleted file mode 100644 index cb3c5ae1277..00000000000 --- a/arch/arm/plat-omap/include/mach/board-fsample.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * arch/arm/plat-omap/include/mach/board-fsample.h - * - * Board-specific goodies for TI F-Sample. - * - * Copyright (C) 2006 Google, Inc. - * Author: Brian Swetland - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __ASM_ARCH_OMAP_FSAMPLE_H -#define __ASM_ARCH_OMAP_FSAMPLE_H - -/* fsample is pretty close to p2-sample */ -#include - -#define fsample_cpld_read(reg) __raw_readb(reg) -#define fsample_cpld_write(val, reg) __raw_writeb(val, reg) - -#define FSAMPLE_CPLD_BASE 0xE8100000 -#define FSAMPLE_CPLD_SIZE SZ_4K -#define FSAMPLE_CPLD_START 0x05080000 - -#define FSAMPLE_CPLD_REG_A (FSAMPLE_CPLD_BASE + 0x00) -#define FSAMPLE_CPLD_SWITCH (FSAMPLE_CPLD_BASE + 0x02) -#define FSAMPLE_CPLD_UART (FSAMPLE_CPLD_BASE + 0x02) -#define FSAMPLE_CPLD_REG_B (FSAMPLE_CPLD_BASE + 0x04) -#define FSAMPLE_CPLD_VERSION (FSAMPLE_CPLD_BASE + 0x06) -#define FSAMPLE_CPLD_SET_CLR (FSAMPLE_CPLD_BASE + 0x06) - -#define FSAMPLE_CPLD_BIT_BT_RESET 0 -#define FSAMPLE_CPLD_BIT_LCD_RESET 1 -#define FSAMPLE_CPLD_BIT_CAM_PWDN 2 -#define FSAMPLE_CPLD_BIT_CHARGER_ENABLE 3 -#define FSAMPLE_CPLD_BIT_SD_MMC_EN 4 -#define FSAMPLE_CPLD_BIT_aGPS_PWREN 5 -#define FSAMPLE_CPLD_BIT_BACKLIGHT 6 -#define FSAMPLE_CPLD_BIT_aGPS_EN_RESET 7 -#define FSAMPLE_CPLD_BIT_aGPS_SLEEPx_N 8 -#define FSAMPLE_CPLD_BIT_OTG_RESET 9 - -#define fsample_cpld_set(bit) \ - fsample_cpld_write((((bit) & 15) << 4) | 0x0f, FSAMPLE_CPLD_SET_CLR) - -#define fsample_cpld_clear(bit) \ - fsample_cpld_write(0xf0 | ((bit) & 15), FSAMPLE_CPLD_SET_CLR) - -#endif diff --git a/arch/arm/plat-omap/include/mach/board-perseus2.h b/arch/arm/plat-omap/include/mach/board-perseus2.h deleted file mode 100644 index c06c3d717d5..00000000000 --- a/arch/arm/plat-omap/include/mach/board-perseus2.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * arch/arm/plat-omap/include/mach/board-perseus2.h - * - * Copyright 2003 by Texas Instruments Incorporated - * OMAP730 / Perseus2 support by Jean Pihet - * - * Copyright (C) 2001 RidgeRun, Inc. (http://www.ridgerun.com) - * Author: RidgeRun, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#ifndef __ASM_ARCH_OMAP_PERSEUS2_H -#define __ASM_ARCH_OMAP_PERSEUS2_H - -#include - -#ifndef OMAP_SDRAM_DEVICE -#define OMAP_SDRAM_DEVICE D256M_1X16_4B -#endif - -#endif diff --git a/arch/arm/plat-omap/include/mach/hardware.h b/arch/arm/plat-omap/include/mach/hardware.h index 6589ddbb63b..5b59188ecea 100644 --- a/arch/arm/plat-omap/include/mach/hardware.h +++ b/arch/arm/plat-omap/include/mach/hardware.h @@ -302,14 +302,6 @@ #include "board-h2.h" #endif -#ifdef CONFIG_MACH_OMAP_PERSEUS2 -#include "board-perseus2.h" -#endif - -#ifdef CONFIG_MACH_OMAP_FSAMPLE -#include "board-fsample.h" -#endif - #ifdef CONFIG_MACH_OMAP_H3 #include "board-h3.h" #endif -- GitLab From eb6b0b1832a779cfa65bb66b8a88454d988a1d69 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 23 Mar 2009 18:07:33 -0700 Subject: [PATCH 3982/4982] ARM: OMAP: No need to include board-h2.h from hardware.h Also move board-h2.h to mach-omap1. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/board-h2-mmc.c | 2 ++ arch/arm/mach-omap1/board-h2.c | 5 +++++ arch/arm/{plat-omap/include/mach => mach-omap1}/board-h2.h | 5 +---- arch/arm/plat-omap/include/mach/hardware.h | 4 ---- 4 files changed, 8 insertions(+), 8 deletions(-) rename arch/arm/{plat-omap/include/mach => mach-omap1}/board-h2.h (90%) diff --git a/arch/arm/mach-omap1/board-h2-mmc.c b/arch/arm/mach-omap1/board-h2-mmc.c index 409fa56d0a8..44d4a966bed 100644 --- a/arch/arm/mach-omap1/board-h2-mmc.c +++ b/arch/arm/mach-omap1/board-h2-mmc.c @@ -19,6 +19,8 @@ #include #include +#include "board-h2.h" + #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) static int mmc_set_power(struct device *dev, int slot, int power_on, diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c index 0d784a79509..b31b6d9b2e3 100644 --- a/arch/arm/mach-omap1/board-h2.c +++ b/arch/arm/mach-omap1/board-h2.c @@ -46,6 +46,11 @@ #include #include +#include "board-h2.h" + +/* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */ +#define OMAP1610_ETHR_START 0x04000300 + static int h2_keymap[] = { KEY(0, 0, KEY_LEFT), KEY(0, 1, KEY_RIGHT), diff --git a/arch/arm/plat-omap/include/mach/board-h2.h b/arch/arm/mach-omap1/board-h2.h similarity index 90% rename from arch/arm/plat-omap/include/mach/board-h2.h rename to arch/arm/mach-omap1/board-h2.h index 15531c8dc0e..315e2662547 100644 --- a/arch/arm/plat-omap/include/mach/board-h2.h +++ b/arch/arm/mach-omap1/board-h2.h @@ -1,5 +1,5 @@ /* - * arch/arm/plat-omap/include/mach/board-h2.h + * arch/arm/mach-omap1/board-h2.h * * Hardware definitions for TI OMAP1610 H2 board. * @@ -29,9 +29,6 @@ #ifndef __ASM_ARCH_OMAP_H2_H #define __ASM_ARCH_OMAP_H2_H -/* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */ -#define OMAP1610_ETHR_START 0x04000300 - #define H2_TPS_GPIO_BASE (OMAP_MAX_GPIO_LINES + 16 /* MPUIO */) # define H2_TPS_GPIO_MMC_PWR_EN (H2_TPS_GPIO_BASE + 3) diff --git a/arch/arm/plat-omap/include/mach/hardware.h b/arch/arm/plat-omap/include/mach/hardware.h index 5b59188ecea..ac4d8d05155 100644 --- a/arch/arm/plat-omap/include/mach/hardware.h +++ b/arch/arm/plat-omap/include/mach/hardware.h @@ -298,10 +298,6 @@ #include "board-innovator.h" #endif -#ifdef CONFIG_MACH_OMAP_H2 -#include "board-h2.h" -#endif - #ifdef CONFIG_MACH_OMAP_H3 #include "board-h3.h" #endif -- GitLab From 228fe42e5e78649f4a773a47c0a48cbea8e640af Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 23 Mar 2009 18:07:33 -0700 Subject: [PATCH 3983/4982] ARM: OMAP: No need to include board-h3.h from hardware.h Also move board-h3.h to mach-omap1. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/board-h3-mmc.c | 2 ++ arch/arm/mach-omap1/board-h3.c | 5 +++++ arch/arm/{plat-omap/include/mach => mach-omap1}/board-h3.h | 5 +---- arch/arm/plat-omap/include/mach/hardware.h | 4 ---- 4 files changed, 8 insertions(+), 8 deletions(-) rename arch/arm/{plat-omap/include/mach => mach-omap1}/board-h3.h (90%) diff --git a/arch/arm/mach-omap1/board-h3-mmc.c b/arch/arm/mach-omap1/board-h3-mmc.c index fdfe793d56f..0d8a3c195e2 100644 --- a/arch/arm/mach-omap1/board-h3-mmc.c +++ b/arch/arm/mach-omap1/board-h3-mmc.c @@ -19,6 +19,8 @@ #include #include +#include "board-h3.h" + #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) static int mmc_set_power(struct device *dev, int slot, int power_on, diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index bf08b6ad22e..4b872f3822b 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c @@ -50,6 +50,11 @@ #include #include +#include "board-h3.h" + +/* In OMAP1710 H3 the Ethernet is directly connected to CS1 */ +#define OMAP1710_ETHR_START 0x04000300 + #define H3_TS_GPIO 48 static int h3_keymap[] = { diff --git a/arch/arm/plat-omap/include/mach/board-h3.h b/arch/arm/mach-omap1/board-h3.h similarity index 90% rename from arch/arm/plat-omap/include/mach/board-h3.h rename to arch/arm/mach-omap1/board-h3.h index 1888326da7e..78de535be3c 100644 --- a/arch/arm/plat-omap/include/mach/board-h3.h +++ b/arch/arm/mach-omap1/board-h3.h @@ -1,5 +1,5 @@ /* - * arch/arm/plat-omap/include/mach/board-h3.h + * arch/arm/mach-omap1/board-h3.h * * Copyright (C) 2001 RidgeRun, Inc. * Copyright (C) 2004 Texas Instruments, Inc. @@ -27,9 +27,6 @@ #ifndef __ASM_ARCH_OMAP_H3_H #define __ASM_ARCH_OMAP_H3_H -/* In OMAP1710 H3 the Ethernet is directly connected to CS1 */ -#define OMAP1710_ETHR_START 0x04000300 - #define H3_TPS_GPIO_BASE (OMAP_MAX_GPIO_LINES + 16 /* MPUIO */) # define H3_TPS_GPIO_MMC_PWR_EN (H3_TPS_GPIO_BASE + 4) diff --git a/arch/arm/plat-omap/include/mach/hardware.h b/arch/arm/plat-omap/include/mach/hardware.h index ac4d8d05155..040244cc719 100644 --- a/arch/arm/plat-omap/include/mach/hardware.h +++ b/arch/arm/plat-omap/include/mach/hardware.h @@ -298,10 +298,6 @@ #include "board-innovator.h" #endif -#ifdef CONFIG_MACH_OMAP_H3 -#include "board-h3.h" -#endif - #ifdef CONFIG_MACH_OMAP_H4 #include "board-h4.h" #endif -- GitLab From 278267be38949b051f49e0bc3da76bfb2af49abf Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 23 Mar 2009 18:07:34 -0700 Subject: [PATCH 3984/4982] ARM: OMAP: No need to include board-innovator.h from hardware.h Move the defines to the board file and remove the now unnecessary header file. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/board-innovator.c | 3 ++ .../plat-omap/include/mach/board-innovator.h | 52 ------------------- arch/arm/plat-omap/include/mach/hardware.h | 4 -- 3 files changed, 3 insertions(+), 56 deletions(-) delete mode 100644 arch/arm/plat-omap/include/mach/board-innovator.h diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c index 071cd02a734..714a08f79e9 100644 --- a/arch/arm/mach-omap1/board-innovator.c +++ b/arch/arm/mach-omap1/board-innovator.c @@ -39,6 +39,9 @@ #include #include +/* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */ +#define INNOVATOR1610_ETHR_START 0x04000300 + static int innovator_keymap[] = { KEY(0, 0, KEY_F1), KEY(0, 3, KEY_DOWN), diff --git a/arch/arm/plat-omap/include/mach/board-innovator.h b/arch/arm/plat-omap/include/mach/board-innovator.h deleted file mode 100644 index 5ae3e79b9f9..00000000000 --- a/arch/arm/plat-omap/include/mach/board-innovator.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * arch/arm/plat-omap/include/mach/board-innovator.h - * - * Copyright (C) 2001 RidgeRun, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#ifndef __ASM_ARCH_OMAP_INNOVATOR_H -#define __ASM_ARCH_OMAP_INNOVATOR_H - -#if defined (CONFIG_ARCH_OMAP15XX) - -#ifndef OMAP_SDRAM_DEVICE -#define OMAP_SDRAM_DEVICE D256M_1X16_4B -#endif - -#define OMAP1510P1_IMIF_PRI_VALUE 0x00 -#define OMAP1510P1_EMIFS_PRI_VALUE 0x00 -#define OMAP1510P1_EMIFF_PRI_VALUE 0x00 - -#ifndef __ASSEMBLY__ -void fpga_write(unsigned char val, int reg); -unsigned char fpga_read(int reg); -#endif - -#endif /* CONFIG_ARCH_OMAP15XX */ - -#if defined (CONFIG_ARCH_OMAP16XX) - -/* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */ -#define INNOVATOR1610_ETHR_START 0x04000300 - -#endif /* CONFIG_ARCH_OMAP1610 */ -#endif /* __ASM_ARCH_OMAP_INNOVATOR_H */ diff --git a/arch/arm/plat-omap/include/mach/hardware.h b/arch/arm/plat-omap/include/mach/hardware.h index 040244cc719..0b1b91f1981 100644 --- a/arch/arm/plat-omap/include/mach/hardware.h +++ b/arch/arm/plat-omap/include/mach/hardware.h @@ -294,10 +294,6 @@ * --------------------------------------------------------------------------- */ -#ifdef CONFIG_MACH_OMAP_INNOVATOR -#include "board-innovator.h" -#endif - #ifdef CONFIG_MACH_OMAP_H4 #include "board-h4.h" #endif -- GitLab From 3a0110cdae41fb91d005c335db9e5e697dddc5cd Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 23 Mar 2009 18:07:34 -0700 Subject: [PATCH 3985/4982] ARM: OMAP: No need to include board-osk.h from hardware.h Move the defines to the board file and remove the now unnecessary header file. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/board-osk.c | 14 ++++++ arch/arm/plat-omap/include/mach/board-osk.h | 47 --------------------- arch/arm/plat-omap/include/mach/hardware.h | 4 -- 3 files changed, 14 insertions(+), 51 deletions(-) delete mode 100644 arch/arm/plat-omap/include/mach/board-osk.h diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c index 1a16ecb2ccc..9c4cac274cc 100644 --- a/arch/arm/mach-omap1/board-osk.c +++ b/arch/arm/mach-omap1/board-osk.c @@ -52,6 +52,20 @@ #include #include +/* At OMAP5912 OSK the Ethernet is directly connected to CS1 */ +#define OMAP_OSK_ETHR_START 0x04800300 + +/* TPS65010 has four GPIOs. nPG and LED2 can be treated like GPIOs with + * alternate pin configurations for hardware-controlled blinking. + */ +#define OSK_TPS_GPIO_BASE (OMAP_MAX_GPIO_LINES + 16 /* MPUIO */) +# define OSK_TPS_GPIO_USB_PWR_EN (OSK_TPS_GPIO_BASE + 0) +# define OSK_TPS_GPIO_LED_D3 (OSK_TPS_GPIO_BASE + 1) +# define OSK_TPS_GPIO_LAN_RESET (OSK_TPS_GPIO_BASE + 2) +# define OSK_TPS_GPIO_DSP_PWR_EN (OSK_TPS_GPIO_BASE + 3) +# define OSK_TPS_GPIO_LED_D9 (OSK_TPS_GPIO_BASE + 4) +# define OSK_TPS_GPIO_LED_D2 (OSK_TPS_GPIO_BASE + 5) + static struct mtd_partition osk_partitions[] = { /* bootloader (U-Boot, etc) in first sector */ { diff --git a/arch/arm/plat-omap/include/mach/board-osk.h b/arch/arm/plat-omap/include/mach/board-osk.h deleted file mode 100644 index 3850cb1f220..00000000000 --- a/arch/arm/plat-omap/include/mach/board-osk.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * arch/arm/plat-omap/include/mach/board-osk.h - * - * Hardware definitions for TI OMAP5912 OSK board. - * - * Written by Dirk Behme - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __ASM_ARCH_OMAP_OSK_H -#define __ASM_ARCH_OMAP_OSK_H - -/* At OMAP5912 OSK the Ethernet is directly connected to CS1 */ -#define OMAP_OSK_ETHR_START 0x04800300 - -/* TPS65010 has four GPIOs. nPG and LED2 can be treated like GPIOs with - * alternate pin configurations for hardware-controlled blinking. - */ -#define OSK_TPS_GPIO_BASE (OMAP_MAX_GPIO_LINES + 16 /* MPUIO */) -# define OSK_TPS_GPIO_USB_PWR_EN (OSK_TPS_GPIO_BASE + 0) -# define OSK_TPS_GPIO_LED_D3 (OSK_TPS_GPIO_BASE + 1) -# define OSK_TPS_GPIO_LAN_RESET (OSK_TPS_GPIO_BASE + 2) -# define OSK_TPS_GPIO_DSP_PWR_EN (OSK_TPS_GPIO_BASE + 3) -# define OSK_TPS_GPIO_LED_D9 (OSK_TPS_GPIO_BASE + 4) -# define OSK_TPS_GPIO_LED_D2 (OSK_TPS_GPIO_BASE + 5) - -#endif /* __ASM_ARCH_OMAP_OSK_H */ - diff --git a/arch/arm/plat-omap/include/mach/hardware.h b/arch/arm/plat-omap/include/mach/hardware.h index 0b1b91f1981..201a8fa2479 100644 --- a/arch/arm/plat-omap/include/mach/hardware.h +++ b/arch/arm/plat-omap/include/mach/hardware.h @@ -314,10 +314,6 @@ #include "board-apollon.h" #endif -#ifdef CONFIG_MACH_OMAP_OSK -#include "board-osk.h" -#endif - #ifdef CONFIG_MACH_VOICEBLUE #include "board-voiceblue.h" #endif -- GitLab From b2830810fd8ca8cd8a929a6d6a6c886b1d689a51 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 23 Mar 2009 18:07:35 -0700 Subject: [PATCH 3986/4982] ARM: OMAP: No need to include board-palm*.h from hardware.h Move the defines to the associated board file and remove the now unnecessary header files. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/board-palmte.c | 15 +++++++++ arch/arm/mach-omap1/board-palmtt.c | 7 ++++ arch/arm/mach-omap1/board-palmz71.c | 10 ++++++ arch/arm/mach-omap1/board-sx1-mmc.c | 1 + arch/arm/mach-omap1/board-sx1.c | 1 + .../arm/plat-omap/include/mach/board-palmte.h | 32 ------------------- .../arm/plat-omap/include/mach/board-palmtt.h | 23 ------------- .../plat-omap/include/mach/board-palmz71.h | 26 --------------- arch/arm/plat-omap/include/mach/hardware.h | 12 ------- 9 files changed, 34 insertions(+), 93 deletions(-) delete mode 100644 arch/arm/plat-omap/include/mach/board-palmte.h delete mode 100644 arch/arm/plat-omap/include/mach/board-palmtt.h delete mode 100644 arch/arm/plat-omap/include/mach/board-palmz71.h diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c index 99f2b43f254..55d524b78e2 100644 --- a/arch/arm/mach-omap1/board-palmte.c +++ b/arch/arm/mach-omap1/board-palmte.c @@ -43,6 +43,21 @@ #include #include +#define PALMTE_USBDETECT_GPIO 0 +#define PALMTE_USB_OR_DC_GPIO 1 +#define PALMTE_TSC_GPIO 4 +#define PALMTE_PINTDAV_GPIO 6 +#define PALMTE_MMC_WP_GPIO 8 +#define PALMTE_MMC_POWER_GPIO 9 +#define PALMTE_HDQ_GPIO 11 +#define PALMTE_HEADPHONES_GPIO 14 +#define PALMTE_SPEAKER_GPIO 15 +#define PALMTE_DC_GPIO OMAP_MPUIO(2) +#define PALMTE_MMC_SWITCH_GPIO OMAP_MPUIO(4) +#define PALMTE_MMC1_GPIO OMAP_MPUIO(6) +#define PALMTE_MMC2_GPIO OMAP_MPUIO(7) +#define PALMTE_MMC3_GPIO OMAP_MPUIO(11) + static void __init omap_palmte_init_irq(void) { omap1_init_common_hw(); diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c index 1cbc1275c95..9dc9d7931b5 100644 --- a/arch/arm/mach-omap1/board-palmtt.c +++ b/arch/arm/mach-omap1/board-palmtt.c @@ -43,6 +43,13 @@ #include #include +#define PALMTT_USBDETECT_GPIO 0 +#define PALMTT_CABLE_GPIO 1 +#define PALMTT_LED_GPIO 3 +#define PALMTT_PENIRQ_GPIO 6 +#define PALMTT_MMC_WP_GPIO 8 +#define PALMTT_HDQ_GPIO 11 + static int palmtt_keymap[] = { KEY(0, 0, KEY_ESC), KEY(0, 1, KEY_SPACE), diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c index baf5efbfe3e..a2f99a46e7b 100644 --- a/arch/arm/mach-omap1/board-palmz71.c +++ b/arch/arm/mach-omap1/board-palmz71.c @@ -46,6 +46,16 @@ #include #include +#define PALMZ71_USBDETECT_GPIO 0 +#define PALMZ71_PENIRQ_GPIO 6 +#define PALMZ71_MMC_WP_GPIO 8 +#define PALMZ71_HDQ_GPIO 11 + +#define PALMZ71_HOTSYNC_GPIO OMAP_MPUIO(1) +#define PALMZ71_CABLE_GPIO OMAP_MPUIO(2) +#define PALMZ71_SLIDER_GPIO OMAP_MPUIO(3) +#define PALMZ71_MMC_IN_GPIO OMAP_MPUIO(4) + static void __init omap_palmz71_init_irq(void) { diff --git a/arch/arm/mach-omap1/board-sx1-mmc.c b/arch/arm/mach-omap1/board-sx1-mmc.c index 66a4d7d5255..58a46e4e45c 100644 --- a/arch/arm/mach-omap1/board-sx1-mmc.c +++ b/arch/arm/mach-omap1/board-sx1-mmc.c @@ -17,6 +17,7 @@ #include #include #include +#include #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c index 28c76a1e71c..ab277d42f30 100644 --- a/arch/arm/mach-omap1/board-sx1.c +++ b/arch/arm/mach-omap1/board-sx1.c @@ -41,6 +41,7 @@ #include #include #include +#include /* Write to I2C device */ int sx1_i2c_write_byte(u8 devaddr, u8 regoffset, u8 value) diff --git a/arch/arm/plat-omap/include/mach/board-palmte.h b/arch/arm/plat-omap/include/mach/board-palmte.h deleted file mode 100644 index 6906cdebbcf..00000000000 --- a/arch/arm/plat-omap/include/mach/board-palmte.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * arch/arm/plat-omap/include/mach/board-palmte.h - * - * Hardware definitions for the Palm Tungsten E device. - * - * Maintainters : http://palmtelinux.sf.net - * palmtelinux-developpers@lists.sf.net - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __OMAP_BOARD_PALMTE_H -#define __OMAP_BOARD_PALMTE_H - -#define PALMTE_USBDETECT_GPIO 0 -#define PALMTE_USB_OR_DC_GPIO 1 -#define PALMTE_TSC_GPIO 4 -#define PALMTE_PINTDAV_GPIO 6 -#define PALMTE_MMC_WP_GPIO 8 -#define PALMTE_MMC_POWER_GPIO 9 -#define PALMTE_HDQ_GPIO 11 -#define PALMTE_HEADPHONES_GPIO 14 -#define PALMTE_SPEAKER_GPIO 15 -#define PALMTE_DC_GPIO OMAP_MPUIO(2) -#define PALMTE_MMC_SWITCH_GPIO OMAP_MPUIO(4) -#define PALMTE_MMC1_GPIO OMAP_MPUIO(6) -#define PALMTE_MMC2_GPIO OMAP_MPUIO(7) -#define PALMTE_MMC3_GPIO OMAP_MPUIO(11) - -#endif /* __OMAP_BOARD_PALMTE_H */ diff --git a/arch/arm/plat-omap/include/mach/board-palmtt.h b/arch/arm/plat-omap/include/mach/board-palmtt.h deleted file mode 100644 index e79f382b593..00000000000 --- a/arch/arm/plat-omap/include/mach/board-palmtt.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * arch/arm/plat-omap/include/mach/board-palmte.h - * - * Hardware definitions for the Palm Tungsten|T device. - * - * Maintainters : Marek Vasut - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __OMAP_BOARD_PALMTT_H -#define __OMAP_BOARD_PALMTT_H - -#define PALMTT_USBDETECT_GPIO 0 -#define PALMTT_CABLE_GPIO 1 -#define PALMTT_LED_GPIO 3 -#define PALMTT_PENIRQ_GPIO 6 -#define PALMTT_MMC_WP_GPIO 8 -#define PALMTT_HDQ_GPIO 11 - -#endif /* __OMAP_BOARD_PALMTT_H */ diff --git a/arch/arm/plat-omap/include/mach/board-palmz71.h b/arch/arm/plat-omap/include/mach/board-palmz71.h deleted file mode 100644 index b1d7d579b31..00000000000 --- a/arch/arm/plat-omap/include/mach/board-palmz71.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * arch/arm/plat-omap/include/mach/board-palmz71.h - * - * Hardware definitions for the Palm Zire71 device. - * - * Maintainters : Marek Vasut - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __OMAP_BOARD_PALMZ71_H -#define __OMAP_BOARD_PALMZ71_H - -#define PALMZ71_USBDETECT_GPIO 0 -#define PALMZ71_PENIRQ_GPIO 6 -#define PALMZ71_MMC_WP_GPIO 8 -#define PALMZ71_HDQ_GPIO 11 - -#define PALMZ71_HOTSYNC_GPIO OMAP_MPUIO(1) -#define PALMZ71_CABLE_GPIO OMAP_MPUIO(2) -#define PALMZ71_SLIDER_GPIO OMAP_MPUIO(3) -#define PALMZ71_MMC_IN_GPIO OMAP_MPUIO(4) - -#endif /* __OMAP_BOARD_PALMZ71_H */ diff --git a/arch/arm/plat-omap/include/mach/hardware.h b/arch/arm/plat-omap/include/mach/hardware.h index 201a8fa2479..194ed49e4d7 100644 --- a/arch/arm/plat-omap/include/mach/hardware.h +++ b/arch/arm/plat-omap/include/mach/hardware.h @@ -318,18 +318,6 @@ #include "board-voiceblue.h" #endif -#ifdef CONFIG_MACH_OMAP_PALMTE -#include "board-palmte.h" -#endif - -#ifdef CONFIG_MACH_OMAP_PALMZ71 -#include "board-palmz71.h" -#endif - -#ifdef CONFIG_MACH_OMAP_PALMTT -#include "board-palmtt.h" -#endif - #ifdef CONFIG_MACH_SX1 #include "board-sx1.h" #endif -- GitLab From a362fdbddb713d27ec0931a8be64b767f85bae0d Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 23 Mar 2009 18:07:35 -0700 Subject: [PATCH 3987/4982] ARM: OMAP: No need to include board-omap2430sdp.h from hardware.h Move the defines to the associated board file and remove the now unnecessary header file. Also rename SDP2430_ETHR_GPIO_IRQ to SDP2430_ETHR_GPIO_IRQ. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-2430sdp.c | 13 +++--- .../plat-omap/include/mach/board-2430sdp.h | 41 ------------------- arch/arm/plat-omap/include/mach/hardware.h | 4 -- 3 files changed, 8 insertions(+), 50 deletions(-) delete mode 100644 arch/arm/plat-omap/include/mach/board-2430sdp.h diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index 83fa37211d7..c8abe6a8dfe 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -38,9 +38,12 @@ #include "mmc-twl4030.h" +#define SDP2430_CS0_BASE 0x04000000 #define SDP2430_FLASH_CS 0 #define SDP2430_SMC91X_CS 5 +#define SDP2430_ETHR_GPIO_IRQ 149 + static struct mtd_partition sdp2430_partitions[] = { /* bootloader (U-Boot, etc) in first sector */ { @@ -102,8 +105,8 @@ static struct resource sdp2430_smc91x_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = OMAP_GPIO_IRQ(OMAP24XX_ETHR_GPIO_IRQ), - .end = OMAP_GPIO_IRQ(OMAP24XX_ETHR_GPIO_IRQ), + .start = OMAP_GPIO_IRQ(SDP2430_ETHR_GPIO_IRQ), + .end = OMAP_GPIO_IRQ(SDP2430_ETHR_GPIO_IRQ), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, }, }; @@ -170,13 +173,13 @@ static inline void __init sdp2430_init_smc91x(void) sdp2430_smc91x_resources[0].end = cs_mem_base + 0x30f; udelay(100); - if (gpio_request(OMAP24XX_ETHR_GPIO_IRQ, "SMC91x irq") < 0) { + if (gpio_request(SDP2430_ETHR_GPIO_IRQ, "SMC91x irq") < 0) { printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n", - OMAP24XX_ETHR_GPIO_IRQ); + SDP2430_ETHR_GPIO_IRQ); gpmc_cs_free(eth_cs); goto out; } - gpio_direction_input(OMAP24XX_ETHR_GPIO_IRQ); + gpio_direction_input(SDP2430_ETHR_GPIO_IRQ); out: clk_disable(gpmc_fck); diff --git a/arch/arm/plat-omap/include/mach/board-2430sdp.h b/arch/arm/plat-omap/include/mach/board-2430sdp.h deleted file mode 100644 index 10d449ea7ed..00000000000 --- a/arch/arm/plat-omap/include/mach/board-2430sdp.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * arch/arm/plat-omap/include/mach/board-2430sdp.h - * - * Hardware definitions for TI OMAP2430 SDP board. - * - * Based on board-h4.h by Dirk Behme - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __ASM_ARCH_OMAP_2430SDP_H -#define __ASM_ARCH_OMAP_2430SDP_H - -/* Placeholder for 2430SDP specific defines */ -#define OMAP24XX_ETHR_START 0x08000300 -#define OMAP24XX_ETHR_GPIO_IRQ 149 -#define SDP2430_CS0_BASE 0x04000000 - -/* Function prototypes */ -extern void sdp2430_flash_init(void); -extern void sdp2430_usb_init(void); - -#endif /* __ASM_ARCH_OMAP_2430SDP_H */ diff --git a/arch/arm/plat-omap/include/mach/hardware.h b/arch/arm/plat-omap/include/mach/hardware.h index 194ed49e4d7..346a5c73197 100644 --- a/arch/arm/plat-omap/include/mach/hardware.h +++ b/arch/arm/plat-omap/include/mach/hardware.h @@ -298,10 +298,6 @@ #include "board-h4.h" #endif -#ifdef CONFIG_MACH_OMAP_2430SDP -#include "board-2430sdp.h" -#endif - #ifdef CONFIG_MACH_OMAP3_BEAGLE #include "board-omap3beagle.h" #endif -- GitLab From 7055477558686e106149bf0bb0edc0f5cd848ad9 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 23 Mar 2009 18:07:35 -0700 Subject: [PATCH 3988/4982] ARM: OMAP: No need to include board-apollon.h from hardware.h Move the defines to the associated board file and remove the now unnecessary header file. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-apollon.c | 1 + .../plat-omap/include/mach/board-apollon.h | 46 ------------------- arch/arm/plat-omap/include/mach/hardware.h | 4 -- 3 files changed, 1 insertion(+), 50 deletions(-) delete mode 100644 arch/arm/plat-omap/include/mach/board-apollon.h diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c index 0a7b24ba165..64561247d93 100644 --- a/arch/arm/mach-omap2/board-apollon.c +++ b/arch/arm/mach-omap2/board-apollon.c @@ -51,6 +51,7 @@ #define APOLLON_FLASH_CS 0 #define APOLLON_ETH_CS 1 +#define APOLLON_ETHR_GPIO_IRQ 74 static struct mtd_partition apollon_partitions[] = { { diff --git a/arch/arm/plat-omap/include/mach/board-apollon.h b/arch/arm/plat-omap/include/mach/board-apollon.h deleted file mode 100644 index 61bd5e8f09b..00000000000 --- a/arch/arm/plat-omap/include/mach/board-apollon.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * arch/arm/plat-omap/include/mach/board-apollon.h - * - * Hardware definitions for Samsung OMAP24XX Apollon board. - * - * Initial creation by Kyungmin Park - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __ASM_ARCH_OMAP_APOLLON_H -#define __ASM_ARCH_OMAP_APOLLON_H - -#include - -extern void apollon_mmc_init(void); - -static inline int apollon_plus(void) -{ - /* The apollon plus has IDCODE revision 5 */ - return omap_rev() & 0xc0; -} - -/* Placeholder for APOLLON specific defines */ -#define APOLLON_ETHR_GPIO_IRQ 74 - -#endif /* __ASM_ARCH_OMAP_APOLLON_H */ - diff --git a/arch/arm/plat-omap/include/mach/hardware.h b/arch/arm/plat-omap/include/mach/hardware.h index 346a5c73197..26f14f7b3e6 100644 --- a/arch/arm/plat-omap/include/mach/hardware.h +++ b/arch/arm/plat-omap/include/mach/hardware.h @@ -306,10 +306,6 @@ #include "board-ldp.h" #endif -#ifdef CONFIG_MACH_OMAP_APOLLON -#include "board-apollon.h" -#endif - #ifdef CONFIG_MACH_VOICEBLUE #include "board-voiceblue.h" #endif -- GitLab From 40662d77311d8de3a26c33f2fd5a2d4d810a4c8a Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 23 Mar 2009 18:07:36 -0700 Subject: [PATCH 3989/4982] ARM: OMAP: No need to include board-h4.h from hardware.h Move the defines to the associated board file and remove the now unnecessary header file. Also rename OMAP24XX_ETHR_GPIO_IRQ to H4_ETHR_GPIO_IRQ. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-h4.c | 4 ++- arch/arm/plat-omap/include/mach/board-h4.h | 38 ---------------------- arch/arm/plat-omap/include/mach/hardware.h | 4 --- 3 files changed, 3 insertions(+), 43 deletions(-) delete mode 100644 arch/arm/plat-omap/include/mach/board-h4.h diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c index 5e9b14675b1..71226973eee 100644 --- a/arch/arm/mach-omap2/board-h4.c +++ b/arch/arm/mach-omap2/board-h4.c @@ -47,6 +47,8 @@ #define H4_FLASH_CS 0 #define H4_SMC91X_CS 1 +#define H4_ETHR_GPIO_IRQ 92 + static unsigned int row_gpios[6] = { 88, 89, 124, 11, 6, 96 }; static unsigned int col_gpios[7] = { 90, 91, 100, 36, 12, 97, 98 }; @@ -341,7 +343,7 @@ static inline void __init h4_init_debug(void) udelay(100); omap_cfg_reg(M15_24XX_GPIO92); - if (debug_card_init(cs_mem_base, OMAP24XX_ETHR_GPIO_IRQ) < 0) + if (debug_card_init(cs_mem_base, H4_ETHR_GPIO_IRQ) < 0) gpmc_cs_free(eth_cs); out: diff --git a/arch/arm/plat-omap/include/mach/board-h4.h b/arch/arm/plat-omap/include/mach/board-h4.h deleted file mode 100644 index 7c3fa0f0a65..00000000000 --- a/arch/arm/plat-omap/include/mach/board-h4.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * arch/arm/plat-omap/include/mach/board-h4.h - * - * Hardware definitions for TI OMAP2420 H4 board. - * - * Initial creation by Dirk Behme - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __ASM_ARCH_OMAP_H4_H -#define __ASM_ARCH_OMAP_H4_H - -/* MMC Prototypes */ -extern void h4_mmc_init(void); - -/* Placeholder for H4 specific defines */ -#define OMAP24XX_ETHR_GPIO_IRQ 92 -#endif /* __ASM_ARCH_OMAP_H4_H */ - diff --git a/arch/arm/plat-omap/include/mach/hardware.h b/arch/arm/plat-omap/include/mach/hardware.h index 26f14f7b3e6..85f02b6a802 100644 --- a/arch/arm/plat-omap/include/mach/hardware.h +++ b/arch/arm/plat-omap/include/mach/hardware.h @@ -294,10 +294,6 @@ * --------------------------------------------------------------------------- */ -#ifdef CONFIG_MACH_OMAP_H4 -#include "board-h4.h" -#endif - #ifdef CONFIG_MACH_OMAP3_BEAGLE #include "board-omap3beagle.h" #endif -- GitLab From ec7558a62d2e28ec607fdfab1cd39b475d929ce5 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 23 Mar 2009 18:07:37 -0700 Subject: [PATCH 3990/4982] ARM: OMAP: No need to include board-ldp.h from hardware.h Move the defines to the associated board file and remove the now unnecessary header file. Also rename OMAP34XX_ETHR_START to LDP_ETHR_START. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-ldp.c | 10 +++--- arch/arm/plat-omap/include/mach/board-ldp.h | 39 --------------------- arch/arm/plat-omap/include/mach/hardware.h | 4 --- 3 files changed, 6 insertions(+), 47 deletions(-) delete mode 100644 arch/arm/plat-omap/include/mach/board-ldp.h diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index 6031e179926..f035d7836e5 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c @@ -28,7 +28,6 @@ #include #include -#include #include #include #include @@ -41,12 +40,15 @@ #include "mmc-twl4030.h" -#define SDP3430_SMC91X_CS 3 +#define LDP_SMC911X_CS 1 +#define LDP_SMC911X_GPIO 152 +#define DEBUG_BASE 0x08000000 +#define LDP_ETHR_START DEBUG_BASE static struct resource ldp_smc911x_resources[] = { [0] = { - .start = OMAP34XX_ETHR_START, - .end = OMAP34XX_ETHR_START + SZ_4K, + .start = LDP_ETHR_START, + .end = LDP_ETHR_START + SZ_4K, .flags = IORESOURCE_MEM, }, [1] = { diff --git a/arch/arm/plat-omap/include/mach/board-ldp.h b/arch/arm/plat-omap/include/mach/board-ldp.h deleted file mode 100644 index f2339966521..00000000000 --- a/arch/arm/plat-omap/include/mach/board-ldp.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * arch/arm/plat-omap/include/mach/board-ldp.h - * - * Hardware definitions for TI OMAP3 LDP. - * - * Copyright (C) 2008 Texas Instruments Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __ASM_ARCH_OMAP_LDP_H -#define __ASM_ARCH_OMAP_LDP_H - -extern void twl4030_bci_battery_init(void); - -#define TWL4030_IRQNUM INT_34XX_SYS_NIRQ -#define LDP_SMC911X_CS 1 -#define LDP_SMC911X_GPIO 152 -#define DEBUG_BASE 0x08000000 -#define OMAP34XX_ETHR_START DEBUG_BASE -#endif /* __ASM_ARCH_OMAP_LDP_H */ diff --git a/arch/arm/plat-omap/include/mach/hardware.h b/arch/arm/plat-omap/include/mach/hardware.h index 85f02b6a802..bba9498253e 100644 --- a/arch/arm/plat-omap/include/mach/hardware.h +++ b/arch/arm/plat-omap/include/mach/hardware.h @@ -298,10 +298,6 @@ #include "board-omap3beagle.h" #endif -#ifdef CONFIG_MACH_OMAP_LDP -#include "board-ldp.h" -#endif - #ifdef CONFIG_MACH_VOICEBLUE #include "board-voiceblue.h" #endif -- GitLab From 0d4d9ab08ac28b4742dadc35b5ac7613abf71475 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 23 Mar 2009 18:07:38 -0700 Subject: [PATCH 3991/4982] ARM: OMAP: No need to include board-overo.h from hardware.h Move the defines to the associated board file and remove the now unnecessary header file. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-overo.c | 7 ++++- arch/arm/plat-omap/include/mach/board-overo.h | 26 ------------------- 2 files changed, 6 insertions(+), 27 deletions(-) delete mode 100644 arch/arm/plat-omap/include/mach/board-overo.h diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index 82b3dc557c9..b92313c8b84 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -37,7 +37,6 @@ #include #include -#include #include #include #include @@ -47,6 +46,12 @@ #include "mmc-twl4030.h" +#define OVERO_GPIO_BT_XGATE 15 +#define OVERO_GPIO_W2W_NRESET 16 +#define OVERO_GPIO_BT_NRESET 164 +#define OVERO_GPIO_USBH_CPEN 168 +#define OVERO_GPIO_USBH_NRESET 183 + #define NAND_BLOCK_SIZE SZ_128K #define GPMC_CS0_BASE 0x60 #define GPMC_CS_SIZE 0x30 diff --git a/arch/arm/plat-omap/include/mach/board-overo.h b/arch/arm/plat-omap/include/mach/board-overo.h deleted file mode 100644 index 7ecae66966d..00000000000 --- a/arch/arm/plat-omap/include/mach/board-overo.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * board-overo.h (Gumstix Overo) - * - * Initial code: Steve Sakoman - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __ASM_ARCH_OVERO_H -#define __ASM_ARCH_OVERO_H - -#define OVERO_GPIO_BT_XGATE 15 -#define OVERO_GPIO_W2W_NRESET 16 -#define OVERO_GPIO_BT_NRESET 164 -#define OVERO_GPIO_USBH_CPEN 168 -#define OVERO_GPIO_USBH_NRESET 183 - -#endif /* ____ASM_ARCH_OVERO_H */ - -- GitLab From d40cdf080deac7dfa1b3c6ea216db97e872de1b2 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 23 Mar 2009 18:07:38 -0700 Subject: [PATCH 3992/4982] ARM: OMAP: No need to include board-nokia.h from hardware.h Move the defines to the associated board file and remove the now unnecessary header file. Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/mach/board-nokia.h | 54 ------------------- arch/arm/plat-omap/include/mach/board.h | 3 -- 2 files changed, 57 deletions(-) delete mode 100644 arch/arm/plat-omap/include/mach/board-nokia.h diff --git a/arch/arm/plat-omap/include/mach/board-nokia.h b/arch/arm/plat-omap/include/mach/board-nokia.h deleted file mode 100644 index 2abbe001af8..00000000000 --- a/arch/arm/plat-omap/include/mach/board-nokia.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * arch/arm/plat-omap/include/mach/board-nokia.h - * - * Information structures for Nokia-specific board config data - * - * Copyright (C) 2005 Nokia Corporation - */ - -#ifndef _OMAP_BOARD_NOKIA_H -#define _OMAP_BOARD_NOKIA_H - -#include - -#define OMAP_TAG_NOKIA_BT 0x4e01 -#define OMAP_TAG_WLAN_CX3110X 0x4e02 -#define OMAP_TAG_CBUS 0x4e03 -#define OMAP_TAG_EM_ASIC_BB5 0x4e04 - - -#define BT_CHIP_CSR 1 -#define BT_CHIP_TI 2 - -#define BT_SYSCLK_12 1 -#define BT_SYSCLK_38_4 2 - -struct omap_bluetooth_config { - u8 chip_type; - u8 bt_wakeup_gpio; - u8 host_wakeup_gpio; - u8 reset_gpio; - u8 bt_uart; - u8 bd_addr[6]; - u8 bt_sysclk; -}; - -struct omap_wlan_cx3110x_config { - u8 chip_type; - s16 power_gpio; - s16 irq_gpio; - s16 spi_cs_gpio; -}; - -struct omap_cbus_config { - s16 clk_gpio; - s16 dat_gpio; - s16 sel_gpio; -}; - -struct omap_em_asic_bb5_config { - s16 retu_irq_gpio; - s16 tahvo_irq_gpio; -}; - -#endif diff --git a/arch/arm/plat-omap/include/mach/board.h b/arch/arm/plat-omap/include/mach/board.h index 9466772fc7c..4a0afd2366e 100644 --- a/arch/arm/plat-omap/include/mach/board.h +++ b/arch/arm/plat-omap/include/mach/board.h @@ -133,9 +133,6 @@ struct omap_version_config { char version[12]; }; - -#include - struct omap_board_config_entry { u16 tag; u16 len; -- GitLab From 6b0147cda6a9d8c236cd04fb35b44de828d8a7eb Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 23 Mar 2009 18:07:39 -0700 Subject: [PATCH 3993/4982] ARM: OMAP: Remove remaining board-*.h includes from hardware.h Also remove board-omap3beagle.h that is not included anywhere, and move protoype for voiceblue_reset() from board-voiceblue.h to system.h. After this patch there are still board-ams-delta.h, board-sx1.h and board-voiceblue.h that export some functions. These could be removed if the functions were moved under drivers. Signed-off-by: Tony Lindgren --- .../include/mach/board-omap3beagle.h | 33 ------------------- .../plat-omap/include/mach/board-voiceblue.h | 1 - arch/arm/plat-omap/include/mach/hardware.h | 22 ------------- arch/arm/plat-omap/include/mach/system.h | 2 ++ 4 files changed, 2 insertions(+), 56 deletions(-) delete mode 100644 arch/arm/plat-omap/include/mach/board-omap3beagle.h diff --git a/arch/arm/plat-omap/include/mach/board-omap3beagle.h b/arch/arm/plat-omap/include/mach/board-omap3beagle.h deleted file mode 100644 index 3080d52d877..00000000000 --- a/arch/arm/plat-omap/include/mach/board-omap3beagle.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * arch/arm/plat-omap/include/mach/board-omap3beagle.h - * - * Hardware definitions for TI OMAP3 BEAGLE. - * - * Initial creation by Syed Mohammed Khasim - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __ASM_ARCH_OMAP3_BEAGLE_H -#define __ASM_ARCH_OMAP3_BEAGLE_H - -#endif /* __ASM_ARCH_OMAP3_BEAGLE_H */ - diff --git a/arch/arm/plat-omap/include/mach/board-voiceblue.h b/arch/arm/plat-omap/include/mach/board-voiceblue.h index ed6d346ee12..27916b210f5 100644 --- a/arch/arm/plat-omap/include/mach/board-voiceblue.h +++ b/arch/arm/plat-omap/include/mach/board-voiceblue.h @@ -14,7 +14,6 @@ extern void voiceblue_wdt_enable(void); extern void voiceblue_wdt_disable(void); extern void voiceblue_wdt_ping(void); -extern void voiceblue_reset(void); #endif /* __ASM_ARCH_VOICEBLUE_H */ diff --git a/arch/arm/plat-omap/include/mach/hardware.h b/arch/arm/plat-omap/include/mach/hardware.h index bba9498253e..3dc423ed3e8 100644 --- a/arch/arm/plat-omap/include/mach/hardware.h +++ b/arch/arm/plat-omap/include/mach/hardware.h @@ -286,26 +286,4 @@ #include "omap24xx.h" #include "omap34xx.h" -#ifndef __ASSEMBLER__ - -/* - * --------------------------------------------------------------------------- - * Board specific defines - * --------------------------------------------------------------------------- - */ - -#ifdef CONFIG_MACH_OMAP3_BEAGLE -#include "board-omap3beagle.h" -#endif - -#ifdef CONFIG_MACH_VOICEBLUE -#include "board-voiceblue.h" -#endif - -#ifdef CONFIG_MACH_SX1 -#include "board-sx1.h" -#endif - -#endif /* !__ASSEMBLER__ */ - #endif /* __ASM_ARCH_OMAP_HARDWARE_H */ diff --git a/arch/arm/plat-omap/include/mach/system.h b/arch/arm/plat-omap/include/mach/system.h index 06923f26154..8422845c5b6 100644 --- a/arch/arm/plat-omap/include/mach/system.h +++ b/arch/arm/plat-omap/include/mach/system.h @@ -11,6 +11,8 @@ #ifndef CONFIG_MACH_VOICEBLUE #define voiceblue_reset() do {} while (0) +#else +extern void voiceblue_reset(void); #endif extern void omap_prcm_arch_reset(char mode); -- GitLab From ae302f40061235f6bc58ae9ba02aa849d60223b5 Mon Sep 17 00:00:00 2001 From: "Zebediah C. McClure" Date: Mon, 23 Mar 2009 18:07:39 -0700 Subject: [PATCH 3994/4982] [OMAP850] Add base support for omap850 cpu Add base support for omap850 cpu. Signed-off-by: Zebediah C. McClure Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/id.c | 4 +- arch/arm/plat-omap/include/mach/cpu.h | 35 +++++++- arch/arm/plat-omap/include/mach/omap850.h | 102 ++++++++++++++++++++++ 3 files changed, 136 insertions(+), 5 deletions(-) create mode 100644 arch/arm/plat-omap/include/mach/omap850.h diff --git a/arch/arm/mach-omap1/id.c b/arch/arm/mach-omap1/id.c index 89bb8756f45..4ef26faf083 100644 --- a/arch/arm/mach-omap1/id.c +++ b/arch/arm/mach-omap1/id.c @@ -38,6 +38,7 @@ static struct omap_id omap_ids[] __initdata = { { .jtag_id = 0xb574, .die_rev = 0x2, .omap_id = 0x03310315, .type = 0x03100000}, { .jtag_id = 0x355f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300100}, { .jtag_id = 0xb55f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300300}, + { .jtag_id = 0xb55f, .die_rev = 0x0, .omap_id = 0x03320500, .type = 0x08500000}, { .jtag_id = 0xb470, .die_rev = 0x0, .omap_id = 0x03310100, .type = 0x15100000}, { .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x16100000}, { .jtag_id = 0xb576, .die_rev = 0x2, .omap_id = 0x03320100, .type = 0x16110000}, @@ -77,7 +78,7 @@ static u16 __init omap_get_jtag_id(void) prod_id = omap_readl(OMAP_PRODUCTION_ID_1); omap_id = omap_readl(OMAP32_ID_1); - /* Check for unusable OMAP_PRODUCTION_ID_1 on 1611B/5912 and 730 */ + /* Check for unusable OMAP_PRODUCTION_ID_1 on 1611B/5912 and 730/850 */ if (((prod_id >> 20) == 0) || (prod_id == omap_id)) prod_id = 0; else @@ -178,6 +179,7 @@ void __init omap_check_revision(void) switch (cpu_type) { case 0x07: + case 0x08: omap_revision |= 0x07; break; case 0x03: diff --git a/arch/arm/plat-omap/include/mach/cpu.h b/arch/arm/plat-omap/include/mach/cpu.h index a8e1178a946..366f829edb1 100644 --- a/arch/arm/plat-omap/include/mach/cpu.h +++ b/arch/arm/plat-omap/include/mach/cpu.h @@ -56,6 +56,14 @@ unsigned int omap_rev(void); # define OMAP_NAME omap730 # endif #endif +#ifdef CONFIG_ARCH_OMAP850 +# ifdef OMAP_NAME +# undef MULTI_OMAP1 +# define MULTI_OMAP1 +# else +# define OMAP_NAME omap850 +# endif +#endif #ifdef CONFIG_ARCH_OMAP15XX # ifdef OMAP_NAME # undef MULTI_OMAP1 @@ -105,7 +113,7 @@ unsigned int omap_rev(void); /* * Macros to group OMAP into cpu classes. * These can be used in most places. - * cpu_is_omap7xx(): True for OMAP730 + * cpu_is_omap7xx(): True for OMAP730, OMAP850 * cpu_is_omap15xx(): True for OMAP1510, OMAP5910 and OMAP310 * cpu_is_omap16xx(): True for OMAP1610, OMAP5912 and OMAP1710 * cpu_is_omap24xx(): True for OMAP2420, OMAP2422, OMAP2423, OMAP2430 @@ -153,6 +161,10 @@ IS_OMAP_SUBCLASS(343x, 0x343) # undef cpu_is_omap7xx # define cpu_is_omap7xx() is_omap7xx() # endif +# if defined(CONFIG_ARCH_OMAP850) +# undef cpu_is_omap7xx +# define cpu_is_omap7xx() is_omap7xx() +# endif # if defined(CONFIG_ARCH_OMAP15XX) # undef cpu_is_omap15xx # define cpu_is_omap15xx() is_omap15xx() @@ -166,6 +178,10 @@ IS_OMAP_SUBCLASS(343x, 0x343) # undef cpu_is_omap7xx # define cpu_is_omap7xx() 1 # endif +# if defined(CONFIG_ARCH_OMAP850) +# undef cpu_is_omap7xx +# define cpu_is_omap7xx() 1 +# endif # if defined(CONFIG_ARCH_OMAP15XX) # undef cpu_is_omap15xx # define cpu_is_omap15xx() 1 @@ -219,6 +235,7 @@ IS_OMAP_SUBCLASS(343x, 0x343) * These are only rarely needed. * cpu_is_omap330(): True for OMAP330 * cpu_is_omap730(): True for OMAP730 + * cpu_is_omap850(): True for OMAP850 * cpu_is_omap1510(): True for OMAP1510 * cpu_is_omap1610(): True for OMAP1610 * cpu_is_omap1611(): True for OMAP1611 @@ -241,6 +258,7 @@ static inline int is_omap ##type (void) \ IS_OMAP_TYPE(310, 0x0310) IS_OMAP_TYPE(730, 0x0730) +IS_OMAP_TYPE(850, 0x0850) IS_OMAP_TYPE(1510, 0x1510) IS_OMAP_TYPE(1610, 0x1610) IS_OMAP_TYPE(1611, 0x1611) @@ -255,6 +273,7 @@ IS_OMAP_TYPE(3430, 0x3430) #define cpu_is_omap310() 0 #define cpu_is_omap730() 0 +#define cpu_is_omap850() 0 #define cpu_is_omap1510() 0 #define cpu_is_omap1610() 0 #define cpu_is_omap5912() 0 @@ -272,12 +291,22 @@ IS_OMAP_TYPE(3430, 0x3430) # undef cpu_is_omap730 # define cpu_is_omap730() is_omap730() # endif +# if defined(CONFIG_ARCH_OMAP850) +# undef cpu_is_omap850 +# define cpu_is_omap850() is_omap850() +# endif #else # if defined(CONFIG_ARCH_OMAP730) # undef cpu_is_omap730 # define cpu_is_omap730() 1 # endif #endif +#else +# if defined(CONFIG_ARCH_OMAP850) +# undef cpu_is_omap850 +# define cpu_is_omap850() 1 +# endif +#endif /* * Whether we have MULTI_OMAP1 or not, we still need to distinguish @@ -320,7 +349,7 @@ IS_OMAP_TYPE(3430, 0x3430) #endif /* Macros to detect if we have OMAP1 or OMAP2 */ -#define cpu_class_is_omap1() (cpu_is_omap730() || cpu_is_omap15xx() || \ +#define cpu_class_is_omap1() (cpu_is_omap7xx() || cpu_is_omap15xx() || \ cpu_is_omap16xx()) #define cpu_class_is_omap2() (cpu_is_omap24xx() || cpu_is_omap34xx()) @@ -378,5 +407,3 @@ int omap_type(void); void omap2_check_revision(void); #endif /* defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) */ - -#endif diff --git a/arch/arm/plat-omap/include/mach/omap850.h b/arch/arm/plat-omap/include/mach/omap850.h new file mode 100644 index 00000000000..c33f6798171 --- /dev/null +++ b/arch/arm/plat-omap/include/mach/omap850.h @@ -0,0 +1,102 @@ +/* arch/arm/plat-omap/include/mach/omap850.h + * + * Hardware definitions for TI OMAP850 processor. + * + * Derived from omap730.h by Zebediah C. McClure + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __ASM_ARCH_OMAP850_H +#define __ASM_ARCH_OMAP850_H + +/* + * ---------------------------------------------------------------------------- + * Base addresses + * ---------------------------------------------------------------------------- + */ + +/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */ + +#define OMAP850_DSP_BASE 0xE0000000 +#define OMAP850_DSP_SIZE 0x50000 +#define OMAP850_DSP_START 0xE0000000 + +#define OMAP850_DSPREG_BASE 0xE1000000 +#define OMAP850_DSPREG_SIZE SZ_128K +#define OMAP850_DSPREG_START 0xE1000000 + +/* + * ---------------------------------------------------------------------------- + * OMAP850 specific configuration registers + * ---------------------------------------------------------------------------- + */ +#define OMAP850_CONFIG_BASE 0xfffe1000 +#define OMAP850_IO_CONF_0 0xfffe1070 +#define OMAP850_IO_CONF_1 0xfffe1074 +#define OMAP850_IO_CONF_2 0xfffe1078 +#define OMAP850_IO_CONF_3 0xfffe107c +#define OMAP850_IO_CONF_4 0xfffe1080 +#define OMAP850_IO_CONF_5 0xfffe1084 +#define OMAP850_IO_CONF_6 0xfffe1088 +#define OMAP850_IO_CONF_7 0xfffe108c +#define OMAP850_IO_CONF_8 0xfffe1090 +#define OMAP850_IO_CONF_9 0xfffe1094 +#define OMAP850_IO_CONF_10 0xfffe1098 +#define OMAP850_IO_CONF_11 0xfffe109c +#define OMAP850_IO_CONF_12 0xfffe10a0 +#define OMAP850_IO_CONF_13 0xfffe10a4 + +#define OMAP850_MODE_1 0xfffe1010 +#define OMAP850_MODE_2 0xfffe1014 + +/* CSMI specials: in terms of base + offset */ +#define OMAP850_MODE2_OFFSET 0x14 + +/* + * ---------------------------------------------------------------------------- + * OMAP850 traffic controller configuration registers + * ---------------------------------------------------------------------------- + */ +#define OMAP850_FLASH_CFG_0 0xfffecc10 +#define OMAP850_FLASH_ACFG_0 0xfffecc50 +#define OMAP850_FLASH_CFG_1 0xfffecc14 +#define OMAP850_FLASH_ACFG_1 0xfffecc54 + +/* + * ---------------------------------------------------------------------------- + * OMAP850 DSP control registers + * ---------------------------------------------------------------------------- + */ +#define OMAP850_ICR_BASE 0xfffbb800 +#define OMAP850_DSP_M_CTL 0xfffbb804 +#define OMAP850_DSP_MMU_BASE 0xfffed200 + +/* + * ---------------------------------------------------------------------------- + * OMAP850 PCC_UPLD configuration registers + * ---------------------------------------------------------------------------- + */ +#define OMAP850_PCC_UPLD_CTRL_BASE (0xfffe0900) +#define OMAP850_PCC_UPLD_CTRL (OMAP850_PCC_UPLD_CTRL_BASE + 0x00) + +#endif /* __ASM_ARCH_OMAP850_H */ + -- GitLab From 56739a692946d4c2630cf287646ccaa67c828f47 Mon Sep 17 00:00:00 2001 From: "Zebediah C. McClure" Date: Mon, 23 Mar 2009 18:07:40 -0700 Subject: [PATCH 3995/4982] [OMAP850] Changes to base IO subsystem, v2 Changes to base IO subsystem. Signed-off-by: Zebediah C. McClure Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/io.c | 23 +++++ arch/arm/mach-omap1/mux.c | 24 ++++++ arch/arm/mach-omap1/serial.c | 7 ++ arch/arm/plat-omap/gpio.c | 111 +++++++++++++++++++++++-- arch/arm/plat-omap/include/mach/gpio.h | 3 +- arch/arm/plat-omap/include/mach/mux.h | 52 +++++++++++- 6 files changed, 212 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c index 4c3e582f3d3..3afe540149f 100644 --- a/arch/arm/mach-omap1/io.c +++ b/arch/arm/mach-omap1/io.c @@ -52,6 +52,22 @@ static struct map_desc omap730_io_desc[] __initdata = { }; #endif +#ifdef CONFIG_ARCH_OMAP850 +static struct map_desc omap850_io_desc[] __initdata = { + { + .virtual = OMAP850_DSP_BASE, + .pfn = __phys_to_pfn(OMAP850_DSP_START), + .length = OMAP850_DSP_SIZE, + .type = MT_DEVICE + }, { + .virtual = OMAP850_DSPREG_BASE, + .pfn = __phys_to_pfn(OMAP850_DSPREG_START), + .length = OMAP850_DSPREG_SIZE, + .type = MT_DEVICE + } +}; +#endif + #ifdef CONFIG_ARCH_OMAP15XX static struct map_desc omap1510_io_desc[] __initdata = { { @@ -109,6 +125,13 @@ void __init omap1_map_common_io(void) iotable_init(omap730_io_desc, ARRAY_SIZE(omap730_io_desc)); } #endif + +#ifdef CONFIG_ARCH_OMAP850 + if (cpu_is_omap850()) { + iotable_init(omap850_io_desc, ARRAY_SIZE(omap850_io_desc)); + } +#endif + #ifdef CONFIG_ARCH_OMAP15XX if (cpu_is_omap15xx()) { iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc)); diff --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c index 062c905c2ba..721e0d9d8b1 100644 --- a/arch/arm/mach-omap1/mux.c +++ b/arch/arm/mach-omap1/mux.c @@ -58,6 +58,25 @@ MUX_CFG_730("W17_730_USB_VBUSI", 2, 29, 0, 28, 0, 0) #define OMAP730_PINS_SZ 0 #endif /* CONFIG_ARCH_OMAP730 */ +#ifdef CONFIG_ARCH_OMAP850 +struct pin_config __initdata_or_module omap850_pins[] = { +MUX_CFG_850("E2_850_KBR0", 12, 21, 0, 20, 1, 0) +MUX_CFG_850("J7_850_KBR1", 12, 25, 0, 24, 1, 0) +MUX_CFG_850("E1_850_KBR2", 12, 29, 0, 28, 1, 0) +MUX_CFG_850("F3_850_KBR3", 13, 1, 0, 0, 1, 0) +MUX_CFG_850("D2_850_KBR4", 13, 5, 0, 4, 1, 0) +MUX_CFG_850("C2_850_KBC0", 13, 9, 0, 8, 1, 0) +MUX_CFG_850("D3_850_KBC1", 13, 13, 0, 12, 1, 0) +MUX_CFG_850("E4_850_KBC2", 13, 17, 0, 16, 1, 0) +MUX_CFG_850("F4_850_KBC3", 13, 21, 0, 20, 1, 0) +MUX_CFG_850("E3_850_KBC4", 13, 25, 0, 24, 1, 0) + +MUX_CFG_850("AA17_850_USB_DM", 2, 21, 0, 20, 0, 0) +MUX_CFG_850("W16_850_USB_PU_EN", 2, 25, 0, 24, 0, 0) +MUX_CFG_850("W17_850_USB_VBUSI", 2, 29, 0, 28, 0, 0) +}; +#endif + #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) static struct pin_config __initdata_or_module omap1xxx_pins[] = { /* @@ -419,6 +438,11 @@ int __init_or_module omap1_cfg_reg(const struct pin_config *cfg) printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n", cfg->pull_name, cfg->pull_reg, pull_orig, pull); } + +#ifdef CONFIG_ARCH_OMAP850 + omap_mux_register(omap850_pins, ARRAY_SIZE(omap850_pins)); +#endif + #endif #ifdef CONFIG_OMAP_MUX_ERRORS diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c index 0002084e065..842090b148f 100644 --- a/arch/arm/mach-omap1/serial.c +++ b/arch/arm/mach-omap1/serial.c @@ -121,6 +121,13 @@ void __init omap_serial_init(void) serial_platform_data[1].irq = INT_730_UART_MODEM_IRDA_2; } + if (cpu_is_omap850()) { + serial_platform_data[0].regshift = 0; + serial_platform_data[1].regshift = 0; + serial_platform_data[0].irq = INT_850_UART_MODEM_1; + serial_platform_data[1].irq = INT_850_UART_MODEM_IRDA_2; + } + if (cpu_is_omap15xx()) { serial_platform_data[0].uartclk = OMAP1510_BASE_BAUD * 16; serial_platform_data[1].uartclk = OMAP1510_BASE_BAUD * 16; diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index f856a90b264..d3fa41e3d8c 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -80,6 +80,22 @@ #define OMAP730_GPIO_INT_MASK 0x10 #define OMAP730_GPIO_INT_STATUS 0x14 +/* + * OMAP850 specific GPIO registers + */ +#define OMAP850_GPIO1_BASE IO_ADDRESS(0xfffbc000) +#define OMAP850_GPIO2_BASE IO_ADDRESS(0xfffbc800) +#define OMAP850_GPIO3_BASE IO_ADDRESS(0xfffbd000) +#define OMAP850_GPIO4_BASE IO_ADDRESS(0xfffbd800) +#define OMAP850_GPIO5_BASE IO_ADDRESS(0xfffbe000) +#define OMAP850_GPIO6_BASE IO_ADDRESS(0xfffbe800) +#define OMAP850_GPIO_DATA_INPUT 0x00 +#define OMAP850_GPIO_DATA_OUTPUT 0x04 +#define OMAP850_GPIO_DIR_CONTROL 0x08 +#define OMAP850_GPIO_INT_CONTROL 0x0c +#define OMAP850_GPIO_INT_MASK 0x10 +#define OMAP850_GPIO_INT_STATUS 0x14 + /* * omap24xx specific GPIO registers */ @@ -159,7 +175,8 @@ struct gpio_bank { #define METHOD_GPIO_1510 1 #define METHOD_GPIO_1610 2 #define METHOD_GPIO_730 3 -#define METHOD_GPIO_24XX 4 +#define METHOD_GPIO_850 4 +#define METHOD_GPIO_24XX 5 #ifdef CONFIG_ARCH_OMAP16XX static struct gpio_bank gpio_bank_1610[5] = { @@ -190,6 +207,19 @@ static struct gpio_bank gpio_bank_730[7] = { }; #endif +#ifdef CONFIG_ARCH_OMAP850 +static struct gpio_bank gpio_bank_850[7] = { + { OMAP_MPUIO_BASE, INT_850_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO }, + { OMAP850_GPIO1_BASE, INT_850_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_850 }, + { OMAP850_GPIO2_BASE, INT_850_GPIO_BANK2, IH_GPIO_BASE + 32, METHOD_GPIO_850 }, + { OMAP850_GPIO3_BASE, INT_850_GPIO_BANK3, IH_GPIO_BASE + 64, METHOD_GPIO_850 }, + { OMAP850_GPIO4_BASE, INT_850_GPIO_BANK4, IH_GPIO_BASE + 96, METHOD_GPIO_850 }, + { OMAP850_GPIO5_BASE, INT_850_GPIO_BANK5, IH_GPIO_BASE + 128, METHOD_GPIO_850 }, + { OMAP850_GPIO6_BASE, INT_850_GPIO_BANK6, IH_GPIO_BASE + 160, METHOD_GPIO_850 }, +}; +#endif + + #ifdef CONFIG_ARCH_OMAP24XX static struct gpio_bank gpio_bank_242x[4] = { @@ -236,7 +266,7 @@ static inline struct gpio_bank *get_gpio_bank(int gpio) return &gpio_bank[0]; return &gpio_bank[1 + (gpio >> 4)]; } - if (cpu_is_omap730()) { + if (cpu_is_omap7xx()) { if (OMAP_GPIO_IS_MPUIO(gpio)) return &gpio_bank[0]; return &gpio_bank[1 + (gpio >> 5)]; @@ -251,7 +281,7 @@ static inline struct gpio_bank *get_gpio_bank(int gpio) static inline int get_gpio_index(int gpio) { - if (cpu_is_omap730()) + if (cpu_is_omap7xx()) return gpio & 0x1f; if (cpu_is_omap24xx()) return gpio & 0x1f; @@ -273,7 +303,7 @@ static inline int gpio_valid(int gpio) return 0; if ((cpu_is_omap16xx()) && gpio < 64) return 0; - if (cpu_is_omap730() && gpio < 192) + if (cpu_is_omap7xx() && gpio < 192) return 0; if (cpu_is_omap24xx() && gpio < 128) return 0; @@ -318,6 +348,11 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input) reg += OMAP730_GPIO_DIR_CONTROL; break; #endif +#ifdef CONFIG_ARCH_OMAP850 + case METHOD_GPIO_850: + reg += OMAP850_GPIO_DIR_CONTROL; + break; +#endif #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) case METHOD_GPIO_24XX: reg += OMAP24XX_GPIO_OE; @@ -380,6 +415,16 @@ static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable) l &= ~(1 << gpio); break; #endif +#ifdef CONFIG_ARCH_OMAP850 + case METHOD_GPIO_850: + reg += OMAP850_GPIO_DATA_OUTPUT; + l = __raw_readl(reg); + if (enable) + l |= 1 << gpio; + else + l &= ~(1 << gpio); + break; +#endif #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) case METHOD_GPIO_24XX: if (enable) @@ -426,6 +471,11 @@ static int __omap_get_gpio_datain(int gpio) reg += OMAP730_GPIO_DATA_INPUT; break; #endif +#ifdef CONFIG_ARCH_OMAP850 + case METHOD_GPIO_850: + reg += OMAP850_GPIO_DATA_INPUT; + break; +#endif #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) case METHOD_GPIO_24XX: reg += OMAP24XX_GPIO_DATAIN; @@ -598,6 +648,18 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) goto bad; break; #endif +#ifdef CONFIG_ARCH_OMAP850 + case METHOD_GPIO_850: + reg += OMAP850_GPIO_INT_CONTROL; + l = __raw_readl(reg); + if (trigger & IRQ_TYPE_EDGE_RISING) + l |= 1 << gpio; + else if (trigger & IRQ_TYPE_EDGE_FALLING) + l &= ~(1 << gpio); + else + goto bad; + break; +#endif #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) case METHOD_GPIO_24XX: set_24xx_gpio_triggering(bank, gpio, trigger); @@ -678,6 +740,11 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) reg += OMAP730_GPIO_INT_STATUS; break; #endif +#ifdef CONFIG_ARCH_OMAP850 + case METHOD_GPIO_850: + reg += OMAP850_GPIO_INT_STATUS; + break; +#endif #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) case METHOD_GPIO_24XX: reg += OMAP24XX_GPIO_IRQSTATUS1; @@ -736,6 +803,13 @@ static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank) inv = 1; break; #endif +#ifdef CONFIG_ARCH_OMAP850 + case METHOD_GPIO_850: + reg += OMAP850_GPIO_INT_MASK; + mask = 0xffffffff; + inv = 1; + break; +#endif #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) case METHOD_GPIO_24XX: reg += OMAP24XX_GPIO_IRQENABLE1; @@ -799,6 +873,16 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enab l |= gpio_mask; break; #endif +#ifdef CONFIG_ARCH_OMAP850 + case METHOD_GPIO_850: + reg += OMAP850_GPIO_INT_MASK; + l = __raw_readl(reg); + if (enable) + l &= ~(gpio_mask); + else + l |= gpio_mask; + break; +#endif #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) case METHOD_GPIO_24XX: if (enable) @@ -983,6 +1067,10 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) if (bank->method == METHOD_GPIO_730) isr_reg = bank->base + OMAP730_GPIO_INT_STATUS; #endif +#ifdef CONFIG_ARCH_OMAP850 + if (bank->method == METHOD_GPIO_850) + isr_reg = bank->base + OMAP850_GPIO_INT_STATUS; +#endif #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) if (bank->method == METHOD_GPIO_24XX) isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1; @@ -1372,6 +1460,13 @@ static int __init _omap_gpio_init(void) gpio_bank = gpio_bank_730; } #endif +#ifdef CONFIG_ARCH_OMAP850 + if (cpu_is_omap850()) { + printk(KERN_INFO "OMAP850 GPIO hardware\n"); + gpio_bank_count = 7; + gpio_bank = gpio_bank_850; + } +#endif #ifdef CONFIG_ARCH_OMAP24XX if (cpu_is_omap242x()) { @@ -1420,7 +1515,7 @@ static int __init _omap_gpio_init(void) __raw_writew(0xffff, bank->base + OMAP1610_GPIO_IRQSTATUS1); __raw_writew(0x0014, bank->base + OMAP1610_GPIO_SYSCONFIG); } - if (cpu_is_omap730() && bank->method == METHOD_GPIO_730) { + if (cpu_is_omap7xx() && bank->method == METHOD_GPIO_730) { __raw_writel(0xffffffff, bank->base + OMAP730_GPIO_INT_MASK); __raw_writel(0x00000000, bank->base + OMAP730_GPIO_INT_STATUS); @@ -1743,6 +1838,9 @@ static int gpio_is_input(struct gpio_bank *bank, int mask) case METHOD_GPIO_730: reg += OMAP730_GPIO_DIR_CONTROL; break; + case METHOD_GPIO_850: + reg += OMAP850_GPIO_DIR_CONTROL; + break; case METHOD_GPIO_24XX: reg += OMAP24XX_GPIO_OE; break; @@ -1762,7 +1860,8 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) if (bank_is_mpuio(bank)) gpio = OMAP_MPUIO(0); - else if (cpu_class_is_omap2() || cpu_is_omap730()) + else if (cpu_class_is_omap2() || cpu_is_omap730() || + cpu_is_omap850()) bankwidth = 32; for (j = 0; j < bankwidth; j++, gpio++, mask <<= 1) { diff --git a/arch/arm/plat-omap/include/mach/gpio.h b/arch/arm/plat-omap/include/mach/gpio.h index 8d9dfe31438..2b22a8799bc 100644 --- a/arch/arm/plat-omap/include/mach/gpio.h +++ b/arch/arm/plat-omap/include/mach/gpio.h @@ -31,7 +31,8 @@ #define OMAP_MPUIO_BASE 0xfffb5000 -#ifdef CONFIG_ARCH_OMAP730 +#if (defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)) + #define OMAP_MPUIO_INPUT_LATCH 0x00 #define OMAP_MPUIO_OUTPUT 0x02 #define OMAP_MPUIO_IO_CNTL 0x04 diff --git a/arch/arm/plat-omap/include/mach/mux.h b/arch/arm/plat-omap/include/mach/mux.h index f4362b8682c..6a02f8f4c8b 100644 --- a/arch/arm/plat-omap/include/mach/mux.h +++ b/arch/arm/plat-omap/include/mach/mux.h @@ -61,6 +61,16 @@ .pull_bit = bit, \ .pull_val = status, +#define MUX_REG_850(reg, mode_offset, mode) .mux_reg_name = "OMAP850_IO_CONF_"#reg, \ + .mux_reg = OMAP850_IO_CONF_##reg, \ + .mask_offset = mode_offset, \ + .mask = mode, + +#define PULL_REG_850(reg, bit, status) .pull_name = "OMAP850_IO_CONF_"#reg, \ + .pull_reg = OMAP850_IO_CONF_##reg, \ + .pull_bit = bit, \ + .pull_val = status, + #else #define MUX_REG(reg, mode_offset, mode) .mux_reg = FUNC_MUX_CTRL_##reg, \ @@ -83,6 +93,15 @@ .pull_bit = bit, \ .pull_val = status, +#define MUX_REG_850(reg, mode_offset, mode) \ + .mux_reg = OMAP850_IO_CONF_##reg, \ + .mask_offset = mode_offset, \ + .mask = mode, + +#define PULL_REG_850(reg, bit, status) .pull_reg = OMAP850_IO_CONF_##reg, \ + .pull_bit = bit, \ + .pull_val = status, + #endif /* CONFIG_OMAP_MUX_DEBUG */ #define MUX_CFG(desc, mux_reg, mode_offset, mode, \ @@ -98,7 +117,7 @@ /* - * OMAP730 has a slightly different config for the pin mux. + * OMAP730/850 has a slightly different config for the pin mux. * - config regs are the OMAP730_IO_CONF_x regs (see omap730.h) regs and * not the FUNC_MUX_CTRL_x regs from hardware.h * - for pull-up/down, only has one enable bit which is is in the same register @@ -114,6 +133,17 @@ PU_PD_REG(NA, 0) \ }, +#define MUX_CFG_850(desc, mux_reg, mode_offset, mode, \ + pull_bit, pull_status, debug_status)\ +{ \ + .name = desc, \ + .debug = debug_status, \ + MUX_REG_850(mux_reg, mode_offset, mode) \ + PULL_REG_850(mux_reg, pull_bit, pull_status) \ + PU_PD_REG(NA, 0) \ +}, + + #define MUX_CFG_24XX(desc, reg_offset, mode, \ pull_en, pull_mode, dbg) \ { \ @@ -221,6 +251,26 @@ enum omap730_index { W17_730_USB_VBUSI, }; +enum omap850_index { + /* OMAP 850 keyboard */ + E2_850_KBR0, + J7_850_KBR1, + E1_850_KBR2, + F3_850_KBR3, + D2_850_KBR4, + C2_850_KBC0, + D3_850_KBC1, + E4_850_KBC2, + F4_850_KBC3, + E3_850_KBC4, + + /* USB */ + AA17_850_USB_DM, + W16_850_USB_PU_EN, + W17_850_USB_VBUSI, +}; + + enum omap1xxx_index { /* UART1 (BT_UART_GATING)*/ UART1_TX = 0, -- GitLab From 557096fe2838778ec1c6df0186560ff21749f63d Mon Sep 17 00:00:00 2001 From: "Zebediah C. McClure" Date: Mon, 23 Mar 2009 18:07:44 -0700 Subject: [PATCH 3996/4982] [OMAP850] Changes to memory subsystem Changes to memory subsystem. Signed-off-by: Zebediah C. McClure Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dma.c | 4 ++-- arch/arm/plat-omap/sram.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 47ec77af4cc..dcc9e83a61e 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -737,7 +737,7 @@ int omap_request_dma(int dev_id, const char *dev_name, * id. */ dma_write(dev_id | (1 << 10), CCR(free_ch)); - } else if (cpu_is_omap730() || cpu_is_omap15xx()) { + } else if (cpu_is_omap7xx() || cpu_is_omap15xx()) { dma_write(dev_id, CCR(free_ch)); } @@ -2339,7 +2339,7 @@ static int __init omap_init_dma(void) printk(KERN_INFO "DMA support for OMAP15xx initialized\n"); dma_chan_count = 9; enable_1510_mode = 1; - } else if (cpu_is_omap16xx() || cpu_is_omap730()) { + } else if (cpu_is_omap16xx() || cpu_is_omap7xx()) { printk(KERN_INFO "OMAP DMA hardware version %d\n", dma_read(HW_ID)); printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n", diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index be7bcaf2b83..fa5297d643d 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -148,7 +148,7 @@ void __init omap_detect_sram(void) omap_sram_base = OMAP1_SRAM_VA; omap_sram_start = OMAP1_SRAM_PA; - if (cpu_is_omap730()) + if (cpu_is_omap7xx()) omap_sram_size = 0x32000; /* 200K */ else if (cpu_is_omap15xx()) omap_sram_size = 0x30000; /* 192K */ -- GitLab From 59185eeeaad1f07fc930c1878f3773484219e3da Mon Sep 17 00:00:00 2001 From: "Zebediah C. McClure" Date: Mon, 23 Mar 2009 18:07:45 -0700 Subject: [PATCH 3997/4982] [OMAP850] IRQ related changes IRQ related changes. Signed-off-by: Zebediah C. McClure Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/irq.c | 19 +++++- arch/arm/plat-omap/include/mach/irqs.h | 83 +++++++++++++++++++++++++- 2 files changed, 99 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c index 9ad5197075f..de03c844899 100644 --- a/arch/arm/mach-omap1/irq.c +++ b/arch/arm/mach-omap1/irq.c @@ -145,6 +145,14 @@ static struct omap_irq_bank omap730_irq_banks[] = { }; #endif +#ifdef CONFIG_ARCH_OMAP850 +static struct omap_irq_bank omap850_irq_banks[] = { + { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3f8e22f }, + { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb9c1f2 }, + { .base_reg = OMAP_IH2_BASE + 0x100, .trigger_map = 0x800040f3 }, +}; +#endif + #ifdef CONFIG_ARCH_OMAP15XX static struct omap_irq_bank omap1510_irq_banks[] = { { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3febfff }, @@ -184,6 +192,12 @@ void __init omap_init_irq(void) irq_bank_count = ARRAY_SIZE(omap730_irq_banks); } #endif +#ifdef CONFIG_ARCH_OMAP850 + if (cpu_is_omap850()) { + irq_banks = omap850_irq_banks; + irq_bank_count = ARRAY_SIZE(omap850_irq_banks); + } +#endif #ifdef CONFIG_ARCH_OMAP15XX if (cpu_is_omap1510()) { irq_banks = omap1510_irq_banks; @@ -214,9 +228,8 @@ void __init omap_init_irq(void) irq_bank_writel(0x03, 1, IRQ_CONTROL_REG_OFFSET); /* Enable interrupts in global mask */ - if (cpu_is_omap730()) { + if (cpu_is_omap7xx()) irq_bank_writel(0x0, 0, IRQ_GMR_REG_OFFSET); - } /* Install the interrupt handlers for each bank */ for (i = 0; i < irq_bank_count; i++) { @@ -236,6 +249,8 @@ void __init omap_init_irq(void) if (cpu_is_omap730()) omap_unmask_irq(INT_730_IH2_IRQ); + else if (cpu_is_omap850()) + omap_unmask_irq(INT_850_IH2_IRQ); else if (cpu_is_omap15xx()) omap_unmask_irq(INT_1510_IH2_IRQ); else if (cpu_is_omap16xx()) diff --git a/arch/arm/plat-omap/include/mach/irqs.h b/arch/arm/plat-omap/include/mach/irqs.h index bed5274c910..7f57ee66f36 100644 --- a/arch/arm/plat-omap/include/mach/irqs.h +++ b/arch/arm/plat-omap/include/mach/irqs.h @@ -104,6 +104,29 @@ #define INT_730_GPIO_BANK6 18 #define INT_730_SPGIO_WR 29 +/* + * OMAP-850 specific IRQ numbers for interrupt handler 1 + */ +#define INT_850_IH2_FIQ 0 +#define INT_850_IH2_IRQ 1 +#define INT_850_USB_NON_ISO 2 +#define INT_850_USB_ISO 3 +#define INT_850_ICR 4 +#define INT_850_EAC 5 +#define INT_850_GPIO_BANK1 6 +#define INT_850_GPIO_BANK2 7 +#define INT_850_GPIO_BANK3 8 +#define INT_850_McBSP2TX 10 +#define INT_850_McBSP2RX 11 +#define INT_850_McBSP2RX_OVF 12 +#define INT_850_LCD_LINE 14 +#define INT_850_GSM_PROTECT 15 +#define INT_850_TIMER3 16 +#define INT_850_GPIO_BANK5 17 +#define INT_850_GPIO_BANK6 18 +#define INT_850_SPGIO_WR 29 + + /* * IRQ numbers for interrupt handler 2 * @@ -237,6 +260,64 @@ #define INT_730_DMA_CH15 (62 + IH2_BASE) #define INT_730_NAND (63 + IH2_BASE) +/* + * OMAP-850 specific IRQ numbers for interrupt handler 2 + */ +#define INT_850_HW_ERRORS (0 + IH2_BASE) +#define INT_850_NFIQ_PWR_FAIL (1 + IH2_BASE) +#define INT_850_CFCD (2 + IH2_BASE) +#define INT_850_CFIREQ (3 + IH2_BASE) +#define INT_850_I2C (4 + IH2_BASE) +#define INT_850_PCC (5 + IH2_BASE) +#define INT_850_MPU_EXT_NIRQ (6 + IH2_BASE) +#define INT_850_SPI_100K_1 (7 + IH2_BASE) +#define INT_850_SYREN_SPI (8 + IH2_BASE) +#define INT_850_VLYNQ (9 + IH2_BASE) +#define INT_850_GPIO_BANK4 (10 + IH2_BASE) +#define INT_850_McBSP1TX (11 + IH2_BASE) +#define INT_850_McBSP1RX (12 + IH2_BASE) +#define INT_850_McBSP1RX_OF (13 + IH2_BASE) +#define INT_850_UART_MODEM_IRDA_2 (14 + IH2_BASE) +#define INT_850_UART_MODEM_1 (15 + IH2_BASE) +#define INT_850_MCSI (16 + IH2_BASE) +#define INT_850_uWireTX (17 + IH2_BASE) +#define INT_850_uWireRX (18 + IH2_BASE) +#define INT_850_SMC_CD (19 + IH2_BASE) +#define INT_850_SMC_IREQ (20 + IH2_BASE) +#define INT_850_HDQ_1WIRE (21 + IH2_BASE) +#define INT_850_TIMER32K (22 + IH2_BASE) +#define INT_850_MMC_SDIO (23 + IH2_BASE) +#define INT_850_UPLD (24 + IH2_BASE) +#define INT_850_USB_HHC_1 (27 + IH2_BASE) +#define INT_850_USB_HHC_2 (28 + IH2_BASE) +#define INT_850_USB_GENI (29 + IH2_BASE) +#define INT_850_USB_OTG (30 + IH2_BASE) +#define INT_850_CAMERA_IF (31 + IH2_BASE) +#define INT_850_RNG (32 + IH2_BASE) +#define INT_850_DUAL_MODE_TIMER (33 + IH2_BASE) +#define INT_850_DBB_RF_EN (34 + IH2_BASE) +#define INT_850_MPUIO_KEYPAD (35 + IH2_BASE) +#define INT_850_SHA1_MD5 (36 + IH2_BASE) +#define INT_850_SPI_100K_2 (37 + IH2_BASE) +#define INT_850_RNG_IDLE (38 + IH2_BASE) +#define INT_850_MPUIO (39 + IH2_BASE) +#define INT_850_LLPC_LCD_CTRL_CAN_BE_OFF (40 + IH2_BASE) +#define INT_850_LLPC_OE_FALLING (41 + IH2_BASE) +#define INT_850_LLPC_OE_RISING (42 + IH2_BASE) +#define INT_850_LLPC_VSYNC (43 + IH2_BASE) +#define INT_850_WAKE_UP_REQ (46 + IH2_BASE) +#define INT_850_DMA_CH6 (53 + IH2_BASE) +#define INT_850_DMA_CH7 (54 + IH2_BASE) +#define INT_850_DMA_CH8 (55 + IH2_BASE) +#define INT_850_DMA_CH9 (56 + IH2_BASE) +#define INT_850_DMA_CH10 (57 + IH2_BASE) +#define INT_850_DMA_CH11 (58 + IH2_BASE) +#define INT_850_DMA_CH12 (59 + IH2_BASE) +#define INT_850_DMA_CH13 (60 + IH2_BASE) +#define INT_850_DMA_CH14 (61 + IH2_BASE) +#define INT_850_DMA_CH15 (62 + IH2_BASE) +#define INT_850_NAND (63 + IH2_BASE) + #define INT_24XX_SYS_NIRQ 7 #define INT_24XX_SDMA_IRQ0 12 #define INT_24XX_SDMA_IRQ1 13 @@ -341,7 +422,7 @@ #define INT_34XX_BENCH_MPU_EMUL 3 -/* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730) and +/* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730/850) and * 16 MPUIO lines */ #define OMAP_MAX_GPIO_LINES 192 #define IH_GPIO_BASE (128 + IH2_BASE) -- GitLab From ed98178319948d97ce8e664cf451cff6dbf04cdd Mon Sep 17 00:00:00 2001 From: "Zebediah C. McClure" Date: Mon, 23 Mar 2009 18:07:46 -0700 Subject: [PATCH 3998/4982] [OMAP850] Build system changes Build system changes. Signed-off-by: Zebediah C. McClure Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/Kconfig | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig index 10a301e3243..3f325d3718a 100644 --- a/arch/arm/mach-omap1/Kconfig +++ b/arch/arm/mach-omap1/Kconfig @@ -7,6 +7,11 @@ config ARCH_OMAP730 select CPU_ARM926T select ARCH_OMAP_OTG +config ARCH_OMAP850 + depends on ARCH_OMAP1 + bool "OMAP850 Based System" + select CPU_ARM926T + config ARCH_OMAP15XX depends on ARCH_OMAP1 default y @@ -46,6 +51,12 @@ config MACH_OMAP_H3 TI OMAP 1710 H3 board support. Say Y here if you have such a board. +config MACH_OMAP_HTCWIZARD + bool "HTC Wizard" + depends on ARCH_OMAP850 + help + HTC Wizard smartphone support (AKA QTEK 9100, ...) + config MACH_OMAP_OSK bool "TI OSK Support" depends on ARCH_OMAP1 && ARCH_OMAP16XX @@ -163,7 +174,7 @@ config OMAP_ARM_216MHZ config OMAP_ARM_195MHZ bool "OMAP ARM 195 MHz CPU" - depends on ARCH_OMAP1 && ARCH_OMAP730 + depends on ARCH_OMAP1 && (ARCH_OMAP730 || ARCH_OMAP850) help Enable 195MHz clock for OMAP CPU. If unsure, say N. @@ -175,13 +186,13 @@ config OMAP_ARM_192MHZ config OMAP_ARM_182MHZ bool "OMAP ARM 182 MHz CPU" - depends on ARCH_OMAP1 && ARCH_OMAP730 + depends on ARCH_OMAP1 && (ARCH_OMAP730 || ARCH_OMAP850) help Enable 182MHz clock for OMAP CPU. If unsure, say N. config OMAP_ARM_168MHZ bool "OMAP ARM 168 MHz CPU" - depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730) + depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_OMAP850) help Enable 168MHz clock for OMAP CPU. If unsure, say N. @@ -193,20 +204,20 @@ config OMAP_ARM_150MHZ config OMAP_ARM_120MHZ bool "OMAP ARM 120 MHz CPU" - depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730) + depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_OMAP850) help Enable 120MHz clock for OMAP CPU. If unsure, say N. config OMAP_ARM_60MHZ bool "OMAP ARM 60 MHz CPU" - depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730) + depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_OMAP850) default y help Enable 60MHz clock for OMAP CPU. If unsure, say Y. config OMAP_ARM_30MHZ bool "OMAP ARM 30 MHz CPU" - depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730) + depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_OMAP850) help Enable 30MHz clock for OMAP CPU. If unsure, say N. -- GitLab From 6c366e3299e8e9458881e19913a79ea3ceff4a8f Mon Sep 17 00:00:00 2001 From: Timo Kokkonen Date: Mon, 23 Mar 2009 18:07:46 -0700 Subject: [PATCH 3999/4982] ARM: OMAP: Export dmtimer functions Make the dmtimer function symbols available so modules can take use of them. Signed-off-by: Timo Kokkonen Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dmtimer.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index e4f0ce04ba9..bfd47570cc9 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -362,6 +363,7 @@ struct omap_dm_timer *omap_dm_timer_request(void) return timer; } +EXPORT_SYMBOL_GPL(omap_dm_timer_request); struct omap_dm_timer *omap_dm_timer_request_specific(int id) { @@ -385,6 +387,7 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id) return timer; } +EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific); void omap_dm_timer_free(struct omap_dm_timer *timer) { @@ -395,6 +398,7 @@ void omap_dm_timer_free(struct omap_dm_timer *timer) WARN_ON(!timer->reserved); timer->reserved = 0; } +EXPORT_SYMBOL_GPL(omap_dm_timer_free); void omap_dm_timer_enable(struct omap_dm_timer *timer) { @@ -406,6 +410,7 @@ void omap_dm_timer_enable(struct omap_dm_timer *timer) timer->enabled = 1; } +EXPORT_SYMBOL_GPL(omap_dm_timer_enable); void omap_dm_timer_disable(struct omap_dm_timer *timer) { @@ -417,11 +422,13 @@ void omap_dm_timer_disable(struct omap_dm_timer *timer) timer->enabled = 0; } +EXPORT_SYMBOL_GPL(omap_dm_timer_disable); int omap_dm_timer_get_irq(struct omap_dm_timer *timer) { return timer->irq; } +EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq); #if defined(CONFIG_ARCH_OMAP1) @@ -452,6 +459,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) return inputmask; } +EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask); #elif defined(CONFIG_ARCH_OMAP2) || defined (CONFIG_ARCH_OMAP3) @@ -459,6 +467,7 @@ struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer) { return timer->fclk; } +EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk); __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) { @@ -466,6 +475,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) return 0; } +EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask); #endif @@ -473,6 +483,7 @@ void omap_dm_timer_trigger(struct omap_dm_timer *timer) { omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0); } +EXPORT_SYMBOL_GPL(omap_dm_timer_trigger); void omap_dm_timer_start(struct omap_dm_timer *timer) { @@ -484,6 +495,7 @@ void omap_dm_timer_start(struct omap_dm_timer *timer) omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); } } +EXPORT_SYMBOL_GPL(omap_dm_timer_start); void omap_dm_timer_stop(struct omap_dm_timer *timer) { @@ -495,6 +507,7 @@ void omap_dm_timer_stop(struct omap_dm_timer *timer) omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); } } +EXPORT_SYMBOL_GPL(omap_dm_timer_stop); #ifdef CONFIG_ARCH_OMAP1 @@ -507,6 +520,7 @@ void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) l |= source << n; omap_writel(l, MOD_CONF_CTRL_1); } +EXPORT_SYMBOL_GPL(omap_dm_timer_set_source); #else @@ -523,6 +537,7 @@ void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) * cause an abort. */ __delay(150000); } +EXPORT_SYMBOL_GPL(omap_dm_timer_set_source); #endif @@ -541,6 +556,7 @@ void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0); } +EXPORT_SYMBOL_GPL(omap_dm_timer_set_load); /* Optimized set_load which removes costly spin wait in timer_start */ void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, @@ -560,6 +576,7 @@ void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, load); omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); } +EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start); void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match) @@ -574,6 +591,7 @@ void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match); } +EXPORT_SYMBOL_GPL(omap_dm_timer_set_match); void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, int trigger) @@ -590,6 +608,7 @@ void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, l |= trigger << 10; omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); } +EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm); void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler) { @@ -603,6 +622,7 @@ void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler) } omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); } +EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler); void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value) @@ -610,6 +630,7 @@ void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value); omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, value); } +EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable); unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) { @@ -619,11 +640,13 @@ unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) return l; } +EXPORT_SYMBOL_GPL(omap_dm_timer_read_status); void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) { omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value); } +EXPORT_SYMBOL_GPL(omap_dm_timer_write_status); unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) { @@ -633,11 +656,13 @@ unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) return l; } +EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter); void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value) { omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value); } +EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter); int omap_dm_timers_active(void) { @@ -658,6 +683,7 @@ int omap_dm_timers_active(void) } return 0; } +EXPORT_SYMBOL_GPL(omap_dm_timers_active); int __init omap_dm_timer_init(void) { -- GitLab From d4c58bf45a9a1668cb850e02a2e1aad785bd9325 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 23 Mar 2009 18:07:46 -0700 Subject: [PATCH 4000/4982] ARM: OMAP: Add documentation for function omap_register_i2c_bus Signed-off-by: Jarkko Nikula Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/i2c.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index 467531edefd..3e95954e2a8 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -119,6 +119,15 @@ static void __init omap_i2c_mux_pins(int bus) omap_cfg_reg(scl); } +/** + * omap_register_i2c_bus - register I2C bus with device descriptors + * @bus_id: bus id counting from number 1 + * @clkrate: clock rate of the bus in kHz + * @info: pointer into I2C device descriptor table or NULL + * @len: number of descriptors in the table + * + * Returns 0 on success or an error code. + */ int __init omap_register_i2c_bus(int bus_id, u32 clkrate, struct i2c_board_info const *info, unsigned len) -- GitLab From 3a853fb933ddf9c5ea8c9f7c665dd8def26bceae Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 23 Mar 2009 18:07:47 -0700 Subject: [PATCH 4001/4982] ARM: OMAP: Add command line option for I2C bus speed, v2 This patch adds a new command line option "i2c_bus=bus_id,clkrate" into I2C bus registration helper. Purpose of the option is to override the default board specific bus speed which is supplied by the omap_register_i2c_bus. The default bus speed is typically set to speed of slowest I2C chip on the bus and overriding allow to use some experimental configurations or updated chip versions without any kernel modifications. Cc: linux-i2c@vger.kernel.org Signed-off-by: Jarkko Nikula Signed-off-by: Tony Lindgren --- Documentation/kernel-parameters.txt | 4 +++ arch/arm/plat-omap/i2c.c | 54 +++++++++++++++++++++++------ 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 54f21a5c262..d775076d156 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -830,6 +830,10 @@ and is between 256 and 4096 characters. It is defined in the file hvc_iucv= [S390] Number of z/VM IUCV hypervisor console (HVC) terminal devices. Valid values: 0..8 + i2c_bus= [HW] Override the default board specific I2C bus speed + Format: + , + i8042.debug [HW] Toggle i8042 debug mode i8042.direct [HW] Put keyboard port into non-translated mode i8042.dumbkbd [HW] Pretend that controller can only read data from diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index 3e95954e2a8..aa70e435fa7 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -119,6 +119,46 @@ static void __init omap_i2c_mux_pins(int bus) omap_cfg_reg(scl); } +static int __init omap_i2c_nr_ports(void) +{ + int ports = 0; + + if (cpu_class_is_omap1()) + ports = 1; + else if (cpu_is_omap24xx()) + ports = 2; + else if (cpu_is_omap34xx()) + ports = 3; + + return ports; +} + +/** + * omap_i2c_bus_setup - Process command line options for the I2C bus speed + * @str: String of options + * + * This function allow to override the default I2C bus speed for given I2C + * bus with a command line option. + * + * Format: i2c_bus=bus_id,clkrate (in kHz) + * + * Returns 1 on success, 0 otherwise. + */ +static int __init omap_i2c_bus_setup(char *str) +{ + int ports; + int ints[3]; + + ports = omap_i2c_nr_ports(); + get_options(str, 3, ints); + if (ints[0] < 2 || ints[1] < 1 || ints[1] > ports) + return 0; + i2c_rate[ints[1] - 1] = ints[2]; + + return 1; +} +__setup("i2c_bus=", omap_i2c_bus_setup); + /** * omap_register_i2c_bus - register I2C bus with device descriptors * @bus_id: bus id counting from number 1 @@ -132,19 +172,12 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate, struct i2c_board_info const *info, unsigned len) { - int ports, err; + int err; struct platform_device *pdev; struct resource *res; resource_size_t base, irq; - if (cpu_class_is_omap1()) - ports = 1; - else if (cpu_is_omap24xx()) - ports = 2; - else if (cpu_is_omap34xx()) - ports = 3; - - BUG_ON(bus_id < 1 || bus_id > ports); + BUG_ON(bus_id < 1 || bus_id > omap_i2c_nr_ports()); if (info) { err = i2c_register_board_info(bus_id, info, len); @@ -153,7 +186,8 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate, } pdev = &omap_i2c_devices[bus_id - 1]; - *(u32 *)pdev->dev.platform_data = clkrate; + if (i2c_rate[bus_id - 1] == 0) + i2c_rate[bus_id - 1] = clkrate; if (bus_id == 1) { res = pdev->resource; -- GitLab From 7954763bb95fd484a76d1151b40956fe331d23b9 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 23 Mar 2009 18:07:48 -0700 Subject: [PATCH 4002/4982] ARM: OMAP: Add method to register additional I2C busses on the command line, v2 This patch extends command line option "i2c_bus=bus_id,clkrate" so that it allow to register additional I2C busses that are not registered with omap_register_i2c_bus from board initialization code. Purpose of this is to register additional board busses which are routed to external connectors only without any on board I2C devices. Cc: linux-i2c@vger.kernel.org Signed-off-by: Jarkko Nikula Signed-off-by: Tony Lindgren --- Documentation/kernel-parameters.txt | 2 + arch/arm/plat-omap/i2c.c | 73 ++++++++++++++++++++--------- 2 files changed, 54 insertions(+), 21 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index d775076d156..ef9827f7c84 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -831,6 +831,8 @@ and is between 256 and 4096 characters. It is defined in the file terminal devices. Valid values: 0..8 i2c_bus= [HW] Override the default board specific I2C bus speed + or register an additional I2C bus that is not + registered from board initialization code. Format: , diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index aa70e435fa7..a303071d5e3 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -98,6 +98,8 @@ static const int omap34xx_pins[][2] = { static const int omap34xx_pins[][2] = {}; #endif +#define OMAP_I2C_CMDLINE_SETUP (BIT(31)) + static void __init omap_i2c_mux_pins(int bus) { int scl, sda; @@ -133,6 +135,31 @@ static int __init omap_i2c_nr_ports(void) return ports; } +static int __init omap_i2c_add_bus(int bus_id) +{ + struct platform_device *pdev; + struct resource *res; + resource_size_t base, irq; + + pdev = &omap_i2c_devices[bus_id - 1]; + if (bus_id == 1) { + res = pdev->resource; + if (cpu_class_is_omap1()) { + base = OMAP1_I2C_BASE; + irq = INT_I2C; + } else { + base = OMAP2_I2C_BASE1; + irq = INT_24XX_I2C1_IRQ; + } + res[0].start = base; + res[0].end = base + OMAP_I2C_SIZE; + res[1].start = irq; + } + + omap_i2c_mux_pins(bus_id - 1); + return platform_device_register(pdev); +} + /** * omap_i2c_bus_setup - Process command line options for the I2C bus speed * @str: String of options @@ -154,11 +181,33 @@ static int __init omap_i2c_bus_setup(char *str) if (ints[0] < 2 || ints[1] < 1 || ints[1] > ports) return 0; i2c_rate[ints[1] - 1] = ints[2]; + i2c_rate[ints[1] - 1] |= OMAP_I2C_CMDLINE_SETUP; return 1; } __setup("i2c_bus=", omap_i2c_bus_setup); +/* + * Register busses defined in command line but that are not registered with + * omap_register_i2c_bus from board initialization code. + */ +static int __init omap_register_i2c_bus_cmdline(void) +{ + int i, err = 0; + + for (i = 0; i < ARRAY_SIZE(i2c_rate); i++) + if (i2c_rate[i] & OMAP_I2C_CMDLINE_SETUP) { + i2c_rate[i] &= ~OMAP_I2C_CMDLINE_SETUP; + err = omap_i2c_add_bus(i + 1); + if (err) + goto out; + } + +out: + return err; +} +subsys_initcall(omap_register_i2c_bus_cmdline); + /** * omap_register_i2c_bus - register I2C bus with device descriptors * @bus_id: bus id counting from number 1 @@ -173,9 +222,6 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate, unsigned len) { int err; - struct platform_device *pdev; - struct resource *res; - resource_size_t base, irq; BUG_ON(bus_id < 1 || bus_id > omap_i2c_nr_ports()); @@ -185,24 +231,9 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate, return err; } - pdev = &omap_i2c_devices[bus_id - 1]; - if (i2c_rate[bus_id - 1] == 0) + if (!i2c_rate[bus_id - 1]) i2c_rate[bus_id - 1] = clkrate; + i2c_rate[bus_id - 1] &= ~OMAP_I2C_CMDLINE_SETUP; - if (bus_id == 1) { - res = pdev->resource; - if (cpu_class_is_omap1()) { - base = OMAP1_I2C_BASE; - irq = INT_I2C; - } else { - base = OMAP2_I2C_BASE1; - irq = INT_24XX_I2C1_IRQ; - } - res[0].start = base; - res[0].end = base + OMAP_I2C_SIZE; - res[1].start = irq; - } - - omap_i2c_mux_pins(bus_id - 1); - return platform_device_register(pdev); + return omap_i2c_add_bus(bus_id); } -- GitLab From 2263f0222e836c7b2c144e0546a2701661e2f517 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Mon, 23 Mar 2009 18:07:48 -0700 Subject: [PATCH 4003/4982] ARM: OMAP: Get available DMA channels from cmdline This patch set up a cmdline option for omap dma for masking the available channels. It is needed since the OMAP DMA is a system wide resource and can be used by another software apart from the kernel. To reserve the omap SDMA channels for kernel dma usage, use cmdline bootarg "omap_dma_reserve_ch=". The valid range is 1 to 32. Signed-off-by: Santosh Shilimkar Acked-by: Nishant Kamat Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dma.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index dcc9e83a61e..b1d3c7991ff 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -123,6 +123,7 @@ static struct dma_link_info *dma_linked_lch; static int dma_lch_count; static int dma_chan_count; +static int omap_dma_reserve_channels; static spinlock_t dma_chan_lock; static struct omap_dma_lch *dma_chan; @@ -2321,6 +2322,10 @@ static int __init omap_init_dma(void) return -ENODEV; } + if (cpu_class_is_omap2() && omap_dma_reserve_channels + && (omap_dma_reserve_channels <= dma_lch_count)) + dma_lch_count = omap_dma_reserve_channels; + dma_chan = kzalloc(sizeof(struct omap_dma_lch) * dma_lch_count, GFP_KERNEL); if (!dma_chan) @@ -2371,7 +2376,7 @@ static int __init omap_init_dma(void) u8 revision = dma_read(REVISION) & 0xff; printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n", revision >> 4, revision & 0xf); - dma_chan_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; + dma_chan_count = dma_lch_count; } else { dma_chan_count = 0; return 0; @@ -2437,4 +2442,17 @@ static int __init omap_init_dma(void) arch_initcall(omap_init_dma); +/* + * Reserve the omap SDMA channels using cmdline bootarg + * "omap_dma_reserve_ch=". The valid range is 1 to 32 + */ +static int __init omap_dma_cmdline_reserve_ch(char *str) +{ + if (get_option(&str, &omap_dma_reserve_channels) != 1) + omap_dma_reserve_channels = 0; + return 1; +} + +__setup("omap_dma_reserve_ch=", omap_dma_cmdline_reserve_ch); + -- GitLab From 52176e70837d56cd238d6edc04cc403f1ffa86c6 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Mon, 23 Mar 2009 18:07:49 -0700 Subject: [PATCH 4004/4982] ARM: OMAP: Dispatch only relevant DMA interrupts This fixes the spurious interrupt issue on a DMA channel. In OMAP sDMA, contrast to the SDMA.DMA4_CSRi registers, the SDMA.DMA4_IRQSTATUS_Lj registers are updated regardless of the corresponding bits in the SDMA.DMA4_IRQENABLE_Lj registers. Since there are four sDMA interrupt lines and if more than one line is actively used by two concurrently running sDMA softwares modules,then the spurious interrupt can be observed on the other lines. Fix in this patch will only dispatch the relevant and enabled interrupts on a particular line thus perevting spurious IRQ. Signed-off-by: Santosh Shilimkar Acked-by: Nishant Kamat Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dma.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index b1d3c7991ff..21cc0142b97 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -1901,7 +1901,7 @@ static int omap2_dma_handle_ch(int ch) /* STATUS register count is from 1-32 while our is 0-31 */ static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id) { - u32 val; + u32 val, enable_reg; int i; val = dma_read(IRQSTATUS_L0); @@ -1910,6 +1910,8 @@ static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id) printk(KERN_WARNING "Spurious DMA IRQ\n"); return IRQ_HANDLED; } + enable_reg = dma_read(IRQENABLE_L0); + val &= enable_reg; /* Dispatch only relevant interrupts */ for (i = 0; i < dma_lch_count && val != 0; i++) { if (val & 1) omap2_dma_handle_ch(i); -- GitLab From b0b5aa3f4c17c6a21423b9728d701216ab2e1ff1 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 23 Mar 2009 18:07:49 -0700 Subject: [PATCH 4005/4982] ARM: OMAP: get rid of OMAP_TAG_USB, v2 OMAP_TAGS should vanish soon since they're not generic arm tags. Most of them can be converted to a platform_data or parsed from a command line like e.g. serial tag. For OMAP_TAG_USB we just let boards call omap_usb_init() passing a pointer to omap_usb_config. Patch updated by Tony for mainline, basically make n770 and h4 compile. Also folded in a fix for OSK by David Brownell . Signed-off-by: Felipe Balbi Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/board-ams-delta.c | 2 +- arch/arm/mach-omap1/board-generic.c | 5 ++-- arch/arm/mach-omap1/board-h2.c | 2 +- arch/arm/mach-omap1/board-h3.c | 2 +- arch/arm/mach-omap1/board-innovator.c | 5 ++-- arch/arm/mach-omap1/board-nokia770.c | 9 +------ arch/arm/mach-omap1/board-osk.c | 3 ++- arch/arm/mach-omap1/board-palmte.c | 2 +- arch/arm/mach-omap1/board-palmtt.c | 2 +- arch/arm/mach-omap1/board-palmz71.c | 2 +- arch/arm/mach-omap1/board-sx1.c | 2 +- arch/arm/mach-omap1/board-voiceblue.c | 2 +- arch/arm/mach-omap2/board-apollon.c | 2 +- arch/arm/mach-omap2/board-h4.c | 34 +++++++++++++++++++++++++ arch/arm/plat-omap/include/mach/board.h | 1 - arch/arm/plat-omap/include/mach/usb.h | 2 ++ arch/arm/plat-omap/usb.c | 25 +++--------------- 17 files changed, 56 insertions(+), 46 deletions(-) diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index 2e618391cc5..8b40aace9db 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c @@ -175,7 +175,6 @@ static struct omap_usb_config ams_delta_usb_config __initdata = { static struct omap_board_config_kernel ams_delta_config[] = { { OMAP_TAG_LCD, &ams_delta_lcd_config }, { OMAP_TAG_UART, &ams_delta_uart_config }, - { OMAP_TAG_USB, &ams_delta_usb_config }, }; static struct resource ams_delta_kp_resources[] = { @@ -232,6 +231,7 @@ static void __init ams_delta_init(void) /* Clear latch2 (NAND, LCD, modem enable) */ ams_delta_latch2_write(~0, 0); + omap_usb_init(&ams_delta_usb_config); platform_add_devices(ams_delta_devices, ARRAY_SIZE(ams_delta_devices)); } diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c index 7d267020537..e724940e86f 100644 --- a/arch/arm/mach-omap1/board-generic.c +++ b/arch/arm/mach-omap1/board-generic.c @@ -62,7 +62,6 @@ static struct omap_uart_config generic_uart_config __initdata = { }; static struct omap_board_config_kernel generic_config[] __initdata = { - { OMAP_TAG_USB, NULL }, { OMAP_TAG_UART, &generic_uart_config }, }; @@ -70,12 +69,12 @@ static void __init omap_generic_init(void) { #ifdef CONFIG_ARCH_OMAP15XX if (cpu_is_omap15xx()) { - generic_config[0].data = &generic1510_usb_config; + omap_usb_init(&generic1510_usb_config); } #endif #if defined(CONFIG_ARCH_OMAP16XX) if (!cpu_is_omap1510()) { - generic_config[0].data = &generic1610_usb_config; + omap_usb_init(&generic1610_usb_config); } #endif diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c index b31b6d9b2e3..f695aa053ac 100644 --- a/arch/arm/mach-omap1/board-h2.c +++ b/arch/arm/mach-omap1/board-h2.c @@ -369,7 +369,6 @@ static struct omap_lcd_config h2_lcd_config __initdata = { }; static struct omap_board_config_kernel h2_config[] __initdata = { - { OMAP_TAG_USB, &h2_usb_config }, { OMAP_TAG_UART, &h2_uart_config }, { OMAP_TAG_LCD, &h2_lcd_config }, }; @@ -418,6 +417,7 @@ static void __init h2_init(void) omap_serial_init(); omap_register_i2c_bus(1, 100, h2_i2c_board_info, ARRAY_SIZE(h2_i2c_board_info)); + omap_usb_init(&h2_usb_config); h2_mmc_init(); } diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index 4b872f3822b..4695965114c 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c @@ -423,7 +423,6 @@ static struct omap_lcd_config h3_lcd_config __initdata = { }; static struct omap_board_config_kernel h3_config[] __initdata = { - { OMAP_TAG_USB, &h3_usb_config }, { OMAP_TAG_UART, &h3_uart_config }, { OMAP_TAG_LCD, &h3_lcd_config }, }; @@ -477,6 +476,7 @@ static void __init h3_init(void) omap_serial_init(); omap_register_i2c_bus(1, 100, h3_i2c_board_info, ARRAY_SIZE(h3_i2c_board_info)); + omap_usb_init(&h3_usb_config); h3_mmc_init(); } diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c index 714a08f79e9..2fd98260ea4 100644 --- a/arch/arm/mach-omap1/board-innovator.c +++ b/arch/arm/mach-omap1/board-innovator.c @@ -373,7 +373,6 @@ static struct omap_uart_config innovator_uart_config __initdata = { }; static struct omap_board_config_kernel innovator_config[] = { - { OMAP_TAG_USB, NULL }, { OMAP_TAG_LCD, NULL }, { OMAP_TAG_UART, &innovator_uart_config }, }; @@ -395,13 +394,13 @@ static void __init innovator_init(void) #ifdef CONFIG_ARCH_OMAP15XX if (cpu_is_omap1510()) { - innovator_config[0].data = &innovator1510_usb_config; + omap_usb_init(&innovator1510_usb_config); innovator_config[1].data = &innovator1510_lcd_config; } #endif #ifdef CONFIG_ARCH_OMAP16XX if (cpu_is_omap1610()) { - innovator_config[0].data = &h2_usb_config; + omap_usb_init(&h2_usb_config); innovator_config[1].data = &innovator1610_lcd_config; } #endif diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c index af51e0b180f..7bc7a3cb9c5 100644 --- a/arch/arm/mach-omap1/board-nokia770.c +++ b/arch/arm/mach-omap1/board-nokia770.c @@ -233,10 +233,6 @@ static inline void nokia770_mmc_init(void) } #endif -static struct omap_board_config_kernel nokia770_config[] __initdata = { - { OMAP_TAG_USB, NULL }, -}; - #if defined(CONFIG_OMAP_DSP) /* * audio power control @@ -371,19 +367,16 @@ static __init int omap_dsp_init(void) static void __init omap_nokia770_init(void) { - nokia770_config[0].data = &nokia770_usb_config; - platform_add_devices(nokia770_devices, ARRAY_SIZE(nokia770_devices)); spi_register_board_info(nokia770_spi_board_info, ARRAY_SIZE(nokia770_spi_board_info)); - omap_board_config = nokia770_config; - omap_board_config_size = ARRAY_SIZE(nokia770_config); omap_gpio_init(); omap_serial_init(); omap_register_i2c_bus(1, 100, NULL, 0); omap_dsp_init(); ads7846_dev_init(); mipid_dev_init(); + omap_usb_init(&nokia770_usb_config); nokia770_mmc_init(); } diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c index 9c4cac274cc..cf3247b15f8 100644 --- a/arch/arm/mach-omap1/board-osk.c +++ b/arch/arm/mach-omap1/board-osk.c @@ -304,7 +304,6 @@ static struct omap_lcd_config osk_lcd_config __initdata = { #endif static struct omap_board_config_kernel osk_config[] __initdata = { - { OMAP_TAG_USB, &osk_usb_config }, { OMAP_TAG_UART, &osk_uart_config }, #ifdef CONFIG_OMAP_OSK_MISTRAL { OMAP_TAG_LCD, &osk_lcd_config }, @@ -555,6 +554,8 @@ static void __init osk_init(void) l |= (3 << 1); omap_writel(l, USB_TRANSCEIVER_CTRL); + omap_usb_init(&osk_usb_config); + /* irq for tps65010 chip */ /* bootloader effectively does: omap_cfg_reg(U19_1610_MPUIO1); */ if (gpio_request(OMAP_MPUIO(1), "tps65010") == 0) diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c index 55d524b78e2..886b4c0569b 100644 --- a/arch/arm/mach-omap1/board-palmte.c +++ b/arch/arm/mach-omap1/board-palmte.c @@ -301,7 +301,6 @@ static void palmte_get_power_status(struct apm_power_info *info, int *battery) #endif static struct omap_board_config_kernel palmte_config[] __initdata = { - { OMAP_TAG_USB, &palmte_usb_config }, { OMAP_TAG_LCD, &palmte_lcd_config }, { OMAP_TAG_UART, &palmte_uart_config }, }; @@ -356,6 +355,7 @@ static void __init omap_palmte_init(void) spi_register_board_info(palmte_spi_info, ARRAY_SIZE(palmte_spi_info)); palmte_misc_gpio_setup(); omap_serial_init(); + omap_usb_init(&palmte_usb_config); omap_register_i2c_bus(1, 100, NULL, 0); } diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c index 9dc9d7931b5..4f1b44831d3 100644 --- a/arch/arm/mach-omap1/board-palmtt.c +++ b/arch/arm/mach-omap1/board-palmtt.c @@ -279,7 +279,6 @@ static struct omap_uart_config palmtt_uart_config __initdata = { }; static struct omap_board_config_kernel palmtt_config[] __initdata = { - { OMAP_TAG_USB, &palmtt_usb_config }, { OMAP_TAG_LCD, &palmtt_lcd_config }, { OMAP_TAG_UART, &palmtt_uart_config }, }; @@ -304,6 +303,7 @@ static void __init omap_palmtt_init(void) spi_register_board_info(palmtt_boardinfo,ARRAY_SIZE(palmtt_boardinfo)); omap_serial_init(); + omap_usb_init(&palmtt_usb_config); omap_register_i2c_bus(1, 100, NULL, 0); } diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c index a2f99a46e7b..9a55c3c5821 100644 --- a/arch/arm/mach-omap1/board-palmz71.c +++ b/arch/arm/mach-omap1/board-palmz71.c @@ -249,7 +249,6 @@ static struct omap_uart_config palmz71_uart_config __initdata = { }; static struct omap_board_config_kernel palmz71_config[] __initdata = { - {OMAP_TAG_USB, &palmz71_usb_config}, {OMAP_TAG_LCD, &palmz71_lcd_config}, {OMAP_TAG_UART, &palmz71_uart_config}, }; @@ -323,6 +322,7 @@ omap_palmz71_init(void) spi_register_board_info(palmz71_boardinfo, ARRAY_SIZE(palmz71_boardinfo)); + omap_usb_init(&palmz71_usb_config); omap_serial_init(); omap_register_i2c_bus(1, 100, NULL, 0); palmz71_gpio_setup(0); diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c index ab277d42f30..c096577695f 100644 --- a/arch/arm/mach-omap1/board-sx1.c +++ b/arch/arm/mach-omap1/board-sx1.c @@ -374,7 +374,6 @@ static struct omap_uart_config sx1_uart_config __initdata = { }; static struct omap_board_config_kernel sx1_config[] __initdata = { - { OMAP_TAG_USB, &sx1_usb_config }, { OMAP_TAG_LCD, &sx1_lcd_config }, { OMAP_TAG_UART, &sx1_uart_config }, }; @@ -389,6 +388,7 @@ static void __init omap_sx1_init(void) omap_board_config_size = ARRAY_SIZE(sx1_config); omap_serial_init(); omap_register_i2c_bus(1, 100, NULL, 0); + omap_usb_init(&sx1_usb_config); sx1_mmc_init(); /* turn on USB power */ diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c index a7653542a2b..98275e03dad 100644 --- a/arch/arm/mach-omap1/board-voiceblue.c +++ b/arch/arm/mach-omap1/board-voiceblue.c @@ -145,7 +145,6 @@ static struct omap_uart_config voiceblue_uart_config __initdata = { }; static struct omap_board_config_kernel voiceblue_config[] = { - { OMAP_TAG_USB, &voiceblue_usb_config }, { OMAP_TAG_UART, &voiceblue_uart_config }, }; @@ -185,6 +184,7 @@ static void __init voiceblue_init(void) omap_board_config = voiceblue_config; omap_board_config_size = ARRAY_SIZE(voiceblue_config); omap_serial_init(); + omap_usb_init(&voiceblue_usb_config); omap_register_i2c_bus(1, 100, NULL, 0); /* There is a good chance board is going up, so enable power LED diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c index 64561247d93..41823538d36 100644 --- a/arch/arm/mach-omap2/board-apollon.c +++ b/arch/arm/mach-omap2/board-apollon.c @@ -273,7 +273,6 @@ static struct omap_lcd_config apollon_lcd_config __initdata = { static struct omap_board_config_kernel apollon_config[] = { { OMAP_TAG_UART, &apollon_uart_config }, - { OMAP_TAG_USB, &apollon_usb_config }, { OMAP_TAG_LCD, &apollon_lcd_config }, }; @@ -300,6 +299,7 @@ static void __init apollon_usb_init(void) omap_cfg_reg(P21_242X_GPIO12); gpio_request(12, "USB suspend"); gpio_direction_output(12, 0); + omap_usb_init(&apollon_usb_config); } static void __init omap_apollon_init(void) diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c index 71226973eee..1343cebd19a 100644 --- a/arch/arm/mach-omap2/board-h4.c +++ b/arch/arm/mach-omap2/board-h4.c @@ -379,6 +379,39 @@ static struct omap_lcd_config h4_lcd_config __initdata = { .ctrl_name = "internal", }; +static struct omap_usb_config h4_usb_config __initdata = { +#ifdef CONFIG_MACH_OMAP2_H4_USB1 + /* NOTE: usb1 could also be used with 3 wire signaling */ + .pins[1] = 4, +#endif + +#ifdef CONFIG_MACH_OMAP_H4_OTG + /* S1.10 ON -- USB OTG port + * usb0 switched to Mini-AB port and isp1301 transceiver; + * S2.POS3 = OFF, S2.POS4 = ON ... to allow battery charging + */ + .otg = 1, + .pins[0] = 4, +#ifdef CONFIG_USB_GADGET_OMAP + /* use OTG cable, or standard A-to-MiniB */ + .hmc_mode = 0x14, /* 0:dev/otg 1:host 2:disable */ +#elif defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) + /* use OTG cable, or NONSTANDARD (B-to-MiniB) */ + .hmc_mode = 0x11, /* 0:host 1:host 2:disable */ +#endif /* XX */ + +#else + /* S1.10 OFF -- usb "download port" + * usb0 switched to Mini-B port and isp1105 transceiver; + * S2.POS3 = ON, S2.POS4 = OFF ... to enable battery charging + */ + .register_dev = 1, + .pins[0] = 3, +/* .hmc_mode = 0x14,*/ /* 0:dev 1:host 2:disable */ + .hmc_mode = 0x00, /* 0:dev|otg 1:disable 2:disable */ +#endif +}; + static struct omap_board_config_kernel h4_config[] = { { OMAP_TAG_UART, &h4_uart_config }, { OMAP_TAG_LCD, &h4_lcd_config }, @@ -430,6 +463,7 @@ static void __init omap_h4_init(void) platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices)); omap_board_config = h4_config; omap_board_config_size = ARRAY_SIZE(h4_config); + omap_usb_init(&h4_usb_config); omap_serial_init(); } diff --git a/arch/arm/plat-omap/include/mach/board.h b/arch/arm/plat-omap/include/mach/board.h index 4a0afd2366e..50ea79a0efa 100644 --- a/arch/arm/plat-omap/include/mach/board.h +++ b/arch/arm/plat-omap/include/mach/board.h @@ -17,7 +17,6 @@ /* Different peripheral ids */ #define OMAP_TAG_CLOCK 0x4f01 #define OMAP_TAG_SERIAL_CONSOLE 0x4f03 -#define OMAP_TAG_USB 0x4f04 #define OMAP_TAG_LCD 0x4f05 #define OMAP_TAG_GPIO_SWITCH 0x4f06 #define OMAP_TAG_UART 0x4f07 diff --git a/arch/arm/plat-omap/include/mach/usb.h b/arch/arm/plat-omap/include/mach/usb.h index a56a610950c..e033e51d4ba 100644 --- a/arch/arm/plat-omap/include/mach/usb.h +++ b/arch/arm/plat-omap/include/mach/usb.h @@ -29,6 +29,8 @@ #endif +void omap_usb_init(struct omap_usb_config *pdata); + /*-------------------------------------------------------------------------*/ /* diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c index e278de6862a..509f2ed99e2 100644 --- a/arch/arm/plat-omap/usb.c +++ b/arch/arm/plat-omap/usb.c @@ -729,30 +729,13 @@ static inline void omap_1510_usb_init(struct omap_usb_config *config) {} /*-------------------------------------------------------------------------*/ -static struct omap_usb_config platform_data; - -static int __init -omap_usb_init(void) +void __init omap_usb_init(struct omap_usb_config *pdata) { - const struct omap_usb_config *config; - - config = omap_get_config(OMAP_TAG_USB, struct omap_usb_config); - if (config == NULL) { - printk(KERN_ERR "USB: No board-specific " - "platform config found\n"); - return -ENODEV; - } - platform_data = *config; - if (cpu_is_omap730() || cpu_is_omap16xx() || cpu_is_omap24xx()) - omap_otg_init(&platform_data); + omap_otg_init(pdata); else if (cpu_is_omap15xx()) - omap_1510_usb_init(&platform_data); - else { + omap_1510_usb_init(pdata); + else printk(KERN_ERR "USB: No init for your chip yet\n"); - return -ENODEV; - } - return 0; } -subsys_initcall(omap_usb_init); -- GitLab From 2bb6c8026ccfa26ba713f4462f661aba7dd4dc16 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 23 Mar 2009 18:23:46 -0700 Subject: [PATCH 4006/4982] ARM: OMAP3: Remove unused CONFIG_I2C2_OMAP_BEAGLE There is no CONFIG_I2C2_OMAP_BEAGLE in mainline and it is under removal in linux-omap also so remove this dead code now. Signed-off-by: Jarkko Nikula Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-omap3beagle.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index e39cd2c46cf..e3c862866b7 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -175,9 +175,6 @@ static int __init omap3_beagle_i2c_init(void) { omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo, ARRAY_SIZE(beagle_i2c_boardinfo)); -#ifdef CONFIG_I2C2_OMAP_BEAGLE - omap_register_i2c_bus(2, 400, NULL, 0); -#endif /* Bus 3 is attached to the DVI port where devices like the pico DLP * projector don't work reliably with 400kHz */ omap_register_i2c_bus(3, 100, NULL, 0); -- GitLab From b9d766c767d53a9be1f741a53fe8151354ba1da3 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 23 Mar 2009 18:23:46 -0700 Subject: [PATCH 4007/4982] ARM: OMAP3: Add more GPIO mux options This patch adds several new GPIO pins and updates the pin naming comments. The patch is based on earlier patches on linux-omap list by Manikandan Pillai , Vaibhav Hiremath and David Brownell . Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/mux.c | 27 +++++++++++++++++++++++++++ arch/arm/plat-omap/include/mach/mux.h | 13 +++++++++++++ 2 files changed, 40 insertions(+) diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index dacb41f130c..026c4fc883a 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c @@ -453,10 +453,37 @@ MUX_CFG_34XX("AC1_3430_USB3FS_PHY_MM3_TXEN_N", 0x18a, /* 34XX GPIO - bidirectional, unless the name has an "_OUT" suffix. + * (Always specify PIN_INPUT, except for names suffixed by "_OUT".) * No internal pullup/pulldown without "_UP" or "_DOWN" suffix. */ +MUX_CFG_34XX("AF26_34XX_GPIO0", 0x1e0, + OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) +MUX_CFG_34XX("AF22_34XX_GPIO9", 0xa18, + OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) MUX_CFG_34XX("AH8_34XX_GPIO29", 0x5fa, OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) +MUX_CFG_34XX("U8_34XX_GPIO54_OUT", 0x0b4, + OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT) +MUX_CFG_34XX("U8_34XX_GPIO54_DOWN", 0x0b4, + OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT_PULLDOWN) +MUX_CFG_34XX("L8_34XX_GPIO63", 0x0ce, + OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) +MUX_CFG_34XX("G25_34XX_GPIO86_OUT", 0x0fc, + OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT) +MUX_CFG_34XX("AG4_34XX_GPIO134_OUT", 0x160, + OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT) +MUX_CFG_34XX("AE4_34XX_GPIO136_OUT", 0x164, + OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT) +MUX_CFG_34XX("AF6_34XX_GPIO140_UP", 0x16c, + OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT_PULLUP) +MUX_CFG_34XX("AE6_34XX_GPIO141", 0x16e, + OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) +MUX_CFG_34XX("AF5_34XX_GPIO142", 0x170, + OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) +MUX_CFG_34XX("AE5_34XX_GPIO143", 0x172, + OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) +MUX_CFG_34XX("H19_34XX_GPIO164_OUT", 0x19c, + OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT) MUX_CFG_34XX("J25_34XX_GPIO170", 0x1c6, OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) }; diff --git a/arch/arm/plat-omap/include/mach/mux.h b/arch/arm/plat-omap/include/mach/mux.h index 6a02f8f4c8b..85a62170576 100644 --- a/arch/arm/plat-omap/include/mach/mux.h +++ b/arch/arm/plat-omap/include/mach/mux.h @@ -838,7 +838,20 @@ enum omap34xx_index { * - "_DOWN" suffix (GPIO3_DOWN) with internal pulldown * - "_OUT" suffix (GPIO3_OUT) for output-only pins (unlike 24xx) */ + AF26_34XX_GPIO0, + AF22_34XX_GPIO9, AH8_34XX_GPIO29, + U8_34XX_GPIO54_OUT, + U8_34XX_GPIO54_DOWN, + L8_34XX_GPIO63, + G25_34XX_GPIO86_OUT, + AG4_34XX_GPIO134_OUT, + AE4_34XX_GPIO136_OUT, + AF6_34XX_GPIO140_UP, + AE6_34XX_GPIO141, + AF5_34XX_GPIO142, + AE5_34XX_GPIO143, + H19_34XX_GPIO164_OUT, J25_34XX_GPIO170, }; -- GitLab From 8466032d862a2e52d73af3311bc97f950aaa36c8 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Mon, 23 Mar 2009 18:23:46 -0700 Subject: [PATCH 4008/4982] ARM: OMAP3: mmc-twl4030 fix name buffer length, v2 Add 1 to buffer length for null terminator and use snprintf. Signed-off-by: Adrian Hunter Acked-by: David Brownell Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/mmc-twl4030.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c index 437f52073f6..84cac87537a 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.c +++ b/arch/arm/mach-omap2/mmc-twl4030.c @@ -59,7 +59,7 @@ static struct twl_mmc_controller { struct omap_mmc_platform_data *mmc; u8 twl_vmmc_dev_grp; u8 twl_mmc_dedicated; - char name[HSMMC_NAME_LEN]; + char name[HSMMC_NAME_LEN + 1]; } hsmmc[] = { { .twl_vmmc_dev_grp = VMMC1_DEV_GRP, @@ -349,7 +349,8 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) return; } - sprintf(twl->name, "mmc%islot%i", c->mmc, 1); + snprintf(twl->name, ARRAY_SIZE(twl->name), "mmc%islot%i", + c->mmc, 1); mmc->slots[0].name = twl->name; mmc->nr_slots = 1; mmc->slots[0].ocr_mask = MMC_VDD_165_195 | -- GitLab From 0329c3773e59aa7e50dc3760a27fb4e098773d0f Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 23 Mar 2009 18:23:47 -0700 Subject: [PATCH 4009/4982] ARM: OMAP3: mmc-twl4030 voltage cleanup Correct twl4030 MMC power switching: fix voltage ranges reported for each slot, and handle them fully. Lies corrected: - MMC-1 doesn't support the 2.6-2.7 Volt range - MMC-2 can't normally support anything except 1.8V Omissions corrected - MMC-1 *does* handle the 2.8-2.9 Volt range - MMC-2 can handle 2.5-3.2 Volt cards, given a transceiver Add transciever support for MMC-2; enable it for Overo and Pandora. (Depends on something else to have set up pinmuxing for control signals instead of as MMC2_DAT4..7 pins.) Also shrink twl4030_hsmmc_info a smidgeon ... padding is all gone. Signed-off-by: David Brownell Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-omap3pandora.c | 1 + arch/arm/mach-omap2/board-overo.c | 1 + arch/arm/mach-omap2/mmc-twl4030.c | 127 ++++++++++++++--------- arch/arm/mach-omap2/mmc-twl4030.h | 3 +- 4 files changed, 84 insertions(+), 48 deletions(-) diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index b3196107afd..7a46a6563a5 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -53,6 +53,7 @@ static struct twl4030_hsmmc_info omap3pandora_mmc[] = { .gpio_cd = -EINVAL, .gpio_wp = 127, .ext_clock = 1, + .transceiver = true, }, {} /* Terminator */ }; diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index b92313c8b84..9c14324d8c6 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -214,6 +214,7 @@ static struct twl4030_hsmmc_info mmc[] __initdata = { .wires = 4, .gpio_cd = -EINVAL, .gpio_wp = -EINVAL, + .transceiver = true, }, {} /* Terminator */ }; diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c index 84cac87537a..df1539e2cd0 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.c +++ b/arch/arm/mach-omap2/mmc-twl4030.c @@ -44,6 +44,7 @@ #define VMMC2_315V 0x0c #define VMMC2_300V 0x0b #define VMMC2_285V 0x0a +#define VMMC2_280V 0x09 #define VMMC2_260V 0x08 #define VMMC2_185V 0x06 #define VMMC2_DEDICATED 0x2E @@ -166,56 +167,73 @@ static int twl_mmc_resume(struct device *dev, int slot) /* * Sets the MMC voltage in twl4030 */ + +#define MMC1_OCR (MMC_VDD_165_195 \ + |MMC_VDD_28_29|MMC_VDD_29_30|MMC_VDD_30_31|MMC_VDD_31_32) +#define MMC2_OCR (MMC_VDD_165_195 \ + |MMC_VDD_25_26|MMC_VDD_26_27|MMC_VDD_27_28 \ + |MMC_VDD_28_29|MMC_VDD_29_30|MMC_VDD_30_31|MMC_VDD_31_32) + static int twl_mmc_set_voltage(struct twl_mmc_controller *c, int vdd) { int ret; u8 vmmc, dev_grp_val; - switch (1 << vdd) { - case MMC_VDD_35_36: - case MMC_VDD_34_35: - case MMC_VDD_33_34: - case MMC_VDD_32_33: - case MMC_VDD_31_32: - case MMC_VDD_30_31: - if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) - vmmc = VMMC1_315V; - else - vmmc = VMMC2_315V; - break; - case MMC_VDD_29_30: - if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) - vmmc = VMMC1_315V; - else - vmmc = VMMC2_300V; - break; - case MMC_VDD_27_28: - case MMC_VDD_26_27: - if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) - vmmc = VMMC1_285V; - else - vmmc = VMMC2_285V; - break; - case MMC_VDD_25_26: - case MMC_VDD_24_25: - case MMC_VDD_23_24: - case MMC_VDD_22_23: - case MMC_VDD_21_22: - case MMC_VDD_20_21: - if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) - vmmc = VMMC1_285V; - else - vmmc = VMMC2_260V; - break; - case MMC_VDD_165_195: - if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) + if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) { + /* VMMC1: max 220 mA. And for 8-bit mode, + * VSIM: max 50 mA + */ + switch (1 << vdd) { + case MMC_VDD_165_195: vmmc = VMMC1_185V; - else + /* and VSIM_180V */ + break; + case MMC_VDD_28_29: + vmmc = VMMC1_285V; + /* and VSIM_280V */ + break; + case MMC_VDD_29_30: + case MMC_VDD_30_31: + vmmc = VMMC1_300V; + /* and VSIM_300V */ + break; + case MMC_VDD_31_32: + vmmc = VMMC1_315V; + /* error if VSIM needed */ + break; + default: + vmmc = 0; + break; + } + } else if (c->twl_vmmc_dev_grp == VMMC2_DEV_GRP) { + /* VMMC2: max 100 mA */ + switch (1 << vdd) { + case MMC_VDD_165_195: vmmc = VMMC2_185V; - break; - default: - vmmc = 0; - break; + break; + case MMC_VDD_25_26: + case MMC_VDD_26_27: + vmmc = VMMC2_260V; + break; + case MMC_VDD_27_28: + vmmc = VMMC2_280V; + break; + case MMC_VDD_28_29: + vmmc = VMMC2_285V; + break; + case MMC_VDD_29_30: + case MMC_VDD_30_31: + vmmc = VMMC2_300V; + break; + case MMC_VDD_31_32: + vmmc = VMMC2_315V; + break; + default: + vmmc = 0; + break; + } + } else { + return 0; } if (vmmc) @@ -242,6 +260,14 @@ static int twl_mmc1_set_power(struct device *dev, int slot, int power_on, struct twl_mmc_controller *c = &hsmmc[0]; struct omap_mmc_platform_data *mmc = dev->platform_data; + /* + * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the + * card using the same TWL VMMC1 supply (hsmmc[0]); OMAP has both + * 1.8V and 3.0V modes, controlled by the PBIAS register. + * + * In 8-bit modes, OMAP VMMC1A (for DAT4..7) needs a supply, which + * is most naturally TWL VSIM; those pins also use PBIAS. + */ if (power_on) { if (cpu_is_omap2430()) { reg = omap_ctrl_readl(OMAP243X_CONTROL_DEVCONF1); @@ -298,6 +324,12 @@ static int twl_mmc2_set_power(struct device *dev, int slot, int power_on, int vd struct twl_mmc_controller *c = &hsmmc[1]; struct omap_mmc_platform_data *mmc = dev->platform_data; + /* + * Assume TWL VMMC2 (hsmmc[1]) is used only to power the card ... OMAP + * VDDS is used to power the pins, optionally with a transceiver to + * support cards using voltages other than VDDS (1.8V nominal). When a + * transceiver is used, DAT3..7 are muxed as transceiver control pins. + */ if (power_on) { if (mmc->slots[0].internal_clock) { u32 reg; @@ -353,10 +385,6 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) c->mmc, 1); mmc->slots[0].name = twl->name; mmc->nr_slots = 1; - mmc->slots[0].ocr_mask = MMC_VDD_165_195 | - MMC_VDD_26_27 | MMC_VDD_27_28 | - MMC_VDD_29_30 | - MMC_VDD_30_31 | MMC_VDD_31_32; mmc->slots[0].wires = c->wires; mmc->slots[0].internal_clock = !c->ext_clock; mmc->dma_mask = 0xffffffff; @@ -392,9 +420,14 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) switch (c->mmc) { case 1: mmc->slots[0].set_power = twl_mmc1_set_power; + mmc->slots[0].ocr_mask = MMC1_OCR; break; case 2: mmc->slots[0].set_power = twl_mmc2_set_power; + if (c->transceiver) + mmc->slots[0].ocr_mask = MMC2_OCR; + else + mmc->slots[0].ocr_mask = MMC_VDD_165_195; break; default: pr_err("MMC%d configuration not supported!\n", c->mmc); diff --git a/arch/arm/mach-omap2/mmc-twl4030.h b/arch/arm/mach-omap2/mmc-twl4030.h index e1c8076400c..380dde7bcfe 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.h +++ b/arch/arm/mach-omap2/mmc-twl4030.h @@ -9,9 +9,10 @@ struct twl4030_hsmmc_info { u8 mmc; /* controller 1/2/3 */ u8 wires; /* 1/4/8 wires */ + bool transceiver; /* MMC-2 option */ + bool ext_clock; /* use external pin for input clock */ int gpio_cd; /* or -EINVAL */ int gpio_wp; /* or -EINVAL */ - int ext_clock:1; /* use external pin for input clock */ }; #if defined(CONFIG_TWL4030_CORE) && \ -- GitLab From 01971f65ff88e3ebe2b6ae42b95d68e26b83718d Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 23 Mar 2009 18:23:47 -0700 Subject: [PATCH 4010/4982] ARM: OMAP3: mmc-twl4030 init passes device nodes back, v2 When setting up HSMMC devices, pass the device nodes back so board code can linking them to their power supply regulators. Signed-off-by: David Brownell Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/mmc-twl4030.c | 10 ++++++++++ arch/arm/mach-omap2/mmc-twl4030.h | 1 + arch/arm/plat-omap/devices.c | 3 +++ arch/arm/plat-omap/include/mach/mmc.h | 2 ++ 4 files changed, 16 insertions(+) diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c index df1539e2cd0..c67078db07b 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.c +++ b/arch/arm/mach-omap2/mmc-twl4030.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -437,6 +438,15 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) } omap2_init_mmc(hsmmc_data, OMAP34XX_NR_MMC); + + /* pass the device nodes back to board setup code */ + for (c = controllers; c->mmc; c++) { + struct omap_mmc_platform_data *mmc = hsmmc_data[c->mmc - 1]; + + if (!c->mmc || c->mmc > nr_hsmmc) + continue; + c->dev = mmc->dev; + } } #endif diff --git a/arch/arm/mach-omap2/mmc-twl4030.h b/arch/arm/mach-omap2/mmc-twl4030.h index 380dde7bcfe..21d35727f92 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.h +++ b/arch/arm/mach-omap2/mmc-twl4030.h @@ -13,6 +13,7 @@ struct twl4030_hsmmc_info { bool ext_clock; /* use external pin for input clock */ int gpio_cd; /* or -EINVAL */ int gpio_wp; /* or -EINVAL */ + struct device *dev; /* returned: pointer to mmc adapter */ }; #if defined(CONFIG_TWL4030_CORE) && \ diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index 208dbb121f4..87fb7ff4179 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -228,6 +228,9 @@ int __init omap_mmc_add(const char *name, int id, unsigned long base, ret = platform_device_add(pdev); if (ret) goto fail; + + /* return device handle to board setup code */ + data->dev = &pdev->dev; return 0; fail: diff --git a/arch/arm/plat-omap/include/mach/mmc.h b/arch/arm/plat-omap/include/mach/mmc.h index 73a9e15031b..4435bd434e1 100644 --- a/arch/arm/plat-omap/include/mach/mmc.h +++ b/arch/arm/plat-omap/include/mach/mmc.h @@ -37,6 +37,8 @@ #define OMAP_MMC_MAX_SLOTS 2 struct omap_mmc_platform_data { + /* back-link to device */ + struct device *dev; /* number of slots per controller */ unsigned nr_slots:2; -- GitLab From 07d83cc9c839a5f05c7c1b6d823a8f483bda0441 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Mon, 23 Mar 2009 18:23:47 -0700 Subject: [PATCH 4011/4982] ARM: OMAP3: mmc-twl4030 add MMC3 support, v2 Device connected to MMC3 is assumed to be self-powered, so set_power() function is empty. It can't be omited because host driver requires it. Array size for hsmmc[] is specified to allocate to allocate an instance for the third MMC controller. Also fix a leak which happens if invalid controller id is passed. Signed-off-by: Grazvydas Ignotas Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-omap3pandora.c | 6 ++++++ arch/arm/mach-omap2/mmc-twl4030.c | 19 +++++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index 7a46a6563a5..6e17180c1a5 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -55,6 +55,12 @@ static struct twl4030_hsmmc_info omap3pandora_mmc[] = { .ext_clock = 1, .transceiver = true, }, + { + .mmc = 3, + .wires = 4, + .gpio_cd = -EINVAL, + .gpio_wp = -EINVAL, + }, {} /* Terminator */ }; diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c index c67078db07b..d9fad8dda15 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.c +++ b/arch/arm/mach-omap2/mmc-twl4030.c @@ -62,7 +62,7 @@ static struct twl_mmc_controller { u8 twl_vmmc_dev_grp; u8 twl_mmc_dedicated; char name[HSMMC_NAME_LEN + 1]; -} hsmmc[] = { +} hsmmc[OMAP34XX_NR_MMC] = { { .twl_vmmc_dev_grp = VMMC1_DEV_GRP, .twl_mmc_dedicated = VMMC1_DEDICATED, @@ -347,6 +347,16 @@ static int twl_mmc2_set_power(struct device *dev, int slot, int power_on, int vd return ret; } +static int twl_mmc3_set_power(struct device *dev, int slot, int power_on, + int vdd) +{ + /* + * Assume MMC3 has self-powered device connected, for example on-board + * chip with external power source. + */ + return 0; +} + static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata; void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) @@ -415,7 +425,7 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) /* NOTE: we assume OMAP's MMC1 and MMC2 use * the TWL4030's VMMC1 and VMMC2, respectively; - * and that OMAP's MMC3 isn't used. + * and that MMC3 device has it's own power source. */ switch (c->mmc) { @@ -430,8 +440,13 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) else mmc->slots[0].ocr_mask = MMC_VDD_165_195; break; + case 3: + mmc->slots[0].set_power = twl_mmc3_set_power; + mmc->slots[0].ocr_mask = MMC_VDD_165_195; + break; default: pr_err("MMC%d configuration not supported!\n", c->mmc); + kfree(mmc); continue; } hsmmc_data[c->mmc - 1] = mmc; -- GitLab From 034ae7b41720a26cadd4b2f02bf0b23e79240344 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 23 Mar 2009 18:23:48 -0700 Subject: [PATCH 4012/4982] ARM: OMAP3: mmc-twl4030 fix for vmmc = 0 Resolve longstanding issue noted by Adrian Hunter: confusion between settting VSEL=0 (which is 1.8V on MMC1) and poweroff. Also, leave VSEL alone if we're just powering the regulator off. Signed-off-by: David Brownell Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/mmc-twl4030.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c index d9fad8dda15..d43421400e9 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.c +++ b/arch/arm/mach-omap2/mmc-twl4030.c @@ -178,7 +178,10 @@ static int twl_mmc_resume(struct device *dev, int slot) static int twl_mmc_set_voltage(struct twl_mmc_controller *c, int vdd) { int ret; - u8 vmmc, dev_grp_val; + u8 vmmc = 0, dev_grp_val; + + if (!vdd) + goto doit; if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) { /* VMMC1: max 220 mA. And for 8-bit mode, @@ -203,8 +206,7 @@ static int twl_mmc_set_voltage(struct twl_mmc_controller *c, int vdd) /* error if VSIM needed */ break; default: - vmmc = 0; - break; + return -EINVAL; } } else if (c->twl_vmmc_dev_grp == VMMC2_DEV_GRP) { /* VMMC2: max 100 mA */ @@ -230,21 +232,21 @@ static int twl_mmc_set_voltage(struct twl_mmc_controller *c, int vdd) vmmc = VMMC2_315V; break; default: - vmmc = 0; - break; + return -EINVAL; } } else { - return 0; + return -EINVAL; } - if (vmmc) +doit: + if (vdd) dev_grp_val = VMMC_DEV_GRP_P1; /* Power up */ else dev_grp_val = LDO_CLR; /* Power down */ ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, dev_grp_val, c->twl_vmmc_dev_grp); - if (ret) + if (ret || !vdd) return ret; ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, -- GitLab From 8d75e98b5880f8f02be68ddc3cc4e3d433630d7b Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Mon, 23 Mar 2009 18:23:48 -0700 Subject: [PATCH 4013/4982] ARM: OMAP3: mmc-twl4030 add cover switch Allow a cover switch to be used to cause a rescan of the MMC slot. Signed-off-by: Adrian Hunter Acked-by: David Brownell Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/mmc-twl4030.c | 13 ++++++++++++- arch/arm/mach-omap2/mmc-twl4030.h | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c index d43421400e9..e2b2aeb713d 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.c +++ b/arch/arm/mach-omap2/mmc-twl4030.c @@ -100,6 +100,14 @@ static int twl_mmc_get_ro(struct device *dev, int slot) return gpio_get_value_cansleep(mmc->slots[0].gpio_wp); } +static int twl_mmc_get_cover_state(struct device *dev, int slot) +{ + struct omap_mmc_platform_data *mmc = dev->platform_data; + + /* NOTE: assumes card detect signal is active-low */ + return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); +} + /* * MMC Slot Initialization. */ @@ -411,7 +419,10 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) mmc->slots[0].switch_pin = c->gpio_cd; mmc->slots[0].card_detect_irq = gpio_to_irq(c->gpio_cd); - mmc->slots[0].card_detect = twl_mmc_card_detect; + if (c->cover_only) + mmc->slots[0].get_cover_state = twl_mmc_get_cover_state; + else + mmc->slots[0].card_detect = twl_mmc_card_detect; } else mmc->slots[0].switch_pin = -EINVAL; diff --git a/arch/arm/mach-omap2/mmc-twl4030.h b/arch/arm/mach-omap2/mmc-twl4030.h index 21d35727f92..0aa168690ed 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.h +++ b/arch/arm/mach-omap2/mmc-twl4030.h @@ -11,6 +11,7 @@ struct twl4030_hsmmc_info { u8 wires; /* 1/4/8 wires */ bool transceiver; /* MMC-2 option */ bool ext_clock; /* use external pin for input clock */ + bool cover_only; /* No card detect - just cover switch */ int gpio_cd; /* or -EINVAL */ int gpio_wp; /* or -EINVAL */ struct device *dev; /* returned: pointer to mmc adapter */ -- GitLab From e51151a53fc85fb1730ec4d6c1474275dcdb9ec3 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Mon, 23 Mar 2009 18:23:48 -0700 Subject: [PATCH 4014/4982] ARM: OMAP3: mmc-twl4030 allow arbitrary slot names, v3 Signed-off-by: Adrian Hunter Acked-by: David Brownell Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/mmc-twl4030.c | 7 +++++-- arch/arm/mach-omap2/mmc-twl4030.h | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c index e2b2aeb713d..dc40b3e7220 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.c +++ b/arch/arm/mach-omap2/mmc-twl4030.c @@ -402,8 +402,11 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) return; } - snprintf(twl->name, ARRAY_SIZE(twl->name), "mmc%islot%i", - c->mmc, 1); + if (c->name) + strncpy(twl->name, c->name, HSMMC_NAME_LEN); + else + snprintf(twl->name, ARRAY_SIZE(twl->name), + "mmc%islot%i", c->mmc, 1); mmc->slots[0].name = twl->name; mmc->nr_slots = 1; mmc->slots[0].wires = c->wires; diff --git a/arch/arm/mach-omap2/mmc-twl4030.h b/arch/arm/mach-omap2/mmc-twl4030.h index 0aa168690ed..ea59e862429 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.h +++ b/arch/arm/mach-omap2/mmc-twl4030.h @@ -14,6 +14,7 @@ struct twl4030_hsmmc_info { bool cover_only; /* No card detect - just cover switch */ int gpio_cd; /* or -EINVAL */ int gpio_wp; /* or -EINVAL */ + char *name; /* or NULL for default */ struct device *dev; /* returned: pointer to mmc adapter */ }; -- GitLab From 828c707e6dbd0ca7882f721a466ff28729376ff0 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 23 Mar 2009 18:23:49 -0700 Subject: [PATCH 4015/4982] ARM: OMAP3: Add base address definitions and resources for OMAP 3 IS, v2 This replaces earlier patch from Sergio Aguirre titled "[REVIEW PATCH 03/14] OMAP34XX: CAM: Resources fixes". Signed-off-by: Sakari Ailus Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/devices.c | 108 +++++++++++++++++++++ arch/arm/plat-omap/include/mach/omap34xx.h | 27 ++++++ 2 files changed, 135 insertions(+) diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 14537ffd8af..7b2af1ba553 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -28,6 +28,113 @@ #include #include +#if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE) + +static struct resource cam_resources[] = { + { + .start = OMAP24XX_CAMERA_BASE, + .end = OMAP24XX_CAMERA_BASE + 0xfff, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_24XX_CAM_IRQ, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device omap_cam_device = { + .name = "omap24xxcam", + .id = -1, + .num_resources = ARRAY_SIZE(cam_resources), + .resource = cam_resources, +}; + +static inline void omap_init_camera(void) +{ + platform_device_register(&omap_cam_device); +} + +#elif defined(CONFIG_VIDEO_OMAP3) || defined(CONFIG_VIDEO_OMAP3_MODULE) + +static struct resource omap3isp_resources[] = { + { + .start = OMAP3430_ISP_BASE, + .end = OMAP3430_ISP_END, + .flags = IORESOURCE_MEM, + }, + { + .start = OMAP3430_ISP_CBUFF_BASE, + .end = OMAP3430_ISP_CBUFF_END, + .flags = IORESOURCE_MEM, + }, + { + .start = OMAP3430_ISP_CCP2_BASE, + .end = OMAP3430_ISP_CCP2_END, + .flags = IORESOURCE_MEM, + }, + { + .start = OMAP3430_ISP_CCDC_BASE, + .end = OMAP3430_ISP_CCDC_END, + .flags = IORESOURCE_MEM, + }, + { + .start = OMAP3430_ISP_HIST_BASE, + .end = OMAP3430_ISP_HIST_END, + .flags = IORESOURCE_MEM, + }, + { + .start = OMAP3430_ISP_H3A_BASE, + .end = OMAP3430_ISP_H3A_END, + .flags = IORESOURCE_MEM, + }, + { + .start = OMAP3430_ISP_PREV_BASE, + .end = OMAP3430_ISP_PREV_END, + .flags = IORESOURCE_MEM, + }, + { + .start = OMAP3430_ISP_RESZ_BASE, + .end = OMAP3430_ISP_RESZ_END, + .flags = IORESOURCE_MEM, + }, + { + .start = OMAP3430_ISP_SBL_BASE, + .end = OMAP3430_ISP_SBL_END, + .flags = IORESOURCE_MEM, + }, + { + .start = OMAP3430_ISP_CSI2A_BASE, + .end = OMAP3430_ISP_CSI2A_END, + .flags = IORESOURCE_MEM, + }, + { + .start = OMAP3430_ISP_CSI2PHY_BASE, + .end = OMAP3430_ISP_CSI2PHY_END, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_34XX_CAM_IRQ, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device omap3isp_device = { + .name = "omap3isp", + .id = -1, + .num_resources = ARRAY_SIZE(omap3isp_resources), + .resource = omap3isp_resources, +}; + +static inline void omap_init_camera(void) +{ + platform_device_register(&omap3isp_device); +} +#else +static inline void omap_init_camera(void) +{ +} +#endif + #if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE) #define MBOX_REG_SIZE 0x120 @@ -527,6 +634,7 @@ static int __init omap2_init_devices(void) * in alphabetical order so they're easier to sort through. */ omap_hsmmc_reset(); + omap_init_camera(); omap_init_mbox(); omap_init_mcspi(); omap_hdq_init(); diff --git a/arch/arm/plat-omap/include/mach/omap34xx.h b/arch/arm/plat-omap/include/mach/omap34xx.h index 89173f16b9b..1b1c35d2169 100644 --- a/arch/arm/plat-omap/include/mach/omap34xx.h +++ b/arch/arm/plat-omap/include/mach/omap34xx.h @@ -49,6 +49,33 @@ #define OMAP343X_CTRL_BASE OMAP343X_SCM_BASE #define OMAP34XX_IC_BASE 0x48200000 + +#define OMAP3430_ISP_BASE (L4_34XX_BASE + 0xBC000) +#define OMAP3430_ISP_CBUFF_BASE (OMAP3430_ISP_BASE + 0x0100) +#define OMAP3430_ISP_CCP2_BASE (OMAP3430_ISP_BASE + 0x0400) +#define OMAP3430_ISP_CCDC_BASE (OMAP3430_ISP_BASE + 0x0600) +#define OMAP3430_ISP_HIST_BASE (OMAP3430_ISP_BASE + 0x0A00) +#define OMAP3430_ISP_H3A_BASE (OMAP3430_ISP_BASE + 0x0C00) +#define OMAP3430_ISP_PREV_BASE (OMAP3430_ISP_BASE + 0x0E00) +#define OMAP3430_ISP_RESZ_BASE (OMAP3430_ISP_BASE + 0x1000) +#define OMAP3430_ISP_SBL_BASE (OMAP3430_ISP_BASE + 0x1200) +#define OMAP3430_ISP_MMU_BASE (OMAP3430_ISP_BASE + 0x1400) +#define OMAP3430_ISP_CSI2A_BASE (OMAP3430_ISP_BASE + 0x1800) +#define OMAP3430_ISP_CSI2PHY_BASE (OMAP3430_ISP_BASE + 0x1970) + +#define OMAP3430_ISP_END (OMAP3430_ISP_BASE + 0x06F) +#define OMAP3430_ISP_CBUFF_END (OMAP3430_ISP_CBUFF_BASE + 0x077) +#define OMAP3430_ISP_CCP2_END (OMAP3430_ISP_CCP2_BASE + 0x1EF) +#define OMAP3430_ISP_CCDC_END (OMAP3430_ISP_CCDC_BASE + 0x0A7) +#define OMAP3430_ISP_HIST_END (OMAP3430_ISP_HIST_BASE + 0x047) +#define OMAP3430_ISP_H3A_END (OMAP3430_ISP_H3A_BASE + 0x05F) +#define OMAP3430_ISP_PREV_END (OMAP3430_ISP_PREV_BASE + 0x09F) +#define OMAP3430_ISP_RESZ_END (OMAP3430_ISP_RESZ_BASE + 0x0AB) +#define OMAP3430_ISP_SBL_END (OMAP3430_ISP_SBL_BASE + 0x0FB) +#define OMAP3430_ISP_MMU_END (OMAP3430_ISP_MMU_BASE + 0x06F) +#define OMAP3430_ISP_CSI2A_END (OMAP3430_ISP_CSI2A_BASE + 0x16F) +#define OMAP3430_ISP_CSI2PHY_END (OMAP3430_ISP_CSI2PHY_BASE + 0x007) + #define OMAP34XX_IVA_INTC_BASE 0x40000000 #define OMAP34XX_HSUSB_OTG_BASE (L4_34XX_BASE + 0xAB000) #define OMAP34XX_HSUSB_HOST_BASE (L4_34XX_BASE + 0x64000) -- GitLab From 18cb7aca6f94357d78d99970ec0bd5933ac4495d Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 23 Mar 2009 18:34:06 -0700 Subject: [PATCH 4016/4982] ARM: OMAP3: MUSB initialization for omap hw, v2 Create a generic board-file for initializing usb on omap2430 and omap3 boards. Patch modified by Tony to build the module based on CONFIG_USB_MUSB_SOC. Also merged in a patch adding the nop xceiv from Ajay Kumar Gupta . Signed-off-by: Ajay Kumar Gupta Signed-off-by: Felipe Balbi Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/Makefile | 4 + arch/arm/mach-omap2/board-2430sdp.c | 2 + arch/arm/mach-omap2/board-ldp.c | 2 + arch/arm/mach-omap2/board-omap3beagle.c | 2 + arch/arm/mach-omap2/board-omap3pandora.c | 2 + arch/arm/mach-omap2/board-overo.c | 2 + arch/arm/mach-omap2/usb-musb.c | 187 +++++++++++++++++++++++ arch/arm/plat-omap/include/mach/usb.h | 8 + 8 files changed, 209 insertions(+) create mode 100644 arch/arm/mach-omap2/usb-musb.c diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index bbd12bc10fd..29f6ca94c36 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -39,3 +39,7 @@ obj-$(CONFIG_MACH_OVERO) += board-overo.o \ obj-$(CONFIG_MACH_OMAP3_PANDORA) += board-omap3pandora.o \ mmc-twl4030.o +# Platform specific device init code +ifeq ($(CONFIG_USB_MUSB_SOC),y) +obj-y += usb-musb.o +endif diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index c8abe6a8dfe..21ee2195eb5 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "mmc-twl4030.h" @@ -254,6 +255,7 @@ static void __init omap_2430sdp_init(void) omap_board_config_size = ARRAY_SIZE(sdp2430_config); omap_serial_init(); twl4030_mmc_init(mmc); + usb_musb_init(); } static void __init omap_2430sdp_map_io(void) diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index f035d7836e5..92661e5df93 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "mmc-twl4030.h" @@ -164,6 +165,7 @@ static void __init omap_ldp_init(void) omap_board_config_size = ARRAY_SIZE(ldp_config); omap_serial_init(); twl4030_mmc_init(mmc); + usb_musb_init(); } static void __init omap_ldp_map_io(void) diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index e3c862866b7..2f3d821e634 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "mmc-twl4030.h" @@ -313,6 +314,7 @@ static void __init omap3_beagle_init(void) /* REVISIT leave DVI powered down until it's needed ... */ gpio_direction_output(170, true); + usb_musb_init(); omap3beagle_flash_init(); } diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index 6e17180c1a5..16e2128daa1 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "mmc-twl4030.h" @@ -200,6 +201,7 @@ static void __init omap3pandora_init(void) spi_register_board_info(omap3pandora_spi_board_info, ARRAY_SIZE(omap3pandora_spi_board_info)); omap3pandora_ads7846_init(); + usb_musb_init(); } static void __init omap3pandora_map_io(void) diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index 9c14324d8c6..d3ceed398e0 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "mmc-twl4030.h" @@ -228,6 +229,7 @@ static void __init overo_init(void) omap_serial_init(); twl4030_mmc_init(mmc); overo_flash_init(); + usb_musb_init(); if ((gpio_request(OVERO_GPIO_W2W_NRESET, "OVERO_GPIO_W2W_NRESET") == 0) && diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c new file mode 100644 index 00000000000..fc74e913c41 --- /dev/null +++ b/arch/arm/mach-omap2/usb-musb.c @@ -0,0 +1,187 @@ +/* + * linux/arch/arm/mach-omap2/usb-musb.c + * + * This file will contain the board specific details for the + * MENTOR USB OTG controller on OMAP3430 + * + * Copyright (C) 2007-2008 Texas Instruments + * Copyright (C) 2008 Nokia Corporation + * Author: Vikram Pandita + * + * Generalization by: + * Felipe Balbi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +static struct resource musb_resources[] = { + [0] = { /* start and end set dynamically */ + .flags = IORESOURCE_MEM, + }, + [1] = { /* general IRQ */ + .start = INT_243X_HS_USB_MC, + .flags = IORESOURCE_IRQ, + }, + [2] = { /* DMA IRQ */ + .start = INT_243X_HS_USB_DMA, + .flags = IORESOURCE_IRQ, + }, +}; + +static int clk_on; + +static int musb_set_clock(struct clk *clk, int state) +{ + if (state) { + if (clk_on > 0) + return -ENODEV; + + clk_enable(clk); + clk_on = 1; + } else { + if (clk_on == 0) + return -ENODEV; + + clk_disable(clk); + clk_on = 0; + } + + return 0; +} + +static struct musb_hdrc_eps_bits musb_eps[] = { + { "ep1_tx", 10, }, + { "ep1_rx", 10, }, + { "ep2_tx", 9, }, + { "ep2_rx", 9, }, + { "ep3_tx", 3, }, + { "ep3_rx", 3, }, + { "ep4_tx", 3, }, + { "ep4_rx", 3, }, + { "ep5_tx", 3, }, + { "ep5_rx", 3, }, + { "ep6_tx", 3, }, + { "ep6_rx", 3, }, + { "ep7_tx", 3, }, + { "ep7_rx", 3, }, + { "ep8_tx", 2, }, + { "ep8_rx", 2, }, + { "ep9_tx", 2, }, + { "ep9_rx", 2, }, + { "ep10_tx", 2, }, + { "ep10_rx", 2, }, + { "ep11_tx", 2, }, + { "ep11_rx", 2, }, + { "ep12_tx", 2, }, + { "ep12_rx", 2, }, + { "ep13_tx", 2, }, + { "ep13_rx", 2, }, + { "ep14_tx", 2, }, + { "ep14_rx", 2, }, + { "ep15_tx", 2, }, + { "ep15_rx", 2, }, +}; + +static struct musb_hdrc_config musb_config = { + .multipoint = 1, + .dyn_fifo = 1, + .soft_con = 1, + .dma = 1, + .num_eps = 16, + .dma_channels = 7, + .dma_req_chan = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3), + .ram_bits = 12, + .eps_bits = musb_eps, +}; + +static struct musb_hdrc_platform_data musb_plat = { +#ifdef CONFIG_USB_MUSB_OTG + .mode = MUSB_OTG, +#elif defined(CONFIG_USB_MUSB_HDRC_HCD) + .mode = MUSB_HOST, +#elif defined(CONFIG_USB_GADGET_MUSB_HDRC) + .mode = MUSB_PERIPHERAL, +#endif + /* .clock is set dynamically */ + .set_clock = musb_set_clock, + .config = &musb_config, + + /* REVISIT charge pump on TWL4030 can supply up to + * 100 mA ... but this value is board-specific, like + * "mode", and should be passed to usb_musb_init(). + */ + .power = 50, /* up to 100 mA */ +}; + +static u64 musb_dmamask = DMA_32BIT_MASK; + +static struct platform_device musb_device = { + .name = "musb_hdrc", + .id = -1, + .dev = { + .dma_mask = &musb_dmamask, + .coherent_dma_mask = DMA_32BIT_MASK, + .platform_data = &musb_plat, + }, + .num_resources = ARRAY_SIZE(musb_resources), + .resource = musb_resources, +}; + +#ifdef CONFIG_NOP_USB_XCEIV +static u64 nop_xceiv_dmamask = DMA_32BIT_MASK; + +static struct platform_device nop_xceiv_device = { + .name = "nop_usb_xceiv", + .id = -1, + .dev = { + .dma_mask = &nop_xceiv_dmamask, + .coherent_dma_mask = DMA_32BIT_MASK, + .platform_data = NULL, + }, +}; +#endif + +void __init usb_musb_init(void) +{ + if (cpu_is_omap243x()) + musb_resources[0].start = OMAP243X_HS_BASE; + else + musb_resources[0].start = OMAP34XX_HSUSB_OTG_BASE; + musb_resources[0].end = musb_resources[0].start + SZ_8K - 1; + + /* + * REVISIT: This line can be removed once all the platforms using + * musb_core.c have been converted to use use clkdev. + */ + musb_plat.clock = "ick"; + +#ifdef CONFIG_NOP_USB_XCEIV + if (platform_device_register(&nop_xceiv_device) < 0) { + printk(KERN_ERR "Unable to register NOP-XCEIV device\n"); + return; + } +#endif + + if (platform_device_register(&musb_device) < 0) { + printk(KERN_ERR "Unable to register HS-USB (MUSB) device\n"); + return; + } +} diff --git a/arch/arm/plat-omap/include/mach/usb.h b/arch/arm/plat-omap/include/mach/usb.h index e033e51d4ba..69f0ceed500 100644 --- a/arch/arm/plat-omap/include/mach/usb.h +++ b/arch/arm/plat-omap/include/mach/usb.h @@ -27,6 +27,14 @@ #define UDC_BASE OMAP2_UDC_BASE #define OMAP_OHCI_BASE OMAP2_OHCI_BASE +#ifdef CONFIG_USB_MUSB_SOC +extern void usb_musb_init(void); +#else +static inline void usb_musb_init(void) +{ +} +#endif + #endif void omap_usb_init(struct omap_usb_config *pdata); -- GitLab From c6a81316c721a20639871f08cf0cbff7e83889b4 Mon Sep 17 00:00:00 2001 From: Steve Sakoman Date: Mon, 23 Mar 2009 18:38:16 -0700 Subject: [PATCH 4017/4982] ARM: OMAP3: Add ADS7846 touchscreen support to Overo platform, v3 An upcoming Overo expansion board includes an ADS7846 touchscreen controller. This patch adds support via the ads7846 driver when enabled in the kernel config. Signed-off-by: Steve Sakoman Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-overo.c | 60 +++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index d3ceed398e0..782268c9194 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -57,6 +57,65 @@ #define GPMC_CS0_BASE 0x60 #define GPMC_CS_SIZE 0x30 +#if defined(CONFIG_TOUCHSCREEN_ADS7846) || \ + defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE) + +#include +#include +#include + +static struct omap2_mcspi_device_config ads7846_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, /* 0: slave, 1: master */ +}; + +static int ads7846_get_pendown_state(void) +{ + return !gpio_get_value(OVERO_GPIO_PENDOWN); +} + +static struct ads7846_platform_data ads7846_config = { + .x_max = 0x0fff, + .y_max = 0x0fff, + .x_plate_ohms = 180, + .pressure_max = 255, + .debounce_max = 10, + .debounce_tol = 3, + .debounce_rep = 1, + .get_pendown_state = ads7846_get_pendown_state, + .keep_vref_on = 1, +}; + +static struct spi_board_info overo_spi_board_info[] __initdata = { + { + .modalias = "ads7846", + .bus_num = 1, + .chip_select = 0, + .max_speed_hz = 1500000, + .controller_data = &ads7846_mcspi_config, + .irq = OMAP_GPIO_IRQ(OVERO_GPIO_PENDOWN), + .platform_data = &ads7846_config, + } +}; + +static void __init overo_ads7846_init(void) +{ + if ((gpio_request(OVERO_GPIO_PENDOWN, "ADS7846_PENDOWN") == 0) && + (gpio_direction_input(OVERO_GPIO_PENDOWN) == 0)) { + gpio_export(OVERO_GPIO_PENDOWN, 0); + } else { + printk(KERN_ERR "could not obtain gpio for ADS7846_PENDOWN\n"); + return; + } + + spi_register_board_info(overo_spi_board_info, + ARRAY_SIZE(overo_spi_board_info)); +} + +#else +static inline void __init overo_ads7846_init(void) { return; } +#endif + static struct mtd_partition overo_nand_partitions[] = { { .name = "xloader", @@ -230,6 +289,7 @@ static void __init overo_init(void) twl4030_mmc_init(mmc); overo_flash_init(); usb_musb_init(); + overo_ads7846_init(); if ((gpio_request(OVERO_GPIO_W2W_NRESET, "OVERO_GPIO_W2W_NRESET") == 0) && -- GitLab From 6fdc29e262f9a776a77f50ca9157f7c0dcfbbbc8 Mon Sep 17 00:00:00 2001 From: Syed Mohammed Khasim Date: Mon, 23 Mar 2009 18:38:16 -0700 Subject: [PATCH 4018/4982] ARM: OMAP3: Add support for 3430 SDP, v4 Add support for 3430 SDP. Various updates have been merged into this patch from the linux-omap list. Patch updated to initialize regulators by David Brownell . Signed-off-by: Syed Mohammed Khasim David Brownell Signed-off-by: Tony Lindgren --- arch/arm/configs/omap_3430sdp_defconfig | 2061 +++++++++++++++++++++++ arch/arm/mach-omap2/Kconfig | 6 +- arch/arm/mach-omap2/Makefile | 2 + arch/arm/mach-omap2/board-3430sdp.c | 542 ++++++ 4 files changed, 2610 insertions(+), 1 deletion(-) create mode 100644 arch/arm/configs/omap_3430sdp_defconfig create mode 100644 arch/arm/mach-omap2/board-3430sdp.c diff --git a/arch/arm/configs/omap_3430sdp_defconfig b/arch/arm/configs/omap_3430sdp_defconfig new file mode 100644 index 00000000000..8fb918d9ba6 --- /dev/null +++ b/arch/arm/configs/omap_3430sdp_defconfig @@ -0,0 +1,2061 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.29-rc8 +# Fri Mar 13 14:17:01 2009 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_OPROFILE_ARMV7=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set +# CONFIG_CGROUPS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +# CONFIG_ELF_CORE is not set +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +# CONFIG_COMPAT_BRK is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +CONFIG_PROFILING=y +CONFIG_TRACEPOINTS=y +# CONFIG_MARKERS is not set +CONFIG_OPROFILE=y +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_BLOCK=y +CONFIG_LBD=y +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_FREEZER=y + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +CONFIG_ARCH_OMAP=y +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_W90X900 is not set + +# +# TI OMAP Implementations +# +CONFIG_ARCH_OMAP_OTG=y +# CONFIG_ARCH_OMAP1 is not set +# CONFIG_ARCH_OMAP2 is not set +CONFIG_ARCH_OMAP3=y + +# +# OMAP Feature Selections +# +# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set +# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set +# CONFIG_OMAP_RESET_CLOCKS is not set +CONFIG_OMAP_MUX=y +CONFIG_OMAP_MUX_DEBUG=y +CONFIG_OMAP_MUX_WARNINGS=y +CONFIG_OMAP_MCBSP=y +# CONFIG_OMAP_MPU_TIMER is not set +CONFIG_OMAP_32K_TIMER=y +CONFIG_OMAP_32K_TIMER_HZ=128 +CONFIG_OMAP_DM_TIMER=y +# CONFIG_OMAP_LL_DEBUG_UART1 is not set +# CONFIG_OMAP_LL_DEBUG_UART2 is not set +CONFIG_OMAP_LL_DEBUG_UART3=y +CONFIG_OMAP_SERIAL_WAKE=y +CONFIG_ARCH_OMAP34XX=y +CONFIG_ARCH_OMAP3430=y + +# +# OMAP Board Type +# +CONFIG_MACH_OMAP3_BEAGLE=y +CONFIG_MACH_OMAP_LDP=y +CONFIG_MACH_OVERO=y +CONFIG_MACH_OMAP3_PANDORA=y +CONFIG_MACH_OMAP_3430SDP=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_V7=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_IFAR=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +CONFIG_ARM_THUMBEE=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_HAS_TLS_REG=y +# CONFIG_OUTER_CACHE is not set + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +# CONFIG_PREEMPT is not set +CONFIG_HZ=128 +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y +CONFIG_LEDS=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="console=ttyS2,115200 root=/dev/mmcblk0p3 rootwait debug" +# CONFIG_XIP_KERNEL is not set +CONFIG_KEXEC=y +CONFIG_ATAGS_PROC=y + +# +# CPU Power Management +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +# CONFIG_CPU_FREQ_DEBUG is not set +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_NEON=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_HAVE_AOUT=y +CONFIG_BINFMT_AOUT=m +CONFIG_BINFMT_MISC=y + +# +# Power management options +# +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +CONFIG_PM_SLEEP=y +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +# CONFIG_APM_EMULATION is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_COMPAT_NET_DEV_OPS=y +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=m +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=m +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +CONFIG_BT=y +CONFIG_BT_L2CAP=y +CONFIG_BT_SCO=y +CONFIG_BT_RFCOMM=y +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=y +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=y + +# +# Bluetooth device drivers +# +# CONFIG_BT_HCIBTUSB is not set +# CONFIG_BT_HCIBTSDIO is not set +CONFIG_BT_HCIUART=y +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +# CONFIG_BT_HCIUART_LL is not set +CONFIG_BT_HCIBCM203X=y +CONFIG_BT_HCIBPA10X=y +# CONFIG_BT_HCIBFUSB is not set +# CONFIG_BT_HCIVHCI is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y +CONFIG_CFG80211=y +# CONFIG_CFG80211_REG_DEBUG is not set +CONFIG_NL80211=y +CONFIG_WIRELESS_OLD_REGULATORY=y +CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +CONFIG_LIB80211=y +CONFIG_LIB80211_CRYPT_WEP=m +CONFIG_LIB80211_CRYPT_CCMP=m +CONFIG_LIB80211_CRYPT_TKIP=m +CONFIG_MAC80211=y + +# +# Rate control algorithm selection +# +CONFIG_MAC80211_RC_PID=y +# CONFIG_MAC80211_RC_MINSTREL is not set +CONFIG_MAC80211_RC_DEFAULT_PID=y +# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set +CONFIG_MAC80211_RC_DEFAULT="pid" +# CONFIG_MAC80211_MESH is not set +CONFIG_MAC80211_LEDS=y +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=m +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +# CONFIG_BLK_DEV_XIP is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_MISC_DEVICES=y +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +CONFIG_EEPROM_93CX6=m +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=m +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_LIBFC is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_ATA is not set +CONFIG_MD=y +CONFIG_BLK_DEV_MD=m +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +# CONFIG_DM_DEBUG is not set +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_DELAY=m +# CONFIG_DM_UEVENT is not set +CONFIG_NETDEVICES=y +CONFIG_DUMMY=m +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +CONFIG_TUN=m +# CONFIG_VETH is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +CONFIG_SMSC_PHY=y +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +CONFIG_SMC91X=y +# CONFIG_DM9000 is not set +# CONFIG_ENC28J60 is not set +CONFIG_SMC911X=m +CONFIG_SMSC911X=m +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +CONFIG_WLAN_80211=y +CONFIG_LIBERTAS=y +CONFIG_LIBERTAS_USB=y +CONFIG_LIBERTAS_SDIO=y +CONFIG_LIBERTAS_DEBUG=y +# CONFIG_LIBERTAS_THINFIRM is not set +CONFIG_USB_ZD1201=m +# CONFIG_USB_NET_RNDIS_WLAN is not set +CONFIG_RTL8187=m +# CONFIG_MAC80211_HWSIM is not set +CONFIG_P54_COMMON=m +CONFIG_P54_USB=m +# CONFIG_IWLWIFI_LEDS is not set +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +# CONFIG_ZD1211RW is not set +# CONFIG_RT2X00 is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=y +CONFIG_USB_NET_AX8817X=y +CONFIG_USB_NET_CDCETHER=y +CONFIG_USB_NET_DM9601=m +# CONFIG_USB_NET_SMSC95XX is not set +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_KC2190=y +CONFIG_USB_NET_ZAURUS=m +# CONFIG_WAN is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +# CONFIG_PPPOL2TP is not set +# CONFIG_SLIP is not set +CONFIG_SLHC=m +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_GPIO is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_OMAP=y +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_GPIO is not set +CONFIG_SPI_OMAP24XX=y + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_DEBUG_GPIO=y +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +CONFIG_GPIO_TWL4030=y + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_W1 is not set +CONFIG_POWER_SUPPLY=m +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_BATTERY_DS2760 is not set +# CONFIG_BATTERY_BQ27x00 is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7473 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_OMAP_WATCHDOG is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_TPS65010 is not set +CONFIG_TWL4030_CORE=y +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L2_COMMON=m +CONFIG_VIDEO_ALLOW_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_DVB_CORE=m +CONFIG_VIDEO_MEDIA=m + +# +# Multimedia drivers +# +CONFIG_MEDIA_ATTACH=y +CONFIG_MEDIA_TUNER=m +# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set +CONFIG_MEDIA_TUNER_SIMPLE=m +CONFIG_MEDIA_TUNER_TDA8290=m +CONFIG_MEDIA_TUNER_TDA827X=m +CONFIG_MEDIA_TUNER_TDA18271=m +CONFIG_MEDIA_TUNER_TDA9887=m +CONFIG_MEDIA_TUNER_TEA5761=m +CONFIG_MEDIA_TUNER_TEA5767=m +CONFIG_MEDIA_TUNER_MT20XX=m +CONFIG_MEDIA_TUNER_MT2060=m +CONFIG_MEDIA_TUNER_MT2266=m +CONFIG_MEDIA_TUNER_QT1010=m +CONFIG_MEDIA_TUNER_XC2028=m +CONFIG_MEDIA_TUNER_XC5000=m +CONFIG_MEDIA_TUNER_MXL5005S=m +CONFIG_VIDEO_V4L2=m +CONFIG_VIDEO_V4L1=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_CAPTURE_DRIVERS=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +CONFIG_VIDEO_HELPER_CHIPS_AUTO=y +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_CX2341X=m +# CONFIG_VIDEO_VIVI is not set +# CONFIG_VIDEO_CPIA is not set +# CONFIG_VIDEO_CPIA2 is not set +# CONFIG_VIDEO_SAA5246A is not set +# CONFIG_VIDEO_SAA5249 is not set +# CONFIG_VIDEO_AU0828 is not set +# CONFIG_SOC_CAMERA is not set +CONFIG_V4L_USB_DRIVERS=y +CONFIG_USB_VIDEO_CLASS=m +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +# CONFIG_USB_GSPCA is not set +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_SYSFS=y +CONFIG_VIDEO_PVRUSB2_DVB=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +# CONFIG_VIDEO_EM28XX is not set +CONFIG_VIDEO_USBVISION=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_USB_VICAM=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_QUICKCAM_MESSENGER=m +# CONFIG_USB_ET61X251 is not set +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_USB_W9968CF=m +CONFIG_USB_OV511=m +CONFIG_USB_SE401=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STV680=m +# CONFIG_USB_ZC0301 is not set +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set +CONFIG_USB_ZR364XX=m +# CONFIG_USB_STKWEBCAM is not set +# CONFIG_USB_S2255 is not set +CONFIG_RADIO_ADAPTERS=y +# CONFIG_USB_DSBR is not set +# CONFIG_USB_SI470X is not set +# CONFIG_USB_MR800 is not set +# CONFIG_RADIO_TEA5764 is not set +# CONFIG_DVB_DYNAMIC_MINORS is not set +CONFIG_DVB_CAPTURE_DRIVERS=y +# CONFIG_TTPCI_EEPROM is not set + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_DIB0700=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_M920X=m +CONFIG_DVB_USB_GL861=m +CONFIG_DVB_USB_AU6610=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_TTUSB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_USB_OPERA1=m +CONFIG_DVB_USB_AF9005=m +CONFIG_DVB_USB_AF9005_REMOTE=m +# CONFIG_DVB_USB_DW2102 is not set +# CONFIG_DVB_USB_CINERGY_T2 is not set +# CONFIG_DVB_USB_ANYSEE is not set +# CONFIG_DVB_USB_DTV5100 is not set +# CONFIG_DVB_USB_AF9015 is not set +# CONFIG_DVB_SIANO_SMS1XXX is not set + +# +# Supported FlexCopII (B2C2) Adapters +# +# CONFIG_DVB_B2C2_FLEXCOP is not set + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# +# CONFIG_DVB_FE_CUSTOMISE is not set + +# +# Multistandard (satellite) frontends +# +# CONFIG_DVB_STB0899 is not set +# CONFIG_DVB_STB6100 is not set + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_MT312=m +CONFIG_DVB_S5H1420=m +# CONFIG_DVB_STV0288 is not set +# CONFIG_DVB_STB6000 is not set +CONFIG_DVB_STV0299=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_TDA10086=m +# CONFIG_DVB_TDA8261 is not set +CONFIG_DVB_VES1X93=m +CONFIG_DVB_TUNER_ITD1000=m +# CONFIG_DVB_TUNER_CX24113 is not set +CONFIG_DVB_TDA826X=m +CONFIG_DVB_TUA6100=m +# CONFIG_DVB_CX24116 is not set +# CONFIG_DVB_SI21XX is not set + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +# CONFIG_DVB_DRX397XD is not set +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m +CONFIG_DVB_DIB7000M=m +CONFIG_DVB_DIB7000P=m +CONFIG_DVB_TDA10048=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_TDA10023=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +# CONFIG_DVB_OR51211 is not set +# CONFIG_DVB_OR51132 is not set +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m +# CONFIG_DVB_LGDT3304 is not set +CONFIG_DVB_S5H1409=m +CONFIG_DVB_AU8522=m +CONFIG_DVB_S5H1411=m + +# +# ISDB-T (terrestrial) frontends +# +# CONFIG_DVB_S921 is not set + +# +# Digital terrestrial only tuners/PLL +# +CONFIG_DVB_PLL=m +CONFIG_DVB_TUNER_DIB0070=m + +# +# SEC control devices for DVB-S +# +CONFIG_DVB_LNBP21=m +# CONFIG_DVB_ISL6405 is not set +CONFIG_DVB_ISL6421=m +# CONFIG_DVB_LGS8GL5 is not set + +# +# Tools to develop new frontends +# +# CONFIG_DVB_DUMMY_FE is not set +# CONFIG_DVB_AF9013 is not set +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +CONFIG_DISPLAY_SUPPORT=y + +# +# Display hardware drivers +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_SOUND=y +CONFIG_SOUND_OSS_CORE=y +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_HWDEP=y +CONFIG_SND_RAWMIDI=y +CONFIG_SND_SEQUENCER=m +# CONFIG_SND_SEQ_DUMMY is not set +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +# CONFIG_SND_HRTIMER is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +CONFIG_SND_VERBOSE_PRINTK=y +CONFIG_SND_DEBUG=y +# CONFIG_SND_DEBUG_VERBOSE is not set +# CONFIG_SND_PCM_XRUN_DEBUG is not set +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_VIRMIDI is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +CONFIG_SND_ARM=y +CONFIG_SND_SPI=y +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_USB_CAIAQ=m +CONFIG_SND_USB_CAIAQ_INPUT=y +CONFIG_SND_SOC=y +CONFIG_SND_OMAP_SOC=y +CONFIG_SND_OMAP_SOC_MCBSP=y +# CONFIG_SND_OMAP_SOC_OVERO is not set +CONFIG_SND_OMAP_SOC_SDP3430=y +CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=y +CONFIG_SND_SOC_I2C_AND_SPI=y +# CONFIG_SND_SOC_ALL_CODECS is not set +CONFIG_SND_SOC_TWL4030=y +# CONFIG_SOUND_PRIME is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +CONFIG_HID_DEBUG=y +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV is not set + +# +# Special HID drivers +# +CONFIG_HID_COMPAT=y +CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_EZKEY=y +CONFIG_HID_GYRATION=y +CONFIG_HID_LOGITECH=y +# CONFIG_LOGITECH_FF is not set +# CONFIG_LOGIRUMBLEPAD2_FF is not set +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +# CONFIG_HID_NTRIG is not set +CONFIG_HID_PANTHERLORD=y +# CONFIG_PANTHERLORD_FF is not set +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SONY=y +CONFIG_HID_SUNPLUS=y +# CONFIG_GREENASIA_FF is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_THRUSTMASTER_FF is not set +# CONFIG_ZEROPLUS_FF is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +CONFIG_USB_DEBUG=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +CONFIG_USB_DYNAMIC_MINORS=y +CONFIG_USB_SUSPEND=y +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +CONFIG_USB_MON=y +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_SOC=y + +# +# OMAP 343x high speed USB support +# +# CONFIG_USB_MUSB_HOST is not set +# CONFIG_USB_MUSB_PERIPHERAL is not set +CONFIG_USB_MUSB_OTG=y +CONFIG_USB_GADGET_MUSB_HDRC=y +CONFIG_USB_MUSB_HDRC_HCD=y +CONFIG_MUSB_PIO_ONLY=y +# CONFIG_USB_MUSB_DEBUG is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +CONFIG_USB_PRINTER=y +CONFIG_USB_WDM=y +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; +# + +# +# see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_PXA27X is not set +# CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_IMX is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_FSL_QE is not set +# CONFIG_USB_GADGET_CI13XXX is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_ZERO is not set +CONFIG_USB_ETH=y +CONFIG_USB_ETH_RNDIS=y +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set + +# +# OTG and related infrastructure +# +CONFIG_USB_OTG_UTILS=y +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_ISP1301_OMAP is not set +CONFIG_TWL4030_USB=y +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_UNSAFE_RESUME=y + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +CONFIG_SDIO_UART=y +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_OMAP is not set +CONFIG_MMC_OMAP_HS=y +# CONFIG_MMC_SPI is not set +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_PCA955X is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +CONFIG_RTC_DRV_TWL4030=y +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_DMADEVICES is not set +# CONFIG_REGULATOR is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_XATTR is not set +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y +CONFIG_XFS_FS=m +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_POSIX_ACL is not set +# CONFIG_XFS_RT is not set +# CONFIG_XFS_DEBUG is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QUOTA_NETLINK_INTERFACE is not set +CONFIG_PRINT_QUOTA_WARNING=y +CONFIG_QUOTA_TREE=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +CONFIG_FUSE_FS=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +CONFIG_JFFS2_FS_XATTR=y +CONFIG_JFFS2_FS_POSIX_ACL=y +CONFIG_JFFS2_FS_SECURITY=y +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_LZO=y +CONFIG_JFFS2_RTIME=y +CONFIG_JFFS2_RUBIN=y +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +# CONFIG_JFFS2_CMODE_FAVOURLZO is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +# CONFIG_SUNRPC_REGISTER_V4 is not set +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +CONFIG_SCHEDSTATS=y +CONFIG_TIMER_STATS=y +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +CONFIG_NOP_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_RING_BUFFER=y +CONFIG_TRACING=y + +# +# Tracers +# +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_FTRACE_STARTUP_TEST is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_XOR_BLOCKS=m +CONFIG_ASYNC_CORE=m +CONFIG_ASYNC_MEMCPY=m +CONFIG_ASYNC_XOR=m +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_GF128MUL=m +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_CRYPTD=m +# CONFIG_CRYPTO_AUTHENC is not set +CONFIG_CRYPTO_TEST=m + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_LRW=m +CONFIG_CRYPTO_PCBC=m +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +CONFIG_CRYPTO_HMAC=m +CONFIG_CRYPTO_XCBC=m + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=y +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_ARC4=y +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_CAMELLIA=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_FCRYPT=m +CONFIG_CRYPTO_KHAZAD=m +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_TWOFISH_COMMON=m + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=m +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_HW=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_CRC_CCITT=y +CONFIG_CRC16=m +CONFIG_CRC_T10DIF=y +CONFIG_CRC_ITU_T=y +CONFIG_CRC32=y +CONFIG_CRC7=y +CONFIG_LIBCRC32C=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 3754b79092a..64ad5c04b64 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -58,4 +58,8 @@ config MACH_OVERO config MACH_OMAP3_PANDORA bool "OMAP3 Pandora" - depends on ARCH_OMAP3 && ARCH_OMAP34XX \ No newline at end of file + depends on ARCH_OMAP3 && ARCH_OMAP34XX + +config MACH_OMAP_3430SDP + bool "OMAP 3430 SDP board" + depends on ARCH_OMAP3 && ARCH_OMAP34XX diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 29f6ca94c36..809416dc644 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -38,6 +38,8 @@ obj-$(CONFIG_MACH_OVERO) += board-overo.o \ mmc-twl4030.o obj-$(CONFIG_MACH_OMAP3_PANDORA) += board-omap3pandora.o \ mmc-twl4030.o +obj-$(CONFIG_MACH_OMAP_3430SDP) += board-3430sdp.o \ + mmc-twl4030.o # Platform specific device init code ifeq ($(CONFIG_USB_MUSB_SOC),y) diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c new file mode 100644 index 00000000000..2af38e56db3 --- /dev/null +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -0,0 +1,542 @@ +/* + * linux/arch/arm/mach-omap2/board-3430sdp.c + * + * Copyright (C) 2007 Texas Instruments + * + * Modified from mach-omap2/board-generic.c + * + * Initial code: Syed Mohammed Khasim + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "mmc-twl4030.h" + +#define CONFIG_DISABLE_HFCLK 1 + +#define SDP3430_ETHR_GPIO_IRQ_SDPV1 29 +#define SDP3430_ETHR_GPIO_IRQ_SDPV2 6 +#define SDP3430_SMC91X_CS 3 + +#define SDP3430_TS_GPIO_IRQ_SDPV1 3 +#define SDP3430_TS_GPIO_IRQ_SDPV2 2 + +#define ENABLE_VAUX3_DEDICATED 0x03 +#define ENABLE_VAUX3_DEV_GRP 0x20 + +#define TWL4030_MSECURE_GPIO 22 + +static struct resource sdp3430_smc91x_resources[] = { + [0] = { + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 0, + .end = 0, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, + }, +}; + +static struct platform_device sdp3430_smc91x_device = { + .name = "smc91x", + .id = -1, + .num_resources = ARRAY_SIZE(sdp3430_smc91x_resources), + .resource = sdp3430_smc91x_resources, +}; + +static int sdp3430_keymap[] = { + KEY(0, 0, KEY_LEFT), + KEY(0, 1, KEY_RIGHT), + KEY(0, 2, KEY_A), + KEY(0, 3, KEY_B), + KEY(0, 4, KEY_C), + KEY(1, 0, KEY_DOWN), + KEY(1, 1, KEY_UP), + KEY(1, 2, KEY_E), + KEY(1, 3, KEY_F), + KEY(1, 4, KEY_G), + KEY(2, 0, KEY_ENTER), + KEY(2, 1, KEY_I), + KEY(2, 2, KEY_J), + KEY(2, 3, KEY_K), + KEY(2, 4, KEY_3), + KEY(3, 0, KEY_M), + KEY(3, 1, KEY_N), + KEY(3, 2, KEY_O), + KEY(3, 3, KEY_P), + KEY(3, 4, KEY_Q), + KEY(4, 0, KEY_R), + KEY(4, 1, KEY_4), + KEY(4, 2, KEY_T), + KEY(4, 3, KEY_U), + KEY(4, 4, KEY_D), + KEY(5, 0, KEY_V), + KEY(5, 1, KEY_W), + KEY(5, 2, KEY_L), + KEY(5, 3, KEY_S), + KEY(5, 4, KEY_H), + 0 +}; + +static struct twl4030_keypad_data sdp3430_kp_data = { + .rows = 5, + .cols = 6, + .keymap = sdp3430_keymap, + .keymapsize = ARRAY_SIZE(sdp3430_keymap), + .rep = 1, +}; + +static int ts_gpio; /* Needed for ads7846_get_pendown_state */ + +/** + * @brief ads7846_dev_init : Requests & sets GPIO line for pen-irq + * + * @return - void. If request gpio fails then Flag KERN_ERR. + */ +static void ads7846_dev_init(void) +{ + if (gpio_request(ts_gpio, "ADS7846 pendown") < 0) { + printk(KERN_ERR "can't get ads746 pen down GPIO\n"); + return; + } + + gpio_direction_input(ts_gpio); + + omap_set_gpio_debounce(ts_gpio, 1); + omap_set_gpio_debounce_time(ts_gpio, 0xa); +} + +static int ads7846_get_pendown_state(void) +{ + return !gpio_get_value(ts_gpio); +} + +static struct ads7846_platform_data tsc2046_config __initdata = { + .get_pendown_state = ads7846_get_pendown_state, + .keep_vref_on = 1, +}; + + +static struct omap2_mcspi_device_config tsc2046_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, /* 0: slave, 1: master */ +}; + +static struct spi_board_info sdp3430_spi_board_info[] __initdata = { + [0] = { + /* + * TSC2046 operates at a max freqency of 2MHz, so + * operate slightly below at 1.5MHz + */ + .modalias = "ads7846", + .bus_num = 1, + .chip_select = 0, + .max_speed_hz = 1500000, + .controller_data = &tsc2046_mcspi_config, + .irq = 0, + .platform_data = &tsc2046_config, + }, +}; + +static struct platform_device sdp3430_lcd_device = { + .name = "sdp2430_lcd", + .id = -1, +}; + +static struct regulator_consumer_supply sdp3430_vdac_supply = { + .supply = "vdac", + .dev = &sdp3430_lcd_device.dev, +}; + +static struct regulator_consumer_supply sdp3430_vdvi_supply = { + .supply = "vdvi", + .dev = &sdp3430_lcd_device.dev, +}; + +static struct platform_device *sdp3430_devices[] __initdata = { + &sdp3430_smc91x_device, + &sdp3430_lcd_device, +}; + +static inline void __init sdp3430_init_smc91x(void) +{ + int eth_cs; + unsigned long cs_mem_base; + int eth_gpio = 0; + + eth_cs = SDP3430_SMC91X_CS; + + if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) { + printk(KERN_ERR "Failed to request GPMC mem for smc91x\n"); + return; + } + + sdp3430_smc91x_resources[0].start = cs_mem_base + 0x300; + sdp3430_smc91x_resources[0].end = cs_mem_base + 0x30f; + udelay(100); + + if (omap_rev() > OMAP3430_REV_ES1_0) + eth_gpio = SDP3430_ETHR_GPIO_IRQ_SDPV2; + else + eth_gpio = SDP3430_ETHR_GPIO_IRQ_SDPV1; + + sdp3430_smc91x_resources[1].start = gpio_to_irq(eth_gpio); + + if (gpio_request(eth_gpio, "SMC91x irq") < 0) { + printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n", + eth_gpio); + return; + } + gpio_direction_input(eth_gpio); +} + +static void __init omap_3430sdp_init_irq(void) +{ + omap2_init_common_hw(); + omap_init_irq(); + omap_gpio_init(); + sdp3430_init_smc91x(); +} + +static struct omap_uart_config sdp3430_uart_config __initdata = { + .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), +}; + +static struct omap_lcd_config sdp3430_lcd_config __initdata = { + .ctrl_name = "internal", +}; + +static struct omap_board_config_kernel sdp3430_config[] __initdata = { + { OMAP_TAG_UART, &sdp3430_uart_config }, + { OMAP_TAG_LCD, &sdp3430_lcd_config }, +}; + +static int sdp3430_batt_table[] = { +/* 0 C*/ +30800, 29500, 28300, 27100, +26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700, 17900, +17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100, 12600, 12100, +11600, 11200, 10800, 10400, 10000, 9630, 9280, 8950, 8620, 8310, +8020, 7730, 7460, 7200, 6950, 6710, 6470, 6250, 6040, 5830, +5640, 5450, 5260, 5090, 4920, 4760, 4600, 4450, 4310, 4170, +4040, 3910, 3790, 3670, 3550 +}; + +static struct twl4030_bci_platform_data sdp3430_bci_data = { + .battery_tmp_tbl = sdp3430_batt_table, + .tblsize = ARRAY_SIZE(sdp3430_batt_table), +}; + +static struct twl4030_hsmmc_info mmc[] = { + { + .mmc = 1, + /* 8 bits (default) requires S6.3 == ON, + * so the SIM card isn't used; else 4 bits. + */ + .wires = 8, + .gpio_wp = 4, + }, + { + .mmc = 2, + .wires = 8, + .gpio_wp = 7, + }, + {} /* Terminator */ +}; + +static struct regulator_consumer_supply sdp3430_vmmc1_supply = { + .supply = "vmmc", +}; + +static struct regulator_consumer_supply sdp3430_vsim_supply = { + .supply = "vmmc_aux", +}; + +static struct regulator_consumer_supply sdp3430_vmmc2_supply = { + .supply = "vmmc", +}; + +static int sdp3430_twl_gpio_setup(struct device *dev, + unsigned gpio, unsigned ngpio) +{ + /* gpio + 0 is "mmc0_cd" (input/IRQ), + * gpio + 1 is "mmc1_cd" (input/IRQ) + */ + mmc[0].gpio_cd = gpio + 0; + mmc[1].gpio_cd = gpio + 1; + twl4030_mmc_init(mmc); + + /* link regulators to MMC adapters ... we "know" the + * regulators will be set up only *after* we return. + */ + sdp3430_vmmc1_supply.dev = mmc[0].dev; + sdp3430_vsim_supply.dev = mmc[0].dev; + sdp3430_vmmc2_supply.dev = mmc[1].dev; + + /* gpio + 7 is "sub_lcd_en_bkl" (output/PWM1) */ + gpio_request(gpio + 7, "sub_lcd_en_bkl"); + gpio_direction_output(gpio + 7, 0); + + /* gpio + 15 is "sub_lcd_nRST" (output) */ + gpio_request(gpio + 15, "sub_lcd_nRST"); + gpio_direction_output(gpio + 15, 0); + + return 0; +} + +static struct twl4030_gpio_platform_data sdp3430_gpio_data = { + .gpio_base = OMAP_MAX_GPIO_LINES, + .irq_base = TWL4030_GPIO_IRQ_BASE, + .irq_end = TWL4030_GPIO_IRQ_END, + .pulldowns = BIT(2) | BIT(6) | BIT(8) | BIT(13) + | BIT(16) | BIT(17), + .setup = sdp3430_twl_gpio_setup, +}; + +static struct twl4030_usb_data sdp3430_usb_data = { + .usb_mode = T2_USB_MODE_ULPI, +}; + +static struct twl4030_madc_platform_data sdp3430_madc_data = { + .irq_line = 1, +}; + +/* + * Apply all the fixed voltages since most versions of U-Boot + * don't bother with that initialization. + */ + +/* VAUX1 for mainboard (irda and sub-lcd) */ +static struct regulator_init_data sdp3430_vaux1 = { + .constraints = { + .min_uV = 2800000, + .max_uV = 2800000, + .apply_uV = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, +}; + +/* VAUX2 for camera module */ +static struct regulator_init_data sdp3430_vaux2 = { + .constraints = { + .min_uV = 2800000, + .max_uV = 2800000, + .apply_uV = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, +}; + +/* VAUX3 for LCD board */ +static struct regulator_init_data sdp3430_vaux3 = { + .constraints = { + .min_uV = 2800000, + .max_uV = 2800000, + .apply_uV = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, +}; + +/* VAUX4 for OMAP VDD_CSI2 (camera) */ +static struct regulator_init_data sdp3430_vaux4 = { + .constraints = { + .min_uV = 1800000, + .max_uV = 1800000, + .apply_uV = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, +}; + +/* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */ +static struct regulator_init_data sdp3430_vmmc1 = { + .constraints = { + .min_uV = 1850000, + .max_uV = 3150000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE + | REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &sdp3430_vmmc1_supply, +}; + +/* VMMC2 for MMC2 card */ +static struct regulator_init_data sdp3430_vmmc2 = { + .constraints = { + .min_uV = 1850000, + .max_uV = 1850000, + .apply_uV = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &sdp3430_vmmc2_supply, +}; + +/* VSIM for OMAP VDD_MMC1A (i/o for DAT4..DAT7) */ +static struct regulator_init_data sdp3430_vsim = { + .constraints = { + .min_uV = 1800000, + .max_uV = 3000000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE + | REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &sdp3430_vsim_supply, +}; + +/* VDAC for DSS driving S-Video */ +static struct regulator_init_data sdp3430_vdac = { + .constraints = { + .min_uV = 1800000, + .max_uV = 1800000, + .apply_uV = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &sdp3430_vdac_supply, +}; + +/* VPLL2 for digital video outputs */ +static struct regulator_init_data sdp3430_vpll2 = { + .constraints = { + .name = "VDVI", + .min_uV = 1800000, + .max_uV = 1800000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &sdp3430_vdvi_supply, +}; + +static struct twl4030_platform_data sdp3430_twldata = { + .irq_base = TWL4030_IRQ_BASE, + .irq_end = TWL4030_IRQ_END, + + /* platform_data for children goes here */ + .bci = &sdp3430_bci_data, + .gpio = &sdp3430_gpio_data, + .madc = &sdp3430_madc_data, + .keypad = &sdp3430_kp_data, + .usb = &sdp3430_usb_data, + + .vaux1 = &sdp3430_vaux1, + .vaux2 = &sdp3430_vaux2, + .vaux3 = &sdp3430_vaux3, + .vaux4 = &sdp3430_vaux4, + .vmmc1 = &sdp3430_vmmc1, + .vmmc2 = &sdp3430_vmmc2, + .vsim = &sdp3430_vsim, + .vdac = &sdp3430_vdac, + .vpll2 = &sdp3430_vpll2, +}; + +static struct i2c_board_info __initdata sdp3430_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("twl4030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &sdp3430_twldata, + }, +}; + +static int __init omap3430_i2c_init(void) +{ + /* i2c1 for PMIC only */ + omap_register_i2c_bus(1, 2600, sdp3430_i2c_boardinfo, + ARRAY_SIZE(sdp3430_i2c_boardinfo)); + /* i2c2 on camera connector (for sensor control) and optional isp1301 */ + omap_register_i2c_bus(2, 400, NULL, 0); + /* i2c3 on display connector (for DVI, tfp410) */ + omap_register_i2c_bus(3, 400, NULL, 0); + return 0; +} + +static void __init omap_3430sdp_init(void) +{ + omap3430_i2c_init(); + platform_add_devices(sdp3430_devices, ARRAY_SIZE(sdp3430_devices)); + omap_board_config = sdp3430_config; + omap_board_config_size = ARRAY_SIZE(sdp3430_config); + if (omap_rev() > OMAP3430_REV_ES1_0) + ts_gpio = SDP3430_TS_GPIO_IRQ_SDPV2; + else + ts_gpio = SDP3430_TS_GPIO_IRQ_SDPV1; + sdp3430_spi_board_info[0].irq = gpio_to_irq(ts_gpio); + spi_register_board_info(sdp3430_spi_board_info, + ARRAY_SIZE(sdp3430_spi_board_info)); + ads7846_dev_init(); + omap_serial_init(); + usb_musb_init(); +} + +static void __init omap_3430sdp_map_io(void) +{ + omap2_set_globals_343x(); + omap2_map_common_io(); +} + +MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board") + /* Maintainer: Syed Khasim - Texas Instruments Inc */ + .phys_io = 0x48000000, + .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = omap_3430sdp_map_io, + .init_irq = omap_3430sdp_init_irq, + .init_machine = omap_3430sdp_init, + .timer = &omap_timer, +MACHINE_END -- GitLab From ffe7f95bb1a4d1e9ca5d252445dc38476e1a208e Mon Sep 17 00:00:00 2001 From: Lauri Leukkunen Date: Mon, 23 Mar 2009 18:38:17 -0700 Subject: [PATCH 4019/4982] ARM OMAP3: Initial support for Nokia RX-51, v3 Adds board files and related headers for Nokia RX-51 Internet Tablet. This patch has been updated with some clean-up patches posted earlier to linux-omap list. Signed-off-by: Lauri Leukkunen Signed-off-by: Tony Lindgren --- arch/arm/configs/rx51_defconfig | 1821 ++++++++++++++++++ arch/arm/mach-omap2/Kconfig | 4 + arch/arm/mach-omap2/Makefile | 2 + arch/arm/mach-omap2/board-rx51-peripherals.c | 419 ++++ arch/arm/mach-omap2/board-rx51.c | 96 + 5 files changed, 2342 insertions(+) create mode 100644 arch/arm/configs/rx51_defconfig create mode 100644 arch/arm/mach-omap2/board-rx51-peripherals.c create mode 100644 arch/arm/mach-omap2/board-rx51.c diff --git a/arch/arm/configs/rx51_defconfig b/arch/arm/configs/rx51_defconfig new file mode 100644 index 00000000000..593102da8cd --- /dev/null +++ b/arch/arm/configs/rx51_defconfig @@ -0,0 +1,1821 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.29-rc8 +# Fri Mar 13 15:28:56 2009 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set +# CONFIG_CGROUPS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +CONFIG_KPROBES=y +CONFIG_KRETPROBES=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +CONFIG_MODULE_FORCE_LOAD=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_FREEZER=y + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +CONFIG_ARCH_OMAP=y +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_W90X900 is not set + +# +# TI OMAP Implementations +# +CONFIG_ARCH_OMAP_OTG=y +# CONFIG_ARCH_OMAP1 is not set +# CONFIG_ARCH_OMAP2 is not set +CONFIG_ARCH_OMAP3=y + +# +# OMAP Feature Selections +# +# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set +# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set +CONFIG_OMAP_RESET_CLOCKS=y +CONFIG_OMAP_MUX=y +CONFIG_OMAP_MUX_DEBUG=y +CONFIG_OMAP_MUX_WARNINGS=y +CONFIG_OMAP_MCBSP=y +# CONFIG_OMAP_MPU_TIMER is not set +CONFIG_OMAP_32K_TIMER=y +CONFIG_OMAP_32K_TIMER_HZ=128 +CONFIG_OMAP_DM_TIMER=y +# CONFIG_OMAP_LL_DEBUG_UART1 is not set +# CONFIG_OMAP_LL_DEBUG_UART2 is not set +CONFIG_OMAP_LL_DEBUG_UART3=y +CONFIG_OMAP_SERIAL_WAKE=y +CONFIG_ARCH_OMAP34XX=y +CONFIG_ARCH_OMAP3430=y + +# +# OMAP Board Type +# +# CONFIG_MACH_OMAP3_BEAGLE is not set +# CONFIG_MACH_OMAP_LDP is not set +# CONFIG_MACH_OVERO is not set +# CONFIG_MACH_OMAP3_PANDORA is not set +# CONFIG_MACH_OMAP_3430SDP is not set +CONFIG_MACH_NOKIA_RX51=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_V7=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_IFAR=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_HAS_TLS_REG=y +# CONFIG_OUTER_CACHE is not set + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +# CONFIG_PREEMPT is not set +CONFIG_HZ=128 +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="init=/sbin/preinit ubi.mtd=4 root=ubi0:rootfs rootfstype=ubifs rw console=ttyMTD5" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_FREQ is not set +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_NEON=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Power management options +# +CONFIG_PM=y +CONFIG_PM_DEBUG=y +# CONFIG_PM_VERBOSE is not set +CONFIG_CAN_PM_TRACE=y +CONFIG_PM_SLEEP=y +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +# CONFIG_APM_EMULATION is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_COMPAT_NET_DEV_OPS=y +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETLABEL is not set +# CONFIG_NETWORK_SECMARK is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set +# CONFIG_NF_CONNTRACK is not set +CONFIG_NETFILTER_XTABLES=m +# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set +# CONFIG_NETFILTER_XT_TARGET_MARK is not set +# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set +# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set +# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +# CONFIG_NETFILTER_XT_MATCH_DSCP is not set +# CONFIG_NETFILTER_XT_MATCH_ESP is not set +# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set +# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set +# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_MAC is not set +# CONFIG_NETFILTER_XT_MATCH_MARK is not set +# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set +# CONFIG_NETFILTER_XT_MATCH_POLICY is not set +# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set +# CONFIG_NETFILTER_XT_MATCH_REALM is not set +# CONFIG_NETFILTER_XT_MATCH_RECENT is not set +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set +# CONFIG_NETFILTER_XT_MATCH_STRING is not set +# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set +# CONFIG_NETFILTER_XT_MATCH_TIME is not set +# CONFIG_NETFILTER_XT_MATCH_U32 is not set +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_NF_DEFRAG_IPV4 is not set +# CONFIG_IP_NF_QUEUE is not set +CONFIG_IP_NF_IPTABLES=m +# CONFIG_IP_NF_MATCH_ADDRTYPE is not set +# CONFIG_IP_NF_MATCH_AH is not set +# CONFIG_IP_NF_MATCH_ECN is not set +# CONFIG_IP_NF_MATCH_TTL is not set +CONFIG_IP_NF_FILTER=m +# CONFIG_IP_NF_TARGET_REJECT is not set +# CONFIG_IP_NF_TARGET_LOG is not set +# CONFIG_IP_NF_TARGET_ULOG is not set +# CONFIG_IP_NF_MANGLE is not set +# CONFIG_IP_NF_RAW is not set +# CONFIG_IP_NF_SECURITY is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_NET_TCPPROBE is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +# CONFIG_BT_HCIBTUSB is not set +# CONFIG_BT_HCIBTSDIO is not set +# CONFIG_BT_HCIUART is not set +# CONFIG_BT_HCIBCM203X is not set +# CONFIG_BT_HCIBPA10X is not set +# CONFIG_BT_HCIBFUSB is not set +# CONFIG_BT_HCIVHCI is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y +CONFIG_CFG80211=y +# CONFIG_CFG80211_REG_DEBUG is not set +CONFIG_NL80211=y +CONFIG_WIRELESS_OLD_REGULATORY=y +CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +# CONFIG_LIB80211 is not set +CONFIG_MAC80211=m + +# +# Rate control algorithm selection +# +CONFIG_MAC80211_RC_PID=y +# CONFIG_MAC80211_RC_MINSTREL is not set +CONFIG_MAC80211_RC_DEFAULT_PID=y +# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set +CONFIG_MAC80211_RC_DEFAULT="pid" +# CONFIG_MAC80211_MESH is not set +# CONFIG_MAC80211_LEDS is not set +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +CONFIG_MTD_OOPS=y + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_OMAP_NOR is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +CONFIG_MTD_ONENAND=y +# CONFIG_MTD_ONENAND_VERIFY_WRITE is not set +# CONFIG_MTD_ONENAND_GENERIC is not set +CONFIG_MTD_ONENAND_OMAP2=y +# CONFIG_MTD_ONENAND_OTP is not set +# CONFIG_MTD_ONENAND_2X_PROGRAM is not set +# CONFIG_MTD_ONENAND_SIM is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_RESERVE=1 +# CONFIG_MTD_UBI_GLUEBI is not set + +# +# UBI debugging options +# +# CONFIG_MTD_UBI_DEBUG is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_MISC_DEVICES=y +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_93CX6 is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=m +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_LIBFC is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +CONFIG_TUN=m +# CONFIG_VETH is not set +# CONFIG_PHYLIB is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +# CONFIG_AX88796 is not set +CONFIG_SMC91X=m +# CONFIG_DM9000 is not set +# CONFIG_ENC28J60 is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +CONFIG_WLAN_80211=y +# CONFIG_LIBERTAS is not set +# CONFIG_LIBERTAS_THINFIRM is not set +# CONFIG_USB_ZD1201 is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_RTL8187 is not set +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_P54_COMMON is not set +# CONFIG_IWLWIFI_LEDS is not set +# CONFIG_HOSTAP is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +# CONFIG_ZD1211RW is not set +# CONFIG_RT2X00 is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_ATI_REMOTE is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=m +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_OMAP=y +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_GPIO is not set +CONFIG_SPI_OMAP24XX=y + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +CONFIG_GPIO_TWL4030=y + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7473 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_OMAP_WATCHDOG=m + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_TPS65010 is not set +CONFIG_TWL4030_CORE=y +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L2_COMMON=m +CONFIG_VIDEO_ALLOW_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +# CONFIG_DVB_CORE is not set +CONFIG_VIDEO_MEDIA=m + +# +# Multimedia drivers +# +# CONFIG_MEDIA_ATTACH is not set +CONFIG_MEDIA_TUNER=m +# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set +CONFIG_MEDIA_TUNER_SIMPLE=m +CONFIG_MEDIA_TUNER_TDA8290=m +CONFIG_MEDIA_TUNER_TDA9887=m +CONFIG_MEDIA_TUNER_TEA5761=m +CONFIG_MEDIA_TUNER_TEA5767=m +CONFIG_MEDIA_TUNER_MT20XX=m +CONFIG_MEDIA_TUNER_XC2028=m +CONFIG_MEDIA_TUNER_XC5000=m +CONFIG_VIDEO_V4L2=m +CONFIG_VIDEO_V4L1=m +CONFIG_VIDEO_CAPTURE_DRIVERS=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +CONFIG_VIDEO_HELPER_CHIPS_AUTO=y +# CONFIG_VIDEO_VIVI is not set +# CONFIG_VIDEO_CPIA is not set +# CONFIG_VIDEO_CPIA2 is not set +# CONFIG_VIDEO_SAA5246A is not set +# CONFIG_VIDEO_SAA5249 is not set +# CONFIG_SOC_CAMERA is not set +CONFIG_V4L_USB_DRIVERS=y +# CONFIG_USB_VIDEO_CLASS is not set +# CONFIG_USB_GSPCA is not set +# CONFIG_VIDEO_PVRUSB2 is not set +# CONFIG_VIDEO_EM28XX is not set +# CONFIG_VIDEO_USBVISION is not set +# CONFIG_USB_VICAM is not set +# CONFIG_USB_IBMCAM is not set +# CONFIG_USB_KONICAWC is not set +# CONFIG_USB_QUICKCAM_MESSENGER is not set +# CONFIG_USB_ET61X251 is not set +# CONFIG_VIDEO_OVCAMCHIP is not set +# CONFIG_USB_OV511 is not set +# CONFIG_USB_SE401 is not set +# CONFIG_USB_SN9C102 is not set +# CONFIG_USB_STV680 is not set +# CONFIG_USB_ZC0301 is not set +# CONFIG_USB_PWC is not set +# CONFIG_USB_ZR364XX is not set +# CONFIG_USB_STKWEBCAM is not set +# CONFIG_USB_S2255 is not set +CONFIG_RADIO_ADAPTERS=y +# CONFIG_USB_DSBR is not set +# CONFIG_USB_SI470X is not set +# CONFIG_USB_MR800 is not set +# CONFIG_RADIO_TEA5764 is not set +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +CONFIG_DISPLAY_SUPPORT=y + +# +# Display hardware drivers +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_SOUND=y +# CONFIG_SOUND_OSS_CORE is not set +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_HRTIMER is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +CONFIG_SND_ARM=y +CONFIG_SND_SPI=y +# CONFIG_SND_USB is not set +CONFIG_SND_SOC=y +CONFIG_SND_OMAP_SOC=y +CONFIG_SND_SOC_I2C_AND_SPI=y +# CONFIG_SND_SOC_ALL_CODECS is not set +# CONFIG_SOUND_PRIME is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=m +# CONFIG_HID_DEBUG is not set +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=m +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set + +# +# Special HID drivers +# +CONFIG_HID_COMPAT=y +CONFIG_HID_A4TECH=m +CONFIG_HID_APPLE=m +CONFIG_HID_BELKIN=m +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +CONFIG_HID_CYPRESS=m +CONFIG_HID_EZKEY=m +CONFIG_HID_GYRATION=m +CONFIG_HID_LOGITECH=m +# CONFIG_LOGITECH_FF is not set +# CONFIG_LOGIRUMBLEPAD2_FF is not set +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MONTEREY=m +# CONFIG_HID_NTRIG is not set +CONFIG_HID_PANTHERLORD=m +# CONFIG_PANTHERLORD_FF is not set +CONFIG_HID_PETALYNX=m +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SONY=m +CONFIG_HID_SUNPLUS=m +# CONFIG_GREENASIA_FF is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_THRUSTMASTER_FF is not set +# CONFIG_ZEROPLUS_FF is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +CONFIG_USB_DEBUG=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_SUSPEND=y +CONFIG_USB_OTG=y +CONFIG_USB_OTG_WHITELIST=y +CONFIG_USB_OTG_BLACKLIST_HUB=y +CONFIG_USB_MON=y +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_SOC=y + +# +# OMAP 343x high speed USB support +# +# CONFIG_USB_MUSB_HOST is not set +# CONFIG_USB_MUSB_PERIPHERAL is not set +CONFIG_USB_MUSB_OTG=y +CONFIG_USB_GADGET_MUSB_HDRC=y +CONFIG_USB_MUSB_HDRC_HCD=y +# CONFIG_MUSB_PIO_ONLY is not set +CONFIG_USB_INVENTRA_DMA=y +# CONFIG_USB_TI_CPPI_DMA is not set +# CONFIG_USB_MUSB_DEBUG is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; +# + +# +# see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +CONFIG_USB_LIBUSUAL=y + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +CONFIG_USB_TEST=m +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set +CONFIG_USB_GADGET=m +CONFIG_USB_GADGET_DEBUG=y +CONFIG_USB_GADGET_DEBUG_FILES=y +CONFIG_USB_GADGET_DEBUG_FS=y +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_PXA27X is not set +# CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_IMX is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_FSL_QE is not set +# CONFIG_USB_GADGET_CI13XXX is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +CONFIG_USB_ZERO=m +# CONFIG_USB_ZERO_HNPTEST is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_GADGETFS is not set +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set + +# +# OTG and related infrastructure +# +CONFIG_USB_OTG_UTILS=y +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_ISP1301_OMAP is not set +CONFIG_TWL4030_USB=y +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=m +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_OMAP is not set +CONFIG_MMC_OMAP_HS=m +# CONFIG_MMC_SPI is not set +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=m + +# +# LED drivers +# +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_PCA955X is not set + +# +# LED Triggers +# +# CONFIG_LEDS_TRIGGERS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +CONFIG_RTC_DRV_TWL4030=m +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_DMADEVICES is not set +# CONFIG_REGULATOR is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set + +# +# File systems +# +CONFIG_EXT2_FS=m +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=m +# CONFIG_EXT3_FS_XATTR is not set +# CONFIG_EXT4_FS is not set +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QUOTA_NETLINK_INTERFACE is not set +CONFIG_PRINT_QUOTA_WARNING=y +CONFIG_QUOTA_TREE=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +CONFIG_FUSE_FS=m + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS2_FS is not set +CONFIG_UBIFS_FS=y +# CONFIG_UBIFS_FS_XATTR is not set +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_UBIFS_FS_DEBUG is not set +CONFIG_CRAMFS=y +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +# CONFIG_SUNRPC_REGISTER_V4 is not set +CONFIG_RPCSEC_GSS_KRB5=m +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +CONFIG_PRINTK_TIME=y +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +CONFIG_TIMER_STATS=y +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_LOCK_ALLOC=y +CONFIG_PROVE_LOCKING=y +CONFIG_LOCKDEP=y +CONFIG_LOCK_STAT=y +# CONFIG_DEBUG_LOCKDEP is not set +CONFIG_TRACE_IRQFLAGS=y +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_KPROBES_SANITY_TEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_LKDTM is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +CONFIG_HAVE_FUNCTION_TRACER=y + +# +# Tracers +# +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +CONFIG_SECURITY=y +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_NETWORK is not set +# CONFIG_SECURITY_PATH is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_SECURITY_ROOTPLUG is not set +CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0 +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +CONFIG_CRYPTO_PCBC=m +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_LZO=y + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_HW=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +CONFIG_CRC7=m +CONFIG_LIBCRC32C=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 64ad5c04b64..64ab386a65c 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -63,3 +63,7 @@ config MACH_OMAP3_PANDORA config MACH_OMAP_3430SDP bool "OMAP 3430 SDP board" depends on ARCH_OMAP3 && ARCH_OMAP34XX + +config MACH_NOKIA_RX51 + bool "Nokia RX-51 board" + depends on ARCH_OMAP3 && ARCH_OMAP34XX diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 809416dc644..e08e482b89f 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -41,6 +41,8 @@ obj-$(CONFIG_MACH_OMAP3_PANDORA) += board-omap3pandora.o \ obj-$(CONFIG_MACH_OMAP_3430SDP) += board-3430sdp.o \ mmc-twl4030.o +obj-$(CONFIG_MACH_NOKIA_RX51) += board-rx51.o \ + board-rx51-peripherals.o \ # Platform specific device init code ifeq ($(CONFIG_USB_MUSB_SOC),y) obj-y += usb-musb.o diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c new file mode 100644 index 00000000000..a7381729645 --- /dev/null +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -0,0 +1,419 @@ +/* + * linux/arch/arm/mach-omap2/board-rx51-flash.c + * + * Copyright (C) 2008-2009 Nokia + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "mmc-twl4030.h" + + +#define SMC91X_CS 1 +#define SMC91X_GPIO_IRQ 54 +#define SMC91X_GPIO_RESET 164 +#define SMC91X_GPIO_PWRDWN 86 + +static struct resource rx51_smc91x_resources[] = { + [0] = { + .flags = IORESOURCE_MEM, + }, + [1] = { + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, + }, +}; + +static struct platform_device rx51_smc91x_device = { + .name = "smc91x", + .id = -1, + .num_resources = ARRAY_SIZE(rx51_smc91x_resources), + .resource = rx51_smc91x_resources, +}; + +static int rx51_keymap[] = { + KEY(0, 0, KEY_Q), + KEY(0, 1, KEY_W), + KEY(0, 2, KEY_E), + KEY(0, 3, KEY_R), + KEY(0, 4, KEY_T), + KEY(0, 5, KEY_Y), + KEY(0, 6, KEY_U), + KEY(0, 7, KEY_I), + KEY(1, 0, KEY_O), + KEY(1, 1, KEY_D), + KEY(1, 2, KEY_DOT), + KEY(1, 3, KEY_V), + KEY(1, 4, KEY_DOWN), + KEY(2, 0, KEY_P), + KEY(2, 1, KEY_F), + KEY(2, 2, KEY_UP), + KEY(2, 3, KEY_B), + KEY(2, 4, KEY_RIGHT), + KEY(3, 0, KEY_COMMA), + KEY(3, 1, KEY_G), + KEY(3, 2, KEY_ENTER), + KEY(3, 3, KEY_N), + KEY(4, 0, KEY_BACKSPACE), + KEY(4, 1, KEY_H), + KEY(4, 3, KEY_M), + KEY(4, 4, KEY_LEFTCTRL), + KEY(5, 1, KEY_J), + KEY(5, 2, KEY_Z), + KEY(5, 3, KEY_SPACE), + KEY(5, 4, KEY_LEFTSHIFT), + KEY(6, 0, KEY_A), + KEY(6, 1, KEY_K), + KEY(6, 2, KEY_X), + KEY(6, 3, KEY_SPACE), + KEY(6, 4, KEY_FN), + KEY(7, 0, KEY_S), + KEY(7, 1, KEY_L), + KEY(7, 2, KEY_C), + KEY(7, 3, KEY_LEFT), + KEY(0xff, 0, KEY_F6), + KEY(0xff, 1, KEY_F7), + KEY(0xff, 2, KEY_F8), + KEY(0xff, 4, KEY_F9), + KEY(0xff, 5, KEY_F10), +}; + +static struct twl4030_keypad_data rx51_kp_data = { + .rows = 8, + .cols = 8, + .keymap = rx51_keymap, + .keymapsize = ARRAY_SIZE(rx51_keymap), + .rep = 1, +}; + +static struct platform_device *rx51_peripherals_devices[] = { + &rx51_smc91x_device, +}; + +/* + * Timings are taken from smsc-lan91c96-ms.pdf + */ +static int smc91x_init_gpmc(int cs) +{ + struct gpmc_timings t; + const int t2_r = 45; /* t2 in Figure 12.10 */ + const int t2_w = 30; /* t2 in Figure 12.11 */ + const int t3 = 15; /* t3 in Figure 12.10 */ + const int t5_r = 0; /* t5 in Figure 12.10 */ + const int t6_r = 45; /* t6 in Figure 12.10 */ + const int t6_w = 0; /* t6 in Figure 12.11 */ + const int t7_w = 15; /* t7 in Figure 12.11 */ + const int t15 = 12; /* t15 in Figure 12.2 */ + const int t20 = 185; /* t20 in Figure 12.2 */ + + memset(&t, 0, sizeof(t)); + + t.cs_on = t15; + t.cs_rd_off = t3 + t2_r + t5_r; /* Figure 12.10 */ + t.cs_wr_off = t3 + t2_w + t6_w; /* Figure 12.11 */ + t.adv_on = t3; /* Figure 12.10 */ + t.adv_rd_off = t3 + t2_r; /* Figure 12.10 */ + t.adv_wr_off = t3 + t2_w; /* Figure 12.11 */ + t.oe_off = t3 + t2_r + t5_r; /* Figure 12.10 */ + t.oe_on = t.oe_off - t6_r; /* Figure 12.10 */ + t.we_off = t3 + t2_w + t6_w; /* Figure 12.11 */ + t.we_on = t.we_off - t7_w; /* Figure 12.11 */ + t.rd_cycle = t20; /* Figure 12.2 */ + t.wr_cycle = t20; /* Figure 12.4 */ + t.access = t3 + t2_r + t5_r; /* Figure 12.10 */ + t.wr_access = t3 + t2_w + t6_w; /* Figure 12.11 */ + + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, GPMC_CONFIG1_DEVICESIZE_16); + + return gpmc_cs_set_timings(cs, &t); +} + +static void __init rx51_init_smc91x(void) +{ + unsigned long cs_mem_base; + int ret; + + omap_cfg_reg(U8_34XX_GPIO54_DOWN); + omap_cfg_reg(G25_34XX_GPIO86_OUT); + omap_cfg_reg(H19_34XX_GPIO164_OUT); + + if (gpmc_cs_request(SMC91X_CS, SZ_16M, &cs_mem_base) < 0) { + printk(KERN_ERR "Failed to request GPMC mem for smc91x\n"); + return; + } + + rx51_smc91x_resources[0].start = cs_mem_base + 0x300; + rx51_smc91x_resources[0].end = cs_mem_base + 0x30f; + + smc91x_init_gpmc(SMC91X_CS); + + if (gpio_request(SMC91X_GPIO_IRQ, "SMC91X irq") < 0) + goto free1; + + gpio_direction_input(SMC91X_GPIO_IRQ); + rx51_smc91x_resources[1].start = gpio_to_irq(SMC91X_GPIO_IRQ); + + ret = gpio_request(SMC91X_GPIO_PWRDWN, "SMC91X powerdown"); + if (ret) + goto free2; + gpio_direction_output(SMC91X_GPIO_PWRDWN, 0); + + ret = gpio_request(SMC91X_GPIO_RESET, "SMC91X reset"); + if (ret) + goto free3; + gpio_direction_output(SMC91X_GPIO_RESET, 0); + gpio_set_value(SMC91X_GPIO_RESET, 1); + msleep(100); + gpio_set_value(SMC91X_GPIO_RESET, 0); + + return; + +free3: + gpio_free(SMC91X_GPIO_PWRDWN); +free2: + gpio_free(SMC91X_GPIO_IRQ); +free1: + gpmc_cs_free(SMC91X_CS); + + printk(KERN_ERR "Could not initialize smc91x\n"); +} + +static struct twl4030_madc_platform_data rx51_madc_data = { + .irq_line = 1, +}; + +static struct twl4030_hsmmc_info mmc[] = { + { + .name = "external", + .mmc = 1, + .wires = 4, + .cover_only = true, + .gpio_cd = 160, + .gpio_wp = -EINVAL, + }, + { + .name = "internal", + .mmc = 2, + .wires = 8, + .gpio_cd = -EINVAL, + .gpio_wp = -EINVAL, + }, + {} /* Terminator */ +}; + +static struct regulator_consumer_supply rx51_vmmc1_supply = { + .supply = "vmmc", +}; + +static struct regulator_consumer_supply rx51_vmmc2_supply = { + .supply = "vmmc", +}; + +static struct regulator_consumer_supply rx51_vsim_supply = { + .supply = "vmmc_aux", +}; + +static struct regulator_init_data rx51_vaux1 = { + .constraints = { + .name = "V28", + .min_uV = 2800000, + .max_uV = 2800000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, +}; + +static struct regulator_init_data rx51_vaux2 = { + .constraints = { + .name = "VCSI", + .min_uV = 1800000, + .max_uV = 1800000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, +}; + +/* VAUX3 - adds more power to VIO_18 rail */ +static struct regulator_init_data rx51_vaux3 = { + .constraints = { + .name = "VCAM_DIG_18", + .min_uV = 1800000, + .max_uV = 1800000, + .apply_uV = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, +}; + +static struct regulator_init_data rx51_vaux4 = { + .constraints = { + .name = "VCAM_ANA_28", + .min_uV = 2800000, + .max_uV = 2800000, + .apply_uV = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, +}; + +static struct regulator_init_data rx51_vmmc1 = { + .constraints = { + .min_uV = 1850000, + .max_uV = 3150000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE + | REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &rx51_vmmc1_supply, +}; + +static struct regulator_init_data rx51_vmmc2 = { + .constraints = { + .name = "VMMC2_30", + .min_uV = 1850000, + .max_uV = 3150000, + .apply_uV = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE + | REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &rx51_vmmc2_supply, +}; + +static struct regulator_init_data rx51_vsim = { + .constraints = { + .name = "VMMC2_IO_18", + .min_uV = 1800000, + .max_uV = 1800000, + .apply_uV = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &rx51_vsim_supply, +}; + +static struct regulator_init_data rx51_vdac = { + .constraints = { + .min_uV = 1800000, + .max_uV = 1800000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE + | REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, +}; + +static int rx51_twlgpio_setup(struct device *dev, unsigned gpio, unsigned n) +{ + /* FIXME this gpio setup is just a placeholder for now */ + gpio_request(gpio + 6, "backlight_pwm"); + gpio_direction_output(gpio + 6, 0); + gpio_request(gpio + 7, "speaker_en"); + gpio_direction_output(gpio + 7, 1); + + /* set up MMC adapters, linking their regulators to them */ + twl4030_mmc_init(mmc); + rx51_vmmc1_supply.dev = mmc[0].dev; + rx51_vmmc2_supply.dev = mmc[1].dev; + rx51_vsim_supply.dev = mmc[1].dev; + + return 0; +} + +static struct twl4030_gpio_platform_data rx51_gpio_data = { + .gpio_base = OMAP_MAX_GPIO_LINES, + .irq_base = TWL4030_GPIO_IRQ_BASE, + .irq_end = TWL4030_GPIO_IRQ_END, + .pulldowns = BIT(0) | BIT(1) | BIT(2) | BIT(3) + | BIT(4) | BIT(5) + | BIT(8) | BIT(9) | BIT(10) | BIT(11) + | BIT(12) | BIT(13) | BIT(14) | BIT(15) + | BIT(16) | BIT(17) , + .setup = rx51_twlgpio_setup, +}; + +static struct twl4030_platform_data rx51_twldata = { + .irq_base = TWL4030_IRQ_BASE, + .irq_end = TWL4030_IRQ_END, + + /* platform_data for children goes here */ + .gpio = &rx51_gpio_data, + .keypad = &rx51_kp_data, + .madc = &rx51_madc_data, + + .vaux1 = &rx51_vaux1, + .vaux2 = &rx51_vaux2, + .vaux3 = &rx51_vaux3, + .vaux4 = &rx51_vaux4, + .vmmc1 = &rx51_vmmc1, + .vmmc2 = &rx51_vmmc2, + .vsim = &rx51_vsim, + .vdac = &rx51_vdac, +}; + +static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_1[] = { + { + I2C_BOARD_INFO("twl5030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &rx51_twldata, + }, +}; + +static int __init rx51_i2c_init(void) +{ + omap_register_i2c_bus(1, 2600, rx51_peripherals_i2c_board_info_1, + ARRAY_SIZE(rx51_peripherals_i2c_board_info_1)); + omap_register_i2c_bus(2, 100, NULL, 0); + omap_register_i2c_bus(3, 400, NULL, 0); + return 0; +} + + +void __init rx51_peripherals_init(void) +{ + platform_add_devices(rx51_peripherals_devices, + ARRAY_SIZE(rx51_peripherals_devices)); + rx51_i2c_init(); + rx51_init_smc91x(); +} + diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c new file mode 100644 index 00000000000..6a3c5e53d99 --- /dev/null +++ b/arch/arm/mach-omap2/board-rx51.c @@ -0,0 +1,96 @@ +/* + * linux/arch/arm/mach-omap2/board-rx51.c + * + * Copyright (C) 2007, 2008 Nokia + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct omap_uart_config rx51_uart_config = { + .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), +}; + +static struct omap_lcd_config rx51_lcd_config = { + .ctrl_name = "internal", +}; + +static struct omap_fbmem_config rx51_fbmem0_config = { + .size = 752 * 1024, +}; + +static struct omap_fbmem_config rx51_fbmem1_config = { + .size = 752 * 1024, +}; + +static struct omap_fbmem_config rx51_fbmem2_config = { + .size = 752 * 1024, +}; + +static struct omap_board_config_kernel rx51_config[] = { + { OMAP_TAG_UART, &rx51_uart_config }, + { OMAP_TAG_FBMEM, &rx51_fbmem0_config }, + { OMAP_TAG_FBMEM, &rx51_fbmem1_config }, + { OMAP_TAG_FBMEM, &rx51_fbmem2_config }, + { OMAP_TAG_LCD, &rx51_lcd_config }, +}; + +static void __init rx51_init_irq(void) +{ + omap2_init_common_hw(); + omap_init_irq(); + omap_gpio_init(); +} + +extern void __init rx51_peripherals_init(void); + +static void __init rx51_init(void) +{ + omap_board_config = rx51_config; + omap_board_config_size = ARRAY_SIZE(rx51_config); + omap_serial_init(); + usb_musb_init(); + rx51_peripherals_init(); +} + +static void __init rx51_map_io(void) +{ + omap2_set_globals_343x(); + omap2_map_common_io(); +} + +MACHINE_START(NOKIA_RX51, "Nokia RX-51 board") + /* Maintainer: Lauri Leukkunen */ + .phys_io = 0x48000000, + .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = rx51_map_io, + .init_irq = rx51_init_irq, + .init_machine = rx51_init, + .timer = &omap_timer, +MACHINE_END -- GitLab From 5201b0a47b83aba66e1e348d18f3f9a7bc17d612 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Sat, 21 Mar 2009 13:50:58 +0800 Subject: [PATCH 4020/4982] avr32: remove duplicated #include Remove duplicated #include in arch/avr32/boards/hammerhead/flash.c. Signed-off-by: Huang Weiyi Acked-by: Alex Raimondi Signed-off-by: Haavard Skinnemoen --- arch/avr32/boards/hammerhead/flash.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/avr32/boards/hammerhead/flash.c b/arch/avr32/boards/hammerhead/flash.c index a98c6dd3a02..559bbcb03f9 100644 --- a/arch/avr32/boards/hammerhead/flash.c +++ b/arch/avr32/boards/hammerhead/flash.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include -- GitLab From f0b85051d0f0891378a83db22c0786f1d756fbff Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 25 Nov 2008 20:17:01 +0100 Subject: [PATCH 4021/4982] KVM: SVM: Clean up VINTR setting The current VINTR intercept setters don't look clean to me. To make the code easier to read and enable the possibilty to trap on a VINTR set, this uses a helper function to set the VINTR intercept. v2 uses two distinct functions for setting and clearing the bit Acked-by: Joerg Roedel Signed-off-by: Alexander Graf Signed-off-by: Avi Kivity --- arch/x86/kvm/svm.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index a9e769e4e25..33407d95761 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -718,6 +718,16 @@ static void svm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags) to_svm(vcpu)->vmcb->save.rflags = rflags; } +static void svm_set_vintr(struct vcpu_svm *svm) +{ + svm->vmcb->control.intercept |= 1ULL << INTERCEPT_VINTR; +} + +static void svm_clear_vintr(struct vcpu_svm *svm) +{ + svm->vmcb->control.intercept &= ~(1ULL << INTERCEPT_VINTR); +} + static struct vmcb_seg *svm_seg(struct kvm_vcpu *vcpu, int seg) { struct vmcb_save_area *save = &to_svm(vcpu)->vmcb->save; @@ -1380,7 +1390,7 @@ static int interrupt_window_interception(struct vcpu_svm *svm, { KVMTRACE_0D(PEND_INTR, &svm->vcpu, handler); - svm->vmcb->control.intercept &= ~(1ULL << INTERCEPT_VINTR); + svm_clear_vintr(svm); svm->vmcb->control.int_ctl &= ~V_IRQ_MASK; /* * If the user space waits to inject interrupts, exit as soon as @@ -1593,7 +1603,7 @@ static void svm_intr_assist(struct kvm_vcpu *vcpu) (vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) || (vmcb->control.event_inj & SVM_EVTINJ_VALID)) { /* unable to deliver irq, set pending irq */ - vmcb->control.intercept |= (1ULL << INTERCEPT_VINTR); + svm_set_vintr(svm); svm_inject_irq(svm, 0x0); goto out; } @@ -1652,9 +1662,9 @@ static void do_interrupt_requests(struct kvm_vcpu *vcpu, */ if (!svm->vcpu.arch.interrupt_window_open && (svm->vcpu.arch.irq_summary || kvm_run->request_interrupt_window)) - control->intercept |= 1ULL << INTERCEPT_VINTR; - else - control->intercept &= ~(1ULL << INTERCEPT_VINTR); + svm_set_vintr(svm); + else + svm_clear_vintr(svm); } static int svm_set_tss_addr(struct kvm *kvm, unsigned int addr) -- GitLab From 9962d032bbff0268f22068787831405f8468c8b4 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 25 Nov 2008 20:17:02 +0100 Subject: [PATCH 4022/4982] KVM: SVM: Move EFER and MSR constants to generic x86 code MSR_EFER_SVME_MASK, MSR_VM_CR and MSR_VM_HSAVE_PA are set in KVM specific headers. Linux does have nice header files to collect EFER bits and MSR IDs, so IMHO we should put them there. While at it, I also changed the naming scheme to match that of the other defines. (introduced in v6) Acked-by: Joerg Roedel Signed-off-by: Alexander Graf Signed-off-by: Avi Kivity --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/include/asm/msr-index.h | 7 +++++++ arch/x86/include/asm/svm.h | 4 ---- arch/x86/include/asm/virtext.h | 2 +- arch/x86/kvm/svm.c | 6 +++--- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 730843d1d2f..2998efe8927 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -22,6 +22,7 @@ #include #include #include +#include #define KVM_MAX_VCPUS 16 #define KVM_MEMORY_SLOTS 32 diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 358acc59ae0..46e9646e7a6 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -18,11 +18,13 @@ #define _EFER_LME 8 /* Long mode enable */ #define _EFER_LMA 10 /* Long mode active (read-only) */ #define _EFER_NX 11 /* No execute enable */ +#define _EFER_SVME 12 /* Enable virtualization */ #define EFER_SCE (1<<_EFER_SCE) #define EFER_LME (1<<_EFER_LME) #define EFER_LMA (1<<_EFER_LMA) #define EFER_NX (1<<_EFER_NX) +#define EFER_SVME (1<<_EFER_SVME) /* Intel MSRs. Some also available on other CPUs */ #define MSR_IA32_PERFCTR0 0x000000c1 @@ -360,4 +362,9 @@ #define MSR_IA32_VMX_PROCBASED_CTLS2 0x0000048b #define MSR_IA32_VMX_EPT_VPID_CAP 0x0000048c +/* AMD-V MSRs */ + +#define MSR_VM_CR 0xc0010114 +#define MSR_VM_HSAVE_PA 0xc0010117 + #endif /* _ASM_X86_MSR_INDEX_H */ diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h index 1b8afa78e86..82ada75f3eb 100644 --- a/arch/x86/include/asm/svm.h +++ b/arch/x86/include/asm/svm.h @@ -174,10 +174,6 @@ struct __attribute__ ((__packed__)) vmcb { #define SVM_CPUID_FEATURE_SHIFT 2 #define SVM_CPUID_FUNC 0x8000000a -#define MSR_EFER_SVME_MASK (1ULL << 12) -#define MSR_VM_CR 0xc0010114 -#define MSR_VM_HSAVE_PA 0xc0010117ULL - #define SVM_VM_CR_SVM_DISABLE 4 #define SVM_SELECTOR_S_SHIFT 4 diff --git a/arch/x86/include/asm/virtext.h b/arch/x86/include/asm/virtext.h index 59363627523..e0f9aa16358 100644 --- a/arch/x86/include/asm/virtext.h +++ b/arch/x86/include/asm/virtext.h @@ -118,7 +118,7 @@ static inline void cpu_svm_disable(void) wrmsrl(MSR_VM_HSAVE_PA, 0); rdmsrl(MSR_EFER, efer); - wrmsrl(MSR_EFER, efer & ~MSR_EFER_SVME_MASK); + wrmsrl(MSR_EFER, efer & ~EFER_SVME); } /** Makes sure SVM is disabled, if it is supported on the CPU diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 33407d95761..e4eb3fd91b9 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -198,7 +198,7 @@ static void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer) if (!npt_enabled && !(efer & EFER_LMA)) efer &= ~EFER_LME; - to_svm(vcpu)->vmcb->save.efer = efer | MSR_EFER_SVME_MASK; + to_svm(vcpu)->vmcb->save.efer = efer | EFER_SVME; vcpu->arch.shadow_efer = efer; } @@ -292,7 +292,7 @@ static void svm_hardware_enable(void *garbage) svm_data->tss_desc = (struct kvm_ldttss_desc *)(gdt + GDT_ENTRY_TSS); rdmsrl(MSR_EFER, efer); - wrmsrl(MSR_EFER, efer | MSR_EFER_SVME_MASK); + wrmsrl(MSR_EFER, efer | EFER_SVME); wrmsrl(MSR_VM_HSAVE_PA, page_to_pfn(svm_data->save_area) << PAGE_SHIFT); @@ -559,7 +559,7 @@ static void init_vmcb(struct vcpu_svm *svm) init_sys_seg(&save->ldtr, SEG_TYPE_LDT); init_sys_seg(&save->tr, SEG_TYPE_BUSY_TSS16); - save->efer = MSR_EFER_SVME_MASK; + save->efer = EFER_SVME; save->dr6 = 0xffff0ff0; save->dr7 = 0x400; save->rflags = 2; -- GitLab From c0725420cfdcf6dd9705b164a8c6cba86684080d Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 25 Nov 2008 20:17:03 +0100 Subject: [PATCH 4023/4982] KVM: SVM: Add helper functions for nested SVM These are helpers for the nested SVM implementation. - nsvm_printk implements a debug printk variant - nested_svm_do calls a handler that can accesses gpa-based memory v3 makes use of the new permission checker v6 changes: - streamline nsvm_debug() - remove printk(KERN_ERR) - SVME check before CPL check - give GP error code - use new EFER constant Acked-by: Joerg Roedel Signed-off-by: Alexander Graf Signed-off-by: Avi Kivity --- arch/x86/kvm/svm.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index e4eb3fd91b9..87debdcd1b9 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -50,6 +50,15 @@ MODULE_LICENSE("GPL"); #define DEBUGCTL_RESERVED_BITS (~(0x3fULL)) +/* Turn on to get debugging output*/ +/* #define NESTED_DEBUG */ + +#ifdef NESTED_DEBUG +#define nsvm_printk(fmt, args...) printk(KERN_INFO fmt, ## args) +#else +#define nsvm_printk(fmt, args...) do {} while(0) +#endif + /* enable NPT for AMD64 and X86 with PAE */ #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE) static bool npt_enabled = true; @@ -1149,6 +1158,82 @@ static int vmmcall_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) return 1; } +static int nested_svm_check_permissions(struct vcpu_svm *svm) +{ + if (!(svm->vcpu.arch.shadow_efer & EFER_SVME) + || !is_paging(&svm->vcpu)) { + kvm_queue_exception(&svm->vcpu, UD_VECTOR); + return 1; + } + + if (svm->vmcb->save.cpl) { + kvm_inject_gp(&svm->vcpu, 0); + return 1; + } + + return 0; +} + +static struct page *nested_svm_get_page(struct vcpu_svm *svm, u64 gpa) +{ + struct page *page; + + down_read(¤t->mm->mmap_sem); + page = gfn_to_page(svm->vcpu.kvm, gpa >> PAGE_SHIFT); + up_read(¤t->mm->mmap_sem); + + if (is_error_page(page)) { + printk(KERN_INFO "%s: could not find page at 0x%llx\n", + __func__, gpa); + kvm_release_page_clean(page); + kvm_inject_gp(&svm->vcpu, 0); + return NULL; + } + return page; +} + +static int nested_svm_do(struct vcpu_svm *svm, + u64 arg1_gpa, u64 arg2_gpa, void *opaque, + int (*handler)(struct vcpu_svm *svm, + void *arg1, + void *arg2, + void *opaque)) +{ + struct page *arg1_page; + struct page *arg2_page = NULL; + void *arg1; + void *arg2 = NULL; + int retval; + + arg1_page = nested_svm_get_page(svm, arg1_gpa); + if(arg1_page == NULL) + return 1; + + if (arg2_gpa) { + arg2_page = nested_svm_get_page(svm, arg2_gpa); + if(arg2_page == NULL) { + kvm_release_page_clean(arg1_page); + return 1; + } + } + + arg1 = kmap_atomic(arg1_page, KM_USER0); + if (arg2_gpa) + arg2 = kmap_atomic(arg2_page, KM_USER1); + + retval = handler(svm, arg1, arg2, opaque); + + kunmap_atomic(arg1, KM_USER0); + if (arg2_gpa) + kunmap_atomic(arg2, KM_USER1); + + kvm_release_page_dirty(arg1_page); + if (arg2_gpa) + kvm_release_page_dirty(arg2_page); + + return retval; +} + static int invalid_op_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) { -- GitLab From 1371d90460189d02bf1bcca19dbfe6bd10dc6031 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 25 Nov 2008 20:17:04 +0100 Subject: [PATCH 4024/4982] KVM: SVM: Implement GIF, clgi and stgi This patch implements the GIF flag and the clgi and stgi instructions that set this flag. Only if the flag is set (default), interrupts can be received by the CPU. To keep the information about that somewhere, this patch adds a new hidden flags vector. that is used to store information that does not go into the vmcb, but is SVM specific. I tried to write some code to make -no-kvm-irqchip work too, but the first level guest won't even boot with that atm, so I ditched it. v2 moves the hflags to x86 generic code v3 makes use of the new permission helper v6 only enables interrupt_window if GIF=1 Acked-by: Joerg Roedel Signed-off-by: Alexander Graf Signed-off-by: Avi Kivity --- arch/x86/include/asm/kvm_host.h | 3 +++ arch/x86/kvm/svm.c | 47 +++++++++++++++++++++++++++++---- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 2998efe8927..29e4157732d 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -259,6 +259,7 @@ struct kvm_vcpu_arch { unsigned long cr3; unsigned long cr4; unsigned long cr8; + u32 hflags; u64 pdptrs[4]; /* pae */ u64 shadow_efer; u64 apic_base; @@ -738,6 +739,8 @@ enum { TASK_SWITCH_GATE = 3, }; +#define HF_GIF_MASK (1 << 0) + /* * Hardware virtualization extension instructions may fault if a * reboot turns off virtualization while processes are running. diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 87debdcd1b9..79cc06bfe57 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -251,7 +251,7 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu) kvm_rip_write(vcpu, svm->next_rip); svm->vmcb->control.int_state &= ~SVM_INTERRUPT_SHADOW_MASK; - vcpu->arch.interrupt_window_open = 1; + vcpu->arch.interrupt_window_open = (svm->vcpu.arch.hflags & HF_GIF_MASK); } static int has_svm(void) @@ -600,6 +600,8 @@ static void init_vmcb(struct vcpu_svm *svm) save->cr4 = 0; } force_new_asid(&svm->vcpu); + + svm->vcpu.arch.hflags = HF_GIF_MASK; } static int svm_vcpu_reset(struct kvm_vcpu *vcpu) @@ -1234,6 +1236,36 @@ static int nested_svm_do(struct vcpu_svm *svm, return retval; } +static int stgi_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) +{ + if (nested_svm_check_permissions(svm)) + return 1; + + svm->next_rip = kvm_rip_read(&svm->vcpu) + 3; + skip_emulated_instruction(&svm->vcpu); + + svm->vcpu.arch.hflags |= HF_GIF_MASK; + + return 1; +} + +static int clgi_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) +{ + if (nested_svm_check_permissions(svm)) + return 1; + + svm->next_rip = kvm_rip_read(&svm->vcpu) + 3; + skip_emulated_instruction(&svm->vcpu); + + svm->vcpu.arch.hflags &= ~HF_GIF_MASK; + + /* After a CLGI no interrupts should come */ + svm_clear_vintr(svm); + svm->vmcb->control.int_ctl &= ~V_IRQ_MASK; + + return 1; +} + static int invalid_op_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) { @@ -1535,8 +1567,8 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm, [SVM_EXIT_VMMCALL] = vmmcall_interception, [SVM_EXIT_VMLOAD] = invalid_op_interception, [SVM_EXIT_VMSAVE] = invalid_op_interception, - [SVM_EXIT_STGI] = invalid_op_interception, - [SVM_EXIT_CLGI] = invalid_op_interception, + [SVM_EXIT_STGI] = stgi_interception, + [SVM_EXIT_CLGI] = clgi_interception, [SVM_EXIT_SKINIT] = invalid_op_interception, [SVM_EXIT_WBINVD] = emulate_on_interception, [SVM_EXIT_MONITOR] = invalid_op_interception, @@ -1684,6 +1716,9 @@ static void svm_intr_assist(struct kvm_vcpu *vcpu) if (!kvm_cpu_has_interrupt(vcpu)) goto out; + if (!(svm->vcpu.arch.hflags & HF_GIF_MASK)) + goto out; + if (!(vmcb->save.rflags & X86_EFLAGS_IF) || (vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) || (vmcb->control.event_inj & SVM_EVTINJ_VALID)) { @@ -1710,7 +1745,8 @@ static void kvm_reput_irq(struct vcpu_svm *svm) } svm->vcpu.arch.interrupt_window_open = - !(control->int_state & SVM_INTERRUPT_SHADOW_MASK); + !(control->int_state & SVM_INTERRUPT_SHADOW_MASK) && + (svm->vcpu.arch.hflags & HF_GIF_MASK); } static void svm_do_inject_vector(struct vcpu_svm *svm) @@ -1734,7 +1770,8 @@ static void do_interrupt_requests(struct kvm_vcpu *vcpu, svm->vcpu.arch.interrupt_window_open = (!(control->int_state & SVM_INTERRUPT_SHADOW_MASK) && - (svm->vmcb->save.rflags & X86_EFLAGS_IF)); + (svm->vmcb->save.rflags & X86_EFLAGS_IF) && + (svm->vcpu.arch.hflags & HF_GIF_MASK)); if (svm->vcpu.arch.interrupt_window_open && svm->vcpu.arch.irq_summary) /* -- GitLab From b286d5d8b0836e76832dafcc5a18b0e8e5a3bc5e Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 25 Nov 2008 20:17:05 +0100 Subject: [PATCH 4025/4982] KVM: SVM: Implement hsave Implement the hsave MSR, that gives the VCPU a GPA to save the old guest state in. v2 allows userspace to save/restore hsave v4 dummys out the hsave MSR, so we use a host page v6 remembers the guest's hsave and exports the MSR Acked-by: Joerg Roedel Signed-off-by: Alexander Graf Signed-off-by: Avi Kivity --- arch/x86/kvm/kvm_svm.h | 2 ++ arch/x86/kvm/svm.c | 13 +++++++++++++ arch/x86/kvm/x86.c | 2 +- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/kvm_svm.h b/arch/x86/kvm/kvm_svm.h index 8e5ee99551f..a0877cac7b9 100644 --- a/arch/x86/kvm/kvm_svm.h +++ b/arch/x86/kvm/kvm_svm.h @@ -41,6 +41,8 @@ struct vcpu_svm { unsigned long host_dr7; u32 *msrpm; + struct vmcb *hsave; + u64 hsave_msr; }; #endif diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 79cc06bfe57..59aaff1c959 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -626,6 +626,7 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id) struct vcpu_svm *svm; struct page *page; struct page *msrpm_pages; + struct page *hsave_page; int err; svm = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); @@ -651,6 +652,11 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id) svm->msrpm = page_address(msrpm_pages); svm_vcpu_init_msrpm(svm->msrpm); + hsave_page = alloc_page(GFP_KERNEL); + if (!hsave_page) + goto uninit; + svm->hsave = page_address(hsave_page); + svm->vmcb = page_address(page); clear_page(svm->vmcb); svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT; @@ -680,6 +686,7 @@ static void svm_free_vcpu(struct kvm_vcpu *vcpu) __free_page(pfn_to_page(svm->vmcb_pa >> PAGE_SHIFT)); __free_pages(virt_to_page(svm->msrpm), MSRPM_ALLOC_ORDER); + __free_page(virt_to_page(svm->hsave)); kvm_vcpu_uninit(vcpu); kmem_cache_free(kvm_vcpu_cache, svm); } @@ -1377,6 +1384,9 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data) case MSR_IA32_LASTINTTOIP: *data = svm->vmcb->save.last_excp_to; break; + case MSR_VM_HSAVE_PA: + *data = svm->hsave_msr; + break; default: return kvm_get_msr_common(vcpu, ecx, data); } @@ -1470,6 +1480,9 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data) */ pr_unimpl(vcpu, "unimplemented perfctr wrmsr: 0x%x data 0x%llx\n", ecx, data); + break; + case MSR_VM_HSAVE_PA: + svm->hsave_msr = data; break; default: return kvm_set_msr_common(vcpu, ecx, data); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 758b7a155ae..99165a961f0 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -456,7 +456,7 @@ static u32 msrs_to_save[] = { MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR, #endif MSR_IA32_TIME_STAMP_COUNTER, MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK, - MSR_IA32_PERF_STATUS, MSR_IA32_CR_PAT + MSR_IA32_PERF_STATUS, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA }; static unsigned num_msrs_to_save; -- GitLab From 5542675baa7e62ca4d18278c8758b6a4ec410639 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 25 Nov 2008 20:17:06 +0100 Subject: [PATCH 4026/4982] KVM: SVM: Add VMLOAD and VMSAVE handlers This implements the VMLOAD and VMSAVE instructions, that usually surround the VMRUN instructions. Both instructions load / restore the same elements, so we only need to implement them once. v2 fixes CPL checking and replaces memcpy by assignments v3 makes use of the new permission checking Acked-by: Joerg Roedel Signed-off-by: Alexander Graf Signed-off-by: Avi Kivity --- arch/x86/kvm/svm.c | 60 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 59aaff1c959..a83c94eb577 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -1243,6 +1243,62 @@ static int nested_svm_do(struct vcpu_svm *svm, return retval; } +static int nested_svm_vmloadsave(struct vmcb *from_vmcb, struct vmcb *to_vmcb) +{ + to_vmcb->save.fs = from_vmcb->save.fs; + to_vmcb->save.gs = from_vmcb->save.gs; + to_vmcb->save.tr = from_vmcb->save.tr; + to_vmcb->save.ldtr = from_vmcb->save.ldtr; + to_vmcb->save.kernel_gs_base = from_vmcb->save.kernel_gs_base; + to_vmcb->save.star = from_vmcb->save.star; + to_vmcb->save.lstar = from_vmcb->save.lstar; + to_vmcb->save.cstar = from_vmcb->save.cstar; + to_vmcb->save.sfmask = from_vmcb->save.sfmask; + to_vmcb->save.sysenter_cs = from_vmcb->save.sysenter_cs; + to_vmcb->save.sysenter_esp = from_vmcb->save.sysenter_esp; + to_vmcb->save.sysenter_eip = from_vmcb->save.sysenter_eip; + + return 1; +} + +static int nested_svm_vmload(struct vcpu_svm *svm, void *nested_vmcb, + void *arg2, void *opaque) +{ + return nested_svm_vmloadsave((struct vmcb *)nested_vmcb, svm->vmcb); +} + +static int nested_svm_vmsave(struct vcpu_svm *svm, void *nested_vmcb, + void *arg2, void *opaque) +{ + return nested_svm_vmloadsave(svm->vmcb, (struct vmcb *)nested_vmcb); +} + +static int vmload_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) +{ + if (nested_svm_check_permissions(svm)) + return 1; + + svm->next_rip = kvm_rip_read(&svm->vcpu) + 3; + skip_emulated_instruction(&svm->vcpu); + + nested_svm_do(svm, svm->vmcb->save.rax, 0, NULL, nested_svm_vmload); + + return 1; +} + +static int vmsave_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) +{ + if (nested_svm_check_permissions(svm)) + return 1; + + svm->next_rip = kvm_rip_read(&svm->vcpu) + 3; + skip_emulated_instruction(&svm->vcpu); + + nested_svm_do(svm, svm->vmcb->save.rax, 0, NULL, nested_svm_vmsave); + + return 1; +} + static int stgi_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) { if (nested_svm_check_permissions(svm)) @@ -1578,8 +1634,8 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm, [SVM_EXIT_SHUTDOWN] = shutdown_interception, [SVM_EXIT_VMRUN] = invalid_op_interception, [SVM_EXIT_VMMCALL] = vmmcall_interception, - [SVM_EXIT_VMLOAD] = invalid_op_interception, - [SVM_EXIT_VMSAVE] = invalid_op_interception, + [SVM_EXIT_VMLOAD] = vmload_interception, + [SVM_EXIT_VMSAVE] = vmsave_interception, [SVM_EXIT_STGI] = stgi_interception, [SVM_EXIT_CLGI] = clgi_interception, [SVM_EXIT_SKINIT] = invalid_op_interception, -- GitLab From 3d6368ef580a4dff012960834bba4e28d3c1430c Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 25 Nov 2008 20:17:07 +0100 Subject: [PATCH 4027/4982] KVM: SVM: Add VMRUN handler This patch implements VMRUN. VMRUN enters a virtual CPU and runs that in the same context as the normal guest CPU would run. So basically it is implemented the same way, a normal CPU would do it. We also prepare all intercepts that get OR'ed with the original intercepts, as we do not allow a level 2 guest to be intercepted less than the first level guest. v2 implements the following improvements: - fixes the CPL check - does not allocate iopm when not used - remembers the host's IF in the HIF bit in the hflags v3: - make use of the new permission checking - add support for V_INTR_MASKING_MASK v4: - use host page backed hsave v5: - remove IOPM merging code v6: - save cr4 so PAE l1 guests work v7: - return 0 on vmrun so we check the MSRs too - fix MSR check to use the correct variable Acked-by: Joerg Roedel Signed-off-by: Alexander Graf Signed-off-by: Avi Kivity --- arch/x86/include/asm/kvm_host.h | 2 + arch/x86/kvm/kvm_svm.h | 8 ++ arch/x86/kvm/svm.c | 157 +++++++++++++++++++++++++++++++- 3 files changed, 165 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 29e4157732d..53779309514 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -740,6 +740,8 @@ enum { }; #define HF_GIF_MASK (1 << 0) +#define HF_HIF_MASK (1 << 1) +#define HF_VINTR_MASK (1 << 2) /* * Hardware virtualization extension instructions may fault if a diff --git a/arch/x86/kvm/kvm_svm.h b/arch/x86/kvm/kvm_svm.h index a0877cac7b9..91673413d8f 100644 --- a/arch/x86/kvm/kvm_svm.h +++ b/arch/x86/kvm/kvm_svm.h @@ -43,6 +43,14 @@ struct vcpu_svm { u32 *msrpm; struct vmcb *hsave; u64 hsave_msr; + + u64 nested_vmcb; + + /* These are the merged vectors */ + u32 *nested_msrpm; + + /* gpa pointers to the real vectors */ + u64 nested_vmcb_msrpm; }; #endif diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index a83c94eb577..fad187cbfab 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -77,6 +77,11 @@ static inline struct vcpu_svm *to_svm(struct kvm_vcpu *vcpu) return container_of(vcpu, struct vcpu_svm, vcpu); } +static inline bool is_nested(struct vcpu_svm *svm) +{ + return svm->nested_vmcb; +} + static unsigned long iopm_base; struct kvm_ldttss_desc { @@ -601,6 +606,7 @@ static void init_vmcb(struct vcpu_svm *svm) } force_new_asid(&svm->vcpu); + svm->nested_vmcb = 0; svm->vcpu.arch.hflags = HF_GIF_MASK; } @@ -627,6 +633,7 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id) struct page *page; struct page *msrpm_pages; struct page *hsave_page; + struct page *nested_msrpm_pages; int err; svm = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); @@ -649,6 +656,11 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id) msrpm_pages = alloc_pages(GFP_KERNEL, MSRPM_ALLOC_ORDER); if (!msrpm_pages) goto uninit; + + nested_msrpm_pages = alloc_pages(GFP_KERNEL, MSRPM_ALLOC_ORDER); + if (!nested_msrpm_pages) + goto uninit; + svm->msrpm = page_address(msrpm_pages); svm_vcpu_init_msrpm(svm->msrpm); @@ -657,6 +669,8 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id) goto uninit; svm->hsave = page_address(hsave_page); + svm->nested_msrpm = page_address(nested_msrpm_pages); + svm->vmcb = page_address(page); clear_page(svm->vmcb); svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT; @@ -687,6 +701,7 @@ static void svm_free_vcpu(struct kvm_vcpu *vcpu) __free_page(pfn_to_page(svm->vmcb_pa >> PAGE_SHIFT)); __free_pages(virt_to_page(svm->msrpm), MSRPM_ALLOC_ORDER); __free_page(virt_to_page(svm->hsave)); + __free_pages(virt_to_page(svm->nested_msrpm), MSRPM_ALLOC_ORDER); kvm_vcpu_uninit(vcpu); kmem_cache_free(kvm_vcpu_cache, svm); } @@ -1243,6 +1258,123 @@ static int nested_svm_do(struct vcpu_svm *svm, return retval; } + +static int nested_svm_vmrun_msrpm(struct vcpu_svm *svm, void *arg1, + void *arg2, void *opaque) +{ + int i; + u32 *nested_msrpm = (u32*)arg1; + for (i=0; i< PAGE_SIZE * (1 << MSRPM_ALLOC_ORDER) / 4; i++) + svm->nested_msrpm[i] = svm->msrpm[i] | nested_msrpm[i]; + svm->vmcb->control.msrpm_base_pa = __pa(svm->nested_msrpm); + + return 0; +} + +static int nested_svm_vmrun(struct vcpu_svm *svm, void *arg1, + void *arg2, void *opaque) +{ + struct vmcb *nested_vmcb = (struct vmcb *)arg1; + struct vmcb *hsave = svm->hsave; + + /* nested_vmcb is our indicator if nested SVM is activated */ + svm->nested_vmcb = svm->vmcb->save.rax; + + /* Clear internal status */ + svm->vcpu.arch.exception.pending = false; + + /* Save the old vmcb, so we don't need to pick what we save, but + can restore everything when a VMEXIT occurs */ + memcpy(hsave, svm->vmcb, sizeof(struct vmcb)); + /* We need to remember the original CR3 in the SPT case */ + if (!npt_enabled) + hsave->save.cr3 = svm->vcpu.arch.cr3; + hsave->save.cr4 = svm->vcpu.arch.cr4; + hsave->save.rip = svm->next_rip; + + if (svm->vmcb->save.rflags & X86_EFLAGS_IF) + svm->vcpu.arch.hflags |= HF_HIF_MASK; + else + svm->vcpu.arch.hflags &= ~HF_HIF_MASK; + + /* Load the nested guest state */ + svm->vmcb->save.es = nested_vmcb->save.es; + svm->vmcb->save.cs = nested_vmcb->save.cs; + svm->vmcb->save.ss = nested_vmcb->save.ss; + svm->vmcb->save.ds = nested_vmcb->save.ds; + svm->vmcb->save.gdtr = nested_vmcb->save.gdtr; + svm->vmcb->save.idtr = nested_vmcb->save.idtr; + svm->vmcb->save.rflags = nested_vmcb->save.rflags; + svm_set_efer(&svm->vcpu, nested_vmcb->save.efer); + svm_set_cr0(&svm->vcpu, nested_vmcb->save.cr0); + svm_set_cr4(&svm->vcpu, nested_vmcb->save.cr4); + if (npt_enabled) { + svm->vmcb->save.cr3 = nested_vmcb->save.cr3; + svm->vcpu.arch.cr3 = nested_vmcb->save.cr3; + } else { + kvm_set_cr3(&svm->vcpu, nested_vmcb->save.cr3); + kvm_mmu_reset_context(&svm->vcpu); + } + svm->vmcb->save.cr2 = nested_vmcb->save.cr2; + kvm_register_write(&svm->vcpu, VCPU_REGS_RAX, nested_vmcb->save.rax); + kvm_register_write(&svm->vcpu, VCPU_REGS_RSP, nested_vmcb->save.rsp); + kvm_register_write(&svm->vcpu, VCPU_REGS_RIP, nested_vmcb->save.rip); + /* In case we don't even reach vcpu_run, the fields are not updated */ + svm->vmcb->save.rax = nested_vmcb->save.rax; + svm->vmcb->save.rsp = nested_vmcb->save.rsp; + svm->vmcb->save.rip = nested_vmcb->save.rip; + svm->vmcb->save.dr7 = nested_vmcb->save.dr7; + svm->vmcb->save.dr6 = nested_vmcb->save.dr6; + svm->vmcb->save.cpl = nested_vmcb->save.cpl; + + /* We don't want a nested guest to be more powerful than the guest, + so all intercepts are ORed */ + svm->vmcb->control.intercept_cr_read |= + nested_vmcb->control.intercept_cr_read; + svm->vmcb->control.intercept_cr_write |= + nested_vmcb->control.intercept_cr_write; + svm->vmcb->control.intercept_dr_read |= + nested_vmcb->control.intercept_dr_read; + svm->vmcb->control.intercept_dr_write |= + nested_vmcb->control.intercept_dr_write; + svm->vmcb->control.intercept_exceptions |= + nested_vmcb->control.intercept_exceptions; + + svm->vmcb->control.intercept |= nested_vmcb->control.intercept; + + svm->nested_vmcb_msrpm = nested_vmcb->control.msrpm_base_pa; + + force_new_asid(&svm->vcpu); + svm->vmcb->control.exit_int_info = nested_vmcb->control.exit_int_info; + svm->vmcb->control.exit_int_info_err = nested_vmcb->control.exit_int_info_err; + svm->vmcb->control.int_ctl = nested_vmcb->control.int_ctl | V_INTR_MASKING_MASK; + if (nested_vmcb->control.int_ctl & V_IRQ_MASK) { + nsvm_printk("nSVM Injecting Interrupt: 0x%x\n", + nested_vmcb->control.int_ctl); + } + if (nested_vmcb->control.int_ctl & V_INTR_MASKING_MASK) + svm->vcpu.arch.hflags |= HF_VINTR_MASK; + else + svm->vcpu.arch.hflags &= ~HF_VINTR_MASK; + + nsvm_printk("nSVM exit_int_info: 0x%x | int_state: 0x%x\n", + nested_vmcb->control.exit_int_info, + nested_vmcb->control.int_state); + + svm->vmcb->control.int_vector = nested_vmcb->control.int_vector; + svm->vmcb->control.int_state = nested_vmcb->control.int_state; + svm->vmcb->control.tsc_offset += nested_vmcb->control.tsc_offset; + if (nested_vmcb->control.event_inj & SVM_EVTINJ_VALID) + nsvm_printk("Injecting Event: 0x%x\n", + nested_vmcb->control.event_inj); + svm->vmcb->control.event_inj = nested_vmcb->control.event_inj; + svm->vmcb->control.event_inj_err = nested_vmcb->control.event_inj_err; + + svm->vcpu.arch.hflags |= HF_GIF_MASK; + + return 0; +} + static int nested_svm_vmloadsave(struct vmcb *from_vmcb, struct vmcb *to_vmcb) { to_vmcb->save.fs = from_vmcb->save.fs; @@ -1299,6 +1431,26 @@ static int vmsave_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) return 1; } +static int vmrun_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) +{ + nsvm_printk("VMrun\n"); + if (nested_svm_check_permissions(svm)) + return 1; + + svm->next_rip = kvm_rip_read(&svm->vcpu) + 3; + skip_emulated_instruction(&svm->vcpu); + + if (nested_svm_do(svm, svm->vmcb->save.rax, 0, + NULL, nested_svm_vmrun)) + return 1; + + if (nested_svm_do(svm, svm->nested_vmcb_msrpm, 0, + NULL, nested_svm_vmrun_msrpm)) + return 1; + + return 1; +} + static int stgi_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) { if (nested_svm_check_permissions(svm)) @@ -1632,7 +1784,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm, [SVM_EXIT_MSR] = msr_interception, [SVM_EXIT_TASK_SWITCH] = task_switch_interception, [SVM_EXIT_SHUTDOWN] = shutdown_interception, - [SVM_EXIT_VMRUN] = invalid_op_interception, + [SVM_EXIT_VMRUN] = vmrun_interception, [SVM_EXIT_VMMCALL] = vmmcall_interception, [SVM_EXIT_VMLOAD] = vmload_interception, [SVM_EXIT_VMSAVE] = vmsave_interception, @@ -1939,7 +2091,8 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) svm->host_cr2 = kvm_read_cr2(); svm->host_dr6 = read_dr6(); svm->host_dr7 = read_dr7(); - svm->vmcb->save.cr2 = vcpu->arch.cr2; + if (!is_nested(svm)) + svm->vmcb->save.cr2 = vcpu->arch.cr2; /* required for live migration with NPT */ if (npt_enabled) svm->vmcb->save.cr3 = vcpu->arch.cr3; -- GitLab From cf74a78b229d07f77416d2fe1f029f183a8a31df Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 25 Nov 2008 20:17:08 +0100 Subject: [PATCH 4028/4982] KVM: SVM: Add VMEXIT handler and intercepts This adds the #VMEXIT intercept, so we return to the level 1 guest when something happens in the level 2 guest that should return to the level 1 guest. v2 implements HIF handling and cleans up exception interception v3 adds support for V_INTR_MASKING_MASK v4 uses the host page hsave v5 removes IOPM merging code v6 moves mmu code out of the atomic section Acked-by: Joerg Roedel Signed-off-by: Alexander Graf Signed-off-by: Avi Kivity --- arch/x86/kvm/svm.c | 293 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 293 insertions(+) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index fad187cbfab..4cb2920b152 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -72,6 +72,13 @@ module_param(npt, int, S_IRUGO); static void kvm_reput_irq(struct vcpu_svm *svm); static void svm_flush_tlb(struct kvm_vcpu *vcpu); +static int nested_svm_exit_handled(struct vcpu_svm *svm, bool kvm_override); +static int nested_svm_vmexit(struct vcpu_svm *svm); +static int nested_svm_vmsave(struct vcpu_svm *svm, void *nested_vmcb, + void *arg2, void *opaque); +static int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr, + bool has_error_code, u32 error_code); + static inline struct vcpu_svm *to_svm(struct kvm_vcpu *vcpu) { return container_of(vcpu, struct vcpu_svm, vcpu); @@ -221,6 +228,11 @@ static void svm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr, { struct vcpu_svm *svm = to_svm(vcpu); + /* If we are within a nested VM we'd better #VMEXIT and let the + guest handle the exception */ + if (nested_svm_check_exception(svm, nr, has_error_code, error_code)) + return; + svm->vmcb->control.event_inj = nr | SVM_EVTINJ_VALID | (has_error_code ? SVM_EVTINJ_VALID_ERR : 0) @@ -1198,6 +1210,46 @@ static int nested_svm_check_permissions(struct vcpu_svm *svm) return 0; } +static int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr, + bool has_error_code, u32 error_code) +{ + if (is_nested(svm)) { + svm->vmcb->control.exit_code = SVM_EXIT_EXCP_BASE + nr; + svm->vmcb->control.exit_code_hi = 0; + svm->vmcb->control.exit_info_1 = error_code; + svm->vmcb->control.exit_info_2 = svm->vcpu.arch.cr2; + if (nested_svm_exit_handled(svm, false)) { + nsvm_printk("VMexit -> EXCP 0x%x\n", nr); + + nested_svm_vmexit(svm); + return 1; + } + } + + return 0; +} + +static inline int nested_svm_intr(struct vcpu_svm *svm) +{ + if (is_nested(svm)) { + if (!(svm->vcpu.arch.hflags & HF_VINTR_MASK)) + return 0; + + if (!(svm->vcpu.arch.hflags & HF_HIF_MASK)) + return 0; + + svm->vmcb->control.exit_code = SVM_EXIT_INTR; + + if (nested_svm_exit_handled(svm, false)) { + nsvm_printk("VMexit -> INTR\n"); + nested_svm_vmexit(svm); + return 1; + } + } + + return 0; +} + static struct page *nested_svm_get_page(struct vcpu_svm *svm, u64 gpa) { struct page *page; @@ -1258,6 +1310,228 @@ static int nested_svm_do(struct vcpu_svm *svm, return retval; } +static int nested_svm_exit_handled_real(struct vcpu_svm *svm, + void *arg1, + void *arg2, + void *opaque) +{ + struct vmcb *nested_vmcb = (struct vmcb *)arg1; + bool kvm_overrides = *(bool *)opaque; + u32 exit_code = svm->vmcb->control.exit_code; + + if (kvm_overrides) { + switch (exit_code) { + case SVM_EXIT_INTR: + case SVM_EXIT_NMI: + return 0; + /* For now we are always handling NPFs when using them */ + case SVM_EXIT_NPF: + if (npt_enabled) + return 0; + break; + /* When we're shadowing, trap PFs */ + case SVM_EXIT_EXCP_BASE + PF_VECTOR: + if (!npt_enabled) + return 0; + break; + default: + break; + } + } + + switch (exit_code) { + case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR8: { + u32 cr_bits = 1 << (exit_code - SVM_EXIT_READ_CR0); + if (nested_vmcb->control.intercept_cr_read & cr_bits) + return 1; + break; + } + case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR8: { + u32 cr_bits = 1 << (exit_code - SVM_EXIT_WRITE_CR0); + if (nested_vmcb->control.intercept_cr_write & cr_bits) + return 1; + break; + } + case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR7: { + u32 dr_bits = 1 << (exit_code - SVM_EXIT_READ_DR0); + if (nested_vmcb->control.intercept_dr_read & dr_bits) + return 1; + break; + } + case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR7: { + u32 dr_bits = 1 << (exit_code - SVM_EXIT_WRITE_DR0); + if (nested_vmcb->control.intercept_dr_write & dr_bits) + return 1; + break; + } + case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 0x1f: { + u32 excp_bits = 1 << (exit_code - SVM_EXIT_EXCP_BASE); + if (nested_vmcb->control.intercept_exceptions & excp_bits) + return 1; + break; + } + default: { + u64 exit_bits = 1ULL << (exit_code - SVM_EXIT_INTR); + nsvm_printk("exit code: 0x%x\n", exit_code); + if (nested_vmcb->control.intercept & exit_bits) + return 1; + } + } + + return 0; +} + +static int nested_svm_exit_handled_msr(struct vcpu_svm *svm, + void *arg1, void *arg2, + void *opaque) +{ + struct vmcb *nested_vmcb = (struct vmcb *)arg1; + u8 *msrpm = (u8 *)arg2; + u32 t0, t1; + u32 msr = svm->vcpu.arch.regs[VCPU_REGS_RCX]; + u32 param = svm->vmcb->control.exit_info_1 & 1; + + if (!(nested_vmcb->control.intercept & (1ULL << INTERCEPT_MSR_PROT))) + return 0; + + switch(msr) { + case 0 ... 0x1fff: + t0 = (msr * 2) % 8; + t1 = msr / 8; + break; + case 0xc0000000 ... 0xc0001fff: + t0 = (8192 + msr - 0xc0000000) * 2; + t1 = (t0 / 8); + t0 %= 8; + break; + case 0xc0010000 ... 0xc0011fff: + t0 = (16384 + msr - 0xc0010000) * 2; + t1 = (t0 / 8); + t0 %= 8; + break; + default: + return 1; + break; + } + if (msrpm[t1] & ((1 << param) << t0)) + return 1; + + return 0; +} + +static int nested_svm_exit_handled(struct vcpu_svm *svm, bool kvm_override) +{ + bool k = kvm_override; + + switch (svm->vmcb->control.exit_code) { + case SVM_EXIT_MSR: + return nested_svm_do(svm, svm->nested_vmcb, + svm->nested_vmcb_msrpm, NULL, + nested_svm_exit_handled_msr); + default: break; + } + + return nested_svm_do(svm, svm->nested_vmcb, 0, &k, + nested_svm_exit_handled_real); +} + +static int nested_svm_vmexit_real(struct vcpu_svm *svm, void *arg1, + void *arg2, void *opaque) +{ + struct vmcb *nested_vmcb = (struct vmcb *)arg1; + struct vmcb *hsave = svm->hsave; + u64 nested_save[] = { nested_vmcb->save.cr0, + nested_vmcb->save.cr3, + nested_vmcb->save.cr4, + nested_vmcb->save.efer, + nested_vmcb->control.intercept_cr_read, + nested_vmcb->control.intercept_cr_write, + nested_vmcb->control.intercept_dr_read, + nested_vmcb->control.intercept_dr_write, + nested_vmcb->control.intercept_exceptions, + nested_vmcb->control.intercept, + nested_vmcb->control.msrpm_base_pa, + nested_vmcb->control.iopm_base_pa, + nested_vmcb->control.tsc_offset }; + + /* Give the current vmcb to the guest */ + memcpy(nested_vmcb, svm->vmcb, sizeof(struct vmcb)); + nested_vmcb->save.cr0 = nested_save[0]; + if (!npt_enabled) + nested_vmcb->save.cr3 = nested_save[1]; + nested_vmcb->save.cr4 = nested_save[2]; + nested_vmcb->save.efer = nested_save[3]; + nested_vmcb->control.intercept_cr_read = nested_save[4]; + nested_vmcb->control.intercept_cr_write = nested_save[5]; + nested_vmcb->control.intercept_dr_read = nested_save[6]; + nested_vmcb->control.intercept_dr_write = nested_save[7]; + nested_vmcb->control.intercept_exceptions = nested_save[8]; + nested_vmcb->control.intercept = nested_save[9]; + nested_vmcb->control.msrpm_base_pa = nested_save[10]; + nested_vmcb->control.iopm_base_pa = nested_save[11]; + nested_vmcb->control.tsc_offset = nested_save[12]; + + /* We always set V_INTR_MASKING and remember the old value in hflags */ + if (!(svm->vcpu.arch.hflags & HF_VINTR_MASK)) + nested_vmcb->control.int_ctl &= ~V_INTR_MASKING_MASK; + + if ((nested_vmcb->control.int_ctl & V_IRQ_MASK) && + (nested_vmcb->control.int_vector)) { + nsvm_printk("WARNING: IRQ 0x%x still enabled on #VMEXIT\n", + nested_vmcb->control.int_vector); + } + + /* Restore the original control entries */ + svm->vmcb->control = hsave->control; + + /* Kill any pending exceptions */ + if (svm->vcpu.arch.exception.pending == true) + nsvm_printk("WARNING: Pending Exception\n"); + svm->vcpu.arch.exception.pending = false; + + /* Restore selected save entries */ + svm->vmcb->save.es = hsave->save.es; + svm->vmcb->save.cs = hsave->save.cs; + svm->vmcb->save.ss = hsave->save.ss; + svm->vmcb->save.ds = hsave->save.ds; + svm->vmcb->save.gdtr = hsave->save.gdtr; + svm->vmcb->save.idtr = hsave->save.idtr; + svm->vmcb->save.rflags = hsave->save.rflags; + svm_set_efer(&svm->vcpu, hsave->save.efer); + svm_set_cr0(&svm->vcpu, hsave->save.cr0 | X86_CR0_PE); + svm_set_cr4(&svm->vcpu, hsave->save.cr4); + if (npt_enabled) { + svm->vmcb->save.cr3 = hsave->save.cr3; + svm->vcpu.arch.cr3 = hsave->save.cr3; + } else { + kvm_set_cr3(&svm->vcpu, hsave->save.cr3); + } + kvm_register_write(&svm->vcpu, VCPU_REGS_RAX, hsave->save.rax); + kvm_register_write(&svm->vcpu, VCPU_REGS_RSP, hsave->save.rsp); + kvm_register_write(&svm->vcpu, VCPU_REGS_RIP, hsave->save.rip); + svm->vmcb->save.dr7 = 0; + svm->vmcb->save.cpl = 0; + svm->vmcb->control.exit_int_info = 0; + + svm->vcpu.arch.hflags &= ~HF_GIF_MASK; + /* Exit nested SVM mode */ + svm->nested_vmcb = 0; + + return 0; +} + +static int nested_svm_vmexit(struct vcpu_svm *svm) +{ + nsvm_printk("VMexit\n"); + if (nested_svm_do(svm, svm->nested_vmcb, 0, + NULL, nested_svm_vmexit_real)) + return 1; + + kvm_mmu_reset_context(&svm->vcpu); + kvm_mmu_load(&svm->vcpu); + + return 0; +} static int nested_svm_vmrun_msrpm(struct vcpu_svm *svm, void *arg1, void *arg2, void *opaque) @@ -1805,6 +2079,17 @@ static int handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) KVMTRACE_3D(VMEXIT, vcpu, exit_code, (u32)svm->vmcb->save.rip, (u32)((u64)svm->vmcb->save.rip >> 32), entryexit); + if (is_nested(svm)) { + nsvm_printk("nested handle_exit: 0x%x | 0x%lx | 0x%lx | 0x%lx\n", + exit_code, svm->vmcb->control.exit_info_1, + svm->vmcb->control.exit_info_2, svm->vmcb->save.rip); + if (nested_svm_exit_handled(svm, true)) { + nested_svm_vmexit(svm); + nsvm_printk("-> #VMEXIT\n"); + return 1; + } + } + if (npt_enabled) { int mmu_reload = 0; if ((vcpu->arch.cr0 ^ svm->vmcb->save.cr0) & X86_CR0_PG) { @@ -1892,6 +2177,8 @@ static void svm_set_irq(struct kvm_vcpu *vcpu, int irq) { struct vcpu_svm *svm = to_svm(vcpu); + nested_svm_intr(svm); + svm_inject_irq(svm, irq); } @@ -1937,6 +2224,9 @@ static void svm_intr_assist(struct kvm_vcpu *vcpu) if (!kvm_cpu_has_interrupt(vcpu)) goto out; + if (nested_svm_intr(svm)) + goto out; + if (!(svm->vcpu.arch.hflags & HF_GIF_MASK)) goto out; @@ -1989,6 +2279,9 @@ static void do_interrupt_requests(struct kvm_vcpu *vcpu, struct vcpu_svm *svm = to_svm(vcpu); struct vmcb_control_area *control = &svm->vmcb->control; + if (nested_svm_intr(svm)) + return; + svm->vcpu.arch.interrupt_window_open = (!(control->int_state & SVM_INTERRUPT_SHADOW_MASK) && (svm->vmcb->save.rflags & X86_EFLAGS_IF) && -- GitLab From eb6f302edff9da963e687bf6c15dcf88843b1c3b Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 25 Nov 2008 20:17:09 +0100 Subject: [PATCH 4029/4982] KVM: SVM: Allow read access to MSR_VM_VR KVM tries to read the VM_CR MSR to find out if SVM was disabled by the BIOS. So implement read support for this MSR to make nested SVM running. Signed-off-by: Joerg Roedel Signed-off-by: Alexander Graf Signed-off-by: Avi Kivity --- arch/x86/kvm/svm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 4cb2920b152..df5b4119266 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -1869,6 +1869,9 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data) case MSR_VM_HSAVE_PA: *data = svm->hsave_msr; break; + case MSR_VM_CR: + *data = 0; + break; default: return kvm_get_msr_common(vcpu, ecx, data); } -- GitLab From 236de05553a7ef8f6940de8686ae9bf1272cd2cf Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 25 Nov 2008 20:17:10 +0100 Subject: [PATCH 4030/4982] KVM: SVM: Allow setting the SVME bit Normally setting the SVME bit in EFER is not allowed, as we did not support SVM. Not since we do, we should also allow enabling SVM mode. v2 comes as last patch, so we don't enable half-ready code v4 introduces a module option to enable SVM v6 warns that nesting is enabled Acked-by: Joerg Roedel Signed-off-by: Alexander Graf Signed-off-by: Avi Kivity --- arch/x86/kvm/svm.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index df5b4119266..0fbbde54eca 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -69,6 +69,9 @@ static int npt = 1; module_param(npt, int, S_IRUGO); +static int nested = 0; +module_param(nested, int, S_IRUGO); + static void kvm_reput_irq(struct vcpu_svm *svm); static void svm_flush_tlb(struct kvm_vcpu *vcpu); @@ -443,6 +446,11 @@ static __init int svm_hardware_setup(void) if (boot_cpu_has(X86_FEATURE_NX)) kvm_enable_efer_bits(EFER_NX); + if (nested) { + printk(KERN_INFO "kvm: Nested Virtualization enabled\n"); + kvm_enable_efer_bits(EFER_SVME); + } + for_each_online_cpu(cpu) { r = svm_cpu_init(cpu); if (r) -- GitLab From d80174745ba3938bc6abb8f95ed670ac0631a182 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 25 Nov 2008 20:17:11 +0100 Subject: [PATCH 4031/4982] KVM: SVM: Only allow setting of EFER_SVME when CPUID SVM is set Userspace has to tell the kernel module somehow that nested SVM should be used. The easiest way that doesn't break anything I could think of is to implement if (cpuid & svm) allow write to efer else deny write to efer Old userspaces mask the SVM capability bit, so they don't break. In order to find out that the SVM capability is set, I had to split the kvm_emulate_cpuid into a finding and an emulating part. (introduced in v6) Acked-by: Joerg Roedel Signed-off-by: Alexander Graf Signed-off-by: Avi Kivity --- arch/x86/kvm/x86.c | 58 +++++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 99165a961f0..b5e9932e0f6 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -69,6 +69,8 @@ static u64 __read_mostly efer_reserved_bits = 0xfffffffffffffffeULL; static int kvm_dev_ioctl_get_supported_cpuid(struct kvm_cpuid2 *cpuid, struct kvm_cpuid_entry2 __user *entries); +struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu, + u32 function, u32 index); struct kvm_x86_ops *kvm_x86_ops; EXPORT_SYMBOL_GPL(kvm_x86_ops); @@ -173,6 +175,7 @@ void kvm_inject_page_fault(struct kvm_vcpu *vcpu, unsigned long addr, u32 error_code) { ++vcpu->stat.pf_guest; + if (vcpu->arch.exception.pending) { if (vcpu->arch.exception.nr == PF_VECTOR) { printk(KERN_DEBUG "kvm: inject_page_fault:" @@ -442,6 +445,11 @@ unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu) } EXPORT_SYMBOL_GPL(kvm_get_cr8); +static inline u32 bit(int bitno) +{ + return 1 << (bitno & 31); +} + /* * List of msr numbers which we expose to userspace through KVM_GET_MSRS * and KVM_SET_MSRS, and KVM_GET_MSR_INDEX_LIST. @@ -481,6 +489,17 @@ static void set_efer(struct kvm_vcpu *vcpu, u64 efer) return; } + if (efer & EFER_SVME) { + struct kvm_cpuid_entry2 *feat; + + feat = kvm_find_cpuid_entry(vcpu, 0x80000001, 0); + if (!feat || !(feat->ecx & bit(X86_FEATURE_SVM))) { + printk(KERN_DEBUG "set_efer: #GP, enable SVM w/o SVM\n"); + kvm_inject_gp(vcpu, 0); + return; + } + } + kvm_x86_ops->set_efer(vcpu, efer); efer &= ~EFER_LMA; @@ -1181,11 +1200,6 @@ out: return r; } -static inline u32 bit(int bitno) -{ - return 1 << (bitno & 31); -} - static void do_cpuid_1_ent(struct kvm_cpuid_entry2 *entry, u32 function, u32 index) { @@ -1228,7 +1242,8 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, const u32 kvm_supported_word3_x86_features = bit(X86_FEATURE_XMM3) | bit(X86_FEATURE_CX16); const u32 kvm_supported_word6_x86_features = - bit(X86_FEATURE_LAHF_LM) | bit(X86_FEATURE_CMP_LEGACY); + bit(X86_FEATURE_LAHF_LM) | bit(X86_FEATURE_CMP_LEGACY) | + bit(X86_FEATURE_SVM); /* all func 2 cpuid_count() should be called on the same cpu */ get_cpu(); @@ -2832,20 +2847,15 @@ static int is_matching_cpuid_entry(struct kvm_cpuid_entry2 *e, return 1; } -void kvm_emulate_cpuid(struct kvm_vcpu *vcpu) +struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu, + u32 function, u32 index) { int i; - u32 function, index; - struct kvm_cpuid_entry2 *e, *best; + struct kvm_cpuid_entry2 *best = NULL; - function = kvm_register_read(vcpu, VCPU_REGS_RAX); - index = kvm_register_read(vcpu, VCPU_REGS_RCX); - kvm_register_write(vcpu, VCPU_REGS_RAX, 0); - kvm_register_write(vcpu, VCPU_REGS_RBX, 0); - kvm_register_write(vcpu, VCPU_REGS_RCX, 0); - kvm_register_write(vcpu, VCPU_REGS_RDX, 0); - best = NULL; for (i = 0; i < vcpu->arch.cpuid_nent; ++i) { + struct kvm_cpuid_entry2 *e; + e = &vcpu->arch.cpuid_entries[i]; if (is_matching_cpuid_entry(e, function, index)) { if (e->flags & KVM_CPUID_FLAG_STATEFUL_FUNC) @@ -2860,6 +2870,22 @@ void kvm_emulate_cpuid(struct kvm_vcpu *vcpu) if (!best || e->function > best->function) best = e; } + + return best; +} + +void kvm_emulate_cpuid(struct kvm_vcpu *vcpu) +{ + u32 function, index; + struct kvm_cpuid_entry2 *best; + + function = kvm_register_read(vcpu, VCPU_REGS_RAX); + index = kvm_register_read(vcpu, VCPU_REGS_RCX); + kvm_register_write(vcpu, VCPU_REGS_RAX, 0); + kvm_register_write(vcpu, VCPU_REGS_RBX, 0); + kvm_register_write(vcpu, VCPU_REGS_RCX, 0); + kvm_register_write(vcpu, VCPU_REGS_RDX, 0); + best = kvm_find_cpuid_entry(vcpu, function, index); if (best) { kvm_register_write(vcpu, VCPU_REGS_RAX, best->eax); kvm_register_write(vcpu, VCPU_REGS_RBX, best->ebx); -- GitLab From 8ab2d2e231062814bd89bba2d6d92563190aa2bb Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 15 Dec 2008 13:52:10 +0100 Subject: [PATCH 4032/4982] KVM: VMX: Support for injecting software exceptions VMX differentiates between processor and software generated exceptions when injecting them into the guest. Extend vmx_queue_exception accordingly (and refactor related constants) so that we can use this service reliably for the new guest debugging framework. Signed-off-by: Jan Kiszka Signed-off-by: Avi Kivity --- arch/x86/include/asm/vmx.h | 3 ++- arch/x86/kvm/vmx.c | 35 ++++++++++++++++++++--------------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index d0238e6151d..32159f034ef 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h @@ -270,8 +270,9 @@ enum vmcs_field { #define INTR_TYPE_EXT_INTR (0 << 8) /* external interrupt */ #define INTR_TYPE_NMI_INTR (2 << 8) /* NMI */ -#define INTR_TYPE_EXCEPTION (3 << 8) /* processor exception */ +#define INTR_TYPE_HARD_EXCEPTION (3 << 8) /* processor exception */ #define INTR_TYPE_SOFT_INTR (4 << 8) /* software interrupt */ +#define INTR_TYPE_SOFT_EXCEPTION (6 << 8) /* software exception */ /* GUEST_INTERRUPTIBILITY_INFO flags. */ #define GUEST_INTR_STATE_STI 0x00000001 diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 7611af57682..1d974c1eaa7 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -189,21 +189,21 @@ static inline int is_page_fault(u32 intr_info) { return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK | INTR_INFO_VALID_MASK)) == - (INTR_TYPE_EXCEPTION | PF_VECTOR | INTR_INFO_VALID_MASK); + (INTR_TYPE_HARD_EXCEPTION | PF_VECTOR | INTR_INFO_VALID_MASK); } static inline int is_no_device(u32 intr_info) { return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK | INTR_INFO_VALID_MASK)) == - (INTR_TYPE_EXCEPTION | NM_VECTOR | INTR_INFO_VALID_MASK); + (INTR_TYPE_HARD_EXCEPTION | NM_VECTOR | INTR_INFO_VALID_MASK); } static inline int is_invalid_opcode(u32 intr_info) { return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK | INTR_INFO_VALID_MASK)) == - (INTR_TYPE_EXCEPTION | UD_VECTOR | INTR_INFO_VALID_MASK); + (INTR_TYPE_HARD_EXCEPTION | UD_VECTOR | INTR_INFO_VALID_MASK); } static inline int is_external_interrupt(u32 intr_info) @@ -747,29 +747,33 @@ static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr, bool has_error_code, u32 error_code) { struct vcpu_vmx *vmx = to_vmx(vcpu); + u32 intr_info = nr | INTR_INFO_VALID_MASK; - if (has_error_code) + if (has_error_code) { vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code); + intr_info |= INTR_INFO_DELIVER_CODE_MASK; + } if (vcpu->arch.rmode.active) { vmx->rmode.irq.pending = true; vmx->rmode.irq.vector = nr; vmx->rmode.irq.rip = kvm_rip_read(vcpu); - if (nr == BP_VECTOR) + if (nr == BP_VECTOR || nr == OF_VECTOR) vmx->rmode.irq.rip++; - vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, - nr | INTR_TYPE_SOFT_INTR - | (has_error_code ? INTR_INFO_DELIVER_CODE_MASK : 0) - | INTR_INFO_VALID_MASK); + intr_info |= INTR_TYPE_SOFT_INTR; + vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info); vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, 1); kvm_rip_write(vcpu, vmx->rmode.irq.rip - 1); return; } - vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, - nr | INTR_TYPE_EXCEPTION - | (has_error_code ? INTR_INFO_DELIVER_CODE_MASK : 0) - | INTR_INFO_VALID_MASK); + if (nr == BP_VECTOR || nr == OF_VECTOR) { + vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, 1); + intr_info |= INTR_TYPE_SOFT_EXCEPTION; + } else + intr_info |= INTR_TYPE_HARD_EXCEPTION; + + vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info); } static bool vmx_exception_injected(struct kvm_vcpu *vcpu) @@ -2650,7 +2654,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) } if ((intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK)) == - (INTR_TYPE_EXCEPTION | 1)) { + (INTR_TYPE_HARD_EXCEPTION | 1)) { kvm_run->exit_reason = KVM_EXIT_DEBUG; return 0; } @@ -3238,7 +3242,8 @@ static void vmx_complete_interrupts(struct vcpu_vmx *vmx) vmx->vcpu.arch.nmi_injected = false; } kvm_clear_exception_queue(&vmx->vcpu); - if (idtv_info_valid && type == INTR_TYPE_EXCEPTION) { + if (idtv_info_valid && (type == INTR_TYPE_HARD_EXCEPTION || + type == INTR_TYPE_SOFT_EXCEPTION)) { if (idt_vectoring_info & VECTORING_INFO_DELIVER_CODE_MASK) { error = vmcs_read32(IDT_VECTORING_ERROR_CODE); kvm_queue_exception_e(&vmx->vcpu, vector, error); -- GitLab From d0bfb940ecabf0b44fb1fd80d8d60594e569e5ec Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 15 Dec 2008 13:52:10 +0100 Subject: [PATCH 4033/4982] KVM: New guest debug interface This rips out the support for KVM_DEBUG_GUEST and introduces a new IOCTL instead: KVM_SET_GUEST_DEBUG. The IOCTL payload consists of a generic part, controlling the "main switch" and the single-step feature. The arch specific part adds an x86 interface for intercepting both types of debug exceptions separately and re-injecting them when the host was not interested. Moveover, the foundation for guest debugging via debug registers is layed. To signal breakpoint events properly back to userland, an arch-specific data block is now returned along KVM_EXIT_DEBUG. For x86, the arch block contains the PC, the debug exception, and relevant debug registers to tell debug events properly apart. The availability of this new interface is signaled by KVM_CAP_SET_GUEST_DEBUG. Empty stubs for not yet supported archs are provided. Note that both SVM and VTX are supported, but only the latter was tested yet. Based on the experience with all those VTX corner case, I would be fairly surprised if SVM will work out of the box. Signed-off-by: Jan Kiszka Signed-off-by: Avi Kivity --- arch/ia64/include/asm/kvm.h | 7 +++ arch/ia64/kvm/kvm-ia64.c | 4 +- arch/powerpc/include/asm/kvm.h | 7 +++ arch/powerpc/kvm/powerpc.c | 4 +- arch/s390/include/asm/kvm.h | 7 +++ arch/s390/kvm/kvm-s390.c | 4 +- arch/x86/include/asm/kvm.h | 18 +++++++ arch/x86/include/asm/kvm_host.h | 9 +--- arch/x86/kvm/svm.c | 50 +++++++++++++++++- arch/x86/kvm/vmx.c | 93 +++++++++++++-------------------- arch/x86/kvm/x86.c | 14 ++--- include/linux/kvm.h | 51 ++++++++++++------ include/linux/kvm_host.h | 6 +-- virt/kvm/kvm_main.c | 6 +-- 14 files changed, 179 insertions(+), 101 deletions(-) diff --git a/arch/ia64/include/asm/kvm.h b/arch/ia64/include/asm/kvm.h index bfa86b6af7c..be3fdb89121 100644 --- a/arch/ia64/include/asm/kvm.h +++ b/arch/ia64/include/asm/kvm.h @@ -214,4 +214,11 @@ struct kvm_sregs { struct kvm_fpu { }; +struct kvm_debug_exit_arch { +}; + +/* for KVM_SET_GUEST_DEBUG */ +struct kvm_guest_debug_arch { +}; + #endif diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index 28f982045f2..de47467a0e6 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c @@ -1303,8 +1303,8 @@ int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) return -EINVAL; } -int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu, - struct kvm_debug_guest *dbg) +int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, + struct kvm_guest_debug *dbg) { return -EINVAL; } diff --git a/arch/powerpc/include/asm/kvm.h b/arch/powerpc/include/asm/kvm.h index f993e4198d5..755f1b1948c 100644 --- a/arch/powerpc/include/asm/kvm.h +++ b/arch/powerpc/include/asm/kvm.h @@ -52,4 +52,11 @@ struct kvm_fpu { __u64 fpr[32]; }; +struct kvm_debug_exit_arch { +}; + +/* for KVM_SET_GUEST_DEBUG */ +struct kvm_guest_debug_arch { +}; + #endif /* __LINUX_KVM_POWERPC_H */ diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 5f81256287f..7c2ad4017d6 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -240,8 +240,8 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) kvmppc_core_vcpu_put(vcpu); } -int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu, - struct kvm_debug_guest *dbg) +int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, + struct kvm_guest_debug *dbg) { int i; diff --git a/arch/s390/include/asm/kvm.h b/arch/s390/include/asm/kvm.h index e1f54654e3a..0b2f829f6d5 100644 --- a/arch/s390/include/asm/kvm.h +++ b/arch/s390/include/asm/kvm.h @@ -42,4 +42,11 @@ struct kvm_fpu { __u64 fprs[16]; }; +struct kvm_debug_exit_arch { +}; + +/* for KVM_SET_GUEST_DEBUG */ +struct kvm_guest_debug_arch { +}; + #endif diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 0d33893e1e8..cbfe91e1012 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -422,8 +422,8 @@ int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, return -EINVAL; /* not implemented yet */ } -int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu, - struct kvm_debug_guest *dbg) +int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, + struct kvm_guest_debug *dbg) { return -EINVAL; /* not implemented yet */ } diff --git a/arch/x86/include/asm/kvm.h b/arch/x86/include/asm/kvm.h index 886c9402ec4..32eb96c7ca2 100644 --- a/arch/x86/include/asm/kvm.h +++ b/arch/x86/include/asm/kvm.h @@ -212,6 +212,24 @@ struct kvm_pit_channel_state { __s64 count_load_time; }; +struct kvm_debug_exit_arch { + __u32 exception; + __u32 pad; + __u64 pc; + __u64 dr6; + __u64 dr7; +}; + +#define KVM_GUESTDBG_USE_SW_BP 0x00010000 +#define KVM_GUESTDBG_USE_HW_BP 0x00020000 +#define KVM_GUESTDBG_INJECT_DB 0x00040000 +#define KVM_GUESTDBG_INJECT_BP 0x00080000 + +/* for KVM_SET_GUEST_DEBUG */ +struct kvm_guest_debug_arch { + __u64 debugreg[8]; +}; + struct kvm_pit_state { struct kvm_pit_channel_state channels[3]; }; diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 53779309514..c430cd580ee 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -135,12 +135,6 @@ enum { #define KVM_NR_MEM_OBJS 40 -struct kvm_guest_debug { - int enabled; - unsigned long bp[4]; - int singlestep; -}; - /* * We don't want allocation failures within the mmu code, so we preallocate * enough memory for a single page fault in a cache. @@ -448,8 +442,7 @@ struct kvm_x86_ops { void (*vcpu_put)(struct kvm_vcpu *vcpu); int (*set_guest_debug)(struct kvm_vcpu *vcpu, - struct kvm_debug_guest *dbg); - void (*guest_debug_pre)(struct kvm_vcpu *vcpu); + struct kvm_guest_debug *dbg); int (*get_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata); int (*set_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 data); u64 (*get_segment_base)(struct kvm_vcpu *vcpu, int seg); diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 0fbbde54eca..88d9062f454 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -968,9 +968,32 @@ static void svm_set_segment(struct kvm_vcpu *vcpu, } -static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg) +static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg) { - return -EOPNOTSUPP; + int old_debug = vcpu->guest_debug; + struct vcpu_svm *svm = to_svm(vcpu); + + vcpu->guest_debug = dbg->control; + + svm->vmcb->control.intercept_exceptions &= + ~((1 << DB_VECTOR) | (1 << BP_VECTOR)); + if (vcpu->guest_debug & KVM_GUESTDBG_ENABLE) { + if (vcpu->guest_debug & + (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP)) + svm->vmcb->control.intercept_exceptions |= + 1 << DB_VECTOR; + if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP) + svm->vmcb->control.intercept_exceptions |= + 1 << BP_VECTOR; + } else + vcpu->guest_debug = 0; + + if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) + svm->vmcb->save.rflags |= X86_EFLAGS_TF | X86_EFLAGS_RF; + else if (old_debug & KVM_GUESTDBG_SINGLESTEP) + svm->vmcb->save.rflags &= ~(X86_EFLAGS_TF | X86_EFLAGS_RF); + + return 0; } static int svm_get_irq(struct kvm_vcpu *vcpu) @@ -1094,6 +1117,27 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) return kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code); } +static int db_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) +{ + if (!(svm->vcpu.guest_debug & + (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))) { + kvm_queue_exception(&svm->vcpu, DB_VECTOR); + return 1; + } + kvm_run->exit_reason = KVM_EXIT_DEBUG; + kvm_run->debug.arch.pc = svm->vmcb->save.cs.base + svm->vmcb->save.rip; + kvm_run->debug.arch.exception = DB_VECTOR; + return 0; +} + +static int bp_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) +{ + kvm_run->exit_reason = KVM_EXIT_DEBUG; + kvm_run->debug.arch.pc = svm->vmcb->save.cs.base + svm->vmcb->save.rip; + kvm_run->debug.arch.exception = BP_VECTOR; + return 0; +} + static int ud_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) { int er; @@ -2050,6 +2094,8 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm, [SVM_EXIT_WRITE_DR3] = emulate_on_interception, [SVM_EXIT_WRITE_DR5] = emulate_on_interception, [SVM_EXIT_WRITE_DR7] = emulate_on_interception, + [SVM_EXIT_EXCP_BASE + DB_VECTOR] = db_interception, + [SVM_EXIT_EXCP_BASE + BP_VECTOR] = bp_interception, [SVM_EXIT_EXCP_BASE + UD_VECTOR] = ud_interception, [SVM_EXIT_EXCP_BASE + PF_VECTOR] = pf_interception, [SVM_EXIT_EXCP_BASE + NM_VECTOR] = nm_interception, diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 1d974c1eaa7..f55690ddb3a 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -480,8 +480,13 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu) eb = (1u << PF_VECTOR) | (1u << UD_VECTOR); if (!vcpu->fpu_active) eb |= 1u << NM_VECTOR; - if (vcpu->guest_debug.enabled) - eb |= 1u << DB_VECTOR; + if (vcpu->guest_debug & KVM_GUESTDBG_ENABLE) { + if (vcpu->guest_debug & + (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP)) + eb |= 1u << DB_VECTOR; + if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP) + eb |= 1u << BP_VECTOR; + } if (vcpu->arch.rmode.active) eb = ~0; if (vm_need_ept()) @@ -1003,40 +1008,23 @@ static void vmx_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg) } } -static int set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg) +static int set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg) { - unsigned long dr7 = 0x400; - int old_singlestep; - - old_singlestep = vcpu->guest_debug.singlestep; - - vcpu->guest_debug.enabled = dbg->enabled; - if (vcpu->guest_debug.enabled) { - int i; - - dr7 |= 0x200; /* exact */ - for (i = 0; i < 4; ++i) { - if (!dbg->breakpoints[i].enabled) - continue; - vcpu->guest_debug.bp[i] = dbg->breakpoints[i].address; - dr7 |= 2 << (i*2); /* global enable */ - dr7 |= 0 << (i*4+16); /* execution breakpoint */ - } - - vcpu->guest_debug.singlestep = dbg->singlestep; - } else - vcpu->guest_debug.singlestep = 0; + int old_debug = vcpu->guest_debug; + unsigned long flags; - if (old_singlestep && !vcpu->guest_debug.singlestep) { - unsigned long flags; + vcpu->guest_debug = dbg->control; + if (!(vcpu->guest_debug & KVM_GUESTDBG_ENABLE)) + vcpu->guest_debug = 0; - flags = vmcs_readl(GUEST_RFLAGS); + flags = vmcs_readl(GUEST_RFLAGS); + if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) + flags |= X86_EFLAGS_TF | X86_EFLAGS_RF; + else if (old_debug & KVM_GUESTDBG_SINGLESTEP) flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_RF); - vmcs_writel(GUEST_RFLAGS, flags); - } + vmcs_writel(GUEST_RFLAGS, flags); update_exception_bitmap(vcpu); - vmcs_writel(GUEST_DR7, dr7); return 0; } @@ -2540,24 +2528,6 @@ static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr) return 0; } -static void kvm_guest_debug_pre(struct kvm_vcpu *vcpu) -{ - struct kvm_guest_debug *dbg = &vcpu->guest_debug; - - set_debugreg(dbg->bp[0], 0); - set_debugreg(dbg->bp[1], 1); - set_debugreg(dbg->bp[2], 2); - set_debugreg(dbg->bp[3], 3); - - if (dbg->singlestep) { - unsigned long flags; - - flags = vmcs_readl(GUEST_RFLAGS); - flags |= X86_EFLAGS_TF | X86_EFLAGS_RF; - vmcs_writel(GUEST_RFLAGS, flags); - } -} - static int handle_rmode_exception(struct kvm_vcpu *vcpu, int vec, u32 err_code) { @@ -2574,9 +2544,17 @@ static int handle_rmode_exception(struct kvm_vcpu *vcpu, * the required debugging infrastructure rework. */ switch (vec) { - case DE_VECTOR: case DB_VECTOR: + if (vcpu->guest_debug & + (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP)) + return 0; + kvm_queue_exception(vcpu, vec); + return 1; case BP_VECTOR: + if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP) + return 0; + /* fall through */ + case DE_VECTOR: case OF_VECTOR: case BR_VECTOR: case UD_VECTOR: @@ -2593,7 +2571,7 @@ static int handle_rmode_exception(struct kvm_vcpu *vcpu, static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) { struct vcpu_vmx *vmx = to_vmx(vcpu); - u32 intr_info, error_code; + u32 intr_info, ex_no, error_code; unsigned long cr2, rip; u32 vect_info; enum emulation_result er; @@ -2653,14 +2631,16 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) return 1; } - if ((intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK)) == - (INTR_TYPE_HARD_EXCEPTION | 1)) { + ex_no = intr_info & INTR_INFO_VECTOR_MASK; + if (ex_no == DB_VECTOR || ex_no == BP_VECTOR) { kvm_run->exit_reason = KVM_EXIT_DEBUG; - return 0; + kvm_run->debug.arch.pc = vmcs_readl(GUEST_CS_BASE) + rip; + kvm_run->debug.arch.exception = ex_no; + } else { + kvm_run->exit_reason = KVM_EXIT_EXCEPTION; + kvm_run->ex.exception = ex_no; + kvm_run->ex.error_code = error_code; } - kvm_run->exit_reason = KVM_EXIT_EXCEPTION; - kvm_run->ex.exception = intr_info & INTR_INFO_VECTOR_MASK; - kvm_run->ex.error_code = error_code; return 0; } @@ -3600,7 +3580,6 @@ static struct kvm_x86_ops vmx_x86_ops = { .vcpu_put = vmx_vcpu_put, .set_guest_debug = set_guest_debug, - .guest_debug_pre = kvm_guest_debug_pre, .get_msr = vmx_get_msr, .set_msr = vmx_set_msr, .get_segment_base = vmx_get_segment_base, diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index b5e9932e0f6..e990d164b56 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3005,9 +3005,6 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) goto out; } - if (vcpu->guest_debug.enabled) - kvm_x86_ops->guest_debug_pre(vcpu); - vcpu->guest_mode = 1; /* * Make sure that guest_mode assignment won't happen after @@ -3218,7 +3215,7 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) /* * Don't leak debug flags in case they were set for guest debugging */ - if (vcpu->guest_debug.enabled && vcpu->guest_debug.singlestep) + if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) regs->rflags &= ~(X86_EFLAGS_TF | X86_EFLAGS_RF); vcpu_put(vcpu); @@ -3837,8 +3834,8 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, return 0; } -int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu, - struct kvm_debug_guest *dbg) +int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, + struct kvm_guest_debug *dbg) { int r; @@ -3846,6 +3843,11 @@ int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu, r = kvm_x86_ops->set_guest_debug(vcpu, dbg); + if (dbg->control & KVM_GUESTDBG_INJECT_DB) + kvm_queue_exception(vcpu, DB_VECTOR); + else if (dbg->control & KVM_GUESTDBG_INJECT_BP) + kvm_queue_exception(vcpu, BP_VECTOR); + vcpu_put(vcpu); return r; diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 0424326f167..429a2ce202f 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h @@ -126,6 +126,7 @@ struct kvm_run { __u64 data_offset; /* relative to kvm_run start */ } io; struct { + struct kvm_debug_exit_arch arch; } debug; /* KVM_EXIT_MMIO */ struct { @@ -217,21 +218,6 @@ struct kvm_interrupt { __u32 irq; }; -struct kvm_breakpoint { - __u32 enabled; - __u32 padding; - __u64 address; -}; - -/* for KVM_DEBUG_GUEST */ -struct kvm_debug_guest { - /* int */ - __u32 enabled; - __u32 pad; - struct kvm_breakpoint breakpoints[4]; - __u32 singlestep; -}; - /* for KVM_GET_DIRTY_LOG */ struct kvm_dirty_log { __u32 slot; @@ -292,6 +278,17 @@ struct kvm_s390_interrupt { __u64 parm64; }; +/* for KVM_SET_GUEST_DEBUG */ + +#define KVM_GUESTDBG_ENABLE 0x00000001 +#define KVM_GUESTDBG_SINGLESTEP 0x00000002 + +struct kvm_guest_debug { + __u32 control; + __u32 pad; + struct kvm_guest_debug_arch arch; +}; + #define KVM_TRC_SHIFT 16 /* * kvm trace categories @@ -396,6 +393,7 @@ struct kvm_trace_rec { #ifdef __KVM_HAVE_USER_NMI #define KVM_CAP_USER_NMI 22 #endif +#define KVM_CAP_SET_GUEST_DEBUG 23 /* * ioctls for VM fds @@ -440,7 +438,8 @@ struct kvm_trace_rec { #define KVM_SET_SREGS _IOW(KVMIO, 0x84, struct kvm_sregs) #define KVM_TRANSLATE _IOWR(KVMIO, 0x85, struct kvm_translation) #define KVM_INTERRUPT _IOW(KVMIO, 0x86, struct kvm_interrupt) -#define KVM_DEBUG_GUEST _IOW(KVMIO, 0x87, struct kvm_debug_guest) +/* KVM_DEBUG_GUEST is no longer supported, use KVM_SET_GUEST_DEBUG instead */ +#define KVM_DEBUG_GUEST __KVM_DEPRECATED_DEBUG_GUEST #define KVM_GET_MSRS _IOWR(KVMIO, 0x88, struct kvm_msrs) #define KVM_SET_MSRS _IOW(KVMIO, 0x89, struct kvm_msrs) #define KVM_SET_CPUID _IOW(KVMIO, 0x8a, struct kvm_cpuid) @@ -469,6 +468,26 @@ struct kvm_trace_rec { #define KVM_SET_MP_STATE _IOW(KVMIO, 0x99, struct kvm_mp_state) /* Available with KVM_CAP_NMI */ #define KVM_NMI _IO(KVMIO, 0x9a) +/* Available with KVM_CAP_SET_GUEST_DEBUG */ +#define KVM_SET_GUEST_DEBUG _IOW(KVMIO, 0x9b, struct kvm_guest_debug) + +/* + * Deprecated interfaces + */ +struct kvm_breakpoint { + __u32 enabled; + __u32 padding; + __u64 address; +}; + +struct kvm_debug_guest { + __u32 enabled; + __u32 pad; + struct kvm_breakpoint breakpoints[4]; + __u32 singlestep; +}; + +#define __KVM_DEPRECATED_DEBUG_GUEST _IOW(KVMIO, 0x87, struct kvm_debug_guest) #define KVM_TRC_INJ_VIRQ (KVM_TRC_HANDLER + 0x02) #define KVM_TRC_REDELIVER_EVT (KVM_TRC_HANDLER + 0x03) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index bf6f703642f..e92212f970d 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -73,7 +73,7 @@ struct kvm_vcpu { struct kvm_run *run; int guest_mode; unsigned long requests; - struct kvm_guest_debug guest_debug; + unsigned long guest_debug; int fpu_active; int guest_fpu_loaded; wait_queue_head_t wq; @@ -255,8 +255,8 @@ int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu, struct kvm_mp_state *mp_state); int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, struct kvm_mp_state *mp_state); -int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu, - struct kvm_debug_guest *dbg); +int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, + struct kvm_guest_debug *dbg); int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run); int kvm_arch_init(void *opaque); diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 29a667ce35b..f83ef9c7e89 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1755,13 +1755,13 @@ out_free2: r = 0; break; } - case KVM_DEBUG_GUEST: { - struct kvm_debug_guest dbg; + case KVM_SET_GUEST_DEBUG: { + struct kvm_guest_debug dbg; r = -EFAULT; if (copy_from_user(&dbg, argp, sizeof dbg)) goto out; - r = kvm_arch_vcpu_ioctl_debug_guest(vcpu, &dbg); + r = kvm_arch_vcpu_ioctl_set_guest_debug(vcpu, &dbg); if (r) goto out; r = 0; -- GitLab From 55934c0bd3bb232a9cf902820dd63ad18ed65e49 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 15 Dec 2008 13:52:10 +0100 Subject: [PATCH 4034/4982] KVM: VMX: Allow single-stepping when uninterruptible When single-stepping over STI and MOV SS, we must clear the corresponding interruptibility bits in the guest state. Otherwise vmentry fails as it then expects bit 14 (BS) in pending debug exceptions being set, but that's not correct for the guest debugging case. Note that clearing those bits is safe as we check for interruptibility based on the original state and do not inject interrupts or NMIs if guest interruptibility was blocked. Signed-off-by: Jan Kiszka Signed-off-by: Avi Kivity --- arch/x86/kvm/vmx.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index f55690ddb3a..c776868ffe4 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -2478,6 +2478,11 @@ static void do_interrupt_requests(struct kvm_vcpu *vcpu, { vmx_update_window_states(vcpu); + if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) + vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO, + GUEST_INTR_STATE_STI | + GUEST_INTR_STATE_MOV_SS); + if (vcpu->arch.nmi_pending && !vcpu->arch.nmi_injected) { if (vcpu->arch.interrupt.pending) { enable_nmi_window(vcpu); @@ -3244,6 +3249,11 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu) vmx_update_window_states(vcpu); + if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) + vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO, + GUEST_INTR_STATE_STI | + GUEST_INTR_STATE_MOV_SS); + if (vcpu->arch.nmi_pending && !vcpu->arch.nmi_injected) { if (vcpu->arch.interrupt.pending) { enable_nmi_window(vcpu); -- GitLab From 42dbaa5a057736bf8b5c22aa42dbe975bf1080e5 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 15 Dec 2008 13:52:10 +0100 Subject: [PATCH 4035/4982] KVM: x86: Virtualize debug registers So far KVM only had basic x86 debug register support, once introduced to realize guest debugging that way. The guest itself was not able to use those registers. This patch now adds (almost) full support for guest self-debugging via hardware registers. It refactors the code, moving generic parts out of SVM (VMX was already cleaned up by the KVM_SET_GUEST_DEBUG patches), and it ensures that the registers are properly switched between host and guest. This patch also prepares debug register usage by the host. The latter will (once wired-up by the following patch) allow for hardware breakpoints/watchpoints in guest code. If this is enabled, the guest will only see faked debug registers without functionality, but with content reflecting the guest's modifications. Tested on Intel only, but SVM /should/ work as well, but who knows... Known limitations: Trapping on tss switch won't work - most probably on Intel. Credits also go to Joerg Roedel - I used his once posted debugging series as platform for this patch. Signed-off-by: Jan Kiszka Signed-off-by: Avi Kivity --- arch/x86/include/asm/kvm_host.h | 22 ++++++ arch/x86/include/asm/vmx.h | 2 +- arch/x86/kvm/kvm_svm.h | 6 -- arch/x86/kvm/svm.c | 116 ++++++++++++-------------------- arch/x86/kvm/vmx.c | 114 ++++++++++++++++++++++++++----- arch/x86/kvm/x86.c | 29 ++++++++ 6 files changed, 193 insertions(+), 96 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index c430cd580ee..0a4dab25a91 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -135,6 +135,19 @@ enum { #define KVM_NR_MEM_OBJS 40 +#define KVM_NR_DB_REGS 4 + +#define DR6_BD (1 << 13) +#define DR6_BS (1 << 14) +#define DR6_FIXED_1 0xffff0ff0 +#define DR6_VOLATILE 0x0000e00f + +#define DR7_BP_EN_MASK 0x000000ff +#define DR7_GE (1 << 9) +#define DR7_GD (1 << 13) +#define DR7_FIXED_1 0x00000400 +#define DR7_VOLATILE 0xffff23ff + /* * We don't want allocation failures within the mmu code, so we preallocate * enough memory for a single page fault in a cache. @@ -334,6 +347,15 @@ struct kvm_vcpu_arch { struct mtrr_state_type mtrr_state; u32 pat; + + int switch_db_regs; + unsigned long host_db[KVM_NR_DB_REGS]; + unsigned long host_dr6; + unsigned long host_dr7; + unsigned long db[KVM_NR_DB_REGS]; + unsigned long dr6; + unsigned long dr7; + unsigned long eff_db[KVM_NR_DB_REGS]; }; struct kvm_mem_alias { diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index 32159f034ef..498f944010b 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h @@ -312,7 +312,7 @@ enum vmcs_field { #define DEBUG_REG_ACCESS_TYPE 0x10 /* 4, direction of access */ #define TYPE_MOV_TO_DR (0 << 4) #define TYPE_MOV_FROM_DR (1 << 4) -#define DEBUG_REG_ACCESS_REG 0xf00 /* 11:8, general purpose reg. */ +#define DEBUG_REG_ACCESS_REG(eq) (((eq) >> 8) & 0xf) /* 11:8, general purpose reg. */ /* segment AR */ diff --git a/arch/x86/kvm/kvm_svm.h b/arch/x86/kvm/kvm_svm.h index 91673413d8f..ed66e4c078d 100644 --- a/arch/x86/kvm/kvm_svm.h +++ b/arch/x86/kvm/kvm_svm.h @@ -18,7 +18,6 @@ static const u32 host_save_user_msrs[] = { }; #define NR_HOST_SAVE_USER_MSRS ARRAY_SIZE(host_save_user_msrs) -#define NUM_DB_REGS 4 struct kvm_vcpu; @@ -29,16 +28,11 @@ struct vcpu_svm { struct svm_cpu_data *svm_data; uint64_t asid_generation; - unsigned long db_regs[NUM_DB_REGS]; - u64 next_rip; u64 host_user_msrs[NR_HOST_SAVE_USER_MSRS]; u64 host_gs_base; unsigned long host_cr2; - unsigned long host_db_regs[NUM_DB_REGS]; - unsigned long host_dr6; - unsigned long host_dr7; u32 *msrpm; struct vmcb *hsave; diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 88d9062f454..815f50e425a 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -38,9 +38,6 @@ MODULE_LICENSE("GPL"); #define IOPM_ALLOC_ORDER 2 #define MSRPM_ALLOC_ORDER 1 -#define DR7_GD_MASK (1 << 13) -#define DR6_BD_MASK (1 << 13) - #define SEG_TYPE_LDT 2 #define SEG_TYPE_BUSY_TSS16 3 @@ -181,32 +178,6 @@ static inline void kvm_write_cr2(unsigned long val) asm volatile ("mov %0, %%cr2" :: "r" (val)); } -static inline unsigned long read_dr6(void) -{ - unsigned long dr6; - - asm volatile ("mov %%dr6, %0" : "=r" (dr6)); - return dr6; -} - -static inline void write_dr6(unsigned long val) -{ - asm volatile ("mov %0, %%dr6" :: "r" (val)); -} - -static inline unsigned long read_dr7(void) -{ - unsigned long dr7; - - asm volatile ("mov %%dr7, %0" : "=r" (dr7)); - return dr7; -} - -static inline void write_dr7(unsigned long val) -{ - asm volatile ("mov %0, %%dr7" :: "r" (val)); -} - static inline void force_new_asid(struct kvm_vcpu *vcpu) { to_svm(vcpu)->asid_generation--; @@ -695,7 +666,6 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id) clear_page(svm->vmcb); svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT; svm->asid_generation = 0; - memset(svm->db_regs, 0, sizeof(svm->db_regs)); init_vmcb(svm); fx_init(&svm->vcpu); @@ -1035,7 +1005,29 @@ static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *svm_data) static unsigned long svm_get_dr(struct kvm_vcpu *vcpu, int dr) { - unsigned long val = to_svm(vcpu)->db_regs[dr]; + struct vcpu_svm *svm = to_svm(vcpu); + unsigned long val; + + switch (dr) { + case 0 ... 3: + val = vcpu->arch.db[dr]; + break; + case 6: + if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) + val = vcpu->arch.dr6; + else + val = svm->vmcb->save.dr6; + break; + case 7: + if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) + val = vcpu->arch.dr7; + else + val = svm->vmcb->save.dr7; + break; + default: + val = 0; + } + KVMTRACE_2D(DR_READ, vcpu, (u32)dr, (u32)val, handler); return val; } @@ -1045,33 +1037,40 @@ static void svm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long value, { struct vcpu_svm *svm = to_svm(vcpu); - *exception = 0; + KVMTRACE_2D(DR_WRITE, vcpu, (u32)dr, (u32)value, handler); - if (svm->vmcb->save.dr7 & DR7_GD_MASK) { - svm->vmcb->save.dr7 &= ~DR7_GD_MASK; - svm->vmcb->save.dr6 |= DR6_BD_MASK; - *exception = DB_VECTOR; - return; - } + *exception = 0; switch (dr) { case 0 ... 3: - svm->db_regs[dr] = value; + vcpu->arch.db[dr] = value; + if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) + vcpu->arch.eff_db[dr] = value; return; case 4 ... 5: - if (vcpu->arch.cr4 & X86_CR4_DE) { + if (vcpu->arch.cr4 & X86_CR4_DE) *exception = UD_VECTOR; + return; + case 6: + if (value & 0xffffffff00000000ULL) { + *exception = GP_VECTOR; return; } - case 7: { - if (value & ~((1ULL << 32) - 1)) { + vcpu->arch.dr6 = (value & DR6_VOLATILE) | DR6_FIXED_1; + return; + case 7: + if (value & 0xffffffff00000000ULL) { *exception = GP_VECTOR; return; } - svm->vmcb->save.dr7 = value; + vcpu->arch.dr7 = (value & DR7_VOLATILE) | DR7_FIXED_1; + if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) { + svm->vmcb->save.dr7 = vcpu->arch.dr7; + vcpu->arch.switch_db_regs = (value & DR7_BP_EN_MASK); + } return; - } default: + /* FIXME: Possible case? */ printk(KERN_DEBUG "%s: unexpected dr %u\n", __func__, dr); *exception = UD_VECTOR; @@ -2365,22 +2364,6 @@ static int svm_set_tss_addr(struct kvm *kvm, unsigned int addr) return 0; } -static void save_db_regs(unsigned long *db_regs) -{ - asm volatile ("mov %%dr0, %0" : "=r"(db_regs[0])); - asm volatile ("mov %%dr1, %0" : "=r"(db_regs[1])); - asm volatile ("mov %%dr2, %0" : "=r"(db_regs[2])); - asm volatile ("mov %%dr3, %0" : "=r"(db_regs[3])); -} - -static void load_db_regs(unsigned long *db_regs) -{ - asm volatile ("mov %0, %%dr0" : : "r"(db_regs[0])); - asm volatile ("mov %0, %%dr1" : : "r"(db_regs[1])); - asm volatile ("mov %0, %%dr2" : : "r"(db_regs[2])); - asm volatile ("mov %0, %%dr3" : : "r"(db_regs[3])); -} - static void svm_flush_tlb(struct kvm_vcpu *vcpu) { force_new_asid(vcpu); @@ -2439,20 +2422,12 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) gs_selector = kvm_read_gs(); ldt_selector = kvm_read_ldt(); svm->host_cr2 = kvm_read_cr2(); - svm->host_dr6 = read_dr6(); - svm->host_dr7 = read_dr7(); if (!is_nested(svm)) svm->vmcb->save.cr2 = vcpu->arch.cr2; /* required for live migration with NPT */ if (npt_enabled) svm->vmcb->save.cr3 = vcpu->arch.cr3; - if (svm->vmcb->save.dr7 & 0xff) { - write_dr7(0); - save_db_regs(svm->host_db_regs); - load_db_regs(svm->db_regs); - } - clgi(); local_irq_enable(); @@ -2528,16 +2503,11 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) #endif ); - if ((svm->vmcb->save.dr7 & 0xff)) - load_db_regs(svm->host_db_regs); - vcpu->arch.cr2 = svm->vmcb->save.cr2; vcpu->arch.regs[VCPU_REGS_RAX] = svm->vmcb->save.rax; vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp; vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip; - write_dr6(svm->host_dr6); - write_dr7(svm->host_dr7); kvm_write_cr2(svm->host_cr2); kvm_load_fs(fs_selector); diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index c776868ffe4..0989776ee7b 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -2311,7 +2311,6 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu) kvm_rip_write(vcpu, 0); kvm_register_write(vcpu, VCPU_REGS_RSP, 0); - /* todo: dr0 = dr1 = dr2 = dr3 = 0; dr6 = 0xffff0ff0 */ vmcs_writel(GUEST_DR7, 0x400); vmcs_writel(GUEST_GDTR_BASE, 0); @@ -2577,7 +2576,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) { struct vcpu_vmx *vmx = to_vmx(vcpu); u32 intr_info, ex_no, error_code; - unsigned long cr2, rip; + unsigned long cr2, rip, dr6; u32 vect_info; enum emulation_result er; @@ -2637,14 +2636,28 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) } ex_no = intr_info & INTR_INFO_VECTOR_MASK; - if (ex_no == DB_VECTOR || ex_no == BP_VECTOR) { + switch (ex_no) { + case DB_VECTOR: + dr6 = vmcs_readl(EXIT_QUALIFICATION); + if (!(vcpu->guest_debug & + (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))) { + vcpu->arch.dr6 = dr6 | DR6_FIXED_1; + kvm_queue_exception(vcpu, DB_VECTOR); + return 1; + } + kvm_run->debug.arch.dr6 = dr6 | DR6_FIXED_1; + kvm_run->debug.arch.dr7 = vmcs_readl(GUEST_DR7); + /* fall through */ + case BP_VECTOR: kvm_run->exit_reason = KVM_EXIT_DEBUG; kvm_run->debug.arch.pc = vmcs_readl(GUEST_CS_BASE) + rip; kvm_run->debug.arch.exception = ex_no; - } else { + break; + default: kvm_run->exit_reason = KVM_EXIT_EXCEPTION; kvm_run->ex.exception = ex_no; kvm_run->ex.error_code = error_code; + break; } return 0; } @@ -2784,21 +2797,44 @@ static int handle_dr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) unsigned long val; int dr, reg; - /* - * FIXME: this code assumes the host is debugging the guest. - * need to deal with guest debugging itself too. - */ + dr = vmcs_readl(GUEST_DR7); + if (dr & DR7_GD) { + /* + * As the vm-exit takes precedence over the debug trap, we + * need to emulate the latter, either for the host or the + * guest debugging itself. + */ + if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) { + kvm_run->debug.arch.dr6 = vcpu->arch.dr6; + kvm_run->debug.arch.dr7 = dr; + kvm_run->debug.arch.pc = + vmcs_readl(GUEST_CS_BASE) + + vmcs_readl(GUEST_RIP); + kvm_run->debug.arch.exception = DB_VECTOR; + kvm_run->exit_reason = KVM_EXIT_DEBUG; + return 0; + } else { + vcpu->arch.dr7 &= ~DR7_GD; + vcpu->arch.dr6 |= DR6_BD; + vmcs_writel(GUEST_DR7, vcpu->arch.dr7); + kvm_queue_exception(vcpu, DB_VECTOR); + return 1; + } + } + exit_qualification = vmcs_readl(EXIT_QUALIFICATION); - dr = exit_qualification & 7; - reg = (exit_qualification >> 8) & 15; - if (exit_qualification & 16) { - /* mov from dr */ + dr = exit_qualification & DEBUG_REG_ACCESS_NUM; + reg = DEBUG_REG_ACCESS_REG(exit_qualification); + if (exit_qualification & TYPE_MOV_FROM_DR) { switch (dr) { + case 0 ... 3: + val = vcpu->arch.db[dr]; + break; case 6: - val = 0xffff0ff0; + val = vcpu->arch.dr6; break; case 7: - val = 0x400; + val = vcpu->arch.dr7; break; default: val = 0; @@ -2806,7 +2842,38 @@ static int handle_dr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) kvm_register_write(vcpu, reg, val); KVMTRACE_2D(DR_READ, vcpu, (u32)dr, (u32)val, handler); } else { - /* mov to dr */ + val = vcpu->arch.regs[reg]; + switch (dr) { + case 0 ... 3: + vcpu->arch.db[dr] = val; + if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) + vcpu->arch.eff_db[dr] = val; + break; + case 4 ... 5: + if (vcpu->arch.cr4 & X86_CR4_DE) + kvm_queue_exception(vcpu, UD_VECTOR); + break; + case 6: + if (val & 0xffffffff00000000ULL) { + kvm_queue_exception(vcpu, GP_VECTOR); + break; + } + vcpu->arch.dr6 = (val & DR6_VOLATILE) | DR6_FIXED_1; + break; + case 7: + if (val & 0xffffffff00000000ULL) { + kvm_queue_exception(vcpu, GP_VECTOR); + break; + } + vcpu->arch.dr7 = (val & DR7_VOLATILE) | DR7_FIXED_1; + if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) { + vmcs_writel(GUEST_DR7, vcpu->arch.dr7); + vcpu->arch.switch_db_regs = + (val & DR7_BP_EN_MASK); + } + break; + } + KVMTRACE_2D(DR_WRITE, vcpu, (u32)dr, (u32)val, handler); } skip_emulated_instruction(vcpu); return 1; @@ -2957,7 +3024,18 @@ static int handle_task_switch(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) } tss_selector = exit_qualification; - return kvm_task_switch(vcpu, tss_selector, reason); + if (!kvm_task_switch(vcpu, tss_selector, reason)) + return 0; + + /* clear all local breakpoint enable flags */ + vmcs_writel(GUEST_DR7, vmcs_readl(GUEST_DR7) & ~55); + + /* + * TODO: What about debug traps on tss switch? + * Are we supposed to inject them and update dr6? + */ + + return 1; } static int handle_ept_violation(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) @@ -3342,6 +3420,8 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) */ vmcs_writel(HOST_CR0, read_cr0()); + set_debugreg(vcpu->arch.dr6, 6); + asm( /* Store host registers */ "push %%"R"dx; push %%"R"bp;" @@ -3436,6 +3516,8 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP)); vcpu->arch.regs_dirty = 0; + get_debugreg(vcpu->arch.dr6, 6); + vmx->idt_vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD); if (vmx->rmode.irq.pending) fixup_rmode_irq(vmx); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index e990d164b56..300bc4d42ab 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3025,10 +3025,34 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) kvm_guest_enter(); + get_debugreg(vcpu->arch.host_dr6, 6); + get_debugreg(vcpu->arch.host_dr7, 7); + if (unlikely(vcpu->arch.switch_db_regs)) { + get_debugreg(vcpu->arch.host_db[0], 0); + get_debugreg(vcpu->arch.host_db[1], 1); + get_debugreg(vcpu->arch.host_db[2], 2); + get_debugreg(vcpu->arch.host_db[3], 3); + + set_debugreg(0, 7); + set_debugreg(vcpu->arch.eff_db[0], 0); + set_debugreg(vcpu->arch.eff_db[1], 1); + set_debugreg(vcpu->arch.eff_db[2], 2); + set_debugreg(vcpu->arch.eff_db[3], 3); + } KVMTRACE_0D(VMENTRY, vcpu, entryexit); kvm_x86_ops->run(vcpu, kvm_run); + if (unlikely(vcpu->arch.switch_db_regs)) { + set_debugreg(0, 7); + set_debugreg(vcpu->arch.host_db[0], 0); + set_debugreg(vcpu->arch.host_db[1], 1); + set_debugreg(vcpu->arch.host_db[2], 2); + set_debugreg(vcpu->arch.host_db[3], 3); + } + set_debugreg(vcpu->arch.host_dr6, 6); + set_debugreg(vcpu->arch.host_dr7, 7); + vcpu->guest_mode = 0; local_irq_enable(); @@ -4035,6 +4059,11 @@ int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu) vcpu->arch.nmi_pending = false; vcpu->arch.nmi_injected = false; + vcpu->arch.switch_db_regs = 0; + memset(vcpu->arch.db, 0, sizeof(vcpu->arch.db)); + vcpu->arch.dr6 = DR6_FIXED_1; + vcpu->arch.dr7 = DR7_FIXED_1; + return kvm_x86_ops->vcpu_reset(vcpu); } -- GitLab From ae675ef01cd86014acf8da5dee87876b71122495 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 15 Dec 2008 13:52:10 +0100 Subject: [PATCH 4036/4982] KVM: x86: Wire-up hardware breakpoints for guest debugging Add the remaining bits to make use of debug registers also for guest debugging, thus enabling the use of hardware breakpoints and watchpoints. Signed-off-by: Jan Kiszka Signed-off-by: Avi Kivity --- arch/x86/kvm/svm.c | 5 +++++ arch/x86/kvm/vmx.c | 5 +++++ arch/x86/kvm/x86.c | 14 +++++++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 815f50e425a..b3a7a314d55 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -958,6 +958,11 @@ static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg) } else vcpu->guest_debug = 0; + if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) + svm->vmcb->save.dr7 = dbg->arch.debugreg[7]; + else + svm->vmcb->save.dr7 = vcpu->arch.dr7; + if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) svm->vmcb->save.rflags |= X86_EFLAGS_TF | X86_EFLAGS_RF; else if (old_debug & KVM_GUESTDBG_SINGLESTEP) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 0989776ee7b..cee81c9a665 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -1017,6 +1017,11 @@ static int set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg) if (!(vcpu->guest_debug & KVM_GUESTDBG_ENABLE)) vcpu->guest_debug = 0; + if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) + vmcs_writel(GUEST_DR7, dbg->arch.debugreg[7]); + else + vmcs_writel(GUEST_DR7, vcpu->arch.dr7); + flags = vmcs_readl(GUEST_RFLAGS); if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) flags |= X86_EFLAGS_TF | X86_EFLAGS_RF; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 300bc4d42ab..2477e87b2f8 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3861,10 +3861,22 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg) { - int r; + int i, r; vcpu_load(vcpu); + if ((dbg->control & (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP)) == + (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP)) { + for (i = 0; i < KVM_NR_DB_REGS; ++i) + vcpu->arch.eff_db[i] = dbg->arch.debugreg[i]; + vcpu->arch.switch_db_regs = + (dbg->arch.debugreg[7] & DR7_BP_EN_MASK); + } else { + for (i = 0; i < KVM_NR_DB_REGS; i++) + vcpu->arch.eff_db[i] = vcpu->arch.db[i]; + vcpu->arch.switch_db_regs = (vcpu->arch.dr7 & DR7_BP_EN_MASK); + } + r = kvm_x86_ops->set_guest_debug(vcpu, dbg); if (dbg->control & KVM_GUESTDBG_INJECT_DB) -- GitLab From e9a999fe1feaddb71bffbacbbd68e0da8ca8b50b Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 18 Dec 2008 12:17:51 +0100 Subject: [PATCH 4037/4982] KVM: ia64: stack get/restore patch Implement KVM_IA64_VCPU_[GS]ET_STACK ioctl calls. This is required for live migrations. Patch is based on previous implementation that was part of old GET/SET_REGS ioctl calls. Signed-off-by: Jes Sorensen Signed-off-by: Avi Kivity --- arch/ia64/include/asm/kvm.h | 7 +++ arch/ia64/include/asm/kvm_host.h | 6 ++- arch/ia64/kvm/kvm-ia64.c | 92 ++++++++++++++++++++++++++++++-- include/linux/kvm.h | 3 ++ 4 files changed, 104 insertions(+), 4 deletions(-) diff --git a/arch/ia64/include/asm/kvm.h b/arch/ia64/include/asm/kvm.h index be3fdb89121..b5145784233 100644 --- a/arch/ia64/include/asm/kvm.h +++ b/arch/ia64/include/asm/kvm.h @@ -214,6 +214,13 @@ struct kvm_sregs { struct kvm_fpu { }; +#define KVM_IA64_VCPU_STACK_SHIFT 16 +#define KVM_IA64_VCPU_STACK_SIZE (1UL << KVM_IA64_VCPU_STACK_SHIFT) + +struct kvm_ia64_vcpu_stack { + unsigned char stack[KVM_IA64_VCPU_STACK_SIZE]; +}; + struct kvm_debug_exit_arch { }; diff --git a/arch/ia64/include/asm/kvm_host.h b/arch/ia64/include/asm/kvm_host.h index 34866366165..7da0c096322 100644 --- a/arch/ia64/include/asm/kvm_host.h +++ b/arch/ia64/include/asm/kvm_host.h @@ -112,7 +112,11 @@ #define VCPU_STRUCT_SHIFT 16 #define VCPU_STRUCT_SIZE (__IA64_UL_CONST(1) << VCPU_STRUCT_SHIFT) -#define KVM_STK_OFFSET VCPU_STRUCT_SIZE +/* + * This must match KVM_IA64_VCPU_STACK_{SHIFT,SIZE} arch/ia64/include/asm/kvm.h + */ +#define KVM_STK_SHIFT 16 +#define KVM_STK_OFFSET (__IA64_UL_CONST(1)<< KVM_STK_SHIFT) #define KVM_VM_STRUCT_SHIFT 19 #define KVM_VM_STRUCT_SIZE (__IA64_UL_CONST(1) << KVM_VM_STRUCT_SHIFT) diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index de47467a0e6..1477f91617a 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c @@ -1421,6 +1421,23 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) return 0; } +int kvm_arch_vcpu_ioctl_get_stack(struct kvm_vcpu *vcpu, + struct kvm_ia64_vcpu_stack *stack) +{ + memcpy(stack, vcpu, sizeof(struct kvm_ia64_vcpu_stack)); + return 0; +} + +int kvm_arch_vcpu_ioctl_set_stack(struct kvm_vcpu *vcpu, + struct kvm_ia64_vcpu_stack *stack) +{ + memcpy(vcpu + 1, &stack->stack[0] + sizeof(struct kvm_vcpu), + sizeof(struct kvm_ia64_vcpu_stack) - sizeof(struct kvm_vcpu)); + + vcpu->arch.exit_data = ((struct kvm_vcpu *)stack)->arch.exit_data; + return 0; +} + void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) { @@ -1430,9 +1447,78 @@ void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) long kvm_arch_vcpu_ioctl(struct file *filp, - unsigned int ioctl, unsigned long arg) + unsigned int ioctl, unsigned long arg) { - return -EINVAL; + struct kvm_vcpu *vcpu = filp->private_data; + void __user *argp = (void __user *)arg; + struct kvm_ia64_vcpu_stack *stack = NULL; + long r; + + switch (ioctl) { + case KVM_IA64_VCPU_GET_STACK: { + struct kvm_ia64_vcpu_stack __user *user_stack; + void __user *first_p = argp; + + r = -EFAULT; + if (copy_from_user(&user_stack, first_p, sizeof(void *))) + goto out; + + if (!access_ok(VERIFY_WRITE, user_stack, + sizeof(struct kvm_ia64_vcpu_stack))) { + printk(KERN_INFO "KVM_IA64_VCPU_GET_STACK: " + "Illegal user destination address for stack\n"); + goto out; + } + stack = kzalloc(sizeof(struct kvm_ia64_vcpu_stack), GFP_KERNEL); + if (!stack) { + r = -ENOMEM; + goto out; + } + + r = kvm_arch_vcpu_ioctl_get_stack(vcpu, stack); + if (r) + goto out; + + if (copy_to_user(user_stack, stack, + sizeof(struct kvm_ia64_vcpu_stack))) + goto out; + + break; + } + case KVM_IA64_VCPU_SET_STACK: { + struct kvm_ia64_vcpu_stack __user *user_stack; + void __user *first_p = argp; + + r = -EFAULT; + if (copy_from_user(&user_stack, first_p, sizeof(void *))) + goto out; + + if (!access_ok(VERIFY_READ, user_stack, + sizeof(struct kvm_ia64_vcpu_stack))) { + printk(KERN_INFO "KVM_IA64_VCPU_SET_STACK: " + "Illegal user address for stack\n"); + goto out; + } + stack = kmalloc(sizeof(struct kvm_ia64_vcpu_stack), GFP_KERNEL); + if (!stack) { + r = -ENOMEM; + goto out; + } + if (copy_from_user(stack, user_stack, + sizeof(struct kvm_ia64_vcpu_stack))) + goto out; + + r = kvm_arch_vcpu_ioctl_set_stack(vcpu, stack); + break; + } + + default: + r = -EINVAL; + } + +out: + kfree(stack); + return r; } int kvm_arch_set_memory_region(struct kvm *kvm, @@ -1472,7 +1558,7 @@ void kvm_arch_flush_shadow(struct kvm *kvm) } long kvm_arch_dev_ioctl(struct file *filp, - unsigned int ioctl, unsigned long arg) + unsigned int ioctl, unsigned long arg) { return -EINVAL; } diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 429a2ce202f..28582fcd3f7 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h @@ -489,6 +489,9 @@ struct kvm_debug_guest { #define __KVM_DEPRECATED_DEBUG_GUEST _IOW(KVMIO, 0x87, struct kvm_debug_guest) +#define KVM_IA64_VCPU_GET_STACK _IOR(KVMIO, 0x9a, void *) +#define KVM_IA64_VCPU_SET_STACK _IOW(KVMIO, 0x9b, void *) + #define KVM_TRC_INJ_VIRQ (KVM_TRC_HANDLER + 0x02) #define KVM_TRC_REDELIVER_EVT (KVM_TRC_HANDLER + 0x03) #define KVM_TRC_PEND_INTR (KVM_TRC_HANDLER + 0x04) -- GitLab From 989c0f0ed56468a4aa48711cef5acf122a40d1dd Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Thu, 18 Dec 2008 12:33:18 +0100 Subject: [PATCH 4038/4982] KVM: Remove old kvm_guest_debug structs Remove the remaining arch fragments of the old guest debug interface that now break non-x86 builds. Signed-off-by: Jan Kiszka Signed-off-by: Avi Kivity --- arch/ia64/include/asm/kvm_host.h | 2 -- arch/powerpc/include/asm/kvm_host.h | 6 ------ arch/s390/include/asm/kvm_host.h | 3 --- 3 files changed, 11 deletions(-) diff --git a/arch/ia64/include/asm/kvm_host.h b/arch/ia64/include/asm/kvm_host.h index 7da0c096322..46f8b0eb568 100644 --- a/arch/ia64/include/asm/kvm_host.h +++ b/arch/ia64/include/asm/kvm_host.h @@ -239,8 +239,6 @@ struct kvm_vm_data { struct kvm; struct kvm_vcpu; -struct kvm_guest_debug{ -}; struct kvm_mmio_req { uint64_t addr; /* physical address */ diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index c1e436fe773..a22600537a8 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -200,10 +200,4 @@ struct kvm_vcpu_arch { unsigned long pending_exceptions; }; -struct kvm_guest_debug { - int enabled; - unsigned long bp[4]; - int singlestep; -}; - #endif /* __POWERPC_KVM_HOST_H__ */ diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index 3c55e4107dc..c6e674f5fca 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h @@ -21,9 +21,6 @@ /* memory slots that does not exposed to userspace */ #define KVM_PRIVATE_MEM_SLOTS 4 -struct kvm_guest_debug { -}; - struct sca_entry { atomic_t scn; __u64 reserved; -- GitLab From 22ccb14203d59a8bcf6f3fea76b3594d710569fa Mon Sep 17 00:00:00 2001 From: Xiantao Zhang Date: Thu, 18 Dec 2008 10:23:58 +0800 Subject: [PATCH 4039/4982] KVM: ia64: Code cleanup Remove some unnecessary blank lines to accord with Kernel's coding style. Also remove vcpu_get_itir_on_fault due to no reference to it. Signed-off-by: Xiantao Zhang Signed-off-by: Avi Kivity --- arch/ia64/kvm/process.c | 15 --------------- arch/ia64/kvm/vcpu.c | 39 ++------------------------------------- arch/ia64/kvm/vtlb.c | 5 ----- 3 files changed, 2 insertions(+), 57 deletions(-) diff --git a/arch/ia64/kvm/process.c b/arch/ia64/kvm/process.c index 230eae482f3..f9c9504144f 100644 --- a/arch/ia64/kvm/process.c +++ b/arch/ia64/kvm/process.c @@ -167,7 +167,6 @@ static u64 vcpu_get_itir_on_fault(struct kvm_vcpu *vcpu, u64 ifa) return (rr1.val); } - /* * Set vIFA & vITIR & vIHA, when vPSR.ic =1 * Parameter: @@ -222,8 +221,6 @@ void itlb_fault(struct kvm_vcpu *vcpu, u64 vadr) inject_guest_interruption(vcpu, IA64_INST_TLB_VECTOR); } - - /* * Data Nested TLB Fault * @ Data Nested TLB Vector @@ -245,7 +242,6 @@ void alt_dtlb(struct kvm_vcpu *vcpu, u64 vadr) inject_guest_interruption(vcpu, IA64_ALT_DATA_TLB_VECTOR); } - /* * Data TLB Fault * @ Data TLB vector @@ -265,8 +261,6 @@ static void _vhpt_fault(struct kvm_vcpu *vcpu, u64 vadr) /* If vPSR.ic, IFA, ITIR, IHA*/ set_ifa_itir_iha(vcpu, vadr, 1, 1, 1); inject_guest_interruption(vcpu, IA64_VHPT_TRANS_VECTOR); - - } /* @@ -279,7 +273,6 @@ void ivhpt_fault(struct kvm_vcpu *vcpu, u64 vadr) _vhpt_fault(vcpu, vadr); } - /* * VHPT Data Fault * @ VHPT Translation vector @@ -290,8 +283,6 @@ void dvhpt_fault(struct kvm_vcpu *vcpu, u64 vadr) _vhpt_fault(vcpu, vadr); } - - /* * Deal with: * General Exception vector @@ -301,7 +292,6 @@ void _general_exception(struct kvm_vcpu *vcpu) inject_guest_interruption(vcpu, IA64_GENEX_VECTOR); } - /* * Illegal Operation Fault * @ General Exception Vector @@ -419,19 +409,16 @@ static void __page_not_present(struct kvm_vcpu *vcpu, u64 vadr) inject_guest_interruption(vcpu, IA64_PAGE_NOT_PRESENT_VECTOR); } - void data_page_not_present(struct kvm_vcpu *vcpu, u64 vadr) { __page_not_present(vcpu, vadr); } - void inst_page_not_present(struct kvm_vcpu *vcpu, u64 vadr) { __page_not_present(vcpu, vadr); } - /* Deal with * Data access rights vector */ @@ -703,7 +690,6 @@ void vhpi_detection(struct kvm_vcpu *vcpu) } } - void leave_hypervisor_tail(void) { struct kvm_vcpu *v = current_vcpu; @@ -737,7 +723,6 @@ void leave_hypervisor_tail(void) } } - static inline void handle_lds(struct kvm_pt_regs *regs) { regs->cr_ipsr |= IA64_PSR_ED; diff --git a/arch/ia64/kvm/vcpu.c b/arch/ia64/kvm/vcpu.c index ecd526b5532..4d8be4c252f 100644 --- a/arch/ia64/kvm/vcpu.c +++ b/arch/ia64/kvm/vcpu.c @@ -112,7 +112,6 @@ void switch_to_physical_rid(struct kvm_vcpu *vcpu) return; } - void switch_to_virtual_rid(struct kvm_vcpu *vcpu) { unsigned long psr; @@ -166,8 +165,6 @@ void switch_mm_mode(struct kvm_vcpu *vcpu, struct ia64_psr old_psr, return; } - - /* * In physical mode, insert tc/tr for region 0 and 4 uses * RID[0] and RID[4] which is for physical mode emulation. @@ -269,7 +266,6 @@ static inline unsigned long fph_index(struct kvm_pt_regs *regs, return rotate_reg(96, rrb_fr, (regnum - IA64_FIRST_ROTATING_FR)); } - /* * The inverse of the above: given bspstore and the number of * registers, calculate ar.bsp. @@ -1039,8 +1035,6 @@ u64 vcpu_tak(struct kvm_vcpu *vcpu, u64 vadr) return key; } - - void kvm_thash(struct kvm_vcpu *vcpu, INST64 inst) { unsigned long thash, vadr; @@ -1050,7 +1044,6 @@ void kvm_thash(struct kvm_vcpu *vcpu, INST64 inst) vcpu_set_gr(vcpu, inst.M46.r1, thash, 0); } - void kvm_ttag(struct kvm_vcpu *vcpu, INST64 inst) { unsigned long tag, vadr; @@ -1131,7 +1124,6 @@ int vcpu_tpa(struct kvm_vcpu *vcpu, u64 vadr, u64 *padr) return IA64_NO_FAULT; } - int kvm_tpa(struct kvm_vcpu *vcpu, INST64 inst) { unsigned long r1, r3; @@ -1154,7 +1146,6 @@ void kvm_tak(struct kvm_vcpu *vcpu, INST64 inst) vcpu_set_gr(vcpu, inst.M46.r1, r1, 0); } - /************************************ * Insert/Purge translation register/cache ************************************/ @@ -1385,7 +1376,6 @@ void kvm_mov_to_ar_reg(struct kvm_vcpu *vcpu, INST64 inst) vcpu_set_itc(vcpu, r2); } - void kvm_mov_from_ar_reg(struct kvm_vcpu *vcpu, INST64 inst) { unsigned long r1; @@ -1393,8 +1383,9 @@ void kvm_mov_from_ar_reg(struct kvm_vcpu *vcpu, INST64 inst) r1 = vcpu_get_itc(vcpu); vcpu_set_gr(vcpu, inst.M31.r1, r1, 0); } + /************************************************************************** - struct kvm_vcpu*protection key register access routines + struct kvm_vcpu protection key register access routines **************************************************************************/ unsigned long vcpu_get_pkr(struct kvm_vcpu *vcpu, unsigned long reg) @@ -1407,20 +1398,6 @@ void vcpu_set_pkr(struct kvm_vcpu *vcpu, unsigned long reg, unsigned long val) ia64_set_pkr(reg, val); } - -unsigned long vcpu_get_itir_on_fault(struct kvm_vcpu *vcpu, unsigned long ifa) -{ - union ia64_rr rr, rr1; - - rr.val = vcpu_get_rr(vcpu, ifa); - rr1.val = 0; - rr1.ps = rr.ps; - rr1.rid = rr.rid; - return (rr1.val); -} - - - /******************************** * Moves to privileged registers ********************************/ @@ -1464,8 +1441,6 @@ unsigned long vcpu_set_rr(struct kvm_vcpu *vcpu, unsigned long reg, return (IA64_NO_FAULT); } - - void kvm_mov_to_rr(struct kvm_vcpu *vcpu, INST64 inst) { unsigned long r3, r2; @@ -1510,8 +1485,6 @@ void kvm_mov_to_pkr(struct kvm_vcpu *vcpu, INST64 inst) vcpu_set_pkr(vcpu, r3, r2); } - - void kvm_mov_from_rr(struct kvm_vcpu *vcpu, INST64 inst) { unsigned long r3, r1; @@ -1557,7 +1530,6 @@ void kvm_mov_from_pmc(struct kvm_vcpu *vcpu, INST64 inst) vcpu_set_gr(vcpu, inst.M43.r1, r1, 0); } - unsigned long vcpu_get_cpuid(struct kvm_vcpu *vcpu, unsigned long reg) { /* FIXME: This could get called as a result of a rsvd-reg fault */ @@ -1609,7 +1581,6 @@ unsigned long kvm_mov_to_cr(struct kvm_vcpu *vcpu, INST64 inst) return 0; } - unsigned long kvm_mov_from_cr(struct kvm_vcpu *vcpu, INST64 inst) { unsigned long tgt = inst.M33.r1; @@ -1633,8 +1604,6 @@ unsigned long kvm_mov_from_cr(struct kvm_vcpu *vcpu, INST64 inst) return 0; } - - void vcpu_set_psr(struct kvm_vcpu *vcpu, unsigned long val) { @@ -1776,9 +1745,6 @@ void vcpu_bsw1(struct kvm_vcpu *vcpu) } } - - - void vcpu_rfi(struct kvm_vcpu *vcpu) { unsigned long ifs, psr; @@ -1796,7 +1762,6 @@ void vcpu_rfi(struct kvm_vcpu *vcpu) regs->cr_iip = VCPU(vcpu, iip); } - /* VPSR can't keep track of below bits of guest PSR This function gets guest PSR diff --git a/arch/ia64/kvm/vtlb.c b/arch/ia64/kvm/vtlb.c index 6b6307a3bd5..ac94867f826 100644 --- a/arch/ia64/kvm/vtlb.c +++ b/arch/ia64/kvm/vtlb.c @@ -509,7 +509,6 @@ void thash_purge_all(struct kvm_vcpu *v) local_flush_tlb_all(); } - /* * Lookup the hash table and its collision chain to find an entry * covering this address rid:va or the entry. @@ -517,7 +516,6 @@ void thash_purge_all(struct kvm_vcpu *v) * INPUT: * in: TLB format for both VHPT & TLB. */ - struct thash_data *vtlb_lookup(struct kvm_vcpu *v, u64 va, int is_data) { struct thash_data *cch; @@ -547,7 +545,6 @@ struct thash_data *vtlb_lookup(struct kvm_vcpu *v, u64 va, int is_data) return NULL; } - /* * Initialize internal control data before service. */ @@ -589,7 +586,6 @@ u64 kvm_gpa_to_mpa(u64 gpa) return (pte >> PAGE_SHIFT << PAGE_SHIFT) | (gpa & ~PAGE_MASK); } - /* * Fetch guest bundle code. * INPUT: @@ -631,7 +627,6 @@ int fetch_code(struct kvm_vcpu *vcpu, u64 gip, IA64_BUNDLE *pbundle) return IA64_NO_FAULT; } - void kvm_init_vhpt(struct kvm_vcpu *v) { v->arch.vhpt.num = VHPT_NUM_ENTRIES; -- GitLab From a770f6f28b1a9287189f3dc8333eb694d9a2f0ab Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 21 Dec 2008 19:20:09 +0200 Subject: [PATCH 4040/4982] KVM: MMU: Inherit a shadow page's guest level count from vcpu setup Instead of "calculating" it on every shadow page allocation, set it once when switching modes, and copy it when allocating pages. This doesn't buy us much, but sets up the stage for inheriting more information related to the mmu setup. Signed-off-by: Avi Kivity --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/mmu.c | 17 +++++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 0a4dab25a91..28f875f28f5 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -244,6 +244,7 @@ struct kvm_mmu { hpa_t root_hpa; int root_level; int shadow_root_level; + union kvm_mmu_page_role base_role; u64 *pae_root; }; diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 2d4477c7147..f15023c11fe 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -1204,8 +1204,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp; struct hlist_node *node, *tmp; - role.word = 0; - role.glevels = vcpu->arch.mmu.root_level; + role = vcpu->arch.mmu.base_role; role.level = level; role.metaphysical = metaphysical; role.access = access; @@ -2251,17 +2250,23 @@ static int init_kvm_tdp_mmu(struct kvm_vcpu *vcpu) static int init_kvm_softmmu(struct kvm_vcpu *vcpu) { + int r; + ASSERT(vcpu); ASSERT(!VALID_PAGE(vcpu->arch.mmu.root_hpa)); if (!is_paging(vcpu)) - return nonpaging_init_context(vcpu); + r = nonpaging_init_context(vcpu); else if (is_long_mode(vcpu)) - return paging64_init_context(vcpu); + r = paging64_init_context(vcpu); else if (is_pae(vcpu)) - return paging32E_init_context(vcpu); + r = paging32E_init_context(vcpu); else - return paging32_init_context(vcpu); + r = paging32_init_context(vcpu); + + vcpu->arch.mmu.base_role.glevels = vcpu->arch.mmu.root_level; + + return r; } static int init_kvm_mmu(struct kvm_vcpu *vcpu) -- GitLab From 2f0b3d60b2c43aef7cd10169c425c052169c622a Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 21 Dec 2008 19:27:36 +0200 Subject: [PATCH 4041/4982] KVM: MMU: Segregate mmu pages created with different cr4.pge settings Don't allow a vcpu with cr4.pge cleared to use a shadow page created with cr4.pge set; this might cause a cr3 switch not to sync ptes that have the global bit set (the global bit has no effect if !cr4.pge). This can only occur on smp with different cr4.pge settings for different vcpus (since a cr4 change will resync the shadow ptes), but there's no cost to being correct here. Signed-off-by: Avi Kivity --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/x86.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 28f875f28f5..c2a01d0513f 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -183,6 +183,7 @@ union kvm_mmu_page_role { unsigned metaphysical:1; unsigned access:3; unsigned invalid:1; + unsigned cr4_pge:1; }; }; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 2477e87b2f8..873602b5edf 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -364,6 +364,7 @@ void kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) } kvm_x86_ops->set_cr4(vcpu, cr4); vcpu->arch.cr4 = cr4; + vcpu->arch.mmu.base_role.cr4_pge = !!(cr4 & X86_CR4_PGE); kvm_mmu_sync_global(vcpu); kvm_mmu_reset_context(vcpu); } -- GitLab From e2078318042569682d0496cfd7bd962a766e82b1 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 21 Dec 2008 19:36:59 +0200 Subject: [PATCH 4042/4982] KVM: MMU: Initialize a shadow page's global attribute from cr4.pge If cr4.pge is cleared, we ought to treat any ptes in the page as non-global. This allows us to remove the check from set_spte(). Signed-off-by: Avi Kivity --- arch/x86/kvm/mmu.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index f15023c11fe..5f03ec324e3 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -797,7 +797,6 @@ static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu, ASSERT(is_empty_shadow_page(sp->spt)); bitmap_zero(sp->slot_bitmap, KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS); sp->multimapped = 0; - sp->global = 1; sp->parent_pte = parent_pte; --vcpu->kvm->arch.n_free_mmu_pages; return sp; @@ -1241,6 +1240,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, pgprintk("%s: adding gfn %lx role %x\n", __func__, gfn, role.word); sp->gfn = gfn; sp->role = role; + sp->global = role.cr4_pge; hlist_add_head(&sp->hash_link, bucket); if (!metaphysical) { if (rmap_write_protect(vcpu->kvm, gfn)) @@ -1668,8 +1668,6 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, u64 mt_mask = shadow_mt_mask; struct kvm_mmu_page *sp = page_header(__pa(shadow_pte)); - if (!(vcpu->arch.cr4 & X86_CR4_PGE)) - global = 0; if (!global && sp->global) { sp->global = 0; if (sp->unsync) { -- GitLab From 2b3d2a206037b1471de6a6dc51427af034cfdb47 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 23 Dec 2008 19:46:01 +0200 Subject: [PATCH 4043/4982] KVM: Fix vmload and friends misinterpreted as lidt The AMD SVM instruction family all overload the 0f 01 /3 opcode, further multiplexing on the three r/m bits. But the code decided that anything that isn't a vmmcall must be an lidt (which shares the 0f 01 /3 opcode, for the case that mod = 3). Fix by aborting emulation if this isn't a vmmcall. Signed-off-by: Avi Kivity --- arch/x86/kvm/x86_emulate.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/x86_emulate.c b/arch/x86/kvm/x86_emulate.c index d174db7a337..54fb09889a8 100644 --- a/arch/x86/kvm/x86_emulate.c +++ b/arch/x86/kvm/x86_emulate.c @@ -1908,11 +1908,16 @@ twobyte_insn: c->dst.type = OP_NONE; break; case 3: /* lidt/vmmcall */ - if (c->modrm_mod == 3 && c->modrm_rm == 1) { - rc = kvm_fix_hypercall(ctxt->vcpu); - if (rc) - goto done; - kvm_emulate_hypercall(ctxt->vcpu); + if (c->modrm_mod == 3) { + switch (c->modrm_rm) { + case 1: + rc = kvm_fix_hypercall(ctxt->vcpu); + if (rc) + goto done; + break; + default: + goto cannot_emulate; + } } else { rc = read_descriptor(ctxt, ops, c->src.ptr, &size, &address, -- GitLab From 971cc3dcbc0e020b82f568e61a47b72be03307dd Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 19 Dec 2008 18:13:54 +0100 Subject: [PATCH 4044/4982] KVM: Advertise guest debug capability per-arch Limit KVM_CAP_SET_GUEST_DEBUG only to those archs (currently x86) that support it. This simplifies user space stub implementations. Signed-off-by: Jan Kiszka Signed-off-by: Avi Kivity --- include/linux/kvm.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 28582fcd3f7..11e3e6197c8 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h @@ -393,7 +393,9 @@ struct kvm_trace_rec { #ifdef __KVM_HAVE_USER_NMI #define KVM_CAP_USER_NMI 22 #endif +#if defined(CONFIG_X86) #define KVM_CAP_SET_GUEST_DEBUG 23 +#endif /* * ioctls for VM fds -- GitLab From 2d11123a77e54d5cea262c958e8498f4a08bce3d Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Thu, 25 Dec 2008 14:39:47 +0200 Subject: [PATCH 4045/4982] KVM: MMU: Add for_each_shadow_entry(), a simpler alternative to walk_shadow() Using a for_each loop style removes the need to write callback and nasty casts. Implement the walk_shadow() using the for_each_shadow_entry(). Signed-off-by: Avi Kivity --- arch/x86/kvm/mmu.c | 69 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 5f03ec324e3..c669f2af1d1 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -150,6 +150,20 @@ struct kvm_shadow_walk { u64 addr, u64 *spte, int level); }; +struct kvm_shadow_walk_iterator { + u64 addr; + hpa_t shadow_addr; + int level; + u64 *sptep; + unsigned index; +}; + +#define for_each_shadow_entry(_vcpu, _addr, _walker) \ + for (shadow_walk_init(&(_walker), _vcpu, _addr); \ + shadow_walk_okay(&(_walker)); \ + shadow_walk_next(&(_walker))) + + struct kvm_unsync_walk { int (*entry) (struct kvm_mmu_page *sp, struct kvm_unsync_walk *walk); }; @@ -1254,33 +1268,48 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, return sp; } +static void shadow_walk_init(struct kvm_shadow_walk_iterator *iterator, + struct kvm_vcpu *vcpu, u64 addr) +{ + iterator->addr = addr; + iterator->shadow_addr = vcpu->arch.mmu.root_hpa; + iterator->level = vcpu->arch.mmu.shadow_root_level; + if (iterator->level == PT32E_ROOT_LEVEL) { + iterator->shadow_addr + = vcpu->arch.mmu.pae_root[(addr >> 30) & 3]; + iterator->shadow_addr &= PT64_BASE_ADDR_MASK; + --iterator->level; + if (!iterator->shadow_addr) + iterator->level = 0; + } +} + +static bool shadow_walk_okay(struct kvm_shadow_walk_iterator *iterator) +{ + if (iterator->level < PT_PAGE_TABLE_LEVEL) + return false; + iterator->index = SHADOW_PT_INDEX(iterator->addr, iterator->level); + iterator->sptep = ((u64 *)__va(iterator->shadow_addr)) + iterator->index; + return true; +} + +static void shadow_walk_next(struct kvm_shadow_walk_iterator *iterator) +{ + iterator->shadow_addr = *iterator->sptep & PT64_BASE_ADDR_MASK; + --iterator->level; +} + static int walk_shadow(struct kvm_shadow_walk *walker, struct kvm_vcpu *vcpu, u64 addr) { - hpa_t shadow_addr; - int level; + struct kvm_shadow_walk_iterator iterator; int r; - u64 *sptep; - unsigned index; - - shadow_addr = vcpu->arch.mmu.root_hpa; - level = vcpu->arch.mmu.shadow_root_level; - if (level == PT32E_ROOT_LEVEL) { - shadow_addr = vcpu->arch.mmu.pae_root[(addr >> 30) & 3]; - shadow_addr &= PT64_BASE_ADDR_MASK; - if (!shadow_addr) - return 1; - --level; - } - while (level >= PT_PAGE_TABLE_LEVEL) { - index = SHADOW_PT_INDEX(addr, level); - sptep = ((u64 *)__va(shadow_addr)) + index; - r = walker->entry(walker, vcpu, addr, sptep, level); + for_each_shadow_entry(vcpu, addr, iterator) { + r = walker->entry(walker, vcpu, addr, + iterator.sptep, iterator.level); if (r) return r; - shadow_addr = *sptep & PT64_BASE_ADDR_MASK; - --level; } return 0; } -- GitLab From 9f652d21c3f887075a33abae85bf53fec64e67b1 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Thu, 25 Dec 2008 14:54:25 +0200 Subject: [PATCH 4046/4982] KVM: MMU: Use for_each_shadow_entry() in __direct_map() Eliminating a callback and a useless structure. Signed-off-by: Avi Kivity --- arch/x86/kvm/mmu.c | 83 ++++++++++++++++------------------------------ 1 file changed, 29 insertions(+), 54 deletions(-) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index c669f2af1d1..a25e1adb5cf 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -1846,67 +1846,42 @@ static void nonpaging_new_cr3(struct kvm_vcpu *vcpu) { } -struct direct_shadow_walk { - struct kvm_shadow_walk walker; - pfn_t pfn; - int write; - int largepage; - int pt_write; -}; - -static int direct_map_entry(struct kvm_shadow_walk *_walk, - struct kvm_vcpu *vcpu, - u64 addr, u64 *sptep, int level) +static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write, + int largepage, gfn_t gfn, pfn_t pfn) { - struct direct_shadow_walk *walk = - container_of(_walk, struct direct_shadow_walk, walker); + struct kvm_shadow_walk_iterator iterator; struct kvm_mmu_page *sp; + int pt_write = 0; gfn_t pseudo_gfn; - gfn_t gfn = addr >> PAGE_SHIFT; - - if (level == PT_PAGE_TABLE_LEVEL - || (walk->largepage && level == PT_DIRECTORY_LEVEL)) { - mmu_set_spte(vcpu, sptep, ACC_ALL, ACC_ALL, - 0, walk->write, 1, &walk->pt_write, - walk->largepage, 0, gfn, walk->pfn, false); - ++vcpu->stat.pf_fixed; - return 1; - } - if (*sptep == shadow_trap_nonpresent_pte) { - pseudo_gfn = (addr & PT64_DIR_BASE_ADDR_MASK) >> PAGE_SHIFT; - sp = kvm_mmu_get_page(vcpu, pseudo_gfn, (gva_t)addr, level - 1, - 1, ACC_ALL, sptep); - if (!sp) { - pgprintk("nonpaging_map: ENOMEM\n"); - kvm_release_pfn_clean(walk->pfn); - return -ENOMEM; + for_each_shadow_entry(vcpu, (u64)gfn << PAGE_SHIFT, iterator) { + if (iterator.level == PT_PAGE_TABLE_LEVEL + || (largepage && iterator.level == PT_DIRECTORY_LEVEL)) { + mmu_set_spte(vcpu, iterator.sptep, ACC_ALL, ACC_ALL, + 0, write, 1, &pt_write, + largepage, 0, gfn, pfn, false); + ++vcpu->stat.pf_fixed; + break; } - set_shadow_pte(sptep, - __pa(sp->spt) - | PT_PRESENT_MASK | PT_WRITABLE_MASK - | shadow_user_mask | shadow_x_mask); - } - return 0; -} + if (*iterator.sptep == shadow_trap_nonpresent_pte) { + pseudo_gfn = (iterator.addr & PT64_DIR_BASE_ADDR_MASK) >> PAGE_SHIFT; + sp = kvm_mmu_get_page(vcpu, pseudo_gfn, iterator.addr, + iterator.level - 1, + 1, ACC_ALL, iterator.sptep); + if (!sp) { + pgprintk("nonpaging_map: ENOMEM\n"); + kvm_release_pfn_clean(pfn); + return -ENOMEM; + } -static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write, - int largepage, gfn_t gfn, pfn_t pfn) -{ - int r; - struct direct_shadow_walk walker = { - .walker = { .entry = direct_map_entry, }, - .pfn = pfn, - .largepage = largepage, - .write = write, - .pt_write = 0, - }; - - r = walk_shadow(&walker.walker, vcpu, gfn << PAGE_SHIFT); - if (r < 0) - return r; - return walker.pt_write; + set_shadow_pte(iterator.sptep, + __pa(sp->spt) + | PT_PRESENT_MASK | PT_WRITABLE_MASK + | shadow_user_mask | shadow_x_mask); + } + } + return pt_write; } static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write, gfn_t gfn) -- GitLab From e7a04c99b54ad9acb98a56113ec3163bc1039e13 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Thu, 25 Dec 2008 15:10:50 +0200 Subject: [PATCH 4047/4982] KVM: MMU: Replace walk_shadow() by for_each_shadow_entry() in fetch() Effectively reverting to the pre walk_shadow() version -- but now with the reusable for_each(). Signed-off-by: Avi Kivity --- arch/x86/kvm/paging_tmpl.h | 128 +++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 70 deletions(-) diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index 9fd78b6e17a..69c7e3311b8 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h @@ -283,91 +283,79 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page, /* * Fetch a shadow pte for a specific level in the paging hierarchy. */ -static int FNAME(shadow_walk_entry)(struct kvm_shadow_walk *_sw, - struct kvm_vcpu *vcpu, u64 addr, - u64 *sptep, int level) +static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, + struct guest_walker *gw, + int user_fault, int write_fault, int largepage, + int *ptwrite, pfn_t pfn) { - struct shadow_walker *sw = - container_of(_sw, struct shadow_walker, walker); - struct guest_walker *gw = sw->guest_walker; unsigned access = gw->pt_access; struct kvm_mmu_page *shadow_page; - u64 spte; + u64 spte, *sptep; int metaphysical; gfn_t table_gfn; int r; + int level; pt_element_t curr_pte; + struct kvm_shadow_walk_iterator iterator; - if (level == PT_PAGE_TABLE_LEVEL - || (sw->largepage && level == PT_DIRECTORY_LEVEL)) { - mmu_set_spte(vcpu, sptep, access, gw->pte_access & access, - sw->user_fault, sw->write_fault, - gw->ptes[gw->level-1] & PT_DIRTY_MASK, - sw->ptwrite, sw->largepage, - gw->ptes[gw->level-1] & PT_GLOBAL_MASK, - gw->gfn, sw->pfn, false); - sw->sptep = sptep; - return 1; - } - - if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep)) - return 0; - - if (is_large_pte(*sptep)) { - set_shadow_pte(sptep, shadow_trap_nonpresent_pte); - kvm_flush_remote_tlbs(vcpu->kvm); - rmap_remove(vcpu->kvm, sptep); - } + if (!is_present_pte(gw->ptes[gw->level - 1])) + return NULL; - if (level == PT_DIRECTORY_LEVEL && gw->level == PT_DIRECTORY_LEVEL) { - metaphysical = 1; - if (!is_dirty_pte(gw->ptes[level - 1])) - access &= ~ACC_WRITE_MASK; - table_gfn = gpte_to_gfn(gw->ptes[level - 1]); - } else { - metaphysical = 0; - table_gfn = gw->table_gfn[level - 2]; - } - shadow_page = kvm_mmu_get_page(vcpu, table_gfn, (gva_t)addr, level-1, - metaphysical, access, sptep); - if (!metaphysical) { - r = kvm_read_guest_atomic(vcpu->kvm, gw->pte_gpa[level - 2], - &curr_pte, sizeof(curr_pte)); - if (r || curr_pte != gw->ptes[level - 2]) { - kvm_mmu_put_page(shadow_page, sptep); - kvm_release_pfn_clean(sw->pfn); - sw->sptep = NULL; - return 1; + for_each_shadow_entry(vcpu, addr, iterator) { + level = iterator.level; + sptep = iterator.sptep; + if (level == PT_PAGE_TABLE_LEVEL + || (largepage && level == PT_DIRECTORY_LEVEL)) { + mmu_set_spte(vcpu, sptep, access, + gw->pte_access & access, + user_fault, write_fault, + gw->ptes[gw->level-1] & PT_DIRTY_MASK, + ptwrite, largepage, + gw->ptes[gw->level-1] & PT_GLOBAL_MASK, + gw->gfn, pfn, false); + break; } - } - spte = __pa(shadow_page->spt) | PT_PRESENT_MASK | PT_ACCESSED_MASK - | PT_WRITABLE_MASK | PT_USER_MASK; - *sptep = spte; - return 0; -} + if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep)) + continue; -static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, - struct guest_walker *guest_walker, - int user_fault, int write_fault, int largepage, - int *ptwrite, pfn_t pfn) -{ - struct shadow_walker walker = { - .walker = { .entry = FNAME(shadow_walk_entry), }, - .guest_walker = guest_walker, - .user_fault = user_fault, - .write_fault = write_fault, - .largepage = largepage, - .ptwrite = ptwrite, - .pfn = pfn, - }; + if (is_large_pte(*sptep)) { + set_shadow_pte(sptep, shadow_trap_nonpresent_pte); + kvm_flush_remote_tlbs(vcpu->kvm); + rmap_remove(vcpu->kvm, sptep); + } - if (!is_present_pte(guest_walker->ptes[guest_walker->level - 1])) - return NULL; + if (level == PT_DIRECTORY_LEVEL + && gw->level == PT_DIRECTORY_LEVEL) { + metaphysical = 1; + if (!is_dirty_pte(gw->ptes[level - 1])) + access &= ~ACC_WRITE_MASK; + table_gfn = gpte_to_gfn(gw->ptes[level - 1]); + } else { + metaphysical = 0; + table_gfn = gw->table_gfn[level - 2]; + } + shadow_page = kvm_mmu_get_page(vcpu, table_gfn, addr, level-1, + metaphysical, access, sptep); + if (!metaphysical) { + r = kvm_read_guest_atomic(vcpu->kvm, + gw->pte_gpa[level - 2], + &curr_pte, sizeof(curr_pte)); + if (r || curr_pte != gw->ptes[level - 2]) { + kvm_mmu_put_page(shadow_page, sptep); + kvm_release_pfn_clean(pfn); + sptep = NULL; + break; + } + } - walk_shadow(&walker.walker, vcpu, addr); + spte = __pa(shadow_page->spt) + | PT_PRESENT_MASK | PT_ACCESSED_MASK + | PT_WRITABLE_MASK | PT_USER_MASK; + *sptep = spte; + } - return walker.sptep; + return sptep; } /* -- GitLab From a461930bc3cece021f8f89a80dcc1d0691a92b52 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Thu, 25 Dec 2008 15:19:00 +0200 Subject: [PATCH 4048/4982] KVM: MMU: Replace walk_shadow() by for_each_shadow_entry() in invlpg() Signed-off-by: Avi Kivity --- arch/x86/kvm/paging_tmpl.h | 81 +++++++++++++++----------------------- 1 file changed, 32 insertions(+), 49 deletions(-) diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index 69c7e3311b8..46b68f941f6 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h @@ -25,7 +25,6 @@ #if PTTYPE == 64 #define pt_element_t u64 #define guest_walker guest_walker64 - #define shadow_walker shadow_walker64 #define FNAME(name) paging##64_##name #define PT_BASE_ADDR_MASK PT64_BASE_ADDR_MASK #define PT_DIR_BASE_ADDR_MASK PT64_DIR_BASE_ADDR_MASK @@ -42,7 +41,6 @@ #elif PTTYPE == 32 #define pt_element_t u32 #define guest_walker guest_walker32 - #define shadow_walker shadow_walker32 #define FNAME(name) paging##32_##name #define PT_BASE_ADDR_MASK PT32_BASE_ADDR_MASK #define PT_DIR_BASE_ADDR_MASK PT32_DIR_BASE_ADDR_MASK @@ -73,18 +71,6 @@ struct guest_walker { u32 error_code; }; -struct shadow_walker { - struct kvm_shadow_walk walker; - struct guest_walker *guest_walker; - int user_fault; - int write_fault; - int largepage; - int *ptwrite; - pfn_t pfn; - u64 *sptep; - gpa_t pte_gpa; -}; - static gfn_t gpte_to_gfn(pt_element_t gpte) { return (gpte & PT_BASE_ADDR_MASK) >> PAGE_SHIFT; @@ -453,54 +439,52 @@ out_unlock: return 0; } -static int FNAME(shadow_invlpg_entry)(struct kvm_shadow_walk *_sw, - struct kvm_vcpu *vcpu, u64 addr, - u64 *sptep, int level) +static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva) { - struct shadow_walker *sw = - container_of(_sw, struct shadow_walker, walker); + struct kvm_shadow_walk_iterator iterator; + pt_element_t gpte; + gpa_t pte_gpa = -1; + int level; + u64 *sptep; + + spin_lock(&vcpu->kvm->mmu_lock); - /* FIXME: properly handle invlpg on large guest pages */ - if (level == PT_PAGE_TABLE_LEVEL || - ((level == PT_DIRECTORY_LEVEL) && is_large_pte(*sptep))) { - struct kvm_mmu_page *sp = page_header(__pa(sptep)); + for_each_shadow_entry(vcpu, gva, iterator) { + level = iterator.level; + sptep = iterator.sptep; - sw->pte_gpa = (sp->gfn << PAGE_SHIFT); - sw->pte_gpa += (sptep - sp->spt) * sizeof(pt_element_t); + /* FIXME: properly handle invlpg on large guest pages */ + if (level == PT_PAGE_TABLE_LEVEL || + ((level == PT_DIRECTORY_LEVEL) && is_large_pte(*sptep))) { + struct kvm_mmu_page *sp = page_header(__pa(sptep)); - if (is_shadow_present_pte(*sptep)) { - rmap_remove(vcpu->kvm, sptep); - if (is_large_pte(*sptep)) - --vcpu->kvm->stat.lpages; + pte_gpa = (sp->gfn << PAGE_SHIFT); + pte_gpa += (sptep - sp->spt) * sizeof(pt_element_t); + + if (is_shadow_present_pte(*sptep)) { + rmap_remove(vcpu->kvm, sptep); + if (is_large_pte(*sptep)) + --vcpu->kvm->stat.lpages; + } + set_shadow_pte(sptep, shadow_trap_nonpresent_pte); + break; } - set_shadow_pte(sptep, shadow_trap_nonpresent_pte); - return 1; - } - if (!is_shadow_present_pte(*sptep)) - return 1; - return 0; -} -static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva) -{ - pt_element_t gpte; - struct shadow_walker walker = { - .walker = { .entry = FNAME(shadow_invlpg_entry), }, - .pte_gpa = -1, - }; + if (!is_shadow_present_pte(*sptep)) + break; + } - spin_lock(&vcpu->kvm->mmu_lock); - walk_shadow(&walker.walker, vcpu, gva); spin_unlock(&vcpu->kvm->mmu_lock); - if (walker.pte_gpa == -1) + + if (pte_gpa == -1) return; - if (kvm_read_guest_atomic(vcpu->kvm, walker.pte_gpa, &gpte, + if (kvm_read_guest_atomic(vcpu->kvm, pte_gpa, &gpte, sizeof(pt_element_t))) return; if (is_present_pte(gpte) && (gpte & PT_ACCESSED_MASK)) { if (mmu_topup_memory_caches(vcpu)) return; - kvm_mmu_pte_write(vcpu, walker.pte_gpa, (const u8 *)&gpte, + kvm_mmu_pte_write(vcpu, pte_gpa, (const u8 *)&gpte, sizeof(pt_element_t), 0); } } @@ -607,7 +591,6 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) #undef pt_element_t #undef guest_walker -#undef shadow_walker #undef FNAME #undef PT_BASE_ADDR_MASK #undef PT_INDEX -- GitLab From e8c4a4e8a7cc047dfb3c26b2cbc8599ad3460364 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Thu, 25 Dec 2008 15:20:07 +0200 Subject: [PATCH 4049/4982] KVM: MMU: Drop walk_shadow() No longer used. Signed-off-by: Avi Kivity --- arch/x86/kvm/mmu.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index a25e1adb5cf..15850809b55 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -145,11 +145,6 @@ struct kvm_rmap_desc { struct kvm_rmap_desc *more; }; -struct kvm_shadow_walk { - int (*entry)(struct kvm_shadow_walk *walk, struct kvm_vcpu *vcpu, - u64 addr, u64 *spte, int level); -}; - struct kvm_shadow_walk_iterator { u64 addr; hpa_t shadow_addr; @@ -1299,21 +1294,6 @@ static void shadow_walk_next(struct kvm_shadow_walk_iterator *iterator) --iterator->level; } -static int walk_shadow(struct kvm_shadow_walk *walker, - struct kvm_vcpu *vcpu, u64 addr) -{ - struct kvm_shadow_walk_iterator iterator; - int r; - - for_each_shadow_entry(vcpu, addr, iterator) { - r = walker->entry(walker, vcpu, addr, - iterator.sptep, iterator.level); - if (r) - return r; - } - return 0; -} - static void kvm_mmu_page_unlink_children(struct kvm *kvm, struct kvm_mmu_page *sp) { -- GitLab From 53f658b3c33616a4997ee254311b335e59063289 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Thu, 11 Dec 2008 20:45:05 +0100 Subject: [PATCH 4050/4982] KVM: VMX: initialize TSC offset relative to vm creation time VMX initializes the TSC offset for each vcpu at different times, and also reinitializes it for vcpus other than 0 on APIC SIPI message. This bug causes the TSC's to appear unsynchronized in the guest, even if the host is good. Older Linux kernels don't handle the situation very well, so gettimeofday is likely to go backwards in time: http://www.mail-archive.com/kvm@vger.kernel.org/msg02955.html http://sourceforge.net/tracker/index.php?func=detail&aid=2025534&group_id=180599&atid=893831 Fix it by initializating the offset of each vcpu relative to vm creation time, and moving it from vmx_vcpu_reset to vmx_vcpu_setup, out of the APIC MP init path. Signed-off-by: Marcelo Tosatti Signed-off-by: Avi Kivity --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/vmx.c | 19 +++++++++++-------- arch/x86/kvm/x86.c | 2 ++ 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index c2a01d0513f..9efc446b5ac 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -398,6 +398,7 @@ struct kvm_arch{ unsigned long irq_sources_bitmap; unsigned long irq_states[KVM_IOAPIC_NUM_PINS]; + u64 vm_init_tsc; }; struct kvm_vm_stat { diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index cee81c9a665..3312047664a 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -865,11 +865,8 @@ static u64 guest_read_tsc(void) * writes 'guest_tsc' into guest's timestamp counter "register" * guest_tsc = host_tsc + tsc_offset ==> tsc_offset = guest_tsc - host_tsc */ -static void guest_write_tsc(u64 guest_tsc) +static void guest_write_tsc(u64 guest_tsc, u64 host_tsc) { - u64 host_tsc; - - rdtscll(host_tsc); vmcs_write64(TSC_OFFSET, guest_tsc - host_tsc); } @@ -934,6 +931,7 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data) { struct vcpu_vmx *vmx = to_vmx(vcpu); struct kvm_msr_entry *msr; + u64 host_tsc; int ret = 0; switch (msr_index) { @@ -959,7 +957,8 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data) vmcs_writel(GUEST_SYSENTER_ESP, data); break; case MSR_IA32_TIME_STAMP_COUNTER: - guest_write_tsc(data); + rdtscll(host_tsc); + guest_write_tsc(data, host_tsc); break; case MSR_P6_PERFCTR0: case MSR_P6_PERFCTR1: @@ -2109,7 +2108,7 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) { u32 host_sysenter_cs, msr_low, msr_high; u32 junk; - u64 host_pat; + u64 host_pat, tsc_this, tsc_base; unsigned long a; struct descriptor_table dt; int i; @@ -2237,6 +2236,12 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) vmcs_writel(CR0_GUEST_HOST_MASK, ~0UL); vmcs_writel(CR4_GUEST_HOST_MASK, KVM_GUEST_CR4_MASK); + tsc_base = vmx->vcpu.kvm->arch.vm_init_tsc; + rdtscll(tsc_this); + if (tsc_this < vmx->vcpu.kvm->arch.vm_init_tsc) + tsc_base = tsc_this; + + guest_write_tsc(0, tsc_base); return 0; } @@ -2328,8 +2333,6 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu) vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, 0); vmcs_write32(GUEST_PENDING_DBG_EXCEPTIONS, 0); - guest_write_tsc(0); - /* Special registers */ vmcs_write64(GUEST_IA32_DEBUGCTL, 0); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 873602b5edf..3b2acfd72d7 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4170,6 +4170,8 @@ struct kvm *kvm_arch_create_vm(void) /* Reserve bit 0 of irq_sources_bitmap for userspace irq source */ set_bit(KVM_USERSPACE_IRQ_SOURCE_ID, &kvm->arch.irq_sources_bitmap); + rdtscll(kvm->arch.vm_init_tsc); + return kvm; } -- GitLab From 77c2002e7c6f019f59a6f3cc5f8b16b41748dbe1 Mon Sep 17 00:00:00 2001 From: Izik Eidus Date: Mon, 29 Dec 2008 01:42:19 +0200 Subject: [PATCH 4051/4982] KVM: introduce kvm_read_guest_virt, kvm_write_guest_virt This commit change the name of emulator_read_std into kvm_read_guest_virt, and add new function name kvm_write_guest_virt that allow writing into a guest virtual address. Signed-off-by: Izik Eidus Signed-off-by: Avi Kivity --- arch/x86/include/asm/kvm_host.h | 4 --- arch/x86/kvm/x86.c | 56 ++++++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 9efc446b5ac..b74576aec19 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -609,10 +609,6 @@ void kvm_inject_nmi(struct kvm_vcpu *vcpu); void fx_init(struct kvm_vcpu *vcpu); -int emulator_read_std(unsigned long addr, - void *val, - unsigned int bytes, - struct kvm_vcpu *vcpu); int emulator_write_emulated(unsigned long addr, const void *val, unsigned int bytes, diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 3b2acfd72d7..67f91764e99 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1976,10 +1976,8 @@ static struct kvm_io_device *vcpu_find_mmio_dev(struct kvm_vcpu *vcpu, return dev; } -int emulator_read_std(unsigned long addr, - void *val, - unsigned int bytes, - struct kvm_vcpu *vcpu) +int kvm_read_guest_virt(gva_t addr, void *val, unsigned int bytes, + struct kvm_vcpu *vcpu) { void *data = val; int r = X86EMUL_CONTINUE; @@ -1987,27 +1985,57 @@ int emulator_read_std(unsigned long addr, while (bytes) { gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr); unsigned offset = addr & (PAGE_SIZE-1); - unsigned tocopy = min(bytes, (unsigned)PAGE_SIZE - offset); + unsigned toread = min(bytes, (unsigned)PAGE_SIZE - offset); int ret; if (gpa == UNMAPPED_GVA) { r = X86EMUL_PROPAGATE_FAULT; goto out; } - ret = kvm_read_guest(vcpu->kvm, gpa, data, tocopy); + ret = kvm_read_guest(vcpu->kvm, gpa, data, toread); if (ret < 0) { r = X86EMUL_UNHANDLEABLE; goto out; } - bytes -= tocopy; - data += tocopy; - addr += tocopy; + bytes -= toread; + data += toread; + addr += toread; } out: return r; } -EXPORT_SYMBOL_GPL(emulator_read_std); + +int kvm_write_guest_virt(gva_t addr, void *val, unsigned int bytes, + struct kvm_vcpu *vcpu) +{ + void *data = val; + int r = X86EMUL_CONTINUE; + + while (bytes) { + gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr); + unsigned offset = addr & (PAGE_SIZE-1); + unsigned towrite = min(bytes, (unsigned)PAGE_SIZE - offset); + int ret; + + if (gpa == UNMAPPED_GVA) { + r = X86EMUL_PROPAGATE_FAULT; + goto out; + } + ret = kvm_write_guest(vcpu->kvm, gpa, data, towrite); + if (ret < 0) { + r = X86EMUL_UNHANDLEABLE; + goto out; + } + + bytes -= towrite; + data += towrite; + addr += towrite; + } +out: + return r; +} + static int emulator_read_emulated(unsigned long addr, void *val, @@ -2029,8 +2057,8 @@ static int emulator_read_emulated(unsigned long addr, if ((gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE) goto mmio; - if (emulator_read_std(addr, val, bytes, vcpu) - == X86EMUL_CONTINUE) + if (kvm_read_guest_virt(addr, val, bytes, vcpu) + == X86EMUL_CONTINUE) return X86EMUL_CONTINUE; if (gpa == UNMAPPED_GVA) return X86EMUL_PROPAGATE_FAULT; @@ -2233,7 +2261,7 @@ void kvm_report_emulation_failure(struct kvm_vcpu *vcpu, const char *context) rip_linear = rip + get_segment_base(vcpu, VCPU_SREG_CS); - emulator_read_std(rip_linear, (void *)opcodes, 4, vcpu); + kvm_read_guest_virt(rip_linear, (void *)opcodes, 4, vcpu); printk(KERN_ERR "emulation failed (%s) rip %lx %02x %02x %02x %02x\n", context, rip, opcodes[0], opcodes[1], opcodes[2], opcodes[3]); @@ -2241,7 +2269,7 @@ void kvm_report_emulation_failure(struct kvm_vcpu *vcpu, const char *context) EXPORT_SYMBOL_GPL(kvm_report_emulation_failure); static struct x86_emulate_ops emulate_ops = { - .read_std = emulator_read_std, + .read_std = kvm_read_guest_virt, .read_emulated = emulator_read_emulated, .write_emulated = emulator_write_emulated, .cmpxchg_emulated = emulator_cmpxchg_emulated, -- GitLab From 0f346074403bc109f9569f14b45cb09e83729032 Mon Sep 17 00:00:00 2001 From: Izik Eidus Date: Mon, 29 Dec 2008 01:42:20 +0200 Subject: [PATCH 4052/4982] KVM: remove the vmap usage vmap() on guest pages hides those pages from the Linux mm for an extended (userspace determined) amount of time. Get rid of it. Signed-off-by: Izik Eidus Signed-off-by: Avi Kivity --- arch/x86/kvm/x86.c | 62 ++++++++------------------------------- include/linux/kvm_types.h | 3 +- 2 files changed, 14 insertions(+), 51 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 67f91764e99..2a4f3a69734 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2371,40 +2371,19 @@ int emulate_instruction(struct kvm_vcpu *vcpu, } EXPORT_SYMBOL_GPL(emulate_instruction); -static void free_pio_guest_pages(struct kvm_vcpu *vcpu) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(vcpu->arch.pio.guest_pages); ++i) - if (vcpu->arch.pio.guest_pages[i]) { - kvm_release_page_dirty(vcpu->arch.pio.guest_pages[i]); - vcpu->arch.pio.guest_pages[i] = NULL; - } -} - static int pio_copy_data(struct kvm_vcpu *vcpu) { void *p = vcpu->arch.pio_data; - void *q; + gva_t q = vcpu->arch.pio.guest_gva; unsigned bytes; - int nr_pages = vcpu->arch.pio.guest_pages[1] ? 2 : 1; + int ret; - q = vmap(vcpu->arch.pio.guest_pages, nr_pages, VM_READ|VM_WRITE, - PAGE_KERNEL); - if (!q) { - free_pio_guest_pages(vcpu); - return -ENOMEM; - } - q += vcpu->arch.pio.guest_page_offset; bytes = vcpu->arch.pio.size * vcpu->arch.pio.cur_count; if (vcpu->arch.pio.in) - memcpy(q, p, bytes); + ret = kvm_write_guest_virt(q, p, bytes, vcpu); else - memcpy(p, q, bytes); - q -= vcpu->arch.pio.guest_page_offset; - vunmap(q); - free_pio_guest_pages(vcpu); - return 0; + ret = kvm_read_guest_virt(q, p, bytes, vcpu); + return ret; } int complete_pio(struct kvm_vcpu *vcpu) @@ -2515,7 +2494,6 @@ int kvm_emulate_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, vcpu->arch.pio.in = in; vcpu->arch.pio.string = 0; vcpu->arch.pio.down = 0; - vcpu->arch.pio.guest_page_offset = 0; vcpu->arch.pio.rep = 0; if (vcpu->run->io.direction == KVM_EXIT_IO_IN) @@ -2543,9 +2521,7 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, gva_t address, int rep, unsigned port) { unsigned now, in_page; - int i, ret = 0; - int nr_pages = 1; - struct page *page; + int ret = 0; struct kvm_io_device *pio_dev; vcpu->run->exit_reason = KVM_EXIT_IO; @@ -2557,7 +2533,6 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, vcpu->arch.pio.in = in; vcpu->arch.pio.string = 1; vcpu->arch.pio.down = down; - vcpu->arch.pio.guest_page_offset = offset_in_page(address); vcpu->arch.pio.rep = rep; if (vcpu->run->io.direction == KVM_EXIT_IO_IN) @@ -2577,15 +2552,8 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, else in_page = offset_in_page(address) + size; now = min(count, (unsigned long)in_page / size); - if (!now) { - /* - * String I/O straddles page boundary. Pin two guest pages - * so that we satisfy atomicity constraints. Do just one - * transaction to avoid complexity. - */ - nr_pages = 2; + if (!now) now = 1; - } if (down) { /* * String I/O in reverse. Yuck. Kill the guest, fix later. @@ -2600,15 +2568,7 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, if (vcpu->arch.pio.cur_count == vcpu->arch.pio.count) kvm_x86_ops->skip_emulated_instruction(vcpu); - for (i = 0; i < nr_pages; ++i) { - page = gva_to_page(vcpu, address + i * PAGE_SIZE); - vcpu->arch.pio.guest_pages[i] = page; - if (!page) { - kvm_inject_gp(vcpu, 0); - free_pio_guest_pages(vcpu); - return 1; - } - } + vcpu->arch.pio.guest_gva = address; pio_dev = vcpu_find_pio_dev(vcpu, port, vcpu->arch.pio.cur_count, @@ -2616,7 +2576,11 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, if (!vcpu->arch.pio.in) { /* string PIO write */ ret = pio_copy_data(vcpu); - if (ret >= 0 && pio_dev) { + if (ret == X86EMUL_PROPAGATE_FAULT) { + kvm_inject_gp(vcpu, 0); + return 1; + } + if (ret == 0 && pio_dev) { pio_string_write(pio_dev, vcpu); complete_pio(vcpu); if (vcpu->arch.pio.count == 0) diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h index 9b6f395c962..5f4a18cae26 100644 --- a/include/linux/kvm_types.h +++ b/include/linux/kvm_types.h @@ -43,8 +43,7 @@ typedef hfn_t pfn_t; struct kvm_pio_request { unsigned long count; int cur_count; - struct page *guest_pages[2]; - unsigned guest_page_offset; + gva_t guest_gva; int in; int port; int size; -- GitLab From 61a6bd672bda3b9468bf5895c1be085c4e481138 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Mon, 29 Dec 2008 17:32:28 +0200 Subject: [PATCH 4053/4982] KVM: Fallback support for MSR_VM_HSAVE_PA Since we advertise MSR_VM_HSAVE_PA, userspace will attempt to read it even on Intel. Implement fake support for this MSR to avoid the warnings. Signed-off-by: Avi Kivity --- arch/x86/kvm/x86.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 2a4f3a69734..c3fbe8c55c1 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -742,6 +742,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) break; case MSR_IA32_UCODE_REV: case MSR_IA32_UCODE_WRITE: + case MSR_VM_HSAVE_PA: break; case 0x200 ... 0x2ff: return set_msr_mtrr(vcpu, msr, data); @@ -863,6 +864,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) case MSR_IA32_LASTBRANCHTOIP: case MSR_IA32_LASTINTFROMIP: case MSR_IA32_LASTINTTOIP: + case MSR_VM_HSAVE_PA: data = 0; break; case MSR_MTRRcap: -- GitLab From 52d939a0bf44081bc9f69b4fbdc9e7f416df27c7 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Tue, 30 Dec 2008 15:55:06 -0200 Subject: [PATCH 4054/4982] KVM: PIT: provide an option to disable interrupt reinjection Certain clocks (such as TSC) in older 2.6 guests overaccount for lost ticks, causing severe time drift. Interrupt reinjection magnifies the problem. Provide an option to disable it. [avi: allow room for expansion in case we want to disable reinjection of other timers] Signed-off-by: Marcelo Tosatti Signed-off-by: Avi Kivity --- arch/x86/include/asm/kvm.h | 5 +++++ arch/x86/kvm/i8254.c | 4 ++++ arch/x86/kvm/i8254.h | 1 + arch/x86/kvm/x86.c | 21 +++++++++++++++++++++ include/linux/kvm.h | 4 ++++ 5 files changed, 35 insertions(+) diff --git a/arch/x86/include/asm/kvm.h b/arch/x86/include/asm/kvm.h index 32eb96c7ca2..54bcf228152 100644 --- a/arch/x86/include/asm/kvm.h +++ b/arch/x86/include/asm/kvm.h @@ -233,4 +233,9 @@ struct kvm_guest_debug_arch { struct kvm_pit_state { struct kvm_pit_channel_state channels[3]; }; + +struct kvm_reinject_control { + __u8 pit_reinject; + __u8 reserved[31]; +}; #endif /* _ASM_X86_KVM_H */ diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c index 72bd275a9b5..528daadeba4 100644 --- a/arch/x86/kvm/i8254.c +++ b/arch/x86/kvm/i8254.c @@ -201,6 +201,9 @@ static int __pit_timer_fn(struct kvm_kpit_state *ps) if (!atomic_inc_and_test(&pt->pending)) set_bit(KVM_REQ_PENDING_TIMER, &vcpu0->requests); + if (!pt->reinject) + atomic_set(&pt->pending, 1); + if (vcpu0 && waitqueue_active(&vcpu0->wq)) wake_up_interruptible(&vcpu0->wq); @@ -580,6 +583,7 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm) pit_state->irq_ack_notifier.gsi = 0; pit_state->irq_ack_notifier.irq_acked = kvm_pit_ack_irq; kvm_register_irq_ack_notifier(kvm, &pit_state->irq_ack_notifier); + pit_state->pit_timer.reinject = true; mutex_unlock(&pit->pit_state.lock); kvm_pit_reset(pit); diff --git a/arch/x86/kvm/i8254.h b/arch/x86/kvm/i8254.h index 4178022b97a..76959c4b500 100644 --- a/arch/x86/kvm/i8254.h +++ b/arch/x86/kvm/i8254.h @@ -9,6 +9,7 @@ struct kvm_kpit_timer { s64 period; /* unit: ns */ s64 scheduled; atomic_t pending; + bool reinject; }; struct kvm_kpit_channel_state { diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index c3fbe8c55c1..a1f14611f4b 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -993,6 +993,7 @@ int kvm_dev_ioctl_check_extension(long ext) case KVM_CAP_NOP_IO_DELAY: case KVM_CAP_MP_STATE: case KVM_CAP_SYNC_MMU: + case KVM_CAP_REINJECT_CONTROL: r = 1; break; case KVM_CAP_COALESCED_MMIO: @@ -1728,6 +1729,15 @@ static int kvm_vm_ioctl_set_pit(struct kvm *kvm, struct kvm_pit_state *ps) return r; } +static int kvm_vm_ioctl_reinject(struct kvm *kvm, + struct kvm_reinject_control *control) +{ + if (!kvm->arch.vpit) + return -ENXIO; + kvm->arch.vpit->pit_state.pit_timer.reinject = control->pit_reinject; + return 0; +} + /* * Get (and clear) the dirty memory log for a memory slot. */ @@ -1925,6 +1935,17 @@ long kvm_arch_vm_ioctl(struct file *filp, r = 0; break; } + case KVM_REINJECT_CONTROL: { + struct kvm_reinject_control control; + r = -EFAULT; + if (copy_from_user(&control, argp, sizeof(control))) + goto out; + r = kvm_vm_ioctl_reinject(kvm, &control); + if (r) + goto out; + r = 0; + break; + } default: ; } diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 11e3e6197c8..ae7a12c7742 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h @@ -396,6 +396,9 @@ struct kvm_trace_rec { #if defined(CONFIG_X86) #define KVM_CAP_SET_GUEST_DEBUG 23 #endif +#if defined(CONFIG_X86) +#define KVM_CAP_REINJECT_CONTROL 24 +#endif /* * ioctls for VM fds @@ -429,6 +432,7 @@ struct kvm_trace_rec { struct kvm_assigned_pci_dev) #define KVM_ASSIGN_IRQ _IOR(KVMIO, 0x70, \ struct kvm_assigned_irq) +#define KVM_REINJECT_CONTROL _IO(KVMIO, 0x71) /* * ioctls for vcpu fds -- GitLab From 1c08364c3565242f1e1bd585bc2ce458967941af Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 4 Jan 2009 12:39:07 +0200 Subject: [PATCH 4055/4982] KVM: Move struct kvm_pio_request into x86 kvm_host.h This is an x86 specific stucture and has no business living in common code. Signed-off-by: Avi Kivity --- arch/x86/include/asm/kvm_host.h | 12 ++++++++++++ include/linux/kvm_types.h | 12 ------------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index b74576aec19..863ea73431a 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -227,6 +227,18 @@ struct kvm_pv_mmu_op_buffer { char buf[512] __aligned(sizeof(long)); }; +struct kvm_pio_request { + unsigned long count; + int cur_count; + gva_t guest_gva; + int in; + int port; + int size; + int string; + int down; + int rep; +}; + /* * x86 supports 3 paging modes (4-level 64-bit, 3-level 64-bit, and 2-level * 32-bit). The kvm_mmu structure abstracts the details of the current mmu diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h index 5f4a18cae26..2b8318c83e5 100644 --- a/include/linux/kvm_types.h +++ b/include/linux/kvm_types.h @@ -40,16 +40,4 @@ typedef unsigned long hfn_t; typedef hfn_t pfn_t; -struct kvm_pio_request { - unsigned long count; - int cur_count; - gva_t guest_gva; - int in; - int port; - int size; - int string; - int down; - int rep; -}; - #endif /* __KVM_TYPES_H__ */ -- GitLab From c46fb0211f8b93de45400bff814c0f29335af5fc Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Sat, 3 Jan 2009 16:22:58 -0600 Subject: [PATCH 4056/4982] KVM: ppc: move struct kvmppc_44x_tlbe into 44x-specific header Signed-off-by: Hollis Blanchard Signed-off-by: Avi Kivity --- arch/powerpc/include/asm/kvm_44x.h | 7 +++++++ arch/powerpc/include/asm/kvm_host.h | 7 ------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/include/asm/kvm_44x.h b/arch/powerpc/include/asm/kvm_44x.h index f49031b632c..d22d39942a9 100644 --- a/arch/powerpc/include/asm/kvm_44x.h +++ b/arch/powerpc/include/asm/kvm_44x.h @@ -28,6 +28,13 @@ * need to find some way of advertising it. */ #define KVM44x_GUEST_TLB_SIZE 64 +struct kvmppc_44x_tlbe { + u32 tid; /* Only the low 8 bits are used. */ + u32 word0; + u32 word1; + u32 word2; +}; + struct kvmppc_44x_shadow_ref { struct page *page; u16 gtlb_index; diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index a22600537a8..65c4d492d72 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -64,13 +64,6 @@ struct kvm_vcpu_stat { u32 halt_wakeup; }; -struct kvmppc_44x_tlbe { - u32 tid; /* Only the low 8 bits are used. */ - u32 word0; - u32 word1; - u32 word2; -}; - enum kvm_exit_types { MMIO_EXITS, DCR_EXITS, -- GitLab From ecc0981ff07cbe7cdf95de20be5b24fee8e49cb5 Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Sat, 3 Jan 2009 16:22:59 -0600 Subject: [PATCH 4057/4982] KVM: ppc: cosmetic changes to mmu hook names Signed-off-by: Hollis Blanchard Signed-off-by: Avi Kivity --- arch/powerpc/include/asm/kvm_ppc.h | 5 +++-- arch/powerpc/kvm/44x_tlb.c | 2 +- arch/powerpc/kvm/powerpc.c | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index 36d2a50a848..7ba95d28b83 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h @@ -52,13 +52,14 @@ extern int kvmppc_emulate_instruction(struct kvm_run *run, extern int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu); extern void kvmppc_emulate_dec(struct kvm_vcpu *vcpu); +/* Core-specific hooks */ + extern void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gpa_t gpaddr, u64 asid, u32 flags, u32 max_bytes, unsigned int gtlb_idx); extern void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode); extern void kvmppc_mmu_switch_pid(struct kvm_vcpu *vcpu, u32 pid); - -/* Core-specific hooks */ +extern void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu); extern struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id); diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c index 9a34b8edb9e..8f9c09cbb83 100644 --- a/arch/powerpc/kvm/44x_tlb.c +++ b/arch/powerpc/kvm/44x_tlb.c @@ -248,7 +248,7 @@ static void kvmppc_44x_shadow_release(struct kvmppc_vcpu_44x *vcpu_44x, KVMTRACE_1D(STLB_INVAL, &vcpu_44x->vcpu, stlb_index, handler); } -void kvmppc_core_destroy_mmu(struct kvm_vcpu *vcpu) +void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu) { struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); int i; diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 7c2ad4017d6..f30be9ef231 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -216,7 +216,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) { - kvmppc_core_destroy_mmu(vcpu); + kvmppc_mmu_destroy(vcpu); } void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) -- GitLab From 475e7cdd69101939006659a63c2e4a32d5b71389 Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Sat, 3 Jan 2009 16:23:00 -0600 Subject: [PATCH 4058/4982] KVM: ppc: small cosmetic changes to Book E DTLB miss handler Signed-off-by: Hollis Blanchard Signed-off-by: Avi Kivity --- arch/powerpc/kvm/booke.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 35485dd6927..d196ae61930 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c @@ -290,6 +290,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, struct kvmppc_44x_tlbe *gtlbe; unsigned long eaddr = vcpu->arch.fault_dear; int gtlb_index; + gpa_t gpaddr; gfn_t gfn; /* Check the guest TLB. */ @@ -305,8 +306,8 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, } gtlbe = &vcpu_44x->guest_tlb[gtlb_index]; - vcpu->arch.paddr_accessed = tlb_xlate(gtlbe, eaddr); - gfn = vcpu->arch.paddr_accessed >> PAGE_SHIFT; + gpaddr = tlb_xlate(gtlbe, eaddr); + gfn = gpaddr >> PAGE_SHIFT; if (kvm_is_visible_gfn(vcpu->kvm, gfn)) { /* The guest TLB had a mapping, but the shadow TLB @@ -315,13 +316,14 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, * b) the guest used a large mapping which we're faking * Either way, we need to satisfy the fault without * invoking the guest. */ - kvmppc_mmu_map(vcpu, eaddr, vcpu->arch.paddr_accessed, gtlbe->tid, + kvmppc_mmu_map(vcpu, eaddr, gpaddr, gtlbe->tid, gtlbe->word2, get_tlb_bytes(gtlbe), gtlb_index); kvmppc_account_exit(vcpu, DTLB_VIRT_MISS_EXITS); r = RESUME_GUEST; } else { /* Guest has mapped and accessed a page which is not * actually RAM. */ + vcpu->arch.paddr_accessed = gpaddr; r = kvmppc_emulate_mmio(run, vcpu); kvmppc_account_exit(vcpu, MMIO_EXITS); } -- GitLab From 58a96214a306fc7fc66105097eea9c4f3bfa35bc Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Sat, 3 Jan 2009 16:23:01 -0600 Subject: [PATCH 4059/4982] KVM: ppc: change kvmppc_mmu_map() parameters Passing just the TLB index will ease an e500 implementation. Signed-off-by: Hollis Blanchard Signed-off-by: Avi Kivity --- arch/powerpc/include/asm/kvm_ppc.h | 1 - arch/powerpc/kvm/44x_tlb.c | 15 +++++++-------- arch/powerpc/kvm/booke.c | 6 ++---- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index 7ba95d28b83..f661f8ba3ab 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h @@ -55,7 +55,6 @@ extern void kvmppc_emulate_dec(struct kvm_vcpu *vcpu); /* Core-specific hooks */ extern void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gpa_t gpaddr, - u64 asid, u32 flags, u32 max_bytes, unsigned int gtlb_idx); extern void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode); extern void kvmppc_mmu_switch_pid(struct kvm_vcpu *vcpu, u32 pid); diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c index 8f9c09cbb83..e8ed22f28ea 100644 --- a/arch/powerpc/kvm/44x_tlb.c +++ b/arch/powerpc/kvm/44x_tlb.c @@ -269,15 +269,19 @@ void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu) * Caller must ensure that the specified guest TLB entry is safe to insert into * the shadow TLB. */ -void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gpa_t gpaddr, u64 asid, - u32 flags, u32 max_bytes, unsigned int gtlb_index) +void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gpa_t gpaddr, + unsigned int gtlb_index) { struct kvmppc_44x_tlbe stlbe; struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); + struct kvmppc_44x_tlbe *gtlbe = &vcpu_44x->guest_tlb[gtlb_index]; struct kvmppc_44x_shadow_ref *ref; struct page *new_page; hpa_t hpaddr; gfn_t gfn; + u32 asid = gtlbe->tid; + u32 flags = gtlbe->word2; + u32 max_bytes = get_tlb_bytes(gtlbe); unsigned int victim; /* Select TLB entry to clobber. Indirectly guard against races with the TLB @@ -448,10 +452,8 @@ int kvmppc_44x_emul_tlbwe(struct kvm_vcpu *vcpu, u8 ra, u8 rs, u8 ws) } if (tlbe_is_host_safe(vcpu, tlbe)) { - u64 asid; gva_t eaddr; gpa_t gpaddr; - u32 flags; u32 bytes; eaddr = get_tlb_eaddr(tlbe); @@ -462,10 +464,7 @@ int kvmppc_44x_emul_tlbwe(struct kvm_vcpu *vcpu, u8 ra, u8 rs, u8 ws) eaddr &= ~(bytes - 1); gpaddr &= ~(bytes - 1); - asid = (tlbe->word0 & PPC44x_TLB_TS) | tlbe->tid; - flags = tlbe->word2 & 0xffff; - - kvmppc_mmu_map(vcpu, eaddr, gpaddr, asid, flags, bytes, gtlb_index); + kvmppc_mmu_map(vcpu, eaddr, gpaddr, gtlb_index); } KVMTRACE_5D(GTLB_WRITE, vcpu, gtlb_index, tlbe->tid, tlbe->word0, diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index d196ae61930..85b9e2fc6c6 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c @@ -316,8 +316,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, * b) the guest used a large mapping which we're faking * Either way, we need to satisfy the fault without * invoking the guest. */ - kvmppc_mmu_map(vcpu, eaddr, gpaddr, gtlbe->tid, - gtlbe->word2, get_tlb_bytes(gtlbe), gtlb_index); + kvmppc_mmu_map(vcpu, eaddr, gpaddr, gtlb_index); kvmppc_account_exit(vcpu, DTLB_VIRT_MISS_EXITS); r = RESUME_GUEST; } else { @@ -364,8 +363,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, * b) the guest used a large mapping which we're faking * Either way, we need to satisfy the fault without * invoking the guest. */ - kvmppc_mmu_map(vcpu, eaddr, gpaddr, gtlbe->tid, - gtlbe->word2, get_tlb_bytes(gtlbe), gtlb_index); + kvmppc_mmu_map(vcpu, eaddr, gpaddr, gtlb_index); } else { /* Guest mapped and leaped at non-RAM! */ kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_MACHINE_CHECK); -- GitLab From be8d1cae07d5acf4a61046d7def5eda40f0981e1 Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Sat, 3 Jan 2009 16:23:02 -0600 Subject: [PATCH 4060/4982] KVM: ppc: turn tlb_xlate() into a per-core hook (and give it a better name) Signed-off-by: Hollis Blanchard Signed-off-by: Avi Kivity --- arch/powerpc/include/asm/kvm_ppc.h | 2 ++ arch/powerpc/kvm/44x.c | 6 +----- arch/powerpc/kvm/44x_tlb.c | 10 ++++++++++ arch/powerpc/kvm/44x_tlb.h | 7 ------- arch/powerpc/kvm/booke.c | 10 ++-------- 5 files changed, 15 insertions(+), 20 deletions(-) diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index f661f8ba3ab..9fd70aa916d 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h @@ -59,6 +59,8 @@ extern void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gpa_t gpaddr, extern void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode); extern void kvmppc_mmu_switch_pid(struct kvm_vcpu *vcpu, u32 pid); extern void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu); +extern gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int gtlb_index, + gva_t eaddr); extern struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id); diff --git a/arch/powerpc/kvm/44x.c b/arch/powerpc/kvm/44x.c index a66bec57265..8383603dd8a 100644 --- a/arch/powerpc/kvm/44x.c +++ b/arch/powerpc/kvm/44x.c @@ -149,8 +149,6 @@ int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu) int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu, struct kvm_translation *tr) { - struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); - struct kvmppc_44x_tlbe *gtlbe; int index; gva_t eaddr; u8 pid; @@ -166,9 +164,7 @@ int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu, return 0; } - gtlbe = &vcpu_44x->guest_tlb[index]; - - tr->physical_address = tlb_xlate(gtlbe, eaddr); + tr->physical_address = kvmppc_mmu_xlate(vcpu, index, eaddr); /* XXX what does "writeable" and "usermode" even mean? */ tr->valid = 1; diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c index e8ed22f28ea..2f14671e8a1 100644 --- a/arch/powerpc/kvm/44x_tlb.c +++ b/arch/powerpc/kvm/44x_tlb.c @@ -208,6 +208,16 @@ int kvmppc_44x_tlb_index(struct kvm_vcpu *vcpu, gva_t eaddr, unsigned int pid, return -1; } +gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int gtlb_index, + gva_t eaddr) +{ + struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); + struct kvmppc_44x_tlbe *gtlbe = &vcpu_44x->guest_tlb[gtlb_index]; + unsigned int pgmask = get_tlb_bytes(gtlbe) - 1; + + return get_tlb_raddr(gtlbe) | (eaddr & pgmask); +} + int kvmppc_44x_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr) { unsigned int as = !!(vcpu->arch.msr & MSR_IS); diff --git a/arch/powerpc/kvm/44x_tlb.h b/arch/powerpc/kvm/44x_tlb.h index 772191f29e6..05b6f7eef5b 100644 --- a/arch/powerpc/kvm/44x_tlb.h +++ b/arch/powerpc/kvm/44x_tlb.h @@ -85,11 +85,4 @@ static inline unsigned int get_mmucr_sts(const struct kvm_vcpu *vcpu) return (vcpu->arch.mmucr >> 16) & 0x1; } -static inline gpa_t tlb_xlate(struct kvmppc_44x_tlbe *tlbe, gva_t eaddr) -{ - unsigned int pgmask = get_tlb_bytes(tlbe) - 1; - - return get_tlb_raddr(tlbe) | (eaddr & pgmask); -} - #endif /* __KVM_POWERPC_TLB_H__ */ diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 85b9e2fc6c6..56d6ed69ed6 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c @@ -286,8 +286,6 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, /* XXX move to a 440-specific file. */ case BOOKE_INTERRUPT_DTLB_MISS: { - struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); - struct kvmppc_44x_tlbe *gtlbe; unsigned long eaddr = vcpu->arch.fault_dear; int gtlb_index; gpa_t gpaddr; @@ -305,8 +303,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, break; } - gtlbe = &vcpu_44x->guest_tlb[gtlb_index]; - gpaddr = tlb_xlate(gtlbe, eaddr); + gpaddr = kvmppc_mmu_xlate(vcpu, gtlb_index, eaddr); gfn = gpaddr >> PAGE_SHIFT; if (kvm_is_visible_gfn(vcpu->kvm, gfn)) { @@ -332,8 +329,6 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, /* XXX move to a 440-specific file. */ case BOOKE_INTERRUPT_ITLB_MISS: { - struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); - struct kvmppc_44x_tlbe *gtlbe; unsigned long eaddr = vcpu->arch.pc; gpa_t gpaddr; gfn_t gfn; @@ -352,8 +347,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, kvmppc_account_exit(vcpu, ITLB_VIRT_MISS_EXITS); - gtlbe = &vcpu_44x->guest_tlb[gtlb_index]; - gpaddr = tlb_xlate(gtlbe, eaddr); + gpaddr = kvmppc_mmu_xlate(vcpu, gtlb_index, eaddr); gfn = gpaddr >> PAGE_SHIFT; if (kvm_is_visible_gfn(vcpu->kvm, gfn)) { -- GitLab From fa86b8dda2e0faccefbeda61edc02a50bd588f4f Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Sat, 3 Jan 2009 16:23:03 -0600 Subject: [PATCH 4061/4982] KVM: ppc: rename 44x MMU functions used in booke.c e500 will provide its own implementation of these. Signed-off-by: Hollis Blanchard Signed-off-by: Avi Kivity --- arch/powerpc/include/asm/kvm_ppc.h | 2 ++ arch/powerpc/kvm/44x_tlb.c | 4 ++-- arch/powerpc/kvm/44x_tlb.h | 2 -- arch/powerpc/kvm/booke.c | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index 9fd70aa916d..5e80a20f32b 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h @@ -59,6 +59,8 @@ extern void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gpa_t gpaddr, extern void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode); extern void kvmppc_mmu_switch_pid(struct kvm_vcpu *vcpu, u32 pid); extern void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu); +extern int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr); +extern int kvmppc_mmu_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr); extern gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int gtlb_index, gva_t eaddr); diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c index 2f14671e8a1..e67b7313ffc 100644 --- a/arch/powerpc/kvm/44x_tlb.c +++ b/arch/powerpc/kvm/44x_tlb.c @@ -218,14 +218,14 @@ gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int gtlb_index, return get_tlb_raddr(gtlbe) | (eaddr & pgmask); } -int kvmppc_44x_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr) +int kvmppc_mmu_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr) { unsigned int as = !!(vcpu->arch.msr & MSR_IS); return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as); } -int kvmppc_44x_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr) +int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr) { unsigned int as = !!(vcpu->arch.msr & MSR_DS); diff --git a/arch/powerpc/kvm/44x_tlb.h b/arch/powerpc/kvm/44x_tlb.h index 05b6f7eef5b..a9ff80e5152 100644 --- a/arch/powerpc/kvm/44x_tlb.h +++ b/arch/powerpc/kvm/44x_tlb.h @@ -25,8 +25,6 @@ extern int kvmppc_44x_tlb_index(struct kvm_vcpu *vcpu, gva_t eaddr, unsigned int pid, unsigned int as); -extern int kvmppc_44x_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr); -extern int kvmppc_44x_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr); extern int kvmppc_44x_emul_tlbsx(struct kvm_vcpu *vcpu, u8 rt, u8 ra, u8 rb, u8 rc); diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 56d6ed69ed6..1e692ac16e9 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c @@ -292,7 +292,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, gfn_t gfn; /* Check the guest TLB. */ - gtlb_index = kvmppc_44x_dtlb_index(vcpu, eaddr); + gtlb_index = kvmppc_mmu_dtlb_index(vcpu, eaddr); if (gtlb_index < 0) { /* The guest didn't have a mapping for it. */ kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DTLB_MISS); @@ -337,7 +337,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, r = RESUME_GUEST; /* Check the guest TLB. */ - gtlb_index = kvmppc_44x_itlb_index(vcpu, eaddr); + gtlb_index = kvmppc_mmu_itlb_index(vcpu, eaddr); if (gtlb_index < 0) { /* The guest didn't have a mapping for it. */ kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ITLB_MISS); -- GitLab From f44353610b584fcbc31e363f35594796c6446d63 Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Sat, 3 Jan 2009 16:23:04 -0600 Subject: [PATCH 4062/4982] KVM: ppc: remove last 44x-specific bits from booke.c Signed-off-by: Hollis Blanchard Signed-off-by: Avi Kivity --- arch/powerpc/kvm/booke.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 1e692ac16e9..a73b3959e41 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c @@ -30,10 +30,8 @@ #include #include "timing.h" #include -#include #include "booke.h" -#include "44x_tlb.h" unsigned long kvmppc_booke_handlers; @@ -284,7 +282,6 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, r = RESUME_GUEST; break; - /* XXX move to a 440-specific file. */ case BOOKE_INTERRUPT_DTLB_MISS: { unsigned long eaddr = vcpu->arch.fault_dear; int gtlb_index; @@ -327,7 +324,6 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, break; } - /* XXX move to a 440-specific file. */ case BOOKE_INTERRUPT_ITLB_MISS: { unsigned long eaddr = vcpu->arch.pc; gpa_t gpaddr; -- GitLab From cea5d8c9de669e30ed6d60930318376d5cc42e9e Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Sat, 3 Jan 2009 16:23:05 -0600 Subject: [PATCH 4063/4982] KVM: ppc: use macros instead of hardcoded literals for instruction decoding Signed-off-by: Hollis Blanchard Signed-off-by: Avi Kivity --- arch/powerpc/kvm/emulate.c | 93 ++++++++++++++++++++++++++------------ 1 file changed, 63 insertions(+), 30 deletions(-) diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c index d1d38daa93f..a561d6e8da1 100644 --- a/arch/powerpc/kvm/emulate.c +++ b/arch/powerpc/kvm/emulate.c @@ -30,6 +30,39 @@ #include #include "timing.h" +#define OP_TRAP 3 + +#define OP_31_XOP_LWZX 23 +#define OP_31_XOP_LBZX 87 +#define OP_31_XOP_STWX 151 +#define OP_31_XOP_STBX 215 +#define OP_31_XOP_STBUX 247 +#define OP_31_XOP_LHZX 279 +#define OP_31_XOP_LHZUX 311 +#define OP_31_XOP_MFSPR 339 +#define OP_31_XOP_STHX 407 +#define OP_31_XOP_STHUX 439 +#define OP_31_XOP_MTSPR 467 +#define OP_31_XOP_DCBI 470 +#define OP_31_XOP_LWBRX 534 +#define OP_31_XOP_TLBSYNC 566 +#define OP_31_XOP_STWBRX 662 +#define OP_31_XOP_LHBRX 790 +#define OP_31_XOP_STHBRX 918 + +#define OP_LWZ 32 +#define OP_LWZU 33 +#define OP_LBZ 34 +#define OP_LBZU 35 +#define OP_STW 36 +#define OP_STWU 37 +#define OP_STB 38 +#define OP_STBU 39 +#define OP_LHZ 40 +#define OP_LHZU 41 +#define OP_STH 44 +#define OP_STHU 45 + void kvmppc_emulate_dec(struct kvm_vcpu *vcpu) { if (vcpu->arch.tcr & TCR_DIE) { @@ -78,7 +111,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS); switch (get_op(inst)) { - case 3: /* trap */ + case OP_TRAP: vcpu->arch.esr |= ESR_PTR; kvmppc_core_queue_program(vcpu); advance = 0; @@ -87,31 +120,31 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) case 31: switch (get_xop(inst)) { - case 23: /* lwzx */ + case OP_31_XOP_LWZX: rt = get_rt(inst); emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1); break; - case 87: /* lbzx */ + case OP_31_XOP_LBZX: rt = get_rt(inst); emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1); break; - case 151: /* stwx */ + case OP_31_XOP_STWX: rs = get_rs(inst); emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs], 4, 1); break; - case 215: /* stbx */ + case OP_31_XOP_STBX: rs = get_rs(inst); emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs], 1, 1); break; - case 247: /* stbux */ + case OP_31_XOP_STBUX: rs = get_rs(inst); ra = get_ra(inst); rb = get_rb(inst); @@ -126,12 +159,12 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) vcpu->arch.gpr[rs] = ea; break; - case 279: /* lhzx */ + case OP_31_XOP_LHZX: rt = get_rt(inst); emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1); break; - case 311: /* lhzux */ + case OP_31_XOP_LHZUX: rt = get_rt(inst); ra = get_ra(inst); rb = get_rb(inst); @@ -144,7 +177,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) vcpu->arch.gpr[ra] = ea; break; - case 339: /* mfspr */ + case OP_31_XOP_MFSPR: sprn = get_sprn(inst); rt = get_rt(inst); @@ -185,7 +218,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) } break; - case 407: /* sthx */ + case OP_31_XOP_STHX: rs = get_rs(inst); ra = get_ra(inst); rb = get_rb(inst); @@ -195,7 +228,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) 2, 1); break; - case 439: /* sthux */ + case OP_31_XOP_STHUX: rs = get_rs(inst); ra = get_ra(inst); rb = get_rb(inst); @@ -210,7 +243,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) vcpu->arch.gpr[ra] = ea; break; - case 467: /* mtspr */ + case OP_31_XOP_MTSPR: sprn = get_sprn(inst); rs = get_rs(inst); switch (sprn) { @@ -246,7 +279,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) } break; - case 470: /* dcbi */ + case OP_31_XOP_DCBI: /* Do nothing. The guest is performing dcbi because * hardware DMA is not snooped by the dcache, but * emulated DMA either goes through the dcache as @@ -254,15 +287,15 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) * coherence. */ break; - case 534: /* lwbrx */ + case OP_31_XOP_LWBRX: rt = get_rt(inst); emulated = kvmppc_handle_load(run, vcpu, rt, 4, 0); break; - case 566: /* tlbsync */ + case OP_31_XOP_TLBSYNC: break; - case 662: /* stwbrx */ + case OP_31_XOP_STWBRX: rs = get_rs(inst); ra = get_ra(inst); rb = get_rb(inst); @@ -272,12 +305,12 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) 4, 0); break; - case 790: /* lhbrx */ + case OP_31_XOP_LHBRX: rt = get_rt(inst); emulated = kvmppc_handle_load(run, vcpu, rt, 2, 0); break; - case 918: /* sthbrx */ + case OP_31_XOP_STHBRX: rs = get_rs(inst); ra = get_ra(inst); rb = get_rb(inst); @@ -293,37 +326,37 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) } break; - case 32: /* lwz */ + case OP_LWZ: rt = get_rt(inst); emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1); break; - case 33: /* lwzu */ + case OP_LWZU: ra = get_ra(inst); rt = get_rt(inst); emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1); vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed; break; - case 34: /* lbz */ + case OP_LBZ: rt = get_rt(inst); emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1); break; - case 35: /* lbzu */ + case OP_LBZU: ra = get_ra(inst); rt = get_rt(inst); emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1); vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed; break; - case 36: /* stw */ + case OP_STW: rs = get_rs(inst); emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs], 4, 1); break; - case 37: /* stwu */ + case OP_STWU: ra = get_ra(inst); rs = get_rs(inst); emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs], @@ -331,13 +364,13 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed; break; - case 38: /* stb */ + case OP_STB: rs = get_rs(inst); emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs], 1, 1); break; - case 39: /* stbu */ + case OP_STBU: ra = get_ra(inst); rs = get_rs(inst); emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs], @@ -345,25 +378,25 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed; break; - case 40: /* lhz */ + case OP_LHZ: rt = get_rt(inst); emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1); break; - case 41: /* lhzu */ + case OP_LHZU: ra = get_ra(inst); rt = get_rt(inst); emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1); vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed; break; - case 44: /* sth */ + case OP_STH: rs = get_rs(inst); emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs], 2, 1); break; - case 45: /* sthu */ + case OP_STHU: ra = get_ra(inst); rs = get_rs(inst); emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs], -- GitLab From d0c7dc03442f7cbd8740d9a4e7a4e7f84bfa676d Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Sat, 3 Jan 2009 16:23:06 -0600 Subject: [PATCH 4064/4982] KVM: ppc: split out common Book E instruction emulation The Book E code will be shared with e500. I've left PID in kvmppc_core_emulate_op() just so that we don't need to move kvmppc_set_pid() right now. Once we have the e500 implementation, we can probably share that too. Signed-off-by: Hollis Blanchard Signed-off-by: Avi Kivity --- arch/powerpc/kvm/44x_emulate.c | 217 ++----------------------- arch/powerpc/kvm/Makefile | 1 + arch/powerpc/kvm/booke.h | 6 + arch/powerpc/kvm/booke_emulate.c | 262 +++++++++++++++++++++++++++++++ 4 files changed, 284 insertions(+), 202 deletions(-) create mode 100644 arch/powerpc/kvm/booke_emulate.c diff --git a/arch/powerpc/kvm/44x_emulate.c b/arch/powerpc/kvm/44x_emulate.c index 82489a743a6..61af58fcece 100644 --- a/arch/powerpc/kvm/44x_emulate.c +++ b/arch/powerpc/kvm/44x_emulate.c @@ -27,25 +27,12 @@ #include "booke.h" #include "44x_tlb.h" -#define OP_RFI 19 - -#define XOP_RFI 50 -#define XOP_MFMSR 83 -#define XOP_WRTEE 131 -#define XOP_MTMSR 146 -#define XOP_WRTEEI 163 #define XOP_MFDCR 323 #define XOP_MTDCR 451 #define XOP_TLBSX 914 #define XOP_ICCCI 966 #define XOP_TLBWE 978 -static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu) -{ - vcpu->arch.pc = vcpu->arch.srr0; - kvmppc_set_msr(vcpu, vcpu->arch.srr1); -} - int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, unsigned int inst, int *advance) { @@ -59,48 +46,9 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, int ws; switch (get_op(inst)) { - case OP_RFI: - switch (get_xop(inst)) { - case XOP_RFI: - kvmppc_emul_rfi(vcpu); - kvmppc_set_exit_type(vcpu, EMULATED_RFI_EXITS); - *advance = 0; - break; - - default: - emulated = EMULATE_FAIL; - break; - } - break; - case 31: switch (get_xop(inst)) { - case XOP_MFMSR: - rt = get_rt(inst); - vcpu->arch.gpr[rt] = vcpu->arch.msr; - kvmppc_set_exit_type(vcpu, EMULATED_MFMSR_EXITS); - break; - - case XOP_MTMSR: - rs = get_rs(inst); - kvmppc_set_exit_type(vcpu, EMULATED_MTMSR_EXITS); - kvmppc_set_msr(vcpu, vcpu->arch.gpr[rs]); - break; - - case XOP_WRTEE: - rs = get_rs(inst); - vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE) - | (vcpu->arch.gpr[rs] & MSR_EE); - kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS); - break; - - case XOP_WRTEEI: - vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE) - | (inst & MSR_EE); - kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS); - break; - case XOP_MFDCR: dcrn = get_dcrn(inst); rt = get_rt(inst); @@ -186,186 +134,51 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, emulated = EMULATE_FAIL; } + if (emulated == EMULATE_FAIL) + emulated = kvmppc_booke_emulate_op(run, vcpu, inst, advance); + return emulated; } int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) { + int emulated = EMULATE_DONE; + switch (sprn) { - case SPRN_MMUCR: - vcpu->arch.mmucr = vcpu->arch.gpr[rs]; break; case SPRN_PID: kvmppc_set_pid(vcpu, vcpu->arch.gpr[rs]); break; + case SPRN_MMUCR: + vcpu->arch.mmucr = vcpu->arch.gpr[rs]; break; case SPRN_CCR0: vcpu->arch.ccr0 = vcpu->arch.gpr[rs]; break; case SPRN_CCR1: vcpu->arch.ccr1 = vcpu->arch.gpr[rs]; break; - case SPRN_DEAR: - vcpu->arch.dear = vcpu->arch.gpr[rs]; break; - case SPRN_ESR: - vcpu->arch.esr = vcpu->arch.gpr[rs]; break; - case SPRN_DBCR0: - vcpu->arch.dbcr0 = vcpu->arch.gpr[rs]; break; - case SPRN_DBCR1: - vcpu->arch.dbcr1 = vcpu->arch.gpr[rs]; break; - case SPRN_TSR: - vcpu->arch.tsr &= ~vcpu->arch.gpr[rs]; break; - case SPRN_TCR: - vcpu->arch.tcr = vcpu->arch.gpr[rs]; - kvmppc_emulate_dec(vcpu); - break; - - /* Note: SPRG4-7 are user-readable. These values are - * loaded into the real SPRGs when resuming the - * guest. */ - case SPRN_SPRG4: - vcpu->arch.sprg4 = vcpu->arch.gpr[rs]; break; - case SPRN_SPRG5: - vcpu->arch.sprg5 = vcpu->arch.gpr[rs]; break; - case SPRN_SPRG6: - vcpu->arch.sprg6 = vcpu->arch.gpr[rs]; break; - case SPRN_SPRG7: - vcpu->arch.sprg7 = vcpu->arch.gpr[rs]; break; - - case SPRN_IVPR: - vcpu->arch.ivpr = vcpu->arch.gpr[rs]; - break; - case SPRN_IVOR0: - vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL] = vcpu->arch.gpr[rs]; - break; - case SPRN_IVOR1: - vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK] = vcpu->arch.gpr[rs]; - break; - case SPRN_IVOR2: - vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE] = vcpu->arch.gpr[rs]; - break; - case SPRN_IVOR3: - vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE] = vcpu->arch.gpr[rs]; - break; - case SPRN_IVOR4: - vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL] = vcpu->arch.gpr[rs]; - break; - case SPRN_IVOR5: - vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT] = vcpu->arch.gpr[rs]; - break; - case SPRN_IVOR6: - vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM] = vcpu->arch.gpr[rs]; - break; - case SPRN_IVOR7: - vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL] = vcpu->arch.gpr[rs]; - break; - case SPRN_IVOR8: - vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL] = vcpu->arch.gpr[rs]; - break; - case SPRN_IVOR9: - vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL] = vcpu->arch.gpr[rs]; - break; - case SPRN_IVOR10: - vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER] = vcpu->arch.gpr[rs]; - break; - case SPRN_IVOR11: - vcpu->arch.ivor[BOOKE_IRQPRIO_FIT] = vcpu->arch.gpr[rs]; - break; - case SPRN_IVOR12: - vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG] = vcpu->arch.gpr[rs]; - break; - case SPRN_IVOR13: - vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS] = vcpu->arch.gpr[rs]; - break; - case SPRN_IVOR14: - vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS] = vcpu->arch.gpr[rs]; - break; - case SPRN_IVOR15: - vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG] = vcpu->arch.gpr[rs]; - break; - default: - return EMULATE_FAIL; + emulated = kvmppc_booke_emulate_mtspr(vcpu, sprn, rs); } kvmppc_set_exit_type(vcpu, EMULATED_MTSPR_EXITS); - return EMULATE_DONE; + return emulated; } int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt) { + int emulated = EMULATE_DONE; + switch (sprn) { - /* 440 */ + case SPRN_PID: + vcpu->arch.gpr[rt] = vcpu->arch.pid; break; case SPRN_MMUCR: vcpu->arch.gpr[rt] = vcpu->arch.mmucr; break; case SPRN_CCR0: vcpu->arch.gpr[rt] = vcpu->arch.ccr0; break; case SPRN_CCR1: vcpu->arch.gpr[rt] = vcpu->arch.ccr1; break; - - /* Book E */ - case SPRN_PID: - vcpu->arch.gpr[rt] = vcpu->arch.pid; break; - case SPRN_IVPR: - vcpu->arch.gpr[rt] = vcpu->arch.ivpr; break; - case SPRN_DEAR: - vcpu->arch.gpr[rt] = vcpu->arch.dear; break; - case SPRN_ESR: - vcpu->arch.gpr[rt] = vcpu->arch.esr; break; - case SPRN_DBCR0: - vcpu->arch.gpr[rt] = vcpu->arch.dbcr0; break; - case SPRN_DBCR1: - vcpu->arch.gpr[rt] = vcpu->arch.dbcr1; break; - - case SPRN_IVOR0: - vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL]; - break; - case SPRN_IVOR1: - vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK]; - break; - case SPRN_IVOR2: - vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE]; - break; - case SPRN_IVOR3: - vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE]; - break; - case SPRN_IVOR4: - vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL]; - break; - case SPRN_IVOR5: - vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT]; - break; - case SPRN_IVOR6: - vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM]; - break; - case SPRN_IVOR7: - vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL]; - break; - case SPRN_IVOR8: - vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL]; - break; - case SPRN_IVOR9: - vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL]; - break; - case SPRN_IVOR10: - vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER]; - break; - case SPRN_IVOR11: - vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_FIT]; - break; - case SPRN_IVOR12: - vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG]; - break; - case SPRN_IVOR13: - vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS]; - break; - case SPRN_IVOR14: - vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS]; - break; - case SPRN_IVOR15: - vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG]; - break; - default: - return EMULATE_FAIL; + emulated = kvmppc_booke_emulate_mfspr(vcpu, sprn, rt); } kvmppc_set_exit_type(vcpu, EMULATED_MFSPR_EXITS); - return EMULATE_DONE; + return emulated; } diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile index df7ba59e6d5..3ef5261828e 100644 --- a/arch/powerpc/kvm/Makefile +++ b/arch/powerpc/kvm/Makefile @@ -16,6 +16,7 @@ AFLAGS_booke_interrupts.o := -I$(obj) kvm-440-objs := \ booke.o \ + booke_emulate.o \ booke_interrupts.o \ 44x.o \ 44x_tlb.o \ diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h index cf7c94ca24b..311fdbc23fb 100644 --- a/arch/powerpc/kvm/booke.h +++ b/arch/powerpc/kvm/booke.h @@ -22,6 +22,7 @@ #include #include +#include #include "timing.h" /* interrupt priortity ordering */ @@ -57,4 +58,9 @@ static inline void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr) }; } +int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, + unsigned int inst, int *advance); +int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt); +int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs); + #endif /* __KVM_BOOKE_H__ */ diff --git a/arch/powerpc/kvm/booke_emulate.c b/arch/powerpc/kvm/booke_emulate.c new file mode 100644 index 00000000000..8aa78f1a1f8 --- /dev/null +++ b/arch/powerpc/kvm/booke_emulate.c @@ -0,0 +1,262 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright IBM Corp. 2008 + * + * Authors: Hollis Blanchard + */ + +#include +#include + +#include "booke.h" + +#define OP_19_XOP_RFI 50 + +#define OP_31_XOP_MFMSR 83 +#define OP_31_XOP_WRTEE 131 +#define OP_31_XOP_MTMSR 146 +#define OP_31_XOP_WRTEEI 163 + +static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu) +{ + vcpu->arch.pc = vcpu->arch.srr0; + kvmppc_set_msr(vcpu, vcpu->arch.srr1); +} + +int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, + unsigned int inst, int *advance) +{ + int emulated = EMULATE_DONE; + int rs; + int rt; + + switch (get_op(inst)) { + case 19: + switch (get_xop(inst)) { + case OP_19_XOP_RFI: + kvmppc_emul_rfi(vcpu); + kvmppc_set_exit_type(vcpu, EMULATED_RFI_EXITS); + *advance = 0; + break; + + default: + emulated = EMULATE_FAIL; + break; + } + break; + + case 31: + switch (get_xop(inst)) { + + case OP_31_XOP_MFMSR: + rt = get_rt(inst); + vcpu->arch.gpr[rt] = vcpu->arch.msr; + kvmppc_set_exit_type(vcpu, EMULATED_MFMSR_EXITS); + break; + + case OP_31_XOP_MTMSR: + rs = get_rs(inst); + kvmppc_set_exit_type(vcpu, EMULATED_MTMSR_EXITS); + kvmppc_set_msr(vcpu, vcpu->arch.gpr[rs]); + break; + + case OP_31_XOP_WRTEE: + rs = get_rs(inst); + vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE) + | (vcpu->arch.gpr[rs] & MSR_EE); + kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS); + break; + + case OP_31_XOP_WRTEEI: + vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE) + | (inst & MSR_EE); + kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS); + break; + + default: + emulated = EMULATE_FAIL; + } + + break; + + default: + emulated = EMULATE_FAIL; + } + + return emulated; +} + +int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) +{ + int emulated = EMULATE_DONE; + + switch (sprn) { + case SPRN_DEAR: + vcpu->arch.dear = vcpu->arch.gpr[rs]; break; + case SPRN_ESR: + vcpu->arch.esr = vcpu->arch.gpr[rs]; break; + case SPRN_DBCR0: + vcpu->arch.dbcr0 = vcpu->arch.gpr[rs]; break; + case SPRN_DBCR1: + vcpu->arch.dbcr1 = vcpu->arch.gpr[rs]; break; + case SPRN_TSR: + vcpu->arch.tsr &= ~vcpu->arch.gpr[rs]; break; + case SPRN_TCR: + vcpu->arch.tcr = vcpu->arch.gpr[rs]; + kvmppc_emulate_dec(vcpu); + break; + + /* Note: SPRG4-7 are user-readable. These values are + * loaded into the real SPRGs when resuming the + * guest. */ + case SPRN_SPRG4: + vcpu->arch.sprg4 = vcpu->arch.gpr[rs]; break; + case SPRN_SPRG5: + vcpu->arch.sprg5 = vcpu->arch.gpr[rs]; break; + case SPRN_SPRG6: + vcpu->arch.sprg6 = vcpu->arch.gpr[rs]; break; + case SPRN_SPRG7: + vcpu->arch.sprg7 = vcpu->arch.gpr[rs]; break; + + case SPRN_IVPR: + vcpu->arch.ivpr = vcpu->arch.gpr[rs]; + break; + case SPRN_IVOR0: + vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL] = vcpu->arch.gpr[rs]; + break; + case SPRN_IVOR1: + vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK] = vcpu->arch.gpr[rs]; + break; + case SPRN_IVOR2: + vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE] = vcpu->arch.gpr[rs]; + break; + case SPRN_IVOR3: + vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE] = vcpu->arch.gpr[rs]; + break; + case SPRN_IVOR4: + vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL] = vcpu->arch.gpr[rs]; + break; + case SPRN_IVOR5: + vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT] = vcpu->arch.gpr[rs]; + break; + case SPRN_IVOR6: + vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM] = vcpu->arch.gpr[rs]; + break; + case SPRN_IVOR7: + vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL] = vcpu->arch.gpr[rs]; + break; + case SPRN_IVOR8: + vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL] = vcpu->arch.gpr[rs]; + break; + case SPRN_IVOR9: + vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL] = vcpu->arch.gpr[rs]; + break; + case SPRN_IVOR10: + vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER] = vcpu->arch.gpr[rs]; + break; + case SPRN_IVOR11: + vcpu->arch.ivor[BOOKE_IRQPRIO_FIT] = vcpu->arch.gpr[rs]; + break; + case SPRN_IVOR12: + vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG] = vcpu->arch.gpr[rs]; + break; + case SPRN_IVOR13: + vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS] = vcpu->arch.gpr[rs]; + break; + case SPRN_IVOR14: + vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS] = vcpu->arch.gpr[rs]; + break; + case SPRN_IVOR15: + vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG] = vcpu->arch.gpr[rs]; + break; + + default: + emulated = EMULATE_FAIL; + } + + return emulated; +} + +int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt) +{ + int emulated = EMULATE_DONE; + + switch (sprn) { + case SPRN_IVPR: + vcpu->arch.gpr[rt] = vcpu->arch.ivpr; break; + case SPRN_DEAR: + vcpu->arch.gpr[rt] = vcpu->arch.dear; break; + case SPRN_ESR: + vcpu->arch.gpr[rt] = vcpu->arch.esr; break; + case SPRN_DBCR0: + vcpu->arch.gpr[rt] = vcpu->arch.dbcr0; break; + case SPRN_DBCR1: + vcpu->arch.gpr[rt] = vcpu->arch.dbcr1; break; + + case SPRN_IVOR0: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL]; + break; + case SPRN_IVOR1: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK]; + break; + case SPRN_IVOR2: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE]; + break; + case SPRN_IVOR3: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE]; + break; + case SPRN_IVOR4: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL]; + break; + case SPRN_IVOR5: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT]; + break; + case SPRN_IVOR6: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM]; + break; + case SPRN_IVOR7: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL]; + break; + case SPRN_IVOR8: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL]; + break; + case SPRN_IVOR9: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL]; + break; + case SPRN_IVOR10: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER]; + break; + case SPRN_IVOR11: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_FIT]; + break; + case SPRN_IVOR12: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG]; + break; + case SPRN_IVOR13: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS]; + break; + case SPRN_IVOR14: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS]; + break; + case SPRN_IVOR15: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG]; + break; + + default: + emulated = EMULATE_FAIL; + } + + return emulated; +} -- GitLab From f7b200af8f1da748cc67993caeff3923d6014070 Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Sat, 3 Jan 2009 16:23:07 -0600 Subject: [PATCH 4065/4982] KVM: ppc: Add dbsr in kvm_vcpu_arch Kernel for E500 need clear dbsr when startup. So add dbsr register in kvm_vcpu_arch for BOOKE. Signed-off-by: Liu Yu Signed-off-by: Hollis Blanchard Signed-off-by: Avi Kivity --- arch/powerpc/include/asm/kvm_host.h | 1 + arch/powerpc/kvm/booke_emulate.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 65c4d492d72..50e5ce1b400 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -163,6 +163,7 @@ struct kvm_vcpu_arch { u32 ccr1; u32 dbcr0; u32 dbcr1; + u32 dbsr; #ifdef CONFIG_KVM_EXIT_TIMING struct kvmppc_exit_timing timing_exit; diff --git a/arch/powerpc/kvm/booke_emulate.c b/arch/powerpc/kvm/booke_emulate.c index 8aa78f1a1f8..aebc65e93f4 100644 --- a/arch/powerpc/kvm/booke_emulate.c +++ b/arch/powerpc/kvm/booke_emulate.c @@ -111,6 +111,8 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) vcpu->arch.dbcr0 = vcpu->arch.gpr[rs]; break; case SPRN_DBCR1: vcpu->arch.dbcr1 = vcpu->arch.gpr[rs]; break; + case SPRN_DBSR: + vcpu->arch.dbsr &= ~vcpu->arch.gpr[rs]; break; case SPRN_TSR: vcpu->arch.tsr &= ~vcpu->arch.gpr[rs]; break; case SPRN_TCR: @@ -204,6 +206,8 @@ int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt) vcpu->arch.gpr[rt] = vcpu->arch.dbcr0; break; case SPRN_DBCR1: vcpu->arch.gpr[rt] = vcpu->arch.dbcr1; break; + case SPRN_DBSR: + vcpu->arch.gpr[rt] = vcpu->arch.dbsr; break; case SPRN_IVOR0: vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL]; -- GitLab From 366d4b9b9fdda282006b97316f8038cd36f8ecb7 Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Sat, 3 Jan 2009 16:23:08 -0600 Subject: [PATCH 4066/4982] KVM: ppc: No need to include core-header for KVM in asm-offsets.c currently Signed-off-by: Liu Yu Signed-off-by: Hollis Blanchard Signed-off-by: Avi Kivity --- arch/powerpc/kernel/asm-offsets.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 19ee491e9e2..42fe4da4e8a 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -49,7 +49,7 @@ #include #endif #ifdef CONFIG_KVM -#include +#include #endif #if defined(CONFIG_BOOKE) || defined(CONFIG_40x) @@ -361,8 +361,6 @@ int main(void) DEFINE(PTE_SIZE, sizeof(pte_t)); #ifdef CONFIG_KVM - DEFINE(TLBE_BYTES, sizeof(struct kvmppc_44x_tlbe)); - DEFINE(VCPU_HOST_STACK, offsetof(struct kvm_vcpu, arch.host_stack)); DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid)); DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr)); -- GitLab From 17c885eb5c38f39a2bb3143a67687bd905dcd0fa Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Sat, 3 Jan 2009 16:23:09 -0600 Subject: [PATCH 4067/4982] KVM: ppc: ifdef iccci with CONFIG_44x E500 deosn't support this instruction. Signed-off-by: Liu Yu Signed-off-by: Hollis Blanchard Signed-off-by: Avi Kivity --- arch/powerpc/kvm/booke_interrupts.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S index 084ebcd7dd8..4679ec287e6 100644 --- a/arch/powerpc/kvm/booke_interrupts.S +++ b/arch/powerpc/kvm/booke_interrupts.S @@ -347,7 +347,9 @@ lightweight_exit: lwz r3, VCPU_SHADOW_PID(r4) mtspr SPRN_PID, r3 +#ifdef CONFIG_44x iccci 0, 0 /* XXX hack */ +#endif /* Load some guest volatiles. */ lwz r0, VCPU_GPR(r0)(r4) -- GitLab From bc8080cbcc8870178f0910edd537d0cb5706d703 Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Sat, 3 Jan 2009 16:23:10 -0600 Subject: [PATCH 4068/4982] KVM: ppc: E500 core-specific code Signed-off-by: Liu Yu Signed-off-by: Hollis Blanchard Signed-off-by: Avi Kivity --- arch/powerpc/include/asm/kvm_e500.h | 67 +++ arch/powerpc/kvm/Kconfig | 13 + arch/powerpc/kvm/Makefile | 9 + arch/powerpc/kvm/e500.c | 151 ++++++ arch/powerpc/kvm/e500_emulate.c | 169 +++++++ arch/powerpc/kvm/e500_tlb.c | 737 ++++++++++++++++++++++++++++ arch/powerpc/kvm/e500_tlb.h | 184 +++++++ 7 files changed, 1330 insertions(+) create mode 100644 arch/powerpc/include/asm/kvm_e500.h create mode 100644 arch/powerpc/kvm/e500.c create mode 100644 arch/powerpc/kvm/e500_emulate.c create mode 100644 arch/powerpc/kvm/e500_tlb.c create mode 100644 arch/powerpc/kvm/e500_tlb.h diff --git a/arch/powerpc/include/asm/kvm_e500.h b/arch/powerpc/include/asm/kvm_e500.h new file mode 100644 index 00000000000..9d497ce4972 --- /dev/null +++ b/arch/powerpc/include/asm/kvm_e500.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved. + * + * Author: Yu Liu, + * + * Description: + * This file is derived from arch/powerpc/include/asm/kvm_44x.h, + * by Hollis Blanchard . + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_KVM_E500_H__ +#define __ASM_KVM_E500_H__ + +#include + +#define BOOKE_INTERRUPT_SIZE 36 + +#define E500_PID_NUM 3 +#define E500_TLB_NUM 2 + +struct tlbe{ + u32 mas1; + u32 mas2; + u32 mas3; + u32 mas7; +}; + +struct kvmppc_vcpu_e500 { + /* Unmodified copy of the guest's TLB. */ + struct tlbe *guest_tlb[E500_TLB_NUM]; + /* TLB that's actually used when the guest is running. */ + struct tlbe *shadow_tlb[E500_TLB_NUM]; + /* Pages which are referenced in the shadow TLB. */ + struct page **shadow_pages[E500_TLB_NUM]; + + unsigned int guest_tlb_size[E500_TLB_NUM]; + unsigned int shadow_tlb_size[E500_TLB_NUM]; + unsigned int guest_tlb_nv[E500_TLB_NUM]; + + u32 host_pid[E500_PID_NUM]; + u32 pid[E500_PID_NUM]; + + u32 mas0; + u32 mas1; + u32 mas2; + u32 mas3; + u32 mas4; + u32 mas5; + u32 mas6; + u32 mas7; + u32 l1csr1; + u32 hid0; + u32 hid1; + + struct kvm_vcpu vcpu; +}; + +static inline struct kvmppc_vcpu_e500 *to_e500(struct kvm_vcpu *vcpu) +{ + return container_of(vcpu, struct kvmppc_vcpu_e500, vcpu); +} + +#endif /* __ASM_KVM_E500_H__ */ diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig index 6dbdc4817d8..14657055014 100644 --- a/arch/powerpc/kvm/Kconfig +++ b/arch/powerpc/kvm/Kconfig @@ -43,6 +43,19 @@ config KVM_EXIT_TIMING If unsure, say N. +config KVM_E500 + bool "KVM support for PowerPC E500 processors" + depends on EXPERIMENTAL && E500 + select KVM + ---help--- + Support running unmodified E500 guest kernels in virtual machines on + E500 host processors. + + This module provides access to the hardware capabilities through + a character device node named /dev/kvm. + + If unsure, say N. + config KVM_TRACE bool "KVM trace support" depends on KVM && MARKERS && SYSFS diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile index 3ef5261828e..4b2df66c79d 100644 --- a/arch/powerpc/kvm/Makefile +++ b/arch/powerpc/kvm/Makefile @@ -22,3 +22,12 @@ kvm-440-objs := \ 44x_tlb.o \ 44x_emulate.o obj-$(CONFIG_KVM_440) += kvm-440.o + +kvm-e500-objs := \ + booke.o \ + booke_emulate.o \ + booke_interrupts.o \ + e500.o \ + e500_tlb.o \ + e500_emulate.o +obj-$(CONFIG_KVM_E500) += kvm-e500.o diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c new file mode 100644 index 00000000000..7992da497cd --- /dev/null +++ b/arch/powerpc/kvm/e500.c @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved. + * + * Author: Yu Liu, + * + * Description: + * This file is derived from arch/powerpc/kvm/44x.c, + * by Hollis Blanchard . + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "e500_tlb.h" + +void kvmppc_core_load_host_debugstate(struct kvm_vcpu *vcpu) +{ +} + +void kvmppc_core_load_guest_debugstate(struct kvm_vcpu *vcpu) +{ +} + +void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) +{ + kvmppc_e500_tlb_load(vcpu, cpu); +} + +void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) +{ + kvmppc_e500_tlb_put(vcpu); +} + +int kvmppc_core_check_processor_compat(void) +{ + int r; + + if (strcmp(cur_cpu_spec->cpu_name, "e500v2") == 0) + r = 0; + else + r = -ENOTSUPP; + + return r; +} + +int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu) +{ + struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); + + kvmppc_e500_tlb_setup(vcpu_e500); + + /* Use the same core vertion as host's */ + vcpu->arch.pvr = mfspr(SPRN_PVR); + + return 0; +} + +/* 'linear_address' is actually an encoding of AS|PID|EADDR . */ +int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu, + struct kvm_translation *tr) +{ + int index; + gva_t eaddr; + u8 pid; + u8 as; + + eaddr = tr->linear_address; + pid = (tr->linear_address >> 32) & 0xff; + as = (tr->linear_address >> 40) & 0x1; + + index = kvmppc_e500_tlb_search(vcpu, eaddr, pid, as); + if (index < 0) { + tr->valid = 0; + return 0; + } + + tr->physical_address = kvmppc_mmu_xlate(vcpu, index, eaddr); + /* XXX what does "writeable" and "usermode" even mean? */ + tr->valid = 1; + + return 0; +} + +struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) +{ + struct kvmppc_vcpu_e500 *vcpu_e500; + struct kvm_vcpu *vcpu; + int err; + + vcpu_e500 = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); + if (!vcpu_e500) { + err = -ENOMEM; + goto out; + } + + vcpu = &vcpu_e500->vcpu; + err = kvm_vcpu_init(vcpu, kvm, id); + if (err) + goto free_vcpu; + + err = kvmppc_e500_tlb_init(vcpu_e500); + if (err) + goto uninit_vcpu; + + return vcpu; + +uninit_vcpu: + kvm_vcpu_uninit(vcpu); +free_vcpu: + kmem_cache_free(kvm_vcpu_cache, vcpu_e500); +out: + return ERR_PTR(err); +} + +void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) +{ + struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); + + kvmppc_e500_tlb_uninit(vcpu_e500); + kvm_vcpu_uninit(vcpu); + kmem_cache_free(kvm_vcpu_cache, vcpu_e500); +} + +static int kvmppc_e500_init(void) +{ + int r; + + r = kvmppc_booke_init(); + if (r) + return r; + + return kvm_init(NULL, sizeof(struct kvmppc_vcpu_e500), THIS_MODULE); +} + +static void kvmppc_e500_exit(void) +{ + kvmppc_booke_exit(); +} + +module_init(kvmppc_e500_init); +module_exit(kvmppc_e500_exit); diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c new file mode 100644 index 00000000000..a47f44cd2cf --- /dev/null +++ b/arch/powerpc/kvm/e500_emulate.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved. + * + * Author: Yu Liu, + * + * Description: + * This file is derived from arch/powerpc/kvm/44x_emulate.c, + * by Hollis Blanchard . + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +#include "booke.h" +#include "e500_tlb.h" + +#define XOP_TLBIVAX 786 +#define XOP_TLBSX 914 +#define XOP_TLBRE 946 +#define XOP_TLBWE 978 + +int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, + unsigned int inst, int *advance) +{ + int emulated = EMULATE_DONE; + int ra; + int rb; + int rs; + int rt; + + switch (get_op(inst)) { + case 31: + switch (get_xop(inst)) { + + case XOP_TLBRE: + emulated = kvmppc_e500_emul_tlbre(vcpu); + break; + + case XOP_TLBWE: + emulated = kvmppc_e500_emul_tlbwe(vcpu); + break; + + case XOP_TLBSX: + rb = get_rb(inst); + emulated = kvmppc_e500_emul_tlbsx(vcpu,rb); + break; + + case XOP_TLBIVAX: + ra = get_ra(inst); + rb = get_rb(inst); + emulated = kvmppc_e500_emul_tlbivax(vcpu, ra, rb); + break; + + default: + emulated = EMULATE_FAIL; + } + + break; + + default: + emulated = EMULATE_FAIL; + } + + if (emulated == EMULATE_FAIL) + emulated = kvmppc_booke_emulate_op(run, vcpu, inst, advance); + + return emulated; +} + +int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) +{ + struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); + int emulated = EMULATE_DONE; + + switch (sprn) { + case SPRN_PID: + vcpu_e500->pid[0] = vcpu->arch.shadow_pid = + vcpu->arch.pid = vcpu->arch.gpr[rs]; + break; + case SPRN_PID1: + vcpu_e500->pid[1] = vcpu->arch.gpr[rs]; break; + case SPRN_PID2: + vcpu_e500->pid[2] = vcpu->arch.gpr[rs]; break; + case SPRN_MAS0: + vcpu_e500->mas0 = vcpu->arch.gpr[rs]; break; + case SPRN_MAS1: + vcpu_e500->mas1 = vcpu->arch.gpr[rs]; break; + case SPRN_MAS2: + vcpu_e500->mas2 = vcpu->arch.gpr[rs]; break; + case SPRN_MAS3: + vcpu_e500->mas3 = vcpu->arch.gpr[rs]; break; + case SPRN_MAS4: + vcpu_e500->mas4 = vcpu->arch.gpr[rs]; break; + case SPRN_MAS6: + vcpu_e500->mas6 = vcpu->arch.gpr[rs]; break; + case SPRN_MAS7: + vcpu_e500->mas7 = vcpu->arch.gpr[rs]; break; + case SPRN_L1CSR1: + vcpu_e500->l1csr1 = vcpu->arch.gpr[rs]; break; + case SPRN_HID0: + vcpu_e500->hid0 = vcpu->arch.gpr[rs]; break; + case SPRN_HID1: + vcpu_e500->hid1 = vcpu->arch.gpr[rs]; break; + + default: + emulated = kvmppc_booke_emulate_mtspr(vcpu, sprn, rs); + } + + return emulated; +} + +int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt) +{ + struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); + int emulated = EMULATE_DONE; + + switch (sprn) { + case SPRN_PID: + vcpu->arch.gpr[rt] = vcpu_e500->pid[0]; break; + case SPRN_PID1: + vcpu->arch.gpr[rt] = vcpu_e500->pid[1]; break; + case SPRN_PID2: + vcpu->arch.gpr[rt] = vcpu_e500->pid[2]; break; + case SPRN_MAS0: + vcpu->arch.gpr[rt] = vcpu_e500->mas0; break; + case SPRN_MAS1: + vcpu->arch.gpr[rt] = vcpu_e500->mas1; break; + case SPRN_MAS2: + vcpu->arch.gpr[rt] = vcpu_e500->mas2; break; + case SPRN_MAS3: + vcpu->arch.gpr[rt] = vcpu_e500->mas3; break; + case SPRN_MAS4: + vcpu->arch.gpr[rt] = vcpu_e500->mas4; break; + case SPRN_MAS6: + vcpu->arch.gpr[rt] = vcpu_e500->mas6; break; + case SPRN_MAS7: + vcpu->arch.gpr[rt] = vcpu_e500->mas7; break; + + case SPRN_TLB0CFG: + vcpu->arch.gpr[rt] = mfspr(SPRN_TLB0CFG); + vcpu->arch.gpr[rt] &= ~0xfffUL; + vcpu->arch.gpr[rt] |= vcpu_e500->guest_tlb_size[0]; + break; + + case SPRN_TLB1CFG: + vcpu->arch.gpr[rt] = mfspr(SPRN_TLB1CFG); + vcpu->arch.gpr[rt] &= ~0xfffUL; + vcpu->arch.gpr[rt] |= vcpu_e500->guest_tlb_size[1]; + break; + + case SPRN_L1CSR1: + vcpu->arch.gpr[rt] = vcpu_e500->l1csr1; break; + case SPRN_HID0: + vcpu->arch.gpr[rt] = vcpu_e500->hid0; break; + case SPRN_HID1: + vcpu->arch.gpr[rt] = vcpu_e500->hid1; break; + + default: + emulated = kvmppc_booke_emulate_mfspr(vcpu, sprn, rt); + } + + return emulated; +} + diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c new file mode 100644 index 00000000000..6a50340f575 --- /dev/null +++ b/arch/powerpc/kvm/e500_tlb.c @@ -0,0 +1,737 @@ +/* + * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved. + * + * Author: Yu Liu, yu.liu@freescale.com + * + * Description: + * This file is based on arch/powerpc/kvm/44x_tlb.c, + * by Hollis Blanchard . + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "e500_tlb.h" + +#define to_htlb1_esel(esel) (tlb1_entry_num - (esel) - 1) + +static unsigned int tlb1_entry_num; + +void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu) +{ + struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); + struct tlbe *tlbe; + int i, tlbsel; + + printk("| %8s | %8s | %8s | %8s | %8s |\n", + "nr", "mas1", "mas2", "mas3", "mas7"); + + for (tlbsel = 0; tlbsel < 2; tlbsel++) { + printk("Guest TLB%d:\n", tlbsel); + for (i = 0; i < vcpu_e500->guest_tlb_size[tlbsel]; i++) { + tlbe = &vcpu_e500->guest_tlb[tlbsel][i]; + if (tlbe->mas1 & MAS1_VALID) + printk(" G[%d][%3d] | %08X | %08X | %08X | %08X |\n", + tlbsel, i, tlbe->mas1, tlbe->mas2, + tlbe->mas3, tlbe->mas7); + } + } + + for (tlbsel = 0; tlbsel < 2; tlbsel++) { + printk("Shadow TLB%d:\n", tlbsel); + for (i = 0; i < vcpu_e500->shadow_tlb_size[tlbsel]; i++) { + tlbe = &vcpu_e500->shadow_tlb[tlbsel][i]; + if (tlbe->mas1 & MAS1_VALID) + printk(" S[%d][%3d] | %08X | %08X | %08X | %08X |\n", + tlbsel, i, tlbe->mas1, tlbe->mas2, + tlbe->mas3, tlbe->mas7); + } + } +} + +static inline unsigned int tlb0_get_next_victim( + struct kvmppc_vcpu_e500 *vcpu_e500) +{ + unsigned int victim; + + victim = vcpu_e500->guest_tlb_nv[0]++; + if (unlikely(vcpu_e500->guest_tlb_nv[0] >= KVM_E500_TLB0_WAY_NUM)) + vcpu_e500->guest_tlb_nv[0] = 0; + + return victim; +} + +static inline unsigned int tlb1_max_shadow_size(void) +{ + return tlb1_entry_num - tlbcam_index; +} + +static inline int tlbe_is_writable(struct tlbe *tlbe) +{ + return tlbe->mas3 & (MAS3_SW|MAS3_UW); +} + +static inline u32 e500_shadow_mas3_attrib(u32 mas3, int usermode) +{ + /* Mask off reserved bits. */ + mas3 &= MAS3_ATTRIB_MASK; + + if (!usermode) { + /* Guest is in supervisor mode, + * so we need to translate guest + * supervisor permissions into user permissions. */ + mas3 &= ~E500_TLB_USER_PERM_MASK; + mas3 |= (mas3 & E500_TLB_SUPER_PERM_MASK) << 1; + } + + return mas3 | E500_TLB_SUPER_PERM_MASK; +} + +static inline u32 e500_shadow_mas2_attrib(u32 mas2, int usermode) +{ + return mas2 & MAS2_ATTRIB_MASK; +} + +/* + * writing shadow tlb entry to host TLB + */ +static inline void __write_host_tlbe(struct tlbe *stlbe) +{ + mtspr(SPRN_MAS1, stlbe->mas1); + mtspr(SPRN_MAS2, stlbe->mas2); + mtspr(SPRN_MAS3, stlbe->mas3); + mtspr(SPRN_MAS7, stlbe->mas7); + __asm__ __volatile__ ("tlbwe\n" : : ); +} + +static inline void write_host_tlbe(struct kvmppc_vcpu_e500 *vcpu_e500, + int tlbsel, int esel) +{ + struct tlbe *stlbe = &vcpu_e500->shadow_tlb[tlbsel][esel]; + + local_irq_disable(); + if (tlbsel == 0) { + __write_host_tlbe(stlbe); + } else { + unsigned register mas0; + + mas0 = mfspr(SPRN_MAS0); + + mtspr(SPRN_MAS0, MAS0_TLBSEL(1) | MAS0_ESEL(to_htlb1_esel(esel))); + __write_host_tlbe(stlbe); + + mtspr(SPRN_MAS0, mas0); + } + local_irq_enable(); +} + +void kvmppc_e500_tlb_load(struct kvm_vcpu *vcpu, int cpu) +{ + struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); + int i; + unsigned register mas0; + + /* Load all valid TLB1 entries to reduce guest tlb miss fault */ + local_irq_disable(); + mas0 = mfspr(SPRN_MAS0); + for (i = 0; i < tlb1_max_shadow_size(); i++) { + struct tlbe *stlbe = &vcpu_e500->shadow_tlb[1][i]; + + if (get_tlb_v(stlbe)) { + mtspr(SPRN_MAS0, MAS0_TLBSEL(1) + | MAS0_ESEL(to_htlb1_esel(i))); + __write_host_tlbe(stlbe); + } + } + mtspr(SPRN_MAS0, mas0); + local_irq_enable(); +} + +void kvmppc_e500_tlb_put(struct kvm_vcpu *vcpu) +{ + _tlbia(); +} + +/* Search the guest TLB for a matching entry. */ +static int kvmppc_e500_tlb_index(struct kvmppc_vcpu_e500 *vcpu_e500, + gva_t eaddr, int tlbsel, unsigned int pid, int as) +{ + int i; + + /* XXX Replace loop with fancy data structures. */ + for (i = 0; i < vcpu_e500->guest_tlb_size[tlbsel]; i++) { + struct tlbe *tlbe = &vcpu_e500->guest_tlb[tlbsel][i]; + unsigned int tid; + + if (eaddr < get_tlb_eaddr(tlbe)) + continue; + + if (eaddr > get_tlb_end(tlbe)) + continue; + + tid = get_tlb_tid(tlbe); + if (tid && (tid != pid)) + continue; + + if (!get_tlb_v(tlbe)) + continue; + + if (get_tlb_ts(tlbe) != as && as != -1) + continue; + + return i; + } + + return -1; +} + +static void kvmppc_e500_shadow_release(struct kvmppc_vcpu_e500 *vcpu_e500, + int tlbsel, int esel) +{ + struct tlbe *stlbe = &vcpu_e500->shadow_tlb[tlbsel][esel]; + struct page *page = vcpu_e500->shadow_pages[tlbsel][esel]; + + if (page) { + vcpu_e500->shadow_pages[tlbsel][esel] = NULL; + + if (get_tlb_v(stlbe)) { + if (tlbe_is_writable(stlbe)) + kvm_release_page_dirty(page); + else + kvm_release_page_clean(page); + } + } +} + +static void kvmppc_e500_stlbe_invalidate(struct kvmppc_vcpu_e500 *vcpu_e500, + int tlbsel, int esel) +{ + struct tlbe *stlbe = &vcpu_e500->shadow_tlb[tlbsel][esel]; + + kvmppc_e500_shadow_release(vcpu_e500, tlbsel, esel); + stlbe->mas1 = 0; + KVMTRACE_5D(STLB_INVAL, &vcpu_e500->vcpu, index_of(tlbsel, esel), + stlbe->mas1, stlbe->mas2, stlbe->mas3, stlbe->mas7, + handler); +} + +static void kvmppc_e500_tlb1_invalidate(struct kvmppc_vcpu_e500 *vcpu_e500, + gva_t eaddr, gva_t eend, u32 tid) +{ + unsigned int pid = tid & 0xff; + unsigned int i; + + /* XXX Replace loop with fancy data structures. */ + for (i = 0; i < vcpu_e500->guest_tlb_size[1]; i++) { + struct tlbe *stlbe = &vcpu_e500->shadow_tlb[1][i]; + unsigned int tid; + + if (!get_tlb_v(stlbe)) + continue; + + if (eend < get_tlb_eaddr(stlbe)) + continue; + + if (eaddr > get_tlb_end(stlbe)) + continue; + + tid = get_tlb_tid(stlbe); + if (tid && (tid != pid)) + continue; + + kvmppc_e500_stlbe_invalidate(vcpu_e500, 1, i); + write_host_tlbe(vcpu_e500, 1, i); + } +} + +static inline void kvmppc_e500_deliver_tlb_miss(struct kvm_vcpu *vcpu, + unsigned int eaddr, int as) +{ + struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); + unsigned int victim, pidsel, tsized; + int tlbsel; + + /* since we only have tow TLBs, only lower bit is used. */ + tlbsel = (vcpu_e500->mas4 >> 28) & 0x1; + victim = (tlbsel == 0) ? tlb0_get_next_victim(vcpu_e500) : 0; + pidsel = (vcpu_e500->mas4 >> 16) & 0xf; + tsized = (vcpu_e500->mas4 >> 8) & 0xf; + + vcpu_e500->mas0 = MAS0_TLBSEL(tlbsel) | MAS0_ESEL(victim) + | MAS0_NV(vcpu_e500->guest_tlb_nv[tlbsel]); + vcpu_e500->mas1 = MAS1_VALID | (as ? MAS1_TS : 0) + | MAS1_TID(vcpu_e500->pid[pidsel]) + | MAS1_TSIZE(tsized); + vcpu_e500->mas2 = (eaddr & MAS2_EPN) + | (vcpu_e500->mas4 & MAS2_ATTRIB_MASK); + vcpu_e500->mas3 &= MAS3_U0 | MAS3_U1 | MAS3_U2 | MAS3_U3; + vcpu_e500->mas6 = (vcpu_e500->mas6 & MAS6_SPID1) + | (get_cur_pid(vcpu) << 16) + | (as ? MAS6_SAS : 0); + vcpu_e500->mas7 = 0; +} + +static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, + u64 gvaddr, gfn_t gfn, struct tlbe *gtlbe, int tlbsel, int esel) +{ + struct page *new_page; + struct tlbe *stlbe; + hpa_t hpaddr; + + stlbe = &vcpu_e500->shadow_tlb[tlbsel][esel]; + + /* Get reference to new page. */ + new_page = gfn_to_page(vcpu_e500->vcpu.kvm, gfn); + if (is_error_page(new_page)) { + printk(KERN_ERR "Couldn't get guest page for gfn %lx!\n", gfn); + kvm_release_page_clean(new_page); + return; + } + hpaddr = page_to_phys(new_page); + + /* Drop reference to old page. */ + kvmppc_e500_shadow_release(vcpu_e500, tlbsel, esel); + + vcpu_e500->shadow_pages[tlbsel][esel] = new_page; + + /* Force TS=1 IPROT=0 TSIZE=4KB for all guest mappings. */ + stlbe->mas1 = MAS1_TSIZE(BOOKE_PAGESZ_4K) + | MAS1_TID(get_tlb_tid(gtlbe)) | MAS1_TS | MAS1_VALID; + stlbe->mas2 = (gvaddr & MAS2_EPN) + | e500_shadow_mas2_attrib(gtlbe->mas2, + vcpu_e500->vcpu.arch.msr & MSR_PR); + stlbe->mas3 = (hpaddr & MAS3_RPN) + | e500_shadow_mas3_attrib(gtlbe->mas3, + vcpu_e500->vcpu.arch.msr & MSR_PR); + stlbe->mas7 = (hpaddr >> 32) & MAS7_RPN; + + KVMTRACE_5D(STLB_WRITE, &vcpu_e500->vcpu, index_of(tlbsel, esel), + stlbe->mas1, stlbe->mas2, stlbe->mas3, stlbe->mas7, + handler); +} + +/* XXX only map the one-one case, for now use TLB0 */ +static int kvmppc_e500_stlbe_map(struct kvmppc_vcpu_e500 *vcpu_e500, + int tlbsel, int esel) +{ + struct tlbe *gtlbe; + + gtlbe = &vcpu_e500->guest_tlb[tlbsel][esel]; + + kvmppc_e500_shadow_map(vcpu_e500, get_tlb_eaddr(gtlbe), + get_tlb_raddr(gtlbe) >> PAGE_SHIFT, + gtlbe, tlbsel, esel); + + return esel; +} + +/* Caller must ensure that the specified guest TLB entry is safe to insert into + * the shadow TLB. */ +/* XXX for both one-one and one-to-many , for now use TLB1 */ +static int kvmppc_e500_tlb1_map(struct kvmppc_vcpu_e500 *vcpu_e500, + u64 gvaddr, gfn_t gfn, struct tlbe *gtlbe) +{ + unsigned int victim; + + victim = vcpu_e500->guest_tlb_nv[1]++; + + if (unlikely(vcpu_e500->guest_tlb_nv[1] >= tlb1_max_shadow_size())) + vcpu_e500->guest_tlb_nv[1] = 0; + + kvmppc_e500_shadow_map(vcpu_e500, gvaddr, gfn, gtlbe, 1, victim); + + return victim; +} + +/* Invalidate all guest kernel mappings when enter usermode, + * so that when they fault back in they will get the + * proper permission bits. */ +void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode) +{ + if (usermode) { + struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); + int i; + + /* XXX Replace loop with fancy data structures. */ + /* needn't set modified since tlbia will make TLB1 coherent */ + for (i = 0; i < tlb1_max_shadow_size(); i++) + kvmppc_e500_stlbe_invalidate(vcpu_e500, 1, i); + + _tlbia(); + } +} + +static int kvmppc_e500_gtlbe_invalidate(struct kvmppc_vcpu_e500 *vcpu_e500, + int tlbsel, int esel) +{ + struct tlbe *gtlbe = &vcpu_e500->guest_tlb[tlbsel][esel]; + + if (unlikely(get_tlb_iprot(gtlbe))) + return -1; + + if (tlbsel == 1) { + kvmppc_e500_tlb1_invalidate(vcpu_e500, get_tlb_eaddr(gtlbe), + get_tlb_end(gtlbe), + get_tlb_tid(gtlbe)); + } else { + kvmppc_e500_stlbe_invalidate(vcpu_e500, tlbsel, esel); + } + + gtlbe->mas1 = 0; + + return 0; +} + +int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb) +{ + struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); + unsigned int ia; + int esel, tlbsel; + gva_t ea; + + ea = ((ra) ? vcpu->arch.gpr[ra] : 0) + vcpu->arch.gpr[rb]; + + ia = (ea >> 2) & 0x1; + + /* since we only have tow TLBs, only lower bit is used. */ + tlbsel = (ea >> 3) & 0x1; + + if (ia) { + /* invalidate all entries */ + for (esel = 0; esel < vcpu_e500->guest_tlb_size[tlbsel]; esel++) + kvmppc_e500_gtlbe_invalidate(vcpu_e500, tlbsel, esel); + } else { + ea &= 0xfffff000; + esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, + get_cur_pid(vcpu), -1); + if (esel >= 0) + kvmppc_e500_gtlbe_invalidate(vcpu_e500, tlbsel, esel); + } + + _tlbia(); + + return EMULATE_DONE; +} + +int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu) +{ + struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); + int tlbsel, esel; + struct tlbe *gtlbe; + + tlbsel = get_tlb_tlbsel(vcpu_e500); + esel = get_tlb_esel(vcpu_e500, tlbsel); + + gtlbe = &vcpu_e500->guest_tlb[tlbsel][esel]; + vcpu_e500->mas0 &= MAS0_NV(0); + vcpu_e500->mas0 |= MAS0_NV(vcpu_e500->guest_tlb_nv[tlbsel]); + vcpu_e500->mas1 = gtlbe->mas1; + vcpu_e500->mas2 = gtlbe->mas2; + vcpu_e500->mas3 = gtlbe->mas3; + vcpu_e500->mas7 = gtlbe->mas7; + + return EMULATE_DONE; +} + +int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb) +{ + struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); + int as = !!get_cur_sas(vcpu_e500); + unsigned int pid = get_cur_spid(vcpu_e500); + int esel, tlbsel; + struct tlbe *gtlbe = NULL; + gva_t ea; + + ea = vcpu->arch.gpr[rb]; + + for (tlbsel = 0; tlbsel < 2; tlbsel++) { + esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, as); + if (esel >= 0) { + gtlbe = &vcpu_e500->guest_tlb[tlbsel][esel]; + break; + } + } + + if (gtlbe) { + vcpu_e500->mas0 = MAS0_TLBSEL(tlbsel) | MAS0_ESEL(esel) + | MAS0_NV(vcpu_e500->guest_tlb_nv[tlbsel]); + vcpu_e500->mas1 = gtlbe->mas1; + vcpu_e500->mas2 = gtlbe->mas2; + vcpu_e500->mas3 = gtlbe->mas3; + vcpu_e500->mas7 = gtlbe->mas7; + } else { + int victim; + + /* since we only have tow TLBs, only lower bit is used. */ + tlbsel = vcpu_e500->mas4 >> 28 & 0x1; + victim = (tlbsel == 0) ? tlb0_get_next_victim(vcpu_e500) : 0; + + vcpu_e500->mas0 = MAS0_TLBSEL(tlbsel) | MAS0_ESEL(victim) + | MAS0_NV(vcpu_e500->guest_tlb_nv[tlbsel]); + vcpu_e500->mas1 = (vcpu_e500->mas6 & MAS6_SPID0) + | (vcpu_e500->mas6 & (MAS6_SAS ? MAS1_TS : 0)) + | (vcpu_e500->mas4 & MAS4_TSIZED(~0)); + vcpu_e500->mas2 &= MAS2_EPN; + vcpu_e500->mas2 |= vcpu_e500->mas4 & MAS2_ATTRIB_MASK; + vcpu_e500->mas3 &= MAS3_U0 | MAS3_U1 | MAS3_U2 | MAS3_U3; + vcpu_e500->mas7 = 0; + } + + return EMULATE_DONE; +} + +int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu) +{ + struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); + u64 eaddr; + u64 raddr; + u32 tid; + struct tlbe *gtlbe; + int tlbsel, esel, stlbsel, sesel; + + tlbsel = get_tlb_tlbsel(vcpu_e500); + esel = get_tlb_esel(vcpu_e500, tlbsel); + + gtlbe = &vcpu_e500->guest_tlb[tlbsel][esel]; + + if (get_tlb_v(gtlbe) && tlbsel == 1) { + eaddr = get_tlb_eaddr(gtlbe); + tid = get_tlb_tid(gtlbe); + kvmppc_e500_tlb1_invalidate(vcpu_e500, eaddr, + get_tlb_end(gtlbe), tid); + } + + gtlbe->mas1 = vcpu_e500->mas1; + gtlbe->mas2 = vcpu_e500->mas2; + gtlbe->mas3 = vcpu_e500->mas3; + gtlbe->mas7 = vcpu_e500->mas7; + + KVMTRACE_5D(GTLB_WRITE, vcpu, vcpu_e500->mas0, + gtlbe->mas1, gtlbe->mas2, gtlbe->mas3, gtlbe->mas7, + handler); + + /* Invalidate shadow mappings for the about-to-be-clobbered TLBE. */ + if (tlbe_is_host_safe(vcpu, gtlbe)) { + switch (tlbsel) { + case 0: + /* TLB0 */ + gtlbe->mas1 &= ~MAS1_TSIZE(~0); + gtlbe->mas1 |= MAS1_TSIZE(BOOKE_PAGESZ_4K); + + stlbsel = 0; + sesel = kvmppc_e500_stlbe_map(vcpu_e500, 0, esel); + + break; + + case 1: + /* TLB1 */ + eaddr = get_tlb_eaddr(gtlbe); + raddr = get_tlb_raddr(gtlbe); + + /* Create a 4KB mapping on the host. + * If the guest wanted a large page, + * only the first 4KB is mapped here and the rest + * are mapped on the fly. */ + stlbsel = 1; + sesel = kvmppc_e500_tlb1_map(vcpu_e500, eaddr, + raddr >> PAGE_SHIFT, gtlbe); + break; + + default: + BUG(); + } + write_host_tlbe(vcpu_e500, stlbsel, sesel); + } + + return EMULATE_DONE; +} + +int kvmppc_mmu_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr) +{ + unsigned int as = !!(vcpu->arch.msr & MSR_IS); + + return kvmppc_e500_tlb_search(vcpu, eaddr, get_cur_pid(vcpu), as); +} + +int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr) +{ + unsigned int as = !!(vcpu->arch.msr & MSR_DS); + + return kvmppc_e500_tlb_search(vcpu, eaddr, get_cur_pid(vcpu), as); +} + +void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu) +{ + unsigned int as = !!(vcpu->arch.msr & MSR_IS); + + kvmppc_e500_deliver_tlb_miss(vcpu, vcpu->arch.pc, as); +} + +void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu) +{ + unsigned int as = !!(vcpu->arch.msr & MSR_DS); + + kvmppc_e500_deliver_tlb_miss(vcpu, vcpu->arch.fault_dear, as); +} + +gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int index, + gva_t eaddr) +{ + struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); + struct tlbe *gtlbe = + &vcpu_e500->guest_tlb[tlbsel_of(index)][esel_of(index)]; + u64 pgmask = get_tlb_bytes(gtlbe) - 1; + + return get_tlb_raddr(gtlbe) | (eaddr & pgmask); +} + +void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu) +{ + struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); + int tlbsel, i; + + for (tlbsel = 0; tlbsel < 2; tlbsel++) + for (i = 0; i < vcpu_e500->guest_tlb_size[tlbsel]; i++) + kvmppc_e500_shadow_release(vcpu_e500, tlbsel, i); + + /* discard all guest mapping */ + _tlbia(); +} + +void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr, + unsigned int index) +{ + struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); + int tlbsel = tlbsel_of(index); + int esel = esel_of(index); + int stlbsel, sesel; + + switch (tlbsel) { + case 0: + stlbsel = 0; + sesel = esel; + break; + + case 1: { + gfn_t gfn = gpaddr >> PAGE_SHIFT; + struct tlbe *gtlbe + = &vcpu_e500->guest_tlb[tlbsel][esel]; + + stlbsel = 1; + sesel = kvmppc_e500_tlb1_map(vcpu_e500, eaddr, gfn, gtlbe); + break; + } + + default: + BUG(); + break; + } + write_host_tlbe(vcpu_e500, stlbsel, sesel); +} + +int kvmppc_e500_tlb_search(struct kvm_vcpu *vcpu, + gva_t eaddr, unsigned int pid, int as) +{ + struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); + int esel, tlbsel; + + for (tlbsel = 0; tlbsel < 2; tlbsel++) { + esel = kvmppc_e500_tlb_index(vcpu_e500, eaddr, tlbsel, pid, as); + if (esel >= 0) + return index_of(tlbsel, esel); + } + + return -1; +} + +void kvmppc_e500_tlb_setup(struct kvmppc_vcpu_e500 *vcpu_e500) +{ + struct tlbe *tlbe; + + /* Insert large initial mapping for guest. */ + tlbe = &vcpu_e500->guest_tlb[1][0]; + tlbe->mas1 = MAS1_VALID | MAS1_TSIZE(BOOKE_PAGESZ_256M); + tlbe->mas2 = 0; + tlbe->mas3 = E500_TLB_SUPER_PERM_MASK; + tlbe->mas7 = 0; + + /* 4K map for serial output. Used by kernel wrapper. */ + tlbe = &vcpu_e500->guest_tlb[1][1]; + tlbe->mas1 = MAS1_VALID | MAS1_TSIZE(BOOKE_PAGESZ_4K); + tlbe->mas2 = (0xe0004500 & 0xFFFFF000) | MAS2_I | MAS2_G; + tlbe->mas3 = (0xe0004500 & 0xFFFFF000) | E500_TLB_SUPER_PERM_MASK; + tlbe->mas7 = 0; +} + +int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500) +{ + tlb1_entry_num = mfspr(SPRN_TLB1CFG) & 0xFFF; + + vcpu_e500->guest_tlb_size[0] = KVM_E500_TLB0_SIZE; + vcpu_e500->guest_tlb[0] = + kzalloc(sizeof(struct tlbe) * KVM_E500_TLB0_SIZE, GFP_KERNEL); + if (vcpu_e500->guest_tlb[0] == NULL) + goto err_out; + + vcpu_e500->shadow_tlb_size[0] = KVM_E500_TLB0_SIZE; + vcpu_e500->shadow_tlb[0] = + kzalloc(sizeof(struct tlbe) * KVM_E500_TLB0_SIZE, GFP_KERNEL); + if (vcpu_e500->shadow_tlb[0] == NULL) + goto err_out_guest0; + + vcpu_e500->guest_tlb_size[1] = KVM_E500_TLB1_SIZE; + vcpu_e500->guest_tlb[1] = + kzalloc(sizeof(struct tlbe) * KVM_E500_TLB1_SIZE, GFP_KERNEL); + if (vcpu_e500->guest_tlb[1] == NULL) + goto err_out_shadow0; + + vcpu_e500->shadow_tlb_size[1] = tlb1_entry_num; + vcpu_e500->shadow_tlb[1] = + kzalloc(sizeof(struct tlbe) * tlb1_entry_num, GFP_KERNEL); + if (vcpu_e500->shadow_tlb[1] == NULL) + goto err_out_guest1; + + vcpu_e500->shadow_pages[0] = (struct page **) + kzalloc(sizeof(struct page *) * KVM_E500_TLB0_SIZE, GFP_KERNEL); + if (vcpu_e500->shadow_pages[0] == NULL) + goto err_out_shadow1; + + vcpu_e500->shadow_pages[1] = (struct page **) + kzalloc(sizeof(struct page *) * tlb1_entry_num, GFP_KERNEL); + if (vcpu_e500->shadow_pages[1] == NULL) + goto err_out_page0; + + return 0; + +err_out_page0: + kfree(vcpu_e500->shadow_pages[0]); +err_out_shadow1: + kfree(vcpu_e500->shadow_tlb[1]); +err_out_guest1: + kfree(vcpu_e500->guest_tlb[1]); +err_out_shadow0: + kfree(vcpu_e500->shadow_tlb[0]); +err_out_guest0: + kfree(vcpu_e500->guest_tlb[0]); +err_out: + return -1; +} + +void kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 *vcpu_e500) +{ + kfree(vcpu_e500->shadow_pages[1]); + kfree(vcpu_e500->shadow_pages[0]); + kfree(vcpu_e500->shadow_tlb[1]); + kfree(vcpu_e500->guest_tlb[1]); + kfree(vcpu_e500->shadow_tlb[0]); + kfree(vcpu_e500->guest_tlb[0]); +} diff --git a/arch/powerpc/kvm/e500_tlb.h b/arch/powerpc/kvm/e500_tlb.h new file mode 100644 index 00000000000..d8833f95516 --- /dev/null +++ b/arch/powerpc/kvm/e500_tlb.h @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved. + * + * Author: Yu Liu, yu.liu@freescale.com + * + * Description: + * This file is based on arch/powerpc/kvm/44x_tlb.h, + * by Hollis Blanchard . + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + */ + +#ifndef __KVM_E500_TLB_H__ +#define __KVM_E500_TLB_H__ + +#include +#include +#include +#include + +#define KVM_E500_TLB0_WAY_SIZE_BIT 7 /* Fixed */ +#define KVM_E500_TLB0_WAY_SIZE (1UL << KVM_E500_TLB0_WAY_SIZE_BIT) +#define KVM_E500_TLB0_WAY_SIZE_MASK (KVM_E500_TLB0_WAY_SIZE - 1) + +#define KVM_E500_TLB0_WAY_NUM_BIT 1 /* No greater than 7 */ +#define KVM_E500_TLB0_WAY_NUM (1UL << KVM_E500_TLB0_WAY_NUM_BIT) +#define KVM_E500_TLB0_WAY_NUM_MASK (KVM_E500_TLB0_WAY_NUM - 1) + +#define KVM_E500_TLB0_SIZE (KVM_E500_TLB0_WAY_SIZE * KVM_E500_TLB0_WAY_NUM) +#define KVM_E500_TLB1_SIZE 16 + +#define index_of(tlbsel, esel) (((tlbsel) << 16) | ((esel) & 0xFFFF)) +#define tlbsel_of(index) ((index) >> 16) +#define esel_of(index) ((index) & 0xFFFF) + +#define E500_TLB_USER_PERM_MASK (MAS3_UX|MAS3_UR|MAS3_UW) +#define E500_TLB_SUPER_PERM_MASK (MAS3_SX|MAS3_SR|MAS3_SW) +#define MAS2_ATTRIB_MASK \ + (MAS2_X0 | MAS2_X1 | MAS2_W | MAS2_I | MAS2_M | MAS2_G | MAS2_E) +#define MAS3_ATTRIB_MASK \ + (MAS3_U0 | MAS3_U1 | MAS3_U2 | MAS3_U3 \ + | E500_TLB_USER_PERM_MASK | E500_TLB_SUPER_PERM_MASK) + +extern void kvmppc_dump_tlbs(struct kvm_vcpu *); +extern int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *); +extern int kvmppc_e500_emul_tlbre(struct kvm_vcpu *); +extern int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *, int, int); +extern int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *, int); +extern int kvmppc_e500_tlb_search(struct kvm_vcpu *, gva_t, unsigned int, int); +extern void kvmppc_e500_tlb_put(struct kvm_vcpu *); +extern void kvmppc_e500_tlb_load(struct kvm_vcpu *, int); +extern int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *); +extern void kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 *); +extern void kvmppc_e500_tlb_setup(struct kvmppc_vcpu_e500 *); + +/* TLB helper functions */ +static inline unsigned int get_tlb_size(const struct tlbe *tlbe) +{ + return (tlbe->mas1 >> 8) & 0xf; +} + +static inline gva_t get_tlb_eaddr(const struct tlbe *tlbe) +{ + return tlbe->mas2 & 0xfffff000; +} + +static inline u64 get_tlb_bytes(const struct tlbe *tlbe) +{ + unsigned int pgsize = get_tlb_size(tlbe); + return 1ULL << 10 << (pgsize << 1); +} + +static inline gva_t get_tlb_end(const struct tlbe *tlbe) +{ + u64 bytes = get_tlb_bytes(tlbe); + return get_tlb_eaddr(tlbe) + bytes - 1; +} + +static inline u64 get_tlb_raddr(const struct tlbe *tlbe) +{ + u64 rpn = tlbe->mas7; + return (rpn << 32) | (tlbe->mas3 & 0xfffff000); +} + +static inline unsigned int get_tlb_tid(const struct tlbe *tlbe) +{ + return (tlbe->mas1 >> 16) & 0xff; +} + +static inline unsigned int get_tlb_ts(const struct tlbe *tlbe) +{ + return (tlbe->mas1 >> 12) & 0x1; +} + +static inline unsigned int get_tlb_v(const struct tlbe *tlbe) +{ + return (tlbe->mas1 >> 31) & 0x1; +} + +static inline unsigned int get_tlb_iprot(const struct tlbe *tlbe) +{ + return (tlbe->mas1 >> 30) & 0x1; +} + +static inline unsigned int get_cur_pid(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.pid & 0xff; +} + +static inline unsigned int get_cur_spid( + const struct kvmppc_vcpu_e500 *vcpu_e500) +{ + return (vcpu_e500->mas6 >> 16) & 0xff; +} + +static inline unsigned int get_cur_sas( + const struct kvmppc_vcpu_e500 *vcpu_e500) +{ + return vcpu_e500->mas6 & 0x1; +} + +static inline unsigned int get_tlb_tlbsel( + const struct kvmppc_vcpu_e500 *vcpu_e500) +{ + /* + * Manual says that tlbsel has 2 bits wide. + * Since we only have tow TLBs, only lower bit is used. + */ + return (vcpu_e500->mas0 >> 28) & 0x1; +} + +static inline unsigned int get_tlb_nv_bit( + const struct kvmppc_vcpu_e500 *vcpu_e500) +{ + return vcpu_e500->mas0 & 0xfff; +} + +static inline unsigned int get_tlb_esel_bit( + const struct kvmppc_vcpu_e500 *vcpu_e500) +{ + return (vcpu_e500->mas0 >> 16) & 0xfff; +} + +static inline unsigned int get_tlb_esel( + const struct kvmppc_vcpu_e500 *vcpu_e500, + int tlbsel) +{ + unsigned int esel = get_tlb_esel_bit(vcpu_e500); + + if (tlbsel == 0) { + esel &= KVM_E500_TLB0_WAY_NUM_MASK; + esel |= ((vcpu_e500->mas2 >> 12) & KVM_E500_TLB0_WAY_SIZE_MASK) + << KVM_E500_TLB0_WAY_NUM_BIT; + } else { + esel &= KVM_E500_TLB1_SIZE - 1; + } + + return esel; +} + +static inline int tlbe_is_host_safe(const struct kvm_vcpu *vcpu, + const struct tlbe *tlbe) +{ + gpa_t gpa; + + if (!get_tlb_v(tlbe)) + return 0; + + /* Does it match current guest AS? */ + /* XXX what about IS != DS? */ + if (get_tlb_ts(tlbe) != !!(vcpu->arch.msr & MSR_IS)) + return 0; + + gpa = get_tlb_raddr(tlbe); + if (!gfn_to_memslot(vcpu->kvm, gpa >> PAGE_SHIFT)) + /* Mapping is not for RAM. */ + return 0; + + return 1; +} + +#endif /* __KVM_E500_TLB_H__ */ -- GitLab From b52a638c391c5c7b013180f5374274698b8535c8 Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Sat, 3 Jan 2009 16:23:11 -0600 Subject: [PATCH 4069/4982] KVM: ppc: Add kvmppc_mmu_dtlb/itlb_miss for booke When itlb or dtlb miss happens, E500 needs to update some mmu registers. So that the auto-load mechanism can work on E500 when write a tlb entry. Signed-off-by: Liu Yu Signed-off-by: Hollis Blanchard Signed-off-by: Avi Kivity --- arch/powerpc/include/asm/kvm_ppc.h | 2 ++ arch/powerpc/kvm/44x_tlb.c | 8 ++++++++ arch/powerpc/kvm/booke.c | 2 ++ 3 files changed, 12 insertions(+) diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index 5e80a20f32b..6052779dbb5 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h @@ -63,6 +63,8 @@ extern int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr); extern int kvmppc_mmu_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr); extern gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int gtlb_index, gva_t eaddr); +extern void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu); +extern void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu); extern struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id); diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c index e67b7313ffc..4a16f472cc1 100644 --- a/arch/powerpc/kvm/44x_tlb.c +++ b/arch/powerpc/kvm/44x_tlb.c @@ -232,6 +232,14 @@ int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr) return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as); } +void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu) +{ +} + +void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu) +{ +} + static void kvmppc_44x_shadow_release(struct kvmppc_vcpu_44x *vcpu_44x, unsigned int stlb_index) { diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index a73b3959e41..933c406c791 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c @@ -295,6 +295,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DTLB_MISS); vcpu->arch.dear = vcpu->arch.fault_dear; vcpu->arch.esr = vcpu->arch.fault_esr; + kvmppc_mmu_dtlb_miss(vcpu); kvmppc_account_exit(vcpu, DTLB_REAL_MISS_EXITS); r = RESUME_GUEST; break; @@ -337,6 +338,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, if (gtlb_index < 0) { /* The guest didn't have a mapping for it. */ kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ITLB_MISS); + kvmppc_mmu_itlb_miss(vcpu); kvmppc_account_exit(vcpu, ITLB_REAL_MISS_EXITS); break; } -- GitLab From bdc89f13ec955c14777d5caf02dfca3f51d639bd Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Sat, 3 Jan 2009 16:23:12 -0600 Subject: [PATCH 4070/4982] KVM: ppc: distinguish between interrupts and priorities Although BOOKE_MAX_INTERRUPT has the right value, the meaning is not match. Signed-off-by: Liu Yu Signed-off-by: Hollis Blanchard Signed-off-by: Avi Kivity --- arch/powerpc/kvm/booke.c | 2 +- arch/powerpc/kvm/booke.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 933c406c791..f192fbee2f2 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c @@ -163,7 +163,7 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu) unsigned int priority; priority = __ffs(*pending); - while (priority <= BOOKE_MAX_INTERRUPT) { + while (priority <= BOOKE_IRQPRIO_MAX) { if (kvmppc_booke_irqprio_deliver(vcpu, priority)) break; diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h index 311fdbc23fb..7ceeb3e739b 100644 --- a/arch/powerpc/kvm/booke.h +++ b/arch/powerpc/kvm/booke.h @@ -42,6 +42,7 @@ #define BOOKE_IRQPRIO_EXTERNAL 13 #define BOOKE_IRQPRIO_FIT 14 #define BOOKE_IRQPRIO_DECREMENTER 15 +#define BOOKE_IRQPRIO_MAX 15 /* Helper function for "full" MSR writes. No need to call this if only EE is * changing. */ -- GitLab From bb3a8a178dec1e46df3138a30f76acf67fe12397 Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Sat, 3 Jan 2009 16:23:13 -0600 Subject: [PATCH 4071/4982] KVM: ppc: Add extra E500 exceptions e500 has additional interrupt vectors (and corresponding IVORs) for SPE and performance monitoring interrupts. Signed-off-by: Liu Yu Signed-off-by: Hollis Blanchard Signed-off-by: Avi Kivity --- arch/powerpc/include/asm/kvm_asm.h | 7 ++++++- arch/powerpc/include/asm/kvm_host.h | 2 +- arch/powerpc/kvm/booke.c | 18 +++++++++++++++++ arch/powerpc/kvm/booke.h | 30 +++++++++++++++++------------ arch/powerpc/kvm/booke_interrupts.S | 3 +++ arch/powerpc/kvm/e500.c | 20 ++++++++++++++++++- arch/powerpc/kvm/e500_emulate.c | 27 ++++++++++++++++++++++++++ 7 files changed, 92 insertions(+), 15 deletions(-) diff --git a/arch/powerpc/include/asm/kvm_asm.h b/arch/powerpc/include/asm/kvm_asm.h index 2197764796d..56bfae59837 100644 --- a/arch/powerpc/include/asm/kvm_asm.h +++ b/arch/powerpc/include/asm/kvm_asm.h @@ -42,7 +42,12 @@ #define BOOKE_INTERRUPT_DTLB_MISS 13 #define BOOKE_INTERRUPT_ITLB_MISS 14 #define BOOKE_INTERRUPT_DEBUG 15 -#define BOOKE_MAX_INTERRUPT 15 + +/* E500 */ +#define BOOKE_INTERRUPT_SPE_UNAVAIL 32 +#define BOOKE_INTERRUPT_SPE_FP_DATA 33 +#define BOOKE_INTERRUPT_SPE_FP_ROUND 34 +#define BOOKE_INTERRUPT_PERFORMANCE_MONITOR 35 #define RESUME_FLAG_NV (1<<0) /* Reload guest nonvolatile state? */ #define RESUME_FLAG_HOST (1<<1) /* Resume host? */ diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 50e5ce1b400..1c618769752 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -150,7 +150,7 @@ struct kvm_vcpu_arch { u32 tbu; u32 tcr; u32 tsr; - u32 ivor[16]; + u32 ivor[64]; ulong ivpr; u32 pir; diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index f192fbee2f2..642e4204cf2 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c @@ -118,6 +118,9 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu, case BOOKE_IRQPRIO_DATA_STORAGE: case BOOKE_IRQPRIO_INST_STORAGE: case BOOKE_IRQPRIO_FP_UNAVAIL: + case BOOKE_IRQPRIO_SPE_UNAVAIL: + case BOOKE_IRQPRIO_SPE_FP_DATA: + case BOOKE_IRQPRIO_SPE_FP_ROUND: case BOOKE_IRQPRIO_AP_UNAVAIL: case BOOKE_IRQPRIO_ALIGNMENT: allowed = 1; @@ -261,6 +264,21 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, r = RESUME_GUEST; break; + case BOOKE_INTERRUPT_SPE_UNAVAIL: + kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_UNAVAIL); + r = RESUME_GUEST; + break; + + case BOOKE_INTERRUPT_SPE_FP_DATA: + kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_FP_DATA); + r = RESUME_GUEST; + break; + + case BOOKE_INTERRUPT_SPE_FP_ROUND: + kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_FP_ROUND); + r = RESUME_GUEST; + break; + case BOOKE_INTERRUPT_DATA_STORAGE: vcpu->arch.dear = vcpu->arch.fault_dear; vcpu->arch.esr = vcpu->arch.fault_esr; diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h index 7ceeb3e739b..d59bcca1f9d 100644 --- a/arch/powerpc/kvm/booke.h +++ b/arch/powerpc/kvm/booke.h @@ -31,18 +31,24 @@ #define BOOKE_IRQPRIO_ALIGNMENT 2 #define BOOKE_IRQPRIO_PROGRAM 3 #define BOOKE_IRQPRIO_FP_UNAVAIL 4 -#define BOOKE_IRQPRIO_SYSCALL 5 -#define BOOKE_IRQPRIO_AP_UNAVAIL 6 -#define BOOKE_IRQPRIO_DTLB_MISS 7 -#define BOOKE_IRQPRIO_ITLB_MISS 8 -#define BOOKE_IRQPRIO_MACHINE_CHECK 9 -#define BOOKE_IRQPRIO_DEBUG 10 -#define BOOKE_IRQPRIO_CRITICAL 11 -#define BOOKE_IRQPRIO_WATCHDOG 12 -#define BOOKE_IRQPRIO_EXTERNAL 13 -#define BOOKE_IRQPRIO_FIT 14 -#define BOOKE_IRQPRIO_DECREMENTER 15 -#define BOOKE_IRQPRIO_MAX 15 +#define BOOKE_IRQPRIO_SPE_UNAVAIL 5 +#define BOOKE_IRQPRIO_SPE_FP_DATA 6 +#define BOOKE_IRQPRIO_SPE_FP_ROUND 7 +#define BOOKE_IRQPRIO_SYSCALL 8 +#define BOOKE_IRQPRIO_AP_UNAVAIL 9 +#define BOOKE_IRQPRIO_DTLB_MISS 10 +#define BOOKE_IRQPRIO_ITLB_MISS 11 +#define BOOKE_IRQPRIO_MACHINE_CHECK 12 +#define BOOKE_IRQPRIO_DEBUG 13 +#define BOOKE_IRQPRIO_CRITICAL 14 +#define BOOKE_IRQPRIO_WATCHDOG 15 +#define BOOKE_IRQPRIO_EXTERNAL 16 +#define BOOKE_IRQPRIO_FIT 17 +#define BOOKE_IRQPRIO_DECREMENTER 18 +#define BOOKE_IRQPRIO_PERFORMANCE_MONITOR 19 +#define BOOKE_IRQPRIO_MAX 19 + +extern unsigned long kvmppc_booke_handlers; /* Helper function for "full" MSR writes. No need to call this if only EE is * changing. */ diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S index 4679ec287e6..d0c6f841bbd 100644 --- a/arch/powerpc/kvm/booke_interrupts.S +++ b/arch/powerpc/kvm/booke_interrupts.S @@ -86,6 +86,9 @@ KVM_HANDLER BOOKE_INTERRUPT_WATCHDOG KVM_HANDLER BOOKE_INTERRUPT_DTLB_MISS KVM_HANDLER BOOKE_INTERRUPT_ITLB_MISS KVM_HANDLER BOOKE_INTERRUPT_DEBUG +KVM_HANDLER BOOKE_INTERRUPT_SPE_UNAVAIL +KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_DATA +KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_ROUND _GLOBAL(kvmppc_handler_len) .long kvmppc_handler_1 - kvmppc_handler_0 diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c index 7992da497cd..d8067fd81cd 100644 --- a/arch/powerpc/kvm/e500.c +++ b/arch/powerpc/kvm/e500.c @@ -21,6 +21,7 @@ #include #include +#include "booke.h" #include "e500_tlb.h" void kvmppc_core_load_host_debugstate(struct kvm_vcpu *vcpu) @@ -133,12 +134,29 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) static int kvmppc_e500_init(void) { - int r; + int r, i; + unsigned long ivor[3]; + unsigned long max_ivor = 0; r = kvmppc_booke_init(); if (r) return r; + /* copy extra E500 exception handlers */ + ivor[0] = mfspr(SPRN_IVOR32); + ivor[1] = mfspr(SPRN_IVOR33); + ivor[2] = mfspr(SPRN_IVOR34); + for (i = 0; i < 3; i++) { + if (ivor[i] > max_ivor) + max_ivor = ivor[i]; + + memcpy((void *)kvmppc_booke_handlers + ivor[i], + kvmppc_handlers_start + (i + 16) * kvmppc_handler_len, + kvmppc_handler_len); + } + flush_icache_range(kvmppc_booke_handlers, + kvmppc_booke_handlers + max_ivor + kvmppc_handler_len); + return kvm_init(NULL, sizeof(struct kvmppc_vcpu_e500), THIS_MODULE); } diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c index a47f44cd2cf..d3c0c7c7f20 100644 --- a/arch/powerpc/kvm/e500_emulate.c +++ b/arch/powerpc/kvm/e500_emulate.c @@ -107,6 +107,20 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) case SPRN_HID1: vcpu_e500->hid1 = vcpu->arch.gpr[rs]; break; + /* extra exceptions */ + case SPRN_IVOR32: + vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = vcpu->arch.gpr[rs]; + break; + case SPRN_IVOR33: + vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA] = vcpu->arch.gpr[rs]; + break; + case SPRN_IVOR34: + vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND] = vcpu->arch.gpr[rs]; + break; + case SPRN_IVOR35: + vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR] = vcpu->arch.gpr[rs]; + break; + default: emulated = kvmppc_booke_emulate_mtspr(vcpu, sprn, rs); } @@ -160,6 +174,19 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt) case SPRN_HID1: vcpu->arch.gpr[rt] = vcpu_e500->hid1; break; + /* extra exceptions */ + case SPRN_IVOR32: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL]; + break; + case SPRN_IVOR33: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA]; + break; + case SPRN_IVOR34: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND]; + break; + case SPRN_IVOR35: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR]; + break; default: emulated = kvmppc_booke_emulate_mfspr(vcpu, sprn, rt); } -- GitLab From 1872a3f411ffe95c8e92300e0986a3532db55ce9 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 4 Jan 2009 23:26:52 +0200 Subject: [PATCH 4072/4982] KVM: VMX: Fix guest state validity checks The vmx guest state validity checks are full of bugs. Make them conform to the manual. Signed-off-by: Avi Kivity --- arch/x86/kvm/vmx.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 3312047664a..be9441056ff 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -1784,14 +1784,16 @@ static bool code_segment_valid(struct kvm_vcpu *vcpu) vmx_get_segment(vcpu, &cs, VCPU_SREG_CS); cs_rpl = cs.selector & SELECTOR_RPL_MASK; + if (cs.unusable) + return false; if (~cs.type & (AR_TYPE_CODE_MASK|AR_TYPE_ACCESSES_MASK)) return false; if (!cs.s) return false; - if (!(~cs.type & (AR_TYPE_CODE_MASK|AR_TYPE_WRITEABLE_MASK))) { + if (cs.type & AR_TYPE_WRITEABLE_MASK) { if (cs.dpl > cs_rpl) return false; - } else if (cs.type & AR_TYPE_CODE_MASK) { + } else { if (cs.dpl != cs_rpl) return false; } @@ -1810,7 +1812,9 @@ static bool stack_segment_valid(struct kvm_vcpu *vcpu) vmx_get_segment(vcpu, &ss, VCPU_SREG_SS); ss_rpl = ss.selector & SELECTOR_RPL_MASK; - if ((ss.type != 3) || (ss.type != 7)) + if (ss.unusable) + return true; + if (ss.type != 3 && ss.type != 7) return false; if (!ss.s) return false; @@ -1830,6 +1834,8 @@ static bool data_segment_valid(struct kvm_vcpu *vcpu, int seg) vmx_get_segment(vcpu, &var, seg); rpl = var.selector & SELECTOR_RPL_MASK; + if (var.unusable) + return true; if (!var.s) return false; if (!var.present) @@ -1851,9 +1857,11 @@ static bool tr_valid(struct kvm_vcpu *vcpu) vmx_get_segment(vcpu, &tr, VCPU_SREG_TR); + if (tr.unusable) + return false; if (tr.selector & SELECTOR_TI_MASK) /* TI = 1 */ return false; - if ((tr.type != 3) || (tr.type != 11)) /* TODO: Check if guest is in IA32e mode */ + if (tr.type != 3 && tr.type != 11) /* TODO: Check if guest is in IA32e mode */ return false; if (!tr.present) return false; @@ -1867,6 +1875,8 @@ static bool ldtr_valid(struct kvm_vcpu *vcpu) vmx_get_segment(vcpu, &ldtr, VCPU_SREG_LDTR); + if (ldtr.unusable) + return true; if (ldtr.selector & SELECTOR_TI_MASK) /* TI = 1 */ return false; if (ldtr.type != 2) -- GitLab From 9fd4a3b7a412f983696b23121413a79d2132fed6 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 4 Jan 2009 23:43:42 +0200 Subject: [PATCH 4073/4982] KVM: VMX: don't clobber segment AR if emulating invalid state The ususable bit is important for determining state validity; don't clobber it. Signed-off-by: Avi Kivity --- arch/x86/kvm/vmx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index be9441056ff..a6598cbaa00 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -1649,7 +1649,7 @@ static void vmx_get_segment(struct kvm_vcpu *vcpu, var->limit = vmcs_read32(sf->limit); var->selector = vmcs_read16(sf->selector); ar = vmcs_read32(sf->ar_bytes); - if (ar & AR_UNUSABLE_MASK) + if ((ar & AR_UNUSABLE_MASK) && !emulate_invalid_guest_state) ar = 0; var->type = ar & 15; var->s = (ar >> 4) & 1; -- GitLab From 10f32d84c750ccf8c0afb3a4ea9d4059aa3e9ffc Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Mon, 5 Jan 2009 00:53:19 +0200 Subject: [PATCH 4074/4982] KVM: VMX: Prevent exit handler from running if emulating due to invalid state If we've just emulated an instruction, we won't have any valid exit reason and associated information. Fix by moving the clearing of the emulation_required flag to the exit handler. This way the exit handler can notice that we've been emulating and abort early. Signed-off-by: Avi Kivity --- arch/x86/kvm/vmx.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index a6598cbaa00..a309be6788e 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -3130,7 +3130,6 @@ static int handle_nmi_window(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) static void handle_invalid_guest_state(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) { - struct vcpu_vmx *vmx = to_vmx(vcpu); int err; preempt_enable(); @@ -3155,11 +3154,6 @@ static void handle_invalid_guest_state(struct kvm_vcpu *vcpu, local_irq_disable(); preempt_disable(); - - /* Guest state should be valid now except if we need to - * emulate an MMIO */ - if (guest_state_valid(vcpu)) - vmx->emulation_required = 0; } /* @@ -3208,8 +3202,11 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) /* If we need to emulate an MMIO from handle_invalid_guest_state * we just return 0 */ - if (vmx->emulation_required && emulate_invalid_guest_state) + if (vmx->emulation_required && emulate_invalid_guest_state) { + if (guest_state_valid(vcpu)) + vmx->emulation_required = 0; return 0; + } /* Access CR3 don't cause VMExit in paging mode, so we need * to sync with guest real CR3. */ -- GitLab From 350f69dcd169d536307aa4a8c38c480e3a51c0db Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Mon, 5 Jan 2009 11:12:40 +0200 Subject: [PATCH 4075/4982] KVM: x86 emulator: Make emulate_pop() a little more generic Allow emulate_pop() to read into arbitrary memory rather than just the source operand. Needed for complicated instructions like far returns. Signed-off-by: Avi Kivity --- arch/x86/kvm/x86_emulate.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/arch/x86/kvm/x86_emulate.c b/arch/x86/kvm/x86_emulate.c index 54fb09889a8..94459f313f1 100644 --- a/arch/x86/kvm/x86_emulate.c +++ b/arch/x86/kvm/x86_emulate.c @@ -1136,18 +1136,19 @@ static inline void emulate_push(struct x86_emulate_ctxt *ctxt) } static int emulate_pop(struct x86_emulate_ctxt *ctxt, - struct x86_emulate_ops *ops) + struct x86_emulate_ops *ops, + void *dest, int len) { struct decode_cache *c = &ctxt->decode; int rc; rc = ops->read_emulated(register_address(c, ss_base(ctxt), c->regs[VCPU_REGS_RSP]), - &c->src.val, c->src.bytes, ctxt->vcpu); + dest, len, ctxt->vcpu); if (rc != 0) return rc; - register_address_increment(c, &c->regs[VCPU_REGS_RSP], c->src.bytes); + register_address_increment(c, &c->regs[VCPU_REGS_RSP], len); return rc; } @@ -1157,11 +1158,9 @@ static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt, struct decode_cache *c = &ctxt->decode; int rc; - c->src.bytes = c->dst.bytes; - rc = emulate_pop(ctxt, ops); + rc = emulate_pop(ctxt, ops, &c->dst.val, c->dst.bytes); if (rc != 0) return rc; - c->dst.val = c->src.val; return 0; } @@ -1467,11 +1466,9 @@ special_insn: break; case 0x58 ... 0x5f: /* pop reg */ pop_instruction: - c->src.bytes = c->op_bytes; - rc = emulate_pop(ctxt, ops); + rc = emulate_pop(ctxt, ops, &c->dst.val, c->op_bytes); if (rc != 0) goto done; - c->dst.val = c->src.val; break; case 0x63: /* movsxd */ if (ctxt->mode != X86EMUL_MODE_PROT64) -- GitLab From 8b3079a5c0c031de07c8390aa160a4229088274f Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Mon, 5 Jan 2009 12:10:54 +0200 Subject: [PATCH 4076/4982] KVM: VMX: When emulating on invalid vmx state, don't return to userspace unnecessarily If we aren't doing mmio there's no need to exit to userspace (which will just be confused). Signed-off-by: Avi Kivity --- arch/x86/kvm/vmx.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index a309be6788e..df454de8acf 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -91,6 +91,7 @@ struct vcpu_vmx { } rmode; int vpid; bool emulation_required; + enum emulation_result invalid_state_emulation_result; /* Support for vnmi-less CPUs */ int soft_vnmi_blocked; @@ -3130,7 +3131,8 @@ static int handle_nmi_window(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) static void handle_invalid_guest_state(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) { - int err; + struct vcpu_vmx *vmx = to_vmx(vcpu); + enum emulation_result err = EMULATE_DONE; preempt_enable(); local_irq_enable(); @@ -3154,6 +3156,8 @@ static void handle_invalid_guest_state(struct kvm_vcpu *vcpu, local_irq_disable(); preempt_disable(); + + vmx->invalid_state_emulation_result = err; } /* @@ -3205,7 +3209,7 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) if (vmx->emulation_required && emulate_invalid_guest_state) { if (guest_state_valid(vcpu)) vmx->emulation_required = 0; - return 0; + return vmx->invalid_state_emulation_result != EMULATE_DO_MMIO; } /* Access CR3 don't cause VMExit in paging mode, so we need -- GitLab From a77ab5ead5c1fef2c6c5a9b3cf3765e52643a2aa Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Mon, 5 Jan 2009 13:27:34 +0200 Subject: [PATCH 4077/4982] KVM: x86 emulator: implement 'ret far' instruction (opcode 0xcb) Signed-off-by: Avi Kivity --- arch/x86/kvm/x86_emulate.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/x86_emulate.c b/arch/x86/kvm/x86_emulate.c index 94459f313f1..ca91749d208 100644 --- a/arch/x86/kvm/x86_emulate.c +++ b/arch/x86/kvm/x86_emulate.c @@ -178,7 +178,7 @@ static u32 opcode_table[256] = { 0, ImplicitOps | Stack, 0, 0, ByteOp | DstMem | SrcImm | ModRM | Mov, DstMem | SrcImm | ModRM | Mov, /* 0xC8 - 0xCF */ - 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, ImplicitOps | Stack, 0, 0, 0, 0, /* 0xD0 - 0xD7 */ ByteOp | DstMem | SrcImplicit | ModRM, DstMem | SrcImplicit | ModRM, ByteOp | DstMem | SrcImplicit | ModRM, DstMem | SrcImplicit | ModRM, @@ -1278,6 +1278,25 @@ static inline int emulate_grp9(struct x86_emulate_ctxt *ctxt, return 0; } +static int emulate_ret_far(struct x86_emulate_ctxt *ctxt, + struct x86_emulate_ops *ops) +{ + struct decode_cache *c = &ctxt->decode; + int rc; + unsigned long cs; + + rc = emulate_pop(ctxt, ops, &c->eip, c->op_bytes); + if (rc) + return rc; + if (c->op_bytes == 4) + c->eip = (u32)c->eip; + rc = emulate_pop(ctxt, ops, &cs, c->op_bytes); + if (rc) + return rc; + rc = kvm_load_segment_descriptor(ctxt->vcpu, (u16)cs, 1, VCPU_SREG_CS); + return rc; +} + static inline int writeback(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) { @@ -1735,6 +1754,11 @@ special_insn: mov: c->dst.val = c->src.val; break; + case 0xcb: /* ret far */ + rc = emulate_ret_far(ctxt, ops); + if (rc) + goto done; + break; case 0xd0 ... 0xd1: /* Grp2 */ c->src.val = 1; emulate_grp2(ctxt); -- GitLab From 269e05e48502f1cc06802e9fba90f5100dd6bb0d Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Mon, 5 Jan 2009 15:21:42 +0200 Subject: [PATCH 4078/4982] KVM: Properly lock PIT creation Otherwise, two threads can create a PIT in parallel and cause a memory leak. Signed-off-by: Avi Kivity --- arch/x86/kvm/i8254.c | 2 -- arch/x86/kvm/x86.c | 6 ++++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c index 528daadeba4..69d1bbff3fd 100644 --- a/arch/x86/kvm/i8254.c +++ b/arch/x86/kvm/i8254.c @@ -548,9 +548,7 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm) if (!pit) return NULL; - mutex_lock(&kvm->lock); pit->irq_source_id = kvm_request_irq_source_id(kvm); - mutex_unlock(&kvm->lock); if (pit->irq_source_id < 0) { kfree(pit); return NULL; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index a1f14611f4b..6fbc3460337 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1837,10 +1837,16 @@ long kvm_arch_vm_ioctl(struct file *filp, goto out; break; case KVM_CREATE_PIT: + mutex_lock(&kvm->lock); + r = -EEXIST; + if (kvm->arch.vpit) + goto create_pit_unlock; r = -ENOMEM; kvm->arch.vpit = kvm_create_pit(kvm); if (kvm->arch.vpit) r = 0; + create_pit_unlock: + mutex_unlock(&kvm->lock); break; case KVM_IRQ_LINE: { struct kvm_irq_level irq_event; -- GitLab From f5d0906b5bafd7faea553ed1cc92bd06755b66b9 Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Sun, 4 Jan 2009 13:51:09 -0600 Subject: [PATCH 4079/4982] KVM: ppc: remove debug support broken by KVM debug rewrite After the rewrite of KVM's debug support, this code doesn't even build any more. Signed-off-by: Hollis Blanchard Signed-off-by: Avi Kivity --- arch/powerpc/include/asm/kvm_host.h | 5 --- arch/powerpc/include/asm/kvm_ppc.h | 3 -- arch/powerpc/kvm/44x.c | 66 ----------------------------- arch/powerpc/kvm/powerpc.c | 27 +----------- 4 files changed, 2 insertions(+), 99 deletions(-) diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 1c618769752..dfdf13c9fef 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -111,11 +111,6 @@ struct kvm_arch { struct kvm_vcpu_arch { u32 host_stack; u32 host_pid; - u32 host_dbcr0; - u32 host_dbcr1; - u32 host_dbcr2; - u32 host_iac[4]; - u32 host_msr; u64 fpr[32]; ulong gpr[32]; diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index 6052779dbb5..2c6ee349df5 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h @@ -77,9 +77,6 @@ extern int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu, extern void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu); extern void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu); -extern void kvmppc_core_load_guest_debugstate(struct kvm_vcpu *vcpu); -extern void kvmppc_core_load_host_debugstate(struct kvm_vcpu *vcpu); - extern void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu); extern int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu); extern void kvmppc_core_queue_program(struct kvm_vcpu *vcpu); diff --git a/arch/powerpc/kvm/44x.c b/arch/powerpc/kvm/44x.c index 8383603dd8a..0cef809cec2 100644 --- a/arch/powerpc/kvm/44x.c +++ b/arch/powerpc/kvm/44x.c @@ -28,72 +28,6 @@ #include "44x_tlb.h" -/* Note: clearing MSR[DE] just means that the debug interrupt will not be - * delivered *immediately*. Instead, it simply sets the appropriate DBSR bits. - * If those DBSR bits are still set when MSR[DE] is re-enabled, the interrupt - * will be delivered as an "imprecise debug event" (which is indicated by - * DBSR[IDE]. - */ -static void kvm44x_disable_debug_interrupts(void) -{ - mtmsr(mfmsr() & ~MSR_DE); -} - -void kvmppc_core_load_host_debugstate(struct kvm_vcpu *vcpu) -{ - kvm44x_disable_debug_interrupts(); - - mtspr(SPRN_IAC1, vcpu->arch.host_iac[0]); - mtspr(SPRN_IAC2, vcpu->arch.host_iac[1]); - mtspr(SPRN_IAC3, vcpu->arch.host_iac[2]); - mtspr(SPRN_IAC4, vcpu->arch.host_iac[3]); - mtspr(SPRN_DBCR1, vcpu->arch.host_dbcr1); - mtspr(SPRN_DBCR2, vcpu->arch.host_dbcr2); - mtspr(SPRN_DBCR0, vcpu->arch.host_dbcr0); - mtmsr(vcpu->arch.host_msr); -} - -void kvmppc_core_load_guest_debugstate(struct kvm_vcpu *vcpu) -{ - struct kvm_guest_debug *dbg = &vcpu->guest_debug; - u32 dbcr0 = 0; - - vcpu->arch.host_msr = mfmsr(); - kvm44x_disable_debug_interrupts(); - - /* Save host debug register state. */ - vcpu->arch.host_iac[0] = mfspr(SPRN_IAC1); - vcpu->arch.host_iac[1] = mfspr(SPRN_IAC2); - vcpu->arch.host_iac[2] = mfspr(SPRN_IAC3); - vcpu->arch.host_iac[3] = mfspr(SPRN_IAC4); - vcpu->arch.host_dbcr0 = mfspr(SPRN_DBCR0); - vcpu->arch.host_dbcr1 = mfspr(SPRN_DBCR1); - vcpu->arch.host_dbcr2 = mfspr(SPRN_DBCR2); - - /* set registers up for guest */ - - if (dbg->bp[0]) { - mtspr(SPRN_IAC1, dbg->bp[0]); - dbcr0 |= DBCR0_IAC1 | DBCR0_IDM; - } - if (dbg->bp[1]) { - mtspr(SPRN_IAC2, dbg->bp[1]); - dbcr0 |= DBCR0_IAC2 | DBCR0_IDM; - } - if (dbg->bp[2]) { - mtspr(SPRN_IAC3, dbg->bp[2]); - dbcr0 |= DBCR0_IAC3 | DBCR0_IDM; - } - if (dbg->bp[3]) { - mtspr(SPRN_IAC4, dbg->bp[3]); - dbcr0 |= DBCR0_IAC4 | DBCR0_IDM; - } - - mtspr(SPRN_DBCR0, dbcr0); - mtspr(SPRN_DBCR1, 0); - mtspr(SPRN_DBCR2, 0); -} - void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) { kvmppc_44x_tlb_load(vcpu); diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index f30be9ef231..9057335fdc6 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -221,41 +221,18 @@ void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) { - if (vcpu->guest_debug.enabled) - kvmppc_core_load_guest_debugstate(vcpu); - kvmppc_core_vcpu_load(vcpu, cpu); } void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) { - if (vcpu->guest_debug.enabled) - kvmppc_core_load_host_debugstate(vcpu); - - /* Don't leave guest TLB entries resident when being de-scheduled. */ - /* XXX It would be nice to differentiate between heavyweight exit and - * sched_out here, since we could avoid the TLB flush for heavyweight - * exits. */ - _tlbil_all(); kvmppc_core_vcpu_put(vcpu); } int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, - struct kvm_guest_debug *dbg) + struct kvm_guest_debug *dbg) { - int i; - - vcpu->guest_debug.enabled = dbg->enabled; - if (vcpu->guest_debug.enabled) { - for (i=0; i < ARRAY_SIZE(vcpu->guest_debug.bp); i++) { - if (dbg->breakpoints[i].enabled) - vcpu->guest_debug.bp[i] = dbg->breakpoints[i].address; - else - vcpu->guest_debug.bp[i] = 0; - } - } - - return 0; + return -EINVAL; } static void kvmppc_complete_dcr_load(struct kvm_vcpu *vcpu, -- GitLab From 67346440e83d2a2f2e9801f370b6240317c7d9bd Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Tue, 6 Jan 2009 10:03:01 +0800 Subject: [PATCH 4080/4982] KVM: Remove duplicated prototype of kvm_arch_destroy_vm Signed-off-by: Sheng Yang Signed-off-by: Avi Kivity --- include/linux/kvm_host.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index e92212f970d..3cf0ede3fd7 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -237,7 +237,6 @@ int kvm_vm_ioctl_set_memory_region(struct kvm *kvm, int user_alloc); long kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg); -void kvm_arch_destroy_vm(struct kvm *kvm); int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu); int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu); -- GitLab From 17071fe74fe0fbfdb03cd9b82f2490447cf1f986 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Tue, 6 Jan 2009 16:25:11 +0800 Subject: [PATCH 4081/4982] KVM: Add support to disable MSI for assigned device MSI is always enabled by default for msi2intx=1. But if msi2intx=0, we have to disable MSI if guest require to do so. The patch also discard unnecessary msi2intx judgment if guest want to update MSI state. Notice KVM_DEV_IRQ_ASSIGN_MSI_ACTION is a mask which should cover all MSI related operations, though we only got one for now. Signed-off-by: Sheng Yang Signed-off-by: Avi Kivity --- include/linux/kvm.h | 1 + virt/kvm/kvm_main.c | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/include/linux/kvm.h b/include/linux/kvm.h index ae7a12c7742..73f34806686 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h @@ -550,6 +550,7 @@ struct kvm_assigned_irq { #define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0) +#define KVM_DEV_IRQ_ASSIGN_MSI_ACTION KVM_DEV_IRQ_ASSIGN_ENABLE_MSI #define KVM_DEV_IRQ_ASSIGN_ENABLE_MSI (1 << 0) #endif diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index f83ef9c7e89..04401e17c75 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -343,6 +343,14 @@ static int assigned_device_update_msi(struct kvm *kvm, adev->irq_requested_type &= ~KVM_ASSIGNED_DEV_GUEST_MSI; adev->guest_irq = airq->guest_irq; adev->ack_notifier.gsi = airq->guest_irq; + } else { + /* + * Guest require to disable device MSI, we disable MSI and + * re-enable INTx by default again. Notice it's only for + * non-msi2intx. + */ + assigned_device_update_intx(kvm, adev, airq); + return 0; } if (adev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_MSI) @@ -379,6 +387,7 @@ static int kvm_vm_ioctl_assign_irq(struct kvm *kvm, { int r = 0; struct kvm_assigned_dev_kernel *match; + u32 current_flags = 0, changed_flags; mutex_lock(&kvm->lock); @@ -416,8 +425,13 @@ static int kvm_vm_ioctl_assign_irq(struct kvm *kvm, } } - if ((!msi2intx && - (assigned_irq->flags & KVM_DEV_IRQ_ASSIGN_ENABLE_MSI)) || + if ((match->irq_requested_type & KVM_ASSIGNED_DEV_HOST_MSI) && + (match->irq_requested_type & KVM_ASSIGNED_DEV_GUEST_MSI)) + current_flags |= KVM_DEV_IRQ_ASSIGN_ENABLE_MSI; + + changed_flags = assigned_irq->flags ^ current_flags; + + if ((changed_flags & KVM_DEV_IRQ_ASSIGN_MSI_ACTION) || (msi2intx && match->dev->msi_enabled)) { #ifdef CONFIG_X86 r = assigned_device_update_msi(kvm, match, assigned_irq); -- GitLab From c8a73f186bf62235b6fb5dd52601d641917dd50b Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 5 Jan 2009 16:02:47 +0100 Subject: [PATCH 4082/4982] KVM: SVM: Add microcode patch level dummy VMware ESX checks if the microcode level is correct when using a barcelona CPU, in order to see if it actually can use SVM. Let's tell it we're on the safe side... Signed-off-by: Alexander Graf Signed-off-by: Avi Kivity --- arch/x86/kvm/svm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index b3a7a314d55..3a60c3f04e6 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -1928,6 +1928,9 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data) case MSR_VM_CR: *data = 0; break; + case MSR_IA32_UCODE_REV: + *data = 0x01000065; + break; default: return kvm_get_msr_common(vcpu, ecx, data); } -- GitLab From 4677a3b693e035f186e2875259b9a0bb94c42fbe Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 6 Jan 2009 13:00:27 +0200 Subject: [PATCH 4083/4982] KVM: MMU: Optimize page unshadowing Using kvm_mmu_lookup_page() will result in multiple scans of the hash chains; use hlist_for_each_entry_safe() to achieve a single scan instead. Signed-off-by: Avi Kivity --- arch/x86/kvm/mmu.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 15850809b55..aac0499947d 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -1471,11 +1471,20 @@ static int kvm_mmu_unprotect_page(struct kvm *kvm, gfn_t gfn) static void mmu_unshadow(struct kvm *kvm, gfn_t gfn) { + unsigned index; + struct hlist_head *bucket; struct kvm_mmu_page *sp; + struct hlist_node *node, *nn; - while ((sp = kvm_mmu_lookup_page(kvm, gfn)) != NULL) { - pgprintk("%s: zap %lx %x\n", __func__, gfn, sp->role.word); - kvm_mmu_zap_page(kvm, sp); + index = kvm_page_table_hashfn(gfn); + bucket = &kvm->arch.mmu_page_hash[index]; + hlist_for_each_entry_safe(sp, node, nn, bucket, hash_link) { + if (sp->gfn == gfn && !sp->role.metaphysical + && !sp->role.invalid) { + pgprintk("%s: zap %lx %x\n", + __func__, gfn, sp->role.word); + kvm_mmu_zap_page(kvm, sp); + } } } -- GitLab From 5d9b8e30f543a9f21a968a4cda71e8f6d1c66a61 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 4 Jan 2009 18:04:18 +0200 Subject: [PATCH 4084/4982] KVM: Add CONFIG_HAVE_KVM_IRQCHIP Two KVM archs support irqchips and two don't. Add a Kconfig item to make selecting between the two models easier. Signed-off-by: Avi Kivity --- arch/ia64/kvm/Kconfig | 4 ++++ arch/powerpc/kvm/Kconfig | 3 +++ arch/s390/kvm/Kconfig | 3 +++ arch/x86/kvm/Kconfig | 4 ++++ 4 files changed, 14 insertions(+) diff --git a/arch/ia64/kvm/Kconfig b/arch/ia64/kvm/Kconfig index f833a0b4188..0a2d6b86075 100644 --- a/arch/ia64/kvm/Kconfig +++ b/arch/ia64/kvm/Kconfig @@ -4,6 +4,10 @@ config HAVE_KVM bool +config HAVE_KVM_IRQCHIP + bool + default y + menuconfig VIRTUALIZATION bool "Virtualization" depends on HAVE_KVM || IA64 diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig index 14657055014..5a152a52796 100644 --- a/arch/powerpc/kvm/Kconfig +++ b/arch/powerpc/kvm/Kconfig @@ -2,6 +2,9 @@ # KVM configuration # +config HAVE_KVM_IRQCHIP + bool + menuconfig VIRTUALIZATION bool "Virtualization" ---help--- diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig index e051cad1f1e..3e260b7e37b 100644 --- a/arch/s390/kvm/Kconfig +++ b/arch/s390/kvm/Kconfig @@ -4,6 +4,9 @@ config HAVE_KVM bool +config HAVE_KVM_IRQCHIP + bool + menuconfig VIRTUALIZATION bool "Virtualization" default y diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig index b81125f0bde..0a303c3ed11 100644 --- a/arch/x86/kvm/Kconfig +++ b/arch/x86/kvm/Kconfig @@ -4,6 +4,10 @@ config HAVE_KVM bool +config HAVE_KVM_IRQCHIP + bool + default y + menuconfig VIRTUALIZATION bool "Virtualization" depends on HAVE_KVM || X86 -- GitLab From 75858a84a6207f5e60196f6bbd18fde4250e5759 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 4 Jan 2009 17:10:50 +0200 Subject: [PATCH 4085/4982] KVM: Interrupt mask notifiers for ioapic Allow clients to request notifications when the guest masks or unmasks a particular irq line. This complements irq ack notifications, as the guest will not ack an irq line that is masked. Currently implemented for the ioapic only. Signed-off-by: Avi Kivity --- include/linux/kvm_host.h | 17 +++++++++++++++++ virt/kvm/ioapic.c | 6 ++++++ virt/kvm/irq_comm.c | 24 ++++++++++++++++++++++++ virt/kvm/kvm_main.c | 3 +++ 4 files changed, 50 insertions(+) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 3cf0ede3fd7..99963f36a6d 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -127,6 +127,10 @@ struct kvm { struct kvm_coalesced_mmio_ring *coalesced_mmio_ring; #endif +#ifdef CONFIG_HAVE_KVM_IRQCHIP + struct hlist_head mask_notifier_list; +#endif + #ifdef KVM_ARCH_WANT_MMU_NOTIFIER struct mmu_notifier mmu_notifier; unsigned long mmu_notifier_seq; @@ -320,6 +324,19 @@ struct kvm_assigned_dev_kernel { struct pci_dev *dev; struct kvm *kvm; }; + +struct kvm_irq_mask_notifier { + void (*func)(struct kvm_irq_mask_notifier *kimn, bool masked); + int irq; + struct hlist_node link; +}; + +void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq, + struct kvm_irq_mask_notifier *kimn); +void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq, + struct kvm_irq_mask_notifier *kimn); +void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, bool mask); + void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level); void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi); void kvm_register_irq_ack_notifier(struct kvm *kvm, diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index 23b81cf242a..e85a2bcd2db 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c @@ -101,6 +101,7 @@ static void ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx) static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) { unsigned index; + bool mask_before, mask_after; switch (ioapic->ioregsel) { case IOAPIC_REG_VERSION: @@ -120,6 +121,7 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) ioapic_debug("change redir index %x val %x\n", index, val); if (index >= IOAPIC_NUM_PINS) return; + mask_before = ioapic->redirtbl[index].fields.mask; if (ioapic->ioregsel & 1) { ioapic->redirtbl[index].bits &= 0xffffffff; ioapic->redirtbl[index].bits |= (u64) val << 32; @@ -128,6 +130,9 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) ioapic->redirtbl[index].bits |= (u32) val; ioapic->redirtbl[index].fields.remote_irr = 0; } + mask_after = ioapic->redirtbl[index].fields.mask; + if (mask_before != mask_after) + kvm_fire_mask_notifiers(ioapic->kvm, index, mask_after); if (ioapic->irr & (1 << index)) ioapic_service(ioapic, index); break; @@ -426,3 +431,4 @@ int kvm_ioapic_init(struct kvm *kvm) kvm_io_bus_register_dev(&kvm->mmio_bus, &ioapic->dev); return 0; } + diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index aa5d1e5c497..5162a411e4d 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c @@ -99,3 +99,27 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id) clear_bit(irq_source_id, &kvm->arch.irq_states[i]); clear_bit(irq_source_id, &kvm->arch.irq_sources_bitmap); } + +void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq, + struct kvm_irq_mask_notifier *kimn) +{ + kimn->irq = irq; + hlist_add_head(&kimn->link, &kvm->mask_notifier_list); +} + +void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq, + struct kvm_irq_mask_notifier *kimn) +{ + hlist_del(&kimn->link); +} + +void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, bool mask) +{ + struct kvm_irq_mask_notifier *kimn; + struct hlist_node *n; + + hlist_for_each_entry(kimn, n, &kvm->mask_notifier_list, link) + if (kimn->irq == irq) + kimn->func(kimn, mask); +} + diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 04401e17c75..786a3ae373b 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -842,6 +842,9 @@ static struct kvm *kvm_create_vm(void) if (IS_ERR(kvm)) goto out; +#ifdef CONFIG_HAVE_KVM_IRQCHIP + INIT_HLIST_HEAD(&kvm->mask_notifier_list); +#endif #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET page = alloc_page(GFP_KERNEL | __GFP_ZERO); -- GitLab From 4780c65904f0fc4e312ee2da9383eacbe04e61ea Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 4 Jan 2009 18:06:06 +0200 Subject: [PATCH 4086/4982] KVM: Reset PIT irq injection logic when the PIT IRQ is unmasked While the PIT is masked the guest cannot ack the irq, so the reinject logic will never allow the interrupt to be injected. Fix by resetting the reinjection counters on unmask. Unbreaks Xen. Signed-off-by: Avi Kivity --- arch/x86/kvm/i8254.c | 15 +++++++++++++++ arch/x86/kvm/i8254.h | 1 + 2 files changed, 16 insertions(+) diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c index 69d1bbff3fd..c13bb92d315 100644 --- a/arch/x86/kvm/i8254.c +++ b/arch/x86/kvm/i8254.c @@ -539,6 +539,16 @@ void kvm_pit_reset(struct kvm_pit *pit) pit->pit_state.irq_ack = 1; } +static void pit_mask_notifer(struct kvm_irq_mask_notifier *kimn, bool mask) +{ + struct kvm_pit *pit = container_of(kimn, struct kvm_pit, mask_notifier); + + if (!mask) { + atomic_set(&pit->pit_state.pit_timer.pending, 0); + pit->pit_state.irq_ack = 1; + } +} + struct kvm_pit *kvm_create_pit(struct kvm *kvm) { struct kvm_pit *pit; @@ -586,6 +596,9 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm) kvm_pit_reset(pit); + pit->mask_notifier.func = pit_mask_notifer; + kvm_register_irq_mask_notifier(kvm, 0, &pit->mask_notifier); + return pit; } @@ -594,6 +607,8 @@ void kvm_free_pit(struct kvm *kvm) struct hrtimer *timer; if (kvm->arch.vpit) { + kvm_unregister_irq_mask_notifier(kvm, 0, + &kvm->arch.vpit->mask_notifier); mutex_lock(&kvm->arch.vpit->pit_state.lock); timer = &kvm->arch.vpit->pit_state.pit_timer.timer; hrtimer_cancel(timer); diff --git a/arch/x86/kvm/i8254.h b/arch/x86/kvm/i8254.h index 76959c4b500..6acbe4b505d 100644 --- a/arch/x86/kvm/i8254.h +++ b/arch/x86/kvm/i8254.h @@ -46,6 +46,7 @@ struct kvm_pit { struct kvm *kvm; struct kvm_kpit_state pit_state; int irq_source_id; + struct kvm_irq_mask_notifier mask_notifier; }; #define KVM_PIT_BASE_ADDRESS 0x40 -- GitLab From a26b73ad5e763db1b01cca6965ac3b65fe36e82a Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 8 Jan 2009 13:58:48 +0100 Subject: [PATCH 4087/4982] KVM: ia64: expose registers in struct kvm_regs Provide register layout for struct kvm_regs exposed to userland. Signed-off-by: Jes Sorensen Signed-off-by: Avi Kivity --- arch/ia64/include/asm/kvm.h | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/arch/ia64/include/asm/kvm.h b/arch/ia64/include/asm/kvm.h index b5145784233..0ee5bd7a988 100644 --- a/arch/ia64/include/asm/kvm.h +++ b/arch/ia64/include/asm/kvm.h @@ -166,7 +166,40 @@ struct saved_vpd { unsigned long vcpuid[5]; unsigned long vpsr; unsigned long vpr; - unsigned long vcr[128]; + union { + unsigned long vcr[128]; + struct { + unsigned long dcr; + unsigned long itm; + unsigned long iva; + unsigned long rsv1[5]; + unsigned long pta; + unsigned long rsv2[7]; + unsigned long ipsr; + unsigned long isr; + unsigned long rsv3; + unsigned long iip; + unsigned long ifa; + unsigned long itir; + unsigned long iipa; + unsigned long ifs; + unsigned long iim; + unsigned long iha; + unsigned long rsv4[38]; + unsigned long lid; + unsigned long ivr; + unsigned long tpr; + unsigned long eoi; + unsigned long irr[4]; + unsigned long itv; + unsigned long pmv; + unsigned long cmcv; + unsigned long rsv5[5]; + unsigned long lrr0; + unsigned long lrr1; + unsigned long rsv6[46]; + }; + }; }; struct kvm_regs { -- GitLab From ff81ff10b4417952919dcc0bd67effa9ceb411c0 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 8 Jan 2009 11:05:17 -0800 Subject: [PATCH 4088/4982] KVM: SVM: Fix typo in has_svm() Signed-off-by: Joe Perches Acked-by: Joerg Roedel Signed-off-by: Avi Kivity --- arch/x86/kvm/svm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 3a60c3f04e6..db5021b2b5a 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -250,7 +250,7 @@ static int has_svm(void) const char *msg; if (!cpu_has_svm(&msg)) { - printk(KERN_INFO "has_svn: %s\n", msg); + printk(KERN_INFO "has_svm: %s\n", msg); return 0; } -- GitLab From 9903a927a4aea4b1ea42356a8453fca664df0b18 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Thu, 8 Jan 2009 17:44:19 -0200 Subject: [PATCH 4089/4982] KVM: MMU: drop zeroing on mmu_memory_cache_alloc Zeroing on mmu_memory_cache_alloc is unnecessary since: - Smaller areas are pre-allocated with kmem_cache_zalloc. - Page pointed by ->spt is overwritten with prefetch_page and entries in page pointed by ->gfns are initialized before reading. [avi: zeroing pages is unnecessary] Signed-off-by: Marcelo Tosatti Signed-off-by: Avi Kivity --- arch/x86/kvm/mmu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index aac0499947d..de9a9fbc16e 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -352,7 +352,6 @@ static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc, BUG_ON(!mc->nobjs); p = mc->objects[--mc->nobjs]; - memset(p, 0, size); return p; } -- GitLab From f6e2c02b6d28ddabe99377c5640a833407a62632 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 11 Jan 2009 13:02:10 +0200 Subject: [PATCH 4090/4982] KVM: MMU: Rename "metaphysical" attribute to "direct" This actually describes what is going on, rather than alerting the reader that something strange is going on. Signed-off-by: Avi Kivity --- arch/x86/include/asm/kvm_host.h | 5 +++-- arch/x86/kvm/mmu.c | 32 ++++++++++++++++---------------- arch/x86/kvm/paging_tmpl.h | 12 ++++++------ 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 863ea73431a..55fd4c5fd38 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -170,7 +170,8 @@ struct kvm_pte_chain { * bits 0:3 - total guest paging levels (2-4, or zero for real mode) * bits 4:7 - page table level for this shadow (1-4) * bits 8:9 - page table quadrant for 2-level guests - * bit 16 - "metaphysical" - gfn is not a real page (huge page/real mode) + * bit 16 - direct mapping of virtual to physical mapping at gfn + * used for real mode and two-dimensional paging * bits 17:19 - common access permissions for all ptes in this shadow page */ union kvm_mmu_page_role { @@ -180,7 +181,7 @@ union kvm_mmu_page_role { unsigned level:4; unsigned quadrant:2; unsigned pad_for_nice_hex_output:6; - unsigned metaphysical:1; + unsigned direct:1; unsigned access:3; unsigned invalid:1; unsigned cr4_pge:1; diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index de9a9fbc16e..ef060ec444a 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -1066,7 +1066,7 @@ static struct kvm_mmu_page *kvm_mmu_lookup_page(struct kvm *kvm, gfn_t gfn) index = kvm_page_table_hashfn(gfn); bucket = &kvm->arch.mmu_page_hash[index]; hlist_for_each_entry(sp, node, bucket, hash_link) - if (sp->gfn == gfn && !sp->role.metaphysical + if (sp->gfn == gfn && !sp->role.direct && !sp->role.invalid) { pgprintk("%s: found role %x\n", __func__, sp->role.word); @@ -1200,7 +1200,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, gfn_t gfn, gva_t gaddr, unsigned level, - int metaphysical, + int direct, unsigned access, u64 *parent_pte) { @@ -1213,7 +1213,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, role = vcpu->arch.mmu.base_role; role.level = level; - role.metaphysical = metaphysical; + role.direct = direct; role.access = access; if (vcpu->arch.mmu.root_level <= PT32_ROOT_LEVEL) { quadrant = gaddr >> (PAGE_SHIFT + (PT64_PT_BITS * level)); @@ -1250,7 +1250,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, sp->role = role; sp->global = role.cr4_pge; hlist_add_head(&sp->hash_link, bucket); - if (!metaphysical) { + if (!direct) { if (rmap_write_protect(vcpu->kvm, gfn)) kvm_flush_remote_tlbs(vcpu->kvm); account_shadowed(vcpu->kvm, gfn); @@ -1395,7 +1395,7 @@ static int kvm_mmu_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp) kvm_mmu_page_unlink_children(kvm, sp); kvm_mmu_unlink_parents(kvm, sp); kvm_flush_remote_tlbs(kvm); - if (!sp->role.invalid && !sp->role.metaphysical) + if (!sp->role.invalid && !sp->role.direct) unaccount_shadowed(kvm, sp->gfn); if (sp->unsync) kvm_unlink_unsync_page(kvm, sp); @@ -1458,7 +1458,7 @@ static int kvm_mmu_unprotect_page(struct kvm *kvm, gfn_t gfn) index = kvm_page_table_hashfn(gfn); bucket = &kvm->arch.mmu_page_hash[index]; hlist_for_each_entry_safe(sp, node, n, bucket, hash_link) - if (sp->gfn == gfn && !sp->role.metaphysical) { + if (sp->gfn == gfn && !sp->role.direct) { pgprintk("%s: gfn %lx role %x\n", __func__, gfn, sp->role.word); r = 1; @@ -1478,7 +1478,7 @@ static void mmu_unshadow(struct kvm *kvm, gfn_t gfn) index = kvm_page_table_hashfn(gfn); bucket = &kvm->arch.mmu_page_hash[index]; hlist_for_each_entry_safe(sp, node, nn, bucket, hash_link) { - if (sp->gfn == gfn && !sp->role.metaphysical + if (sp->gfn == gfn && !sp->role.direct && !sp->role.invalid) { pgprintk("%s: zap %lx %x\n", __func__, gfn, sp->role.word); @@ -1638,7 +1638,7 @@ static int kvm_unsync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) bucket = &vcpu->kvm->arch.mmu_page_hash[index]; /* don't unsync if pagetable is shadowed with multiple roles */ hlist_for_each_entry_safe(s, node, n, bucket, hash_link) { - if (s->gfn != sp->gfn || s->role.metaphysical) + if (s->gfn != sp->gfn || s->role.direct) continue; if (s->role.word != sp->role.word) return 1; @@ -1951,7 +1951,7 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu) int i; gfn_t root_gfn; struct kvm_mmu_page *sp; - int metaphysical = 0; + int direct = 0; root_gfn = vcpu->arch.cr3 >> PAGE_SHIFT; @@ -1960,18 +1960,18 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu) ASSERT(!VALID_PAGE(root)); if (tdp_enabled) - metaphysical = 1; + direct = 1; sp = kvm_mmu_get_page(vcpu, root_gfn, 0, - PT64_ROOT_LEVEL, metaphysical, + PT64_ROOT_LEVEL, direct, ACC_ALL, NULL); root = __pa(sp->spt); ++sp->root_count; vcpu->arch.mmu.root_hpa = root; return; } - metaphysical = !is_paging(vcpu); + direct = !is_paging(vcpu); if (tdp_enabled) - metaphysical = 1; + direct = 1; for (i = 0; i < 4; ++i) { hpa_t root = vcpu->arch.mmu.pae_root[i]; @@ -1985,7 +1985,7 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu) } else if (vcpu->arch.mmu.root_level == 0) root_gfn = 0; sp = kvm_mmu_get_page(vcpu, root_gfn, i << 30, - PT32_ROOT_LEVEL, metaphysical, + PT32_ROOT_LEVEL, direct, ACC_ALL, NULL); root = __pa(sp->spt); ++sp->root_count; @@ -2487,7 +2487,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, index = kvm_page_table_hashfn(gfn); bucket = &vcpu->kvm->arch.mmu_page_hash[index]; hlist_for_each_entry_safe(sp, node, n, bucket, hash_link) { - if (sp->gfn != gfn || sp->role.metaphysical || sp->role.invalid) + if (sp->gfn != gfn || sp->role.direct || sp->role.invalid) continue; pte_size = sp->role.glevels == PT32_ROOT_LEVEL ? 4 : 8; misaligned = (offset ^ (offset + bytes - 1)) & ~(pte_size - 1); @@ -3125,7 +3125,7 @@ static void audit_write_protection(struct kvm_vcpu *vcpu) gfn_t gfn; list_for_each_entry(sp, &vcpu->kvm->arch.active_mmu_pages, link) { - if (sp->role.metaphysical) + if (sp->role.direct) continue; gfn = unalias_gfn(vcpu->kvm, sp->gfn); diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index 46b68f941f6..7314c0944c5 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h @@ -277,7 +277,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, unsigned access = gw->pt_access; struct kvm_mmu_page *shadow_page; u64 spte, *sptep; - int metaphysical; + int direct; gfn_t table_gfn; int r; int level; @@ -313,17 +313,17 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, if (level == PT_DIRECTORY_LEVEL && gw->level == PT_DIRECTORY_LEVEL) { - metaphysical = 1; + direct = 1; if (!is_dirty_pte(gw->ptes[level - 1])) access &= ~ACC_WRITE_MASK; table_gfn = gpte_to_gfn(gw->ptes[level - 1]); } else { - metaphysical = 0; + direct = 0; table_gfn = gw->table_gfn[level - 2]; } shadow_page = kvm_mmu_get_page(vcpu, table_gfn, addr, level-1, - metaphysical, access, sptep); - if (!metaphysical) { + direct, access, sptep); + if (!direct) { r = kvm_read_guest_atomic(vcpu->kvm, gw->pte_gpa[level - 2], &curr_pte, sizeof(curr_pte)); @@ -512,7 +512,7 @@ static void FNAME(prefetch_page)(struct kvm_vcpu *vcpu, pt_element_t pt[256 / sizeof(pt_element_t)]; gpa_t pte_gpa; - if (sp->role.metaphysical + if (sp->role.direct || (PTTYPE == 32 && sp->role.level > PT_PAGE_TABLE_LEVEL)) { nonpaging_prefetch_page(vcpu, sp); return; -- GitLab From 5a41accd3f69c6ef1d58f0c148980bae70515937 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 11 Jan 2009 17:19:35 +0200 Subject: [PATCH 4091/4982] KVM: MMU: Only enable cr4_pge role in shadow mode Two dimensional paging is only confused by it. Signed-off-by: Avi Kivity --- arch/x86/kvm/x86.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 6fbc3460337..19ccde621cd 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -364,7 +364,7 @@ void kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) } kvm_x86_ops->set_cr4(vcpu, cr4); vcpu->arch.cr4 = cr4; - vcpu->arch.mmu.base_role.cr4_pge = !!(cr4 & X86_CR4_PGE); + vcpu->arch.mmu.base_role.cr4_pge = (cr4 & X86_CR4_PGE) && !tdp_enabled; kvm_mmu_sync_global(vcpu); kvm_mmu_reset_context(vcpu); } -- GitLab From 87c656b4147cd08c6efba95d8d70c12cba181255 Mon Sep 17 00:00:00 2001 From: Liu Yu Date: Wed, 14 Jan 2009 10:47:36 -0600 Subject: [PATCH 4092/4982] powerpc/fsl-booke: declare tlbcam_index for use in c So, KVM needs to read tlbcam_index to know exactly which TLB1 entry is unused by host. Signed-off-by: Liu Yu Acked-by: Kumar Gala Signed-off-by: Hollis Blanchard Signed-off-by: Avi Kivity --- arch/powerpc/include/asm/mmu-fsl-booke.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/powerpc/include/asm/mmu-fsl-booke.h b/arch/powerpc/include/asm/mmu-fsl-booke.h index 3f941c0f7e8..4285b64a65e 100644 --- a/arch/powerpc/include/asm/mmu-fsl-booke.h +++ b/arch/powerpc/include/asm/mmu-fsl-booke.h @@ -75,6 +75,8 @@ #ifndef __ASSEMBLY__ +extern unsigned int tlbcam_index; + typedef struct { unsigned int id; unsigned int active; -- GitLab From fb2838d446f6ee7e13e4149e08ec138753c5c450 Mon Sep 17 00:00:00 2001 From: Liu Yu Date: Wed, 14 Jan 2009 10:47:37 -0600 Subject: [PATCH 4093/4982] KVM: ppc: Fix e500 warnings and some spelling problems Signed-off-by: Avi Kivity --- arch/powerpc/kvm/e500_emulate.c | 2 -- arch/powerpc/kvm/e500_tlb.c | 6 +++--- arch/powerpc/kvm/e500_tlb.h | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c index d3c0c7c7f20..7a98d4a4c1e 100644 --- a/arch/powerpc/kvm/e500_emulate.c +++ b/arch/powerpc/kvm/e500_emulate.c @@ -30,8 +30,6 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, int emulated = EMULATE_DONE; int ra; int rb; - int rs; - int rt; switch (get_op(inst)) { case 31: diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c index 6a50340f575..e3daf57b5f5 100644 --- a/arch/powerpc/kvm/e500_tlb.c +++ b/arch/powerpc/kvm/e500_tlb.c @@ -260,7 +260,7 @@ static inline void kvmppc_e500_deliver_tlb_miss(struct kvm_vcpu *vcpu, unsigned int victim, pidsel, tsized; int tlbsel; - /* since we only have tow TLBs, only lower bit is used. */ + /* since we only have two TLBs, only lower bit is used. */ tlbsel = (vcpu_e500->mas4 >> 28) & 0x1; victim = (tlbsel == 0) ? tlb0_get_next_victim(vcpu_e500) : 0; pidsel = (vcpu_e500->mas4 >> 16) & 0xf; @@ -402,7 +402,7 @@ int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb) ia = (ea >> 2) & 0x1; - /* since we only have tow TLBs, only lower bit is used. */ + /* since we only have two TLBs, only lower bit is used. */ tlbsel = (ea >> 3) & 0x1; if (ia) { @@ -471,7 +471,7 @@ int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb) } else { int victim; - /* since we only have tow TLBs, only lower bit is used. */ + /* since we only have two TLBs, only lower bit is used. */ tlbsel = vcpu_e500->mas4 >> 28 & 0x1; victim = (tlbsel == 0) ? tlb0_get_next_victim(vcpu_e500) : 0; diff --git a/arch/powerpc/kvm/e500_tlb.h b/arch/powerpc/kvm/e500_tlb.h index d8833f95516..ab49e935518 100644 --- a/arch/powerpc/kvm/e500_tlb.h +++ b/arch/powerpc/kvm/e500_tlb.h @@ -126,7 +126,7 @@ static inline unsigned int get_tlb_tlbsel( { /* * Manual says that tlbsel has 2 bits wide. - * Since we only have tow TLBs, only lower bit is used. + * Since we only have two TLBs, only lower bit is used. */ return (vcpu_e500->mas0 >> 28) & 0x1; } -- GitLab From 9aa4dd5e5f47a5feb96fc394fccf0265ab7d85a4 Mon Sep 17 00:00:00 2001 From: Liu Yu Date: Wed, 14 Jan 2009 10:47:38 -0600 Subject: [PATCH 4094/4982] KVM: ppc: Move to new TLB invalidate interface Commit 2a4aca1144394653269720ffbb5a325a77abd5fa removed old method _tlbia(). Signed-off-by: Liu Yu Signed-off-by: Hollis Blanchard Signed-off-by: Avi Kivity --- arch/powerpc/kvm/e500_tlb.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c index e3daf57b5f5..d437160d388 100644 --- a/arch/powerpc/kvm/e500_tlb.c +++ b/arch/powerpc/kvm/e500_tlb.c @@ -20,6 +20,7 @@ #include #include +#include "../mm/mmu_decl.h" #include "e500_tlb.h" #define to_htlb1_esel(esel) (tlb1_entry_num - (esel) - 1) @@ -158,7 +159,7 @@ void kvmppc_e500_tlb_load(struct kvm_vcpu *vcpu, int cpu) void kvmppc_e500_tlb_put(struct kvm_vcpu *vcpu) { - _tlbia(); + _tlbil_all(); } /* Search the guest TLB for a matching entry. */ @@ -362,11 +363,10 @@ void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode) int i; /* XXX Replace loop with fancy data structures. */ - /* needn't set modified since tlbia will make TLB1 coherent */ for (i = 0; i < tlb1_max_shadow_size(); i++) kvmppc_e500_stlbe_invalidate(vcpu_e500, 1, i); - _tlbia(); + _tlbil_all(); } } @@ -417,7 +417,7 @@ int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb) kvmppc_e500_gtlbe_invalidate(vcpu_e500, tlbsel, esel); } - _tlbia(); + _tlbil_all(); return EMULATE_DONE; } @@ -604,7 +604,7 @@ void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu) kvmppc_e500_shadow_release(vcpu_e500, tlbsel, i); /* discard all guest mapping */ - _tlbia(); + _tlbil_all(); } void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr, -- GitLab From 193554750441d91e127dd5066b8aebe0f769101c Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Wed, 14 Jan 2009 16:56:00 +0000 Subject: [PATCH 4095/4982] KVM: x86: Fix typos and whitespace errors Some typos, comments, whitespace errors corrected in the cpuid code Signed-off-by: Amit Shah Signed-off-by: Avi Kivity --- arch/x86/kvm/x86.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 19ccde621cd..141a0166e51 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1067,7 +1067,7 @@ long kvm_arch_dev_ioctl(struct file *filp, if (copy_from_user(&cpuid, cpuid_arg, sizeof cpuid)) goto out; r = kvm_dev_ioctl_get_supported_cpuid(&cpuid, - cpuid_arg->entries); + cpuid_arg->entries); if (r) goto out; @@ -1165,8 +1165,8 @@ out: } static int kvm_vcpu_ioctl_set_cpuid2(struct kvm_vcpu *vcpu, - struct kvm_cpuid2 *cpuid, - struct kvm_cpuid_entry2 __user *entries) + struct kvm_cpuid2 *cpuid, + struct kvm_cpuid_entry2 __user *entries) { int r; @@ -1185,8 +1185,8 @@ out: } static int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu, - struct kvm_cpuid2 *cpuid, - struct kvm_cpuid_entry2 __user *entries) + struct kvm_cpuid2 *cpuid, + struct kvm_cpuid_entry2 __user *entries) { int r; @@ -1195,7 +1195,7 @@ static int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu, goto out; r = -EFAULT; if (copy_to_user(entries, &vcpu->arch.cpuid_entries, - vcpu->arch.cpuid_nent * sizeof(struct kvm_cpuid_entry2))) + vcpu->arch.cpuid_nent * sizeof(struct kvm_cpuid_entry2))) goto out; return 0; @@ -1205,12 +1205,12 @@ out: } static void do_cpuid_1_ent(struct kvm_cpuid_entry2 *entry, u32 function, - u32 index) + u32 index) { entry->function = function; entry->index = index; cpuid_count(entry->function, entry->index, - &entry->eax, &entry->ebx, &entry->ecx, &entry->edx); + &entry->eax, &entry->ebx, &entry->ecx, &entry->edx); entry->flags = 0; } @@ -1249,7 +1249,7 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, bit(X86_FEATURE_LAHF_LM) | bit(X86_FEATURE_CMP_LEGACY) | bit(X86_FEATURE_SVM); - /* all func 2 cpuid_count() should be called on the same cpu */ + /* all calls to cpuid_count() should be made on the same cpu */ get_cpu(); do_cpuid_1_ent(entry, function, index); ++*nent; @@ -1323,7 +1323,7 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, } static int kvm_dev_ioctl_get_supported_cpuid(struct kvm_cpuid2 *cpuid, - struct kvm_cpuid_entry2 __user *entries) + struct kvm_cpuid_entry2 __user *entries) { struct kvm_cpuid_entry2 *cpuid_entries; int limit, nent = 0, r = -E2BIG; @@ -1340,7 +1340,7 @@ static int kvm_dev_ioctl_get_supported_cpuid(struct kvm_cpuid2 *cpuid, limit = cpuid_entries[0].eax; for (func = 1; func <= limit && nent < cpuid->nent; ++func) do_cpuid_ent(&cpuid_entries[nent], func, 0, - &nent, cpuid->nent); + &nent, cpuid->nent); r = -E2BIG; if (nent >= cpuid->nent) goto out_free; @@ -1349,10 +1349,10 @@ static int kvm_dev_ioctl_get_supported_cpuid(struct kvm_cpuid2 *cpuid, limit = cpuid_entries[nent - 1].eax; for (func = 0x80000001; func <= limit && nent < cpuid->nent; ++func) do_cpuid_ent(&cpuid_entries[nent], func, 0, - &nent, cpuid->nent); + &nent, cpuid->nent); r = -EFAULT; if (copy_to_user(entries, cpuid_entries, - nent * sizeof(struct kvm_cpuid_entry2))) + nent * sizeof(struct kvm_cpuid_entry2))) goto out_free; cpuid->nent = nent; r = 0; @@ -1496,7 +1496,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp, if (copy_from_user(&cpuid, cpuid_arg, sizeof cpuid)) goto out; r = kvm_vcpu_ioctl_set_cpuid2(vcpu, &cpuid, - cpuid_arg->entries); + cpuid_arg->entries); if (r) goto out; break; @@ -1509,7 +1509,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp, if (copy_from_user(&cpuid, cpuid_arg, sizeof cpuid)) goto out; r = kvm_vcpu_ioctl_get_cpuid2(vcpu, &cpuid, - cpuid_arg->entries); + cpuid_arg->entries); if (r) goto out; r = -EFAULT; @@ -2864,7 +2864,7 @@ static int is_matching_cpuid_entry(struct kvm_cpuid_entry2 *e, if ((e->flags & KVM_CPUID_FLAG_SIGNIFCANT_INDEX) && e->index != index) return 0; if ((e->flags & KVM_CPUID_FLAG_STATEFUL_FUNC) && - !(e->flags & KVM_CPUID_FLAG_STATE_READ_NEXT)) + !(e->flags & KVM_CPUID_FLAG_STATE_READ_NEXT)) return 0; return 1; } @@ -2892,7 +2892,6 @@ struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu, if (!best || e->function > best->function) best = e; } - return best; } -- GitLab From 399ec807ddc38ecccf8c06dbde04531cbdc63e11 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 19 Nov 2008 13:58:46 +0200 Subject: [PATCH 4096/4982] KVM: Userspace controlled irq routing Currently KVM has a static routing from GSI numbers to interrupts (namely, 0-15 are mapped 1:1 to both PIC and IOAPIC, and 16:23 are mapped 1:1 to the IOAPIC). This is insufficient for several reasons: - HPET requires non 1:1 mapping for the timer interrupt - MSIs need a new method to assign interrupt numbers and dispatch them - ACPI APIC mode needs to be able to reassign the PCI LINK interrupts to the ioapics This patch implements an interrupt routing table (as a linked list, but this can be easily changed) and a userspace interface to replace the table. The routing table is initialized according to the current hardwired mapping. Signed-off-by: Avi Kivity --- arch/ia64/kvm/kvm-ia64.c | 5 ++ arch/x86/kvm/x86.c | 6 ++ include/linux/kvm.h | 33 ++++++++ include/linux/kvm_host.h | 31 ++++++++ virt/kvm/irq_comm.c | 168 ++++++++++++++++++++++++++++++++++++++- virt/kvm/kvm_main.c | 36 +++++++++ 6 files changed, 275 insertions(+), 4 deletions(-) diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index 1477f91617a..dbf527a5734 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c @@ -919,6 +919,11 @@ long kvm_arch_vm_ioctl(struct file *filp, r = kvm_ioapic_init(kvm); if (r) goto out; + r = kvm_setup_default_irq_routing(kvm); + if (r) { + kfree(kvm->arch.vioapic); + goto out; + } break; case KVM_IRQ_LINE: { struct kvm_irq_level irq_event; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 141a0166e51..32e3a7ec6ad 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1835,6 +1835,12 @@ long kvm_arch_vm_ioctl(struct file *filp, } } else goto out; + r = kvm_setup_default_irq_routing(kvm); + if (r) { + kfree(kvm->arch.vpic); + kfree(kvm->arch.vioapic); + goto out; + } break; case KVM_CREATE_PIT: mutex_lock(&kvm->lock); diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 73f34806686..7a5d73a8d4f 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h @@ -398,6 +398,38 @@ struct kvm_trace_rec { #endif #if defined(CONFIG_X86) #define KVM_CAP_REINJECT_CONTROL 24 +#endif +#if defined(CONFIG_X86)||defined(CONFIG_IA64) +#define KVM_CAP_IRQ_ROUTING 25 +#endif + +#ifdef KVM_CAP_IRQ_ROUTING + +struct kvm_irq_routing_irqchip { + __u32 irqchip; + __u32 pin; +}; + +/* gsi routing entry types */ +#define KVM_IRQ_ROUTING_IRQCHIP 1 + +struct kvm_irq_routing_entry { + __u32 gsi; + __u32 type; + __u32 flags; + __u32 pad; + union { + struct kvm_irq_routing_irqchip irqchip; + __u32 pad[8]; + } u; +}; + +struct kvm_irq_routing { + __u32 nr; + __u32 flags; + struct kvm_irq_routing_entry entries[0]; +}; + #endif /* @@ -430,6 +462,7 @@ struct kvm_trace_rec { _IOW(KVMIO, 0x68, struct kvm_coalesced_mmio_zone) #define KVM_ASSIGN_PCI_DEVICE _IOR(KVMIO, 0x69, \ struct kvm_assigned_pci_dev) +#define KVM_SET_GSI_ROUTING _IOW(KVMIO, 0x6a, struct kvm_irq_routing) #define KVM_ASSIGN_IRQ _IOR(KVMIO, 0x70, \ struct kvm_assigned_irq) #define KVM_REINJECT_CONTROL _IO(KVMIO, 0x71) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 99963f36a6d..ce285e01bd5 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -107,6 +107,19 @@ struct kvm_memory_slot { int user_alloc; }; +struct kvm_kernel_irq_routing_entry { + u32 gsi; + void (*set)(struct kvm_kernel_irq_routing_entry *e, + struct kvm *kvm, int level); + union { + struct { + unsigned irqchip; + unsigned pin; + } irqchip; + }; + struct list_head link; +}; + struct kvm { struct mutex lock; /* protects the vcpus array and APIC accesses */ spinlock_t mmu_lock; @@ -128,6 +141,7 @@ struct kvm { #endif #ifdef CONFIG_HAVE_KVM_IRQCHIP + struct list_head irq_routing; /* of kvm_kernel_irq_routing_entry */ struct hlist_head mask_notifier_list; #endif @@ -480,4 +494,21 @@ static inline int mmu_notifier_retry(struct kvm_vcpu *vcpu, unsigned long mmu_se } #endif +#ifdef CONFIG_HAVE_KVM_IRQCHIP + +#define KVM_MAX_IRQ_ROUTES 1024 + +int kvm_setup_default_irq_routing(struct kvm *kvm); +int kvm_set_irq_routing(struct kvm *kvm, + const struct kvm_irq_routing_entry *entries, + unsigned nr, + unsigned flags); +void kvm_free_irq_routing(struct kvm *kvm); + +#else + +static inline void kvm_free_irq_routing(struct kvm *kvm) {} + +#endif + #endif diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index 5162a411e4d..a797fa5e642 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c @@ -24,9 +24,24 @@ #include "ioapic.h" +static void kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e, + struct kvm *kvm, int level) +{ +#ifdef CONFIG_X86 + kvm_pic_set_irq(pic_irqchip(kvm), e->irqchip.pin, level); +#endif +} + +static void kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e, + struct kvm *kvm, int level) +{ + kvm_ioapic_set_irq(kvm->arch.vioapic, e->irqchip.pin, level); +} + /* This should be called with the kvm->lock mutex held */ void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level) { + struct kvm_kernel_irq_routing_entry *e; unsigned long *irq_state = (unsigned long *)&kvm->arch.irq_states[irq]; /* Logical OR for level trig interrupt */ @@ -39,10 +54,9 @@ void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level) * IOAPIC. So set the bit in both. The guest will ignore * writes to the unused one. */ - kvm_ioapic_set_irq(kvm->arch.vioapic, irq, !!(*irq_state)); -#ifdef CONFIG_X86 - kvm_pic_set_irq(pic_irqchip(kvm), irq, !!(*irq_state)); -#endif + list_for_each_entry(e, &kvm->irq_routing, link) + if (e->gsi == irq) + e->set(e, kvm, !!(*irq_state)); } void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi) @@ -123,3 +137,149 @@ void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, bool mask) kimn->func(kimn, mask); } +static void __kvm_free_irq_routing(struct list_head *irq_routing) +{ + struct kvm_kernel_irq_routing_entry *e, *n; + + list_for_each_entry_safe(e, n, irq_routing, link) + kfree(e); +} + +void kvm_free_irq_routing(struct kvm *kvm) +{ + __kvm_free_irq_routing(&kvm->irq_routing); +} + +int setup_routing_entry(struct kvm_kernel_irq_routing_entry *e, + const struct kvm_irq_routing_entry *ue) +{ + int r = -EINVAL; + int delta; + + e->gsi = ue->gsi; + switch (ue->type) { + case KVM_IRQ_ROUTING_IRQCHIP: + delta = 0; + switch (ue->u.irqchip.irqchip) { + case KVM_IRQCHIP_PIC_MASTER: + e->set = kvm_set_pic_irq; + break; + case KVM_IRQCHIP_PIC_SLAVE: + e->set = kvm_set_pic_irq; + delta = 8; + break; + case KVM_IRQCHIP_IOAPIC: + e->set = kvm_set_ioapic_irq; + break; + default: + goto out; + } + e->irqchip.irqchip = ue->u.irqchip.irqchip; + e->irqchip.pin = ue->u.irqchip.pin + delta; + break; + default: + goto out; + } + r = 0; +out: + return r; +} + + +int kvm_set_irq_routing(struct kvm *kvm, + const struct kvm_irq_routing_entry *ue, + unsigned nr, + unsigned flags) +{ + struct list_head irq_list = LIST_HEAD_INIT(irq_list); + struct list_head tmp = LIST_HEAD_INIT(tmp); + struct kvm_kernel_irq_routing_entry *e = NULL; + unsigned i; + int r; + + for (i = 0; i < nr; ++i) { + r = -EINVAL; + if (ue->gsi >= KVM_MAX_IRQ_ROUTES) + goto out; + if (ue->flags) + goto out; + r = -ENOMEM; + e = kzalloc(sizeof(*e), GFP_KERNEL); + if (!e) + goto out; + r = setup_routing_entry(e, ue); + if (r) + goto out; + ++ue; + list_add(&e->link, &irq_list); + e = NULL; + } + + mutex_lock(&kvm->lock); + list_splice(&kvm->irq_routing, &tmp); + INIT_LIST_HEAD(&kvm->irq_routing); + list_splice(&irq_list, &kvm->irq_routing); + INIT_LIST_HEAD(&irq_list); + list_splice(&tmp, &irq_list); + mutex_unlock(&kvm->lock); + + r = 0; + +out: + kfree(e); + __kvm_free_irq_routing(&irq_list); + return r; +} + +#define IOAPIC_ROUTING_ENTRY(irq) \ + { .gsi = irq, .type = KVM_IRQ_ROUTING_IRQCHIP, \ + .u.irqchip.irqchip = KVM_IRQCHIP_IOAPIC, .u.irqchip.pin = (irq) } +#define ROUTING_ENTRY1(irq) IOAPIC_ROUTING_ENTRY(irq) + +#ifdef CONFIG_X86 +#define SELECT_PIC(irq) \ + ((irq) < 8 ? KVM_IRQCHIP_PIC_MASTER : KVM_IRQCHIP_PIC_SLAVE) +# define PIC_ROUTING_ENTRY(irq) \ + { .gsi = irq, .type = KVM_IRQ_ROUTING_IRQCHIP, \ + .u.irqchip.irqchip = SELECT_PIC(irq), .u.irqchip.pin = (irq) % 8 } +# define ROUTING_ENTRY2(irq) \ + IOAPIC_ROUTING_ENTRY(irq), PIC_ROUTING_ENTRY(irq) +#else +# define ROUTING_ENTRY2(irq) \ + IOAPIC_ROUTING_ENTRY(irq) +#endif + +static const struct kvm_irq_routing_entry default_routing[] = { + ROUTING_ENTRY2(0), ROUTING_ENTRY2(1), + ROUTING_ENTRY2(2), ROUTING_ENTRY2(3), + ROUTING_ENTRY2(4), ROUTING_ENTRY2(5), + ROUTING_ENTRY2(6), ROUTING_ENTRY2(7), + ROUTING_ENTRY2(8), ROUTING_ENTRY2(9), + ROUTING_ENTRY2(10), ROUTING_ENTRY2(11), + ROUTING_ENTRY2(12), ROUTING_ENTRY2(13), + ROUTING_ENTRY2(14), ROUTING_ENTRY2(15), + ROUTING_ENTRY1(16), ROUTING_ENTRY1(17), + ROUTING_ENTRY1(18), ROUTING_ENTRY1(19), + ROUTING_ENTRY1(20), ROUTING_ENTRY1(21), + ROUTING_ENTRY1(22), ROUTING_ENTRY1(23), +#ifdef CONFIG_IA64 + ROUTING_ENTRY1(24), ROUTING_ENTRY1(25), + ROUTING_ENTRY1(26), ROUTING_ENTRY1(27), + ROUTING_ENTRY1(28), ROUTING_ENTRY1(29), + ROUTING_ENTRY1(30), ROUTING_ENTRY1(31), + ROUTING_ENTRY1(32), ROUTING_ENTRY1(33), + ROUTING_ENTRY1(34), ROUTING_ENTRY1(35), + ROUTING_ENTRY1(36), ROUTING_ENTRY1(37), + ROUTING_ENTRY1(38), ROUTING_ENTRY1(39), + ROUTING_ENTRY1(40), ROUTING_ENTRY1(41), + ROUTING_ENTRY1(42), ROUTING_ENTRY1(43), + ROUTING_ENTRY1(44), ROUTING_ENTRY1(45), + ROUTING_ENTRY1(46), ROUTING_ENTRY1(47), +#endif +}; + +int kvm_setup_default_irq_routing(struct kvm *kvm) +{ + return kvm_set_irq_routing(kvm, default_routing, + ARRAY_SIZE(default_routing), 0); +} diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 786a3ae373b..c65484b471c 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -843,6 +843,7 @@ static struct kvm *kvm_create_vm(void) if (IS_ERR(kvm)) goto out; #ifdef CONFIG_HAVE_KVM_IRQCHIP + INIT_LIST_HEAD(&kvm->irq_routing); INIT_HLIST_HEAD(&kvm->mask_notifier_list); #endif @@ -926,6 +927,7 @@ static void kvm_destroy_vm(struct kvm *kvm) spin_lock(&kvm_lock); list_del(&kvm->vm_list); spin_unlock(&kvm_lock); + kvm_free_irq_routing(kvm); kvm_io_bus_destroy(&kvm->pio_bus); kvm_io_bus_destroy(&kvm->mmio_bus); #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET @@ -1945,6 +1947,36 @@ static long kvm_vm_ioctl(struct file *filp, goto out; break; } +#endif +#ifdef KVM_CAP_IRQ_ROUTING + case KVM_SET_GSI_ROUTING: { + struct kvm_irq_routing routing; + struct kvm_irq_routing __user *urouting; + struct kvm_irq_routing_entry *entries; + + r = -EFAULT; + if (copy_from_user(&routing, argp, sizeof(routing))) + goto out; + r = -EINVAL; + if (routing.nr >= KVM_MAX_IRQ_ROUTES) + goto out; + if (routing.flags) + goto out; + r = -ENOMEM; + entries = vmalloc(routing.nr * sizeof(*entries)); + if (!entries) + goto out; + r = -EFAULT; + urouting = argp; + if (copy_from_user(entries, urouting->entries, + routing.nr * sizeof(*entries))) + goto out_free_irq_routing; + r = kvm_set_irq_routing(kvm, entries, routing.nr, + routing.flags); + out_free_irq_routing: + vfree(entries); + break; + } #endif default: r = kvm_arch_vm_ioctl(filp, ioctl, arg); @@ -2012,6 +2044,10 @@ static long kvm_dev_ioctl_check_extension_generic(long arg) case KVM_CAP_USER_MEMORY: case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: return 1; +#ifdef CONFIG_HAVE_KVM_IRQCHIP + case KVM_CAP_IRQ_ROUTING: + return 1; +#endif default: break; } -- GitLab From 91b2ae773d3b168b763237fac33f75b13d891f20 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Mon, 19 Jan 2009 14:57:52 +0200 Subject: [PATCH 4097/4982] KVM: Avoid using CONFIG_ in userspace visible headers Kconfig symbols are not available in userspace, and are not stripped by headers-install. Avoid their use by adding #defines in to suit each architecture. Signed-off-by: Avi Kivity --- arch/x86/include/asm/kvm.h | 1 + include/linux/kvm.h | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/kvm.h b/arch/x86/include/asm/kvm.h index 54bcf228152..dc3f6cf1170 100644 --- a/arch/x86/include/asm/kvm.h +++ b/arch/x86/include/asm/kvm.h @@ -15,6 +15,7 @@ #define __KVM_HAVE_DEVICE_ASSIGNMENT #define __KVM_HAVE_MSI #define __KVM_HAVE_USER_NMI +#define __KVM_HAVE_GUEST_DEBUG /* Architectural interrupt line count. */ #define KVM_NR_INTERRUPTS 256 diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 7a5d73a8d4f..869462ca762 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h @@ -393,13 +393,13 @@ struct kvm_trace_rec { #ifdef __KVM_HAVE_USER_NMI #define KVM_CAP_USER_NMI 22 #endif -#if defined(CONFIG_X86) +#ifdef __KVM_HAVE_GUEST_DEBUG #define KVM_CAP_SET_GUEST_DEBUG 23 #endif -#if defined(CONFIG_X86) +#ifdef __KVM_HAVE_PIT #define KVM_CAP_REINJECT_CONTROL 24 #endif -#if defined(CONFIG_X86)||defined(CONFIG_IA64) +#ifdef __KVM_HAVE_IOAPIC #define KVM_CAP_IRQ_ROUTING 25 #endif -- GitLab From 27d146449ccaad16480888129bb32a000ee33717 Mon Sep 17 00:00:00 2001 From: Xiantao Zhang Date: Thu, 15 Jan 2009 17:58:19 +0800 Subject: [PATCH 4098/4982] KVM: ia64: vTLB change for enabling windows 2008 boot Simply the logic of hash vTLB, and export kvm_gpa_to_mpa. Signed-off-by: Xiantao Zhang Signed-off-by: Avi Kivity --- arch/ia64/kvm/vcpu.h | 4 ++-- arch/ia64/kvm/vtlb.c | 39 +++++++++++++++++---------------------- 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/arch/ia64/kvm/vcpu.h b/arch/ia64/kvm/vcpu.h index b2f12a562bd..042af92ced8 100644 --- a/arch/ia64/kvm/vcpu.h +++ b/arch/ia64/kvm/vcpu.h @@ -703,7 +703,7 @@ extern u64 guest_vhpt_lookup(u64 iha, u64 *pte); extern void thash_purge_entries(struct kvm_vcpu *v, u64 va, u64 ps); extern void thash_purge_entries_remote(struct kvm_vcpu *v, u64 va, u64 ps); extern u64 translate_phy_pte(u64 *pte, u64 itir, u64 va); -extern int thash_purge_and_insert(struct kvm_vcpu *v, u64 pte, +extern void thash_purge_and_insert(struct kvm_vcpu *v, u64 pte, u64 itir, u64 ifa, int type); extern void thash_purge_all(struct kvm_vcpu *v); extern struct thash_data *vtlb_lookup(struct kvm_vcpu *v, @@ -738,7 +738,7 @@ void kvm_init_vhpt(struct kvm_vcpu *v); void thash_init(struct thash_cb *hcb, u64 sz); void panic_vm(struct kvm_vcpu *v, const char *fmt, ...); - +u64 kvm_gpa_to_mpa(u64 gpa); extern u64 ia64_call_vsa(u64 proc, u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7); diff --git a/arch/ia64/kvm/vtlb.c b/arch/ia64/kvm/vtlb.c index ac94867f826..38232b37668 100644 --- a/arch/ia64/kvm/vtlb.c +++ b/arch/ia64/kvm/vtlb.c @@ -164,11 +164,11 @@ static void vhpt_insert(u64 pte, u64 itir, u64 ifa, u64 gpte) unsigned long ps, gpaddr; ps = itir_ps(itir); + rr.val = ia64_get_rr(ifa); - gpaddr = ((gpte & _PAGE_PPN_MASK) >> ps << ps) | - (ifa & ((1UL << ps) - 1)); + gpaddr = ((gpte & _PAGE_PPN_MASK) >> ps << ps) | + (ifa & ((1UL << ps) - 1)); - rr.val = ia64_get_rr(ifa); head = (struct thash_data *)ia64_thash(ifa); head->etag = INVALID_TI_TAG; ia64_mf(); @@ -412,16 +412,14 @@ u64 translate_phy_pte(u64 *pte, u64 itir, u64 va) /* * Purge overlap TCs and then insert the new entry to emulate itc ops. - * Notes: Only TC entry can purge and insert. - * 1 indicates this is MMIO + * Notes: Only TC entry can purge and insert. */ -int thash_purge_and_insert(struct kvm_vcpu *v, u64 pte, u64 itir, +void thash_purge_and_insert(struct kvm_vcpu *v, u64 pte, u64 itir, u64 ifa, int type) { u64 ps; u64 phy_pte, io_mask, index; union ia64_rr vrr, mrr; - int ret = 0; ps = itir_ps(itir); vrr.val = vcpu_get_rr(v, ifa); @@ -441,25 +439,19 @@ int thash_purge_and_insert(struct kvm_vcpu *v, u64 pte, u64 itir, phy_pte &= ~_PAGE_MA_MASK; } - if (pte & VTLB_PTE_IO) - ret = 1; - vtlb_purge(v, ifa, ps); vhpt_purge(v, ifa, ps); - if (ps == mrr.ps) { - if (!(pte&VTLB_PTE_IO)) { - vhpt_insert(phy_pte, itir, ifa, pte); - } else { - vtlb_insert(v, pte, itir, ifa); - vcpu_quick_region_set(VMX(v, tc_regions), ifa); - } - } else if (ps > mrr.ps) { + if ((ps != mrr.ps) || (pte & VTLB_PTE_IO)) { vtlb_insert(v, pte, itir, ifa); vcpu_quick_region_set(VMX(v, tc_regions), ifa); - if (!(pte&VTLB_PTE_IO)) - vhpt_insert(phy_pte, itir, ifa, pte); - } else { + } + if (pte & VTLB_PTE_IO) + return; + + if (ps >= mrr.ps) + vhpt_insert(phy_pte, itir, ifa, pte); + else { u64 psr; phy_pte &= ~PAGE_FLAGS_RV_MASK; psr = ia64_clear_ic(); @@ -469,7 +461,6 @@ int thash_purge_and_insert(struct kvm_vcpu *v, u64 pte, u64 itir, if (!(pte&VTLB_PTE_IO)) mark_pages_dirty(v, pte, ps); - return ret; } /* @@ -570,6 +561,10 @@ void thash_init(struct thash_cb *hcb, u64 sz) u64 kvm_get_mpt_entry(u64 gpfn) { u64 *base = (u64 *) KVM_P2M_BASE; + + if (gpfn >= (KVM_P2M_SIZE >> 3)) + panic_vm(current_vcpu, "Invalid gpfn =%lx\n", gpfn); + return *(base + gpfn); } -- GitLab From 4b7bb626e3133eab131328a0770864b322c1bfe6 Mon Sep 17 00:00:00 2001 From: Xiantao Zhang Date: Thu, 15 Jan 2009 18:08:36 +0800 Subject: [PATCH 4099/4982] KVM: ia64: Add the support for translating PAL Call's pointer args Add the support to translate PAL Call's pointer args. Signed-off-by: Xiantao Zhang Signed-off-by: Avi Kivity --- arch/ia64/kvm/process.c | 48 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/arch/ia64/kvm/process.c b/arch/ia64/kvm/process.c index f9c9504144f..0e727ce0d55 100644 --- a/arch/ia64/kvm/process.c +++ b/arch/ia64/kvm/process.c @@ -550,18 +550,60 @@ void reflect_interruption(u64 ifa, u64 isr, u64 iim, inject_guest_interruption(vcpu, vector); } +static unsigned long kvm_trans_pal_call_args(struct kvm_vcpu *vcpu, + unsigned long arg) +{ + struct thash_data *data; + unsigned long gpa, poff; + + if (!is_physical_mode(vcpu)) { + /* Depends on caller to provide the DTR or DTC mapping.*/ + data = vtlb_lookup(vcpu, arg, D_TLB); + if (data) + gpa = data->page_flags & _PAGE_PPN_MASK; + else { + data = vhpt_lookup(arg); + if (!data) + return 0; + gpa = data->gpaddr & _PAGE_PPN_MASK; + } + + poff = arg & (PSIZE(data->ps) - 1); + arg = PAGEALIGN(gpa, data->ps) | poff; + } + arg = kvm_gpa_to_mpa(arg << 1 >> 1); + + return (unsigned long)__va(arg); +} + static void set_pal_call_data(struct kvm_vcpu *vcpu) { struct exit_ctl_data *p = &vcpu->arch.exit_data; + unsigned long gr28 = vcpu_get_gr(vcpu, 28); + unsigned long gr29 = vcpu_get_gr(vcpu, 29); + unsigned long gr30 = vcpu_get_gr(vcpu, 30); /*FIXME:For static and stacked convention, firmware * has put the parameters in gr28-gr31 before * break to vmm !!*/ - p->u.pal_data.gr28 = vcpu_get_gr(vcpu, 28); - p->u.pal_data.gr29 = vcpu_get_gr(vcpu, 29); - p->u.pal_data.gr30 = vcpu_get_gr(vcpu, 30); + switch (gr28) { + case PAL_PERF_MON_INFO: + case PAL_HALT_INFO: + p->u.pal_data.gr29 = kvm_trans_pal_call_args(vcpu, gr29); + p->u.pal_data.gr30 = vcpu_get_gr(vcpu, 30); + break; + case PAL_BRAND_INFO: + p->u.pal_data.gr29 = gr29;; + p->u.pal_data.gr30 = kvm_trans_pal_call_args(vcpu, gr30); + break; + default: + p->u.pal_data.gr29 = gr29;; + p->u.pal_data.gr30 = vcpu_get_gr(vcpu, 30); + } + p->u.pal_data.gr28 = gr28; p->u.pal_data.gr31 = vcpu_get_gr(vcpu, 31); + p->exit_reason = EXIT_REASON_PAL_CALL; } -- GitLab From 7d656bd996b68737d5d07643bc57311059038d67 Mon Sep 17 00:00:00 2001 From: Xiantao Zhang Date: Wed, 21 Jan 2009 11:21:27 +0800 Subject: [PATCH 4100/4982] KVM: ia64: Implement some pal calls needed for windows 2008 For windows 2008, it needs more pal calls to implement for booting. In addition, also changes the name of set_{sal, pal}_call_result to get_{sal,pal}_call_result for readability. Signed-off-by: Xiantao Zhang Signed-off-by: Avi Kivity --- arch/ia64/kvm/kvm_fw.c | 151 +++++++++++++++++++++++++++++++++++++++- arch/ia64/kvm/process.c | 8 +-- 2 files changed, 152 insertions(+), 7 deletions(-) diff --git a/arch/ia64/kvm/kvm_fw.c b/arch/ia64/kvm/kvm_fw.c index cb7600bdff9..a8ae52ed563 100644 --- a/arch/ia64/kvm/kvm_fw.c +++ b/arch/ia64/kvm/kvm_fw.c @@ -227,6 +227,18 @@ static struct ia64_pal_retval pal_proc_get_features(struct kvm_vcpu *vcpu) return result; } +static struct ia64_pal_retval pal_register_info(struct kvm_vcpu *vcpu) +{ + + struct ia64_pal_retval result = {0, 0, 0, 0}; + long in0, in1, in2, in3; + + kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3); + result.status = ia64_pal_register_info(in1, &result.v1, &result.v2); + + return result; +} + static struct ia64_pal_retval pal_cache_info(struct kvm_vcpu *vcpu) { @@ -268,8 +280,12 @@ static struct ia64_pal_retval pal_vm_summary(struct kvm_vcpu *vcpu) static struct ia64_pal_retval pal_vm_info(struct kvm_vcpu *vcpu) { struct ia64_pal_retval result; + unsigned long in0, in1, in2, in3; - INIT_PAL_STATUS_UNIMPLEMENTED(result); + kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3); + + result.status = ia64_pal_vm_info(in1, in2, + (pal_tc_info_u_t *)&result.v1, &result.v2); return result; } @@ -292,6 +308,108 @@ static void prepare_for_halt(struct kvm_vcpu *vcpu) vcpu->arch.timer_fired = 0; } +static struct ia64_pal_retval pal_perf_mon_info(struct kvm_vcpu *vcpu) +{ + long status; + unsigned long in0, in1, in2, in3, r9; + unsigned long pm_buffer[16]; + + kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3); + status = ia64_pal_perf_mon_info(pm_buffer, + (pal_perf_mon_info_u_t *) &r9); + if (status != 0) { + printk(KERN_DEBUG"PAL_PERF_MON_INFO fails ret=%ld\n", status); + } else { + if (in1) + memcpy((void *)in1, pm_buffer, sizeof(pm_buffer)); + else { + status = PAL_STATUS_EINVAL; + printk(KERN_WARNING"Invalid parameters " + "for PAL call:0x%lx!\n", in0); + } + } + return (struct ia64_pal_retval){status, r9, 0, 0}; +} + +static struct ia64_pal_retval pal_halt_info(struct kvm_vcpu *vcpu) +{ + unsigned long in0, in1, in2, in3; + long status; + unsigned long res = 1000UL | (1000UL << 16) | (10UL << 32) + | (1UL << 61) | (1UL << 60); + + kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3); + if (in1) { + memcpy((void *)in1, &res, sizeof(res)); + status = 0; + } else{ + status = PAL_STATUS_EINVAL; + printk(KERN_WARNING"Invalid parameters " + "for PAL call:0x%lx!\n", in0); + } + + return (struct ia64_pal_retval){status, 0, 0, 0}; +} + +static struct ia64_pal_retval pal_mem_attrib(struct kvm_vcpu *vcpu) +{ + unsigned long r9; + long status; + + status = ia64_pal_mem_attrib(&r9); + + return (struct ia64_pal_retval){status, r9, 0, 0}; +} + +static void remote_pal_prefetch_visibility(void *v) +{ + s64 trans_type = (s64)v; + ia64_pal_prefetch_visibility(trans_type); +} + +static struct ia64_pal_retval pal_prefetch_visibility(struct kvm_vcpu *vcpu) +{ + struct ia64_pal_retval result = {0, 0, 0, 0}; + unsigned long in0, in1, in2, in3; + kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3); + result.status = ia64_pal_prefetch_visibility(in1); + if (result.status == 0) { + /* Must be performed on all remote processors + in the coherence domain. */ + smp_call_function(remote_pal_prefetch_visibility, + (void *)in1, 1); + /* Unnecessary on remote processor for other vcpus!*/ + result.status = 1; + } + return result; +} + +static void remote_pal_mc_drain(void *v) +{ + ia64_pal_mc_drain(); +} + +static struct ia64_pal_retval pal_get_brand_info(struct kvm_vcpu *vcpu) +{ + struct ia64_pal_retval result = {0, 0, 0, 0}; + unsigned long in0, in1, in2, in3; + + kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3); + + if (in1 == 0 && in2) { + char brand_info[128]; + result.status = ia64_pal_get_brand_info(brand_info); + if (result.status == PAL_STATUS_SUCCESS) + memcpy((void *)in2, brand_info, 128); + } else { + result.status = PAL_STATUS_REQUIRES_MEMORY; + printk(KERN_WARNING"Invalid parameters for " + "PAL call:0x%lx!\n", in0); + } + + return result; +} + int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run) { @@ -300,14 +418,22 @@ int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run) int ret = 1; gr28 = kvm_get_pal_call_index(vcpu); - /*printk("pal_call index:%lx\n",gr28);*/ switch (gr28) { case PAL_CACHE_FLUSH: result = pal_cache_flush(vcpu); break; + case PAL_MEM_ATTRIB: + result = pal_mem_attrib(vcpu); + break; case PAL_CACHE_SUMMARY: result = pal_cache_summary(vcpu); break; + case PAL_PERF_MON_INFO: + result = pal_perf_mon_info(vcpu); + break; + case PAL_HALT_INFO: + result = pal_halt_info(vcpu); + break; case PAL_HALT_LIGHT: { INIT_PAL_STATUS_SUCCESS(result); @@ -317,6 +443,16 @@ int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run) } break; + case PAL_PREFETCH_VISIBILITY: + result = pal_prefetch_visibility(vcpu); + break; + case PAL_MC_DRAIN: + result.status = ia64_pal_mc_drain(); + /* FIXME: All vcpus likely call PAL_MC_DRAIN. + That causes the congestion. */ + smp_call_function(remote_pal_mc_drain, NULL, 1); + break; + case PAL_FREQ_RATIOS: result = pal_freq_ratios(vcpu); break; @@ -346,6 +482,9 @@ int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run) INIT_PAL_STATUS_SUCCESS(result); result.v1 = (1L << 32) | 1L; break; + case PAL_REGISTER_INFO: + result = pal_register_info(vcpu); + break; case PAL_VM_PAGE_SIZE: result.status = ia64_pal_vm_page_size(&result.v0, &result.v1); @@ -365,12 +504,18 @@ int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run) result.status = ia64_pal_version( (pal_version_u_t *)&result.v0, (pal_version_u_t *)&result.v1); - break; case PAL_FIXED_ADDR: result.status = PAL_STATUS_SUCCESS; result.v0 = vcpu->vcpu_id; break; + case PAL_BRAND_INFO: + result = pal_get_brand_info(vcpu); + break; + case PAL_GET_PSTATE: + case PAL_CACHE_SHARED_INFO: + INIT_PAL_STATUS_UNIMPLEMENTED(result); + break; default: INIT_PAL_STATUS_UNIMPLEMENTED(result); printk(KERN_WARNING"kvm: Unsupported pal call," diff --git a/arch/ia64/kvm/process.c b/arch/ia64/kvm/process.c index 0e727ce0d55..b1dc80952d9 100644 --- a/arch/ia64/kvm/process.c +++ b/arch/ia64/kvm/process.c @@ -607,7 +607,7 @@ static void set_pal_call_data(struct kvm_vcpu *vcpu) p->exit_reason = EXIT_REASON_PAL_CALL; } -static void set_pal_call_result(struct kvm_vcpu *vcpu) +static void get_pal_call_result(struct kvm_vcpu *vcpu) { struct exit_ctl_data *p = &vcpu->arch.exit_data; @@ -635,7 +635,7 @@ static void set_sal_call_data(struct kvm_vcpu *vcpu) p->exit_reason = EXIT_REASON_SAL_CALL; } -static void set_sal_call_result(struct kvm_vcpu *vcpu) +static void get_sal_call_result(struct kvm_vcpu *vcpu) { struct exit_ctl_data *p = &vcpu->arch.exit_data; @@ -658,13 +658,13 @@ void kvm_ia64_handle_break(unsigned long ifa, struct kvm_pt_regs *regs, if (iim == DOMN_PAL_REQUEST) { set_pal_call_data(v); vmm_transition(v); - set_pal_call_result(v); + get_pal_call_result(v); vcpu_increment_iip(v); return; } else if (iim == DOMN_SAL_REQUEST) { set_sal_call_data(v); vmm_transition(v); - set_sal_call_result(v); + get_sal_call_result(v); vcpu_increment_iip(v); return; } -- GitLab From 2c411b48af3e3c534b9cfb6a79be1df384d1ca1a Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Thu, 22 Jan 2009 14:20:27 +0100 Subject: [PATCH 4101/4982] KVM: s390: Fix printk on SIGP set arch KVM on s390 does not support the ESA/390 architecture. We refuse to change the architecture mode and print a warning. This patch removes the printk for several reasons: o A malicious guest can flood host dmesg o The old message had no newline o there is no connection between the message and the failing guest This patch simply removes the printk. We already set the condition code to 3 - the guest knows that something went wrong. Reported-by: Heiko Carstens Signed-off-by: Christian Borntraeger Signed-off-by: Avi Kivity --- arch/s390/kvm/sigp.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index 2a01b9e0280..f27dbedf086 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c @@ -153,8 +153,6 @@ static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter) switch (parameter & 0xff) { case 0: - printk(KERN_WARNING "kvm: request to switch to ESA/390 mode" - " not supported"); rc = 3; /* not operational */ break; case 1: -- GitLab From 70455a36a073cbb83ca17f92d135a6128c73cb3c Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Thu, 22 Jan 2009 10:28:29 +0100 Subject: [PATCH 4102/4982] KVM: s390: Fix problem state check for b2 intercepts The kernel handles some priviledged instruction exits. While I was unable to trigger such an exit from guest userspace, the code should check for supervisor state before emulating a priviledged instruction. I also renamed kvm_s390_handle_priv to kvm_s390_handle_b2. After all there are non priviledged b2 instructions like stck (store clock). Signed-off-by: Christian Borntraeger Signed-off-by: Avi Kivity --- arch/s390/kvm/intercept.c | 2 +- arch/s390/kvm/kvm-s390.h | 2 +- arch/s390/kvm/priv.c | 18 +++++++++++++++--- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index 61236102203..9d19803111b 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c @@ -103,7 +103,7 @@ static int handle_lctl(struct kvm_vcpu *vcpu) static intercept_handler_t instruction_handlers[256] = { [0x83] = kvm_s390_handle_diag, [0xae] = kvm_s390_handle_sigp, - [0xb2] = kvm_s390_handle_priv, + [0xb2] = kvm_s390_handle_b2, [0xb7] = handle_lctl, [0xeb] = handle_lctlg, }; diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h index 3893cf12eac..00bbe69b78d 100644 --- a/arch/s390/kvm/kvm-s390.h +++ b/arch/s390/kvm/kvm-s390.h @@ -50,7 +50,7 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code); /* implemented in priv.c */ -int kvm_s390_handle_priv(struct kvm_vcpu *vcpu); +int kvm_s390_handle_b2(struct kvm_vcpu *vcpu); /* implemented in sigp.c */ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu); diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 3605df45dd4..4b88834b8dd 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c @@ -304,12 +304,24 @@ static intercept_handler_t priv_handlers[256] = { [0xb1] = handle_stfl, }; -int kvm_s390_handle_priv(struct kvm_vcpu *vcpu) +int kvm_s390_handle_b2(struct kvm_vcpu *vcpu) { intercept_handler_t handler; + /* + * a lot of B2 instructions are priviledged. We first check for + * the priviledges ones, that we can handle in the kernel. If the + * kernel can handle this instruction, we check for the problem + * state bit and (a) handle the instruction or (b) send a code 2 + * program check. + * Anything else goes to userspace.*/ handler = priv_handlers[vcpu->arch.sie_block->ipa & 0x00ff]; - if (handler) - return handler(vcpu); + if (handler) { + if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) + return kvm_s390_inject_program_int(vcpu, + PGM_PRIVILEGED_OPERATION); + else + return handler(vcpu); + } return -ENOTSUPP; } -- GitLab From b7e6e4d3602c738b8f61225d9f4514945df52f07 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Thu, 22 Jan 2009 10:29:08 +0100 Subject: [PATCH 4103/4982] KVM: s390: Fix SIGP set prefix ioctl This patch fixes the SET PREFIX interrupt if triggered by userspace. Until now, it was not necessary, but life migration will need it. In addition, it helped me creating SMP support for my kvm_crashme tool (lets kvm execute random guest memory content). Signed-off-by: Christian Borntraeger Signed-off-by: Avi Kivity --- arch/s390/kvm/interrupt.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index f4fe28a2521..0189356fe20 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c @@ -555,9 +555,14 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, VCPU_EVENT(vcpu, 3, "inject: program check %d (from user)", s390int->parm); break; + case KVM_S390_SIGP_SET_PREFIX: + inti->prefix.address = s390int->parm; + inti->type = s390int->type; + VCPU_EVENT(vcpu, 3, "inject: set prefix to %x (from user)", + s390int->parm); + break; case KVM_S390_SIGP_STOP: case KVM_S390_RESTART: - case KVM_S390_SIGP_SET_PREFIX: case KVM_S390_INT_EMERGENCY: VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type); inti->type = s390int->type; -- GitLab From 934d534f8a5a39e20d5682b3a3a45ff351706b59 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Wed, 21 Jan 2009 15:16:43 +0100 Subject: [PATCH 4104/4982] KVM: ia64: dynamic nr online cpus Account for number of online cpus and use that in loops iterating over the list of vpus instead of scanning the full array unconditionally. This patch is a building block to facilitate allowing to bump up the size of MAX_VCPUS significantly. Signed-off-by: Jes Sorensen Acked-by : Xiantao Zhang Signed-off-by: Avi Kivity --- arch/ia64/include/asm/kvm_host.h | 10 ++++++---- arch/ia64/kvm/kvm-ia64.c | 12 ++++++++---- arch/ia64/kvm/vcpu.c | 5 ++++- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/arch/ia64/include/asm/kvm_host.h b/arch/ia64/include/asm/kvm_host.h index 46f8b0eb568..4542651e6ac 100644 --- a/arch/ia64/include/asm/kvm_host.h +++ b/arch/ia64/include/asm/kvm_host.h @@ -157,10 +157,10 @@ struct kvm_vm_data { struct kvm_vcpu_data vcpu_data[KVM_MAX_VCPUS]; }; -#define VCPU_BASE(n) KVM_VM_DATA_BASE + \ - offsetof(struct kvm_vm_data, vcpu_data[n]) -#define VM_BASE KVM_VM_DATA_BASE + \ - offsetof(struct kvm_vm_data, kvm_vm_struct) +#define VCPU_BASE(n) (KVM_VM_DATA_BASE + \ + offsetof(struct kvm_vm_data, vcpu_data[n])) +#define KVM_VM_BASE (KVM_VM_DATA_BASE + \ + offsetof(struct kvm_vm_data, kvm_vm_struct)) #define KVM_MEM_DIRTY_LOG_BASE KVM_VM_DATA_BASE + \ offsetof(struct kvm_vm_data, kvm_mem_dirty_log) @@ -464,6 +464,8 @@ struct kvm_arch { unsigned long metaphysical_rr4; unsigned long vmm_init_rr; + int online_vcpus; + struct kvm_ioapic *vioapic; struct kvm_vm_stat stat; struct kvm_sal_data rdv_sal_data; diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index dbf527a5734..9c77e3939e9 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c @@ -314,7 +314,7 @@ static struct kvm_vcpu *lid_to_vcpu(struct kvm *kvm, unsigned long id, union ia64_lid lid; int i; - for (i = 0; i < KVM_MAX_VCPUS; i++) { + for (i = 0; i < kvm->arch.online_vcpus; i++) { if (kvm->vcpus[i]) { lid.val = VCPU_LID(kvm->vcpus[i]); if (lid.id == id && lid.eid == eid) @@ -388,7 +388,7 @@ static int handle_global_purge(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) call_data.ptc_g_data = p->u.ptc_g_data; - for (i = 0; i < KVM_MAX_VCPUS; i++) { + for (i = 0; i < kvm->arch.online_vcpus; i++) { if (!kvm->vcpus[i] || kvm->vcpus[i]->arch.mp_state == KVM_MP_STATE_UNINITIALIZED || vcpu == kvm->vcpus[i]) @@ -788,6 +788,8 @@ struct kvm *kvm_arch_create_vm(void) return ERR_PTR(-ENOMEM); kvm_init_vm(kvm); + kvm->arch.online_vcpus = 0; + return kvm; } @@ -1154,7 +1156,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) /*Initialize itc offset for vcpus*/ itc_offset = 0UL - ia64_getreg(_IA64_REG_AR_ITC); - for (i = 0; i < KVM_MAX_VCPUS; i++) { + for (i = 0; i < kvm->arch.online_vcpus; i++) { v = (struct kvm_vcpu *)((char *)vcpu + sizeof(struct kvm_vcpu_data) * i); v->arch.itc_offset = itc_offset; @@ -1288,6 +1290,8 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, goto fail; } + kvm->arch.online_vcpus++; + return vcpu; fail: return ERR_PTR(r); @@ -1828,7 +1832,7 @@ struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector, struct kvm_vcpu *lvcpu = kvm->vcpus[0]; int i; - for (i = 1; i < KVM_MAX_VCPUS; i++) { + for (i = 1; i < kvm->arch.online_vcpus; i++) { if (!kvm->vcpus[i]) continue; if (lvcpu->arch.xtp > kvm->vcpus[i]->arch.xtp) diff --git a/arch/ia64/kvm/vcpu.c b/arch/ia64/kvm/vcpu.c index 4d8be4c252f..d4d28050587 100644 --- a/arch/ia64/kvm/vcpu.c +++ b/arch/ia64/kvm/vcpu.c @@ -807,12 +807,15 @@ static inline void vcpu_set_itm(struct kvm_vcpu *vcpu, u64 val); static void vcpu_set_itc(struct kvm_vcpu *vcpu, u64 val) { struct kvm_vcpu *v; + struct kvm *kvm; int i; long itc_offset = val - ia64_getreg(_IA64_REG_AR_ITC); unsigned long vitv = VCPU(vcpu, itv); + kvm = (struct kvm *)KVM_VM_BASE; + if (vcpu->vcpu_id == 0) { - for (i = 0; i < KVM_MAX_VCPUS; i++) { + for (i = 0; i < kvm->arch.online_vcpus; i++) { v = (struct kvm_vcpu *)((char *)vcpu + sizeof(struct kvm_vcpu_data) * i); VMX(v, itc_offset) = itc_offset; -- GitLab From 44882eed2ebe7f75f8cdae5671ab1d6e0fa40dbc Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Tue, 27 Jan 2009 15:12:38 -0200 Subject: [PATCH 4105/4982] KVM: make irq ack notifications aware of routing table IRQ ack notifications assume an identity mapping between pin->gsi, which might not be the case with, for example, HPET. Translate before acking. Signed-off-by: Marcelo Tosatti Acked-by: Gleb Natapov --- arch/x86/kvm/i8259.c | 5 +++-- arch/x86/kvm/irq.h | 2 ++ include/linux/kvm_host.h | 2 +- virt/kvm/ioapic.c | 10 +++++----- virt/kvm/irq_comm.c | 13 ++++++++++--- 5 files changed, 21 insertions(+), 11 deletions(-) diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c index 179dcb0103f..93160375c84 100644 --- a/arch/x86/kvm/i8259.c +++ b/arch/x86/kvm/i8259.c @@ -49,7 +49,8 @@ static void pic_unlock(struct kvm_pic *s) spin_unlock(&s->lock); while (acks) { - kvm_notify_acked_irq(kvm, __ffs(acks)); + kvm_notify_acked_irq(kvm, SELECT_PIC(__ffs(acks)), + __ffs(acks)); acks &= acks - 1; } @@ -232,7 +233,7 @@ int kvm_pic_read_irq(struct kvm *kvm) } pic_update_irq(s); pic_unlock(s); - kvm_notify_acked_irq(kvm, irq); + kvm_notify_acked_irq(kvm, SELECT_PIC(irq), irq); return intno; } diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h index 82579ee538d..9f593188129 100644 --- a/arch/x86/kvm/irq.h +++ b/arch/x86/kvm/irq.h @@ -32,6 +32,8 @@ #include "lapic.h" #define PIC_NUM_PINS 16 +#define SELECT_PIC(irq) \ + ((irq) < 8 ? KVM_IRQCHIP_PIC_MASTER : KVM_IRQCHIP_PIC_SLAVE) struct kvm; struct kvm_vcpu; diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index ce285e01bd5..c03a0a9a858 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -352,7 +352,7 @@ void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq, void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, bool mask); void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level); -void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi); +void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin); void kvm_register_irq_ack_notifier(struct kvm *kvm, struct kvm_irq_ack_notifier *kian); void kvm_unregister_irq_ack_notifier(struct kvm_irq_ack_notifier *kian); diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index e85a2bcd2db..1c986ac59ad 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c @@ -293,20 +293,20 @@ void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level) } } -static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int gsi, +static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int pin, int trigger_mode) { union ioapic_redir_entry *ent; - ent = &ioapic->redirtbl[gsi]; + ent = &ioapic->redirtbl[pin]; - kvm_notify_acked_irq(ioapic->kvm, gsi); + kvm_notify_acked_irq(ioapic->kvm, KVM_IRQCHIP_IOAPIC, pin); if (trigger_mode == IOAPIC_LEVEL_TRIG) { ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG); ent->fields.remote_irr = 0; - if (!ent->fields.mask && (ioapic->irr & (1 << gsi))) - ioapic_service(ioapic, gsi); + if (!ent->fields.mask && (ioapic->irr & (1 << pin))) + ioapic_service(ioapic, pin); } } diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index a797fa5e642..7aa5086c862 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c @@ -59,10 +59,19 @@ void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level) e->set(e, kvm, !!(*irq_state)); } -void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi) +void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin) { + struct kvm_kernel_irq_routing_entry *e; struct kvm_irq_ack_notifier *kian; struct hlist_node *n; + unsigned gsi = pin; + + list_for_each_entry(e, &kvm->irq_routing, link) + if (e->irqchip.irqchip == irqchip && + e->irqchip.pin == pin) { + gsi = e->gsi; + break; + } hlist_for_each_entry(kian, n, &kvm->arch.irq_ack_notifier_list, link) if (kian->gsi == gsi) @@ -237,8 +246,6 @@ out: #define ROUTING_ENTRY1(irq) IOAPIC_ROUTING_ENTRY(irq) #ifdef CONFIG_X86 -#define SELECT_PIC(irq) \ - ((irq) < 8 ? KVM_IRQCHIP_PIC_MASTER : KVM_IRQCHIP_PIC_SLAVE) # define PIC_ROUTING_ENTRY(irq) \ { .gsi = irq, .type = KVM_IRQ_ROUTING_IRQCHIP, \ .u.irqchip.irqchip = SELECT_PIC(irq), .u.irqchip.pin = (irq) % 8 } -- GitLab From d20626936dd6aa783760e780dae5abb127564316 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 2 Feb 2009 16:23:50 +0100 Subject: [PATCH 4106/4982] x86: Add EFER descriptions for FFXSR AMD k10 includes support for the FFXSR feature, which leaves out XMM registers on FXSAVE/FXSAVE when the EFER_FFXSR bit is set in EFER. The CPUID feature bit exists already, but the EFER bit is missing currently, so this patch adds it to the list of known EFER bits. Signed-off-by: Alexander Graf CC: Joerg Roedel Signed-off-by: Avi Kivity --- arch/x86/include/asm/msr-index.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 46e9646e7a6..f4e505f286b 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -19,12 +19,14 @@ #define _EFER_LMA 10 /* Long mode active (read-only) */ #define _EFER_NX 11 /* No execute enable */ #define _EFER_SVME 12 /* Enable virtualization */ +#define _EFER_FFXSR 14 /* Enable Fast FXSAVE/FXRSTOR */ #define EFER_SCE (1<<_EFER_SCE) #define EFER_LME (1<<_EFER_LME) #define EFER_LMA (1<<_EFER_LMA) #define EFER_NX (1<<_EFER_NX) #define EFER_SVME (1<<_EFER_SVME) +#define EFER_FFXSR (1<<_EFER_FFXSR) /* Intel MSRs. Some also available on other CPUs */ #define MSR_IA32_PERFCTR0 0x000000c1 -- GitLab From 1b2fd70c4eddef53f32639296818c0253e7ca48d Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 2 Feb 2009 16:23:51 +0100 Subject: [PATCH 4107/4982] KVM: Add FFXSR support AMD K10 CPUs implement the FFXSR feature that gets enabled using EFER. Let's check if the virtual CPU description includes that CPUID feature bit and allow enabling it then. This is required for Windows Server 2008 in Hyper-V mode. v2 adds CPUID capability exposure Signed-off-by: Alexander Graf Signed-off-by: Avi Kivity --- arch/x86/kvm/svm.c | 3 +++ arch/x86/kvm/x86.c | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index db5021b2b5a..1c4a018bf4b 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -417,6 +417,9 @@ static __init int svm_hardware_setup(void) if (boot_cpu_has(X86_FEATURE_NX)) kvm_enable_efer_bits(EFER_NX); + if (boot_cpu_has(X86_FEATURE_FXSR_OPT)) + kvm_enable_efer_bits(EFER_FFXSR); + if (nested) { printk(KERN_INFO "kvm: Nested Virtualization enabled\n"); kvm_enable_efer_bits(EFER_SVME); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 32e3a7ec6ad..8f83590b47d 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -490,6 +490,17 @@ static void set_efer(struct kvm_vcpu *vcpu, u64 efer) return; } + if (efer & EFER_FFXSR) { + struct kvm_cpuid_entry2 *feat; + + feat = kvm_find_cpuid_entry(vcpu, 0x80000001, 0); + if (!feat || !(feat->edx & bit(X86_FEATURE_FXSR_OPT))) { + printk(KERN_DEBUG "set_efer: #GP, enable FFXSR w/o CPUID capability\n"); + kvm_inject_gp(vcpu, 0); + return; + } + } + if (efer & EFER_SVME) { struct kvm_cpuid_entry2 *feat; @@ -1240,6 +1251,7 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, #ifdef CONFIG_X86_64 bit(X86_FEATURE_LM) | #endif + bit(X86_FEATURE_FXSR_OPT) | bit(X86_FEATURE_MMXEXT) | bit(X86_FEATURE_3DNOWEXT) | bit(X86_FEATURE_3DNOW); -- GitLab From 34c33d163fe509da8414a736c6328855f8c164e5 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Sun, 8 Feb 2009 13:28:15 +0100 Subject: [PATCH 4108/4982] KVM: Drop unused evaluations from string pio handlers Looks like neither the direction nor the rep prefix are used anymore. Drop related evaluations from SVM's and VMX's I/O exit handlers. Signed-off-by: Jan Kiszka Signed-off-by: Avi Kivity --- arch/x86/kvm/svm.c | 4 +--- arch/x86/kvm/vmx.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 1c4a018bf4b..22e88a4a51c 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -1194,7 +1194,7 @@ static int shutdown_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) static int io_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) { u32 io_info = svm->vmcb->control.exit_info_1; /* address size bug? */ - int size, down, in, string, rep; + int size, in, string; unsigned port; ++svm->vcpu.stat.io_exits; @@ -1213,8 +1213,6 @@ static int io_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) in = (io_info & SVM_IOIO_TYPE_MASK) != 0; port = io_info >> 16; size = (io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT; - rep = (io_info & SVM_IOIO_REP_MASK) != 0; - down = (svm->vmcb->save.rflags & X86_EFLAGS_DF) != 0; skip_emulated_instruction(&svm->vcpu); return kvm_emulate_pio(&svm->vcpu, kvm_run, in, size, port); diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index df454de8acf..509b3530540 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -2698,7 +2698,7 @@ static int handle_triple_fault(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) { unsigned long exit_qualification; - int size, down, in, string, rep; + int size, in, string; unsigned port; ++vcpu->stat.io_exits; @@ -2714,8 +2714,6 @@ static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) size = (exit_qualification & 7) + 1; in = (exit_qualification & 8) != 0; - down = (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_DF) != 0; - rep = (exit_qualification & 32) != 0; port = exit_qualification >> 16; skip_emulated_instruction(vcpu); -- GitLab From 79950e1073150909619b7c0f9a39a2fea83a42d8 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Tue, 10 Feb 2009 13:57:06 +0800 Subject: [PATCH 4109/4982] KVM: Use irq routing API for MSI Merge MSI userspace interface with IRQ routing table. Notice the API have been changed, and using IRQ routing table would be the only interface kvm-userspace supported. Signed-off-by: Sheng Yang Signed-off-by: Avi Kivity --- include/linux/kvm.h | 9 +++++ include/linux/kvm_host.h | 2 +- virt/kvm/irq_comm.c | 78 ++++++++++++++++++++++++++++++++++++---- virt/kvm/kvm_main.c | 70 +++--------------------------------- 4 files changed, 86 insertions(+), 73 deletions(-) diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 869462ca762..2163b3dd36e 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h @@ -410,8 +410,16 @@ struct kvm_irq_routing_irqchip { __u32 pin; }; +struct kvm_irq_routing_msi { + __u32 address_lo; + __u32 address_hi; + __u32 data; + __u32 pad; +}; + /* gsi routing entry types */ #define KVM_IRQ_ROUTING_IRQCHIP 1 +#define KVM_IRQ_ROUTING_MSI 2 struct kvm_irq_routing_entry { __u32 gsi; @@ -420,6 +428,7 @@ struct kvm_irq_routing_entry { __u32 pad; union { struct kvm_irq_routing_irqchip irqchip; + struct kvm_irq_routing_msi msi; __u32 pad[8]; } u; }; diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index c03a0a9a858..339eda3ca6e 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -116,6 +116,7 @@ struct kvm_kernel_irq_routing_entry { unsigned irqchip; unsigned pin; } irqchip; + struct msi_msg msi; }; struct list_head link; }; @@ -327,7 +328,6 @@ struct kvm_assigned_dev_kernel { int host_irq; bool host_irq_disabled; int guest_irq; - struct msi_msg guest_msi; #define KVM_ASSIGNED_DEV_GUEST_INTX (1 << 0) #define KVM_ASSIGNED_DEV_GUEST_MSI (1 << 1) #define KVM_ASSIGNED_DEV_HOST_INTX (1 << 8) diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index 7aa5086c862..6bc7439eff6 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c @@ -20,6 +20,11 @@ */ #include + +#ifdef CONFIG_X86 +#include +#endif + #include "irq.h" #include "ioapic.h" @@ -38,17 +43,70 @@ static void kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e, kvm_ioapic_set_irq(kvm->arch.vioapic, e->irqchip.pin, level); } +static void kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, + struct kvm *kvm, int level) +{ + int vcpu_id; + struct kvm_vcpu *vcpu; + struct kvm_ioapic *ioapic = ioapic_irqchip(kvm); + int dest_id = (e->msi.address_lo & MSI_ADDR_DEST_ID_MASK) + >> MSI_ADDR_DEST_ID_SHIFT; + int vector = (e->msi.data & MSI_DATA_VECTOR_MASK) + >> MSI_DATA_VECTOR_SHIFT; + int dest_mode = test_bit(MSI_ADDR_DEST_MODE_SHIFT, + (unsigned long *)&e->msi.address_lo); + int trig_mode = test_bit(MSI_DATA_TRIGGER_SHIFT, + (unsigned long *)&e->msi.data); + int delivery_mode = test_bit(MSI_DATA_DELIVERY_MODE_SHIFT, + (unsigned long *)&e->msi.data); + u32 deliver_bitmask; + + BUG_ON(!ioapic); + + deliver_bitmask = kvm_ioapic_get_delivery_bitmask(ioapic, + dest_id, dest_mode); + /* IOAPIC delivery mode value is the same as MSI here */ + switch (delivery_mode) { + case IOAPIC_LOWEST_PRIORITY: + vcpu = kvm_get_lowest_prio_vcpu(ioapic->kvm, vector, + deliver_bitmask); + if (vcpu != NULL) + kvm_apic_set_irq(vcpu, vector, trig_mode); + else + printk(KERN_INFO "kvm: null lowest priority vcpu!\n"); + break; + case IOAPIC_FIXED: + for (vcpu_id = 0; deliver_bitmask != 0; vcpu_id++) { + if (!(deliver_bitmask & (1 << vcpu_id))) + continue; + deliver_bitmask &= ~(1 << vcpu_id); + vcpu = ioapic->kvm->vcpus[vcpu_id]; + if (vcpu) + kvm_apic_set_irq(vcpu, vector, trig_mode); + } + break; + default: + break; + } +} + /* This should be called with the kvm->lock mutex held */ void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level) { struct kvm_kernel_irq_routing_entry *e; - unsigned long *irq_state = (unsigned long *)&kvm->arch.irq_states[irq]; + unsigned long *irq_state, sig_level; + + if (irq < KVM_IOAPIC_NUM_PINS) { + irq_state = (unsigned long *)&kvm->arch.irq_states[irq]; - /* Logical OR for level trig interrupt */ - if (level) - set_bit(irq_source_id, irq_state); - else - clear_bit(irq_source_id, irq_state); + /* Logical OR for level trig interrupt */ + if (level) + set_bit(irq_source_id, irq_state); + else + clear_bit(irq_source_id, irq_state); + sig_level = !!(*irq_state); + } else /* Deal with MSI/MSI-X */ + sig_level = 1; /* Not possible to detect if the guest uses the PIC or the * IOAPIC. So set the bit in both. The guest will ignore @@ -56,7 +114,7 @@ void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level) */ list_for_each_entry(e, &kvm->irq_routing, link) if (e->gsi == irq) - e->set(e, kvm, !!(*irq_state)); + e->set(e, kvm, sig_level); } void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin) @@ -186,6 +244,12 @@ int setup_routing_entry(struct kvm_kernel_irq_routing_entry *e, e->irqchip.irqchip = ue->u.irqchip.irqchip; e->irqchip.pin = ue->u.irqchip.pin + delta; break; + case KVM_IRQ_ROUTING_MSI: + e->set = kvm_set_msi; + e->msi.address_lo = ue->u.msi.address_lo; + e->msi.address_hi = ue->u.msi.address_hi; + e->msi.data = ue->u.msi.data; + break; default: goto out; } diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index c65484b471c..266bdaf0ce4 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -47,10 +47,6 @@ #include #include -#ifdef CONFIG_X86 -#include -#endif - #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET #include "coalesced_mmio.h" #endif @@ -85,57 +81,6 @@ static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl, static bool kvm_rebooting; #ifdef KVM_CAP_DEVICE_ASSIGNMENT - -#ifdef CONFIG_X86 -static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev) -{ - int vcpu_id; - struct kvm_vcpu *vcpu; - struct kvm_ioapic *ioapic = ioapic_irqchip(dev->kvm); - int dest_id = (dev->guest_msi.address_lo & MSI_ADDR_DEST_ID_MASK) - >> MSI_ADDR_DEST_ID_SHIFT; - int vector = (dev->guest_msi.data & MSI_DATA_VECTOR_MASK) - >> MSI_DATA_VECTOR_SHIFT; - int dest_mode = test_bit(MSI_ADDR_DEST_MODE_SHIFT, - (unsigned long *)&dev->guest_msi.address_lo); - int trig_mode = test_bit(MSI_DATA_TRIGGER_SHIFT, - (unsigned long *)&dev->guest_msi.data); - int delivery_mode = test_bit(MSI_DATA_DELIVERY_MODE_SHIFT, - (unsigned long *)&dev->guest_msi.data); - u32 deliver_bitmask; - - BUG_ON(!ioapic); - - deliver_bitmask = kvm_ioapic_get_delivery_bitmask(ioapic, - dest_id, dest_mode); - /* IOAPIC delivery mode value is the same as MSI here */ - switch (delivery_mode) { - case IOAPIC_LOWEST_PRIORITY: - vcpu = kvm_get_lowest_prio_vcpu(ioapic->kvm, vector, - deliver_bitmask); - if (vcpu != NULL) - kvm_apic_set_irq(vcpu, vector, trig_mode); - else - printk(KERN_INFO "kvm: null lowest priority vcpu!\n"); - break; - case IOAPIC_FIXED: - for (vcpu_id = 0; deliver_bitmask != 0; vcpu_id++) { - if (!(deliver_bitmask & (1 << vcpu_id))) - continue; - deliver_bitmask &= ~(1 << vcpu_id); - vcpu = ioapic->kvm->vcpus[vcpu_id]; - if (vcpu) - kvm_apic_set_irq(vcpu, vector, trig_mode); - } - break; - default: - printk(KERN_INFO "kvm: unsupported MSI delivery mode\n"); - } -} -#else -static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev) {} -#endif - static struct kvm_assigned_dev_kernel *kvm_find_assigned_dev(struct list_head *head, int assigned_dev_id) { @@ -162,13 +107,10 @@ static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work) * finer-grained lock, update this */ mutex_lock(&assigned_dev->kvm->lock); - if (assigned_dev->irq_requested_type & KVM_ASSIGNED_DEV_GUEST_INTX) - kvm_set_irq(assigned_dev->kvm, - assigned_dev->irq_source_id, - assigned_dev->guest_irq, 1); - else if (assigned_dev->irq_requested_type & - KVM_ASSIGNED_DEV_GUEST_MSI) { - assigned_device_msi_dispatch(assigned_dev); + kvm_set_irq(assigned_dev->kvm, assigned_dev->irq_source_id, + assigned_dev->guest_irq, 1); + + if (assigned_dev->irq_requested_type & KVM_ASSIGNED_DEV_GUEST_MSI) { enable_irq(assigned_dev->host_irq); assigned_dev->host_irq_disabled = false; } @@ -331,17 +273,15 @@ static int assigned_device_update_msi(struct kvm *kvm, { int r; + adev->guest_irq = airq->guest_irq; if (airq->flags & KVM_DEV_IRQ_ASSIGN_ENABLE_MSI) { /* x86 don't care upper address of guest msi message addr */ adev->irq_requested_type |= KVM_ASSIGNED_DEV_GUEST_MSI; adev->irq_requested_type &= ~KVM_ASSIGNED_DEV_GUEST_INTX; - adev->guest_msi.address_lo = airq->guest_msi.addr_lo; - adev->guest_msi.data = airq->guest_msi.data; adev->ack_notifier.gsi = -1; } else if (msi2intx) { adev->irq_requested_type |= KVM_ASSIGNED_DEV_GUEST_INTX; adev->irq_requested_type &= ~KVM_ASSIGNED_DEV_GUEST_MSI; - adev->guest_irq = airq->guest_irq; adev->ack_notifier.gsi = airq->guest_irq; } else { /* -- GitLab From 49cd7d2238e44f7ee4269481cd8a1261cc8f93a5 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Wed, 11 Feb 2009 13:50:40 +0800 Subject: [PATCH 4110/4982] KVM: VMX: Use kvm_mmu_page_fault() handle EPT violation mmio Removed duplicated code. Signed-off-by: Sheng Yang Signed-off-by: Avi Kivity --- arch/x86/kvm/vmx.c | 30 +----------------------------- 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 509b3530540..cb27ffccf46 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -3058,11 +3058,8 @@ static int handle_task_switch(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) static int handle_ept_violation(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) { u64 exit_qualification; - enum emulation_result er; gpa_t gpa; - unsigned long hva; int gla_validity; - int r; exit_qualification = vmcs_read64(EXIT_QUALIFICATION); @@ -3085,32 +3082,7 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) } gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS); - hva = gfn_to_hva(vcpu->kvm, gpa >> PAGE_SHIFT); - if (!kvm_is_error_hva(hva)) { - r = kvm_mmu_page_fault(vcpu, gpa & PAGE_MASK, 0); - if (r < 0) { - printk(KERN_ERR "EPT: Not enough memory!\n"); - return -ENOMEM; - } - return 1; - } else { - /* must be MMIO */ - er = emulate_instruction(vcpu, kvm_run, 0, 0, 0); - - if (er == EMULATE_FAIL) { - printk(KERN_ERR - "EPT: Fail to handle EPT violation vmexit!er is %d\n", - er); - printk(KERN_ERR "EPT: GPA: 0x%lx, GVA: 0x%lx\n", - (long unsigned int)vmcs_read64(GUEST_PHYSICAL_ADDRESS), - (long unsigned int)vmcs_read64(GUEST_LINEAR_ADDRESS)); - printk(KERN_ERR "EPT: Exit qualification is 0x%lx\n", - (long unsigned int)exit_qualification); - return -ENOTSUPP; - } else if (er == EMULATE_DO_MMIO) - return 0; - } - return 1; + return kvm_mmu_page_fault(vcpu, gpa & PAGE_MASK, 0); } static int handle_nmi_window(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) -- GitLab From c807660407a695f390034e402edfe544a1d2e40c Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 4 Feb 2009 17:52:04 +0100 Subject: [PATCH 4111/4982] KVM: Fix kvmclock on !constant_tsc boxes kvmclock currently falls apart on machines without constant tsc. This patch fixes it. Changes: * keep tsc frequency in a per-cpu variable. * handle kvmclock update using a new request flag, thus checking whenever we need an update each time we enter guest context. * use a cpufreq notifier to track frequency changes and force kvmclock updates. * send ipis to kick cpu out of guest context if needed to make sure the guest doesn't see stale values. Signed-off-by: Gerd Hoffmann Signed-off-by: Avi Kivity --- arch/x86/kvm/x86.c | 103 +++++++++++++++++++++++++++++++++++---- include/linux/kvm_host.h | 1 + 2 files changed, 95 insertions(+), 9 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 8f83590b47d..05d7be89b5e 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -617,6 +618,8 @@ static void kvm_set_time_scale(uint32_t tsc_khz, struct pvclock_vcpu_time_info * hv_clock->tsc_to_system_mul); } +static DEFINE_PER_CPU(unsigned long, cpu_tsc_khz); + static void kvm_write_guest_time(struct kvm_vcpu *v) { struct timespec ts; @@ -627,9 +630,9 @@ static void kvm_write_guest_time(struct kvm_vcpu *v) if ((!vcpu->time_page)) return; - if (unlikely(vcpu->hv_clock_tsc_khz != tsc_khz)) { - kvm_set_time_scale(tsc_khz, &vcpu->hv_clock); - vcpu->hv_clock_tsc_khz = tsc_khz; + if (unlikely(vcpu->hv_clock_tsc_khz != __get_cpu_var(cpu_tsc_khz))) { + kvm_set_time_scale(__get_cpu_var(cpu_tsc_khz), &vcpu->hv_clock); + vcpu->hv_clock_tsc_khz = __get_cpu_var(cpu_tsc_khz); } /* Keep irq disabled to prevent changes to the clock */ @@ -660,6 +663,16 @@ static void kvm_write_guest_time(struct kvm_vcpu *v) mark_page_dirty(v->kvm, vcpu->time >> PAGE_SHIFT); } +static int kvm_request_guest_time_update(struct kvm_vcpu *v) +{ + struct kvm_vcpu_arch *vcpu = &v->arch; + + if (!vcpu->time_page) + return 0; + set_bit(KVM_REQ_KVMCLOCK_UPDATE, &v->requests); + return 1; +} + static bool msr_mtrr_valid(unsigned msr) { switch (msr) { @@ -790,7 +803,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) vcpu->arch.time_page = NULL; } - kvm_write_guest_time(vcpu); + kvm_request_guest_time_update(vcpu); break; } default: @@ -1000,6 +1013,7 @@ int kvm_dev_ioctl_check_extension(long ext) case KVM_CAP_MMU_SHADOW_CACHE_CONTROL: case KVM_CAP_SET_TSS_ADDR: case KVM_CAP_EXT_CPUID: + case KVM_CAP_CLOCKSOURCE: case KVM_CAP_PIT: case KVM_CAP_NOP_IO_DELAY: case KVM_CAP_MP_STATE: @@ -1025,9 +1039,6 @@ int kvm_dev_ioctl_check_extension(long ext) case KVM_CAP_IOMMU: r = iommu_found(); break; - case KVM_CAP_CLOCKSOURCE: - r = boot_cpu_has(X86_FEATURE_CONSTANT_TSC); - break; default: r = 0; break; @@ -1098,7 +1109,7 @@ out: void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) { kvm_x86_ops->vcpu_load(vcpu, cpu); - kvm_write_guest_time(vcpu); + kvm_request_guest_time_update(vcpu); } void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) @@ -2642,9 +2653,72 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, } EXPORT_SYMBOL_GPL(kvm_emulate_pio_string); +static void bounce_off(void *info) +{ + /* nothing */ +} + +static unsigned int ref_freq; +static unsigned long tsc_khz_ref; + +static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long val, + void *data) +{ + struct cpufreq_freqs *freq = data; + struct kvm *kvm; + struct kvm_vcpu *vcpu; + int i, send_ipi = 0; + + if (!ref_freq) + ref_freq = freq->old; + + if (val == CPUFREQ_PRECHANGE && freq->old > freq->new) + return 0; + if (val == CPUFREQ_POSTCHANGE && freq->old < freq->new) + return 0; + per_cpu(cpu_tsc_khz, freq->cpu) = cpufreq_scale(tsc_khz_ref, ref_freq, freq->new); + + spin_lock(&kvm_lock); + list_for_each_entry(kvm, &vm_list, vm_list) { + for (i = 0; i < KVM_MAX_VCPUS; ++i) { + vcpu = kvm->vcpus[i]; + if (!vcpu) + continue; + if (vcpu->cpu != freq->cpu) + continue; + if (!kvm_request_guest_time_update(vcpu)) + continue; + if (vcpu->cpu != smp_processor_id()) + send_ipi++; + } + } + spin_unlock(&kvm_lock); + + if (freq->old < freq->new && send_ipi) { + /* + * We upscale the frequency. Must make the guest + * doesn't see old kvmclock values while running with + * the new frequency, otherwise we risk the guest sees + * time go backwards. + * + * In case we update the frequency for another cpu + * (which might be in guest context) send an interrupt + * to kick the cpu out of guest context. Next time + * guest context is entered kvmclock will be updated, + * so the guest will not see stale values. + */ + smp_call_function_single(freq->cpu, bounce_off, NULL, 1); + } + return 0; +} + +static struct notifier_block kvmclock_cpufreq_notifier_block = { + .notifier_call = kvmclock_cpufreq_notifier +}; + int kvm_arch_init(void *opaque) { - int r; + int r, cpu; struct kvm_x86_ops *ops = (struct kvm_x86_ops *)opaque; if (kvm_x86_ops) { @@ -2675,6 +2749,15 @@ int kvm_arch_init(void *opaque) kvm_mmu_set_base_ptes(PT_PRESENT_MASK); kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK, PT_DIRTY_MASK, PT64_NX_MASK, 0, 0); + + for_each_possible_cpu(cpu) + per_cpu(cpu_tsc_khz, cpu) = tsc_khz; + if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) { + tsc_khz_ref = tsc_khz; + cpufreq_register_notifier(&kvmclock_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); + } + return 0; out: @@ -3010,6 +3093,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) if (vcpu->requests) { if (test_and_clear_bit(KVM_REQ_MIGRATE_TIMER, &vcpu->requests)) __kvm_migrate_timers(vcpu); + if (test_and_clear_bit(KVM_REQ_KVMCLOCK_UPDATE, &vcpu->requests)) + kvm_write_guest_time(vcpu); if (test_and_clear_bit(KVM_REQ_MMU_SYNC, &vcpu->requests)) kvm_mmu_sync_roots(vcpu); if (test_and_clear_bit(KVM_REQ_TLB_FLUSH, &vcpu->requests)) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 339eda3ca6e..18b4df8264c 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -37,6 +37,7 @@ #define KVM_REQ_PENDING_TIMER 5 #define KVM_REQ_UNHALT 6 #define KVM_REQ_MMU_SYNC 7 +#define KVM_REQ_KVMCLOCK_UPDATE 8 #define KVM_USERSPACE_IRQ_SOURCE_ID 0 -- GitLab From fc5659c8c6b6c4e02ac354b369017c1bf231f347 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 18 Feb 2009 14:08:58 +0100 Subject: [PATCH 4112/4982] KVM: MMU: handle compound pages in kvm_is_mmio_pfn The function kvm_is_mmio_pfn is called before put_page is called on a page by KVM. This is a problem when when this function is called on some struct page which is part of a compund page. It does not test the reserved flag of the compound page but of the struct page within the compount page. This is a problem when KVM works with hugepages allocated at boot time. These pages have the reserved bit set in all tail pages. Only the flag in the compount head is cleared. KVM would not put such a page which results in a memory leak. Signed-off-by: Joerg Roedel Acked-by: Marcelo Tosatti Signed-off-by: Avi Kivity --- virt/kvm/kvm_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 266bdaf0ce4..0ed662dc72d 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -535,8 +535,10 @@ static inline int valid_vcpu(int n) inline int kvm_is_mmio_pfn(pfn_t pfn) { - if (pfn_valid(pfn)) - return PageReserved(pfn_to_page(pfn)); + if (pfn_valid(pfn)) { + struct page *page = compound_head(pfn_to_page(pfn)); + return PageReserved(page); + } return true; } -- GitLab From 6bed6b9e84bf5e6b468847a50c0751389fdd01d4 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 18 Feb 2009 14:08:59 +0100 Subject: [PATCH 4113/4982] KVM: MMU: remove redundant check in mmu_set_spte The following code flow is unnecessary: if (largepage) was_rmapped = is_large_pte(*shadow_pte); else was_rmapped = 1; The is_large_pte() function will always evaluate to one here because the (largepage && !is_large_pte) case is already handled in the first if-clause. So we can remove this check and set was_rmapped to one always here. Signed-off-by: Joerg Roedel Acked-by: Marcelo Tosatti Signed-off-by: Avi Kivity --- arch/x86/kvm/mmu.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index ef060ec444a..c90b4b2f2ab 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -1791,12 +1791,8 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, pgprintk("hfn old %lx new %lx\n", spte_to_pfn(*shadow_pte), pfn); rmap_remove(vcpu->kvm, shadow_pte); - } else { - if (largepage) - was_rmapped = is_large_pte(*shadow_pte); - else - was_rmapped = 1; - } + } else + was_rmapped = 1; } if (set_spte(vcpu, shadow_pte, pte_access, user_fault, write_fault, dirty, largepage, global, gfn, pfn, speculative, true)) { -- GitLab From 452425dbaa1974e9fc489e64a8de46a47b4c2754 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 18 Feb 2009 14:54:37 +0100 Subject: [PATCH 4114/4982] KVM: MMU: remove assertion in kvm_mmu_alloc_page The assertion no longer makes sense since we don't clear page tables on allocation; instead we clear them during prefetch. Signed-off-by: Joerg Roedel Signed-off-by: Avi Kivity --- arch/x86/kvm/mmu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index c90b4b2f2ab..4a21b0f8491 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -802,7 +802,6 @@ static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu, set_page_private(virt_to_page(sp->spt), (unsigned long)sp); list_add(&sp->link, &vcpu->kvm->arch.active_mmu_pages); INIT_LIST_HEAD(&sp->oos_link); - ASSERT(is_empty_shadow_page(sp->spt)); bitmap_zero(sp->slot_bitmap, KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS); sp->multimapped = 0; sp->parent_pte = parent_pte; -- GitLab From 4925663a079c77d95d8685228ad6675fc5639c8e Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Wed, 4 Feb 2009 17:28:14 +0200 Subject: [PATCH 4115/4982] KVM: Report IRQ injection status to userspace. IRQ injection status is either -1 (if there was no CPU found that should except the interrupt because IRQ was masked or ioapic was misconfigured or ...) or >= 0 in that case the number indicates to how many CPUs interrupt was injected. If the value is 0 it means that the interrupt was coalesced and probably should be reinjected. Signed-off-by: Gleb Natapov Signed-off-by: Avi Kivity --- arch/ia64/kvm/kvm-ia64.c | 12 ++++++++-- arch/x86/include/asm/kvm_host.h | 2 +- arch/x86/kvm/i8259.c | 18 +++++++++++---- arch/x86/kvm/x86.c | 13 +++++++++-- include/linux/kvm.h | 7 +++++- include/linux/kvm_host.h | 4 ++-- virt/kvm/ioapic.c | 23 ++++++++++++------ virt/kvm/ioapic.h | 2 +- virt/kvm/irq_comm.c | 41 ++++++++++++++++++++++----------- 9 files changed, 88 insertions(+), 34 deletions(-) diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index 9c77e3939e9..076b00d1dbf 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c @@ -182,7 +182,7 @@ int kvm_dev_ioctl_check_extension(long ext) switch (ext) { case KVM_CAP_IRQCHIP: case KVM_CAP_MP_STATE: - + case KVM_CAP_IRQ_INJECT_STATUS: r = 1; break; case KVM_CAP_COALESCED_MMIO: @@ -927,6 +927,7 @@ long kvm_arch_vm_ioctl(struct file *filp, goto out; } break; + case KVM_IRQ_LINE_STATUS: case KVM_IRQ_LINE: { struct kvm_irq_level irq_event; @@ -934,10 +935,17 @@ long kvm_arch_vm_ioctl(struct file *filp, if (copy_from_user(&irq_event, argp, sizeof irq_event)) goto out; if (irqchip_in_kernel(kvm)) { + __s32 status; mutex_lock(&kvm->lock); - kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, + status = kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, irq_event.irq, irq_event.level); mutex_unlock(&kvm->lock); + if (ioctl == KVM_IRQ_LINE_STATUS) { + irq_event.status = status; + if (copy_to_user(argp, &irq_event, + sizeof irq_event)) + goto out; + } r = 0; } break; diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 55fd4c5fd38..f0faf58044f 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -616,7 +616,7 @@ void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code); void kvm_inject_page_fault(struct kvm_vcpu *vcpu, unsigned long cr2, u32 error_code); -void kvm_pic_set_irq(void *opaque, int irq, int level); +int kvm_pic_set_irq(void *opaque, int irq, int level); void kvm_inject_nmi(struct kvm_vcpu *vcpu); diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c index 93160375c84..b4e662e94dd 100644 --- a/arch/x86/kvm/i8259.c +++ b/arch/x86/kvm/i8259.c @@ -77,12 +77,13 @@ void kvm_pic_clear_isr_ack(struct kvm *kvm) /* * set irq level. If an edge is detected, then the IRR is set to 1 */ -static inline void pic_set_irq1(struct kvm_kpic_state *s, int irq, int level) +static inline int pic_set_irq1(struct kvm_kpic_state *s, int irq, int level) { - int mask; + int mask, ret = 1; mask = 1 << irq; if (s->elcr & mask) /* level triggered */ if (level) { + ret = !(s->irr & mask); s->irr |= mask; s->last_irr |= mask; } else { @@ -91,11 +92,15 @@ static inline void pic_set_irq1(struct kvm_kpic_state *s, int irq, int level) } else /* edge triggered */ if (level) { - if ((s->last_irr & mask) == 0) + if ((s->last_irr & mask) == 0) { + ret = !(s->irr & mask); s->irr |= mask; + } s->last_irr |= mask; } else s->last_irr &= ~mask; + + return (s->imr & mask) ? -1 : ret; } /* @@ -172,16 +177,19 @@ void kvm_pic_update_irq(struct kvm_pic *s) pic_unlock(s); } -void kvm_pic_set_irq(void *opaque, int irq, int level) +int kvm_pic_set_irq(void *opaque, int irq, int level) { struct kvm_pic *s = opaque; + int ret = -1; pic_lock(s); if (irq >= 0 && irq < PIC_NUM_PINS) { - pic_set_irq1(&s->pics[irq >> 3], irq & 7, level); + ret = pic_set_irq1(&s->pics[irq >> 3], irq & 7, level); pic_update_irq(s); } pic_unlock(s); + + return ret; } /* diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 05d7be89b5e..e4db5be7c95 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1019,6 +1019,7 @@ int kvm_dev_ioctl_check_extension(long ext) case KVM_CAP_MP_STATE: case KVM_CAP_SYNC_MMU: case KVM_CAP_REINJECT_CONTROL: + case KVM_CAP_IRQ_INJECT_STATUS: r = 1; break; case KVM_CAP_COALESCED_MMIO: @@ -1877,6 +1878,7 @@ long kvm_arch_vm_ioctl(struct file *filp, create_pit_unlock: mutex_unlock(&kvm->lock); break; + case KVM_IRQ_LINE_STATUS: case KVM_IRQ_LINE: { struct kvm_irq_level irq_event; @@ -1884,10 +1886,17 @@ long kvm_arch_vm_ioctl(struct file *filp, if (copy_from_user(&irq_event, argp, sizeof irq_event)) goto out; if (irqchip_in_kernel(kvm)) { + __s32 status; mutex_lock(&kvm->lock); - kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, - irq_event.irq, irq_event.level); + status = kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, + irq_event.irq, irq_event.level); mutex_unlock(&kvm->lock); + if (ioctl == KVM_IRQ_LINE_STATUS) { + irq_event.status = status; + if (copy_to_user(argp, &irq_event, + sizeof irq_event)) + goto out; + } r = 0; } break; diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 2163b3dd36e..dd48225d182 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h @@ -48,7 +48,10 @@ struct kvm_irq_level { * For IA-64 (APIC model) IOAPIC0: irq 0-23; IOAPIC1: irq 24-47.. * For X86 (standard AT mode) PIC0/1: irq 0-15. IOAPIC0: 0-23.. */ - __u32 irq; + union { + __u32 irq; + __s32 status; + }; __u32 level; }; @@ -402,6 +405,7 @@ struct kvm_trace_rec { #ifdef __KVM_HAVE_IOAPIC #define KVM_CAP_IRQ_ROUTING 25 #endif +#define KVM_CAP_IRQ_INJECT_STATUS 26 #ifdef KVM_CAP_IRQ_ROUTING @@ -465,6 +469,7 @@ struct kvm_irq_routing { #define KVM_CREATE_PIT _IO(KVMIO, 0x64) #define KVM_GET_PIT _IOWR(KVMIO, 0x65, struct kvm_pit_state) #define KVM_SET_PIT _IOR(KVMIO, 0x66, struct kvm_pit_state) +#define KVM_IRQ_LINE_STATUS _IOWR(KVMIO, 0x67, struct kvm_irq_level) #define KVM_REGISTER_COALESCED_MMIO \ _IOW(KVMIO, 0x67, struct kvm_coalesced_mmio_zone) #define KVM_UNREGISTER_COALESCED_MMIO \ diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 18b4df8264c..894a56e365e 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -110,7 +110,7 @@ struct kvm_memory_slot { struct kvm_kernel_irq_routing_entry { u32 gsi; - void (*set)(struct kvm_kernel_irq_routing_entry *e, + int (*set)(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm, int level); union { struct { @@ -352,7 +352,7 @@ void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq, struct kvm_irq_mask_notifier *kimn); void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, bool mask); -void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level); +int kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level); void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin); void kvm_register_irq_ack_notifier(struct kvm *kvm, struct kvm_irq_ack_notifier *kian); diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index 1c986ac59ad..c3b99def9cb 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c @@ -83,19 +83,22 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic, return result; } -static void ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx) +static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx) { union ioapic_redir_entry *pent; + int injected = -1; pent = &ioapic->redirtbl[idx]; if (!pent->fields.mask) { - int injected = ioapic_deliver(ioapic, idx); + injected = ioapic_deliver(ioapic, idx); if (injected && pent->fields.trig_mode == IOAPIC_LEVEL_TRIG) pent->fields.remote_irr = 1; } if (!pent->fields.trig_mode) ioapic->irr &= ~(1 << idx); + + return injected; } static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) @@ -207,7 +210,7 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) u8 trig_mode = ioapic->redirtbl[irq].fields.trig_mode; u32 deliver_bitmask; struct kvm_vcpu *vcpu; - int vcpu_id, r = 0; + int vcpu_id, r = -1; ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x " "vector=%x trig_mode=%x\n", @@ -247,7 +250,9 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) deliver_bitmask &= ~(1 << vcpu_id); vcpu = ioapic->kvm->vcpus[vcpu_id]; if (vcpu) { - r = ioapic_inj_irq(ioapic, vcpu, vector, + if (r < 0) + r = 0; + r += ioapic_inj_irq(ioapic, vcpu, vector, trig_mode, delivery_mode); } } @@ -258,8 +263,10 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) continue; deliver_bitmask &= ~(1 << vcpu_id); vcpu = ioapic->kvm->vcpus[vcpu_id]; - if (vcpu) + if (vcpu) { ioapic_inj_nmi(vcpu); + r = 1; + } else ioapic_debug("NMI to vcpu %d failed\n", vcpu->vcpu_id); @@ -273,11 +280,12 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) return r; } -void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level) +int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level) { u32 old_irr = ioapic->irr; u32 mask = 1 << irq; union ioapic_redir_entry entry; + int ret = 1; if (irq >= 0 && irq < IOAPIC_NUM_PINS) { entry = ioapic->redirtbl[irq]; @@ -288,9 +296,10 @@ void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level) ioapic->irr |= mask; if ((!entry.fields.trig_mode && old_irr != ioapic->irr) || !entry.fields.remote_irr) - ioapic_service(ioapic, irq); + ret = ioapic_service(ioapic, irq); } } + return ret; } static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int pin, diff --git a/virt/kvm/ioapic.h b/virt/kvm/ioapic.h index 49c9581d258..a34bd5e6436 100644 --- a/virt/kvm/ioapic.h +++ b/virt/kvm/ioapic.h @@ -83,7 +83,7 @@ struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector, unsigned long bitmap); void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode); int kvm_ioapic_init(struct kvm *kvm); -void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level); +int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level); void kvm_ioapic_reset(struct kvm_ioapic *ioapic); u32 kvm_ioapic_get_delivery_bitmask(struct kvm_ioapic *ioapic, u8 dest, u8 dest_mode); diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index 6bc7439eff6..be8aba79155 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c @@ -29,22 +29,24 @@ #include "ioapic.h" -static void kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e, - struct kvm *kvm, int level) +static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e, + struct kvm *kvm, int level) { #ifdef CONFIG_X86 - kvm_pic_set_irq(pic_irqchip(kvm), e->irqchip.pin, level); + return kvm_pic_set_irq(pic_irqchip(kvm), e->irqchip.pin, level); +#else + return -1; #endif } -static void kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e, - struct kvm *kvm, int level) +static int kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e, + struct kvm *kvm, int level) { - kvm_ioapic_set_irq(kvm->arch.vioapic, e->irqchip.pin, level); + return kvm_ioapic_set_irq(kvm->arch.vioapic, e->irqchip.pin, level); } -static void kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, - struct kvm *kvm, int level) +static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, + struct kvm *kvm, int level) { int vcpu_id; struct kvm_vcpu *vcpu; @@ -88,13 +90,20 @@ static void kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, default: break; } + return 1; } -/* This should be called with the kvm->lock mutex held */ -void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level) +/* This should be called with the kvm->lock mutex held + * Return value: + * < 0 Interrupt was ignored (masked or not delivered for other reasons) + * = 0 Interrupt was coalesced (previous irq is still pending) + * > 0 Number of CPUs interrupt was delivered to + */ +int kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level) { struct kvm_kernel_irq_routing_entry *e; unsigned long *irq_state, sig_level; + int ret = -1; if (irq < KVM_IOAPIC_NUM_PINS) { irq_state = (unsigned long *)&kvm->arch.irq_states[irq]; @@ -113,8 +122,14 @@ void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level) * writes to the unused one. */ list_for_each_entry(e, &kvm->irq_routing, link) - if (e->gsi == irq) - e->set(e, kvm, sig_level); + if (e->gsi == irq) { + int r = e->set(e, kvm, sig_level); + if (r < 0) + continue; + + ret = r + ((ret < 0) ? 0 : ret); + } + return ret; } void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin) @@ -232,7 +247,7 @@ int setup_routing_entry(struct kvm_kernel_irq_routing_entry *e, e->set = kvm_set_pic_irq; break; case KVM_IRQCHIP_PIC_SLAVE: - e->set = kvm_set_pic_irq; + e->set = kvm_set_pic_irq; delta = 8; break; case KVM_IRQCHIP_IOAPIC: -- GitLab From 1fbdc7a58512a6283e10fd27108197679db95ffa Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Sun, 11 Jan 2009 22:39:44 +0100 Subject: [PATCH 4116/4982] KVM: SVM: set accessed bit for VMCB segment selectors In the segment descriptor _cache_ the accessed bit is always set (although it can be cleared in the descriptor itself). Since Intel checks for this condition on a VMENTRY, set this bit in the AMD path to enable cross vendor migration. Cc: stable@kernel.org Signed-off-by: Andre Przywara Acked-By: Amit Shah Signed-off-by: Avi Kivity --- arch/x86/kvm/svm.c | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 22e88a4a51c..1821c207819 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -796,20 +796,37 @@ static void svm_get_segment(struct kvm_vcpu *vcpu, var->db = (s->attrib >> SVM_SELECTOR_DB_SHIFT) & 1; var->g = (s->attrib >> SVM_SELECTOR_G_SHIFT) & 1; - /* - * SVM always stores 0 for the 'G' bit in the CS selector in - * the VMCB on a VMEXIT. This hurts cross-vendor migration: - * Intel's VMENTRY has a check on the 'G' bit. - */ - if (seg == VCPU_SREG_CS) + switch (seg) { + case VCPU_SREG_CS: + /* + * SVM always stores 0 for the 'G' bit in the CS selector in + * the VMCB on a VMEXIT. This hurts cross-vendor migration: + * Intel's VMENTRY has a check on the 'G' bit. + */ var->g = s->limit > 0xfffff; - - /* - * Work around a bug where the busy flag in the tr selector - * isn't exposed - */ - if (seg == VCPU_SREG_TR) + break; + case VCPU_SREG_TR: + /* + * Work around a bug where the busy flag in the tr selector + * isn't exposed + */ var->type |= 0x2; + break; + case VCPU_SREG_DS: + case VCPU_SREG_ES: + case VCPU_SREG_FS: + case VCPU_SREG_GS: + /* + * The accessed bit must always be set in the segment + * descriptor cache, although it can be cleared in the + * descriptor, the cached bit always remains at 1. Since + * Intel has a check on this, set it here to support + * cross-vendor migration. + */ + if (!var->unusable) + var->type |= 0x1; + break; + } var->unusable = !var->present; } -- GitLab From c5bc22424021cabda862727fb3f5098b866f074d Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 19 Feb 2009 12:18:56 +0100 Subject: [PATCH 4117/4982] KVM: MMU: Fix another largepage memory leak In the paging_fetch function rmap_remove is called after setting a large pte to non-present. This causes rmap_remove to not drop the reference to the large page. The result is a memory leak of that page. Cc: stable@kernel.org Signed-off-by: Joerg Roedel Acked-by: Marcelo Tosatti Signed-off-by: Avi Kivity --- arch/x86/kvm/paging_tmpl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index 7314c0944c5..0f11792fafa 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h @@ -306,9 +306,9 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, continue; if (is_large_pte(*sptep)) { + rmap_remove(vcpu->kvm, sptep); set_shadow_pte(sptep, shadow_trap_nonpresent_pte); kvm_flush_remote_tlbs(vcpu->kvm); - rmap_remove(vcpu->kvm, sptep); } if (level == PT_DIRECTORY_LEVEL -- GitLab From 71450f78853b82d55cda4e182c9db6e26b631485 Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Mon, 23 Feb 2009 12:57:11 +0200 Subject: [PATCH 4118/4982] KVM: Report IRQ injection status for MSI delivered interrupts Return number of CPUs interrupt was successfully injected into or -1 if none. Signed-off-by: Gleb Natapov Signed-off-by: Avi Kivity --- virt/kvm/irq_comm.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index be8aba79155..c516d618d38 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c @@ -48,7 +48,7 @@ static int kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e, static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm, int level) { - int vcpu_id; + int vcpu_id, r = -1; struct kvm_vcpu *vcpu; struct kvm_ioapic *ioapic = ioapic_irqchip(kvm); int dest_id = (e->msi.address_lo & MSI_ADDR_DEST_ID_MASK) @@ -73,7 +73,7 @@ static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, vcpu = kvm_get_lowest_prio_vcpu(ioapic->kvm, vector, deliver_bitmask); if (vcpu != NULL) - kvm_apic_set_irq(vcpu, vector, trig_mode); + r = kvm_apic_set_irq(vcpu, vector, trig_mode); else printk(KERN_INFO "kvm: null lowest priority vcpu!\n"); break; @@ -83,14 +83,17 @@ static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, continue; deliver_bitmask &= ~(1 << vcpu_id); vcpu = ioapic->kvm->vcpus[vcpu_id]; - if (vcpu) - kvm_apic_set_irq(vcpu, vector, trig_mode); + if (vcpu) { + if (r < 0) + r = 0; + r += kvm_apic_set_irq(vcpu, vector, trig_mode); + } } break; default: break; } - return 1; + return r; } /* This should be called with the kvm->lock mutex held -- GitLab From b0a1835d53c57bc38b36867c04436b60454cb610 Mon Sep 17 00:00:00 2001 From: Liu Yu Date: Tue, 17 Feb 2009 16:52:08 +0800 Subject: [PATCH 4119/4982] KVM: ppc: Add emulation of E500 register mmucsr0 Latest kernel flushes TLB via mmucsr0. Signed-off-by: Liu Yu Acked-by: Hollis Blanchard Signed-off-by: Avi Kivity --- arch/powerpc/kvm/e500_emulate.c | 8 ++++++++ arch/powerpc/kvm/e500_tlb.c | 16 ++++++++++++++++ arch/powerpc/kvm/e500_tlb.h | 1 + 3 files changed, 25 insertions(+) diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c index 7a98d4a4c1e..3f760414b9f 100644 --- a/arch/powerpc/kvm/e500_emulate.c +++ b/arch/powerpc/kvm/e500_emulate.c @@ -105,6 +105,11 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) case SPRN_HID1: vcpu_e500->hid1 = vcpu->arch.gpr[rs]; break; + case SPRN_MMUCSR0: + emulated = kvmppc_e500_emul_mt_mmucsr0(vcpu_e500, + vcpu->arch.gpr[rs]); + break; + /* extra exceptions */ case SPRN_IVOR32: vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = vcpu->arch.gpr[rs]; @@ -172,6 +177,9 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt) case SPRN_HID1: vcpu->arch.gpr[rt] = vcpu_e500->hid1; break; + case SPRN_MMUCSR0: + vcpu->arch.gpr[rt] = 0; break; + /* extra exceptions */ case SPRN_IVOR32: vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL]; diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c index d437160d388..72386ddbd9d 100644 --- a/arch/powerpc/kvm/e500_tlb.c +++ b/arch/powerpc/kvm/e500_tlb.c @@ -391,6 +391,22 @@ static int kvmppc_e500_gtlbe_invalidate(struct kvmppc_vcpu_e500 *vcpu_e500, return 0; } +int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500, ulong value) +{ + int esel; + + if (value & MMUCSR0_TLB0FI) + for (esel = 0; esel < vcpu_e500->guest_tlb_size[0]; esel++) + kvmppc_e500_gtlbe_invalidate(vcpu_e500, 0, esel); + if (value & MMUCSR0_TLB1FI) + for (esel = 0; esel < vcpu_e500->guest_tlb_size[1]; esel++) + kvmppc_e500_gtlbe_invalidate(vcpu_e500, 1, esel); + + _tlbil_all(); + + return EMULATE_DONE; +} + int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb) { struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); diff --git a/arch/powerpc/kvm/e500_tlb.h b/arch/powerpc/kvm/e500_tlb.h index ab49e935518..4d5cc0f7d79 100644 --- a/arch/powerpc/kvm/e500_tlb.h +++ b/arch/powerpc/kvm/e500_tlb.h @@ -44,6 +44,7 @@ | E500_TLB_USER_PERM_MASK | E500_TLB_SUPER_PERM_MASK) extern void kvmppc_dump_tlbs(struct kvm_vcpu *); +extern int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *, ulong); extern int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *); extern int kvmppc_e500_emul_tlbre(struct kvm_vcpu *); extern int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *, int, int); -- GitLab From 2df8a40bccf5999261d0d3a82eac5a77678e61bd Mon Sep 17 00:00:00 2001 From: Weidong Han Date: Fri, 13 Feb 2009 10:50:56 +0800 Subject: [PATCH 4120/4982] KVM: define KVM_CAP_DEVICE_DEASSIGNMENT define KVM_CAP_DEVICE_DEASSIGNMENT and KVM_DEASSIGN_PCI_DEVICE for device deassignment. the ioctl has been already implemented in the commit: 0a920356748df4fb06e86c21c23d2ed6d31d37ad Acked-by: Mark McLoughlin Signed-off-by: Weidong Han Signed-off-by: Avi Kivity --- include/linux/kvm.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/linux/kvm.h b/include/linux/kvm.h index dd48225d182..0d94b274c3a 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h @@ -406,6 +406,9 @@ struct kvm_trace_rec { #define KVM_CAP_IRQ_ROUTING 25 #endif #define KVM_CAP_IRQ_INJECT_STATUS 26 +#ifdef __KVM_HAVE_DEVICE_ASSIGNMENT +#define KVM_CAP_DEVICE_DEASSIGNMENT 27 +#endif #ifdef KVM_CAP_IRQ_ROUTING @@ -480,6 +483,8 @@ struct kvm_irq_routing { #define KVM_ASSIGN_IRQ _IOR(KVMIO, 0x70, \ struct kvm_assigned_irq) #define KVM_REINJECT_CONTROL _IO(KVMIO, 0x71) +#define KVM_DEASSIGN_PCI_DEVICE _IOR(KVMIO, 0x72, \ + struct kvm_assigned_pci_dev) /* * ioctls for vcpu fds -- GitLab From 4a906e49f103c2e544148a209ba1db316510799f Mon Sep 17 00:00:00 2001 From: Weidong Han Date: Fri, 13 Feb 2009 17:27:51 +0800 Subject: [PATCH 4121/4982] KVM: fix kvm_vm_ioctl_deassign_device only need to set assigned_dev_id for deassignment, use match->flags to judge and deassign it. Acked-by: Mark McLoughlin Signed-off-by: Weidong Han Signed-off-by: Avi Kivity --- virt/kvm/kvm_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 0ed662dc72d..c4278975c8c 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -517,7 +517,7 @@ static int kvm_vm_ioctl_deassign_device(struct kvm *kvm, goto out; } - if (assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU) + if (match->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU) kvm_deassign_device(kvm, match); kvm_free_assigned_device(kvm, match); -- GitLab From 2fa8937f3af8873e006ce324e7b2d3f9b2077b87 Mon Sep 17 00:00:00 2001 From: Xiantao Zhang Date: Mon, 16 Feb 2009 15:14:48 +0800 Subject: [PATCH 4122/4982] ia64: Move the macro definitions related to MSI to one header file. For kvm's MSI support, it needs these macros defined in ia64_msi.c, and to avoid duplicate them, move them to one header file and share with kvm. Signed-off-by: Xiantao Zhang Acked-by: Tony Luck Signed-off-by: Avi Kivity --- arch/ia64/include/asm/msidef.h | 42 ++++++++++++++++++++++++++ arch/ia64/kernel/msi_ia64.c | 55 ++++++---------------------------- 2 files changed, 51 insertions(+), 46 deletions(-) create mode 100644 arch/ia64/include/asm/msidef.h diff --git a/arch/ia64/include/asm/msidef.h b/arch/ia64/include/asm/msidef.h new file mode 100644 index 00000000000..592c1047a0c --- /dev/null +++ b/arch/ia64/include/asm/msidef.h @@ -0,0 +1,42 @@ +#ifndef _IA64_MSI_DEF_H +#define _IA64_MSI_DEF_H + +/* + * Shifts for APIC-based data + */ + +#define MSI_DATA_VECTOR_SHIFT 0 +#define MSI_DATA_VECTOR(v) (((u8)v) << MSI_DATA_VECTOR_SHIFT) +#define MSI_DATA_VECTOR_MASK 0xffffff00 + +#define MSI_DATA_DELIVERY_MODE_SHIFT 8 +#define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_MODE_SHIFT) +#define MSI_DATA_DELIVERY_LOWPRI (1 << MSI_DATA_DELIVERY_MODE_SHIFT) + +#define MSI_DATA_LEVEL_SHIFT 14 +#define MSI_DATA_LEVEL_DEASSERT (0 << MSI_DATA_LEVEL_SHIFT) +#define MSI_DATA_LEVEL_ASSERT (1 << MSI_DATA_LEVEL_SHIFT) + +#define MSI_DATA_TRIGGER_SHIFT 15 +#define MSI_DATA_TRIGGER_EDGE (0 << MSI_DATA_TRIGGER_SHIFT) +#define MSI_DATA_TRIGGER_LEVEL (1 << MSI_DATA_TRIGGER_SHIFT) + +/* + * Shift/mask fields for APIC-based bus address + */ + +#define MSI_ADDR_DEST_ID_SHIFT 4 +#define MSI_ADDR_HEADER 0xfee00000 + +#define MSI_ADDR_DEST_ID_MASK 0xfff0000f +#define MSI_ADDR_DEST_ID_CPU(cpu) ((cpu) << MSI_ADDR_DEST_ID_SHIFT) + +#define MSI_ADDR_DEST_MODE_SHIFT 2 +#define MSI_ADDR_DEST_MODE_PHYS (0 << MSI_ADDR_DEST_MODE_SHIFT) +#define MSI_ADDR_DEST_MODE_LOGIC (1 << MSI_ADDR_DEST_MODE_SHIFT) + +#define MSI_ADDR_REDIRECTION_SHIFT 3 +#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT) +#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT) + +#endif/* _IA64_MSI_DEF_H */ diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c index 89033933903..368ee4e5266 100644 --- a/arch/ia64/kernel/msi_ia64.c +++ b/arch/ia64/kernel/msi_ia64.c @@ -7,44 +7,7 @@ #include #include #include - -/* - * Shifts for APIC-based data - */ - -#define MSI_DATA_VECTOR_SHIFT 0 -#define MSI_DATA_VECTOR(v) (((u8)v) << MSI_DATA_VECTOR_SHIFT) -#define MSI_DATA_VECTOR_MASK 0xffffff00 - -#define MSI_DATA_DELIVERY_SHIFT 8 -#define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_SHIFT) -#define MSI_DATA_DELIVERY_LOWPRI (1 << MSI_DATA_DELIVERY_SHIFT) - -#define MSI_DATA_LEVEL_SHIFT 14 -#define MSI_DATA_LEVEL_DEASSERT (0 << MSI_DATA_LEVEL_SHIFT) -#define MSI_DATA_LEVEL_ASSERT (1 << MSI_DATA_LEVEL_SHIFT) - -#define MSI_DATA_TRIGGER_SHIFT 15 -#define MSI_DATA_TRIGGER_EDGE (0 << MSI_DATA_TRIGGER_SHIFT) -#define MSI_DATA_TRIGGER_LEVEL (1 << MSI_DATA_TRIGGER_SHIFT) - -/* - * Shift/mask fields for APIC-based bus address - */ - -#define MSI_TARGET_CPU_SHIFT 4 -#define MSI_ADDR_HEADER 0xfee00000 - -#define MSI_ADDR_DESTID_MASK 0xfff0000f -#define MSI_ADDR_DESTID_CPU(cpu) ((cpu) << MSI_TARGET_CPU_SHIFT) - -#define MSI_ADDR_DESTMODE_SHIFT 2 -#define MSI_ADDR_DESTMODE_PHYS (0 << MSI_ADDR_DESTMODE_SHIFT) -#define MSI_ADDR_DESTMODE_LOGIC (1 << MSI_ADDR_DESTMODE_SHIFT) - -#define MSI_ADDR_REDIRECTION_SHIFT 3 -#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT) -#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT) +#include static struct irq_chip ia64_msi_chip; @@ -65,8 +28,8 @@ static void ia64_set_msi_irq_affinity(unsigned int irq, read_msi_msg(irq, &msg); addr = msg.address_lo; - addr &= MSI_ADDR_DESTID_MASK; - addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(cpu)); + addr &= MSI_ADDR_DEST_ID_MASK; + addr |= MSI_ADDR_DEST_ID_CPU(cpu_physical_id(cpu)); msg.address_lo = addr; data = msg.data; @@ -98,9 +61,9 @@ int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) msg.address_hi = 0; msg.address_lo = MSI_ADDR_HEADER | - MSI_ADDR_DESTMODE_PHYS | + MSI_ADDR_DEST_MODE_PHYS | MSI_ADDR_REDIRECTION_CPU | - MSI_ADDR_DESTID_CPU(dest_phys_id); + MSI_ADDR_DEST_ID_CPU(dest_phys_id); msg.data = MSI_DATA_TRIGGER_EDGE | @@ -183,8 +146,8 @@ static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask) msg.data &= ~MSI_DATA_VECTOR_MASK; msg.data |= MSI_DATA_VECTOR(cfg->vector); - msg.address_lo &= ~MSI_ADDR_DESTID_MASK; - msg.address_lo |= MSI_ADDR_DESTID_CPU(cpu_physical_id(cpu)); + msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK; + msg.address_lo |= MSI_ADDR_DEST_ID_CPU(cpu_physical_id(cpu)); dmar_msi_write(irq, &msg); irq_desc[irq].affinity = *mask; @@ -215,9 +178,9 @@ msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg) msg->address_hi = 0; msg->address_lo = MSI_ADDR_HEADER | - MSI_ADDR_DESTMODE_PHYS | + MSI_ADDR_DEST_MODE_PHYS | MSI_ADDR_REDIRECTION_CPU | - MSI_ADDR_DESTID_CPU(dest); + MSI_ADDR_DEST_ID_CPU(dest); msg->data = MSI_DATA_TRIGGER_EDGE | -- GitLab From 6b08035f3e64d8e474be166d682b52c95941662e Mon Sep 17 00:00:00 2001 From: Xiantao Zhang Date: Mon, 16 Feb 2009 15:24:05 +0800 Subject: [PATCH 4123/4982] KVM: ia64: Fix the build errors due to lack of macros related to MSI. Include the newly introduced msidef.h to solve the build issues. Signed-off-by: Xiantao Zhang Signed-off-by: Avi Kivity --- arch/ia64/kvm/irq.h | 2 ++ virt/kvm/irq_comm.c | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/ia64/kvm/irq.h b/arch/ia64/kvm/irq.h index c6786e8b1bf..c0785a72827 100644 --- a/arch/ia64/kvm/irq.h +++ b/arch/ia64/kvm/irq.h @@ -23,6 +23,8 @@ #ifndef __IRQ_H #define __IRQ_H +#include "lapic.h" + static inline int irqchip_in_kernel(struct kvm *kvm) { return 1; diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index c516d618d38..a70d805e014 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c @@ -21,9 +21,7 @@ #include -#ifdef CONFIG_X86 #include -#endif #include "irq.h" -- GitLab From 401d10dee083bda281f2fdcdf654080313ba30ec Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Fri, 20 Feb 2009 22:53:37 +0530 Subject: [PATCH 4124/4982] KVM: VMX: Update necessary state when guest enters long mode setup_msrs() should be called when entering long mode to save the shadow state for the 64-bit guest state. Using vmx_set_efer() in enter_lmode() removes some duplicated code and also ensures we call setup_msrs(). We can safely pass the value of shadow_efer to vmx_set_efer() as no other bits in the efer change while enabling long mode (guest first sets EFER.LME, then sets CR0.PG which causes a vmexit where we activate long mode). With this fix, is_long_mode() can check for EFER.LMA set instead of EFER.LME and 5e23049e86dd298b72e206b420513dbc3a240cd9 can be reverted. Signed-off-by: Amit Shah Signed-off-by: Avi Kivity --- arch/x86/kvm/vmx.c | 54 +++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index cb27ffccf46..48063a0aa24 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -1430,6 +1430,29 @@ continue_rmode: init_rmode(vcpu->kvm); } +static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer) +{ + struct vcpu_vmx *vmx = to_vmx(vcpu); + struct kvm_msr_entry *msr = find_msr_entry(vmx, MSR_EFER); + + vcpu->arch.shadow_efer = efer; + if (!msr) + return; + if (efer & EFER_LMA) { + vmcs_write32(VM_ENTRY_CONTROLS, + vmcs_read32(VM_ENTRY_CONTROLS) | + VM_ENTRY_IA32E_MODE); + msr->data = efer; + } else { + vmcs_write32(VM_ENTRY_CONTROLS, + vmcs_read32(VM_ENTRY_CONTROLS) & + ~VM_ENTRY_IA32E_MODE); + + msr->data = efer & ~EFER_LME; + } + setup_msrs(vmx); +} + #ifdef CONFIG_X86_64 static void enter_lmode(struct kvm_vcpu *vcpu) @@ -1444,13 +1467,8 @@ static void enter_lmode(struct kvm_vcpu *vcpu) (guest_tr_ar & ~AR_TYPE_MASK) | AR_TYPE_BUSY_64_TSS); } - vcpu->arch.shadow_efer |= EFER_LMA; - - find_msr_entry(to_vmx(vcpu), MSR_EFER)->data |= EFER_LMA | EFER_LME; - vmcs_write32(VM_ENTRY_CONTROLS, - vmcs_read32(VM_ENTRY_CONTROLS) - | VM_ENTRY_IA32E_MODE); + vmx_set_efer(vcpu, vcpu->arch.shadow_efer); } static void exit_lmode(struct kvm_vcpu *vcpu) @@ -1609,30 +1627,6 @@ static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) vmcs_writel(GUEST_CR4, hw_cr4); } -static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer) -{ - struct vcpu_vmx *vmx = to_vmx(vcpu); - struct kvm_msr_entry *msr = find_msr_entry(vmx, MSR_EFER); - - vcpu->arch.shadow_efer = efer; - if (!msr) - return; - if (efer & EFER_LMA) { - vmcs_write32(VM_ENTRY_CONTROLS, - vmcs_read32(VM_ENTRY_CONTROLS) | - VM_ENTRY_IA32E_MODE); - msr->data = efer; - - } else { - vmcs_write32(VM_ENTRY_CONTROLS, - vmcs_read32(VM_ENTRY_CONTROLS) & - ~VM_ENTRY_IA32E_MODE); - - msr->data = efer & ~EFER_LME; - } - setup_msrs(vmx); -} - static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg) { struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg]; -- GitLab From 41d6af119206e98764b4ae6d264d63acefcf851e Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Thu, 28 Feb 2008 16:06:15 +0530 Subject: [PATCH 4125/4982] KVM: is_long_mode() should check for EFER.LMA is_long_mode currently checks the LongModeEnable bit in EFER instead of the LongModeActive bit. This is wrong, but we survived this till now since it wasn't triggered. This breaks guests that go from long mode to compatibility mode. This is noticed on a solaris guest and fixes bug #1842160 Signed-off-by: Amit Shah Signed-off-by: Avi Kivity --- arch/x86/kvm/mmu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h index 258e5d56298..eaab2145f62 100644 --- a/arch/x86/kvm/mmu.h +++ b/arch/x86/kvm/mmu.h @@ -54,7 +54,7 @@ static inline int kvm_mmu_reload(struct kvm_vcpu *vcpu) static inline int is_long_mode(struct kvm_vcpu *vcpu) { #ifdef CONFIG_X86_64 - return vcpu->arch.shadow_efer & EFER_LME; + return vcpu->arch.shadow_efer & EFER_LMA; #else return 0; #endif -- GitLab From d7364a29b305862cbc92b3f8b6ad9968270d068c Mon Sep 17 00:00:00 2001 From: Hannes Eder Date: Sat, 21 Feb 2009 02:18:13 +0100 Subject: [PATCH 4126/4982] KVM: fix sparse warnings: context imbalance Impact: Attribute function with __acquires(...) resp. __releases(...). Fix this sparse warnings: arch/x86/kvm/i8259.c:34:13: warning: context imbalance in 'pic_lock' - wrong count at exit arch/x86/kvm/i8259.c:39:13: warning: context imbalance in 'pic_unlock' - unexpected unlock Signed-off-by: Hannes Eder Signed-off-by: Avi Kivity --- arch/x86/kvm/i8259.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c index b4e662e94dd..1ccb50c74f1 100644 --- a/arch/x86/kvm/i8259.c +++ b/arch/x86/kvm/i8259.c @@ -32,11 +32,13 @@ #include static void pic_lock(struct kvm_pic *s) + __acquires(&s->lock) { spin_lock(&s->lock); } static void pic_unlock(struct kvm_pic *s) + __releases(&s->lock) { struct kvm *kvm = s->kvm; unsigned acks = s->pending_acks; -- GitLab From cded19f396bc3c9d299331709d0a9fbc6ecc148a Mon Sep 17 00:00:00 2001 From: Hannes Eder Date: Sat, 21 Feb 2009 02:19:13 +0100 Subject: [PATCH 4127/4982] KVM: fix sparse warnings: Should it be static? Impact: Make symbols static. Fix this sparse warnings: arch/x86/kvm/mmu.c:992:5: warning: symbol 'mmu_pages_add' was not declared. Should it be static? arch/x86/kvm/mmu.c:1124:5: warning: symbol 'mmu_pages_next' was not declared. Should it be static? arch/x86/kvm/mmu.c:1144:6: warning: symbol 'mmu_pages_clear_parents' was not declared. Should it be static? arch/x86/kvm/x86.c:2037:5: warning: symbol 'kvm_read_guest_virt' was not declared. Should it be static? arch/x86/kvm/x86.c:2067:5: warning: symbol 'kvm_write_guest_virt' was not declared. Should it be static? virt/kvm/irq_comm.c:220:5: warning: symbol 'setup_routing_entry' was not declared. Should it be static? Signed-off-by: Hannes Eder Signed-off-by: Avi Kivity --- arch/x86/kvm/mmu.c | 11 ++++++----- arch/x86/kvm/x86.c | 8 ++++---- virt/kvm/irq_comm.c | 4 ++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 4a21b0f8491..2a36f7f7c4c 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -989,8 +989,8 @@ struct kvm_mmu_pages { idx < 512; \ idx = find_next_bit(bitmap, 512, idx+1)) -int mmu_pages_add(struct kvm_mmu_pages *pvec, struct kvm_mmu_page *sp, - int idx) +static int mmu_pages_add(struct kvm_mmu_pages *pvec, struct kvm_mmu_page *sp, + int idx) { int i; @@ -1121,8 +1121,9 @@ struct mmu_page_path { i < pvec.nr && ({ sp = pvec.page[i].sp; 1;}); \ i = mmu_pages_next(&pvec, &parents, i)) -int mmu_pages_next(struct kvm_mmu_pages *pvec, struct mmu_page_path *parents, - int i) +static int mmu_pages_next(struct kvm_mmu_pages *pvec, + struct mmu_page_path *parents, + int i) { int n; @@ -1141,7 +1142,7 @@ int mmu_pages_next(struct kvm_mmu_pages *pvec, struct mmu_page_path *parents, return n; } -void mmu_pages_clear_parents(struct mmu_page_path *parents) +static void mmu_pages_clear_parents(struct mmu_page_path *parents) { struct kvm_mmu_page *sp; unsigned int level = 0; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index e4db5be7c95..8ca100a9eca 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2043,8 +2043,8 @@ static struct kvm_io_device *vcpu_find_mmio_dev(struct kvm_vcpu *vcpu, return dev; } -int kvm_read_guest_virt(gva_t addr, void *val, unsigned int bytes, - struct kvm_vcpu *vcpu) +static int kvm_read_guest_virt(gva_t addr, void *val, unsigned int bytes, + struct kvm_vcpu *vcpu) { void *data = val; int r = X86EMUL_CONTINUE; @@ -2073,8 +2073,8 @@ out: return r; } -int kvm_write_guest_virt(gva_t addr, void *val, unsigned int bytes, - struct kvm_vcpu *vcpu) +static int kvm_write_guest_virt(gva_t addr, void *val, unsigned int bytes, + struct kvm_vcpu *vcpu) { void *data = val; int r = X86EMUL_CONTINUE; diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index a70d805e014..864ac5483ba 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c @@ -233,8 +233,8 @@ void kvm_free_irq_routing(struct kvm *kvm) __kvm_free_irq_routing(&kvm->irq_routing); } -int setup_routing_entry(struct kvm_kernel_irq_routing_entry *e, - const struct kvm_irq_routing_entry *ue) +static int setup_routing_entry(struct kvm_kernel_irq_routing_entry *e, + const struct kvm_irq_routing_entry *ue) { int r = -EINVAL; int delta; -- GitLab From 36463146ffb7eee4582ed785a8c8be213b8ed110 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Mon, 16 Mar 2009 16:33:43 +0800 Subject: [PATCH 4128/4982] KVM: Get support IRQ routing entry counts In capability probing ioctl. Signed-off-by: Sheng Yang Signed-off-by: Avi Kivity --- virt/kvm/kvm_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index c4278975c8c..605697e9c4d 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1988,7 +1988,7 @@ static long kvm_dev_ioctl_check_extension_generic(long arg) return 1; #ifdef CONFIG_HAVE_KVM_IRQCHIP case KVM_CAP_IRQ_ROUTING: - return 1; + return KVM_MAX_IRQ_ROUTES; #endif default: break; -- GitLab From 4539b35881ae9664b0e2953438dd83f5ee02c0b4 Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Thu, 12 Mar 2009 18:18:43 +0100 Subject: [PATCH 4129/4982] KVM: Fix missing smp tlb flush in invlpg When kvm emulates an invlpg instruction, it can drop a shadow pte, but leaves the guest tlbs intact. This can cause memory corruption when swapping out. Without this the other cpu can still write to a freed host physical page. tlb smp flush must happen if rmap_remove is called always before mmu_lock is released because the VM will take the mmu_lock before it can finally add the page to the freelist after swapout. mmu notifier makes it safe to flush the tlb after freeing the page (otherwise it would never be safe) so we can do a single flush for multiple sptes invalidated. Cc: stable@kernel.org Signed-off-by: Andrea Arcangeli Acked-by: Marcelo Tosatti Signed-off-by: Avi Kivity --- arch/x86/kvm/paging_tmpl.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index 0f11792fafa..6bd70206c56 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h @@ -446,6 +446,7 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva) gpa_t pte_gpa = -1; int level; u64 *sptep; + int need_flush = 0; spin_lock(&vcpu->kvm->mmu_lock); @@ -465,6 +466,7 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva) rmap_remove(vcpu->kvm, sptep); if (is_large_pte(*sptep)) --vcpu->kvm->stat.lpages; + need_flush = 1; } set_shadow_pte(sptep, shadow_trap_nonpresent_pte); break; @@ -474,6 +476,8 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva) break; } + if (need_flush) + kvm_flush_remote_tlbs(vcpu->kvm); spin_unlock(&vcpu->kvm->mmu_lock); if (pte_gpa == -1) -- GitLab From bc35cbc85cd78213590761618a13da6a9707652c Mon Sep 17 00:00:00 2001 From: Liu Yu Date: Tue, 17 Mar 2009 16:57:45 +0800 Subject: [PATCH 4130/4982] KVM: ppc: e500: Fix the bug that mas0 update to wrong value when read TLB entry Should clear and then update the next victim area here. Guest kernel only read TLB1 when startup kernel, this bug result in an extra 4K TLB1 mapping in guest from 0x0 to 0x0. As the problem has no impact to bootup a guest, we didn't notice it before. Signed-off-by: Liu Yu Signed-off-by: Avi Kivity --- arch/powerpc/kvm/e500_tlb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c index 72386ddbd9d..ec933209e8a 100644 --- a/arch/powerpc/kvm/e500_tlb.c +++ b/arch/powerpc/kvm/e500_tlb.c @@ -448,7 +448,7 @@ int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu) esel = get_tlb_esel(vcpu_e500, tlbsel); gtlbe = &vcpu_e500->guest_tlb[tlbsel][esel]; - vcpu_e500->mas0 &= MAS0_NV(0); + vcpu_e500->mas0 &= ~MAS0_NV(~0); vcpu_e500->mas0 |= MAS0_NV(vcpu_e500->guest_tlb_nv[tlbsel]); vcpu_e500->mas1 = gtlbe->mas1; vcpu_e500->mas2 = gtlbe->mas2; -- GitLab From 046a48b35baa7c66d0d0331256ba12ca51665411 Mon Sep 17 00:00:00 2001 From: Liu Yu Date: Tue, 17 Mar 2009 16:57:46 +0800 Subject: [PATCH 4131/4982] KVM: ppc: e500: Fix the bug that KVM is unstable in SMP TLB entry should enable memory coherence in SMP. And like commit 631fba9dd3aca519355322cef035730609e91593, remove guard attribute to enable the prefetch of guest memory. Signed-off-by: Liu Yu Signed-off-by: Avi Kivity --- arch/powerpc/kvm/e500_tlb.c | 4 ++++ arch/powerpc/kvm/e500_tlb.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c index ec933209e8a..0e773fc2d5e 100644 --- a/arch/powerpc/kvm/e500_tlb.c +++ b/arch/powerpc/kvm/e500_tlb.c @@ -99,7 +99,11 @@ static inline u32 e500_shadow_mas3_attrib(u32 mas3, int usermode) static inline u32 e500_shadow_mas2_attrib(u32 mas2, int usermode) { +#ifdef CONFIG_SMP + return (mas2 & MAS2_ATTRIB_MASK) | MAS2_M; +#else return mas2 & MAS2_ATTRIB_MASK; +#endif } /* diff --git a/arch/powerpc/kvm/e500_tlb.h b/arch/powerpc/kvm/e500_tlb.h index 4d5cc0f7d79..45b064b7690 100644 --- a/arch/powerpc/kvm/e500_tlb.h +++ b/arch/powerpc/kvm/e500_tlb.h @@ -38,7 +38,7 @@ #define E500_TLB_USER_PERM_MASK (MAS3_UX|MAS3_UR|MAS3_UW) #define E500_TLB_SUPER_PERM_MASK (MAS3_SX|MAS3_SR|MAS3_SW) #define MAS2_ATTRIB_MASK \ - (MAS2_X0 | MAS2_X1 | MAS2_W | MAS2_I | MAS2_M | MAS2_G | MAS2_E) + (MAS2_X0 | MAS2_X1) #define MAS3_ATTRIB_MASK \ (MAS3_U0 | MAS3_U1 | MAS3_U2 | MAS3_U3 \ | E500_TLB_USER_PERM_MASK | E500_TLB_SUPER_PERM_MASK) -- GitLab From bc7a8660df62da3fb5cad025322eda75fbee8731 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Tue, 17 Mar 2009 19:27:19 +0800 Subject: [PATCH 4132/4982] KVM: Correct deassign device ioctl to IOW It's IOR by mistake, so fix it before release. Signed-off-by: Sheng Yang Signed-off-by: Avi Kivity --- include/linux/kvm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 0d94b274c3a..311a073afe8 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h @@ -483,7 +483,7 @@ struct kvm_irq_routing { #define KVM_ASSIGN_IRQ _IOR(KVMIO, 0x70, \ struct kvm_assigned_irq) #define KVM_REINJECT_CONTROL _IO(KVMIO, 0x71) -#define KVM_DEASSIGN_PCI_DEVICE _IOR(KVMIO, 0x72, \ +#define KVM_DEASSIGN_PCI_DEVICE _IOW(KVMIO, 0x72, \ struct kvm_assigned_pci_dev) /* -- GitLab From 16175a796d061833aacfbd9672235f2d2725df65 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Mon, 23 Mar 2009 22:13:44 +0200 Subject: [PATCH 4133/4982] KVM: VMX: Don't allow uninhibited access to EFER on i386 vmx_set_msr() does not allow i386 guests to touch EFER, but they can still do so through the default: label in the switch. If they set EFER_LME, they can oops the host. Fix by having EFER access through the normal channel (which will check for EFER_LME) even on i386. Reported-and-tested-by: Benjamin Gilbert Cc: stable@kernel.org Signed-off-by: Avi Kivity --- arch/x86/kvm/vmx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 48063a0aa24..bb481330716 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -936,11 +936,11 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data) int ret = 0; switch (msr_index) { -#ifdef CONFIG_X86_64 case MSR_EFER: vmx_load_host_state(vmx); ret = kvm_set_msr_common(vcpu, msr_index, data); break; +#ifdef CONFIG_X86_64 case MSR_FS_BASE: vmcs_writel(GUEST_FS_BASE, data); break; -- GitLab From 6f04c1c7fe9566d777fb7961391690866839e722 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Tue, 6 Jan 2009 11:52:25 +0000 Subject: [PATCH 4134/4982] GFS2: Fix remount argument parsing The following patch fixes an issue relating to remount and argument parsing. After this fix is applied, remount becomes atomic in that it either succeeds changing the mount to the new state, or it fails and leaves it in the old state. Previously it was possible for the parsing of options to fail part way though and for the fs to be left in a state where some of the new arguments had been applied, but some had not. Signed-off-by: Steven Whitehouse --- fs/gfs2/mount.c | 111 ++++++++----------------------------------- fs/gfs2/mount.h | 17 ------- fs/gfs2/ops_fstype.c | 11 ++++- fs/gfs2/ops_super.c | 41 ++++++++++++---- fs/gfs2/super.h | 26 +++++----- 5 files changed, 73 insertions(+), 133 deletions(-) delete mode 100644 fs/gfs2/mount.h diff --git a/fs/gfs2/mount.c b/fs/gfs2/mount.c index 3cb0a44ba02..3524ae81189 100644 --- a/fs/gfs2/mount.c +++ b/fs/gfs2/mount.c @@ -17,7 +17,7 @@ #include "gfs2.h" #include "incore.h" -#include "mount.h" +#include "super.h" #include "sys.h" #include "util.h" @@ -77,101 +77,46 @@ static const match_table_t tokens = { * Return: errno */ -int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount) +int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options) { - struct gfs2_args *args = &sdp->sd_args; - char *data = data_arg; - char *options, *o, *v; - int error = 0; - - if (!remount) { - /* Set some defaults */ - args->ar_quota = GFS2_QUOTA_DEFAULT; - args->ar_data = GFS2_DATA_DEFAULT; - } + char *o; + int token; + substring_t tmp[MAX_OPT_ARGS]; /* Split the options into tokens with the "," character and process them */ - for (options = data; (o = strsep(&options, ",")); ) { - int token; - substring_t tmp[MAX_OPT_ARGS]; - - if (!*o) + while (1) { + o = strsep(&options, ","); + if (o == NULL) + break; + if (*o == '\0') continue; token = match_token(o, tokens, tmp); switch (token) { case Opt_lockproto: - v = match_strdup(&tmp[0]); - if (!v) { - fs_info(sdp, "no memory for lockproto\n"); - error = -ENOMEM; - goto out_error; - } - - if (remount && strcmp(v, args->ar_lockproto)) { - kfree(v); - goto cant_remount; - } - - strncpy(args->ar_lockproto, v, GFS2_LOCKNAME_LEN); - args->ar_lockproto[GFS2_LOCKNAME_LEN - 1] = 0; - kfree(v); + match_strlcpy(args->ar_lockproto, &tmp[0], + GFS2_LOCKNAME_LEN); break; case Opt_locktable: - v = match_strdup(&tmp[0]); - if (!v) { - fs_info(sdp, "no memory for locktable\n"); - error = -ENOMEM; - goto out_error; - } - - if (remount && strcmp(v, args->ar_locktable)) { - kfree(v); - goto cant_remount; - } - - strncpy(args->ar_locktable, v, GFS2_LOCKNAME_LEN); - args->ar_locktable[GFS2_LOCKNAME_LEN - 1] = 0; - kfree(v); + match_strlcpy(args->ar_locktable, &tmp[0], + GFS2_LOCKNAME_LEN); break; case Opt_hostdata: - v = match_strdup(&tmp[0]); - if (!v) { - fs_info(sdp, "no memory for hostdata\n"); - error = -ENOMEM; - goto out_error; - } - - if (remount && strcmp(v, args->ar_hostdata)) { - kfree(v); - goto cant_remount; - } - - strncpy(args->ar_hostdata, v, GFS2_LOCKNAME_LEN); - args->ar_hostdata[GFS2_LOCKNAME_LEN - 1] = 0; - kfree(v); + match_strlcpy(args->ar_hostdata, &tmp[0], + GFS2_LOCKNAME_LEN); break; case Opt_spectator: - if (remount && !args->ar_spectator) - goto cant_remount; args->ar_spectator = 1; - sdp->sd_vfs->s_flags |= MS_RDONLY; break; case Opt_ignore_local_fs: - if (remount && !args->ar_ignore_local_fs) - goto cant_remount; args->ar_ignore_local_fs = 1; break; case Opt_localflocks: - if (remount && !args->ar_localflocks) - goto cant_remount; args->ar_localflocks = 1; break; case Opt_localcaching: - if (remount && !args->ar_localcaching) - goto cant_remount; args->ar_localcaching = 1; break; case Opt_debug: @@ -181,17 +126,13 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount) args->ar_debug = 0; break; case Opt_upgrade: - if (remount && !args->ar_upgrade) - goto cant_remount; args->ar_upgrade = 1; break; case Opt_acl: args->ar_posix_acl = 1; - sdp->sd_vfs->s_flags |= MS_POSIXACL; break; case Opt_noacl: args->ar_posix_acl = 0; - sdp->sd_vfs->s_flags &= ~MS_POSIXACL; break; case Opt_quota_off: args->ar_quota = GFS2_QUOTA_OFF; @@ -215,29 +156,15 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount) args->ar_data = GFS2_DATA_ORDERED; break; case Opt_meta: - if (remount && args->ar_meta != 1) - goto cant_remount; args->ar_meta = 1; break; case Opt_err: default: - fs_info(sdp, "unknown option: %s\n", o); - error = -EINVAL; - goto out_error; + fs_info(sdp, "invalid mount option: %s\n", o); + return -EINVAL; } } -out_error: - if (error) - fs_info(sdp, "invalid mount option(s)\n"); - - if (data != data_arg) - kfree(data); - - return error; - -cant_remount: - fs_info(sdp, "can't remount with option %s\n", o); - return -EINVAL; + return 0; } diff --git a/fs/gfs2/mount.h b/fs/gfs2/mount.h deleted file mode 100644 index 401288acfdf..00000000000 --- a/fs/gfs2/mount.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. - * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. - * - * This copyrighted material is made available to anyone wishing to use, - * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU General Public License version 2. - */ - -#ifndef __MOUNT_DOT_H__ -#define __MOUNT_DOT_H__ - -struct gfs2_sbd; - -int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount); - -#endif /* __MOUNT_DOT_H__ */ diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index f91eebdde58..3eb49edae54 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -25,7 +25,6 @@ #include "glock.h" #include "glops.h" #include "inode.h" -#include "mount.h" #include "recovery.h" #include "rgrp.h" #include "super.h" @@ -1116,12 +1115,20 @@ static int fill_super(struct super_block *sb, void *data, int silent) return -ENOMEM; } - error = gfs2_mount_args(sdp, (char *)data, 0); + sdp->sd_args.ar_quota = GFS2_QUOTA_DEFAULT; + sdp->sd_args.ar_data = GFS2_DATA_DEFAULT; + + error = gfs2_mount_args(sdp, &sdp->sd_args, data); if (error) { printk(KERN_WARNING "GFS2: can't parse mount arguments\n"); goto fail; } + if (sdp->sd_args.ar_spectator) + sb->s_flags |= MS_RDONLY; + if (sdp->sd_args.ar_posix_acl) + sb->s_flags |= MS_POSIXACL; + sb->s_magic = GFS2_MAGIC; sb->s_op = &gfs2_super_ops; sb->s_export_op = &gfs2_export_ops; diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index 320323d0347..f0699ac453f 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c @@ -27,7 +27,6 @@ #include "glock.h" #include "inode.h" #include "log.h" -#include "mount.h" #include "quota.h" #include "recovery.h" #include "rgrp.h" @@ -40,6 +39,8 @@ #include "bmap.h" #include "meta_io.h" +#define args_neq(a1, a2, x) ((a1)->ar_##x != (a2)->ar_##x) + /** * gfs2_write_inode - Make sure the inode is stable on the disk * @inode: The inode @@ -435,25 +436,45 @@ static int gfs2_statfs(struct dentry *dentry, struct kstatfs *buf) static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data) { struct gfs2_sbd *sdp = sb->s_fs_info; + struct gfs2_args args = sdp->sd_args; /* Default to current settings */ int error; - error = gfs2_mount_args(sdp, data, 1); + error = gfs2_mount_args(sdp, &args, data); if (error) return error; + /* Not allowed to change locking details */ + if (strcmp(args.ar_lockproto, sdp->sd_args.ar_lockproto) || + strcmp(args.ar_locktable, sdp->sd_args.ar_locktable) || + strcmp(args.ar_hostdata, sdp->sd_args.ar_hostdata)) + return -EINVAL; + + /* Some flags must not be changed */ + if (args_neq(&args, &sdp->sd_args, spectator) || + args_neq(&args, &sdp->sd_args, ignore_local_fs) || + args_neq(&args, &sdp->sd_args, localflocks) || + args_neq(&args, &sdp->sd_args, localcaching) || + args_neq(&args, &sdp->sd_args, meta)) + return -EINVAL; + if (sdp->sd_args.ar_spectator) *flags |= MS_RDONLY; - else { - if (*flags & MS_RDONLY) { - if (!(sb->s_flags & MS_RDONLY)) - error = gfs2_make_fs_ro(sdp); - } else if (!(*flags & MS_RDONLY) && - (sb->s_flags & MS_RDONLY)) { + + if ((sb->s_flags ^ *flags) & MS_RDONLY) { + if (*flags & MS_RDONLY) + error = gfs2_make_fs_ro(sdp); + else error = gfs2_make_fs_rw(sdp); - } + if (error) + return error; } - return error; + sdp->sd_args = args; + if (sdp->sd_args.ar_posix_acl) + sb->s_flags |= MS_POSIXACL; + else + sb->s_flags &= ~MS_POSIXACL; + return 0; } /** diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h index f6b8b00ad88..91abdbedcc8 100644 --- a/fs/gfs2/super.h +++ b/fs/gfs2/super.h @@ -14,7 +14,7 @@ #include #include "incore.h" -void gfs2_lm_unmount(struct gfs2_sbd *sdp); +extern void gfs2_lm_unmount(struct gfs2_sbd *sdp); static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp) { @@ -27,21 +27,23 @@ static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp) void gfs2_jindex_free(struct gfs2_sbd *sdp); -struct gfs2_jdesc *gfs2_jdesc_find(struct gfs2_sbd *sdp, unsigned int jid); -int gfs2_jdesc_check(struct gfs2_jdesc *jd); +extern int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *data); -int gfs2_lookup_in_master_dir(struct gfs2_sbd *sdp, char *filename, - struct gfs2_inode **ipp); +extern struct gfs2_jdesc *gfs2_jdesc_find(struct gfs2_sbd *sdp, unsigned int jid); +extern int gfs2_jdesc_check(struct gfs2_jdesc *jd); -int gfs2_make_fs_rw(struct gfs2_sbd *sdp); +extern int gfs2_lookup_in_master_dir(struct gfs2_sbd *sdp, char *filename, + struct gfs2_inode **ipp); -int gfs2_statfs_init(struct gfs2_sbd *sdp); -void gfs2_statfs_change(struct gfs2_sbd *sdp, - s64 total, s64 free, s64 dinodes); -int gfs2_statfs_sync(struct gfs2_sbd *sdp); +extern int gfs2_make_fs_rw(struct gfs2_sbd *sdp); -int gfs2_freeze_fs(struct gfs2_sbd *sdp); -void gfs2_unfreeze_fs(struct gfs2_sbd *sdp); +extern int gfs2_statfs_init(struct gfs2_sbd *sdp); +extern void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free, + s64 dinodes); +extern int gfs2_statfs_sync(struct gfs2_sbd *sdp); + +extern int gfs2_freeze_fs(struct gfs2_sbd *sdp); +extern void gfs2_unfreeze_fs(struct gfs2_sbd *sdp); extern struct file_system_type gfs2_fs_type; extern struct file_system_type gfs2meta_fs_type; -- GitLab From 2db2aac255c38e75ad17c0b24feb589ccfccc0ae Mon Sep 17 00:00:00 2001 From: Abhijith Das Date: Wed, 7 Jan 2009 10:21:34 -0600 Subject: [PATCH 4135/4982] GFS2: Bring back lvb-related stuff to lock_nolock to support quotas The quota code uses lvbs and this is currently not implemented in lock_nolock, thereby causing panics when quota is enabled with lock_nolock. This patch adds the relevant bits. Signed-off-by: Abhijith Das Signed-off-by: Steven Whitehouse --- fs/gfs2/locking.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/fs/gfs2/locking.c b/fs/gfs2/locking.c index 523243a13a2..d3657bc7938 100644 --- a/fs/gfs2/locking.c +++ b/fs/gfs2/locking.c @@ -23,11 +23,74 @@ struct lmh_wrapper { const struct lm_lockops *lw_ops; }; +struct nolock_lockspace { + unsigned int nl_lvb_size; +}; + +/** + * nolock_get_lock - get a lm_lock_t given a descripton of the lock + * @lockspace: the lockspace the lock lives in + * @name: the name of the lock + * @lockp: return the lm_lock_t here + * + * Returns: 0 on success, -EXXX on failure + */ + +static int nolock_get_lock(void *lockspace, struct lm_lockname *name, + void **lockp) +{ + *lockp = lockspace; + return 0; +} + +/** + * nolock_put_lock - get rid of a lock structure + * @lock: the lock to throw away + * + */ + +static void nolock_put_lock(void *lock) +{ +} + +/** + * nolock_hold_lvb - hold on to a lock value block + * @lock: the lock the LVB is associated with + * @lvbp: return the lm_lvb_t here + * + * Returns: 0 on success, -EXXX on failure + */ + +static int nolock_hold_lvb(void *lock, char **lvbp) +{ + struct nolock_lockspace *nl = lock; + int error = 0; + + *lvbp = kzalloc(nl->nl_lvb_size, GFP_KERNEL); + if (!*lvbp) + error = -ENOMEM; + + return error; +} + +/** + * nolock_unhold_lvb - release a LVB + * @lock: the lock the LVB is associated with + * @lvb: the lock value block + * + */ + +static void nolock_unhold_lvb(void *lock, char *lvb) +{ + kfree(lvb); +} + static int nolock_mount(char *table_name, char *host_data, lm_callback_t cb, void *cb_data, unsigned int min_lvb_size, int flags, struct lm_lockstruct *lockstruct, struct kobject *fskobj); +static void nolock_unmount(void *lockspace); /* List of registered low-level locking protocols. A file system selects one of them by name at mount time, e.g. lock_nolock, lock_dlm. */ @@ -35,6 +98,11 @@ static int nolock_mount(char *table_name, char *host_data, static const struct lm_lockops nolock_ops = { .lm_proto_name = "lock_nolock", .lm_mount = nolock_mount, + .lm_unmount = nolock_unmount, + .lm_get_lock = nolock_get_lock, + .lm_put_lock = nolock_put_lock, + .lm_hold_lvb = nolock_hold_lvb, + .lm_unhold_lvb = nolock_unhold_lvb, }; static struct lmh_wrapper nolock_proto = { @@ -53,6 +121,7 @@ static int nolock_mount(char *table_name, char *host_data, { char *c; unsigned int jid; + struct nolock_lockspace *nl; c = strstr(host_data, "jid="); if (!c) @@ -62,15 +131,28 @@ static int nolock_mount(char *table_name, char *host_data, sscanf(c, "%u", &jid); } + nl = kzalloc(sizeof(struct nolock_lockspace), GFP_KERNEL); + if (!nl) + return -ENOMEM; + + nl->nl_lvb_size = min_lvb_size; + lockstruct->ls_jid = jid; lockstruct->ls_first = 1; lockstruct->ls_lvb_size = min_lvb_size; + lockstruct->ls_lockspace = nl; lockstruct->ls_ops = &nolock_ops; lockstruct->ls_flags = LM_LSFLAG_LOCAL; return 0; } +static void nolock_unmount(void *lockspace) +{ + struct nolock_lockspace *nl = lockspace; + kfree(nl); +} + /** * gfs2_register_lockproto - Register a low-level locking protocol * @proto: the protocol definition -- GitLab From 0a7ab79c5b5a16035e09b466c9013c8afc3b4bff Mon Sep 17 00:00:00 2001 From: Abhijith Das Date: Wed, 7 Jan 2009 16:03:37 -0600 Subject: [PATCH 4136/4982] GFS2: change gfs2_quota_scan into a shrinker Deallocation of gfs2_quota_data objects now happens on-demand through a shrinker instead of routinely deallocating through the quotad daemon. Signed-off-by: Abhijith Das Signed-off-by: Steven Whitehouse --- fs/gfs2/incore.h | 6 +- fs/gfs2/main.c | 10 +++ fs/gfs2/ops_address.c | 1 + fs/gfs2/ops_fstype.c | 1 - fs/gfs2/quota.c | 165 +++++++++++++++++++++++++----------------- fs/gfs2/quota.h | 2 + fs/gfs2/sys.c | 2 - 7 files changed, 114 insertions(+), 73 deletions(-) diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 608849d0002..592aa5040d2 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -283,7 +283,9 @@ enum { struct gfs2_quota_data { struct list_head qd_list; - unsigned int qd_count; + struct list_head qd_reclaim; + + atomic_t qd_count; u32 qd_id; unsigned long qd_flags; /* QDF_... */ @@ -303,7 +305,6 @@ struct gfs2_quota_data { u64 qd_sync_gen; unsigned long qd_last_warn; - unsigned long qd_last_touched; }; struct gfs2_trans { @@ -406,7 +407,6 @@ struct gfs2_tune { unsigned int gt_quota_warn_period; /* Secs between quota warn msgs */ unsigned int gt_quota_scale_num; /* Numerator */ unsigned int gt_quota_scale_den; /* Denominator */ - unsigned int gt_quota_cache_secs; unsigned int gt_quota_quantum; /* Secs between syncs to quota file */ unsigned int gt_new_files_jdata; unsigned int gt_max_readahead; /* Max bytes to read-ahead from disk */ diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index 7cacfde3219..86fe0679871 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c @@ -23,6 +23,12 @@ #include "sys.h" #include "util.h" #include "glock.h" +#include "quota.h" + +static struct shrinker qd_shrinker = { + .shrink = gfs2_shrink_qd_memory, + .seeks = DEFAULT_SEEKS, +}; static void gfs2_init_inode_once(void *foo) { @@ -100,6 +106,8 @@ static int __init init_gfs2_fs(void) if (!gfs2_quotad_cachep) goto fail; + register_shrinker(&qd_shrinker); + error = register_filesystem(&gfs2_fs_type); if (error) goto fail; @@ -117,6 +125,7 @@ static int __init init_gfs2_fs(void) fail_unregister: unregister_filesystem(&gfs2_fs_type); fail: + unregister_shrinker(&qd_shrinker); gfs2_glock_exit(); if (gfs2_quotad_cachep) @@ -145,6 +154,7 @@ fail: static void __exit exit_gfs2_fs(void) { + unregister_shrinker(&qd_shrinker); gfs2_glock_exit(); gfs2_unregister_debugfs(); unregister_filesystem(&gfs2_fs_type); diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 4ddab67867e..dde4ead2c3b 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c @@ -442,6 +442,7 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page) */ if (unlikely(page->index)) { zero_user(page, 0, PAGE_CACHE_SIZE); + SetPageUptodate(page); return 0; } diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 3eb49edae54..530d3f6f6ea 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -63,7 +63,6 @@ static void gfs2_tune_init(struct gfs2_tune *gt) gt->gt_quota_warn_period = 10; gt->gt_quota_scale_num = 1; gt->gt_quota_scale_den = 1; - gt->gt_quota_cache_secs = 300; gt->gt_quota_quantum = 60; gt->gt_new_files_jdata = 0; gt->gt_max_readahead = 1 << 18; diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index b08d09696b3..2ada6e10d07 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -80,6 +80,53 @@ struct gfs2_quota_change_host { u32 qc_id; }; +static LIST_HEAD(qd_lru_list); +static atomic_t qd_lru_count = ATOMIC_INIT(0); +static spinlock_t qd_lru_lock = SPIN_LOCK_UNLOCKED; + +int gfs2_shrink_qd_memory(int nr, gfp_t gfp_mask) +{ + struct gfs2_quota_data *qd; + struct gfs2_sbd *sdp; + + if (nr == 0) + goto out; + + if (!(gfp_mask & __GFP_FS)) + return -1; + + spin_lock(&qd_lru_lock); + while (nr && !list_empty(&qd_lru_list)) { + qd = list_entry(qd_lru_list.next, + struct gfs2_quota_data, qd_reclaim); + sdp = qd->qd_gl->gl_sbd; + + /* Free from the filesystem-specific list */ + list_del(&qd->qd_list); + + spin_lock(&sdp->sd_quota_spin); + gfs2_assert_warn(sdp, !qd->qd_change); + gfs2_assert_warn(sdp, !qd->qd_slot_count); + gfs2_assert_warn(sdp, !qd->qd_bh_count); + + gfs2_lvb_unhold(qd->qd_gl); + spin_unlock(&sdp->sd_quota_spin); + atomic_dec(&sdp->sd_quota_count); + + /* Delete it from the common reclaim list */ + list_del_init(&qd->qd_reclaim); + atomic_dec(&qd_lru_count); + spin_unlock(&qd_lru_lock); + kmem_cache_free(gfs2_quotad_cachep, qd); + spin_lock(&qd_lru_lock); + nr--; + } + spin_unlock(&qd_lru_lock); + +out: + return (atomic_read(&qd_lru_count) * sysctl_vfs_cache_pressure) / 100; +} + static u64 qd2offset(struct gfs2_quota_data *qd) { u64 offset; @@ -100,11 +147,12 @@ static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id, if (!qd) return -ENOMEM; - qd->qd_count = 1; + atomic_set(&qd->qd_count, 1); qd->qd_id = id; if (user) set_bit(QDF_USER, &qd->qd_flags); qd->qd_slot = -1; + INIT_LIST_HEAD(&qd->qd_reclaim); error = gfs2_glock_get(sdp, 2 * (u64)id + !user, &gfs2_quota_glops, CREATE, &qd->qd_gl); @@ -135,11 +183,17 @@ static int qd_get(struct gfs2_sbd *sdp, int user, u32 id, int create, for (;;) { found = 0; - spin_lock(&sdp->sd_quota_spin); + spin_lock(&qd_lru_lock); list_for_each_entry(qd, &sdp->sd_quota_list, qd_list) { if (qd->qd_id == id && !test_bit(QDF_USER, &qd->qd_flags) == !user) { - qd->qd_count++; + if (!atomic_read(&qd->qd_count) && + !list_empty(&qd->qd_reclaim)) { + /* Remove it from reclaim list */ + list_del_init(&qd->qd_reclaim); + atomic_dec(&qd_lru_count); + } + atomic_inc(&qd->qd_count); found = 1; break; } @@ -155,7 +209,7 @@ static int qd_get(struct gfs2_sbd *sdp, int user, u32 id, int create, new_qd = NULL; } - spin_unlock(&sdp->sd_quota_spin); + spin_unlock(&qd_lru_lock); if (qd || !create) { if (new_qd) { @@ -175,21 +229,18 @@ static int qd_get(struct gfs2_sbd *sdp, int user, u32 id, int create, static void qd_hold(struct gfs2_quota_data *qd) { struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd; - - spin_lock(&sdp->sd_quota_spin); - gfs2_assert(sdp, qd->qd_count); - qd->qd_count++; - spin_unlock(&sdp->sd_quota_spin); + gfs2_assert(sdp, atomic_read(&qd->qd_count)); + atomic_inc(&qd->qd_count); } static void qd_put(struct gfs2_quota_data *qd) { - struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd; - spin_lock(&sdp->sd_quota_spin); - gfs2_assert(sdp, qd->qd_count); - if (!--qd->qd_count) - qd->qd_last_touched = jiffies; - spin_unlock(&sdp->sd_quota_spin); + if (atomic_dec_and_lock(&qd->qd_count, &qd_lru_lock)) { + /* Add to the reclaim list */ + list_add_tail(&qd->qd_reclaim, &qd_lru_list); + atomic_inc(&qd_lru_count); + spin_unlock(&qd_lru_lock); + } } static int slot_get(struct gfs2_quota_data *qd) @@ -330,6 +381,7 @@ static int qd_fish(struct gfs2_sbd *sdp, struct gfs2_quota_data **qdp) if (sdp->sd_vfs->s_flags & MS_RDONLY) return 0; + spin_lock(&qd_lru_lock); spin_lock(&sdp->sd_quota_spin); list_for_each_entry(qd, &sdp->sd_quota_list, qd_list) { @@ -341,8 +393,8 @@ static int qd_fish(struct gfs2_sbd *sdp, struct gfs2_quota_data **qdp) list_move_tail(&qd->qd_list, &sdp->sd_quota_list); set_bit(QDF_LOCKED, &qd->qd_flags); - gfs2_assert_warn(sdp, qd->qd_count); - qd->qd_count++; + gfs2_assert_warn(sdp, atomic_read(&qd->qd_count)); + atomic_inc(&qd->qd_count); qd->qd_change_sync = qd->qd_change; gfs2_assert_warn(sdp, qd->qd_slot_count); qd->qd_slot_count++; @@ -355,6 +407,7 @@ static int qd_fish(struct gfs2_sbd *sdp, struct gfs2_quota_data **qdp) qd = NULL; spin_unlock(&sdp->sd_quota_spin); + spin_unlock(&qd_lru_lock); if (qd) { gfs2_assert_warn(sdp, qd->qd_change_sync); @@ -379,24 +432,27 @@ static int qd_trylock(struct gfs2_quota_data *qd) if (sdp->sd_vfs->s_flags & MS_RDONLY) return 0; + spin_lock(&qd_lru_lock); spin_lock(&sdp->sd_quota_spin); if (test_bit(QDF_LOCKED, &qd->qd_flags) || !test_bit(QDF_CHANGE, &qd->qd_flags)) { spin_unlock(&sdp->sd_quota_spin); + spin_unlock(&qd_lru_lock); return 0; } list_move_tail(&qd->qd_list, &sdp->sd_quota_list); set_bit(QDF_LOCKED, &qd->qd_flags); - gfs2_assert_warn(sdp, qd->qd_count); - qd->qd_count++; + gfs2_assert_warn(sdp, atomic_read(&qd->qd_count)); + atomic_inc(&qd->qd_count); qd->qd_change_sync = qd->qd_change; gfs2_assert_warn(sdp, qd->qd_slot_count); qd->qd_slot_count++; spin_unlock(&sdp->sd_quota_spin); + spin_unlock(&qd_lru_lock); gfs2_assert_warn(sdp, qd->qd_change_sync); if (bh_get(qd)) { @@ -802,8 +858,8 @@ restart: loff_t pos; gfs2_glock_dq_uninit(q_gh); error = gfs2_glock_nq_init(qd->qd_gl, - LM_ST_EXCLUSIVE, GL_NOCACHE, - q_gh); + LM_ST_EXCLUSIVE, GL_NOCACHE, + q_gh); if (error) return error; @@ -820,7 +876,6 @@ restart: gfs2_glock_dq_uninit(&i_gh); - gfs2_quota_in(&q, buf); qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb; qlvb->qb_magic = cpu_to_be32(GFS2_MAGIC); @@ -1171,13 +1226,14 @@ int gfs2_quota_init(struct gfs2_sbd *sdp) qd->qd_change = qc.qc_change; qd->qd_slot = slot; qd->qd_slot_count = 1; - qd->qd_last_touched = jiffies; + spin_lock(&qd_lru_lock); spin_lock(&sdp->sd_quota_spin); gfs2_icbit_munge(sdp, sdp->sd_quota_bitmap, slot, 1); + spin_unlock(&sdp->sd_quota_spin); list_add(&qd->qd_list, &sdp->sd_quota_list); atomic_inc(&sdp->sd_quota_count); - spin_unlock(&sdp->sd_quota_spin); + spin_unlock(&qd_lru_lock); found++; } @@ -1197,61 +1253,39 @@ fail: return error; } -static void gfs2_quota_scan(struct gfs2_sbd *sdp) -{ - struct gfs2_quota_data *qd, *safe; - LIST_HEAD(dead); - - spin_lock(&sdp->sd_quota_spin); - list_for_each_entry_safe(qd, safe, &sdp->sd_quota_list, qd_list) { - if (!qd->qd_count && - time_after_eq(jiffies, qd->qd_last_touched + - gfs2_tune_get(sdp, gt_quota_cache_secs) * HZ)) { - list_move(&qd->qd_list, &dead); - gfs2_assert_warn(sdp, - atomic_read(&sdp->sd_quota_count) > 0); - atomic_dec(&sdp->sd_quota_count); - } - } - spin_unlock(&sdp->sd_quota_spin); - - while (!list_empty(&dead)) { - qd = list_entry(dead.next, struct gfs2_quota_data, qd_list); - list_del(&qd->qd_list); - - gfs2_assert_warn(sdp, !qd->qd_change); - gfs2_assert_warn(sdp, !qd->qd_slot_count); - gfs2_assert_warn(sdp, !qd->qd_bh_count); - - gfs2_lvb_unhold(qd->qd_gl); - kmem_cache_free(gfs2_quotad_cachep, qd); - } -} - void gfs2_quota_cleanup(struct gfs2_sbd *sdp) { struct list_head *head = &sdp->sd_quota_list; struct gfs2_quota_data *qd; unsigned int x; - spin_lock(&sdp->sd_quota_spin); + spin_lock(&qd_lru_lock); while (!list_empty(head)) { qd = list_entry(head->prev, struct gfs2_quota_data, qd_list); - if (qd->qd_count > 1 || - (qd->qd_count && !test_bit(QDF_CHANGE, &qd->qd_flags))) { - list_move(&qd->qd_list, head); + spin_lock(&sdp->sd_quota_spin); + if (atomic_read(&qd->qd_count) > 1 || + (atomic_read(&qd->qd_count) && + !test_bit(QDF_CHANGE, &qd->qd_flags))) { spin_unlock(&sdp->sd_quota_spin); + list_move(&qd->qd_list, head); + spin_unlock(&qd_lru_lock); schedule(); - spin_lock(&sdp->sd_quota_spin); + spin_lock(&qd_lru_lock); continue; } + spin_unlock(&sdp->sd_quota_spin); list_del(&qd->qd_list); + /* Also remove if this qd exists in the reclaim list */ + if (!list_empty(&qd->qd_reclaim)) { + list_del_init(&qd->qd_reclaim); + atomic_dec(&qd_lru_count); + } atomic_dec(&sdp->sd_quota_count); - spin_unlock(&sdp->sd_quota_spin); + spin_unlock(&qd_lru_lock); - if (!qd->qd_count) { + if (!atomic_read(&qd->qd_count)) { gfs2_assert_warn(sdp, !qd->qd_change); gfs2_assert_warn(sdp, !qd->qd_slot_count); } else @@ -1261,9 +1295,9 @@ void gfs2_quota_cleanup(struct gfs2_sbd *sdp) gfs2_lvb_unhold(qd->qd_gl); kmem_cache_free(gfs2_quotad_cachep, qd); - spin_lock(&sdp->sd_quota_spin); + spin_lock(&qd_lru_lock); } - spin_unlock(&sdp->sd_quota_spin); + spin_unlock(&qd_lru_lock); gfs2_assert_warn(sdp, !atomic_read(&sdp->sd_quota_count)); @@ -1341,9 +1375,6 @@ int gfs2_quotad(void *data) quotad_check_timeo(sdp, "sync", gfs2_quota_sync, t, "ad_timeo, &tune->gt_quota_quantum); - /* FIXME: This should be turned into a shrinker */ - gfs2_quota_scan(sdp); - /* Check for & recover partially truncated inodes */ quotad_check_trunc_list(sdp); diff --git a/fs/gfs2/quota.h b/fs/gfs2/quota.h index cec9032be97..0fa5fa63d0e 100644 --- a/fs/gfs2/quota.h +++ b/fs/gfs2/quota.h @@ -49,4 +49,6 @@ static inline int gfs2_quota_lock_check(struct gfs2_inode *ip) return ret; } +extern int gfs2_shrink_qd_memory(int nr, gfp_t gfp_mask); + #endif /* __QUOTA_DOT_H__ */ diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index 26c1fa777a9..a58a120dac9 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c @@ -373,7 +373,6 @@ TUNE_ATTR(complain_secs, 0); TUNE_ATTR(statfs_slow, 0); TUNE_ATTR(new_files_jdata, 0); TUNE_ATTR(quota_simul_sync, 1); -TUNE_ATTR(quota_cache_secs, 1); TUNE_ATTR(stall_secs, 1); TUNE_ATTR(statfs_quantum, 1); TUNE_ATTR_DAEMON(recoverd_secs, recoverd_process); @@ -389,7 +388,6 @@ static struct attribute *tune_attrs[] = { &tune_attr_complain_secs.attr, &tune_attr_statfs_slow.attr, &tune_attr_quota_simul_sync.attr, - &tune_attr_quota_cache_secs.attr, &tune_attr_stall_secs.attr, &tune_attr_statfs_quantum.attr, &tune_attr_recoverd_secs.attr, -- GitLab From 22077f57dec8fcbeb1112b35313961c0902ff038 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Thu, 8 Jan 2009 14:28:42 +0000 Subject: [PATCH 4137/4982] GFS2: Remove "double" locking in quota We only really need a single spin lock for the quota data, so lets just use the lru lock for now. Signed-off-by: Steven Whitehouse Cc: Abhijith Das --- fs/gfs2/incore.h | 1 - fs/gfs2/ops_fstype.c | 1 - fs/gfs2/quota.c | 40 ++++++++++++++-------------------------- 3 files changed, 14 insertions(+), 28 deletions(-) diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 592aa5040d2..a0117d6eb14 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -540,7 +540,6 @@ struct gfs2_sbd { struct list_head sd_quota_list; atomic_t sd_quota_count; - spinlock_t sd_quota_spin; struct mutex sd_quota_mutex; wait_queue_head_t sd_quota_wait; struct list_head sd_trunc_list; diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 530d3f6f6ea..402b6a2cd2c 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -98,7 +98,6 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) mutex_init(&sdp->sd_jindex_mutex); INIT_LIST_HEAD(&sdp->sd_quota_list); - spin_lock_init(&sdp->sd_quota_spin); mutex_init(&sdp->sd_quota_mutex); init_waitqueue_head(&sdp->sd_quota_wait); INIT_LIST_HEAD(&sdp->sd_trunc_list); diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 2ada6e10d07..e8ef0f80fb1 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -104,13 +104,11 @@ int gfs2_shrink_qd_memory(int nr, gfp_t gfp_mask) /* Free from the filesystem-specific list */ list_del(&qd->qd_list); - spin_lock(&sdp->sd_quota_spin); gfs2_assert_warn(sdp, !qd->qd_change); gfs2_assert_warn(sdp, !qd->qd_slot_count); gfs2_assert_warn(sdp, !qd->qd_bh_count); gfs2_lvb_unhold(qd->qd_gl); - spin_unlock(&sdp->sd_quota_spin); atomic_dec(&sdp->sd_quota_count); /* Delete it from the common reclaim list */ @@ -249,10 +247,10 @@ static int slot_get(struct gfs2_quota_data *qd) unsigned int c, o = 0, b; unsigned char byte = 0; - spin_lock(&sdp->sd_quota_spin); + spin_lock(&qd_lru_lock); if (qd->qd_slot_count++) { - spin_unlock(&sdp->sd_quota_spin); + spin_unlock(&qd_lru_lock); return 0; } @@ -276,13 +274,13 @@ found: sdp->sd_quota_bitmap[c][o] |= 1 << b; - spin_unlock(&sdp->sd_quota_spin); + spin_unlock(&qd_lru_lock); return 0; fail: qd->qd_slot_count--; - spin_unlock(&sdp->sd_quota_spin); + spin_unlock(&qd_lru_lock); return -ENOSPC; } @@ -290,23 +288,23 @@ static void slot_hold(struct gfs2_quota_data *qd) { struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd; - spin_lock(&sdp->sd_quota_spin); + spin_lock(&qd_lru_lock); gfs2_assert(sdp, qd->qd_slot_count); qd->qd_slot_count++; - spin_unlock(&sdp->sd_quota_spin); + spin_unlock(&qd_lru_lock); } static void slot_put(struct gfs2_quota_data *qd) { struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd; - spin_lock(&sdp->sd_quota_spin); + spin_lock(&qd_lru_lock); gfs2_assert(sdp, qd->qd_slot_count); if (!--qd->qd_slot_count) { gfs2_icbit_munge(sdp, sdp->sd_quota_bitmap, qd->qd_slot, 0); qd->qd_slot = -1; } - spin_unlock(&sdp->sd_quota_spin); + spin_unlock(&qd_lru_lock); } static int bh_get(struct gfs2_quota_data *qd) @@ -382,7 +380,6 @@ static int qd_fish(struct gfs2_sbd *sdp, struct gfs2_quota_data **qdp) return 0; spin_lock(&qd_lru_lock); - spin_lock(&sdp->sd_quota_spin); list_for_each_entry(qd, &sdp->sd_quota_list, qd_list) { if (test_bit(QDF_LOCKED, &qd->qd_flags) || @@ -406,7 +403,6 @@ static int qd_fish(struct gfs2_sbd *sdp, struct gfs2_quota_data **qdp) if (!found) qd = NULL; - spin_unlock(&sdp->sd_quota_spin); spin_unlock(&qd_lru_lock); if (qd) { @@ -433,11 +429,9 @@ static int qd_trylock(struct gfs2_quota_data *qd) return 0; spin_lock(&qd_lru_lock); - spin_lock(&sdp->sd_quota_spin); if (test_bit(QDF_LOCKED, &qd->qd_flags) || !test_bit(QDF_CHANGE, &qd->qd_flags)) { - spin_unlock(&sdp->sd_quota_spin); spin_unlock(&qd_lru_lock); return 0; } @@ -451,7 +445,6 @@ static int qd_trylock(struct gfs2_quota_data *qd) gfs2_assert_warn(sdp, qd->qd_slot_count); qd->qd_slot_count++; - spin_unlock(&sdp->sd_quota_spin); spin_unlock(&qd_lru_lock); gfs2_assert_warn(sdp, qd->qd_change_sync); @@ -612,9 +605,9 @@ static void do_qc(struct gfs2_quota_data *qd, s64 change) x = be64_to_cpu(qc->qc_change) + change; qc->qc_change = cpu_to_be64(x); - spin_lock(&sdp->sd_quota_spin); + spin_lock(&qd_lru_lock); qd->qd_change = x; - spin_unlock(&sdp->sd_quota_spin); + spin_unlock(&qd_lru_lock); if (!x) { gfs2_assert_warn(sdp, test_bit(QDF_CHANGE, &qd->qd_flags)); @@ -945,9 +938,9 @@ static int need_sync(struct gfs2_quota_data *qd) if (!qd->qd_qb.qb_limit) return 0; - spin_lock(&sdp->sd_quota_spin); + spin_lock(&qd_lru_lock); value = qd->qd_change; - spin_unlock(&sdp->sd_quota_spin); + spin_unlock(&qd_lru_lock); spin_lock(>->gt_spin); num = gt->gt_quota_scale_num; @@ -1040,9 +1033,9 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid) continue; value = (s64)be64_to_cpu(qd->qd_qb.qb_value); - spin_lock(&sdp->sd_quota_spin); + spin_lock(&qd_lru_lock); value += qd->qd_change; - spin_unlock(&sdp->sd_quota_spin); + spin_unlock(&qd_lru_lock); if (be64_to_cpu(qd->qd_qb.qb_limit) && (s64)be64_to_cpu(qd->qd_qb.qb_limit) < value) { print_message(qd, "exceeded"); @@ -1228,9 +1221,7 @@ int gfs2_quota_init(struct gfs2_sbd *sdp) qd->qd_slot_count = 1; spin_lock(&qd_lru_lock); - spin_lock(&sdp->sd_quota_spin); gfs2_icbit_munge(sdp, sdp->sd_quota_bitmap, slot, 1); - spin_unlock(&sdp->sd_quota_spin); list_add(&qd->qd_list, &sdp->sd_quota_list); atomic_inc(&sdp->sd_quota_count); spin_unlock(&qd_lru_lock); @@ -1263,18 +1254,15 @@ void gfs2_quota_cleanup(struct gfs2_sbd *sdp) while (!list_empty(head)) { qd = list_entry(head->prev, struct gfs2_quota_data, qd_list); - spin_lock(&sdp->sd_quota_spin); if (atomic_read(&qd->qd_count) > 1 || (atomic_read(&qd->qd_count) && !test_bit(QDF_CHANGE, &qd->qd_flags))) { - spin_unlock(&sdp->sd_quota_spin); list_move(&qd->qd_list, head); spin_unlock(&qd_lru_lock); schedule(); spin_lock(&qd_lru_lock); continue; } - spin_unlock(&sdp->sd_quota_spin); list_del(&qd->qd_list); /* Also remove if this qd exists in the reclaim list */ -- GitLab From f057f6cdf64175db1151b1f5d110e29904f119a1 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Mon, 12 Jan 2009 10:43:39 +0000 Subject: [PATCH 4138/4982] GFS2: Merge lock_dlm module into GFS2 This is the big patch that I've been working on for some time now. There are many reasons for wanting to make this change such as: o Reducing overhead by eliminating duplicated fields between structures o Simplifcation of the code (reduces the code size by a fair bit) o The locking interface is now the DLM interface itself as proposed some time ago. o Fewer lookups of glocks when processing replies from the DLM o Fewer memory allocations/deallocations for each glock o Scope to do further optimisations in the future (but this patch is more than big enough for now!) Please note that (a) this patch relates to the lock_dlm module and not the DLM itself, that is still a separate module; and (b) that we retain the ability to build GFS2 as a standalone single node filesystem with out requiring the DLM. This patch needs a lot of testing, hence my keeping it I restarted my -git tree after the last merge window. That way, this has the maximum exposure before its merged. This is (modulo a few minor bug fixes) the same patch that I've been posting on and off the the last three months and its passed a number of different tests so far. Signed-off-by: Steven Whitehouse --- fs/gfs2/Kconfig | 17 +- fs/gfs2/Makefile | 4 +- fs/gfs2/acl.c | 1 - fs/gfs2/bmap.c | 1 - fs/gfs2/dir.c | 1 - fs/gfs2/eaops.c | 1 - fs/gfs2/eattr.c | 1 - fs/gfs2/glock.c | 249 ++++-------- fs/gfs2/glock.h | 127 +++++- fs/gfs2/glops.c | 14 - fs/gfs2/incore.h | 59 ++- fs/gfs2/inode.c | 13 +- fs/gfs2/inode.h | 22 +- fs/gfs2/lock_dlm.c | 240 +++++++++++ fs/gfs2/locking.c | 314 --------------- fs/gfs2/locking/dlm/Makefile | 3 - fs/gfs2/locking/dlm/lock.c | 708 --------------------------------- fs/gfs2/locking/dlm/lock_dlm.h | 166 -------- fs/gfs2/locking/dlm/main.c | 48 --- fs/gfs2/locking/dlm/mount.c | 276 ------------- fs/gfs2/locking/dlm/sysfs.c | 226 ----------- fs/gfs2/locking/dlm/thread.c | 68 ---- fs/gfs2/log.c | 1 - fs/gfs2/lops.c | 1 - fs/gfs2/main.c | 3 - fs/gfs2/meta_io.c | 1 - fs/gfs2/mount.c | 1 - fs/gfs2/ops_address.c | 1 - fs/gfs2/ops_dentry.c | 1 - fs/gfs2/ops_export.c | 1 - fs/gfs2/ops_file.c | 74 +--- fs/gfs2/ops_fstype.c | 134 +++++-- fs/gfs2/ops_inode.c | 1 - fs/gfs2/ops_super.c | 1 - fs/gfs2/quota.c | 12 +- fs/gfs2/recovery.c | 28 +- fs/gfs2/rgrp.c | 1 - fs/gfs2/super.c | 1 - fs/gfs2/sys.c | 154 ++++++- fs/gfs2/trans.c | 3 +- fs/gfs2/util.c | 11 +- include/linux/lm_interface.h | 277 ------------- 42 files changed, 819 insertions(+), 2447 deletions(-) create mode 100644 fs/gfs2/lock_dlm.c delete mode 100644 fs/gfs2/locking.c delete mode 100644 fs/gfs2/locking/dlm/Makefile delete mode 100644 fs/gfs2/locking/dlm/lock.c delete mode 100644 fs/gfs2/locking/dlm/lock_dlm.h delete mode 100644 fs/gfs2/locking/dlm/main.c delete mode 100644 fs/gfs2/locking/dlm/mount.c delete mode 100644 fs/gfs2/locking/dlm/sysfs.c delete mode 100644 fs/gfs2/locking/dlm/thread.c delete mode 100644 include/linux/lm_interface.h diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig index e563a644981..3a981b7f64c 100644 --- a/fs/gfs2/Kconfig +++ b/fs/gfs2/Kconfig @@ -1,6 +1,10 @@ config GFS2_FS tristate "GFS2 file system support" depends on EXPERIMENTAL && (64BIT || LBD) + select DLM if GFS2_FS_LOCKING_DLM + select CONFIGFS_FS if GFS2_FS_LOCKING_DLM + select SYSFS if GFS2_FS_LOCKING_DLM + select IP_SCTP if DLM_SCTP select FS_POSIX_ACL select CRC32 help @@ -18,17 +22,16 @@ config GFS2_FS the locking module below. Documentation and utilities for GFS2 can be found here: http://sources.redhat.com/cluster - The "nolock" lock module is now built in to GFS2 by default. + The "nolock" lock module is now built in to GFS2 by default. If + you want to use the DLM, be sure to enable HOTPLUG and IPv4/6 + networking. config GFS2_FS_LOCKING_DLM - tristate "GFS2 DLM locking module" - depends on GFS2_FS && SYSFS && NET && INET && (IPV6 || IPV6=n) - select IP_SCTP if DLM_SCTP - select CONFIGFS_FS - select DLM + bool "GFS2 DLM locking" + depends on (GFS2_FS!=n) && NET && INET && (IPV6 || IPV6=n) && HOTPLUG help Multiple node locking module for GFS2 - Most users of GFS2 will require this module. It provides the locking + Most users of GFS2 will require this. It provides the locking interface between GFS2 and the DLM, which is required to use GFS2 in a cluster environment. diff --git a/fs/gfs2/Makefile b/fs/gfs2/Makefile index c1b4ec6a965..a851ea4bdf7 100644 --- a/fs/gfs2/Makefile +++ b/fs/gfs2/Makefile @@ -1,9 +1,9 @@ obj-$(CONFIG_GFS2_FS) += gfs2.o gfs2-y := acl.o bmap.o dir.o eaops.o eattr.o glock.o \ - glops.o inode.o log.o lops.o locking.o main.o meta_io.o \ + glops.o inode.o log.o lops.o main.o meta_io.o \ mount.o ops_address.o ops_dentry.o ops_export.o ops_file.o \ ops_fstype.o ops_inode.o ops_super.o quota.o \ recovery.o rgrp.o super.o sys.o trans.o util.o -obj-$(CONFIG_GFS2_FS_LOCKING_DLM) += locking/dlm/ +gfs2-$(CONFIG_GFS2_FS_LOCKING_DLM) += lock_dlm.o diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c index e335dceb6a4..43764f4fa76 100644 --- a/fs/gfs2/acl.c +++ b/fs/gfs2/acl.c @@ -15,7 +15,6 @@ #include #include #include -#include #include "gfs2.h" #include "incore.h" diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 11ffc56f1f8..3a5d3f883e1 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -13,7 +13,6 @@ #include #include #include -#include #include "gfs2.h" #include "incore.h" diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index b7c8e5c7079..aef4d0c0674 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -60,7 +60,6 @@ #include #include #include -#include #include "gfs2.h" #include "incore.h" diff --git a/fs/gfs2/eaops.c b/fs/gfs2/eaops.c index f114ba2b355..dee9b03e5b3 100644 --- a/fs/gfs2/eaops.c +++ b/fs/gfs2/eaops.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include "gfs2.h" diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c index 0d1c76d906a..899763aed21 100644 --- a/fs/gfs2/eattr.c +++ b/fs/gfs2/eattr.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include "gfs2.h" diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 6b983aef785..cd200a564c7 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -18,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -155,13 +153,10 @@ static void glock_free(struct gfs2_glock *gl) struct gfs2_sbd *sdp = gl->gl_sbd; struct inode *aspace = gl->gl_aspace; - if (sdp->sd_lockstruct.ls_ops->lm_put_lock) - sdp->sd_lockstruct.ls_ops->lm_put_lock(gl->gl_lock); - if (aspace) gfs2_aspace_put(aspace); - kmem_cache_free(gfs2_glock_cachep, gl); + sdp->sd_lockstruct.ls_ops->lm_put_lock(gfs2_glock_cachep, gl); } /** @@ -211,7 +206,6 @@ int gfs2_glock_put(struct gfs2_glock *gl) atomic_dec(&lru_count); } spin_unlock(&lru_lock); - GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_UNLOCKED); GLOCK_BUG_ON(gl, !list_empty(&gl->gl_lru)); GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders)); glock_free(gl); @@ -255,27 +249,6 @@ static struct gfs2_glock *search_bucket(unsigned int hash, return NULL; } -/** - * gfs2_glock_find() - Find glock by lock number - * @sdp: The GFS2 superblock - * @name: The lock name - * - * Returns: NULL, or the struct gfs2_glock with the requested number - */ - -static struct gfs2_glock *gfs2_glock_find(const struct gfs2_sbd *sdp, - const struct lm_lockname *name) -{ - unsigned int hash = gl_hash(sdp, name); - struct gfs2_glock *gl; - - read_lock(gl_lock_addr(hash)); - gl = search_bucket(hash, sdp, name); - read_unlock(gl_lock_addr(hash)); - - return gl; -} - /** * may_grant - check if its ok to grant a new lock * @gl: The glock @@ -523,7 +496,7 @@ out_locked: } static unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock, - unsigned int cur_state, unsigned int req_state, + unsigned int req_state, unsigned int flags) { int ret = LM_OUT_ERROR; @@ -532,7 +505,7 @@ static unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock, return req_state == LM_ST_UNLOCKED ? 0 : req_state; if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) - ret = sdp->sd_lockstruct.ls_ops->lm_lock(lock, cur_state, + ret = sdp->sd_lockstruct.ls_ops->lm_lock(lock, req_state, flags); return ret; } @@ -575,7 +548,7 @@ __acquires(&gl->gl_spin) gl->gl_state == LM_ST_DEFERRED) && !(lck_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))) lck_flags |= LM_FLAG_TRY_1CB; - ret = gfs2_lm_lock(sdp, gl->gl_lock, gl->gl_state, target, lck_flags); + ret = gfs2_lm_lock(sdp, gl, target, lck_flags); if (!(ret & LM_OUT_ASYNC)) { finish_xmote(gl, ret); @@ -681,18 +654,6 @@ static void glock_work_func(struct work_struct *work) gfs2_glock_put(gl); } -static int gfs2_lm_get_lock(struct gfs2_sbd *sdp, struct lm_lockname *name, - void **lockp) -{ - int error = -EIO; - if (!sdp->sd_lockstruct.ls_ops->lm_get_lock) - return 0; - if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) - error = sdp->sd_lockstruct.ls_ops->lm_get_lock( - sdp->sd_lockstruct.ls_lockspace, name, lockp); - return error; -} - /** * gfs2_glock_get() - Get a glock, or create one if one doesn't exist * @sdp: The GFS2 superblock @@ -736,6 +697,9 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, gl->gl_demote_state = LM_ST_EXCLUSIVE; gl->gl_hash = hash; gl->gl_ops = glops; + snprintf(gl->gl_strname, GDLM_STRNAME_BYTES, "%8x%16llx", name.ln_type, (unsigned long long)number); + memset(&gl->gl_lksb, 0, sizeof(struct dlm_lksb)); + gl->gl_lksb.sb_lvbptr = gl->gl_lvb; gl->gl_stamp = jiffies; gl->gl_tchange = jiffies; gl->gl_object = NULL; @@ -753,10 +717,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, } } - error = gfs2_lm_get_lock(sdp, &name, &gl->gl_lock); - if (error) - goto fail_aspace; - write_lock(gl_lock_addr(hash)); tmp = search_bucket(hash, sdp, &name); if (tmp) { @@ -772,9 +732,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, return 0; -fail_aspace: - if (gl->gl_aspace) - gfs2_aspace_put(gl->gl_aspace); fail: kmem_cache_free(gfs2_glock_cachep, gl); return error; @@ -966,7 +923,7 @@ do_cancel: if (!(gh->gh_flags & LM_FLAG_PRIORITY)) { spin_unlock(&gl->gl_spin); if (sdp->sd_lockstruct.ls_ops->lm_cancel) - sdp->sd_lockstruct.ls_ops->lm_cancel(gl->gl_lock); + sdp->sd_lockstruct.ls_ops->lm_cancel(gl); spin_lock(&gl->gl_spin); } return; @@ -1240,70 +1197,13 @@ void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs) gfs2_glock_dq_uninit(&ghs[x]); } -static int gfs2_lm_hold_lvb(struct gfs2_sbd *sdp, void *lock, char **lvbp) +void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state) { - int error = -EIO; - if (!sdp->sd_lockstruct.ls_ops->lm_hold_lvb) - return 0; - if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) - error = sdp->sd_lockstruct.ls_ops->lm_hold_lvb(lock, lvbp); - return error; -} - -/** - * gfs2_lvb_hold - attach a LVB from a glock - * @gl: The glock in question - * - */ - -int gfs2_lvb_hold(struct gfs2_glock *gl) -{ - int error; - - if (!atomic_read(&gl->gl_lvb_count)) { - error = gfs2_lm_hold_lvb(gl->gl_sbd, gl->gl_lock, &gl->gl_lvb); - if (error) - return error; - gfs2_glock_hold(gl); - } - atomic_inc(&gl->gl_lvb_count); - - return 0; -} - -/** - * gfs2_lvb_unhold - detach a LVB from a glock - * @gl: The glock in question - * - */ - -void gfs2_lvb_unhold(struct gfs2_glock *gl) -{ - struct gfs2_sbd *sdp = gl->gl_sbd; - - gfs2_glock_hold(gl); - gfs2_assert(gl->gl_sbd, atomic_read(&gl->gl_lvb_count) > 0); - if (atomic_dec_and_test(&gl->gl_lvb_count)) { - if (sdp->sd_lockstruct.ls_ops->lm_unhold_lvb) - sdp->sd_lockstruct.ls_ops->lm_unhold_lvb(gl->gl_lock, gl->gl_lvb); - gl->gl_lvb = NULL; - gfs2_glock_put(gl); - } - gfs2_glock_put(gl); -} - -static void blocking_cb(struct gfs2_sbd *sdp, struct lm_lockname *name, - unsigned int state) -{ - struct gfs2_glock *gl; unsigned long delay = 0; unsigned long holdtime; unsigned long now = jiffies; - gl = gfs2_glock_find(sdp, name); - if (!gl) - return; - + gfs2_glock_hold(gl); holdtime = gl->gl_tchange + gl->gl_ops->go_min_hold_time; if (time_before(now, holdtime)) delay = holdtime - now; @@ -1317,74 +1217,37 @@ static void blocking_cb(struct gfs2_sbd *sdp, struct lm_lockname *name, gfs2_glock_put(gl); } -static void gfs2_jdesc_make_dirty(struct gfs2_sbd *sdp, unsigned int jid) -{ - struct gfs2_jdesc *jd; - - spin_lock(&sdp->sd_jindex_spin); - list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) { - if (jd->jd_jid != jid) - continue; - jd->jd_dirty = 1; - break; - } - spin_unlock(&sdp->sd_jindex_spin); -} - /** - * gfs2_glock_cb - Callback used by locking module - * @sdp: Pointer to the superblock - * @type: Type of callback - * @data: Type dependent data pointer + * gfs2_glock_complete - Callback used by locking + * @gl: Pointer to the glock + * @ret: The return value from the dlm * - * Called by the locking module when it wants to tell us something. - * Either we need to drop a lock, one of our ASYNC requests completed, or - * a journal from another client needs to be recovered. */ -void gfs2_glock_cb(void *cb_data, unsigned int type, void *data) +void gfs2_glock_complete(struct gfs2_glock *gl, int ret) { - struct gfs2_sbd *sdp = cb_data; - - switch (type) { - case LM_CB_NEED_E: - blocking_cb(sdp, data, LM_ST_UNLOCKED); - return; - - case LM_CB_NEED_D: - blocking_cb(sdp, data, LM_ST_DEFERRED); - return; - - case LM_CB_NEED_S: - blocking_cb(sdp, data, LM_ST_SHARED); - return; - - case LM_CB_ASYNC: { - struct lm_async_cb *async = data; - struct gfs2_glock *gl; - - down_read(&gfs2_umount_flush_sem); - gl = gfs2_glock_find(sdp, &async->lc_name); - if (gfs2_assert_warn(sdp, gl)) + struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct; + down_read(&gfs2_umount_flush_sem); + gl->gl_reply = ret; + if (unlikely(test_bit(DFL_BLOCK_LOCKS, &ls->ls_flags))) { + struct gfs2_holder *gh; + spin_lock(&gl->gl_spin); + gh = find_first_waiter(gl); + if ((!(gh && (gh->gh_flags & LM_FLAG_NOEXP)) && + (gl->gl_target != LM_ST_UNLOCKED)) || + ((ret & ~LM_OUT_ST_MASK) != 0)) + set_bit(GLF_FROZEN, &gl->gl_flags); + spin_unlock(&gl->gl_spin); + if (test_bit(GLF_FROZEN, &gl->gl_flags)) { + up_read(&gfs2_umount_flush_sem); return; - gl->gl_reply = async->lc_ret; - set_bit(GLF_REPLY_PENDING, &gl->gl_flags); - if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) - gfs2_glock_put(gl); - up_read(&gfs2_umount_flush_sem); - return; - } - - case LM_CB_NEED_RECOVERY: - gfs2_jdesc_make_dirty(sdp, *(unsigned int *)data); - if (sdp->sd_recoverd_process) - wake_up_process(sdp->sd_recoverd_process); - return; - - default: - gfs2_assert_warn(sdp, 0); - return; + } } + set_bit(GLF_REPLY_PENDING, &gl->gl_flags); + gfs2_glock_hold(gl); + if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) + gfs2_glock_put(gl); + up_read(&gfs2_umount_flush_sem); } /** @@ -1515,6 +1378,27 @@ out: return has_entries; } + +/** + * thaw_glock - thaw out a glock which has an unprocessed reply waiting + * @gl: The glock to thaw + * + * N.B. When we freeze a glock, we leave a ref to the glock outstanding, + * so this has to result in the ref count being dropped by one. + */ + +static void thaw_glock(struct gfs2_glock *gl) +{ + if (!test_and_clear_bit(GLF_FROZEN, &gl->gl_flags)) + return; + down_read(&gfs2_umount_flush_sem); + set_bit(GLF_REPLY_PENDING, &gl->gl_flags); + gfs2_glock_hold(gl); + if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) + gfs2_glock_put(gl); + up_read(&gfs2_umount_flush_sem); +} + /** * clear_glock - look at a glock and see if we can free it from glock cache * @gl: the glock to look at @@ -1539,6 +1423,20 @@ static void clear_glock(struct gfs2_glock *gl) gfs2_glock_put(gl); } +/** + * gfs2_glock_thaw - Thaw any frozen glocks + * @sdp: The super block + * + */ + +void gfs2_glock_thaw(struct gfs2_sbd *sdp) +{ + unsigned x; + + for (x = 0; x < GFS2_GL_HASH_SIZE; x++) + examine_bucket(thaw_glock, sdp, x); +} + /** * gfs2_gl_hash_clear - Empty out the glock hash table * @sdp: the filesystem @@ -1619,7 +1517,7 @@ static const char *hflags2str(char *buf, unsigned flags, unsigned long iflags) if (flags & LM_FLAG_NOEXP) *p++ = 'e'; if (flags & LM_FLAG_ANY) - *p++ = 'a'; + *p++ = 'A'; if (flags & LM_FLAG_PRIORITY) *p++ = 'p'; if (flags & GL_ASYNC) @@ -1683,6 +1581,10 @@ static const char *gflags2str(char *buf, const unsigned long *gflags) *p++ = 'i'; if (test_bit(GLF_REPLY_PENDING, gflags)) *p++ = 'r'; + if (test_bit(GLF_INITIAL, gflags)) + *p++ = 'i'; + if (test_bit(GLF_FROZEN, gflags)) + *p++ = 'F'; *p = 0; return buf; } @@ -1717,14 +1619,13 @@ static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl) dtime *= 1000000/HZ; /* demote time in uSec */ if (!test_bit(GLF_DEMOTE, &gl->gl_flags)) dtime = 0; - gfs2_print_dbg(seq, "G: s:%s n:%u/%llu f:%s t:%s d:%s/%llu l:%d a:%d r:%d\n", + gfs2_print_dbg(seq, "G: s:%s n:%u/%llu f:%s t:%s d:%s/%llu a:%d r:%d\n", state2str(gl->gl_state), gl->gl_name.ln_type, (unsigned long long)gl->gl_name.ln_number, gflags2str(gflags_buf, &gl->gl_flags), state2str(gl->gl_target), state2str(gl->gl_demote_state), dtime, - atomic_read(&gl->gl_lvb_count), atomic_read(&gl->gl_ail_count), atomic_read(&gl->gl_ref)); diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index 543ec7ecfbd..a602a28f6f0 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h @@ -11,15 +11,130 @@ #define __GLOCK_DOT_H__ #include +#include #include "incore.h" -/* Flags for lock requests; used in gfs2_holder gh_flag field. - From lm_interface.h: +/* Options for hostdata parser */ + +enum { + Opt_jid, + Opt_id, + Opt_first, + Opt_nodir, + Opt_err, +}; + +/* + * lm_lockname types + */ + +#define LM_TYPE_RESERVED 0x00 +#define LM_TYPE_NONDISK 0x01 +#define LM_TYPE_INODE 0x02 +#define LM_TYPE_RGRP 0x03 +#define LM_TYPE_META 0x04 +#define LM_TYPE_IOPEN 0x05 +#define LM_TYPE_FLOCK 0x06 +#define LM_TYPE_PLOCK 0x07 +#define LM_TYPE_QUOTA 0x08 +#define LM_TYPE_JOURNAL 0x09 + +/* + * lm_lock() states + * + * SHARED is compatible with SHARED, not with DEFERRED or EX. + * DEFERRED is compatible with DEFERRED, not with SHARED or EX. + */ + +#define LM_ST_UNLOCKED 0 +#define LM_ST_EXCLUSIVE 1 +#define LM_ST_DEFERRED 2 +#define LM_ST_SHARED 3 + +/* + * lm_lock() flags + * + * LM_FLAG_TRY + * Don't wait to acquire the lock if it can't be granted immediately. + * + * LM_FLAG_TRY_1CB + * Send one blocking callback if TRY is set and the lock is not granted. + * + * LM_FLAG_NOEXP + * GFS sets this flag on lock requests it makes while doing journal recovery. + * These special requests should not be blocked due to the recovery like + * ordinary locks would be. + * + * LM_FLAG_ANY + * A SHARED request may also be granted in DEFERRED, or a DEFERRED request may + * also be granted in SHARED. The preferred state is whichever is compatible + * with other granted locks, or the specified state if no other locks exist. + * + * LM_FLAG_PRIORITY + * Override fairness considerations. Suppose a lock is held in a shared state + * and there is a pending request for the deferred state. A shared lock + * request with the priority flag would be allowed to bypass the deferred + * request and directly join the other shared lock. A shared lock request + * without the priority flag might be forced to wait until the deferred + * requested had acquired and released the lock. + */ + #define LM_FLAG_TRY 0x00000001 #define LM_FLAG_TRY_1CB 0x00000002 #define LM_FLAG_NOEXP 0x00000004 #define LM_FLAG_ANY 0x00000008 -#define LM_FLAG_PRIORITY 0x00000010 */ +#define LM_FLAG_PRIORITY 0x00000010 +#define GL_ASYNC 0x00000040 +#define GL_EXACT 0x00000080 +#define GL_SKIP 0x00000100 +#define GL_ATIME 0x00000200 +#define GL_NOCACHE 0x00000400 + +/* + * lm_lock() and lm_async_cb return flags + * + * LM_OUT_ST_MASK + * Masks the lower two bits of lock state in the returned value. + * + * LM_OUT_CANCELED + * The lock request was canceled. + * + * LM_OUT_ASYNC + * The result of the request will be returned in an LM_CB_ASYNC callback. + * + */ + +#define LM_OUT_ST_MASK 0x00000003 +#define LM_OUT_CANCELED 0x00000008 +#define LM_OUT_ASYNC 0x00000080 +#define LM_OUT_ERROR 0x00000100 + +/* + * lm_recovery_done() messages + */ + +#define LM_RD_GAVEUP 308 +#define LM_RD_SUCCESS 309 + +#define GLR_TRYFAILED 13 + +struct lm_lockops { + const char *lm_proto_name; + int (*lm_mount) (struct gfs2_sbd *sdp, const char *fsname); + void (*lm_unmount) (struct gfs2_sbd *sdp); + void (*lm_withdraw) (struct gfs2_sbd *sdp); + void (*lm_put_lock) (struct kmem_cache *cachep, void *gl); + unsigned int (*lm_lock) (struct gfs2_glock *gl, + unsigned int req_state, unsigned int flags); + void (*lm_cancel) (struct gfs2_glock *gl); + const match_table_t *lm_tokens; +}; + +#define LM_FLAG_TRY 0x00000001 +#define LM_FLAG_TRY_1CB 0x00000002 +#define LM_FLAG_NOEXP 0x00000004 +#define LM_FLAG_ANY 0x00000008 +#define LM_FLAG_PRIORITY 0x00000010 #define GL_ASYNC 0x00000040 #define GL_EXACT 0x00000080 @@ -128,10 +243,12 @@ static inline int gfs2_glock_nq_init(struct gfs2_glock *gl, int gfs2_lvb_hold(struct gfs2_glock *gl); void gfs2_lvb_unhold(struct gfs2_glock *gl); -void gfs2_glock_cb(void *cb_data, unsigned int type, void *data); +void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state); +void gfs2_glock_complete(struct gfs2_glock *gl, int ret); void gfs2_reclaim_glock(struct gfs2_sbd *sdp); void gfs2_gl_hash_clear(struct gfs2_sbd *sdp); void gfs2_glock_finish_truncate(struct gfs2_inode *ip); +void gfs2_glock_thaw(struct gfs2_sbd *sdp); int __init gfs2_glock_init(void); void gfs2_glock_exit(void); @@ -141,4 +258,6 @@ void gfs2_delete_debugfs_file(struct gfs2_sbd *sdp); int gfs2_register_debugfs(void); void gfs2_unregister_debugfs(void); +extern const struct lm_lockops gfs2_dlm_ops; + #endif /* __GLOCK_DOT_H__ */ diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 8522d3aa64f..f07ede8cb9b 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include "gfs2.h" @@ -390,18 +389,6 @@ static int trans_go_demote_ok(const struct gfs2_glock *gl) return 0; } -/** - * quota_go_demote_ok - Check to see if it's ok to unlock a quota glock - * @gl: the glock - * - * Returns: 1 if it's ok - */ - -static int quota_go_demote_ok(const struct gfs2_glock *gl) -{ - return !atomic_read(&gl->gl_lvb_count); -} - const struct gfs2_glock_operations gfs2_meta_glops = { .go_xmote_th = meta_go_sync, .go_type = LM_TYPE_META, @@ -448,7 +435,6 @@ const struct gfs2_glock_operations gfs2_nondisk_glops = { }; const struct gfs2_glock_operations gfs2_quota_glops = { - .go_demote_ok = quota_go_demote_ok, .go_type = LM_TYPE_QUOTA, }; diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index a0117d6eb14..0af7c24de6a 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -12,6 +12,8 @@ #include #include +#include +#include #define DIO_WAIT 0x00000010 #define DIO_METADATA 0x00000020 @@ -26,6 +28,7 @@ struct gfs2_trans; struct gfs2_ail; struct gfs2_jdesc; struct gfs2_sbd; +struct lm_lockops; typedef void (*gfs2_glop_bh_t) (struct gfs2_glock *gl, unsigned int ret); @@ -121,6 +124,28 @@ struct gfs2_bufdata { struct list_head bd_ail_gl_list; }; +/* + * Internally, we prefix things with gdlm_ and GDLM_ (for gfs-dlm) since a + * prefix of lock_dlm_ gets awkward. + */ + +#define GDLM_STRNAME_BYTES 25 +#define GDLM_LVB_SIZE 32 + +enum { + DFL_BLOCK_LOCKS = 0, +}; + +struct lm_lockname { + u64 ln_number; + unsigned int ln_type; +}; + +#define lm_name_equal(name1, name2) \ + (((name1)->ln_number == (name2)->ln_number) && \ + ((name1)->ln_type == (name2)->ln_type)) + + struct gfs2_glock_operations { void (*go_xmote_th) (struct gfs2_glock *gl); int (*go_xmote_bh) (struct gfs2_glock *gl, struct gfs2_holder *gh); @@ -162,6 +187,8 @@ enum { GLF_LFLUSH = 7, GLF_INVALIDATE_IN_PROGRESS = 8, GLF_REPLY_PENDING = 9, + GLF_INITIAL = 10, + GLF_FROZEN = 11, }; struct gfs2_glock { @@ -181,10 +208,9 @@ struct gfs2_glock { struct list_head gl_holders; const struct gfs2_glock_operations *gl_ops; - void *gl_lock; - char *gl_lvb; - atomic_t gl_lvb_count; - + char gl_strname[GDLM_STRNAME_BYTES]; + struct dlm_lksb gl_lksb; + char gl_lvb[32]; unsigned long gl_stamp; unsigned long gl_tchange; void *gl_object; @@ -447,6 +473,30 @@ struct gfs2_sb_host { char sb_locktable[GFS2_LOCKNAME_LEN]; }; +/* + * lm_mount() return values + * + * ls_jid - the journal ID this node should use + * ls_first - this node is the first to mount the file system + * ls_lockspace - lock module's context for this file system + * ls_ops - lock module's functions + */ + +struct lm_lockstruct { + u32 ls_id; + unsigned int ls_jid; + unsigned int ls_first; + unsigned int ls_first_done; + unsigned int ls_nodir; + const struct lm_lockops *ls_ops; + unsigned long ls_flags; + dlm_lockspace_t *ls_dlm; + + int ls_recover_jid; + int ls_recover_jid_done; + int ls_recover_jid_status; +}; + struct gfs2_sbd { struct super_block *sd_vfs; struct kobject sd_kobj; @@ -520,7 +570,6 @@ struct gfs2_sbd { spinlock_t sd_jindex_spin; struct mutex sd_jindex_mutex; unsigned int sd_journals; - unsigned long sd_jindex_refresh_time; struct gfs2_jdesc *sd_jdesc; struct gfs2_holder sd_journal_gh; diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 3b87c188da4..7b277d44915 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -137,16 +136,16 @@ void gfs2_set_iop(struct inode *inode) if (S_ISREG(mode)) { inode->i_op = &gfs2_file_iops; - if (sdp->sd_args.ar_localflocks) - inode->i_fop = &gfs2_file_fops_nolock; + if (gfs2_localflocks(sdp)) + inode->i_fop = gfs2_file_fops_nolock; else - inode->i_fop = &gfs2_file_fops; + inode->i_fop = gfs2_file_fops; } else if (S_ISDIR(mode)) { inode->i_op = &gfs2_dir_iops; - if (sdp->sd_args.ar_localflocks) - inode->i_fop = &gfs2_dir_fops_nolock; + if (gfs2_localflocks(sdp)) + inode->i_fop = gfs2_dir_fops_nolock; else - inode->i_fop = &gfs2_dir_fops; + inode->i_fop = gfs2_dir_fops; } else if (S_ISLNK(mode)) { inode->i_op = &gfs2_symlink_iops; } else { diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index d5329364cdf..dca4fee3078 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h @@ -101,12 +101,26 @@ void gfs2_dinode_print(const struct gfs2_inode *ip); extern const struct inode_operations gfs2_file_iops; extern const struct inode_operations gfs2_dir_iops; extern const struct inode_operations gfs2_symlink_iops; -extern const struct file_operations gfs2_file_fops; -extern const struct file_operations gfs2_dir_fops; -extern const struct file_operations gfs2_file_fops_nolock; -extern const struct file_operations gfs2_dir_fops_nolock; +extern const struct file_operations *gfs2_file_fops_nolock; +extern const struct file_operations *gfs2_dir_fops_nolock; extern void gfs2_set_inode_flags(struct inode *inode); + +#ifdef CONFIG_GFS2_FS_LOCKING_DLM +extern const struct file_operations *gfs2_file_fops; +extern const struct file_operations *gfs2_dir_fops; +static inline int gfs2_localflocks(const struct gfs2_sbd *sdp) +{ + return sdp->sd_args.ar_localflocks; +} +#else /* Single node only */ +#define gfs2_file_fops NULL +#define gfs2_dir_fops NULL +static inline int gfs2_localflocks(const struct gfs2_sbd *sdp) +{ + return 1; +} +#endif /* CONFIG_GFS2_FS_LOCKING_DLM */ #endif /* __INODE_DOT_H__ */ diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c new file mode 100644 index 00000000000..a0bb7d2251a --- /dev/null +++ b/fs/gfs2/lock_dlm.c @@ -0,0 +1,240 @@ +/* + * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. + * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License version 2. + */ + +#include +#include +#include +#include + +#include "incore.h" +#include "glock.h" +#include "util.h" + + +static void gdlm_ast(void *arg) +{ + struct gfs2_glock *gl = arg; + unsigned ret = gl->gl_state; + + BUG_ON(gl->gl_lksb.sb_flags & DLM_SBF_DEMOTED); + + if (gl->gl_lksb.sb_flags & DLM_SBF_VALNOTVALID) + memset(gl->gl_lvb, 0, GDLM_LVB_SIZE); + + switch (gl->gl_lksb.sb_status) { + case -DLM_EUNLOCK: /* Unlocked, so glock can be freed */ + kmem_cache_free(gfs2_glock_cachep, gl); + return; + case -DLM_ECANCEL: /* Cancel while getting lock */ + ret |= LM_OUT_CANCELED; + goto out; + case -EAGAIN: /* Try lock fails */ + goto out; + case -EINVAL: /* Invalid */ + case -ENOMEM: /* Out of memory */ + ret |= LM_OUT_ERROR; + goto out; + case 0: /* Success */ + break; + default: /* Something unexpected */ + BUG(); + } + + ret = gl->gl_target; + if (gl->gl_lksb.sb_flags & DLM_SBF_ALTMODE) { + if (gl->gl_target == LM_ST_SHARED) + ret = LM_ST_DEFERRED; + else if (gl->gl_target == LM_ST_DEFERRED) + ret = LM_ST_SHARED; + else + BUG(); + } + + set_bit(GLF_INITIAL, &gl->gl_flags); + gfs2_glock_complete(gl, ret); + return; +out: + if (!test_bit(GLF_INITIAL, &gl->gl_flags)) + gl->gl_lksb.sb_lkid = 0; + gfs2_glock_complete(gl, ret); +} + +static void gdlm_bast(void *arg, int mode) +{ + struct gfs2_glock *gl = arg; + + switch (mode) { + case DLM_LOCK_EX: + gfs2_glock_cb(gl, LM_ST_UNLOCKED); + break; + case DLM_LOCK_CW: + gfs2_glock_cb(gl, LM_ST_DEFERRED); + break; + case DLM_LOCK_PR: + gfs2_glock_cb(gl, LM_ST_SHARED); + break; + default: + printk(KERN_ERR "unknown bast mode %d", mode); + BUG(); + } +} + +/* convert gfs lock-state to dlm lock-mode */ + +static int make_mode(const unsigned int lmstate) +{ + switch (lmstate) { + case LM_ST_UNLOCKED: + return DLM_LOCK_NL; + case LM_ST_EXCLUSIVE: + return DLM_LOCK_EX; + case LM_ST_DEFERRED: + return DLM_LOCK_CW; + case LM_ST_SHARED: + return DLM_LOCK_PR; + } + printk(KERN_ERR "unknown LM state %d", lmstate); + BUG(); + return -1; +} + +static u32 make_flags(const u32 lkid, const unsigned int gfs_flags, + const int req) +{ + u32 lkf = 0; + + if (gfs_flags & LM_FLAG_TRY) + lkf |= DLM_LKF_NOQUEUE; + + if (gfs_flags & LM_FLAG_TRY_1CB) { + lkf |= DLM_LKF_NOQUEUE; + lkf |= DLM_LKF_NOQUEUEBAST; + } + + if (gfs_flags & LM_FLAG_PRIORITY) { + lkf |= DLM_LKF_NOORDER; + lkf |= DLM_LKF_HEADQUE; + } + + if (gfs_flags & LM_FLAG_ANY) { + if (req == DLM_LOCK_PR) + lkf |= DLM_LKF_ALTCW; + else if (req == DLM_LOCK_CW) + lkf |= DLM_LKF_ALTPR; + else + BUG(); + } + + if (lkid != 0) + lkf |= DLM_LKF_CONVERT; + + lkf |= DLM_LKF_VALBLK; + + return lkf; +} + +static unsigned int gdlm_lock(struct gfs2_glock *gl, + unsigned int req_state, unsigned int flags) +{ + struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct; + int error; + int req; + u32 lkf; + + req = make_mode(req_state); + lkf = make_flags(gl->gl_lksb.sb_lkid, flags, req); + + /* + * Submit the actual lock request. + */ + + error = dlm_lock(ls->ls_dlm, req, &gl->gl_lksb, lkf, gl->gl_strname, + GDLM_STRNAME_BYTES - 1, 0, gdlm_ast, gl, gdlm_bast); + if (error == -EAGAIN) + return 0; + if (error) + return LM_OUT_ERROR; + return LM_OUT_ASYNC; +} + +static void gdlm_put_lock(struct kmem_cache *cachep, void *ptr) +{ + struct gfs2_glock *gl = ptr; + struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct; + int error; + + if (gl->gl_lksb.sb_lkid == 0) { + kmem_cache_free(cachep, gl); + return; + } + + error = dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_VALBLK, + NULL, gl); + if (error) { + printk(KERN_ERR "gdlm_unlock %x,%llx err=%d\n", + gl->gl_name.ln_type, + (unsigned long long)gl->gl_name.ln_number, error); + return; + } +} + +static void gdlm_cancel(struct gfs2_glock *gl) +{ + struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct; + dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_CANCEL, NULL, gl); +} + +static int gdlm_mount(struct gfs2_sbd *sdp, const char *fsname) +{ + struct lm_lockstruct *ls = &sdp->sd_lockstruct; + int error; + + if (fsname == NULL) { + fs_info(sdp, "no fsname found\n"); + return -EINVAL; + } + + error = dlm_new_lockspace(fsname, strlen(fsname), &ls->ls_dlm, + DLM_LSFL_FS | DLM_LSFL_NEWEXCL | + (ls->ls_nodir ? DLM_LSFL_NODIR : 0), + GDLM_LVB_SIZE); + if (error) + printk(KERN_ERR "dlm_new_lockspace error %d", error); + + return error; +} + +static void gdlm_unmount(struct gfs2_sbd *sdp) +{ + struct lm_lockstruct *ls = &sdp->sd_lockstruct; + + if (ls->ls_dlm) { + dlm_release_lockspace(ls->ls_dlm, 2); + ls->ls_dlm = NULL; + } +} + +static const match_table_t dlm_tokens = { + { Opt_jid, "jid=%d"}, + { Opt_id, "id=%d"}, + { Opt_first, "first=%d"}, + { Opt_nodir, "nodir=%d"}, + { Opt_err, NULL }, +}; + +const struct lm_lockops gfs2_dlm_ops = { + .lm_proto_name = "lock_dlm", + .lm_mount = gdlm_mount, + .lm_unmount = gdlm_unmount, + .lm_put_lock = gdlm_put_lock, + .lm_lock = gdlm_lock, + .lm_cancel = gdlm_cancel, + .lm_tokens = &dlm_tokens, +}; + diff --git a/fs/gfs2/locking.c b/fs/gfs2/locking.c deleted file mode 100644 index d3657bc7938..00000000000 --- a/fs/gfs2/locking.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. - * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. - * - * This copyrighted material is made available to anyone wishing to use, - * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU General Public License version 2. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct lmh_wrapper { - struct list_head lw_list; - const struct lm_lockops *lw_ops; -}; - -struct nolock_lockspace { - unsigned int nl_lvb_size; -}; - -/** - * nolock_get_lock - get a lm_lock_t given a descripton of the lock - * @lockspace: the lockspace the lock lives in - * @name: the name of the lock - * @lockp: return the lm_lock_t here - * - * Returns: 0 on success, -EXXX on failure - */ - -static int nolock_get_lock(void *lockspace, struct lm_lockname *name, - void **lockp) -{ - *lockp = lockspace; - return 0; -} - -/** - * nolock_put_lock - get rid of a lock structure - * @lock: the lock to throw away - * - */ - -static void nolock_put_lock(void *lock) -{ -} - -/** - * nolock_hold_lvb - hold on to a lock value block - * @lock: the lock the LVB is associated with - * @lvbp: return the lm_lvb_t here - * - * Returns: 0 on success, -EXXX on failure - */ - -static int nolock_hold_lvb(void *lock, char **lvbp) -{ - struct nolock_lockspace *nl = lock; - int error = 0; - - *lvbp = kzalloc(nl->nl_lvb_size, GFP_KERNEL); - if (!*lvbp) - error = -ENOMEM; - - return error; -} - -/** - * nolock_unhold_lvb - release a LVB - * @lock: the lock the LVB is associated with - * @lvb: the lock value block - * - */ - -static void nolock_unhold_lvb(void *lock, char *lvb) -{ - kfree(lvb); -} - -static int nolock_mount(char *table_name, char *host_data, - lm_callback_t cb, void *cb_data, - unsigned int min_lvb_size, int flags, - struct lm_lockstruct *lockstruct, - struct kobject *fskobj); -static void nolock_unmount(void *lockspace); - -/* List of registered low-level locking protocols. A file system selects one - of them by name at mount time, e.g. lock_nolock, lock_dlm. */ - -static const struct lm_lockops nolock_ops = { - .lm_proto_name = "lock_nolock", - .lm_mount = nolock_mount, - .lm_unmount = nolock_unmount, - .lm_get_lock = nolock_get_lock, - .lm_put_lock = nolock_put_lock, - .lm_hold_lvb = nolock_hold_lvb, - .lm_unhold_lvb = nolock_unhold_lvb, -}; - -static struct lmh_wrapper nolock_proto = { - .lw_list = LIST_HEAD_INIT(nolock_proto.lw_list), - .lw_ops = &nolock_ops, -}; - -static LIST_HEAD(lmh_list); -static DEFINE_MUTEX(lmh_lock); - -static int nolock_mount(char *table_name, char *host_data, - lm_callback_t cb, void *cb_data, - unsigned int min_lvb_size, int flags, - struct lm_lockstruct *lockstruct, - struct kobject *fskobj) -{ - char *c; - unsigned int jid; - struct nolock_lockspace *nl; - - c = strstr(host_data, "jid="); - if (!c) - jid = 0; - else { - c += 4; - sscanf(c, "%u", &jid); - } - - nl = kzalloc(sizeof(struct nolock_lockspace), GFP_KERNEL); - if (!nl) - return -ENOMEM; - - nl->nl_lvb_size = min_lvb_size; - - lockstruct->ls_jid = jid; - lockstruct->ls_first = 1; - lockstruct->ls_lvb_size = min_lvb_size; - lockstruct->ls_lockspace = nl; - lockstruct->ls_ops = &nolock_ops; - lockstruct->ls_flags = LM_LSFLAG_LOCAL; - - return 0; -} - -static void nolock_unmount(void *lockspace) -{ - struct nolock_lockspace *nl = lockspace; - kfree(nl); -} - -/** - * gfs2_register_lockproto - Register a low-level locking protocol - * @proto: the protocol definition - * - * Returns: 0 on success, -EXXX on failure - */ - -int gfs2_register_lockproto(const struct lm_lockops *proto) -{ - struct lmh_wrapper *lw; - - mutex_lock(&lmh_lock); - - list_for_each_entry(lw, &lmh_list, lw_list) { - if (!strcmp(lw->lw_ops->lm_proto_name, proto->lm_proto_name)) { - mutex_unlock(&lmh_lock); - printk(KERN_INFO "GFS2: protocol %s already exists\n", - proto->lm_proto_name); - return -EEXIST; - } - } - - lw = kzalloc(sizeof(struct lmh_wrapper), GFP_KERNEL); - if (!lw) { - mutex_unlock(&lmh_lock); - return -ENOMEM; - } - - lw->lw_ops = proto; - list_add(&lw->lw_list, &lmh_list); - - mutex_unlock(&lmh_lock); - - return 0; -} - -/** - * gfs2_unregister_lockproto - Unregister a low-level locking protocol - * @proto: the protocol definition - * - */ - -void gfs2_unregister_lockproto(const struct lm_lockops *proto) -{ - struct lmh_wrapper *lw; - - mutex_lock(&lmh_lock); - - list_for_each_entry(lw, &lmh_list, lw_list) { - if (!strcmp(lw->lw_ops->lm_proto_name, proto->lm_proto_name)) { - list_del(&lw->lw_list); - mutex_unlock(&lmh_lock); - kfree(lw); - return; - } - } - - mutex_unlock(&lmh_lock); - - printk(KERN_WARNING "GFS2: can't unregister lock protocol %s\n", - proto->lm_proto_name); -} - -/** - * gfs2_mount_lockproto - Mount a lock protocol - * @proto_name - the name of the protocol - * @table_name - the name of the lock space - * @host_data - data specific to this host - * @cb - the callback to the code using the lock module - * @sdp - The GFS2 superblock - * @min_lvb_size - the mininum LVB size that the caller can deal with - * @flags - LM_MFLAG_* - * @lockstruct - a structure returned describing the mount - * - * Returns: 0 on success, -EXXX on failure - */ - -int gfs2_mount_lockproto(char *proto_name, char *table_name, char *host_data, - lm_callback_t cb, void *cb_data, - unsigned int min_lvb_size, int flags, - struct lm_lockstruct *lockstruct, - struct kobject *fskobj) -{ - struct lmh_wrapper *lw = NULL; - int try = 0; - int error, found; - - -retry: - mutex_lock(&lmh_lock); - - if (list_empty(&nolock_proto.lw_list)) - list_add(&nolock_proto.lw_list, &lmh_list); - - found = 0; - list_for_each_entry(lw, &lmh_list, lw_list) { - if (!strcmp(lw->lw_ops->lm_proto_name, proto_name)) { - found = 1; - break; - } - } - - if (!found) { - if (!try && capable(CAP_SYS_MODULE)) { - try = 1; - mutex_unlock(&lmh_lock); - request_module(proto_name); - goto retry; - } - printk(KERN_INFO "GFS2: can't find protocol %s\n", proto_name); - error = -ENOENT; - goto out; - } - - if (lw->lw_ops->lm_owner && - !try_module_get(lw->lw_ops->lm_owner)) { - try = 0; - mutex_unlock(&lmh_lock); - msleep(1000); - goto retry; - } - - error = lw->lw_ops->lm_mount(table_name, host_data, cb, cb_data, - min_lvb_size, flags, lockstruct, fskobj); - if (error) - module_put(lw->lw_ops->lm_owner); -out: - mutex_unlock(&lmh_lock); - return error; -} - -void gfs2_unmount_lockproto(struct lm_lockstruct *lockstruct) -{ - mutex_lock(&lmh_lock); - if (lockstruct->ls_ops->lm_unmount) - lockstruct->ls_ops->lm_unmount(lockstruct->ls_lockspace); - if (lockstruct->ls_ops->lm_owner) - module_put(lockstruct->ls_ops->lm_owner); - mutex_unlock(&lmh_lock); -} - -/** - * gfs2_withdraw_lockproto - abnormally unmount a lock module - * @lockstruct: the lockstruct passed into mount - * - */ - -void gfs2_withdraw_lockproto(struct lm_lockstruct *lockstruct) -{ - mutex_lock(&lmh_lock); - lockstruct->ls_ops->lm_withdraw(lockstruct->ls_lockspace); - if (lockstruct->ls_ops->lm_owner) - module_put(lockstruct->ls_ops->lm_owner); - mutex_unlock(&lmh_lock); -} - -EXPORT_SYMBOL_GPL(gfs2_register_lockproto); -EXPORT_SYMBOL_GPL(gfs2_unregister_lockproto); - diff --git a/fs/gfs2/locking/dlm/Makefile b/fs/gfs2/locking/dlm/Makefile deleted file mode 100644 index 2609bb6cd01..00000000000 --- a/fs/gfs2/locking/dlm/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_GFS2_FS_LOCKING_DLM) += lock_dlm.o -lock_dlm-y := lock.o main.o mount.o sysfs.o thread.o - diff --git a/fs/gfs2/locking/dlm/lock.c b/fs/gfs2/locking/dlm/lock.c deleted file mode 100644 index 2482c904750..00000000000 --- a/fs/gfs2/locking/dlm/lock.c +++ /dev/null @@ -1,708 +0,0 @@ -/* - * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. - * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. - * - * This copyrighted material is made available to anyone wishing to use, - * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU General Public License version 2. - */ - -#include "lock_dlm.h" - -static char junk_lvb[GDLM_LVB_SIZE]; - - -/* convert dlm lock-mode to gfs lock-state */ - -static s16 gdlm_make_lmstate(s16 dlmmode) -{ - switch (dlmmode) { - case DLM_LOCK_IV: - case DLM_LOCK_NL: - return LM_ST_UNLOCKED; - case DLM_LOCK_EX: - return LM_ST_EXCLUSIVE; - case DLM_LOCK_CW: - return LM_ST_DEFERRED; - case DLM_LOCK_PR: - return LM_ST_SHARED; - } - gdlm_assert(0, "unknown DLM mode %d", dlmmode); - return -1; -} - -/* A lock placed on this queue is re-submitted to DLM as soon as the lock_dlm - thread gets to it. */ - -static void queue_submit(struct gdlm_lock *lp) -{ - struct gdlm_ls *ls = lp->ls; - - spin_lock(&ls->async_lock); - list_add_tail(&lp->delay_list, &ls->submit); - spin_unlock(&ls->async_lock); - wake_up(&ls->thread_wait); -} - -static void wake_up_ast(struct gdlm_lock *lp) -{ - clear_bit(LFL_AST_WAIT, &lp->flags); - smp_mb__after_clear_bit(); - wake_up_bit(&lp->flags, LFL_AST_WAIT); -} - -static void gdlm_delete_lp(struct gdlm_lock *lp) -{ - struct gdlm_ls *ls = lp->ls; - - spin_lock(&ls->async_lock); - if (!list_empty(&lp->delay_list)) - list_del_init(&lp->delay_list); - ls->all_locks_count--; - spin_unlock(&ls->async_lock); - - kfree(lp); -} - -static void gdlm_queue_delayed(struct gdlm_lock *lp) -{ - struct gdlm_ls *ls = lp->ls; - - spin_lock(&ls->async_lock); - list_add_tail(&lp->delay_list, &ls->delayed); - spin_unlock(&ls->async_lock); -} - -static void process_complete(struct gdlm_lock *lp) -{ - struct gdlm_ls *ls = lp->ls; - struct lm_async_cb acb; - - memset(&acb, 0, sizeof(acb)); - - if (lp->lksb.sb_status == -DLM_ECANCEL) { - log_info("complete dlm cancel %x,%llx flags %lx", - lp->lockname.ln_type, - (unsigned long long)lp->lockname.ln_number, - lp->flags); - - lp->req = lp->cur; - acb.lc_ret |= LM_OUT_CANCELED; - if (lp->cur == DLM_LOCK_IV) - lp->lksb.sb_lkid = 0; - goto out; - } - - if (test_and_clear_bit(LFL_DLM_UNLOCK, &lp->flags)) { - if (lp->lksb.sb_status != -DLM_EUNLOCK) { - log_info("unlock sb_status %d %x,%llx flags %lx", - lp->lksb.sb_status, lp->lockname.ln_type, - (unsigned long long)lp->lockname.ln_number, - lp->flags); - return; - } - - lp->cur = DLM_LOCK_IV; - lp->req = DLM_LOCK_IV; - lp->lksb.sb_lkid = 0; - - if (test_and_clear_bit(LFL_UNLOCK_DELETE, &lp->flags)) { - gdlm_delete_lp(lp); - return; - } - goto out; - } - - if (lp->lksb.sb_flags & DLM_SBF_VALNOTVALID) - memset(lp->lksb.sb_lvbptr, 0, GDLM_LVB_SIZE); - - if (lp->lksb.sb_flags & DLM_SBF_ALTMODE) { - if (lp->req == DLM_LOCK_PR) - lp->req = DLM_LOCK_CW; - else if (lp->req == DLM_LOCK_CW) - lp->req = DLM_LOCK_PR; - } - - /* - * A canceled lock request. The lock was just taken off the delayed - * list and was never even submitted to dlm. - */ - - if (test_and_clear_bit(LFL_CANCEL, &lp->flags)) { - log_info("complete internal cancel %x,%llx", - lp->lockname.ln_type, - (unsigned long long)lp->lockname.ln_number); - lp->req = lp->cur; - acb.lc_ret |= LM_OUT_CANCELED; - goto out; - } - - /* - * An error occured. - */ - - if (lp->lksb.sb_status) { - /* a "normal" error */ - if ((lp->lksb.sb_status == -EAGAIN) && - (lp->lkf & DLM_LKF_NOQUEUE)) { - lp->req = lp->cur; - if (lp->cur == DLM_LOCK_IV) - lp->lksb.sb_lkid = 0; - goto out; - } - - /* this could only happen with cancels I think */ - log_info("ast sb_status %d %x,%llx flags %lx", - lp->lksb.sb_status, lp->lockname.ln_type, - (unsigned long long)lp->lockname.ln_number, - lp->flags); - return; - } - - /* - * This is an AST for an EX->EX conversion for sync_lvb from GFS. - */ - - if (test_and_clear_bit(LFL_SYNC_LVB, &lp->flags)) { - wake_up_ast(lp); - return; - } - - /* - * A lock has been demoted to NL because it initially completed during - * BLOCK_LOCKS. Now it must be requested in the originally requested - * mode. - */ - - if (test_and_clear_bit(LFL_REREQUEST, &lp->flags)) { - gdlm_assert(lp->req == DLM_LOCK_NL, "%x,%llx", - lp->lockname.ln_type, - (unsigned long long)lp->lockname.ln_number); - gdlm_assert(lp->prev_req > DLM_LOCK_NL, "%x,%llx", - lp->lockname.ln_type, - (unsigned long long)lp->lockname.ln_number); - - lp->cur = DLM_LOCK_NL; - lp->req = lp->prev_req; - lp->prev_req = DLM_LOCK_IV; - lp->lkf &= ~DLM_LKF_CONVDEADLK; - - set_bit(LFL_NOCACHE, &lp->flags); - - if (test_bit(DFL_BLOCK_LOCKS, &ls->flags) && - !test_bit(LFL_NOBLOCK, &lp->flags)) - gdlm_queue_delayed(lp); - else - queue_submit(lp); - return; - } - - /* - * A request is granted during dlm recovery. It may be granted - * because the locks of a failed node were cleared. In that case, - * there may be inconsistent data beneath this lock and we must wait - * for recovery to complete to use it. When gfs recovery is done this - * granted lock will be converted to NL and then reacquired in this - * granted state. - */ - - if (test_bit(DFL_BLOCK_LOCKS, &ls->flags) && - !test_bit(LFL_NOBLOCK, &lp->flags) && - lp->req != DLM_LOCK_NL) { - - lp->cur = lp->req; - lp->prev_req = lp->req; - lp->req = DLM_LOCK_NL; - lp->lkf |= DLM_LKF_CONVERT; - lp->lkf &= ~DLM_LKF_CONVDEADLK; - - log_debug("rereq %x,%llx id %x %d,%d", - lp->lockname.ln_type, - (unsigned long long)lp->lockname.ln_number, - lp->lksb.sb_lkid, lp->cur, lp->req); - - set_bit(LFL_REREQUEST, &lp->flags); - queue_submit(lp); - return; - } - - /* - * DLM demoted the lock to NL before it was granted so GFS must be - * told it cannot cache data for this lock. - */ - - if (lp->lksb.sb_flags & DLM_SBF_DEMOTED) - set_bit(LFL_NOCACHE, &lp->flags); - -out: - /* - * This is an internal lock_dlm lock - */ - - if (test_bit(LFL_INLOCK, &lp->flags)) { - clear_bit(LFL_NOBLOCK, &lp->flags); - lp->cur = lp->req; - wake_up_ast(lp); - return; - } - - /* - * Normal completion of a lock request. Tell GFS it now has the lock. - */ - - clear_bit(LFL_NOBLOCK, &lp->flags); - lp->cur = lp->req; - - acb.lc_name = lp->lockname; - acb.lc_ret |= gdlm_make_lmstate(lp->cur); - - ls->fscb(ls->sdp, LM_CB_ASYNC, &acb); -} - -static void gdlm_ast(void *astarg) -{ - struct gdlm_lock *lp = astarg; - clear_bit(LFL_ACTIVE, &lp->flags); - process_complete(lp); -} - -static void process_blocking(struct gdlm_lock *lp, int bast_mode) -{ - struct gdlm_ls *ls = lp->ls; - unsigned int cb = 0; - - switch (gdlm_make_lmstate(bast_mode)) { - case LM_ST_EXCLUSIVE: - cb = LM_CB_NEED_E; - break; - case LM_ST_DEFERRED: - cb = LM_CB_NEED_D; - break; - case LM_ST_SHARED: - cb = LM_CB_NEED_S; - break; - default: - gdlm_assert(0, "unknown bast mode %u", bast_mode); - } - - ls->fscb(ls->sdp, cb, &lp->lockname); -} - - -static void gdlm_bast(void *astarg, int mode) -{ - struct gdlm_lock *lp = astarg; - - if (!mode) { - printk(KERN_INFO "lock_dlm: bast mode zero %x,%llx\n", - lp->lockname.ln_type, - (unsigned long long)lp->lockname.ln_number); - return; - } - - process_blocking(lp, mode); -} - -/* convert gfs lock-state to dlm lock-mode */ - -static s16 make_mode(s16 lmstate) -{ - switch (lmstate) { - case LM_ST_UNLOCKED: - return DLM_LOCK_NL; - case LM_ST_EXCLUSIVE: - return DLM_LOCK_EX; - case LM_ST_DEFERRED: - return DLM_LOCK_CW; - case LM_ST_SHARED: - return DLM_LOCK_PR; - } - gdlm_assert(0, "unknown LM state %d", lmstate); - return -1; -} - - -/* verify agreement with GFS on the current lock state, NB: DLM_LOCK_NL and - DLM_LOCK_IV are both considered LM_ST_UNLOCKED by GFS. */ - -static void check_cur_state(struct gdlm_lock *lp, unsigned int cur_state) -{ - s16 cur = make_mode(cur_state); - if (lp->cur != DLM_LOCK_IV) - gdlm_assert(lp->cur == cur, "%d, %d", lp->cur, cur); -} - -static inline unsigned int make_flags(struct gdlm_lock *lp, - unsigned int gfs_flags, - s16 cur, s16 req) -{ - unsigned int lkf = 0; - - if (gfs_flags & LM_FLAG_TRY) - lkf |= DLM_LKF_NOQUEUE; - - if (gfs_flags & LM_FLAG_TRY_1CB) { - lkf |= DLM_LKF_NOQUEUE; - lkf |= DLM_LKF_NOQUEUEBAST; - } - - if (gfs_flags & LM_FLAG_PRIORITY) { - lkf |= DLM_LKF_NOORDER; - lkf |= DLM_LKF_HEADQUE; - } - - if (gfs_flags & LM_FLAG_ANY) { - if (req == DLM_LOCK_PR) - lkf |= DLM_LKF_ALTCW; - else if (req == DLM_LOCK_CW) - lkf |= DLM_LKF_ALTPR; - } - - if (lp->lksb.sb_lkid != 0) { - lkf |= DLM_LKF_CONVERT; - } - - if (lp->lvb) - lkf |= DLM_LKF_VALBLK; - - return lkf; -} - -/* make_strname - convert GFS lock numbers to a string */ - -static inline void make_strname(const struct lm_lockname *lockname, - struct gdlm_strname *str) -{ - sprintf(str->name, "%8x%16llx", lockname->ln_type, - (unsigned long long)lockname->ln_number); - str->namelen = GDLM_STRNAME_BYTES; -} - -static int gdlm_create_lp(struct gdlm_ls *ls, struct lm_lockname *name, - struct gdlm_lock **lpp) -{ - struct gdlm_lock *lp; - - lp = kzalloc(sizeof(struct gdlm_lock), GFP_NOFS); - if (!lp) - return -ENOMEM; - - lp->lockname = *name; - make_strname(name, &lp->strname); - lp->ls = ls; - lp->cur = DLM_LOCK_IV; - INIT_LIST_HEAD(&lp->delay_list); - - spin_lock(&ls->async_lock); - ls->all_locks_count++; - spin_unlock(&ls->async_lock); - - *lpp = lp; - return 0; -} - -int gdlm_get_lock(void *lockspace, struct lm_lockname *name, - void **lockp) -{ - struct gdlm_lock *lp; - int error; - - error = gdlm_create_lp(lockspace, name, &lp); - - *lockp = lp; - return error; -} - -void gdlm_put_lock(void *lock) -{ - gdlm_delete_lp(lock); -} - -unsigned int gdlm_do_lock(struct gdlm_lock *lp) -{ - struct gdlm_ls *ls = lp->ls; - int error, bast = 1; - - /* - * When recovery is in progress, delay lock requests for submission - * once recovery is done. Requests for recovery (NOEXP) and unlocks - * can pass. - */ - - if (test_bit(DFL_BLOCK_LOCKS, &ls->flags) && - !test_bit(LFL_NOBLOCK, &lp->flags) && lp->req != DLM_LOCK_NL) { - gdlm_queue_delayed(lp); - return LM_OUT_ASYNC; - } - - /* - * Submit the actual lock request. - */ - - if (test_bit(LFL_NOBAST, &lp->flags)) - bast = 0; - - set_bit(LFL_ACTIVE, &lp->flags); - - log_debug("lk %x,%llx id %x %d,%d %x", lp->lockname.ln_type, - (unsigned long long)lp->lockname.ln_number, lp->lksb.sb_lkid, - lp->cur, lp->req, lp->lkf); - - error = dlm_lock(ls->dlm_lockspace, lp->req, &lp->lksb, lp->lkf, - lp->strname.name, lp->strname.namelen, 0, gdlm_ast, - lp, bast ? gdlm_bast : NULL); - - if ((error == -EAGAIN) && (lp->lkf & DLM_LKF_NOQUEUE)) { - lp->lksb.sb_status = -EAGAIN; - gdlm_ast(lp); - error = 0; - } - - if (error) { - log_error("%s: gdlm_lock %x,%llx err=%d cur=%d req=%d lkf=%x " - "flags=%lx", ls->fsname, lp->lockname.ln_type, - (unsigned long long)lp->lockname.ln_number, error, - lp->cur, lp->req, lp->lkf, lp->flags); - return LM_OUT_ERROR; - } - return LM_OUT_ASYNC; -} - -static unsigned int gdlm_do_unlock(struct gdlm_lock *lp) -{ - struct gdlm_ls *ls = lp->ls; - unsigned int lkf = 0; - int error; - - set_bit(LFL_DLM_UNLOCK, &lp->flags); - set_bit(LFL_ACTIVE, &lp->flags); - - if (lp->lvb) - lkf = DLM_LKF_VALBLK; - - log_debug("un %x,%llx %x %d %x", lp->lockname.ln_type, - (unsigned long long)lp->lockname.ln_number, - lp->lksb.sb_lkid, lp->cur, lkf); - - error = dlm_unlock(ls->dlm_lockspace, lp->lksb.sb_lkid, lkf, NULL, lp); - - if (error) { - log_error("%s: gdlm_unlock %x,%llx err=%d cur=%d req=%d lkf=%x " - "flags=%lx", ls->fsname, lp->lockname.ln_type, - (unsigned long long)lp->lockname.ln_number, error, - lp->cur, lp->req, lp->lkf, lp->flags); - return LM_OUT_ERROR; - } - return LM_OUT_ASYNC; -} - -unsigned int gdlm_lock(void *lock, unsigned int cur_state, - unsigned int req_state, unsigned int flags) -{ - struct gdlm_lock *lp = lock; - - if (req_state == LM_ST_UNLOCKED) - return gdlm_unlock(lock, cur_state); - - if (req_state == LM_ST_UNLOCKED) - return gdlm_unlock(lock, cur_state); - - clear_bit(LFL_DLM_CANCEL, &lp->flags); - if (flags & LM_FLAG_NOEXP) - set_bit(LFL_NOBLOCK, &lp->flags); - - check_cur_state(lp, cur_state); - lp->req = make_mode(req_state); - lp->lkf = make_flags(lp, flags, lp->cur, lp->req); - - return gdlm_do_lock(lp); -} - -unsigned int gdlm_unlock(void *lock, unsigned int cur_state) -{ - struct gdlm_lock *lp = lock; - - clear_bit(LFL_DLM_CANCEL, &lp->flags); - if (lp->cur == DLM_LOCK_IV) - return 0; - return gdlm_do_unlock(lp); -} - -void gdlm_cancel(void *lock) -{ - struct gdlm_lock *lp = lock; - struct gdlm_ls *ls = lp->ls; - int error, delay_list = 0; - - if (test_bit(LFL_DLM_CANCEL, &lp->flags)) - return; - - log_info("gdlm_cancel %x,%llx flags %lx", lp->lockname.ln_type, - (unsigned long long)lp->lockname.ln_number, lp->flags); - - spin_lock(&ls->async_lock); - if (!list_empty(&lp->delay_list)) { - list_del_init(&lp->delay_list); - delay_list = 1; - } - spin_unlock(&ls->async_lock); - - if (delay_list) { - set_bit(LFL_CANCEL, &lp->flags); - set_bit(LFL_ACTIVE, &lp->flags); - gdlm_ast(lp); - return; - } - - if (!test_bit(LFL_ACTIVE, &lp->flags) || - test_bit(LFL_DLM_UNLOCK, &lp->flags)) { - log_info("gdlm_cancel skip %x,%llx flags %lx", - lp->lockname.ln_type, - (unsigned long long)lp->lockname.ln_number, lp->flags); - return; - } - - /* the lock is blocked in the dlm */ - - set_bit(LFL_DLM_CANCEL, &lp->flags); - set_bit(LFL_ACTIVE, &lp->flags); - - error = dlm_unlock(ls->dlm_lockspace, lp->lksb.sb_lkid, DLM_LKF_CANCEL, - NULL, lp); - - log_info("gdlm_cancel rv %d %x,%llx flags %lx", error, - lp->lockname.ln_type, - (unsigned long long)lp->lockname.ln_number, lp->flags); - - if (error == -EBUSY) - clear_bit(LFL_DLM_CANCEL, &lp->flags); -} - -static int gdlm_add_lvb(struct gdlm_lock *lp) -{ - char *lvb; - - lvb = kzalloc(GDLM_LVB_SIZE, GFP_NOFS); - if (!lvb) - return -ENOMEM; - - lp->lksb.sb_lvbptr = lvb; - lp->lvb = lvb; - return 0; -} - -static void gdlm_del_lvb(struct gdlm_lock *lp) -{ - kfree(lp->lvb); - lp->lvb = NULL; - lp->lksb.sb_lvbptr = NULL; -} - -static int gdlm_ast_wait(void *word) -{ - schedule(); - return 0; -} - -/* This can do a synchronous dlm request (requiring a lock_dlm thread to get - the completion) because gfs won't call hold_lvb() during a callback (from - the context of a lock_dlm thread). */ - -static int hold_null_lock(struct gdlm_lock *lp) -{ - struct gdlm_lock *lpn = NULL; - int error; - - if (lp->hold_null) { - printk(KERN_INFO "lock_dlm: lvb already held\n"); - return 0; - } - - error = gdlm_create_lp(lp->ls, &lp->lockname, &lpn); - if (error) - goto out; - - lpn->lksb.sb_lvbptr = junk_lvb; - lpn->lvb = junk_lvb; - - lpn->req = DLM_LOCK_NL; - lpn->lkf = DLM_LKF_VALBLK | DLM_LKF_EXPEDITE; - set_bit(LFL_NOBAST, &lpn->flags); - set_bit(LFL_INLOCK, &lpn->flags); - set_bit(LFL_AST_WAIT, &lpn->flags); - - gdlm_do_lock(lpn); - wait_on_bit(&lpn->flags, LFL_AST_WAIT, gdlm_ast_wait, TASK_UNINTERRUPTIBLE); - error = lpn->lksb.sb_status; - if (error) { - printk(KERN_INFO "lock_dlm: hold_null_lock dlm error %d\n", - error); - gdlm_delete_lp(lpn); - lpn = NULL; - } -out: - lp->hold_null = lpn; - return error; -} - -/* This cannot do a synchronous dlm request (requiring a lock_dlm thread to get - the completion) because gfs may call unhold_lvb() during a callback (from - the context of a lock_dlm thread) which could cause a deadlock since the - other lock_dlm thread could be engaged in recovery. */ - -static void unhold_null_lock(struct gdlm_lock *lp) -{ - struct gdlm_lock *lpn = lp->hold_null; - - gdlm_assert(lpn, "%x,%llx", lp->lockname.ln_type, - (unsigned long long)lp->lockname.ln_number); - lpn->lksb.sb_lvbptr = NULL; - lpn->lvb = NULL; - set_bit(LFL_UNLOCK_DELETE, &lpn->flags); - gdlm_do_unlock(lpn); - lp->hold_null = NULL; -} - -/* Acquire a NL lock because gfs requires the value block to remain - intact on the resource while the lvb is "held" even if it's holding no locks - on the resource. */ - -int gdlm_hold_lvb(void *lock, char **lvbp) -{ - struct gdlm_lock *lp = lock; - int error; - - error = gdlm_add_lvb(lp); - if (error) - return error; - - *lvbp = lp->lvb; - - error = hold_null_lock(lp); - if (error) - gdlm_del_lvb(lp); - - return error; -} - -void gdlm_unhold_lvb(void *lock, char *lvb) -{ - struct gdlm_lock *lp = lock; - - unhold_null_lock(lp); - gdlm_del_lvb(lp); -} - -void gdlm_submit_delayed(struct gdlm_ls *ls) -{ - struct gdlm_lock *lp, *safe; - - spin_lock(&ls->async_lock); - list_for_each_entry_safe(lp, safe, &ls->delayed, delay_list) { - list_del_init(&lp->delay_list); - list_add_tail(&lp->delay_list, &ls->submit); - } - spin_unlock(&ls->async_lock); - wake_up(&ls->thread_wait); -} - diff --git a/fs/gfs2/locking/dlm/lock_dlm.h b/fs/gfs2/locking/dlm/lock_dlm.h deleted file mode 100644 index 3c98e7c6f93..00000000000 --- a/fs/gfs2/locking/dlm/lock_dlm.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. - * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. - * - * This copyrighted material is made available to anyone wishing to use, - * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU General Public License version 2. - */ - -#ifndef LOCK_DLM_DOT_H -#define LOCK_DLM_DOT_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* - * Internally, we prefix things with gdlm_ and GDLM_ (for gfs-dlm) since a - * prefix of lock_dlm_ gets awkward. Externally, GFS refers to this module - * as "lock_dlm". - */ - -#define GDLM_STRNAME_BYTES 24 -#define GDLM_LVB_SIZE 32 -#define GDLM_DROP_COUNT 0 -#define GDLM_DROP_PERIOD 60 -#define GDLM_NAME_LEN 128 - -/* GFS uses 12 bytes to identify a resource (32 bit type + 64 bit number). - We sprintf these numbers into a 24 byte string of hex values to make them - human-readable (to make debugging simpler.) */ - -struct gdlm_strname { - unsigned char name[GDLM_STRNAME_BYTES]; - unsigned short namelen; -}; - -enum { - DFL_BLOCK_LOCKS = 0, - DFL_SPECTATOR = 1, - DFL_WITHDRAW = 2, -}; - -struct gdlm_ls { - u32 id; - int jid; - int first; - int first_done; - unsigned long flags; - struct kobject kobj; - char clustername[GDLM_NAME_LEN]; - char fsname[GDLM_NAME_LEN]; - int fsflags; - dlm_lockspace_t *dlm_lockspace; - lm_callback_t fscb; - struct gfs2_sbd *sdp; - int recover_jid; - int recover_jid_done; - int recover_jid_status; - spinlock_t async_lock; - struct list_head delayed; - struct list_head submit; - u32 all_locks_count; - wait_queue_head_t wait_control; - struct task_struct *thread; - wait_queue_head_t thread_wait; -}; - -enum { - LFL_NOBLOCK = 0, - LFL_NOCACHE = 1, - LFL_DLM_UNLOCK = 2, - LFL_DLM_CANCEL = 3, - LFL_SYNC_LVB = 4, - LFL_FORCE_PROMOTE = 5, - LFL_REREQUEST = 6, - LFL_ACTIVE = 7, - LFL_INLOCK = 8, - LFL_CANCEL = 9, - LFL_NOBAST = 10, - LFL_HEADQUE = 11, - LFL_UNLOCK_DELETE = 12, - LFL_AST_WAIT = 13, -}; - -struct gdlm_lock { - struct gdlm_ls *ls; - struct lm_lockname lockname; - struct gdlm_strname strname; - char *lvb; - struct dlm_lksb lksb; - - s16 cur; - s16 req; - s16 prev_req; - u32 lkf; /* dlm flags DLM_LKF_ */ - unsigned long flags; /* lock_dlm flags LFL_ */ - - struct list_head delay_list; /* delayed */ - struct gdlm_lock *hold_null; /* NL lock for hold_lvb */ -}; - -#define gdlm_assert(assertion, fmt, args...) \ -do { \ - if (unlikely(!(assertion))) { \ - printk(KERN_EMERG "lock_dlm: fatal assertion failed \"%s\"\n" \ - "lock_dlm: " fmt "\n", \ - #assertion, ##args); \ - BUG(); \ - } \ -} while (0) - -#define log_print(lev, fmt, arg...) printk(lev "lock_dlm: " fmt "\n" , ## arg) -#define log_info(fmt, arg...) log_print(KERN_INFO , fmt , ## arg) -#define log_error(fmt, arg...) log_print(KERN_ERR , fmt , ## arg) -#ifdef LOCK_DLM_LOG_DEBUG -#define log_debug(fmt, arg...) log_print(KERN_DEBUG , fmt , ## arg) -#else -#define log_debug(fmt, arg...) -#endif - -/* sysfs.c */ - -int gdlm_sysfs_init(void); -void gdlm_sysfs_exit(void); -int gdlm_kobject_setup(struct gdlm_ls *, struct kobject *); -void gdlm_kobject_release(struct gdlm_ls *); - -/* thread.c */ - -int gdlm_init_threads(struct gdlm_ls *); -void gdlm_release_threads(struct gdlm_ls *); - -/* lock.c */ - -void gdlm_submit_delayed(struct gdlm_ls *); -unsigned int gdlm_do_lock(struct gdlm_lock *); - -int gdlm_get_lock(void *, struct lm_lockname *, void **); -void gdlm_put_lock(void *); -unsigned int gdlm_lock(void *, unsigned int, unsigned int, unsigned int); -unsigned int gdlm_unlock(void *, unsigned int); -void gdlm_cancel(void *); -int gdlm_hold_lvb(void *, char **); -void gdlm_unhold_lvb(void *, char *); - -/* mount.c */ - -extern const struct lm_lockops gdlm_ops; - -#endif - diff --git a/fs/gfs2/locking/dlm/main.c b/fs/gfs2/locking/dlm/main.c deleted file mode 100644 index b9a03a7ff80..00000000000 --- a/fs/gfs2/locking/dlm/main.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. - * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. - * - * This copyrighted material is made available to anyone wishing to use, - * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU General Public License version 2. - */ - -#include - -#include "lock_dlm.h" - -static int __init init_lock_dlm(void) -{ - int error; - - error = gfs2_register_lockproto(&gdlm_ops); - if (error) { - printk(KERN_WARNING "lock_dlm: can't register protocol: %d\n", - error); - return error; - } - - error = gdlm_sysfs_init(); - if (error) { - gfs2_unregister_lockproto(&gdlm_ops); - return error; - } - - printk(KERN_INFO - "Lock_DLM (built %s %s) installed\n", __DATE__, __TIME__); - return 0; -} - -static void __exit exit_lock_dlm(void) -{ - gdlm_sysfs_exit(); - gfs2_unregister_lockproto(&gdlm_ops); -} - -module_init(init_lock_dlm); -module_exit(exit_lock_dlm); - -MODULE_DESCRIPTION("GFS DLM Locking Module"); -MODULE_AUTHOR("Red Hat, Inc."); -MODULE_LICENSE("GPL"); - diff --git a/fs/gfs2/locking/dlm/mount.c b/fs/gfs2/locking/dlm/mount.c deleted file mode 100644 index 1aa7eb6a022..00000000000 --- a/fs/gfs2/locking/dlm/mount.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. - * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. - * - * This copyrighted material is made available to anyone wishing to use, - * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU General Public License version 2. - */ - -#include "lock_dlm.h" - -const struct lm_lockops gdlm_ops; - - -static struct gdlm_ls *init_gdlm(lm_callback_t cb, struct gfs2_sbd *sdp, - int flags, char *table_name) -{ - struct gdlm_ls *ls; - char buf[256], *p; - - ls = kzalloc(sizeof(struct gdlm_ls), GFP_KERNEL); - if (!ls) - return NULL; - - ls->fscb = cb; - ls->sdp = sdp; - ls->fsflags = flags; - spin_lock_init(&ls->async_lock); - INIT_LIST_HEAD(&ls->delayed); - INIT_LIST_HEAD(&ls->submit); - init_waitqueue_head(&ls->thread_wait); - init_waitqueue_head(&ls->wait_control); - ls->jid = -1; - - strncpy(buf, table_name, 256); - buf[255] = '\0'; - - p = strchr(buf, ':'); - if (!p) { - log_info("invalid table_name \"%s\"", table_name); - kfree(ls); - return NULL; - } - *p = '\0'; - p++; - - strncpy(ls->clustername, buf, GDLM_NAME_LEN); - strncpy(ls->fsname, p, GDLM_NAME_LEN); - - return ls; -} - -static int make_args(struct gdlm_ls *ls, char *data_arg, int *nodir) -{ - char data[256]; - char *options, *x, *y; - int error = 0; - - memset(data, 0, 256); - strncpy(data, data_arg, 255); - - if (!strlen(data)) { - log_error("no mount options, (u)mount helpers not installed"); - return -EINVAL; - } - - for (options = data; (x = strsep(&options, ":")); ) { - if (!*x) - continue; - - y = strchr(x, '='); - if (y) - *y++ = 0; - - if (!strcmp(x, "jid")) { - if (!y) { - log_error("need argument to jid"); - error = -EINVAL; - break; - } - sscanf(y, "%u", &ls->jid); - - } else if (!strcmp(x, "first")) { - if (!y) { - log_error("need argument to first"); - error = -EINVAL; - break; - } - sscanf(y, "%u", &ls->first); - - } else if (!strcmp(x, "id")) { - if (!y) { - log_error("need argument to id"); - error = -EINVAL; - break; - } - sscanf(y, "%u", &ls->id); - - } else if (!strcmp(x, "nodir")) { - if (!y) { - log_error("need argument to nodir"); - error = -EINVAL; - break; - } - sscanf(y, "%u", nodir); - - } else { - log_error("unkonwn option: %s", x); - error = -EINVAL; - break; - } - } - - return error; -} - -static int gdlm_mount(char *table_name, char *host_data, - lm_callback_t cb, void *cb_data, - unsigned int min_lvb_size, int flags, - struct lm_lockstruct *lockstruct, - struct kobject *fskobj) -{ - struct gdlm_ls *ls; - int error = -ENOMEM, nodir = 0; - - if (min_lvb_size > GDLM_LVB_SIZE) - goto out; - - ls = init_gdlm(cb, cb_data, flags, table_name); - if (!ls) - goto out; - - error = make_args(ls, host_data, &nodir); - if (error) - goto out; - - error = gdlm_init_threads(ls); - if (error) - goto out_free; - - error = gdlm_kobject_setup(ls, fskobj); - if (error) - goto out_thread; - - error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname), - &ls->dlm_lockspace, - DLM_LSFL_FS | DLM_LSFL_NEWEXCL | - (nodir ? DLM_LSFL_NODIR : 0), - GDLM_LVB_SIZE); - if (error) { - log_error("dlm_new_lockspace error %d", error); - goto out_kobj; - } - - lockstruct->ls_jid = ls->jid; - lockstruct->ls_first = ls->first; - lockstruct->ls_lockspace = ls; - lockstruct->ls_ops = &gdlm_ops; - lockstruct->ls_flags = 0; - lockstruct->ls_lvb_size = GDLM_LVB_SIZE; - return 0; - -out_kobj: - gdlm_kobject_release(ls); -out_thread: - gdlm_release_threads(ls); -out_free: - kfree(ls); -out: - return error; -} - -static void gdlm_unmount(void *lockspace) -{ - struct gdlm_ls *ls = lockspace; - - log_debug("unmount flags %lx", ls->flags); - - /* FIXME: serialize unmount and withdraw in case they - happen at once. Also, if unmount follows withdraw, - wait for withdraw to finish. */ - - if (test_bit(DFL_WITHDRAW, &ls->flags)) - goto out; - - gdlm_kobject_release(ls); - dlm_release_lockspace(ls->dlm_lockspace, 2); - gdlm_release_threads(ls); - BUG_ON(ls->all_locks_count); -out: - kfree(ls); -} - -static void gdlm_recovery_done(void *lockspace, unsigned int jid, - unsigned int message) -{ - char env_jid[20]; - char env_status[20]; - char *envp[] = { env_jid, env_status, NULL }; - struct gdlm_ls *ls = lockspace; - ls->recover_jid_done = jid; - ls->recover_jid_status = message; - sprintf(env_jid, "JID=%d", jid); - sprintf(env_status, "RECOVERY=%s", - message == LM_RD_SUCCESS ? "Done" : "Failed"); - kobject_uevent_env(&ls->kobj, KOBJ_CHANGE, envp); -} - -static void gdlm_others_may_mount(void *lockspace) -{ - char *message = "FIRSTMOUNT=Done"; - char *envp[] = { message, NULL }; - struct gdlm_ls *ls = lockspace; - ls->first_done = 1; - kobject_uevent_env(&ls->kobj, KOBJ_CHANGE, envp); -} - -/* Userspace gets the offline uevent, blocks new gfs locks on - other mounters, and lets us know (sets WITHDRAW flag). Then, - userspace leaves the mount group while we leave the lockspace. */ - -static void gdlm_withdraw(void *lockspace) -{ - struct gdlm_ls *ls = lockspace; - - kobject_uevent(&ls->kobj, KOBJ_OFFLINE); - - wait_event_interruptible(ls->wait_control, - test_bit(DFL_WITHDRAW, &ls->flags)); - - dlm_release_lockspace(ls->dlm_lockspace, 2); - gdlm_release_threads(ls); - gdlm_kobject_release(ls); -} - -static int gdlm_plock(void *lockspace, struct lm_lockname *name, - struct file *file, int cmd, struct file_lock *fl) -{ - struct gdlm_ls *ls = lockspace; - return dlm_posix_lock(ls->dlm_lockspace, name->ln_number, file, cmd, fl); -} - -static int gdlm_punlock(void *lockspace, struct lm_lockname *name, - struct file *file, struct file_lock *fl) -{ - struct gdlm_ls *ls = lockspace; - return dlm_posix_unlock(ls->dlm_lockspace, name->ln_number, file, fl); -} - -static int gdlm_plock_get(void *lockspace, struct lm_lockname *name, - struct file *file, struct file_lock *fl) -{ - struct gdlm_ls *ls = lockspace; - return dlm_posix_get(ls->dlm_lockspace, name->ln_number, file, fl); -} - -const struct lm_lockops gdlm_ops = { - .lm_proto_name = "lock_dlm", - .lm_mount = gdlm_mount, - .lm_others_may_mount = gdlm_others_may_mount, - .lm_unmount = gdlm_unmount, - .lm_withdraw = gdlm_withdraw, - .lm_get_lock = gdlm_get_lock, - .lm_put_lock = gdlm_put_lock, - .lm_lock = gdlm_lock, - .lm_unlock = gdlm_unlock, - .lm_plock = gdlm_plock, - .lm_punlock = gdlm_punlock, - .lm_plock_get = gdlm_plock_get, - .lm_cancel = gdlm_cancel, - .lm_hold_lvb = gdlm_hold_lvb, - .lm_unhold_lvb = gdlm_unhold_lvb, - .lm_recovery_done = gdlm_recovery_done, - .lm_owner = THIS_MODULE, -}; - diff --git a/fs/gfs2/locking/dlm/sysfs.c b/fs/gfs2/locking/dlm/sysfs.c deleted file mode 100644 index 9b7edcf7bd4..00000000000 --- a/fs/gfs2/locking/dlm/sysfs.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. - * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. - * - * This copyrighted material is made available to anyone wishing to use, - * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU General Public License version 2. - */ - -#include -#include - -#include "lock_dlm.h" - -static ssize_t proto_name_show(struct gdlm_ls *ls, char *buf) -{ - return sprintf(buf, "%s\n", gdlm_ops.lm_proto_name); -} - -static ssize_t block_show(struct gdlm_ls *ls, char *buf) -{ - ssize_t ret; - int val = 0; - - if (test_bit(DFL_BLOCK_LOCKS, &ls->flags)) - val = 1; - ret = sprintf(buf, "%d\n", val); - return ret; -} - -static ssize_t block_store(struct gdlm_ls *ls, const char *buf, size_t len) -{ - ssize_t ret = len; - int val; - - val = simple_strtol(buf, NULL, 0); - - if (val == 1) - set_bit(DFL_BLOCK_LOCKS, &ls->flags); - else if (val == 0) { - clear_bit(DFL_BLOCK_LOCKS, &ls->flags); - gdlm_submit_delayed(ls); - } else { - ret = -EINVAL; - } - return ret; -} - -static ssize_t withdraw_show(struct gdlm_ls *ls, char *buf) -{ - ssize_t ret; - int val = 0; - - if (test_bit(DFL_WITHDRAW, &ls->flags)) - val = 1; - ret = sprintf(buf, "%d\n", val); - return ret; -} - -static ssize_t withdraw_store(struct gdlm_ls *ls, const char *buf, size_t len) -{ - ssize_t ret = len; - int val; - - val = simple_strtol(buf, NULL, 0); - - if (val == 1) - set_bit(DFL_WITHDRAW, &ls->flags); - else - ret = -EINVAL; - wake_up(&ls->wait_control); - return ret; -} - -static ssize_t id_show(struct gdlm_ls *ls, char *buf) -{ - return sprintf(buf, "%u\n", ls->id); -} - -static ssize_t jid_show(struct gdlm_ls *ls, char *buf) -{ - return sprintf(buf, "%d\n", ls->jid); -} - -static ssize_t first_show(struct gdlm_ls *ls, char *buf) -{ - return sprintf(buf, "%d\n", ls->first); -} - -static ssize_t first_done_show(struct gdlm_ls *ls, char *buf) -{ - return sprintf(buf, "%d\n", ls->first_done); -} - -static ssize_t recover_show(struct gdlm_ls *ls, char *buf) -{ - return sprintf(buf, "%d\n", ls->recover_jid); -} - -static ssize_t recover_store(struct gdlm_ls *ls, const char *buf, size_t len) -{ - ls->recover_jid = simple_strtol(buf, NULL, 0); - ls->fscb(ls->sdp, LM_CB_NEED_RECOVERY, &ls->recover_jid); - return len; -} - -static ssize_t recover_done_show(struct gdlm_ls *ls, char *buf) -{ - return sprintf(buf, "%d\n", ls->recover_jid_done); -} - -static ssize_t recover_status_show(struct gdlm_ls *ls, char *buf) -{ - return sprintf(buf, "%d\n", ls->recover_jid_status); -} - -struct gdlm_attr { - struct attribute attr; - ssize_t (*show)(struct gdlm_ls *, char *); - ssize_t (*store)(struct gdlm_ls *, const char *, size_t); -}; - -#define GDLM_ATTR(_name,_mode,_show,_store) \ -static struct gdlm_attr gdlm_attr_##_name = __ATTR(_name,_mode,_show,_store) - -GDLM_ATTR(proto_name, 0444, proto_name_show, NULL); -GDLM_ATTR(block, 0644, block_show, block_store); -GDLM_ATTR(withdraw, 0644, withdraw_show, withdraw_store); -GDLM_ATTR(id, 0444, id_show, NULL); -GDLM_ATTR(jid, 0444, jid_show, NULL); -GDLM_ATTR(first, 0444, first_show, NULL); -GDLM_ATTR(first_done, 0444, first_done_show, NULL); -GDLM_ATTR(recover, 0644, recover_show, recover_store); -GDLM_ATTR(recover_done, 0444, recover_done_show, NULL); -GDLM_ATTR(recover_status, 0444, recover_status_show, NULL); - -static struct attribute *gdlm_attrs[] = { - &gdlm_attr_proto_name.attr, - &gdlm_attr_block.attr, - &gdlm_attr_withdraw.attr, - &gdlm_attr_id.attr, - &gdlm_attr_jid.attr, - &gdlm_attr_first.attr, - &gdlm_attr_first_done.attr, - &gdlm_attr_recover.attr, - &gdlm_attr_recover_done.attr, - &gdlm_attr_recover_status.attr, - NULL, -}; - -static ssize_t gdlm_attr_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct gdlm_ls *ls = container_of(kobj, struct gdlm_ls, kobj); - struct gdlm_attr *a = container_of(attr, struct gdlm_attr, attr); - return a->show ? a->show(ls, buf) : 0; -} - -static ssize_t gdlm_attr_store(struct kobject *kobj, struct attribute *attr, - const char *buf, size_t len) -{ - struct gdlm_ls *ls = container_of(kobj, struct gdlm_ls, kobj); - struct gdlm_attr *a = container_of(attr, struct gdlm_attr, attr); - return a->store ? a->store(ls, buf, len) : len; -} - -static struct sysfs_ops gdlm_attr_ops = { - .show = gdlm_attr_show, - .store = gdlm_attr_store, -}; - -static struct kobj_type gdlm_ktype = { - .default_attrs = gdlm_attrs, - .sysfs_ops = &gdlm_attr_ops, -}; - -static struct kset *gdlm_kset; - -int gdlm_kobject_setup(struct gdlm_ls *ls, struct kobject *fskobj) -{ - int error; - - ls->kobj.kset = gdlm_kset; - error = kobject_init_and_add(&ls->kobj, &gdlm_ktype, fskobj, - "lock_module"); - if (error) - log_error("can't register kobj %d", error); - kobject_uevent(&ls->kobj, KOBJ_ADD); - - return error; -} - -void gdlm_kobject_release(struct gdlm_ls *ls) -{ - kobject_put(&ls->kobj); -} - -static int gdlm_uevent(struct kset *kset, struct kobject *kobj, - struct kobj_uevent_env *env) -{ - struct gdlm_ls *ls = container_of(kobj, struct gdlm_ls, kobj); - add_uevent_var(env, "LOCKTABLE=%s:%s", ls->clustername, ls->fsname); - add_uevent_var(env, "LOCKPROTO=lock_dlm"); - return 0; -} - -static struct kset_uevent_ops gdlm_uevent_ops = { - .uevent = gdlm_uevent, -}; - - -int gdlm_sysfs_init(void) -{ - gdlm_kset = kset_create_and_add("lock_dlm", &gdlm_uevent_ops, kernel_kobj); - if (!gdlm_kset) { - printk(KERN_WARNING "%s: can not create kset\n", __func__); - return -ENOMEM; - } - return 0; -} - -void gdlm_sysfs_exit(void) -{ - kset_unregister(gdlm_kset); -} - diff --git a/fs/gfs2/locking/dlm/thread.c b/fs/gfs2/locking/dlm/thread.c deleted file mode 100644 index 38823efd698..00000000000 --- a/fs/gfs2/locking/dlm/thread.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. - * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. - * - * This copyrighted material is made available to anyone wishing to use, - * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU General Public License version 2. - */ - -#include "lock_dlm.h" - -static inline int no_work(struct gdlm_ls *ls) -{ - int ret; - - spin_lock(&ls->async_lock); - ret = list_empty(&ls->submit); - spin_unlock(&ls->async_lock); - - return ret; -} - -static int gdlm_thread(void *data) -{ - struct gdlm_ls *ls = (struct gdlm_ls *) data; - struct gdlm_lock *lp = NULL; - - while (!kthread_should_stop()) { - wait_event_interruptible(ls->thread_wait, - !no_work(ls) || kthread_should_stop()); - - spin_lock(&ls->async_lock); - - if (!list_empty(&ls->submit)) { - lp = list_entry(ls->submit.next, struct gdlm_lock, - delay_list); - list_del_init(&lp->delay_list); - spin_unlock(&ls->async_lock); - gdlm_do_lock(lp); - spin_lock(&ls->async_lock); - } - spin_unlock(&ls->async_lock); - } - - return 0; -} - -int gdlm_init_threads(struct gdlm_ls *ls) -{ - struct task_struct *p; - int error; - - p = kthread_run(gdlm_thread, ls, "lock_dlm"); - error = IS_ERR(p); - if (error) { - log_error("can't start lock_dlm thread %d", error); - return error; - } - ls->thread = p; - - return 0; -} - -void gdlm_release_threads(struct gdlm_ls *ls) -{ - kthread_stop(ls->thread); -} - diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index ad305854bdc..98918a75641 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 4390f6f4047..80e4f5f898b 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c @@ -13,7 +13,6 @@ #include #include #include -#include #include "gfs2.h" #include "incore.h" diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index 86fe0679871..a6892ed0840 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include "gfs2.h" @@ -47,8 +46,6 @@ static void gfs2_init_glock_once(void *foo) INIT_HLIST_NODE(&gl->gl_list); spin_lock_init(&gl->gl_spin); INIT_LIST_HEAD(&gl->gl_holders); - gl->gl_lvb = NULL; - atomic_set(&gl->gl_lvb_count, 0); INIT_LIST_HEAD(&gl->gl_lru); INIT_LIST_HEAD(&gl->gl_ail_list); atomic_set(&gl->gl_ail_count, 0); diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 09853620c95..870d65ae7ae 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c @@ -19,7 +19,6 @@ #include #include #include -#include #include "gfs2.h" #include "incore.h" diff --git a/fs/gfs2/mount.c b/fs/gfs2/mount.c index 3524ae81189..fba502aa8b2 100644 --- a/fs/gfs2/mount.c +++ b/fs/gfs2/mount.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include "gfs2.h" diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index dde4ead2c3b..a6d00e8ffe1 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include "gfs2.h" diff --git a/fs/gfs2/ops_dentry.c b/fs/gfs2/ops_dentry.c index c2ad36330ca..5eb57b04438 100644 --- a/fs/gfs2/ops_dentry.c +++ b/fs/gfs2/ops_dentry.c @@ -13,7 +13,6 @@ #include #include #include -#include #include "gfs2.h" #include "incore.h" diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c index 7fdeb14ddd1..9200ef22171 100644 --- a/fs/gfs2/ops_export.c +++ b/fs/gfs2/ops_export.c @@ -14,7 +14,6 @@ #include #include #include -#include #include "gfs2.h" #include "incore.h" diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index 93fe41b67f9..99d726f1c7a 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c @@ -20,9 +20,10 @@ #include #include #include -#include #include #include +#include +#include #include "gfs2.h" #include "incore.h" @@ -560,57 +561,24 @@ static int gfs2_fsync(struct file *file, struct dentry *dentry, int datasync) return ret; } +#ifdef CONFIG_GFS2_FS_LOCKING_DLM + /** * gfs2_setlease - acquire/release a file lease * @file: the file pointer * @arg: lease type * @fl: file lock * + * We don't currently have a way to enforce a lease across the whole + * cluster; until we do, disable leases (by just returning -EINVAL), + * unless the administrator has requested purely local locking. + * * Returns: errno */ static int gfs2_setlease(struct file *file, long arg, struct file_lock **fl) { - struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host); - - /* - * We don't currently have a way to enforce a lease across the whole - * cluster; until we do, disable leases (by just returning -EINVAL), - * unless the administrator has requested purely local locking. - */ - if (!sdp->sd_args.ar_localflocks) - return -EINVAL; - return generic_setlease(file, arg, fl); -} - -static int gfs2_lm_plock_get(struct gfs2_sbd *sdp, struct lm_lockname *name, - struct file *file, struct file_lock *fl) -{ - int error = -EIO; - if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) - error = sdp->sd_lockstruct.ls_ops->lm_plock_get( - sdp->sd_lockstruct.ls_lockspace, name, file, fl); - return error; -} - -static int gfs2_lm_plock(struct gfs2_sbd *sdp, struct lm_lockname *name, - struct file *file, int cmd, struct file_lock *fl) -{ - int error = -EIO; - if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) - error = sdp->sd_lockstruct.ls_ops->lm_plock( - sdp->sd_lockstruct.ls_lockspace, name, file, cmd, fl); - return error; -} - -static int gfs2_lm_punlock(struct gfs2_sbd *sdp, struct lm_lockname *name, - struct file *file, struct file_lock *fl) -{ - int error = -EIO; - if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) - error = sdp->sd_lockstruct.ls_ops->lm_punlock( - sdp->sd_lockstruct.ls_lockspace, name, file, fl); - return error; + return -EINVAL; } /** @@ -626,9 +594,7 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl) { struct gfs2_inode *ip = GFS2_I(file->f_mapping->host); struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host); - struct lm_lockname name = - { .ln_number = ip->i_no_addr, - .ln_type = LM_TYPE_PLOCK }; + struct lm_lockstruct *ls = &sdp->sd_lockstruct; if (!(fl->fl_flags & FL_POSIX)) return -ENOLCK; @@ -640,12 +606,14 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl) cmd = F_SETLK; fl->fl_type = F_UNLCK; } + if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) + return -EIO; if (IS_GETLK(cmd)) - return gfs2_lm_plock_get(sdp, &name, file, fl); + return dlm_posix_get(ls->ls_dlm, ip->i_no_addr, file, fl); else if (fl->fl_type == F_UNLCK) - return gfs2_lm_punlock(sdp, &name, file, fl); + return dlm_posix_unlock(ls->ls_dlm, ip->i_no_addr, file, fl); else - return gfs2_lm_plock(sdp, &name, file, cmd, fl); + return dlm_posix_lock(ls->ls_dlm, ip->i_no_addr, file, cmd, fl); } static int do_flock(struct file *file, int cmd, struct file_lock *fl) @@ -732,7 +700,7 @@ static int gfs2_flock(struct file *file, int cmd, struct file_lock *fl) } } -const struct file_operations gfs2_file_fops = { +const struct file_operations *gfs2_file_fops = &(const struct file_operations){ .llseek = gfs2_llseek, .read = do_sync_read, .aio_read = generic_file_aio_read, @@ -750,7 +718,7 @@ const struct file_operations gfs2_file_fops = { .setlease = gfs2_setlease, }; -const struct file_operations gfs2_dir_fops = { +const struct file_operations *gfs2_dir_fops = &(const struct file_operations){ .readdir = gfs2_readdir, .unlocked_ioctl = gfs2_ioctl, .open = gfs2_open, @@ -760,7 +728,9 @@ const struct file_operations gfs2_dir_fops = { .flock = gfs2_flock, }; -const struct file_operations gfs2_file_fops_nolock = { +#endif /* CONFIG_GFS2_FS_LOCKING_DLM */ + +const struct file_operations *gfs2_file_fops_nolock = &(const struct file_operations){ .llseek = gfs2_llseek, .read = do_sync_read, .aio_read = generic_file_aio_read, @@ -773,10 +743,10 @@ const struct file_operations gfs2_file_fops_nolock = { .fsync = gfs2_fsync, .splice_read = generic_file_splice_read, .splice_write = generic_file_splice_write, - .setlease = gfs2_setlease, + .setlease = generic_setlease, }; -const struct file_operations gfs2_dir_fops_nolock = { +const struct file_operations *gfs2_dir_fops_nolock = &(const struct file_operations){ .readdir = gfs2_readdir, .unlocked_ioctl = gfs2_ioctl, .open = gfs2_open, diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 402b6a2cd2c..95bb33e41a7 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -17,7 +17,6 @@ #include #include #include -#include #include "gfs2.h" #include "incore.h" @@ -627,13 +626,13 @@ static int map_journal_extents(struct gfs2_sbd *sdp) return rc; } -static void gfs2_lm_others_may_mount(struct gfs2_sbd *sdp) +static void gfs2_others_may_mount(struct gfs2_sbd *sdp) { - if (!sdp->sd_lockstruct.ls_ops->lm_others_may_mount) - return; - if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) - sdp->sd_lockstruct.ls_ops->lm_others_may_mount( - sdp->sd_lockstruct.ls_lockspace); + char *message = "FIRSTMOUNT=Done"; + char *envp[] = { message, NULL }; + struct lm_lockstruct *ls = &sdp->sd_lockstruct; + ls->ls_first_done = 1; + kobject_uevent_env(&sdp->sd_kobj, KOBJ_CHANGE, envp); } /** @@ -793,7 +792,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) } } - gfs2_lm_others_may_mount(sdp); + gfs2_others_may_mount(sdp); } else if (!sdp->sd_args.ar_spectator) { error = gfs2_recover_journal(sdp->sd_jdesc); if (error) { @@ -1002,7 +1001,6 @@ static int init_threads(struct gfs2_sbd *sdp, int undo) goto fail_quotad; sdp->sd_log_flush_time = jiffies; - sdp->sd_jindex_refresh_time = jiffies; p = kthread_run(gfs2_logd, sdp, "gfs2_logd"); error = IS_ERR(p); @@ -1030,6 +1028,17 @@ fail: return error; } +static const match_table_t nolock_tokens = { + { Opt_jid, "jid=%d\n", }, + { Opt_err, NULL }, +}; + +static const struct lm_lockops nolock_ops = { + .lm_proto_name = "lock_nolock", + .lm_put_lock = kmem_cache_free, + .lm_tokens = &nolock_tokens, +}; + /** * gfs2_lm_mount - mount a locking protocol * @sdp: the filesystem @@ -1041,31 +1050,73 @@ fail: static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent) { - char *proto = sdp->sd_proto_name; - char *table = sdp->sd_table_name; - int flags = LM_MFLAG_CONV_NODROP; - int error; + const struct lm_lockops *lm; + struct lm_lockstruct *ls = &sdp->sd_lockstruct; + struct gfs2_args *args = &sdp->sd_args; + const char *proto = sdp->sd_proto_name; + const char *table = sdp->sd_table_name; + const char *fsname; + char *o, *options; + int ret; - if (sdp->sd_args.ar_spectator) - flags |= LM_MFLAG_SPECTATOR; + if (!strcmp("lock_nolock", proto)) { + lm = &nolock_ops; + sdp->sd_args.ar_localflocks = 1; + sdp->sd_args.ar_localcaching = 1; +#ifdef CONFIG_GFS2_FS_LOCKING_DLM + } else if (!strcmp("lock_dlm", proto)) { + lm = &gfs2_dlm_ops; +#endif + } else { + printk(KERN_INFO "GFS2: can't find protocol %s\n", proto); + return -ENOENT; + } fs_info(sdp, "Trying to join cluster \"%s\", \"%s\"\n", proto, table); - error = gfs2_mount_lockproto(proto, table, sdp->sd_args.ar_hostdata, - gfs2_glock_cb, sdp, - GFS2_MIN_LVB_SIZE, flags, - &sdp->sd_lockstruct, &sdp->sd_kobj); - if (error) { - fs_info(sdp, "can't mount proto=%s, table=%s, hostdata=%s\n", - proto, table, sdp->sd_args.ar_hostdata); - goto out; - } + ls->ls_ops = lm; + ls->ls_first = 1; + ls->ls_id = 0; - if (gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_ops) || - gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_lvb_size >= - GFS2_MIN_LVB_SIZE)) { - gfs2_unmount_lockproto(&sdp->sd_lockstruct); - goto out; + for (options = args->ar_hostdata; (o = strsep(&options, ":")); ) { + substring_t tmp[MAX_OPT_ARGS]; + int token, option; + + if (!o || !*o) + continue; + + token = match_token(o, *lm->lm_tokens, tmp); + switch (token) { + case Opt_jid: + ret = match_int(&tmp[0], &option); + if (ret || option < 0) + goto hostdata_error; + ls->ls_jid = option; + break; + case Opt_id: + ret = match_int(&tmp[0], &option); + if (ret) + goto hostdata_error; + ls->ls_id = option; + break; + case Opt_first: + ret = match_int(&tmp[0], &option); + if (ret || (option != 0 && option != 1)) + goto hostdata_error; + ls->ls_first = option; + break; + case Opt_nodir: + ret = match_int(&tmp[0], &option); + if (ret || (option != 0 && option != 1)) + goto hostdata_error; + ls->ls_nodir = option; + break; + case Opt_err: + default: +hostdata_error: + fs_info(sdp, "unknown hostdata (%s)\n", o); + return -EINVAL; + } } if (sdp->sd_args.ar_spectator) @@ -1074,22 +1125,25 @@ static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent) snprintf(sdp->sd_fsname, GFS2_FSNAME_LEN, "%s.%u", table, sdp->sd_lockstruct.ls_jid); - fs_info(sdp, "Joined cluster. Now mounting FS...\n"); - - if ((sdp->sd_lockstruct.ls_flags & LM_LSFLAG_LOCAL) && - !sdp->sd_args.ar_ignore_local_fs) { - sdp->sd_args.ar_localflocks = 1; - sdp->sd_args.ar_localcaching = 1; + fsname = strchr(table, ':'); + if (fsname) + fsname++; + if (lm->lm_mount == NULL) { + fs_info(sdp, "Now mounting FS...\n"); + return 0; } - -out: - return error; + ret = lm->lm_mount(sdp, fsname); + if (ret == 0) + fs_info(sdp, "Joined cluster. Now mounting FS...\n"); + return ret; } void gfs2_lm_unmount(struct gfs2_sbd *sdp) { - if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) - gfs2_unmount_lockproto(&sdp->sd_lockstruct); + const struct lm_lockops *lm = sdp->sd_lockstruct.ls_ops; + if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) && + lm->lm_unmount) + lm->lm_unmount(sdp); } /** diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index 49877546beb..abd5429ae28 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index f0699ac453f..4ecdad026ea 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include "gfs2.h" diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index e8ef0f80fb1..8d53f66b5bc 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -45,7 +45,6 @@ #include #include #include -#include #include #include @@ -108,7 +107,7 @@ int gfs2_shrink_qd_memory(int nr, gfp_t gfp_mask) gfs2_assert_warn(sdp, !qd->qd_slot_count); gfs2_assert_warn(sdp, !qd->qd_bh_count); - gfs2_lvb_unhold(qd->qd_gl); + gfs2_glock_put(qd->qd_gl); atomic_dec(&sdp->sd_quota_count); /* Delete it from the common reclaim list */ @@ -157,11 +156,6 @@ static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id, if (error) goto fail; - error = gfs2_lvb_hold(qd->qd_gl); - gfs2_glock_put(qd->qd_gl); - if (error) - goto fail; - *qdp = qd; return 0; @@ -211,7 +205,7 @@ static int qd_get(struct gfs2_sbd *sdp, int user, u32 id, int create, if (qd || !create) { if (new_qd) { - gfs2_lvb_unhold(new_qd->qd_gl); + gfs2_glock_put(new_qd->qd_gl); kmem_cache_free(gfs2_quotad_cachep, new_qd); } *qdp = qd; @@ -1280,7 +1274,7 @@ void gfs2_quota_cleanup(struct gfs2_sbd *sdp) gfs2_assert_warn(sdp, qd->qd_slot_count == 1); gfs2_assert_warn(sdp, !qd->qd_bh_count); - gfs2_lvb_unhold(qd->qd_gl); + gfs2_glock_put(qd->qd_gl); kmem_cache_free(gfs2_quotad_cachep, qd); spin_lock(&qd_lru_lock); diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c index efd09c3d2b2..247e8f7d6b3 100644 --- a/fs/gfs2/recovery.c +++ b/fs/gfs2/recovery.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include @@ -427,20 +426,23 @@ static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header_host *hea } -static void gfs2_lm_recovery_done(struct gfs2_sbd *sdp, unsigned int jid, - unsigned int message) +static void gfs2_recovery_done(struct gfs2_sbd *sdp, unsigned int jid, + unsigned int message) { - if (!sdp->sd_lockstruct.ls_ops->lm_recovery_done) - return; - - if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) - sdp->sd_lockstruct.ls_ops->lm_recovery_done( - sdp->sd_lockstruct.ls_lockspace, jid, message); + char env_jid[20]; + char env_status[20]; + char *envp[] = { env_jid, env_status, NULL }; + struct lm_lockstruct *ls = &sdp->sd_lockstruct; + ls->ls_recover_jid_done = jid; + ls->ls_recover_jid_status = message; + sprintf(env_jid, "JID=%d", jid); + sprintf(env_status, "RECOVERY=%s", + message == LM_RD_SUCCESS ? "Done" : "Failed"); + kobject_uevent_env(&sdp->sd_kobj, KOBJ_CHANGE, envp); } - /** - * gfs2_recover_journal - recovery a given journal + * gfs2_recover_journal - recover a given journal * @jd: the struct gfs2_jdesc describing the journal * * Acquire the journal's lock, check to see if the journal is clean, and @@ -561,7 +563,7 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd) if (jd->jd_jid != sdp->sd_lockstruct.ls_jid) gfs2_glock_dq_uninit(&ji_gh); - gfs2_lm_recovery_done(sdp, jd->jd_jid, LM_RD_SUCCESS); + gfs2_recovery_done(sdp, jd->jd_jid, LM_RD_SUCCESS); if (jd->jd_jid != sdp->sd_lockstruct.ls_jid) gfs2_glock_dq_uninit(&j_gh); @@ -581,7 +583,7 @@ fail_gunlock_j: fs_info(sdp, "jid=%u: %s\n", jd->jd_jid, (error) ? "Failed" : "Done"); fail: - gfs2_lm_recovery_done(sdp, jd->jd_jid, LM_RD_GAVEUP); + gfs2_recovery_done(sdp, jd->jd_jid, LM_RD_GAVEUP); return error; } diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 8b01c635d92..ba5a021b1c5 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include "gfs2.h" diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 141b781f2fc..7cf302b135c 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -15,7 +15,6 @@ #include #include #include -#include #include "gfs2.h" #include "incore.h" diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index a58a120dac9..a78997ea503 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c @@ -14,9 +14,8 @@ #include #include #include -#include -#include #include +#include #include "gfs2.h" #include "incore.h" @@ -224,14 +223,145 @@ static struct lockstruct_attr lockstruct_attr_##name = __ATTR_RO(name) LOCKSTRUCT_ATTR(jid, "%u\n"); LOCKSTRUCT_ATTR(first, "%u\n"); -LOCKSTRUCT_ATTR(lvb_size, "%u\n"); -LOCKSTRUCT_ATTR(flags, "%d\n"); static struct attribute *lockstruct_attrs[] = { &lockstruct_attr_jid.attr, &lockstruct_attr_first.attr, - &lockstruct_attr_lvb_size.attr, - &lockstruct_attr_flags.attr, + NULL, +}; + +/* + * lock_module. Originally from lock_dlm + */ + +static ssize_t proto_name_show(struct gfs2_sbd *sdp, char *buf) +{ + const struct lm_lockops *ops = sdp->sd_lockstruct.ls_ops; + return sprintf(buf, "%s\n", ops->lm_proto_name); +} + +static ssize_t block_show(struct gfs2_sbd *sdp, char *buf) +{ + struct lm_lockstruct *ls = &sdp->sd_lockstruct; + ssize_t ret; + int val = 0; + + if (test_bit(DFL_BLOCK_LOCKS, &ls->ls_flags)) + val = 1; + ret = sprintf(buf, "%d\n", val); + return ret; +} + +static ssize_t block_store(struct gfs2_sbd *sdp, const char *buf, size_t len) +{ + struct lm_lockstruct *ls = &sdp->sd_lockstruct; + ssize_t ret = len; + int val; + + val = simple_strtol(buf, NULL, 0); + + if (val == 1) + set_bit(DFL_BLOCK_LOCKS, &ls->ls_flags); + else if (val == 0) { + clear_bit(DFL_BLOCK_LOCKS, &ls->ls_flags); + smp_mb__after_clear_bit(); + gfs2_glock_thaw(sdp); + } else { + ret = -EINVAL; + } + return ret; +} + +static ssize_t lkid_show(struct gfs2_sbd *sdp, char *buf) +{ + struct lm_lockstruct *ls = &sdp->sd_lockstruct; + return sprintf(buf, "%u\n", ls->ls_id); +} + +static ssize_t lkfirst_show(struct gfs2_sbd *sdp, char *buf) +{ + struct lm_lockstruct *ls = &sdp->sd_lockstruct; + return sprintf(buf, "%d\n", ls->ls_first); +} + +static ssize_t first_done_show(struct gfs2_sbd *sdp, char *buf) +{ + struct lm_lockstruct *ls = &sdp->sd_lockstruct; + return sprintf(buf, "%d\n", ls->ls_first_done); +} + +static ssize_t recover_show(struct gfs2_sbd *sdp, char *buf) +{ + struct lm_lockstruct *ls = &sdp->sd_lockstruct; + return sprintf(buf, "%d\n", ls->ls_recover_jid); +} + +static void gfs2_jdesc_make_dirty(struct gfs2_sbd *sdp, unsigned int jid) +{ + struct gfs2_jdesc *jd; + + spin_lock(&sdp->sd_jindex_spin); + list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) { + if (jd->jd_jid != jid) + continue; + jd->jd_dirty = 1; + break; + } + spin_unlock(&sdp->sd_jindex_spin); +} + +static ssize_t recover_store(struct gfs2_sbd *sdp, const char *buf, size_t len) +{ + struct lm_lockstruct *ls = &sdp->sd_lockstruct; + ls->ls_recover_jid = simple_strtol(buf, NULL, 0); + gfs2_jdesc_make_dirty(sdp, ls->ls_recover_jid); + if (sdp->sd_recoverd_process) + wake_up_process(sdp->sd_recoverd_process); + return len; +} + +static ssize_t recover_done_show(struct gfs2_sbd *sdp, char *buf) +{ + struct lm_lockstruct *ls = &sdp->sd_lockstruct; + return sprintf(buf, "%d\n", ls->ls_recover_jid_done); +} + +static ssize_t recover_status_show(struct gfs2_sbd *sdp, char *buf) +{ + struct lm_lockstruct *ls = &sdp->sd_lockstruct; + return sprintf(buf, "%d\n", ls->ls_recover_jid_status); +} + +struct gdlm_attr { + struct attribute attr; + ssize_t (*show)(struct gfs2_sbd *sdp, char *); + ssize_t (*store)(struct gfs2_sbd *sdp, const char *, size_t); +}; + +#define GDLM_ATTR(_name,_mode,_show,_store) \ +static struct gdlm_attr gdlm_attr_##_name = __ATTR(_name,_mode,_show,_store) + +GDLM_ATTR(proto_name, 0444, proto_name_show, NULL); +GDLM_ATTR(block, 0644, block_show, block_store); +GDLM_ATTR(withdraw, 0644, withdraw_show, withdraw_store); +GDLM_ATTR(id, 0444, lkid_show, NULL); +GDLM_ATTR(first, 0444, lkfirst_show, NULL); +GDLM_ATTR(first_done, 0444, first_done_show, NULL); +GDLM_ATTR(recover, 0644, recover_show, recover_store); +GDLM_ATTR(recover_done, 0444, recover_done_show, NULL); +GDLM_ATTR(recover_status, 0444, recover_status_show, NULL); + +static struct attribute *lock_module_attrs[] = { + &gdlm_attr_proto_name.attr, + &gdlm_attr_block.attr, + &gdlm_attr_withdraw.attr, + &gdlm_attr_id.attr, + &lockstruct_attr_jid.attr, + &gdlm_attr_first.attr, + &gdlm_attr_first_done.attr, + &gdlm_attr_recover.attr, + &gdlm_attr_recover_done.attr, + &gdlm_attr_recover_status.attr, NULL, }; @@ -412,6 +542,11 @@ static struct attribute_group tune_group = { .attrs = tune_attrs, }; +static struct attribute_group lock_module_group = { + .name = "lock_module", + .attrs = lock_module_attrs, +}; + int gfs2_sys_fs_add(struct gfs2_sbd *sdp) { int error; @@ -434,9 +569,15 @@ int gfs2_sys_fs_add(struct gfs2_sbd *sdp) if (error) goto fail_args; + error = sysfs_create_group(&sdp->sd_kobj, &lock_module_group); + if (error) + goto fail_tune; + kobject_uevent(&sdp->sd_kobj, KOBJ_ADD); return 0; +fail_tune: + sysfs_remove_group(&sdp->sd_kobj, &tune_group); fail_args: sysfs_remove_group(&sdp->sd_kobj, &args_group); fail_lockstruct: @@ -453,6 +594,7 @@ void gfs2_sys_fs_del(struct gfs2_sbd *sdp) sysfs_remove_group(&sdp->sd_kobj, &tune_group); sysfs_remove_group(&sdp->sd_kobj, &args_group); sysfs_remove_group(&sdp->sd_kobj, &lockstruct_group); + sysfs_remove_group(&sdp->sd_kobj, &lock_module_group); kobject_put(&sdp->sd_kobj); } diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c index f677b8a83f0..33cd523ec97 100644 --- a/fs/gfs2/trans.c +++ b/fs/gfs2/trans.c @@ -12,9 +12,8 @@ #include #include #include -#include #include -#include +#include #include "gfs2.h" #include "incore.h" diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c index 374f50e9549..9d12b1118ba 100644 --- a/fs/gfs2/util.c +++ b/fs/gfs2/util.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include "gfs2.h" @@ -35,6 +34,8 @@ void gfs2_assert_i(struct gfs2_sbd *sdp) int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...) { + struct lm_lockstruct *ls = &sdp->sd_lockstruct; + const struct lm_lockops *lm = ls->ls_ops; va_list args; if (test_and_set_bit(SDF_SHUTDOWN, &sdp->sd_flags)) @@ -47,8 +48,12 @@ int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...) fs_err(sdp, "about to withdraw this file system\n"); BUG_ON(sdp->sd_args.ar_debug); - fs_err(sdp, "telling LM to withdraw\n"); - gfs2_withdraw_lockproto(&sdp->sd_lockstruct); + kobject_uevent(&sdp->sd_kobj, KOBJ_OFFLINE); + + if (lm->lm_unmount) { + fs_err(sdp, "telling LM to unmount\n"); + lm->lm_unmount(sdp); + } fs_err(sdp, "withdrawn\n"); dump_stack(); diff --git a/include/linux/lm_interface.h b/include/linux/lm_interface.h deleted file mode 100644 index 2ed8fa1b762..00000000000 --- a/include/linux/lm_interface.h +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. - * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. - * - * This copyrighted material is made available to anyone wishing to use, - * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU General Public License version 2. - */ - -#ifndef __LM_INTERFACE_DOT_H__ -#define __LM_INTERFACE_DOT_H__ - - -typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data); - -/* - * lm_mount() flags - * - * LM_MFLAG_SPECTATOR - * GFS is asking to join the filesystem's lockspace, but it doesn't want to - * modify the filesystem. The lock module shouldn't assign a journal to the FS - * mount. It shouldn't send recovery callbacks to the FS mount. If the node - * dies or withdraws, all locks can be wiped immediately. - * - * LM_MFLAG_CONV_NODROP - * Do not allow the dlm to internally resolve conversion deadlocks by demoting - * the lock to unlocked and then reacquiring it in the requested mode. Instead, - * it should cancel the request and return LM_OUT_CONV_DEADLK. - */ - -#define LM_MFLAG_SPECTATOR 0x00000001 -#define LM_MFLAG_CONV_NODROP 0x00000002 - -/* - * lm_lockstruct flags - * - * LM_LSFLAG_LOCAL - * The lock_nolock module returns LM_LSFLAG_LOCAL to GFS, indicating that GFS - * can make single-node optimizations. - */ - -#define LM_LSFLAG_LOCAL 0x00000001 - -/* - * lm_lockname types - */ - -#define LM_TYPE_RESERVED 0x00 -#define LM_TYPE_NONDISK 0x01 -#define LM_TYPE_INODE 0x02 -#define LM_TYPE_RGRP 0x03 -#define LM_TYPE_META 0x04 -#define LM_TYPE_IOPEN 0x05 -#define LM_TYPE_FLOCK 0x06 -#define LM_TYPE_PLOCK 0x07 -#define LM_TYPE_QUOTA 0x08 -#define LM_TYPE_JOURNAL 0x09 - -/* - * lm_lock() states - * - * SHARED is compatible with SHARED, not with DEFERRED or EX. - * DEFERRED is compatible with DEFERRED, not with SHARED or EX. - */ - -#define LM_ST_UNLOCKED 0 -#define LM_ST_EXCLUSIVE 1 -#define LM_ST_DEFERRED 2 -#define LM_ST_SHARED 3 - -/* - * lm_lock() flags - * - * LM_FLAG_TRY - * Don't wait to acquire the lock if it can't be granted immediately. - * - * LM_FLAG_TRY_1CB - * Send one blocking callback if TRY is set and the lock is not granted. - * - * LM_FLAG_NOEXP - * GFS sets this flag on lock requests it makes while doing journal recovery. - * These special requests should not be blocked due to the recovery like - * ordinary locks would be. - * - * LM_FLAG_ANY - * A SHARED request may also be granted in DEFERRED, or a DEFERRED request may - * also be granted in SHARED. The preferred state is whichever is compatible - * with other granted locks, or the specified state if no other locks exist. - * - * LM_FLAG_PRIORITY - * Override fairness considerations. Suppose a lock is held in a shared state - * and there is a pending request for the deferred state. A shared lock - * request with the priority flag would be allowed to bypass the deferred - * request and directly join the other shared lock. A shared lock request - * without the priority flag might be forced to wait until the deferred - * requested had acquired and released the lock. - */ - -#define LM_FLAG_TRY 0x00000001 -#define LM_FLAG_TRY_1CB 0x00000002 -#define LM_FLAG_NOEXP 0x00000004 -#define LM_FLAG_ANY 0x00000008 -#define LM_FLAG_PRIORITY 0x00000010 - -/* - * lm_lock() and lm_async_cb return flags - * - * LM_OUT_ST_MASK - * Masks the lower two bits of lock state in the returned value. - * - * LM_OUT_CACHEABLE - * The lock hasn't been released so GFS can continue to cache data for it. - * - * LM_OUT_CANCELED - * The lock request was canceled. - * - * LM_OUT_ASYNC - * The result of the request will be returned in an LM_CB_ASYNC callback. - * - * LM_OUT_CONV_DEADLK - * The lock request was canceled do to a conversion deadlock. - */ - -#define LM_OUT_ST_MASK 0x00000003 -#define LM_OUT_CANCELED 0x00000008 -#define LM_OUT_ASYNC 0x00000080 -#define LM_OUT_ERROR 0x00000100 - -/* - * lm_callback_t types - * - * LM_CB_NEED_E LM_CB_NEED_D LM_CB_NEED_S - * Blocking callback, a remote node is requesting the given lock in - * EXCLUSIVE, DEFERRED, or SHARED. - * - * LM_CB_NEED_RECOVERY - * The given journal needs to be recovered. - * - * LM_CB_ASYNC - * The given lock has been granted. - */ - -#define LM_CB_NEED_E 257 -#define LM_CB_NEED_D 258 -#define LM_CB_NEED_S 259 -#define LM_CB_NEED_RECOVERY 260 -#define LM_CB_ASYNC 262 - -/* - * lm_recovery_done() messages - */ - -#define LM_RD_GAVEUP 308 -#define LM_RD_SUCCESS 309 - - -struct lm_lockname { - u64 ln_number; - unsigned int ln_type; -}; - -#define lm_name_equal(name1, name2) \ - (((name1)->ln_number == (name2)->ln_number) && \ - ((name1)->ln_type == (name2)->ln_type)) \ - -struct lm_async_cb { - struct lm_lockname lc_name; - int lc_ret; -}; - -struct lm_lockstruct; - -struct lm_lockops { - const char *lm_proto_name; - - /* - * Mount/Unmount - */ - - int (*lm_mount) (char *table_name, char *host_data, - lm_callback_t cb, void *cb_data, - unsigned int min_lvb_size, int flags, - struct lm_lockstruct *lockstruct, - struct kobject *fskobj); - - void (*lm_others_may_mount) (void *lockspace); - - void (*lm_unmount) (void *lockspace); - - void (*lm_withdraw) (void *lockspace); - - /* - * Lock oriented operations - */ - - int (*lm_get_lock) (void *lockspace, struct lm_lockname *name, void **lockp); - - void (*lm_put_lock) (void *lock); - - unsigned int (*lm_lock) (void *lock, unsigned int cur_state, - unsigned int req_state, unsigned int flags); - - unsigned int (*lm_unlock) (void *lock, unsigned int cur_state); - - void (*lm_cancel) (void *lock); - - int (*lm_hold_lvb) (void *lock, char **lvbp); - void (*lm_unhold_lvb) (void *lock, char *lvb); - - /* - * Posix Lock oriented operations - */ - - int (*lm_plock_get) (void *lockspace, struct lm_lockname *name, - struct file *file, struct file_lock *fl); - - int (*lm_plock) (void *lockspace, struct lm_lockname *name, - struct file *file, int cmd, struct file_lock *fl); - - int (*lm_punlock) (void *lockspace, struct lm_lockname *name, - struct file *file, struct file_lock *fl); - - /* - * Client oriented operations - */ - - void (*lm_recovery_done) (void *lockspace, unsigned int jid, - unsigned int message); - - struct module *lm_owner; -}; - -/* - * lm_mount() return values - * - * ls_jid - the journal ID this node should use - * ls_first - this node is the first to mount the file system - * ls_lvb_size - size in bytes of lock value blocks - * ls_lockspace - lock module's context for this file system - * ls_ops - lock module's functions - * ls_flags - lock module features - */ - -struct lm_lockstruct { - unsigned int ls_jid; - unsigned int ls_first; - unsigned int ls_lvb_size; - void *ls_lockspace; - const struct lm_lockops *ls_ops; - int ls_flags; -}; - -/* - * Lock module bottom interface. A lock module makes itself available to GFS - * with these functions. - */ - -int gfs2_register_lockproto(const struct lm_lockops *proto); -void gfs2_unregister_lockproto(const struct lm_lockops *proto); - -/* - * Lock module top interface. GFS calls these functions when mounting or - * unmounting a file system. - */ - -int gfs2_mount_lockproto(char *proto_name, char *table_name, char *host_data, - lm_callback_t cb, void *cb_data, - unsigned int min_lvb_size, int flags, - struct lm_lockstruct *lockstruct, - struct kobject *fskobj); - -void gfs2_unmount_lockproto(struct lm_lockstruct *lockstruct); - -void gfs2_withdraw_lockproto(struct lm_lockstruct *lockstruct); - -#endif /* __LM_INTERFACE_DOT_H__ */ - -- GitLab From ac2425e7d319dec0523e52ee120a158ce6668cbd Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Tue, 13 Jan 2009 09:53:43 +0000 Subject: [PATCH 4139/4982] GFS2: Remove unused field from glock The time stamp field is unused in the glock now that we are using a shrinker, so that we can remove it and save sizeof(unsigned long) bytes in each glock. Signed-off-by: Steven Whitehouse --- fs/gfs2/glock.c | 2 -- fs/gfs2/incore.h | 1 - 2 files changed, 3 deletions(-) diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index cd200a564c7..173e59ce9ad 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -700,7 +700,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, snprintf(gl->gl_strname, GDLM_STRNAME_BYTES, "%8x%16llx", name.ln_type, (unsigned long long)number); memset(&gl->gl_lksb, 0, sizeof(struct dlm_lksb)); gl->gl_lksb.sb_lvbptr = gl->gl_lvb; - gl->gl_stamp = jiffies; gl->gl_tchange = jiffies; gl->gl_object = NULL; gl->gl_sbd = sdp; @@ -1008,7 +1007,6 @@ void gfs2_glock_dq(struct gfs2_holder *gh) spin_lock(&gl->gl_spin); clear_bit(GLF_LOCK, &gl->gl_flags); } - gl->gl_stamp = jiffies; if (list_empty(&gl->gl_holders) && !test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) && !test_bit(GLF_DEMOTE, &gl->gl_flags)) diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 0af7c24de6a..8fe0675120a 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -211,7 +211,6 @@ struct gfs2_glock { char gl_strname[GDLM_STRNAME_BYTES]; struct dlm_lksb gl_lksb; char gl_lvb[32]; - unsigned long gl_stamp; unsigned long gl_tchange; void *gl_object; -- GitLab From e7c8707ea2b9106f0f78c43348ff5d5e82ba7961 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Tue, 20 Jan 2009 16:39:23 +0000 Subject: [PATCH 4140/4982] GFS2: Fix error path ref counting for root inode We were keeping hold of an extra ref to the root inode in one of the error paths, that resulted in a hang. Reported-by: Nate Straz Signed-off-by: Steven Whitehouse Tested-by: Robert Peterson --- fs/gfs2/ops_fstype.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 95bb33e41a7..e502b379a4d 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -1258,6 +1258,8 @@ fail_sb: dput(sdp->sd_root_dir); if (sdp->sd_master_dir) dput(sdp->sd_master_dir); + if (sb->s_root) + dput(sb->s_root); sb->s_root = NULL; fail_locking: init_locking(sdp, &mount_gh, UNDO); -- GitLab From d8348de06f704fc34d24ec068546ecb1045fc11a Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Thu, 5 Feb 2009 10:12:38 +0000 Subject: [PATCH 4141/4982] GFS2: Fix deadlock on journal flush This patch fixes a deadlock when the journal is flushed and there are dirty inodes other than the one which caused the journal flush. Originally the journal flushing code was trying to obtain the transaction glock while running the flush code for an inode glock. We no longer require the transaction glock at this point in time since we know that any attempt to get the transaction glock from another node will result in a journal flush. So if we are flushing the journal, we can be sure that the transaction lock is still cached from when the transaction was started. By inlining a version of gfs2_trans_begin() (minus the bit which gets the transaction glock) we can avoid the deadlock problems caused if there is a demote request queued up on the transaction glock. In addition I've also moved the umount rwsem so that it covers the glock workqueue, since it all demotions are done by this workqueue now. That fixes a bug on umount which I came across while fixing the original problem. Reported-by: David Teigland Signed-off-by: Steven Whitehouse --- fs/gfs2/glock.c | 26 ++++++++++++-------------- fs/gfs2/glops.c | 19 ++++++++++++------- fs/gfs2/trans.c | 16 ++++++++++------ 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 173e59ce9ad..ad8e121427c 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -167,6 +167,7 @@ static void glock_free(struct gfs2_glock *gl) static void gfs2_glock_hold(struct gfs2_glock *gl) { + GLOCK_BUG_ON(gl, atomic_read(&gl->gl_ref) == 0); atomic_inc(&gl->gl_ref); } @@ -206,16 +207,15 @@ int gfs2_glock_put(struct gfs2_glock *gl) atomic_dec(&lru_count); } spin_unlock(&lru_lock); - GLOCK_BUG_ON(gl, !list_empty(&gl->gl_lru)); GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders)); glock_free(gl); rv = 1; goto out; } - write_unlock(gl_lock_addr(gl->gl_hash)); /* 1 for being hashed, 1 for having state != LM_ST_UNLOCKED */ if (atomic_read(&gl->gl_ref) == 2) gfs2_glock_schedule_for_reclaim(gl); + write_unlock(gl_lock_addr(gl->gl_hash)); out: return rv; } @@ -597,10 +597,11 @@ __acquires(&gl->gl_spin) GLOCK_BUG_ON(gl, test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags)); + down_read(&gfs2_umount_flush_sem); if (test_bit(GLF_DEMOTE, &gl->gl_flags) && gl->gl_demote_state != gl->gl_state) { if (find_first_holder(gl)) - goto out; + goto out_unlock; if (nonblock) goto out_sched; set_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags); @@ -611,23 +612,26 @@ __acquires(&gl->gl_spin) gfs2_demote_wake(gl); ret = do_promote(gl); if (ret == 0) - goto out; + goto out_unlock; if (ret == 2) - return; + goto out_sem; gh = find_first_waiter(gl); gl->gl_target = gh->gh_state; if (!(gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))) do_error(gl, 0); /* Fail queued try locks */ } do_xmote(gl, gh, gl->gl_target); +out_sem: + up_read(&gfs2_umount_flush_sem); return; out_sched: gfs2_glock_hold(gl); if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) gfs2_glock_put(gl); -out: +out_unlock: clear_bit(GLF_LOCK, &gl->gl_flags); + goto out_sem; } static void glock_work_func(struct work_struct *work) @@ -1225,7 +1229,6 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state) void gfs2_glock_complete(struct gfs2_glock *gl, int ret) { struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct; - down_read(&gfs2_umount_flush_sem); gl->gl_reply = ret; if (unlikely(test_bit(DFL_BLOCK_LOCKS, &ls->ls_flags))) { struct gfs2_holder *gh; @@ -1236,16 +1239,13 @@ void gfs2_glock_complete(struct gfs2_glock *gl, int ret) ((ret & ~LM_OUT_ST_MASK) != 0)) set_bit(GLF_FROZEN, &gl->gl_flags); spin_unlock(&gl->gl_spin); - if (test_bit(GLF_FROZEN, &gl->gl_flags)) { - up_read(&gfs2_umount_flush_sem); + if (test_bit(GLF_FROZEN, &gl->gl_flags)) return; - } } set_bit(GLF_REPLY_PENDING, &gl->gl_flags); gfs2_glock_hold(gl); if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) gfs2_glock_put(gl); - up_read(&gfs2_umount_flush_sem); } /** @@ -1389,12 +1389,10 @@ static void thaw_glock(struct gfs2_glock *gl) { if (!test_and_clear_bit(GLF_FROZEN, &gl->gl_flags)) return; - down_read(&gfs2_umount_flush_sem); set_bit(GLF_REPLY_PENDING, &gl->gl_flags); gfs2_glock_hold(gl); if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) gfs2_glock_put(gl); - up_read(&gfs2_umount_flush_sem); } /** @@ -1580,7 +1578,7 @@ static const char *gflags2str(char *buf, const unsigned long *gflags) if (test_bit(GLF_REPLY_PENDING, gflags)) *p++ = 'r'; if (test_bit(GLF_INITIAL, gflags)) - *p++ = 'i'; + *p++ = 'I'; if (test_bit(GLF_FROZEN, gflags)) *p++ = 'F'; *p = 0; diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index f07ede8cb9b..a9b7d3a6008 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c @@ -37,20 +37,25 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl) { struct gfs2_sbd *sdp = gl->gl_sbd; - unsigned int blocks; struct list_head *head = &gl->gl_ail_list; struct gfs2_bufdata *bd; struct buffer_head *bh; - int error; + struct gfs2_trans tr; - blocks = atomic_read(&gl->gl_ail_count); - if (!blocks) - return; + memset(&tr, 0, sizeof(tr)); + tr.tr_revokes = atomic_read(&gl->gl_ail_count); - error = gfs2_trans_begin(sdp, 0, blocks); - if (gfs2_assert_withdraw(sdp, !error)) + if (!tr.tr_revokes) return; + /* A shortened, inline version of gfs2_trans_begin() */ + tr.tr_reserved = 1 + gfs2_struct2blk(sdp, tr.tr_revokes, sizeof(u64)); + tr.tr_ip = (unsigned long)__builtin_return_address(0); + INIT_LIST_HEAD(&tr.tr_list_buf); + gfs2_log_reserve(sdp, tr.tr_reserved); + BUG_ON(current->journal_info); + current->journal_info = &tr; + gfs2_log_lock(sdp); while (!list_empty(head)) { bd = list_entry(head->next, struct gfs2_bufdata, diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c index 33cd523ec97..053752d4b27 100644 --- a/fs/gfs2/trans.c +++ b/fs/gfs2/trans.c @@ -87,9 +87,11 @@ void gfs2_trans_end(struct gfs2_sbd *sdp) if (!tr->tr_touched) { gfs2_log_release(sdp, tr->tr_reserved); - gfs2_glock_dq(&tr->tr_t_gh); - gfs2_holder_uninit(&tr->tr_t_gh); - kfree(tr); + if (tr->tr_t_gh.gh_gl) { + gfs2_glock_dq(&tr->tr_t_gh); + gfs2_holder_uninit(&tr->tr_t_gh); + kfree(tr); + } return; } @@ -105,9 +107,11 @@ void gfs2_trans_end(struct gfs2_sbd *sdp) } gfs2_log_commit(sdp, tr); - gfs2_glock_dq(&tr->tr_t_gh); - gfs2_holder_uninit(&tr->tr_t_gh); - kfree(tr); + if (tr->tr_t_gh.gh_gl) { + gfs2_glock_dq(&tr->tr_t_gh); + gfs2_holder_uninit(&tr->tr_t_gh); + kfree(tr); + } if (sdp->sd_vfs->s_flags & MS_SYNCHRONOUS) gfs2_log_flush(sdp, NULL); -- GitLab From f15ab5619d8068a321094f4705147764d689e88e Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Mon, 9 Feb 2009 09:25:01 +0000 Subject: [PATCH 4142/4982] GFS2: Support generation of discard requests This patch allows GFS2 to generate discard requests for blocks which are no longer useful to the filesystem (i.e. those which have been freed as the result of an unlink operation). The requests are generated at the time which those blocks become available for reuse in the filesystem. In order to use this new feature, you have to specify the "discard" mount option. The code coalesces adjacent blocks into a single extent when generating the discard requests, thus generating the minimum number. If an error occurs when the request has been sent to the block device, then it will print a message and turn off the requests for that filesystem. If the problem is temporary, then you can use remount to turn the option back on again. There is also a nodiscard mount option so that you can use remount to turn discard requests off, if required. Signed-off-by: Steven Whitehouse --- fs/gfs2/incore.h | 2 +- fs/gfs2/mount.c | 10 +++++++++ fs/gfs2/ops_super.c | 2 ++ fs/gfs2/rgrp.c | 55 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 1 deletion(-) diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 8fe0675120a..3f29bd224ba 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -416,7 +416,7 @@ struct gfs2_args { unsigned int ar_suiddir:1; /* suiddir support */ unsigned int ar_data:2; /* ordered/writeback */ unsigned int ar_meta:1; /* mount metafs */ - unsigned int ar_num_glockd; /* Number of glockd threads */ + unsigned int ar_discard:1; /* discard requests */ }; struct gfs2_tune { diff --git a/fs/gfs2/mount.c b/fs/gfs2/mount.c index fba502aa8b2..ee69701a777 100644 --- a/fs/gfs2/mount.c +++ b/fs/gfs2/mount.c @@ -41,6 +41,8 @@ enum { Opt_data_writeback, Opt_data_ordered, Opt_meta, + Opt_discard, + Opt_nodiscard, Opt_err, }; @@ -65,6 +67,8 @@ static const match_table_t tokens = { {Opt_data_writeback, "data=writeback"}, {Opt_data_ordered, "data=ordered"}, {Opt_meta, "meta"}, + {Opt_discard, "discard"}, + {Opt_nodiscard, "nodiscard"}, {Opt_err, NULL} }; @@ -157,6 +161,12 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options) case Opt_meta: args->ar_meta = 1; break; + case Opt_discard: + args->ar_discard = 1; + break; + case Opt_nodiscard: + args->ar_discard = 0; + break; case Opt_err: default: fs_info(sdp, "invalid mount option: %s\n", o); diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index 4ecdad026ea..458019569dc 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c @@ -608,6 +608,8 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) } seq_printf(s, ",data=%s", state); } + if (args->ar_discard) + seq_printf(s, ",discard"); return 0; } diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index ba5a021b1c5..789953a2b6a 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "gfs2.h" #include "incore.h" @@ -830,6 +831,58 @@ void gfs2_rgrp_bh_put(struct gfs2_rgrpd *rgd) spin_unlock(&sdp->sd_rindex_spin); } +static void gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset, + const struct gfs2_bitmap *bi) +{ + struct super_block *sb = sdp->sd_vfs; + struct block_device *bdev = sb->s_bdev; + const unsigned int sects_per_blk = sdp->sd_sb.sb_bsize / + bdev_hardsect_size(sb->s_bdev); + u64 blk; + sector_t start; + sector_t nr_sects = 0; + int rv; + unsigned int x; + + for (x = 0; x < bi->bi_len; x++) { + const u8 *orig = bi->bi_bh->b_data + bi->bi_offset + x; + const u8 *clone = bi->bi_clone + bi->bi_offset + x; + u8 diff = ~(*orig | (*orig >> 1)) & (*clone | (*clone >> 1)); + diff &= 0x55; + if (diff == 0) + continue; + blk = offset + ((bi->bi_start + x) * GFS2_NBBY); + blk *= sects_per_blk; /* convert to sectors */ + while(diff) { + if (diff & 1) { + if (nr_sects == 0) + goto start_new_extent; + if ((start + nr_sects) != blk) { + rv = blkdev_issue_discard(bdev, start, + nr_sects, GFP_NOFS); + if (rv) + goto fail; + nr_sects = 0; +start_new_extent: + start = blk; + } + nr_sects += sects_per_blk; + } + diff >>= 2; + blk += sects_per_blk; + } + } + if (nr_sects) { + rv = blkdev_issue_discard(bdev, start, nr_sects, GFP_NOFS); + if (rv) + goto fail; + } + return; +fail: + fs_warn(sdp, "error %d on discard request, turning discards off for this filesystem", rv); + sdp->sd_args.ar_discard = 0; +} + void gfs2_rgrp_repolish_clones(struct gfs2_rgrpd *rgd) { struct gfs2_sbd *sdp = rgd->rd_sbd; @@ -840,6 +893,8 @@ void gfs2_rgrp_repolish_clones(struct gfs2_rgrpd *rgd) struct gfs2_bitmap *bi = rgd->rd_bits + x; if (!bi->bi_clone) continue; + if (sdp->sd_args.ar_discard) + gfs2_rgrp_send_discards(sdp, rgd->rd_data0, bi); memcpy(bi->bi_clone + bi->bi_offset, bi->bi_bh->b_data + bi->bi_offset, bi->bi_len); } -- GitLab From 02e3cc70ecbd4352ae4d26459929f43ab1547251 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Tue, 10 Feb 2009 13:48:30 +0000 Subject: [PATCH 4143/4982] GFS2: Expose UUID via sysfs/uevent Since we have a UUID, we ought to expose it to the user via sysfs and uevents. We already have the fs name in both of these places (a combination of the lock proto and lock table name) so if we add the UUID as well, we have a full set. For older filesystems (i.e. those created before mkfs.gfs2 was writing UUIDs by default) the sysfs file will appear zero length, and no UUID env var will be added to the uevents. Signed-off-by: Steven Whitehouse --- fs/gfs2/incore.h | 1 + fs/gfs2/ops_fstype.c | 1 + fs/gfs2/sys.c | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 3f29bd224ba..980a0864ca6 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -470,6 +470,7 @@ struct gfs2_sb_host { char sb_lockproto[GFS2_LOCKNAME_LEN]; char sb_locktable[GFS2_LOCKNAME_LEN]; + u8 sb_uuid[16]; }; /* diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index e502b379a4d..804ca7273a4 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -234,6 +234,7 @@ static void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf) memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN); memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN); + memcpy(sb->sb_uuid, str->sb_uuid, 16); } /** diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index a78997ea503..4d284d14980 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c @@ -36,6 +36,30 @@ static ssize_t fsname_show(struct gfs2_sbd *sdp, char *buf) return snprintf(buf, PAGE_SIZE, "%s\n", sdp->sd_fsname); } +static int gfs2_uuid_valid(const u8 *uuid) +{ + int i; + + for (i = 0; i < 16; i++) { + if (uuid[i]) + return 1; + } + return 0; +} + +static ssize_t uuid_show(struct gfs2_sbd *sdp, char *buf) +{ + const u8 *uuid = sdp->sd_sb.sb_uuid; + buf[0] = '\0'; + if (!gfs2_uuid_valid(uuid)) + return 0; + return snprintf(buf, PAGE_SIZE, "%02X%02X%02X%02X-%02X%02X-" + "%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X\n", + uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], + uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11], + uuid[12], uuid[13], uuid[14], uuid[15]); +} + static ssize_t freeze_show(struct gfs2_sbd *sdp, char *buf) { unsigned int count; @@ -158,6 +182,7 @@ static struct gfs2_attr gfs2_attr_##name = __ATTR(name, mode, show, store) GFS2_ATTR(id, 0444, id_show, NULL); GFS2_ATTR(fsname, 0444, fsname_show, NULL); +GFS2_ATTR(uuid, 0444, uuid_show, NULL); GFS2_ATTR(freeze, 0644, freeze_show, freeze_store); GFS2_ATTR(withdraw, 0644, withdraw_show, withdraw_store); GFS2_ATTR(statfs_sync, 0200, NULL, statfs_sync_store); @@ -168,6 +193,7 @@ GFS2_ATTR(quota_refresh_group, 0200, NULL, quota_refresh_group_store); static struct attribute *gfs2_attrs[] = { &gfs2_attr_id.attr, &gfs2_attr_fsname.attr, + &gfs2_attr_uuid.attr, &gfs2_attr_freeze.attr, &gfs2_attr_withdraw.attr, &gfs2_attr_statfs_sync.attr, @@ -598,12 +624,23 @@ void gfs2_sys_fs_del(struct gfs2_sbd *sdp) kobject_put(&sdp->sd_kobj); } + static int gfs2_uevent(struct kset *kset, struct kobject *kobj, struct kobj_uevent_env *env) { struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj); + const u8 *uuid = sdp->sd_sb.sb_uuid; + add_uevent_var(env, "LOCKTABLE=%s", sdp->sd_table_name); add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name); + if (gfs2_uuid_valid(uuid)) { + add_uevent_var(env, "UUID=%02X%02X%02X%02X-%02X%02X-%02X%02X-" + "%02X%02X-%02X%02X%02X%02X%02X%02X", + uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], + uuid[5], uuid[6], uuid[7], uuid[8], uuid[9], + uuid[10], uuid[11], uuid[12], uuid[13], + uuid[14], uuid[15]); + } return 0; } -- GitLab From 64d576ba23bfd9b770cbb0279200f479272eb859 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Thu, 12 Feb 2009 13:31:58 +0000 Subject: [PATCH 4144/4982] GFS2: Add a "demote a glock" interface to sysfs This adds a sysfs file called demote_rq to GFS2's per filesystem directory. Its possible to use this file to demote arbitrary glocks in exactly the same way as if a request had come in from a remote node. This is intended for testing issues relating to caching of data under glocks. Despite that, the interface is generic enough to send requests to any type of glock, but be careful as its not always safe to send an arbitrary message to an arbitrary glock. For that reason and to prevent DoS, this interface is restricted to root only. The messages look like this: : Example: echo -n "2:13324 EX" >/sys/fs/gfs2/unity:myfs/demote_rq Which means "please demote inode glock (type 2) number 13324 so that I can get an EX (exclusive) lock". The lock modes are those which would normally be sent by a remote node in its callback so if you want to unlock a glock, you use EX, to demote to shared, use SH or PR (depending on whether you like GFS2 or DLM lock modes better!). If the glock doesn't exist, you'll get -ENOENT returned. If the arguments don't make sense, you'll get -EINVAL returned. The plan is that this interface will be used in combination with the blktrace patch which I recently posted for comments although it is, of course, still useful in its own right. Signed-off-by: Steven Whitehouse --- fs/gfs2/glock.c | 7 ++++--- fs/gfs2/glops.c | 12 ++++++++++++ fs/gfs2/glops.h | 1 + fs/gfs2/rgrp.c | 2 +- fs/gfs2/sys.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 61 insertions(+), 4 deletions(-) diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index ad8e121427c..3984e47d1d3 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -684,10 +684,11 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, gl = search_bucket(hash, sdp, &name); read_unlock(gl_lock_addr(hash)); - if (gl || !create) { - *glp = gl; + *glp = gl; + if (gl) return 0; - } + if (!create) + return -ENOENT; gl = kmem_cache_alloc(gfs2_glock_cachep, GFP_KERNEL); if (!gl) diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index a9b7d3a6008..f34bc7093dd 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c @@ -447,3 +447,15 @@ const struct gfs2_glock_operations gfs2_journal_glops = { .go_type = LM_TYPE_JOURNAL, }; +const struct gfs2_glock_operations *gfs2_glops_list[] = { + [LM_TYPE_META] = &gfs2_meta_glops, + [LM_TYPE_INODE] = &gfs2_inode_glops, + [LM_TYPE_RGRP] = &gfs2_rgrp_glops, + [LM_TYPE_NONDISK] = &gfs2_trans_glops, + [LM_TYPE_IOPEN] = &gfs2_iopen_glops, + [LM_TYPE_FLOCK] = &gfs2_flock_glops, + [LM_TYPE_NONDISK] = &gfs2_nondisk_glops, + [LM_TYPE_QUOTA] = &gfs2_quota_glops, + [LM_TYPE_JOURNAL] = &gfs2_journal_glops, +}; + diff --git a/fs/gfs2/glops.h b/fs/gfs2/glops.h index a1d9b5b024e..b3aa2e3210f 100644 --- a/fs/gfs2/glops.h +++ b/fs/gfs2/glops.h @@ -21,5 +21,6 @@ extern const struct gfs2_glock_operations gfs2_flock_glops; extern const struct gfs2_glock_operations gfs2_nondisk_glops; extern const struct gfs2_glock_operations gfs2_quota_glops; extern const struct gfs2_glock_operations gfs2_journal_glops; +extern const struct gfs2_glock_operations *gfs2_glops_list[]; #endif /* __GLOPS_DOT_H__ */ diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 789953a2b6a..a068ac940de 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -839,7 +839,7 @@ static void gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset, const unsigned int sects_per_blk = sdp->sd_sb.sb_bsize / bdev_hardsect_size(sb->s_bdev); u64 blk; - sector_t start; + sector_t start = 0; sector_t nr_sects = 0; int rv; unsigned int x; diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index 4d284d14980..7655f5025fe 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c @@ -24,6 +24,7 @@ #include "glock.h" #include "quota.h" #include "util.h" +#include "glops.h" static ssize_t id_show(struct gfs2_sbd *sdp, char *buf) { @@ -171,6 +172,46 @@ static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf, return len; } +static ssize_t demote_rq_store(struct gfs2_sbd *sdp, const char *buf, size_t len) +{ + struct gfs2_glock *gl; + const struct gfs2_glock_operations *glops; + unsigned int glmode; + unsigned int gltype; + unsigned long long glnum; + char mode[16]; + int rv; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + rv = sscanf(buf, "%u:%llu %15s", &gltype, &glnum, + mode); + if (rv != 3) + return -EINVAL; + + if (strcmp(mode, "EX") == 0) + glmode = LM_ST_UNLOCKED; + else if ((strcmp(mode, "CW") == 0) || (strcmp(mode, "DF") == 0)) + glmode = LM_ST_DEFERRED; + else if ((strcmp(mode, "PR") == 0) || (strcmp(mode, "SH") == 0)) + glmode = LM_ST_SHARED; + else + return -EINVAL; + + if (gltype > LM_TYPE_JOURNAL) + return -EINVAL; + glops = gfs2_glops_list[gltype]; + if (glops == NULL) + return -EINVAL; + rv = gfs2_glock_get(sdp, glnum, glops, 0, &gl); + if (rv) + return rv; + gfs2_glock_cb(gl, glmode); + gfs2_glock_put(gl); + return len; +} + struct gfs2_attr { struct attribute attr; ssize_t (*show)(struct gfs2_sbd *, char *); @@ -189,6 +230,7 @@ GFS2_ATTR(statfs_sync, 0200, NULL, statfs_sync_store); GFS2_ATTR(quota_sync, 0200, NULL, quota_sync_store); GFS2_ATTR(quota_refresh_user, 0200, NULL, quota_refresh_user_store); GFS2_ATTR(quota_refresh_group, 0200, NULL, quota_refresh_group_store); +GFS2_ATTR(demote_rq, 0200, NULL, demote_rq_store); static struct attribute *gfs2_attrs[] = { &gfs2_attr_id.attr, @@ -200,6 +242,7 @@ static struct attribute *gfs2_attrs[] = { &gfs2_attr_quota_sync.attr, &gfs2_attr_quota_refresh_user.attr, &gfs2_attr_quota_refresh_group.attr, + &gfs2_attr_demote_rq.attr, NULL, }; -- GitLab From 223b2b889f379dcea9cef722336a57e8b398bc95 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Tue, 17 Feb 2009 14:13:35 +0000 Subject: [PATCH 4145/4982] GFS2: Fix alignment issue and tidy gfs2_bitfit An alignment issue with the existing bitfit algorithm was reported on IA64. This patch attempts to fix that, and also to tidy up the code a bit. There is now more documentation about how this works and it has survived a number of different tests. Signed-off-by: Steven Whitehouse --- fs/gfs2/rgrp.c | 132 ++++++++++++++++++++++++++----------------------- 1 file changed, 70 insertions(+), 62 deletions(-) diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index a068ac940de..c0abe698af8 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -131,82 +131,90 @@ static inline unsigned char gfs2_testbit(struct gfs2_rgrpd *rgd, return cur_state; } +/** + * gfs2_bit_search + * @ptr: Pointer to bitmap data + * @mask: Mask to use (normally 0x55555.... but adjusted for search start) + * @state: The state we are searching for + * + * We xor the bitmap data with a patter which is the bitwise opposite + * of what we are looking for, this gives rise to a pattern of ones + * wherever there is a match. Since we have two bits per entry, we + * take this pattern, shift it down by one place and then and it with + * the original. All the even bit positions (0,2,4, etc) then represent + * successful matches, so we mask with 0x55555..... to remove the unwanted + * odd bit positions. + * + * This allows searching of a whole u64 at once (32 blocks) with a + * single test (on 64 bit arches). + */ + +static inline u64 gfs2_bit_search(const __le64 *ptr, u64 mask, u8 state) +{ + u64 tmp; + static const u64 search[] = { + [0] = 0xffffffffffffffff, + [1] = 0xaaaaaaaaaaaaaaaa, + [2] = 0x5555555555555555, + [3] = 0x0000000000000000, + }; + tmp = le64_to_cpu(*ptr) ^ search[state]; + tmp &= (tmp >> 1); + tmp &= mask; + return tmp; +} + /** * gfs2_bitfit - Search an rgrp's bitmap buffer to find a bit-pair representing * a block in a given allocation state. * @buffer: the buffer that holds the bitmaps - * @buflen: the length (in bytes) of the buffer + * @len: the length (in bytes) of the buffer * @goal: start search at this block's bit-pair (within @buffer) - * @old_state: GFS2_BLKST_XXX the state of the block we're looking for. + * @state: GFS2_BLKST_XXX the state of the block we're looking for. * * Scope of @goal and returned block number is only within this bitmap buffer, * not entire rgrp or filesystem. @buffer will be offset from the actual - * beginning of a bitmap block buffer, skipping any header structures. + * beginning of a bitmap block buffer, skipping any header structures, but + * headers are always a multiple of 64 bits long so that the buffer is + * always aligned to a 64 bit boundary. + * + * The size of the buffer is in bytes, but is it assumed that it is + * always ok to to read a complete multiple of 64 bits at the end + * of the block in case the end is no aligned to a natural boundary. * * Return: the block number (bitmap buffer scope) that was found */ -static u32 gfs2_bitfit(const u8 *buffer, unsigned int buflen, u32 goal, - u8 old_state) +u32 gfs2_bitfit(const u8 *buf, const unsigned int len, u32 goal, u8 state) { - const u8 *byte, *start, *end; - int bit, startbit; - u32 g1, g2, misaligned; - unsigned long *plong; - unsigned long lskipval; - - lskipval = (old_state & GFS2_BLKST_USED) ? LBITSKIP00 : LBITSKIP55; - g1 = (goal / GFS2_NBBY); - start = buffer + g1; - byte = start; - end = buffer + buflen; - g2 = ALIGN(g1, sizeof(unsigned long)); - plong = (unsigned long *)(buffer + g2); - startbit = bit = (goal % GFS2_NBBY) * GFS2_BIT_SIZE; - misaligned = g2 - g1; - if (!misaligned) - goto ulong_aligned; -/* parse the bitmap a byte at a time */ -misaligned: - while (byte < end) { - if (((*byte >> bit) & GFS2_BIT_MASK) == old_state) { - return goal + - (((byte - start) * GFS2_NBBY) + - ((bit - startbit) >> 1)); - } - bit += GFS2_BIT_SIZE; - if (bit >= GFS2_NBBY * GFS2_BIT_SIZE) { - bit = 0; - byte++; - misaligned--; - if (!misaligned) { - plong = (unsigned long *)byte; - goto ulong_aligned; - } - } - } - return BFITNOENT; - -/* parse the bitmap a unsigned long at a time */ -ulong_aligned: - /* Stop at "end - 1" or else prefetch can go past the end and segfault. - We could "if" it but we'd lose some of the performance gained. - This way will only slow down searching the very last 4/8 bytes - depending on architecture. I've experimented with several ways - of writing this section such as using an else before the goto - but this one seems to be the fastest. */ - while ((unsigned char *)plong < end - sizeof(unsigned long)) { - prefetch(plong + 1); - if (((*plong) & LBITMASK) != lskipval) - break; - plong++; - } - if ((unsigned char *)plong < end) { - byte = (const u8 *)plong; - misaligned += sizeof(unsigned long) - 1; - goto misaligned; + u32 spoint = (goal << 1) & ((8*sizeof(u64)) - 1); + const __le64 *ptr = ((__le64 *)buf) + (goal >> 5); + const __le64 *end = (__le64 *)(buf + ALIGN(len, sizeof(u64))); + u64 tmp; + u64 mask = 0x5555555555555555; + u32 bit; + + BUG_ON(state > 3); + + /* Mask off bits we don't care about at the start of the search */ + mask <<= spoint; + tmp = gfs2_bit_search(ptr, mask, state); + ptr++; + while(tmp == 0 && ptr < end) { + tmp = gfs2_bit_search(ptr, 0x5555555555555555, state); + ptr++; } - return BFITNOENT; + /* Mask off any bits which are more than len bytes from the start */ + if (ptr == end && (len & (sizeof(u64) - 1))) + tmp &= (((u64)~0) >> (64 - 8*(len & (sizeof(u64) - 1)))); + /* Didn't find anything, so return */ + if (tmp == 0) + return BFITNOENT; + ptr--; + bit = fls64(tmp); + bit--; /* fls64 always adds one to the bit count */ + bit /= 2; /* two bits per entry in the bitmap */ + return (((const unsigned char *)ptr - buf) * GFS2_NBBY) + bit; } /** -- GitLab From b9a9694570756e689068f0450cf3c570f74b2b01 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Thu, 19 Feb 2009 10:32:35 +0000 Subject: [PATCH 4146/4982] GFS2: Support quota/noquota mount arguments This adds support for "quota" and "noquota" mount options in addition to the existing "quota=on/off/account" so that we are compatible with the names by which these options are more generally known. Signed-off-by: Steven Whitehouse --- fs/gfs2/mount.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/gfs2/mount.c b/fs/gfs2/mount.c index ee69701a777..f7e8527a21e 100644 --- a/fs/gfs2/mount.c +++ b/fs/gfs2/mount.c @@ -36,6 +36,8 @@ enum { Opt_quota_off, Opt_quota_account, Opt_quota_on, + Opt_quota, + Opt_noquota, Opt_suiddir, Opt_nosuiddir, Opt_data_writeback, @@ -62,6 +64,8 @@ static const match_table_t tokens = { {Opt_quota_off, "quota=off"}, {Opt_quota_account, "quota=account"}, {Opt_quota_on, "quota=on"}, + {Opt_quota, "quota"}, + {Opt_noquota, "noquota"}, {Opt_suiddir, "suiddir"}, {Opt_nosuiddir, "nosuiddir"}, {Opt_data_writeback, "data=writeback"}, @@ -138,12 +142,14 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options) args->ar_posix_acl = 0; break; case Opt_quota_off: + case Opt_noquota: args->ar_quota = GFS2_QUOTA_OFF; break; case Opt_quota_account: args->ar_quota = GFS2_QUOTA_ACCOUNT; break; case Opt_quota_on: + case Opt_quota: args->ar_quota = GFS2_QUOTA_ON; break; case Opt_suiddir: -- GitLab From 075ac44875323941210335b3b0abc1895356d919 Mon Sep 17 00:00:00 2001 From: Hannes Eder Date: Sat, 21 Feb 2009 02:11:42 +0100 Subject: [PATCH 4147/4982] GFS2: fix sparse warnings: constant is so big it is ... Fix this sparse warnings: fs/gfs2/rgrp.c:156:23: warning: constant 0xffffffffffffffff is so big it is unsigned long long fs/gfs2/rgrp.c:157:23: warning: constant 0xaaaaaaaaaaaaaaaa is so big it is unsigned long long fs/gfs2/rgrp.c:158:23: warning: constant 0x5555555555555555 is so big it is long long fs/gfs2/rgrp.c:194:20: warning: constant 0x5555555555555555 is so big it is long long fs/gfs2/rgrp.c:204:44: warning: constant 0x5555555555555555 is so big it is long long Signed-off-by: Hannes Eder Signed-off-by: Steven Whitehouse --- fs/gfs2/rgrp.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index c0abe698af8..34691d75819 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -153,10 +153,10 @@ static inline u64 gfs2_bit_search(const __le64 *ptr, u64 mask, u8 state) { u64 tmp; static const u64 search[] = { - [0] = 0xffffffffffffffff, - [1] = 0xaaaaaaaaaaaaaaaa, - [2] = 0x5555555555555555, - [3] = 0x0000000000000000, + [0] = 0xffffffffffffffffULL, + [1] = 0xaaaaaaaaaaaaaaaaULL, + [2] = 0x5555555555555555ULL, + [3] = 0x0000000000000000ULL, }; tmp = le64_to_cpu(*ptr) ^ search[state]; tmp &= (tmp >> 1); @@ -191,7 +191,7 @@ u32 gfs2_bitfit(const u8 *buf, const unsigned int len, u32 goal, u8 state) const __le64 *ptr = ((__le64 *)buf) + (goal >> 5); const __le64 *end = (__le64 *)(buf + ALIGN(len, sizeof(u64))); u64 tmp; - u64 mask = 0x5555555555555555; + u64 mask = 0x5555555555555555ULL; u32 bit; BUG_ON(state > 3); @@ -201,7 +201,7 @@ u32 gfs2_bitfit(const u8 *buf, const unsigned int len, u32 goal, u8 state) tmp = gfs2_bit_search(ptr, mask, state); ptr++; while(tmp == 0 && ptr < end) { - tmp = gfs2_bit_search(ptr, 0x5555555555555555, state); + tmp = gfs2_bit_search(ptr, 0x5555555555555555ULL, state); ptr++; } /* Mask off any bits which are more than len bytes from the start */ -- GitLab From 02ab1721591f7ac1f632fc74b301513bd6f5849f Mon Sep 17 00:00:00 2001 From: Hannes Eder Date: Sat, 21 Feb 2009 02:12:05 +0100 Subject: [PATCH 4148/4982] GFS2: fix sparse warning: Should it be static? Impact: Make symbol static. Fix this sparse warning: fs/gfs2/rgrp.c:188:5: warning: symbol 'gfs2_bitfit' was not declared. Should it be static? Signed-off-by: Hannes Eder Signed-off-by: Steven Whitehouse --- fs/gfs2/rgrp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 34691d75819..f03d024038e 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -185,7 +185,8 @@ static inline u64 gfs2_bit_search(const __le64 *ptr, u64 mask, u8 state) * Return: the block number (bitmap buffer scope) that was found */ -u32 gfs2_bitfit(const u8 *buf, const unsigned int len, u32 goal, u8 state) +static u32 gfs2_bitfit(const u8 *buf, const unsigned int len, + u32 goal, u8 state) { u32 spoint = (goal << 1) & ((8*sizeof(u64)) - 1); const __le64 *ptr = ((__le64 *)buf) + (goal >> 5); -- GitLab From 229615def3f573fc448d20f62c6ec1bc9340cefb Mon Sep 17 00:00:00 2001 From: Hisashi Hifumi Date: Tue, 3 Mar 2009 11:45:20 +0900 Subject: [PATCH 4149/4982] GFS2: Pagecache usage optimization on GFS2 I introduced "is_partially_uptodate" aops for GFS2. A page can have multiple buffers and even if a page is not uptodate, some buffers can be uptodate on pagesize != blocksize environment. This aops checks that all buffers which correspond to a part of a file that we want to read are uptodate. If so, we do not have to issue actual read IO to HDD even if a page is not uptodate because the portion we want to read are uptodate. "block_is_partially_uptodate" function is already used by ext2/3/4. With the following patch random read/write mixed workloads or random read after random write workloads can be optimized and we can get performance improvement. I did a performance test using the sysbench. #sysbench --num-threads=16 --max-requests=200000 --test=fileio --file-num=1 --file-block-size=8K --file-total-size=2G --file-test-mode=rndrw --file-fsync-freq=0 --file-rw-ratio=1 run -2.6.29-rc6 Test execution summary: total time: 202.6389s total number of events: 200000 total time taken by event execution: 2580.0480 per-request statistics: min: 0.0000s avg: 0.0129s max: 49.5852s approx. 95 percentile: 0.0462s -2.6.29-rc6-patched Test execution summary: total time: 177.8639s total number of events: 200000 total time taken by event execution: 2419.0199 per-request statistics: min: 0.0000s avg: 0.0121s max: 52.4306s approx. 95 percentile: 0.0444s arch: ia64 pagesize: 16k blocksize: 4k Signed-off-by: Hisashi Hifumi Signed-off-by: Steven Whitehouse --- fs/gfs2/ops_address.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index a6d00e8ffe1..a6dde1751e1 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c @@ -1096,6 +1096,7 @@ static const struct address_space_operations gfs2_writeback_aops = { .releasepage = gfs2_releasepage, .direct_IO = gfs2_direct_IO, .migratepage = buffer_migrate_page, + .is_partially_uptodate = block_is_partially_uptodate, }; static const struct address_space_operations gfs2_ordered_aops = { @@ -1111,6 +1112,7 @@ static const struct address_space_operations gfs2_ordered_aops = { .releasepage = gfs2_releasepage, .direct_IO = gfs2_direct_IO, .migratepage = buffer_migrate_page, + .is_partially_uptodate = block_is_partially_uptodate, }; static const struct address_space_operations gfs2_jdata_aops = { @@ -1125,6 +1127,7 @@ static const struct address_space_operations gfs2_jdata_aops = { .bmap = gfs2_bmap, .invalidatepage = gfs2_invalidatepage, .releasepage = gfs2_releasepage, + .is_partially_uptodate = block_is_partially_uptodate, }; void gfs2_set_aops(struct inode *inode) -- GitLab From 02ffad08e838997fad3de05c85560a57e5fd92de Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Fri, 6 Mar 2009 10:03:20 -0600 Subject: [PATCH 4150/4982] GFS2: Fix locking bug in failed shared to exclusive conversion After calling out to the dlm, GFS2 sets the new state of a glock to gl_target in gdlm_ast(). However, gl_target is not always the lock state that was requested. If a conversion from shared to exclusive fails, finish_xmote() will call do_xmote() with LM_ST_UNLOCKED, instead of gl->gl_target, so that it can reacquire the lock in exlusive the next time around. In this case, setting the lock to gl_target in gdlm_ast() will make GFS2 think that it has the glock in exclusive mode, when really, it doesn't have the glock locked at all. This patch adds a new field to the gfs2_glock structure, gl_req, to track the mode that was requested. Signed-off-by: Benjamin Marzinski Signed-off-by: Steven Whitehouse --- fs/gfs2/incore.h | 1 + fs/gfs2/lock_dlm.c | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 980a0864ca6..399d1b97804 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -203,6 +203,7 @@ struct gfs2_glock { unsigned int gl_target; unsigned int gl_reply; unsigned int gl_hash; + unsigned int gl_req; unsigned int gl_demote_state; /* state requested by remote node */ unsigned long gl_demote_time; /* time of first demote request */ struct list_head gl_holders; diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c index a0bb7d2251a..46df988323b 100644 --- a/fs/gfs2/lock_dlm.c +++ b/fs/gfs2/lock_dlm.c @@ -46,11 +46,11 @@ static void gdlm_ast(void *arg) BUG(); } - ret = gl->gl_target; + ret = gl->gl_req; if (gl->gl_lksb.sb_flags & DLM_SBF_ALTMODE) { - if (gl->gl_target == LM_ST_SHARED) + if (gl->gl_req == LM_ST_SHARED) ret = LM_ST_DEFERRED; - else if (gl->gl_target == LM_ST_DEFERRED) + else if (gl->gl_req == LM_ST_DEFERRED) ret = LM_ST_SHARED; else BUG(); @@ -147,6 +147,7 @@ static unsigned int gdlm_lock(struct gfs2_glock *gl, int req; u32 lkf; + gl->gl_req = req_state; req = make_mode(req_state); lkf = make_flags(gl->gl_lksb.sb_lkid, flags, req); -- GitLab From 6bac243f0793499782267342eba852a8a6cc7ac4 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Mon, 9 Mar 2009 09:03:51 +0000 Subject: [PATCH 4151/4982] GFS2: Clean up of glops.c This cleans up a number of bits of code mostly based in glops.c. A couple of simple functions have been merged into the callers to make it more obvious what is going on, the mysterious raising of i_writecount around the truncate_inode_pages() call has been removed. The meta_go_* operations have been renamed rgrp_go_* since that is the only lock type that they are used with. The unused argument of gfs2_read_sb has been removed. Also a bug has been fixed where a check for the rindex inode was in the wrong callback. More comments are added, and the debugging code is improved too. Signed-off-by: Steven Whitehouse --- fs/gfs2/glops.c | 115 +++++++++++++++++++------------------------ fs/gfs2/meta_io.c | 21 -------- fs/gfs2/meta_io.h | 1 - fs/gfs2/ops_file.c | 3 +- fs/gfs2/ops_fstype.c | 6 +-- 5 files changed, 57 insertions(+), 89 deletions(-) diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index f34bc7093dd..bf23a62aa92 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c @@ -76,29 +76,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl) } /** - * gfs2_pte_inval - Sync and invalidate all PTEs associated with a glock - * @gl: the glock - * - */ - -static void gfs2_pte_inval(struct gfs2_glock *gl) -{ - struct gfs2_inode *ip; - struct inode *inode; - - ip = gl->gl_object; - inode = &ip->i_inode; - if (!ip || !S_ISREG(inode->i_mode)) - return; - - unmap_shared_mapping_range(inode->i_mapping, 0, 0); - if (test_bit(GIF_SW_PAGED, &ip->i_flags)) - set_bit(GLF_DIRTY, &gl->gl_flags); - -} - -/** - * meta_go_sync - sync out the metadata for this glock + * rgrp_go_sync - sync out the metadata for this glock * @gl: the glock * * Called when demoting or unlocking an EX glock. We must flush @@ -106,36 +84,42 @@ static void gfs2_pte_inval(struct gfs2_glock *gl) * not return to caller to demote/unlock the glock until I/O is complete. */ -static void meta_go_sync(struct gfs2_glock *gl) +static void rgrp_go_sync(struct gfs2_glock *gl) { - if (gl->gl_state != LM_ST_EXCLUSIVE) + struct address_space *metamapping = gl->gl_aspace->i_mapping; + int error; + + if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) return; + BUG_ON(gl->gl_state != LM_ST_EXCLUSIVE); - if (test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) { - gfs2_log_flush(gl->gl_sbd, gl); - gfs2_meta_sync(gl); - gfs2_ail_empty_gl(gl); - } + gfs2_log_flush(gl->gl_sbd, gl); + filemap_fdatawrite(metamapping); + error = filemap_fdatawait(metamapping); + mapping_set_error(metamapping, error); + gfs2_ail_empty_gl(gl); } /** - * meta_go_inval - invalidate the metadata for this glock + * rgrp_go_inval - invalidate the metadata for this glock * @gl: the glock * @flags: * + * We never used LM_ST_DEFERRED with resource groups, so that we + * should always see the metadata flag set here. + * */ -static void meta_go_inval(struct gfs2_glock *gl, int flags) +static void rgrp_go_inval(struct gfs2_glock *gl, int flags) { - if (!(flags & DIO_METADATA)) - return; + struct address_space *mapping = gl->gl_aspace->i_mapping; - gfs2_meta_inval(gl); - if (gl->gl_object == GFS2_I(gl->gl_sbd->sd_rindex)) - gl->gl_sbd->sd_rindex_uptodate = 0; - else if (gl->gl_ops == &gfs2_rgrp_glops && gl->gl_object) { - struct gfs2_rgrpd *rgd = (struct gfs2_rgrpd *)gl->gl_object; + BUG_ON(!(flags & DIO_METADATA)); + gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count)); + truncate_inode_pages(mapping, 0); + if (gl->gl_object) { + struct gfs2_rgrpd *rgd = (struct gfs2_rgrpd *)gl->gl_object; rgd->rd_flags &= ~GFS2_RDF_UPTODATE; } } @@ -152,48 +136,54 @@ static void inode_go_sync(struct gfs2_glock *gl) struct address_space *metamapping = gl->gl_aspace->i_mapping; int error; - if (gl->gl_state != LM_ST_UNLOCKED) - gfs2_pte_inval(gl); - if (gl->gl_state != LM_ST_EXCLUSIVE) - return; - if (ip && !S_ISREG(ip->i_inode.i_mode)) ip = NULL; + if (ip && test_and_clear_bit(GIF_SW_PAGED, &ip->i_flags)) + unmap_shared_mapping_range(ip->i_inode.i_mapping, 0, 0); + if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) + return; - if (test_bit(GLF_DIRTY, &gl->gl_flags)) { - gfs2_log_flush(gl->gl_sbd, gl); - filemap_fdatawrite(metamapping); - if (ip) { - struct address_space *mapping = ip->i_inode.i_mapping; - filemap_fdatawrite(mapping); - error = filemap_fdatawait(mapping); - mapping_set_error(mapping, error); - } - error = filemap_fdatawait(metamapping); - mapping_set_error(metamapping, error); - clear_bit(GLF_DIRTY, &gl->gl_flags); - gfs2_ail_empty_gl(gl); + BUG_ON(gl->gl_state != LM_ST_EXCLUSIVE); + + gfs2_log_flush(gl->gl_sbd, gl); + filemap_fdatawrite(metamapping); + if (ip) { + struct address_space *mapping = ip->i_inode.i_mapping; + filemap_fdatawrite(mapping); + error = filemap_fdatawait(mapping); + mapping_set_error(mapping, error); } + error = filemap_fdatawait(metamapping); + mapping_set_error(metamapping, error); + gfs2_ail_empty_gl(gl); } /** * inode_go_inval - prepare a inode glock to be released * @gl: the glock * @flags: + * + * Normally we invlidate everything, but if we are moving into + * LM_ST_DEFERRED from LM_ST_SHARED or LM_ST_EXCLUSIVE then we + * can keep hold of the metadata, since it won't have changed. * */ static void inode_go_inval(struct gfs2_glock *gl, int flags) { struct gfs2_inode *ip = gl->gl_object; - int meta = (flags & DIO_METADATA); - if (meta) { - gfs2_meta_inval(gl); + gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count)); + + if (flags & DIO_METADATA) { + struct address_space *mapping = gl->gl_aspace->i_mapping; + truncate_inode_pages(mapping, 0); if (ip) set_bit(GIF_INVALID, &ip->i_flags); } + if (ip == GFS2_I(gl->gl_sbd->sd_rindex)) + gl->gl_sbd->sd_rindex_uptodate = 0; if (ip && S_ISREG(ip->i_inode.i_mode)) truncate_inode_pages(ip->i_inode.i_mapping, 0); } @@ -395,7 +385,6 @@ static int trans_go_demote_ok(const struct gfs2_glock *gl) } const struct gfs2_glock_operations gfs2_meta_glops = { - .go_xmote_th = meta_go_sync, .go_type = LM_TYPE_META, }; @@ -410,8 +399,8 @@ const struct gfs2_glock_operations gfs2_inode_glops = { }; const struct gfs2_glock_operations gfs2_rgrp_glops = { - .go_xmote_th = meta_go_sync, - .go_inval = meta_go_inval, + .go_xmote_th = rgrp_go_sync, + .go_inval = rgrp_go_inval, .go_demote_ok = rgrp_go_demote_ok, .go_lock = rgrp_go_lock, .go_unlock = rgrp_go_unlock, diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 870d65ae7ae..8d6f13256b2 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c @@ -88,27 +88,6 @@ void gfs2_aspace_put(struct inode *aspace) iput(aspace); } -/** - * gfs2_meta_inval - Invalidate all buffers associated with a glock - * @gl: the glock - * - */ - -void gfs2_meta_inval(struct gfs2_glock *gl) -{ - struct gfs2_sbd *sdp = gl->gl_sbd; - struct inode *aspace = gl->gl_aspace; - struct address_space *mapping = gl->gl_aspace->i_mapping; - - gfs2_assert_withdraw(sdp, !atomic_read(&gl->gl_ail_count)); - - atomic_inc(&aspace->i_writecount); - truncate_inode_pages(mapping, 0); - atomic_dec(&aspace->i_writecount); - - gfs2_assert_withdraw(sdp, !mapping->nrpages); -} - /** * gfs2_meta_sync - Sync all buffers associated with a glock * @gl: The glock diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h index b1a5f3674d4..de270c2f9b6 100644 --- a/fs/gfs2/meta_io.h +++ b/fs/gfs2/meta_io.h @@ -40,7 +40,6 @@ static inline void gfs2_buffer_copy_tail(struct buffer_head *to_bh, struct inode *gfs2_aspace_get(struct gfs2_sbd *sdp); void gfs2_aspace_put(struct inode *aspace); -void gfs2_meta_inval(struct gfs2_glock *gl); void gfs2_meta_sync(struct gfs2_glock *gl); struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno); diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index 99d726f1c7a..48ec3d5e29e 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c @@ -355,7 +355,6 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page) if (ret) goto out; - set_bit(GIF_SW_PAGED, &ip->i_flags); ret = gfs2_write_alloc_required(ip, pos, PAGE_CACHE_SIZE, &alloc_required); if (ret || !alloc_required) goto out_unlock; @@ -396,6 +395,8 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page) goto out_unlock_page; } ret = gfs2_allocate_page_backing(page); + if (!ret) + set_bit(GIF_SW_PAGED, &ip->i_flags); out_unlock_page: unlock_page(page); diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 804ca7273a4..51883b3ad89 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -296,15 +296,15 @@ static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector) __free_page(page); return 0; } + /** * gfs2_read_sb - Read super block * @sdp: The GFS2 superblock - * @gl: the glock for the superblock (assumed to be held) * @silent: Don't print message if mount fails * */ -static int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent) +static int gfs2_read_sb(struct gfs2_sbd *sdp, int silent) { u32 hash_blocks, ind_blocks, leaf_blocks; u32 tmp_blocks; @@ -524,7 +524,7 @@ static int init_sb(struct gfs2_sbd *sdp, int silent) return ret; } - ret = gfs2_read_sb(sdp, sb_gh.gh_gl, silent); + ret = gfs2_read_sb(sdp, silent); if (ret) { fs_err(sdp, "can't read superblock: %d\n", ret); goto out; -- GitLab From 9c538837d844574787c95bd5665f684559fb7065 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Thu, 19 Mar 2009 13:15:44 +0000 Subject: [PATCH 4152/4982] Fix a minor bug in the previous patch The logic requires that we mark the glock dirty in page_mkwrite otherwise we might not flush correctly in the case that no allocation was required in the process of dirying the page. Also we need to set the shared write flag early for the same reason. Signed-off-by: Steven Whitehouse --- fs/gfs2/ops_file.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index 48ec3d5e29e..3b9e8de3500 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c @@ -355,6 +355,9 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page) if (ret) goto out; + set_bit(GLF_DIRTY, &ip->i_gl->gl_flags); + set_bit(GIF_SW_PAGED, &ip->i_flags); + ret = gfs2_write_alloc_required(ip, pos, PAGE_CACHE_SIZE, &alloc_required); if (ret || !alloc_required) goto out_unlock; @@ -395,8 +398,6 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page) goto out_unlock_page; } ret = gfs2_allocate_page_backing(page); - if (!ret) - set_bit(GIF_SW_PAGED, &ip->i_flags); out_unlock_page: unlock_page(page); -- GitLab From df3647b24510e23523f81a77bb179cd9ae3d613b Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Mon, 23 Mar 2009 11:38:55 +0000 Subject: [PATCH 4153/4982] GFS2: Fix freeze issue This removes some old code that was causing issues during filesystem freeze. Reported-by: Andrew Price Tested-by: Andrew Price Signed-off-by: Steven Whitehouse --- fs/gfs2/super.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 7cf302b135c..601913e0a48 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -338,7 +338,6 @@ static int gfs2_lock_fs_check_clean(struct gfs2_sbd *sdp, struct gfs2_holder *t_gh) { struct gfs2_inode *ip; - struct gfs2_holder ji_gh; struct gfs2_jdesc *jd; struct lfcc *lfcc; LIST_HEAD(list); @@ -386,7 +385,6 @@ out: gfs2_glock_dq_uninit(&lfcc->gh); kfree(lfcc); } - gfs2_glock_dq_uninit(&ji_gh); return error; } -- GitLab From 34053979fb1d923217685cf166349f1899980581 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 21 Feb 2009 11:16:36 +0100 Subject: [PATCH 4154/4982] block: cleanup bio_alloc_bioset() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this warning (which got fixed by commit b2bf968): fs/bio.c: In function ‘bio_alloc_bioset’: fs/bio.c:305: warning: ‘p’ may be used uninitialized in this function Triggered because the code flow in bio_alloc_bioset() is correct but a bit complex for the compiler to see through. Streamline it a bit - this also makes the code a tiny bit more compact: text data bss dec hex filename 7540 256 40 7836 1e9c bio.o.before 7539 256 40 7835 1e9b bio.o.after Also remove an older compiler-warnings annotation from this function, it's not needed. Signed-off-by: Ingo Molnar Signed-off-by: Jens Axboe --- fs/bio.c | 71 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/fs/bio.c b/fs/bio.c index d4f06327c81..cef6258b894 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -301,48 +301,51 @@ void bio_init(struct bio *bio) **/ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs) { + struct bio_vec *bvl = NULL; struct bio *bio = NULL; - void *uninitialized_var(p); + unsigned long idx = 0; + void *p = NULL; if (bs) { p = mempool_alloc(bs->bio_pool, gfp_mask); - - if (p) - bio = p + bs->front_pad; - } else + if (!p) + goto err; + bio = p + bs->front_pad; + } else { bio = kmalloc(sizeof(*bio), gfp_mask); + if (!bio) + goto err; + } - if (likely(bio)) { - struct bio_vec *bvl = NULL; - - bio_init(bio); - if (likely(nr_iovecs)) { - unsigned long uninitialized_var(idx); - - if (nr_iovecs <= BIO_INLINE_VECS) { - idx = 0; - bvl = bio->bi_inline_vecs; - nr_iovecs = BIO_INLINE_VECS; - } else { - bvl = bvec_alloc_bs(gfp_mask, nr_iovecs, &idx, - bs); - nr_iovecs = bvec_nr_vecs(idx); - } - if (unlikely(!bvl)) { - if (bs) - mempool_free(p, bs->bio_pool); - else - kfree(bio); - bio = NULL; - goto out; - } - bio->bi_flags |= idx << BIO_POOL_OFFSET; - bio->bi_max_vecs = nr_iovecs; - } - bio->bi_io_vec = bvl; + bio_init(bio); + + if (unlikely(!nr_iovecs)) + goto out_set; + + if (nr_iovecs <= BIO_INLINE_VECS) { + bvl = bio->bi_inline_vecs; + nr_iovecs = BIO_INLINE_VECS; + } else { + bvl = bvec_alloc_bs(gfp_mask, nr_iovecs, &idx, bs); + if (unlikely(!bvl)) + goto err_free; + + nr_iovecs = bvec_nr_vecs(idx); } -out: + bio->bi_flags |= idx << BIO_POOL_OFFSET; + bio->bi_max_vecs = nr_iovecs; +out_set: + bio->bi_io_vec = bvl; + return bio; + +err_free: + if (bs) + mempool_free(p, bs->bio_pool); + else + kfree(bio); +err: + return NULL; } struct bio *bio_alloc(gfp_t gfp_mask, int nr_iovecs) -- GitLab From a7fcd37cdcb47806fb8a9070f006ee34061defa6 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 5 Dec 2008 16:10:29 +0100 Subject: [PATCH 4155/4982] block: don't create bio_vec slabs of less than the inline number If we don't have CONFIG_BLK_DEV_INTEGRITY set, then we don't have any external dependencies on the bio_vec slabs. So don't create the ones that we will inline anyway. Signed-off-by: Jens Axboe --- fs/bio.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fs/bio.c b/fs/bio.c index cef6258b894..9cc1430b449 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -1589,6 +1589,13 @@ static void __init biovec_init_slabs(void) int size; struct biovec_slab *bvs = bvec_slabs + i; +#ifndef CONFIG_BLK_DEV_INTEGRITY + if (bvs->nr_vecs <= BIO_INLINE_VECS) { + bvs->slab = NULL; + continue; + } +#endif + size = bvs->nr_vecs * sizeof(struct bio_vec); bvs->slab = kmem_cache_create(bvs->name, size, 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); -- GitLab From 10cbda97e73c7d537d7174eadb2d098484f8f1da Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 27 Feb 2009 20:14:20 +0100 Subject: [PATCH 4156/4982] cciss: add BUILD_BUG_ON() for catching bad CommandList_struct alignment The hardware requires 64-bit alignment of commands, so add a build bug check for that. The recent commit 8a3173de4ab4cdacc43675dc5c077f9a5bf17f5f didn't change the size of the command, but other additions/changes may and thus break badly at runtime. Signed-off-by: Jens Axboe --- drivers/block/cciss.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 4f9b6d79201..5d0e135824f 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -3898,6 +3898,13 @@ static struct pci_driver cciss_pci_driver = { */ static int __init cciss_init(void) { + /* + * The hardware requires that commands are aligned on a 64-bit + * boundary. Given that we use pci_alloc_consistent() to allocate an + * array of them, the size must be a multiple of 8 bytes. + */ + BUILD_BUG_ON(sizeof(CommandList_struct) % 8); + printk(KERN_INFO DRIVER_NAME "\n"); /* Register for our PCI devices */ -- GitLab From f3b144aa7f2861e1024682af3bf3dbf1c29184b9 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 6 Mar 2009 08:48:33 +0100 Subject: [PATCH 4157/4982] block: remove various blk_queue_*() setting functions in blk_init_queue_node() It calls blk_queue_make_request(), which sets the identical set of limits. Signed-off-by: Jens Axboe --- block/blk-core.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 29bcfac6c68..5e14b3f4510 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -603,13 +603,10 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id) q->queue_flags = QUEUE_FLAG_DEFAULT; q->queue_lock = lock; - blk_queue_segment_boundary(q, BLK_SEG_BOUNDARY_MASK); - + /* + * This also sets hw/phys segments, boundary and size + */ blk_queue_make_request(q, __make_request); - blk_queue_max_segment_size(q, MAX_SEGMENT_SIZE); - - blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS); - blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS); q->sg_reserved_size = INT_MAX; -- GitLab From 50e174931051bf4849cd7931667bb0a4d681ff60 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 6 Mar 2009 11:12:17 +0100 Subject: [PATCH 4158/4982] block: get rid of unused blkdev_free_rq() define Signed-off-by: Jens Axboe --- block/blk-core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/block/blk-core.c b/block/blk-core.c index 5e14b3f4510..7b63c9b6333 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -732,7 +732,6 @@ static void freed_request(struct request_queue *q, int rw, int priv) __freed_request(q, rw ^ 1); } -#define blkdev_free_rq(list) list_entry((list)->next, struct request, queuelist) /* * Get a free request, queue_lock must be held. * Returns NULL on failure, with queue_lock held. -- GitLab From 32ca163c9cdb33151d79e95a7cf244f62b5d4418 Mon Sep 17 00:00:00 2001 From: Petros Koutoupis Date: Tue, 10 Mar 2009 08:25:54 +0100 Subject: [PATCH 4159/4982] block: genhd.h comment needs updating The include/linux/genhd.h file, on line 338-352 declares some function prototypes in which the comment on line 338 states that the definition of these prototypes are to be found at drivers/block/genhd.c. The problem is that genhd.c has been relocated to block/genhd.c. See attached patch to correct this minor cosmetic typo. Signed-off-by: Petros Koutoupis Signed-off-by: Jens Axboe --- include/linux/genhd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 16948eaecae..56946b21ab7 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -336,7 +336,7 @@ static inline void part_dec_in_flight(struct hd_struct *part) /* drivers/block/ll_rw_blk.c */ extern void part_round_stats(int cpu, struct hd_struct *part); -/* drivers/block/genhd.c */ +/* block/genhd.c */ extern int get_blkdev_list(char *, int); extern void add_disk(struct gendisk *disk); extern void del_gendisk(struct gendisk *gp); -- GitLab From 6d2a78e783416ba99e36beb1d4395b785b34e867 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Tue, 10 Mar 2009 08:27:39 +0100 Subject: [PATCH 4160/4982] block: add private bio_set for bio integrity allocations The integrity bio allocation needs its own bio_set to avoid violating the mempool allocation rules and risking deadlocks. Signed-off-by: Martin K. Petersen Signed-off-by: Jens Axboe --- fs/bio-integrity.c | 85 ++++++++++++++------------------------------- fs/bio.c | 9 ++--- include/linux/bio.h | 18 +++------- 3 files changed, 32 insertions(+), 80 deletions(-) diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index fe2b1aa2464..31c46a241ba 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c @@ -26,23 +26,23 @@ #include static struct kmem_cache *bio_integrity_slab __read_mostly; +static mempool_t *bio_integrity_pool; +static struct bio_set *integrity_bio_set; static struct workqueue_struct *kintegrityd_wq; /** - * bio_integrity_alloc_bioset - Allocate integrity payload and attach it to bio + * bio_integrity_alloc - Allocate integrity payload and attach it to bio * @bio: bio to attach integrity metadata to * @gfp_mask: Memory allocation mask * @nr_vecs: Number of integrity metadata scatter-gather elements - * @bs: bio_set to allocate from * * Description: This function prepares a bio for attaching integrity * metadata. nr_vecs specifies the maximum number of pages containing * integrity metadata that can be attached. */ -struct bio_integrity_payload *bio_integrity_alloc_bioset(struct bio *bio, - gfp_t gfp_mask, - unsigned int nr_vecs, - struct bio_set *bs) +struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio, + gfp_t gfp_mask, + unsigned int nr_vecs) { struct bio_integrity_payload *bip; struct bio_vec *iv; @@ -50,7 +50,7 @@ struct bio_integrity_payload *bio_integrity_alloc_bioset(struct bio *bio, BUG_ON(bio == NULL); - bip = mempool_alloc(bs->bio_integrity_pool, gfp_mask); + bip = mempool_alloc(bio_integrity_pool, gfp_mask); if (unlikely(bip == NULL)) { printk(KERN_ERR "%s: could not alloc bip\n", __func__); return NULL; @@ -58,10 +58,10 @@ struct bio_integrity_payload *bio_integrity_alloc_bioset(struct bio *bio, memset(bip, 0, sizeof(*bip)); - iv = bvec_alloc_bs(gfp_mask, nr_vecs, &idx, bs); + iv = bvec_alloc_bs(gfp_mask, nr_vecs, &idx, integrity_bio_set); if (unlikely(iv == NULL)) { printk(KERN_ERR "%s: could not alloc bip_vec\n", __func__); - mempool_free(bip, bs->bio_integrity_pool); + mempool_free(bip, bio_integrity_pool); return NULL; } @@ -72,35 +72,16 @@ struct bio_integrity_payload *bio_integrity_alloc_bioset(struct bio *bio, return bip; } -EXPORT_SYMBOL(bio_integrity_alloc_bioset); - -/** - * bio_integrity_alloc - Allocate integrity payload and attach it to bio - * @bio: bio to attach integrity metadata to - * @gfp_mask: Memory allocation mask - * @nr_vecs: Number of integrity metadata scatter-gather elements - * - * Description: This function prepares a bio for attaching integrity - * metadata. nr_vecs specifies the maximum number of pages containing - * integrity metadata that can be attached. - */ -struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio, - gfp_t gfp_mask, - unsigned int nr_vecs) -{ - return bio_integrity_alloc_bioset(bio, gfp_mask, nr_vecs, fs_bio_set); -} EXPORT_SYMBOL(bio_integrity_alloc); /** * bio_integrity_free - Free bio integrity payload * @bio: bio containing bip to be freed - * @bs: bio_set this bio was allocated from * * Description: Used to free the integrity portion of a bio. Usually * called from bio_free(). */ -void bio_integrity_free(struct bio *bio, struct bio_set *bs) +void bio_integrity_free(struct bio *bio) { struct bio_integrity_payload *bip = bio->bi_integrity; @@ -111,8 +92,8 @@ void bio_integrity_free(struct bio *bio, struct bio_set *bs) && bip->bip_buf != NULL) kfree(bip->bip_buf); - bvec_free_bs(bs, bip->bip_vec, bip->bip_pool); - mempool_free(bip, bs->bio_integrity_pool); + bvec_free_bs(integrity_bio_set, bip->bip_vec, bip->bip_pool); + mempool_free(bip, bio_integrity_pool); bio->bi_integrity = NULL; } @@ -686,19 +667,17 @@ EXPORT_SYMBOL(bio_integrity_split); * @bio: New bio * @bio_src: Original bio * @gfp_mask: Memory allocation mask - * @bs: bio_set to allocate bip from * * Description: Called to allocate a bip when cloning a bio */ -int bio_integrity_clone(struct bio *bio, struct bio *bio_src, - gfp_t gfp_mask, struct bio_set *bs) +int bio_integrity_clone(struct bio *bio, struct bio *bio_src, gfp_t gfp_mask) { struct bio_integrity_payload *bip_src = bio_src->bi_integrity; struct bio_integrity_payload *bip; BUG_ON(bip_src == NULL); - bip = bio_integrity_alloc_bioset(bio, gfp_mask, bip_src->bip_vcnt, bs); + bip = bio_integrity_alloc(bio, gfp_mask, bip_src->bip_vcnt); if (bip == NULL) return -EIO; @@ -714,37 +693,25 @@ int bio_integrity_clone(struct bio *bio, struct bio *bio_src, } EXPORT_SYMBOL(bio_integrity_clone); -int bioset_integrity_create(struct bio_set *bs, int pool_size) +static int __init bio_integrity_init(void) { - bs->bio_integrity_pool = mempool_create_slab_pool(pool_size, - bio_integrity_slab); - if (!bs->bio_integrity_pool) - return -1; - - return 0; -} -EXPORT_SYMBOL(bioset_integrity_create); + kintegrityd_wq = create_workqueue("kintegrityd"); -void bioset_integrity_free(struct bio_set *bs) -{ - if (bs->bio_integrity_pool) - mempool_destroy(bs->bio_integrity_pool); -} -EXPORT_SYMBOL(bioset_integrity_free); + if (!kintegrityd_wq) + panic("Failed to create kintegrityd\n"); -void __init bio_integrity_init_slab(void) -{ bio_integrity_slab = KMEM_CACHE(bio_integrity_payload, SLAB_HWCACHE_ALIGN|SLAB_PANIC); -} -static int __init integrity_init(void) -{ - kintegrityd_wq = create_workqueue("kintegrityd"); + bio_integrity_pool = mempool_create_slab_pool(BIO_POOL_SIZE, + bio_integrity_slab); + if (!bio_integrity_pool) + panic("bio_integrity: can't allocate bip pool\n"); - if (!kintegrityd_wq) - panic("Failed to create kintegrityd\n"); + integrity_bio_set = bioset_create(BIO_POOL_SIZE, 0); + if (!integrity_bio_set) + panic("bio_integrity: can't allocate bio_set\n"); return 0; } -subsys_initcall(integrity_init); +subsys_initcall(bio_integrity_init); diff --git a/fs/bio.c b/fs/bio.c index 9cc1430b449..a040cde7f6f 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -248,7 +248,7 @@ void bio_free(struct bio *bio, struct bio_set *bs) bvec_free_bs(bs, bio->bi_io_vec, BIO_POOL_IDX(bio)); if (bio_integrity(bio)) - bio_integrity_free(bio, bs); + bio_integrity_free(bio); /* * If we have front padding, adjust the bio pointer before freeing @@ -466,7 +466,7 @@ struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask) if (bio_integrity(bio)) { int ret; - ret = bio_integrity_clone(b, bio, gfp_mask, fs_bio_set); + ret = bio_integrity_clone(b, bio, gfp_mask); if (ret < 0) { bio_put(b); @@ -1529,7 +1529,6 @@ void bioset_free(struct bio_set *bs) if (bs->bio_pool) mempool_destroy(bs->bio_pool); - bioset_integrity_free(bs); biovec_free_pools(bs); bio_put_slab(bs); @@ -1570,9 +1569,6 @@ struct bio_set *bioset_create(unsigned int pool_size, unsigned int front_pad) if (!bs->bio_pool) goto bad; - if (bioset_integrity_create(bs, pool_size)) - goto bad; - if (!biovec_create_pools(bs, pool_size)) return bs; @@ -1610,7 +1606,6 @@ static int __init init_bio(void) if (!bio_slabs) panic("bio: can't allocate bios\n"); - bio_integrity_init_slab(); biovec_init_slabs(); fs_bio_set = bioset_create(BIO_POOL_SIZE, 0); diff --git a/include/linux/bio.h b/include/linux/bio.h index d8bd43bfdcf..b05b1d4d17d 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -426,9 +426,6 @@ struct bio_set { unsigned int front_pad; mempool_t *bio_pool; -#if defined(CONFIG_BLK_DEV_INTEGRITY) - mempool_t *bio_integrity_pool; -#endif mempool_t *bvec_pool; }; @@ -519,9 +516,8 @@ static inline int bio_has_data(struct bio *bio) #define bio_integrity(bio) (bio->bi_integrity != NULL) -extern struct bio_integrity_payload *bio_integrity_alloc_bioset(struct bio *, gfp_t, unsigned int, struct bio_set *); extern struct bio_integrity_payload *bio_integrity_alloc(struct bio *, gfp_t, unsigned int); -extern void bio_integrity_free(struct bio *, struct bio_set *); +extern void bio_integrity_free(struct bio *); extern int bio_integrity_add_page(struct bio *, struct page *, unsigned int, unsigned int); extern int bio_integrity_enabled(struct bio *bio); extern int bio_integrity_set_tag(struct bio *, void *, unsigned int); @@ -531,27 +527,21 @@ extern void bio_integrity_endio(struct bio *, int); extern void bio_integrity_advance(struct bio *, unsigned int); extern void bio_integrity_trim(struct bio *, unsigned int, unsigned int); extern void bio_integrity_split(struct bio *, struct bio_pair *, int); -extern int bio_integrity_clone(struct bio *, struct bio *, gfp_t, struct bio_set *); -extern int bioset_integrity_create(struct bio_set *, int); -extern void bioset_integrity_free(struct bio_set *); -extern void bio_integrity_init_slab(void); +extern int bio_integrity_clone(struct bio *, struct bio *, gfp_t); #else /* CONFIG_BLK_DEV_INTEGRITY */ #define bio_integrity(a) (0) -#define bioset_integrity_create(a, b) (0) #define bio_integrity_prep(a) (0) #define bio_integrity_enabled(a) (0) -#define bio_integrity_clone(a, b, c,d ) (0) -#define bioset_integrity_free(a) do { } while (0) -#define bio_integrity_free(a, b) do { } while (0) +#define bio_integrity_clone(a, b, c) (0) +#define bio_integrity_free(a) do { } while (0) #define bio_integrity_endio(a, b) do { } while (0) #define bio_integrity_advance(a, b) do { } while (0) #define bio_integrity_trim(a, b, c) do { } while (0) #define bio_integrity_split(a, b, c) do { } while (0) #define bio_integrity_set_tag(a, b, c) do { } while (0) #define bio_integrity_get_tag(a, b, c) do { } while (0) -#define bio_integrity_init_slab(a) do { } while (0) #endif /* CONFIG_BLK_DEV_INTEGRITY */ -- GitLab From d399228646e26db315d6233bed65ec9d08c57f57 Mon Sep 17 00:00:00 2001 From: Petros Koutoupis Date: Wed, 11 Mar 2009 10:49:35 +0100 Subject: [PATCH 4161/4982] block: genhd.h cleanup patch In include/linux/genhd.h: Line 335 has a comment that needs to be updated from: /* drivers/block/ll_rw_blk.c */ to /* block/blk-core.c */. Also as of kernel 2.6.16, the function definition for get_blkdev_list was removed from block/genhd.c but the function declaration is still present on line 339. This patch addresses both those fixes, by updating the comment and removing the declaration. Signed-off-by: Petros Koutoupis Signed-off-by: Jens Axboe --- include/linux/genhd.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 56946b21ab7..634c53028fb 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -333,11 +333,10 @@ static inline void part_dec_in_flight(struct hd_struct *part) part_to_disk(part)->part0.in_flight--; } -/* drivers/block/ll_rw_blk.c */ +/* block/blk-core.c */ extern void part_round_stats(int cpu, struct hd_struct *part); /* block/genhd.c */ -extern int get_blkdev_list(char *, int); extern void add_disk(struct gendisk *disk); extern void del_gendisk(struct gendisk *gp); extern void unlink_gendisk(struct gendisk *gp); -- GitLab From 0061d38642244892e17156f005bd7055fe744644 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 16 Mar 2009 10:06:05 +0100 Subject: [PATCH 4162/4982] cpqarray: enable bus mastering We've been carrying this patch for the last 3 years in Fedora, long past time we got it upstream... Call pci_set_master to enable bus-mastering if the BIOS hasn't done it already. Signed-off-by: Kyle McMartin Signed-off-by: Dave Jones Signed-off-by: Jens Axboe --- drivers/block/cpqarray.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index 5d39df14ed9..ca268ca1115 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -617,6 +617,7 @@ static int cpqarray_pci_init(ctlr_info_t *c, struct pci_dev *pdev) int i; c->pci_dev = pdev; + pci_set_master(pdev); if (pci_enable_device(pdev)) { printk(KERN_ERR "cpqarray: Unable to Enable PCI device\n"); return -1; -- GitLab From 05378940caf979a8655c18b18a17213dcfa52412 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Tue, 24 Mar 2009 12:23:40 +0100 Subject: [PATCH 4163/4982] bsg: add support for tail queuing Currently inherited from sg.c bsg will submit asynchronous request at the head-of-the-queue, (using "at_head" set in the call to blk_execute_rq_nowait()). This is bad in situation where the queues are full, requests will execute out of order, and can cause starvation of the first submitted requests. The sg_io_v4->flags member is used and a bit is allocated to denote the Q_AT_TAIL. Zero is to queue at_head as before, to be compatible with old code at the write/read path. SG_IO code path behavior was changed so to be the same as write/read behavior. SG_IO was very rarely used and breaking compatibility with it is OK at this stage. sg_io_hdr at sg.h also has a flags member and uses 3 bits from the first nibble and one bit from the last nibble. Even though none of these bits are supported by bsg, The second nibble is allocated for use by bsg. Just in case. Signed-off-by: Boaz Harrosh CC: Douglas Gilbert Signed-off-by: Jens Axboe --- block/bsg.c | 9 +++++++-- include/linux/bsg.h | 8 ++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/block/bsg.c b/block/bsg.c index 0ce8806dd0c..0f63b91d0af 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -353,6 +353,8 @@ static void bsg_rq_end_io(struct request *rq, int uptodate) static void bsg_add_command(struct bsg_device *bd, struct request_queue *q, struct bsg_command *bc, struct request *rq) { + int at_head = (0 == (bc->hdr.flags & BSG_FLAG_Q_AT_TAIL)); + /* * add bc command to busy queue and submit rq for io */ @@ -368,7 +370,7 @@ static void bsg_add_command(struct bsg_device *bd, struct request_queue *q, dprintk("%s: queueing rq %p, bc %p\n", bd->name, rq, bc); rq->end_io_data = bc; - blk_execute_rq_nowait(q, NULL, rq, 1, bsg_rq_end_io); + blk_execute_rq_nowait(q, NULL, rq, at_head, bsg_rq_end_io); } static struct bsg_command *bsg_next_done_cmd(struct bsg_device *bd) @@ -924,6 +926,7 @@ static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct request *rq; struct bio *bio, *bidi_bio = NULL; struct sg_io_v4 hdr; + int at_head; u8 sense[SCSI_SENSE_BUFFERSIZE]; if (copy_from_user(&hdr, uarg, sizeof(hdr))) @@ -936,7 +939,9 @@ static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg) bio = rq->bio; if (rq->next_rq) bidi_bio = rq->next_rq->bio; - blk_execute_rq(bd->queue, NULL, rq, 0); + + at_head = (0 == (hdr.flags & BSG_FLAG_Q_AT_TAIL)); + blk_execute_rq(bd->queue, NULL, rq, at_head); ret = blk_complete_sgv4_hdr_rq(rq, &hdr, bio, bidi_bio); if (copy_to_user(uarg, &hdr, sizeof(hdr))) diff --git a/include/linux/bsg.h b/include/linux/bsg.h index cf0303a6061..3f0c64ace42 100644 --- a/include/linux/bsg.h +++ b/include/linux/bsg.h @@ -7,6 +7,14 @@ #define BSG_SUB_PROTOCOL_SCSI_TMF 1 #define BSG_SUB_PROTOCOL_SCSI_TRANSPORT 2 +/* + * For flags member below + * sg.h sg_io_hdr also has bits defined for it's flags member. However + * none of these bits are implemented/used by bsg. The bits below are + * allocated to not conflict with sg.h ones anyway. + */ +#define BSG_FLAG_Q_AT_TAIL 0x10 /* default, == 0 at this bit, is Q_AT_HEAD */ + struct sg_io_v4 { __s32 guard; /* [i] 'Q' to differentiate from v3 */ __u32 protocol; /* [i] 0 -> SCSI , .... */ -- GitLab From 68db1961bbf4e16c220ccec4a780e966bc1fece3 Mon Sep 17 00:00:00 2001 From: Nikanth Karthikesan Date: Tue, 24 Mar 2009 12:29:54 +0100 Subject: [PATCH 4164/4982] loop: support barrier writes Honour barrier requests in the loop back block device driver. In case of barrier bios, flush the backing file once before processing the barrier and once after to guarantee ordering. In case of filesystems that does not support fsync, barrier bios would be failed with -EOPNOTSUPP. Signed-off-by: Nikanth Karthikesan Signed-off-by: Jens Axboe --- drivers/block/loop.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index bf034557767..9721d100caf 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -474,10 +474,35 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio) int ret; pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset; - if (bio_rw(bio) == WRITE) + + if (bio_rw(bio) == WRITE) { + int barrier = bio_barrier(bio); + struct file *file = lo->lo_backing_file; + + if (barrier) { + if (unlikely(!file->f_op->fsync)) { + ret = -EOPNOTSUPP; + goto out; + } + + ret = vfs_fsync(file, file->f_path.dentry, 0); + if (unlikely(ret)) { + ret = -EIO; + goto out; + } + } + ret = lo_send(lo, bio, pos); - else + + if (barrier && !ret) { + ret = vfs_fsync(file, file->f_path.dentry, 0); + if (unlikely(ret)) + ret = -EIO; + } + } else ret = lo_receive(lo, bio, lo->lo_blocksize, pos); + +out: return ret; } @@ -826,6 +851,9 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, lo->lo_queue->queuedata = lo; lo->lo_queue->unplug_fn = loop_unplug; + if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync) + blk_queue_ordered(lo->lo_queue, QUEUE_ORDERED_DRAIN, NULL); + set_capacity(lo->lo_disk, size); bd_set_size(bdev, size << 9); -- GitLab From 9d1d4f9eabbca276a2a618a94ed3149d5971063e Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 23 Mar 2009 20:42:29 -0400 Subject: [PATCH 4165/4982] [ARM] Kirkwood: fail the probe if internal RTC does not work Having a RTC that doesn't maintain proper time across a reboot is one thing. But a RTC that doesn't work at all and only causes timeouts is another. Tested-by: Martin Michlmayr Signed-off-by: Nicolas Pitre --- drivers/rtc/rtc-mv.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c index 45f12dcd371..e0263d2005e 100644 --- a/drivers/rtc/rtc-mv.c +++ b/drivers/rtc/rtc-mv.c @@ -12,6 +12,7 @@ #include #include #include +#include #define RTC_TIME_REG_OFFS 0 @@ -119,6 +120,16 @@ static int __init mv_rtc_probe(struct platform_device *pdev) return -EINVAL; } + /* make sure it is actually functional */ + if (rtc_time == 0x01000000) { + ssleep(1); + rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS); + if (rtc_time == 0x01000000) { + dev_err(&pdev->dev, "internal RTC not ticking\n"); + return -ENODEV; + } + } + platform_set_drvdata(pdev, pdata); pdata->rtc = rtc_device_register(pdev->name, &pdev->dev, &mv_rtc_ops, THIS_MODULE); -- GitLab From 1d45209d89e647e9f27e4afa1f47338df73bc112 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 24 Mar 2009 14:26:50 +0100 Subject: [PATCH 4166/4982] netfilter: nf_conntrack: Reduce conntrack count in nf_conntrack_free() We use RCU to defer freeing of conntrack structures. In DOS situation, RCU might accumulate about 10.000 elements per CPU in its internal queues. To get accurate conntrack counts (at the expense of slightly more RAM used), we might consider conntrack counter not taking into account "about to be freed elements, waiting in RCU queues". We thus decrement it in nf_conntrack_free(), not in the RCU callback. Signed-off-by: Eric Dumazet Tested-by: Joakim Tjernlund Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index ebc27560012..55befe59e1c 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -517,16 +517,17 @@ EXPORT_SYMBOL_GPL(nf_conntrack_alloc); static void nf_conntrack_free_rcu(struct rcu_head *head) { struct nf_conn *ct = container_of(head, struct nf_conn, rcu); - struct net *net = nf_ct_net(ct); nf_ct_ext_free(ct); kmem_cache_free(nf_conntrack_cachep, ct); - atomic_dec(&net->ct.count); } void nf_conntrack_free(struct nf_conn *ct) { + struct net *net = nf_ct_net(ct); + nf_ct_ext_destroy(ct); + atomic_dec(&net->ct.count); call_rcu(&ct->rcu, nf_conntrack_free_rcu); } EXPORT_SYMBOL_GPL(nf_conntrack_free); -- GitLab From bb4f92b3a33bfc31f55098da85be44702bea2d16 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Tue, 24 Mar 2009 12:06:46 -0700 Subject: [PATCH 4167/4982] ucc_geth: Fix build breakage caused by a merge This patch fixes following build error: CC ucc_geth.o ucc_geth.c: In function 'ucc_geth_probe': ucc_geth.c:3644: error: implicit declaration of function 'uec_mdio_bus_name' make[2]: *** [ucc_geth.o] Error 1 Signed-off-by: Anton Vorontsov Signed-off-by: David S. Miller --- drivers/net/ucc_geth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 5f866e276dd..0b675127e83 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -3641,7 +3641,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma if (err) return -1; - uec_mdio_bus_name(bus_name, mdio); + fsl_pq_mdio_bus_name(bus_name, mdio); snprintf(ug_info->phy_bus_id, sizeof(ug_info->phy_bus_id), "%s:%02x", bus_name, *prop); } -- GitLab From 1aa292bb1c53500e3ab570b955d03afa97a9404d Mon Sep 17 00:00:00 2001 From: David Moore Date: Tue, 22 Jul 2008 23:23:40 -0700 Subject: [PATCH 4168/4982] firewire: Include iso timestamp in headers when header_size > 4 Previously, when an iso context had header_size > 4, the iso header (len/tag/channel/tcode/sy) was passed to userspace followed by quadlets stripped from the payload. This patch changes the behavior: header_size = 8 now passes the header quadlet followed by the timestamp quadlet. When header_size > 8, quadlets are stripped from the payload. The header_size = 4 case remains identical. Since this alters the semantics of the API, the firewire API version needs to be bumped concurrently with this change. This change also refactors the header copying code slightly to be much easier to read. Signed-off-by: David Moore Signed-off-by: Stefan Richter --- drivers/firewire/fw-ohci.c | 73 ++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 6d19828a93a..bbfd6cdac66 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -1765,6 +1765,28 @@ ohci_get_bus_time(struct fw_card *card) return bus_time; } +static void copy_iso_headers(struct iso_context *ctx, void *p) +{ + int i = ctx->header_length; + + if (i + ctx->base.header_size > PAGE_SIZE) + return; + + /* + * The iso header is byteswapped to little endian by + * the controller, but the remaining header quadlets + * are big endian. We want to present all the headers + * as big endian, so we have to swap the first quadlet. + */ + if (ctx->base.header_size > 0) + *(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4)); + if (ctx->base.header_size > 4) + *(u32 *) (ctx->header + i + 4) = __swab32(*(u32 *) p); + if (ctx->base.header_size > 8) + memcpy(ctx->header + i + 8, p + 8, ctx->base.header_size - 8); + ctx->header_length += ctx->base.header_size; +} + static int handle_ir_dualbuffer_packet(struct context *context, struct descriptor *d, struct descriptor *last) @@ -1775,7 +1797,6 @@ static int handle_ir_dualbuffer_packet(struct context *context, __le32 *ir_header; size_t header_length; void *p, *end; - int i; if (db->first_res_count != 0 && db->second_res_count != 0) { if (ctx->excess_bytes <= le16_to_cpu(db->second_req_count)) { @@ -1788,25 +1809,14 @@ static int handle_ir_dualbuffer_packet(struct context *context, header_length = le16_to_cpu(db->first_req_count) - le16_to_cpu(db->first_res_count); - i = ctx->header_length; p = db + 1; end = p + header_length; - while (p < end && i + ctx->base.header_size <= PAGE_SIZE) { - /* - * The iso header is byteswapped to little endian by - * the controller, but the remaining header quadlets - * are big endian. We want to present all the headers - * as big endian, so we have to swap the first - * quadlet. - */ - *(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4)); - memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4); - i += ctx->base.header_size; + while (p < end) { + copy_iso_headers(ctx, p); ctx->excess_bytes += (le32_to_cpu(*(__le32 *)(p + 4)) >> 16) & 0xffff; - p += ctx->base.header_size + 4; + p += max(ctx->base.header_size, (size_t)8); } - ctx->header_length = i; ctx->excess_bytes -= le16_to_cpu(db->second_req_count) - le16_to_cpu(db->second_res_count); @@ -1832,7 +1842,6 @@ static int handle_ir_packet_per_buffer(struct context *context, struct descriptor *pd; __le32 *ir_header; void *p; - int i; for (pd = d; pd <= last; pd++) { if (pd->transfer_status) @@ -1842,21 +1851,8 @@ static int handle_ir_packet_per_buffer(struct context *context, /* Descriptor(s) not done yet, stop iteration */ return 0; - i = ctx->header_length; - p = last + 1; - - if (ctx->base.header_size > 0 && - i + ctx->base.header_size <= PAGE_SIZE) { - /* - * The iso header is byteswapped to little endian by - * the controller, but the remaining header quadlets - * are big endian. We want to present all the headers - * as big endian, so we have to swap the first quadlet. - */ - *(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4)); - memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4); - ctx->header_length += ctx->base.header_size; - } + p = last + 1; + copy_iso_headers(ctx, p); if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) { ir_header = (__le32 *) p; @@ -2151,11 +2147,11 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, z = 2; /* - * The OHCI controller puts the status word in the header - * buffer too, so we need 4 extra bytes per packet. + * The OHCI controller puts the isochronous header and trailer in the + * buffer, so we need at least 8 bytes. */ packet_count = p->header_length / ctx->base.header_size; - header_size = packet_count * (ctx->base.header_size + 4); + header_size = packet_count * max(ctx->base.header_size, (size_t)8); /* Get header size in number of descriptors. */ header_z = DIV_ROUND_UP(header_size, sizeof(*d)); @@ -2173,7 +2169,8 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, db = (struct db_descriptor *) d; db->control = cpu_to_le16(DESCRIPTOR_STATUS | DESCRIPTOR_BRANCH_ALWAYS); - db->first_size = cpu_to_le16(ctx->base.header_size + 4); + db->first_size = + cpu_to_le16(max(ctx->base.header_size, (size_t)8)); if (p->skip && rest == p->payload_length) { db->control |= cpu_to_le16(DESCRIPTOR_WAIT); db->first_req_count = db->first_size; @@ -2223,11 +2220,11 @@ ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base, int page, offset, packet_count, header_size, payload_per_buffer; /* - * The OHCI controller puts the status word in the - * buffer too, so we need 4 extra bytes per packet. + * The OHCI controller puts the isochronous header and trailer in the + * buffer, so we need at least 8 bytes. */ packet_count = p->header_length / ctx->base.header_size; - header_size = ctx->base.header_size + 4; + header_size = max(ctx->base.header_size, (size_t)8); /* Get header size in number of descriptors. */ header_z = DIV_ROUND_UP(header_size, sizeof(*d)); -- GitLab From cf417e5494582453c033d8cac9e1352e74215435 Mon Sep 17 00:00:00 2001 From: Jay Fenlason Date: Fri, 3 Oct 2008 11:19:09 -0400 Subject: [PATCH 4169/4982] firewire: add a client_list_lock This adds a client_list_lock, which only protects the device's client_list, so that future versions of the driver can call code that takes the card->lock while holding the client_list_lock. Adding this lock is much simpler than adding __ versions of all the functions that the future version may need. The one ordering issue is to make sure code never takes the client_list_lock with card->lock held. Since client_list_lock is only used in three places, that isn't hard. Signed-off-by: Jay Fenlason Update fill_bus_reset_event() accordingly. Include linux/spinlock.h. Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 28 +++++++++++++--------------- drivers/firewire/fw-device.c | 2 ++ drivers/firewire/fw-device.h | 3 +++ 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index ed03234cbea..40cc9732dc2 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -132,9 +133,9 @@ static int fw_device_op_open(struct inode *inode, struct file *file) file->private_data = client; - spin_lock_irqsave(&device->card->lock, flags); + spin_lock_irqsave(&device->client_list_lock, flags); list_add_tail(&client->link, &device->client_list); - spin_unlock_irqrestore(&device->card->lock, flags); + spin_unlock_irqrestore(&device->client_list_lock, flags); return 0; } @@ -205,12 +206,14 @@ fw_device_op_read(struct file *file, return dequeue_event(client, buffer, count); } -/* caller must hold card->lock so that node pointers can be dereferenced here */ static void fill_bus_reset_event(struct fw_cdev_event_bus_reset *event, struct client *client) { struct fw_card *card = client->device->card; + unsigned long flags; + + spin_lock_irqsave(&card->lock, flags); event->closure = client->bus_reset_closure; event->type = FW_CDEV_EVENT_BUS_RESET; @@ -220,22 +223,23 @@ fill_bus_reset_event(struct fw_cdev_event_bus_reset *event, event->bm_node_id = 0; /* FIXME: We don't track the BM. */ event->irm_node_id = card->irm_node->node_id; event->root_node_id = card->root_node->node_id; + + spin_unlock_irqrestore(&card->lock, flags); } static void for_each_client(struct fw_device *device, void (*callback)(struct client *client)) { - struct fw_card *card = device->card; struct client *c; unsigned long flags; - spin_lock_irqsave(&card->lock, flags); + spin_lock_irqsave(&device->client_list_lock, flags); list_for_each_entry(c, &device->client_list, link) callback(c); - spin_unlock_irqrestore(&card->lock, flags); + spin_unlock_irqrestore(&device->client_list_lock, flags); } static void @@ -274,11 +278,11 @@ static int ioctl_get_info(struct client *client, void *buffer) { struct fw_cdev_get_info *get_info = buffer; struct fw_cdev_event_bus_reset bus_reset; - struct fw_card *card = client->device->card; unsigned long ret = 0; client->version = get_info->version; get_info->version = FW_CDEV_VERSION; + get_info->card = client->device->card->index; down_read(&fw_device_rwsem); @@ -300,18 +304,12 @@ static int ioctl_get_info(struct client *client, void *buffer) client->bus_reset_closure = get_info->bus_reset_closure; if (get_info->bus_reset != 0) { void __user *uptr = u64_to_uptr(get_info->bus_reset); - unsigned long flags; - spin_lock_irqsave(&card->lock, flags); fill_bus_reset_event(&bus_reset, client); - spin_unlock_irqrestore(&card->lock, flags); - if (copy_to_user(uptr, &bus_reset, sizeof(bus_reset))) return -EFAULT; } - get_info->card = card->index; - return 0; } @@ -1009,9 +1007,9 @@ static int fw_device_op_release(struct inode *inode, struct file *file) list_for_each_entry_safe(e, next_e, &client->event_list, link) kfree(e); - spin_lock_irqsave(&client->device->card->lock, flags); + spin_lock_irqsave(&client->device->client_list_lock, flags); list_del(&client->link); - spin_unlock_irqrestore(&client->device->card->lock, flags); + spin_unlock_irqrestore(&client->device->client_list_lock, flags); fw_device_put(client->device); kfree(client); diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index bf53acb4565..ffde1bed46b 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include "fw-transaction.h" @@ -1004,6 +1005,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event) device->node = fw_node_get(node); device->node_id = node->node_id; device->generation = card->generation; + spin_lock_init(&device->client_list_lock); INIT_LIST_HEAD(&device->client_list); /* diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h index 8ef6ec2ca21..008a7908a86 100644 --- a/drivers/firewire/fw-device.h +++ b/drivers/firewire/fw-device.h @@ -23,6 +23,7 @@ #include #include #include +#include #include enum fw_device_state { @@ -64,6 +65,8 @@ struct fw_device { bool cmc; struct fw_card *card; struct device device; + /* to prevent deadlocks, never take this lock with card->lock held */ + spinlock_t client_list_lock; struct list_head client_list; u32 *config_rom; size_t config_rom_length; -- GitLab From d67cfb9613f373d76daa2c8d209629601424ca12 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 5 Oct 2008 10:37:11 +0200 Subject: [PATCH 4170/4982] firewire: convert client_list_lock to mutex So far it is only taken in non-atomic contexts. Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 20 ++++++++------------ drivers/firewire/fw-device.c | 3 ++- drivers/firewire/fw-device.h | 7 ++++--- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 40cc9732dc2..75bbd66f852 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -108,7 +109,6 @@ static int fw_device_op_open(struct inode *inode, struct file *file) { struct fw_device *device; struct client *client; - unsigned long flags; device = fw_device_get_by_devt(inode->i_rdev); if (device == NULL) @@ -133,9 +133,9 @@ static int fw_device_op_open(struct inode *inode, struct file *file) file->private_data = client; - spin_lock_irqsave(&device->client_list_lock, flags); + mutex_lock(&device->client_list_mutex); list_add_tail(&client->link, &device->client_list); - spin_unlock_irqrestore(&device->client_list_lock, flags); + mutex_unlock(&device->client_list_mutex); return 0; } @@ -232,14 +232,11 @@ for_each_client(struct fw_device *device, void (*callback)(struct client *client)) { struct client *c; - unsigned long flags; - - spin_lock_irqsave(&device->client_list_lock, flags); + mutex_lock(&device->client_list_mutex); list_for_each_entry(c, &device->client_list, link) callback(c); - - spin_unlock_irqrestore(&device->client_list_lock, flags); + mutex_unlock(&device->client_list_mutex); } static void @@ -247,7 +244,7 @@ queue_bus_reset_event(struct client *client) { struct bus_reset *bus_reset; - bus_reset = kzalloc(sizeof(*bus_reset), GFP_ATOMIC); + bus_reset = kzalloc(sizeof(*bus_reset), GFP_KERNEL); if (bus_reset == NULL) { fw_notify("Out of memory when allocating bus reset event\n"); return; @@ -988,7 +985,6 @@ static int fw_device_op_release(struct inode *inode, struct file *file) struct client *client = file->private_data; struct event *e, *next_e; struct client_resource *r, *next_r; - unsigned long flags; if (client->buffer.pages) fw_iso_buffer_destroy(&client->buffer, client->device->card); @@ -1007,9 +1003,9 @@ static int fw_device_op_release(struct inode *inode, struct file *file) list_for_each_entry_safe(e, next_e, &client->event_list, link) kfree(e); - spin_lock_irqsave(&client->device->client_list_lock, flags); + mutex_lock(&client->device->client_list_mutex); list_del(&client->link); - spin_unlock_irqrestore(&client->device->client_list_lock, flags); + mutex_unlock(&client->device->client_list_mutex); fw_device_put(client->device); kfree(client); diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index ffde1bed46b..2de3dd5ebc4 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -1005,7 +1006,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event) device->node = fw_node_get(node); device->node_id = node->node_id; device->generation = card->generation; - spin_lock_init(&device->client_list_lock); + mutex_init(&device->client_list_mutex); INIT_LIST_HEAD(&device->client_list); /* diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h index 008a7908a86..655d7e83801 100644 --- a/drivers/firewire/fw-device.h +++ b/drivers/firewire/fw-device.h @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include enum fw_device_state { @@ -65,9 +65,10 @@ struct fw_device { bool cmc; struct fw_card *card; struct device device; - /* to prevent deadlocks, never take this lock with card->lock held */ - spinlock_t client_list_lock; + + struct mutex client_list_mutex; struct list_head client_list; + u32 *config_rom; size_t config_rom_length; int config_rom_retries; -- GitLab From bf8e3355ec8f4e472f9841e94203cd759b45226e Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Fri, 5 Dec 2008 22:43:41 +0100 Subject: [PATCH 4171/4982] firewire: cdev: documentation fixlet Reported-by: Jay Fenlason Signed-off-by: Stefan Richter --- include/linux/firewire-cdev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 4d078e99c01..899ef279f5b 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -229,7 +229,7 @@ struct fw_cdev_get_info { * Send a request to the device. This ioctl implements all outgoing requests. * Both quadlet and block request specify the payload as a pointer to the data * in the @data field. Once the transaction completes, the kernel writes an - * &fw_cdev_event_request event back. The @closure field is passed back to + * &fw_cdev_event_response event back. The @closure field is passed back to * user space in the response event. */ struct fw_cdev_send_request { -- GitLab From 1f3125af8ed7410cc0ebcc0acd59bbfc1ae0057a Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Fri, 5 Dec 2008 22:44:42 +0100 Subject: [PATCH 4172/4982] firewire: cdev: tcodes input validation The behaviour of fw-transaction.c::fw_send_request is ill-defined for any other tcodes than read/ write/ lock request tcodes. Therefore prevent requests with wrong tcodes from entering the transaction layer. Maybe fw_send_request should check them itself, but I am not inclined to change it and fw_fill_request from void-valued functions to ones which return error codes and pass those up. Besides, maybe fw_send_request is going to support one more tcode than ioctl_send_request in the future (TCODE_STREAM_DATA). Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 75bbd66f852..a320ab48edd 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -398,6 +398,7 @@ static int ioctl_send_request(struct client *client, void *buffer) struct fw_device *device = client->device; struct fw_cdev_send_request *request = buffer; struct response *response; + int ret; /* What is the biggest size we'll accept, really? */ if (request->length > 4096) @@ -414,8 +415,26 @@ static int ioctl_send_request(struct client *client, void *buffer) if (request->data && copy_from_user(response->response.data, u64_to_uptr(request->data), request->length)) { - kfree(response); - return -EFAULT; + ret = -EFAULT; + goto err; + } + + switch (request->tcode) { + case TCODE_WRITE_QUADLET_REQUEST: + case TCODE_WRITE_BLOCK_REQUEST: + case TCODE_READ_QUADLET_REQUEST: + case TCODE_READ_BLOCK_REQUEST: + case TCODE_LOCK_MASK_SWAP: + case TCODE_LOCK_COMPARE_SWAP: + case TCODE_LOCK_FETCH_ADD: + case TCODE_LOCK_LITTLE_ADD: + case TCODE_LOCK_BOUNDED_ADD: + case TCODE_LOCK_WRAP_ADD: + case TCODE_LOCK_VENDOR_DEPENDENT: + break; + default: + ret = -EINVAL; + goto err; } response->resource.release = release_transaction; @@ -434,6 +453,10 @@ static int ioctl_send_request(struct client *client, void *buffer) return sizeof(request) + request->length; else return sizeof(request); + err: + kfree(response); + + return ret; } struct address_handler { -- GitLab From 97811e347310766030a648fdf0e407b2c91a39c1 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 14 Dec 2008 19:19:23 +0100 Subject: [PATCH 4173/4982] firewire: cdev: fix race of fw_device_op_release with bus reset Unlink the client from the fw_device earlier in order to prevent bus reset events being added to client->event_list during shutdown. Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index a320ab48edd..4dd66c1a36d 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -1009,6 +1009,10 @@ static int fw_device_op_release(struct inode *inode, struct file *file) struct event *e, *next_e; struct client_resource *r, *next_r; + mutex_lock(&client->device->client_list_mutex); + list_del(&client->link); + mutex_unlock(&client->device->client_list_mutex); + if (client->buffer.pages) fw_iso_buffer_destroy(&client->buffer, client->device->card); @@ -1026,10 +1030,6 @@ static int fw_device_op_release(struct inode *inode, struct file *file) list_for_each_entry_safe(e, next_e, &client->event_list, link) kfree(e); - mutex_lock(&client->device->client_list_mutex); - list_del(&client->link); - mutex_unlock(&client->device->client_list_mutex); - fw_device_put(client->device); kfree(client); -- GitLab From 45ee3199eb3e4233b755a9bb353a0527a4c58b5f Mon Sep 17 00:00:00 2001 From: Jay Fenlason Date: Sun, 21 Dec 2008 16:47:17 +0100 Subject: [PATCH 4174/4982] firewire: cdev: use an idr rather than a linked list for resources The current code uses a linked list and a counter for storing resources and the corresponding handle numbers. By changing to an idr we can be safe from counter wrap-around giving two resources the same handle. Furthermore, the deallocation ioctls now check whether the resource to be freed is of the intended type. Signed-off-by: Jay Fenlason Some rework by Stefan R: - The idr API documentation says we get an ID within 0...0x7fffffff. Hence we can rest assured that idr handles fit into cdev handles. - Fix some races. Add a client->in_shutdown flag for this purpose. - Add allocation retry to add_client_resource(). - It is possible to use idr_for_each() in fw_device_op_release(). - Fix ioctl_send_response() regression. - Small style changes. Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 165 +++++++++++++++++++++++++------------ 1 file changed, 114 insertions(+), 51 deletions(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 4dd66c1a36d..094aee5c8bc 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -41,10 +41,12 @@ #include "fw-device.h" struct client; +struct client_resource; +typedef void (*client_resource_release_fn_t)(struct client *, + struct client_resource *); struct client_resource { - struct list_head link; - void (*release)(struct client *client, struct client_resource *r); - u32 handle; + client_resource_release_fn_t release; + int handle; }; /* @@ -78,9 +80,10 @@ struct iso_interrupt { struct client { u32 version; struct fw_device *device; + spinlock_t lock; - u32 resource_handle; - struct list_head resource_list; + bool in_shutdown; + struct idr resource_idr; struct list_head event_list; wait_queue_head_t wait; u64 bus_reset_closure; @@ -126,9 +129,9 @@ static int fw_device_op_open(struct inode *inode, struct file *file) } client->device = device; - INIT_LIST_HEAD(&client->event_list); - INIT_LIST_HEAD(&client->resource_list); spin_lock_init(&client->lock); + idr_init(&client->resource_idr); + INIT_LIST_HEAD(&client->event_list); init_waitqueue_head(&client->wait); file->private_data = client; @@ -151,7 +154,10 @@ static void queue_event(struct client *client, struct event *event, event->v[1].size = size1; spin_lock_irqsave(&client->lock, flags); - list_add_tail(&event->link, &client->event_list); + if (client->in_shutdown) + kfree(event); + else + list_add_tail(&event->link, &client->event_list); spin_unlock_irqrestore(&client->lock, flags); wake_up_interruptible(&client->wait); @@ -310,34 +316,49 @@ static int ioctl_get_info(struct client *client, void *buffer) return 0; } -static void -add_client_resource(struct client *client, struct client_resource *resource) +static int +add_client_resource(struct client *client, struct client_resource *resource, + gfp_t gfp_mask) { unsigned long flags; + int ret; + + retry: + if (idr_pre_get(&client->resource_idr, gfp_mask) == 0) + return -ENOMEM; spin_lock_irqsave(&client->lock, flags); - list_add_tail(&resource->link, &client->resource_list); - resource->handle = client->resource_handle++; + if (client->in_shutdown) + ret = -ECANCELED; + else + ret = idr_get_new(&client->resource_idr, resource, + &resource->handle); spin_unlock_irqrestore(&client->lock, flags); + + if (ret == -EAGAIN) + goto retry; + + return ret < 0 ? ret : 0; } static int release_client_resource(struct client *client, u32 handle, + client_resource_release_fn_t release, struct client_resource **resource) { struct client_resource *r; unsigned long flags; spin_lock_irqsave(&client->lock, flags); - list_for_each_entry(r, &client->resource_list, link) { - if (r->handle == handle) { - list_del(&r->link); - break; - } - } + if (client->in_shutdown) + r = NULL; + else + r = idr_find(&client->resource_idr, handle); + if (r && r->release == release) + idr_remove(&client->resource_idr, handle); spin_unlock_irqrestore(&client->lock, flags); - if (&r->link == &client->resource_list) + if (!(r && r->release == release)) return -EINVAL; if (resource) @@ -372,7 +393,12 @@ complete_transaction(struct fw_card *card, int rcode, memcpy(r->data, payload, r->length); spin_lock_irqsave(&client->lock, flags); - list_del(&response->resource.link); + /* + * If called while in shutdown, the idr tree must be left untouched. + * The idr handle will be removed later. + */ + if (!client->in_shutdown) + idr_remove(&client->resource_idr, response->resource.handle); spin_unlock_irqrestore(&client->lock, flags); r->type = FW_CDEV_EVENT_RESPONSE; @@ -416,7 +442,7 @@ static int ioctl_send_request(struct client *client, void *buffer) copy_from_user(response->response.data, u64_to_uptr(request->data), request->length)) { ret = -EFAULT; - goto err; + goto failed; } switch (request->tcode) { @@ -434,11 +460,13 @@ static int ioctl_send_request(struct client *client, void *buffer) break; default: ret = -EINVAL; - goto err; + goto failed; } response->resource.release = release_transaction; - add_client_resource(client, &response->resource); + ret = add_client_resource(client, &response->resource, GFP_KERNEL); + if (ret < 0) + goto failed; fw_send_request(device->card, &response->transaction, request->tcode & 0x1f, @@ -453,7 +481,7 @@ static int ioctl_send_request(struct client *client, void *buffer) return sizeof(request) + request->length; else return sizeof(request); - err: + failed: kfree(response); return ret; @@ -500,22 +528,21 @@ handle_request(struct fw_card *card, struct fw_request *r, struct request *request; struct request_event *e; struct client *client = handler->client; + int ret; request = kmalloc(sizeof(*request), GFP_ATOMIC); e = kmalloc(sizeof(*e), GFP_ATOMIC); - if (request == NULL || e == NULL) { - kfree(request); - kfree(e); - fw_send_response(card, r, RCODE_CONFLICT_ERROR); - return; - } + if (request == NULL || e == NULL) + goto failed; request->request = r; request->data = payload; request->length = length; request->resource.release = release_request; - add_client_resource(client, &request->resource); + ret = add_client_resource(client, &request->resource, GFP_ATOMIC); + if (ret < 0) + goto failed; e->request.type = FW_CDEV_EVENT_REQUEST; e->request.tcode = tcode; @@ -526,6 +553,12 @@ handle_request(struct fw_card *card, struct fw_request *r, queue_event(client, &e->event, &e->request, sizeof(e->request), payload, length); + return; + + failed: + kfree(request); + kfree(e); + fw_send_response(card, r, RCODE_CONFLICT_ERROR); } static void @@ -544,6 +577,7 @@ static int ioctl_allocate(struct client *client, void *buffer) struct fw_cdev_allocate *request = buffer; struct address_handler *handler; struct fw_address_region region; + int ret; handler = kmalloc(sizeof(*handler), GFP_KERNEL); if (handler == NULL) @@ -563,7 +597,11 @@ static int ioctl_allocate(struct client *client, void *buffer) } handler->resource.release = release_address_handler; - add_client_resource(client, &handler->resource); + ret = add_client_resource(client, &handler->resource, GFP_KERNEL); + if (ret < 0) { + release_address_handler(client, &handler->resource); + return ret; + } request->handle = handler->resource.handle; return 0; @@ -573,7 +611,8 @@ static int ioctl_deallocate(struct client *client, void *buffer) { struct fw_cdev_deallocate *request = buffer; - return release_client_resource(client, request->handle, NULL); + return release_client_resource(client, request->handle, + release_address_handler, NULL); } static int ioctl_send_response(struct client *client, void *buffer) @@ -582,8 +621,10 @@ static int ioctl_send_response(struct client *client, void *buffer) struct client_resource *resource; struct request *r; - if (release_client_resource(client, request->handle, &resource) < 0) + if (release_client_resource(client, request->handle, + release_request, &resource) < 0) return -EINVAL; + r = container_of(resource, struct request, resource); if (request->length < r->length) r->length = request->length; @@ -626,7 +667,7 @@ static int ioctl_add_descriptor(struct client *client, void *buffer) { struct fw_cdev_add_descriptor *request = buffer; struct descriptor *descriptor; - int retval; + int ret; if (request->length > 256) return -EINVAL; @@ -638,8 +679,8 @@ static int ioctl_add_descriptor(struct client *client, void *buffer) if (copy_from_user(descriptor->data, u64_to_uptr(request->data), request->length * 4)) { - kfree(descriptor); - return -EFAULT; + ret = -EFAULT; + goto failed; } descriptor->d.length = request->length; @@ -647,24 +688,31 @@ static int ioctl_add_descriptor(struct client *client, void *buffer) descriptor->d.key = request->key; descriptor->d.data = descriptor->data; - retval = fw_core_add_descriptor(&descriptor->d); - if (retval < 0) { - kfree(descriptor); - return retval; - } + ret = fw_core_add_descriptor(&descriptor->d); + if (ret < 0) + goto failed; descriptor->resource.release = release_descriptor; - add_client_resource(client, &descriptor->resource); + ret = add_client_resource(client, &descriptor->resource, GFP_KERNEL); + if (ret < 0) { + fw_core_remove_descriptor(&descriptor->d); + goto failed; + } request->handle = descriptor->resource.handle; return 0; + failed: + kfree(descriptor); + + return ret; } static int ioctl_remove_descriptor(struct client *client, void *buffer) { struct fw_cdev_remove_descriptor *request = buffer; - return release_client_resource(client, request->handle, NULL); + return release_client_resource(client, request->handle, + release_descriptor, NULL); } static void @@ -1003,11 +1051,21 @@ static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma) return retval; } +static int shutdown_resource(int id, void *p, void *data) +{ + struct client_resource *r = p; + struct client *client = data; + + r->release(client, r); + + return 0; +} + static int fw_device_op_release(struct inode *inode, struct file *file) { struct client *client = file->private_data; struct event *e, *next_e; - struct client_resource *r, *next_r; + unsigned long flags; mutex_lock(&client->device->client_list_mutex); list_del(&client->link); @@ -1019,17 +1077,22 @@ static int fw_device_op_release(struct inode *inode, struct file *file) if (client->iso_context) fw_iso_context_destroy(client->iso_context); - list_for_each_entry_safe(r, next_r, &client->resource_list, link) - r->release(client, r); + /* Freeze client->resource_idr and client->event_list */ + spin_lock_irqsave(&client->lock, flags); + client->in_shutdown = true; + spin_unlock_irqrestore(&client->lock, flags); - /* - * FIXME: We should wait for the async tasklets to stop - * running before freeing the memory. - */ + idr_for_each(&client->resource_idr, shutdown_resource, client); + idr_remove_all(&client->resource_idr); + idr_destroy(&client->resource_idr); list_for_each_entry_safe(e, next_e, &client->event_list, link) kfree(e); + /* + * FIXME: client should be reference-counted. It's extremely unlikely + * but there may still be transactions being completed at this point. + */ fw_device_put(client->device); kfree(client); -- GitLab From 3e0b5f0d7cb5fef402517e41eebff5a0f0e65a13 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 14 Dec 2008 19:21:01 +0100 Subject: [PATCH 4175/4982] firewire: cdev: address handler input validation Like before my commit 1415d9189e8c59aa9c77a3bba419dcea062c145f, fw_core_add_address_handler() does not align the address region now. Instead the caller is required to pass valid parameters. Since one of the callers of fw_core_add_address_handler() is the cdev userspace interface, we now check for valid input. If the client is buggy, we give it a hint with -EINVAL. Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 5 +++-- drivers/firewire/fw-transaction.c | 27 ++++++++++++++++++--------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 094aee5c8bc..44af45205dc 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -591,9 +591,10 @@ static int ioctl_allocate(struct client *client, void *buffer) handler->closure = request->closure; handler->client = client; - if (fw_core_add_address_handler(&handler->handler, ®ion) < 0) { + ret = fw_core_add_address_handler(&handler->handler, ®ion); + if (ret < 0) { kfree(handler); - return -EBUSY; + return ret; } handler->resource.release = release_address_handler; diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index 699ac041f39..12a6cdcb447 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -449,16 +449,19 @@ const struct fw_address_region fw_unit_space_region = #endif /* 0 */ /** - * Allocate a range of addresses in the node space of the OHCI - * controller. When a request is received that falls within the - * specified address range, the specified callback is invoked. The - * parameters passed to the callback give the details of the - * particular request. + * fw_core_add_address_handler - register for incoming requests + * @handler: callback + * @region: region in the IEEE 1212 node space address range + * + * region->start, ->end, and handler->length have to be quadlet-aligned. + * + * When a request is received that falls within the specified address range, + * the specified callback is invoked. The parameters passed to the callback + * give the details of the particular request. * * Return value: 0 on success, non-zero otherwise. * The start offset of the handler's address region is determined by * fw_core_add_address_handler() and is returned in handler->offset. - * The offset is quadlet-aligned. */ int fw_core_add_address_handler(struct fw_address_handler *handler, @@ -468,17 +471,23 @@ fw_core_add_address_handler(struct fw_address_handler *handler, unsigned long flags; int ret = -EBUSY; + if (region->start & 0xffff000000000003ULL || + region->end & 0xffff000000000003ULL || + region->start >= region->end || + handler->length & 3 || + handler->length == 0) + return -EINVAL; + spin_lock_irqsave(&address_handler_lock, flags); - handler->offset = roundup(region->start, 4); + handler->offset = region->start; while (handler->offset + handler->length <= region->end) { other = lookup_overlapping_address_handler(&address_handler_list, handler->offset, handler->length); if (other != NULL) { - handler->offset = - roundup(other->offset + other->length, 4); + handler->offset += other->length; } else { list_add_tail(&handler->link, &address_handler_list); ret = 0; -- GitLab From 44be21b63e0c551df21253540b7f216f0d18928e Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 14 Dec 2008 19:21:31 +0100 Subject: [PATCH 4176/4982] firewire: core: remove outdated comment Signed-off-by: Stefan Richter --- drivers/firewire/fw-transaction.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index 12a6cdcb447..024d1f5537c 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -502,12 +502,7 @@ fw_core_add_address_handler(struct fw_address_handler *handler, EXPORT_SYMBOL(fw_core_add_address_handler); /** - * Deallocate a range of addresses allocated with fw_allocate. This - * will call the associated callback one last time with a the special - * tcode TCODE_DEALLOCATE, to let the client destroy the registered - * callback data. For convenience, the callback parameters offset and - * length are set to the start and the length respectively for the - * deallocated region, payload is set to NULL. + * fw_core_remove_address_handler - unregister an address handler */ void fw_core_remove_address_handler(struct fw_address_handler *handler) { -- GitLab From c490a6dec6cc1b7f0eab56b9fbd565129b3dea2e Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 14 Dec 2008 21:45:14 +0100 Subject: [PATCH 4177/4982] firewire: core: remove obsolete assertions This code never changes. Signed-off-by: Stefan Richter --- drivers/firewire/fw-transaction.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index 024d1f5537c..058f5ed2439 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -955,19 +955,10 @@ static int __init fw_core_init(void) return fw_cdev_major; } - retval = fw_core_add_address_handler(&topology_map, - &topology_map_region); - BUG_ON(retval < 0); - - retval = fw_core_add_address_handler(®isters, - ®isters_region); - BUG_ON(retval < 0); - - /* Add the vendor textual descriptor. */ - retval = fw_core_add_descriptor(&vendor_id_descriptor); - BUG_ON(retval < 0); - retval = fw_core_add_descriptor(&model_id_descriptor); - BUG_ON(retval < 0); + fw_core_add_address_handler(&topology_map, &topology_map_region); + fw_core_add_address_handler(®isters, ®isters_region); + fw_core_add_descriptor(&vendor_id_descriptor); + fw_core_add_descriptor(&model_id_descriptor); return 0; } -- GitLab From 2dbd7d7e2327b0c2cc4e2de903e1cfa19980a504 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 14 Dec 2008 21:45:45 +0100 Subject: [PATCH 4178/4982] firewire: standardize a variable name "ret" is the new "retval". Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 44 +++++++++++++------------- drivers/firewire/fw-iso.c | 12 ++++---- drivers/firewire/fw-ohci.c | 51 +++++++++++++++---------------- drivers/firewire/fw-transaction.c | 8 ++--- 4 files changed, 57 insertions(+), 58 deletions(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 44af45205dc..07c32a4bada 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -169,13 +169,13 @@ dequeue_event(struct client *client, char __user *buffer, size_t count) unsigned long flags; struct event *event; size_t size, total; - int i, retval; + int i, ret; - retval = wait_event_interruptible(client->wait, - !list_empty(&client->event_list) || - fw_device_is_shutdown(client->device)); - if (retval < 0) - return retval; + ret = wait_event_interruptible(client->wait, + !list_empty(&client->event_list) || + fw_device_is_shutdown(client->device)); + if (ret < 0) + return ret; if (list_empty(&client->event_list) && fw_device_is_shutdown(client->device)) @@ -190,17 +190,17 @@ dequeue_event(struct client *client, char __user *buffer, size_t count) for (i = 0; i < ARRAY_SIZE(event->v) && total < count; i++) { size = min(event->v[i].size, count - total); if (copy_to_user(buffer + total, event->v[i].data, size)) { - retval = -EFAULT; + ret = -EFAULT; goto out; } total += size; } - retval = total; + ret = total; out: kfree(event); - return retval; + return ret; } static ssize_t @@ -958,7 +958,7 @@ static int dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) { char buffer[256]; - int retval; + int ret; if (_IOC_TYPE(cmd) != '#' || _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers)) @@ -970,9 +970,9 @@ dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) return -EFAULT; } - retval = ioctl_handlers[_IOC_NR(cmd)](client, buffer); - if (retval < 0) - return retval; + ret = ioctl_handlers[_IOC_NR(cmd)](client, buffer); + if (ret < 0) + return ret; if (_IOC_DIR(cmd) & _IOC_READ) { if (_IOC_SIZE(cmd) > sizeof(buffer) || @@ -980,7 +980,7 @@ dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) return -EFAULT; } - return retval; + return ret; } static long @@ -1014,7 +1014,7 @@ static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma) struct client *client = file->private_data; enum dma_data_direction direction; unsigned long size; - int page_count, retval; + int page_count, ret; if (fw_device_is_shutdown(client->device)) return -ENODEV; @@ -1040,16 +1040,16 @@ static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma) else direction = DMA_FROM_DEVICE; - retval = fw_iso_buffer_init(&client->buffer, client->device->card, - page_count, direction); - if (retval < 0) - return retval; + ret = fw_iso_buffer_init(&client->buffer, client->device->card, + page_count, direction); + if (ret < 0) + return ret; - retval = fw_iso_buffer_map(&client->buffer, vma); - if (retval < 0) + ret = fw_iso_buffer_map(&client->buffer, vma); + if (ret < 0) fw_iso_buffer_destroy(&client->buffer, client->device->card); - return retval; + return ret; } static int shutdown_resource(int id, void *p, void *data) diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c index e14c03dc006..cb32b20da9a 100644 --- a/drivers/firewire/fw-iso.c +++ b/drivers/firewire/fw-iso.c @@ -32,7 +32,7 @@ int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card, int page_count, enum dma_data_direction direction) { - int i, j, retval = -ENOMEM; + int i, j; dma_addr_t address; buffer->page_count = page_count; @@ -69,19 +69,19 @@ fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card, kfree(buffer->pages); out: buffer->pages = NULL; - return retval; + return -ENOMEM; } int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma) { unsigned long uaddr; - int i, retval; + int i, ret; uaddr = vma->vm_start; for (i = 0; i < buffer->page_count; i++) { - retval = vm_insert_page(vma, uaddr, buffer->pages[i]); - if (retval) - return retval; + ret = vm_insert_page(vma, uaddr, buffer->pages[i]); + if (ret) + return ret; uaddr += PAGE_SIZE; } diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index bbfd6cdac66..b941ab3da18 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -1209,7 +1209,7 @@ static void at_context_transmit(struct context *ctx, struct fw_packet *packet) { unsigned long flags; - int retval; + int ret; spin_lock_irqsave(&ctx->ohci->lock, flags); @@ -1220,10 +1220,10 @@ at_context_transmit(struct context *ctx, struct fw_packet *packet) return; } - retval = at_context_queue_packet(ctx, packet); + ret = at_context_queue_packet(ctx, packet); spin_unlock_irqrestore(&ctx->ohci->lock, flags); - if (retval < 0) + if (ret < 0) packet->callback(packet, &ctx->ohci->card, packet->ack); } @@ -1595,7 +1595,7 @@ ohci_set_config_rom(struct fw_card *card, u32 *config_rom, size_t length) { struct fw_ohci *ohci; unsigned long flags; - int retval = -EBUSY; + int ret = -EBUSY; __be32 *next_config_rom; dma_addr_t uninitialized_var(next_config_rom_bus); @@ -1649,7 +1649,7 @@ ohci_set_config_rom(struct fw_card *card, u32 *config_rom, size_t length) reg_write(ohci, OHCI1394_ConfigROMmap, ohci->next_config_rom_bus); - retval = 0; + ret = 0; } spin_unlock_irqrestore(&ohci->lock, flags); @@ -1661,13 +1661,13 @@ ohci_set_config_rom(struct fw_card *card, u32 *config_rom, size_t length) * controller could need to access it before the bus reset * takes effect. */ - if (retval == 0) + if (ret == 0) fw_core_initiate_bus_reset(&ohci->card, 1); else dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, next_config_rom, next_config_rom_bus); - return retval; + return ret; } static void ohci_send_request(struct fw_card *card, struct fw_packet *packet) @@ -1689,7 +1689,7 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet) struct fw_ohci *ohci = fw_ohci(card); struct context *ctx = &ohci->at_request_ctx; struct driver_data *driver_data = packet->driver_data; - int retval = -ENOENT; + int ret = -ENOENT; tasklet_disable(&ctx->tasklet); @@ -1704,12 +1704,11 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet) driver_data->packet = NULL; packet->ack = RCODE_CANCELLED; packet->callback(packet, &ohci->card, packet->ack); - retval = 0; - + ret = 0; out: tasklet_enable(&ctx->tasklet); - return retval; + return ret; } static int @@ -1720,7 +1719,7 @@ ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation) #else struct fw_ohci *ohci = fw_ohci(card); unsigned long flags; - int n, retval = 0; + int n, ret = 0; /* * FIXME: Make sure this bitmask is cleared when we clear the busReset @@ -1730,7 +1729,7 @@ ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation) spin_lock_irqsave(&ohci->lock, flags); if (ohci->generation != generation) { - retval = -ESTALE; + ret = -ESTALE; goto out; } @@ -1748,7 +1747,8 @@ ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation) flush_writes(ohci); out: spin_unlock_irqrestore(&ohci->lock, flags); - return retval; + + return ret; #endif /* CONFIG_FIREWIRE_OHCI_REMOTE_DMA */ } @@ -1892,7 +1892,7 @@ ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size) descriptor_callback_t callback; u32 *mask, regs; unsigned long flags; - int index, retval = -ENOMEM; + int index, ret = -ENOMEM; if (type == FW_ISO_CONTEXT_TRANSMIT) { mask = &ohci->it_context_mask; @@ -1928,8 +1928,8 @@ ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size) if (ctx->header == NULL) goto out; - retval = context_init(&ctx->context, ohci, regs, callback); - if (retval < 0) + ret = context_init(&ctx->context, ohci, regs, callback); + if (ret < 0) goto out_with_header; return &ctx->base; @@ -1941,7 +1941,7 @@ ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size) *mask |= 1 << index; spin_unlock_irqrestore(&ohci->lock, flags); - return ERR_PTR(retval); + return ERR_PTR(ret); } static int ohci_start_iso(struct fw_iso_context *base, @@ -2291,21 +2291,20 @@ ohci_queue_iso(struct fw_iso_context *base, { struct iso_context *ctx = container_of(base, struct iso_context, base); unsigned long flags; - int retval; + int ret; spin_lock_irqsave(&ctx->context.ohci->lock, flags); if (base->type == FW_ISO_CONTEXT_TRANSMIT) - retval = ohci_queue_iso_transmit(base, packet, buffer, payload); + ret = ohci_queue_iso_transmit(base, packet, buffer, payload); else if (ctx->context.ohci->use_dualbuffer) - retval = ohci_queue_iso_receive_dualbuffer(base, packet, - buffer, payload); + ret = ohci_queue_iso_receive_dualbuffer(base, packet, + buffer, payload); else - retval = ohci_queue_iso_receive_packet_per_buffer(base, packet, - buffer, - payload); + ret = ohci_queue_iso_receive_packet_per_buffer(base, packet, + buffer, payload); spin_unlock_irqrestore(&ctx->context.ohci->lock, flags); - return retval; + return ret; } static const struct fw_card_driver ohci_driver = { diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index 058f5ed2439..e17ebc42f12 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -943,11 +943,11 @@ static struct fw_descriptor model_id_descriptor = { static int __init fw_core_init(void) { - int retval; + int ret; - retval = bus_register(&fw_bus_type); - if (retval < 0) - return retval; + ret = bus_register(&fw_bus_type); + if (ret < 0) + return ret; fw_cdev_major = register_chrdev(0, "firewire", &fw_device_ops); if (fw_cdev_major < 0) { -- GitLab From 53dca51175cc2f66d21aeb1e70146cca65c53dad Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 14 Dec 2008 21:47:04 +0100 Subject: [PATCH 4179/4982] firewire: remove line breaks before function names type function_name(parameters); is nice to look at but was not used consistently. Signed-off-by: Stefan Richter --- drivers/firewire/fw-card.c | 68 +++++++------------ drivers/firewire/fw-cdev.c | 88 ++++++++++-------------- drivers/firewire/fw-device.c | 40 +++++------ drivers/firewire/fw-device.h | 3 +- drivers/firewire/fw-iso.c | 28 ++++---- drivers/firewire/fw-ohci.c | 100 ++++++++++++--------------- drivers/firewire/fw-sbp2.c | 57 +++++++--------- drivers/firewire/fw-topology.c | 28 +++----- drivers/firewire/fw-topology.h | 13 ++-- drivers/firewire/fw-transaction.c | 92 ++++++++++--------------- drivers/firewire/fw-transaction.h | 109 ++++++++++-------------------- 11 files changed, 249 insertions(+), 377 deletions(-) diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index a5dd7a665aa..27a3aae58cf 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c @@ -63,8 +63,7 @@ static int descriptor_count; #define BIB_CMC ((1) << 30) #define BIB_IMC ((1) << 31) -static u32 * -generate_config_rom(struct fw_card *card, size_t *config_rom_length) +static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length) { struct fw_descriptor *desc; static u32 config_rom[256]; @@ -128,8 +127,7 @@ generate_config_rom(struct fw_card *card, size_t *config_rom_length) return config_rom; } -static void -update_config_roms(void) +static void update_config_roms(void) { struct fw_card *card; u32 *config_rom; @@ -141,8 +139,7 @@ update_config_roms(void) } } -int -fw_core_add_descriptor(struct fw_descriptor *desc) +int fw_core_add_descriptor(struct fw_descriptor *desc) { size_t i; @@ -171,8 +168,7 @@ fw_core_add_descriptor(struct fw_descriptor *desc) return 0; } -void -fw_core_remove_descriptor(struct fw_descriptor *desc) +void fw_core_remove_descriptor(struct fw_descriptor *desc) { mutex_lock(&card_mutex); @@ -189,8 +185,7 @@ static const char gap_count_table[] = { 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40 }; -void -fw_schedule_bm_work(struct fw_card *card, unsigned long delay) +void fw_schedule_bm_work(struct fw_card *card, unsigned long delay) { int scheduled; @@ -200,8 +195,7 @@ fw_schedule_bm_work(struct fw_card *card, unsigned long delay) fw_card_put(card); } -static void -fw_card_bm_work(struct work_struct *work) +static void fw_card_bm_work(struct work_struct *work) { struct fw_card *card = container_of(work, struct fw_card, work.work); struct fw_device *root_device; @@ -371,17 +365,16 @@ fw_card_bm_work(struct work_struct *work) fw_card_put(card); } -static void -flush_timer_callback(unsigned long data) +static void flush_timer_callback(unsigned long data) { struct fw_card *card = (struct fw_card *)data; fw_flush_transactions(card); } -void -fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, - struct device *device) +void fw_card_initialize(struct fw_card *card, + const struct fw_card_driver *driver, + struct device *device) { static atomic_t index = ATOMIC_INIT(-1); @@ -406,9 +399,8 @@ fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, } EXPORT_SYMBOL(fw_card_initialize); -int -fw_card_add(struct fw_card *card, - u32 max_receive, u32 link_speed, u64 guid) +int fw_card_add(struct fw_card *card, + u32 max_receive, u32 link_speed, u64 guid) { u32 *config_rom; size_t length; @@ -442,23 +434,20 @@ EXPORT_SYMBOL(fw_card_add); * dummy driver just fails all IO. */ -static int -dummy_enable(struct fw_card *card, u32 *config_rom, size_t length) +static int dummy_enable(struct fw_card *card, u32 *config_rom, size_t length) { BUG(); return -1; } -static int -dummy_update_phy_reg(struct fw_card *card, int address, - int clear_bits, int set_bits) +static int dummy_update_phy_reg(struct fw_card *card, int address, + int clear_bits, int set_bits) { return -ENODEV; } -static int -dummy_set_config_rom(struct fw_card *card, - u32 *config_rom, size_t length) +static int dummy_set_config_rom(struct fw_card *card, + u32 *config_rom, size_t length) { /* * We take the card out of card_list before setting the dummy @@ -468,27 +457,23 @@ dummy_set_config_rom(struct fw_card *card, return -1; } -static void -dummy_send_request(struct fw_card *card, struct fw_packet *packet) +static void dummy_send_request(struct fw_card *card, struct fw_packet *packet) { packet->callback(packet, card, -ENODEV); } -static void -dummy_send_response(struct fw_card *card, struct fw_packet *packet) +static void dummy_send_response(struct fw_card *card, struct fw_packet *packet) { packet->callback(packet, card, -ENODEV); } -static int -dummy_cancel_packet(struct fw_card *card, struct fw_packet *packet) +static int dummy_cancel_packet(struct fw_card *card, struct fw_packet *packet) { return -ENOENT; } -static int -dummy_enable_phys_dma(struct fw_card *card, - int node_id, int generation) +static int dummy_enable_phys_dma(struct fw_card *card, + int node_id, int generation) { return -ENODEV; } @@ -503,16 +488,14 @@ static struct fw_card_driver dummy_driver = { .enable_phys_dma = dummy_enable_phys_dma, }; -void -fw_card_release(struct kref *kref) +void fw_card_release(struct kref *kref) { struct fw_card *card = container_of(kref, struct fw_card, kref); complete(&card->done); } -void -fw_core_remove_card(struct fw_card *card) +void fw_core_remove_card(struct fw_card *card) { card->driver->update_phy_reg(card, 4, PHY_LINK_ACTIVE | PHY_CONTENDER, 0); @@ -536,8 +519,7 @@ fw_core_remove_card(struct fw_card *card) } EXPORT_SYMBOL(fw_core_remove_card); -int -fw_core_initiate_bus_reset(struct fw_card *card, int short_reset) +int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset) { int reg = short_reset ? 5 : 1; int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET; diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 07c32a4bada..3c075b2eedf 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -96,14 +96,12 @@ struct client { struct list_head link; }; -static inline void __user * -u64_to_uptr(__u64 value) +static inline void __user *u64_to_uptr(__u64 value) { return (void __user *)(unsigned long)value; } -static inline __u64 -uptr_to_u64(void __user *ptr) +static inline __u64 uptr_to_u64(void __user *ptr) { return (__u64)(unsigned long)ptr; } @@ -163,8 +161,8 @@ static void queue_event(struct client *client, struct event *event, wake_up_interruptible(&client->wait); } -static int -dequeue_event(struct client *client, char __user *buffer, size_t count) +static int dequeue_event(struct client *client, + char __user *buffer, size_t count) { unsigned long flags; struct event *event; @@ -203,18 +201,16 @@ dequeue_event(struct client *client, char __user *buffer, size_t count) return ret; } -static ssize_t -fw_device_op_read(struct file *file, - char __user *buffer, size_t count, loff_t *offset) +static ssize_t fw_device_op_read(struct file *file, char __user *buffer, + size_t count, loff_t *offset) { struct client *client = file->private_data; return dequeue_event(client, buffer, count); } -static void -fill_bus_reset_event(struct fw_cdev_event_bus_reset *event, - struct client *client) +static void fill_bus_reset_event(struct fw_cdev_event_bus_reset *event, + struct client *client) { struct fw_card *card = client->device->card; unsigned long flags; @@ -233,9 +229,8 @@ fill_bus_reset_event(struct fw_cdev_event_bus_reset *event, spin_unlock_irqrestore(&card->lock, flags); } -static void -for_each_client(struct fw_device *device, - void (*callback)(struct client *client)) +static void for_each_client(struct fw_device *device, + void (*callback)(struct client *client)) { struct client *c; @@ -245,8 +240,7 @@ for_each_client(struct fw_device *device, mutex_unlock(&device->client_list_mutex); } -static void -queue_bus_reset_event(struct client *client) +static void queue_bus_reset_event(struct client *client) { struct bus_reset *bus_reset; @@ -316,9 +310,8 @@ static int ioctl_get_info(struct client *client, void *buffer) return 0; } -static int -add_client_resource(struct client *client, struct client_resource *resource, - gfp_t gfp_mask) +static int add_client_resource(struct client *client, + struct client_resource *resource, gfp_t gfp_mask) { unsigned long flags; int ret; @@ -341,10 +334,9 @@ add_client_resource(struct client *client, struct client_resource *resource, return ret < 0 ? ret : 0; } -static int -release_client_resource(struct client *client, u32 handle, - client_resource_release_fn_t release, - struct client_resource **resource) +static int release_client_resource(struct client *client, u32 handle, + client_resource_release_fn_t release, + struct client_resource **resource) { struct client_resource *r; unsigned long flags; @@ -369,8 +361,8 @@ release_client_resource(struct client *client, u32 handle, return 0; } -static void -release_transaction(struct client *client, struct client_resource *resource) +static void release_transaction(struct client *client, + struct client_resource *resource) { struct response *response = container_of(resource, struct response, resource); @@ -378,9 +370,8 @@ release_transaction(struct client *client, struct client_resource *resource) fw_cancel_transaction(client->device->card, &response->transaction); } -static void -complete_transaction(struct fw_card *card, int rcode, - void *payload, size_t length, void *data) +static void complete_transaction(struct fw_card *card, int rcode, + void *payload, size_t length, void *data) { struct response *response = data; struct client *client = response->client; @@ -506,8 +497,8 @@ struct request_event { struct fw_cdev_event_request request; }; -static void -release_request(struct client *client, struct client_resource *resource) +static void release_request(struct client *client, + struct client_resource *resource) { struct request *request = container_of(resource, struct request, resource); @@ -517,12 +508,11 @@ release_request(struct client *client, struct client_resource *resource) kfree(request); } -static void -handle_request(struct fw_card *card, struct fw_request *r, - int tcode, int destination, int source, - int generation, int speed, - unsigned long long offset, - void *payload, size_t length, void *callback_data) +static void handle_request(struct fw_card *card, struct fw_request *r, + int tcode, int destination, int source, + int generation, int speed, + unsigned long long offset, + void *payload, size_t length, void *callback_data) { struct address_handler *handler = callback_data; struct request *request; @@ -561,9 +551,8 @@ handle_request(struct fw_card *card, struct fw_request *r, fw_send_response(card, r, RCODE_CONFLICT_ERROR); } -static void -release_address_handler(struct client *client, - struct client_resource *resource) +static void release_address_handler(struct client *client, + struct client_resource *resource) { struct address_handler *handler = container_of(resource, struct address_handler, resource); @@ -716,9 +705,8 @@ static int ioctl_remove_descriptor(struct client *client, void *buffer) release_descriptor, NULL); } -static void -iso_callback(struct fw_iso_context *context, u32 cycle, - size_t header_length, void *header, void *data) +static void iso_callback(struct fw_iso_context *context, u32 cycle, + size_t header_length, void *header, void *data) { struct client *client = data; struct iso_interrupt *irq; @@ -954,8 +942,8 @@ static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { ioctl_get_cycle_timer, }; -static int -dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) +static int dispatch_ioctl(struct client *client, + unsigned int cmd, void __user *arg) { char buffer[256]; int ret; @@ -983,9 +971,8 @@ dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) return ret; } -static long -fw_device_op_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) +static long fw_device_op_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) { struct client *client = file->private_data; @@ -996,9 +983,8 @@ fw_device_op_ioctl(struct file *file, } #ifdef CONFIG_COMPAT -static long -fw_device_op_compat_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) +static long fw_device_op_compat_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) { struct client *client = file->private_data; diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index 2de3dd5ebc4..ac5043cc9ad 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c @@ -134,8 +134,7 @@ static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size) vendor, model, specifier_id, version); } -static int -fw_unit_uevent(struct device *dev, struct kobj_uevent_env *env) +static int fw_unit_uevent(struct device *dev, struct kobj_uevent_env *env) { struct fw_unit *unit = fw_unit(dev); char modalias[64]; @@ -193,8 +192,8 @@ struct config_rom_attribute { u32 key; }; -static ssize_t -show_immediate(struct device *dev, struct device_attribute *dattr, char *buf) +static ssize_t show_immediate(struct device *dev, + struct device_attribute *dattr, char *buf) { struct config_rom_attribute *attr = container_of(dattr, struct config_rom_attribute, attr); @@ -225,8 +224,8 @@ show_immediate(struct device *dev, struct device_attribute *dattr, char *buf) #define IMMEDIATE_ATTR(name, key) \ { __ATTR(name, S_IRUGO, show_immediate, NULL), key } -static ssize_t -show_text_leaf(struct device *dev, struct device_attribute *dattr, char *buf) +static ssize_t show_text_leaf(struct device *dev, + struct device_attribute *dattr, char *buf) { struct config_rom_attribute *attr = container_of(dattr, struct config_rom_attribute, attr); @@ -295,10 +294,9 @@ static struct config_rom_attribute config_rom_attributes[] = { TEXT_LEAF_ATTR(hardware_version_name, CSR_HARDWARE_VERSION), }; -static void -init_fw_attribute_group(struct device *dev, - struct device_attribute *attrs, - struct fw_attribute_group *group) +static void init_fw_attribute_group(struct device *dev, + struct device_attribute *attrs, + struct fw_attribute_group *group) { struct device_attribute *attr; int i, j; @@ -321,9 +319,8 @@ init_fw_attribute_group(struct device *dev, dev->groups = group->groups; } -static ssize_t -modalias_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t modalias_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct fw_unit *unit = fw_unit(dev); int length; @@ -334,9 +331,8 @@ modalias_show(struct device *dev, return length + 1; } -static ssize_t -rom_index_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t rom_index_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct fw_device *device = fw_device(dev->parent); struct fw_unit *unit = fw_unit(dev); @@ -351,8 +347,8 @@ static struct device_attribute fw_unit_attributes[] = { __ATTR_NULL, }; -static ssize_t -config_rom_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t config_rom_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct fw_device *device = fw_device(dev); size_t length; @@ -365,8 +361,8 @@ config_rom_show(struct device *dev, struct device_attribute *attr, char *buf) return length; } -static ssize_t -guid_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t guid_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct fw_device *device = fw_device(dev); int ret; @@ -385,8 +381,8 @@ static struct device_attribute fw_device_attributes[] = { __ATTR_NULL, }; -static int -read_rom(struct fw_device *device, int generation, int index, u32 *data) +static int read_rom(struct fw_device *device, + int generation, int index, u32 *data) { int rcode; diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h index 655d7e83801..41483f1a1be 100644 --- a/drivers/firewire/fw-device.h +++ b/drivers/firewire/fw-device.h @@ -180,8 +180,7 @@ struct fw_driver { const struct fw_device_id *id_table; }; -static inline struct fw_driver * -fw_driver(struct device_driver *drv) +static inline struct fw_driver *fw_driver(struct device_driver *drv) { return container_of(drv, struct fw_driver, driver); } diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c index cb32b20da9a..3ff2cfc1bba 100644 --- a/drivers/firewire/fw-iso.c +++ b/drivers/firewire/fw-iso.c @@ -28,9 +28,8 @@ #include "fw-topology.h" #include "fw-device.h" -int -fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card, - int page_count, enum dma_data_direction direction) +int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card, + int page_count, enum dma_data_direction direction) { int i, j; dma_addr_t address; @@ -105,10 +104,9 @@ void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, buffer->pages = NULL; } -struct fw_iso_context * -fw_iso_context_create(struct fw_card *card, int type, - int channel, int speed, size_t header_size, - fw_iso_callback_t callback, void *callback_data) +struct fw_iso_context *fw_iso_context_create(struct fw_card *card, + int type, int channel, int speed, size_t header_size, + fw_iso_callback_t callback, void *callback_data) { struct fw_iso_context *ctx; @@ -134,25 +132,23 @@ void fw_iso_context_destroy(struct fw_iso_context *ctx) card->driver->free_iso_context(ctx); } -int -fw_iso_context_start(struct fw_iso_context *ctx, int cycle, int sync, int tags) +int fw_iso_context_start(struct fw_iso_context *ctx, + int cycle, int sync, int tags) { return ctx->card->driver->start_iso(ctx, cycle, sync, tags); } -int -fw_iso_context_queue(struct fw_iso_context *ctx, - struct fw_iso_packet *packet, - struct fw_iso_buffer *buffer, - unsigned long payload) +int fw_iso_context_queue(struct fw_iso_context *ctx, + struct fw_iso_packet *packet, + struct fw_iso_buffer *buffer, + unsigned long payload) { struct fw_card *card = ctx->card; return card->driver->queue_iso(ctx, packet, buffer, payload); } -int -fw_iso_context_stop(struct fw_iso_context *ctx) +int fw_iso_context_stop(struct fw_iso_context *ctx) { return ctx->card->driver->stop_iso(ctx); } diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index b941ab3da18..4c7cf15986a 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -441,9 +441,8 @@ static inline void flush_writes(const struct fw_ohci *ohci) reg_read(ohci, OHCI1394_Version); } -static int -ohci_update_phy_reg(struct fw_card *card, int addr, - int clear_bits, int set_bits) +static int ohci_update_phy_reg(struct fw_card *card, int addr, + int clear_bits, int set_bits) { struct fw_ohci *ohci = fw_ohci(card); u32 val, old; @@ -658,8 +657,8 @@ static void ar_context_tasklet(unsigned long data) } } -static int -ar_context_init(struct ar_context *ctx, struct fw_ohci *ohci, u32 regs) +static int ar_context_init(struct ar_context *ctx, + struct fw_ohci *ohci, u32 regs) { struct ar_buffer ab; @@ -690,8 +689,7 @@ static void ar_context_run(struct ar_context *ctx) flush_writes(ctx->ohci); } -static struct descriptor * -find_branch_descriptor(struct descriptor *d, int z) +static struct descriptor *find_branch_descriptor(struct descriptor *d, int z) { int b, key; @@ -751,8 +749,7 @@ static void context_tasklet(unsigned long data) * Allocate a new buffer and add it to the list of free buffers for this * context. Must be called with ohci->lock held. */ -static int -context_add_buffer(struct context *ctx) +static int context_add_buffer(struct context *ctx) { struct descriptor_buffer *desc; dma_addr_t uninitialized_var(bus_addr); @@ -781,9 +778,8 @@ context_add_buffer(struct context *ctx) return 0; } -static int -context_init(struct context *ctx, struct fw_ohci *ohci, - u32 regs, descriptor_callback_t callback) +static int context_init(struct context *ctx, struct fw_ohci *ohci, + u32 regs, descriptor_callback_t callback) { ctx->ohci = ohci; ctx->regs = regs; @@ -814,8 +810,7 @@ context_init(struct context *ctx, struct fw_ohci *ohci, return 0; } -static void -context_release(struct context *ctx) +static void context_release(struct context *ctx) { struct fw_card *card = &ctx->ohci->card; struct descriptor_buffer *desc, *tmp; @@ -827,8 +822,8 @@ context_release(struct context *ctx) } /* Must be called with ohci->lock held */ -static struct descriptor * -context_get_descriptors(struct context *ctx, int z, dma_addr_t *d_bus) +static struct descriptor *context_get_descriptors(struct context *ctx, + int z, dma_addr_t *d_bus) { struct descriptor *d = NULL; struct descriptor_buffer *desc = ctx->buffer_tail; @@ -912,8 +907,8 @@ struct driver_data { * Must always be called with the ochi->lock held to ensure proper * generation handling and locking around packet queue manipulation. */ -static int -at_context_queue_packet(struct context *ctx, struct fw_packet *packet) +static int at_context_queue_packet(struct context *ctx, + struct fw_packet *packet) { struct fw_ohci *ohci = ctx->ohci; dma_addr_t d_bus, uninitialized_var(payload_bus); @@ -1095,8 +1090,8 @@ static int handle_at_packet(struct context *context, #define HEADER_GET_DATA_LENGTH(q) (((q) >> 16) & 0xffff) #define HEADER_GET_EXTENDED_TCODE(q) (((q) >> 0) & 0xffff) -static void -handle_local_rom(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr) +static void handle_local_rom(struct fw_ohci *ohci, + struct fw_packet *packet, u32 csr) { struct fw_packet response; int tcode, length, i; @@ -1122,8 +1117,8 @@ handle_local_rom(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr) fw_core_handle_response(&ohci->card, &response); } -static void -handle_local_lock(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr) +static void handle_local_lock(struct fw_ohci *ohci, + struct fw_packet *packet, u32 csr) { struct fw_packet response; int tcode, length, ext_tcode, sel; @@ -1164,8 +1159,7 @@ handle_local_lock(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr) fw_core_handle_response(&ohci->card, &response); } -static void -handle_local_request(struct context *ctx, struct fw_packet *packet) +static void handle_local_request(struct context *ctx, struct fw_packet *packet) { u64 offset; u32 csr; @@ -1205,8 +1199,7 @@ handle_local_request(struct context *ctx, struct fw_packet *packet) } } -static void -at_context_transmit(struct context *ctx, struct fw_packet *packet) +static void at_context_transmit(struct context *ctx, struct fw_packet *packet) { unsigned long flags; int ret; @@ -1590,8 +1583,8 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length) return 0; } -static int -ohci_set_config_rom(struct fw_card *card, u32 *config_rom, size_t length) +static int ohci_set_config_rom(struct fw_card *card, + u32 *config_rom, size_t length) { struct fw_ohci *ohci; unsigned long flags; @@ -1711,8 +1704,8 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet) return ret; } -static int -ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation) +static int ohci_enable_phys_dma(struct fw_card *card, + int node_id, int generation) { #ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA return 0; @@ -1752,8 +1745,7 @@ ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation) #endif /* CONFIG_FIREWIRE_OHCI_REMOTE_DMA */ } -static u64 -ohci_get_bus_time(struct fw_card *card) +static u64 ohci_get_bus_time(struct fw_card *card) { struct fw_ohci *ohci = fw_ohci(card); u32 cycle_time; @@ -1884,8 +1876,8 @@ static int handle_it_packet(struct context *context, return 1; } -static struct fw_iso_context * -ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size) +static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card, + int type, size_t header_size) { struct fw_ohci *ohci = fw_ohci(card); struct iso_context *ctx, *list; @@ -2025,11 +2017,10 @@ static void ohci_free_iso_context(struct fw_iso_context *base) spin_unlock_irqrestore(&ohci->lock, flags); } -static int -ohci_queue_iso_transmit(struct fw_iso_context *base, - struct fw_iso_packet *packet, - struct fw_iso_buffer *buffer, - unsigned long payload) +static int ohci_queue_iso_transmit(struct fw_iso_context *base, + struct fw_iso_packet *packet, + struct fw_iso_buffer *buffer, + unsigned long payload) { struct iso_context *ctx = container_of(base, struct iso_context, base); struct descriptor *d, *last, *pd; @@ -2124,11 +2115,10 @@ ohci_queue_iso_transmit(struct fw_iso_context *base, return 0; } -static int -ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, - struct fw_iso_packet *packet, - struct fw_iso_buffer *buffer, - unsigned long payload) +static int ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, + struct fw_iso_packet *packet, + struct fw_iso_buffer *buffer, + unsigned long payload) { struct iso_context *ctx = container_of(base, struct iso_context, base); struct db_descriptor *db = NULL; @@ -2205,11 +2195,10 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, return 0; } -static int -ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base, - struct fw_iso_packet *packet, - struct fw_iso_buffer *buffer, - unsigned long payload) +static int ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base, + struct fw_iso_packet *packet, + struct fw_iso_buffer *buffer, + unsigned long payload) { struct iso_context *ctx = container_of(base, struct iso_context, base); struct descriptor *d = NULL, *pd = NULL; @@ -2283,11 +2272,10 @@ ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base, return 0; } -static int -ohci_queue_iso(struct fw_iso_context *base, - struct fw_iso_packet *packet, - struct fw_iso_buffer *buffer, - unsigned long payload) +static int ohci_queue_iso(struct fw_iso_context *base, + struct fw_iso_packet *packet, + struct fw_iso_buffer *buffer, + unsigned long payload) { struct iso_context *ctx = container_of(base, struct iso_context, base); unsigned long flags; @@ -2353,8 +2341,8 @@ static void ohci_pmac_off(struct pci_dev *dev) #define ohci_pmac_off(dev) #endif /* CONFIG_PPC_PMAC */ -static int __devinit -pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) +static int __devinit pci_probe(struct pci_dev *dev, + const struct pci_device_id *ent) { struct fw_ohci *ohci; u32 bus_options, max_receive, link_speed, version; diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index c71c4419d9e..2bcf51557c7 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c @@ -392,20 +392,18 @@ static const struct { } }; -static void -free_orb(struct kref *kref) +static void free_orb(struct kref *kref) { struct sbp2_orb *orb = container_of(kref, struct sbp2_orb, kref); kfree(orb); } -static void -sbp2_status_write(struct fw_card *card, struct fw_request *request, - int tcode, int destination, int source, - int generation, int speed, - unsigned long long offset, - void *payload, size_t length, void *callback_data) +static void sbp2_status_write(struct fw_card *card, struct fw_request *request, + int tcode, int destination, int source, + int generation, int speed, + unsigned long long offset, + void *payload, size_t length, void *callback_data) { struct sbp2_logical_unit *lu = callback_data; struct sbp2_orb *orb; @@ -451,9 +449,8 @@ sbp2_status_write(struct fw_card *card, struct fw_request *request, fw_send_response(card, request, RCODE_COMPLETE); } -static void -complete_transaction(struct fw_card *card, int rcode, - void *payload, size_t length, void *data) +static void complete_transaction(struct fw_card *card, int rcode, + void *payload, size_t length, void *data) { struct sbp2_orb *orb = data; unsigned long flags; @@ -482,9 +479,8 @@ complete_transaction(struct fw_card *card, int rcode, kref_put(&orb->kref, free_orb); } -static void -sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu, - int node_id, int generation, u64 offset) +static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu, + int node_id, int generation, u64 offset) { struct fw_device *device = fw_device(lu->tgt->unit->device.parent); unsigned long flags; @@ -531,8 +527,8 @@ static int sbp2_cancel_orbs(struct sbp2_logical_unit *lu) return retval; } -static void -complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) +static void complete_management_orb(struct sbp2_orb *base_orb, + struct sbp2_status *status) { struct sbp2_management_orb *orb = container_of(base_orb, struct sbp2_management_orb, base); @@ -542,10 +538,9 @@ complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) complete(&orb->done); } -static int -sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id, - int generation, int function, int lun_or_login_id, - void *response) +static int sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id, + int generation, int function, + int lun_or_login_id, void *response) { struct fw_device *device = fw_device(lu->tgt->unit->device.parent); struct sbp2_management_orb *orb; @@ -652,9 +647,8 @@ static void sbp2_agent_reset(struct sbp2_logical_unit *lu) &d, sizeof(d)); } -static void -complete_agent_reset_write_no_wait(struct fw_card *card, int rcode, - void *payload, size_t length, void *data) +static void complete_agent_reset_write_no_wait(struct fw_card *card, + int rcode, void *payload, size_t length, void *data) { kfree(data); } @@ -1299,8 +1293,7 @@ static void sbp2_unmap_scatterlist(struct device *card_device, sizeof(orb->page_table), DMA_TO_DEVICE); } -static unsigned int -sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data) +static unsigned int sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data) { int sam_status; @@ -1337,8 +1330,8 @@ sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data) } } -static void -complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) +static void complete_command_orb(struct sbp2_orb *base_orb, + struct sbp2_status *status) { struct sbp2_command_orb *orb = container_of(base_orb, struct sbp2_command_orb, base); @@ -1384,9 +1377,8 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) orb->done(orb->cmd); } -static int -sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device, - struct sbp2_logical_unit *lu) +static int sbp2_map_scatterlist(struct sbp2_command_orb *orb, + struct fw_device *device, struct sbp2_logical_unit *lu) { struct scatterlist *sg = scsi_sglist(orb->cmd); int i, n; @@ -1584,9 +1576,8 @@ static int sbp2_scsi_abort(struct scsi_cmnd *cmd) * This is the concatenation of target port identifier and logical unit * identifier as per SAM-2...SAM-4 annex A. */ -static ssize_t -sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct scsi_device *sdev = to_scsi_device(dev); struct sbp2_logical_unit *lu; diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c index 8dd6703b55c..b44131cf0c6 100644 --- a/drivers/firewire/fw-topology.c +++ b/drivers/firewire/fw-topology.c @@ -314,9 +314,8 @@ typedef void (*fw_node_callback_t)(struct fw_card * card, struct fw_node * node, struct fw_node * parent); -static void -for_each_fw_node(struct fw_card *card, struct fw_node *root, - fw_node_callback_t callback) +static void for_each_fw_node(struct fw_card *card, struct fw_node *root, + fw_node_callback_t callback) { struct list_head list; struct fw_node *node, *next, *child, *parent; @@ -349,9 +348,8 @@ for_each_fw_node(struct fw_card *card, struct fw_node *root, fw_node_put(node); } -static void -report_lost_node(struct fw_card *card, - struct fw_node *node, struct fw_node *parent) +static void report_lost_node(struct fw_card *card, + struct fw_node *node, struct fw_node *parent) { fw_node_event(card, node, FW_NODE_DESTROYED); fw_node_put(node); @@ -360,9 +358,8 @@ report_lost_node(struct fw_card *card, card->bm_retries = 0; } -static void -report_found_node(struct fw_card *card, - struct fw_node *node, struct fw_node *parent) +static void report_found_node(struct fw_card *card, + struct fw_node *node, struct fw_node *parent) { int b_path = (node->phy_speed == SCODE_BETA); @@ -415,8 +412,7 @@ static void move_tree(struct fw_node *node0, struct fw_node *node1, int port) * found, lost or updated. Update the nodes in the card topology tree * as we go. */ -static void -update_tree(struct fw_card *card, struct fw_node *root) +static void update_tree(struct fw_card *card, struct fw_node *root) { struct list_head list0, list1; struct fw_node *node0, *node1, *next1; @@ -497,8 +493,8 @@ update_tree(struct fw_card *card, struct fw_node *root) } } -static void -update_topology_map(struct fw_card *card, u32 *self_ids, int self_id_count) +static void update_topology_map(struct fw_card *card, + u32 *self_ids, int self_id_count) { int node_count; @@ -510,10 +506,8 @@ update_topology_map(struct fw_card *card, u32 *self_ids, int self_id_count) fw_compute_block_crc(card->topology_map); } -void -fw_core_handle_bus_reset(struct fw_card *card, - int node_id, int generation, - int self_id_count, u32 * self_ids) +void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation, + int self_id_count, u32 *self_ids) { struct fw_node *local_node; unsigned long flags; diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h index addb9f8ea77..7e930f80beb 100644 --- a/drivers/firewire/fw-topology.h +++ b/drivers/firewire/fw-topology.h @@ -51,26 +51,21 @@ struct fw_node { struct fw_node *ports[0]; }; -static inline struct fw_node * -fw_node_get(struct fw_node *node) +static inline struct fw_node *fw_node_get(struct fw_node *node) { atomic_inc(&node->ref_count); return node; } -static inline void -fw_node_put(struct fw_node *node) +static inline void fw_node_put(struct fw_node *node) { if (atomic_dec_and_test(&node->ref_count)) kfree(node); } -void -fw_destroy_nodes(struct fw_card *card); - -int -fw_compute_block_crc(u32 *block); +void fw_destroy_nodes(struct fw_card *card); +int fw_compute_block_crc(u32 *block); #endif /* __fw_topology_h */ diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index e17ebc42f12..1537737e442 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -64,10 +64,9 @@ #define PHY_CONFIG_ROOT_ID(node_id) ((((node_id) & 0x3f) << 24) | (1 << 23)) #define PHY_IDENTIFIER(id) ((id) << 30) -static int -close_transaction(struct fw_transaction *transaction, - struct fw_card *card, int rcode, - u32 *payload, size_t length) +static int close_transaction(struct fw_transaction *transaction, + struct fw_card *card, int rcode, + u32 *payload, size_t length) { struct fw_transaction *t; unsigned long flags; @@ -94,9 +93,8 @@ close_transaction(struct fw_transaction *transaction, * Only valid for transactions that are potentially pending (ie have * been sent). */ -int -fw_cancel_transaction(struct fw_card *card, - struct fw_transaction *transaction) +int fw_cancel_transaction(struct fw_card *card, + struct fw_transaction *transaction) { /* * Cancel the packet transmission if it's still queued. That @@ -116,9 +114,8 @@ fw_cancel_transaction(struct fw_card *card, } EXPORT_SYMBOL(fw_cancel_transaction); -static void -transmit_complete_callback(struct fw_packet *packet, - struct fw_card *card, int status) +static void transmit_complete_callback(struct fw_packet *packet, + struct fw_card *card, int status) { struct fw_transaction *t = container_of(packet, struct fw_transaction, packet); @@ -151,8 +148,7 @@ transmit_complete_callback(struct fw_packet *packet, } } -static void -fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, +static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, int destination_id, int source_id, int generation, int speed, unsigned long long offset, void *payload, size_t length) { @@ -247,12 +243,10 @@ fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, * @param callback_data pointer to arbitrary data, which will be * passed to the callback */ -void -fw_send_request(struct fw_card *card, struct fw_transaction *t, - int tcode, int destination_id, int generation, int speed, - unsigned long long offset, - void *payload, size_t length, - fw_transaction_callback_t callback, void *callback_data) +void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, + int destination_id, int generation, int speed, + unsigned long long offset, void *payload, size_t length, + fw_transaction_callback_t callback, void *callback_data) { unsigned long flags; int tlabel; @@ -322,8 +316,8 @@ static void transaction_callback(struct fw_card *card, int rcode, * Returns the RCODE. */ int fw_run_transaction(struct fw_card *card, int tcode, int destination_id, - int generation, int speed, unsigned long long offset, - void *data, size_t length) + int generation, int speed, unsigned long long offset, + void *data, size_t length) { struct transaction_callback_data d; struct fw_transaction t; @@ -399,9 +393,8 @@ void fw_flush_transactions(struct fw_card *card) } } -static struct fw_address_handler * -lookup_overlapping_address_handler(struct list_head *list, - unsigned long long offset, size_t length) +static struct fw_address_handler *lookup_overlapping_address_handler( + struct list_head *list, unsigned long long offset, size_t length) { struct fw_address_handler *handler; @@ -414,9 +407,8 @@ lookup_overlapping_address_handler(struct list_head *list, return NULL; } -static struct fw_address_handler * -lookup_enclosing_address_handler(struct list_head *list, - unsigned long long offset, size_t length) +static struct fw_address_handler *lookup_enclosing_address_handler( + struct list_head *list, unsigned long long offset, size_t length) { struct fw_address_handler *handler; @@ -463,9 +455,8 @@ const struct fw_address_region fw_unit_space_region = * The start offset of the handler's address region is determined by * fw_core_add_address_handler() and is returned in handler->offset. */ -int -fw_core_add_address_handler(struct fw_address_handler *handler, - const struct fw_address_region *region) +int fw_core_add_address_handler(struct fw_address_handler *handler, + const struct fw_address_region *region) { struct fw_address_handler *other; unsigned long flags; @@ -522,9 +513,8 @@ struct fw_request { u32 data[0]; }; -static void -free_response_callback(struct fw_packet *packet, - struct fw_card *card, int status) +static void free_response_callback(struct fw_packet *packet, + struct fw_card *card, int status) { struct fw_request *request; @@ -532,9 +522,8 @@ free_response_callback(struct fw_packet *packet, kfree(request); } -void -fw_fill_response(struct fw_packet *response, u32 *request_header, - int rcode, void *payload, size_t length) +void fw_fill_response(struct fw_packet *response, u32 *request_header, + int rcode, void *payload, size_t length) { int tcode, tlabel, extended_tcode, source, destination; @@ -592,8 +581,7 @@ fw_fill_response(struct fw_packet *response, u32 *request_header, } EXPORT_SYMBOL(fw_fill_response); -static struct fw_request * -allocate_request(struct fw_packet *p) +static struct fw_request *allocate_request(struct fw_packet *p) { struct fw_request *request; u32 *data, length; @@ -653,8 +641,8 @@ allocate_request(struct fw_packet *p) return request; } -void -fw_send_response(struct fw_card *card, struct fw_request *request, int rcode) +void fw_send_response(struct fw_card *card, + struct fw_request *request, int rcode) { /* unified transaction or broadcast transaction: don't respond */ if (request->ack != ACK_PENDING || @@ -674,8 +662,7 @@ fw_send_response(struct fw_card *card, struct fw_request *request, int rcode) } EXPORT_SYMBOL(fw_send_response); -void -fw_core_handle_request(struct fw_card *card, struct fw_packet *p) +void fw_core_handle_request(struct fw_card *card, struct fw_packet *p) { struct fw_address_handler *handler; struct fw_request *request; @@ -723,8 +710,7 @@ fw_core_handle_request(struct fw_card *card, struct fw_packet *p) } EXPORT_SYMBOL(fw_core_handle_request); -void -fw_core_handle_response(struct fw_card *card, struct fw_packet *p) +void fw_core_handle_response(struct fw_card *card, struct fw_packet *p) { struct fw_transaction *t; unsigned long flags; @@ -797,12 +783,10 @@ static const struct fw_address_region topology_map_region = { .start = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP, .end = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP_END, }; -static void -handle_topology_map(struct fw_card *card, struct fw_request *request, - int tcode, int destination, int source, - int generation, int speed, - unsigned long long offset, - void *payload, size_t length, void *callback_data) +static void handle_topology_map(struct fw_card *card, struct fw_request *request, + int tcode, int destination, int source, int generation, + int speed, unsigned long long offset, + void *payload, size_t length, void *callback_data) { int i, start, end; __be32 *map; @@ -836,12 +820,10 @@ static const struct fw_address_region registers_region = { .start = CSR_REGISTER_BASE, .end = CSR_REGISTER_BASE | CSR_CONFIG_ROM, }; -static void -handle_registers(struct fw_card *card, struct fw_request *request, - int tcode, int destination, int source, - int generation, int speed, - unsigned long long offset, - void *payload, size_t length, void *callback_data) +static void handle_registers(struct fw_card *card, struct fw_request *request, + int tcode, int destination, int source, int generation, + int speed, unsigned long long offset, + void *payload, size_t length, void *callback_data) { int reg = offset & ~CSR_REGISTER_BASE; unsigned long long bus_time; diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 1d78e9cc594..7112e62942f 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -88,8 +88,7 @@ #define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args) #define fw_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args) -static inline void -fw_memcpy_from_be32(void *_dst, void *_src, size_t size) +static inline void fw_memcpy_from_be32(void *_dst, void *_src, size_t size) { u32 *dst = _dst; __be32 *src = _src; @@ -99,8 +98,7 @@ fw_memcpy_from_be32(void *_dst, void *_src, size_t size) dst[i] = be32_to_cpu(src[i]); } -static inline void -fw_memcpy_to_be32(void *_dst, void *_src, size_t size) +static inline void fw_memcpy_to_be32(void *_dst, void *_src, size_t size) { fw_memcpy_from_be32(_dst, _src, size); } @@ -125,8 +123,7 @@ typedef void (*fw_packet_callback_t)(struct fw_packet *packet, struct fw_card *card, int status); typedef void (*fw_transaction_callback_t)(struct fw_card *card, int rcode, - void *data, - size_t length, + void *data, size_t length, void *callback_data); /* @@ -201,7 +198,6 @@ struct fw_address_handler { struct list_head link; }; - struct fw_address_region { u64 start; u64 end; @@ -315,10 +311,8 @@ struct fw_iso_packet { struct fw_iso_context; typedef void (*fw_iso_callback_t)(struct fw_iso_context *context, - u32 cycle, - size_t header_length, - void *header, - void *data); + u32 cycle, size_t header_length, + void *header, void *data); /* * An iso buffer is just a set of pages mapped for DMA in the @@ -344,36 +338,22 @@ struct fw_iso_context { void *callback_data; }; -int -fw_iso_buffer_init(struct fw_iso_buffer *buffer, - struct fw_card *card, - int page_count, - enum dma_data_direction direction); -int -fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); -void -fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card); - -struct fw_iso_context * -fw_iso_context_create(struct fw_card *card, int type, - int channel, int speed, size_t header_size, - fw_iso_callback_t callback, void *callback_data); - -void -fw_iso_context_destroy(struct fw_iso_context *ctx); - -int -fw_iso_context_queue(struct fw_iso_context *ctx, - struct fw_iso_packet *packet, - struct fw_iso_buffer *buffer, - unsigned long payload); - -int -fw_iso_context_start(struct fw_iso_context *ctx, - int cycle, int sync, int tags); - -int -fw_iso_context_stop(struct fw_iso_context *ctx); +int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card, + int page_count, enum dma_data_direction direction); +int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); +void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card); + +struct fw_iso_context *fw_iso_context_create(struct fw_card *card, + int type, int channel, int speed, size_t header_size, + fw_iso_callback_t callback, void *callback_data); +int fw_iso_context_queue(struct fw_iso_context *ctx, + struct fw_iso_packet *packet, + struct fw_iso_buffer *buffer, + unsigned long payload); +int fw_iso_context_start(struct fw_iso_context *ctx, + int cycle, int sync, int tags); +int fw_iso_context_stop(struct fw_iso_context *ctx); +void fw_iso_context_destroy(struct fw_iso_context *ctx); struct fw_card_driver { /* @@ -429,24 +409,18 @@ struct fw_card_driver { int (*stop_iso)(struct fw_iso_context *ctx); }; -int -fw_core_initiate_bus_reset(struct fw_card *card, int short_reset); +int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset); -void -fw_send_request(struct fw_card *card, struct fw_transaction *t, +void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, int destination_id, int generation, int speed, unsigned long long offset, void *data, size_t length, fw_transaction_callback_t callback, void *callback_data); - -int fw_run_transaction(struct fw_card *card, int tcode, int destination_id, - int generation, int speed, unsigned long long offset, - void *data, size_t length); - int fw_cancel_transaction(struct fw_card *card, struct fw_transaction *transaction); - void fw_flush_transactions(struct fw_card *card); - +int fw_run_transaction(struct fw_card *card, int tcode, int destination_id, + int generation, int speed, unsigned long long offset, + void *data, size_t length); void fw_send_phy_config(struct fw_card *card, int node_id, int generation, int gap_count); @@ -454,29 +428,18 @@ void fw_send_phy_config(struct fw_card *card, * Called by the topology code to inform the device code of node * activity; found, lost, or updated nodes. */ -void -fw_node_event(struct fw_card *card, struct fw_node *node, int event); +void fw_node_event(struct fw_card *card, struct fw_node *node, int event); /* API used by card level drivers */ -void -fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, - struct device *device); -int -fw_card_add(struct fw_card *card, - u32 max_receive, u32 link_speed, u64 guid); - -void -fw_core_remove_card(struct fw_card *card); - -void -fw_core_handle_bus_reset(struct fw_card *card, - int node_id, int generation, - int self_id_count, u32 *self_ids); -void -fw_core_handle_request(struct fw_card *card, struct fw_packet *request); - -void -fw_core_handle_response(struct fw_card *card, struct fw_packet *packet); +void fw_card_initialize(struct fw_card *card, + const struct fw_card_driver *driver, struct device *device); +int fw_card_add(struct fw_card *card, + u32 max_receive, u32 link_speed, u64 guid); +void fw_core_remove_card(struct fw_card *card); +void fw_core_handle_bus_reset(struct fw_card *card, int node_id, + int generation, int self_id_count, u32 *self_ids); +void fw_core_handle_request(struct fw_card *card, struct fw_packet *request); +void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet); #endif /* __fw_transaction_h */ -- GitLab From da62df141e3f879445e3daef36bd3a12c90841e2 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 14 Dec 2008 21:47:36 +0100 Subject: [PATCH 4180/4982] firewire: core: remove unused definitions Signed-off-by: Stefan Richter --- drivers/firewire/fw-transaction.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 7112e62942f..0dd96ecc2dc 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -138,12 +138,6 @@ typedef void (*fw_address_callback_t)(struct fw_card *card, void *data, size_t length, void *callback_data); -typedef void (*fw_bus_reset_callback_t)(struct fw_card *handle, - int node_id, int generation, - u32 *self_ids, - int self_id_count, - void *callback_data); - struct fw_packet { int speed; int generation; @@ -184,12 +178,6 @@ struct fw_transaction { void *callback_data; }; -static inline struct fw_packet * -fw_packet(struct list_head *l) -{ - return list_entry(l, struct fw_packet, link); -} - struct fw_address_handler { u64 offset; size_t length; -- GitLab From a459b8ab9c176143fecef8ace4b70d6dbd7a8113 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 21 Dec 2008 16:49:57 +0100 Subject: [PATCH 4181/4982] firewire: cdev: use list_first_entry Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 3c075b2eedf..ead5c7b06ec 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -180,7 +180,7 @@ static int dequeue_event(struct client *client, return -ENODEV; spin_lock_irqsave(&client->lock, flags); - event = container_of(client->event_list.next, struct event, link); + event = list_first_entry(&client->event_list, struct event, link); list_del(&event->link); spin_unlock_irqrestore(&client->lock, flags); -- GitLab From 4817ed240232e89583b0506c2d8e426739af5da3 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 21 Dec 2008 16:39:46 +0100 Subject: [PATCH 4182/4982] firewire: prevent creation of multiple IR DMA contexts for the same channel OHCI-1394 1.1 clause 10.4.3 says: "If more than one IR DMA context specifies receives for packets from the same isochronous channel, the context destination for that channel's packets is undefined." Any userspace client and in the future also kernelspace clients can allocate IR DMA contexts for any channel. We don't want them to interfere with each other, hence it is preferable to return -EBUSY if allocation of a second context for a channel is attempted. Notes: - This limitation is OHCI-1394 specific, therefore its proper place of implementation is down in the low-level driver. - Since the ABI simply maps one userspace iso client context to one hardware iso context, this OHCI-1394 limitation alas requires userspace to implement its own multiplexing of iso reception from the same channel and card to multiple clients when needed. - The limitation is independent of channel allocation at the IRM; the latter is really only important for the initiation of iso transmission but not of iso reception. - We don't need to do the same for IT DMA because OHCI-1394 does not have any ties between IT contexts and channels. Only the voluntary channel allocation protocol via the IRM, globally to the FireWire bus, can ensure proper isochronous transmit behaviour anyway. Signed-off-by: Stefan Richter --- drivers/firewire/fw-iso.c | 3 ++- drivers/firewire/fw-ohci.c | 14 +++++++++++--- drivers/firewire/fw-transaction.h | 2 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c index 3ff2cfc1bba..39f3bacee40 100644 --- a/drivers/firewire/fw-iso.c +++ b/drivers/firewire/fw-iso.c @@ -110,7 +110,8 @@ struct fw_iso_context *fw_iso_context_create(struct fw_card *card, { struct fw_iso_context *ctx; - ctx = card->driver->allocate_iso_context(card, type, header_size); + ctx = card->driver->allocate_iso_context(card, + type, channel, header_size); if (IS_ERR(ctx)) return ctx; diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 4c7cf15986a..859af71b06a 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -205,6 +205,7 @@ struct fw_ohci { u32 it_context_mask; struct iso_context *it_context_list; + u64 ir_context_channels; u32 ir_context_mask; struct iso_context *ir_context_list; }; @@ -1877,20 +1878,23 @@ static int handle_it_packet(struct context *context, } static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card, - int type, size_t header_size) + int type, int channel, size_t header_size) { struct fw_ohci *ohci = fw_ohci(card); struct iso_context *ctx, *list; descriptor_callback_t callback; + u64 *channels, dont_care = ~0ULL; u32 *mask, regs; unsigned long flags; int index, ret = -ENOMEM; if (type == FW_ISO_CONTEXT_TRANSMIT) { + channels = &dont_care; mask = &ohci->it_context_mask; list = ohci->it_context_list; callback = handle_it_packet; } else { + channels = &ohci->ir_context_channels; mask = &ohci->ir_context_mask; list = ohci->ir_context_list; if (ohci->use_dualbuffer) @@ -1900,9 +1904,11 @@ static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card, } spin_lock_irqsave(&ohci->lock, flags); - index = ffs(*mask) - 1; - if (index >= 0) + index = *channels & 1ULL << channel ? ffs(*mask) - 1 : -1; + if (index >= 0) { + *channels &= ~(1ULL << channel); *mask &= ~(1 << index); + } spin_unlock_irqrestore(&ohci->lock, flags); if (index < 0) @@ -2012,6 +2018,7 @@ static void ohci_free_iso_context(struct fw_iso_context *base) } else { index = ctx - ohci->ir_context_list; ohci->ir_context_mask |= 1 << index; + ohci->ir_context_channels |= 1ULL << base->channel; } spin_unlock_irqrestore(&ohci->lock, flags); @@ -2424,6 +2431,7 @@ static int __devinit pci_probe(struct pci_dev *dev, ohci->it_context_list = kzalloc(size, GFP_KERNEL); reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0); + ohci->ir_context_channels = ~0ULL; ohci->ir_context_mask = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet); reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0); size = sizeof(struct iso_context) * hweight32(ohci->ir_context_mask); diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 0dd96ecc2dc..48e88d53998 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -383,7 +383,7 @@ struct fw_card_driver { struct fw_iso_context * (*allocate_iso_context)(struct fw_card *card, - int type, size_t header_size); + int type, int channel, size_t header_size); void (*free_iso_context)(struct fw_iso_context *ctx); int (*start_iso)(struct fw_iso_context *ctx, -- GitLab From 632321ecd99bf85c982a75f8329b4ecbb95b3a8f Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Fri, 2 Jan 2009 12:47:13 +0100 Subject: [PATCH 4183/4982] firewire: cdev: fix documentation of FW_CDEV_IOC_GET_INFO The FW_CDEV_IOC_GET_INFO ioctl looks at client->device->config_rom, not at the local node's config ROM. We could fix the implementation or the documentation. I believe the way how it is currently implemented is more useful than the way how it is currently documented. In fact, libdc1394 uses the ABI already as implemented, not as documented. Hence let's change the documentation. Signed-off-by: Stefan Richter --- include/linux/firewire-cdev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 899ef279f5b..86c8ff5326f 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -201,7 +201,7 @@ union fw_cdev_event { * case, @rom_length is updated with the actual length of the * configuration ROM. * @rom: If non-zero, address of a buffer to be filled by a copy of the - * local node's configuration ROM + * device's configuration ROM * @bus_reset: If non-zero, address of a buffer to be filled by a * &struct fw_cdev_event_bus_reset with the current state * of the bus. This does not cause a bus reset to happen. -- GitLab From fb4430367b0bbee2420132faf16c7c762a39c0bb Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 4 Jan 2009 16:23:29 +0100 Subject: [PATCH 4184/4982] firewire: cdev: reference-count client instances The lifetime of struct client instances must be longer than the lifetime of any client resource. This fixes a possible race between fw_device_op_release and transaction completions. It also prepares for new ioctls for isochronous resource management which will involve delayed processing of client resources. Signed-off-by: Stefan Richter Reviewed-by: David Moore --- drivers/firewire/fw-cdev.c | 55 +++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index ead5c7b06ec..81362c14ef4 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -94,8 +95,27 @@ struct client { unsigned long vm_start; struct list_head link; + struct kref kref; }; +static inline void client_get(struct client *client) +{ + kref_get(&client->kref); +} + +static void client_release(struct kref *kref) +{ + struct client *client = container_of(kref, struct client, kref); + + fw_device_put(client->device); + kfree(client); +} + +static void client_put(struct client *client) +{ + kref_put(&client->kref, client_release); +} + static inline void __user *u64_to_uptr(__u64 value) { return (void __user *)(unsigned long)value; @@ -131,6 +151,7 @@ static int fw_device_op_open(struct inode *inode, struct file *file) idr_init(&client->resource_idr); INIT_LIST_HEAD(&client->event_list); init_waitqueue_head(&client->wait); + kref_init(&client->kref); file->private_data = client; @@ -326,6 +347,8 @@ static int add_client_resource(struct client *client, else ret = idr_get_new(&client->resource_idr, resource, &resource->handle); + if (ret >= 0) + client_get(client); spin_unlock_irqrestore(&client->lock, flags); if (ret == -EAGAIN) @@ -358,6 +381,8 @@ static int release_client_resource(struct client *client, u32 handle, else r->release(client, r); + client_put(client); + return 0; } @@ -385,11 +410,21 @@ static void complete_transaction(struct fw_card *card, int rcode, spin_lock_irqsave(&client->lock, flags); /* - * If called while in shutdown, the idr tree must be left untouched. - * The idr handle will be removed later. + * 1. If called while in shutdown, the idr tree must be left untouched. + * The idr handle will be removed and the client reference will be + * dropped later. + * 2. If the call chain was release_client_resource -> + * release_transaction -> complete_transaction (instead of a normal + * conclusion of the transaction), i.e. if this resource was already + * unregistered from the idr, the client reference will be dropped + * by release_client_resource and we must not drop it here. */ - if (!client->in_shutdown) + if (!client->in_shutdown && + idr_find(&client->resource_idr, response->resource.handle)) { idr_remove(&client->resource_idr, response->resource.handle); + /* Drop the idr's reference */ + client_put(client); + } spin_unlock_irqrestore(&client->lock, flags); r->type = FW_CDEV_EVENT_RESPONSE; @@ -408,6 +443,9 @@ static void complete_transaction(struct fw_card *card, int rcode, else queue_event(client, &response->event, r, sizeof(*r) + r->length, NULL, 0); + + /* Drop the transaction callback's reference */ + client_put(client); } static int ioctl_send_request(struct client *client, void *buffer) @@ -459,6 +497,9 @@ static int ioctl_send_request(struct client *client, void *buffer) if (ret < 0) goto failed; + /* Get a reference for the transaction callback */ + client_get(client); + fw_send_request(device->card, &response->transaction, request->tcode & 0x1f, device->node->node_id, @@ -1044,6 +1085,7 @@ static int shutdown_resource(int id, void *p, void *data) struct client *client = data; r->release(client, r); + client_put(client); return 0; } @@ -1076,12 +1118,7 @@ static int fw_device_op_release(struct inode *inode, struct file *file) list_for_each_entry_safe(e, next_e, &client->event_list, link) kfree(e); - /* - * FIXME: client should be reference-counted. It's extremely unlikely - * but there may still be transactions being completed at this point. - */ - fw_device_put(client->device); - kfree(client); + client_put(client); return 0; } -- GitLab From 97c18b7fd6df4ae0d32509f292a2eb0d4b26d623 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 4 Jan 2009 16:23:29 +0100 Subject: [PATCH 4185/4982] firewire: cdev: unify names of struct types and of their instances to indicate that they are specializations of struct event or of struct client_resource, respectively. struct response was both an event and a client_resource; it is now split into struct outbound_transaction_resource and ~_event in order to document more explicitly which types of client resources exist. struct request and struct_request_event are renamed to struct inbound_transaction_resource and ~_event because requests and responses occur in outbound and in inbound transactions. Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 337 +++++++++++++++++++------------------ 1 file changed, 169 insertions(+), 168 deletions(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 81362c14ef4..85e866e28a2 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -41,43 +41,6 @@ #include "fw-topology.h" #include "fw-device.h" -struct client; -struct client_resource; -typedef void (*client_resource_release_fn_t)(struct client *, - struct client_resource *); -struct client_resource { - client_resource_release_fn_t release; - int handle; -}; - -/* - * dequeue_event() just kfree()'s the event, so the event has to be - * the first field in the struct. - */ - -struct event { - struct { void *data; size_t size; } v[2]; - struct list_head link; -}; - -struct bus_reset { - struct event event; - struct fw_cdev_event_bus_reset reset; -}; - -struct response { - struct event event; - struct fw_transaction transaction; - struct client *client; - struct client_resource resource; - struct fw_cdev_event_response response; -}; - -struct iso_interrupt { - struct event event; - struct fw_cdev_event_iso_interrupt interrupt; -}; - struct client { u32 version; struct fw_device *device; @@ -116,6 +79,70 @@ static void client_put(struct client *client) kref_put(&client->kref, client_release); } +struct client_resource; +typedef void (*client_resource_release_fn_t)(struct client *, + struct client_resource *); +struct client_resource { + client_resource_release_fn_t release; + int handle; +}; + +struct address_handler_resource { + struct client_resource resource; + struct fw_address_handler handler; + __u64 closure; + struct client *client; +}; + +struct outbound_transaction_resource { + struct client_resource resource; + struct fw_transaction transaction; +}; + +struct inbound_transaction_resource { + struct client_resource resource; + struct fw_request *request; + void *data; + size_t length; +}; + +struct descriptor_resource { + struct client_resource resource; + struct fw_descriptor descriptor; + u32 data[0]; +}; + +/* + * dequeue_event() just kfree()'s the event, so the event has to be + * the first field in a struct XYZ_event. + */ +struct event { + struct { void *data; size_t size; } v[2]; + struct list_head link; +}; + +struct bus_reset_event { + struct event event; + struct fw_cdev_event_bus_reset reset; +}; + +struct outbound_transaction_event { + struct event event; + struct client *client; + struct outbound_transaction_resource r; + struct fw_cdev_event_response response; +}; + +struct inbound_transaction_event { + struct event event; + struct fw_cdev_event_request request; +}; + +struct iso_interrupt_event { + struct event event; + struct fw_cdev_event_iso_interrupt interrupt; +}; + static inline void __user *u64_to_uptr(__u64 value) { return (void __user *)(unsigned long)value; @@ -263,18 +290,18 @@ static void for_each_client(struct fw_device *device, static void queue_bus_reset_event(struct client *client) { - struct bus_reset *bus_reset; + struct bus_reset_event *e; - bus_reset = kzalloc(sizeof(*bus_reset), GFP_KERNEL); - if (bus_reset == NULL) { + e = kzalloc(sizeof(*e), GFP_KERNEL); + if (e == NULL) { fw_notify("Out of memory when allocating bus reset event\n"); return; } - fill_bus_reset_event(&bus_reset->reset, client); + fill_bus_reset_event(&e->reset, client); - queue_event(client, &bus_reset->event, - &bus_reset->reset, sizeof(bus_reset->reset), NULL, 0); + queue_event(client, &e->event, + &e->reset, sizeof(e->reset), NULL, 0); } void fw_device_cdev_update(struct fw_device *device) @@ -389,24 +416,24 @@ static int release_client_resource(struct client *client, u32 handle, static void release_transaction(struct client *client, struct client_resource *resource) { - struct response *response = - container_of(resource, struct response, resource); + struct outbound_transaction_resource *r = container_of(resource, + struct outbound_transaction_resource, resource); - fw_cancel_transaction(client->device->card, &response->transaction); + fw_cancel_transaction(client->device->card, &r->transaction); } static void complete_transaction(struct fw_card *card, int rcode, void *payload, size_t length, void *data) { - struct response *response = data; - struct client *client = response->client; + struct outbound_transaction_event *e = data; + struct fw_cdev_event_response *rsp = &e->response; + struct client *client = e->client; unsigned long flags; - struct fw_cdev_event_response *r = &response->response; - if (length < r->length) - r->length = length; + if (length < rsp->length) + rsp->length = length; if (rcode == RCODE_COMPLETE) - memcpy(r->data, payload, r->length); + memcpy(rsp->data, payload, rsp->length); spin_lock_irqsave(&client->lock, flags); /* @@ -420,28 +447,28 @@ static void complete_transaction(struct fw_card *card, int rcode, * by release_client_resource and we must not drop it here. */ if (!client->in_shutdown && - idr_find(&client->resource_idr, response->resource.handle)) { - idr_remove(&client->resource_idr, response->resource.handle); + idr_find(&client->resource_idr, e->r.resource.handle)) { + idr_remove(&client->resource_idr, e->r.resource.handle); /* Drop the idr's reference */ client_put(client); } spin_unlock_irqrestore(&client->lock, flags); - r->type = FW_CDEV_EVENT_RESPONSE; - r->rcode = rcode; + rsp->type = FW_CDEV_EVENT_RESPONSE; + rsp->rcode = rcode; /* - * In the case that sizeof(*r) doesn't align with the position of the + * In the case that sizeof(*rsp) doesn't align with the position of the * data, and the read is short, preserve an extra copy of the data * to stay compatible with a pre-2.6.27 bug. Since the bug is harmless * for short reads and some apps depended on it, this is both safe * and prudent for compatibility. */ - if (r->length <= sizeof(*r) - offsetof(typeof(*r), data)) - queue_event(client, &response->event, r, sizeof(*r), - r->data, r->length); + if (rsp->length <= sizeof(*rsp) - offsetof(typeof(*rsp), data)) + queue_event(client, &e->event, rsp, sizeof(*rsp), + rsp->data, rsp->length); else - queue_event(client, &response->event, r, sizeof(*r) + r->length, + queue_event(client, &e->event, rsp, sizeof(*rsp) + rsp->length, NULL, 0); /* Drop the transaction callback's reference */ @@ -452,23 +479,23 @@ static int ioctl_send_request(struct client *client, void *buffer) { struct fw_device *device = client->device; struct fw_cdev_send_request *request = buffer; - struct response *response; + struct outbound_transaction_event *e; int ret; /* What is the biggest size we'll accept, really? */ if (request->length > 4096) return -EINVAL; - response = kmalloc(sizeof(*response) + request->length, GFP_KERNEL); - if (response == NULL) + e = kmalloc(sizeof(*e) + request->length, GFP_KERNEL); + if (e == NULL) return -ENOMEM; - response->client = client; - response->response.length = request->length; - response->response.closure = request->closure; + e->client = client; + e->response.length = request->length; + e->response.closure = request->closure; if (request->data && - copy_from_user(response->response.data, + copy_from_user(e->response.data, u64_to_uptr(request->data), request->length)) { ret = -EFAULT; goto failed; @@ -492,86 +519,66 @@ static int ioctl_send_request(struct client *client, void *buffer) goto failed; } - response->resource.release = release_transaction; - ret = add_client_resource(client, &response->resource, GFP_KERNEL); + e->r.resource.release = release_transaction; + ret = add_client_resource(client, &e->r.resource, GFP_KERNEL); if (ret < 0) goto failed; /* Get a reference for the transaction callback */ client_get(client); - fw_send_request(device->card, &response->transaction, + fw_send_request(device->card, &e->r.transaction, request->tcode & 0x1f, device->node->node_id, request->generation, device->max_speed, request->offset, - response->response.data, request->length, - complete_transaction, response); + e->response.data, request->length, + complete_transaction, e); if (request->data) return sizeof(request) + request->length; else return sizeof(request); failed: - kfree(response); + kfree(e); return ret; } -struct address_handler { - struct fw_address_handler handler; - __u64 closure; - struct client *client; - struct client_resource resource; -}; - -struct request { - struct fw_request *request; - void *data; - size_t length; - struct client_resource resource; -}; - -struct request_event { - struct event event; - struct fw_cdev_event_request request; -}; - static void release_request(struct client *client, struct client_resource *resource) { - struct request *request = - container_of(resource, struct request, resource); + struct inbound_transaction_resource *r = container_of(resource, + struct inbound_transaction_resource, resource); - fw_send_response(client->device->card, request->request, + fw_send_response(client->device->card, r->request, RCODE_CONFLICT_ERROR); - kfree(request); + kfree(r); } -static void handle_request(struct fw_card *card, struct fw_request *r, +static void handle_request(struct fw_card *card, struct fw_request *request, int tcode, int destination, int source, int generation, int speed, unsigned long long offset, void *payload, size_t length, void *callback_data) { - struct address_handler *handler = callback_data; - struct request *request; - struct request_event *e; - struct client *client = handler->client; + struct address_handler_resource *handler = callback_data; + struct inbound_transaction_resource *r; + struct inbound_transaction_event *e; int ret; - request = kmalloc(sizeof(*request), GFP_ATOMIC); + r = kmalloc(sizeof(*r), GFP_ATOMIC); e = kmalloc(sizeof(*e), GFP_ATOMIC); - if (request == NULL || e == NULL) + if (r == NULL || e == NULL) goto failed; - request->request = r; - request->data = payload; - request->length = length; + r->request = request; + r->data = payload; + r->length = length; - request->resource.release = release_request; - ret = add_client_resource(client, &request->resource, GFP_ATOMIC); + r->resource.release = release_request; + ret = add_client_resource(handler->client, &r->resource, GFP_ATOMIC); if (ret < 0) goto failed; @@ -579,61 +586,61 @@ static void handle_request(struct fw_card *card, struct fw_request *r, e->request.tcode = tcode; e->request.offset = offset; e->request.length = length; - e->request.handle = request->resource.handle; + e->request.handle = r->resource.handle; e->request.closure = handler->closure; - queue_event(client, &e->event, + queue_event(handler->client, &e->event, &e->request, sizeof(e->request), payload, length); return; failed: - kfree(request); + kfree(r); kfree(e); - fw_send_response(card, r, RCODE_CONFLICT_ERROR); + fw_send_response(card, request, RCODE_CONFLICT_ERROR); } static void release_address_handler(struct client *client, struct client_resource *resource) { - struct address_handler *handler = - container_of(resource, struct address_handler, resource); + struct address_handler_resource *r = + container_of(resource, struct address_handler_resource, resource); - fw_core_remove_address_handler(&handler->handler); - kfree(handler); + fw_core_remove_address_handler(&r->handler); + kfree(r); } static int ioctl_allocate(struct client *client, void *buffer) { struct fw_cdev_allocate *request = buffer; - struct address_handler *handler; + struct address_handler_resource *r; struct fw_address_region region; int ret; - handler = kmalloc(sizeof(*handler), GFP_KERNEL); - if (handler == NULL) + r = kmalloc(sizeof(*r), GFP_KERNEL); + if (r == NULL) return -ENOMEM; region.start = request->offset; region.end = request->offset + request->length; - handler->handler.length = request->length; - handler->handler.address_callback = handle_request; - handler->handler.callback_data = handler; - handler->closure = request->closure; - handler->client = client; + r->handler.length = request->length; + r->handler.address_callback = handle_request; + r->handler.callback_data = r; + r->closure = request->closure; + r->client = client; - ret = fw_core_add_address_handler(&handler->handler, ®ion); + ret = fw_core_add_address_handler(&r->handler, ®ion); if (ret < 0) { - kfree(handler); + kfree(r); return ret; } - handler->resource.release = release_address_handler; - ret = add_client_resource(client, &handler->resource, GFP_KERNEL); + r->resource.release = release_address_handler; + ret = add_client_resource(client, &r->resource, GFP_KERNEL); if (ret < 0) { - release_address_handler(client, &handler->resource); + release_address_handler(client, &r->resource); return ret; } - request->handle = handler->resource.handle; + request->handle = r->resource.handle; return 0; } @@ -650,13 +657,14 @@ static int ioctl_send_response(struct client *client, void *buffer) { struct fw_cdev_send_response *request = buffer; struct client_resource *resource; - struct request *r; + struct inbound_transaction_resource *r; if (release_client_resource(client, request->handle, release_request, &resource) < 0) return -EINVAL; - r = container_of(resource, struct request, resource); + r = container_of(resource, struct inbound_transaction_resource, + resource); if (request->length < r->length) r->length = request->length; if (copy_from_user(r->data, u64_to_uptr(request->data), r->length)) @@ -678,62 +686,55 @@ static int ioctl_initiate_bus_reset(struct client *client, void *buffer) return fw_core_initiate_bus_reset(client->device->card, short_reset); } -struct descriptor { - struct fw_descriptor d; - struct client_resource resource; - u32 data[0]; -}; - static void release_descriptor(struct client *client, struct client_resource *resource) { - struct descriptor *descriptor = - container_of(resource, struct descriptor, resource); + struct descriptor_resource *r = + container_of(resource, struct descriptor_resource, resource); - fw_core_remove_descriptor(&descriptor->d); - kfree(descriptor); + fw_core_remove_descriptor(&r->descriptor); + kfree(r); } static int ioctl_add_descriptor(struct client *client, void *buffer) { struct fw_cdev_add_descriptor *request = buffer; - struct descriptor *descriptor; + struct descriptor_resource *r; int ret; if (request->length > 256) return -EINVAL; - descriptor = - kmalloc(sizeof(*descriptor) + request->length * 4, GFP_KERNEL); - if (descriptor == NULL) + r = kmalloc(sizeof(*r) + request->length * 4, GFP_KERNEL); + if (r == NULL) return -ENOMEM; - if (copy_from_user(descriptor->data, + if (copy_from_user(r->data, u64_to_uptr(request->data), request->length * 4)) { ret = -EFAULT; goto failed; } - descriptor->d.length = request->length; - descriptor->d.immediate = request->immediate; - descriptor->d.key = request->key; - descriptor->d.data = descriptor->data; + r->descriptor.length = request->length; + r->descriptor.immediate = request->immediate; + r->descriptor.key = request->key; + r->descriptor.data = r->data; - ret = fw_core_add_descriptor(&descriptor->d); + ret = fw_core_add_descriptor(&r->descriptor); if (ret < 0) goto failed; - descriptor->resource.release = release_descriptor; - ret = add_client_resource(client, &descriptor->resource, GFP_KERNEL); + r->resource.release = release_descriptor; + ret = add_client_resource(client, &r->resource, GFP_KERNEL); if (ret < 0) { - fw_core_remove_descriptor(&descriptor->d); + fw_core_remove_descriptor(&r->descriptor); goto failed; } - request->handle = descriptor->resource.handle; + request->handle = r->resource.handle; return 0; failed: - kfree(descriptor); + kfree(r); return ret; } @@ -750,19 +751,19 @@ static void iso_callback(struct fw_iso_context *context, u32 cycle, size_t header_length, void *header, void *data) { struct client *client = data; - struct iso_interrupt *irq; + struct iso_interrupt_event *e; - irq = kzalloc(sizeof(*irq) + header_length, GFP_ATOMIC); - if (irq == NULL) + e = kzalloc(sizeof(*e) + header_length, GFP_ATOMIC); + if (e == NULL) return; - irq->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT; - irq->interrupt.closure = client->iso_closure; - irq->interrupt.cycle = cycle; - irq->interrupt.header_length = header_length; - memcpy(irq->interrupt.header, header, header_length); - queue_event(client, &irq->event, &irq->interrupt, - sizeof(irq->interrupt) + header_length, NULL, 0); + e->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT; + e->interrupt.closure = client->iso_closure; + e->interrupt.cycle = cycle; + e->interrupt.header_length = header_length; + memcpy(e->interrupt.header, header, header_length); + queue_event(client, &e->event, &e->interrupt, + sizeof(e->interrupt) + header_length, NULL, 0); } static int ioctl_create_iso_context(struct client *client, void *buffer) -- GitLab From be5bbd6756b44602a3f281af05c2f416fa9bd1c6 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 4 Jan 2009 16:23:29 +0100 Subject: [PATCH 4186/4982] firewire: cdev: sort includes Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 85e866e28a2..4c33b51b735 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -18,28 +18,30 @@ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include +#include +#include #include #include #include -#include #include -#include -#include -#include -#include -#include +#include +#include +#include + #include #include -#include "fw-transaction.h" -#include "fw-topology.h" + #include "fw-device.h" +#include "fw-topology.h" +#include "fw-transaction.h" struct client { u32 version; -- GitLab From b769bd17656f991c5588c676376e5ec77d25997a Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 4 Jan 2009 16:23:29 +0100 Subject: [PATCH 4187/4982] firewire: core: topology header fix Signed-off-by: Stefan Richter --- drivers/firewire/fw-topology.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h index 7e930f80beb..3c497bb4fae 100644 --- a/drivers/firewire/fw-topology.h +++ b/drivers/firewire/fw-topology.h @@ -19,6 +19,11 @@ #ifndef __fw_topology_h #define __fw_topology_h +#include +#include + +#include + enum { FW_NODE_CREATED, FW_NODE_UPDATED, @@ -64,6 +69,7 @@ static inline void fw_node_put(struct fw_node *node) kfree(node); } +struct fw_card; void fw_destroy_nodes(struct fw_card *card); int fw_compute_block_crc(u32 *block); -- GitLab From b1bda4cdc2037447bd66753bf5ccab66d91b0b59 Mon Sep 17 00:00:00 2001 From: "Jay Fenlason, Stefan Richter" Date: Sun, 4 Jan 2009 16:23:29 +0100 Subject: [PATCH 4188/4982] firewire: cdev: add ioctls for isochronous resource management Based on Date: Tue, 18 Nov 2008 11:41:27 -0500 From: Jay Fenlason Subject: [Patch V4] Add ISO resource management support with several changes to the ABI and implementation. Only the part of the ABI which enables auto-reallocation and auto-deallocation is included here. This implements ioctls for kernel-assisted allocation of isochronous channels and isochronous bandwidth. The benefits are: - The client does not have to have write access to the /dev/fw* device corresponding to the IRM. - The client does not have to perform reallocation after bus resets. - Channel and bandwidth are deallocated by the kernel if the file is closed before the client deallocated the resources. Thus resources are released even if the client crashes. It is anticipated that future in-kernel code (firewire-core IRM code; the firewire port of firedtv), will use the fw-iso.c portions of this code too. Signed-off-by: Stefan Richter Tested-by: David Moore --- drivers/firewire/fw-cdev.c | 215 +++++++++++++++++++++++++++++- drivers/firewire/fw-iso.c | 176 +++++++++++++++++++++++- drivers/firewire/fw-transaction.h | 4 + include/linux/firewire-cdev.h | 100 ++++++++++++-- 4 files changed, 475 insertions(+), 20 deletions(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 4c33b51b735..a227853aa1e 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,7 @@ #include #include #include +#include #include #include @@ -114,6 +116,21 @@ struct descriptor_resource { u32 data[0]; }; +struct iso_resource { + struct client_resource resource; + struct client *client; + /* Schedule work and access todo only with client->lock held. */ + struct delayed_work work; + enum {ISO_RES_ALLOC, ISO_RES_REALLOC, ISO_RES_DEALLOC,} todo; + int generation; + u64 channels; + s32 bandwidth; + struct iso_resource_event *e_alloc, *e_dealloc; +}; + +static void schedule_iso_resource(struct iso_resource *); +static void release_iso_resource(struct client *, struct client_resource *); + /* * dequeue_event() just kfree()'s the event, so the event has to be * the first field in a struct XYZ_event. @@ -145,6 +162,11 @@ struct iso_interrupt_event { struct fw_cdev_event_iso_interrupt interrupt; }; +struct iso_resource_event { + struct event event; + struct fw_cdev_event_iso_resource resource; +}; + static inline void __user *u64_to_uptr(__u64 value) { return (void __user *)(unsigned long)value; @@ -290,6 +312,16 @@ static void for_each_client(struct fw_device *device, mutex_unlock(&device->client_list_mutex); } +static int schedule_reallocations(int id, void *p, void *data) +{ + struct client_resource *r = p; + + if (r->release == release_iso_resource) + schedule_iso_resource(container_of(r, + struct iso_resource, resource)); + return 0; +} + static void queue_bus_reset_event(struct client *client) { struct bus_reset_event *e; @@ -304,6 +336,10 @@ static void queue_bus_reset_event(struct client *client) queue_event(client, &e->event, &e->reset, sizeof(e->reset), NULL, 0); + + spin_lock_irq(&client->lock); + idr_for_each(&client->resource_idr, schedule_reallocations, client); + spin_unlock_irq(&client->lock); } void fw_device_cdev_update(struct fw_device *device) @@ -376,8 +412,12 @@ static int add_client_resource(struct client *client, else ret = idr_get_new(&client->resource_idr, resource, &resource->handle); - if (ret >= 0) + if (ret >= 0) { client_get(client); + if (resource->release == release_iso_resource) + schedule_iso_resource(container_of(resource, + struct iso_resource, resource)); + } spin_unlock_irqrestore(&client->lock, flags); if (ret == -EAGAIN) @@ -970,6 +1010,177 @@ static int ioctl_get_cycle_timer(struct client *client, void *buffer) return 0; } +static void iso_resource_work(struct work_struct *work) +{ + struct iso_resource_event *e; + struct iso_resource *r = + container_of(work, struct iso_resource, work.work); + struct client *client = r->client; + int generation, channel, bandwidth, todo; + bool skip, free, success; + + spin_lock_irq(&client->lock); + generation = client->device->generation; + todo = r->todo; + /* Allow 1000ms grace period for other reallocations. */ + if (todo == ISO_RES_ALLOC && + time_is_after_jiffies(client->device->card->reset_jiffies + HZ)) { + if (schedule_delayed_work(&r->work, DIV_ROUND_UP(HZ, 3))) + client_get(client); + skip = true; + } else { + /* We could be called twice within the same generation. */ + skip = todo == ISO_RES_REALLOC && + r->generation == generation; + } + free = todo == ISO_RES_DEALLOC; + r->generation = generation; + spin_unlock_irq(&client->lock); + + if (skip) + goto out; + + bandwidth = r->bandwidth; + + fw_iso_resource_manage(client->device->card, generation, + r->channels, &channel, &bandwidth, + todo == ISO_RES_ALLOC || todo == ISO_RES_REALLOC); + /* + * Is this generation outdated already? As long as this resource sticks + * in the idr, it will be scheduled again for a newer generation or at + * shutdown. + */ + if (channel == -EAGAIN && + (todo == ISO_RES_ALLOC || todo == ISO_RES_REALLOC)) + goto out; + + success = channel >= 0 || bandwidth > 0; + + spin_lock_irq(&client->lock); + /* + * Transit from allocation to reallocation, except if the client + * requested deallocation in the meantime. + */ + if (r->todo == ISO_RES_ALLOC) + r->todo = ISO_RES_REALLOC; + /* + * Allocation or reallocation failure? Pull this resource out of the + * idr and prepare for deletion, unless the client is shutting down. + */ + if (r->todo == ISO_RES_REALLOC && !success && + !client->in_shutdown && + idr_find(&client->resource_idr, r->resource.handle)) { + idr_remove(&client->resource_idr, r->resource.handle); + client_put(client); + free = true; + } + spin_unlock_irq(&client->lock); + + if (todo == ISO_RES_ALLOC && channel >= 0) + r->channels = 1ULL << (63 - channel); + + if (todo == ISO_RES_REALLOC && success) + goto out; + + if (todo == ISO_RES_ALLOC) { + e = r->e_alloc; + r->e_alloc = NULL; + } else { + e = r->e_dealloc; + r->e_dealloc = NULL; + } + e->resource.handle = r->resource.handle; + e->resource.channel = channel; + e->resource.bandwidth = bandwidth; + + queue_event(client, &e->event, + &e->resource, sizeof(e->resource), NULL, 0); + + if (free) { + cancel_delayed_work(&r->work); + kfree(r->e_alloc); + kfree(r->e_dealloc); + kfree(r); + } + out: + client_put(client); +} + +static void schedule_iso_resource(struct iso_resource *r) +{ + if (schedule_delayed_work(&r->work, 0)) + client_get(r->client); +} + +static void release_iso_resource(struct client *client, + struct client_resource *resource) +{ + struct iso_resource *r = + container_of(resource, struct iso_resource, resource); + + spin_lock_irq(&client->lock); + r->todo = ISO_RES_DEALLOC; + schedule_iso_resource(r); + spin_unlock_irq(&client->lock); +} + +static int ioctl_allocate_iso_resource(struct client *client, void *buffer) +{ + struct fw_cdev_allocate_iso_resource *request = buffer; + struct iso_resource_event *e1, *e2; + struct iso_resource *r; + int ret; + + if ((request->channels == 0 && request->bandwidth == 0) || + request->bandwidth > BANDWIDTH_AVAILABLE_INITIAL || + request->bandwidth < 0) + return -EINVAL; + + r = kmalloc(sizeof(*r), GFP_KERNEL); + e1 = kmalloc(sizeof(*e1), GFP_KERNEL); + e2 = kmalloc(sizeof(*e2), GFP_KERNEL); + if (r == NULL || e1 == NULL || e2 == NULL) { + ret = -ENOMEM; + goto fail; + } + + INIT_DELAYED_WORK(&r->work, iso_resource_work); + r->client = client; + r->todo = ISO_RES_ALLOC; + r->generation = -1; + r->channels = request->channels; + r->bandwidth = request->bandwidth; + r->e_alloc = e1; + r->e_dealloc = e2; + + e1->resource.closure = request->closure; + e1->resource.type = FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED; + e2->resource.closure = request->closure; + e2->resource.type = FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED; + + r->resource.release = release_iso_resource; + ret = add_client_resource(client, &r->resource, GFP_KERNEL); + if (ret < 0) + goto fail; + request->handle = r->resource.handle; + + return 0; + fail: + kfree(r); + kfree(e1); + kfree(e2); + + return ret; +} + +static int ioctl_deallocate_iso_resource(struct client *client, void *buffer) +{ + struct fw_cdev_deallocate *request = buffer; + + return release_client_resource(client, request->handle, + release_iso_resource, NULL); +} + static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { ioctl_get_info, ioctl_send_request, @@ -984,6 +1195,8 @@ static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { ioctl_start_iso, ioctl_stop_iso, ioctl_get_cycle_timer, + ioctl_allocate_iso_resource, + ioctl_deallocate_iso_resource, }; static int dispatch_ioctl(struct client *client, diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c index 39f3bacee40..a7b57b253b0 100644 --- a/drivers/firewire/fw-iso.c +++ b/drivers/firewire/fw-iso.c @@ -1,5 +1,7 @@ /* - * Isochronous IO functionality + * Isochronous I/O functionality: + * - Isochronous DMA context management + * - Isochronous bus resource management (channels, bandwidth), client side * * Copyright (C) 2006 Kristian Hoegsberg * @@ -18,15 +20,20 @@ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include -#include #include -#include +#include +#include +#include #include +#include +#include -#include "fw-transaction.h" #include "fw-topology.h" -#include "fw-device.h" +#include "fw-transaction.h" + +/* + * Isochronous DMA context management + */ int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card, int page_count, enum dma_data_direction direction) @@ -153,3 +160,160 @@ int fw_iso_context_stop(struct fw_iso_context *ctx) { return ctx->card->driver->stop_iso(ctx); } + +/* + * Isochronous bus resource management (channels, bandwidth), client side + */ + +static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, + int bandwidth, bool allocate) +{ + __be32 data[2]; + int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0; + + /* + * On a 1394a IRM with low contention, try < 1 is enough. + * On a 1394-1995 IRM, we need at least try < 2. + * Let's just do try < 5. + */ + for (try = 0; try < 5; try++) { + new = allocate ? old - bandwidth : old + bandwidth; + if (new < 0 || new > BANDWIDTH_AVAILABLE_INITIAL) + break; + + data[0] = cpu_to_be32(old); + data[1] = cpu_to_be32(new); + switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, + irm_id, generation, SCODE_100, + CSR_REGISTER_BASE + CSR_BANDWIDTH_AVAILABLE, + data, sizeof(data))) { + case RCODE_GENERATION: + /* A generation change frees all bandwidth. */ + return allocate ? -EAGAIN : bandwidth; + + case RCODE_COMPLETE: + if (be32_to_cpup(data) == old) + return bandwidth; + + old = be32_to_cpup(data); + /* Fall through. */ + } + } + + return -EIO; +} + +static int manage_channel(struct fw_card *card, int irm_id, int generation, + __be32 channels_mask, u64 offset, bool allocate) +{ + __be32 data[2], c, old = allocate ? cpu_to_be32(~0) : 0; + int i, retry = 5; + + for (i = 0; i < 32; i++) { + c = cpu_to_be32(1 << (31 - i)); + if (!(channels_mask & c)) + continue; + + if (allocate == !(old & c)) + continue; + + data[0] = old; + data[1] = old ^ c; + switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, + irm_id, generation, SCODE_100, + offset, data, sizeof(data))) { + case RCODE_GENERATION: + /* A generation change frees all channels. */ + return allocate ? -EAGAIN : i; + + case RCODE_COMPLETE: + if (data[0] == old) + return i; + + old = data[0]; + + /* Is the IRM 1394a-2000 compliant? */ + if ((data[0] & c) != (data[1] & c)) + continue; + + /* 1394-1995 IRM, fall through to retry. */ + default: + if (retry--) + i--; + } + } + + return -EIO; +} + +static void deallocate_channel(struct fw_card *card, int irm_id, + int generation, int channel) +{ + __be32 mask; + u64 offset; + + mask = channel < 32 ? cpu_to_be32(1 << (31 - channel)) : + cpu_to_be32(1 << (63 - channel)); + offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI : + CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO; + + manage_channel(card, irm_id, generation, mask, offset, false); +} + +/** + * fw_iso_resource_manage - Allocate or deallocate a channel and/or bandwidth + * + * In parameters: card, generation, channels_mask, bandwidth, allocate + * Out parameters: channel, bandwidth + * This function blocks (sleeps) during communication with the IRM. + * Allocates or deallocates at most one channel out of channels_mask. + * + * Returns channel < 0 if no channel was allocated or deallocated. + * Returns bandwidth = 0 if no bandwidth was allocated or deallocated. + * + * If generation is stale, deallocations succeed but allocations fail with + * channel = -EAGAIN. + * + * If channel (de)allocation fails, bandwidth (de)allocation fails too. + * If bandwidth allocation fails, no channel will be allocated either. + * If bandwidth deallocation fails, channel deallocation may still have been + * successful. + */ +void fw_iso_resource_manage(struct fw_card *card, int generation, + u64 channels_mask, int *channel, int *bandwidth, + bool allocate) +{ + __be32 channels_hi = cpu_to_be32(channels_mask >> 32); + __be32 channels_lo = cpu_to_be32(channels_mask); + int irm_id, ret, c = -EINVAL; + + spin_lock_irq(&card->lock); + irm_id = card->irm_node->node_id; + spin_unlock_irq(&card->lock); + + if (channels_hi) + c = manage_channel(card, irm_id, generation, channels_hi, + CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, allocate); + if (channels_lo && c < 0) { + c = manage_channel(card, irm_id, generation, channels_lo, + CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, allocate); + if (c >= 0) + c += 32; + } + *channel = c; + + if (channels_mask != 0 && c < 0) + *bandwidth = 0; + + if (*bandwidth == 0) + return; + + ret = manage_bandwidth(card, irm_id, generation, *bandwidth, allocate); + if (ret < 0) + *bandwidth = 0; + + if (ret < 0 && c >= 0 && allocate) { + deallocate_channel(card, irm_id, generation, c); + *channel = ret; + } +} diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 48e88d53998..212a1029382 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -82,6 +82,7 @@ #define CSR_SPEED_MAP 0x2000 #define CSR_SPEED_MAP_END 0x3000 +#define BANDWIDTH_AVAILABLE_INITIAL 4915 #define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31) #define BROADCAST_CHANNEL_VALID (1 << 30) @@ -343,6 +344,9 @@ int fw_iso_context_start(struct fw_iso_context *ctx, int fw_iso_context_stop(struct fw_iso_context *ctx); void fw_iso_context_destroy(struct fw_iso_context *ctx); +void fw_iso_resource_manage(struct fw_card *card, int generation, + u64 channels_mask, int *channel, int *bandwidth, bool allocate); + struct fw_card_driver { /* * Enable the given card with the given initial config rom. diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 86c8ff5326f..25b96dd0574 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -25,10 +25,12 @@ #include #include -#define FW_CDEV_EVENT_BUS_RESET 0x00 -#define FW_CDEV_EVENT_RESPONSE 0x01 -#define FW_CDEV_EVENT_REQUEST 0x02 -#define FW_CDEV_EVENT_ISO_INTERRUPT 0x03 +#define FW_CDEV_EVENT_BUS_RESET 0x00 +#define FW_CDEV_EVENT_RESPONSE 0x01 +#define FW_CDEV_EVENT_REQUEST 0x02 +#define FW_CDEV_EVENT_ISO_INTERRUPT 0x03 +#define FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED 0x04 +#define FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED 0x05 /** * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types @@ -146,6 +148,37 @@ struct fw_cdev_event_iso_interrupt { __u32 header[0]; }; +/** + * struct fw_cdev_event_iso_resource - Iso resources were allocated or freed + * @closure: See &fw_cdev_event_common; + * set by %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE ioctl + * @type: %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or + * %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED + * @handle: Reference by which an allocated resource can be deallocated + * @channel: Isochronous channel which was (de)allocated, if any + * @bandwidth: Bandwidth allocation units which were (de)allocated, if any + * @channels_available: Last known availability of channels + * @bandwidth_available: Last known availability of bandwidth + * + * An %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED event is sent after an isochronous + * resource was allocated at the IRM. The client has to check @channel and + * @bandwidth for whether the allocation actually succeeded. + * + * @channel is <0 if no channel was allocated. + * @bandwidth is 0 if no bandwidth was allocated. + * + * An %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED event is sent after an isochronous + * resource was deallocated at the IRM. It is also sent when automatic + * reallocation after a bus reset failed. + */ +struct fw_cdev_event_iso_resource { + __u64 closure; + __u32 type; + __u32 handle; + __s32 channel; + __s32 bandwidth; +}; + /** * union fw_cdev_event - Convenience union of fw_cdev_event_ types * @common: Valid for all types @@ -153,6 +186,9 @@ struct fw_cdev_event_iso_interrupt { * @response: Valid if @common.type == %FW_CDEV_EVENT_RESPONSE * @request: Valid if @common.type == %FW_CDEV_EVENT_REQUEST * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT + * @iso_resource: Valid if @common.type == + * %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or + * %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED * * Convenience union for userspace use. Events could be read(2) into an * appropriately aligned char buffer and then cast to this union for further @@ -163,13 +199,15 @@ struct fw_cdev_event_iso_interrupt { * not fit will be discarded so that the next read(2) will return a new event. */ union fw_cdev_event { - struct fw_cdev_event_common common; - struct fw_cdev_event_bus_reset bus_reset; - struct fw_cdev_event_response response; - struct fw_cdev_event_request request; - struct fw_cdev_event_iso_interrupt iso_interrupt; + struct fw_cdev_event_common common; + struct fw_cdev_event_bus_reset bus_reset; + struct fw_cdev_event_response response; + struct fw_cdev_event_request request; + struct fw_cdev_event_iso_interrupt iso_interrupt; + struct fw_cdev_event_iso_resource iso_resource; }; +/* available since kernel version 2.6.22 */ #define FW_CDEV_IOC_GET_INFO _IOWR('#', 0x00, struct fw_cdev_get_info) #define FW_CDEV_IOC_SEND_REQUEST _IOW('#', 0x01, struct fw_cdev_send_request) #define FW_CDEV_IOC_ALLOCATE _IOWR('#', 0x02, struct fw_cdev_allocate) @@ -178,13 +216,18 @@ union fw_cdev_event { #define FW_CDEV_IOC_INITIATE_BUS_RESET _IOW('#', 0x05, struct fw_cdev_initiate_bus_reset) #define FW_CDEV_IOC_ADD_DESCRIPTOR _IOWR('#', 0x06, struct fw_cdev_add_descriptor) #define FW_CDEV_IOC_REMOVE_DESCRIPTOR _IOW('#', 0x07, struct fw_cdev_remove_descriptor) - #define FW_CDEV_IOC_CREATE_ISO_CONTEXT _IOWR('#', 0x08, struct fw_cdev_create_iso_context) #define FW_CDEV_IOC_QUEUE_ISO _IOWR('#', 0x09, struct fw_cdev_queue_iso) #define FW_CDEV_IOC_START_ISO _IOW('#', 0x0a, struct fw_cdev_start_iso) #define FW_CDEV_IOC_STOP_ISO _IOW('#', 0x0b, struct fw_cdev_stop_iso) + +/* available since kernel version 2.6.24 */ #define FW_CDEV_IOC_GET_CYCLE_TIMER _IOR('#', 0x0c, struct fw_cdev_get_cycle_timer) +/* available since kernel version 2.6.30 */ +#define FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE _IOWR('#', 0x0d, struct fw_cdev_allocate_iso_resource) +#define FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE _IOW('#', 0x0e, struct fw_cdev_deallocate) + /* FW_CDEV_VERSION History * * 1 Feb 18, 2007: Initial version. @@ -284,9 +327,9 @@ struct fw_cdev_allocate { }; /** - * struct fw_cdev_deallocate - Free an address range allocation - * @handle: Handle to the address range, as returned by the kernel when the - * range was allocated + * struct fw_cdev_deallocate - Free a CSR address range or isochronous resource + * @handle: Handle to the address range or iso resource, as returned by the + * kernel when the range or resource was allocated */ struct fw_cdev_deallocate { __u32 handle; @@ -479,4 +522,35 @@ struct fw_cdev_get_cycle_timer { __u32 cycle_timer; }; +/** + * struct fw_cdev_allocate_iso_resource - Allocate a channel or bandwidth + * @closure: Passed back to userspace in correponding iso resource events + * @channels: Isochronous channels of which one is to be allocated + * @bandwidth: Isochronous bandwidth units to be allocated + * @handle: Handle to the allocation, written by the kernel + * + * The %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE ioctl initiates allocation of an + * isochronous channel and/or of isochronous bandwidth at the isochronous + * resource manager (IRM). Only one of the channels specified in @channels is + * allocated. An %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED is sent after + * communication with the IRM, indicating success or failure in the event data. + * The kernel will automatically reallocate the resources after bus resets. + * Should a reallocation fail, an %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED event + * will be sent. The kernel will also automatically deallocate the resources + * when the file descriptor is closed. + * + * @channels is a host-endian bitfield with the most significant bit + * representing channel 0 and the least significant bit representing channel 63: + * 1ULL << (63 - c) + * + * @bandwidth is expressed in bandwidth allocation units, i.e. the time to send + * one quadlet of data (payload or header data) at speed S1600. + */ +struct fw_cdev_allocate_iso_resource { + __u64 closure; + __u64 channels; + __u32 bandwidth; + __u32 handle; +}; + #endif /* _LINUX_FIREWIRE_CDEV_H */ -- GitLab From 1ec3c0269d7196118cc7c403654ca5f19ef4d584 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 4 Jan 2009 16:23:29 +0100 Subject: [PATCH 4189/4982] firewire: cdev: add ioctls for manual iso resource management This adds ioctls for allocation and deallocation of a channel or/and bandwidth without auto-reallocation and without auto-deallocation. The benefit of these ioctls is that libraw1394-style isochronous resource management can be implemented without write access to the IRM's character device file. Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 67 ++++++++++++++++++++++++++++------- include/linux/firewire-cdev.h | 42 ++++++++++++++++------ 2 files changed, 86 insertions(+), 23 deletions(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index a227853aa1e..08fe68d34f3 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -121,14 +121,15 @@ struct iso_resource { struct client *client; /* Schedule work and access todo only with client->lock held. */ struct delayed_work work; - enum {ISO_RES_ALLOC, ISO_RES_REALLOC, ISO_RES_DEALLOC,} todo; + enum {ISO_RES_ALLOC, ISO_RES_REALLOC, ISO_RES_DEALLOC, + ISO_RES_ALLOC_ONCE, ISO_RES_DEALLOC_ONCE,} todo; int generation; u64 channels; s32 bandwidth; struct iso_resource_event *e_alloc, *e_dealloc; }; -static void schedule_iso_resource(struct iso_resource *); +static int schedule_iso_resource(struct iso_resource *); static void release_iso_resource(struct client *, struct client_resource *); /* @@ -1033,7 +1034,9 @@ static void iso_resource_work(struct work_struct *work) skip = todo == ISO_RES_REALLOC && r->generation == generation; } - free = todo == ISO_RES_DEALLOC; + free = todo == ISO_RES_DEALLOC || + todo == ISO_RES_ALLOC_ONCE || + todo == ISO_RES_DEALLOC_ONCE; r->generation = generation; spin_unlock_irq(&client->lock); @@ -1044,7 +1047,9 @@ static void iso_resource_work(struct work_struct *work) fw_iso_resource_manage(client->device->card, generation, r->channels, &channel, &bandwidth, - todo == ISO_RES_ALLOC || todo == ISO_RES_REALLOC); + todo == ISO_RES_ALLOC || + todo == ISO_RES_REALLOC || + todo == ISO_RES_ALLOC_ONCE); /* * Is this generation outdated already? As long as this resource sticks * in the idr, it will be scheduled again for a newer generation or at @@ -1082,7 +1087,7 @@ static void iso_resource_work(struct work_struct *work) if (todo == ISO_RES_REALLOC && success) goto out; - if (todo == ISO_RES_ALLOC) { + if (todo == ISO_RES_ALLOC || todo == ISO_RES_ALLOC_ONCE) { e = r->e_alloc; r->e_alloc = NULL; } else { @@ -1106,10 +1111,17 @@ static void iso_resource_work(struct work_struct *work) client_put(client); } -static void schedule_iso_resource(struct iso_resource *r) +static int schedule_iso_resource(struct iso_resource *r) { - if (schedule_delayed_work(&r->work, 0)) - client_get(r->client); + int scheduled; + + client_get(r->client); + + scheduled = schedule_delayed_work(&r->work, 0); + if (!scheduled) + client_put(r->client); + + return scheduled; } static void release_iso_resource(struct client *client, @@ -1124,9 +1136,9 @@ static void release_iso_resource(struct client *client, spin_unlock_irq(&client->lock); } -static int ioctl_allocate_iso_resource(struct client *client, void *buffer) +static int init_iso_resource(struct client *client, + struct fw_cdev_allocate_iso_resource *request, int todo) { - struct fw_cdev_allocate_iso_resource *request = buffer; struct iso_resource_event *e1, *e2; struct iso_resource *r; int ret; @@ -1146,7 +1158,7 @@ static int ioctl_allocate_iso_resource(struct client *client, void *buffer) INIT_DELAYED_WORK(&r->work, iso_resource_work); r->client = client; - r->todo = ISO_RES_ALLOC; + r->todo = todo; r->generation = -1; r->channels = request->channels; r->bandwidth = request->bandwidth; @@ -1158,8 +1170,14 @@ static int ioctl_allocate_iso_resource(struct client *client, void *buffer) e2->resource.closure = request->closure; e2->resource.type = FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED; - r->resource.release = release_iso_resource; - ret = add_client_resource(client, &r->resource, GFP_KERNEL); + if (todo == ISO_RES_ALLOC) { + r->resource.release = release_iso_resource; + ret = add_client_resource(client, &r->resource, GFP_KERNEL); + } else { + r->resource.release = NULL; + r->resource.handle = -1; + ret = schedule_iso_resource(r) ? 0 : -ENOMEM; + } if (ret < 0) goto fail; request->handle = r->resource.handle; @@ -1173,6 +1191,13 @@ static int ioctl_allocate_iso_resource(struct client *client, void *buffer) return ret; } +static int ioctl_allocate_iso_resource(struct client *client, void *buffer) +{ + struct fw_cdev_allocate_iso_resource *request = buffer; + + return init_iso_resource(client, request, ISO_RES_ALLOC); +} + static int ioctl_deallocate_iso_resource(struct client *client, void *buffer) { struct fw_cdev_deallocate *request = buffer; @@ -1181,6 +1206,20 @@ static int ioctl_deallocate_iso_resource(struct client *client, void *buffer) release_iso_resource, NULL); } +static int ioctl_allocate_iso_resource_once(struct client *client, void *buffer) +{ + struct fw_cdev_allocate_iso_resource *request = buffer; + + return init_iso_resource(client, request, ISO_RES_ALLOC_ONCE); +} + +static int ioctl_deallocate_iso_resource_once(struct client *client, void *buffer) +{ + struct fw_cdev_allocate_iso_resource *request = buffer; + + return init_iso_resource(client, request, ISO_RES_DEALLOC_ONCE); +} + static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { ioctl_get_info, ioctl_send_request, @@ -1197,6 +1236,8 @@ static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { ioctl_get_cycle_timer, ioctl_allocate_iso_resource, ioctl_deallocate_iso_resource, + ioctl_allocate_iso_resource_once, + ioctl_deallocate_iso_resource_once, }; static int dispatch_ioctl(struct client *client, diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 25b96dd0574..08ca838a727 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -151,7 +151,7 @@ struct fw_cdev_event_iso_interrupt { /** * struct fw_cdev_event_iso_resource - Iso resources were allocated or freed * @closure: See &fw_cdev_event_common; - * set by %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE ioctl + * set by %FW_CDEV_IOC_(DE)ALLOCATE_ISO_RESOURCE(_ONCE) ioctl * @type: %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or * %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED * @handle: Reference by which an allocated resource can be deallocated @@ -164,12 +164,12 @@ struct fw_cdev_event_iso_interrupt { * resource was allocated at the IRM. The client has to check @channel and * @bandwidth for whether the allocation actually succeeded. * - * @channel is <0 if no channel was allocated. - * @bandwidth is 0 if no bandwidth was allocated. - * * An %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED event is sent after an isochronous * resource was deallocated at the IRM. It is also sent when automatic * reallocation after a bus reset failed. + * + * @channel is <0 if no channel was (de)allocated or if reallocation failed. + * @bandwidth is 0 if no bandwidth was (de)allocated or if reallocation failed. */ struct fw_cdev_event_iso_resource { __u64 closure; @@ -225,8 +225,10 @@ union fw_cdev_event { #define FW_CDEV_IOC_GET_CYCLE_TIMER _IOR('#', 0x0c, struct fw_cdev_get_cycle_timer) /* available since kernel version 2.6.30 */ -#define FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE _IOWR('#', 0x0d, struct fw_cdev_allocate_iso_resource) -#define FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE _IOW('#', 0x0e, struct fw_cdev_deallocate) +#define FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE _IOWR('#', 0x0d, struct fw_cdev_allocate_iso_resource) +#define FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE _IOW('#', 0x0e, struct fw_cdev_deallocate) +#define FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE _IOW('#', 0x0f, struct fw_cdev_allocate_iso_resource) +#define FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE_ONCE _IOW('#', 0x10, struct fw_cdev_allocate_iso_resource) /* FW_CDEV_VERSION History * @@ -523,11 +525,12 @@ struct fw_cdev_get_cycle_timer { }; /** - * struct fw_cdev_allocate_iso_resource - Allocate a channel or bandwidth + * struct fw_cdev_allocate_iso_resource - (De)allocate a channel or bandwidth * @closure: Passed back to userspace in correponding iso resource events - * @channels: Isochronous channels of which one is to be allocated - * @bandwidth: Isochronous bandwidth units to be allocated - * @handle: Handle to the allocation, written by the kernel + * @channels: Isochronous channels of which one is to be (de)allocated + * @bandwidth: Isochronous bandwidth units to be (de)allocated + * @handle: Handle to the allocation, written by the kernel (only valid in + * case of %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE ioctls) * * The %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE ioctl initiates allocation of an * isochronous channel and/or of isochronous bandwidth at the isochronous @@ -539,6 +542,25 @@ struct fw_cdev_get_cycle_timer { * will be sent. The kernel will also automatically deallocate the resources * when the file descriptor is closed. * + * The %FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE ioctl can be used to initiate + * deallocation of resources which were allocated as described above. + * An %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED event concludes this operation. + * + * The %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE ioctl is a variant of allocation + * without automatic re- or deallocation. + * An %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED event concludes this operation, + * indicating success or failure in its data. + * + * The %FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE_ONCE ioctl works like + * %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE except that resources are freed + * instead of allocated. At most one channel may be specified in this ioctl. + * An %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED event concludes this operation. + * + * To summarize, %FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE allocates iso resources + * for the lifetime of the fd or handle. + * In contrast, %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE allocates iso resources + * for the duration of a bus generation. + * * @channels is a host-endian bitfield with the most significant bit * representing channel 0 and the least significant bit representing channel 63: * 1ULL << (63 - c) -- GitLab From 33580a3ef5ba3bc0ee1b520df82a24bb37ce28f0 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 4 Jan 2009 16:23:29 +0100 Subject: [PATCH 4190/4982] firewire: cdev: add ioctl to query maximum transmission speed While the speed of asynchronous transactions is automatically chosen by the kernel, the speed of isochronous streams has to be chosen by the initiating client. In case of 1394a bus topologies, the maximum possible speed could be figured out with some effort by evaluation of the remote node's link speed field in the config ROM, the local node's link speed field, and the PHY speeds and topologic information in the local node's or IRM's topology map CSR. However, this does not work in case of 1394b buses. Hence add an ioctl to export the maximum speed which the kernel already determined. Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 10 ++++++++++ include/linux/firewire-cdev.h | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 08fe68d34f3..05ad2a8f286 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -1220,6 +1220,15 @@ static int ioctl_deallocate_iso_resource_once(struct client *client, void *buffe return init_iso_resource(client, request, ISO_RES_DEALLOC_ONCE); } +static int ioctl_get_speed(struct client *client, void *buffer) +{ + struct fw_cdev_get_speed *request = buffer; + + request->max_speed = client->device->max_speed; + + return 0; +} + static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { ioctl_get_info, ioctl_send_request, @@ -1238,6 +1247,7 @@ static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { ioctl_deallocate_iso_resource, ioctl_allocate_iso_resource_once, ioctl_deallocate_iso_resource_once, + ioctl_get_speed, }; static int dispatch_ioctl(struct client *client, diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 08ca838a727..f819c102695 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -229,6 +229,7 @@ union fw_cdev_event { #define FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE _IOW('#', 0x0e, struct fw_cdev_deallocate) #define FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE _IOW('#', 0x0f, struct fw_cdev_allocate_iso_resource) #define FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE_ONCE _IOW('#', 0x10, struct fw_cdev_allocate_iso_resource) +#define FW_CDEV_IOC_GET_SPEED _IOR('#', 0x11, struct fw_cdev_get_speed) /* FW_CDEV_VERSION History * @@ -575,4 +576,13 @@ struct fw_cdev_allocate_iso_resource { __u32 handle; }; +/** + * struct fw_cdev_get_speed - Query maximum speed to or from this device + * @max_speed: Speed code; minimum of the device's link speed, the local node's + * link speed, and all PHY port speeds between the two links + */ +struct fw_cdev_get_speed { + __u32 max_speed; +}; + #endif /* _LINUX_FIREWIRE_CDEV_H */ -- GitLab From acfe8333572cad5dc70fce18ac966be0446548d7 Mon Sep 17 00:00:00 2001 From: "Jay Fenlason, Stefan Richter" Date: Sun, 4 Jan 2009 16:23:29 +0100 Subject: [PATCH 4191/4982] firewire: cdev: add ioctl for broadcast write requests Write transactions to the broadcast node ID are a convenient way to trigger functions of multiple nodes at once. IIDC is a protocol which can make use of this if multiple cameras with same command_regs_base are connected at the same bus. Based on Date: Wed, 10 Sep 2008 11:32:16 -0400 From: Jay Fenlason Subject: [patch] SEND_BROADCAST_REQUEST Changes: ioctl_send_request() and ioctl_send_broadcast_request() now share code. Broadcast speed corrected to S100. Check for proper tcode. Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 74 ++++++++++++++++++++++------------- include/linux/firewire-cdev.h | 1 + 2 files changed, 48 insertions(+), 27 deletions(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 05ad2a8f286..a1637a86da3 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -518,10 +518,10 @@ static void complete_transaction(struct fw_card *card, int rcode, client_put(client); } -static int ioctl_send_request(struct client *client, void *buffer) +static int init_request(struct client *client, + struct fw_cdev_send_request *request, + int destination_id, int speed) { - struct fw_device *device = client->device; - struct fw_cdev_send_request *request = buffer; struct outbound_transaction_event *e; int ret; @@ -544,24 +544,6 @@ static int ioctl_send_request(struct client *client, void *buffer) goto failed; } - switch (request->tcode) { - case TCODE_WRITE_QUADLET_REQUEST: - case TCODE_WRITE_BLOCK_REQUEST: - case TCODE_READ_QUADLET_REQUEST: - case TCODE_READ_BLOCK_REQUEST: - case TCODE_LOCK_MASK_SWAP: - case TCODE_LOCK_COMPARE_SWAP: - case TCODE_LOCK_FETCH_ADD: - case TCODE_LOCK_LITTLE_ADD: - case TCODE_LOCK_BOUNDED_ADD: - case TCODE_LOCK_WRAP_ADD: - case TCODE_LOCK_VENDOR_DEPENDENT: - break; - default: - ret = -EINVAL; - goto failed; - } - e->r.resource.release = release_transaction; ret = add_client_resource(client, &e->r.resource, GFP_KERNEL); if (ret < 0) @@ -570,12 +552,9 @@ static int ioctl_send_request(struct client *client, void *buffer) /* Get a reference for the transaction callback */ client_get(client); - fw_send_request(device->card, &e->r.transaction, - request->tcode & 0x1f, - device->node->node_id, - request->generation, - device->max_speed, - request->offset, + fw_send_request(client->device->card, &e->r.transaction, + request->tcode & 0x1f, destination_id, + request->generation, speed, request->offset, e->response.data, request->length, complete_transaction, e); @@ -589,6 +568,31 @@ static int ioctl_send_request(struct client *client, void *buffer) return ret; } +static int ioctl_send_request(struct client *client, void *buffer) +{ + struct fw_cdev_send_request *request = buffer; + + switch (request->tcode) { + case TCODE_WRITE_QUADLET_REQUEST: + case TCODE_WRITE_BLOCK_REQUEST: + case TCODE_READ_QUADLET_REQUEST: + case TCODE_READ_BLOCK_REQUEST: + case TCODE_LOCK_MASK_SWAP: + case TCODE_LOCK_COMPARE_SWAP: + case TCODE_LOCK_FETCH_ADD: + case TCODE_LOCK_LITTLE_ADD: + case TCODE_LOCK_BOUNDED_ADD: + case TCODE_LOCK_WRAP_ADD: + case TCODE_LOCK_VENDOR_DEPENDENT: + break; + default: + return -EINVAL; + } + + return init_request(client, request, client->device->node->node_id, + client->device->max_speed); +} + static void release_request(struct client *client, struct client_resource *resource) { @@ -1229,6 +1233,21 @@ static int ioctl_get_speed(struct client *client, void *buffer) return 0; } +static int ioctl_send_broadcast_request(struct client *client, void *buffer) +{ + struct fw_cdev_send_request *request = buffer; + + switch (request->tcode) { + case TCODE_WRITE_QUADLET_REQUEST: + case TCODE_WRITE_BLOCK_REQUEST: + break; + default: + return -EINVAL; + } + + return init_request(client, request, LOCAL_BUS | 0x3f, SCODE_100); +} + static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { ioctl_get_info, ioctl_send_request, @@ -1248,6 +1267,7 @@ static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { ioctl_allocate_iso_resource_once, ioctl_deallocate_iso_resource_once, ioctl_get_speed, + ioctl_send_broadcast_request, }; static int dispatch_ioctl(struct client *client, diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index f819c102695..340a78502bc 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -230,6 +230,7 @@ union fw_cdev_event { #define FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE _IOW('#', 0x0f, struct fw_cdev_allocate_iso_resource) #define FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE_ONCE _IOW('#', 0x10, struct fw_cdev_allocate_iso_resource) #define FW_CDEV_IOC_GET_SPEED _IOR('#', 0x11, struct fw_cdev_get_speed) +#define FW_CDEV_IOC_SEND_BROADCAST_REQUEST _IOW('#', 0x12, struct fw_cdev_send_request) /* FW_CDEV_VERSION History * -- GitLab From 1566f3dc3e5986a16c7bbb3bb95bb691251a8d25 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 4 Jan 2009 16:23:29 +0100 Subject: [PATCH 4192/4982] firewire: cdev: restrict broadcast write requests to Units Space We don't want random users write to Memory Space (e.g. PCs with physical DMA filters down) or to core CSRs like Reset_Start. This does not protect SBP-2 target CSRs. But properly behaving SBP-2 targets ignore broadcast write requests to these registers, and the maximum damage which can happen with laxer targets is DOS. But there are ways to create DOS situations anyway if there are devices with weak device file permissions (like audio/video devices) present at the same bus as an SBP-2 target. Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index a1637a86da3..d48fa1c23a7 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -1245,6 +1245,10 @@ static int ioctl_send_broadcast_request(struct client *client, void *buffer) return -EINVAL; } + /* Security policy: Only allow accesses to Units Space. */ + if (request->offset < CSR_REGISTER_BASE + CSR_CONFIG_ROM_END) + return -EACCES; + return init_request(client, request, LOCAL_BUS | 0x3f, SCODE_100); } -- GitLab From 5d3fd692a7196a9045fb606f891f5987959b65a0 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 4 Jan 2009 16:23:29 +0100 Subject: [PATCH 4193/4982] firewire: cdev: extend transaction payload size check Make the size check of ioctl_send_request and ioctl_send_broadcast_request speed dependent. Also change the error return code from -EINVAL to -EIO to distinguish this from other errors concerning the ioctl parameters. Another payload size limit for which we don't check here though is the remote node's Bus_Info_Block.max_rec. Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index d48fa1c23a7..6b33f15584c 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -525,9 +525,8 @@ static int init_request(struct client *client, struct outbound_transaction_event *e; int ret; - /* What is the biggest size we'll accept, really? */ - if (request->length > 4096) - return -EINVAL; + if (request->length > 4096 || request->length > 512 << speed) + return -EIO; e = kmalloc(sizeof(*e) + request->length, GFP_KERNEL); if (e == NULL) -- GitLab From 3ba949868a6dc082b24cba5c3bf3f50de7391433 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 4 Jan 2009 16:23:29 +0100 Subject: [PATCH 4194/4982] firewire: cdev: replace some spin_lock_irqsave by spin_lock_irq All of these functions are entered with IRQs enabled. Hence the unconditional spin_unlock_irq can be used. Function: Caller context: dequeue_event() client process, via read(2) fill_bus_reset_event() fw-device.c update worqueue job release_client_resource() client process, via ioctl(2) fw_device_op_release() client process, via close(2) Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 6b33f15584c..3d816a6395c 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -237,7 +237,6 @@ static void queue_event(struct client *client, struct event *event, static int dequeue_event(struct client *client, char __user *buffer, size_t count) { - unsigned long flags; struct event *event; size_t size, total; int i, ret; @@ -252,10 +251,10 @@ static int dequeue_event(struct client *client, fw_device_is_shutdown(client->device)) return -ENODEV; - spin_lock_irqsave(&client->lock, flags); + spin_lock_irq(&client->lock); event = list_first_entry(&client->event_list, struct event, link); list_del(&event->link); - spin_unlock_irqrestore(&client->lock, flags); + spin_unlock_irq(&client->lock); total = 0; for (i = 0; i < ARRAY_SIZE(event->v) && total < count; i++) { @@ -286,9 +285,8 @@ static void fill_bus_reset_event(struct fw_cdev_event_bus_reset *event, struct client *client) { struct fw_card *card = client->device->card; - unsigned long flags; - spin_lock_irqsave(&card->lock, flags); + spin_lock_irq(&card->lock); event->closure = client->bus_reset_closure; event->type = FW_CDEV_EVENT_BUS_RESET; @@ -299,7 +297,7 @@ static void fill_bus_reset_event(struct fw_cdev_event_bus_reset *event, event->irm_node_id = card->irm_node->node_id; event->root_node_id = card->root_node->node_id; - spin_unlock_irqrestore(&card->lock, flags); + spin_unlock_irq(&card->lock); } static void for_each_client(struct fw_device *device, @@ -432,16 +430,15 @@ static int release_client_resource(struct client *client, u32 handle, struct client_resource **resource) { struct client_resource *r; - unsigned long flags; - spin_lock_irqsave(&client->lock, flags); + spin_lock_irq(&client->lock); if (client->in_shutdown) r = NULL; else r = idr_find(&client->resource_idr, handle); if (r && r->release == release) idr_remove(&client->resource_idr, handle); - spin_unlock_irqrestore(&client->lock, flags); + spin_unlock_irq(&client->lock); if (!(r && r->release == release)) return -EINVAL; @@ -1384,7 +1381,6 @@ static int fw_device_op_release(struct inode *inode, struct file *file) { struct client *client = file->private_data; struct event *e, *next_e; - unsigned long flags; mutex_lock(&client->device->client_list_mutex); list_del(&client->link); @@ -1397,9 +1393,9 @@ static int fw_device_op_release(struct inode *inode, struct file *file) fw_iso_context_destroy(client->iso_context); /* Freeze client->resource_idr and client->event_list */ - spin_lock_irqsave(&client->lock, flags); + spin_lock_irq(&client->lock); client->in_shutdown = true; - spin_unlock_irqrestore(&client->lock, flags); + spin_unlock_irq(&client->lock); idr_for_each(&client->resource_idr, shutdown_resource, client); idr_remove_all(&client->resource_idr); -- GitLab From 36a755cfc398fc50abc74055d4478c1b067dac55 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 5 Jan 2009 20:28:10 +0100 Subject: [PATCH 4195/4982] firewire: cdev: shut down iso context before freeing the buffer DMA must be halted before we DMA-unmap and free the DMA buffer. Since we cannot rely on the client to stop the context before it closes the fd, we have to reorder fw_iso_buffer_destroy vs. fw_iso_context_destroy. Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 3d816a6395c..b93ad9c0a0d 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -1386,12 +1386,12 @@ static int fw_device_op_release(struct inode *inode, struct file *file) list_del(&client->link); mutex_unlock(&client->device->client_list_mutex); - if (client->buffer.pages) - fw_iso_buffer_destroy(&client->buffer, client->device->card); - if (client->iso_context) fw_iso_context_destroy(client->iso_context); + if (client->buffer.pages) + fw_iso_buffer_destroy(&client->buffer, client->device->card); + /* Freeze client->resource_idr and client->event_list */ spin_lock_irq(&client->lock); client->in_shutdown = true; -- GitLab From 77258da403be4cfce84b6abcdb515ad0bd1f92f1 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Wed, 7 Jan 2009 20:14:53 +0100 Subject: [PATCH 4196/4982] firewire: cdev: increment fw_cdev_version, update documentation Necessary due to Date: Tue, 22 Jul 2008 23:23:40 -0700 From: David Moore Subject: firewire: Include iso timestamp in headers when header_size > 4 Side note: The lack of upwards compatibility sounds worse than it is. All existing client implementations, libraw1394 and libdc1394, set header_size = 4. And since the ABI v1 behaviour does not offer any advantages over the new behaviour, we deliberately do not provide the old behaviour anymore. Also add documentation about the format of fw_cdev_get_cycle_timer which may be used in conjunction with the timestamp of iso packets but has a different format. Signed-off-by: Stefan Richter --- include/linux/firewire-cdev.h | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 340a78502bc..6ed9127680f 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -138,7 +138,24 @@ struct fw_cdev_event_request { * This event is sent when the controller has completed an &fw_cdev_iso_packet * with the %FW_CDEV_ISO_INTERRUPT bit set. In the receive case, the headers * stripped of all packets up until and including the interrupt packet are - * returned in the @header field. + * returned in the @header field. The amount of header data per packet is as + * specified at iso context creation by &fw_cdev_create_iso_context.header_size. + * + * In version 1 of this ABI, header data consisted of the 1394 isochronous + * packet header, followed by quadlets from the packet payload if + * &fw_cdev_create_iso_context.header_size > 4. + * + * In version 2 of this ABI, header data consist of the 1394 isochronous + * packet header, followed by a timestamp quadlet if + * &fw_cdev_create_iso_context.header_size > 4, followed by quadlets from the + * packet payload if &fw_cdev_create_iso_context.header_size > 8. + * + * Behaviour of ver. 1 of this ABI is no longer available since ABI ver. 2. + * + * Format of 1394 iso packet header: 16 bits len, 2 bits tag, 6 bits channel, + * 4 bits tcode, 4 bits sy, in big endian byte order. Format of timestamp: + * 16 bits invalid, 3 bits cycleSeconds, 13 bits cycleCount, in big endian byte + * order. */ struct fw_cdev_event_iso_interrupt { __u64 closure; @@ -232,11 +249,13 @@ union fw_cdev_event { #define FW_CDEV_IOC_GET_SPEED _IOR('#', 0x11, struct fw_cdev_get_speed) #define FW_CDEV_IOC_SEND_BROADCAST_REQUEST _IOW('#', 0x12, struct fw_cdev_send_request) -/* FW_CDEV_VERSION History - * - * 1 Feb 18, 2007: Initial version. +/* + * FW_CDEV_VERSION History + * 1 (2.6.22) - initial version + * 2 (2.6.30) - changed &fw_cdev_event_iso_interrupt.header if + * &fw_cdev_create_iso_context.header_size is 8 or more */ -#define FW_CDEV_VERSION 1 +#define FW_CDEV_VERSION 2 /** * struct fw_cdev_get_info - General purpose information ioctl @@ -417,6 +436,9 @@ struct fw_cdev_remove_descriptor { * * If a context was successfully created, the kernel writes back a handle to the * context, which must be passed in for subsequent operations on that context. + * + * Note that the effect of a @header_size > 4 depends on + * &fw_cdev_get_info.version, as documented at &fw_cdev_event_iso_interrupt. */ struct fw_cdev_create_iso_context { __u32 type; @@ -520,6 +542,9 @@ struct fw_cdev_stop_iso { * The %FW_CDEV_IOC_GET_CYCLE_TIMER ioctl reads the isochronous cycle timer * and also the system clock. This allows to express the receive time of an * isochronous packet as a system time with microsecond accuracy. + * + * @cycle_timer consists of 7 bits cycleSeconds, 13 bits cycleCount, and + * 12 bits cycleOffset, in host byte order. */ struct fw_cdev_get_cycle_timer { __u64 local_time; -- GitLab From 5d9cb7d276a9c465fef5a771792eac2cf1929f2b Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Thu, 8 Jan 2009 23:07:40 +0100 Subject: [PATCH 4197/4982] firewire: cdev: add ioctls for iso resource management, amendment Some fixes: - Remove stale documentation. - Fix a != vs. == thinko that got in the way of channel management. - Try bandwidth deallocation even if channel deallocation failed. A simplification: - fw_cdev_allocate_iso_resource.channels is now ordered like libdc1394's dc1394_iso_allocate_channel() channels_allowed argument. By the way, I looked closer at cards from NEC, TI, and VIA, and noticed that they all don't implement IEEE 1394a behaviour which is meant to deviate from IEEE 1212's notion of lock compare-swap. This means that we have to do two lock transactions instead of one in many cases where one transaction would already succeed on a fully 1394a compliant IRM. Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 2 +- drivers/firewire/fw-iso.c | 38 ++++++++++++++++++++--------------- include/linux/firewire-cdev.h | 10 ++++----- 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index b93ad9c0a0d..257b0c709a8 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -1082,7 +1082,7 @@ static void iso_resource_work(struct work_struct *work) spin_unlock_irq(&client->lock); if (todo == ISO_RES_ALLOC && channel >= 0) - r->channels = 1ULL << (63 - channel); + r->channels = 1ULL << channel; if (todo == ISO_RES_REALLOC && success) goto out; diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c index a7b57b253b0..f511d16efae 100644 --- a/drivers/firewire/fw-iso.c +++ b/drivers/firewire/fw-iso.c @@ -204,17 +204,19 @@ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, } static int manage_channel(struct fw_card *card, int irm_id, int generation, - __be32 channels_mask, u64 offset, bool allocate) + u32 channels_mask, u64 offset, bool allocate) { - __be32 data[2], c, old = allocate ? cpu_to_be32(~0) : 0; + __be32 data[2], c, all, old; int i, retry = 5; + old = all = allocate ? cpu_to_be32(~0) : 0; + for (i = 0; i < 32; i++) { - c = cpu_to_be32(1 << (31 - i)); - if (!(channels_mask & c)) + if (!(channels_mask & 1 << i)) continue; - if (allocate == !(old & c)) + c = cpu_to_be32(1 << (31 - i)); + if ((old & c) != (all & c)) continue; data[0] = old; @@ -233,7 +235,7 @@ static int manage_channel(struct fw_card *card, int irm_id, int generation, old = data[0]; /* Is the IRM 1394a-2000 compliant? */ - if ((data[0] & c) != (data[1] & c)) + if ((data[0] & c) == (data[1] & c)) continue; /* 1394-1995 IRM, fall through to retry. */ @@ -249,11 +251,10 @@ static int manage_channel(struct fw_card *card, int irm_id, int generation, static void deallocate_channel(struct fw_card *card, int irm_id, int generation, int channel) { - __be32 mask; + u32 mask; u64 offset; - mask = channel < 32 ? cpu_to_be32(1 << (31 - channel)) : - cpu_to_be32(1 << (63 - channel)); + mask = channel < 32 ? 1 << channel : 1 << (channel - 32); offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI : CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO; @@ -266,7 +267,12 @@ static void deallocate_channel(struct fw_card *card, int irm_id, * In parameters: card, generation, channels_mask, bandwidth, allocate * Out parameters: channel, bandwidth * This function blocks (sleeps) during communication with the IRM. + * * Allocates or deallocates at most one channel out of channels_mask. + * channels_mask is a bitfield with MSB for channel 63 and LSB for channel 0. + * (Note, the IRM's CHANNELS_AVAILABLE is a big-endian bitfield with MSB for + * channel 0 and LSB for channel 63.) + * Allocates or deallocates as many bandwidth allocation units as specified. * * Returns channel < 0 if no channel was allocated or deallocated. * Returns bandwidth = 0 if no bandwidth was allocated or deallocated. @@ -274,17 +280,17 @@ static void deallocate_channel(struct fw_card *card, int irm_id, * If generation is stale, deallocations succeed but allocations fail with * channel = -EAGAIN. * - * If channel (de)allocation fails, bandwidth (de)allocation fails too. + * If channel allocation fails, no bandwidth will be allocated either. * If bandwidth allocation fails, no channel will be allocated either. - * If bandwidth deallocation fails, channel deallocation may still have been - * successful. + * But deallocations of channel and bandwidth are tried independently + * of each other's success. */ void fw_iso_resource_manage(struct fw_card *card, int generation, u64 channels_mask, int *channel, int *bandwidth, bool allocate) { - __be32 channels_hi = cpu_to_be32(channels_mask >> 32); - __be32 channels_lo = cpu_to_be32(channels_mask); + u32 channels_hi = channels_mask; /* channels 31...0 */ + u32 channels_lo = channels_mask >> 32; /* channels 63...32 */ int irm_id, ret, c = -EINVAL; spin_lock_irq(&card->lock); @@ -302,7 +308,7 @@ void fw_iso_resource_manage(struct fw_card *card, int generation, } *channel = c; - if (channels_mask != 0 && c < 0) + if (allocate && channels_mask != 0 && c < 0) *bandwidth = 0; if (*bandwidth == 0) @@ -312,7 +318,7 @@ void fw_iso_resource_manage(struct fw_card *card, int generation, if (ret < 0) *bandwidth = 0; - if (ret < 0 && c >= 0 && allocate) { + if (allocate && ret < 0 && c >= 0) { deallocate_channel(card, irm_id, generation, c); *channel = ret; } diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 6ed9127680f..2e35379bf96 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -174,8 +174,6 @@ struct fw_cdev_event_iso_interrupt { * @handle: Reference by which an allocated resource can be deallocated * @channel: Isochronous channel which was (de)allocated, if any * @bandwidth: Bandwidth allocation units which were (de)allocated, if any - * @channels_available: Last known availability of channels - * @bandwidth_available: Last known availability of bandwidth * * An %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED event is sent after an isochronous * resource was allocated at the IRM. The client has to check @channel and @@ -580,7 +578,7 @@ struct fw_cdev_get_cycle_timer { * * The %FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE_ONCE ioctl works like * %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE except that resources are freed - * instead of allocated. At most one channel may be specified in this ioctl. + * instead of allocated. * An %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED event concludes this operation. * * To summarize, %FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE allocates iso resources @@ -588,9 +586,9 @@ struct fw_cdev_get_cycle_timer { * In contrast, %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE allocates iso resources * for the duration of a bus generation. * - * @channels is a host-endian bitfield with the most significant bit - * representing channel 0 and the least significant bit representing channel 63: - * 1ULL << (63 - c) + * @channels is a host-endian bitfield with the least significant bit + * representing channel 0 and the most significant bit representing channel 63: + * 1ULL << c for each channel c that is a candidate for (de)allocation. * * @bandwidth is expressed in bandwidth allocation units, i.e. the time to send * one quadlet of data (payload or header data) at speed S1600. -- GitLab From 81610b8fbfc027a67707ff567d490819a3d55844 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 11 Jan 2009 13:44:46 +0100 Subject: [PATCH 4198/4982] firewire: cdev: simplify a schedule_delayed_work wrapper The kernel API documentation says that queue_delayed_work() returns 0 (only) if the work was already queued. The return codes of schedule_delayed_work() are not documented but the same. In init_iso_resource(), the work has never been queued yet, hence we can assume schedule_delayed_work() to be a guaranteed success there. Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 257b0c709a8..214e534efee 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -129,7 +129,7 @@ struct iso_resource { struct iso_resource_event *e_alloc, *e_dealloc; }; -static int schedule_iso_resource(struct iso_resource *); +static void schedule_iso_resource(struct iso_resource *); static void release_iso_resource(struct client *, struct client_resource *); /* @@ -1111,17 +1111,11 @@ static void iso_resource_work(struct work_struct *work) client_put(client); } -static int schedule_iso_resource(struct iso_resource *r) +static void schedule_iso_resource(struct iso_resource *r) { - int scheduled; - client_get(r->client); - - scheduled = schedule_delayed_work(&r->work, 0); - if (!scheduled) + if (!schedule_delayed_work(&r->work, 0)) client_put(r->client); - - return scheduled; } static void release_iso_resource(struct client *client, @@ -1173,13 +1167,13 @@ static int init_iso_resource(struct client *client, if (todo == ISO_RES_ALLOC) { r->resource.release = release_iso_resource; ret = add_client_resource(client, &r->resource, GFP_KERNEL); + if (ret < 0) + goto fail; } else { r->resource.release = NULL; r->resource.handle = -1; - ret = schedule_iso_resource(r) ? 0 : -ENOMEM; + schedule_iso_resource(r); } - if (ret < 0) - goto fail; request->handle = r->resource.handle; return 0; -- GitLab From 41f321c2ecf416f9dcf76de989e9059fd699c8c1 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 17 Jan 2009 22:45:54 +0100 Subject: [PATCH 4199/4982] firewire: core: clean up includes Signed-off-by: Stefan Richter --- drivers/firewire/fw-device.c | 20 +++++++++++--------- drivers/firewire/fw-device.h | 13 +++++++++++-- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index ac5043cc9ad..7e05e994c1b 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c @@ -18,24 +18,26 @@ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include -#include -#include -#include -#include +#include #include +#include +#include #include #include -#include +#include +#include #include #include #include #include +#include +#include + #include -#include -#include "fw-transaction.h" -#include "fw-topology.h" + #include "fw-device.h" +#include "fw-topology.h" +#include "fw-transaction.h" void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 * p) { diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h index 41483f1a1be..3085a74669b 100644 --- a/drivers/firewire/fw-device.h +++ b/drivers/firewire/fw-device.h @@ -19,11 +19,17 @@ #ifndef __fw_device_h #define __fw_device_h +#include #include -#include #include -#include +#include +#include #include +#include +#include +#include +#include + #include enum fw_device_state { @@ -39,6 +45,9 @@ struct fw_attribute_group { struct attribute *attrs[11]; }; +struct fw_node; +struct fw_card; + /* * Note, fw_device.generation always has to be read before fw_device.node_id. * Use SMP memory barriers to ensure this. Otherwise requests will be sent -- GitLab From aed808927410d0b1d80378492059f22a46974267 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 17 Jan 2009 22:45:54 +0100 Subject: [PATCH 4200/4982] firewire: core: move some functions Signed-off-by: Stefan Richter --- drivers/firewire/fw-device.c | 90 ++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 46 deletions(-) diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index 7e05e994c1b..7276a0d5520 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c @@ -155,27 +155,6 @@ struct bus_type fw_bus_type = { }; EXPORT_SYMBOL(fw_bus_type); -static void fw_device_release(struct device *dev) -{ - struct fw_device *device = fw_device(dev); - struct fw_card *card = device->card; - unsigned long flags; - - /* - * Take the card lock so we don't set this to NULL while a - * FW_NODE_UPDATED callback is being handled or while the - * bus manager work looks at this node. - */ - spin_lock_irqsave(&card->lock, flags); - device->node->data = NULL; - spin_unlock_irqrestore(&card->lock, flags); - - fw_node_put(device->node); - kfree(device->config_rom); - kfree(device); - fw_card_put(card); -} - int fw_device_enable_phys_dma(struct fw_device *device) { int generation = device->generation; @@ -679,11 +658,53 @@ static void fw_device_shutdown(struct work_struct *work) fw_device_put(device); } +static void fw_device_release(struct device *dev) +{ + struct fw_device *device = fw_device(dev); + struct fw_card *card = device->card; + unsigned long flags; + + /* + * Take the card lock so we don't set this to NULL while a + * FW_NODE_UPDATED callback is being handled or while the + * bus manager work looks at this node. + */ + spin_lock_irqsave(&card->lock, flags); + device->node->data = NULL; + spin_unlock_irqrestore(&card->lock, flags); + + fw_node_put(device->node); + kfree(device->config_rom); + kfree(device); + fw_card_put(card); +} + static struct device_type fw_device_type = { - .release = fw_device_release, + .release = fw_device_release, }; -static void fw_device_update(struct work_struct *work); +static int update_unit(struct device *dev, void *data) +{ + struct fw_unit *unit = fw_unit(dev); + struct fw_driver *driver = (struct fw_driver *)dev->driver; + + if (is_fw_unit(dev) && driver != NULL && driver->update != NULL) { + down(&dev->sem); + driver->update(unit); + up(&dev->sem); + } + + return 0; +} + +static void fw_device_update(struct work_struct *work) +{ + struct fw_device *device = + container_of(work, struct fw_device, work.work); + + fw_device_cdev_update(device); + device_for_each_child(&device->device, NULL, update_unit); +} /* * If a device was pending for deletion because its node went away but its @@ -851,29 +872,6 @@ static void fw_device_init(struct work_struct *work) put_device(&device->device); /* our reference */ } -static int update_unit(struct device *dev, void *data) -{ - struct fw_unit *unit = fw_unit(dev); - struct fw_driver *driver = (struct fw_driver *)dev->driver; - - if (is_fw_unit(dev) && driver != NULL && driver->update != NULL) { - down(&dev->sem); - driver->update(unit); - up(&dev->sem); - } - - return 0; -} - -static void fw_device_update(struct work_struct *work) -{ - struct fw_device *device = - container_of(work, struct fw_device, work.work); - - fw_device_cdev_update(device); - device_for_each_child(&device->device, NULL, update_unit); -} - enum { REREAD_BIB_ERROR, REREAD_BIB_GONE, -- GitLab From d01b01787680a1156ff6a554e40baa460bb88efb Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 17 Jan 2009 22:45:54 +0100 Subject: [PATCH 4201/4982] firewire: core: remove condition which is always false reread_bus_info_block() only gets to see devices whose config_rom_length is at least 6 (ROM header, bus info block, root directory header). Signed-off-by: Stefan Richter --- drivers/firewire/fw-device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index 7276a0d5520..df789d321d1 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c @@ -892,7 +892,7 @@ static int reread_bus_info_block(struct fw_device *device, int generation) if (i == 0 && q == 0) return REREAD_BIB_GONE; - if (i > device->config_rom_length || q != device->config_rom[i]) + if (q != device->config_rom[i]) return REREAD_BIB_CHANGED; } -- GitLab From e1eff7a393d4a4e3ad1cf65fcba899146840bfd2 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 3 Feb 2009 17:55:19 +0100 Subject: [PATCH 4202/4982] firewire: normalize a variable name Standardize on if (err) handle_error; and if (ret < 0) handle_error; Don't call a variable err if we store values in it which mean success. Also, offset some return statements by a blank line since this how we do it in drivers/firewire. Signed-off-by: Stefan Richter --- drivers/firewire/fw-card.c | 9 +++++---- drivers/firewire/fw-device.c | 6 +++--- drivers/firewire/fw-iso.c | 10 ++++++---- drivers/firewire/fw-ohci.c | 3 ++- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index 27a3aae58cf..08a7e18526e 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c @@ -404,7 +404,7 @@ int fw_card_add(struct fw_card *card, { u32 *config_rom; size_t length; - int err; + int ret; card->max_receive = max_receive; card->link_speed = link_speed; @@ -415,13 +415,14 @@ int fw_card_add(struct fw_card *card, list_add_tail(&card->link, &card_list); mutex_unlock(&card_mutex); - err = card->driver->enable(card, config_rom, length); - if (err < 0) { + ret = card->driver->enable(card, config_rom, length); + if (ret < 0) { mutex_lock(&card_mutex); list_del(&card->link); mutex_unlock(&card_mutex); } - return err; + + return ret; } EXPORT_SYMBOL(fw_card_add); diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index df789d321d1..633e44de5d1 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c @@ -761,7 +761,7 @@ static void fw_device_init(struct work_struct *work) struct fw_device *device = container_of(work, struct fw_device, work.work); struct device *revived_dev; - int minor, err; + int minor, ret; /* * All failure paths here set node->data to NULL, so that we @@ -797,12 +797,12 @@ static void fw_device_init(struct work_struct *work) fw_device_get(device); down_write(&fw_device_rwsem); - err = idr_pre_get(&fw_device_idr, GFP_KERNEL) ? + ret = idr_pre_get(&fw_device_idr, GFP_KERNEL) ? idr_get_new(&fw_device_idr, device, &minor) : -ENOMEM; up_write(&fw_device_rwsem); - if (err < 0) + if (ret < 0) goto error; device->device.bus = &fw_bus_type; diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c index f511d16efae..2baf1007253 100644 --- a/drivers/firewire/fw-iso.c +++ b/drivers/firewire/fw-iso.c @@ -75,19 +75,21 @@ int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card, kfree(buffer->pages); out: buffer->pages = NULL; + return -ENOMEM; } int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma) { unsigned long uaddr; - int i, ret; + int i, err; uaddr = vma->vm_start; for (i = 0; i < buffer->page_count; i++) { - ret = vm_insert_page(vma, uaddr, buffer->pages[i]); - if (ret) - return ret; + err = vm_insert_page(vma, uaddr, buffer->pages[i]); + if (err) + return err; + uaddr += PAGE_SIZE; } diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 859af71b06a..c9227837465 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -2459,11 +2459,12 @@ static int __devinit pci_probe(struct pci_dev *dev, reg_read(ohci, OHCI1394_GUIDLo); err = fw_card_add(&ohci->card, max_receive, link_speed, guid); - if (err < 0) + if (err) goto fail_self_id; fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n", dev_name(&dev->dev), version >> 16, version & 0xff); + return 0; fail_self_id: -- GitLab From ba27e1f7bf220799cd3d7503f82bda71b8ebe8c5 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Thu, 5 Mar 2009 19:07:00 +0100 Subject: [PATCH 4203/4982] firewire: core: normalize a function argument name It's called "payload" rather than "data" almost everywhere in fw-transaction.c. Signed-off-by: Stefan Richter --- drivers/firewire/fw-transaction.c | 6 +++--- drivers/firewire/fw-transaction.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index 1537737e442..76938fe432a 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -317,15 +317,15 @@ static void transaction_callback(struct fw_card *card, int rcode, */ int fw_run_transaction(struct fw_card *card, int tcode, int destination_id, int generation, int speed, unsigned long long offset, - void *data, size_t length) + void *payload, size_t length) { struct transaction_callback_data d; struct fw_transaction t; init_completion(&d.done); - d.payload = data; + d.payload = payload; fw_send_request(card, &t, tcode, destination_id, generation, speed, - offset, data, length, transaction_callback, &d); + offset, payload, length, transaction_callback, &d); wait_for_completion(&d.done); return d.rcode; diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 212a1029382..35d0a4bb6d5 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -405,14 +405,14 @@ int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset); void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, int destination_id, int generation, int speed, - unsigned long long offset, void *data, size_t length, + unsigned long long offset, void *payload, size_t length, fw_transaction_callback_t callback, void *callback_data); int fw_cancel_transaction(struct fw_card *card, struct fw_transaction *transaction); void fw_flush_transactions(struct fw_card *card); int fw_run_transaction(struct fw_card *card, int tcode, int destination_id, int generation, int speed, unsigned long long offset, - void *data, size_t length); + void *payload, size_t length); void fw_send_phy_config(struct fw_card *card, int node_id, int generation, int gap_count); -- GitLab From f8c2287c65f8f72000102fc058232669e4540bc4 Mon Sep 17 00:00:00 2001 From: Jay Fenlason Date: Thu, 5 Mar 2009 19:08:40 +0100 Subject: [PATCH 4204/4982] firewire: implement asynchronous stream transmission Allow userspace and other firewire drivers (fw-ipv4 I'm looking at you!) to send Asynchronous Transmit Streams as described in 7.8.3 of release 1.1 of the 1394 Open Host Controller Interface Specification. Signed-off-by: Jay Fenlason Signed-off-by: Stefan Richter (tweaks) --- drivers/firewire/fw-cdev.c | 33 +++++++++++++++++++++++++++++++ drivers/firewire/fw-ohci.c | 21 ++++++++++++++++++-- drivers/firewire/fw-transaction.c | 25 +++++++++++++++++++++++ drivers/firewire/fw-transaction.h | 4 ++++ include/linux/firewire-cdev.h | 27 +++++++++++++++++++++++++ 5 files changed, 108 insertions(+), 2 deletions(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 214e534efee..539dae5eb5b 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -1242,6 +1242,38 @@ static int ioctl_send_broadcast_request(struct client *client, void *buffer) return init_request(client, request, LOCAL_BUS | 0x3f, SCODE_100); } +struct stream_packet { + struct fw_packet packet; + u8 data[0]; +}; + +static void send_stream_packet_done(struct fw_packet *packet, + struct fw_card *card, int status) +{ + kfree(container_of(packet, struct stream_packet, packet)); +} + +static int ioctl_send_stream_packet(struct client *client, void *buffer) +{ + struct fw_cdev_send_stream_packet *request = buffer; + struct stream_packet *p; + + p = kmalloc(sizeof(*p) + request->size, GFP_KERNEL); + if (p == NULL) + return -ENOMEM; + + if (request->data && + copy_from_user(p->data, u64_to_uptr(request->data), request->size)) { + kfree(p); + return -EFAULT; + } + fw_send_stream_packet(client->device->card, &p->packet, + request->generation, request->speed, + request->channel, request->sy, request->tag, + p->data, request->size, send_stream_packet_done); + return 0; +} + static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { ioctl_get_info, ioctl_send_request, @@ -1262,6 +1294,7 @@ static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { ioctl_deallocate_iso_resource_once, ioctl_get_speed, ioctl_send_broadcast_request, + ioctl_send_stream_packet, }; static int dispatch_ioctl(struct client *client, diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index c9227837465..1180d0be0bb 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -936,7 +936,9 @@ static int at_context_queue_packet(struct context *ctx, */ header = (__le32 *) &d[1]; - if (packet->header_length > 8) { + switch (packet->header_length) { + case 16: + case 12: header[0] = cpu_to_le32((packet->header[0] & 0xffff) | (packet->speed << 16)); header[1] = cpu_to_le32((packet->header[1] & 0xffff) | @@ -950,12 +952,27 @@ static int at_context_queue_packet(struct context *ctx, header[3] = (__force __le32) packet->header[3]; d[0].req_count = cpu_to_le16(packet->header_length); - } else { + break; + + case 8: header[0] = cpu_to_le32((OHCI1394_phy_tcode << 4) | (packet->speed << 16)); header[1] = cpu_to_le32(packet->header[0]); header[2] = cpu_to_le32(packet->header[1]); d[0].req_count = cpu_to_le16(12); + break; + + case 4: + header[0] = cpu_to_le32((packet->header[0] & 0xffff) | + (packet->speed << 16)); + header[1] = cpu_to_le32(packet->header[0] & 0xffff0000); + d[0].req_count = cpu_to_le16(8); + break; + + default: + /* BUG(); */ + packet->ack = RCODE_SEND_ERROR; + return -1; } driver_data = (struct driver_data *) &d[3]; diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index 76938fe432a..e3da5899196 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -37,6 +37,10 @@ #include "fw-topology.h" #include "fw-device.h" +#define HEADER_TAG(tag) ((tag) << 14) +#define HEADER_CHANNEL(ch) ((ch) << 8) +#define HEADER_SY(sy) ((sy) << 0) + #define HEADER_PRI(pri) ((pri) << 0) #define HEADER_TCODE(tcode) ((tcode) << 4) #define HEADER_RETRY(retry) ((retry) << 8) @@ -293,6 +297,27 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, } EXPORT_SYMBOL(fw_send_request); +void fw_send_stream_packet(struct fw_card *card, struct fw_packet *p, + int generation, int speed, int channel, int sy, int tag, + void *payload, size_t length, fw_packet_callback_t callback) +{ + p->callback = callback; + p->header[0] = + HEADER_DATA_LENGTH(length) + | HEADER_TAG(tag) + | HEADER_CHANNEL(channel) + | HEADER_TCODE(TCODE_STREAM_DATA) + | HEADER_SY(sy); + p->header_length = 4; + p->payload = payload; + p->payload_length = length; + p->speed = speed; + p->generation = generation; + p->ack = 0; + + card->driver->send_request(card, p); +} + struct transaction_callback_data { struct completion done; void *payload; diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 35d0a4bb6d5..eed2e295eb3 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -407,6 +407,10 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, int destination_id, int generation, int speed, unsigned long long offset, void *payload, size_t length, fw_transaction_callback_t callback, void *callback_data); +void fw_send_stream_packet(struct fw_card *card, struct fw_packet *p, + int generation, int speed, int channel, int sy, int tag, + void *payload, size_t length, fw_packet_callback_t callback); + int fw_cancel_transaction(struct fw_card *card, struct fw_transaction *transaction); void fw_flush_transactions(struct fw_card *card); diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 2e35379bf96..4dfc84d0ac7 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -246,6 +246,7 @@ union fw_cdev_event { #define FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE_ONCE _IOW('#', 0x10, struct fw_cdev_allocate_iso_resource) #define FW_CDEV_IOC_GET_SPEED _IOR('#', 0x11, struct fw_cdev_get_speed) #define FW_CDEV_IOC_SEND_BROADCAST_REQUEST _IOW('#', 0x12, struct fw_cdev_send_request) +#define FW_CDEV_IOC_SEND_STREAM_PACKET _IOW('#', 0x13, struct fw_cdev_send_stream_packet) /* * FW_CDEV_VERSION History @@ -609,4 +610,30 @@ struct fw_cdev_get_speed { __u32 max_speed; }; +/** + * struct fw_cdev_send_stream_packet - send an asynchronous stream packet + * @generation: Bus generation where the packet is valid + * @speed: Speed code to send the packet at + * @channel: Channel to send the packet on + * @sy: Four-bit sy code for the packet + * @tag: Two-bit tag field to use for the packet + * @size: Size of the packet's data payload + * @data: Userspace pointer to the payload + * + * The %FW_CDEV_IOC_SEND_STREAM_PACKET ioctl sends an asynchronous stream packet + * to every device (that is listening to the specified channel) on the + * firewire bus. It is the applications's job to ensure + * that the intended device(s) will be able to receive the packet at the chosen + * transmit speed. + */ +struct fw_cdev_send_stream_packet { + __u32 generation; + __u32 speed; + __u32 channel; + __u32 sy; + __u32 tag; + __u32 size; + __u64 data; +}; + #endif /* _LINUX_FIREWIRE_CDEV_H */ -- GitLab From 6104ee92d62ea3638b67494fcf061cb4b9b9d518 Mon Sep 17 00:00:00 2001 From: Jay Fenlason Date: Mon, 23 Feb 2009 15:59:34 -0500 Subject: [PATCH 4205/4982] firewire: broadcast channel support This patch adds the ISO broadcast channel support that is required of a 1394a IRM. In specific, if the local device the IRM, it allocates ISO channel 31 and sets the broadcast channel register of all devices on the local bus to BROADCAST_CHANNEL_INITIAL | BROADCAST_CHANNEL_VALID to indicate that channel 31 can be use for broadcast messages. One minor complication is that on startup the local device may become IRM before all the devices on the bus have been enumerated by the stack. Therefore we have to keep a "the local device is IRM" flag and possibly set the broadcast channel register of new devices at enumeration time. Signed-off-by: Jay Fenlason Signed-off-by: Stefan Richter --- drivers/firewire/fw-card.c | 172 ++++++++++++++++++++++++++++-- drivers/firewire/fw-device.c | 3 + drivers/firewire/fw-transaction.h | 8 ++ 3 files changed, 177 insertions(+), 6 deletions(-) diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index 08a7e18526e..f2b363ea443 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c @@ -181,6 +181,147 @@ void fw_core_remove_descriptor(struct fw_descriptor *desc) mutex_unlock(&card_mutex); } +/* ------------------------------------------------------------------ */ +/* Code to handle 1394a broadcast channel */ + +#define THIRTY_TWO_CHANNELS (0xFFFFFFFFU) +#define IRM_RETRIES 2 + +/* + * The abi is set by device_for_each_child(), even though we have no use + * for data, nor do we have a meaningful return value. + */ +int fw_irm_set_broadcast_channel_register(struct device *dev, void *data) +{ + struct fw_device *d; + int rcode; + int node_id; + int max_speed; + int retries; + int generation; + __be32 regval; + struct fw_card *card; + + d = fw_device(dev); + /* FIXME: do we need locking here? */ + generation = d->generation; + smp_rmb(); /* Ensure generation is at least as old as node_id */ + node_id = d->node_id; + max_speed = d->max_speed; + retries = IRM_RETRIES; + card = d->card; +tryagain_r: + rcode = fw_run_transaction(card, TCODE_READ_QUADLET_REQUEST, + node_id, generation, max_speed, + CSR_REGISTER_BASE + CSR_BROADCAST_CHANNEL, + ®val, 4); + switch (rcode) { + case RCODE_BUSY: + if (retries--) + goto tryagain_r; + fw_notify("node %x read broadcast channel busy\n", + node_id); + return 0; + + default: + fw_notify("node %x read broadcast channel failed %x\n", + node_id, rcode); + return 0; + + case RCODE_COMPLETE: + /* + * Paranoid reporting of nonstandard broadcast channel + * contents goes here + */ + if (regval != cpu_to_be32(BROADCAST_CHANNEL_INITIAL)) + return 0; + break; + } + retries = IRM_RETRIES; + regval = cpu_to_be32(BROADCAST_CHANNEL_INITIAL | + BROADCAST_CHANNEL_VALID); +tryagain_w: + rcode = fw_run_transaction(card, + TCODE_WRITE_QUADLET_REQUEST, node_id, + generation, max_speed, + CSR_REGISTER_BASE + CSR_BROADCAST_CHANNEL, + ®val, 4); + switch (rcode) { + case RCODE_BUSY: + if (retries--) + goto tryagain_w; + fw_notify("node %x write broadcast channel busy\n", + node_id); + return 0; + + default: + fw_notify("node %x write broadcast channel failed %x\n", + node_id, rcode); + return 0; + + case RCODE_COMPLETE: + return 0; + } + return 0; +} + +static void +irm_allocate_broadcast(struct fw_device *irm_dev, struct device *locald) +{ + u32 generation; + u32 node_id; + u32 max_speed; + u32 retries; + __be32 old_data; + __be32 lock_data[2]; + int rcode; + + /* + * The device we are updating is the IRM, so we must do + * some extra work. + */ + retries = IRM_RETRIES; + generation = irm_dev->generation; + /* FIXME: do we need locking here? */ + smp_rmb(); + node_id = irm_dev->node_id; + max_speed = irm_dev->max_speed; + + lock_data[0] = cpu_to_be32(THIRTY_TWO_CHANNELS); + lock_data[1] = cpu_to_be32(THIRTY_TWO_CHANNELS & ~1); +tryagain: + old_data = lock_data[0]; + rcode = fw_run_transaction(irm_dev->card, TCODE_LOCK_COMPARE_SWAP, + node_id, generation, max_speed, + CSR_REGISTER_BASE+CSR_CHANNELS_AVAILABLE_HI, + &lock_data[0], 8); + switch (rcode) { + case RCODE_BUSY: + if (retries--) + goto tryagain; + /* fallthrough */ + default: + fw_error("node %x: allocate broadcast channel failed (%x)\n", + node_id, rcode); + return; + + case RCODE_COMPLETE: + if (lock_data[0] == old_data) + break; + if (retries--) { + lock_data[1] = cpu_to_be32(be32_to_cpu(lock_data[0])&~1); + goto tryagain; + } + fw_error("node %x: allocate broadcast channel failed: too many" + " retries\n", node_id); + return; + } + irm_dev->card->is_irm = true; + device_for_each_child(locald, NULL, fw_irm_set_broadcast_channel_register); +} +/* ------------------------------------------------------------------ */ + + static const char gap_count_table[] = { 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40 }; @@ -198,8 +339,8 @@ void fw_schedule_bm_work(struct fw_card *card, unsigned long delay) static void fw_card_bm_work(struct work_struct *work) { struct fw_card *card = container_of(work, struct fw_card, work.work); - struct fw_device *root_device; - struct fw_node *root_node, *local_node; + struct fw_device *root_device, *irm_device, *local_device; + struct fw_node *root_node, *local_node, *irm_node; unsigned long flags; int root_id, new_root_id, irm_id, gap_count, generation, grace, rcode; bool do_reset = false; @@ -208,8 +349,10 @@ static void fw_card_bm_work(struct work_struct *work) __be32 lock_data[2]; spin_lock_irqsave(&card->lock, flags); + card->is_irm = false; local_node = card->local_node; root_node = card->root_node; + irm_node = card->irm_node; if (local_node == NULL) { spin_unlock_irqrestore(&card->lock, flags); @@ -217,6 +360,7 @@ static void fw_card_bm_work(struct work_struct *work) } fw_node_get(local_node); fw_node_get(root_node); + fw_node_get(irm_node); generation = card->generation; root_device = root_node->data; @@ -225,7 +369,8 @@ static void fw_card_bm_work(struct work_struct *work) root_device_is_cmc = root_device && root_device->cmc; root_id = root_node->node_id; grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 10)); - + irm_device = irm_node->data; + local_device = local_node->data; if (is_next_generation(generation, card->bm_generation) || (card->bm_generation != generation && grace)) { /* @@ -240,8 +385,8 @@ static void fw_card_bm_work(struct work_struct *work) * next generation. */ - irm_id = card->irm_node->node_id; - if (!card->irm_node->link_on) { + irm_id = irm_node->node_id; + if (!irm_node->link_on) { new_root_id = local_node->node_id; fw_notify("IRM has link off, making local node (%02x) root.\n", new_root_id); @@ -263,9 +408,15 @@ static void fw_card_bm_work(struct work_struct *work) goto out; if (rcode == RCODE_COMPLETE && - lock_data[0] != cpu_to_be32(0x3f)) + lock_data[0] != cpu_to_be32(0x3f)) { /* Somebody else is BM, let them do the work. */ + if (irm_id == local_node->node_id) { + /* But we are IRM, so do irm-y things */ + irm_allocate_broadcast(irm_device, + card->device); + } goto out; + } spin_lock_irqsave(&card->lock, flags); @@ -357,10 +508,19 @@ static void fw_card_bm_work(struct work_struct *work) card->index, new_root_id, gap_count); fw_send_phy_config(card, new_root_id, generation, gap_count); fw_core_initiate_bus_reset(card, 1); + } else if (irm_node->node_id == local_node->node_id) { + /* + * We are IRM, so do irm-y things. + * There's no reason to do this if we're doing a reset. . . + * We'll be back. + */ + irm_allocate_broadcast(irm_device, card->device); } + out: fw_node_put(root_node); fw_node_put(local_node); + fw_node_put(irm_node); out_put_card: fw_card_put(card); } diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index 633e44de5d1..a40444e8eb2 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c @@ -849,6 +849,9 @@ static void fw_device_init(struct work_struct *work) device->config_rom[3], device->config_rom[4], 1 << device->max_speed); device->config_rom_retries = 0; + if (device->card->is_irm) + fw_irm_set_broadcast_channel_register(&device->device, + NULL); } /* diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index eed2e295eb3..f90f09c0583 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -230,6 +230,11 @@ struct fw_card { u8 color; /* must be u8 to match the definition in struct fw_node */ int gap_count; bool beta_repeaters_present; + /* + * Set if the local device is the IRM and the broadcast channel + * was allocated. + */ + bool is_irm; int index; @@ -438,4 +443,7 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, void fw_core_handle_request(struct fw_card *card, struct fw_packet *request); void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet); +extern int fw_irm_set_broadcast_channel_register(struct device *dev, + void *data); + #endif /* __fw_transaction_h */ -- GitLab From c8a25900f35e575938c791507894c036c0f2ca7d Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 10 Mar 2009 20:59:16 +0100 Subject: [PATCH 4206/4982] firewire: cdev: amendment to "add ioctl to query maximum transmission speed" The as yet unreleased FW_CDEV_IOC_GET_SPEED ioctl puts only a single integer into the parameter buffer. We can use ioctl()'s return value instead. (Also: Some whitespace change in firewire-cdev.h.) Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 11 ++++++----- include/linux/firewire-cdev.h | 37 +++++++++++++---------------------- 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 539dae5eb5b..2784f91896d 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -1214,13 +1214,14 @@ static int ioctl_deallocate_iso_resource_once(struct client *client, void *buffe return init_iso_resource(client, request, ISO_RES_DEALLOC_ONCE); } +/* + * Returns a speed code: Maximum speed to or from this device, + * limited by the device's link speed, the local node's link speed, + * and all PHY port speeds between the two links. + */ static int ioctl_get_speed(struct client *client, void *buffer) { - struct fw_cdev_get_speed *request = buffer; - - request->max_speed = client->device->max_speed; - - return 0; + return client->device->max_speed; } static int ioctl_send_broadcast_request(struct client *client, void *buffer) diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 4dfc84d0ac7..de4035792f7 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -223,28 +223,28 @@ union fw_cdev_event { }; /* available since kernel version 2.6.22 */ -#define FW_CDEV_IOC_GET_INFO _IOWR('#', 0x00, struct fw_cdev_get_info) -#define FW_CDEV_IOC_SEND_REQUEST _IOW('#', 0x01, struct fw_cdev_send_request) -#define FW_CDEV_IOC_ALLOCATE _IOWR('#', 0x02, struct fw_cdev_allocate) -#define FW_CDEV_IOC_DEALLOCATE _IOW('#', 0x03, struct fw_cdev_deallocate) -#define FW_CDEV_IOC_SEND_RESPONSE _IOW('#', 0x04, struct fw_cdev_send_response) -#define FW_CDEV_IOC_INITIATE_BUS_RESET _IOW('#', 0x05, struct fw_cdev_initiate_bus_reset) -#define FW_CDEV_IOC_ADD_DESCRIPTOR _IOWR('#', 0x06, struct fw_cdev_add_descriptor) -#define FW_CDEV_IOC_REMOVE_DESCRIPTOR _IOW('#', 0x07, struct fw_cdev_remove_descriptor) -#define FW_CDEV_IOC_CREATE_ISO_CONTEXT _IOWR('#', 0x08, struct fw_cdev_create_iso_context) -#define FW_CDEV_IOC_QUEUE_ISO _IOWR('#', 0x09, struct fw_cdev_queue_iso) -#define FW_CDEV_IOC_START_ISO _IOW('#', 0x0a, struct fw_cdev_start_iso) -#define FW_CDEV_IOC_STOP_ISO _IOW('#', 0x0b, struct fw_cdev_stop_iso) +#define FW_CDEV_IOC_GET_INFO _IOWR('#', 0x00, struct fw_cdev_get_info) +#define FW_CDEV_IOC_SEND_REQUEST _IOW('#', 0x01, struct fw_cdev_send_request) +#define FW_CDEV_IOC_ALLOCATE _IOWR('#', 0x02, struct fw_cdev_allocate) +#define FW_CDEV_IOC_DEALLOCATE _IOW('#', 0x03, struct fw_cdev_deallocate) +#define FW_CDEV_IOC_SEND_RESPONSE _IOW('#', 0x04, struct fw_cdev_send_response) +#define FW_CDEV_IOC_INITIATE_BUS_RESET _IOW('#', 0x05, struct fw_cdev_initiate_bus_reset) +#define FW_CDEV_IOC_ADD_DESCRIPTOR _IOWR('#', 0x06, struct fw_cdev_add_descriptor) +#define FW_CDEV_IOC_REMOVE_DESCRIPTOR _IOW('#', 0x07, struct fw_cdev_remove_descriptor) +#define FW_CDEV_IOC_CREATE_ISO_CONTEXT _IOWR('#', 0x08, struct fw_cdev_create_iso_context) +#define FW_CDEV_IOC_QUEUE_ISO _IOWR('#', 0x09, struct fw_cdev_queue_iso) +#define FW_CDEV_IOC_START_ISO _IOW('#', 0x0a, struct fw_cdev_start_iso) +#define FW_CDEV_IOC_STOP_ISO _IOW('#', 0x0b, struct fw_cdev_stop_iso) /* available since kernel version 2.6.24 */ -#define FW_CDEV_IOC_GET_CYCLE_TIMER _IOR('#', 0x0c, struct fw_cdev_get_cycle_timer) +#define FW_CDEV_IOC_GET_CYCLE_TIMER _IOR('#', 0x0c, struct fw_cdev_get_cycle_timer) /* available since kernel version 2.6.30 */ #define FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE _IOWR('#', 0x0d, struct fw_cdev_allocate_iso_resource) #define FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE _IOW('#', 0x0e, struct fw_cdev_deallocate) #define FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE _IOW('#', 0x0f, struct fw_cdev_allocate_iso_resource) #define FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE_ONCE _IOW('#', 0x10, struct fw_cdev_allocate_iso_resource) -#define FW_CDEV_IOC_GET_SPEED _IOR('#', 0x11, struct fw_cdev_get_speed) +#define FW_CDEV_IOC_GET_SPEED _IO('#', 0x11) /* returns speed code */ #define FW_CDEV_IOC_SEND_BROADCAST_REQUEST _IOW('#', 0x12, struct fw_cdev_send_request) #define FW_CDEV_IOC_SEND_STREAM_PACKET _IOW('#', 0x13, struct fw_cdev_send_stream_packet) @@ -601,15 +601,6 @@ struct fw_cdev_allocate_iso_resource { __u32 handle; }; -/** - * struct fw_cdev_get_speed - Query maximum speed to or from this device - * @max_speed: Speed code; minimum of the device's link speed, the local node's - * link speed, and all PHY port speeds between the two links - */ -struct fw_cdev_get_speed { - __u32 max_speed; -}; - /** * struct fw_cdev_send_stream_packet - send an asynchronous stream packet * @generation: Bus generation where the packet is valid -- GitLab From de487da8ca5839d057e1f4b57ee3f387e180b800 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 10 Mar 2009 21:00:23 +0100 Subject: [PATCH 4207/4982] firewire: cdev: secure add_descriptor ioctl The access permissions and ownership or ACL of /dev/fw* character device files will typically be set based on the device type of the respective nodes, as obtained by firewire-core from descriptors in the device's configuration ROM. An example policy is to deny write permission by default but grant write permission to files of AV/C video and audio devices and IIDC video devices. The FW_CDEV_IOC_ADD_DESCRIPTOR ioctl could be used to partly subvert such a policy: Find a device file with relaxed permissions, use the ioctl to add a descriptor with AV/C marker to the local node's ROM, thus gain access to the local node's character device file. (This is only possible if there are udev scripts installed which actively relax permissions for known device types and if there is a device of such a type connected.) Accessibility of the local node's device file is relevant to host security if the host contains two or more IEEE 1394 link layer controllers which are plugged into a single bus. Therefore change the ABI to deny FW_CDEV_IOC_ADD_DESCRIPTOR if the file belongs to a remote node. (This change has no impact on known implementers of the ABI: None of them uses the ioctl yet.) Also clarify the documentation: The ioctl affects all local nodes, not just one local node. Cc: stable@kernel.org Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 8 ++++++++ include/linux/firewire-cdev.h | 5 ++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 2784f91896d..160cb27e120 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -742,9 +742,17 @@ static void release_descriptor(struct client *client, static int ioctl_add_descriptor(struct client *client, void *buffer) { struct fw_cdev_add_descriptor *request = buffer; + struct fw_card *card = client->device->card; struct descriptor_resource *r; int ret; + /* Access policy: Allow this ioctl only on local nodes' device files. */ + spin_lock_irq(&card->lock); + ret = client->device->node_id != card->local_node->node_id; + spin_unlock_irq(&card->lock); + if (ret) + return -ENOSYS; + if (request->length > 256) return -EINVAL; diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index de4035792f7..25bc82726ef 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -394,6 +394,9 @@ struct fw_cdev_initiate_bus_reset { * If successful, the kernel adds the descriptor and writes back a handle to the * kernel-side object to be used for later removal of the descriptor block and * immediate key. + * + * This ioctl affects the configuration ROMs of all local nodes. + * The ioctl only succeeds on device files which represent a local node. */ struct fw_cdev_add_descriptor { __u32 immediate; @@ -409,7 +412,7 @@ struct fw_cdev_add_descriptor { * descriptor was added * * Remove a descriptor block and accompanying immediate key from the local - * node's configuration ROM. + * nodes' configuration ROMs. */ struct fw_cdev_remove_descriptor { __u32 handle; -- GitLab From 207fbefb18de9bc6f871e4008da29879c90cb67e Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 10 Mar 2009 21:01:08 +0100 Subject: [PATCH 4208/4982] firewire: cdev: fix race of ioctl_send_request with bus reset The bus reset handler concurrently frees client->device->node. Use device->node_id instead. This is equivalent to device->node->node_id while device->generation is current. Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 160cb27e120..c54e019c958 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -585,7 +585,7 @@ static int ioctl_send_request(struct client *client, void *buffer) return -EINVAL; } - return init_request(client, request, client->device->node->node_id, + return init_request(client, request, client->device->node_id, client->device->max_speed); } -- GitLab From 664d8010b170ae8b3ce9268b4f4da934d27b0491 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 10 Mar 2009 21:01:54 +0100 Subject: [PATCH 4209/4982] firewire: cdev: simplify FW_CDEV_IOC_SEND_REQUEST return value This changes the ioctl() return value of FW_CDEV_IOC_SEND_REQUEST and of the as yet unreleased FW_CDEV_IOC_SEND_BROADCAST_REQUEST. They used to return sizeof(struct fw_cdev_send_request *) + data_length which is obviously a failed attempt to emulate the return value of raw1394's respective interface which uses write() instead of ioctl(). However, the first summand, as size of a kernel pointer, is entirely meaningless to clients and the second summand is already known to clients. And the result does not resemble raw1394's write() return code anyway. So simplify it to a constant non-negative value, i.e. 0. The only dangers here would be that future client implementations check for error by ret != 0 instead of ret < 0 when running on top of an old kernel; or that current clients interpret ret = 0 or more as failure. But both are hypothetical cases which don't justify to return irritating values. While we touch this code, also remove "& 0x1f" from tcode in the call of fw_send_request. The tcode cannot be bigger than 0x1f at this point. Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index c54e019c958..95a207545eb 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -549,15 +549,11 @@ static int init_request(struct client *client, client_get(client); fw_send_request(client->device->card, &e->r.transaction, - request->tcode & 0x1f, destination_id, - request->generation, speed, request->offset, - e->response.data, request->length, - complete_transaction, e); + request->tcode, destination_id, request->generation, + speed, request->offset, e->response.data, + request->length, complete_transaction, e); + return 0; - if (request->data) - return sizeof(request) + request->length; - else - return sizeof(request); failed: kfree(e); -- GitLab From 18e9b10fcdc090d3a38606958167d5923c7099b7 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 10 Mar 2009 21:02:21 +0100 Subject: [PATCH 4210/4982] firewire: cdev: add closure to async stream ioctl This changes the as yet unreleased FW_CDEV_IOC_SEND_STREAM_PACKET ioctl to generate an fw_cdev_event_response event just like the other two ioctls for asynchronous request transmission do. This way, clients get feedback on successful or unsuccessful transmission. This also adds input validation for length, tag, channel, sy, speed. Signed-off-by: Stefan Richter --- drivers/firewire/fw-cdev.c | 46 +++++++++++++------------------ drivers/firewire/fw-transaction.c | 42 +++++++++++----------------- drivers/firewire/fw-transaction.h | 9 +++--- include/linux/firewire-cdev.h | 31 +++++++++++---------- 4 files changed, 56 insertions(+), 72 deletions(-) diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 95a207545eb..7eb6594cc3e 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -522,7 +522,8 @@ static int init_request(struct client *client, struct outbound_transaction_event *e; int ret; - if (request->length > 4096 || request->length > 512 << speed) + if (request->tcode != TCODE_STREAM_DATA && + (request->length > 4096 || request->length > 512 << speed)) return -EIO; e = kmalloc(sizeof(*e) + request->length, GFP_KERNEL); @@ -1247,36 +1248,27 @@ static int ioctl_send_broadcast_request(struct client *client, void *buffer) return init_request(client, request, LOCAL_BUS | 0x3f, SCODE_100); } -struct stream_packet { - struct fw_packet packet; - u8 data[0]; -}; - -static void send_stream_packet_done(struct fw_packet *packet, - struct fw_card *card, int status) -{ - kfree(container_of(packet, struct stream_packet, packet)); -} - static int ioctl_send_stream_packet(struct client *client, void *buffer) { - struct fw_cdev_send_stream_packet *request = buffer; - struct stream_packet *p; + struct fw_cdev_send_stream_packet *p = buffer; + struct fw_cdev_send_request request; + int dest; - p = kmalloc(sizeof(*p) + request->size, GFP_KERNEL); - if (p == NULL) - return -ENOMEM; + if (p->speed > client->device->card->link_speed || + p->length > 1024 << p->speed) + return -EIO; - if (request->data && - copy_from_user(p->data, u64_to_uptr(request->data), request->size)) { - kfree(p); - return -EFAULT; - } - fw_send_stream_packet(client->device->card, &p->packet, - request->generation, request->speed, - request->channel, request->sy, request->tag, - p->data, request->size, send_stream_packet_done); - return 0; + if (p->tag > 3 || p->channel > 63 || p->sy > 15) + return -EINVAL; + + dest = fw_stream_packet_destination_id(p->tag, p->channel, p->sy); + request.tcode = TCODE_STREAM_DATA; + request.length = p->length; + request.closure = p->closure; + request.data = p->data; + request.generation = p->generation; + + return init_request(client, &request, dest, p->speed); } static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index e3da5899196..4a9b37461c2 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -37,10 +37,6 @@ #include "fw-topology.h" #include "fw-device.h" -#define HEADER_TAG(tag) ((tag) << 14) -#define HEADER_CHANNEL(ch) ((ch) << 8) -#define HEADER_SY(sy) ((sy) << 0) - #define HEADER_PRI(pri) ((pri) << 0) #define HEADER_TCODE(tcode) ((tcode) << 4) #define HEADER_RETRY(retry) ((retry) << 8) @@ -158,6 +154,18 @@ static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, { int ext_tcode; + if (tcode == TCODE_STREAM_DATA) { + packet->header[0] = + HEADER_DATA_LENGTH(length) | + destination_id | + HEADER_TCODE(TCODE_STREAM_DATA); + packet->header_length = 4; + packet->payload = payload; + packet->payload_length = length; + + goto common; + } + if (tcode > 0x10) { ext_tcode = tcode & ~0x10; tcode = TCODE_LOCK_REQUEST; @@ -204,7 +212,7 @@ static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, packet->payload_length = 0; break; } - + common: packet->speed = speed; packet->generation = generation; packet->ack = 0; @@ -246,6 +254,9 @@ static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, * @param callback function to be called when the transaction is completed * @param callback_data pointer to arbitrary data, which will be * passed to the callback + * + * In case of asynchronous stream packets i.e. TCODE_STREAM_DATA, the caller + * needs to synthesize @destination_id with fw_stream_packet_destination_id(). */ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, int destination_id, int generation, int speed, @@ -297,27 +308,6 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, } EXPORT_SYMBOL(fw_send_request); -void fw_send_stream_packet(struct fw_card *card, struct fw_packet *p, - int generation, int speed, int channel, int sy, int tag, - void *payload, size_t length, fw_packet_callback_t callback) -{ - p->callback = callback; - p->header[0] = - HEADER_DATA_LENGTH(length) - | HEADER_TAG(tag) - | HEADER_CHANNEL(channel) - | HEADER_TCODE(TCODE_STREAM_DATA) - | HEADER_SY(sy); - p->header_length = 4; - p->payload = payload; - p->payload_length = length; - p->speed = speed; - p->generation = generation; - p->ack = 0; - - card->driver->send_request(card, p); -} - struct transaction_callback_data { struct completion done; void *payload; diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index f90f09c0583..d4f42cecbdf 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -412,10 +412,6 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, int destination_id, int generation, int speed, unsigned long long offset, void *payload, size_t length, fw_transaction_callback_t callback, void *callback_data); -void fw_send_stream_packet(struct fw_card *card, struct fw_packet *p, - int generation, int speed, int channel, int sy, int tag, - void *payload, size_t length, fw_packet_callback_t callback); - int fw_cancel_transaction(struct fw_card *card, struct fw_transaction *transaction); void fw_flush_transactions(struct fw_card *card); @@ -425,6 +421,11 @@ int fw_run_transaction(struct fw_card *card, int tcode, int destination_id, void fw_send_phy_config(struct fw_card *card, int node_id, int generation, int gap_count); +static inline int fw_stream_packet_destination_id(int tag, int channel, int sy) +{ + return tag << 14 | channel << 8 | sy; +} + /* * Called by the topology code to inform the device code of node * activity; found, lost, or updated nodes. diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 25bc82726ef..c6b3ca3af6d 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -606,28 +606,29 @@ struct fw_cdev_allocate_iso_resource { /** * struct fw_cdev_send_stream_packet - send an asynchronous stream packet - * @generation: Bus generation where the packet is valid - * @speed: Speed code to send the packet at - * @channel: Channel to send the packet on - * @sy: Four-bit sy code for the packet - * @tag: Two-bit tag field to use for the packet - * @size: Size of the packet's data payload - * @data: Userspace pointer to the payload + * @length: Length of outgoing payload, in bytes + * @tag: Data format tag + * @channel: Isochronous channel to transmit to + * @sy: Synchronization code + * @closure: Passed back to userspace in the response event + * @data: Userspace pointer to payload + * @generation: The bus generation where packet is valid + * @speed: Speed to transmit at * * The %FW_CDEV_IOC_SEND_STREAM_PACKET ioctl sends an asynchronous stream packet - * to every device (that is listening to the specified channel) on the - * firewire bus. It is the applications's job to ensure - * that the intended device(s) will be able to receive the packet at the chosen - * transmit speed. + * to every device which is listening to the specified channel. The kernel + * writes an &fw_cdev_event_response event which indicates success or failure of + * the transmission. */ struct fw_cdev_send_stream_packet { - __u32 generation; - __u32 speed; + __u32 length; + __u32 tag; __u32 channel; __u32 sy; - __u32 tag; - __u32 size; + __u64 closure; __u64 data; + __u32 generation; + __u32 speed; }; #endif /* _LINUX_FIREWIRE_CDEV_H */ -- GitLab From a38a00fdef98a8eda23a25e54490b32865bc7c33 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 10 Mar 2009 21:07:06 +0100 Subject: [PATCH 4211/4982] firewire: core: drop unused call parameters of close_transaction All callers inserted NULL and 0 here. Signed-off-by: Stefan Richter --- drivers/firewire/fw-transaction.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index 4a9b37461c2..283dac6d327 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -65,8 +65,7 @@ #define PHY_IDENTIFIER(id) ((id) << 30) static int close_transaction(struct fw_transaction *transaction, - struct fw_card *card, int rcode, - u32 *payload, size_t length) + struct fw_card *card, int rcode) { struct fw_transaction *t; unsigned long flags; @@ -82,7 +81,7 @@ static int close_transaction(struct fw_transaction *transaction, spin_unlock_irqrestore(&card->lock, flags); if (&t->link != &card->transaction_list) { - t->callback(card, rcode, payload, length, t->callback_data); + t->callback(card, rcode, NULL, 0, t->callback_data); return 0; } @@ -110,7 +109,7 @@ int fw_cancel_transaction(struct fw_card *card, * if the transaction is still pending and remove it in that case. */ - return close_transaction(transaction, card, RCODE_CANCELLED, NULL, 0); + return close_transaction(transaction, card, RCODE_CANCELLED); } EXPORT_SYMBOL(fw_cancel_transaction); @@ -122,7 +121,7 @@ static void transmit_complete_callback(struct fw_packet *packet, switch (status) { case ACK_COMPLETE: - close_transaction(t, card, RCODE_COMPLETE, NULL, 0); + close_transaction(t, card, RCODE_COMPLETE); break; case ACK_PENDING: t->timestamp = packet->timestamp; @@ -130,20 +129,20 @@ static void transmit_complete_callback(struct fw_packet *packet, case ACK_BUSY_X: case ACK_BUSY_A: case ACK_BUSY_B: - close_transaction(t, card, RCODE_BUSY, NULL, 0); + close_transaction(t, card, RCODE_BUSY); break; case ACK_DATA_ERROR: - close_transaction(t, card, RCODE_DATA_ERROR, NULL, 0); + close_transaction(t, card, RCODE_DATA_ERROR); break; case ACK_TYPE_ERROR: - close_transaction(t, card, RCODE_TYPE_ERROR, NULL, 0); + close_transaction(t, card, RCODE_TYPE_ERROR); break; default: /* * In this case the ack is really a juju specific * rcode, so just forward that to the callback. */ - close_transaction(t, card, status, NULL, 0); + close_transaction(t, card, status); break; } } -- GitLab From e1dc7cab43619a2fbc90fd4cd712bd3fff703768 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 10 Mar 2009 21:07:46 +0100 Subject: [PATCH 4212/4982] firewire: core: increase bus manager grace period Per IEEE 1394 clause 8.4.2.5, bus manager capable nodes which are not incumbent shall wait at least 125ms before trying to establish themselves as bus manager. Signed-off-by: Stefan Richter --- drivers/firewire/fw-card.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index f2b363ea443..b3463b8d8c6 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c @@ -368,9 +368,11 @@ static void fw_card_bm_work(struct work_struct *work) atomic_read(&root_device->state) == FW_DEVICE_RUNNING; root_device_is_cmc = root_device && root_device->cmc; root_id = root_node->node_id; - grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 10)); irm_device = irm_node->data; local_device = local_node->data; + + grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 8)); + if (is_next_generation(generation, card->bm_generation) || (card->bm_generation != generation && grace)) { /* @@ -434,12 +436,11 @@ static void fw_card_bm_work(struct work_struct *work) } } else if (card->bm_generation != generation) { /* - * OK, we weren't BM in the last generation, and it's - * less than 100ms since last bus reset. Reschedule - * this task 100ms from now. + * We weren't BM in the last generation, and the last + * bus reset is less than 125ms ago. Reschedule this job. */ spin_unlock_irqrestore(&card->lock, flags); - fw_schedule_bm_work(card, DIV_ROUND_UP(HZ, 10)); + fw_schedule_bm_work(card, DIV_ROUND_UP(HZ, 8)); goto out; } -- GitLab From cbae787c0f288c3ad385ad4165ae30b5500a1f23 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 10 Mar 2009 21:08:37 +0100 Subject: [PATCH 4213/4982] firewire: core: simplify broadcast channel allocation fw-iso.c has channel allocation code now, use it. Signed-off-by: Stefan Richter --- drivers/firewire/fw-card.c | 126 ++++++++++--------------------------- 1 file changed, 34 insertions(+), 92 deletions(-) diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index b3463b8d8c6..d63d0ed9e04 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c @@ -181,10 +181,6 @@ void fw_core_remove_descriptor(struct fw_descriptor *desc) mutex_unlock(&card_mutex); } -/* ------------------------------------------------------------------ */ -/* Code to handle 1394a broadcast channel */ - -#define THIRTY_TWO_CHANNELS (0xFFFFFFFFU) #define IRM_RETRIES 2 /* @@ -265,62 +261,18 @@ tryagain_w: return 0; } -static void -irm_allocate_broadcast(struct fw_device *irm_dev, struct device *locald) +static void allocate_broadcast_channel(struct fw_card *card, int generation) { - u32 generation; - u32 node_id; - u32 max_speed; - u32 retries; - __be32 old_data; - __be32 lock_data[2]; - int rcode; - - /* - * The device we are updating is the IRM, so we must do - * some extra work. - */ - retries = IRM_RETRIES; - generation = irm_dev->generation; - /* FIXME: do we need locking here? */ - smp_rmb(); - node_id = irm_dev->node_id; - max_speed = irm_dev->max_speed; - - lock_data[0] = cpu_to_be32(THIRTY_TWO_CHANNELS); - lock_data[1] = cpu_to_be32(THIRTY_TWO_CHANNELS & ~1); -tryagain: - old_data = lock_data[0]; - rcode = fw_run_transaction(irm_dev->card, TCODE_LOCK_COMPARE_SWAP, - node_id, generation, max_speed, - CSR_REGISTER_BASE+CSR_CHANNELS_AVAILABLE_HI, - &lock_data[0], 8); - switch (rcode) { - case RCODE_BUSY: - if (retries--) - goto tryagain; - /* fallthrough */ - default: - fw_error("node %x: allocate broadcast channel failed (%x)\n", - node_id, rcode); - return; - - case RCODE_COMPLETE: - if (lock_data[0] == old_data) - break; - if (retries--) { - lock_data[1] = cpu_to_be32(be32_to_cpu(lock_data[0])&~1); - goto tryagain; - } - fw_error("node %x: allocate broadcast channel failed: too many" - " retries\n", node_id); - return; + int channel, bandwidth = 0; + + fw_iso_resource_manage(card, generation, 1ULL << 31, + &channel, &bandwidth, true); + if (channel == 31) { + card->is_irm = true; + device_for_each_child(card->device, NULL, + fw_irm_set_broadcast_channel_register); } - irm_dev->card->is_irm = true; - device_for_each_child(locald, NULL, fw_irm_set_broadcast_channel_register); } -/* ------------------------------------------------------------------ */ - static const char gap_count_table[] = { 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40 @@ -339,10 +291,11 @@ void fw_schedule_bm_work(struct fw_card *card, unsigned long delay) static void fw_card_bm_work(struct work_struct *work) { struct fw_card *card = container_of(work, struct fw_card, work.work); - struct fw_device *root_device, *irm_device, *local_device; - struct fw_node *root_node, *local_node, *irm_node; + struct fw_device *root_device; + struct fw_node *root_node; unsigned long flags; - int root_id, new_root_id, irm_id, gap_count, generation, grace, rcode; + int root_id, new_root_id, irm_id, local_id; + int gap_count, generation, grace, rcode; bool do_reset = false; bool root_device_is_running; bool root_device_is_cmc; @@ -350,26 +303,22 @@ static void fw_card_bm_work(struct work_struct *work) spin_lock_irqsave(&card->lock, flags); card->is_irm = false; - local_node = card->local_node; - root_node = card->root_node; - irm_node = card->irm_node; - if (local_node == NULL) { + if (card->local_node == NULL) { spin_unlock_irqrestore(&card->lock, flags); goto out_put_card; } - fw_node_get(local_node); - fw_node_get(root_node); - fw_node_get(irm_node); generation = card->generation; + root_node = card->root_node; + fw_node_get(root_node); root_device = root_node->data; root_device_is_running = root_device && atomic_read(&root_device->state) == FW_DEVICE_RUNNING; root_device_is_cmc = root_device && root_device->cmc; - root_id = root_node->node_id; - irm_device = irm_node->data; - local_device = local_node->data; + root_id = root_node->node_id; + irm_id = card->irm_node->node_id; + local_id = card->local_node->node_id; grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 8)); @@ -387,16 +336,15 @@ static void fw_card_bm_work(struct work_struct *work) * next generation. */ - irm_id = irm_node->node_id; - if (!irm_node->link_on) { - new_root_id = local_node->node_id; + if (!card->irm_node->link_on) { + new_root_id = local_id; fw_notify("IRM has link off, making local node (%02x) root.\n", new_root_id); goto pick_me; } lock_data[0] = cpu_to_be32(0x3f); - lock_data[1] = cpu_to_be32(local_node->node_id); + lock_data[1] = cpu_to_be32(local_id); spin_unlock_irqrestore(&card->lock, flags); @@ -411,12 +359,11 @@ static void fw_card_bm_work(struct work_struct *work) if (rcode == RCODE_COMPLETE && lock_data[0] != cpu_to_be32(0x3f)) { - /* Somebody else is BM, let them do the work. */ - if (irm_id == local_node->node_id) { - /* But we are IRM, so do irm-y things */ - irm_allocate_broadcast(irm_device, - card->device); - } + + /* Somebody else is BM. Only act as IRM. */ + if (local_id == irm_id) + allocate_broadcast_channel(card, generation); + goto out; } @@ -429,7 +376,7 @@ static void fw_card_bm_work(struct work_struct *work) * do a bus reset and pick the local node as * root, and thus, IRM. */ - new_root_id = local_node->node_id; + new_root_id = local_id; fw_notify("BM lock failed, making local node (%02x) root.\n", new_root_id); goto pick_me; @@ -456,7 +403,7 @@ static void fw_card_bm_work(struct work_struct *work) * Either link_on is false, or we failed to read the * config rom. In either case, pick another root. */ - new_root_id = local_node->node_id; + new_root_id = local_id; } else if (!root_device_is_running) { /* * If we haven't probed this device yet, bail out now @@ -478,7 +425,7 @@ static void fw_card_bm_work(struct work_struct *work) * successfully read the config rom, but it's not * cycle master capable. */ - new_root_id = local_node->node_id; + new_root_id = local_id; } pick_me: @@ -509,19 +456,14 @@ static void fw_card_bm_work(struct work_struct *work) card->index, new_root_id, gap_count); fw_send_phy_config(card, new_root_id, generation, gap_count); fw_core_initiate_bus_reset(card, 1); - } else if (irm_node->node_id == local_node->node_id) { - /* - * We are IRM, so do irm-y things. - * There's no reason to do this if we're doing a reset. . . - * We'll be back. - */ - irm_allocate_broadcast(irm_device, card->device); + /* Will allocate broadcast channel after the reset. */ + } else { + if (local_id == irm_id) + allocate_broadcast_channel(card, generation); } out: fw_node_put(root_node); - fw_node_put(local_node); - fw_node_put(irm_node); out_put_card: fw_card_put(card); } -- GitLab From 7889b60ee71eafaf50699a154a2455424bb92daa Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 10 Mar 2009 21:09:28 +0100 Subject: [PATCH 4214/4982] firewire: core: optimize propagation of BROADCAST_CHANNEL Cache the test result of whether a device implements BROADCAST_CHANNEL. This minimizes traffic on the bus after each bus reset. A majority of devices does not implement BROADCAST_CHANNEL. Remove busy retries; just rely on the hardware to retry requests to busy responders. Remove unnecessary log messages. Rename the flag is_irm to broadcast_channel_allocated to better reflect its meaning. Reset the flag earlier in fw_core_handle_bus_reset. Pass the generation down as a call parameter; that way generation can't be newer than card->broadcast_channel_allocated and device->node_id. Signed-off-by: Stefan Richter --- drivers/firewire/fw-card.c | 85 ++----------------------------- drivers/firewire/fw-device.c | 45 ++++++++++++++-- drivers/firewire/fw-device.h | 5 +- drivers/firewire/fw-topology.c | 1 + drivers/firewire/fw-transaction.h | 6 +-- 5 files changed, 52 insertions(+), 90 deletions(-) diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index d63d0ed9e04..8b8c8c22f0f 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c @@ -181,83 +181,9 @@ void fw_core_remove_descriptor(struct fw_descriptor *desc) mutex_unlock(&card_mutex); } -#define IRM_RETRIES 2 - -/* - * The abi is set by device_for_each_child(), even though we have no use - * for data, nor do we have a meaningful return value. - */ -int fw_irm_set_broadcast_channel_register(struct device *dev, void *data) +static int set_broadcast_channel(struct device *dev, void *data) { - struct fw_device *d; - int rcode; - int node_id; - int max_speed; - int retries; - int generation; - __be32 regval; - struct fw_card *card; - - d = fw_device(dev); - /* FIXME: do we need locking here? */ - generation = d->generation; - smp_rmb(); /* Ensure generation is at least as old as node_id */ - node_id = d->node_id; - max_speed = d->max_speed; - retries = IRM_RETRIES; - card = d->card; -tryagain_r: - rcode = fw_run_transaction(card, TCODE_READ_QUADLET_REQUEST, - node_id, generation, max_speed, - CSR_REGISTER_BASE + CSR_BROADCAST_CHANNEL, - ®val, 4); - switch (rcode) { - case RCODE_BUSY: - if (retries--) - goto tryagain_r; - fw_notify("node %x read broadcast channel busy\n", - node_id); - return 0; - - default: - fw_notify("node %x read broadcast channel failed %x\n", - node_id, rcode); - return 0; - - case RCODE_COMPLETE: - /* - * Paranoid reporting of nonstandard broadcast channel - * contents goes here - */ - if (regval != cpu_to_be32(BROADCAST_CHANNEL_INITIAL)) - return 0; - break; - } - retries = IRM_RETRIES; - regval = cpu_to_be32(BROADCAST_CHANNEL_INITIAL | - BROADCAST_CHANNEL_VALID); -tryagain_w: - rcode = fw_run_transaction(card, - TCODE_WRITE_QUADLET_REQUEST, node_id, - generation, max_speed, - CSR_REGISTER_BASE + CSR_BROADCAST_CHANNEL, - ®val, 4); - switch (rcode) { - case RCODE_BUSY: - if (retries--) - goto tryagain_w; - fw_notify("node %x write broadcast channel busy\n", - node_id); - return 0; - - default: - fw_notify("node %x write broadcast channel failed %x\n", - node_id, rcode); - return 0; - - case RCODE_COMPLETE: - return 0; - } + fw_device_set_broadcast_channel(fw_device(dev), (long)data); return 0; } @@ -268,9 +194,9 @@ static void allocate_broadcast_channel(struct fw_card *card, int generation) fw_iso_resource_manage(card, generation, 1ULL << 31, &channel, &bandwidth, true); if (channel == 31) { - card->is_irm = true; - device_for_each_child(card->device, NULL, - fw_irm_set_broadcast_channel_register); + card->broadcast_channel_allocated = true; + device_for_each_child(card->device, (void *)(long)generation, + set_broadcast_channel); } } @@ -302,7 +228,6 @@ static void fw_card_bm_work(struct work_struct *work) __be32 lock_data[2]; spin_lock_irqsave(&card->lock, flags); - card->is_irm = false; if (card->local_node == NULL) { spin_unlock_irqrestore(&card->lock, flags); diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index a40444e8eb2..a47e2129d83 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c @@ -518,7 +518,7 @@ static int read_bus_info_block(struct fw_device *device, int generation) kfree(old_rom); ret = 0; - device->cmc = rom[2] & 1 << 30; + device->cmc = rom[2] >> 30 & 1; out: kfree(rom); @@ -756,6 +756,44 @@ static int lookup_existing_device(struct device *dev, void *data) return match; } +enum { BC_UNKNOWN = 0, BC_UNIMPLEMENTED, BC_IMPLEMENTED, }; + +void fw_device_set_broadcast_channel(struct fw_device *device, int generation) +{ + struct fw_card *card = device->card; + __be32 data; + int rcode; + + if (!card->broadcast_channel_allocated) + return; + + if (device->bc_implemented == BC_UNKNOWN) { + rcode = fw_run_transaction(card, TCODE_READ_QUADLET_REQUEST, + device->node_id, generation, device->max_speed, + CSR_REGISTER_BASE + CSR_BROADCAST_CHANNEL, + &data, 4); + switch (rcode) { + case RCODE_COMPLETE: + if (data & cpu_to_be32(1 << 31)) { + device->bc_implemented = BC_IMPLEMENTED; + break; + } + /* else fall through to case address error */ + case RCODE_ADDRESS_ERROR: + device->bc_implemented = BC_UNIMPLEMENTED; + } + } + + if (device->bc_implemented == BC_IMPLEMENTED) { + data = cpu_to_be32(BROADCAST_CHANNEL_INITIAL | + BROADCAST_CHANNEL_VALID); + fw_run_transaction(card, TCODE_WRITE_QUADLET_REQUEST, + device->node_id, generation, device->max_speed, + CSR_REGISTER_BASE + CSR_BROADCAST_CHANNEL, + &data, 4); + } +} + static void fw_device_init(struct work_struct *work) { struct fw_device *device = @@ -849,9 +887,8 @@ static void fw_device_init(struct work_struct *work) device->config_rom[3], device->config_rom[4], 1 << device->max_speed); device->config_rom_retries = 0; - if (device->card->is_irm) - fw_irm_set_broadcast_channel_register(&device->device, - NULL); + + fw_device_set_broadcast_channel(device, device->generation); } /* diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h index 3085a74669b..97588937c01 100644 --- a/drivers/firewire/fw-device.h +++ b/drivers/firewire/fw-device.h @@ -71,7 +71,6 @@ struct fw_device { int node_id; int generation; unsigned max_speed; - bool cmc; struct fw_card *card; struct device device; @@ -81,6 +80,9 @@ struct fw_device { u32 *config_rom; size_t config_rom_length; int config_rom_retries; + unsigned cmc:1; + unsigned bc_implemented:2; + struct delayed_work work; struct fw_attribute_group attribute_group; }; @@ -109,6 +111,7 @@ static inline void fw_device_put(struct fw_device *device) struct fw_device *fw_device_get_by_devt(dev_t devt); int fw_device_enable_phys_dma(struct fw_device *device); +void fw_device_set_broadcast_channel(struct fw_device *device, int generation); void fw_device_cdev_update(struct fw_device *device); void fw_device_cdev_remove(struct fw_device *device); diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c index b44131cf0c6..d0deecc4de9 100644 --- a/drivers/firewire/fw-topology.c +++ b/drivers/firewire/fw-topology.c @@ -526,6 +526,7 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation, spin_lock_irqsave(&card->lock, flags); + card->broadcast_channel_allocated = false; card->node_id = node_id; /* * Update node_id before generation to prevent anybody from using diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index d4f42cecbdf..dfa799068f8 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -230,11 +230,6 @@ struct fw_card { u8 color; /* must be u8 to match the definition in struct fw_node */ int gap_count; bool beta_repeaters_present; - /* - * Set if the local device is the IRM and the broadcast channel - * was allocated. - */ - bool is_irm; int index; @@ -245,6 +240,7 @@ struct fw_card { int bm_retries; int bm_generation; + bool broadcast_channel_allocated; u32 broadcast_channel; u32 topology_map[(CSR_TOPOLOGY_MAP_END - CSR_TOPOLOGY_MAP) / 4]; }; -- GitLab From e90874f64c89d8a3a8b287f67c5655141720c28d Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 24 Jan 2009 19:41:46 +0100 Subject: [PATCH 4215/4982] ieee1394: sbp2: follow up on "ieee1394: inherit ud vendor_id from node vendor_id" Signed-off-by: Stefan Richter --- drivers/ieee1394/sbp2.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index f3fd8657ce4..02255a8a1c8 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -1413,8 +1413,7 @@ static void sbp2_parse_unit_directory(struct sbp2_lu *lu, "(firmware_revision 0x%06x, vendor_id 0x%06x," " model_id 0x%06x)", NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid), - workarounds, firmware_revision, - ud->vendor_id ? ud->vendor_id : ud->ne->vendor_id, + workarounds, firmware_revision, ud->vendor_id, model); /* We would need one SCSI host template for each target to adjust -- GitLab From 1c4fb577aa5aeeace026d8295936947f0f0743f0 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 9 Feb 2009 22:05:06 +0100 Subject: [PATCH 4216/4982] ieee1394: Storage class should be before const qualifier The C99 specification states in section 6.11.5: The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature. Signed-off-by: Tobias Klauser Signed-off-by: Stefan Richter --- drivers/ieee1394/csr.c | 8 ++++---- drivers/ieee1394/eth1394.c | 2 +- drivers/ieee1394/highlevel.c | 2 +- drivers/ieee1394/raw1394.c | 2 +- drivers/ieee1394/sbp2.c | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/ieee1394/csr.c b/drivers/ieee1394/csr.c index 31400c8ae05..d696f69ebce 100644 --- a/drivers/ieee1394/csr.c +++ b/drivers/ieee1394/csr.c @@ -68,22 +68,22 @@ static struct hpsb_highlevel csr_highlevel = { .host_reset = host_reset, }; -const static struct hpsb_address_ops map_ops = { +static const struct hpsb_address_ops map_ops = { .read = read_maps, }; -const static struct hpsb_address_ops fcp_ops = { +static const struct hpsb_address_ops fcp_ops = { .write = write_fcp, }; -const static struct hpsb_address_ops reg_ops = { +static const struct hpsb_address_ops reg_ops = { .read = read_regs, .write = write_regs, .lock = lock_regs, .lock64 = lock64_regs, }; -const static struct hpsb_address_ops config_rom_ops = { +static const struct hpsb_address_ops config_rom_ops = { .read = read_config_rom, }; diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index 1a919df809f..0ed0f80c7cb 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -181,7 +181,7 @@ static void ether1394_remove_host(struct hpsb_host *host); static void ether1394_host_reset(struct hpsb_host *host); /* Function for incoming 1394 packets */ -const static struct hpsb_address_ops addr_ops = { +static const struct hpsb_address_ops addr_ops = { .write = ether1394_write, }; diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c index 600e391c8fe..4bc443546e0 100644 --- a/drivers/ieee1394/highlevel.c +++ b/drivers/ieee1394/highlevel.c @@ -478,7 +478,7 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, return retval; } -const static struct hpsb_address_ops dummy_ops; +static const struct hpsb_address_ops dummy_ops; /* dummy address spaces as lower and upper bounds of the host's a.s. list */ static void init_hpsb_highlevel(struct hpsb_host *host) diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index bad66c65b0d..281229b027f 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -90,7 +90,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags); -const static struct hpsb_address_ops arm_ops = { +static const struct hpsb_address_ops arm_ops = { .read = arm_read, .write = arm_write, .lock = arm_lock, diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 02255a8a1c8..092fbf087b0 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -265,7 +265,7 @@ static struct hpsb_highlevel sbp2_highlevel = { .host_reset = sbp2_host_reset, }; -const static struct hpsb_address_ops sbp2_ops = { +static const struct hpsb_address_ops sbp2_ops = { .write = sbp2_handle_status_write }; @@ -275,7 +275,7 @@ static int sbp2_handle_physdma_write(struct hpsb_host *, int, int, quadlet_t *, static int sbp2_handle_physdma_read(struct hpsb_host *, int, quadlet_t *, u64, size_t, u16); -const static struct hpsb_address_ops sbp2_physdma_ops = { +static const struct hpsb_address_ops sbp2_physdma_ops = { .read = sbp2_handle_physdma_read, .write = sbp2_handle_physdma_write, }; -- GitLab From 421696887b0da241401710e83b0dffcc195bc484 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 15 Feb 2009 22:49:24 +0100 Subject: [PATCH 4217/4982] ieee1394: raw1394: add sparse annotations to raw1394_compat_write Eliminate the following warnings in raw1394_compat_write()'s error return path, seen on x86-64 with CONFIG_COMPAT=y: drivers/ieee1394/raw1394.c:381:17: warning: incorrect type in return expression (different address spaces) drivers/ieee1394/raw1394.c:381:17: expected char const [noderef] * drivers/ieee1394/raw1394.c:381:17: got void * drivers/ieee1394/raw1394.c:2252:14: warning: incorrect type in argument 1 (different address spaces) drivers/ieee1394/raw1394.c:2252:14: expected void const *ptr drivers/ieee1394/raw1394.c:2252:14: got char const [noderef] *[assigned] buffer drivers/ieee1394/raw1394.c:2253:19: warning: incorrect type in argument 1 (different address spaces) drivers/ieee1394/raw1394.c:2253:19: expected void const *ptr drivers/ieee1394/raw1394.c:2253:19: got char const [noderef] *[assigned] buffer Signed-off-by: Stefan Richter --- drivers/ieee1394/raw1394.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index 281229b027f..9b71390b0a0 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -369,6 +369,7 @@ static const char __user *raw1394_compat_write(const char __user *buf) { struct compat_raw1394_req __user *cr = (typeof(cr)) buf; struct raw1394_request __user *r; + r = compat_alloc_user_space(sizeof(struct raw1394_request)); #define C(x) __copy_in_user(&r->x, &cr->x, sizeof(r->x)) @@ -378,7 +379,8 @@ static const char __user *raw1394_compat_write(const char __user *buf) C(tag) || C(sendb) || C(recvb)) - return ERR_PTR(-EFAULT); + return (__force const char __user *)ERR_PTR(-EFAULT); + return (const char __user *)r; } #undef C @@ -389,6 +391,7 @@ static int raw1394_compat_read(const char __user *buf, struct raw1394_request *r) { struct compat_raw1394_req __user *cr = (typeof(cr)) buf; + if (!access_ok(VERIFY_WRITE, cr, sizeof(struct compat_raw1394_req)) || P(type) || P(error) || @@ -400,6 +403,7 @@ raw1394_compat_read(const char __user *buf, struct raw1394_request *r) P(sendb) || P(recvb)) return -EFAULT; + return sizeof(struct compat_raw1394_req); } #undef P @@ -2249,8 +2253,8 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer, sizeof(struct compat_raw1394_req) != sizeof(struct raw1394_request)) { buffer = raw1394_compat_write(buffer); - if (IS_ERR(buffer)) - return PTR_ERR(buffer); + if (IS_ERR((__force void *)buffer)) + return PTR_ERR((__force void *)buffer); } else #endif if (count != sizeof(struct raw1394_request)) { -- GitLab From c64094684dad4a903099f1ff83b7db9b62782adc Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 15 Feb 2009 23:11:38 +0100 Subject: [PATCH 4218/4982] ieee1394: constify device ID tables Signed-off-by: Stefan Richter --- drivers/ieee1394/dv1394.c | 2 +- drivers/ieee1394/eth1394.c | 2 +- drivers/ieee1394/nodemgr.c | 4 ++-- drivers/ieee1394/nodemgr.h | 2 +- drivers/ieee1394/raw1394.c | 2 +- drivers/ieee1394/sbp2.c | 2 +- drivers/ieee1394/video1394.c | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index 3838bc4acab..4c2c02572d2 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c @@ -2175,7 +2175,7 @@ static const struct file_operations dv1394_fops= * Export information about protocols/devices supported by this driver. */ #ifdef MODULE -static struct ieee1394_device_id dv1394_id_table[] = { +static const struct ieee1394_device_id dv1394_id_table[] = { { .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff, diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index 0ed0f80c7cb..4ca103577c0 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -438,7 +438,7 @@ static int eth1394_update(struct unit_directory *ud) return eth1394_new_node(hi, ud); } -static struct ieee1394_device_id eth1394_id_table[] = { +static const struct ieee1394_device_id eth1394_id_table[] = { { .match_flags = (IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION), diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 53aada5bbe1..a6d55bebe61 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -484,7 +484,7 @@ static struct device_attribute *const fw_host_attrs[] = { static ssize_t fw_show_drv_device_ids(struct device_driver *drv, char *buf) { struct hpsb_protocol_driver *driver; - struct ieee1394_device_id *id; + const struct ieee1394_device_id *id; int length = 0; char *scratch = buf; @@ -658,7 +658,7 @@ static int nodemgr_bus_match(struct device * dev, struct device_driver * drv) { struct hpsb_protocol_driver *driver; struct unit_directory *ud; - struct ieee1394_device_id *id; + const struct ieee1394_device_id *id; /* We only match unit directories */ if (dev->platform_data != &nodemgr_ud_platform_data) diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h index ee5acdbd114..749b271d310 100644 --- a/drivers/ieee1394/nodemgr.h +++ b/drivers/ieee1394/nodemgr.h @@ -125,7 +125,7 @@ struct hpsb_protocol_driver { * probe function below can implement further protocol * dependent or vendor dependent checking. */ - struct ieee1394_device_id *id_table; + const struct ieee1394_device_id *id_table; /* * The update function is called when the node has just diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index 9b71390b0a0..da5f8829b50 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -2982,7 +2982,7 @@ static int raw1394_release(struct inode *inode, struct file *file) * Export information about protocols/devices supported by this driver. */ #ifdef MODULE -static struct ieee1394_device_id raw1394_id_table[] = { +static const struct ieee1394_device_id raw1394_id_table[] = { { .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff, diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 092fbf087b0..a51ab233342 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -285,7 +285,7 @@ static const struct hpsb_address_ops sbp2_physdma_ops = { /* * Interface to driver core and IEEE 1394 core */ -static struct ieee1394_device_id sbp2_id_table[] = { +static const struct ieee1394_device_id sbp2_id_table[] = { { .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, .specifier_id = SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff, diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c index 679a918a5cc..d287ba79821 100644 --- a/drivers/ieee1394/video1394.c +++ b/drivers/ieee1394/video1394.c @@ -1294,7 +1294,7 @@ static const struct file_operations video1394_fops= * Export information about protocols/devices supported by this driver. */ #ifdef MODULE -static struct ieee1394_device_id video1394_id_table[] = { +static const struct ieee1394_device_id video1394_id_table[] = { { .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, -- GitLab From 40cf65d149053889c8876c6c2b4ce204fde55baa Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Thu, 5 Mar 2009 19:13:43 +0100 Subject: [PATCH 4219/4982] DVB: firedtv: fix printk format mismatch Eliminate drivers/media/dvb/firewire/firedtv-avc.c: In function 'debug_fcp': drivers/media/dvb/firewire/firedtv-avc.c:156: warning: format '%d' expects type 'int', but argument 5 has type 'size_t' Acked-by: Mauro Carvalho Chehab Signed-off-by: Stefan Richter --- drivers/media/dvb/firewire/firedtv-avc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c index b55d9ccaf33..1a300f00e0f 100644 --- a/drivers/media/dvb/firewire/firedtv-avc.c +++ b/drivers/media/dvb/firewire/firedtv-avc.c @@ -115,7 +115,7 @@ static const char *debug_fcp_ctype(unsigned int ctype) } static const char *debug_fcp_opcode(unsigned int opcode, - const u8 *data, size_t length) + const u8 *data, int length) { switch (opcode) { case AVC_OPCODE_VENDOR: break; @@ -141,7 +141,7 @@ static const char *debug_fcp_opcode(unsigned int opcode, return "Vendor"; } -static void debug_fcp(const u8 *data, size_t length) +static void debug_fcp(const u8 *data, int length) { unsigned int subunit_type, subunit_id, op; const char *prefix = data[0] > 7 ? "FCP <- " : "FCP -> "; -- GitLab From 142071b83426674ef2dab98cf2a6627328d0988e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 24 Mar 2009 13:19:50 -0700 Subject: [PATCH 4220/4982] dnet: drivers/net/dnet.c needs On m68k: | drivers/net/dnet.c: In function 'dnet_readw_mac': | drivers/net/dnet.c:36: error: implicit declaration of function 'writel' | drivers/net/dnet.c:43: error: implicit declaration of function 'readl' | drivers/net/dnet.c: In function 'dnet_probe': | drivers/net/dnet.c:873: error: implicit declaration of function 'ioremap' | drivers/net/dnet.c:873: warning: assignment makes pointer from integer without a cast | drivers/net/dnet.c:939: error: implicit declaration of function 'iounmap' Signed-off-by: Geert Uytterhoeven Signed-off-by: David S. Miller --- drivers/net/dnet.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c index 1b4063222a8..edf23c9ea63 100644 --- a/drivers/net/dnet.c +++ b/drivers/net/dnet.c @@ -9,6 +9,7 @@ * published by the Free Software Foundation. */ #include +#include #include #include #include -- GitLab From 8dd1d0471bcf634f2cd6a6cf4b6531bb61f0af47 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 24 Mar 2009 13:35:27 -0700 Subject: [PATCH 4221/4982] netfilter: trivial Kconfig spelling fixes Supplements commit 67c0d57930ff9a24c6c34abee1b01f7716a9b0e2. Signed-off-by: Jan Engelhardt Signed-off-by: David S. Miller --- net/ipv6/netfilter/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 625353a5fe1..29d643bcafa 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig @@ -101,7 +101,7 @@ config IP6_NF_MATCH_HL ---help--- This is a backwards-compat option for the user's convenience (e.g. when running oldconfig). It selects - COFNIG_NETFILTER_XT_MATCH_HL. + CONFIG_NETFILTER_XT_MATCH_HL. config IP6_NF_MATCH_IPV6HEADER tristate '"ipv6header" IPv6 Extension Headers Match' @@ -137,7 +137,7 @@ config IP6_NF_TARGET_HL ---help--- This is a backwards-compat option for the user's convenience (e.g. when running oldconfig). It selects - COFNIG_NETFILTER_XT_TARGET_HL. + CONFIG_NETFILTER_XT_TARGET_HL. config IP6_NF_TARGET_LOG tristate "LOG target support" -- GitLab From 35c7f6de7339f40a591a8aeccacdc429b1953674 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 24 Mar 2009 14:15:22 -0700 Subject: [PATCH 4222/4982] arp_tables: ifname_compare() can assume 16bit alignment Arches without efficient unaligned access can still perform a loop assuming 16bit alignment in ifname_compare() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/netfilter/arp_tables.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 64a7c6ce0b9..84b9c179df5 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -76,6 +76,7 @@ static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, /* * Unfortunatly, _b and _mask are not aligned to an int (or long int) * Some arches dont care, unrolling the loop is a win on them. + * For other arches, we only have a 16bit alignement. */ static unsigned long ifname_compare(const char *_a, const char *_b, const char *_mask) { @@ -95,10 +96,13 @@ static unsigned long ifname_compare(const char *_a, const char *_b, const char * BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long)); #else unsigned long ret = 0; + const u16 *a = (const u16 *)_a; + const u16 *b = (const u16 *)_b; + const u16 *mask = (const u16 *)_mask; int i; - for (i = 0; i < IFNAMSIZ; i++) - ret |= (_a[i] ^ _b[i]) & _mask[i]; + for (i = 0; i < IFNAMSIZ/sizeof(u16); i++) + ret |= (a[i] ^ b[i]) & mask[i]; #endif return ret; } -- GitLab From 5393f3162d3a85317e1e22c33539905fa5258e5f Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 24 Mar 2009 09:44:28 +0000 Subject: [PATCH 4223/4982] net: Add dependent headers to trace/skb.h The tracing header needs to include definitions for the macros used and the types referenced. This lets automated tracing tools like SystemTap make use of the tracepoint without any specific knowledge of its meaning (leaving that to the user). Signed-off-by: Josh Stone CC: Neil Horman Signed-off-by: David S. Miller --- include/trace/skb.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/trace/skb.h b/include/trace/skb.h index 3aa864697c0..a96610f92f6 100644 --- a/include/trace/skb.h +++ b/include/trace/skb.h @@ -1,6 +1,9 @@ #ifndef _TRACE_SKB_H_ #define _TRACE_SKB_H_ +#include +#include + DECLARE_TRACE(kfree_skb, TPPROTO(struct sk_buff *skb, void *location), TPARGS(skb, location)); -- GitLab From 67aa0f767af488a7f1e41cccb4f7a4893f24a1ab Mon Sep 17 00:00:00 2001 From: Luis Henriques Date: Tue, 24 Mar 2009 22:10:02 +0000 Subject: [PATCH 4224/4982] sched: remove unused fields from struct rq Impact: cleanup, new schedstat ABI Since they are used on in statistics and are always set to zero, the following fields from struct rq have been removed: yld_exp_empty, yld_act_empty and yld_both_empty. Both Sched Debug and SCHEDSTAT_VERSION versions has also been incremented since ABIs have been changed. The schedtop tool has been updated to properly handle new version of schedstat: http://rt.wiki.kernel.org/index.php/Schedtop_utility Signed-off-by: Luis Henriques Acked-by: Gregory Haskins Acked-by: Peter Zijlstra LKML-Reference: <20090324221002.GA10061@hades.domain.com> Signed-off-by: Ingo Molnar --- kernel/sched.c | 3 --- kernel/sched_debug.c | 5 +---- kernel/sched_stats.h | 7 +++---- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index d2dfe4c1a22..7b389c74f8f 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -638,9 +638,6 @@ struct rq { /* could above be rq->cfs_rq.exec_clock + rq->rt_rq.rt_runtime ? */ /* sys_sched_yield() stats */ - unsigned int yld_exp_empty; - unsigned int yld_act_empty; - unsigned int yld_both_empty; unsigned int yld_count; /* schedule() stats */ diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c index 4daebffa056..467ca72f165 100644 --- a/kernel/sched_debug.c +++ b/kernel/sched_debug.c @@ -286,9 +286,6 @@ static void print_cpu(struct seq_file *m, int cpu) #ifdef CONFIG_SCHEDSTATS #define P(n) SEQ_printf(m, " .%-30s: %d\n", #n, rq->n); - P(yld_exp_empty); - P(yld_act_empty); - P(yld_both_empty); P(yld_count); P(sched_switch); @@ -313,7 +310,7 @@ static int sched_debug_show(struct seq_file *m, void *v) u64 now = ktime_to_ns(ktime_get()); int cpu; - SEQ_printf(m, "Sched Debug Version: v0.08, %s %.*s\n", + SEQ_printf(m, "Sched Debug Version: v0.09, %s %.*s\n", init_utsname()->release, (int)strcspn(init_utsname()->version, " "), init_utsname()->version); diff --git a/kernel/sched_stats.h b/kernel/sched_stats.h index a8f93dd374e..32d2bd4061b 100644 --- a/kernel/sched_stats.h +++ b/kernel/sched_stats.h @@ -4,7 +4,7 @@ * bump this up when changing the output format or the meaning of an existing * format, so that tools can adapt (or abort) */ -#define SCHEDSTAT_VERSION 14 +#define SCHEDSTAT_VERSION 15 static int show_schedstat(struct seq_file *seq, void *v) { @@ -26,9 +26,8 @@ static int show_schedstat(struct seq_file *seq, void *v) /* runqueue-specific stats */ seq_printf(seq, - "cpu%d %u %u %u %u %u %u %u %u %u %llu %llu %lu", - cpu, rq->yld_both_empty, - rq->yld_act_empty, rq->yld_exp_empty, rq->yld_count, + "cpu%d %u %u %u %u %u %u %llu %llu %lu", + cpu, rq->yld_count, rq->sched_switch, rq->sched_count, rq->sched_goidle, rq->ttwu_count, rq->ttwu_local, rq->rq_cpu_time, -- GitLab From 7610c4f5efc495d8e15ef608c4a66932f895379a Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:38 +0100 Subject: [PATCH 4225/4982] ide: fix IDE_DFLAG_NO_IO_32BIT handling * IDE_DFLAG_NO_IO_32BIT may be set by cmd640's ->init_dev method so don't clear it in ide_port_tune_devices() (+ no need to do it). * Move IDE_DFLAG_NO_IO_32BIT handling to ide_port_init_devices(). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index ee8e3e7cad5..97ea5328c8e 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -848,13 +848,6 @@ static void ide_port_tune_devices(ide_hwif_t *hwif) ide_set_dma(drive); } } - - ide_port_for_each_dev(i, drive, hwif) { - if (hwif->host_flags & IDE_HFLAG_NO_IO_32BIT) - drive->dev_flags |= IDE_DFLAG_NO_IO_32BIT; - else - drive->dev_flags &= ~IDE_DFLAG_NO_IO_32BIT; - } } /* @@ -1192,6 +1185,8 @@ static void ide_port_init_devices(ide_hwif_t *hwif) if (hwif->host_flags & IDE_HFLAG_IO_32BIT) drive->io_32bit = 1; + if (hwif->host_flags & IDE_HFLAG_NO_IO_32BIT) + drive->dev_flags |= IDE_DFLAG_NO_IO_32BIT; if (hwif->host_flags & IDE_HFLAG_UNMASK_IRQS) drive->dev_flags |= IDE_DFLAG_UNMASK; if (hwif->host_flags & IDE_HFLAG_NO_UNMASK_IRQS) -- GitLab From 7a254df007b3db88bd430474030fec92e7bab22a Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:39 +0100 Subject: [PATCH 4226/4982] ide: move ide_pktcmd_tf_load() to ide-atapi.c Then make it static and remove 'dma' argument. Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-atapi.c | 21 ++++++++++++++++++++- drivers/ide/ide-io.c | 20 -------------------- include/linux/ide.h | 2 -- 3 files changed, 20 insertions(+), 23 deletions(-) diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index e9d042dba0e..09ae30f4607 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -456,6 +456,25 @@ next_irq: return ide_started; } +static void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount) +{ + ide_hwif_t *hwif = drive->hwif; + ide_task_t task; + u8 dma = drive->dma; + + memset(&task, 0, sizeof(task)); + task.tf_flags = IDE_TFLAG_OUT_LBAH | IDE_TFLAG_OUT_LBAM | + IDE_TFLAG_OUT_FEATURE | tf_flags; + task.tf.feature = dma; /* Use PIO/DMA */ + task.tf.lbam = bcount & 0xff; + task.tf.lbah = (bcount >> 8) & 0xff; + + ide_tf_dump(drive->name, &task.tf); + hwif->tp_ops->set_irq(hwif, 1); + SELECT_MASK(drive, 0); + hwif->tp_ops->tf_load(drive, &task); +} + static u8 ide_read_ireason(ide_drive_t *drive) { ide_task_t task; @@ -629,7 +648,7 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive) : WAIT_TAPE_CMD; } - ide_pktcmd_tf_load(drive, tf_flags, bcount, drive->dma); + ide_pktcmd_tf_load(drive, tf_flags, bcount); /* Issue the packet command */ if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) { diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index a9a6c208288..4344b6119d7 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -1192,26 +1192,6 @@ void ide_do_drive_cmd(ide_drive_t *drive, struct request *rq) } EXPORT_SYMBOL(ide_do_drive_cmd); -void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma) -{ - ide_hwif_t *hwif = drive->hwif; - ide_task_t task; - - memset(&task, 0, sizeof(task)); - task.tf_flags = IDE_TFLAG_OUT_LBAH | IDE_TFLAG_OUT_LBAM | - IDE_TFLAG_OUT_FEATURE | tf_flags; - task.tf.feature = dma; /* Use PIO/DMA */ - task.tf.lbam = bcount & 0xff; - task.tf.lbah = (bcount >> 8) & 0xff; - - ide_tf_dump(drive->name, &task.tf); - hwif->tp_ops->set_irq(hwif, 1); - SELECT_MASK(drive, 0); - hwif->tp_ops->tf_load(drive, &task); -} - -EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load); - void ide_pad_transfer(ide_drive_t *drive, int write, int len) { ide_hwif_t *hwif = drive->hwif; diff --git a/include/linux/ide.h b/include/linux/ide.h index 25087aead65..e7b787de528 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1202,8 +1202,6 @@ void ide_read_bcount_and_ireason(ide_drive_t *, u16 *, u8 *); extern int drive_is_ready(ide_drive_t *); -void ide_pktcmd_tf_load(ide_drive_t *, u32, u16, u8); - int ide_check_atapi_device(ide_drive_t *, const char *); void ide_init_pc(struct ide_atapi_pc *); -- GitLab From d336ae3cf567185fb8fc03c10e9394920f7d5ab1 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:39 +0100 Subject: [PATCH 4227/4982] ide: no need to touch local IRQs in ide_probe_port() Remove superfluous local_save_flags() local_irq_enable_in_hardirq() ... local_irq_restore() combo. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 97ea5328c8e..eebd4ed2906 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -779,7 +779,6 @@ EXPORT_SYMBOL_GPL(ide_undecoded_slave); static int ide_probe_port(ide_hwif_t *hwif) { ide_drive_t *drive; - unsigned long flags; unsigned int irqd; int i, rc = -ENODEV; @@ -797,9 +796,6 @@ static int ide_probe_port(ide_hwif_t *hwif) if (irqd) disable_irq(hwif->irq); - local_save_flags(flags); - local_irq_enable_in_hardirq(); - if (ide_port_wait_ready(hwif) == -EBUSY) printk(KERN_DEBUG "%s: Wait for ready failed before probe !\n", hwif->name); @@ -813,8 +809,6 @@ static int ide_probe_port(ide_hwif_t *hwif) rc = 0; } - local_irq_restore(flags); - /* * Use cached IRQ number. It might be (and is...) changed by probe * code above -- GitLab From 7362951b4818763b6abaecd3f870739125145cc1 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:39 +0100 Subject: [PATCH 4228/4982] ide: move ->lock and ->timer init from init_irq() to ide_init_port_data() Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index eebd4ed2906..63f67e3c255 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -941,11 +941,6 @@ static int init_irq (ide_hwif_t *hwif) int sa = 0; mutex_lock(&ide_cfg_mtx); - spin_lock_init(&hwif->lock); - - init_timer(&hwif->timer); - hwif->timer.function = &ide_timer_expiry; - hwif->timer.data = (unsigned long)hwif; irq_handler = hwif->host->irq_handler; if (irq_handler == NULL) @@ -1306,6 +1301,12 @@ static void ide_init_port_data(ide_hwif_t *hwif, unsigned int index) hwif->name[2] = 'e'; hwif->name[3] = '0' + index; + spin_lock_init(&hwif->lock); + + init_timer(&hwif->timer); + hwif->timer.function = &ide_timer_expiry; + hwif->timer.data = (unsigned long)hwif; + init_completion(&hwif->gendev_rel_comp); hwif->tp_ops = &default_tp_ops; -- GitLab From 0688d3a6ba9bf4e1df62ce627ad1daa0e2bf9148 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:39 +0100 Subject: [PATCH 4229/4982] ide: init_irq() doesn't need to hold ide_cfg_mtx Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 63f67e3c255..5deb7e71733 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -940,8 +940,6 @@ static int init_irq (ide_hwif_t *hwif) irq_handler_t irq_handler; int sa = 0; - mutex_lock(&ide_cfg_mtx); - irq_handler = hwif->host->irq_handler; if (irq_handler == NULL) irq_handler = ide_intr; @@ -979,10 +977,8 @@ static int init_irq (ide_hwif_t *hwif) printk(KERN_CONT " (serialized)"); printk(KERN_CONT "\n"); - mutex_unlock(&ide_cfg_mtx); return 0; out_up: - mutex_unlock(&ide_cfg_mtx); return 1; } -- GitLab From 1902a253e4b14378405de761cb444dfeef15e500 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:40 +0100 Subject: [PATCH 4230/4982] ide: remove superfluous check from ide_proc_port_register_devices() Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index a7b9287ee0d..417cde56eaf 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -600,7 +600,7 @@ void ide_proc_port_register_devices(ide_hwif_t *hwif) int i; ide_port_for_each_dev(i, drive, hwif) { - if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0 || drive->proc) + if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) continue; drive->proc = proc_mkdir(drive->name, parent); -- GitLab From 94635d3ecfd478ada7cedcffd9d53709074444fc Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:41 +0100 Subject: [PATCH 4231/4982] ide-acpi: no need to zero ->acpidata for devices ide_acpi_init() takes care of it. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-acpi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index ec7d07fa570..0ac5c786a31 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -712,8 +712,6 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif) * Send IDENTIFY for each drive */ ide_port_for_each_dev(i, drive, hwif) { - memset(drive->acpidata, 0, sizeof(*drive->acpidata)); - if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) continue; -- GitLab From 8cd3c605624035b7f57deb8894e17c5ba6d05b2e Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:41 +0100 Subject: [PATCH 4232/4982] ide-acpi: init ACPI handles early for devices Init ACPI handles for devices in ide_acpi_port_init_devices() and remove no longer needed ide_acpi_drive_get_handle(). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-acpi.c | 65 ++++++++++++++---------------------------- 1 file changed, 21 insertions(+), 44 deletions(-) diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index 0ac5c786a31..a3bebba1842 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -201,40 +201,6 @@ static acpi_handle ide_acpi_hwif_get_handle(ide_hwif_t *hwif) return chan_handle; } -/** - * ide_acpi_drive_get_handle - Get ACPI object handle for a given drive - * @drive: device to locate - * - * Retrieves the object handle of a given drive. According to the ACPI - * spec the drive is a child of the hwif. - * - * Returns handle on success, 0 on error. - */ -static acpi_handle ide_acpi_drive_get_handle(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - int port; - acpi_handle drive_handle; - - if (!hwif->acpidata) - return NULL; - - if (!hwif->acpidata->obj_handle) - return NULL; - - port = hwif->channel ? drive->dn - 2: drive->dn; - - DEBPRINT("ENTER: %s at channel#: %d port#: %d\n", - drive->name, hwif->channel, port); - - - /* TBD: could also check ACPI object VALID bits */ - drive_handle = acpi_get_child(hwif->acpidata->obj_handle, port); - DEBPRINT("drive %s handle 0x%p\n", drive->name, drive_handle); - - return drive_handle; -} - /** * do_drive_get_GTF - get the drive bootup default taskfile settings * @drive: the drive for which the taskfile settings should be retrieved @@ -290,14 +256,9 @@ static int do_drive_get_GTF(ide_drive_t *drive, goto out; } - /* Get this drive's _ADR info. if not already known. */ if (!drive->acpidata->obj_handle) { - drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive); - if (!drive->acpidata->obj_handle) { - DEBPRINT("No ACPI object found for %s\n", - drive->name); - goto out; - } + DEBPRINT("No ACPI object found for %s\n", drive->name); + goto out; } /* Setting up output buffer */ @@ -652,9 +613,6 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on) acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D0); ide_port_for_each_dev(i, drive, hwif) { - if (!drive->acpidata->obj_handle) - drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive); - if (drive->acpidata->obj_handle && (drive->dev_flags & IDE_DFLAG_PRESENT)) { acpi_bus_set_power(drive->acpidata->obj_handle, @@ -708,6 +666,25 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif) hwif->devices[0]->acpidata = &hwif->acpidata->master; hwif->devices[1]->acpidata = &hwif->acpidata->slave; + /* get _ADR info for each device */ + ide_port_for_each_dev(i, drive, hwif) { + acpi_handle dev_handle; + + if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) + continue; + + DEBPRINT("ENTER: %s at channel#: %d port#: %d\n", + drive->name, hwif->channel, drive->dn & 1); + + /* TBD: could also check ACPI object VALID bits */ + dev_handle = acpi_get_child(hwif->acpidata->obj_handle, + drive->dn & 1); + + DEBPRINT("drive %s handle 0x%p\n", drive->name, dev_handle); + + drive->acpidata->obj_handle = dev_handle; + } + /* * Send IDENTIFY for each drive */ -- GitLab From 7ed5b157d9dff55bf477b4c8b4708d5d45476677 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:41 +0100 Subject: [PATCH 4233/4982] ide: add ide_for_each_present_dev() iterator * Add ide_for_each_present_dev() iterator and convert IDE code to use it. * Do some drive-by CodingStyle fixups in ide-acpi.c while at it. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-acpi.c | 30 ++++++++++-------------------- drivers/ide/ide-iops.c | 5 ++--- drivers/ide/ide-probe.c | 38 +++++++++++++------------------------- include/linux/ide.h | 4 ++++ 4 files changed, 29 insertions(+), 48 deletions(-) diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index a3bebba1842..8d6d31fcbfb 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -608,17 +608,17 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on) DEBPRINT("no ACPI data for %s\n", hwif->name); return; } + /* channel first and then drives for power on and verse versa for power off */ if (on) acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D0); - ide_port_for_each_dev(i, drive, hwif) { - if (drive->acpidata->obj_handle && - (drive->dev_flags & IDE_DFLAG_PRESENT)) { + ide_port_for_each_present_dev(i, drive, hwif) { + if (drive->acpidata->obj_handle) acpi_bus_set_power(drive->acpidata->obj_handle, - on? ACPI_STATE_D0: ACPI_STATE_D3); - } + on ? ACPI_STATE_D0 : ACPI_STATE_D3); } + if (!on) acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D3); } @@ -667,12 +667,9 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif) hwif->devices[1]->acpidata = &hwif->acpidata->slave; /* get _ADR info for each device */ - ide_port_for_each_dev(i, drive, hwif) { + ide_port_for_each_present_dev(i, drive, hwif) { acpi_handle dev_handle; - if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) - continue; - DEBPRINT("ENTER: %s at channel#: %d port#: %d\n", drive->name, hwif->channel, drive->dn & 1); @@ -685,13 +682,8 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif) drive->acpidata->obj_handle = dev_handle; } - /* - * Send IDENTIFY for each drive - */ - ide_port_for_each_dev(i, drive, hwif) { - if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) - continue; - + /* send IDENTIFY for each device */ + ide_port_for_each_present_dev(i, drive, hwif) { err = taskfile_lib_get_identify(drive, drive->acpidata->idbuff); if (err) DEBPRINT("identify device %s failed (%d)\n", @@ -711,9 +703,7 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif) ide_acpi_get_timing(hwif); ide_acpi_push_timing(hwif); - ide_port_for_each_dev(i, drive, hwif) { - if (drive->dev_flags & IDE_DFLAG_PRESENT) - /* Execute ACPI startup code */ - ide_acpi_exec_tfs(drive); + ide_port_for_each_present_dev(i, drive, hwif) { + ide_acpi_exec_tfs(drive); } } diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index b1892bd95c6..02fed32a404 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -1103,9 +1103,8 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) prepare_to_wait(&ide_park_wq, &wait, TASK_UNINTERRUPTIBLE); timeout = jiffies; - ide_port_for_each_dev(i, tdrive, hwif) { - if (tdrive->dev_flags & IDE_DFLAG_PRESENT && - tdrive->dev_flags & IDE_DFLAG_PARKED && + ide_port_for_each_present_dev(i, tdrive, hwif) { + if ((tdrive->dev_flags & IDE_DFLAG_PARKED) && time_after(tdrive->sleep, timeout)) timeout = tdrive->sleep; } diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 5deb7e71733..eb0a38cd83c 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -825,22 +825,18 @@ static void ide_port_tune_devices(ide_hwif_t *hwif) ide_drive_t *drive; int i; - ide_port_for_each_dev(i, drive, hwif) { - if (drive->dev_flags & IDE_DFLAG_PRESENT) { - if (port_ops && port_ops->quirkproc) - port_ops->quirkproc(drive); - } + ide_port_for_each_present_dev(i, drive, hwif) { + if (port_ops && port_ops->quirkproc) + port_ops->quirkproc(drive); } - ide_port_for_each_dev(i, drive, hwif) { - if (drive->dev_flags & IDE_DFLAG_PRESENT) { - ide_set_max_pio(drive); + ide_port_for_each_present_dev(i, drive, hwif) { + ide_set_max_pio(drive); - drive->dev_flags |= IDE_DFLAG_NICE1; + drive->dev_flags |= IDE_DFLAG_NICE1; - if (hwif->dma_ops) - ide_set_dma(drive); - } + if (hwif->dma_ops) + ide_set_dma(drive); } } @@ -911,10 +907,7 @@ static int ide_port_setup_devices(ide_hwif_t *hwif) int i, j = 0; mutex_lock(&ide_cfg_mtx); - ide_port_for_each_dev(i, drive, hwif) { - if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) - continue; - + ide_port_for_each_present_dev(i, drive, hwif) { if (ide_init_queue(drive)) { printk(KERN_ERR "ide: failed to init %s\n", drive->name); @@ -1139,13 +1132,10 @@ static void hwif_register_devices(ide_hwif_t *hwif) ide_drive_t *drive; unsigned int i; - ide_port_for_each_dev(i, drive, hwif) { + ide_port_for_each_present_dev(i, drive, hwif) { struct device *dev = &drive->gendev; int ret; - if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) - continue; - dev_set_name(dev, "%u.%u", hwif->index, i); dev->parent = &hwif->gendev; dev->bus = &ide_bus_type; @@ -1610,11 +1600,9 @@ static void __ide_port_unregister_devices(ide_hwif_t *hwif) ide_drive_t *drive; int i; - ide_port_for_each_dev(i, drive, hwif) { - if (drive->dev_flags & IDE_DFLAG_PRESENT) { - device_unregister(&drive->gendev); - wait_for_completion(&drive->gendev_rel_comp); - } + ide_port_for_each_present_dev(i, drive, hwif) { + device_unregister(&drive->gendev); + wait_for_completion(&drive->gendev_rel_comp); } } diff --git a/include/linux/ide.h b/include/linux/ide.h index e7b787de528..7ed395b4b89 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1609,6 +1609,10 @@ static inline ide_drive_t *ide_get_pair_dev(ide_drive_t *drive) #define ide_port_for_each_dev(i, dev, port) \ for ((i) = 0; ((dev) = (port)->devices[i]) || (i) < MAX_DRIVES; (i)++) +#define ide_port_for_each_present_dev(i, dev, port) \ + for ((i) = 0; ((dev) = (port)->devices[i]) || (i) < MAX_DRIVES; (i)++) \ + if ((dev)->dev_flags & IDE_DFLAG_PRESENT) + #define ide_host_for_each_port(i, port, host) \ for ((i) = 0; ((port) = (host)->ports[i]) || (i) < MAX_HOST_PORTS; (i)++) -- GitLab From 8b803bd184e3f6892284d4b50801b9ec85cd9b96 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:41 +0100 Subject: [PATCH 4234/4982] ide: sanitize ACPI initialization * ide_acpi_init() -> ide_acpi_init_port() * ide_acpi_blacklist() -> ide_acpi_init() * Call ide_acpi_init() only once (do it during IDE core initialization) and cleanup the function accordingly. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-acpi.c | 12 +++--------- drivers/ide/ide-probe.c | 2 +- drivers/ide/ide.c | 2 ++ include/linux/ide.h | 6 ++++-- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index 8d6d31fcbfb..ba5932d7b1b 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -89,12 +89,8 @@ static const struct dmi_system_id ide_acpi_dmi_table[] = { { } /* terminate list */ }; -static int ide_acpi_blacklist(void) +int ide_acpi_init(void) { - static int done; - if (done) - return 0; - done = 1; dmi_check_system(ide_acpi_dmi_table); return 0; } @@ -624,7 +620,7 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on) } /** - * ide_acpi_init - initialize the ACPI link for an IDE interface + * ide_acpi_init_port - initialize the ACPI link for an IDE interface * @hwif: target IDE interface (channel) * * The ACPI spec is not quite clear when the drive identify buffer @@ -634,10 +630,8 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on) * So we get the information during startup; but this means that * any changes during run-time will be lost after resume. */ -void ide_acpi_init(ide_hwif_t *hwif) +void ide_acpi_init_port(ide_hwif_t *hwif) { - ide_acpi_blacklist(); - hwif->acpidata = kzalloc(sizeof(struct ide_acpi_hwif_link), GFP_KERNEL); if (!hwif->acpidata) return; diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index eb0a38cd83c..a51ad2bd62b 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1543,7 +1543,7 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, j++; - ide_acpi_init(hwif); + ide_acpi_init_port(hwif); if (hwif->present) ide_acpi_port_init_devices(hwif); diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 0920e3b0c96..c779aa24dbe 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -527,6 +527,8 @@ static int __init ide_init(void) goto out_port_class; } + ide_acpi_init(); + proc_ide_create(); return 0; diff --git a/include/linux/ide.h b/include/linux/ide.h index 7ed395b4b89..6bb104f4e34 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1484,17 +1484,19 @@ static inline void ide_release_dma_engine(ide_hwif_t *hwif) { ; } #endif /* CONFIG_BLK_DEV_IDEDMA */ #ifdef CONFIG_BLK_DEV_IDEACPI +int ide_acpi_init(void); extern int ide_acpi_exec_tfs(ide_drive_t *drive); extern void ide_acpi_get_timing(ide_hwif_t *hwif); extern void ide_acpi_push_timing(ide_hwif_t *hwif); -extern void ide_acpi_init(ide_hwif_t *hwif); +void ide_acpi_init_port(ide_hwif_t *); void ide_acpi_port_init_devices(ide_hwif_t *); extern void ide_acpi_set_state(ide_hwif_t *hwif, int on); #else +static inline int ide_acpi_init(void) { return 0; } static inline int ide_acpi_exec_tfs(ide_drive_t *drive) { return 0; } static inline void ide_acpi_get_timing(ide_hwif_t *hwif) { ; } static inline void ide_acpi_push_timing(ide_hwif_t *hwif) { ; } -static inline void ide_acpi_init(ide_hwif_t *hwif) { ; } +static inline void ide_acpi_init_port(ide_hwif_t *hwif) { ; } static inline void ide_acpi_port_init_devices(ide_hwif_t *hwif) { ; } static inline void ide_acpi_set_state(ide_hwif_t *hwif, int on) {} #endif -- GitLab From 2f0d0fd2a605666d38e290c5c0d2907484352dc4 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:42 +0100 Subject: [PATCH 4235/4982] ide-acpi: cleanup do_drive_get_GTF() * ide_noacpi is already checked by ide_acpi_exec_tfs() which is the only user of do_drive_get_GTF(). * ide_acpi_exec_tfs() prints sufficient debug info about the device so no need to have excessive data about port/host. * It is sufficient to check for drive->acpidata->obj_handle as it will be NULL if dev == NULL or hwif->acpidata == NULL or device is not present. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-acpi.c | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index ba5932d7b1b..6b3123612f1 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -219,39 +219,12 @@ static int do_drive_get_GTF(ide_drive_t *drive, acpi_status status; struct acpi_buffer output; union acpi_object *out_obj; - ide_hwif_t *hwif = drive->hwif; - struct device *dev = hwif->gendev.parent; int err = -ENODEV; - int port; *gtf_length = 0; *gtf_address = 0UL; *obj_loc = 0UL; - if (ide_noacpi) - return 0; - - if (!dev) { - DEBPRINT("no PCI device for %s\n", hwif->name); - goto out; - } - - if (!hwif->acpidata) { - DEBPRINT("no ACPI data for %s\n", hwif->name); - goto out; - } - - port = hwif->channel ? drive->dn - 2: drive->dn; - - DEBPRINT("ENTER: %s at %s, port#: %d, hard_port#: %d\n", - hwif->name, dev_name(dev), port, hwif->channel); - - if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) { - DEBPRINT("%s drive %d:%d not present\n", - hwif->name, hwif->channel, port); - goto out; - } - if (!drive->acpidata->obj_handle) { DEBPRINT("No ACPI object found for %s\n", drive->name); goto out; -- GitLab From 1f5892a5d21c905b1614cbd6bd8c5ad2cfbc106f Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:42 +0100 Subject: [PATCH 4236/4982] ide-acpi: cleanup do_drive_set_taskfiles() * ide_noacpi is already checked by ide_acpi_exec_tfs() which is the only user of do_drive_set_taskfiles(). * ide_acpi_exec_tfs() prints sufficient debug info about the device so no need to do it again. * do_drive_get_GTF() + ide_acpi_exec_tfs() make sure that this function will never be called with incorrect gtf_length argument or if device is not present. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-acpi.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index 6b3123612f1..ce5b213e2bc 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -334,32 +334,14 @@ static int do_drive_set_taskfiles(ide_drive_t *drive, unsigned int gtf_length, unsigned long gtf_address) { - int rc = -ENODEV, err; + int rc = 0, err; int gtf_count = gtf_length / REGS_PER_GTF; int ix; struct taskfile_array *gtf; - if (ide_noacpi) - return 0; - - DEBPRINT("ENTER: %s, hard_port#: %d\n", drive->name, drive->dn); - - if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) - goto out; - - if (!gtf_count) /* shouldn't be here */ - goto out; - DEBPRINT("total GTF bytes=%u (0x%x), gtf_count=%d, addr=0x%lx\n", gtf_length, gtf_length, gtf_count, gtf_address); - if (gtf_length % REGS_PER_GTF) { - printk(KERN_ERR "%s: unexpected GTF length (%d)\n", - __func__, gtf_length); - goto out; - } - - rc = 0; for (ix = 0; ix < gtf_count; ix++) { gtf = (struct taskfile_array *) (gtf_address + ix * REGS_PER_GTF); @@ -370,7 +352,6 @@ static int do_drive_set_taskfiles(ide_drive_t *drive, rc = err; } -out: return rc; } -- GitLab From b0b391430bea405ced6038e4cf4d8cf831511935 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:42 +0100 Subject: [PATCH 4237/4982] ide-acpi: remove taskfile_load_raw() * taskfile_load_raw() is used only by do_drive_set_taskfiles() so inline it there. While at it: - rename 'args' variable to 'task' - remove struct taskfile_array - do ide_acpigtf check early - use REGS_PER_GTF Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-acpi.c | 71 ++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 47 deletions(-) diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index ce5b213e2bc..5b704f1ea90 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -20,9 +20,6 @@ #include #define REGS_PER_GTF 7 -struct taskfile_array { - u8 tfa[REGS_PER_GTF]; /* regs. 0x1f1 - 0x1f7 */ -}; struct GTM_buffer { u32 PIO_speed0; @@ -284,43 +281,6 @@ out: return err; } -/** - * taskfile_load_raw - send taskfile registers to drive - * @drive: drive to which output is sent - * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7) - * - * Outputs IDE taskfile to the drive. - */ -static int taskfile_load_raw(ide_drive_t *drive, - const struct taskfile_array *gtf) -{ - ide_task_t args; - int err = 0; - - DEBPRINT("(0x1f1-1f7): hex: " - "%02x %02x %02x %02x %02x %02x %02x\n", - gtf->tfa[0], gtf->tfa[1], gtf->tfa[2], - gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]); - - memset(&args, 0, sizeof(ide_task_t)); - - /* convert gtf to IDE Taskfile */ - memcpy(&args.tf_array[7], >f->tfa, 7); - args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - - if (!ide_acpigtf) { - DEBPRINT("_GTF execution disabled\n"); - return err; - } - - err = ide_no_data_taskfile(drive, &args); - if (err) - printk(KERN_ERR "%s: ide_no_data_taskfile failed: %u\n", - __func__, err); - - return err; -} - /** * do_drive_set_taskfiles - write the drive taskfile settings from _GTF * @drive: the drive to which the taskfile command should be sent @@ -337,19 +297,36 @@ static int do_drive_set_taskfiles(ide_drive_t *drive, int rc = 0, err; int gtf_count = gtf_length / REGS_PER_GTF; int ix; - struct taskfile_array *gtf; DEBPRINT("total GTF bytes=%u (0x%x), gtf_count=%d, addr=0x%lx\n", gtf_length, gtf_length, gtf_count, gtf_address); + /* send all taskfile registers (0x1f1-0x1f7) *in*that*order* */ for (ix = 0; ix < gtf_count; ix++) { - gtf = (struct taskfile_array *) - (gtf_address + ix * REGS_PER_GTF); - - /* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */ - err = taskfile_load_raw(drive, gtf); - if (err) + u8 *gtf = (u8 *)(gtf_address + ix * REGS_PER_GTF); + ide_task_t task; + + DEBPRINT("(0x1f1-1f7): " + "hex: %02x %02x %02x %02x %02x %02x %02x\n", + gtf[0], gtf[1], gtf[2], + gtf[3], gtf[4], gtf[5], gtf[6]); + + if (!ide_acpigtf) { + DEBPRINT("_GTF execution disabled\n"); + continue; + } + + /* convert GTF to taskfile */ + memset(&task, 0, sizeof(ide_task_t)); + memcpy(&task.tf_array[7], gtf, REGS_PER_GTF); + task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; + + err = ide_no_data_taskfile(drive, &task); + if (err) { + printk(KERN_ERR "%s: ide_no_data_taskfile failed: %u\n", + __func__, err); rc = err; + } } return rc; -- GitLab From 2b9ae4608ffbdb57c1d5fe9db440810a995a91fa Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:42 +0100 Subject: [PATCH 4238/4982] ide: remove stale comments from drive_is_ready() Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 02fed32a404..cd1f2e464c4 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -438,9 +438,6 @@ void ide_fixstring (u8 *s, const int bytecount, const int byteswap) EXPORT_SYMBOL(ide_fixstring); -/* - * Needed for PCI irq sharing - */ int drive_is_ready (ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; @@ -449,12 +446,6 @@ int drive_is_ready (ide_drive_t *drive) if (drive->waiting_for_dma) return hwif->dma_ops->dma_test_irq(drive); - /* - * We do a passive status test under shared PCI interrupts on - * cards that truly share the ATA side interrupt, but may also share - * an interrupt with another pci card/device. We make no assumptions - * about possible isa-pnp and pci-pnp issues yet. - */ if (hwif->io_ports.ctl_addr && (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) stat = hwif->tp_ops->read_altstatus(hwif); -- GitLab From 75a0cff4e8ed47584dd15fbde2172ebc4c051bb2 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:43 +0100 Subject: [PATCH 4239/4982] ide: unexport ide_devset_execute() There are no modular ide_devset_execute() users left so unexport it. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-io.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 4344b6119d7..d90cf5d0814 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -513,7 +513,6 @@ int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting, return ret; } -EXPORT_SYMBOL_GPL(ide_devset_execute); static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq) { -- GitLab From b6a45a0b1e9a358b81201659cf87b023e3ec73e0 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:43 +0100 Subject: [PATCH 4240/4982] ide: move drive_is_ready() to ide-io.c Move drive_is_ready() to ide-io.c, then make it static. Also make some minor CodingStyle fixups while at it. Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-io.c | 23 +++++++++++++++++++++++ drivers/ide/ide-iops.c | 25 ------------------------- include/linux/ide.h | 2 -- 3 files changed, 23 insertions(+), 27 deletions(-) diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index d90cf5d0814..835cf646bb0 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -887,6 +887,29 @@ static void ide_plug_device(ide_drive_t *drive) spin_unlock_irqrestore(q->queue_lock, flags); } +static int drive_is_ready(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + u8 stat = 0; + + if (drive->waiting_for_dma) + return hwif->dma_ops->dma_test_irq(drive); + + if (hwif->io_ports.ctl_addr && + (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) + stat = hwif->tp_ops->read_altstatus(hwif); + else + /* Note: this may clear a pending IRQ!! */ + stat = hwif->tp_ops->read_status(hwif); + + if (stat & ATA_BUSY) + /* drive busy: definitely not interrupting */ + return 0; + + /* drive ready: *might* be interrupting */ + return 1; +} + /** * ide_timer_expiry - handle lack of an IDE interrupt * @data: timer callback magic (hwif) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index cd1f2e464c4..ee9c6034278 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -438,31 +438,6 @@ void ide_fixstring (u8 *s, const int bytecount, const int byteswap) EXPORT_SYMBOL(ide_fixstring); -int drive_is_ready (ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - u8 stat = 0; - - if (drive->waiting_for_dma) - return hwif->dma_ops->dma_test_irq(drive); - - if (hwif->io_ports.ctl_addr && - (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) - stat = hwif->tp_ops->read_altstatus(hwif); - else - /* Note: this may clear a pending IRQ!! */ - stat = hwif->tp_ops->read_status(hwif); - - if (stat & ATA_BUSY) - /* drive busy: definitely not interrupting */ - return 0; - - /* drive ready: *might* be interrupting */ - return 1; -} - -EXPORT_SYMBOL(drive_is_ready); - /* * This routine busy-waits for the drive status to be not "busy". * It then checks the status for all of the "good" bits and none diff --git a/include/linux/ide.h b/include/linux/ide.h index 6bb104f4e34..2e95adeedff 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1200,8 +1200,6 @@ void SELECT_MASK(ide_drive_t *, int); u8 ide_read_error(ide_drive_t *); void ide_read_bcount_and_ireason(ide_drive_t *, u16 *, u8 *); -extern int drive_is_ready(ide_drive_t *); - int ide_check_atapi_device(ide_drive_t *, const char *); void ide_init_pc(struct ide_atapi_pc *); -- GitLab From 65ca5377322c7543163066f373ae9e6b0ad8de8a Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:43 +0100 Subject: [PATCH 4241/4982] ide: move ide_dma_timeout_retry() to ide-dma.c Move ide_dma_timeout_retry() to ide-dma.c and add static inline version for CONFIG_BLK_DEV_IDEDMA=n. Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-dma.c | 57 +++++++++++++++++++++++++++++++++++++++++++ drivers/ide/ide-io.c | 57 ------------------------------------------- include/linux/ide.h | 2 ++ 3 files changed, 59 insertions(+), 57 deletions(-) diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 059c90bb5ad..a878f4734f8 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -470,6 +470,63 @@ void ide_dma_timeout(ide_drive_t *drive) } EXPORT_SYMBOL_GPL(ide_dma_timeout); +/* + * un-busy the port etc, and clear any pending DMA status. we want to + * retry the current request in pio mode instead of risking tossing it + * all away + */ +ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error) +{ + ide_hwif_t *hwif = drive->hwif; + struct request *rq; + ide_startstop_t ret = ide_stopped; + + /* + * end current dma transaction + */ + + if (error < 0) { + printk(KERN_WARNING "%s: DMA timeout error\n", drive->name); + (void)hwif->dma_ops->dma_end(drive); + ret = ide_error(drive, "dma timeout error", + hwif->tp_ops->read_status(hwif)); + } else { + printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name); + hwif->dma_ops->dma_timeout(drive); + } + + /* + * disable dma for now, but remember that we did so because of + * a timeout -- we'll reenable after we finish this next request + * (or rather the first chunk of it) in pio. + */ + drive->dev_flags |= IDE_DFLAG_DMA_PIO_RETRY; + drive->retry_pio++; + ide_dma_off_quietly(drive); + + /* + * un-busy drive etc and make sure request is sane + */ + + rq = hwif->rq; + if (!rq) + goto out; + + hwif->rq = NULL; + + rq->errors = 0; + + if (!rq->bio) + goto out; + + rq->sector = rq->bio->bi_sector; + rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9; + rq->hard_cur_sectors = rq->current_nr_sectors; + rq->buffer = bio_data(rq->bio); +out: + return ret; +} + void ide_release_dma_engine(ide_hwif_t *hwif) { if (hwif->dmatable_cpu) { diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 835cf646bb0..557b15700ea 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -819,63 +819,6 @@ plug_device_2: blk_plug_device(q); } -/* - * un-busy the port etc, and clear any pending DMA status. we want to - * retry the current request in pio mode instead of risking tossing it - * all away - */ -static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error) -{ - ide_hwif_t *hwif = drive->hwif; - struct request *rq; - ide_startstop_t ret = ide_stopped; - - /* - * end current dma transaction - */ - - if (error < 0) { - printk(KERN_WARNING "%s: DMA timeout error\n", drive->name); - (void)hwif->dma_ops->dma_end(drive); - ret = ide_error(drive, "dma timeout error", - hwif->tp_ops->read_status(hwif)); - } else { - printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name); - hwif->dma_ops->dma_timeout(drive); - } - - /* - * disable dma for now, but remember that we did so because of - * a timeout -- we'll reenable after we finish this next request - * (or rather the first chunk of it) in pio. - */ - drive->dev_flags |= IDE_DFLAG_DMA_PIO_RETRY; - drive->retry_pio++; - ide_dma_off_quietly(drive); - - /* - * un-busy drive etc and make sure request is sane - */ - - rq = hwif->rq; - if (!rq) - goto out; - - hwif->rq = NULL; - - rq->errors = 0; - - if (!rq->bio) - goto out; - - rq->sector = rq->bio->bi_sector; - rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9; - rq->hard_cur_sectors = rq->current_nr_sectors; - rq->buffer = bio_data(rq->bio); -out: - return ret; -} - static void ide_plug_device(ide_drive_t *drive) { struct request_queue *q = drive->queue; diff --git a/include/linux/ide.h b/include/linux/ide.h index 2e95adeedff..d0065a90452 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1467,6 +1467,7 @@ static inline int config_drive_for_dma(ide_drive_t *drive) { return 0; } void ide_dma_lost_irq(ide_drive_t *); void ide_dma_timeout(ide_drive_t *); +ide_startstop_t ide_dma_timeout_retry(ide_drive_t *, int); #else static inline int ide_id_dma_bug(ide_drive_t *drive) { return 0; } @@ -1478,6 +1479,7 @@ static inline void ide_dma_on(ide_drive_t *drive) { ; } static inline void ide_dma_verbose(ide_drive_t *drive) { ; } static inline int ide_set_dma(ide_drive_t *drive) { return 1; } static inline void ide_check_dma_crc(ide_drive_t *drive) { ; } +static inline ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error) { return ide_stopped; } static inline void ide_release_dma_engine(ide_hwif_t *hwif) { ; } #endif /* CONFIG_BLK_DEV_IDEDMA */ -- GitLab From 1866082339597930c5b77aad8de34ab4fbb5724f Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:44 +0100 Subject: [PATCH 4242/4982] ide: remove ide_do_drive_cmd() * Use elv_add_request() instead of __elv_add_request() in ide_do_drive_cmd(). * ide_do_drive_cmd() is used only in ide-{atapi,cd}.c so inline it there. There should be no functional changes caused by this patch. Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-atapi.c | 5 ++++- drivers/ide/ide-cd.c | 4 +++- drivers/ide/ide-io.c | 28 ---------------------------- include/linux/ide.h | 2 -- 4 files changed, 7 insertions(+), 32 deletions(-) diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 09ae30f4607..3044c51c06a 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -149,7 +149,10 @@ static void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk, memcpy(rq->cmd, pc->c, 12); if (drive->media == ide_tape) rq->cmd[13] = REQ_IDETAPE_PC1; - ide_do_drive_cmd(drive, rq); + + drive->hwif->rq = NULL; + + elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0); } /* diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index ddfbea41d29..2177cd11664 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -242,7 +242,9 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense, ide_debug_log(IDE_DBG_SENSE, "failed_cmd: 0x%x\n", failed_command->cmd[0]); - ide_do_drive_cmd(drive, rq); + drive->hwif->rq = NULL; + + elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0); } static void cdrom_end_request(ide_drive_t *drive, int uptodate) diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 557b15700ea..56be3375bee 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -1129,34 +1129,6 @@ out_early: } EXPORT_SYMBOL_GPL(ide_intr); -/** - * ide_do_drive_cmd - issue IDE special command - * @drive: device to issue command - * @rq: request to issue - * - * This function issues a special IDE device request - * onto the request queue. - * - * the rq is queued at the head of the request queue, displacing - * the currently-being-processed request and this function - * returns immediately without waiting for the new rq to be - * completed. This is VERY DANGEROUS, and is intended for - * careful use by the ATAPI tape/cdrom driver code. - */ - -void ide_do_drive_cmd(ide_drive_t *drive, struct request *rq) -{ - struct request_queue *q = drive->queue; - unsigned long flags; - - drive->hwif->rq = NULL; - - spin_lock_irqsave(q->queue_lock, flags); - __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0); - spin_unlock_irqrestore(q->queue_lock, flags); -} -EXPORT_SYMBOL(ide_do_drive_cmd); - void ide_pad_transfer(ide_drive_t *drive, int write, int len) { ide_hwif_t *hwif = drive->hwif; diff --git a/include/linux/ide.h b/include/linux/ide.h index d0065a90452..8fadffe53cd 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1174,8 +1174,6 @@ extern ide_startstop_t ide_do_reset (ide_drive_t *); extern int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting, int arg); -extern void ide_do_drive_cmd(ide_drive_t *, struct request *); - extern void ide_end_drive_cmd(ide_drive_t *, u8, u8); void ide_tf_dump(const char *, struct ide_taskfile *); -- GitLab From 1bc6daae4aba9194f8ff6801af8367a1a4718965 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:44 +0100 Subject: [PATCH 4243/4982] ide: factor out processing of special commands from ide_special_rq() Factor out processing of special commands from ide_special_rq() to ide_do_devset() and ide_do_park_unpark(). There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-io.c | 75 ++++++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 56be3375bee..c37883ae266 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -514,46 +514,53 @@ int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting, return ret; } +static ide_startstop_t ide_do_devset(ide_drive_t *drive, struct request *rq) +{ + int err, (*setfunc)(ide_drive_t *, int) = rq->special; + + err = setfunc(drive, *(int *)&rq->cmd[1]); + if (err) + rq->errors = err; + else + err = 1; + ide_end_request(drive, err, 0); + return ide_stopped; +} + +static ide_startstop_t ide_do_park_unpark(ide_drive_t *drive, struct request *rq) +{ + ide_task_t task; + struct ide_taskfile *tf = &task.tf; + + memset(&task, 0, sizeof(task)); + if (rq->cmd[0] == REQ_PARK_HEADS) { + drive->sleep = *(unsigned long *)rq->special; + drive->dev_flags |= IDE_DFLAG_SLEEPING; + tf->command = ATA_CMD_IDLEIMMEDIATE; + tf->feature = 0x44; + tf->lbal = 0x4c; + tf->lbam = 0x4e; + tf->lbah = 0x55; + task.tf_flags |= IDE_TFLAG_CUSTOM_HANDLER; + } else /* cmd == REQ_UNPARK_HEADS */ + tf->command = ATA_CMD_CHK_POWER; + + task.tf_flags |= IDE_TFLAG_TF | IDE_TFLAG_DEVICE; + task.rq = rq; + drive->hwif->data_phase = task.data_phase = TASKFILE_NO_DATA; + return do_rw_taskfile(drive, &task); +} + static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq) { u8 cmd = rq->cmd[0]; - if (cmd == REQ_PARK_HEADS || cmd == REQ_UNPARK_HEADS) { - ide_task_t task; - struct ide_taskfile *tf = &task.tf; - - memset(&task, 0, sizeof(task)); - if (cmd == REQ_PARK_HEADS) { - drive->sleep = *(unsigned long *)rq->special; - drive->dev_flags |= IDE_DFLAG_SLEEPING; - tf->command = ATA_CMD_IDLEIMMEDIATE; - tf->feature = 0x44; - tf->lbal = 0x4c; - tf->lbam = 0x4e; - tf->lbah = 0x55; - task.tf_flags |= IDE_TFLAG_CUSTOM_HANDLER; - } else /* cmd == REQ_UNPARK_HEADS */ - tf->command = ATA_CMD_CHK_POWER; - - task.tf_flags |= IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - task.rq = rq; - drive->hwif->data_phase = task.data_phase = TASKFILE_NO_DATA; - return do_rw_taskfile(drive, &task); - } - switch (cmd) { + case REQ_PARK_HEADS: + case REQ_UNPARK_HEADS: + return ide_do_park_unpark(drive, rq); case REQ_DEVSET_EXEC: - { - int err, (*setfunc)(ide_drive_t *, int) = rq->special; - - err = setfunc(drive, *(int *)&rq->cmd[1]); - if (err) - rq->errors = err; - else - err = 1; - ide_end_request(drive, err, 0); - return ide_stopped; - } + return ide_do_devset(drive, rq); case REQ_DRIVE_RESET: return ide_do_reset(drive); default: -- GitLab From c4e66c36cce3f23d68013c4112013123ffe80bdb Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:44 +0100 Subject: [PATCH 4244/4982] ide: move ide_do_park_unpark() to ide-park.c Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-io.c | 24 ------------------------ drivers/ide/ide-park.c | 25 +++++++++++++++++++++++++ include/linux/ide.h | 2 ++ 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index c37883ae266..16e47989fcf 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -527,30 +527,6 @@ static ide_startstop_t ide_do_devset(ide_drive_t *drive, struct request *rq) return ide_stopped; } -static ide_startstop_t ide_do_park_unpark(ide_drive_t *drive, struct request *rq) -{ - ide_task_t task; - struct ide_taskfile *tf = &task.tf; - - memset(&task, 0, sizeof(task)); - if (rq->cmd[0] == REQ_PARK_HEADS) { - drive->sleep = *(unsigned long *)rq->special; - drive->dev_flags |= IDE_DFLAG_SLEEPING; - tf->command = ATA_CMD_IDLEIMMEDIATE; - tf->feature = 0x44; - tf->lbal = 0x4c; - tf->lbam = 0x4e; - tf->lbah = 0x55; - task.tf_flags |= IDE_TFLAG_CUSTOM_HANDLER; - } else /* cmd == REQ_UNPARK_HEADS */ - tf->command = ATA_CMD_CHK_POWER; - - task.tf_flags |= IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - task.rq = rq; - drive->hwif->data_phase = task.data_phase = TASKFILE_NO_DATA; - return do_rw_taskfile(drive, &task); -} - static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq) { u8 cmd = rq->cmd[0]; diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c index c875a957596..f30e52152fc 100644 --- a/drivers/ide/ide-park.c +++ b/drivers/ide/ide-park.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -60,6 +61,30 @@ out: return; } +ide_startstop_t ide_do_park_unpark(ide_drive_t *drive, struct request *rq) +{ + ide_task_t task; + struct ide_taskfile *tf = &task.tf; + + memset(&task, 0, sizeof(task)); + if (rq->cmd[0] == REQ_PARK_HEADS) { + drive->sleep = *(unsigned long *)rq->special; + drive->dev_flags |= IDE_DFLAG_SLEEPING; + tf->command = ATA_CMD_IDLEIMMEDIATE; + tf->feature = 0x44; + tf->lbal = 0x4c; + tf->lbam = 0x4e; + tf->lbah = 0x55; + task.tf_flags |= IDE_TFLAG_CUSTOM_HANDLER; + } else /* cmd == REQ_UNPARK_HEADS */ + tf->command = ATA_CMD_CHK_POWER; + + task.tf_flags |= IDE_TFLAG_TF | IDE_TFLAG_DEVICE; + task.rq = rq; + drive->hwif->data_phase = task.data_phase = TASKFILE_NO_DATA; + return do_rw_taskfile(drive, &task); +} + ssize_t ide_park_show(struct device *dev, struct device_attribute *attr, char *buf) { diff --git a/include/linux/ide.h b/include/linux/ide.h index 8fadffe53cd..110d2635989 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1169,6 +1169,8 @@ int ide_busy_sleep(ide_hwif_t *, unsigned long, int); int ide_wait_stat(ide_startstop_t *, ide_drive_t *, u8, u8, unsigned long); +ide_startstop_t ide_do_park_unpark(ide_drive_t *, struct request *); + extern ide_startstop_t ide_do_reset (ide_drive_t *); extern int ide_devset_execute(ide_drive_t *drive, -- GitLab From 11938c929022bb92b1a42f5e1289524a1e465dc0 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:44 +0100 Subject: [PATCH 4245/4982] ide: move device settings code to ide-devsets.c Remove stale comment from ide.c while at it. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/Makefile | 3 +- drivers/ide/ide-devsets.c | 190 ++++++++++++++++++++++++++++++++++++++ drivers/ide/ide-io.c | 37 -------- drivers/ide/ide.c | 154 ------------------------------ include/linux/ide.h | 1 + 5 files changed, 193 insertions(+), 192 deletions(-) create mode 100644 drivers/ide/ide-devsets.c diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 1c326d94aa6..83a970ee4bf 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -5,7 +5,8 @@ EXTRA_CFLAGS += -Idrivers/ide ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \ - ide-taskfile.o ide-pm.o ide-park.o ide-pio-blacklist.o ide-sysfs.o + ide-taskfile.o ide-pm.o ide-park.o ide-pio-blacklist.o \ + ide-sysfs.o ide-devsets.o # core IDE code ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o diff --git a/drivers/ide/ide-devsets.c b/drivers/ide/ide-devsets.c new file mode 100644 index 00000000000..7c3953414d4 --- /dev/null +++ b/drivers/ide/ide-devsets.c @@ -0,0 +1,190 @@ + +#include +#include + +DEFINE_MUTEX(ide_setting_mtx); + +ide_devset_get(io_32bit, io_32bit); + +static int set_io_32bit(ide_drive_t *drive, int arg) +{ + if (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT) + return -EPERM; + + if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1)) + return -EINVAL; + + drive->io_32bit = arg; + + return 0; +} + +ide_devset_get_flag(ksettings, IDE_DFLAG_KEEP_SETTINGS); + +static int set_ksettings(ide_drive_t *drive, int arg) +{ + if (arg < 0 || arg > 1) + return -EINVAL; + + if (arg) + drive->dev_flags |= IDE_DFLAG_KEEP_SETTINGS; + else + drive->dev_flags &= ~IDE_DFLAG_KEEP_SETTINGS; + + return 0; +} + +ide_devset_get_flag(using_dma, IDE_DFLAG_USING_DMA); + +static int set_using_dma(ide_drive_t *drive, int arg) +{ +#ifdef CONFIG_BLK_DEV_IDEDMA + int err = -EPERM; + + if (arg < 0 || arg > 1) + return -EINVAL; + + if (ata_id_has_dma(drive->id) == 0) + goto out; + + if (drive->hwif->dma_ops == NULL) + goto out; + + err = 0; + + if (arg) { + if (ide_set_dma(drive)) + err = -EIO; + } else + ide_dma_off(drive); + +out: + return err; +#else + if (arg < 0 || arg > 1) + return -EINVAL; + + return -EPERM; +#endif +} + +/* + * handle HDIO_SET_PIO_MODE ioctl abusers here, eventually it will go away + */ +static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio) +{ + switch (req_pio) { + case 202: + case 201: + case 200: + case 102: + case 101: + case 100: + return (hwif->host_flags & IDE_HFLAG_ABUSE_DMA_MODES) ? 1 : 0; + case 9: + case 8: + return (hwif->host_flags & IDE_HFLAG_ABUSE_PREFETCH) ? 1 : 0; + case 7: + case 6: + return (hwif->host_flags & IDE_HFLAG_ABUSE_FAST_DEVSEL) ? 1 : 0; + default: + return 0; + } +} + +static int set_pio_mode(ide_drive_t *drive, int arg) +{ + ide_hwif_t *hwif = drive->hwif; + const struct ide_port_ops *port_ops = hwif->port_ops; + + if (arg < 0 || arg > 255) + return -EINVAL; + + if (port_ops == NULL || port_ops->set_pio_mode == NULL || + (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) + return -ENOSYS; + + if (set_pio_mode_abuse(drive->hwif, arg)) { + if (arg == 8 || arg == 9) { + unsigned long flags; + + /* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */ + spin_lock_irqsave(&hwif->lock, flags); + port_ops->set_pio_mode(drive, arg); + spin_unlock_irqrestore(&hwif->lock, flags); + } else + port_ops->set_pio_mode(drive, arg); + } else { + int keep_dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA); + + ide_set_pio(drive, arg); + + if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) { + if (keep_dma) + ide_dma_on(drive); + } + } + + return 0; +} + +ide_devset_get_flag(unmaskirq, IDE_DFLAG_UNMASK); + +static int set_unmaskirq(ide_drive_t *drive, int arg) +{ + if (drive->dev_flags & IDE_DFLAG_NO_UNMASK) + return -EPERM; + + if (arg < 0 || arg > 1) + return -EINVAL; + + if (arg) + drive->dev_flags |= IDE_DFLAG_UNMASK; + else + drive->dev_flags &= ~IDE_DFLAG_UNMASK; + + return 0; +} + +ide_ext_devset_rw_sync(io_32bit, io_32bit); +ide_ext_devset_rw_sync(keepsettings, ksettings); +ide_ext_devset_rw_sync(unmaskirq, unmaskirq); +ide_ext_devset_rw_sync(using_dma, using_dma); +__IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode); + +int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting, + int arg) +{ + struct request_queue *q = drive->queue; + struct request *rq; + int ret = 0; + + if (!(setting->flags & DS_SYNC)) + return setting->set(drive, arg); + + rq = blk_get_request(q, READ, __GFP_WAIT); + rq->cmd_type = REQ_TYPE_SPECIAL; + rq->cmd_len = 5; + rq->cmd[0] = REQ_DEVSET_EXEC; + *(int *)&rq->cmd[1] = arg; + rq->special = setting->set; + + if (blk_execute_rq(q, NULL, rq, 0)) + ret = rq->errors; + blk_put_request(rq); + + return ret; +} + +ide_startstop_t ide_do_devset(ide_drive_t *drive, struct request *rq) +{ + int err, (*setfunc)(ide_drive_t *, int) = rq->special; + + err = setfunc(drive, *(int *)&rq->cmd[1]); + if (err) + rq->errors = err; + else + err = 1; + ide_end_request(drive, err, 0); + return ide_stopped; +} diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 16e47989fcf..74d1a3e6825 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -490,43 +490,6 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, return ide_stopped; } -int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting, - int arg) -{ - struct request_queue *q = drive->queue; - struct request *rq; - int ret = 0; - - if (!(setting->flags & DS_SYNC)) - return setting->set(drive, arg); - - rq = blk_get_request(q, READ, __GFP_WAIT); - rq->cmd_type = REQ_TYPE_SPECIAL; - rq->cmd_len = 5; - rq->cmd[0] = REQ_DEVSET_EXEC; - *(int *)&rq->cmd[1] = arg; - rq->special = setting->set; - - if (blk_execute_rq(q, NULL, rq, 0)) - ret = rq->errors; - blk_put_request(rq); - - return ret; -} - -static ide_startstop_t ide_do_devset(ide_drive_t *drive, struct request *rq) -{ - int err, (*setfunc)(ide_drive_t *, int) = rq->special; - - err = setfunc(drive, *(int *)&rq->cmd[1]); - if (err) - rq->errors = err; - else - err = 1; - ide_end_request(drive, err, 0); - return ide_stopped; -} - static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq) { u8 cmd = rq->cmd[0]; diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index c779aa24dbe..92c9b90931e 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -62,160 +62,6 @@ struct class *ide_port_class; -/* - * Locks for IDE setting functionality - */ - -DEFINE_MUTEX(ide_setting_mtx); - -ide_devset_get(io_32bit, io_32bit); - -static int set_io_32bit(ide_drive_t *drive, int arg) -{ - if (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT) - return -EPERM; - - if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1)) - return -EINVAL; - - drive->io_32bit = arg; - - return 0; -} - -ide_devset_get_flag(ksettings, IDE_DFLAG_KEEP_SETTINGS); - -static int set_ksettings(ide_drive_t *drive, int arg) -{ - if (arg < 0 || arg > 1) - return -EINVAL; - - if (arg) - drive->dev_flags |= IDE_DFLAG_KEEP_SETTINGS; - else - drive->dev_flags &= ~IDE_DFLAG_KEEP_SETTINGS; - - return 0; -} - -ide_devset_get_flag(using_dma, IDE_DFLAG_USING_DMA); - -static int set_using_dma(ide_drive_t *drive, int arg) -{ -#ifdef CONFIG_BLK_DEV_IDEDMA - int err = -EPERM; - - if (arg < 0 || arg > 1) - return -EINVAL; - - if (ata_id_has_dma(drive->id) == 0) - goto out; - - if (drive->hwif->dma_ops == NULL) - goto out; - - err = 0; - - if (arg) { - if (ide_set_dma(drive)) - err = -EIO; - } else - ide_dma_off(drive); - -out: - return err; -#else - if (arg < 0 || arg > 1) - return -EINVAL; - - return -EPERM; -#endif -} - -/* - * handle HDIO_SET_PIO_MODE ioctl abusers here, eventually it will go away - */ -static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio) -{ - switch (req_pio) { - case 202: - case 201: - case 200: - case 102: - case 101: - case 100: - return (hwif->host_flags & IDE_HFLAG_ABUSE_DMA_MODES) ? 1 : 0; - case 9: - case 8: - return (hwif->host_flags & IDE_HFLAG_ABUSE_PREFETCH) ? 1 : 0; - case 7: - case 6: - return (hwif->host_flags & IDE_HFLAG_ABUSE_FAST_DEVSEL) ? 1 : 0; - default: - return 0; - } -} - -static int set_pio_mode(ide_drive_t *drive, int arg) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_port_ops *port_ops = hwif->port_ops; - - if (arg < 0 || arg > 255) - return -EINVAL; - - if (port_ops == NULL || port_ops->set_pio_mode == NULL || - (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) - return -ENOSYS; - - if (set_pio_mode_abuse(drive->hwif, arg)) { - if (arg == 8 || arg == 9) { - unsigned long flags; - - /* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */ - spin_lock_irqsave(&hwif->lock, flags); - port_ops->set_pio_mode(drive, arg); - spin_unlock_irqrestore(&hwif->lock, flags); - } else - port_ops->set_pio_mode(drive, arg); - } else { - int keep_dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA); - - ide_set_pio(drive, arg); - - if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) { - if (keep_dma) - ide_dma_on(drive); - } - } - - return 0; -} - -ide_devset_get_flag(unmaskirq, IDE_DFLAG_UNMASK); - -static int set_unmaskirq(ide_drive_t *drive, int arg) -{ - if (drive->dev_flags & IDE_DFLAG_NO_UNMASK) - return -EPERM; - - if (arg < 0 || arg > 1) - return -EINVAL; - - if (arg) - drive->dev_flags |= IDE_DFLAG_UNMASK; - else - drive->dev_flags &= ~IDE_DFLAG_UNMASK; - - return 0; -} - -ide_ext_devset_rw_sync(io_32bit, io_32bit); -ide_ext_devset_rw_sync(keepsettings, ksettings); -ide_ext_devset_rw_sync(unmaskirq, unmaskirq); -ide_ext_devset_rw_sync(using_dma, using_dma); -__IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode); - /** * ide_device_get - get an additional reference to a ide_drive_t * @drive: device to get a reference to diff --git a/include/linux/ide.h b/include/linux/ide.h index 110d2635989..eca5082c343 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1170,6 +1170,7 @@ int ide_busy_sleep(ide_hwif_t *, unsigned long, int); int ide_wait_stat(ide_startstop_t *, ide_drive_t *, u8, u8, unsigned long); ide_startstop_t ide_do_park_unpark(ide_drive_t *, struct request *); +ide_startstop_t ide_do_devset(ide_drive_t *, struct request *); extern ide_startstop_t ide_do_reset (ide_drive_t *); -- GitLab From 7eeaaaa52285d5e6cb79f515e99c591dcb9d04fe Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:46 +0100 Subject: [PATCH 4246/4982] ide: move xfer mode tuning code to ide-xfer-mode.c * Move xfer mode tuning code to ide-xfer-mode.c. * Add CONFIG_IDE_XFER_MODE config option to be selected by host drivers that support xfer mode tuning. * Add CONFIG_IDE_XFER_MODE=n static inline versions of ide_set_pio() and ide_set_xfer_rate(). * Make IDE_TIMINGS and BLK_DEV_IDEDMA config options select IDE_XFER_MODE, also add explicit selects for few host drivers that need it. * Build/link ide-xfer-mode.o and ide-pio-blacklist.o (it is needed only by ide-xfer-mode.o) only if CONFIG_IDE_XFER_MODE=y. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/Kconfig | 8 ++ drivers/ide/Makefile | 4 +- drivers/ide/ide-lib.c | 240 ----------------------------------- drivers/ide/ide-xfer-mode.c | 246 ++++++++++++++++++++++++++++++++++++ include/linux/ide.h | 12 +- 5 files changed, 263 insertions(+), 247 deletions(-) create mode 100644 drivers/ide/ide-xfer-mode.c diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 5ea3bfad172..640c9920724 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -56,8 +56,12 @@ if IDE comment "Please see Documentation/ide/ide.txt for help/info on IDE drives" +config IDE_XFER_MODE + bool + config IDE_TIMINGS bool + select IDE_XFER_MODE config IDE_ATAPI bool @@ -698,6 +702,7 @@ config BLK_DEV_IDE_PMAC_ATA100FIRST config BLK_DEV_IDE_AU1XXX bool "IDE for AMD Alchemy Au1200" depends on SOC_AU1200 + select IDE_XFER_MODE choice prompt "IDE Mode for AMD Alchemy Au1200" default CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA @@ -871,6 +876,7 @@ config BLK_DEV_ALI14XX config BLK_DEV_DTC2278 tristate "DTC-2278 support" + select IDE_XFER_MODE select IDE_LEGACY help This driver is enabled at runtime using the "dtc2278.probe" kernel @@ -902,6 +908,7 @@ config BLK_DEV_QD65XX config BLK_DEV_UMC8672 tristate "UMC-8672 support" + select IDE_XFER_MODE select IDE_LEGACY help This driver is enabled at runtime using the "umc8672.probe" kernel @@ -915,5 +922,6 @@ endif config BLK_DEV_IDEDMA def_bool BLK_DEV_IDEDMA_SFF || \ BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA + select IDE_XFER_MODE endif # IDE diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 83a970ee4bf..d0976e6ee09 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -5,10 +5,10 @@ EXTRA_CFLAGS += -Idrivers/ide ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \ - ide-taskfile.o ide-pm.o ide-park.o ide-pio-blacklist.o \ - ide-sysfs.o ide-devsets.o + ide-taskfile.o ide-pm.o ide-park.o ide-sysfs.o ide-devsets.o # core IDE code +ide-core-$(CONFIG_IDE_XFER_MODE) += ide-pio-blacklist.o ide-xfer-mode.o ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o ide-core-$(CONFIG_IDE_ATAPI) += ide-atapi.o ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 09526a0de73..f6c683dd298 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -5,163 +5,6 @@ #include #include -static const char *udma_str[] = - { "UDMA/16", "UDMA/25", "UDMA/33", "UDMA/44", - "UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" }; -static const char *mwdma_str[] = - { "MWDMA0", "MWDMA1", "MWDMA2" }; -static const char *swdma_str[] = - { "SWDMA0", "SWDMA1", "SWDMA2" }; -static const char *pio_str[] = - { "PIO0", "PIO1", "PIO2", "PIO3", "PIO4", "PIO5" }; - -/** - * ide_xfer_verbose - return IDE mode names - * @mode: transfer mode - * - * Returns a constant string giving the name of the mode - * requested. - */ - -const char *ide_xfer_verbose(u8 mode) -{ - const char *s; - u8 i = mode & 0xf; - - if (mode >= XFER_UDMA_0 && mode <= XFER_UDMA_7) - s = udma_str[i]; - else if (mode >= XFER_MW_DMA_0 && mode <= XFER_MW_DMA_2) - s = mwdma_str[i]; - else if (mode >= XFER_SW_DMA_0 && mode <= XFER_SW_DMA_2) - s = swdma_str[i]; - else if (mode >= XFER_PIO_0 && mode <= XFER_PIO_5) - s = pio_str[i & 0x7]; - else if (mode == XFER_PIO_SLOW) - s = "PIO SLOW"; - else - s = "XFER ERROR"; - - return s; -} -EXPORT_SYMBOL(ide_xfer_verbose); - -/** - * ide_rate_filter - filter transfer mode - * @drive: IDE device - * @speed: desired speed - * - * Given the available transfer modes this function returns - * the best available speed at or below the speed requested. - * - * TODO: check device PIO capabilities - */ - -static u8 ide_rate_filter(ide_drive_t *drive, u8 speed) -{ - ide_hwif_t *hwif = drive->hwif; - u8 mode = ide_find_dma_mode(drive, speed); - - if (mode == 0) { - if (hwif->pio_mask) - mode = fls(hwif->pio_mask) - 1 + XFER_PIO_0; - else - mode = XFER_PIO_4; - } - -/* printk("%s: mode 0x%02x, speed 0x%02x\n", __func__, mode, speed); */ - - return min(speed, mode); -} - -/** - * ide_get_best_pio_mode - get PIO mode from drive - * @drive: drive to consider - * @mode_wanted: preferred mode - * @max_mode: highest allowed mode - * - * This routine returns the recommended PIO settings for a given drive, - * based on the drive->id information and the ide_pio_blacklist[]. - * - * Drive PIO mode is auto-selected if 255 is passed as mode_wanted. - * This is used by most chipset support modules when "auto-tuning". - */ - -u8 ide_get_best_pio_mode(ide_drive_t *drive, u8 mode_wanted, u8 max_mode) -{ - u16 *id = drive->id; - int pio_mode = -1, overridden = 0; - - if (mode_wanted != 255) - return min_t(u8, mode_wanted, max_mode); - - if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_BLACKLIST) == 0) - pio_mode = ide_scan_pio_blacklist((char *)&id[ATA_ID_PROD]); - - if (pio_mode != -1) { - printk(KERN_INFO "%s: is on PIO blacklist\n", drive->name); - } else { - pio_mode = id[ATA_ID_OLD_PIO_MODES] >> 8; - if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */ - pio_mode = 2; - overridden = 1; - } - - if (id[ATA_ID_FIELD_VALID] & 2) { /* ATA2? */ - if (ata_id_has_iordy(id)) { - if (id[ATA_ID_PIO_MODES] & 7) { - overridden = 0; - if (id[ATA_ID_PIO_MODES] & 4) - pio_mode = 5; - else if (id[ATA_ID_PIO_MODES] & 2) - pio_mode = 4; - else - pio_mode = 3; - } - } - } - - if (overridden) - printk(KERN_INFO "%s: tPIO > 2, assuming tPIO = 2\n", - drive->name); - } - - if (pio_mode > max_mode) - pio_mode = max_mode; - - return pio_mode; -} -EXPORT_SYMBOL_GPL(ide_get_best_pio_mode); - -/* req_pio == "255" for auto-tune */ -void ide_set_pio(ide_drive_t *drive, u8 req_pio) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_port_ops *port_ops = hwif->port_ops; - u8 host_pio, pio; - - if (port_ops == NULL || port_ops->set_pio_mode == NULL || - (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) - return; - - BUG_ON(hwif->pio_mask == 0x00); - - host_pio = fls(hwif->pio_mask) - 1; - - pio = ide_get_best_pio_mode(drive, req_pio, host_pio); - - /* - * TODO: - * - report device max PIO mode - * - check req_pio != 255 against device max PIO mode - */ - printk(KERN_DEBUG "%s: host max PIO%d wanted PIO%d%s selected PIO%d\n", - drive->name, host_pio, req_pio, - req_pio == 255 ? "(auto-tune)" : "", pio); - - (void)ide_set_pio_mode(drive, XFER_PIO_0 + pio); -} -EXPORT_SYMBOL_GPL(ide_set_pio); - /** * ide_toggle_bounce - handle bounce buffering * @drive: drive to update @@ -188,89 +31,6 @@ void ide_toggle_bounce(ide_drive_t *drive, int on) blk_queue_bounce_limit(drive->queue, addr); } -int ide_set_pio_mode(ide_drive_t *drive, const u8 mode) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_port_ops *port_ops = hwif->port_ops; - - if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE) - return 0; - - if (port_ops == NULL || port_ops->set_pio_mode == NULL) - return -1; - - /* - * TODO: temporary hack for some legacy host drivers that didn't - * set transfer mode on the device in ->set_pio_mode method... - */ - if (port_ops->set_dma_mode == NULL) { - port_ops->set_pio_mode(drive, mode - XFER_PIO_0); - return 0; - } - - if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) { - if (ide_config_drive_speed(drive, mode)) - return -1; - port_ops->set_pio_mode(drive, mode - XFER_PIO_0); - return 0; - } else { - port_ops->set_pio_mode(drive, mode - XFER_PIO_0); - return ide_config_drive_speed(drive, mode); - } -} - -int ide_set_dma_mode(ide_drive_t *drive, const u8 mode) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_port_ops *port_ops = hwif->port_ops; - - if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE) - return 0; - - if (port_ops == NULL || port_ops->set_dma_mode == NULL) - return -1; - - if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) { - if (ide_config_drive_speed(drive, mode)) - return -1; - port_ops->set_dma_mode(drive, mode); - return 0; - } else { - port_ops->set_dma_mode(drive, mode); - return ide_config_drive_speed(drive, mode); - } -} -EXPORT_SYMBOL_GPL(ide_set_dma_mode); - -/** - * ide_set_xfer_rate - set transfer rate - * @drive: drive to set - * @rate: speed to attempt to set - * - * General helper for setting the speed of an IDE device. This - * function knows about user enforced limits from the configuration - * which ->set_pio_mode/->set_dma_mode does not. - */ - -int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_port_ops *port_ops = hwif->port_ops; - - if (port_ops == NULL || port_ops->set_dma_mode == NULL || - (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) - return -1; - - rate = ide_rate_filter(drive, rate); - - BUG_ON(rate < XFER_PIO_0); - - if (rate >= XFER_PIO_0 && rate <= XFER_PIO_5) - return ide_set_pio_mode(drive, rate); - - return ide_set_dma_mode(drive, rate); -} - static void ide_dump_opcode(ide_drive_t *drive) { struct request *rq = drive->hwif->rq; diff --git a/drivers/ide/ide-xfer-mode.c b/drivers/ide/ide-xfer-mode.c new file mode 100644 index 00000000000..6910f6a257e --- /dev/null +++ b/drivers/ide/ide-xfer-mode.c @@ -0,0 +1,246 @@ +#include +#include +#include +#include +#include +#include + +static const char *udma_str[] = + { "UDMA/16", "UDMA/25", "UDMA/33", "UDMA/44", + "UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" }; +static const char *mwdma_str[] = + { "MWDMA0", "MWDMA1", "MWDMA2" }; +static const char *swdma_str[] = + { "SWDMA0", "SWDMA1", "SWDMA2" }; +static const char *pio_str[] = + { "PIO0", "PIO1", "PIO2", "PIO3", "PIO4", "PIO5" }; + +/** + * ide_xfer_verbose - return IDE mode names + * @mode: transfer mode + * + * Returns a constant string giving the name of the mode + * requested. + */ + +const char *ide_xfer_verbose(u8 mode) +{ + const char *s; + u8 i = mode & 0xf; + + if (mode >= XFER_UDMA_0 && mode <= XFER_UDMA_7) + s = udma_str[i]; + else if (mode >= XFER_MW_DMA_0 && mode <= XFER_MW_DMA_2) + s = mwdma_str[i]; + else if (mode >= XFER_SW_DMA_0 && mode <= XFER_SW_DMA_2) + s = swdma_str[i]; + else if (mode >= XFER_PIO_0 && mode <= XFER_PIO_5) + s = pio_str[i & 0x7]; + else if (mode == XFER_PIO_SLOW) + s = "PIO SLOW"; + else + s = "XFER ERROR"; + + return s; +} +EXPORT_SYMBOL(ide_xfer_verbose); + +/** + * ide_get_best_pio_mode - get PIO mode from drive + * @drive: drive to consider + * @mode_wanted: preferred mode + * @max_mode: highest allowed mode + * + * This routine returns the recommended PIO settings for a given drive, + * based on the drive->id information and the ide_pio_blacklist[]. + * + * Drive PIO mode is auto-selected if 255 is passed as mode_wanted. + * This is used by most chipset support modules when "auto-tuning". + */ + +u8 ide_get_best_pio_mode(ide_drive_t *drive, u8 mode_wanted, u8 max_mode) +{ + u16 *id = drive->id; + int pio_mode = -1, overridden = 0; + + if (mode_wanted != 255) + return min_t(u8, mode_wanted, max_mode); + + if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_BLACKLIST) == 0) + pio_mode = ide_scan_pio_blacklist((char *)&id[ATA_ID_PROD]); + + if (pio_mode != -1) { + printk(KERN_INFO "%s: is on PIO blacklist\n", drive->name); + } else { + pio_mode = id[ATA_ID_OLD_PIO_MODES] >> 8; + if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */ + pio_mode = 2; + overridden = 1; + } + + if (id[ATA_ID_FIELD_VALID] & 2) { /* ATA2? */ + if (ata_id_has_iordy(id)) { + if (id[ATA_ID_PIO_MODES] & 7) { + overridden = 0; + if (id[ATA_ID_PIO_MODES] & 4) + pio_mode = 5; + else if (id[ATA_ID_PIO_MODES] & 2) + pio_mode = 4; + else + pio_mode = 3; + } + } + } + + if (overridden) + printk(KERN_INFO "%s: tPIO > 2, assuming tPIO = 2\n", + drive->name); + } + + if (pio_mode > max_mode) + pio_mode = max_mode; + + return pio_mode; +} +EXPORT_SYMBOL_GPL(ide_get_best_pio_mode); + +int ide_set_pio_mode(ide_drive_t *drive, const u8 mode) +{ + ide_hwif_t *hwif = drive->hwif; + const struct ide_port_ops *port_ops = hwif->port_ops; + + if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE) + return 0; + + if (port_ops == NULL || port_ops->set_pio_mode == NULL) + return -1; + + /* + * TODO: temporary hack for some legacy host drivers that didn't + * set transfer mode on the device in ->set_pio_mode method... + */ + if (port_ops->set_dma_mode == NULL) { + port_ops->set_pio_mode(drive, mode - XFER_PIO_0); + return 0; + } + + if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) { + if (ide_config_drive_speed(drive, mode)) + return -1; + port_ops->set_pio_mode(drive, mode - XFER_PIO_0); + return 0; + } else { + port_ops->set_pio_mode(drive, mode - XFER_PIO_0); + return ide_config_drive_speed(drive, mode); + } +} + +int ide_set_dma_mode(ide_drive_t *drive, const u8 mode) +{ + ide_hwif_t *hwif = drive->hwif; + const struct ide_port_ops *port_ops = hwif->port_ops; + + if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE) + return 0; + + if (port_ops == NULL || port_ops->set_dma_mode == NULL) + return -1; + + if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) { + if (ide_config_drive_speed(drive, mode)) + return -1; + port_ops->set_dma_mode(drive, mode); + return 0; + } else { + port_ops->set_dma_mode(drive, mode); + return ide_config_drive_speed(drive, mode); + } +} +EXPORT_SYMBOL_GPL(ide_set_dma_mode); + +/* req_pio == "255" for auto-tune */ +void ide_set_pio(ide_drive_t *drive, u8 req_pio) +{ + ide_hwif_t *hwif = drive->hwif; + const struct ide_port_ops *port_ops = hwif->port_ops; + u8 host_pio, pio; + + if (port_ops == NULL || port_ops->set_pio_mode == NULL || + (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) + return; + + BUG_ON(hwif->pio_mask == 0x00); + + host_pio = fls(hwif->pio_mask) - 1; + + pio = ide_get_best_pio_mode(drive, req_pio, host_pio); + + /* + * TODO: + * - report device max PIO mode + * - check req_pio != 255 against device max PIO mode + */ + printk(KERN_DEBUG "%s: host max PIO%d wanted PIO%d%s selected PIO%d\n", + drive->name, host_pio, req_pio, + req_pio == 255 ? "(auto-tune)" : "", pio); + + (void)ide_set_pio_mode(drive, XFER_PIO_0 + pio); +} +EXPORT_SYMBOL_GPL(ide_set_pio); + +/** + * ide_rate_filter - filter transfer mode + * @drive: IDE device + * @speed: desired speed + * + * Given the available transfer modes this function returns + * the best available speed at or below the speed requested. + * + * TODO: check device PIO capabilities + */ + +static u8 ide_rate_filter(ide_drive_t *drive, u8 speed) +{ + ide_hwif_t *hwif = drive->hwif; + u8 mode = ide_find_dma_mode(drive, speed); + + if (mode == 0) { + if (hwif->pio_mask) + mode = fls(hwif->pio_mask) - 1 + XFER_PIO_0; + else + mode = XFER_PIO_4; + } + +/* printk("%s: mode 0x%02x, speed 0x%02x\n", __func__, mode, speed); */ + + return min(speed, mode); +} + +/** + * ide_set_xfer_rate - set transfer rate + * @drive: drive to set + * @rate: speed to attempt to set + * + * General helper for setting the speed of an IDE device. This + * function knows about user enforced limits from the configuration + * which ->set_pio_mode/->set_dma_mode does not. + */ + +int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) +{ + ide_hwif_t *hwif = drive->hwif; + const struct ide_port_ops *port_ops = hwif->port_ops; + + if (port_ops == NULL || port_ops->set_dma_mode == NULL || + (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) + return -1; + + rate = ide_rate_filter(drive, rate); + + BUG_ON(rate < XFER_PIO_0); + + if (rate >= XFER_PIO_0 && rate <= XFER_PIO_5) + return ide_set_pio_mode(drive, rate); + + return ide_set_dma_mode(drive, rate); +} diff --git a/include/linux/ide.h b/include/linux/ide.h index eca5082c343..323c3710fbf 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1531,9 +1531,7 @@ static inline void ide_set_hwifdata (ide_hwif_t * hwif, void *data) hwif->hwif_data = data; } -const char *ide_xfer_verbose(u8 mode); extern void ide_toggle_bounce(ide_drive_t *drive, int on); -extern int ide_set_xfer_rate(ide_drive_t *drive, u8 rate); u64 ide_get_lba_addr(struct ide_taskfile *, int); u8 ide_dump_status(ide_drive_t *, const char *, u8); @@ -1572,14 +1570,18 @@ void ide_timing_merge(struct ide_timing *, struct ide_timing *, struct ide_timing *, unsigned int); int ide_timing_compute(ide_drive_t *, u8, struct ide_timing *, int, int); +#ifdef CONFIG_IDE_XFER_MODE int ide_scan_pio_blacklist(char *); - +const char *ide_xfer_verbose(u8); u8 ide_get_best_pio_mode(ide_drive_t *, u8, u8); - int ide_set_pio_mode(ide_drive_t *, u8); int ide_set_dma_mode(ide_drive_t *, u8); - void ide_set_pio(ide_drive_t *, u8); +int ide_set_xfer_rate(ide_drive_t *, u8); +#else +static inline void ide_set_pio(ide_drive_t *drive, u8 pio) { ; } +static inline int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) { return -1; } +#endif static inline void ide_set_max_pio(ide_drive_t *drive) { -- GitLab From 0d6a9754c06e173552b0ad5fad45f69786b6de99 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:46 +0100 Subject: [PATCH 4247/4982] ide: move ide_read_bcount_and_ireason() to ide-atapi.c Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-atapi.c | 15 +++++++++++++++ drivers/ide/ide-iops.c | 15 --------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 3044c51c06a..6adc5b4a440 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -300,6 +300,21 @@ int ide_cd_get_xferlen(struct request *rq) } EXPORT_SYMBOL_GPL(ide_cd_get_xferlen); +void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason) +{ + ide_task_t task; + + memset(&task, 0, sizeof(task)); + task.tf_flags = IDE_TFLAG_IN_LBAH | IDE_TFLAG_IN_LBAM | + IDE_TFLAG_IN_NSECT; + + drive->hwif->tp_ops->tf_read(drive, &task); + + *bcount = (task.tf.lbah << 8) | task.tf.lbam; + *ireason = task.tf.nsect & 3; +} +EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason); + /* * This is the usual interrupt handler which will be called during a packet * command. We will transfer some of the data (as requested by the drive) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index ee9c6034278..d24add69212 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -362,21 +362,6 @@ u8 ide_read_error(ide_drive_t *drive) } EXPORT_SYMBOL_GPL(ide_read_error); -void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason) -{ - ide_task_t task; - - memset(&task, 0, sizeof(task)); - task.tf_flags = IDE_TFLAG_IN_LBAH | IDE_TFLAG_IN_LBAM | - IDE_TFLAG_IN_NSECT; - - drive->hwif->tp_ops->tf_read(drive, &task); - - *bcount = (task.tf.lbah << 8) | task.tf.lbam; - *ireason = task.tf.nsect & 3; -} -EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason); - const struct ide_tp_ops default_tp_ops = { .exec_command = ide_exec_command, .read_status = ide_read_status, -- GitLab From 1574cf6cb4800525be769ee6023c567113fa2d18 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:46 +0100 Subject: [PATCH 4248/4982] ide: move standard I/O code to ide-io-std.c Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/Makefile | 3 +- drivers/ide/ide-io-std.c | 316 +++++++++++++++++++++++++++++++++++++++ drivers/ide/ide-iops.c | 313 -------------------------------------- 3 files changed, 318 insertions(+), 314 deletions(-) create mode 100644 drivers/ide/ide-io-std.c diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index d0976e6ee09..cbb1aea2aea 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -5,7 +5,8 @@ EXTRA_CFLAGS += -Idrivers/ide ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \ - ide-taskfile.o ide-pm.o ide-park.o ide-sysfs.o ide-devsets.o + ide-taskfile.o ide-pm.o ide-park.o ide-sysfs.o ide-devsets.o \ + ide-io-std.o # core IDE code ide-core-$(CONFIG_IDE_XFER_MODE) += ide-pio-blacklist.o ide-xfer-mode.o diff --git a/drivers/ide/ide-io-std.c b/drivers/ide/ide-io-std.c new file mode 100644 index 00000000000..45b43dd49cd --- /dev/null +++ b/drivers/ide/ide-io-std.c @@ -0,0 +1,316 @@ + +#include +#include + +/* + * Conventional PIO operations for ATA devices + */ + +static u8 ide_inb(unsigned long port) +{ + return (u8) inb(port); +} + +static void ide_outb(u8 val, unsigned long port) +{ + outb(val, port); +} + +/* + * MMIO operations, typically used for SATA controllers + */ + +static u8 ide_mm_inb(unsigned long port) +{ + return (u8) readb((void __iomem *) port); +} + +static void ide_mm_outb(u8 value, unsigned long port) +{ + writeb(value, (void __iomem *) port); +} + +void ide_exec_command(ide_hwif_t *hwif, u8 cmd) +{ + if (hwif->host_flags & IDE_HFLAG_MMIO) + writeb(cmd, (void __iomem *)hwif->io_ports.command_addr); + else + outb(cmd, hwif->io_ports.command_addr); +} +EXPORT_SYMBOL_GPL(ide_exec_command); + +u8 ide_read_status(ide_hwif_t *hwif) +{ + if (hwif->host_flags & IDE_HFLAG_MMIO) + return readb((void __iomem *)hwif->io_ports.status_addr); + else + return inb(hwif->io_ports.status_addr); +} +EXPORT_SYMBOL_GPL(ide_read_status); + +u8 ide_read_altstatus(ide_hwif_t *hwif) +{ + if (hwif->host_flags & IDE_HFLAG_MMIO) + return readb((void __iomem *)hwif->io_ports.ctl_addr); + else + return inb(hwif->io_ports.ctl_addr); +} +EXPORT_SYMBOL_GPL(ide_read_altstatus); + +void ide_set_irq(ide_hwif_t *hwif, int on) +{ + u8 ctl = ATA_DEVCTL_OBS; + + if (on == 4) { /* hack for SRST */ + ctl |= 4; + on &= ~4; + } + + ctl |= on ? 0 : 2; + + if (hwif->host_flags & IDE_HFLAG_MMIO) + writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr); + else + outb(ctl, hwif->io_ports.ctl_addr); +} +EXPORT_SYMBOL_GPL(ide_set_irq); + +void ide_tf_load(ide_drive_t *drive, ide_task_t *task) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + struct ide_taskfile *tf = &task->tf; + void (*tf_outb)(u8 addr, unsigned long port); + u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; + u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; + + if (mmio) + tf_outb = ide_mm_outb; + else + tf_outb = ide_outb; + + if (task->tf_flags & IDE_TFLAG_FLAGGED) + HIHI = 0xFF; + + if (task->tf_flags & IDE_TFLAG_OUT_DATA) { + u16 data = (tf->hob_data << 8) | tf->data; + + if (mmio) + writew(data, (void __iomem *)io_ports->data_addr); + else + outw(data, io_ports->data_addr); + } + + if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) + tf_outb(tf->hob_feature, io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) + tf_outb(tf->hob_nsect, io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) + tf_outb(tf->hob_lbal, io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) + tf_outb(tf->hob_lbam, io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) + tf_outb(tf->hob_lbah, io_ports->lbah_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) + tf_outb(tf->feature, io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_OUT_NSECT) + tf_outb(tf->nsect, io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAL) + tf_outb(tf->lbal, io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAM) + tf_outb(tf->lbam, io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAH) + tf_outb(tf->lbah, io_ports->lbah_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) + tf_outb((tf->device & HIHI) | drive->select, + io_ports->device_addr); +} +EXPORT_SYMBOL_GPL(ide_tf_load); + +void ide_tf_read(ide_drive_t *drive, ide_task_t *task) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + struct ide_taskfile *tf = &task->tf; + void (*tf_outb)(u8 addr, unsigned long port); + u8 (*tf_inb)(unsigned long port); + u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; + + if (mmio) { + tf_outb = ide_mm_outb; + tf_inb = ide_mm_inb; + } else { + tf_outb = ide_outb; + tf_inb = ide_inb; + } + + if (task->tf_flags & IDE_TFLAG_IN_DATA) { + u16 data; + + if (mmio) + data = readw((void __iomem *)io_ports->data_addr); + else + data = inw(io_ports->data_addr); + + tf->data = data & 0xff; + tf->hob_data = (data >> 8) & 0xff; + } + + /* be sure we're looking at the low order bits */ + tf_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_FEATURE) + tf->feature = tf_inb(io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_IN_NSECT) + tf->nsect = tf_inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAL) + tf->lbal = tf_inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAM) + tf->lbam = tf_inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAH) + tf->lbah = tf_inb(io_ports->lbah_addr); + if (task->tf_flags & IDE_TFLAG_IN_DEVICE) + tf->device = tf_inb(io_ports->device_addr); + + if (task->tf_flags & IDE_TFLAG_LBA48) { + tf_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) + tf->hob_feature = tf_inb(io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) + tf->hob_nsect = tf_inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) + tf->hob_lbal = tf_inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) + tf->hob_lbam = tf_inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) + tf->hob_lbah = tf_inb(io_ports->lbah_addr); + } +} +EXPORT_SYMBOL_GPL(ide_tf_read); + +/* + * Some localbus EIDE interfaces require a special access sequence + * when using 32-bit I/O instructions to transfer data. We call this + * the "vlb_sync" sequence, which consists of three successive reads + * of the sector count register location, with interrupts disabled + * to ensure that the reads all happen together. + */ +static void ata_vlb_sync(unsigned long port) +{ + (void)inb(port); + (void)inb(port); + (void)inb(port); +} + +/* + * This is used for most PIO data transfers *from* the IDE interface + * + * These routines will round up any request for an odd number of bytes, + * so if an odd len is specified, be sure that there's at least one + * extra byte allocated for the buffer. + */ +void ide_input_data(ide_drive_t *drive, struct request *rq, void *buf, + unsigned int len) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + unsigned long data_addr = io_ports->data_addr; + u8 io_32bit = drive->io_32bit; + u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; + + len++; + + if (io_32bit) { + unsigned long uninitialized_var(flags); + + if ((io_32bit & 2) && !mmio) { + local_irq_save(flags); + ata_vlb_sync(io_ports->nsect_addr); + } + + if (mmio) + __ide_mm_insl((void __iomem *)data_addr, buf, len / 4); + else + insl(data_addr, buf, len / 4); + + if ((io_32bit & 2) && !mmio) + local_irq_restore(flags); + + if ((len & 3) >= 2) { + if (mmio) + __ide_mm_insw((void __iomem *)data_addr, + (u8 *)buf + (len & ~3), 1); + else + insw(data_addr, (u8 *)buf + (len & ~3), 1); + } + } else { + if (mmio) + __ide_mm_insw((void __iomem *)data_addr, buf, len / 2); + else + insw(data_addr, buf, len / 2); + } +} +EXPORT_SYMBOL_GPL(ide_input_data); + +/* + * This is used for most PIO data transfers *to* the IDE interface + */ +void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf, + unsigned int len) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + unsigned long data_addr = io_ports->data_addr; + u8 io_32bit = drive->io_32bit; + u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; + + len++; + + if (io_32bit) { + unsigned long uninitialized_var(flags); + + if ((io_32bit & 2) && !mmio) { + local_irq_save(flags); + ata_vlb_sync(io_ports->nsect_addr); + } + + if (mmio) + __ide_mm_outsl((void __iomem *)data_addr, buf, len / 4); + else + outsl(data_addr, buf, len / 4); + + if ((io_32bit & 2) && !mmio) + local_irq_restore(flags); + + if ((len & 3) >= 2) { + if (mmio) + __ide_mm_outsw((void __iomem *)data_addr, + (u8 *)buf + (len & ~3), 1); + else + outsw(data_addr, (u8 *)buf + (len & ~3), 1); + } + } else { + if (mmio) + __ide_mm_outsw((void __iomem *)data_addr, buf, len / 2); + else + outsw(data_addr, buf, len / 2); + } +} +EXPORT_SYMBOL_GPL(ide_output_data); + +const struct ide_tp_ops default_tp_ops = { + .exec_command = ide_exec_command, + .read_status = ide_read_status, + .read_altstatus = ide_read_altstatus, + + .set_irq = ide_set_irq, + + .tf_load = ide_tf_load, + .tf_read = ide_tf_read, + + .input_data = ide_input_data, + .output_data = ide_output_data, +}; diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index d24add69212..91a49b543bd 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -27,34 +27,6 @@ #include #include -/* - * Conventional PIO operations for ATA devices - */ - -static u8 ide_inb (unsigned long port) -{ - return (u8) inb(port); -} - -static void ide_outb (u8 val, unsigned long port) -{ - outb(val, port); -} - -/* - * MMIO operations, typically used for SATA controllers - */ - -static u8 ide_mm_inb (unsigned long port) -{ - return (u8) readb((void __iomem *) port); -} - -static void ide_mm_outb (u8 value, unsigned long port) -{ - writeb(value, (void __iomem *) port); -} - void SELECT_DRIVE (ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; @@ -78,277 +50,6 @@ void SELECT_MASK(ide_drive_t *drive, int mask) port_ops->maskproc(drive, mask); } -void ide_exec_command(ide_hwif_t *hwif, u8 cmd) -{ - if (hwif->host_flags & IDE_HFLAG_MMIO) - writeb(cmd, (void __iomem *)hwif->io_ports.command_addr); - else - outb(cmd, hwif->io_ports.command_addr); -} -EXPORT_SYMBOL_GPL(ide_exec_command); - -u8 ide_read_status(ide_hwif_t *hwif) -{ - if (hwif->host_flags & IDE_HFLAG_MMIO) - return readb((void __iomem *)hwif->io_ports.status_addr); - else - return inb(hwif->io_ports.status_addr); -} -EXPORT_SYMBOL_GPL(ide_read_status); - -u8 ide_read_altstatus(ide_hwif_t *hwif) -{ - if (hwif->host_flags & IDE_HFLAG_MMIO) - return readb((void __iomem *)hwif->io_ports.ctl_addr); - else - return inb(hwif->io_ports.ctl_addr); -} -EXPORT_SYMBOL_GPL(ide_read_altstatus); - -void ide_set_irq(ide_hwif_t *hwif, int on) -{ - u8 ctl = ATA_DEVCTL_OBS; - - if (on == 4) { /* hack for SRST */ - ctl |= 4; - on &= ~4; - } - - ctl |= on ? 0 : 2; - - if (hwif->host_flags & IDE_HFLAG_MMIO) - writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr); - else - outb(ctl, hwif->io_ports.ctl_addr); -} -EXPORT_SYMBOL_GPL(ide_set_irq); - -void ide_tf_load(ide_drive_t *drive, ide_task_t *task) -{ - ide_hwif_t *hwif = drive->hwif; - struct ide_io_ports *io_ports = &hwif->io_ports; - struct ide_taskfile *tf = &task->tf; - void (*tf_outb)(u8 addr, unsigned long port); - u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; - u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; - - if (mmio) - tf_outb = ide_mm_outb; - else - tf_outb = ide_outb; - - if (task->tf_flags & IDE_TFLAG_FLAGGED) - HIHI = 0xFF; - - if (task->tf_flags & IDE_TFLAG_OUT_DATA) { - u16 data = (tf->hob_data << 8) | tf->data; - - if (mmio) - writew(data, (void __iomem *)io_ports->data_addr); - else - outw(data, io_ports->data_addr); - } - - if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) - tf_outb(tf->hob_feature, io_ports->feature_addr); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) - tf_outb(tf->hob_nsect, io_ports->nsect_addr); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) - tf_outb(tf->hob_lbal, io_ports->lbal_addr); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) - tf_outb(tf->hob_lbam, io_ports->lbam_addr); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) - tf_outb(tf->hob_lbah, io_ports->lbah_addr); - - if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) - tf_outb(tf->feature, io_ports->feature_addr); - if (task->tf_flags & IDE_TFLAG_OUT_NSECT) - tf_outb(tf->nsect, io_ports->nsect_addr); - if (task->tf_flags & IDE_TFLAG_OUT_LBAL) - tf_outb(tf->lbal, io_ports->lbal_addr); - if (task->tf_flags & IDE_TFLAG_OUT_LBAM) - tf_outb(tf->lbam, io_ports->lbam_addr); - if (task->tf_flags & IDE_TFLAG_OUT_LBAH) - tf_outb(tf->lbah, io_ports->lbah_addr); - - if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) - tf_outb((tf->device & HIHI) | drive->select, - io_ports->device_addr); -} -EXPORT_SYMBOL_GPL(ide_tf_load); - -void ide_tf_read(ide_drive_t *drive, ide_task_t *task) -{ - ide_hwif_t *hwif = drive->hwif; - struct ide_io_ports *io_ports = &hwif->io_ports; - struct ide_taskfile *tf = &task->tf; - void (*tf_outb)(u8 addr, unsigned long port); - u8 (*tf_inb)(unsigned long port); - u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; - - if (mmio) { - tf_outb = ide_mm_outb; - tf_inb = ide_mm_inb; - } else { - tf_outb = ide_outb; - tf_inb = ide_inb; - } - - if (task->tf_flags & IDE_TFLAG_IN_DATA) { - u16 data; - - if (mmio) - data = readw((void __iomem *)io_ports->data_addr); - else - data = inw(io_ports->data_addr); - - tf->data = data & 0xff; - tf->hob_data = (data >> 8) & 0xff; - } - - /* be sure we're looking at the low order bits */ - tf_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); - - if (task->tf_flags & IDE_TFLAG_IN_FEATURE) - tf->feature = tf_inb(io_ports->feature_addr); - if (task->tf_flags & IDE_TFLAG_IN_NSECT) - tf->nsect = tf_inb(io_ports->nsect_addr); - if (task->tf_flags & IDE_TFLAG_IN_LBAL) - tf->lbal = tf_inb(io_ports->lbal_addr); - if (task->tf_flags & IDE_TFLAG_IN_LBAM) - tf->lbam = tf_inb(io_ports->lbam_addr); - if (task->tf_flags & IDE_TFLAG_IN_LBAH) - tf->lbah = tf_inb(io_ports->lbah_addr); - if (task->tf_flags & IDE_TFLAG_IN_DEVICE) - tf->device = tf_inb(io_ports->device_addr); - - if (task->tf_flags & IDE_TFLAG_LBA48) { - tf_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); - - if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) - tf->hob_feature = tf_inb(io_ports->feature_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) - tf->hob_nsect = tf_inb(io_ports->nsect_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) - tf->hob_lbal = tf_inb(io_ports->lbal_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) - tf->hob_lbam = tf_inb(io_ports->lbam_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) - tf->hob_lbah = tf_inb(io_ports->lbah_addr); - } -} -EXPORT_SYMBOL_GPL(ide_tf_read); - -/* - * Some localbus EIDE interfaces require a special access sequence - * when using 32-bit I/O instructions to transfer data. We call this - * the "vlb_sync" sequence, which consists of three successive reads - * of the sector count register location, with interrupts disabled - * to ensure that the reads all happen together. - */ -static void ata_vlb_sync(unsigned long port) -{ - (void)inb(port); - (void)inb(port); - (void)inb(port); -} - -/* - * This is used for most PIO data transfers *from* the IDE interface - * - * These routines will round up any request for an odd number of bytes, - * so if an odd len is specified, be sure that there's at least one - * extra byte allocated for the buffer. - */ -void ide_input_data(ide_drive_t *drive, struct request *rq, void *buf, - unsigned int len) -{ - ide_hwif_t *hwif = drive->hwif; - struct ide_io_ports *io_ports = &hwif->io_ports; - unsigned long data_addr = io_ports->data_addr; - u8 io_32bit = drive->io_32bit; - u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; - - len++; - - if (io_32bit) { - unsigned long uninitialized_var(flags); - - if ((io_32bit & 2) && !mmio) { - local_irq_save(flags); - ata_vlb_sync(io_ports->nsect_addr); - } - - if (mmio) - __ide_mm_insl((void __iomem *)data_addr, buf, len / 4); - else - insl(data_addr, buf, len / 4); - - if ((io_32bit & 2) && !mmio) - local_irq_restore(flags); - - if ((len & 3) >= 2) { - if (mmio) - __ide_mm_insw((void __iomem *)data_addr, - (u8 *)buf + (len & ~3), 1); - else - insw(data_addr, (u8 *)buf + (len & ~3), 1); - } - } else { - if (mmio) - __ide_mm_insw((void __iomem *)data_addr, buf, len / 2); - else - insw(data_addr, buf, len / 2); - } -} -EXPORT_SYMBOL_GPL(ide_input_data); - -/* - * This is used for most PIO data transfers *to* the IDE interface - */ -void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf, - unsigned int len) -{ - ide_hwif_t *hwif = drive->hwif; - struct ide_io_ports *io_ports = &hwif->io_ports; - unsigned long data_addr = io_ports->data_addr; - u8 io_32bit = drive->io_32bit; - u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; - - len++; - - if (io_32bit) { - unsigned long uninitialized_var(flags); - - if ((io_32bit & 2) && !mmio) { - local_irq_save(flags); - ata_vlb_sync(io_ports->nsect_addr); - } - - if (mmio) - __ide_mm_outsl((void __iomem *)data_addr, buf, len / 4); - else - outsl(data_addr, buf, len / 4); - - if ((io_32bit & 2) && !mmio) - local_irq_restore(flags); - - if ((len & 3) >= 2) { - if (mmio) - __ide_mm_outsw((void __iomem *)data_addr, - (u8 *)buf + (len & ~3), 1); - else - outsw(data_addr, (u8 *)buf + (len & ~3), 1); - } - } else { - if (mmio) - __ide_mm_outsw((void __iomem *)data_addr, buf, len / 2); - else - outsw(data_addr, buf, len / 2); - } -} -EXPORT_SYMBOL_GPL(ide_output_data); - u8 ide_read_error(ide_drive_t *drive) { ide_task_t task; @@ -362,20 +63,6 @@ u8 ide_read_error(ide_drive_t *drive) } EXPORT_SYMBOL_GPL(ide_read_error); -const struct ide_tp_ops default_tp_ops = { - .exec_command = ide_exec_command, - .read_status = ide_read_status, - .read_altstatus = ide_read_altstatus, - - .set_irq = ide_set_irq, - - .tf_load = ide_tf_load, - .tf_read = ide_tf_read, - - .input_data = ide_input_data, - .output_data = ide_output_data, -}; - void ide_fix_driveid(u16 *id) { #ifndef __LITTLE_ENDIAN -- GitLab From 4d7bb471ce0283f586817abea81254b67598aae6 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:47 +0100 Subject: [PATCH 4249/4982] ide: fix printk() levels in [atapi_]reset_pollfunc() Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 91a49b543bd..aad0d52ff1e 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -549,7 +549,7 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive) stat = hwif->tp_ops->read_status(hwif); if (OK_STAT(stat, 0, ATA_BUSY)) - printk("%s: ATAPI reset complete\n", drive->name); + printk(KERN_INFO "%s: ATAPI reset complete\n", drive->name); else { if (time_before(jiffies, hwif->poll_timeout)) { ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL); @@ -558,8 +558,8 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive) } /* end of polling */ hwif->polling = 0; - printk("%s: ATAPI reset timed-out, status=0x%02x\n", - drive->name, stat); + printk(KERN_ERR "%s: ATAPI reset timed-out, status=0x%02x\n", + drive->name, stat); /* do it the old fashioned way */ return do_reset1(drive, 1); } @@ -618,7 +618,8 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive) /* continue polling */ return ide_started; } - printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp); + printk(KERN_ERR "%s: reset timed-out, status=0x%02x\n", + hwif->name, tmp); drive->failures++; err = -EIO; } else { -- GitLab From ee1b1cc974816b59af2ba0be1912e1c2a200ae11 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:47 +0100 Subject: [PATCH 4250/4982] ide: fix comments in ide_config_drive_speed() Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index aad0d52ff1e..73ff16bf9f1 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -369,18 +369,15 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) * but for some reason these don't work at * this point (lost interrupt). */ - /* - * Select the drive, and issue the SETFEATURES command - */ - disable_irq_nosync(hwif->irq); - + /* * FIXME: we race against the running IRQ here if * this is called from non IRQ context. If we use * disable_irq() we hang on the error path. Work * is needed. */ - + disable_irq_nosync(hwif->irq); + udelay(1); SELECT_DRIVE(drive); SELECT_MASK(drive, 1); -- GitLab From 122f06f8bce406169d61242a3eb667027e27cca7 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:47 +0100 Subject: [PATCH 4251/4982] ide: checkpatch.pl fixes for ide-iops.c Fix following checkpatch.pl warnings/errors: - WARNING: space prohibited between function name and open parenthesis '(' - WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable - WARNING: line over 80 characters - ERROR: trailing whitespace - ERROR: space required before the open parenthesis '(' Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 48 ++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 73ff16bf9f1..cf6c3036ae7 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -27,7 +27,7 @@ #include #include -void SELECT_DRIVE (ide_drive_t *drive) +void SELECT_DRIVE(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; const struct ide_port_ops *port_ops = hwif->port_ops; @@ -84,7 +84,7 @@ void ide_fix_driveid(u16 *id) * returned by the ATA_CMD_ID_ATA[PI] commands. */ -void ide_fixstring (u8 *s, const int bytecount, const int byteswap) +void ide_fixstring(u8 *s, const int bytecount, const int byteswap) { u8 *p, *end = &s[bytecount & ~1]; /* bytecount must be even */ @@ -107,7 +107,6 @@ void ide_fixstring (u8 *s, const int bytecount, const int byteswap) while (p != end) *p++ = '\0'; } - EXPORT_SYMBOL(ide_fixstring); /* @@ -121,7 +120,8 @@ EXPORT_SYMBOL(ide_fixstring); * setting a timer to wake up at half second intervals thereafter, * until timeout is achieved, before timing out. */ -static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout, u8 *rstat) +static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, + unsigned long timeout, u8 *rstat) { ide_hwif_t *hwif = drive->hwif; const struct ide_tp_ops *tp_ops = hwif->tp_ops; @@ -179,7 +179,8 @@ static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long ti * The caller should return the updated value of "startstop" in this case, * "startstop" is unchanged when the function returns 0. */ -int ide_wait_stat(ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout) +int ide_wait_stat(ide_startstop_t *startstop, ide_drive_t *drive, u8 good, + u8 bad, unsigned long timeout) { int err; u8 stat; @@ -199,7 +200,6 @@ int ide_wait_stat(ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 ba return err; } - EXPORT_SYMBOL(ide_wait_stat); /** @@ -220,7 +220,6 @@ int ide_in_drive_list(u16 *id, const struct drive_list_entry *table) return 1; return 0; } - EXPORT_SYMBOL_GPL(ide_in_drive_list); /* @@ -245,7 +244,7 @@ static const struct drive_list_entry ivb_list[] = { * All hosts that use the 80c ribbon must use! * The name is derived from upper byte of word 93 and the 80c ribbon. */ -u8 eighty_ninty_three (ide_drive_t *drive) +u8 eighty_ninty_three(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; u16 *id = drive->id; @@ -470,9 +469,8 @@ void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, __ide_set_handler(drive, handler, timeout, expiry); spin_unlock_irqrestore(&hwif->lock, flags); } - EXPORT_SYMBOL(ide_set_handler); - + /** * ide_execute_command - execute an IDE command * @drive: IDE drive to issue the command against @@ -482,7 +480,7 @@ EXPORT_SYMBOL(ide_set_handler); * @expiry: handler to run on timeout * * Helper function to issue an IDE command. This handles the - * atomicity requirements, command timing and ensures that the + * atomicity requirements, command timing and ensures that the * handler and IRQ setup do not race. All IDE command kick off * should go via this function or do equivalent locking. */ @@ -528,28 +526,29 @@ static inline void ide_complete_drive_reset(ide_drive_t *drive, int err) } /* needed below */ -static ide_startstop_t do_reset1 (ide_drive_t *, int); +static ide_startstop_t do_reset1(ide_drive_t *, int); /* - * atapi_reset_pollfunc() gets invoked to poll the interface for completion every 50ms - * during an atapi drive reset operation. If the drive has not yet responded, - * and we have not yet hit our maximum waiting time, then the timer is restarted - * for another 50ms. + * atapi_reset_pollfunc() gets invoked to poll the interface for completion + * every 50ms during an atapi drive reset operation. If the drive has not yet + * responded, and we have not yet hit our maximum waiting time, then the timer + * is restarted for another 50ms. */ -static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive) +static ide_startstop_t atapi_reset_pollfunc(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; u8 stat; SELECT_DRIVE(drive); - udelay (10); + udelay(10); stat = hwif->tp_ops->read_status(hwif); if (OK_STAT(stat, 0, ATA_BUSY)) printk(KERN_INFO "%s: ATAPI reset complete\n", drive->name); else { if (time_before(jiffies, hwif->poll_timeout)) { - ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL); + ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, + NULL); /* continue polling */ return ide_started; } @@ -591,7 +590,7 @@ static void ide_reset_report_error(ide_hwif_t *hwif, u8 err) * and we have not yet hit our maximum waiting time, then the timer is restarted * for another 50ms. */ -static ide_startstop_t reset_pollfunc (ide_drive_t *drive) +static ide_startstop_t reset_pollfunc(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; const struct ide_port_ops *port_ops = hwif->port_ops; @@ -703,7 +702,7 @@ static void pre_reset(ide_drive_t *drive) * (up to 30 seconds worstcase). So, instead of busy-waiting here for it, * we set a timer to poll at 50ms intervals. */ -static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) +static ide_startstop_t do_reset1(ide_drive_t *drive, int do_not_try_atapi) { ide_hwif_t *hwif = drive->hwif; struct ide_io_ports *io_ports = &hwif->io_ports; @@ -723,7 +722,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) if (drive->media != ide_disk && !do_not_try_atapi) { pre_reset(drive); SELECT_DRIVE(drive); - udelay (20); + udelay(20); tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET); ndelay(400); hwif->poll_timeout = jiffies + WAIT_WORSTCASE; @@ -807,11 +806,10 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) * ide_do_reset() is the entry point to the drive/interface reset code. */ -ide_startstop_t ide_do_reset (ide_drive_t *drive) +ide_startstop_t ide_do_reset(ide_drive_t *drive) { return do_reset1(drive, 0); } - EXPORT_SYMBOL(ide_do_reset); /* @@ -822,7 +820,7 @@ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout) { u8 stat = 0; - while(timeout--) { + while (timeout--) { /* * Turn this into a schedule() sleep once I'm sure * about locking issues (2.5 work ?). -- GitLab From 327fa1c29466b8fe471a91fc11e9c6171163c81a Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:47 +0100 Subject: [PATCH 4252/4982] ide: move error handling code to ide-eh.c (v2) Do some CodingStyle fixups in while at it. v2: Add missing include (reported by Stephen Rothwell). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/Makefile | 2 +- drivers/ide/ide-eh.c | 428 +++++++++++++++++++++++++++++++++++++++++ drivers/ide/ide-io.c | 129 +------------ drivers/ide/ide-iops.c | 299 +--------------------------- include/linux/ide.h | 13 +- 5 files changed, 440 insertions(+), 431 deletions(-) create mode 100644 drivers/ide/ide-eh.c diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index cbb1aea2aea..9b4bbe1cdc1 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -6,7 +6,7 @@ EXTRA_CFLAGS += -Idrivers/ide ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \ ide-taskfile.o ide-pm.o ide-park.o ide-sysfs.o ide-devsets.o \ - ide-io-std.o + ide-io-std.o ide-eh.o # core IDE code ide-core-$(CONFIG_IDE_XFER_MODE) += ide-pio-blacklist.o ide-xfer-mode.o diff --git a/drivers/ide/ide-eh.c b/drivers/ide/ide-eh.c new file mode 100644 index 00000000000..1231b5e486f --- /dev/null +++ b/drivers/ide/ide-eh.c @@ -0,0 +1,428 @@ + +#include +#include +#include + +static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, + u8 stat, u8 err) +{ + ide_hwif_t *hwif = drive->hwif; + + if ((stat & ATA_BUSY) || + ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) { + /* other bits are useless when BUSY */ + rq->errors |= ERROR_RESET; + } else if (stat & ATA_ERR) { + /* err has different meaning on cdrom and tape */ + if (err == ATA_ABORTED) { + if ((drive->dev_flags & IDE_DFLAG_LBA) && + /* some newer drives don't support ATA_CMD_INIT_DEV_PARAMS */ + hwif->tp_ops->read_status(hwif) == ATA_CMD_INIT_DEV_PARAMS) + return ide_stopped; + } else if ((err & BAD_CRC) == BAD_CRC) { + /* UDMA crc error, just retry the operation */ + drive->crc_count++; + } else if (err & (ATA_BBK | ATA_UNC)) { + /* retries won't help these */ + rq->errors = ERROR_MAX; + } else if (err & ATA_TRK0NF) { + /* help it find track zero */ + rq->errors |= ERROR_RECAL; + } + } + + if ((stat & ATA_DRQ) && rq_data_dir(rq) == READ && + (hwif->host_flags & IDE_HFLAG_ERROR_STOPS_FIFO) == 0) { + int nsect = drive->mult_count ? drive->mult_count : 1; + + ide_pad_transfer(drive, READ, nsect * SECTOR_SIZE); + } + + if (rq->errors >= ERROR_MAX || blk_noretry_request(rq)) { + ide_kill_rq(drive, rq); + return ide_stopped; + } + + if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ)) + rq->errors |= ERROR_RESET; + + if ((rq->errors & ERROR_RESET) == ERROR_RESET) { + ++rq->errors; + return ide_do_reset(drive); + } + + if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) + drive->special.b.recalibrate = 1; + + ++rq->errors; + + return ide_stopped; +} + +static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, + u8 stat, u8 err) +{ + ide_hwif_t *hwif = drive->hwif; + + if ((stat & ATA_BUSY) || + ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) { + /* other bits are useless when BUSY */ + rq->errors |= ERROR_RESET; + } else { + /* add decoding error stuff */ + } + + if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ)) + /* force an abort */ + hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE); + + if (rq->errors >= ERROR_MAX) { + ide_kill_rq(drive, rq); + } else { + if ((rq->errors & ERROR_RESET) == ERROR_RESET) { + ++rq->errors; + return ide_do_reset(drive); + } + ++rq->errors; + } + + return ide_stopped; +} + +static ide_startstop_t __ide_error(ide_drive_t *drive, struct request *rq, + u8 stat, u8 err) +{ + if (drive->media == ide_disk) + return ide_ata_error(drive, rq, stat, err); + return ide_atapi_error(drive, rq, stat, err); +} + +/** + * ide_error - handle an error on the IDE + * @drive: drive the error occurred on + * @msg: message to report + * @stat: status bits + * + * ide_error() takes action based on the error returned by the drive. + * For normal I/O that may well include retries. We deal with + * both new-style (taskfile) and old style command handling here. + * In the case of taskfile command handling there is work left to + * do + */ + +ide_startstop_t ide_error(ide_drive_t *drive, const char *msg, u8 stat) +{ + struct request *rq; + u8 err; + + err = ide_dump_status(drive, msg, stat); + + rq = drive->hwif->rq; + if (rq == NULL) + return ide_stopped; + + /* retry only "normal" I/O: */ + if (!blk_fs_request(rq)) { + rq->errors = 1; + ide_end_drive_cmd(drive, stat, err); + return ide_stopped; + } + + return __ide_error(drive, rq, stat, err); +} +EXPORT_SYMBOL_GPL(ide_error); + +static inline void ide_complete_drive_reset(ide_drive_t *drive, int err) +{ + struct request *rq = drive->hwif->rq; + + if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET) + ide_end_request(drive, err ? err : 1, 0); +} + +/* needed below */ +static ide_startstop_t do_reset1(ide_drive_t *, int); + +/* + * atapi_reset_pollfunc() gets invoked to poll the interface for completion + * every 50ms during an atapi drive reset operation. If the drive has not yet + * responded, and we have not yet hit our maximum waiting time, then the timer + * is restarted for another 50ms. + */ +static ide_startstop_t atapi_reset_pollfunc(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + u8 stat; + + SELECT_DRIVE(drive); + udelay(10); + stat = hwif->tp_ops->read_status(hwif); + + if (OK_STAT(stat, 0, ATA_BUSY)) + printk(KERN_INFO "%s: ATAPI reset complete\n", drive->name); + else { + if (time_before(jiffies, hwif->poll_timeout)) { + ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, + NULL); + /* continue polling */ + return ide_started; + } + /* end of polling */ + hwif->polling = 0; + printk(KERN_ERR "%s: ATAPI reset timed-out, status=0x%02x\n", + drive->name, stat); + /* do it the old fashioned way */ + return do_reset1(drive, 1); + } + /* done polling */ + hwif->polling = 0; + ide_complete_drive_reset(drive, 0); + return ide_stopped; +} + +static void ide_reset_report_error(ide_hwif_t *hwif, u8 err) +{ + static const char *err_master_vals[] = + { NULL, "passed", "formatter device error", + "sector buffer error", "ECC circuitry error", + "controlling MPU error" }; + + u8 err_master = err & 0x7f; + + printk(KERN_ERR "%s: reset: master: ", hwif->name); + if (err_master && err_master < 6) + printk(KERN_CONT "%s", err_master_vals[err_master]); + else + printk(KERN_CONT "error (0x%02x?)", err); + if (err & 0x80) + printk(KERN_CONT "; slave: failed"); + printk(KERN_CONT "\n"); +} + +/* + * reset_pollfunc() gets invoked to poll the interface for completion every 50ms + * during an ide reset operation. If the drives have not yet responded, + * and we have not yet hit our maximum waiting time, then the timer is restarted + * for another 50ms. + */ +static ide_startstop_t reset_pollfunc(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + const struct ide_port_ops *port_ops = hwif->port_ops; + u8 tmp; + int err = 0; + + if (port_ops && port_ops->reset_poll) { + err = port_ops->reset_poll(drive); + if (err) { + printk(KERN_ERR "%s: host reset_poll failure for %s.\n", + hwif->name, drive->name); + goto out; + } + } + + tmp = hwif->tp_ops->read_status(hwif); + + if (!OK_STAT(tmp, 0, ATA_BUSY)) { + if (time_before(jiffies, hwif->poll_timeout)) { + ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL); + /* continue polling */ + return ide_started; + } + printk(KERN_ERR "%s: reset timed-out, status=0x%02x\n", + hwif->name, tmp); + drive->failures++; + err = -EIO; + } else { + tmp = ide_read_error(drive); + + if (tmp == 1) { + printk(KERN_INFO "%s: reset: success\n", hwif->name); + drive->failures = 0; + } else { + ide_reset_report_error(hwif, tmp); + drive->failures++; + err = -EIO; + } + } +out: + hwif->polling = 0; /* done polling */ + ide_complete_drive_reset(drive, err); + return ide_stopped; +} + +static void ide_disk_pre_reset(ide_drive_t *drive) +{ + int legacy = (drive->id[ATA_ID_CFS_ENABLE_2] & 0x0400) ? 0 : 1; + + drive->special.all = 0; + drive->special.b.set_geometry = legacy; + drive->special.b.recalibrate = legacy; + + drive->mult_count = 0; + drive->dev_flags &= ~IDE_DFLAG_PARKED; + + if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0 && + (drive->dev_flags & IDE_DFLAG_USING_DMA) == 0) + drive->mult_req = 0; + + if (drive->mult_req != drive->mult_count) + drive->special.b.set_multmode = 1; +} + +static void pre_reset(ide_drive_t *drive) +{ + const struct ide_port_ops *port_ops = drive->hwif->port_ops; + + if (drive->media == ide_disk) + ide_disk_pre_reset(drive); + else + drive->dev_flags |= IDE_DFLAG_POST_RESET; + + if (drive->dev_flags & IDE_DFLAG_USING_DMA) { + if (drive->crc_count) + ide_check_dma_crc(drive); + else + ide_dma_off(drive); + } + + if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0) { + if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0) { + drive->dev_flags &= ~IDE_DFLAG_UNMASK; + drive->io_32bit = 0; + } + return; + } + + if (port_ops && port_ops->pre_reset) + port_ops->pre_reset(drive); + + if (drive->current_speed != 0xff) + drive->desired_speed = drive->current_speed; + drive->current_speed = 0xff; +} + +/* + * do_reset1() attempts to recover a confused drive by resetting it. + * Unfortunately, resetting a disk drive actually resets all devices on + * the same interface, so it can really be thought of as resetting the + * interface rather than resetting the drive. + * + * ATAPI devices have their own reset mechanism which allows them to be + * individually reset without clobbering other devices on the same interface. + * + * Unfortunately, the IDE interface does not generate an interrupt to let + * us know when the reset operation has finished, so we must poll for this. + * Equally poor, though, is the fact that this may a very long time to complete, + * (up to 30 seconds worstcase). So, instead of busy-waiting here for it, + * we set a timer to poll at 50ms intervals. + */ +static ide_startstop_t do_reset1(ide_drive_t *drive, int do_not_try_atapi) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + const struct ide_tp_ops *tp_ops = hwif->tp_ops; + const struct ide_port_ops *port_ops; + ide_drive_t *tdrive; + unsigned long flags, timeout; + int i; + DEFINE_WAIT(wait); + + spin_lock_irqsave(&hwif->lock, flags); + + /* We must not reset with running handlers */ + BUG_ON(hwif->handler != NULL); + + /* For an ATAPI device, first try an ATAPI SRST. */ + if (drive->media != ide_disk && !do_not_try_atapi) { + pre_reset(drive); + SELECT_DRIVE(drive); + udelay(20); + tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET); + ndelay(400); + hwif->poll_timeout = jiffies + WAIT_WORSTCASE; + hwif->polling = 1; + __ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL); + spin_unlock_irqrestore(&hwif->lock, flags); + return ide_started; + } + + /* We must not disturb devices in the IDE_DFLAG_PARKED state. */ + do { + unsigned long now; + + prepare_to_wait(&ide_park_wq, &wait, TASK_UNINTERRUPTIBLE); + timeout = jiffies; + ide_port_for_each_present_dev(i, tdrive, hwif) { + if ((tdrive->dev_flags & IDE_DFLAG_PARKED) && + time_after(tdrive->sleep, timeout)) + timeout = tdrive->sleep; + } + + now = jiffies; + if (time_before_eq(timeout, now)) + break; + + spin_unlock_irqrestore(&hwif->lock, flags); + timeout = schedule_timeout_uninterruptible(timeout - now); + spin_lock_irqsave(&hwif->lock, flags); + } while (timeout); + finish_wait(&ide_park_wq, &wait); + + /* + * First, reset any device state data we were maintaining + * for any of the drives on this interface. + */ + ide_port_for_each_dev(i, tdrive, hwif) + pre_reset(tdrive); + + if (io_ports->ctl_addr == 0) { + spin_unlock_irqrestore(&hwif->lock, flags); + ide_complete_drive_reset(drive, -ENXIO); + return ide_stopped; + } + + /* + * Note that we also set nIEN while resetting the device, + * to mask unwanted interrupts from the interface during the reset. + * However, due to the design of PC hardware, this will cause an + * immediate interrupt due to the edge transition it produces. + * This single interrupt gives us a "fast poll" for drives that + * recover from reset very quickly, saving us the first 50ms wait time. + * + * TODO: add ->softreset method and stop abusing ->set_irq + */ + /* set SRST and nIEN */ + tp_ops->set_irq(hwif, 4); + /* more than enough time */ + udelay(10); + /* clear SRST, leave nIEN (unless device is on the quirk list) */ + tp_ops->set_irq(hwif, drive->quirk_list == 2); + /* more than enough time */ + udelay(10); + hwif->poll_timeout = jiffies + WAIT_WORSTCASE; + hwif->polling = 1; + __ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL); + + /* + * Some weird controller like resetting themselves to a strange + * state when the disks are reset this way. At least, the Winbond + * 553 documentation says that + */ + port_ops = hwif->port_ops; + if (port_ops && port_ops->resetproc) + port_ops->resetproc(drive); + + spin_unlock_irqrestore(&hwif->lock, flags); + return ide_started; +} + +/* + * ide_do_reset() is the entry point to the drive/interface reset code. + */ + +ide_startstop_t ide_do_reset(ide_drive_t *drive) +{ + return do_reset1(drive, 0); +} +EXPORT_SYMBOL(ide_do_reset); diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 74d1a3e6825..2e92497b58a 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -196,7 +196,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) } EXPORT_SYMBOL(ide_end_drive_cmd); -static void ide_kill_rq(ide_drive_t *drive, struct request *rq) +void ide_kill_rq(ide_drive_t *drive, struct request *rq) { if (rq->rq_disk) { struct ide_driver *drv; @@ -207,133 +207,6 @@ static void ide_kill_rq(ide_drive_t *drive, struct request *rq) ide_end_request(drive, 0, 0); } -static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) -{ - ide_hwif_t *hwif = drive->hwif; - - if ((stat & ATA_BUSY) || - ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) { - /* other bits are useless when BUSY */ - rq->errors |= ERROR_RESET; - } else if (stat & ATA_ERR) { - /* err has different meaning on cdrom and tape */ - if (err == ATA_ABORTED) { - if ((drive->dev_flags & IDE_DFLAG_LBA) && - /* some newer drives don't support ATA_CMD_INIT_DEV_PARAMS */ - hwif->tp_ops->read_status(hwif) == ATA_CMD_INIT_DEV_PARAMS) - return ide_stopped; - } else if ((err & BAD_CRC) == BAD_CRC) { - /* UDMA crc error, just retry the operation */ - drive->crc_count++; - } else if (err & (ATA_BBK | ATA_UNC)) { - /* retries won't help these */ - rq->errors = ERROR_MAX; - } else if (err & ATA_TRK0NF) { - /* help it find track zero */ - rq->errors |= ERROR_RECAL; - } - } - - if ((stat & ATA_DRQ) && rq_data_dir(rq) == READ && - (hwif->host_flags & IDE_HFLAG_ERROR_STOPS_FIFO) == 0) { - int nsect = drive->mult_count ? drive->mult_count : 1; - - ide_pad_transfer(drive, READ, nsect * SECTOR_SIZE); - } - - if (rq->errors >= ERROR_MAX || blk_noretry_request(rq)) { - ide_kill_rq(drive, rq); - return ide_stopped; - } - - if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ)) - rq->errors |= ERROR_RESET; - - if ((rq->errors & ERROR_RESET) == ERROR_RESET) { - ++rq->errors; - return ide_do_reset(drive); - } - - if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) - drive->special.b.recalibrate = 1; - - ++rq->errors; - - return ide_stopped; -} - -static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) -{ - ide_hwif_t *hwif = drive->hwif; - - if ((stat & ATA_BUSY) || - ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) { - /* other bits are useless when BUSY */ - rq->errors |= ERROR_RESET; - } else { - /* add decoding error stuff */ - } - - if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ)) - /* force an abort */ - hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE); - - if (rq->errors >= ERROR_MAX) { - ide_kill_rq(drive, rq); - } else { - if ((rq->errors & ERROR_RESET) == ERROR_RESET) { - ++rq->errors; - return ide_do_reset(drive); - } - ++rq->errors; - } - - return ide_stopped; -} - -static ide_startstop_t -__ide_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) -{ - if (drive->media == ide_disk) - return ide_ata_error(drive, rq, stat, err); - return ide_atapi_error(drive, rq, stat, err); -} - -/** - * ide_error - handle an error on the IDE - * @drive: drive the error occurred on - * @msg: message to report - * @stat: status bits - * - * ide_error() takes action based on the error returned by the drive. - * For normal I/O that may well include retries. We deal with - * both new-style (taskfile) and old style command handling here. - * In the case of taskfile command handling there is work left to - * do - */ - -ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat) -{ - struct request *rq; - u8 err; - - err = ide_dump_status(drive, msg, stat); - - rq = drive->hwif->rq; - if (rq == NULL) - return ide_stopped; - - /* retry only "normal" I/O: */ - if (!blk_fs_request(rq)) { - rq->errors = 1; - ide_end_drive_cmd(drive, stat, err); - return ide_stopped; - } - - return __ide_error(drive, rq, stat, err); -} -EXPORT_SYMBOL_GPL(ide_error); - static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf) { tf->nsect = drive->sect; diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index cf6c3036ae7..e0cfa2d2acc 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -446,8 +446,8 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) * * See also ide_execute_command */ -static void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, - unsigned int timeout, ide_expiry_t *expiry) +void __ide_set_handler(ide_drive_t *drive, ide_handler_t *handler, + unsigned int timeout, ide_expiry_t *expiry) { ide_hwif_t *hwif = drive->hwif; @@ -517,301 +517,6 @@ void ide_execute_pkt_cmd(ide_drive_t *drive) } EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd); -static inline void ide_complete_drive_reset(ide_drive_t *drive, int err) -{ - struct request *rq = drive->hwif->rq; - - if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET) - ide_end_request(drive, err ? err : 1, 0); -} - -/* needed below */ -static ide_startstop_t do_reset1(ide_drive_t *, int); - -/* - * atapi_reset_pollfunc() gets invoked to poll the interface for completion - * every 50ms during an atapi drive reset operation. If the drive has not yet - * responded, and we have not yet hit our maximum waiting time, then the timer - * is restarted for another 50ms. - */ -static ide_startstop_t atapi_reset_pollfunc(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - u8 stat; - - SELECT_DRIVE(drive); - udelay(10); - stat = hwif->tp_ops->read_status(hwif); - - if (OK_STAT(stat, 0, ATA_BUSY)) - printk(KERN_INFO "%s: ATAPI reset complete\n", drive->name); - else { - if (time_before(jiffies, hwif->poll_timeout)) { - ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, - NULL); - /* continue polling */ - return ide_started; - } - /* end of polling */ - hwif->polling = 0; - printk(KERN_ERR "%s: ATAPI reset timed-out, status=0x%02x\n", - drive->name, stat); - /* do it the old fashioned way */ - return do_reset1(drive, 1); - } - /* done polling */ - hwif->polling = 0; - ide_complete_drive_reset(drive, 0); - return ide_stopped; -} - -static void ide_reset_report_error(ide_hwif_t *hwif, u8 err) -{ - static const char *err_master_vals[] = - { NULL, "passed", "formatter device error", - "sector buffer error", "ECC circuitry error", - "controlling MPU error" }; - - u8 err_master = err & 0x7f; - - printk(KERN_ERR "%s: reset: master: ", hwif->name); - if (err_master && err_master < 6) - printk(KERN_CONT "%s", err_master_vals[err_master]); - else - printk(KERN_CONT "error (0x%02x?)", err); - if (err & 0x80) - printk(KERN_CONT "; slave: failed"); - printk(KERN_CONT "\n"); -} - -/* - * reset_pollfunc() gets invoked to poll the interface for completion every 50ms - * during an ide reset operation. If the drives have not yet responded, - * and we have not yet hit our maximum waiting time, then the timer is restarted - * for another 50ms. - */ -static ide_startstop_t reset_pollfunc(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_port_ops *port_ops = hwif->port_ops; - u8 tmp; - int err = 0; - - if (port_ops && port_ops->reset_poll) { - err = port_ops->reset_poll(drive); - if (err) { - printk(KERN_ERR "%s: host reset_poll failure for %s.\n", - hwif->name, drive->name); - goto out; - } - } - - tmp = hwif->tp_ops->read_status(hwif); - - if (!OK_STAT(tmp, 0, ATA_BUSY)) { - if (time_before(jiffies, hwif->poll_timeout)) { - ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL); - /* continue polling */ - return ide_started; - } - printk(KERN_ERR "%s: reset timed-out, status=0x%02x\n", - hwif->name, tmp); - drive->failures++; - err = -EIO; - } else { - tmp = ide_read_error(drive); - - if (tmp == 1) { - printk(KERN_INFO "%s: reset: success\n", hwif->name); - drive->failures = 0; - } else { - ide_reset_report_error(hwif, tmp); - drive->failures++; - err = -EIO; - } - } -out: - hwif->polling = 0; /* done polling */ - ide_complete_drive_reset(drive, err); - return ide_stopped; -} - -static void ide_disk_pre_reset(ide_drive_t *drive) -{ - int legacy = (drive->id[ATA_ID_CFS_ENABLE_2] & 0x0400) ? 0 : 1; - - drive->special.all = 0; - drive->special.b.set_geometry = legacy; - drive->special.b.recalibrate = legacy; - - drive->mult_count = 0; - drive->dev_flags &= ~IDE_DFLAG_PARKED; - - if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0 && - (drive->dev_flags & IDE_DFLAG_USING_DMA) == 0) - drive->mult_req = 0; - - if (drive->mult_req != drive->mult_count) - drive->special.b.set_multmode = 1; -} - -static void pre_reset(ide_drive_t *drive) -{ - const struct ide_port_ops *port_ops = drive->hwif->port_ops; - - if (drive->media == ide_disk) - ide_disk_pre_reset(drive); - else - drive->dev_flags |= IDE_DFLAG_POST_RESET; - - if (drive->dev_flags & IDE_DFLAG_USING_DMA) { - if (drive->crc_count) - ide_check_dma_crc(drive); - else - ide_dma_off(drive); - } - - if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0) { - if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0) { - drive->dev_flags &= ~IDE_DFLAG_UNMASK; - drive->io_32bit = 0; - } - return; - } - - if (port_ops && port_ops->pre_reset) - port_ops->pre_reset(drive); - - if (drive->current_speed != 0xff) - drive->desired_speed = drive->current_speed; - drive->current_speed = 0xff; -} - -/* - * do_reset1() attempts to recover a confused drive by resetting it. - * Unfortunately, resetting a disk drive actually resets all devices on - * the same interface, so it can really be thought of as resetting the - * interface rather than resetting the drive. - * - * ATAPI devices have their own reset mechanism which allows them to be - * individually reset without clobbering other devices on the same interface. - * - * Unfortunately, the IDE interface does not generate an interrupt to let - * us know when the reset operation has finished, so we must poll for this. - * Equally poor, though, is the fact that this may a very long time to complete, - * (up to 30 seconds worstcase). So, instead of busy-waiting here for it, - * we set a timer to poll at 50ms intervals. - */ -static ide_startstop_t do_reset1(ide_drive_t *drive, int do_not_try_atapi) -{ - ide_hwif_t *hwif = drive->hwif; - struct ide_io_ports *io_ports = &hwif->io_ports; - const struct ide_tp_ops *tp_ops = hwif->tp_ops; - const struct ide_port_ops *port_ops; - ide_drive_t *tdrive; - unsigned long flags, timeout; - int i; - DEFINE_WAIT(wait); - - spin_lock_irqsave(&hwif->lock, flags); - - /* We must not reset with running handlers */ - BUG_ON(hwif->handler != NULL); - - /* For an ATAPI device, first try an ATAPI SRST. */ - if (drive->media != ide_disk && !do_not_try_atapi) { - pre_reset(drive); - SELECT_DRIVE(drive); - udelay(20); - tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET); - ndelay(400); - hwif->poll_timeout = jiffies + WAIT_WORSTCASE; - hwif->polling = 1; - __ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL); - spin_unlock_irqrestore(&hwif->lock, flags); - return ide_started; - } - - /* We must not disturb devices in the IDE_DFLAG_PARKED state. */ - do { - unsigned long now; - - prepare_to_wait(&ide_park_wq, &wait, TASK_UNINTERRUPTIBLE); - timeout = jiffies; - ide_port_for_each_present_dev(i, tdrive, hwif) { - if ((tdrive->dev_flags & IDE_DFLAG_PARKED) && - time_after(tdrive->sleep, timeout)) - timeout = tdrive->sleep; - } - - now = jiffies; - if (time_before_eq(timeout, now)) - break; - - spin_unlock_irqrestore(&hwif->lock, flags); - timeout = schedule_timeout_uninterruptible(timeout - now); - spin_lock_irqsave(&hwif->lock, flags); - } while (timeout); - finish_wait(&ide_park_wq, &wait); - - /* - * First, reset any device state data we were maintaining - * for any of the drives on this interface. - */ - ide_port_for_each_dev(i, tdrive, hwif) - pre_reset(tdrive); - - if (io_ports->ctl_addr == 0) { - spin_unlock_irqrestore(&hwif->lock, flags); - ide_complete_drive_reset(drive, -ENXIO); - return ide_stopped; - } - - /* - * Note that we also set nIEN while resetting the device, - * to mask unwanted interrupts from the interface during the reset. - * However, due to the design of PC hardware, this will cause an - * immediate interrupt due to the edge transition it produces. - * This single interrupt gives us a "fast poll" for drives that - * recover from reset very quickly, saving us the first 50ms wait time. - * - * TODO: add ->softreset method and stop abusing ->set_irq - */ - /* set SRST and nIEN */ - tp_ops->set_irq(hwif, 4); - /* more than enough time */ - udelay(10); - /* clear SRST, leave nIEN (unless device is on the quirk list) */ - tp_ops->set_irq(hwif, drive->quirk_list == 2); - /* more than enough time */ - udelay(10); - hwif->poll_timeout = jiffies + WAIT_WORSTCASE; - hwif->polling = 1; - __ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL); - - /* - * Some weird controller like resetting themselves to a strange - * state when the disks are reset this way. At least, the Winbond - * 553 documentation says that - */ - port_ops = hwif->port_ops; - if (port_ops && port_ops->resetproc) - port_ops->resetproc(drive); - - spin_unlock_irqrestore(&hwif->lock, flags); - return ide_started; -} - -/* - * ide_do_reset() is the entry point to the drive/interface reset code. - */ - -ide_startstop_t ide_do_reset(ide_drive_t *drive) -{ - return do_reset1(drive, 0); -} -EXPORT_SYMBOL(ide_do_reset); - /* * ide_wait_not_busy() waits for the currently selected device on the hwif * to report a non-busy status, see comments in ide_probe_port(). diff --git a/include/linux/ide.h b/include/linux/ide.h index 323c3710fbf..0c87ed52a87 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1146,11 +1146,14 @@ int generic_ide_ioctl(ide_drive_t *, struct block_device *, unsigned, unsigned l extern int ide_vlb_clk; extern int ide_pci_clk; -extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs); -int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq, - int uptodate, int nr_sectors); - -extern void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry); +int ide_end_request(ide_drive_t *, int, int); +int ide_end_dequeued_request(ide_drive_t *, struct request *, int, int); +void ide_kill_rq(ide_drive_t *, struct request *); + +void __ide_set_handler(ide_drive_t *, ide_handler_t *, unsigned int, + ide_expiry_t *); +void ide_set_handler(ide_drive_t *, ide_handler_t *, unsigned int, + ide_expiry_t *); void ide_execute_command(ide_drive_t *, u8, ide_handler_t *, unsigned int, ide_expiry_t *); -- GitLab From b75aa122edd91599e0cf2ae57a5de1e84d9895c2 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:48 +0100 Subject: [PATCH 4253/4982] mn10300: add pci_get_legacy_ide_irq() to Add missing pci_get_legacy_ide_irq() implementation before it becomes required by core IDE PCI code. Cc: David Howells Signed-off-by: Bartlomiej Zolnierkiewicz --- include/asm-mn10300/pci.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/asm-mn10300/pci.h b/include/asm-mn10300/pci.h index cd9cc5c89ce..0517b45313d 100644 --- a/include/asm-mn10300/pci.h +++ b/include/asm-mn10300/pci.h @@ -121,4 +121,9 @@ pcibios_select_root(struct pci_dev *pdev, struct resource *res) #define pcibios_scan_all_fns(a, b) 0 +static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) +{ + return channel ? 15 : 14; +} + #endif /* _ASM_PCI_H */ -- GitLab From 213e4b0a3483b8cc99c4578923b9899e84e086e0 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:48 +0100 Subject: [PATCH 4254/4982] amd74xx: use ide_pci_is_in_compatibility_mode() Fix ->init_hwif to check if IDE PCI controller is in compatibility mode instead of checking for hwif->irq == 0. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/amd74xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c index 77267c85996..0caecad1998 100644 --- a/drivers/ide/amd74xx.c +++ b/drivers/ide/amd74xx.c @@ -187,7 +187,7 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif) { struct pci_dev *dev = to_pci_dev(hwif->dev); - if (hwif->irq == 0) /* 0 is bogus but will do for now */ + if (ide_pci_is_in_compatibility_mode(dev)) hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel); } -- GitLab From 973d9e743979d4d3f06d8071c22187b2bdc0ef24 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:48 +0100 Subject: [PATCH 4255/4982] ns87415: use pci_get_legacy_ide_irq() Fix ->init_hwif to use pci_get_legacy_ide_irq() instead of __ide_default_irq(). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ns87415.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ide/ns87415.c b/drivers/ide/ns87415.c index 83643ed9a42..56042a36d63 100644 --- a/drivers/ide/ns87415.c +++ b/drivers/ide/ns87415.c @@ -286,7 +286,7 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) } if (!using_inta) - hwif->irq = __ide_default_irq(hwif->io_ports.data_addr); + hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel); else if (!hwif->irq && hwif->mate && hwif->mate->irq) hwif->irq = hwif->mate->irq; /* share IRQ with mate */ -- GitLab From 49727e3d20ba10921572e35bc99b2c2e1b8c1dba Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:49 +0100 Subject: [PATCH 4256/4982] ns87415: small ->init_hwif cleanup Core IDE PCI code takes care of assigning hwif->irq for both ports. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ns87415.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/ide/ns87415.c b/drivers/ide/ns87415.c index 56042a36d63..ea48a3ee806 100644 --- a/drivers/ide/ns87415.c +++ b/drivers/ide/ns87415.c @@ -287,8 +287,6 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) if (!using_inta) hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel); - else if (!hwif->irq && hwif->mate && hwif->mate->irq) - hwif->irq = hwif->mate->irq; /* share IRQ with mate */ if (!hwif->dma_base) return; -- GitLab From 1b166ae7bb9610cdd3c4c66b960aa04004054e41 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:49 +0100 Subject: [PATCH 4257/4982] trm290: small ->init_hwif cleanup Core IDE PCI code takes care of assigning hwif->irq for both ports. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/trm290.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/ide/trm290.c b/drivers/ide/trm290.c index b6a1285a402..1c09e549c42 100644 --- a/drivers/ide/trm290.c +++ b/drivers/ide/trm290.c @@ -277,9 +277,6 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif) if (reg & 0x10) /* legacy mode */ hwif->irq = hwif->channel ? 15 : 14; - else if (!hwif->irq && hwif->mate && hwif->mate->irq) - /* sharing IRQ with mate */ - hwif->irq = hwif->mate->irq; #if 1 { -- GitLab From 80d15a607ae95dd0514ab1ab5ea1058a3a585f2b Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:49 +0100 Subject: [PATCH 4258/4982] ide: handle IDE_HFLAG[_FORCE]_LEGACY_IRQS in ide_pci_init_{one,two}() Move handling of IDE_HFLAG[_FORCE]_LEGACY_IRQS from ide_init_port() to ide_pci_init_{one,two}(). There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 4 ---- drivers/ide/setup-pci.c | 12 ++++++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index a51ad2bd62b..80967307f2b 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1183,10 +1183,6 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port, if (d->init_iops) d->init_iops(hwif); - if ((!hwif->irq && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) || - (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS)) - hwif->irq = port ? 15 : 14; - /* ->host_flags may be set by ->init_iops (or even earlier...) */ hwif->host_flags |= d->host_flags; hwif->pio_mask = d->pio_mask; diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index e85d1ed29c2..9482288e861 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -570,6 +570,12 @@ int ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d, /* fixup IRQ */ hw[1].irq = hw[0].irq = ret; + if ((ret == 0 && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) || + (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS)) { + hw[0].irq = 14; + hw[1].irq = 15; + } + ret = ide_host_register(host, d, hws); if (ret) ide_host_free(host); @@ -620,6 +626,12 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, /* fixup IRQ */ hw[i*2 + 1].irq = hw[i*2].irq = ret; + + if ((ret == 0 && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) || + (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS)) { + hw[i*2].irq = 14; + hw[i*2 + 1].irq = 15; + } } ret = ide_host_register(host, d, hws); -- GitLab From 5bae8bf4508004d46487b3a18769d0ccff01c532 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:49 +0100 Subject: [PATCH 4259/4982] ide: use pci_get_legacy_ide_irq() in ide_pci_init_{one,two}() Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/setup-pci.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 9482288e861..fa645fc41b8 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -572,8 +572,8 @@ int ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d, if ((ret == 0 && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) || (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS)) { - hw[0].irq = 14; - hw[1].irq = 15; + hw[0].irq = pci_get_legacy_ide_irq(dev, 0); + hw[1].irq = pci_get_legacy_ide_irq(dev, 1); } ret = ide_host_register(host, d, hws); @@ -629,8 +629,8 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, if ((ret == 0 && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) || (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS)) { - hw[i*2].irq = 14; - hw[i*2 + 1].irq = 15; + hw[i*2].irq = pci_get_legacy_ide_irq(pdev[i], 0); + hw[i*2 + 1].irq = pci_get_legacy_ide_irq(pdev[i], 1); } } -- GitLab From f65dedfd7b75f19bde42bafbe84fddce18c42499 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:51 +0100 Subject: [PATCH 4260/4982] ide: use ide_pci_is_in_compatibility_mode() in ide_pci_init_{one,two}() Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/setup-pci.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index fa645fc41b8..79e3244691e 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -568,13 +568,11 @@ int ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d, goto out; /* fixup IRQ */ - hw[1].irq = hw[0].irq = ret; - - if ((ret == 0 && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) || - (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS)) { + if (ide_pci_is_in_compatibility_mode(dev)) { hw[0].irq = pci_get_legacy_ide_irq(dev, 0); hw[1].irq = pci_get_legacy_ide_irq(dev, 1); - } + } else + hw[1].irq = hw[0].irq = ret; ret = ide_host_register(host, d, hws); if (ret) @@ -625,13 +623,11 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, goto out; /* fixup IRQ */ - hw[i*2 + 1].irq = hw[i*2].irq = ret; - - if ((ret == 0 && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) || - (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS)) { + if (ide_pci_is_in_compatibility_mode(pdev[i])) { hw[i*2].irq = pci_get_legacy_ide_irq(pdev[i], 0); hw[i*2 + 1].irq = pci_get_legacy_ide_irq(pdev[i], 1); - } + } else + hw[i*2 + 1].irq = hw[i*2].irq = ret; } ret = ide_host_register(host, d, hws); -- GitLab From 2467922a560bb7e6eb4635435760ad0a2197ffcc Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:52 +0100 Subject: [PATCH 4261/4982] ide: remove no longer needed IDE_HFLAG[_FORCE]_LEGACY_IRQS There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/atiixp.c | 3 +-- drivers/ide/ide-pci-generic.c | 4 +--- drivers/ide/piix.c | 11 +---------- drivers/ide/serverworks.c | 9 ++------- drivers/ide/sis5513.c | 2 +- drivers/ide/slc90e66.c | 1 - drivers/ide/via82cxxx.c | 10 ---------- include/linux/ide.h | 4 ---- 8 files changed, 6 insertions(+), 38 deletions(-) diff --git a/drivers/ide/atiixp.c b/drivers/ide/atiixp.c index ecd1e62ca91..923cbfe259d 100644 --- a/drivers/ide/atiixp.c +++ b/drivers/ide/atiixp.c @@ -142,7 +142,6 @@ static const struct ide_port_info atiixp_pci_info[] __devinitdata = { .name = DRV_NAME, .enablebits = {{0x48,0x01,0x00}, {0x48,0x08,0x00}}, .port_ops = &atiixp_port_ops, - .host_flags = IDE_HFLAG_LEGACY_IRQS, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, @@ -151,7 +150,7 @@ static const struct ide_port_info atiixp_pci_info[] __devinitdata = { .name = DRV_NAME, .enablebits = {{0x48,0x01,0x00}, {0x00,0x00,0x00}}, .port_ops = &atiixp_port_ops, - .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS, + .host_flags = IDE_HFLAG_SINGLE, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, diff --git a/drivers/ide/ide-pci-generic.c b/drivers/ide/ide-pci-generic.c index bddae2b329a..61111fd2713 100644 --- a/drivers/ide/ide-pci-generic.c +++ b/drivers/ide/ide-pci-generic.c @@ -33,8 +33,6 @@ static int ide_generic_all; /* Set to claim all devices */ module_param_named(all_generic_ide, ide_generic_all, bool, 0444); MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE storage controllers."); -#define IDE_HFLAGS_UMC (IDE_HFLAG_NO_DMA | IDE_HFLAG_FORCE_LEGACY_IRQS) - #define DECLARE_GENERIC_PCI_DEV(extra_flags) \ { \ .name = DRV_NAME, \ @@ -61,7 +59,7 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = { /* 2: SAMURAI / HT6565 / HINT_IDE */ DECLARE_GENERIC_PCI_DEV(0), /* 3: UM8673F / UM8886A / UM8886BF */ - DECLARE_GENERIC_PCI_DEV(IDE_HFLAGS_UMC), + DECLARE_GENERIC_PCI_DEV(IDE_HFLAG_NO_DMA), /* 4: VIA_IDE / OPTI621V / Piccolo010{2,3,5} */ DECLARE_GENERIC_PCI_DEV(IDE_HFLAG_NO_AUTODMA), diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c index f1e2e4ef0d7..42c2e3522d7 100644 --- a/drivers/ide/piix.c +++ b/drivers/ide/piix.c @@ -318,19 +318,12 @@ static const struct ide_port_ops ich_port_ops = { .cable_detect = piix_cable_detect, }; -#ifndef CONFIG_IA64 - #define IDE_HFLAGS_PIIX IDE_HFLAG_LEGACY_IRQS -#else - #define IDE_HFLAGS_PIIX 0 -#endif - #define DECLARE_PIIX_DEV(udma) \ { \ .name = DRV_NAME, \ .init_hwif = init_hwif_piix, \ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \ .port_ops = &piix_port_ops, \ - .host_flags = IDE_HFLAGS_PIIX, \ .pio_mask = ATA_PIO4, \ .swdma_mask = ATA_SWDMA2_ONLY, \ .mwdma_mask = ATA_MWDMA12_ONLY, \ @@ -344,7 +337,6 @@ static const struct ide_port_ops ich_port_ops = { .init_hwif = init_hwif_piix, \ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \ .port_ops = &ich_port_ops, \ - .host_flags = IDE_HFLAGS_PIIX, \ .pio_mask = ATA_PIO4, \ .swdma_mask = ATA_SWDMA2_ONLY, \ .mwdma_mask = ATA_MWDMA12_ONLY, \ @@ -360,8 +352,7 @@ static const struct ide_port_info piix_pci_info[] __devinitdata = { */ .name = DRV_NAME, .enablebits = {{0x6d,0xc0,0x80}, {0x6d,0xc0,0xc0}}, - .host_flags = IDE_HFLAG_ISA_PORTS | IDE_HFLAG_NO_DMA | - IDE_HFLAGS_PIIX, + .host_flags = IDE_HFLAG_ISA_PORTS | IDE_HFLAG_NO_DMA, .pio_mask = ATA_PIO4, /* This is a painful system best to let it self tune for now */ }, diff --git a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c index 382102ba467..14718e73991 100644 --- a/drivers/ide/serverworks.c +++ b/drivers/ide/serverworks.c @@ -353,14 +353,11 @@ static const struct ide_port_ops svwks_port_ops = { .cable_detect = svwks_cable_detect, }; -#define IDE_HFLAGS_SVWKS IDE_HFLAG_LEGACY_IRQS - static const struct ide_port_info serverworks_chipsets[] __devinitdata = { { /* 0: OSB4 */ .name = DRV_NAME, .init_chipset = init_chipset_svwks, .port_ops = &osb4_port_ops, - .host_flags = IDE_HFLAGS_SVWKS, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = 0x00, /* UDMA is problematic on OSB4 */ @@ -369,7 +366,6 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = { .name = DRV_NAME, .init_chipset = init_chipset_svwks, .port_ops = &svwks_port_ops, - .host_flags = IDE_HFLAGS_SVWKS, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, @@ -378,7 +374,6 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = { .name = DRV_NAME, .init_chipset = init_chipset_svwks, .port_ops = &svwks_port_ops, - .host_flags = IDE_HFLAGS_SVWKS, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, @@ -387,7 +382,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = { .name = DRV_NAME, .init_chipset = init_chipset_svwks, .port_ops = &svwks_port_ops, - .host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE, + .host_flags = IDE_HFLAG_SINGLE, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, @@ -396,7 +391,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = { .name = DRV_NAME, .init_chipset = init_chipset_svwks, .port_ops = &svwks_port_ops, - .host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE, + .host_flags = IDE_HFLAG_SINGLE, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c index 9ec1a4a4432..d2d54aaea13 100644 --- a/drivers/ide/sis5513.c +++ b/drivers/ide/sis5513.c @@ -563,7 +563,7 @@ static const struct ide_port_info sis5513_chipset __devinitdata = { .name = DRV_NAME, .init_chipset = init_chipset_sis5513, .enablebits = { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} }, - .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA, + .host_flags = IDE_HFLAG_NO_AUTODMA, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, }; diff --git a/drivers/ide/slc90e66.c b/drivers/ide/slc90e66.c index 40b4b94a428..f55d7d6313e 100644 --- a/drivers/ide/slc90e66.c +++ b/drivers/ide/slc90e66.c @@ -136,7 +136,6 @@ static const struct ide_port_info slc90e66_chipset __devinitdata = { .name = DRV_NAME, .enablebits = { {0x41, 0x80, 0x80}, {0x43, 0x80, 0x80} }, .port_ops = &slc90e66_port_ops, - .host_flags = IDE_HFLAG_LEGACY_IRQS, .pio_mask = ATA_PIO4, .swdma_mask = ATA_SWDMA2_ONLY, .mwdma_mask = ATA_MWDMA12_ONLY, diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c index 6092fe3f409..a41eab5cb5d 100644 --- a/drivers/ide/via82cxxx.c +++ b/drivers/ide/via82cxxx.c @@ -443,16 +443,6 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i if ((via_config->flags & VIA_NO_UNMASK) == 0) d.host_flags |= IDE_HFLAG_UNMASK_IRQS; -#ifdef CONFIG_PPC_CHRP - if (machine_is(chrp) && _chrp_type == _CHRP_Pegasos) - d.host_flags |= IDE_HFLAG_FORCE_LEGACY_IRQS; -#endif - -#ifdef CONFIG_AMIGAONE - if (machine_is(amigaone)) - d.host_flags |= IDE_HFLAG_FORCE_LEGACY_IRQS; -#endif - d.udma_mask = via_config->udma_mask; vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); diff --git a/include/linux/ide.h b/include/linux/ide.h index 0c87ed52a87..bfd07b866b6 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1349,10 +1349,6 @@ enum { IDE_HFLAG_ERROR_STOPS_FIFO = (1 << 19), /* serialize ports */ IDE_HFLAG_SERIALIZE = (1 << 20), - /* use legacy IRQs */ - IDE_HFLAG_LEGACY_IRQS = (1 << 21), - /* force use of legacy IRQs */ - IDE_HFLAG_FORCE_LEGACY_IRQS = (1 << 22), /* host is TRM290 */ IDE_HFLAG_TRM290 = (1 << 23), /* use 32-bit I/O ops */ -- GitLab From bd0c08470fcded75d3904734ee22ae5b363737db Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:52 +0100 Subject: [PATCH 4262/4982] amd74xx: remove no longer needed ->init_hwif method This is now handled by core IDE PCI code. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/amd74xx.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c index 0caecad1998..0b51921e63e 100644 --- a/drivers/ide/amd74xx.c +++ b/drivers/ide/amd74xx.c @@ -183,14 +183,6 @@ static u8 amd_cable_detect(ide_hwif_t *hwif) return ATA_CBL_PATA40; } -static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - - if (ide_pci_is_in_compatibility_mode(dev)) - hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel); -} - static const struct ide_port_ops amd_port_ops = { .set_pio_mode = amd_set_pio_mode, .set_dma_mode = amd_set_drive, @@ -207,7 +199,6 @@ static const struct ide_port_ops amd_port_ops = { { \ .name = DRV_NAME, \ .init_chipset = init_chipset_amd74xx, \ - .init_hwif = init_hwif_amd74xx, \ .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, \ .port_ops = &amd_port_ops, \ .host_flags = IDE_HFLAGS_AMD, \ @@ -221,7 +212,6 @@ static const struct ide_port_ops amd_port_ops = { { \ .name = DRV_NAME, \ .init_chipset = init_chipset_amd74xx, \ - .init_hwif = init_hwif_amd74xx, \ .enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, \ .port_ops = &amd_port_ops, \ .host_flags = IDE_HFLAGS_AMD, \ -- GitLab From 8b07ed26f8eb73d4f55a9d852712cd588c45ff51 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:52 +0100 Subject: [PATCH 4263/4982] ide: remove no longer needed IRQ fallback code from hwif_init() Then remove no longer used __ide_default_irq(). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 30 ++++-------------------------- include/linux/ide.h | 15 --------------- 2 files changed, 4 insertions(+), 41 deletions(-) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 80967307f2b..ebc328c2e7e 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1070,14 +1070,9 @@ static void drive_release_dev (struct device *dev) static int hwif_init(ide_hwif_t *hwif) { - int old_irq; - if (!hwif->irq) { - hwif->irq = __ide_default_irq(hwif->io_ports.data_addr); - if (!hwif->irq) { - printk(KERN_ERR "%s: disabled, no IRQ\n", hwif->name); - return 0; - } + printk(KERN_ERR "%s: disabled, no IRQ\n", hwif->name); + return 0; } if (register_blkdev(hwif->major, hwif->name)) @@ -1095,29 +1090,12 @@ static int hwif_init(ide_hwif_t *hwif) sg_init_table(hwif->sg_table, hwif->sg_max_nents); - if (init_irq(hwif) == 0) - goto done; - - old_irq = hwif->irq; - /* - * It failed to initialise. Find the default IRQ for - * this port and try that. - */ - hwif->irq = __ide_default_irq(hwif->io_ports.data_addr); - if (!hwif->irq) { - printk(KERN_ERR "%s: disabled, unable to get IRQ %d\n", - hwif->name, old_irq); - goto out; - } if (init_irq(hwif)) { - printk(KERN_ERR "%s: probed IRQ %d and default IRQ %d failed\n", - hwif->name, old_irq, hwif->irq); + printk(KERN_ERR "%s: disabled, unable to get IRQ %d\n", + hwif->name, hwif->irq); goto out; } - printk(KERN_WARNING "%s: probed IRQ %d failed, using default\n", - hwif->name, hwif->irq); -done: blk_register_region(MKDEV(hwif->major, 0), MAX_DRIVES << PARTN_BITS, THIS_MODULE, ata_probe, ata_lock, hwif); return 1; diff --git a/include/linux/ide.h b/include/linux/ide.h index bfd07b866b6..31e492c7bde 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -193,21 +193,6 @@ static inline void ide_std_init_ports(hw_regs_t *hw, hw->io_ports.ctl_addr = ctl_addr; } -/* for IDE PCI controllers in legacy mode, temporary */ -static inline int __ide_default_irq(unsigned long base) -{ - switch (base) { -#ifdef CONFIG_IA64 - case 0x1f0: return isa_irq_to_vector(14); - case 0x170: return isa_irq_to_vector(15); -#else - case 0x1f0: return 14; - case 0x170: return 15; -#endif - } - return 0; -} - #if defined(CONFIG_ARM) || defined(CONFIG_FRV) || defined(CONFIG_M68K) || \ defined(CONFIG_MIPS) || defined(CONFIG_MN10300) || defined(CONFIG_PARISC) \ || defined(CONFIG_PPC) || defined(CONFIG_SPARC) || defined(CONFIG_SPARC64) -- GitLab From f77e03c68f11f54509cd660ddb5a0badfdfc61cb Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:53 +0100 Subject: [PATCH 4264/4982] ide: remove no longer needed IRQ auto-probing from try_to_identify() (v2) v2: Update actual_try_to_identify() documentation. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 50 ++++++----------------------------------- 1 file changed, 7 insertions(+), 43 deletions(-) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index ebc328c2e7e..c63c0780758 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -255,9 +255,7 @@ err_misc: * @cmd: command to use * * try_to_identify() sends an ATA(PI) IDENTIFY request to a drive - * and waits for a response. It also monitors irqs while this is - * happening, in hope of automatically determining which one is - * being used by the interface. + * and waits for a response. * * Returns: 0 device was identified * 1 device timed-out (no response to identify request) @@ -334,56 +332,22 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) * @drive: drive to probe * @cmd: command to use * - * Issue the identify command and then do IRQ probing to - * complete the identification when needed by finding the - * IRQ the drive is attached to + * Issue the identify command. */ static int try_to_identify (ide_drive_t *drive, u8 cmd) { ide_hwif_t *hwif = drive->hwif; const struct ide_tp_ops *tp_ops = hwif->tp_ops; - int retval; - int autoprobe = 0; - unsigned long cookie = 0; /* - * Disable device irq unless we need to - * probe for it. Otherwise we'll get spurious - * interrupts during the identify-phase that - * the irq handler isn't expecting. + * Disable device IRQ. Otherwise we'll get spurious interrupts + * during the identify phase that the IRQ handler isn't expecting. */ - if (hwif->io_ports.ctl_addr) { - if (!hwif->irq) { - autoprobe = 1; - cookie = probe_irq_on(); - } - tp_ops->set_irq(hwif, autoprobe); - } - - retval = actual_try_to_identify(drive, cmd); - - if (autoprobe) { - int irq; - + if (hwif->io_ports.ctl_addr) tp_ops->set_irq(hwif, 0); - /* clear drive IRQ */ - (void)tp_ops->read_status(hwif); - udelay(5); - irq = probe_irq_off(cookie); - if (!hwif->irq) { - if (irq > 0) { - hwif->irq = irq; - } else { - /* Mmmm.. multiple IRQs.. - * don't know which was ours - */ - printk(KERN_ERR "%s: IRQ probe failed (0x%lx)\n", - drive->name, cookie); - } - } - } - return retval; + + return actual_try_to_identify(drive, cmd); } int ide_busy_sleep(ide_hwif_t *hwif, unsigned long timeout, int altstatus) -- GitLab From a182807a89946bd531122bb2da60fa9ceee90343 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:53 +0100 Subject: [PATCH 4265/4982] ide: remove try_to_identify() wrapper There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index c63c0780758..5e0c3fb3b43 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -250,7 +250,7 @@ err_misc: } /** - * actual_try_to_identify - send ata/atapi identify + * try_to_identify - send ATA/ATAPI identify * @drive: drive to identify * @cmd: command to use * @@ -262,7 +262,7 @@ err_misc: * 2 device aborted the command (refused to identify itself) */ -static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) +static int try_to_identify(ide_drive_t *drive, u8 cmd) { ide_hwif_t *hwif = drive->hwif; struct ide_io_ports *io_ports = &hwif->io_ports; @@ -271,6 +271,13 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) unsigned long timeout; u8 s = 0, a = 0; + /* + * Disable device IRQ. Otherwise we'll get spurious interrupts + * during the identify phase that the IRQ handler isn't expecting. + */ + if (io_ports->ctl_addr) + tp_ops->set_irq(hwif, 0); + /* take a deep breath */ msleep(50); @@ -327,29 +334,6 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) return rc; } -/** - * try_to_identify - try to identify a drive - * @drive: drive to probe - * @cmd: command to use - * - * Issue the identify command. - */ - -static int try_to_identify (ide_drive_t *drive, u8 cmd) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_tp_ops *tp_ops = hwif->tp_ops; - - /* - * Disable device IRQ. Otherwise we'll get spurious interrupts - * during the identify phase that the IRQ handler isn't expecting. - */ - if (hwif->io_ports.ctl_addr) - tp_ops->set_irq(hwif, 0); - - return actual_try_to_identify(drive, cmd); -} - int ide_busy_sleep(ide_hwif_t *hwif, unsigned long timeout, int altstatus) { u8 stat; -- GitLab From 2ed0ef543ae3f3ea4f8bd0433fb1fed22625a309 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:53 +0100 Subject: [PATCH 4266/4982] ide: fix ->init_chipset method to return 'int' value * Return 0 instead of dev->irq in ->init_chipset implementations. * Fix ->init_chipset method to return 'int' value instead of 'unsigned int' one. This fixes ->init_chipset handling for host drivers (cs5530, hpt366 and pdc202xx_new) for which it is possible for this method to fail. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/aec62xx.c | 4 ++-- drivers/ide/alim15x3.c | 2 +- drivers/ide/amd74xx.c | 4 ++-- drivers/ide/cmd64x.c | 2 +- drivers/ide/cs5530.c | 2 +- drivers/ide/delkin_cb.c | 2 +- drivers/ide/hpt366.c | 4 ++-- drivers/ide/it821x.c | 2 +- drivers/ide/pdc202xx_new.c | 4 ++-- drivers/ide/pdc202xx_old.c | 4 ++-- drivers/ide/piix.c | 2 +- drivers/ide/serverworks.c | 4 ++-- drivers/ide/setup-pci.c | 2 +- drivers/ide/siimage.c | 2 +- drivers/ide/sis5513.c | 2 +- drivers/ide/sl82c105.c | 4 ++-- drivers/ide/via82cxxx.c | 2 +- include/linux/ide.h | 4 ++-- 18 files changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/ide/aec62xx.c b/drivers/ide/aec62xx.c index 4485b9c6f0e..878f8ec6dbe 100644 --- a/drivers/ide/aec62xx.c +++ b/drivers/ide/aec62xx.c @@ -139,7 +139,7 @@ static void aec_set_pio_mode(ide_drive_t *drive, const u8 pio) drive->hwif->port_ops->set_dma_mode(drive, pio + XFER_PIO_0); } -static unsigned int init_chipset_aec62xx(struct pci_dev *dev) +static int init_chipset_aec62xx(struct pci_dev *dev) { /* These are necessary to get AEC6280 Macintosh cards to work */ if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP865) || @@ -156,7 +156,7 @@ static unsigned int init_chipset_aec62xx(struct pci_dev *dev) pci_write_config_byte(dev, 0x4a, reg4ah | 0x80); } - return dev->irq; + return 0; } static u8 atp86x_cable_detect(ide_hwif_t *hwif) diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c index 66f43083408..d3513b6b853 100644 --- a/drivers/ide/alim15x3.c +++ b/drivers/ide/alim15x3.c @@ -212,7 +212,7 @@ static int ali15x3_dma_setup(ide_drive_t *drive) * appropriate also sets up the 1533 southbridge. */ -static unsigned int init_chipset_ali15x3(struct pci_dev *dev) +static int init_chipset_ali15x3(struct pci_dev *dev) { unsigned long flags; u8 tmpbyte; diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c index 0b51921e63e..628cd2e5fed 100644 --- a/drivers/ide/amd74xx.c +++ b/drivers/ide/amd74xx.c @@ -140,7 +140,7 @@ static void amd7411_cable_detect(struct pci_dev *dev) * The initialization callback. Initialize drive independent registers. */ -static unsigned int init_chipset_amd74xx(struct pci_dev *dev) +static int init_chipset_amd74xx(struct pci_dev *dev) { u8 t = 0, offset = amd_offset(dev); @@ -172,7 +172,7 @@ static unsigned int init_chipset_amd74xx(struct pci_dev *dev) t |= 0xf0; pci_write_config_byte(dev, AMD_IDE_CONFIG + offset, t); - return dev->irq; + return 0; } static u8 amd_cable_detect(ide_hwif_t *hwif) diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c index 2f9688d87ec..aeee036b150 100644 --- a/drivers/ide/cmd64x.c +++ b/drivers/ide/cmd64x.c @@ -333,7 +333,7 @@ static int cmd646_1_dma_end(ide_drive_t *drive) return (dma_stat & 7) != 4; } -static unsigned int init_chipset_cmd64x(struct pci_dev *dev) +static int init_chipset_cmd64x(struct pci_dev *dev) { u8 mrdmode = 0; diff --git a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c index d8ede85fe17..8e8b35a8990 100644 --- a/drivers/ide/cs5530.c +++ b/drivers/ide/cs5530.c @@ -135,7 +135,7 @@ static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode) * Initialize the cs5530 bridge for reliable IDE DMA operation. */ -static unsigned int init_chipset_cs5530(struct pci_dev *dev) +static int init_chipset_cs5530(struct pci_dev *dev) { struct pci_dev *master_0 = NULL, *cs5530_0 = NULL; diff --git a/drivers/ide/delkin_cb.c b/drivers/ide/delkin_cb.c index 8f1b2d9f051..bacb1194c9c 100644 --- a/drivers/ide/delkin_cb.c +++ b/drivers/ide/delkin_cb.c @@ -46,7 +46,7 @@ static const struct ide_port_ops delkin_cb_port_ops = { .quirkproc = ide_undecoded_slave, }; -static unsigned int delkin_cb_init_chipset(struct pci_dev *dev) +static int delkin_cb_init_chipset(struct pci_dev *dev) { unsigned long base = pci_resource_start(dev, 0); int i; diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c index 3eb9b5c63a0..d3b3e824f44 100644 --- a/drivers/ide/hpt366.c +++ b/drivers/ide/hpt366.c @@ -995,7 +995,7 @@ static void hpt3xx_disable_fast_irq(struct pci_dev *dev, u8 mcr_addr) pci_write_config_byte(dev, mcr_addr + 1, new_mcr); } -static unsigned int init_chipset_hpt366(struct pci_dev *dev) +static int init_chipset_hpt366(struct pci_dev *dev) { unsigned long io_base = pci_resource_start(dev, 4); struct hpt_info *info = hpt3xx_get_info(&dev->dev); @@ -1237,7 +1237,7 @@ static unsigned int init_chipset_hpt366(struct pci_dev *dev) hpt3xx_disable_fast_irq(dev, 0x50); hpt3xx_disable_fast_irq(dev, 0x54); - return dev->irq; + return 0; } static u8 hpt3xx_cable_detect(ide_hwif_t *hwif) diff --git a/drivers/ide/it821x.c b/drivers/ide/it821x.c index 13b8153112e..6b9fc950b4a 100644 --- a/drivers/ide/it821x.c +++ b/drivers/ide/it821x.c @@ -603,7 +603,7 @@ static void it8212_disable_raid(struct pci_dev *dev) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); } -static unsigned int init_chipset_it821x(struct pci_dev *dev) +static int init_chipset_it821x(struct pci_dev *dev) { u8 conf; static char *mode[2] = { "pass through", "smart" }; diff --git a/drivers/ide/pdc202xx_new.c b/drivers/ide/pdc202xx_new.c index f21290c4b44..b68906c3c17 100644 --- a/drivers/ide/pdc202xx_new.c +++ b/drivers/ide/pdc202xx_new.c @@ -325,7 +325,7 @@ static void apple_kiwi_init(struct pci_dev *pdev) } #endif /* CONFIG_PPC_PMAC */ -static unsigned int init_chipset_pdcnew(struct pci_dev *dev) +static int init_chipset_pdcnew(struct pci_dev *dev) { const char *name = DRV_NAME; unsigned long dma_base = pci_resource_start(dev, 4); @@ -444,7 +444,7 @@ static unsigned int init_chipset_pdcnew(struct pci_dev *dev) #endif out: - return dev->irq; + return 0; } static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev) diff --git a/drivers/ide/pdc202xx_old.c b/drivers/ide/pdc202xx_old.c index 97193323aeb..cba66ebce4e 100644 --- a/drivers/ide/pdc202xx_old.c +++ b/drivers/ide/pdc202xx_old.c @@ -264,7 +264,7 @@ static void pdc202xx_dma_timeout(ide_drive_t *drive) ide_dma_timeout(drive); } -static unsigned int init_chipset_pdc202xx(struct pci_dev *dev) +static int init_chipset_pdc202xx(struct pci_dev *dev) { unsigned long dmabase = pci_resource_start(dev, 4); u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0; @@ -290,7 +290,7 @@ static unsigned int init_chipset_pdc202xx(struct pci_dev *dev) printk("%sACTIVE\n", (inb(dmabase | 0x1f) & 1) ? "" : "IN"); } out: - return dev->irq; + return 0; } static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev, diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c index 42c2e3522d7..2aa69993306 100644 --- a/drivers/ide/piix.c +++ b/drivers/ide/piix.c @@ -204,7 +204,7 @@ static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed) * out to be nice and simple. */ -static unsigned int init_chipset_ich(struct pci_dev *dev) +static int init_chipset_ich(struct pci_dev *dev) { u32 extra = 0; diff --git a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c index 14718e73991..b6554ef9271 100644 --- a/drivers/ide/serverworks.c +++ b/drivers/ide/serverworks.c @@ -175,7 +175,7 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed) pci_write_config_byte(dev, 0x54, ultra_enable); } -static unsigned int init_chipset_svwks(struct pci_dev *dev) +static int init_chipset_svwks(struct pci_dev *dev) { unsigned int reg; u8 btr; @@ -270,7 +270,7 @@ static unsigned int init_chipset_svwks(struct pci_dev *dev) pci_write_config_byte(dev, 0x5A, btr); } - return dev->irq; + return 0; } static u8 ata66_svwks_svwks(ide_hwif_t *hwif) diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 79e3244691e..75e3beca86f 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -524,7 +524,7 @@ static int do_ide_setup_pci_device(struct pci_dev *dev, if (noisy) printk(KERN_INFO "%s %s: not 100%% native mode: will " "probe irqs later\n", d->name, pci_name(dev)); - pciirq = ret; + pciirq = 0; } else if (!pciirq && noisy) { printk(KERN_WARNING "%s %s: bad irq (%d): will probe later\n", d->name, pci_name(dev), pciirq); diff --git a/drivers/ide/siimage.c b/drivers/ide/siimage.c index cb2b352b876..1811ae9cd84 100644 --- a/drivers/ide/siimage.c +++ b/drivers/ide/siimage.c @@ -464,7 +464,7 @@ static void sil_sata_pre_reset(ide_drive_t *drive) * to 133 MHz clocking if the system isn't already set up to do it. */ -static unsigned int init_chipset_siimage(struct pci_dev *dev) +static int init_chipset_siimage(struct pci_dev *dev) { struct ide_host *host = pci_get_drvdata(dev); void __iomem *ioaddr = host->host_priv; diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c index d2d54aaea13..afca22beaad 100644 --- a/drivers/ide/sis5513.c +++ b/drivers/ide/sis5513.c @@ -447,7 +447,7 @@ static int __devinit sis_find_family(struct pci_dev *dev) return chipset_family; } -static unsigned int init_chipset_sis5513(struct pci_dev *dev) +static int init_chipset_sis5513(struct pci_dev *dev) { /* Make general config ops here 1/ tell IDE channels to operate in Compatibility mode only diff --git a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c index 6297956507c..dba213c51ba 100644 --- a/drivers/ide/sl82c105.c +++ b/drivers/ide/sl82c105.c @@ -271,7 +271,7 @@ static u8 sl82c105_bridge_revision(struct pci_dev *dev) * channel 0 here at least, but channel 1 has to be enabled by * firmware or arch code. We still set both to 16 bits mode. */ -static unsigned int init_chipset_sl82c105(struct pci_dev *dev) +static int init_chipset_sl82c105(struct pci_dev *dev) { u32 val; @@ -281,7 +281,7 @@ static unsigned int init_chipset_sl82c105(struct pci_dev *dev) val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16; pci_write_config_dword(dev, 0x40, val); - return dev->irq; + return 0; } static const struct ide_port_ops sl82c105_port_ops = { diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c index a41eab5cb5d..3ff7231e485 100644 --- a/drivers/ide/via82cxxx.c +++ b/drivers/ide/via82cxxx.c @@ -267,7 +267,7 @@ static void via_cable_detect(struct via82cxxx_dev *vdev, u32 u) * and initialize its drive independent registers. */ -static unsigned int init_chipset_via82cxxx(struct pci_dev *dev) +static int init_chipset_via82cxxx(struct pci_dev *dev) { struct ide_host *host = pci_get_drvdata(dev); struct via82cxxx_dev *vdev = host->host_priv; diff --git a/include/linux/ide.h b/include/linux/ide.h index 31e492c7bde..117dd171e70 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -851,7 +851,7 @@ struct ide_host { ide_hwif_t *ports[MAX_HOST_PORTS + 1]; unsigned int n_ports; struct device *dev[2]; - unsigned int (*init_chipset)(struct pci_dev *); + int (*init_chipset)(struct pci_dev *); irq_handler_t irq_handler; unsigned long host_flags; void *host_priv; @@ -1361,7 +1361,7 @@ enum { struct ide_port_info { char *name; - unsigned int (*init_chipset)(struct pci_dev *); + int (*init_chipset)(struct pci_dev *); void (*init_iops)(ide_hwif_t *); void (*init_hwif)(ide_hwif_t *); int (*init_dma)(ide_hwif_t *, -- GitLab From 86ccf37c6acd74cf7e4b7751ee045de19943c5a0 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:53 +0100 Subject: [PATCH 4267/4982] ide: remove pciirq argument from ide_pci_setup_ports() * Set ->irq explicitly in cs5520.c. * Remove irq argument from ide_hw_configure(). * Remove pciirq argument from ide_pci_setup_ports(). There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/cs5520.c | 3 ++- drivers/ide/setup-pci.c | 13 +++++-------- include/linux/ide.h | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/ide/cs5520.c b/drivers/ide/cs5520.c index d003bec56ff..58fb90e5b76 100644 --- a/drivers/ide/cs5520.c +++ b/drivers/ide/cs5520.c @@ -133,7 +133,8 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic * do all the device setup for us */ - ide_pci_setup_ports(dev, d, 14, &hw[0], &hws[0]); + ide_pci_setup_ports(dev, d, &hw[0], &hws[0]); + hw[0].irq = 14; return ide_host_add(d, hws, NULL); } diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 75e3beca86f..24bc884826f 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -305,7 +305,6 @@ static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info * * @dev: PCI device holding interface * @d: IDE port info * @port: port number - * @irq: PCI IRQ * @hw: hw_regs_t instance corresponding to this port * * Perform the initial set up for the hardware interface structure. This @@ -316,7 +315,7 @@ static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info * */ static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d, - unsigned int port, int irq, hw_regs_t *hw) + unsigned int port, hw_regs_t *hw) { unsigned long ctl = 0, base = 0; @@ -344,7 +343,6 @@ static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d, } memset(hw, 0, sizeof(*hw)); - hw->irq = irq; hw->dev = &dev->dev; hw->chipset = d->chipset ? d->chipset : ide_pci; ide_std_init_ports(hw, base, ctl | 2); @@ -448,7 +446,6 @@ out: * ide_pci_setup_ports - configure ports/devices on PCI IDE * @dev: PCI device * @d: IDE port info - * @pciirq: IRQ line * @hw: hw_regs_t instances corresponding to this PCI IDE device * @hws: hw_regs_t pointers table to update * @@ -462,7 +459,7 @@ out: */ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, - int pciirq, hw_regs_t *hw, hw_regs_t **hws) + hw_regs_t *hw, hw_regs_t **hws) { int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port; u8 tmp; @@ -481,7 +478,7 @@ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, continue; /* port not enabled */ } - if (ide_hw_configure(dev, d, port, pciirq, hw + port)) + if (ide_hw_configure(dev, d, port, hw + port)) continue; *(hws + port) = hw + port; @@ -549,7 +546,7 @@ int ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d, if (ret < 0) goto out; - ide_pci_setup_ports(dev, d, 0, &hw[0], &hws[0]); + ide_pci_setup_ports(dev, d, &hw[0], &hws[0]); host = ide_host_alloc(d, hws); if (host == NULL) { @@ -595,7 +592,7 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, if (ret < 0) goto out; - ide_pci_setup_ports(pdev[i], d, 0, &hw[i*2], &hws[i*2]); + ide_pci_setup_ports(pdev[i], d, &hw[i*2], &hws[i*2]); } host = ide_host_alloc(d, hws); diff --git a/include/linux/ide.h b/include/linux/ide.h index 117dd171e70..24e265af4f1 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1265,7 +1265,7 @@ static inline int ide_pci_is_in_compatibility_mode(struct pci_dev *dev) return 0; } -void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *, int, +void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *, hw_regs_t *, hw_regs_t **); void ide_setup_pci_noise(struct pci_dev *, const struct ide_port_info *); -- GitLab From 662641d98b4396b48f513726d141c5f646c08259 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:54 +0100 Subject: [PATCH 4268/4982] frv: remove * Remove superfluous includes. * Remove . Cc: David Howells Signed-off-by: Bartlomiej Zolnierkiewicz --- include/asm-frv/ide.h | 24 ------------------------ include/linux/ide.h | 4 ++-- 2 files changed, 2 insertions(+), 26 deletions(-) delete mode 100644 include/asm-frv/ide.h diff --git a/include/asm-frv/ide.h b/include/asm-frv/ide.h deleted file mode 100644 index 36107661185..00000000000 --- a/include/asm-frv/ide.h +++ /dev/null @@ -1,24 +0,0 @@ -/* ide.h: FRV IDE declarations - * - * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#ifndef _ASM_IDE_H -#define _ASM_IDE_H - -#ifdef __KERNEL__ - -#include -#include -#include - -#include - -#endif /* __KERNEL__ */ -#endif /* _ASM_IDE_H */ diff --git a/include/linux/ide.h b/include/linux/ide.h index 24e265af4f1..047b74621dd 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -193,8 +193,8 @@ static inline void ide_std_init_ports(hw_regs_t *hw, hw->io_ports.ctl_addr = ctl_addr; } -#if defined(CONFIG_ARM) || defined(CONFIG_FRV) || defined(CONFIG_M68K) || \ - defined(CONFIG_MIPS) || defined(CONFIG_MN10300) || defined(CONFIG_PARISC) \ +#if defined(CONFIG_ARM) || defined(CONFIG_M68K) || defined(CONFIG_MIPS) || \ + defined(CONFIG_MN10300) || defined(CONFIG_PARISC) \ || defined(CONFIG_PPC) || defined(CONFIG_SPARC) || defined(CONFIG_SPARC64) #include #else -- GitLab From d45b70ab9bbf1a46ae52972d532f9e267b8d39d9 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:54 +0100 Subject: [PATCH 4269/4982] mn10300: remove * Remove superfluous include. * Remove no longer used SUPPORT_SLOW_DATA_PORTS define. * Move defining SUPPORT_VLB_SYNC to . * Use __ide_mm_*() macros from (MN10300 uses only memory-mapped I/O). * Remove . While at it: * Remove superfluous SPARC64 #ifdef from . Cc: David Howells Signed-off-by: Bartlomiej Zolnierkiewicz --- include/asm-mn10300/ide.h | 39 --------------------------------------- include/linux/ide.h | 5 ++--- 2 files changed, 2 insertions(+), 42 deletions(-) delete mode 100644 include/asm-mn10300/ide.h diff --git a/include/asm-mn10300/ide.h b/include/asm-mn10300/ide.h deleted file mode 100644 index 6adcdd92e83..00000000000 --- a/include/asm-mn10300/ide.h +++ /dev/null @@ -1,39 +0,0 @@ -/* MN10300 Arch-specific IDE code - * - * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - Derived from include/asm-i386/ide.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public Licence - * as published by the Free Software Foundation; either version - * 2 of the Licence, or (at your option) any later version. - */ - -#ifndef _ASM_IDE_H -#define _ASM_IDE_H - -#ifdef __KERNEL__ - -#include - -#undef SUPPORT_SLOW_DATA_PORTS -#define SUPPORT_SLOW_DATA_PORTS 0 - -#undef SUPPORT_VLB_SYNC -#define SUPPORT_VLB_SYNC 0 - -/* - * some bits needed for parts of the IDE subsystem to compile - */ -#define __ide_mm_insw(port, addr, n) \ - insw((unsigned long) (port), (addr), (n)) -#define __ide_mm_insl(port, addr, n) \ - insl((unsigned long) (port), (addr), (n)) -#define __ide_mm_outsw(port, addr, n) \ - outsw((unsigned long) (port), (addr), (n)) -#define __ide_mm_outsl(port, addr, n) \ - outsl((unsigned long) (port), (addr), (n)) - -#endif /* __KERNEL__ */ -#endif /* _ASM_IDE_H */ diff --git a/include/linux/ide.h b/include/linux/ide.h index 047b74621dd..bbce9b2bdfc 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -26,7 +26,7 @@ #include #include -#if defined(CONFIG_CRIS) || defined(CONFIG_FRV) +#if defined(CONFIG_CRIS) || defined(CONFIG_FRV) || defined(CONFIG_MN10300) # define SUPPORT_VLB_SYNC 0 #else # define SUPPORT_VLB_SYNC 1 @@ -194,8 +194,7 @@ static inline void ide_std_init_ports(hw_regs_t *hw, } #if defined(CONFIG_ARM) || defined(CONFIG_M68K) || defined(CONFIG_MIPS) || \ - defined(CONFIG_MN10300) || defined(CONFIG_PARISC) \ - || defined(CONFIG_PPC) || defined(CONFIG_SPARC) || defined(CONFIG_SPARC64) + defined(CONFIG_PARISC) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) #include #else #include -- GitLab From 2f40c9b0b65b5635e2e13dfa068bd56fe7a8ff98 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:54 +0100 Subject: [PATCH 4270/4982] ide: fix kmalloc() failure handling in ide_driveid_update() * Doing kmalloc() in the middle of command execution is not only ugly but leaves drive waiting to send data on kmalloc() failure. Fix it. While at it: * Unify error code paths. * Fixup error message to be more useful and add missing KERN_ERR level. * Rename 'stat' variable to 's'. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index e0cfa2d2acc..a955483d240 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -293,7 +293,12 @@ int ide_driveid_update(ide_drive_t *drive) const struct ide_tp_ops *tp_ops = hwif->tp_ops; u16 *id; unsigned long flags; - u8 stat; + int rc; + u8 uninitialized_var(s); + + id = kmalloc(SECTOR_SIZE, GFP_ATOMIC); + if (id == NULL) + return 0; /* * Re-read drive->id for possible DMA mode @@ -306,25 +311,21 @@ int ide_driveid_update(ide_drive_t *drive) tp_ops->exec_command(hwif, ATA_CMD_ID_ATA); if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 1)) { - SELECT_MASK(drive, 0); - return 0; + rc = 1; + goto out_err; } msleep(50); /* wait for IRQ and ATA_DRQ */ - stat = tp_ops->read_status(hwif); - if (!OK_STAT(stat, ATA_DRQ, BAD_R_STAT)) { - SELECT_MASK(drive, 0); - printk("%s: CHECK for good STATUS\n", drive->name); - return 0; + s = tp_ops->read_status(hwif); + + if (!OK_STAT(s, ATA_DRQ, BAD_R_STAT)) { + rc = 2; + goto out_err; } + local_irq_save(flags); SELECT_MASK(drive, 0); - id = kmalloc(SECTOR_SIZE, GFP_ATOMIC); - if (!id) { - local_irq_restore(flags); - return 0; - } tp_ops->input_data(drive, NULL, id, SECTOR_SIZE); (void)tp_ops->read_status(hwif); /* clear drive IRQ */ local_irq_enable(); @@ -342,6 +343,12 @@ int ide_driveid_update(ide_drive_t *drive) ide_dma_off(drive); return 1; +out_err: + SELECT_MASK(drive, 0); + if (rc == 2) + printk(KERN_ERR "%s: %s: bad status\n", drive->name, __func__); + kfree(id); + return 0; } int ide_config_drive_speed(ide_drive_t *drive, u8 speed) -- GitLab From 62bd0441a60b0499db339b3dc1be039f8ed9fd35 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:55 +0100 Subject: [PATCH 4271/4982] ide: propagate AltStatus workarounds to ide_driveid_update() Propagate AltStatus workarounds from try_to_identify() to ide_driveid_update(). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index a955483d240..944cd857c90 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -293,8 +293,8 @@ int ide_driveid_update(ide_drive_t *drive) const struct ide_tp_ops *tp_ops = hwif->tp_ops; u16 *id; unsigned long flags; - int rc; - u8 uninitialized_var(s); + int use_altstatus = 0, rc; + u8 a, uninitialized_var(s); id = kmalloc(SECTOR_SIZE, GFP_ATOMIC); if (id == NULL) @@ -308,9 +308,24 @@ int ide_driveid_update(ide_drive_t *drive) SELECT_MASK(drive, 1); tp_ops->set_irq(hwif, 0); msleep(50); + + if (hwif->io_ports.ctl_addr && + (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) { + a = tp_ops->read_altstatus(hwif); + s = tp_ops->read_status(hwif); + if ((a ^ s) & ~ATA_IDX) + /* ancient Seagate drives, broken interfaces */ + printk(KERN_INFO "%s: probing with STATUS(0x%02x) " + "instead of ALTSTATUS(0x%02x)\n", + drive->name, s, a); + else + /* use non-intrusive polling */ + use_altstatus = 1; + } + tp_ops->exec_command(hwif, ATA_CMD_ID_ATA); - if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 1)) { + if (ide_busy_sleep(hwif, WAIT_WORSTCASE, use_altstatus)) { rc = 1; goto out_err; } -- GitLab From 4cda15a0995f2da5727514f84ec26d8b7420e1f9 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:57 +0100 Subject: [PATCH 4272/4982] ide: shorten timeout value in ide_driveid_update() Shorten timeout value in ide_driveid_update() (30s -> 15s) to match try_to_identify(). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 944cd857c90..59c02184ba8 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -325,7 +325,7 @@ int ide_driveid_update(ide_drive_t *drive) tp_ops->exec_command(hwif, ATA_CMD_ID_ATA); - if (ide_busy_sleep(hwif, WAIT_WORSTCASE, use_altstatus)) { + if (ide_busy_sleep(hwif, WAIT_WORSTCASE / 2, use_altstatus)) { rc = 1; goto out_err; } -- GitLab From 552d3a99bdce8a0d7f9abe3766fb3655ef5757dc Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:58 +0100 Subject: [PATCH 4273/4982] ide: remove broken EXABYTENEST support do_identify() marks EXABYTENEST device as non-present and frees drive->id so enable_nest() has absolutely no chance of working. The code was like this since at least 2.6.12-rc2 and nobody has noticed so just remove broken EXABYTENEST support. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 37 ------------------------------------- include/linux/ata.h | 2 -- 2 files changed, 39 deletions(-) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 5e0c3fb3b43..29649d09dbb 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -465,37 +465,6 @@ static int do_probe (ide_drive_t *drive, u8 cmd) return rc; } -/* - * - */ -static void enable_nest (ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_tp_ops *tp_ops = hwif->tp_ops; - u8 stat; - - printk(KERN_INFO "%s: enabling %s -- ", - hwif->name, (char *)&drive->id[ATA_ID_PROD]); - - SELECT_DRIVE(drive); - msleep(50); - tp_ops->exec_command(hwif, ATA_EXABYTE_ENABLE_NEST); - - if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 0)) { - printk(KERN_CONT "failed (timeout)\n"); - return; - } - - msleep(50); - - stat = tp_ops->read_status(hwif); - - if (!OK_STAT(stat, 0, BAD_STAT)) - printk(KERN_CONT "failed (status = 0x%02x)\n", stat); - else - printk(KERN_CONT "success\n"); -} - /** * probe_for_drives - upper level drive probe * @drive: drive to probe for @@ -534,7 +503,6 @@ static u8 probe_for_drive(ide_drive_t *drive) /* skip probing? */ if ((drive->dev_flags & IDE_DFLAG_NOPROBE) == 0) { -retry: /* if !(success||timed-out) */ if (do_probe(drive, ATA_CMD_ID_ATA) >= 2) /* look for ATAPI device */ @@ -544,11 +512,6 @@ retry: /* drive not found */ return 0; - if (strstr(m, "E X A B Y T E N E S T")) { - enable_nest(drive); - goto retry; - } - /* identification failed? */ if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) { if (drive->media == ide_disk) { diff --git a/include/linux/ata.h b/include/linux/ata.h index 9a061accd8b..68132c4a0e9 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -244,8 +244,6 @@ enum { ATA_CMD_MEDIA_UNLOCK = 0xDF, /* marked obsolete in the ATA/ATAPI-7 spec */ ATA_CMD_RESTORE = 0x10, - /* EXABYTE specific */ - ATA_EXABYTE_ENABLE_NEST = 0xF0, /* READ_LOG_EXT pages */ ATA_LOG_SATA_NCQ = 0x10, -- GitLab From 1bd4c1f4fe6607a0253d1318847b618a2a598612 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:58 +0100 Subject: [PATCH 4274/4982] ide: classify device type in do_probe() Defer classifying device type from do_identify() to do_probe(). There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 29649d09dbb..3f9faef5e50 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -233,16 +233,6 @@ static void do_identify(ide_drive_t *drive, u8 cmd) drive->dev_flags |= IDE_DFLAG_PRESENT; drive->dev_flags &= ~IDE_DFLAG_DEAD; - /* - * Check for an ATAPI device - */ - if (cmd == ATA_CMD_ID_ATAPI) - ide_classify_atapi_dev(drive); - else - /* - * Not an ATAPI device: looks like a "regular" hard disk - */ - ide_classify_ata_dev(drive); return; err_misc: kfree(id); @@ -480,6 +470,8 @@ static int do_probe (ide_drive_t *drive, u8 cmd) static u8 probe_for_drive(ide_drive_t *drive) { char *m; + int rc; + u8 cmd; /* * In order to keep things simple we have an id @@ -504,9 +496,13 @@ static u8 probe_for_drive(ide_drive_t *drive) /* skip probing? */ if ((drive->dev_flags & IDE_DFLAG_NOPROBE) == 0) { /* if !(success||timed-out) */ - if (do_probe(drive, ATA_CMD_ID_ATA) >= 2) + cmd = ATA_CMD_ID_ATA; + rc = do_probe(drive, cmd); + if (rc >= 2) { /* look for ATAPI device */ - (void)do_probe(drive, ATA_CMD_ID_ATAPI); + cmd = ATA_CMD_ID_ATAPI; + rc = do_probe(drive, cmd); + } if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) /* drive not found */ @@ -525,8 +521,12 @@ static u8 probe_for_drive(ide_drive_t *drive) printk(KERN_WARNING "%s: Unknown device on bus refused identification. Ignoring.\n", drive->name); drive->dev_flags &= ~IDE_DFLAG_PRESENT; } + } else { + if (cmd == ATA_CMD_ID_ATAPI) + ide_classify_atapi_dev(drive); + else + ide_classify_ata_dev(drive); } - /* drive was found */ } if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) -- GitLab From f323b80dceaca858f8e240ca098681fcfe7fd3c4 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:58 +0100 Subject: [PATCH 4275/4982] ide: sanitize SELECT_MASK() usage in ide_driveid_update() Call SELECT_MASK() after ide_fix_driveid(). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 59c02184ba8..f92c63f564d 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -340,13 +340,15 @@ int ide_driveid_update(ide_drive_t *drive) } local_irq_save(flags); - SELECT_MASK(drive, 0); tp_ops->input_data(drive, NULL, id, SECTOR_SIZE); (void)tp_ops->read_status(hwif); /* clear drive IRQ */ local_irq_enable(); local_irq_restore(flags); + ide_fix_driveid(id); + SELECT_MASK(drive, 0); + drive->id[ATA_ID_UDMA_MODES] = id[ATA_ID_UDMA_MODES]; drive->id[ATA_ID_MWDMA_MODES] = id[ATA_ID_MWDMA_MODES]; drive->id[ATA_ID_SWDMA_MODES] = id[ATA_ID_SWDMA_MODES]; -- GitLab From ff18b89bef76d291db594af3e27b6c91e6600b57 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:58 +0100 Subject: [PATCH 4276/4982] ide: clear drive IRQ after re-enabling local IRQs in ide_driveid_update() Clear drive IRQ after re-enabling local IRQs in ide_driveid_update() to match try_to_identify(). Also remove superfluous local_irq_enable() call while at it. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index f92c63f564d..affbc603987 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -341,10 +341,10 @@ int ide_driveid_update(ide_drive_t *drive) local_irq_save(flags); tp_ops->input_data(drive, NULL, id, SECTOR_SIZE); - (void)tp_ops->read_status(hwif); /* clear drive IRQ */ - local_irq_enable(); local_irq_restore(flags); + (void)tp_ops->read_status(hwif); /* clear drive IRQ */ + ide_fix_driveid(id); SELECT_MASK(drive, 0); -- GitLab From 2ebe1d9efed5f232afc8d00901d0959c9814bce3 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:59 +0100 Subject: [PATCH 4277/4982] ide: use try_to_identify() in ide_driveid_update() * Pass pointer to buffer for IDENTIFY data to do_identify() and try_to_identify(). * Un-static try_to_identify() and use it in ide_driveid_update(). * Rename try_to_identify() to ide_dev_read_id(). There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 54 +++-------------------------------------- drivers/ide/ide-probe.c | 24 +++++++++--------- include/linux/ide.h | 2 ++ 3 files changed, 18 insertions(+), 62 deletions(-) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index affbc603987..317c5dadd7c 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -289,65 +289,19 @@ no_80w: int ide_driveid_update(ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; - const struct ide_tp_ops *tp_ops = hwif->tp_ops; u16 *id; - unsigned long flags; - int use_altstatus = 0, rc; - u8 a, uninitialized_var(s); + int rc; id = kmalloc(SECTOR_SIZE, GFP_ATOMIC); if (id == NULL) return 0; - /* - * Re-read drive->id for possible DMA mode - * change (copied from ide-probe.c) - */ - SELECT_MASK(drive, 1); - tp_ops->set_irq(hwif, 0); - msleep(50); - - if (hwif->io_ports.ctl_addr && - (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) { - a = tp_ops->read_altstatus(hwif); - s = tp_ops->read_status(hwif); - if ((a ^ s) & ~ATA_IDX) - /* ancient Seagate drives, broken interfaces */ - printk(KERN_INFO "%s: probing with STATUS(0x%02x) " - "instead of ALTSTATUS(0x%02x)\n", - drive->name, s, a); - else - /* use non-intrusive polling */ - use_altstatus = 1; - } - - tp_ops->exec_command(hwif, ATA_CMD_ID_ATA); - - if (ide_busy_sleep(hwif, WAIT_WORSTCASE / 2, use_altstatus)) { - rc = 1; - goto out_err; - } - - msleep(50); /* wait for IRQ and ATA_DRQ */ - - s = tp_ops->read_status(hwif); + rc = ide_dev_read_id(drive, ATA_CMD_ID_ATA, id); + SELECT_MASK(drive, 0); - if (!OK_STAT(s, ATA_DRQ, BAD_R_STAT)) { - rc = 2; + if (rc) goto out_err; - } - - local_irq_save(flags); - tp_ops->input_data(drive, NULL, id, SECTOR_SIZE); - local_irq_restore(flags); - - (void)tp_ops->read_status(hwif); /* clear drive IRQ */ - - ide_fix_driveid(id); - - SELECT_MASK(drive, 0); drive->id[ATA_ID_UDMA_MODES] = id[ATA_ID_UDMA_MODES]; drive->id[ATA_ID_MWDMA_MODES] = id[ATA_ID_MWDMA_MODES]; diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 3f9faef5e50..974067043fb 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -181,16 +181,16 @@ static void ide_classify_atapi_dev(ide_drive_t *drive) * do_identify - identify a drive * @drive: drive to identify * @cmd: command used + * @id: buffer for IDENTIFY data * * Called when we have issued a drive identify command to * read and parse the results. This function is run with * interrupts disabled. */ -static void do_identify(ide_drive_t *drive, u8 cmd) +static void do_identify(ide_drive_t *drive, u8 cmd, u16 *id) { ide_hwif_t *hwif = drive->hwif; - u16 *id = drive->id; char *m = (char *)&id[ATA_ID_PROD]; unsigned long flags; int bswap = 1; @@ -240,19 +240,19 @@ err_misc: } /** - * try_to_identify - send ATA/ATAPI identify + * ide_dev_read_id - send ATA/ATAPI IDENTIFY command * @drive: drive to identify * @cmd: command to use + * @id: buffer for IDENTIFY data * - * try_to_identify() sends an ATA(PI) IDENTIFY request to a drive - * and waits for a response. + * Sends an ATA(PI) IDENTIFY request to a drive and waits for a response. * * Returns: 0 device was identified * 1 device timed-out (no response to identify request) * 2 device aborted the command (refused to identify itself) */ -static int try_to_identify(ide_drive_t *drive, u8 cmd) +int ide_dev_read_id(ide_drive_t *drive, u8 cmd, u16 *id) { ide_hwif_t *hwif = drive->hwif; struct ide_io_ports *io_ports = &hwif->io_ports; @@ -312,7 +312,7 @@ static int try_to_identify(ide_drive_t *drive, u8 cmd) if (OK_STAT(s, ATA_DRQ, BAD_R_STAT)) { /* drive returned ID */ - do_identify(drive, cmd); + do_identify(drive, cmd, id); /* drive responded with ID */ rc = 0; /* clear drive IRQ */ @@ -378,6 +378,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd) { ide_hwif_t *hwif = drive->hwif; const struct ide_tp_ops *tp_ops = hwif->tp_ops; + u16 *id = drive->id; int rc; u8 present = !!(drive->dev_flags & IDE_DFLAG_PRESENT), stat; @@ -413,11 +414,10 @@ static int do_probe (ide_drive_t *drive, u8 cmd) if (OK_STAT(stat, ATA_DRDY, ATA_BUSY) || present || cmd == ATA_CMD_ID_ATAPI) { - /* send cmd and wait */ - if ((rc = try_to_identify(drive, cmd))) { + rc = ide_dev_read_id(drive, cmd, id); + if (rc) /* failed: try again */ - rc = try_to_identify(drive,cmd); - } + rc = ide_dev_read_id(drive, cmd, id); stat = tp_ops->read_status(hwif); @@ -432,7 +432,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd) msleep(50); tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET); (void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0); - rc = try_to_identify(drive, cmd); + rc = ide_dev_read_id(drive, cmd, id); } /* ensure drive IRQ is clear */ diff --git a/include/linux/ide.h b/include/linux/ide.h index bbce9b2bdfc..854eba8b2ba 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1235,6 +1235,8 @@ int ide_no_data_taskfile(ide_drive_t *, ide_task_t *); int ide_taskfile_ioctl(ide_drive_t *, unsigned int, unsigned long); +int ide_dev_read_id(ide_drive_t *, u8, u16 *); + extern int ide_driveid_update(ide_drive_t *); extern int ide_config_drive_speed(ide_drive_t *, u8); extern u8 eighty_ninty_three (ide_drive_t *); -- GitLab From e5b5719b06d3c614e904bc817177bd3c49c52edb Mon Sep 17 00:00:00 2001 From: Klaus-Dieter Wacker Date: Tue, 24 Mar 2009 03:27:43 +0000 Subject: [PATCH 4278/4982] Use kthread instead of kernel_thread Lcs uses low-level kernel_thread implementation. All drivers should use API instead. Signed-off-by: Klaus-Dieter Wacker Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- drivers/s390/net/lcs.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 083f787d260..840dbf3d341 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -1259,7 +1260,6 @@ lcs_register_mc_addresses(void *data) struct in_device *in4_dev; card = (struct lcs_card *) data; - daemonize("regipm"); if (!lcs_do_run_thread(card, LCS_SET_MC_THREAD)) return 0; @@ -1753,11 +1753,10 @@ lcs_start_kernel_thread(struct work_struct *work) struct lcs_card *card = container_of(work, struct lcs_card, kernel_thread_starter); LCS_DBF_TEXT(5, trace, "krnthrd"); if (lcs_do_start_thread(card, LCS_RECOVERY_THREAD)) - kernel_thread(lcs_recovery, (void *) card, SIGCHLD); + kthread_run(lcs_recovery, card, "lcs_recover"); #ifdef CONFIG_IP_MULTICAST if (lcs_do_start_thread(card, LCS_SET_MC_THREAD)) - kernel_thread(lcs_register_mc_addresses, - (void *) card, SIGCHLD); + kthread_run(lcs_register_mc_addresses, card, "regipm"); #endif } @@ -2269,7 +2268,6 @@ lcs_recovery(void *ptr) int rc; card = (struct lcs_card *) ptr; - daemonize("lcs_recover"); LCS_DBF_TEXT(4, trace, "recover1"); if (!lcs_do_run_thread(card, LCS_RECOVERY_THREAD)) -- GitLab From 9e669d327a873bbab51e7e95ee9f9c3c49755594 Mon Sep 17 00:00:00 2001 From: Klaus-Dieter Wacker Date: Tue, 24 Mar 2009 03:27:44 +0000 Subject: [PATCH 4279/4982] lcs: invalid return codes from hard_start_xmit. Lcs hard_start_xmit routine issued return codes other than defined for this interface. Now lcs returns only either NETDEV_TX_OK or NETDEV_TX_BUSY. Signed-off-by: Klaus-Dieter Wacker Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- drivers/s390/net/lcs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 840dbf3d341..a45bc24eb5f 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -1562,7 +1562,7 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb, if (skb == NULL) { card->stats.tx_dropped++; card->stats.tx_errors++; - return -EIO; + return 0; } if (card->state != DEV_STATE_UP) { dev_kfree_skb(skb); @@ -1587,7 +1587,7 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb, card->tx_buffer = lcs_get_buffer(&card->write); if (card->tx_buffer == NULL) { card->stats.tx_dropped++; - rc = -EBUSY; + rc = NETDEV_TX_BUSY; goto out; } card->tx_buffer->callback = lcs_txbuffer_cb; -- GitLab From 4e584d66ea60cf3d921aea78372f4e4d48a9155d Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Tue, 24 Mar 2009 03:27:45 +0000 Subject: [PATCH 4280/4982] netiucv: invalid return code from hard_start_xmit Avoid kernel warning by using the correct hard_start_xmit return code NETDEV_TX_BUSY for skb requeuing. Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- drivers/s390/net/netiucv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 1ba4509435f..be716e45f7a 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -1312,7 +1312,7 @@ static int netiucv_tx(struct sk_buff *skb, struct net_device *dev) if (netiucv_test_and_set_busy(dev)) { IUCV_DBF_TEXT(data, 2, "EBUSY from netiucv_tx\n"); - return -EBUSY; + return NETDEV_TX_BUSY; } dev->trans_start = jiffies; rc = netiucv_transmit_skb(privptr->conn, skb) != 0; -- GitLab From 8f0c40d4b6a6207ef2105d94544a9d1c0835c4ab Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Tue, 24 Mar 2009 03:27:46 +0000 Subject: [PATCH 4281/4982] claw: invalid return codes from hard_start_xmit Avoid kernel warnings by using the correct hard_start_xmit return code NETDEV_TX_BUSY for skb requeuing. Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- drivers/s390/net/claw.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index 6669adf355b..a4524ecd9dc 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -348,6 +348,8 @@ claw_tx(struct sk_buff *skb, struct net_device *dev) rc=claw_hw_tx( skb, dev, 1 ); spin_unlock_irqrestore(get_ccwdev_lock(p_ch->cdev), saveflags); CLAW_DBF_TEXT_(4, trace, "clawtx%d", rc); + if (rc) + rc = NETDEV_TX_BUSY; return rc; } /* end of claw_tx */ -- GitLab From 3a05d1404d91efd63f0654a4bf59b8803c32efdd Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Tue, 24 Mar 2009 03:27:47 +0000 Subject: [PATCH 4282/4982] ctcm: invalid return code from hard_start_xmit Avoid kernel warning by using the correct hard_start_xmit return code NETDEV_TX_BUSY for skb requeuing. Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- drivers/s390/net/ctcm_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index 8f2a888d0a0..59ce7fb7308 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -906,11 +906,11 @@ static int ctcm_tx(struct sk_buff *skb, struct net_device *dev) } if (ctcm_test_and_set_busy(dev)) - return -EBUSY; + return NETDEV_TX_BUSY; dev->trans_start = jiffies; if (ctcm_transmit_skb(priv->channel[WRITE], skb) != 0) - return 1; + return NETDEV_TX_BUSY; return 0; } -- GitLab From fb8585fc3f9b39153e0bdaf03f00a02dde9c03c6 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 24 Mar 2009 03:27:48 +0000 Subject: [PATCH 4283/4982] ctcm: avoid wraparound in length of incoming data Since the receive code should tolerate any incoming garbage, it should be protected against a potential wraparound when manipulating length values within incoming data. block_len is unsigned, so a too large subtraction will cause a wraparound. Signed-off-by: Roel Kluin Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- drivers/s390/net/ctcm_fsms.c | 5 ++--- drivers/s390/net/ctcm_main.c | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/s390/net/ctcm_fsms.c b/drivers/s390/net/ctcm_fsms.c index f29c7086fc1..4ded9ac2c5e 100644 --- a/drivers/s390/net/ctcm_fsms.c +++ b/drivers/s390/net/ctcm_fsms.c @@ -410,9 +410,8 @@ static void chx_rx(fsm_instance *fi, int event, void *arg) priv->stats.rx_length_errors++; goto again; } - block_len -= 2; - if (block_len > 0) { - *((__u16 *)skb->data) = block_len; + if (block_len > 2) { + *((__u16 *)skb->data) = block_len - 2; ctcm_unpack_skb(ch, skb); } again: diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index 59ce7fb7308..a7a25383db7 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -105,7 +105,8 @@ void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb) return; } pskb->protocol = ntohs(header->type); - if (header->length <= LL_HEADER_LENGTH) { + if ((header->length <= LL_HEADER_LENGTH) || + (len <= LL_HEADER_LENGTH)) { if (!(ch->logflags & LOG_FLAG_ILLEGALSIZE)) { CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR, "%s(%s): Illegal packet size %d(%d,%d)" -- GitLab From e2fc8cb4fedf57a63c05cd1e0f6e4f0e0238614a Mon Sep 17 00:00:00 2001 From: "Joel A. Fowler" Date: Tue, 24 Mar 2009 03:27:49 +0000 Subject: [PATCH 4284/4982] ctcm: fix minor findings from code analysis tool From: Ursula Braun This patch fixes problems in the ctcm driver identified by static code analysis: o remove an unnecessary always true condition in ctcm_unpack_skb o remove duplicate assignment in ctc_mpc_alloc_channel o remove an unnecessary always true condition in ctcmpc_send_sweep_resp o remove duplicate initialization in ctcmpc_unpack_skb o shorten if condition in mpc_action_go_inop o remove INOP event if mpc group is undefined in mpc_action_doxid7 Signed-off-by: Joel A. Fowler Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- drivers/s390/net/ctcm_main.c | 8 +++----- drivers/s390/net/ctcm_mpc.c | 17 +++++------------ 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index a7a25383db7..77f4033a0f4 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -168,11 +168,9 @@ void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb) if (len > 0) { skb_pull(pskb, header->length); if (skb_tailroom(pskb) < LL_HEADER_LENGTH) { - if (!(ch->logflags & LOG_FLAG_OVERRUN)) { - CTCM_DBF_DEV_NAME(TRACE, dev, - "Overrun in ctcm_unpack_skb"); - ch->logflags |= LOG_FLAG_OVERRUN; - } + CTCM_DBF_DEV_NAME(TRACE, dev, + "Overrun in ctcm_unpack_skb"); + ch->logflags |= LOG_FLAG_OVERRUN; return; } skb_put(pskb, LL_HEADER_LENGTH); diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c index 3db5f846bbf..781e18be7e8 100644 --- a/drivers/s390/net/ctcm_mpc.c +++ b/drivers/s390/net/ctcm_mpc.c @@ -393,7 +393,6 @@ int ctc_mpc_alloc_channel(int port_num, void (*callback)(int, int)) } else { /* there are problems...bail out */ /* there may be a state mismatch so restart */ - grp->port_persist = 1; fsm_event(grp->fsm, MPCG_EVENT_INOP, dev); grp->allocchan_callback_retries = 0; } @@ -699,11 +698,9 @@ static void ctcmpc_send_sweep_resp(struct channel *rch) return; done: - if (rc != 0) { - grp->in_sweep = 0; - ctcm_clear_busy_do(dev); - fsm_event(grp->fsm, MPCG_EVENT_INOP, dev); - } + grp->in_sweep = 0; + ctcm_clear_busy_do(dev); + fsm_event(grp->fsm, MPCG_EVENT_INOP, dev); return; } @@ -1118,7 +1115,6 @@ static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb) if (unlikely(fsm_getstate(grp->fsm) != MPCG_STATE_READY)) goto done; - pdu_last_seen = 0; while ((pskb->len > 0) && !pdu_last_seen) { curr_pdu = (struct pdu *)pskb->data; @@ -1396,8 +1392,7 @@ static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg) CTCM_FUNTAIL, dev->name); if ((grp->saved_state != MPCG_STATE_RESET) || /* dealloc_channel has been called */ - ((grp->saved_state == MPCG_STATE_RESET) && - (grp->port_persist == 0))) + (grp->port_persist == 0)) fsm_deltimer(&priv->restart_timer); wch = priv->channel[WRITE]; @@ -1917,10 +1912,8 @@ static void mpc_action_doxid7(fsm_instance *fsm, int event, void *arg) if (priv) grp = priv->mpcg; - if (grp == NULL) { - fsm_event(grp->fsm, MPCG_EVENT_INOP, dev); + if (grp == NULL) return; - } for (direction = READ; direction <= WRITE; direction++) { struct channel *ch = priv->channel[direction]; -- GitLab From b9d2fceecb6afd9dead4fd2488a543b302a3272e Mon Sep 17 00:00:00 2001 From: "Andrew H. Richter" Date: Tue, 24 Mar 2009 03:27:51 +0000 Subject: [PATCH 4285/4982] claw: fix minor findings from code analysis tool This patch fixes two problems in the claw driver identified by static code analysis: o Change in case differentiation of received sense codes o Use correct data length in claw hard_start_xmit routine Signed-off-by: Andrew H. Richter Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- drivers/s390/net/claw.c | 44 +++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index a4524ecd9dc..30a43cc79e7 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -1033,7 +1033,7 @@ static int pages_to_order_of_mag(int num_of_pages) { int order_of_mag=1; /* assume 2 pages */ - int nump=2; + int nump; CLAW_DBF_TEXT_(5, trace, "pages%d", num_of_pages); if (num_of_pages == 1) {return 0; } /* magnitude of 0 = 1 page */ @@ -1187,37 +1187,31 @@ ccw_check_unit_check(struct chbk * p_ch, unsigned char sense ) dev_warn(dev, "The communication peer of %s disconnected\n", ndev->name); - if (sense & 0x40) { - if (sense & 0x01) { + if (sense & 0x40) { + if (sense & 0x01) { dev_warn(dev, "The remote channel adapter for" " %s has been reset\n", ndev->name); - } - } - else if (sense & 0x20) { - if (sense & 0x04) { + } + } else if (sense & 0x20) { + if (sense & 0x04) { dev_warn(dev, "A data streaming timeout occurred" " for %s\n", ndev->name); - } - else { - dev_warn(dev, "A data transfer parity error occurred" - " for %s\n", - ndev->name); - } - } - else if (sense & 0x10) { - if (sense & 0x20) { + } else if (sense & 0x10) { dev_warn(dev, "The remote channel adapter for %s" " is faulty\n", ndev->name); - } - else { - dev_warn(dev, "A read data parity error occurred" + } else { + dev_warn(dev, "A data transfer parity error occurred" " for %s\n", ndev->name); - } - } + } + } else if (sense & 0x10) { + dev_warn(dev, "A read data parity error occurred" + " for %s\n", + ndev->name); + } } /* end of ccw_check_unit_check */ @@ -1254,7 +1248,7 @@ find_link(struct net_device *dev, char *host_name, char *ws_name ) break; } - return 0; + return rc; } /* end of find_link */ /*-------------------------------------------------------------------* @@ -1366,7 +1360,10 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid) privptr->p_write_free_chain=p_this_ccw->next; p_this_ccw->next=NULL; --privptr->write_free_count; /* -1 */ - bytesInThisBuffer=len_of_data; + if (len_of_data >= privptr->p_env->write_size) + bytesInThisBuffer = privptr->p_env->write_size; + else + bytesInThisBuffer = len_of_data; memcpy( p_this_ccw->p_buffer,pDataAddress, bytesInThisBuffer); len_of_data-=bytesInThisBuffer; pDataAddress+=(unsigned long)bytesInThisBuffer; @@ -2517,7 +2514,6 @@ unpack_read(struct net_device *dev ) p_dev = &privptr->channel[READ].cdev->dev; p_env = privptr->p_env; p_this_ccw=privptr->p_read_active_first; - i=0; while (p_this_ccw!=NULL && p_this_ccw->header.flag!=CLAW_PENDING) { pack_off = 0; p = 0; -- GitLab From ecbf61e7357d5c7047c813edd6983902d158688c Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 23 Mar 2009 10:37:57 +0000 Subject: [PATCH 4286/4982] [ARM] cumana: Fix a long standing bogon Should be using strncmp as the data from user space may be unterminated (Bug #8004) Signed-off-by: Alan Cox --- drivers/scsi/arm/cumana_2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c index 68a64123af8..ed502b7412d 100644 --- a/drivers/scsi/arm/cumana_2.c +++ b/drivers/scsi/arm/cumana_2.c @@ -318,7 +318,7 @@ cumanascsi_2_set_proc_info(struct Scsi_Host *host, char *buffer, int length) { int ret = length; - if (length >= 11 && strcmp(buffer, "CUMANASCSI2") == 0) { + if (length >= 11 && strncmp(buffer, "CUMANASCSI2", 11) == 0) { buffer += 11; length -= 11; -- GitLab From b23c7a427e4b3764ad686a46de89ab652811c50a Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 23 Mar 2009 10:44:07 +0000 Subject: [PATCH 4287/4982] [ARM] fix leak in iop13xx/pci MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Another leak found by Daniel Marjamäki Signed-off-by: Alan Cox Signed-off-by: Russell King --- arch/arm/mach-iop13xx/pci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-iop13xx/pci.c b/arch/arm/mach-iop13xx/pci.c index 673b0db2203..4873f26a42e 100644 --- a/arch/arm/mach-iop13xx/pci.c +++ b/arch/arm/mach-iop13xx/pci.c @@ -1026,8 +1026,10 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys) which_atu = 0; } - if (!which_atu) + if (!which_atu) { + kfree(res); return 0; + } switch(which_atu) { case IOP13XX_INIT_ATU_ATUX: @@ -1074,6 +1076,7 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys) sys->map_irq = iop13xx_pcie_map_irq; break; default: + kfree(res); return 0; } -- GitLab From 803c78e4da28d7d7cb0642caf643b9289ae7838a Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 23 Mar 2009 10:43:54 +0000 Subject: [PATCH 4288/4982] [ARM] twl4030 - leak fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trivial error path leak fix. Problem found by Daniel Marjamäki using cppcheck Signed-off-by: Alan Cox Acked-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/mmc-twl4030.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c index 437f52073f6..e1dadf7344a 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.c +++ b/arch/arm/mach-omap2/mmc-twl4030.c @@ -397,6 +397,7 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) break; default: pr_err("MMC%d configuration not supported!\n", c->mmc); + kfree(mmc); continue; } hsmmc_data[c->mmc - 1] = mmc; -- GitLab From 1662e3a7f076e51e3073faf9ce77157b529c475b Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 18 Mar 2009 14:28:53 -0400 Subject: [PATCH 4289/4982] USB: add quirk to avoid config and interface strings Apparently the Configuration and Interface strings aren't used as often as the Vendor, Product, and Serial strings. In at least one device (a Saitek Cyborg Gold 3D joystick), attempts to read the Configuration string cause the device to stop responding to Control requests. This patch (as1226) adds a quirks flag, telling the kernel not to read a device's Configuration or Interface strings, together with a new quirk for the offending joystick. Reported-by: Melchior FRANZ Tested-by: Melchior FRANZ Signed-off-by: Alan Stern Cc: stable [2.6.28 and 2.6.29, nothing earlier] Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 3 ++- drivers/usb/core/quirks.c | 4 ++++ drivers/usb/core/sysfs.c | 4 +++- include/linux/usb/quirks.h | 3 +++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 49e7f56e0d7..3922fa915ed 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1719,7 +1719,8 @@ free_interfaces: } kfree(new_interfaces); - if (cp->string == NULL) + if (cp->string == NULL && + !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS)) cp->string = usb_cache_string(dev, cp->desc.iConfiguration); /* Now that all the interfaces are set up, register them diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index c070b34b669..ab93918d920 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -54,6 +54,10 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x0638, 0x0a13), .driver_info = USB_QUIRK_STRING_FETCH_255 }, + /* Saitek Cyborg Gold Joystick */ + { USB_DEVICE(0x06a3, 0x0006), .driver_info = + USB_QUIRK_CONFIG_INTF_STRINGS }, + /* M-Systems Flash Disk Pioneers */ { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 4cc2456ef3b..c6678919792 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "usb.h" /* Active configuration fields */ @@ -813,7 +814,8 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf) if (intf->sysfs_files_created || intf->unregistering) return 0; - if (alt->string == NULL) + if (alt->string == NULL && + !(udev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS)) alt->string = usb_cache_string(udev, alt->desc.iInterface); if (alt->string) retval = device_create_file(&intf->dev, &dev_attr_interface); diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h index 7f6c603db65..2526f3bbd27 100644 --- a/include/linux/usb/quirks.h +++ b/include/linux/usb/quirks.h @@ -16,4 +16,7 @@ /* device can't handle Set-Interface requests */ #define USB_QUIRK_NO_SET_INTF 0x00000004 +/* device can't handle its Configuration or Interface strings */ +#define USB_QUIRK_CONFIG_INTF_STRINGS 0x00000008 + #endif /* __LINUX_USB_QUIRKS_H */ -- GitLab From 090b90118207e786d2990310d063fda5d52cce6e Mon Sep 17 00:00:00 2001 From: David Brownell Date: Fri, 20 Mar 2009 01:08:20 -0700 Subject: [PATCH 4290/4982] USB: gadget: fix rndis regression Restore some code that was wrongly dropped from the RNDIS driver, and caused interop problems observed with OpenMoko. The issue is with hardware which needs help conforming to part of the USB 2.0 spec (section 8.5.3.2); some can automagically send a ZLP in response to an unexpected IN, but not all chips will do that. We don't need to check the packet length ourselves the way earlier code did, since the UDC must already check it. But we do need to tell the UDC when it must force a short packet termination of the data stage. (Based on a patch from Aric D. Blumer ) Signed-off-by: David Brownell Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_rndis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 3a8bb53fc47..fd7b356f902 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -437,7 +437,7 @@ invalid: DBG(cdev, "rndis req%02x.%02x v%04x i%04x l%d\n", ctrl->bRequestType, ctrl->bRequest, w_value, w_index, w_length); - req->zero = 0; + req->zero = (value < w_length); req->length = value; value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); if (value < 0) -- GitLab From 5c16034d73da2c1b663aa25dedadbc533b3d811c Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 23 Mar 2009 09:51:02 -0400 Subject: [PATCH 4291/4982] USB: usb-storage: increase max_sectors for tape drives This patch (as1203) increases the max_sector limit for USB tape drives. By default usb-storage sets max_sectors to 240 (i.e., 120 KB) for all devices. But tape drives need a higher limit, since tapes can and do have very large block sizes. Without the ability to transfer an entire large block in a single command, such tapes can't be used. This fixes Bugzilla #12207. Signed-off-by: Alan Stern Reported-and-tested-by: Phil Mitchell Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/scsiglue.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 727c506417c..ed710bcdaab 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -135,6 +135,12 @@ static int slave_configure(struct scsi_device *sdev) if (sdev->request_queue->max_sectors > max_sectors) blk_queue_max_sectors(sdev->request_queue, max_sectors); + } else if (sdev->type == TYPE_TAPE) { + /* Tapes need much higher max_sector limits, so just + * raise it to the maximum possible (4 GB / 512) and + * let the queue segment size sort out the real limit. + */ + blk_queue_max_sectors(sdev->request_queue, 0x7FFFFF); } /* Some USB host controllers can't do DMA; they have to use PIO. -- GitLab From dd44be6b17ac52238aa6c7f46b906d9fb76e7052 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Tue, 6 Jan 2009 17:20:42 -0700 Subject: [PATCH 4292/4982] usblp: continuously poll for status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The usblp in 2.6.18 polled for status regardless if we actually needed it. At some point I dropped it, to save the batteries if nothing else. As it turned out, printers exist (e.g. Canon BJC-3000) that need prodding this way or else they stop. This patch restores the old behaviour. If you want to save battery, don't leave jobs in the print queue. I tested this on my printers by printing and examining usbmon traces to make sure status is being requested and printers continue to print. Tuomas Jäntti verified the fix on BJC-3000. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usblp.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 3f3ee135193..d2747a49b97 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -880,16 +880,19 @@ static int usblp_wwait(struct usblp *usblp, int nonblock) if (rc <= 0) break; - if (usblp->flags & LP_ABORT) { - if (schedule_timeout(msecs_to_jiffies(5000)) == 0) { + if (schedule_timeout(msecs_to_jiffies(1500)) == 0) { + if (usblp->flags & LP_ABORT) { err = usblp_check_status(usblp, err); if (err == 1) { /* Paper out */ rc = -ENOSPC; break; } + } else { + /* Prod the printer, Gentoo#251237. */ + mutex_lock(&usblp->mut); + usblp_read_status(usblp, usblp->statusbuf); + mutex_unlock(&usblp->mut); } - } else { - schedule(); } } set_current_state(TASK_RUNNING); -- GitLab From c2344f13b59e007d782a3e591ebc551bc583a8b7 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 24 Jan 2009 23:54:31 -0800 Subject: [PATCH 4293/4982] USB: gpio_vbus: add delayed vbus_session calls Call usb_gadget_vbus_connect() and ...disconnect() from a workqueue rather than from an irq handler, allowing msleep() calls in vbus_session. Update kerneldoc to match. [ dbrownell@users.sourceforge.net: more kerneldoc updates ] Signed-off-by: Robert Jarzmik Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/otg/gpio_vbus.c | 42 +++++++++++++++++++++++++++---------- include/linux/usb/gadget.h | 6 ++++-- include/linux/usb/otg.h | 4 ++++ 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/otg/gpio_vbus.c index 63a6036f04b..1c26c94513e 100644 --- a/drivers/usb/otg/gpio_vbus.c +++ b/drivers/usb/otg/gpio_vbus.c @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -34,6 +35,7 @@ struct gpio_vbus_data { struct regulator *vbus_draw; int vbus_draw_enabled; unsigned mA; + struct work_struct work; }; @@ -76,24 +78,26 @@ static void set_vbus_draw(struct gpio_vbus_data *gpio_vbus, unsigned mA) gpio_vbus->mA = mA; } -/* VBUS change IRQ handler */ -static irqreturn_t gpio_vbus_irq(int irq, void *data) +static int is_vbus_powered(struct gpio_vbus_mach_info *pdata) { - struct platform_device *pdev = data; - struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data; - struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev); - int gpio, vbus; + int vbus; vbus = gpio_get_value(pdata->gpio_vbus); if (pdata->gpio_vbus_inverted) vbus = !vbus; - dev_dbg(&pdev->dev, "VBUS %s (gadget: %s)\n", - vbus ? "supplied" : "inactive", - gpio_vbus->otg.gadget ? gpio_vbus->otg.gadget->name : "none"); + return vbus; +} + +static void gpio_vbus_work(struct work_struct *work) +{ + struct gpio_vbus_data *gpio_vbus = + container_of(work, struct gpio_vbus_data, work); + struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data; + int gpio; if (!gpio_vbus->otg.gadget) - return IRQ_HANDLED; + return; /* Peripheral controllers which manage the pullup themselves won't have * gpio_pullup configured here. If it's configured here, we'll do what @@ -101,7 +105,7 @@ static irqreturn_t gpio_vbus_irq(int irq, void *data) * that may complicate usb_gadget_{,dis}connect() support. */ gpio = pdata->gpio_pullup; - if (vbus) { + if (is_vbus_powered(pdata)) { gpio_vbus->otg.state = OTG_STATE_B_PERIPHERAL; usb_gadget_vbus_connect(gpio_vbus->otg.gadget); @@ -121,6 +125,21 @@ static irqreturn_t gpio_vbus_irq(int irq, void *data) usb_gadget_vbus_disconnect(gpio_vbus->otg.gadget); gpio_vbus->otg.state = OTG_STATE_B_IDLE; } +} + +/* VBUS change IRQ handler */ +static irqreturn_t gpio_vbus_irq(int irq, void *data) +{ + struct platform_device *pdev = data; + struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data; + struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev); + + dev_dbg(&pdev->dev, "VBUS %s (gadget: %s)\n", + is_vbus_powered(pdata) ? "supplied" : "inactive", + gpio_vbus->otg.gadget ? gpio_vbus->otg.gadget->name : "none"); + + if (gpio_vbus->otg.gadget) + schedule_work(&gpio_vbus->work); return IRQ_HANDLED; } @@ -257,6 +276,7 @@ static int __init gpio_vbus_probe(struct platform_device *pdev) irq, err); goto err_irq; } + INIT_WORK(&gpio_vbus->work, gpio_vbus_work); /* only active when a gadget is registered */ err = otg_set_transceiver(&gpio_vbus->otg); diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 0460a746480..bbf45d500b6 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -598,6 +598,7 @@ static inline int usb_gadget_clear_selfpowered(struct usb_gadget *gadget) /** * usb_gadget_vbus_connect - Notify controller that VBUS is powered * @gadget:The device which now has VBUS power. + * Context: can sleep * * This call is used by a driver for an external transceiver (or GPIO) * that detects a VBUS power session starting. Common responses include @@ -636,6 +637,7 @@ static inline int usb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA) /** * usb_gadget_vbus_disconnect - notify controller about VBUS session end * @gadget:the device whose VBUS supply is being described + * Context: can sleep * * This call is used by a driver for an external transceiver (or GPIO) * that detects a VBUS power session ending. Common responses include @@ -792,19 +794,20 @@ struct usb_gadget_driver { /** * usb_gadget_register_driver - register a gadget driver * @driver:the driver being registered + * Context: can sleep * * Call this in your gadget driver's module initialization function, * to tell the underlying usb controller driver about your driver. * The driver's bind() function will be called to bind it to a * gadget before this registration call returns. It's expected that * the bind() functions will be in init sections. - * This function must be called in a context that can sleep. */ int usb_gadget_register_driver(struct usb_gadget_driver *driver); /** * usb_gadget_unregister_driver - unregister a gadget driver * @driver:the driver being unregistered + * Context: can sleep * * Call this in your gadget driver's module cleanup function, * to tell the underlying usb controller that your driver is @@ -813,7 +816,6 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver); * to unbind() and clean up any device state, before this procedure * finally returns. It's expected that the unbind() functions * will in in exit sections, so may not be linked in some kernels. - * This function must be called in a context that can sleep. */ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver); diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h index 94df4fe6c6c..60a52576fd5 100644 --- a/include/linux/usb/otg.h +++ b/include/linux/usb/otg.h @@ -86,6 +86,7 @@ extern int otg_set_transceiver(struct otg_transceiver *); extern struct otg_transceiver *otg_get_transceiver(void); extern void otg_put_transceiver(struct otg_transceiver *); +/* Context: can sleep */ static inline int otg_start_hnp(struct otg_transceiver *otg) { @@ -102,6 +103,8 @@ otg_set_host(struct otg_transceiver *otg, struct usb_bus *host) /* for usb peripheral controller drivers */ + +/* Context: can sleep */ static inline int otg_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *periph) { @@ -114,6 +117,7 @@ otg_set_power(struct otg_transceiver *otg, unsigned mA) return otg->set_power(otg, mA); } +/* Context: can sleep */ static inline int otg_set_suspend(struct otg_transceiver *otg, int suspend) { -- GitLab From eb50702539f9be3765127d927d3e9ccfeb65f26e Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 24 Jan 2009 23:55:34 -0800 Subject: [PATCH 4294/4982] USB: pxa27x_udc: factor pullup code to prepare otg transceiver Prepare pxa27x_udc to handle usb D+ pullup properly : it should connect the pullup resistor and disconnect it only if no external transceiver is handling it. [ dbrownell@users.sourceforge.net: kerneldoc and gpio fixes ] Signed-off-by: Robert Jarzmik Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/pxa27x_udc.c | 140 ++++++++++++++++++++++++++++++-- drivers/usb/gadget/pxa27x_udc.h | 6 ++ 2 files changed, 138 insertions(+), 8 deletions(-) diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 990f40f988d..f8145590944 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -1471,6 +1472,32 @@ static struct usb_ep_ops pxa_ep_ops = { .fifo_flush = pxa_ep_fifo_flush, }; +/** + * dplus_pullup - Connect or disconnect pullup resistor to D+ pin + * @udc: udc device + * @on: 0 if disconnect pullup resistor, 1 otherwise + * Context: any + * + * Handle D+ pullup resistor, make the device visible to the usb bus, and + * declare it as a full speed usb device + */ +static void dplus_pullup(struct pxa_udc *udc, int on) +{ + if (on) { + if (gpio_is_valid(udc->mach->gpio_pullup)) + gpio_set_value(udc->mach->gpio_pullup, + !udc->mach->gpio_pullup_inverted); + if (udc->mach->udc_command) + udc->mach->udc_command(PXA2XX_UDC_CMD_CONNECT); + } else { + if (gpio_is_valid(udc->mach->gpio_pullup)) + gpio_set_value(udc->mach->gpio_pullup, + udc->mach->gpio_pullup_inverted); + if (udc->mach->udc_command) + udc->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); + } + udc->pullup_on = on; +} /** * pxa_udc_get_frame - Returns usb frame number @@ -1500,21 +1527,91 @@ static int pxa_udc_wakeup(struct usb_gadget *_gadget) return 0; } +static void udc_enable(struct pxa_udc *udc); +static void udc_disable(struct pxa_udc *udc); + +/** + * should_enable_udc - Tells if UDC should be enabled + * @udc: udc device + * Context: any + * + * The UDC should be enabled if : + * - the pullup resistor is connected + * - and a gadget driver is bound + * + * Returns 1 if UDC should be enabled, 0 otherwise + */ +static int should_enable_udc(struct pxa_udc *udc) +{ + int put_on; + + put_on = ((udc->pullup_on) && (udc->driver)); + return put_on; +} + +/** + * should_disable_udc - Tells if UDC should be disabled + * @udc: udc device + * Context: any + * + * The UDC should be disabled if : + * - the pullup resistor is not connected + * - or no gadget driver is bound + * + * Returns 1 if UDC should be disabled + */ +static int should_disable_udc(struct pxa_udc *udc) +{ + int put_off; + + put_off = ((!udc->pullup_on) || (!udc->driver)); + return put_off; +} + +/** + * pxa_udc_pullup - Offer manual D+ pullup control + * @_gadget: usb gadget using the control + * @is_active: 0 if disconnect, else connect D+ pullup resistor + * Context: !in_interrupt() + * + * Returns 0 if OK, -EOPNOTSUPP if udc driver doesn't handle D+ pullup + */ +static int pxa_udc_pullup(struct usb_gadget *_gadget, int is_active) +{ + struct pxa_udc *udc = to_gadget_udc(_gadget); + + if (!gpio_is_valid(udc->mach->gpio_pullup) && !udc->mach->udc_command) + return -EOPNOTSUPP; + + dplus_pullup(udc, is_active); + + if (should_enable_udc(udc)) + udc_enable(udc); + if (should_disable_udc(udc)) + udc_disable(udc); + return 0; +} + static const struct usb_gadget_ops pxa_udc_ops = { .get_frame = pxa_udc_get_frame, .wakeup = pxa_udc_wakeup, + .pullup = pxa_udc_pullup, /* current versions must always be self-powered */ }; /** * udc_disable - disable udc device controller * @udc: udc device + * Context: any * * Disables the udc device : disables clocks, udc interrupts, control endpoint * interrupts. */ static void udc_disable(struct pxa_udc *udc) { + if (!udc->enabled) + return; + udc_writel(udc, UDCICR0, 0); udc_writel(udc, UDCICR1, 0); @@ -1523,8 +1620,8 @@ static void udc_disable(struct pxa_udc *udc) ep0_idle(udc); udc->gadget.speed = USB_SPEED_UNKNOWN; - if (udc->mach->udc_command) - udc->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); + + udc->enabled = 0; } /** @@ -1570,6 +1667,9 @@ static __init void udc_init_data(struct pxa_udc *dev) */ static void udc_enable(struct pxa_udc *udc) { + if (udc->enabled) + return; + udc_writel(udc, UDCICR0, 0); udc_writel(udc, UDCICR1, 0); udc_clear_mask_UDCCR(udc, UDCCR_UDE); @@ -1598,9 +1698,7 @@ static void udc_enable(struct pxa_udc *udc) /* enable ep0 irqs */ pio_irq_enable(&udc->pxa_ep[0]); - dev_info(udc->dev, "UDC connecting\n"); - if (udc->mach->udc_command) - udc->mach->udc_command(PXA2XX_UDC_CMD_CONNECT); + udc->enabled = 1; } /** @@ -1612,6 +1710,9 @@ static void udc_enable(struct pxa_udc *udc) * usb traffic follows until a disconnect is reported. Then a host may connect * again, or the driver might get unbound. * + * Note that the udc is not automatically enabled. Check function + * should_enable_udc(). + * * Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise */ int usb_gadget_register_driver(struct usb_gadget_driver *driver) @@ -1630,6 +1731,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) /* first hook up the driver ... */ udc->driver = driver; udc->gadget.dev.driver = &driver->driver; + dplus_pullup(udc, 1); retval = device_add(&udc->gadget.dev); if (retval) { @@ -1645,7 +1747,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) dev_dbg(udc->dev, "registered gadget driver '%s'\n", driver->driver.name); - udc_enable(udc); + if (should_enable_udc(udc)) + udc_enable(udc); return 0; bind_fail: @@ -1699,6 +1802,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) stop_activity(udc, driver); udc_disable(udc); + dplus_pullup(udc, 0); driver->unbind(&udc->gadget); udc->driver = NULL; @@ -2212,7 +2316,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev) { struct resource *regs; struct pxa_udc *udc = &memory; - int retval; + int retval = 0, gpio; regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!regs) @@ -2224,6 +2328,19 @@ static int __init pxa_udc_probe(struct platform_device *pdev) udc->dev = &pdev->dev; udc->mach = pdev->dev.platform_data; + gpio = udc->mach->gpio_pullup; + if (gpio_is_valid(gpio)) { + retval = gpio_request(gpio, "USB D+ pullup"); + if (retval == 0) + gpio_direction_output(gpio, + udc->mach->gpio_pullup_inverted); + } + if (retval) { + dev_err(&pdev->dev, "Couldn't request gpio %d : %d\n", + gpio, retval); + return retval; + } + udc->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(udc->clk)) { retval = PTR_ERR(udc->clk); @@ -2273,10 +2390,13 @@ err_clk: static int __exit pxa_udc_remove(struct platform_device *_dev) { struct pxa_udc *udc = platform_get_drvdata(_dev); + int gpio = udc->mach->gpio_pullup; usb_gadget_unregister_driver(udc->driver); free_irq(udc->irq, udc); pxa_cleanup_debugfs(udc); + if (gpio_is_valid(gpio)) + gpio_free(gpio); platform_set_drvdata(_dev, NULL); the_controller = NULL; @@ -2319,6 +2439,8 @@ static int pxa_udc_suspend(struct platform_device *_dev, pm_message_t state) } udc_disable(udc); + udc->pullup_resume = udc->pullup_on; + dplus_pullup(udc, 0); return 0; } @@ -2346,7 +2468,9 @@ static int pxa_udc_resume(struct platform_device *_dev) ep->udccsr_value, ep->udccr_value); } - udc_enable(udc); + dplus_pullup(udc, udc->pullup_resume); + if (should_enable_udc(udc)) + udc_enable(udc); /* * We do not handle OTG yet. * diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h index 1d1b7936ee1..6f5234dff8a 100644 --- a/drivers/usb/gadget/pxa27x_udc.h +++ b/drivers/usb/gadget/pxa27x_udc.h @@ -425,6 +425,9 @@ struct udc_stats { * @stats: statistics on udc usage * @udc_usb_ep: array of usb endpoints offered by the gadget * @pxa_ep: array of pxa available endpoints + * @enabled: UDC was enabled by a previous udc_enable() + * @pullup_on: if pullup resistor connected to D+ pin + * @pullup_resume: if pullup resistor should be connected to D+ pin on resume * @config: UDC active configuration * @last_interface: UDC interface of the last SET_INTERFACE host request * @last_alternate: UDC altsetting of the last SET_INTERFACE host request @@ -450,6 +453,9 @@ struct pxa_udc { struct udc_usb_ep udc_usb_ep[NR_USB_ENDPOINTS]; struct pxa_ep pxa_ep[NR_PXA_ENDPOINTS]; + unsigned enabled:1; + unsigned pullup_on:1; + unsigned pullup_resume:1; unsigned config:2; unsigned last_interface:3; unsigned last_alternate:3; -- GitLab From b799a7eb68082af620b7e37b6f41c98802e831f6 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 24 Jan 2009 23:56:42 -0800 Subject: [PATCH 4295/4982] USB: pxa27x_udc: add vbus session handling On vbus_session() call, optionally activate D+ pullup resistor and enable the udc, or deactivate D+ pullup resistor and disable the udc. It is intentional to not handle any VBus sense related irq. An external transceiver driver (like gpio_vbus) should catch VBus sense signal, and call usb_gadget_vbus_connect() or usb_gadget_vbus_disconnect(). Signed-off-by: Robert Jarzmik Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/pxa27x_udc.c | 33 +++++++++++++++++++++++++++++++++ drivers/usb/gadget/pxa27x_udc.h | 1 + 2 files changed, 34 insertions(+) diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index f8145590944..0c9307118b5 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -1536,8 +1536,10 @@ static void udc_disable(struct pxa_udc *udc); * Context: any * * The UDC should be enabled if : + * - the pullup resistor is connected * - and a gadget driver is bound + * - and vbus is sensed (or no vbus sense is available) * * Returns 1 if UDC should be enabled, 0 otherwise */ @@ -1546,6 +1548,7 @@ static int should_enable_udc(struct pxa_udc *udc) int put_on; put_on = ((udc->pullup_on) && (udc->driver)); + put_on &= ((udc->vbus_sensed) || (!udc->transceiver)); return put_on; } @@ -1557,6 +1560,7 @@ static int should_enable_udc(struct pxa_udc *udc) * The UDC should be disabled if : * - the pullup resistor is not connected * - or no gadget driver is bound + * - or no vbus is sensed (when vbus sesing is available) * * Returns 1 if UDC should be disabled */ @@ -1565,6 +1569,7 @@ static int should_disable_udc(struct pxa_udc *udc) int put_off; put_off = ((!udc->pullup_on) || (!udc->driver)); + put_off |= ((!udc->vbus_sensed) && (udc->transceiver)); return put_off; } @@ -1592,10 +1597,37 @@ static int pxa_udc_pullup(struct usb_gadget *_gadget, int is_active) return 0; } +static void udc_enable(struct pxa_udc *udc); +static void udc_disable(struct pxa_udc *udc); + +/** + * pxa_udc_vbus_session - Called by external transceiver to enable/disable udc + * @_gadget: usb gadget + * @is_active: 0 if should disable the udc, 1 if should enable + * + * Enables the udc, and optionnaly activates D+ pullup resistor. Or disables the + * udc, and deactivates D+ pullup resistor. + * + * Returns 0 + */ +static int pxa_udc_vbus_session(struct usb_gadget *_gadget, int is_active) +{ + struct pxa_udc *udc = to_gadget_udc(_gadget); + + udc->vbus_sensed = is_active; + if (should_enable_udc(udc)) + udc_enable(udc); + if (should_disable_udc(udc)) + udc_disable(udc); + + return 0; +} + static const struct usb_gadget_ops pxa_udc_ops = { .get_frame = pxa_udc_get_frame, .wakeup = pxa_udc_wakeup, .pullup = pxa_udc_pullup, + .vbus_session = pxa_udc_vbus_session, /* current versions must always be self-powered */ }; @@ -2357,6 +2389,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev) device_initialize(&udc->gadget.dev); udc->gadget.dev.parent = &pdev->dev; udc->gadget.dev.dma_mask = NULL; + udc->vbus_sensed = 0; the_controller = udc; platform_set_drvdata(pdev, udc); diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h index 6f5234dff8a..64741e19920 100644 --- a/drivers/usb/gadget/pxa27x_udc.h +++ b/drivers/usb/gadget/pxa27x_udc.h @@ -456,6 +456,7 @@ struct pxa_udc { unsigned enabled:1; unsigned pullup_on:1; unsigned pullup_resume:1; + unsigned vbus_sensed:1; unsigned config:2; unsigned last_interface:3; unsigned last_alternate:3; -- GitLab From 7fec3c25b773883bd50c4078bcccdd23d3dadeac Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 24 Jan 2009 23:57:30 -0800 Subject: [PATCH 4296/4982] USB: pxa27x_udc: add otg transceiver support When a transceiver driver is used, no automatic udc enable is done. The transceiver (OTG or not) should : - take care of VBus sensing - call usb_gadget_vbus_connect() - call usb_gadget_vbus_disconnect() The pullup should remain within this driver's management, either by gpio_pullup of udc_command() fields. Signed-off-by: Robert Jarzmik Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/Kconfig | 1 + drivers/usb/gadget/pxa27x_udc.c | 19 ++++++++++++++++++- drivers/usb/gadget/pxa27x_udc.h | 3 +++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index e55fef52a5d..770b3eaa918 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -254,6 +254,7 @@ config USB_PXA25X_SMALL config USB_GADGET_PXA27X boolean "PXA 27x" depends on ARCH_PXA && PXA27x + select USB_OTG_UTILS help Intel's PXA 27x series XScale ARM v5TE processors include an integrated full speed USB 1.1 device controller. diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 0c9307118b5..11510472ee0 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -1779,10 +1779,21 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) dev_dbg(udc->dev, "registered gadget driver '%s'\n", driver->driver.name); + if (udc->transceiver) { + retval = otg_set_peripheral(udc->transceiver, &udc->gadget); + if (retval) { + dev_err(udc->dev, "can't bind to transceiver\n"); + goto transceiver_fail; + } + } + if (should_enable_udc(udc)) udc_enable(udc); return 0; +transceiver_fail: + if (driver->unbind) + driver->unbind(&udc->gadget); bind_fail: device_del(&udc->gadget.dev); add_fail: @@ -1840,9 +1851,11 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) udc->driver = NULL; device_del(&udc->gadget.dev); - dev_info(udc->dev, "unregistered gadget driver '%s'\n", driver->driver.name); + + if (udc->transceiver) + return otg_set_peripheral(udc->transceiver, NULL); return 0; } EXPORT_SYMBOL(usb_gadget_unregister_driver); @@ -2359,6 +2372,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev) udc->dev = &pdev->dev; udc->mach = pdev->dev.platform_data; + udc->transceiver = otg_get_transceiver(); gpio = udc->mach->gpio_pullup; if (gpio_is_valid(gpio)) { @@ -2431,6 +2445,9 @@ static int __exit pxa_udc_remove(struct platform_device *_dev) if (gpio_is_valid(gpio)) gpio_free(gpio); + otg_put_transceiver(udc->transceiver); + + udc->transceiver = NULL; platform_set_drvdata(_dev, NULL); the_controller = NULL; clk_put(udc->clk); diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h index 64741e19920..db58125331d 100644 --- a/drivers/usb/gadget/pxa27x_udc.h +++ b/drivers/usb/gadget/pxa27x_udc.h @@ -26,6 +26,7 @@ #include #include #include +#include /* * Register definitions @@ -421,6 +422,7 @@ struct udc_stats { * @driver: bound gadget (zero, g_ether, g_file_storage, ...) * @dev: device * @mach: machine info, used to activate specific GPIO + * @transceiver: external transceiver to handle vbus sense and D+ pullup * @ep0state: control endpoint state machine state * @stats: statistics on udc usage * @udc_usb_ep: array of usb endpoints offered by the gadget @@ -446,6 +448,7 @@ struct pxa_udc { struct usb_gadget_driver *driver; struct device *dev; struct pxa2xx_udc_mach_info *mach; + struct otg_transceiver *transceiver; enum ep0_state ep0state; struct udc_stats stats; -- GitLab From ee069fb1185895e725ad942c7a529f947e25166d Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 24 Jan 2009 23:59:38 -0800 Subject: [PATCH 4297/4982] USB: pxa27x_udc: add vbus_draw callback Add the vbus_draw() callback to inform the transceiver, if it exists, how much current may be drawn. The decision is taken on gadget driver side using the configuration chosen by the host and its bMaxPower field. Some systems can use the host's VBUS supply to augment or recharge a battery. (There's also a default of 100 mA for unconfigured devices, or 8 mA if they're OTG devices.) Signed-off-by: Robert Jarzmik Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/pxa27x_udc.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 11510472ee0..e50419d0899 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -1623,12 +1623,34 @@ static int pxa_udc_vbus_session(struct usb_gadget *_gadget, int is_active) return 0; } +/** + * pxa_udc_vbus_draw - Called by gadget driver after SET_CONFIGURATION completed + * @_gadget: usb gadget + * @mA: current drawn + * + * Context: !in_interrupt() + * + * Called after a configuration was chosen by a USB host, to inform how much + * current can be drawn by the device from VBus line. + * + * Returns 0 or -EOPNOTSUPP if no transceiver is handling the udc + */ +static int pxa_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA) +{ + struct pxa_udc *udc; + + udc = to_gadget_udc(_gadget); + if (udc->transceiver) + return otg_set_power(udc->transceiver, mA); + return -EOPNOTSUPP; +} + static const struct usb_gadget_ops pxa_udc_ops = { .get_frame = pxa_udc_get_frame, .wakeup = pxa_udc_wakeup, .pullup = pxa_udc_pullup, .vbus_session = pxa_udc_vbus_session, - /* current versions must always be self-powered */ + .vbus_draw = pxa_udc_vbus_draw, }; /** -- GitLab From 4d6914b72966862f37de634299a80ca2a4b1829f Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 29 Dec 2008 22:48:19 +0100 Subject: [PATCH 4298/4982] USB: Move definitions from usb.h to usb/ch9.h The functions: usb_endpoint_dir_in(epd) usb_endpoint_dir_out(epd) usb_endpoint_is_bulk_in(epd) usb_endpoint_is_bulk_out(epd) usb_endpoint_is_int_in(epd) usb_endpoint_is_int_out(epd) usb_endpoint_is_isoc_in(epd) usb_endpoint_is_isoc_out(epd) usb_endpoint_num(epd) usb_endpoint_type(epd) usb_endpoint_xfer_bulk(epd) usb_endpoint_xfer_control(epd) usb_endpoint_xfer_int(epd) usb_endpoint_xfer_isoc(epd) are moved from include/linux/usb.h to include/linux/usb/ch9.h. include/linux/usb/ch9.h makes more sense for these functions because they only depend on constants that are defined in this file. Signed-off-by: Julia Lawall Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- include/linux/usb.h | 180 ---------------------------------------- include/linux/usb/ch9.h | 179 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+), 180 deletions(-) diff --git a/include/linux/usb.h b/include/linux/usb.h index 88079fd6023..0c05ff62119 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -643,186 +643,6 @@ static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size) /*-------------------------------------------------------------------------*/ -/** - * usb_endpoint_num - get the endpoint's number - * @epd: endpoint to be checked - * - * Returns @epd's number: 0 to 15. - */ -static inline int usb_endpoint_num(const struct usb_endpoint_descriptor *epd) -{ - return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; -} - -/** - * usb_endpoint_type - get the endpoint's transfer type - * @epd: endpoint to be checked - * - * Returns one of USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT} according - * to @epd's transfer type. - */ -static inline int usb_endpoint_type(const struct usb_endpoint_descriptor *epd) -{ - return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; -} - -/** - * usb_endpoint_dir_in - check if the endpoint has IN direction - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type IN, otherwise it returns false. - */ -static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN); -} - -/** - * usb_endpoint_dir_out - check if the endpoint has OUT direction - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type OUT, otherwise it returns false. - */ -static inline int usb_endpoint_dir_out( - const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT); -} - -/** - * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type bulk, otherwise it returns false. - */ -static inline int usb_endpoint_xfer_bulk( - const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_BULK); -} - -/** - * usb_endpoint_xfer_control - check if the endpoint has control transfer type - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type control, otherwise it returns false. - */ -static inline int usb_endpoint_xfer_control( - const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_CONTROL); -} - -/** - * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type interrupt, otherwise it returns - * false. - */ -static inline int usb_endpoint_xfer_int( - const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_INT); -} - -/** - * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type isochronous, otherwise it returns - * false. - */ -static inline int usb_endpoint_xfer_isoc( - const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_ISOC); -} - -/** - * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN - * @epd: endpoint to be checked - * - * Returns true if the endpoint has bulk transfer type and IN direction, - * otherwise it returns false. - */ -static inline int usb_endpoint_is_bulk_in( - const struct usb_endpoint_descriptor *epd) -{ - return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd)); -} - -/** - * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT - * @epd: endpoint to be checked - * - * Returns true if the endpoint has bulk transfer type and OUT direction, - * otherwise it returns false. - */ -static inline int usb_endpoint_is_bulk_out( - const struct usb_endpoint_descriptor *epd) -{ - return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd)); -} - -/** - * usb_endpoint_is_int_in - check if the endpoint is interrupt IN - * @epd: endpoint to be checked - * - * Returns true if the endpoint has interrupt transfer type and IN direction, - * otherwise it returns false. - */ -static inline int usb_endpoint_is_int_in( - const struct usb_endpoint_descriptor *epd) -{ - return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd)); -} - -/** - * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT - * @epd: endpoint to be checked - * - * Returns true if the endpoint has interrupt transfer type and OUT direction, - * otherwise it returns false. - */ -static inline int usb_endpoint_is_int_out( - const struct usb_endpoint_descriptor *epd) -{ - return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd)); -} - -/** - * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN - * @epd: endpoint to be checked - * - * Returns true if the endpoint has isochronous transfer type and IN direction, - * otherwise it returns false. - */ -static inline int usb_endpoint_is_isoc_in( - const struct usb_endpoint_descriptor *epd) -{ - return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd)); -} - -/** - * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT - * @epd: endpoint to be checked - * - * Returns true if the endpoint has isochronous transfer type and OUT direction, - * otherwise it returns false. - */ -static inline int usb_endpoint_is_isoc_out( - const struct usb_endpoint_descriptor *epd) -{ - return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd)); -} - -/*-------------------------------------------------------------------------*/ - #define USB_DEVICE_ID_MATCH_DEVICE \ (USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT) #define USB_DEVICE_ID_MATCH_DEV_RANGE \ diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h index 9b42baed390..fa777db7f7e 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -353,6 +353,185 @@ struct usb_endpoint_descriptor { #define USB_ENDPOINT_XFER_INT 3 #define USB_ENDPOINT_MAX_ADJUSTABLE 0x80 +/*-------------------------------------------------------------------------*/ + +/** + * usb_endpoint_num - get the endpoint's number + * @epd: endpoint to be checked + * + * Returns @epd's number: 0 to 15. + */ +static inline int usb_endpoint_num(const struct usb_endpoint_descriptor *epd) +{ + return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; +} + +/** + * usb_endpoint_type - get the endpoint's transfer type + * @epd: endpoint to be checked + * + * Returns one of USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT} according + * to @epd's transfer type. + */ +static inline int usb_endpoint_type(const struct usb_endpoint_descriptor *epd) +{ + return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; +} + +/** + * usb_endpoint_dir_in - check if the endpoint has IN direction + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type IN, otherwise it returns false. + */ +static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN); +} + +/** + * usb_endpoint_dir_out - check if the endpoint has OUT direction + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type OUT, otherwise it returns false. + */ +static inline int usb_endpoint_dir_out( + const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT); +} + +/** + * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type bulk, otherwise it returns false. + */ +static inline int usb_endpoint_xfer_bulk( + const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_BULK); +} + +/** + * usb_endpoint_xfer_control - check if the endpoint has control transfer type + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type control, otherwise it returns false. + */ +static inline int usb_endpoint_xfer_control( + const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_CONTROL); +} + +/** + * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type interrupt, otherwise it returns + * false. + */ +static inline int usb_endpoint_xfer_int( + const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_INT); +} + +/** + * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type isochronous, otherwise it returns + * false. + */ +static inline int usb_endpoint_xfer_isoc( + const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_ISOC); +} + +/** + * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN + * @epd: endpoint to be checked + * + * Returns true if the endpoint has bulk transfer type and IN direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_bulk_in( + const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd)); +} + +/** + * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT + * @epd: endpoint to be checked + * + * Returns true if the endpoint has bulk transfer type and OUT direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_bulk_out( + const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd)); +} + +/** + * usb_endpoint_is_int_in - check if the endpoint is interrupt IN + * @epd: endpoint to be checked + * + * Returns true if the endpoint has interrupt transfer type and IN direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_int_in( + const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd)); +} + +/** + * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT + * @epd: endpoint to be checked + * + * Returns true if the endpoint has interrupt transfer type and OUT direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_int_out( + const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd)); +} + +/** + * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN + * @epd: endpoint to be checked + * + * Returns true if the endpoint has isochronous transfer type and IN direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_isoc_in( + const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd)); +} + +/** + * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT + * @epd: endpoint to be checked + * + * Returns true if the endpoint has isochronous transfer type and OUT direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_isoc_out( + const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd)); +} /*-------------------------------------------------------------------------*/ -- GitLab From db5e6df172309c382982790aafa8cd87dc0b6292 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 29 Dec 2008 11:19:10 +0100 Subject: [PATCH 4299/4982] USB: ub: use USB API functions rather than constants This set of patches introduces calls to the following set of functions: usb_endpoint_dir_in(epd) usb_endpoint_dir_out(epd) usb_endpoint_is_bulk_in(epd) usb_endpoint_is_bulk_out(epd) usb_endpoint_is_int_in(epd) usb_endpoint_is_int_out(epd) usb_endpoint_num(epd) usb_endpoint_type(epd) usb_endpoint_xfer_bulk(epd) usb_endpoint_xfer_control(epd) usb_endpoint_xfer_int(epd) usb_endpoint_xfer_isoc(epd) In some cases, introducing one of these functions is not possible, and it just replaces an explicit integer value by one of the following constants: USB_ENDPOINT_XFER_BULK USB_ENDPOINT_XFER_CONTROL USB_ENDPOINT_XFER_INT USB_ENDPOINT_XFER_ISOC An extract of the semantic patch that makes these changes is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r1@ struct usb_endpoint_descriptor *epd; @@ - ((epd->bmAttributes & \(USB_ENDPOINT_XFERTYPE_MASK\|3\)) == - \(USB_ENDPOINT_XFER_CONTROL\|0\)) + usb_endpoint_xfer_control(epd) @r5@ struct usb_endpoint_descriptor *epd; @@ - ((epd->bEndpointAddress & \(USB_ENDPOINT_DIR_MASK\|0x80\)) == - \(USB_DIR_IN\|0x80\)) + usb_endpoint_dir_in(epd) @inc@ @@ #include @depends on !inc && (r1||r5)@ @@ + #include #include // Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/block/ub.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 12fb816db7b..b36b84fbe39 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -2146,10 +2146,9 @@ static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev, ep = &altsetting->endpoint[i].desc; /* Is it a BULK endpoint? */ - if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_BULK) { + if (usb_endpoint_xfer_bulk(ep)) { /* BULK in or out? */ - if (ep->bEndpointAddress & USB_DIR_IN) { + if (usb_endpoint_dir_in(ep)) { if (ep_in == NULL) ep_in = ep; } else { @@ -2168,9 +2167,9 @@ static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev, sc->send_ctrl_pipe = usb_sndctrlpipe(dev, 0); sc->recv_ctrl_pipe = usb_rcvctrlpipe(dev, 0); sc->send_bulk_pipe = usb_sndbulkpipe(dev, - ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + usb_endpoint_num(ep_out)); sc->recv_bulk_pipe = usb_rcvbulkpipe(dev, - ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + usb_endpoint_num(ep_in)); return 0; } -- GitLab From 00185a60c37549531b9eee562d3eba19020875d5 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 21 Dec 2008 16:41:36 +0100 Subject: [PATCH 4300/4982] USB: Remove redundant test in pxa27x_udc and ftdi_sio priv is checked not to be NULL near the beginning of the function and not changed subsequently, making the test redundant. A simplified version of the semantic patch that makes this change is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r exists@ local idexpression x; expression E; position p1,p2; @@ if (x@p1 == NULL || ...) { ... when forall return ...; } ... when != \(x=E\|x--\|x++\|--x\|++x\|x-=E\|x+=E\|x|=E\|x&=E\|&x\) ( x@p2 == NULL | x@p2 != NULL ) // another path to the test that is not through p1? @s exists@ local idexpression r.x; position r.p1,r.p2; @@ ... when != x@p1 ( x@p2 == NULL | x@p2 != NULL ) @fix depends on !s@ position r.p1,r.p2; expression x,E; statement S1,S2; @@ ( - if ((x@p2 != NULL) || ...) S1 | - if ((x@p2 == NULL) && ...) S1 | - BUG_ON(x@p2 == NULL); ) // Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/pxa27x_udc.c | 2 +- drivers/usb/serial/ftdi_sio.c | 16 +++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index e50419d0899..91ba1e93947 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -279,7 +279,7 @@ static void pxa_init_debugfs(struct pxa_udc *udc) goto err_queues; eps = debugfs_create_file("epstate", 0400, root, udc, &eps_dbg_fops); - if (!queues) + if (!eps) goto err_eps; udc->debugfs_root = root; diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index ae84c326a54..d889216bcb3 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1938,15 +1938,13 @@ static void ftdi_process_read(struct work_struct *work) /* Compare new line status to the old one, signal if different/ N.B. packet may be processed more than once, but differences are only processed once. */ - if (priv != NULL) { - char new_status = data[packet_offset + 0] & - FTDI_STATUS_B0_MASK; - if (new_status != priv->prev_status) { - priv->diff_status |= - new_status ^ priv->prev_status; - wake_up_interruptible(&priv->delta_msr_wait); - priv->prev_status = new_status; - } + char new_status = data[packet_offset + 0] & + FTDI_STATUS_B0_MASK; + if (new_status != priv->prev_status) { + priv->diff_status |= + new_status ^ priv->prev_status; + wake_up_interruptible(&priv->delta_msr_wait); + priv->prev_status = new_status; } length = min(PKTSZ, urb->actual_length-packet_offset)-2; -- GitLab From 2e0fe709687470637a0709b930ccc9e993d2dad5 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 29 Dec 2008 11:22:14 +0100 Subject: [PATCH 4301/4982] USB: drivers: use USB API functions rather than constants This set of patches introduces calls to the following set of functions: usb_endpoint_dir_in(epd) usb_endpoint_dir_out(epd) usb_endpoint_is_bulk_in(epd) usb_endpoint_is_bulk_out(epd) usb_endpoint_is_int_in(epd) usb_endpoint_is_int_out(epd) usb_endpoint_num(epd) usb_endpoint_type(epd) usb_endpoint_xfer_bulk(epd) usb_endpoint_xfer_control(epd) usb_endpoint_xfer_int(epd) usb_endpoint_xfer_isoc(epd) In some cases, introducing one of these functions is not possible, and it just replaces an explicit integer value by one of the following constants: USB_ENDPOINT_XFER_BULK USB_ENDPOINT_XFER_CONTROL USB_ENDPOINT_XFER_INT USB_ENDPOINT_XFER_ISOC An extract of the semantic patch that makes these changes is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r1@ struct usb_endpoint_descriptor *epd; @@ - ((epd->bmAttributes & \(USB_ENDPOINT_XFERTYPE_MASK\|3\)) == - \(USB_ENDPOINT_XFER_CONTROL\|0\)) + usb_endpoint_xfer_control(epd) @r5@ struct usb_endpoint_descriptor *epd; @@ - ((epd->bEndpointAddress & \(USB_ENDPOINT_DIR_MASK\|0x80\)) == - \(USB_DIR_IN\|0x80\)) + usb_endpoint_dir_in(epd) @inc@ @@ #include @depends on !inc && (r1||r5)@ @@ + #include #include // Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devices.c | 2 +- drivers/usb/core/endpoint.c | 9 ++++----- drivers/usb/host/r8a66597-hcd.c | 15 +++++++-------- drivers/usb/serial/keyspan.c | 2 +- drivers/usb/storage/usb.c | 6 +++--- 5 files changed, 16 insertions(+), 18 deletions(-) diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 6ec38175a81..73c108d117b 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -187,7 +187,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end, } /* this isn't checking for illegal values */ - switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + switch (usb_endpoint_type(desc)) { case USB_ENDPOINT_XFER_CONTROL: type = "Ctrl"; if (speed == USB_SPEED_HIGH) /* uframes per NAK */ diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index e1710f260b4..40dee2ac013 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c @@ -66,7 +66,7 @@ static ssize_t show_ep_type(struct device *dev, struct device_attribute *attr, struct ep_device *ep = to_ep_device(dev); char *type = "unknown"; - switch (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + switch (usb_endpoint_type(ep->desc)) { case USB_ENDPOINT_XFER_CONTROL: type = "Control"; break; @@ -94,7 +94,7 @@ static ssize_t show_ep_interval(struct device *dev, in = (ep->desc->bEndpointAddress & USB_DIR_IN); - switch (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + switch (usb_endpoint_type(ep->desc)) { case USB_ENDPOINT_XFER_CONTROL: if (ep->udev->speed == USB_SPEED_HIGH) /* uframes per NAK */ interval = ep->desc->bInterval; @@ -131,10 +131,9 @@ static ssize_t show_ep_direction(struct device *dev, struct ep_device *ep = to_ep_device(dev); char *direction; - if ((ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_CONTROL) + if (usb_endpoint_xfer_control(ep->desc)) direction = "both"; - else if (ep->desc->bEndpointAddress & USB_DIR_IN) + else if (usb_endpoint_dir_in(ep->desc)) direction = "in"; else direction = "out"; diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 319041205b5..5e942d94aeb 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -660,9 +660,9 @@ static u16 get_empty_pipenum(struct r8a66597 *r8a66597, u16 array[R8A66597_MAX_NUM_PIPE], i = 0, min; memset(array, 0, sizeof(array)); - switch (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + switch (usb_endpoint_type(ep)) { case USB_ENDPOINT_XFER_BULK: - if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + if (usb_endpoint_dir_in(ep)) array[i++] = 4; else { array[i++] = 3; @@ -670,7 +670,7 @@ static u16 get_empty_pipenum(struct r8a66597 *r8a66597, } break; case USB_ENDPOINT_XFER_INT: - if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) { + if (usb_endpoint_dir_in(ep)) { array[i++] = 6; array[i++] = 7; array[i++] = 8; @@ -678,7 +678,7 @@ static u16 get_empty_pipenum(struct r8a66597 *r8a66597, array[i++] = 9; break; case USB_ENDPOINT_XFER_ISOC: - if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + if (usb_endpoint_dir_in(ep)) array[i++] = 2; else array[i++] = 1; @@ -928,10 +928,9 @@ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb, info.pipenum = get_empty_pipenum(r8a66597, ep); info.address = get_urb_to_r8a66597_addr(r8a66597, urb); - info.epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + info.epnum = usb_endpoint_num(ep); info.maxpacket = le16_to_cpu(ep->wMaxPacketSize); - info.type = get_r8a66597_type(ep->bmAttributes - & USB_ENDPOINT_XFERTYPE_MASK); + info.type = get_r8a66597_type(usb_endpoint_type(ep)); info.bufnum = get_bufnum(info.pipenum); info.buf_bsize = get_buf_bsize(info.pipenum); if (info.type == R8A66597_BULK) { @@ -941,7 +940,7 @@ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb, info.interval = get_interval(urb, ep->bInterval); info.timer_interval = get_timer_interval(urb, ep->bInterval); } - if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + if (usb_endpoint_dir_in(ep)) info.dir_in = 1; else info.dir_in = 0; diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 9878c0fb385..00daa8f7759 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -1507,7 +1507,7 @@ static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint, } else { dev_warn(&serial->interface->dev, "unsupported endpoint type %x\n", - ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); + usb_endpoint_type(ep_desc)); usb_free_urb(urb); return NULL; } diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 4becf495ca2..b01dade63cb 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -846,12 +846,12 @@ static int get_pipes(struct us_data *us) us->send_ctrl_pipe = usb_sndctrlpipe(us->pusb_dev, 0); us->recv_ctrl_pipe = usb_rcvctrlpipe(us->pusb_dev, 0); us->send_bulk_pipe = usb_sndbulkpipe(us->pusb_dev, - ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + usb_endpoint_num(ep_out)); us->recv_bulk_pipe = usb_rcvbulkpipe(us->pusb_dev, - ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + usb_endpoint_num(ep_in)); if (ep_int) { us->recv_intr_pipe = usb_rcvintpipe(us->pusb_dev, - ep_int->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + usb_endpoint_num(ep_int)); us->ep_bInterval = ep_int->bInterval; } return 0; -- GitLab From bcbbbfc169e837f0bf54dd4a6ef0a6494fb14925 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Sun, 11 Jan 2009 17:25:13 +0800 Subject: [PATCH 4302/4982] USB: gadget: remove duplicated #include Removed duplicated #include in drivers/usb/gadget/ci13xxx_udc.c Signed-off-by: Huang Weiyi Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/ci13xxx_udc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c index bebf911c7e5..0e310b9aa7a 100644 --- a/drivers/usb/gadget/ci13xxx_udc.c +++ b/drivers/usb/gadget/ci13xxx_udc.c @@ -56,7 +56,6 @@ #include #include #include -#include #include #include #include -- GitLab From 664d5df92e88b6ef091048a802b3750f4e989180 Mon Sep 17 00:00:00 2001 From: Werner Cornelius Date: Fri, 16 Jan 2009 21:02:41 +0100 Subject: [PATCH 4303/4982] USB: usb-serial ch341: support for DTR/RTS/CTS Fixup of Werner Cornelius patch to the ch341 USB-serial driver, which adds: - support all baudrates, not just a hard-coded set - support for controlling DTR, RTS and CTS Features still missing: - character length other than 8 bits - parity settings - break control I adapted his patch for the new usb_serial API introduced in 2.6.25-git8 by Alan Cox on 22 July 2008. Non-compliance to the new API was a reason for refusing a similar patch from Tollef Fog Heen. Usage example by Tollef Fog Heen : TEMPer USB thermometer Signed-off-by: Werner Cornelius Signed-off-by: Boris Hajduk Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ch341.c | 374 ++++++++++++++++++++++++++++++------- 1 file changed, 302 insertions(+), 72 deletions(-) diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index f61e3ca6430..d5ea679e169 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -1,5 +1,7 @@ /* * Copyright 2007, Frank A Kingswood + * Copyright 2007, Werner Cornelius + * Copyright 2009, Boris Hajduk * * ch341.c implements a serial port driver for the Winchiphead CH341. * @@ -21,9 +23,39 @@ #include #include -#define DEFAULT_BAUD_RATE 2400 +#define DEFAULT_BAUD_RATE 9600 #define DEFAULT_TIMEOUT 1000 +/* flags for IO-Bits */ +#define CH341_BIT_RTS (1 << 6) +#define CH341_BIT_DTR (1 << 5) + +/******************************/ +/* interrupt pipe definitions */ +/******************************/ +/* always 4 interrupt bytes */ +/* first irq byte normally 0x08 */ +/* second irq byte base 0x7d + below */ +/* third irq byte base 0x94 + below */ +/* fourth irq byte normally 0xee */ + +/* second interrupt byte */ +#define CH341_MULT_STAT 0x04 /* multiple status since last interrupt event */ + +/* status returned in third interrupt answer byte, inverted in data + from irq */ +#define CH341_BIT_CTS 0x01 +#define CH341_BIT_DSR 0x02 +#define CH341_BIT_RI 0x04 +#define CH341_BIT_DCD 0x08 +#define CH341_BITS_MODEM_STAT 0x0f /* all bits */ + +/*******************************/ +/* baudrate calculation factor */ +/*******************************/ +#define CH341_BAUDBASE_FACTOR 1532620800 +#define CH341_BAUDBASE_DIVMAX 3 + static int debug; static struct usb_device_id id_table [] = { @@ -34,9 +66,12 @@ static struct usb_device_id id_table [] = { MODULE_DEVICE_TABLE(usb, id_table); struct ch341_private { - unsigned baud_rate; - u8 dtr; - u8 rts; + spinlock_t lock; /* access lock */ + wait_queue_head_t delta_msr_wait; /* wait queue for modem status */ + unsigned baud_rate; /* set baud rate */ + u8 line_control; /* set line control value RTS/DTR */ + u8 line_status; /* active status of modem control inputs */ + u8 multi_status_change; /* status changed multiple since last call */ }; static int ch341_control_out(struct usb_device *dev, u8 request, @@ -72,37 +107,28 @@ static int ch341_set_baudrate(struct usb_device *dev, { short a, b; int r; + unsigned long factor; + short divisor; dbg("ch341_set_baudrate(%d)", priv->baud_rate); - switch (priv->baud_rate) { - case 2400: - a = 0xd901; - b = 0x0038; - break; - case 4800: - a = 0x6402; - b = 0x001f; - break; - case 9600: - a = 0xb202; - b = 0x0013; - break; - case 19200: - a = 0xd902; - b = 0x000d; - break; - case 38400: - a = 0x6403; - b = 0x000a; - break; - case 115200: - a = 0xcc03; - b = 0x0008; - break; - default: + + if (!priv->baud_rate) return -EINVAL; + factor = (CH341_BAUDBASE_FACTOR / priv->baud_rate); + divisor = CH341_BAUDBASE_DIVMAX; + + while ((factor > 0xfff0) && divisor) { + factor >>= 3; + divisor--; } + if (factor > 0xfff0) + return -EINVAL; + + factor = 0x10000 - factor; + a = (factor & 0xff00) | divisor; + b = factor & 0xff; + r = ch341_control_out(dev, 0x9a, 0x1312, a); if (!r) r = ch341_control_out(dev, 0x9a, 0x0f2c, b); @@ -110,19 +136,18 @@ static int ch341_set_baudrate(struct usb_device *dev, return r; } -static int ch341_set_handshake(struct usb_device *dev, - struct ch341_private *priv) +static int ch341_set_handshake(struct usb_device *dev, u8 control) { - dbg("ch341_set_handshake(%d,%d)", priv->dtr, priv->rts); - return ch341_control_out(dev, 0xa4, - ~((priv->dtr?1<<5:0)|(priv->rts?1<<6:0)), 0); + dbg("ch341_set_handshake(0x%02x)", control); + return ch341_control_out(dev, 0xa4, ~control, 0); } -static int ch341_get_status(struct usb_device *dev) +static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv) { char *buffer; int r; const unsigned size = 8; + unsigned long flags; dbg("ch341_get_status()"); @@ -134,10 +159,15 @@ static int ch341_get_status(struct usb_device *dev) if (r < 0) goto out; - /* Not having the datasheet for the CH341, we ignore the bytes returned - * from the device. Return error if the device did not respond in time. - */ - r = 0; + /* setup the private status if available */ + if (r == 2) { + r = 0; + spin_lock_irqsave(&priv->lock, flags); + priv->line_status = (~(*buffer)) & CH341_BITS_MODEM_STAT; + priv->multi_status_change = 0; + spin_unlock_irqrestore(&priv->lock, flags); + } else + r = -EPROTO; out: kfree(buffer); return r; @@ -180,7 +210,7 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv) goto out; /* expect 0xff 0xee */ - r = ch341_get_status(dev); + r = ch341_get_status(dev, priv); if (r < 0) goto out; @@ -192,12 +222,12 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv) if (r < 0) goto out; - r = ch341_set_handshake(dev, priv); + r = ch341_set_handshake(dev, priv->line_control); if (r < 0) goto out; /* expect 0x9f 0xee */ - r = ch341_get_status(dev); + r = ch341_get_status(dev, priv); out: kfree(buffer); return r; @@ -216,9 +246,10 @@ static int ch341_attach(struct usb_serial *serial) if (!priv) return -ENOMEM; + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->delta_msr_wait); priv->baud_rate = DEFAULT_BAUD_RATE; - priv->dtr = 1; - priv->rts = 1; + priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR; r = ch341_configure(serial->dev, priv); if (r < 0) @@ -231,6 +262,35 @@ error: kfree(priv); return r; } +static void ch341_close(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) +{ + struct ch341_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + unsigned int c_cflag; + + dbg("%s - port %d", __func__, port->number); + + /* shutdown our urbs */ + dbg("%s - shutting down urbs", __func__); + usb_kill_urb(port->write_urb); + usb_kill_urb(port->read_urb); + usb_kill_urb(port->interrupt_in_urb); + + if (tty) { + c_cflag = tty->termios->c_cflag; + if (c_cflag & HUPCL) { + /* drop DTR and RTS */ + spin_lock_irqsave(&priv->lock, flags); + priv->line_control = 0; + spin_unlock_irqrestore(&priv->lock, flags); + ch341_set_handshake(port->serial->dev, 0); + } + } + wake_up_interruptible(&priv->delta_msr_wait); +} + + /* open this device, set default parameters */ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp) @@ -242,14 +302,13 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port, dbg("ch341_open()"); priv->baud_rate = DEFAULT_BAUD_RATE; - priv->dtr = 1; - priv->rts = 1; + priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR; r = ch341_configure(serial->dev, priv); if (r) goto out; - r = ch341_set_handshake(serial->dev, priv); + r = ch341_set_handshake(serial->dev, priv->line_control); if (r) goto out; @@ -257,6 +316,16 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port, if (r) goto out; + dbg("%s - submitting interrupt urb", __func__); + port->interrupt_in_urb->dev = serial->dev; + r = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); + if (r) { + dev_err(&port->dev, "%s - failed submitting interrupt urb," + " error %d\n", __func__, r); + ch341_close(tty, port, NULL); + return -EPROTO; + } + r = usb_serial_generic_open(tty, port, filp); out: return r; @@ -270,38 +339,194 @@ static void ch341_set_termios(struct tty_struct *tty, { struct ch341_private *priv = usb_get_serial_port_data(port); unsigned baud_rate; + unsigned long flags; dbg("ch341_set_termios()"); + if (!tty || !tty->termios) + return; + baud_rate = tty_get_baud_rate(tty); - switch (baud_rate) { - case 2400: - case 4800: - case 9600: - case 19200: - case 38400: - case 115200: - priv->baud_rate = baud_rate; - break; - default: - dbg("Rate %d not supported, using %d", - baud_rate, DEFAULT_BAUD_RATE); - priv->baud_rate = DEFAULT_BAUD_RATE; + priv->baud_rate = baud_rate; + + if (baud_rate) { + spin_lock_irqsave(&priv->lock, flags); + priv->line_control |= (CH341_BIT_DTR | CH341_BIT_RTS); + spin_unlock_irqrestore(&priv->lock, flags); + ch341_set_baudrate(port->serial->dev, priv); + } else { + spin_lock_irqsave(&priv->lock, flags); + priv->line_control &= ~(CH341_BIT_DTR | CH341_BIT_RTS); + spin_unlock_irqrestore(&priv->lock, flags); } - ch341_set_baudrate(port->serial->dev, priv); + ch341_set_handshake(port->serial->dev, priv->line_control); /* Unimplemented: * (cflag & CSIZE) : data bits [5, 8] * (cflag & PARENB) : parity {NONE, EVEN, ODD} * (cflag & CSTOPB) : stop bits [1, 2] */ +} + +static int ch341_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + struct usb_serial_port *port = tty->driver_data; + struct ch341_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + u8 control; + + spin_lock_irqsave(&priv->lock, flags); + if (set & TIOCM_RTS) + priv->line_control |= CH341_BIT_RTS; + if (set & TIOCM_DTR) + priv->line_control |= CH341_BIT_DTR; + if (clear & TIOCM_RTS) + priv->line_control &= ~CH341_BIT_RTS; + if (clear & TIOCM_DTR) + priv->line_control &= ~CH341_BIT_DTR; + control = priv->line_control; + spin_unlock_irqrestore(&priv->lock, flags); + + return ch341_set_handshake(port->serial->dev, control); +} + +static void ch341_read_int_callback(struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *) urb->context; + unsigned char *data = urb->transfer_buffer; + unsigned int actual_length = urb->actual_length; + int status; + + dbg("%s (%d)", __func__, port->number); + + switch (urb->status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", __func__, + urb->status); + return; + default: + dbg("%s - nonzero urb status received: %d", __func__, + urb->status); + goto exit; + } + + usb_serial_debug_data(debug, &port->dev, __func__, + urb->actual_length, urb->transfer_buffer); + + if (actual_length >= 4) { + struct ch341_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + priv->line_status = (~(data[2])) & CH341_BITS_MODEM_STAT; + if ((data[1] & CH341_MULT_STAT)) + priv->multi_status_change = 1; + spin_unlock_irqrestore(&priv->lock, flags); + wake_up_interruptible(&priv->delta_msr_wait); + } + +exit: + status = usb_submit_urb(urb, GFP_ATOMIC); + if (status) + dev_err(&urb->dev->dev, + "%s - usb_submit_urb failed with result %d\n", + __func__, status); +} + +static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) +{ + struct ch341_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + u8 prevstatus; + u8 status; + u8 changed; + u8 multi_change = 0; + + spin_lock_irqsave(&priv->lock, flags); + prevstatus = priv->line_status; + priv->multi_status_change = 0; + spin_unlock_irqrestore(&priv->lock, flags); + + while (!multi_change) { + interruptible_sleep_on(&priv->delta_msr_wait); + /* see if a signal did it */ + if (signal_pending(current)) + return -ERESTARTSYS; + + spin_lock_irqsave(&priv->lock, flags); + status = priv->line_status; + multi_change = priv->multi_status_change; + spin_unlock_irqrestore(&priv->lock, flags); + + changed = prevstatus ^ status; + + if (((arg & TIOCM_RNG) && (changed & CH341_BIT_RI)) || + ((arg & TIOCM_DSR) && (changed & CH341_BIT_DSR)) || + ((arg & TIOCM_CD) && (changed & CH341_BIT_DCD)) || + ((arg & TIOCM_CTS) && (changed & CH341_BIT_CTS))) { + return 0; + } + prevstatus = status; + } + + return 0; +} + +/*static int ch341_ioctl(struct usb_serial_port *port, struct file *file,*/ +static int ch341_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct usb_serial_port *port = tty->driver_data; + dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd); + + switch (cmd) { + case TIOCMIWAIT: + dbg("%s (%d) TIOCMIWAIT", __func__, port->number); + return wait_modem_info(port, arg); + + default: + dbg("%s not supported = 0x%04x", __func__, cmd); + break; + } + + return -ENOIOCTLCMD; +} + +static int ch341_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct usb_serial_port *port = tty->driver_data; + struct ch341_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + u8 mcr; + u8 status; + unsigned int result; + + dbg("%s (%d)", __func__, port->number); + + spin_lock_irqsave(&priv->lock, flags); + mcr = priv->line_control; + status = priv->line_status; + spin_unlock_irqrestore(&priv->lock, flags); + + result = ((mcr & CH341_BIT_DTR) ? TIOCM_DTR : 0) + | ((mcr & CH341_BIT_RTS) ? TIOCM_RTS : 0) + | ((status & CH341_BIT_CTS) ? TIOCM_CTS : 0) + | ((status & CH341_BIT_DSR) ? TIOCM_DSR : 0) + | ((status & CH341_BIT_RI) ? TIOCM_RI : 0) + | ((status & CH341_BIT_DCD) ? TIOCM_CD : 0); + + dbg("%s - result = %x", __func__, result); - /* Copy back the old hardware settings */ - tty_termios_copy_hw(tty->termios, old_termios); - /* And re-encode with the new baud */ - tty_encode_baud_rate(tty, baud_rate, baud_rate); + return result; } static struct usb_driver ch341_driver = { @@ -317,12 +542,17 @@ static struct usb_serial_driver ch341_device = { .owner = THIS_MODULE, .name = "ch341-uart", }, - .id_table = id_table, - .usb_driver = &ch341_driver, - .num_ports = 1, - .open = ch341_open, - .set_termios = ch341_set_termios, - .attach = ch341_attach, + .id_table = id_table, + .usb_driver = &ch341_driver, + .num_ports = 1, + .open = ch341_open, + .close = ch341_close, + .ioctl = ch341_ioctl, + .set_termios = ch341_set_termios, + .tiocmget = ch341_tiocmget, + .tiocmset = ch341_tiocmset, + .read_int_callback = ch341_read_int_callback, + .attach = ch341_attach, }; static int __init ch341_init(void) -- GitLab From 8f182e5ddc84a30d7014a753ae359d85b1238e7f Mon Sep 17 00:00:00 2001 From: Darius Augulis Date: Wed, 21 Jan 2009 15:17:25 +0200 Subject: [PATCH 4304/4982] USB: imx_udc: Fix IMX UDC gadget bugs Fix small bugs and add some omptimization in IMX UDC Gadget. Signed-off-by: Darius Augulis Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/imx_udc.c | 33 +++++++++++++++++++-------------- drivers/usb/gadget/imx_udc.h | 2 +- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index 77c5d0a8a06..9e3fe306301 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -283,7 +283,7 @@ void imx_ep_stall(struct imx_ep_struct *imx_ep) imx_flush(imx_ep); /* Special care for ep0 */ - if (EP_NO(imx_ep)) { + if (!EP_NO(imx_ep)) { temp = __raw_readl(imx_usb->base + USB_CTRL); __raw_writel(temp | CTRL_CMDOVER | CTRL_CMDERROR, imx_usb->base + USB_CTRL); do { } while (__raw_readl(imx_usb->base + USB_CTRL) & CTRL_CMDOVER); @@ -301,7 +301,7 @@ void imx_ep_stall(struct imx_ep_struct *imx_ep) break; udelay(20); } - if (i == 50) + if (i == 100) D_ERR(imx_usb->dev, "<%s> Non finished stall on %s\n", __func__, imx_ep->ep.name); } @@ -539,10 +539,9 @@ static int handle_ep0(struct imx_ep_struct *imx_ep) struct imx_request *req = NULL; int ret = 0; - if (!list_empty(&imx_ep->queue)) + if (!list_empty(&imx_ep->queue)) { req = list_entry(imx_ep->queue.next, struct imx_request, queue); - if (req) { switch (imx_ep->imx_usb->ep0state) { case EP0_IN_DATA_PHASE: /* GET_DESCRIPTOR */ @@ -561,6 +560,10 @@ static int handle_ep0(struct imx_ep_struct *imx_ep) } } + else + D_ERR(imx_ep->imx_usb->dev, "<%s> no request on %s\n", + __func__, imx_ep->ep.name); + return ret; } @@ -759,7 +762,7 @@ static int imx_ep_queue */ if (imx_usb->set_config && !EP_NO(imx_ep)) { imx_usb->set_config = 0; - D_EPX(imx_usb->dev, + D_ERR(imx_usb->dev, "<%s> gadget reply set config\n", __func__); return 0; } @@ -779,8 +782,6 @@ static int imx_ep_queue return -ESHUTDOWN; } - local_irq_save(flags); - /* Debug */ D_REQ(imx_usb->dev, "<%s> ep%d %s request for [%d] bytes\n", __func__, EP_NO(imx_ep), @@ -790,17 +791,18 @@ static int imx_ep_queue if (imx_ep->stopped) { usb_req->status = -ESHUTDOWN; - ret = -ESHUTDOWN; - goto out; + return -ESHUTDOWN; } if (req->in_use) { D_ERR(imx_usb->dev, "<%s> refusing to queue req %p (already queued)\n", __func__, req); - goto out; + return 0; } + local_irq_save(flags); + usb_req->status = -EINPROGRESS; usb_req->actual = 0; @@ -810,7 +812,7 @@ static int imx_ep_queue ret = handle_ep0(imx_ep); else ret = handle_ep(imx_ep); -out: + local_irq_restore(flags); return ret; } @@ -1010,10 +1012,8 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) dump_usb_stat(__func__, imx_usb); } - if (!imx_usb->driver) { - /*imx_udc_disable(imx_usb);*/ + if (!imx_usb->driver) goto end_irq; - } if (intr & INTR_WAKEUP) { if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN @@ -1095,6 +1095,11 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) } if (intr & INTR_SOF) { + /* Copy from Freescale BSP. + We must enable SOF intr and set CMDOVER. + Datasheet don't specifiy this action, but it + is done in Freescale BSP, so just copy it. + */ if (imx_usb->ep0state == EP0_IDLE) { temp = __raw_readl(imx_usb->base + USB_CTRL); __raw_writel(temp | CTRL_CMDOVER, imx_usb->base + USB_CTRL); diff --git a/drivers/usb/gadget/imx_udc.h b/drivers/usb/gadget/imx_udc.h index 850076937d8..d1dfb2d2fa8 100644 --- a/drivers/usb/gadget/imx_udc.h +++ b/drivers/usb/gadget/imx_udc.h @@ -170,7 +170,7 @@ struct imx_udc_struct { /* #define DEBUG_IRQ */ /* #define DEBUG_EPIRQ */ /* #define DEBUG_DUMP */ -#define DEBUG_ERR +/* #define DEBUG_ERR */ #ifdef DEBUG_REQ #define D_REQ(dev, args...) dev_dbg(dev, ## args) -- GitLab From 593bef6c75e11d2edb5396bd9775cf49a4cda659 Mon Sep 17 00:00:00 2001 From: Darius Augulis Date: Wed, 21 Jan 2009 15:17:55 +0200 Subject: [PATCH 4305/4982] USB: imx_udc: Fix IMX UDC gadget code style Fix code style errors in IMX UDC Gadget. Signed-off-by: Darius Augulis Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/imx_udc.c | 59 ++++++++++++++++++++++++------------ drivers/usb/gadget/imx_udc.h | 46 ++++++++++++++++++---------- 2 files changed, 69 insertions(+), 36 deletions(-) diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index 9e3fe306301..3ee5bd8bea7 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -1,7 +1,7 @@ /* * driver/usb/gadget/imx_udc.c * - * Copyright (C) 2005 Mike Lee(eemike@gmail.com) + * Copyright (C) 2005 Mike Lee * Copyright (C) 2008 Darius Augulis * * This program is free software; you can redistribute it and/or modify @@ -51,7 +51,8 @@ void ep0_chg_stat(const char *label, struct imx_udc_struct *imx_usb, void imx_udc_enable(struct imx_udc_struct *imx_usb) { int temp = __raw_readl(imx_usb->base + USB_CTRL); - __raw_writel(temp | CTRL_FE_ENA | CTRL_AFE_ENA, imx_usb->base + USB_CTRL); + __raw_writel(temp | CTRL_FE_ENA | CTRL_AFE_ENA, + imx_usb->base + USB_CTRL); imx_usb->gadget.speed = USB_SPEED_FULL; } @@ -126,7 +127,8 @@ void imx_udc_config(struct imx_udc_struct *imx_usb) for (j = 0; j < 5; j++) { __raw_writeb(ep_conf[j], imx_usb->base + USB_DDAT); - do {} while (__raw_readl(imx_usb->base + USB_DADR) + do {} while (__raw_readl(imx_usb->base + + USB_DADR) & DADR_BSY); } } @@ -183,7 +185,8 @@ void imx_udc_init_ep(struct imx_udc_struct *imx_usb) temp = (EP_DIR(imx_ep) << 7) | (max << 5) | (imx_ep->bmAttributes << 3); __raw_writel(temp, imx_usb->base + USB_EP_STAT(i)); - __raw_writel(temp | EPSTAT_FLUSH, imx_usb->base + USB_EP_STAT(i)); + __raw_writel(temp | EPSTAT_FLUSH, + imx_usb->base + USB_EP_STAT(i)); D_INI(imx_usb->dev, "<%s> ep%d_stat %08x\n", __func__, i, __raw_readl(imx_usb->base + USB_EP_STAT(i))); } @@ -278,15 +281,18 @@ void imx_ep_stall(struct imx_ep_struct *imx_ep) struct imx_udc_struct *imx_usb = imx_ep->imx_usb; int temp, i; - D_ERR(imx_usb->dev, "<%s> Forced stall on %s\n", __func__, imx_ep->ep.name); + D_ERR(imx_usb->dev, + "<%s> Forced stall on %s\n", __func__, imx_ep->ep.name); imx_flush(imx_ep); /* Special care for ep0 */ if (!EP_NO(imx_ep)) { temp = __raw_readl(imx_usb->base + USB_CTRL); - __raw_writel(temp | CTRL_CMDOVER | CTRL_CMDERROR, imx_usb->base + USB_CTRL); - do { } while (__raw_readl(imx_usb->base + USB_CTRL) & CTRL_CMDOVER); + __raw_writel(temp | CTRL_CMDOVER | CTRL_CMDERROR, + imx_usb->base + USB_CTRL); + do { } while (__raw_readl(imx_usb->base + USB_CTRL) + & CTRL_CMDOVER); temp = __raw_readl(imx_usb->base + USB_CTRL); __raw_writel(temp & ~CTRL_CMDERROR, imx_usb->base + USB_CTRL); } @@ -296,7 +302,8 @@ void imx_ep_stall(struct imx_ep_struct *imx_ep) imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); for (i = 0; i < 100; i ++) { - temp = __raw_readl(imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); + temp = __raw_readl(imx_usb->base + + USB_EP_STAT(EP_NO(imx_ep))); if (!(temp & EPSTAT_STALL)) break; udelay(20); @@ -325,7 +332,8 @@ static int imx_udc_wakeup(struct usb_gadget *_gadget) ******************************************************************************* */ -static void ep_add_request(struct imx_ep_struct *imx_ep, struct imx_request *req) +static void ep_add_request(struct imx_ep_struct *imx_ep, + struct imx_request *req) { if (unlikely(!req)) return; @@ -334,7 +342,8 @@ static void ep_add_request(struct imx_ep_struct *imx_ep, struct imx_request *req list_add_tail(&req->queue, &imx_ep->queue); } -static void ep_del_request(struct imx_ep_struct *imx_ep, struct imx_request *req) +static void ep_del_request(struct imx_ep_struct *imx_ep, + struct imx_request *req) { if (unlikely(!req)) return; @@ -343,7 +352,8 @@ static void ep_del_request(struct imx_ep_struct *imx_ep, struct imx_request *req req->in_use = 0; } -static void done(struct imx_ep_struct *imx_ep, struct imx_request *req, int status) +static void done(struct imx_ep_struct *imx_ep, + struct imx_request *req, int status) { ep_del_request(imx_ep, req); @@ -494,7 +504,8 @@ static int write_fifo(struct imx_ep_struct *imx_ep, struct imx_request *req) __func__, imx_ep->ep.name, req, completed ? "completed" : "not completed"); if (!EP_NO(imx_ep)) - ep0_chg_stat(__func__, imx_ep->imx_usb, EP0_IDLE); + ep0_chg_stat(__func__, + imx_ep->imx_usb, EP0_IDLE); } } @@ -586,7 +597,8 @@ static void handle_ep0_devreq(struct imx_udc_struct *imx_usb) "<%s> no setup packet received\n", __func__); goto stall; } - u.word[i] = __raw_readl(imx_usb->base + USB_EP_FDAT(EP_NO(imx_ep))); + u.word[i] = __raw_readl(imx_usb->base + + USB_EP_FDAT(EP_NO(imx_ep))); } temp = imx_ep_empty(imx_ep); @@ -785,8 +797,10 @@ static int imx_ep_queue /* Debug */ D_REQ(imx_usb->dev, "<%s> ep%d %s request for [%d] bytes\n", __func__, EP_NO(imx_ep), - ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state == EP0_IN_DATA_PHASE) - || (EP_NO(imx_ep) && EP_DIR(imx_ep))) ? "IN" : "OUT", usb_req->length); + ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state + == EP0_IN_DATA_PHASE) + || (EP_NO(imx_ep) && EP_DIR(imx_ep))) + ? "IN" : "OUT", usb_req->length); dump_req(__func__, imx_ep, usb_req); if (imx_ep->stopped) { @@ -1061,7 +1075,8 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) /* Config setup */ if (imx_usb->cfg != cfg) { - D_REQ(imx_usb->dev, "<%s> Change config start\n",__func__); + D_REQ(imx_usb->dev, + "<%s> Change config start\n", __func__); u.bRequest = USB_REQ_SET_CONFIGURATION; u.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | @@ -1073,11 +1088,13 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) imx_usb->set_config = 1; imx_usb->driver->setup(&imx_usb->gadget, &u); imx_usb->set_config = 0; - D_REQ(imx_usb->dev, "<%s> Change config done\n",__func__); + D_REQ(imx_usb->dev, + "<%s> Change config done\n", __func__); } if (imx_usb->intf != intf || imx_usb->alt != alt) { - D_REQ(imx_usb->dev, "<%s> Change interface start\n",__func__); + D_REQ(imx_usb->dev, + "<%s> Change interface start\n", __func__); u.bRequest = USB_REQ_SET_INTERFACE; u.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | @@ -1090,7 +1107,8 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) imx_usb->set_config = 1; imx_usb->driver->setup(&imx_usb->gadget, &u); imx_usb->set_config = 0; - D_REQ(imx_usb->dev, "<%s> Change interface done\n",__func__); + D_REQ(imx_usb->dev, + "<%s> Change interface done\n", __func__); } } @@ -1102,7 +1120,8 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) */ if (imx_usb->ep0state == EP0_IDLE) { temp = __raw_readl(imx_usb->base + USB_CTRL); - __raw_writel(temp | CTRL_CMDOVER, imx_usb->base + USB_CTRL); + __raw_writel(temp | CTRL_CMDOVER, + imx_usb->base + USB_CTRL); } } diff --git a/drivers/usb/gadget/imx_udc.h b/drivers/usb/gadget/imx_udc.h index d1dfb2d2fa8..6b0b1e3d6fc 100644 --- a/drivers/usb/gadget/imx_udc.h +++ b/drivers/usb/gadget/imx_udc.h @@ -23,7 +23,8 @@ /* Helper macros */ #define EP_NO(ep) ((ep->bEndpointAddress) & ~USB_DIR_IN) /* IN:1, OUT:0 */ #define EP_DIR(ep) ((ep->bEndpointAddress) & USB_DIR_IN ? 1 : 0) -#define irq_to_ep(irq) (((irq) >= USBD_INT0) || ((irq) <= USBD_INT6) ? ((irq) - USBD_INT0) : (USBD_INT6)) /*should not happen*/ +#define irq_to_ep(irq) (((irq) >= USBD_INT0) || ((irq) <= USBD_INT6) \ + ? ((irq) - USBD_INT0) : (USBD_INT6)) /*should not happen*/ #define ep_to_irq(ep) (EP_NO((ep)) + USBD_INT0) #define IMX_USB_NB_EP 6 @@ -88,8 +89,8 @@ struct imx_udc_struct { #define USB_EP_FDAT3(x) (0x3F + (x*0x30)) /* USB FIFO data */ #define USB_EP_FSTAT(x) (0x40 + (x*0x30)) /* USB FIFO status */ #define USB_EP_FCTRL(x) (0x44 + (x*0x30)) /* USB FIFO control */ -#define USB_EP_LRFP(x) (0x48 + (x*0x30)) /* USB last read frame pointer */ -#define USB_EP_LWFP(x) (0x4C + (x*0x30)) /* USB last write frame pointer */ +#define USB_EP_LRFP(x) (0x48 + (x*0x30)) /* USB last rd f. pointer */ +#define USB_EP_LWFP(x) (0x4C + (x*0x30)) /* USB last wr f. pointer */ #define USB_EP_FALRM(x) (0x50 + (x*0x30)) /* USB FIFO alarm */ #define USB_EP_FRDP(x) (0x54 + (x*0x30)) /* USB FIFO read pointer */ #define USB_EP_FWRP(x) (0x58 + (x*0x30)) /* USB FIFO write pointer */ @@ -228,7 +229,8 @@ struct imx_udc_struct { #endif /* DEBUG_IRQ */ #ifdef DEBUG_EPIRQ - static void dump_ep_intr(const char *label, int nr, int irqreg, struct device *dev) + static void dump_ep_intr(const char *label, int nr, int irqreg, + struct device *dev) { dev_dbg(dev, "<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, nr, (irqreg & EPINTR_FIFO_FULL) ? " full" : "", @@ -246,7 +248,8 @@ struct imx_udc_struct { #endif /* DEBUG_IRQ */ #ifdef DEBUG_DUMP - static void dump_usb_stat(const char *label, struct imx_udc_struct *imx_usb) + static void dump_usb_stat(const char *label, + struct imx_udc_struct *imx_usb) { int temp = __raw_readl(imx_usb->base + USB_STAT); @@ -259,12 +262,15 @@ struct imx_udc_struct { (temp & STAT_ALTSET)); } - static void dump_ep_stat(const char *label, struct imx_ep_struct *imx_ep) + static void dump_ep_stat(const char *label, + struct imx_ep_struct *imx_ep) { - int temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_INTR(EP_NO(imx_ep))); + int temp = __raw_readl(imx_ep->imx_usb->base + + USB_EP_INTR(EP_NO(imx_ep))); dev_dbg(imx_ep->imx_usb->dev, - "<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, EP_NO(imx_ep), + "<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", + label, EP_NO(imx_ep), (temp & EPINTR_FIFO_FULL) ? " full" : "", (temp & EPINTR_FIFO_EMPTY) ? " fempty" : "", (temp & EPINTR_FIFO_ERROR) ? " ferr" : "", @@ -275,18 +281,22 @@ struct imx_udc_struct { (temp & EPINTR_DEVREQ) ? " devreq" : "", (temp & EPINTR_EOT) ? " eot" : ""); - temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); + temp = __raw_readl(imx_ep->imx_usb->base + + USB_EP_STAT(EP_NO(imx_ep))); dev_dbg(imx_ep->imx_usb->dev, - "<%s> EP%d_STAT=[%s%s bcount=%d]\n", label, EP_NO(imx_ep), + "<%s> EP%d_STAT=[%s%s bcount=%d]\n", + label, EP_NO(imx_ep), (temp & EPSTAT_SIP) ? " sip" : "", (temp & EPSTAT_STALL) ? " stall" : "", (temp & EPSTAT_BCOUNT) >> 16); - temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_FSTAT(EP_NO(imx_ep))); + temp = __raw_readl(imx_ep->imx_usb->base + + USB_EP_FSTAT(EP_NO(imx_ep))); dev_dbg(imx_ep->imx_usb->dev, - "<%s> EP%d_FSTAT=[%s%s%s%s%s%s%s]\n", label, EP_NO(imx_ep), + "<%s> EP%d_FSTAT=[%s%s%s%s%s%s%s]\n", + label, EP_NO(imx_ep), (temp & FSTAT_ERR) ? " ferr" : "", (temp & FSTAT_UF) ? " funder" : "", (temp & FSTAT_OF) ? " fover" : "", @@ -296,19 +306,23 @@ struct imx_udc_struct { (temp & FSTAT_EMPTY) ? " fempty" : ""); } - static void dump_req(const char *label, struct imx_ep_struct *imx_ep, struct usb_request *req) + static void dump_req(const char *label, struct imx_ep_struct *imx_ep, + struct usb_request *req) { int i; if (!req || !req->buf) { - dev_dbg(imx_ep->imx_usb->dev, "<%s> req or req buf is free\n", label); + dev_dbg(imx_ep->imx_usb->dev, + "<%s> req or req buf is free\n", label); return; } - if ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state == EP0_IN_DATA_PHASE) + if ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state + == EP0_IN_DATA_PHASE) || (EP_NO(imx_ep) && EP_DIR(imx_ep))) { - dev_dbg(imx_ep->imx_usb->dev, "<%s> request dump <", label); + dev_dbg(imx_ep->imx_usb->dev, + "<%s> request dump <", label); for (i = 0; i < req->length; i++) printk("%02x-", *((u8 *)req->buf + i)); printk(">\n"); -- GitLab From d24921a36df31332c32e1bb539671284d9e36bfa Mon Sep 17 00:00:00 2001 From: Darius Augulis Date: Wed, 21 Jan 2009 15:18:33 +0200 Subject: [PATCH 4306/4982] USB: imx_udc: Fix IMX UDC gadget ep0 irq handling Fix ep0 interrupt handling in IMX UDC Gadget. Signed-off-by: Darius Augulis Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/imx_udc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index 3ee5bd8bea7..e590464c3a5 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -1133,6 +1133,7 @@ end_irq: static irqreturn_t imx_udc_ctrl_irq(int irq, void *dev) { struct imx_udc_struct *imx_usb = dev; + struct imx_ep_struct *imx_ep = &imx_usb->imx_ep[0]; int intr = __raw_readl(imx_usb->base + USB_EP_INTR(0)); dump_ep_intr(__func__, 0, intr, imx_usb->dev); @@ -1142,16 +1143,15 @@ static irqreturn_t imx_udc_ctrl_irq(int irq, void *dev) return IRQ_HANDLED; } - /* DEVREQ IRQ has highest priority */ + /* DEVREQ has highest priority */ if (intr & (EPINTR_DEVREQ | EPINTR_MDEVREQ)) handle_ep0_devreq(imx_usb); /* Seem i.MX is missing EOF interrupt sometimes. - * Therefore we monitor both EOF and FIFO_EMPTY interrups - * when transmiting, and both EOF and FIFO_FULL when - * receiving data. + * Therefore we don't monitor EOF. + * We call handle_ep0() only if a request is queued for ep0. */ - else if (intr & (EPINTR_EOF | EPINTR_FIFO_EMPTY | EPINTR_FIFO_FULL)) - handle_ep0(&imx_usb->imx_ep[0]); + else if (!list_empty(&imx_ep->queue)) + handle_ep0(imx_ep); __raw_writel(intr, imx_usb->base + USB_EP_INTR(0)); -- GitLab From b633d28e2c5fbe1c8d163892644f57df04aa1421 Mon Sep 17 00:00:00 2001 From: Darius Augulis Date: Wed, 21 Jan 2009 15:19:19 +0200 Subject: [PATCH 4307/4982] USB: imx_udc: Fix IMX UDC gadget general irq handling Workaround of hw bug in IMX UDC. This bug causes wrong handling of CFG_CHG interrupt. Workaround is documented inline source code. Signed-off-by: Darius Augulis Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/imx_udc.c | 158 +++++++++++++++++++++-------------- drivers/usb/gadget/imx_udc.h | 1 + 2 files changed, 94 insertions(+), 65 deletions(-) diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index e590464c3a5..8d3c6a96098 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -1013,70 +1014,32 @@ static void udc_stop_activity(struct imx_udc_struct *imx_usb, ******************************************************************************* */ -static irqreturn_t imx_udc_irq(int irq, void *dev) +/* + * Called when timer expires. + * Timer is started when CFG_CHG is received. + */ +static void handle_config(unsigned long data) { - struct imx_udc_struct *imx_usb = dev; + struct imx_udc_struct *imx_usb = (void *)data; struct usb_ctrlrequest u; int temp, cfg, intf, alt; - int intr = __raw_readl(imx_usb->base + USB_INTR); - - if (intr & (INTR_WAKEUP | INTR_SUSPEND | INTR_RESUME | INTR_RESET_START - | INTR_RESET_STOP | INTR_CFG_CHG)) { - dump_intr(__func__, intr, imx_usb->dev); - dump_usb_stat(__func__, imx_usb); - } - - if (!imx_usb->driver) - goto end_irq; - - if (intr & INTR_WAKEUP) { - if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN - && imx_usb->driver && imx_usb->driver->resume) - imx_usb->driver->resume(&imx_usb->gadget); - imx_usb->set_config = 0; - imx_usb->gadget.speed = USB_SPEED_FULL; - } - - if (intr & INTR_SUSPEND) { - if (imx_usb->gadget.speed != USB_SPEED_UNKNOWN - && imx_usb->driver && imx_usb->driver->suspend) - imx_usb->driver->suspend(&imx_usb->gadget); - imx_usb->set_config = 0; - imx_usb->gadget.speed = USB_SPEED_UNKNOWN; - } - if (intr & INTR_RESET_START) { - __raw_writel(intr, imx_usb->base + USB_INTR); - udc_stop_activity(imx_usb, imx_usb->driver); - imx_usb->set_config = 0; - imx_usb->gadget.speed = USB_SPEED_UNKNOWN; - } - - if (intr & INTR_RESET_STOP) - imx_usb->gadget.speed = USB_SPEED_FULL; + local_irq_disable(); - if (intr & INTR_CFG_CHG) { - __raw_writel(INTR_CFG_CHG, imx_usb->base + USB_INTR); - temp = __raw_readl(imx_usb->base + USB_STAT); - cfg = (temp & STAT_CFG) >> 5; - intf = (temp & STAT_INTF) >> 3; - alt = temp & STAT_ALTSET; + temp = __raw_readl(imx_usb->base + USB_STAT); + cfg = (temp & STAT_CFG) >> 5; + intf = (temp & STAT_INTF) >> 3; + alt = temp & STAT_ALTSET; - D_REQ(imx_usb->dev, - "<%s> orig config C=%d, I=%d, A=%d / " - "req config C=%d, I=%d, A=%d\n", - __func__, imx_usb->cfg, imx_usb->intf, imx_usb->alt, - cfg, intf, alt); + D_REQ(imx_usb->dev, + "<%s> orig config C=%d, I=%d, A=%d / " + "req config C=%d, I=%d, A=%d\n", + __func__, imx_usb->cfg, imx_usb->intf, imx_usb->alt, + cfg, intf, alt); - if (cfg != 1 && cfg != 2) - goto end_irq; + if (cfg == 1 || cfg == 2) { - imx_usb->set_config = 0; - - /* Config setup */ if (imx_usb->cfg != cfg) { - D_REQ(imx_usb->dev, - "<%s> Change config start\n", __func__); u.bRequest = USB_REQ_SET_CONFIGURATION; u.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | @@ -1085,16 +1048,10 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) u.wIndex = 0; u.wLength = 0; imx_usb->cfg = cfg; - imx_usb->set_config = 1; imx_usb->driver->setup(&imx_usb->gadget, &u); - imx_usb->set_config = 0; - D_REQ(imx_usb->dev, - "<%s> Change config done\n", __func__); } if (imx_usb->intf != intf || imx_usb->alt != alt) { - D_REQ(imx_usb->dev, - "<%s> Change interface start\n", __func__); u.bRequest = USB_REQ_SET_INTERFACE; u.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | @@ -1104,14 +1061,30 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) u.wLength = 0; imx_usb->intf = intf; imx_usb->alt = alt; - imx_usb->set_config = 1; imx_usb->driver->setup(&imx_usb->gadget, &u); - imx_usb->set_config = 0; - D_REQ(imx_usb->dev, - "<%s> Change interface done\n", __func__); } } + imx_usb->set_config = 0; + + local_irq_enable(); +} + +static irqreturn_t imx_udc_irq(int irq, void *dev) +{ + struct imx_udc_struct *imx_usb = dev; + int intr = __raw_readl(imx_usb->base + USB_INTR); + int temp; + + if (intr & (INTR_WAKEUP | INTR_SUSPEND | INTR_RESUME | INTR_RESET_START + | INTR_RESET_STOP | INTR_CFG_CHG)) { + dump_intr(__func__, intr, imx_usb->dev); + dump_usb_stat(__func__, imx_usb); + } + + if (!imx_usb->driver) + goto end_irq; + if (intr & INTR_SOF) { /* Copy from Freescale BSP. We must enable SOF intr and set CMDOVER. @@ -1125,6 +1098,55 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) } } + if (intr & INTR_CFG_CHG) { + /* A workaround of serious IMX UDC bug. + Handling of CFG_CHG should be delayed for some time, because + IMX does not NACK the host when CFG_CHG interrupt is pending. + There is no time to handle current CFG_CHG + if next CFG_CHG or SETUP packed is send immediately. + We have to clear CFG_CHG, start the timer and + NACK the host by setting CTRL_CMDOVER + if it sends any SETUP packet. + When timer expires, handler is called to handle configuration + changes. While CFG_CHG is not handled (set_config=1), + we must NACK the host to every SETUP packed. + This delay prevents from going out of sync with host. + */ + __raw_writel(INTR_CFG_CHG, imx_usb->base + USB_INTR); + imx_usb->set_config = 1; + mod_timer(&imx_usb->timer, jiffies + 5); + goto end_irq; + } + + if (intr & INTR_WAKEUP) { + if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN + && imx_usb->driver && imx_usb->driver->resume) + imx_usb->driver->resume(&imx_usb->gadget); + imx_usb->set_config = 0; + del_timer(&imx_usb->timer); + imx_usb->gadget.speed = USB_SPEED_FULL; + } + + if (intr & INTR_SUSPEND) { + if (imx_usb->gadget.speed != USB_SPEED_UNKNOWN + && imx_usb->driver && imx_usb->driver->suspend) + imx_usb->driver->suspend(&imx_usb->gadget); + imx_usb->set_config = 0; + del_timer(&imx_usb->timer); + imx_usb->gadget.speed = USB_SPEED_UNKNOWN; + } + + if (intr & INTR_RESET_START) { + __raw_writel(intr, imx_usb->base + USB_INTR); + udc_stop_activity(imx_usb, imx_usb->driver); + imx_usb->set_config = 0; + del_timer(&imx_usb->timer); + imx_usb->gadget.speed = USB_SPEED_UNKNOWN; + } + + if (intr & INTR_RESET_STOP) + imx_usb->gadget.speed = USB_SPEED_FULL; + end_irq: __raw_writel(intr, imx_usb->base + USB_INTR); return IRQ_HANDLED; @@ -1342,6 +1364,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) udc_stop_activity(imx_usb, driver); imx_udc_disable(imx_usb); + del_timer(&imx_usb->timer); driver->unbind(&imx_usb->gadget); imx_usb->gadget.dev.driver = NULL; @@ -1459,6 +1482,10 @@ static int __init imx_udc_probe(struct platform_device *pdev) usb_init_data(imx_usb); imx_udc_init(imx_usb); + init_timer(&imx_usb->timer); + imx_usb->timer.function = handle_config; + imx_usb->timer.data = (unsigned long)imx_usb; + return 0; fail3: @@ -1481,6 +1508,7 @@ static int __exit imx_udc_remove(struct platform_device *pdev) int i; imx_udc_disable(imx_usb); + del_timer(&imx_usb->timer); for (i = 0; i < IMX_USB_NB_EP + 1; i++) free_irq(imx_usb->usbd_int[i], imx_usb); diff --git a/drivers/usb/gadget/imx_udc.h b/drivers/usb/gadget/imx_udc.h index 6b0b1e3d6fc..b48ad59603d 100644 --- a/drivers/usb/gadget/imx_udc.h +++ b/drivers/usb/gadget/imx_udc.h @@ -59,6 +59,7 @@ struct imx_udc_struct { struct device *dev; struct imx_ep_struct imx_ep[IMX_USB_NB_EP]; struct clk *clk; + struct timer_list timer; enum ep0_state ep0state; struct resource *res; void __iomem *base; -- GitLab From 4901b2c34ecb6fc45909228ad269c8126efe4401 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Tue, 27 Jan 2009 17:21:40 +0100 Subject: [PATCH 4308/4982] USB: suspend/resume support for option driver This patch implements suspend and resume methods for the option driver. With my hardware I can even suspend the system and keep up a connection for a short time. Signed-off-by: Oliver Neukum Signed-Off-By: Matthias Urlichs Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 86 ++++++++++++++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 6 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 61ebddc4849..d560c0b54e6 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -62,6 +62,8 @@ static int option_tiocmget(struct tty_struct *tty, struct file *file); static int option_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *port); +static int option_suspend(struct usb_serial *serial, pm_message_t message); +static int option_resume(struct usb_serial *serial); /* Vendor and product IDs */ #define OPTION_VENDOR_ID 0x0AF0 @@ -523,6 +525,8 @@ static struct usb_driver option_driver = { .name = "option", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, + .suspend = usb_serial_suspend, + .resume = usb_serial_resume, .id_table = option_ids, .no_dynamic_id = 1, }; @@ -551,6 +555,8 @@ static struct usb_serial_driver option_1port_device = { .attach = option_startup, .shutdown = option_shutdown, .read_int_callback = option_instat_callback, + .suspend = option_suspend, + .resume = option_resume, }; static int debug; @@ -821,10 +827,10 @@ static void option_instat_callback(struct urb *urb) req_pkt->bRequestType, req_pkt->bRequest); } } else - dbg("%s: error %d", __func__, status); + err("%s: error %d", __func__, status); /* Resubmit urb so we continue receiving IRQ data */ - if (status != -ESHUTDOWN) { + if (status != -ESHUTDOWN && status != -ENOENT) { urb->dev = serial->dev; err = usb_submit_urb(urb, GFP_ATOMIC); if (err) @@ -843,7 +849,6 @@ static int option_write_room(struct tty_struct *tty) portdata = usb_get_serial_port_data(port); - for (i = 0; i < N_OUT_URB; i++) { this_urb = portdata->out_urbs[i]; if (this_urb && !test_bit(i, &portdata->out_busy)) @@ -1105,14 +1110,12 @@ bail_out_error: return 1; } -static void option_shutdown(struct usb_serial *serial) +static void stop_read_write_urbs(struct usb_serial *serial) { int i, j; struct usb_serial_port *port; struct option_port_private *portdata; - dbg("%s", __func__); - /* Stop reading/writing urbs */ for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; @@ -1122,6 +1125,17 @@ static void option_shutdown(struct usb_serial *serial) for (j = 0; j < N_OUT_URB; j++) usb_kill_urb(portdata->out_urbs[j]); } +} + +static void option_shutdown(struct usb_serial *serial) +{ + int i, j; + struct usb_serial_port *port; + struct option_port_private *portdata; + + dbg("%s", __func__); + + stop_read_write_urbs(serial); /* Now free them */ for (i = 0; i < serial->num_ports; ++i) { @@ -1152,6 +1166,66 @@ static void option_shutdown(struct usb_serial *serial) } } +static int option_suspend(struct usb_serial *serial, pm_message_t message) +{ + dbg("%s entered", __func__); + stop_read_write_urbs(serial); + + return 0; +} + +static int option_resume(struct usb_serial *serial) +{ + int err, i, j; + struct usb_serial_port *port; + struct urb *urb; + struct option_port_private *portdata; + + dbg("%s entered", __func__); + /* get the interrupt URBs resubmitted unconditionally */ + for (i = 0; i < serial->num_ports; i++) { + port = serial->port[i]; + if (!port->interrupt_in_urb) { + dbg("%s: No interrupt URB for port %d\n", __func__, i); + continue; + } + port->interrupt_in_urb->dev = serial->dev; + err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO); + dbg("Submitted interrupt URB for port %d (result %d)", i, err); + if (err < 0) { + err("%s: Error %d for interrupt URB of port%d", + __func__, err, i); + return err; + } + } + + for (i = 0; i < serial->num_ports; i++) { + /* walk all ports */ + port = serial->port[i]; + portdata = usb_get_serial_port_data(port); + mutex_lock(&port->mutex); + + /* skip closed ports */ + if (!port->port.count) { + mutex_unlock(&port->mutex); + continue; + } + + for (j = 0; j < N_IN_URB; j++) { + urb = portdata->in_urbs[j]; + err = usb_submit_urb(urb, GFP_NOIO); + if (err < 0) { + mutex_unlock(&port->mutex); + err("%s: Error %d for bulk URB %d", + __func__, err, i); + return err; + } + } + mutex_unlock(&port->mutex); + } + return 0; +} + MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_VERSION(DRIVER_VERSION); -- GitLab From d1c0713daea5d1d881ecc8707458ca6746031376 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 14 Jan 2009 18:34:06 +0100 Subject: [PATCH 4309/4982] USB: suspend/resume for opticon driver this does the standard support for suspend/resume for the opticon driver. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/opticon.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index cea326f1f10..00d5c60aded 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -306,11 +306,37 @@ static void opticon_shutdown(struct usb_serial *serial) usb_set_serial_data(serial, NULL); } +static int opticon_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct usb_serial *serial = usb_get_intfdata(intf); + struct opticon_private *priv = usb_get_serial_data(serial); + + usb_kill_urb(priv->bulk_read_urb); + return 0; +} + +static int opticon_resume(struct usb_interface *intf) +{ + struct usb_serial *serial = usb_get_intfdata(intf); + struct opticon_private *priv = usb_get_serial_data(serial); + struct usb_serial_port *port = serial->port[0]; + int result; + + mutex_lock(&port->mutex); + if (port->port.count) + result = usb_submit_urb(priv->bulk_read_urb, GFP_NOIO); + else + result = 0; + mutex_unlock(&port->mutex); + return result; +} static struct usb_driver opticon_driver = { .name = "opticon", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, + .suspend = opticon_suspend, + .resume = opticon_resume, .id_table = id_table, .no_dynamic_id = 1, }; -- GitLab From 6e14bda1b18b2e3c16258427fc43ceb43e1bc1d5 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Sat, 31 Jan 2009 12:37:04 +0100 Subject: [PATCH 4310/4982] USB: count reaches -1, tested 0 With a postfix decrement count will reach -1 rather than 0, so the warning will not be issued. Signed-off-by: Roel Kluin Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/pci-quirks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 75b69847918..033c2846ce5 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -234,7 +234,7 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) */ hcc_params = readl(base + EHCI_HCC_PARAMS); offset = (hcc_params >> 8) & 0xff; - while (offset && count--) { + while (offset && --count) { u32 cap; int msec; -- GitLab From f8bece8d91f9ed9cff3c98920802f1b3046b7560 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 5 Feb 2009 16:54:25 +0100 Subject: [PATCH 4311/4982] USB: serial: introduce a flag into the usb serial layer to tell drivers that their URBs are killed due to suspension This patch introduces a flag into the usb serial layer to tell drivers that their URBs are killed due to suspension. That is necessary to let drivers know whether they should report an error back. Signed-off-by: Oliver Neukum Hi Greg, this is for 2.6.30. Patches to use this in drivers are under development. Regards Oliver --- drivers/usb/serial/usb-serial.c | 4 ++++ include/linux/usb/serial.h | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index cfcfd5ab06c..c6aaa6dc756 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1067,6 +1067,8 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message) struct usb_serial_port *port; int i, r = 0; + serial->suspending = 1; + for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; if (port) @@ -1084,8 +1086,10 @@ int usb_serial_resume(struct usb_interface *intf) { struct usb_serial *serial = usb_get_intfdata(intf); + serial->suspending = 0; if (serial->type->resume) return serial->type->resume(serial); + return 0; } EXPORT_SYMBOL(usb_serial_resume); diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 0b8617a9176..b9584254259 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -130,7 +130,8 @@ struct usb_serial { struct usb_device *dev; struct usb_serial_driver *type; struct usb_interface *interface; - unsigned char disconnected; + unsigned char disconnected:1; + unsigned char suspending:1; unsigned char minor; unsigned char num_ports; unsigned char num_port_pointers; -- GitLab From d55c0ae6b243bb8e247259089b3a2e47ebfabdf6 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 6 Feb 2009 15:01:54 +0100 Subject: [PATCH 4312/4982] USB: serial generic resume function fix This removes an unnecessary check for autoresume from the generic resume method. The check has been obsoleted by the now delayed increase of the usage counter which makes the error this check prevented impossible. This change allows drivers which only use the bulk read URB the use of the generic method even if they support autosuspend. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 814909f1ee6..c4a47abfee6 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -177,14 +177,6 @@ int usb_serial_generic_resume(struct usb_serial *serial) struct usb_serial_port *port; int i, c = 0, r; -#ifdef CONFIG_PM - /* - * If this is an autoresume, don't submit URBs. - * They will be submitted in the open function instead. - */ - if (serial->dev->auto_pm) - return 0; -#endif for (i = 0; i < serial->num_ports; i++) { port = serial->port[i]; if (port->port.count && port->read_urb) { -- GitLab From 81d043c2f30b157b96cb8ef2b570d12c112e395d Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 6 Feb 2009 15:37:14 +0100 Subject: [PATCH 4313/4982] USB: serial: export symbol of usb_serial_generic_resume This exports a symbol for usb_serial_generic_resume, so that modules can use it. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index c4a47abfee6..9d57cace373 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -188,6 +188,7 @@ int usb_serial_generic_resume(struct usb_serial *serial) return c ? -EIO : 0; } +EXPORT_SYMBOL_GPL(usb_serial_generic_resume); void usb_serial_generic_close(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp) -- GitLab From c49cfa9170256295f4a0fd1668a2411fc05d6b33 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 6 Feb 2009 18:06:43 +0100 Subject: [PATCH 4314/4982] USB: serial: use generic method if no alternative is provided in usb serial layer This patch makes use of the generic method if a serial driver provides no implementation. This simplifies implementing suspend/resume support in serial drivers. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index c6aaa6dc756..18f94084731 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1085,12 +1085,15 @@ EXPORT_SYMBOL(usb_serial_suspend); int usb_serial_resume(struct usb_interface *intf) { struct usb_serial *serial = usb_get_intfdata(intf); + int rv; serial->suspending = 0; if (serial->type->resume) - return serial->type->resume(serial); + rv = serial->type->resume(serial); + else + rv = usb_serial_generic_resume(serial); - return 0; + return rv; } EXPORT_SYMBOL(usb_serial_resume); -- GitLab From 6f8aa65b52037123beab573432e371c0f70b7b9a Mon Sep 17 00:00:00 2001 From: Frank Seidel Date: Thu, 5 Feb 2009 16:16:24 +0100 Subject: [PATCH 4315/4982] USB: add missing KERN_* constants to printks According to kerneljanitors todo list all printk calls (beginning a new line) should have an according KERN_* constant. Those are the missing peaces here for the usb subsystem. Signed-off-by: Frank Seidel Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/fsl_usb2_udc.c | 8 ++++--- drivers/usb/gadget/lh7a40x_udc.c | 16 +++++++------ drivers/usb/host/isp116x.h | 8 +++---- drivers/usb/storage/alauda.c | 25 +++++++++++++-------- drivers/usb/storage/sddr09.c | 37 ++++++++++++++++++------------- drivers/usb/storage/sddr55.c | 4 +++- 6 files changed, 59 insertions(+), 39 deletions(-) diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c index d8d9a52a44b..9d7b95d4e3d 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.c +++ b/drivers/usb/gadget/fsl_usb2_udc.c @@ -1802,7 +1802,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) out: if (retval) - printk("gadget driver register failed %d\n", retval); + printk(KERN_WARNING "gadget driver register failed %d\n", + retval); return retval; } EXPORT_SYMBOL(usb_gadget_register_driver); @@ -1847,7 +1848,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) udc_controller->gadget.dev.driver = NULL; udc_controller->driver = NULL; - printk("unregistered gadget driver '%s'\n", driver->driver.name); + printk(KERN_WARNING "unregistered gadget driver '%s'\n", + driver->driver.name); return 0; } EXPORT_SYMBOL(usb_gadget_unregister_driver); @@ -2455,7 +2457,7 @@ module_init(udc_init); static void __exit udc_exit(void) { platform_driver_unregister(&udc_driver); - printk("%s unregistered\n", driver_desc); + printk(KERN_WARNING "%s unregistered\n", driver_desc); } module_exit(udc_exit); diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c index d554b089560..6cd3d54f564 100644 --- a/drivers/usb/gadget/lh7a40x_udc.c +++ b/drivers/usb/gadget/lh7a40x_udc.c @@ -432,8 +432,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) device_add(&dev->gadget.dev); retval = driver->bind(&dev->gadget); if (retval) { - printk("%s: bind to driver %s --> error %d\n", dev->gadget.name, - driver->driver.name, retval); + printk(KERN_WARNING "%s: bind to driver %s --> error %d\n", + dev->gadget.name, driver->driver.name, retval); device_del(&dev->gadget.dev); dev->driver = 0; @@ -445,8 +445,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) * for set_configuration as well as eventual disconnect. * NOTE: this shouldn't power up until later. */ - printk("%s: registered gadget driver '%s'\n", dev->gadget.name, - driver->driver.name); + printk(KERN_WARNING "%s: registered gadget driver '%s'\n", + dev->gadget.name, driver->driver.name); udc_enable(dev); @@ -581,7 +581,8 @@ static int read_fifo(struct lh7a40x_ep *ep, struct lh7a40x_request *req) * discard the extra data. */ if (req->req.status != -EOVERFLOW) - printk("%s overflow %d\n", ep->ep.name, count); + printk(KERN_WARNING "%s overflow %d\n", + ep->ep.name, count); req->req.status = -EOVERFLOW; } else { *buf++ = byte; @@ -831,7 +832,8 @@ static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr) queue); if (!req) { - printk("%s: NULL REQ %d\n", + printk(KERN_WARNING + "%s: NULL REQ %d\n", __func__, ep_idx); flush(ep); break; @@ -844,7 +846,7 @@ static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr) } else { /* Throw packet away.. */ - printk("%s: No descriptor?!?\n", __func__); + printk(KERN_WARNING "%s: No descriptor?!?\n", __func__); flush(ep); } } diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h index aa211bafcff..12db961acdf 100644 --- a/drivers/usb/host/isp116x.h +++ b/drivers/usb/host/isp116x.h @@ -563,7 +563,7 @@ static void urb_dbg(struct urb *urb, char *msg) */ static inline void dump_ptd(struct ptd *ptd) { - printk("td: %x %d%c%d %d,%d,%d %x %x%x%x\n", + printk(KERN_WARNING "td: %x %d%c%d %d,%d,%d %x %x%x%x\n", PTD_GET_CC(ptd), PTD_GET_FA(ptd), PTD_DIR_STR(ptd), PTD_GET_EP(ptd), PTD_GET_COUNT(ptd), PTD_GET_LEN(ptd), PTD_GET_MPS(ptd), @@ -576,7 +576,7 @@ static inline void dump_ptd_out_data(struct ptd *ptd, u8 * buf) int k; if (PTD_GET_DIR(ptd) != PTD_DIR_IN && PTD_GET_LEN(ptd)) { - printk("-> "); + printk(KERN_WARNING "-> "); for (k = 0; k < PTD_GET_LEN(ptd); ++k) printk("%02x ", ((u8 *) buf)[k]); printk("\n"); @@ -588,13 +588,13 @@ static inline void dump_ptd_in_data(struct ptd *ptd, u8 * buf) int k; if (PTD_GET_DIR(ptd) == PTD_DIR_IN && PTD_GET_COUNT(ptd)) { - printk("<- "); + printk(KERN_WARNING "<- "); for (k = 0; k < PTD_GET_COUNT(ptd); ++k) printk("%02x ", ((u8 *) buf)[k]); printk("\n"); } if (PTD_GET_LAST(ptd)) - printk("-\n"); + printk(KERN_WARNING "-\n"); } #else diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c index 8d3711a7ff0..5407411e30e 100644 --- a/drivers/usb/storage/alauda.c +++ b/drivers/usb/storage/alauda.c @@ -307,7 +307,8 @@ static int alauda_init_media(struct us_data *us) data[0], data[1], data[2], data[3]); media_info = alauda_card_find_id(data[1]); if (media_info == NULL) { - printk("alauda_init_media: Unrecognised media signature: " + printk(KERN_WARNING + "alauda_init_media: Unrecognised media signature: " "%02X %02X %02X %02X\n", data[0], data[1], data[2], data[3]); return USB_STOR_TRANSPORT_ERROR; @@ -518,7 +519,8 @@ static int alauda_read_map(struct us_data *us, unsigned int zone) /* check even parity */ if (parity[data[6] ^ data[7]]) { - printk("alauda_read_map: Bad parity in LBA for block %d" + printk(KERN_WARNING + "alauda_read_map: Bad parity in LBA for block %d" " (%02X %02X)\n", i, data[6], data[7]); pba_to_lba[i] = UNUSABLE; continue; @@ -538,13 +540,16 @@ static int alauda_read_map(struct us_data *us, unsigned int zone) */ if (lba_offset >= uzonesize) { - printk("alauda_read_map: Bad low LBA %d for block %d\n", + printk(KERN_WARNING + "alauda_read_map: Bad low LBA %d for block %d\n", lba_real, blocknum); continue; } if (lba_to_pba[lba_offset] != UNDEF) { - printk("alauda_read_map: LBA %d seen for PBA %d and %d\n", + printk(KERN_WARNING + "alauda_read_map: " + "LBA %d seen for PBA %d and %d\n", lba_real, lba_to_pba[lba_offset], blocknum); continue; } @@ -712,13 +717,15 @@ static int alauda_write_lba(struct us_data *us, u16 lba, if (pba == 1) { /* Maybe it is impossible to write to PBA 1. Fake success, but don't do anything. */ - printk("alauda_write_lba: avoid writing to pba 1\n"); + printk(KERN_WARNING + "alauda_write_lba: avoid writing to pba 1\n"); return USB_STOR_TRANSPORT_GOOD; } new_pba = alauda_find_unused_pba(&MEDIA_INFO(us), zone); if (!new_pba) { - printk("alauda_write_lba: Out of unused blocks\n"); + printk(KERN_WARNING + "alauda_write_lba: Out of unused blocks\n"); return USB_STOR_TRANSPORT_ERROR; } @@ -818,7 +825,7 @@ static int alauda_read_data(struct us_data *us, unsigned long address, len = min(sectors, blocksize) * (pagesize + 64); buffer = kmalloc(len, GFP_NOIO); if (buffer == NULL) { - printk("alauda_read_data: Out of memory\n"); + printk(KERN_WARNING "alauda_read_data: Out of memory\n"); return USB_STOR_TRANSPORT_ERROR; } @@ -911,7 +918,7 @@ static int alauda_write_data(struct us_data *us, unsigned long address, len = min(sectors, blocksize) * pagesize; buffer = kmalloc(len, GFP_NOIO); if (buffer == NULL) { - printk("alauda_write_data: Out of memory\n"); + printk(KERN_WARNING "alauda_write_data: Out of memory\n"); return USB_STOR_TRANSPORT_ERROR; } @@ -921,7 +928,7 @@ static int alauda_write_data(struct us_data *us, unsigned long address, */ blockbuffer = kmalloc((pagesize + 64) * blocksize, GFP_NOIO); if (blockbuffer == NULL) { - printk("alauda_write_data: Out of memory\n"); + printk(KERN_WARNING "alauda_write_data: Out of memory\n"); kfree(buffer); return USB_STOR_TRANSPORT_ERROR; } diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index 531ae5c5abf..b667c7d2b83 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c @@ -723,7 +723,7 @@ sddr09_read_data(struct us_data *us, len = min(sectors, (unsigned int) info->blocksize) * info->pagesize; buffer = kmalloc(len, GFP_NOIO); if (buffer == NULL) { - printk("sddr09_read_data: Out of memory\n"); + printk(KERN_WARNING "sddr09_read_data: Out of memory\n"); return -ENOMEM; } @@ -838,7 +838,8 @@ sddr09_write_lba(struct us_data *us, unsigned int lba, if (pba == UNDEF) { pba = sddr09_find_unused_pba(info, lba); if (!pba) { - printk("sddr09_write_lba: Out of unused blocks\n"); + printk(KERN_WARNING + "sddr09_write_lba: Out of unused blocks\n"); return -ENOSPC; } info->pba_to_lba[pba] = lba; @@ -849,7 +850,7 @@ sddr09_write_lba(struct us_data *us, unsigned int lba, if (pba == 1) { /* Maybe it is impossible to write to PBA 1. Fake success, but don't do anything. */ - printk("sddr09: avoid writing to pba 1\n"); + printk(KERN_WARNING "sddr09: avoid writing to pba 1\n"); return 0; } @@ -954,7 +955,7 @@ sddr09_write_data(struct us_data *us, blocklen = (pagelen << info->blockshift); blockbuffer = kmalloc(blocklen, GFP_NOIO); if (!blockbuffer) { - printk("sddr09_write_data: Out of memory\n"); + printk(KERN_WARNING "sddr09_write_data: Out of memory\n"); return -ENOMEM; } @@ -965,7 +966,7 @@ sddr09_write_data(struct us_data *us, len = min(sectors, (unsigned int) info->blocksize) * info->pagesize; buffer = kmalloc(len, GFP_NOIO); if (buffer == NULL) { - printk("sddr09_write_data: Out of memory\n"); + printk(KERN_WARNING "sddr09_write_data: Out of memory\n"); kfree(blockbuffer); return -ENOMEM; } @@ -1112,7 +1113,7 @@ sddr09_get_cardinfo(struct us_data *us, unsigned char flags) { if (result) { US_DEBUGP("Result of read_deviceID is %d\n", result); - printk("sddr09: could not read card info\n"); + printk(KERN_WARNING "sddr09: could not read card info\n"); return NULL; } @@ -1153,7 +1154,7 @@ sddr09_get_cardinfo(struct us_data *us, unsigned char flags) { sprintf(blurbtxt + strlen(blurbtxt), ", WP"); - printk("%s\n", blurbtxt); + printk(KERN_WARNING "%s\n", blurbtxt); return cardinfo; } @@ -1184,7 +1185,7 @@ sddr09_read_map(struct us_data *us) { alloc_len = (alloc_blocks << CONTROL_SHIFT); buffer = kmalloc(alloc_len, GFP_NOIO); if (buffer == NULL) { - printk("sddr09_read_map: out of memory\n"); + printk(KERN_WARNING "sddr09_read_map: out of memory\n"); result = -1; goto done; } @@ -1198,7 +1199,7 @@ sddr09_read_map(struct us_data *us) { info->pba_to_lba = kmalloc(numblocks*sizeof(int), GFP_NOIO); if (info->lba_to_pba == NULL || info->pba_to_lba == NULL) { - printk("sddr09_read_map: out of memory\n"); + printk(KERN_WARNING "sddr09_read_map: out of memory\n"); result = -1; goto done; } @@ -1238,7 +1239,8 @@ sddr09_read_map(struct us_data *us) { if (ptr[j] != 0) goto nonz; info->pba_to_lba[i] = UNUSABLE; - printk("sddr09: PBA %d has no logical mapping\n", i); + printk(KERN_WARNING "sddr09: PBA %d has no logical mapping\n", + i); continue; nonz: @@ -1251,7 +1253,8 @@ sddr09_read_map(struct us_data *us) { nonff: /* normal PBAs start with six FFs */ if (j < 6) { - printk("sddr09: PBA %d has no logical mapping: " + printk(KERN_WARNING + "sddr09: PBA %d has no logical mapping: " "reserved area = %02X%02X%02X%02X " "data status %02X block status %02X\n", i, ptr[0], ptr[1], ptr[2], ptr[3], @@ -1261,7 +1264,8 @@ sddr09_read_map(struct us_data *us) { } if ((ptr[6] >> 4) != 0x01) { - printk("sddr09: PBA %d has invalid address field " + printk(KERN_WARNING + "sddr09: PBA %d has invalid address field " "%02X%02X/%02X%02X\n", i, ptr[6], ptr[7], ptr[11], ptr[12]); info->pba_to_lba[i] = UNUSABLE; @@ -1270,7 +1274,8 @@ sddr09_read_map(struct us_data *us) { /* check even parity */ if (parity[ptr[6] ^ ptr[7]]) { - printk("sddr09: Bad parity in LBA for block %d" + printk(KERN_WARNING + "sddr09: Bad parity in LBA for block %d" " (%02X %02X)\n", i, ptr[6], ptr[7]); info->pba_to_lba[i] = UNUSABLE; continue; @@ -1289,7 +1294,8 @@ sddr09_read_map(struct us_data *us) { */ if (lba >= 1000) { - printk("sddr09: Bad low LBA %d for block %d\n", + printk(KERN_WARNING + "sddr09: Bad low LBA %d for block %d\n", lba, i); goto possibly_erase; } @@ -1297,7 +1303,8 @@ sddr09_read_map(struct us_data *us) { lba += 1000*(i/0x400); if (info->lba_to_pba[lba] != UNDEF) { - printk("sddr09: LBA %d seen for PBA %d and %d\n", + printk(KERN_WARNING + "sddr09: LBA %d seen for PBA %d and %d\n", lba, info->lba_to_pba[lba], i); goto possibly_erase; } diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c index 0d8df757789..5a0106ba256 100644 --- a/drivers/usb/storage/sddr55.c +++ b/drivers/usb/storage/sddr55.c @@ -703,7 +703,9 @@ static int sddr55_read_map(struct us_data *us) { if (info->lba_to_pba[lba + zone * 1000] != NOT_ALLOCATED && !info->force_read_only) { - printk("sddr55: map inconsistency at LBA %04X\n", lba + zone * 1000); + printk(KERN_WARNING + "sddr55: map inconsistency at LBA %04X\n", + lba + zone * 1000); info->force_read_only = 1; } -- GitLab From 5d1ca6cf7f80644b07c348d6be870ccd8e3a92ed Mon Sep 17 00:00:00 2001 From: David Brownell Date: Fri, 6 Feb 2009 02:39:11 -0800 Subject: [PATCH 4316/4982] USB: ftdi_sio: remove pointless syslog spew Remove some pointless messages from the FTDI serial driver; I found these filling up syslog on one system. Also remove a pointless "break" after a "return" in the same area. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index d889216bcb3..adeb23fb800 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -2292,11 +2292,8 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file) FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, 0, 0, buf, 1, WDR_TIMEOUT); - if (ret < 0) { - dbg("%s Could not get modem status of device - err: %d", __func__, - ret); + if (ret < 0) return ret; - } break; case FT8U232AM: case FT232BM: @@ -2311,15 +2308,11 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file) FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, 0, priv->interface, buf, 2, WDR_TIMEOUT); - if (ret < 0) { - dbg("%s Could not get modem status of device - err: %d", __func__, - ret); + if (ret < 0) return ret; - } break; default: return -EFAULT; - break; } return (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | -- GitLab From f6d92a05c86754d62eabc84856d2035d0de3ddc3 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Fri, 6 Feb 2009 17:32:35 +0530 Subject: [PATCH 4317/4982] USB: otg: adding nop usb transceiver NOP transceiver is used by all the usb transceiver which are mostly autonomous and doesn't require any programming or which are built into the usb ip itself.NOP transceiver only allocates the memory for struct xceiv and calls otg_set_transceiver() so function call to otg_get_transceiver() will return a valid transceiver. NOP transceiver device should be registered by calling usb_nop_xceiv_register() from platform files. Signed-off-by: Ajay Kumar Gupta Cc: Felipe Balbi Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/otg/Kconfig | 8 ++ drivers/usb/otg/Makefile | 1 + drivers/usb/otg/nop-usb-xceiv.c | 180 ++++++++++++++++++++++++++++++++ include/linux/usb/otg.h | 4 + 4 files changed, 193 insertions(+) create mode 100644 drivers/usb/otg/nop-usb-xceiv.c diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index ee55b449ffd..fc1ca03ce4d 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -51,4 +51,12 @@ config TWL4030_USB This transceiver supports high and full speed devices plus, in host mode, low speed. +config NOP_USB_XCEIV + tristate "NOP USB Transceiver Driver" + select USB_OTG_UTILS + help + this driver is to be used by all the usb transceiver which are either + built-in with usb ip or which are autonomous and doesn't require any + phy programming such as ISP1x04 etc. + endif # USB || OTG diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index d73c7cf5e2f..20816785652 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_USB_OTG_UTILS) += otg.o obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o +obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c new file mode 100644 index 00000000000..4b933f646f2 --- /dev/null +++ b/drivers/usb/otg/nop-usb-xceiv.c @@ -0,0 +1,180 @@ +/* + * drivers/usb/otg/nop-usb-xceiv.c + * + * NOP USB transceiver for all USB transceiver which are either built-in + * into USB IP or which are mostly autonomous. + * + * Copyright (C) 2009 Texas Instruments Inc + * Author: Ajay Kumar Gupta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Current status: + * this is to add "nop" transceiver for all those phy which is + * autonomous such as isp1504 etc. + */ + +#include +#include +#include +#include + +struct nop_usb_xceiv { + struct otg_transceiver otg; + struct device *dev; +}; + +static u64 nop_xceiv_dmamask = DMA_32BIT_MASK; + +static struct platform_device nop_xceiv_device = { + .name = "nop_usb_xceiv", + .id = -1, + .dev = { + .dma_mask = &nop_xceiv_dmamask, + .coherent_dma_mask = DMA_32BIT_MASK, + .platform_data = NULL, + }, +}; + +void usb_nop_xceiv_register(void) +{ + if (platform_device_register(&nop_xceiv_device) < 0) { + printk(KERN_ERR "Unable to register usb nop transceiver\n"); + return; + } +} + +void usb_nop_xceiv_unregister(void) +{ + platform_device_unregister(&nop_xceiv_device); +} + +static inline struct nop_usb_xceiv *xceiv_to_nop(struct otg_transceiver *x) +{ + return container_of(x, struct nop_usb_xceiv, otg); +} + +static int nop_set_suspend(struct otg_transceiver *x, int suspend) +{ + return 0; +} + +static int nop_set_peripheral(struct otg_transceiver *x, + struct usb_gadget *gadget) +{ + struct nop_usb_xceiv *nop; + + if (!x) + return -ENODEV; + + nop = xceiv_to_nop(x); + + if (!gadget) { + nop->otg.gadget = NULL; + return -ENODEV; + } + + nop->otg.gadget = gadget; + nop->otg.state = OTG_STATE_B_IDLE; + return 0; +} + +static int nop_set_host(struct otg_transceiver *x, struct usb_bus *host) +{ + struct nop_usb_xceiv *nop; + + if (!x) + return -ENODEV; + + nop = xceiv_to_nop(x); + + if (!host) { + nop->otg.host = NULL; + return -ENODEV; + } + + nop->otg.host = host; + return 0; +} + +static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev) +{ + struct nop_usb_xceiv *nop; + int err; + + nop = kzalloc(sizeof *nop, GFP_KERNEL); + if (!nop) + return -ENOMEM; + + nop->dev = &pdev->dev; + nop->otg.dev = nop->dev; + nop->otg.label = "nop-xceiv"; + nop->otg.state = OTG_STATE_UNDEFINED; + nop->otg.set_host = nop_set_host; + nop->otg.set_peripheral = nop_set_peripheral; + nop->otg.set_suspend = nop_set_suspend; + + err = otg_set_transceiver(&nop->otg); + if (err) { + dev_err(&pdev->dev, "can't register transceiver, err: %d\n", + err); + goto exit; + } + + platform_set_drvdata(pdev, nop); + + return 0; +exit: + kfree(nop); + return err; +} + +static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev) +{ + struct nop_usb_xceiv *nop = platform_get_drvdata(pdev); + + otg_set_transceiver(NULL); + + platform_set_drvdata(pdev, NULL); + kfree(nop); + + return 0; +} + +static struct platform_driver nop_usb_xceiv_driver = { + .probe = nop_usb_xceiv_probe, + .remove = __devexit_p(nop_usb_xceiv_remove), + .driver = { + .name = "nop_usb_xceiv", + .owner = THIS_MODULE, + }, +}; + +static int __init nop_usb_xceiv_init(void) +{ + return platform_driver_register(&nop_usb_xceiv_driver); +} +subsys_initcall(nop_usb_xceiv_init); + +static void __exit nop_usb_xceiv_exit(void) +{ + platform_driver_unregister(&nop_usb_xceiv_driver); +} +module_exit(nop_usb_xceiv_exit); + +MODULE_ALIAS("platform:nop_usb_xceiv"); +MODULE_AUTHOR("Texas Instruments Inc"); +MODULE_DESCRIPTION("NOP USB Transceiver driver"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h index 60a52576fd5..1aaa826396a 100644 --- a/include/linux/usb/otg.h +++ b/include/linux/usb/otg.h @@ -80,6 +80,10 @@ struct otg_transceiver { /* for board-specific init logic */ extern int otg_set_transceiver(struct otg_transceiver *); +#ifdef CONFIG_NOP_USB_XCEIV +extern void usb_nop_xceiv_register(void); +extern void usb_nop_xceiv_unregister(void); +#endif /* for usb host and peripheral controller drivers */ -- GitLab From 648d4e16567eae4c643bd2125e91128f06c0d3ad Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 6 Feb 2009 18:30:56 -0800 Subject: [PATCH 4318/4982] USB: serial: opticon: add write support This patch allows data to be sent to the scanner. Cc: Kees Stoop Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/opticon.c | 124 ++++++++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 00d5c60aded..8c87a49ee2b 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -1,8 +1,8 @@ /* * Opticon USB barcode to serial driver * - * Copyright (C) 2008 Greg Kroah-Hartman - * Copyright (C) 2008 Novell Inc. + * Copyright (C) 2008 - 2009 Greg Kroah-Hartman + * Copyright (C) 2008 - 2009 Novell Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version @@ -40,8 +40,12 @@ struct opticon_private { bool throttled; bool actually_throttled; bool rts; + int outstanding_urbs; }; +/* max number of write urbs in flight */ +#define URB_UPPER_LIMIT 4 + static void opticon_bulk_callback(struct urb *urb) { struct opticon_private *priv = urb->context; @@ -188,6 +192,120 @@ static void opticon_close(struct tty_struct *tty, struct usb_serial_port *port, usb_kill_urb(priv->bulk_read_urb); } +static void opticon_write_bulk_callback(struct urb *urb) +{ + struct opticon_private *priv = urb->context; + int status = urb->status; + unsigned long flags; + + /* free up the transfer buffer, as usb_free_urb() does not do this */ + kfree(urb->transfer_buffer); + + if (status) + dbg("%s - nonzero write bulk status received: %d", + __func__, status); + + spin_lock_irqsave(&priv->lock, flags); + --priv->outstanding_urbs; + spin_unlock_irqrestore(&priv->lock, flags); + + usb_serial_port_softint(priv->port); +} + +static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count) +{ + struct opticon_private *priv = usb_get_serial_data(port->serial); + struct usb_serial *serial = port->serial; + struct urb *urb; + unsigned char *buffer; + unsigned long flags; + int status; + + dbg("%s - port %d", __func__, port->number); + + spin_lock_irqsave(&priv->lock, flags); + if (priv->outstanding_urbs > URB_UPPER_LIMIT) { + spin_unlock_irqrestore(&priv->lock, flags); + dbg("%s - write limit hit\n", __func__); + return 0; + } + priv->outstanding_urbs++; + spin_unlock_irqrestore(&priv->lock, flags); + + buffer = kmalloc(count, GFP_ATOMIC); + if (!buffer) { + dev_err(&port->dev, "out of memory\n"); + count = -ENOMEM; + goto error_no_buffer; + } + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) { + dev_err(&port->dev, "no more free urbs\n"); + count = -ENOMEM; + goto error_no_urb; + } + + memcpy(buffer, buf, count); + + usb_serial_debug_data(debug, &port->dev, __func__, count, buffer); + + usb_fill_bulk_urb(urb, serial->dev, + usb_sndbulkpipe(serial->dev, + port->bulk_out_endpointAddress), + buffer, count, opticon_write_bulk_callback, priv); + + /* send it down the pipe */ + status = usb_submit_urb(urb, GFP_ATOMIC); + if (status) { + dev_err(&port->dev, + "%s - usb_submit_urb(write bulk) failed with status = %d\n", + __func__, status); + count = status; + goto error; + } + + /* we are done with this urb, so let the host driver + * really free it when it is finished with it */ + usb_free_urb(urb); + + return count; +error: + usb_free_urb(urb); +error_no_urb: + kfree(buffer); +error_no_buffer: + spin_lock_irqsave(&priv->lock, flags); + --priv->outstanding_urbs; + spin_unlock_irqrestore(&priv->lock, flags); + return count; +} + +static int opticon_write_room(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + struct opticon_private *priv = usb_get_serial_data(port->serial); + unsigned long flags; + + dbg("%s - port %d", __func__, port->number); + + /* + * We really can take almost anything the user throws at us + * but let's pick a nice big number to tell the tty + * layer that we have lots of free space, unless we don't. + */ + spin_lock_irqsave(&priv->lock, flags); + if (priv->outstanding_urbs > URB_UPPER_LIMIT * 2 / 3) { + spin_unlock_irqrestore(&priv->lock, flags); + dbg("%s - write limit hit\n", __func__); + return 0; + } + spin_unlock_irqrestore(&priv->lock, flags); + + return 2048; +} + static void opticon_throttle(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; @@ -352,6 +470,8 @@ static struct usb_serial_driver opticon_device = { .attach = opticon_startup, .open = opticon_open, .close = opticon_close, + .write = opticon_write, + .write_room = opticon_write_room, .shutdown = opticon_shutdown, .throttle = opticon_throttle, .unthrottle = opticon_unthrottle, -- GitLab From faac64ad9c7b1aa56a10be6b5f9b813789e81dfd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 6 Feb 2009 18:31:46 -0800 Subject: [PATCH 4319/4982] USB: serial: opticon: add serial line ioctls This lets userspace determine what the state of the RTS line is, which is what is needed to properly handle data flow for this device (it raises RTS when there is data to be sent from it.) Cc: Kees Stoop Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/opticon.c | 65 +++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 8c87a49ee2b..839583dc8b6 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -110,7 +111,6 @@ static void opticon_bulk_callback(struct urb *urb) priv->rts = false; else priv->rts = true; - /* FIXME change the RTS level */ } else { dev_dbg(&priv->udev->dev, "Unknown data packet received from the device:" @@ -341,6 +341,67 @@ static void opticon_unthrottle(struct tty_struct *tty) __func__, result); } +static int opticon_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct usb_serial_port *port = tty->driver_data; + struct opticon_private *priv = usb_get_serial_data(port->serial); + unsigned long flags; + int result = 0; + + dbg("%s - port %d", __func__, port->number); + + spin_lock_irqsave(&priv->lock, flags); + if (priv->rts) + result = TIOCM_RTS; + spin_unlock_irqrestore(&priv->lock, flags); + + dbg("%s - %x", __func__, result); + return result; +} + +static int get_serial_info(struct opticon_private *priv, + struct serial_struct __user *serial) +{ + struct serial_struct tmp; + + if (!serial) + return -EFAULT; + + memset(&tmp, 0x00, sizeof(tmp)); + + /* fake emulate a 16550 uart to make userspace code happy */ + tmp.type = PORT_16550A; + tmp.line = priv->serial->minor; + tmp.port = 0; + tmp.irq = 0; + tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; + tmp.xmit_fifo_size = 1024; + tmp.baud_base = 9600; + tmp.close_delay = 5*HZ; + tmp.closing_wait = 30*HZ; + + if (copy_to_user(serial, &tmp, sizeof(*serial))) + return -EFAULT; + return 0; +} + +static int opticon_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct usb_serial_port *port = tty->driver_data; + struct opticon_private *priv = usb_get_serial_data(port->serial); + + dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); + + switch (cmd) { + case TIOCGSERIAL: + return get_serial_info(priv, + (struct serial_struct __user *)arg); + } + + return -ENOIOCTLCMD; +} + static int opticon_startup(struct usb_serial *serial) { struct opticon_private *priv; @@ -475,6 +536,8 @@ static struct usb_serial_driver opticon_device = { .shutdown = opticon_shutdown, .throttle = opticon_throttle, .unthrottle = opticon_unthrottle, + .ioctl = opticon_ioctl, + .tiocmget = opticon_tiocmget, }; static int __init opticon_init(void) -- GitLab From 0eb526b96ced3759e7d4445fc55204f314e33d8c Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sat, 7 Feb 2009 20:20:42 +0100 Subject: [PATCH 4320/4982] usb_storage: make Kconfig note visible in the console Make lines about usb_storage depending on SCSI visible when configuring the kernel in a 80x25 console Signed-off-by: Borislav Petkov Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 9df6887b91f..5c367566be8 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -2,8 +2,8 @@ # USB Storage driver configuration # -comment "NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;" -comment "see USB_STORAGE Help for more information" +comment "NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may" +comment "also be needed; see USB_STORAGE Help for more info" depends on USB config USB_STORAGE -- GitLab From a5f5ea230d70f5dde4d787208855fa3c3cd7b31e Mon Sep 17 00:00:00 2001 From: Matt Kraai Date: Fri, 6 Feb 2009 19:38:51 -0800 Subject: [PATCH 4321/4982] USB: skeleton: Use dev_info instead of info 338b67b0c1a97ca705023a8189cf41aa0828d294 removed the info macro and replaced its uses with dev_info. This patch does so for usb-skeleton.c, which was missed. Signed-off-by: Matt Kraai Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usb-skeleton.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index be76084c8d7..60ba631e99c 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -410,7 +410,9 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i } /* let the user know what node this device is now attached to */ - info("USB Skeleton device now attached to USBSkel-%d", interface->minor); + dev_info(&interface->dev, + "USB Skeleton device now attached to USBSkel-%d", + interface->minor); return 0; error: @@ -441,7 +443,7 @@ static void skel_disconnect(struct usb_interface *interface) /* decrement our usage count */ kref_put(&dev->kref, skel_delete); - info("USB Skeleton #%d now disconnected", minor); + dev_info(&interface->dev, "USB Skeleton #%d now disconnected", minor); } static void skel_draw_down(struct usb_skel *dev) -- GitLab From 1c27ae671e6b465e04544450276c88f4dba8de60 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 9 Feb 2009 10:03:49 +0100 Subject: [PATCH 4322/4982] USB: serial: remove recourse to generic method This removes the fallback to the generic method. It is cleaner to explicitely request it. Introducing this was my mistake. This will be solved by an explicit test and the driver being allowed to request what it needs to be done upon resumption. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 18f94084731..9a2617845df 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1229,7 +1229,6 @@ static void fixup_generic(struct usb_serial_driver *device) set_to_generic_if_null(device, read_bulk_callback); set_to_generic_if_null(device, write_bulk_callback); set_to_generic_if_null(device, shutdown); - set_to_generic_if_null(device, resume); } int usb_serial_register(struct usb_serial_driver *driver) -- GitLab From 331879fd6f584d60327ba802616d41bfa636b873 Mon Sep 17 00:00:00 2001 From: James Woodcock Date: Wed, 11 Feb 2009 15:06:53 +0000 Subject: [PATCH 4323/4982] USB: serial: refuse to open recently removed USB Serial devices A USB-serial converter device is plugged into a system, and a process opens it's device node. If the device is physically removed whilst the process still has its device node open, then other processes can sucessfully open the now non-existent device's node. I would expect that open() on a device that has been physically removed should return ENODEV. This is manifesting itself with getty on my system. I do the following: 1. set up inittab to spawn getty on ttyUSB0, eg: T1:23:respawn:/sbin/getty -L ttyUSB0 115200 vt100 2. Plug in USB-serial converter cable 3. Wait for a login prompt on a terminal program attached to the serial cable 4. Login 5. Pull the USB-serial converter cable from the box 6. getty doesn't realise that ttyUSB0 no longer exists as /dev/ttyUSB0 can still be opened. 7. Re-insert the USB-serial converter cable 8. You should no longer get a login prompt over the serial cable, as the the USB-serial cable now shows up as /dev/ttyUSB1, and getty is trying to talk to /dev/ttyUSB0. The attached patch will cause open("/dev/ttyUSB0", O_RDONLY) to return ENODEV after the USB-serial converter has been pulled. The patch was created against 2.6.28.1. I can supply it against something else if needs be. It is fairly simple, so should be OK. I am using a pl2303 device, although I don't think that makes any difference. From: James Woodcock Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 9a2617845df..73172898ccb 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -204,6 +204,11 @@ static int serial_open (struct tty_struct *tty, struct file *filp) goto bailout_kref_put; } + if (port->serial->disconnected) { + retval = -ENODEV; + goto bailout_kref_put; + } + if (mutex_lock_interruptible(&port->mutex)) { retval = -ERESTARTSYS; goto bailout_kref_put; -- GitLab From b967c88ed1b48bc353ea83e0cacb2249a3bb1a51 Mon Sep 17 00:00:00 2001 From: Thierry Vignaud Date: Wed, 11 Feb 2009 13:31:05 -0800 Subject: [PATCH 4324/4982] usb: kill prehistorical comments about USB_EHCI_HCD Remove old comments about USB_EHCI_HCD. Cc: Alan Stern Signed-off-by: Andrew Morton Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 2c63bfb1f8d..c1cfed7eefb 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -24,10 +24,7 @@ config USB_EHCI_HCD The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0 "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware. If your USB host controller supports USB 2.0, you will likely want to - configure this Host Controller Driver. At the time of this writing, - the primary implementation of EHCI is a chip from NEC, widely available - in add-on PCI cards, but implementations are in the works from other - vendors including Intel and Philips. Motherboard support is appearing. + configure this Host Controller Driver. EHCI controllers are packaged with "companion" host controllers (OHCI or UHCI) to handle USB 1.1 devices connected to root hub ports. Ports -- GitLab From bc29847e16cb6b571157220ec9b20a7d86e58046 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 11 Feb 2009 14:26:38 -0500 Subject: [PATCH 4325/4982] USB: EHCI: Make timer_action out-of-line This patch (as1205) moves timer_action() from ehci.h to ehci-hcd.c and makes it out-of-line. Over the years it has grown too big to be inline any more. Signed-off-by: Alan Stern Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 36 ++++++++++++++++++++++++++++++++++++ drivers/usb/host/ehci.h | 34 ---------------------------------- 2 files changed, 36 insertions(+), 34 deletions(-) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index e551bb38852..f2618d17710 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -110,6 +110,42 @@ MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications"); /*-------------------------------------------------------------------------*/ +static void +timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action) +{ + /* Don't override timeouts which shrink or (later) disable + * the async ring; just the I/O watchdog. Note that if a + * SHRINK were pending, OFF would never be requested. + */ + if (timer_pending(&ehci->watchdog) + && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF)) + & ehci->actions)) + return; + + if (!test_and_set_bit(action, &ehci->actions)) { + unsigned long t; + + switch (action) { + case TIMER_IO_WATCHDOG: + t = EHCI_IO_JIFFIES; + break; + case TIMER_ASYNC_OFF: + t = EHCI_ASYNC_JIFFIES; + break; + /* case TIMER_ASYNC_SHRINK: */ + default: + /* add a jiffie since we synch against the + * 8 KHz uframe counter. + */ + t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1; + break; + } + mod_timer(&ehci->watchdog, t + jiffies); + } +} + +/*-------------------------------------------------------------------------*/ + /* * handshake - spin reading hc until handshake completes or fails * @ptr: address of hc register to be read diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 262b00c9b33..0042deb671d 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -190,40 +190,6 @@ timer_action_done (struct ehci_hcd *ehci, enum ehci_timer_action action) clear_bit (action, &ehci->actions); } -static inline void -timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) -{ - /* Don't override timeouts which shrink or (later) disable - * the async ring; just the I/O watchdog. Note that if a - * SHRINK were pending, OFF would never be requested. - */ - if (timer_pending(&ehci->watchdog) - && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF)) - & ehci->actions)) - return; - - if (!test_and_set_bit (action, &ehci->actions)) { - unsigned long t; - - switch (action) { - case TIMER_IO_WATCHDOG: - t = EHCI_IO_JIFFIES; - break; - case TIMER_ASYNC_OFF: - t = EHCI_ASYNC_JIFFIES; - break; - // case TIMER_ASYNC_SHRINK: - default: - /* add a jiffie since we synch against the - * 8 KHz uframe counter. - */ - t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1; - break; - } - mod_timer(&ehci->watchdog, t + jiffies); - } -} - static void free_cached_itd_list(struct ehci_hcd *ehci); /*-------------------------------------------------------------------------*/ -- GitLab From 1f4159c1620f74377e26d8a569d10ca5907ef475 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Wed, 11 Feb 2009 09:54:31 +0200 Subject: [PATCH 4326/4982] USB: fix USB_STORAGE_CYPRESS_ATACB commit 64a87b24: [SCSI] Let scsi_cmnd->cmnd use request->cmd buffer changed the scsi_eh_prep_cmnd logic by making it clear the ->cmnd buffer. But the sat to cypress atacb translation supposed the ->cmnd buffer wasn't modified. This patch makes it set the ->cmnd buffer after scsi_eh_prep_cmnd call. The problem and a fix was reported by Matthieu CASTET It also removes all the hackery fiddling of scsi_cmnd and scsi_eh_save by requesting from scsi_eh_prep_cmnd to prepare a read into ->sense_buffer, which is much more suitable a buffer for HW transfers, then after the command execution the regs read is copied into regs buffer before actual preparation of sense_buffer. Also fix an alien comment character to my utf-8 editor. Signed-off-by: Boaz Harrosh Signed-off-by: Matthieu CASTET Cc: stable Cc: James Bottomley Cc: Matthew Dharm Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/cypress_atacb.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c index 898e67d30e5..9466a99baab 100644 --- a/drivers/usb/storage/cypress_atacb.c +++ b/drivers/usb/storage/cypress_atacb.c @@ -133,19 +133,18 @@ void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us) /* build the command for * reading the ATA registers */ - scsi_eh_prep_cmnd(srb, &ses, NULL, 0, 0); - srb->sdb.length = sizeof(regs); - sg_init_one(&ses.sense_sgl, regs, srb->sdb.length); - srb->sdb.table.sgl = &ses.sense_sgl; - srb->sc_data_direction = DMA_FROM_DEVICE; - srb->sdb.table.nents = 1; + scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sizeof(regs)); + /* we use the same command as before, but we set * the read taskfile bit, for not executing atacb command, * but reading register selected in srb->cmnd[4] */ + srb->cmd_len = 16; + srb->cmnd = ses.cmnd; srb->cmnd[2] = 1; usb_stor_transparent_scsi_command(srb, us); + memcpy(regs, srb->sense_buffer, sizeof(regs)); tmp_result = srb->result; scsi_eh_restore_cmnd(srb, &ses); /* we fail to get registers, report invalid command */ @@ -162,8 +161,8 @@ void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us) /* XXX we should generate sk, asc, ascq from status and error * regs - * (see 11.1 Error translation ­ ATA device error to SCSI error map) - * and ata_to_sense_error from libata. + * (see 11.1 Error translation ATA device error to SCSI error + * map, and ata_to_sense_error from libata.) */ /* Sense data is current and format is descriptor. */ -- GitLab From a2c2706e1043c17139c2dafd171c4a5cf008ef7e Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 10 Feb 2009 10:16:58 -0500 Subject: [PATCH 4327/4982] USB: EHCI: add software retry for transaction errors This patch (as1204) adds a software retry mechanism to ehci-hcd. It gets invoked when the driver encounters transaction errors on an asynchronous endpoint. On many systems, hardware deficiencies cause such errors to occur if one device is unplugged while the host is communicating with another device. With the patch, the failed transactions are retried and generally succeed the second or third time through. This is based on code originally written by Koichiro Saito. Signed-off-by: Alan Stern Tested by: Koichiro Saito CC: David Brownell Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-q.c | 32 ++++++++++++++++++++++++++++++++ drivers/usb/host/ehci.h | 3 +++ 2 files changed, 35 insertions(+) diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index ecc9b66c03c..01132ac74eb 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -333,12 +333,40 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) token = hc32_to_cpu(ehci, qtd->hw_token); /* always clean up qtds the hc de-activated */ + retry_xacterr: if ((token & QTD_STS_ACTIVE) == 0) { /* on STALL, error, and short reads this urb must * complete and all its qtds must be recycled. */ if ((token & QTD_STS_HALT) != 0) { + + /* retry transaction errors until we + * reach the software xacterr limit + */ + if ((token & QTD_STS_XACT) && + QTD_CERR(token) == 0 && + --qh->xacterrs > 0 && + !urb->unlinked) { + ehci_dbg(ehci, + "detected XactErr len %d/%d retry %d\n", + qtd->length - QTD_LENGTH(token), qtd->length, + QH_XACTERR_MAX - qh->xacterrs); + + /* reset the token in the qtd and the + * qh overlay (which still contains + * the qtd) so that we pick up from + * where we left off + */ + token &= ~QTD_STS_HALT; + token |= QTD_STS_ACTIVE | + (EHCI_TUNE_CERR << 10); + qtd->hw_token = cpu_to_hc32(ehci, + token); + wmb(); + qh->hw_token = cpu_to_hc32(ehci, token); + goto retry_xacterr; + } stopped = 1; /* magic dummy for some short reads; qh won't advance. @@ -421,6 +449,9 @@ halt: /* remove qtd; it's recycled after possible urb completion */ list_del (&qtd->qtd_list); last = qtd; + + /* reinit the xacterr counter for the next qtd */ + qh->xacterrs = QH_XACTERR_MAX; } /* last urb's completion might still need calling */ @@ -862,6 +893,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) head->qh_next.qh = qh; head->hw_next = dma; + qh->xacterrs = QH_XACTERR_MAX; qh->qh_state = QH_STATE_LINKED; /* qtd completions reported later by interrupt */ } diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 0042deb671d..9aba560fd56 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -342,6 +342,9 @@ struct ehci_qh { #define QH_STATE_UNLINK_WAIT 4 /* LINKED and on reclaim q */ #define QH_STATE_COMPLETING 5 /* don't touch token.HALT */ + u8 xacterrs; /* XactErr retry counter */ +#define QH_XACTERR_MAX 32 /* XactErr retry limit */ + /* periodic schedule info */ u8 usecs; /* intr bandwidth */ u8 gap_uf; /* uframes split/csplit gap */ -- GitLab From f9031f2c4237abfe75d9ad33f5c0f0dde96f7d09 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Tue, 10 Feb 2009 16:55:45 +0000 Subject: [PATCH 4328/4982] USB: Make the isp1760_register function prototype more generic The patch changes the prototype of the isp1760_register() function to use predefined types like phys_addr_t and resource_size_t rather than u64 Signed-off-by: Catalin Marinas Cc: Sebastian Siewior Cc: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1760-hcd.c | 7 ++++--- drivers/usb/host/isp1760-hcd.h | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index b899f1a59c2..8ee2f415984 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -2235,9 +2235,10 @@ void deinit_kmem_cache(void) kmem_cache_destroy(qh_cachep); } -struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq, - u64 irqflags, struct device *dev, const char *busname, - unsigned int devflags) +struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, + int irq, unsigned long irqflags, + struct device *dev, const char *busname, + unsigned int devflags) { struct usb_hcd *hcd; struct isp1760_hcd *priv; diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h index a9daea58796..462f4943cb1 100644 --- a/drivers/usb/host/isp1760-hcd.h +++ b/drivers/usb/host/isp1760-hcd.h @@ -2,9 +2,10 @@ #define _ISP1760_HCD_H_ /* exports for if */ -struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq, - u64 irqflags, struct device *dev, const char *busname, - unsigned int devflags); +struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, + int irq, unsigned long irqflags, + struct device *dev, const char *busname, + unsigned int devflags); int init_kmem_once(void); void deinit_kmem_cache(void); -- GitLab From f7e7aa5850839faa5eb7c7c177da5fd6bca8949b Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Tue, 10 Feb 2009 16:55:51 +0000 Subject: [PATCH 4329/4982] USB: Add platform device support for the ISP1760 USB chip Currently, the driver only supports PCI and PPC_OF but there are boards like ARM RealView where this is a platform device. The patch adds the necessary functions and registration to the isp1760-if.c file and modifies the corresponding Makefile and Kconfig to be able to use this driver even if PCI and PPC_OF are not enabled. Signed-off-by: Catalin Marinas Cc: Sebastian Siewior Cc: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/usb/Makefile | 1 + drivers/usb/host/Kconfig | 2 +- drivers/usb/host/isp1760-if.c | 95 +++++++++++++++++++++++++++++------ 3 files changed, 81 insertions(+), 17 deletions(-) diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index b2ceb4aff23..89299a5ce16 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_USB_SL811_HCD) += host/ obj-$(CONFIG_USB_U132_HCD) += host/ obj-$(CONFIG_USB_R8A66597_HCD) += host/ obj-$(CONFIG_USB_HWA_HCD) += host/ +obj-$(CONFIG_USB_ISP1760_HCD) += host/ obj-$(CONFIG_USB_C67X00_HCD) += c67x00/ diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index c1cfed7eefb..845479f7c70 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -120,7 +120,7 @@ config USB_ISP116X_HCD config USB_ISP1760_HCD tristate "ISP 1760 HCD support" - depends on USB && EXPERIMENTAL && (PCI || PPC_OF) + depends on USB && EXPERIMENTAL ---help--- The ISP1760 chip is a USB 2.0 host controller. diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index 4cf7ca428b3..3fa3a170279 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -10,6 +10,7 @@ #include #include +#include #include "../core/hcd.h" #include "isp1760-hcd.h" @@ -300,39 +301,101 @@ static struct pci_driver isp1761_pci_driver = { }; #endif +static int __devinit isp1760_plat_probe(struct platform_device *pdev) +{ + int ret = 0; + struct usb_hcd *hcd; + struct resource *mem_res; + struct resource *irq_res; + resource_size_t mem_size; + unsigned long irqflags = IRQF_SHARED | IRQF_DISABLED; + + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem_res) { + pr_warning("isp1760: Memory resource not available\n"); + ret = -ENODEV; + goto out; + } + mem_size = resource_size(mem_res); + if (!request_mem_region(mem_res->start, mem_size, "isp1760")) { + pr_warning("isp1760: Cannot reserve the memory resource\n"); + ret = -EBUSY; + goto out; + } + + irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!irq_res) { + pr_warning("isp1760: IRQ resource not available\n"); + return -ENODEV; + } + irqflags |= irq_res->flags & IRQF_TRIGGER_MASK; + + hcd = isp1760_register(mem_res->start, mem_size, irq_res->start, + irqflags, &pdev->dev, dev_name(&pdev->dev), 0); + if (IS_ERR(hcd)) { + pr_warning("isp1760: Failed to register the HCD device\n"); + ret = -ENODEV; + goto cleanup; + } + + pr_info("ISP1760 USB device initialised\n"); + return ret; + +cleanup: + release_mem_region(mem_res->start, mem_size); +out: + return ret; +} + +static int __devexit isp1760_plat_remove(struct platform_device *pdev) +{ + struct resource *mem_res; + resource_size_t mem_size; + + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mem_size = resource_size(mem_res); + release_mem_region(mem_res->start, mem_size); + + return 0; +} + +static struct platform_driver isp1760_plat_driver = { + .probe = isp1760_plat_probe, + .remove = isp1760_plat_remove, + .driver = { + .name = "isp1760", + }, +}; + static int __init isp1760_init(void) { - int ret; + int ret, any_ret = -ENODEV; init_kmem_once(); + ret = platform_driver_register(&isp1760_plat_driver); + if (!ret) + any_ret = 0; #ifdef CONFIG_PPC_OF ret = of_register_platform_driver(&isp1760_of_driver); - if (ret) { - deinit_kmem_cache(); - return ret; - } + if (!ret) + any_ret = 0; #endif #ifdef CONFIG_PCI ret = pci_register_driver(&isp1761_pci_driver); - if (ret) - goto unreg_of; + if (!ret) + any_ret = 0; #endif - return ret; -#ifdef CONFIG_PCI -unreg_of: -#endif -#ifdef CONFIG_PPC_OF - of_unregister_platform_driver(&isp1760_of_driver); -#endif - deinit_kmem_cache(); - return ret; + if (any_ret) + deinit_kmem_cache(); + return any_ret; } module_init(isp1760_init); static void __exit isp1760_exit(void) { + platform_driver_unregister(&isp1760_plat_driver); #ifdef CONFIG_PPC_OF of_unregister_platform_driver(&isp1760_of_driver); #endif -- GitLab From 68b44eaed5def7b6490c23c3e88c6f2ccec57beb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 13 Feb 2009 17:25:46 -0800 Subject: [PATCH 4330/4982] USB: serial: add symbol serial driver This is for the Symbol 6608 barcode scanner in a fake "HID" mode. Thanks to Dalibor Grgec for working with me to get this to start to work properly. Cc: Dalibor Grgec Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/Kconfig | 9 + drivers/usb/serial/Makefile | 1 + drivers/usb/serial/symbolserial.c | 340 ++++++++++++++++++++++++++++++ 3 files changed, 350 insertions(+) create mode 100644 drivers/usb/serial/symbolserial.c diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index b361f05cafa..dbc0781a416 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -515,6 +515,15 @@ config USB_SERIAL_SIERRAWIRELESS To compile this driver as a module, choose M here: the module will be called sierra. +config USB_SERIAL_SYMBOL + tristate "USB Symbol Barcode driver (serial mode)" + help + Say Y here if you want to use a Symbol USB Barcode device + in serial emulation mode. + + To compile this driver as a module, choose M here: the + module will be called symbolserial. + config USB_SERIAL_TI tristate "USB TI 3410/5052 Serial Driver" help diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index b75be91eb8f..222939739ff 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI) += siemens_mpi.o obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o obj-$(CONFIG_USB_SERIAL_SPCP8X5) += spcp8x5.o +obj-$(CONFIG_USB_SERIAL_SYMBOL) += symbolserial.o obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c new file mode 100644 index 00000000000..c5990fd88e2 --- /dev/null +++ b/drivers/usb/serial/symbolserial.c @@ -0,0 +1,340 @@ +/* + * Symbol USB barcode to serial driver + * + * Copyright (C) 2009 Greg Kroah-Hartman + * Copyright (C) 2009 Novell Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int debug; + +static struct usb_device_id id_table[] = { + { USB_DEVICE(0x05e0, 0x0600) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table); + +/* This structure holds all of the individual device information */ +struct symbol_private { + struct usb_device *udev; + struct usb_serial *serial; + struct usb_serial_port *port; + unsigned char *int_buffer; + struct urb *int_urb; + int buffer_size; + u8 bInterval; + u8 int_address; + spinlock_t lock; /* protects the following flags */ + bool throttled; + bool actually_throttled; + bool rts; +}; + +static void symbol_int_callback(struct urb *urb) +{ + struct symbol_private *priv = urb->context; + unsigned char *data = urb->transfer_buffer; + struct usb_serial_port *port = priv->port; + int status = urb->status; + struct tty_struct *tty; + int result; + int available_room = 0; + int data_length; + + dbg("%s - port %d", __func__, port->number); + + switch (status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", + __func__, status); + return; + default: + dbg("%s - nonzero urb status received: %d", + __func__, status); + goto exit; + } + + usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, + data); + + if (urb->actual_length > 1) { + data_length = urb->actual_length - 1; + + /* + * Data from the device comes with a 1 byte header: + * + * data... + * This is real data to be sent to the tty layer + * we pretty much just ignore the size and send everything + * else to the tty layer. + */ + tty = tty_port_tty_get(&port->port); + if (tty) { + available_room = tty_buffer_request_room(tty, + data_length); + if (available_room) { + tty_insert_flip_string(tty, &data[1], + available_room); + tty_flip_buffer_push(tty); + } + tty_kref_put(tty); + } + } else { + dev_dbg(&priv->udev->dev, + "Improper ammount of data received from the device, " + "%d bytes", urb->actual_length); + } + +exit: + spin_lock(&priv->lock); + + /* Continue trying to always read if we should */ + if (!priv->throttled) { + usb_fill_int_urb(priv->int_urb, priv->udev, + usb_rcvintpipe(priv->udev, + priv->int_address), + priv->int_buffer, priv->buffer_size, + symbol_int_callback, priv, priv->bInterval); + result = usb_submit_urb(priv->int_urb, GFP_ATOMIC); + if (result) + dev_err(&port->dev, + "%s - failed resubmitting read urb, error %d\n", + __func__, result); + } else + priv->actually_throttled = true; + spin_unlock(&priv->lock); +} + +static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) +{ + struct symbol_private *priv = usb_get_serial_data(port->serial); + unsigned long flags; + int result = 0; + + dbg("%s - port %d", __func__, port->number); + + spin_lock_irqsave(&priv->lock, flags); + priv->throttled = false; + priv->actually_throttled = false; + priv->port = port; + spin_unlock_irqrestore(&priv->lock, flags); + + /* + * Force low_latency on so that our tty_push actually forces the data + * through, otherwise it is scheduled, and with high data rates (like + * with OHCI) data can get lost. + */ + if (tty) + tty->low_latency = 1; + + /* Start reading from the device */ + usb_fill_int_urb(priv->int_urb, priv->udev, + usb_rcvintpipe(priv->udev, priv->int_address), + priv->int_buffer, priv->buffer_size, + symbol_int_callback, priv, priv->bInterval); + result = usb_submit_urb(priv->int_urb, GFP_KERNEL); + if (result) + dev_err(&port->dev, + "%s - failed resubmitting read urb, error %d\n", + __func__, result); + return result; +} + +static void symbol_close(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) +{ + struct symbol_private *priv = usb_get_serial_data(port->serial); + + dbg("%s - port %d", __func__, port->number); + + /* shutdown our urbs */ + usb_kill_urb(priv->int_urb); +} + +static void symbol_throttle(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + struct symbol_private *priv = usb_get_serial_data(port->serial); + unsigned long flags; + + dbg("%s - port %d", __func__, port->number); + spin_lock_irqsave(&priv->lock, flags); + priv->throttled = true; + spin_unlock_irqrestore(&priv->lock, flags); +} + +static void symbol_unthrottle(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + struct symbol_private *priv = usb_get_serial_data(port->serial); + unsigned long flags; + int result; + + dbg("%s - port %d", __func__, port->number); + + spin_lock_irqsave(&priv->lock, flags); + priv->throttled = false; + priv->actually_throttled = false; + spin_unlock_irqrestore(&priv->lock, flags); + + priv->int_urb->dev = port->serial->dev; + result = usb_submit_urb(priv->int_urb, GFP_ATOMIC); + if (result) + dev_err(&port->dev, + "%s - failed submitting read urb, error %d\n", + __func__, result); +} + +static int symbol_startup(struct usb_serial *serial) +{ + struct symbol_private *priv; + struct usb_host_interface *intf; + int i; + int retval = -ENOMEM; + bool int_in_found = false; + + /* create our private serial structure */ + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (priv == NULL) { + dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__); + return -ENOMEM; + } + spin_lock_init(&priv->lock); + priv->serial = serial; + priv->port = serial->port[0]; + priv->udev = serial->dev; + + /* find our interrupt endpoint */ + intf = serial->interface->altsetting; + for (i = 0; i < intf->desc.bNumEndpoints; ++i) { + struct usb_endpoint_descriptor *endpoint; + + endpoint = &intf->endpoint[i].desc; + if (!usb_endpoint_is_int_in(endpoint)) + continue; + + priv->int_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!priv->int_urb) { + dev_err(&priv->udev->dev, "out of memory\n"); + goto error; + } + + priv->buffer_size = le16_to_cpu(endpoint->wMaxPacketSize) * 2; + priv->int_buffer = kmalloc(priv->buffer_size, GFP_KERNEL); + if (!priv->int_buffer) { + dev_err(&priv->udev->dev, "out of memory\n"); + goto error; + } + + priv->int_address = endpoint->bEndpointAddress; + priv->bInterval = endpoint->bInterval; + + /* set up our int urb */ + usb_fill_int_urb(priv->int_urb, priv->udev, + usb_rcvintpipe(priv->udev, + endpoint->bEndpointAddress), + priv->int_buffer, priv->buffer_size, + symbol_int_callback, priv, priv->bInterval); + + int_in_found = true; + break; + } + + if (!int_in_found) { + dev_err(&priv->udev->dev, + "Error - the proper endpoints were not found!\n"); + goto error; + } + + usb_set_serial_data(serial, priv); + return 0; + +error: + usb_free_urb(priv->int_urb); + kfree(priv->int_buffer); + kfree(priv); + return retval; +} + +static void symbol_shutdown(struct usb_serial *serial) +{ + struct symbol_private *priv = usb_get_serial_data(serial); + + dbg("%s", __func__); + + usb_kill_urb(priv->int_urb); + usb_free_urb(priv->int_urb); + kfree(priv->int_buffer); + kfree(priv); + usb_set_serial_data(serial, NULL); +} + +static struct usb_driver symbol_driver = { + .name = "symbol", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table, + .no_dynamic_id = 1, +}; + +static struct usb_serial_driver symbol_device = { + .driver = { + .owner = THIS_MODULE, + .name = "symbol", + }, + .id_table = id_table, + .usb_driver = &symbol_driver, + .num_ports = 1, + .attach = symbol_startup, + .open = symbol_open, + .close = symbol_close, + .shutdown = symbol_shutdown, + .throttle = symbol_throttle, + .unthrottle = symbol_unthrottle, +}; + +static int __init symbol_init(void) +{ + int retval; + + retval = usb_serial_register(&symbol_device); + if (retval) + return retval; + retval = usb_register(&symbol_driver); + if (retval) + usb_serial_deregister(&symbol_device); + return retval; +} + +static void __exit symbol_exit(void) +{ + usb_deregister(&symbol_driver); + usb_serial_deregister(&symbol_device); +} + +module_init(symbol_init); +module_exit(symbol_exit); +MODULE_LICENSE("GPL"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug enabled or not"); -- GitLab From 3d940b7d27c5fec35de66449836ab9a01575447c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 20 Mar 2009 20:26:30 -0700 Subject: [PATCH 4331/4982] USB: symbolserial: log the ioctl commands We need to figure out what userspace programs are expecting from this driver, so log them so we can try to get it right. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/symbolserial.c | 59 +++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index c5990fd88e2..8b3cbc87adc 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c @@ -205,6 +205,62 @@ static void symbol_unthrottle(struct tty_struct *tty) __func__, result); } +static int symbol_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct usb_serial_port *port = tty->driver_data; + struct device *dev = &port->dev; + + /* + * Right now we need to figure out what commands + * most userspace tools want to see for this driver, + * so just log the things. + */ + switch (cmd) { + case TIOCSERGETLSR: + dev_info(dev, "%s: TIOCSERGETLSR\n", __func__); + break; + + case TIOCGSERIAL: + dev_info(dev, "%s: TIOCGSERIAL\n", __func__); + break; + + case TIOCMIWAIT: + dev_info(dev, "%s: TIOCMIWAIT\n", __func__); + break; + + case TIOCGICOUNT: + dev_info(dev, "%s: TIOCGICOUNT\n", __func__); + break; + default: + dev_info(dev, "%s: unknown (%d)\n", __func__, cmd); + } + return -ENOIOCTLCMD; +} + +static int symbol_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct usb_serial_port *port = tty->driver_data; + struct device *dev = &port->dev; + + /* TODO */ + /* probably just need to shadow whatever was sent to us here */ + dev_info(dev, "%s\n", __func__); + return 0; +} + +static int symbol_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + struct usb_serial_port *port = tty->driver_data; + struct device *dev = &port->dev; + + /* TODO */ + /* probably just need to shadow whatever was sent to us here */ + dev_info(dev, "%s\n", __func__); + return 0; +} + static int symbol_startup(struct usb_serial *serial) { struct symbol_private *priv; @@ -311,6 +367,9 @@ static struct usb_serial_driver symbol_device = { .shutdown = symbol_shutdown, .throttle = symbol_throttle, .unthrottle = symbol_unthrottle, + .ioctl = symbol_ioctl, + .tiocmget = symbol_tiocmget, + .tiocmset = symbol_tiocmset, }; static int __init symbol_init(void) -- GitLab From a78b42824dd7c2b40d72fb01f1b1842f7e845f3a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 17 Feb 2009 22:39:56 -0800 Subject: [PATCH 4332/4982] USB: serial: add qualcomm wireless modem driver Driver originally written by Qualcomm, but rewritten by me due to the totally different coding style. Cleaned up the probe logic to make a bit more sense, this is one wierd device. They could have prevented all of this by just writing sane firmware for the modem. Cc: Tamm Liu Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/Kconfig | 9 +++ drivers/usb/serial/Makefile | 1 + drivers/usb/serial/qcserial.c | 145 ++++++++++++++++++++++++++++++++++ 3 files changed, 155 insertions(+) create mode 100644 drivers/usb/serial/qcserial.c diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index dbc0781a416..4afe73e8ec4 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -472,6 +472,15 @@ config USB_SERIAL_OTI6858 To compile this driver as a module, choose M here: the module will be called oti6858. +config USB_SERIAL_QUALCOMM + tristate "USB Qualcomm Serial modem" + help + Say Y here if you have a Qualcomm USB modem device. These are + usually wireless cellular modems. + + To compile this driver as a module, choose M here: the + module will be called qcserial. + config USB_SERIAL_SPCP8X5 tristate "USB SPCP8x5 USB To Serial Driver" help diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 222939739ff..94043babe1d 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_USB_SERIAL_OPTICON) += opticon.o obj-$(CONFIG_USB_SERIAL_OPTION) += option.o obj-$(CONFIG_USB_SERIAL_OTI6858) += oti6858.o obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o +obj-$(CONFIG_USB_SERIAL_QUALCOMM) += qcserial.o obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI) += siemens_mpi.o obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c new file mode 100644 index 00000000000..6c6add50fea --- /dev/null +++ b/drivers/usb/serial/qcserial.c @@ -0,0 +1,145 @@ +/* + * Qualcomm Serial USB driver + * + * Copyright (c) 2008 QUALCOMM Incorporated. + * Copyright (c) 2009 Greg Kroah-Hartman + * Copyright (c) 2009 Novell Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include + +#define DRIVER_AUTHOR "Qualcomm Inc" +#define DRIVER_DESC "Qualcomm USB Serial driver" + +static int debug; + +static struct usb_device_id id_table[] = { + {USB_DEVICE(0x05c6, 0x9211)}, /* Acer Gobi QDL device */ + {USB_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, id_table); + +static struct usb_driver qcdriver = { + .name = "qcserial", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table, + .suspend = usb_serial_suspend, + .resume = usb_serial_resume, + .supports_autosuspend = true, +}; + +static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) +{ + int retval = -ENODEV; + __u8 nintf; + __u8 ifnum; + + dbg("%s", __func__); + + nintf = serial->dev->actconfig->desc.bNumInterfaces; + dbg("Num Interfaces = %d", nintf); + ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber; + dbg("This Interface = %d", ifnum); + + switch (nintf) { + case 1: + /* QDL mode */ + if (serial->interface->num_altsetting == 2) { + struct usb_host_interface *intf; + + intf = &serial->interface->altsetting[1]; + if (intf->desc.bNumEndpoints == 2) { + if (usb_endpoint_is_bulk_in(&intf->endpoint[0].desc) && + usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) { + dbg("QDL port found"); + retval = usb_set_interface(serial->dev, ifnum, 1); + if (retval < 0) { + dev_err(&serial->dev->dev, + "Could not set interface, error %d\n", + retval); + retval = -ENODEV; + } + return retval; + } + } + } + break; + + case 4: + /* Composite mode */ + if (ifnum == 2) { + dbg("Modem port found"); + retval = usb_set_interface(serial->dev, ifnum, 0); + if (retval < 0) { + dev_err(&serial->dev->dev, + "Could not set interface, error %d\n", + retval); + retval = -ENODEV; + } + return retval; + } + break; + + default: + dev_err(&serial->dev->dev, + "unknown number of interfaces: %d\n", nintf); + return -ENODEV; + } + + return retval; +} + +static struct usb_serial_driver qcdevice = { + .driver = { + .owner = THIS_MODULE, + .name = "qcserial", + }, + .description = "Qualcomm USB modem", + .id_table = id_table, + .usb_driver = &qcdriver, + .num_ports = 1, + .probe = qcprobe, +}; + +static int __init qcinit(void) +{ + int retval; + + retval = usb_serial_register(&qcdevice); + if (retval) + return retval; + + retval = usb_register(&qcdriver); + if (retval) { + usb_serial_deregister(&qcdevice); + return retval; + } + + return 0; +} + +static void __exit qcexit(void) +{ + usb_deregister(&qcdriver); + usb_serial_deregister(&qcdevice); +} + +module_init(qcinit); +module_exit(qcexit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL v2"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug enabled or not"); -- GitLab From 551509d267905705f6d723e51ec706916f06b859 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 11 Feb 2009 14:11:36 -0800 Subject: [PATCH 4333/4982] USB: replace uses of __constant_{endian} The base versions handle constant folding now. Signed-off-by: Harvey Harrison Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 2 +- drivers/usb/core/hub.c | 8 ++++---- drivers/usb/gadget/amd5536udc.c | 2 +- drivers/usb/gadget/atmel_usba_udc.c | 20 ++++++++++---------- drivers/usb/gadget/cdc2.c | 8 ++++---- drivers/usb/gadget/dummy_hcd.c | 2 +- drivers/usb/gadget/epautoconf.c | 2 +- drivers/usb/gadget/ether.c | 8 ++++---- drivers/usb/gadget/f_acm.c | 10 +++++----- drivers/usb/gadget/f_ecm.c | 16 ++++++++-------- drivers/usb/gadget/f_loopback.c | 4 ++-- drivers/usb/gadget/f_obex.c | 8 ++++---- drivers/usb/gadget/f_phonet.c | 8 ++++---- drivers/usb/gadget/f_rndis.c | 10 +++++----- drivers/usb/gadget/f_serial.c | 4 ++-- drivers/usb/gadget/f_sourcesink.c | 4 ++-- drivers/usb/gadget/f_subset.c | 14 +++++++------- drivers/usb/gadget/file_storage.c | 22 +++++++++++----------- drivers/usb/gadget/gmidi.c | 16 ++++++++-------- drivers/usb/gadget/goku_udc.c | 8 ++++---- drivers/usb/gadget/inode.c | 4 ++-- drivers/usb/gadget/net2280.c | 16 ++++++++-------- drivers/usb/gadget/printer.c | 18 +++++++++--------- drivers/usb/gadget/serial.c | 12 ++++++------ drivers/usb/gadget/u_serial.c | 2 +- drivers/usb/gadget/zero.c | 8 ++++---- drivers/usb/host/ehci-sched.c | 2 +- drivers/usb/host/ehci.h | 2 +- drivers/usb/host/isp1760-hcd.c | 4 ++-- drivers/usb/host/oxu210hp-hcd.c | 22 +++++++++++----------- drivers/usb/host/oxu210hp.h | 8 ++++---- drivers/usb/host/uhci-hcd.h | 10 +++++----- drivers/usb/host/uhci-q.c | 10 +++++----- drivers/usb/image/mdc800.c | 8 ++++---- drivers/usb/musb/musb_virthub.c | 2 +- 35 files changed, 152 insertions(+), 152 deletions(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 3c711db55d8..0eee32a65e2 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -901,7 +901,7 @@ static int register_root_hub(struct usb_hcd *hcd) mutex_lock(&usb_bus_list_lock); - usb_dev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64); + usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE); if (retval != sizeof usb_dev->descriptor) { mutex_unlock(&usb_bus_list_lock); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index cd50d86029e..7e33d63ab92 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2471,20 +2471,20 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, */ switch (udev->speed) { case USB_SPEED_VARIABLE: /* fixed at 512 */ - udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(512); + udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512); break; case USB_SPEED_HIGH: /* fixed at 64 */ - udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64); + udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); break; case USB_SPEED_FULL: /* 8, 16, 32, or 64 */ /* to determine the ep0 maxpacket size, try to read * the device descriptor to get bMaxPacketSize0 and * then correct our initial guess. */ - udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64); + udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); break; case USB_SPEED_LOW: /* fixed at 8 */ - udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(8); + udev->ep0.desc.wMaxPacketSize = cpu_to_le16(8); break; default: goto fail; diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index abf8192f89e..826f3adde5d 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -551,7 +551,7 @@ udc_alloc_request(struct usb_ep *usbep, gfp_t gfp) dma_desc->status = AMD_ADDBITS(dma_desc->status, UDC_DMA_STP_STS_BS_HOST_BUSY, UDC_DMA_STP_STS_BS); - dma_desc->bufptr = __constant_cpu_to_le32(DMA_DONT_USE); + dma_desc->bufptr = cpu_to_le32(DMA_DONT_USE); req->td_data = dma_desc; req->td_data_last = NULL; req->chain_len = 1; diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index 65b03e3445a..c22fab16411 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -1017,7 +1017,7 @@ static struct usb_endpoint_descriptor usba_ep0_desc = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = 0, .bmAttributes = USB_ENDPOINT_XFER_CONTROL, - .wMaxPacketSize = __constant_cpu_to_le16(64), + .wMaxPacketSize = cpu_to_le16(64), /* FIXME: I have no idea what to put here */ .bInterval = 1, }; @@ -1207,21 +1207,21 @@ static int do_test_mode(struct usba_udc *udc) /* Avoid overly long expressions */ static inline bool feature_is_dev_remote_wakeup(struct usb_ctrlrequest *crq) { - if (crq->wValue == __constant_cpu_to_le16(USB_DEVICE_REMOTE_WAKEUP)) + if (crq->wValue == cpu_to_le16(USB_DEVICE_REMOTE_WAKEUP)) return true; return false; } static inline bool feature_is_dev_test_mode(struct usb_ctrlrequest *crq) { - if (crq->wValue == __constant_cpu_to_le16(USB_DEVICE_TEST_MODE)) + if (crq->wValue == cpu_to_le16(USB_DEVICE_TEST_MODE)) return true; return false; } static inline bool feature_is_ep_halt(struct usb_ctrlrequest *crq) { - if (crq->wValue == __constant_cpu_to_le16(USB_ENDPOINT_HALT)) + if (crq->wValue == cpu_to_le16(USB_ENDPOINT_HALT)) return true; return false; } @@ -1239,7 +1239,7 @@ static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep, status = cpu_to_le16(udc->devstatus); } else if (crq->bRequestType == (USB_DIR_IN | USB_RECIP_INTERFACE)) { - status = __constant_cpu_to_le16(0); + status = cpu_to_le16(0); } else if (crq->bRequestType == (USB_DIR_IN | USB_RECIP_ENDPOINT)) { struct usba_ep *target; @@ -1250,12 +1250,12 @@ static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep, status = 0; if (is_stalled(udc, target)) - status |= __constant_cpu_to_le16(1); + status |= cpu_to_le16(1); } else goto delegate; /* Write directly to the FIFO. No queueing is done. */ - if (crq->wLength != __constant_cpu_to_le16(sizeof(status))) + if (crq->wLength != cpu_to_le16(sizeof(status))) goto stall; ep->state = DATA_STAGE_IN; __raw_writew(status, ep->fifo); @@ -1274,7 +1274,7 @@ static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep, } else if (crq->bRequestType == USB_RECIP_ENDPOINT) { struct usba_ep *target; - if (crq->wLength != __constant_cpu_to_le16(0) + if (crq->wLength != cpu_to_le16(0) || !feature_is_ep_halt(crq)) goto stall; target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex)); @@ -1308,7 +1308,7 @@ static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep, } else if (crq->bRequestType == USB_RECIP_ENDPOINT) { struct usba_ep *target; - if (crq->wLength != __constant_cpu_to_le16(0) + if (crq->wLength != cpu_to_le16(0) || !feature_is_ep_halt(crq)) goto stall; @@ -1514,7 +1514,7 @@ restart: */ ep->state = DATA_STAGE_IN; } else { - if (crq.crq.wLength != __constant_cpu_to_le16(0)) + if (crq.crq.wLength != cpu_to_le16(0)) ep->state = DATA_STAGE_OUT; else ep->state = STATUS_STAGE_IN; diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index 5495b171cf2..928137d3dbd 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c @@ -66,7 +66,7 @@ static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_COMM, .bDeviceSubClass = 0, @@ -74,8 +74,8 @@ static struct usb_device_descriptor device_desc = { /* .bMaxPacketSize0 = f(hardware) */ /* Vendor and product id can be overridden by module parameters. */ - .idVendor = __constant_cpu_to_le16(CDC_VENDOR_NUM), - .idProduct = __constant_cpu_to_le16(CDC_PRODUCT_NUM), + .idVendor = cpu_to_le16(CDC_VENDOR_NUM), + .idProduct = cpu_to_le16(CDC_PRODUCT_NUM), /* .bcdDevice = f(hardware) */ /* .iManufacturer = DYNAMIC */ /* .iProduct = DYNAMIC */ @@ -193,7 +193,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev) gadget->name, cdc_config_driver.label); device_desc.bcdDevice = - __constant_cpu_to_le16(0x0300 | 0x0099); + cpu_to_le16(0x0300 | 0x0099); } diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 9064696636a..3b42888b72f 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -1626,7 +1626,7 @@ static int dummy_hub_control ( hub_descriptor ((struct usb_hub_descriptor *) buf); break; case GetHubStatus: - *(__le32 *) buf = __constant_cpu_to_le32 (0); + *(__le32 *) buf = cpu_to_le32 (0); break; case GetPortStatus: if (wIndex != 1) diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index a36b1175b18..cd0914ec898 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -148,7 +148,7 @@ ep_matches ( return 0; /* BOTH: "high bandwidth" works only at high speed */ - if ((desc->wMaxPacketSize & __constant_cpu_to_le16(3<<11))) { + if ((desc->wMaxPacketSize & cpu_to_le16(3<<11))) { if (!gadget->is_dualspeed) return 0; /* configure your hardware with enough buffering!! */ diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 37252d0012a..d006dc652e0 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -156,7 +156,7 @@ static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16 (0x0200), + .bcdUSB = cpu_to_le16 (0x0200), .bDeviceClass = USB_CLASS_COMM, .bDeviceSubClass = 0, @@ -167,8 +167,8 @@ static struct usb_device_descriptor device_desc = { * we support. (As does bNumConfigurations.) These values can * also be overridden by module parameters. */ - .idVendor = __constant_cpu_to_le16 (CDC_VENDOR_NUM), - .idProduct = __constant_cpu_to_le16 (CDC_PRODUCT_NUM), + .idVendor = cpu_to_le16 (CDC_VENDOR_NUM), + .idProduct = cpu_to_le16 (CDC_PRODUCT_NUM), /* .bcdDevice = f(hardware) */ /* .iManufacturer = DYNAMIC */ /* .iProduct = DYNAMIC */ @@ -318,7 +318,7 @@ static int __init eth_bind(struct usb_composite_dev *cdev) gadget->name, eth_config_driver.label); device_desc.bcdDevice = - __constant_cpu_to_le16(0x0300 | 0x0099); + cpu_to_le16(0x0300 | 0x0099); } diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c index c1d34df0b15..7953948bfe4 100644 --- a/drivers/usb/gadget/f_acm.c +++ b/drivers/usb/gadget/f_acm.c @@ -125,7 +125,7 @@ static struct usb_cdc_header_desc acm_header_desc __initdata = { .bLength = sizeof(acm_header_desc), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, - .bcdCDC = __constant_cpu_to_le16(0x0110), + .bcdCDC = cpu_to_le16(0x0110), }; static struct usb_cdc_call_mgmt_descriptor @@ -159,7 +159,7 @@ static struct usb_endpoint_descriptor acm_fs_notify_desc __initdata = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(GS_NOTIFY_MAXPACKET), + .wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET), .bInterval = 1 << GS_LOG2_NOTIFY_INTERVAL, }; @@ -197,7 +197,7 @@ static struct usb_endpoint_descriptor acm_hs_notify_desc __initdata = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(GS_NOTIFY_MAXPACKET), + .wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET), .bInterval = GS_LOG2_NOTIFY_INTERVAL+4, }; @@ -205,14 +205,14 @@ static struct usb_endpoint_descriptor acm_hs_in_desc __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor acm_hs_out_desc __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *acm_hs_function[] __initdata = { diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c index 4ae579948e5..ecf5bdd0ae0 100644 --- a/drivers/usb/gadget/f_ecm.c +++ b/drivers/usb/gadget/f_ecm.c @@ -130,7 +130,7 @@ static struct usb_cdc_header_desc ecm_header_desc __initdata = { .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, - .bcdCDC = __constant_cpu_to_le16(0x0110), + .bcdCDC = cpu_to_le16(0x0110), }; static struct usb_cdc_union_desc ecm_union_desc __initdata = { @@ -148,9 +148,9 @@ static struct usb_cdc_ether_desc ecm_desc __initdata = { /* this descriptor actually adds value, surprise! */ /* .iMACAddress = DYNAMIC */ - .bmEthernetStatistics = __constant_cpu_to_le32(0), /* no statistics */ - .wMaxSegmentSize = __constant_cpu_to_le16(ETH_FRAME_LEN), - .wNumberMCFilters = __constant_cpu_to_le16(0), + .bmEthernetStatistics = cpu_to_le32(0), /* no statistics */ + .wMaxSegmentSize = cpu_to_le16(ETH_FRAME_LEN), + .wNumberMCFilters = cpu_to_le16(0), .bNumberPowerFilters = 0, }; @@ -192,7 +192,7 @@ static struct usb_endpoint_descriptor fs_ecm_notify_desc __initdata = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(ECM_STATUS_BYTECOUNT), + .wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT), .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC, }; @@ -236,7 +236,7 @@ static struct usb_endpoint_descriptor hs_ecm_notify_desc __initdata = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(ECM_STATUS_BYTECOUNT), + .wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT), .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4, }; static struct usb_endpoint_descriptor hs_ecm_in_desc __initdata = { @@ -245,7 +245,7 @@ static struct usb_endpoint_descriptor hs_ecm_in_desc __initdata = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor hs_ecm_out_desc __initdata = { @@ -254,7 +254,7 @@ static struct usb_endpoint_descriptor hs_ecm_out_desc __initdata = { .bEndpointAddress = USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *ecm_hs_function[] __initdata = { diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c index 8affe1dfc2c..83301bdcdd1 100644 --- a/drivers/usb/gadget/f_loopback.c +++ b/drivers/usb/gadget/f_loopback.c @@ -100,7 +100,7 @@ static struct usb_endpoint_descriptor hs_loop_source_desc = { .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor hs_loop_sink_desc = { @@ -108,7 +108,7 @@ static struct usb_endpoint_descriptor hs_loop_sink_desc = { .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *hs_loopback_descs[] = { diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c index 38aa896cc5d..46d6266f30e 100644 --- a/drivers/usb/gadget/f_obex.c +++ b/drivers/usb/gadget/f_obex.c @@ -123,7 +123,7 @@ static struct usb_cdc_header_desc obex_cdc_header_desc __initdata = { .bLength = sizeof(obex_cdc_header_desc), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, - .bcdCDC = __constant_cpu_to_le16(0x0120), + .bcdCDC = cpu_to_le16(0x0120), }; static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = { @@ -138,7 +138,7 @@ static struct usb_cdc_obex_desc obex_desc __initdata = { .bLength = sizeof(obex_desc), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_OBEX_TYPE, - .bcdVersion = __constant_cpu_to_le16(0x0100), + .bcdVersion = cpu_to_le16(0x0100), }; /* High-Speed Support */ @@ -149,7 +149,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = { .bEndpointAddress = USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = { @@ -158,7 +158,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *hs_function[] __initdata = { diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c index c0916c7b217..c1abeb89b41 100644 --- a/drivers/usb/gadget/f_phonet.c +++ b/drivers/usb/gadget/f_phonet.c @@ -79,7 +79,7 @@ pn_header_desc = { .bLength = sizeof pn_header_desc, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, - .bcdCDC = __constant_cpu_to_le16(0x0110), + .bcdCDC = cpu_to_le16(0x0110), }; static const struct usb_cdc_header_desc @@ -87,7 +87,7 @@ pn_phonet_desc = { .bLength = sizeof pn_phonet_desc, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_PHONET_TYPE, - .bcdCDC = __constant_cpu_to_le16(0x1505), /* ??? */ + .bcdCDC = cpu_to_le16(0x1505), /* ??? */ }; static struct usb_cdc_union_desc @@ -138,7 +138,7 @@ pn_hs_sink_desc = { .bEndpointAddress = USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor @@ -157,7 +157,7 @@ pn_hs_source_desc = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *fs_pn_function[] = { diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index fd7b356f902..3279a472604 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -137,7 +137,7 @@ static struct usb_cdc_header_desc header_desc __initdata = { .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, - .bcdCDC = __constant_cpu_to_le16(0x0110), + .bcdCDC = cpu_to_le16(0x0110), }; static struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor __initdata = { @@ -187,7 +187,7 @@ static struct usb_endpoint_descriptor fs_notify_desc __initdata = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT), + .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT), .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC, }; @@ -230,7 +230,7 @@ static struct usb_endpoint_descriptor hs_notify_desc __initdata = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT), + .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT), .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4, }; static struct usb_endpoint_descriptor hs_in_desc __initdata = { @@ -239,7 +239,7 @@ static struct usb_endpoint_descriptor hs_in_desc __initdata = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor hs_out_desc __initdata = { @@ -248,7 +248,7 @@ static struct usb_endpoint_descriptor hs_out_desc __initdata = { .bEndpointAddress = USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *eth_hs_function[] __initdata = { diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c index fe5674db344..db0aa93606e 100644 --- a/drivers/usb/gadget/f_serial.c +++ b/drivers/usb/gadget/f_serial.c @@ -89,14 +89,14 @@ static struct usb_endpoint_descriptor gser_hs_in_desc __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor gser_hs_out_desc __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *gser_hs_function[] __initdata = { diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c index dc84d26d283..6aca5c81414 100644 --- a/drivers/usb/gadget/f_sourcesink.c +++ b/drivers/usb/gadget/f_sourcesink.c @@ -118,7 +118,7 @@ static struct usb_endpoint_descriptor hs_source_desc = { .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor hs_sink_desc = { @@ -126,7 +126,7 @@ static struct usb_endpoint_descriptor hs_sink_desc = { .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *hs_source_sink_descs[] = { diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c index fe183287577..a9c98fdb626 100644 --- a/drivers/usb/gadget/f_subset.c +++ b/drivers/usb/gadget/f_subset.c @@ -108,7 +108,7 @@ static struct usb_cdc_header_desc mdlm_header_desc __initdata = { .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, - .bcdCDC = __constant_cpu_to_le16(0x0110), + .bcdCDC = cpu_to_le16(0x0110), }; static struct usb_cdc_mdlm_desc mdlm_desc __initdata = { @@ -116,7 +116,7 @@ static struct usb_cdc_mdlm_desc mdlm_desc __initdata = { .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_MDLM_TYPE, - .bcdVersion = __constant_cpu_to_le16(0x0100), + .bcdVersion = cpu_to_le16(0x0100), .bGUID = { 0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6, 0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f, @@ -144,9 +144,9 @@ static struct usb_cdc_ether_desc ether_desc __initdata = { /* this descriptor actually adds value, surprise! */ /* .iMACAddress = DYNAMIC */ - .bmEthernetStatistics = __constant_cpu_to_le32(0), /* no statistics */ - .wMaxSegmentSize = __constant_cpu_to_le16(ETH_FRAME_LEN), - .wNumberMCFilters = __constant_cpu_to_le16(0), + .bmEthernetStatistics = cpu_to_le32(0), /* no statistics */ + .wMaxSegmentSize = cpu_to_le16(ETH_FRAME_LEN), + .wNumberMCFilters = cpu_to_le16(0), .bNumberPowerFilters = 0, }; @@ -186,7 +186,7 @@ static struct usb_endpoint_descriptor hs_subset_in_desc __initdata = { .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor hs_subset_out_desc __initdata = { @@ -194,7 +194,7 @@ static struct usb_endpoint_descriptor hs_subset_out_desc __initdata = { .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *hs_eth_function[] __initdata = { diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 1ab9dac7e12..d3c2464dee8 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -847,13 +847,13 @@ device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_PER_INTERFACE, /* The next three values can be overridden by module parameters */ - .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_ID), - .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_ID), - .bcdDevice = __constant_cpu_to_le16(0xffff), + .idVendor = cpu_to_le16(DRIVER_VENDOR_ID), + .idProduct = cpu_to_le16(DRIVER_PRODUCT_ID), + .bcdDevice = cpu_to_le16(0xffff), .iManufacturer = STRING_MANUFACTURER, .iProduct = STRING_PRODUCT, @@ -926,7 +926,7 @@ fs_intr_in_desc = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(2), + .wMaxPacketSize = cpu_to_le16(2), .bInterval = 32, // frames -> 32 ms }; @@ -954,7 +954,7 @@ dev_qualifier = { .bLength = sizeof dev_qualifier, .bDescriptorType = USB_DT_DEVICE_QUALIFIER, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_PER_INTERFACE, .bNumConfigurations = 1, @@ -967,7 +967,7 @@ hs_bulk_in_desc = { /* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */ .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor @@ -977,7 +977,7 @@ hs_bulk_out_desc = { /* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */ .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), .bInterval = 1, // NAK every 1 uframe }; @@ -988,7 +988,7 @@ hs_intr_in_desc = { /* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */ .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(2), + .wMaxPacketSize = cpu_to_le16(2), .bInterval = 9, // 2**(9-1) = 256 uframes -> 32 ms }; @@ -2646,7 +2646,7 @@ static int send_status(struct fsg_dev *fsg) struct bulk_cs_wrap *csw = bh->buf; /* Store and send the Bulk-only CSW */ - csw->Signature = __constant_cpu_to_le32(USB_BULK_CS_SIG); + csw->Signature = cpu_to_le32(USB_BULK_CS_SIG); csw->Tag = fsg->tag; csw->Residue = cpu_to_le32(fsg->residue); csw->Status = status; @@ -3089,7 +3089,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) /* Is the CBW valid? */ if (req->actual != USB_BULK_CB_WRAP_LEN || - cbw->Signature != __constant_cpu_to_le32( + cbw->Signature != cpu_to_le32( USB_BULK_CB_SIG)) { DBG(fsg, "invalid CBW: len %u sig 0x%x\n", req->actual, diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 60d3f9e9b51..bb738bc96d4 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -199,10 +199,10 @@ DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(1); static struct usb_device_descriptor device_desc = { .bLength = USB_DT_DEVICE_SIZE, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_PER_INTERFACE, - .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_NUM), - .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_NUM), + .idVendor = cpu_to_le16(DRIVER_VENDOR_NUM), + .idProduct = cpu_to_le16(DRIVER_PRODUCT_NUM), .iManufacturer = STRING_MANUFACTURER, .iProduct = STRING_PRODUCT, .bNumConfigurations = 1, @@ -241,8 +241,8 @@ static const struct usb_ac_header_descriptor_1 ac_header_desc = { .bLength = USB_DT_AC_HEADER_SIZE(1), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubtype = USB_MS_HEADER, - .bcdADC = __constant_cpu_to_le16(0x0100), - .wTotalLength = __constant_cpu_to_le16(USB_DT_AC_HEADER_SIZE(1)), + .bcdADC = cpu_to_le16(0x0100), + .wTotalLength = cpu_to_le16(USB_DT_AC_HEADER_SIZE(1)), .bInCollection = 1, .baInterfaceNr = { [0] = GMIDI_MS_INTERFACE, @@ -265,8 +265,8 @@ static const struct usb_ms_header_descriptor ms_header_desc = { .bLength = USB_DT_MS_HEADER_SIZE, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubtype = USB_MS_HEADER, - .bcdMSC = __constant_cpu_to_le16(0x0100), - .wTotalLength = __constant_cpu_to_le16(USB_DT_MS_HEADER_SIZE + .bcdMSC = cpu_to_le16(0x0100), + .wTotalLength = cpu_to_le16(USB_DT_MS_HEADER_SIZE + 2*USB_DT_MIDI_IN_SIZE + 2*USB_DT_MIDI_OUT_SIZE(1)), }; @@ -1227,7 +1227,7 @@ autoconf_fail: */ pr_warning("%s: controller '%s' not recognized\n", shortname, gadget->name); - device_desc.bcdDevice = __constant_cpu_to_le16(0x9999); + device_desc.bcdDevice = cpu_to_le16(0x9999); } diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 63419c4d503..de010c939db 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -1472,7 +1472,7 @@ static void ep0_setup(struct goku_udc *dev) /* active endpoint */ if (tmp > 3 || (!dev->ep[tmp].desc && tmp != 0)) goto stall; - if (ctrl.wIndex & __constant_cpu_to_le16( + if (ctrl.wIndex & cpu_to_le16( USB_DIR_IN)) { if (!dev->ep[tmp].is_in) goto stall; @@ -1480,7 +1480,7 @@ static void ep0_setup(struct goku_udc *dev) if (dev->ep[tmp].is_in) goto stall; } - if (ctrl.wValue != __constant_cpu_to_le16( + if (ctrl.wValue != cpu_to_le16( USB_ENDPOINT_HALT)) goto stall; if (tmp) @@ -1493,7 +1493,7 @@ succeed: return; case USB_RECIP_DEVICE: /* device remote wakeup: always clear */ - if (ctrl.wValue != __constant_cpu_to_le16(1)) + if (ctrl.wValue != cpu_to_le16(1)) goto stall; VDBG(dev, "clear dev remote wakeup\n"); goto succeed; @@ -1519,7 +1519,7 @@ succeed: dev->req_config = (ctrl.bRequest == USB_REQ_SET_CONFIGURATION && ctrl.bRequestType == USB_RECIP_DEVICE); if (unlikely(dev->req_config)) - dev->configured = (ctrl.wValue != __constant_cpu_to_le16(0)); + dev->configured = (ctrl.wValue != cpu_to_le16(0)); /* delegate everything to the gadget driver. * it may respond after this irq handler returns. diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 317b48fdbf0..d20937f28a1 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -1334,7 +1334,7 @@ static void make_qualifier (struct dev_data *dev) qual.bLength = sizeof qual; qual.bDescriptorType = USB_DT_DEVICE_QUALIFIER; - qual.bcdUSB = __constant_cpu_to_le16 (0x0200); + qual.bcdUSB = cpu_to_le16 (0x0200); desc = dev->dev; qual.bDeviceClass = desc->bDeviceClass; @@ -1908,7 +1908,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) || dev->dev->bNumConfigurations != 1) goto fail; dev->dev->bNumConfigurations = 1; - dev->dev->bcdUSB = __constant_cpu_to_le16 (0x0200); + dev->dev->bcdUSB = cpu_to_le16 (0x0200); /* triggers gadgetfs_bind(); then we can enumerate. */ spin_unlock_irq (&dev->lock); diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 12c6d83b218..9498be87a72 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -142,8 +142,8 @@ static char *type_string (u8 bmAttributes) #include "net2280.h" -#define valid_bit __constant_cpu_to_le32 (1 << VALID_BIT) -#define dma_done_ie __constant_cpu_to_le32 (1 << DMA_DONE_INTERRUPT_ENABLE) +#define valid_bit cpu_to_le32 (1 << VALID_BIT) +#define dma_done_ie cpu_to_le32 (1 << DMA_DONE_INTERRUPT_ENABLE) /*-------------------------------------------------------------------------*/ @@ -425,7 +425,7 @@ net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags) return NULL; } td->dmacount = 0; /* not VALID */ - td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID); + td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID); td->dmadesc = td->dmaaddr; req->td = td; } @@ -775,7 +775,7 @@ static void start_dma (struct net2280_ep *ep, struct net2280_request *req) fill_dma_desc (ep, req, 1); if (!use_dma_chaining) - req->td->dmacount |= __constant_cpu_to_le32 (1 << END_OF_CHAIN); + req->td->dmacount |= cpu_to_le32 (1 << END_OF_CHAIN); start_queue (ep, tmp, req->td_dma); } @@ -2407,9 +2407,9 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) if (readl (&e->regs->ep_rsp) & (1 << SET_ENDPOINT_HALT)) - status = __constant_cpu_to_le32 (1); + status = cpu_to_le32 (1); else - status = __constant_cpu_to_le32 (0); + status = cpu_to_le32 (0); /* don't bother with a request object! */ writel (0, &dev->epregs [0].ep_irqenb); @@ -2667,7 +2667,7 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat) req = list_entry (ep->queue.next, struct net2280_request, queue); dmacount = req->td->dmacount; - dmacount &= __constant_cpu_to_le32 ( + dmacount &= cpu_to_le32 ( (1 << VALID_BIT) | DMA_BYTE_COUNT_MASK); if (dmacount && (dmacount & valid_bit) == 0) @@ -2881,7 +2881,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) goto done; } td->dmacount = 0; /* not VALID */ - td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID); + td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID); td->dmadesc = td->dmaaddr; dev->ep [i].dummy = td; } diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 5a3034fdfe4..29500154d00 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -225,12 +225,12 @@ module_param(qlen, uint, S_IRUGO|S_IWUSR); static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_PER_INTERFACE, .bDeviceSubClass = 0, .bDeviceProtocol = 0, - .idVendor = __constant_cpu_to_le16(PRINTER_VENDOR_NUM), - .idProduct = __constant_cpu_to_le16(PRINTER_PRODUCT_NUM), + .idVendor = cpu_to_le16(PRINTER_VENDOR_NUM), + .idProduct = cpu_to_le16(PRINTER_PRODUCT_NUM), .iManufacturer = STRING_MANUFACTURER, .iProduct = STRING_PRODUCT, .iSerialNumber = STRING_SERIALNUM, @@ -299,20 +299,20 @@ static struct usb_endpoint_descriptor hs_ep_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512) + .wMaxPacketSize = cpu_to_le16(512) }; static struct usb_endpoint_descriptor hs_ep_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512) + .wMaxPacketSize = cpu_to_le16(512) }; static struct usb_qualifier_descriptor dev_qualifier = { .bLength = sizeof dev_qualifier, .bDescriptorType = USB_DT_DEVICE_QUALIFIER, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_PRINTER, .bNumConfigurations = 1 }; @@ -1406,16 +1406,16 @@ printer_bind(struct usb_gadget *gadget) gadget->name); /* unrecognized, but safe unless bulk is REALLY quirky */ device_desc.bcdDevice = - __constant_cpu_to_le16(0xFFFF); + cpu_to_le16(0xFFFF); } snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s", init_utsname()->sysname, init_utsname()->release, gadget->name); device_desc.idVendor = - __constant_cpu_to_le16(PRINTER_VENDOR_NUM); + cpu_to_le16(PRINTER_VENDOR_NUM); device_desc.idProduct = - __constant_cpu_to_le16(PRINTER_PRODUCT_NUM); + cpu_to_le16(PRINTER_PRODUCT_NUM); /* support optional vendor/distro customization */ if (idVendor) { diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 37879af1c43..f46a60962da 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -87,12 +87,12 @@ static struct usb_gadget_strings *dev_strings[] = { static struct usb_device_descriptor device_desc = { .bLength = USB_DT_DEVICE_SIZE, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), /* .bDeviceClass = f(use_acm) */ .bDeviceSubClass = 0, .bDeviceProtocol = 0, /* .bMaxPacketSize0 = f(hardware) */ - .idVendor = __constant_cpu_to_le16(GS_VENDOR_ID), + .idVendor = cpu_to_le16(GS_VENDOR_ID), /* .idProduct = f(use_acm) */ /* .bcdDevice = f(hardware) */ /* .iManufacturer = DYNAMIC */ @@ -216,7 +216,7 @@ static int __init gs_bind(struct usb_composite_dev *cdev) pr_warning("gs_bind: controller '%s' not recognized\n", gadget->name); device_desc.bcdDevice = - __constant_cpu_to_le16(GS_VERSION_NUM | 0x0099); + cpu_to_le16(GS_VERSION_NUM | 0x0099); } if (gadget_is_otg(cdev->gadget)) { @@ -255,19 +255,19 @@ static int __init init(void) serial_config_driver.bConfigurationValue = 2; device_desc.bDeviceClass = USB_CLASS_COMM; device_desc.idProduct = - __constant_cpu_to_le16(GS_CDC_PRODUCT_ID); + cpu_to_le16(GS_CDC_PRODUCT_ID); } else if (use_obex) { serial_config_driver.label = "CDC OBEX config"; serial_config_driver.bConfigurationValue = 3; device_desc.bDeviceClass = USB_CLASS_COMM; device_desc.idProduct = - __constant_cpu_to_le16(GS_CDC_OBEX_PRODUCT_ID); + cpu_to_le16(GS_CDC_OBEX_PRODUCT_ID); } else { serial_config_driver.label = "Generic Serial config"; serial_config_driver.bConfigurationValue = 1; device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC; device_desc.idProduct = - __constant_cpu_to_le16(GS_PRODUCT_ID); + cpu_to_le16(GS_PRODUCT_ID); } strings_dev[STRING_DESCRIPTION_IDX].s = serial_config_driver.label; diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index 53d59287f2b..0a4d99ab40d 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -1092,7 +1092,7 @@ int __init gserial_setup(struct usb_gadget *g, unsigned count) gs_tty_driver->init_termios.c_ispeed = 9600; gs_tty_driver->init_termios.c_ospeed = 9600; - coding.dwDTERate = __constant_cpu_to_le32(9600); + coding.dwDTERate = cpu_to_le32(9600); coding.bCharFormat = 8; coding.bParityType = USB_CDC_NO_PARITY; coding.bDataBits = USB_CDC_1_STOP_BITS; diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 361d9659ac4..20614dce8db 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -113,11 +113,11 @@ static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_VENDOR_SPEC, - .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_NUM), - .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_NUM), + .idVendor = cpu_to_le16(DRIVER_VENDOR_NUM), + .idProduct = cpu_to_le16(DRIVER_PRODUCT_NUM), .bNumConfigurations = 2, }; @@ -265,7 +265,7 @@ static int __init zero_bind(struct usb_composite_dev *cdev) */ pr_warning("%s: controller '%s' not recognized\n", longname, gadget->name); - device_desc.bcdDevice = __constant_cpu_to_le16(0x9999); + device_desc.bcdDevice = cpu_to_le16(0x9999); } diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 1d0b49e3f19..ada5d2ba297 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -563,7 +563,7 @@ static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) // and this qh is active in the current uframe // (and overlay token SplitXstate is false?) // THEN - // qh->hw_info1 |= __constant_cpu_to_hc32(1 << 7 /* "ignore" */); + // qh->hw_info1 |= cpu_to_hc32(1 << 7 /* "ignore" */); /* high bandwidth, or otherwise part of every microframe */ if ((period = qh->period) == 0) diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 9aba560fd56..6cff195e1a3 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -253,7 +253,7 @@ struct ehci_qtd { /* * Now the following defines are not converted using the - * __constant_cpu_to_le32() macro anymore, since we have to support + * cpu_to_le32() macro anymore, since we have to support * "dynamic" switching between be and le support, so that the driver * can be used on one system with SoC EHCI controller using big-endian * descriptors as well as a normal little-endian PCI EHCI controller. diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 8ee2f415984..3172c0fd2a6 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -644,7 +644,7 @@ static void transform_add_int(struct isp1760_hcd *priv, struct isp1760_qh *qh, if (urb->dev->speed != USB_SPEED_HIGH) { /* split */ - ptd->dw5 = __constant_cpu_to_le32(0x1c); + ptd->dw5 = cpu_to_le32(0x1c); if (qh->period >= 32) period = qh->period / 2; @@ -1054,7 +1054,7 @@ static void do_atl_int(struct usb_hcd *usb_hcd) priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs + atl_regs, sizeof(ptd)); - ptd.dw0 |= __constant_cpu_to_le32(PTD_VALID); + ptd.dw0 |= cpu_to_le32(PTD_VALID); priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs + atl_regs, sizeof(ptd)); diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index 75548f7c716..2947c69b347 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -845,14 +845,14 @@ static inline void qh_update(struct oxu_hcd *oxu, is_out = !(qtd->hw_token & cpu_to_le32(1 << 8)); epnum = (le32_to_cpup(&qh->hw_info1) >> 8) & 0x0f; if (unlikely(!usb_gettoggle(qh->dev, epnum, is_out))) { - qh->hw_token &= ~__constant_cpu_to_le32(QTD_TOGGLE); + qh->hw_token &= ~cpu_to_le32(QTD_TOGGLE); usb_settoggle(qh->dev, epnum, is_out, 1); } } /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */ wmb(); - qh->hw_token &= __constant_cpu_to_le32(QTD_TOGGLE | QTD_STS_PING); + qh->hw_token &= cpu_to_le32(QTD_TOGGLE | QTD_STS_PING); } /* If it weren't for a common silicon quirk (writing the dummy into the qh @@ -937,7 +937,7 @@ __acquires(oxu->lock) struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; /* S-mask in a QH means it's an interrupt urb */ - if ((qh->hw_info2 & __constant_cpu_to_le32(QH_SMASK)) != 0) { + if ((qh->hw_info2 & cpu_to_le32(QH_SMASK)) != 0) { /* ... update hc-wide periodic stats (for usbfs) */ oxu_to_hcd(oxu)->self.bandwidth_int_reqs--; @@ -981,7 +981,7 @@ static void unlink_async(struct oxu_hcd *oxu, struct ehci_qh *qh); static void intr_deschedule(struct oxu_hcd *oxu, struct ehci_qh *qh); static int qh_schedule(struct oxu_hcd *oxu, struct ehci_qh *qh); -#define HALT_BIT __constant_cpu_to_le32(QTD_STS_HALT) +#define HALT_BIT cpu_to_le32(QTD_STS_HALT) /* Process and free completed qtds for a qh, returning URBs to drivers. * Chases up to qh->hw_current. Returns number of completions called, @@ -1160,7 +1160,7 @@ halt: /* should be rare for periodic transfers, * except maybe high bandwidth ... */ - if ((__constant_cpu_to_le32(QH_SMASK) + if ((cpu_to_le32(QH_SMASK) & qh->hw_info2) != 0) { intr_deschedule(oxu, qh); (void) qh_schedule(oxu, qh); @@ -1350,7 +1350,7 @@ static struct list_head *qh_urb_transaction(struct oxu_hcd *oxu, } /* by default, enable interrupt on urb completion */ - qtd->hw_token |= __constant_cpu_to_le32(QTD_IOC); + qtd->hw_token |= cpu_to_le32(QTD_IOC); return head; cleanup: @@ -1539,7 +1539,7 @@ static void qh_link_async(struct oxu_hcd *oxu, struct ehci_qh *qh) /* qtd completions reported later by interrupt */ } -#define QH_ADDR_MASK __constant_cpu_to_le32(0x7f) +#define QH_ADDR_MASK cpu_to_le32(0x7f) /* * For control/bulk/interrupt, return QH with these TDs appended. @@ -2012,7 +2012,7 @@ static void qh_unlink_periodic(struct oxu_hcd *oxu, struct ehci_qh *qh) * and this qh is active in the current uframe * (and overlay token SplitXstate is false?) * THEN - * qh->hw_info1 |= __constant_cpu_to_le32(1 << 7 "ignore"); + * qh->hw_info1 |= cpu_to_le32(1 << 7 "ignore"); */ /* high bandwidth, or otherwise part of every microframe */ @@ -2057,7 +2057,7 @@ static void intr_deschedule(struct oxu_hcd *oxu, struct ehci_qh *qh) * active high speed queues may need bigger delays... */ if (list_empty(&qh->qtd_list) - || (__constant_cpu_to_le32(QH_CMASK) & qh->hw_info2) != 0) + || (cpu_to_le32(QH_CMASK) & qh->hw_info2) != 0) wait = 2; else wait = 55; /* worst case: 3 * 1024 */ @@ -2183,10 +2183,10 @@ static int qh_schedule(struct oxu_hcd *oxu, struct ehci_qh *qh) qh->start = frame; /* reset S-frame and (maybe) C-frame masks */ - qh->hw_info2 &= __constant_cpu_to_le32(~(QH_CMASK | QH_SMASK)); + qh->hw_info2 &= cpu_to_le32(~(QH_CMASK | QH_SMASK)); qh->hw_info2 |= qh->period ? cpu_to_le32(1 << uframe) - : __constant_cpu_to_le32(QH_SMASK); + : cpu_to_le32(QH_SMASK); qh->hw_info2 |= c_mask; } else oxu_dbg(oxu, "reused qh %p schedule\n", qh); diff --git a/drivers/usb/host/oxu210hp.h b/drivers/usb/host/oxu210hp.h index 8910e271cc7..1c216ad9aad 100644 --- a/drivers/usb/host/oxu210hp.h +++ b/drivers/usb/host/oxu210hp.h @@ -235,21 +235,21 @@ struct ehci_qtd { } __attribute__ ((aligned(32))); /* mask NakCnt+T in qh->hw_alt_next */ -#define QTD_MASK __constant_cpu_to_le32 (~0x1f) +#define QTD_MASK cpu_to_le32 (~0x1f) #define IS_SHORT_READ(token) (QTD_LENGTH(token) != 0 && QTD_PID(token) == 1) /* Type tag from {qh, itd, sitd, fstn}->hw_next */ -#define Q_NEXT_TYPE(dma) ((dma) & __constant_cpu_to_le32 (3 << 1)) +#define Q_NEXT_TYPE(dma) ((dma) & cpu_to_le32 (3 << 1)) /* values for that type tag */ -#define Q_TYPE_QH __constant_cpu_to_le32 (1 << 1) +#define Q_TYPE_QH cpu_to_le32 (1 << 1) /* next async queue entry, or pointer to interrupt/periodic QH */ #define QH_NEXT(dma) (cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH) /* for periodic/async schedules and qtd lists, mark end of list */ -#define EHCI_LIST_END __constant_cpu_to_le32(1) /* "null pointer" to hw */ +#define EHCI_LIST_END cpu_to_le32(1) /* "null pointer" to hw */ /* * Entries in periodic shadow table are pointers to one of four kinds diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 7d01c5677f9..26bd1b2bcbf 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -73,11 +73,11 @@ #define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ #define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */ -#define UHCI_PTR_BITS __constant_cpu_to_le32(0x000F) -#define UHCI_PTR_TERM __constant_cpu_to_le32(0x0001) -#define UHCI_PTR_QH __constant_cpu_to_le32(0x0002) -#define UHCI_PTR_DEPTH __constant_cpu_to_le32(0x0004) -#define UHCI_PTR_BREADTH __constant_cpu_to_le32(0x0000) +#define UHCI_PTR_BITS cpu_to_le32(0x000F) +#define UHCI_PTR_TERM cpu_to_le32(0x0001) +#define UHCI_PTR_QH cpu_to_le32(0x0002) +#define UHCI_PTR_DEPTH cpu_to_le32(0x0004) +#define UHCI_PTR_BREADTH cpu_to_le32(0x0000) #define UHCI_NUMFRAMES 1024 /* in the frame list [array] */ #define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 5631d89c873..58f87367914 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -402,7 +402,7 @@ static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first) /* Otherwise all the toggles in the URB have to be switched */ } else { list_for_each_entry(td, &urbp->td_list, list) { - td->token ^= __constant_cpu_to_le32( + td->token ^= cpu_to_le32( TD_TOKEN_TOGGLE); toggle ^= 1; } @@ -883,7 +883,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0); wmb(); - qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE); + qh->dummy_td->status |= cpu_to_le32(TD_CTRL_ACTIVE); qh->dummy_td = td; /* Low-speed transfers get a different queue, and won't hog the bus. @@ -1003,7 +1003,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, * fast side but not enough to justify delaying an interrupt * more than 2 or 3 URBs, so we will ignore the URB_NO_INTERRUPT * flag setting. */ - td->status |= __constant_cpu_to_le32(TD_CTRL_IOC); + td->status |= cpu_to_le32(TD_CTRL_IOC); /* * Build the new dummy TD and activate the old one @@ -1015,7 +1015,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0); wmb(); - qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE); + qh->dummy_td->status |= cpu_to_le32(TD_CTRL_ACTIVE); qh->dummy_td = td; usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), @@ -1317,7 +1317,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, } /* Set the interrupt-on-completion flag on the last packet. */ - td->status |= __constant_cpu_to_le32(TD_CTRL_IOC); + td->status |= cpu_to_le32(TD_CTRL_IOC); /* Add the TDs to the frame list */ frame = urb->start_frame; diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c index 972f20b3406..eca355dccf6 100644 --- a/drivers/usb/image/mdc800.c +++ b/drivers/usb/image/mdc800.c @@ -188,7 +188,7 @@ static struct usb_endpoint_descriptor mdc800_ed [4] = .bDescriptorType = 0, .bEndpointAddress = 0x01, .bmAttributes = 0x02, - .wMaxPacketSize = __constant_cpu_to_le16(8), + .wMaxPacketSize = cpu_to_le16(8), .bInterval = 0, .bRefresh = 0, .bSynchAddress = 0, @@ -198,7 +198,7 @@ static struct usb_endpoint_descriptor mdc800_ed [4] = .bDescriptorType = 0, .bEndpointAddress = 0x82, .bmAttributes = 0x03, - .wMaxPacketSize = __constant_cpu_to_le16(8), + .wMaxPacketSize = cpu_to_le16(8), .bInterval = 0, .bRefresh = 0, .bSynchAddress = 0, @@ -208,7 +208,7 @@ static struct usb_endpoint_descriptor mdc800_ed [4] = .bDescriptorType = 0, .bEndpointAddress = 0x03, .bmAttributes = 0x02, - .wMaxPacketSize = __constant_cpu_to_le16(64), + .wMaxPacketSize = cpu_to_le16(64), .bInterval = 0, .bRefresh = 0, .bSynchAddress = 0, @@ -218,7 +218,7 @@ static struct usb_endpoint_descriptor mdc800_ed [4] = .bDescriptorType = 0, .bEndpointAddress = 0x84, .bmAttributes = 0x02, - .wMaxPacketSize = __constant_cpu_to_le16(64), + .wMaxPacketSize = cpu_to_le16(64), .bInterval = 0, .bRefresh = 0, .bSynchAddress = 0, diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index e0e9ce58417..bf677acc83d 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -285,7 +285,7 @@ int musb_hub_control( desc->bDescLength = 9; desc->bDescriptorType = 0x29; desc->bNbrPorts = 1; - desc->wHubCharacteristics = __constant_cpu_to_le16( + desc->wHubCharacteristics = cpu_to_le16( 0x0001 /* per-port power switching */ | 0x0010 /* no overcurrent reporting */ ); -- GitLab From d0626808f7a6181c1c750d261da9a7a845c29e13 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 13 Feb 2009 11:22:06 -0800 Subject: [PATCH 4334/4982] USB: fix ehci printk formats Fix ehci printk formats: drivers/usb/host/ehci-q.c:351: warning: format '%d' expects type 'int', but argument 4 has type 'size_t' drivers/usb/host/ehci-q.c:351: warning: format '%d' expects type 'int', but argument 5 has type 'size_t' Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-q.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 01132ac74eb..1976b1b3778 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -349,7 +349,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) --qh->xacterrs > 0 && !urb->unlinked) { ehci_dbg(ehci, - "detected XactErr len %d/%d retry %d\n", + "detected XactErr len %zu/%zu retry %d\n", qtd->length - QTD_LENGTH(token), qtd->length, QH_XACTERR_MAX - qh->xacterrs); -- GitLab From e4abe6658aa17a5d7e7321dfda807d287255511b Mon Sep 17 00:00:00 2001 From: Dave Young Date: Sat, 14 Feb 2009 21:21:13 +0800 Subject: [PATCH 4335/4982] usb-serial: fix usb_serial_register bug when boot with nousb param With "nousb" cmdline booting, built-in serial drivers (ie. airecable) will trigger kernel oops. Indeed, if nousb, usb_serial_init will failed, and the usb serial bus type will not be registerd, then usb_serial_register call driver_register which try to register the driver to a not registered bus. Here add usb_disabled() check in usb_serial_register to fix it. Signed-off-by: Dave Young Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 73172898ccb..742a5bc44be 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1241,6 +1241,9 @@ int usb_serial_register(struct usb_serial_driver *driver) /* must be called with BKL held */ int retval; + if (usb_disabled()) + return -ENODEV; + fixup_generic(driver); if (!driver->description) -- GitLab From e6e244b6cb1f70e7109381626293cd40a8334ed3 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:47:44 -0500 Subject: [PATCH 4336/4982] usb-storage: prepare for subdriver separation This patch (as1206) is the first step in converting usb-storage's subdrivers into separate modules. It makes the following large-scale changes: Remove a bunch of unnecessary #ifdef's from usb_usual.h. Not truly necessary, but it does clean things up. Move the USB device-ID table (which is duplicated between libusual and usb-storage) into its own source file, usual-tables.c, and arrange for this to be linked with either libusual or usb-storage according to whether USB_LIBUSUAL is configured. Add to usual-tables.c a new usb_usual_ignore_device() function to detect whether a particular device needs to be managed by a subdriver and not by the standard handlers in usb-storage. Export a whole bunch of functions in usb-storage, renaming some of them because their names don't already begin with "usb_stor_". These functions will be needed by the new subdriver modules. Split usb-storage's probe routine into two functions. The subdrivers will call the probe1 routine, then fill in their transport and protocol settings, and then call the probe2 routine. Take the default cases and error checking out of get_transport() and get_protocol(), which run during probe1, and instead put a check for invalid transport or protocol values into the probe2 function. Add a new probe routine to be used for standard devices, i.e., those that don't need a subdriver. This new routine checks whether the device should be ignored (because it should be handled by ub or by a subdriver), and if not, calls the probe1 and probe2 functions. Signed-off-by: Alan Stern CC: Matthew Dharm Signed-off-by: Greg Kroah-Hartman --- drivers/block/ub.c | 2 +- drivers/usb/storage/Makefile | 6 +- drivers/usb/storage/libusual.c | 33 +---- drivers/usb/storage/protocol.c | 3 + drivers/usb/storage/scsiglue.c | 2 +- drivers/usb/storage/transport.c | 10 ++ drivers/usb/storage/usb.c | 209 +++++++++++++++-------------- drivers/usb/storage/usb.h | 21 +++ drivers/usb/storage/usual-tables.c | 105 +++++++++++++++ include/linux/usb_usual.h | 21 +-- 10 files changed, 261 insertions(+), 151 deletions(-) create mode 100644 drivers/usb/storage/usual-tables.c diff --git a/drivers/block/ub.c b/drivers/block/ub.c index b36b84fbe39..69b7f8e7759 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -391,7 +391,7 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum); */ #ifdef CONFIG_USB_LIBUSUAL -#define ub_usb_ids storage_usb_ids +#define ub_usb_ids usb_storage_usb_ids #else static struct usb_device_id ub_usb_ids[] = { diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index b3206931339..a9e475e127a 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -25,6 +25,8 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += cypress_atacb.o usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ initializers.o sierra_ms.o option_ms.o $(usb-storage-obj-y) -ifneq ($(CONFIG_USB_LIBUSUAL),) - obj-$(CONFIG_USB) += libusual.o +ifeq ($(CONFIG_USB_LIBUSUAL),) + usb-storage-objs += usual-tables.o +else + obj-$(CONFIG_USB) += libusual.o usual-tables.o endif diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c index f970b27ba30..fe3ffe1459b 100644 --- a/drivers/usb/storage/libusual.c +++ b/drivers/usb/storage/libusual.c @@ -37,37 +37,6 @@ static atomic_t total_threads = ATOMIC_INIT(0); static int usu_probe_thread(void *arg); -/* - * The table. - */ -#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ - vendorName, productName,useProtocol, useTransport, \ - initFunction, flags) \ -{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } - -#define COMPLIANT_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ - vendorName, productName, useProtocol, useTransport, \ - initFunction, flags) \ -{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags) } - -#define USUAL_DEV(useProto, useTrans, useType) \ -{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ - .driver_info = ((useType)<<24) } - -struct usb_device_id storage_usb_ids [] = { -# include "unusual_devs.h" - { } /* Terminating entry */ -}; - -#undef USUAL_DEV -#undef UNUSUAL_DEV -#undef COMPLIANT_DEV - -MODULE_DEVICE_TABLE(usb, storage_usb_ids); -EXPORT_SYMBOL_GPL(storage_usb_ids); - /* * @type: the module type as an integer */ @@ -167,7 +136,7 @@ static struct usb_driver usu_driver = { .name = "libusual", .probe = usu_probe, .disconnect = usu_disconnect, - .id_table = storage_usb_ids, + .id_table = usb_storage_usb_ids, }; /* diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c index be441d84bc6..fc310f75ead 100644 --- a/drivers/usb/storage/protocol.c +++ b/drivers/usb/storage/protocol.c @@ -121,6 +121,7 @@ void usb_stor_transparent_scsi_command(struct scsi_cmnd *srb, /* send the command to the transport layer */ usb_stor_invoke_transport(srb, us); } +EXPORT_SYMBOL_GPL(usb_stor_transparent_scsi_command); /*********************************************************************** * Scatter-gather transfer buffer access routines @@ -199,6 +200,7 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, /* Return the amount actually transferred */ return cnt; } +EXPORT_SYMBOL_GPL(usb_stor_access_xfer_buf); /* Store the contents of buffer into srb's transfer buffer and set the * SCSI residue. @@ -215,3 +217,4 @@ void usb_stor_set_xfer_buf(unsigned char *buffer, if (buflen < scsi_bufflen(srb)) scsi_set_resid(srb, scsi_bufflen(srb) - buflen); } +EXPORT_SYMBOL_GPL(usb_stor_set_xfer_buf); diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index ed710bcdaab..4ca3b586064 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -569,4 +569,4 @@ unsigned char usb_stor_sense_invalidCDB[18] = { [7] = 0x0a, /* additional length */ [12] = 0x24 /* Invalid Field in CDB */ }; - +EXPORT_SYMBOL_GPL(usb_stor_sense_invalidCDB); diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index fb65d221ced..d48c8553539 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -220,6 +220,7 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe, status = us->current_urb->actual_length; return status; } +EXPORT_SYMBOL_GPL(usb_stor_control_msg); /* This is a version of usb_clear_halt() that allows early termination and * doesn't read the status from the device -- this is because some devices @@ -254,6 +255,7 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe) US_DEBUGP("%s: result = %d\n", __func__, result); return result; } +EXPORT_SYMBOL_GPL(usb_stor_clear_halt); /* @@ -352,6 +354,7 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe, return interpret_urb_result(us, pipe, size, result, us->current_urb->actual_length); } +EXPORT_SYMBOL_GPL(usb_stor_ctrl_transfer); /* * Receive one interrupt buffer, without timeouts, but allowing early @@ -407,6 +410,7 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe, return interpret_urb_result(us, pipe, length, result, us->current_urb->actual_length); } +EXPORT_SYMBOL_GPL(usb_stor_bulk_transfer_buf); /* * Transfer a scatter-gather list via bulk transfer @@ -474,6 +478,7 @@ int usb_stor_bulk_srb(struct us_data* us, unsigned int pipe, scsi_set_resid(srb, scsi_bufflen(srb) - partial); return result; } +EXPORT_SYMBOL_GPL(usb_stor_bulk_srb); /* * Transfer an entire SCSI command's worth of data payload over the bulk @@ -509,6 +514,7 @@ int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe, *residual = length_left; return result; } +EXPORT_SYMBOL_GPL(usb_stor_bulk_transfer_sg); /*********************************************************************** * Transport routines @@ -940,6 +946,7 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us) usb_stor_clear_halt(us, pipe); return USB_STOR_TRANSPORT_FAILED; } +EXPORT_SYMBOL_GPL(usb_stor_CB_transport); /* * Bulk only transport @@ -1156,6 +1163,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) /* we should never get here, but if we do, we're in trouble */ return USB_STOR_TRANSPORT_ERROR; } +EXPORT_SYMBOL_GPL(usb_stor_Bulk_transport); /*********************************************************************** * Reset routines @@ -1230,6 +1238,7 @@ int usb_stor_CB_reset(struct us_data *us) USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, us->ifnum, us->iobuf, CB_RESET_CMD_SIZE); } +EXPORT_SYMBOL_GPL(usb_stor_CB_reset); /* This issues a Bulk-only Reset to the device in question, including * clearing the subsequent endpoint halts that may occur. @@ -1242,6 +1251,7 @@ int usb_stor_Bulk_reset(struct us_data *us) USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, us->ifnum, NULL, 0); } +EXPORT_SYMBOL_GPL(usb_stor_Bulk_reset); /* Issue a USB port reset to the device. The caller must not hold * us->dev_mutex. diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index b01dade63cb..490ea761398 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -5,7 +5,7 @@ * * Developed with the assistance of: * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org) - * (c) 2003 Alan Stern (stern@rowland.harvard.edu) + * (c) 2003-2009 Alan Stern (stern@rowland.harvard.edu) * * Initial work by: * (c) 1999 Michael Gee (michael@linuxspecific.com) @@ -118,36 +118,8 @@ MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks"); /* * The entries in this table correspond, line for line, - * with the entries of us_unusual_dev_list[]. + * with the entries in usb_storage_usb_ids[], defined in usual-tables.c. */ -#ifndef CONFIG_USB_LIBUSUAL - -#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ - vendorName, productName,useProtocol, useTransport, \ - initFunction, flags) \ -{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } - -#define COMPLIANT_DEV UNUSUAL_DEV - -#define USUAL_DEV(useProto, useTrans, useType) \ -{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ - .driver_info = (USB_US_TYPE_STOR<<24) } - -static struct usb_device_id storage_usb_ids [] = { - -# include "unusual_devs.h" -#undef UNUSUAL_DEV -#undef COMPLIANT_DEV -#undef USUAL_DEV - /* Terminating entry */ - { } -}; - -MODULE_DEVICE_TABLE (usb, storage_usb_ids); -#endif /* CONFIG_USB_LIBUSUAL */ - -/* This is the list of devices we recognize, along with their flag data */ /* The vendor name should be kept at eight characters or less, and * the product name should be kept at 16 characters or less. If a device @@ -179,18 +151,17 @@ MODULE_DEVICE_TABLE (usb, storage_usb_ids); static struct us_unusual_dev us_unusual_dev_list[] = { # include "unusual_devs.h" -# undef UNUSUAL_DEV -# undef COMPLIANT_DEV -# undef USUAL_DEV - - /* Terminating entry */ - { NULL } + { } /* Terminating entry */ }; +#undef UNUSUAL_DEV +#undef COMPLIANT_DEV +#undef USUAL_DEV + #ifdef CONFIG_PM /* Minimal support for suspend and resume */ -static int storage_suspend(struct usb_interface *iface, pm_message_t message) +int usb_stor_suspend(struct usb_interface *iface, pm_message_t message) { struct us_data *us = usb_get_intfdata(iface); @@ -207,8 +178,9 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message) mutex_unlock(&us->dev_mutex); return 0; } +EXPORT_SYMBOL_GPL(usb_stor_suspend); -static int storage_resume(struct usb_interface *iface) +int usb_stor_resume(struct usb_interface *iface) { struct us_data *us = usb_get_intfdata(iface); @@ -221,8 +193,9 @@ static int storage_resume(struct usb_interface *iface) mutex_unlock(&us->dev_mutex); return 0; } +EXPORT_SYMBOL_GPL(usb_stor_resume); -static int storage_reset_resume(struct usb_interface *iface) +int usb_stor_reset_resume(struct usb_interface *iface) { struct us_data *us = usb_get_intfdata(iface); @@ -235,6 +208,7 @@ static int storage_reset_resume(struct usb_interface *iface) * the device */ return 0; } +EXPORT_SYMBOL_GPL(usb_stor_reset_resume); #endif /* CONFIG_PM */ @@ -243,7 +217,7 @@ static int storage_reset_resume(struct usb_interface *iface) * a USB port reset, whether from this driver or a different one. */ -static int storage_pre_reset(struct usb_interface *iface) +int usb_stor_pre_reset(struct usb_interface *iface) { struct us_data *us = usb_get_intfdata(iface); @@ -253,8 +227,9 @@ static int storage_pre_reset(struct usb_interface *iface) mutex_lock(&us->dev_mutex); return 0; } +EXPORT_SYMBOL_GPL(usb_stor_pre_reset); -static int storage_post_reset(struct usb_interface *iface) +int usb_stor_post_reset(struct usb_interface *iface) { struct us_data *us = usb_get_intfdata(iface); @@ -269,6 +244,7 @@ static int storage_post_reset(struct usb_interface *iface) mutex_unlock(&us->dev_mutex); return 0; } +EXPORT_SYMBOL_GPL(usb_stor_post_reset); /* * fill_inquiry_response takes an unsigned char array (which must @@ -311,6 +287,7 @@ void fill_inquiry_response(struct us_data *us, unsigned char *data, usb_stor_set_xfer_buf(data, data_len, us->srb); } +EXPORT_SYMBOL_GPL(fill_inquiry_response); static int usb_stor_control_thread(void * __us) { @@ -551,20 +528,13 @@ static void adjust_quirks(struct us_data *us) vid, pid, f); } -/* Find an unusual_dev descriptor (always succeeds in the current code) */ -static struct us_unusual_dev *find_unusual(const struct usb_device_id *id) -{ - const int id_index = id - storage_usb_ids; - return &us_unusual_dev_list[id_index]; -} - /* Get the unusual_devs entries and the string descriptors */ -static int get_device_info(struct us_data *us, const struct usb_device_id *id) +static int get_device_info(struct us_data *us, const struct usb_device_id *id, + struct us_unusual_dev *unusual_dev) { struct usb_device *dev = us->pusb_dev; struct usb_interface_descriptor *idesc = &us->pusb_intf->cur_altsetting->desc; - struct us_unusual_dev *unusual_dev = find_unusual(id); /* Store the entries */ us->unusual_dev = unusual_dev; @@ -629,7 +599,7 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id) } /* Get the transport settings */ -static int get_transport(struct us_data *us) +static void get_transport(struct us_data *us) { switch (us->protocol) { case US_PR_CB: @@ -732,19 +702,11 @@ static int get_transport(struct us_data *us) break; #endif - default: - return -EIO; } - US_DEBUGP("Transport: %s\n", us->transport_name); - - /* fix for single-lun devices */ - if (us->fflags & US_FL_SINGLE_LUN) - us->max_lun = 0; - return 0; } /* Get the protocol settings */ -static int get_protocol(struct us_data *us) +static void get_protocol(struct us_data *us) { switch (us->subclass) { case US_SC_RBC: @@ -794,11 +756,7 @@ static int get_protocol(struct us_data *us) break; #endif - default: - return -EIO; } - US_DEBUGP("Protocol: %s\n", us->protocol_name); - return 0; } /* Get the pipe settings */ @@ -1012,17 +970,15 @@ static int usb_stor_scan_thread(void * __us) } -/* Probe to see if we can drive a newly-connected USB device */ -static int storage_probe(struct usb_interface *intf, - const struct usb_device_id *id) +/* First part of general USB mass-storage probing */ +int usb_stor_probe1(struct us_data **pus, + struct usb_interface *intf, + const struct usb_device_id *id, + struct us_unusual_dev *unusual_dev) { struct Scsi_Host *host; struct us_data *us; int result; - struct task_struct *th; - - if (usb_usual_check_type(id, USB_US_TYPE_STOR)) - return -ENXIO; US_DEBUGP("USB Mass Storage device detected\n"); @@ -1041,7 +997,7 @@ static int storage_probe(struct usb_interface *intf, * Allow 16-byte CDBs and thus > 2TB */ host->max_cmd_len = 16; - us = host_to_us(host); + *pus = us = host_to_us(host); memset(us, 0, sizeof(struct us_data)); mutex_init(&(us->dev_mutex)); init_completion(&us->cmnd_ready); @@ -1054,24 +1010,46 @@ static int storage_probe(struct usb_interface *intf, if (result) goto BadDevice; - /* - * Get the unusual_devs entries and the descriptors - * - * id_index is calculated in the declaration to be the index number - * of the match from the usb_device_id table, so we can find the - * corresponding entry in the private table. - */ - result = get_device_info(us, id); + /* Get the unusual_devs entries and the descriptors */ + result = get_device_info(us, id, unusual_dev); if (result) goto BadDevice; - /* Get the transport, protocol, and pipe settings */ - result = get_transport(us); - if (result) - goto BadDevice; - result = get_protocol(us); - if (result) + /* Get standard transport and protocol settings */ + get_transport(us); + get_protocol(us); + + /* Give the caller a chance to fill in specialized transport + * or protocol settings. + */ + return 0; + +BadDevice: + US_DEBUGP("storage_probe() failed\n"); + release_everything(us); + return result; +} +EXPORT_SYMBOL_GPL(usb_stor_probe1); + +/* Second part of general USB mass-storage probing */ +int usb_stor_probe2(struct us_data *us) +{ + struct task_struct *th; + int result; + + /* Make sure the transport and protocol have both been set */ + if (!us->transport || !us->proto_handler) { + result = -ENXIO; goto BadDevice; + } + US_DEBUGP("Transport: %s\n", us->transport_name); + US_DEBUGP("Protocol: %s\n", us->protocol_name); + + /* fix for single-lun devices */ + if (us->fflags & US_FL_SINGLE_LUN) + us->max_lun = 0; + + /* Find the endpoints and calculate pipe values */ result = get_pipes(us); if (result) goto BadDevice; @@ -1080,7 +1058,7 @@ static int storage_probe(struct usb_interface *intf, result = usb_stor_acquire_resources(us); if (result) goto BadDevice; - result = scsi_add_host(host, &intf->dev); + result = scsi_add_host(us_to_host(us), &us->pusb_intf->dev); if (result) { printk(KERN_WARNING USB_STORAGE "Unable to add the scsi host\n"); @@ -1108,9 +1086,10 @@ BadDevice: release_everything(us); return result; } +EXPORT_SYMBOL_GPL(usb_stor_probe2); -/* Handle a disconnect event from the USB core */ -static void storage_disconnect(struct usb_interface *intf) +/* Handle a USB mass-storage disconnect */ +void usb_stor_disconnect(struct usb_interface *intf) { struct us_data *us = usb_get_intfdata(intf); @@ -1118,6 +1097,42 @@ static void storage_disconnect(struct usb_interface *intf) quiesce_and_remove_host(us); release_everything(us); } +EXPORT_SYMBOL_GPL(usb_stor_disconnect); + +/* The main probe routine for standard devices */ +static int storage_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + /* + * If libusual is configured, let it decide whether a standard + * device should be handled by usb-storage or by ub. + * If the device isn't standard (is handled by a subdriver + * module) then don't accept it. + */ + if (usb_usual_check_type(id, USB_US_TYPE_STOR) || + usb_usual_ignore_device(intf)) + return -ENXIO; + + /* + * Call the general probe procedures. + * + * The unusual_dev_list array is parallel to the usb_storage_usb_ids + * table, so we use the index of the id entry to find the + * corresponding unusual_devs entry. + */ + result = usb_stor_probe1(&us, intf, id, + (id - usb_storage_usb_ids) + us_unusual_dev_list); + if (result) + return result; + + /* No special transport or protocol settings in the main module */ + + result = usb_stor_probe2(us); + return result; +} /*********************************************************************** * Initialization and registration @@ -1126,15 +1141,13 @@ static void storage_disconnect(struct usb_interface *intf) static struct usb_driver usb_storage_driver = { .name = "usb-storage", .probe = storage_probe, - .disconnect = storage_disconnect, -#ifdef CONFIG_PM - .suspend = storage_suspend, - .resume = storage_resume, - .reset_resume = storage_reset_resume, -#endif - .pre_reset = storage_pre_reset, - .post_reset = storage_post_reset, - .id_table = storage_usb_ids, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = usb_storage_usb_ids, .soft_unbind = 1, }; diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h index 65e674e4be9..2609efb2bd7 100644 --- a/drivers/usb/storage/usb.h +++ b/drivers/usb/storage/usb.h @@ -177,4 +177,25 @@ extern void fill_inquiry_response(struct us_data *us, #define scsi_unlock(host) spin_unlock_irq(host->host_lock) #define scsi_lock(host) spin_lock_irq(host->host_lock) +/* General routines provided by the usb-storage standard core */ +#ifdef CONFIG_PM +extern int usb_stor_suspend(struct usb_interface *iface, pm_message_t message); +extern int usb_stor_resume(struct usb_interface *iface); +extern int usb_stor_reset_resume(struct usb_interface *iface); +#else +#define usb_stor_suspend NULL +#define usb_stor_resume NULL +#define usb_stor_reset_resume NULL +#endif + +extern int usb_stor_pre_reset(struct usb_interface *iface); +extern int usb_stor_post_reset(struct usb_interface *iface); + +extern int usb_stor_probe1(struct us_data **pus, + struct usb_interface *intf, + const struct usb_device_id *id, + struct us_unusual_dev *unusual_dev); +extern int usb_stor_probe2(struct us_data *us); +extern void usb_stor_disconnect(struct usb_interface *intf); + #endif diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c new file mode 100644 index 00000000000..1924e322940 --- /dev/null +++ b/drivers/usb/storage/usual-tables.c @@ -0,0 +1,105 @@ +/* Driver for USB Mass Storage devices + * Usual Tables File for usb-storage and libusual + * + * Copyright (C) 2009 Alan Stern (stern@rowland.harvard.edu) + * + * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more + * information about this driver. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +#define COMPLIANT_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags) } + +#define USUAL_DEV(useProto, useTrans, useType) \ +{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ + .driver_info = ((useType)<<24) } + +struct usb_device_id usb_storage_usb_ids[] = { +# include "unusual_devs.h" + { } /* Terminating entry */ +}; +EXPORT_SYMBOL_GPL(usb_storage_usb_ids); + +MODULE_DEVICE_TABLE(usb, usb_storage_usb_ids); + +#undef UNUSUAL_DEV +#undef COMPLIANT_DEV +#undef USUAL_DEV + + +/* + * The table of devices to ignore + */ +struct ignore_entry { + u16 vid, pid, bcdmin, bcdmax; +}; + +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ \ + .vid = id_vendor, \ + .pid = id_product, \ + .bcdmin = bcdDeviceMin, \ + .bcdmax = bcdDeviceMax, \ +} + +static struct ignore_entry ignore_ids[] = { + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + + +/* Return an error if a device is in the ignore_ids list */ +int usb_usual_ignore_device(struct usb_interface *intf) +{ + struct usb_device *udev; + unsigned vid, pid, bcd; + struct ignore_entry *p; + + udev = interface_to_usbdev(intf); + vid = le16_to_cpu(udev->descriptor.idVendor); + pid = le16_to_cpu(udev->descriptor.idProduct); + bcd = le16_to_cpu(udev->descriptor.bcdDevice); + + for (p = ignore_ids; p->vid; ++p) { + if (p->vid == vid && p->pid == pid && + p->bcdmin <= bcd && p->bcdmax >= bcd) + return -ENXIO; + } + return 0; +} +EXPORT_SYMBOL_GPL(usb_usual_ignore_device); diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h index 1eea1ab68dc..3d15fb9bc11 100644 --- a/include/linux/usb_usual.h +++ b/include/linux/usb_usual.h @@ -96,39 +96,26 @@ enum { US_DO_ALL_FLAGS }; #define US_PR_CBI 0x00 /* Control/Bulk/Interrupt */ #define US_PR_CB 0x01 /* Control/Bulk w/o interrupt */ #define US_PR_BULK 0x50 /* bulk only */ -#ifdef CONFIG_USB_STORAGE_USBAT + #define US_PR_USBAT 0x80 /* SCM-ATAPI bridge */ -#endif -#ifdef CONFIG_USB_STORAGE_SDDR09 #define US_PR_EUSB_SDDR09 0x81 /* SCM-SCSI bridge for SDDR-09 */ -#endif -#ifdef CONFIG_USB_STORAGE_SDDR55 #define US_PR_SDDR55 0x82 /* SDDR-55 (made up) */ -#endif #define US_PR_DPCM_USB 0xf0 /* Combination CB/SDDR09 */ -#ifdef CONFIG_USB_STORAGE_FREECOM #define US_PR_FREECOM 0xf1 /* Freecom */ -#endif -#ifdef CONFIG_USB_STORAGE_DATAFAB #define US_PR_DATAFAB 0xf2 /* Datafab chipsets */ -#endif -#ifdef CONFIG_USB_STORAGE_JUMPSHOT #define US_PR_JUMPSHOT 0xf3 /* Lexar Jumpshot */ -#endif -#ifdef CONFIG_USB_STORAGE_ALAUDA #define US_PR_ALAUDA 0xf4 /* Alauda chipsets */ -#endif -#ifdef CONFIG_USB_STORAGE_KARMA #define US_PR_KARMA 0xf5 /* Rio Karma */ -#endif #define US_PR_DEVICE 0xff /* Use device's value */ /* */ +extern int usb_usual_ignore_device(struct usb_interface *intf); +extern struct usb_device_id usb_storage_usb_ids[]; + #ifdef CONFIG_USB_LIBUSUAL -extern struct usb_device_id storage_usb_ids[]; extern void usb_usual_set_present(int type); extern void usb_usual_clear_present(int type); extern int usb_usual_check_type(const struct usb_device_id *, int type); -- GitLab From 0ff71883b2d60136430458413c135d545c69b0c4 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:47:49 -0500 Subject: [PATCH 4337/4982] usb-storage: make sddr09 a separate module This patch (as1207) converts usb-storage's sddr09 subdriver into a separate module. An unexpected complication arises because of DPCM devices, in which one LUN uses the sddr09 transport and one uses the standard CB transport. Since these devices can be used even when USB_STORAGE_SDDR09 isn't configured, their entries in unusual_devs.h require special treatment. If SDDR09 isn't configured then the entries remain in unusual_devs.h; if it is then the entries are present in unusual_sddr09.h instead. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 5 +- drivers/usb/storage/sddr09.c | 107 +++++++++++++++++++++++++-- drivers/usb/storage/sddr09.h | 38 ---------- drivers/usb/storage/unusual_devs.h | 50 ++----------- drivers/usb/storage/unusual_sddr09.h | 56 ++++++++++++++ drivers/usb/storage/usb.c | 21 ------ drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 174 insertions(+), 108 deletions(-) delete mode 100644 drivers/usb/storage/sddr09.h create mode 100644 drivers/usb/storage/unusual_sddr09.h diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 5c367566be8..7be8899f255 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -83,13 +83,15 @@ config USB_STORAGE_USBAT - Sandisk ImageMate SDDR-05b config USB_STORAGE_SDDR09 - bool "SanDisk SDDR-09 (and other SmartMedia, including DPCM) support" + tristate "SanDisk SDDR-09 (and other SmartMedia, including DPCM) support" depends on USB_STORAGE help Say Y here to include additional code to support the Sandisk SDDR-09 SmartMedia reader in the USB Mass Storage driver. Also works for the Microtech Zio! CompactFlash/SmartMedia reader. + If this driver is compiled as a module, it will be named ums-sddr09. + config USB_STORAGE_SDDR55 bool "SanDisk SDDR-55 SmartMedia support" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index a9e475e127a..a52740a9560 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o usb-storage-obj-$(CONFIG_USB_STORAGE_USBAT) += shuttle_usbat.o -usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR09) += sddr09.o usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR55) += sddr55.o usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM) += freecom.o usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200) += isd200.o @@ -30,3 +29,7 @@ ifeq ($(CONFIG_USB_LIBUSUAL),) else obj-$(CONFIG_USB) += libusual.o usual-tables.o endif + +obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o + +ums-sddr09-objs := sddr09.o diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index b667c7d2b83..170ad86b2d3 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c @@ -41,6 +41,7 @@ */ #include +#include #include #include @@ -51,7 +52,50 @@ #include "transport.h" #include "protocol.h" #include "debug.h" -#include "sddr09.h" + + +static int usb_stor_sddr09_dpcm_init(struct us_data *us); +static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us); +static int usb_stor_sddr09_init(struct us_data *us); + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id sddr09_usb_ids[] = { +# include "unusual_sddr09.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, sddr09_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev sddr09_unusual_dev_list[] = { +# include "unusual_sddr09.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) ) @@ -1406,7 +1450,7 @@ sddr09_common_init(struct us_data *us) { * unusual devices list but called from here then LUN 0 of the combo reader * is not recognized. But I do not know what precisely these calls do. */ -int +static int usb_stor_sddr09_dpcm_init(struct us_data *us) { int result; unsigned char *data = us->iobuf; @@ -1456,7 +1500,7 @@ usb_stor_sddr09_dpcm_init(struct us_data *us) { /* * Transport for the Microtech DPCM-USB */ -int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us) +static int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us) { int ret; @@ -1498,7 +1542,7 @@ int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us) /* * Transport for the Sandisk SDDR-09 */ -int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) +static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) { static unsigned char sensekey = 0, sensecode = 0; static unsigned char havefakesense = 0; @@ -1697,7 +1741,60 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) /* * Initialization routine for the sddr09 subdriver */ -int +static int usb_stor_sddr09_init(struct us_data *us) { return sddr09_common_init(us); } + +static int sddr09_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - sddr09_usb_ids) + sddr09_unusual_dev_list); + if (result) + return result; + + if (us->protocol == US_PR_DPCM_USB) { + us->transport_name = "Control/Bulk-EUSB/SDDR09"; + us->transport = dpcm_transport; + us->transport_reset = usb_stor_CB_reset; + us->max_lun = 1; + } else { + us->transport_name = "EUSB/SDDR09"; + us->transport = sddr09_transport; + us->transport_reset = usb_stor_CB_reset; + us->max_lun = 0; + } + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver sddr09_driver = { + .name = "ums-sddr09", + .probe = sddr09_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = sddr09_usb_ids, + .soft_unbind = 1, +}; + +static int __init sddr09_init(void) +{ + return usb_register(&sddr09_driver); +} + +static void __exit sddr09_exit(void) +{ + usb_deregister(&sddr09_driver); +} + +module_init(sddr09_init); +module_exit(sddr09_exit); diff --git a/drivers/usb/storage/sddr09.h b/drivers/usb/storage/sddr09.h deleted file mode 100644 index b701172e12e..00000000000 --- a/drivers/usb/storage/sddr09.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Driver for SanDisk SDDR-09 SmartMedia reader - * Header File - * - * Current development and maintenance by: - * (c) 2000 Robert Baruch (autophile@dol.net) - * (c) 2002 Andries Brouwer (aeb@cwi.nl) - * - * See sddr09.c for more explanation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _USB_SHUTTLE_EUSB_SDDR09_H -#define _USB_SHUTTLE_EUSB_SDDR09_H - -/* Sandisk SDDR-09 stuff */ - -extern int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us); -extern int usb_stor_sddr09_init(struct us_data *us); - -/* Microtech DPCM-USB stuff */ - -extern int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us); -extern int usb_stor_sddr09_dpcm_init(struct us_data *us); - -#endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index cfde74a6faa..1fe7062f1cd 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -53,6 +53,11 @@ * as opposed to devices that do something strangely or wrongly. */ +#if !defined(CONFIG_USB_STORAGE_SDDR09) && \ + !defined(CONFIG_USB_STORAGE_SDDR09_MODULE) +#define NO_SDDR09 +#endif + /* patch submitted by Vivian Bregier */ UNUSUAL_DEV( 0x03eb, 0x2002, 0x0100, 0x0100, @@ -246,12 +251,7 @@ UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), -#ifdef CONFIG_USB_STORAGE_SDDR09 -UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, - "Microtech", - "CameraMate (DPCM_USB)", - US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ), -#else +#ifdef NO_SDDR09 UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, "Microtech", "CameraMate", @@ -467,20 +467,7 @@ UNUSUAL_DEV( 0x04e6, 0x0002, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, US_FL_SCM_MULT_TARG ), -#ifdef CONFIG_USB_STORAGE_SDDR09 -UNUSUAL_DEV( 0x04e6, 0x0003, 0x0000, 0x9999, - "Sandisk", - "ImageMate SDDR09", - US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, - 0), - -/* This entry is from Andries.Brouwer@cwi.nl */ -UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208, - "SCM Microsystems", - "eUSB SmartMedia / CompactFlash Adapter", - US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init, - 0), -#else +#ifdef NO_SDDR09 UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208, "SCM Microsystems", "eUSB CompactFlash Adapter", @@ -935,14 +922,6 @@ UNUSUAL_DEV( 0x0644, 0x0000, 0x0100, 0x0100, "Floppy Drive", US_SC_UFI, US_PR_CB, NULL, 0 ), -#ifdef CONFIG_USB_STORAGE_SDDR09 -UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100, - "Olympus", - "Camedia MAUSB-2", - US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, - 0), -#endif - /* Reported by Darsen Lu */ UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001, "SigmaTel", @@ -1057,14 +1036,6 @@ UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100, US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN ), -#ifdef CONFIG_USB_STORAGE_SDDR09 -UNUSUAL_DEV( 0x0781, 0x0200, 0x0000, 0x9999, - "Sandisk", - "ImageMate SDDR-09", - US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, - 0), -#endif - #ifdef CONFIG_USB_STORAGE_FREECOM UNUSUAL_DEV( 0x07ab, 0xfc01, 0x0000, 0x9999, "Freecom", @@ -1091,12 +1062,7 @@ UNUSUAL_DEV( 0x07af, 0x0005, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, US_FL_SCM_MULT_TARG ), -#ifdef CONFIG_USB_STORAGE_SDDR09 -UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, - "Microtech", - "CameraMate (DPCM_USB)", - US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ), -#else +#ifdef NO_SDDR09 UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, "Microtech", "CameraMate", diff --git a/drivers/usb/storage/unusual_sddr09.h b/drivers/usb/storage/unusual_sddr09.h new file mode 100644 index 00000000000..50cab511a4d --- /dev/null +++ b/drivers/usb/storage/unusual_sddr09.h @@ -0,0 +1,56 @@ +/* Unusual Devices File for SanDisk SDDR-09 SmartMedia reader + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_SDDR09) || \ + defined(CONFIG_USB_STORAGE_SDDR09_MODULE) + +UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, + "Microtech", + "CameraMate (DPCM_USB)", + US_SC_SCSI, US_PR_DPCM_USB, NULL, 0), + +UNUSUAL_DEV( 0x04e6, 0x0003, 0x0000, 0x9999, + "Sandisk", + "ImageMate SDDR09", + US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, + 0), + +/* This entry is from Andries.Brouwer@cwi.nl */ +UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208, + "SCM Microsystems", + "eUSB SmartMedia / CompactFlash Adapter", + US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init, + 0), + +UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100, + "Olympus", + "Camedia MAUSB-2", + US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, + 0), + +UNUSUAL_DEV( 0x0781, 0x0200, 0x0000, 0x9999, + "Sandisk", + "ImageMate SDDR-09", + US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, + 0), + +UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, + "Microtech", + "CameraMate (DPCM_USB)", + US_SC_SCSI, US_PR_DPCM_USB, NULL, 0), + +#endif /* defined(CONFIG_USB_STORAGE_SDDR09) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 490ea761398..33cce41a5e8 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -69,9 +69,6 @@ #ifdef CONFIG_USB_STORAGE_USBAT #include "shuttle_usbat.h" #endif -#ifdef CONFIG_USB_STORAGE_SDDR09 -#include "sddr09.h" -#endif #ifdef CONFIG_USB_STORAGE_SDDR55 #include "sddr55.h" #endif @@ -631,15 +628,6 @@ static void get_transport(struct us_data *us) break; #endif -#ifdef CONFIG_USB_STORAGE_SDDR09 - case US_PR_EUSB_SDDR09: - us->transport_name = "EUSB/SDDR09"; - us->transport = sddr09_transport; - us->transport_reset = usb_stor_CB_reset; - us->max_lun = 0; - break; -#endif - #ifdef CONFIG_USB_STORAGE_SDDR55 case US_PR_SDDR55: us->transport_name = "SDDR55"; @@ -649,15 +637,6 @@ static void get_transport(struct us_data *us) break; #endif -#ifdef CONFIG_USB_STORAGE_DPCM - case US_PR_DPCM_USB: - us->transport_name = "Control/Bulk-EUSB/SDDR09"; - us->transport = dpcm_transport; - us->transport_reset = usb_stor_CB_reset; - us->max_lun = 1; - break; -#endif - #ifdef CONFIG_USB_STORAGE_FREECOM case US_PR_FREECOM: us->transport_name = "Freecom"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index 1924e322940..f808c5262d0 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -77,6 +77,7 @@ struct ignore_entry { } static struct ignore_entry ignore_ids[] = { +# include "unusual_sddr09.h" { } /* Terminating entry */ }; -- GitLab From 32d5493eb83a217c3b1eba4b98cd6d19864f71a8 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:47:54 -0500 Subject: [PATCH 4338/4982] usb-storage: make isd200 a separate module This patch (as1208) converts usb-storage's isd200 subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/isd200.c | 94 +++++++++++++++++++++++++++- drivers/usb/storage/isd200.h | 31 --------- drivers/usb/storage/unusual_devs.h | 42 ------------- drivers/usb/storage/unusual_isd200.h | 57 +++++++++++++++++ drivers/usb/storage/usb.c | 10 --- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 154 insertions(+), 88 deletions(-) delete mode 100644 drivers/usb/storage/isd200.h create mode 100644 drivers/usb/storage/unusual_isd200.h diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 7be8899f255..fc356a770a7 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -46,7 +46,7 @@ config USB_STORAGE_FREECOM Freecom has a web page at . config USB_STORAGE_ISD200 - bool "ISD-200 USB/ATA Bridge support" + tristate "ISD-200 USB/ATA Bridge support" depends on USB_STORAGE ---help--- Say Y here if you want to use USB Mass Store devices based @@ -61,6 +61,8 @@ config USB_STORAGE_ISD200 - CyQ've CQ8060A CDRW drive - Planex eXtreme Drive RX-25HU USB-IDE cable (not model RX-25U) + If this driver is compiled as a module, it will be named ums-isd200. + config USB_STORAGE_USBAT bool "USBAT/USBAT02-based storage support" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index a52740a9560..b47f94e59fd 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -13,7 +13,6 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o usb-storage-obj-$(CONFIG_USB_STORAGE_USBAT) += shuttle_usbat.o usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR55) += sddr55.o usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM) += freecom.o -usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200) += isd200.o usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o @@ -30,6 +29,8 @@ else obj-$(CONFIG_USB) += libusual.o usual-tables.o endif +obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o +ums-isd200-objs := isd200.o ums-sddr09-objs := sddr09.o diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index 383abf2516a..df943008538 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -44,6 +44,7 @@ #include #include +#include #include #include #include @@ -57,7 +58,50 @@ #include "protocol.h" #include "debug.h" #include "scsiglue.h" -#include "isd200.h" + + +static int isd200_Initialization(struct us_data *us); + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id isd200_usb_ids[] = { +# include "unusual_isd200.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, isd200_usb_ids); + +#undef UNUSUAL_DEV +#undef USUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev isd200_unusual_dev_list[] = { +# include "unusual_isd200.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV +#undef USUAL_DEV /* Timeout defines (in Seconds) */ @@ -1518,7 +1562,7 @@ static int isd200_init_info(struct us_data *us) * Initialization for the ISD200 */ -int isd200_Initialization(struct us_data *us) +static int isd200_Initialization(struct us_data *us) { US_DEBUGP("ISD200 Initialization...\n"); @@ -1549,7 +1593,7 @@ int isd200_Initialization(struct us_data *us) * */ -void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us) +static void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us) { int sendToTransport = 1, orig_bufflen; union ata_cdb ataCdb; @@ -1570,3 +1614,47 @@ void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us) isd200_srb_set_bufflen(srb, orig_bufflen); } + +static int isd200_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - isd200_usb_ids) + isd200_unusual_dev_list); + if (result) + return result; + + us->protocol_name = "ISD200 ATA/ATAPI"; + us->proto_handler = isd200_ata_command; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver isd200_driver = { + .name = "ums-isd200", + .probe = isd200_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = isd200_usb_ids, + .soft_unbind = 1, +}; + +static int __init isd200_init(void) +{ + return usb_register(&isd200_driver); +} + +static void __exit isd200_exit(void) +{ + usb_deregister(&isd200_driver); +} + +module_init(isd200_init); +module_exit(isd200_exit); diff --git a/drivers/usb/storage/isd200.h b/drivers/usb/storage/isd200.h deleted file mode 100644 index 0a35f4fa78f..00000000000 --- a/drivers/usb/storage/isd200.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Header File for In-System Design, Inc. ISD200 ASIC - * - * First release - * - * Current development and maintenance by: - * (c) 2000 In-System Design, Inc. (support@in-system.com) - * - * See isd200.c for more information. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _USB_ISD200_H -#define _USB_ISD200_H - -extern void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us); -extern int isd200_Initialization(struct us_data *us); - -#endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 1fe7062f1cd..83ce1d33554 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -632,14 +632,6 @@ UNUSUAL_DEV( 0x054c, 0x0025, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), -#ifdef CONFIG_USB_STORAGE_ISD200 -UNUSUAL_DEV( 0x054c, 0x002b, 0x0100, 0x0110, - "Sony", - "Portable USB Harddrive V2", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), -#endif - /* Submitted by Olaf Hering, SuSE Bugzilla #49049 */ UNUSUAL_DEV( 0x054c, 0x002c, 0x0501, 0x2000, "Sony", @@ -785,32 +777,6 @@ UNUSUAL_DEV( 0x05ab, 0x0060, 0x1104, 0x1110, US_SC_SCSI, US_PR_BULK, NULL, US_FL_NEED_OVERRIDE ), -#ifdef CONFIG_USB_STORAGE_ISD200 -UNUSUAL_DEV( 0x05ab, 0x0031, 0x0100, 0x0110, - "In-System", - "USB/IDE Bridge (ATA/ATAPI)", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), - -UNUSUAL_DEV( 0x05ab, 0x0301, 0x0100, 0x0110, - "In-System", - "Portable USB Harddrive V2", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), - -UNUSUAL_DEV( 0x05ab, 0x0351, 0x0100, 0x0110, - "In-System", - "Portable USB Harddrive V2", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), - -UNUSUAL_DEV( 0x05ab, 0x5701, 0x0100, 0x0110, - "In-System", - "USB Storage Adapter V2", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), -#endif - /* Submitted by Sven Anderson * There are at least four ProductIDs used for iPods, so I added 0x1202 and * 0x1204. They just need the US_FL_FIX_CAPACITY. As the bcdDevice appears @@ -1375,14 +1341,6 @@ UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SANE_SENSE ), -#ifdef CONFIG_USB_STORAGE_ISD200 -UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, - "ATI", - "USB Cable 205", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), -#endif - #ifdef CONFIG_USB_STORAGE_DATAFAB UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, "Acomdata", diff --git a/drivers/usb/storage/unusual_isd200.h b/drivers/usb/storage/unusual_isd200.h new file mode 100644 index 00000000000..0d99dde3382 --- /dev/null +++ b/drivers/usb/storage/unusual_isd200.h @@ -0,0 +1,57 @@ +/* Unusual Devices File for In-System Design, Inc. ISD200 ASIC + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_ISD200) || \ + defined(CONFIG_USB_STORAGE_ISD200_MODULE) + +UNUSUAL_DEV( 0x054c, 0x002b, 0x0100, 0x0110, + "Sony", + "Portable USB Harddrive V2", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0), + +UNUSUAL_DEV( 0x05ab, 0x0031, 0x0100, 0x0110, + "In-System", + "USB/IDE Bridge (ATA/ATAPI)", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0), + +UNUSUAL_DEV( 0x05ab, 0x0301, 0x0100, 0x0110, + "In-System", + "Portable USB Harddrive V2", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0), + +UNUSUAL_DEV( 0x05ab, 0x0351, 0x0100, 0x0110, + "In-System", + "Portable USB Harddrive V2", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0), + +UNUSUAL_DEV( 0x05ab, 0x5701, 0x0100, 0x0110, + "In-System", + "USB Storage Adapter V2", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0), + +UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, + "ATI", + "USB Cable 205", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0), + +#endif /* defined(CONFIG_USB_STORAGE_ISD200) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 33cce41a5e8..e65cbba452b 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -75,9 +75,6 @@ #ifdef CONFIG_USB_STORAGE_FREECOM #include "freecom.h" #endif -#ifdef CONFIG_USB_STORAGE_ISD200 -#include "isd200.h" -#endif #ifdef CONFIG_USB_STORAGE_DATAFAB #include "datafab.h" #endif @@ -721,13 +718,6 @@ static void get_protocol(struct us_data *us) us->proto_handler = usb_stor_ufi_command; break; -#ifdef CONFIG_USB_STORAGE_ISD200 - case US_SC_ISD200: - us->protocol_name = "ISD200 ATA/ATAPI"; - us->proto_handler = isd200_ata_command; - break; -#endif - #ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB case US_SC_CYP_ATACB: us->protocol_name = "Transparent SCSI with Cypress ATACB"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index f808c5262d0..61ebddcc9ae 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -77,6 +77,7 @@ struct ignore_entry { } static struct ignore_entry ignore_ids[] = { +# include "unusual_isd200.h" # include "unusual_sddr09.h" { } /* Terminating entry */ }; -- GitLab From 70fcc0050733a7cd1b452cfa3de3a9b376412565 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:47:59 -0500 Subject: [PATCH 4339/4982] usb-storage: make sddr55 a separate module This patch (as1209) converts usb-storage's sddr55 subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/sddr55.c | 92 +++++++++++++++++++++++++++- drivers/usb/storage/sddr55.h | 32 ---------- drivers/usb/storage/unusual_devs.h | 32 ---------- drivers/usb/storage/unusual_sddr55.h | 44 +++++++++++++ drivers/usb/storage/usb.c | 12 ---- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 139 insertions(+), 81 deletions(-) delete mode 100644 drivers/usb/storage/sddr55.h create mode 100644 drivers/usb/storage/unusual_sddr55.h diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index fc356a770a7..e6cc245257f 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -95,12 +95,14 @@ config USB_STORAGE_SDDR09 If this driver is compiled as a module, it will be named ums-sddr09. config USB_STORAGE_SDDR55 - bool "SanDisk SDDR-55 SmartMedia support" + tristate "SanDisk SDDR-55 SmartMedia support" depends on USB_STORAGE help Say Y here to include additional code to support the Sandisk SDDR-55 SmartMedia reader in the USB Mass Storage driver. + If this driver is compiled as a module, it will be named ums-sddr55. + config USB_STORAGE_JUMPSHOT bool "Lexar Jumpshot Compact Flash Reader" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index b47f94e59fd..5fb7847e41a 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o usb-storage-obj-$(CONFIG_USB_STORAGE_USBAT) += shuttle_usbat.o -usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR55) += sddr55.o usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM) += freecom.o usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o @@ -31,6 +30,8 @@ endif obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o +obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o ums-isd200-objs := isd200.o ums-sddr09-objs := sddr09.o +ums-sddr55-objs := sddr55.o diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c index 5a0106ba256..e97716f8eb0 100644 --- a/drivers/usb/storage/sddr55.c +++ b/drivers/usb/storage/sddr55.c @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -33,7 +34,45 @@ #include "transport.h" #include "protocol.h" #include "debug.h" -#include "sddr55.h" + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id sddr55_usb_ids[] = { +# include "unusual_sddr55.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, sddr55_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev sddr55_unusual_dev_list[] = { +# include "unusual_sddr55.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) ) @@ -513,7 +552,8 @@ static int sddr55_read_deviceID(struct us_data *us, } -int sddr55_reset(struct us_data *us) { +static int sddr55_reset(struct us_data *us) +{ return 0; } @@ -734,7 +774,7 @@ static void sddr55_card_info_destructor(void *extra) { /* * Transport for the Sandisk SDDR-55 */ -int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us) +static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us) { int result; static unsigned char inquiry_response[8] = { @@ -931,3 +971,49 @@ int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us) return USB_STOR_TRANSPORT_FAILED; // FIXME: sense buffer? } + +static int sddr55_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - sddr55_usb_ids) + sddr55_unusual_dev_list); + if (result) + return result; + + us->transport_name = "SDDR55"; + us->transport = sddr55_transport; + us->transport_reset = sddr55_reset; + us->max_lun = 0; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver sddr55_driver = { + .name = "ums-sddr55", + .probe = sddr55_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = sddr55_usb_ids, + .soft_unbind = 1, +}; + +static int __init sddr55_init(void) +{ + return usb_register(&sddr55_driver); +} + +static void __exit sddr55_exit(void) +{ + usb_deregister(&sddr55_driver); +} + +module_init(sddr55_init); +module_exit(sddr55_exit); diff --git a/drivers/usb/storage/sddr55.h b/drivers/usb/storage/sddr55.h deleted file mode 100644 index a815a0470c8..00000000000 --- a/drivers/usb/storage/sddr55.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Driver for SanDisk SDDR-55 SmartMedia reader - * Header File - * - * Current development and maintenance by: - * (c) 2002 Simon Munton - * - * See sddr55.c for more explanation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _USB_SHUTTLE_EUSB_SDDR55_H -#define _USB_SHUTTLE_EUSB_SDDR55_H - -/* Sandisk SDDR-55 stuff */ - -extern int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us); -extern int sddr55_reset(struct us_data *us); - -#endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 83ce1d33554..50034e141f9 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1098,15 +1098,6 @@ UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff, US_SC_SCSI, US_PR_DATAFAB, NULL, 0 ), #endif - -#ifdef CONFIG_USB_STORAGE_SDDR55 -/* Contributed by Peter Waechtler */ -UNUSUAL_DEV( 0x07c4, 0xa103, 0x0000, 0x9999, - "Datafab", - "MDSM-B reader", - US_SC_SCSI, US_PR_SDDR55, NULL, - US_FL_FIX_INQUIRY ), -#endif #ifdef CONFIG_USB_STORAGE_DATAFAB /* Submitted by Olaf Hering */ @@ -1116,14 +1107,6 @@ UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff, US_SC_SCSI, US_PR_DATAFAB, NULL, 0 ), #endif -#ifdef CONFIG_USB_STORAGE_SDDR55 -/* SM part - aeb */ -UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff, - "Datafab Systems, Inc.", - "USB to CF + SM Combo (LC1)", - US_SC_SCSI, US_PR_SDDR55, NULL, - US_FL_SINGLE_LUN ), -#endif #ifdef CONFIG_USB_STORAGE_DATAFAB /* Reported by Felix Moeller @@ -1348,13 +1331,6 @@ UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, US_SC_SCSI, US_PR_DATAFAB, NULL, US_FL_SINGLE_LUN ), #endif -#ifdef CONFIG_USB_STORAGE_SDDR55 -UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, - "Acomdata", - "SM", - US_SC_SCSI, US_PR_SDDR55, NULL, - US_FL_SINGLE_LUN ), -#endif UNUSUAL_DEV( 0x0d49, 0x7310, 0x0000, 0x9999, "Maxtor", @@ -2041,14 +2017,6 @@ UNUSUAL_DEV( 0x4146, 0xba01, 0x0100, 0x0100, "Micro Mini 1GB", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), -#ifdef CONFIG_USB_STORAGE_SDDR55 -UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999, - "Sandisk", - "ImageMate SDDR55", - US_SC_SCSI, US_PR_SDDR55, NULL, - US_FL_SINGLE_LUN), -#endif - /* Reported by Andrew Simmons */ UNUSUAL_DEV( 0xed06, 0x4500, 0x0001, 0x0001, "DataStor", diff --git a/drivers/usb/storage/unusual_sddr55.h b/drivers/usb/storage/unusual_sddr55.h new file mode 100644 index 00000000000..ae81ef7a1cf --- /dev/null +++ b/drivers/usb/storage/unusual_sddr55.h @@ -0,0 +1,44 @@ +/* Unusual Devices File for SanDisk SDDR-55 SmartMedia reader + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_SDDR55) || \ + defined(CONFIG_USB_STORAGE_SDDR55_MODULE) + +/* Contributed by Peter Waechtler */ +UNUSUAL_DEV( 0x07c4, 0xa103, 0x0000, 0x9999, + "Datafab", + "MDSM-B reader", + US_SC_SCSI, US_PR_SDDR55, NULL, + US_FL_FIX_INQUIRY), + +/* SM part - aeb */ +UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff, + "Datafab Systems, Inc.", + "USB to CF + SM Combo (LC1)", + US_SC_SCSI, US_PR_SDDR55, NULL, 0), + +UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, + "Acomdata", + "SM", + US_SC_SCSI, US_PR_SDDR55, NULL, 0), + +UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999, + "Sandisk", + "ImageMate SDDR55", + US_SC_SCSI, US_PR_SDDR55, NULL, 0), + +#endif /* defined(CONFIG_USB_STORAGE_SDDR55) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index e65cbba452b..238f271d817 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -69,9 +69,6 @@ #ifdef CONFIG_USB_STORAGE_USBAT #include "shuttle_usbat.h" #endif -#ifdef CONFIG_USB_STORAGE_SDDR55 -#include "sddr55.h" -#endif #ifdef CONFIG_USB_STORAGE_FREECOM #include "freecom.h" #endif @@ -625,15 +622,6 @@ static void get_transport(struct us_data *us) break; #endif -#ifdef CONFIG_USB_STORAGE_SDDR55 - case US_PR_SDDR55: - us->transport_name = "SDDR55"; - us->transport = sddr55_transport; - us->transport_reset = sddr55_reset; - us->max_lun = 0; - break; -#endif - #ifdef CONFIG_USB_STORAGE_FREECOM case US_PR_FREECOM: us->transport_name = "Freecom"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index 61ebddcc9ae..5f2703fa48e 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -79,6 +79,7 @@ struct ignore_entry { static struct ignore_entry ignore_ids[] = { # include "unusual_isd200.h" # include "unusual_sddr09.h" +# include "unusual_sddr55.h" { } /* Terminating entry */ }; -- GitLab From fcdb51401f7f695b7fb782721b2e33372c5a06ce Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:04 -0500 Subject: [PATCH 4340/4982] usb-storage: make cypress_atacb a separate module This patch (as1210) converts usb-storage's cypress_atacb subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/cypress_atacb.c | 88 ++++++++++++++++++- .../{cypress_atacb.h => unusual_cypress.h} | 27 ++++-- drivers/usb/storage/unusual_devs.h | 16 ---- drivers/usb/storage/usb.c | 11 --- drivers/usb/storage/usual-tables.c | 1 + 7 files changed, 111 insertions(+), 39 deletions(-) rename drivers/usb/storage/{cypress_atacb.h => unusual_cypress.h} (54%) diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index e6cc245257f..2c73fa97d94 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -146,7 +146,7 @@ config USB_STORAGE_KARMA operation. config USB_STORAGE_CYPRESS_ATACB - bool "SAT emulation on Cypress USB/ATA Bridge with ATACB" + tristate "SAT emulation on Cypress USB/ATA Bridge with ATACB" depends on USB_STORAGE ---help--- Say Y here if you want to use SAT (ata pass through) on devices based @@ -156,6 +156,8 @@ config USB_STORAGE_CYPRESS_ATACB If you say no here your device will still work with the standard usb mass storage class. + If this driver is compiled as a module, it will be named ums-cypress. + config USB_LIBUSUAL bool "The shared table of common (or usual) storage devices" depends on USB diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 5fb7847e41a..0650f022e56 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -17,7 +17,6 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA) += karma.o -usb-storage-obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += cypress_atacb.o usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ initializers.o sierra_ms.o option_ms.o $(usb-storage-obj-y) @@ -28,10 +27,12 @@ else obj-$(CONFIG_USB) += libusual.o usual-tables.o endif +obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o +ums-cypress-objs := cypress_atacb.o ums-isd200-objs := isd200.o ums-sddr09-objs := sddr09.o ums-sddr55-objs := sddr55.o diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c index 9466a99baab..19306f7b1da 100644 --- a/drivers/usb/storage/cypress_atacb.c +++ b/drivers/usb/storage/cypress_atacb.c @@ -19,6 +19,7 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include #include #include @@ -29,6 +30,46 @@ #include "scsiglue.h" #include "debug.h" + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id cypress_usb_ids[] = { +# include "unusual_cypress.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, cypress_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev cypress_unusual_dev_list[] = { +# include "unusual_cypress.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + + /* * ATACB is a protocol used on cypress usb<->ata bridge to * send raw ATA command over mass storage @@ -36,7 +77,7 @@ * More info that be found on cy7c68310_8.pdf and cy7c68300c_8.pdf * datasheet from cypress.com. */ -void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us) +static void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us) { unsigned char save_cmnd[MAX_COMMAND_SIZE]; @@ -197,3 +238,48 @@ end: if (srb->cmnd[0] == ATA_12) srb->cmd_len = 12; } + + +static int cypress_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - cypress_usb_ids) + cypress_unusual_dev_list); + if (result) + return result; + + us->protocol_name = "Transparent SCSI with Cypress ATACB"; + us->proto_handler = cypress_atacb_passthrough; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver cypress_driver = { + .name = "ums-cypress", + .probe = cypress_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = cypress_usb_ids, + .soft_unbind = 1, +}; + +static int __init cypress_init(void) +{ + return usb_register(&cypress_driver); +} + +static void __exit cypress_exit(void) +{ + usb_deregister(&cypress_driver); +} + +module_init(cypress_init); +module_exit(cypress_exit); diff --git a/drivers/usb/storage/cypress_atacb.h b/drivers/usb/storage/unusual_cypress.h similarity index 54% rename from drivers/usb/storage/cypress_atacb.h rename to drivers/usb/storage/unusual_cypress.h index fbada898d56..44be6d75dab 100644 --- a/drivers/usb/storage/cypress_atacb.h +++ b/drivers/usb/storage/unusual_cypress.h @@ -1,8 +1,5 @@ -/* - * Support for emulating SAT (ata pass through) on devices based - * on the Cypress USB/ATA bridge supporting ATACB. - * - * Copyright (c) 2008 Matthieu Castet (castet.matthieu@free.fr) +/* Unusual Devices File for devices based on the Cypress USB/ATA bridge + * with support for ATACB * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -19,7 +16,19 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _CYPRESS_ATACB_H_ -#define _CYPRESS_ATACB_H_ -extern void cypress_atacb_passthrough(struct scsi_cmnd*, struct us_data*); -#endif +#if defined(CONFIG_USB_STORAGE_CYPRESS_ATACB) || \ + defined(CONFIG_USB_STORAGE_CYPRESS_ATACB_MODULE) + +/* CY7C68300 : support atacb */ +UNUSUAL_DEV( 0x04b4, 0x6830, 0x0000, 0x9999, + "Cypress", + "Cypress AT2LP", + US_SC_CYP_ATACB, US_PR_DEVICE, NULL, 0), + +/* CY7C68310 : support atacb and atacb2 */ +UNUSUAL_DEV( 0x04b4, 0x6831, 0x0000, 0x9999, + "Cypress", + "Cypress ISD-300LP", + US_SC_CYP_ATACB, US_PR_DEVICE, NULL, 0), + +#endif /* defined(CONFIG_USB_STORAGE_CYPRESS_ATACB) || ... */ diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 50034e141f9..eff97aed7bf 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -375,22 +375,6 @@ UNUSUAL_DEV( 0x04b3, 0x4001, 0x0110, 0x0110, US_SC_DEVICE, US_PR_CB, NULL, US_FL_MAX_SECTORS_MIN), -#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB -/* CY7C68300 : support atacb */ -UNUSUAL_DEV( 0x04b4, 0x6830, 0x0000, 0x9999, - "Cypress", - "Cypress AT2LP", - US_SC_CYP_ATACB, US_PR_DEVICE, NULL, - 0), - -/* CY7C68310 : support atacb and atacb2 */ -UNUSUAL_DEV( 0x04b4, 0x6831, 0x0000, 0x9999, - "Cypress", - "Cypress ISD-300LP", - US_SC_CYP_ATACB, US_PR_DEVICE, NULL, - 0), -#endif - /* Reported by Simon Levitt * This entry needs Sub and Proto fields */ UNUSUAL_DEV( 0x04b8, 0x0601, 0x0100, 0x0100, diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 238f271d817..241e1944cf1 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -87,9 +87,6 @@ #ifdef CONFIG_USB_STORAGE_KARMA #include "karma.h" #endif -#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB -#include "cypress_atacb.h" -#endif #include "sierra_ms.h" #include "option_ms.h" @@ -705,14 +702,6 @@ static void get_protocol(struct us_data *us) us->protocol_name = "Uniform Floppy Interface (UFI)"; us->proto_handler = usb_stor_ufi_command; break; - -#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB - case US_SC_CYP_ATACB: - us->protocol_name = "Transparent SCSI with Cypress ATACB"; - us->proto_handler = cypress_atacb_passthrough; - break; -#endif - } } diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index 5f2703fa48e..be461ee9f00 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -77,6 +77,7 @@ struct ignore_entry { } static struct ignore_entry ignore_ids[] = { +# include "unusual_cypress.h" # include "unusual_isd200.h" # include "unusual_sddr09.h" # include "unusual_sddr55.h" -- GitLab From 26d6818f19d0ab018f28a20d699511c1efdf508b Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:08 -0500 Subject: [PATCH 4341/4982] usb-storage: make shuttle_usbat a separate module This patch (as1211) converts usb-storage's shuttle_usbat subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/shuttle_usbat.c | 199 +++++++++++++++++++++++++--- drivers/usb/storage/shuttle_usbat.h | 123 ----------------- drivers/usb/storage/unusual_devs.h | 28 ---- drivers/usb/storage/unusual_usbat.h | 43 ++++++ drivers/usb/storage/usb.c | 12 -- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 227 insertions(+), 186 deletions(-) delete mode 100644 drivers/usb/storage/shuttle_usbat.h create mode 100644 drivers/usb/storage/unusual_usbat.h diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 2c73fa97d94..44c6b1940f7 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -64,7 +64,7 @@ config USB_STORAGE_ISD200 If this driver is compiled as a module, it will be named ums-isd200. config USB_STORAGE_USBAT - bool "USBAT/USBAT02-based storage support" + tristate "USBAT/USBAT02-based storage support" depends on USB_STORAGE help Say Y here to include additional code to support storage devices @@ -84,6 +84,8 @@ config USB_STORAGE_USBAT - RCA LYRA MP3 portable - Sandisk ImageMate SDDR-05b + If this driver is compiled as a module, it will be named ums-usbat. + config USB_STORAGE_SDDR09 tristate "SanDisk SDDR-09 (and other SmartMedia, including DPCM) support" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 0650f022e56..2387368cb7a 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -10,7 +10,6 @@ EXTRA_CFLAGS := -Idrivers/scsi obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o -usb-storage-obj-$(CONFIG_USB_STORAGE_USBAT) += shuttle_usbat.o usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM) += freecom.o usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o @@ -31,8 +30,10 @@ obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o +obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o ums-cypress-objs := cypress_atacb.o ums-isd200-objs := isd200.o ums-sddr09-objs := sddr09.o ums-sddr55-objs := sddr55.o +ums-usbat-objs := shuttle_usbat.o diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index ae6d64810d2..d4fe0bb327a 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -42,6 +42,7 @@ */ #include +#include #include #include @@ -52,7 +53,97 @@ #include "transport.h" #include "protocol.h" #include "debug.h" -#include "shuttle_usbat.h" + + +/* Supported device types */ +#define USBAT_DEV_HP8200 0x01 +#define USBAT_DEV_FLASH 0x02 + +#define USBAT_EPP_PORT 0x10 +#define USBAT_EPP_REGISTER 0x30 +#define USBAT_ATA 0x40 +#define USBAT_ISA 0x50 + +/* Commands (need to be logically OR'd with an access type */ +#define USBAT_CMD_READ_REG 0x00 +#define USBAT_CMD_WRITE_REG 0x01 +#define USBAT_CMD_READ_BLOCK 0x02 +#define USBAT_CMD_WRITE_BLOCK 0x03 +#define USBAT_CMD_COND_READ_BLOCK 0x04 +#define USBAT_CMD_COND_WRITE_BLOCK 0x05 +#define USBAT_CMD_WRITE_REGS 0x07 + +/* Commands (these don't need an access type) */ +#define USBAT_CMD_EXEC_CMD 0x80 +#define USBAT_CMD_SET_FEAT 0x81 +#define USBAT_CMD_UIO 0x82 + +/* Methods of accessing UIO register */ +#define USBAT_UIO_READ 1 +#define USBAT_UIO_WRITE 0 + +/* Qualifier bits */ +#define USBAT_QUAL_FCQ 0x20 /* full compare */ +#define USBAT_QUAL_ALQ 0x10 /* auto load subcount */ + +/* USBAT Flash Media status types */ +#define USBAT_FLASH_MEDIA_NONE 0 +#define USBAT_FLASH_MEDIA_CF 1 + +/* USBAT Flash Media change types */ +#define USBAT_FLASH_MEDIA_SAME 0 +#define USBAT_FLASH_MEDIA_CHANGED 1 + +/* USBAT ATA registers */ +#define USBAT_ATA_DATA 0x10 /* read/write data (R/W) */ +#define USBAT_ATA_FEATURES 0x11 /* set features (W) */ +#define USBAT_ATA_ERROR 0x11 /* error (R) */ +#define USBAT_ATA_SECCNT 0x12 /* sector count (R/W) */ +#define USBAT_ATA_SECNUM 0x13 /* sector number (R/W) */ +#define USBAT_ATA_LBA_ME 0x14 /* cylinder low (R/W) */ +#define USBAT_ATA_LBA_HI 0x15 /* cylinder high (R/W) */ +#define USBAT_ATA_DEVICE 0x16 /* head/device selection (R/W) */ +#define USBAT_ATA_STATUS 0x17 /* device status (R) */ +#define USBAT_ATA_CMD 0x17 /* device command (W) */ +#define USBAT_ATA_ALTSTATUS 0x0E /* status (no clear IRQ) (R) */ + +/* USBAT User I/O Data registers */ +#define USBAT_UIO_EPAD 0x80 /* Enable Peripheral Control Signals */ +#define USBAT_UIO_CDT 0x40 /* Card Detect (Read Only) */ + /* CDT = ACKD & !UI1 & !UI0 */ +#define USBAT_UIO_1 0x20 /* I/O 1 */ +#define USBAT_UIO_0 0x10 /* I/O 0 */ +#define USBAT_UIO_EPP_ATA 0x08 /* 1=EPP mode, 0=ATA mode */ +#define USBAT_UIO_UI1 0x04 /* Input 1 */ +#define USBAT_UIO_UI0 0x02 /* Input 0 */ +#define USBAT_UIO_INTR_ACK 0x01 /* Interrupt (ATA/ISA)/Acknowledge (EPP) */ + +/* USBAT User I/O Enable registers */ +#define USBAT_UIO_DRVRST 0x80 /* Reset Peripheral */ +#define USBAT_UIO_ACKD 0x40 /* Enable Card Detect */ +#define USBAT_UIO_OE1 0x20 /* I/O 1 set=output/clr=input */ + /* If ACKD=1, set OE1 to 1 also. */ +#define USBAT_UIO_OE0 0x10 /* I/O 0 set=output/clr=input */ +#define USBAT_UIO_ADPRST 0x01 /* Reset SCM chip */ + +/* USBAT Features */ +#define USBAT_FEAT_ETEN 0x80 /* External trigger enable */ +#define USBAT_FEAT_U1 0x08 +#define USBAT_FEAT_U0 0x04 +#define USBAT_FEAT_ET1 0x02 +#define USBAT_FEAT_ET2 0x01 + +struct usbat_info { + int devicetype; + + /* Used for Flash readers only */ + unsigned long sectors; /* total sector count */ + unsigned long ssize; /* sector size in bytes */ + + unsigned char sense_key; + unsigned long sense_asc; /* additional sense code */ + unsigned long sense_ascq; /* additional sense code qualifier */ +}; #define short_pack(LSB,MSB) ( ((u16)(LSB)) | ( ((u16)(MSB))<<8 ) ) #define LSB_of(s) ((s)&0xFF) @@ -63,6 +154,48 @@ static int transferred = 0; static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us); static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us); +static int init_usbat_cd(struct us_data *us); +static int init_usbat_flash(struct us_data *us); + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id usbat_usb_ids[] = { +# include "unusual_usbat.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, usbat_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev usbat_unusual_dev_list[] = { +# include "unusual_usbat.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + /* * Convenience function to produce an ATA read/write sectors command * Use cmd=0x20 for read, cmd=0x30 for write @@ -1684,37 +1817,61 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us) return USB_STOR_TRANSPORT_FAILED; } -int init_usbat_cd(struct us_data *us) +static int init_usbat_cd(struct us_data *us) { return init_usbat(us, USBAT_DEV_HP8200); } - -int init_usbat_flash(struct us_data *us) +static int init_usbat_flash(struct us_data *us) { return init_usbat(us, USBAT_DEV_FLASH); } -int init_usbat_probe(struct us_data *us) +static int usbat_probe(struct usb_interface *intf, + const struct usb_device_id *id) { - return init_usbat(us, 0); + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - usbat_usb_ids) + usbat_unusual_dev_list); + if (result) + return result; + + /* The actual transport will be determined later by the + * initialization routine; this is just a placeholder. + */ + us->transport_name = "Shuttle USBAT"; + us->transport = usbat_flash_transport; + us->transport_reset = usb_stor_CB_reset; + us->max_lun = 1; + + result = usb_stor_probe2(us); + return result; } -/* - * Default transport function. Attempts to detect which transport function - * should be called, makes it the new default, and calls it. - * - * This function should never be called. Our usbat_init() function detects the - * device type and changes the us->transport ptr to the transport function - * relevant to the device. - * However, we'll support this impossible(?) case anyway. - */ -int usbat_transport(struct scsi_cmnd *srb, struct us_data *us) +static struct usb_driver usbat_driver = { + .name = "ums-usbat", + .probe = usbat_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = usbat_usb_ids, + .soft_unbind = 1, +}; + +static int __init usbat_init(void) { - struct usbat_info *info = (struct usbat_info*) (us->extra); - - if (usbat_set_transport(us, info, 0)) - return USB_STOR_TRANSPORT_ERROR; + return usb_register(&usbat_driver); +} - return us->transport(srb, us); +static void __exit usbat_exit(void) +{ + usb_deregister(&usbat_driver); } + +module_init(usbat_init); +module_exit(usbat_exit); diff --git a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h deleted file mode 100644 index d8bfc43e904..00000000000 --- a/drivers/usb/storage/shuttle_usbat.h +++ /dev/null @@ -1,123 +0,0 @@ -/* Driver for SCM Microsystems USB-ATAPI cable - * Header File - * - * Current development and maintenance by: - * (c) 2000 Robert Baruch (autophile@dol.net) - * (c) 2004, 2005 Daniel Drake - * - * See shuttle_usbat.c for more explanation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _USB_SHUTTLE_USBAT_H -#define _USB_SHUTTLE_USBAT_H - -/* Supported device types */ -#define USBAT_DEV_HP8200 0x01 -#define USBAT_DEV_FLASH 0x02 - -#define USBAT_EPP_PORT 0x10 -#define USBAT_EPP_REGISTER 0x30 -#define USBAT_ATA 0x40 -#define USBAT_ISA 0x50 - -/* Commands (need to be logically OR'd with an access type */ -#define USBAT_CMD_READ_REG 0x00 -#define USBAT_CMD_WRITE_REG 0x01 -#define USBAT_CMD_READ_BLOCK 0x02 -#define USBAT_CMD_WRITE_BLOCK 0x03 -#define USBAT_CMD_COND_READ_BLOCK 0x04 -#define USBAT_CMD_COND_WRITE_BLOCK 0x05 -#define USBAT_CMD_WRITE_REGS 0x07 - -/* Commands (these don't need an access type) */ -#define USBAT_CMD_EXEC_CMD 0x80 -#define USBAT_CMD_SET_FEAT 0x81 -#define USBAT_CMD_UIO 0x82 - -/* Methods of accessing UIO register */ -#define USBAT_UIO_READ 1 -#define USBAT_UIO_WRITE 0 - -/* Qualifier bits */ -#define USBAT_QUAL_FCQ 0x20 /* full compare */ -#define USBAT_QUAL_ALQ 0x10 /* auto load subcount */ - -/* USBAT Flash Media status types */ -#define USBAT_FLASH_MEDIA_NONE 0 -#define USBAT_FLASH_MEDIA_CF 1 - -/* USBAT Flash Media change types */ -#define USBAT_FLASH_MEDIA_SAME 0 -#define USBAT_FLASH_MEDIA_CHANGED 1 - -/* USBAT ATA registers */ -#define USBAT_ATA_DATA 0x10 /* read/write data (R/W) */ -#define USBAT_ATA_FEATURES 0x11 /* set features (W) */ -#define USBAT_ATA_ERROR 0x11 /* error (R) */ -#define USBAT_ATA_SECCNT 0x12 /* sector count (R/W) */ -#define USBAT_ATA_SECNUM 0x13 /* sector number (R/W) */ -#define USBAT_ATA_LBA_ME 0x14 /* cylinder low (R/W) */ -#define USBAT_ATA_LBA_HI 0x15 /* cylinder high (R/W) */ -#define USBAT_ATA_DEVICE 0x16 /* head/device selection (R/W) */ -#define USBAT_ATA_STATUS 0x17 /* device status (R) */ -#define USBAT_ATA_CMD 0x17 /* device command (W) */ -#define USBAT_ATA_ALTSTATUS 0x0E /* status (no clear IRQ) (R) */ - -/* USBAT User I/O Data registers */ -#define USBAT_UIO_EPAD 0x80 /* Enable Peripheral Control Signals */ -#define USBAT_UIO_CDT 0x40 /* Card Detect (Read Only) */ - /* CDT = ACKD & !UI1 & !UI0 */ -#define USBAT_UIO_1 0x20 /* I/O 1 */ -#define USBAT_UIO_0 0x10 /* I/O 0 */ -#define USBAT_UIO_EPP_ATA 0x08 /* 1=EPP mode, 0=ATA mode */ -#define USBAT_UIO_UI1 0x04 /* Input 1 */ -#define USBAT_UIO_UI0 0x02 /* Input 0 */ -#define USBAT_UIO_INTR_ACK 0x01 /* Interrupt (ATA/ISA)/Acknowledge (EPP) */ - -/* USBAT User I/O Enable registers */ -#define USBAT_UIO_DRVRST 0x80 /* Reset Peripheral */ -#define USBAT_UIO_ACKD 0x40 /* Enable Card Detect */ -#define USBAT_UIO_OE1 0x20 /* I/O 1 set=output/clr=input */ - /* If ACKD=1, set OE1 to 1 also. */ -#define USBAT_UIO_OE0 0x10 /* I/O 0 set=output/clr=input */ -#define USBAT_UIO_ADPRST 0x01 /* Reset SCM chip */ - -/* USBAT Features */ -#define USBAT_FEAT_ETEN 0x80 /* External trigger enable */ -#define USBAT_FEAT_U1 0x08 -#define USBAT_FEAT_U0 0x04 -#define USBAT_FEAT_ET1 0x02 -#define USBAT_FEAT_ET2 0x01 - -extern int usbat_transport(struct scsi_cmnd *srb, struct us_data *us); -extern int init_usbat_cd(struct us_data *us); -extern int init_usbat_flash(struct us_data *us); -extern int init_usbat_probe(struct us_data *us); - -struct usbat_info { - int devicetype; - - /* Used for Flash readers only */ - unsigned long sectors; /* total sector count */ - unsigned long ssize; /* sector size in bytes */ - - unsigned char sense_key; - unsigned long sense_asc; /* additional sense code */ - unsigned long sense_ascq; /* additional sense code qualifier */ -}; - -#endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index eff97aed7bf..6462c4c54dc 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -85,18 +85,6 @@ UNUSUAL_DEV( 0x03f0, 0x0107, 0x0200, 0x0200, "CD-Writer+", US_SC_8070, US_PR_CB, NULL, 0), -#ifdef CONFIG_USB_STORAGE_USBAT -UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001, - "HP", - "CD-Writer+ 8200e", - US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), - -UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001, - "HP", - "CD-Writer+ CD-4e", - US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), -#endif - /* Reported by Ben Efros */ UNUSUAL_DEV( 0x03f0, 0x070c, 0x0000, 0x0000, "HP", @@ -506,14 +494,6 @@ UNUSUAL_DEV( 0x04e6, 0x0101, 0x0200, 0x0200, "CD-RW Device", US_SC_8020, US_PR_CB, NULL, 0), -#ifdef CONFIG_USB_STORAGE_USBAT -UNUSUAL_DEV( 0x04e6, 0x1010, 0x0000, 0x9999, - "Shuttle/SCM", - "USBAT-02", - US_SC_SCSI, US_PR_USBAT, init_usbat_flash, - US_FL_SINGLE_LUN), -#endif - /* Reported by Dmitry Khlystov */ UNUSUAL_DEV( 0x04e8, 0x507c, 0x0220, 0x0220, "Samsung", @@ -972,14 +952,6 @@ UNUSUAL_DEV( 0x0781, 0x0002, 0x0009, 0x0009, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), -#ifdef CONFIG_USB_STORAGE_USBAT -UNUSUAL_DEV( 0x0781, 0x0005, 0x0005, 0x0005, - "Sandisk", - "ImageMate SDDR-05b", - US_SC_SCSI, US_PR_USBAT, init_usbat_flash, - US_FL_SINGLE_LUN ), -#endif - UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100, "Sandisk", "ImageMate SDDR-12", diff --git a/drivers/usb/storage/unusual_usbat.h b/drivers/usb/storage/unusual_usbat.h new file mode 100644 index 00000000000..80e869f1018 --- /dev/null +++ b/drivers/usb/storage/unusual_usbat.h @@ -0,0 +1,43 @@ +/* Unusual Devices File for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_USBAT) || \ + defined(CONFIG_USB_STORAGE_USBAT_MODULE) + +UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001, + "HP", + "CD-Writer+ 8200e", + US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), + +UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001, + "HP", + "CD-Writer+ CD-4e", + US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), + +UNUSUAL_DEV( 0x04e6, 0x1010, 0x0000, 0x9999, + "Shuttle/SCM", + "USBAT-02", + US_SC_SCSI, US_PR_USBAT, init_usbat_flash, + US_FL_SINGLE_LUN), + +UNUSUAL_DEV( 0x0781, 0x0005, 0x0005, 0x0005, + "Sandisk", + "ImageMate SDDR-05b", + US_SC_SCSI, US_PR_USBAT, init_usbat_flash, + US_FL_SINGLE_LUN), + +#endif /* defined(CONFIG_USB_STORAGE_USBAT) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 241e1944cf1..3ad22a8142c 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -66,9 +66,6 @@ #include "debug.h" #include "initializers.h" -#ifdef CONFIG_USB_STORAGE_USBAT -#include "shuttle_usbat.h" -#endif #ifdef CONFIG_USB_STORAGE_FREECOM #include "freecom.h" #endif @@ -610,15 +607,6 @@ static void get_transport(struct us_data *us) us->transport_reset = usb_stor_Bulk_reset; break; -#ifdef CONFIG_USB_STORAGE_USBAT - case US_PR_USBAT: - us->transport_name = "Shuttle USBAT"; - us->transport = usbat_transport; - us->transport_reset = usb_stor_CB_reset; - us->max_lun = 1; - break; -#endif - #ifdef CONFIG_USB_STORAGE_FREECOM case US_PR_FREECOM: us->transport_name = "Freecom"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index be461ee9f00..899a8c8da71 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -81,6 +81,7 @@ static struct ignore_entry ignore_ids[] = { # include "unusual_isd200.h" # include "unusual_sddr09.h" # include "unusual_sddr55.h" +# include "unusual_usbat.h" { } /* Terminating entry */ }; -- GitLab From 0d62939fab3cf28a23ac6934cec599793d3a1d9d Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:11 -0500 Subject: [PATCH 4342/4982] usb-storage: make freecom a separate module This patch (as1212) converts usb-storage's freecom subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/freecom.c | 95 ++++++++++++++++++- drivers/usb/storage/unusual_devs.h | 7 -- .../storage/{freecom.h => unusual_freecom.h} | 24 ++--- drivers/usb/storage/usb.c | 12 --- drivers/usb/storage/usual-tables.c | 1 + 7 files changed, 104 insertions(+), 42 deletions(-) rename drivers/usb/storage/{freecom.h => unusual_freecom.h} (60%) diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 44c6b1940f7..14508b8a55f 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -39,12 +39,14 @@ config USB_STORAGE_DATAFAB Datafab has a web page at . config USB_STORAGE_FREECOM - bool "Freecom USB/ATAPI Bridge support" + tristate "Freecom USB/ATAPI Bridge support" depends on USB_STORAGE help Support for the Freecom USB to IDE/ATAPI adaptor. Freecom has a web page at . + If this driver is compiled as a module, it will be named ums-freecom. + config USB_STORAGE_ISD200 tristate "ISD-200 USB/ATA Bridge support" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 2387368cb7a..93e91ec3a2d 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -10,7 +10,6 @@ EXTRA_CFLAGS := -Idrivers/scsi obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o -usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM) += freecom.o usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o @@ -27,12 +26,14 @@ else endif obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o +obj-$(CONFIG_USB_STORAGE_FREECOM) += ums-freecom.o obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o ums-cypress-objs := cypress_atacb.o +ums-freecom-objs := freecom.o ums-isd200-objs := isd200.o ums-sddr09-objs := sddr09.o ums-sddr55-objs := sddr55.o diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c index 73ac7262239..393047b3890 100644 --- a/drivers/usb/storage/freecom.c +++ b/drivers/usb/storage/freecom.c @@ -26,6 +26,7 @@ * (http://www.freecom.de/) */ +#include #include #include @@ -33,7 +34,6 @@ #include "transport.h" #include "protocol.h" #include "debug.h" -#include "freecom.h" #ifdef CONFIG_USB_STORAGE_DEBUG static void pdump (void *, int); @@ -103,6 +103,47 @@ struct freecom_status { #define FCM_PACKET_LENGTH 64 #define FCM_STATUS_PACKET_LENGTH 4 +static int init_freecom(struct us_data *us); + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id freecom_usb_ids[] = { +# include "unusual_freecom.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, freecom_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev freecom_unusual_dev_list[] = { +# include "unusual_freecom.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + static int freecom_readdata (struct scsi_cmnd *srb, struct us_data *us, unsigned int ipipe, unsigned int opipe, int count) @@ -173,7 +214,7 @@ freecom_writedata (struct scsi_cmnd *srb, struct us_data *us, * Transport for the Freecom USB/IDE adaptor. * */ -int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) +static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) { struct freecom_cb_wrap *fcb; struct freecom_status *fst; @@ -377,8 +418,7 @@ int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) return USB_STOR_TRANSPORT_GOOD; } -int -freecom_init (struct us_data *us) +static int init_freecom(struct us_data *us) { int result; char *buffer = us->iobuf; @@ -417,7 +457,7 @@ freecom_init (struct us_data *us) return USB_STOR_TRANSPORT_GOOD; } -int usb_stor_freecom_reset(struct us_data *us) +static int usb_stor_freecom_reset(struct us_data *us) { printk (KERN_CRIT "freecom reset called\n"); @@ -479,3 +519,48 @@ static void pdump (void *ibuffer, int length) } #endif +static int freecom_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - freecom_usb_ids) + freecom_unusual_dev_list); + if (result) + return result; + + us->transport_name = "Freecom"; + us->transport = freecom_transport; + us->transport_reset = usb_stor_freecom_reset; + us->max_lun = 0; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver freecom_driver = { + .name = "ums-freecom", + .probe = freecom_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = freecom_usb_ids, + .soft_unbind = 1, +}; + +static int __init freecom_init(void) +{ + return usb_register(&freecom_driver); +} + +static void __exit freecom_exit(void) +{ + usb_deregister(&freecom_driver); +} + +module_init(freecom_init); +module_exit(freecom_exit); diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 6462c4c54dc..eef2075cf2e 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -958,13 +958,6 @@ UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100, US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN ), -#ifdef CONFIG_USB_STORAGE_FREECOM -UNUSUAL_DEV( 0x07ab, 0xfc01, 0x0000, 0x9999, - "Freecom", - "USB-IDE", - US_SC_QIC, US_PR_FREECOM, freecom_init, 0), -#endif - /* Reported by Eero Volotinen */ UNUSUAL_DEV( 0x07ab, 0xfccd, 0x0000, 0x9999, "Freecom Technologies", diff --git a/drivers/usb/storage/freecom.h b/drivers/usb/storage/unusual_freecom.h similarity index 60% rename from drivers/usb/storage/freecom.h rename to drivers/usb/storage/unusual_freecom.h index 20d0fe6ba0c..37586794239 100644 --- a/drivers/usb/storage/freecom.h +++ b/drivers/usb/storage/unusual_freecom.h @@ -1,13 +1,4 @@ -/* Driver for Freecom USB/IDE adaptor - * - * Freecom v0.1: - * - * First release - * - * Current development and maintenance by: - * (c) 2000 David Brown - * - * See freecom.c for more explanation +/* Unusual Devices File for the Freecom USB/IDE adaptor * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -24,11 +15,12 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _FREECOM_USB_H -#define _FREECOM_USB_H +#if defined(CONFIG_USB_STORAGE_FREECOM) || \ + defined(CONFIG_USB_STORAGE_FREECOM_MODULE) -extern int freecom_transport(struct scsi_cmnd *srb, struct us_data *us); -extern int usb_stor_freecom_reset(struct us_data *us); -extern int freecom_init (struct us_data *us); +UNUSUAL_DEV( 0x07ab, 0xfc01, 0x0000, 0x9999, + "Freecom", + "USB-IDE", + US_SC_QIC, US_PR_FREECOM, init_freecom, 0), -#endif +#endif /* defined(CONFIG_USB_STORAGE_FREECOM) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 3ad22a8142c..985275d5d4c 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -66,9 +66,6 @@ #include "debug.h" #include "initializers.h" -#ifdef CONFIG_USB_STORAGE_FREECOM -#include "freecom.h" -#endif #ifdef CONFIG_USB_STORAGE_DATAFAB #include "datafab.h" #endif @@ -607,15 +604,6 @@ static void get_transport(struct us_data *us) us->transport_reset = usb_stor_Bulk_reset; break; -#ifdef CONFIG_USB_STORAGE_FREECOM - case US_PR_FREECOM: - us->transport_name = "Freecom"; - us->transport = freecom_transport; - us->transport_reset = usb_stor_freecom_reset; - us->max_lun = 0; - break; -#endif - #ifdef CONFIG_USB_STORAGE_DATAFAB case US_PR_DATAFAB: us->transport_name = "Datafab Bulk-Only"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index 899a8c8da71..a50f0eefb73 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -78,6 +78,7 @@ struct ignore_entry { static struct ignore_entry ignore_ids[] = { # include "unusual_cypress.h" +# include "unusual_freecom.h" # include "unusual_isd200.h" # include "unusual_sddr09.h" # include "unusual_sddr55.h" -- GitLab From 2cbbf3576aa9eae9a92f2669f38a453b6cb8e956 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:15 -0500 Subject: [PATCH 4343/4982] usb-storage: make datafab a separate module This patch (as1213) converts usb-storage's datafab subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/datafab.c | 100 +++++++++++++++++++++++++- drivers/usb/storage/datafab.h | 40 ----------- drivers/usb/storage/unusual_datafab.h | 98 +++++++++++++++++++++++++ drivers/usb/storage/unusual_devs.h | 86 ---------------------- drivers/usb/storage/usb.c | 12 ---- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 202 insertions(+), 142 deletions(-) delete mode 100644 drivers/usb/storage/datafab.h create mode 100644 drivers/usb/storage/unusual_datafab.h diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 14508b8a55f..7dac413e0f2 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -32,12 +32,14 @@ config USB_STORAGE_DEBUG verbose debugging messages. config USB_STORAGE_DATAFAB - bool "Datafab Compact Flash Reader support" + tristate "Datafab Compact Flash Reader support" depends on USB_STORAGE help Support for certain Datafab CompactFlash readers. Datafab has a web page at . + If this driver is compiled as a module, it will be named ums-datafab. + config USB_STORAGE_FREECOM tristate "Freecom USB/ATAPI Bridge support" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 93e91ec3a2d..0f78bd680f0 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -10,7 +10,6 @@ EXTRA_CFLAGS := -Idrivers/scsi obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o -usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o @@ -26,6 +25,7 @@ else endif obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o +obj-$(CONFIG_USB_STORAGE_DATAFAB) += ums-datafab.o obj-$(CONFIG_USB_STORAGE_FREECOM) += ums-freecom.o obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o @@ -33,6 +33,7 @@ obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o ums-cypress-objs := cypress_atacb.o +ums-datafab-objs := datafab.o ums-freecom-objs := freecom.o ums-isd200-objs := isd200.o ums-sddr09-objs := sddr09.o diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c index 17f1ae23291..2d8d8351909 100644 --- a/drivers/usb/storage/datafab.c +++ b/drivers/usb/storage/datafab.c @@ -49,6 +49,7 @@ */ #include +#include #include #include @@ -58,12 +59,61 @@ #include "transport.h" #include "protocol.h" #include "debug.h" -#include "datafab.h" + +struct datafab_info { + unsigned long sectors; /* total sector count */ + unsigned long ssize; /* sector size in bytes */ + signed char lun; /* used for dual-slot readers */ + + /* the following aren't used yet */ + unsigned char sense_key; + unsigned long sense_asc; /* additional sense code */ + unsigned long sense_ascq; /* additional sense code qualifier */ +}; static int datafab_determine_lun(struct us_data *us, struct datafab_info *info); +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id datafab_usb_ids[] = { +# include "unusual_datafab.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, datafab_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev datafab_unusual_dev_list[] = { +# include "unusual_datafab.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + + static inline int datafab_bulk_read(struct us_data *us, unsigned char *data, unsigned int len) { if (len == 0) @@ -500,7 +550,7 @@ static void datafab_info_destructor(void *extra) // Transport for the Datafab MDCFE-B // -int datafab_transport(struct scsi_cmnd * srb, struct us_data *us) +static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us) { struct datafab_info *info; int rc; @@ -665,3 +715,49 @@ int datafab_transport(struct scsi_cmnd * srb, struct us_data *us) info->sense_ascq = 0x00; return USB_STOR_TRANSPORT_FAILED; } + +static int datafab_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - datafab_usb_ids) + datafab_unusual_dev_list); + if (result) + return result; + + us->transport_name = "Datafab Bulk-Only"; + us->transport = datafab_transport; + us->transport_reset = usb_stor_Bulk_reset; + us->max_lun = 1; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver datafab_driver = { + .name = "ums-datafab", + .probe = datafab_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = datafab_usb_ids, + .soft_unbind = 1, +}; + +static int __init datafab_init(void) +{ + return usb_register(&datafab_driver); +} + +static void __exit datafab_exit(void) +{ + usb_deregister(&datafab_driver); +} + +module_init(datafab_init); +module_exit(datafab_exit); diff --git a/drivers/usb/storage/datafab.h b/drivers/usb/storage/datafab.h deleted file mode 100644 index 32e3f271e58..00000000000 --- a/drivers/usb/storage/datafab.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Driver for Datafab MDCFE-B USB Compact Flash reader - * Header File - * - * Current development and maintenance by: - * (c) 2000 Jimmie Mayfield (mayfield+datafab@sackheads.org) - * - * See datafab.c for more explanation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _USB_DATAFAB_MDCFE_B_H -#define _USB_DATAFAB_MDCFE_B_H - -extern int datafab_transport(struct scsi_cmnd *srb, struct us_data *us); - -struct datafab_info { - unsigned long sectors; // total sector count - unsigned long ssize; // sector size in bytes - signed char lun; // used for dual-slot readers - - // the following aren't used yet - unsigned char sense_key; - unsigned long sense_asc; // additional sense code - unsigned long sense_ascq; // additional sense code qualifier -}; - -#endif diff --git a/drivers/usb/storage/unusual_datafab.h b/drivers/usb/storage/unusual_datafab.h new file mode 100644 index 00000000000..c9298ce9f22 --- /dev/null +++ b/drivers/usb/storage/unusual_datafab.h @@ -0,0 +1,98 @@ +/* Unusual Devices File for the Datafab USB Compact Flash reader + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_DATAFAB) || \ + defined(CONFIG_USB_STORAGE_DATAFAB_MODULE) + +UNUSUAL_DEV( 0x07c4, 0xa000, 0x0000, 0x0015, + "Datafab", + "MDCFE-B USB CF Reader", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +/* + * The following Datafab-based devices may or may not work + * using the current driver...the 0xffff is arbitrary since I + * don't know what device versions exist for these guys. + * + * The 0xa003 and 0xa004 devices in particular I'm curious about. + * I'm told they exist but so far nobody has come forward to say that + * they work with this driver. Given the success we've had getting + * other Datafab-based cards operational with this driver, I've decided + * to leave these two devices in the list. + */ +UNUSUAL_DEV( 0x07c4, 0xa001, 0x0000, 0xffff, + "SIIG/Datafab", + "SIIG/Datafab Memory Stick+CF Reader/Writer", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +/* Reported by Josef Reisinger */ +UNUSUAL_DEV( 0x07c4, 0xa002, 0x0000, 0xffff, + "Datafab/Unknown", + "MD2/MD3 Disk enclosure", + US_SC_SCSI, US_PR_DATAFAB, NULL, + US_FL_SINGLE_LUN), + +UNUSUAL_DEV( 0x07c4, 0xa003, 0x0000, 0xffff, + "Datafab/Unknown", + "Datafab-based Reader", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +UNUSUAL_DEV( 0x07c4, 0xa004, 0x0000, 0xffff, + "Datafab/Unknown", + "Datafab-based Reader", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +UNUSUAL_DEV( 0x07c4, 0xa005, 0x0000, 0xffff, + "PNY/Datafab", + "PNY/Datafab CF+SM Reader", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff, + "Simple Tech/Datafab", + "Simple Tech/Datafab CF+SM Reader", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +/* Submitted by Olaf Hering */ +UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff, + "Datafab Systems, Inc.", + "USB to CF + SM Combo (LC1)", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +/* Reported by Felix Moeller + * in Germany this is sold by Hama with the productnumber 46952 + * as "DualSlot CompactFlash(TM) & MStick Drive USB" + */ +UNUSUAL_DEV( 0x07c4, 0xa10b, 0x0000, 0xffff, + "DataFab Systems Inc.", + "USB CF+MS", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, + "Acomdata", + "CF", + US_SC_SCSI, US_PR_DATAFAB, NULL, + US_FL_SINGLE_LUN), + +#endif /* defined(CONFIG_USB_STORAGE_DATAFAB) || ... */ diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index eef2075cf2e..a5867c6d761 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -992,84 +992,6 @@ UNUSUAL_DEV( 0x07b4, 0x010a, 0x0102, 0x0102, US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ), #endif -#ifdef CONFIG_USB_STORAGE_DATAFAB -UNUSUAL_DEV( 0x07c4, 0xa000, 0x0000, 0x0015, - "Datafab", - "MDCFE-B USB CF Reader", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), - -/* - * The following Datafab-based devices may or may not work - * using the current driver...the 0xffff is arbitrary since I - * don't know what device versions exist for these guys. - * - * The 0xa003 and 0xa004 devices in particular I'm curious about. - * I'm told they exist but so far nobody has come forward to say that - * they work with this driver. Given the success we've had getting - * other Datafab-based cards operational with this driver, I've decided - * to leave these two devices in the list. - */ -UNUSUAL_DEV( 0x07c4, 0xa001, 0x0000, 0xffff, - "SIIG/Datafab", - "SIIG/Datafab Memory Stick+CF Reader/Writer", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), - -/* Reported by Josef Reisinger */ -UNUSUAL_DEV( 0x07c4, 0xa002, 0x0000, 0xffff, - "Datafab/Unknown", - "MD2/MD3 Disk enclosure", - US_SC_SCSI, US_PR_DATAFAB, NULL, - US_FL_SINGLE_LUN ), - -UNUSUAL_DEV( 0x07c4, 0xa003, 0x0000, 0xffff, - "Datafab/Unknown", - "Datafab-based Reader", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), - -UNUSUAL_DEV( 0x07c4, 0xa004, 0x0000, 0xffff, - "Datafab/Unknown", - "Datafab-based Reader", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), - -UNUSUAL_DEV( 0x07c4, 0xa005, 0x0000, 0xffff, - "PNY/Datafab", - "PNY/Datafab CF+SM Reader", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), - -UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff, - "Simple Tech/Datafab", - "Simple Tech/Datafab CF+SM Reader", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), -#endif - -#ifdef CONFIG_USB_STORAGE_DATAFAB -/* Submitted by Olaf Hering */ -UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff, - "Datafab Systems, Inc.", - "USB to CF + SM Combo (LC1)", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), -#endif - -#ifdef CONFIG_USB_STORAGE_DATAFAB -/* Reported by Felix Moeller - * in Germany this is sold by Hama with the productnumber 46952 - * as "DualSlot CompactFlash(TM) & MStick Drive USB" - */ -UNUSUAL_DEV( 0x07c4, 0xa10b, 0x0000, 0xffff, - "DataFab Systems Inc.", - "USB CF+MS", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), - -#endif - /* Datafab KECF-USB / Sagatek DCS-CF / Simpletech Flashlink UCF-100 * Only revision 1.13 tested (same for all of the above devices, * based on the Datafab DF-UG-07 chip). Needed for US_FL_FIX_INQUIRY. @@ -1273,14 +1195,6 @@ UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SANE_SENSE ), -#ifdef CONFIG_USB_STORAGE_DATAFAB -UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, - "Acomdata", - "CF", - US_SC_SCSI, US_PR_DATAFAB, NULL, - US_FL_SINGLE_LUN ), -#endif - UNUSUAL_DEV( 0x0d49, 0x7310, 0x0000, 0x9999, "Maxtor", "USB to SATA", diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 985275d5d4c..a537b3513b9 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -66,9 +66,6 @@ #include "debug.h" #include "initializers.h" -#ifdef CONFIG_USB_STORAGE_DATAFAB -#include "datafab.h" -#endif #ifdef CONFIG_USB_STORAGE_JUMPSHOT #include "jumpshot.h" #endif @@ -604,15 +601,6 @@ static void get_transport(struct us_data *us) us->transport_reset = usb_stor_Bulk_reset; break; -#ifdef CONFIG_USB_STORAGE_DATAFAB - case US_PR_DATAFAB: - us->transport_name = "Datafab Bulk-Only"; - us->transport = datafab_transport; - us->transport_reset = usb_stor_Bulk_reset; - us->max_lun = 1; - break; -#endif - #ifdef CONFIG_USB_STORAGE_JUMPSHOT case US_PR_JUMPSHOT: us->transport_name = "Lexar Jumpshot Control/Bulk"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index a50f0eefb73..c6ceac62cf6 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -78,6 +78,7 @@ struct ignore_entry { static struct ignore_entry ignore_ids[] = { # include "unusual_cypress.h" +# include "unusual_datafab.h" # include "unusual_freecom.h" # include "unusual_isd200.h" # include "unusual_sddr09.h" -- GitLab From a9fb6d05d59c9e118ad8c355adfdf88c970c61bc Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:19 -0500 Subject: [PATCH 4344/4982] usb-storage: make jumpshot a separate module This patch (as1214) converts usb-storage's jumpshot subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/jumpshot.c | 99 ++++++++++++++++++- drivers/usb/storage/unusual_devs.h | 8 -- .../{jumpshot.h => unusual_jumpshot.h} | 30 ++---- drivers/usb/storage/usb.c | 12 --- drivers/usb/storage/usual-tables.c | 1 + 7 files changed, 112 insertions(+), 45 deletions(-) rename drivers/usb/storage/{jumpshot.h => unusual_jumpshot.h} (50%) diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 7dac413e0f2..43e1afeb7f8 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -110,12 +110,14 @@ config USB_STORAGE_SDDR55 If this driver is compiled as a module, it will be named ums-sddr55. config USB_STORAGE_JUMPSHOT - bool "Lexar Jumpshot Compact Flash Reader" + tristate "Lexar Jumpshot Compact Flash Reader" depends on USB_STORAGE help Say Y here to include additional code to support the Lexar Jumpshot USB CompactFlash reader. + If this driver is compiled as a module, it will be named ums-jumpshot. + config USB_STORAGE_ALAUDA bool "Olympus MAUSB-10/Fuji DPC-R1 support" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 0f78bd680f0..7b9d53563d3 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -10,7 +10,6 @@ EXTRA_CFLAGS := -Idrivers/scsi obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o -usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA) += karma.o @@ -28,6 +27,7 @@ obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o obj-$(CONFIG_USB_STORAGE_DATAFAB) += ums-datafab.o obj-$(CONFIG_USB_STORAGE_FREECOM) += ums-freecom.o obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o +obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += ums-jumpshot.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o @@ -36,6 +36,7 @@ ums-cypress-objs := cypress_atacb.o ums-datafab-objs := datafab.o ums-freecom-objs := freecom.o ums-isd200-objs := isd200.o +ums-jumpshot-objs := jumpshot.o ums-sddr09-objs := sddr09.o ums-sddr55-objs := sddr55.o ums-usbat-objs := shuttle_usbat.o diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c index df67f13c9e7..a50d6dc1fe6 100644 --- a/drivers/usb/storage/jumpshot.c +++ b/drivers/usb/storage/jumpshot.c @@ -46,6 +46,7 @@ */ #include +#include #include #include @@ -55,9 +56,57 @@ #include "transport.h" #include "protocol.h" #include "debug.h" -#include "jumpshot.h" +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id jumpshot_usb_ids[] = { +# include "unusual_jumpshot.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, jumpshot_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev jumpshot_unusual_dev_list[] = { +# include "unusual_jumpshot.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + + +struct jumpshot_info { + unsigned long sectors; /* total sector count */ + unsigned long ssize; /* sector size in bytes */ + + /* the following aren't used yet */ + unsigned char sense_key; + unsigned long sense_asc; /* additional sense code */ + unsigned long sense_ascq; /* additional sense code qualifier */ +}; + static inline int jumpshot_bulk_read(struct us_data *us, unsigned char *data, unsigned int len) @@ -429,7 +478,7 @@ static void jumpshot_info_destructor(void *extra) // Transport for the Lexar 'Jumpshot' // -int jumpshot_transport(struct scsi_cmnd * srb, struct us_data *us) +static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us) { struct jumpshot_info *info; int rc; @@ -592,3 +641,49 @@ int jumpshot_transport(struct scsi_cmnd * srb, struct us_data *us) info->sense_ascq = 0x00; return USB_STOR_TRANSPORT_FAILED; } + +static int jumpshot_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - jumpshot_usb_ids) + jumpshot_unusual_dev_list); + if (result) + return result; + + us->transport_name = "Lexar Jumpshot Control/Bulk"; + us->transport = jumpshot_transport; + us->transport_reset = usb_stor_Bulk_reset; + us->max_lun = 1; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver jumpshot_driver = { + .name = "ums-jumpshot", + .probe = jumpshot_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = jumpshot_usb_ids, + .soft_unbind = 1, +}; + +static int __init jumpshot_init(void) +{ + return usb_register(&jumpshot_driver); +} + +static void __exit jumpshot_exit(void) +{ + usb_deregister(&jumpshot_driver); +} + +module_init(jumpshot_init); +module_exit(jumpshot_exit); diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index a5867c6d761..24e23c29d29 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -794,14 +794,6 @@ UNUSUAL_DEV( 0x05c6, 0x1000, 0x0000, 0x9999, US_SC_DEVICE, US_PR_DEVICE, option_ms_init, 0), -#ifdef CONFIG_USB_STORAGE_JUMPSHOT -UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001, - "Lexar", - "Jumpshot USB CF Reader", - US_SC_SCSI, US_PR_JUMPSHOT, NULL, - US_FL_NEED_OVERRIDE ), -#endif - /* Reported by Blake Matheny */ UNUSUAL_DEV( 0x05dc, 0xb002, 0x0000, 0x0113, "Lexar", diff --git a/drivers/usb/storage/jumpshot.h b/drivers/usb/storage/unusual_jumpshot.h similarity index 50% rename from drivers/usb/storage/jumpshot.h rename to drivers/usb/storage/unusual_jumpshot.h index 19bac9d1558..2e549b1c2c6 100644 --- a/drivers/usb/storage/jumpshot.h +++ b/drivers/usb/storage/unusual_jumpshot.h @@ -1,10 +1,4 @@ -/* Driver for Lexar "Jumpshot" USB Compact Flash reader - * Header File - * - * Current development and maintenance by: - * (c) 2000 Jimmie Mayfield (mayfield+usb@sackheads.org) - * - * See jumpshot.c for more explanation +/* Unusual Devices File for the Lexar "Jumpshot" Compact Flash reader * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -21,19 +15,13 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _USB_JUMPSHOT_H -#define _USB_JUMPSHOT_H - -extern int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us); +#if defined(CONFIG_USB_STORAGE_JUMPSHOT) || \ + defined(CONFIG_USB_STORAGE_JUMPSHOT_MODULE) -struct jumpshot_info { - unsigned long sectors; // total sector count - unsigned long ssize; // sector size in bytes - - // the following aren't used yet - unsigned char sense_key; - unsigned long sense_asc; // additional sense code - unsigned long sense_ascq; // additional sense code qualifier -}; +UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001, + "Lexar", + "Jumpshot USB CF Reader", + US_SC_SCSI, US_PR_JUMPSHOT, NULL, + US_FL_NEED_OVERRIDE), -#endif +#endif /* defined(CONFIG_USB_STORAGE_JUMPSHOT) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index a537b3513b9..2ea57691a7b 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -66,9 +66,6 @@ #include "debug.h" #include "initializers.h" -#ifdef CONFIG_USB_STORAGE_JUMPSHOT -#include "jumpshot.h" -#endif #ifdef CONFIG_USB_STORAGE_ONETOUCH #include "onetouch.h" #endif @@ -601,15 +598,6 @@ static void get_transport(struct us_data *us) us->transport_reset = usb_stor_Bulk_reset; break; -#ifdef CONFIG_USB_STORAGE_JUMPSHOT - case US_PR_JUMPSHOT: - us->transport_name = "Lexar Jumpshot Control/Bulk"; - us->transport = jumpshot_transport; - us->transport_reset = usb_stor_Bulk_reset; - us->max_lun = 1; - break; -#endif - #ifdef CONFIG_USB_STORAGE_ALAUDA case US_PR_ALAUDA: us->transport_name = "Alauda Control/Bulk"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index c6ceac62cf6..182a097e076 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -81,6 +81,7 @@ static struct ignore_entry ignore_ids[] = { # include "unusual_datafab.h" # include "unusual_freecom.h" # include "unusual_isd200.h" +# include "unusual_jumpshot.h" # include "unusual_sddr09.h" # include "unusual_sddr55.h" # include "unusual_usbat.h" -- GitLab From a74bba3bf92cb6425789ae5050bdcca1283bc6f4 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:22 -0500 Subject: [PATCH 4345/4982] usb-storage: make alauda a separate module This patch (as1215) converts usb-storage's alauda subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/alauda.c | 163 ++++++++++++++++++++++++++- drivers/usb/storage/alauda.h | 100 ---------------- drivers/usb/storage/unusual_alauda.h | 31 +++++ drivers/usb/storage/unusual_devs.h | 14 --- drivers/usb/storage/usb.c | 12 -- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 197 insertions(+), 131 deletions(-) delete mode 100644 drivers/usb/storage/alauda.h create mode 100644 drivers/usb/storage/unusual_alauda.h diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 43e1afeb7f8..c56c2c6d37b 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -119,7 +119,7 @@ config USB_STORAGE_JUMPSHOT If this driver is compiled as a module, it will be named ums-jumpshot. config USB_STORAGE_ALAUDA - bool "Olympus MAUSB-10/Fuji DPC-R1 support" + tristate "Olympus MAUSB-10/Fuji DPC-R1 support" depends on USB_STORAGE help Say Y here to include additional code to support the Olympus MAUSB-10 @@ -128,6 +128,8 @@ config USB_STORAGE_ALAUDA These devices are based on the Alauda chip and support both XD and SmartMedia cards. + If this driver is compiled as a module, it will be named ums-alauda. + config USB_STORAGE_ONETOUCH bool "Support OneTouch Button on Maxtor Hard Drives" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 7b9d53563d3..fea05c0b676 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -10,7 +10,6 @@ EXTRA_CFLAGS := -Idrivers/scsi obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o -usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA) += karma.o @@ -23,6 +22,7 @@ else obj-$(CONFIG_USB) += libusual.o usual-tables.o endif +obj-$(CONFIG_USB_STORAGE_ALAUDA) += ums-alauda.o obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o obj-$(CONFIG_USB_STORAGE_DATAFAB) += ums-datafab.o obj-$(CONFIG_USB_STORAGE_FREECOM) += ums-freecom.o @@ -32,6 +32,7 @@ obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o +ums-alauda-objs := alauda.o ums-cypress-objs := cypress_atacb.o ums-datafab-objs := datafab.o ums-freecom-objs := freecom.o diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c index 5407411e30e..d3a88ebe690 100644 --- a/drivers/usb/storage/alauda.c +++ b/drivers/usb/storage/alauda.c @@ -31,6 +31,8 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include + #include #include #include @@ -39,7 +41,75 @@ #include "transport.h" #include "protocol.h" #include "debug.h" -#include "alauda.h" + +/* + * Status bytes + */ +#define ALAUDA_STATUS_ERROR 0x01 +#define ALAUDA_STATUS_READY 0x40 + +/* + * Control opcodes (for request field) + */ +#define ALAUDA_GET_XD_MEDIA_STATUS 0x08 +#define ALAUDA_GET_SM_MEDIA_STATUS 0x98 +#define ALAUDA_ACK_XD_MEDIA_CHANGE 0x0a +#define ALAUDA_ACK_SM_MEDIA_CHANGE 0x9a +#define ALAUDA_GET_XD_MEDIA_SIG 0x86 +#define ALAUDA_GET_SM_MEDIA_SIG 0x96 + +/* + * Bulk command identity (byte 0) + */ +#define ALAUDA_BULK_CMD 0x40 + +/* + * Bulk opcodes (byte 1) + */ +#define ALAUDA_BULK_GET_REDU_DATA 0x85 +#define ALAUDA_BULK_READ_BLOCK 0x94 +#define ALAUDA_BULK_ERASE_BLOCK 0xa3 +#define ALAUDA_BULK_WRITE_BLOCK 0xb4 +#define ALAUDA_BULK_GET_STATUS2 0xb7 +#define ALAUDA_BULK_RESET_MEDIA 0xe0 + +/* + * Port to operate on (byte 8) + */ +#define ALAUDA_PORT_XD 0x00 +#define ALAUDA_PORT_SM 0x01 + +/* + * LBA and PBA are unsigned ints. Special values. + */ +#define UNDEF 0xffff +#define SPARE 0xfffe +#define UNUSABLE 0xfffd + +struct alauda_media_info { + unsigned long capacity; /* total media size in bytes */ + unsigned int pagesize; /* page size in bytes */ + unsigned int blocksize; /* number of pages per block */ + unsigned int uzonesize; /* number of usable blocks per zone */ + unsigned int zonesize; /* number of blocks per zone */ + unsigned int blockmask; /* mask to get page from address */ + + unsigned char pageshift; + unsigned char blockshift; + unsigned char zoneshift; + + u16 **lba_to_pba; /* logical to physical block map */ + u16 **pba_to_lba; /* physical to logical block map */ +}; + +struct alauda_info { + struct alauda_media_info port[2]; + int wr_ep; /* endpoint to write data out of */ + + unsigned char sense_key; + unsigned long sense_asc; /* additional sense code */ + unsigned long sense_ascq; /* additional sense code qualifier */ +}; #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) ) #define LSB_of(s) ((s)&0xFF) @@ -52,6 +122,48 @@ #define PBA_HI(pba) (pba >> 3) #define PBA_ZONE(pba) (pba >> 11) +static int init_alauda(struct us_data *us); + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id alauda_usb_ids[] = { +# include "unusual_alauda.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, alauda_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev alauda_unusual_dev_list[] = { +# include "unusual_alauda.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + + /* * Media handling */ @@ -998,7 +1110,7 @@ static void alauda_info_destructor(void *extra) /* * Initialize alauda_info struct and find the data-write endpoint */ -int init_alauda(struct us_data *us) +static int init_alauda(struct us_data *us) { struct alauda_info *info; struct usb_host_interface *altsetting = us->pusb_intf->cur_altsetting; @@ -1020,7 +1132,7 @@ int init_alauda(struct us_data *us) return USB_STOR_TRANSPORT_GOOD; } -int alauda_transport(struct scsi_cmnd *srb, struct us_data *us) +static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us) { int rc; struct alauda_info *info = (struct alauda_info *) us->extra; @@ -1128,3 +1240,48 @@ int alauda_transport(struct scsi_cmnd *srb, struct us_data *us) return USB_STOR_TRANSPORT_FAILED; } +static int alauda_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - alauda_usb_ids) + alauda_unusual_dev_list); + if (result) + return result; + + us->transport_name = "Alauda Control/Bulk"; + us->transport = alauda_transport; + us->transport_reset = usb_stor_Bulk_reset; + us->max_lun = 1; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver alauda_driver = { + .name = "ums-alauda", + .probe = alauda_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = alauda_usb_ids, + .soft_unbind = 1, +}; + +static int __init alauda_init(void) +{ + return usb_register(&alauda_driver); +} + +static void __exit alauda_exit(void) +{ + usb_deregister(&alauda_driver); +} + +module_init(alauda_init); +module_exit(alauda_exit); diff --git a/drivers/usb/storage/alauda.h b/drivers/usb/storage/alauda.h deleted file mode 100644 index a700f87d080..00000000000 --- a/drivers/usb/storage/alauda.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Driver for Alauda-based card readers - * - * Current development and maintenance by: - * (c) 2005 Daniel Drake - * - * See alauda.c for more explanation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _USB_ALAUDA_H -#define _USB_ALAUDA_H - -/* - * Status bytes - */ -#define ALAUDA_STATUS_ERROR 0x01 -#define ALAUDA_STATUS_READY 0x40 - -/* - * Control opcodes (for request field) - */ -#define ALAUDA_GET_XD_MEDIA_STATUS 0x08 -#define ALAUDA_GET_SM_MEDIA_STATUS 0x98 -#define ALAUDA_ACK_XD_MEDIA_CHANGE 0x0a -#define ALAUDA_ACK_SM_MEDIA_CHANGE 0x9a -#define ALAUDA_GET_XD_MEDIA_SIG 0x86 -#define ALAUDA_GET_SM_MEDIA_SIG 0x96 - -/* - * Bulk command identity (byte 0) - */ -#define ALAUDA_BULK_CMD 0x40 - -/* - * Bulk opcodes (byte 1) - */ -#define ALAUDA_BULK_GET_REDU_DATA 0x85 -#define ALAUDA_BULK_READ_BLOCK 0x94 -#define ALAUDA_BULK_ERASE_BLOCK 0xa3 -#define ALAUDA_BULK_WRITE_BLOCK 0xb4 -#define ALAUDA_BULK_GET_STATUS2 0xb7 -#define ALAUDA_BULK_RESET_MEDIA 0xe0 - -/* - * Port to operate on (byte 8) - */ -#define ALAUDA_PORT_XD 0x00 -#define ALAUDA_PORT_SM 0x01 - -/* - * LBA and PBA are unsigned ints. Special values. - */ -#define UNDEF 0xffff -#define SPARE 0xfffe -#define UNUSABLE 0xfffd - -int init_alauda(struct us_data *us); -int alauda_transport(struct scsi_cmnd *srb, struct us_data *us); - -struct alauda_media_info { - unsigned long capacity; /* total media size in bytes */ - unsigned int pagesize; /* page size in bytes */ - unsigned int blocksize; /* number of pages per block */ - unsigned int uzonesize; /* number of usable blocks per zone */ - unsigned int zonesize; /* number of blocks per zone */ - unsigned int blockmask; /* mask to get page from address */ - - unsigned char pageshift; - unsigned char blockshift; - unsigned char zoneshift; - - u16 **lba_to_pba; /* logical to physical block map */ - u16 **pba_to_lba; /* physical to logical block map */ -}; - -struct alauda_info { - struct alauda_media_info port[2]; - int wr_ep; /* endpoint to write data out of */ - - unsigned char sense_key; - unsigned long sense_asc; /* additional sense code */ - unsigned long sense_ascq; /* additional sense code qualifier */ -}; - -#endif - diff --git a/drivers/usb/storage/unusual_alauda.h b/drivers/usb/storage/unusual_alauda.h new file mode 100644 index 00000000000..8c412f885dd --- /dev/null +++ b/drivers/usb/storage/unusual_alauda.h @@ -0,0 +1,31 @@ +/* Unusual Devices File for the Alauda-based card readers + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_ALAUDA) || \ + defined(CONFIG_USB_STORAGE_ALAUDA_MODULE) + +UNUSUAL_DEV( 0x0584, 0x0008, 0x0102, 0x0102, + "Fujifilm", + "DPC-R1 (Alauda)", + US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0), + +UNUSUAL_DEV( 0x07b4, 0x010a, 0x0102, 0x0102, + "Olympus", + "MAUSB-10 (Alauda)", + US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0), + +#endif /* defined(CONFIG_USB_STORAGE_ALAUDA) || ... */ diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 24e23c29d29..bcdb74dfa3d 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -692,13 +692,6 @@ UNUSUAL_DEV( 0x057b, 0x0022, 0x0000, 0x9999, "Silicon Media R/W", US_SC_DEVICE, US_PR_DEVICE, NULL, 0), -#ifdef CONFIG_USB_STORAGE_ALAUDA -UNUSUAL_DEV( 0x0584, 0x0008, 0x0102, 0x0102, - "Fujifilm", - "DPC-R1 (Alauda)", - US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ), -#endif - /* Reported by RTE */ UNUSUAL_DEV( 0x058f, 0x6387, 0x0141, 0x0141, "JetFlash", @@ -977,13 +970,6 @@ UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, US_FL_SINGLE_LUN ), #endif -#ifdef CONFIG_USB_STORAGE_ALAUDA -UNUSUAL_DEV( 0x07b4, 0x010a, 0x0102, 0x0102, - "Olympus", - "MAUSB-10 (Alauda)", - US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ), -#endif - /* Datafab KECF-USB / Sagatek DCS-CF / Simpletech Flashlink UCF-100 * Only revision 1.13 tested (same for all of the above devices, * based on the Datafab DF-UG-07 chip). Needed for US_FL_FIX_INQUIRY. diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 2ea57691a7b..cd039c00846 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -69,9 +69,6 @@ #ifdef CONFIG_USB_STORAGE_ONETOUCH #include "onetouch.h" #endif -#ifdef CONFIG_USB_STORAGE_ALAUDA -#include "alauda.h" -#endif #ifdef CONFIG_USB_STORAGE_KARMA #include "karma.h" #endif @@ -598,15 +595,6 @@ static void get_transport(struct us_data *us) us->transport_reset = usb_stor_Bulk_reset; break; -#ifdef CONFIG_USB_STORAGE_ALAUDA - case US_PR_ALAUDA: - us->transport_name = "Alauda Control/Bulk"; - us->transport = alauda_transport; - us->transport_reset = usb_stor_Bulk_reset; - us->max_lun = 1; - break; -#endif - #ifdef CONFIG_USB_STORAGE_KARMA case US_PR_KARMA: us->transport_name = "Rio Karma/Bulk"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index 182a097e076..ad102e8e191 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -77,6 +77,7 @@ struct ignore_entry { } static struct ignore_entry ignore_ids[] = { +# include "unusual_alauda.h" # include "unusual_cypress.h" # include "unusual_datafab.h" # include "unusual_freecom.h" -- GitLab From c10337846c93bd914dd3003ffb001adc583b313e Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:26 -0500 Subject: [PATCH 4346/4982] usb-storage: make karma a separate module This patch (as1216) converts usb-storage's karma subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/karma.c | 96 +++++++++++++++++++++++++++-- drivers/usb/storage/karma.h | 7 --- drivers/usb/storage/unusual_devs.h | 7 --- drivers/usb/storage/unusual_karma.h | 26 ++++++++ drivers/usb/storage/usb.c | 12 ---- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 123 insertions(+), 33 deletions(-) delete mode 100644 drivers/usb/storage/karma.h create mode 100644 drivers/usb/storage/unusual_karma.h diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index c56c2c6d37b..8adece1dd29 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -144,7 +144,7 @@ config USB_STORAGE_ONETOUCH cuts) config USB_STORAGE_KARMA - bool "Support for Rio Karma music player" + tristate "Support for Rio Karma music player" depends on USB_STORAGE help Say Y here to include additional code to support the Rio Karma @@ -155,6 +155,8 @@ config USB_STORAGE_KARMA on the resulting scsi device node returns the Karma to normal operation. + If this driver is compiled as a module, it will be named ums-karma. + config USB_STORAGE_CYPRESS_ATACB tristate "SAT emulation on Cypress USB/ATA Bridge with ATACB" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index fea05c0b676..870680ea370 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o -usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA) += karma.o usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ initializers.o sierra_ms.o option_ms.o $(usb-storage-obj-y) @@ -28,6 +27,7 @@ obj-$(CONFIG_USB_STORAGE_DATAFAB) += ums-datafab.o obj-$(CONFIG_USB_STORAGE_FREECOM) += ums-freecom.o obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += ums-jumpshot.o +obj-$(CONFIG_USB_STORAGE_KARMA) += ums-karma.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o @@ -38,6 +38,7 @@ ums-datafab-objs := datafab.o ums-freecom-objs := freecom.o ums-isd200-objs := isd200.o ums-jumpshot-objs := jumpshot.o +ums-karma-objs := karma.o ums-sddr09-objs := sddr09.o ums-sddr55-objs := sddr55.o ums-usbat-objs := shuttle_usbat.o diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c index 0d79ae5683f..cfb8e60866b 100644 --- a/drivers/usb/storage/karma.c +++ b/drivers/usb/storage/karma.c @@ -18,6 +18,8 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include + #include #include #include @@ -25,7 +27,6 @@ #include "usb.h" #include "transport.h" #include "debug.h" -#include "karma.h" #define RIO_PREFIX "RIOP\x00" #define RIO_PREFIX_LEN 5 @@ -36,13 +37,53 @@ #define RIO_LEAVE_STORAGE 0x2 #define RIO_RESET 0xC -extern int usb_stor_Bulk_transport(struct scsi_cmnd *, struct us_data *); - struct karma_data { int in_storage; char *recv; }; +static int rio_karma_init(struct us_data *us); + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id karma_usb_ids[] = { +# include "unusual_karma.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, karma_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev karma_unusual_dev_list[] = { +# include "unusual_karma.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + + /* * Send commands to Rio Karma. * @@ -104,7 +145,7 @@ err: * Trap START_STOP and READ_10 to leave/re-enter storage mode. * Everything else is propagated to the normal bulk layer. */ -int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us) +static int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us) { int ret; struct karma_data *data = (struct karma_data *) us->extra; @@ -133,7 +174,7 @@ static void rio_karma_destructor(void *extra) kfree(data->recv); } -int rio_karma_init(struct us_data *us) +static int rio_karma_init(struct us_data *us) { int ret = 0; struct karma_data *data = kzalloc(sizeof(struct karma_data), GFP_NOIO); @@ -153,3 +194,48 @@ int rio_karma_init(struct us_data *us) out: return ret; } + +static int karma_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - karma_usb_ids) + karma_unusual_dev_list); + if (result) + return result; + + us->transport_name = "Rio Karma/Bulk"; + us->transport = rio_karma_transport; + us->transport_reset = usb_stor_Bulk_reset; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver karma_driver = { + .name = "ums-karma", + .probe = karma_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = karma_usb_ids, + .soft_unbind = 1, +}; + +static int __init karma_init(void) +{ + return usb_register(&karma_driver); +} + +static void __exit karma_exit(void) +{ + usb_deregister(&karma_driver); +} + +module_init(karma_init); +module_exit(karma_exit); diff --git a/drivers/usb/storage/karma.h b/drivers/usb/storage/karma.h deleted file mode 100644 index 8a60972af8c..00000000000 --- a/drivers/usb/storage/karma.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _KARMA_USB_H -#define _KARMA_USB_H - -extern int rio_karma_init(struct us_data *us); -extern int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us); - -#endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index bcdb74dfa3d..83e34a6ad59 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -276,13 +276,6 @@ UNUSUAL_DEV( 0x0457, 0x0151, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), -#ifdef CONFIG_USB_STORAGE_KARMA -UNUSUAL_DEV( 0x045a, 0x5210, 0x0101, 0x0101, - "Rio", - "Rio Karma", - US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0), -#endif - /* Reported by Tamas Kerecsen * Obviously the PROM has not been customized by the VAR; * the Vendor and Product string descriptors are: diff --git a/drivers/usb/storage/unusual_karma.h b/drivers/usb/storage/unusual_karma.h new file mode 100644 index 00000000000..12ae3a03e80 --- /dev/null +++ b/drivers/usb/storage/unusual_karma.h @@ -0,0 +1,26 @@ +/* Unusual Devices File for the Rio Karma + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_KARMA) || \ + defined(CONFIG_USB_STORAGE_KARMA_MODULE) + +UNUSUAL_DEV( 0x045a, 0x5210, 0x0101, 0x0101, + "Rio", + "Rio Karma", + US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0), + +#endif /* defined(CONFIG_USB_STORAGE_KARMA) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index cd039c00846..c5abf9bbce1 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -69,9 +69,6 @@ #ifdef CONFIG_USB_STORAGE_ONETOUCH #include "onetouch.h" #endif -#ifdef CONFIG_USB_STORAGE_KARMA -#include "karma.h" -#endif #include "sierra_ms.h" #include "option_ms.h" @@ -594,15 +591,6 @@ static void get_transport(struct us_data *us) us->transport = usb_stor_Bulk_transport; us->transport_reset = usb_stor_Bulk_reset; break; - -#ifdef CONFIG_USB_STORAGE_KARMA - case US_PR_KARMA: - us->transport_name = "Rio Karma/Bulk"; - us->transport = rio_karma_transport; - us->transport_reset = usb_stor_Bulk_reset; - break; -#endif - } } diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index ad102e8e191..bce086fcef5 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -83,6 +83,7 @@ static struct ignore_entry ignore_ids[] = { # include "unusual_freecom.h" # include "unusual_isd200.h" # include "unusual_jumpshot.h" +# include "unusual_karma.h" # include "unusual_sddr09.h" # include "unusual_sddr55.h" # include "unusual_usbat.h" -- GitLab From 9cfb95ef72c637bc9b90260e0f98a23f3f49b1bb Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:33 -0500 Subject: [PATCH 4347/4982] usb-storage: make onetouch a separate module This patch (as1217) converts usb-storage's onetouch subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/onetouch.c | 90 +++++++++++++++++++++++++- drivers/usb/storage/onetouch.h | 9 --- drivers/usb/storage/unusual_devs.h | 17 ----- drivers/usb/storage/unusual_onetouch.h | 36 +++++++++++ drivers/usb/storage/usb.c | 3 - drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 130 insertions(+), 33 deletions(-) delete mode 100644 drivers/usb/storage/onetouch.h create mode 100644 drivers/usb/storage/unusual_onetouch.h diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 8adece1dd29..8a372bac0e4 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -131,7 +131,7 @@ config USB_STORAGE_ALAUDA If this driver is compiled as a module, it will be named ums-alauda. config USB_STORAGE_ONETOUCH - bool "Support OneTouch Button on Maxtor Hard Drives" + tristate "Support OneTouch Button on Maxtor Hard Drives" depends on USB_STORAGE depends on INPUT=y || INPUT=USB_STORAGE help @@ -143,6 +143,8 @@ config USB_STORAGE_ONETOUCH this input in any keybinding software. (e.g. gnome's keyboard short- cuts) + If this driver is compiled as a module, it will be named ums-onetouch. + config USB_STORAGE_KARMA tristate "Support for Rio Karma music player" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 870680ea370..5be54c01966 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -10,7 +10,6 @@ EXTRA_CFLAGS := -Idrivers/scsi obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o -usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ initializers.o sierra_ms.o option_ms.o $(usb-storage-obj-y) @@ -28,6 +27,7 @@ obj-$(CONFIG_USB_STORAGE_FREECOM) += ums-freecom.o obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += ums-jumpshot.o obj-$(CONFIG_USB_STORAGE_KARMA) += ums-karma.o +obj-$(CONFIG_USB_STORAGE_ONETOUCH) += ums-onetouch.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o @@ -39,6 +39,7 @@ ums-freecom-objs := freecom.o ums-isd200-objs := isd200.o ums-jumpshot-objs := jumpshot.o ums-karma-objs := karma.o +ums-onetouch-objs := onetouch.o ums-sddr09-objs := sddr09.o ums-sddr55-objs := sddr55.o ums-usbat-objs := shuttle_usbat.o diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c index c7bf8954b4e..8bd095635a9 100644 --- a/drivers/usb/storage/onetouch.c +++ b/drivers/usb/storage/onetouch.c @@ -35,9 +35,12 @@ #include #include #include "usb.h" -#include "onetouch.h" #include "debug.h" +#define ONETOUCH_PKT_LEN 0x02 +#define ONETOUCH_BUTTON KEY_PROG1 + +static int onetouch_connect_input(struct us_data *ss); static void onetouch_release_input(void *onetouch_); struct usb_onetouch { @@ -52,6 +55,46 @@ struct usb_onetouch { unsigned int is_open:1; }; + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id onetouch_usb_ids[] = { +# include "unusual_onetouch.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, onetouch_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev onetouch_unusual_dev_list[] = { +# include "unusual_onetouch.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + + static void usb_onetouch_irq(struct urb *urb) { struct usb_onetouch *onetouch = urb->context; @@ -127,7 +170,7 @@ static void usb_onetouch_pm_hook(struct us_data *us, int action) } #endif /* CONFIG_PM */ -int onetouch_connect_input(struct us_data *ss) +static int onetouch_connect_input(struct us_data *ss) { struct usb_device *udev = ss->pusb_dev; struct usb_host_interface *interface; @@ -236,3 +279,46 @@ static void onetouch_release_input(void *onetouch_) onetouch->data, onetouch->data_dma); } } + +static int onetouch_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - onetouch_usb_ids) + onetouch_unusual_dev_list); + if (result) + return result; + + /* Use default transport and protocol */ + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver onetouch_driver = { + .name = "ums-onetouch", + .probe = onetouch_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = onetouch_usb_ids, + .soft_unbind = 1, +}; + +static int __init onetouch_init(void) +{ + return usb_register(&onetouch_driver); +} + +static void __exit onetouch_exit(void) +{ + usb_deregister(&onetouch_driver); +} + +module_init(onetouch_init); +module_exit(onetouch_exit); diff --git a/drivers/usb/storage/onetouch.h b/drivers/usb/storage/onetouch.h deleted file mode 100644 index 41c7aa8f044..00000000000 --- a/drivers/usb/storage/onetouch.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _ONETOUCH_H_ -#define _ONETOUCH_H_ - -#define ONETOUCH_PKT_LEN 0x02 -#define ONETOUCH_BUTTON KEY_PROG1 - -int onetouch_connect_input(struct us_data *ss); - -#endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 83e34a6ad59..1c1f643e8a7 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1182,23 +1182,6 @@ UNUSUAL_DEV( 0x0c45, 0x1060, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), -/* Submitted by: Nick Sillik - * Needed for OneTouch extension to usb-storage - * - */ -#ifdef CONFIG_USB_STORAGE_ONETOUCH - UNUSUAL_DEV( 0x0d49, 0x7000, 0x0000, 0x9999, - "Maxtor", - "OneTouch External Harddrive", - US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input, - 0), - UNUSUAL_DEV( 0x0d49, 0x7010, 0x0000, 0x9999, - "Maxtor", - "OneTouch External Harddrive", - US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input, - 0), -#endif - /* Submitted by Joris Struyve */ UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff, "Medion", diff --git a/drivers/usb/storage/unusual_onetouch.h b/drivers/usb/storage/unusual_onetouch.h new file mode 100644 index 00000000000..bd9306b637d --- /dev/null +++ b/drivers/usb/storage/unusual_onetouch.h @@ -0,0 +1,36 @@ +/* Unusual Devices File for the Maxtor OneTouch USB hard drive's button + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_ONETOUCH) || \ + defined(CONFIG_USB_STORAGE_ONETOUCH_MODULE) + +/* Submitted by: Nick Sillik + * Needed for OneTouch extension to usb-storage + */ +UNUSUAL_DEV( 0x0d49, 0x7000, 0x0000, 0x9999, + "Maxtor", + "OneTouch External Harddrive", + US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input, + 0), + +UNUSUAL_DEV( 0x0d49, 0x7010, 0x0000, 0x9999, + "Maxtor", + "OneTouch External Harddrive", + US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input, + 0), + +#endif /* defined(CONFIG_USB_STORAGE_ONETOUCH) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index c5abf9bbce1..8060b85fe1a 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -66,9 +66,6 @@ #include "debug.h" #include "initializers.h" -#ifdef CONFIG_USB_STORAGE_ONETOUCH -#include "onetouch.h" -#endif #include "sierra_ms.h" #include "option_ms.h" diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index bce086fcef5..468bde7d197 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -84,6 +84,7 @@ static struct ignore_entry ignore_ids[] = { # include "unusual_isd200.h" # include "unusual_jumpshot.h" # include "unusual_karma.h" +# include "unusual_onetouch.h" # include "unusual_sddr09.h" # include "unusual_sddr55.h" # include "unusual_usbat.h" -- GitLab From 4246b06a33ebdd6593dccaab3aa01eb0c9f8c1c8 Mon Sep 17 00:00:00 2001 From: Maciej Grela Date: Sat, 28 Feb 2009 12:39:20 -0800 Subject: [PATCH 4348/4982] USB: usb-storage: added missing MODULE_LICENSE("GPL") for usb-storage ums-* modules The lack of a MODULE_LICENSE macro in ums-* subdrivers prevented them from loading. Needs to be applied after Alan Stern's usb-storage subdriver separation patchset. Also added missing MODULE_DESCRIPTION and MODULE_AUTHOR entries. Signed-off-by: Maciej Grela Acked-by: Alan Stern Acked-by: Matthew Dharm Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/alauda.c | 4 ++++ drivers/usb/storage/cypress_atacb.c | 3 +++ drivers/usb/storage/datafab.c | 4 ++++ drivers/usb/storage/freecom.c | 4 ++++ drivers/usb/storage/isd200.c | 3 +++ drivers/usb/storage/jumpshot.c | 4 ++++ drivers/usb/storage/karma.c | 4 ++++ drivers/usb/storage/onetouch.c | 4 ++++ drivers/usb/storage/sddr09.c | 3 +++ drivers/usb/storage/sddr55.c | 3 +++ drivers/usb/storage/shuttle_usbat.c | 3 +++ 11 files changed, 39 insertions(+) diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c index d3a88ebe690..67edc65acb8 100644 --- a/drivers/usb/storage/alauda.c +++ b/drivers/usb/storage/alauda.c @@ -42,6 +42,10 @@ #include "protocol.h" #include "debug.h" +MODULE_DESCRIPTION("Driver for Alauda-based card readers"); +MODULE_AUTHOR("Daniel Drake "); +MODULE_LICENSE("GPL"); + /* * Status bytes */ diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c index 19306f7b1da..c8447182118 100644 --- a/drivers/usb/storage/cypress_atacb.c +++ b/drivers/usb/storage/cypress_atacb.c @@ -30,6 +30,9 @@ #include "scsiglue.h" #include "debug.h" +MODULE_DESCRIPTION("SAT support for Cypress USB/ATA bridges with ATACB"); +MODULE_AUTHOR("Matthieu Castet "); +MODULE_LICENSE("GPL"); /* * The table of devices diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c index 2d8d8351909..2b6e565262c 100644 --- a/drivers/usb/storage/datafab.c +++ b/drivers/usb/storage/datafab.c @@ -60,6 +60,10 @@ #include "protocol.h" #include "debug.h" +MODULE_DESCRIPTION("Driver for Datafab USB Compact Flash reader"); +MODULE_AUTHOR("Jimmie Mayfield "); +MODULE_LICENSE("GPL"); + struct datafab_info { unsigned long sectors; /* total sector count */ unsigned long ssize; /* sector size in bytes */ diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c index 393047b3890..54cc94277ac 100644 --- a/drivers/usb/storage/freecom.c +++ b/drivers/usb/storage/freecom.c @@ -35,6 +35,10 @@ #include "protocol.h" #include "debug.h" +MODULE_DESCRIPTION("Driver for Freecom USB/IDE adaptor"); +MODULE_AUTHOR("David Brown "); +MODULE_LICENSE("GPL"); + #ifdef CONFIG_USB_STORAGE_DEBUG static void pdump (void *, int); #endif diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index df943008538..882c57b399f 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -59,6 +59,9 @@ #include "debug.h" #include "scsiglue.h" +MODULE_DESCRIPTION("Driver for In-System Design, Inc. ISD200 ASIC"); +MODULE_AUTHOR("Björn Stenberg "); +MODULE_LICENSE("GPL"); static int isd200_Initialization(struct us_data *us); diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c index a50d6dc1fe6..1c69420e3ac 100644 --- a/drivers/usb/storage/jumpshot.c +++ b/drivers/usb/storage/jumpshot.c @@ -58,6 +58,10 @@ #include "debug.h" +MODULE_DESCRIPTION("Driver for Lexar \"Jumpshot\" Compact Flash reader"); +MODULE_AUTHOR("Jimmie Mayfield "); +MODULE_LICENSE("GPL"); + /* * The table of devices */ diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c index cfb8e60866b..7953d93a773 100644 --- a/drivers/usb/storage/karma.c +++ b/drivers/usb/storage/karma.c @@ -28,6 +28,10 @@ #include "transport.h" #include "debug.h" +MODULE_DESCRIPTION("Driver for Rio Karma"); +MODULE_AUTHOR("Bob Copeland , Keith Bennett "); +MODULE_LICENSE("GPL"); + #define RIO_PREFIX "RIOP\x00" #define RIO_PREFIX_LEN 5 #define RIO_SEND_LEN 40 diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c index 8bd095635a9..380233bd6a3 100644 --- a/drivers/usb/storage/onetouch.c +++ b/drivers/usb/storage/onetouch.c @@ -37,6 +37,10 @@ #include "usb.h" #include "debug.h" +MODULE_DESCRIPTION("Maxtor USB OneTouch hard drive button driver"); +MODULE_AUTHOR("Nick Sillik "); +MODULE_LICENSE("GPL"); + #define ONETOUCH_PKT_LEN 0x02 #define ONETOUCH_BUTTON KEY_PROG1 diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index 170ad86b2d3..ab5f9f37575 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c @@ -53,6 +53,9 @@ #include "protocol.h" #include "debug.h" +MODULE_DESCRIPTION("Driver for SanDisk SDDR-09 SmartMedia reader"); +MODULE_AUTHOR("Andries Brouwer , Robert Baruch "); +MODULE_LICENSE("GPL"); static int usb_stor_sddr09_dpcm_init(struct us_data *us); static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us); diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c index e97716f8eb0..44dfed7754e 100644 --- a/drivers/usb/storage/sddr55.c +++ b/drivers/usb/storage/sddr55.c @@ -35,6 +35,9 @@ #include "protocol.h" #include "debug.h" +MODULE_DESCRIPTION("Driver for SanDisk SDDR-55 SmartMedia reader"); +MODULE_AUTHOR("Simon Munton"); +MODULE_LICENSE("GPL"); /* * The table of devices diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index d4fe0bb327a..b62a28814eb 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -54,6 +54,9 @@ #include "protocol.h" #include "debug.h" +MODULE_DESCRIPTION("Driver for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable"); +MODULE_AUTHOR("Daniel Drake , Robert Baruch "); +MODULE_LICENSE("GPL"); /* Supported device types */ #define USBAT_DEV_HP8200 0x01 -- GitLab From 6da9c99059bf24fb1faae6b9613bae64ea50c05e Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Wed, 18 Feb 2009 14:43:47 +0000 Subject: [PATCH 4349/4982] USB: allow libusb to talk to unauthenticated WUSB devices To permit a userspace application to associate with WUSB devices using numeric association, control transfers to unauthenticated WUSB devices must be allowed. This requires that wusbcore correctly sets the device state to UNAUTHENTICATED, DEFAULT and ADDRESS and that control transfers can be performed to UNAUTHENTICATED devices. Signed-off-by: David Vrabel Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 3 ++- drivers/usb/core/hub.c | 1 + drivers/usb/core/urb.c | 2 +- drivers/usb/wusbcore/devconnect.c | 2 ++ drivers/usb/wusbcore/security.c | 2 ++ include/linux/usb/ch9.h | 2 +- 6 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 6585f527e38..8f022af2fd7 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -525,7 +525,8 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, { int ret = 0; - if (ps->dev->state != USB_STATE_ADDRESS + if (ps->dev->state != USB_STATE_UNAUTHENTICATED + && ps->dev->state != USB_STATE_ADDRESS && ps->dev->state != USB_STATE_CONFIGURED) return -EHOSTUNREACH; if (USB_TYPE_VENDOR == (USB_TYPE_MASK & requesttype)) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 7e33d63ab92..f17d9ebc44a 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1305,6 +1305,7 @@ void usb_set_device_state(struct usb_device *udev, recursively_mark_NOTATTACHED(udev); spin_unlock_irqrestore(&device_state_lock, flags); } +EXPORT_SYMBOL_GPL(usb_set_device_state); /* * WUSB devices are simple: they have no hubs behind, so the mapping diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 58bc5e3c256..7025d801f23 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -295,7 +295,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) if (!urb || urb->hcpriv || !urb->complete) return -EINVAL; dev = urb->dev; - if ((!dev) || (dev->state < USB_STATE_DEFAULT)) + if ((!dev) || (dev->state < USB_STATE_UNAUTHENTICATED)) return -ENODEV; /* For now, get the endpoint from the pipe. Eventually drivers diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c index 8e18141bb2e..f0aac0cf315 100644 --- a/drivers/usb/wusbcore/devconnect.c +++ b/drivers/usb/wusbcore/devconnect.c @@ -889,6 +889,8 @@ static void wusb_dev_add_ncb(struct usb_device *usb_dev) if (usb_dev->wusb == 0 || usb_dev->devnum == 1) return; /* skip non wusb and wusb RHs */ + usb_set_device_state(usb_dev, USB_STATE_UNAUTHENTICATED); + wusbhc = wusbhc_get_by_usb_dev(usb_dev); if (wusbhc == NULL) goto error_nodev; diff --git a/drivers/usb/wusbcore/security.c b/drivers/usb/wusbcore/security.c index f4aa28eca70..8118db7f1d8 100644 --- a/drivers/usb/wusbcore/security.c +++ b/drivers/usb/wusbcore/security.c @@ -312,6 +312,7 @@ int wusb_dev_update_address(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) result = wusb_set_dev_addr(wusbhc, wusb_dev, 0); if (result < 0) goto error_addr0; + usb_set_device_state(usb_dev, USB_STATE_DEFAULT); usb_ep0_reinit(usb_dev); /* Set new (authenticated) address. */ @@ -327,6 +328,7 @@ int wusb_dev_update_address(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) result = wusb_set_dev_addr(wusbhc, wusb_dev, new_address); if (result < 0) goto error_addr; + usb_set_device_state(usb_dev, USB_STATE_ADDRESS); usb_ep0_reinit(usb_dev); usb_dev->authenticated = 1; error_addr: diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h index fa777db7f7e..d9d54803dbc 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -763,8 +763,8 @@ enum usb_device_state { /* chapter 9 and authentication (wireless) device states */ USB_STATE_ATTACHED, USB_STATE_POWERED, /* wired */ - USB_STATE_UNAUTHENTICATED, /* auth */ USB_STATE_RECONNECTING, /* auth */ + USB_STATE_UNAUTHENTICATED, /* auth */ USB_STATE_DEFAULT, /* limited function */ USB_STATE_ADDRESS, USB_STATE_CONFIGURED, /* most functions */ -- GitLab From b2bdf3a789162aa6ff9c6f139bee9cc7954bc5b4 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 12 Feb 2009 15:09:47 +0200 Subject: [PATCH 4350/4982] USB: composite: avoid inconsistent lock state Avoid the following INFO from lock debugging: [ 369.126112] ================================= [ 369.132063] [ INFO: inconsistent lock state ] [ 369.136457] 2.6.28-maemo1 #1 [ 369.139387] --------------------------------- [ 369.143782] inconsistent {hardirq-on-W} -> {in-hardirq-W} usage. [ 369.149855] swapper/0 [HC1[1]:SC0[0]:HE0:SE1] takes: [ 369.154890] (&cdev->lock){+-..}, at: [] composite_disconnect+0x1c/0] [ 369.163404] {hardirq-on-W} state was registered at: [ 369.168348] [] __lock_acquire+0x5d0/0x7d8 [ 369.173506] [] lock_acquire+0x64/0x78 [ 369.178266] [] _spin_lock+0x4c/0x80 [ 369.182905] [] usb_function_deactivate+0x20/0x70 [g_nokia] [ 369.189527] [] 0xbf1a0a88 [ 369.193281] [] 0xbf19f450 [ 369.197004] [] 0xbf19fa3c [ 369.200758] [] 0xbf1a03a0 [ 369.204481] [] 0xbf19f254 [ 369.208204] [] 0xbf1a0158 [ 369.211927] [] 0xbf1a130c [ 369.215650] [] usb_gadget_register_driver+0x12c/0x28c [ 369.221846] [] 0xbf1a06bc [ 369.225569] [] 0xbf1a06e8 [ 369.229322] [] __exception_text_end+0x64/0x19c [ 369.234877] [] sys_init_module+0x9c/0x194 [ 369.240004] [] ret_fast_syscall+0x0/0x2c [ 369.245039] [] 0xffffffff [ 369.248793] irq event stamp: 218356 [ 369.252302] hardirqs last enabled at (218355): [] omap3_enter_idle+8 [ 369.260420] hardirqs last disabled at (218356): [] __irq_svc+0x34/0x0 [ 369.267927] softirqs last enabled at (218348): [] __do_softirq+0x134 [ 369.275892] softirqs last disabled at (218335): [] irq_exit+0x60/0xb0 [ 369.283308] [ 369.283308] other info that might help us debug this: [ 369.289930] no locks held by swapper/0. Cc: David Brownell Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/composite.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 5d11c291f1a..40f1da77a00 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -149,16 +149,17 @@ done: int usb_function_deactivate(struct usb_function *function) { struct usb_composite_dev *cdev = function->config->cdev; + unsigned long flags; int status = 0; - spin_lock(&cdev->lock); + spin_lock_irqsave(&cdev->lock, flags); if (cdev->deactivations == 0) status = usb_gadget_disconnect(cdev->gadget); if (status == 0) cdev->deactivations++; - spin_unlock(&cdev->lock); + spin_unlock_irqrestore(&cdev->lock, flags); return status; } -- GitLab From 5d67a851bca63d30cde0474bfc4fc4f03db1a1b8 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Tue, 24 Feb 2009 15:23:34 -0800 Subject: [PATCH 4351/4982] USB: musb: rewrite host periodic endpoint allocation The current MUSB host code doesn't make use of all the available FIFOs in for periodic transfers since it wrongly assumes the RX and TX sides of any given hw_ep always share one FIFO. Change: use 'in_qh' and 'out_qh' fields of the 'struct musb_hw_ep' to check the endpoint's business; get rid of the now-unused 'periodic' array in the 'struct musb'. Also optimize a loop induction variable in the endpoint lookup code. (Based on a previous patch from Ajay Kumar Gupta ) [ dbrownell@users.sourceforge.net: clarify description and origin of this fix; whitespace ] Signed-off-by: Sergei Shtylyov Signed-off-by: David Brownell Cc: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.h | 1 - drivers/usb/musb/musb_host.c | 28 +++++++++++----------------- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 630946a2d9f..adf1806007f 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -331,7 +331,6 @@ struct musb { struct list_head control; /* of musb_qh */ struct list_head in_bulk; /* of musb_qh */ struct list_head out_bulk; /* of musb_qh */ - struct musb_qh *periodic[32]; /* tree of interrupt+iso */ #endif /* called with IRQs blocked; ON/nonzero implies starting a session, diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 6dbbd0786a6..9489c859868 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -395,7 +395,6 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status) * de-allocated if it's tracked and allocated; * and where we'd update the schedule tree... */ - musb->periodic[ep->epnum] = NULL; kfree(qh); qh = NULL; break; @@ -1711,31 +1710,27 @@ static int musb_schedule( /* else, periodic transfers get muxed to other endpoints */ - /* FIXME this doesn't consider direction, so it can only - * work for one half of the endpoint hardware, and assumes - * the previous cases handled all non-shared endpoints... - */ - - /* we know this qh hasn't been scheduled, so all we need to do + /* + * We know this qh hasn't been scheduled, so all we need to do * is choose which hardware endpoint to put it on ... * * REVISIT what we really want here is a regular schedule tree - * like e.g. OHCI uses, but for now musb->periodic is just an - * array of the _single_ logical endpoint associated with a - * given physical one (identity mapping logical->physical). - * - * that simplistic approach makes TT scheduling a lot simpler; - * there is none, and thus none of its complexity... + * like e.g. OHCI uses. */ best_diff = 4096; best_end = -1; - for (epnum = 1; epnum < musb->nr_endpoints; epnum++) { + for (epnum = 1, hw_ep = musb->endpoints + 1; + epnum < musb->nr_endpoints; + epnum++, hw_ep++) { int diff; - if (musb->periodic[epnum]) + if (is_in || hw_ep->is_shared_fifo) { + if (hw_ep->in_qh != NULL) + continue; + } else if (hw_ep->out_qh != NULL) continue; - hw_ep = &musb->endpoints[epnum]; + if (hw_ep == musb->bulk_ep) continue; @@ -1764,7 +1759,6 @@ static int musb_schedule( idle = 1; qh->mux = 0; hw_ep = musb->endpoints + best_end; - musb->periodic[best_end] = qh; DBG(4, "qh %p periodic slot %d\n", qh, best_end); success: if (head) { -- GitLab From 1e0320f0d46022d12ddc84516cbdb8865e8cd744 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Tue, 24 Feb 2009 15:26:13 -0800 Subject: [PATCH 4352/4982] USB: musb: NAK timeout scheme on bulk RX endpoint Fixes endpoint starvation issue when more than one bulk QH is multiplexed on the reserved bulk RX endpoint, which is normal for cases like serial and ethernet adapters. This patch sets the NAK timeout interval for such QHs, and when a timeout triggers the next QH will be scheduled. (This resembles the bulk scheduling done in hardware by EHCI, OHCI, and UHCI.) This scheme doesn't work for devices which are connected to a high to full speed tree (transaction translator) as there is no NAK timeout interrupt from the musb controller from such devices. Tested with PIO, Inventra DMA, CPPI DMA. [ dbrownell@users.sourceforge.net: fold in start_urb() update; clarify only for bulk RX; don't accidentally clear WZC bits ] Signed-off-by: Ajay Kumar Gupta Cc: Felipe Balbi Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_host.c | 112 ++++++++++++++++++++++++++--------- 1 file changed, 85 insertions(+), 27 deletions(-) diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 9489c859868..499c431a6d6 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -64,11 +64,8 @@ * * - DMA (Mentor/OMAP) ...has at least toggle update problems * - * - Still no traffic scheduling code to make NAKing for bulk or control - * transfers unable to starve other requests; or to make efficient use - * of hardware with periodic transfers. (Note that network drivers - * commonly post bulk reads that stay pending for a long time; these - * would make very visible trouble.) + * - [23-feb-2009] minimal traffic scheduling to avoid bulk RX packet + * starvation ... nothing yet for TX, interrupt, or bulk. * * - Not tested with HNP, but some SRP paths seem to behave. * @@ -88,11 +85,8 @@ * * CONTROL transfers all go through ep0. BULK ones go through dedicated IN * and OUT endpoints ... hardware is dedicated for those "async" queue(s). - * * (Yes, bulk _could_ use more of the endpoints than that, and would even - * benefit from it ... one remote device may easily be NAKing while others - * need to perform transfers in that same direction. The same thing could - * be done in software though, assuming dma cooperates.) + * benefit from it.) * * INTERUPPT and ISOCHRONOUS transfers are scheduled to the other endpoints. * So far that scheduling is both dumb and optimistic: the endpoint will be @@ -201,8 +195,9 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) len = urb->iso_frame_desc[0].length; break; default: /* bulk, interrupt */ - buf = urb->transfer_buffer; - len = urb->transfer_buffer_length; + /* actual_length may be nonzero on retry paths */ + buf = urb->transfer_buffer + urb->actual_length; + len = urb->transfer_buffer_length - urb->actual_length; } DBG(4, "qh %p urb %p dev%d ep%d%s%s, hw_ep %d, %p/%d\n", @@ -1044,7 +1039,8 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb) /* NOTE: this code path would be a good place to PAUSE a * control transfer, if another one is queued, so that - * ep0 is more likely to stay busy. + * ep0 is more likely to stay busy. That's already done + * for bulk RX transfers. * * if (qh->ring.next != &musb->control), then * we have a candidate... NAKing is *NOT* an error @@ -1196,6 +1192,7 @@ void musb_host_tx(struct musb *musb, u8 epnum) /* NOTE: this code path would be a good place to PAUSE a * transfer, if there's some other (nonperiodic) tx urb * that could use this fifo. (dma complicates it...) + * That's already done for bulk RX transfers. * * if (bulk && qh->ring.next != &musb->out_bulk), then * we have a candidate... NAKing is *NOT* an error @@ -1357,6 +1354,50 @@ finish: #endif +/* Schedule next QH from musb->in_bulk and move the current qh to + * the end; avoids starvation for other endpoints. + */ +static void musb_bulk_rx_nak_timeout(struct musb *musb, struct musb_hw_ep *ep) +{ + struct dma_channel *dma; + struct urb *urb; + void __iomem *mbase = musb->mregs; + void __iomem *epio = ep->regs; + struct musb_qh *cur_qh, *next_qh; + u16 rx_csr; + + musb_ep_select(mbase, ep->epnum); + dma = is_dma_capable() ? ep->rx_channel : NULL; + + /* clear nak timeout bit */ + rx_csr = musb_readw(epio, MUSB_RXCSR); + rx_csr |= MUSB_RXCSR_H_WZC_BITS; + rx_csr &= ~MUSB_RXCSR_DATAERROR; + musb_writew(epio, MUSB_RXCSR, rx_csr); + + cur_qh = first_qh(&musb->in_bulk); + if (cur_qh) { + urb = next_urb(cur_qh); + if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { + dma->status = MUSB_DMA_STATUS_CORE_ABORT; + musb->dma_controller->channel_abort(dma); + urb->actual_length += dma->actual_len; + dma->actual_len = 0L; + } + musb_save_toggle(ep, 1, urb); + + /* move cur_qh to end of queue */ + list_move_tail(&cur_qh->ring, &musb->in_bulk); + + /* get the next qh from musb->in_bulk */ + next_qh = first_qh(&musb->in_bulk); + + /* set rx_reinit and schedule the next qh */ + ep->rx_reinit = 1; + musb_start_urb(musb, 1, next_qh); + } +} + /* * Service an RX interrupt for the given IN endpoint; docs cover bulk, iso, * and high-bandwidth IN transfer cases. @@ -1420,18 +1461,26 @@ void musb_host_rx(struct musb *musb, u8 epnum) } else if (rx_csr & MUSB_RXCSR_DATAERROR) { if (USB_ENDPOINT_XFER_ISOC != qh->type) { - /* NOTE this code path would be a good place to PAUSE a - * transfer, if there's some other (nonperiodic) rx urb - * that could use this fifo. (dma complicates it...) + DBG(6, "RX end %d NAK timeout\n", epnum); + + /* NOTE: NAKing is *NOT* an error, so we want to + * continue. Except ... if there's a request for + * another QH, use that instead of starving it. * - * if (bulk && qh->ring.next != &musb->in_bulk), then - * we have a candidate... NAKing is *NOT* an error + * Devices like Ethernet and serial adapters keep + * reads posted at all times, which will starve + * other devices without this logic. */ - DBG(6, "RX end %d NAK timeout\n", epnum); + if (usb_pipebulk(urb->pipe) + && qh->mux == 1 + && !list_is_singular(&musb->in_bulk)) { + musb_bulk_rx_nak_timeout(musb, hw_ep); + return; + } musb_ep_select(mbase, epnum); - musb_writew(epio, MUSB_RXCSR, - MUSB_RXCSR_H_WZC_BITS - | MUSB_RXCSR_H_REQPKT); + rx_csr |= MUSB_RXCSR_H_WZC_BITS; + rx_csr &= ~MUSB_RXCSR_DATAERROR; + musb_writew(epio, MUSB_RXCSR, rx_csr); goto finish; } else { @@ -1751,6 +1800,17 @@ static int musb_schedule( head = &musb->in_bulk; else head = &musb->out_bulk; + + /* Enable bulk RX NAK timeout scheme when bulk requests are + * multiplexed. This scheme doen't work in high speed to full + * speed scenario as NAK interrupts are not coming from a + * full speed device connected to a high speed device. + * NAK timeout interval is 8 (128 uframe or 16ms) for HS and + * 4 (8 frame or 8ms) for FS device. + */ + if (is_in && qh->dev) + qh->intv_reg = + (USB_SPEED_HIGH == qh->dev->speed) ? 8 : 4; goto success; } else if (best_end < 0) { return -ENOSPC; @@ -1882,13 +1942,11 @@ static int musb_urb_enqueue( * * The downside of disabling this is that transfer scheduling * gets VERY unfair for nonperiodic transfers; a misbehaving - * peripheral could make that hurt. Or for reads, one that's - * perfectly normal: network and other drivers keep reads - * posted at all times, having one pending for a week should - * be perfectly safe. + * peripheral could make that hurt. That's perfectly normal + * for reads from network or serial adapters ... so we have + * partial NAKlimit support for bulk RX. * - * The upside of disabling it is avoidng transfer scheduling - * code to put this aside for while. + * The upside of disabling it is simpler transfer scheduling. */ interval = 0; } -- GitLab From 322337168f22e8245aae7f38e84c5711cd4c1265 Mon Sep 17 00:00:00 2001 From: Giuseppe GORGOGLIONE Date: Tue, 24 Feb 2009 15:27:34 -0800 Subject: [PATCH 4353/4982] USB: musb: fix init oops crash with static FIFO config Correct musb_read_fifosize() and musb_configure_ep0() functions for the #ifndef BLACKFIN branch when the silicon uses static FIFO configuration. (Most current silicon configures this controller to use dynamic FIFO configuration; some parts from ST don't, like the STM STA2062.) Signed-off-by: Giuseppe GORGOGLIONE Signed-off-by: Felipe Balbi Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index adf1806007f..efb39b5e55b 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -478,10 +478,11 @@ static inline void musb_configure_ep0(struct musb *musb) static inline int musb_read_fifosize(struct musb *musb, struct musb_hw_ep *hw_ep, u8 epnum) { + void *mbase = musb->mregs; u8 reg = 0; /* read from core using indexed model */ - reg = musb_readb(hw_ep->regs, 0x10 + MUSB_FIFOSIZE); + reg = musb_readb(mbase, MUSB_EP_OFFSET(epnum, MUSB_FIFOSIZE)); /* 0's returned when no more endpoints */ if (!reg) return -ENODEV; @@ -508,6 +509,7 @@ static inline void musb_configure_ep0(struct musb *musb) { musb->endpoints[0].max_packet_sz_tx = MUSB_EP0_FIFOSIZE; musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE; + musb->endpoints[0].is_shared_fifo = true; } #endif /* CONFIG_BLACKFIN */ -- GitLab From 743821717c611913a5a3f95010b141f0b4cb5463 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Tue, 24 Feb 2009 15:29:04 -0800 Subject: [PATCH 4354/4982] USB: musb: only turn off vbus in OTG hosts Except on DaVinci, VBUS is now switched off as part of idling the USB link (after a_wait_bcon) whenever a device is disconnected from host. This is correct for OTG hosts, where either SRP or an ID interrupt could turn VBUS on again. However, for non-OTG hosts there's no way to turn VBUS on again, so the host becomes unusable. And the procfs entry which once allowed a manual workaround for this is now gone. This patch adds an is_otg_enabled() check before scheduling the switch-off timer in disconnect path, supporting a "classic host" mode where SRP is unavailable. [ dbrownell@users.sourceforge.net: tweak patch description ] Signed-off-by: Ajay Kumar Gupta Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index af77e465900..338cd1611ab 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -769,7 +769,7 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb, case OTG_STATE_A_SUSPEND: usb_hcd_resume_root_hub(musb_to_hcd(musb)); musb_root_disconnect(musb); - if (musb->a_wait_bcon != 0) + if (musb->a_wait_bcon != 0 && is_otg_enabled(musb)) musb_platform_try_idle(musb, jiffies + msecs_to_jiffies(musb->a_wait_bcon)); break; -- GitLab From a227fd7db74fa05d866790a4b29ba049bb5035cc Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 24 Feb 2009 15:31:54 -0800 Subject: [PATCH 4355/4982] USB: musb: partial DaVinci dm355 support Partial support for DaVinci DM355, on the EVM board; peripheral mode should work, once mainline merges DM355 support. Missing: (a) renumbering the GPIO for DRVVBUS on the DM6446 EVM, when DAVINCI_N_GPIO increases; (b) disabling DM355_DEEPSLEEP.DRVVBUS_OVERRIDE so VBUS is driven according to the ID signal, if cpu_is_..._dm355() The new PHY control bits are ignored on DM6446. Signed-off-by: David Brownell Cc: Kevin Hilman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/Kconfig | 6 ++-- drivers/usb/musb/davinci.c | 63 ++++++++++++++++++++++++++------------ drivers/usb/musb/davinci.h | 23 +++++++++----- 3 files changed, 62 insertions(+), 30 deletions(-) diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 9985db08e7d..b66e8544d8b 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -20,8 +20,8 @@ config USB_MUSB_HDRC it's being used with, including the USB peripheral role, or the USB host role, or both. - Texas Instruments parts using this IP include DaVinci 644x, - OMAP 243x, OMAP 343x, and TUSB 6010. + Texas Instruments familiies using this IP include DaVinci + (35x, 644x ...), OMAP 243x, OMAP 3, and TUSB 6010. Analog Devices parts using this IP include Blackfin BF54x, BF525 and BF527. @@ -40,7 +40,7 @@ config USB_MUSB_SOC default y if (BF54x && !BF544) default y if (BF52x && !BF522 && !BF523) -comment "DaVinci 644x USB support" +comment "DaVinci 35x and 644x USB support" depends on USB_MUSB_HDRC && ARCH_DAVINCI comment "OMAP 243x high speed USB support" diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 2dc7606f319..10d11ab113a 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -48,6 +48,9 @@ #include "cppi_dma.h" +#define USB_PHY_CTRL IO_ADDRESS(USBPHY_CTL_PADDR) +#define DM355_DEEPSLEEP IO_ADDRESS(DM355_DEEPSLEEP_PADDR) + /* REVISIT (PM) we should be able to keep the PHY in low power mode most * of the time (24 MHZ oscillator and PLL off, etc) by setting POWER.D0 * and, when in host mode, autosuspending idle root ports... PHYPLLON @@ -56,20 +59,26 @@ static inline void phy_on(void) { - /* start the on-chip PHY and its PLL */ - __raw_writel(USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON, - (void __force __iomem *) IO_ADDRESS(USBPHY_CTL_PADDR)); - while ((__raw_readl((void __force __iomem *) - IO_ADDRESS(USBPHY_CTL_PADDR)) - & USBPHY_PHYCLKGD) == 0) + u32 phy_ctrl = __raw_readl(USB_PHY_CTRL); + + /* power everything up; start the on-chip PHY and its PLL */ + phy_ctrl &= ~(USBPHY_OSCPDWN | USBPHY_OTGPDWN | USBPHY_PHYPDWN); + phy_ctrl |= USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON; + __raw_writel(phy_ctrl, USB_PHY_CTRL); + + /* wait for PLL to lock before proceeding */ + while ((__raw_readl(USB_PHY_CTRL) & USBPHY_PHYCLKGD) == 0) cpu_relax(); } static inline void phy_off(void) { - /* powerdown the on-chip PHY and its oscillator */ - __raw_writel(USBPHY_OSCPDWN | USBPHY_PHYPDWN, (void __force __iomem *) - IO_ADDRESS(USBPHY_CTL_PADDR)); + u32 phy_ctrl = __raw_readl(USB_PHY_CTRL); + + /* powerdown the on-chip PHY, its PLL, and the OTG block */ + phy_ctrl &= ~(USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON); + phy_ctrl |= USBPHY_OSCPDWN | USBPHY_OTGPDWN | USBPHY_PHYPDWN; + __raw_writel(phy_ctrl, USB_PHY_CTRL); } static int dma_off = 1; @@ -126,10 +135,6 @@ void musb_platform_disable(struct musb *musb) } -/* REVISIT it's not clear whether DaVinci can support full OTG. */ - -static int vbus_state = -1; - #ifdef CONFIG_USB_MUSB_HDRC_HCD #define portstate(stmt) stmt #else @@ -137,10 +142,19 @@ static int vbus_state = -1; #endif -/* VBUS SWITCHING IS BOARD-SPECIFIC */ +/* + * VBUS SWITCHING IS BOARD-SPECIFIC ... at least for the DM6446 EVM, + * which doesn't wire DRVVBUS to the FET that switches it. Unclear + * if that's a problem with the DM6446 chip or just with that board. + * + * In either case, the DM355 EVM automates DRVVBUS the normal way, + * when J10 is out, and TI documents it as handling OTG. + */ #ifdef CONFIG_MACH_DAVINCI_EVM +static int vbus_state = -1; + /* I2C operations are always synchronous, and require a task context. * With unloaded systems, using the shared workqueue seems to suffice * to satisfy the 100msec A_WAIT_VRISE timeout... @@ -150,12 +164,12 @@ static void evm_deferred_drvvbus(struct work_struct *ignored) gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); vbus_state = !vbus_state; } -static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus); #endif /* EVM */ static void davinci_source_power(struct musb *musb, int is_on, int immediate) { +#ifdef CONFIG_MACH_DAVINCI_EVM if (is_on) is_on = 1; @@ -163,16 +177,17 @@ static void davinci_source_power(struct musb *musb, int is_on, int immediate) return; vbus_state = !is_on; /* 0/1 vs "-1 == unknown/init" */ -#ifdef CONFIG_MACH_DAVINCI_EVM if (machine_is_davinci_evm()) { + static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus); + if (immediate) gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); else schedule_work(&evm_vbus_work); } -#endif if (immediate) vbus_state = is_on; +#endif } static void davinci_set_vbus(struct musb *musb, int is_on) @@ -391,6 +406,17 @@ int __init musb_platform_init(struct musb *musb) musb->board_set_vbus = davinci_set_vbus; davinci_source_power(musb, 0, 1); + /* dm355 EVM swaps D+/D- for signal integrity, and + * is clocked from the main 24 MHz crystal. + */ + if (machine_is_davinci_dm355_evm()) { + u32 phy_ctrl = __raw_readl(USB_PHY_CTRL); + + phy_ctrl &= ~(3 << 9); + phy_ctrl |= USBPHY_DATAPOL; + __raw_writel(phy_ctrl, USB_PHY_CTRL); + } + /* reset the controller */ musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1); @@ -401,8 +427,7 @@ int __init musb_platform_init(struct musb *musb) /* NOTE: irqs are in mixed mode, not bypass to pure-musb */ pr_debug("DaVinci OTG revision %08x phy %03x control %02x\n", - revision, __raw_readl((void __force __iomem *) - IO_ADDRESS(USBPHY_CTL_PADDR)), + revision, __raw_readl(USB_PHY_CTRL), musb_readb(tibase, DAVINCI_USB_CTRL_REG)); musb->isr = davinci_interrupt; diff --git a/drivers/usb/musb/davinci.h b/drivers/usb/musb/davinci.h index 7fb6238e270..046c84433ca 100644 --- a/drivers/usb/musb/davinci.h +++ b/drivers/usb/musb/davinci.h @@ -15,14 +15,21 @@ */ /* Integrated highspeed/otg PHY */ -#define USBPHY_CTL_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x34) -#define USBPHY_PHYCLKGD (1 << 8) -#define USBPHY_SESNDEN (1 << 7) /* v(sess_end) comparator */ -#define USBPHY_VBDTCTEN (1 << 6) /* v(bus) comparator */ -#define USBPHY_PHYPLLON (1 << 4) /* override pll suspend */ -#define USBPHY_CLKO1SEL (1 << 3) -#define USBPHY_OSCPDWN (1 << 2) -#define USBPHY_PHYPDWN (1 << 0) +#define USBPHY_CTL_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x34) +#define USBPHY_DATAPOL BIT(11) /* (dm355) switch D+/D- */ +#define USBPHY_PHYCLKGD BIT(8) +#define USBPHY_SESNDEN BIT(7) /* v(sess_end) comparator */ +#define USBPHY_VBDTCTEN BIT(6) /* v(bus) comparator */ +#define USBPHY_VBUSSENS BIT(5) /* (dm355,ro) is vbus > 0.5V */ +#define USBPHY_PHYPLLON BIT(4) /* override pll suspend */ +#define USBPHY_CLKO1SEL BIT(3) +#define USBPHY_OSCPDWN BIT(2) +#define USBPHY_OTGPDWN BIT(1) +#define USBPHY_PHYPDWN BIT(0) + +#define DM355_DEEPSLEEP_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x48) +#define DRVVBUS_FORCE BIT(2) +#define DRVVBUS_OVERRIDE BIT(1) /* For now include usb OTG module registers here */ #define DAVINCI_USB_VERSION_REG 0x00 -- GitLab From 1ded7ea47b8829a06068c3bb5e3ebe471076617a Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Fri, 20 Feb 2009 21:23:09 +0800 Subject: [PATCH 4356/4982] USB: ch341 serial: fix port number changed after resume This patch fixes the following bug: .plug ch341 usb serial port into a hub port; .ch341 driver bound to the device and /dev/ttyUSB0 comes .open /dev/ttyUSB0 by minicom and we can use the serial successfully .suspend the ch341 usb serial device(such as: echo suspend > power/level) .resume the ch341 usb serial device (such as: echo on > power/level) .new port /dev/ttyUSB1 comes ,and the original /dev/ttyUSB0 still exists, but is no longer usable by minicom The patch adds suspend and resume callback to ch341 usb driver to prevent it from unbinding during suspend. The /dev/ttyUSB0 is not released until being closed, so /dev/ttyUSB1 comes after resume, and the original /dev/ttyUSB0 is no longer usable by minicom. It is really a mess for a minicom user. This patch also adds the reset_resume callback to make it usable after resuming from STR or hibernation, for generally STR or hibernation will make the vbus of root-hub lost. Finally enable the driver's supports_autosuspend, for the device is in working order with it. Signed-off-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ch341.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index d5ea679e169..ab4cc277aa6 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -529,12 +529,34 @@ static int ch341_tiocmget(struct tty_struct *tty, struct file *file) return result; } + +static int ch341_reset_resume(struct usb_interface *intf) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct usb_serial *serial = NULL; + struct ch341_private *priv; + + serial = usb_get_intfdata(intf); + priv = usb_get_serial_port_data(serial->port[0]); + + /*reconfigure ch341 serial port after bus-reset*/ + ch341_configure(dev, priv); + + usb_serial_resume(intf); + + return 0; +} + static struct usb_driver ch341_driver = { .name = "ch341", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, + .suspend = usb_serial_suspend, + .resume = usb_serial_resume, + .reset_resume = ch341_reset_resume, .id_table = id_table, .no_dynamic_id = 1, + .supports_autosuspend = 1, }; static struct usb_serial_driver ch341_device = { -- GitLab From 471c604daf73ff549d374ee54f9e6bfd5a54d4e8 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Thu, 19 Feb 2009 22:54:45 -0700 Subject: [PATCH 4357/4982] USB: usbmon: Add binary API v1 This patch adds an extension to the binary API so it reaches parity with existing text API (so-called "1u"). The extension delivers additional data, such as ISO descriptors and the interrupt interval. Signed-Off-By: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- Documentation/usb/usbmon.txt | 27 +++++-- drivers/usb/mon/mon_bin.c | 142 ++++++++++++++++++++++++++++------- 2 files changed, 136 insertions(+), 33 deletions(-) diff --git a/Documentation/usb/usbmon.txt b/Documentation/usb/usbmon.txt index 270481906dc..6c3c625b7f3 100644 --- a/Documentation/usb/usbmon.txt +++ b/Documentation/usb/usbmon.txt @@ -229,16 +229,26 @@ struct usbmon_packet { int status; /* 28: */ unsigned int length; /* 32: Length of data (submitted or actual) */ unsigned int len_cap; /* 36: Delivered length */ - unsigned char setup[8]; /* 40: Only for Control 'S' */ -}; /* 48 bytes total */ + union { /* 40: */ + unsigned char setup[SETUP_LEN]; /* Only for Control S-type */ + struct iso_rec { /* Only for ISO */ + int error_count; + int numdesc; + } iso; + } s; + int interval; /* 48: Only for Interrupt and ISO */ + int start_frame; /* 52: For ISO */ + unsigned int xfer_flags; /* 56: copy of URB's transfer_flags */ + unsigned int ndesc; /* 60: Actual number of ISO descriptors */ +}; /* 64 total length */ These events can be received from a character device by reading with read(2), -with an ioctl(2), or by accessing the buffer with mmap. +with an ioctl(2), or by accessing the buffer with mmap. However, read(2) +only returns first 48 bytes for compatibility reasons. The character device is usually called /dev/usbmonN, where N is the USB bus number. Number zero (/dev/usbmon0) is special and means "all buses". -However, this feature is not implemented yet. Note that specific naming -policy is set by your Linux distribution. +Note that specific naming policy is set by your Linux distribution. If you create /dev/usbmon0 by hand, make sure that it is owned by root and has mode 0600. Otherwise, unpriviledged users will be able to snoop @@ -279,9 +289,10 @@ size is out of [unspecified] bounds for this kernel, the call fails with This call returns the current size of the buffer in bytes. MON_IOCX_GET, defined as _IOW(MON_IOC_MAGIC, 6, struct mon_get_arg) + MON_IOCX_GETX, defined as _IOW(MON_IOC_MAGIC, 10, struct mon_get_arg) -This call waits for events to arrive if none were in the kernel buffer, -then returns the first event. Its argument is a pointer to the following +These calls wait for events to arrive if none were in the kernel buffer, +then return the first event. The argument is a pointer to the following structure: struct mon_get_arg { @@ -294,6 +305,8 @@ Before the call, hdr, data, and alloc should be filled. Upon return, the area pointed by hdr contains the next event structure, and the data buffer contains the data, if any. The event is removed from the kernel buffer. +The MON_IOCX_GET copies 48 bytes, MON_IOCX_GETX copies 64 bytes. + MON_IOCX_MFETCH, defined as _IOWR(MON_IOC_MAGIC, 7, struct mon_mfetch_arg) This ioctl is primarily used when the application accesses the buffer diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index 4cf27c72423..f8d9045d668 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c @@ -37,10 +37,13 @@ #define MON_IOCX_GET _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get) #define MON_IOCX_MFETCH _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch) #define MON_IOCH_MFLUSH _IO(MON_IOC_MAGIC, 8) +/* #9 was MON_IOCT_SETAPI */ +#define MON_IOCX_GETX _IOW(MON_IOC_MAGIC, 10, struct mon_bin_get) #ifdef CONFIG_COMPAT #define MON_IOCX_GET32 _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get32) #define MON_IOCX_MFETCH32 _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch32) +#define MON_IOCX_GETX32 _IOW(MON_IOC_MAGIC, 10, struct mon_bin_get32) #endif /* @@ -92,7 +95,29 @@ struct mon_bin_hdr { int status; unsigned int len_urb; /* Length of data (submitted or actual) */ unsigned int len_cap; /* Delivered length */ - unsigned char setup[SETUP_LEN]; /* Only for Control S-type */ + union { + unsigned char setup[SETUP_LEN]; /* Only for Control S-type */ + struct iso_rec { + int error_count; + int numdesc; + } iso; + } s; + int interval; + int start_frame; + unsigned int xfer_flags; + unsigned int ndesc; /* Actual number of ISO descriptors */ +}; + +/* + * ISO vector, packed into the head of data stream. + * This has to take 16 bytes to make sure that the end of buffer + * wrap is not happening in the middle of a descriptor. + */ +struct mon_bin_isodesc { + int iso_status; + unsigned int iso_off; + unsigned int iso_len; + u32 _pad; }; /* per file statistic */ @@ -102,7 +127,7 @@ struct mon_bin_stats { }; struct mon_bin_get { - struct mon_bin_hdr __user *hdr; /* Only 48 bytes, not 64. */ + struct mon_bin_hdr __user *hdr; /* Can be 48 bytes or 64. */ void __user *data; size_t alloc; /* Length of data (can be zero) */ }; @@ -131,6 +156,11 @@ struct mon_bin_mfetch32 { #define PKT_ALIGN 64 #define PKT_SIZE 64 +#define PKT_SZ_API0 48 /* API 0 (2.6.20) size */ +#define PKT_SZ_API1 64 /* API 1 size: extra fields */ + +#define ISODESC_MAX 128 /* Same number as usbfs allows, 2048 bytes. */ + /* max number of USB bus supported */ #define MON_BIN_MAX_MINOR 128 @@ -360,12 +390,8 @@ static inline char mon_bin_get_setup(unsigned char *setupb, const struct urb *urb, char ev_type) { - if (!usb_endpoint_xfer_control(&urb->ep->desc) || ev_type != 'S') - return '-'; - if (urb->setup_packet == NULL) return 'Z'; - memcpy(setupb, urb->setup_packet, SETUP_LEN); return 0; } @@ -387,6 +413,26 @@ static char mon_bin_get_data(const struct mon_reader_bin *rp, return 0; } +static void mon_bin_get_isodesc(const struct mon_reader_bin *rp, + unsigned int offset, struct urb *urb, char ev_type, unsigned int ndesc) +{ + struct mon_bin_isodesc *dp; + struct usb_iso_packet_descriptor *fp; + + fp = urb->iso_frame_desc; + while (ndesc-- != 0) { + dp = (struct mon_bin_isodesc *) + (rp->b_vec[offset / CHUNK_SIZE].ptr + offset % CHUNK_SIZE); + dp->iso_status = fp->status; + dp->iso_off = fp->offset; + dp->iso_len = (ev_type == 'S') ? fp->length : fp->actual_length; + dp->_pad = 0; + if ((offset += sizeof(struct mon_bin_isodesc)) >= rp->b_size) + offset = 0; + fp++; + } +} + static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, char ev_type, int status) { @@ -396,6 +442,7 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, unsigned int urb_length; unsigned int offset; unsigned int length; + unsigned int ndesc, lendesc; unsigned char dir; struct mon_bin_hdr *ep; char data_tag = 0; @@ -407,6 +454,19 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, /* * Find the maximum allowable length, then allocate space. */ + if (usb_endpoint_xfer_isoc(epd)) { + if (urb->number_of_packets < 0) { + ndesc = 0; + } else if (urb->number_of_packets >= ISODESC_MAX) { + ndesc = ISODESC_MAX; + } else { + ndesc = urb->number_of_packets; + } + } else { + ndesc = 0; + } + lendesc = ndesc*sizeof(struct mon_bin_isodesc); + urb_length = (ev_type == 'S') ? urb->transfer_buffer_length : urb->actual_length; length = urb_length; @@ -429,10 +489,12 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, dir = 0; } - if (rp->mmap_active) - offset = mon_buff_area_alloc_contiguous(rp, length + PKT_SIZE); - else - offset = mon_buff_area_alloc(rp, length + PKT_SIZE); + if (rp->mmap_active) { + offset = mon_buff_area_alloc_contiguous(rp, + length + PKT_SIZE + lendesc); + } else { + offset = mon_buff_area_alloc(rp, length + PKT_SIZE + lendesc); + } if (offset == ~0) { rp->cnt_lost++; spin_unlock_irqrestore(&rp->b_lock, flags); @@ -456,9 +518,31 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, ep->ts_usec = ts.tv_usec; ep->status = status; ep->len_urb = urb_length; - ep->len_cap = length; + ep->len_cap = length + lendesc; + ep->xfer_flags = urb->transfer_flags; + + if (usb_endpoint_xfer_int(epd)) { + ep->interval = urb->interval; + } else if (usb_endpoint_xfer_isoc(epd)) { + ep->interval = urb->interval; + ep->start_frame = urb->start_frame; + ep->s.iso.error_count = urb->error_count; + ep->s.iso.numdesc = urb->number_of_packets; + } + + if (usb_endpoint_xfer_control(epd) && ev_type == 'S') { + ep->flag_setup = mon_bin_get_setup(ep->s.setup, urb, ev_type); + } else { + ep->flag_setup = '-'; + } + + if (ndesc != 0) { + ep->ndesc = ndesc; + mon_bin_get_isodesc(rp, offset, urb, ev_type, ndesc); + if ((offset += lendesc) >= rp->b_size) + offset -= rp->b_size; + } - ep->flag_setup = mon_bin_get_setup(ep->setup, urb, ev_type); if (length != 0) { ep->flag_data = mon_bin_get_data(rp, offset, urb, length); if (ep->flag_data != 0) { /* Yes, it's 0x00, not '0' */ @@ -592,7 +676,8 @@ err_alloc: * Returns zero or error. */ static int mon_bin_get_event(struct file *file, struct mon_reader_bin *rp, - struct mon_bin_hdr __user *hdr, void __user *data, unsigned int nbytes) + struct mon_bin_hdr __user *hdr, unsigned int hdrbytes, + void __user *data, unsigned int nbytes) { unsigned long flags; struct mon_bin_hdr *ep; @@ -609,7 +694,7 @@ static int mon_bin_get_event(struct file *file, struct mon_reader_bin *rp, ep = MON_OFF2HDR(rp, rp->b_out); - if (copy_to_user(hdr, ep, sizeof(struct mon_bin_hdr))) { + if (copy_to_user(hdr, ep, hdrbytes)) { mutex_unlock(&rp->fetch_lock); return -EFAULT; } @@ -657,6 +742,7 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { struct mon_reader_bin *rp = file->private_data; + unsigned int hdrbytes = PKT_SZ_API0; unsigned long flags; struct mon_bin_hdr *ep; unsigned int offset; @@ -674,8 +760,8 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf, ep = MON_OFF2HDR(rp, rp->b_out); - if (rp->b_read < sizeof(struct mon_bin_hdr)) { - step_len = min(nbytes, sizeof(struct mon_bin_hdr) - rp->b_read); + if (rp->b_read < hdrbytes) { + step_len = min(nbytes, (size_t)(hdrbytes - rp->b_read)); ptr = ((char *)ep) + rp->b_read; if (step_len && copy_to_user(buf, ptr, step_len)) { mutex_unlock(&rp->fetch_lock); @@ -687,13 +773,13 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf, done += step_len; } - if (rp->b_read >= sizeof(struct mon_bin_hdr)) { + if (rp->b_read >= hdrbytes) { step_len = ep->len_cap; - step_len -= rp->b_read - sizeof(struct mon_bin_hdr); + step_len -= rp->b_read - hdrbytes; if (step_len > nbytes) step_len = nbytes; offset = rp->b_out + PKT_SIZE; - offset += rp->b_read - sizeof(struct mon_bin_hdr); + offset += rp->b_read - hdrbytes; if (offset >= rp->b_size) offset -= rp->b_size; if (copy_from_buf(rp, offset, buf, step_len)) { @@ -709,7 +795,7 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf, /* * Check if whole packet was read, and if so, jump to the next one. */ - if (rp->b_read >= sizeof(struct mon_bin_hdr) + ep->len_cap) { + if (rp->b_read >= hdrbytes + ep->len_cap) { spin_lock_irqsave(&rp->b_lock, flags); mon_buff_area_free(rp, PKT_SIZE + ep->len_cap); spin_unlock_irqrestore(&rp->b_lock, flags); @@ -908,6 +994,7 @@ static int mon_bin_ioctl(struct inode *inode, struct file *file, break; case MON_IOCX_GET: + case MON_IOCX_GETX: { struct mon_bin_get getb; @@ -917,8 +1004,9 @@ static int mon_bin_ioctl(struct inode *inode, struct file *file, if (getb.alloc > 0x10000000) /* Want to cast to u32 */ return -EINVAL; - ret = mon_bin_get_event(file, rp, - getb.hdr, getb.data, (unsigned int)getb.alloc); + ret = mon_bin_get_event(file, rp, getb.hdr, + (cmd == MON_IOCX_GET)? PKT_SZ_API0: PKT_SZ_API1, + getb.data, (unsigned int)getb.alloc); } break; @@ -984,16 +1072,18 @@ static long mon_bin_compat_ioctl(struct file *file, switch (cmd) { - case MON_IOCX_GET32: { + case MON_IOCX_GET32: + case MON_IOCX_GETX32: + { struct mon_bin_get32 getb; if (copy_from_user(&getb, (void __user *)arg, sizeof(struct mon_bin_get32))) return -EFAULT; - ret = mon_bin_get_event(file, rp, - compat_ptr(getb.hdr32), compat_ptr(getb.data32), - getb.alloc32); + ret = mon_bin_get_event(file, rp, compat_ptr(getb.hdr32), + (cmd == MON_IOCX_GET32)? PKT_SZ_API0: PKT_SZ_API1, + compat_ptr(getb.data32), getb.alloc32); if (ret < 0) return ret; } -- GitLab From 66760169492445395c530c812443f58e2cfdb3dc Mon Sep 17 00:00:00 2001 From: Jouni Hogander Date: Fri, 20 Feb 2009 14:02:31 +0200 Subject: [PATCH 4358/4982] USB: TWL: disable VUSB regulators when cable unplugged This patch disables USB regulators VUSB1V5, VUSB1V8, and VUSB3V1 when the USB cable is unplugged to reduce power consumption. Added a depencency from twl4030 usb driver to TWL_REGULATOR. Signed-off-by: Jouni Hogander Signed-off-by: Kalle Jokiniemi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/otg/Kconfig | 2 +- drivers/usb/otg/twl4030-usb.c | 73 ++++++++++++++++++++++++++++++----- 2 files changed, 65 insertions(+), 10 deletions(-) diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index fc1ca03ce4d..aa884d072f0 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -43,7 +43,7 @@ config ISP1301_OMAP config TWL4030_USB tristate "TWL4030 USB Transceiver Driver" - depends on TWL4030_CORE + depends on TWL4030_CORE && REGULATOR_TWL4030 select USB_OTG_UTILS help Enable this to support the USB OTG transceiver on TWL4030 diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index 416e4410be0..d9478d0e1c8 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c @@ -34,6 +34,8 @@ #include #include #include +#include +#include /* Register defines */ @@ -246,6 +248,11 @@ struct twl4030_usb { struct otg_transceiver otg; struct device *dev; + /* TWL4030 internal USB regulator supplies */ + struct regulator *usb1v5; + struct regulator *usb1v8; + struct regulator *usb3v1; + /* for vbus reporting with irqs disabled */ spinlock_t lock; @@ -434,6 +441,18 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on) pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); if (on) { + regulator_enable(twl->usb3v1); + regulator_enable(twl->usb1v8); + /* + * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP + * in twl4030) resets the VUSB_DEDICATED2 register. This reset + * enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to + * SLEEP. We work around this by clearing the bit after usv3v1 + * is re-activated. This ensures that VUSB3V1 is really active. + */ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, + VUSB_DEDICATED2); + regulator_enable(twl->usb1v5); pwr &= ~PHY_PWR_PHYPWD; WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); twl4030_usb_write(twl, PHY_CLK_CTRL, @@ -443,6 +462,9 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on) } else { pwr |= PHY_PWR_PHYPWD; WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); + regulator_disable(twl->usb1v5); + regulator_disable(twl->usb1v8); + regulator_disable(twl->usb3v1); } } @@ -468,7 +490,7 @@ static void twl4030_phy_resume(struct twl4030_usb *twl) twl->asleep = 0; } -static void twl4030_usb_ldo_init(struct twl4030_usb *twl) +static int twl4030_usb_ldo_init(struct twl4030_usb *twl) { /* Enable writing to power configuration registers */ twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY); @@ -480,20 +502,45 @@ static void twl4030_usb_ldo_init(struct twl4030_usb *twl) /* input to VUSB3V1 LDO is from VBAT, not VBUS */ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1); - /* turn on 3.1V regulator */ - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB3V1_DEV_GRP); + /* Initialize 3.1V regulator */ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP); + + twl->usb3v1 = regulator_get(twl->dev, "usb3v1"); + if (IS_ERR(twl->usb3v1)) + return -ENODEV; + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE); - /* turn on 1.5V regulator */ - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V5_DEV_GRP); + /* Initialize 1.5V regulator */ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP); + + twl->usb1v5 = regulator_get(twl->dev, "usb1v5"); + if (IS_ERR(twl->usb1v5)) + goto fail1; + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE); - /* turn on 1.8V regulator */ - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V8_DEV_GRP); + /* Initialize 1.8V regulator */ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP); + + twl->usb1v8 = regulator_get(twl->dev, "usb1v8"); + if (IS_ERR(twl->usb1v8)) + goto fail2; + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE); /* disable access to power configuration registers */ twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, PROTECT_KEY); + + return 0; + +fail2: + regulator_put(twl->usb1v5); + twl->usb1v5 = NULL; +fail1: + regulator_put(twl->usb3v1); + twl->usb3v1 = NULL; + return -ENODEV; } static ssize_t twl4030_usb_vbus_show(struct device *dev, @@ -598,7 +645,7 @@ static int __init twl4030_usb_probe(struct platform_device *pdev) { struct twl4030_usb_data *pdata = pdev->dev.platform_data; struct twl4030_usb *twl; - int status; + int status, err; if (!pdata) { dev_dbg(&pdev->dev, "platform_data not available\n"); @@ -622,7 +669,12 @@ static int __init twl4030_usb_probe(struct platform_device *pdev) /* init spinlock for workqueue */ spin_lock_init(&twl->lock); - twl4030_usb_ldo_init(twl); + err = twl4030_usb_ldo_init(twl); + if (err) { + dev_err(&pdev->dev, "ldo init failed\n"); + kfree(twl); + return err; + } otg_set_transceiver(&twl->otg); platform_set_drvdata(pdev, twl); @@ -688,6 +740,9 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev) twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); twl4030_phy_power(twl, 0); + regulator_put(twl->usb1v5); + regulator_put(twl->usb1v8); + regulator_put(twl->usb3v1); kfree(twl); -- GitLab From 7ea0a2bcfe40b1c525e63e931b7142ab22b64269 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 5 Mar 2009 11:01:11 -0500 Subject: [PATCH 4359/4982] USB: uhci: don't use pseudo negative values The code in uhci-q.c doesn't have to use pseudo-negative values. I did it that way because it was easy and because it would give the expected output during debugging. But it doesn't have to work that way. Here's another approach. Signed-off-by: Alan Stern Cc: Roel Kluin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-debug.c | 4 +++- drivers/usb/host/uhci-q.c | 11 ++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 20cc58b9780..e52b954dda4 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -118,7 +118,9 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space) } out += sprintf(out, "%s%s", ptype, (urbp->fsbr ? " FSBR" : "")); - out += sprintf(out, " Actlen=%d", urbp->urb->actual_length); + out += sprintf(out, " Actlen=%d%s", urbp->urb->actual_length, + (urbp->qh->type == USB_ENDPOINT_XFER_CONTROL ? + "-8" : "")); if (urbp->urb->unlinked) out += sprintf(out, " Unlinked=%d", urbp->urb->unlinked); diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 58f87367914..3e5807d14ff 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -899,8 +899,6 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, } if (qh->state != QH_STATE_ACTIVE) qh->skel = skel; - - urb->actual_length = -8; /* Account for the SETUP packet */ return 0; nomem: @@ -1494,11 +1492,10 @@ __acquires(uhci->lock) if (qh->type == USB_ENDPOINT_XFER_CONTROL) { - /* urb->actual_length < 0 means the setup transaction didn't - * complete successfully. Either it failed or the URB was - * unlinked first. Regardless, don't confuse people with a - * negative length. */ - urb->actual_length = max(urb->actual_length, 0); + /* Subtract off the length of the SETUP packet from + * urb->actual_length. + */ + urb->actual_length -= min_t(u32, 8, urb->actual_length); } /* When giving back the first URB in an Isochronous queue, -- GitLab From 16e2e5f634f86ccda18366967c4e592eb61bc9cc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 3 Mar 2009 16:44:13 -0800 Subject: [PATCH 4360/4982] USB: make transfer_buffer_lengths in struct urb field u32 Roel Kluin pointed out that transfer_buffer_lengths in struct urb was declared as an 'int'. This patch changes this field to be 'u32' to prevent any potential negative conversion and comparison errors. This triggered a few compiler warning messages when these fields were being used with the min macro, so they have also been fixed up in this patch. Cc: Roel Kluin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/dummy_hcd.c | 2 +- drivers/usb/host/isp116x-hcd.c | 2 +- drivers/usb/host/r8a66597-hcd.c | 2 +- drivers/usb/host/sl811-hcd.c | 4 ++-- drivers/usb/misc/ftdi-elan.c | 6 +++--- include/linux/usb.h | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 3b42888b72f..a56b24d305f 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -1437,7 +1437,7 @@ restart: } if (urb->transfer_buffer_length > 1) buf [1] = 0; - urb->actual_length = min (2, + urb->actual_length = min_t(u32, 2, urb->transfer_buffer_length); value = 0; status = 0; diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 4dda31b2689..a2b305477af 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -772,7 +772,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd, break; case PIPE_INTERRUPT: urb->interval = ep->period; - ep->length = min((int)ep->maxpacket, + ep->length = min_t(u32, ep->maxpacket, urb->transfer_buffer_length); /* urb submitted for already existing endpoint */ diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 5e942d94aeb..713f4cf0b0d 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -1394,7 +1394,7 @@ static void packet_write(struct r8a66597 *r8a66597, u16 pipenum) (int)urb->iso_frame_desc[td->iso_cnt].length); } else { buf = (u16 *)(urb->transfer_buffer + urb->actual_length); - size = min((int)bufsize, + size = min_t(u32, bufsize, urb->transfer_buffer_length - urb->actual_length); } diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index e106e9d48d4..a949259f18b 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -230,7 +230,7 @@ static void in_packet( writeb(usb_pipedevice(urb->pipe), data_reg); sl811_write(sl811, bank + SL11H_HOSTCTLREG, control); - ep->length = min((int)len, + ep->length = min_t(u32, len, urb->transfer_buffer_length - urb->actual_length); PACKET("IN%s/%d qh%p len%d\n", ep->nak_count ? "/retry" : "", !!usb_gettoggle(urb->dev, ep->epnum, 0), ep, len); @@ -255,7 +255,7 @@ static void out_packet( buf = urb->transfer_buffer + urb->actual_length; prefetch(buf); - len = min((int)ep->maxpacket, + len = min_t(u32, ep->maxpacket, urb->transfer_buffer_length - urb->actual_length); if (!(control & SL11H_HCTLMASK_ISOCH) diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 79a7668ef26..9d0675ed0d4 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -1568,7 +1568,7 @@ static int ftdi_elan_edset_input(struct usb_ftdi *ftdi, u8 ed_number, struct u132_target *target = &ftdi->target[ed]; struct u132_command *command = &ftdi->command[ COMMAND_MASK & ftdi->command_next]; - int remaining_length = urb->transfer_buffer_length - + u32 remaining_length = urb->transfer_buffer_length - urb->actual_length; command->header = 0x82 | (ed << 5); if (remaining_length == 0) { @@ -1702,7 +1702,7 @@ static int ftdi_elan_edset_output(struct usb_ftdi *ftdi, u8 ed_number, | (address << 0); command->width = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); - command->follows = min(1024, + command->follows = min_t(u32, 1024, urb->transfer_buffer_length - urb->actual_length); command->value = 0; @@ -1766,7 +1766,7 @@ static int ftdi_elan_edset_single(struct usb_ftdi *ftdi, u8 ed_number, mutex_lock(&ftdi->u132_lock); command_size = ftdi->command_next - ftdi->command_head; if (command_size < COMMAND_SIZE) { - int remaining_length = urb->transfer_buffer_length - + u32 remaining_length = urb->transfer_buffer_length - urb->actual_length; struct u132_target *target = &ftdi->target[ed]; struct u132_command *command = &ftdi->command[ diff --git a/include/linux/usb.h b/include/linux/usb.h index 0c05ff62119..db8808e05a2 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1177,7 +1177,7 @@ struct urb { unsigned int transfer_flags; /* (in) URB_SHORT_NOT_OK | ...*/ void *transfer_buffer; /* (in) associated data buffer */ dma_addr_t transfer_dma; /* (in) dma addr for transfer_buffer */ - int transfer_buffer_length; /* (in) data buffer length */ + u32 transfer_buffer_length; /* (in) data buffer length */ int actual_length; /* (return) actual transfer length */ unsigned char *setup_packet; /* (in) setup packet (control only) */ dma_addr_t setup_dma; /* (in) dma addr for setup_packet */ -- GitLab From 8c209e6782ca0e3046803fc04a5ac01c8c10437a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 6 Mar 2009 21:31:03 -0800 Subject: [PATCH 4361/4982] USB: make actual_length in struct urb field u32 actual_length should also be a u32 and not a signed value. This patch changes this field to be 'u32' to prevent any potential negative conversion and comparison errors. This triggered a few compiler warning messages when these fields were being used with the min macro, so they have also been fixed up in this patch. Cc: Roel Kluin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 2 +- include/linux/usb.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index adeb23fb800..dcc87aaa862 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1947,7 +1947,7 @@ static void ftdi_process_read(struct work_struct *work) priv->prev_status = new_status; } - length = min(PKTSZ, urb->actual_length-packet_offset)-2; + length = min_t(u32, PKTSZ, urb->actual_length-packet_offset)-2; if (length < 0) { dev_err(&port->dev, "%s - bad packet length: %d\n", __func__, length+2); diff --git a/include/linux/usb.h b/include/linux/usb.h index db8808e05a2..c6b2ab41b90 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1178,7 +1178,7 @@ struct urb { void *transfer_buffer; /* (in) associated data buffer */ dma_addr_t transfer_dma; /* (in) dma addr for transfer_buffer */ u32 transfer_buffer_length; /* (in) data buffer length */ - int actual_length; /* (return) actual transfer length */ + u32 actual_length; /* (return) actual transfer length */ unsigned char *setup_packet; /* (in) setup packet (control only) */ dma_addr_t setup_dma; /* (in) dma addr for setup_packet */ int start_frame; /* (modify) start frame (ISO) */ -- GitLab From 77aa2b5878f48d6ab6e0c412cc9214c845483475 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 4 Mar 2009 16:23:31 -0800 Subject: [PATCH 4362/4982] USB: remove phidget drivers from kernel tree. These devices are better controlled with the LGPL userspace library found at: http://www.phidgets.com/downloads.php?os_id=3 and full documentation at: http://www.phidgets.com/documentation/web/cdoc/index.html Cc: Chester Fitchett Acked-by: Sean Young Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/Kconfig | 39 -- drivers/usb/misc/Makefile | 4 - drivers/usb/misc/phidget.c | 43 -- drivers/usb/misc/phidget.h | 12 - drivers/usb/misc/phidgetkit.c | 740 ------------------------- drivers/usb/misc/phidgetmotorcontrol.c | 465 ---------------- drivers/usb/misc/phidgetservo.c | 375 ------------- 7 files changed, 1678 deletions(-) delete mode 100644 drivers/usb/misc/phidget.c delete mode 100644 drivers/usb/misc/phidget.h delete mode 100644 drivers/usb/misc/phidgetkit.c delete mode 100644 drivers/usb/misc/phidgetmotorcontrol.c delete mode 100644 drivers/usb/misc/phidgetservo.c diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index e463db5d818..a68d91a11be 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -135,45 +135,6 @@ config USB_CYTHERM To compile this driver as a module, choose M here: the module will be called cytherm. -config USB_PHIDGET - tristate "USB Phidgets drivers" - depends on USB - help - Say Y here to enable the various drivers for devices from - Phidgets inc. - -config USB_PHIDGETKIT - tristate "USB PhidgetInterfaceKit support" - depends on USB_PHIDGET - help - Say Y here if you want to connect a PhidgetInterfaceKit USB device - from Phidgets Inc. - - To compile this driver as a module, choose M here: the - module will be called phidgetkit. - -config USB_PHIDGETMOTORCONTROL - tristate "USB PhidgetMotorControl support" - depends on USB_PHIDGET - help - Say Y here if you want to connect a PhidgetMotorControl USB device - from Phidgets Inc. - - To compile this driver as a module, choose M here: the - module will be called phidgetmotorcontrol. - -config USB_PHIDGETSERVO - tristate "USB PhidgetServo support" - depends on USB_PHIDGET - help - Say Y here if you want to connect an 1 or 4 Motor PhidgetServo - servo controller version 2.0 or 3.0. - - Phidgets Inc. has a web page at . - - To compile this driver as a module, choose M here: the - module will be called phidgetservo. - config USB_IDMOUSE tristate "Siemens ID USB Mouse Fingerprint sensor support" depends on USB diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 1334f7bdd7b..0826aab8303 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -18,10 +18,6 @@ obj-$(CONFIG_USB_LCD) += usblcd.o obj-$(CONFIG_USB_LD) += ldusb.o obj-$(CONFIG_USB_LED) += usbled.o obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o -obj-$(CONFIG_USB_PHIDGET) += phidget.o -obj-$(CONFIG_USB_PHIDGETKIT) += phidgetkit.o -obj-$(CONFIG_USB_PHIDGETMOTORCONTROL) += phidgetmotorcontrol.o -obj-$(CONFIG_USB_PHIDGETSERVO) += phidgetservo.o obj-$(CONFIG_USB_RIO500) += rio500.o obj-$(CONFIG_USB_TEST) += usbtest.o obj-$(CONFIG_USB_TRANCEVIBRATOR) += trancevibrator.o diff --git a/drivers/usb/misc/phidget.c b/drivers/usb/misc/phidget.c deleted file mode 100644 index 735ed33f4f7..00000000000 --- a/drivers/usb/misc/phidget.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * USB Phidgets class - * - * Copyright (C) 2006 Sean Young - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include -#include -#include -#include -#include - -struct class *phidget_class; - -static int __init init_phidget(void) -{ - phidget_class = class_create(THIS_MODULE, "phidget"); - - if (IS_ERR(phidget_class)) - return PTR_ERR(phidget_class); - - return 0; -} - -static void __exit cleanup_phidget(void) -{ - class_destroy(phidget_class); -} - -EXPORT_SYMBOL_GPL(phidget_class); - -module_init(init_phidget); -module_exit(cleanup_phidget); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Sean Young "); -MODULE_DESCRIPTION("Container module for phidget class"); - diff --git a/drivers/usb/misc/phidget.h b/drivers/usb/misc/phidget.h deleted file mode 100644 index c4011907d43..00000000000 --- a/drivers/usb/misc/phidget.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * USB Phidgets class - * - * Copyright (C) 2006 Sean Young - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -extern struct class *phidget_class; diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c deleted file mode 100644 index cc8e0a926f9..00000000000 --- a/drivers/usb/misc/phidgetkit.c +++ /dev/null @@ -1,740 +0,0 @@ -/* - * USB PhidgetInterfaceKit driver 1.0 - * - * Copyright (C) 2004, 2006 Sean Young - * Copyright (C) 2005 Daniel Saakes - * Copyright (C) 2004 Greg Kroah-Hartman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This is a driver for the USB PhidgetInterfaceKit. - */ - -#include -#include -#include -#include -#include -#include - -#include "phidget.h" - -#define DRIVER_AUTHOR "Sean Young " -#define DRIVER_DESC "USB PhidgetInterfaceKit Driver" - -#define USB_VENDOR_ID_GLAB 0x06c2 -#define USB_DEVICE_ID_INTERFACEKIT004 0x0040 -#define USB_DEVICE_ID_INTERFACEKIT01616 0x0044 -#define USB_DEVICE_ID_INTERFACEKIT888 0x0045 -#define USB_DEVICE_ID_INTERFACEKIT047 0x0051 -#define USB_DEVICE_ID_INTERFACEKIT088 0x0053 - -#define USB_VENDOR_ID_WISEGROUP 0x0925 -#define USB_DEVICE_ID_INTERFACEKIT884 0x8201 - -#define MAX_INTERFACES 16 - -#define URB_INT_SIZE 8 - -struct driver_interfacekit { - int sensors; - int inputs; - int outputs; - int has_lcd; - int amnesiac; -}; - -#define ifkit(_sensors, _inputs, _outputs, _lcd, _amnesiac) \ -{ \ - .sensors = _sensors, \ - .inputs = _inputs, \ - .outputs = _outputs, \ - .has_lcd = _lcd, \ - .amnesiac = _amnesiac \ -}; - -static const struct driver_interfacekit ph_004 = ifkit(0, 0, 4, 0, 0); -static const struct driver_interfacekit ph_888n = ifkit(8, 8, 8, 0, 1); -static const struct driver_interfacekit ph_888o = ifkit(8, 8, 8, 0, 0); -static const struct driver_interfacekit ph_047 = ifkit(0, 4, 7, 1, 0); -static const struct driver_interfacekit ph_884 = ifkit(8, 8, 4, 0, 0); -static const struct driver_interfacekit ph_088 = ifkit(0, 8, 8, 1, 0); -static const struct driver_interfacekit ph_01616 = ifkit(0, 16, 16, 0, 0); - -static unsigned long device_no; - -struct interfacekit { - struct usb_device *udev; - struct usb_interface *intf; - struct driver_interfacekit *ifkit; - struct device *dev; - unsigned long outputs; - int dev_no; - u8 inputs[MAX_INTERFACES]; - u16 sensors[MAX_INTERFACES]; - u8 lcd_files_on; - - struct urb *irq; - unsigned char *data; - dma_addr_t data_dma; - - struct delayed_work do_notify; - struct delayed_work do_resubmit; - unsigned long input_events; - unsigned long sensor_events; -}; - -static struct usb_device_id id_table[] = { - {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT004), - .driver_info = (kernel_ulong_t)&ph_004}, - {USB_DEVICE_VER(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888, 0, 0x814), - .driver_info = (kernel_ulong_t)&ph_888o}, - {USB_DEVICE_VER(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888, 0x0815, 0xffff), - .driver_info = (kernel_ulong_t)&ph_888n}, - {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT047), - .driver_info = (kernel_ulong_t)&ph_047}, - {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088), - .driver_info = (kernel_ulong_t)&ph_088}, - {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT01616), - .driver_info = (kernel_ulong_t)&ph_01616}, - {USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_INTERFACEKIT884), - .driver_info = (kernel_ulong_t)&ph_884}, - {} -}; -MODULE_DEVICE_TABLE(usb, id_table); - -static int set_outputs(struct interfacekit *kit) -{ - u8 *buffer; - int retval; - - buffer = kzalloc(4, GFP_KERNEL); - if (!buffer) { - dev_err(&kit->udev->dev, "%s - out of memory\n", __func__); - return -ENOMEM; - } - buffer[0] = (u8)kit->outputs; - buffer[1] = (u8)(kit->outputs >> 8); - - dev_dbg(&kit->udev->dev, "sending data: 0x%04x\n", (u16)kit->outputs); - - retval = usb_control_msg(kit->udev, - usb_sndctrlpipe(kit->udev, 0), - 0x09, 0x21, 0x0200, 0x0000, buffer, 4, 2000); - - if (retval != 4) - dev_err(&kit->udev->dev, "usb_control_msg returned %d\n", - retval); - kfree(buffer); - - if (kit->ifkit->amnesiac) - schedule_delayed_work(&kit->do_resubmit, HZ / 2); - - return retval < 0 ? retval : 0; -} - -static int change_string(struct interfacekit *kit, const char *display, unsigned char row) -{ - unsigned char *buffer; - unsigned char *form_buffer; - int retval = -ENOMEM; - int i,j, len, buf_ptr; - - buffer = kmalloc(8, GFP_KERNEL); - form_buffer = kmalloc(30, GFP_KERNEL); - if ((!buffer) || (!form_buffer)) { - dev_err(&kit->udev->dev, "%s - out of memory\n", __func__); - goto exit; - } - - len = strlen(display); - if (len > 20) - len = 20; - - dev_dbg(&kit->udev->dev, "Setting LCD line %d to %s\n", row, display); - - form_buffer[0] = row * 0x40 + 0x80; - form_buffer[1] = 0x02; - buf_ptr = 2; - for (i = 0; i 7) - len = 7; - else - len = (buf_ptr - i); - for (j = 0; j < len; j++) - buffer[j] = form_buffer[i + j]; - buffer[7] = len; - - retval = usb_control_msg(kit->udev, - usb_sndctrlpipe(kit->udev, 0), - 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000); - if (retval < 0) - goto exit; - } - - retval = 0; -exit: - kfree(buffer); - kfree(form_buffer); - - return retval; -} - -#define set_lcd_line(number) \ -static ssize_t lcd_line_##number(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct interfacekit *kit = dev_get_drvdata(dev); \ - change_string(kit, buf, number - 1); \ - return count; \ -} - -#define lcd_line_attr(number) \ - __ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number) - -set_lcd_line(1); -set_lcd_line(2); - -static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct interfacekit *kit = dev_get_drvdata(dev); - int enabled; - unsigned char *buffer; - int retval = -ENOMEM; - - buffer = kzalloc(8, GFP_KERNEL); - if (!buffer) { - dev_err(&kit->udev->dev, "%s - out of memory\n", __func__); - goto exit; - } - - if (sscanf(buf, "%d", &enabled) < 1) { - retval = -EINVAL; - goto exit; - } - if (enabled) - buffer[0] = 0x01; - buffer[7] = 0x11; - - dev_dbg(&kit->udev->dev, "Setting backlight to %s\n", enabled ? "on" : "off"); - - retval = usb_control_msg(kit->udev, - usb_sndctrlpipe(kit->udev, 0), - 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000); - if (retval < 0) - goto exit; - - retval = count; -exit: - kfree(buffer); - return retval; -} - -static struct device_attribute dev_lcd_line_attrs[] = { - lcd_line_attr(1), - lcd_line_attr(2), - __ATTR(backlight, S_IWUGO, NULL, set_backlight) -}; - -static void remove_lcd_files(struct interfacekit *kit) -{ - int i; - - if (kit->lcd_files_on) { - dev_dbg(&kit->udev->dev, "Removing lcd files\n"); - - for (i=0; idev, &dev_lcd_line_attrs[i]); - } -} - -static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct interfacekit *kit = dev_get_drvdata(dev); - int enable; - int i, rc; - - if (kit->ifkit->has_lcd == 0) - return -ENODEV; - - if (sscanf(buf, "%d", &enable) < 1) - return -EINVAL; - - if (enable) { - if (!kit->lcd_files_on) { - dev_dbg(&kit->udev->dev, "Adding lcd files\n"); - for (i=0; idev, - &dev_lcd_line_attrs[i]); - if (rc) - goto out; - } - kit->lcd_files_on = 1; - } - } else { - if (kit->lcd_files_on) { - remove_lcd_files(kit); - kit->lcd_files_on = 0; - } - } - - return count; -out: - while (i-- > 0) - device_remove_file(kit->dev, &dev_lcd_line_attrs[i]); - - return rc; -} - -static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files); - -static void interfacekit_irq(struct urb *urb) -{ - struct interfacekit *kit = urb->context; - unsigned char *buffer = kit->data; - int i, level, sensor; - int retval; - int status = urb->status; - - switch (status) { - case 0: /* success */ - break; - case -ECONNRESET: /* unlink */ - case -ENOENT: - case -ESHUTDOWN: - return; - /* -EPIPE: should clear the halt */ - default: /* error */ - goto resubmit; - } - - /* digital inputs */ - if (kit->ifkit->inputs == 16) { - for (i=0; i < 8; i++) { - level = (buffer[0] >> i) & 1; - if (kit->inputs[i] != level) { - kit->inputs[i] = level; - set_bit(i, &kit->input_events); - } - level = (buffer[1] >> i) & 1; - if (kit->inputs[8 + i] != level) { - kit->inputs[8 + i] = level; - set_bit(8 + i, &kit->input_events); - } - } - } - else if (kit->ifkit->inputs == 8) { - for (i=0; i < 8; i++) { - level = (buffer[1] >> i) & 1; - if (kit->inputs[i] != level) { - kit->inputs[i] = level; - set_bit(i, &kit->input_events); - } - } - } - - /* analog inputs */ - if (kit->ifkit->sensors) { - sensor = (buffer[0] & 1) ? 4 : 0; - - level = buffer[2] + (buffer[3] & 0x0f) * 256; - if (level != kit->sensors[sensor]) { - kit->sensors[sensor] = level; - set_bit(sensor, &kit->sensor_events); - } - sensor++; - level = buffer[4] + (buffer[3] & 0xf0) * 16; - if (level != kit->sensors[sensor]) { - kit->sensors[sensor] = level; - set_bit(sensor, &kit->sensor_events); - } - sensor++; - level = buffer[5] + (buffer[6] & 0x0f) * 256; - if (level != kit->sensors[sensor]) { - kit->sensors[sensor] = level; - set_bit(sensor, &kit->sensor_events); - } - sensor++; - level = buffer[7] + (buffer[6] & 0xf0) * 16; - if (level != kit->sensors[sensor]) { - kit->sensors[sensor] = level; - set_bit(sensor, &kit->sensor_events); - } - } - - if (kit->input_events || kit->sensor_events) - schedule_delayed_work(&kit->do_notify, 0); - -resubmit: - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - err("can't resubmit intr, %s-%s/interfacekit0, retval %d", - kit->udev->bus->bus_name, - kit->udev->devpath, retval); -} - -static void do_notify(struct work_struct *work) -{ - struct interfacekit *kit = - container_of(work, struct interfacekit, do_notify.work); - int i; - char sysfs_file[8]; - - for (i=0; iifkit->inputs; i++) { - if (test_and_clear_bit(i, &kit->input_events)) { - sprintf(sysfs_file, "input%d", i + 1); - sysfs_notify(&kit->dev->kobj, NULL, sysfs_file); - } - } - - for (i=0; iifkit->sensors; i++) { - if (test_and_clear_bit(i, &kit->sensor_events)) { - sprintf(sysfs_file, "sensor%d", i + 1); - sysfs_notify(&kit->dev->kobj, NULL, sysfs_file); - } - } -} - -static void do_resubmit(struct work_struct *work) -{ - struct interfacekit *kit = - container_of(work, struct interfacekit, do_resubmit.work); - set_outputs(kit); -} - -#define show_set_output(value) \ -static ssize_t set_output##value(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct interfacekit *kit = dev_get_drvdata(dev); \ - int enable; \ - int retval; \ - \ - if (sscanf(buf, "%d", &enable) < 1) \ - return -EINVAL; \ - \ - if (enable) \ - set_bit(value - 1, &kit->outputs); \ - else \ - clear_bit(value - 1, &kit->outputs); \ - \ - retval = set_outputs(kit); \ - \ - return retval ? retval : count; \ -} \ - \ -static ssize_t show_output##value(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct interfacekit *kit = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\ -} - -#define output_attr(value) \ - __ATTR(output##value, S_IWUGO | S_IRUGO, \ - show_output##value, set_output##value) - -show_set_output(1); -show_set_output(2); -show_set_output(3); -show_set_output(4); -show_set_output(5); -show_set_output(6); -show_set_output(7); -show_set_output(8); -show_set_output(9); -show_set_output(10); -show_set_output(11); -show_set_output(12); -show_set_output(13); -show_set_output(14); -show_set_output(15); -show_set_output(16); - -static struct device_attribute dev_output_attrs[] = { - output_attr(1), output_attr(2), output_attr(3), output_attr(4), - output_attr(5), output_attr(6), output_attr(7), output_attr(8), - output_attr(9), output_attr(10), output_attr(11), output_attr(12), - output_attr(13), output_attr(14), output_attr(15), output_attr(16) -}; - -#define show_input(value) \ -static ssize_t show_input##value(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct interfacekit *kit = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]); \ -} - -#define input_attr(value) \ - __ATTR(input##value, S_IRUGO, show_input##value, NULL) - -show_input(1); -show_input(2); -show_input(3); -show_input(4); -show_input(5); -show_input(6); -show_input(7); -show_input(8); -show_input(9); -show_input(10); -show_input(11); -show_input(12); -show_input(13); -show_input(14); -show_input(15); -show_input(16); - -static struct device_attribute dev_input_attrs[] = { - input_attr(1), input_attr(2), input_attr(3), input_attr(4), - input_attr(5), input_attr(6), input_attr(7), input_attr(8), - input_attr(9), input_attr(10), input_attr(11), input_attr(12), - input_attr(13), input_attr(14), input_attr(15), input_attr(16) -}; - -#define show_sensor(value) \ -static ssize_t show_sensor##value(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct interfacekit *kit = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]); \ -} - -#define sensor_attr(value) \ - __ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL) - -show_sensor(1); -show_sensor(2); -show_sensor(3); -show_sensor(4); -show_sensor(5); -show_sensor(6); -show_sensor(7); -show_sensor(8); - -static struct device_attribute dev_sensor_attrs[] = { - sensor_attr(1), sensor_attr(2), sensor_attr(3), sensor_attr(4), - sensor_attr(5), sensor_attr(6), sensor_attr(7), sensor_attr(8) -}; - -static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct interfacekit *kit; - struct driver_interfacekit *ifkit; - int pipe, maxp, rc = -ENOMEM; - int bit, value, i; - - ifkit = (struct driver_interfacekit *)id->driver_info; - if (!ifkit) - return -ENODEV; - - interface = intf->cur_altsetting; - if (interface->desc.bNumEndpoints != 1) - return -ENODEV; - - endpoint = &interface->endpoint[0].desc; - if (!usb_endpoint_dir_in(endpoint)) - return -ENODEV; - /* - * bmAttributes - */ - pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); - maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - - kit = kzalloc(sizeof(*kit), GFP_KERNEL); - if (!kit) - goto out; - - kit->dev_no = -1; - kit->ifkit = ifkit; - kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, GFP_ATOMIC, &kit->data_dma); - if (!kit->data) - goto out; - - kit->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!kit->irq) - goto out; - - kit->udev = usb_get_dev(dev); - kit->intf = intf; - INIT_DELAYED_WORK(&kit->do_notify, do_notify); - INIT_DELAYED_WORK(&kit->do_resubmit, do_resubmit); - usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data, - maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp, - interfacekit_irq, kit, endpoint->bInterval); - kit->irq->transfer_dma = kit->data_dma; - kit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - usb_set_intfdata(intf, kit); - - do { - bit = find_first_zero_bit(&device_no, sizeof(device_no)); - value = test_and_set_bit(bit, &device_no); - } while(value); - kit->dev_no = bit; - - kit->dev = device_create(phidget_class, &kit->udev->dev, MKDEV(0, 0), - kit, "interfacekit%d", kit->dev_no); - if (IS_ERR(kit->dev)) { - rc = PTR_ERR(kit->dev); - kit->dev = NULL; - goto out; - } - - if (usb_submit_urb(kit->irq, GFP_KERNEL)) { - rc = -EIO; - goto out; - } - - for (i=0; ioutputs; i++ ) { - rc = device_create_file(kit->dev, &dev_output_attrs[i]); - if (rc) - goto out2; - } - - for (i=0; iinputs; i++ ) { - rc = device_create_file(kit->dev, &dev_input_attrs[i]); - if (rc) - goto out3; - } - - for (i=0; isensors; i++ ) { - rc = device_create_file(kit->dev, &dev_sensor_attrs[i]); - if (rc) - goto out4; - } - - if (ifkit->has_lcd) { - rc = device_create_file(kit->dev, &dev_attr_lcd); - if (rc) - goto out4; - - } - - dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n", - ifkit->sensors, ifkit->inputs, ifkit->outputs); - - return 0; - -out4: - while (i-- > 0) - device_remove_file(kit->dev, &dev_sensor_attrs[i]); - - i = ifkit->inputs; -out3: - while (i-- > 0) - device_remove_file(kit->dev, &dev_input_attrs[i]); - - i = ifkit->outputs; -out2: - while (i-- > 0) - device_remove_file(kit->dev, &dev_output_attrs[i]); -out: - if (kit) { - usb_free_urb(kit->irq); - if (kit->data) - usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma); - if (kit->dev) - device_unregister(kit->dev); - if (kit->dev_no >= 0) - clear_bit(kit->dev_no, &device_no); - - kfree(kit); - } - - return rc; -} - -static void interfacekit_disconnect(struct usb_interface *interface) -{ - struct interfacekit *kit; - int i; - - kit = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - if (!kit) - return; - - usb_kill_urb(kit->irq); - usb_free_urb(kit->irq); - usb_buffer_free(kit->udev, URB_INT_SIZE, kit->data, kit->data_dma); - - cancel_delayed_work(&kit->do_notify); - cancel_delayed_work(&kit->do_resubmit); - - for (i=0; iifkit->outputs; i++) - device_remove_file(kit->dev, &dev_output_attrs[i]); - - for (i=0; iifkit->inputs; i++) - device_remove_file(kit->dev, &dev_input_attrs[i]); - - for (i=0; iifkit->sensors; i++) - device_remove_file(kit->dev, &dev_sensor_attrs[i]); - - if (kit->ifkit->has_lcd) { - device_remove_file(kit->dev, &dev_attr_lcd); - remove_lcd_files(kit); - } - - device_unregister(kit->dev); - - dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n", - kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs); - - usb_put_dev(kit->udev); - clear_bit(kit->dev_no, &device_no); - - kfree(kit); -} - -static struct usb_driver interfacekit_driver = { - .name = "phidgetkit", - .probe = interfacekit_probe, - .disconnect = interfacekit_disconnect, - .id_table = id_table -}; - -static int __init interfacekit_init(void) -{ - int retval = 0; - - retval = usb_register(&interfacekit_driver); - if (retval) - err("usb_register failed. Error number %d", retval); - - return retval; -} - -static void __exit interfacekit_exit(void) -{ - usb_deregister(&interfacekit_driver); -} - -module_init(interfacekit_init); -module_exit(interfacekit_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c deleted file mode 100644 index 38088b44349..00000000000 --- a/drivers/usb/misc/phidgetmotorcontrol.c +++ /dev/null @@ -1,465 +0,0 @@ -/* - * USB Phidget MotorControl driver - * - * Copyright (C) 2006 Sean Young - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include -#include -#include -#include -#include - -#include "phidget.h" - -#define DRIVER_AUTHOR "Sean Young " -#define DRIVER_DESC "USB PhidgetMotorControl Driver" - -#define USB_VENDOR_ID_GLAB 0x06c2 -#define USB_DEVICE_ID_MOTORCONTROL 0x0058 - -#define URB_INT_SIZE 8 - -static unsigned long device_no; - -struct motorcontrol { - struct usb_device *udev; - struct usb_interface *intf; - struct device *dev; - int dev_no; - u8 inputs[4]; - s8 desired_speed[2]; - s8 speed[2]; - s16 _current[2]; - s8 acceleration[2]; - struct urb *irq; - unsigned char *data; - dma_addr_t data_dma; - - struct delayed_work do_notify; - unsigned long input_events; - unsigned long speed_events; - unsigned long exceed_events; -}; - -static struct usb_device_id id_table[] = { - { USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_MOTORCONTROL) }, - {} -}; -MODULE_DEVICE_TABLE(usb, id_table); - -static int set_motor(struct motorcontrol *mc, int motor) -{ - u8 *buffer; - int speed, speed2, acceleration; - int retval; - - buffer = kzalloc(8, GFP_KERNEL); - if (!buffer) { - dev_err(&mc->intf->dev, "%s - out of memory\n", __func__); - return -ENOMEM; - } - - acceleration = mc->acceleration[motor] * 10; - /* -127 <= speed <= 127 */ - speed = (mc->desired_speed[motor] * 127) / 100; - /* -0x7300 <= speed2 <= 0x7300 */ - speed2 = (mc->desired_speed[motor] * 230 * 128) / 100; - - buffer[0] = motor; - buffer[1] = speed; - buffer[2] = acceleration >> 8; - buffer[3] = acceleration; - buffer[4] = speed2 >> 8; - buffer[5] = speed2; - - retval = usb_control_msg(mc->udev, - usb_sndctrlpipe(mc->udev, 0), - 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000); - - if (retval != 8) - dev_err(&mc->intf->dev, "usb_control_msg returned %d\n", - retval); - kfree(buffer); - - return retval < 0 ? retval : 0; -} - -static void motorcontrol_irq(struct urb *urb) -{ - struct motorcontrol *mc = urb->context; - unsigned char *buffer = mc->data; - int i, level; - int retval; - int status = urb->status;; - - switch (status) { - case 0: /* success */ - break; - case -ECONNRESET: /* unlink */ - case -ENOENT: - case -ESHUTDOWN: - return; - /* -EPIPE: should clear the halt */ - default: /* error */ - goto resubmit; - } - - /* digital inputs */ - for (i=0; i<4; i++) { - level = (buffer[0] >> i) & 1; - if (mc->inputs[i] != level) { - mc->inputs[i] = level; - set_bit(i, &mc->input_events); - } - } - - /* motor speed */ - if (buffer[2] == 0) { - for (i=0; i<2; i++) { - level = ((s8)buffer[4+i]) * 100 / 127; - if (mc->speed[i] != level) { - mc->speed[i] = level; - set_bit(i, &mc->speed_events); - } - } - } else { - int index = buffer[3] & 1; - - level = ((s8)buffer[4] << 8) | buffer[5]; - level = level * 100 / 29440; - if (mc->speed[index] != level) { - mc->speed[index] = level; - set_bit(index, &mc->speed_events); - } - - level = ((s8)buffer[6] << 8) | buffer[7]; - mc->_current[index] = level * 100 / 1572; - } - - if (buffer[1] & 1) - set_bit(0, &mc->exceed_events); - - if (buffer[1] & 2) - set_bit(1, &mc->exceed_events); - - if (mc->input_events || mc->exceed_events || mc->speed_events) - schedule_delayed_work(&mc->do_notify, 0); - -resubmit: - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - dev_err(&mc->intf->dev, - "can't resubmit intr, %s-%s/motorcontrol0, retval %d\n", - mc->udev->bus->bus_name, - mc->udev->devpath, retval); -} - -static void do_notify(struct work_struct *work) -{ - struct motorcontrol *mc = - container_of(work, struct motorcontrol, do_notify.work); - int i; - char sysfs_file[8]; - - for (i=0; i<4; i++) { - if (test_and_clear_bit(i, &mc->input_events)) { - sprintf(sysfs_file, "input%d", i); - sysfs_notify(&mc->dev->kobj, NULL, sysfs_file); - } - } - - for (i=0; i<2; i++) { - if (test_and_clear_bit(i, &mc->speed_events)) { - sprintf(sysfs_file, "speed%d", i); - sysfs_notify(&mc->dev->kobj, NULL, sysfs_file); - } - } - - for (i=0; i<2; i++) { - if (test_and_clear_bit(i, &mc->exceed_events)) - dev_warn(&mc->intf->dev, - "motor #%d exceeds 1.5 Amp current limit\n", i); - } -} - -#define show_set_speed(value) \ -static ssize_t set_speed##value(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct motorcontrol *mc = dev_get_drvdata(dev); \ - int speed; \ - int retval; \ - \ - if (sscanf(buf, "%d", &speed) < 1) \ - return -EINVAL; \ - \ - if (speed < -100 || speed > 100) \ - return -EINVAL; \ - \ - mc->desired_speed[value] = speed; \ - \ - retval = set_motor(mc, value); \ - \ - return retval ? retval : count; \ -} \ - \ -static ssize_t show_speed##value(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct motorcontrol *mc = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%d\n", mc->speed[value]); \ -} - -#define speed_attr(value) \ - __ATTR(speed##value, S_IWUGO | S_IRUGO, \ - show_speed##value, set_speed##value) - -show_set_speed(0); -show_set_speed(1); - -#define show_set_acceleration(value) \ -static ssize_t set_acceleration##value(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct motorcontrol *mc = dev_get_drvdata(dev); \ - int acceleration; \ - int retval; \ - \ - if (sscanf(buf, "%d", &acceleration) < 1) \ - return -EINVAL; \ - \ - if (acceleration < 0 || acceleration > 100) \ - return -EINVAL; \ - \ - mc->acceleration[value] = acceleration; \ - \ - retval = set_motor(mc, value); \ - \ - return retval ? retval : count; \ -} \ - \ -static ssize_t show_acceleration##value(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct motorcontrol *mc = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%d\n", mc->acceleration[value]); \ -} - -#define acceleration_attr(value) \ - __ATTR(acceleration##value, S_IWUGO | S_IRUGO, \ - show_acceleration##value, set_acceleration##value) - -show_set_acceleration(0); -show_set_acceleration(1); - -#define show_current(value) \ -static ssize_t show_current##value(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct motorcontrol *mc = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%dmA\n", (int)mc->_current[value]); \ -} - -#define current_attr(value) \ - __ATTR(current##value, S_IRUGO, show_current##value, NULL) - -show_current(0); -show_current(1); - -#define show_input(value) \ -static ssize_t show_input##value(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct motorcontrol *mc = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%d\n", (int)mc->inputs[value]); \ -} - -#define input_attr(value) \ - __ATTR(input##value, S_IRUGO, show_input##value, NULL) - -show_input(0); -show_input(1); -show_input(2); -show_input(3); - -static struct device_attribute dev_attrs[] = { - input_attr(0), - input_attr(1), - input_attr(2), - input_attr(3), - speed_attr(0), - speed_attr(1), - acceleration_attr(0), - acceleration_attr(1), - current_attr(0), - current_attr(1) -}; - -static int motorcontrol_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct motorcontrol *mc; - int pipe, maxp, rc = -ENOMEM; - int bit, value, i; - - interface = intf->cur_altsetting; - if (interface->desc.bNumEndpoints != 1) - return -ENODEV; - - endpoint = &interface->endpoint[0].desc; - if (!usb_endpoint_dir_in(endpoint)) - return -ENODEV; - - /* - * bmAttributes - */ - pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); - maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - - mc = kzalloc(sizeof(*mc), GFP_KERNEL); - if (!mc) - goto out; - - mc->dev_no = -1; - mc->data = usb_buffer_alloc(dev, URB_INT_SIZE, GFP_ATOMIC, &mc->data_dma); - if (!mc->data) - goto out; - - mc->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!mc->irq) - goto out; - - mc->udev = usb_get_dev(dev); - mc->intf = intf; - mc->acceleration[0] = mc->acceleration[1] = 10; - INIT_DELAYED_WORK(&mc->do_notify, do_notify); - usb_fill_int_urb(mc->irq, mc->udev, pipe, mc->data, - maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp, - motorcontrol_irq, mc, endpoint->bInterval); - mc->irq->transfer_dma = mc->data_dma; - mc->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - usb_set_intfdata(intf, mc); - - do { - bit = find_first_zero_bit(&device_no, sizeof(device_no)); - value = test_and_set_bit(bit, &device_no); - } while(value); - mc->dev_no = bit; - - mc->dev = device_create(phidget_class, &mc->udev->dev, MKDEV(0, 0), mc, - "motorcontrol%d", mc->dev_no); - if (IS_ERR(mc->dev)) { - rc = PTR_ERR(mc->dev); - mc->dev = NULL; - goto out; - } - - if (usb_submit_urb(mc->irq, GFP_KERNEL)) { - rc = -EIO; - goto out; - } - - for (i=0; idev, &dev_attrs[i]); - if (rc) - goto out2; - } - - dev_info(&intf->dev, "USB PhidgetMotorControl attached\n"); - - return 0; -out2: - while (i-- > 0) - device_remove_file(mc->dev, &dev_attrs[i]); -out: - if (mc) { - usb_free_urb(mc->irq); - if (mc->data) - usb_buffer_free(dev, URB_INT_SIZE, mc->data, mc->data_dma); - if (mc->dev) - device_unregister(mc->dev); - if (mc->dev_no >= 0) - clear_bit(mc->dev_no, &device_no); - - kfree(mc); - } - - return rc; -} - -static void motorcontrol_disconnect(struct usb_interface *interface) -{ - struct motorcontrol *mc; - int i; - - mc = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - if (!mc) - return; - - usb_kill_urb(mc->irq); - usb_free_urb(mc->irq); - usb_buffer_free(mc->udev, URB_INT_SIZE, mc->data, mc->data_dma); - - cancel_delayed_work(&mc->do_notify); - - for (i=0; idev, &dev_attrs[i]); - - device_unregister(mc->dev); - - usb_put_dev(mc->udev); - clear_bit(mc->dev_no, &device_no); - kfree(mc); - - dev_info(&interface->dev, "USB PhidgetMotorControl detached\n"); -} - -static struct usb_driver motorcontrol_driver = { - .name = "phidgetmotorcontrol", - .probe = motorcontrol_probe, - .disconnect = motorcontrol_disconnect, - .id_table = id_table -}; - -static int __init motorcontrol_init(void) -{ - int retval = 0; - - retval = usb_register(&motorcontrol_driver); - if (retval) - err("usb_register failed. Error number %d", retval); - - return retval; -} - -static void __exit motorcontrol_exit(void) -{ - usb_deregister(&motorcontrol_driver); -} - -module_init(motorcontrol_init); -module_exit(motorcontrol_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c deleted file mode 100644 index bef6fe16364..00000000000 --- a/drivers/usb/misc/phidgetservo.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - * USB PhidgetServo driver 1.0 - * - * Copyright (C) 2004, 2006 Sean Young - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This is a driver for the USB PhidgetServo version 2.0 and 3.0 servo - * controllers available at: http://www.phidgets.com/ - * - * Note that the driver takes input as: degrees.minutes - * - * CAUTION: Generally you should use 0 < degrees < 180 as anything else - * is probably beyond the range of your servo and may damage it. - */ - -#include -#include -#include -#include -#include -#include - -#include "phidget.h" - -#define DRIVER_AUTHOR "Sean Young " -#define DRIVER_DESC "USB PhidgetServo Driver" - -#define VENDOR_ID_GLAB 0x06c2 -#define DEVICE_ID_GLAB_PHIDGETSERVO_QUAD 0x0038 -#define DEVICE_ID_GLAB_PHIDGETSERVO_UNI 0x0039 - -#define VENDOR_ID_WISEGROUP 0x0925 -#define VENDOR_ID_WISEGROUP_PHIDGETSERVO_QUAD 0x8101 -#define VENDOR_ID_WISEGROUP_PHIDGETSERVO_UNI 0x8104 - -#define SERVO_VERSION_30 0x01 -#define SERVO_COUNT_QUAD 0x02 - -static struct usb_device_id id_table[] = { - { - USB_DEVICE(VENDOR_ID_GLAB, DEVICE_ID_GLAB_PHIDGETSERVO_QUAD), - .driver_info = SERVO_VERSION_30 | SERVO_COUNT_QUAD - }, - { - USB_DEVICE(VENDOR_ID_GLAB, DEVICE_ID_GLAB_PHIDGETSERVO_UNI), - .driver_info = SERVO_VERSION_30 - }, - { - USB_DEVICE(VENDOR_ID_WISEGROUP, - VENDOR_ID_WISEGROUP_PHIDGETSERVO_QUAD), - .driver_info = SERVO_COUNT_QUAD - }, - { - USB_DEVICE(VENDOR_ID_WISEGROUP, - VENDOR_ID_WISEGROUP_PHIDGETSERVO_UNI), - .driver_info = 0 - }, - {} -}; - -MODULE_DEVICE_TABLE(usb, id_table); - -static int unsigned long device_no; - -struct phidget_servo { - struct usb_device *udev; - struct device *dev; - int dev_no; - ulong type; - int pulse[4]; - int degrees[4]; - int minutes[4]; -}; - -static int -change_position_v30(struct phidget_servo *servo, int servo_no, int degrees, - int minutes) -{ - int retval; - unsigned char *buffer; - - if (degrees < -23 || degrees > 362) - return -EINVAL; - - buffer = kmalloc(6, GFP_KERNEL); - if (!buffer) { - dev_err(&servo->udev->dev, "%s - out of memory\n", - __func__); - return -ENOMEM; - } - - /* - * pulse = 0 - 4095 - * angle = 0 - 180 degrees - * - * pulse = angle * 10.6 + 243.8 - */ - servo->pulse[servo_no] = ((degrees*60 + minutes)*106 + 2438*60)/600; - servo->degrees[servo_no]= degrees; - servo->minutes[servo_no]= minutes; - - /* - * The PhidgetServo v3.0 is controlled by sending 6 bytes, - * 4 * 12 bits for each servo. - * - * low = lower 8 bits pulse - * high = higher 4 bits pulse - * - * offset bits - * +---+-----------------+ - * | 0 | low 0 | - * +---+--------+--------+ - * | 1 | high 1 | high 0 | - * +---+--------+--------+ - * | 2 | low 1 | - * +---+-----------------+ - * | 3 | low 2 | - * +---+--------+--------+ - * | 4 | high 3 | high 2 | - * +---+--------+--------+ - * | 5 | low 3 | - * +---+-----------------+ - */ - - buffer[0] = servo->pulse[0] & 0xff; - buffer[1] = (servo->pulse[0] >> 8 & 0x0f) - | (servo->pulse[1] >> 4 & 0xf0); - buffer[2] = servo->pulse[1] & 0xff; - buffer[3] = servo->pulse[2] & 0xff; - buffer[4] = (servo->pulse[2] >> 8 & 0x0f) - | (servo->pulse[3] >> 4 & 0xf0); - buffer[5] = servo->pulse[3] & 0xff; - - dev_dbg(&servo->udev->dev, - "data: %02x %02x %02x %02x %02x %02x\n", - buffer[0], buffer[1], buffer[2], - buffer[3], buffer[4], buffer[5]); - - retval = usb_control_msg(servo->udev, - usb_sndctrlpipe(servo->udev, 0), - 0x09, 0x21, 0x0200, 0x0000, buffer, 6, 2000); - - kfree(buffer); - - return retval; -} - -static int -change_position_v20(struct phidget_servo *servo, int servo_no, int degrees, - int minutes) -{ - int retval; - unsigned char *buffer; - - if (degrees < -23 || degrees > 278) - return -EINVAL; - - buffer = kmalloc(2, GFP_KERNEL); - if (!buffer) { - dev_err(&servo->udev->dev, "%s - out of memory\n", - __func__); - return -ENOMEM; - } - - /* - * angle = 0 - 180 degrees - * pulse = angle + 23 - */ - servo->pulse[servo_no]= degrees + 23; - servo->degrees[servo_no]= degrees; - servo->minutes[servo_no]= 0; - - /* - * The PhidgetServo v2.0 is controlled by sending two bytes. The - * first byte is the servo number xor'ed with 2: - * - * servo 0 = 2 - * servo 1 = 3 - * servo 2 = 0 - * servo 3 = 1 - * - * The second byte is the position. - */ - - buffer[0] = servo_no ^ 2; - buffer[1] = servo->pulse[servo_no]; - - dev_dbg(&servo->udev->dev, "data: %02x %02x\n", buffer[0], buffer[1]); - - retval = usb_control_msg(servo->udev, - usb_sndctrlpipe(servo->udev, 0), - 0x09, 0x21, 0x0200, 0x0000, buffer, 2, 2000); - - kfree(buffer); - - return retval; -} - -#define show_set(value) \ -static ssize_t set_servo##value (struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - int degrees, minutes, retval; \ - struct phidget_servo *servo = dev_get_drvdata(dev); \ - \ - minutes = 0; \ - /* must at least convert degrees */ \ - if (sscanf(buf, "%d.%d", °rees, &minutes) < 1) { \ - return -EINVAL; \ - } \ - \ - if (minutes < 0 || minutes > 59) \ - return -EINVAL; \ - \ - if (servo->type & SERVO_VERSION_30) \ - retval = change_position_v30(servo, value, degrees, \ - minutes); \ - else \ - retval = change_position_v20(servo, value, degrees, \ - minutes); \ - \ - return retval < 0 ? retval : count; \ -} \ - \ -static ssize_t show_servo##value (struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct phidget_servo *servo = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%d.%02d\n", servo->degrees[value], \ - servo->minutes[value]); \ -} - -#define servo_attr(value) \ - __ATTR(servo##value, S_IWUGO | S_IRUGO, \ - show_servo##value, set_servo##value) -show_set(0); -show_set(1); -show_set(2); -show_set(3); - -static struct device_attribute dev_attrs[] = { - servo_attr(0), servo_attr(1), servo_attr(2), servo_attr(3) -}; - -static int -servo_probe(struct usb_interface *interface, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(interface); - struct phidget_servo *dev; - int bit, value, rc; - int servo_count, i; - - dev = kzalloc(sizeof (struct phidget_servo), GFP_KERNEL); - if (dev == NULL) { - dev_err(&interface->dev, "%s - out of memory\n", __func__); - rc = -ENOMEM; - goto out; - } - - dev->udev = usb_get_dev(udev); - dev->type = id->driver_info; - dev->dev_no = -1; - usb_set_intfdata(interface, dev); - - do { - bit = find_first_zero_bit(&device_no, sizeof(device_no)); - value = test_and_set_bit(bit, &device_no); - } while (value); - dev->dev_no = bit; - - dev->dev = device_create(phidget_class, &dev->udev->dev, MKDEV(0, 0), - dev, "servo%d", dev->dev_no); - if (IS_ERR(dev->dev)) { - rc = PTR_ERR(dev->dev); - dev->dev = NULL; - goto out; - } - - servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1; - - for (i=0; idev, &dev_attrs[i]); - if (rc) - goto out2; - } - - dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 attached\n", - servo_count, dev->type & SERVO_VERSION_30 ? 3 : 2); - - if (!(dev->type & SERVO_VERSION_30)) - dev_info(&interface->dev, - "WARNING: v2.0 not tested! Please report if it works.\n"); - - return 0; -out2: - while (i-- > 0) - device_remove_file(dev->dev, &dev_attrs[i]); -out: - if (dev) { - if (dev->dev) - device_unregister(dev->dev); - if (dev->dev_no >= 0) - clear_bit(dev->dev_no, &device_no); - - kfree(dev); - } - - return rc; -} - -static void -servo_disconnect(struct usb_interface *interface) -{ - struct phidget_servo *dev; - int servo_count, i; - - dev = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - - if (!dev) - return; - - servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1; - - for (i=0; idev, &dev_attrs[i]); - - device_unregister(dev->dev); - usb_put_dev(dev->udev); - - dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 detached\n", - servo_count, dev->type & SERVO_VERSION_30 ? 3 : 2); - - clear_bit(dev->dev_no, &device_no); - kfree(dev); -} - -static struct usb_driver servo_driver = { - .name = "phidgetservo", - .probe = servo_probe, - .disconnect = servo_disconnect, - .id_table = id_table -}; - -static int __init -phidget_servo_init(void) -{ - int retval; - - retval = usb_register(&servo_driver); - if (retval) - err("usb_register failed. Error number %d", retval); - - return retval; -} - -static void __exit -phidget_servo_exit(void) -{ - usb_deregister(&servo_driver); -} - -module_init(phidget_servo_init); -module_exit(phidget_servo_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); -- GitLab From 4fe0387afa893b44c5a21b9bfbb0888354ef4656 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 26 Feb 2009 10:21:02 -0500 Subject: [PATCH 4363/4982] USB: don't send Set-Interface after reset This patch (as1221) changes the way usbcore reinitializes a device following a reset or a reset-resume. Currently we call usb_set_interface() for every interface in the active configuration; this is to put the interface into the same altsetting as before the reset and to make sure that the host's endpoint state matches the device's endpoint state. However, sending a Set-Interface request is a waste of time if an interface was already in altsetting 0 before the reset, since it is certainly in altsetting 0 afterward. In addition, many devices can't handle Set-Interface requests -- they crash when they receive them. So instead, the patch adds code to check each interface. If the interface wasn't in altsetting 0 before the reset, we go head with the Set-Interface request as before. But if it was then we skip sending the Set-Interface request, and we clear out the host-side endpoint state by calling usb_disable_interface() followed by usb_enable_interface(). The patch also adds a couple of new comments to explain what's going on. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index f17d9ebc44a..81eb3e6b659 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3393,10 +3393,10 @@ static int usb_reset_and_verify_device(struct usb_device *udev) udev->descriptor = descriptor; /* for disconnect() calls */ goto re_enumerate; } - + + /* Restore the device's previous configuration */ if (!udev->actconfig) goto done; - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), USB_REQ_SET_CONFIGURATION, 0, udev->actconfig->desc.bConfigurationValue, 0, @@ -3409,16 +3409,25 @@ static int usb_reset_and_verify_device(struct usb_device *udev) } usb_set_device_state(udev, USB_STATE_CONFIGURED); + /* Put interfaces back into the same altsettings as before. + * Don't bother to send the Set-Interface request for interfaces + * that were already in altsetting 0; besides being unnecessary, + * many devices can't handle it. Instead just reset the host-side + * endpoint state. + */ for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { struct usb_interface *intf = udev->actconfig->interface[i]; struct usb_interface_descriptor *desc; - /* set_interface resets host side toggle even - * for altsetting zero. the interface may have no driver. - */ desc = &intf->cur_altsetting->desc; - ret = usb_set_interface(udev, desc->bInterfaceNumber, - desc->bAlternateSetting); + if (desc->bAlternateSetting == 0) { + usb_disable_interface(udev, intf, true); + usb_enable_interface(udev, intf, true); + ret = 0; + } else { + ret = usb_set_interface(udev, desc->bInterfaceNumber, + desc->bAlternateSetting); + } if (ret < 0) { dev_err(&udev->dev, "failed to restore interface %d " "altsetting %d (error=%d)\n", -- GitLab From d34d9721a559fd11ec682bd9ef17220de0162060 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 9 Mar 2009 13:44:48 -0400 Subject: [PATCH 4364/4982] USB: usbfs: remove unneeded "inline" annotations This patch (as1223) removes a bunch of unnecessary "inline" annotations from the usbfs driver. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 8f022af2fd7..d3883f63960 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -104,7 +104,7 @@ MODULE_PARM_DESC(usbfs_snoop, "true to log all usbfs traffic"); #define MAX_USBFS_BUFFER_SIZE 16384 -static inline int connected(struct dev_state *ps) +static int connected(struct dev_state *ps) { return (!list_empty(&ps->list) && ps->dev->state != USB_STATE_NOTATTACHED); @@ -248,7 +248,7 @@ static void free_async(struct async *as) kfree(as); } -static inline void async_newpending(struct async *as) +static void async_newpending(struct async *as) { struct dev_state *ps = as->ps; unsigned long flags; @@ -258,7 +258,7 @@ static inline void async_newpending(struct async *as) spin_unlock_irqrestore(&ps->lock, flags); } -static inline void async_removepending(struct async *as) +static void async_removepending(struct async *as) { struct dev_state *ps = as->ps; unsigned long flags; @@ -268,7 +268,7 @@ static inline void async_removepending(struct async *as) spin_unlock_irqrestore(&ps->lock, flags); } -static inline struct async *async_getcompleted(struct dev_state *ps) +static struct async *async_getcompleted(struct dev_state *ps) { unsigned long flags; struct async *as = NULL; @@ -283,7 +283,7 @@ static inline struct async *async_getcompleted(struct dev_state *ps) return as; } -static inline struct async *async_getpending(struct dev_state *ps, +static struct async *async_getpending(struct dev_state *ps, void __user *userurb) { unsigned long flags; @@ -376,7 +376,7 @@ static void destroy_async_on_interface(struct dev_state *ps, destroy_async(ps, &hitlist); } -static inline void destroy_all_async(struct dev_state *ps) +static void destroy_all_async(struct dev_state *ps) { destroy_async(ps, &ps->async_pending); } -- GitLab From 31dbb803464d75b96212cce9052dfeaeac0819de Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Wed, 4 Mar 2009 12:06:15 -0800 Subject: [PATCH 4365/4982] USB: use kzfree() Use kzfree() instead of memset() + kfree(). Signed-off-by: Johannes Weiner Reviewed-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/hwa-hc.c | 3 +-- drivers/usb/wusbcore/cbaf.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c index 8582236e4ca..cbf30e515f2 100644 --- a/drivers/usb/host/hwa-hc.c +++ b/drivers/usb/host/hwa-hc.c @@ -464,8 +464,7 @@ static int __hwahc_dev_set_key(struct wusbhc *wusbhc, u8 port_idx, u32 tkid, port_idx << 8 | iface_no, keyd, keyd_len, 1000 /* FIXME: arbitrary */); - memset(keyd, 0, sizeof(*keyd)); /* clear keys etc. */ - kfree(keyd); + kzfree(keyd); /* clear keys etc. */ return result; } diff --git a/drivers/usb/wusbcore/cbaf.c b/drivers/usb/wusbcore/cbaf.c index 1335cbe1191..25eae405f62 100644 --- a/drivers/usb/wusbcore/cbaf.c +++ b/drivers/usb/wusbcore/cbaf.c @@ -638,8 +638,7 @@ static void cbaf_disconnect(struct usb_interface *iface) usb_put_intf(iface); kfree(cbaf->buffer); /* paranoia: clean up crypto keys */ - memset(cbaf, 0, sizeof(*cbaf)); - kfree(cbaf); + kzfree(cbaf); } static struct usb_device_id cbaf_id_table[] = { -- GitLab From ef8b6bcb39559d956f897acf7ebe600d5105d479 Mon Sep 17 00:00:00 2001 From: Craig Shelley Date: Thu, 26 Feb 2009 22:19:22 +0000 Subject: [PATCH 4366/4982] USB: CP2101 Support AN205 baud rates This patch adds support for the extended range of baud rates supported by CP2102 and CP2103 devices described in SiLabs AN205. An additional function cp2101_quantise_baudrate rounds the baud rate as per AN205 Table 1. A modification to the baud rate calculation removes a rounding error, allowing the full range of baud rates to be used. Signed-off-by: Craig Shelley Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp2101.c | 92 +++++++++++++++++++++---------------- 1 file changed, 52 insertions(+), 40 deletions(-) diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 9b4082b58c5..9b56e35aee4 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -31,7 +31,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.07" +#define DRIVER_VERSION "v0.08" #define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver" /* @@ -301,6 +301,47 @@ static inline int cp2101_set_config_single(struct usb_serial_port *port, return cp2101_set_config(port, request, &data, 2); } +/* + * cp2101_quantise_baudrate + * Quantises the baud rate as per AN205 Table 1 + */ +static unsigned int cp2101_quantise_baudrate(unsigned int baud) { + if (baud <= 56) baud = 0; + else if (baud <= 300) baud = 300; + else if (baud <= 600) baud = 600; + else if (baud <= 1200) baud = 1200; + else if (baud <= 1800) baud = 1800; + else if (baud <= 2400) baud = 2400; + else if (baud <= 4000) baud = 4000; + else if (baud <= 4803) baud = 4800; + else if (baud <= 7207) baud = 7200; + else if (baud <= 9612) baud = 9600; + else if (baud <= 14428) baud = 14400; + else if (baud <= 16062) baud = 16000; + else if (baud <= 19250) baud = 19200; + else if (baud <= 28912) baud = 28800; + else if (baud <= 38601) baud = 38400; + else if (baud <= 51558) baud = 51200; + else if (baud <= 56280) baud = 56000; + else if (baud <= 58053) baud = 57600; + else if (baud <= 64111) baud = 64000; + else if (baud <= 77608) baud = 76800; + else if (baud <= 117028) baud = 115200; + else if (baud <= 129347) baud = 128000; + else if (baud <= 156868) baud = 153600; + else if (baud <= 237832) baud = 230400; + else if (baud <= 254234) baud = 250000; + else if (baud <= 273066) baud = 256000; + else if (baud <= 491520) baud = 460800; + else if (baud <= 567138) baud = 500000; + else if (baud <= 670254) baud = 576000; + else if (baud <= 1053257) baud = 921600; + else if (baud <= 1474560) baud = 1228800; + else if (baud <= 2457600) baud = 1843200; + else baud = 3686400; + return baud; +} + static int cp2101_open(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp) { @@ -388,7 +429,7 @@ static void cp2101_get_termios (struct tty_struct *tty) cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2); /* Convert to baudrate */ if (baud) - baud = BAUD_RATE_GEN_FREQ / baud; + baud = cp2101_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud); dbg("%s - baud rate = %d", __func__, baud); @@ -517,46 +558,17 @@ static void cp2101_set_termios(struct tty_struct *tty, tty->termios->c_cflag &= ~CMSPAR; cflag = tty->termios->c_cflag; old_cflag = old_termios->c_cflag; - baud = tty_get_baud_rate(tty); + baud = cp2101_quantise_baudrate(tty_get_baud_rate(tty)); /* If the baud rate is to be updated*/ - if (baud != tty_termios_baud_rate(old_termios)) { - switch (baud) { - case 0: - case 600: - case 1200: - case 1800: - case 2400: - case 4800: - case 7200: - case 9600: - case 14400: - case 19200: - case 28800: - case 38400: - case 55854: - case 57600: - case 115200: - case 127117: - case 230400: - case 460800: - case 921600: - case 3686400: - break; - default: - baud = 9600; - break; - } - - if (baud) { - dbg("%s - Setting baud rate to %d baud", __func__, - baud); - if (cp2101_set_config_single(port, CP2101_BAUDRATE, - (BAUD_RATE_GEN_FREQ / baud))) { - dev_err(&port->dev, "Baud rate requested not " - "supported by device\n"); - baud = tty_termios_baud_rate(old_termios); - } + if (baud != tty_termios_baud_rate(old_termios) && baud != 0) { + dbg("%s - Setting baud rate to %d baud", __func__, + baud); + if (cp2101_set_config_single(port, CP2101_BAUDRATE, + ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) { + dev_err(&port->dev, "Baud rate requested not " + "supported by device\n"); + baud = tty_termios_baud_rate(old_termios); } } /* Report back the resulting baud rate */ -- GitLab From 97324955c62aaa104edea2ef4370dc8882a5ab82 Mon Sep 17 00:00:00 2001 From: Craig Shelley Date: Thu, 26 Feb 2009 22:21:51 +0000 Subject: [PATCH 4367/4982] USB: CP2101 Reduce Error Logging This patch lowers the logging priority of certain messages to prevent users from flooding the log files. Signed-off-by: Craig Shelley Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp2101.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 9b56e35aee4..2f23d064362 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -11,10 +11,6 @@ * thanks to Karl Hiramoto karl@hiramoto.org. RTSCTS hardware flow * control thanks to Munir Nassar nassarmu@real-time.com * - * Outstanding Issues: - * Buffers are not flushed when the port is opened. - * Multiple calls to write() may fail with "Resource temporarily unavailable" - * */ #include @@ -225,7 +221,7 @@ static int cp2101_get_config(struct usb_serial_port *port, u8 request, kfree(buf); if (result != size) { - dev_err(&port->dev, "%s - Unable to send config request, " + dbg("%s - Unable to send config request, " "request=0x%x size=%d result=%d\n", __func__, request, size, result); return -EPROTO; @@ -276,7 +272,7 @@ static int cp2101_set_config(struct usb_serial_port *port, u8 request, kfree(buf); if ((size > 2 && result != size) || result < 0) { - dev_err(&port->dev, "%s - Unable to send request, " + dbg("%s - Unable to send request, " "request=0x%x size=%d result=%d\n", __func__, request, size, result); return -EPROTO; @@ -566,8 +562,7 @@ static void cp2101_set_termios(struct tty_struct *tty, baud); if (cp2101_set_config_single(port, CP2101_BAUDRATE, ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) { - dev_err(&port->dev, "Baud rate requested not " - "supported by device\n"); + dbg("Baud rate requested not supported by device\n"); baud = tty_termios_baud_rate(old_termios); } } @@ -600,14 +595,14 @@ static void cp2101_set_termios(struct tty_struct *tty, dbg("%s - data bits = 9", __func__); break;*/ default: - dev_err(&port->dev, "cp2101 driver does not " + dbg("cp2101 driver does not " "support the number of bits requested," " using 8 bit mode\n"); bits |= BITS_DATA_8; break; } if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) - dev_err(&port->dev, "Number of data bits requested " + dbg("Number of data bits requested " "not supported by device\n"); } @@ -624,7 +619,7 @@ static void cp2101_set_termios(struct tty_struct *tty, } } if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) - dev_err(&port->dev, "Parity mode not supported " + dbg("Parity mode not supported " "by device\n"); } @@ -639,7 +634,7 @@ static void cp2101_set_termios(struct tty_struct *tty, dbg("%s - stop bits = 1", __func__); } if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) - dev_err(&port->dev, "Number of stop bits requested " + dbg("Number of stop bits requested " "not supported by device\n"); } -- GitLab From 03ee251546a9360cbb4c27c250d128dcbcfd9931 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Mar 2009 11:03:49 -0700 Subject: [PATCH 4368/4982] USB: serial: rename cp2101 driver to cp210x Lots of users are getting confused about the cp2101 driver. It really does support more than just the cp2101 device, so rename it to cp210x to try to prevent confusion. Cc: Craig Shelley Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/Kconfig | 10 +++++----- drivers/usb/serial/Makefile | 2 +- drivers/usb/serial/{cp2101.c => cp210x.c} | 0 3 files changed, 6 insertions(+), 6 deletions(-) rename drivers/usb/serial/{cp2101.c => cp210x.c} (100%) diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 4afe73e8ec4..a65f9196b0a 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -116,14 +116,14 @@ config USB_SERIAL_DIGI_ACCELEPORT To compile this driver as a module, choose M here: the module will be called digi_acceleport. -config USB_SERIAL_CP2101 - tristate "USB CP2101 UART Bridge Controller" +config USB_SERIAL_CP210X + tristate "USB CP210x family of UART Bridge Controllers" help - Say Y here if you want to use a CP2101/CP2102 based USB to RS232 - converter. + Say Y here if you want to use a CP2101/CP2102/CP2103 based USB + to RS232 converters. To compile this driver as a module, choose M here: the - module will be called cp2101. + module will be called cp210x. config USB_SERIAL_CYPRESS_M8 tristate "USB Cypress M8 USB Serial Driver" diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 94043babe1d..66619beb6cc 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -15,7 +15,7 @@ obj-$(CONFIG_USB_SERIAL_AIRCABLE) += aircable.o obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o obj-$(CONFIG_USB_SERIAL_CH341) += ch341.o -obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.o +obj-$(CONFIG_USB_SERIAL_CP210X) += cp210x.o obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o obj-$(CONFIG_USB_SERIAL_CYPRESS_M8) += cypress_m8.o obj-$(CONFIG_USB_SERIAL_DEBUG) += usb_debug.o diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp210x.c similarity index 100% rename from drivers/usb/serial/cp2101.c rename to drivers/usb/serial/cp210x.c -- GitLab From 3edb8a208b5be90c829f7b19058cb63e947b1d18 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 26 Feb 2009 23:02:19 +0000 Subject: [PATCH 4369/4982] USB: ohci-s3c2410: remove include Remove the include of , as no definitions from it are used by the OHCI driver. Signed-off-by: Ben Dooks Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-s3c2410.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index f46af7a718d..0e62d2044f7 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -22,7 +22,6 @@ #include #include -#include #include #define valid_port(idx) ((idx) == 1 || (idx) == 2) -- GitLab From 2dfa319a649b9de029777994b6af201c1fe81d53 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 26 Feb 2009 23:03:15 +0000 Subject: [PATCH 4370/4982] USB: ohci-s3c2410: fix name of bus clock The USB bus clock is usb-bus-host, so print the correct name in the dev_err() statement if we cannot find it. Signed-off-by: Ben Dooks Acked-by: David Brownell --- drivers/usb/host/ohci-s3c2410.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index 0e62d2044f7..a7ddd5d14a5 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -371,7 +371,7 @@ static int usb_hcd_s3c2410_probe (const struct hc_driver *driver, usb_clk = clk_get(&dev->dev, "usb-bus-host"); if (IS_ERR(usb_clk)) { - dev_err(&dev->dev, "cannot get usb-host clock\n"); + dev_err(&dev->dev, "cannot get usb-bus-host clock\n"); retval = -ENOENT; goto err_clk; } -- GitLab From a9f8ec4db1d308643e13ec7638ccb5ace4d34982 Mon Sep 17 00:00:00 2001 From: Hannes Eder Date: Fri, 27 Feb 2009 02:04:31 +0100 Subject: [PATCH 4371/4982] USB: host: fix sparse warning: Using plain integer as NULL pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix this sparse warning:  drivers/usb/host/oxu210hp-hcd.c:2687:42: warning: Using plain integer as NULL pointer Signed-off-by: Hannes Eder Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/oxu210hp-hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index 2947c69b347..5ac489ee3da 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -2684,7 +2684,7 @@ static int oxu_reset(struct usb_hcd *hcd) oxu->urb_len = 0; /* FIMXE */ - hcd->self.controller->dma_mask = 0UL; + hcd->self.controller->dma_mask = NULL; if (oxu->is_otg) { oxu->caps = hcd->regs + OXU_OTG_CAP_OFFSET; -- GitLab From 64a3a25f440c65510cb0d15080dcd2f0032d6051 Mon Sep 17 00:00:00 2001 From: "D.J. Capelis" Date: Wed, 4 Mar 2009 10:27:52 -0800 Subject: [PATCH 4372/4982] USB: pedantic: spelling correction in comment for ch9.h Just noticed this during a grep, figured I might as well send it in. From: D.J. Capelis Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/ch9.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h index d9d54803dbc..b145119a90d 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -102,7 +102,7 @@ #define USB_REQ_LOOPBACK_DATA_READ 0x16 #define USB_REQ_SET_INTERFACE_DS 0x17 -/* The Link Power Mangement (LPM) ECN defines USB_REQ_TEST_AND_SET command, +/* The Link Power Management (LPM) ECN defines USB_REQ_TEST_AND_SET command, * used by hubs to put ports into a new L1 suspend state, except that it * forgot to define its number ... */ -- GitLab From 3ba5f38f3d5143a879de132a9df71814d1f3cff0 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Sat, 7 Mar 2009 11:44:10 +0000 Subject: [PATCH 4373/4982] USB: ohci-hcd: Add ARCH_S3C24XX to the ohci-s3c2410.c glue The ohci-s3c2410.c glue supports both CONFIG_ARCH_S3C2410 and CONFIG_ARCH_S3C64XX so add it to the build of ohci-s3c2410.c Signed-off-by: Ben Dooks Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 5cf5f1eca4f..d052955439c 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -997,7 +997,7 @@ MODULE_LICENSE ("GPL"); #define SA1111_DRIVER ohci_hcd_sa1111_driver #endif -#ifdef CONFIG_ARCH_S3C2410 +#if defined(CONFIG_ARCH_S3C2410) || defined(CONFIG_ARCH_S3C64XX) #include "ohci-s3c2410.c" #define PLATFORM_DRIVER ohci_hcd_s3c2410_driver #endif -- GitLab From 49121aa14c2a372a5fd01982df900257784be63d Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Sat, 7 Mar 2009 11:44:21 +0000 Subject: [PATCH 4374/4982] USB: S3C: Move usb-control.h to platform include The usb-control.h is needed by ohci-s3c2410.c for both S3C24XX and S3C64XX architectures, so move it to Signed-off-by: Ben Dooks Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-s3c2410/usb-simtec.c | 3 ++- .../include/mach => plat-s3c/include/plat}/usb-control.h | 6 +++--- drivers/usb/host/ohci-s3c2410.c | 3 +-- 3 files changed, 6 insertions(+), 6 deletions(-) rename arch/arm/{mach-s3c2410/include/mach => plat-s3c/include/plat}/usb-control.h (84%) diff --git a/arch/arm/mach-s3c2410/usb-simtec.c b/arch/arm/mach-s3c2410/usb-simtec.c index 6078f09b7df..8331e8d97e2 100644 --- a/arch/arm/mach-s3c2410/usb-simtec.c +++ b/arch/arm/mach-s3c2410/usb-simtec.c @@ -29,13 +29,14 @@ #include #include -#include #include #include #include +#include #include + #include "usb-simtec.h" /* control power and monitor over-current events on various Simtec diff --git a/arch/arm/mach-s3c2410/include/mach/usb-control.h b/arch/arm/plat-s3c/include/plat/usb-control.h similarity index 84% rename from arch/arm/mach-s3c2410/include/mach/usb-control.h rename to arch/arm/plat-s3c/include/plat/usb-control.h index cd91d1591f3..822c87fe948 100644 --- a/arch/arm/mach-s3c2410/include/mach/usb-control.h +++ b/arch/arm/plat-s3c/include/plat/usb-control.h @@ -1,9 +1,9 @@ -/* arch/arm/mach-s3c2410/include/mach/usb-control.h +/* arch/arm/plat-s3c/include/plat/usb-control.h * * Copyright (c) 2004 Simtec Electronics * Ben Dooks * - * S3C2410 - usb port information + * S3C - USB host port information * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -11,7 +11,7 @@ */ #ifndef __ASM_ARCH_USBCONTROL_H -#define __ASM_ARCH_USBCONTROL_H "arch/arm/mach-s3c2410/include/mach/usb-control.h" +#define __ASM_ARCH_USBCONTROL_H #define S3C_HCDFLG_USED (1) diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index a7ddd5d14a5..a68af2dd55c 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -21,8 +21,7 @@ #include #include - -#include +#include #define valid_port(idx) ((idx) == 1 || (idx) == 2) -- GitLab From 1b8fb4141eb52f4aace9f152dad3e4c1609b76fe Mon Sep 17 00:00:00 2001 From: Mark Ellis Date: Mon, 9 Mar 2009 22:24:29 +0000 Subject: [PATCH 4375/4982] USB: ipaq: handle 4 endpoint devices The ipaq driver currently enforces one port on all devices. This is correct for 2 and 3 endpoint devices, but with 4 endpoint devices meaningful communication occurs on the second pair. This patch allows 2 ports for 4 endpoint devices. Signed-off-by: Mark Ellis Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ipaq.c | 43 +++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 132be74d2b8..ef92095b073 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -78,6 +78,7 @@ static int ipaq_open(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp); static void ipaq_close(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp); +static int ipaq_calc_num_ports(struct usb_serial *serial); static int ipaq_startup(struct usb_serial *serial); static void ipaq_shutdown(struct usb_serial *serial); static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port, @@ -572,15 +573,10 @@ static struct usb_serial_driver ipaq_device = { .description = "PocketPC PDA", .usb_driver = &ipaq_driver, .id_table = ipaq_id_table, - /* - * some devices have an extra endpoint, which - * must be ignored as it would make the core - * create a second port which oopses when used - */ - .num_ports = 1, .open = ipaq_open, .close = ipaq_close, .attach = ipaq_startup, + .calc_num_ports = ipaq_calc_num_ports, .shutdown = ipaq_shutdown, .write = ipaq_write, .write_room = ipaq_write_room, @@ -956,14 +952,49 @@ static void ipaq_destroy_lists(struct usb_serial_port *port) } +static int ipaq_calc_num_ports(struct usb_serial *serial) +{ + /* + * some devices have 3 endpoints, the 3rd of which + * must be ignored as it would make the core + * create a second port which oopses when used + */ + int ipaq_num_ports = 1; + + dbg("%s - numberofendpoints: %d", __FUNCTION__, + (int)serial->interface->cur_altsetting->desc.bNumEndpoints); + + /* + * a few devices have 4 endpoints, seemingly Yakuma devices, + * and we need the second pair, so let them have 2 ports + * + * TODO: can we drop port 1 ? + */ + if (serial->interface->cur_altsetting->desc.bNumEndpoints > 3) { + ipaq_num_ports = 2; + } + + return ipaq_num_ports; +} + + static int ipaq_startup(struct usb_serial *serial) { dbg("%s", __func__); if (serial->dev->actconfig->desc.bConfigurationValue != 1) { + /* + * FIXME: HP iPaq rx3715, possibly others, have 1 config that + * is labeled as 2 + */ + dev_err(&serial->dev->dev, "active config #%d != 1 ??\n", serial->dev->actconfig->desc.bConfigurationValue); return -ENODEV; } + + dbg("%s - iPAQ module configured for %d ports", + __FUNCTION__, serial->num_ports); + return usb_reset_configuration(serial->dev); } -- GitLab From d23bac9f8b3cf1ad674d6390364d559103013213 Mon Sep 17 00:00:00 2001 From: Alex Stephens Date: Tue, 17 Mar 2009 00:06:19 +0000 Subject: [PATCH 4376/4982] USB: CP2101 New Device ID One new device ID for CP2101 driver. Signed-off-by: Alex Stephens alex@miranova.com --- drivers/usb/serial/cp210x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 2f23d064362..292f0163b92 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -87,6 +87,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */ { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ + { USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */ -- GitLab From d2ad67b3fa61eed52b22491210c668a94c7bf17e Mon Sep 17 00:00:00 2001 From: VomLehn Date: Thu, 12 Mar 2009 14:37:42 -0700 Subject: [PATCH 4377/4982] USB: Fix cp2101 USB serial device driver termios functions for console use This is really a follow up to the modifications Alan Cox made for commit 95da310e66ee8090119596c70ca8432e57f9a97f to pass a tty_struct to various interface functions, which broke the serial configuration (termios) functions when the device is being used as a console. These changes restore the configuration to proper functioning both as a tty and as a console. As Alan notes in that commit, these changes will need to be tweaked when we have a proper console abstraction. Signed-off-by: David VomLehn Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 53 ++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 292f0163b92..e8d5133ce9c 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -38,17 +38,21 @@ static int cp2101_open(struct tty_struct *, struct usb_serial_port *, static void cp2101_cleanup(struct usb_serial_port *); static void cp2101_close(struct tty_struct *, struct usb_serial_port *, struct file*); -static void cp2101_get_termios(struct tty_struct *); +static void cp2101_get_termios(struct tty_struct *, + struct usb_serial_port *port); +static void cp2101_get_termios_port(struct usb_serial_port *port, + unsigned int *cflagp, unsigned int *baudp); static void cp2101_set_termios(struct tty_struct *, struct usb_serial_port *, struct ktermios*); static int cp2101_tiocmget(struct tty_struct *, struct file *); static int cp2101_tiocmset(struct tty_struct *, struct file *, unsigned int, unsigned int); +static int cp2101_tiocmset_port(struct usb_serial_port *port, struct file *, + unsigned int, unsigned int); static void cp2101_break_ctl(struct tty_struct *, int); static int cp2101_startup(struct usb_serial *); static void cp2101_shutdown(struct usb_serial *); - static int debug; static struct usb_device_id id_table [] = { @@ -369,10 +373,12 @@ static int cp2101_open(struct tty_struct *tty, struct usb_serial_port *port, } /* Configure the termios structure */ - cp2101_get_termios(tty); + cp2101_get_termios(tty, port); /* Set the DTR and RTS pins low */ - cp2101_tiocmset(tty, NULL, TIOCM_DTR | TIOCM_RTS, 0); + cp2101_tiocmset_port(tty ? (struct usb_serial_port *) tty->driver_data + : port, + NULL, TIOCM_DTR | TIOCM_RTS, 0); return 0; } @@ -414,9 +420,31 @@ static void cp2101_close(struct tty_struct *tty, struct usb_serial_port *port, * from the device, corrects any unsupported values, and configures the * termios structure to reflect the state of the device */ -static void cp2101_get_termios (struct tty_struct *tty) +static void cp2101_get_termios(struct tty_struct *tty, + struct usb_serial_port *port) +{ + unsigned int baud; + + if (tty) { + cp2101_get_termios_port(tty->driver_data, + &tty->termios->c_cflag, &baud); + tty_encode_baud_rate(tty, baud, baud); + } + + else { + unsigned int cflag; + cflag = 0; + cp2101_get_termios_port(port, &cflag, &baud); + } +} + +/* + * cp2101_get_termios_port + * This is the heart of cp2101_get_termios which always uses a &usb_serial_port. + */ +static void cp2101_get_termios_port(struct usb_serial_port *port, + unsigned int *cflagp, unsigned int *baudp) { - struct usb_serial_port *port = tty->driver_data; unsigned int cflag, modem_ctl[4]; unsigned int baud; unsigned int bits; @@ -429,9 +457,9 @@ static void cp2101_get_termios (struct tty_struct *tty) baud = cp2101_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud); dbg("%s - baud rate = %d", __func__, baud); + *baudp = baud; - tty_encode_baud_rate(tty, baud, baud); - cflag = tty->termios->c_cflag; + cflag = *cflagp; cp2101_get_config(port, CP2101_BITS, &bits, 2); cflag &= ~CSIZE; @@ -537,7 +565,7 @@ static void cp2101_get_termios (struct tty_struct *tty) cflag &= ~CRTSCTS; } - tty->termios->c_cflag = cflag; + *cflagp = cflag; } static void cp2101_set_termios(struct tty_struct *tty, @@ -669,6 +697,12 @@ static int cp2101_tiocmset (struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; + return cp2101_tiocmset_port(port, file, set, clear); +} + +static int cp2101_tiocmset_port(struct usb_serial_port *port, struct file *file, + unsigned int set, unsigned int clear) +{ unsigned int control = 0; dbg("%s - port %d", __func__, port->number); @@ -693,7 +727,6 @@ static int cp2101_tiocmset (struct tty_struct *tty, struct file *file, dbg("%s - control = 0x%.4x", __func__, control); return cp2101_set_config(port, CP2101_CONTROL, &control, 2); - } static int cp2101_tiocmget (struct tty_struct *tty, struct file *file) -- GitLab From 71d2718f2507dc17501d04e2bdca7b8e694ce365 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Fri, 13 Mar 2009 12:19:18 +0100 Subject: [PATCH 4378/4982] USB: more u32 conversion after transfer_buffer_length and actual_length transfer_buffer_length and actual_length have become unsigned, therefore some additional conversion of local variables, function arguments and print specifications is desired. A test for a negative urb->transfer_buffer_length became obsolete; instead we ensure that it does not exceed INT_MAX. Also, urb->actual_length is always less than urb->transfer_buffer_length. rh_string() does no longer return -EPIPE in the case of an unsupported ID. Instead its only caller, rh_call_control() does the check. Signed-off-by: Roel Kluin Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 6 +++--- drivers/usb/core/hcd.c | 31 ++++++++++++------------------- drivers/usb/core/hub.c | 2 +- drivers/usb/core/message.c | 2 +- drivers/usb/core/urb.c | 2 +- 5 files changed, 18 insertions(+), 25 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index d3883f63960..df3c539f652 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -302,7 +302,7 @@ static struct async *async_getpending(struct dev_state *ps, static void snoop_urb(struct urb *urb, void __user *userurb) { - int j; + unsigned j; unsigned char *data = urb->transfer_buffer; if (!usbfs_snoop) @@ -311,9 +311,9 @@ static void snoop_urb(struct urb *urb, void __user *userurb) dev_info(&urb->dev->dev, "direction=%s\n", usb_urb_dir_in(urb) ? "IN" : "OUT"); dev_info(&urb->dev->dev, "userurb=%p\n", userurb); - dev_info(&urb->dev->dev, "transfer_buffer_length=%d\n", + dev_info(&urb->dev->dev, "transfer_buffer_length=%u\n", urb->transfer_buffer_length); - dev_info(&urb->dev->dev, "actual_length=%d\n", urb->actual_length); + dev_info(&urb->dev->dev, "actual_length=%u\n", urb->actual_length); dev_info(&urb->dev->dev, "data: "); for (j = 0; j < urb->transfer_buffer_length; ++j) printk("%02x ", data[j]); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 0eee32a65e2..81fa8506825 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -279,9 +279,9 @@ static const u8 hs_rh_config_descriptor [] = { * helper routine for returning string descriptors in UTF-16LE * input can actually be ISO-8859-1; ASCII is its 7-bit subset */ -static int ascii2utf (char *s, u8 *utf, int utfmax) +static unsigned ascii2utf(char *s, u8 *utf, int utfmax) { - int retval; + unsigned retval; for (retval = 0; *s && utfmax > 1; utfmax -= 2, retval += 2) { *utf++ = *s++; @@ -304,19 +304,15 @@ static int ascii2utf (char *s, u8 *utf, int utfmax) * Produces either a manufacturer, product or serial number string for the * virtual root hub device. */ -static int rh_string ( - int id, - struct usb_hcd *hcd, - u8 *data, - int len -) { +static unsigned rh_string(int id, struct usb_hcd *hcd, u8 *data, unsigned len) +{ char buf [100]; // language ids if (id == 0) { buf[0] = 4; buf[1] = 3; /* 4 bytes string data */ buf[2] = 0x09; buf[3] = 0x04; /* MSFT-speak for "en-us" */ - len = min (len, 4); + len = min_t(unsigned, len, 4); memcpy (data, buf, len); return len; @@ -332,10 +328,7 @@ static int rh_string ( } else if (id == 3) { snprintf (buf, sizeof buf, "%s %s %s", init_utsname()->sysname, init_utsname()->release, hcd->driver->description); - - // unsupported IDs --> "protocol stall" - } else - return -EPIPE; + } switch (len) { /* All cases fall through */ default: @@ -360,9 +353,8 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) u8 tbuf [sizeof (struct usb_hub_descriptor)] __attribute__((aligned(4))); const u8 *bufp = tbuf; - int len = 0; + unsigned len = 0; int status; - int n; u8 patch_wakeup = 0; u8 patch_protocol = 0; @@ -456,10 +448,11 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) patch_wakeup = 1; break; case USB_DT_STRING << 8: - n = rh_string (wValue & 0xff, hcd, ubuf, wLength); - if (n < 0) + if ((wValue & 0xff) < 4) + urb->actual_length = rh_string(wValue & 0xff, + hcd, ubuf, wLength); + else /* unsupported IDs --> "protocol stall" */ goto error; - urb->actual_length = n; break; default: goto error; @@ -629,7 +622,7 @@ static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb) { int retval; unsigned long flags; - int len = 1 + (urb->dev->maxchild / 8); + unsigned len = 1 + (urb->dev->maxchild / 8); spin_lock_irqsave (&hcd_root_hub_lock, flags); if (hcd->status_urb || urb->transfer_buffer_length < len) { diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 81eb3e6b659..be86ae3f408 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -392,7 +392,7 @@ static void hub_irq(struct urb *urb) { struct usb_hub *hub = urb->context; int status = urb->status; - int i; + unsigned i; unsigned long bits; switch (status) { diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 3922fa915ed..293a30d78d2 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -59,7 +59,7 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length) retval = (ctx.status == -ENOENT ? -ETIMEDOUT : ctx.status); dev_dbg(&urb->dev->dev, - "%s timed out on ep%d%s len=%d/%d\n", + "%s timed out on ep%d%s len=%u/%u\n", current->comm, usb_endpoint_num(&urb->ep->desc), usb_urb_dir_in(urb) ? "in" : "out", diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 7025d801f23..3376055f36e 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -370,7 +370,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) } /* the I/O buffer must be mapped/unmapped, except when length=0 */ - if (urb->transfer_buffer_length < 0) + if (urb->transfer_buffer_length > INT_MAX) return -EMSGSIZE; #ifdef DEBUG -- GitLab From e1e609be49c9d345e8b67a122a7cdae48ad27c7e Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Thu, 19 Mar 2009 14:18:15 +0900 Subject: [PATCH 4379/4982] USB: r8a66597-hcd: suspend/resume support Fix the problem that system cannot suspend. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/r8a66597-hcd.c | 101 +++++++++++++++++++++++++++++++- drivers/usb/host/r8a66597.h | 2 + 2 files changed, 102 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 713f4cf0b0d..f1626e58c14 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -1013,6 +1013,9 @@ static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port, r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port)); r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port)); + + if (r8a66597->bus_suspended) + usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597)); } /* this function must be called with interrupt disabled */ @@ -1614,6 +1617,11 @@ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd) r8a66597_bclr(r8a66597, DTCHE, INTENB2); r8a66597_usb_disconnect(r8a66597, 1); } + if (mask2 & BCHG) { + r8a66597_write(r8a66597, ~BCHG, INTSTS2); + r8a66597_bclr(r8a66597, BCHGE, INTENB2); + usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597)); + } } if (mask1) { @@ -1629,6 +1637,12 @@ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd) r8a66597_bclr(r8a66597, DTCHE, INTENB1); r8a66597_usb_disconnect(r8a66597, 0); } + if (mask1 & BCHG) { + r8a66597_write(r8a66597, ~BCHG, INTSTS1); + r8a66597_bclr(r8a66597, BCHGE, INTENB1); + usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597)); + } + if (mask1 & SIGN) { r8a66597_write(r8a66597, ~SIGN, INTSTS1); status = get_urb_error(r8a66597, 0); @@ -2140,7 +2154,7 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, switch (wValue) { case USB_PORT_FEAT_ENABLE: - rh->port &= (1 << USB_PORT_FEAT_POWER); + rh->port &= ~(1 << USB_PORT_FEAT_POWER); break; case USB_PORT_FEAT_SUSPEND: break; @@ -2212,6 +2226,68 @@ error: return ret; } +#if defined(CONFIG_PM) +static int r8a66597_bus_suspend(struct usb_hcd *hcd) +{ + struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); + int port; + + dbg("%s", __func__); + + for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) { + struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; + unsigned long dvstctr_reg = get_dvstctr_reg(port); + + if (!(rh->port & (1 << USB_PORT_FEAT_ENABLE))) + continue; + + dbg("suspend port = %d", port); + r8a66597_bclr(r8a66597, UACT, dvstctr_reg); /* suspend */ + rh->port |= 1 << USB_PORT_FEAT_SUSPEND; + + if (rh->dev->udev->do_remote_wakeup) { + msleep(3); /* waiting last SOF */ + r8a66597_bset(r8a66597, RWUPE, dvstctr_reg); + r8a66597_write(r8a66597, ~BCHG, get_intsts_reg(port)); + r8a66597_bset(r8a66597, BCHGE, get_intenb_reg(port)); + } + } + + r8a66597->bus_suspended = 1; + + return 0; +} + +static int r8a66597_bus_resume(struct usb_hcd *hcd) +{ + struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); + int port; + + dbg("%s", __func__); + + for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) { + struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; + unsigned long dvstctr_reg = get_dvstctr_reg(port); + + if (!(rh->port & (1 << USB_PORT_FEAT_SUSPEND))) + continue; + + dbg("resume port = %d", port); + rh->port &= ~(1 << USB_PORT_FEAT_SUSPEND); + rh->port |= 1 << USB_PORT_FEAT_C_SUSPEND; + r8a66597_mdfy(r8a66597, RESUME, RESUME | UACT, dvstctr_reg); + msleep(50); + r8a66597_mdfy(r8a66597, UACT, RESUME | UACT, dvstctr_reg); + } + + return 0; + +} +#else +#define r8a66597_bus_suspend NULL +#define r8a66597_bus_resume NULL +#endif + static struct hc_driver r8a66597_hc_driver = { .description = hcd_name, .hcd_priv_size = sizeof(struct r8a66597), @@ -2242,16 +2318,39 @@ static struct hc_driver r8a66597_hc_driver = { */ .hub_status_data = r8a66597_hub_status_data, .hub_control = r8a66597_hub_control, + .bus_suspend = r8a66597_bus_suspend, + .bus_resume = r8a66597_bus_resume, }; #if defined(CONFIG_PM) static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state) { + struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev); + int port; + + dbg("%s", __func__); + + disable_controller(r8a66597); + + for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) { + struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; + + rh->port = 0x00000000; + } + return 0; } static int r8a66597_resume(struct platform_device *pdev) { + struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev); + struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597); + + dbg("%s", __func__); + + enable_controller(r8a66597); + usb_root_hub_lost_power(hcd->self.root_hub); + return 0; } #else /* if defined(CONFIG_PM) */ diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h index ecacde4d69b..f49208f1bb7 100644 --- a/drivers/usb/host/r8a66597.h +++ b/drivers/usb/host/r8a66597.h @@ -504,6 +504,8 @@ struct r8a66597 { struct list_head child_device; unsigned long child_connect_map[4]; + + unsigned bus_suspended:1; }; static inline struct r8a66597 *hcd_to_r8a66597(struct usb_hcd *hcd) -- GitLab From 8942939a6c83f34615de5ae041cc9ca846923f94 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 19 Mar 2009 14:14:17 -0700 Subject: [PATCH 4380/4982] USB: gadget: composite device-level suspend/resume hooks Address one open question in the composite gadget framework: Yes, we should have device-level suspend/resume callbacks in addition to the function-level ones. We have at least one scenario (with gadget zero in OTG test mode) that's awkward to handle without it. Signed-off-by: David Brownell Cc: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/composite.c | 8 ++++++-- include/linux/usb/composite.h | 8 ++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 40f1da77a00..59e85234fa0 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1014,7 +1014,7 @@ composite_suspend(struct usb_gadget *gadget) struct usb_composite_dev *cdev = get_gadget_data(gadget); struct usb_function *f; - /* REVISIT: should we have config and device level + /* REVISIT: should we have config level * suspend/resume callbacks? */ DBG(cdev, "suspend\n"); @@ -1024,6 +1024,8 @@ composite_suspend(struct usb_gadget *gadget) f->suspend(f); } } + if (composite->suspend) + composite->suspend(cdev); } static void @@ -1032,10 +1034,12 @@ composite_resume(struct usb_gadget *gadget) struct usb_composite_dev *cdev = get_gadget_data(gadget); struct usb_function *f; - /* REVISIT: should we have config and device level + /* REVISIT: should we have config level * suspend/resume callbacks? */ DBG(cdev, "resume\n"); + if (composite->resume) + composite->resume(cdev); if (cdev->config) { list_for_each_entry(f, &cdev->config->functions, list) { if (f->resume) diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 935c380ffe4..acd7b0f06c8 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -244,6 +244,10 @@ int usb_add_config(struct usb_composite_dev *, * value; it should return zero on successful initialization. * @unbind: Reverses @bind(); called as a side effect of unregistering * this driver. + * @suspend: Notifies when the host stops sending USB traffic, + * after function notifications + * @resume: Notifies configuration when the host restarts USB traffic, + * before function notifications * * Devices default to reporting self powered operation. Devices which rely * on bus powered operation should report this in their @bind() method. @@ -268,6 +272,10 @@ struct usb_composite_driver { int (*bind)(struct usb_composite_dev *); int (*unbind)(struct usb_composite_dev *); + + /* global suspend hooks */ + void (*suspend)(struct usb_composite_dev *); + void (*resume)(struct usb_composite_dev *); }; extern int usb_composite_register(struct usb_composite_driver *); -- GitLab From ab943a2e125b098489ccaa0166c2c52f8266d9ed Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 19 Mar 2009 14:16:09 -0700 Subject: [PATCH 4381/4982] USB: gadget: gadget zero uses new suspend/resume hooks Use the new device-level suspend/resume hooks for Gadget Zero; always enable them with the OTG test mode; and support remote wakeup on both configurations even in non-OTG mode. This ensures that both configurations can pass the USBCV remote wakeup tests when the OTG test mode is enabled. This changes behavior by adding autoresume support to the loopback config even in non-OTG mode; the test failure was that it didn't work in OTG mode. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_loopback.c | 6 ++- drivers/usb/gadget/f_sourcesink.c | 52 +---------------------- drivers/usb/gadget/g_zero.h | 4 +- drivers/usb/gadget/zero.c | 70 +++++++++++++++++++++++++++++-- 4 files changed, 74 insertions(+), 58 deletions(-) diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c index 83301bdcdd1..eb6ddfc2085 100644 --- a/drivers/usb/gadget/f_loopback.c +++ b/drivers/usb/gadget/f_loopback.c @@ -359,7 +359,7 @@ static struct usb_configuration loopback_driver = { * loopback_add - add a loopback testing configuration to a device * @cdev: the device to support the loopback configuration */ -int __init loopback_add(struct usb_composite_dev *cdev) +int __init loopback_add(struct usb_composite_dev *cdev, bool autoresume) { int id; @@ -372,6 +372,10 @@ int __init loopback_add(struct usb_composite_dev *cdev) loopback_intf.iInterface = id; loopback_driver.iConfiguration = id; + /* support autoresume for remote wakeup testing */ + if (autoresume) + sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; + /* support OTG systems */ if (gadget_is_otg(cdev->gadget)) { loopback_driver.descriptors = otg_desc; diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c index 6aca5c81414..bffe91d525f 100644 --- a/drivers/usb/gadget/f_sourcesink.c +++ b/drivers/usb/gadget/f_sourcesink.c @@ -59,7 +59,6 @@ struct f_sourcesink { struct usb_ep *in_ep; struct usb_ep *out_ep; - struct timer_list resume; }; static inline struct f_sourcesink *func_to_ss(struct usb_function *f) @@ -67,10 +66,6 @@ static inline struct f_sourcesink *func_to_ss(struct usb_function *f) return container_of(f, struct f_sourcesink, function); } -static unsigned autoresume; -module_param(autoresume, uint, 0); -MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup"); - static unsigned pattern; module_param(pattern, uint, 0); MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63 "); @@ -155,21 +150,6 @@ static struct usb_gadget_strings *sourcesink_strings[] = { /*-------------------------------------------------------------------------*/ -static void sourcesink_autoresume(unsigned long _c) -{ - struct usb_composite_dev *cdev = (void *)_c; - struct usb_gadget *g = cdev->gadget; - - /* Normally the host would be woken up for something - * more significant than just a timer firing; likely - * because of some direct user request. - */ - if (g->speed != USB_SPEED_UNKNOWN) { - int status = usb_gadget_wakeup(g); - DBG(cdev, "%s --> %d\n", __func__, status); - } -} - static int __init sourcesink_bind(struct usb_configuration *c, struct usb_function *f) { @@ -198,9 +178,6 @@ autoconf_fail: goto autoconf_fail; ss->out_ep->driver_data = cdev; /* claim */ - setup_timer(&ss->resume, sourcesink_autoresume, - (unsigned long) c->cdev); - /* support high speed hardware */ if (gadget_is_dualspeed(c->cdev->gadget)) { hs_source_desc.bEndpointAddress = @@ -359,7 +336,6 @@ static void disable_source_sink(struct f_sourcesink *ss) cdev = ss->function.config->cdev; disable_endpoints(cdev, ss->in_ep, ss->out_ep); - del_timer(&ss->resume); VDBG(cdev, "%s disabled\n", ss->function.name); } @@ -426,30 +402,6 @@ static void sourcesink_disable(struct usb_function *f) disable_source_sink(ss); } -static void sourcesink_suspend(struct usb_function *f) -{ - struct f_sourcesink *ss = func_to_ss(f); - struct usb_composite_dev *cdev = f->config->cdev; - - if (cdev->gadget->speed == USB_SPEED_UNKNOWN) - return; - - if (autoresume) { - mod_timer(&ss->resume, jiffies + (HZ * autoresume)); - DBG(cdev, "suspend, wakeup in %d seconds\n", autoresume); - } else - DBG(cdev, "%s\n", __func__); -} - -static void sourcesink_resume(struct usb_function *f) -{ - struct f_sourcesink *ss = func_to_ss(f); - struct usb_composite_dev *cdev = f->config->cdev; - - DBG(cdev, "%s\n", __func__); - del_timer(&ss->resume); -} - /*-------------------------------------------------------------------------*/ static int __init sourcesink_bind_config(struct usb_configuration *c) @@ -467,8 +419,6 @@ static int __init sourcesink_bind_config(struct usb_configuration *c) ss->function.unbind = sourcesink_unbind; ss->function.set_alt = sourcesink_set_alt; ss->function.disable = sourcesink_disable; - ss->function.suspend = sourcesink_suspend; - ss->function.resume = sourcesink_resume; status = usb_add_function(c, &ss->function); if (status) @@ -559,7 +509,7 @@ static struct usb_configuration sourcesink_driver = { * sourcesink_add - add a source/sink testing configuration to a device * @cdev: the device to support the configuration */ -int __init sourcesink_add(struct usb_composite_dev *cdev) +int __init sourcesink_add(struct usb_composite_dev *cdev, bool autoresume) { int id; diff --git a/drivers/usb/gadget/g_zero.h b/drivers/usb/gadget/g_zero.h index dd2f16ad5a8..e84b3c47ed3 100644 --- a/drivers/usb/gadget/g_zero.h +++ b/drivers/usb/gadget/g_zero.h @@ -19,7 +19,7 @@ void disable_endpoints(struct usb_composite_dev *cdev, struct usb_ep *in, struct usb_ep *out); /* configuration-specific linkup */ -int sourcesink_add(struct usb_composite_dev *cdev); -int loopback_add(struct usb_composite_dev *cdev); +int sourcesink_add(struct usb_composite_dev *cdev, bool autoresume); +int loopback_add(struct usb_composite_dev *cdev, bool autoresume); #endif /* __G_ZERO_H */ diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 20614dce8db..2d772401b7a 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -102,11 +102,21 @@ module_param(loopdefault, bool, S_IRUGO|S_IWUSR); #ifndef CONFIG_USB_ZERO_HNPTEST #define DRIVER_VENDOR_NUM 0x0525 /* NetChip */ #define DRIVER_PRODUCT_NUM 0xa4a0 /* Linux-USB "Gadget Zero" */ +#define DEFAULT_AUTORESUME 0 #else #define DRIVER_VENDOR_NUM 0x1a0a /* OTG test device IDs */ #define DRIVER_PRODUCT_NUM 0xbadd +#define DEFAULT_AUTORESUME 5 #endif +/* If the optional "autoresume" mode is enabled, it provides good + * functional coverage for the "USBCV" test harness from USB-IF. + * It's always set if OTG mode is enabled. + */ +unsigned autoresume = DEFAULT_AUTORESUME; +module_param(autoresume, uint, S_IRUGO); +MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup"); + /*-------------------------------------------------------------------------*/ static struct usb_device_descriptor device_desc = { @@ -212,6 +222,47 @@ void disable_endpoints(struct usb_composite_dev *cdev, /*-------------------------------------------------------------------------*/ +static struct timer_list autoresume_timer; + +static void zero_autoresume(unsigned long _c) +{ + struct usb_composite_dev *cdev = (void *)_c; + struct usb_gadget *g = cdev->gadget; + + /* unconfigured devices can't issue wakeups */ + if (!cdev->config) + return; + + /* Normally the host would be woken up for something + * more significant than just a timer firing; likely + * because of some direct user request. + */ + if (g->speed != USB_SPEED_UNKNOWN) { + int status = usb_gadget_wakeup(g); + INFO(cdev, "%s --> %d\n", __func__, status); + } +} + +static void zero_suspend(struct usb_composite_dev *cdev) +{ + if (cdev->gadget->speed == USB_SPEED_UNKNOWN) + return; + + if (autoresume) { + mod_timer(&autoresume_timer, jiffies + (HZ * autoresume)); + DBG(cdev, "suspend, wakeup in %d seconds\n", autoresume); + } else + DBG(cdev, "%s\n", __func__); +} + +static void zero_resume(struct usb_composite_dev *cdev) +{ + DBG(cdev, "%s\n", __func__); + del_timer(&autoresume_timer); +} + +/*-------------------------------------------------------------------------*/ + static int __init zero_bind(struct usb_composite_dev *cdev) { int gcnum; @@ -239,17 +290,19 @@ static int __init zero_bind(struct usb_composite_dev *cdev) strings_dev[STRING_SERIAL_IDX].id = id; device_desc.iSerialNumber = id; + setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev); + /* Register primary, then secondary configuration. Note that * SH3 only allows one config... */ if (loopdefault) { - loopback_add(cdev); + loopback_add(cdev, autoresume != 0); if (!gadget_is_sh(gadget)) - sourcesink_add(cdev); + sourcesink_add(cdev, autoresume != 0); } else { - sourcesink_add(cdev); + sourcesink_add(cdev, autoresume != 0); if (!gadget_is_sh(gadget)) - loopback_add(cdev); + loopback_add(cdev, autoresume != 0); } gcnum = usb_gadget_controller_number(gadget); @@ -278,11 +331,20 @@ static int __init zero_bind(struct usb_composite_dev *cdev) return 0; } +static int zero_unbind(struct usb_composite_dev *cdev) +{ + del_timer_sync(&autoresume_timer); + return 0; +} + static struct usb_composite_driver zero_driver = { .name = "zero", .dev = &device_desc, .strings = dev_strings, .bind = zero_bind, + .unbind = zero_unbind, + .suspend = zero_suspend, + .resume = zero_resume, }; MODULE_AUTHOR("David Brownell"); -- GitLab From 4c24b6d045a9d355c95ca4e6beb10ce2fd263390 Mon Sep 17 00:00:00 2001 From: Vernon Sauder Date: Fri, 20 Mar 2009 01:44:50 -0700 Subject: [PATCH 4382/4982] USB: pxa27x_udc: typo fixes and code cleanups This patch is a merge of patches : - fix function doc and debug - cleanup loop count - optimize code to remove local variable and extra check - init 'req' before use - add missing iounmap call [dbrownell@users.sourceforge.net: capitalize IN/OUT directions in doc] Signed-off-by: Vernon Sauder [folded by Robert Jarzmik Signed-off-by: Robert Jarzmik Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/pxa27x_udc.c | 54 +++++++++++++++------------------ 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 91ba1e93947..8cc676ecbb2 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -748,13 +748,13 @@ static void req_done(struct pxa_ep *ep, struct pxa27x_request *req, int status) } /** - * ep_end_out_req - Ends control endpoint in request + * ep_end_out_req - Ends endpoint OUT request * @ep: physical endpoint * @req: pxa request * * Context: ep->lock held * - * Ends endpoint in request (completes usb request). + * Ends endpoint OUT request (completes usb request). */ static void ep_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req) { @@ -763,13 +763,13 @@ static void ep_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req) } /** - * ep0_end_out_req - Ends control endpoint in request (ends data stage) + * ep0_end_out_req - Ends control endpoint OUT request (ends data stage) * @ep: physical endpoint * @req: pxa request * * Context: ep->lock held * - * Ends control endpoint in request (completes usb request), and puts + * Ends control endpoint OUT request (completes usb request), and puts * control endpoint into idle state */ static void ep0_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req) @@ -780,13 +780,13 @@ static void ep0_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req) } /** - * ep_end_in_req - Ends endpoint out request + * ep_end_in_req - Ends endpoint IN request * @ep: physical endpoint * @req: pxa request * * Context: ep->lock held * - * Ends endpoint out request (completes usb request). + * Ends endpoint IN request (completes usb request). */ static void ep_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req) { @@ -795,20 +795,18 @@ static void ep_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req) } /** - * ep0_end_in_req - Ends control endpoint out request (ends data stage) + * ep0_end_in_req - Ends control endpoint IN request (ends data stage) * @ep: physical endpoint * @req: pxa request * * Context: ep->lock held * - * Ends control endpoint out request (completes usb request), and puts + * Ends control endpoint IN request (completes usb request), and puts * control endpoint into status state */ static void ep0_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req) { - struct pxa_udc *udc = ep->dev; - - set_ep0state(udc, IN_STATUS_STAGE); + set_ep0state(ep->dev, IN_STATUS_STAGE); ep_end_in_req(ep, req); } @@ -1168,7 +1166,7 @@ static int pxa_ep_queue(struct usb_ep *_ep, struct usb_request *_req, ep_end_in_req(ep, req); } else { ep_err(ep, "got a request of %d bytes while" - "in state WATI_ACK_SET_CONF_INTERF\n", + "in state WAIT_ACK_SET_CONF_INTERF\n", length); ep_del_request(ep, req); rc = -EL2HLT; @@ -1214,30 +1212,26 @@ static int pxa_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) struct udc_usb_ep *udc_usb_ep; struct pxa27x_request *req; unsigned long flags; - int rc; + int rc = -EINVAL; if (!_ep) - return -EINVAL; + return rc; udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep); ep = udc_usb_ep->pxa_ep; if (!ep || is_ep0(ep)) - return -EINVAL; + return rc; spin_lock_irqsave(&ep->lock, flags); /* make sure it's actually queued on this endpoint */ list_for_each_entry(req, &ep->queue, queue) { - if (&req->req == _req) + if (&req->req == _req) { + req_done(ep, req, -ECONNRESET); + rc = 0; break; + } } - rc = -EINVAL; - if (&req->req != _req) - goto out; - - rc = 0; - req_done(ep, req, -ECONNRESET); -out: spin_unlock_irqrestore(&ep->lock, flags); return rc; } @@ -1706,10 +1700,9 @@ static __init void udc_init_data(struct pxa_udc *dev) } /* USB endpoints init */ - for (i = 0; i < NR_USB_ENDPOINTS; i++) - if (i != 0) - list_add_tail(&dev->udc_usb_ep[i].usb_ep.ep_list, - &dev->gadget.ep_list); + for (i = 1; i < NR_USB_ENDPOINTS; i++) + list_add_tail(&dev->udc_usb_ep[i].usb_ep.ep_list, + &dev->gadget.ep_list); } /** @@ -1994,14 +1987,14 @@ static void handle_ep0(struct pxa_udc *udc, int fifo_irq, int opc_irq) struct pxa27x_request *req = NULL; int completed = 0; + if (!list_empty(&ep->queue)) + req = list_entry(ep->queue.next, struct pxa27x_request, queue); + udccsr0 = udc_ep_readl(ep, UDCCSR); ep_dbg(ep, "state=%s, req=%p, udccsr0=0x%03x, udcbcr=%d, irq_msk=%x\n", EP0_STNAME(udc), req, udccsr0, udc_ep_readl(ep, UDCBCR), (fifo_irq << 1 | opc_irq)); - if (!list_empty(&ep->queue)) - req = list_entry(ep->queue.next, struct pxa27x_request, queue); - if (udccsr0 & UDCCSR0_SST) { ep_dbg(ep, "clearing stall status\n"); nuke(ep, -EPIPE); @@ -2473,6 +2466,7 @@ static int __exit pxa_udc_remove(struct platform_device *_dev) platform_set_drvdata(_dev, NULL); the_controller = NULL; clk_put(udc->clk); + iounmap(udc->regs); return 0; } -- GitLab From b7af0bb26899bb47ae16fb41d2296111b0784a56 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 20 Mar 2009 19:58:57 +0100 Subject: [PATCH 4383/4982] USB: allow malformed LANGID descriptors When an USB hardware does not provide a valid LANGID, fall back to value zero which is still a reasonable default for most devices. Signed-off-by: Daniel Mack Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 293a30d78d2..30a0690f368 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -804,18 +804,16 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) dev_err(&dev->dev, "string descriptor 0 read error: %d\n", err); - goto errout; } else if (err < 4) { dev_err(&dev->dev, "string descriptor 0 too short\n"); - err = -EINVAL; - goto errout; } else { - dev->have_langid = 1; dev->string_langid = tbuf[2] | (tbuf[3] << 8); /* always use the first langid listed */ dev_dbg(&dev->dev, "default language 0x%04x\n", dev->string_langid); } + + dev->have_langid = 1; } err = usb_string_sub(dev, dev->string_langid, index, tbuf); -- GitLab From e6bdfe36e52f0e552b50acf49a82851eeb122fde Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Mon, 23 Mar 2009 12:38:16 +0000 Subject: [PATCH 4384/4982] USB: isp1760: Add a delay before reading the SKIPMAP registers in isp1760-hcd.c The data read from the SKIPMAP registers is not immediately available after writing and the driver panics when a packet is enqueued from the interrupt handler. This patch adds an ndelay(195) before these registers are read (delay value mentioned in section 15.1.1.3 of the ISP1760 data sheet). Signed-off-by: Catalin Marinas Acked-by: Sebastian Andrzej Siewior Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1760-hcd.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 3172c0fd2a6..cd07ea3f0c6 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -819,6 +819,13 @@ static void enqueue_an_ATL_packet(struct usb_hcd *hcd, struct isp1760_qh *qh, u32 atl_regs, payload; u32 buffstatus; + /* + * When this function is called from the interrupt handler to enqueue + * a follow-up packet, the SKIP register gets written and read back + * almost immediately. With ISP1761, this register requires a delay of + * 195ns between a write and subsequent read (see section 15.1.1.3). + */ + ndelay(195); skip_map = isp1760_readl(hcd->regs + HC_ATL_PTD_SKIPMAP_REG); BUG_ON(!skip_map); @@ -853,6 +860,13 @@ static void enqueue_an_INT_packet(struct usb_hcd *hcd, struct isp1760_qh *qh, u32 int_regs, payload; u32 buffstatus; + /* + * When this function is called from the interrupt handler to enqueue + * a follow-up packet, the SKIP register gets written and read back + * almost immediately. With ISP1761, this register requires a delay of + * 195ns between a write and subsequent read (see section 15.1.1.3). + */ + ndelay(195); skip_map = isp1760_readl(hcd->regs + HC_INT_PTD_SKIPMAP_REG); BUG_ON(!skip_map); -- GitLab From fd8345f8dea93691b0ceba55146088d8c05415f6 Mon Sep 17 00:00:00 2001 From: Alexander Shumakovitch Date: Sat, 21 Mar 2009 00:50:16 -0400 Subject: [PATCH 4385/4982] USB: qcserial: add device id for HP devices Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/qcserial.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 6c6add50fea..e6d6b0c17fd 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -24,6 +24,8 @@ static int debug; static struct usb_device_id id_table[] = { {USB_DEVICE(0x05c6, 0x9211)}, /* Acer Gobi QDL device */ {USB_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ + {USB_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ + {USB_DEVICE(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, id_table); -- GitLab From a9dbae78506b2099985c4ca9975f079c94cb8165 Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Fri, 20 Mar 2009 21:09:14 +0100 Subject: [PATCH 4386/4982] ucc_geth: Convert to net_device_ops Signed-off-by: David S. Miller --- drivers/net/ucc_geth.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 0b675127e83..a110326dce6 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -3501,6 +3501,20 @@ static phy_interface_t to_phy_interface(const char *phy_connection_type) return PHY_INTERFACE_MODE_MII; } +static const struct net_device_ops ucc_geth_netdev_ops = { + .ndo_open = ucc_geth_open, + .ndo_stop = ucc_geth_close, + .ndo_start_xmit = ucc_geth_start_xmit, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_multicast_list = ucc_geth_set_multi, + .ndo_tx_timeout = ucc_geth_timeout, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = ucc_netpoll, +#endif +}; + static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *match) { struct device *device = &ofdev->dev; @@ -3716,19 +3730,11 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma /* Fill in the dev structure */ uec_set_ethtool_ops(dev); - dev->open = ucc_geth_open; - dev->hard_start_xmit = ucc_geth_start_xmit; - dev->tx_timeout = ucc_geth_timeout; + dev->netdev_ops = &ucc_geth_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; INIT_WORK(&ugeth->timeout_work, ucc_geth_timeout_work); netif_napi_add(dev, &ugeth->napi, ucc_geth_poll, UCC_GETH_DEV_WEIGHT); -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = ucc_netpoll; -#endif - dev->stop = ucc_geth_close; -// dev->change_mtu = ucc_geth_change_mtu; dev->mtu = 1500; - dev->set_multicast_list = ucc_geth_set_multi; ugeth->msg_enable = netif_msg_init(debug.msg_enable, UGETH_MSG_DEFAULT); ugeth->phy_interface = phy_interface; -- GitLab From de7927457a2e12d89f37b744fb258d2ae68cdb56 Mon Sep 17 00:00:00 2001 From: vibi sreenivasan Date: Tue, 24 Mar 2009 16:30:20 -0700 Subject: [PATCH 4387/4982] macb: fix warning "warning: unused variable `dev' " Removed unused variable dev Signed-off-by: vibi sreenivasan Signed-off-by: Haavard Skinnemoen Signed-off-by: David S. Miller --- drivers/net/macb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 872c1bdf42b..f50501013b1 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -513,7 +513,6 @@ static int macb_rx(struct macb *bp, int budget) static int macb_poll(struct napi_struct *napi, int budget) { struct macb *bp = container_of(napi, struct macb, napi); - struct net_device *dev = bp->dev; int work_done; u32 status; -- GitLab From 7f649269c318c41030e492fc35f03d38c6e3b39b Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Tue, 24 Mar 2009 16:32:13 -0700 Subject: [PATCH 4388/4982] myri10ge: update firmware headers to 1.4.41 Update myri10ge firmware headers to firmware version 1.4.41. Signed-off-by: Brice Goglin Signed-off-by: David S. Miller --- drivers/net/myri10ge/myri10ge_mcp_gen_header.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/myri10ge/myri10ge_mcp_gen_header.h b/drivers/net/myri10ge/myri10ge_mcp_gen_header.h index caa6cbbb631..62a1cbab603 100644 --- a/drivers/net/myri10ge/myri10ge_mcp_gen_header.h +++ b/drivers/net/myri10ge/myri10ge_mcp_gen_header.h @@ -9,6 +9,7 @@ #define MCP_TYPE_ETH 0x45544820 /* "ETH " */ #define MCP_TYPE_MCP0 0x4d435030 /* "MCP0" */ #define MCP_TYPE_DFLT 0x20202020 /* " " */ +#define MCP_TYPE_ETHZ 0x4554485a /* "ETHZ" */ struct mcp_gen_header { /* the first 4 fields are filled at compile time */ @@ -43,7 +44,15 @@ struct mcp_gen_header { unsigned msix_table_addr; /* start address of msix table in firmware */ unsigned bss_addr; /* start of bss */ unsigned features; + unsigned ee_hdr_addr; /* 8 */ }; +struct zmcp_info { + unsigned info_len; + unsigned zmcp_addr; + unsigned zmcp_len; + unsigned mcp_edata; +}; + #endif /* __MYRI10GE_MCP_GEN_HEADER_H__ */ -- GitLab From 38938bfe3489394e2eed5e40c9bb8f66a2ce1405 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 24 Mar 2009 16:37:55 -0700 Subject: [PATCH 4389/4982] netlink: add NETLINK_NO_ENOBUFS socket flag This patch adds the NETLINK_NO_ENOBUFS socket flag. This flag can be used by unicast and broadcast listeners to avoid receiving ENOBUFS errors. Generally speaking, ENOBUFS errors are useful to notify two things to the listener: a) You may increase the receiver buffer size via setsockopt(). b) You have lost messages, you may be out of sync. In some cases, ignoring ENOBUFS errors can be useful. For example: a) nfnetlink_queue: this subsystem does not have any sort of resync method and you can decide to ignore ENOBUFS once you have set a given buffer size. b) ctnetlink: you can use this together with the socket flag NETLINK_BROADCAST_SEND_ERROR to stop getting ENOBUFS errors as you do not need to resync (packets whose event are not delivered are drop to provide reliable logging and state-synchronization). Moreover, the use of NETLINK_NO_ENOBUFS also reduces a "go up, go down" effect in terms of performance which is due to the netlink congestion control when the listener cannot back off. The effect is the following: 1) throughput rate goes up and netlink messages are inserted in the receiver buffer. 2) Then, netlink buffer fills and overruns (set on nlk->state bit 0). 3) While the listener empties the receiver buffer, netlink keeps dropping messages. Thus, throughput goes dramatically down. 4) Then, once the listener has emptied the buffer (nlk->state bit 0 is set off), goto step 1. This effect is easy to trigger with netlink broadcast under heavy load, and it is more noticeable when using a big receiver buffer. You can find some results in [1] that show this problem. [1] http://1984.lsi.us.es/linux/netlink/ This patch also includes the use of sk_drop to account the number of netlink messages drop due to overrun. This value is shown in /proc/net/netlink. Signed-off-by: Pablo Neira Ayuso Signed-off-by: David S. Miller --- include/linux/netlink.h | 1 + net/netlink/af_netlink.c | 38 ++++++++++++++++++++++++++++++++------ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 1e6bf995435..5ba398e9030 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -104,6 +104,7 @@ struct nlmsgerr #define NETLINK_DROP_MEMBERSHIP 2 #define NETLINK_PKTINFO 3 #define NETLINK_BROADCAST_ERROR 4 +#define NETLINK_NO_ENOBUFS 5 struct nl_pktinfo { diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index b73d4e61c5a..8b6bbb3032b 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -86,6 +86,7 @@ struct netlink_sock { #define NETLINK_KERNEL_SOCKET 0x1 #define NETLINK_RECV_PKTINFO 0x2 #define NETLINK_BROADCAST_SEND_ERROR 0x4 +#define NETLINK_RECV_NO_ENOBUFS 0x8 static inline struct netlink_sock *nlk_sk(struct sock *sk) { @@ -717,10 +718,15 @@ static int netlink_getname(struct socket *sock, struct sockaddr *addr, static void netlink_overrun(struct sock *sk) { - if (!test_and_set_bit(0, &nlk_sk(sk)->state)) { - sk->sk_err = ENOBUFS; - sk->sk_error_report(sk); + struct netlink_sock *nlk = nlk_sk(sk); + + if (!(nlk->flags & NETLINK_RECV_NO_ENOBUFS)) { + if (!test_and_set_bit(0, &nlk_sk(sk)->state)) { + sk->sk_err = ENOBUFS; + sk->sk_error_report(sk); + } } + atomic_inc(&sk->sk_drops); } static struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid) @@ -1182,6 +1188,15 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname, nlk->flags &= ~NETLINK_BROADCAST_SEND_ERROR; err = 0; break; + case NETLINK_NO_ENOBUFS: + if (val) { + nlk->flags |= NETLINK_RECV_NO_ENOBUFS; + clear_bit(0, &nlk->state); + wake_up_interruptible(&nlk->wait); + } else + nlk->flags &= ~NETLINK_RECV_NO_ENOBUFS; + err = 0; + break; default: err = -ENOPROTOOPT; } @@ -1224,6 +1239,16 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname, return -EFAULT; err = 0; break; + case NETLINK_NO_ENOBUFS: + if (len < sizeof(int)) + return -EINVAL; + len = sizeof(int); + val = nlk->flags & NETLINK_RECV_NO_ENOBUFS ? 1 : 0; + if (put_user(len, optlen) || + put_user(val, optval)) + return -EFAULT; + err = 0; + break; default: err = -ENOPROTOOPT; } @@ -1879,12 +1904,12 @@ static int netlink_seq_show(struct seq_file *seq, void *v) if (v == SEQ_START_TOKEN) seq_puts(seq, "sk Eth Pid Groups " - "Rmem Wmem Dump Locks\n"); + "Rmem Wmem Dump Locks Drops\n"); else { struct sock *s = v; struct netlink_sock *nlk = nlk_sk(s); - seq_printf(seq, "%p %-3d %-6d %08x %-8d %-8d %p %d\n", + seq_printf(seq, "%p %-3d %-6d %08x %-8d %-8d %p %-8d %-8d\n", s, s->sk_protocol, nlk->pid, @@ -1892,7 +1917,8 @@ static int netlink_seq_show(struct seq_file *seq, void *v) atomic_read(&s->sk_rmem_alloc), atomic_read(&s->sk_wmem_alloc), nlk->cb, - atomic_read(&s->sk_refcnt) + atomic_read(&s->sk_refcnt), + atomic_read(&s->sk_drops) ); } -- GitLab From 031d5518591006efd13a33a86909b9477b22917b Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:21 -0700 Subject: [PATCH 4390/4982] edac: struct device - replace bus_id with dev_name(), dev_set_name() Cc: dougthompson@xmission.com Cc: bluesmoke-devel@lists.sourceforge.net Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/edac/cell_edac.c | 2 +- drivers/edac/mpc85xx_edac.c | 2 +- drivers/edac/mv64x60_edac.c | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c index 24f3ca85152..cb0f639f049 100644 --- a/drivers/edac/cell_edac.c +++ b/drivers/edac/cell_edac.c @@ -198,7 +198,7 @@ static int __devinit cell_edac_probe(struct platform_device *pdev) mci->edac_cap = EDAC_FLAG_EC | EDAC_FLAG_SECDED; mci->mod_name = "cell_edac"; mci->ctl_name = "MIC"; - mci->dev_name = pdev->dev.bus_id; + mci->dev_name = dev_name(&pdev->dev); mci->edac_check = cell_edac_check; cell_edac_init_csrows(mci); diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 853ef37ec00..4637a4a757d 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -218,7 +218,7 @@ static int __devinit mpc85xx_pci_err_probe(struct of_device *op, pci->dev = &op->dev; pci->mod_name = EDAC_MOD_STR; pci->ctl_name = pdata->name; - pci->dev_name = op->dev.bus_id; + pci->dev_name = dev_name(&op->dev); if (edac_op_state == EDAC_OPSTATE_POLL) pci->edac_check = mpc85xx_pci_check; diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c index 083ce8d0c63..5131aaae8e0 100644 --- a/drivers/edac/mv64x60_edac.c +++ b/drivers/edac/mv64x60_edac.c @@ -121,7 +121,7 @@ static int __devinit mv64x60_pci_err_probe(struct platform_device *pdev) pdata->irq = NO_IRQ; platform_set_drvdata(pdev, pci); pci->dev = &pdev->dev; - pci->dev_name = pdev->dev.bus_id; + pci->dev_name = dev_name(&pdev->dev); pci->mod_name = EDAC_MOD_STR; pci->ctl_name = pdata->name; @@ -294,7 +294,7 @@ static int __devinit mv64x60_sram_err_probe(struct platform_device *pdev) pdata->irq = NO_IRQ; edac_dev->dev = &pdev->dev; platform_set_drvdata(pdev, edac_dev); - edac_dev->dev_name = pdev->dev.bus_id; + edac_dev->dev_name = dev_name(&pdev->dev); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) { @@ -462,7 +462,7 @@ static int __devinit mv64x60_cpu_err_probe(struct platform_device *pdev) pdata->irq = NO_IRQ; edac_dev->dev = &pdev->dev; platform_set_drvdata(pdev, edac_dev); - edac_dev->dev_name = pdev->dev.bus_id; + edac_dev->dev_name = dev_name(&pdev->dev); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) { @@ -713,7 +713,7 @@ static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev) platform_set_drvdata(pdev, mci); pdata->name = "mv64x60_mc_err"; pdata->irq = NO_IRQ; - mci->dev_name = pdev->dev.bus_id; + mci->dev_name = dev_name(&pdev->dev); pdata->edac_idx = edac_mc_idx++; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- GitLab From 6c7377ab6814c247d7600955a4ead2e3db490697 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:21 -0700 Subject: [PATCH 4391/4982] spi: struct device - replace bus_id with dev_name(), dev_set_name() Cc: dbrownell@users.sourceforge.net Cc: spi-devel-general@lists.sourceforge.net Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/spi/atmel_spi.c | 8 ++++---- drivers/spi/mpc52xx_psc_spi.c | 2 +- drivers/spi/omap2_mcspi.c | 2 +- drivers/spi/omap_uwire.c | 12 ++++++------ drivers/spi/orion_spi.c | 2 +- drivers/spi/pxa2xx_spi.c | 4 ++-- drivers/spi/spi_bfin5xx.c | 4 ++-- drivers/spi/spi_gpio.c | 2 +- drivers/spi/spi_imx.c | 5 +++-- drivers/spi/spi_mpc83xx.c | 4 ++-- drivers/spi/spi_txx9.c | 3 ++- 11 files changed, 25 insertions(+), 23 deletions(-) diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index 56ff3e6864e..12e443cc4ac 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c @@ -322,7 +322,7 @@ static void atmel_spi_next_message(struct spi_master *master) spi = msg->spi; dev_dbg(master->dev.parent, "start message %p for %s\n", - msg, spi->dev.bus_id); + msg, dev_name(&spi->dev)); /* select chip if it's not still active */ if (as->stay) { @@ -627,7 +627,7 @@ static int atmel_spi_setup(struct spi_device *spi) if (!asd) return -ENOMEM; - ret = gpio_request(npcs_pin, spi->dev.bus_id); + ret = gpio_request(npcs_pin, dev_name(&spi->dev)); if (ret) { kfree(asd); return ret; @@ -668,7 +668,7 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg) as = spi_master_get_devdata(spi->master); dev_dbg(controller, "new message %p submitted for %s\n", - msg, spi->dev.bus_id); + msg, dev_name(&spi->dev)); if (unlikely(list_empty(&msg->transfers))) return -EINVAL; @@ -803,7 +803,7 @@ static int __init atmel_spi_probe(struct platform_device *pdev) as->clk = clk; ret = request_irq(irq, atmel_spi_interrupt, 0, - pdev->dev.bus_id, master); + dev_name(&pdev->dev), master); if (ret) goto out_unmap_regs; diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c index 3b97803e1d1..68c77a91159 100644 --- a/drivers/spi/mpc52xx_psc_spi.c +++ b/drivers/spi/mpc52xx_psc_spi.c @@ -429,7 +429,7 @@ static int __init mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr, INIT_LIST_HEAD(&mps->queue); mps->workqueue = create_singlethread_workqueue( - master->dev.parent->bus_id); + dev_name(master->dev.parent)); if (mps->workqueue == NULL) { ret = -EBUSY; goto free_irq; diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c index 454a2712e62..1c65e380c84 100644 --- a/drivers/spi/omap2_mcspi.c +++ b/drivers/spi/omap2_mcspi.c @@ -1003,7 +1003,7 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev) goto err1; } if (!request_mem_region(r->start, (r->end - r->start) + 1, - pdev->dev.bus_id)) { + dev_name(&pdev->dev))) { status = -EBUSY; goto err1; } diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/omap_uwire.c index bab6ff061e9..60b5381c65c 100644 --- a/drivers/spi/omap_uwire.c +++ b/drivers/spi/omap_uwire.c @@ -245,7 +245,7 @@ static int uwire_txrx(struct spi_device *spi, struct spi_transfer *t) #ifdef VERBOSE pr_debug("%s: write-%d =%04x\n", - spi->dev.bus_id, bits, val); + dev_name(&spi->dev), bits, val); #endif if (wait_uwire_csr_flag(CSRB, 0, 0)) goto eio; @@ -305,7 +305,7 @@ static int uwire_txrx(struct spi_device *spi, struct spi_transfer *t) status += bytes; #ifdef VERBOSE pr_debug("%s: read-%d =%04x\n", - spi->dev.bus_id, bits, val); + dev_name(&spi->dev), bits, val); #endif } @@ -331,7 +331,7 @@ static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t) uwire = spi_master_get_devdata(spi->master); if (spi->chip_select > 3) { - pr_debug("%s: cs%d?\n", spi->dev.bus_id, spi->chip_select); + pr_debug("%s: cs%d?\n", dev_name(&spi->dev), spi->chip_select); status = -ENODEV; goto done; } @@ -343,7 +343,7 @@ static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t) bits = 8; if (bits > 16) { - pr_debug("%s: wordsize %d?\n", spi->dev.bus_id, bits); + pr_debug("%s: wordsize %d?\n", dev_name(&spi->dev), bits); status = -ENODEV; goto done; } @@ -378,7 +378,7 @@ static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t) hz = t->speed_hz; if (!hz) { - pr_debug("%s: zero speed?\n", spi->dev.bus_id); + pr_debug("%s: zero speed?\n", dev_name(&spi->dev)); status = -EINVAL; goto done; } @@ -406,7 +406,7 @@ static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t) } if (div1_idx == 4) { pr_debug("%s: lowest clock %ld, need %d\n", - spi->dev.bus_id, rate / 10 / 8, hz); + dev_name(&spi->dev), rate / 10 / 8, hz); status = -EDOM; goto done; } diff --git a/drivers/spi/orion_spi.c b/drivers/spi/orion_spi.c index 014becb7d53..c8b0babdc2a 100644 --- a/drivers/spi/orion_spi.c +++ b/drivers/spi/orion_spi.c @@ -496,7 +496,7 @@ static int __init orion_spi_probe(struct platform_device *pdev) } if (!request_mem_region(r->start, (r->end - r->start) + 1, - pdev->dev.bus_id)) { + dev_name(&pdev->dev))) { status = -EBUSY; goto out; } diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index d0fc4ca2f65..ec24f2d16f3 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -1333,7 +1333,7 @@ static int __init init_queue(struct driver_data *drv_data) INIT_WORK(&drv_data->pump_messages, pump_messages); drv_data->workqueue = create_singlethread_workqueue( - drv_data->master->dev.parent->bus_id); + dev_name(drv_data->master->dev.parent)); if (drv_data->workqueue == NULL) return -EBUSY; @@ -1462,7 +1462,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) drv_data->mask_sr = SSSR_TINT | SSSR_RFS | SSSR_TFS | SSSR_ROR; } - status = request_irq(ssp->irq, ssp_int, 0, dev->bus_id, drv_data); + status = request_irq(ssp->irq, ssp_int, 0, dev_name(dev), drv_data); if (status < 0) { dev_err(&pdev->dev, "cannot get IRQ %d\n", ssp->irq); goto out_error_master_alloc; diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c index 7fea3cf4588..3410b0c55ed 100644 --- a/drivers/spi/spi_bfin5xx.c +++ b/drivers/spi/spi_bfin5xx.c @@ -1160,8 +1160,8 @@ static inline int init_queue(struct driver_data *drv_data) /* init messages workqueue */ INIT_WORK(&drv_data->pump_messages, pump_messages); - drv_data->workqueue = - create_singlethread_workqueue(drv_data->master->dev.parent->bus_id); + drv_data->workqueue = create_singlethread_workqueue( + dev_name(drv_data->master->dev.parent)); if (drv_data->workqueue == NULL) return -EBUSY; diff --git a/drivers/spi/spi_gpio.c b/drivers/spi/spi_gpio.c index f5ed9721aab..d2866c293de 100644 --- a/drivers/spi/spi_gpio.c +++ b/drivers/spi/spi_gpio.c @@ -191,7 +191,7 @@ static int spi_gpio_setup(struct spi_device *spi) return -EINVAL; if (!spi->controller_state) { - status = gpio_request(cs, spi->dev.bus_id); + status = gpio_request(cs, dev_name(&spi->dev)); if (status) return status; status = gpio_direction_output(cs, spi->mode & SPI_CS_HIGH); diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c index 269a55ec52e..0480d8bb19d 100644 --- a/drivers/spi/spi_imx.c +++ b/drivers/spi/spi_imx.c @@ -1381,7 +1381,7 @@ static int __init init_queue(struct driver_data *drv_data) INIT_WORK(&drv_data->work, pump_messages); drv_data->workqueue = create_singlethread_workqueue( - drv_data->master->dev.parent->bus_id); + dev_name(drv_data->master->dev.parent)); if (drv_data->workqueue == NULL) return -EBUSY; @@ -1525,7 +1525,8 @@ static int __init spi_imx_probe(struct platform_device *pdev) status = -ENODEV; goto err_no_irqres; } - status = request_irq(irq, spi_int, IRQF_DISABLED, dev->bus_id, drv_data); + status = request_irq(irq, spi_int, IRQF_DISABLED, + dev_name(dev), drv_data); if (status < 0) { dev_err(&pdev->dev, "probe - cannot get IRQ (%d)\n", status); goto err_no_irqres; diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c index ac0e3e4b3c5..44a2b46ccb7 100644 --- a/drivers/spi/spi_mpc83xx.c +++ b/drivers/spi/spi_mpc83xx.c @@ -637,7 +637,7 @@ static int __init mpc83xx_spi_probe(struct platform_device *dev) INIT_LIST_HEAD(&mpc83xx_spi->queue); mpc83xx_spi->workqueue = create_singlethread_workqueue( - master->dev.parent->bus_id); + dev_name(master->dev.parent)); if (mpc83xx_spi->workqueue == NULL) { ret = -EBUSY; goto free_irq; @@ -649,7 +649,7 @@ static int __init mpc83xx_spi_probe(struct platform_device *dev) printk(KERN_INFO "%s: MPC83xx SPI Controller driver at 0x%p (irq = %d)\n", - dev->dev.bus_id, mpc83xx_spi->base, mpc83xx_spi->irq); + dev_name(&dev->dev), mpc83xx_spi->base, mpc83xx_spi->irq); return ret; diff --git a/drivers/spi/spi_txx9.c b/drivers/spi/spi_txx9.c index 2296f37ea3c..29cbb065618 100644 --- a/drivers/spi/spi_txx9.c +++ b/drivers/spi/spi_txx9.c @@ -404,7 +404,8 @@ static int __init txx9spi_probe(struct platform_device *dev) if (ret) goto exit; - c->workqueue = create_singlethread_workqueue(master->dev.parent->bus_id); + c->workqueue = create_singlethread_workqueue( + dev_name(master->dev.parent)); if (!c->workqueue) goto exit_busy; c->last_chipselect = -1; -- GitLab From 7ad33e74857f16f1202cbc5746faf52e88e8b376 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:21 -0700 Subject: [PATCH 4392/4982] video: struct device - replace bus_id with dev_name(), dev_set_name() Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/video/pmag-ba-fb.c | 17 +++++++++-------- drivers/video/pmagb-b-fb.c | 17 +++++++++-------- drivers/video/ps3fb.c | 2 +- drivers/video/sh_mobile_lcdcfb.c | 2 +- drivers/video/tmiofb.c | 2 +- 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c index 3a3f80f6521..0573ec685a5 100644 --- a/drivers/video/pmag-ba-fb.c +++ b/drivers/video/pmag-ba-fb.c @@ -151,7 +151,7 @@ static int __init pmagbafb_probe(struct device *dev) info = framebuffer_alloc(sizeof(struct pmagbafb_par), dev); if (!info) { - printk(KERN_ERR "%s: Cannot allocate memory\n", dev->bus_id); + printk(KERN_ERR "%s: Cannot allocate memory\n", dev_name(dev)); return -ENOMEM; } @@ -160,7 +160,7 @@ static int __init pmagbafb_probe(struct device *dev) if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { printk(KERN_ERR "%s: Cannot allocate color map\n", - dev->bus_id); + dev_name(dev)); err = -ENOMEM; goto err_alloc; } @@ -173,8 +173,9 @@ static int __init pmagbafb_probe(struct device *dev) /* Request the I/O MEM resource. */ start = tdev->resource.start; len = tdev->resource.end - start + 1; - if (!request_mem_region(start, len, dev->bus_id)) { - printk(KERN_ERR "%s: Cannot reserve FB region\n", dev->bus_id); + if (!request_mem_region(start, len, dev_name(dev))) { + printk(KERN_ERR "%s: Cannot reserve FB region\n", + dev_name(dev)); err = -EBUSY; goto err_cmap; } @@ -183,7 +184,7 @@ static int __init pmagbafb_probe(struct device *dev) info->fix.mmio_start = start; par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len); if (!par->mmio) { - printk(KERN_ERR "%s: Cannot map MMIO\n", dev->bus_id); + printk(KERN_ERR "%s: Cannot map MMIO\n", dev_name(dev)); err = -ENOMEM; goto err_resource; } @@ -194,7 +195,7 @@ static int __init pmagbafb_probe(struct device *dev) info->screen_base = ioremap_nocache(info->fix.smem_start, info->fix.smem_len); if (!info->screen_base) { - printk(KERN_ERR "%s: Cannot map FB\n", dev->bus_id); + printk(KERN_ERR "%s: Cannot map FB\n", dev_name(dev)); err = -ENOMEM; goto err_mmio_map; } @@ -205,14 +206,14 @@ static int __init pmagbafb_probe(struct device *dev) err = register_framebuffer(info); if (err < 0) { printk(KERN_ERR "%s: Cannot register framebuffer\n", - dev->bus_id); + dev_name(dev)); goto err_smem_map; } get_device(dev); pr_info("fb%d: %s frame buffer device at %s\n", - info->node, info->fix.id, dev->bus_id); + info->node, info->fix.id, dev_name(dev)); return 0; diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c index 9b80597241b..98748723af9 100644 --- a/drivers/video/pmagb-b-fb.c +++ b/drivers/video/pmagb-b-fb.c @@ -258,7 +258,7 @@ static int __init pmagbbfb_probe(struct device *dev) info = framebuffer_alloc(sizeof(struct pmagbbfb_par), dev); if (!info) { - printk(KERN_ERR "%s: Cannot allocate memory\n", dev->bus_id); + printk(KERN_ERR "%s: Cannot allocate memory\n", dev_name(dev)); return -ENOMEM; } @@ -267,7 +267,7 @@ static int __init pmagbbfb_probe(struct device *dev) if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { printk(KERN_ERR "%s: Cannot allocate color map\n", - dev->bus_id); + dev_name(dev)); err = -ENOMEM; goto err_alloc; } @@ -280,8 +280,9 @@ static int __init pmagbbfb_probe(struct device *dev) /* Request the I/O MEM resource. */ start = tdev->resource.start; len = tdev->resource.end - start + 1; - if (!request_mem_region(start, len, dev->bus_id)) { - printk(KERN_ERR "%s: Cannot reserve FB region\n", dev->bus_id); + if (!request_mem_region(start, len, dev_name(dev))) { + printk(KERN_ERR "%s: Cannot reserve FB region\n", + dev_name(dev)); err = -EBUSY; goto err_cmap; } @@ -290,7 +291,7 @@ static int __init pmagbbfb_probe(struct device *dev) info->fix.mmio_start = start; par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len); if (!par->mmio) { - printk(KERN_ERR "%s: Cannot map MMIO\n", dev->bus_id); + printk(KERN_ERR "%s: Cannot map MMIO\n", dev_name(dev)); err = -ENOMEM; goto err_resource; } @@ -301,7 +302,7 @@ static int __init pmagbbfb_probe(struct device *dev) info->fix.smem_start = start + PMAGB_B_FBMEM; par->smem = ioremap_nocache(info->fix.smem_start, info->fix.smem_len); if (!par->smem) { - printk(KERN_ERR "%s: Cannot map FB\n", dev->bus_id); + printk(KERN_ERR "%s: Cannot map FB\n", dev_name(dev)); err = -ENOMEM; goto err_mmio_map; } @@ -316,7 +317,7 @@ static int __init pmagbbfb_probe(struct device *dev) err = register_framebuffer(info); if (err < 0) { printk(KERN_ERR "%s: Cannot register framebuffer\n", - dev->bus_id); + dev_name(dev)); goto err_smem_map; } @@ -328,7 +329,7 @@ static int __init pmagbbfb_probe(struct device *dev) par->osc1 / 1000, par->osc1 % 1000); pr_info("fb%d: %s frame buffer device at %s\n", - info->node, info->fix.id, dev->bus_id); + info->node, info->fix.id, dev_name(dev)); pr_info("fb%d: Osc0: %s, Osc1: %s, Osc%u selected\n", info->node, freq0, par->osc1 ? freq1 : "disabled", par->osc1 != 0); diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c index 87f826e4c95..e00c1dff55d 100644 --- a/drivers/video/ps3fb.c +++ b/drivers/video/ps3fb.c @@ -1213,7 +1213,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) dev->core.driver_data = info; dev_info(info->device, "%s %s, using %u KiB of video memory\n", - dev_driver_string(info->dev), info->dev->bus_id, + dev_driver_string(info->dev), dev_name(info->dev), info->fix.smem_len >> 10); task = kthread_run(ps3fbd, info, DEVICE_NAME); diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 2c5d069e5f0..1d2636a898c 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -687,7 +687,7 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) } error = request_irq(i, sh_mobile_lcdc_irq, IRQF_DISABLED, - pdev->dev.bus_id, priv); + dev_name(&pdev->dev), priv); if (error) { dev_err(&pdev->dev, "unable to request irq\n"); goto err1; diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c index 7baf2dd12d5..a1eb0862255 100644 --- a/drivers/video/tmiofb.c +++ b/drivers/video/tmiofb.c @@ -751,7 +751,7 @@ static int __devinit tmiofb_probe(struct platform_device *dev) } retval = request_irq(irq, &tmiofb_irq, IRQF_DISABLED, - dev->dev.bus_id, info); + dev_name(&dev->dev), info); if (retval) goto err_request_irq; -- GitLab From 2796872c40c462bacf2d09bb99faa6dcd640a620 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:21 -0700 Subject: [PATCH 4393/4982] zorro: struct device - replace bus_id with dev_name(), dev_set_name() Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/zorro/zorro.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c index a1585d6f648..d45fb34e2d2 100644 --- a/drivers/zorro/zorro.c +++ b/drivers/zorro/zorro.c @@ -140,7 +140,7 @@ static int __init zorro_init(void) /* Initialize the Zorro bus */ INIT_LIST_HEAD(&zorro_bus.devices); - strcpy(zorro_bus.dev.bus_id, "zorro"); + dev_set_name(&zorro_bus.dev, "zorro"); error = device_register(&zorro_bus.dev); if (error) { pr_err("Zorro: Error registering zorro_bus\n"); @@ -167,7 +167,7 @@ static int __init zorro_init(void) if (request_resource(zorro_find_parent_resource(z), &z->resource)) pr_err("Zorro: Address space collision on device %s %pR\n", z->name, &z->resource); - sprintf(z->dev.bus_id, "%02x", i); + dev_set_name(&z->dev, "%02x", i); z->dev.parent = &zorro_bus.dev; z->dev.bus = &zorro_bus_type; error = device_register(&z->dev); -- GitLab From 48f8151ea68ad78391ef6ff12a83e6fbdb6094f6 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:21 -0700 Subject: [PATCH 4394/4982] mmc: struct device - replace bus_id with dev_name(), dev_set_name() Cc: drzeus-mmc@drzeus.cx Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/mmc/host/atmel-mci.c | 2 +- drivers/mmc/host/of_mmc_spi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 2b1196e6142..e94e92001e7 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -1603,7 +1603,7 @@ static int __init atmci_probe(struct platform_device *pdev) tasklet_init(&host->tasklet, atmci_tasklet_func, (unsigned long)host); - ret = request_irq(irq, atmci_interrupt, 0, pdev->dev.bus_id, host); + ret = request_irq(irq, atmci_interrupt, 0, dev_name(&pdev->dev), host); if (ret) goto err_request_irq; diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c index fb2921f8099..0c44d560bf1 100644 --- a/drivers/mmc/host/of_mmc_spi.c +++ b/drivers/mmc/host/of_mmc_spi.c @@ -103,7 +103,7 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi) if (!gpio_is_valid(oms->gpios[i])) continue; - ret = gpio_request(oms->gpios[i], dev->bus_id); + ret = gpio_request(oms->gpios[i], dev_name(dev)); if (ret < 0) { oms->gpios[i] = -EINVAL; continue; -- GitLab From c36f1e3301ee9d8045938a2741da7f8e4c7fbbff Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:21 -0700 Subject: [PATCH 4395/4982] mtd: struct device - replace bus_id with dev_name(), dev_set_name() Cc: dwmw2@infradead.org Cc: linux-mtd@lists.infradead.org Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/mtd/nand/ndfc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index 582cf80f555..89bf85af642 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c @@ -187,7 +187,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, return -ENODEV; ndfc->mtd.name = kasprintf(GFP_KERNEL, "%s.%s", - ndfc->ofdev->dev.bus_id, flash_np->name); + dev_name(&ndfc->ofdev->dev), flash_np->name); if (!ndfc->mtd.name) { ret = -ENOMEM; goto err; -- GitLab From 54cc6954a431dad42fb73e0a50b6d318a70594f6 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:21 -0700 Subject: [PATCH 4396/4982] pci: struct device - replace bus_id with dev_name(), dev_set_name() Cc: jbarnes@virtuousgeek.org Cc: linux-pci@vger.kernel.org Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/pci/hotplug/cpqphp_sysfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c index a13abf55d78..8450f4a6568 100644 --- a/drivers/pci/hotplug/cpqphp_sysfs.c +++ b/drivers/pci/hotplug/cpqphp_sysfs.c @@ -225,7 +225,8 @@ void cpqhp_shutdown_debugfs(void) void cpqhp_create_debugfs_files(struct controller *ctrl) { - ctrl->dentry = debugfs_create_file(ctrl->pci_dev->dev.bus_id, S_IRUGO, root, ctrl, &debug_ops); + ctrl->dentry = debugfs_create_file(dev_name(&ctrl->pci_dev->dev), + S_IRUGO, root, ctrl, &debug_ops); } void cpqhp_remove_debugfs_files(struct controller *ctrl) -- GitLab From 37f105448eac49073c3ff9f101553aad845d24eb Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:21 -0700 Subject: [PATCH 4397/4982] rapidio: struct device - replace bus_id with dev_name(), dev_set_name() Cc: mporter@kernel.crashing.org Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/rapidio/rio-driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c index addb87cf44d..3222fa3c808 100644 --- a/drivers/rapidio/rio-driver.c +++ b/drivers/rapidio/rio-driver.c @@ -193,7 +193,7 @@ static int rio_match_bus(struct device *dev, struct device_driver *drv) } static struct device rio_bus = { - .bus_id = "rapidio", + .init_name = "rapidio", }; struct bus_type rio_bus_type = { -- GitLab From 1173960b0e85761811a421eb0bbcefb117eb7535 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:21 -0700 Subject: [PATCH 4398/4982] s390: struct device - replace bus_id with dev_name(), dev_set_name() Cc: schwidefsky@de.ibm.com Cc: linux-s390@vger.kernel.org Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/s390/net/qeth_l3_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 3d04920b9bb..0dcc036d34a 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1038,7 +1038,7 @@ static int qeth_l3_setadapter_parms(struct qeth_card *card) rc = qeth_query_setadapterparms(card); if (rc) { QETH_DBF_MESSAGE(2, "%s couldn't set adapter parameters: " - "0x%x\n", card->gdev->dev.bus_id, rc); + "0x%x\n", dev_name(&card->gdev->dev), rc); return rc; } if (qeth_adp_supported(card, IPA_SETADP_ALTER_MAC_ADDRESS)) { -- GitLab From 65a212dd71ffd99c83ad780205932fcb96a973b6 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:21 -0700 Subject: [PATCH 4399/4982] serial: struct device - replace bus_id with dev_name(), dev_set_name() Cc: davem@davemloft.net Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/serial/sunzilog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index 45a299f3561..e09d3cebb4f 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -1438,12 +1438,12 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m } else { printk(KERN_INFO "%s: Keyboard at MMIO 0x%llx (irq = %d) " "is a %s\n", - op->dev.bus_id, + dev_name(&op->dev), (unsigned long long) up[0].port.mapbase, op->irqs[0], sunzilog_type(&up[0].port)); printk(KERN_INFO "%s: Mouse at MMIO 0x%llx (irq = %d) " "is a %s\n", - op->dev.bus_id, + dev_name(&op->dev), (unsigned long long) up[1].port.mapbase, op->irqs[0], sunzilog_type(&up[1].port)); kbm_inst++; -- GitLab From 1692713ee94e8d26f592a8e90b817ef66354246c Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:21 -0700 Subject: [PATCH 4400/4982] sh: struct device - replace bus_id with dev_name(), dev_set_name() Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/sh/maple/maple.c | 8 ++++---- drivers/sh/superhyway/superhyway.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c index 63f0de29aa1..7e1257af3d4 100644 --- a/drivers/sh/maple/maple.c +++ b/drivers/sh/maple/maple.c @@ -424,7 +424,7 @@ static void maple_attach_driver(struct maple_device *mdev) /* Do this silently - as not a real device */ function = 0; mdev->driver = &maple_dummy_driver; - sprintf(mdev->dev.bus_id, "%d:0.port", mdev->port); + dev_set_name(&mdev->dev, "%d:0.port", mdev->port); } else { printk(KERN_INFO "Maple bus at (%d, %d): Function 0x%lX\n", @@ -440,8 +440,8 @@ static void maple_attach_driver(struct maple_device *mdev) "No maple driver found.\n"); mdev->driver = &maple_dummy_driver; } - sprintf(mdev->dev.bus_id, "%d:0%d.%lX", mdev->port, - mdev->unit, function); + dev_set_name(&mdev->dev, "%d:0%d.%lX", mdev->port, + mdev->unit, function); } mdev->function = function; mdev->dev.release = &maple_release_device; @@ -780,7 +780,7 @@ struct bus_type maple_bus_type = { EXPORT_SYMBOL_GPL(maple_bus_type); static struct device maple_bus = { - .bus_id = "maple", + .init_name = "maple", .release = maple_bus_release, }; diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c index 4d0282b821b..2d9e7f3d561 100644 --- a/drivers/sh/superhyway/superhyway.c +++ b/drivers/sh/superhyway/superhyway.c @@ -22,7 +22,7 @@ static int superhyway_devices; static struct device superhyway_bus_device = { - .bus_id = "superhyway", + .init_name = "superhyway", }; static void superhyway_device_release(struct device *dev) @@ -83,7 +83,7 @@ int superhyway_add_device(unsigned long base, struct superhyway_device *sdev, dev->id.id = dev->vcr.mod_id; sprintf(dev->name, "SuperHyway device %04x", dev->id.id); - sprintf(dev->dev.bus_id, "%02x", superhyway_devices); + dev_set_name(&dev->dev, "%02x", superhyway_devices); superhyway_devices++; -- GitLab From df388556d7d845983c0da3a4a49873472c466275 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:22 -0700 Subject: [PATCH 4401/4982] tc: struct device - replace bus_id with dev_name(), dev_set_name() Cc: macro@linux-mips.org Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/tc/tc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/tc/tc.c b/drivers/tc/tc.c index f77f62a4b32..e5bd4470a57 100644 --- a/drivers/tc/tc.c +++ b/drivers/tc/tc.c @@ -86,7 +86,7 @@ static void __init tc_bus_add_devices(struct tc_bus *tbus) slot); goto out_err; } - sprintf(tdev->dev.bus_id, "tc%x", slot); + dev_set_name(&tdev->dev, "tc%x", slot); tdev->bus = tbus; tdev->dev.parent = &tbus->dev; tdev->dev.bus = &tc_bus_type; @@ -104,7 +104,7 @@ static void __init tc_bus_add_devices(struct tc_bus *tbus) tdev->vendor[8] = 0; tdev->name[8] = 0; - pr_info("%s: %s %s %s\n", tdev->dev.bus_id, tdev->vendor, + pr_info("%s: %s %s %s\n", dev_name(&tdev->dev), tdev->vendor, tdev->name, tdev->firmware); devsize = readb(module + offset + TC_SLOT_SIZE); @@ -118,7 +118,7 @@ static void __init tc_bus_add_devices(struct tc_bus *tbus) } else { printk(KERN_ERR "%s: Cannot provide slot space " "(%dMiB required, up to %dMiB supported)\n", - tdev->dev.bus_id, devsize >> 20, + dev_name(&tdev->dev), devsize >> 20, max(slotsize, extslotsize) >> 20); kfree(tdev); goto out_err; @@ -146,7 +146,7 @@ static int __init tc_init(void) return 0; INIT_LIST_HEAD(&tc_bus.devices); - strcpy(tc_bus.dev.bus_id, "tc"); + dev_set_name(&tc_bus.dev, "tc"); device_register(&tc_bus.dev); if (tc_bus.info.slot_size) { -- GitLab From f2fecec51ad593cce1b07a2b54830a8412a441ea Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:22 -0700 Subject: [PATCH 4402/4982] pcmcia: struct device - replace bus_id with dev_name(), dev_set_name() Cc: Dominik Brodowski Cc: linux-pcmcia@lists.infradead.org Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/pcmcia/rsrc_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index c0e2afc79e3..e592e0e0d7e 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -153,7 +153,7 @@ static struct resource *iodyn_find_io_region(unsigned long base, int num, unsigned long align, struct pcmcia_socket *s) { struct resource *res = make_resource(0, num, IORESOURCE_IO, - s->dev.bus_id); + dev_name(&s->dev)); struct pcmcia_align_data data; unsigned long min = base; int ret; -- GitLab From 744bcb13d376b38ff1df3bbcc810493e1b999502 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:22 -0700 Subject: [PATCH 4403/4982] rtc: struct device - replace bus_id with dev_name(), dev_set_name() Cc: a.zummo@towertech.it Cc: rtc-linux@googlegroups.com Signed-off-by: Kay Sievers Signed-off-by: Alessandro Zummo Signed-off-by: Greg Kroah-Hartman --- drivers/rtc/rtc-at91sam9.c | 4 ++-- drivers/rtc/rtc-omap.c | 4 ++-- drivers/rtc/rtc-twl4030.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index d5e4e637dde..86c61f14351 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c @@ -351,7 +351,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev) /* register irq handler after we know what name we'll use */ ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt, IRQF_DISABLED | IRQF_SHARED, - rtc->rtcdev->dev.bus_id, rtc); + dev_name(&rtc->rtcdev->dev), rtc); if (ret) { dev_dbg(&pdev->dev, "can't share IRQ %d?\n", AT91_ID_SYS); rtc_device_unregister(rtc->rtcdev); @@ -366,7 +366,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev) if (gpbr_readl(rtc) == 0) dev_warn(&pdev->dev, "%s: SET TIME!\n", - rtc->rtcdev->dev.bus_id); + dev_name(&rtc->rtcdev->dev)); return 0; diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 2cbeb0794f1..bd1ce8e2bc1 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -377,13 +377,13 @@ static int __init omap_rtc_probe(struct platform_device *pdev) /* handle periodic and alarm irqs */ if (request_irq(omap_rtc_timer, rtc_irq, IRQF_DISABLED, - rtc->dev.bus_id, rtc)) { + dev_name(&rtc->dev), rtc)) { pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n", pdev->name, omap_rtc_timer); goto fail0; } if (request_irq(omap_rtc_alarm, rtc_irq, IRQF_DISABLED, - rtc->dev.bus_id, rtc)) { + dev_name(&rtc->dev), rtc)) { pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n", pdev->name, omap_rtc_alarm); goto fail1; diff --git a/drivers/rtc/rtc-twl4030.c b/drivers/rtc/rtc-twl4030.c index ad35f76c46b..a6341e4f9a0 100644 --- a/drivers/rtc/rtc-twl4030.c +++ b/drivers/rtc/rtc-twl4030.c @@ -426,7 +426,7 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) ret = request_irq(irq, twl4030_rtc_interrupt, IRQF_TRIGGER_RISING, - rtc->dev.bus_id, rtc); + dev_name(&rtc->dev), rtc); if (ret < 0) { dev_err(&pdev->dev, "IRQ is not free.\n"); goto out1; -- GitLab From c23135573f37facd18edb2e8e8512c67928c54ac Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:22 -0700 Subject: [PATCH 4404/4982] net: struct device - replace bus_id with dev_name(), dev_set_name() Cc: davem@davemloft.net Cc: netdev@vger.kernel.org Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/net/arm/ks8695net.c | 2 +- drivers/net/au1000_eth.c | 8 ++++---- drivers/net/bfin_mac.c | 12 ++++++------ drivers/net/bmac.c | 2 +- drivers/net/cpmac.c | 2 +- drivers/net/declance.c | 6 +++--- drivers/net/depca.c | 6 +++--- drivers/net/ehea/ehea_main.c | 2 +- drivers/net/jazzsonic.c | 6 ++++-- drivers/net/macb.c | 10 +++++----- drivers/net/macsonic.c | 15 ++++++++------- drivers/net/mv643xx_eth.c | 2 +- drivers/net/sb1250-mac.c | 10 +++++----- drivers/net/smc911x.c | 2 +- drivers/net/smc91x.c | 2 +- drivers/net/smsc911x.c | 7 ++++--- drivers/net/smsc9420.c | 4 ++-- drivers/net/tc35815.c | 4 ++-- drivers/net/xtsonic.c | 2 +- 19 files changed, 54 insertions(+), 50 deletions(-) diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c index f3a12743489..35cd264abae 100644 --- a/drivers/net/arm/ks8695net.c +++ b/drivers/net/arm/ks8695net.c @@ -1059,7 +1059,7 @@ ks8695_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info) { strlcpy(info->driver, MODULENAME, sizeof(info->driver)); strlcpy(info->version, MODULEVERSION, sizeof(info->version)); - strlcpy(info->bus_info, ndev->dev.parent->bus_id, + strlcpy(info->bus_info, dev_name(ndev->dev.parent), sizeof(info->bus_info)); } diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index 9c875bb3f76..79aec32c6ad 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -355,8 +355,8 @@ static int mii_probe (struct net_device *dev) /* now we are supposed to have a proper phydev, to attach to... */ BUG_ON(phydev->attached_dev); - phydev = phy_connect(dev, phydev->dev.bus_id, &au1000_adjust_link, 0, - PHY_INTERFACE_MODE_MII); + phydev = phy_connect(dev, dev_name(&phydev->dev), &au1000_adjust_link, + 0, PHY_INTERFACE_MODE_MII); if (IS_ERR(phydev)) { printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); @@ -381,8 +381,8 @@ static int mii_probe (struct net_device *dev) aup->phy_dev = phydev; printk(KERN_INFO "%s: attached PHY driver [%s] " - "(mii_bus:phy_addr=%s, irq=%d)\n", - dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq); + "(mii_bus:phy_addr=%s, irq=%d)\n", dev->name, + phydev->drv->name, dev_name(&phydev->dev), phydev->irq); return 0; } diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 78e31aa861e..9afe8092dfc 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -415,11 +415,11 @@ static int mii_probe(struct net_device *dev) } #if defined(CONFIG_BFIN_MAC_RMII) - phydev = phy_connect(dev, phydev->dev.bus_id, &bfin_mac_adjust_link, 0, - PHY_INTERFACE_MODE_RMII); + phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link, + 0, PHY_INTERFACE_MODE_RMII); #else - phydev = phy_connect(dev, phydev->dev.bus_id, &bfin_mac_adjust_link, 0, - PHY_INTERFACE_MODE_MII); + phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link, + 0, PHY_INTERFACE_MODE_MII); #endif if (IS_ERR(phydev)) { @@ -447,7 +447,7 @@ static int mii_probe(struct net_device *dev) printk(KERN_INFO "%s: attached PHY driver [%s] " "(mii_bus:phy_addr=%s, irq=%d, mdc_clk=%dHz(mdc_div=%d)" "@sclk=%dMHz)\n", - DRV_NAME, phydev->drv->name, phydev->dev.bus_id, phydev->irq, + DRV_NAME, phydev->drv->name, dev_name(&phydev->dev), phydev->irq, MDC_CLK, mdc_div, sclk/1000000); return 0; @@ -488,7 +488,7 @@ static void bfin_mac_ethtool_getdrvinfo(struct net_device *dev, strcpy(info->driver, DRV_NAME); strcpy(info->version, DRV_VERSION); strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, dev->dev.bus_id); + strcpy(info->bus_info, dev_name(&dev->dev)); } static struct ethtool_ops bfin_mac_ethtool_ops = { diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index 8a546a33d58..1ab58375d06 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c @@ -1240,7 +1240,7 @@ static void bmac_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *inf { struct bmac_data *bp = netdev_priv(dev); strcpy(info->driver, "bmac"); - strcpy(info->bus_info, bp->mdev->ofdev.dev.bus_id); + strcpy(info->bus_info, dev_name(&bp->mdev->ofdev.dev)); } static const struct ethtool_ops bmac_ethtool_ops = { diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index f66548751c3..79741c5f9fe 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -1161,7 +1161,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev) priv->msg_enable = netif_msg_init(debug_level, 0xff); memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr)); - priv->phy = phy_connect(dev, cpmac_mii->phy_map[phy_id]->dev.bus_id, + priv->phy = phy_connect(dev, dev_name(&cpmac_mii->phy_map[phy_id]->dev), &cpmac_adjust_link, 0, PHY_INTERFACE_MODE_MII); if (IS_ERR(priv->phy)) { if (netif_msg_drv(priv)) diff --git a/drivers/net/declance.c b/drivers/net/declance.c index 7ce3053530f..861c867fca8 100644 --- a/drivers/net/declance.c +++ b/drivers/net/declance.c @@ -1027,7 +1027,7 @@ static int __init dec_lance_probe(struct device *bdev, const int type) printk(version); if (bdev) - snprintf(name, sizeof(name), "%s", bdev->bus_id); + snprintf(name, sizeof(name), "%s", dev_name(bdev)); else { i = 0; dev = root_lance_dev; @@ -1105,10 +1105,10 @@ static int __init dec_lance_probe(struct device *bdev, const int type) start = to_tc_dev(bdev)->resource.start; len = to_tc_dev(bdev)->resource.end - start + 1; - if (!request_mem_region(start, len, bdev->bus_id)) { + if (!request_mem_region(start, len, dev_name(bdev))) { printk(KERN_ERR "%s: Unable to reserve MMIO resource\n", - bdev->bus_id); + dev_name(bdev)); ret = -EBUSY; goto err_out_dev; } diff --git a/drivers/net/depca.c b/drivers/net/depca.c index e4cef491dc7..55625dbbae5 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -606,8 +606,8 @@ static int __init depca_hw_init (struct net_device *dev, struct device *device) if (!mem_start || lp->adapter < DEPCA || lp->adapter >=unknown) return -ENXIO; - printk ("%s: %s at 0x%04lx", - device->bus_id, depca_signature[lp->adapter], ioaddr); + printk("%s: %s at 0x%04lx", + dev_name(device), depca_signature[lp->adapter], ioaddr); switch (lp->depca_bus) { #ifdef CONFIG_MCA @@ -669,7 +669,7 @@ static int __init depca_hw_init (struct net_device *dev, struct device *device) spin_lock_init(&lp->lock); sprintf(lp->adapter_name, "%s (%s)", - depca_signature[lp->adapter], device->bus_id); + depca_signature[lp->adapter], dev_name(device)); status = -EBUSY; /* Initialisation Block */ diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index dfe92264e82..8e7c16535ad 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -3040,7 +3040,7 @@ static struct device *ehea_register_port(struct ehea_port *port, port->ofdev.dev.parent = &port->adapter->ofdev->dev; port->ofdev.dev.bus = &ibmebus_bus_type; - sprintf(port->ofdev.dev.bus_id, "port%d", port_name_cnt++); + dev_set_name(&port->ofdev.dev, "port%d", port_name_cnt++); port->ofdev.dev.release = logical_port_release; ret = of_device_register(&port->ofdev); diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c index 334ff9e12cd..14248cfc3df 100644 --- a/drivers/net/jazzsonic.c +++ b/drivers/net/jazzsonic.c @@ -131,7 +131,8 @@ static int __init sonic_probe1(struct net_device *dev) if (sonic_debug && version_printed++ == 0) printk(version); - printk(KERN_INFO "%s: Sonic ethernet found at 0x%08lx, ", lp->device->bus_id, dev->base_addr); + printk(KERN_INFO "%s: Sonic ethernet found at 0x%08lx, ", + dev_name(lp->device), dev->base_addr); /* * Put the sonic into software reset, then @@ -156,7 +157,8 @@ static int __init sonic_probe1(struct net_device *dev) if ((lp->descriptors = dma_alloc_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode), &lp->descriptors_laddr, GFP_KERNEL)) == NULL) { - printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", lp->device->bus_id); + printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", + dev_name(lp->device)); goto out; } diff --git a/drivers/net/macb.c b/drivers/net/macb.c index f6c4936e2fa..f4086542c35 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -211,10 +211,10 @@ static int macb_mii_probe(struct net_device *dev) /* attach the mac to the phy */ if (pdata && pdata->is_rmii) { - phydev = phy_connect(dev, phydev->dev.bus_id, + phydev = phy_connect(dev, dev_name(&phydev->dev), &macb_handle_link_change, 0, PHY_INTERFACE_MODE_RMII); } else { - phydev = phy_connect(dev, phydev->dev.bus_id, + phydev = phy_connect(dev, dev_name(&phydev->dev), &macb_handle_link_change, 0, PHY_INTERFACE_MODE_MII); } @@ -1077,7 +1077,7 @@ static void macb_get_drvinfo(struct net_device *dev, strcpy(info->driver, bp->pdev->dev.driver->name); strcpy(info->version, "$Revision: 1.14 $"); - strcpy(info->bus_info, bp->pdev->dev.bus_id); + strcpy(info->bus_info, dev_name(&bp->pdev->dev)); } static struct ethtool_ops macb_ethtool_ops = { @@ -1234,8 +1234,8 @@ static int __init macb_probe(struct platform_device *pdev) phydev = bp->phy_dev; printk(KERN_INFO "%s: attached PHY driver [%s] " - "(mii_bus:phy_addr=%s, irq=%d)\n", - dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq); + "(mii_bus:phy_addr=%s, irq=%d)\n", dev->name, + phydev->drv->name, dev_name(&phydev->dev), phydev->irq); return 0; diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c index 205bb05c25d..527166e35d5 100644 --- a/drivers/net/macsonic.c +++ b/drivers/net/macsonic.c @@ -176,7 +176,8 @@ static int __init macsonic_init(struct net_device *dev) if ((lp->descriptors = dma_alloc_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode), &lp->descriptors_laddr, GFP_KERNEL)) == NULL) { - printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", lp->device->bus_id); + printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", + dev_name(lp->device)); return -ENOMEM; } @@ -337,7 +338,7 @@ static int __init mac_onboard_sonic_probe(struct net_device *dev) sonic_version_printed = 1; } printk(KERN_INFO "%s: onboard / comm-slot SONIC at 0x%08lx\n", - lp->device->bus_id, dev->base_addr); + dev_name(lp->device), dev->base_addr); /* The PowerBook's SONIC is 16 bit always. */ if (macintosh_config->ident == MAC_MODEL_PB520) { @@ -370,10 +371,10 @@ static int __init mac_onboard_sonic_probe(struct net_device *dev) } printk(KERN_INFO "%s: revision 0x%04x, using %d bit DMA and register offset %d\n", - lp->device->bus_id, sr, lp->dma_bitmode?32:16, lp->reg_offset); + dev_name(lp->device), sr, lp->dma_bitmode?32:16, lp->reg_offset); #if 0 /* This is sometimes useful to find out how MacOS configured the card. */ - printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", lp->device->bus_id, + printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", dev_name(lp->device), SONIC_READ(SONIC_DCR) & 0xffff, SONIC_READ(SONIC_DCR2) & 0xffff); #endif @@ -525,12 +526,12 @@ static int __init mac_nubus_sonic_probe(struct net_device *dev) sonic_version_printed = 1; } printk(KERN_INFO "%s: %s in slot %X\n", - lp->device->bus_id, ndev->board->name, ndev->board->slot); + dev_name(lp->device), ndev->board->name, ndev->board->slot); printk(KERN_INFO "%s: revision 0x%04x, using %d bit DMA and register offset %d\n", - lp->device->bus_id, SONIC_READ(SONIC_SR), dma_bitmode?32:16, reg_offset); + dev_name(lp->device), SONIC_READ(SONIC_SR), dma_bitmode?32:16, reg_offset); #if 0 /* This is sometimes useful to find out how MacOS configured the card. */ - printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", lp->device->bus_id, + printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", dev_name(lp->device), SONIC_READ(SONIC_DCR) & 0xffff, SONIC_READ(SONIC_DCR2) & 0xffff); #endif diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index b0bc3bc18e9..fe4e158c893 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -2588,7 +2588,7 @@ static void phy_init(struct mv643xx_eth_private *mp, int speed, int duplex) phy_reset(mp); - phy_attach(mp->dev, phy->dev.bus_id, 0, PHY_INTERFACE_MODE_GMII); + phy_attach(mp->dev, dev_name(&phy->dev), 0, PHY_INTERFACE_MODE_GMII); if (speed == 0) { phy->autoneg = AUTONEG_ENABLE; diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index 31e38fae017..845431c186a 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -2478,7 +2478,7 @@ static int sbmac_mii_probe(struct net_device *dev) return -ENXIO; } - phy_dev = phy_connect(dev, phy_dev->dev.bus_id, &sbmac_mii_poll, 0, + phy_dev = phy_connect(dev, dev_name(&phy_dev->dev), &sbmac_mii_poll, 0, PHY_INTERFACE_MODE_GMII); if (IS_ERR(phy_dev)) { printk(KERN_ERR "%s: could not attach to PHY\n", dev->name); @@ -2500,7 +2500,7 @@ static int sbmac_mii_probe(struct net_device *dev) pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", dev->name, phy_dev->drv->name, - phy_dev->dev.bus_id, phy_dev->irq); + dev_name(&phy_dev->dev), phy_dev->irq); sc->phy_dev = phy_dev; @@ -2697,7 +2697,7 @@ static int __init sbmac_probe(struct platform_device *pldev) sbm_base = ioremap_nocache(res->start, res->end - res->start + 1); if (!sbm_base) { printk(KERN_ERR "%s: unable to map device registers\n", - pldev->dev.bus_id); + dev_name(&pldev->dev)); err = -ENOMEM; goto out_out; } @@ -2708,7 +2708,7 @@ static int __init sbmac_probe(struct platform_device *pldev) * If we find a zero, skip this MAC. */ sbmac_orig_hwaddr = __raw_readq(sbm_base + R_MAC_ETHERNET_ADDR); - pr_debug("%s: %sconfiguring MAC at 0x%08Lx\n", pldev->dev.bus_id, + pr_debug("%s: %sconfiguring MAC at 0x%08Lx\n", dev_name(&pldev->dev), sbmac_orig_hwaddr ? "" : "not ", (long long)res->start); if (sbmac_orig_hwaddr == 0) { err = 0; @@ -2721,7 +2721,7 @@ static int __init sbmac_probe(struct platform_device *pldev) dev = alloc_etherdev(sizeof(struct sbmac_softc)); if (!dev) { printk(KERN_ERR "%s: unable to allocate etherdev\n", - pldev->dev.bus_id); + dev_name(&pldev->dev)); err = -ENOMEM; goto out_unmap; } diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 223cde0d43b..293610334a7 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -1545,7 +1545,7 @@ smc911x_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { strncpy(info->driver, CARDNAME, sizeof(info->driver)); strncpy(info->version, version, sizeof(info->version)); - strncpy(info->bus_info, dev->dev.parent->bus_id, sizeof(info->bus_info)); + strncpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info)); } static int smc911x_ethtool_nwayreset(struct net_device *dev) diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index b215a8d85e6..0b6da950144 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -1614,7 +1614,7 @@ smc_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { strncpy(info->driver, CARDNAME, sizeof(info->driver)); strncpy(info->version, version, sizeof(info->version)); - strncpy(info->bus_info, dev->dev.parent->bus_id, sizeof(info->bus_info)); + strncpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info)); } static int smc_ethtool_nwayreset(struct net_device *dev) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index d1590ac55e4..ab18ee0f60f 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -769,7 +769,7 @@ static int smsc911x_mii_probe(struct net_device *dev) return -ENODEV; } - phydev = phy_connect(dev, phydev->dev.bus_id, + phydev = phy_connect(dev, dev_name(&phydev->dev), &smsc911x_phy_adjust_link, 0, pdata->config.phy_interface); if (IS_ERR(phydev)) { @@ -778,7 +778,8 @@ static int smsc911x_mii_probe(struct net_device *dev) } pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", - dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq); + dev->name, phydev->drv->name, + dev_name(&phydev->dev), phydev->irq); /* mask with MAC supported features */ phydev->supported &= (PHY_BASIC_FEATURES | SUPPORTED_Pause | @@ -1549,7 +1550,7 @@ static void smsc911x_ethtool_getdrvinfo(struct net_device *dev, { strlcpy(info->driver, SMSC_CHIPNAME, sizeof(info->driver)); strlcpy(info->version, SMSC_DRV_VERSION, sizeof(info->version)); - strlcpy(info->bus_info, dev->dev.parent->bus_id, + strlcpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info)); } diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c index 4e15ae068b3..72f1348eb80 100644 --- a/drivers/net/smsc9420.c +++ b/drivers/net/smsc9420.c @@ -1160,7 +1160,7 @@ static int smsc9420_mii_probe(struct net_device *dev) smsc_info(PROBE, "PHY addr %d, phy_id 0x%08X", phydev->addr, phydev->phy_id); - phydev = phy_connect(dev, phydev->dev.bus_id, + phydev = phy_connect(dev, dev_name(&phydev->dev), &smsc9420_phy_adjust_link, 0, PHY_INTERFACE_MODE_MII); if (IS_ERR(phydev)) { @@ -1169,7 +1169,7 @@ static int smsc9420_mii_probe(struct net_device *dev) } pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", - dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq); + dev->name, phydev->drv->name, dev_name(&phydev->dev), phydev->irq); /* mask with MAC supported features */ phydev->supported &= (PHY_BASIC_FEATURES | SUPPORTED_Pause | diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index bcd0e60cbda..e1f8eb96a45 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -725,7 +725,7 @@ static int tc_mii_probe(struct net_device *dev) } /* attach the mac to the phy */ - phydev = phy_connect(dev, phydev->dev.bus_id, + phydev = phy_connect(dev, dev_name(&phydev->dev), &tc_handle_link_change, 0, lp->chiptype == TC35815_TX4939 ? PHY_INTERFACE_MODE_RMII : PHY_INTERFACE_MODE_MII); @@ -735,7 +735,7 @@ static int tc_mii_probe(struct net_device *dev) } printk(KERN_INFO "%s: attached PHY driver [%s] " "(mii_bus:phy_addr=%s, id=%x)\n", - dev->name, phydev->drv->name, phydev->dev.bus_id, + dev->name, phydev->drv->name, dev_name(&phydev->dev), phydev->phy_id); /* mask with MAC supported features */ diff --git a/drivers/net/xtsonic.c b/drivers/net/xtsonic.c index 03a3f34e903..a12a7211c98 100644 --- a/drivers/net/xtsonic.c +++ b/drivers/net/xtsonic.c @@ -183,7 +183,7 @@ static int __init sonic_probe1(struct net_device *dev) if (lp->descriptors == NULL) { printk(KERN_ERR "%s: couldn't alloc DMA memory for " - " descriptors.\n", lp->device->bus_id); + " descriptors.\n", dev_name(lp->device)); goto out; } -- GitLab From 2ead054cd26752c7ce47dfbf320dd021ef70682d Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:22 -0700 Subject: [PATCH 4405/4982] drm: struct device - replace bus_id with dev_name(), dev_set_name() Cc: airlied@linux.ie Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/gpu/drm/drm_sysfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 5aa6780652a..186d08159d4 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -359,8 +359,8 @@ int drm_sysfs_connector_add(struct drm_connector *connector) DRM_DEBUG("adding \"%s\" to sysfs\n", drm_get_connector_name(connector)); - snprintf(connector->kdev.bus_id, BUS_ID_SIZE, "card%d-%s", - dev->primary->index, drm_get_connector_name(connector)); + dev_set_name(&connector->kdev, "card%d-%s", + dev->primary->index, drm_get_connector_name(connector)); ret = device_register(&connector->kdev); if (ret) { -- GitLab From c3ef01ce4f73f41e99b2a5f0796f1f1a1daaaaa2 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:22 -0700 Subject: [PATCH 4406/4982] v4l: struct device - replace bus_id with dev_name(), dev_set_name() Cc: mchehab@infradead.org Cc: linux-media@vger.kernel.org Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/media/radio/radio-tea5764.c | 3 ++- drivers/media/video/v4l2-device.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index 4d35308fc1f..393623818ad 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c @@ -298,7 +298,8 @@ static int vidioc_querycap(struct file *file, void *priv, strlcpy(v->driver, dev->dev.driver->name, sizeof(v->driver)); strlcpy(v->card, dev->name, sizeof(v->card)); - snprintf(v->bus_info, sizeof(v->bus_info), "I2C:%s", dev->dev.bus_id); + snprintf(v->bus_info, sizeof(v->bus_info), + "I2C:%s", dev_name(&dev->dev)); v->version = RADIO_VERSION; v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c index cf9d4c7f571..8a4b74f3129 100644 --- a/drivers/media/video/v4l2-device.c +++ b/drivers/media/video/v4l2-device.c @@ -34,7 +34,7 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev) spin_lock_init(&v4l2_dev->lock); v4l2_dev->dev = dev; snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s", - dev->driver->name, dev->bus_id); + dev->driver->name, dev_name(dev)); dev_set_drvdata(dev, v4l2_dev); return 0; } -- GitLab From 9d6b4c82bffbe6de624ff86cb279166867f46365 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:22 -0700 Subject: [PATCH 4407/4982] amba: struct device - replace bus_id with dev_name(), dev_set_name() Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/amba/bus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index 00c46e0b40e..3d763fdf99b 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -210,7 +210,7 @@ int amba_device_register(struct amba_device *dev, struct resource *parent) dev->dev.release = amba_device_release; dev->dev.bus = &amba_bustype; dev->dev.dma_mask = &dev->dma_mask; - dev->res.name = dev->dev.bus_id; + dev->res.name = dev_name(&dev->dev); if (!dev->dev.coherent_dma_mask && dev->dma_mask) dev_warn(&dev->dev, "coherent dma mask is unset\n"); @@ -294,7 +294,7 @@ static int amba_find_match(struct device *dev, void *data) if (d->parent) r &= d->parent == dev->parent; if (d->busid) - r &= strcmp(dev->bus_id, d->busid) == 0; + r &= strcmp(dev_name(dev), d->busid) == 0; if (r) { get_device(dev); -- GitLab From 9591463af7ea3a2d723c7e39c08aa05ad27e7bfc Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:22 -0700 Subject: [PATCH 4408/4982] dio: struct device - replace bus_id with dev_name(), dev_set_name() Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/dio/dio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/dio/dio.c b/drivers/dio/dio.c index 10c3c498358..55dd88d82d6 100644 --- a/drivers/dio/dio.c +++ b/drivers/dio/dio.c @@ -182,7 +182,7 @@ static int __init dio_init(void) /* Initialize the DIO bus */ INIT_LIST_HEAD(&dio_bus.devices); - strcpy(dio_bus.dev.bus_id, "dio"); + dev_set_name(&dio_bus.dev, "dio"); error = device_register(&dio_bus.dev); if (error) { pr_err("DIO: Error registering dio_bus\n"); @@ -237,7 +237,7 @@ static int __init dio_init(void) dev->scode = scode; dev->resource.start = pa; dev->resource.end = pa + DIO_SIZE(scode, va); - sprintf(dev->dev.bus_id,"%02x", scode); + dev_set_name(&dev->dev, "%02x", scode); /* read the ID byte(s) and encode if necessary. */ prid = DIO_ID(va); -- GitLab From dfbc90196dfb9a814e7f2e1f4c47aa425452d313 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:22 -0700 Subject: [PATCH 4409/4982] dma: struct device - replace bus_id with dev_name(), dev_set_name() Cc: Dan Williams Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/dma/dw_dmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index a97c07eef7e..20ad3d26bec 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -1011,7 +1011,7 @@ static int __init dw_probe(struct platform_device *pdev) dma_writel(dw, CFG, DW_CFG_DMA_EN); printk(KERN_INFO "%s: DesignWare DMA Controller, %d channels\n", - pdev->dev.bus_id, dw->dma.chancnt); + dev_name(&pdev->dev), dw->dma.chancnt); dma_async_device_register(&dw->dma); -- GitLab From e537b2453ccf8884513201d6afcb62ca0763ecf0 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:22 -0700 Subject: [PATCH 4410/4982] eisa: struct device - replace bus_id with dev_name(), dev_set_name() Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/eisa/eisa-bus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c index c950bf8606d..66958b3f10b 100644 --- a/drivers/eisa/eisa-bus.c +++ b/drivers/eisa/eisa-bus.c @@ -200,7 +200,7 @@ static int __init eisa_init_device (struct eisa_root_device *root, edev->dev.bus = &eisa_bus_type; edev->dev.dma_mask = &edev->dma_mask; edev->dev.coherent_dma_mask = edev->dma_mask; - sprintf (edev->dev.bus_id, "%02X:%02X", root->bus_nr, slot); + dev_set_name(&edev->dev, "%02X:%02X", root->bus_nr, slot); for (i = 0; i < EISA_MAX_RESOURCES; i++) { #ifdef CONFIG_EISA_NAMES @@ -301,7 +301,7 @@ static int __init eisa_probe (struct eisa_root_device *root) struct eisa_device *edev; printk (KERN_INFO "EISA: Probing bus %d at %s\n", - root->bus_nr, root->dev->bus_id); + root->bus_nr, dev_name(root->dev)); /* First try to get hold of slot 0. If there is no device * here, simply fail, unless root->force_probe is set. */ -- GitLab From 3e274bd02b04064632492a86fe99d3b613c74d84 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:23 -0700 Subject: [PATCH 4411/4982] gpio: struct device - replace bus_id with dev_name(), dev_set_name() Cc: Michael Buesch Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/gpio/bt8xxgpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/bt8xxgpio.c b/drivers/gpio/bt8xxgpio.c index 7a1168249dd..984b587f0f9 100644 --- a/drivers/gpio/bt8xxgpio.c +++ b/drivers/gpio/bt8xxgpio.c @@ -160,7 +160,7 @@ static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg) { struct gpio_chip *c = &bg->gpio; - c->label = bg->pdev->dev.bus_id; + c->label = dev_name(&bg->pdev->dev); c->owner = THIS_MODULE; c->direction_input = bt8xxgpio_gpio_direction_input; c->get = bt8xxgpio_gpio_get; -- GitLab From cf43f4ab3a065296822bb245975d006707ccde8d Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:23 -0700 Subject: [PATCH 4412/4982] mca: struct device - replace bus_id with dev_name(), dev_set_name() Cc: James.Bottomley@HansenPartnership.com Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/mca/mca-bus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mca/mca-bus.c b/drivers/mca/mca-bus.c index ef2dbfe7471..ada5ebbaa25 100644 --- a/drivers/mca/mca-bus.c +++ b/drivers/mca/mca-bus.c @@ -110,7 +110,7 @@ int __init mca_register_device(int bus, struct mca_device *mca_dev) mca_dev->dev.parent = &mca_bus->dev; mca_dev->dev.bus = &mca_bus_type; - sprintf (mca_dev->dev.bus_id, "%02d:%02X", bus, mca_dev->slot); + dev_set_name(&mca_dev->dev, "%02d:%02X", bus, mca_dev->slot); mca_dev->dma_mask = mca_bus->default_dma_mask; mca_dev->dev.dma_mask = &mca_dev->dma_mask; mca_dev->dev.coherent_dma_mask = mca_dev->dma_mask; @@ -151,7 +151,7 @@ struct mca_bus * __devinit mca_attach_bus(int bus) if (!mca_bus) return NULL; - sprintf(mca_bus->dev.bus_id,"mca%d",bus); + dev_set_name(&mca_bus->dev, "mca%d", bus); sprintf(mca_bus->name,"Host %s MCA Bridge", bus ? "Secondary" : "Primary"); if (device_register(&mca_bus->dev)) { kfree(mca_bus); -- GitLab From b2bf61f23f74d5b5aa35f242a2fe2f08ce4a53e7 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:23 -0700 Subject: [PATCH 4413/4982] mfd: struct device - replace bus_id with dev_name(), dev_set_name() Cc: sameo@openedhand.com Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/mfd/mcp-core.c | 2 +- drivers/mfd/ucb1x00-core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c index 6063dc2b52e..57271cb3b31 100644 --- a/drivers/mfd/mcp-core.c +++ b/drivers/mfd/mcp-core.c @@ -214,7 +214,7 @@ EXPORT_SYMBOL(mcp_host_alloc); int mcp_host_register(struct mcp *mcp) { - strcpy(mcp->attached_device.bus_id, "mcp0"); + dev_set_name(&mcp->attached_device, "mcp0"); return device_register(&mcp->attached_device); } EXPORT_SYMBOL(mcp_host_register); diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c index 6860c924f36..fea9085fe52 100644 --- a/drivers/mfd/ucb1x00-core.c +++ b/drivers/mfd/ucb1x00-core.c @@ -492,7 +492,7 @@ static int ucb1x00_probe(struct mcp *mcp) ucb->dev.class = &ucb1x00_class; ucb->dev.parent = &mcp->attached_device; - strlcpy(ucb->dev.bus_id, "ucb1x00", sizeof(ucb->dev.bus_id)); + dev_set_name(&ucb->dev, "ucb1x00"); spin_lock_init(&ucb->lock); spin_lock_init(&ucb->io_lock); -- GitLab From 2c0f3e96f3fc7bbd1cb3caa601f19cf030c2b958 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:23 -0700 Subject: [PATCH 4414/4982] wimax: struct device - replace bus_id with dev_name(), dev_set_name() Cc: inaky.perez-gonzalez@intel.com Cc: linux-wimax@intel.com Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/net/wimax/i2400m/driver.c | 2 +- drivers/net/wimax/i2400m/usb-notif.c | 2 +- include/linux/wimax/debug.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c index e80a0b65a75..d58b971faa6 100644 --- a/drivers/net/wimax/i2400m/driver.c +++ b/drivers/net/wimax/i2400m/driver.c @@ -613,7 +613,7 @@ int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags) d_fnstart(3, dev, "(i2400m %p)\n", i2400m); snprintf(wimax_dev->name, sizeof(wimax_dev->name), - "i2400m-%s:%s", dev->bus->name, dev->bus_id); + "i2400m-%s:%s", dev->bus->name, dev_name(dev)); i2400m->bm_cmd_buf = kzalloc(I2400M_BM_CMD_BUF_SIZE, GFP_KERNEL); if (i2400m->bm_cmd_buf == NULL) { diff --git a/drivers/net/wimax/i2400m/usb-notif.c b/drivers/net/wimax/i2400m/usb-notif.c index 9702c22b249..0528879f6d3 100644 --- a/drivers/net/wimax/i2400m/usb-notif.c +++ b/drivers/net/wimax/i2400m/usb-notif.c @@ -102,7 +102,7 @@ int i2400mu_notification_grok(struct i2400mu *i2400mu, const void *buf, dev_err(dev, "HW BUG? Unknown/unexpected data in notification " "message (%zu bytes)\n", buf_len); snprintf(prefix, sizeof(prefix), "%s %s: ", - dev_driver_string(dev) , dev->bus_id); + dev_driver_string(dev) , dev_name(dev)); if (buf_len > 64) { print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 8, 4, buf, 64, 0); diff --git a/include/linux/wimax/debug.h b/include/linux/wimax/debug.h index ba0c49399a8..c703e034042 100644 --- a/include/linux/wimax/debug.h +++ b/include/linux/wimax/debug.h @@ -178,7 +178,7 @@ void __d_head(char *head, size_t head_size, WARN_ON(1); } else snprintf(head, head_size, "%s %s: ", - dev_driver_string(dev), dev->bus_id); + dev_driver_string(dev), dev_name(dev)); } -- GitLab From 5df5852446196c9713e897ab5f9b8a168d971a00 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:23 -0700 Subject: [PATCH 4415/4982] usb: struct device - replace bus_id with dev_name(), dev_set_name() Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/usb/gadget/ci13xxx_udc.c | 2 +- drivers/usb/gadget/imx_udc.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c index bebf911c7e5..7f4e5eb1dc8 100644 --- a/drivers/usb/gadget/ci13xxx_udc.c +++ b/drivers/usb/gadget/ci13xxx_udc.c @@ -2626,7 +2626,7 @@ static int udc_probe(struct device *dev, void __iomem *regs, const char *name) INIT_LIST_HEAD(&udc->gadget.ep_list); udc->gadget.ep0 = NULL; - strcpy(udc->gadget.dev.bus_id, "gadget"); + dev_set_name(&udc->gadget.dev, "gadget"); udc->gadget.dev.dma_mask = dev->dma_mask; udc->gadget.dev.parent = dev; udc->gadget.dev.release = udc_release; diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index 77c5d0a8a06..cd67ac75e62 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -1186,8 +1186,8 @@ static struct imx_udc_struct controller = { .ep0 = &controller.imx_ep[0].ep, .name = driver_name, .dev = { - .bus_id = "gadget", - }, + .init_name = "gadget", + }, }, .imx_ep[0] = { -- GitLab From 54ca5412b5576fdb0a4ea4fedf6565bd6f34150c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 26 Jan 2009 09:12:12 -0800 Subject: [PATCH 4416/4982] PS3: replace bus_id usage These simple debug statments should be using dev_dbg() instead of accessing bus_id directly (or they should use device_name). As bus_id is going away, this patch is necessary. Acked-by: Geoff Levand Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/platforms/ps3/system-bus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c index 58311a86785..a705fffbb49 100644 --- a/arch/powerpc/platforms/ps3/system-bus.c +++ b/arch/powerpc/platforms/ps3/system-bus.c @@ -376,7 +376,7 @@ static int ps3_system_bus_probe(struct device *_dev) struct ps3_system_bus_driver *drv; BUG_ON(!dev); - pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id); + dev_dbg(_dev, "%s:%d\n", __func__, __LINE__); drv = ps3_system_bus_dev_to_system_bus_drv(dev); BUG_ON(!drv); @@ -398,7 +398,7 @@ static int ps3_system_bus_remove(struct device *_dev) struct ps3_system_bus_driver *drv; BUG_ON(!dev); - pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id); + dev_dbg(_dev, "%s:%d\n", __func__, __LINE__); drv = ps3_system_bus_dev_to_system_bus_drv(dev); BUG_ON(!drv); -- GitLab From 6866ac9db02ac1ec71f2aa720a1019581f69a725 Mon Sep 17 00:00:00 2001 From: Sachin Sant Date: Mon, 16 Feb 2009 19:10:11 +0530 Subject: [PATCH 4417/4982] USB: FHCI: use dev_name() in place of bus_id. Replace references to bus_id with dev_name() to fix fhci driver build break. drivers/usb/host/fhci-hcd.c:586: error: struct device has no member named bus_id drivers/usb/host/fhci-hcd.c:653: error: struct device has no member named bus_id drivers/usb/host/fhci-dbg.c:111: error: struct device has no member named bus_id Signed-off-by: Sachin Sant Acked-by: Anton Vorontsov Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/fhci-dbg.c | 2 +- drivers/usb/host/fhci-hcd.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/fhci-dbg.c b/drivers/usb/host/fhci-dbg.c index 34e14edf390..ea8a4255c5d 100644 --- a/drivers/usb/host/fhci-dbg.c +++ b/drivers/usb/host/fhci-dbg.c @@ -108,7 +108,7 @@ void fhci_dfs_create(struct fhci_hcd *fhci) { struct device *dev = fhci_to_hcd(fhci)->self.controller; - fhci->dfs_root = debugfs_create_dir(dev->bus_id, NULL); + fhci->dfs_root = debugfs_create_dir(dev_name(dev), NULL); if (!fhci->dfs_root) { WARN_ON(1); return; diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c index ba622cc8a9b..0951818ef93 100644 --- a/drivers/usb/host/fhci-hcd.c +++ b/drivers/usb/host/fhci-hcd.c @@ -583,7 +583,7 @@ static int __devinit of_fhci_probe(struct of_device *ofdev, if (sprop && strcmp(sprop, "host")) return -ENODEV; - hcd = usb_create_hcd(&fhci_driver, dev, dev->bus_id); + hcd = usb_create_hcd(&fhci_driver, dev, dev_name(dev)); if (!hcd) { dev_err(dev, "could not create hcd\n"); return -ENOMEM; @@ -650,7 +650,7 @@ static int __devinit of_fhci_probe(struct of_device *ofdev, } } - ret = gpio_request(gpio, dev->bus_id); + ret = gpio_request(gpio, dev_name(dev)); if (ret) { dev_err(dev, "failed to request gpio %d", i); goto err_gpios; -- GitLab From 1fa5ae857bb14f6046205171d98506d8112dd74e Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Sun, 25 Jan 2009 15:17:37 +0100 Subject: [PATCH 4418/4982] driver core: get rid of struct device's bus_id string array Now that all users of bus_id is gone, we can remove it from struct device. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 39 +++++++++++++++++++-------------------- include/linux/device.h | 4 +--- include/linux/kobject.h | 2 ++ lib/kobject.c | 2 +- 4 files changed, 23 insertions(+), 24 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index f3eae630e58..059966b617f 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -777,17 +777,12 @@ static void device_remove_class_symlinks(struct device *dev) int dev_set_name(struct device *dev, const char *fmt, ...) { va_list vargs; - char *s; + int err; va_start(vargs, fmt); - vsnprintf(dev->bus_id, sizeof(dev->bus_id), fmt, vargs); + err = kobject_set_name_vargs(&dev->kobj, fmt, vargs); va_end(vargs); - - /* ewww... some of these buggers have / in the name... */ - while ((s = strchr(dev->bus_id, '/'))) - *s = '!'; - - return 0; + return err; } EXPORT_SYMBOL_GPL(dev_set_name); @@ -864,12 +859,17 @@ int device_add(struct device *dev) if (!dev) goto done; - /* Temporarily support init_name if it is set. - * It will override bus_id for now */ - if (dev->init_name) - dev_set_name(dev, "%s", dev->init_name); + /* + * for statically allocated devices, which should all be converted + * some day, we need to initialize the name. We prevent reading back + * the name, and force the use of dev_name() + */ + if (dev->init_name) { + dev_set_name(dev, dev->init_name); + dev->init_name = NULL; + } - if (!strlen(dev->bus_id)) + if (!dev_name(dev)) goto done; pr_debug("device: '%s': %s\n", dev_name(dev), __func__); @@ -1348,7 +1348,10 @@ struct device *device_create_vargs(struct class *class, struct device *parent, dev->release = device_create_release; dev_set_drvdata(dev, drvdata); - vsnprintf(dev->bus_id, BUS_ID_SIZE, fmt, args); + retval = kobject_set_name_vargs(&dev->kobj, fmt, args); + if (retval) + goto error; + retval = device_register(dev); if (retval) goto error; @@ -1452,19 +1455,15 @@ int device_rename(struct device *dev, char *new_name) old_class_name = make_class_name(dev->class->name, &dev->kobj); #endif - old_device_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL); + old_device_name = kstrdup(dev_name(dev), GFP_KERNEL); if (!old_device_name) { error = -ENOMEM; goto out; } - strlcpy(old_device_name, dev->bus_id, BUS_ID_SIZE); - strlcpy(dev->bus_id, new_name, BUS_ID_SIZE); error = kobject_rename(&dev->kobj, new_name); - if (error) { - strlcpy(dev->bus_id, old_device_name, BUS_ID_SIZE); + if (error) goto out; - } #ifdef CONFIG_SYSFS_DEPRECATED if (old_class_name) { diff --git a/include/linux/device.h b/include/linux/device.h index 47f343c7bdd..d5706c448bc 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -374,7 +374,6 @@ struct device { struct device *parent; struct kobject kobj; - char bus_id[BUS_ID_SIZE]; /* position on parent bus */ unsigned uevent_suppress:1; const char *init_name; /* initial name of the device */ struct device_type *type; @@ -427,8 +426,7 @@ struct device { static inline const char *dev_name(const struct device *dev) { - /* will be changed into kobject_name(&dev->kobj) in the near future */ - return dev->bus_id; + return kobject_name(&dev->kobj); } extern int dev_set_name(struct device *dev, const char *name, ...) diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 5437ac0276e..c9c214d7bba 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -72,6 +72,8 @@ struct kobject { extern int kobject_set_name(struct kobject *kobj, const char *name, ...) __attribute__((format(printf, 2, 3))); +extern int kobject_set_name_vargs(struct kobject *kobj, const char *fmt, + va_list vargs); static inline const char *kobject_name(const struct kobject *kobj) { diff --git a/lib/kobject.c b/lib/kobject.c index 0487d1f6480..a6dec32f2dd 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -212,7 +212,7 @@ static int kobject_add_internal(struct kobject *kobj) * @fmt: format string used to build the name * @vargs: vargs to format the string. */ -static int kobject_set_name_vargs(struct kobject *kobj, const char *fmt, +int kobject_set_name_vargs(struct kobject *kobj, const char *fmt, va_list vargs) { const char *old_name = kobj->name; -- GitLab From 8231f2f99a5e5fc45a25e8de09fd1ab9711babf1 Mon Sep 17 00:00:00 2001 From: Qinghuang Feng Date: Wed, 14 Jan 2009 15:45:13 +0800 Subject: [PATCH 4419/4982] SYSFS: use standard magic.h for sysfs SYSFS_MAGIC has been added into magic.h, so only use that definition in magic.h to avoid potential consistency problem. Signed-off-by: Qinghuang Feng Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/mount.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index ab343e371d6..8133ca36ee0 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -17,11 +17,10 @@ #include #include #include +#include #include "sysfs.h" -/* Random magic number */ -#define SYSFS_MAGIC 0x62656572 static struct vfsmount *sysfs_mount; struct super_block * sysfs_sb = NULL; -- GitLab From 4a67a1bc0b3a0db017b560cee27370d141c58e25 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 21 Jan 2009 11:55:11 -0800 Subject: [PATCH 4420/4982] sysfs: Take sysfs_mutex when fetching the root inode. sysfs_get_inode ultimately calls sysfs_count_nlink when the a directory inode is fectched. sysfs_count_nlink needs to be called under the sysfs_mutex to guard against the unlikely but possible scenario that the root directory is changing as we are counting the number entries in it, and just in general to be consistent. Signed-off-by: Eric W. Biederman Acked-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/mount.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 8133ca36ee0..84ef378673a 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -52,7 +52,9 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) sysfs_sb = sb; /* get root inode, initialize and unlock it */ + mutex_lock(&sysfs_mutex); inode = sysfs_get_inode(&sysfs_root); + mutex_unlock(&sysfs_mutex); if (!inode) { pr_debug("sysfs: could not get root inode\n"); return -ENOMEM; -- GitLab From 49b420a13ff95b449947181190b08367348e3e1b Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Wed, 21 Jan 2009 23:27:47 +0800 Subject: [PATCH 4421/4982] driver core: check bus->match without holding device lock This patch moves bus->match out from driver_probe_device and does not hold device lock to check the match between a device and a driver. The idea has been verified by the commit 6cd495860901, which leads to a faster boot. But the commit 6cd495860901 has the following drawbacks: 1),only does the quick check in the path of __driver_attach->driver_probe_device, not in other paths; 2),for a matched device and driver, check the same match twice. It is a waste of cpu ,especially for some drivers with long device id table (eg. usb-storage driver). This patch adds a helper of driver_match_device to check the match in all paths, and testes the match only once. Signed-off-by: Ming Lei Acked-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 5 +++++ drivers/base/bus.c | 2 +- drivers/base/dd.c | 19 +++++++------------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/base/base.h b/drivers/base/base.h index 9f50f1b545d..ca2b0376685 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -86,6 +86,11 @@ extern void bus_remove_driver(struct device_driver *drv); extern void driver_detach(struct device_driver *drv); extern int driver_probe_device(struct device_driver *drv, struct device *dev); +static inline int driver_match_device(struct device_driver *drv, + struct device *dev) +{ + return drv->bus->match && drv->bus->match(dev, drv); +} extern void sysdev_shutdown(void); diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 83f32b891fa..8547b780bb5 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -198,7 +198,7 @@ static ssize_t driver_bind(struct device_driver *drv, int err = -ENODEV; dev = bus_find_device_by_name(bus, NULL, buf); - if (dev && dev->driver == NULL) { + if (dev && dev->driver == NULL && driver_match_device(drv, dev)) { if (dev->parent) /* Needed for USB */ down(&dev->parent->sem); down(&dev->sem); diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 13523123910..3f32df7ed37 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -189,14 +189,8 @@ int wait_for_device_probe(void) * @drv: driver to bind a device to * @dev: device to try to bind to the driver * - * First, we call the bus's match function, if one present, which should - * compare the device IDs the driver supports with the device IDs of the - * device. Note we don't do this ourselves because we don't know the - * format of the ID structures, nor what is to be considered a match and - * what is not. - * - * This function returns 1 if a match is found, -ENODEV if the device is - * not registered, and 0 otherwise. + * This function returns -ENODEV if the device is not registered, + * 1 if the device is bound sucessfully and 0 otherwise. * * This function must be called with @dev->sem held. When called for a * USB interface, @dev->parent->sem must be held as well. @@ -207,21 +201,22 @@ int driver_probe_device(struct device_driver *drv, struct device *dev) if (!device_is_registered(dev)) return -ENODEV; - if (drv->bus->match && !drv->bus->match(dev, drv)) - goto done; pr_debug("bus: '%s': %s: matched device %s with driver %s\n", drv->bus->name, __func__, dev_name(dev), drv->name); ret = really_probe(dev, drv); -done: return ret; } static int __device_attach(struct device_driver *drv, void *data) { struct device *dev = data; + + if (!driver_match_device(drv, dev)) + return 0; + return driver_probe_device(drv, dev); } @@ -274,7 +269,7 @@ static int __driver_attach(struct device *dev, void *data) * is an error. */ - if (drv->bus->match && !drv->bus->match(dev, drv)) + if (!driver_match_device(drv, dev)) return 0; if (dev->parent) /* Needed for USB */ -- GitLab From 71b3e0c1ad90f28e34c105069175cbd4edb43dfa Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Sat, 31 Jan 2009 22:47:44 +0800 Subject: [PATCH 4422/4982] platform: make better use of to_platform_{device,driver}() macros This helps the code look more consistent and cleaner. Signed-off-by: Eric Miao Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 21 +++++++++------------ drivers/block/floppy.c | 3 +-- drivers/isdn/gigaset/ser-gigaset.c | 3 +-- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 349a1013603..62a8768d96b 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -603,9 +603,8 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) */ static int platform_match(struct device *dev, struct device_driver *drv) { - struct platform_device *pdev; + struct platform_device *pdev = to_platform_device(dev); - pdev = container_of(dev, struct platform_device, dev); return (strcmp(pdev->name, drv->name) == 0); } @@ -623,26 +622,24 @@ static int platform_legacy_suspend(struct device *dev, pm_message_t mesg) static int platform_legacy_suspend_late(struct device *dev, pm_message_t mesg) { - struct platform_driver *drv = to_platform_driver(dev->driver); - struct platform_device *pdev; + struct platform_driver *pdrv = to_platform_driver(dev->driver); + struct platform_device *pdev = to_platform_device(dev); int ret = 0; - pdev = container_of(dev, struct platform_device, dev); - if (dev->driver && drv->suspend_late) - ret = drv->suspend_late(pdev, mesg); + if (dev->driver && pdrv->suspend_late) + ret = pdrv->suspend_late(pdev, mesg); return ret; } static int platform_legacy_resume_early(struct device *dev) { - struct platform_driver *drv = to_platform_driver(dev->driver); - struct platform_device *pdev; + struct platform_driver *pdrv = to_platform_driver(dev->driver); + struct platform_device *pdev = to_platform_device(dev); int ret = 0; - pdev = container_of(dev, struct platform_device, dev); - if (dev->driver && drv->resume_early) - ret = drv->resume_early(pdev); + if (dev->driver && pdrv->resume_early) + ret = pdrv->resume_early(pdev); return ret; } diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 83d8ed39433..c2c95e61450 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4135,10 +4135,9 @@ static int have_no_fdc = -ENODEV; static ssize_t floppy_cmos_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct platform_device *p; + struct platform_device *p = to_platform_device(dev); int drive; - p = container_of(dev, struct platform_device,dev); drive = p->id; return sprintf(buf, "%X\n", UDP->cmos); } diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index ac245e7e96a..3071a52467e 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c @@ -389,8 +389,7 @@ static void gigaset_freecshw(struct cardstate *cs) static void gigaset_device_release(struct device *dev) { - struct platform_device *pdev = - container_of(dev, struct platform_device, dev); + struct platform_device *pdev = to_platform_device(dev); /* adapted from platform_device_release() in drivers/base/platform.c */ //FIXME is this actually necessary? -- GitLab From 57fee4a58fe802272742caae248872c392a60670 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Wed, 4 Feb 2009 11:52:40 +0800 Subject: [PATCH 4423/4982] platform: introduce module id table for platform devices Now platform_device is being widely used on SoC processors where the peripherals are attached to the system bus, which is simple enough. However, silicon IPs for these SoCs are usually shared heavily across a family of processors, even products from different companies. This makes the original simple driver name based matching insufficient, or simply not straight-forward. Introduce a module id table for platform devices, and makes it clear that a platform driver is able to support some shared IP and handle slight differences across different platforms (by 'driver_data'). Module alias is handled automatically when a MODULE_DEVICE_TABLE() is defined. To not disturb the current platform drivers too much, the matched id entry is recorded and can be retrieved by platform_get_device_id(). Signed-off-by: Eric Miao Cc: Kay Sievers Cc: Ben Dooks Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 23 ++++++++++++++++++++++- include/linux/mod_devicetable.h | 9 +++++++++ include/linux/platform_device.h | 6 ++++++ scripts/mod/file2alias.c | 12 ++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 62a8768d96b..ec993aa6a2c 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -584,10 +584,25 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) { struct platform_device *pdev = to_platform_device(dev); - add_uevent_var(env, "MODALIAS=platform:%s", pdev->name); + add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX, + (pdev->id_entry) ? pdev->id_entry->name : pdev->name); return 0; } +static const struct platform_device_id *platform_match_id( + struct platform_device_id *id, + struct platform_device *pdev) +{ + while (id->name[0]) { + if (strcmp(pdev->name, id->name) == 0) { + pdev->id_entry = id; + return id; + } + id++; + } + return NULL; +} + /** * platform_match - bind platform device to platform driver. * @dev: device. @@ -604,7 +619,13 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) static int platform_match(struct device *dev, struct device_driver *drv) { struct platform_device *pdev = to_platform_device(dev); + struct platform_driver *pdrv = to_platform_driver(drv); + + /* match against the id table first */ + if (pdrv->id_table) + return platform_match_id(pdrv->id_table, pdev) != NULL; + /* fall-back to driver name match */ return (strcmp(pdev->name, drv->name) == 0); } diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index fde86671f48..1bf5900ffe4 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -454,4 +454,13 @@ struct dmi_system_id { #define DMI_MATCH(a, b) { a, b } +#define PLATFORM_NAME_SIZE 20 +#define PLATFORM_MODULE_PREFIX "platform:" + +struct platform_device_id { + char name[PLATFORM_NAME_SIZE]; + kernel_ulong_t driver_data + __attribute__((aligned(sizeof(kernel_ulong_t)))); +}; + #endif /* LINUX_MOD_DEVICETABLE_H */ diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 9a342699c60..76aef7be32a 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -12,6 +12,7 @@ #define _PLATFORM_DEVICE_H_ #include +#include struct platform_device { const char * name; @@ -19,8 +20,12 @@ struct platform_device { struct device dev; u32 num_resources; struct resource * resource; + + struct platform_device_id *id_entry; }; +#define platform_get_device_id(pdev) ((pdev)->id_entry) + #define to_platform_device(x) container_of((x), struct platform_device, dev) extern int platform_device_register(struct platform_device *); @@ -56,6 +61,7 @@ struct platform_driver { int (*resume_early)(struct platform_device *); int (*resume)(struct platform_device *); struct device_driver driver; + struct platform_device_id *id_table; }; extern int platform_driver_register(struct platform_driver *); diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 4eea60b1693..a3344285ccf 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -710,6 +710,14 @@ static int do_dmi_entry(const char *filename, struct dmi_system_id *id, strcat(alias, ":"); return 1; } + +static int do_platform_entry(const char *filename, + struct platform_device_id *id, char *alias) +{ + sprintf(alias, PLATFORM_MODULE_PREFIX "%s", id->name); + return 1; +} + /* Ignore any prefix, eg. some architectures prepend _ */ static inline int sym_is(const char *symbol, const char *name) { @@ -849,6 +857,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, do_table(symval, sym->st_size, sizeof(struct dmi_system_id), "dmi", do_dmi_entry, mod); + else if (sym_is(symname, "__mod_platform_device_table")) + do_table(symval, sym->st_size, + sizeof(struct platform_device_id), "platform", + do_platform_entry, mod); free(zeros); } -- GitLab From 8205779114e8f612549d191f8e151526a74ab9f2 Mon Sep 17 00:00:00 2001 From: "Hans J. Koch" Date: Wed, 7 Jan 2009 00:15:39 +0100 Subject: [PATCH 4424/4982] UIO: Add name attributes for mappings and port regions If a UIO device has several memory mappings, it can be difficult for userspace to find the right one. The situation becomes even worse if the UIO driver can handle different versions of a card that have different numbers of mappings. Benedikt Spranger has such cards and pointed this out to me. Thanks, Bene! To address this problem, this patch adds "name" sysfs attributes for each mapping. Userspace can use these to clearly identify each mapping. The name string is optional. If a driver doesn't set it, an empty string will be returned, so this patch won't break existing drivers. The same problem exists for port region information, so a "name" attribute is added there, too. Signed-off-by: Hans J. Koch Signed-off-by: Greg Kroah-Hartman --- Documentation/DocBook/uio-howto.tmpl | 29 ++++++++++++++++++++++++---- drivers/uio/uio.c | 22 +++++++++++++++++++++ include/linux/uio_driver.h | 4 ++++ 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl index 52e1b79ce0e..8f6e3b2403c 100644 --- a/Documentation/DocBook/uio-howto.tmpl +++ b/Documentation/DocBook/uio-howto.tmpl @@ -41,6 +41,13 @@ GPL version 2. + + 0.8 + 2008-12-24 + hjk + Added name attributes in mem and portio sysfs directories. + + 0.7 2008-12-23 @@ -303,10 +310,17 @@ interested in translating it, please email me appear if the size of the mapping is not 0. - Each mapX/ directory contains two read-only files - that show start address and size of the memory: + Each mapX/ directory contains four read-only files + that show attributes of the memory: + + + name: A string identifier for this mapping. This + is optional, the string can be empty. Drivers can set this to make it + easier for userspace to find the correct mapping. + + addr: The address of memory that can be mapped. @@ -366,10 +380,17 @@ offset = N * getpagesize(); /sys/class/uio/uioX/portio/. - Each portX/ directory contains three read-only - files that show start, size, and type of the port region: + Each portX/ directory contains four read-only + files that show name, start, size, and type of the port region: + + + name: A string identifier for this port region. + The string is optional and can be empty. Drivers can set it to make it + easier for userspace to find a certain port region. + + start: The first port of this region. diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index 4ca85a113aa..68a49655778 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -61,6 +61,14 @@ struct uio_map { }; #define to_map(map) container_of(map, struct uio_map, kobj) +static ssize_t map_name_show(struct uio_mem *mem, char *buf) +{ + if (unlikely(!mem->name)) + mem->name = ""; + + return sprintf(buf, "%s\n", mem->name); +} + static ssize_t map_addr_show(struct uio_mem *mem, char *buf) { return sprintf(buf, "0x%lx\n", mem->addr); @@ -82,6 +90,8 @@ struct map_sysfs_entry { ssize_t (*store)(struct uio_mem *, const char *, size_t); }; +static struct map_sysfs_entry name_attribute = + __ATTR(name, S_IRUGO, map_name_show, NULL); static struct map_sysfs_entry addr_attribute = __ATTR(addr, S_IRUGO, map_addr_show, NULL); static struct map_sysfs_entry size_attribute = @@ -90,6 +100,7 @@ static struct map_sysfs_entry offset_attribute = __ATTR(offset, S_IRUGO, map_offset_show, NULL); static struct attribute *attrs[] = { + &name_attribute.attr, &addr_attribute.attr, &size_attribute.attr, &offset_attribute.attr, @@ -133,6 +144,14 @@ struct uio_portio { }; #define to_portio(portio) container_of(portio, struct uio_portio, kobj) +static ssize_t portio_name_show(struct uio_port *port, char *buf) +{ + if (unlikely(!port->name)) + port->name = ""; + + return sprintf(buf, "%s\n", port->name); +} + static ssize_t portio_start_show(struct uio_port *port, char *buf) { return sprintf(buf, "0x%lx\n", port->start); @@ -159,6 +178,8 @@ struct portio_sysfs_entry { ssize_t (*store)(struct uio_port *, const char *, size_t); }; +static struct portio_sysfs_entry portio_name_attribute = + __ATTR(name, S_IRUGO, portio_name_show, NULL); static struct portio_sysfs_entry portio_start_attribute = __ATTR(start, S_IRUGO, portio_start_show, NULL); static struct portio_sysfs_entry portio_size_attribute = @@ -167,6 +188,7 @@ static struct portio_sysfs_entry portio_porttype_attribute = __ATTR(porttype, S_IRUGO, portio_porttype_show, NULL); static struct attribute *portio_attrs[] = { + &portio_name_attribute.attr, &portio_start_attribute.attr, &portio_size_attribute.attr, &portio_porttype_attribute.attr, diff --git a/include/linux/uio_driver.h b/include/linux/uio_driver.h index a0bb6bd2e5c..5dcc9ff72f6 100644 --- a/include/linux/uio_driver.h +++ b/include/linux/uio_driver.h @@ -22,6 +22,7 @@ struct uio_map; /** * struct uio_mem - description of a UIO memory region + * @name: name of the memory region for identification * @addr: address of the device's memory * @size: size of IO * @memtype: type of memory addr points to @@ -29,6 +30,7 @@ struct uio_map; * @map: for use by the UIO core only. */ struct uio_mem { + const char *name; unsigned long addr; unsigned long size; int memtype; @@ -42,12 +44,14 @@ struct uio_portio; /** * struct uio_port - description of a UIO port region + * @name: name of the port region for identification * @start: start of port region * @size: size of port region * @porttype: type of port (see UIO_PORT_* below) * @portio: for use by the UIO core only. */ struct uio_port { + const char *name; unsigned long start; unsigned long size; int porttype; -- GitLab From 1bafeb378e915f39b1bf44ee0871823d6f402ea5 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Tue, 27 Jan 2009 13:00:04 -0800 Subject: [PATCH 4425/4982] uio: add the uio_aec driver UIO driver for the Adrienne Electronics Corporation PCI time code device. This device differs from other UIO devices since it uses I/O ports instead of memory mapped I/O. In order to make it possible for UIO to work with this device a utility, uioport, can be used to read and write the ports. uioport is designed to be a setuid program and checks the permissions of the /dev/uio* node and if the user has write permissions it will use iopl and out*/in* to access the device. [1] git clone git://ifup.org/philips/uioport.git Signed-off-by: Brandon Philips Signed-off-by: Hans J. Koch Signed-off-by: Greg Kroah-Hartman --- drivers/uio/Kconfig | 18 +++++ drivers/uio/Makefile | 1 + drivers/uio/uio_aec.c | 175 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 194 insertions(+) create mode 100644 drivers/uio/uio_aec.c diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig index 04b954cfce7..7f86534de26 100644 --- a/drivers/uio/Kconfig +++ b/drivers/uio/Kconfig @@ -58,6 +58,24 @@ config UIO_SMX If you compile this as a module, it will be called uio_smx. +config UIO_AEC + tristate "AEC video timestamp device" + depends on PCI + default n + help + + UIO driver for the Adrienne Electronics Corporation PCI time + code device. + + This device differs from other UIO devices since it uses I/O + ports instead of memory mapped I/O. In order to make it + possible for UIO to work with this device a utility, uioport, + can be used to read and write the ports: + + git clone git://ifup.org/philips/uioport.git + + If you compile this as a module, it will be called uio_aec. + config UIO_SERCOS3 tristate "Automata Sercos III PCI card driver" default n diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile index e6955814985..5c2586d7579 100644 --- a/drivers/uio/Makefile +++ b/drivers/uio/Makefile @@ -3,4 +3,5 @@ obj-$(CONFIG_UIO_CIF) += uio_cif.o obj-$(CONFIG_UIO_PDRV) += uio_pdrv.o obj-$(CONFIG_UIO_PDRV_GENIRQ) += uio_pdrv_genirq.o obj-$(CONFIG_UIO_SMX) += uio_smx.o +obj-$(CONFIG_UIO_AEC) += uio_aec.o obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o diff --git a/drivers/uio/uio_aec.c b/drivers/uio/uio_aec.c new file mode 100644 index 00000000000..b7830e9a3ba --- /dev/null +++ b/drivers/uio/uio_aec.c @@ -0,0 +1,175 @@ +/* + * uio_aec.c -- simple driver for Adrienne Electronics Corp time code PCI device + * + * Copyright (C) 2008 Brandon Philips + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PCI_VENDOR_ID_AEC 0xaecb +#define PCI_DEVICE_ID_AEC_VITCLTC 0x6250 + +#define INT_ENABLE_ADDR 0xFC +#define INT_ENABLE 0x10 +#define INT_DISABLE 0x0 + +#define INT_MASK_ADDR 0x2E +#define INT_MASK_ALL 0x3F + +#define INTA_DRVR_ADDR 0xFE +#define INTA_ENABLED_FLAG 0x08 +#define INTA_FLAG 0x01 + +#define MAILBOX 0x0F + +static struct pci_device_id ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_AEC, PCI_DEVICE_ID_AEC_VITCLTC), }, + { 0, } +}; +MODULE_DEVICE_TABLE(pci, ids); + +static irqreturn_t aectc_irq(int irq, struct uio_info *dev_info) +{ + void __iomem *int_flag = dev_info->priv + INTA_DRVR_ADDR; + unsigned char status = ioread8(int_flag); + + + if ((status & INTA_ENABLED_FLAG) && (status & INTA_FLAG)) { + /* application writes 0x00 to 0x2F to get next interrupt */ + status = ioread8(dev_info->priv + MAILBOX); + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static void print_board_data(struct pci_dev *pdev, struct uio_info *i) +{ + dev_info(&pdev->dev, "PCI-TC board vendor: %x%x number: %x%x" + " revision: %c%c\n", + ioread8(i->priv + 0x01), + ioread8(i->priv + 0x00), + ioread8(i->priv + 0x03), + ioread8(i->priv + 0x02), + ioread8(i->priv + 0x06), + ioread8(i->priv + 0x07)); +} + +static int __devinit probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct uio_info *info; + int ret; + + info = kzalloc(sizeof(struct uio_info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + if (pci_enable_device(pdev)) + goto out_free; + + if (pci_request_regions(pdev, "aectc")) + goto out_disable; + + info->name = "aectc"; + info->port[0].start = pci_resource_start(pdev, 0); + if (!info->port[0].start) + goto out_release; + info->priv = pci_iomap(pdev, 0, 0); + if (!info->priv) + goto out_release; + info->port[0].size = pci_resource_len(pdev, 0); + info->port[0].porttype = UIO_PORT_GPIO; + + info->version = "0.0.1"; + info->irq = pdev->irq; + info->irq_flags = IRQF_SHARED; + info->handler = aectc_irq; + + print_board_data(pdev, info); + ret = uio_register_device(&pdev->dev, info); + if (ret) + goto out_unmap; + + iowrite32(INT_ENABLE, info->priv + INT_ENABLE_ADDR); + iowrite8(INT_MASK_ALL, info->priv + INT_MASK_ADDR); + if (!(ioread8(info->priv + INTA_DRVR_ADDR) + & INTA_ENABLED_FLAG)) + dev_err(&pdev->dev, "aectc: interrupts not enabled\n"); + + pci_set_drvdata(pdev, info); + + return 0; + +out_unmap: + pci_iounmap(pdev, info->priv); +out_release: + pci_release_regions(pdev); +out_disable: + pci_disable_device(pdev); +out_free: + kfree(info); + return -ENODEV; +} + +static void remove(struct pci_dev *pdev) +{ + struct uio_info *info = pci_get_drvdata(pdev); + + /* disable interrupts */ + iowrite8(INT_DISABLE, info->priv + INT_MASK_ADDR); + iowrite32(INT_DISABLE, info->priv + INT_ENABLE_ADDR); + /* read mailbox to ensure board drops irq */ + ioread8(info->priv + MAILBOX); + + uio_unregister_device(info); + pci_release_regions(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + iounmap(info->priv); + + kfree(info); +} + +static struct pci_driver pci_driver = { + .name = "aectc", + .id_table = ids, + .probe = probe, + .remove = remove, +}; + +static int __init aectc_init(void) +{ + return pci_register_driver(&pci_driver); +} + +static void __exit aectc_exit(void) +{ + pci_unregister_driver(&pci_driver); +} + +MODULE_LICENSE("GPL"); + +module_init(aectc_init); +module_exit(aectc_exit); -- GitLab From 6da2d377bba06c29d0bc41c8dee014164dec82a7 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 24 Feb 2009 17:22:59 +0000 Subject: [PATCH 4426/4982] UIO: Take offset into account when determining number of pages that can be mapped If a UIO memory region does not start on a page boundary but straddles one, the number of actual pages that overlap the memory region may be calculated incorrectly because the offset isn't taken into account. If userspace sets the mmap length to offset+size, it may fail with -EINVAL if UIO thinks it's trying to allocate too many pages. Signed-off-by: Ian Abbott Cc: Hans J. Koch Signed-off-by: Greg Kroah-Hartman --- drivers/uio/uio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index 68a49655778..03efb065455 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -708,7 +708,8 @@ static int uio_mmap(struct file *filep, struct vm_area_struct *vma) return -EINVAL; requested_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; - actual_pages = (idev->info->mem[mi].size + PAGE_SIZE -1) >> PAGE_SHIFT; + actual_pages = ((idev->info->mem[mi].addr & ~PAGE_MASK) + + idev->info->mem[mi].size + PAGE_SIZE -1) >> PAGE_SHIFT; if (requested_pages > actual_pages) return -EINVAL; -- GitLab From 7a192ec334cab9fafe3a8665a65af398b0e24730 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Fri, 6 Feb 2009 23:40:12 +0800 Subject: [PATCH 4427/4982] platform driver: fix incorrect use of 'platform_bus_type' with 'struct device_driver' This patch fixes the bug reported in http://bugzilla.kernel.org/show_bug.cgi?id=11681. "Lots of device drivers register a 'struct device_driver' with the '.bus' member set to '&platform_bus_type'. This is wrong, since the platform_bus functions expect the 'struct device_driver' to be wrapped up in a 'struct platform_driver' which provides some additional callbacks (like suspend_late, resume_early). The effect may be that platform_suspend_late() uses bogus data outside the device_driver struct as a pointer pointer to the device driver's suspend_late() function or other hard to reproduce failures."(Lothar Wassmann) Signed-off-by: Ming Lei Acked-by: Henrique de Moraes Holschuh Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- arch/mips/basler/excite/excite_iodev.c | 27 +++++++++--------- drivers/char/tpm/tpm_atmel.c | 28 +++++++++++++------ drivers/char/tpm/tpm_tis.c | 28 +++++++++++++------ drivers/ide/au1xxx-ide.c | 36 ++++++++++++------------ drivers/mtd/maps/pxa2xx-flash.c | 37 +++++++++++++------------ drivers/mtd/nand/excite_nandflash.c | 25 +++++++++-------- drivers/mtd/onenand/generic.c | 26 +++++++++--------- drivers/net/mipsnet.c | 26 ++++++++++-------- drivers/pcmcia/au1000_generic.c | 37 ++++++++++++++++--------- drivers/pcmcia/i82365.c | 28 +++++++++++++------ drivers/pcmcia/m32r_cfc.c | 30 ++++++++++++++------ drivers/pcmcia/m32r_pcc.c | 30 ++++++++++++++------ drivers/pcmcia/sa1100_generic.c | 38 +++++++++++++++++++------- drivers/pcmcia/tcic.c | 30 ++++++++++++++------ drivers/pcmcia/vrc4171_card.c | 34 ++++++++++++++++------- drivers/scsi/a4000t.c | 26 ++++++++++-------- drivers/scsi/bvme6000_scsi.c | 26 ++++++++++-------- drivers/scsi/mvme16x_scsi.c | 26 ++++++++++-------- drivers/video/au1100fb.c | 31 +++++++++++---------- drivers/video/au1200fb.c | 25 +++++++++-------- drivers/watchdog/rm9k_wdt.c | 27 ++++++++---------- 21 files changed, 371 insertions(+), 250 deletions(-) diff --git a/arch/mips/basler/excite/excite_iodev.c b/arch/mips/basler/excite/excite_iodev.c index a1e3526b4a9..dfbfd7e2ac0 100644 --- a/arch/mips/basler/excite/excite_iodev.c +++ b/arch/mips/basler/excite/excite_iodev.c @@ -33,8 +33,8 @@ static const struct resource *iodev_get_resource(struct platform_device *, const char *, unsigned int); -static int __init iodev_probe(struct device *); -static int __exit iodev_remove(struct device *); +static int __init iodev_probe(struct platform_device *); +static int __exit iodev_remove(struct platform_device *); static int iodev_open(struct inode *, struct file *); static int iodev_release(struct inode *, struct file *); static ssize_t iodev_read(struct file *, char __user *, size_t s, loff_t *); @@ -65,13 +65,13 @@ static struct miscdevice miscdev = .fops = &fops }; -static struct device_driver iodev_driver = -{ - .name = (char *) iodev_name, - .bus = &platform_bus_type, - .owner = THIS_MODULE, +static struct platform_driver iodev_driver = { + .driver = { + .name = iodev_name, + .owner = THIS_MODULE, + }, .probe = iodev_probe, - .remove = __exit_p(iodev_remove) + .remove = __devexit_p(iodev_remove), }; @@ -89,11 +89,10 @@ iodev_get_resource(struct platform_device *pdv, const char *name, /* No hotplugging on the platform bus - use __init */ -static int __init iodev_probe(struct device *dev) +static int __init iodev_probe(struct platform_device *dev) { - struct platform_device * const pdv = to_platform_device(dev); const struct resource * const ri = - iodev_get_resource(pdv, IODEV_RESOURCE_IRQ, IORESOURCE_IRQ); + iodev_get_resource(dev, IODEV_RESOURCE_IRQ, IORESOURCE_IRQ); if (unlikely(!ri)) return -ENXIO; @@ -104,7 +103,7 @@ static int __init iodev_probe(struct device *dev) -static int __exit iodev_remove(struct device *dev) +static int __exit iodev_remove(struct platform_device *dev) { return misc_deregister(&miscdev); } @@ -160,14 +159,14 @@ static irqreturn_t iodev_irqhdl(int irq, void *ctxt) static int __init iodev_init_module(void) { - return driver_register(&iodev_driver); + return platform_driver_register(&iodev_driver); } static void __exit iodev_cleanup_module(void) { - driver_unregister(&iodev_driver); + platform_driver_unregister(&iodev_driver); } module_init(iodev_init_module); diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index d0e7926eb48..c64a1bc6534 100644 --- a/drivers/char/tpm/tpm_atmel.c +++ b/drivers/char/tpm/tpm_atmel.c @@ -168,12 +168,22 @@ static void atml_plat_remove(void) } } -static struct device_driver atml_drv = { - .name = "tpm_atmel", - .bus = &platform_bus_type, - .owner = THIS_MODULE, - .suspend = tpm_pm_suspend, - .resume = tpm_pm_resume, +static int tpm_atml_suspend(struct platform_device *dev, pm_message_t msg) +{ + return tpm_pm_suspend(&dev->dev, msg); +} + +static int tpm_atml_resume(struct platform_device *dev) +{ + return tpm_pm_resume(&dev->dev); +} +static struct platform_driver atml_drv = { + .driver = { + .name = "tpm_atmel", + .owner = THIS_MODULE, + }, + .suspend = tpm_atml_suspend, + .resume = tpm_atml_resume, }; static int __init init_atmel(void) @@ -184,7 +194,7 @@ static int __init init_atmel(void) unsigned long base; struct tpm_chip *chip; - rc = driver_register(&atml_drv); + rc = platform_driver_register(&atml_drv); if (rc) return rc; @@ -223,13 +233,13 @@ err_rel_reg: atmel_release_region(base, region_size); err_unreg_drv: - driver_unregister(&atml_drv); + platform_driver_unregister(&atml_drv); return rc; } static void __exit cleanup_atmel(void) { - driver_unregister(&atml_drv); + platform_driver_unregister(&atml_drv); atml_plat_remove(); } diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 717af7ad1bd..aec1931608a 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -654,12 +654,22 @@ module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); -static struct device_driver tis_drv = { - .name = "tpm_tis", - .bus = &platform_bus_type, - .owner = THIS_MODULE, - .suspend = tpm_pm_suspend, - .resume = tpm_pm_resume, +static int tpm_tis_suspend(struct platform_device *dev, pm_message_t msg) +{ + return tpm_pm_suspend(&dev->dev, msg); +} + +static int tpm_tis_resume(struct platform_device *dev) +{ + return tpm_pm_resume(&dev->dev); +} +static struct platform_driver tis_drv = { + .driver = { + .name = "tpm_tis", + .owner = THIS_MODULE, + }, + .suspend = tpm_tis_suspend, + .resume = tpm_tis_resume, }; static struct platform_device *pdev; @@ -672,14 +682,14 @@ static int __init init_tis(void) int rc; if (force) { - rc = driver_register(&tis_drv); + rc = platform_driver_register(&tis_drv); if (rc < 0) return rc; if (IS_ERR(pdev=platform_device_register_simple("tpm_tis", -1, NULL, 0))) return PTR_ERR(pdev); if((rc=tpm_tis_init(&pdev->dev, TIS_MEM_BASE, TIS_MEM_LEN, 0)) != 0) { platform_device_unregister(pdev); - driver_unregister(&tis_drv); + platform_driver_unregister(&tis_drv); } return rc; } @@ -711,7 +721,7 @@ static void __exit cleanup_tis(void) if (force) { platform_device_unregister(pdev); - driver_unregister(&tis_drv); + platform_driver_unregister(&tis_drv); } else pnp_unregister_driver(&tis_pnp_driver); } diff --git a/drivers/ide/au1xxx-ide.c b/drivers/ide/au1xxx-ide.c index 79a2dfed8eb..154ec2cf734 100644 --- a/drivers/ide/au1xxx-ide.c +++ b/drivers/ide/au1xxx-ide.c @@ -536,9 +536,8 @@ static const struct ide_port_info au1xxx_port_info = { #endif }; -static int au_ide_probe(struct device *dev) +static int au_ide_probe(struct platform_device *dev) { - struct platform_device *pdev = to_platform_device(dev); _auide_hwif *ahwif = &auide_hwif; struct resource *res; struct ide_host *host; @@ -552,23 +551,23 @@ static int au_ide_probe(struct device *dev) #endif memset(&auide_hwif, 0, sizeof(_auide_hwif)); - ahwif->irq = platform_get_irq(pdev, 0); + ahwif->irq = platform_get_irq(dev, 0); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + res = platform_get_resource(dev, IORESOURCE_MEM, 0); if (res == NULL) { - pr_debug("%s %d: no base address\n", DRV_NAME, pdev->id); + pr_debug("%s %d: no base address\n", DRV_NAME, dev->id); ret = -ENODEV; goto out; } if (ahwif->irq < 0) { - pr_debug("%s %d: no IRQ\n", DRV_NAME, pdev->id); + pr_debug("%s %d: no IRQ\n", DRV_NAME, dev->id); ret = -ENODEV; goto out; } if (!request_mem_region(res->start, res->end - res->start + 1, - pdev->name)) { + dev->name)) { pr_debug("%s: request_mem_region failed\n", DRV_NAME); ret = -EBUSY; goto out; @@ -583,7 +582,7 @@ static int au_ide_probe(struct device *dev) memset(&hw, 0, sizeof(hw)); auide_setup_ports(&hw, ahwif); hw.irq = ahwif->irq; - hw.dev = dev; + hw.dev = &dev->dev; hw.chipset = ide_au1xxx; ret = ide_host_add(&au1xxx_port_info, hws, &host); @@ -592,7 +591,7 @@ static int au_ide_probe(struct device *dev) auide_hwif.hwif = host->ports[0]; - dev_set_drvdata(dev, host); + platform_set_drvdata(dev, host); printk(KERN_INFO "Au1xxx IDE(builtin) configured for %s\n", mode ); @@ -600,38 +599,39 @@ static int au_ide_probe(struct device *dev) return ret; } -static int au_ide_remove(struct device *dev) +static int au_ide_remove(struct platform_device *dev) { - struct platform_device *pdev = to_platform_device(dev); struct resource *res; - struct ide_host *host = dev_get_drvdata(dev); + struct ide_host *host = platform_get_drvdata(dev); _auide_hwif *ahwif = &auide_hwif; ide_host_remove(host); iounmap((void *)ahwif->regbase); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + res = platform_get_resource(dev, IORESOURCE_MEM, 0); release_mem_region(res->start, res->end - res->start + 1); return 0; } -static struct device_driver au1200_ide_driver = { - .name = "au1200-ide", - .bus = &platform_bus_type, +static struct platform_driver au1200_ide_driver = { + .driver = { + .name = "au1200-ide", + .owner = THIS_MODULE, + }, .probe = au_ide_probe, .remove = au_ide_remove, }; static int __init au_ide_init(void) { - return driver_register(&au1200_ide_driver); + return platform_driver_register(&au1200_ide_driver); } static void __exit au_ide_exit(void) { - driver_unregister(&au1200_ide_driver); + platform_driver_unregister(&au1200_ide_driver); } MODULE_LICENSE("GPL"); diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c index 771139c5bf8..e9026cb1c5b 100644 --- a/drivers/mtd/maps/pxa2xx-flash.c +++ b/drivers/mtd/maps/pxa2xx-flash.c @@ -41,9 +41,8 @@ struct pxa2xx_flash_info { static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; -static int __init pxa2xx_flash_probe(struct device *dev) +static int __init pxa2xx_flash_probe(struct platform_device *pdev) { - struct platform_device *pdev = to_platform_device(dev); struct flash_platform_data *flash = pdev->dev.platform_data; struct pxa2xx_flash_info *info; struct mtd_partition *parts; @@ -114,15 +113,15 @@ static int __init pxa2xx_flash_probe(struct device *dev) add_mtd_device(info->mtd); } - dev_set_drvdata(dev, info); + platform_set_drvdata(pdev, info); return 0; } -static int __exit pxa2xx_flash_remove(struct device *dev) +static int __exit pxa2xx_flash_remove(struct platform_device *dev) { - struct pxa2xx_flash_info *info = dev_get_drvdata(dev); + struct pxa2xx_flash_info *info = platform_get_drvdata(dev); - dev_set_drvdata(dev, NULL); + platform_set_drvdata(dev, NULL); #ifdef CONFIG_MTD_PARTITIONS if (info->nr_parts) @@ -141,9 +140,9 @@ static int __exit pxa2xx_flash_remove(struct device *dev) } #ifdef CONFIG_PM -static int pxa2xx_flash_suspend(struct device *dev, pm_message_t state) +static int pxa2xx_flash_suspend(struct platform_device *dev, pm_message_t state) { - struct pxa2xx_flash_info *info = dev_get_drvdata(dev); + struct pxa2xx_flash_info *info = platform_get_drvdata(dev); int ret = 0; if (info->mtd && info->mtd->suspend) @@ -151,17 +150,17 @@ static int pxa2xx_flash_suspend(struct device *dev, pm_message_t state) return ret; } -static int pxa2xx_flash_resume(struct device *dev) +static int pxa2xx_flash_resume(struct platform_device *dev) { - struct pxa2xx_flash_info *info = dev_get_drvdata(dev); + struct pxa2xx_flash_info *info = platform_get_drvdata(dev); if (info->mtd && info->mtd->resume) info->mtd->resume(info->mtd); return 0; } -static void pxa2xx_flash_shutdown(struct device *dev) +static void pxa2xx_flash_shutdown(struct platform_device *dev) { - struct pxa2xx_flash_info *info = dev_get_drvdata(dev); + struct pxa2xx_flash_info *info = platform_get_drvdata(dev); if (info && info->mtd->suspend(info->mtd) == 0) info->mtd->resume(info->mtd); @@ -172,11 +171,13 @@ static void pxa2xx_flash_shutdown(struct device *dev) #define pxa2xx_flash_shutdown NULL #endif -static struct device_driver pxa2xx_flash_driver = { - .name = "pxa2xx-flash", - .bus = &platform_bus_type, +static struct platform_driver pxa2xx_flash_driver = { + .driver = { + .name = "pxa2xx-flash", + .owner = THIS_MODULE, + }, .probe = pxa2xx_flash_probe, - .remove = __exit_p(pxa2xx_flash_remove), + .remove = __devexit_p(pxa2xx_flash_remove), .suspend = pxa2xx_flash_suspend, .resume = pxa2xx_flash_resume, .shutdown = pxa2xx_flash_shutdown, @@ -184,12 +185,12 @@ static struct device_driver pxa2xx_flash_driver = { static int __init init_pxa2xx_flash(void) { - return driver_register(&pxa2xx_flash_driver); + return platform_driver_register(&pxa2xx_flash_driver); } static void __exit cleanup_pxa2xx_flash(void) { - driver_unregister(&pxa2xx_flash_driver); + platform_driver_unregister(&pxa2xx_flash_driver); } module_init(init_pxa2xx_flash); diff --git a/drivers/mtd/nand/excite_nandflash.c b/drivers/mtd/nand/excite_nandflash.c index ced14b5294d..72446fb48d4 100644 --- a/drivers/mtd/nand/excite_nandflash.c +++ b/drivers/mtd/nand/excite_nandflash.c @@ -128,11 +128,11 @@ static int excite_nand_devready(struct mtd_info *mtd) * The binding to the mtd and all allocated * resources are released. */ -static int __exit excite_nand_remove(struct device *dev) +static int __exit excite_nand_remove(struct platform_device *dev) { - struct excite_nand_drvdata * const this = dev_get_drvdata(dev); + struct excite_nand_drvdata * const this = platform_get_drvdata(dev); - dev_set_drvdata(dev, NULL); + platform_set_drvdata(dev, NULL); if (unlikely(!this)) { printk(KERN_ERR "%s: called %s without private data!!", @@ -159,9 +159,8 @@ static int __exit excite_nand_remove(struct device *dev) * it can allocate all necessary resources then calls the * nand layer to look for devices. */ -static int __init excite_nand_probe(struct device *dev) +static int __init excite_nand_probe(struct platform_device *pdev) { - struct platform_device * const pdev = to_platform_device(dev); struct excite_nand_drvdata *drvdata; /* private driver data */ struct nand_chip *board_chip; /* private flash chip data */ struct mtd_info *board_mtd; /* mtd info for this board */ @@ -175,7 +174,7 @@ static int __init excite_nand_probe(struct device *dev) } /* bind private data into driver */ - dev_set_drvdata(dev, drvdata); + platform_set_drvdata(pdev, drvdata); /* allocate and map the resource */ drvdata->regs = @@ -219,23 +218,25 @@ static int __init excite_nand_probe(struct device *dev) return 0; } -static struct device_driver excite_nand_driver = { - .name = "excite_nand", - .bus = &platform_bus_type, +static struct platform_driver excite_nand_driver = { + .driver = { + .name = "excite_nand", + .owner = THIS_MODULE, + }, .probe = excite_nand_probe, - .remove = __exit_p(excite_nand_remove) + .remove = __devexit_p(excite_nand_remove) }; static int __init excite_nand_init(void) { pr_info("Basler eXcite nand flash driver Version " EXCITE_NANDFLASH_VERSION "\n"); - return driver_register(&excite_nand_driver); + return platform_driver_register(&excite_nand_driver); } static void __exit excite_nand_exit(void) { - driver_unregister(&excite_nand_driver); + platform_driver_unregister(&excite_nand_driver); } module_init(excite_nand_init); diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c index 5b69e7773c6..3a496c33fb5 100644 --- a/drivers/mtd/onenand/generic.c +++ b/drivers/mtd/onenand/generic.c @@ -36,10 +36,9 @@ struct onenand_info { struct onenand_chip onenand; }; -static int __devinit generic_onenand_probe(struct device *dev) +static int __devinit generic_onenand_probe(struct platform_device *pdev) { struct onenand_info *info; - struct platform_device *pdev = to_platform_device(dev); struct flash_platform_data *pdata = pdev->dev.platform_data; struct resource *res = pdev->resource; unsigned long size = res->end - res->start + 1; @@ -49,7 +48,7 @@ static int __devinit generic_onenand_probe(struct device *dev) if (!info) return -ENOMEM; - if (!request_mem_region(res->start, size, dev->driver->name)) { + if (!request_mem_region(res->start, size, pdev->dev.driver->name)) { err = -EBUSY; goto out_free_info; } @@ -82,7 +81,7 @@ static int __devinit generic_onenand_probe(struct device *dev) #endif err = add_mtd_device(&info->mtd); - dev_set_drvdata(&pdev->dev, info); + platform_set_drvdata(pdev, info); return 0; @@ -96,14 +95,13 @@ out_free_info: return err; } -static int __devexit generic_onenand_remove(struct device *dev) +static int __devexit generic_onenand_remove(struct platform_device *pdev) { - struct platform_device *pdev = to_platform_device(dev); - struct onenand_info *info = dev_get_drvdata(&pdev->dev); + struct onenand_info *info = platform_get_drvdata(pdev); struct resource *res = pdev->resource; unsigned long size = res->end - res->start + 1; - dev_set_drvdata(&pdev->dev, NULL); + platform_set_drvdata(pdev, NULL); if (info) { if (info->parts) @@ -120,9 +118,11 @@ static int __devexit generic_onenand_remove(struct device *dev) return 0; } -static struct device_driver generic_onenand_driver = { - .name = DRIVER_NAME, - .bus = &platform_bus_type, +static struct platform_driver generic_onenand_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, .probe = generic_onenand_probe, .remove = __devexit_p(generic_onenand_remove), }; @@ -131,12 +131,12 @@ MODULE_ALIAS(DRIVER_NAME); static int __init generic_onenand_init(void) { - return driver_register(&generic_onenand_driver); + return platform_driver_register(&generic_onenand_driver); } static void __exit generic_onenand_exit(void) { - driver_unregister(&generic_onenand_driver); + platform_driver_unregister(&generic_onenand_driver); } module_init(generic_onenand_init); diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c index 4e7a5faf035..664835b822f 100644 --- a/drivers/net/mipsnet.c +++ b/drivers/net/mipsnet.c @@ -237,7 +237,7 @@ static void mipsnet_set_mclist(struct net_device *dev) { } -static int __init mipsnet_probe(struct device *dev) +static int __init mipsnet_probe(struct platform_device *dev) { struct net_device *netdev; int err; @@ -248,7 +248,7 @@ static int __init mipsnet_probe(struct device *dev) goto out; } - dev_set_drvdata(dev, netdev); + platform_set_drvdata(dev, netdev); netdev->open = mipsnet_open; netdev->stop = mipsnet_close; @@ -293,23 +293,25 @@ out: return err; } -static int __devexit mipsnet_device_remove(struct device *device) +static int __devexit mipsnet_device_remove(struct platform_device *device) { - struct net_device *dev = dev_get_drvdata(device); + struct net_device *dev = platform_get_drvdata(device); unregister_netdev(dev); release_region(dev->base_addr, sizeof(struct mipsnet_regs)); free_netdev(dev); - dev_set_drvdata(device, NULL); + platform_set_drvdata(device, NULL); return 0; } -static struct device_driver mipsnet_driver = { - .name = mipsnet_string, - .bus = &platform_bus_type, - .probe = mipsnet_probe, - .remove = __devexit_p(mipsnet_device_remove), +static struct platform_driver mipsnet_driver = { + .driver = { + .name = mipsnet_string, + .owner = THIS_MODULE, + }, + .probe = mipsnet_probe, + .remove = __devexit_p(mipsnet_device_remove), }; static int __init mipsnet_init_module(void) @@ -319,7 +321,7 @@ static int __init mipsnet_init_module(void) printk(KERN_INFO "MIPSNet Ethernet driver. Version: %s. " "(c)2005 MIPS Technologies, Inc.\n", MIPSNET_VERSION); - err = driver_register(&mipsnet_driver); + err = platform_driver_register(&mipsnet_driver); if (err) printk(KERN_ERR "Driver registration failed\n"); @@ -328,7 +330,7 @@ static int __init mipsnet_init_module(void) static void __exit mipsnet_exit_module(void) { - driver_unregister(&mipsnet_driver); + platform_driver_unregister(&mipsnet_driver); } module_init(mipsnet_init_module); diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c index fc1de46fd20..90013341cd5 100644 --- a/drivers/pcmcia/au1000_generic.c +++ b/drivers/pcmcia/au1000_generic.c @@ -468,13 +468,13 @@ out: return ret; } -int au1x00_drv_pcmcia_remove(struct device *dev) +int au1x00_drv_pcmcia_remove(struct platform_device *dev) { - struct skt_dev_info *sinfo = dev_get_drvdata(dev); + struct skt_dev_info *sinfo = platform_get_drvdata(dev); int i; mutex_lock(&pcmcia_sockets_lock); - dev_set_drvdata(dev, NULL); + platform_set_drvdata(dev, NULL); for (i = 0; i < sinfo->nskt; i++) { struct au1000_pcmcia_socket *skt = PCMCIA_SOCKET(i); @@ -498,13 +498,13 @@ int au1x00_drv_pcmcia_remove(struct device *dev) * PCMCIA "Driver" API */ -static int au1x00_drv_pcmcia_probe(struct device *dev) +static int au1x00_drv_pcmcia_probe(struct platform_device *dev) { int i, ret = -ENODEV; mutex_lock(&pcmcia_sockets_lock); for (i=0; i < ARRAY_SIZE(au1x00_pcmcia_hw_init); i++) { - ret = au1x00_pcmcia_hw_init[i](dev); + ret = au1x00_pcmcia_hw_init[i](&dev->dev); if (ret == 0) break; } @@ -512,14 +512,26 @@ static int au1x00_drv_pcmcia_probe(struct device *dev) return ret; } +static int au1x00_drv_pcmcia_suspend(struct platform_device *dev, + pm_message_t state) +{ + return pcmcia_socket_dev_suspend(&dev->dev, state); +} + +static int au1x00_drv_pcmcia_resume(struct platform_device *dev) +{ + return pcmcia_socket_dev_resume(&dev->dev); +} -static struct device_driver au1x00_pcmcia_driver = { +static struct platform_driver au1x00_pcmcia_driver = { + .driver = { + .name = "au1x00-pcmcia", + .owner = THIS_MODULE, + }, .probe = au1x00_drv_pcmcia_probe, .remove = au1x00_drv_pcmcia_remove, - .name = "au1x00-pcmcia", - .bus = &platform_bus_type, - .suspend = pcmcia_socket_dev_suspend, - .resume = pcmcia_socket_dev_resume, + .suspend = au1x00_drv_pcmcia_suspend, + .resume = au1x00_drv_pcmcia_resume, }; @@ -533,8 +545,7 @@ static struct device_driver au1x00_pcmcia_driver = { static int __init au1x00_pcmcia_init(void) { int error = 0; - if ((error = driver_register(&au1x00_pcmcia_driver))) - return error; + error = platform_driver_register(&au1x00_pcmcia_driver); return error; } @@ -544,7 +555,7 @@ static int __init au1x00_pcmcia_init(void) */ static void __exit au1x00_pcmcia_exit(void) { - driver_unregister(&au1x00_pcmcia_driver); + platform_driver_unregister(&au1x00_pcmcia_driver); } module_init(au1x00_pcmcia_init); diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index 71653ab8489..40d4953e4b1 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c @@ -1238,6 +1238,16 @@ static int pcic_init(struct pcmcia_socket *s) return 0; } +static int i82365_drv_pcmcia_suspend(struct platform_device *dev, + pm_message_t state) +{ + return pcmcia_socket_dev_suspend(&dev->dev, state); +} + +static int i82365_drv_pcmcia_resume(struct platform_device *dev) +{ + return pcmcia_socket_dev_resume(&dev->dev); +} static struct pccard_operations pcic_operations = { .init = pcic_init, .get_status = pcic_get_status, @@ -1248,11 +1258,13 @@ static struct pccard_operations pcic_operations = { /*====================================================================*/ -static struct device_driver i82365_driver = { - .name = "i82365", - .bus = &platform_bus_type, - .suspend = pcmcia_socket_dev_suspend, - .resume = pcmcia_socket_dev_resume, +static struct platform_driver i82365_driver = { + .driver = { + .name = "i82365", + .owner = THIS_MODULE, + }, + .suspend = i82365_drv_pcmcia_suspend, + .resume = i82365_drv_pcmcia_resume, }; static struct platform_device *i82365_device; @@ -1261,7 +1273,7 @@ static int __init init_i82365(void) { int i, ret; - ret = driver_register(&i82365_driver); + ret = platform_driver_register(&i82365_driver); if (ret) goto err_out; @@ -1337,7 +1349,7 @@ err_dev_unregister: pnp_disable_dev(i82365_pnpdev); #endif err_driver_unregister: - driver_unregister(&i82365_driver); + platform_driver_unregister(&i82365_driver); err_out: return ret; } /* init_i82365 */ @@ -1365,7 +1377,7 @@ static void __exit exit_i82365(void) if (i82365_pnpdev) pnp_disable_dev(i82365_pnpdev); #endif - driver_unregister(&i82365_driver); + platform_driver_unregister(&i82365_driver); } /* exit_i82365 */ module_init(init_i82365); diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c index 2ab4f22c21d..62b4ecc97c4 100644 --- a/drivers/pcmcia/m32r_cfc.c +++ b/drivers/pcmcia/m32r_cfc.c @@ -696,13 +696,25 @@ static struct pccard_operations pcc_operations = { .set_mem_map = pcc_set_mem_map, }; +static int cfc_drv_pcmcia_suspend(struct platform_device *dev, + pm_message_t state) +{ + return pcmcia_socket_dev_suspend(&dev->dev, state); +} + +static int cfc_drv_pcmcia_resume(struct platform_device *dev) +{ + return pcmcia_socket_dev_resume(&dev->dev); +} /*====================================================================*/ -static struct device_driver pcc_driver = { - .name = "cfc", - .bus = &platform_bus_type, - .suspend = pcmcia_socket_dev_suspend, - .resume = pcmcia_socket_dev_resume, +static struct platform_driver pcc_driver = { + .driver = { + .name = "cfc", + .owner = THIS_MODULE, + }, + .suspend = cfc_drv_pcmcia_suspend, + .resume = cfc_drv_pcmcia_resume, }; static struct platform_device pcc_device = { @@ -716,13 +728,13 @@ static int __init init_m32r_pcc(void) { int i, ret; - ret = driver_register(&pcc_driver); + ret = platform_driver_register(&pcc_driver); if (ret) return ret; ret = platform_device_register(&pcc_device); if (ret){ - driver_unregister(&pcc_driver); + platform_driver_unregister(&pcc_driver); return ret; } @@ -754,7 +766,7 @@ static int __init init_m32r_pcc(void) if (pcc_sockets == 0) { printk("socket is not found.\n"); platform_device_unregister(&pcc_device); - driver_unregister(&pcc_driver); + platform_driver_unregister(&pcc_driver); return -ENODEV; } @@ -802,7 +814,7 @@ static void __exit exit_m32r_pcc(void) if (poll_interval != 0) del_timer_sync(&poll_timer); - driver_unregister(&pcc_driver); + platform_driver_unregister(&pcc_driver); } /* exit_m32r_pcc */ module_init(init_m32r_pcc); diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c index 2f108c23dbd..12034b41d19 100644 --- a/drivers/pcmcia/m32r_pcc.c +++ b/drivers/pcmcia/m32r_pcc.c @@ -672,13 +672,25 @@ static struct pccard_operations pcc_operations = { .set_mem_map = pcc_set_mem_map, }; +static int pcc_drv_pcmcia_suspend(struct platform_device *dev, + pm_message_t state) +{ + return pcmcia_socket_dev_suspend(&dev->dev, state); +} + +static int pcc_drv_pcmcia_resume(struct platform_device *dev) +{ + return pcmcia_socket_dev_resume(&dev->dev); +} /*====================================================================*/ -static struct device_driver pcc_driver = { - .name = "pcc", - .bus = &platform_bus_type, - .suspend = pcmcia_socket_dev_suspend, - .resume = pcmcia_socket_dev_resume, +static struct platform_driver pcc_driver = { + .driver = { + .name = "pcc", + .owner = THIS_MODULE, + }, + .suspend = pcc_drv_pcmcia_suspend, + .resume = pcc_drv_pcmcia_resume, }; static struct platform_device pcc_device = { @@ -692,13 +704,13 @@ static int __init init_m32r_pcc(void) { int i, ret; - ret = driver_register(&pcc_driver); + ret = platform_driver_register(&pcc_driver); if (ret) return ret; ret = platform_device_register(&pcc_device); if (ret){ - driver_unregister(&pcc_driver); + platform_driver_unregister(&pcc_driver); return ret; } @@ -715,7 +727,7 @@ static int __init init_m32r_pcc(void) if (pcc_sockets == 0) { printk("socket is not found.\n"); platform_device_unregister(&pcc_device); - driver_unregister(&pcc_driver); + platform_driver_unregister(&pcc_driver); return -ENODEV; } @@ -763,7 +775,7 @@ static void __exit exit_m32r_pcc(void) if (poll_interval != 0) del_timer_sync(&poll_timer); - driver_unregister(&pcc_driver); + platform_driver_unregister(&pcc_driver); } /* exit_m32r_pcc */ module_init(init_m32r_pcc); diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c index c5b2a44b4c3..d8da5ac844e 100644 --- a/drivers/pcmcia/sa1100_generic.c +++ b/drivers/pcmcia/sa1100_generic.c @@ -65,7 +65,7 @@ static int (*sa11x0_pcmcia_hw_init[])(struct device *dev) = { #endif }; -static int sa11x0_drv_pcmcia_probe(struct device *dev) +static int sa11x0_drv_pcmcia_probe(struct platform_device *dev) { int i, ret = -ENODEV; @@ -73,7 +73,7 @@ static int sa11x0_drv_pcmcia_probe(struct device *dev) * Initialise any "on-board" PCMCIA sockets. */ for (i = 0; i < ARRAY_SIZE(sa11x0_pcmcia_hw_init); i++) { - ret = sa11x0_pcmcia_hw_init[i](dev); + ret = sa11x0_pcmcia_hw_init[i](&dev->dev); if (ret == 0) break; } @@ -81,13 +81,31 @@ static int sa11x0_drv_pcmcia_probe(struct device *dev) return ret; } -static struct device_driver sa11x0_pcmcia_driver = { +static int sa11x0_drv_pcmcia_remove(struct platform_device *dev) +{ + return soc_common_drv_pcmcia_remove(&dev->dev); +} + +static int sa11x0_drv_pcmcia_suspend(struct platform_device *dev, + pm_message_t state) +{ + return pcmcia_socket_dev_suspend(&dev->dev, state); +} + +static int sa11x0_drv_pcmcia_resume(struct platform_device *dev) +{ + return pcmcia_socket_dev_resume(&dev->dev); +} + +static struct platform_driver sa11x0_pcmcia_driver = { + .driver = { + .name = "sa11x0-pcmcia", + .owner = THIS_MODULE, + }, .probe = sa11x0_drv_pcmcia_probe, - .remove = soc_common_drv_pcmcia_remove, - .name = "sa11x0-pcmcia", - .bus = &platform_bus_type, - .suspend = pcmcia_socket_dev_suspend, - .resume = pcmcia_socket_dev_resume, + .remove = sa11x0_drv_pcmcia_remove, + .suspend = sa11x0_drv_pcmcia_suspend, + .resume = sa11x0_drv_pcmcia_resume, }; /* sa11x0_pcmcia_init() @@ -100,7 +118,7 @@ static struct device_driver sa11x0_pcmcia_driver = { */ static int __init sa11x0_pcmcia_init(void) { - return driver_register(&sa11x0_pcmcia_driver); + return platform_driver_register(&sa11x0_pcmcia_driver); } /* sa11x0_pcmcia_exit() @@ -110,7 +128,7 @@ static int __init sa11x0_pcmcia_init(void) */ static void __exit sa11x0_pcmcia_exit(void) { - driver_unregister(&sa11x0_pcmcia_driver); + platform_driver_unregister(&sa11x0_pcmcia_driver); } MODULE_AUTHOR("John Dorsey "); diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c index 2a613e920fd..9ad97ea836e 100644 --- a/drivers/pcmcia/tcic.c +++ b/drivers/pcmcia/tcic.c @@ -363,13 +363,25 @@ static int __init get_tcic_id(void) return id; } +static int tcic_drv_pcmcia_suspend(struct platform_device *dev, + pm_message_t state) +{ + return pcmcia_socket_dev_suspend(&dev->dev, state); +} + +static int tcic_drv_pcmcia_resume(struct platform_device *dev) +{ + return pcmcia_socket_dev_resume(&dev->dev); +} /*====================================================================*/ -static struct device_driver tcic_driver = { - .name = "tcic-pcmcia", - .bus = &platform_bus_type, - .suspend = pcmcia_socket_dev_suspend, - .resume = pcmcia_socket_dev_resume, +static struct platform_driver tcic_driver = { + .driver = { + .name = "tcic-pcmcia", + .owner = THIS_MODULE, + }, + .suspend = tcic_drv_pcmcia_suspend, + .resume = tcic_drv_pcmcia_resume, }; static struct platform_device tcic_device = { @@ -383,7 +395,7 @@ static int __init init_tcic(void) int i, sock, ret = 0; u_int mask, scan; - if (driver_register(&tcic_driver)) + if (platform_driver_register(&tcic_driver)) return -1; printk(KERN_INFO "Databook TCIC-2 PCMCIA probe: "); @@ -391,7 +403,7 @@ static int __init init_tcic(void) if (!request_region(tcic_base, 16, "tcic-2")) { printk("could not allocate ports,\n "); - driver_unregister(&tcic_driver); + platform_driver_unregister(&tcic_driver); return -ENODEV; } else { @@ -414,7 +426,7 @@ static int __init init_tcic(void) if (sock == 0) { printk("not found.\n"); release_region(tcic_base, 16); - driver_unregister(&tcic_driver); + platform_driver_unregister(&tcic_driver); return -ENODEV; } @@ -542,7 +554,7 @@ static void __exit exit_tcic(void) } platform_device_unregister(&tcic_device); - driver_unregister(&tcic_driver); + platform_driver_unregister(&tcic_driver); } /* exit_tcic */ /*====================================================================*/ diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c index b2c41241905..659421d0ca4 100644 --- a/drivers/pcmcia/vrc4171_card.c +++ b/drivers/pcmcia/vrc4171_card.c @@ -704,24 +704,37 @@ static int __devinit vrc4171_card_setup(char *options) __setup("vrc4171_card=", vrc4171_card_setup); -static struct device_driver vrc4171_card_driver = { - .name = vrc4171_card_name, - .bus = &platform_bus_type, - .suspend = pcmcia_socket_dev_suspend, - .resume = pcmcia_socket_dev_resume, +static int vrc4171_card_suspend(struct platform_device *dev, + pm_message_t state) +{ + return pcmcia_socket_dev_suspend(&dev->dev, state); +} + +static int vrc4171_card_resume(struct platform_device *dev) +{ + return pcmcia_socket_dev_resume(&dev->dev); +} + +static struct platform_driver vrc4171_card_driver = { + .driver = { + .name = vrc4171_card_name, + .owner = THIS_MODULE, + }, + .suspend = vrc4171_card_suspend, + .resume = vrc4171_card_resume, }; static int __devinit vrc4171_card_init(void) { int retval; - retval = driver_register(&vrc4171_card_driver); + retval = platform_driver_register(&vrc4171_card_driver); if (retval < 0) return retval; retval = platform_device_register(&vrc4171_card_device); if (retval < 0) { - driver_unregister(&vrc4171_card_driver); + platform_driver_unregister(&vrc4171_card_driver); return retval; } @@ -735,11 +748,12 @@ static int __devinit vrc4171_card_init(void) if (retval < 0) { vrc4171_remove_sockets(); platform_device_unregister(&vrc4171_card_device); - driver_unregister(&vrc4171_card_driver); + platform_driver_unregister(&vrc4171_card_driver); return retval; } - printk(KERN_INFO "%s, connected to IRQ %d\n", vrc4171_card_driver.name, vrc4171_irq); + printk(KERN_INFO "%s, connected to IRQ %d\n", + vrc4171_card_driver.driver.name, vrc4171_irq); return 0; } @@ -749,7 +763,7 @@ static void __devexit vrc4171_card_exit(void) free_irq(vrc4171_irq, vrc4171_sockets); vrc4171_remove_sockets(); platform_device_unregister(&vrc4171_card_device); - driver_unregister(&vrc4171_card_driver); + platform_driver_unregister(&vrc4171_card_driver); } module_init(vrc4171_card_init); diff --git a/drivers/scsi/a4000t.c b/drivers/scsi/a4000t.c index d4bda201774..6d25aca7b41 100644 --- a/drivers/scsi/a4000t.c +++ b/drivers/scsi/a4000t.c @@ -35,7 +35,7 @@ static struct platform_device *a4000t_scsi_device; #define A4000T_SCSI_ADDR 0xdd0040 -static int __devinit a4000t_probe(struct device *dev) +static int __devinit a4000t_probe(struct platform_device *dev) { struct Scsi_Host *host; struct NCR_700_Host_Parameters *hostdata; @@ -78,7 +78,7 @@ static int __devinit a4000t_probe(struct device *dev) goto out_put_host; } - dev_set_drvdata(dev, host); + platform_set_drvdata(dev, host); scsi_scan_host(host); return 0; @@ -93,9 +93,9 @@ static int __devinit a4000t_probe(struct device *dev) return -ENODEV; } -static __devexit int a4000t_device_remove(struct device *dev) +static __devexit int a4000t_device_remove(struct platform_device *dev) { - struct Scsi_Host *host = dev_get_drvdata(dev); + struct Scsi_Host *host = platform_get_drvdata(dev); struct NCR_700_Host_Parameters *hostdata = shost_priv(host); scsi_remove_host(host); @@ -108,25 +108,27 @@ static __devexit int a4000t_device_remove(struct device *dev) return 0; } -static struct device_driver a4000t_scsi_driver = { - .name = "a4000t-scsi", - .bus = &platform_bus_type, - .probe = a4000t_probe, - .remove = __devexit_p(a4000t_device_remove), +static struct platform_driver a4000t_scsi_driver = { + .driver = { + .name = "a4000t-scsi", + .owner = THIS_MODULE, + }, + .probe = a4000t_probe, + .remove = __devexit_p(a4000t_device_remove), }; static int __init a4000t_scsi_init(void) { int err; - err = driver_register(&a4000t_scsi_driver); + err = platform_driver_register(&a4000t_scsi_driver); if (err) return err; a4000t_scsi_device = platform_device_register_simple("a4000t-scsi", -1, NULL, 0); if (IS_ERR(a4000t_scsi_device)) { - driver_unregister(&a4000t_scsi_driver); + platform_driver_register(&a4000t_scsi_driver); return PTR_ERR(a4000t_scsi_device); } @@ -136,7 +138,7 @@ static int __init a4000t_scsi_init(void) static void __exit a4000t_scsi_exit(void) { platform_device_unregister(a4000t_scsi_device); - driver_unregister(&a4000t_scsi_driver); + platform_driver_unregister(&a4000t_scsi_driver); } module_init(a4000t_scsi_init); diff --git a/drivers/scsi/bvme6000_scsi.c b/drivers/scsi/bvme6000_scsi.c index d858f3d4127..9e9a82b03f2 100644 --- a/drivers/scsi/bvme6000_scsi.c +++ b/drivers/scsi/bvme6000_scsi.c @@ -34,7 +34,7 @@ static struct scsi_host_template bvme6000_scsi_driver_template = { static struct platform_device *bvme6000_scsi_device; static __devinit int -bvme6000_probe(struct device *dev) +bvme6000_probe(struct platform_device *dev) { struct Scsi_Host *host; struct NCR_700_Host_Parameters *hostdata; @@ -73,7 +73,7 @@ bvme6000_probe(struct device *dev) goto out_put_host; } - dev_set_drvdata(dev, host); + platform_set_drvdata(dev, host); scsi_scan_host(host); return 0; @@ -87,9 +87,9 @@ bvme6000_probe(struct device *dev) } static __devexit int -bvme6000_device_remove(struct device *dev) +bvme6000_device_remove(struct platform_device *dev) { - struct Scsi_Host *host = dev_get_drvdata(dev); + struct Scsi_Host *host = platform_get_drvdata(dev); struct NCR_700_Host_Parameters *hostdata = shost_priv(host); scsi_remove_host(host); @@ -100,25 +100,27 @@ bvme6000_device_remove(struct device *dev) return 0; } -static struct device_driver bvme6000_scsi_driver = { - .name = "bvme6000-scsi", - .bus = &platform_bus_type, - .probe = bvme6000_probe, - .remove = __devexit_p(bvme6000_device_remove), +static struct platform_driver bvme6000_scsi_driver = { + .driver = { + .name = "bvme6000-scsi", + .owner = THIS_MODULE, + }, + .probe = bvme6000_probe, + .remove = __devexit_p(bvme6000_device_remove), }; static int __init bvme6000_scsi_init(void) { int err; - err = driver_register(&bvme6000_scsi_driver); + err = platform_driver_register(&bvme6000_scsi_driver); if (err) return err; bvme6000_scsi_device = platform_device_register_simple("bvme6000-scsi", -1, NULL, 0); if (IS_ERR(bvme6000_scsi_device)) { - driver_unregister(&bvme6000_scsi_driver); + platform_driver_unregister(&bvme6000_scsi_driver); return PTR_ERR(bvme6000_scsi_device); } @@ -128,7 +130,7 @@ static int __init bvme6000_scsi_init(void) static void __exit bvme6000_scsi_exit(void) { platform_device_unregister(bvme6000_scsi_device); - driver_unregister(&bvme6000_scsi_driver); + platform_driver_unregister(&bvme6000_scsi_driver); } module_init(bvme6000_scsi_init); diff --git a/drivers/scsi/mvme16x_scsi.c b/drivers/scsi/mvme16x_scsi.c index b264b499d98..7794fc158b1 100644 --- a/drivers/scsi/mvme16x_scsi.c +++ b/drivers/scsi/mvme16x_scsi.c @@ -34,7 +34,7 @@ static struct scsi_host_template mvme16x_scsi_driver_template = { static struct platform_device *mvme16x_scsi_device; static __devinit int -mvme16x_probe(struct device *dev) +mvme16x_probe(struct platform_device *dev) { struct Scsi_Host * host = NULL; struct NCR_700_Host_Parameters *hostdata; @@ -88,7 +88,7 @@ mvme16x_probe(struct device *dev) out_be32(0xfff4202c, v); } - dev_set_drvdata(dev, host); + platform_set_drvdata(dev, host); scsi_scan_host(host); return 0; @@ -102,9 +102,9 @@ mvme16x_probe(struct device *dev) } static __devexit int -mvme16x_device_remove(struct device *dev) +mvme16x_device_remove(struct platform_device *dev) { - struct Scsi_Host *host = dev_get_drvdata(dev); + struct Scsi_Host *host = platform_get_drvdata(dev); struct NCR_700_Host_Parameters *hostdata = shost_priv(host); /* Disable scsi chip ints */ @@ -123,25 +123,27 @@ mvme16x_device_remove(struct device *dev) return 0; } -static struct device_driver mvme16x_scsi_driver = { - .name = "mvme16x-scsi", - .bus = &platform_bus_type, - .probe = mvme16x_probe, - .remove = __devexit_p(mvme16x_device_remove), +static struct platform_driver mvme16x_scsi_driver = { + .driver = { + .name = "mvme16x-scsi", + .owner = THIS_MODULE, + }, + .probe = mvme16x_probe, + .remove = __devexit_p(mvme16x_device_remove), }; static int __init mvme16x_scsi_init(void) { int err; - err = driver_register(&mvme16x_scsi_driver); + err = platform_driver_register(&mvme16x_scsi_driver); if (err) return err; mvme16x_scsi_device = platform_device_register_simple("mvme16x-scsi", -1, NULL, 0); if (IS_ERR(mvme16x_scsi_device)) { - driver_unregister(&mvme16x_scsi_driver); + platform_driver_unregister(&mvme16x_scsi_driver); return PTR_ERR(mvme16x_scsi_device); } @@ -151,7 +153,7 @@ static int __init mvme16x_scsi_init(void) static void __exit mvme16x_scsi_exit(void) { platform_device_unregister(mvme16x_scsi_device); - driver_unregister(&mvme16x_scsi_driver); + platform_driver_unregister(&mvme16x_scsi_driver); } module_init(mvme16x_scsi_init); diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c index 62bd4441b5e..378f27745a1 100644 --- a/drivers/video/au1100fb.c +++ b/drivers/video/au1100fb.c @@ -457,7 +457,7 @@ static struct fb_ops au1100fb_ops = /* AU1100 LCD controller device driver */ -static int __init au1100fb_drv_probe(struct device *dev) +static int __init au1100fb_drv_probe(struct platform_device *dev) { struct au1100fb_device *fbdev = NULL; struct resource *regs_res; @@ -475,7 +475,7 @@ static int __init au1100fb_drv_probe(struct device *dev) fbdev->panel = &known_lcd_panels[drv_info.panel_idx]; - dev_set_drvdata(dev, (void*)fbdev); + platform_set_drvdata(dev, (void *)fbdev); /* Allocate region for our registers and map them */ if (!(regs_res = platform_get_resource(to_platform_device(dev), @@ -583,19 +583,19 @@ failed: fb_dealloc_cmap(&fbdev->info.cmap); } kfree(fbdev); - dev_set_drvdata(dev, NULL); + platform_set_drvdata(dev, NULL); return 0; } -int au1100fb_drv_remove(struct device *dev) +int au1100fb_drv_remove(struct platform_device *dev) { struct au1100fb_device *fbdev = NULL; if (!dev) return -ENODEV; - fbdev = (struct au1100fb_device*) dev_get_drvdata(dev); + fbdev = (struct au1100fb_device *) platform_get_drvdata(dev); #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) au1100fb_fb_blank(VESA_POWERDOWN, &fbdev->info); @@ -620,9 +620,9 @@ int au1100fb_drv_remove(struct device *dev) static u32 sys_clksrc; static struct au1100fb_regs fbregs; -int au1100fb_drv_suspend(struct device *dev, pm_message_t state) +int au1100fb_drv_suspend(struct platform_device *dev, pm_message_t state) { - struct au1100fb_device *fbdev = dev_get_drvdata(dev); + struct au1100fb_device *fbdev = platform_get_drvdata(dev); if (!fbdev) return 0; @@ -641,9 +641,9 @@ int au1100fb_drv_suspend(struct device *dev, pm_message_t state) return 0; } -int au1100fb_drv_resume(struct device *dev) +int au1100fb_drv_resume(struct platform_device *dev) { - struct au1100fb_device *fbdev = dev_get_drvdata(dev); + struct au1100fb_device *fbdev = platform_get_drvdata(dev); if (!fbdev) return 0; @@ -663,10 +663,11 @@ int au1100fb_drv_resume(struct device *dev) #define au1100fb_drv_resume NULL #endif -static struct device_driver au1100fb_driver = { - .name = "au1100-lcd", - .bus = &platform_bus_type, - +static struct platform_driver au1100fb_driver = { + .driver = { + .name = "au1100-lcd", + .owner = THIS_MODULE, + }, .probe = au1100fb_drv_probe, .remove = au1100fb_drv_remove, .suspend = au1100fb_drv_suspend, @@ -753,12 +754,12 @@ int __init au1100fb_init(void) return ret; } - return driver_register(&au1100fb_driver); + return platform_driver_register(&au1100fb_driver); } void __exit au1100fb_cleanup(void) { - driver_unregister(&au1100fb_driver); + platform_driver_unregister(&au1100fb_driver); kfree(drv_info.opt_mode); } diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c index 03e57ef8837..0d96f1d2d4c 100644 --- a/drivers/video/au1200fb.c +++ b/drivers/video/au1200fb.c @@ -1622,7 +1622,7 @@ static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) /* AU1200 LCD controller device driver */ -static int au1200fb_drv_probe(struct device *dev) +static int au1200fb_drv_probe(struct platform_device *dev) { struct au1200fb_device *fbdev; unsigned long page; @@ -1645,7 +1645,7 @@ static int au1200fb_drv_probe(struct device *dev) /* Allocate the framebuffer to the maximum screen size */ fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8; - fbdev->fb_mem = dma_alloc_noncoherent(dev, + fbdev->fb_mem = dma_alloc_noncoherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len), &fbdev->fb_phys, GFP_KERNEL); if (!fbdev->fb_mem) { @@ -1715,7 +1715,7 @@ failed: return ret; } -static int au1200fb_drv_remove(struct device *dev) +static int au1200fb_drv_remove(struct platform_device *dev) { struct au1200fb_device *fbdev; int plane; @@ -1733,7 +1733,8 @@ static int au1200fb_drv_remove(struct device *dev) /* Clean up all probe data */ unregister_framebuffer(&fbdev->fb_info); if (fbdev->fb_mem) - dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len), + dma_free_noncoherent(&dev->dev, + PAGE_ALIGN(fbdev->fb_len), fbdev->fb_mem, fbdev->fb_phys); if (fbdev->fb_info.cmap.len != 0) fb_dealloc_cmap(&fbdev->fb_info.cmap); @@ -1747,22 +1748,24 @@ static int au1200fb_drv_remove(struct device *dev) } #ifdef CONFIG_PM -static int au1200fb_drv_suspend(struct device *dev, u32 state, u32 level) +static int au1200fb_drv_suspend(struct platform_device *dev, u32 state) { /* TODO */ return 0; } -static int au1200fb_drv_resume(struct device *dev, u32 level) +static int au1200fb_drv_resume(struct platform_device *dev) { /* TODO */ return 0; } #endif /* CONFIG_PM */ -static struct device_driver au1200fb_driver = { - .name = "au1200-lcd", - .bus = &platform_bus_type, +static struct platform_driver au1200fb_driver = { + .driver = { + .name = "au1200-lcd", + .owner = THIS_MODULE, + }, .probe = au1200fb_drv_probe, .remove = au1200fb_drv_remove, #ifdef CONFIG_PM @@ -1906,12 +1909,12 @@ static int __init au1200fb_init(void) printk(KERN_INFO "Power management device entry for the au1200fb loaded.\n"); #endif - return driver_register(&au1200fb_driver); + return platform_driver_register(&au1200fb_driver); } static void __exit au1200fb_cleanup(void) { - driver_unregister(&au1200fb_driver); + platform_driver_unregister(&au1200fb_driver); } module_init(au1200fb_init); diff --git a/drivers/watchdog/rm9k_wdt.c b/drivers/watchdog/rm9k_wdt.c index f1ae3729a19..cce1982a1b5 100644 --- a/drivers/watchdog/rm9k_wdt.c +++ b/drivers/watchdog/rm9k_wdt.c @@ -59,8 +59,8 @@ static long wdt_gpi_ioctl(struct file *, unsigned int, unsigned long); static int wdt_gpi_notify(struct notifier_block *, unsigned long, void *); static const struct resource *wdt_gpi_get_resource(struct platform_device *, const char *, unsigned int); -static int __init wdt_gpi_probe(struct device *); -static int __exit wdt_gpi_remove(struct device *); +static int __init wdt_gpi_probe(struct platform_device *); +static int __exit wdt_gpi_remove(struct platform_device *); static const char wdt_gpi_name[] = "wdt_gpi"; @@ -346,10 +346,9 @@ static const struct resource *wdt_gpi_get_resource(struct platform_device *pdv, } /* No hotplugging on the platform bus - use __init */ -static int __init wdt_gpi_probe(struct device *dev) +static int __init wdt_gpi_probe(struct platform_device *pdv) { int res; - struct platform_device * const pdv = to_platform_device(dev); const struct resource * const rr = wdt_gpi_get_resource(pdv, WDT_RESOURCE_REGS, IORESOURCE_MEM), @@ -374,7 +373,7 @@ static int __init wdt_gpi_probe(struct device *dev) return res; } -static int __exit wdt_gpi_remove(struct device *dev) +static int __exit wdt_gpi_remove(struct platform_device *dev) { int res; @@ -387,15 +386,13 @@ static int __exit wdt_gpi_remove(struct device *dev) /* Device driver init & exit */ -static struct device_driver wdt_gpi_driver = { - .name = (char *) wdt_gpi_name, - .bus = &platform_bus_type, - .owner = THIS_MODULE, +static struct platform_driver wgt_gpi_driver = { + .driver = { + .name = wdt_gpi_name, + .owner = THIS_MODULE, + }, .probe = wdt_gpi_probe, - .remove = __exit_p(wdt_gpi_remove), - .shutdown = NULL, - .suspend = NULL, - .resume = NULL, + .remove = __devexit_p(wdt_gpi_remove), }; static int __init wdt_gpi_init_module(void) @@ -403,12 +400,12 @@ static int __init wdt_gpi_init_module(void) atomic_set(&opencnt, 1); if (timeout > MAX_TIMEOUT_SECONDS) timeout = MAX_TIMEOUT_SECONDS; - return driver_register(&wdt_gpi_driver); + return platform_driver_register(&wdt_gpi_driver); } static void __exit wdt_gpi_cleanup_module(void) { - driver_unregister(&wdt_gpi_driver); + platform_driver_unregister(&wdt_gpi_driver); } module_init(wdt_gpi_init_module); -- GitLab From e5779a583ddb9916b37cfbb916dc53ec2eaf0b9b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 11 Mar 2009 09:23:52 +0100 Subject: [PATCH 4428/4982] scsi/m68k: Kill NCR_700_detect() warnings The patch from Ming Lei entitled: platform driver: fix incorrect use of 'platform_bus_type' with 'struct devic introduced the following warnings on m68k, as `dev' is now a `struct platform_device *' instead of a `struct device *': | drivers/scsi/a4000t.c:64: warning: passing argument 3 of 'NCR_700_detect' from incompatible pointer type | drivers/scsi/mvme16x_scsi.c:67: warning: passing argument 3 of 'NCR_700_detect' from incompatible pointer type | drivers/scsi/bvme6000_scsi.c:61: warning: passing argument 3 of 'NCR_700_detect' from incompatible pointer type I think the below is missing (untested on real hardware). Signed-off-by: Geert Uytterhoeven Cc: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/a4000t.c | 3 ++- drivers/scsi/bvme6000_scsi.c | 3 ++- drivers/scsi/mvme16x_scsi.c | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/a4000t.c b/drivers/scsi/a4000t.c index 6d25aca7b41..61af3d91ac8 100644 --- a/drivers/scsi/a4000t.c +++ b/drivers/scsi/a4000t.c @@ -61,7 +61,8 @@ static int __devinit a4000t_probe(struct platform_device *dev) hostdata->dcntl_extra = EA_710; /* and register the chip */ - host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata, dev); + host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata, + &dev->dev); if (!host) { printk(KERN_ERR "a4000t-scsi: No host detected; " "board configuration problem?\n"); diff --git a/drivers/scsi/bvme6000_scsi.c b/drivers/scsi/bvme6000_scsi.c index 9e9a82b03f2..5799cb5cba6 100644 --- a/drivers/scsi/bvme6000_scsi.c +++ b/drivers/scsi/bvme6000_scsi.c @@ -58,7 +58,8 @@ bvme6000_probe(struct platform_device *dev) hostdata->ctest7_extra = CTEST7_TT1; /* and register the chip */ - host = NCR_700_detect(&bvme6000_scsi_driver_template, hostdata, dev); + host = NCR_700_detect(&bvme6000_scsi_driver_template, hostdata, + &dev->dev); if (!host) { printk(KERN_ERR "bvme6000-scsi: No host detected; " "board configuration problem?\n"); diff --git a/drivers/scsi/mvme16x_scsi.c b/drivers/scsi/mvme16x_scsi.c index 7794fc158b1..b5fbfd6ce87 100644 --- a/drivers/scsi/mvme16x_scsi.c +++ b/drivers/scsi/mvme16x_scsi.c @@ -64,7 +64,8 @@ mvme16x_probe(struct platform_device *dev) hostdata->ctest7_extra = CTEST7_TT1; /* and register the chip */ - host = NCR_700_detect(&mvme16x_scsi_driver_template, hostdata, dev); + host = NCR_700_detect(&mvme16x_scsi_driver_template, hostdata, + &dev->dev); if (!host) { printk(KERN_ERR "mvme16x-scsi: No host detected; " "board configuration problem?\n"); -- GitLab From f48f3febb2cbfd0f2ecee7690835ba745c1034a4 Mon Sep 17 00:00:00 2001 From: Dave Young Date: Sat, 14 Feb 2009 21:23:22 +0800 Subject: [PATCH 4429/4982] driver-core: do not register a driver with bus_type not registered If the bus_type is not registerd, driver_register to that bus will cause oops. I found this bug when test built-in usb serial drivers (ie. aircable driver) with 'nousb' cmdline params. In this patch: 1. set the bus->p=NULL when bus_register failed and unregisterd. 2. if bus->p is NULL, driver_register BUG_ON will be triggered. Signed-off-by: Dave Young Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 2 ++ drivers/base/driver.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 8547b780bb5..11463c00451 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -932,6 +932,7 @@ bus_uevent_fail: kset_unregister(&bus->p->subsys); kfree(bus->p); out: + bus->p = NULL; return retval; } EXPORT_SYMBOL_GPL(bus_register); @@ -953,6 +954,7 @@ void bus_unregister(struct bus_type *bus) bus_remove_file(bus, &bus_attr_uevent); kset_unregister(&bus->p->subsys); kfree(bus->p); + bus->p = NULL; } EXPORT_SYMBOL_GPL(bus_unregister); diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 1e2bda780e4..2889ad57e48 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -216,6 +216,8 @@ int driver_register(struct device_driver *drv) int ret; struct device_driver *other; + BUG_ON(!drv->bus->p); + if ((drv->bus->probe && drv->probe) || (drv->bus->remove && drv->remove) || (drv->bus->shutdown && drv->shutdown)) -- GitLab From 425cb02912d1095febfeaf8d379af7b2ac9e4a89 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Thu, 12 Feb 2009 10:56:59 -0700 Subject: [PATCH 4430/4982] sysfs: sysfs_add_one WARNs with full path to duplicate filename sysfs: sysfs_add_one WARNs with full path to duplicate filename As a debugging aid, it can be useful to know the full path to a duplicate file being created in sysfs. We now will display warnings such as: sysfs: cannot create duplicate filename '/foo' when attempting to create multiple files named 'foo' in the sysfs root, or: sysfs: cannot create duplicate filename '/bus/pci/slots/5/foo' when attempting to create multiple files named 'foo' under a given directory in sysfs. The path displayed is always a relative path to sysfs_root. The leading '/' in the path name refers to the sysfs_root mount point, and should not be confused with the "real" '/'. Thanks to Alex Williamson for essentially writing sysfs_pathname. Cc: Alex Williamson Signed-off-by: Alex Chiang Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 82d3b79d0e0..f13d852ab3c 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -433,6 +433,26 @@ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) return 0; } +/** + * sysfs_pathname - return full path to sysfs dirent + * @sd: sysfs_dirent whose path we want + * @path: caller allocated buffer + * + * Gives the name "/" to the sysfs_root entry; any path returned + * is relative to wherever sysfs is mounted. + * + * XXX: does no error checking on @path size + */ +static char *sysfs_pathname(struct sysfs_dirent *sd, char *path) +{ + if (sd->s_parent) { + sysfs_pathname(sd->s_parent, path); + strcat(path, "/"); + } + strcat(path, sd->s_name); + return path; +} + /** * sysfs_add_one - add sysfs_dirent to parent * @acxt: addrm context to use @@ -458,8 +478,16 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) int ret; ret = __sysfs_add_one(acxt, sd); - WARN(ret == -EEXIST, KERN_WARNING "sysfs: duplicate filename '%s' " - "can not be created\n", sd->s_name); + if (ret == -EEXIST) { + char *path = kzalloc(PATH_MAX, GFP_KERNEL); + WARN(1, KERN_WARNING + "sysfs: cannot create duplicate filename '%s'\n", + (path == NULL) ? sd->s_name : + strcat(strcat(sysfs_pathname(acxt->parent_sd, path), "/"), + sd->s_name)); + kfree(path); + } + return ret; } -- GitLab From 04256b4a8fc73f54cd14f20867882c299728a446 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 11 Feb 2009 13:20:23 -0800 Subject: [PATCH 4431/4982] sysfs: reference sysfs_dirent from sysfs inodes The sysfs_dirent serves as both an inode and a directory entry for sysfs. To prevent the sysfs inode numbers from being freed prematurely hold a reference to sysfs_dirent from the sysfs inode. [akpm@linux-foundation.org: add comment] Signed-off-by: Eric W. Biederman Cc: Tejun Heo Cc: Al Viro Cc: Cornelia Huck Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/inode.c | 17 +++++++++++++++++ fs/sysfs/mount.c | 1 + fs/sysfs/sysfs.h | 1 + 3 files changed, 19 insertions(+) diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index dfa3d94cfc7..555f0ff988d 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -147,6 +147,7 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) { struct bin_attribute *bin_attr; + inode->i_private = sysfs_get(sd); inode->i_mapping->a_ops = &sysfs_aops; inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; inode->i_op = &sysfs_inode_operations; @@ -214,6 +215,22 @@ struct inode * sysfs_get_inode(struct sysfs_dirent *sd) return inode; } +/* + * The sysfs_dirent serves as both an inode and a directory entry for sysfs. + * To prevent the sysfs inode numbers from being freed prematurely we take a + * reference to sysfs_dirent from the sysfs inode. A + * super_operations.delete_inode() implementation is needed to drop that + * reference upon inode destruction. + */ +void sysfs_delete_inode(struct inode *inode) +{ + struct sysfs_dirent *sd = inode->i_private; + + truncate_inode_pages(&inode->i_data, 0); + clear_inode(inode); + sysfs_put(sd); +} + int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) { struct sysfs_addrm_cxt acxt; diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 84ef378673a..49749955cca 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -29,6 +29,7 @@ struct kmem_cache *sysfs_dir_cachep; static const struct super_operations sysfs_ops = { .statfs = simple_statfs, .drop_inode = generic_delete_inode, + .delete_inode = sysfs_delete_inode, }; struct sysfs_dirent sysfs_root = { diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 93c6d6b27c4..9055d04e4ab 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -145,6 +145,7 @@ static inline void __sysfs_put(struct sysfs_dirent *sd) * inode.c */ struct inode *sysfs_get_inode(struct sysfs_dirent *sd); +void sysfs_delete_inode(struct inode *inode); int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); int sysfs_inode_init(void); -- GitLab From b23530ebc339c4092ae2c9f37341a5398fea8b89 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sat, 21 Feb 2009 16:45:07 +0800 Subject: [PATCH 4432/4982] driver core: remove polling for driver_probe_done(v5) This patch removes 100ms polling for driver_probe_done in wait_for_device_probe(), and uses wait_event() instead. Removing polling in fs initialization may lead to a faster boot. This patch also changes the return type of wait_for_device_done() from int to void. This patch is against Arjan's patch in linux-next tree. Signed-off-by: Ming Lei Acked-by: Cornelia Huck Reviewed-by: Arjan van de Ven Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 8 ++------ include/linux/device.h | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 3f32df7ed37..0dfd08c1592 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -172,16 +172,12 @@ int driver_probe_done(void) /** * wait_for_device_probe * Wait for device probing to be completed. - * - * Note: this function polls at 100 msec intervals. */ -int wait_for_device_probe(void) +void wait_for_device_probe(void) { /* wait for the known devices to complete their probing */ - while (driver_probe_done() != 0) - msleep(100); + wait_event(probe_waitqueue, atomic_read(&probe_count) == 0); async_synchronize_full(); - return 0; } /** diff --git a/include/linux/device.h b/include/linux/device.h index d5706c448bc..c56b154a0bf 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -147,7 +147,7 @@ extern void put_driver(struct device_driver *drv); extern struct device_driver *driver_find(const char *name, struct bus_type *bus); extern int driver_probe_done(void); -extern int wait_for_device_probe(void); +extern void wait_for_device_probe(void); /* sysfs interface for exporting driver attributes */ -- GitLab From fb069a5d132fb926ed17af3211a114ac7cf27d7a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 16 Dec 2008 12:23:36 -0800 Subject: [PATCH 4433/4982] driver core: create a private portion of struct device This is to be used to move things out of struct device that no code outside of the driver core should ever touch. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 12 ++++++++++++ drivers/base/core.c | 9 +++++++++ include/linux/device.h | 3 +++ 3 files changed, 24 insertions(+) diff --git a/drivers/base/base.h b/drivers/base/base.h index ca2b0376685..62a2cb5e178 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -63,6 +63,18 @@ struct class_private { #define to_class(obj) \ container_of(obj, struct class_private, class_subsys.kobj) +/** + * struct device_private - structure to hold the private to the driver core portions of the device structure. + * + * @device - pointer back to the struct class that this structure is + * associated with. + * + * Nothing outside of the driver core should ever touch these fields. + */ +struct device_private { + struct device *device; +}; + /* initialisation functions */ extern int devices_init(void); extern int buses_init(void); diff --git a/drivers/base/core.c b/drivers/base/core.c index 059966b617f..16d85991010 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -109,6 +109,7 @@ static struct sysfs_ops dev_sysfs_ops = { static void device_release(struct kobject *kobj) { struct device *dev = to_dev(kobj); + struct device_private *p = dev->p; if (dev->release) dev->release(dev); @@ -120,6 +121,7 @@ static void device_release(struct kobject *kobj) WARN(1, KERN_ERR "Device '%s' does not have a release() " "function, it is broken and must be fixed.\n", dev_name(dev)); + kfree(p); } static struct kobj_type device_ktype = { @@ -859,6 +861,13 @@ int device_add(struct device *dev) if (!dev) goto done; + dev->p = kzalloc(sizeof(*dev->p), GFP_KERNEL); + if (!dev->p) { + error = -ENOMEM; + goto done; + } + dev->p->device = dev; + /* * for statically allocated devices, which should all be converted * some day, we need to initialize the name. We prevent reading back diff --git a/include/linux/device.h b/include/linux/device.h index c56b154a0bf..4cf063fea2a 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -28,6 +28,7 @@ #define BUS_ID_SIZE 20 struct device; +struct device_private; struct device_driver; struct driver_private; struct class; @@ -373,6 +374,8 @@ struct device { struct klist_node knode_bus; struct device *parent; + struct device_private *p; + struct kobject kobj; unsigned uevent_suppress:1; const char *init_name; /* initial name of the device */ -- GitLab From f791b8c836307b58cbf62133a6a772ed1a92fb33 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 16 Dec 2008 12:24:56 -0800 Subject: [PATCH 4434/4982] driver core: move klist_children into private structure Nothing outside of the driver core should ever touch klist_children, or knode_parent, so move them out of the public eye. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 6 ++++++ drivers/base/core.c | 39 +++++++++++++++++++++++++-------------- include/linux/device.h | 2 -- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/drivers/base/base.h b/drivers/base/base.h index 62a2cb5e178..7c4fafc314c 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -66,14 +66,20 @@ struct class_private { /** * struct device_private - structure to hold the private to the driver core portions of the device structure. * + * @klist_children - klist containing all children of this device + * @knode_parent - node in sibling list * @device - pointer back to the struct class that this structure is * associated with. * * Nothing outside of the driver core should ever touch these fields. */ struct device_private { + struct klist klist_children; + struct klist_node knode_parent; struct device *device; }; +#define to_device_private_parent(obj) \ + container_of(obj, struct device_private, knode_parent) /* initialisation functions */ extern int devices_init(void); diff --git a/drivers/base/core.c b/drivers/base/core.c index 16d85991010..a90f56f64d6 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -509,14 +509,16 @@ EXPORT_SYMBOL_GPL(device_schedule_callback_owner); static void klist_children_get(struct klist_node *n) { - struct device *dev = container_of(n, struct device, knode_parent); + struct device_private *p = to_device_private_parent(n); + struct device *dev = p->device; get_device(dev); } static void klist_children_put(struct klist_node *n) { - struct device *dev = container_of(n, struct device, knode_parent); + struct device_private *p = to_device_private_parent(n); + struct device *dev = p->device; put_device(dev); } @@ -540,8 +542,6 @@ void device_initialize(struct device *dev) { dev->kobj.kset = devices_kset; kobject_init(&dev->kobj, &device_ktype); - klist_init(&dev->klist_children, klist_children_get, - klist_children_put); INIT_LIST_HEAD(&dev->dma_pools); init_MUTEX(&dev->sem); spin_lock_init(&dev->devres_lock); @@ -867,6 +867,8 @@ int device_add(struct device *dev) goto done; } dev->p->device = dev; + klist_init(&dev->p->klist_children, klist_children_get, + klist_children_put); /* * for statically allocated devices, which should all be converted @@ -937,7 +939,8 @@ int device_add(struct device *dev) kobject_uevent(&dev->kobj, KOBJ_ADD); bus_attach_device(dev); if (parent) - klist_add_tail(&dev->knode_parent, &parent->klist_children); + klist_add_tail(&dev->p->knode_parent, + &parent->p->klist_children); if (dev->class) { mutex_lock(&dev->class->p->class_mutex); @@ -1051,7 +1054,7 @@ void device_del(struct device *dev) device_pm_remove(dev); dpm_sysfs_remove(dev); if (parent) - klist_del(&dev->knode_parent); + klist_del(&dev->p->knode_parent); if (MAJOR(dev->devt)) { device_remove_sys_dev_entry(dev); device_remove_file(dev, &devt_attr); @@ -1112,7 +1115,14 @@ void device_unregister(struct device *dev) static struct device *next_device(struct klist_iter *i) { struct klist_node *n = klist_next(i); - return n ? container_of(n, struct device, knode_parent) : NULL; + struct device *dev = NULL; + struct device_private *p; + + if (n) { + p = to_device_private_parent(n); + dev = p->device; + } + return dev; } /** @@ -1134,7 +1144,7 @@ int device_for_each_child(struct device *parent, void *data, struct device *child; int error = 0; - klist_iter_init(&parent->klist_children, &i); + klist_iter_init(&parent->p->klist_children, &i); while ((child = next_device(&i)) && !error) error = fn(child, data); klist_iter_exit(&i); @@ -1165,7 +1175,7 @@ struct device *device_find_child(struct device *parent, void *data, if (!parent) return NULL; - klist_iter_init(&parent->klist_children, &i); + klist_iter_init(&parent->p->klist_children, &i); while ((child = next_device(&i))) if (match(child, data) && get_device(child)) break; @@ -1578,9 +1588,10 @@ int device_move(struct device *dev, struct device *new_parent) old_parent = dev->parent; dev->parent = new_parent; if (old_parent) - klist_remove(&dev->knode_parent); + klist_remove(&dev->p->knode_parent); if (new_parent) { - klist_add_tail(&dev->knode_parent, &new_parent->klist_children); + klist_add_tail(&dev->p->knode_parent, + &new_parent->p->klist_children); set_dev_node(dev, dev_to_node(new_parent)); } @@ -1592,11 +1603,11 @@ int device_move(struct device *dev, struct device *new_parent) device_move_class_links(dev, new_parent, old_parent); if (!kobject_move(&dev->kobj, &old_parent->kobj)) { if (new_parent) - klist_remove(&dev->knode_parent); + klist_remove(&dev->p->knode_parent); dev->parent = old_parent; if (old_parent) { - klist_add_tail(&dev->knode_parent, - &old_parent->klist_children); + klist_add_tail(&dev->p->knode_parent, + &old_parent->p->klist_children); set_dev_node(dev, dev_to_node(old_parent)); } } diff --git a/include/linux/device.h b/include/linux/device.h index 4cf063fea2a..808d808ec69 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -368,8 +368,6 @@ struct device_dma_parameters { }; struct device { - struct klist klist_children; - struct klist_node knode_parent; /* node in sibling list */ struct klist_node knode_driver; struct klist_node knode_bus; struct device *parent; -- GitLab From 8940b4f312dced51b45004819b776ec3aa7fcd5d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 16 Dec 2008 12:25:49 -0800 Subject: [PATCH 4435/4982] driver core: move knode_driver into private structure Nothing outside of the driver core should ever touch knode_driver, so move it out of the public eye. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 4 ++++ drivers/base/dd.c | 13 ++++++++----- drivers/base/driver.c | 13 ++++++++++--- include/linux/device.h | 1 - 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/drivers/base/base.h b/drivers/base/base.h index 7c4fafc314c..4fc5fd3984c 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -68,6 +68,7 @@ struct class_private { * * @klist_children - klist containing all children of this device * @knode_parent - node in sibling list + * @knode_driver - node in driver list * @device - pointer back to the struct class that this structure is * associated with. * @@ -76,10 +77,13 @@ struct class_private { struct device_private { struct klist klist_children; struct klist_node knode_parent; + struct klist_node knode_driver; struct device *device; }; #define to_device_private_parent(obj) \ container_of(obj, struct device_private, knode_parent) +#define to_device_private_driver(obj) \ + container_of(obj, struct device_private, knode_driver) /* initialisation functions */ extern int devices_init(void); diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 0dfd08c1592..f17c3266a0e 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -30,7 +30,7 @@ static void driver_bound(struct device *dev) { - if (klist_node_attached(&dev->knode_driver)) { + if (klist_node_attached(&dev->p->knode_driver)) { printk(KERN_WARNING "%s: device %s already bound\n", __func__, kobject_name(&dev->kobj)); return; @@ -43,7 +43,7 @@ static void driver_bound(struct device *dev) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_BOUND_DRIVER, dev); - klist_add_tail(&dev->knode_driver, &dev->driver->p->klist_devices); + klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices); } static int driver_sysfs_add(struct device *dev) @@ -318,7 +318,7 @@ static void __device_release_driver(struct device *dev) drv->remove(dev); devres_release_all(dev); dev->driver = NULL; - klist_remove(&dev->knode_driver); + klist_remove(&dev->p->knode_driver); } } @@ -348,6 +348,7 @@ EXPORT_SYMBOL_GPL(device_release_driver); */ void driver_detach(struct device_driver *drv) { + struct device_private *dev_prv; struct device *dev; for (;;) { @@ -356,8 +357,10 @@ void driver_detach(struct device_driver *drv) spin_unlock(&drv->p->klist_devices.k_lock); break; } - dev = list_entry(drv->p->klist_devices.k_list.prev, - struct device, knode_driver.n_node); + dev_prv = list_entry(drv->p->klist_devices.k_list.prev, + struct device_private, + knode_driver.n_node); + dev = dev_prv->device; get_device(dev); spin_unlock(&drv->p->klist_devices.k_lock); diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 2889ad57e48..c51f11bb29a 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -19,7 +19,14 @@ static struct device *next_device(struct klist_iter *i) { struct klist_node *n = klist_next(i); - return n ? container_of(n, struct device, knode_driver) : NULL; + struct device *dev = NULL; + struct device_private *dev_prv; + + if (n) { + dev_prv = to_device_private_driver(n); + dev = dev_prv->device; + } + return dev; } /** @@ -42,7 +49,7 @@ int driver_for_each_device(struct device_driver *drv, struct device *start, return -EINVAL; klist_iter_init_node(&drv->p->klist_devices, &i, - start ? &start->knode_driver : NULL); + start ? &start->p->knode_driver : NULL); while ((dev = next_device(&i)) && !error) error = fn(dev, data); klist_iter_exit(&i); @@ -76,7 +83,7 @@ struct device *driver_find_device(struct device_driver *drv, return NULL; klist_iter_init_node(&drv->p->klist_devices, &i, - (start ? &start->knode_driver : NULL)); + (start ? &start->p->knode_driver : NULL)); while ((dev = next_device(&i))) if (match(dev, data) && get_device(dev)) break; diff --git a/include/linux/device.h b/include/linux/device.h index 808d808ec69..83e241f407b 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -368,7 +368,6 @@ struct device_dma_parameters { }; struct device { - struct klist_node knode_driver; struct klist_node knode_bus; struct device *parent; -- GitLab From ae1b41715ee2aae356fbcca032838b71d70b855f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 16 Dec 2008 12:26:21 -0800 Subject: [PATCH 4436/4982] driver core: move knode_bus into private structure Nothing outside of the driver core should ever touch knode_bus, so move it out of the public eye. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 4 ++++ drivers/base/bus.c | 40 +++++++++++++++++++++++++++------------- include/linux/device.h | 1 - 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/drivers/base/base.h b/drivers/base/base.h index 4fc5fd3984c..ddc97496db4 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -69,6 +69,7 @@ struct class_private { * @klist_children - klist containing all children of this device * @knode_parent - node in sibling list * @knode_driver - node in driver list + * @knode_bus - node in bus list * @device - pointer back to the struct class that this structure is * associated with. * @@ -78,12 +79,15 @@ struct device_private { struct klist klist_children; struct klist_node knode_parent; struct klist_node knode_driver; + struct klist_node knode_bus; struct device *device; }; #define to_device_private_parent(obj) \ container_of(obj, struct device_private, knode_parent) #define to_device_private_driver(obj) \ container_of(obj, struct device_private, knode_driver) +#define to_device_private_bus(obj) \ + container_of(obj, struct device_private, knode_bus) /* initialisation functions */ extern int devices_init(void); diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 11463c00451..dc030f1f00f 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -253,7 +253,14 @@ static ssize_t store_drivers_probe(struct bus_type *bus, static struct device *next_device(struct klist_iter *i) { struct klist_node *n = klist_next(i); - return n ? container_of(n, struct device, knode_bus) : NULL; + struct device *dev = NULL; + struct device_private *dev_prv; + + if (n) { + dev_prv = to_device_private_bus(n); + dev = dev_prv->device; + } + return dev; } /** @@ -286,7 +293,7 @@ int bus_for_each_dev(struct bus_type *bus, struct device *start, return -EINVAL; klist_iter_init_node(&bus->p->klist_devices, &i, - (start ? &start->knode_bus : NULL)); + (start ? &start->p->knode_bus : NULL)); while ((dev = next_device(&i)) && !error) error = fn(dev, data); klist_iter_exit(&i); @@ -320,7 +327,7 @@ struct device *bus_find_device(struct bus_type *bus, return NULL; klist_iter_init_node(&bus->p->klist_devices, &i, - (start ? &start->knode_bus : NULL)); + (start ? &start->p->knode_bus : NULL)); while ((dev = next_device(&i))) if (match(dev, data) && get_device(dev)) break; @@ -507,7 +514,8 @@ void bus_attach_device(struct device *dev) ret = device_attach(dev); WARN_ON(ret < 0); if (ret >= 0) - klist_add_tail(&dev->knode_bus, &bus->p->klist_devices); + klist_add_tail(&dev->p->knode_bus, + &bus->p->klist_devices); } } @@ -528,8 +536,8 @@ void bus_remove_device(struct device *dev) sysfs_remove_link(&dev->bus->p->devices_kset->kobj, dev_name(dev)); device_remove_attrs(dev->bus, dev); - if (klist_node_attached(&dev->knode_bus)) - klist_del(&dev->knode_bus); + if (klist_node_attached(&dev->p->knode_bus)) + klist_del(&dev->p->knode_bus); pr_debug("bus: '%s': remove device %s\n", dev->bus->name, dev_name(dev)); @@ -831,14 +839,16 @@ static void bus_remove_attrs(struct bus_type *bus) static void klist_devices_get(struct klist_node *n) { - struct device *dev = container_of(n, struct device, knode_bus); + struct device_private *dev_prv = to_device_private_bus(n); + struct device *dev = dev_prv->device; get_device(dev); } static void klist_devices_put(struct klist_node *n) { - struct device *dev = container_of(n, struct device, knode_bus); + struct device_private *dev_prv = to_device_private_bus(n); + struct device *dev = dev_prv->device; put_device(dev); } @@ -995,18 +1005,20 @@ static void device_insertion_sort_klist(struct device *a, struct list_head *list { struct list_head *pos; struct klist_node *n; + struct device_private *dev_prv; struct device *b; list_for_each(pos, list) { n = container_of(pos, struct klist_node, n_node); - b = container_of(n, struct device, knode_bus); + dev_prv = to_device_private_bus(n); + b = dev_prv->device; if (compare(a, b) <= 0) { - list_move_tail(&a->knode_bus.n_node, - &b->knode_bus.n_node); + list_move_tail(&a->p->knode_bus.n_node, + &b->p->knode_bus.n_node); return; } } - list_move_tail(&a->knode_bus.n_node, list); + list_move_tail(&a->p->knode_bus.n_node, list); } void bus_sort_breadthfirst(struct bus_type *bus, @@ -1016,6 +1028,7 @@ void bus_sort_breadthfirst(struct bus_type *bus, LIST_HEAD(sorted_devices); struct list_head *pos, *tmp; struct klist_node *n; + struct device_private *dev_prv; struct device *dev; struct klist *device_klist; @@ -1024,7 +1037,8 @@ void bus_sort_breadthfirst(struct bus_type *bus, spin_lock(&device_klist->k_lock); list_for_each_safe(pos, tmp, &device_klist->k_list) { n = container_of(pos, struct klist_node, n_node); - dev = container_of(n, struct device, knode_bus); + dev_prv = to_device_private_bus(n); + dev = dev_prv->device; device_insertion_sort_klist(dev, &sorted_devices, compare); } list_splice(&sorted_devices, &device_klist->k_list); diff --git a/include/linux/device.h b/include/linux/device.h index 83e241f407b..5a64775e68e 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -368,7 +368,6 @@ struct device_dma_parameters { }; struct device { - struct klist_node knode_bus; struct device *parent; struct device_private *p; -- GitLab From e0edd3c65aa5b53e20280565a7ce11675eb7ed6b Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 4 Mar 2009 11:57:20 -0800 Subject: [PATCH 4437/4982] sysfs: don't block indefinitely for unmapped files. Modify sysfs bin files so that we can remove the bin file while they are still mapped. When the kobject is removed we unmap the bin file and arrange for future accesses to the mapping to receive SIGBUS. Implementing this prevents a nasty DOS when pci devices are hot plugged and unplugged. Where if any of their resources were mmaped the kernel could not free up their pci resources or release their pci data structures. [akpm@linux-foundation.org: remove unused var] Signed-off-by: Eric W. Biederman Cc: Jesse Barnes Acked-by: Tejun Heo Cc: Kay Sievers Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/bin.c | 184 +++++++++++++++++++++++++++++++++++++++++++---- fs/sysfs/dir.c | 1 + fs/sysfs/sysfs.h | 2 + 3 files changed, 174 insertions(+), 13 deletions(-) diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index f2c478c3424..96cc2bf6a84 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c @@ -21,15 +21,28 @@ #include #include #include +#include #include #include "sysfs.h" +/* + * There's one bin_buffer for each open file. + * + * filp->private_data points to bin_buffer and + * sysfs_dirent->s_bin_attr.buffers points to a the bin_buffer s + * sysfs_dirent->s_bin_attr.buffers is protected by sysfs_bin_lock + */ +static DEFINE_MUTEX(sysfs_bin_lock); + struct bin_buffer { - struct mutex mutex; - void *buffer; - int mmapped; + struct mutex mutex; + void *buffer; + int mmapped; + struct vm_operations_struct *vm_ops; + struct file *file; + struct hlist_node list; }; static int @@ -168,29 +181,148 @@ out_free: return count; } +static void bin_vma_open(struct vm_area_struct *vma) +{ + struct file *file = vma->vm_file; + struct bin_buffer *bb = file->private_data; + struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; + + if (!bb->vm_ops || !bb->vm_ops->open) + return; + + if (!sysfs_get_active_two(attr_sd)) + return; + + bb->vm_ops->open(vma); + + sysfs_put_active_two(attr_sd); +} + +static void bin_vma_close(struct vm_area_struct *vma) +{ + struct file *file = vma->vm_file; + struct bin_buffer *bb = file->private_data; + struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; + + if (!bb->vm_ops || !bb->vm_ops->close) + return; + + if (!sysfs_get_active_two(attr_sd)) + return; + + bb->vm_ops->close(vma); + + sysfs_put_active_two(attr_sd); +} + +static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + struct file *file = vma->vm_file; + struct bin_buffer *bb = file->private_data; + struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; + int ret; + + if (!bb->vm_ops || !bb->vm_ops->fault) + return VM_FAULT_SIGBUS; + + if (!sysfs_get_active_two(attr_sd)) + return VM_FAULT_SIGBUS; + + ret = bb->vm_ops->fault(vma, vmf); + + sysfs_put_active_two(attr_sd); + return ret; +} + +static int bin_page_mkwrite(struct vm_area_struct *vma, struct page *page) +{ + struct file *file = vma->vm_file; + struct bin_buffer *bb = file->private_data; + struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; + int ret; + + if (!bb->vm_ops || !bb->vm_ops->page_mkwrite) + return -EINVAL; + + if (!sysfs_get_active_two(attr_sd)) + return -EINVAL; + + ret = bb->vm_ops->page_mkwrite(vma, page); + + sysfs_put_active_two(attr_sd); + return ret; +} + +static int bin_access(struct vm_area_struct *vma, unsigned long addr, + void *buf, int len, int write) +{ + struct file *file = vma->vm_file; + struct bin_buffer *bb = file->private_data; + struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; + int ret; + + if (!bb->vm_ops || !bb->vm_ops->access) + return -EINVAL; + + if (!sysfs_get_active_two(attr_sd)) + return -EINVAL; + + ret = bb->vm_ops->access(vma, addr, buf, len, write); + + sysfs_put_active_two(attr_sd); + return ret; +} + +static struct vm_operations_struct bin_vm_ops = { + .open = bin_vma_open, + .close = bin_vma_close, + .fault = bin_fault, + .page_mkwrite = bin_page_mkwrite, + .access = bin_access, +}; + static int mmap(struct file *file, struct vm_area_struct *vma) { struct bin_buffer *bb = file->private_data; struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr; struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; + struct vm_operations_struct *vm_ops; int rc; mutex_lock(&bb->mutex); /* need attr_sd for attr, its parent for kobj */ + rc = -ENODEV; if (!sysfs_get_active_two(attr_sd)) - return -ENODEV; + goto out_unlock; rc = -EINVAL; - if (attr->mmap) - rc = attr->mmap(kobj, attr, vma); + if (!attr->mmap) + goto out_put; - if (rc == 0 && !bb->mmapped) - bb->mmapped = 1; - else - sysfs_put_active_two(attr_sd); + rc = attr->mmap(kobj, attr, vma); + vm_ops = vma->vm_ops; + vma->vm_ops = &bin_vm_ops; + if (rc) + goto out_put; + rc = -EINVAL; + if (bb->mmapped && bb->vm_ops != vma->vm_ops) + goto out_put; + +#ifdef CONFIG_NUMA + rc = -EINVAL; + if (vm_ops && ((vm_ops->set_policy || vm_ops->get_policy || vm_ops->migrate))) + goto out_put; +#endif + + rc = 0; + bb->mmapped = 1; + bb->vm_ops = vm_ops; +out_put: + sysfs_put_active_two(attr_sd); +out_unlock: mutex_unlock(&bb->mutex); return rc; @@ -223,8 +355,13 @@ static int open(struct inode * inode, struct file * file) goto err_out; mutex_init(&bb->mutex); + bb->file = file; file->private_data = bb; + mutex_lock(&sysfs_bin_lock); + hlist_add_head(&bb->list, &attr_sd->s_bin_attr.buffers); + mutex_unlock(&sysfs_bin_lock); + /* open succeeded, put active references */ sysfs_put_active_two(attr_sd); return 0; @@ -237,11 +374,12 @@ static int open(struct inode * inode, struct file * file) static int release(struct inode * inode, struct file * file) { - struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; struct bin_buffer *bb = file->private_data; - if (bb->mmapped) - sysfs_put_active_two(attr_sd); + mutex_lock(&sysfs_bin_lock); + hlist_del(&bb->list); + mutex_unlock(&sysfs_bin_lock); + kfree(bb->buffer); kfree(bb); return 0; @@ -256,6 +394,26 @@ const struct file_operations bin_fops = { .release = release, }; + +void unmap_bin_file(struct sysfs_dirent *attr_sd) +{ + struct bin_buffer *bb; + struct hlist_node *tmp; + + if (sysfs_type(attr_sd) != SYSFS_KOBJ_BIN_ATTR) + return; + + mutex_lock(&sysfs_bin_lock); + + hlist_for_each_entry(bb, tmp, &attr_sd->s_bin_attr.buffers, list) { + struct inode *inode = bb->file->f_path.dentry->d_inode; + + unmap_mapping_range(inode->i_mapping, 0, 0, 1); + } + + mutex_unlock(&sysfs_bin_lock); +} + /** * sysfs_create_bin_file - create binary file for object. * @kobj: object. diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index f13d852ab3c..66aeb4fff0c 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -609,6 +609,7 @@ void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) sysfs_drop_dentry(sd); sysfs_deactivate(sd); + unmap_bin_file(sd); sysfs_put(sd); } } diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 9055d04e4ab..3fa0d98481e 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -28,6 +28,7 @@ struct sysfs_elem_attr { struct sysfs_elem_bin_attr { struct bin_attribute *bin_attr; + struct hlist_head buffers; }; /* @@ -164,6 +165,7 @@ int sysfs_add_file_mode(struct sysfs_dirent *dir_sd, * bin.c */ extern const struct file_operations bin_fops; +void unmap_bin_file(struct sysfs_dirent *attr_sd); /* * symlink.c -- GitLab From 006f4571a15fae3a0575f2a0f9e9b63b3d1012f8 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sun, 8 Mar 2009 23:13:32 +0800 Subject: [PATCH 4438/4982] driver core: move platform_data into platform_device This patch moves platform_data from struct device into struct platform_device, based on the two ideas: 1. Now all platform_driver is registered by platform_driver_register, which makes probe()/release()/... of platform_driver passed parameter of platform_device *, so platform driver can get platform_data from platform_device; 2. Other kind of devices do not need to use platform_data, we can decrease size of device if moving it to platform_device. Taking into consideration of thousands of files to be fixed and they can't be finished in one night(maybe it will take a long time), so we keep platform_data in device to allow two kind of cases coexist until all platform devices pass its platfrom data from platform_device->platform_data. All patches to do this kind of conversion are welcome. Signed-off-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 3 +++ include/linux/device.h | 9 +++++++-- include/linux/platform_device.h | 1 + 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index ec993aa6a2c..c5ac81d2230 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -217,6 +217,7 @@ int platform_device_add_data(struct platform_device *pdev, const void *data, if (d) { memcpy(d, data, size); pdev->dev.platform_data = d; + pdev->platform_data = d; } return d ? 0 : -ENOMEM; } @@ -246,6 +247,8 @@ int platform_device_add(struct platform_device *pdev) else dev_set_name(&pdev->dev, pdev->name); + pdev->platform_data = pdev->dev.platform_data; + for (i = 0; i < pdev->num_resources; i++) { struct resource *p, *r = &pdev->resource[i]; diff --git a/include/linux/device.h b/include/linux/device.h index 5a64775e68e..4bea53fe8f4 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -385,8 +385,13 @@ struct device { struct device_driver *driver; /* which driver has allocated this device */ void *driver_data; /* data private to the driver */ - void *platform_data; /* Platform specific data, device - core doesn't touch it */ + + void *platform_data; /* We will remove platform_data + field if all platform devices + pass its platform specific data + from platform_device->platform_data, + other kind of devices should not + use platform_data. */ struct dev_pm_info power; #ifdef CONFIG_NUMA diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 76aef7be32a..76e470a299b 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -20,6 +20,7 @@ struct platform_device { struct device dev; u32 num_resources; struct resource * resource; + void *platform_data; struct platform_device_id *id_entry; }; -- GitLab From ce21c7bcd796fc4f45d48781b7e85f493cc55ee5 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Fri, 13 Mar 2009 23:06:59 +0800 Subject: [PATCH 4439/4982] driver core: fix passing platform_data We will remove platform_data field from struct device until all platform devices pass its specific data from platfom_device and all platform drivers use platform specific data passed by platform_device->platform_data. This kind of conversion will need a long time, for thousands of files is affected. To make the conversion easily, we allow platform specific data passed by struct device or struct platform_device and platform driver may use it from struct device or struct platform_device. Signed-off-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index c5ac81d2230..d2198f64ad4 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -247,7 +247,20 @@ int platform_device_add(struct platform_device *pdev) else dev_set_name(&pdev->dev, pdev->name); - pdev->platform_data = pdev->dev.platform_data; + /* We will remove platform_data field from struct device + * if all platform devices pass its platform specific data + * from platform_device. The conversion is going to be a + * long time, so we allow the two cases coexist to make + * this kind of fix more easily*/ + if (pdev->platform_data && pdev->dev.platform_data) { + printk(KERN_ERR + "%s: use which platform_data?\n", + dev_name(&pdev->dev)); + } else if (pdev->platform_data) { + pdev->dev.platform_data = pdev->platform_data; + } else if (pdev->dev.platform_data) { + pdev->platform_data = pdev->dev.platform_data; + } for (i = 0; i < pdev->num_resources; i++) { struct resource *p, *r = &pdev->resource[i]; -- GitLab From 4995f8ef9d3aac72745e12419d7fbaa8d01b1d81 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Mon, 9 Mar 2009 14:18:52 +0100 Subject: [PATCH 4440/4982] vcs: hook sysfs devices into object lifetime instead of "binding" During bootup performance tracing I noticed many occurrences of vca* device creation and removal, leading to the usual userspace uevent processing, which are, in this case, rather pointless. A simple test showing the kernel timing (not including all the work userspace has to do), gives us these numbers: $ time for i in `seq 1000`; do echo a > /dev/tty2; done real 0m1.142s user 0m0.015s sys 0m0.540s If we move the hook for the vcs* driver core devices from the tty "binding" to the vc allocation/deallocation, which is what the vcs* devices represent, we get the following numbers: $ time for i in `seq 1000`; do echo a > /dev/tty2; done real 0m0.152s user 0m0.030s sys 0m0.072s Cc: Alan Cox Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/char/vc_screen.c | 16 ++++++++-------- drivers/char/vt.c | 5 +++-- include/linux/console.h | 4 ++-- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index 4f3b3f95fc4..d94d25c12aa 100644 --- a/drivers/char/vc_screen.c +++ b/drivers/char/vc_screen.c @@ -479,18 +479,18 @@ static const struct file_operations vcs_fops = { static struct class *vc_class; -void vcs_make_sysfs(struct tty_struct *tty) +void vcs_make_sysfs(int index) { - device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1), NULL, - "vcs%u", tty->index + 1); - device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129), NULL, - "vcsa%u", tty->index + 1); + device_create(vc_class, NULL, MKDEV(VCS_MAJOR, index + 1), NULL, + "vcs%u", index + 1); + device_create(vc_class, NULL, MKDEV(VCS_MAJOR, index + 129), NULL, + "vcsa%u", index + 1); } -void vcs_remove_sysfs(struct tty_struct *tty) +void vcs_remove_sysfs(int index) { - device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1)); - device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 129)); + device_destroy(vc_class, MKDEV(VCS_MAJOR, index + 1)); + device_destroy(vc_class, MKDEV(VCS_MAJOR, index + 129)); } int __init vcs_init(void) diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 7900bd63b36..2c1d133819b 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -778,6 +778,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ } vc->vc_kmalloced = 1; vc_init(vc, vc->vc_rows, vc->vc_cols, 1); + vcs_make_sysfs(currcons); atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, ¶m); } return 0; @@ -987,7 +988,9 @@ void vc_deallocate(unsigned int currcons) if (vc_cons_allocated(currcons)) { struct vc_data *vc = vc_cons[currcons].d; struct vt_notifier_param param = { .vc = vc }; + atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, ¶m); + vcs_remove_sysfs(currcons); vc->vc_sw->con_deinit(vc); put_pid(vc->vt_pid); module_put(vc->vc_sw->owner); @@ -2775,7 +2778,6 @@ static int con_open(struct tty_struct *tty, struct file *filp) tty->termios->c_iflag |= IUTF8; else tty->termios->c_iflag &= ~IUTF8; - vcs_make_sysfs(tty); release_console_sem(); return ret; } @@ -2795,7 +2797,6 @@ static void con_shutdown(struct tty_struct *tty) BUG_ON(vc == NULL); acquire_console_sem(); vc->vc_tty = NULL; - vcs_remove_sysfs(tty); release_console_sem(); tty_shutdown(tty); } diff --git a/include/linux/console.h b/include/linux/console.h index a67a90cf826..dcca5339ceb 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -137,8 +137,8 @@ extern void resume_console(void); int mda_console_init(void); void prom_con_init(void); -void vcs_make_sysfs(struct tty_struct *tty); -void vcs_remove_sysfs(struct tty_struct *tty); +void vcs_make_sysfs(int index); +void vcs_remove_sysfs(int index); /* Some debug stub to catch some of the obvious races in the VT code */ #if 1 -- GitLab From f67f129e519fa87f8ebd236b6336fe43f31ee141 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sun, 1 Mar 2009 21:10:49 +0800 Subject: [PATCH 4441/4982] Driver core: implement uevent suppress in kobject This patch implements uevent suppress in kobject and removes it from struct device, based on the following ideas: 1,Uevent sending should be one attribute of kobject, so suppressing it in kobject layer is more natural than in device layer. By this way, we can do it for other objects embedded with kobject. 2,It may save several bytes for each instance of struct device.(On my omap3(32bit ARM) based box, can save 8bytes per device object) This patch also introduces dev_set|get_uevent_suppress() helpers to set and query uevent_suppress attribute in case to help kobject as private part of struct device in future. [This version is against the latest driver-core patch set of Greg,please ignore the last version.] Signed-off-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/dock.c | 2 +- drivers/base/core.c | 2 -- drivers/base/firmware_class.c | 4 ++-- drivers/i2c/i2c-core.c | 2 +- drivers/s390/cio/chsc_sch.c | 4 ++-- drivers/s390/cio/css.c | 4 ++-- drivers/s390/cio/device.c | 4 ++-- fs/partitions/check.c | 10 +++++----- include/linux/device.h | 11 ++++++++++- include/linux/kobject.h | 1 + lib/kobject_uevent.c | 7 +++++++ 11 files changed, 33 insertions(+), 18 deletions(-) diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 35094f230b1..7af7db1ba8c 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -977,7 +977,7 @@ static int dock_add(acpi_handle handle) sizeof(struct dock_station *)); /* we want the dock device to send uevents */ - dock_device->dev.uevent_suppress = 0; + dev_set_uevent_suppress(&dock_device->dev, 0); if (is_dock(handle)) dock_station->flags |= DOCK_IS_DOCK; diff --git a/drivers/base/core.c b/drivers/base/core.c index a90f56f64d6..95c67ffd71d 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -136,8 +136,6 @@ static int dev_uevent_filter(struct kset *kset, struct kobject *kobj) if (ktype == &device_ktype) { struct device *dev = to_dev(kobj); - if (dev->uevent_suppress) - return 0; if (dev->bus) return 1; if (dev->class) diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 44699d9dd85..d3a59c688fe 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -319,7 +319,7 @@ static int fw_register_device(struct device **dev_p, const char *fw_name, f_dev->parent = device; f_dev->class = &firmware_class; dev_set_drvdata(f_dev, fw_priv); - f_dev->uevent_suppress = 1; + dev_set_uevent_suppress(f_dev, 1); retval = device_register(f_dev); if (retval) { dev_err(device, "%s: device_register failed\n", __func__); @@ -366,7 +366,7 @@ static int fw_setup_device(struct firmware *fw, struct device **dev_p, } if (uevent) - f_dev->uevent_suppress = 0; + dev_set_uevent_suppress(f_dev, 0); *dev_p = f_dev; goto out; diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index e7d984866de..fbb9030b68a 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -841,7 +841,7 @@ int i2c_attach_client(struct i2c_client *client) if (client->driver && !is_newstyle_driver(client->driver)) { client->dev.release = i2c_client_release; - client->dev.uevent_suppress = 1; + dev_set_uevent_suppress(&client->dev, 1); } else client->dev.release = i2c_client_dev_release; diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c index 0a2f2edafc0..93eca1731b8 100644 --- a/drivers/s390/cio/chsc_sch.c +++ b/drivers/s390/cio/chsc_sch.c @@ -84,8 +84,8 @@ static int chsc_subchannel_probe(struct subchannel *sch) kfree(private); } else { sch->private = private; - if (sch->dev.uevent_suppress) { - sch->dev.uevent_suppress = 0; + if (dev_get_uevent_suppress(&sch->dev)) { + dev_set_uevent_suppress(&sch->dev, 0); kobject_uevent(&sch->dev.kobj, KOBJ_ADD); } } diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 8019288bc6d..427d11d8806 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -272,7 +272,7 @@ static int css_register_subchannel(struct subchannel *sch) * the subchannel driver can decide itself when it wants to inform * userspace of its existence. */ - sch->dev.uevent_suppress = 1; + dev_set_uevent_suppress(&sch->dev, 1); css_update_ssd_info(sch); /* make it known to the system */ ret = css_sch_device_register(sch); @@ -287,7 +287,7 @@ static int css_register_subchannel(struct subchannel *sch) * a fitting driver module may be loaded based on the * modalias. */ - sch->dev.uevent_suppress = 0; + dev_set_uevent_suppress(&sch->dev, 0); kobject_uevent(&sch->dev.kobj, KOBJ_ADD); } return ret; diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 23d5752349b..611d2e001dd 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -981,7 +981,7 @@ io_subchannel_register(struct work_struct *work) * Now we know this subchannel will stay, we can throw * our delayed uevent. */ - sch->dev.uevent_suppress = 0; + dev_set_uevent_suppress(&sch->dev, 0); kobject_uevent(&sch->dev.kobj, KOBJ_ADD); /* make it known to the system */ ret = ccw_device_register(cdev); @@ -1243,7 +1243,7 @@ static int io_subchannel_probe(struct subchannel *sch) * the ccw_device and exit. This happens for all early * devices, e.g. the console. */ - sch->dev.uevent_suppress = 0; + dev_set_uevent_suppress(&sch->dev, 0); kobject_uevent(&sch->dev.kobj, KOBJ_ADD); cdev->dev.groups = ccwdev_attr_groups; device_initialize(&cdev->dev); diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 6d720243f5f..38e337d51ce 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -400,7 +400,7 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, pdev->devt = devt; /* delay uevent until 'holders' subdir is created */ - pdev->uevent_suppress = 1; + dev_set_uevent_suppress(pdev, 1); err = device_add(pdev); if (err) goto out_put; @@ -410,7 +410,7 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, if (!p->holder_dir) goto out_del; - pdev->uevent_suppress = 0; + dev_set_uevent_suppress(pdev, 0); if (flags & ADDPART_FLAG_WHOLEDISK) { err = device_create_file(pdev, &dev_attr_whole_disk); if (err) @@ -422,7 +422,7 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, rcu_assign_pointer(ptbl->part[partno], p); /* suppress uevent if the disk supresses it */ - if (!ddev->uevent_suppress) + if (!dev_get_uevent_suppress(pdev)) kobject_uevent(&pdev->kobj, KOBJ_ADD); return p; @@ -455,7 +455,7 @@ void register_disk(struct gendisk *disk) dev_set_name(ddev, disk->disk_name); /* delay uevents, until we scanned partition table */ - ddev->uevent_suppress = 1; + dev_set_uevent_suppress(ddev, 1); if (device_add(ddev)) return; @@ -490,7 +490,7 @@ void register_disk(struct gendisk *disk) exit: /* announce disk after possible partitions are created */ - ddev->uevent_suppress = 0; + dev_set_uevent_suppress(ddev, 0); kobject_uevent(&ddev->kobj, KOBJ_ADD); /* announce possible partitions */ diff --git a/include/linux/device.h b/include/linux/device.h index 4bea53fe8f4..914c1016dd8 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -373,7 +373,6 @@ struct device { struct device_private *p; struct kobject kobj; - unsigned uevent_suppress:1; const char *init_name; /* initial name of the device */ struct device_type *type; @@ -465,6 +464,16 @@ static inline void dev_set_drvdata(struct device *dev, void *data) dev->driver_data = data; } +static inline unsigned int dev_get_uevent_suppress(const struct device *dev) +{ + return dev->kobj.uevent_suppress; +} + +static inline void dev_set_uevent_suppress(struct device *dev, int val) +{ + dev->kobj.uevent_suppress = val; +} + static inline int device_is_registered(struct device *dev) { return dev->kobj.state_in_sysfs; diff --git a/include/linux/kobject.h b/include/linux/kobject.h index c9c214d7bba..58ae8e00fcd 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -68,6 +68,7 @@ struct kobject { unsigned int state_in_sysfs:1; unsigned int state_add_uevent_sent:1; unsigned int state_remove_uevent_sent:1; + unsigned int uevent_suppress:1; }; extern int kobject_set_name(struct kobject *kobj, const char *name, ...) diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index 318328ddbd1..b2181cc8e4d 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c @@ -118,6 +118,13 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, kset = top_kobj->kset; uevent_ops = kset->uevent_ops; + /* skip the event, if uevent_suppress is set*/ + if (kobj->uevent_suppress) { + pr_debug("kobject: '%s' (%p): %s: uevent_suppress " + "caused the event to drop!\n", + kobject_name(kobj), kobj, __func__); + return 0; + } /* skip the event, if the filter returns zero. */ if (uevent_ops && uevent_ops->filter) if (!uevent_ops->filter(kset, kobj)) { -- GitLab From 60530afe1ee8a5532cb09d0ab5bc3f1a6495b780 Mon Sep 17 00:00:00 2001 From: Zhenwen Xu Date: Tue, 3 Mar 2009 18:36:02 +0800 Subject: [PATCH 4442/4982] Driver core: some cleanup on drivers/base/sys.c do some cleanup on drivers/base/sys.c Signed-off-by: Zhenwen Xu Signed-off-by: Greg Kroah-Hartman --- drivers/base/sys.c | 54 +++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/drivers/base/sys.c b/drivers/base/sys.c index b428c8c4bc6..cbd36cf59a0 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -30,10 +30,10 @@ static ssize_t -sysdev_show(struct kobject * kobj, struct attribute * attr, char * buffer) +sysdev_show(struct kobject *kobj, struct attribute *attr, char *buffer) { - struct sys_device * sysdev = to_sysdev(kobj); - struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr); + struct sys_device *sysdev = to_sysdev(kobj); + struct sysdev_attribute *sysdev_attr = to_sysdev_attr(attr); if (sysdev_attr->show) return sysdev_attr->show(sysdev, sysdev_attr, buffer); @@ -42,11 +42,11 @@ sysdev_show(struct kobject * kobj, struct attribute * attr, char * buffer) static ssize_t -sysdev_store(struct kobject * kobj, struct attribute * attr, - const char * buffer, size_t count) +sysdev_store(struct kobject *kobj, struct attribute *attr, + const char *buffer, size_t count) { - struct sys_device * sysdev = to_sysdev(kobj); - struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr); + struct sys_device *sysdev = to_sysdev(kobj); + struct sysdev_attribute *sysdev_attr = to_sysdev_attr(attr); if (sysdev_attr->store) return sysdev_attr->store(sysdev, sysdev_attr, buffer, count); @@ -63,13 +63,13 @@ static struct kobj_type ktype_sysdev = { }; -int sysdev_create_file(struct sys_device * s, struct sysdev_attribute * a) +int sysdev_create_file(struct sys_device *s, struct sysdev_attribute *a) { return sysfs_create_file(&s->kobj, &a->attr); } -void sysdev_remove_file(struct sys_device * s, struct sysdev_attribute * a) +void sysdev_remove_file(struct sys_device *s, struct sysdev_attribute *a) { sysfs_remove_file(&s->kobj, &a->attr); } @@ -84,7 +84,7 @@ EXPORT_SYMBOL_GPL(sysdev_remove_file); static ssize_t sysdev_class_show(struct kobject *kobj, struct attribute *attr, char *buffer) { - struct sysdev_class * class = to_sysdev_class(kobj); + struct sysdev_class *class = to_sysdev_class(kobj); struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr); if (class_attr->show) @@ -95,8 +95,8 @@ static ssize_t sysdev_class_show(struct kobject *kobj, struct attribute *attr, static ssize_t sysdev_class_store(struct kobject *kobj, struct attribute *attr, const char *buffer, size_t count) { - struct sysdev_class * class = to_sysdev_class(kobj); - struct sysdev_class_attribute * class_attr = to_sysdev_class_attr(attr); + struct sysdev_class *class = to_sysdev_class(kobj); + struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr); if (class_attr->store) return class_attr->store(class, buffer, count); @@ -128,7 +128,7 @@ EXPORT_SYMBOL_GPL(sysdev_class_remove_file); static struct kset *system_kset; -int sysdev_class_register(struct sysdev_class * cls) +int sysdev_class_register(struct sysdev_class *cls) { pr_debug("Registering sysdev class '%s'\n", cls->name); @@ -141,7 +141,7 @@ int sysdev_class_register(struct sysdev_class * cls) return kset_register(&cls->kset); } -void sysdev_class_unregister(struct sysdev_class * cls) +void sysdev_class_unregister(struct sysdev_class *cls) { pr_debug("Unregistering sysdev class '%s'\n", kobject_name(&cls->kset.kobj)); @@ -203,8 +203,8 @@ int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv) * @cls: Class driver belongs to. * @drv: Driver. */ -void sysdev_driver_unregister(struct sysdev_class * cls, - struct sysdev_driver * drv) +void sysdev_driver_unregister(struct sysdev_class *cls, + struct sysdev_driver *drv) { mutex_lock(&sysdev_drivers_lock); list_del_init(&drv->entry); @@ -229,10 +229,10 @@ EXPORT_SYMBOL_GPL(sysdev_driver_unregister); * @sysdev: device in question * */ -int sysdev_register(struct sys_device * sysdev) +int sysdev_register(struct sys_device *sysdev) { int error; - struct sysdev_class * cls = sysdev->cls; + struct sysdev_class *cls = sysdev->cls; if (!cls) return -EINVAL; @@ -252,7 +252,7 @@ int sysdev_register(struct sys_device * sysdev) sysdev->id); if (!error) { - struct sysdev_driver * drv; + struct sysdev_driver *drv; pr_debug("Registering sys device '%s'\n", kobject_name(&sysdev->kobj)); @@ -274,9 +274,9 @@ int sysdev_register(struct sys_device * sysdev) return error; } -void sysdev_unregister(struct sys_device * sysdev) +void sysdev_unregister(struct sys_device *sysdev) { - struct sysdev_driver * drv; + struct sysdev_driver *drv; mutex_lock(&sysdev_drivers_lock); list_for_each_entry(drv, &sysdev->cls->drivers, entry) { @@ -305,19 +305,19 @@ void sysdev_unregister(struct sys_device * sysdev) */ void sysdev_shutdown(void) { - struct sysdev_class * cls; + struct sysdev_class *cls; pr_debug("Shutting Down System Devices\n"); mutex_lock(&sysdev_drivers_lock); list_for_each_entry_reverse(cls, &system_kset->list, kset.kobj.entry) { - struct sys_device * sysdev; + struct sys_device *sysdev; pr_debug("Shutting down type '%s':\n", kobject_name(&cls->kset.kobj)); list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) { - struct sysdev_driver * drv; + struct sysdev_driver *drv; pr_debug(" %s\n", kobject_name(&sysdev->kobj)); /* Call auxillary drivers first */ @@ -364,7 +364,7 @@ static void __sysdev_resume(struct sys_device *dev) */ int sysdev_suspend(pm_message_t state) { - struct sysdev_class * cls; + struct sysdev_class *cls; struct sys_device *sysdev, *err_dev; struct sysdev_driver *drv, *err_drv; int ret; @@ -442,12 +442,12 @@ EXPORT_SYMBOL_GPL(sysdev_suspend); */ int sysdev_resume(void) { - struct sysdev_class * cls; + struct sysdev_class *cls; pr_debug("Resuming System Devices\n"); list_for_each_entry(cls, &system_kset->list, kset.kobj.entry) { - struct sys_device * sysdev; + struct sys_device *sysdev; pr_debug("Resuming type '%s':\n", kobject_name(&cls->kset.kobj)); -- GitLab From ffa6a7054d172a2f57248dff2de600ca795c5656 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Wed, 4 Mar 2009 12:44:00 +0100 Subject: [PATCH 4443/4982] Driver core: Fix device_move() vs. dpm list ordering, v2 dpm_list currently relies on the fact that child devices will be registered after their parents to get a correct suspend order. Using device_move() however destroys this assumption, as an already registered device may be moved under a newly registered one. This patch adds a new argument to device_move(), allowing callers to specify how dpm_list should be adapted. Signed-off-by: Cornelia Huck Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 19 +++++++++++++++- drivers/base/power/main.c | 44 ++++++++++++++++++++++++++++++++++++++ drivers/base/power/power.h | 8 +++++++ drivers/s390/cio/device.c | 9 ++++---- include/linux/device.h | 3 ++- include/linux/pm.h | 11 ++++++++++ net/bluetooth/hci_sysfs.c | 2 +- net/bluetooth/rfcomm/tty.c | 5 +++-- 8 files changed, 92 insertions(+), 9 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 95c67ffd71d..e73c92d13a2 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1561,8 +1561,10 @@ out: * device_move - moves a device to a new parent * @dev: the pointer to the struct device to be moved * @new_parent: the new parent of the device (can by NULL) + * @dpm_order: how to reorder the dpm_list */ -int device_move(struct device *dev, struct device *new_parent) +int device_move(struct device *dev, struct device *new_parent, + enum dpm_order dpm_order) { int error; struct device *old_parent; @@ -1572,6 +1574,7 @@ int device_move(struct device *dev, struct device *new_parent) if (!dev) return -EINVAL; + device_pm_lock(); new_parent = get_device(new_parent); new_parent_kobj = get_device_parent(dev, new_parent); @@ -1613,9 +1616,23 @@ int device_move(struct device *dev, struct device *new_parent) put_device(new_parent); goto out; } + switch (dpm_order) { + case DPM_ORDER_NONE: + break; + case DPM_ORDER_DEV_AFTER_PARENT: + device_pm_move_after(dev, new_parent); + break; + case DPM_ORDER_PARENT_BEFORE_DEV: + device_pm_move_before(new_parent, dev); + break; + case DPM_ORDER_DEV_LAST: + device_pm_move_last(dev); + break; + } out_put: put_device(old_parent); out: + device_pm_unlock(); put_device(dev); return error; } diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 2d14f4ae6c0..e255341682c 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -106,6 +106,50 @@ void device_pm_remove(struct device *dev) mutex_unlock(&dpm_list_mtx); } +/** + * device_pm_move_before - move device in dpm_list + * @deva: Device to move in dpm_list + * @devb: Device @deva should come before + */ +void device_pm_move_before(struct device *deva, struct device *devb) +{ + pr_debug("PM: Moving %s:%s before %s:%s\n", + deva->bus ? deva->bus->name : "No Bus", + kobject_name(&deva->kobj), + devb->bus ? devb->bus->name : "No Bus", + kobject_name(&devb->kobj)); + /* Delete deva from dpm_list and reinsert before devb. */ + list_move_tail(&deva->power.entry, &devb->power.entry); +} + +/** + * device_pm_move_after - move device in dpm_list + * @deva: Device to move in dpm_list + * @devb: Device @deva should come after + */ +void device_pm_move_after(struct device *deva, struct device *devb) +{ + pr_debug("PM: Moving %s:%s after %s:%s\n", + deva->bus ? deva->bus->name : "No Bus", + kobject_name(&deva->kobj), + devb->bus ? devb->bus->name : "No Bus", + kobject_name(&devb->kobj)); + /* Delete deva from dpm_list and reinsert after devb. */ + list_move(&deva->power.entry, &devb->power.entry); +} + +/** + * device_pm_move_last - move device to end of dpm_list + * @dev: Device to move in dpm_list + */ +void device_pm_move_last(struct device *dev) +{ + pr_debug("PM: Moving %s:%s to end of list\n", + dev->bus ? dev->bus->name : "No Bus", + kobject_name(&dev->kobj)); + list_move_tail(&dev->power.entry, &dpm_list); +} + /** * pm_op - execute the PM operation appropiate for given PM event * @dev: Device. diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index 41f51fae042..c7cb4fc3735 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h @@ -18,11 +18,19 @@ static inline struct device *to_device(struct list_head *entry) extern void device_pm_add(struct device *); extern void device_pm_remove(struct device *); +extern void device_pm_move_before(struct device *, struct device *); +extern void device_pm_move_after(struct device *, struct device *); +extern void device_pm_move_last(struct device *); #else /* CONFIG_PM_SLEEP */ static inline void device_pm_add(struct device *dev) {} static inline void device_pm_remove(struct device *dev) {} +static inline void device_pm_move_before(struct device *deva, + struct device *devb) {} +static inline void device_pm_move_after(struct device *deva, + struct device *devb) {} +static inline void device_pm_move_last(struct device *dev) {} #endif diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 611d2e001dd..e28f8ae5345 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -799,7 +799,7 @@ static void sch_attach_disconnected_device(struct subchannel *sch, return; other_sch = to_subchannel(cdev->dev.parent); /* Note: device_move() changes cdev->dev.parent */ - ret = device_move(&cdev->dev, &sch->dev); + ret = device_move(&cdev->dev, &sch->dev, DPM_ORDER_PARENT_BEFORE_DEV); if (ret) { CIO_MSG_EVENT(0, "Moving disconnected device 0.%x.%04x failed " "(ret=%d)!\n", cdev->private->dev_id.ssid, @@ -830,7 +830,7 @@ static void sch_attach_orphaned_device(struct subchannel *sch, * Try to move the ccw device to its new subchannel. * Note: device_move() changes cdev->dev.parent */ - ret = device_move(&cdev->dev, &sch->dev); + ret = device_move(&cdev->dev, &sch->dev, DPM_ORDER_PARENT_BEFORE_DEV); if (ret) { CIO_MSG_EVENT(0, "Moving device 0.%x.%04x from orphanage " "failed (ret=%d)!\n", @@ -897,7 +897,8 @@ void ccw_device_move_to_orphanage(struct work_struct *work) * ccw device can take its place on the subchannel. * Note: device_move() changes cdev->dev.parent */ - ret = device_move(&cdev->dev, &css->pseudo_subchannel->dev); + ret = device_move(&cdev->dev, &css->pseudo_subchannel->dev, + DPM_ORDER_NONE); if (ret) { CIO_MSG_EVENT(0, "Moving device 0.%x.%04x to orphanage failed " "(ret=%d)!\n", cdev->private->dev_id.ssid, @@ -1129,7 +1130,7 @@ static void ccw_device_move_to_sch(struct work_struct *work) * Try to move the ccw device to its new subchannel. * Note: device_move() changes cdev->dev.parent */ - rc = device_move(&cdev->dev, &sch->dev); + rc = device_move(&cdev->dev, &sch->dev, DPM_ORDER_PARENT_BEFORE_DEV); mutex_unlock(&sch->reg_mutex); if (rc) { CIO_MSG_EVENT(0, "Moving device 0.%x.%04x to subchannel " diff --git a/include/linux/device.h b/include/linux/device.h index 914c1016dd8..f98d0cfb4f8 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -494,7 +494,8 @@ extern int device_for_each_child(struct device *dev, void *data, extern struct device *device_find_child(struct device *dev, void *data, int (*match)(struct device *dev, void *data)); extern int device_rename(struct device *dev, char *new_name); -extern int device_move(struct device *dev, struct device *new_parent); +extern int device_move(struct device *dev, struct device *new_parent, + enum dpm_order dpm_order); /* * Root device objects for grouping under /sys/devices diff --git a/include/linux/pm.h b/include/linux/pm.h index 24ba5f67b3a..1d4e2d28982 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -400,6 +400,9 @@ extern void __suspend_report_result(const char *function, void *fn, int ret); #else /* !CONFIG_PM_SLEEP */ +#define device_pm_lock() do {} while (0) +#define device_pm_unlock() do {} while (0) + static inline int device_suspend(pm_message_t state) { return 0; @@ -409,6 +412,14 @@ static inline int device_suspend(pm_message_t state) #endif /* !CONFIG_PM_SLEEP */ +/* How to reorder dpm_list after device_move() */ +enum dpm_order { + DPM_ORDER_NONE, + DPM_ORDER_DEV_AFTER_PARENT, + DPM_ORDER_PARENT_BEFORE_DEV, + DPM_ORDER_DEV_LAST, +}; + /* * Global Power Management flags * Used to keep APM and ACPI from both being active diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 1a1f916be44..ed82796d4a0 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -140,7 +140,7 @@ static void del_conn(struct work_struct *work) dev = device_find_child(&conn->dev, NULL, __match_tty); if (!dev) break; - device_move(dev, NULL); + device_move(dev, NULL, DPM_ORDER_DEV_LAST); put_device(dev); } diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index d030c69cb5a..abdc703a11d 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -731,7 +731,8 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) remove_wait_queue(&dev->wait, &wait); if (err == 0) - device_move(dev->tty_dev, rfcomm_get_device(dev)); + device_move(dev->tty_dev, rfcomm_get_device(dev), + DPM_ORDER_DEV_AFTER_PARENT); rfcomm_tty_copy_pending(dev); @@ -751,7 +752,7 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp) if (atomic_dec_and_test(&dev->opened)) { if (dev->tty_dev->parent) - device_move(dev->tty_dev, NULL); + device_move(dev->tty_dev, NULL, DPM_ORDER_DEV_LAST); /* Close DLC and dettach TTY */ rfcomm_dlc_close(dev->dlc, 0); -- GitLab From 669420644c79c207f83fdf9105ae782867e2991f Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Fri, 13 Mar 2009 12:07:36 -0600 Subject: [PATCH 4444/4982] sysfs: only allow one scheduled removal callback per kobj The only way for a sysfs attribute to remove itself (without deadlock) is to use the sysfs_schedule_callback() interface. Vegard Nossum discovered that a poorly written sysfs ->store callback can repeatedly schedule remove callbacks on the same device over and over, e.g. $ while true ; do echo 1 > /sys/devices/.../remove ; done If the 'remove' attribute uses the sysfs_schedule_callback API and also does not protect itself from concurrent accesses, its callback handler will be called multiple times, and will eventually attempt to perform operations on a freed kobject, leading to many problems. Instead of requiring all callers of sysfs_schedule_callback to implement their own synchronization, provide the protection in the infrastructure. Now, sysfs_schedule_callback will only allow one scheduled callback per kobject. On subsequent calls with the same kobject, return -EAGAIN. This is a short term fix. The long term fix is to allow sysfs attributes to remove themselves directly, without any of this callback hokey pokey. [cornelia.huck@de.ibm.com: s390 ccwgroup bits] Reported-by: vegard.nossum@gmail.com Signed-off-by: Alex Chiang Acked-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- drivers/s390/cio/ccwgroup.c | 5 +++-- fs/sysfs/file.c | 26 +++++++++++++++++++++++--- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 918e6fce257..b91c1719b07 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -104,8 +104,9 @@ ccwgroup_ungroup_store(struct device *dev, struct device_attribute *attr, const rc = device_schedule_callback(dev, ccwgroup_ungroup_callback); out: if (rc) { - /* Release onoff "lock" when ungrouping failed. */ - atomic_set(&gdev->onoff, 0); + if (rc != -EAGAIN) + /* Release onoff "lock" when ungrouping failed. */ + atomic_set(&gdev->onoff, 0); return rc; } return count; diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 1f4a3f87726..289c43a4726 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -659,13 +659,16 @@ void sysfs_remove_file_from_group(struct kobject *kobj, EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group); struct sysfs_schedule_callback_struct { - struct kobject *kobj; + struct list_head workq_list; + struct kobject *kobj; void (*func)(void *); void *data; struct module *owner; struct work_struct work; }; +static DEFINE_MUTEX(sysfs_workq_mutex); +static LIST_HEAD(sysfs_workq); static void sysfs_schedule_callback_work(struct work_struct *work) { struct sysfs_schedule_callback_struct *ss = container_of(work, @@ -674,6 +677,9 @@ static void sysfs_schedule_callback_work(struct work_struct *work) (ss->func)(ss->data); kobject_put(ss->kobj); module_put(ss->owner); + mutex_lock(&sysfs_workq_mutex); + list_del(&ss->workq_list); + mutex_unlock(&sysfs_workq_mutex); kfree(ss); } @@ -695,15 +701,25 @@ static void sysfs_schedule_callback_work(struct work_struct *work) * until @func returns. * * Returns 0 if the request was submitted, -ENOMEM if storage could not - * be allocated, -ENODEV if a reference to @owner isn't available. + * be allocated, -ENODEV if a reference to @owner isn't available, + * -EAGAIN if a callback has already been scheduled for @kobj. */ int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), void *data, struct module *owner) { - struct sysfs_schedule_callback_struct *ss; + struct sysfs_schedule_callback_struct *ss, *tmp; if (!try_module_get(owner)) return -ENODEV; + + mutex_lock(&sysfs_workq_mutex); + list_for_each_entry_safe(ss, tmp, &sysfs_workq, workq_list) + if (ss->kobj == kobj) { + mutex_unlock(&sysfs_workq_mutex); + return -EAGAIN; + } + mutex_unlock(&sysfs_workq_mutex); + ss = kmalloc(sizeof(*ss), GFP_KERNEL); if (!ss) { module_put(owner); @@ -715,6 +731,10 @@ int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), ss->data = data; ss->owner = owner; INIT_WORK(&ss->work, sysfs_schedule_callback_work); + INIT_LIST_HEAD(&ss->workq_list); + mutex_lock(&sysfs_workq_mutex); + list_add_tail(&ss->workq_list, &sysfs_workq); + mutex_unlock(&sysfs_workq_mutex); schedule_work(&ss->work); return 0; } -- GitLab From f520360d93cdc37de5d972dac4bf3bdef6a7f6a7 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Thu, 19 Mar 2009 09:09:05 -0700 Subject: [PATCH 4445/4982] kobject: don't block for each kobject_uevent Right now, the kobject_uevent code blocks for each uevent that's being generated, due to using (for hystoric reasons) UHM_WAIT_EXEC as flag to call_usermode_helper(). Specifically, the effect is that each uevent that is being sent causes the code to wake up keventd, then block until keventd has processed the work. Needless to say, this happens many times during the system boot. This patches changes that to UHN_NO_WAIT (brilliant name for a constant btw) so that we only schedule the work to fire the uevent message, but do not wait for keventd to process the work. This removes one of the bottlenecks during boot; each one of them is only a small effect, but the sum of them does add up. [Note, distros that need this are broken, they should be setting CONFIG_UEVENT_HELPER_PATH to "", that way this code path will never be excuted at all -- gregkh] Signed-off-by: Arjan van de Ven Signed-off-by: Greg Kroah-Hartman --- lib/kobject_uevent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index b2181cc8e4d..e68e743bd86 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c @@ -255,7 +255,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, goto exit; retval = call_usermodehelper(argv[0], argv, - env->envp, UMH_WAIT_EXEC); + env->envp, UMH_NO_WAIT); } exit: -- GitLab From 095160aee954688a9bad225952c4bee546541e19 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 23 Mar 2009 01:41:27 +0000 Subject: [PATCH 4446/4982] sysfs: fix some bin_vm_ops errors Commit 86c9508eb1c0ce5aa07b5cf1d36b60c54efc3d7a "sysfs: don't block indefinitely for unmapped files" in linux-next crashes the PowerMac G5 when X starts up. It's caught out by the way powerpc's pci_mmap of legacy_mem uses shmem_zero_setup(), substituting a new vma->vm_file whose private_data no longer points to the bin_buffer (substitution done because some versions of X crash if that mmap fails). The fix to this is straightforward: the original vm_file is fput() in that case, so this mmap won't block sysfs at all, so just don't switch over to bin_vm_ops if vm_file has changed. But more fixes made before realizing that was the problem:- It should not be an error if bin_page_mkwrite() finds no underlying page_mkwrite(). Check that a file already mmap'ed has the same underlying vm_ops _before_ pointing vma->vm_ops at bin_vm_ops. If the file being mmap'ed is a shmem/tmpfs file, don't fail the mmap on CONFIG_NUMA=y, just because that has a set_policy and get_policy: provide bin_set_policy, bin_get_policy and bin_migrate. Signed-off-by: Hugh Dickins Acked-by: Eric Biederman Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/bin.c | 89 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 79 insertions(+), 10 deletions(-) diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index 96cc2bf6a84..07703d3ff4a 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c @@ -241,9 +241,12 @@ static int bin_page_mkwrite(struct vm_area_struct *vma, struct page *page) struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; int ret; - if (!bb->vm_ops || !bb->vm_ops->page_mkwrite) + if (!bb->vm_ops) return -EINVAL; + if (!bb->vm_ops->page_mkwrite) + return 0; + if (!sysfs_get_active_two(attr_sd)) return -EINVAL; @@ -273,12 +276,78 @@ static int bin_access(struct vm_area_struct *vma, unsigned long addr, return ret; } +#ifdef CONFIG_NUMA +static int bin_set_policy(struct vm_area_struct *vma, struct mempolicy *new) +{ + struct file *file = vma->vm_file; + struct bin_buffer *bb = file->private_data; + struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; + int ret; + + if (!bb->vm_ops || !bb->vm_ops->set_policy) + return 0; + + if (!sysfs_get_active_two(attr_sd)) + return -EINVAL; + + ret = bb->vm_ops->set_policy(vma, new); + + sysfs_put_active_two(attr_sd); + return ret; +} + +static struct mempolicy *bin_get_policy(struct vm_area_struct *vma, + unsigned long addr) +{ + struct file *file = vma->vm_file; + struct bin_buffer *bb = file->private_data; + struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; + struct mempolicy *pol; + + if (!bb->vm_ops || !bb->vm_ops->get_policy) + return vma->vm_policy; + + if (!sysfs_get_active_two(attr_sd)) + return vma->vm_policy; + + pol = bb->vm_ops->get_policy(vma, addr); + + sysfs_put_active_two(attr_sd); + return pol; +} + +static int bin_migrate(struct vm_area_struct *vma, const nodemask_t *from, + const nodemask_t *to, unsigned long flags) +{ + struct file *file = vma->vm_file; + struct bin_buffer *bb = file->private_data; + struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; + int ret; + + if (!bb->vm_ops || !bb->vm_ops->migrate) + return 0; + + if (!sysfs_get_active_two(attr_sd)) + return 0; + + ret = bb->vm_ops->migrate(vma, from, to, flags); + + sysfs_put_active_two(attr_sd); + return ret; +} +#endif + static struct vm_operations_struct bin_vm_ops = { .open = bin_vma_open, .close = bin_vma_close, .fault = bin_fault, .page_mkwrite = bin_page_mkwrite, .access = bin_access, +#ifdef CONFIG_NUMA + .set_policy = bin_set_policy, + .get_policy = bin_get_policy, + .migrate = bin_migrate, +#endif }; static int mmap(struct file *file, struct vm_area_struct *vma) @@ -287,7 +356,6 @@ static int mmap(struct file *file, struct vm_area_struct *vma) struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr; struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; - struct vm_operations_struct *vm_ops; int rc; mutex_lock(&bb->mutex); @@ -302,24 +370,25 @@ static int mmap(struct file *file, struct vm_area_struct *vma) goto out_put; rc = attr->mmap(kobj, attr, vma); - vm_ops = vma->vm_ops; - vma->vm_ops = &bin_vm_ops; if (rc) goto out_put; - rc = -EINVAL; - if (bb->mmapped && bb->vm_ops != vma->vm_ops) + /* + * PowerPC's pci_mmap of legacy_mem uses shmem_zero_setup() + * to satisfy versions of X which crash if the mmap fails: that + * substitutes a new vm_file, and we don't then want bin_vm_ops. + */ + if (vma->vm_file != file) goto out_put; -#ifdef CONFIG_NUMA rc = -EINVAL; - if (vm_ops && ((vm_ops->set_policy || vm_ops->get_policy || vm_ops->migrate))) + if (bb->mmapped && bb->vm_ops != vma->vm_ops) goto out_put; -#endif rc = 0; bb->mmapped = 1; - bb->vm_ops = vm_ops; + bb->vm_ops = vma->vm_ops; + vma->vm_ops = &bin_vm_ops; out_put: sysfs_put_active_two(attr_sd); out_unlock: -- GitLab From e9d376f0fa66bd630fe27403669c6ae6c22a868f Mon Sep 17 00:00:00 2001 From: Jason Baron Date: Thu, 5 Feb 2009 11:51:38 -0500 Subject: [PATCH 4447/4982] dynamic debug: combine dprintk and dynamic printk This patch combines Greg Bank's dprintk() work with the existing dynamic printk patchset, we are now calling it 'dynamic debug'. The new feature of this patchset is a richer /debugfs control file interface, (an example output from my system is at the bottom), which allows fined grained control over the the debug output. The output can be controlled by function, file, module, format string, and line number. for example, enabled all debug messages in module 'nf_conntrack': echo -n 'module nf_conntrack +p' > /mnt/debugfs/dynamic_debug/control to disable them: echo -n 'module nf_conntrack -p' > /mnt/debugfs/dynamic_debug/control A further explanation can be found in the documentation patch. Signed-off-by: Greg Banks Signed-off-by: Jason Baron Signed-off-by: Greg Kroah-Hartman --- Documentation/kernel-parameters.txt | 5 - include/asm-generic/vmlinux.lds.h | 15 +- include/linux/device.h | 2 +- include/linux/dynamic_debug.h | 88 ++++ include/linux/dynamic_printk.h | 93 ---- include/linux/kernel.h | 4 +- kernel/module.c | 25 +- lib/Kconfig.debug | 2 +- lib/Makefile | 2 +- lib/dynamic_debug.c | 756 ++++++++++++++++++++++++++++ lib/dynamic_printk.c | 414 --------------- net/netfilter/nf_conntrack_pptp.c | 2 +- scripts/Makefile.lib | 2 +- 13 files changed, 867 insertions(+), 543 deletions(-) create mode 100644 include/linux/dynamic_debug.h delete mode 100644 include/linux/dynamic_printk.h create mode 100644 lib/dynamic_debug.c delete mode 100644 lib/dynamic_printk.c diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 54f21a5c262..3a1aa8a4aff 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1816,11 +1816,6 @@ and is between 256 and 4096 characters. It is defined in the file autoconfiguration. Ranges are in pairs (memory base and size). - dynamic_printk Enables pr_debug()/dev_dbg() calls if - CONFIG_DYNAMIC_PRINTK_DEBUG has been enabled. - These can also be switched on/off via - /dynamic_printk/modules - print-fatal-signals= [KNL] debug: print fatal signals print-fatal-signals=1: print segfault info to diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index c61fab1dd2f..aca40b93bd2 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -80,6 +80,11 @@ VMLINUX_SYMBOL(__start___tracepoints) = .; \ *(__tracepoints) \ VMLINUX_SYMBOL(__stop___tracepoints) = .; \ + /* implement dynamic printk debug */ \ + . = ALIGN(8); \ + VMLINUX_SYMBOL(__start___verbose) = .; \ + *(__verbose) \ + VMLINUX_SYMBOL(__stop___verbose) = .; \ LIKELY_PROFILE() \ BRANCH_PROFILE() @@ -309,15 +314,7 @@ CPU_DISCARD(init.data) \ CPU_DISCARD(init.rodata) \ MEM_DISCARD(init.data) \ - MEM_DISCARD(init.rodata) \ - /* implement dynamic printk debug */ \ - VMLINUX_SYMBOL(__start___verbose_strings) = .; \ - *(__verbose_strings) \ - VMLINUX_SYMBOL(__stop___verbose_strings) = .; \ - . = ALIGN(8); \ - VMLINUX_SYMBOL(__start___verbose) = .; \ - *(__verbose) \ - VMLINUX_SYMBOL(__stop___verbose) = .; + MEM_DISCARD(init.rodata) #define INIT_TEXT \ *(.init.text) \ diff --git a/include/linux/device.h b/include/linux/device.h index f98d0cfb4f8..2918c0e8fdf 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -582,7 +582,7 @@ extern const char *dev_driver_string(const struct device *dev); #if defined(DEBUG) #define dev_dbg(dev, format, arg...) \ dev_printk(KERN_DEBUG , dev , format , ## arg) -#elif defined(CONFIG_DYNAMIC_PRINTK_DEBUG) +#elif defined(CONFIG_DYNAMIC_DEBUG) #define dev_dbg(dev, format, ...) do { \ dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \ } while (0) diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h new file mode 100644 index 00000000000..07781aaa116 --- /dev/null +++ b/include/linux/dynamic_debug.h @@ -0,0 +1,88 @@ +#ifndef _DYNAMIC_DEBUG_H +#define _DYNAMIC_DEBUG_H + +/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which + * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They + * use independent hash functions, to reduce the chance of false positives. + */ +extern long long dynamic_debug_enabled; +extern long long dynamic_debug_enabled2; + +/* + * An instance of this structure is created in a special + * ELF section at every dynamic debug callsite. At runtime, + * the special section is treated as an array of these. + */ +struct _ddebug { + /* + * These fields are used to drive the user interface + * for selecting and displaying debug callsites. + */ + const char *modname; + const char *function; + const char *filename; + const char *format; + char primary_hash; + char secondary_hash; + unsigned int lineno:24; + /* + * The flags field controls the behaviour at the callsite. + * The bits here are changed dynamically when the user + * writes commands to /dynamic_debug/ddebug + */ +#define _DPRINTK_FLAGS_PRINT (1<<0) /* printk() a message using the format */ +#define _DPRINTK_FLAGS_DEFAULT 0 + unsigned int flags:8; +} __attribute__((aligned(8))); + + +int ddebug_add_module(struct _ddebug *tab, unsigned int n, + const char *modname); + +#if defined(CONFIG_DYNAMIC_DEBUG) +extern int ddebug_remove_module(char *mod_name); + +#define __dynamic_dbg_enabled(dd) ({ \ + int __ret = 0; \ + if (unlikely((dynamic_debug_enabled & (1LL << DEBUG_HASH)) && \ + (dynamic_debug_enabled2 & (1LL << DEBUG_HASH2)))) \ + if (unlikely(dd.flags)) \ + __ret = 1; \ + __ret; }) + +#define dynamic_pr_debug(fmt, ...) do { \ + static struct _ddebug descriptor \ + __used \ + __attribute__((section("__verbose"), aligned(8))) = \ + { KBUILD_MODNAME, __func__, __FILE__, fmt, DEBUG_HASH, \ + DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT }; \ + if (__dynamic_dbg_enabled(descriptor)) \ + printk(KERN_DEBUG KBUILD_MODNAME ":" fmt, \ + ##__VA_ARGS__); \ + } while (0) + + +#define dynamic_dev_dbg(dev, fmt, ...) do { \ + static struct _ddebug descriptor \ + __used \ + __attribute__((section("__verbose"), aligned(8))) = \ + { KBUILD_MODNAME, __func__, __FILE__, fmt, DEBUG_HASH, \ + DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT }; \ + if (__dynamic_dbg_enabled(descriptor)) \ + dev_printk(KERN_DEBUG, dev, \ + KBUILD_MODNAME ": " fmt, \ + ##__VA_ARGS__); \ + } while (0) + +#else + +static inline int ddebug_remove_module(char *mod) +{ + return 0; +} + +#define dynamic_pr_debug(fmt, ...) do { } while (0) +#define dynamic_dev_dbg(dev, format, ...) do { } while (0) +#endif + +#endif diff --git a/include/linux/dynamic_printk.h b/include/linux/dynamic_printk.h deleted file mode 100644 index 2d528d00907..00000000000 --- a/include/linux/dynamic_printk.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef _DYNAMIC_PRINTK_H -#define _DYNAMIC_PRINTK_H - -#define DYNAMIC_DEBUG_HASH_BITS 6 -#define DEBUG_HASH_TABLE_SIZE (1 << DYNAMIC_DEBUG_HASH_BITS) - -#define TYPE_BOOLEAN 1 - -#define DYNAMIC_ENABLED_ALL 0 -#define DYNAMIC_ENABLED_NONE 1 -#define DYNAMIC_ENABLED_SOME 2 - -extern int dynamic_enabled; - -/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which - * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They - * use independent hash functions, to reduce the chance of false positives. - */ -extern long long dynamic_printk_enabled; -extern long long dynamic_printk_enabled2; - -struct mod_debug { - char *modname; - char *logical_modname; - char *flag_names; - int type; - int hash; - int hash2; -} __attribute__((aligned(8))); - -int register_dynamic_debug_module(char *mod_name, int type, char *share_name, - char *flags, int hash, int hash2); - -#if defined(CONFIG_DYNAMIC_PRINTK_DEBUG) -extern int unregister_dynamic_debug_module(char *mod_name); -extern int __dynamic_dbg_enabled_helper(char *modname, int type, - int value, int hash); - -#define __dynamic_dbg_enabled(module, type, value, level, hash) ({ \ - int __ret = 0; \ - if (unlikely((dynamic_printk_enabled & (1LL << DEBUG_HASH)) && \ - (dynamic_printk_enabled2 & (1LL << DEBUG_HASH2)))) \ - __ret = __dynamic_dbg_enabled_helper(module, type, \ - value, hash);\ - __ret; }) - -#define dynamic_pr_debug(fmt, ...) do { \ - static char mod_name[] \ - __attribute__((section("__verbose_strings"))) \ - = KBUILD_MODNAME; \ - static struct mod_debug descriptor \ - __used \ - __attribute__((section("__verbose"), aligned(8))) = \ - { mod_name, mod_name, NULL, TYPE_BOOLEAN, DEBUG_HASH, DEBUG_HASH2 };\ - if (__dynamic_dbg_enabled(KBUILD_MODNAME, TYPE_BOOLEAN, \ - 0, 0, DEBUG_HASH)) \ - printk(KERN_DEBUG KBUILD_MODNAME ":" fmt, \ - ##__VA_ARGS__); \ - } while (0) - -#define dynamic_dev_dbg(dev, format, ...) do { \ - static char mod_name[] \ - __attribute__((section("__verbose_strings"))) \ - = KBUILD_MODNAME; \ - static struct mod_debug descriptor \ - __used \ - __attribute__((section("__verbose"), aligned(8))) = \ - { mod_name, mod_name, NULL, TYPE_BOOLEAN, DEBUG_HASH, DEBUG_HASH2 };\ - if (__dynamic_dbg_enabled(KBUILD_MODNAME, TYPE_BOOLEAN, \ - 0, 0, DEBUG_HASH)) \ - dev_printk(KERN_DEBUG, dev, \ - KBUILD_MODNAME ": " format, \ - ##__VA_ARGS__); \ - } while (0) - -#else - -static inline int unregister_dynamic_debug_module(const char *mod_name) -{ - return 0; -} -static inline int __dynamic_dbg_enabled_helper(char *modname, int type, - int value, int hash) -{ - return 0; -} - -#define __dynamic_dbg_enabled(module, type, value, level, hash) ({ 0; }) -#define dynamic_pr_debug(fmt, ...) do { } while (0) -#define dynamic_dev_dbg(dev, format, ...) do { } while (0) -#endif - -#endif diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 7fa371898e3..b5496ecbec7 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include @@ -358,7 +358,7 @@ static inline char *pack_hex_byte(char *buf, u8 byte) #if defined(DEBUG) #define pr_debug(fmt, ...) \ printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) -#elif defined(CONFIG_DYNAMIC_PRINTK_DEBUG) +#elif defined(CONFIG_DYNAMIC_DEBUG) #define pr_debug(fmt, ...) do { \ dynamic_pr_debug(pr_fmt(fmt), ##__VA_ARGS__); \ } while (0) diff --git a/kernel/module.c b/kernel/module.c index 1196f5d1170..77672233387 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -822,7 +822,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user, mutex_lock(&module_mutex); /* Store the name of the last unloaded module for diagnostic purposes */ strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module)); - unregister_dynamic_debug_module(mod->name); + ddebug_remove_module(mod->name); free_module(mod); out: @@ -1827,19 +1827,13 @@ static inline void add_kallsyms(struct module *mod, } #endif /* CONFIG_KALLSYMS */ -static void dynamic_printk_setup(struct mod_debug *debug, unsigned int num) +static void dynamic_debug_setup(struct _ddebug *debug, unsigned int num) { -#ifdef CONFIG_DYNAMIC_PRINTK_DEBUG - unsigned int i; - - for (i = 0; i < num; i++) { - register_dynamic_debug_module(debug[i].modname, - debug[i].type, - debug[i].logical_modname, - debug[i].flag_names, - debug[i].hash, debug[i].hash2); - } -#endif /* CONFIG_DYNAMIC_PRINTK_DEBUG */ +#ifdef CONFIG_DYNAMIC_DEBUG + if (ddebug_add_module(debug, num, debug->modname)) + printk(KERN_ERR "dynamic debug error adding module: %s\n", + debug->modname); +#endif } static void *module_alloc_update_bounds(unsigned long size) @@ -2213,12 +2207,13 @@ static noinline struct module *load_module(void __user *umod, add_kallsyms(mod, sechdrs, symindex, strindex, secstrings); if (!mod->taints) { - struct mod_debug *debug; + struct _ddebug *debug; unsigned int num_debug; debug = section_objs(hdr, sechdrs, secstrings, "__verbose", sizeof(*debug), &num_debug); - dynamic_printk_setup(debug, num_debug); + if (debug) + dynamic_debug_setup(debug, num_debug); } /* sechdrs[0].sh_size is always zero */ diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 1bcf9cd4baa..0dd1c04c732 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -847,7 +847,7 @@ config BUILD_DOCSRC Say N if you are unsure. -config DYNAMIC_PRINTK_DEBUG +config DYNAMIC_DEBUG bool "Enable dynamic printk() call support" default n depends on PRINTK diff --git a/lib/Makefile b/lib/Makefile index 32b0e64ded2..8633d6be9d2 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -82,7 +82,7 @@ obj-$(CONFIG_HAVE_LMB) += lmb.o obj-$(CONFIG_HAVE_ARCH_TRACEHOOK) += syscall.o -obj-$(CONFIG_DYNAMIC_PRINTK_DEBUG) += dynamic_printk.o +obj-$(CONFIG_DYNAMIC_DEBUG) += dynamic_debug.o hostprogs-y := gen_crc32table clean-files := crc32table.h diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c new file mode 100644 index 00000000000..9e123ae326b --- /dev/null +++ b/lib/dynamic_debug.c @@ -0,0 +1,756 @@ +/* + * lib/dynamic_debug.c + * + * make pr_debug()/dev_dbg() calls runtime configurable based upon their + * source module. + * + * Copyright (C) 2008 Jason Baron + * By Greg Banks + * Copyright (c) 2008 Silicon Graphics Inc. All Rights Reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern struct _ddebug __start___verbose[]; +extern struct _ddebug __stop___verbose[]; + +/* dynamic_debug_enabled, and dynamic_debug_enabled2 are bitmasks in which + * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They + * use independent hash functions, to reduce the chance of false positives. + */ +long long dynamic_debug_enabled; +EXPORT_SYMBOL_GPL(dynamic_debug_enabled); +long long dynamic_debug_enabled2; +EXPORT_SYMBOL_GPL(dynamic_debug_enabled2); + +struct ddebug_table { + struct list_head link; + char *mod_name; + unsigned int num_ddebugs; + unsigned int num_enabled; + struct _ddebug *ddebugs; +}; + +struct ddebug_query { + const char *filename; + const char *module; + const char *function; + const char *format; + unsigned int first_lineno, last_lineno; +}; + +struct ddebug_iter { + struct ddebug_table *table; + unsigned int idx; +}; + +static DEFINE_MUTEX(ddebug_lock); +static LIST_HEAD(ddebug_tables); +static int verbose = 0; + +/* Return the last part of a pathname */ +static inline const char *basename(const char *path) +{ + const char *tail = strrchr(path, '/'); + return tail ? tail+1 : path; +} + +/* format a string into buf[] which describes the _ddebug's flags */ +static char *ddebug_describe_flags(struct _ddebug *dp, char *buf, + size_t maxlen) +{ + char *p = buf; + + BUG_ON(maxlen < 4); + if (dp->flags & _DPRINTK_FLAGS_PRINT) + *p++ = 'p'; + if (p == buf) + *p++ = '-'; + *p = '\0'; + + return buf; +} + +/* + * must be called with ddebug_lock held + */ + +static int disabled_hash(char hash, bool first_table) +{ + struct ddebug_table *dt; + char table_hash_value; + + list_for_each_entry(dt, &ddebug_tables, link) { + if (first_table) + table_hash_value = dt->ddebugs->primary_hash; + else + table_hash_value = dt->ddebugs->secondary_hash; + if (dt->num_enabled && (hash == table_hash_value)) + return 0; + } + return 1; +} + +/* + * Search the tables for _ddebug's which match the given + * `query' and apply the `flags' and `mask' to them. Tells + * the user which ddebug's were changed, or whether none + * were matched. + */ +static void ddebug_change(const struct ddebug_query *query, + unsigned int flags, unsigned int mask) +{ + int i; + struct ddebug_table *dt; + unsigned int newflags; + unsigned int nfound = 0; + char flagbuf[8]; + + /* search for matching ddebugs */ + mutex_lock(&ddebug_lock); + list_for_each_entry(dt, &ddebug_tables, link) { + + /* match against the module name */ + if (query->module != NULL && + strcmp(query->module, dt->mod_name)) + continue; + + for (i = 0 ; i < dt->num_ddebugs ; i++) { + struct _ddebug *dp = &dt->ddebugs[i]; + + /* match against the source filename */ + if (query->filename != NULL && + strcmp(query->filename, dp->filename) && + strcmp(query->filename, basename(dp->filename))) + continue; + + /* match against the function */ + if (query->function != NULL && + strcmp(query->function, dp->function)) + continue; + + /* match against the format */ + if (query->format != NULL && + strstr(dp->format, query->format) == NULL) + continue; + + /* match against the line number range */ + if (query->first_lineno && + dp->lineno < query->first_lineno) + continue; + if (query->last_lineno && + dp->lineno > query->last_lineno) + continue; + + nfound++; + + newflags = (dp->flags & mask) | flags; + if (newflags == dp->flags) + continue; + + if (!newflags) + dt->num_enabled--; + else if (!dp-flags) + dt->num_enabled++; + dp->flags = newflags; + if (newflags) { + dynamic_debug_enabled |= + (1LL << dp->primary_hash); + dynamic_debug_enabled2 |= + (1LL << dp->secondary_hash); + } else { + if (disabled_hash(dp->primary_hash, true)) + dynamic_debug_enabled &= + ~(1LL << dp->primary_hash); + if (disabled_hash(dp->secondary_hash, false)) + dynamic_debug_enabled2 &= + ~(1LL << dp->secondary_hash); + } + if (verbose) + printk(KERN_INFO + "ddebug: changed %s:%d [%s]%s %s\n", + dp->filename, dp->lineno, + dt->mod_name, dp->function, + ddebug_describe_flags(dp, flagbuf, + sizeof(flagbuf))); + } + } + mutex_unlock(&ddebug_lock); + + if (!nfound && verbose) + printk(KERN_INFO "ddebug: no matches for query\n"); +} + +/* + * Wrapper around strsep() to collapse the multiple empty tokens + * that it returns when fed sequences of separator characters. + * Now, if we had strtok_r()... + */ +static inline char *nearly_strtok_r(char **p, const char *sep) +{ + char *r; + + while ((r = strsep(p, sep)) != NULL && *r == '\0') + ; + return r; +} + +/* + * Split the buffer `buf' into space-separated words. + * Return the number of such words or <0 on error. + */ +static int ddebug_tokenize(char *buf, char *words[], int maxwords) +{ + int nwords = 0; + + while (nwords < maxwords && + (words[nwords] = nearly_strtok_r(&buf, " \t\r\n")) != NULL) + nwords++; + if (buf) + return -EINVAL; /* ran out of words[] before bytes */ + + if (verbose) { + int i; + printk(KERN_INFO "%s: split into words:", __func__); + for (i = 0 ; i < nwords ; i++) + printk(" \"%s\"", words[i]); + printk("\n"); + } + + return nwords; +} + +/* + * Parse a single line number. Note that the empty string "" + * is treated as a special case and converted to zero, which + * is later treated as a "don't care" value. + */ +static inline int parse_lineno(const char *str, unsigned int *val) +{ + char *end = NULL; + BUG_ON(str == NULL); + if (*str == '\0') { + *val = 0; + return 0; + } + *val = simple_strtoul(str, &end, 10); + return end == NULL || end == str || *end != '\0' ? -EINVAL : 0; +} + +/* + * Undo octal escaping in a string, inplace. This is useful to + * allow the user to express a query which matches a format + * containing embedded spaces. + */ +#define isodigit(c) ((c) >= '0' && (c) <= '7') +static char *unescape(char *str) +{ + char *in = str; + char *out = str; + + while (*in) { + if (*in == '\\') { + if (in[1] == '\\') { + *out++ = '\\'; + in += 2; + continue; + } else if (in[1] == 't') { + *out++ = '\t'; + in += 2; + continue; + } else if (in[1] == 'n') { + *out++ = '\n'; + in += 2; + continue; + } else if (isodigit(in[1]) && + isodigit(in[2]) && + isodigit(in[3])) { + *out++ = ((in[1] - '0')<<6) | + ((in[2] - '0')<<3) | + (in[3] - '0'); + in += 4; + continue; + } + } + *out++ = *in++; + } + *out = '\0'; + + return str; +} + +/* + * Parse words[] as a ddebug query specification, which is a series + * of (keyword, value) pairs chosen from these possibilities: + * + * func + * file + * file + * module + * format + * line + * line - // where either may be empty + */ +static int ddebug_parse_query(char *words[], int nwords, + struct ddebug_query *query) +{ + unsigned int i; + + /* check we have an even number of words */ + if (nwords % 2 != 0) + return -EINVAL; + memset(query, 0, sizeof(*query)); + + for (i = 0 ; i < nwords ; i += 2) { + if (!strcmp(words[i], "func")) + query->function = words[i+1]; + else if (!strcmp(words[i], "file")) + query->filename = words[i+1]; + else if (!strcmp(words[i], "module")) + query->module = words[i+1]; + else if (!strcmp(words[i], "format")) + query->format = unescape(words[i+1]); + else if (!strcmp(words[i], "line")) { + char *first = words[i+1]; + char *last = strchr(first, '-'); + if (last) + *last++ = '\0'; + if (parse_lineno(first, &query->first_lineno) < 0) + return -EINVAL; + if (last != NULL) { + /* range - */ + if (parse_lineno(last, &query->last_lineno) < 0) + return -EINVAL; + } else { + query->last_lineno = query->first_lineno; + } + } else { + if (verbose) + printk(KERN_ERR "%s: unknown keyword \"%s\"\n", + __func__, words[i]); + return -EINVAL; + } + } + + if (verbose) + printk(KERN_INFO "%s: q->function=\"%s\" q->filename=\"%s\" " + "q->module=\"%s\" q->format=\"%s\" q->lineno=%u-%u\n", + __func__, query->function, query->filename, + query->module, query->format, query->first_lineno, + query->last_lineno); + + return 0; +} + +/* + * Parse `str' as a flags specification, format [-+=][p]+. + * Sets up *maskp and *flagsp to be used when changing the + * flags fields of matched _ddebug's. Returns 0 on success + * or <0 on error. + */ +static int ddebug_parse_flags(const char *str, unsigned int *flagsp, + unsigned int *maskp) +{ + unsigned flags = 0; + int op = '='; + + switch (*str) { + case '+': + case '-': + case '=': + op = *str++; + break; + default: + return -EINVAL; + } + if (verbose) + printk(KERN_INFO "%s: op='%c'\n", __func__, op); + + for ( ; *str ; ++str) { + switch (*str) { + case 'p': + flags |= _DPRINTK_FLAGS_PRINT; + break; + default: + return -EINVAL; + } + } + if (flags == 0) + return -EINVAL; + if (verbose) + printk(KERN_INFO "%s: flags=0x%x\n", __func__, flags); + + /* calculate final *flagsp, *maskp according to mask and op */ + switch (op) { + case '=': + *maskp = 0; + *flagsp = flags; + break; + case '+': + *maskp = ~0U; + *flagsp = flags; + break; + case '-': + *maskp = ~flags; + *flagsp = 0; + break; + } + if (verbose) + printk(KERN_INFO "%s: *flagsp=0x%x *maskp=0x%x\n", + __func__, *flagsp, *maskp); + return 0; +} + +/* + * File_ops->write method for /dynamic_debug/conrol. Gathers the + * command text from userspace, parses and executes it. + */ +static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf, + size_t len, loff_t *offp) +{ + unsigned int flags = 0, mask = 0; + struct ddebug_query query; +#define MAXWORDS 9 + int nwords; + char *words[MAXWORDS]; + char tmpbuf[256]; + + if (len == 0) + return 0; + /* we don't check *offp -- multiple writes() are allowed */ + if (len > sizeof(tmpbuf)-1) + return -E2BIG; + if (copy_from_user(tmpbuf, ubuf, len)) + return -EFAULT; + tmpbuf[len] = '\0'; + if (verbose) + printk(KERN_INFO "%s: read %d bytes from userspace\n", + __func__, (int)len); + + nwords = ddebug_tokenize(tmpbuf, words, MAXWORDS); + if (nwords < 0) + return -EINVAL; + if (ddebug_parse_query(words, nwords-1, &query)) + return -EINVAL; + if (ddebug_parse_flags(words[nwords-1], &flags, &mask)) + return -EINVAL; + + /* actually go and implement the change */ + ddebug_change(&query, flags, mask); + + *offp += len; + return len; +} + +/* + * Set the iterator to point to the first _ddebug object + * and return a pointer to that first object. Returns + * NULL if there are no _ddebugs at all. + */ +static struct _ddebug *ddebug_iter_first(struct ddebug_iter *iter) +{ + if (list_empty(&ddebug_tables)) { + iter->table = NULL; + iter->idx = 0; + return NULL; + } + iter->table = list_entry(ddebug_tables.next, + struct ddebug_table, link); + iter->idx = 0; + return &iter->table->ddebugs[iter->idx]; +} + +/* + * Advance the iterator to point to the next _ddebug + * object from the one the iterator currently points at, + * and returns a pointer to the new _ddebug. Returns + * NULL if the iterator has seen all the _ddebugs. + */ +static struct _ddebug *ddebug_iter_next(struct ddebug_iter *iter) +{ + if (iter->table == NULL) + return NULL; + if (++iter->idx == iter->table->num_ddebugs) { + /* iterate to next table */ + iter->idx = 0; + if (list_is_last(&iter->table->link, &ddebug_tables)) { + iter->table = NULL; + return NULL; + } + iter->table = list_entry(iter->table->link.next, + struct ddebug_table, link); + } + return &iter->table->ddebugs[iter->idx]; +} + +/* + * Seq_ops start method. Called at the start of every + * read() call from userspace. Takes the ddebug_lock and + * seeks the seq_file's iterator to the given position. + */ +static void *ddebug_proc_start(struct seq_file *m, loff_t *pos) +{ + struct ddebug_iter *iter = m->private; + struct _ddebug *dp; + int n = *pos; + + if (verbose) + printk(KERN_INFO "%s: called m=%p *pos=%lld\n", + __func__, m, (unsigned long long)*pos); + + mutex_lock(&ddebug_lock); + + if (!n) + return SEQ_START_TOKEN; + if (n < 0) + return NULL; + dp = ddebug_iter_first(iter); + while (dp != NULL && --n > 0) + dp = ddebug_iter_next(iter); + return dp; +} + +/* + * Seq_ops next method. Called several times within a read() + * call from userspace, with ddebug_lock held. Walks to the + * next _ddebug object with a special case for the header line. + */ +static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos) +{ + struct ddebug_iter *iter = m->private; + struct _ddebug *dp; + + if (verbose) + printk(KERN_INFO "%s: called m=%p p=%p *pos=%lld\n", + __func__, m, p, (unsigned long long)*pos); + + if (p == SEQ_START_TOKEN) + dp = ddebug_iter_first(iter); + else + dp = ddebug_iter_next(iter); + ++*pos; + return dp; +} + +/* + * Seq_ops show method. Called several times within a read() + * call from userspace, with ddebug_lock held. Formats the + * current _ddebug as a single human-readable line, with a + * special case for the header line. + */ +static int ddebug_proc_show(struct seq_file *m, void *p) +{ + struct ddebug_iter *iter = m->private; + struct _ddebug *dp = p; + char flagsbuf[8]; + + if (verbose) + printk(KERN_INFO "%s: called m=%p p=%p\n", + __func__, m, p); + + if (p == SEQ_START_TOKEN) { + seq_puts(m, + "# filename:lineno [module]function flags format\n"); + return 0; + } + + seq_printf(m, "%s:%u [%s]%s %s \"", + dp->filename, dp->lineno, + iter->table->mod_name, dp->function, + ddebug_describe_flags(dp, flagsbuf, sizeof(flagsbuf))); + seq_escape(m, dp->format, "\t\r\n\""); + seq_puts(m, "\"\n"); + + return 0; +} + +/* + * Seq_ops stop method. Called at the end of each read() + * call from userspace. Drops ddebug_lock. + */ +static void ddebug_proc_stop(struct seq_file *m, void *p) +{ + if (verbose) + printk(KERN_INFO "%s: called m=%p p=%p\n", + __func__, m, p); + mutex_unlock(&ddebug_lock); +} + +static const struct seq_operations ddebug_proc_seqops = { + .start = ddebug_proc_start, + .next = ddebug_proc_next, + .show = ddebug_proc_show, + .stop = ddebug_proc_stop +}; + +/* + * File_ops->open method for /dynamic_debug/control. Does the seq_file + * setup dance, and also creates an iterator to walk the _ddebugs. + * Note that we create a seq_file always, even for O_WRONLY files + * where it's not needed, as doing so simplifies the ->release method. + */ +static int ddebug_proc_open(struct inode *inode, struct file *file) +{ + struct ddebug_iter *iter; + int err; + + if (verbose) + printk(KERN_INFO "%s: called\n", __func__); + + iter = kzalloc(sizeof(*iter), GFP_KERNEL); + if (iter == NULL) + return -ENOMEM; + + err = seq_open(file, &ddebug_proc_seqops); + if (err) { + kfree(iter); + return err; + } + ((struct seq_file *) file->private_data)->private = iter; + return 0; +} + +static const struct file_operations ddebug_proc_fops = { + .owner = THIS_MODULE, + .open = ddebug_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, + .write = ddebug_proc_write +}; + +/* + * Allocate a new ddebug_table for the given module + * and add it to the global list. + */ +int ddebug_add_module(struct _ddebug *tab, unsigned int n, + const char *name) +{ + struct ddebug_table *dt; + char *new_name; + + dt = kzalloc(sizeof(*dt), GFP_KERNEL); + if (dt == NULL) + return -ENOMEM; + new_name = kstrdup(name, GFP_KERNEL); + if (new_name == NULL) { + kfree(dt); + return -ENOMEM; + } + dt->mod_name = new_name; + dt->num_ddebugs = n; + dt->num_enabled = 0; + dt->ddebugs = tab; + + mutex_lock(&ddebug_lock); + list_add_tail(&dt->link, &ddebug_tables); + mutex_unlock(&ddebug_lock); + + if (verbose) + printk(KERN_INFO "%u debug prints in module %s\n", + n, dt->mod_name); + return 0; +} +EXPORT_SYMBOL_GPL(ddebug_add_module); + +static void ddebug_table_free(struct ddebug_table *dt) +{ + list_del_init(&dt->link); + kfree(dt->mod_name); + kfree(dt); +} + +/* + * Called in response to a module being unloaded. Removes + * any ddebug_table's which point at the module. + */ +int ddebug_remove_module(char *mod_name) +{ + struct ddebug_table *dt, *nextdt; + int ret = -ENOENT; + + if (verbose) + printk(KERN_INFO "%s: removing module \"%s\"\n", + __func__, mod_name); + + mutex_lock(&ddebug_lock); + list_for_each_entry_safe(dt, nextdt, &ddebug_tables, link) { + if (!strcmp(dt->mod_name, mod_name)) { + ddebug_table_free(dt); + ret = 0; + } + } + mutex_unlock(&ddebug_lock); + return ret; +} +EXPORT_SYMBOL_GPL(ddebug_remove_module); + +static void ddebug_remove_all_tables(void) +{ + mutex_lock(&ddebug_lock); + while (!list_empty(&ddebug_tables)) { + struct ddebug_table *dt = list_entry(ddebug_tables.next, + struct ddebug_table, + link); + ddebug_table_free(dt); + } + mutex_unlock(&ddebug_lock); +} + +static int __init dynamic_debug_init(void) +{ + struct dentry *dir, *file; + struct _ddebug *iter, *iter_start; + const char *modname = NULL; + int ret = 0; + int n = 0; + + dir = debugfs_create_dir("dynamic_debug", NULL); + if (!dir) + return -ENOMEM; + file = debugfs_create_file("control", 0644, dir, NULL, + &ddebug_proc_fops); + if (!file) { + debugfs_remove(dir); + return -ENOMEM; + } + if (__start___verbose != __stop___verbose) { + iter = __start___verbose; + modname = iter->modname; + iter_start = iter; + for (; iter < __stop___verbose; iter++) { + if (strcmp(modname, iter->modname)) { + ret = ddebug_add_module(iter_start, n, modname); + if (ret) + goto out_free; + n = 0; + modname = iter->modname; + iter_start = iter; + } + n++; + } + ret = ddebug_add_module(iter_start, n, modname); + } +out_free: + if (ret) { + ddebug_remove_all_tables(); + debugfs_remove(dir); + debugfs_remove(file); + } + return 0; +} +module_init(dynamic_debug_init); diff --git a/lib/dynamic_printk.c b/lib/dynamic_printk.c deleted file mode 100644 index 165a19763dc..00000000000 --- a/lib/dynamic_printk.c +++ /dev/null @@ -1,414 +0,0 @@ -/* - * lib/dynamic_printk.c - * - * make pr_debug()/dev_dbg() calls runtime configurable based upon their - * their source module. - * - * Copyright (C) 2008 Red Hat, Inc., Jason Baron - */ - -#include -#include -#include -#include -#include -#include - -extern struct mod_debug __start___verbose[]; -extern struct mod_debug __stop___verbose[]; - -struct debug_name { - struct hlist_node hlist; - struct hlist_node hlist2; - int hash1; - int hash2; - char *name; - int enable; - int type; -}; - -static int nr_entries; -static int num_enabled; -int dynamic_enabled = DYNAMIC_ENABLED_NONE; -static struct hlist_head module_table[DEBUG_HASH_TABLE_SIZE] = - { [0 ... DEBUG_HASH_TABLE_SIZE-1] = HLIST_HEAD_INIT }; -static struct hlist_head module_table2[DEBUG_HASH_TABLE_SIZE] = - { [0 ... DEBUG_HASH_TABLE_SIZE-1] = HLIST_HEAD_INIT }; -static DECLARE_MUTEX(debug_list_mutex); - -/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which - * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They - * use independent hash functions, to reduce the chance of false positives. - */ -long long dynamic_printk_enabled; -EXPORT_SYMBOL_GPL(dynamic_printk_enabled); -long long dynamic_printk_enabled2; -EXPORT_SYMBOL_GPL(dynamic_printk_enabled2); - -/* returns the debug module pointer. */ -static struct debug_name *find_debug_module(char *module_name) -{ - int i; - struct hlist_head *head; - struct hlist_node *node; - struct debug_name *element; - - element = NULL; - for (i = 0; i < DEBUG_HASH_TABLE_SIZE; i++) { - head = &module_table[i]; - hlist_for_each_entry_rcu(element, node, head, hlist) - if (!strcmp(element->name, module_name)) - return element; - } - return NULL; -} - -/* returns the debug module pointer. */ -static struct debug_name *find_debug_module_hash(char *module_name, int hash) -{ - struct hlist_head *head; - struct hlist_node *node; - struct debug_name *element; - - element = NULL; - head = &module_table[hash]; - hlist_for_each_entry_rcu(element, node, head, hlist) - if (!strcmp(element->name, module_name)) - return element; - return NULL; -} - -/* caller must hold mutex*/ -static int __add_debug_module(char *mod_name, int hash, int hash2) -{ - struct debug_name *new; - char *module_name; - int ret = 0; - - if (find_debug_module(mod_name)) { - ret = -EINVAL; - goto out; - } - module_name = kmalloc(strlen(mod_name) + 1, GFP_KERNEL); - if (!module_name) { - ret = -ENOMEM; - goto out; - } - module_name = strcpy(module_name, mod_name); - module_name[strlen(mod_name)] = '\0'; - new = kzalloc(sizeof(struct debug_name), GFP_KERNEL); - if (!new) { - kfree(module_name); - ret = -ENOMEM; - goto out; - } - INIT_HLIST_NODE(&new->hlist); - INIT_HLIST_NODE(&new->hlist2); - new->name = module_name; - new->hash1 = hash; - new->hash2 = hash2; - hlist_add_head_rcu(&new->hlist, &module_table[hash]); - hlist_add_head_rcu(&new->hlist2, &module_table2[hash2]); - nr_entries++; -out: - return ret; -} - -int unregister_dynamic_debug_module(char *mod_name) -{ - struct debug_name *element; - int ret = 0; - - down(&debug_list_mutex); - element = find_debug_module(mod_name); - if (!element) { - ret = -EINVAL; - goto out; - } - hlist_del_rcu(&element->hlist); - hlist_del_rcu(&element->hlist2); - synchronize_rcu(); - kfree(element->name); - if (element->enable) - num_enabled--; - kfree(element); - nr_entries--; -out: - up(&debug_list_mutex); - return ret; -} -EXPORT_SYMBOL_GPL(unregister_dynamic_debug_module); - -int register_dynamic_debug_module(char *mod_name, int type, char *share_name, - char *flags, int hash, int hash2) -{ - struct debug_name *elem; - int ret = 0; - - down(&debug_list_mutex); - elem = find_debug_module(mod_name); - if (!elem) { - if (__add_debug_module(mod_name, hash, hash2)) - goto out; - elem = find_debug_module(mod_name); - if (dynamic_enabled == DYNAMIC_ENABLED_ALL && - !strcmp(mod_name, share_name)) { - elem->enable = true; - num_enabled++; - } - } - elem->type |= type; -out: - up(&debug_list_mutex); - return ret; -} -EXPORT_SYMBOL_GPL(register_dynamic_debug_module); - -int __dynamic_dbg_enabled_helper(char *mod_name, int type, int value, int hash) -{ - struct debug_name *elem; - int ret = 0; - - if (dynamic_enabled == DYNAMIC_ENABLED_ALL) - return 1; - rcu_read_lock(); - elem = find_debug_module_hash(mod_name, hash); - if (elem && elem->enable) - ret = 1; - rcu_read_unlock(); - return ret; -} -EXPORT_SYMBOL_GPL(__dynamic_dbg_enabled_helper); - -static void set_all(bool enable) -{ - struct debug_name *e; - struct hlist_node *node; - int i; - long long enable_mask; - - for (i = 0; i < DEBUG_HASH_TABLE_SIZE; i++) { - if (module_table[i].first != NULL) { - hlist_for_each_entry(e, node, &module_table[i], hlist) { - e->enable = enable; - } - } - } - if (enable) - enable_mask = ULLONG_MAX; - else - enable_mask = 0; - dynamic_printk_enabled = enable_mask; - dynamic_printk_enabled2 = enable_mask; -} - -static int disabled_hash(int i, bool first_table) -{ - struct debug_name *e; - struct hlist_node *node; - - if (first_table) { - hlist_for_each_entry(e, node, &module_table[i], hlist) { - if (e->enable) - return 0; - } - } else { - hlist_for_each_entry(e, node, &module_table2[i], hlist2) { - if (e->enable) - return 0; - } - } - return 1; -} - -static ssize_t pr_debug_write(struct file *file, const char __user *buf, - size_t length, loff_t *ppos) -{ - char *buffer, *s, *value_str, *setting_str; - int err, value; - struct debug_name *elem = NULL; - int all = 0; - - if (length > PAGE_SIZE || length < 0) - return -EINVAL; - - buffer = (char *)__get_free_page(GFP_KERNEL); - if (!buffer) - return -ENOMEM; - - err = -EFAULT; - if (copy_from_user(buffer, buf, length)) - goto out; - - err = -EINVAL; - if (length < PAGE_SIZE) - buffer[length] = '\0'; - else if (buffer[PAGE_SIZE-1]) - goto out; - - err = -EINVAL; - down(&debug_list_mutex); - - if (strncmp("set", buffer, 3)) - goto out_up; - s = buffer + 3; - setting_str = strsep(&s, "="); - if (s == NULL) - goto out_up; - setting_str = strstrip(setting_str); - value_str = strsep(&s, " "); - if (s == NULL) - goto out_up; - s = strstrip(s); - if (!strncmp(s, "all", 3)) - all = 1; - else - elem = find_debug_module(s); - if (!strncmp(setting_str, "enable", 6)) { - value = !!simple_strtol(value_str, NULL, 10); - if (all) { - if (value) { - set_all(true); - num_enabled = nr_entries; - dynamic_enabled = DYNAMIC_ENABLED_ALL; - } else { - set_all(false); - num_enabled = 0; - dynamic_enabled = DYNAMIC_ENABLED_NONE; - } - err = 0; - } else if (elem) { - if (value && (elem->enable == 0)) { - dynamic_printk_enabled |= (1LL << elem->hash1); - dynamic_printk_enabled2 |= (1LL << elem->hash2); - elem->enable = 1; - num_enabled++; - dynamic_enabled = DYNAMIC_ENABLED_SOME; - err = 0; - printk(KERN_DEBUG - "debugging enabled for module %s\n", - elem->name); - } else if (!value && (elem->enable == 1)) { - elem->enable = 0; - num_enabled--; - if (disabled_hash(elem->hash1, true)) - dynamic_printk_enabled &= - ~(1LL << elem->hash1); - if (disabled_hash(elem->hash2, false)) - dynamic_printk_enabled2 &= - ~(1LL << elem->hash2); - if (num_enabled) - dynamic_enabled = DYNAMIC_ENABLED_SOME; - else - dynamic_enabled = DYNAMIC_ENABLED_NONE; - err = 0; - printk(KERN_DEBUG - "debugging disabled for module %s\n", - elem->name); - } - } - } - if (!err) - err = length; -out_up: - up(&debug_list_mutex); -out: - free_page((unsigned long)buffer); - return err; -} - -static void *pr_debug_seq_start(struct seq_file *f, loff_t *pos) -{ - return (*pos < DEBUG_HASH_TABLE_SIZE) ? pos : NULL; -} - -static void *pr_debug_seq_next(struct seq_file *s, void *v, loff_t *pos) -{ - (*pos)++; - if (*pos >= DEBUG_HASH_TABLE_SIZE) - return NULL; - return pos; -} - -static void pr_debug_seq_stop(struct seq_file *s, void *v) -{ - /* Nothing to do */ -} - -static int pr_debug_seq_show(struct seq_file *s, void *v) -{ - struct hlist_head *head; - struct hlist_node *node; - struct debug_name *elem; - unsigned int i = *(loff_t *) v; - - rcu_read_lock(); - head = &module_table[i]; - hlist_for_each_entry_rcu(elem, node, head, hlist) { - seq_printf(s, "%s enabled=%d", elem->name, elem->enable); - seq_printf(s, "\n"); - } - rcu_read_unlock(); - return 0; -} - -static struct seq_operations pr_debug_seq_ops = { - .start = pr_debug_seq_start, - .next = pr_debug_seq_next, - .stop = pr_debug_seq_stop, - .show = pr_debug_seq_show -}; - -static int pr_debug_open(struct inode *inode, struct file *filp) -{ - return seq_open(filp, &pr_debug_seq_ops); -} - -static const struct file_operations pr_debug_operations = { - .open = pr_debug_open, - .read = seq_read, - .write = pr_debug_write, - .llseek = seq_lseek, - .release = seq_release, -}; - -static int __init dynamic_printk_init(void) -{ - struct dentry *dir, *file; - struct mod_debug *iter; - unsigned long value; - - dir = debugfs_create_dir("dynamic_printk", NULL); - if (!dir) - return -ENOMEM; - file = debugfs_create_file("modules", 0644, dir, NULL, - &pr_debug_operations); - if (!file) { - debugfs_remove(dir); - return -ENOMEM; - } - for (value = (unsigned long)__start___verbose; - value < (unsigned long)__stop___verbose; - value += sizeof(struct mod_debug)) { - iter = (struct mod_debug *)value; - register_dynamic_debug_module(iter->modname, - iter->type, - iter->logical_modname, - iter->flag_names, iter->hash, iter->hash2); - } - if (dynamic_enabled == DYNAMIC_ENABLED_ALL) - set_all(true); - return 0; -} -module_init(dynamic_printk_init); -/* may want to move this earlier so we can get traces as early as possible */ - -static int __init dynamic_printk_setup(char *str) -{ - if (str) - return -ENOENT; - dynamic_enabled = DYNAMIC_ENABLED_ALL; - return 0; -} -/* Use early_param(), so we can get debug output as early as possible */ -early_param("dynamic_printk", dynamic_printk_setup); diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c index 9e169ef2e85..12bd09dbd36 100644 --- a/net/netfilter/nf_conntrack_pptp.c +++ b/net/netfilter/nf_conntrack_pptp.c @@ -66,7 +66,7 @@ void struct nf_conntrack_expect *exp) __read_mostly; EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_expectfn); -#if defined(DEBUG) || defined(CONFIG_DYNAMIC_PRINTK_DEBUG) +#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) /* PptpControlMessageType names */ const char *const pptp_msg_name[] = { "UNKNOWN_MESSAGE", diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index e06365775bd..c18fa150b6f 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -97,7 +97,7 @@ modname_flags = $(if $(filter 1,$(words $(modname))),\ -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") #hash values -ifdef CONFIG_DYNAMIC_PRINTK_DEBUG +ifdef CONFIG_DYNAMIC_DEBUG debug_flags = -D"DEBUG_HASH=$(shell ./scripts/basic/hash djb2 $(@D)$(modname))"\ -D"DEBUG_HASH2=$(shell ./scripts/basic/hash r5 $(@D)$(modname))" else -- GitLab From 86151fdf38b3795f292b39defbff39d2684b9c8c Mon Sep 17 00:00:00 2001 From: Jason Baron Date: Thu, 5 Feb 2009 11:53:15 -0500 Subject: [PATCH 4448/4982] dynamic debug: update docs updates the documentation for 'dynamic debug' feature. Signed-off-by: Greg Banks Signed-off-by: Jason Baron Signed-off-by: Greg Kroah-Hartman --- Documentation/dynamic-debug-howto.txt | 232 ++++++++++++++++++++++++++ lib/Kconfig.debug | 72 ++++---- 2 files changed, 273 insertions(+), 31 deletions(-) create mode 100644 Documentation/dynamic-debug-howto.txt diff --git a/Documentation/dynamic-debug-howto.txt b/Documentation/dynamic-debug-howto.txt new file mode 100644 index 00000000000..68394825e86 --- /dev/null +++ b/Documentation/dynamic-debug-howto.txt @@ -0,0 +1,232 @@ + +Introduction +============ + +This document describes how to use the dynamic debug (ddebug) feature. + +Dynamic debug is designed to allow you to dynamically enable/disable kernel +code to obtain additional kernel information. Currently, if +CONFIG_DYNAMIC_DEBUG is set, then all pr_debug()/dev_debug() calls can be +dynamically enabled per-callsite. + +Dynamic debug has even more useful features: + + * Simple query language allows turning on and off debugging statements by + matching any combination of: + + - source filename + - function name + - line number (including ranges of line numbers) + - module name + - format string + + * Provides a debugfs control file: /dynamic_debug/control which can be + read to display the complete list of known debug statements, to help guide you + +Controlling dynamic debug Behaviour +=============================== + +The behaviour of pr_debug()/dev_debug()s are controlled via writing to a +control file in the 'debugfs' filesystem. Thus, you must first mount the debugfs +filesystem, in order to make use of this feature. Subsequently, we refer to the +control file as: /dynamic_debug/control. For example, if you want to +enable printing from source file 'svcsock.c', line 1603 you simply do: + +nullarbor:~ # echo 'file svcsock.c line 1603 +p' > + /dynamic_debug/control + +If you make a mistake with the syntax, the write will fail thus: + +nullarbor:~ # echo 'file svcsock.c wtf 1 +p' > + /dynamic_debug/control +-bash: echo: write error: Invalid argument + +Viewing Dynamic Debug Behaviour +=========================== + +You can view the currently configured behaviour of all the debug statements +via: + +nullarbor:~ # cat /dynamic_debug/control +# filename:lineno [module]function flags format +/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:323 [svcxprt_rdma]svc_rdma_cleanup - "SVCRDMA\040Module\040Removed,\040deregister\040RPC\040RDMA\040transport\012" +/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:341 [svcxprt_rdma]svc_rdma_init - "\011max_inline\040\040\040\040\040\040\040:\040%d\012" +/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:340 [svcxprt_rdma]svc_rdma_init - "\011sq_depth\040\040\040\040\040\040\040\040\040:\040%d\012" +/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:338 [svcxprt_rdma]svc_rdma_init - "\011max_requests\040\040\040\040\040:\040%d\012" +... + + +You can also apply standard Unix text manipulation filters to this +data, e.g. + +nullarbor:~ # grep -i rdma /dynamic_debug/control | wc -l +62 + +nullarbor:~ # grep -i tcp /dynamic_debug/control | wc -l +42 + +Note in particular that the third column shows the enabled behaviour +flags for each debug statement callsite (see below for definitions of the +flags). The default value, no extra behaviour enabled, is "-". So +you can view all the debug statement callsites with any non-default flags: + +nullarbor:~ # awk '$3 != "-"' /dynamic_debug/control +# filename:lineno [module]function flags format +/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c:1603 [sunrpc]svc_send p "svc_process:\040st_sendto\040returned\040%d\012" + + +Command Language Reference +========================== + +At the lexical level, a command comprises a sequence of words separated +by whitespace characters. Note that newlines are treated as word +separators and do *not* end a command or allow multiple commands to +be done together. So these are all equivalent: + +nullarbor:~ # echo -c 'file svcsock.c line 1603 +p' > + /dynamic_debug/control +nullarbor:~ # echo -c ' file svcsock.c line 1603 +p ' > + /dynamic_debug/control +nullarbor:~ # echo -c 'file svcsock.c\nline 1603 +p' > + /dynamic_debug/control +nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' > + /dynamic_debug/control + +Commands are bounded by a write() system call. If you want to do +multiple commands you need to do a separate "echo" for each, like: + +nullarbor:~ # echo 'file svcsock.c line 1603 +p' > /proc/dprintk ;\ +> echo 'file svcsock.c line 1563 +p' > /proc/dprintk + +or even like: + +nullarbor:~ # ( +> echo 'file svcsock.c line 1603 +p' ;\ +> echo 'file svcsock.c line 1563 +p' ;\ +> ) > /proc/dprintk + +At the syntactical level, a command comprises a sequence of match +specifications, followed by a flags change specification. + +command ::= match-spec* flags-spec + +The match-spec's are used to choose a subset of the known dprintk() +callsites to which to apply the flags-spec. Think of them as a query +with implicit ANDs between each pair. Note that an empty list of +match-specs is possible, but is not very useful because it will not +match any debug statement callsites. + +A match specification comprises a keyword, which controls the attribute +of the callsite to be compared, and a value to compare against. Possible +keywords are: + +match-spec ::= 'func' string | + 'file' string | + 'module' string | + 'format' string | + 'line' line-range + +line-range ::= lineno | + '-'lineno | + lineno'-' | + lineno'-'lineno +// Note: line-range cannot contain space, e.g. +// "1-30" is valid range but "1 - 30" is not. + +lineno ::= unsigned-int + +The meanings of each keyword are: + +func + The given string is compared against the function name + of each callsite. Example: + + func svc_tcp_accept + +file + The given string is compared against either the full + pathname or the basename of the source file of each + callsite. Examples: + + file svcsock.c + file /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c + +module + The given string is compared against the module name + of each callsite. The module name is the string as + seen in "lsmod", i.e. without the directory or the .ko + suffix and with '-' changed to '_'. Examples: + + module sunrpc + module nfsd + +format + The given string is searched for in the dynamic debug format + string. Note that the string does not need to match the + entire format, only some part. Whitespace and other + special characters can be escaped using C octal character + escape \ooo notation, e.g. the space character is \040. + Examples: + + format svcrdma: // many of the NFS/RDMA server dprintks + format readahead // some dprintks in the readahead cache + format nfsd:\040SETATTR // how to match a format with whitespace + +line + The given line number or range of line numbers is compared + against the line number of each dprintk() callsite. A single + line number matches the callsite line number exactly. A + range of line numbers matches any callsite between the first + and last line number inclusive. An empty first number means + the first line in the file, an empty line number means the + last number in the file. Examples: + + line 1603 // exactly line 1603 + line 1600-1605 // the six lines from line 1600 to line 1605 + line -1605 // the 1605 lines from line 1 to line 1605 + line 1600- // all lines from line 1600 to the end of the file + +The flags specification comprises a change operation followed +by one or more flag characters. The change operation is one +of the characters: + +- + remove the given flags + ++ + add the given flags + += + set the flags to the given flags + +The flags are: + +p + Causes a printk() message to be emitted to dmesg + +Note the regexp ^[-+=][scp]+$ matches a flags specification. +Note also that there is no convenient syntax to remove all +the flags at once, you need to use "-psc". + +Examples +======== + +// enable the message at line 1603 of file svcsock.c +nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' > + /dynamic_debug/control + +// enable all the messages in file svcsock.c +nullarbor:~ # echo -n 'file svcsock.c +p' > + /dynamic_debug/control + +// enable all the messages in the NFS server module +nullarbor:~ # echo -n 'module nfsd +p' > + /dynamic_debug/control + +// enable all 12 messages in the function svc_process() +nullarbor:~ # echo -n 'func svc_process +p' > + /dynamic_debug/control + +// disable all 12 messages in the function svc_process() +nullarbor:~ # echo -n 'func svc_process -p' > + /dynamic_debug/control diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 0dd1c04c732..8fee0a13ac5 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -848,59 +848,69 @@ config BUILD_DOCSRC Say N if you are unsure. config DYNAMIC_DEBUG - bool "Enable dynamic printk() call support" + bool "Enable dynamic printk() support" default n depends on PRINTK + depends on DEBUG_FS select PRINTK_DEBUG help Compiles debug level messages into the kernel, which would not otherwise be available at runtime. These messages can then be - enabled/disabled on a per module basis. This mechanism implicitly - enables all pr_debug() and dev_dbg() calls. The impact of this - compile option is a larger kernel text size of about 2%. + enabled/disabled based on various levels of scope - per source file, + function, module, format string, and line number. This mechanism + implicitly enables all pr_debug() and dev_dbg() calls. The impact of + this compile option is a larger kernel text size of about 2%. Usage: - Dynamic debugging is controlled by the debugfs file, - dynamic_printk/modules. This file contains a list of the modules that - can be enabled. The format of the file is the module name, followed - by a set of flags that can be enabled. The first flag is always the - 'enabled' flag. For example: + Dynamic debugging is controlled via the 'dynamic_debug/ddebug' file, + which is contained in the 'debugfs' filesystem. Thus, the debugfs + filesystem must first be mounted before making use of this feature. + We refer the control file as: /dynamic_debug/ddebug. This + file contains a list of the debug statements that can be enabled. The + format for each line of the file is: - - . - . - . + filename:lineno [module]function flags format - : Name of the module in which the debug call resides - : whether the messages are enabled or not + filename : source file of the debug statement + lineno : line number of the debug statement + module : module that contains the debug statement + function : function that contains the debug statement + flags : 'p' means the line is turned 'on' for printing + format : the format used for the debug statement From a live system: - snd_hda_intel enabled=0 - fixup enabled=0 - driver enabled=0 + nullarbor:~ # cat /dynamic_debug/ddebug + # filename:lineno [module]function flags format + fs/aio.c:222 [aio]__put_ioctx - "__put_ioctx:\040freeing\040%p\012" + fs/aio.c:248 [aio]ioctx_alloc - "ENOMEM:\040nr_events\040too\040high\012" + fs/aio.c:1770 [aio]sys_io_cancel - "calling\040cancel\012" - Enable a module: + Example usage: - $echo "set enabled=1 " > dynamic_printk/modules + // enable the message at line 1603 of file svcsock.c + nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' > + /dynamic_debug/ddebug - Disable a module: + // enable all the messages in file svcsock.c + nullarbor:~ # echo -n 'file svcsock.c +p' > + /dynamic_debug/ddebug - $echo "set enabled=0 " > dynamic_printk/modules + // enable all the messages in the NFS server module + nullarbor:~ # echo -n 'module nfsd +p' > + /dynamic_debug/ddebug - Enable all modules: + // enable all 12 messages in the function svc_process() + nullarbor:~ # echo -n 'func svc_process +p' > + /dynamic_debug/ddebug - $echo "set enabled=1 all" > dynamic_printk/modules + // disable all 12 messages in the function svc_process() + nullarbor:~ # echo -n 'func svc_process -p' > + /dynamic_debug/ddebug - Disable all modules: - - $echo "set enabled=0 all" > dynamic_printk/modules - - Finally, passing "dynamic_printk" at the command line enables - debugging for all modules. This mode can be turned off via the above - disable command. + See Documentation/dynamic-debug-howto.txt for additional information. source "samples/Kconfig" -- GitLab From 9898abb3d23311fa227a7f46bf4e40fd2954057f Mon Sep 17 00:00:00 2001 From: Greg Banks Date: Fri, 6 Feb 2009 12:54:26 +1100 Subject: [PATCH 4449/4982] Dynamic debug: allow simple quoting of words Allow simple quoting of words in the dynamic debug control language. This allows more natural specification when using the control language to match against printk formats, e.g #echo -n 'format "Setting node for non-present cpu" +p' > /mnt/debugfs/dynamic_debug/control instead of #echo -n 'format Setting\040node\040for\040non-present\040cpu +p' > /mnt/debugfs/dynamic_debug/control Adjust the dynamic debug documention to describe that and provide a new example. Adjust the existing examples in the documentation to reflect the current whitespace escaping behaviour when reading the control file. Fix some minor documentation trailing whitespace. Signed-off-by: Greg Banks Acked-by: Jason Baron Signed-off-by: Greg Kroah-Hartman --- Documentation/dynamic-debug-howto.txt | 20 +++++++--- lib/dynamic_debug.c | 53 +++++++++++++++++---------- 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/Documentation/dynamic-debug-howto.txt b/Documentation/dynamic-debug-howto.txt index 68394825e86..674c5663d34 100644 --- a/Documentation/dynamic-debug-howto.txt +++ b/Documentation/dynamic-debug-howto.txt @@ -49,10 +49,10 @@ via: nullarbor:~ # cat /dynamic_debug/control # filename:lineno [module]function flags format -/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:323 [svcxprt_rdma]svc_rdma_cleanup - "SVCRDMA\040Module\040Removed,\040deregister\040RPC\040RDMA\040transport\012" -/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:341 [svcxprt_rdma]svc_rdma_init - "\011max_inline\040\040\040\040\040\040\040:\040%d\012" -/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:340 [svcxprt_rdma]svc_rdma_init - "\011sq_depth\040\040\040\040\040\040\040\040\040:\040%d\012" -/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:338 [svcxprt_rdma]svc_rdma_init - "\011max_requests\040\040\040\040\040:\040%d\012" +/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:323 [svcxprt_rdma]svc_rdma_cleanup - "SVCRDMA Module Removed, deregister RPC RDMA transport\012" +/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:341 [svcxprt_rdma]svc_rdma_init - "\011max_inline : %d\012" +/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:340 [svcxprt_rdma]svc_rdma_init - "\011sq_depth : %d\012" +/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:338 [svcxprt_rdma]svc_rdma_init - "\011max_requests : %d\012" ... @@ -72,7 +72,7 @@ you can view all the debug statement callsites with any non-default flags: nullarbor:~ # awk '$3 != "-"' /dynamic_debug/control # filename:lineno [module]function flags format -/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c:1603 [sunrpc]svc_send p "svc_process:\040st_sendto\040returned\040%d\012" +/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c:1603 [sunrpc]svc_send p "svc_process: st_sendto returned %d\012" Command Language Reference @@ -166,11 +166,15 @@ format entire format, only some part. Whitespace and other special characters can be escaped using C octal character escape \ooo notation, e.g. the space character is \040. + Alternatively, the string can be enclosed in double quote + characters (") or single quote characters ('). Examples: format svcrdma: // many of the NFS/RDMA server dprintks format readahead // some dprintks in the readahead cache - format nfsd:\040SETATTR // how to match a format with whitespace + format nfsd:\040SETATTR // one way to match a format with whitespace + format "nfsd: SETATTR" // a neater way to match a format with whitespace + format 'nfsd: SETATTR' // yet another way to match a format with whitespace line The given line number or range of line numbers is compared @@ -230,3 +234,7 @@ nullarbor:~ # echo -n 'func svc_process +p' > // disable all 12 messages in the function svc_process() nullarbor:~ # echo -n 'func svc_process -p' > /dynamic_debug/control + +// enable messages for NFS calls READ, READLINK, READDIR and READDIR+. +nullarbor:~ # echo -n 'format "nfsd: READ" +p' > + /dynamic_debug/control diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index 9e123ae326b..833139ce1e2 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c @@ -195,33 +195,46 @@ static void ddebug_change(const struct ddebug_query *query, printk(KERN_INFO "ddebug: no matches for query\n"); } -/* - * Wrapper around strsep() to collapse the multiple empty tokens - * that it returns when fed sequences of separator characters. - * Now, if we had strtok_r()... - */ -static inline char *nearly_strtok_r(char **p, const char *sep) -{ - char *r; - - while ((r = strsep(p, sep)) != NULL && *r == '\0') - ; - return r; -} - /* * Split the buffer `buf' into space-separated words. - * Return the number of such words or <0 on error. + * Handles simple " and ' quoting, i.e. without nested, + * embedded or escaped \". Return the number of words + * or <0 on error. */ static int ddebug_tokenize(char *buf, char *words[], int maxwords) { int nwords = 0; - while (nwords < maxwords && - (words[nwords] = nearly_strtok_r(&buf, " \t\r\n")) != NULL) - nwords++; - if (buf) - return -EINVAL; /* ran out of words[] before bytes */ + while (*buf) { + char *end; + + /* Skip leading whitespace */ + while (*buf && isspace(*buf)) + buf++; + if (!*buf) + break; /* oh, it was trailing whitespace */ + + /* Run `end' over a word, either whitespace separated or quoted */ + if (*buf == '"' || *buf == '\'') { + int quote = *buf++; + for (end = buf ; *end && *end != quote ; end++) + ; + if (!*end) + return -EINVAL; /* unclosed quote */ + } else { + for (end = buf ; *end && !isspace(*end) ; end++) + ; + BUG_ON(end == buf); + } + /* Here `buf' is the start of the word, `end' is one past the end */ + + if (nwords == maxwords) + return -EINVAL; /* ran out of words[] before bytes */ + if (*end) + *end++ = '\0'; /* terminate the word */ + words[nwords++] = buf; + buf = end; + } if (verbose) { int i; -- GitLab From e6e66b02e11563abdb7f69dcb7a2efbd8d577e77 Mon Sep 17 00:00:00 2001 From: Greg Banks Date: Wed, 11 Mar 2009 21:07:28 +1100 Subject: [PATCH 4450/4982] Dynamic debug: fix pr_fmt() build error When CONFIG_DYNAMIC_DEBUG is enabled, allow callers of pr_debug() to provide their own definition of pr_fmt() even if that definition uses tricks like #define pr_fmt(fmt) "%s:" fmt, __func__ Signed-off-by: Greg Banks Cc: Jason Baron Acked-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- include/linux/dynamic_debug.h | 4 ++-- include/linux/kernel.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h index 07781aaa116..baabf33be24 100644 --- a/include/linux/dynamic_debug.h +++ b/include/linux/dynamic_debug.h @@ -57,7 +57,7 @@ extern int ddebug_remove_module(char *mod_name); { KBUILD_MODNAME, __func__, __FILE__, fmt, DEBUG_HASH, \ DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT }; \ if (__dynamic_dbg_enabled(descriptor)) \ - printk(KERN_DEBUG KBUILD_MODNAME ":" fmt, \ + printk(KERN_DEBUG KBUILD_MODNAME ":" pr_fmt(fmt), \ ##__VA_ARGS__); \ } while (0) @@ -70,7 +70,7 @@ extern int ddebug_remove_module(char *mod_name); DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT }; \ if (__dynamic_dbg_enabled(descriptor)) \ dev_printk(KERN_DEBUG, dev, \ - KBUILD_MODNAME ": " fmt, \ + KBUILD_MODNAME ": " pr_fmt(fmt),\ ##__VA_ARGS__); \ } while (0) diff --git a/include/linux/kernel.h b/include/linux/kernel.h index b5496ecbec7..914918abfdd 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -359,8 +359,9 @@ static inline char *pack_hex_byte(char *buf, u8 byte) #define pr_debug(fmt, ...) \ printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) #elif defined(CONFIG_DYNAMIC_DEBUG) +/* dynamic_pr_debug() uses pr_fmt() internally so we don't need it here */ #define pr_debug(fmt, ...) do { \ - dynamic_pr_debug(pr_fmt(fmt), ##__VA_ARGS__); \ + dynamic_pr_debug(fmt, ##__VA_ARGS__); \ } while (0) #else #define pr_debug(fmt, ...) \ -- GitLab From 4097f663cbe9e58de7ebed222f8af33267f297a8 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Tue, 24 Mar 2009 16:40:13 -0700 Subject: [PATCH 4451/4982] be2net: cleanup rx/tx rate calculations Hi, Pls accept this patch to cleanup rx/tx rate calculations as follows: - check for jiffies wraparound - remove typecast of a denominator - do rate calculation only in workqueue context periodically Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 12 ++--- drivers/net/benet/be_main.c | 96 +++++++++++++++++++++++++------------ 2 files changed, 72 insertions(+), 36 deletions(-) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index f327be57ca9..c49ddd08b2a 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -100,9 +100,9 @@ struct be_drvr_stats { u32 be_tx_wrbs; /* number of tx WRBs used */ u32 be_tx_events; /* number of tx completion events */ u32 be_tx_compl; /* number of tx completion entries processed */ - u64 be_tx_jiffies; - ulong be_tx_bytes; - ulong be_tx_bytes_prev; + ulong be_tx_jiffies; + u64 be_tx_bytes; + u64 be_tx_bytes_prev; u32 be_tx_rate; u32 cache_barrier[16]; @@ -113,9 +113,9 @@ struct be_drvr_stats { u32 be_rx_compl; /* number of rx completion entries processed */ u32 be_lro_hgram_data[8]; /* histogram of LRO data packets */ u32 be_lro_hgram_ack[8]; /* histogram of LRO ACKs */ - u64 be_rx_jiffies; - ulong be_rx_bytes; - ulong be_rx_bytes_prev; + ulong be_rx_jiffies; + u64 be_rx_bytes; + u64 be_rx_bytes_prev; u32 be_rx_rate; /* number of non ether type II frames dropped where * frame len > length field of Mac Hdr */ diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 0ecaffb70e5..f901fee79a2 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -245,19 +245,29 @@ static void be_link_status_update(struct be_adapter *adapter) /* Update the EQ delay n BE based on the RX frags consumed / sec */ static void be_rx_eqd_update(struct be_adapter *adapter) { - u32 eqd; struct be_ctrl_info *ctrl = &adapter->ctrl; struct be_eq_obj *rx_eq = &adapter->rx_eq; struct be_drvr_stats *stats = &adapter->stats.drvr_stats; + ulong now = jiffies; + u32 eqd; + + if (!rx_eq->enable_aic) + return; + + /* Wrapped around */ + if (time_before(now, stats->rx_fps_jiffies)) { + stats->rx_fps_jiffies = now; + return; + } /* Update once a second */ - if (((jiffies - stats->rx_fps_jiffies) < HZ) || rx_eq->enable_aic == 0) + if ((now - stats->rx_fps_jiffies) < HZ) return; stats->be_rx_fps = (stats->be_rx_frags - stats->be_prev_rx_frags) / - ((jiffies - stats->rx_fps_jiffies) / HZ); + ((now - stats->rx_fps_jiffies) / HZ); - stats->rx_fps_jiffies = jiffies; + stats->rx_fps_jiffies = now; stats->be_prev_rx_frags = stats->be_rx_frags; eqd = stats->be_rx_fps / 110000; eqd = eqd << 3; @@ -280,26 +290,38 @@ static struct net_device_stats *be_get_stats(struct net_device *dev) return &adapter->stats.net_stats; } +static void be_tx_rate_update(struct be_adapter *adapter) +{ + struct be_drvr_stats *stats = drvr_stats(adapter); + ulong now = jiffies; + + /* Wrapped around? */ + if (time_before(now, stats->be_tx_jiffies)) { + stats->be_tx_jiffies = now; + return; + } + + /* Update tx rate once in two seconds */ + if ((now - stats->be_tx_jiffies) > 2 * HZ) { + u32 r; + r = (stats->be_tx_bytes - stats->be_tx_bytes_prev) / + ((now - stats->be_tx_jiffies) / HZ); + r = r / 1000000; /* M bytes/s */ + stats->be_tx_rate = r * 8; /* M bits/s */ + stats->be_tx_jiffies = now; + stats->be_tx_bytes_prev = stats->be_tx_bytes; + } +} + static void be_tx_stats_update(struct be_adapter *adapter, u32 wrb_cnt, u32 copied, bool stopped) { - struct be_drvr_stats *stats = &adapter->stats.drvr_stats; + struct be_drvr_stats *stats = drvr_stats(adapter); stats->be_tx_reqs++; stats->be_tx_wrbs += wrb_cnt; stats->be_tx_bytes += copied; if (stopped) stats->be_tx_stops++; - - /* Update tx rate once in two seconds */ - if ((jiffies - stats->be_tx_jiffies) > 2 * HZ) { - u32 r; - r = (stats->be_tx_bytes - stats->be_tx_bytes_prev) / - ((u32) (jiffies - stats->be_tx_jiffies) / HZ); - r = (r / 1000000); /* M bytes/s */ - stats->be_tx_rate = (r * 8); /* M bits/s */ - stats->be_tx_jiffies = jiffies; - stats->be_tx_bytes_prev = stats->be_tx_bytes; - } } /* Determine number of WRB entries needed to xmit data in an skb */ @@ -573,28 +595,40 @@ static void be_set_multicast_list(struct net_device *netdev) } } -static void be_rx_rate_update(struct be_adapter *adapter, u32 pktsize, - u16 numfrags) +static void be_rx_rate_update(struct be_adapter *adapter) { - struct be_drvr_stats *stats = &adapter->stats.drvr_stats; + struct be_drvr_stats *stats = drvr_stats(adapter); + ulong now = jiffies; u32 rate; - stats->be_rx_compl++; - stats->be_rx_frags += numfrags; - stats->be_rx_bytes += pktsize; + /* Wrapped around */ + if (time_before(now, stats->be_rx_jiffies)) { + stats->be_rx_jiffies = now; + return; + } /* Update the rate once in two seconds */ - if ((jiffies - stats->be_rx_jiffies) < 2 * HZ) + if ((now - stats->be_rx_jiffies) < 2 * HZ) return; rate = (stats->be_rx_bytes - stats->be_rx_bytes_prev) / - ((u32) (jiffies - stats->be_rx_jiffies) / HZ); - rate = (rate / 1000000); /* MB/Sec */ - stats->be_rx_rate = (rate * 8); /* Mega Bits/Sec */ - stats->be_rx_jiffies = jiffies; + ((now - stats->be_rx_jiffies) / HZ); + rate = rate / 1000000; /* MB/Sec */ + stats->be_rx_rate = rate * 8; /* Mega Bits/Sec */ + stats->be_rx_jiffies = now; stats->be_rx_bytes_prev = stats->be_rx_bytes; } +static void be_rx_stats_update(struct be_adapter *adapter, + u32 pktsize, u16 numfrags) +{ + struct be_drvr_stats *stats = drvr_stats(adapter); + + stats->be_rx_compl++; + stats->be_rx_frags += numfrags; + stats->be_rx_bytes += pktsize; +} + static struct be_rx_page_info * get_rx_page_info(struct be_adapter *adapter, u16 frag_idx) { @@ -700,7 +734,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, memset(page_info, 0, sizeof(*page_info)); } - be_rx_rate_update(adapter, pktsize, num_rcvd); + be_rx_stats_update(adapter, pktsize, num_rcvd); return; } @@ -799,7 +833,7 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter, vid, NULL, 0); } - be_rx_rate_update(adapter, pkt_size, num_rcvd); + be_rx_stats_update(adapter, pkt_size, num_rcvd); return; } @@ -841,7 +875,6 @@ static void be_post_rx_frags(struct be_adapter *adapter) u64 page_dmaaddr = 0, frag_dmaaddr; u32 posted, page_offset = 0; - page_info = &page_info_tbl[rxq->head]; for (posted = 0; posted < MAX_RX_POST && !page_info->page; posted++) { if (!pagep) { @@ -1305,6 +1338,9 @@ static void be_worker(struct work_struct *work) /* Set EQ delay */ be_rx_eqd_update(adapter); + be_tx_rate_update(adapter); + be_rx_rate_update(adapter); + if (adapter->rx_post_starved) { adapter->rx_post_starved = false; be_post_rx_frags(adapter); -- GitLab From 91b1a84c10869e2e46a576e5367de3166bff8ecc Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Fri, 30 Jan 2009 18:46:39 -0500 Subject: [PATCH 4452/4982] sata_mv: cleanup chipset GENeration FLAGS Clean up the chipset GENeration FLAGS, and rename them for consistency with other uses of GEN_XX within sata_mv. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 74b1080d116..3dc35543fb3 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -120,14 +120,15 @@ enum { MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */ MV_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI | - ATA_FLAG_PIO_POLLING, + ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING, - MV_6XXX_FLAGS = MV_FLAG_IRQ_COALESCE, + MV_GEN_I_FLAGS = MV_COMMON_FLAGS | ATA_FLAG_NO_ATAPI, - MV_GENIIE_FLAGS = MV_COMMON_FLAGS | MV_6XXX_FLAGS | + MV_GEN_II_FLAGS = MV_COMMON_FLAGS | MV_FLAG_IRQ_COALESCE | ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA | - ATA_FLAG_NCQ | ATA_FLAG_AN, + ATA_FLAG_NCQ | ATA_FLAG_NO_ATAPI, + + MV_GEN_IIE_FLAGS = MV_GEN_II_FLAGS | ATA_FLAG_AN, CRQB_FLAG_READ = (1 << 0), CRQB_TAG_SHIFT = 1, @@ -603,53 +604,49 @@ static struct ata_port_operations mv_iie_ops = { static const struct ata_port_info mv_port_info[] = { { /* chip_504x */ - .flags = MV_COMMON_FLAGS, + .flags = MV_GEN_I_FLAGS, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA6, .port_ops = &mv5_ops, }, { /* chip_508x */ - .flags = MV_COMMON_FLAGS | MV_FLAG_DUAL_HC, + .flags = MV_GEN_I_FLAGS | MV_FLAG_DUAL_HC, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA6, .port_ops = &mv5_ops, }, { /* chip_5080 */ - .flags = MV_COMMON_FLAGS | MV_FLAG_DUAL_HC, + .flags = MV_GEN_I_FLAGS | MV_FLAG_DUAL_HC, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA6, .port_ops = &mv5_ops, }, { /* chip_604x */ - .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS | - ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA | - ATA_FLAG_NCQ, + .flags = MV_GEN_II_FLAGS, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA6, .port_ops = &mv6_ops, }, { /* chip_608x */ - .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS | - ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA | - ATA_FLAG_NCQ | MV_FLAG_DUAL_HC, + .flags = MV_GEN_II_FLAGS | MV_FLAG_DUAL_HC, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA6, .port_ops = &mv6_ops, }, { /* chip_6042 */ - .flags = MV_GENIIE_FLAGS, + .flags = MV_GEN_IIE_FLAGS, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA6, .port_ops = &mv_iie_ops, }, { /* chip_7042 */ - .flags = MV_GENIIE_FLAGS, + .flags = MV_GEN_IIE_FLAGS, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA6, .port_ops = &mv_iie_ops, }, { /* chip_soc */ - .flags = MV_GENIIE_FLAGS, + .flags = MV_GEN_IIE_FLAGS, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA6, .port_ops = &mv_iie_ops, -- GitLab From 00b81235aa0368f84c0e704bec4142cd8c516ad5 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Fri, 30 Jan 2009 18:47:51 -0500 Subject: [PATCH 4453/4982] sata_mv: rearrange mv_start_dma() and friends Rearrange mv_start_dma() and friends, in preparation for adding non-EDMA DMA modes, and non-EDMA interrupts, to the driver. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 66 +++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 3dc35543fb3..fb3288bbd9f 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -536,7 +536,7 @@ static void mv_reset_channel(struct mv_host_priv *hpriv, void __iomem *mmio, unsigned int port_no); static int mv_stop_edma(struct ata_port *ap); static int mv_stop_edma_engine(void __iomem *port_mmio); -static void mv_edma_cfg(struct ata_port *ap, int want_ncq); +static void mv_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma); static void mv_pmp_select(struct ata_port *ap, int pmp); static int mv_pmp_hardreset(struct ata_link *link, unsigned int *class, @@ -849,8 +849,32 @@ static void mv_enable_port_irqs(struct ata_port *ap, mv_set_main_irq_mask(ap->host, disable_bits, enable_bits); } +static void mv_clear_and_enable_port_irqs(struct ata_port *ap, + void __iomem *port_mmio, + unsigned int port_irqs) +{ + struct mv_host_priv *hpriv = ap->host->private_data; + int hardport = mv_hardport_from_port(ap->port_no); + void __iomem *hc_mmio = mv_hc_base_from_port( + mv_host_base(ap->host), ap->port_no); + u32 hc_irq_cause; + + /* clear EDMA event indicators, if any */ + writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); + + /* clear pending irq events */ + hc_irq_cause = ~((DEV_IRQ | DMA_IRQ) << hardport); + writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS); + + /* clear FIS IRQ Cause */ + if (IS_GEN_IIE(hpriv)) + writelfl(0, port_mmio + SATA_FIS_IRQ_CAUSE_OFS); + + mv_enable_port_irqs(ap, port_irqs); +} + /** - * mv_start_dma - Enable eDMA engine + * mv_start_edma - Enable eDMA engine * @base: port base address * @pp: port private data * @@ -860,7 +884,7 @@ static void mv_enable_port_irqs(struct ata_port *ap, * LOCKING: * Inherited from caller. */ -static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio, +static void mv_start_edma(struct ata_port *ap, void __iomem *port_mmio, struct mv_port_priv *pp, u8 protocol) { int want_ncq = (protocol == ATA_PROT_NCQ); @@ -872,26 +896,11 @@ static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio, } if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) { struct mv_host_priv *hpriv = ap->host->private_data; - int hardport = mv_hardport_from_port(ap->port_no); - void __iomem *hc_mmio = mv_hc_base_from_port( - mv_host_base(ap->host), ap->port_no); - u32 hc_irq_cause; - - /* clear EDMA event indicators, if any */ - writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); - - /* clear pending irq events */ - hc_irq_cause = ~((DEV_IRQ | DMA_IRQ) << hardport); - writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS); - mv_edma_cfg(ap, want_ncq); - - /* clear FIS IRQ Cause */ - if (IS_GEN_IIE(hpriv)) - writelfl(0, port_mmio + SATA_FIS_IRQ_CAUSE_OFS); + mv_edma_cfg(ap, want_ncq, 1); mv_set_edma_ptrs(port_mmio, hpriv, pp); - mv_enable_port_irqs(ap, DONE_IRQ|ERR_IRQ); + mv_clear_and_enable_port_irqs(ap, port_mmio, DONE_IRQ|ERR_IRQ); writelfl(EDMA_EN, port_mmio + EDMA_CMD_OFS); pp->pp_flags |= MV_PP_FLAG_EDMA_EN; @@ -1173,7 +1182,7 @@ static void mv_60x1_errata_sata25(struct ata_port *ap, int want_ncq) writel(new, hpriv->base + MV_GPIO_PORT_CTL_OFS); } -static void mv_edma_cfg(struct ata_port *ap, int want_ncq) +static void mv_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma) { u32 cfg; struct mv_port_priv *pp = ap->private_data; @@ -1182,7 +1191,7 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq) /* set up non-NCQ EDMA configuration */ cfg = EDMA_CFG_Q_DEPTH; /* always 0x1f for *all* chips */ - pp->pp_flags &= ~MV_PP_FLAG_FBS_EN; + pp->pp_flags &= ~(MV_PP_FLAG_FBS_EN | MV_PP_FLAG_NCQ_EN); if (IS_GEN_I(hpriv)) cfg |= (1 << 8); /* enab config burst size mask */ @@ -1211,9 +1220,11 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq) } cfg |= (1 << 23); /* do not mask PM field in rx'd FIS */ - cfg |= (1 << 22); /* enab 4-entry host queue cache */ - if (!IS_SOC(hpriv)) - cfg |= (1 << 18); /* enab early completion */ + if (want_edma) { + cfg |= (1 << 22); /* enab 4-entry host queue cache */ + if (!IS_SOC(hpriv)) + cfg |= (1 << 18); /* enab early completion */ + } if (hpriv->hp_flags & MV_HP_CUT_THROUGH) cfg |= (1 << 17); /* enab cut-thru (dis stor&forwrd) */ } @@ -1221,8 +1232,7 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq) if (want_ncq) { cfg |= EDMA_CFG_NCQ; pp->pp_flags |= MV_PP_FLAG_NCQ_EN; - } else - pp->pp_flags &= ~MV_PP_FLAG_NCQ_EN; + } writelfl(cfg, port_mmio + EDMA_CFG_OFS); } @@ -1591,7 +1601,7 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) return ata_sff_qc_issue(qc); } - mv_start_dma(ap, port_mmio, pp, qc->tf.protocol); + mv_start_edma(ap, port_mmio, pp, qc->tf.protocol); pp->req_idx = (pp->req_idx + 1) & MV_MAX_Q_DEPTH_MASK; in_index = pp->req_idx << EDMA_REQ_Q_PTR_SHIFT; -- GitLab From f48765ccb48a62596b664aa88a2b0f943c12c0e1 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Fri, 30 Jan 2009 18:48:41 -0500 Subject: [PATCH 4454/4982] sata_mv: restructure mv_qc_issue Rearrange logic in mv_qc_issue() to handle protocols other than ATA_PROT_DMA, ATA_PROT_NCQ, and ATA_PROT_PIO. This is in preparation for later enabling ATAPI support. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index fb3288bbd9f..0c25f52249d 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1565,14 +1565,26 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc) */ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) { + static int limit_warnings = 10; struct ata_port *ap = qc->ap; void __iomem *port_mmio = mv_ap_base(ap); struct mv_port_priv *pp = ap->private_data; u32 in_index; + unsigned int port_irqs = DONE_IRQ | ERR_IRQ; + + switch (qc->tf.protocol) { + case ATA_PROT_DMA: + case ATA_PROT_NCQ: + mv_start_edma(ap, port_mmio, pp, qc->tf.protocol); + pp->req_idx = (pp->req_idx + 1) & MV_MAX_Q_DEPTH_MASK; + in_index = pp->req_idx << EDMA_REQ_Q_PTR_SHIFT; + + /* Write the request in pointer to kick the EDMA to life */ + writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index, + port_mmio + EDMA_REQ_Q_IN_PTR_OFS); + return 0; - if ((qc->tf.protocol != ATA_PROT_DMA) && - (qc->tf.protocol != ATA_PROT_NCQ)) { - static int limit_warnings = 10; + case ATA_PROT_PIO: /* * Errata SATA#16, SATA#24: warn if multiple DRQs expected. * @@ -1590,27 +1602,22 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) ": attempting PIO w/multiple DRQ: " "this may fail due to h/w errata\n"); } + /* drop through */ + case ATAPI_PROT_PIO: + port_irqs = ERR_IRQ; /* leave DONE_IRQ masked for PIO */ + /* drop through */ + default: /* * We're about to send a non-EDMA capable command to the * port. Turn off EDMA so there won't be problems accessing * shadow block, etc registers. */ mv_stop_edma(ap); - mv_enable_port_irqs(ap, ERR_IRQ); + mv_edma_cfg(ap, 0, 0); + mv_clear_and_enable_port_irqs(ap, mv_ap_base(ap), port_irqs); mv_pmp_select(ap, qc->dev->link->pmp); return ata_sff_qc_issue(qc); } - - mv_start_edma(ap, port_mmio, pp, qc->tf.protocol); - - pp->req_idx = (pp->req_idx + 1) & MV_MAX_Q_DEPTH_MASK; - in_index = pp->req_idx << EDMA_REQ_Q_PTR_SHIFT; - - /* and write the request in pointer to kick the EDMA to life */ - writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index, - port_mmio + EDMA_REQ_Q_IN_PTR_OFS); - - return 0; } static struct ata_queued_cmd *mv_get_active_qc(struct ata_port *ap) -- GitLab From 95db505125fb7bc624b7c3b6747bbeaebbffc2e4 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Fri, 30 Jan 2009 18:49:29 -0500 Subject: [PATCH 4455/4982] sata_mv: update ata_qc_from_tag Update the logic in ata_qc_from_tag() to match that used in similar places elsewhere in libata. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 0c25f52249d..181f0212741 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1628,6 +1628,12 @@ static struct ata_queued_cmd *mv_get_active_qc(struct ata_port *ap) if (pp->pp_flags & MV_PP_FLAG_NCQ_EN) return NULL; qc = ata_qc_from_tag(ap, ap->link.active_tag); + if (qc) { + if (qc->tf.flags & ATA_TFLAG_POLLING) + qc = NULL; + else if (!(qc->flags & ATA_QCFLAG_ACTIVE)) + qc = NULL; + } if (qc && (qc->tf.flags & ATA_TFLAG_POLLING)) qc = NULL; return qc; -- GitLab From 32cd11a61007511ddb38783deec8bb1aa6735789 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Sun, 1 Feb 2009 16:50:32 -0500 Subject: [PATCH 4456/4982] sata_mv: mv_fill_sg fixes v2 Fix mv_fill_sg() to zero out the reserved word (required for ATAPI), and to include a memory barrier. This may also help with problems reported by Jens on the PPC platform. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 181f0212741..9c8ea2c1116 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1364,12 +1364,13 @@ static void mv_fill_sg(struct ata_queued_cmd *qc) u32 offset = addr & 0xffff; u32 len = sg_len; - if ((offset + sg_len > 0x10000)) + if (offset + len > 0x10000) len = 0x10000 - offset; mv_sg->addr = cpu_to_le32(addr & 0xffffffff); mv_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16); mv_sg->flags_size = cpu_to_le32(len & 0xffff); + mv_sg->reserved = 0; sg_len -= len; addr += len; @@ -1381,6 +1382,7 @@ static void mv_fill_sg(struct ata_queued_cmd *qc) if (likely(last_sg)) last_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL); + mb(); /* ensure data structure is visible to the chipset */ } static void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last) -- GitLab From da14265e776f35067045b8555b5f5f7521e50bc4 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Fri, 30 Jan 2009 18:51:54 -0500 Subject: [PATCH 4457/4982] sata_mv: introduce support for ATAPI devices Add ATAPI support to sata_mv, using sff DMA for GEN_II chipsets, and plain old PIO for GEN_IIE. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 190 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 186 insertions(+), 4 deletions(-) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 9c8ea2c1116..6f8a49bc452 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -31,8 +31,6 @@ * * --> Complete a full errata audit for all chipsets to identify others. * - * --> ATAPI support (Marvell claims the 60xx/70xx chips can do it). - * * --> Develop a low-power-consumption strategy, and implement it. * * --> [Experiment, low priority] Investigate interrupt coalescing. @@ -68,7 +66,7 @@ #include #define DRV_NAME "sata_mv" -#define DRV_VERSION "1.25" +#define DRV_VERSION "1.26" enum { /* BAR's are enumerated in terms of pci_resource_start() terms */ @@ -126,7 +124,7 @@ enum { MV_GEN_II_FLAGS = MV_COMMON_FLAGS | MV_FLAG_IRQ_COALESCE | ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA | - ATA_FLAG_NCQ | ATA_FLAG_NO_ATAPI, + ATA_FLAG_NCQ, MV_GEN_IIE_FLAGS = MV_GEN_II_FLAGS | ATA_FLAG_AN, @@ -348,6 +346,12 @@ enum { EDMA_HALTCOND_OFS = 0x60, /* GenIIe halt conditions */ + + BMDMA_CMD_OFS = 0x224, /* bmdma command register */ + BMDMA_STATUS_OFS = 0x228, /* bmdma status register */ + BMDMA_PRD_LOW_OFS = 0x22c, /* bmdma PRD addr 31:0 */ + BMDMA_PRD_HIGH_OFS = 0x230, /* bmdma PRD addr 63:32 */ + /* Host private flags (hp_flags) */ MV_HP_FLAG_MSI = (1 << 0), MV_HP_ERRATA_50XXB0 = (1 << 1), @@ -547,6 +551,15 @@ static void mv_pmp_error_handler(struct ata_port *ap); static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp); +static unsigned long mv_mode_filter(struct ata_device *dev, + unsigned long xfer_mask); +static void mv_sff_irq_clear(struct ata_port *ap); +static int mv_check_atapi_dma(struct ata_queued_cmd *qc); +static void mv_bmdma_setup(struct ata_queued_cmd *qc); +static void mv_bmdma_start(struct ata_queued_cmd *qc); +static void mv_bmdma_stop(struct ata_queued_cmd *qc); +static u8 mv_bmdma_status(struct ata_port *ap); + /* .sg_tablesize is (MV_MAX_SG_CT / 2) in the structures below * because we have to allow room for worst case splitting of * PRDs for 64K boundaries in mv_fill_sg(). @@ -594,6 +607,14 @@ static struct ata_port_operations mv6_ops = { .pmp_softreset = mv_softreset, .softreset = mv_softreset, .error_handler = mv_pmp_error_handler, + + .sff_irq_clear = mv_sff_irq_clear, + .check_atapi_dma = mv_check_atapi_dma, + .bmdma_setup = mv_bmdma_setup, + .bmdma_start = mv_bmdma_start, + .bmdma_stop = mv_bmdma_stop, + .bmdma_status = mv_bmdma_status, + .mode_filter = mv_mode_filter, }; static struct ata_port_operations mv_iie_ops = { @@ -1392,6 +1413,167 @@ static void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last) *cmdw = cpu_to_le16(tmp); } +/** + * mv_mode_filter - Allow ATAPI DMA only on GenII chips. + * @dev: device whose xfer modes are being configured. + * + * Only the GenII hardware can use DMA with ATAPI drives. + */ +static unsigned long mv_mode_filter(struct ata_device *adev, + unsigned long xfer_mask) +{ + if (adev->class == ATA_DEV_ATAPI) { + struct mv_host_priv *hpriv = adev->link->ap->host->private_data; + if (!IS_GEN_II(hpriv)) { + xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); + ata_dev_printk(adev, KERN_INFO, + "ATAPI DMA not supported on this chipset\n"); + } + } + return xfer_mask; +} + +/** + * mv_sff_irq_clear - Clear hardware interrupt after DMA. + * @ap: Port associated with this ATA transaction. + * + * We need this only for ATAPI bmdma transactions, + * as otherwise we experience spurious interrupts + * after libata-sff handles the bmdma interrupts. + */ +static void mv_sff_irq_clear(struct ata_port *ap) +{ + mv_clear_and_enable_port_irqs(ap, mv_ap_base(ap), ERR_IRQ); +} + +/** + * mv_check_atapi_dma - Filter ATAPI cmds which are unsuitable for DMA. + * @qc: queued command to check for chipset/DMA compatibility. + * + * The bmdma engines cannot handle speculative data sizes + * (bytecount under/over flow). So only allow DMA for + * data transfer commands with known data sizes. + * + * LOCKING: + * Inherited from caller. + */ +static int mv_check_atapi_dma(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *scmd = qc->scsicmd; + + if (scmd) { + switch (scmd->cmnd[0]) { + case READ_6: + case READ_10: + case READ_12: + case WRITE_6: + case WRITE_10: + case WRITE_12: + case GPCMD_READ_CD: + case GPCMD_SEND_DVD_STRUCTURE: + case GPCMD_SEND_CUE_SHEET: + return 0; /* DMA is safe */ + } + } + return -EOPNOTSUPP; /* use PIO instead */ +} + +/** + * mv_bmdma_setup - Set up BMDMA transaction + * @qc: queued command to prepare DMA for. + * + * LOCKING: + * Inherited from caller. + */ +static void mv_bmdma_setup(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + void __iomem *port_mmio = mv_ap_base(ap); + struct mv_port_priv *pp = ap->private_data; + + mv_fill_sg(qc); + + /* clear all DMA cmd bits */ + writel(0, port_mmio + BMDMA_CMD_OFS); + + /* load PRD table addr. */ + writel((pp->sg_tbl_dma[qc->tag] >> 16) >> 16, + port_mmio + BMDMA_PRD_HIGH_OFS); + writelfl(pp->sg_tbl_dma[qc->tag], + port_mmio + BMDMA_PRD_LOW_OFS); + + /* issue r/w command */ + ap->ops->sff_exec_command(ap, &qc->tf); +} + +/** + * mv_bmdma_start - Start a BMDMA transaction + * @qc: queued command to start DMA on. + * + * LOCKING: + * Inherited from caller. + */ +static void mv_bmdma_start(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + void __iomem *port_mmio = mv_ap_base(ap); + unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); + u32 cmd = (rw ? 0 : ATA_DMA_WR) | ATA_DMA_START; + + /* start host DMA transaction */ + writelfl(cmd, port_mmio + BMDMA_CMD_OFS); +} + +/** + * mv_bmdma_stop - Stop BMDMA transfer + * @qc: queued command to stop DMA on. + * + * Clears the ATA_DMA_START flag in the bmdma control register + * + * LOCKING: + * Inherited from caller. + */ +static void mv_bmdma_stop(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + void __iomem *port_mmio = mv_ap_base(ap); + u32 cmd; + + /* clear start/stop bit */ + cmd = readl(port_mmio + BMDMA_CMD_OFS); + cmd &= ~ATA_DMA_START; + writelfl(cmd, port_mmio + BMDMA_CMD_OFS); + + /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ + ata_sff_dma_pause(ap); +} + +/** + * mv_bmdma_status - Read BMDMA status + * @ap: port for which to retrieve DMA status. + * + * Read and return equivalent of the sff BMDMA status register. + * + * LOCKING: + * Inherited from caller. + */ +static u8 mv_bmdma_status(struct ata_port *ap) +{ + void __iomem *port_mmio = mv_ap_base(ap); + u32 reg, status; + + /* + * Other bits are valid only if ATA_DMA_ACTIVE==0, + * and the ATA_DMA_INTR bit doesn't exist. + */ + reg = readl(port_mmio + BMDMA_STATUS_OFS); + if (reg & ATA_DMA_ACTIVE) + status = ATA_DMA_ACTIVE; + else + status = (reg & ATA_DMA_ERR) | ATA_DMA_INTR; + return status; +} + /** * mv_qc_prep - Host specific command preparation. * @qc: queued command to prepare -- GitLab From 66e57a2cb0c538d4f84a7233c224735fe1eaa672 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Fri, 30 Jan 2009 18:52:58 -0500 Subject: [PATCH 4458/4982] sata_mv: optimize use of mv_edma_cfg Try and avoid unnecessary reconfiguration of the EDMA config register on every single non-EDMA I/O operation, by moving the call to mv_edma_cfg() into mv_stop_edma(). It must then also be invoked from mv_hardreset() and from mv_port_start(). Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 6f8a49bc452..8f356e4417d 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -979,6 +979,7 @@ static int mv_stop_edma(struct ata_port *ap) { void __iomem *port_mmio = mv_ap_base(ap); struct mv_port_priv *pp = ap->private_data; + int err = 0; if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) return 0; @@ -986,9 +987,10 @@ static int mv_stop_edma(struct ata_port *ap) mv_wait_for_edma_empty_idle(ap); if (mv_stop_edma_engine(port_mmio)) { ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n"); - return -EIO; + err = -EIO; } - return 0; + mv_edma_cfg(ap, 0, 0); + return err; } #ifdef ATA_DEBUG @@ -1337,6 +1339,7 @@ static int mv_port_start(struct ata_port *ap) pp->sg_tbl_dma[tag] = pp->sg_tbl_dma[0]; } } + mv_edma_cfg(ap, 0, 0); return 0; out_port_free_dma_mem: @@ -1797,7 +1800,6 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) * shadow block, etc registers. */ mv_stop_edma(ap); - mv_edma_cfg(ap, 0, 0); mv_clear_and_enable_port_irqs(ap, mv_ap_base(ap), port_irqs); mv_pmp_select(ap, qc->dev->link->pmp); return ata_sff_qc_issue(qc); @@ -2997,6 +2999,7 @@ static int mv_hardreset(struct ata_link *link, unsigned int *class, extra = HZ; /* only extend it once, max */ } } while (sstatus != 0x0 && sstatus != 0x113 && sstatus != 0x123); + mv_edma_cfg(ap, 0, 0); return rc; } -- GitLab From 84bcbeebcfd283c3f4804287ed4610c3a18e1590 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Fri, 30 Jan 2009 21:40:48 -0500 Subject: [PATCH 4459/4982] sata_mv: remove leftovers Remove redundant code left over from the earlier patch 04/07. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 8f356e4417d..1f14b1b5234 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1820,8 +1820,6 @@ static struct ata_queued_cmd *mv_get_active_qc(struct ata_port *ap) else if (!(qc->flags & ATA_QCFLAG_ACTIVE)) qc = NULL; } - if (qc && (qc->tf.flags & ATA_TFLAG_POLLING)) - qc = NULL; return qc; } -- GitLab From 96b34ce7cafa0888580698d199b9fac6ad9f9a2e Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Tue, 27 Jan 2009 14:35:50 +0100 Subject: [PATCH 4460/4982] pata-rb532-cf: replace rb532_pata_finish_io() Since the delay used internally is just the same as ata_sff_pause() uses, rb532_pata_finish_io() does exactly the same as ata_sff_pause() and thus can be replaced by the later one. Signed-off-by: Phil Sutter Signed-off-by: Jeff Garzik --- drivers/ata/pata_rb532_cf.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c index ebfcda26d63..6fe660b27dc 100644 --- a/drivers/ata/pata_rb532_cf.c +++ b/drivers/ata/pata_rb532_cf.c @@ -54,22 +54,11 @@ struct rb532_cf_info { /* ------------------------------------------------------------------------ */ -static inline void rb532_pata_finish_io(struct ata_port *ap) -{ - struct ata_host *ah = ap->host; - struct rb532_cf_info *info = ah->private_data; - - /* FIXME: Keep previous delay. If this is merely a fence then - ata_sff_sync might be sufficient. */ - ata_sff_dma_pause(ap); - ndelay(RB500_CF_IO_DELAY); -} - static void rb532_pata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf) { writeb(tf->command, ap->ioaddr.command_addr); - rb532_pata_finish_io(ap); + ata_sff_pause(ap); } static unsigned int rb532_pata_data_xfer(struct ata_device *adev, unsigned char *buf, @@ -87,7 +76,7 @@ static unsigned int rb532_pata_data_xfer(struct ata_device *adev, unsigned char *buf = readb(ioaddr); } - rb532_pata_finish_io(adev->link->ap); + ata_sff_pause(ap); return retlen; } -- GitLab From bff9ad3c4c8fff340854d3912196ed470f94602c Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Tue, 27 Jan 2009 14:35:51 +0100 Subject: [PATCH 4461/4982] pata-rb532-cf: use ata_sff_exec_command() The only difference between rb532_pata_exec_command() and ata_sff_exec_command() is added debugging output, so it can be dropped and the standard op used instead. Signed-off-by: Phil Sutter Signed-off-by: Jeff Garzik --- drivers/ata/pata_rb532_cf.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c index 6fe660b27dc..9d61ce51e4e 100644 --- a/drivers/ata/pata_rb532_cf.c +++ b/drivers/ata/pata_rb532_cf.c @@ -54,13 +54,6 @@ struct rb532_cf_info { /* ------------------------------------------------------------------------ */ -static void rb532_pata_exec_command(struct ata_port *ap, - const struct ata_taskfile *tf) -{ - writeb(tf->command, ap->ioaddr.command_addr); - ata_sff_pause(ap); -} - static unsigned int rb532_pata_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data) { @@ -112,7 +105,6 @@ static irqreturn_t rb532_pata_irq_handler(int irq, void *dev_instance) static struct ata_port_operations rb532_pata_port_ops = { .inherits = &ata_sff_port_ops, - .sff_exec_command = rb532_pata_exec_command, .sff_data_xfer = rb532_pata_data_xfer, .freeze = rb532_pata_freeze, .thaw = rb532_pata_thaw, -- GitLab From 180bd147f18316d92bd5f59aebc9932cabc03edd Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Tue, 27 Jan 2009 14:35:52 +0100 Subject: [PATCH 4462/4982] pata-rb532-cf: use ata_sff_data_xfer32() The biggest difference between rb532_pata_data_xfer() and ata_sff_data_xfer32() is the call to ata_sff_pause() at the end of rb532_pata_data_xfer() which I suppose to be unnecessary since it works without. I've also tested using ata_sff_data_xfer() as replacement, but since we know that the driver supports 32bit IO, using the optimised version should be safe. Signed-off-by: Phil Sutter Signed-off-by: Jeff Garzik --- drivers/ata/pata_rb532_cf.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c index 9d61ce51e4e..9fb91e4dd88 100644 --- a/drivers/ata/pata_rb532_cf.c +++ b/drivers/ata/pata_rb532_cf.c @@ -54,25 +54,6 @@ struct rb532_cf_info { /* ------------------------------------------------------------------------ */ -static unsigned int rb532_pata_data_xfer(struct ata_device *adev, unsigned char *buf, - unsigned int buflen, int write_data) -{ - struct ata_port *ap = adev->link->ap; - void __iomem *ioaddr = ap->ioaddr.data_addr; - int retlen = buflen; - - if (write_data) { - for (; buflen > 0; buflen--, buf++) - writeb(*buf, ioaddr); - } else { - for (; buflen > 0; buflen--, buf++) - *buf = readb(ioaddr); - } - - ata_sff_pause(ap); - return retlen; -} - static void rb532_pata_freeze(struct ata_port *ap) { struct rb532_cf_info *info = ap->host->private_data; @@ -105,7 +86,7 @@ static irqreturn_t rb532_pata_irq_handler(int irq, void *dev_instance) static struct ata_port_operations rb532_pata_port_ops = { .inherits = &ata_sff_port_ops, - .sff_data_xfer = rb532_pata_data_xfer, + .sff_data_xfer = ata_sff_data_xfer32, .freeze = rb532_pata_freeze, .thaw = rb532_pata_thaw, }; -- GitLab From 6be976e79db3ba691b657476a8bf4a635e5586f9 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Tue, 27 Jan 2009 14:35:53 +0100 Subject: [PATCH 4463/4982] pata-rb532-cf: drop custom freeze and thaw I'm not quite sure what freezing and thawing is used for. Tests showed that the port is being frozen at initialisation state and thawed right afterwards, then the functions were not called anymore. Dropping the complete custom code for handling the frozen state seems to work at least for a standard use case including mounting a partition, copying some files in it (in parallel) and finally removing them and unmounting the partition. Signed-off-by: Phil Sutter Signed-off-by: Jeff Garzik --- drivers/ata/pata_rb532_cf.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c index 9fb91e4dd88..fbfee1bd85f 100644 --- a/drivers/ata/pata_rb532_cf.c +++ b/drivers/ata/pata_rb532_cf.c @@ -48,26 +48,11 @@ struct rb532_cf_info { void __iomem *iobase; unsigned int gpio_line; - int frozen; unsigned int irq; }; /* ------------------------------------------------------------------------ */ -static void rb532_pata_freeze(struct ata_port *ap) -{ - struct rb532_cf_info *info = ap->host->private_data; - - info->frozen = 1; -} - -static void rb532_pata_thaw(struct ata_port *ap) -{ - struct rb532_cf_info *info = ap->host->private_data; - - info->frozen = 0; -} - static irqreturn_t rb532_pata_irq_handler(int irq, void *dev_instance) { struct ata_host *ah = dev_instance; @@ -75,8 +60,7 @@ static irqreturn_t rb532_pata_irq_handler(int irq, void *dev_instance) if (gpio_get_value(info->gpio_line)) { set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW); - if (!info->frozen) - ata_sff_interrupt(info->irq, dev_instance); + ata_sff_interrupt(info->irq, dev_instance); } else { set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH); } @@ -87,8 +71,6 @@ static irqreturn_t rb532_pata_irq_handler(int irq, void *dev_instance) static struct ata_port_operations rb532_pata_port_ops = { .inherits = &ata_sff_port_ops, .sff_data_xfer = ata_sff_data_xfer32, - .freeze = rb532_pata_freeze, - .thaw = rb532_pata_thaw, }; /* ------------------------------------------------------------------------ */ -- GitLab From a5bfc4714b3f01365aef89a92673f2ceb1ccf246 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 23 Jan 2009 11:31:39 +0900 Subject: [PATCH 4464/4982] ahci: drop intx manipulation on msi enable There's no need to turn off intx explicitly on msi enable. This is automatically handled by pci. Drop it. This might be needed on machines if the BIOS turns intx off during boot. However, there's no evidence of such behavior for ahci and the only such case seems to be ICH5 PATA according to ata_piix. Also, given the way ahci operates, it's highly unlikely BIOS ever disables IRQ for the controller. However, as this change has slight possibility of introducing failure, please schedule it for #upstream. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 66e012cd327..98d7a9fbb7e 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -2647,8 +2647,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; - if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev)) - pci_intx(pdev, 1); + if (!(hpriv->flags & AHCI_HFLAG_NO_MSI)) + pci_enable_msi(pdev); /* save initial config */ ahci_save_initial_config(pdev, hpriv); -- GitLab From 08da175937a35d34a83eaefbb3458472eb1a89d4 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Wed, 25 Feb 2009 15:13:03 -0500 Subject: [PATCH 4465/4982] [libata] sata_mv: cache frequently-accessed registers Maintain a local (mv_port_priv) cache of frequently accessed registers, to avoid having to re-read them (very slow) on every transistion between EDMA and non-EDMA modes. This speeds up things like flushing the drive write cache, and anything using basic DMA transfers. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 91 +++++++++++++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 21 deletions(-) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 1f14b1b5234..146b8e67c44 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -438,6 +438,17 @@ struct mv_sg { __le32 reserved; }; +/* + * We keep a local cache of a few frequently accessed port + * registers here, to avoid having to read them (very slow) + * when switching between EDMA and non-EDMA modes. + */ +struct mv_cached_regs { + u32 fiscfg; + u32 ltmode; + u32 haltcond; +}; + struct mv_port_priv { struct mv_crqb *crqb; dma_addr_t crqb_dma; @@ -450,6 +461,7 @@ struct mv_port_priv { unsigned int resp_idx; u32 pp_flags; + struct mv_cached_regs cached; unsigned int delayed_eh_pmp_map; }; @@ -812,6 +824,43 @@ static inline int mv_get_hc_count(unsigned long port_flags) return ((port_flags & MV_FLAG_DUAL_HC) ? 2 : 1); } +/** + * mv_save_cached_regs - (re-)initialize cached port registers + * @ap: the port whose registers we are caching + * + * Initialize the local cache of port registers, + * so that reading them over and over again can + * be avoided on the hotter paths of this driver. + * This saves a few microseconds each time we switch + * to/from EDMA mode to perform (eg.) a drive cache flush. + */ +static void mv_save_cached_regs(struct ata_port *ap) +{ + void __iomem *port_mmio = mv_ap_base(ap); + struct mv_port_priv *pp = ap->private_data; + + pp->cached.fiscfg = readl(port_mmio + FISCFG_OFS); + pp->cached.ltmode = readl(port_mmio + LTMODE_OFS); + pp->cached.haltcond = readl(port_mmio + EDMA_HALTCOND_OFS); +} + +/** + * mv_write_cached_reg - write to a cached port register + * @addr: hardware address of the register + * @old: pointer to cached value of the register + * @new: new value for the register + * + * Write a new value to a cached register, + * but only if the value is different from before. + */ +static inline void mv_write_cached_reg(void __iomem *addr, u32 *old, u32 new) +{ + if (new != *old) { + *old = new; + writel(new, addr); + } +} + static void mv_set_edma_ptrs(void __iomem *port_mmio, struct mv_host_priv *hpriv, struct mv_port_priv *pp) @@ -1159,35 +1208,33 @@ static int mv_qc_defer(struct ata_queued_cmd *qc) return ATA_DEFER_PORT; } -static void mv_config_fbs(void __iomem *port_mmio, int want_ncq, int want_fbs) +static void mv_config_fbs(struct ata_port *ap, int want_ncq, int want_fbs) { - u32 new_fiscfg, old_fiscfg; - u32 new_ltmode, old_ltmode; - u32 new_haltcond, old_haltcond; + struct mv_port_priv *pp = ap->private_data; + void __iomem *port_mmio; - old_fiscfg = readl(port_mmio + FISCFG_OFS); - old_ltmode = readl(port_mmio + LTMODE_OFS); - old_haltcond = readl(port_mmio + EDMA_HALTCOND_OFS); + u32 fiscfg, *old_fiscfg = &pp->cached.fiscfg; + u32 ltmode, *old_ltmode = &pp->cached.ltmode; + u32 haltcond, *old_haltcond = &pp->cached.haltcond; - new_fiscfg = old_fiscfg & ~(FISCFG_SINGLE_SYNC | FISCFG_WAIT_DEV_ERR); - new_ltmode = old_ltmode & ~LTMODE_BIT8; - new_haltcond = old_haltcond | EDMA_ERR_DEV; + ltmode = *old_ltmode & ~LTMODE_BIT8; + haltcond = *old_haltcond | EDMA_ERR_DEV; if (want_fbs) { - new_fiscfg = old_fiscfg | FISCFG_SINGLE_SYNC; - new_ltmode = old_ltmode | LTMODE_BIT8; + fiscfg = *old_fiscfg | FISCFG_SINGLE_SYNC; + ltmode = *old_ltmode | LTMODE_BIT8; if (want_ncq) - new_haltcond &= ~EDMA_ERR_DEV; + haltcond &= ~EDMA_ERR_DEV; else - new_fiscfg |= FISCFG_WAIT_DEV_ERR; + fiscfg |= FISCFG_WAIT_DEV_ERR; + } else { + fiscfg = *old_fiscfg & ~(FISCFG_SINGLE_SYNC | FISCFG_WAIT_DEV_ERR); } - if (new_fiscfg != old_fiscfg) - writelfl(new_fiscfg, port_mmio + FISCFG_OFS); - if (new_ltmode != old_ltmode) - writelfl(new_ltmode, port_mmio + LTMODE_OFS); - if (new_haltcond != old_haltcond) - writelfl(new_haltcond, port_mmio + EDMA_HALTCOND_OFS); + port_mmio = mv_ap_base(ap); + mv_write_cached_reg(port_mmio + FISCFG_OFS, old_fiscfg, fiscfg); + mv_write_cached_reg(port_mmio + LTMODE_OFS, old_ltmode, ltmode); + mv_write_cached_reg(port_mmio + EDMA_HALTCOND_OFS, old_haltcond, haltcond); } static void mv_60x1_errata_sata25(struct ata_port *ap, int want_ncq) @@ -1235,7 +1282,7 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma) */ want_fbs &= want_ncq; - mv_config_fbs(port_mmio, want_ncq, want_fbs); + mv_config_fbs(ap, want_ncq, want_fbs); if (want_fbs) { pp->pp_flags |= MV_PP_FLAG_FBS_EN; @@ -1339,6 +1386,7 @@ static int mv_port_start(struct ata_port *ap) pp->sg_tbl_dma[tag] = pp->sg_tbl_dma[0]; } } + mv_save_cached_regs(ap); mv_edma_cfg(ap, 0, 0); return 0; @@ -2997,6 +3045,7 @@ static int mv_hardreset(struct ata_link *link, unsigned int *class, extra = HZ; /* only extend it once, max */ } } while (sstatus != 0x0 && sstatus != 0x113 && sstatus != 0x123); + mv_save_cached_regs(ap); mv_edma_cfg(ap, 0, 0); return rc; -- GitLab From c01e8a23128c746f23088db836bd4c820f3eb0b4 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Wed, 25 Feb 2009 15:14:48 -0500 Subject: [PATCH 4466/4982] [libata] sata_mv: Enable use of (basic) DMA for ATAPI on GEN_IIE chips This also gets rid of any need for mv_mode_filter(). Using basic DMA on GEN_IIE requires setting an undocumented bit in an undocumented register. For safety, we clear that bit again when switching back to EDMA mode. To avoid a performance penalty when switching modes, we cache the register in port_priv, as already done for other regs. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 52 +++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 146b8e67c44..3bfe721ba76 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -345,7 +345,7 @@ enum { EDMA_ARB_CFG_OFS = 0x38, EDMA_HALTCOND_OFS = 0x60, /* GenIIe halt conditions */ - + EDMA_UNKNOWN_RSVD_OFS = 0x6C, /* GenIIe unknown/reserved */ BMDMA_CMD_OFS = 0x224, /* bmdma command register */ BMDMA_STATUS_OFS = 0x228, /* bmdma status register */ @@ -447,6 +447,7 @@ struct mv_cached_regs { u32 fiscfg; u32 ltmode; u32 haltcond; + u32 unknown_rsvd; }; struct mv_port_priv { @@ -563,8 +564,6 @@ static void mv_pmp_error_handler(struct ata_port *ap); static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp); -static unsigned long mv_mode_filter(struct ata_device *dev, - unsigned long xfer_mask); static void mv_sff_irq_clear(struct ata_port *ap); static int mv_check_atapi_dma(struct ata_queued_cmd *qc); static void mv_bmdma_setup(struct ata_queued_cmd *qc); @@ -626,7 +625,6 @@ static struct ata_port_operations mv6_ops = { .bmdma_start = mv_bmdma_start, .bmdma_stop = mv_bmdma_stop, .bmdma_status = mv_bmdma_status, - .mode_filter = mv_mode_filter, }; static struct ata_port_operations mv_iie_ops = { @@ -842,6 +840,7 @@ static void mv_save_cached_regs(struct ata_port *ap) pp->cached.fiscfg = readl(port_mmio + FISCFG_OFS); pp->cached.ltmode = readl(port_mmio + LTMODE_OFS); pp->cached.haltcond = readl(port_mmio + EDMA_HALTCOND_OFS); + pp->cached.unknown_rsvd = readl(port_mmio + EDMA_UNKNOWN_RSVD_OFS); } /** @@ -1252,6 +1251,30 @@ static void mv_60x1_errata_sata25(struct ata_port *ap, int want_ncq) writel(new, hpriv->base + MV_GPIO_PORT_CTL_OFS); } +/** + * mv_bmdma_enable - set a magic bit on GEN_IIE to allow bmdma + * @ap: Port being initialized + * + * There are two DMA modes on these chips: basic DMA, and EDMA. + * + * Bit-0 of the "EDMA RESERVED" register enables/disables use + * of basic DMA on the GEN_IIE versions of the chips. + * + * This bit survives EDMA resets, and must be set for basic DMA + * to function, and should be cleared when EDMA is active. + */ +static void mv_bmdma_enable_iie(struct ata_port *ap, int enable_bmdma) +{ + struct mv_port_priv *pp = ap->private_data; + u32 new, *old = &pp->cached.unknown_rsvd; + + if (enable_bmdma) + new = *old | 1; + else + new = *old & ~1; + mv_write_cached_reg(mv_ap_base(ap) + EDMA_UNKNOWN_RSVD_OFS, old, new); +} + static void mv_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma) { u32 cfg; @@ -1297,6 +1320,7 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma) } if (hpriv->hp_flags & MV_HP_CUT_THROUGH) cfg |= (1 << 17); /* enab cut-thru (dis stor&forwrd) */ + mv_bmdma_enable_iie(ap, !want_edma); } if (want_ncq) { @@ -1464,26 +1488,6 @@ static void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last) *cmdw = cpu_to_le16(tmp); } -/** - * mv_mode_filter - Allow ATAPI DMA only on GenII chips. - * @dev: device whose xfer modes are being configured. - * - * Only the GenII hardware can use DMA with ATAPI drives. - */ -static unsigned long mv_mode_filter(struct ata_device *adev, - unsigned long xfer_mask) -{ - if (adev->class == ATA_DEV_ATAPI) { - struct mv_host_priv *hpriv = adev->link->ap->host->private_data; - if (!IS_GEN_II(hpriv)) { - xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); - ata_dev_printk(adev, KERN_INFO, - "ATAPI DMA not supported on this chipset\n"); - } - } - return xfer_mask; -} - /** * mv_sff_irq_clear - Clear hardware interrupt after DMA. * @ap: Port associated with this ATA transaction. -- GitLab From 42ed893d8011264f9945c2f54055b47c298ac53e Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Wed, 25 Feb 2009 15:15:39 -0500 Subject: [PATCH 4467/4982] [libata] sata_mv: Tighten up interrupt masking in mv_qc_issue() so that it doesn't miss any protocols. Handle future cases where a qc is specially marked for polled issue or where a particular chip version prefers interrupts over polling for PIO. This mimics the polling decision logic from ata_sff_qc_issue(). Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 3bfe721ba76..b74af945a2f 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1809,7 +1809,7 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) void __iomem *port_mmio = mv_ap_base(ap); struct mv_port_priv *pp = ap->private_data; u32 in_index; - unsigned int port_irqs = DONE_IRQ | ERR_IRQ; + unsigned int port_irqs; switch (qc->tf.protocol) { case ATA_PROT_DMA: @@ -1842,20 +1842,28 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) "this may fail due to h/w errata\n"); } /* drop through */ + case ATA_PROT_NODATA: case ATAPI_PROT_PIO: - port_irqs = ERR_IRQ; /* leave DONE_IRQ masked for PIO */ - /* drop through */ - default: - /* - * We're about to send a non-EDMA capable command to the - * port. Turn off EDMA so there won't be problems accessing - * shadow block, etc registers. - */ - mv_stop_edma(ap); - mv_clear_and_enable_port_irqs(ap, mv_ap_base(ap), port_irqs); - mv_pmp_select(ap, qc->dev->link->pmp); - return ata_sff_qc_issue(qc); + case ATAPI_PROT_NODATA: + if (ap->flags & ATA_FLAG_PIO_POLLING) + qc->tf.flags |= ATA_TFLAG_POLLING; + break; } + + if (qc->tf.flags & ATA_TFLAG_POLLING) + port_irqs = ERR_IRQ; /* mask device interrupt when polling */ + else + port_irqs = ERR_IRQ | DONE_IRQ; /* unmask all interrupts */ + + /* + * We're about to send a non-EDMA capable command to the + * port. Turn off EDMA so there won't be problems accessing + * shadow block, etc registers. + */ + mv_stop_edma(ap); + mv_clear_and_enable_port_irqs(ap, mv_ap_base(ap), port_irqs); + mv_pmp_select(ap, qc->dev->link->pmp); + return ata_sff_qc_issue(qc); } static struct ata_queued_cmd *mv_get_active_qc(struct ata_port *ap) -- GitLab From d16ab3f633b75aac1cf42b00355cd9aa65033dcc Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Wed, 25 Feb 2009 15:17:43 -0500 Subject: [PATCH 4468/4982] [libata] sata_mv: Add a new mv_sff_check_status() function to sata_mv. This is necessary for use with the upcoming "mv_qc_issue_fis()" patch, but is being added separately here for easier code review. When using command issue via the "mv_qc_issue_fis()" mechanism, the initial ATA_BUSY bit does not show in the ATA status (shadow) register. This can confuse libata! So here we add a hook to fake ATA_BUSY for that situation, until the first time a BUSY, DRQ, or ERR bit is seen. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index b74af945a2f..542e244f37a 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -370,6 +370,7 @@ enum { MV_PP_FLAG_NCQ_EN = (1 << 1), /* is EDMA set up for NCQ? */ MV_PP_FLAG_FBS_EN = (1 << 2), /* is EDMA set up for FBS? */ MV_PP_FLAG_DELAYED_EH = (1 << 3), /* delayed dev err handling */ + MV_PP_FLAG_FAKE_ATA_BUSY = (1 << 4), /* ignore initial ATA_DRDY */ }; #define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I) @@ -570,6 +571,7 @@ static void mv_bmdma_setup(struct ata_queued_cmd *qc); static void mv_bmdma_start(struct ata_queued_cmd *qc); static void mv_bmdma_stop(struct ata_queued_cmd *qc); static u8 mv_bmdma_status(struct ata_port *ap); +static u8 mv_sff_check_status(struct ata_port *ap); /* .sg_tablesize is (MV_MAX_SG_CT / 2) in the structures below * because we have to allow room for worst case splitting of @@ -619,6 +621,7 @@ static struct ata_port_operations mv6_ops = { .softreset = mv_softreset, .error_handler = mv_pmp_error_handler, + .sff_check_status = mv_sff_check_status, .sff_irq_clear = mv_sff_irq_clear, .check_atapi_dma = mv_check_atapi_dma, .bmdma_setup = mv_bmdma_setup, @@ -1284,7 +1287,8 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma) /* set up non-NCQ EDMA configuration */ cfg = EDMA_CFG_Q_DEPTH; /* always 0x1f for *all* chips */ - pp->pp_flags &= ~(MV_PP_FLAG_FBS_EN | MV_PP_FLAG_NCQ_EN); + pp->pp_flags &= + ~(MV_PP_FLAG_FBS_EN | MV_PP_FLAG_NCQ_EN | MV_PP_FLAG_FAKE_ATA_BUSY); if (IS_GEN_I(hpriv)) cfg |= (1 << 8); /* enab config burst size mask */ @@ -1790,6 +1794,33 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc) mv_fill_sg(qc); } +/** + * mv_sff_check_status - fetch device status, if valid + * @ap: ATA port to fetch status from + * + * When using command issue via mv_qc_issue_fis(), + * the initial ATA_BUSY state does not show up in the + * ATA status (shadow) register. This can confuse libata! + * + * So we have a hook here to fake ATA_BUSY for that situation, + * until the first time a BUSY, DRQ, or ERR bit is seen. + * + * The rest of the time, it simply returns the ATA status register. + */ +static u8 mv_sff_check_status(struct ata_port *ap) +{ + u8 stat = ioread8(ap->ioaddr.status_addr); + struct mv_port_priv *pp = ap->private_data; + + if (pp->pp_flags & MV_PP_FLAG_FAKE_ATA_BUSY) { + if (stat & (ATA_BUSY | ATA_DRQ | ATA_ERR)) + pp->pp_flags &= ~MV_PP_FLAG_FAKE_ATA_BUSY; + else + stat = ATA_BUSY; + } + return stat; +} + /** * mv_qc_issue - Initiate a command to the host * @qc: queued command to start @@ -1811,6 +1842,8 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) u32 in_index; unsigned int port_irqs; + pp->pp_flags &= ~MV_PP_FLAG_FAKE_ATA_BUSY; /* paranoia */ + switch (qc->tf.protocol) { case ATA_PROT_DMA: case ATA_PROT_NCQ: @@ -3038,6 +3071,8 @@ static int mv_hardreset(struct ata_link *link, unsigned int *class, mv_reset_channel(hpriv, mmio, ap->port_no); pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; + pp->pp_flags &= + ~(MV_PP_FLAG_FBS_EN | MV_PP_FLAG_NCQ_EN | MV_PP_FLAG_FAKE_ATA_BUSY); /* Workaround for errata FEr SATA#10 (part 2) */ do { -- GitLab From 1a660164c291f41b2aa853a7269b310933574ef9 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Wed, 25 Feb 2009 15:18:32 -0500 Subject: [PATCH 4469/4982] [libata] Export ata_pio_queue_task() so that it can be used from sata_mv. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 1 + drivers/ata/libata.h | 2 -- include/linux/libata.h | 3 +++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 060bcd601f5..d4a7b8a96ec 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -6709,6 +6709,7 @@ EXPORT_SYMBOL_GPL(ata_id_c_string); EXPORT_SYMBOL_GPL(ata_do_dev_read_id); EXPORT_SYMBOL_GPL(ata_scsi_simulate); +EXPORT_SYMBOL_GPL(ata_pio_queue_task); EXPORT_SYMBOL_GPL(ata_pio_need_iordy); EXPORT_SYMBOL_GPL(ata_timing_find_mode); EXPORT_SYMBOL_GPL(ata_timing_compute); diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index cea8014cd87..89a1e0018e7 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -79,8 +79,6 @@ extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, u64 block, u32 n_block, unsigned int tf_flags, unsigned int tag); extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev); -extern void ata_pio_queue_task(struct ata_port *ap, void *data, - unsigned long delay); extern void ata_port_flush_task(struct ata_port *ap); extern unsigned ata_exec_internal(struct ata_device *dev, struct ata_taskfile *tf, const u8 *cdb, diff --git a/include/linux/libata.h b/include/linux/libata.h index dc18b87ed72..19af7d22a7f 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -1008,6 +1008,9 @@ extern int ata_cable_sata(struct ata_port *ap); extern int ata_cable_ignore(struct ata_port *ap); extern int ata_cable_unknown(struct ata_port *ap); +extern void ata_pio_queue_task(struct ata_port *ap, void *data, + unsigned long delay); + /* Timing helpers */ extern unsigned int ata_pio_need_iordy(const struct ata_device *); extern const struct ata_timing *ata_timing_find_mode(u8 xfer_mode); -- GitLab From 70f8b79cf3a2eb892a01271fdfbb1903c0c982a8 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Wed, 25 Feb 2009 15:19:20 -0500 Subject: [PATCH 4470/4982] [libata] sata_mv: Implement direct FIS transmission via mv_qc_issue_fis(). This is initially needed to work around NCQ errata, whereby the READ_LOG_EXT command sometimes fails when issued in the traditional (sff) fashion. Portions of this code will likely be reused for implementation of the target mode feature later on. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 116 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 542e244f37a..8cad3b2fe55 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1821,6 +1821,105 @@ static u8 mv_sff_check_status(struct ata_port *ap) return stat; } +/** + * mv_send_fis - Send a FIS, using the "Vendor-Unique FIS" register + * @fis: fis to be sent + * @nwords: number of 32-bit words in the fis + */ +static unsigned int mv_send_fis(struct ata_port *ap, u32 *fis, int nwords) +{ + void __iomem *port_mmio = mv_ap_base(ap); + u32 ifctl, old_ifctl, ifstat; + int i, timeout = 200, final_word = nwords - 1; + + /* Initiate FIS transmission mode */ + old_ifctl = readl(port_mmio + SATA_IFCTL_OFS); + ifctl = 0x100 | (old_ifctl & 0xf); + writelfl(ifctl, port_mmio + SATA_IFCTL_OFS); + + /* Send all words of the FIS except for the final word */ + for (i = 0; i < final_word; ++i) + writel(fis[i], port_mmio + VENDOR_UNIQUE_FIS_OFS); + + /* Flag end-of-transmission, and then send the final word */ + writelfl(ifctl | 0x200, port_mmio + SATA_IFCTL_OFS); + writelfl(fis[final_word], port_mmio + VENDOR_UNIQUE_FIS_OFS); + + /* + * Wait for FIS transmission to complete. + * This typically takes just a single iteration. + */ + do { + ifstat = readl(port_mmio + SATA_IFSTAT_OFS); + } while (!(ifstat & 0x1000) && --timeout); + + /* Restore original port configuration */ + writelfl(old_ifctl, port_mmio + SATA_IFCTL_OFS); + + /* See if it worked */ + if ((ifstat & 0x3000) != 0x1000) { + ata_port_printk(ap, KERN_WARNING, + "%s transmission error, ifstat=%08x\n", + __func__, ifstat); + return AC_ERR_OTHER; + } + return 0; +} + +/** + * mv_qc_issue_fis - Issue a command directly as a FIS + * @qc: queued command to start + * + * Note that the ATA shadow registers are not updated + * after command issue, so the device will appear "READY" + * if polled, even while it is BUSY processing the command. + * + * So we use a status hook to fake ATA_BUSY until the drive changes state. + * + * Note: we don't get updated shadow regs on *completion* + * of non-data commands. So avoid sending them via this function, + * as they will appear to have completed immediately. + * + * GEN_IIE has special registers that we could get the result tf from, + * but earlier chipsets do not. For now, we ignore those registers. + */ +static unsigned int mv_qc_issue_fis(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct mv_port_priv *pp = ap->private_data; + struct ata_link *link = qc->dev->link; + u32 fis[5]; + int err = 0; + + ata_tf_to_fis(&qc->tf, link->pmp, 1, (void *)fis); + err = mv_send_fis(ap, fis, sizeof(fis) / sizeof(fis[0])); + if (err) + return err; + + switch (qc->tf.protocol) { + case ATAPI_PROT_PIO: + pp->pp_flags |= MV_PP_FLAG_FAKE_ATA_BUSY; + /* fall through */ + case ATAPI_PROT_NODATA: + ap->hsm_task_state = HSM_ST_FIRST; + break; + case ATA_PROT_PIO: + pp->pp_flags |= MV_PP_FLAG_FAKE_ATA_BUSY; + if (qc->tf.flags & ATA_TFLAG_WRITE) + ap->hsm_task_state = HSM_ST_FIRST; + else + ap->hsm_task_state = HSM_ST; + break; + default: + ap->hsm_task_state = HSM_ST_LAST; + break; + } + + if (qc->tf.flags & ATA_TFLAG_POLLING) + ata_pio_queue_task(ap, qc, 0); + return 0; +} + /** * mv_qc_issue - Initiate a command to the host * @qc: queued command to start @@ -1896,6 +1995,23 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) mv_stop_edma(ap); mv_clear_and_enable_port_irqs(ap, mv_ap_base(ap), port_irqs); mv_pmp_select(ap, qc->dev->link->pmp); + + if (qc->tf.command == ATA_CMD_READ_LOG_EXT) { + struct mv_host_priv *hpriv = ap->host->private_data; + /* + * Workaround for 88SX60x1 FEr SATA#25 (part 2). + * + * After any NCQ error, the READ_LOG_EXT command + * from libata-eh *must* use mv_qc_issue_fis(). + * Otherwise it might fail, due to chip errata. + * + * Rather than special-case it, we'll just *always* + * use this method here for READ_LOG_EXT, making for + * easier testing. + */ + if (IS_GEN_II(hpriv)) + return mv_qc_issue_fis(qc); + } return ata_sff_qc_issue(qc); } -- GitLab From d2f9c0614e664708978c53eca4a5963e92830e88 Mon Sep 17 00:00:00 2001 From: Maciej Rutecki Date: Fri, 20 Mar 2009 00:06:46 +0100 Subject: [PATCH 4471/4982] ahci: Blacklist HP Compaq 6720s that spins off disks during ACPI power off Blacklist HP Compaq 6720s so that it doesn't play a "spin down, spin up, spin down" ping-pong with the hard disk during system power off. Signed-off-by: Maciej Rutecki Signed-off-by: Rafael J. Wysocki Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 98d7a9fbb7e..699789bc9ea 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -2565,6 +2565,15 @@ static bool ahci_broken_system_poweroff(struct pci_dev *pdev) /* PCI slot number of the controller */ .driver_data = (void *)0x1FUL, }, + { + .ident = "HP Compaq 6720s", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"), + }, + /* PCI slot number of the controller */ + .driver_data = (void *)0x1FUL, + }, { } /* terminate list */ }; -- GitLab From 22ddbd1e036ce035c1cccb2496aefafac79aba2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Inge=20Bols=C3=B8?= Date: Sat, 14 Mar 2009 21:37:48 +0100 Subject: [PATCH 4472/4982] include/linux/ata.h: add some more transfer masks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Erik Inge Bolsø Signed-off-by: Jeff Garzik --- include/linux/ata.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/linux/ata.h b/include/linux/ata.h index 9a061accd8b..3901b0022cd 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -108,6 +108,8 @@ enum { ATA_PIO5 = ATA_PIO4 | (1 << 5), ATA_PIO6 = ATA_PIO5 | (1 << 6), + ATA_PIO4_ONLY = (1 << 4), + ATA_SWDMA0 = (1 << 0), ATA_SWDMA1 = ATA_SWDMA0 | (1 << 1), ATA_SWDMA2 = ATA_SWDMA1 | (1 << 2), @@ -117,6 +119,8 @@ enum { ATA_MWDMA0 = (1 << 0), ATA_MWDMA1 = ATA_MWDMA0 | (1 << 1), ATA_MWDMA2 = ATA_MWDMA1 | (1 << 2), + ATA_MWDMA3 = ATA_MWDMA2 | (1 << 3), + ATA_MWDMA4 = ATA_MWDMA3 | (1 << 4), ATA_MWDMA12_ONLY = (1 << 1) | (1 << 2), ATA_MWDMA2_ONLY = (1 << 2), @@ -131,6 +135,8 @@ enum { ATA_UDMA7 = ATA_UDMA6 | (1 << 7), /* ATA_UDMA7 is just for completeness... doesn't exist (yet?). */ + ATA_UDMA24_ONLY = (1 << 2) | (1 << 4), + ATA_UDMA_MASK_40C = ATA_UDMA2, /* udma0-2 */ /* DMA-related */ -- GitLab From 14bdef982caeda19afe34010482867c18217c641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Inge=20Bols=C3=B8?= Date: Sat, 14 Mar 2009 21:38:24 +0100 Subject: [PATCH 4473/4982] [libata] convert drivers to use ata.h mode mask defines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No functional changes in this patch. Signed-off-by: Erik Inge Bolsø Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 16 ++++---- drivers/ata/ata_generic.c | 4 +- drivers/ata/ata_piix.c | 60 ++++++++++++++-------------- drivers/ata/pata_acpi.c | 6 +-- drivers/ata/pata_ali.c | 28 ++++++------- drivers/ata/pata_amd.c | 70 ++++++++++++++++----------------- drivers/ata/pata_artop.c | 16 ++++---- drivers/ata/pata_at32.c | 4 +- drivers/ata/pata_atiixp.c | 6 +-- drivers/ata/pata_bf54x.c | 2 +- drivers/ata/pata_cmd640.c | 2 +- drivers/ata/pata_cmd64x.c | 24 +++++------ drivers/ata/pata_cs5520.c | 2 +- drivers/ata/pata_cs5530.c | 8 ++-- drivers/ata/pata_cs5535.c | 4 +- drivers/ata/pata_cs5536.c | 4 +- drivers/ata/pata_cypress.c | 4 +- drivers/ata/pata_efar.c | 6 +-- drivers/ata/pata_hpt366.c | 4 +- drivers/ata/pata_hpt37x.c | 28 ++++++------- drivers/ata/pata_hpt3x2n.c | 4 +- drivers/ata/pata_hpt3x3.c | 6 +-- drivers/ata/pata_icside.c | 4 +- drivers/ata/pata_isapnp.c | 2 +- drivers/ata/pata_it8213.c | 4 +- drivers/ata/pata_it821x.c | 16 ++++---- drivers/ata/pata_ixp4xx_cf.c | 2 +- drivers/ata/pata_jmicron.c | 4 +- drivers/ata/pata_legacy.c | 2 +- drivers/ata/pata_marvell.c | 8 ++-- drivers/ata/pata_mpc52xx.c | 4 +- drivers/ata/pata_mpiix.c | 2 +- drivers/ata/pata_netcell.c | 4 +- drivers/ata/pata_ninja32.c | 2 +- drivers/ata/pata_ns87410.c | 2 +- drivers/ata/pata_ns87415.c | 8 ++-- drivers/ata/pata_octeon_cf.c | 4 +- drivers/ata/pata_oldpiix.c | 4 +- drivers/ata/pata_opti.c | 2 +- drivers/ata/pata_optidma.c | 10 ++--- drivers/ata/pata_pcmcia.c | 2 +- drivers/ata/pata_pdc2027x.c | 12 +++--- drivers/ata/pata_pdc202xx_old.c | 12 +++--- drivers/ata/pata_qdi.c | 4 +- drivers/ata/pata_radisys.c | 6 +-- drivers/ata/pata_rb532_cf.c | 2 +- drivers/ata/pata_rz1000.c | 2 +- drivers/ata/pata_sc1200.c | 6 +-- drivers/ata/pata_scc.c | 4 +- drivers/ata/pata_sch.c | 6 +-- drivers/ata/pata_serverworks.c | 20 +++++----- drivers/ata/pata_sil680.c | 8 ++-- drivers/ata/pata_sis.c | 32 +++++++++------ drivers/ata/pata_sl82c105.c | 6 +-- drivers/ata/pata_triflex.c | 4 +- drivers/ata/pata_via.c | 24 +++++------ drivers/ata/pata_winbond.c | 2 +- drivers/ata/pdc_adma.c | 2 +- drivers/ata/sata_fsl.c | 4 +- drivers/ata/sata_inic162x.c | 4 +- drivers/ata/sata_nv.c | 6 +-- drivers/ata/sata_promise.c | 28 ++++++------- drivers/ata/sata_qstor.c | 2 +- drivers/ata/sata_sil.c | 16 ++++---- drivers/ata/sata_sil24.c | 18 ++++----- drivers/ata/sata_sis.c | 4 +- drivers/ata/sata_svw.c | 16 ++++---- drivers/ata/sata_sx4.c | 4 +- drivers/ata/sata_uli.c | 2 +- drivers/ata/sata_via.c | 16 ++++---- drivers/ata/sata_vsc.c | 4 +- 71 files changed, 339 insertions(+), 331 deletions(-) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 699789bc9ea..ec2922ad2dc 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -404,7 +404,7 @@ static const struct ata_port_info ahci_port_info[] = { /* board_ahci */ { .flags = AHCI_FLAG_COMMON, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, @@ -412,7 +412,7 @@ static const struct ata_port_info ahci_port_info[] = { { AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP), .flags = AHCI_FLAG_COMMON, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_vt8251_ops, }, @@ -420,7 +420,7 @@ static const struct ata_port_info ahci_port_info[] = { { AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR), .flags = AHCI_FLAG_COMMON, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, @@ -430,7 +430,7 @@ static const struct ata_port_info ahci_port_info[] = { AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255), .flags = AHCI_FLAG_COMMON, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_sb600_ops, }, @@ -440,7 +440,7 @@ static const struct ata_port_info ahci_port_info[] = { AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP), .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, @@ -448,7 +448,7 @@ static const struct ata_port_info ahci_port_info[] = { { AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL), .flags = AHCI_FLAG_COMMON, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_sb600_ops, }, @@ -456,7 +456,7 @@ static const struct ata_port_info ahci_port_info[] = { { AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ), .flags = AHCI_FLAG_COMMON, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, @@ -464,7 +464,7 @@ static const struct ata_port_info ahci_port_info[] = { { AHCI_HFLAGS (AHCI_HFLAG_NO_PMP), .flags = AHCI_FLAG_COMMON, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c index dc48a6398ab..ecfd22b4f1c 100644 --- a/drivers/ata/ata_generic.c +++ b/drivers/ata/ata_generic.c @@ -118,8 +118,8 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id u16 command; static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &generic_port_ops }; diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index ef8b30d577b..e5cbe80ce17 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -446,34 +446,34 @@ static struct ata_port_info piix_port_info[] = { [piix_pata_mwdma] = /* PIIX3 MWDMA only */ { .flags = PIIX_PATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ .port_ops = &piix_pata_ops, }, [piix_pata_33] = /* PIIX4 at 33MHz */ { .flags = PIIX_PATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ - .udma_mask = ATA_UDMA_MASK_40C, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ + .udma_mask = ATA_UDMA2, .port_ops = &piix_pata_ops, }, [ich_pata_33] = /* ICH0 - ICH at 33Mhz*/ { .flags = PIIX_PATA_FLAGS, - .pio_mask = 0x1f, /* pio 0-4 */ - .mwdma_mask = 0x06, /* Check: maybe 0x07 */ - .udma_mask = ATA_UDMA2, /* UDMA33 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA12_ONLY, /* Check: maybe MWDMA0 is ok */ + .udma_mask = ATA_UDMA2, .port_ops = &ich_pata_ops, }, [ich_pata_66] = /* ICH controllers up to 66MHz */ { .flags = PIIX_PATA_FLAGS, - .pio_mask = 0x1f, /* pio 0-4 */ - .mwdma_mask = 0x06, /* MWDMA0 is broken on chip */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA12_ONLY, /* MWDMA0 is broken on chip */ .udma_mask = ATA_UDMA4, .port_ops = &ich_pata_ops, }, @@ -481,17 +481,17 @@ static struct ata_port_info piix_port_info[] = { [ich_pata_100] = { .flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x06, /* mwdma1-2 */ - .udma_mask = ATA_UDMA5, /* udma0-5 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA12_ONLY, + .udma_mask = ATA_UDMA5, .port_ops = &ich_pata_ops, }, [ich5_sata] = { .flags = PIIX_SATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &piix_sata_ops, }, @@ -499,8 +499,8 @@ static struct ata_port_info piix_port_info[] = { [ich6_sata] = { .flags = PIIX_SATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &piix_sata_ops, }, @@ -508,8 +508,8 @@ static struct ata_port_info piix_port_info[] = { [ich6m_sata] = { .flags = PIIX_SATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &piix_sata_ops, }, @@ -517,8 +517,8 @@ static struct ata_port_info piix_port_info[] = { [ich8_sata] = { .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &piix_sata_ops, }, @@ -526,8 +526,8 @@ static struct ata_port_info piix_port_info[] = { [ich8_2port_sata] = { .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &piix_sata_ops, }, @@ -535,8 +535,8 @@ static struct ata_port_info piix_port_info[] = { [tolapai_sata] = { .flags = PIIX_SATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &piix_sata_ops, }, @@ -544,8 +544,8 @@ static struct ata_port_info piix_port_info[] = { [ich8m_apple_sata] = { .flags = PIIX_SATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &piix_sata_ops, }, @@ -553,9 +553,9 @@ static struct ata_port_info piix_port_info[] = { [piix_pata_vmw] = { .flags = PIIX_PATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ - .udma_mask = ATA_UDMA_MASK_40C, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ + .udma_mask = ATA_UDMA2, .port_ops = &piix_vmw_ops, }, diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c index 8b77a9802df..d8f35fe4442 100644 --- a/drivers/ata/pata_acpi.c +++ b/drivers/ata/pata_acpi.c @@ -246,9 +246,9 @@ static int pacpi_init_one (struct pci_dev *pdev, const struct pci_device_id *id) static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x7f, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, .port_ops = &pacpi_ops, }; diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index eb99dbe7808..751b7ea4816 100644 --- a/drivers/ata/pata_ali.c +++ b/drivers/ata/pata_ali.c @@ -492,53 +492,53 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { static const struct ata_port_info info_early = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, + .pio_mask = ATA_PIO4, .port_ops = &ali_early_port_ops }; /* Revision 0x20 added DMA */ static const struct ata_port_info info_20 = { .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &ali_20_port_ops }; /* Revision 0x20 with support logic added UDMA */ static const struct ata_port_info info_20_udma = { .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x07, /* UDMA33 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA2, .port_ops = &ali_20_port_ops }; /* Revision 0xC2 adds UDMA66 */ static const struct ata_port_info info_c2 = { .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, .port_ops = &ali_c2_port_ops }; /* Revision 0xC3 is UDMA66 for now */ static const struct ata_port_info info_c3 = { .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, .port_ops = &ali_c2_port_ops }; /* Revision 0xC4 is UDMA100 */ static const struct ata_port_info info_c4 = { .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &ali_c4_port_ops }; /* Revision 0xC5 is UDMA133 with LBA48 DMA */ static const struct ata_port_info info_c5 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &ali_c5_port_ops }; diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c index 115b1cd6dcf..33a74f11171 100644 --- a/drivers/ata/pata_amd.c +++ b/drivers/ata/pata_amd.c @@ -455,74 +455,74 @@ static void amd_clear_fifo(struct pci_dev *pdev) static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { static const struct ata_port_info info[10] = { - { /* 0: AMD 7401 */ + { /* 0: AMD 7401 - no swdma */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, /* No SWDMA */ - .udma_mask = 0x07, /* UDMA 33 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA2, .port_ops = &amd33_port_ops }, { /* 1: Early AMD7409 - no swdma */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA4, /* UDMA 66 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA4, .port_ops = &amd66_port_ops }, - { /* 2: AMD 7409, no swdma errata */ + { /* 2: AMD 7409 */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA4, /* UDMA 66 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA4, .port_ops = &amd66_port_ops }, { /* 3: AMD 7411 */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, /* UDMA 100 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &amd100_port_ops }, { /* 4: AMD 7441 */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, /* UDMA 100 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &amd100_port_ops }, - { /* 5: AMD 8111*/ + { /* 5: AMD 8111 - no swdma */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA6, /* UDMA 133, no swdma */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, .port_ops = &amd133_port_ops }, - { /* 6: AMD 8111 UDMA 100 (Serenade) */ + { /* 6: AMD 8111 UDMA 100 (Serenade) - no swdma */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, /* UDMA 100, no swdma */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &amd133_port_ops }, { /* 7: Nvidia Nforce */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, /* UDMA 100 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &nv100_port_ops }, - { /* 8: Nvidia Nforce2 and later */ + { /* 8: Nvidia Nforce2 and later - no swdma */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA6, /* UDMA 133, no swdma */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, .port_ops = &nv133_port_ops }, { /* 9: AMD CS5536 (Geode companion) */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, /* UDMA 100 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &amd100_port_ops } }; diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c index 6b3092c75ff..07c7fae6da1 100644 --- a/drivers/ata/pata_artop.c +++ b/drivers/ata/pata_artop.c @@ -323,29 +323,29 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id) static int printed_version; static const struct ata_port_info info_6210 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA2, .port_ops = &artop6210_ops, }; static const struct ata_port_info info_626x = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, .port_ops = &artop6260_ops, }; static const struct ata_port_info info_628x = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &artop6260_ops, }; static const struct ata_port_info info_628x_fast = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &artop6260_ops, }; diff --git a/drivers/ata/pata_at32.c b/drivers/ata/pata_at32.c index ab61095093b..5c129f99a7e 100644 --- a/drivers/ata/pata_at32.c +++ b/drivers/ata/pata_at32.c @@ -67,7 +67,9 @@ * * Alter PIO_MASK below according to table to set maximal PIO mode. */ -#define PIO_MASK (0x1f) +enum { + PIO_MASK = ATA_PIO4, +}; /* * Struct containing private information about device. diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c index 506adde8ebb..bec0b8ade66 100644 --- a/drivers/ata/pata_atiixp.c +++ b/drivers/ata/pata_atiixp.c @@ -220,9 +220,9 @@ static int atiixp_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x06, /* No MWDMA0 support */ - .udma_mask = 0x3F, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA12_ONLY, + .udma_mask = ATA_UDMA5, .port_ops = &atiixp_port_ops }; static const struct pci_bits atiixp_enable_bits[] = { diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c index 1050fed96b2..c4b47a3e544 100644 --- a/drivers/ata/pata_bf54x.c +++ b/drivers/ata/pata_bf54x.c @@ -1502,7 +1502,7 @@ static struct ata_port_info bfin_port_info[] = { .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, .mwdma_mask = 0, .udma_mask = 0, .port_ops = &bfin_pata_ops, diff --git a/drivers/ata/pata_cmd640.c b/drivers/ata/pata_cmd640.c index 34a394264c3..5acf9fa9b39 100644 --- a/drivers/ata/pata_cmd640.c +++ b/drivers/ata/pata_cmd640.c @@ -211,7 +211,7 @@ static int cmd640_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, + .pio_mask = ATA_PIO4, .port_ops = &cmd640_port_ops }; const struct ata_port_info *ppi[] = { &info, NULL }; diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c index 3167d8fed2f..f98dffedf4b 100644 --- a/drivers/ata/pata_cmd64x.c +++ b/drivers/ata/pata_cmd64x.c @@ -299,40 +299,40 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) static const struct ata_port_info cmd_info[6] = { { /* CMD 643 - no UDMA */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &cmd64x_port_ops }, { /* CMD 646 with broken UDMA */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &cmd64x_port_ops }, { /* CMD 646 with working UDMA */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA2, .port_ops = &cmd64x_port_ops }, { /* CMD 646 rev 1 */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &cmd646r1_port_ops }, { /* CMD 648 */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, .port_ops = &cmd648_port_ops }, { /* CMD 649 */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &cmd648_port_ops } diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c index 1186bcd2781..db6a96984f3 100644 --- a/drivers/ata/pata_cs5520.c +++ b/drivers/ata/pata_cs5520.c @@ -158,7 +158,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi static const unsigned int ctl_port[] = { 0x3F6, 0x376 }; struct ata_port_info pi = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, + .pio_mask = ATA_PIO4, .port_ops = &cs5520_port_ops, }; const struct ata_port_info *ppi[2]; diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c index bba453381f4..c974b05e412 100644 --- a/drivers/ata/pata_cs5530.c +++ b/drivers/ata/pata_cs5530.c @@ -298,15 +298,15 @@ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA2, .port_ops = &cs5530_port_ops }; /* The docking connector doesn't do UDMA, and it seems not MWDMA */ static const struct ata_port_info info_palmax_secondary = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, + .pio_mask = ATA_PIO4, .port_ops = &cs5530_port_ops }; const struct ata_port_info *ppi[] = { &info, NULL }; diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c index 8b236af84c2..d33aa28239a 100644 --- a/drivers/ata/pata_cs5535.c +++ b/drivers/ata/pata_cs5535.c @@ -181,8 +181,8 @@ static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, .port_ops = &cs5535_port_ops }; diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c index afed9297619..6da4cb486c8 100644 --- a/drivers/ata/pata_cs5536.c +++ b/drivers/ata/pata_cs5536.c @@ -241,8 +241,8 @@ static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &cs5536_port_ops, }; diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c index d546425cd38..8fb040bf736 100644 --- a/drivers/ata/pata_cypress.c +++ b/drivers/ata/pata_cypress.c @@ -124,8 +124,8 @@ static int cy82c693_init_one(struct pci_dev *pdev, const struct pci_device_id *i { static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &cy82c693_port_ops }; const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info }; diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c index ac6392ea35b..bd498cc3920 100644 --- a/drivers/ata/pata_efar.c +++ b/drivers/ata/pata_efar.c @@ -251,9 +251,9 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) static int printed_version; static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma1-2 */ - .udma_mask = 0x0f, /* UDMA 66 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, /* mwdma1-2 */ + .udma_mask = ATA_UDMA3, /* UDMA 66 */ .port_ops = &efar_ops, }; const struct ata_port_info *ppi[] = { &info, NULL }; diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c index 65c28e5a6cd..d7f2da127d1 100644 --- a/drivers/ata/pata_hpt366.c +++ b/drivers/ata/pata_hpt366.c @@ -336,8 +336,8 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info_hpt366 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, .port_ops = &hpt366_port_ops }; diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index 42163998de9..81ab57003ab 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c @@ -753,55 +753,55 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) /* HPT370 - UDMA100 */ static const struct ata_port_info info_hpt370 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &hpt370_port_ops }; /* HPT370A - UDMA100 */ static const struct ata_port_info info_hpt370a = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &hpt370a_port_ops }; /* HPT370 - UDMA100 */ static const struct ata_port_info info_hpt370_33 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &hpt370_port_ops }; /* HPT370A - UDMA100 */ static const struct ata_port_info info_hpt370a_33 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &hpt370a_port_ops }; /* HPT371, 372 and friends - UDMA133 */ static const struct ata_port_info info_hpt372 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &hpt372_port_ops }; /* HPT374 - UDMA100, function 1 uses different prereset method */ static const struct ata_port_info info_hpt374_fn0 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &hpt372_port_ops }; static const struct ata_port_info info_hpt374_fn1 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &hpt374_fn1_port_ops }; diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c index d5c9fd7b82b..3d59fe0a408 100644 --- a/drivers/ata/pata_hpt3x2n.c +++ b/drivers/ata/pata_hpt3x2n.c @@ -441,8 +441,8 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) /* HPT372N and friends - UDMA133 */ static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &hpt3x2n_port_ops }; diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c index f19cc645881..7e310253b36 100644 --- a/drivers/ata/pata_hpt3x3.c +++ b/drivers/ata/pata_hpt3x3.c @@ -188,11 +188,11 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id) static int printed_version; static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, + .pio_mask = ATA_PIO4, #if defined(CONFIG_PATA_HPT3X3_DMA) /* Further debug needed */ - .mwdma_mask = 0x07, - .udma_mask = 0x07, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA2, #endif .port_ops = &hpt3x3_port_ops }; diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c index cf9e9848f8b..e7347db5b6c 100644 --- a/drivers/ata/pata_icside.c +++ b/drivers/ata/pata_icside.c @@ -297,7 +297,7 @@ static int icside_dma_init(struct pata_icside_info *info) if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) { state->dma = ec->dma; - info->mwdma_mask = 0x07; /* MW0..2 */ + info->mwdma_mask = ATA_MWDMA2; } return 0; @@ -473,7 +473,7 @@ static int __devinit pata_icside_add_ports(struct pata_icside_info *info) for (i = 0; i < info->nr_ports; i++) { struct ata_port *ap = host->ports[i]; - ap->pio_mask = 0x1f; + ap->pio_mask = ATA_PIO4; ap->mwdma_mask = info->mwdma_mask; ap->flags |= ATA_FLAG_SLAVE_POSS; ap->ops = &pata_icside_port_ops; diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c index 15cdb9148aa..afa8f704271 100644 --- a/drivers/ata/pata_isapnp.c +++ b/drivers/ata/pata_isapnp.c @@ -66,7 +66,7 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev ap = host->ports[0]; ap->ops = &isapnp_port_ops; - ap->pio_mask = 1; + ap->pio_mask = ATA_PIO0; ap->flags |= ATA_FLAG_SLAVE_POSS; ap->ioaddr.cmd_addr = cmd_addr; diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c index c113d7c079c..f156da8076f 100644 --- a/drivers/ata/pata_it8213.c +++ b/drivers/ata/pata_it8213.c @@ -262,8 +262,8 @@ static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *en static int printed_version; static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, /* FIXME: want UDMA 100? */ .port_ops = &it8213_ops, }; diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index b05b86a912c..188bc2fcd22 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c @@ -875,29 +875,29 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) static const struct ata_port_info info_smart = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &it821x_smart_port_ops }; static const struct ata_port_info info_passthru = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &it821x_passthru_port_ops }; static const struct ata_port_info info_rdc = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &it821x_rdc_port_ops }; static const struct ata_port_info info_rdc_11 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, /* No UDMA */ .port_ops = &it821x_rdc_port_ops }; diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c index b173c157ab0..19fdecf319a 100644 --- a/drivers/ata/pata_ixp4xx_cf.c +++ b/drivers/ata/pata_ixp4xx_cf.c @@ -176,7 +176,7 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev) ap = host->ports[0]; ap->ops = &ixp4xx_port_ops; - ap->pio_mask = 0x1f; /* PIO4 */ + ap->pio_mask = ATA_PIO4; ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_NO_ATAPI; ixp4xx_setup_port(ap, data, cs0->start, cs1->start); diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c index 38cf1ab2d28..3a1474ac883 100644 --- a/drivers/ata/pata_jmicron.c +++ b/drivers/ata/pata_jmicron.c @@ -136,8 +136,8 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &jmicron_ops, diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c index e3bc1b43628..3f830f0fe2c 100644 --- a/drivers/ata/pata_legacy.c +++ b/drivers/ata/pata_legacy.c @@ -129,7 +129,7 @@ static int qdi; /* Set to probe QDI controllers */ static int winbond; /* Set to probe Winbond controllers, give I/O port if non standard */ static int autospeed; /* Chip present which snoops speed changes */ -static int pio_mask = 0x1F; /* PIO range for autospeed devices */ +static int pio_mask = ATA_PIO4; /* PIO range for autospeed devices */ static int iordy_mask = 0xFFFFFFFF; /* Use iordy if available */ /** diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c index 76e399bf8c1..2096fb737f8 100644 --- a/drivers/ata/pata_marvell.c +++ b/drivers/ata/pata_marvell.c @@ -126,8 +126,8 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &marvell_ops, @@ -136,8 +136,8 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i /* Slave possible as its magically mapped not real */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &marvell_ops, diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c index 50ae6d13078..68d27bc70d0 100644 --- a/drivers/ata/pata_mpc52xx.c +++ b/drivers/ata/pata_mpc52xx.c @@ -737,10 +737,10 @@ mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match) */ prop = of_get_property(op->node, "mwdma-mode", &proplen); if ((prop) && (proplen >= 4)) - mwdma_mask = 0x7 & ((1 << (*prop + 1)) - 1); + mwdma_mask = ATA_MWDMA2 & ((1 << (*prop + 1)) - 1); prop = of_get_property(op->node, "udma-mode", &proplen); if ((prop) && (proplen >= 4)) - udma_mask = 0x7 & ((1 << (*prop + 1)) - 1); + udma_mask = ATA_UDMA2 & ((1 << (*prop + 1)) - 1); ata_irq = irq_of_parse_and_map(op->node, 0); if (ata_irq == NO_IRQ) { diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c index aa576cac4d1..b21f0021f54 100644 --- a/drivers/ata/pata_mpiix.c +++ b/drivers/ata/pata_mpiix.c @@ -200,7 +200,7 @@ static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id) the MPIIX your box goes castors up */ ap->ops = &mpiix_port_ops; - ap->pio_mask = 0x1F; + ap->pio_mask = ATA_PIO4; ap->flags |= ATA_FLAG_SLAVE_POSS; ap->ioaddr.cmd_addr = cmd_addr; diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c index 9dc05e1656a..bdb236957cb 100644 --- a/drivers/ata/pata_netcell.c +++ b/drivers/ata/pata_netcell.c @@ -51,8 +51,8 @@ static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *e .flags = ATA_FLAG_SLAVE_POSS, /* Actually we don't really care about these as the firmware deals with it */ - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, /* UDMA 133 */ .port_ops = &netcell_ops, }; diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c index 4dd9a3b031e..0fb6b1b1e63 100644 --- a/drivers/ata/pata_ninja32.c +++ b/drivers/ata/pata_ninja32.c @@ -136,7 +136,7 @@ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id) if (!base) return -ENOMEM; ap->ops = &ninja32_port_ops; - ap->pio_mask = 0x1F; + ap->pio_mask = ATA_PIO4; ap->flags |= ATA_FLAG_SLAVE_POSS; ap->ioaddr.cmd_addr = base + 0x10; diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c index 40d411c460d..ca53fac0671 100644 --- a/drivers/ata/pata_ns87410.c +++ b/drivers/ata/pata_ns87410.c @@ -144,7 +144,7 @@ static int ns87410_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x0F, + .pio_mask = ATA_PIO3, .port_ops = &ns87410_port_ops }; const struct ata_port_info *ppi[] = { &info, NULL }; diff --git a/drivers/ata/pata_ns87415.c b/drivers/ata/pata_ns87415.c index 89bf5f865d6..773b1590b49 100644 --- a/drivers/ata/pata_ns87415.c +++ b/drivers/ata/pata_ns87415.c @@ -346,8 +346,8 @@ static int ns87415_init_one (struct pci_dev *pdev, const struct pci_device_id *e static int printed_version; static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &ns87415_pata_ops, }; const struct ata_port_info *ppi[] = { &info, NULL }; @@ -355,8 +355,8 @@ static int ns87415_init_one (struct pci_dev *pdev, const struct pci_device_id *e #if defined(CONFIG_SUPERIO) static const struct ata_port_info info87560 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &ns87560_pata_ops, }; diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c index 0fe4ef309c6..efe2c1985af 100644 --- a/drivers/ata/pata_octeon_cf.c +++ b/drivers/ata/pata_octeon_cf.c @@ -871,7 +871,7 @@ static int __devinit octeon_cf_probe(struct platform_device *pdev) ap->private_data = cf_port; cf_port->ap = ap; ap->ops = &octeon_cf_ops; - ap->pio_mask = 0x7f; /* Support PIO 0-6 */ + ap->pio_mask = ATA_PIO6; ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING; @@ -900,7 +900,7 @@ static int __devinit octeon_cf_probe(struct platform_device *pdev) ap->ioaddr.ctl_addr = cs1 + (6 << 1) + 1; octeon_cf_ops.sff_data_xfer = octeon_cf_data_xfer16; - ap->mwdma_mask = 0x1f; /* Support MWDMA 0-4 */ + ap->mwdma_mask = ATA_MWDMA4; irq = platform_get_irq(pdev, 0); irq_handler = octeon_cf_interrupt; diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c index 2c1a91c40c1..84ac5033ac8 100644 --- a/drivers/ata/pata_oldpiix.c +++ b/drivers/ata/pata_oldpiix.c @@ -238,8 +238,8 @@ static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *e static int printed_version; static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma1-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &oldpiix_pata_ops, }; const struct ata_port_info *ppi[] = { &info, NULL }; diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c index e4fa4d565e9..99eddda2d2e 100644 --- a/drivers/ata/pata_opti.c +++ b/drivers/ata/pata_opti.c @@ -163,7 +163,7 @@ static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, + .pio_mask = ATA_PIO4, .port_ops = &opti_port_ops }; const struct ata_port_info *ppi[] = { &info, NULL }; diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c index 93bb6e91973..86885a445f9 100644 --- a/drivers/ata/pata_optidma.c +++ b/drivers/ata/pata_optidma.c @@ -399,15 +399,15 @@ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info_82c700 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &optidma_port_ops }; static const struct ata_port_info info_82c700_udma = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA2, .port_ops = &optiplus_port_ops }; const struct ata_port_info *ppi[] = { &info_82c700, NULL }; diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index 64b2e2281ee..a5cbcc280b2 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c @@ -299,7 +299,7 @@ static int pcmcia_init_one(struct pcmcia_device *pdev) ap = host->ports[p]; ap->ops = ops; - ap->pio_mask = 1; /* ISA so PIO 0 cycles */ + ap->pio_mask = ATA_PIO0; /* ISA so PIO 0 cycles */ ap->flags |= ATA_FLAG_SLAVE_POSS; ap->ioaddr.cmd_addr = io_addr + 0x10 * p; ap->ioaddr.altstatus_addr = ctl_addr + 0x10 * p; diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c index e94efccaa48..ca5cad0fd80 100644 --- a/drivers/ata/pata_pdc2027x.c +++ b/drivers/ata/pata_pdc2027x.c @@ -152,18 +152,18 @@ static struct ata_port_info pdc2027x_port_info[] = { { .flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS | ATA_FLAG_MMIO, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA5, /* udma0-5 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &pdc2027x_pata100_ops, }, /* PDC_UDMA_133 */ { .flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS | ATA_FLAG_MMIO, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, /* udma0-6 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, .port_ops = &pdc2027x_pata133_ops, }, }; diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c index 799a6a09871..5fedb3d4032 100644 --- a/drivers/ata/pata_pdc202xx_old.c +++ b/drivers/ata/pata_pdc202xx_old.c @@ -291,22 +291,22 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id static const struct ata_port_info info[3] = { { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA2, .port_ops = &pdc2024x_port_ops }, { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, .port_ops = &pdc2026x_port_ops }, { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &pdc2026x_port_ops } diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c index f1b26f7c8e4..45879dc6fa4 100644 --- a/drivers/ata/pata_qdi.c +++ b/drivers/ata/pata_qdi.c @@ -212,11 +212,11 @@ static __init int qdi_init_one(unsigned long port, int type, unsigned long io, i if (type == 6580) { ap->ops = &qdi6580_port_ops; - ap->pio_mask = 0x1F; + ap->pio_mask = ATA_PIO4; ap->flags |= ATA_FLAG_SLAVE_POSS; } else { ap->ops = &qdi6500_port_ops; - ap->pio_mask = 0x07; /* Actually PIO3 !IORDY is possible */ + ap->pio_mask = ATA_PIO2; /* Actually PIO3 !IORDY is possible */ ap->flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_IORDY; } diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c index 695d44ae52c..1956d5c03a7 100644 --- a/drivers/ata/pata_radisys.c +++ b/drivers/ata/pata_radisys.c @@ -216,9 +216,9 @@ static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *e static int printed_version; static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma1-2 */ - .udma_mask = 0x14, /* UDMA33/66 only */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, /* mwdma1-2 */ + .udma_mask = ATA_UDMA24_ONLY, .port_ops = &radisys_pata_ops, }; const struct ata_port_info *ppi[] = { &info, NULL }; diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c index fbfee1bd85f..2f3b49cc497 100644 --- a/drivers/ata/pata_rb532_cf.c +++ b/drivers/ata/pata_rb532_cf.c @@ -89,7 +89,7 @@ static void rb532_pata_setup_ports(struct ata_host *ah) ap = ah->ports[0]; ap->ops = &rb532_pata_port_ops; - ap->pio_mask = 0x1f; /* PIO4 */ + ap->pio_mask = ATA_PIO4; ap->flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO; ap->ioaddr.cmd_addr = info->iobase + RB500_CF_REG_BASE; diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c index 46d6bc1bf1e..0c574c065c6 100644 --- a/drivers/ata/pata_rz1000.c +++ b/drivers/ata/pata_rz1000.c @@ -88,7 +88,7 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en static int printed_version; static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, + .pio_mask = ATA_PIO4, .port_ops = &rz1000_port_ops }; const struct ata_port_info *ppi[] = { &info, NULL }; diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c index 9a4bdca5461..36a0c359329 100644 --- a/drivers/ata/pata_sc1200.c +++ b/drivers/ata/pata_sc1200.c @@ -205,9 +205,9 @@ static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA2, .port_ops = &sc1200_port_ops }; /* Can't enable port 2 yet, see top comments */ diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c index d447f1cb46e..4257d6b40af 100644 --- a/drivers/ata/pata_scc.c +++ b/drivers/ata/pata_scc.c @@ -1001,8 +1001,8 @@ static struct ata_port_operations scc_pata_ops = { static struct ata_port_info scc_port_info[] = { { .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x00, + .pio_mask = ATA_PIO4, + /* No MWDMA */ .udma_mask = ATA_UDMA6, .port_ops = &scc_pata_ops, }, diff --git a/drivers/ata/pata_sch.c b/drivers/ata/pata_sch.c index 6aeeeeb3412..99cceb458e2 100644 --- a/drivers/ata/pata_sch.c +++ b/drivers/ata/pata_sch.c @@ -84,9 +84,9 @@ static struct ata_port_operations sch_pata_ops = { static struct ata_port_info sch_port_info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = ATA_PIO4, /* pio0-4 */ - .mwdma_mask = ATA_MWDMA2, /* mwdma0-2 */ - .udma_mask = ATA_UDMA5, /* udma0-5 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &sch_pata_ops, }; diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c index 8d2fd9dd40c..beaed12d50e 100644 --- a/drivers/ata/pata_serverworks.c +++ b/drivers/ata/pata_serverworks.c @@ -398,26 +398,26 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id static const struct ata_port_info info[4] = { { /* OSB4 */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA2, .port_ops = &serverworks_osb4_port_ops }, { /* OSB4 no UDMA */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x00, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + /* No UDMA */ .port_ops = &serverworks_osb4_port_ops }, { /* CSB5 */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, .port_ops = &serverworks_csb_port_ops }, { /* CSB5 - later revisions*/ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &serverworks_csb_port_ops } diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c index 9e764e5747e..4cb649d8d38 100644 --- a/drivers/ata/pata_sil680.c +++ b/drivers/ata/pata_sil680.c @@ -282,15 +282,15 @@ static int __devinit sil680_init_one(struct pci_dev *pdev, { static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &sil680_port_ops }; static const struct ata_port_info info_slow = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &sil680_port_ops }; diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c index 27ceb42a774..488e77bcd22 100644 --- a/drivers/ata/pata_sis.c +++ b/drivers/ata/pata_sis.c @@ -552,51 +552,57 @@ static struct ata_port_operations sis_old_ops = { static const struct ata_port_info sis_info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, - .udma_mask = 0, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + /* No UDMA */ .port_ops = &sis_old_ops, }; static const struct ata_port_info sis_info33 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA2, /* UDMA 33 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA2, .port_ops = &sis_old_ops, }; static const struct ata_port_info sis_info66 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .udma_mask = ATA_UDMA4, /* UDMA 66 */ + .pio_mask = ATA_PIO4, + /* No MWDMA */ + .udma_mask = ATA_UDMA4, .port_ops = &sis_66_ops, }; static const struct ata_port_info sis_info100 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, + /* No MWDMA */ .udma_mask = ATA_UDMA5, .port_ops = &sis_100_ops, }; static const struct ata_port_info sis_info100_early = { .flags = ATA_FLAG_SLAVE_POSS, + .pio_mask = ATA_PIO4, + /* No MWDMA */ .udma_mask = ATA_UDMA5, - .pio_mask = 0x1f, /* pio0-4 */ .port_ops = &sis_66_ops, }; static const struct ata_port_info sis_info133 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, + /* No MWDMA */ .udma_mask = ATA_UDMA6, .port_ops = &sis_133_ops, }; const struct ata_port_info sis_info133_for_sata = { .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, + /* No MWDMA */ .udma_mask = ATA_UDMA6, .port_ops = &sis_133_for_sata_ops, }; static const struct ata_port_info sis_info133_early = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, + /* No MWDMA */ .udma_mask = ATA_UDMA6, .port_ops = &sis_133_early_ops, }; diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c index 1b0e7b6d8ef..29f733c3206 100644 --- a/drivers/ata/pata_sl82c105.c +++ b/drivers/ata/pata_sl82c105.c @@ -283,13 +283,13 @@ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id { static const struct ata_port_info info_dma = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &sl82c105_port_ops }; static const struct ata_port_info info_early = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, + .pio_mask = ATA_PIO4, .port_ops = &sl82c105_port_ops }; /* for now use only the first port */ diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c index ef9597517cd..f1f13ff222f 100644 --- a/drivers/ata/pata_triflex.c +++ b/drivers/ata/pata_triflex.c @@ -191,8 +191,8 @@ static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &triflex_port_ops }; const struct ata_port_info *ppi[] = { &info, NULL }; diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index ba556d3e696..b08e6e0f82b 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c @@ -422,46 +422,46 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) /* Early VIA without UDMA support */ static const struct ata_port_info via_mwdma_info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &via_port_ops }; /* Ditto with IRQ masking required */ static const struct ata_port_info via_mwdma_info_borked = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &via_port_ops_noirq, }; /* VIA UDMA 33 devices (and borked 66) */ static const struct ata_port_info via_udma33_info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA2, .port_ops = &via_port_ops }; /* VIA UDMA 66 devices */ static const struct ata_port_info via_udma66_info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, .port_ops = &via_port_ops }; /* VIA UDMA 100 devices */ static const struct ata_port_info via_udma100_info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &via_port_ops }; /* UDMA133 with bad AST (All current 133) */ static const struct ata_port_info via_udma133_info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, /* FIXME: should check north bridge */ .port_ops = &via_port_ops }; diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c index 319e164a3d7..6d8619b6f67 100644 --- a/drivers/ata/pata_winbond.c +++ b/drivers/ata/pata_winbond.c @@ -193,7 +193,7 @@ static __init int winbond_init_one(unsigned long port) ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", cmd_port, ctl_port); ap->ops = &winbond_port_ops; - ap->pio_mask = 0x1F; + ap->pio_mask = ATA_PIO4; ap->flags |= ATA_FLAG_SLAVE_POSS; ap->ioaddr.cmd_addr = cmd_addr; ap->ioaddr.altstatus_addr = ctl_addr; diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c index be53545c9f6..c509c206a45 100644 --- a/drivers/ata/pdc_adma.c +++ b/drivers/ata/pdc_adma.c @@ -166,7 +166,7 @@ static struct ata_port_info adma_port_info[] = { .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING, - .pio_mask = 0x10, /* pio4 */ + .pio_mask = ATA_PIO4_ONLY, .udma_mask = ATA_UDMA4, .port_ops = &adma_ata_ops, }, diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index 55bc88c1707..c2e90e1fece 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c @@ -1279,8 +1279,8 @@ static struct ata_port_operations sata_fsl_ops = { static const struct ata_port_info sata_fsl_port_info[] = { { .flags = SATA_FSL_HOST_FLAGS, - .pio_mask = 0x1f, /* pio 0-4 */ - .udma_mask = 0x7f, /* udma 0-6 */ + .pio_mask = ATA_PIO4, + .udma_mask = ATA_UDMA6, .port_ops = &sata_fsl_ops, }, }; diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index fbbd87c96f1..305a4f825f5 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -744,8 +744,8 @@ static struct ata_port_operations inic_port_ops = { static struct ata_port_info inic_port_info = { .flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &inic_port_ops }; diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index f65b53785a8..2f523f8c27f 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -57,9 +57,9 @@ enum { NV_MMIO_BAR = 5, NV_PORTS = 2, - NV_PIO_MASK = 0x1f, - NV_MWDMA_MASK = 0x07, - NV_UDMA_MASK = 0x7f, + NV_PIO_MASK = ATA_PIO4, + NV_MWDMA_MASK = ATA_MWDMA2, + NV_UDMA_MASK = ATA_UDMA6, NV_PORT0_SCR_REG_OFFSET = 0x00, NV_PORT1_SCR_REG_OFFSET = 0x40, diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index ba9a2570a74..3ad2b886363 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -213,8 +213,8 @@ static const struct ata_port_info pdc_port_info[] = { { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | PDC_FLAG_SATA_PATA, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &pdc_old_sata_ops, }, @@ -222,8 +222,8 @@ static const struct ata_port_info pdc_port_info[] = { [board_2037x_pata] = { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &pdc_pata_ops, }, @@ -232,8 +232,8 @@ static const struct ata_port_info pdc_port_info[] = { { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | PDC_FLAG_4_PORTS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &pdc_old_sata_ops, }, @@ -242,8 +242,8 @@ static const struct ata_port_info pdc_port_info[] = { { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS | PDC_FLAG_4_PORTS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &pdc_pata_ops, }, @@ -252,8 +252,8 @@ static const struct ata_port_info pdc_port_info[] = { { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | PDC_FLAG_GEN_II | PDC_FLAG_SATA_PATA, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &pdc_sata_ops, }, @@ -262,8 +262,8 @@ static const struct ata_port_info pdc_port_info[] = { { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS | PDC_FLAG_GEN_II, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &pdc_pata_ops, }, @@ -272,8 +272,8 @@ static const struct ata_port_info pdc_port_info[] = { { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &pdc_sata_ops, }, diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c index a000c86ac85..7112d89fd9f 100644 --- a/drivers/ata/sata_qstor.c +++ b/drivers/ata/sata_qstor.c @@ -160,7 +160,7 @@ static const struct ata_port_info qs_port_info[] = { { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING, - .pio_mask = 0x10, /* pio4 */ + .pio_mask = ATA_PIO4_ONLY, .udma_mask = ATA_UDMA6, .port_ops = &qs_ata_ops, }, diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index d0091609e21..e67ce8e5caa 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -200,8 +200,8 @@ static const struct ata_port_info sil_port_info[] = { /* sil_3112 */ { .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &sil_ops, }, @@ -209,24 +209,24 @@ static const struct ata_port_info sil_port_info[] = { { .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE | SIL_FLAG_NO_SATA_IRQ, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &sil_ops, }, /* sil_3512 */ { .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &sil_ops, }, /* sil_3114 */ { .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &sil_ops, }, diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 2590c2279fa..0d8990dcdfc 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -429,25 +429,25 @@ static const struct ata_port_info sil24_port_info[] = { { .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) | SIL24_FLAG_PCIX_IRQ_WOC, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA5, /* udma0-5 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &sil24_ops, }, /* sil_3132 */ { .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2), - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA5, /* udma0-5 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &sil24_ops, }, /* sil_3131/sil_3531 */ { .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1), - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA5, /* udma0-5 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &sil24_ops, }, }; diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c index 9c43b4e7c4a..8f983322861 100644 --- a/drivers/ata/sata_sis.c +++ b/drivers/ata/sata_sis.c @@ -97,8 +97,8 @@ static struct ata_port_operations sis_ops = { static const struct ata_port_info sis_port_info = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, - .pio_mask = 0x1f, - .mwdma_mask = 0x7, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &sis_ops, }; diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c index 609d147813a..7257f2d5c52 100644 --- a/drivers/ata/sata_svw.c +++ b/drivers/ata/sata_svw.c @@ -361,8 +361,8 @@ static const struct ata_port_info k2_port_info[] = { { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &k2_sata_ops, }, @@ -371,8 +371,8 @@ static const struct ata_port_info k2_port_info[] = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA | K2_FLAG_SATA_8_PORTS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &k2_sata_ops, }, @@ -380,8 +380,8 @@ static const struct ata_port_info k2_port_info[] = { { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | K2_FLAG_BAR_POS_3, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &k2_sata_ops, }, @@ -389,8 +389,8 @@ static const struct ata_port_info k2_port_info[] = { { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &k2_sata_ops, }, diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c index ec04b8d3c79..dce3dccced3 100644 --- a/drivers/ata/sata_sx4.c +++ b/drivers/ata/sata_sx4.c @@ -265,8 +265,8 @@ static const struct ata_port_info pdc_port_info[] = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &pdc_20621_ops, }, diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c index 019575bb3e0..e5bff47e8aa 100644 --- a/drivers/ata/sata_uli.c +++ b/drivers/ata/sata_uli.c @@ -89,7 +89,7 @@ static struct ata_port_operations uli_ops = { static const struct ata_port_info uli_port_info = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_IGN_SIMPLEX, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &uli_ops, }; diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 5c62da9cd49..98e8c50703b 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -146,24 +146,24 @@ static struct ata_port_operations vt8251_ops = { static const struct ata_port_info vt6420_port_info = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &vt6420_sata_ops, }; static struct ata_port_info vt6421_sport_info = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &vt6421_sata_ops, }; static struct ata_port_info vt6421_pport_info = { .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY, - .pio_mask = 0x1f, - .mwdma_mask = 0, + .pio_mask = ATA_PIO4, + /* No MWDMA */ .udma_mask = ATA_UDMA6, .port_ops = &vt6421_pata_ops, }; @@ -171,8 +171,8 @@ static struct ata_port_info vt6421_pport_info = { static struct ata_port_info vt8251_port_info = { .flags = ATA_FLAG_SATA | ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &vt8251_ops, }; diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c index c57cdff9e6b..ef211f333d7 100644 --- a/drivers/ata/sata_vsc.c +++ b/drivers/ata/sata_vsc.c @@ -345,8 +345,8 @@ static int __devinit vsc_sata_init_one(struct pci_dev *pdev, static const struct ata_port_info pi = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &vsc_sata_ops, }; -- GitLab From aef37d8d80d8c027f03d362a97afe3f6a42bfbb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Inge=20Bols=C3=B8?= Date: Sat, 14 Mar 2009 23:07:33 +0100 Subject: [PATCH 4474/4982] pata_radisys: fix mwdma_mask to exclude mwdma0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As noted by Alan: >Your suspicions are correct here btw - the device can only do MWDMA1 and >MWDMA2 (much like some PIIX devices) Signed-off-by: Erik Inge Bolsø Signed-off-by: Jeff Garzik --- drivers/ata/pata_radisys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c index 1956d5c03a7..4401b332eaa 100644 --- a/drivers/ata/pata_radisys.c +++ b/drivers/ata/pata_radisys.c @@ -217,7 +217,7 @@ static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *e static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, .pio_mask = ATA_PIO4, - .mwdma_mask = ATA_MWDMA2, /* mwdma1-2 */ + .mwdma_mask = ATA_MWDMA12_ONLY, .udma_mask = ATA_UDMA24_ONLY, .port_ops = &radisys_pata_ops, }; -- GitLab From b2a034cf16a1642e647497c70c1cd9c09bf39412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Inge=20Bols=C3=B8?= Date: Sat, 14 Mar 2009 23:08:20 +0100 Subject: [PATCH 4475/4982] pata_efar: fix *dma_mask MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to Alan: >and yes the EFAR does UDMA66. mwdma: >Yep - wrong comment. The EFAR is a sort of clone of the PIIX and I >copied the comment while EFAR don't appear to have copied the >limitation Signed-off-by: Erik Inge Bolsø Signed-off-by: Jeff Garzik --- drivers/ata/pata_efar.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c index bd498cc3920..2085e0a3a05 100644 --- a/drivers/ata/pata_efar.c +++ b/drivers/ata/pata_efar.c @@ -252,8 +252,8 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, .pio_mask = ATA_PIO4, - .mwdma_mask = ATA_MWDMA2, /* mwdma1-2 */ - .udma_mask = ATA_UDMA3, /* UDMA 66 */ + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA4, .port_ops = &efar_ops, }; const struct ata_port_info *ppi[] = { &info, NULL }; -- GitLab From 9223d01b2fdf638a73888ad73a1784fca3454c1e Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 13 Mar 2009 15:41:43 +0100 Subject: [PATCH 4476/4982] pata-rb532-cf: platform_get_irq() fix ignored failure platform_get_irq() can return -ENXIO, but since 'irq' is an unsigned int, it does not show when the IRQ resource wasn't found. Make irq an int so that we can use a single variable to test the platform_get_irq() return value. Signed-off-by: Roel Kluin Signed-off-by: Phil Sutter Signed-off-by: Florian Fainelli Signed-off-by: Jeff Garzik --- drivers/ata/pata_rb532_cf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c index 2f3b49cc497..8e3cdef8a25 100644 --- a/drivers/ata/pata_rb532_cf.c +++ b/drivers/ata/pata_rb532_cf.c @@ -104,7 +104,7 @@ static void rb532_pata_setup_ports(struct ata_host *ah) static __devinit int rb532_pata_driver_probe(struct platform_device *pdev) { - unsigned int irq; + int irq; int gpio; struct resource *res; struct ata_host *ah; -- GitLab From 40f21b1124a9552bc093469280eb8239dc5f73d7 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Tue, 10 Mar 2009 18:51:04 -0400 Subject: [PATCH 4477/4982] sata_mv: cosmetic preparations for IRQ coalescing Various cosmetic changes in preparation for the IRQ coalescing feature. Note that the various MV_IRQ_COAL_* definitions are restored/renamed in the folloup patch which adds IRQ coalescing to the driver. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 62 +++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 35 deletions(-) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 8cad3b2fe55..206220ec582 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1,10 +1,13 @@ /* * sata_mv.c - Marvell SATA support * - * Copyright 2008: Marvell Corporation, all rights reserved. + * Copyright 2008-2009: Marvell Corporation, all rights reserved. * Copyright 2005: EMC Corporation, all rights reserved. * Copyright 2005 Red Hat, Inc. All rights reserved. * + * Originally written by Brett Russ. + * Extensive overhaul and enhancement by Mark Lord . + * * Please ALWAYS copy linux-ide@vger.kernel.org on emails. * * This program is free software; you can redistribute it and/or modify @@ -25,8 +28,6 @@ /* * sata_mv TODO list: * - * --> Errata workaround for NCQ device errors. - * * --> More errata workarounds for PCI-X. * * --> Complete a full errata audit for all chipsets to identify others. @@ -68,6 +69,16 @@ #define DRV_NAME "sata_mv" #define DRV_VERSION "1.26" +/* + * module options + */ + +static int msi; +#ifdef CONFIG_PCI +module_param(msi, int, S_IRUGO); +MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)"); +#endif + enum { /* BAR's are enumerated in terms of pci_resource_start() terms */ MV_PRIMARY_BAR = 0, /* offset 0x10: memory space */ @@ -78,12 +89,6 @@ enum { MV_MINOR_REG_AREA_SZ = 0x2000, /* 8KB */ MV_PCI_REG_BASE = 0, - MV_IRQ_COAL_REG_BASE = 0x18000, /* 6xxx part only */ - MV_IRQ_COAL_CAUSE = (MV_IRQ_COAL_REG_BASE + 0x08), - MV_IRQ_COAL_CAUSE_LO = (MV_IRQ_COAL_REG_BASE + 0x88), - MV_IRQ_COAL_CAUSE_HI = (MV_IRQ_COAL_REG_BASE + 0x8c), - MV_IRQ_COAL_THRESHOLD = (MV_IRQ_COAL_REG_BASE + 0xcc), - MV_IRQ_COAL_TIME_THRESHOLD = (MV_IRQ_COAL_REG_BASE + 0xd0), MV_SATAHC0_REG_BASE = 0x20000, MV_FLASH_CTL_OFS = 0x1046c, @@ -115,16 +120,14 @@ enum { /* Host Flags */ MV_FLAG_DUAL_HC = (1 << 30), /* two SATA Host Controllers */ - MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */ MV_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING, MV_GEN_I_FLAGS = MV_COMMON_FLAGS | ATA_FLAG_NO_ATAPI, - MV_GEN_II_FLAGS = MV_COMMON_FLAGS | MV_FLAG_IRQ_COALESCE | - ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA | - ATA_FLAG_NCQ, + MV_GEN_II_FLAGS = MV_COMMON_FLAGS | ATA_FLAG_NCQ | + ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA, MV_GEN_IIE_FLAGS = MV_GEN_II_FLAGS | ATA_FLAG_AN, @@ -179,16 +182,16 @@ enum { PCI_HC_MAIN_IRQ_MASK_OFS = 0x1d64, SOC_HC_MAIN_IRQ_CAUSE_OFS = 0x20020, SOC_HC_MAIN_IRQ_MASK_OFS = 0x20024, - ERR_IRQ = (1 << 0), /* shift by port # */ - DONE_IRQ = (1 << 1), /* shift by port # */ + ERR_IRQ = (1 << 0), /* shift by (2 * port #) */ + DONE_IRQ = (1 << 1), /* shift by (2 * port #) */ HC0_IRQ_PEND = 0x1ff, /* bits 0-8 = HC0's ports */ HC_SHIFT = 9, /* bits 9-17 = HC1's ports */ PCI_ERR = (1 << 18), - TRAN_LO_DONE = (1 << 19), /* 6xxx: IRQ coalescing */ - TRAN_HI_DONE = (1 << 20), /* 6xxx: IRQ coalescing */ - PORTS_0_3_COAL_DONE = (1 << 8), - PORTS_4_7_COAL_DONE = (1 << 17), - PORTS_0_7_COAL_DONE = (1 << 21), /* 6xxx: IRQ coalescing */ + TRAN_COAL_LO_DONE = (1 << 19), /* transaction coalescing */ + TRAN_COAL_HI_DONE = (1 << 20), /* transaction coalescing */ + PORTS_0_3_COAL_DONE = (1 << 8), /* HC0 IRQ coalescing */ + PORTS_4_7_COAL_DONE = (1 << 17), /* HC1 IRQ coalescing */ + ALL_PORTS_COAL_DONE = (1 << 21), /* GEN_II(E) IRQ coalescing */ GPIO_INT = (1 << 22), SELF_INT = (1 << 23), TWSI_INT = (1 << 24), @@ -621,7 +624,7 @@ static struct ata_port_operations mv6_ops = { .softreset = mv_softreset, .error_handler = mv_pmp_error_handler, - .sff_check_status = mv_sff_check_status, + .sff_check_status = mv_sff_check_status, .sff_irq_clear = mv_sff_irq_clear, .check_atapi_dma = mv_check_atapi_dma, .bmdma_setup = mv_bmdma_setup, @@ -1255,8 +1258,8 @@ static void mv_60x1_errata_sata25(struct ata_port *ap, int want_ncq) } /** - * mv_bmdma_enable - set a magic bit on GEN_IIE to allow bmdma - * @ap: Port being initialized + * mv_bmdma_enable - set a magic bit on GEN_IIE to allow bmdma + * @ap: Port being initialized * * There are two DMA modes on these chips: basic DMA, and EDMA. * @@ -2000,7 +2003,7 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) struct mv_host_priv *hpriv = ap->host->private_data; /* * Workaround for 88SX60x1 FEr SATA#25 (part 2). - * + * * After any NCQ error, the READ_LOG_EXT command * from libata-eh *must* use mv_qc_issue_fis(). * Otherwise it might fail, due to chip errata. @@ -3704,12 +3707,6 @@ static struct pci_driver mv_pci_driver = { .remove = ata_pci_remove_one, }; -/* - * module options - */ -static int msi; /* Use PCI msi; either zero (off, default) or non-zero */ - - /* move to PCI layer or libata core? */ static int pci_go_64(struct pci_dev *pdev) { @@ -3891,10 +3888,5 @@ MODULE_DEVICE_TABLE(pci, mv_pci_tbl); MODULE_VERSION(DRV_VERSION); MODULE_ALIAS("platform:" DRV_NAME); -#ifdef CONFIG_PCI -module_param(msi, int, 0444); -MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)"); -#endif - module_init(mv_init); module_exit(mv_exit); -- GitLab From 2b748a0a344847fe6b924407bbe153e1878c9f09 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Tue, 10 Mar 2009 22:01:17 -0400 Subject: [PATCH 4478/4982] sata_mv: implement IRQ coalescing (v2) Add IRQ coalescing to sata_mv (off by default). This feature can reduce total interrupt overhead for RAID setups in some situations, by deferring the interrupt signal until one or both of: a) a specified io_count (completed SATA commands) is achieved, or b) a specified time interval elapses after an IO completion. For now, module parameters are used to set the irq_coalescing_io_count and irq_coalescing_usecs (timeout) globally. These may eventually be supplemented with sysfs attributes, so that thresholds can be set on-the-fly and on a per-chip (or even per-host_controller) basis. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 143 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 135 insertions(+), 8 deletions(-) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 206220ec582..ef385451ffd 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -34,10 +34,7 @@ * * --> Develop a low-power-consumption strategy, and implement it. * - * --> [Experiment, low priority] Investigate interrupt coalescing. - * Quite often, especially with PCI Message Signalled Interrupts (MSI), - * the overhead reduced by interrupt mitigation is quite often not - * worth the latency cost. + * --> Add sysfs attributes for per-chip / per-HC IRQ coalescing thresholds. * * --> [Experiment, Marvell value added] Is it possible to use target * mode to cross-connect two Linux boxes with Marvell cards? If so, @@ -67,7 +64,7 @@ #include #define DRV_NAME "sata_mv" -#define DRV_VERSION "1.26" +#define DRV_VERSION "1.27" /* * module options @@ -79,6 +76,16 @@ module_param(msi, int, S_IRUGO); MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)"); #endif +static int irq_coalescing_io_count; +module_param(irq_coalescing_io_count, int, S_IRUGO); +MODULE_PARM_DESC(irq_coalescing_io_count, + "IRQ coalescing I/O count threshold (0..255)"); + +static int irq_coalescing_usecs; +module_param(irq_coalescing_usecs, int, S_IRUGO); +MODULE_PARM_DESC(irq_coalescing_usecs, + "IRQ coalescing time threshold in usecs"); + enum { /* BAR's are enumerated in terms of pci_resource_start() terms */ MV_PRIMARY_BAR = 0, /* offset 0x10: memory space */ @@ -88,8 +95,33 @@ enum { MV_MAJOR_REG_AREA_SZ = 0x10000, /* 64KB */ MV_MINOR_REG_AREA_SZ = 0x2000, /* 8KB */ + /* For use with both IRQ coalescing methods ("all ports" or "per-HC" */ + COAL_CLOCKS_PER_USEC = 150, /* for calculating COAL_TIMEs */ + MAX_COAL_TIME_THRESHOLD = ((1 << 24) - 1), /* internal clocks count */ + MAX_COAL_IO_COUNT = 255, /* completed I/O count */ + MV_PCI_REG_BASE = 0, + /* + * Per-chip ("all ports") interrupt coalescing feature. + * This is only for GEN_II / GEN_IIE hardware. + * + * Coalescing defers the interrupt until either the IO_THRESHOLD + * (count of completed I/Os) is met, or the TIME_THRESHOLD is met. + */ + MV_COAL_REG_BASE = 0x18000, + MV_IRQ_COAL_CAUSE = (MV_COAL_REG_BASE + 0x08), + ALL_PORTS_COAL_IRQ = (1 << 4), /* all ports irq event */ + + MV_IRQ_COAL_IO_THRESHOLD = (MV_COAL_REG_BASE + 0xcc), + MV_IRQ_COAL_TIME_THRESHOLD = (MV_COAL_REG_BASE + 0xd0), + + /* + * Registers for the (unused here) transaction coalescing feature: + */ + MV_TRAN_COAL_CAUSE_LO = (MV_COAL_REG_BASE + 0x88), + MV_TRAN_COAL_CAUSE_HI = (MV_COAL_REG_BASE + 0x8c), + MV_SATAHC0_REG_BASE = 0x20000, MV_FLASH_CTL_OFS = 0x1046c, MV_GPIO_PORT_CTL_OFS = 0x104f0, @@ -186,6 +218,8 @@ enum { DONE_IRQ = (1 << 1), /* shift by (2 * port #) */ HC0_IRQ_PEND = 0x1ff, /* bits 0-8 = HC0's ports */ HC_SHIFT = 9, /* bits 9-17 = HC1's ports */ + DONE_IRQ_0_3 = 0x000000aa, /* DONE_IRQ ports 0,1,2,3 */ + DONE_IRQ_4_7 = (DONE_IRQ_0_3 << HC_SHIFT), /* 4,5,6,7 */ PCI_ERR = (1 << 18), TRAN_COAL_LO_DONE = (1 << 19), /* transaction coalescing */ TRAN_COAL_HI_DONE = (1 << 20), /* transaction coalescing */ @@ -207,6 +241,16 @@ enum { HC_COAL_IRQ = (1 << 4), /* IRQ coalescing */ DEV_IRQ = (1 << 8), /* shift by port # */ + /* + * Per-HC (Host-Controller) interrupt coalescing feature. + * This is present on all chip generations. + * + * Coalescing defers the interrupt until either the IO_THRESHOLD + * (count of completed I/Os) is met, or the TIME_THRESHOLD is met. + */ + HC_IRQ_COAL_IO_THRESHOLD_OFS = 0x000c, + HC_IRQ_COAL_TIME_THRESHOLD_OFS = 0x0010, + /* Shadow block registers */ SHD_BLK_OFS = 0x100, SHD_CTL_AST_OFS = 0x20, /* ofs from SHD_BLK_OFS */ @@ -897,6 +941,23 @@ static void mv_set_edma_ptrs(void __iomem *port_mmio, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); } +static void mv_write_main_irq_mask(u32 mask, struct mv_host_priv *hpriv) +{ + /* + * When writing to the main_irq_mask in hardware, + * we must ensure exclusivity between the interrupt coalescing bits + * and the corresponding individual port DONE_IRQ bits. + * + * Note that this register is really an "IRQ enable" register, + * not an "IRQ mask" register as Marvell's naming might suggest. + */ + if (mask & (ALL_PORTS_COAL_DONE | PORTS_0_3_COAL_DONE)) + mask &= ~DONE_IRQ_0_3; + if (mask & (ALL_PORTS_COAL_DONE | PORTS_4_7_COAL_DONE)) + mask &= ~DONE_IRQ_4_7; + writelfl(mask, hpriv->main_irq_mask_addr); +} + static void mv_set_main_irq_mask(struct ata_host *host, u32 disable_bits, u32 enable_bits) { @@ -907,7 +968,7 @@ static void mv_set_main_irq_mask(struct ata_host *host, new_mask = (old_mask & ~disable_bits) | enable_bits; if (new_mask != old_mask) { hpriv->main_irq_mask = new_mask; - writelfl(new_mask, hpriv->main_irq_mask_addr); + mv_write_main_irq_mask(new_mask, hpriv); } } @@ -948,6 +1009,64 @@ static void mv_clear_and_enable_port_irqs(struct ata_port *ap, mv_enable_port_irqs(ap, port_irqs); } +static void mv_set_irq_coalescing(struct ata_host *host, + unsigned int count, unsigned int usecs) +{ + struct mv_host_priv *hpriv = host->private_data; + void __iomem *mmio = hpriv->base, *hc_mmio; + u32 coal_enable = 0; + unsigned long flags; + unsigned int clks; + const u32 coal_disable = PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE | + ALL_PORTS_COAL_DONE; + + /* Disable IRQ coalescing if either threshold is zero */ + if (!usecs || !count) { + clks = count = 0; + } else { + /* Respect maximum limits of the hardware */ + clks = usecs * COAL_CLOCKS_PER_USEC; + if (clks > MAX_COAL_TIME_THRESHOLD) + clks = MAX_COAL_TIME_THRESHOLD; + if (count > MAX_COAL_IO_COUNT) + count = MAX_COAL_IO_COUNT; + } + + spin_lock_irqsave(&host->lock, flags); + +#if 0 /* disabled pending functional clarification from Marvell */ + if (!IS_GEN_I(hpriv)) { + /* + * GEN_II/GEN_IIE: global thresholds for the entire chip. + */ + writel(clks, mmio + MV_IRQ_COAL_TIME_THRESHOLD); + writel(count, mmio + MV_IRQ_COAL_IO_THRESHOLD); + /* clear leftover coal IRQ bit */ + writelfl(~ALL_PORTS_COAL_IRQ, mmio + MV_IRQ_COAL_CAUSE); + clks = count = 0; /* so as to clear the alternate regs below */ + coal_enable = ALL_PORTS_COAL_DONE; + } +#endif + /* + * All chips: independent thresholds for each HC on the chip. + */ + hc_mmio = mv_hc_base_from_port(mmio, 0); + writel(clks, hc_mmio + HC_IRQ_COAL_TIME_THRESHOLD_OFS); + writel(count, hc_mmio + HC_IRQ_COAL_IO_THRESHOLD_OFS); + coal_enable |= PORTS_0_3_COAL_DONE; + if (hpriv->n_ports > 4) { + hc_mmio = mv_hc_base_from_port(mmio, MV_PORTS_PER_HC); + writel(clks, hc_mmio + HC_IRQ_COAL_TIME_THRESHOLD_OFS); + writel(count, hc_mmio + HC_IRQ_COAL_IO_THRESHOLD_OFS); + coal_enable |= PORTS_4_7_COAL_DONE; + } + if (!count) + coal_enable = 0; + mv_set_main_irq_mask(host, coal_disable, coal_enable); + + spin_unlock_irqrestore(&host->lock, flags); +} + /** * mv_start_edma - Enable eDMA engine * @base: port base address @@ -2500,6 +2619,10 @@ static int mv_host_intr(struct ata_host *host, u32 main_irq_cause) void __iomem *mmio = hpriv->base, *hc_mmio; unsigned int handled = 0, port; + /* If asserted, clear the "all ports" IRQ coalescing bit */ + if (main_irq_cause & ALL_PORTS_COAL_DONE) + writel(~ALL_PORTS_COAL_IRQ, mmio + MV_IRQ_COAL_CAUSE); + for (port = 0; port < hpriv->n_ports; port++) { struct ata_port *ap = host->ports[port]; unsigned int p, shift, hardport, port_cause; @@ -2532,6 +2655,8 @@ static int mv_host_intr(struct ata_host *host, u32 main_irq_cause) * to ack (only) those ports via hc_irq_cause. */ ack_irqs = 0; + if (hc_cause & PORTS_0_3_COAL_DONE) + ack_irqs = HC_COAL_IRQ; for (p = 0; p < MV_PORTS_PER_HC; ++p) { if ((port + p) >= hpriv->n_ports) break; @@ -2620,7 +2745,7 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance) /* for MSI: block new interrupts while in here */ if (using_msi) - writel(0, hpriv->main_irq_mask_addr); + mv_write_main_irq_mask(0, hpriv); main_irq_cause = readl(hpriv->main_irq_cause_addr); pending_irqs = main_irq_cause & hpriv->main_irq_mask; @@ -2637,7 +2762,7 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance) /* for MSI: unmask; interrupt cause bits will retrigger now */ if (using_msi) - writel(hpriv->main_irq_mask, hpriv->main_irq_mask_addr); + mv_write_main_irq_mask(hpriv->main_irq_mask, hpriv); spin_unlock(&host->lock); @@ -3546,6 +3671,8 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx) * The per-port interrupts get done later as ports are set up. */ mv_set_main_irq_mask(host, 0, PCI_ERR); + mv_set_irq_coalescing(host, irq_coalescing_io_count, + irq_coalescing_usecs); done: return rc; } -- GitLab From 6abf4678261218938ccdac90767d34ce9937634f Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Wed, 11 Mar 2009 00:56:00 -0400 Subject: [PATCH 4479/4982] sata_mv: optimize IRQ coalescing for 8-port chips Enable use of the "all ports" IRQ coalescing optimization for GEN_II / GEN_IIE chips that have dual host-controllers (8-ports). Currently only the 6081 chip qualifies, but other chips may come along someday. Rather than each half of the chip having to satisfy a local set of coalescing thresholds, use of this feature groups all ports together under a single set of thresholds. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index ef385451ffd..47184567248 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1016,7 +1016,7 @@ static void mv_set_irq_coalescing(struct ata_host *host, void __iomem *mmio = hpriv->base, *hc_mmio; u32 coal_enable = 0; unsigned long flags; - unsigned int clks; + unsigned int clks, is_dual_hc = hpriv->n_ports > MV_PORTS_PER_HC; const u32 coal_disable = PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE | ALL_PORTS_COAL_DONE; @@ -1033,37 +1033,41 @@ static void mv_set_irq_coalescing(struct ata_host *host, } spin_lock_irqsave(&host->lock, flags); + mv_set_main_irq_mask(host, coal_disable, 0); -#if 0 /* disabled pending functional clarification from Marvell */ - if (!IS_GEN_I(hpriv)) { + if (is_dual_hc && !IS_GEN_I(hpriv)) { /* - * GEN_II/GEN_IIE: global thresholds for the entire chip. + * GEN_II/GEN_IIE with dual host controllers: + * one set of global thresholds for the entire chip. */ writel(clks, mmio + MV_IRQ_COAL_TIME_THRESHOLD); writel(count, mmio + MV_IRQ_COAL_IO_THRESHOLD); /* clear leftover coal IRQ bit */ - writelfl(~ALL_PORTS_COAL_IRQ, mmio + MV_IRQ_COAL_CAUSE); - clks = count = 0; /* so as to clear the alternate regs below */ - coal_enable = ALL_PORTS_COAL_DONE; + writel(~ALL_PORTS_COAL_IRQ, mmio + MV_IRQ_COAL_CAUSE); + if (count) + coal_enable = ALL_PORTS_COAL_DONE; + clks = count = 0; /* force clearing of regular regs below */ } -#endif + /* * All chips: independent thresholds for each HC on the chip. */ hc_mmio = mv_hc_base_from_port(mmio, 0); writel(clks, hc_mmio + HC_IRQ_COAL_TIME_THRESHOLD_OFS); writel(count, hc_mmio + HC_IRQ_COAL_IO_THRESHOLD_OFS); - coal_enable |= PORTS_0_3_COAL_DONE; - if (hpriv->n_ports > 4) { + writel(~HC_COAL_IRQ, hc_mmio + HC_IRQ_CAUSE_OFS); + if (count) + coal_enable |= PORTS_0_3_COAL_DONE; + if (is_dual_hc) { hc_mmio = mv_hc_base_from_port(mmio, MV_PORTS_PER_HC); writel(clks, hc_mmio + HC_IRQ_COAL_TIME_THRESHOLD_OFS); writel(count, hc_mmio + HC_IRQ_COAL_IO_THRESHOLD_OFS); - coal_enable |= PORTS_4_7_COAL_DONE; + writel(~HC_COAL_IRQ, hc_mmio + HC_IRQ_CAUSE_OFS); + if (count) + coal_enable |= PORTS_4_7_COAL_DONE; } - if (!count) - coal_enable = 0; - mv_set_main_irq_mask(host, coal_disable, coal_enable); + mv_set_main_irq_mask(host, 0, coal_enable); spin_unlock_irqrestore(&host->lock, flags); } -- GitLab From 000b344f4ca7828ee43940255c8bbb32e2c7dbec Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Sun, 15 Mar 2009 11:33:19 -0400 Subject: [PATCH 4480/4982] sata_mv: fix LED blinking for SoC+NCQ For Marvell SoC chips, the HDD LED does not blink when there is disk I/O if NCQ is enabled. Add a quirk that enables blink mode for the LED while NCQ is enabled on any port of a SoC host controller. Normal LED function is restored when NCQ is not enabled on any port. The code to enable the blink mode is based on earlier code and suggestions from Frans Pop, Saeed Bishara, and possibly others. Signed-off-by: Mark Lord Tested-by: Frans Pop Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 68 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 47184567248..8a751054c8a 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -251,6 +251,11 @@ enum { HC_IRQ_COAL_IO_THRESHOLD_OFS = 0x000c, HC_IRQ_COAL_TIME_THRESHOLD_OFS = 0x0010, + SOC_LED_CTRL_OFS = 0x2c, + SOC_LED_CTRL_BLINK = (1 << 0), /* Active LED blink */ + SOC_LED_CTRL_ACT_PRESENCE = (1 << 2), /* Multiplex dev presence */ + /* with dev activity LED */ + /* Shadow block registers */ SHD_BLK_OFS = 0x100, SHD_CTL_AST_OFS = 0x20, /* ofs from SHD_BLK_OFS */ @@ -411,6 +416,7 @@ enum { MV_HP_PCIE = (1 << 9), /* PCIe bus/regs: 7042 */ MV_HP_CUT_THROUGH = (1 << 10), /* can use EDMA cut-through */ MV_HP_FLAG_SOC = (1 << 11), /* SystemOnChip, no PCI */ + MV_HP_QUIRK_LED_BLINK_EN = (1 << 12), /* is led blinking enabled? */ /* Port private flags (pp_flags) */ MV_PP_FLAG_EDMA_EN = (1 << 0), /* is EDMA engine enabled? */ @@ -1404,6 +1410,61 @@ static void mv_bmdma_enable_iie(struct ata_port *ap, int enable_bmdma) mv_write_cached_reg(mv_ap_base(ap) + EDMA_UNKNOWN_RSVD_OFS, old, new); } +/* + * SOC chips have an issue whereby the HDD LEDs don't always blink + * during I/O when NCQ is enabled. Enabling a special "LED blink" mode + * of the SOC takes care of it, generating a steady blink rate when + * any drive on the chip is active. + * + * Unfortunately, the blink mode is a global hardware setting for the SOC, + * so we must use it whenever at least one port on the SOC has NCQ enabled. + * + * We turn "LED blink" off when NCQ is not in use anywhere, because the normal + * LED operation works then, and provides better (more accurate) feedback. + * + * Note that this code assumes that an SOC never has more than one HC onboard. + */ +static void mv_soc_led_blink_enable(struct ata_port *ap) +{ + struct ata_host *host = ap->host; + struct mv_host_priv *hpriv = host->private_data; + void __iomem *hc_mmio; + u32 led_ctrl; + + if (hpriv->hp_flags & MV_HP_QUIRK_LED_BLINK_EN) + return; + hpriv->hp_flags |= MV_HP_QUIRK_LED_BLINK_EN; + hc_mmio = mv_hc_base_from_port(mv_host_base(host), ap->port_no); + led_ctrl = readl(hc_mmio + SOC_LED_CTRL_OFS); + writel(led_ctrl | SOC_LED_CTRL_BLINK, hc_mmio + SOC_LED_CTRL_OFS); +} + +static void mv_soc_led_blink_disable(struct ata_port *ap) +{ + struct ata_host *host = ap->host; + struct mv_host_priv *hpriv = host->private_data; + void __iomem *hc_mmio; + u32 led_ctrl; + unsigned int port; + + if (!(hpriv->hp_flags & MV_HP_QUIRK_LED_BLINK_EN)) + return; + + /* disable led-blink only if no ports are using NCQ */ + for (port = 0; port < hpriv->n_ports; port++) { + struct ata_port *this_ap = host->ports[port]; + struct mv_port_priv *pp = this_ap->private_data; + + if (pp->pp_flags & MV_PP_FLAG_NCQ_EN) + return; + } + + hpriv->hp_flags &= ~MV_HP_QUIRK_LED_BLINK_EN; + hc_mmio = mv_hc_base_from_port(mv_host_base(host), ap->port_no); + led_ctrl = readl(hc_mmio + SOC_LED_CTRL_OFS); + writel(led_ctrl & ~SOC_LED_CTRL_BLINK, hc_mmio + SOC_LED_CTRL_OFS); +} + static void mv_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma) { u32 cfg; @@ -1451,6 +1512,13 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma) if (hpriv->hp_flags & MV_HP_CUT_THROUGH) cfg |= (1 << 17); /* enab cut-thru (dis stor&forwrd) */ mv_bmdma_enable_iie(ap, !want_edma); + + if (IS_SOC(hpriv)) { + if (want_ncq) + mv_soc_led_blink_enable(ap); + else + mv_soc_led_blink_disable(ap); + } } if (want_ncq) { -- GitLab From e18086d69cb5bb864749a0637f6ac573aa89d5ea Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Thu, 19 Mar 2009 13:32:21 -0400 Subject: [PATCH 4481/4982] [libata] More robust parsing for IDENTIFY DEVICE multi_count field Make libata more robust when parsing the multi_count field from a drive's identify data. This prevents us from attempting to use dubious multi_count values ad infinitum. Reset dev->multi_count to zero and reprobe it each time through this routine, as it can change on device reset. Also ensure that the reported "maximum" value is valid and is a power of two, and that the reported "count" value is valid and also a power of two. And that the "count" value is not greater than the "maximum" value. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index d4a7b8a96ec..e7ea77cf606 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -2389,6 +2390,7 @@ int ata_dev_configure(struct ata_device *dev) dev->cylinders = 0; dev->heads = 0; dev->sectors = 0; + dev->multi_count = 0; /* * common ATA, ATAPI feature tests @@ -2426,8 +2428,15 @@ int ata_dev_configure(struct ata_device *dev) dev->n_sectors = ata_id_n_sectors(id); - if (dev->id[59] & 0x100) - dev->multi_count = dev->id[59] & 0xff; + /* get current R/W Multiple count setting */ + if ((dev->id[47] >> 8) == 0x80 && (dev->id[59] & 0x100)) { + unsigned int max = dev->id[47] & 0xff; + unsigned int cnt = dev->id[59] & 0xff; + /* only recognize/allow powers of two here */ + if (is_power_of_2(max) && is_power_of_2(cnt)) + if (cnt <= max) + dev->multi_count = cnt; + } if (ata_id_has_lba(id)) { const char *lba_desc; -- GitLab From 208f2a886a2f6cf329c9fcbf8d29a0dd245cc763 Mon Sep 17 00:00:00 2001 From: David Milburn Date: Fri, 20 Mar 2009 14:14:23 -0500 Subject: [PATCH 4482/4982] [libata] ahci: correct enclosure LED state save ahci_transmit_led_message saves off the led_state with a value that includes the port number OR'd in, this incorrect value maybe reported back in ahci_led_store. For instance, if you turn off all the leds for port 1 and cat the value back it will report 1 instead of 0. # echo 0 > /sys/class/scsi_host/host1/em_message # cat /sys/class/scsi_host/host1/em_message 1 Signed-off-by: David Milburn Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index ec2922ad2dc..788bba2b1e1 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1348,7 +1348,7 @@ static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state, writel(message[1], mmio + hpriv->em_loc+4); /* save off new led state for port/slot */ - emp->led_state = message[1]; + emp->led_state = state; /* * tell hardware to transmit the message -- GitLab From 140d6fed71a659f39f0b130b6ac8f8d28600bf60 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 24 Mar 2009 10:21:49 +0000 Subject: [PATCH 4483/4982] pata_artop: Serializing support Enable both ports on the 6210 and serialize them Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/pata_artop.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c index 07c7fae6da1..d332cfdb0f3 100644 --- a/drivers/ata/pata_artop.c +++ b/drivers/ata/pata_artop.c @@ -12,7 +12,6 @@ * performance Alessandro Zummo * * TODO - * 850 serialization once the core supports it * Investigate no_dsc on 850R * Clock detect */ @@ -29,7 +28,7 @@ #include #define DRV_NAME "pata_artop" -#define DRV_VERSION "0.4.4" +#define DRV_VERSION "0.4.5" /* * The ARTOP has 33 Mhz and "over clocked" timing tables. Until we @@ -283,6 +282,31 @@ static void artop6260_set_dmamode (struct ata_port *ap, struct ata_device *adev) pci_write_config_byte(pdev, 0x44 + ap->port_no, ultra); } +/** + * artop_6210_qc_defer - implement serialization + * @qc: command + * + * Issue commands per host on this chip. + */ + +static int artop6210_qc_defer(struct ata_queued_cmd *qc) +{ + struct ata_host *host = qc->ap->host; + struct ata_port *alt = host->ports[1 ^ qc->ap->port_no]; + int rc; + + /* First apply the usual rules */ + rc = ata_std_qc_defer(qc); + if (rc != 0) + return rc; + + /* Now apply serialization rules. Only allow a command if the + other channel state machine is idle */ + if (alt && alt->qc_active) + return ATA_DEFER_PORT; + return 0; +} + static struct scsi_host_template artop_sht = { ATA_BMDMA_SHT(DRV_NAME), }; @@ -293,6 +317,7 @@ static struct ata_port_operations artop6210_ops = { .set_piomode = artop6210_set_piomode, .set_dmamode = artop6210_set_dmamode, .prereset = artop6210_pre_reset, + .qc_defer = artop6210_qc_defer, }; static struct ata_port_operations artop6260_ops = { @@ -362,12 +387,8 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id) if (id->driver_data == 0) { /* 6210 variant */ ppi[0] = &info_6210; - ppi[1] = &ata_dummy_port_info; /* BIOS may have left us in UDMA, clear it before libata probe */ pci_write_config_byte(pdev, 0x54, 0); - /* For the moment (also lacks dsc) */ - printk(KERN_WARNING "ARTOP 6210 requires serialize functionality not yet supported by libata.\n"); - printk(KERN_WARNING "Secondary ATA ports will not be activated.\n"); } else if (id->driver_data == 1) /* 6260 */ ppi[0] = &info_626x; -- GitLab From c0f2ee34a5a0b79fd98d965ad8ae765d4639bfa5 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 24 Mar 2009 10:22:25 +0000 Subject: [PATCH 4484/4982] pata_sc1200: Activate secondary channel Implement serialize and turn on slave channel Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/pata_sc1200.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c index 36a0c359329..f49814d6fd2 100644 --- a/drivers/ata/pata_sc1200.c +++ b/drivers/ata/pata_sc1200.c @@ -2,7 +2,6 @@ * New ATA layer SC1200 driver Alan Cox * * TODO: Mode selection filtering - * TODO: Can't enable second channel until ATA core has serialize * TODO: Needs custom DMA cleanup code * * Based very heavily on @@ -178,6 +177,31 @@ static unsigned int sc1200_qc_issue(struct ata_queued_cmd *qc) return ata_sff_qc_issue(qc); } +/** + * sc1200_qc_defer - implement serialization + * @qc: command + * + * Serialize command issue on this controller. + */ + +static int sc1200_qc_defer(struct ata_queued_cmd *qc) +{ + struct ata_host *host = qc->ap->host; + struct ata_port *alt = host->ports[1 ^ qc->ap->port_no]; + int rc; + + /* First apply the usual rules */ + rc = ata_std_qc_defer(qc); + if (rc != 0) + return rc; + + /* Now apply serialization rules. Only allow a command if the + other channel state machine is idle */ + if (alt && alt->qc_active) + return ATA_DEFER_PORT; + return 0; +} + static struct scsi_host_template sc1200_sht = { ATA_BMDMA_SHT(DRV_NAME), .sg_tablesize = LIBATA_DUMB_MAX_PRD, @@ -187,6 +211,7 @@ static struct ata_port_operations sc1200_port_ops = { .inherits = &ata_bmdma_port_ops, .qc_prep = ata_sff_dumb_qc_prep, .qc_issue = sc1200_qc_issue, + .qc_defer = sc1200_qc_defer, .cable_detect = ata_cable_40wire, .set_piomode = sc1200_set_piomode, .set_dmamode = sc1200_set_dmamode, @@ -211,7 +236,7 @@ static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id) .port_ops = &sc1200_port_ops }; /* Can't enable port 2 yet, see top comments */ - const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info }; + const struct ata_port_info *ppi[] = { &info, }; return ata_pci_sff_init_one(dev, ppi, &sc1200_sht, NULL); } -- GitLab From 3d47aa8e7e7b2aa09256590388aa8dddc79280f9 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 24 Mar 2009 10:23:19 +0000 Subject: [PATCH 4485/4982] [libata] Drain data on errors If the device is signalling that there is data to drain after an error we should read the bytes out and throw them away. Without this some devices and controllers get wedged and don't recover. Based on earlier work by Mark Lord Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/libata-sff.c | 45 +++++++++++++++++++++++++++++++++++++-- drivers/ata/pata_pcmcia.c | 34 ++++++++++++++++++++++++++++- include/linux/libata.h | 3 +++ 3 files changed, 79 insertions(+), 3 deletions(-) diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index f93dc029dfd..9a10cb055ac 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -52,6 +52,7 @@ const struct ata_port_operations ata_sff_port_ops = { .softreset = ata_sff_softreset, .hardreset = sata_sff_hardreset, .postreset = ata_sff_postreset, + .drain_fifo = ata_sff_drain_fifo, .error_handler = ata_sff_error_handler, .post_internal_cmd = ata_sff_post_internal_cmd, @@ -2198,6 +2199,39 @@ void ata_sff_postreset(struct ata_link *link, unsigned int *classes) } EXPORT_SYMBOL_GPL(ata_sff_postreset); +/** + * ata_sff_drain_fifo - Stock FIFO drain logic for SFF controllers + * @qc: command + * + * Drain the FIFO and device of any stuck data following a command + * failing to complete. In some cases this is neccessary before a + * reset will recover the device. + * + */ + +void ata_sff_drain_fifo(struct ata_queued_cmd *qc) +{ + int count; + struct ata_port *ap; + + /* We only need to flush incoming data when a command was running */ + if (qc == NULL || qc->dma_dir == DMA_TO_DEVICE) + return; + + ap = qc->ap; + /* Drain up to 64K of data before we give up this recovery method */ + for (count = 0; (ap->ops->sff_check_status(ap) & ATA_DRQ) + && count < 32768; count++) + ioread16(ap->ioaddr.data_addr); + + /* Can become DEBUG later */ + if (count) + ata_port_printk(ap, KERN_DEBUG, + "drained %d bytes to clear DRQ.\n", count); + +} +EXPORT_SYMBOL_GPL(ata_sff_drain_fifo); + /** * ata_sff_error_handler - Stock error handler for BMDMA controller * @ap: port to handle error for @@ -2239,7 +2273,8 @@ void ata_sff_error_handler(struct ata_port *ap) * really a timeout event, adjust error mask and * cancel frozen state. */ - if (qc->err_mask == AC_ERR_TIMEOUT && (host_stat & ATA_DMA_ERR)) { + if (qc->err_mask == AC_ERR_TIMEOUT + && (host_stat & ATA_DMA_ERR)) { qc->err_mask = AC_ERR_HOST_BUS; thaw = 1; } @@ -2250,6 +2285,13 @@ void ata_sff_error_handler(struct ata_port *ap) ata_sff_sync(ap); /* FIXME: We don't need this */ ap->ops->sff_check_status(ap); ap->ops->sff_irq_clear(ap); + /* We *MUST* do FIFO draining before we issue a reset as several + * devices helpfully clear their internal state and will lock solid + * if we touch the data port post reset. Pass qc in case anyone wants + * to do different PIO/DMA recovery or has per command fixups + */ + if (ap->ops->drain_fifo) + ap->ops->drain_fifo(qc); spin_unlock_irqrestore(ap->lock, flags); @@ -2959,4 +3001,3 @@ out: EXPORT_SYMBOL_GPL(ata_pci_sff_init_one); #endif /* CONFIG_PCI */ - diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index a5cbcc280b2..f4d009ed50a 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c @@ -42,7 +42,7 @@ #define DRV_NAME "pata_pcmcia" -#define DRV_VERSION "0.3.3" +#define DRV_VERSION "0.3.5" /* * Private data structure to glue stuff together @@ -126,6 +126,37 @@ static unsigned int ata_data_xfer_8bit(struct ata_device *dev, return buflen; } +/** + * pcmcia_8bit_drain_fifo - Stock FIFO drain logic for SFF controllers + * @qc: command + * + * Drain the FIFO and device of any stuck data following a command + * failing to complete. In some cases this is neccessary before a + * reset will recover the device. + * + */ + +void pcmcia_8bit_drain_fifo(struct ata_queued_cmd *qc) +{ + int count; + struct ata_port *ap; + + /* We only need to flush incoming data when a command was running */ + if (qc == NULL || qc->dma_dir == DMA_TO_DEVICE) + return; + + ap = qc->ap; + + /* Drain up to 64K of data before we give up this recovery method */ + for (count = 0; (ap->ops->sff_check_status(ap) & ATA_DRQ) + && count++ < 65536;) + ioread8(ap->ioaddr.data_addr); + + if (count) + ata_port_printk(ap, KERN_WARNING, "drained %d bytes to clear DRQ.\n", + count); + +} static struct scsi_host_template pcmcia_sht = { ATA_PIO_SHT(DRV_NAME), @@ -143,6 +174,7 @@ static struct ata_port_operations pcmcia_8bit_port_ops = { .sff_data_xfer = ata_data_xfer_8bit, .cable_detect = ata_cable_40wire, .set_mode = pcmcia_set_mode_8bit, + .drain_fifo = pcmcia_8bit_drain_fifo, }; #define CS_CHECK(fn, ret) \ diff --git a/include/linux/libata.h b/include/linux/libata.h index 19af7d22a7f..3a07a32dfc2 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -836,6 +836,8 @@ struct ata_port_operations { void (*bmdma_start)(struct ata_queued_cmd *qc); void (*bmdma_stop)(struct ata_queued_cmd *qc); u8 (*bmdma_status)(struct ata_port *ap); + + void (*drain_fifo)(struct ata_queued_cmd *qc); #endif /* CONFIG_ATA_SFF */ ssize_t (*em_show)(struct ata_port *ap, char *buf); @@ -1587,6 +1589,7 @@ extern int ata_sff_softreset(struct ata_link *link, unsigned int *classes, extern int sata_sff_hardreset(struct ata_link *link, unsigned int *class, unsigned long deadline); extern void ata_sff_postreset(struct ata_link *link, unsigned int *classes); +extern void ata_sff_drain_fifo(struct ata_queued_cmd *qc); extern void ata_sff_error_handler(struct ata_port *ap); extern void ata_sff_post_internal_cmd(struct ata_queued_cmd *qc); extern int ata_sff_port_start(struct ata_port *ap); -- GitLab From 783ed5a78373253052bc61a3c5c8b9f17af4e3c6 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 24 Mar 2009 16:24:48 +0000 Subject: [PATCH 4486/4982] ipv6: Disallow binding to v4-mapped address on v6-only socket. A socket marked v6-only, can not receive or send traffic to v4-mapped addresses. Thus allowing binding to v4-mapped address on such a socket makes no sense. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/ipv6/af_inet6.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index fbf533cc9dc..7f092fa912b 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -276,6 +276,13 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) /* Check if the address belongs to the host. */ if (addr_type == IPV6_ADDR_MAPPED) { + /* Binding to v4-mapped address on a v6-only socket + * makes no sense + */ + if (np->ipv6only) { + err = -EINVAL; + goto out; + } v4addr = addr->sin6_addr.s6_addr32[3]; if (inet_addr_type(net, v4addr) != RTN_LOCAL) { err = -EADDRNOTAVAIL; -- GitLab From 0f8d3c7ac3693d7b6c731bf2159273a59bf70e12 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 24 Mar 2009 16:24:49 +0000 Subject: [PATCH 4487/4982] ipv6: Allow ipv4 wildcard binds after ipv6 address binds The IPv4 wildcard (0.0.0.0) address does not intersect in any way with explicit IPv6 addresses. These two should be permitted, but the IPv4 conflict code checks the ipv6only bit as part of the test. Since binding to an explicit IPv6 address restricts the socket to only that IPv6 address, the side-effect is that the socket behaves as v6-only. By explicitely setting ipv6only in this case, allows the 2 binds to succeed. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/ipv6/af_inet6.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 7f092fa912b..9b6a37d16fb 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -346,8 +346,11 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) goto out; } - if (addr_type != IPV6_ADDR_ANY) + if (addr_type != IPV6_ADDR_ANY) { sk->sk_userlocks |= SOCK_BINDADDR_LOCK; + if (addr_type != IPV6_ADDR_MAPPED) + np->ipv6only = 1; + } if (snum) sk->sk_userlocks |= SOCK_BINDPORT_LOCK; inet->sport = htons(inet->num); -- GitLab From 63d9950b08184e6531adceb65f64b429909cc101 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 24 Mar 2009 16:24:50 +0000 Subject: [PATCH 4488/4982] ipv6: Make v4-mapped bindings consistent with IPv4 Binding to a v4-mapped address on an AF_INET6 socket should produce the same result as binding to an IPv4 address on AF_INET socket. The two are interchangable as v4-mapped address is really a portability aid. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/ipv6/af_inet6.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 9b6a37d16fb..61f55386a23 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -276,6 +276,8 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) /* Check if the address belongs to the host. */ if (addr_type == IPV6_ADDR_MAPPED) { + int chk_addr_ret; + /* Binding to v4-mapped address on a v6-only socket * makes no sense */ @@ -283,11 +285,17 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) err = -EINVAL; goto out; } + + /* Reproduce AF_INET checks to make the bindings consitant */ v4addr = addr->sin6_addr.s6_addr32[3]; - if (inet_addr_type(net, v4addr) != RTN_LOCAL) { - err = -EADDRNOTAVAIL; + chk_addr_ret = inet_addr_type(net, v4addr); + if (!sysctl_ip_nonlocal_bind && + !(inet->freebind || inet->transparent) && + v4addr != htonl(INADDR_ANY) && + chk_addr_ret != RTN_LOCAL && + chk_addr_ret != RTN_MULTICAST && + chk_addr_ret != RTN_BROADCAST) goto out; - } } else { if (addr_type != IPV6_ADDR_ANY) { struct net_device *dev = NULL; -- GitLab From b2f5e7cd3dee2ed721bf0675e1a1ddebb849aee6 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 24 Mar 2009 16:24:51 +0000 Subject: [PATCH 4489/4982] ipv6: Fix conflict resolutions during ipv6 binding The ipv6 version of bind_conflict code calls ipv6_rcv_saddr_equal() which at times wrongly identified intersections between addresses. It particularly broke down under a few instances and caused erroneous bind conflicts. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/net/addrconf.h | 4 ++-- include/net/udp.h | 2 ++ net/ipv4/udp.c | 3 ++- net/ipv6/addrconf.c | 34 ---------------------------------- net/ipv6/udp.c | 28 ++++++++++++++++++++++++++++ 5 files changed, 34 insertions(+), 37 deletions(-) diff --git a/include/net/addrconf.h b/include/net/addrconf.h index c216de528b0..7b55ab215a6 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -88,8 +88,8 @@ extern int ipv6_dev_get_saddr(struct net *net, extern int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, unsigned char banned_flags); -extern int ipv6_rcv_saddr_equal(const struct sock *sk, - const struct sock *sk2); +extern int ipv6_rcv_saddr_equal(const struct sock *sk, + const struct sock *sk2); extern void addrconf_join_solict(struct net_device *dev, struct in6_addr *addr); extern void addrconf_leave_solict(struct inet6_dev *idev, diff --git a/include/net/udp.h b/include/net/udp.h index 90e6ce56be6..93dbe294d45 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -124,6 +124,8 @@ static inline void udp_lib_close(struct sock *sk, long timeout) sk_common_release(sk); } +extern int ipv4_rcv_saddr_equal(const struct sock *sk1, + const struct sock *sk2); extern int udp_lib_get_port(struct sock *sk, unsigned short snum, int (*)(const struct sock*,const struct sock*)); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 05b7abb99f6..ace2ac8a42f 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -222,7 +222,7 @@ fail: return error; } -static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) +int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) { struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2); @@ -1819,6 +1819,7 @@ EXPORT_SYMBOL(udp_lib_getsockopt); EXPORT_SYMBOL(udp_lib_setsockopt); EXPORT_SYMBOL(udp_poll); EXPORT_SYMBOL(udp_lib_get_port); +EXPORT_SYMBOL(ipv4_rcv_saddr_equal); #ifdef CONFIG_PROC_FS EXPORT_SYMBOL(udp_proc_register); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 8499da9e76a..a8218bc1806 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1370,40 +1370,6 @@ struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *add return ifp; } -int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) -{ - const struct in6_addr *sk_rcv_saddr6 = &inet6_sk(sk)->rcv_saddr; - const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2); - __be32 sk_rcv_saddr = inet_sk(sk)->rcv_saddr; - __be32 sk2_rcv_saddr = inet_rcv_saddr(sk2); - int sk_ipv6only = ipv6_only_sock(sk); - int sk2_ipv6only = inet_v6_ipv6only(sk2); - int addr_type = ipv6_addr_type(sk_rcv_saddr6); - int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED; - - if (!sk2_rcv_saddr && !sk_ipv6only) - return 1; - - if (addr_type2 == IPV6_ADDR_ANY && - !(sk2_ipv6only && addr_type == IPV6_ADDR_MAPPED)) - return 1; - - if (addr_type == IPV6_ADDR_ANY && - !(sk_ipv6only && addr_type2 == IPV6_ADDR_MAPPED)) - return 1; - - if (sk2_rcv_saddr6 && - ipv6_addr_equal(sk_rcv_saddr6, sk2_rcv_saddr6)) - return 1; - - if (addr_type == IPV6_ADDR_MAPPED && - !sk2_ipv6only && - (!sk2_rcv_saddr || !sk_rcv_saddr || sk_rcv_saddr == sk2_rcv_saddr)) - return 1; - - return 0; -} - /* Gets referenced address, destroys ifaddr */ static void addrconf_dad_stop(struct inet6_ifaddr *ifp) diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 84b1a296eec..6842dd2edd5 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -49,6 +49,34 @@ #include #include "udp_impl.h" +int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) +{ + const struct in6_addr *sk_rcv_saddr6 = &inet6_sk(sk)->rcv_saddr; + const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2); + int sk_ipv6only = ipv6_only_sock(sk); + int sk2_ipv6only = inet_v6_ipv6only(sk2); + int addr_type = ipv6_addr_type(sk_rcv_saddr6); + int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED; + + /* if both are mapped, treat as IPv4 */ + if (addr_type == IPV6_ADDR_MAPPED && addr_type2 == IPV6_ADDR_MAPPED) + return ipv4_rcv_saddr_equal(sk, sk2); + + if (addr_type2 == IPV6_ADDR_ANY && + !(sk2_ipv6only && addr_type == IPV6_ADDR_MAPPED)) + return 1; + + if (addr_type == IPV6_ADDR_ANY && + !(sk_ipv6only && addr_type2 == IPV6_ADDR_MAPPED)) + return 1; + + if (sk2_rcv_saddr6 && + ipv6_addr_equal(sk_rcv_saddr6, sk2_rcv_saddr6)) + return 1; + + return 0; +} + int udp_v6_get_port(struct sock *sk, unsigned short snum) { return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal); -- GitLab From c96f1732e25362d10ee7bcac1df8412a2e6b7d23 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 24 Mar 2009 10:23:46 +0000 Subject: [PATCH 4490/4982] [libata] Improve timeout handling On a timeout call a device specific handler early in the recovery so that we can complete and process successful commands which timed out due to IRQ loss or the like rather more elegantly. [Revised to exclude the timeout handling on a few devices that inherit from SFF but are not SFF enough to use the default timeout handler] Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 19 ++++++++++++++-- drivers/ata/libata-sff.c | 46 +++++++++++++++++++++++++++++++++++++- drivers/ata/pata_isapnp.c | 12 ++++++++-- drivers/ata/pdc_adma.c | 2 ++ drivers/ata/sata_mv.c | 2 ++ drivers/ata/sata_nv.c | 1 + drivers/ata/sata_promise.c | 2 ++ drivers/ata/sata_qstor.c | 1 + drivers/ata/sata_vsc.c | 3 +++ include/linux/libata.h | 2 ++ 10 files changed, 85 insertions(+), 5 deletions(-) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index ea890911d4f..01831312c36 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -547,7 +547,7 @@ void ata_scsi_error(struct Scsi_Host *host) /* For new EH, all qcs are finished in one of three ways - * normal completion, error completion, and SCSI timeout. - * Both cmpletions can race against SCSI timeout. When normal + * Both completions can race against SCSI timeout. When normal * completion wins, the qc never reaches EH. When error * completion wins, the qc has ATA_QCFLAG_FAILED set. * @@ -562,7 +562,19 @@ void ata_scsi_error(struct Scsi_Host *host) int nr_timedout = 0; spin_lock_irqsave(ap->lock, flags); - + + /* This must occur under the ap->lock as we don't want + a polled recovery to race the real interrupt handler + + The lost_interrupt handler checks for any completed but + non-notified command and completes much like an IRQ handler. + + We then fall into the error recovery code which will treat + this as if normal completion won the race */ + + if (ap->ops->lost_interrupt) + ap->ops->lost_interrupt(ap); + list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) { struct ata_queued_cmd *qc; @@ -606,6 +618,9 @@ void ata_scsi_error(struct Scsi_Host *host) ap->eh_tries = ATA_EH_MAX_TRIES; } else spin_unlock_wait(ap->lock); + + /* If we timed raced normal completion and there is nothing to + recover nr_timedout == 0 why exactly are we doing error recovery ? */ repeat: /* invoke error handler */ diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 9a10cb055ac..8332e97a9de 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -65,6 +65,8 @@ const struct ata_port_operations ata_sff_port_ops = { .sff_irq_on = ata_sff_irq_on, .sff_irq_clear = ata_sff_irq_clear, + .lost_interrupt = ata_sff_lost_interrupt, + .port_start = ata_sff_port_start, }; EXPORT_SYMBOL_GPL(ata_sff_port_ops); @@ -1647,7 +1649,7 @@ EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf); * RETURNS: * One if interrupt was handled, zero if not (shared irq). */ -inline unsigned int ata_sff_host_intr(struct ata_port *ap, +unsigned int ata_sff_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc) { struct ata_eh_info *ehi = &ap->link.eh_info; @@ -1775,6 +1777,48 @@ irqreturn_t ata_sff_interrupt(int irq, void *dev_instance) } EXPORT_SYMBOL_GPL(ata_sff_interrupt); +/** + * ata_sff_lost_interrupt - Check for an apparent lost interrupt + * @ap: port that appears to have timed out + * + * Called from the libata error handlers when the core code suspects + * an interrupt has been lost. If it has complete anything we can and + * then return. Interface must support altstatus for this faster + * recovery to occur. + * + * Locking: + * Caller holds host lock + */ + +void ata_sff_lost_interrupt(struct ata_port *ap) +{ + u8 status; + struct ata_queued_cmd *qc; + + /* Only one outstanding command per SFF channel */ + qc = ata_qc_from_tag(ap, ap->link.active_tag); + /* Check we have a live one.. */ + if (qc == NULL || !(qc->flags & ATA_QCFLAG_ACTIVE)) + return; + /* We cannot lose an interrupt on a polled command */ + if (qc->tf.flags & ATA_TFLAG_POLLING) + return; + /* See if the controller thinks it is still busy - if so the command + isn't a lost IRQ but is still in progress */ + status = ata_sff_altstatus(ap); + if (status & ATA_BUSY) + return; + + /* There was a command running, we are no longer busy and we have + no interrupt. */ + ata_port_printk(ap, KERN_WARNING, "lost interrupt (Status 0x%x)\n", + status); + /* Run the host interrupt logic as if the interrupt had not been + lost */ + ata_sff_host_intr(ap, qc); +} +EXPORT_SYMBOL_GPL(ata_sff_lost_interrupt); + /** * ata_sff_freeze - Freeze SFF controller port * @ap: port to freeze diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c index afa8f704271..4bceb8803a1 100644 --- a/drivers/ata/pata_isapnp.c +++ b/drivers/ata/pata_isapnp.c @@ -17,7 +17,7 @@ #include #define DRV_NAME "pata_isapnp" -#define DRV_VERSION "0.2.2" +#define DRV_VERSION "0.2.5" static struct scsi_host_template isapnp_sht = { ATA_PIO_SHT(DRV_NAME), @@ -28,6 +28,13 @@ static struct ata_port_operations isapnp_port_ops = { .cable_detect = ata_cable_40wire, }; +static struct ata_port_operations isapnp_noalt_port_ops = { + .inherits = &ata_sff_port_ops, + .cable_detect = ata_cable_40wire, + /* No altstatus so we don't want to use the lost interrupt poll */ + .lost_interrupt = ATA_OP_NULL, +}; + /** * isapnp_init_one - attach an isapnp interface * @idev: PnP device @@ -65,7 +72,7 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev ap = host->ports[0]; - ap->ops = &isapnp_port_ops; + ap->ops = &isapnp_noalt_port_ops; ap->pio_mask = ATA_PIO0; ap->flags |= ATA_FLAG_SLAVE_POSS; @@ -76,6 +83,7 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev pnp_port_start(idev, 1), 1); ap->ioaddr.altstatus_addr = ctl_addr; ap->ioaddr.ctl_addr = ctl_addr; + ap->ops = &isapnp_port_ops; } ata_sff_std_ports(&ap->ioaddr); diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c index c509c206a45..39588178d02 100644 --- a/drivers/ata/pdc_adma.c +++ b/drivers/ata/pdc_adma.c @@ -148,6 +148,8 @@ static struct scsi_host_template adma_ata_sht = { static struct ata_port_operations adma_ata_ops = { .inherits = &ata_sff_port_ops, + .lost_interrupt = ATA_OP_NULL, + .check_atapi_dma = adma_check_atapi_dma, .qc_prep = adma_qc_prep, .qc_issue = adma_qc_issue, diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 8a751054c8a..a377226b81c 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -646,6 +646,8 @@ static struct scsi_host_template mv6_sht = { static struct ata_port_operations mv5_ops = { .inherits = &ata_sff_port_ops, + .lost_interrupt = ATA_OP_NULL, + .qc_defer = mv_qc_defer, .qc_prep = mv_qc_prep, .qc_issue = mv_qc_issue, diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 2f523f8c27f..6cda12ba812 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -408,6 +408,7 @@ static struct scsi_host_template nv_swncq_sht = { static struct ata_port_operations nv_common_ops = { .inherits = &ata_bmdma_port_ops, + .lost_interrupt = ATA_OP_NULL, .scr_read = nv_scr_read, .scr_write = nv_scr_write, }; diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 3ad2b886363..b1fd7d62071 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -176,7 +176,9 @@ static const struct ata_port_operations pdc_common_ops = { .check_atapi_dma = pdc_check_atapi_dma, .qc_prep = pdc_qc_prep, .qc_issue = pdc_qc_issue, + .sff_irq_clear = pdc_irq_clear, + .lost_interrupt = ATA_OP_NULL, .post_internal_cmd = pdc_post_internal_cmd, .error_handler = pdc_error_handler, diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c index 7112d89fd9f..c3936d35cda 100644 --- a/drivers/ata/sata_qstor.c +++ b/drivers/ata/sata_qstor.c @@ -147,6 +147,7 @@ static struct ata_port_operations qs_ata_ops = { .softreset = ATA_OP_NULL, .error_handler = qs_error_handler, .post_internal_cmd = ATA_OP_NULL, + .lost_interrupt = ATA_OP_NULL, .scr_read = qs_scr_read, .scr_write = qs_scr_write, diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c index ef211f333d7..ed70bd28fa2 100644 --- a/drivers/ata/sata_vsc.c +++ b/drivers/ata/sata_vsc.c @@ -308,6 +308,9 @@ static struct scsi_host_template vsc_sata_sht = { static struct ata_port_operations vsc_sata_ops = { .inherits = &ata_bmdma_port_ops, + /* The IRQ handling is not quite standard SFF behaviour so we + cannot use the default lost interrupt handler */ + .lost_interrupt = ATA_OP_NULL, .sff_tf_load = vsc_sata_tf_load, .sff_tf_read = vsc_sata_tf_read, .freeze = vsc_freeze, diff --git a/include/linux/libata.h b/include/linux/libata.h index 3a07a32dfc2..76262d83656 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -795,6 +795,7 @@ struct ata_port_operations { ata_reset_fn_t pmp_hardreset; ata_postreset_fn_t pmp_postreset; void (*error_handler)(struct ata_port *ap); + void (*lost_interrupt)(struct ata_port *ap); void (*post_internal_cmd)(struct ata_queued_cmd *qc); /* @@ -1577,6 +1578,7 @@ extern bool ata_sff_qc_fill_rtf(struct ata_queued_cmd *qc); extern unsigned int ata_sff_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); extern irqreturn_t ata_sff_interrupt(int irq, void *dev_instance); +extern void ata_sff_lost_interrupt(struct ata_port *ap); extern void ata_sff_freeze(struct ata_port *ap); extern void ata_sff_thaw(struct ata_port *ap); extern int ata_sff_prereset(struct ata_link *link, unsigned long deadline); -- GitLab From d1fbe04eee32ed2642cff139b8592866f1d43f41 Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Tue, 24 Mar 2009 20:44:18 -0700 Subject: [PATCH 4491/4982] RDMA/cxgb3: Enforce required firmware The cxgb3 NIC driver can handle more firmware versions than iw_cxgb3, and since commit 8207befa ("cxgb3: untie strict FW matching") cxgb3 will load with firmware versions that iw_cxgb3 can't handle. The FW major number indicates a specific interface between the FW and iw_cxgb3. Thus if the major number of the running firmware does not match the required version compiled into iw_cxgb3, then iw_cxgb3 must not register that device. Signed-off-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/hw/cxgb3/cxio_hal.c | 17 +++++++++++++++++ drivers/infiniband/hw/cxgb3/cxio_hal.h | 3 +++ 2 files changed, 20 insertions(+) diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c index c2740e790f7..d4d7204c11e 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_hal.c +++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c @@ -938,6 +938,23 @@ int cxio_rdev_open(struct cxio_rdev *rdev_p) if (!rdev_p->t3cdev_p) rdev_p->t3cdev_p = dev2t3cdev(netdev_p); rdev_p->t3cdev_p->ulp = (void *) rdev_p; + + err = rdev_p->t3cdev_p->ctl(rdev_p->t3cdev_p, GET_EMBEDDED_INFO, + &(rdev_p->fw_info)); + if (err) { + printk(KERN_ERR "%s t3cdev_p(%p)->ctl returned error %d.\n", + __func__, rdev_p->t3cdev_p, err); + goto err1; + } + if (G_FW_VERSION_MAJOR(rdev_p->fw_info.fw_vers) != CXIO_FW_MAJ) { + printk(KERN_ERR MOD "fatal firmware version mismatch: " + "need version %u but adapter has version %u\n", + CXIO_FW_MAJ, + G_FW_VERSION_MAJOR(rdev_p->fw_info.fw_vers)); + err = -EINVAL; + goto err1; + } + err = rdev_p->t3cdev_p->ctl(rdev_p->t3cdev_p, RDMA_GET_PARAMS, &(rdev_p->rnic_info)); if (err) { diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.h b/drivers/infiniband/hw/cxgb3/cxio_hal.h index 656fe47bc84..e44dc228947 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_hal.h +++ b/drivers/infiniband/hw/cxgb3/cxio_hal.h @@ -61,6 +61,8 @@ #define T3_MAX_DEV_NAME_LEN 32 +#define CXIO_FW_MAJ 7 + struct cxio_hal_ctrl_qp { u32 wptr; u32 rptr; @@ -108,6 +110,7 @@ struct cxio_rdev { struct gen_pool *pbl_pool; struct gen_pool *rqt_pool; struct list_head entry; + struct ch_embedded_info fw_info; }; static inline int cxio_num_stags(struct cxio_rdev *rdev_p) -- GitLab From bef28b11597a4da9ef3b8a51776b8cb14b427e5e Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Tue, 24 Mar 2009 23:28:02 -0700 Subject: [PATCH 4492/4982] e1000e: add support for 82574 device ID 0x10F6 Add device ID for a new variant of the 82574 adapter. Signed-off-by: Bruce Allan Acked-by: John Ronciak Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/hw.h | 1 + drivers/net/e1000e/netdev.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index 11a2f203a01..d8b82296f41 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -339,6 +339,7 @@ enum e1e_registers { #define E1000_DEV_ID_82573E_IAMT 0x108C #define E1000_DEV_ID_82573L 0x109A #define E1000_DEV_ID_82574L 0x10D3 +#define E1000_DEV_ID_82574LA 0x10F6 #define E1000_DEV_ID_82583V 0x150C #define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096 diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index f388a017932..15424bad569 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -5130,6 +5130,7 @@ static struct pci_device_id e1000_pci_tbl[] = { { PCI_VDEVICE(INTEL, E1000_DEV_ID_82573L), board_82573 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82574L), board_82574 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82574LA), board_82574 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82583V), board_82583 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_COPPER_DPT), -- GitLab From 47cb035560a41bd1bd3db506eeab93088815203e Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Tue, 24 Mar 2009 23:31:22 -0700 Subject: [PATCH 4493/4982] drivers/net/ax88796.c: take IRQ flags from platform_device This patch adds support to the ax88796 ethernet driver to take IRQ flags given by the platform_device definition. Signed-off-by: Daniel Mack Signed-off-by: David S. Miller --- drivers/net/ax88796.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c index a4eb6c40678..e7c9748437d 100644 --- a/drivers/net/ax88796.c +++ b/drivers/net/ax88796.c @@ -93,6 +93,7 @@ struct ax_device { unsigned char running; unsigned char resume_open; + unsigned int irqflags; u32 reg_offsets[0x20]; }; @@ -474,7 +475,8 @@ static int ax_open(struct net_device *dev) dev_dbg(&ax->dev->dev, "%s: open\n", dev->name); - ret = request_irq(dev->irq, ax_ei_interrupt, 0, dev->name, dev); + ret = request_irq(dev->irq, ax_ei_interrupt, ax->irqflags, + dev->name, dev); if (ret) return ret; @@ -829,7 +831,7 @@ static int ax_probe(struct platform_device *pdev) struct ax_device *ax; struct resource *res; size_t size; - int ret; + int ret = 0; dev = ax__alloc_ei_netdev(sizeof(struct ax_device)); if (dev == NULL) @@ -850,12 +852,14 @@ static int ax_probe(struct platform_device *pdev) /* find the platform resources */ - ret = platform_get_irq(pdev, 0); - if (ret < 0) { + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (res == NULL) { dev_err(&pdev->dev, "no IRQ specified\n"); goto exit_mem; } - dev->irq = ret; + + dev->irq = res->start; + ax->irqflags = res->flags & IRQF_TRIGGER_MASK; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { -- GitLab From 67fca028f1535e510689d2e444b0289e264e05c1 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Tue, 24 Mar 2009 23:32:03 -0700 Subject: [PATCH 4494/4982] ax88796: Add method to take MAC from platform data Implement a way to provide the MAC address for ax88796 devices from their platform data. Boards might decide to set the address programmatically, taken from boot tags or other sources. Signed-off-by: Daniel Mack Signed-off-by: David S. Miller --- drivers/net/ax88796.c | 17 ++++++++++++----- include/net/ax88796.h | 13 ++++++++----- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c index e7c9748437d..62d9c9cc567 100644 --- a/drivers/net/ax88796.c +++ b/drivers/net/ax88796.c @@ -733,12 +733,19 @@ static int ax_init_dev(struct net_device *dev, int first_init) /* load the mac-address from the device if this is the * first time we've initialised */ - if (first_init && ax->plat->flags & AXFLG_MAC_FROMDEV) { - ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP, - ei_local->mem + E8390_CMD); /* 0x61 */ + if (first_init) { + if (ax->plat->flags & AXFLG_MAC_FROMDEV) { + ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP, + ei_local->mem + E8390_CMD); /* 0x61 */ + for (i = 0; i < ETHER_ADDR_LEN; i++) + dev->dev_addr[i] = + ei_inb(ioaddr + EN1_PHYS_SHIFT(i)); + } - for (i = 0 ; i < ETHER_ADDR_LEN ; i++) - dev->dev_addr[i] = ei_inb(ioaddr + EN1_PHYS_SHIFT(i)); + if ((ax->plat->flags & AXFLG_MAC_FROMPLATFORM) && + ax->plat->mac_addr) + memcpy(dev->dev_addr, ax->plat->mac_addr, + ETHER_ADDR_LEN); } ax_reset_8390(dev); diff --git a/include/net/ax88796.h b/include/net/ax88796.h index 51329dae44e..b9a3beca0ce 100644 --- a/include/net/ax88796.h +++ b/include/net/ax88796.h @@ -15,14 +15,17 @@ #define AXFLG_HAS_EEPROM (1<<0) #define AXFLG_MAC_FROMDEV (1<<1) /* device already has MAC */ #define AXFLG_HAS_93CX6 (1<<2) /* use eeprom_93cx6 driver */ +#define AXFLG_MAC_FROMPLATFORM (1<<3) /* MAC given by platform data */ struct ax_plat_data { unsigned int flags; - unsigned char wordlength; /* 1 or 2 */ - unsigned char dcr_val; /* default value for DCR */ - unsigned char rcr_val; /* default value for RCR */ - unsigned char gpoc_val; /* default value for GPOC */ - u32 *reg_offsets; /* register offsets */ + unsigned char wordlength; /* 1 or 2 */ + unsigned char dcr_val; /* default value for DCR */ + unsigned char rcr_val; /* default value for RCR */ + unsigned char gpoc_val; /* default value for GPOC */ + u32 *reg_offsets; /* register offsets */ + u8 *mac_addr; /* MAC addr (only used when + AXFLG_MAC_FROMPLATFORM is used */ }; #endif /* __NET_AX88796_PLAT_H */ -- GitLab From 23d12e2bdd4f73d90c8c29674c531aa45eecf27f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 25 Mar 2009 00:03:16 -0700 Subject: [PATCH 4495/4982] rndis_wlan: Fix build with netdev_ops compat disabled. Instead of storing a private ->set_multicast_list, just have a private netdev ops. Signed-off-by: David S. Miller --- drivers/net/wireless/rndis_wlan.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 82af21eeb59..db91db77650 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -2524,6 +2524,17 @@ static int bcm4320_early_init(struct usbnet *usbdev) return 0; } +/* same as rndis_netdev_ops but with local multicast handler */ +static const struct net_device_ops rndis_wext_netdev_ops = { + .ndo_open = usbnet_open, + .ndo_stop = usbnet_stop, + .ndo_start_xmit = usbnet_start_xmit, + .ndo_tx_timeout = usbnet_tx_timeout, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_multicast_list = rndis_wext_set_multicast_list, +}; + static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf) { @@ -2559,7 +2570,8 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf) * rndis_host wants to avoid all OID as much as possible * so do promisc/multicast handling in rndis_wext. */ - usbdev->net->set_multicast_list = rndis_wext_set_multicast_list; + usbdev->net->netdev_ops = &rndis_wext_netdev_ops; + tmp = RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_BROADCAST; retval = rndis_set_oid(usbdev, OID_GEN_CURRENT_PACKET_FILTER, &tmp, sizeof(tmp)); -- GitLab From 7f6d95e7bd82b38e669a43a2d2d410d0b5318684 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 20:57:14 +0000 Subject: [PATCH 4496/4982] qeth: struct device - replace bus_id with dev_name(), dev_set_name() Cc: Martin Schwidefsky Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers Signed-off-by: Heiko Carstens Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/qeth_l3_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 3d04920b9bb..0dcc036d34a 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1038,7 +1038,7 @@ static int qeth_l3_setadapter_parms(struct qeth_card *card) rc = qeth_query_setadapterparms(card); if (rc) { QETH_DBF_MESSAGE(2, "%s couldn't set adapter parameters: " - "0x%x\n", card->gdev->dev.bus_id, rc); + "0x%x\n", dev_name(&card->gdev->dev), rc); return rc; } if (qeth_adp_supported(card, IPA_SETADP_ALTER_MAC_ADDRESS)) { -- GitLab From f61a0d0538ca62547a127fd270d9f3c6e713027f Mon Sep 17 00:00:00 2001 From: Frank Blaschka Date: Tue, 24 Mar 2009 20:57:15 +0000 Subject: [PATCH 4497/4982] qeth: add statistics for tx csum Add statistics counter for software tx checksumming. Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 1 + drivers/s390/net/qeth_core_main.c | 2 ++ drivers/s390/net/qeth_l2_main.c | 5 ++++- drivers/s390/net/qeth_l3_main.c | 5 ++++- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index e0c45574b0c..fd34f63dc23 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -134,6 +134,7 @@ struct qeth_perf_stats { unsigned int sg_skbs_rx; unsigned int sg_frags_rx; unsigned int sg_alloc_page_rx; + unsigned int tx_csum; }; /* Routing stuff */ diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index d1b5bebea7f..1a361b3bf62 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -4327,6 +4327,7 @@ static struct { /* 30 */{"tx count"}, {"tx do_QDIO time"}, {"tx do_QDIO count"}, + {"tx csum"}, }; int qeth_core_get_stats_count(struct net_device *dev) @@ -4378,6 +4379,7 @@ void qeth_core_get_ethtool_stats(struct net_device *dev, data[30] = card->perf_stats.outbound_cnt; data[31] = card->perf_stats.outbound_do_qdio_time; data[32] = card->perf_stats.outbound_do_qdio_cnt; + data[33] = card->perf_stats.tx_csum; } EXPORT_SYMBOL_GPL(qeth_core_get_ethtool_stats); diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 07ab8a5c1c4..7632d120884 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -707,8 +707,11 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) } if ((large_send == QETH_LARGE_SEND_NO) && - (skb->ip_summed == CHECKSUM_PARTIAL)) + (skb->ip_summed == CHECKSUM_PARTIAL)) { qeth_tx_csum(new_skb); + if (card->options.performance_stats) + card->perf_stats.tx_csum++; + } if (card->info.type != QETH_CARD_TYPE_IQD) rc = qeth_do_send_packet(card, queue, new_skb, hdr, diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 0dcc036d34a..fea50bdc8f4 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -2711,8 +2711,11 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) } if ((large_send == QETH_LARGE_SEND_NO) && - (new_skb->ip_summed == CHECKSUM_PARTIAL)) + (new_skb->ip_summed == CHECKSUM_PARTIAL)) { qeth_tx_csum(new_skb); + if (card->options.performance_stats) + card->perf_stats.tx_csum++; + } if (card->info.type != QETH_CARD_TYPE_IQD) rc = qeth_do_send_packet(card, queue, new_skb, hdr, -- GitLab From 64ef8957986f6a04f61e7c95fa6ffeb3a86a6661 Mon Sep 17 00:00:00 2001 From: Frank Blaschka Date: Tue, 24 Mar 2009 20:57:16 +0000 Subject: [PATCH 4498/4982] qeth: remove EDDP Performance measurements showed EDDP does not lower CPU costs but increase them. So we dump out EDDP code from qeth driver. Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/Makefile | 2 +- drivers/s390/net/qeth_core.h | 7 +- drivers/s390/net/qeth_core_main.c | 99 +---- drivers/s390/net/qeth_core_offl.c | 699 ------------------------------ drivers/s390/net/qeth_core_offl.h | 76 ---- drivers/s390/net/qeth_core_sys.c | 4 - drivers/s390/net/qeth_l2_main.c | 81 +--- drivers/s390/net/qeth_l3_main.c | 123 ++++-- 8 files changed, 111 insertions(+), 980 deletions(-) diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile index 6382c04d2bd..96eddb3b1d0 100644 --- a/drivers/s390/net/Makefile +++ b/drivers/s390/net/Makefile @@ -8,7 +8,7 @@ obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o obj-$(CONFIG_SMSGIUCV) += smsgiucv.o obj-$(CONFIG_LCS) += lcs.o cu3088.o obj-$(CONFIG_CLAW) += claw.o cu3088.o -qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o qeth_core_offl.o +qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o obj-$(CONFIG_QETH) += qeth.o qeth_l2-y += qeth_l2_main.o obj-$(CONFIG_QETH_L2) += qeth_l2.o diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index fd34f63dc23..447e1d19581 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -404,7 +404,6 @@ struct qeth_qdio_q { /* possible types of qeth large_send support */ enum qeth_large_send_types { QETH_LARGE_SEND_NO, - QETH_LARGE_SEND_EDDP, QETH_LARGE_SEND_TSO, }; @@ -839,11 +838,9 @@ int qeth_get_cast_type(struct qeth_card *, struct sk_buff *); int qeth_get_priority_queue(struct qeth_card *, struct sk_buff *, int, int); int qeth_get_elements_no(struct qeth_card *, void *, struct sk_buff *, int); int qeth_do_send_packet_fast(struct qeth_card *, struct qeth_qdio_out_q *, - struct sk_buff *, struct qeth_hdr *, int, - struct qeth_eddp_context *, int, int); + struct sk_buff *, struct qeth_hdr *, int, int, int); int qeth_do_send_packet(struct qeth_card *, struct qeth_qdio_out_q *, - struct sk_buff *, struct qeth_hdr *, - int, struct qeth_eddp_context *); + struct sk_buff *, struct qeth_hdr *, int); int qeth_core_get_stats_count(struct net_device *); void qeth_core_get_ethtool_stats(struct net_device *, struct ethtool_stats *, u64 *); diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 1a361b3bf62..1b7b08e791a 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -26,7 +25,6 @@ #include #include "qeth_core.h" -#include "qeth_core_offl.h" struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS] = { /* define dbf - Name, Pages, Areas, Maxlen, Level, View, Handle */ @@ -285,17 +283,6 @@ int qeth_set_large_send(struct qeth_card *card, netif_tx_disable(card->dev); card->options.large_send = type; switch (card->options.large_send) { - case QETH_LARGE_SEND_EDDP: - if (card->info.type != QETH_CARD_TYPE_IQD) { - card->dev->features |= NETIF_F_TSO | NETIF_F_SG | - NETIF_F_HW_CSUM; - } else { - card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | - NETIF_F_HW_CSUM); - card->options.large_send = QETH_LARGE_SEND_NO; - rc = -EOPNOTSUPP; - } - break; case QETH_LARGE_SEND_TSO: if (qeth_is_supported(card, IPA_OUTBOUND_TSO)) { card->dev->features |= NETIF_F_TSO | NETIF_F_SG | @@ -956,7 +943,6 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, dev_kfree_skb_any(skb); skb = skb_dequeue(&buf->skb_list); } - qeth_eddp_buf_release_contexts(buf); for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(queue->card); ++i) { if (buf->buffer->element[i].addr && buf->is_header[i]) kmem_cache_free(qeth_core_header_cache, @@ -3187,11 +3173,9 @@ static inline int qeth_fill_buffer(struct qeth_qdio_out_q *queue, int qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue, struct sk_buff *skb, struct qeth_hdr *hdr, int elements_needed, - struct qeth_eddp_context *ctx, int offset, int hd_len) + int offset, int hd_len) { struct qeth_qdio_out_buffer *buffer; - int buffers_needed = 0; - int flush_cnt = 0; int index; /* spin until we get the queue ... */ @@ -3206,27 +3190,11 @@ int qeth_do_send_packet_fast(struct qeth_card *card, */ if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) goto out; - if (ctx == NULL) - queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % + queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % QDIO_MAX_BUFFERS_PER_Q; - else { - buffers_needed = qeth_eddp_check_buffers_for_context(queue, - ctx); - if (buffers_needed < 0) - goto out; - queue->next_buf_to_fill = - (queue->next_buf_to_fill + buffers_needed) % - QDIO_MAX_BUFFERS_PER_Q; - } atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); - if (ctx == NULL) { - qeth_fill_buffer(queue, buffer, skb, hdr, offset, hd_len); - qeth_flush_buffers(queue, index, 1); - } else { - flush_cnt = qeth_eddp_fill_buffer(queue, ctx, index); - WARN_ON(buffers_needed != flush_cnt); - qeth_flush_buffers(queue, index, flush_cnt); - } + qeth_fill_buffer(queue, buffer, skb, hdr, offset, hd_len); + qeth_flush_buffers(queue, index, 1); return 0; out: atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); @@ -3236,7 +3204,7 @@ EXPORT_SYMBOL_GPL(qeth_do_send_packet_fast); int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, struct sk_buff *skb, struct qeth_hdr *hdr, - int elements_needed, struct qeth_eddp_context *ctx) + int elements_needed) { struct qeth_qdio_out_buffer *buffer; int start_index; @@ -3262,53 +3230,32 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, qeth_switch_to_packing_if_needed(queue); if (queue->do_pack) { do_pack = 1; - if (ctx == NULL) { - /* does packet fit in current buffer? */ - if ((QETH_MAX_BUFFER_ELEMENTS(card) - - buffer->next_element_to_fill) < elements_needed) { - /* ... no -> set state PRIMED */ - atomic_set(&buffer->state, - QETH_QDIO_BUF_PRIMED); - flush_count++; - queue->next_buf_to_fill = - (queue->next_buf_to_fill + 1) % - QDIO_MAX_BUFFERS_PER_Q; - buffer = &queue->bufs[queue->next_buf_to_fill]; - /* we did a step forward, so check buffer state - * again */ - if (atomic_read(&buffer->state) != - QETH_QDIO_BUF_EMPTY){ - qeth_flush_buffers(queue, start_index, + /* does packet fit in current buffer? */ + if ((QETH_MAX_BUFFER_ELEMENTS(card) - + buffer->next_element_to_fill) < elements_needed) { + /* ... no -> set state PRIMED */ + atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED); + flush_count++; + queue->next_buf_to_fill = + (queue->next_buf_to_fill + 1) % + QDIO_MAX_BUFFERS_PER_Q; + buffer = &queue->bufs[queue->next_buf_to_fill]; + /* we did a step forward, so check buffer state + * again */ + if (atomic_read(&buffer->state) != + QETH_QDIO_BUF_EMPTY) { + qeth_flush_buffers(queue, start_index, flush_count); - atomic_set(&queue->state, + atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); - return -EBUSY; - } - } - } else { - /* check if we have enough elements (including following - * free buffers) to handle eddp context */ - if (qeth_eddp_check_buffers_for_context(queue, ctx) - < 0) { - rc = -EBUSY; - goto out; + return -EBUSY; } } } - if (ctx == NULL) - tmp = qeth_fill_buffer(queue, buffer, skb, hdr, -1, 0); - else { - tmp = qeth_eddp_fill_buffer(queue, ctx, - queue->next_buf_to_fill); - if (tmp < 0) { - rc = -EBUSY; - goto out; - } - } + tmp = qeth_fill_buffer(queue, buffer, skb, hdr, -1, 0); queue->next_buf_to_fill = (queue->next_buf_to_fill + tmp) % QDIO_MAX_BUFFERS_PER_Q; flush_count += tmp; -out: if (flush_count) qeth_flush_buffers(queue, start_index, flush_count); else if (!atomic_read(&queue->set_pci_flags_count)) diff --git a/drivers/s390/net/qeth_core_offl.c b/drivers/s390/net/qeth_core_offl.c index 4080126ca48..e69de29bb2d 100644 --- a/drivers/s390/net/qeth_core_offl.c +++ b/drivers/s390/net/qeth_core_offl.c @@ -1,699 +0,0 @@ -/* - * drivers/s390/net/qeth_core_offl.c - * - * Copyright IBM Corp. 2007 - * Author(s): Thomas Spatzier , - * Frank Blaschka - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "qeth_core.h" -#include "qeth_core_mpc.h" -#include "qeth_core_offl.h" - -int qeth_eddp_check_buffers_for_context(struct qeth_qdio_out_q *queue, - struct qeth_eddp_context *ctx) -{ - int index = queue->next_buf_to_fill; - int elements_needed = ctx->num_elements; - int elements_in_buffer; - int skbs_in_buffer; - int buffers_needed = 0; - - QETH_DBF_TEXT(TRACE, 5, "eddpcbfc"); - while (elements_needed > 0) { - buffers_needed++; - if (atomic_read(&queue->bufs[index].state) != - QETH_QDIO_BUF_EMPTY) - return -EBUSY; - - elements_in_buffer = QETH_MAX_BUFFER_ELEMENTS(queue->card) - - queue->bufs[index].next_element_to_fill; - skbs_in_buffer = elements_in_buffer / ctx->elements_per_skb; - elements_needed -= skbs_in_buffer * ctx->elements_per_skb; - index = (index + 1) % QDIO_MAX_BUFFERS_PER_Q; - } - return buffers_needed; -} - -static void qeth_eddp_free_context(struct qeth_eddp_context *ctx) -{ - int i; - - QETH_DBF_TEXT(TRACE, 5, "eddpfctx"); - for (i = 0; i < ctx->num_pages; ++i) - free_page((unsigned long)ctx->pages[i]); - kfree(ctx->pages); - kfree(ctx->elements); - kfree(ctx); -} - - -static void qeth_eddp_get_context(struct qeth_eddp_context *ctx) -{ - atomic_inc(&ctx->refcnt); -} - -void qeth_eddp_put_context(struct qeth_eddp_context *ctx) -{ - if (atomic_dec_return(&ctx->refcnt) == 0) - qeth_eddp_free_context(ctx); -} -EXPORT_SYMBOL_GPL(qeth_eddp_put_context); - -void qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *buf) -{ - struct qeth_eddp_context_reference *ref; - - QETH_DBF_TEXT(TRACE, 6, "eddprctx"); - while (!list_empty(&buf->ctx_list)) { - ref = list_entry(buf->ctx_list.next, - struct qeth_eddp_context_reference, list); - qeth_eddp_put_context(ref->ctx); - list_del(&ref->list); - kfree(ref); - } -} - -static int qeth_eddp_buf_ref_context(struct qeth_qdio_out_buffer *buf, - struct qeth_eddp_context *ctx) -{ - struct qeth_eddp_context_reference *ref; - - QETH_DBF_TEXT(TRACE, 6, "eddprfcx"); - ref = kmalloc(sizeof(struct qeth_eddp_context_reference), GFP_ATOMIC); - if (ref == NULL) - return -ENOMEM; - qeth_eddp_get_context(ctx); - ref->ctx = ctx; - list_add_tail(&ref->list, &buf->ctx_list); - return 0; -} - -int qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue, - struct qeth_eddp_context *ctx, int index) -{ - struct qeth_qdio_out_buffer *buf = NULL; - struct qdio_buffer *buffer; - int elements = ctx->num_elements; - int element = 0; - int flush_cnt = 0; - int must_refcnt = 1; - int i; - - QETH_DBF_TEXT(TRACE, 5, "eddpfibu"); - while (elements > 0) { - buf = &queue->bufs[index]; - if (atomic_read(&buf->state) != QETH_QDIO_BUF_EMPTY) { - /* normally this should not happen since we checked for - * available elements in qeth_check_elements_for_context - */ - if (element == 0) - return -EBUSY; - else { - QETH_DBF_MESSAGE(2, "could only partially fill" - "eddp buffer!\n"); - goto out; - } - } - /* check if the whole next skb fits into current buffer */ - if ((QETH_MAX_BUFFER_ELEMENTS(queue->card) - - buf->next_element_to_fill) - < ctx->elements_per_skb){ - /* no -> go to next buffer */ - atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED); - index = (index + 1) % QDIO_MAX_BUFFERS_PER_Q; - flush_cnt++; - /* new buffer, so we have to add ctx to buffer'ctx_list - * and increment ctx's refcnt */ - must_refcnt = 1; - continue; - } - if (must_refcnt) { - must_refcnt = 0; - if (qeth_eddp_buf_ref_context(buf, ctx)) { - goto out_check; - } - } - buffer = buf->buffer; - /* fill one skb into buffer */ - for (i = 0; i < ctx->elements_per_skb; ++i) { - if (ctx->elements[element].length != 0) { - buffer->element[buf->next_element_to_fill]. - addr = ctx->elements[element].addr; - buffer->element[buf->next_element_to_fill]. - length = ctx->elements[element].length; - buffer->element[buf->next_element_to_fill]. - flags = ctx->elements[element].flags; - buf->next_element_to_fill++; - } - element++; - elements--; - } - } -out_check: - if (!queue->do_pack) { - QETH_DBF_TEXT(TRACE, 6, "fillbfnp"); - /* set state to PRIMED -> will be flushed */ - if (buf->next_element_to_fill > 0) { - atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED); - flush_cnt++; - } - } else { - if (queue->card->options.performance_stats) - queue->card->perf_stats.skbs_sent_pack++; - QETH_DBF_TEXT(TRACE, 6, "fillbfpa"); - if (buf->next_element_to_fill >= - QETH_MAX_BUFFER_ELEMENTS(queue->card)) { - /* - * packed buffer if full -> set state PRIMED - * -> will be flushed - */ - atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED); - flush_cnt++; - } - } -out: - return flush_cnt; -} - -static void qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx, - struct qeth_eddp_data *eddp, int data_len) -{ - u8 *page; - int page_remainder; - int page_offset; - int pkt_len; - struct qeth_eddp_element *element; - - QETH_DBF_TEXT(TRACE, 5, "eddpcrsh"); - page = ctx->pages[ctx->offset >> PAGE_SHIFT]; - page_offset = ctx->offset % PAGE_SIZE; - element = &ctx->elements[ctx->num_elements]; - pkt_len = eddp->nhl + eddp->thl + data_len; - /* FIXME: layer2 and VLAN !!! */ - if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) - pkt_len += ETH_HLEN; - if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) - pkt_len += VLAN_HLEN; - /* does complete packet fit in current page ? */ - page_remainder = PAGE_SIZE - page_offset; - if (page_remainder < (sizeof(struct qeth_hdr) + pkt_len)) { - /* no -> go to start of next page */ - ctx->offset += page_remainder; - page = ctx->pages[ctx->offset >> PAGE_SHIFT]; - page_offset = 0; - } - memcpy(page + page_offset, &eddp->qh, sizeof(struct qeth_hdr)); - element->addr = page + page_offset; - element->length = sizeof(struct qeth_hdr); - ctx->offset += sizeof(struct qeth_hdr); - page_offset += sizeof(struct qeth_hdr); - /* add mac header (?) */ - if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) { - memcpy(page + page_offset, &eddp->mac, ETH_HLEN); - element->length += ETH_HLEN; - ctx->offset += ETH_HLEN; - page_offset += ETH_HLEN; - } - /* add VLAN tag */ - if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) { - memcpy(page + page_offset, &eddp->vlan, VLAN_HLEN); - element->length += VLAN_HLEN; - ctx->offset += VLAN_HLEN; - page_offset += VLAN_HLEN; - } - /* add network header */ - memcpy(page + page_offset, (u8 *)&eddp->nh, eddp->nhl); - element->length += eddp->nhl; - eddp->nh_in_ctx = page + page_offset; - ctx->offset += eddp->nhl; - page_offset += eddp->nhl; - /* add transport header */ - memcpy(page + page_offset, (u8 *)&eddp->th, eddp->thl); - element->length += eddp->thl; - eddp->th_in_ctx = page + page_offset; - ctx->offset += eddp->thl; -} - -static void qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, - int len, __wsum *hcsum) -{ - struct skb_frag_struct *frag; - int left_in_frag; - int copy_len; - u8 *src; - - QETH_DBF_TEXT(TRACE, 5, "eddpcdtc"); - if (skb_shinfo(eddp->skb)->nr_frags == 0) { - skb_copy_from_linear_data_offset(eddp->skb, eddp->skb_offset, - dst, len); - *hcsum = csum_partial(eddp->skb->data + eddp->skb_offset, len, - *hcsum); - eddp->skb_offset += len; - } else { - while (len > 0) { - if (eddp->frag < 0) { - /* we're in skb->data */ - left_in_frag = (eddp->skb->len - - eddp->skb->data_len) - - eddp->skb_offset; - src = eddp->skb->data + eddp->skb_offset; - } else { - frag = &skb_shinfo(eddp->skb)->frags[ - eddp->frag]; - left_in_frag = frag->size - eddp->frag_offset; - src = (u8 *)((page_to_pfn(frag->page) << - PAGE_SHIFT) + frag->page_offset + - eddp->frag_offset); - } - if (left_in_frag <= 0) { - eddp->frag++; - eddp->frag_offset = 0; - continue; - } - copy_len = min(left_in_frag, len); - memcpy(dst, src, copy_len); - *hcsum = csum_partial(src, copy_len, *hcsum); - dst += copy_len; - eddp->frag_offset += copy_len; - eddp->skb_offset += copy_len; - len -= copy_len; - } - } -} - -static void qeth_eddp_create_segment_data_tcp(struct qeth_eddp_context *ctx, - struct qeth_eddp_data *eddp, int data_len, __wsum hcsum) -{ - u8 *page; - int page_remainder; - int page_offset; - struct qeth_eddp_element *element; - int first_lap = 1; - - QETH_DBF_TEXT(TRACE, 5, "eddpcsdt"); - page = ctx->pages[ctx->offset >> PAGE_SHIFT]; - page_offset = ctx->offset % PAGE_SIZE; - element = &ctx->elements[ctx->num_elements]; - while (data_len) { - page_remainder = PAGE_SIZE - page_offset; - if (page_remainder < data_len) { - qeth_eddp_copy_data_tcp(page + page_offset, eddp, - page_remainder, &hcsum); - element->length += page_remainder; - if (first_lap) - element->flags = SBAL_FLAGS_FIRST_FRAG; - else - element->flags = SBAL_FLAGS_MIDDLE_FRAG; - ctx->num_elements++; - element++; - data_len -= page_remainder; - ctx->offset += page_remainder; - page = ctx->pages[ctx->offset >> PAGE_SHIFT]; - page_offset = 0; - element->addr = page + page_offset; - } else { - qeth_eddp_copy_data_tcp(page + page_offset, eddp, - data_len, &hcsum); - element->length += data_len; - if (!first_lap) - element->flags = SBAL_FLAGS_LAST_FRAG; - ctx->num_elements++; - ctx->offset += data_len; - data_len = 0; - } - first_lap = 0; - } - ((struct tcphdr *)eddp->th_in_ctx)->check = csum_fold(hcsum); -} - -static __wsum qeth_eddp_check_tcp4_hdr(struct qeth_eddp_data *eddp, - int data_len) -{ - __wsum phcsum; /* pseudo header checksum */ - - QETH_DBF_TEXT(TRACE, 5, "eddpckt4"); - eddp->th.tcp.h.check = 0; - /* compute pseudo header checksum */ - phcsum = csum_tcpudp_nofold(eddp->nh.ip4.h.saddr, eddp->nh.ip4.h.daddr, - eddp->thl + data_len, IPPROTO_TCP, 0); - /* compute checksum of tcp header */ - return csum_partial(&eddp->th, eddp->thl, phcsum); -} - -static __wsum qeth_eddp_check_tcp6_hdr(struct qeth_eddp_data *eddp, - int data_len) -{ - __be32 proto; - __wsum phcsum; /* pseudo header checksum */ - - QETH_DBF_TEXT(TRACE, 5, "eddpckt6"); - eddp->th.tcp.h.check = 0; - /* compute pseudo header checksum */ - phcsum = csum_partial(&eddp->nh.ip6.h.saddr, - sizeof(struct in6_addr), 0); - phcsum = csum_partial(&eddp->nh.ip6.h.daddr, - sizeof(struct in6_addr), phcsum); - proto = htonl(IPPROTO_TCP); - phcsum = csum_partial(&proto, sizeof(u32), phcsum); - return phcsum; -} - -static struct qeth_eddp_data *qeth_eddp_create_eddp_data(struct qeth_hdr *qh, - u8 *nh, u8 nhl, u8 *th, u8 thl) -{ - struct qeth_eddp_data *eddp; - - QETH_DBF_TEXT(TRACE, 5, "eddpcrda"); - eddp = kzalloc(sizeof(struct qeth_eddp_data), GFP_ATOMIC); - if (eddp) { - eddp->nhl = nhl; - eddp->thl = thl; - memcpy(&eddp->qh, qh, sizeof(struct qeth_hdr)); - memcpy(&eddp->nh, nh, nhl); - memcpy(&eddp->th, th, thl); - eddp->frag = -1; /* initially we're in skb->data */ - } - return eddp; -} - -static void __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, - struct qeth_eddp_data *eddp) -{ - struct tcphdr *tcph; - int data_len; - __wsum hcsum; - - QETH_DBF_TEXT(TRACE, 5, "eddpftcp"); - eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl; - if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) { - eddp->skb_offset += sizeof(struct ethhdr); - if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) - eddp->skb_offset += VLAN_HLEN; - } - tcph = tcp_hdr(eddp->skb); - while (eddp->skb_offset < eddp->skb->len) { - data_len = min((int)skb_shinfo(eddp->skb)->gso_size, - (int)(eddp->skb->len - eddp->skb_offset)); - /* prepare qdio hdr */ - if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) { - eddp->qh.hdr.l2.pkt_length = data_len + ETH_HLEN + - eddp->nhl + eddp->thl; - if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) - eddp->qh.hdr.l2.pkt_length += VLAN_HLEN; - } else - eddp->qh.hdr.l3.length = data_len + eddp->nhl + - eddp->thl; - /* prepare ip hdr */ - if (eddp->skb->protocol == htons(ETH_P_IP)) { - eddp->nh.ip4.h.tot_len = htons(data_len + eddp->nhl + - eddp->thl); - eddp->nh.ip4.h.check = 0; - eddp->nh.ip4.h.check = - ip_fast_csum((u8 *)&eddp->nh.ip4.h, - eddp->nh.ip4.h.ihl); - } else - eddp->nh.ip6.h.payload_len = htons(data_len + - eddp->thl); - /* prepare tcp hdr */ - if (data_len == (eddp->skb->len - eddp->skb_offset)) { - /* last segment -> set FIN and PSH flags */ - eddp->th.tcp.h.fin = tcph->fin; - eddp->th.tcp.h.psh = tcph->psh; - } - if (eddp->skb->protocol == htons(ETH_P_IP)) - hcsum = qeth_eddp_check_tcp4_hdr(eddp, data_len); - else - hcsum = qeth_eddp_check_tcp6_hdr(eddp, data_len); - /* fill the next segment into the context */ - qeth_eddp_create_segment_hdrs(ctx, eddp, data_len); - qeth_eddp_create_segment_data_tcp(ctx, eddp, data_len, hcsum); - if (eddp->skb_offset >= eddp->skb->len) - break; - /* prepare headers for next round */ - if (eddp->skb->protocol == htons(ETH_P_IP)) - eddp->nh.ip4.h.id = htons(ntohs(eddp->nh.ip4.h.id) + 1); - eddp->th.tcp.h.seq = htonl(ntohl(eddp->th.tcp.h.seq) + - data_len); - } -} - -static int qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, - struct sk_buff *skb, struct qeth_hdr *qhdr) -{ - struct qeth_eddp_data *eddp = NULL; - - QETH_DBF_TEXT(TRACE, 5, "eddpficx"); - /* create our segmentation headers and copy original headers */ - if (skb->protocol == htons(ETH_P_IP)) - eddp = qeth_eddp_create_eddp_data(qhdr, - skb_network_header(skb), - ip_hdrlen(skb), - skb_transport_header(skb), - tcp_hdrlen(skb)); - else - eddp = qeth_eddp_create_eddp_data(qhdr, - skb_network_header(skb), - sizeof(struct ipv6hdr), - skb_transport_header(skb), - tcp_hdrlen(skb)); - - if (eddp == NULL) { - QETH_DBF_TEXT(TRACE, 2, "eddpfcnm"); - return -ENOMEM; - } - if (qhdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) { - skb_set_mac_header(skb, sizeof(struct qeth_hdr)); - memcpy(&eddp->mac, eth_hdr(skb), ETH_HLEN); - if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) { - eddp->vlan[0] = skb->protocol; - eddp->vlan[1] = htons(vlan_tx_tag_get(skb)); - } - } - /* the next flags will only be set on the last segment */ - eddp->th.tcp.h.fin = 0; - eddp->th.tcp.h.psh = 0; - eddp->skb = skb; - /* begin segmentation and fill context */ - __qeth_eddp_fill_context_tcp(ctx, eddp); - kfree(eddp); - return 0; -} - -static void qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, - struct sk_buff *skb, int hdr_len) -{ - int skbs_per_page; - - QETH_DBF_TEXT(TRACE, 5, "eddpcanp"); - /* can we put multiple skbs in one page? */ - skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->gso_size + hdr_len); - if (skbs_per_page > 1) { - ctx->num_pages = (skb_shinfo(skb)->gso_segs + 1) / - skbs_per_page + 1; - ctx->elements_per_skb = 1; - } else { - /* no -> how many elements per skb? */ - ctx->elements_per_skb = (skb_shinfo(skb)->gso_size + hdr_len + - PAGE_SIZE) >> PAGE_SHIFT; - ctx->num_pages = ctx->elements_per_skb * - (skb_shinfo(skb)->gso_segs + 1); - } - ctx->num_elements = ctx->elements_per_skb * - (skb_shinfo(skb)->gso_segs + 1); -} - -static struct qeth_eddp_context *qeth_eddp_create_context_generic( - struct qeth_card *card, struct sk_buff *skb, int hdr_len) -{ - struct qeth_eddp_context *ctx = NULL; - u8 *addr; - int i; - - QETH_DBF_TEXT(TRACE, 5, "creddpcg"); - /* create the context and allocate pages */ - ctx = kzalloc(sizeof(struct qeth_eddp_context), GFP_ATOMIC); - if (ctx == NULL) { - QETH_DBF_TEXT(TRACE, 2, "ceddpcn1"); - return NULL; - } - ctx->type = QETH_LARGE_SEND_EDDP; - qeth_eddp_calc_num_pages(ctx, skb, hdr_len); - if (ctx->elements_per_skb > QETH_MAX_BUFFER_ELEMENTS(card)) { - QETH_DBF_TEXT(TRACE, 2, "ceddpcis"); - kfree(ctx); - return NULL; - } - ctx->pages = kcalloc(ctx->num_pages, sizeof(u8 *), GFP_ATOMIC); - if (ctx->pages == NULL) { - QETH_DBF_TEXT(TRACE, 2, "ceddpcn2"); - kfree(ctx); - return NULL; - } - for (i = 0; i < ctx->num_pages; ++i) { - addr = (u8 *)get_zeroed_page(GFP_ATOMIC); - if (addr == NULL) { - QETH_DBF_TEXT(TRACE, 2, "ceddpcn3"); - ctx->num_pages = i; - qeth_eddp_free_context(ctx); - return NULL; - } - ctx->pages[i] = addr; - } - ctx->elements = kcalloc(ctx->num_elements, - sizeof(struct qeth_eddp_element), GFP_ATOMIC); - if (ctx->elements == NULL) { - QETH_DBF_TEXT(TRACE, 2, "ceddpcn4"); - qeth_eddp_free_context(ctx); - return NULL; - } - /* reset num_elements; will be incremented again in fill_buffer to - * reflect number of actually used elements */ - ctx->num_elements = 0; - return ctx; -} - -static struct qeth_eddp_context *qeth_eddp_create_context_tcp( - struct qeth_card *card, struct sk_buff *skb, - struct qeth_hdr *qhdr) -{ - struct qeth_eddp_context *ctx = NULL; - - QETH_DBF_TEXT(TRACE, 5, "creddpct"); - if (skb->protocol == htons(ETH_P_IP)) - ctx = qeth_eddp_create_context_generic(card, skb, - (sizeof(struct qeth_hdr) + - ip_hdrlen(skb) + - tcp_hdrlen(skb))); - else if (skb->protocol == htons(ETH_P_IPV6)) - ctx = qeth_eddp_create_context_generic(card, skb, - sizeof(struct qeth_hdr) + sizeof(struct ipv6hdr) + - tcp_hdrlen(skb)); - else - QETH_DBF_TEXT(TRACE, 2, "cetcpinv"); - - if (ctx == NULL) { - QETH_DBF_TEXT(TRACE, 2, "creddpnl"); - return NULL; - } - if (qeth_eddp_fill_context_tcp(ctx, skb, qhdr)) { - QETH_DBF_TEXT(TRACE, 2, "ceddptfe"); - qeth_eddp_free_context(ctx); - return NULL; - } - atomic_set(&ctx->refcnt, 1); - return ctx; -} - -struct qeth_eddp_context *qeth_eddp_create_context(struct qeth_card *card, - struct sk_buff *skb, struct qeth_hdr *qhdr, - unsigned char sk_protocol) -{ - QETH_DBF_TEXT(TRACE, 5, "creddpc"); - switch (sk_protocol) { - case IPPROTO_TCP: - return qeth_eddp_create_context_tcp(card, skb, qhdr); - default: - QETH_DBF_TEXT(TRACE, 2, "eddpinvp"); - } - return NULL; -} -EXPORT_SYMBOL_GPL(qeth_eddp_create_context); - -void qeth_tso_fill_header(struct qeth_card *card, struct qeth_hdr *qhdr, - struct sk_buff *skb) -{ - struct qeth_hdr_tso *hdr = (struct qeth_hdr_tso *)qhdr; - struct tcphdr *tcph = tcp_hdr(skb); - struct iphdr *iph = ip_hdr(skb); - struct ipv6hdr *ip6h = ipv6_hdr(skb); - - QETH_DBF_TEXT(TRACE, 5, "tsofhdr"); - - /*fix header to TSO values ...*/ - hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO; - /*set values which are fix for the first approach ...*/ - hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso); - hdr->ext.imb_hdr_no = 1; - hdr->ext.hdr_type = 1; - hdr->ext.hdr_version = 1; - hdr->ext.hdr_len = 28; - /*insert non-fix values */ - hdr->ext.mss = skb_shinfo(skb)->gso_size; - hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4); - hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len - - sizeof(struct qeth_hdr_tso)); - tcph->check = 0; - if (skb->protocol == ETH_P_IPV6) { - ip6h->payload_len = 0; - tcph->check = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, - 0, IPPROTO_TCP, 0); - } else { - /*OSA want us to set these values ...*/ - tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, - 0, IPPROTO_TCP, 0); - iph->tot_len = 0; - iph->check = 0; - } -} -EXPORT_SYMBOL_GPL(qeth_tso_fill_header); - -void qeth_tx_csum(struct sk_buff *skb) -{ - int tlen; - if (skb->protocol == htons(ETH_P_IP)) { - tlen = ntohs(ip_hdr(skb)->tot_len) - (ip_hdr(skb)->ihl << 2); - switch (ip_hdr(skb)->protocol) { - case IPPROTO_TCP: - tcp_hdr(skb)->check = 0; - tcp_hdr(skb)->check = csum_tcpudp_magic( - ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, - tlen, ip_hdr(skb)->protocol, - skb_checksum(skb, skb_transport_offset(skb), - tlen, 0)); - break; - case IPPROTO_UDP: - udp_hdr(skb)->check = 0; - udp_hdr(skb)->check = csum_tcpudp_magic( - ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, - tlen, ip_hdr(skb)->protocol, - skb_checksum(skb, skb_transport_offset(skb), - tlen, 0)); - break; - } - } else if (skb->protocol == htons(ETH_P_IPV6)) { - switch (ipv6_hdr(skb)->nexthdr) { - case IPPROTO_TCP: - tcp_hdr(skb)->check = 0; - tcp_hdr(skb)->check = csum_ipv6_magic( - &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, - ipv6_hdr(skb)->payload_len, - ipv6_hdr(skb)->nexthdr, - skb_checksum(skb, skb_transport_offset(skb), - ipv6_hdr(skb)->payload_len, 0)); - break; - case IPPROTO_UDP: - udp_hdr(skb)->check = 0; - udp_hdr(skb)->check = csum_ipv6_magic( - &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, - ipv6_hdr(skb)->payload_len, - ipv6_hdr(skb)->nexthdr, - skb_checksum(skb, skb_transport_offset(skb), - ipv6_hdr(skb)->payload_len, 0)); - break; - } - } -} -EXPORT_SYMBOL_GPL(qeth_tx_csum); diff --git a/drivers/s390/net/qeth_core_offl.h b/drivers/s390/net/qeth_core_offl.h index 86bf7df8cf1..e69de29bb2d 100644 --- a/drivers/s390/net/qeth_core_offl.h +++ b/drivers/s390/net/qeth_core_offl.h @@ -1,76 +0,0 @@ -/* - * drivers/s390/net/qeth_core_offl.h - * - * Copyright IBM Corp. 2007 - * Author(s): Thomas Spatzier , - * Frank Blaschka - */ - -#ifndef __QETH_CORE_OFFL_H__ -#define __QETH_CORE_OFFL_H__ - -struct qeth_eddp_element { - u32 flags; - u32 length; - void *addr; -}; - -struct qeth_eddp_context { - atomic_t refcnt; - enum qeth_large_send_types type; - int num_pages; /* # of allocated pages */ - u8 **pages; /* pointers to pages */ - int offset; /* offset in ctx during creation */ - int num_elements; /* # of required 'SBALEs' */ - struct qeth_eddp_element *elements; /* array of 'SBALEs' */ - int elements_per_skb; /* # of 'SBALEs' per skb **/ -}; - -struct qeth_eddp_context_reference { - struct list_head list; - struct qeth_eddp_context *ctx; -}; - -struct qeth_eddp_data { - struct qeth_hdr qh; - struct ethhdr mac; - __be16 vlan[2]; - union { - struct { - struct iphdr h; - u8 options[40]; - } ip4; - struct { - struct ipv6hdr h; - } ip6; - } nh; - u8 nhl; - void *nh_in_ctx; /* address of nh within the ctx */ - union { - struct { - struct tcphdr h; - u8 options[40]; - } tcp; - } th; - u8 thl; - void *th_in_ctx; /* address of th within the ctx */ - struct sk_buff *skb; - int skb_offset; - int frag; - int frag_offset; -} __attribute__ ((packed)); - -extern struct qeth_eddp_context *qeth_eddp_create_context(struct qeth_card *, - struct sk_buff *, struct qeth_hdr *, unsigned char); -extern void qeth_eddp_put_context(struct qeth_eddp_context *); -extern int qeth_eddp_fill_buffer(struct qeth_qdio_out_q *, - struct qeth_eddp_context *, int); -extern void qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *); -extern int qeth_eddp_check_buffers_for_context(struct qeth_qdio_out_q *, - struct qeth_eddp_context *); - -void qeth_tso_fill_header(struct qeth_card *, struct qeth_hdr *, - struct sk_buff *); -void qeth_tx_csum(struct sk_buff *skb); - -#endif /* __QETH_CORE_EDDP_H__ */ diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index c26e842ad90..568465d7517 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c @@ -427,8 +427,6 @@ static ssize_t qeth_dev_large_send_show(struct device *dev, switch (card->options.large_send) { case QETH_LARGE_SEND_NO: return sprintf(buf, "%s\n", "no"); - case QETH_LARGE_SEND_EDDP: - return sprintf(buf, "%s\n", "EDDP"); case QETH_LARGE_SEND_TSO: return sprintf(buf, "%s\n", "TSO"); default: @@ -449,8 +447,6 @@ static ssize_t qeth_dev_large_send_store(struct device *dev, tmp = strsep((char **) &buf, "\n"); if (!strcmp(tmp, "no")) { type = QETH_LARGE_SEND_NO; - } else if (!strcmp(tmp, "EDDP")) { - type = QETH_LARGE_SEND_EDDP; } else if (!strcmp(tmp, "TSO")) { type = QETH_LARGE_SEND_TSO; } else { diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 7632d120884..9e628b322bd 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -21,7 +21,6 @@ #include #include "qeth_core.h" -#include "qeth_core_offl.h" static int qeth_l2_set_offline(struct ccwgroup_device *); static int qeth_l2_stop(struct net_device *); @@ -634,8 +633,6 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) struct qeth_qdio_out_q *queue = card->qdio.out_qs [qeth_get_priority_queue(card, skb, ipv, cast_type)]; int tx_bytes = skb->len; - enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; - struct qeth_eddp_context *ctx = NULL; int data_offset = -1; int elements_needed = 0; int hd_len = 0; @@ -655,14 +652,10 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) } netif_stop_queue(dev); - if (skb_is_gso(skb)) - large_send = QETH_LARGE_SEND_EDDP; - if (card->info.type == QETH_CARD_TYPE_OSN) hdr = (struct qeth_hdr *)skb->data; else { - if ((card->info.type == QETH_CARD_TYPE_IQD) && (!large_send) && - (skb_shinfo(skb)->nr_frags == 0)) { + if (card->info.type == QETH_CARD_TYPE_IQD) { new_skb = skb; data_offset = ETH_HLEN; hd_len = ETH_HLEN; @@ -689,62 +682,26 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) } } - if (large_send == QETH_LARGE_SEND_EDDP) { - ctx = qeth_eddp_create_context(card, new_skb, hdr, - skb->sk->sk_protocol); - if (ctx == NULL) { - QETH_DBF_MESSAGE(2, "could not create eddp context\n"); - goto tx_drop; - } - } else { - elements = qeth_get_elements_no(card, (void *)hdr, new_skb, + elements = qeth_get_elements_no(card, (void *)hdr, new_skb, elements_needed); - if (!elements) { - if (data_offset >= 0) - kmem_cache_free(qeth_core_header_cache, hdr); - goto tx_drop; - } - } - - if ((large_send == QETH_LARGE_SEND_NO) && - (skb->ip_summed == CHECKSUM_PARTIAL)) { - qeth_tx_csum(new_skb); - if (card->options.performance_stats) - card->perf_stats.tx_csum++; + if (!elements) { + if (data_offset >= 0) + kmem_cache_free(qeth_core_header_cache, hdr); + goto tx_drop; } if (card->info.type != QETH_CARD_TYPE_IQD) rc = qeth_do_send_packet(card, queue, new_skb, hdr, - elements, ctx); + elements); else rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr, - elements, ctx, data_offset, hd_len); + elements, data_offset, hd_len); if (!rc) { card->stats.tx_packets++; card->stats.tx_bytes += tx_bytes; if (new_skb != skb) dev_kfree_skb_any(skb); - if (card->options.performance_stats) { - if (large_send != QETH_LARGE_SEND_NO) { - card->perf_stats.large_send_bytes += tx_bytes; - card->perf_stats.large_send_cnt++; - } - if (skb_shinfo(new_skb)->nr_frags > 0) { - card->perf_stats.sg_skbs_sent++; - /* nr_frags + skb->data */ - card->perf_stats.sg_frags_sent += - skb_shinfo(new_skb)->nr_frags + 1; - } - } - - if (ctx != NULL) { - qeth_eddp_put_context(ctx); - dev_kfree_skb_any(new_skb); - } } else { - if (ctx != NULL) - qeth_eddp_put_context(ctx); - if (data_offset >= 0) kmem_cache_free(qeth_core_header_cache, hdr); @@ -881,30 +838,8 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev) return; } -static int qeth_l2_ethtool_set_tso(struct net_device *dev, u32 data) -{ - struct qeth_card *card = dev->ml_priv; - - if (data) { - if (card->options.large_send == QETH_LARGE_SEND_NO) { - card->options.large_send = QETH_LARGE_SEND_EDDP; - dev->features |= NETIF_F_TSO; - } - } else { - dev->features &= ~NETIF_F_TSO; - card->options.large_send = QETH_LARGE_SEND_NO; - } - return 0; -} - static struct ethtool_ops qeth_l2_ethtool_ops = { .get_link = ethtool_op_get_link, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_hw_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, - .get_tso = ethtool_op_get_tso, - .set_tso = qeth_l2_ethtool_set_tso, .get_strings = qeth_core_get_strings, .get_ethtool_stats = qeth_core_get_ethtool_stats, .get_stats_count = qeth_core_get_stats_count, diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index fea50bdc8f4..38071a0e0c3 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -19,15 +19,15 @@ #include #include #include -#include +#include #include #include #include #include +#include #include "qeth_l3.h" -#include "qeth_core_offl.h" static int qeth_l3_set_offline(struct ccwgroup_device *); static int qeth_l3_recover(void *); @@ -2577,12 +2577,63 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, } } +static void qeth_tso_fill_header(struct qeth_card *card, + struct qeth_hdr *qhdr, struct sk_buff *skb) +{ + struct qeth_hdr_tso *hdr = (struct qeth_hdr_tso *)qhdr; + struct tcphdr *tcph = tcp_hdr(skb); + struct iphdr *iph = ip_hdr(skb); + struct ipv6hdr *ip6h = ipv6_hdr(skb); + + /*fix header to TSO values ...*/ + hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO; + /*set values which are fix for the first approach ...*/ + hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso); + hdr->ext.imb_hdr_no = 1; + hdr->ext.hdr_type = 1; + hdr->ext.hdr_version = 1; + hdr->ext.hdr_len = 28; + /*insert non-fix values */ + hdr->ext.mss = skb_shinfo(skb)->gso_size; + hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4); + hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len - + sizeof(struct qeth_hdr_tso)); + tcph->check = 0; + if (skb->protocol == ETH_P_IPV6) { + ip6h->payload_len = 0; + tcph->check = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, + 0, IPPROTO_TCP, 0); + } else { + /*OSA want us to set these values ...*/ + tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, + 0, IPPROTO_TCP, 0); + iph->tot_len = 0; + iph->check = 0; + } +} + +static void qeth_tx_csum(struct sk_buff *skb) +{ + __wsum csum; + int offset; + + skb_set_transport_header(skb, skb->csum_start - skb_headroom(skb)); + offset = skb->csum_start - skb_headroom(skb); + BUG_ON(offset >= skb_headlen(skb)); + csum = skb_checksum(skb, offset, skb->len - offset, 0); + + offset += skb->csum_offset; + BUG_ON(offset + sizeof(__sum16) > skb_headlen(skb)); + *(__sum16 *)(skb->data + offset) = csum_fold(csum); +} + static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { int rc; u16 *tag; struct qeth_hdr *hdr = NULL; int elements_needed = 0; + int elems; struct qeth_card *card = dev->ml_priv; struct sk_buff *new_skb = NULL; int ipv = qeth_get_ip_version(skb); @@ -2591,8 +2642,8 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) [qeth_get_priority_queue(card, skb, ipv, cast_type)]; int tx_bytes = skb->len; enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; - struct qeth_eddp_context *ctx = NULL; int data_offset = -1; + int nr_frags; if ((card->info.type == QETH_CARD_TYPE_IQD) && (skb->protocol != htons(ETH_P_IPV6)) && @@ -2615,6 +2666,12 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) if (skb_is_gso(skb)) large_send = card->options.large_send; + else + if (skb->ip_summed == CHECKSUM_PARTIAL) { + qeth_tx_csum(skb); + if (card->options.performance_stats) + card->perf_stats.tx_csum++; + } if ((card->info.type == QETH_CARD_TYPE_IQD) && (!large_send) && (skb_shinfo(skb)->nr_frags == 0)) { @@ -2661,12 +2718,13 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); /* fix hardware limitation: as long as we do not have sbal - * chaining we can not send long frag lists so we temporary - * switch to EDDP + * chaining we can not send long frag lists */ if ((large_send == QETH_LARGE_SEND_TSO) && - ((skb_shinfo(new_skb)->nr_frags + 2) > 16)) - large_send = QETH_LARGE_SEND_EDDP; + ((skb_shinfo(new_skb)->nr_frags + 2) > 16)) { + if (skb_linearize(new_skb)) + goto tx_drop; + } if ((large_send == QETH_LARGE_SEND_TSO) && (cast_type == RTN_UNSPEC)) { @@ -2689,40 +2747,22 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) } } - if (large_send == QETH_LARGE_SEND_EDDP) { - /* new_skb is not owned by a socket so we use skb to get - * the protocol - */ - ctx = qeth_eddp_create_context(card, new_skb, hdr, - skb->sk->sk_protocol); - if (ctx == NULL) { - QETH_DBF_MESSAGE(2, "could not create eddp context\n"); - goto tx_drop; - } - } else { - int elems = qeth_get_elements_no(card, (void *)hdr, new_skb, + elems = qeth_get_elements_no(card, (void *)hdr, new_skb, elements_needed); - if (!elems) { - if (data_offset >= 0) - kmem_cache_free(qeth_core_header_cache, hdr); - goto tx_drop; - } - elements_needed += elems; - } - - if ((large_send == QETH_LARGE_SEND_NO) && - (new_skb->ip_summed == CHECKSUM_PARTIAL)) { - qeth_tx_csum(new_skb); - if (card->options.performance_stats) - card->perf_stats.tx_csum++; + if (!elems) { + if (data_offset >= 0) + kmem_cache_free(qeth_core_header_cache, hdr); + goto tx_drop; } + elements_needed += elems; + nr_frags = skb_shinfo(new_skb)->nr_frags; if (card->info.type != QETH_CARD_TYPE_IQD) rc = qeth_do_send_packet(card, queue, new_skb, hdr, - elements_needed, ctx); + elements_needed); else rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr, - elements_needed, ctx, data_offset, 0); + elements_needed, data_offset, 0); if (!rc) { card->stats.tx_packets++; @@ -2734,22 +2774,13 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) card->perf_stats.large_send_bytes += tx_bytes; card->perf_stats.large_send_cnt++; } - if (skb_shinfo(new_skb)->nr_frags > 0) { + if (nr_frags) { card->perf_stats.sg_skbs_sent++; /* nr_frags + skb->data */ - card->perf_stats.sg_frags_sent += - skb_shinfo(new_skb)->nr_frags + 1; + card->perf_stats.sg_frags_sent += nr_frags + 1; } } - - if (ctx != NULL) { - qeth_eddp_put_context(ctx); - dev_kfree_skb_any(new_skb); - } } else { - if (ctx != NULL) - qeth_eddp_put_context(ctx); - if (data_offset >= 0) kmem_cache_free(qeth_core_header_cache, hdr); @@ -2844,7 +2875,7 @@ static int qeth_l3_ethtool_set_tso(struct net_device *dev, u32 data) if (data) { if (card->options.large_send == QETH_LARGE_SEND_NO) { if (card->info.type == QETH_CARD_TYPE_IQD) - card->options.large_send = QETH_LARGE_SEND_EDDP; + return -EPERM; else card->options.large_send = QETH_LARGE_SEND_TSO; dev->features |= NETIF_F_TSO; -- GitLab From 932e1583c1e52de6757122b92511e69ee0da1c78 Mon Sep 17 00:00:00 2001 From: Klaus-Dieter Wacker Date: Tue, 24 Mar 2009 20:57:17 +0000 Subject: [PATCH 4499/4982] qeth: unregister MAC addresses during recovery. qeth: Unregister MAC addresses from device (layer 2) during recovery cycle. When the device is set online the MAC addresses are registered again on the device. Signed-off-by: Klaus-Dieter Wacker Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/qeth_l2_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 9e628b322bd..ecd7efc5e31 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -378,7 +378,8 @@ static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode) dev_close(card->dev); rtnl_unlock(); } - if (!card->use_hard_stop) { + if (!card->use_hard_stop || + recovery_mode) { __u8 *mac = &card->dev->dev_addr[0]; rc = qeth_l2_send_delmac(card, mac); QETH_DBF_TEXT_(SETUP, 2, "Lerr%d", rc); @@ -387,7 +388,8 @@ static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode) } if (card->state == CARD_STATE_SOFTSETUP) { qeth_l2_process_vlans(card, 1); - if (!card->use_hard_stop) + if (!card->use_hard_stop || + recovery_mode) qeth_l2_del_all_mc(card); qeth_clear_ipacmd_list(card); card->state = CARD_STATE_HARDSETUP; -- GitLab From 8e98ac48d06068470f1b954e599cf7b706cfceba Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Tue, 24 Mar 2009 20:57:18 +0000 Subject: [PATCH 4500/4982] qeth: check for completion of a running recovery When a recovery is started for a qeth device, additional invocations to change a mac address, to configure a VLAN interface on top, or to add multicast addresses should wait till recovery is finished, otherwise recovery might fail. Signed-off-by: Ursula Braun Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/qeth_l2_main.c | 15 +++++++++++++++ drivers/s390/net/qeth_l3_main.c | 7 +++++++ 2 files changed, 22 insertions(+) diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index ecd7efc5e31..172031baedc 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -327,6 +327,10 @@ static void qeth_l2_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) struct qeth_vlan_vid *id; QETH_DBF_TEXT_(TRACE, 4, "aid:%d", vid); + if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { + QETH_DBF_TEXT(TRACE, 3, "aidREC"); + return; + } id = kmalloc(sizeof(struct qeth_vlan_vid), GFP_ATOMIC); if (id) { id->vid = vid; @@ -343,6 +347,10 @@ static void qeth_l2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) struct qeth_card *card = dev->ml_priv; QETH_DBF_TEXT_(TRACE, 4, "kid:%d", vid); + if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { + QETH_DBF_TEXT(TRACE, 3, "kidREC"); + return; + } spin_lock_bh(&card->vlanlock); list_for_each_entry(id, &card->vid_list, list) { if (id->vid == vid) { @@ -594,6 +602,10 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p) } QETH_DBF_TEXT_(TRACE, 3, "%s", CARD_BUS_ID(card)); QETH_DBF_HEX(TRACE, 3, addr->sa_data, OSA_ADDR_LEN); + if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { + QETH_DBF_TEXT(TRACE, 3, "setmcREC"); + return -ERESTARTSYS; + } rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]); if (!rc) rc = qeth_l2_send_setmac(card, addr->sa_data); @@ -609,6 +621,9 @@ static void qeth_l2_set_multicast_list(struct net_device *dev) return ; QETH_DBF_TEXT(TRACE, 3, "setmulti"); + if (qeth_threads_running(card, QETH_RECOVER_THREAD) && + (card->state != CARD_STATE_UP)) + return; qeth_l2_del_all_mc(card); spin_lock_bh(&card->mclock); for (dm = dev->mc_list; dm; dm = dm->next) diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 38071a0e0c3..0ba3817cb6a 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1838,6 +1838,10 @@ static void qeth_l3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) unsigned long flags; QETH_DBF_TEXT_(TRACE, 4, "kid:%d", vid); + if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { + QETH_DBF_TEXT(TRACE, 3, "kidREC"); + return; + } spin_lock_irqsave(&card->vlanlock, flags); /* unregister IP addresses of vlan device */ qeth_l3_free_vlan_addresses(card, vid); @@ -2101,6 +2105,9 @@ static void qeth_l3_set_multicast_list(struct net_device *dev) struct qeth_card *card = dev->ml_priv; QETH_DBF_TEXT(TRACE, 3, "setmulti"); + if (qeth_threads_running(card, QETH_RECOVER_THREAD) && + (card->state != CARD_STATE_UP)) + return; qeth_l3_delete_mc_addresses(card); qeth_l3_add_multicast_ipv4(card); #ifdef CONFIG_QETH_IPV6 -- GitLab From 7834cd5ae145c9a74d284cef073b96ee5f7f2295 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 24 Mar 2009 20:57:19 +0000 Subject: [PATCH 4501/4982] qeth: fix wait_event_timeout handling wait_event_timeout just takes the numnber of jiffies to wait as an argument. That value does not include jiffies itself. Signed-off-by: Heiko Carstens Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 1b7b08e791a..6fec3cfcf97 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -1676,7 +1676,7 @@ int qeth_send_control_data(struct qeth_card *card, int len, int rc; unsigned long flags; struct qeth_reply *reply = NULL; - unsigned long timeout; + unsigned long timeout, event_timeout; struct qeth_ipa_cmd *cmd; QETH_DBF_TEXT(TRACE, 2, "sendctl"); @@ -1701,9 +1701,10 @@ int qeth_send_control_data(struct qeth_card *card, int len, qeth_prepare_control_data(card, len, iob); if (IS_IPA(iob->data)) - timeout = jiffies + QETH_IPA_TIMEOUT; + event_timeout = QETH_IPA_TIMEOUT; else - timeout = jiffies + QETH_TIMEOUT; + event_timeout = QETH_TIMEOUT; + timeout = jiffies + event_timeout; QETH_DBF_TEXT(TRACE, 6, "noirqpnd"); spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags); @@ -1731,7 +1732,7 @@ int qeth_send_control_data(struct qeth_card *card, int len, if ((cmd->hdr.command == IPA_CMD_SETIP) && (cmd->hdr.prot_version == QETH_PROT_IPV4)) { if (!wait_event_timeout(reply->wait_q, - atomic_read(&reply->received), timeout)) + atomic_read(&reply->received), event_timeout)) goto time_err; } else { while (!atomic_read(&reply->received)) { -- GitLab From 9626dd75c57360666f4cdcb660c1672ee9f952e8 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Wed, 21 Jan 2009 11:13:11 +0000 Subject: [PATCH 4502/4982] [WATCHDOG] cpwd.c & riowd.c - unlocked_ioctl Switch to unlocked_ioctl Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/cpwd.c | 20 ++++++++++---------- drivers/watchdog/riowd.c | 15 +++++++-------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c index 084dfe9cecf..261790afd65 100644 --- a/drivers/watchdog/cpwd.c +++ b/drivers/watchdog/cpwd.c @@ -400,8 +400,7 @@ static int cpwd_release(struct inode *inode, struct file *file) return 0; } -static int cpwd_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long cpwd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { static struct watchdog_info info = { .options = WDIOF_SETTIMEOUT, @@ -409,6 +408,7 @@ static int cpwd_ioctl(struct inode *inode, struct file *file, .identity = DRIVER_NAME, }; void __user *argp = (void __user *)arg; + struct inode *inode = file->f_path.dentry->d_inode; int index = iminor(inode) - WD0_MINOR; struct cpwd *p = cpwd_device; int setopt = 0; @@ -481,7 +481,7 @@ static long cpwd_compat_ioctl(struct file *file, unsigned int cmd, case WIOCSTOP: case WIOCGSTAT: lock_kernel(); - rval = cpwd_ioctl(file->f_path.dentry->d_inode, file, cmd, arg); + rval = cpwd_ioctl(file, cmd, arg); unlock_kernel(); break; @@ -515,13 +515,13 @@ static ssize_t cpwd_read(struct file * file, char __user *buffer, } static const struct file_operations cpwd_fops = { - .owner = THIS_MODULE, - .ioctl = cpwd_ioctl, - .compat_ioctl = cpwd_compat_ioctl, - .open = cpwd_open, - .write = cpwd_write, - .read = cpwd_read, - .release = cpwd_release, + .owner = THIS_MODULE, + .unlocked_ioctl = cpwd_ioctl, + .compat_ioctl = cpwd_compat_ioctl, + .open = cpwd_open, + .write = cpwd_write, + .read = cpwd_read, + .release = cpwd_release, }; static int __devinit cpwd_probe(struct of_device *op, diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c index 09cb1833ea2..01cc7e39d92 100644 --- a/drivers/watchdog/riowd.c +++ b/drivers/watchdog/riowd.c @@ -86,8 +86,7 @@ static int riowd_release(struct inode *inode, struct file *filp) return 0; } -static int riowd_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static long riowd_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { static struct watchdog_info info = { .options = WDIOF_SETTIMEOUT, @@ -160,12 +159,12 @@ static ssize_t riowd_write(struct file *file, const char __user *buf, size_t cou } static const struct file_operations riowd_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .ioctl = riowd_ioctl, - .open = riowd_open, - .write = riowd_write, - .release = riowd_release, + .owner = THIS_MODULE, + .llseek = no_llseek, + .unlocked_ioctl = riowd_ioctl, + .open = riowd_open, + .write = riowd_write, + .release = riowd_release, }; static struct miscdevice riowd_miscdev = { -- GitLab From 63bad1452e9087e6f130316c005eb38a8758a267 Mon Sep 17 00:00:00 2001 From: Eric Lammerts Date: Tue, 3 Feb 2009 17:45:56 -0500 Subject: [PATCH 4503/4982] [WATCHDOG] w83697ug: add error checking I noticed the W83697UG driver tries to register a watchdog even though it already noticed the chip isn't there. WDT driver for the Winbond(TM) W83697UG/UF Super I/O chip initialising. w83697ug/uf WDT: No W83697UG/UF could be found w83697ug/uf WDT: Watchdog already running. Resetting timeout to 60 sec w83697ug/uf WDT: cannot register miscdev on minor=130 (err=-16) Patch propagates the error back to wdt_init(). Signed-off-by: Eric Lammerts Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/w83697ug_wdt.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/watchdog/w83697ug_wdt.c b/drivers/watchdog/w83697ug_wdt.c index ada8ad82d99..6972c0a1e4d 100644 --- a/drivers/watchdog/w83697ug_wdt.c +++ b/drivers/watchdog/w83697ug_wdt.c @@ -79,7 +79,7 @@ MODULE_PARM_DESC(nowayout, (same as EFER) */ #define WDT_EFDR (WDT_EFIR+1) /* Extended Function Data Register */ -static void w83697ug_select_wd_register(void) +static int w83697ug_select_wd_register(void) { unsigned char c; unsigned char version; @@ -102,7 +102,7 @@ static void w83697ug_select_wd_register(void) } else { printk(KERN_ERR PFX "No W83697UG/UF could be found\n"); - return; + return -ENODEV; } outb_p(0x07, WDT_EFER); /* point to logical device number reg */ @@ -110,6 +110,8 @@ static void w83697ug_select_wd_register(void) outb_p(0x30, WDT_EFER); /* select CR30 */ c = inb_p(WDT_EFDR); outb_p(c || 0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */ + + return 0; } static void w83697ug_unselect_wd_register(void) @@ -117,11 +119,14 @@ static void w83697ug_unselect_wd_register(void) outb_p(0xAA, WDT_EFER); /* Leave extended function mode */ } -static void w83697ug_init(void) +static int w83697ug_init(void) { + int ret; unsigned char t; - w83697ug_select_wd_register(); + ret = w83697ug_select_wd_register(); + if (ret != 0) + return ret; outb_p(0xF6, WDT_EFER); /* Select CRF6 */ t = inb_p(WDT_EFDR); /* read CRF6 */ @@ -137,13 +142,15 @@ static void w83697ug_init(void) outb_p(t, WDT_EFDR); /* Write back to CRF5 */ w83697ug_unselect_wd_register(); + return 0; } static void wdt_ctrl(int timeout) { spin_lock(&io_lock); - w83697ug_select_wd_register(); + if (w83697ug_select_wd_register() < 0) + return; outb_p(0xF4, WDT_EFER); /* Select CRF4 */ outb_p(timeout, WDT_EFDR); /* Write Timeout counter to CRF4 */ @@ -347,7 +354,9 @@ static int __init wdt_init(void) goto out; } - w83697ug_init(); + ret = w83697ug_init(); + if (ret != 0) + goto unreg_regions; ret = register_reboot_notifier(&wdt_notifier); if (ret != 0) { -- GitLab From 371d3525e3b9d57c00ca307f8ee4ca51a2eaa70b Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 29 Jan 2009 14:14:30 -0800 Subject: [PATCH 4504/4982] [WATCHDOG] davinci: convert to ioremap() + io[read|write] Remove davinci platform-specific IO accessor macros in favor of standard ioremap + io[read|write]* functions. Also, convert printk(KERN_ERR ....) into dev_err(...) Signed-off-by: Kevin Hilman Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/davinci_wdt.c | 45 +++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c index 2e136028673..c51d0b0ea0c 100644 --- a/drivers/watchdog/davinci_wdt.c +++ b/drivers/watchdog/davinci_wdt.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #define MODULE_NAME "DAVINCI-WDT: " @@ -75,9 +75,9 @@ static void wdt_service(void) spin_lock(&io_lock); /* put watchdog in service state */ - davinci_writel(WDKEY_SEQ0, wdt_base + WDTCR); + iowrite32(WDKEY_SEQ0, wdt_base + WDTCR); /* put watchdog in active state */ - davinci_writel(WDKEY_SEQ1, wdt_base + WDTCR); + iowrite32(WDKEY_SEQ1, wdt_base + WDTCR); spin_unlock(&io_lock); } @@ -90,29 +90,29 @@ static void wdt_enable(void) spin_lock(&io_lock); /* disable, internal clock source */ - davinci_writel(0, wdt_base + TCR); + iowrite32(0, wdt_base + TCR); /* reset timer, set mode to 64-bit watchdog, and unreset */ - davinci_writel(0, wdt_base + TGCR); + iowrite32(0, wdt_base + TGCR); tgcr = TIMMODE_64BIT_WDOG | TIM12RS_UNRESET | TIM34RS_UNRESET; - davinci_writel(tgcr, wdt_base + TGCR); + iowrite32(tgcr, wdt_base + TGCR); /* clear counter regs */ - davinci_writel(0, wdt_base + TIM12); - davinci_writel(0, wdt_base + TIM34); + iowrite32(0, wdt_base + TIM12); + iowrite32(0, wdt_base + TIM34); /* set timeout period */ timer_margin = (((u64)heartbeat * CLOCK_TICK_RATE) & 0xffffffff); - davinci_writel(timer_margin, wdt_base + PRD12); + iowrite32(timer_margin, wdt_base + PRD12); timer_margin = (((u64)heartbeat * CLOCK_TICK_RATE) >> 32); - davinci_writel(timer_margin, wdt_base + PRD34); + iowrite32(timer_margin, wdt_base + PRD34); /* enable run continuously */ - davinci_writel(ENAMODE12_PERIODIC, wdt_base + TCR); + iowrite32(ENAMODE12_PERIODIC, wdt_base + TCR); /* Once the WDT is in pre-active state write to * TIM12, TIM34, PRD12, PRD34, TCR, TGCR, WDTCR are * write protected (except for the WDKEY field) */ /* put watchdog in pre-active state */ - davinci_writel(WDKEY_SEQ0 | WDEN, wdt_base + WDTCR); + iowrite32(WDKEY_SEQ0 | WDEN, wdt_base + WDTCR); /* put watchdog in active state */ - davinci_writel(WDKEY_SEQ1 | WDEN, wdt_base + WDTCR); + iowrite32(WDKEY_SEQ1 | WDEN, wdt_base + WDTCR); spin_unlock(&io_lock); } @@ -197,17 +197,16 @@ static int davinci_wdt_probe(struct platform_device *pdev) { int ret = 0, size; struct resource *res; + struct device *dev = &pdev->dev; if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT) heartbeat = DEFAULT_HEARTBEAT; - printk(KERN_INFO MODULE_NAME - "DaVinci Watchdog Timer: heartbeat %d sec\n", heartbeat); + dev_info(dev, "heartbeat %d sec\n", heartbeat); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { - printk(KERN_INFO MODULE_NAME - "failed to get memory region resource\n"); + dev_err(dev, "failed to get memory region resource\n"); return -ENOENT; } @@ -215,20 +214,26 @@ static int davinci_wdt_probe(struct platform_device *pdev) wdt_mem = request_mem_region(res->start, size, pdev->name); if (wdt_mem == NULL) { - printk(KERN_INFO MODULE_NAME "failed to get memory region\n"); + dev_err(dev, "failed to get memory region\n"); return -ENOENT; } - wdt_base = (void __iomem *)(res->start); + + wdt_base = ioremap(res->start, size); + if (!wdt_base) { + dev_err(dev, "failed to map memory region\n"); + return -ENOMEM; + } ret = misc_register(&davinci_wdt_miscdev); if (ret < 0) { - printk(KERN_ERR MODULE_NAME "cannot register misc device\n"); + dev_err(dev, "cannot register misc device\n"); release_resource(wdt_mem); kfree(wdt_mem); } else { set_bit(WDT_DEVICE_INITED, &wdt_status); } + iounmap(wdt_base); return ret; } -- GitLab From bba7d0b9ba0f04d25145de8170a17a3a07bbfdde Mon Sep 17 00:00:00 2001 From: Paulius Zaleckas Date: Wed, 25 Mar 2009 10:58:47 +0200 Subject: [PATCH 4505/4982] ARM: tlbflush.h: introduce TLB_BTB flag Signed-off-by: Paulius Zaleckas --- arch/arm/include/asm/tlbflush.h | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h index b543a054a17..ffedd2494ea 100644 --- a/arch/arm/include/asm/tlbflush.h +++ b/arch/arm/include/asm/tlbflush.h @@ -39,6 +39,7 @@ #define TLB_V6_D_ASID (1 << 17) #define TLB_V6_I_ASID (1 << 18) +#define TLB_BTB (1 << 28) #define TLB_L2CLEAN_FR (1 << 29) /* Feroceon */ #define TLB_DCLEAN (1 << 30) #define TLB_WB (1 << 31) @@ -140,7 +141,7 @@ # define v4wb_always_flags (-1UL) #endif -#define v6wbi_tlb_flags (TLB_WB | TLB_DCLEAN | \ +#define v6wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \ TLB_V6_I_FULL | TLB_V6_D_FULL | \ TLB_V6_I_PAGE | TLB_V6_D_PAGE | \ TLB_V6_I_ASID | TLB_V6_D_ASID) @@ -297,9 +298,7 @@ static inline void local_flush_tlb_all(void) if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL)) asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc"); - if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL | - TLB_V6_I_PAGE | TLB_V6_D_PAGE | - TLB_V6_I_ASID | TLB_V6_D_ASID)) { + if (tlb_flag(TLB_BTB)) { /* flush the branch target cache */ asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); dsb(); @@ -334,9 +333,7 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm) if (tlb_flag(TLB_V6_I_ASID)) asm("mcr p15, 0, %0, c8, c5, 2" : : "r" (asid) : "cc"); - if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL | - TLB_V6_I_PAGE | TLB_V6_D_PAGE | - TLB_V6_I_ASID | TLB_V6_D_ASID)) { + if (tlb_flag(TLB_BTB)) { /* flush the branch target cache */ asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); dsb(); @@ -374,9 +371,7 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) if (tlb_flag(TLB_V6_I_PAGE)) asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc"); - if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL | - TLB_V6_I_PAGE | TLB_V6_D_PAGE | - TLB_V6_I_ASID | TLB_V6_D_ASID)) { + if (tlb_flag(TLB_BTB)) { /* flush the branch target cache */ asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); dsb(); @@ -411,9 +406,7 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr) if (tlb_flag(TLB_V6_I_PAGE)) asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc"); - if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL | - TLB_V6_I_PAGE | TLB_V6_D_PAGE | - TLB_V6_I_ASID | TLB_V6_D_ASID)) { + if (tlb_flag(TLB_BTB)) { /* flush the branch target cache */ asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); dsb(); -- GitLab From 9b655e07d77e3b1a00c1c8302e2ef3b7fb719de3 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Sun, 8 Feb 2009 16:44:42 +0100 Subject: [PATCH 4506/4982] [WATCHDOG] rc32434_wdt: clean-up driver Clean-up the rc32434 driver code: - name the platform driver rc32434_wdt_driver - Replace KBUILD_MODNAME ": " with PFX define. - Cleanup include files - Order the ioctl's Signed-off-by: Phil Sutter Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/rc32434_wdt.c | 75 +++++++++++++++++----------------- 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c index f3553fa40b1..68fb22625cd 100644 --- a/drivers/watchdog/rc32434_wdt.c +++ b/drivers/watchdog/rc32434_wdt.c @@ -17,22 +17,22 @@ * */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include +#include /* For module specific items */ +#include /* For new moduleparam's */ +#include /* For standard types (like size_t) */ +#include /* For the -ENODEV/... values */ +#include /* For printk/panic/... */ +#include /* For file operations */ +#include /* For MODULE_ALIAS_MISCDEV + (WATCHDOG_MINOR) */ +#include /* For the watchdog specific items */ +#include /* For __init/__exit/... */ +#include /* For platform_driver framework */ +#include /* For copy_to_user/put_user/... */ + +#include /* For the Watchdog registers */ + +#define PFX KBUILD_MODNAME ": " #define VERSION "0.4" @@ -90,12 +90,16 @@ static void rc32434_wdt_start(void) or = 1 << RC32434_WTC_EN; SET_BITS(wdt_reg->wtc, or, nand); + + printk(KERN_INFO PFX "Started watchdog timer.\n"); } static void rc32434_wdt_stop(void) { /* Disable WDT */ SET_BITS(wdt_reg->wtc, 0, 1 << RC32434_WTC_EN); + + printk(KERN_INFO PFX "Stopped watchdog timer.\n"); } static int rc32434_wdt_set(int new_timeout) @@ -103,8 +107,7 @@ static int rc32434_wdt_set(int new_timeout) int max_to = WTCOMP2SEC((u32)-1); if (new_timeout < 0 || new_timeout > max_to) { - printk(KERN_ERR KBUILD_MODNAME - ": timeout value must be between 0 and %d", + printk(KERN_ERR PFX "timeout value must be between 0 and %d", max_to); return -EINVAL; } @@ -137,11 +140,10 @@ static int rc32434_wdt_release(struct inode *inode, struct file *file) { if (expect_close == 42) { rc32434_wdt_stop(); - printk(KERN_INFO KBUILD_MODNAME ": disabling watchdog timer\n"); module_put(THIS_MODULE); } else { - printk(KERN_CRIT KBUILD_MODNAME - ": device closed unexpectedly. WDT will not stop !\n"); + printk(KERN_CRIT PFX + "device closed unexpectedly. WDT will not stop!\n"); rc32434_wdt_ping(); } clear_bit(0, &rc32434_wdt_device.inuse); @@ -185,8 +187,9 @@ static long rc32434_wdt_ioctl(struct file *file, unsigned int cmd, .identity = "RC32434_WDT Watchdog", }; switch (cmd) { - case WDIOC_KEEPALIVE: - rc32434_wdt_ping(); + case WDIOC_GETSUPPORT: + if (copy_to_user(argp, &ident, sizeof(ident))) + return -EFAULT; break; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: @@ -194,10 +197,6 @@ static long rc32434_wdt_ioctl(struct file *file, unsigned int cmd, if (copy_to_user(argp, &value, sizeof(int))) return -EFAULT; break; - case WDIOC_GETSUPPORT: - if (copy_to_user(argp, &ident, sizeof(ident))) - return -EFAULT; - break; case WDIOC_SETOPTIONS: if (copy_from_user(&value, argp, sizeof(int))) return -EFAULT; @@ -212,6 +211,9 @@ static long rc32434_wdt_ioctl(struct file *file, unsigned int cmd, return -EINVAL; } break; + case WDIOC_KEEPALIVE: + rc32434_wdt_ping(); + break; case WDIOC_SETTIMEOUT: if (copy_from_user(&new_timeout, argp, sizeof(int))) return -EFAULT; @@ -242,8 +244,8 @@ static struct miscdevice rc32434_wdt_miscdev = { .fops = &rc32434_wdt_fops, }; -static char banner[] __devinitdata = KERN_INFO KBUILD_MODNAME - ": Watchdog Timer version " VERSION ", timer margin: %d sec\n"; +static char banner[] __devinitdata = KERN_INFO PFX + "Watchdog Timer version " VERSION ", timer margin: %d sec\n"; static int __devinit rc32434_wdt_probe(struct platform_device *pdev) { @@ -252,22 +254,19 @@ static int __devinit rc32434_wdt_probe(struct platform_device *pdev) r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rb532_wdt_res"); if (!r) { - printk(KERN_ERR KBUILD_MODNAME - "failed to retrieve resources\n"); + printk(KERN_ERR PFX "failed to retrieve resources\n"); return -ENODEV; } wdt_reg = ioremap_nocache(r->start, r->end - r->start); if (!wdt_reg) { - printk(KERN_ERR KBUILD_MODNAME - "failed to remap I/O resources\n"); + printk(KERN_ERR PFX "failed to remap I/O resources\n"); return -ENXIO; } ret = misc_register(&rc32434_wdt_miscdev); if (ret < 0) { - printk(KERN_ERR KBUILD_MODNAME - "failed to register watchdog device\n"); + printk(KERN_ERR PFX "failed to register watchdog device\n"); goto unmap; } @@ -287,7 +286,7 @@ static int __devexit rc32434_wdt_remove(struct platform_device *pdev) return 0; } -static struct platform_driver rc32434_wdt = { +static struct platform_driver rc32434_wdt_driver = { .probe = rc32434_wdt_probe, .remove = __devexit_p(rc32434_wdt_remove), .driver = { @@ -297,12 +296,12 @@ static struct platform_driver rc32434_wdt = { static int __init rc32434_wdt_init(void) { - return platform_driver_register(&rc32434_wdt); + return platform_driver_register(&rc32434_wdt_driver); } static void __exit rc32434_wdt_exit(void) { - platform_driver_unregister(&rc32434_wdt); + platform_driver_unregister(&rc32434_wdt_driver); } module_init(rc32434_wdt_init); -- GitLab From 08eb2e0c084778f30691e3f18540cdb754c56530 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Sun, 8 Feb 2009 16:44:42 +0100 Subject: [PATCH 4507/4982] [WATCHDOG] rc32434_wdt: add timeout module parameter The WDT timer ticks quite fast (half of the CPU clock speed, which may be between 198MHz and 330MHz (or 400MHz on newer boards)). Given it's size of 32Bit, the maximum timeout value ranges from about 21s to 43s, depending on the configured CPU clock speed. This patch add's the timeout module parameter and checks that it's not bigger then the maximum timeout for the given clock speed. Signed-off-by: Phil Sutter Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/rc32434_wdt.c | 47 ++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c index 68fb22625cd..89f326a39b6 100644 --- a/drivers/watchdog/rc32434_wdt.c +++ b/drivers/watchdog/rc32434_wdt.c @@ -34,7 +34,7 @@ #define PFX KBUILD_MODNAME ": " -#define VERSION "0.4" +#define VERSION "0.5" static struct { unsigned long inuse; @@ -58,6 +58,9 @@ extern unsigned int idt_cpu_freq; #define WATCHDOG_TIMEOUT 20 static int timeout = WATCHDOG_TIMEOUT; +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, "Watchdog timeout value, in seconds (default=" + WATCHDOG_TIMEOUT ")"); static int nowayout = WATCHDOG_NOWAYOUT; module_param(nowayout, int, 0); @@ -68,6 +71,21 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" #define SET_BITS(addr, or, nand) \ writel((readl(&addr) | or) & ~nand, &addr) +static int rc32434_wdt_set(int new_timeout) +{ + int max_to = WTCOMP2SEC((u32)-1); + + if (new_timeout < 0 || new_timeout > max_to) { + printk(KERN_ERR PFX "timeout value must be between 0 and %d", + max_to); + return -EINVAL; + } + timeout = new_timeout; + writel(SEC2WTCOMP(timeout), &wdt_reg->wtcompare); + + return 0; +} + static void rc32434_wdt_start(void) { u32 or, nand; @@ -85,6 +103,9 @@ static void rc32434_wdt_start(void) SET_BITS(wdt_reg->errcs, or, nand); + /* set the timeout (either default or based on module param) */ + rc32434_wdt_set(timeout); + /* reset WTC timeout bit and enable WDT */ nand = 1 << RC32434_WTC_TO; or = 1 << RC32434_WTC_EN; @@ -102,21 +123,6 @@ static void rc32434_wdt_stop(void) printk(KERN_INFO PFX "Stopped watchdog timer.\n"); } -static int rc32434_wdt_set(int new_timeout) -{ - int max_to = WTCOMP2SEC((u32)-1); - - if (new_timeout < 0 || new_timeout > max_to) { - printk(KERN_ERR PFX "timeout value must be between 0 and %d", - max_to); - return -EINVAL; - } - timeout = new_timeout; - writel(SEC2WTCOMP(timeout), &wdt_reg->wtcompare); - - return 0; -} - static void rc32434_wdt_ping(void) { writel(0, &wdt_reg->wtcount); @@ -264,6 +270,15 @@ static int __devinit rc32434_wdt_probe(struct platform_device *pdev) return -ENXIO; } + /* Check that the heartbeat value is within it's range; + * if not reset to the default */ + if (rc32434_wdt_set(timeout)) { + rc32434_wdt_set(WATCHDOG_TIMEOUT); + printk(KERN_INFO PFX + "timeout value must be between 0 and %d\n", + WTCOMP2SEC((u32)-1)); + } + ret = misc_register(&rc32434_wdt_miscdev); if (ret < 0) { printk(KERN_ERR PFX "failed to register watchdog device\n"); -- GitLab From 0aaae66179f269b7b37d0b526029c5783bed1da3 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Mon, 23 Feb 2009 13:08:35 +0000 Subject: [PATCH 4508/4982] [WATCHDOG] rc32434_wdt: add shutdown method Add shutdown method to the platform driver. Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/rc32434_wdt.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c index 89f326a39b6..eee29923a14 100644 --- a/drivers/watchdog/rc32434_wdt.c +++ b/drivers/watchdog/rc32434_wdt.c @@ -301,11 +301,17 @@ static int __devexit rc32434_wdt_remove(struct platform_device *pdev) return 0; } +static void rc32434_wdt_shutdown(struct platform_device *pdev) +{ + rc32434_wdt_stop(); +} + static struct platform_driver rc32434_wdt_driver = { - .probe = rc32434_wdt_probe, - .remove = __devexit_p(rc32434_wdt_remove), - .driver = { - .name = "rc32434_wdt", + .probe = rc32434_wdt_probe, + .remove = __devexit_p(rc32434_wdt_remove), + .shutdown = rc32434_wdt_shutdown, + .driver = { + .name = "rc32434_wdt", } }; -- GitLab From e455b6b4ed66be0c2aa6e41fd9027c1ce585a490 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Mon, 23 Feb 2009 13:08:36 +0000 Subject: [PATCH 4509/4982] [WATCHDOG] rc32434_wdt: add spin_locking Add spin_locks to prevent races. Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/rc32434_wdt.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c index eee29923a14..bffd4a2b115 100644 --- a/drivers/watchdog/rc32434_wdt.c +++ b/drivers/watchdog/rc32434_wdt.c @@ -28,6 +28,7 @@ #include /* For the watchdog specific items */ #include /* For __init/__exit/... */ #include /* For platform_driver framework */ +#include /* For spin_lock/spin_unlock/... */ #include /* For copy_to_user/put_user/... */ #include /* For the Watchdog registers */ @@ -38,6 +39,7 @@ static struct { unsigned long inuse; + spinlock_t io_lock; } rc32434_wdt_device; static struct integ __iomem *wdt_reg; @@ -81,7 +83,9 @@ static int rc32434_wdt_set(int new_timeout) return -EINVAL; } timeout = new_timeout; + spin_lock(&rc32434_wdt_device.io_lock); writel(SEC2WTCOMP(timeout), &wdt_reg->wtcompare); + spin_unlock(&rc32434_wdt_device.io_lock); return 0; } @@ -90,6 +94,8 @@ static void rc32434_wdt_start(void) { u32 or, nand; + spin_lock(&rc32434_wdt_device.io_lock); + /* zero the counter before enabling */ writel(0, &wdt_reg->wtcount); @@ -112,20 +118,26 @@ static void rc32434_wdt_start(void) SET_BITS(wdt_reg->wtc, or, nand); + spin_unlock(&rc32434_wdt_device.io_lock); printk(KERN_INFO PFX "Started watchdog timer.\n"); } static void rc32434_wdt_stop(void) { + spin_lock(&rc32434_wdt_device.io_lock); + /* Disable WDT */ SET_BITS(wdt_reg->wtc, 0, 1 << RC32434_WTC_EN); + spin_unlock(&rc32434_wdt_device.io_lock); printk(KERN_INFO PFX "Stopped watchdog timer.\n"); } static void rc32434_wdt_ping(void) { + spin_lock(&rc32434_wdt_device.io_lock); writel(0, &wdt_reg->wtcount); + spin_unlock(&rc32434_wdt_device.io_lock); } static int rc32434_wdt_open(struct inode *inode, struct file *file) @@ -270,6 +282,8 @@ static int __devinit rc32434_wdt_probe(struct platform_device *pdev) return -ENXIO; } + spin_lock_init(&rc32434_wdt_device.io_lock); + /* Check that the heartbeat value is within it's range; * if not reset to the default */ if (rc32434_wdt_set(timeout)) { -- GitLab From f296b14355a2d0cb170a85236ec391bb0a3fdb3a Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Mon, 23 Feb 2009 13:08:37 +0000 Subject: [PATCH 4510/4982] [WATCHDOG] rc32434_wdt: make sure watchdog is not running at startup Make sure that the watchdog is not running after loading and before it is started by opening /dev/watchdog. Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/rc32434_wdt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c index bffd4a2b115..071ff7bb81d 100644 --- a/drivers/watchdog/rc32434_wdt.c +++ b/drivers/watchdog/rc32434_wdt.c @@ -35,7 +35,7 @@ #define PFX KBUILD_MODNAME ": " -#define VERSION "0.5" +#define VERSION "1.0" static struct { unsigned long inuse; @@ -284,6 +284,9 @@ static int __devinit rc32434_wdt_probe(struct platform_device *pdev) spin_lock_init(&rc32434_wdt_device.io_lock); + /* Make sure the watchdog is not running */ + rc32434_wdt_stop(); + /* Check that the heartbeat value is within it's range; * if not reset to the default */ if (rc32434_wdt_set(timeout)) { -- GitLab From 9e058d4f57751daa008b764735f97fdfccfeab6c Mon Sep 17 00:00:00 2001 From: Thomas Reitmayr Date: Tue, 24 Feb 2009 14:59:22 -0800 Subject: [PATCH 4511/4982] [WATCHDOG] orion5x_wdt: fix compile issue by providing tclk as platform data The orion5x-wdt driver is now registered as a platform device and receives the tclk value as platform data. This fixes a compile issue cause by a previously removed define "ORION5X_TCLK". Signed-off-by: Thomas Reitmayr Acked-by: Nicolas Pitre Signed-off-by: Kristof Provost Cc: Lennert Buytenhek Cc: Wim Van Sebroeck Cc: Russell King Cc: Martin Michlmayr Cc: Sylver Bruneau Cc: Kunihiko IMAI Signed-off-by: Andrew Morton --- arch/arm/mach-orion5x/common.c | 29 +++++++ .../arm/plat-orion/include/plat/orion5x_wdt.h | 18 +++++ drivers/watchdog/orion5x_wdt.c | 76 +++++++++++++++---- 3 files changed, 109 insertions(+), 14 deletions(-) create mode 100644 arch/arm/plat-orion/include/plat/orion5x_wdt.h diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c index 8a0e49d8425..1a1df24f419 100644 --- a/arch/arm/mach-orion5x/common.c +++ b/arch/arm/mach-orion5x/common.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "common.h" @@ -532,6 +533,29 @@ void __init orion5x_xor_init(void) } +/***************************************************************************** + * Watchdog + ****************************************************************************/ +static struct orion5x_wdt_platform_data orion5x_wdt_data = { + .tclk = 0, +}; + +static struct platform_device orion5x_wdt_device = { + .name = "orion5x_wdt", + .id = -1, + .dev = { + .platform_data = &orion5x_wdt_data, + }, + .num_resources = 0, +}; + +void __init orion5x_wdt_init(void) +{ + orion5x_wdt_data.tclk = orion5x_tclk; + platform_device_register(&orion5x_wdt_device); +} + + /***************************************************************************** * Time handling ****************************************************************************/ @@ -631,6 +655,11 @@ void __init orion5x_init(void) printk(KERN_INFO "Orion: Applying 5281 D0 WFI workaround.\n"); disable_hlt(); } + + /* + * Register watchdog driver + */ + orion5x_wdt_init(); } /* diff --git a/arch/arm/plat-orion/include/plat/orion5x_wdt.h b/arch/arm/plat-orion/include/plat/orion5x_wdt.h new file mode 100644 index 00000000000..3c9cf6a305e --- /dev/null +++ b/arch/arm/plat-orion/include/plat/orion5x_wdt.h @@ -0,0 +1,18 @@ +/* + * arch/arm/plat-orion/include/plat/orion5x_wdt.h + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __PLAT_ORION5X_WDT_H +#define __PLAT_ORION5X_WDT_H + +struct orion5x_wdt_platform_data { + u32 tclk; /* no support yet */ +}; + + +#endif + diff --git a/drivers/watchdog/orion5x_wdt.c b/drivers/watchdog/orion5x_wdt.c index b64ae1a1783..e81441f103d 100644 --- a/drivers/watchdog/orion5x_wdt.c +++ b/drivers/watchdog/orion5x_wdt.c @@ -16,11 +16,13 @@ #include #include #include +#include #include #include #include #include #include +#include /* * Watchdog timer block registers. @@ -29,13 +31,14 @@ #define WDT_EN 0x0010 #define WDT_VAL (TIMER_VIRT_BASE + 0x0024) -#define ORION5X_TCLK 166666667 -#define WDT_MAX_DURATION (0xffffffff / ORION5X_TCLK) +#define WDT_MAX_CYCLE_COUNT 0xffffffff #define WDT_IN_USE 0 #define WDT_OK_TO_CLOSE 1 static int nowayout = WATCHDOG_NOWAYOUT; -static int heartbeat = WDT_MAX_DURATION; /* (seconds) */ +static int heartbeat = -1; /* module parameter (seconds) */ +static unsigned int wdt_max_duration; /* (seconds) */ +static unsigned int wdt_tclk; static unsigned long wdt_status; static spinlock_t wdt_lock; @@ -46,7 +49,7 @@ static void wdt_enable(void) spin_lock(&wdt_lock); /* Set watchdog duration */ - writel(ORION5X_TCLK * heartbeat, WDT_VAL); + writel(wdt_tclk * heartbeat, WDT_VAL); /* Clear watchdog timer interrupt */ reg = readl(BRIDGE_CAUSE); @@ -88,7 +91,7 @@ static void wdt_disable(void) static int orion5x_wdt_get_timeleft(int *time_left) { spin_lock(&wdt_lock); - *time_left = readl(WDT_VAL) / ORION5X_TCLK; + *time_left = readl(WDT_VAL) / wdt_tclk; spin_unlock(&wdt_lock); return 0; } @@ -158,7 +161,7 @@ static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd, if (ret) break; - if (time <= 0 || time > WDT_MAX_DURATION) { + if (time <= 0 || time > wdt_max_duration) { ret = -EINVAL; break; } @@ -210,23 +213,69 @@ static struct miscdevice orion5x_wdt_miscdev = { .fops = &orion5x_wdt_fops, }; -static int __init orion5x_wdt_init(void) +static int __devinit orion5x_wdt_probe(struct platform_device *pdev) { + struct orion5x_wdt_platform_data *pdata = pdev->dev.platform_data; int ret; - spin_lock_init(&wdt_lock); + if (pdata) { + wdt_tclk = pdata->tclk; + } else { + printk(KERN_ERR "Orion5x Watchdog misses platform data\n"); + return -ENODEV; + } + + if (orion5x_wdt_miscdev.parent) + return -EBUSY; + orion5x_wdt_miscdev.parent = &pdev->dev; + + wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk; + if (heartbeat <= 0 || heartbeat > wdt_max_duration) + heartbeat = wdt_max_duration; ret = misc_register(&orion5x_wdt_miscdev); - if (ret == 0) - printk("Orion5x Watchdog Timer: heartbeat %d sec\n", - heartbeat); + if (ret) + return ret; + + printk(KERN_INFO "Orion5x Watchdog Timer: Initial timeout %d sec%s\n", + heartbeat, nowayout ? ", nowayout" : ""); + return 0; +} + +static int __devexit orion5x_wdt_remove(struct platform_device *pdev) +{ + int ret; + + if (test_bit(WDT_IN_USE, &wdt_status)) { + wdt_disable(); + clear_bit(WDT_IN_USE, &wdt_status); + } + + ret = misc_deregister(&orion5x_wdt_miscdev); + if (!ret) + orion5x_wdt_miscdev.parent = NULL; return ret; } +static struct platform_driver orion5x_wdt_driver = { + .probe = orion5x_wdt_probe, + .remove = __devexit_p(orion5x_wdt_remove), + .driver = { + .owner = THIS_MODULE, + .name = "orion5x_wdt", + }, +}; + +static int __init orion5x_wdt_init(void) +{ + spin_lock_init(&wdt_lock); + return platform_driver_register(&orion5x_wdt_driver); +} + static void __exit orion5x_wdt_exit(void) { - misc_deregister(&orion5x_wdt_miscdev); + platform_driver_unregister(&orion5x_wdt_driver); } module_init(orion5x_wdt_init); @@ -236,8 +285,7 @@ MODULE_AUTHOR("Sylver Bruneau "); MODULE_DESCRIPTION("Orion5x Processor Watchdog"); module_param(heartbeat, int, 0); -MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default is " - __MODULE_STRING(WDT_MAX_DURATION) ")"); +MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds"); module_param(nowayout, int, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); -- GitLab From 2855d28a35d14e0087c48cb6f15d0446ea4c54c3 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 29 Dec 2008 11:23:47 +0100 Subject: [PATCH 4512/4982] [PATCH 13/13] drivers/watchdog: use USB API functions rather than constants This set of patches introduces calls to the following set of functions: usb_endpoint_dir_in(epd) usb_endpoint_dir_out(epd) usb_endpoint_is_bulk_in(epd) usb_endpoint_is_bulk_out(epd) usb_endpoint_is_int_in(epd) usb_endpoint_is_int_out(epd) usb_endpoint_num(epd) usb_endpoint_type(epd) usb_endpoint_xfer_bulk(epd) usb_endpoint_xfer_control(epd) usb_endpoint_xfer_int(epd) usb_endpoint_xfer_isoc(epd) In some cases, introducing one of these functions is not possible, and it just replaces an explicit integer value by one of the following constants: USB_ENDPOINT_XFER_BULK USB_ENDPOINT_XFER_CONTROL USB_ENDPOINT_XFER_INT USB_ENDPOINT_XFER_ISOC An extract of the semantic patch that makes these changes is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r1@ struct usb_endpoint_descriptor *epd; @@ - ((epd->bmAttributes & \(USB_ENDPOINT_XFERTYPE_MASK\|3\)) == - \(USB_ENDPOINT_XFER_CONTROL\|0\)) + usb_endpoint_xfer_control(epd) @r5@ struct usb_endpoint_descriptor *epd; @@ - ((epd->bEndpointAddress & \(USB_ENDPOINT_DIR_MASK\|0x80\)) == - \(USB_DIR_IN\|0x80\)) + usb_endpoint_dir_in(epd) @inc@ @@ #include @depends on !inc && (r1||r5)@ @@ + #include #include // Signed-off-by: Julia Lawall Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/pcwd_usb.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c index afb089695da..b5320a8e745 100644 --- a/drivers/watchdog/pcwd_usb.c +++ b/drivers/watchdog/pcwd_usb.c @@ -609,9 +609,7 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi /* check out the endpoint: it has to be Interrupt & IN */ endpoint = &iface_desc->endpoint[0].desc; - if (!((endpoint->bEndpointAddress & USB_DIR_IN) && - ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_INT))) { + if (!usb_endpoint_is_int_in(endpoint)) { /* we didn't find a Interrupt endpoint with direction IN */ printk(KERN_ERR PFX "Couldn't find an INTR & IN endpoint\n"); return -ENODEV; -- GitLab From d8100c3abfd32986a8820ce4e614b0223a2d22a9 Mon Sep 17 00:00:00 2001 From: Thomas Mingarelli Date: Tue, 3 Mar 2009 00:17:16 +0000 Subject: [PATCH 4513/4982] [WATCHDOG] hpwdt.c: Add new HP BMC controller. Add the PCI-ID for the upcoming new BMC controller for HP hardware. Signed-off-by: Thomas Mingarelli Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/hpwdt.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 763c1ea5dce..dad4fe6e20f 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -47,6 +47,7 @@ #define PCI_BIOS32_PARAGRAPH_LEN 16 #define PCI_ROM_BASE1 0x000F0000 #define ROM_SIZE 0x10000 +#define HPWDT_VERSION "1.01" struct bios32_service_dir { u32 signature; @@ -130,12 +131,8 @@ static void *cru_rom_addr; static struct cmn_registers cmn_regs; static struct pci_device_id hpwdt_devices[] = { - { - .vendor = PCI_VENDOR_ID_COMPAQ, - .device = 0xB203, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, + { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB203) }, + { PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3306) }, {0}, /* terminate list */ }; MODULE_DEVICE_TABLE(pci, hpwdt_devices); @@ -704,10 +701,11 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev, } printk(KERN_INFO - "hp Watchdog Timer Driver: 1.00" + "hp Watchdog Timer Driver: %s" ", timer margin: %d seconds (nowayout=%d)" ", allow kernel dump: %s (default = 0/OFF).\n", - soft_margin, nowayout, (allow_kdump == 0) ? "OFF" : "ON"); + HPWDT_VERSION, soft_margin, nowayout, + (allow_kdump == 0) ? "OFF" : "ON"); return 0; @@ -757,6 +755,7 @@ static int __init hpwdt_init(void) MODULE_AUTHOR("Tom Mingarelli"); MODULE_DESCRIPTION("hp watchdog driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(HPWDT_VERSION); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); module_param(soft_margin, int, 0); -- GitLab From 927d69611398f046c4447ce5ded992321c8f90ff Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Wed, 18 Mar 2009 08:05:24 +0000 Subject: [PATCH 4514/4982] [WATCHDOG] cpwd.c: Coding style - Clean-up This brings the cpwd.c watchdog driver in line with the kernel's coding style. Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/cpwd.c | 78 +++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c index 261790afd65..0c14586f58d 100644 --- a/drivers/watchdog/cpwd.c +++ b/drivers/watchdog/cpwd.c @@ -1,13 +1,13 @@ /* cpwd.c - driver implementation for hardware watchdog * timers found on Sun Microsystems CP1400 and CP1500 boards. * - * This device supports both the generic Linux watchdog + * This device supports both the generic Linux watchdog * interface and Solaris-compatible ioctls as best it is * able. * * NOTE: CP1400 systems appear to have a defective intr_mask * register on the PLD, preventing the disabling of - * timer interrupts. We use a timer to periodically + * timer interrupts. We use a timer to periodically * reset 'stopped' watchdogs on affected platforms. * * Copyright (c) 2000 Eric Brower (ebrower@usa.net) @@ -43,8 +43,8 @@ #define WD_BLIMIT 0xFFFF #define WD0_MINOR 212 -#define WD1_MINOR 213 -#define WD2_MINOR 214 +#define WD1_MINOR 213 +#define WD2_MINOR 214 /* Internal driver definitions. */ #define WD0_ID 0 @@ -91,16 +91,16 @@ struct cpwd { static struct cpwd *cpwd_device; -/* Sun uses Altera PLD EPF8820ATC144-4 +/* Sun uses Altera PLD EPF8820ATC144-4 * providing three hardware watchdogs: * - * 1) RIC - sends an interrupt when triggered - * 2) XIR - asserts XIR_B_RESET when triggered, resets CPU - * 3) POR - asserts POR_B_RESET when triggered, resets CPU, backplane, board + * 1) RIC - sends an interrupt when triggered + * 2) XIR - asserts XIR_B_RESET when triggered, resets CPU + * 3) POR - asserts POR_B_RESET when triggered, resets CPU, backplane, board * *** Timer register block definition (struct wd_timer_regblk) * - * dcntr and limit registers (halfword access): + * dcntr and limit registers (halfword access): * ------------------- * | 15 | ...| 1 | 0 | * ------------------- @@ -108,7 +108,8 @@ static struct cpwd *cpwd_device; * ------------------- * dcntr - Current 16-bit downcounter value. * When downcounter reaches '0' watchdog expires. - * Reading this register resets downcounter with 'limit' value. + * Reading this register resets downcounter with + * 'limit' value. * limit - 16-bit countdown value in 1/10th second increments. * Writing this register begins countdown with input value. * Reading from this register does not affect counter. @@ -158,11 +159,11 @@ static int wd0_timeout = 0; static int wd1_timeout = 0; static int wd2_timeout = 0; -module_param (wd0_timeout, int, 0); +module_param(wd0_timeout, int, 0); MODULE_PARM_DESC(wd0_timeout, "Default watchdog0 timeout in 1/10secs"); -module_param (wd1_timeout, int, 0); +module_param(wd1_timeout, int, 0); MODULE_PARM_DESC(wd1_timeout, "Default watchdog1 timeout in 1/10secs"); -module_param (wd2_timeout, int, 0); +module_param(wd2_timeout, int, 0); MODULE_PARM_DESC(wd2_timeout, "Default watchdog2 timeout in 1/10secs"); MODULE_AUTHOR("Eric Brower "); @@ -201,9 +202,9 @@ static u8 cpwd_readb(void __iomem *addr) static void cpwd_toggleintr(struct cpwd *p, int index, int enable) { unsigned char curregs = cpwd_readb(p->regs + PLD_IMASK); - unsigned char setregs = - (index == -1) ? - (WD0_INTR_MASK | WD1_INTR_MASK | WD2_INTR_MASK) : + unsigned char setregs = + (index == -1) ? + (WD0_INTR_MASK | WD1_INTR_MASK | WD2_INTR_MASK) : (p->devs[index].intr_mask); if (enable == WD_INTR_ON) @@ -303,24 +304,24 @@ static int cpwd_getstatus(struct cpwd *p, int index) unsigned char ret = WD_STOPPED; /* determine STOPPED */ - if (!stat) + if (!stat) return ret; /* determine EXPIRED vs FREERUN vs RUNNING */ else if (WD_S_EXPIRED & stat) { ret = WD_EXPIRED; - } else if(WD_S_RUNNING & stat) { + } else if (WD_S_RUNNING & stat) { if (intr & p->devs[index].intr_mask) { ret = WD_FREERUN; } else { /* Fudge WD_EXPIRED status for defective CP1400-- - * IF timer is running - * AND brokenstop is set + * IF timer is running + * AND brokenstop is set * AND an interrupt has been serviced * we are WD_EXPIRED. * - * IF timer is running - * AND brokenstop is set + * IF timer is running + * AND brokenstop is set * AND no interrupt has been serviced * we are WD_FREERUN. */ @@ -329,7 +330,8 @@ static int cpwd_getstatus(struct cpwd *p, int index) if (p->devs[index].runstatus & WD_STAT_SVCD) { ret = WD_EXPIRED; } else { - /* we could as well pretend we are expired */ + /* we could as well pretend + * we are expired */ ret = WD_FREERUN; } } else { @@ -342,7 +344,7 @@ static int cpwd_getstatus(struct cpwd *p, int index) if (p->devs[index].runstatus & WD_STAT_SVCD) ret |= WD_SERVICED; - return(ret); + return ret; } static irqreturn_t cpwd_interrupt(int irq, void *dev_id) @@ -367,22 +369,22 @@ static int cpwd_open(struct inode *inode, struct file *f) struct cpwd *p = cpwd_device; lock_kernel(); - switch(iminor(inode)) { - case WD0_MINOR: - case WD1_MINOR: - case WD2_MINOR: - break; + switch (iminor(inode)) { + case WD0_MINOR: + case WD1_MINOR: + case WD2_MINOR: + break; - default: - unlock_kernel(); - return -ENODEV; + default: + unlock_kernel(); + return -ENODEV; } /* Register IRQ on first open of device */ if (!p->initialized) { - if (request_irq(p->irq, &cpwd_interrupt, + if (request_irq(p->irq, &cpwd_interrupt, IRQF_SHARED, DRIVER_NAME, p)) { - printk(KERN_ERR PFX "Cannot register IRQ %d\n", + printk(KERN_ERR PFX "Cannot register IRQ %d\n", p->irq); unlock_kernel(); return -EBUSY; @@ -442,7 +444,7 @@ static long cpwd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) cpwd_starttimer(p, index); } else { return -EINVAL; - } + } break; /* Solaris-compatible IOCTLs */ @@ -458,7 +460,7 @@ static long cpwd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case WIOCSTOP: if (p->enabled) - return(-EINVAL); + return -EINVAL; cpwd_stoptimer(p, index); break; @@ -493,7 +495,7 @@ static long cpwd_compat_ioctl(struct file *file, unsigned int cmd, return rval; } -static ssize_t cpwd_write(struct file *file, const char __user *buf, +static ssize_t cpwd_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { struct inode *inode = file->f_path.dentry->d_inode; @@ -508,7 +510,7 @@ static ssize_t cpwd_write(struct file *file, const char __user *buf, return 0; } -static ssize_t cpwd_read(struct file * file, char __user *buffer, +static ssize_t cpwd_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { return -EINVAL; -- GitLab From d5c26a597782d4109869abbcc36983969f964864 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Wed, 18 Mar 2009 08:18:43 +0000 Subject: [PATCH 4515/4982] [WATCHDOG] struct file_operations should be const Fix following warnings: WARNING: struct file_operations should normally be const Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/hpwdt.c | 2 +- drivers/watchdog/rc32434_wdt.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index dad4fe6e20f..7cf32ad96fd 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -602,7 +602,7 @@ static long hpwdt_ioctl(struct file *file, unsigned int cmd, /* * Kernel interfaces */ -static struct file_operations hpwdt_fops = { +static const struct file_operations hpwdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = hpwdt_write, diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c index 071ff7bb81d..f6cccc9df02 100644 --- a/drivers/watchdog/rc32434_wdt.c +++ b/drivers/watchdog/rc32434_wdt.c @@ -247,7 +247,7 @@ static long rc32434_wdt_ioctl(struct file *file, unsigned int cmd, return 0; } -static struct file_operations rc32434_wdt_fops = { +static const struct file_operations rc32434_wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = rc32434_wdt_write, -- GitLab From 143a2e54bf53216674eada16e8953f48b159e08a Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Wed, 18 Mar 2009 08:35:09 +0000 Subject: [PATCH 4516/4982] [WATCHDOG] More coding-style and trivial clean-up Some more cleaning-up of the watchdog drivers. Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/acquirewdt.c | 8 +- drivers/watchdog/advantechwdt.c | 7 +- drivers/watchdog/alim1535_wdt.c | 20 +-- drivers/watchdog/alim7101_wdt.c | 6 +- drivers/watchdog/at91sam9_wdt.c | 2 +- drivers/watchdog/eurotechwdt.c | 22 ++-- drivers/watchdog/geodewdt.c | 11 +- drivers/watchdog/hpwdt.c | 3 +- drivers/watchdog/i6300esb.c | 3 +- drivers/watchdog/iTCO_vendor_support.c | 6 +- drivers/watchdog/iTCO_wdt.c | 15 ++- drivers/watchdog/it87_wdt.c | 12 +- drivers/watchdog/mpc5200_wdt.c | 4 +- drivers/watchdog/mpcore_wdt.c | 2 +- drivers/watchdog/mtx-1_wdt.c | 2 +- drivers/watchdog/pc87413_wdt.c | 6 +- drivers/watchdog/pcwd.c | 44 ++++--- drivers/watchdog/pcwd_pci.c | 108 ++++++++++------ drivers/watchdog/pcwd_usb.c | 171 ++++++++++++++++--------- drivers/watchdog/pnx4008_wdt.c | 18 +-- drivers/watchdog/riowd.c | 3 +- drivers/watchdog/sa1100_wdt.c | 6 +- drivers/watchdog/sbc60xxwdt.c | 2 +- drivers/watchdog/sbc8360.c | 12 +- drivers/watchdog/sbc_epx_c3.c | 3 +- drivers/watchdog/sc1200wdt.c | 7 +- drivers/watchdog/sc520_wdt.c | 9 +- drivers/watchdog/smsc37b787_wdt.c | 30 ++--- drivers/watchdog/softdog.c | 5 +- drivers/watchdog/w83697hf_wdt.c | 3 +- drivers/watchdog/w83697ug_wdt.c | 2 +- drivers/watchdog/w83977f_wdt.c | 2 +- drivers/watchdog/wd501p.h | 24 ++-- drivers/watchdog/wdt977.c | 2 +- 34 files changed, 344 insertions(+), 236 deletions(-) diff --git a/drivers/watchdog/acquirewdt.c b/drivers/watchdog/acquirewdt.c index 3e57aa4d643..4d18c874d96 100644 --- a/drivers/watchdog/acquirewdt.c +++ b/drivers/watchdog/acquirewdt.c @@ -1,7 +1,7 @@ /* * Acquire Single Board Computer Watchdog Timer driver * - * Based on wdt.c. Original copyright messages: + * Based on wdt.c. Original copyright messages: * * (c) Copyright 1996 Alan Cox , * All Rights Reserved. @@ -17,9 +17,9 @@ * * (c) Copyright 1995 Alan Cox * - * 14-Dec-2001 Matt Domsch - * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT - * Can't add timeout - driver doesn't allow changing value + * 14-Dec-2001 Matt Domsch + * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT + * Can't add timeout - driver doesn't allow changing value */ /* diff --git a/drivers/watchdog/advantechwdt.c b/drivers/watchdog/advantechwdt.c index a1d7856ea6e..824d076a5cd 100644 --- a/drivers/watchdog/advantechwdt.c +++ b/drivers/watchdog/advantechwdt.c @@ -138,7 +138,9 @@ static long advwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) void __user *argp = (void __user *)arg; int __user *p = argp; static struct watchdog_info ident = { - .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, + .options = WDIOF_KEEPALIVEPING | + WDIOF_SETTIMEOUT | + WDIOF_MAGICCLOSE, .firmware_version = 1, .identity = WATCHDOG_NAME, }; @@ -259,7 +261,8 @@ static int __devinit advwdt_probe(struct platform_device *dev) goto unreg_stop; } - /* Check that the heartbeat value is within it's range ; if not reset to the default */ + /* Check that the heartbeat value is within it's range ; + * if not reset to the default */ if (advwdt_set_heartbeat(timeout)) { advwdt_set_heartbeat(WATCHDOG_TIMEOUT); printk(KERN_INFO PFX diff --git a/drivers/watchdog/alim1535_wdt.c b/drivers/watchdog/alim1535_wdt.c index 2a7690ecf97..937a80fb61e 100644 --- a/drivers/watchdog/alim1535_wdt.c +++ b/drivers/watchdog/alim1535_wdt.c @@ -60,7 +60,7 @@ static void ali_start(void) pci_read_config_dword(ali_pci, 0xCC, &val); val &= ~0x3F; /* Mask count */ - val |= (1<<25) | ali_timeout_bits; + val |= (1 << 25) | ali_timeout_bits; pci_write_config_dword(ali_pci, 0xCC, val); spin_unlock(&ali_lock); @@ -79,8 +79,8 @@ static void ali_stop(void) spin_lock(&ali_lock); pci_read_config_dword(ali_pci, 0xCC, &val); - val &= ~0x3F; /* Mask count to zero (disabled) */ - val &= ~(1<<25);/* and for safety mask the reset enable */ + val &= ~0x3F; /* Mask count to zero (disabled) */ + val &= ~(1 << 25); /* and for safety mask the reset enable */ pci_write_config_dword(ali_pci, 0xCC, val); spin_unlock(&ali_lock); @@ -89,7 +89,7 @@ static void ali_stop(void) /* * ali_keepalive - send a keepalive to the watchdog * - * Send a keepalive to the timer (actually we restart the timer). + * Send a keepalive to the timer (actually we restart the timer). */ static void ali_keepalive(void) @@ -109,11 +109,11 @@ static int ali_settimer(int t) if (t < 0) return -EINVAL; else if (t < 60) - ali_timeout_bits = t|(1<<6); + ali_timeout_bits = t|(1 << 6); else if (t < 3600) - ali_timeout_bits = (t/60)|(1<<7); + ali_timeout_bits = (t / 60)|(1 << 7); else if (t < 18000) - ali_timeout_bits = (t/300)|(1<<6)|(1<<7); + ali_timeout_bits = (t / 300)|(1 << 6)|(1 << 7); else return -EINVAL; @@ -138,7 +138,7 @@ static int ali_settimer(int t) */ static ssize_t ali_write(struct file *file, const char __user *data, - size_t len, loff_t *ppos) + size_t len, loff_t *ppos) { /* See if we got the magic character 'V' and reload the timer */ if (len) { @@ -348,9 +348,9 @@ static int __init ali_find_watchdog(void) /* Timer bits */ wdog &= ~0x3F; /* Issued events */ - wdog &= ~((1<<27)|(1<<26)|(1<<25)|(1<<24)); + wdog &= ~((1 << 27)|(1 << 26)|(1 << 25)|(1 << 24)); /* No monitor bits */ - wdog &= ~((1<<16)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)); + wdog &= ~((1 << 16)|(1 << 13)|(1 << 12)|(1 << 11)|(1 << 10)|(1 << 9)); pci_write_config_dword(pdev, 0xCC, wdog); diff --git a/drivers/watchdog/alim7101_wdt.c b/drivers/watchdog/alim7101_wdt.c index a045ef86943..90f98df5f10 100644 --- a/drivers/watchdog/alim7101_wdt.c +++ b/drivers/watchdog/alim7101_wdt.c @@ -355,7 +355,8 @@ static int __init alim7101_wdt_init(void) alim7101_pmu = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL); if (!alim7101_pmu) { - printk(KERN_INFO PFX "ALi M7101 PMU not present - WDT not set\n"); + printk(KERN_INFO PFX + "ALi M7101 PMU not present - WDT not set\n"); return -EBUSY; } @@ -399,7 +400,8 @@ static int __init alim7101_wdt_init(void) rc = misc_register(&wdt_miscdev); if (rc) { - printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", + printk(KERN_ERR PFX + "cannot register miscdev on minor=%d (err=%d)\n", wdt_miscdev.minor, rc); goto err_out_reboot; } diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c index a56ac84381b..435b0573fb0 100644 --- a/drivers/watchdog/at91sam9_wdt.c +++ b/drivers/watchdog/at91sam9_wdt.c @@ -201,7 +201,7 @@ static long at91_wdt_ioctl(struct file *file, * Pat the watchdog whenever device is written to. */ static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, - loff_t *ppos) + loff_t *ppos) { if (!len) return 0; diff --git a/drivers/watchdog/eurotechwdt.c b/drivers/watchdog/eurotechwdt.c index a171fc6ae1c..9add3541fb4 100644 --- a/drivers/watchdog/eurotechwdt.c +++ b/drivers/watchdog/eurotechwdt.c @@ -8,19 +8,19 @@ * Based on wdt.c. * Original copyright messages: * - * (c) Copyright 1996-1997 Alan Cox , + * (c) Copyright 1996-1997 Alan Cox , * All Rights Reserved. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. * - * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide - * warranty for any of this software. This material is provided - * "AS-IS" and at no charge. + * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. * - * (c) Copyright 1995 Alan Cox * + * (c) Copyright 1995 Alan Cox * */ /* Changelog: @@ -37,7 +37,7 @@ * add expect_close support * * 2002.05.30 - Joel Becker - * Added Matt Domsch's nowayout module option. + * Added Matt Domsch's nowayout module option. */ /* @@ -151,7 +151,7 @@ static void eurwdt_activate_timer(void) if (irq == 0) printk(KERN_INFO ": interrupt disabled\n"); - eurwdt_write_reg(WDT_TIMER_CFG, irq<<4); + eurwdt_write_reg(WDT_TIMER_CFG, irq << 4); eurwdt_write_reg(WDT_UNIT_SEL, WDT_UNIT_SECS); /* we use seconds */ eurwdt_set_timeout(0); /* the default timeout */ diff --git a/drivers/watchdog/geodewdt.c b/drivers/watchdog/geodewdt.c index 6799a6de66f..9acf0015a1e 100644 --- a/drivers/watchdog/geodewdt.c +++ b/drivers/watchdog/geodewdt.c @@ -34,11 +34,15 @@ static int timeout = WATCHDOG_TIMEOUT; module_param(timeout, int, 0); -MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=131, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); +MODULE_PARM_DESC(timeout, + "Watchdog timeout in seconds. 1<= timeout <=131, default=" + __MODULE_STRING(WATCHDOG_TIMEOUT) "."); static int nowayout = WATCHDOG_NOWAYOUT; module_param(nowayout, int, 0); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); +MODULE_PARM_DESC(nowayout, + "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); static struct platform_device *geodewdt_platform_device; static unsigned long wdt_flags; @@ -269,7 +273,8 @@ static int __init geodewdt_init(void) if (ret) return ret; - geodewdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0); + geodewdt_platform_device = platform_device_register_simple(DRV_NAME, + -1, NULL, 0); if (IS_ERR(geodewdt_platform_device)) { ret = PTR_ERR(geodewdt_platform_device); goto err; diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 7cf32ad96fd..6cf155d6b35 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -137,7 +137,8 @@ static struct pci_device_id hpwdt_devices[] = { }; MODULE_DEVICE_TABLE(pci, hpwdt_devices); -extern asmlinkage void asminline_call(struct cmn_registers *pi86Regs, unsigned long *pRomEntry); +extern asmlinkage void asminline_call(struct cmn_registers *pi86Regs, + unsigned long *pRomEntry); #ifndef CONFIG_X86_64 /* --32 Bit Bios------------------------------------------------------------ */ diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c index 74f951c18b9..97ac6bf4222 100644 --- a/drivers/watchdog/i6300esb.c +++ b/drivers/watchdog/i6300esb.c @@ -240,7 +240,8 @@ static ssize_t esb_write(struct file *file, const char __user *data, * five months ago... */ esb_expect_close = 0; - /* scan to see whether or not we got the magic character */ + /* scan to see whether or not we got the + * magic character */ for (i = 0; i != len; i++) { char c; if (get_user(c, data + i)) diff --git a/drivers/watchdog/iTCO_vendor_support.c b/drivers/watchdog/iTCO_vendor_support.c index d8264ad0be4..d3c0f6de552 100644 --- a/drivers/watchdog/iTCO_vendor_support.c +++ b/drivers/watchdog/iTCO_vendor_support.c @@ -47,7 +47,8 @@ static int vendorsupport; module_param(vendorsupport, int, 0); -MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default=0 (none), 1=SuperMicro Pent3, 2=SuperMicro Pent4+"); +MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default=" + "0 (none), 1=SuperMicro Pent3, 2=SuperMicro Pent4+"); /* * Vendor Specific Support @@ -305,7 +306,8 @@ static void __exit iTCO_vendor_exit_module(void) module_init(iTCO_vendor_init_module); module_exit(iTCO_vendor_exit_module); -MODULE_AUTHOR("Wim Van Sebroeck , R. Seretny "); +MODULE_AUTHOR("Wim Van Sebroeck , " + "R. Seretny "); MODULE_DESCRIPTION("Intel TCO Vendor Specific WatchDog Timer Driver Support"); MODULE_VERSION(DRV_VERSION); MODULE_LICENSE("GPL"); diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 352334947ea..648250b998c 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -273,7 +273,9 @@ static struct platform_device *iTCO_wdt_platform_device; #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ module_param(heartbeat, int, 0); -MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2> 8, VAL); - outb(reg, REG); - outb(val, VAL); + outb(reg++, REG); + outb(val >> 8, VAL); + outb(reg, REG); + outb(val, VAL); } /* watchdog timer handling */ diff --git a/drivers/watchdog/mpc5200_wdt.c b/drivers/watchdog/mpc5200_wdt.c index db91892558f..465fe36adad 100644 --- a/drivers/watchdog/mpc5200_wdt.c +++ b/drivers/watchdog/mpc5200_wdt.c @@ -9,8 +9,8 @@ #include -#define GPT_MODE_WDT (1<<15) -#define GPT_MODE_CE (1<<12) +#define GPT_MODE_WDT (1 << 15) +#define GPT_MODE_CE (1 << 12) #define GPT_MODE_MS_TIMER (0x4) diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c index 1130ad697ce..1512ab8b175 100644 --- a/drivers/watchdog/mpcore_wdt.c +++ b/drivers/watchdog/mpcore_wdt.c @@ -5,7 +5,7 @@ * * Based on the SoftDog driver: * (c) Copyright 1996 Alan Cox , - * All Rights Reserved. + * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c index 3acce623f20..539b6f6ba7f 100644 --- a/drivers/watchdog/mtx-1_wdt.c +++ b/drivers/watchdog/mtx-1_wdt.c @@ -5,7 +5,7 @@ * All Rights Reserved. * http://www.4g-systems.biz * - * (C) Copyright 2007 OpenWrt.org, Florian Fainelli + * (C) Copyright 2007 OpenWrt.org, Florian Fainelli * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c index 484c215e9f3..1a2b916e3f8 100644 --- a/drivers/watchdog/pc87413_wdt.c +++ b/drivers/watchdog/pc87413_wdt.c @@ -536,7 +536,8 @@ static int __init pc87413_init(void) ret = misc_register(&pc87413_miscdev); if (ret != 0) { - printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", + printk(KERN_ERR PFX + "cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, ret); unregister_reboot_notifier(&pc87413_notifier); return ret; @@ -574,7 +575,8 @@ static void __exit pc87413_exit(void) module_init(pc87413_init); module_exit(pc87413_exit); -MODULE_AUTHOR("Sven Anders , Marcus Junker ,"); +MODULE_AUTHOR("Sven Anders , " + "Marcus Junker ,"); MODULE_DESCRIPTION("PC87413 WDT driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/watchdog/pcwd.c b/drivers/watchdog/pcwd.c index 9e1331a3b21..aa9512321f3 100644 --- a/drivers/watchdog/pcwd.c +++ b/drivers/watchdog/pcwd.c @@ -24,25 +24,25 @@ * version reporting. Added read routine for temperature. * Removed some extra defines, added an autodetect Revision * routine. - * 961006 Revised some documentation, fixed some cosmetic bugs. Made - * drivers to panic the system if it's overheating at bootup. + * 961006 Revised some documentation, fixed some cosmetic bugs. Made + * drivers to panic the system if it's overheating at bootup. * 961118 Changed some verbiage on some of the output, tidied up * code bits, and added compatibility to 2.1.x. - * 970912 Enabled board on open and disable on close. + * 970912 Enabled board on open and disable on close. * 971107 Took account of recent VFS changes (broke read). - * 971210 Disable board on initialisation in case board already ticking. - * 971222 Changed open/close for temperature handling - * Michael Meskes . - * 980112 Used minor numbers from include/linux/miscdevice.h - * 990403 Clear reset status after reading control status register in - * pcwd_showprevstate(). [Marc Boucher ] + * 971210 Disable board on initialisation in case board already ticking. + * 971222 Changed open/close for temperature handling + * Michael Meskes . + * 980112 Used minor numbers from include/linux/miscdevice.h + * 990403 Clear reset status after reading control status register in + * pcwd_showprevstate(). [Marc Boucher ] * 990605 Made changes to code to support Firmware 1.22a, added * fairly useless proc entry. * 990610 removed said useless proc code for the merge * 000403 Removed last traces of proc code. * 011214 Added nowayout module option to override * CONFIG_WATCHDOG_NOWAYOUT - * Added timeout module option to override default + * Added timeout module option to override default */ /* @@ -76,8 +76,7 @@ #define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog" #define WATCHDOG_NAME "pcwd" #define PFX WATCHDOG_NAME ": " -#define DRIVER_VERSION WATCHDOG_DRIVER_NAME " driver, v" WATCHDOG_VERSION " (" WATCHDOG_DATE ")\n" -#define WD_VER WATCHDOG_VERSION " (" WATCHDOG_DATE ")" +#define DRIVER_VERSION WATCHDOG_DRIVER_NAME " driver, v" WATCHDOG_VERSION "\n" /* * It should be noted that PCWD_REVISION_B was removed because A and B @@ -200,7 +199,9 @@ MODULE_PARM_DESC(debug, #define WATCHDOG_HEARTBEAT 0 static int heartbeat = WATCHDOG_HEARTBEAT; module_param(heartbeat, int, 0); -MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2 <= heartbeat <= 7200 or 0=delay-time from dip-switches, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); +MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. " + "(2 <= heartbeat <= 7200 or 0=delay-time from dip-switches, default=" + __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); static int nowayout = WATCHDOG_NOWAYOUT; module_param(nowayout, int, 0); @@ -239,7 +240,8 @@ static int send_isa_command(int cmd) } if (debug >= DEBUG) - printk(KERN_DEBUG PFX "received following data for cmd=0x%02x: port0=0x%02x last_port0=0x%02x\n", + printk(KERN_DEBUG PFX "received following data for " + "cmd=0x%02x: port0=0x%02x last_port0=0x%02x\n", cmd, port0, last_port0); return port0; @@ -339,10 +341,12 @@ static void pcwd_show_card_info(void) pcwd_private.io_addr); else if (pcwd_private.revision == PCWD_REVISION_C) { pcwd_get_firmware(); - printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n", + printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port " + "0x%04x (Firmware version: %s)\n", pcwd_private.io_addr, pcwd_private.fw_ver_str); option_switches = pcwd_get_option_switches(); - printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", + printk(KERN_INFO PFX "Option switches (0x%02x): " + "Temperature Reset Enable=%s, Power On Delay=%s\n", option_switches, ((option_switches & 0x10) ? "ON" : "OFF"), ((option_switches & 0x08) ? "ON" : "OFF")); @@ -358,7 +362,8 @@ static void pcwd_show_card_info(void) printk(KERN_INFO PFX "Temperature Option Detected\n"); if (pcwd_private.boot_status & WDIOF_CARDRESET) - printk(KERN_INFO PFX "Previous reboot was caused by the card\n"); + printk(KERN_INFO PFX + "Previous reboot was caused by the card\n"); if (pcwd_private.boot_status & WDIOF_OVERHEAT) { printk(KERN_EMERG PFX @@ -871,7 +876,7 @@ static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id) cards_found++; if (cards_found == 1) printk(KERN_INFO PFX "v%s Ken Hollis (kenji@bitgate.com)\n", - WD_VER); + WATCHDOG_VERSION); if (cards_found > 1) { printk(KERN_ERR PFX "This driver only supports 1 device\n"); @@ -1026,7 +1031,8 @@ static void __exit pcwd_cleanup_module(void) module_init(pcwd_init_module); module_exit(pcwd_cleanup_module); -MODULE_AUTHOR("Ken Hollis , Wim Van Sebroeck "); +MODULE_AUTHOR("Ken Hollis , " + "Wim Van Sebroeck "); MODULE_DESCRIPTION("Berkshire ISA-PC Watchdog driver"); MODULE_VERSION(WATCHDOG_VERSION); MODULE_LICENSE("GPL"); diff --git a/drivers/watchdog/pcwd_pci.c b/drivers/watchdog/pcwd_pci.c index 5d76422c402..698f51bff1b 100644 --- a/drivers/watchdog/pcwd_pci.c +++ b/drivers/watchdog/pcwd_pci.c @@ -24,7 +24,8 @@ * A bells and whistles driver is available from: * http://www.kernel.org/pub/linux/kernel/people/wim/pcwd/pcwd_pci/ * - * More info available at http://www.berkprod.com/ or http://www.pcwatchdog.com/ + * More info available at + * http://www.berkprod.com/ or http://www.pcwatchdog.com/ */ /* @@ -51,11 +52,10 @@ /* Module and version information */ #define WATCHDOG_VERSION "1.03" -#define WATCHDOG_DATE "21 Jan 2007" #define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog" #define WATCHDOG_NAME "pcwd_pci" #define PFX WATCHDOG_NAME ": " -#define DRIVER_VERSION WATCHDOG_DRIVER_NAME " driver, v" WATCHDOG_VERSION " (" WATCHDOG_DATE ")\n" +#define DRIVER_VERSION WATCHDOG_DRIVER_NAME " driver, v" WATCHDOG_VERSION "\n" /* Stuff for the PCI ID's */ #ifndef PCI_VENDOR_ID_QUICKLOGIC @@ -76,7 +76,8 @@ #define WD_PCI_TTRP 0x04 /* Temperature Trip status */ #define WD_PCI_RL2A 0x08 /* Relay 2 Active */ #define WD_PCI_RL1A 0x10 /* Relay 1 Active */ -#define WD_PCI_R2DS 0x40 /* Relay 2 Disable Temperature-trip/reset */ +#define WD_PCI_R2DS 0x40 /* Relay 2 Disable Temperature-trip / + reset */ #define WD_PCI_RLY2 0x80 /* Activate Relay 2 on the board */ /* Port 2 : Control Status #2 */ #define WD_PCI_WDIS 0x10 /* Watchdog Disable */ @@ -114,12 +115,18 @@ static int cards_found; static int temp_panic; static unsigned long is_active; static char expect_release; -static struct { /* this is private data for each PCI-PC watchdog card */ - int supports_temp; /* Wether or not the card has a temperature device */ - int boot_status; /* The card's boot status */ - unsigned long io_addr; /* The cards I/O address */ - spinlock_t io_lock; /* the lock for io operations */ - struct pci_dev *pdev; /* the PCI-device */ +/* this is private data for each PCI-PC watchdog card */ +static struct { + /* Wether or not the card has a temperature device */ + int supports_temp; + /* The card's boot status */ + int boot_status; + /* The cards I/O address */ + unsigned long io_addr; + /* the lock for io operations */ + spinlock_t io_lock; + /* the PCI-device */ + struct pci_dev *pdev; } pcipcwd_private; /* module parameters */ @@ -130,14 +137,18 @@ static int debug = QUIET; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)"); -#define WATCHDOG_HEARTBEAT 0 /* default heartbeat = delay-time from dip-switches */ +#define WATCHDOG_HEARTBEAT 0 /* default heartbeat = + delay-time from dip-switches */ static int heartbeat = WATCHDOG_HEARTBEAT; module_param(heartbeat, int, 0); -MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0= DEBUG) - printk(KERN_DEBUG PFX "sending following data cmd=0x%02x msb=0x%02x lsb=0x%02x\n", - cmd, *msb, *lsb); + printk(KERN_DEBUG PFX "sending following data " + "cmd=0x%02x msb=0x%02x lsb=0x%02x\n", cmd, *msb, *lsb); spin_lock(&pcipcwd_private.io_lock); /* If a command requires data it should be written first. @@ -166,17 +177,20 @@ static int send_command(int cmd, int *msb, int *lsb) * the WRSP bit in port 2 and give it a max. timeout of * PCI_COMMAND_TIMEOUT to process */ got_response = inb_p(pcipcwd_private.io_addr + 2) & WD_PCI_WRSP; - for (count = 0; (count < PCI_COMMAND_TIMEOUT) && (!got_response); count++) { + for (count = 0; (count < PCI_COMMAND_TIMEOUT) && (!got_response); + count++) { mdelay(1); got_response = inb_p(pcipcwd_private.io_addr + 2) & WD_PCI_WRSP; } if (debug >= DEBUG) { if (got_response) { - printk(KERN_DEBUG PFX "time to process command was: %d ms\n", + printk(KERN_DEBUG PFX + "time to process command was: %d ms\n", count); } else { - printk(KERN_DEBUG PFX "card did not respond on command!\n"); + printk(KERN_DEBUG PFX + "card did not respond on command!\n"); } } @@ -189,7 +203,8 @@ static int send_command(int cmd, int *msb, int *lsb) inb_p(pcipcwd_private.io_addr + 6); if (debug >= DEBUG) - printk(KERN_DEBUG PFX "received following data for cmd=0x%02x: msb=0x%02x lsb=0x%02x\n", + printk(KERN_DEBUG PFX "received following data for " + "cmd=0x%02x: msb=0x%02x lsb=0x%02x\n", cmd, *msb, *lsb); } @@ -218,7 +233,8 @@ static void pcipcwd_show_card_info(void) char fw_ver_str[20]; /* The cards firmware version */ int option_switches; - got_fw_rev = send_command(CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor); + got_fw_rev = send_command(CMD_GET_FIRMWARE_VERSION, &fw_rev_major, + &fw_rev_minor); if (got_fw_rev) sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor); else @@ -227,23 +243,27 @@ static void pcipcwd_show_card_info(void) /* Get switch settings */ option_switches = pcipcwd_get_option_switches(); - printk(KERN_INFO PFX "Found card at port 0x%04x (Firmware: %s) %s temp option\n", + printk(KERN_INFO PFX "Found card at port " + "0x%04x (Firmware: %s) %s temp option\n", (int) pcipcwd_private.io_addr, fw_ver_str, (pcipcwd_private.supports_temp ? "with" : "without")); - printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", + printk(KERN_INFO PFX "Option switches (0x%02x): " + "Temperature Reset Enable=%s, Power On Delay=%s\n", option_switches, ((option_switches & 0x10) ? "ON" : "OFF"), ((option_switches & 0x08) ? "ON" : "OFF")); if (pcipcwd_private.boot_status & WDIOF_CARDRESET) - printk(KERN_INFO PFX "Previous reset was caused by the Watchdog card\n"); + printk(KERN_INFO PFX + "Previous reset was caused by the Watchdog card\n"); if (pcipcwd_private.boot_status & WDIOF_OVERHEAT) printk(KERN_INFO PFX "Card sensed a CPU Overheat\n"); if (pcipcwd_private.boot_status == 0) - printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n"); + printk(KERN_INFO PFX + "No previous trip detected - Cold boot or reset\n"); } static int pcipcwd_start(void) @@ -283,7 +303,8 @@ static int pcipcwd_stop(void) spin_unlock(&pcipcwd_private.io_lock); if (!(stat_reg & WD_PCI_WDIS)) { - printk(KERN_ERR PFX "Card did not acknowledge disable attempt\n"); + printk(KERN_ERR PFX + "Card did not acknowledge disable attempt\n"); return -1; } @@ -364,7 +385,8 @@ static int pcipcwd_clear_status(void) } /* clear trip status & LED and keep mode of relay 2 */ - outb_p((control_status & WD_PCI_R2DS) | WD_PCI_WTRP, pcipcwd_private.io_addr + 1); + outb_p((control_status & WD_PCI_R2DS) | WD_PCI_WTRP, + pcipcwd_private.io_addr + 1); /* clear reset counter */ msb = 0; @@ -437,7 +459,8 @@ static ssize_t pcipcwd_write(struct file *file, const char __user *data, * five months ago... */ expect_release = 0; - /* scan to see whether or not we got the magic character */ + /* scan to see whether or not we got the + * magic character */ for (i = 0; i != len; i++) { char c; if (get_user(c, data + i)) @@ -531,7 +554,7 @@ static long pcipcwd_ioctl(struct file *file, unsigned int cmd, return -EFAULT; if (pcipcwd_set_heartbeat(new_heartbeat)) - return -EINVAL; + return -EINVAL; pcipcwd_keepalive(); /* Fall */ @@ -560,7 +583,8 @@ static int pcipcwd_open(struct inode *inode, struct file *file) /* /dev/watchdog can only be opened once */ if (test_and_set_bit(0, &is_active)) { if (debug >= VERBOSE) - printk(KERN_ERR PFX "Attempt to open already opened device.\n"); + printk(KERN_ERR PFX + "Attempt to open already opened device.\n"); return -EBUSY; } @@ -578,7 +602,8 @@ static int pcipcwd_release(struct inode *inode, struct file *file) if (expect_release == 42) { pcipcwd_stop(); } else { - printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); + printk(KERN_CRIT PFX + "Unexpected close, not stopping watchdog!\n"); pcipcwd_keepalive(); } expect_release = 0; @@ -621,7 +646,8 @@ static int pcipcwd_temp_release(struct inode *inode, struct file *file) * Notify system */ -static int pcipcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused) +static int pcipcwd_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) { if (code == SYS_DOWN || code == SYS_HALT) pcipcwd_stop(); /* Turn the WDT off */ @@ -722,34 +748,38 @@ static int __devinit pcipcwd_card_init(struct pci_dev *pdev, /* If heartbeat = 0 then we use the heartbeat from the dip-switches */ if (heartbeat == 0) - heartbeat = heartbeat_tbl[(pcipcwd_get_option_switches() & 0x07)]; + heartbeat = + heartbeat_tbl[(pcipcwd_get_option_switches() & 0x07)]; - /* Check that the heartbeat value is within it's range ; if not reset to the default */ + /* Check that the heartbeat value is within it's range ; + * if not reset to the default */ if (pcipcwd_set_heartbeat(heartbeat)) { pcipcwd_set_heartbeat(WATCHDOG_HEARTBEAT); - printk(KERN_INFO PFX "heartbeat value must be 0" #define DRIVER_DESC "Berkshire USB-PC Watchdog driver" #define DRIVER_LICENSE "GPL" @@ -73,14 +72,18 @@ MODULE_ALIAS_MISCDEV(TEMP_MINOR); module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug enabled or not"); -#define WATCHDOG_HEARTBEAT 0 /* default heartbeat = delay-time from dip-switches */ +#define WATCHDOG_HEARTBEAT 0 /* default heartbeat = + delay-time from dip-switches */ static int heartbeat = WATCHDOG_HEARTBEAT; module_param(heartbeat, int, 0); -MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0context; + struct usb_pcwd_private *usb_pcwd = + (struct usb_pcwd_private *)urb->context; unsigned char *data = usb_pcwd->intr_buffer; int retval; @@ -178,11 +197,13 @@ static void usb_pcwd_intr_done(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __func__, urb->status); + dbg("%s - urb shutting down with status: %d", __func__, + urb->status); return; /* -EPIPE: should clear the halt */ default: /* error */ - dbg("%s - nonzero urb status received: %d", __func__, urb->status); + dbg("%s - nonzero urb status received: %d", __func__, + urb->status); goto resubmit; } @@ -199,22 +220,23 @@ static void usb_pcwd_intr_done(struct urb *urb) resubmit: retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) - printk(KERN_ERR PFX "can't resubmit intr, usb_submit_urb failed with result %d\n", - retval); + printk(KERN_ERR PFX "can't resubmit intr, " + "usb_submit_urb failed with result %d\n", retval); } -static int usb_pcwd_send_command(struct usb_pcwd_private *usb_pcwd, unsigned char cmd, - unsigned char *msb, unsigned char *lsb) +static int usb_pcwd_send_command(struct usb_pcwd_private *usb_pcwd, + unsigned char cmd, unsigned char *msb, unsigned char *lsb) { int got_response, count; unsigned char buf[6]; - /* We will not send any commands if the USB PCWD device does not exist */ + /* We will not send any commands if the USB PCWD device does + * not exist */ if ((!usb_pcwd) || (!usb_pcwd->exists)) return -1; - /* The USB PC Watchdog uses a 6 byte report format. The board currently uses - * only 3 of the six bytes of the report. */ + /* The USB PC Watchdog uses a 6 byte report format. + * The board currently uses only 3 of the six bytes of the report. */ buf[0] = cmd; /* Byte 0 = CMD */ buf[1] = *msb; /* Byte 1 = Data MSB */ buf[2] = *lsb; /* Byte 2 = Data LSB */ @@ -229,12 +251,14 @@ static int usb_pcwd_send_command(struct usb_pcwd_private *usb_pcwd, unsigned cha HID_REQ_SET_REPORT, HID_DT_REPORT, 0x0200, usb_pcwd->interface_number, buf, sizeof(buf), USB_COMMAND_TIMEOUT) != sizeof(buf)) { - dbg("usb_pcwd_send_command: error in usb_control_msg for cmd 0x%x 0x%x 0x%x\n", cmd, *msb, *lsb); + dbg("usb_pcwd_send_command: error in usb_control_msg for " + "cmd 0x%x 0x%x 0x%x\n", cmd, *msb, *lsb); } /* wait till the usb card processed the command, * with a max. timeout of USB_COMMAND_TIMEOUT */ got_response = 0; - for (count = 0; (count < USB_COMMAND_TIMEOUT) && (!got_response); count++) { + for (count = 0; (count < USB_COMMAND_TIMEOUT) && (!got_response); + count++) { mdelay(1); if (atomic_read(&usb_pcwd->cmd_received)) got_response = 1; @@ -256,10 +280,12 @@ static int usb_pcwd_start(struct usb_pcwd_private *usb_pcwd) int retval; /* Enable Watchdog */ - retval = usb_pcwd_send_command(usb_pcwd, CMD_ENABLE_WATCHDOG, &msb, &lsb); + retval = usb_pcwd_send_command(usb_pcwd, CMD_ENABLE_WATCHDOG, + &msb, &lsb); if ((retval == 0) || (lsb == 0)) { - printk(KERN_ERR PFX "Card did not acknowledge enable attempt\n"); + printk(KERN_ERR PFX + "Card did not acknowledge enable attempt\n"); return -1; } @@ -273,10 +299,12 @@ static int usb_pcwd_stop(struct usb_pcwd_private *usb_pcwd) int retval; /* Disable Watchdog */ - retval = usb_pcwd_send_command(usb_pcwd, CMD_DISABLE_WATCHDOG, &msb, &lsb); + retval = usb_pcwd_send_command(usb_pcwd, CMD_DISABLE_WATCHDOG, + &msb, &lsb); if ((retval == 0) || (lsb != 0)) { - printk(KERN_ERR PFX "Card did not acknowledge disable attempt\n"); + printk(KERN_ERR PFX + "Card did not acknowledge disable attempt\n"); return -1; } @@ -308,7 +336,8 @@ static int usb_pcwd_set_heartbeat(struct usb_pcwd_private *usb_pcwd, int t) return 0; } -static int usb_pcwd_get_temperature(struct usb_pcwd_private *usb_pcwd, int *temperature) +static int usb_pcwd_get_temperature(struct usb_pcwd_private *usb_pcwd, + int *temperature) { unsigned char msb, lsb; @@ -323,7 +352,8 @@ static int usb_pcwd_get_temperature(struct usb_pcwd_private *usb_pcwd, int *temp return 0; } -static int usb_pcwd_get_timeleft(struct usb_pcwd_private *usb_pcwd, int *time_left) +static int usb_pcwd_get_timeleft(struct usb_pcwd_private *usb_pcwd, + int *time_left) { unsigned char msb, lsb; @@ -341,7 +371,7 @@ static int usb_pcwd_get_timeleft(struct usb_pcwd_private *usb_pcwd, int *time_le */ static ssize_t usb_pcwd_write(struct file *file, const char __user *data, - size_t len, loff_t *ppos) + size_t len, loff_t *ppos) { /* See if we got the magic character 'V' and reload the timer */ if (len) { @@ -352,7 +382,8 @@ static ssize_t usb_pcwd_write(struct file *file, const char __user *data, * five months ago... */ expect_release = 0; - /* scan to see whether or not we got the magic character */ + /* scan to see whether or not we got the + * magic character */ for (i = 0; i != len; i++) { char c; if (get_user(c, data + i)) @@ -431,7 +462,7 @@ static long usb_pcwd_ioctl(struct file *file, unsigned int cmd, return -EFAULT; if (usb_pcwd_set_heartbeat(usb_pcwd_device, new_heartbeat)) - return -EINVAL; + return -EINVAL; usb_pcwd_keepalive(usb_pcwd_device); /* Fall */ @@ -475,7 +506,8 @@ static int usb_pcwd_release(struct inode *inode, struct file *file) if (expect_release == 42) { usb_pcwd_stop(usb_pcwd_device); } else { - printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); + printk(KERN_CRIT PFX + "Unexpected close, not stopping watchdog!\n"); usb_pcwd_keepalive(usb_pcwd_device); } expect_release = 0; @@ -515,7 +547,8 @@ static int usb_pcwd_temperature_release(struct inode *inode, struct file *file) * Notify system */ -static int usb_pcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused) +static int usb_pcwd_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) { if (code == SYS_DOWN || code == SYS_HALT) usb_pcwd_stop(usb_pcwd_device); /* Turn the WDT off */ @@ -578,7 +611,8 @@ static inline void usb_pcwd_delete(struct usb_pcwd_private *usb_pcwd) * Called by the usb core when a new device is connected that it thinks * this driver might be interested in. */ -static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_device_id *id) +static int usb_pcwd_probe(struct usb_interface *interface, + const struct usb_device_id *id) { struct usb_device *udev = interface_to_usbdev(interface); struct usb_host_interface *iface_desc; @@ -602,7 +636,8 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi /* check out that we have a HID device */ if (!(iface_desc->desc.bInterfaceClass == USB_CLASS_HID)) { - printk(KERN_ERR PFX "The device isn't a Human Interface Device\n"); + printk(KERN_ERR PFX + "The device isn't a Human Interface Device\n"); return -ENODEV; } @@ -632,10 +667,12 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi usb_pcwd->udev = udev; usb_pcwd->interface = interface; usb_pcwd->interface_number = iface_desc->desc.bInterfaceNumber; - usb_pcwd->intr_size = (le16_to_cpu(endpoint->wMaxPacketSize) > 8 ? le16_to_cpu(endpoint->wMaxPacketSize) : 8); + usb_pcwd->intr_size = (le16_to_cpu(endpoint->wMaxPacketSize) > 8 ? + le16_to_cpu(endpoint->wMaxPacketSize) : 8); /* set up the memory buffer's */ - usb_pcwd->intr_buffer = usb_buffer_alloc(udev, usb_pcwd->intr_size, GFP_ATOMIC, &usb_pcwd->intr_dma); + usb_pcwd->intr_buffer = usb_buffer_alloc(udev, usb_pcwd->intr_size, + GFP_ATOMIC, &usb_pcwd->intr_dma); if (!usb_pcwd->intr_buffer) { printk(KERN_ERR PFX "Out of memory\n"); goto error; @@ -669,7 +706,8 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi usb_pcwd_stop(usb_pcwd); /* Get the Firmware Version */ - got_fw_rev = usb_pcwd_send_command(usb_pcwd, CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor); + got_fw_rev = usb_pcwd_send_command(usb_pcwd, CMD_GET_FIRMWARE_VERSION, + &fw_rev_major, &fw_rev_minor); if (got_fw_rev) sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor); else @@ -679,9 +717,11 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi fw_ver_str); /* Get switch settings */ - usb_pcwd_send_command(usb_pcwd, CMD_GET_DIP_SWITCH_SETTINGS, &dummy, &option_switches); + usb_pcwd_send_command(usb_pcwd, CMD_GET_DIP_SWITCH_SETTINGS, &dummy, + &option_switches); - printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", + printk(KERN_INFO PFX "Option switches (0x%02x): " + "Temperature Reset Enable=%s, Power On Delay=%s\n", option_switches, ((option_switches & 0x10) ? "ON" : "OFF"), ((option_switches & 0x08) ? "ON" : "OFF")); @@ -690,30 +730,35 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi if (heartbeat == 0) heartbeat = heartbeat_tbl[(option_switches & 0x07)]; - /* Check that the heartbeat value is within it's range ; if not reset to the default */ + /* Check that the heartbeat value is within it's range ; + * if not reset to the default */ if (usb_pcwd_set_heartbeat(usb_pcwd, heartbeat)) { usb_pcwd_set_heartbeat(usb_pcwd, WATCHDOG_HEARTBEAT); - printk(KERN_INFO PFX "heartbeat value must be 0 - * Based on SoftDog driver by Alan Cox + * (c) Copyright 2000 Oleg Drokin + * Based on SoftDog driver by Alan Cox * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -15,7 +15,7 @@ * * (c) Copyright 2000 Oleg Drokin * - * 27/11/2000 Initial release + * 27/11/2000 Initial release */ #include #include diff --git a/drivers/watchdog/sbc60xxwdt.c b/drivers/watchdog/sbc60xxwdt.c index 3266daaaecf..d1c390c7155 100644 --- a/drivers/watchdog/sbc60xxwdt.c +++ b/drivers/watchdog/sbc60xxwdt.c @@ -1,7 +1,7 @@ /* * 60xx Single Board Computer Watchdog Timer driver for Linux 2.2.x * - * Based on acquirewdt.c by Alan Cox. + * Based on acquirewdt.c by Alan Cox. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/drivers/watchdog/sbc8360.c b/drivers/watchdog/sbc8360.c index ae74f6bcfa2..b6e6799ec45 100644 --- a/drivers/watchdog/sbc8360.c +++ b/drivers/watchdog/sbc8360.c @@ -4,12 +4,12 @@ * (c) Copyright 2005 Webcon, Inc. * * Based on ib700wdt.c, which is based on advantechwdt.c which is based - * on acquirewdt.c which is based on wdt.c. + * on acquirewdt.c which is based on wdt.c. * * (c) Copyright 2001 Charles Howes * - * Based on advantechwdt.c which is based on acquirewdt.c which - * is based on wdt.c. + * Based on advantechwdt.c which is based on acquirewdt.c which + * is based on wdt.c. * * (c) Copyright 2000-2001 Marek Michalkiewicz * @@ -30,9 +30,9 @@ * * (c) Copyright 1995 Alan Cox * - * 14-Dec-2001 Matt Domsch - * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT - * Added timeout module option to override default + * 14-Dec-2001 Matt Domsch + * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT + * Added timeout module option to override default * */ diff --git a/drivers/watchdog/sbc_epx_c3.c b/drivers/watchdog/sbc_epx_c3.c index 06553debc7b..e467ddcf796 100644 --- a/drivers/watchdog/sbc_epx_c3.c +++ b/drivers/watchdog/sbc_epx_c3.c @@ -35,7 +35,8 @@ static int epx_c3_alive; static int nowayout = WATCHDOG_NOWAYOUT; module_param(nowayout, int, 0); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); #define EPXC3_WATCHDOG_CTL_REG 0x1ee /* write 1 to enable, 0 to disable */ #define EPXC3_WATCHDOG_PET_REG 0x1ef /* write anything to pet once enabled */ diff --git a/drivers/watchdog/sc1200wdt.c b/drivers/watchdog/sc1200wdt.c index 23da3ccd832..b5e19c1820a 100644 --- a/drivers/watchdog/sc1200wdt.c +++ b/drivers/watchdog/sc1200wdt.c @@ -71,7 +71,7 @@ #define UART2_IRQ 0x04 /* Serial1 */ /* 5 -7 are reserved */ -static char banner[] __initdata = KERN_INFO PFX SC1200_MODULE_VER; +static char banner[] __initdata = PFX SC1200_MODULE_VER; static int timeout = 1; static int io = -1; static int io_len = 2; /* for non plug and play */ @@ -392,7 +392,7 @@ static int __init sc1200wdt_init(void) { int ret; - printk("%s\n", banner); + printk(KERN_INFO "%s\n", banner); #if defined CONFIG_PNP if (isapnp) { @@ -477,6 +477,7 @@ module_init(sc1200wdt_init); module_exit(sc1200wdt_exit); MODULE_AUTHOR("Zwane Mwaikambo "); -MODULE_DESCRIPTION("Driver for National Semiconductor PC87307/PC97307 watchdog component"); +MODULE_DESCRIPTION( + "Driver for National Semiconductor PC87307/PC97307 watchdog component"); MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/drivers/watchdog/sc520_wdt.c b/drivers/watchdog/sc520_wdt.c index a2b6c1067ec..52b63f2f0da 100644 --- a/drivers/watchdog/sc520_wdt.c +++ b/drivers/watchdog/sc520_wdt.c @@ -1,8 +1,8 @@ /* * AMD Elan SC520 processor Watchdog Timer driver * - * Based on acquirewdt.c by Alan Cox, - * and sbc60xxwdt.c by Jakob Oestergaard + * Based on acquirewdt.c by Alan Cox, + * and sbc60xxwdt.c by Jakob Oestergaard * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -11,7 +11,7 @@ * * The authors do NOT admit liability nor provide warranty for * any of this software. This material is provided "AS-IS" in - * the hope that it may be useful for others. + * the hope that it may be useful for others. * * (c) Copyright 2001 Scott Jennings * 9/27 - 2001 [Initial release] @@ -438,6 +438,7 @@ module_init(sc520_wdt_init); module_exit(sc520_wdt_unload); MODULE_AUTHOR("Scott and Bill Jennings"); -MODULE_DESCRIPTION("Driver for watchdog timer in AMD \"Elan\" SC520 uProcessor"); +MODULE_DESCRIPTION( + "Driver for watchdog timer in AMD \"Elan\" SC520 uProcessor"); MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/drivers/watchdog/smsc37b787_wdt.c b/drivers/watchdog/smsc37b787_wdt.c index 2e56cad77d1..8a1f0bc3e27 100644 --- a/drivers/watchdog/smsc37b787_wdt.c +++ b/drivers/watchdog/smsc37b787_wdt.c @@ -2,7 +2,7 @@ * SMsC 37B787 Watchdog Timer driver for Linux 2.6.x.x * * Based on acquirewdt.c by Alan Cox - * and some other existing drivers + * and some other existing drivers * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -11,7 +11,7 @@ * * The authors do NOT admit liability nor provide warranty for * any of this software. This material is provided "AS-IS" in - * the hope that it may be useful for others. + * the hope that it may be useful for others. * * (C) Copyright 2003-2006 Sven Anders * @@ -22,19 +22,19 @@ * * Theory of operation: * - * A Watchdog Timer (WDT) is a hardware circuit that can - * reset the computer system in case of a software fault. - * You probably knew that already. + * A Watchdog Timer (WDT) is a hardware circuit that can + * reset the computer system in case of a software fault. + * You probably knew that already. * - * Usually a userspace daemon will notify the kernel WDT driver - * via the /dev/watchdog special device file that userspace is - * still alive, at regular intervals. When such a notification - * occurs, the driver will usually tell the hardware watchdog - * that everything is in order, and that the watchdog should wait - * for yet another little while to reset the system. - * If userspace fails (RAM error, kernel bug, whatever), the - * notifications cease to occur, and the hardware watchdog will - * reset the system (causing a reboot) after the timeout occurs. + * Usually a userspace daemon will notify the kernel WDT driver + * via the /dev/watchdog special device file that userspace is + * still alive, at regular intervals. When such a notification + * occurs, the driver will usually tell the hardware watchdog + * that everything is in order, and that the watchdog should wait + * for yet another little while to reset the system. + * If userspace fails (RAM error, kernel bug, whatever), the + * notifications cease to occur, and the hardware watchdog will + * reset the system (causing a reboot) after the timeout occurs. * * Create device with: * mknod /dev/watchdog c 10 130 @@ -485,7 +485,7 @@ static long wb_smsc_wdt_ioctl(struct file *file, case WDIOC_GETTIMEOUT: new_timeout = timeout; if (unit == UNIT_MINUTE) - new_timeout *= 60; + new_timeout *= 60; return put_user(new_timeout, uarg.i); default: return -ENOTTY; diff --git a/drivers/watchdog/softdog.c b/drivers/watchdog/softdog.c index 7204f966211..ebcc9cea5e9 100644 --- a/drivers/watchdog/softdog.c +++ b/drivers/watchdog/softdog.c @@ -1,7 +1,8 @@ /* * SoftDog 0.07: A Software Watchdog Device * - * (c) Copyright 1996 Alan Cox , All Rights Reserved. + * (c) Copyright 1996 Alan Cox , + * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -32,7 +33,7 @@ * Added WDIOC_GETTIMEOUT and WDIOC_SETTIMOUT. * * 20020530 Joel Becker - * Added Matt Domsch's nowayout module option. + * Added Matt Domsch's nowayout module option. */ #include diff --git a/drivers/watchdog/w83697hf_wdt.c b/drivers/watchdog/w83697hf_wdt.c index 3c7aa412b1f..a9c7f352fcb 100644 --- a/drivers/watchdog/w83697hf_wdt.c +++ b/drivers/watchdog/w83697hf_wdt.c @@ -462,6 +462,7 @@ module_init(wdt_init); module_exit(wdt_exit); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Marcus Junker , Samuel Tardieu "); +MODULE_AUTHOR("Marcus Junker , " + "Samuel Tardieu "); MODULE_DESCRIPTION("w83697hf/hg WDT driver"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/drivers/watchdog/w83697ug_wdt.c b/drivers/watchdog/w83697ug_wdt.c index 6972c0a1e4d..883b5f79673 100644 --- a/drivers/watchdog/w83697ug_wdt.c +++ b/drivers/watchdog/w83697ug_wdt.c @@ -2,7 +2,7 @@ * w83697ug/uf WDT driver * * (c) Copyright 2008 Flemming Fransen - * reused original code to supoprt w83697ug/uf. + * reused original code to support w83697ug/uf. * * Based on w83627hf_wdt.c which is based on advantechwdt.c * which is based on wdt.c. diff --git a/drivers/watchdog/w83977f_wdt.c b/drivers/watchdog/w83977f_wdt.c index 2525da5080c..0560182a1d0 100644 --- a/drivers/watchdog/w83977f_wdt.c +++ b/drivers/watchdog/w83977f_wdt.c @@ -426,7 +426,7 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return -EFAULT; if (wdt_set_timeout(new_timeout)) - return -EINVAL; + return -EINVAL; wdt_keepalive(); /* Fall */ diff --git a/drivers/watchdog/wd501p.h b/drivers/watchdog/wd501p.h index db34853c28a..0e3a497d562 100644 --- a/drivers/watchdog/wd501p.h +++ b/drivers/watchdog/wd501p.h @@ -11,9 +11,9 @@ * * http://www.cymru.net * - * This driver is provided under the GNU General Public License, incorporated - * herein by reference. The driver is provided without warranty or - * support. + * This driver is provided under the GNU General Public License, + * incorporated herein by reference. The driver is provided without + * warranty or support. * * Release 0.04. * @@ -39,13 +39,13 @@ /* programmable outputs: */ #define WDT_PROGOUT (io+15) /* wr=enable, rd=disable */ - /* FAN 501 500 */ -#define WDC_SR_WCCR 1 /* Active low */ /* X X X */ -#define WDC_SR_TGOOD 2 /* X X - */ -#define WDC_SR_ISOI0 4 /* X X X */ -#define WDC_SR_ISII1 8 /* X X X */ -#define WDC_SR_FANGOOD 16 /* X - - */ -#define WDC_SR_PSUOVER 32 /* Active low */ /* X X - */ -#define WDC_SR_PSUUNDR 64 /* Active low */ /* X X - */ -#define WDC_SR_IRQ 128 /* Active low */ /* X X X */ + /* FAN 501 500 */ +#define WDC_SR_WCCR 1 /* Active low */ /* X X X */ +#define WDC_SR_TGOOD 2 /* X X - */ +#define WDC_SR_ISOI0 4 /* X X X */ +#define WDC_SR_ISII1 8 /* X X X */ +#define WDC_SR_FANGOOD 16 /* X - - */ +#define WDC_SR_PSUOVER 32 /* Active low */ /* X X - */ +#define WDC_SR_PSUUNDR 64 /* Active low */ /* X X - */ +#define WDC_SR_IRQ 128 /* Active low */ /* X X X */ diff --git a/drivers/watchdog/wdt977.c b/drivers/watchdog/wdt977.c index 60e28d49ff5..90ef70eb47d 100644 --- a/drivers/watchdog/wdt977.c +++ b/drivers/watchdog/wdt977.c @@ -401,7 +401,7 @@ static long wdt977_ioctl(struct file *file, unsigned int cmd, return -EFAULT; if (wdt977_set_timeout(new_timeout)) - return -EINVAL; + return -EINVAL; wdt977_keepalive(); /* Fall */ -- GitLab From 278aefc51bdbc7f1a3d39c9bd5313c78335b7828 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Wed, 18 Mar 2009 09:09:26 +0000 Subject: [PATCH 4517/4982] [WATCHDOG] Fix io.h & uaccess.h includes. Fix following includes: * #include should be #include * #include should be #include Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/cpwd.c | 3 +-- drivers/watchdog/riowd.c | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c index 0c14586f58d..41070e4771a 100644 --- a/drivers/watchdog/cpwd.c +++ b/drivers/watchdog/cpwd.c @@ -28,10 +28,9 @@ #include #include #include +#include #include -#include - #include #define DRIVER_NAME "cpwd" diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c index 2cff53310f7..1e8f02f440e 100644 --- a/drivers/watchdog/riowd.c +++ b/drivers/watchdog/riowd.c @@ -14,9 +14,8 @@ #include #include #include - -#include -#include +#include +#include /* RIO uses the NatSemi Super I/O power management logical device -- GitLab From 04bedfa542d90ac7a1bbf28287e9861d0da21576 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sun, 22 Mar 2009 10:46:42 +0000 Subject: [PATCH 4518/4982] [WATCHDOG] wdt.c: remove #ifdef CONFIG_WDT_501 Change the wdt.c watchdog driver so that the code is the same for both the WDT500 as the WDT501-P card. The selection of the card is now being done via the module parameter: 'type' instead of the config option CONFIG_WDT_501. Signed-off-by: Alan Cox Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 15 ---- drivers/watchdog/wdt.c | 152 +++++++++++++++++++-------------------- 2 files changed, 74 insertions(+), 93 deletions(-) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 325c10ff6a2..55f64af072a 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -940,21 +940,6 @@ config WDT To compile this driver as a module, choose M here: the module will be called wdt. -config WDT_501 - bool "WDT501 features" - depends on WDT - help - Saying Y here and creating a character special file /dev/temperature - with major number 10 and minor number 131 ("man mknod") will give - you a thermometer inside your computer: reading from - /dev/temperature yields one byte, the temperature in degrees - Fahrenheit. This works only if you have a WDT501P watchdog board - installed. - - If you want to enable the Fan Tachometer on the WDT501P, then you - can do this via the tachometer parameter. Only do this if you have a - fan tachometer actually set up. - # # PCI-based Watchdog Cards # diff --git a/drivers/watchdog/wdt.c b/drivers/watchdog/wdt.c index eddb9187e7b..3bbefe9a263 100644 --- a/drivers/watchdog/wdt.c +++ b/drivers/watchdog/wdt.c @@ -1,5 +1,5 @@ /* - * Industrial Computer Source WDT500/501 driver + * Industrial Computer Source WDT501 driver * * (c) Copyright 1996-1997 Alan Cox , * All Rights Reserved. @@ -82,14 +82,16 @@ MODULE_PARM_DESC(io, "WDT io port (default=0x240)"); module_param(irq, int, 0); MODULE_PARM_DESC(irq, "WDT irq (default=11)"); -#ifdef CONFIG_WDT_501 /* Support for the Fan Tachometer on the WDT501-P */ static int tachometer; - module_param(tachometer, int, 0); MODULE_PARM_DESC(tachometer, "WDT501-P Fan Tachometer support (0=disable, default=0)"); -#endif /* CONFIG_WDT_501 */ + +static int type = 500; +module_param(type, int, 0); +MODULE_PARM_DESC(type, + "WDT501-P Card type (500 or 501 , default=500)"); /* * Programming support @@ -158,7 +160,7 @@ static int wdt_stop(void) * reloading the cascade counter. */ -static int wdt_ping(void) +static void wdt_ping(void) { unsigned long flags; spin_lock_irqsave(&wdt_lock, flags); @@ -169,7 +171,6 @@ static int wdt_ping(void) wdt_ctr_load(1, wd_heartbeat); /* Heartbeat */ outb_p(0, WDT_DC); /* Enable watchdog */ spin_unlock_irqrestore(&wdt_lock, flags); - return 0; } /** @@ -193,7 +194,6 @@ static int wdt_set_heartbeat(int t) /** * wdt_get_status: - * @status: the new status. * * Extract the status information from a WDT watchdog device. There are * several board variants so we have to know which bits are valid. Some @@ -202,36 +202,35 @@ static int wdt_set_heartbeat(int t) * we then map the bits onto the status ioctl flags. */ -static int wdt_get_status(int *status) +static int wdt_get_status(void) { unsigned char new_status; + int status = 0; unsigned long flags; spin_lock_irqsave(&wdt_lock, flags); new_status = inb_p(WDT_SR); spin_unlock_irqrestore(&wdt_lock, flags); - *status = 0; if (new_status & WDC_SR_ISOI0) - *status |= WDIOF_EXTERN1; + status |= WDIOF_EXTERN1; if (new_status & WDC_SR_ISII1) - *status |= WDIOF_EXTERN2; -#ifdef CONFIG_WDT_501 - if (!(new_status & WDC_SR_TGOOD)) - *status |= WDIOF_OVERHEAT; - if (!(new_status & WDC_SR_PSUOVER)) - *status |= WDIOF_POWEROVER; - if (!(new_status & WDC_SR_PSUUNDR)) - *status |= WDIOF_POWERUNDER; - if (tachometer) { - if (!(new_status & WDC_SR_FANGOOD)) - *status |= WDIOF_FANFAULT; + status |= WDIOF_EXTERN2; + if (type == 501) { + if (!(new_status & WDC_SR_TGOOD)) + status |= WDIOF_OVERHEAT; + if (!(new_status & WDC_SR_PSUOVER)) + status |= WDIOF_POWEROVER; + if (!(new_status & WDC_SR_PSUUNDR)) + status |= WDIOF_POWERUNDER; + if (tachometer) { + if (!(new_status & WDC_SR_FANGOOD)) + status |= WDIOF_FANFAULT; + } } -#endif /* CONFIG_WDT_501 */ - return 0; + return status; } -#ifdef CONFIG_WDT_501 /** * wdt_get_temperature: * @@ -239,7 +238,7 @@ static int wdt_get_status(int *status) * farenheit. It was designed by an imperial measurement luddite. */ -static int wdt_get_temperature(int *temperature) +static int wdt_get_temperature(void) { unsigned short c; unsigned long flags; @@ -247,10 +246,18 @@ static int wdt_get_temperature(int *temperature) spin_lock_irqsave(&wdt_lock, flags); c = inb_p(WDT_RT); spin_unlock_irqrestore(&wdt_lock, flags); - *temperature = (c * 11 / 15) + 7; - return 0; + return (c * 11 / 15) + 7; +} + +static void wdt_decode_501(int status) +{ + if (!(status & WDC_SR_TGOOD)) + printk(KERN_CRIT "Overheat alarm.(%d)\n", inb_p(WDT_RT)); + if (!(status & WDC_SR_PSUOVER)) + printk(KERN_CRIT "PSU over voltage.\n"); + if (!(status & WDC_SR_PSUUNDR)) + printk(KERN_CRIT "PSU under voltage.\n"); } -#endif /* CONFIG_WDT_501 */ /** * wdt_interrupt: @@ -275,18 +282,13 @@ static irqreturn_t wdt_interrupt(int irq, void *dev_id) printk(KERN_CRIT "WDT status %d\n", status); -#ifdef CONFIG_WDT_501 - if (!(status & WDC_SR_TGOOD)) - printk(KERN_CRIT "Overheat alarm.(%d)\n", inb_p(WDT_RT)); - if (!(status & WDC_SR_PSUOVER)) - printk(KERN_CRIT "PSU over voltage.\n"); - if (!(status & WDC_SR_PSUUNDR)) - printk(KERN_CRIT "PSU under voltage.\n"); - if (tachometer) { - if (!(status & WDC_SR_FANGOOD)) - printk(KERN_CRIT "Possible fan fault.\n"); + if (type == 501) { + wdt_decode_501(status); + if (tachometer) { + if (!(status & WDC_SR_FANGOOD)) + printk(KERN_CRIT "Possible fan fault.\n"); + } } -#endif /* CONFIG_WDT_501 */ if (!(status & WDC_SR_WCCR)) { #ifdef SOFTWARE_REBOOT #ifdef ONLY_TESTING @@ -366,17 +368,18 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) /* Add options according to the card we have */ ident.options |= (WDIOF_EXTERN1|WDIOF_EXTERN2); -#ifdef CONFIG_WDT_501 - ident.options |= (WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER); - if (tachometer) - ident.options |= WDIOF_FANFAULT; -#endif /* CONFIG_WDT_501 */ + if (type == 501) { + ident.options |= (WDIOF_OVERHEAT|WDIOF_POWERUNDER| + WDIOF_POWEROVER); + if (tachometer) + ident.options |= WDIOF_FANFAULT; + } switch (cmd) { case WDIOC_GETSUPPORT: return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: - wdt_get_status(&status); + status = wdt_get_status(); return put_user(status, p); case WDIOC_GETBOOTSTATUS: return put_user(0, p); @@ -446,7 +449,6 @@ static int wdt_release(struct inode *inode, struct file *file) return 0; } -#ifdef CONFIG_WDT_501 /** * wdt_temp_read: * @file: file handle to the watchdog board @@ -461,10 +463,7 @@ static int wdt_release(struct inode *inode, struct file *file) static ssize_t wdt_temp_read(struct file *file, char __user *buf, size_t count, loff_t *ptr) { - int temperature; - - if (wdt_get_temperature(&temperature)) - return -EFAULT; + int temperature = wdt_get_temperature(); if (copy_to_user(buf, &temperature, 1)) return -EFAULT; @@ -497,7 +496,6 @@ static int wdt_temp_release(struct inode *inode, struct file *file) { return 0; } -#endif /* CONFIG_WDT_501 */ /** * notify_sys: @@ -539,7 +537,6 @@ static struct miscdevice wdt_miscdev = { .fops = &wdt_fops, }; -#ifdef CONFIG_WDT_501 static const struct file_operations wdt_temp_fops = { .owner = THIS_MODULE, .llseek = no_llseek, @@ -553,7 +550,6 @@ static struct miscdevice temp_miscdev = { .name = "temperature", .fops = &wdt_temp_fops, }; -#endif /* CONFIG_WDT_501 */ /* * The WDT card needs to learn about soft shutdowns in order to @@ -577,9 +573,8 @@ static struct notifier_block wdt_notifier = { static void __exit wdt_exit(void) { misc_deregister(&wdt_miscdev); -#ifdef CONFIG_WDT_501 - misc_deregister(&temp_miscdev); -#endif /* CONFIG_WDT_501 */ + if (type == 501) + misc_deregister(&temp_miscdev); unregister_reboot_notifier(&wdt_notifier); free_irq(irq, NULL); release_region(io, 8); @@ -597,12 +592,17 @@ static int __init wdt_init(void) { int ret; + if (type != 500 && type != 501) { + printk(KERN_ERR "wdt: unknown card type '%d'.\n", type); + return -ENODEV; + } + /* Check that the heartbeat value is within it's range; if not reset to the default */ if (wdt_set_heartbeat(heartbeat)) { wdt_set_heartbeat(WD_TIMO); - printk(KERN_INFO "wdt: heartbeat value must be 0 < heartbeat < 65536, using %d\n", - WD_TIMO); + printk(KERN_INFO "wdt: heartbeat value must be " + "0 < heartbeat < 65536, using %d\n", WD_TIMO); } if (!request_region(io, 8, "wdt501p")) { @@ -625,15 +625,14 @@ static int __init wdt_init(void) goto outirq; } -#ifdef CONFIG_WDT_501 - ret = misc_register(&temp_miscdev); - if (ret) { - printk(KERN_ERR - "wdt: cannot register miscdev on minor=%d (err=%d)\n", - TEMP_MINOR, ret); - goto outrbt; + if (type == 501) { + ret = misc_register(&temp_miscdev); + if (ret) { + printk(KERN_ERR "wdt: cannot register miscdev " + "on minor=%d (err=%d)\n", TEMP_MINOR, ret); + goto outrbt; + } } -#endif /* CONFIG_WDT_501 */ ret = misc_register(&wdt_miscdev); if (ret) { @@ -643,28 +642,25 @@ static int __init wdt_init(void) goto outmisc; } - ret = 0; - printk(KERN_INFO "WDT500/501-P driver 0.10 at 0x%04x (Interrupt %d). heartbeat=%d sec (nowayout=%d)\n", + printk(KERN_INFO "WDT500/501-P driver 0.10 " + "at 0x%04x (Interrupt %d). heartbeat=%d sec (nowayout=%d)\n", io, irq, heartbeat, nowayout); -#ifdef CONFIG_WDT_501 - printk(KERN_INFO "wdt: Fan Tachometer is %s\n", + if (type == 501) + printk(KERN_INFO "wdt: Fan Tachometer is %s\n", (tachometer ? "Enabled" : "Disabled")); -#endif /* CONFIG_WDT_501 */ - -out: - return ret; + return 0; outmisc: -#ifdef CONFIG_WDT_501 - misc_deregister(&temp_miscdev); + if (type == 501) + misc_deregister(&temp_miscdev); outrbt: -#endif /* CONFIG_WDT_501 */ unregister_reboot_notifier(&wdt_notifier); outirq: free_irq(irq, NULL); outreg: release_region(io, 8); - goto out; +out: + return ret; } module_init(wdt_init); -- GitLab From 0426fd0d88a595a8ab18e0cd69bdfe82a4d15115 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Thu, 19 Mar 2009 19:02:44 +0000 Subject: [PATCH 4519/4982] [WATCHDOG] i6300esb.c: convert to platform device driver Convert the Intel 6300ESB watchdog timer to a platform device driver. Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/i6300esb.c | 90 +++++++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 33 deletions(-) diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c index 97ac6bf4222..fbe85285324 100644 --- a/drivers/watchdog/i6300esb.c +++ b/drivers/watchdog/i6300esb.c @@ -13,7 +13,7 @@ * * The timer is implemented in the following I/O controller hubs: * (See the intel documentation on http://developer.intel.com.) - * 6300ESB chip : document number 300641-003 + * 6300ESB chip : document number 300641-004 * * 2004YYZZ Ross Biro * Initial version 0.01 @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include #include @@ -42,7 +42,7 @@ #include /* Module and version information */ -#define ESB_VERSION "0.03" +#define ESB_VERSION "0.04" #define ESB_MODULE_NAME "i6300ESB timer" #define ESB_DRIVER_NAME ESB_MODULE_NAME ", v" ESB_VERSION #define PFX ESB_MODULE_NAME ": " @@ -81,6 +81,8 @@ static unsigned long timer_alive; static struct pci_dev *esb_pci; static unsigned short triggered; /* The status of the watchdog upon boot */ static char esb_expect_close; +static struct platform_device *esb_platform_device; + /* module parameters */ /* 30 sec default heartbeat (1 < heartbeat < 2*1023) */ @@ -319,19 +321,6 @@ static long esb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } } -/* - * Notify system - */ - -static int esb_notify_sys(struct notifier_block *this, - unsigned long code, void *unused) -{ - if (code == SYS_DOWN || code == SYS_HALT) - esb_timer_stop(); /* Turn the WDT off */ - - return NOTIFY_DONE; -} - /* * Kernel Interfaces */ @@ -351,10 +340,6 @@ static struct miscdevice esb_miscdev = { .fops = &esb_fops, }; -static struct notifier_block esb_notifier = { - .notifier_call = esb_notify_sys, -}; - /* * Data for PCI driver interface * @@ -373,7 +358,7 @@ MODULE_DEVICE_TABLE(pci, esb_pci_tbl); * Init & exit routines */ -static unsigned char __init esb_getdevice(void) +static unsigned char __devinit esb_getdevice(void) { u8 val1; unsigned short val2; @@ -444,7 +429,7 @@ err_devput: return 0; } -static int __init watchdog_init(void) +static int __devinit esb_probe(struct platform_device *dev) { int ret; @@ -460,19 +445,13 @@ static int __init watchdog_init(void) "heartbeat value must be 1 Date: Mon, 23 Mar 2009 13:50:38 +0000 Subject: [PATCH 4520/4982] [WATCHDOG] i6300esb.c: start locking Change the start function in preparation of the generic watchdog code. Also make sure that locking of the start function is OK. Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/i6300esb.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c index fbe85285324..2dbe83570d6 100644 --- a/drivers/watchdog/i6300esb.c +++ b/drivers/watchdog/i6300esb.c @@ -83,7 +83,6 @@ static unsigned short triggered; /* The status of the watchdog upon boot */ static char esb_expect_close; static struct platform_device *esb_platform_device; - /* module parameters */ /* 30 sec default heartbeat (1 < heartbeat < 2*1023) */ #define WATCHDOG_HEARTBEAT 30 @@ -116,13 +115,18 @@ static inline void esb_unlock_registers(void) writeb(ESB_UNLOCK2, ESB_RELOAD_REG); } -static void esb_timer_start(void) +static int esb_timer_start(void) { u8 val; + spin_lock(&esb_lock); + esb_unlock_registers(); + writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); /* Enable or Enable + Lock? */ val = 0x02 | (nowayout ? 0x01 : 0x00); pci_write_config_byte(esb_pci, ESB_LOCK_REG, val); + spin_unlock(&esb_lock); + return 0; } static int esb_timer_stop(void) @@ -209,7 +213,6 @@ static int esb_open(struct inode *inode, struct file *file) return -EBUSY; /* Reload and activate timer */ - esb_timer_keepalive(); esb_timer_start(); return nonseekable_open(inode, file); @@ -295,7 +298,6 @@ static long esb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } if (new_options & WDIOS_ENABLECARD) { - esb_timer_keepalive(); esb_timer_start(); retval = 0; } -- GitLab From 67bb6c036d1fc3d332c8527a36a546e3e72e822c Mon Sep 17 00:00:00 2001 From: Gautham R Shenoy Date: Wed, 25 Mar 2009 14:43:35 +0530 Subject: [PATCH 4521/4982] sched: Simple helper functions for find_busiest_group() Impact: cleanup Currently the load idx calculation code is in find_busiest_group(). Move that to a static inline helper function. Similary, to find the first cpu of a sched_group we use cpumask_first(sched_group_cpus(group)) Use a helper to that. It improves readability in some cases. Signed-off-by: Gautham R Shenoy Acked-by: Peter Zijlstra Cc: Suresh Siddha Cc: "Balbir Singh" Cc: Nick Piggin Cc: "Dhaval Giani" Cc: Bharata B Rao Cc: "Vaidyanathan Srinivasan" LKML-Reference: <20090325091335.13992.55424.stgit@sofia.in.ibm.com> Signed-off-by: Ingo Molnar --- kernel/sched.c | 55 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 7b389c74f8f..6aec1e7a72a 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3189,6 +3189,43 @@ static int move_one_task(struct rq *this_rq, int this_cpu, struct rq *busiest, return 0; } +/********** Helpers for find_busiest_group ************************/ + +/** + * group_first_cpu - Returns the first cpu in the cpumask of a sched_group. + * @group: The group whose first cpu is to be returned. + */ +static inline unsigned int group_first_cpu(struct sched_group *group) +{ + return cpumask_first(sched_group_cpus(group)); +} + +/** + * get_sd_load_idx - Obtain the load index for a given sched domain. + * @sd: The sched_domain whose load_idx is to be obtained. + * @idle: The Idle status of the CPU for whose sd load_icx is obtained. + */ +static inline int get_sd_load_idx(struct sched_domain *sd, + enum cpu_idle_type idle) +{ + int load_idx; + + switch (idle) { + case CPU_NOT_IDLE: + load_idx = sd->busy_idx; + break; + + case CPU_NEWLY_IDLE: + load_idx = sd->newidle_idx; + break; + default: + load_idx = sd->idle_idx; + break; + } + + return load_idx; +} +/******* find_busiest_group() helpers end here *********************/ /* * find_busiest_group finds and returns the busiest CPU group within the @@ -3217,12 +3254,7 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, busiest_load_per_task = busiest_nr_running = 0; this_load_per_task = this_nr_running = 0; - if (idle == CPU_NOT_IDLE) - load_idx = sd->busy_idx; - else if (idle == CPU_NEWLY_IDLE) - load_idx = sd->newidle_idx; - else - load_idx = sd->idle_idx; + load_idx = get_sd_load_idx(sd, idle); do { unsigned long load, group_capacity, max_cpu_load, min_cpu_load; @@ -3238,7 +3270,7 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, sched_group_cpus(group)); if (local_group) - balance_cpu = cpumask_first(sched_group_cpus(group)); + balance_cpu = group_first_cpu(group); /* Tally up the load of all CPUs in the group */ sum_weighted_load = sum_nr_running = avg_load = 0; @@ -3359,8 +3391,7 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, */ if ((sum_nr_running < min_nr_running) || (sum_nr_running == min_nr_running && - cpumask_first(sched_group_cpus(group)) > - cpumask_first(sched_group_cpus(group_min)))) { + group_first_cpu(group) > group_first_cpu(group_min))) { group_min = group; min_nr_running = sum_nr_running; min_load_per_task = sum_weighted_load / @@ -3375,8 +3406,8 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, if (sum_nr_running <= group_capacity - 1) { if (sum_nr_running > leader_nr_running || (sum_nr_running == leader_nr_running && - cpumask_first(sched_group_cpus(group)) < - cpumask_first(sched_group_cpus(group_leader)))) { + group_first_cpu(group) < + group_first_cpu(group_leader))) { group_leader = group; leader_nr_running = sum_nr_running; } @@ -3504,7 +3535,7 @@ out_balanced: *imbalance = min_load_per_task; if (sched_mc_power_savings >= POWERSAVINGS_BALANCE_WAKEUP) { cpu_rq(this_cpu)->rd->sched_mc_preferred_wakeup_cpu = - cpumask_first(sched_group_cpus(group_leader)); + group_first_cpu(group_leader); } return group_min; } -- GitLab From 6dfdb0629019f307ab18864b1fd3e5dbb02f383c Mon Sep 17 00:00:00 2001 From: Gautham R Shenoy Date: Wed, 25 Mar 2009 14:43:40 +0530 Subject: [PATCH 4522/4982] sched: Fix indentations in find_busiest_group() using gotos Impact: cleanup Some indentations in find_busiest_group() can minimized by using early exits with the help of gotos. This improves readability in a couple of cases. Signed-off-by: Gautham R Shenoy Acked-by: Peter Zijlstra Cc: Suresh Siddha Cc: "Balbir Singh" Cc: Nick Piggin Cc: "Dhaval Giani" Cc: Bharata B Rao Cc: "Vaidyanathan Srinivasan" LKML-Reference: <20090325091340.13992.45062.stgit@sofia.in.ibm.com> Signed-off-by: Ingo Molnar --- kernel/sched.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 6aec1e7a72a..f87adbe999e 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3403,14 +3403,14 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, * capacity but still has some space to pick up some load * from other group and save more power */ - if (sum_nr_running <= group_capacity - 1) { - if (sum_nr_running > leader_nr_running || - (sum_nr_running == leader_nr_running && - group_first_cpu(group) < - group_first_cpu(group_leader))) { - group_leader = group; - leader_nr_running = sum_nr_running; - } + if (sum_nr_running > group_capacity - 1) + goto group_next; + + if (sum_nr_running > leader_nr_running || + (sum_nr_running == leader_nr_running && + group_first_cpu(group) < group_first_cpu(group_leader))) { + group_leader = group; + leader_nr_running = sum_nr_running; } group_next: #endif @@ -3531,14 +3531,16 @@ out_balanced: if (idle == CPU_NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE)) goto ret; - if (this == group_leader && group_leader != group_min) { - *imbalance = min_load_per_task; - if (sched_mc_power_savings >= POWERSAVINGS_BALANCE_WAKEUP) { - cpu_rq(this_cpu)->rd->sched_mc_preferred_wakeup_cpu = - group_first_cpu(group_leader); - } - return group_min; + if (this != group_leader || group_leader == group_min) + goto ret; + + *imbalance = min_load_per_task; + if (sched_mc_power_savings >= POWERSAVINGS_BALANCE_WAKEUP) { + cpu_rq(this_cpu)->rd->sched_mc_preferred_wakeup_cpu = + group_first_cpu(group_leader); } + return group_min; + #endif ret: *imbalance = 0; -- GitLab From 381be78fdc829a22f6327a0ed09f54b6270a976d Mon Sep 17 00:00:00 2001 From: Gautham R Shenoy Date: Wed, 25 Mar 2009 14:43:46 +0530 Subject: [PATCH 4523/4982] sched: Define structure to store the sched_group statistics for fbg() Impact: cleanup Currently a whole bunch of variables are used to store the various statistics pertaining to the groups we iterate over in find_busiest_group(). Group them together in a single data structure and add appropriate comments. This will be useful later on when we create helper functions to calculate the sched_group statistics. Credit: Vaidyanathan Srinivasan Signed-off-by: Gautham R Shenoy Acked-by: Peter Zijlstra Cc: Suresh Siddha Cc: "Balbir Singh" Cc: Nick Piggin Cc: "Dhaval Giani" Cc: Bharata B Rao LKML-Reference: <20090325091345.13992.20099.stgit@sofia.in.ibm.com> Signed-off-by: Ingo Molnar --- kernel/sched.c | 79 +++++++++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 33 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index f87adbe999e..109db122de5 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3191,6 +3191,18 @@ static int move_one_task(struct rq *this_rq, int this_cpu, struct rq *busiest, } /********** Helpers for find_busiest_group ************************/ +/** + * sg_lb_stats - stats of a sched_group required for load_balancing + */ +struct sg_lb_stats { + unsigned long avg_load; /*Avg load across the CPUs of the group */ + unsigned long group_load; /* Total load over the CPUs of the group */ + unsigned long sum_nr_running; /* Nr tasks running in the group */ + unsigned long sum_weighted_load; /* Weighted load of group's tasks */ + unsigned long group_capacity; + int group_imb; /* Is there an imbalance in the group ? */ +}; + /** * group_first_cpu - Returns the first cpu in the cpumask of a sched_group. * @group: The group whose first cpu is to be returned. @@ -3257,23 +3269,22 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, load_idx = get_sd_load_idx(sd, idle); do { - unsigned long load, group_capacity, max_cpu_load, min_cpu_load; + struct sg_lb_stats sgs; + unsigned long load, max_cpu_load, min_cpu_load; int local_group; int i; - int __group_imb = 0; unsigned int balance_cpu = -1, first_idle_cpu = 0; - unsigned long sum_nr_running, sum_weighted_load; unsigned long sum_avg_load_per_task; unsigned long avg_load_per_task; local_group = cpumask_test_cpu(this_cpu, sched_group_cpus(group)); + memset(&sgs, 0, sizeof(sgs)); if (local_group) balance_cpu = group_first_cpu(group); /* Tally up the load of all CPUs in the group */ - sum_weighted_load = sum_nr_running = avg_load = 0; sum_avg_load_per_task = avg_load_per_task = 0; max_cpu_load = 0; @@ -3301,9 +3312,9 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, min_cpu_load = load; } - avg_load += load; - sum_nr_running += rq->nr_running; - sum_weighted_load += weighted_cpuload(i); + sgs.group_load += load; + sgs.sum_nr_running += rq->nr_running; + sgs.sum_weighted_load += weighted_cpuload(i); sum_avg_load_per_task += cpu_avg_load_per_task(i); } @@ -3320,12 +3331,12 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, goto ret; } - total_load += avg_load; + total_load += sgs.group_load; total_pwr += group->__cpu_power; /* Adjust by relative CPU power of the group */ - avg_load = sg_div_cpu_power(group, - avg_load * SCHED_LOAD_SCALE); + sgs.avg_load = sg_div_cpu_power(group, + sgs.group_load * SCHED_LOAD_SCALE); /* @@ -3341,22 +3352,23 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, sum_avg_load_per_task * SCHED_LOAD_SCALE); if ((max_cpu_load - min_cpu_load) > 2*avg_load_per_task) - __group_imb = 1; + sgs.group_imb = 1; - group_capacity = group->__cpu_power / SCHED_LOAD_SCALE; + sgs.group_capacity = group->__cpu_power / SCHED_LOAD_SCALE; if (local_group) { - this_load = avg_load; + this_load = sgs.avg_load; this = group; - this_nr_running = sum_nr_running; - this_load_per_task = sum_weighted_load; - } else if (avg_load > max_load && - (sum_nr_running > group_capacity || __group_imb)) { - max_load = avg_load; + this_nr_running = sgs.sum_nr_running; + this_load_per_task = sgs.sum_weighted_load; + } else if (sgs.avg_load > max_load && + (sgs.sum_nr_running > sgs.group_capacity || + sgs.group_imb)) { + max_load = sgs.avg_load; busiest = group; - busiest_nr_running = sum_nr_running; - busiest_load_per_task = sum_weighted_load; - group_imb = __group_imb; + busiest_nr_running = sgs.sum_nr_running; + busiest_load_per_task = sgs.sum_weighted_load; + group_imb = sgs.group_imb; } #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) @@ -3372,7 +3384,7 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, * If the local group is idle or completely loaded * no need to do power savings balance at this domain */ - if (local_group && (this_nr_running >= group_capacity || + if (local_group && (this_nr_running >= sgs.group_capacity || !this_nr_running)) power_savings_balance = 0; @@ -3380,8 +3392,9 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, * If a group is already running at full capacity or idle, * don't include that group in power savings calculations */ - if (!power_savings_balance || sum_nr_running >= group_capacity - || !sum_nr_running) + if (!power_savings_balance || + sgs.sum_nr_running >= sgs.group_capacity || + !sgs.sum_nr_running) goto group_next; /* @@ -3389,13 +3402,13 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, * This is the group from where we need to pick up the load * for saving power */ - if ((sum_nr_running < min_nr_running) || - (sum_nr_running == min_nr_running && + if ((sgs.sum_nr_running < min_nr_running) || + (sgs.sum_nr_running == min_nr_running && group_first_cpu(group) > group_first_cpu(group_min))) { group_min = group; - min_nr_running = sum_nr_running; - min_load_per_task = sum_weighted_load / - sum_nr_running; + min_nr_running = sgs.sum_nr_running; + min_load_per_task = sgs.sum_weighted_load / + sgs.sum_nr_running; } /* @@ -3403,14 +3416,14 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, * capacity but still has some space to pick up some load * from other group and save more power */ - if (sum_nr_running > group_capacity - 1) + if (sgs.sum_nr_running > sgs.group_capacity - 1) goto group_next; - if (sum_nr_running > leader_nr_running || - (sum_nr_running == leader_nr_running && + if (sgs.sum_nr_running > leader_nr_running || + (sgs.sum_nr_running == leader_nr_running && group_first_cpu(group) < group_first_cpu(group_leader))) { group_leader = group; - leader_nr_running = sum_nr_running; + leader_nr_running = sgs.sum_nr_running; } group_next: #endif -- GitLab From 1f8c553d0f11d85f7993fe21015695d266771c00 Mon Sep 17 00:00:00 2001 From: Gautham R Shenoy Date: Wed, 25 Mar 2009 14:43:51 +0530 Subject: [PATCH 4524/4982] sched: Create a helper function to calculate sched_group stats for fbg() Impact: cleanup Create a helper function named update_sg_lb_stats() which can be invoked to calculate the individual group's statistics in find_busiest_group(). This reduces the lenght of find_busiest_group() considerably. Credit: Vaidyanathan Srinivasan Signed-off-by: Gautham R Shenoy Aked-by: Peter Zijlstra Cc: Suresh Siddha Cc: "Balbir Singh" Cc: Nick Piggin Cc: "Dhaval Giani" Cc: Bharata B Rao LKML-Reference: <20090325091351.13992.43461.stgit@sofia.in.ibm.com> Signed-off-by: Ingo Molnar --- kernel/sched.c | 175 ++++++++++++++++++++++++++++--------------------- 1 file changed, 100 insertions(+), 75 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 109db122de5..1893d5562f5 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3237,6 +3237,103 @@ static inline int get_sd_load_idx(struct sched_domain *sd, return load_idx; } + + +/** + * update_sg_lb_stats - Update sched_group's statistics for load balancing. + * @group: sched_group whose statistics are to be updated. + * @this_cpu: Cpu for which load balance is currently performed. + * @idle: Idle status of this_cpu + * @load_idx: Load index of sched_domain of this_cpu for load calc. + * @sd_idle: Idle status of the sched_domain containing group. + * @local_group: Does group contain this_cpu. + * @cpus: Set of cpus considered for load balancing. + * @balance: Should we balance. + * @sgs: variable to hold the statistics for this group. + */ +static inline void update_sg_lb_stats(struct sched_group *group, int this_cpu, + enum cpu_idle_type idle, int load_idx, int *sd_idle, + int local_group, const struct cpumask *cpus, + int *balance, struct sg_lb_stats *sgs) +{ + unsigned long load, max_cpu_load, min_cpu_load; + int i; + unsigned int balance_cpu = -1, first_idle_cpu = 0; + unsigned long sum_avg_load_per_task; + unsigned long avg_load_per_task; + + if (local_group) + balance_cpu = group_first_cpu(group); + + /* Tally up the load of all CPUs in the group */ + sum_avg_load_per_task = avg_load_per_task = 0; + max_cpu_load = 0; + min_cpu_load = ~0UL; + + for_each_cpu_and(i, sched_group_cpus(group), cpus) { + struct rq *rq = cpu_rq(i); + + if (*sd_idle && rq->nr_running) + *sd_idle = 0; + + /* Bias balancing toward cpus of our domain */ + if (local_group) { + if (idle_cpu(i) && !first_idle_cpu) { + first_idle_cpu = 1; + balance_cpu = i; + } + + load = target_load(i, load_idx); + } else { + load = source_load(i, load_idx); + if (load > max_cpu_load) + max_cpu_load = load; + if (min_cpu_load > load) + min_cpu_load = load; + } + + sgs->group_load += load; + sgs->sum_nr_running += rq->nr_running; + sgs->sum_weighted_load += weighted_cpuload(i); + + sum_avg_load_per_task += cpu_avg_load_per_task(i); + } + + /* + * First idle cpu or the first cpu(busiest) in this sched group + * is eligible for doing load balancing at this and above + * domains. In the newly idle case, we will allow all the cpu's + * to do the newly idle load balance. + */ + if (idle != CPU_NEWLY_IDLE && local_group && + balance_cpu != this_cpu && balance) { + *balance = 0; + return; + } + + /* Adjust by relative CPU power of the group */ + sgs->avg_load = sg_div_cpu_power(group, + sgs->group_load * SCHED_LOAD_SCALE); + + + /* + * Consider the group unbalanced when the imbalance is larger + * than the average weight of two tasks. + * + * APZ: with cgroup the avg task weight can vary wildly and + * might not be a suitable number - should we keep a + * normalized nr_running number somewhere that negates + * the hierarchy? + */ + avg_load_per_task = sg_div_cpu_power(group, + sum_avg_load_per_task * SCHED_LOAD_SCALE); + + if ((max_cpu_load - min_cpu_load) > 2*avg_load_per_task) + sgs->group_imb = 1; + + sgs->group_capacity = group->__cpu_power / SCHED_LOAD_SCALE; + +} /******* find_busiest_group() helpers end here *********************/ /* @@ -3270,92 +3367,20 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, do { struct sg_lb_stats sgs; - unsigned long load, max_cpu_load, min_cpu_load; int local_group; - int i; - unsigned int balance_cpu = -1, first_idle_cpu = 0; - unsigned long sum_avg_load_per_task; - unsigned long avg_load_per_task; local_group = cpumask_test_cpu(this_cpu, sched_group_cpus(group)); memset(&sgs, 0, sizeof(sgs)); + update_sg_lb_stats(group, this_cpu, idle, load_idx, sd_idle, + local_group, cpus, balance, &sgs); - if (local_group) - balance_cpu = group_first_cpu(group); - - /* Tally up the load of all CPUs in the group */ - sum_avg_load_per_task = avg_load_per_task = 0; - - max_cpu_load = 0; - min_cpu_load = ~0UL; - - for_each_cpu_and(i, sched_group_cpus(group), cpus) { - struct rq *rq = cpu_rq(i); - - if (*sd_idle && rq->nr_running) - *sd_idle = 0; - - /* Bias balancing toward cpus of our domain */ - if (local_group) { - if (idle_cpu(i) && !first_idle_cpu) { - first_idle_cpu = 1; - balance_cpu = i; - } - - load = target_load(i, load_idx); - } else { - load = source_load(i, load_idx); - if (load > max_cpu_load) - max_cpu_load = load; - if (min_cpu_load > load) - min_cpu_load = load; - } - - sgs.group_load += load; - sgs.sum_nr_running += rq->nr_running; - sgs.sum_weighted_load += weighted_cpuload(i); - - sum_avg_load_per_task += cpu_avg_load_per_task(i); - } - - /* - * First idle cpu or the first cpu(busiest) in this sched group - * is eligible for doing load balancing at this and above - * domains. In the newly idle case, we will allow all the cpu's - * to do the newly idle load balance. - */ - if (idle != CPU_NEWLY_IDLE && local_group && - balance_cpu != this_cpu && balance) { - *balance = 0; + if (balance && !(*balance)) goto ret; - } total_load += sgs.group_load; total_pwr += group->__cpu_power; - /* Adjust by relative CPU power of the group */ - sgs.avg_load = sg_div_cpu_power(group, - sgs.group_load * SCHED_LOAD_SCALE); - - - /* - * Consider the group unbalanced when the imbalance is larger - * than the average weight of two tasks. - * - * APZ: with cgroup the avg task weight can vary wildly and - * might not be a suitable number - should we keep a - * normalized nr_running number somewhere that negates - * the hierarchy? - */ - avg_load_per_task = sg_div_cpu_power(group, - sum_avg_load_per_task * SCHED_LOAD_SCALE); - - if ((max_cpu_load - min_cpu_load) > 2*avg_load_per_task) - sgs.group_imb = 1; - - sgs.group_capacity = group->__cpu_power / SCHED_LOAD_SCALE; - if (local_group) { this_load = sgs.avg_load; this = group; -- GitLab From 222d656dea57e4e084fbd1e9383e6fed2ca9fa61 Mon Sep 17 00:00:00 2001 From: Gautham R Shenoy Date: Wed, 25 Mar 2009 14:43:56 +0530 Subject: [PATCH 4525/4982] sched: Define structure to store the sched_domain statistics for fbg() Impact: cleanup Currently we use a lot of local variables in find_busiest_group() to capture the various statistics related to the sched_domain. Group them together into a single data structure. This will help us to offload the job of updating the sched_domain statistics to a helper function. Credit: Vaidyanathan Srinivasan Signed-off-by: Gautham R Shenoy Acked-by: Peter Zijlstra Cc: Suresh Siddha Cc: "Balbir Singh" Cc: Nick Piggin Cc: "Dhaval Giani" Cc: Bharata B Rao LKML-Reference: <20090325091356.13992.25970.stgit@sofia.in.ibm.com> Signed-off-by: Ingo Molnar --- kernel/sched.c | 207 +++++++++++++++++++++++++++++-------------------- 1 file changed, 121 insertions(+), 86 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 1893d5562f5..8198dbe8e4a 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3190,6 +3190,37 @@ static int move_one_task(struct rq *this_rq, int this_cpu, struct rq *busiest, return 0; } /********** Helpers for find_busiest_group ************************/ +/** + * sd_lb_stats - Structure to store the statistics of a sched_domain + * during load balancing. + */ +struct sd_lb_stats { + struct sched_group *busiest; /* Busiest group in this sd */ + struct sched_group *this; /* Local group in this sd */ + unsigned long total_load; /* Total load of all groups in sd */ + unsigned long total_pwr; /* Total power of all groups in sd */ + unsigned long avg_load; /* Average load across all groups in sd */ + + /** Statistics of this group */ + unsigned long this_load; + unsigned long this_load_per_task; + unsigned long this_nr_running; + + /* Statistics of the busiest group */ + unsigned long max_load; + unsigned long busiest_load_per_task; + unsigned long busiest_nr_running; + + int group_imb; /* Is there imbalance in this sd */ +#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) + int power_savings_balance; /* Is powersave balance needed for this sd */ + struct sched_group *group_min; /* Least loaded group in sd */ + struct sched_group *group_leader; /* Group which relieves group_min */ + unsigned long min_load_per_task; /* load_per_task in group_min */ + unsigned long leader_nr_running; /* Nr running of group_leader */ + unsigned long min_nr_running; /* Nr running of group_min */ +#endif +}; /** * sg_lb_stats - stats of a sched_group required for load_balancing @@ -3346,23 +3377,16 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, unsigned long *imbalance, enum cpu_idle_type idle, int *sd_idle, const struct cpumask *cpus, int *balance) { - struct sched_group *busiest = NULL, *this = NULL, *group = sd->groups; - unsigned long max_load, avg_load, total_load, this_load, total_pwr; + struct sd_lb_stats sds; + struct sched_group *group = sd->groups; unsigned long max_pull; - unsigned long busiest_load_per_task, busiest_nr_running; - unsigned long this_load_per_task, this_nr_running; - int load_idx, group_imb = 0; + int load_idx; + + memset(&sds, 0, sizeof(sds)); #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) - int power_savings_balance = 1; - unsigned long leader_nr_running = 0, min_load_per_task = 0; - unsigned long min_nr_running = ULONG_MAX; - struct sched_group *group_min = NULL, *group_leader = NULL; + sds.power_savings_balance = 1; + sds.min_nr_running = ULONG_MAX; #endif - - max_load = this_load = total_load = total_pwr = 0; - busiest_load_per_task = busiest_nr_running = 0; - this_load_per_task = this_nr_running = 0; - load_idx = get_sd_load_idx(sd, idle); do { @@ -3378,22 +3402,22 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, if (balance && !(*balance)) goto ret; - total_load += sgs.group_load; - total_pwr += group->__cpu_power; + sds.total_load += sgs.group_load; + sds.total_pwr += group->__cpu_power; if (local_group) { - this_load = sgs.avg_load; - this = group; - this_nr_running = sgs.sum_nr_running; - this_load_per_task = sgs.sum_weighted_load; - } else if (sgs.avg_load > max_load && + sds.this_load = sgs.avg_load; + sds.this = group; + sds.this_nr_running = sgs.sum_nr_running; + sds.this_load_per_task = sgs.sum_weighted_load; + } else if (sgs.avg_load > sds.max_load && (sgs.sum_nr_running > sgs.group_capacity || sgs.group_imb)) { - max_load = sgs.avg_load; - busiest = group; - busiest_nr_running = sgs.sum_nr_running; - busiest_load_per_task = sgs.sum_weighted_load; - group_imb = sgs.group_imb; + sds.max_load = sgs.avg_load; + sds.busiest = group; + sds.busiest_nr_running = sgs.sum_nr_running; + sds.busiest_load_per_task = sgs.sum_weighted_load; + sds.group_imb = sgs.group_imb; } #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) @@ -3409,15 +3433,16 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, * If the local group is idle or completely loaded * no need to do power savings balance at this domain */ - if (local_group && (this_nr_running >= sgs.group_capacity || - !this_nr_running)) - power_savings_balance = 0; + if (local_group && + (sds.this_nr_running >= sgs.group_capacity || + !sds.this_nr_running)) + sds.power_savings_balance = 0; /* * If a group is already running at full capacity or idle, * don't include that group in power savings calculations */ - if (!power_savings_balance || + if (!sds.power_savings_balance || sgs.sum_nr_running >= sgs.group_capacity || !sgs.sum_nr_running) goto group_next; @@ -3427,12 +3452,13 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, * This is the group from where we need to pick up the load * for saving power */ - if ((sgs.sum_nr_running < min_nr_running) || - (sgs.sum_nr_running == min_nr_running && - group_first_cpu(group) > group_first_cpu(group_min))) { - group_min = group; - min_nr_running = sgs.sum_nr_running; - min_load_per_task = sgs.sum_weighted_load / + if ((sgs.sum_nr_running < sds.min_nr_running) || + (sgs.sum_nr_running == sds.min_nr_running && + group_first_cpu(group) > + group_first_cpu(sds.group_min))) { + sds.group_min = group; + sds.min_nr_running = sgs.sum_nr_running; + sds.min_load_per_task = sgs.sum_weighted_load / sgs.sum_nr_running; } @@ -3444,29 +3470,32 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, if (sgs.sum_nr_running > sgs.group_capacity - 1) goto group_next; - if (sgs.sum_nr_running > leader_nr_running || - (sgs.sum_nr_running == leader_nr_running && - group_first_cpu(group) < group_first_cpu(group_leader))) { - group_leader = group; - leader_nr_running = sgs.sum_nr_running; + if (sgs.sum_nr_running > sds.leader_nr_running || + (sgs.sum_nr_running == sds.leader_nr_running && + group_first_cpu(group) < + group_first_cpu(sds.group_leader))) { + sds.group_leader = group; + sds.leader_nr_running = sgs.sum_nr_running; } group_next: #endif group = group->next; } while (group != sd->groups); - if (!busiest || this_load >= max_load || busiest_nr_running == 0) + if (!sds.busiest || sds.this_load >= sds.max_load + || sds.busiest_nr_running == 0) goto out_balanced; - avg_load = (SCHED_LOAD_SCALE * total_load) / total_pwr; + sds.avg_load = (SCHED_LOAD_SCALE * sds.total_load) / sds.total_pwr; - if (this_load >= avg_load || - 100*max_load <= sd->imbalance_pct*this_load) + if (sds.this_load >= sds.avg_load || + 100*sds.max_load <= sd->imbalance_pct * sds.this_load) goto out_balanced; - busiest_load_per_task /= busiest_nr_running; - if (group_imb) - busiest_load_per_task = min(busiest_load_per_task, avg_load); + sds.busiest_load_per_task /= sds.busiest_nr_running; + if (sds.group_imb) + sds.busiest_load_per_task = + min(sds.busiest_load_per_task, sds.avg_load); /* * We're trying to get all the cpus to the average_load, so we don't @@ -3479,7 +3508,7 @@ group_next: * by pulling tasks to us. Be careful of negative numbers as they'll * appear as very large values with unsigned longs. */ - if (max_load <= busiest_load_per_task) + if (sds.max_load <= sds.busiest_load_per_task) goto out_balanced; /* @@ -3487,17 +3516,18 @@ group_next: * max load less than avg load(as we skip the groups at or below * its cpu_power, while calculating max_load..) */ - if (max_load < avg_load) { + if (sds.max_load < sds.avg_load) { *imbalance = 0; goto small_imbalance; } /* Don't want to pull so many tasks that a group would go idle */ - max_pull = min(max_load - avg_load, max_load - busiest_load_per_task); + max_pull = min(sds.max_load - sds.avg_load, + sds.max_load - sds.busiest_load_per_task); /* How much load to actually move to equalise the imbalance */ - *imbalance = min(max_pull * busiest->__cpu_power, - (avg_load - this_load) * this->__cpu_power) + *imbalance = min(max_pull * sds.busiest->__cpu_power, + (sds.avg_load - sds.this_load) * sds.this->__cpu_power) / SCHED_LOAD_SCALE; /* @@ -3506,24 +3536,27 @@ group_next: * a think about bumping its value to force at least one task to be * moved */ - if (*imbalance < busiest_load_per_task) { + if (*imbalance < sds.busiest_load_per_task) { unsigned long tmp, pwr_now, pwr_move; unsigned int imbn; small_imbalance: pwr_move = pwr_now = 0; imbn = 2; - if (this_nr_running) { - this_load_per_task /= this_nr_running; - if (busiest_load_per_task > this_load_per_task) + if (sds.this_nr_running) { + sds.this_load_per_task /= sds.this_nr_running; + if (sds.busiest_load_per_task > + sds.this_load_per_task) imbn = 1; } else - this_load_per_task = cpu_avg_load_per_task(this_cpu); - - if (max_load - this_load + busiest_load_per_task >= - busiest_load_per_task * imbn) { - *imbalance = busiest_load_per_task; - return busiest; + sds.this_load_per_task = + cpu_avg_load_per_task(this_cpu); + + if (sds.max_load - sds.this_load + + sds.busiest_load_per_task >= + sds.busiest_load_per_task * imbn) { + *imbalance = sds.busiest_load_per_task; + return sds.busiest; } /* @@ -3532,52 +3565,54 @@ small_imbalance: * moving them. */ - pwr_now += busiest->__cpu_power * - min(busiest_load_per_task, max_load); - pwr_now += this->__cpu_power * - min(this_load_per_task, this_load); + pwr_now += sds.busiest->__cpu_power * + min(sds.busiest_load_per_task, sds.max_load); + pwr_now += sds.this->__cpu_power * + min(sds.this_load_per_task, sds.this_load); pwr_now /= SCHED_LOAD_SCALE; /* Amount of load we'd subtract */ - tmp = sg_div_cpu_power(busiest, - busiest_load_per_task * SCHED_LOAD_SCALE); - if (max_load > tmp) - pwr_move += busiest->__cpu_power * - min(busiest_load_per_task, max_load - tmp); + tmp = sg_div_cpu_power(sds.busiest, + sds.busiest_load_per_task * SCHED_LOAD_SCALE); + if (sds.max_load > tmp) + pwr_move += sds.busiest->__cpu_power * + min(sds.busiest_load_per_task, + sds.max_load - tmp); /* Amount of load we'd add */ - if (max_load * busiest->__cpu_power < - busiest_load_per_task * SCHED_LOAD_SCALE) - tmp = sg_div_cpu_power(this, - max_load * busiest->__cpu_power); + if (sds.max_load * sds.busiest->__cpu_power < + sds.busiest_load_per_task * SCHED_LOAD_SCALE) + tmp = sg_div_cpu_power(sds.this, + sds.max_load * sds.busiest->__cpu_power); else - tmp = sg_div_cpu_power(this, - busiest_load_per_task * SCHED_LOAD_SCALE); - pwr_move += this->__cpu_power * - min(this_load_per_task, this_load + tmp); + tmp = sg_div_cpu_power(sds.this, + sds.busiest_load_per_task * SCHED_LOAD_SCALE); + pwr_move += sds.this->__cpu_power * + min(sds.this_load_per_task, + sds.this_load + tmp); pwr_move /= SCHED_LOAD_SCALE; /* Move if we gain throughput */ if (pwr_move > pwr_now) - *imbalance = busiest_load_per_task; + *imbalance = sds.busiest_load_per_task; } - return busiest; + return sds.busiest; out_balanced: #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) if (idle == CPU_NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE)) goto ret; - if (this != group_leader || group_leader == group_min) + if (sds.this != sds.group_leader || sds.group_leader == sds.group_min) goto ret; - *imbalance = min_load_per_task; + *imbalance = sds.min_load_per_task; if (sched_mc_power_savings >= POWERSAVINGS_BALANCE_WAKEUP) { cpu_rq(this_cpu)->rd->sched_mc_preferred_wakeup_cpu = - group_first_cpu(group_leader); + group_first_cpu(sds.group_leader); } - return group_min; + return sds.group_min; #endif ret: -- GitLab From 37abe198b1246ddd206319c43502a687db62d347 Mon Sep 17 00:00:00 2001 From: Gautham R Shenoy Date: Wed, 25 Mar 2009 14:44:01 +0530 Subject: [PATCH 4526/4982] sched: Create a helper function to calculate sched_domain stats for fbg() Impact: cleanup Create a helper function named update_sd_lb_stats() to update the various sched_domain related statistics in find_busiest_group(). With this we would have moved all the statistics computation out of find_busiest_group(). Credit: Vaidyanathan Srinivasan Signed-off-by: Gautham R Shenoy Acked-by: Peter Zijlstra Cc: Suresh Siddha Cc: "Balbir Singh" Cc: Nick Piggin Cc: "Dhaval Giani" Cc: Bharata B Rao LKML-Reference: <20090325091401.13992.88737.stgit@sofia.in.ibm.com> Signed-off-by: Ingo Molnar --- kernel/sched.c | 117 ++++++++++++++++++++++++++++++------------------- 1 file changed, 73 insertions(+), 44 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 8198dbe8e4a..ec715f97202 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3365,32 +3365,33 @@ static inline void update_sg_lb_stats(struct sched_group *group, int this_cpu, sgs->group_capacity = group->__cpu_power / SCHED_LOAD_SCALE; } -/******* find_busiest_group() helpers end here *********************/ -/* - * find_busiest_group finds and returns the busiest CPU group within the - * domain. It calculates and returns the amount of weighted load which - * should be moved to restore balance via the imbalance parameter. +/** + * update_sd_lb_stats - Update sched_group's statistics for load balancing. + * @sd: sched_domain whose statistics are to be updated. + * @this_cpu: Cpu for which load balance is currently performed. + * @idle: Idle status of this_cpu + * @sd_idle: Idle status of the sched_domain containing group. + * @cpus: Set of cpus considered for load balancing. + * @balance: Should we balance. + * @sds: variable to hold the statistics for this sched_domain. */ -static struct sched_group * -find_busiest_group(struct sched_domain *sd, int this_cpu, - unsigned long *imbalance, enum cpu_idle_type idle, - int *sd_idle, const struct cpumask *cpus, int *balance) +static inline void update_sd_lb_stats(struct sched_domain *sd, int this_cpu, + enum cpu_idle_type idle, int *sd_idle, + const struct cpumask *cpus, int *balance, + struct sd_lb_stats *sds) { - struct sd_lb_stats sds; struct sched_group *group = sd->groups; - unsigned long max_pull; + struct sg_lb_stats sgs; int load_idx; - memset(&sds, 0, sizeof(sds)); #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) - sds.power_savings_balance = 1; - sds.min_nr_running = ULONG_MAX; + sds->power_savings_balance = 1; + sds->min_nr_running = ULONG_MAX; #endif load_idx = get_sd_load_idx(sd, idle); do { - struct sg_lb_stats sgs; int local_group; local_group = cpumask_test_cpu(this_cpu, @@ -3399,25 +3400,25 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, update_sg_lb_stats(group, this_cpu, idle, load_idx, sd_idle, local_group, cpus, balance, &sgs); - if (balance && !(*balance)) - goto ret; + if (local_group && balance && !(*balance)) + return; - sds.total_load += sgs.group_load; - sds.total_pwr += group->__cpu_power; + sds->total_load += sgs.group_load; + sds->total_pwr += group->__cpu_power; if (local_group) { - sds.this_load = sgs.avg_load; - sds.this = group; - sds.this_nr_running = sgs.sum_nr_running; - sds.this_load_per_task = sgs.sum_weighted_load; - } else if (sgs.avg_load > sds.max_load && + sds->this_load = sgs.avg_load; + sds->this = group; + sds->this_nr_running = sgs.sum_nr_running; + sds->this_load_per_task = sgs.sum_weighted_load; + } else if (sgs.avg_load > sds->max_load && (sgs.sum_nr_running > sgs.group_capacity || sgs.group_imb)) { - sds.max_load = sgs.avg_load; - sds.busiest = group; - sds.busiest_nr_running = sgs.sum_nr_running; - sds.busiest_load_per_task = sgs.sum_weighted_load; - sds.group_imb = sgs.group_imb; + sds->max_load = sgs.avg_load; + sds->busiest = group; + sds->busiest_nr_running = sgs.sum_nr_running; + sds->busiest_load_per_task = sgs.sum_weighted_load; + sds->group_imb = sgs.group_imb; } #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) @@ -3434,15 +3435,15 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, * no need to do power savings balance at this domain */ if (local_group && - (sds.this_nr_running >= sgs.group_capacity || - !sds.this_nr_running)) - sds.power_savings_balance = 0; + (sds->this_nr_running >= sgs.group_capacity || + !sds->this_nr_running)) + sds->power_savings_balance = 0; /* * If a group is already running at full capacity or idle, * don't include that group in power savings calculations */ - if (!sds.power_savings_balance || + if (!sds->power_savings_balance || sgs.sum_nr_running >= sgs.group_capacity || !sgs.sum_nr_running) goto group_next; @@ -3452,13 +3453,13 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, * This is the group from where we need to pick up the load * for saving power */ - if ((sgs.sum_nr_running < sds.min_nr_running) || - (sgs.sum_nr_running == sds.min_nr_running && + if ((sgs.sum_nr_running < sds->min_nr_running) || + (sgs.sum_nr_running == sds->min_nr_running && group_first_cpu(group) > - group_first_cpu(sds.group_min))) { - sds.group_min = group; - sds.min_nr_running = sgs.sum_nr_running; - sds.min_load_per_task = sgs.sum_weighted_load / + group_first_cpu(sds->group_min))) { + sds->group_min = group; + sds->min_nr_running = sgs.sum_nr_running; + sds->min_load_per_task = sgs.sum_weighted_load / sgs.sum_nr_running; } @@ -3470,18 +3471,46 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, if (sgs.sum_nr_running > sgs.group_capacity - 1) goto group_next; - if (sgs.sum_nr_running > sds.leader_nr_running || - (sgs.sum_nr_running == sds.leader_nr_running && + if (sgs.sum_nr_running > sds->leader_nr_running || + (sgs.sum_nr_running == sds->leader_nr_running && group_first_cpu(group) < - group_first_cpu(sds.group_leader))) { - sds.group_leader = group; - sds.leader_nr_running = sgs.sum_nr_running; + group_first_cpu(sds->group_leader))) { + sds->group_leader = group; + sds->leader_nr_running = sgs.sum_nr_running; } group_next: #endif group = group->next; } while (group != sd->groups); +} +/******* find_busiest_group() helpers end here *********************/ + +/* + * find_busiest_group finds and returns the busiest CPU group within the + * domain. It calculates and returns the amount of weighted load which + * should be moved to restore balance via the imbalance parameter. + */ +static struct sched_group * +find_busiest_group(struct sched_domain *sd, int this_cpu, + unsigned long *imbalance, enum cpu_idle_type idle, + int *sd_idle, const struct cpumask *cpus, int *balance) +{ + struct sd_lb_stats sds; + unsigned long max_pull; + + memset(&sds, 0, sizeof(sds)); + + /* + * Compute the various statistics relavent for load balancing at + * this level. + */ + update_sd_lb_stats(sd, this_cpu, idle, sd_idle, cpus, + balance, &sds); + + if (balance && !(*balance)) + goto ret; + if (!sds.busiest || sds.this_load >= sds.max_load || sds.busiest_nr_running == 0) goto out_balanced; -- GitLab From 2e6f44aeda426054fc58464df1ad571aecca0c92 Mon Sep 17 00:00:00 2001 From: Gautham R Shenoy Date: Wed, 25 Mar 2009 14:44:06 +0530 Subject: [PATCH 4527/4982] sched: Create helper to calculate small_imbalance in fbg() Impact: cleanup We have two places in find_busiest_group() where we need to calculate the minor imbalance before returning the busiest group. Encapsulate this functionality into a seperate helper function. Credit: Vaidyanathan Srinivasan Signed-off-by: Gautham R Shenoy Acked-by: Peter Zijlstra Cc: Suresh Siddha Cc: "Balbir Singh" Cc: Nick Piggin Cc: "Dhaval Giani" Cc: Bharata B Rao LKML-Reference: <20090325091406.13992.54316.stgit@sofia.in.ibm.com> Signed-off-by: Ingo Molnar --- kernel/sched.c | 131 ++++++++++++++++++++++++++----------------------- 1 file changed, 70 insertions(+), 61 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index ec715f97202..540147e5e82 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3484,6 +3484,71 @@ group_next: } while (group != sd->groups); } + +/** + * fix_small_imbalance - Calculate the minor imbalance that exists + * amongst the groups of a sched_domain, during + * load balancing. + * @sds: Statistics of the sched_domain whose imbalance is to be calculated. + * @this_cpu: The cpu at whose sched_domain we're performing load-balance. + * @imbalance: Variable to store the imbalance. + */ +static inline void fix_small_imbalance(struct sd_lb_stats *sds, + int this_cpu, unsigned long *imbalance) +{ + unsigned long tmp, pwr_now = 0, pwr_move = 0; + unsigned int imbn = 2; + + if (sds->this_nr_running) { + sds->this_load_per_task /= sds->this_nr_running; + if (sds->busiest_load_per_task > + sds->this_load_per_task) + imbn = 1; + } else + sds->this_load_per_task = + cpu_avg_load_per_task(this_cpu); + + if (sds->max_load - sds->this_load + sds->busiest_load_per_task >= + sds->busiest_load_per_task * imbn) { + *imbalance = sds->busiest_load_per_task; + return; + } + + /* + * OK, we don't have enough imbalance to justify moving tasks, + * however we may be able to increase total CPU power used by + * moving them. + */ + + pwr_now += sds->busiest->__cpu_power * + min(sds->busiest_load_per_task, sds->max_load); + pwr_now += sds->this->__cpu_power * + min(sds->this_load_per_task, sds->this_load); + pwr_now /= SCHED_LOAD_SCALE; + + /* Amount of load we'd subtract */ + tmp = sg_div_cpu_power(sds->busiest, + sds->busiest_load_per_task * SCHED_LOAD_SCALE); + if (sds->max_load > tmp) + pwr_move += sds->busiest->__cpu_power * + min(sds->busiest_load_per_task, sds->max_load - tmp); + + /* Amount of load we'd add */ + if (sds->max_load * sds->busiest->__cpu_power < + sds->busiest_load_per_task * SCHED_LOAD_SCALE) + tmp = sg_div_cpu_power(sds->this, + sds->max_load * sds->busiest->__cpu_power); + else + tmp = sg_div_cpu_power(sds->this, + sds->busiest_load_per_task * SCHED_LOAD_SCALE); + pwr_move += sds->this->__cpu_power * + min(sds->this_load_per_task, sds->this_load + tmp); + pwr_move /= SCHED_LOAD_SCALE; + + /* Move if we gain throughput */ + if (pwr_move > pwr_now) + *imbalance = sds->busiest_load_per_task; +} /******* find_busiest_group() helpers end here *********************/ /* @@ -3547,7 +3612,8 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, */ if (sds.max_load < sds.avg_load) { *imbalance = 0; - goto small_imbalance; + fix_small_imbalance(&sds, this_cpu, imbalance); + goto ret_busiest; } /* Don't want to pull so many tasks that a group would go idle */ @@ -3565,67 +3631,10 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, * a think about bumping its value to force at least one task to be * moved */ - if (*imbalance < sds.busiest_load_per_task) { - unsigned long tmp, pwr_now, pwr_move; - unsigned int imbn; - -small_imbalance: - pwr_move = pwr_now = 0; - imbn = 2; - if (sds.this_nr_running) { - sds.this_load_per_task /= sds.this_nr_running; - if (sds.busiest_load_per_task > - sds.this_load_per_task) - imbn = 1; - } else - sds.this_load_per_task = - cpu_avg_load_per_task(this_cpu); - - if (sds.max_load - sds.this_load + - sds.busiest_load_per_task >= - sds.busiest_load_per_task * imbn) { - *imbalance = sds.busiest_load_per_task; - return sds.busiest; - } - - /* - * OK, we don't have enough imbalance to justify moving tasks, - * however we may be able to increase total CPU power used by - * moving them. - */ - - pwr_now += sds.busiest->__cpu_power * - min(sds.busiest_load_per_task, sds.max_load); - pwr_now += sds.this->__cpu_power * - min(sds.this_load_per_task, sds.this_load); - pwr_now /= SCHED_LOAD_SCALE; - - /* Amount of load we'd subtract */ - tmp = sg_div_cpu_power(sds.busiest, - sds.busiest_load_per_task * SCHED_LOAD_SCALE); - if (sds.max_load > tmp) - pwr_move += sds.busiest->__cpu_power * - min(sds.busiest_load_per_task, - sds.max_load - tmp); - - /* Amount of load we'd add */ - if (sds.max_load * sds.busiest->__cpu_power < - sds.busiest_load_per_task * SCHED_LOAD_SCALE) - tmp = sg_div_cpu_power(sds.this, - sds.max_load * sds.busiest->__cpu_power); - else - tmp = sg_div_cpu_power(sds.this, - sds.busiest_load_per_task * SCHED_LOAD_SCALE); - pwr_move += sds.this->__cpu_power * - min(sds.this_load_per_task, - sds.this_load + tmp); - pwr_move /= SCHED_LOAD_SCALE; - - /* Move if we gain throughput */ - if (pwr_move > pwr_now) - *imbalance = sds.busiest_load_per_task; - } + if (*imbalance < sds.busiest_load_per_task) + fix_small_imbalance(&sds, this_cpu, imbalance); +ret_busiest: return sds.busiest; out_balanced: -- GitLab From dbc523a3b86f9e1765b5e70e6886913b99cc5cec Mon Sep 17 00:00:00 2001 From: Gautham R Shenoy Date: Wed, 25 Mar 2009 14:44:12 +0530 Subject: [PATCH 4528/4982] sched: Create a helper function to calculate imbalance Move all the imbalance calculation out of find_busiest_group() through this helper function. With this change, the structure of find_busiest_group() will be as follows: - update_sched_domain_statistics. - check if imbalance exits. - update imbalance and return busiest. Signed-off-by: Gautham R Shenoy Acked-by: Peter Zijlstra Cc: Suresh Siddha Cc: "Balbir Singh" Cc: Nick Piggin Cc: "Dhaval Giani" Cc: Bharata B Rao Cc: "Vaidyanathan Srinivasan" LKML-Reference: <20090325091411.13992.43293.stgit@sofia.in.ibm.com> Signed-off-by: Ingo Molnar --- kernel/sched.c | 78 +++++++++++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 33 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 540147e5e82..934f615ccce 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3487,8 +3487,8 @@ group_next: /** * fix_small_imbalance - Calculate the minor imbalance that exists - * amongst the groups of a sched_domain, during - * load balancing. + * amongst the groups of a sched_domain, during + * load balancing. * @sds: Statistics of the sched_domain whose imbalance is to be calculated. * @this_cpu: The cpu at whose sched_domain we're performing load-balance. * @imbalance: Variable to store the imbalance. @@ -3549,6 +3549,47 @@ static inline void fix_small_imbalance(struct sd_lb_stats *sds, if (pwr_move > pwr_now) *imbalance = sds->busiest_load_per_task; } + +/** + * calculate_imbalance - Calculate the amount of imbalance present within the + * groups of a given sched_domain during load balance. + * @sds: statistics of the sched_domain whose imbalance is to be calculated. + * @this_cpu: Cpu for which currently load balance is being performed. + * @imbalance: The variable to store the imbalance. + */ +static inline void calculate_imbalance(struct sd_lb_stats *sds, int this_cpu, + unsigned long *imbalance) +{ + unsigned long max_pull; + /* + * In the presence of smp nice balancing, certain scenarios can have + * max load less than avg load(as we skip the groups at or below + * its cpu_power, while calculating max_load..) + */ + if (sds->max_load < sds->avg_load) { + *imbalance = 0; + return fix_small_imbalance(sds, this_cpu, imbalance); + } + + /* Don't want to pull so many tasks that a group would go idle */ + max_pull = min(sds->max_load - sds->avg_load, + sds->max_load - sds->busiest_load_per_task); + + /* How much load to actually move to equalise the imbalance */ + *imbalance = min(max_pull * sds->busiest->__cpu_power, + (sds->avg_load - sds->this_load) * sds->this->__cpu_power) + / SCHED_LOAD_SCALE; + + /* + * if *imbalance is less than the average load per runnable task + * there is no gaurantee that any tasks will be moved so we'll have + * a think about bumping its value to force at least one task to be + * moved + */ + if (*imbalance < sds->busiest_load_per_task) + return fix_small_imbalance(sds, this_cpu, imbalance); + +} /******* find_busiest_group() helpers end here *********************/ /* @@ -3562,7 +3603,6 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, int *sd_idle, const struct cpumask *cpus, int *balance) { struct sd_lb_stats sds; - unsigned long max_pull; memset(&sds, 0, sizeof(sds)); @@ -3605,36 +3645,8 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, if (sds.max_load <= sds.busiest_load_per_task) goto out_balanced; - /* - * In the presence of smp nice balancing, certain scenarios can have - * max load less than avg load(as we skip the groups at or below - * its cpu_power, while calculating max_load..) - */ - if (sds.max_load < sds.avg_load) { - *imbalance = 0; - fix_small_imbalance(&sds, this_cpu, imbalance); - goto ret_busiest; - } - - /* Don't want to pull so many tasks that a group would go idle */ - max_pull = min(sds.max_load - sds.avg_load, - sds.max_load - sds.busiest_load_per_task); - - /* How much load to actually move to equalise the imbalance */ - *imbalance = min(max_pull * sds.busiest->__cpu_power, - (sds.avg_load - sds.this_load) * sds.this->__cpu_power) - / SCHED_LOAD_SCALE; - - /* - * if *imbalance is less than the average load per runnable task - * there is no gaurantee that any tasks will be moved so we'll have - * a think about bumping its value to force at least one task to be - * moved - */ - if (*imbalance < sds.busiest_load_per_task) - fix_small_imbalance(&sds, this_cpu, imbalance); - -ret_busiest: + /* Looks like there is an imbalance. Compute it */ + calculate_imbalance(&sds, this_cpu, imbalance); return sds.busiest; out_balanced: -- GitLab From a021dc03376707c55a3483e32c16b8986d4414cc Mon Sep 17 00:00:00 2001 From: Gautham R Shenoy Date: Wed, 25 Mar 2009 14:44:17 +0530 Subject: [PATCH 4529/4982] sched: Optimize the !power_savings_balance during fbg() Impact: cleanup, micro-optimization We don't need to perform power_savings balance if either the cpu is NOT_IDLE or if the sched_domain doesn't contain the SD_POWERSAVINGS_BALANCE flag set. Currently, we check for these conditions multiple number of times, even though these variables don't change over the scope of find_busiest_group(). Check once, and store the value in the already exiting "power_savings_balance" variable. Signed-off-by: Gautham R Shenoy Acked-by: Peter Zijlstra Cc: Suresh Siddha Cc: "Balbir Singh" Cc: Nick Piggin Cc: "Dhaval Giani" Cc: Bharata B Rao Cc: "Vaidyanathan Srinivasan" LKML-Reference: <20090325091417.13992.2657.stgit@sofia.in.ibm.com> Signed-off-by: Ingo Molnar --- kernel/sched.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 934f615ccce..71e8dcaf2c7 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3386,8 +3386,17 @@ static inline void update_sd_lb_stats(struct sched_domain *sd, int this_cpu, int load_idx; #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) - sds->power_savings_balance = 1; - sds->min_nr_running = ULONG_MAX; + /* + * Busy processors will not participate in power savings + * balance. + */ + if (idle == CPU_NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE)) + sds->power_savings_balance = 0; + else { + sds->power_savings_balance = 1; + sds->min_nr_running = ULONG_MAX; + sds->leader_nr_running = 0; + } #endif load_idx = get_sd_load_idx(sd, idle); @@ -3422,12 +3431,8 @@ static inline void update_sd_lb_stats(struct sched_domain *sd, int this_cpu, } #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) - /* - * Busy processors will not participate in power savings - * balance. - */ - if (idle == CPU_NOT_IDLE || - !(sd->flags & SD_POWERSAVINGS_BALANCE)) + + if (!sds->power_savings_balance) goto group_next; /* @@ -3651,7 +3656,7 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, out_balanced: #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) - if (idle == CPU_NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE)) + if (!sds.power_savings_balance) goto ret; if (sds.this != sds.group_leader || sds.group_leader == sds.group_min) -- GitLab From c071df18525a95b37dd5821a6dc4af83bd18675e Mon Sep 17 00:00:00 2001 From: Gautham R Shenoy Date: Wed, 25 Mar 2009 14:44:22 +0530 Subject: [PATCH 4530/4982] sched: Refactor the power savings balance code Impact: cleanup Create seperate helper functions to initialize the power-savings-balance related variables, to update them and to check if we have a scope for performing power-savings balance. Add no-op inline functions for the !(CONFIG_SCHED_MC || CONFIG_SCHED_SMT) case. This will eliminate all the #ifdef jungle in find_busiest_group() and the other helper functions. Signed-off-by: Gautham R Shenoy Acked-by: Peter Zijlstra Cc: Suresh Siddha Cc: "Balbir Singh" Cc: Nick Piggin Cc: "Dhaval Giani" Cc: Bharata B Rao Cc: "Vaidyanathan Srinivasan" LKML-Reference: <20090325091422.13992.73616.stgit@sofia.in.ibm.com> Signed-off-by: Ingo Molnar --- kernel/sched.c | 236 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 153 insertions(+), 83 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 71e8dcaf2c7..5f21658b0f6 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3270,6 +3270,151 @@ static inline int get_sd_load_idx(struct sched_domain *sd, } +#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) +/** + * init_sd_power_savings_stats - Initialize power savings statistics for + * the given sched_domain, during load balancing. + * + * @sd: Sched domain whose power-savings statistics are to be initialized. + * @sds: Variable containing the statistics for sd. + * @idle: Idle status of the CPU at which we're performing load-balancing. + */ +static inline void init_sd_power_savings_stats(struct sched_domain *sd, + struct sd_lb_stats *sds, enum cpu_idle_type idle) +{ + /* + * Busy processors will not participate in power savings + * balance. + */ + if (idle == CPU_NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE)) + sds->power_savings_balance = 0; + else { + sds->power_savings_balance = 1; + sds->min_nr_running = ULONG_MAX; + sds->leader_nr_running = 0; + } +} + +/** + * update_sd_power_savings_stats - Update the power saving stats for a + * sched_domain while performing load balancing. + * + * @group: sched_group belonging to the sched_domain under consideration. + * @sds: Variable containing the statistics of the sched_domain + * @local_group: Does group contain the CPU for which we're performing + * load balancing ? + * @sgs: Variable containing the statistics of the group. + */ +static inline void update_sd_power_savings_stats(struct sched_group *group, + struct sd_lb_stats *sds, int local_group, struct sg_lb_stats *sgs) +{ + + if (!sds->power_savings_balance) + return; + + /* + * If the local group is idle or completely loaded + * no need to do power savings balance at this domain + */ + if (local_group && (sds->this_nr_running >= sgs->group_capacity || + !sds->this_nr_running)) + sds->power_savings_balance = 0; + + /* + * If a group is already running at full capacity or idle, + * don't include that group in power savings calculations + */ + if (!sds->power_savings_balance || + sgs->sum_nr_running >= sgs->group_capacity || + !sgs->sum_nr_running) + return; + + /* + * Calculate the group which has the least non-idle load. + * This is the group from where we need to pick up the load + * for saving power + */ + if ((sgs->sum_nr_running < sds->min_nr_running) || + (sgs->sum_nr_running == sds->min_nr_running && + group_first_cpu(group) > group_first_cpu(sds->group_min))) { + sds->group_min = group; + sds->min_nr_running = sgs->sum_nr_running; + sds->min_load_per_task = sgs->sum_weighted_load / + sgs->sum_nr_running; + } + + /* + * Calculate the group which is almost near its + * capacity but still has some space to pick up some load + * from other group and save more power + */ + if (sgs->sum_nr_running > sgs->group_capacity - 1) + return; + + if (sgs->sum_nr_running > sds->leader_nr_running || + (sgs->sum_nr_running == sds->leader_nr_running && + group_first_cpu(group) < group_first_cpu(sds->group_leader))) { + sds->group_leader = group; + sds->leader_nr_running = sgs->sum_nr_running; + } +} + +/** + * check_power_save_busiest_group - Check if we have potential to perform + * some power-savings balance. If yes, set the busiest group to be + * the least loaded group in the sched_domain, so that it's CPUs can + * be put to idle. + * + * @sds: Variable containing the statistics of the sched_domain + * under consideration. + * @this_cpu: Cpu at which we're currently performing load-balancing. + * @imbalance: Variable to store the imbalance. + * + * Returns 1 if there is potential to perform power-savings balance. + * Else returns 0. + */ +static inline int check_power_save_busiest_group(struct sd_lb_stats *sds, + int this_cpu, unsigned long *imbalance) +{ + if (!sds->power_savings_balance) + return 0; + + if (sds->this != sds->group_leader || + sds->group_leader == sds->group_min) + return 0; + + *imbalance = sds->min_load_per_task; + sds->busiest = sds->group_min; + + if (sched_mc_power_savings >= POWERSAVINGS_BALANCE_WAKEUP) { + cpu_rq(this_cpu)->rd->sched_mc_preferred_wakeup_cpu = + group_first_cpu(sds->group_leader); + } + + return 1; + +} +#else /* CONFIG_SCHED_MC || CONFIG_SCHED_SMT */ +static inline void init_sd_power_savings_stats(struct sched_domain *sd, + struct sd_lb_stats *sds, enum cpu_idle_type idle) +{ + return; +} + +static inline void update_sd_power_savings_stats(struct sched_group *group, + struct sd_lb_stats *sds, int local_group, struct sg_lb_stats *sgs) +{ + return; +} + +static inline int check_power_save_busiest_group(struct sd_lb_stats *sds, + int this_cpu, unsigned long *imbalance) +{ + return 0; +} +#endif /* CONFIG_SCHED_MC || CONFIG_SCHED_SMT */ + + /** * update_sg_lb_stats - Update sched_group's statistics for load balancing. * @group: sched_group whose statistics are to be updated. @@ -3385,19 +3530,7 @@ static inline void update_sd_lb_stats(struct sched_domain *sd, int this_cpu, struct sg_lb_stats sgs; int load_idx; -#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) - /* - * Busy processors will not participate in power savings - * balance. - */ - if (idle == CPU_NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE)) - sds->power_savings_balance = 0; - else { - sds->power_savings_balance = 1; - sds->min_nr_running = ULONG_MAX; - sds->leader_nr_running = 0; - } -#endif + init_sd_power_savings_stats(sd, sds, idle); load_idx = get_sd_load_idx(sd, idle); do { @@ -3430,61 +3563,7 @@ static inline void update_sd_lb_stats(struct sched_domain *sd, int this_cpu, sds->group_imb = sgs.group_imb; } -#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) - - if (!sds->power_savings_balance) - goto group_next; - - /* - * If the local group is idle or completely loaded - * no need to do power savings balance at this domain - */ - if (local_group && - (sds->this_nr_running >= sgs.group_capacity || - !sds->this_nr_running)) - sds->power_savings_balance = 0; - - /* - * If a group is already running at full capacity or idle, - * don't include that group in power savings calculations - */ - if (!sds->power_savings_balance || - sgs.sum_nr_running >= sgs.group_capacity || - !sgs.sum_nr_running) - goto group_next; - - /* - * Calculate the group which has the least non-idle load. - * This is the group from where we need to pick up the load - * for saving power - */ - if ((sgs.sum_nr_running < sds->min_nr_running) || - (sgs.sum_nr_running == sds->min_nr_running && - group_first_cpu(group) > - group_first_cpu(sds->group_min))) { - sds->group_min = group; - sds->min_nr_running = sgs.sum_nr_running; - sds->min_load_per_task = sgs.sum_weighted_load / - sgs.sum_nr_running; - } - - /* - * Calculate the group which is almost near its - * capacity but still has some space to pick up some load - * from other group and save more power - */ - if (sgs.sum_nr_running > sgs.group_capacity - 1) - goto group_next; - - if (sgs.sum_nr_running > sds->leader_nr_running || - (sgs.sum_nr_running == sds->leader_nr_running && - group_first_cpu(group) < - group_first_cpu(sds->group_leader))) { - sds->group_leader = group; - sds->leader_nr_running = sgs.sum_nr_running; - } -group_next: -#endif + update_sd_power_savings_stats(group, sds, local_group, &sgs); group = group->next; } while (group != sd->groups); @@ -3655,21 +3734,12 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, return sds.busiest; out_balanced: -#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) - if (!sds.power_savings_balance) - goto ret; - - if (sds.this != sds.group_leader || sds.group_leader == sds.group_min) - goto ret; - - *imbalance = sds.min_load_per_task; - if (sched_mc_power_savings >= POWERSAVINGS_BALANCE_WAKEUP) { - cpu_rq(this_cpu)->rd->sched_mc_preferred_wakeup_cpu = - group_first_cpu(sds.group_leader); - } - return sds.group_min; - -#endif + /* + * There is no obvious imbalance. But check if we can do some balancing + * to save power. + */ + if (check_power_save_busiest_group(&sds, this_cpu, imbalance)) + return sds.busiest; ret: *imbalance = 0; return NULL; -- GitLab From 224be092d116b663ac426c4615e34ee54bab4a14 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 25 Mar 2009 10:14:25 +0100 Subject: [PATCH 4531/4982] [ARM] 5429/1: collie: start scoop converton to new api Start converting scoop gpio access to new API instead of old deprecated one. Signed-off-by: Dmitry Eremin-Solenikov Signed-off-by: Russell King --- arch/arm/mach-sa1100/collie.c | 27 ++++++++++++++++++---- arch/arm/mach-sa1100/include/mach/collie.h | 7 +++--- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index 2052eb88c96..a911f44aa9f 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -195,18 +196,34 @@ static struct mtd_partition collie_partitions[] = { } }; +static int collie_flash_init(void) +{ + int rc; + rc = gpio_request(COLLIE_GPIO_VPEN, "flash Vpp enable"); + if (rc) + return rc; + + rc = gpio_direction_output(COLLIE_GPIO_VPEN, 1); + if (rc) + gpio_free(COLLIE_GPIO_VPEN); + + return rc; +} + static void collie_set_vpp(int vpp) { - write_scoop_reg(&colliescoop_device.dev, SCOOP_GPCR, read_scoop_reg(&colliescoop_device.dev, SCOOP_GPCR) | COLLIE_SCP_VPEN); - if (vpp) - write_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR, read_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR) | COLLIE_SCP_VPEN); - else - write_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR, read_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR) & ~COLLIE_SCP_VPEN); + gpio_set_value(COLLIE_GPIO_VPEN, vpp); } +static void collie_flash_exit(void) +{ + gpio_free(COLLIE_GPIO_VPEN); +} static struct flash_platform_data collie_flash_data = { .map_name = "cfi_probe", + .init = collie_flash_init, .set_vpp = collie_set_vpp, + .exit = collie_flash_exit, .parts = collie_partitions, .nr_parts = ARRAY_SIZE(collie_partitions), }; diff --git a/arch/arm/mach-sa1100/include/mach/collie.h b/arch/arm/mach-sa1100/include/mach/collie.h index 69e962416e3..9bc53497d35 100644 --- a/arch/arm/mach-sa1100/include/mach/collie.h +++ b/arch/arm/mach-sa1100/include/mach/collie.h @@ -14,6 +14,7 @@ #define __ASM_ARCH_COLLIE_H +#define COLLIE_SCOOP_GPIO_BASE (GPIO_MAX + 1) #define COLLIE_SCP_CHARGE_ON SCOOP_GPCR_PA11 #define COLLIE_SCP_DIAG_BOOT1 SCOOP_GPCR_PA12 #define COLLIE_SCP_DIAG_BOOT2 SCOOP_GPCR_PA13 @@ -21,13 +22,13 @@ #define COLLIE_SCP_MUTE_R SCOOP_GPCR_PA15 #define COLLIE_SCP_5VON SCOOP_GPCR_PA16 #define COLLIE_SCP_AMP_ON SCOOP_GPCR_PA17 -#define COLLIE_SCP_VPEN SCOOP_GPCR_PA18 +#define COLLIE_GPIO_VPEN (COLLIE_SCOOP_GPIO_BASE + 7) #define COLLIE_SCP_LB_VOL_CHG SCOOP_GPCR_PA19 #define COLLIE_SCOOP_IO_DIR ( COLLIE_SCP_CHARGE_ON | COLLIE_SCP_MUTE_L | COLLIE_SCP_MUTE_R | \ - COLLIE_SCP_5VON | COLLIE_SCP_AMP_ON | COLLIE_SCP_VPEN | \ + COLLIE_SCP_5VON | COLLIE_SCP_AMP_ON | \ COLLIE_SCP_LB_VOL_CHG ) -#define COLLIE_SCOOP_IO_OUT ( COLLIE_SCP_MUTE_L | COLLIE_SCP_MUTE_R | COLLIE_SCP_VPEN | \ +#define COLLIE_SCOOP_IO_OUT ( COLLIE_SCP_MUTE_L | COLLIE_SCP_MUTE_R | \ COLLIE_SCP_CHARGE_ON ) /* GPIOs for which the generic definition doesn't say much */ -- GitLab From 8cb52f788c73cfcbff4aca66063c55baa3e6d313 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 25 Mar 2009 10:15:28 +0100 Subject: [PATCH 4532/4982] [ARM] 5430/1: collie_pm: use new GPIO API to control charger Signed-off-by: Dmitry Eremin-Solenikov Signed-off-by: Russell King --- arch/arm/mach-sa1100/collie_pm.c | 12 +++++------- arch/arm/mach-sa1100/include/mach/collie.h | 7 +++---- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-sa1100/collie_pm.c b/arch/arm/mach-sa1100/collie_pm.c index b39307f26b5..444f266ecc0 100644 --- a/arch/arm/mach-sa1100/collie_pm.c +++ b/arch/arm/mach-sa1100/collie_pm.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -58,6 +59,9 @@ static void collie_charger_init(void) return; } + gpio_request(COLLIE_GPIO_CHARGE_ON, "charge on"); + gpio_direction_output(COLLIE_GPIO_CHARGE_ON, 1); + ucb1x00_io_set_dir(ucb, 0, COLLIE_TC35143_GPIO_MBAT_ON | COLLIE_TC35143_GPIO_TMP_ON | COLLIE_TC35143_GPIO_BBAT_ON); return; @@ -73,17 +77,11 @@ static void collie_measure_temp(int on) static void collie_charge(int on) { - extern struct platform_device colliescoop_device; - /* Zaurus seems to contain LTC1731; it should know when to * stop charging itself, so setting charge on should be * relatively harmless (as long as it is not done too often). */ - if (on) { - set_scoop_gpio(&colliescoop_device.dev, COLLIE_SCP_CHARGE_ON); - } else { - reset_scoop_gpio(&colliescoop_device.dev, COLLIE_SCP_CHARGE_ON); - } + gpio_set_value(COLLIE_GPIO_CHARGE_ON, on); } static void collie_discharge(int on) diff --git a/arch/arm/mach-sa1100/include/mach/collie.h b/arch/arm/mach-sa1100/include/mach/collie.h index 9bc53497d35..9efb569cdb6 100644 --- a/arch/arm/mach-sa1100/include/mach/collie.h +++ b/arch/arm/mach-sa1100/include/mach/collie.h @@ -15,7 +15,7 @@ #define COLLIE_SCOOP_GPIO_BASE (GPIO_MAX + 1) -#define COLLIE_SCP_CHARGE_ON SCOOP_GPCR_PA11 +#define COLLIE_GPIO_CHARGE_ON (COLLIE_SCOOP_GPIO_BASE + 0) #define COLLIE_SCP_DIAG_BOOT1 SCOOP_GPCR_PA12 #define COLLIE_SCP_DIAG_BOOT2 SCOOP_GPCR_PA13 #define COLLIE_SCP_MUTE_L SCOOP_GPCR_PA14 @@ -25,11 +25,10 @@ #define COLLIE_GPIO_VPEN (COLLIE_SCOOP_GPIO_BASE + 7) #define COLLIE_SCP_LB_VOL_CHG SCOOP_GPCR_PA19 -#define COLLIE_SCOOP_IO_DIR ( COLLIE_SCP_CHARGE_ON | COLLIE_SCP_MUTE_L | COLLIE_SCP_MUTE_R | \ +#define COLLIE_SCOOP_IO_DIR ( COLLIE_SCP_MUTE_L | COLLIE_SCP_MUTE_R | \ COLLIE_SCP_5VON | COLLIE_SCP_AMP_ON | \ COLLIE_SCP_LB_VOL_CHG ) -#define COLLIE_SCOOP_IO_OUT ( COLLIE_SCP_MUTE_L | COLLIE_SCP_MUTE_R | \ - COLLIE_SCP_CHARGE_ON ) +#define COLLIE_SCOOP_IO_OUT ( COLLIE_SCP_MUTE_L | COLLIE_SCP_MUTE_R ) /* GPIOs for which the generic definition doesn't say much */ -- GitLab From 17a92a788e3cebca8a817f01e3c0f121f700ee0e Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 25 Mar 2009 10:16:37 +0100 Subject: [PATCH 4533/4982] [ARM] 5431/1: scoop: completely drop old-style SCOOP GPIO accessors Now, as all places that use Scoop GPIO have been converted to use GPIO API, drop old-style accessors completely. Signed-off-by: Dmitry Eremin-Solenikov Signed-off-by: Russell King --- arch/arm/common/scoop.c | 31 --------------------------- arch/arm/include/asm/hardware/scoop.h | 2 -- 2 files changed, 33 deletions(-) diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c index 697c6491399..7713a08bb10 100644 --- a/arch/arm/common/scoop.c +++ b/arch/arm/common/scoop.c @@ -124,37 +124,6 @@ static int scoop_gpio_direction_output(struct gpio_chip *chip, return 0; } -unsigned short set_scoop_gpio(struct device *dev, unsigned short bit) -{ - unsigned short gpio_bit; - unsigned long flag; - struct scoop_dev *sdev = dev_get_drvdata(dev); - - spin_lock_irqsave(&sdev->scoop_lock, flag); - gpio_bit = ioread16(sdev->base + SCOOP_GPWR) | bit; - iowrite16(gpio_bit, sdev->base + SCOOP_GPWR); - spin_unlock_irqrestore(&sdev->scoop_lock, flag); - - return gpio_bit; -} - -unsigned short reset_scoop_gpio(struct device *dev, unsigned short bit) -{ - unsigned short gpio_bit; - unsigned long flag; - struct scoop_dev *sdev = dev_get_drvdata(dev); - - spin_lock_irqsave(&sdev->scoop_lock, flag); - gpio_bit = ioread16(sdev->base + SCOOP_GPWR) & ~bit; - iowrite16(gpio_bit, sdev->base + SCOOP_GPWR); - spin_unlock_irqrestore(&sdev->scoop_lock, flag); - - return gpio_bit; -} - -EXPORT_SYMBOL(set_scoop_gpio); -EXPORT_SYMBOL(reset_scoop_gpio); - unsigned short read_scoop_reg(struct device *dev, unsigned short reg) { struct scoop_dev *sdev = dev_get_drvdata(dev); diff --git a/arch/arm/include/asm/hardware/scoop.h b/arch/arm/include/asm/hardware/scoop.h index dfb8330599f..46492a63a7c 100644 --- a/arch/arm/include/asm/hardware/scoop.h +++ b/arch/arm/include/asm/hardware/scoop.h @@ -63,7 +63,5 @@ struct scoop_pcmcia_config { extern struct scoop_pcmcia_config *platform_scoop_config; void reset_scoop(struct device *dev); -unsigned short __deprecated set_scoop_gpio(struct device *dev, unsigned short bit); -unsigned short __deprecated reset_scoop_gpio(struct device *dev, unsigned short bit); unsigned short read_scoop_reg(struct device *dev, unsigned short reg); void write_scoop_reg(struct device *dev, unsigned short reg, unsigned short data); -- GitLab From e63cedb656683739eea2696114bc56888e9bff05 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 25 Mar 2009 10:15:00 +0000 Subject: [PATCH 4534/4982] [ARM] collie: fix two minor formatting nits Signed-off-by: Russell King --- arch/arm/mach-sa1100/collie.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index a911f44aa9f..bbf2ebcc306 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c @@ -146,7 +146,8 @@ static struct locomo_driver collie_uart_driver = { .remove = collie_uart_remove, }; -static int __init collie_uart_init(void) { +static int __init collie_uart_init(void) +{ return locomo_driver_register(&collie_uart_driver); } device_initcall(collie_uart_init); @@ -198,8 +199,7 @@ static struct mtd_partition collie_partitions[] = { static int collie_flash_init(void) { - int rc; - rc = gpio_request(COLLIE_GPIO_VPEN, "flash Vpp enable"); + int rc = gpio_request(COLLIE_GPIO_VPEN, "flash Vpp enable"); if (rc) return rc; @@ -219,6 +219,7 @@ static void collie_flash_exit(void) { gpio_free(COLLIE_GPIO_VPEN); } + static struct flash_platform_data collie_flash_data = { .map_name = "cfi_probe", .init = collie_flash_init, -- GitLab From 997302259f386bca8fe1db67c50296ca426c438f Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 25 Mar 2009 10:21:35 +0000 Subject: [PATCH 4535/4982] [ARM] acorn,ebsa110,footbridge,integrator,sa1100: Convert asm/io.h to linux/io.h Signed-off-by: Russell King --- arch/arm/mach-omap2/board-ldp.c | 2 +- drivers/i2c/busses/i2c-acorn.c | 2 +- drivers/input/mouse/rpcmouse.c | 2 +- drivers/input/serio/rpckbd.c | 2 +- drivers/mtd/maps/integrator-flash.c | 2 +- drivers/mtd/maps/sa1100-flash.c | 2 +- drivers/net/arm/am79c961a.c | 2 +- drivers/pcmcia/sa1111_generic.c | 2 +- drivers/pcmcia/sa11xx_base.c | 2 +- drivers/serial/21285.c | 2 +- drivers/serial/clps711x.c | 2 +- drivers/serial/sa1100.c | 2 +- drivers/video/acornfb.c | 2 +- drivers/video/cyber2000fb.c | 2 +- drivers/video/sa1100fb.c | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index 73e3fdb2d20..c71580557c6 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -35,7 +36,6 @@ #include #include -#include #include #include diff --git a/drivers/i2c/busses/i2c-acorn.c b/drivers/i2c/busses/i2c-acorn.c index 9aefb5e5864..86796488ef4 100644 --- a/drivers/i2c/busses/i2c-acorn.c +++ b/drivers/i2c/busses/i2c-acorn.c @@ -15,9 +15,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/input/mouse/rpcmouse.c b/drivers/input/mouse/rpcmouse.c index 56c079ef501..272deddc8db 100644 --- a/drivers/input/mouse/rpcmouse.c +++ b/drivers/input/mouse/rpcmouse.c @@ -22,10 +22,10 @@ #include #include #include +#include #include #include -#include #include MODULE_AUTHOR("Vojtech Pavlik, Russell King"); diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c index 7f36edd34f8..ed045c99f84 100644 --- a/drivers/input/serio/rpckbd.c +++ b/drivers/input/serio/rpckbd.c @@ -33,10 +33,10 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c index d2ec262666c..c9681a339a5 100644 --- a/drivers/mtd/maps/integrator-flash.c +++ b/drivers/mtd/maps/integrator-flash.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -38,7 +39,6 @@ #include #include -#include #include #ifdef CONFIG_ARCH_P720T diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c index 6f6a0f6dafd..8f57b6f40aa 100644 --- a/drivers/mtd/maps/sa1100-flash.c +++ b/drivers/mtd/maps/sa1100-flash.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -19,7 +20,6 @@ #include #include -#include #include #include diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index c2d012fcc29..4bc6901b381 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -27,9 +27,9 @@ #include #include #include +#include #include -#include #include #define TX_BUFFERS 15 diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c index 6924d0ea8d3..401052a21ce 100644 --- a/drivers/pcmcia/sa1111_generic.c +++ b/drivers/pcmcia/sa1111_generic.c @@ -11,12 +11,12 @@ #include #include #include +#include #include #include #include -#include #include #include "sa1111_generic.h" diff --git a/drivers/pcmcia/sa11xx_base.c b/drivers/pcmcia/sa11xx_base.c index 810ac492a8c..e15d59f2d8a 100644 --- a/drivers/pcmcia/sa11xx_base.c +++ b/drivers/pcmcia/sa11xx_base.c @@ -36,9 +36,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index f31c6698419..cb6d85d7ff4 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c @@ -14,8 +14,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c index 459f3420a42..80e76426131 100644 --- a/drivers/serial/clps711x.c +++ b/drivers/serial/clps711x.c @@ -38,9 +38,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index b24a25ea6bc..94530f01521 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c @@ -36,8 +36,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index 61c3d3f40fd..6995fe1e86d 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c @@ -28,9 +28,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index 51b373657aa..83c5cefc266 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c @@ -46,8 +46,8 @@ #include #include #include +#include -#include #include #include diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index 022d07abbf9..fad58cf9ef7 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c @@ -176,9 +176,9 @@ #include #include #include +#include #include -#include #include #include #include -- GitLab From 28853ac8fe5221de74a14f1182d7b2b383dfd85c Mon Sep 17 00:00:00 2001 From: Paulius Zaleckas Date: Wed, 25 Mar 2009 13:10:01 +0200 Subject: [PATCH 4536/4982] ARM: Add support for FA526 v2 Adds support for Faraday FA526 core. This core is used at least by: Cortina Systems Gemini and Centroid family Cavium Networks ECONA family Grain Media GM8120 Pixelplus ImageARM Prolific PL-1029 Faraday IP evaluation boards v2: - move TLB_BTB to separate patch - update copyrights Signed-off-by: Paulius Zaleckas --- arch/arm/Makefile | 1 + arch/arm/boot/compressed/head.S | 26 ++++ arch/arm/include/asm/cacheflush.h | 8 + arch/arm/include/asm/page.h | 8 + arch/arm/include/asm/proc-fns.h | 8 + arch/arm/include/asm/system.h | 6 + arch/arm/include/asm/tlbflush.h | 19 +++ arch/arm/mm/Kconfig | 35 ++++- arch/arm/mm/Makefile | 4 + arch/arm/mm/cache-fa.S | 220 ++++++++++++++++++++++++++ arch/arm/mm/copypage-fa.c | 86 +++++++++++ arch/arm/mm/proc-fa526.S | 248 ++++++++++++++++++++++++++++++ arch/arm/mm/tlb-fa.S | 75 +++++++++ 13 files changed, 742 insertions(+), 2 deletions(-) create mode 100644 arch/arm/mm/cache-fa.S create mode 100644 arch/arm/mm/copypage-fa.c create mode 100644 arch/arm/mm/proc-fa526.S create mode 100644 arch/arm/mm/tlb-fa.S diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 24e0f018769..d29f9260fb1 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -72,6 +72,7 @@ tune-$(CONFIG_CPU_ARM920T) :=-mtune=arm9tdmi tune-$(CONFIG_CPU_ARM922T) :=-mtune=arm9tdmi tune-$(CONFIG_CPU_ARM925T) :=-mtune=arm9tdmi tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi +tune-$(CONFIG_CPU_FA526) :=-mtune=arm9tdmi tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110 tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100 tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 77d614232d8..def02483286 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -459,6 +459,20 @@ __armv7_mmu_cache_on: mcr p15, 0, r0, c7, c5, 4 @ ISB mov pc, r12 +__fa526_cache_on: + mov r12, lr + bl __setup_mmu + mov r0, #0 + mcr p15, 0, r0, c7, c7, 0 @ Invalidate whole cache + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer + mcr p15, 0, r0, c8, c7, 0 @ flush UTLB + mrc p15, 0, r0, c1, c0, 0 @ read control reg + orr r0, r0, #0x1000 @ I-cache enable + bl __common_mmu_cache_on + mov r0, #0 + mcr p15, 0, r0, c8, c7, 0 @ flush UTLB + mov pc, r12 + __arm6_mmu_cache_on: mov r12, lr bl __setup_mmu @@ -636,6 +650,12 @@ proc_types: b __armv4_mmu_cache_off b __armv5tej_mmu_cache_flush + .word 0x66015261 @ FA526 + .word 0xff01fff1 + b __fa526_cache_on + b __armv4_mmu_cache_off + b __fa526_cache_flush + @ These match on the architecture ID .word 0x00020000 @ ARMv4T @@ -775,6 +795,12 @@ __armv4_mpu_cache_flush: mcr p15, 0, ip, c7, c10, 4 @ drain WB mov pc, lr +__fa526_cache_flush: + mov r1, #0 + mcr p15, 0, r1, c7, c14, 0 @ clean and invalidate D cache + mcr p15, 0, r1, c7, c5, 0 @ flush I cache + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mov pc, lr __armv6_mmu_cache_flush: mov r1, #0 diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index 6cbd8fdc9f1..a6b8b90ed57 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -46,6 +46,14 @@ # define MULTI_CACHE 1 #endif +#if defined(CONFIG_CPU_FA526) +# ifdef _CACHE +# define MULTI_CACHE 1 +# else +# define _CACHE fa +# endif +#endif + #if defined(CONFIG_CPU_ARM926T) # ifdef _CACHE # define MULTI_CACHE 1 diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h index f341c9dbd66..e6eb8a67b80 100644 --- a/arch/arm/include/asm/page.h +++ b/arch/arm/include/asm/page.h @@ -76,6 +76,14 @@ # endif #endif +#ifdef CONFIG_CPU_COPY_FA +# ifdef _USER +# define MULTI_USER 1 +# else +# define _USER fa +# endif +#endif + #ifdef CONFIG_CPU_SA1100 # ifdef _USER # define MULTI_USER 1 diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h index db80203b68e..00949281d3e 100644 --- a/arch/arm/include/asm/proc-fns.h +++ b/arch/arm/include/asm/proc-fns.h @@ -89,6 +89,14 @@ # define CPU_NAME cpu_arm922 # endif # endif +# ifdef CONFIG_CPU_FA526 +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_fa526 +# endif +# endif # ifdef CONFIG_CPU_ARM925T # ifdef CPU_NAME # undef MULTI_CPU diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 811be55f338..d6a4dad99c9 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -125,6 +125,12 @@ extern unsigned int user_debug; : : "r" (0) : "memory") #define dmb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \ : : "r" (0) : "memory") +#elif defined(CONFIG_CPU_FA526) +#define isb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" \ + : : "r" (0) : "memory") +#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \ + : : "r" (0) : "memory") +#define dmb() __asm__ __volatile__ ("" : : : "memory") #else #define isb() __asm__ __volatile__ ("" : : : "memory") #define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \ diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h index ffedd2494ea..a62218013c7 100644 --- a/arch/arm/include/asm/tlbflush.h +++ b/arch/arm/include/asm/tlbflush.h @@ -54,6 +54,7 @@ * v4wb - ARMv4 with write buffer without I TLB flush entry instruction * v4wbi - ARMv4 with write buffer with I TLB flush entry instruction * fr - Feroceon (v4wbi with non-outer-cacheable page table walks) + * fa - Faraday (v4 with write buffer with UTLB and branch target buffer (BTB)) * v6wbi - ARMv6 with write buffer with I TLB flush entry instruction * v7wbi - identical to v6wbi */ @@ -90,6 +91,22 @@ # define v4_always_flags (-1UL) #endif +#define fa_tlb_flags (TLB_WB | TLB_BTB | TLB_DCLEAN | \ + TLB_V4_U_FULL | TLB_V4_U_PAGE) + +#ifdef CONFIG_CPU_TLB_FA +# define fa_possible_flags fa_tlb_flags +# define fa_always_flags fa_tlb_flags +# ifdef _TLB +# define MULTI_TLB 1 +# else +# define _TLB fa +# endif +#else +# define fa_possible_flags 0 +# define fa_always_flags (-1UL) +#endif + #define v4wbi_tlb_flags (TLB_WB | TLB_DCLEAN | \ TLB_V4_I_FULL | TLB_V4_D_FULL | \ TLB_V4_I_PAGE | TLB_V4_D_PAGE) @@ -268,6 +285,7 @@ extern struct cpu_tlb_fns cpu_tlb; v4wbi_possible_flags | \ fr_possible_flags | \ v4wb_possible_flags | \ + fa_possible_flags | \ v6wbi_possible_flags | \ v7wbi_possible_flags) @@ -276,6 +294,7 @@ extern struct cpu_tlb_fns cpu_tlb; v4wbi_always_flags & \ fr_always_flags & \ v4wb_always_flags & \ + fa_always_flags & \ v6wbi_always_flags & \ v7wbi_always_flags) diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index d490f3773c0..bc3331863d9 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -186,6 +186,24 @@ config CPU_ARM926T Say Y if you want support for the ARM926T processor. Otherwise, say N. +# FA526 +config CPU_FA526 + bool + select CPU_32v4 + select CPU_ABRT_EV4 + select CPU_PABRT_NOIFAR + select CPU_CACHE_VIVT + select CPU_CP15_MMU + select CPU_CACHE_FA + select CPU_COPY_FA if MMU + select CPU_TLB_FA if MMU + help + The FA526 is a version of the ARMv4 compatible processor with + Branch Target Buffer, Unified TLB and cache line size 16. + + Say Y if you want support for the FA526 processor. + Otherwise, say N. + # ARM940T config CPU_ARM940T bool "Support ARM940T processor" if ARCH_INTEGRATOR @@ -484,6 +502,9 @@ config CPU_CACHE_VIVT config CPU_CACHE_VIPT bool +config CPU_CACHE_FA + bool + if MMU # The copy-page model config CPU_COPY_V3 @@ -498,6 +519,9 @@ config CPU_COPY_V4WB config CPU_COPY_FEROCEON bool +config CPU_COPY_FA + bool + config CPU_COPY_V6 bool @@ -528,6 +552,13 @@ config CPU_TLB_FEROCEON help Feroceon TLB (v4wbi with non-outer-cachable page table walks). +config CPU_TLB_FA + bool + help + Faraday ARM FA526 architecture, unified TLB with writeback cache + and invalidate instruction cache entry. Branch target buffer is + also supported. + config CPU_TLB_V6 bool @@ -638,7 +669,7 @@ config CPU_DCACHE_SIZE config CPU_DCACHE_WRITETHROUGH bool "Force write through D-cache" - depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020) && !CPU_DCACHE_DISABLE + depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_FA526) && !CPU_DCACHE_DISABLE default y if CPU_ARM925T help Say Y here to use the data cache in writethrough mode. Unless you @@ -653,7 +684,7 @@ config CPU_CACHE_ROUND_ROBIN config CPU_BPREDICT_DISABLE bool "Disable branch prediction" - depends on CPU_ARM1020 || CPU_V6 || CPU_XSC3 || CPU_V7 + depends on CPU_ARM1020 || CPU_V6 || CPU_XSC3 || CPU_V7 || CPU_FA526 help Say Y here to disable branch prediction. If unsure, say N. diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index 480f78a3611..40f941c2245 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_CPU_CACHE_V4WT) += cache-v4wt.o obj-$(CONFIG_CPU_CACHE_V4WB) += cache-v4wb.o obj-$(CONFIG_CPU_CACHE_V6) += cache-v6.o obj-$(CONFIG_CPU_CACHE_V7) += cache-v7.o +obj-$(CONFIG_CPU_CACHE_FA) += cache-fa.o obj-$(CONFIG_CPU_COPY_V3) += copypage-v3.o obj-$(CONFIG_CPU_COPY_V4WT) += copypage-v4wt.o @@ -41,6 +42,7 @@ obj-$(CONFIG_CPU_COPY_V6) += copypage-v6.o context.o obj-$(CONFIG_CPU_SA1100) += copypage-v4mc.o obj-$(CONFIG_CPU_XSCALE) += copypage-xscale.o obj-$(CONFIG_CPU_XSC3) += copypage-xsc3.o +obj-$(CONFIG_CPU_COPY_FA) += copypage-fa.o obj-$(CONFIG_CPU_TLB_V3) += tlb-v3.o obj-$(CONFIG_CPU_TLB_V4WT) += tlb-v4.o @@ -49,6 +51,7 @@ obj-$(CONFIG_CPU_TLB_V4WBI) += tlb-v4wbi.o obj-$(CONFIG_CPU_TLB_FEROCEON) += tlb-v4wbi.o # reuse v4wbi TLB functions obj-$(CONFIG_CPU_TLB_V6) += tlb-v6.o obj-$(CONFIG_CPU_TLB_V7) += tlb-v7.o +obj-$(CONFIG_CPU_TLB_FA) += tlb-fa.o obj-$(CONFIG_CPU_ARM610) += proc-arm6_7.o obj-$(CONFIG_CPU_ARM710) += proc-arm6_7.o @@ -62,6 +65,7 @@ obj-$(CONFIG_CPU_ARM925T) += proc-arm925.o obj-$(CONFIG_CPU_ARM926T) += proc-arm926.o obj-$(CONFIG_CPU_ARM940T) += proc-arm940.o obj-$(CONFIG_CPU_ARM946E) += proc-arm946.o +obj-$(CONFIG_CPU_FA526) += proc-fa526.o obj-$(CONFIG_CPU_ARM1020) += proc-arm1020.o obj-$(CONFIG_CPU_ARM1020E) += proc-arm1020e.o obj-$(CONFIG_CPU_ARM1022) += proc-arm1022.o diff --git a/arch/arm/mm/cache-fa.S b/arch/arm/mm/cache-fa.S new file mode 100644 index 00000000000..b63a8f7b95c --- /dev/null +++ b/arch/arm/mm/cache-fa.S @@ -0,0 +1,220 @@ +/* + * linux/arch/arm/mm/cache-fa.S + * + * Copyright (C) 2005 Faraday Corp. + * Copyright (C) 2008-2009 Paulius Zaleckas + * + * Based on cache-v4wb.S: + * Copyright (C) 1997-2002 Russell king + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Processors: FA520 FA526 FA626 + */ +#include +#include +#include +#include + +#include "proc-macros.S" + +/* + * The size of one data cache line. + */ +#define CACHE_DLINESIZE 16 + +/* + * The total size of the data cache. + */ +#ifdef CONFIG_ARCH_GEMINI +#define CACHE_DSIZE 8192 +#else +#define CACHE_DSIZE 16384 +#endif + +/* FIXME: put optimal value here. Current one is just estimation */ +#define CACHE_DLIMIT (CACHE_DSIZE * 2) + +/* + * flush_user_cache_all() + * + * Clean and invalidate all cache entries in a particular address + * space. + */ +ENTRY(fa_flush_user_cache_all) + /* FALLTHROUGH */ +/* + * flush_kern_cache_all() + * + * Clean and invalidate the entire cache. + */ +ENTRY(fa_flush_kern_cache_all) + mov ip, #0 + mov r2, #VM_EXEC +__flush_whole_cache: + mcr p15, 0, ip, c7, c14, 0 @ clean/invalidate D cache + tst r2, #VM_EXEC + mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache + mcrne p15, 0, ip, c7, c5, 6 @ invalidate BTB + mcrne p15, 0, ip, c7, c10, 4 @ drain write buffer + mcrne p15, 0, ip, c7, c5, 4 @ prefetch flush + mov pc, lr + +/* + * flush_user_cache_range(start, end, flags) + * + * Invalidate a range of cache entries in the specified + * address space. + * + * - start - start address (inclusive, page aligned) + * - end - end address (exclusive, page aligned) + * - flags - vma_area_struct flags describing address space + */ +ENTRY(fa_flush_user_cache_range) + mov ip, #0 + sub r3, r1, r0 @ calculate total size + cmp r3, #CACHE_DLIMIT @ total size >= limit? + bhs __flush_whole_cache @ flush whole D cache + +1: tst r2, #VM_EXEC + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I line + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + tst r2, #VM_EXEC + mcrne p15, 0, ip, c7, c5, 6 @ invalidate BTB + mcrne p15, 0, ip, c7, c10, 4 @ data write barrier + mcrne p15, 0, ip, c7, c5, 4 @ prefetch flush + mov pc, lr + +/* + * coherent_kern_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(fa_coherent_kern_range) + /* fall through */ + +/* + * coherent_user_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(fa_coherent_user_range) + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry + mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mov r0, #0 + mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer + mcr p15, 0, r0, c7, c5, 4 @ prefetch flush + mov pc, lr + +/* + * flush_kern_dcache_page(kaddr) + * + * Ensure that the data held in the page kaddr is written back + * to the page in question. + * + * - kaddr - kernel address (guaranteed to be page aligned) + */ +ENTRY(fa_flush_kern_dcache_page) + add r1, r0, #PAGE_SZ +1: mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer + mov pc, lr + +/* + * dma_inv_range(start, end) + * + * Invalidate (discard) the specified virtual address range. + * May not write back any entries. If 'start' or 'end' + * are not cache line aligned, those lines must be written + * back. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(fa_dma_inv_range) + tst r0, #CACHE_DLINESIZE - 1 + bic r0, r0, #CACHE_DLINESIZE - 1 + mcrne p15, 0, r0, c7, c14, 1 @ clean & invalidate D entry + tst r1, #CACHE_DLINESIZE - 1 + bic r1, r1, #CACHE_DLINESIZE - 1 + mcrne p15, 0, r1, c7, c14, 1 @ clean & invalidate D entry +1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer + mov pc, lr + +/* + * dma_clean_range(start, end) + * + * Clean (write back) the specified virtual address range. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(fa_dma_clean_range) + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer + mov pc, lr + +/* + * dma_flush_range(start,end) + * - start - virtual start address of region + * - end - virtual end address of region + */ +ENTRY(fa_dma_flush_range) + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer + mov pc, lr + + __INITDATA + + .type fa_cache_fns, #object +ENTRY(fa_cache_fns) + .long fa_flush_kern_cache_all + .long fa_flush_user_cache_all + .long fa_flush_user_cache_range + .long fa_coherent_kern_range + .long fa_coherent_user_range + .long fa_flush_kern_dcache_page + .long fa_dma_inv_range + .long fa_dma_clean_range + .long fa_dma_flush_range + .size fa_cache_fns, . - fa_cache_fns diff --git a/arch/arm/mm/copypage-fa.c b/arch/arm/mm/copypage-fa.c new file mode 100644 index 00000000000..b2a6008b011 --- /dev/null +++ b/arch/arm/mm/copypage-fa.c @@ -0,0 +1,86 @@ +/* + * linux/arch/arm/lib/copypage-fa.S + * + * Copyright (C) 2005 Faraday Corp. + * Copyright (C) 2008-2009 Paulius Zaleckas + * + * Based on copypage-v4wb.S: + * Copyright (C) 1995-1999 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include + +/* + * Faraday optimised copy_user_page + */ +static void __naked +fa_copy_user_page(void *kto, const void *kfrom) +{ + asm("\ + stmfd sp!, {r4, lr} @ 2\n\ + mov r2, %0 @ 1\n\ +1: ldmia r1!, {r3, r4, ip, lr} @ 4\n\ + stmia r0, {r3, r4, ip, lr} @ 4\n\ + mcr p15, 0, r0, c7, c14, 1 @ 1 clean and invalidate D line\n\ + add r0, r0, #16 @ 1\n\ + ldmia r1!, {r3, r4, ip, lr} @ 4\n\ + stmia r0, {r3, r4, ip, lr} @ 4\n\ + mcr p15, 0, r0, c7, c14, 1 @ 1 clean and invalidate D line\n\ + add r0, r0, #16 @ 1\n\ + subs r2, r2, #1 @ 1\n\ + bne 1b @ 1\n\ + mcr p15, 0, r2, c7, c10, 4 @ 1 drain WB\n\ + ldmfd sp!, {r4, pc} @ 3" + : + : "I" (PAGE_SIZE / 32)); +} + +void fa_copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr) +{ + void *kto, *kfrom; + + kto = kmap_atomic(to, KM_USER0); + kfrom = kmap_atomic(from, KM_USER1); + fa_copy_user_page(kto, kfrom); + kunmap_atomic(kfrom, KM_USER1); + kunmap_atomic(kto, KM_USER0); +} + +/* + * Faraday optimised clear_user_page + * + * Same story as above. + */ +void fa_clear_user_highpage(struct page *page, unsigned long vaddr) +{ + void *ptr, *kaddr = kmap_atomic(page, KM_USER0); + asm volatile("\ + mov r1, %2 @ 1\n\ + mov r2, #0 @ 1\n\ + mov r3, #0 @ 1\n\ + mov ip, #0 @ 1\n\ + mov lr, #0 @ 1\n\ +1: stmia %0, {r2, r3, ip, lr} @ 4\n\ + mcr p15, 0, %0, c7, c14, 1 @ 1 clean and invalidate D line\n\ + add %0, %0, #16 @ 1\n\ + stmia %0, {r2, r3, ip, lr} @ 4\n\ + mcr p15, 0, %0, c7, c14, 1 @ 1 clean and invalidate D line\n\ + add %0, %0, #16 @ 1\n\ + subs r1, r1, #1 @ 1\n\ + bne 1b @ 1\n\ + mcr p15, 0, r1, c7, c10, 4 @ 1 drain WB" + : "=r" (ptr) + : "0" (kaddr), "I" (PAGE_SIZE / 32) + : "r1", "r2", "r3", "ip", "lr"); + kunmap_atomic(kaddr, KM_USER0); +} + +struct cpu_user_fns fa_user_fns __initdata = { + .cpu_clear_user_highpage = fa_clear_user_highpage, + .cpu_copy_user_highpage = fa_copy_user_highpage, +}; diff --git a/arch/arm/mm/proc-fa526.S b/arch/arm/mm/proc-fa526.S new file mode 100644 index 00000000000..08b8a955d5d --- /dev/null +++ b/arch/arm/mm/proc-fa526.S @@ -0,0 +1,248 @@ +/* + * linux/arch/arm/mm/proc-fa526.S: MMU functions for FA526 + * + * Written by : Luke Lee + * Copyright (C) 2005 Faraday Corp. + * Copyright (C) 2008-2009 Paulius Zaleckas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * + * These are the low level assembler for performing cache and TLB + * functions on the fa526. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "proc-macros.S" + +#define CACHE_DLINESIZE 16 + + .text +/* + * cpu_fa526_proc_init() + */ +ENTRY(cpu_fa526_proc_init) + mov pc, lr + +/* + * cpu_fa526_proc_fin() + */ +ENTRY(cpu_fa526_proc_fin) + stmfd sp!, {lr} + mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE + msr cpsr_c, ip + bl fa_flush_kern_cache_all + mrc p15, 0, r0, c1, c0, 0 @ ctrl register + bic r0, r0, #0x1000 @ ...i............ + bic r0, r0, #0x000e @ ............wca. + mcr p15, 0, r0, c1, c0, 0 @ disable caches + nop + nop + ldmfd sp!, {pc} + +/* + * cpu_fa526_reset(loc) + * + * Perform a soft reset of the system. Put the CPU into the + * same state as it would be if it had been reset, and branch + * to what would be the reset vector. + * + * loc: location to jump to for soft reset + */ + .align 4 +ENTRY(cpu_fa526_reset) +/* TODO: Use CP8 if possible... */ + mov ip, #0 + mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches + mcr p15, 0, ip, c7, c10, 4 @ drain WB +#ifdef CONFIG_MMU + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs +#endif + mrc p15, 0, ip, c1, c0, 0 @ ctrl register + bic ip, ip, #0x000f @ ............wcam + bic ip, ip, #0x1100 @ ...i...s........ + bic ip, ip, #0x0800 @ BTB off + mcr p15, 0, ip, c1, c0, 0 @ ctrl register + nop + nop + mov pc, r0 + +/* + * cpu_fa526_do_idle() + */ + .align 4 +ENTRY(cpu_fa526_do_idle) + mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt + mov pc, lr + + +ENTRY(cpu_fa526_dcache_clean_area) +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #CACHE_DLINESIZE + subs r1, r1, #CACHE_DLINESIZE + bhi 1b + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +/* =============================== PageTable ============================== */ + +/* + * cpu_fa526_switch_mm(pgd) + * + * Set the translation base pointer to be as described by pgd. + * + * pgd: new page tables + */ + .align 4 +ENTRY(cpu_fa526_switch_mm) +#ifdef CONFIG_MMU + mov ip, #0 +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache +#else + mcr p15, 0, ip, c7, c14, 0 @ clean and invalidate whole D cache +#endif + mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache + mcr p15, 0, ip, c7, c5, 6 @ invalidate BTB since mm changed + mcr p15, 0, ip, c7, c10, 4 @ data write barrier + mcr p15, 0, ip, c7, c5, 4 @ prefetch flush + mcr p15, 0, r0, c2, c0, 0 @ load page table pointer + mcr p15, 0, ip, c8, c7, 0 @ invalidate UTLB +#endif + mov pc, lr + +/* + * cpu_fa526_set_pte_ext(ptep, pte, ext) + * + * Set a PTE and flush it out + */ + .align 4 +ENTRY(cpu_fa526_set_pte_ext) +#ifdef CONFIG_MMU + armv3_set_pte_ext + mov r0, r0 + mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain WB +#endif + mov pc, lr + + __INIT + + .type __fa526_setup, #function +__fa526_setup: + /* On return of this routine, r0 must carry correct flags for CFG register */ + mov r0, #0 + mcr p15, 0, r0, c7, c7 @ invalidate I,D caches on v4 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 +#ifdef CONFIG_MMU + mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4 +#endif + mcr p15, 0, r0, c7, c5, 5 @ invalidate IScratchpad RAM + + mov r0, #1 + mcr p15, 0, r0, c1, c1, 0 @ turn-on ECR + + mov r0, #0 + mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB All + mcr p15, 0, r0, c7, c10, 4 @ data write barrier + mcr p15, 0, r0, c7, c5, 4 @ prefetch flush + + mov r0, #0x1f @ Domains 0, 1 = manager, 2 = client + mcr p15, 0, r0, c3, c0 @ load domain access register + + mrc p15, 0, r0, c1, c0 @ get control register v4 + ldr r5, fa526_cr1_clear + bic r0, r0, r5 + ldr r5, fa526_cr1_set + orr r0, r0, r5 + mov pc, lr + .size __fa526_setup, . - __fa526_setup + + /* + * .RVI ZFRS BLDP WCAM + * ..11 1001 .111 1101 + * + */ + .type fa526_cr1_clear, #object + .type fa526_cr1_set, #object +fa526_cr1_clear: + .word 0x3f3f +fa526_cr1_set: + .word 0x397D + + __INITDATA + +/* + * Purpose : Function pointers used to access above functions - all calls + * come through these + */ + .type fa526_processor_functions, #object +fa526_processor_functions: + .word v4_early_abort + .word pabort_noifar + .word cpu_fa526_proc_init + .word cpu_fa526_proc_fin + .word cpu_fa526_reset + .word cpu_fa526_do_idle + .word cpu_fa526_dcache_clean_area + .word cpu_fa526_switch_mm + .word cpu_fa526_set_pte_ext + .size fa526_processor_functions, . - fa526_processor_functions + + .section ".rodata" + + .type cpu_arch_name, #object +cpu_arch_name: + .asciz "armv4" + .size cpu_arch_name, . - cpu_arch_name + + .type cpu_elf_name, #object +cpu_elf_name: + .asciz "v4" + .size cpu_elf_name, . - cpu_elf_name + + .type cpu_fa526_name, #object +cpu_fa526_name: + .asciz "FA526" + .size cpu_fa526_name, . - cpu_fa526_name + + .align + + .section ".proc.info.init", #alloc, #execinstr + + .type __fa526_proc_info,#object +__fa526_proc_info: + .long 0x66015261 + .long 0xff01fff1 + .long PMD_TYPE_SECT | \ + PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | \ + PMD_BIT4 | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_BIT4 | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ + b __fa526_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP | HWCAP_HALF + .long cpu_fa526_name + .long fa526_processor_functions + .long fa_tlb_fns + .long fa_user_fns + .long fa_cache_fns + .size __fa526_proc_info, . - __fa526_proc_info diff --git a/arch/arm/mm/tlb-fa.S b/arch/arm/mm/tlb-fa.S new file mode 100644 index 00000000000..9694f1f6f48 --- /dev/null +++ b/arch/arm/mm/tlb-fa.S @@ -0,0 +1,75 @@ +/* + * linux/arch/arm/mm/tlb-fa.S + * + * Copyright (C) 2005 Faraday Corp. + * Copyright (C) 2008-2009 Paulius Zaleckas + * + * Based on tlb-v4wbi.S: + * Copyright (C) 1997-2002 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ARM architecture version 4, Faraday variation. + * This assume an unified TLBs, with a write buffer, and branch target buffer (BTB) + * + * Processors: FA520 FA526 FA626 + */ +#include +#include +#include +#include +#include "proc-macros.S" + + +/* + * flush_user_tlb_range(start, end, mm) + * + * Invalidate a range of TLB entries in the specified address space. + * + * - start - range start address + * - end - range end address + * - mm - mm_struct describing address space + */ + .align 4 +ENTRY(fa_flush_user_tlb_range) + vma_vm_mm ip, r2 + act_mm r3 @ get current->active_mm + eors r3, ip, r3 @ == mm ? + movne pc, lr @ no, we dont do anything + mov r3, #0 + mcr p15, 0, r3, c7, c10, 4 @ drain WB + bic r0, r0, #0x0ff + bic r0, r0, #0xf00 +1: mcr p15, 0, r0, c8, c7, 1 @ invalidate UTLB entry + add r0, r0, #PAGE_SZ + cmp r0, r1 + blo 1b + mcr p15, 0, r3, c7, c5, 6 @ invalidate BTB + mcr p15, 0, r3, c7, c10, 4 @ data write barrier + mov pc, lr + + +ENTRY(fa_flush_kern_tlb_range) + mov r3, #0 + mcr p15, 0, r3, c7, c10, 4 @ drain WB + bic r0, r0, #0x0ff + bic r0, r0, #0xf00 +1: mcr p15, 0, r0, c8, c7, 1 @ invalidate UTLB entry + add r0, r0, #PAGE_SZ + cmp r0, r1 + blo 1b + mcr p15, 0, r3, c7, c5, 6 @ invalidate BTB + mcr p15, 0, r3, c7, c10, 4 @ data write barrier + mcr p15, 0, r3, c7, c5, 4 @ prefetch flush + mov pc, lr + + __INITDATA + + .type fa_tlb_fns, #object +ENTRY(fa_tlb_fns) + .long fa_flush_user_tlb_range + .long fa_flush_kern_tlb_range + .long fa_tlb_flags + .size fa_tlb_fns, . - fa_tlb_fns -- GitLab From 6a915af99fc974be8f2180132ddff7d32aad8779 Mon Sep 17 00:00:00 2001 From: Paulius Zaleckas Date: Wed, 25 Mar 2009 13:10:20 +0200 Subject: [PATCH 4537/4982] MAINTAINERS: Add myself as Faraday ARM core variant maintainer Signed-off-by: Paulius Zaleckas --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 5d460c9d1c2..edca2ad0ebd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -513,6 +513,12 @@ L: openezx-devel@lists.openezx.org (subscribers-only) W: http://www.openezx.org/ S: Maintained +ARM/FARADAY FA526 PORT +P: Paulius Zaleckas +M: paulius.zaleckas@teltonika.lt +L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +S: Maintained + ARM/FREESCALE IMX / MXC ARM ARCHITECTURE P: Sascha Hauer M: kernel@pengutronix.de -- GitLab From b7bb4c9bb01941fe8feb653f3410e7ed0c9bb786 Mon Sep 17 00:00:00 2001 From: Gautham R Shenoy Date: Wed, 25 Mar 2009 14:44:27 +0530 Subject: [PATCH 4538/4982] sched: Add comments to find_busiest_group() function Impact: cleanup Add /** style comments around find_busiest_group(). Also add a few explanatory comments. This concludes the find_busiest_group() cleanup. The function is now down to 72 lines from the original 313 lines. Signed-off-by: Gautham R Shenoy Acked-by: Peter Zijlstra Cc: Suresh Siddha Cc: "Balbir Singh" Cc: Nick Piggin Cc: "Dhaval Giani" Cc: Bharata B Rao Cc: "Vaidyanathan Srinivasan" LKML-Reference: <20090325091427.13992.18933.stgit@sofia.in.ibm.com> Signed-off-by: Ingo Molnar --- kernel/sched.c | 50 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 5f21658b0f6..9f8506d68fd 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3676,10 +3676,30 @@ static inline void calculate_imbalance(struct sd_lb_stats *sds, int this_cpu, } /******* find_busiest_group() helpers end here *********************/ -/* - * find_busiest_group finds and returns the busiest CPU group within the - * domain. It calculates and returns the amount of weighted load which - * should be moved to restore balance via the imbalance parameter. +/** + * find_busiest_group - Returns the busiest group within the sched_domain + * if there is an imbalance. If there isn't an imbalance, and + * the user has opted for power-savings, it returns a group whose + * CPUs can be put to idle by rebalancing those tasks elsewhere, if + * such a group exists. + * + * Also calculates the amount of weighted load which should be moved + * to restore balance. + * + * @sd: The sched_domain whose busiest group is to be returned. + * @this_cpu: The cpu for which load balancing is currently being performed. + * @imbalance: Variable which stores amount of weighted load which should + * be moved to restore balance/put a group to idle. + * @idle: The idle status of this_cpu. + * @sd_idle: The idleness of sd + * @cpus: The set of CPUs under consideration for load-balancing. + * @balance: Pointer to a variable indicating if this_cpu + * is the appropriate cpu to perform load balancing at this_level. + * + * Returns: - the busiest group if imbalance exists. + * - If no imbalance and user has opted for power-savings balance, + * return the least loaded group whose CPUs can be + * put to idle by rebalancing its tasks onto our group. */ static struct sched_group * find_busiest_group(struct sched_domain *sd, int this_cpu, @@ -3697,17 +3717,31 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, update_sd_lb_stats(sd, this_cpu, idle, sd_idle, cpus, balance, &sds); + /* Cases where imbalance does not exist from POV of this_cpu */ + /* 1) this_cpu is not the appropriate cpu to perform load balancing + * at this level. + * 2) There is no busy sibling group to pull from. + * 3) This group is the busiest group. + * 4) This group is more busy than the avg busieness at this + * sched_domain. + * 5) The imbalance is within the specified limit. + * 6) Any rebalance would lead to ping-pong + */ if (balance && !(*balance)) goto ret; - if (!sds.busiest || sds.this_load >= sds.max_load - || sds.busiest_nr_running == 0) + if (!sds.busiest || sds.busiest_nr_running == 0) + goto out_balanced; + + if (sds.this_load >= sds.max_load) goto out_balanced; sds.avg_load = (SCHED_LOAD_SCALE * sds.total_load) / sds.total_pwr; - if (sds.this_load >= sds.avg_load || - 100*sds.max_load <= sd->imbalance_pct * sds.this_load) + if (sds.this_load >= sds.avg_load) + goto out_balanced; + + if (100 * sds.max_load <= sd->imbalance_pct * sds.this_load) goto out_balanced; sds.busiest_load_per_task /= sds.busiest_nr_running; -- GitLab From a9a9adfe2f99ddadfb574a098392a007970a1577 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 25 Mar 2009 17:21:34 +0100 Subject: [PATCH 4539/4982] netfilter: fix xt_LED build failure net/netfilter/xt_LED.c:40: error: field netfilter_led_trigger has incomplete type net/netfilter/xt_LED.c: In function led_timeout_callback: net/netfilter/xt_LED.c:78: warning: unused variable ledinternal net/netfilter/xt_LED.c: In function led_tg_check: net/netfilter/xt_LED.c:102: error: implicit declaration of function led_trigger_register net/netfilter/xt_LED.c: In function led_tg_destroy: net/netfilter/xt_LED.c:135: error: implicit declaration of function led_trigger_unregister Fix by adding a dependency on LED_TRIGGERS. Reported-by: Sachin Sant Tested-by: Subrata Modak Signed-off-by: Patrick McHardy --- net/netfilter/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 2562d05dbaf..2c967e4f706 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -374,7 +374,7 @@ config NETFILTER_XT_TARGET_HL config NETFILTER_XT_TARGET_LED tristate '"LED" target support' - depends on LEDS_CLASS + depends on LEDS_CLASS && LED_TRIGGERS depends on NETFILTER_ADVANCED help This option adds a `LED' target, which allows you to blink LEDs in -- GitLab From 78f3648601fdc7a8166748bbd6d0555a88efa24a Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 25 Mar 2009 17:24:34 +0100 Subject: [PATCH 4540/4982] netfilter: nf_conntrack: use hlist_add_head_rcu() in nf_conntrack_set_hashsize() Using hlist_add_head() in nf_conntrack_set_hashsize() is quite dangerous. Without any barrier, one CPU could see a loop while doing its lookup. Its true new table cannot be seen by another cpu, but previous table is still readable. Signed-off-by: Eric Dumazet Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 55befe59e1c..54e983f1389 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -1121,7 +1121,7 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) struct nf_conntrack_tuple_hash, hnode); hlist_del_rcu(&h->hnode); bucket = __hash_conntrack(&h->tuple, hashsize, rnd); - hlist_add_head(&h->hnode, &hash[bucket]); + hlist_add_head_rcu(&h->hnode, &hash[bucket]); } } old_size = nf_conntrack_htable_size; -- GitLab From b8dfe498775de912116f275680ddb57c8799d9ef Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 25 Mar 2009 17:31:52 +0100 Subject: [PATCH 4541/4982] netfilter: factorize ifname_compare() We use same not trivial helper function in four places. We can factorize it. Signed-off-by: Eric Dumazet Signed-off-by: Patrick McHardy --- include/linux/netfilter/x_tables.h | 23 +++++++++++++++++++++++ net/ipv4/netfilter/arp_tables.c | 14 +------------- net/ipv4/netfilter/ip_tables.c | 23 ++--------------------- net/ipv6/netfilter/ip6_tables.c | 23 ++--------------------- net/netfilter/xt_physdev.c | 21 ++------------------- 5 files changed, 30 insertions(+), 74 deletions(-) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index e8e08d03675..72918b7cbe8 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -435,6 +435,29 @@ extern void xt_free_table_info(struct xt_table_info *info); extern void xt_table_entry_swap_rcu(struct xt_table_info *old, struct xt_table_info *new); +/* + * This helper is performance critical and must be inlined + */ +static inline unsigned long ifname_compare_aligned(const char *_a, + const char *_b, + const char *_mask) +{ + const unsigned long *a = (const unsigned long *)_a; + const unsigned long *b = (const unsigned long *)_b; + const unsigned long *mask = (const unsigned long *)_mask; + unsigned long ret; + + ret = (a[0] ^ b[0]) & mask[0]; + if (IFNAMSIZ > sizeof(unsigned long)) + ret |= (a[1] ^ b[1]) & mask[1]; + if (IFNAMSIZ > 2 * sizeof(unsigned long)) + ret |= (a[2] ^ b[2]) & mask[2]; + if (IFNAMSIZ > 3 * sizeof(unsigned long)) + ret |= (a[3] ^ b[3]) & mask[3]; + BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long)); + return ret; +} + #ifdef CONFIG_COMPAT #include diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 64a7c6ce0b9..4b35dba7cf7 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -80,19 +80,7 @@ static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, static unsigned long ifname_compare(const char *_a, const char *_b, const char *_mask) { #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS - const unsigned long *a = (const unsigned long *)_a; - const unsigned long *b = (const unsigned long *)_b; - const unsigned long *mask = (const unsigned long *)_mask; - unsigned long ret; - - ret = (a[0] ^ b[0]) & mask[0]; - if (IFNAMSIZ > sizeof(unsigned long)) - ret |= (a[1] ^ b[1]) & mask[1]; - if (IFNAMSIZ > 2 * sizeof(unsigned long)) - ret |= (a[2] ^ b[2]) & mask[2]; - if (IFNAMSIZ > 3 * sizeof(unsigned long)) - ret |= (a[3] ^ b[3]) & mask[3]; - BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long)); + unsigned long ret = ifname_compare_aligned(_a, _b, _mask); #else unsigned long ret = 0; int i; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index e5294aec967..41c59e391a6 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -74,25 +74,6 @@ do { \ Hence the start of any table is given by get_table() below. */ -static unsigned long ifname_compare(const char *_a, const char *_b, - const unsigned char *_mask) -{ - const unsigned long *a = (const unsigned long *)_a; - const unsigned long *b = (const unsigned long *)_b; - const unsigned long *mask = (const unsigned long *)_mask; - unsigned long ret; - - ret = (a[0] ^ b[0]) & mask[0]; - if (IFNAMSIZ > sizeof(unsigned long)) - ret |= (a[1] ^ b[1]) & mask[1]; - if (IFNAMSIZ > 2 * sizeof(unsigned long)) - ret |= (a[2] ^ b[2]) & mask[2]; - if (IFNAMSIZ > 3 * sizeof(unsigned long)) - ret |= (a[3] ^ b[3]) & mask[3]; - BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long)); - return ret; -} - /* Returns whether matches rule or not. */ /* Performance critical - called for every packet */ static inline bool @@ -121,7 +102,7 @@ ip_packet_match(const struct iphdr *ip, return false; } - ret = ifname_compare(indev, ipinfo->iniface, ipinfo->iniface_mask); + ret = ifname_compare_aligned(indev, ipinfo->iniface, ipinfo->iniface_mask); if (FWINV(ret != 0, IPT_INV_VIA_IN)) { dprintf("VIA in mismatch (%s vs %s).%s\n", @@ -130,7 +111,7 @@ ip_packet_match(const struct iphdr *ip, return false; } - ret = ifname_compare(outdev, ipinfo->outiface, ipinfo->outiface_mask); + ret = ifname_compare_aligned(outdev, ipinfo->outiface, ipinfo->outiface_mask); if (FWINV(ret != 0, IPT_INV_VIA_OUT)) { dprintf("VIA out mismatch (%s vs %s).%s\n", diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 34af7bb8df5..e59662b3b5b 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -89,25 +89,6 @@ ip6t_ext_hdr(u8 nexthdr) (nexthdr == IPPROTO_DSTOPTS) ); } -static unsigned long ifname_compare(const char *_a, const char *_b, - const unsigned char *_mask) -{ - const unsigned long *a = (const unsigned long *)_a; - const unsigned long *b = (const unsigned long *)_b; - const unsigned long *mask = (const unsigned long *)_mask; - unsigned long ret; - - ret = (a[0] ^ b[0]) & mask[0]; - if (IFNAMSIZ > sizeof(unsigned long)) - ret |= (a[1] ^ b[1]) & mask[1]; - if (IFNAMSIZ > 2 * sizeof(unsigned long)) - ret |= (a[2] ^ b[2]) & mask[2]; - if (IFNAMSIZ > 3 * sizeof(unsigned long)) - ret |= (a[3] ^ b[3]) & mask[3]; - BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long)); - return ret; -} - /* Returns whether matches rule or not. */ /* Performance critical - called for every packet */ static inline bool @@ -138,7 +119,7 @@ ip6_packet_match(const struct sk_buff *skb, return false; } - ret = ifname_compare(indev, ip6info->iniface, ip6info->iniface_mask); + ret = ifname_compare_aligned(indev, ip6info->iniface, ip6info->iniface_mask); if (FWINV(ret != 0, IP6T_INV_VIA_IN)) { dprintf("VIA in mismatch (%s vs %s).%s\n", @@ -147,7 +128,7 @@ ip6_packet_match(const struct sk_buff *skb, return false; } - ret = ifname_compare(outdev, ip6info->outiface, ip6info->outiface_mask); + ret = ifname_compare_aligned(outdev, ip6info->outiface, ip6info->outiface_mask); if (FWINV(ret != 0, IP6T_INV_VIA_OUT)) { dprintf("VIA out mismatch (%s vs %s).%s\n", diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c index 44a234ef443..8d28ca5848b 100644 --- a/net/netfilter/xt_physdev.c +++ b/net/netfilter/xt_physdev.c @@ -20,23 +20,6 @@ MODULE_DESCRIPTION("Xtables: Bridge physical device match"); MODULE_ALIAS("ipt_physdev"); MODULE_ALIAS("ip6t_physdev"); -static unsigned long ifname_compare(const char *_a, const char *_b, const char *_mask) -{ - const unsigned long *a = (const unsigned long *)_a; - const unsigned long *b = (const unsigned long *)_b; - const unsigned long *mask = (const unsigned long *)_mask; - unsigned long ret; - - ret = (a[0] ^ b[0]) & mask[0]; - if (IFNAMSIZ > sizeof(unsigned long)) - ret |= (a[1] ^ b[1]) & mask[1]; - if (IFNAMSIZ > 2 * sizeof(unsigned long)) - ret |= (a[2] ^ b[2]) & mask[2]; - if (IFNAMSIZ > 3 * sizeof(unsigned long)) - ret |= (a[3] ^ b[3]) & mask[3]; - BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long)); - return ret; -} static bool physdev_mt(const struct sk_buff *skb, const struct xt_match_param *par) @@ -85,7 +68,7 @@ physdev_mt(const struct sk_buff *skb, const struct xt_match_param *par) if (!(info->bitmask & XT_PHYSDEV_OP_IN)) goto match_outdev; indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname; - ret = ifname_compare(indev, info->physindev, info->in_mask); + ret = ifname_compare_aligned(indev, info->physindev, info->in_mask); if (!ret ^ !(info->invert & XT_PHYSDEV_OP_IN)) return false; @@ -95,7 +78,7 @@ match_outdev: return true; outdev = nf_bridge->physoutdev ? nf_bridge->physoutdev->name : nulldevname; - ret = ifname_compare(outdev, info->physoutdev, info->out_mask); + ret = ifname_compare_aligned(outdev, info->physoutdev, info->out_mask); return (!!ret ^ !(info->invert & XT_PHYSDEV_OP_OUT)); } -- GitLab From d0dba7255b541f1651a88e75ebdb20dd45509c2f Mon Sep 17 00:00:00 2001 From: Holger Eitzenberger Date: Wed, 25 Mar 2009 18:24:48 +0100 Subject: [PATCH 4542/4982] netfilter: ctnetlink: add callbacks to the per-proto nlattrs There is added a single callback for the l3 proto helper. The two callbacks for the l4 protos are necessary because of the general structure of a ctnetlink event, which is in short: CTA_TUPLE_ORIG CTA_TUPLE_REPLY CTA_ID ... CTA_PROTOINFO CTA_TUPLE_MASTER Therefore the formular is size := sizeof(generic-nlas) + 3 * sizeof(tuple_nlas) + sizeof(protoinfo_nlas) Some of the NLAs are optional, e. g. CTA_TUPLE_MASTER, which is only set if it's an expected connection. But the number of optional NLAs is small enough to prevent netlink_trim() from reallocating if calculated properly. Signed-off-by: Holger Eitzenberger Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_conntrack_l3proto.h | 7 +++++++ include/net/netfilter/nf_conntrack_l4proto.h | 6 ++++++ net/netfilter/nf_conntrack_proto.c | 16 ++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h index 0378676c3dd..9f99d36d5de 100644 --- a/include/net/netfilter/nf_conntrack_l3proto.h +++ b/include/net/netfilter/nf_conntrack_l3proto.h @@ -53,10 +53,17 @@ struct nf_conntrack_l3proto int (*tuple_to_nlattr)(struct sk_buff *skb, const struct nf_conntrack_tuple *t); + /* + * Calculate size of tuple nlattr + */ + int (*nlattr_tuple_size)(void); + int (*nlattr_to_tuple)(struct nlattr *tb[], struct nf_conntrack_tuple *t); const struct nla_policy *nla_policy; + size_t nla_size; + #ifdef CONFIG_SYSCTL struct ctl_table_header *ctl_table_header; struct ctl_path *ctl_table_path; diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h index b01070bf2f8..a120990b3b2 100644 --- a/include/net/netfilter/nf_conntrack_l4proto.h +++ b/include/net/netfilter/nf_conntrack_l4proto.h @@ -64,16 +64,22 @@ struct nf_conntrack_l4proto /* convert protoinfo to nfnetink attributes */ int (*to_nlattr)(struct sk_buff *skb, struct nlattr *nla, const struct nf_conn *ct); + /* Calculate protoinfo nlattr size */ + int (*nlattr_size)(void); /* convert nfnetlink attributes to protoinfo */ int (*from_nlattr)(struct nlattr *tb[], struct nf_conn *ct); int (*tuple_to_nlattr)(struct sk_buff *skb, const struct nf_conntrack_tuple *t); + /* Calculate tuple nlattr size */ + int (*nlattr_tuple_size)(void); int (*nlattr_to_tuple)(struct nlattr *tb[], struct nf_conntrack_tuple *t); const struct nla_policy *nla_policy; + size_t nla_size; + #ifdef CONFIG_SYSCTL struct ctl_table_header **ctl_table_header; struct ctl_table *ctl_table; diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c index 9a62b4efa0e..1a4568bf7ea 100644 --- a/net/netfilter/nf_conntrack_proto.c +++ b/net/netfilter/nf_conntrack_proto.c @@ -167,6 +167,9 @@ int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) if (proto->l3proto >= AF_MAX) return -EBUSY; + if (proto->tuple_to_nlattr && !proto->nlattr_tuple_size) + return -EINVAL; + mutex_lock(&nf_ct_proto_mutex); if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_l3proto_generic) { ret = -EBUSY; @@ -177,6 +180,9 @@ int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) if (ret < 0) goto out_unlock; + if (proto->nlattr_tuple_size) + proto->nla_size = 3 * proto->nlattr_tuple_size(); + rcu_assign_pointer(nf_ct_l3protos[proto->l3proto], proto); out_unlock: @@ -263,6 +269,10 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto) if (l4proto->l3proto >= PF_MAX) return -EBUSY; + if ((l4proto->to_nlattr && !l4proto->nlattr_size) + || (l4proto->tuple_to_nlattr && !l4proto->nlattr_tuple_size)) + return -EINVAL; + mutex_lock(&nf_ct_proto_mutex); if (!nf_ct_protos[l4proto->l3proto]) { /* l3proto may be loaded latter. */ @@ -290,6 +300,12 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto) if (ret < 0) goto out_unlock; + l4proto->nla_size = 0; + if (l4proto->nlattr_size) + l4proto->nla_size += l4proto->nlattr_size(); + if (l4proto->nlattr_tuple_size) + l4proto->nla_size += 3 * l4proto->nlattr_tuple_size(); + rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto], l4proto); -- GitLab From e487eb99cf9381a4f8254fa01747a85818da612b Mon Sep 17 00:00:00 2001 From: Holger Eitzenberger Date: Wed, 25 Mar 2009 18:26:30 +0100 Subject: [PATCH 4543/4982] netlink: add nla_policy_len() It calculates the max. length of a Netlink policy, which is usefull for allocating Netlink buffers roughly the size of the actual message. Signed-off-by: Holger Eitzenberger Signed-off-by: Patrick McHardy --- include/net/netlink.h | 1 + net/netlink/attr.c | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/include/net/netlink.h b/include/net/netlink.h index 8a6150a3f4c..eddb50289d6 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -230,6 +230,7 @@ extern int nla_validate(struct nlattr *head, int len, int maxtype, extern int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, const struct nla_policy *policy); +extern int nla_policy_len(const struct nla_policy *, int); extern struct nlattr * nla_find(struct nlattr *head, int len, int attrtype); extern size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize); diff --git a/net/netlink/attr.c b/net/netlink/attr.c index 56c3ce7fe29..ae32c573df0 100644 --- a/net/netlink/attr.c +++ b/net/netlink/attr.c @@ -132,6 +132,32 @@ errout: return err; } +/** + * nla_policy_len - Determin the max. length of a policy + * @policy: policy to use + * @n: number of policies + * + * Determines the max. length of the policy. It is currently used + * to allocated Netlink buffers roughly the size of the actual + * message. + * + * Returns 0 on success or a negative error code. + */ +int +nla_policy_len(const struct nla_policy *p, int n) +{ + int i, len = 0; + + for (i = 0; i < n; i++) { + if (p->len) + len += nla_total_size(p->len); + else if (nla_attr_minlen[p->type]) + len += nla_total_size(nla_attr_minlen[p->type]); + } + + return len; +} + /** * nla_parse - Parse a stream of attributes into a tb buffer * @tb: destination array with maxtype+1 elements @@ -456,6 +482,7 @@ int nla_append(struct sk_buff *skb, int attrlen, const void *data) } EXPORT_SYMBOL(nla_validate); +EXPORT_SYMBOL(nla_policy_len); EXPORT_SYMBOL(nla_parse); EXPORT_SYMBOL(nla_find); EXPORT_SYMBOL(nla_strlcpy); -- GitLab From af9d32ad6718b9a80fa89f557cc1fbb63a93ec15 Mon Sep 17 00:00:00 2001 From: Holger Eitzenberger Date: Wed, 25 Mar 2009 18:44:01 +0100 Subject: [PATCH 4544/4982] netfilter: limit the length of the helper name This is necessary in order to have an upper bound for Netlink message calculation, which is not a problem at all, as there are no helpers with a longer name. Signed-off-by: Holger Eitzenberger Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_conntrack_helper.h | 2 ++ net/netfilter/nf_conntrack_helper.c | 1 + 2 files changed, 3 insertions(+) diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h index 66d65a7caa3..ee2a4b369a0 100644 --- a/include/net/netfilter/nf_conntrack_helper.h +++ b/include/net/netfilter/nf_conntrack_helper.h @@ -14,6 +14,8 @@ struct module; +#define NF_CT_HELPER_NAME_LEN 16 + struct nf_conntrack_helper { struct hlist_node hnode; /* Internal use. */ diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index a51bdac9f3a..805cfdd4230 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -142,6 +142,7 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me) BUG_ON(me->expect_policy == NULL); BUG_ON(me->expect_class_max >= NF_CT_MAX_EXPECT_CLASSES); + BUG_ON(strlen(me->name) > NF_CT_HELPER_NAME_LEN - 1); mutex_lock(&nf_ct_helper_mutex); hlist_add_head_rcu(&me->hnode, &nf_ct_helper_hash[h]); -- GitLab From 1f9352ae2253a97b07b34dcf16ffa3b4ca12c558 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 25 Mar 2009 19:26:35 +0100 Subject: [PATCH 4545/4982] netfilter: {ip,ip6,arp}_tables: fix incorrect loop detection Commit e1b4b9f ([NETFILTER]: {ip,ip6,arp}_tables: fix exponential worst-case search for loops) introduced a regression in the loop detection algorithm, causing sporadic incorrectly detected loops. When a chain has already been visited during the check, it is treated as having a standard target containing a RETURN verdict directly at the beginning in order to not check it again. The real target of the first rule is then incorrectly treated as STANDARD target and checked not to contain invalid verdicts. Fix by making sure the rule does actually contain a standard target. Based on patch by Francis Dupont Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/arp_tables.c | 4 +++- net/ipv4/netfilter/ip_tables.c | 4 +++- net/ipv6/netfilter/ip6_tables.c | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 4b35dba7cf7..4f454ce9a60 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -388,7 +388,9 @@ static int mark_source_chains(struct xt_table_info *newinfo, && unconditional(&e->arp)) || visited) { unsigned int oldpos, size; - if (t->verdict < -NF_MAX_VERDICT - 1) { + if ((strcmp(t->target.u.user.name, + ARPT_STANDARD_TARGET) == 0) && + t->verdict < -NF_MAX_VERDICT - 1) { duprintf("mark_source_chains: bad " "negative verdict (%i)\n", t->verdict); diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 41c59e391a6..82ee7c9049f 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -488,7 +488,9 @@ mark_source_chains(struct xt_table_info *newinfo, && unconditional(&e->ip)) || visited) { unsigned int oldpos, size; - if (t->verdict < -NF_MAX_VERDICT - 1) { + if ((strcmp(t->target.u.user.name, + IPT_STANDARD_TARGET) == 0) && + t->verdict < -NF_MAX_VERDICT - 1) { duprintf("mark_source_chains: bad " "negative verdict (%i)\n", t->verdict); diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index e59662b3b5b..e89cfa3a8f2 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -517,7 +517,9 @@ mark_source_chains(struct xt_table_info *newinfo, && unconditional(&e->ipv6)) || visited) { unsigned int oldpos, size; - if (t->verdict < -NF_MAX_VERDICT - 1) { + if ((strcmp(t->target.u.user.name, + IP6T_STANDARD_TARGET) == 0) && + t->verdict < -NF_MAX_VERDICT - 1) { duprintf("mark_source_chains: bad " "negative verdict (%i)\n", t->verdict); -- GitLab From 2f3ec501ba1e1a68ab9d413f143bdc8f46417fc1 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 16 Mar 2009 15:28:42 -0700 Subject: [PATCH 4546/4982] [ARM] OMAP: Fix compile for omap2_init_common_hw() Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/board-3430sdp.c | 2 +- arch/arm/mach-omap2/board-omap3pandora.c | 2 +- arch/arm/mach-omap2/board-overo.c | 2 +- arch/arm/mach-omap2/board-rx51.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index 2af38e56db3..ed927497212 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -222,7 +222,7 @@ static inline void __init sdp3430_init_smc91x(void) static void __init omap_3430sdp_init_irq(void) { - omap2_init_common_hw(); + omap2_init_common_hw(NULL); omap_init_irq(); omap_gpio_init(); sdp3430_init_smc91x(); diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index 16e2128daa1..402f09c6cf1 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -118,7 +118,7 @@ static int __init omap3pandora_i2c_init(void) static void __init omap3pandora_init_irq(void) { - omap2_init_common_hw(); + omap2_init_common_hw(NULL); omap_init_irq(); omap_gpio_init(); } diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index 782268c9194..b3f6e9d8180 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -239,7 +239,7 @@ static int __init overo_i2c_init(void) static void __init overo_init_irq(void) { - omap2_init_common_hw(); + omap2_init_common_hw(NULL); omap_init_irq(); omap_gpio_init(); } diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c index 6a3c5e53d99..3a0daac6c83 100644 --- a/arch/arm/mach-omap2/board-rx51.c +++ b/arch/arm/mach-omap2/board-rx51.c @@ -62,7 +62,7 @@ static struct omap_board_config_kernel rx51_config[] = { static void __init rx51_init_irq(void) { - omap2_init_common_hw(); + omap2_init_common_hw(NULL); omap_init_irq(); omap_gpio_init(); } -- GitLab From ea781f197d6a835cbb93a0bf88ee1696296ed8aa Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 25 Mar 2009 21:05:46 +0100 Subject: [PATCH 4547/4982] netfilter: nf_conntrack: use SLAB_DESTROY_BY_RCU and get rid of call_rcu() Use "hlist_nulls" infrastructure we added in 2.6.29 for RCUification of UDP & TCP. This permits an easy conversion from call_rcu() based hash lists to a SLAB_DESTROY_BY_RCU one. Avoiding call_rcu() delay at nf_conn freeing time has numerous gains. First, it doesnt fill RCU queues (up to 10000 elements per cpu). This reduces OOM possibility, if queued elements are not taken into account This reduces latency problems when RCU queue size hits hilimit and triggers emergency mode. - It allows fast reuse of just freed elements, permitting better use of CPU cache. - We delete rcu_head from "struct nf_conn", shrinking size of this structure by 8 or 16 bytes. This patch only takes care of "struct nf_conn". call_rcu() is still used for less critical conntrack parts, that may be converted later if necessary. Signed-off-by: Eric Dumazet Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_conntrack.h | 14 +- include/net/netfilter/nf_conntrack_tuple.h | 6 +- include/net/netns/conntrack.h | 5 +- .../nf_conntrack_l3proto_ipv4_compat.c | 63 +++++---- net/ipv4/netfilter/nf_nat_core.c | 2 +- net/netfilter/nf_conntrack_core.c | 123 ++++++++++-------- net/netfilter/nf_conntrack_expect.c | 2 +- net/netfilter/nf_conntrack_helper.c | 7 +- net/netfilter/nf_conntrack_netlink.c | 20 +-- net/netfilter/nf_conntrack_standalone.c | 57 ++++---- net/netfilter/xt_connlimit.c | 6 +- 11 files changed, 174 insertions(+), 131 deletions(-) diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 4dfb793c3f1..6c3f964de9e 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -91,8 +91,7 @@ struct nf_conn_help { #include #include -struct nf_conn -{ +struct nf_conn { /* Usage count in here is 1 for hash table/destruct timer, 1 per skb, plus 1 for any connection(s) we are `master' for */ struct nf_conntrack ct_general; @@ -126,7 +125,6 @@ struct nf_conn #ifdef CONFIG_NET_NS struct net *ct_net; #endif - struct rcu_head rcu; }; static inline struct nf_conn * @@ -190,9 +188,13 @@ static inline void nf_ct_put(struct nf_conn *ct) extern int nf_ct_l3proto_try_module_get(unsigned short l3proto); extern void nf_ct_l3proto_module_put(unsigned short l3proto); -extern struct hlist_head *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced); -extern void nf_ct_free_hashtable(struct hlist_head *hash, int vmalloced, - unsigned int size); +/* + * Allocate a hashtable of hlist_head (if nulls == 0), + * or hlist_nulls_head (if nulls == 1) + */ +extern void *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced, int nulls); + +extern void nf_ct_free_hashtable(void *hash, int vmalloced, unsigned int size); extern struct nf_conntrack_tuple_hash * __nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple); diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h index f2f6aa73dc1..2628c154d40 100644 --- a/include/net/netfilter/nf_conntrack_tuple.h +++ b/include/net/netfilter/nf_conntrack_tuple.h @@ -12,6 +12,7 @@ #include #include +#include /* A `tuple' is a structure containing the information to uniquely identify a connection. ie. if two packets have the same tuple, they @@ -146,9 +147,8 @@ static inline void nf_ct_dump_tuple(const struct nf_conntrack_tuple *t) ((enum ip_conntrack_dir)(h)->tuple.dst.dir) /* Connections have two entries in the hash table: one for each way */ -struct nf_conntrack_tuple_hash -{ - struct hlist_node hnode; +struct nf_conntrack_tuple_hash { + struct hlist_nulls_node hnnode; struct nf_conntrack_tuple tuple; }; diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h index f4498a62881..9dc58402bc0 100644 --- a/include/net/netns/conntrack.h +++ b/include/net/netns/conntrack.h @@ -2,6 +2,7 @@ #define __NETNS_CONNTRACK_H #include +#include #include struct ctl_table_header; @@ -10,9 +11,9 @@ struct nf_conntrack_ecache; struct netns_ct { atomic_t count; unsigned int expect_count; - struct hlist_head *hash; + struct hlist_nulls_head *hash; struct hlist_head *expect_hash; - struct hlist_head unconfirmed; + struct hlist_nulls_head unconfirmed; struct ip_conntrack_stat *stat; #ifdef CONFIG_NF_CONNTRACK_EVENTS struct nf_conntrack_ecache *ecache; diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c index 6ba5c557690..8668a3defda 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c @@ -25,40 +25,42 @@ struct ct_iter_state { unsigned int bucket; }; -static struct hlist_node *ct_get_first(struct seq_file *seq) +static struct hlist_nulls_node *ct_get_first(struct seq_file *seq) { struct net *net = seq_file_net(seq); struct ct_iter_state *st = seq->private; - struct hlist_node *n; + struct hlist_nulls_node *n; for (st->bucket = 0; st->bucket < nf_conntrack_htable_size; st->bucket++) { n = rcu_dereference(net->ct.hash[st->bucket].first); - if (n) + if (!is_a_nulls(n)) return n; } return NULL; } -static struct hlist_node *ct_get_next(struct seq_file *seq, - struct hlist_node *head) +static struct hlist_nulls_node *ct_get_next(struct seq_file *seq, + struct hlist_nulls_node *head) { struct net *net = seq_file_net(seq); struct ct_iter_state *st = seq->private; head = rcu_dereference(head->next); - while (head == NULL) { - if (++st->bucket >= nf_conntrack_htable_size) - return NULL; + while (is_a_nulls(head)) { + if (likely(get_nulls_value(head) == st->bucket)) { + if (++st->bucket >= nf_conntrack_htable_size) + return NULL; + } head = rcu_dereference(net->ct.hash[st->bucket].first); } return head; } -static struct hlist_node *ct_get_idx(struct seq_file *seq, loff_t pos) +static struct hlist_nulls_node *ct_get_idx(struct seq_file *seq, loff_t pos) { - struct hlist_node *head = ct_get_first(seq); + struct hlist_nulls_node *head = ct_get_first(seq); if (head) while (pos && (head = ct_get_next(seq, head))) @@ -87,69 +89,76 @@ static void ct_seq_stop(struct seq_file *s, void *v) static int ct_seq_show(struct seq_file *s, void *v) { - const struct nf_conntrack_tuple_hash *hash = v; - const struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(hash); + struct nf_conntrack_tuple_hash *hash = v; + struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(hash); const struct nf_conntrack_l3proto *l3proto; const struct nf_conntrack_l4proto *l4proto; + int ret = 0; NF_CT_ASSERT(ct); + if (unlikely(!atomic_inc_not_zero(&ct->ct_general.use))) + return 0; + /* we only want to print DIR_ORIGINAL */ if (NF_CT_DIRECTION(hash)) - return 0; + goto release; if (nf_ct_l3num(ct) != AF_INET) - return 0; + goto release; l3proto = __nf_ct_l3proto_find(nf_ct_l3num(ct)); NF_CT_ASSERT(l3proto); l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); NF_CT_ASSERT(l4proto); + ret = -ENOSPC; if (seq_printf(s, "%-8s %u %ld ", l4proto->name, nf_ct_protonum(ct), timer_pending(&ct->timeout) ? (long)(ct->timeout.expires - jiffies)/HZ : 0) != 0) - return -ENOSPC; + goto release; if (l4proto->print_conntrack && l4proto->print_conntrack(s, ct)) - return -ENOSPC; + goto release; if (print_tuple(s, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, l3proto, l4proto)) - return -ENOSPC; + goto release; if (seq_print_acct(s, ct, IP_CT_DIR_ORIGINAL)) - return -ENOSPC; + goto release; if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status))) if (seq_printf(s, "[UNREPLIED] ")) - return -ENOSPC; + goto release; if (print_tuple(s, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, l3proto, l4proto)) - return -ENOSPC; + goto release; if (seq_print_acct(s, ct, IP_CT_DIR_REPLY)) - return -ENOSPC; + goto release; if (test_bit(IPS_ASSURED_BIT, &ct->status)) if (seq_printf(s, "[ASSURED] ")) - return -ENOSPC; + goto release; #ifdef CONFIG_NF_CONNTRACK_MARK if (seq_printf(s, "mark=%u ", ct->mark)) - return -ENOSPC; + goto release; #endif #ifdef CONFIG_NF_CONNTRACK_SECMARK if (seq_printf(s, "secmark=%u ", ct->secmark)) - return -ENOSPC; + goto release; #endif if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use))) - return -ENOSPC; - - return 0; + goto release; + ret = 0; +release: + nf_ct_put(ct); + return ret; } static const struct seq_operations ct_seq_ops = { diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index a65cf692359..fe65187810f 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -679,7 +679,7 @@ nfnetlink_parse_nat_setup(struct nf_conn *ct, static int __net_init nf_nat_net_init(struct net *net) { net->ipv4.nat_bysource = nf_ct_alloc_hashtable(&nf_nat_htable_size, - &net->ipv4.nat_vmalloced); + &net->ipv4.nat_vmalloced, 0); if (!net->ipv4.nat_bysource) return -ENOMEM; return 0; diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 54e983f1389..c55bbdc7d42 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -163,8 +164,8 @@ static void clean_from_lists(struct nf_conn *ct) { pr_debug("clean_from_lists(%p)\n", ct); - hlist_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode); - hlist_del_rcu(&ct->tuplehash[IP_CT_DIR_REPLY].hnode); + hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode); + hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_REPLY].hnnode); /* Destroy all pending expectations */ nf_ct_remove_expectations(ct); @@ -204,8 +205,8 @@ destroy_conntrack(struct nf_conntrack *nfct) /* We overload first tuple to link into unconfirmed list. */ if (!nf_ct_is_confirmed(ct)) { - BUG_ON(hlist_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode)); - hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode); + BUG_ON(hlist_nulls_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode)); + hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode); } NF_CT_STAT_INC(net, delete); @@ -242,18 +243,26 @@ static void death_by_timeout(unsigned long ul_conntrack) nf_ct_put(ct); } +/* + * Warning : + * - Caller must take a reference on returned object + * and recheck nf_ct_tuple_equal(tuple, &h->tuple) + * OR + * - Caller must lock nf_conntrack_lock before calling this function + */ struct nf_conntrack_tuple_hash * __nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple) { struct nf_conntrack_tuple_hash *h; - struct hlist_node *n; + struct hlist_nulls_node *n; unsigned int hash = hash_conntrack(tuple); /* Disable BHs the entire time since we normally need to disable them * at least once for the stats anyway. */ local_bh_disable(); - hlist_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnode) { +begin: + hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnnode) { if (nf_ct_tuple_equal(tuple, &h->tuple)) { NF_CT_STAT_INC(net, found); local_bh_enable(); @@ -261,6 +270,13 @@ __nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple) } NF_CT_STAT_INC(net, searched); } + /* + * if the nulls value we got at the end of this lookup is + * not the expected one, we must restart lookup. + * We probably met an item that was moved to another chain. + */ + if (get_nulls_value(n) != hash) + goto begin; local_bh_enable(); return NULL; @@ -275,11 +291,18 @@ nf_conntrack_find_get(struct net *net, const struct nf_conntrack_tuple *tuple) struct nf_conn *ct; rcu_read_lock(); +begin: h = __nf_conntrack_find(net, tuple); if (h) { ct = nf_ct_tuplehash_to_ctrack(h); if (unlikely(!atomic_inc_not_zero(&ct->ct_general.use))) h = NULL; + else { + if (unlikely(!nf_ct_tuple_equal(tuple, &h->tuple))) { + nf_ct_put(ct); + goto begin; + } + } } rcu_read_unlock(); @@ -293,9 +316,9 @@ static void __nf_conntrack_hash_insert(struct nf_conn *ct, { struct net *net = nf_ct_net(ct); - hlist_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode, + hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, &net->ct.hash[hash]); - hlist_add_head_rcu(&ct->tuplehash[IP_CT_DIR_REPLY].hnode, + hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_REPLY].hnnode, &net->ct.hash[repl_hash]); } @@ -318,7 +341,7 @@ __nf_conntrack_confirm(struct sk_buff *skb) struct nf_conntrack_tuple_hash *h; struct nf_conn *ct; struct nf_conn_help *help; - struct hlist_node *n; + struct hlist_nulls_node *n; enum ip_conntrack_info ctinfo; struct net *net; @@ -350,17 +373,17 @@ __nf_conntrack_confirm(struct sk_buff *skb) /* See if there's one in the list already, including reverse: NAT could have grabbed it without realizing, since we're not in the hash. If there is, we lost race. */ - hlist_for_each_entry(h, n, &net->ct.hash[hash], hnode) + hlist_nulls_for_each_entry(h, n, &net->ct.hash[hash], hnnode) if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, &h->tuple)) goto out; - hlist_for_each_entry(h, n, &net->ct.hash[repl_hash], hnode) + hlist_nulls_for_each_entry(h, n, &net->ct.hash[repl_hash], hnnode) if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple, &h->tuple)) goto out; /* Remove from unconfirmed list */ - hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode); + hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode); __nf_conntrack_hash_insert(ct, hash, repl_hash); /* Timer relative to confirmation time, not original @@ -399,14 +422,14 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, { struct net *net = nf_ct_net(ignored_conntrack); struct nf_conntrack_tuple_hash *h; - struct hlist_node *n; + struct hlist_nulls_node *n; unsigned int hash = hash_conntrack(tuple); /* Disable BHs the entire time since we need to disable them at * least once for the stats anyway. */ rcu_read_lock_bh(); - hlist_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnode) { + hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnnode) { if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack && nf_ct_tuple_equal(tuple, &h->tuple)) { NF_CT_STAT_INC(net, found); @@ -430,14 +453,14 @@ static noinline int early_drop(struct net *net, unsigned int hash) /* Use oldest entry, which is roughly LRU */ struct nf_conntrack_tuple_hash *h; struct nf_conn *ct = NULL, *tmp; - struct hlist_node *n; + struct hlist_nulls_node *n; unsigned int i, cnt = 0; int dropped = 0; rcu_read_lock(); for (i = 0; i < nf_conntrack_htable_size; i++) { - hlist_for_each_entry_rcu(h, n, &net->ct.hash[hash], - hnode) { + hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], + hnnode) { tmp = nf_ct_tuplehash_to_ctrack(h); if (!test_bit(IPS_ASSURED_BIT, &tmp->status)) ct = tmp; @@ -508,27 +531,19 @@ struct nf_conn *nf_conntrack_alloc(struct net *net, #ifdef CONFIG_NET_NS ct->ct_net = net; #endif - INIT_RCU_HEAD(&ct->rcu); return ct; } EXPORT_SYMBOL_GPL(nf_conntrack_alloc); -static void nf_conntrack_free_rcu(struct rcu_head *head) -{ - struct nf_conn *ct = container_of(head, struct nf_conn, rcu); - - nf_ct_ext_free(ct); - kmem_cache_free(nf_conntrack_cachep, ct); -} - void nf_conntrack_free(struct nf_conn *ct) { struct net *net = nf_ct_net(ct); nf_ct_ext_destroy(ct); atomic_dec(&net->ct.count); - call_rcu(&ct->rcu, nf_conntrack_free_rcu); + nf_ct_ext_free(ct); + kmem_cache_free(nf_conntrack_cachep, ct); } EXPORT_SYMBOL_GPL(nf_conntrack_free); @@ -594,7 +609,7 @@ init_conntrack(struct net *net, } /* Overload tuple linked list to put us in unconfirmed list. */ - hlist_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode, + hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, &net->ct.unconfirmed); spin_unlock_bh(&nf_conntrack_lock); @@ -934,17 +949,17 @@ get_next_corpse(struct net *net, int (*iter)(struct nf_conn *i, void *data), { struct nf_conntrack_tuple_hash *h; struct nf_conn *ct; - struct hlist_node *n; + struct hlist_nulls_node *n; spin_lock_bh(&nf_conntrack_lock); for (; *bucket < nf_conntrack_htable_size; (*bucket)++) { - hlist_for_each_entry(h, n, &net->ct.hash[*bucket], hnode) { + hlist_nulls_for_each_entry(h, n, &net->ct.hash[*bucket], hnnode) { ct = nf_ct_tuplehash_to_ctrack(h); if (iter(ct, data)) goto found; } } - hlist_for_each_entry(h, n, &net->ct.unconfirmed, hnode) { + hlist_nulls_for_each_entry(h, n, &net->ct.unconfirmed, hnnode) { ct = nf_ct_tuplehash_to_ctrack(h); if (iter(ct, data)) set_bit(IPS_DYING_BIT, &ct->status); @@ -992,7 +1007,7 @@ static int kill_all(struct nf_conn *i, void *data) return 1; } -void nf_ct_free_hashtable(struct hlist_head *hash, int vmalloced, unsigned int size) +void nf_ct_free_hashtable(void *hash, int vmalloced, unsigned int size) { if (vmalloced) vfree(hash); @@ -1060,26 +1075,28 @@ void nf_conntrack_cleanup(struct net *net) } } -struct hlist_head *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced) +void *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced, int nulls) { - struct hlist_head *hash; - unsigned int size, i; + struct hlist_nulls_head *hash; + unsigned int nr_slots, i; + size_t sz; *vmalloced = 0; - size = *sizep = roundup(*sizep, PAGE_SIZE / sizeof(struct hlist_head)); - hash = (void*)__get_free_pages(GFP_KERNEL|__GFP_NOWARN, - get_order(sizeof(struct hlist_head) - * size)); + BUILD_BUG_ON(sizeof(struct hlist_nulls_head) != sizeof(struct hlist_head)); + nr_slots = *sizep = roundup(*sizep, PAGE_SIZE / sizeof(struct hlist_nulls_head)); + sz = nr_slots * sizeof(struct hlist_nulls_head); + hash = (void *)__get_free_pages(GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO, + get_order(sz)); if (!hash) { *vmalloced = 1; printk(KERN_WARNING "nf_conntrack: falling back to vmalloc.\n"); - hash = vmalloc(sizeof(struct hlist_head) * size); + hash = __vmalloc(sz, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL); } - if (hash) - for (i = 0; i < size; i++) - INIT_HLIST_HEAD(&hash[i]); + if (hash && nulls) + for (i = 0; i < nr_slots; i++) + INIT_HLIST_NULLS_HEAD(&hash[i], i); return hash; } @@ -1090,7 +1107,7 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) int i, bucket, vmalloced, old_vmalloced; unsigned int hashsize, old_size; int rnd; - struct hlist_head *hash, *old_hash; + struct hlist_nulls_head *hash, *old_hash; struct nf_conntrack_tuple_hash *h; /* On boot, we can set this without any fancy locking. */ @@ -1101,7 +1118,7 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) if (!hashsize) return -EINVAL; - hash = nf_ct_alloc_hashtable(&hashsize, &vmalloced); + hash = nf_ct_alloc_hashtable(&hashsize, &vmalloced, 1); if (!hash) return -ENOMEM; @@ -1116,12 +1133,12 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) */ spin_lock_bh(&nf_conntrack_lock); for (i = 0; i < nf_conntrack_htable_size; i++) { - while (!hlist_empty(&init_net.ct.hash[i])) { - h = hlist_entry(init_net.ct.hash[i].first, - struct nf_conntrack_tuple_hash, hnode); - hlist_del_rcu(&h->hnode); + while (!hlist_nulls_empty(&init_net.ct.hash[i])) { + h = hlist_nulls_entry(init_net.ct.hash[i].first, + struct nf_conntrack_tuple_hash, hnnode); + hlist_nulls_del_rcu(&h->hnnode); bucket = __hash_conntrack(&h->tuple, hashsize, rnd); - hlist_add_head_rcu(&h->hnode, &hash[bucket]); + hlist_nulls_add_head_rcu(&h->hnnode, &hash[bucket]); } } old_size = nf_conntrack_htable_size; @@ -1172,7 +1189,7 @@ static int nf_conntrack_init_init_net(void) nf_conntrack_cachep = kmem_cache_create("nf_conntrack", sizeof(struct nf_conn), - 0, 0, NULL); + 0, SLAB_DESTROY_BY_RCU, NULL); if (!nf_conntrack_cachep) { printk(KERN_ERR "Unable to create nf_conn slab cache\n"); ret = -ENOMEM; @@ -1202,7 +1219,7 @@ static int nf_conntrack_init_net(struct net *net) int ret; atomic_set(&net->ct.count, 0); - INIT_HLIST_HEAD(&net->ct.unconfirmed); + INIT_HLIST_NULLS_HEAD(&net->ct.unconfirmed, 0); net->ct.stat = alloc_percpu(struct ip_conntrack_stat); if (!net->ct.stat) { ret = -ENOMEM; @@ -1212,7 +1229,7 @@ static int nf_conntrack_init_net(struct net *net) if (ret < 0) goto err_ecache; net->ct.hash = nf_ct_alloc_hashtable(&nf_conntrack_htable_size, - &net->ct.hash_vmalloc); + &net->ct.hash_vmalloc, 1); if (!net->ct.hash) { ret = -ENOMEM; printk(KERN_ERR "Unable to create nf_conntrack_hash\n"); diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 357ba39d4c8..3940f996a2e 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -604,7 +604,7 @@ int nf_conntrack_expect_init(struct net *net) net->ct.expect_count = 0; net->ct.expect_hash = nf_ct_alloc_hashtable(&nf_ct_expect_hsize, - &net->ct.expect_vmalloc); + &net->ct.expect_vmalloc, 0); if (net->ct.expect_hash == NULL) goto err1; diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 805cfdd4230..30b8e9009f9 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -159,6 +159,7 @@ static void __nf_conntrack_helper_unregister(struct nf_conntrack_helper *me, struct nf_conntrack_tuple_hash *h; struct nf_conntrack_expect *exp; const struct hlist_node *n, *next; + const struct hlist_nulls_node *nn; unsigned int i; /* Get rid of expectations */ @@ -175,10 +176,10 @@ static void __nf_conntrack_helper_unregister(struct nf_conntrack_helper *me, } /* Get rid of expecteds, set helpers to NULL. */ - hlist_for_each_entry(h, n, &net->ct.unconfirmed, hnode) + hlist_for_each_entry(h, nn, &net->ct.unconfirmed, hnnode) unhelp(h, me); for (i = 0; i < nf_conntrack_htable_size; i++) { - hlist_for_each_entry(h, n, &net->ct.hash[i], hnode) + hlist_nulls_for_each_entry(h, nn, &net->ct.hash[i], hnnode) unhelp(h, me); } } @@ -218,7 +219,7 @@ int nf_conntrack_helper_init(void) nf_ct_helper_hsize = 1; /* gets rounded up to use one page */ nf_ct_helper_hash = nf_ct_alloc_hashtable(&nf_ct_helper_hsize, - &nf_ct_helper_vmalloc); + &nf_ct_helper_vmalloc, 0); if (!nf_ct_helper_hash) return -ENOMEM; diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 1b75c9efb0e..349bbefe551 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -536,7 +537,7 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) { struct nf_conn *ct, *last; struct nf_conntrack_tuple_hash *h; - struct hlist_node *n; + struct hlist_nulls_node *n; struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh); u_int8_t l3proto = nfmsg->nfgen_family; @@ -544,27 +545,27 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) last = (struct nf_conn *)cb->args[1]; for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) { restart: - hlist_for_each_entry_rcu(h, n, &init_net.ct.hash[cb->args[0]], - hnode) { + hlist_nulls_for_each_entry_rcu(h, n, &init_net.ct.hash[cb->args[0]], + hnnode) { if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) continue; ct = nf_ct_tuplehash_to_ctrack(h); + if (!atomic_inc_not_zero(&ct->ct_general.use)) + continue; /* Dump entries of a given L3 protocol number. * If it is not specified, ie. l3proto == 0, * then dump everything. */ if (l3proto && nf_ct_l3num(ct) != l3proto) - continue; + goto releasect; if (cb->args[1]) { if (ct != last) - continue; + goto releasect; cb->args[1] = 0; } if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, IPCTNL_MSG_CT_NEW, 1, ct) < 0) { - if (!atomic_inc_not_zero(&ct->ct_general.use)) - continue; cb->args[1] = (unsigned long)ct; goto out; } @@ -577,6 +578,8 @@ restart: if (acct) memset(acct, 0, sizeof(struct nf_conn_counter[IP_CT_DIR_MAX])); } +releasect: + nf_ct_put(ct); } if (cb->args[1]) { cb->args[1] = 0; @@ -1242,13 +1245,12 @@ ctnetlink_create_conntrack(struct nlattr *cda[], if (err < 0) goto err2; - master_h = __nf_conntrack_find(&init_net, &master); + master_h = nf_conntrack_find_get(&init_net, &master); if (master_h == NULL) { err = -ENOENT; goto err2; } master_ct = nf_ct_tuplehash_to_ctrack(master_h); - nf_conntrack_get(&master_ct->ct_general); __set_bit(IPS_EXPECTED_BIT, &ct->status); ct->master = master_ct; } diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 4da54b0b923..19351538197 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -44,40 +44,42 @@ struct ct_iter_state { unsigned int bucket; }; -static struct hlist_node *ct_get_first(struct seq_file *seq) +static struct hlist_nulls_node *ct_get_first(struct seq_file *seq) { struct net *net = seq_file_net(seq); struct ct_iter_state *st = seq->private; - struct hlist_node *n; + struct hlist_nulls_node *n; for (st->bucket = 0; st->bucket < nf_conntrack_htable_size; st->bucket++) { n = rcu_dereference(net->ct.hash[st->bucket].first); - if (n) + if (!is_a_nulls(n)) return n; } return NULL; } -static struct hlist_node *ct_get_next(struct seq_file *seq, - struct hlist_node *head) +static struct hlist_nulls_node *ct_get_next(struct seq_file *seq, + struct hlist_nulls_node *head) { struct net *net = seq_file_net(seq); struct ct_iter_state *st = seq->private; head = rcu_dereference(head->next); - while (head == NULL) { - if (++st->bucket >= nf_conntrack_htable_size) - return NULL; + while (is_a_nulls(head)) { + if (likely(get_nulls_value(head) == st->bucket)) { + if (++st->bucket >= nf_conntrack_htable_size) + return NULL; + } head = rcu_dereference(net->ct.hash[st->bucket].first); } return head; } -static struct hlist_node *ct_get_idx(struct seq_file *seq, loff_t pos) +static struct hlist_nulls_node *ct_get_idx(struct seq_file *seq, loff_t pos) { - struct hlist_node *head = ct_get_first(seq); + struct hlist_nulls_node *head = ct_get_first(seq); if (head) while (pos && (head = ct_get_next(seq, head))) @@ -107,67 +109,74 @@ static void ct_seq_stop(struct seq_file *s, void *v) /* return 0 on success, 1 in case of error */ static int ct_seq_show(struct seq_file *s, void *v) { - const struct nf_conntrack_tuple_hash *hash = v; - const struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(hash); + struct nf_conntrack_tuple_hash *hash = v; + struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(hash); const struct nf_conntrack_l3proto *l3proto; const struct nf_conntrack_l4proto *l4proto; + int ret = 0; NF_CT_ASSERT(ct); + if (unlikely(!atomic_inc_not_zero(&ct->ct_general.use))) + return 0; /* we only want to print DIR_ORIGINAL */ if (NF_CT_DIRECTION(hash)) - return 0; + goto release; l3proto = __nf_ct_l3proto_find(nf_ct_l3num(ct)); NF_CT_ASSERT(l3proto); l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); NF_CT_ASSERT(l4proto); + ret = -ENOSPC; if (seq_printf(s, "%-8s %u %-8s %u %ld ", l3proto->name, nf_ct_l3num(ct), l4proto->name, nf_ct_protonum(ct), timer_pending(&ct->timeout) ? (long)(ct->timeout.expires - jiffies)/HZ : 0) != 0) - return -ENOSPC; + goto release; if (l4proto->print_conntrack && l4proto->print_conntrack(s, ct)) - return -ENOSPC; + goto release; if (print_tuple(s, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, l3proto, l4proto)) - return -ENOSPC; + goto release; if (seq_print_acct(s, ct, IP_CT_DIR_ORIGINAL)) - return -ENOSPC; + goto release; if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status))) if (seq_printf(s, "[UNREPLIED] ")) - return -ENOSPC; + goto release; if (print_tuple(s, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, l3proto, l4proto)) - return -ENOSPC; + goto release; if (seq_print_acct(s, ct, IP_CT_DIR_REPLY)) - return -ENOSPC; + goto release; if (test_bit(IPS_ASSURED_BIT, &ct->status)) if (seq_printf(s, "[ASSURED] ")) - return -ENOSPC; + goto release; #if defined(CONFIG_NF_CONNTRACK_MARK) if (seq_printf(s, "mark=%u ", ct->mark)) - return -ENOSPC; + goto release; #endif #ifdef CONFIG_NF_CONNTRACK_SECMARK if (seq_printf(s, "secmark=%u ", ct->secmark)) - return -ENOSPC; + goto release; #endif if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use))) - return -ENOSPC; + goto release; + ret = 0; +release: + nf_ct_put(ct); return 0; } diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c index 7f404cc64c8..68098095439 100644 --- a/net/netfilter/xt_connlimit.c +++ b/net/netfilter/xt_connlimit.c @@ -108,7 +108,7 @@ static int count_them(struct xt_connlimit_data *data, const struct nf_conntrack_tuple_hash *found; struct xt_connlimit_conn *conn; struct xt_connlimit_conn *tmp; - const struct nf_conn *found_ct; + struct nf_conn *found_ct; struct list_head *hash; bool addit = true; int matches = 0; @@ -123,7 +123,7 @@ static int count_them(struct xt_connlimit_data *data, /* check the saved connections */ list_for_each_entry_safe(conn, tmp, hash, list) { - found = __nf_conntrack_find(&init_net, &conn->tuple); + found = nf_conntrack_find_get(&init_net, &conn->tuple); found_ct = NULL; if (found != NULL) @@ -151,6 +151,7 @@ static int count_them(struct xt_connlimit_data *data, * we do not care about connections which are * closed already -> ditch it */ + nf_ct_put(found_ct); list_del(&conn->list); kfree(conn); continue; @@ -160,6 +161,7 @@ static int count_them(struct xt_connlimit_data *data, match->family)) /* same source network -> be counted! */ ++matches; + nf_ct_put(found_ct); } rcu_read_unlock(); -- GitLab From 2732c4e45bb67006fdc9ae6669be866762711ab5 Mon Sep 17 00:00:00 2001 From: Holger Eitzenberger Date: Wed, 25 Mar 2009 21:50:59 +0100 Subject: [PATCH 4548/4982] netfilter: ctnetlink: allocate right-sized ctnetlink skb Try to allocate a Netlink skb roughly the size of the actual message, with the help from the l3 and l4 protocol helpers. This is all to prevent a reallocation in netlink_trim() later. The overhead of allocating the right-sized skb is rather small, with ctnetlink_alloc_skb() actually being inlined away on my x86_64 box. The size of the per-proto space is determined at registration time of the protocol helper. Signed-off-by: Holger Eitzenberger Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_netlink.c | 65 +++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 349bbefe551..03547c60f38 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -405,6 +405,69 @@ nla_put_failure: } #ifdef CONFIG_NF_CONNTRACK_EVENTS +/* + * The general structure of a ctnetlink event is + * + * CTA_TUPLE_ORIG + * + * CTA_TUPLE_REPLY + * + * CTA_ID + * ... + * CTA_PROTOINFO + * + * CTA_TUPLE_MASTER + * + * + * Therefore the formular is + * + * size = sizeof(headers) + sizeof(generic_nlas) + 3 * sizeof(tuple_nlas) + * + sizeof(protoinfo_nlas) + */ +static struct sk_buff * +ctnetlink_alloc_skb(const struct nf_conntrack_tuple *tuple, gfp_t gfp) +{ + struct nf_conntrack_l3proto *l3proto; + struct nf_conntrack_l4proto *l4proto; + int len; + +#define NLA_TYPE_SIZE(type) nla_total_size(sizeof(type)) + + /* proto independant part */ + len = NLMSG_SPACE(sizeof(struct nfgenmsg)) + + 3 * nla_total_size(0) /* CTA_TUPLE_ORIG|REPL|MASTER */ + + 3 * nla_total_size(0) /* CTA_TUPLE_IP */ + + 3 * nla_total_size(0) /* CTA_TUPLE_PROTO */ + + 3 * NLA_TYPE_SIZE(u_int8_t) /* CTA_PROTO_NUM */ + + NLA_TYPE_SIZE(u_int32_t) /* CTA_ID */ + + NLA_TYPE_SIZE(u_int32_t) /* CTA_STATUS */ + + 2 * nla_total_size(0) /* CTA_COUNTERS_ORIG|REPL */ + + 2 * NLA_TYPE_SIZE(uint64_t) /* CTA_COUNTERS_PACKETS */ + + 2 * NLA_TYPE_SIZE(uint64_t) /* CTA_COUNTERS_BYTES */ + + NLA_TYPE_SIZE(u_int32_t) /* CTA_TIMEOUT */ + + nla_total_size(0) /* CTA_PROTOINFO */ + + nla_total_size(0) /* CTA_HELP */ + + nla_total_size(NF_CT_HELPER_NAME_LEN) /* CTA_HELP_NAME */ + + NLA_TYPE_SIZE(u_int32_t) /* CTA_SECMARK */ + + 2 * nla_total_size(0) /* CTA_NAT_SEQ_ADJ_ORIG|REPL */ + + 2 * NLA_TYPE_SIZE(u_int32_t) /* CTA_NAT_SEQ_CORRECTION_POS */ + + 2 * NLA_TYPE_SIZE(u_int32_t) /* CTA_NAT_SEQ_CORRECTION_BEFORE */ + + 2 * NLA_TYPE_SIZE(u_int32_t) /* CTA_NAT_SEQ_CORRECTION_AFTER */ + + NLA_TYPE_SIZE(u_int32_t); /* CTA_MARK */ + +#undef NLA_TYPE_SIZE + + rcu_read_lock(); + l3proto = __nf_ct_l3proto_find(tuple->src.l3num); + len += l3proto->nla_size; + + l4proto = __nf_ct_l4proto_find(tuple->src.l3num, tuple->dst.protonum); + len += l4proto->nla_size; + rcu_read_unlock(); + + return alloc_skb(len, gfp); +} + static int ctnetlink_conntrack_event(struct notifier_block *this, unsigned long events, void *ptr) { @@ -438,7 +501,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, if (!item->report && !nfnetlink_has_listeners(group)) return NOTIFY_DONE; - skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); + skb = ctnetlink_alloc_skb(tuple(ct, IP_CT_DIR_ORIGINAL), GFP_ATOMIC); if (!skb) return NOTIFY_DONE; -- GitLab From 5c0de29d06318ec8f6e3ba0d17d62529dbbdc1e8 Mon Sep 17 00:00:00 2001 From: Holger Eitzenberger Date: Wed, 25 Mar 2009 21:52:17 +0100 Subject: [PATCH 4549/4982] netfilter: nf_conntrack: add generic function to get len of generic policy Usefull for all protocols which do not add additional data, such as GRE or UDPlite. Signed-off-by: Holger Eitzenberger Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_conntrack_l4proto.h | 1 + net/netfilter/nf_conntrack_core.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h index a120990b3b2..ba32ed7bdab 100644 --- a/include/net/netfilter/nf_conntrack_l4proto.h +++ b/include/net/netfilter/nf_conntrack_l4proto.h @@ -113,6 +113,7 @@ extern int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb, const struct nf_conntrack_tuple *tuple); extern int nf_ct_port_nlattr_to_tuple(struct nlattr *tb[], struct nf_conntrack_tuple *t); +extern int nf_ct_port_nlattr_tuple_size(void); extern const struct nla_policy nf_ct_port_nla_policy[]; #ifdef CONFIG_SYSCTL diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index c55bbdc7d42..b182b30c7d8 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -921,6 +921,12 @@ int nf_ct_port_nlattr_to_tuple(struct nlattr *tb[], return 0; } EXPORT_SYMBOL_GPL(nf_ct_port_nlattr_to_tuple); + +int nf_ct_port_nlattr_tuple_size(void) +{ + return nla_policy_len(nf_ct_port_nla_policy, CTA_PROTO_MAX + 1); +} +EXPORT_SYMBOL_GPL(nf_ct_port_nlattr_tuple_size); #endif /* Used by ipt_REJECT and ip6t_REJECT. */ -- GitLab From a400c30edb1958ceb53c4b8ce78989189b36df47 Mon Sep 17 00:00:00 2001 From: Holger Eitzenberger Date: Wed, 25 Mar 2009 21:53:39 +0100 Subject: [PATCH 4550/4982] netfilter: nf_conntrack: calculate per-protocol nlattr size Signed-off-by: Holger Eitzenberger Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 6 ++++++ net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 6 ++++++ net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 6 ++++++ net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 6 ++++++ net/netfilter/nf_conntrack_proto_dccp.c | 9 +++++++++ net/netfilter/nf_conntrack_proto_gre.c | 1 + net/netfilter/nf_conntrack_proto_sctp.c | 10 ++++++++++ net/netfilter/nf_conntrack_proto_tcp.c | 15 +++++++++++++++ net/netfilter/nf_conntrack_proto_udp.c | 2 ++ net/netfilter/nf_conntrack_proto_udplite.c | 1 + 10 files changed, 62 insertions(+) diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 8b681f24e27..7d2ead7228a 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -328,6 +328,11 @@ static int ipv4_nlattr_to_tuple(struct nlattr *tb[], return 0; } + +static int ipv4_nlattr_tuple_size(void) +{ + return nla_policy_len(ipv4_nla_policy, CTA_IP_MAX + 1); +} #endif static struct nf_sockopt_ops so_getorigdst = { @@ -347,6 +352,7 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 __read_mostly = { .get_l4proto = ipv4_get_l4proto, #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nlattr = ipv4_tuple_to_nlattr, + .nlattr_tuple_size = ipv4_nlattr_tuple_size, .nlattr_to_tuple = ipv4_nlattr_to_tuple, .nla_policy = ipv4_nla_policy, #endif diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 2a8bee26f43..23b2c2ee869 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -262,6 +262,11 @@ static int icmp_nlattr_to_tuple(struct nlattr *tb[], return 0; } + +static int icmp_nlattr_tuple_size(void) +{ + return nla_policy_len(icmp_nla_policy, CTA_PROTO_MAX + 1); +} #endif #ifdef CONFIG_SYSCTL @@ -309,6 +314,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly = .me = NULL, #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nlattr = icmp_tuple_to_nlattr, + .nlattr_tuple_size = icmp_nlattr_tuple_size, .nlattr_to_tuple = icmp_nlattr_to_tuple, .nla_policy = icmp_nla_policy, #endif diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index e6852f61721..2a15c2d66c6 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -342,6 +342,11 @@ static int ipv6_nlattr_to_tuple(struct nlattr *tb[], return 0; } + +static int ipv6_nlattr_tuple_size(void) +{ + return nla_policy_len(ipv6_nla_policy, CTA_IP_MAX + 1); +} #endif struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = { @@ -353,6 +358,7 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = { .get_l4proto = ipv6_get_l4proto, #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nlattr = ipv6_tuple_to_nlattr, + .nlattr_tuple_size = ipv6_nlattr_tuple_size, .nlattr_to_tuple = ipv6_nlattr_to_tuple, .nla_policy = ipv6_nla_policy, #endif diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 165b256a6fa..032fdf41500 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -268,6 +268,11 @@ static int icmpv6_nlattr_to_tuple(struct nlattr *tb[], return 0; } + +static int icmpv6_nlattr_tuple_size(void) +{ + return nla_policy_len(icmpv6_nla_policy, CTA_PROTO_MAX + 1); +} #endif #ifdef CONFIG_SYSCTL @@ -299,6 +304,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly = .error = icmpv6_error, #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nlattr = icmpv6_tuple_to_nlattr, + .nlattr_tuple_size = icmpv6_nlattr_tuple_size, .nlattr_to_tuple = icmpv6_nlattr_to_tuple, .nla_policy = icmpv6_nla_policy, #endif diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index d3d5a7fd73c..50dac8dbe7d 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c @@ -669,6 +669,12 @@ static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct) write_unlock_bh(&dccp_lock); return 0; } + +static int dccp_nlattr_size(void) +{ + return nla_total_size(0) /* CTA_PROTOINFO_DCCP */ + + nla_policy_len(dccp_nla_policy, CTA_PROTOINFO_DCCP_MAX + 1); +} #endif #ifdef CONFIG_SYSCTL @@ -749,8 +755,10 @@ static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = { .print_conntrack = dccp_print_conntrack, #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .to_nlattr = dccp_to_nlattr, + .nlattr_size = dccp_nlattr_size, .from_nlattr = nlattr_to_dccp, .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, + .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy, #endif @@ -771,6 +779,7 @@ static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = { .to_nlattr = dccp_to_nlattr, .from_nlattr = nlattr_to_dccp, .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, + .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy, #endif diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c index 1b279f9d6bf..117b80112fc 100644 --- a/net/netfilter/nf_conntrack_proto_gre.c +++ b/net/netfilter/nf_conntrack_proto_gre.c @@ -293,6 +293,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = { .me = THIS_MODULE, #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, + .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy, #endif diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 74e03790119..101b4ad9e81 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c @@ -537,6 +537,12 @@ static int nlattr_to_sctp(struct nlattr *cda[], struct nf_conn *ct) return 0; } + +static int sctp_nlattr_size(void) +{ + return nla_total_size(0) /* CTA_PROTOINFO_SCTP */ + + nla_policy_len(sctp_nla_policy, CTA_PROTOINFO_SCTP_MAX + 1); +} #endif #ifdef CONFIG_SYSCTL @@ -668,8 +674,10 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = { .me = THIS_MODULE, #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .to_nlattr = sctp_to_nlattr, + .nlattr_size = sctp_nlattr_size, .from_nlattr = nlattr_to_sctp, .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, + .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy, #endif @@ -696,8 +704,10 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = { .me = THIS_MODULE, #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .to_nlattr = sctp_to_nlattr, + .nlattr_size = sctp_nlattr_size, .from_nlattr = nlattr_to_sctp, .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, + .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy, #endif diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 7d3944f02ea..9b9e6718b2d 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -1183,6 +1183,17 @@ static int nlattr_to_tcp(struct nlattr *cda[], struct nf_conn *ct) return 0; } + +static int tcp_nlattr_size(void) +{ + return nla_total_size(0) /* CTA_PROTOINFO_TCP */ + + nla_policy_len(tcp_nla_policy, CTA_PROTOINFO_TCP_MAX + 1); +} + +static int tcp_nlattr_tuple_size(void) +{ + return nla_policy_len(nf_ct_port_nla_policy, CTA_PROTO_MAX + 1); +} #endif #ifdef CONFIG_SYSCTL @@ -1398,9 +1409,11 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 __read_mostly = .error = tcp_error, #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .to_nlattr = tcp_to_nlattr, + .nlattr_size = tcp_nlattr_size, .from_nlattr = nlattr_to_tcp, .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, + .nlattr_tuple_size = tcp_nlattr_tuple_size, .nla_policy = nf_ct_port_nla_policy, #endif #ifdef CONFIG_SYSCTL @@ -1428,9 +1441,11 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 __read_mostly = .error = tcp_error, #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .to_nlattr = tcp_to_nlattr, + .nlattr_size = tcp_nlattr_size, .from_nlattr = nlattr_to_tcp, .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, + .nlattr_tuple_size = tcp_nlattr_tuple_size, .nla_policy = nf_ct_port_nla_policy, #endif #ifdef CONFIG_SYSCTL diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index d4021179e24..70809d117b9 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c @@ -195,6 +195,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly = #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, + .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, .nla_policy = nf_ct_port_nla_policy, #endif #ifdef CONFIG_SYSCTL @@ -222,6 +223,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 __read_mostly = #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, + .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, .nla_policy = nf_ct_port_nla_policy, #endif #ifdef CONFIG_SYSCTL diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c index 4579d8de13b..4614696c1b8 100644 --- a/net/netfilter/nf_conntrack_proto_udplite.c +++ b/net/netfilter/nf_conntrack_proto_udplite.c @@ -180,6 +180,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly = .error = udplite_error, #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, + .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy, #endif -- GitLab From 2a30ca8b1ec0e3c9b4a77113d5e8648b2fd56cae Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 24 Mar 2009 23:34:35 +0000 Subject: [PATCH 4551/4982] r6040: Fix second PHY address This patch fixes the second PHY address which is strapped to be at PHY address 3 instead of 2. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/r6040.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 9c95ebe643a..d3458efe642 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -54,7 +54,7 @@ /* PHY CHIP Address */ #define PHY1_ADDR 1 /* For MAC1 */ -#define PHY2_ADDR 2 /* For MAC2 */ +#define PHY2_ADDR 3 /* For MAC2 */ #define PHY_MODE 0x3100 /* PHY CHIP Register 0 */ #define PHY_CAP 0x01E1 /* PHY CHIP Register 4 */ -- GitLab From 8ca51986be0c19c8a48ef8f36568c5a3c2c0ac50 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 24 Mar 2009 23:34:38 +0000 Subject: [PATCH 4552/4982] Bump release date to 25Mar2009 and version to 0.22 This patch bumps the driver release date to March 25th 2009 and release version to 0.22. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/r6040.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index d3458efe642..0a37f9902a0 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -49,8 +49,8 @@ #include #define DRV_NAME "r6040" -#define DRV_VERSION "0.21" -#define DRV_RELDATE "09Jan2009" +#define DRV_VERSION "0.22" +#define DRV_RELDATE "25Mar2009" /* PHY CHIP Address */ #define PHY1_ADDR 1 /* For MAC1 */ -- GitLab From 93c1285c5d92c31f9bcc20355f1e86e95bec165e Mon Sep 17 00:00:00 2001 From: Li Yang Date: Tue, 24 Mar 2009 23:15:33 +0000 Subject: [PATCH 4553/4982] gianfar: reallocate skb when headroom is not enough for fcb Gianfar uses a hardware header FCB for offloading. However when used with bridging or IP forwarding, TX skb might not have enough headroom for the FCB. Reallocate skb for such cases. Signed-off-by: Li Yang Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 8a51df045e8..9d81e7a48db 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -1239,10 +1239,19 @@ static int gfar_enet_open(struct net_device *dev) return err; } -static inline struct txfcb *gfar_add_fcb(struct sk_buff *skb) +static inline struct txfcb *gfar_add_fcb(struct sk_buff **skbp) { - struct txfcb *fcb = (struct txfcb *)skb_push (skb, GMAC_FCB_LEN); - + struct txfcb *fcb; + struct sk_buff *skb = *skbp; + + if (unlikely(skb_headroom(skb) < GMAC_FCB_LEN)) { + struct sk_buff *old_skb = skb; + skb = skb_realloc_headroom(old_skb, GMAC_FCB_LEN); + if (!skb) + return NULL; + dev_kfree_skb_any(old_skb); + } + fcb = (struct txfcb *)skb_push(skb, GMAC_FCB_LEN); cacheable_memzero(fcb, GMAC_FCB_LEN); return fcb; @@ -1363,18 +1372,20 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Set up checksumming */ if (CHECKSUM_PARTIAL == skb->ip_summed) { - fcb = gfar_add_fcb(skb); - lstatus |= BD_LFLAG(TXBD_TOE); - gfar_tx_checksum(skb, fcb); + fcb = gfar_add_fcb(&skb); + if (likely(fcb != NULL)) { + lstatus |= BD_LFLAG(TXBD_TOE); + gfar_tx_checksum(skb, fcb); + } } if (priv->vlgrp && vlan_tx_tag_present(skb)) { - if (unlikely(NULL == fcb)) { - fcb = gfar_add_fcb(skb); + if (unlikely(NULL == fcb)) + fcb = gfar_add_fcb(&skb); + if (likely(fcb != NULL)) { lstatus |= BD_LFLAG(TXBD_TOE); + gfar_tx_vlan(skb, fcb); } - - gfar_tx_vlan(skb, fcb); } /* setup the TxBD length and buffer pointer for the first BD */ -- GitLab From 5a29f7893fbe681f1334285be7e41e56f0de666c Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 25 Mar 2009 17:23:38 -0700 Subject: [PATCH 4554/4982] bonding: select current active slave when enslaving device for mode tlb and alb I've hit an issue on my system when I've been using RealTek RTL8139D cards in bonding interface in mode balancing-alb. When I enslave a card, the current active slave (bond->curr_active_slave) is not set and the link is therefore not functional. ---- # cat /proc/net/bonding/bond0 Ethernet Channel Bonding Driver: v3.5.0 (November 4, 2008) Bonding Mode: adaptive load balancing Primary Slave: None Currently Active Slave: None MII Status: up MII Polling Interval (ms): 100 Up Delay (ms): 0 Down Delay (ms): 0 Slave Interface: eth1 MII Status: up Link Failure Count: 0 Permanent HW addr: 00:1f:1f:01:2f:22 ---- The thing that gets it right is when I unplug the cable and then I put it back into the NIC. Then the current active slave is set to eth1 and link is working just fine. Here is dmesg log with bonding DEBUG messages turned on: ---- ADDRCONF(NETDEV_UP): bond0: link is not ready event_dev: bond0, event: 1 IFF_MASTER event_dev: bond0, event: 8 IFF_MASTER bond_ioctl: master=bond0, cmd=35216 slave_dev=cac5d800: slave_dev->name=eth1: eth1: ! NETIF_F_VLAN_CHALLENGED event_dev: eth1, event: 8 eth1: link up, 100Mbps, full-duplex, lpa 0xC5E1 event_dev: eth1, event: 1 event_dev: eth1, event: 8 IFF_SLAVE Initial state of slave_dev is BOND_LINK_UP bonding: bond0: enslaving eth1 as an active interface with an up link. ADDRCONF(NETDEV_CHANGE): bond0: link becomes ready event_dev: bond0, event: 4 IFF_MASTER bond0: no IPv6 routers present <<<>>> eth1: link down event_dev: eth1, event: 4 IFF_SLAVE bonding: bond0: link status definitely down for interface eth1, disabling it event_dev: bond0, event: 4 IFF_MASTER <<<>>> eth1: link up, 100Mbps, full-duplex, lpa 0xC5E1 event_dev: eth1, event: 4 IFF_SLAVE bonding: bond0: link status definitely up for interface eth1. bonding: bond0: making interface eth1 the new active one. event_dev: eth1, event: 8 IFF_SLAVE event_dev: eth1, event: 8 IFF_SLAVE bonding: bond0: first active interface up! event_dev: bond0, event: 4 IFF_MASTER ---- The current active slave is set by calling bond_select_active_slave() function from bond_miimon_commit() function when the slave (eth1) link goes to state up. I also tested this on other machine with Broadcom NetXtreme II BCM5708 1000Base-T NIC and there all works fine. The thing is that this adapter is down and goes up after few seconds after it is enslaved. This patch calls bond_select_active_slave() in bond_enslave() function for modes alb and tlb and makes sure that the current active slave is set up properly even when the slave state is already up. Tested on both systems, works fine. Notice: The same problem can maybe also occrur in mode 8023AD but I'm unable to test that. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index dce3cf92c61..9c326a50a3e 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1714,6 +1714,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) case BOND_MODE_ALB: new_slave->state = BOND_STATE_ACTIVE; bond_set_slave_inactive_flags(new_slave); + bond_select_active_slave(bond); break; default: pr_debug("This slave is always active in trunk mode\n"); -- GitLab From f18df228997fb716990590d248663981a15f17d4 Mon Sep 17 00:00:00 2001 From: Mingming Cao Date: Tue, 13 Jan 2009 16:43:09 +0100 Subject: [PATCH 4555/4982] quota: Add quota reservation support Delayed allocation defers the block allocation at the dirty pages flush-out time, doing quota charge/check at that time is too late. But we can't charge the quota blocks until blocks are really allocated, otherwise users could get overcharged after reboot from system crash. This patch adds quota reservation for delayed allocation. Quota blocks are reserved in memory, inode and quota won't gets dirtied until later block allocation time. Signed-off-by: Mingming Cao Signed-off-by: Jan Kara --- fs/dquot.c | 117 ++++++++++++++++++++++++++++----------- include/linux/quota.h | 3 + include/linux/quotaops.h | 21 +++++++ 3 files changed, 110 insertions(+), 31 deletions(-) diff --git a/fs/dquot.c b/fs/dquot.c index bca3cac4bee..9b1c4d3c9d8 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -899,6 +899,11 @@ static inline void dquot_incr_space(struct dquot *dquot, qsize_t number) dquot->dq_dqb.dqb_curspace += number; } +static inline void dquot_resv_space(struct dquot *dquot, qsize_t number) +{ + dquot->dq_dqb.dqb_rsvspace += number; +} + static inline void dquot_decr_inodes(struct dquot *dquot, qsize_t number) { if (sb_dqopt(dquot->dq_sb)->flags & DQUOT_NEGATIVE_USAGE || @@ -1068,7 +1073,11 @@ err_out: kfree_skb(skb); } #endif - +/* + * Write warnings to the console and send warning messages over netlink. + * + * Note that this function can sleep. + */ static inline void flush_warnings(struct dquot * const *dquots, char *warntype) { int i; @@ -1129,13 +1138,18 @@ static int check_idq(struct dquot *dquot, qsize_t inodes, char *warntype) /* needs dq_data_lock */ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *warntype) { + qsize_t tspace; + *warntype = QUOTA_NL_NOWARN; if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type) || test_bit(DQ_FAKE_B, &dquot->dq_flags)) return QUOTA_OK; + tspace = dquot->dq_dqb.dqb_curspace + dquot->dq_dqb.dqb_rsvspace + + space; + if (dquot->dq_dqb.dqb_bhardlimit && - dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bhardlimit && + tspace > dquot->dq_dqb.dqb_bhardlimit && !ignore_hardlimit(dquot)) { if (!prealloc) *warntype = QUOTA_NL_BHARDWARN; @@ -1143,7 +1157,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war } if (dquot->dq_dqb.dqb_bsoftlimit && - dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bsoftlimit && + tspace > dquot->dq_dqb.dqb_bsoftlimit && dquot->dq_dqb.dqb_btime && get_seconds() >= dquot->dq_dqb.dqb_btime && !ignore_hardlimit(dquot)) { if (!prealloc) @@ -1152,7 +1166,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war } if (dquot->dq_dqb.dqb_bsoftlimit && - dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bsoftlimit && + tspace > dquot->dq_dqb.dqb_bsoftlimit && dquot->dq_dqb.dqb_btime == 0) { if (!prealloc) { *warntype = QUOTA_NL_BSOFTWARN; @@ -1306,51 +1320,92 @@ void vfs_dq_drop(struct inode *inode) /* * This operation can block, but only after everything is updated */ -int dquot_alloc_space(struct inode *inode, qsize_t number, int warn) +int __dquot_alloc_space(struct inode *inode, qsize_t number, + int warn, int reserve) { - int cnt, ret = NO_QUOTA; + int cnt, ret = QUOTA_OK; char warntype[MAXQUOTAS]; - /* First test before acquiring mutex - solves deadlocks when we - * re-enter the quota code and are already holding the mutex */ - if (IS_NOQUOTA(inode)) { -out_add: - inode_add_bytes(inode, number); - return QUOTA_OK; - } for (cnt = 0; cnt < MAXQUOTAS; cnt++) warntype[cnt] = QUOTA_NL_NOWARN; - down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); - if (IS_NOQUOTA(inode)) { /* Now we can do reliable test... */ - up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); - goto out_add; - } spin_lock(&dq_data_lock); for (cnt = 0; cnt < MAXQUOTAS; cnt++) { if (inode->i_dquot[cnt] == NODQUOT) continue; - if (check_bdq(inode->i_dquot[cnt], number, warn, warntype+cnt) == NO_QUOTA) - goto warn_put_all; + if (check_bdq(inode->i_dquot[cnt], number, warn, warntype+cnt) + == NO_QUOTA) { + ret = NO_QUOTA; + goto out_unlock; + } } for (cnt = 0; cnt < MAXQUOTAS; cnt++) { if (inode->i_dquot[cnt] == NODQUOT) continue; - dquot_incr_space(inode->i_dquot[cnt], number); + if (reserve) + dquot_resv_space(inode->i_dquot[cnt], number); + else + dquot_incr_space(inode->i_dquot[cnt], number); } - inode_add_bytes(inode, number); - ret = QUOTA_OK; -warn_put_all: + if (!reserve) + inode_add_bytes(inode, number); +out_unlock: spin_unlock(&dq_data_lock); - if (ret == QUOTA_OK) - /* Dirtify all the dquots - this can block when journalling */ - for (cnt = 0; cnt < MAXQUOTAS; cnt++) - if (inode->i_dquot[cnt]) - mark_dquot_dirty(inode->i_dquot[cnt]); flush_warnings(inode->i_dquot, warntype); + return ret; +} + +int dquot_alloc_space(struct inode *inode, qsize_t number, int warn) +{ + int cnt, ret = QUOTA_OK; + + /* + * First test before acquiring mutex - solves deadlocks when we + * re-enter the quota code and are already holding the mutex + */ + if (IS_NOQUOTA(inode)) { + inode_add_bytes(inode, number); + goto out; + } + + down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); + if (IS_NOQUOTA(inode)) { + inode_add_bytes(inode, number); + goto out_unlock; + } + + ret = __dquot_alloc_space(inode, number, warn, 0); + if (ret == NO_QUOTA) + goto out_unlock; + + /* Dirtify all the dquots - this can block when journalling */ + for (cnt = 0; cnt < MAXQUOTAS; cnt++) + if (inode->i_dquot[cnt]) + mark_dquot_dirty(inode->i_dquot[cnt]); +out_unlock: up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); +out: + return ret; +} + +int dquot_reserve_space(struct inode *inode, qsize_t number, int warn) +{ + int ret = QUOTA_OK; + + if (IS_NOQUOTA(inode)) + goto out; + + down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); + if (IS_NOQUOTA(inode)) + goto out_unlock; + + ret = __dquot_alloc_space(inode, number, warn, 1); +out_unlock: + up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); +out: return ret; } +EXPORT_SYMBOL(dquot_reserve_space); /* * This operation can block, but only after everything is updated @@ -2057,7 +2112,7 @@ static void do_get_dqblk(struct dquot *dquot, struct if_dqblk *di) spin_lock(&dq_data_lock); di->dqb_bhardlimit = stoqb(dm->dqb_bhardlimit); di->dqb_bsoftlimit = stoqb(dm->dqb_bsoftlimit); - di->dqb_curspace = dm->dqb_curspace; + di->dqb_curspace = dm->dqb_curspace + dm->dqb_rsvspace; di->dqb_ihardlimit = dm->dqb_ihardlimit; di->dqb_isoftlimit = dm->dqb_isoftlimit; di->dqb_curinodes = dm->dqb_curinodes; @@ -2097,7 +2152,7 @@ static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di) spin_lock(&dq_data_lock); if (di->dqb_valid & QIF_SPACE) { - dm->dqb_curspace = di->dqb_curspace; + dm->dqb_curspace = di->dqb_curspace - dm->dqb_rsvspace; check_blim = 1; __set_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags); } diff --git a/include/linux/quota.h b/include/linux/quota.h index d72d5d84fde..54b837fa64f 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h @@ -198,6 +198,7 @@ struct mem_dqblk { qsize_t dqb_bhardlimit; /* absolute limit on disk blks alloc */ qsize_t dqb_bsoftlimit; /* preferred limit on disk blks */ qsize_t dqb_curspace; /* current used space */ + qsize_t dqb_rsvspace; /* current reserved space for delalloc*/ qsize_t dqb_ihardlimit; /* absolute limit on allocated inodes */ qsize_t dqb_isoftlimit; /* preferred inode limit */ qsize_t dqb_curinodes; /* current # allocated inodes */ @@ -308,6 +309,8 @@ struct dquot_operations { int (*release_dquot) (struct dquot *); /* Quota is going to be deleted from disk */ int (*mark_dirty) (struct dquot *); /* Dquot is marked dirty */ int (*write_info) (struct super_block *, int); /* Write of quota "superblock" */ + /* reserve quota for delayed block allocation */ + int (*reserve_space) (struct inode *, qsize_t, int); }; /* Operations handling requests from userspace */ diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index 0b35b3a1be0..3e3a0d2874d 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -183,6 +183,16 @@ static inline int vfs_dq_alloc_space(struct inode *inode, qsize_t nr) return ret; } +static inline int vfs_dq_reserve_space(struct inode *inode, qsize_t nr) +{ + if (sb_any_quota_active(inode->i_sb)) { + /* Used space is updated in alloc_space() */ + if (inode->i_sb->dq_op->reserve_space(inode, nr, 0) == NO_QUOTA) + return 1; + } + return 0; +} + static inline int vfs_dq_alloc_inode(struct inode *inode) { if (sb_any_quota_active(inode->i_sb)) { @@ -339,6 +349,11 @@ static inline int vfs_dq_alloc_space(struct inode *inode, qsize_t nr) return 0; } +static inline int vfs_dq_reserve_space(struct inode *inode, qsize_t nr) +{ + return 0; +} + static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr) { inode_sub_bytes(inode, nr); @@ -376,6 +391,12 @@ static inline int vfs_dq_alloc_block(struct inode *inode, qsize_t nr) nr << inode->i_sb->s_blocksize_bits); } +static inline int vfs_dq_reserve_block(struct inode *inode, qsize_t nr) +{ + return vfs_dq_reserve_space(inode, + nr << inode->i_blkbits); +} + static inline void vfs_dq_free_block_nodirty(struct inode *inode, qsize_t nr) { vfs_dq_free_space_nodirty(inode, nr << inode->i_sb->s_blocksize_bits); -- GitLab From 740d9dcd949a986c88886a591054a0cdb89ef669 Mon Sep 17 00:00:00 2001 From: Mingming Cao Date: Tue, 13 Jan 2009 16:43:14 +0100 Subject: [PATCH 4556/4982] quota: Add quota reservation claim and released operations Reserved quota will be claimed at the block allocation time. Over-booked quota could be returned back with the release callback function. Signed-off-by: Mingming Cao Signed-off-by: Jan Kara --- fs/dquot.c | 110 +++++++++++++++++++++++++++++++++++++-- include/linux/quota.h | 6 +++ include/linux/quotaops.h | 53 +++++++++++++++++++ 3 files changed, 165 insertions(+), 4 deletions(-) diff --git a/fs/dquot.c b/fs/dquot.c index 9b1c4d3c9d8..2916f91ca40 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -904,6 +904,23 @@ static inline void dquot_resv_space(struct dquot *dquot, qsize_t number) dquot->dq_dqb.dqb_rsvspace += number; } +/* + * Claim reserved quota space + */ +static void dquot_claim_reserved_space(struct dquot *dquot, + qsize_t number) +{ + WARN_ON(dquot->dq_dqb.dqb_rsvspace < number); + dquot->dq_dqb.dqb_curspace += number; + dquot->dq_dqb.dqb_rsvspace -= number; +} + +static inline +void dquot_free_reserved_space(struct dquot *dquot, qsize_t number) +{ + dquot->dq_dqb.dqb_rsvspace -= number; +} + static inline void dquot_decr_inodes(struct dquot *dquot, qsize_t number) { if (sb_dqopt(dquot->dq_sb)->flags & DQUOT_NEGATIVE_USAGE || @@ -1452,6 +1469,72 @@ warn_put_all: return ret; } +int dquot_claim_space(struct inode *inode, qsize_t number) +{ + int cnt; + int ret = QUOTA_OK; + + if (IS_NOQUOTA(inode)) { + inode_add_bytes(inode, number); + goto out; + } + + down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); + if (IS_NOQUOTA(inode)) { + up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); + inode_add_bytes(inode, number); + goto out; + } + + spin_lock(&dq_data_lock); + /* Claim reserved quotas to allocated quotas */ + for (cnt = 0; cnt < MAXQUOTAS; cnt++) { + if (inode->i_dquot[cnt] != NODQUOT) + dquot_claim_reserved_space(inode->i_dquot[cnt], + number); + } + /* Update inode bytes */ + inode_add_bytes(inode, number); + spin_unlock(&dq_data_lock); + /* Dirtify all the dquots - this can block when journalling */ + for (cnt = 0; cnt < MAXQUOTAS; cnt++) + if (inode->i_dquot[cnt]) + mark_dquot_dirty(inode->i_dquot[cnt]); + up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); +out: + return ret; +} +EXPORT_SYMBOL(dquot_claim_space); + +/* + * Release reserved quota space + */ +void dquot_release_reserved_space(struct inode *inode, qsize_t number) +{ + int cnt; + + if (IS_NOQUOTA(inode)) + goto out; + + down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); + if (IS_NOQUOTA(inode)) + goto out_unlock; + + spin_lock(&dq_data_lock); + /* Release reserved dquots */ + for (cnt = 0; cnt < MAXQUOTAS; cnt++) { + if (inode->i_dquot[cnt] != NODQUOT) + dquot_free_reserved_space(inode->i_dquot[cnt], number); + } + spin_unlock(&dq_data_lock); + +out_unlock: + up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); +out: + return; +} +EXPORT_SYMBOL(dquot_release_reserved_space); + /* * This operation can block, but only after everything is updated */ @@ -1528,6 +1611,19 @@ int dquot_free_inode(const struct inode *inode, qsize_t number) return QUOTA_OK; } +/* + * call back function, get reserved quota space from underlying fs + */ +qsize_t dquot_get_reserved_space(struct inode *inode) +{ + qsize_t reserved_space = 0; + + if (sb_any_quota_active(inode->i_sb) && + inode->i_sb->dq_op->get_reserved_space) + reserved_space = inode->i_sb->dq_op->get_reserved_space(inode); + return reserved_space; +} + /* * Transfer the number of inode and blocks from one diskquota to an other. * @@ -1536,7 +1632,8 @@ int dquot_free_inode(const struct inode *inode, qsize_t number) */ int dquot_transfer(struct inode *inode, struct iattr *iattr) { - qsize_t space; + qsize_t space, cur_space; + qsize_t rsv_space = 0; struct dquot *transfer_from[MAXQUOTAS]; struct dquot *transfer_to[MAXQUOTAS]; int cnt, ret = QUOTA_OK; @@ -1575,7 +1672,9 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr) goto put_all; } spin_lock(&dq_data_lock); - space = inode_get_bytes(inode); + cur_space = inode_get_bytes(inode); + rsv_space = dquot_get_reserved_space(inode); + space = cur_space + rsv_space; /* Build the transfer_from list and check the limits */ for (cnt = 0; cnt < MAXQUOTAS; cnt++) { if (transfer_to[cnt] == NODQUOT) @@ -1604,11 +1703,14 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr) warntype_from_space[cnt] = info_bdq_free(transfer_from[cnt], space); dquot_decr_inodes(transfer_from[cnt], 1); - dquot_decr_space(transfer_from[cnt], space); + dquot_decr_space(transfer_from[cnt], cur_space); + dquot_free_reserved_space(transfer_from[cnt], + rsv_space); } dquot_incr_inodes(transfer_to[cnt], 1); - dquot_incr_space(transfer_to[cnt], space); + dquot_incr_space(transfer_to[cnt], cur_space); + dquot_resv_space(transfer_to[cnt], rsv_space); inode->i_dquot[cnt] = transfer_to[cnt]; } diff --git a/include/linux/quota.h b/include/linux/quota.h index 54b837fa64f..a510d91561f 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h @@ -311,6 +311,12 @@ struct dquot_operations { int (*write_info) (struct super_block *, int); /* Write of quota "superblock" */ /* reserve quota for delayed block allocation */ int (*reserve_space) (struct inode *, qsize_t, int); + /* claim reserved quota for delayed alloc */ + int (*claim_space) (struct inode *, qsize_t); + /* release rsved quota for delayed alloc */ + void (*release_rsv) (struct inode *, qsize_t); + /* get reserved quota for delayed alloc */ + qsize_t (*get_reserved_space) (struct inode *); }; /* Operations handling requests from userspace */ diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index 3e3a0d2874d..7369d04e0a8 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -35,6 +35,11 @@ void dquot_destroy(struct dquot *dquot); int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc); int dquot_alloc_inode(const struct inode *inode, qsize_t number); +int dquot_reserve_space(struct inode *inode, qsize_t number, int prealloc); +int dquot_claim_space(struct inode *inode, qsize_t number); +void dquot_release_reserved_space(struct inode *inode, qsize_t number); +qsize_t dquot_get_reserved_space(struct inode *inode); + int dquot_free_space(struct inode *inode, qsize_t number); int dquot_free_inode(const struct inode *inode, qsize_t number); @@ -203,6 +208,31 @@ static inline int vfs_dq_alloc_inode(struct inode *inode) return 0; } +/* + * Convert in-memory reserved quotas to real consumed quotas + */ +static inline int vfs_dq_claim_space(struct inode *inode, qsize_t nr) +{ + if (sb_any_quota_active(inode->i_sb)) { + if (inode->i_sb->dq_op->claim_space(inode, nr) == NO_QUOTA) + return 1; + } else + inode_add_bytes(inode, nr); + + mark_inode_dirty(inode); + return 0; +} + +/* + * Release reserved (in-memory) quotas + */ +static inline +void vfs_dq_release_reservation_space(struct inode *inode, qsize_t nr) +{ + if (sb_any_quota_active(inode->i_sb)) + inode->i_sb->dq_op->release_rsv(inode, nr); +} + static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr) { if (sb_any_quota_active(inode->i_sb)) @@ -354,6 +384,17 @@ static inline int vfs_dq_reserve_space(struct inode *inode, qsize_t nr) return 0; } +static inline int vfs_dq_claim_space(struct inode *inode, qsize_t nr) +{ + return vfs_dq_alloc_space(inode, nr); +} + +static inline +int vfs_dq_release_reservation_space(struct inode *inode, qsize_t nr) +{ + return 0; +} + static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr) { inode_sub_bytes(inode, nr); @@ -397,6 +438,18 @@ static inline int vfs_dq_reserve_block(struct inode *inode, qsize_t nr) nr << inode->i_blkbits); } +static inline int vfs_dq_claim_block(struct inode *inode, qsize_t nr) +{ + return vfs_dq_claim_space(inode, + nr << inode->i_blkbits); +} + +static inline +void vfs_dq_release_reservation_block(struct inode *inode, qsize_t nr) +{ + vfs_dq_release_reservation_space(inode, nr << inode->i_blkbits); +} + static inline void vfs_dq_free_block_nodirty(struct inode *inode, qsize_t nr) { vfs_dq_free_space_nodirty(inode, nr << inode->i_sb->s_blocksize_bits); -- GitLab From 9900ba3487f9ba392db30e12d210f768a90abb13 Mon Sep 17 00:00:00 2001 From: Mingming Cao Date: Wed, 14 Jan 2009 16:18:57 +0100 Subject: [PATCH 4557/4982] quota: Use inode->i_blkbits to get block bits Andrew has suggested to use inode->i_blkbits to get the block bits info, rather than use super block's blockbits. That should be faster and emit less code. Signed-off-by: Mingming Cao Signed-off-by: Jan Kara --- include/linux/quotaops.h | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index 7369d04e0a8..69b502e5eba 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -410,38 +410,32 @@ static inline void vfs_dq_free_space(struct inode *inode, qsize_t nr) static inline int vfs_dq_prealloc_block_nodirty(struct inode *inode, qsize_t nr) { - return vfs_dq_prealloc_space_nodirty(inode, - nr << inode->i_sb->s_blocksize_bits); + return vfs_dq_prealloc_space_nodirty(inode, nr << inode->i_blkbits); } static inline int vfs_dq_prealloc_block(struct inode *inode, qsize_t nr) { - return vfs_dq_prealloc_space(inode, - nr << inode->i_sb->s_blocksize_bits); + return vfs_dq_prealloc_space(inode, nr << inode->i_blkbits); } static inline int vfs_dq_alloc_block_nodirty(struct inode *inode, qsize_t nr) { - return vfs_dq_alloc_space_nodirty(inode, - nr << inode->i_sb->s_blocksize_bits); + return vfs_dq_alloc_space_nodirty(inode, nr << inode->i_blkbits); } static inline int vfs_dq_alloc_block(struct inode *inode, qsize_t nr) { - return vfs_dq_alloc_space(inode, - nr << inode->i_sb->s_blocksize_bits); + return vfs_dq_alloc_space(inode, nr << inode->i_blkbits); } static inline int vfs_dq_reserve_block(struct inode *inode, qsize_t nr) { - return vfs_dq_reserve_space(inode, - nr << inode->i_blkbits); + return vfs_dq_reserve_space(inode, nr << inode->i_blkbits); } static inline int vfs_dq_claim_block(struct inode *inode, qsize_t nr) { - return vfs_dq_claim_space(inode, - nr << inode->i_blkbits); + return vfs_dq_claim_space(inode, nr << inode->i_blkbits); } static inline @@ -452,12 +446,12 @@ void vfs_dq_release_reservation_block(struct inode *inode, qsize_t nr) static inline void vfs_dq_free_block_nodirty(struct inode *inode, qsize_t nr) { - vfs_dq_free_space_nodirty(inode, nr << inode->i_sb->s_blocksize_bits); + vfs_dq_free_space_nodirty(inode, nr << inode->i_blkbits); } static inline void vfs_dq_free_block(struct inode *inode, qsize_t nr) { - vfs_dq_free_space(inode, nr << inode->i_sb->s_blocksize_bits); + vfs_dq_free_space(inode, nr << inode->i_blkbits); } /* -- GitLab From 08d0350ce9d63b19b62498c7b6421c2a95246b95 Mon Sep 17 00:00:00 2001 From: Mingming Cao Date: Wed, 14 Jan 2009 16:19:32 +0100 Subject: [PATCH 4558/4982] quota: Move EXPORT_SYMBOL immediately next to the functions/varibles According to checkpatch: EXPORT_SYMBOL(foo); should immediately follow its function/variable Signed-off-by: Mingming Cao Signed-off-by: Jan Kara --- fs/dquot.c | 69 ++++++++++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/fs/dquot.c b/fs/dquot.c index 2916f91ca40..28aa1466760 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -132,6 +132,7 @@ static DEFINE_SPINLOCK(dq_list_lock); static DEFINE_SPINLOCK(dq_state_lock); DEFINE_SPINLOCK(dq_data_lock); +EXPORT_SYMBOL(dq_data_lock); static char *quotatypes[] = INITQFNAMES; static struct quota_format_type *quota_formats; /* List of registered formats */ @@ -148,6 +149,7 @@ int register_quota_format(struct quota_format_type *fmt) spin_unlock(&dq_list_lock); return 0; } +EXPORT_SYMBOL(register_quota_format); void unregister_quota_format(struct quota_format_type *fmt) { @@ -159,6 +161,7 @@ void unregister_quota_format(struct quota_format_type *fmt) *actqf = (*actqf)->qf_next; spin_unlock(&dq_list_lock); } +EXPORT_SYMBOL(unregister_quota_format); static struct quota_format_type *find_quota_format(int id) { @@ -215,6 +218,7 @@ static unsigned int dq_hash_bits, dq_hash_mask; static struct hlist_head *dquot_hash; struct dqstats dqstats; +EXPORT_SYMBOL(dqstats); static inline unsigned int hashfn(const struct super_block *sb, unsigned int id, int type) @@ -309,6 +313,7 @@ int dquot_mark_dquot_dirty(struct dquot *dquot) spin_unlock(&dq_list_lock); return 0; } +EXPORT_SYMBOL(dquot_mark_dquot_dirty); /* This function needs dq_list_lock */ static inline int clear_dquot_dirty(struct dquot *dquot) @@ -360,6 +365,7 @@ out_iolock: mutex_unlock(&dquot->dq_lock); return ret; } +EXPORT_SYMBOL(dquot_acquire); /* * Write dquot to disk @@ -389,6 +395,7 @@ out_sem: mutex_unlock(&dqopt->dqio_mutex); return ret; } +EXPORT_SYMBOL(dquot_commit); /* * Release dquot @@ -417,6 +424,7 @@ out_dqlock: mutex_unlock(&dquot->dq_lock); return ret; } +EXPORT_SYMBOL(dquot_release); void dquot_destroy(struct dquot *dquot) { @@ -516,6 +524,7 @@ out: mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); return ret; } +EXPORT_SYMBOL(dquot_scan_active); int vfs_quota_sync(struct super_block *sb, int type) { @@ -563,6 +572,7 @@ int vfs_quota_sync(struct super_block *sb, int type) return 0; } +EXPORT_SYMBOL(vfs_quota_sync); /* Free unused dquots from cache */ static void prune_dqcache(int count) @@ -672,6 +682,7 @@ we_slept: put_dquot_last(dquot); spin_unlock(&dq_list_lock); } +EXPORT_SYMBOL(dqput); struct dquot *dquot_alloc(struct super_block *sb, int type) { @@ -767,6 +778,7 @@ out: return dquot; } +EXPORT_SYMBOL(dqget); static int dqinit_needed(struct inode *inode, int type) { @@ -1282,6 +1294,7 @@ out_err: dqput(got[cnt]); return ret; } +EXPORT_SYMBOL(dquot_initialize); /* * Release all quotas referenced by inode @@ -1302,6 +1315,7 @@ int dquot_drop(struct inode *inode) dqput(put[cnt]); return 0; } +EXPORT_SYMBOL(dquot_drop); /* Wrapper to remove references to quota structures from inode */ void vfs_dq_drop(struct inode *inode) @@ -1324,6 +1338,7 @@ void vfs_dq_drop(struct inode *inode) inode->i_sb->dq_op->drop(inode); } } +EXPORT_SYMBOL(vfs_dq_drop); /* * Following four functions update i_blocks+i_bytes fields and @@ -1404,6 +1419,7 @@ out_unlock: out: return ret; } +EXPORT_SYMBOL(dquot_alloc_space); int dquot_reserve_space(struct inode *inode, qsize_t number, int warn) { @@ -1468,6 +1484,7 @@ warn_put_all: up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); return ret; } +EXPORT_SYMBOL(dquot_alloc_inode); int dquot_claim_space(struct inode *inode, qsize_t number) { @@ -1574,6 +1591,7 @@ out_sub: up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); return QUOTA_OK; } +EXPORT_SYMBOL(dquot_free_space); /* * This operation can block, but only after everything is updated @@ -1610,6 +1628,7 @@ int dquot_free_inode(const struct inode *inode, qsize_t number) up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); return QUOTA_OK; } +EXPORT_SYMBOL(dquot_free_inode); /* * call back function, get reserved quota space from underlying fs @@ -1746,6 +1765,7 @@ over_quota: ret = NO_QUOTA; goto warn_put_all; } +EXPORT_SYMBOL(dquot_transfer); /* Wrapper for transferring ownership of an inode */ int vfs_dq_transfer(struct inode *inode, struct iattr *iattr) @@ -1757,7 +1777,7 @@ int vfs_dq_transfer(struct inode *inode, struct iattr *iattr) } return 0; } - +EXPORT_SYMBOL(vfs_dq_transfer); /* * Write info of quota file to disk @@ -1772,6 +1792,7 @@ int dquot_commit_info(struct super_block *sb, int type) mutex_unlock(&dqopt->dqio_mutex); return ret; } +EXPORT_SYMBOL(dquot_commit_info); /* * Definitions of diskquota operations. @@ -1924,13 +1945,14 @@ put_inodes: } return ret; } +EXPORT_SYMBOL(vfs_quota_disable); int vfs_quota_off(struct super_block *sb, int type, int remount) { return vfs_quota_disable(sb, type, remount ? DQUOT_SUSPENDED : (DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED)); } - +EXPORT_SYMBOL(vfs_quota_off); /* * Turn quotas on on a device */ @@ -2087,6 +2109,7 @@ int vfs_quota_on_path(struct super_block *sb, int type, int format_id, DQUOT_LIMITS_ENABLED); return error; } +EXPORT_SYMBOL(vfs_quota_on_path); int vfs_quota_on(struct super_block *sb, int type, int format_id, char *name, int remount) @@ -2104,6 +2127,7 @@ int vfs_quota_on(struct super_block *sb, int type, int format_id, char *name, } return error; } +EXPORT_SYMBOL(vfs_quota_on); /* * More powerful function for turning on quotas allowing setting @@ -2150,6 +2174,7 @@ out_lock: load_quota: return vfs_load_quota_inode(inode, type, format_id, flags); } +EXPORT_SYMBOL(vfs_quota_enable); /* * This function is used when filesystem needs to initialize quotas @@ -2179,6 +2204,7 @@ out: dput(dentry); return error; } +EXPORT_SYMBOL(vfs_quota_on_mount); /* Wrapper to turn on quotas when remounting rw */ int vfs_dq_quota_on_remount(struct super_block *sb) @@ -2195,6 +2221,7 @@ int vfs_dq_quota_on_remount(struct super_block *sb) } return ret; } +EXPORT_SYMBOL(vfs_dq_quota_on_remount); static inline qsize_t qbtos(qsize_t blocks) { @@ -2236,6 +2263,7 @@ int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *d return 0; } +EXPORT_SYMBOL(vfs_get_dqblk); /* Generic routine for setting common part of quota structure */ static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di) @@ -2327,6 +2355,7 @@ int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *d out: return rc; } +EXPORT_SYMBOL(vfs_set_dqblk); /* Generic routine for getting common part of quota file information */ int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii) @@ -2348,6 +2377,7 @@ int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii) mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); return 0; } +EXPORT_SYMBOL(vfs_get_dqinfo); /* Generic routine for setting common part of quota file information */ int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii) @@ -2376,6 +2406,7 @@ out: mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); return err; } +EXPORT_SYMBOL(vfs_set_dqinfo); struct quotactl_ops vfs_quotactl_ops = { .quota_on = vfs_quota_on, @@ -2531,37 +2562,3 @@ static int __init dquot_init(void) return 0; } module_init(dquot_init); - -EXPORT_SYMBOL(register_quota_format); -EXPORT_SYMBOL(unregister_quota_format); -EXPORT_SYMBOL(dqstats); -EXPORT_SYMBOL(dq_data_lock); -EXPORT_SYMBOL(vfs_quota_enable); -EXPORT_SYMBOL(vfs_quota_on); -EXPORT_SYMBOL(vfs_quota_on_path); -EXPORT_SYMBOL(vfs_quota_on_mount); -EXPORT_SYMBOL(vfs_quota_disable); -EXPORT_SYMBOL(vfs_quota_off); -EXPORT_SYMBOL(dquot_scan_active); -EXPORT_SYMBOL(vfs_quota_sync); -EXPORT_SYMBOL(vfs_get_dqinfo); -EXPORT_SYMBOL(vfs_set_dqinfo); -EXPORT_SYMBOL(vfs_get_dqblk); -EXPORT_SYMBOL(vfs_set_dqblk); -EXPORT_SYMBOL(dquot_commit); -EXPORT_SYMBOL(dquot_commit_info); -EXPORT_SYMBOL(dquot_acquire); -EXPORT_SYMBOL(dquot_release); -EXPORT_SYMBOL(dquot_mark_dquot_dirty); -EXPORT_SYMBOL(dquot_initialize); -EXPORT_SYMBOL(dquot_drop); -EXPORT_SYMBOL(vfs_dq_drop); -EXPORT_SYMBOL(dqget); -EXPORT_SYMBOL(dqput); -EXPORT_SYMBOL(dquot_alloc_space); -EXPORT_SYMBOL(dquot_alloc_inode); -EXPORT_SYMBOL(dquot_free_space); -EXPORT_SYMBOL(dquot_free_inode); -EXPORT_SYMBOL(dquot_transfer); -EXPORT_SYMBOL(vfs_dq_transfer); -EXPORT_SYMBOL(vfs_dq_quota_on_remount); -- GitLab From a219ce3748bbc596cec85c44754b3f6b994f1e1d Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 12 Jan 2009 19:03:19 +0100 Subject: [PATCH 4559/4982] ext3: Remove unnecessary quota functions ext3_dquot_initialize() and ext3_dquot_drop() is no longer needed because of modified quota locking. Signed-off-by: Jan Kara --- fs/ext3/super.c | 44 ++------------------------------------------ 1 file changed, 2 insertions(+), 42 deletions(-) diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 4a970411a45..41e6ae605e0 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -707,8 +707,6 @@ static int bdev_try_to_free_page(struct super_block *sb, struct page *page, #define QTYPE2NAME(t) ((t)==USRQUOTA?"user":"group") #define QTYPE2MOPT(on, t) ((t)==USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA)) -static int ext3_dquot_initialize(struct inode *inode, int type); -static int ext3_dquot_drop(struct inode *inode); static int ext3_write_dquot(struct dquot *dquot); static int ext3_acquire_dquot(struct dquot *dquot); static int ext3_release_dquot(struct dquot *dquot); @@ -723,8 +721,8 @@ static ssize_t ext3_quota_write(struct super_block *sb, int type, const char *data, size_t len, loff_t off); static struct dquot_operations ext3_quota_operations = { - .initialize = ext3_dquot_initialize, - .drop = ext3_dquot_drop, + .initialize = dquot_initialize, + .drop = dquot_drop, .alloc_space = dquot_alloc_space, .alloc_inode = dquot_alloc_inode, .free_space = dquot_free_space, @@ -2714,44 +2712,6 @@ static inline struct inode *dquot_to_inode(struct dquot *dquot) return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type]; } -static int ext3_dquot_initialize(struct inode *inode, int type) -{ - handle_t *handle; - int ret, err; - - /* We may create quota structure so we need to reserve enough blocks */ - handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS(inode->i_sb)); - if (IS_ERR(handle)) - return PTR_ERR(handle); - ret = dquot_initialize(inode, type); - err = ext3_journal_stop(handle); - if (!ret) - ret = err; - return ret; -} - -static int ext3_dquot_drop(struct inode *inode) -{ - handle_t *handle; - int ret, err; - - /* We may delete quota structure so we need to reserve enough blocks */ - handle = ext3_journal_start(inode, 2*EXT3_QUOTA_DEL_BLOCKS(inode->i_sb)); - if (IS_ERR(handle)) { - /* - * We call dquot_drop() anyway to at least release references - * to quota structures so that umount does not hang. - */ - dquot_drop(inode); - return PTR_ERR(handle); - } - ret = dquot_drop(inode); - err = ext3_journal_stop(handle); - if (!ret) - ret = err; - return ret; -} - static int ext3_write_dquot(struct dquot *dquot) { int ret, err; -- GitLab From edf7245362f7b8b8c76c4a6cad3604bf80884848 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 12 Jan 2009 19:05:26 +0100 Subject: [PATCH 4560/4982] ext4: Remove unnecessary quota functions ext4_dquot_initialize() and ext4_dquot_drop() is no longer needed because of modified quota locking. Signed-off-by: Jan Kara --- fs/ext4/super.c | 44 ++------------------------------------------ 1 file changed, 2 insertions(+), 42 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 39d1993cfa1..41f879497f9 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -926,8 +926,6 @@ static int bdev_try_to_free_page(struct super_block *sb, struct page *page, gfp_ #define QTYPE2NAME(t) ((t) == USRQUOTA ? "user" : "group") #define QTYPE2MOPT(on, t) ((t) == USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA)) -static int ext4_dquot_initialize(struct inode *inode, int type); -static int ext4_dquot_drop(struct inode *inode); static int ext4_write_dquot(struct dquot *dquot); static int ext4_acquire_dquot(struct dquot *dquot); static int ext4_release_dquot(struct dquot *dquot); @@ -942,8 +940,8 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type, const char *data, size_t len, loff_t off); static struct dquot_operations ext4_quota_operations = { - .initialize = ext4_dquot_initialize, - .drop = ext4_dquot_drop, + .initialize = dquot_initialize, + .drop = dquot_drop, .alloc_space = dquot_alloc_space, .alloc_inode = dquot_alloc_inode, .free_space = dquot_free_space, @@ -3380,44 +3378,6 @@ static inline struct inode *dquot_to_inode(struct dquot *dquot) return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type]; } -static int ext4_dquot_initialize(struct inode *inode, int type) -{ - handle_t *handle; - int ret, err; - - /* We may create quota structure so we need to reserve enough blocks */ - handle = ext4_journal_start(inode, 2*EXT4_QUOTA_INIT_BLOCKS(inode->i_sb)); - if (IS_ERR(handle)) - return PTR_ERR(handle); - ret = dquot_initialize(inode, type); - err = ext4_journal_stop(handle); - if (!ret) - ret = err; - return ret; -} - -static int ext4_dquot_drop(struct inode *inode) -{ - handle_t *handle; - int ret, err; - - /* We may delete quota structure so we need to reserve enough blocks */ - handle = ext4_journal_start(inode, 2*EXT4_QUOTA_DEL_BLOCKS(inode->i_sb)); - if (IS_ERR(handle)) { - /* - * We call dquot_drop() anyway to at least release references - * to quota structures so that umount does not hang. - */ - dquot_drop(inode); - return PTR_ERR(handle); - } - ret = dquot_drop(inode); - err = ext4_journal_stop(handle); - if (!ret) - ret = err; - return ret; -} - static int ext4_write_dquot(struct dquot *dquot) { int ret, err; -- GitLab From 643d00ccc311664188c8209bf8b596a30e139c3a Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 12 Jan 2009 19:07:14 +0100 Subject: [PATCH 4561/4982] reiserfs: Remove unnecessary quota functions reiserfs_dquot_initialize() and reiserfs_dquot_drop() is no longer needed because of modified quota locking. Signed-off-by: Jan Kara --- fs/reiserfs/super.c | 58 ++------------------------------------------- 1 file changed, 2 insertions(+), 56 deletions(-) diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index f3c820b7582..317c0352163 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -629,8 +629,6 @@ static const struct super_operations reiserfs_sops = { #ifdef CONFIG_QUOTA #define QTYPE2NAME(t) ((t)==USRQUOTA?"user":"group") -static int reiserfs_dquot_initialize(struct inode *, int); -static int reiserfs_dquot_drop(struct inode *); static int reiserfs_write_dquot(struct dquot *); static int reiserfs_acquire_dquot(struct dquot *); static int reiserfs_release_dquot(struct dquot *); @@ -639,8 +637,8 @@ static int reiserfs_write_info(struct super_block *, int); static int reiserfs_quota_on(struct super_block *, int, int, char *, int); static struct dquot_operations reiserfs_quota_operations = { - .initialize = reiserfs_dquot_initialize, - .drop = reiserfs_dquot_drop, + .initialize = dquot_initialize, + .drop = dquot_drop, .alloc_space = dquot_alloc_space, .alloc_inode = dquot_alloc_inode, .free_space = dquot_free_space, @@ -1896,58 +1894,6 @@ static int reiserfs_statfs(struct dentry *dentry, struct kstatfs *buf) } #ifdef CONFIG_QUOTA -static int reiserfs_dquot_initialize(struct inode *inode, int type) -{ - struct reiserfs_transaction_handle th; - int ret, err; - - /* We may create quota structure so we need to reserve enough blocks */ - reiserfs_write_lock(inode->i_sb); - ret = - journal_begin(&th, inode->i_sb, - 2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb)); - if (ret) - goto out; - ret = dquot_initialize(inode, type); - err = - journal_end(&th, inode->i_sb, - 2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb)); - if (!ret && err) - ret = err; - out: - reiserfs_write_unlock(inode->i_sb); - return ret; -} - -static int reiserfs_dquot_drop(struct inode *inode) -{ - struct reiserfs_transaction_handle th; - int ret, err; - - /* We may delete quota structure so we need to reserve enough blocks */ - reiserfs_write_lock(inode->i_sb); - ret = - journal_begin(&th, inode->i_sb, - 2 * REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb)); - if (ret) { - /* - * We call dquot_drop() anyway to at least release references - * to quota structures so that umount does not hang. - */ - dquot_drop(inode); - goto out; - } - ret = dquot_drop(inode); - err = - journal_end(&th, inode->i_sb, - 2 * REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb)); - if (!ret && err) - ret = err; - out: - reiserfs_write_unlock(inode->i_sb); - return ret; -} - static int reiserfs_write_dquot(struct dquot *dquot) { struct reiserfs_transaction_handle th; -- GitLab From 60e58e0f30e723464c2a7d34b71b8675566c572d Mon Sep 17 00:00:00 2001 From: Mingming Cao Date: Thu, 22 Jan 2009 18:13:05 +0100 Subject: [PATCH 4562/4982] ext4: quota reservation for delayed allocation Uses quota reservation/claim/release to handle quota properly for delayed allocation in the three steps: 1) quotas are reserved when data being copied to cache when block allocation is defered 2) when new blocks are allocated. reserved quotas are converted to the real allocated quota, 2) over-booked quotas for metadata blocks are released back. Signed-off-by: Mingming Cao Acked-by: "Theodore Ts'o" Signed-off-by: Jan Kara --- fs/ext4/ext4.h | 2 ++ fs/ext4/inode.c | 36 +++++++++++++++++++++++++++++++++--- fs/ext4/mballoc.c | 44 ++++++++++++++++++++++++++------------------ fs/ext4/super.c | 4 ++++ 4 files changed, 65 insertions(+), 21 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index b0c87dce66a..6083bb38057 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -20,6 +20,7 @@ #include #include #include +#include #include "ext4_i.h" /* @@ -1098,6 +1099,7 @@ extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks); extern int ext4_block_truncate_page(handle_t *handle, struct address_space *mapping, loff_t from); extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct page *page); +extern qsize_t ext4_get_reserved_space(struct inode *inode); /* ioctl.c */ extern long ext4_ioctl(struct file *, unsigned int, unsigned long); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index c7fed5b1874..8290cfbd9fa 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -975,6 +975,17 @@ out: return err; } +qsize_t ext4_get_reserved_space(struct inode *inode) +{ + unsigned long long total; + + spin_lock(&EXT4_I(inode)->i_block_reservation_lock); + total = EXT4_I(inode)->i_reserved_data_blocks + + EXT4_I(inode)->i_reserved_meta_blocks; + spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); + + return total; +} /* * Calculate the number of metadata blocks need to reserve * to allocate @blocks for non extent file based file @@ -1036,8 +1047,14 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used) /* update per-inode reservations */ BUG_ON(used > EXT4_I(inode)->i_reserved_data_blocks); EXT4_I(inode)->i_reserved_data_blocks -= used; - spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); + + /* + * free those over-booking quota for metadata blocks + */ + + if (mdb_free) + vfs_dq_release_reservation_block(inode, mdb_free); } /* @@ -1553,8 +1570,8 @@ static int ext4_journalled_write_end(struct file *file, static int ext4_da_reserve_space(struct inode *inode, int nrblocks) { int retries = 0; - struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); - unsigned long md_needed, mdblocks, total = 0; + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); + unsigned long md_needed, mdblocks, total = 0; /* * recalculate the amount of metadata blocks to reserve @@ -1570,12 +1587,23 @@ repeat: md_needed = mdblocks - EXT4_I(inode)->i_reserved_meta_blocks; total = md_needed + nrblocks; + /* + * Make quota reservation here to prevent quota overflow + * later. Real quota accounting is done at pages writeout + * time. + */ + if (vfs_dq_reserve_block(inode, total)) { + spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); + return -EDQUOT; + } + if (ext4_claim_free_blocks(sbi, total)) { spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); if (ext4_should_retry_alloc(inode->i_sb, &retries)) { yield(); goto repeat; } + vfs_dq_release_reservation_block(inode, total); return -ENOSPC; } EXT4_I(inode)->i_reserved_data_blocks += nrblocks; @@ -1629,6 +1657,8 @@ static void ext4_da_release_space(struct inode *inode, int to_free) BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks); EXT4_I(inode)->i_reserved_meta_blocks = mdb; spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); + + vfs_dq_release_reservation_block(inode, release); } static void ext4_da_page_release_reservation(struct page *page, diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 9f61e62f435..4de42090c41 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -3086,9 +3086,12 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, if (!(ac->ac_flags & EXT4_MB_DELALLOC_RESERVED)) /* release all the reserved blocks if non delalloc */ percpu_counter_sub(&sbi->s_dirtyblocks_counter, reserv_blks); - else + else { percpu_counter_sub(&sbi->s_dirtyblocks_counter, ac->ac_b_ex.fe_len); + /* convert reserved quota blocks to real quota blocks */ + vfs_dq_claim_block(ac->ac_inode, ac->ac_b_ex.fe_len); + } if (sbi->s_log_groups_per_flex) { ext4_group_t flex_group = ext4_flex_group(sbi, @@ -4544,7 +4547,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, struct ext4_sb_info *sbi; struct super_block *sb; ext4_fsblk_t block = 0; - unsigned int inquota; + unsigned int inquota = 0; unsigned int reserv_blks = 0; sb = ar->inode->i_sb; @@ -4562,9 +4565,17 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, (unsigned long long) ar->pleft, (unsigned long long) ar->pright); - if (!EXT4_I(ar->inode)->i_delalloc_reserved_flag) { - /* - * With delalloc we already reserved the blocks + /* + * For delayed allocation, we could skip the ENOSPC and + * EDQUOT check, as blocks and quotas have been already + * reserved when data being copied into pagecache. + */ + if (EXT4_I(ar->inode)->i_delalloc_reserved_flag) + ar->flags |= EXT4_MB_DELALLOC_RESERVED; + else { + /* Without delayed allocation we need to verify + * there is enough free blocks to do block allocation + * and verify allocation doesn't exceed the quota limits. */ while (ar->len && ext4_claim_free_blocks(sbi, ar->len)) { /* let others to free the space */ @@ -4576,19 +4587,16 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, return 0; } reserv_blks = ar->len; + while (ar->len && DQUOT_ALLOC_BLOCK(ar->inode, ar->len)) { + ar->flags |= EXT4_MB_HINT_NOPREALLOC; + ar->len--; + } + inquota = ar->len; + if (ar->len == 0) { + *errp = -EDQUOT; + goto out3; + } } - while (ar->len && DQUOT_ALLOC_BLOCK(ar->inode, ar->len)) { - ar->flags |= EXT4_MB_HINT_NOPREALLOC; - ar->len--; - } - if (ar->len == 0) { - *errp = -EDQUOT; - goto out3; - } - inquota = ar->len; - - if (EXT4_I(ar->inode)->i_delalloc_reserved_flag) - ar->flags |= EXT4_MB_DELALLOC_RESERVED; ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS); if (!ac) { @@ -4654,7 +4662,7 @@ repeat: out2: kmem_cache_free(ext4_ac_cachep, ac); out1: - if (ar->len < inquota) + if (inquota && ar->len < inquota) DQUOT_FREE_BLOCK(ar->inode, inquota - ar->len); out3: if (!ar->len) { diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 41f879497f9..5a238e9c71c 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -943,6 +943,10 @@ static struct dquot_operations ext4_quota_operations = { .initialize = dquot_initialize, .drop = dquot_drop, .alloc_space = dquot_alloc_space, + .reserve_space = dquot_reserve_space, + .claim_space = dquot_claim_space, + .release_rsv = dquot_release_reserved_space, + .get_reserved_space = ext4_get_reserved_space, .alloc_inode = dquot_alloc_inode, .free_space = dquot_free_space, .free_inode = dquot_free_inode, -- GitLab From 884d179dff3aa98a73c3ba9dee05fd6050d664f0 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 26 Jan 2009 15:28:09 +0100 Subject: [PATCH 4563/4982] quota: Move quota files into separate directory Quota subsystem has more and more files. It's time to create a dir for it. Signed-off-by: Jan Kara --- fs/Kconfig | 56 +---------------------------------- fs/Makefile | 6 +--- fs/quota/Kconfig | 59 +++++++++++++++++++++++++++++++++++++ fs/quota/Makefile | 14 +++++++++ fs/{ => quota}/dquot.c | 0 fs/{ => quota}/quota.c | 0 fs/{ => quota}/quota_tree.c | 0 fs/{ => quota}/quota_tree.h | 0 fs/{ => quota}/quota_v1.c | 0 fs/{ => quota}/quota_v2.c | 0 fs/{ => quota}/quotaio_v1.h | 0 fs/{ => quota}/quotaio_v2.h | 0 12 files changed, 75 insertions(+), 60 deletions(-) create mode 100644 fs/quota/Kconfig create mode 100644 fs/quota/Makefile rename fs/{ => quota}/dquot.c (100%) rename fs/{ => quota}/quota.c (100%) rename fs/{ => quota}/quota_tree.c (100%) rename fs/{ => quota}/quota_tree.h (100%) rename fs/{ => quota}/quota_v1.c (100%) rename fs/{ => quota}/quota_v2.c (100%) rename fs/{ => quota}/quotaio_v1.h (100%) rename fs/{ => quota}/quotaio_v2.h (100%) diff --git a/fs/Kconfig b/fs/Kconfig index 93945dd0b1a..cef8b18ceaa 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -56,61 +56,7 @@ endif # BLOCK source "fs/notify/Kconfig" -config QUOTA - bool "Quota support" - help - If you say Y here, you will be able to set per user limits for disk - usage (also called disk quotas). Currently, it works for the - ext2, ext3, and reiserfs file system. ext3 also supports journalled - quotas for which you don't need to run quotacheck(8) after an unclean - shutdown. - For further details, read the Quota mini-HOWTO, available from - , or the documentation provided - with the quota tools. Probably the quota support is only useful for - multi user systems. If unsure, say N. - -config QUOTA_NETLINK_INTERFACE - bool "Report quota messages through netlink interface" - depends on QUOTA && NET - help - If you say Y here, quota warnings (about exceeding softlimit, reaching - hardlimit, etc.) will be reported through netlink interface. If unsure, - say Y. - -config PRINT_QUOTA_WARNING - bool "Print quota warnings to console (OBSOLETE)" - depends on QUOTA - default y - help - If you say Y here, quota warnings (about exceeding softlimit, reaching - hardlimit, etc.) will be printed to the process' controlling terminal. - Note that this behavior is currently deprecated and may go away in - future. Please use notification via netlink socket instead. - -# Generic support for tree structured quota files. Seleted when needed. -config QUOTA_TREE - tristate - -config QFMT_V1 - tristate "Old quota format support" - depends on QUOTA - help - This quota format was (is) used by kernels earlier than 2.4.22. If - you have quota working and you don't want to convert to new quota - format say Y here. - -config QFMT_V2 - tristate "Quota format v2 support" - depends on QUOTA - select QUOTA_TREE - help - This quota format allows using quotas with 32-bit UIDs/GIDs. If you - need this functionality say Y here. - -config QUOTACTL - bool - depends on XFS_QUOTA || QUOTA - default y +source "fs/quota/Kconfig" source "fs/autofs/Kconfig" source "fs/autofs4/Kconfig" diff --git a/fs/Makefile b/fs/Makefile index dc20db34867..6e82a307bcd 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -51,11 +51,7 @@ obj-$(CONFIG_FS_POSIX_ACL) += posix_acl.o xattr_acl.o obj-$(CONFIG_NFS_COMMON) += nfs_common/ obj-$(CONFIG_GENERIC_ACL) += generic_acl.o -obj-$(CONFIG_QUOTA) += dquot.o -obj-$(CONFIG_QFMT_V1) += quota_v1.o -obj-$(CONFIG_QFMT_V2) += quota_v2.o -obj-$(CONFIG_QUOTA_TREE) += quota_tree.o -obj-$(CONFIG_QUOTACTL) += quota.o +obj-y += quota/ obj-$(CONFIG_PROC_FS) += proc/ obj-y += partitions/ diff --git a/fs/quota/Kconfig b/fs/quota/Kconfig new file mode 100644 index 00000000000..d9750d86fde --- /dev/null +++ b/fs/quota/Kconfig @@ -0,0 +1,59 @@ +# +# Quota configuration +# + +config QUOTA + bool "Quota support" + help + If you say Y here, you will be able to set per user limits for disk + usage (also called disk quotas). Currently, it works for the + ext2, ext3, and reiserfs file system. ext3 also supports journalled + quotas for which you don't need to run quotacheck(8) after an unclean + shutdown. + For further details, read the Quota mini-HOWTO, available from + , or the documentation provided + with the quota tools. Probably the quota support is only useful for + multi user systems. If unsure, say N. + +config QUOTA_NETLINK_INTERFACE + bool "Report quota messages through netlink interface" + depends on QUOTA && NET + help + If you say Y here, quota warnings (about exceeding softlimit, reaching + hardlimit, etc.) will be reported through netlink interface. If unsure, + say Y. + +config PRINT_QUOTA_WARNING + bool "Print quota warnings to console (OBSOLETE)" + depends on QUOTA + default y + help + If you say Y here, quota warnings (about exceeding softlimit, reaching + hardlimit, etc.) will be printed to the process' controlling terminal. + Note that this behavior is currently deprecated and may go away in + future. Please use notification via netlink socket instead. + +# Generic support for tree structured quota files. Seleted when needed. +config QUOTA_TREE + tristate + +config QFMT_V1 + tristate "Old quota format support" + depends on QUOTA + help + This quota format was (is) used by kernels earlier than 2.4.22. If + you have quota working and you don't want to convert to new quota + format say Y here. + +config QFMT_V2 + tristate "Quota format v2 support" + depends on QUOTA + select QUOTA_TREE + help + This quota format allows using quotas with 32-bit UIDs/GIDs. If you + need this functionality say Y here. + +config QUOTACTL + bool + depends on XFS_QUOTA || QUOTA + default y diff --git a/fs/quota/Makefile b/fs/quota/Makefile new file mode 100644 index 00000000000..385a0831cc9 --- /dev/null +++ b/fs/quota/Makefile @@ -0,0 +1,14 @@ +# +# Makefile for the Linux filesystems. +# +# 14 Sep 2000, Christoph Hellwig +# Rewritten to use lists instead of if-statements. +# + +obj-y := + +obj-$(CONFIG_QUOTA) += dquot.o +obj-$(CONFIG_QFMT_V1) += quota_v1.o +obj-$(CONFIG_QFMT_V2) += quota_v2.o +obj-$(CONFIG_QUOTA_TREE) += quota_tree.o +obj-$(CONFIG_QUOTACTL) += quota.o diff --git a/fs/dquot.c b/fs/quota/dquot.c similarity index 100% rename from fs/dquot.c rename to fs/quota/dquot.c diff --git a/fs/quota.c b/fs/quota/quota.c similarity index 100% rename from fs/quota.c rename to fs/quota/quota.c diff --git a/fs/quota_tree.c b/fs/quota/quota_tree.c similarity index 100% rename from fs/quota_tree.c rename to fs/quota/quota_tree.c diff --git a/fs/quota_tree.h b/fs/quota/quota_tree.h similarity index 100% rename from fs/quota_tree.h rename to fs/quota/quota_tree.h diff --git a/fs/quota_v1.c b/fs/quota/quota_v1.c similarity index 100% rename from fs/quota_v1.c rename to fs/quota/quota_v1.c diff --git a/fs/quota_v2.c b/fs/quota/quota_v2.c similarity index 100% rename from fs/quota_v2.c rename to fs/quota/quota_v2.c diff --git a/fs/quotaio_v1.h b/fs/quota/quotaio_v1.h similarity index 100% rename from fs/quotaio_v1.h rename to fs/quota/quotaio_v1.h diff --git a/fs/quotaio_v2.h b/fs/quota/quotaio_v2.h similarity index 100% rename from fs/quotaio_v2.h rename to fs/quota/quotaio_v2.h -- GitLab From c516610cfec5c50f84ff8cc315628548481f4990 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 26 Jan 2009 15:32:46 +0100 Subject: [PATCH 4564/4982] quota: Make global quota locks cacheline aligned Andrew Morton has suggested that three global quota locks can end up in the same cacheline which can result in bad cacheline ping-pong on SMP machines. Make locks cacheline aligned so that we avoid this problem (thanks goes to Andrew for the idea). Signed-off-by: Jan Kara CC: Andrew Morton --- fs/quota/dquot.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 28aa1466760..e840fa2b112 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -129,9 +129,9 @@ * i_mutex on quota files is special (it's below dqio_mutex) */ -static DEFINE_SPINLOCK(dq_list_lock); -static DEFINE_SPINLOCK(dq_state_lock); -DEFINE_SPINLOCK(dq_data_lock); +static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_list_lock); +static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_state_lock); +__cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_data_lock); EXPORT_SYMBOL(dq_data_lock); static char *quotatypes[] = INITQFNAMES; -- GitLab From dd6f3c6d5a26a282521f15a183fdc2d6f35cfa0f Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 26 Jan 2009 16:01:43 +0100 Subject: [PATCH 4565/4982] quota: Remove NODQUOT macro Remove this macro which is just a definition of NULL. Fix a few coding style issues along the way. Signed-off-by: Jan Kara --- fs/quota/dquot.c | 70 ++++++++++++++++++++++--------------------- include/linux/quota.h | 2 -- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index e840fa2b112..4881db32e56 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -253,7 +253,7 @@ static inline struct dquot *find_dquot(unsigned int hashent, struct super_block if (dquot->dq_sb == sb && dquot->dq_id == id && dquot->dq_type == type) return dquot; } - return NODQUOT; + return NULL; } /* Add a dquot to the tail of the free list */ @@ -696,7 +696,7 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type) dquot = sb->dq_op->alloc_dquot(sb, type); if(!dquot) - return NODQUOT; + return NULL; mutex_init(&dquot->dq_lock); INIT_LIST_HEAD(&dquot->dq_free); @@ -722,10 +722,10 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type) struct dquot *dqget(struct super_block *sb, unsigned int id, int type) { unsigned int hashent = hashfn(sb, id, type); - struct dquot *dquot = NODQUOT, *empty = NODQUOT; + struct dquot *dquot = NULL, *empty = NULL; if (!sb_has_quota_active(sb, type)) - return NODQUOT; + return NULL; we_slept: spin_lock(&dq_list_lock); spin_lock(&dq_state_lock); @@ -736,15 +736,17 @@ we_slept: } spin_unlock(&dq_state_lock); - if ((dquot = find_dquot(hashent, sb, id, type)) == NODQUOT) { - if (empty == NODQUOT) { + dquot = find_dquot(hashent, sb, id, type); + if (!dquot) { + if (!empty) { spin_unlock(&dq_list_lock); - if ((empty = get_empty_dquot(sb, type)) == NODQUOT) + empty = get_empty_dquot(sb, type); + if (!empty) schedule(); /* Try to wait for a moment... */ goto we_slept; } dquot = empty; - empty = NODQUOT; + empty = NULL; dquot->dq_id = id; /* all dquots go on the inuse_list */ put_inuse(dquot); @@ -766,7 +768,7 @@ we_slept: /* Read the dquot and instantiate it (everything done only if needed) */ if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && sb->dq_op->acquire_dquot(dquot) < 0) { dqput(dquot); - dquot = NODQUOT; + dquot = NULL; goto out; } #ifdef __DQUOT_PARANOIA @@ -787,9 +789,9 @@ static int dqinit_needed(struct inode *inode, int type) if (IS_NOQUOTA(inode)) return 0; if (type != -1) - return inode->i_dquot[type] == NODQUOT; + return !inode->i_dquot[type]; for (cnt = 0; cnt < MAXQUOTAS; cnt++) - if (inode->i_dquot[cnt] == NODQUOT) + if (!inode->i_dquot[cnt]) return 1; return 0; } @@ -840,8 +842,8 @@ static int remove_inode_dquot_ref(struct inode *inode, int type, { struct dquot *dquot = inode->i_dquot[type]; - inode->i_dquot[type] = NODQUOT; - if (dquot != NODQUOT) { + inode->i_dquot[type] = NULL; + if (dquot) { if (dqput_blocks(dquot)) { #ifdef __DQUOT_PARANOIA if (atomic_read(&dquot->dq_count) != 1) @@ -1112,7 +1114,7 @@ static inline void flush_warnings(struct dquot * const *dquots, char *warntype) int i; for (i = 0; i < MAXQUOTAS; i++) - if (dquots[i] != NODQUOT && warntype[i] != QUOTA_NL_NOWARN && + if (dquots[i] && warntype[i] != QUOTA_NL_NOWARN && !warning_issued(dquots[i], warntype[i])) { #ifdef CONFIG_PRINT_QUOTA_WARNING print_warning(dquots[i], warntype[i]); @@ -1249,7 +1251,7 @@ int dquot_initialize(struct inode *inode, int type) { unsigned int id = 0; int cnt, ret = 0; - struct dquot *got[MAXQUOTAS] = { NODQUOT, NODQUOT }; + struct dquot *got[MAXQUOTAS] = { NULL, NULL }; struct super_block *sb = inode->i_sb; /* First test before acquiring mutex - solves deadlocks when we @@ -1282,9 +1284,9 @@ int dquot_initialize(struct inode *inode, int type) /* Avoid races with quotaoff() */ if (!sb_has_quota_active(sb, cnt)) continue; - if (inode->i_dquot[cnt] == NODQUOT) { + if (!inode->i_dquot[cnt]) { inode->i_dquot[cnt] = got[cnt]; - got[cnt] = NODQUOT; + got[cnt] = NULL; } } out_err: @@ -1307,7 +1309,7 @@ int dquot_drop(struct inode *inode) down_write(&sb_dqopt(inode->i_sb)->dqptr_sem); for (cnt = 0; cnt < MAXQUOTAS; cnt++) { put[cnt] = inode->i_dquot[cnt]; - inode->i_dquot[cnt] = NODQUOT; + inode->i_dquot[cnt] = NULL; } up_write(&sb_dqopt(inode->i_sb)->dqptr_sem); @@ -1332,7 +1334,7 @@ void vfs_dq_drop(struct inode *inode) * must assure that nobody can come after the DQUOT_DROP and * add quota pointers back anyway */ for (cnt = 0; cnt < MAXQUOTAS; cnt++) - if (inode->i_dquot[cnt] != NODQUOT) + if (inode->i_dquot[cnt]) break; if (cnt < MAXQUOTAS) inode->i_sb->dq_op->drop(inode); @@ -1363,7 +1365,7 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, spin_lock(&dq_data_lock); for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - if (inode->i_dquot[cnt] == NODQUOT) + if (!inode->i_dquot[cnt]) continue; if (check_bdq(inode->i_dquot[cnt], number, warn, warntype+cnt) == NO_QUOTA) { @@ -1372,7 +1374,7 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, } } for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - if (inode->i_dquot[cnt] == NODQUOT) + if (!inode->i_dquot[cnt]) continue; if (reserve) dquot_resv_space(inode->i_dquot[cnt], number); @@ -1461,14 +1463,14 @@ int dquot_alloc_inode(const struct inode *inode, qsize_t number) } spin_lock(&dq_data_lock); for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - if (inode->i_dquot[cnt] == NODQUOT) + if (!inode->i_dquot[cnt]) continue; if (check_idq(inode->i_dquot[cnt], number, warntype+cnt) == NO_QUOTA) goto warn_put_all; } for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - if (inode->i_dquot[cnt] == NODQUOT) + if (!inode->i_dquot[cnt]) continue; dquot_incr_inodes(inode->i_dquot[cnt], number); } @@ -1506,7 +1508,7 @@ int dquot_claim_space(struct inode *inode, qsize_t number) spin_lock(&dq_data_lock); /* Claim reserved quotas to allocated quotas */ for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - if (inode->i_dquot[cnt] != NODQUOT) + if (inode->i_dquot[cnt]) dquot_claim_reserved_space(inode->i_dquot[cnt], number); } @@ -1540,7 +1542,7 @@ void dquot_release_reserved_space(struct inode *inode, qsize_t number) spin_lock(&dq_data_lock); /* Release reserved dquots */ for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - if (inode->i_dquot[cnt] != NODQUOT) + if (inode->i_dquot[cnt]) dquot_free_reserved_space(inode->i_dquot[cnt], number); } spin_unlock(&dq_data_lock); @@ -1576,7 +1578,7 @@ out_sub: } spin_lock(&dq_data_lock); for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - if (inode->i_dquot[cnt] == NODQUOT) + if (!inode->i_dquot[cnt]) continue; warntype[cnt] = info_bdq_free(inode->i_dquot[cnt], number); dquot_decr_space(inode->i_dquot[cnt], number); @@ -1614,7 +1616,7 @@ int dquot_free_inode(const struct inode *inode, qsize_t number) } spin_lock(&dq_data_lock); for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - if (inode->i_dquot[cnt] == NODQUOT) + if (!inode->i_dquot[cnt]) continue; warntype[cnt] = info_idq_free(inode->i_dquot[cnt], number); dquot_decr_inodes(inode->i_dquot[cnt], number); @@ -1667,8 +1669,8 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr) return QUOTA_OK; /* Initialize the arrays */ for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - transfer_from[cnt] = NODQUOT; - transfer_to[cnt] = NODQUOT; + transfer_from[cnt] = NULL; + transfer_to[cnt] = NULL; warntype_to[cnt] = QUOTA_NL_NOWARN; switch (cnt) { case USRQUOTA: @@ -1696,7 +1698,7 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr) space = cur_space + rsv_space; /* Build the transfer_from list and check the limits */ for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - if (transfer_to[cnt] == NODQUOT) + if (!transfer_to[cnt]) continue; transfer_from[cnt] = inode->i_dquot[cnt]; if (check_idq(transfer_to[cnt], 1, warntype_to + cnt) == @@ -1712,7 +1714,7 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr) /* * Skip changes for same uid or gid or for turned off quota-type. */ - if (transfer_to[cnt] == NODQUOT) + if (!transfer_to[cnt]) continue; /* Due to IO error we might not have transfer_from[] structure */ @@ -1743,7 +1745,7 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr) if (transfer_to[cnt]) { mark_dquot_dirty(transfer_to[cnt]); /* The reference we got is transferred to the inode */ - transfer_to[cnt] = NODQUOT; + transfer_to[cnt] = NULL; } } warn_put_all: @@ -1761,7 +1763,7 @@ over_quota: up_write(&sb_dqopt(inode->i_sb)->dqptr_sem); /* Clear dquot pointers we don't want to dqput() */ for (cnt = 0; cnt < MAXQUOTAS; cnt++) - transfer_from[cnt] = NODQUOT; + transfer_from[cnt] = NULL; ret = NO_QUOTA; goto warn_put_all; } @@ -2256,7 +2258,7 @@ int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *d struct dquot *dquot; dquot = dqget(sb, id, type); - if (dquot == NODQUOT) + if (!dquot) return -ESRCH; do_get_dqblk(dquot, di); dqput(dquot); diff --git a/include/linux/quota.h b/include/linux/quota.h index a510d91561f..78c48895b12 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h @@ -277,8 +277,6 @@ struct dquot { struct mem_dqblk dq_dqb; /* Diskquota usage */ }; -#define NODQUOT (struct dquot *)NULL - #define QUOTA_OK 0 #define NO_QUOTA 1 -- GitLab From d26ac1a8128f6e1fc467f145acaa9f9bf9e16b75 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 26 Jan 2009 16:17:50 +0100 Subject: [PATCH 4566/4982] quota: Remove dqbuf_t and other cleanups Remove bogus typedef which is just a definition of char *. Remove unnecessary type casts. Substitute freedqbuf() with kfree. Signed-off-by: Jan Kara --- fs/quota/quota_tree.c | 104 ++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 55 deletions(-) diff --git a/fs/quota/quota_tree.c b/fs/quota/quota_tree.c index 953404c95b1..3a5a90c0896 100644 --- a/fs/quota/quota_tree.c +++ b/fs/quota/quota_tree.c @@ -22,8 +22,6 @@ MODULE_LICENSE("GPL"); #define __QUOTA_QT_PARANOIA -typedef char *dqbuf_t; - static int get_index(struct qtree_mem_dqinfo *info, qid_t id, int depth) { unsigned int epb = info->dqi_usable_bs >> 2; @@ -41,40 +39,35 @@ static inline int qtree_dqstr_in_blk(struct qtree_mem_dqinfo *info) / info->dqi_entry_size; } -static dqbuf_t getdqbuf(size_t size) +static char *getdqbuf(size_t size) { - dqbuf_t buf = kmalloc(size, GFP_NOFS); + char *buf = kmalloc(size, GFP_NOFS); if (!buf) printk(KERN_WARNING "VFS: Not enough memory for quota buffers.\n"); return buf; } -static inline void freedqbuf(dqbuf_t buf) -{ - kfree(buf); -} - -static inline ssize_t read_blk(struct qtree_mem_dqinfo *info, uint blk, dqbuf_t buf) +static inline ssize_t read_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf) { struct super_block *sb = info->dqi_sb; memset(buf, 0, info->dqi_usable_bs); - return sb->s_op->quota_read(sb, info->dqi_type, (char *)buf, + return sb->s_op->quota_read(sb, info->dqi_type, buf, info->dqi_usable_bs, blk << info->dqi_blocksize_bits); } -static inline ssize_t write_blk(struct qtree_mem_dqinfo *info, uint blk, dqbuf_t buf) +static inline ssize_t write_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf) { struct super_block *sb = info->dqi_sb; - return sb->s_op->quota_write(sb, info->dqi_type, (char *)buf, + return sb->s_op->quota_write(sb, info->dqi_type, buf, info->dqi_usable_bs, blk << info->dqi_blocksize_bits); } /* Remove empty block from list and return it */ static int get_free_dqblk(struct qtree_mem_dqinfo *info) { - dqbuf_t buf = getdqbuf(info->dqi_usable_bs); + char *buf = getdqbuf(info->dqi_usable_bs); struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf; int ret, blk; @@ -98,12 +91,12 @@ static int get_free_dqblk(struct qtree_mem_dqinfo *info) mark_info_dirty(info->dqi_sb, info->dqi_type); ret = blk; out_buf: - freedqbuf(buf); + kfree(buf); return ret; } /* Insert empty block to the list */ -static int put_free_dqblk(struct qtree_mem_dqinfo *info, dqbuf_t buf, uint blk) +static int put_free_dqblk(struct qtree_mem_dqinfo *info, char *buf, uint blk) { struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf; int err; @@ -120,9 +113,9 @@ static int put_free_dqblk(struct qtree_mem_dqinfo *info, dqbuf_t buf, uint blk) } /* Remove given block from the list of blocks with free entries */ -static int remove_free_dqentry(struct qtree_mem_dqinfo *info, dqbuf_t buf, uint blk) +static int remove_free_dqentry(struct qtree_mem_dqinfo *info, char *buf, uint blk) { - dqbuf_t tmpbuf = getdqbuf(info->dqi_usable_bs); + char *tmpbuf = getdqbuf(info->dqi_usable_bs); struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf; uint nextblk = le32_to_cpu(dh->dqdh_next_free); uint prevblk = le32_to_cpu(dh->dqdh_prev_free); @@ -153,21 +146,21 @@ static int remove_free_dqentry(struct qtree_mem_dqinfo *info, dqbuf_t buf, uint info->dqi_free_entry = nextblk; mark_info_dirty(info->dqi_sb, info->dqi_type); } - freedqbuf(tmpbuf); + kfree(tmpbuf); dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0); /* No matter whether write succeeds block is out of list */ if (write_blk(info, blk, buf) < 0) printk(KERN_ERR "VFS: Can't write block (%u) with free entries.\n", blk); return 0; out_buf: - freedqbuf(tmpbuf); + kfree(tmpbuf); return err; } /* Insert given block to the beginning of list with free entries */ -static int insert_free_dqentry(struct qtree_mem_dqinfo *info, dqbuf_t buf, uint blk) +static int insert_free_dqentry(struct qtree_mem_dqinfo *info, char *buf, uint blk) { - dqbuf_t tmpbuf = getdqbuf(info->dqi_usable_bs); + char *tmpbuf = getdqbuf(info->dqi_usable_bs); struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf; int err; @@ -188,12 +181,12 @@ static int insert_free_dqentry(struct qtree_mem_dqinfo *info, dqbuf_t buf, uint if (err < 0) goto out_buf; } - freedqbuf(tmpbuf); + kfree(tmpbuf); info->dqi_free_entry = blk; mark_info_dirty(info->dqi_sb, info->dqi_type); return 0; out_buf: - freedqbuf(tmpbuf); + kfree(tmpbuf); return err; } @@ -215,7 +208,7 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info, { uint blk, i; struct qt_disk_dqdbheader *dh; - dqbuf_t buf = getdqbuf(info->dqi_usable_bs); + char *buf = getdqbuf(info->dqi_usable_bs); char *ddquot; *err = 0; @@ -233,7 +226,7 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info, blk = get_free_dqblk(info); if ((int)blk < 0) { *err = blk; - freedqbuf(buf); + kfree(buf); return 0; } memset(buf, 0, info->dqi_usable_bs); @@ -253,9 +246,10 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info, } le16_add_cpu(&dh->dqdh_entries, 1); /* Find free structure in block */ - for (i = 0, ddquot = ((char *)buf) + sizeof(struct qt_disk_dqdbheader); + for (i = 0, ddquot = buf + sizeof(struct qt_disk_dqdbheader); i < qtree_dqstr_in_blk(info) && !qtree_entry_unused(info, ddquot); - i++, ddquot += info->dqi_entry_size); + i++, ddquot += info->dqi_entry_size) + ; #ifdef __QUOTA_QT_PARANOIA if (i == qtree_dqstr_in_blk(info)) { printk(KERN_ERR "VFS: find_free_dqentry(): Data block full " @@ -273,10 +267,10 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info, dquot->dq_off = (blk << info->dqi_blocksize_bits) + sizeof(struct qt_disk_dqdbheader) + i * info->dqi_entry_size; - freedqbuf(buf); + kfree(buf); return blk; out_buf: - freedqbuf(buf); + kfree(buf); return 0; } @@ -284,7 +278,7 @@ out_buf: static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, uint *treeblk, int depth) { - dqbuf_t buf = getdqbuf(info->dqi_usable_bs); + char *buf = getdqbuf(info->dqi_usable_bs); int ret = 0, newson = 0, newact = 0; __le32 *ref; uint newblk; @@ -333,7 +327,7 @@ static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, put_free_dqblk(info, buf, *treeblk); } out_buf: - freedqbuf(buf); + kfree(buf); return ret; } @@ -353,7 +347,7 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) int type = dquot->dq_type; struct super_block *sb = dquot->dq_sb; ssize_t ret; - dqbuf_t ddquot = getdqbuf(info->dqi_entry_size); + char *ddquot = getdqbuf(info->dqi_entry_size); if (!ddquot) return -ENOMEM; @@ -364,15 +358,15 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) if (ret < 0) { printk(KERN_ERR "VFS: Error %zd occurred while " "creating quota.\n", ret); - freedqbuf(ddquot); + kfree(ddquot); return ret; } } spin_lock(&dq_data_lock); info->dqi_ops->mem2disk_dqblk(ddquot, dquot); spin_unlock(&dq_data_lock); - ret = sb->s_op->quota_write(sb, type, (char *)ddquot, - info->dqi_entry_size, dquot->dq_off); + ret = sb->s_op->quota_write(sb, type, ddquot, info->dqi_entry_size, + dquot->dq_off); if (ret != info->dqi_entry_size) { printk(KERN_WARNING "VFS: dquota write failed on dev %s\n", sb->s_id); @@ -382,7 +376,7 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) ret = 0; } dqstats.writes++; - freedqbuf(ddquot); + kfree(ddquot); return ret; } @@ -393,7 +387,7 @@ static int free_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot, uint blk) { struct qt_disk_dqdbheader *dh; - dqbuf_t buf = getdqbuf(info->dqi_usable_bs); + char *buf = getdqbuf(info->dqi_usable_bs); int ret = 0; if (!buf) @@ -444,7 +438,7 @@ static int free_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot, } dquot->dq_off = 0; /* Quota is now unattached */ out_buf: - freedqbuf(buf); + kfree(buf); return ret; } @@ -452,7 +446,7 @@ out_buf: static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, uint *blk, int depth) { - dqbuf_t buf = getdqbuf(info->dqi_usable_bs); + char *buf = getdqbuf(info->dqi_usable_bs); int ret = 0; uint newblk; __le32 *ref = (__le32 *)buf; @@ -475,9 +469,8 @@ static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, int i; ref[get_index(info, dquot->dq_id, depth)] = cpu_to_le32(0); /* Block got empty? */ - for (i = 0; - i < (info->dqi_usable_bs >> 2) && !ref[i]; - i++); + for (i = 0; i < (info->dqi_usable_bs >> 2) && !ref[i]; i++) + ; /* Don't put the root block into the free block list */ if (i == (info->dqi_usable_bs >> 2) && *blk != QT_TREEOFF) { @@ -491,7 +484,7 @@ static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, } } out_buf: - freedqbuf(buf); + kfree(buf); return ret; } @@ -510,7 +503,7 @@ EXPORT_SYMBOL(qtree_delete_dquot); static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot, uint blk) { - dqbuf_t buf = getdqbuf(info->dqi_usable_bs); + char *buf = getdqbuf(info->dqi_usable_bs); loff_t ret = 0; int i; char *ddquot; @@ -522,9 +515,10 @@ static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info, printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk); goto out_buf; } - for (i = 0, ddquot = ((char *)buf) + sizeof(struct qt_disk_dqdbheader); + for (i = 0, ddquot = buf + sizeof(struct qt_disk_dqdbheader); i < qtree_dqstr_in_blk(info) && !info->dqi_ops->is_id(ddquot, dquot); - i++, ddquot += info->dqi_entry_size); + i++, ddquot += info->dqi_entry_size) + ; if (i == qtree_dqstr_in_blk(info)) { printk(KERN_ERR "VFS: Quota for id %u referenced " "but not present.\n", dquot->dq_id); @@ -535,7 +529,7 @@ static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info, qt_disk_dqdbheader) + i * info->dqi_entry_size; } out_buf: - freedqbuf(buf); + kfree(buf); return ret; } @@ -543,7 +537,7 @@ out_buf: static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot, uint blk, int depth) { - dqbuf_t buf = getdqbuf(info->dqi_usable_bs); + char *buf = getdqbuf(info->dqi_usable_bs); loff_t ret = 0; __le32 *ref = (__le32 *)buf; @@ -563,7 +557,7 @@ static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info, else ret = find_block_dqentry(info, dquot, blk); out_buf: - freedqbuf(buf); + kfree(buf); return ret; } @@ -579,7 +573,7 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) int type = dquot->dq_type; struct super_block *sb = dquot->dq_sb; loff_t offset; - dqbuf_t ddquot; + char *ddquot; int ret = 0; #ifdef __QUOTA_QT_PARANOIA @@ -607,8 +601,8 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) ddquot = getdqbuf(info->dqi_entry_size); if (!ddquot) return -ENOMEM; - ret = sb->s_op->quota_read(sb, type, (char *)ddquot, - info->dqi_entry_size, dquot->dq_off); + ret = sb->s_op->quota_read(sb, type, ddquot, info->dqi_entry_size, + dquot->dq_off); if (ret != info->dqi_entry_size) { if (ret >= 0) ret = -EIO; @@ -616,7 +610,7 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) "structure for id %u.\n", dquot->dq_id); set_bit(DQ_FAKE_B, &dquot->dq_flags); memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk)); - freedqbuf(ddquot); + kfree(ddquot); goto out; } spin_lock(&dq_data_lock); @@ -627,7 +621,7 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) !dquot->dq_dqb.dqb_isoftlimit) set_bit(DQ_FAKE_B, &dquot->dq_flags); spin_unlock(&dq_data_lock); - freedqbuf(ddquot); + kfree(ddquot); out: dqstats.reads++; return ret; -- GitLab From 9e3509e273ecc2a5f937c493f9bb71e5e41ac2e5 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 26 Jan 2009 16:45:12 +0100 Subject: [PATCH 4567/4982] vfs: Use lowercase names of quota functions Use lowercase names of quota functions instead of old uppercase ones. Signed-off-by: Jan Kara CC: Alexander Viro --- fs/attr.c | 3 ++- fs/inode.c | 4 ++-- fs/namei.c | 22 +++++++++++----------- fs/open.c | 2 +- fs/super.c | 8 ++++---- fs/sync.c | 2 +- 6 files changed, 21 insertions(+), 20 deletions(-) diff --git a/fs/attr.c b/fs/attr.c index f4360192a93..9fe1b1bd30a 100644 --- a/fs/attr.c +++ b/fs/attr.c @@ -173,7 +173,8 @@ int notify_change(struct dentry * dentry, struct iattr * attr) if (!error) { if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) - error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0; + error = vfs_dq_transfer(inode, attr) ? + -EDQUOT : 0; if (!error) error = inode_setattr(inode, attr); } diff --git a/fs/inode.c b/fs/inode.c index 826fb0b9d1c..bb81bd515f8 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -284,7 +284,7 @@ void clear_inode(struct inode *inode) BUG_ON(!(inode->i_state & I_FREEING)); BUG_ON(inode->i_state & I_CLEAR); inode_sync_wait(inode); - DQUOT_DROP(inode); + vfs_dq_drop(inode); if (inode->i_sb->s_op->clear_inode) inode->i_sb->s_op->clear_inode(inode); if (S_ISBLK(inode->i_mode) && inode->i_bdev) @@ -1158,7 +1158,7 @@ void generic_delete_inode(struct inode *inode) if (op->delete_inode) { void (*delete)(struct inode *) = op->delete_inode; if (!is_bad_inode(inode)) - DQUOT_INIT(inode); + vfs_dq_init(inode); /* Filesystems implementing their own * s_op->delete_inode are required to call * truncate_inode_pages and clear_inode() diff --git a/fs/namei.c b/fs/namei.c index bbc15c23755..8937f4e7817 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1470,7 +1470,7 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode, error = security_inode_create(dir, dentry, mode); if (error) return error; - DQUOT_INIT(dir); + vfs_dq_init(dir); error = dir->i_op->create(dir, dentry, mode, nd); if (!error) fsnotify_create(dir, dentry); @@ -1544,7 +1544,7 @@ int may_open(struct path *path, int acc_mode, int flag) error = security_path_truncate(path, 0, ATTR_MTIME|ATTR_CTIME|ATTR_OPEN); if (!error) { - DQUOT_INIT(inode); + vfs_dq_init(inode); error = do_truncate(dentry, 0, ATTR_MTIME|ATTR_CTIME|ATTR_OPEN, @@ -1555,7 +1555,7 @@ int may_open(struct path *path, int acc_mode, int flag) return error; } else if (flag & FMODE_WRITE) - DQUOT_INIT(inode); + vfs_dq_init(inode); return 0; } @@ -1938,7 +1938,7 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) if (error) return error; - DQUOT_INIT(dir); + vfs_dq_init(dir); error = dir->i_op->mknod(dir, dentry, mode, dev); if (!error) fsnotify_create(dir, dentry); @@ -2037,7 +2037,7 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) if (error) return error; - DQUOT_INIT(dir); + vfs_dq_init(dir); error = dir->i_op->mkdir(dir, dentry, mode); if (!error) fsnotify_mkdir(dir, dentry); @@ -2123,7 +2123,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) if (!dir->i_op->rmdir) return -EPERM; - DQUOT_INIT(dir); + vfs_dq_init(dir); mutex_lock(&dentry->d_inode->i_mutex); dentry_unhash(dentry); @@ -2210,7 +2210,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) if (!dir->i_op->unlink) return -EPERM; - DQUOT_INIT(dir); + vfs_dq_init(dir); mutex_lock(&dentry->d_inode->i_mutex); if (d_mountpoint(dentry)) @@ -2321,7 +2321,7 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname) if (error) return error; - DQUOT_INIT(dir); + vfs_dq_init(dir); error = dir->i_op->symlink(dir, dentry, oldname); if (!error) fsnotify_create(dir, dentry); @@ -2405,7 +2405,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de return error; mutex_lock(&inode->i_mutex); - DQUOT_INIT(dir); + vfs_dq_init(dir); error = dir->i_op->link(old_dentry, dir, new_dentry); mutex_unlock(&inode->i_mutex); if (!error) @@ -2604,8 +2604,8 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, if (!old_dir->i_op->rename) return -EPERM; - DQUOT_INIT(old_dir); - DQUOT_INIT(new_dir); + vfs_dq_init(old_dir); + vfs_dq_init(new_dir); old_name = fsnotify_oldname_init(old_dentry->d_name.name); diff --git a/fs/open.c b/fs/open.c index a3a78ceb2a2..75b61677daa 100644 --- a/fs/open.c +++ b/fs/open.c @@ -273,7 +273,7 @@ static long do_sys_truncate(const char __user *pathname, loff_t length) if (!error) error = security_path_truncate(&path, length, 0); if (!error) { - DQUOT_INIT(inode); + vfs_dq_init(inode); error = do_truncate(path.dentry, length, 0, NULL); } diff --git a/fs/super.c b/fs/super.c index 6ce501447ad..0f9d17f2c75 100644 --- a/fs/super.c +++ b/fs/super.c @@ -197,7 +197,7 @@ void deactivate_super(struct super_block *s) if (atomic_dec_and_lock(&s->s_active, &sb_lock)) { s->s_count -= S_BIAS-1; spin_unlock(&sb_lock); - DQUOT_OFF(s, 0); + vfs_dq_off(s, 0); down_write(&s->s_umount); fs->kill_sb(s); put_filesystem(fs); @@ -266,7 +266,7 @@ EXPORT_SYMBOL(unlock_super); void __fsync_super(struct super_block *sb) { sync_inodes_sb(sb, 0); - DQUOT_SYNC(sb); + vfs_dq_sync(sb); lock_super(sb); if (sb->s_dirt && sb->s_op->write_super) sb->s_op->write_super(sb); @@ -655,7 +655,7 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) mark_files_ro(sb); else if (!fs_may_remount_ro(sb)) return -EBUSY; - retval = DQUOT_OFF(sb, 1); + retval = vfs_dq_off(sb, 1); if (retval < 0 && retval != -ENOSYS) return -EBUSY; } @@ -670,7 +670,7 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) } sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); if (remount_rw) - DQUOT_ON_REMOUNT(sb); + vfs_dq_quota_on_remount(sb); return 0; } diff --git a/fs/sync.c b/fs/sync.c index a16d53e5fe9..ef36bc921bf 100644 --- a/fs/sync.c +++ b/fs/sync.c @@ -25,7 +25,7 @@ static void do_sync(unsigned long wait) { wakeup_pdflush(0); sync_inodes(0); /* All mappings, inodes and their blockdevs */ - DQUOT_SYNC(NULL); + vfs_dq_sync(NULL); sync_supers(); /* Write the superblocks */ sync_filesystems(0); /* Start syncing the filesystems */ sync_filesystems(wait); /* Waitingly sync the filesystems */ -- GitLab From 314649558d2ff0927d102fa06c62557a92ce5c1d Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 26 Jan 2009 16:46:21 +0100 Subject: [PATCH 4568/4982] ramfs: Remove quota call Ramfs has no bussiness in quotas. Signed-off-by: Jan Kara --- fs/ramfs/file-nommu.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index 5d7c7ececa6..995ef1d6686 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -205,11 +204,6 @@ static int ramfs_nommu_setattr(struct dentry *dentry, struct iattr *ia) if (ret) return ret; - /* by providing our own setattr() method, we skip this quotaism */ - if ((old_ia_valid & ATTR_UID && ia->ia_uid != inode->i_uid) || - (old_ia_valid & ATTR_GID && ia->ia_gid != inode->i_gid)) - ret = DQUOT_TRANSFER(inode, ia) ? -EDQUOT : 0; - /* pick out size-changing events */ if (ia->ia_valid & ATTR_SIZE) { loff_t size = i_size_read(inode); -- GitLab From 6f90bee5062a8af24d8aa5c47182d15aa28a0f17 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 26 Jan 2009 16:52:06 +0100 Subject: [PATCH 4569/4982] ext2: Use lowercase names of quota functions Use lowercase names of quota functions instead of old uppercase ones. Signed-off-by: Jan Kara CC: linux-ext4@vger.kernel.org --- fs/ext2/balloc.c | 8 ++++---- fs/ext2/ialloc.c | 10 +++++----- fs/ext2/inode.c | 2 +- fs/ext2/xattr.c | 8 ++++---- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c index 4a29d637608..7f8d2e5a7ea 100644 --- a/fs/ext2/balloc.c +++ b/fs/ext2/balloc.c @@ -570,7 +570,7 @@ do_more: error_return: brelse(bitmap_bh); release_blocks(sb, freed); - DQUOT_FREE_BLOCK(inode, freed); + vfs_dq_free_block(inode, freed); } /** @@ -1247,7 +1247,7 @@ ext2_fsblk_t ext2_new_blocks(struct inode *inode, ext2_fsblk_t goal, /* * Check quota for allocation of this block. */ - if (DQUOT_ALLOC_BLOCK(inode, num)) { + if (vfs_dq_alloc_block(inode, num)) { *errp = -EDQUOT; return 0; } @@ -1409,7 +1409,7 @@ allocated: *errp = 0; brelse(bitmap_bh); - DQUOT_FREE_BLOCK(inode, *count-num); + vfs_dq_free_block(inode, *count-num); *count = num; return ret_block; @@ -1420,7 +1420,7 @@ out: * Undo the block allocation */ if (!performed_allocation) - DQUOT_FREE_BLOCK(inode, *count); + vfs_dq_free_block(inode, *count); brelse(bitmap_bh); return 0; } diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index 66321a877e7..15387c9c17d 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c @@ -121,8 +121,8 @@ void ext2_free_inode (struct inode * inode) if (!is_bad_inode(inode)) { /* Quota is already initialized in iput() */ ext2_xattr_delete_inode(inode); - DQUOT_FREE_INODE(inode); - DQUOT_DROP(inode); + vfs_dq_free_inode(inode); + vfs_dq_drop(inode); } es = EXT2_SB(sb)->s_es; @@ -586,7 +586,7 @@ got: goto fail_drop; } - if (DQUOT_ALLOC_INODE(inode)) { + if (vfs_dq_alloc_inode(inode)) { err = -EDQUOT; goto fail_drop; } @@ -605,10 +605,10 @@ got: return inode; fail_free_drop: - DQUOT_FREE_INODE(inode); + vfs_dq_free_inode(inode); fail_drop: - DQUOT_DROP(inode); + vfs_dq_drop(inode); inode->i_flags |= S_NOQUOTA; inode->i_nlink = 0; unlock_new_inode(inode); diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 23fff2f8778..b43b9556366 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -1444,7 +1444,7 @@ int ext2_setattr(struct dentry *dentry, struct iattr *iattr) return error; if ((iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) || (iattr->ia_valid & ATTR_GID && iattr->ia_gid != inode->i_gid)) { - error = DQUOT_TRANSFER(inode, iattr) ? -EDQUOT : 0; + error = vfs_dq_transfer(inode, iattr) ? -EDQUOT : 0; if (error) return error; } diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c index 987a5261cc2..7913531ec6d 100644 --- a/fs/ext2/xattr.c +++ b/fs/ext2/xattr.c @@ -642,7 +642,7 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh, ea_bdebug(new_bh, "reusing block"); error = -EDQUOT; - if (DQUOT_ALLOC_BLOCK(inode, 1)) { + if (vfs_dq_alloc_block(inode, 1)) { unlock_buffer(new_bh); goto cleanup; } @@ -699,7 +699,7 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh, * as if nothing happened and cleanup the unused block */ if (error && error != -ENOSPC) { if (new_bh && new_bh != old_bh) - DQUOT_FREE_BLOCK(inode, 1); + vfs_dq_free_block(inode, 1); goto cleanup; } } else @@ -731,7 +731,7 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh, le32_add_cpu(&HDR(old_bh)->h_refcount, -1); if (ce) mb_cache_entry_release(ce); - DQUOT_FREE_BLOCK(inode, 1); + vfs_dq_free_block(inode, 1); mark_buffer_dirty(old_bh); ea_bdebug(old_bh, "refcount now=%d", le32_to_cpu(HDR(old_bh)->h_refcount)); @@ -794,7 +794,7 @@ ext2_xattr_delete_inode(struct inode *inode) mark_buffer_dirty(bh); if (IS_SYNC(inode)) sync_dirty_buffer(bh); - DQUOT_FREE_BLOCK(inode, 1); + vfs_dq_free_block(inode, 1); } EXT2_I(inode)->i_file_acl = 0; -- GitLab From 81a052273998f94b098945c4c313e05246956eb2 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 26 Jan 2009 16:58:01 +0100 Subject: [PATCH 4570/4982] ext3: Use lowercase names of quota functions Use lowercase names of quota functions instead of old uppercase ones. Signed-off-by: Jan Kara CC: linux-ext4@vger.kernel.org --- fs/ext3/balloc.c | 8 ++++---- fs/ext3/ialloc.c | 12 ++++++------ fs/ext3/inode.c | 6 +++--- fs/ext3/namei.c | 6 +++--- fs/ext3/super.c | 4 ++-- fs/ext3/xattr.c | 6 +++--- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 0dbf1c04847..225202db897 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -676,7 +676,7 @@ void ext3_free_blocks(handle_t *handle, struct inode *inode, } ext3_free_blocks_sb(handle, sb, block, count, &dquot_freed_blocks); if (dquot_freed_blocks) - DQUOT_FREE_BLOCK(inode, dquot_freed_blocks); + vfs_dq_free_block(inode, dquot_freed_blocks); return; } @@ -1502,7 +1502,7 @@ ext3_fsblk_t ext3_new_blocks(handle_t *handle, struct inode *inode, /* * Check quota for allocation of this block. */ - if (DQUOT_ALLOC_BLOCK(inode, num)) { + if (vfs_dq_alloc_block(inode, num)) { *errp = -EDQUOT; return 0; } @@ -1714,7 +1714,7 @@ allocated: *errp = 0; brelse(bitmap_bh); - DQUOT_FREE_BLOCK(inode, *count-num); + vfs_dq_free_block(inode, *count-num); *count = num; return ret_block; @@ -1729,7 +1729,7 @@ out: * Undo the block allocation */ if (!performed_allocation) - DQUOT_FREE_BLOCK(inode, *count); + vfs_dq_free_block(inode, *count); brelse(bitmap_bh); return 0; } diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index 8de6c720e51..dd13d60d524 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c @@ -123,10 +123,10 @@ void ext3_free_inode (handle_t *handle, struct inode * inode) * Note: we must free any quota before locking the superblock, * as writing the quota to disk may need the lock as well. */ - DQUOT_INIT(inode); + vfs_dq_init(inode); ext3_xattr_delete_inode(handle, inode); - DQUOT_FREE_INODE(inode); - DQUOT_DROP(inode); + vfs_dq_free_inode(inode); + vfs_dq_drop(inode); is_directory = S_ISDIR(inode->i_mode); @@ -589,7 +589,7 @@ got: sizeof(struct ext3_inode) - EXT3_GOOD_OLD_INODE_SIZE : 0; ret = inode; - if(DQUOT_ALLOC_INODE(inode)) { + if (vfs_dq_alloc_inode(inode)) { err = -EDQUOT; goto fail_drop; } @@ -620,10 +620,10 @@ really_out: return ret; fail_free_drop: - DQUOT_FREE_INODE(inode); + vfs_dq_free_inode(inode); fail_drop: - DQUOT_DROP(inode); + vfs_dq_drop(inode); inode->i_flags |= S_NOQUOTA; inode->i_nlink = 0; unlock_new_inode(inode); diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 5fa453b49a6..c8f9bd30882 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -3055,7 +3055,7 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr) error = PTR_ERR(handle); goto err_out; } - error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0; + error = vfs_dq_transfer(inode, attr) ? -EDQUOT : 0; if (error) { ext3_journal_stop(handle); return error; @@ -3146,7 +3146,7 @@ static int ext3_writepage_trans_blocks(struct inode *inode) ret = 2 * (bpp + indirects) + 2; #ifdef CONFIG_QUOTA - /* We know that structure was already allocated during DQUOT_INIT so + /* We know that structure was already allocated during vfs_dq_init so * we will be updating only the data blocks + inodes */ ret += 2*EXT3_QUOTA_TRANS_BLOCKS(inode->i_sb); #endif @@ -3237,7 +3237,7 @@ int ext3_mark_inode_dirty(handle_t *handle, struct inode *inode) * i_size has been changed by generic_commit_write() and we thus need * to include the updated inode in the current transaction. * - * Also, DQUOT_ALLOC_SPACE() will always dirty the inode when blocks + * Also, vfs_dq_alloc_space() will always dirty the inode when blocks * are allocated to the file. * * If the inode is marked synchronous, we don't honour that here - doing diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 4db4ffa1eda..e2fc63cbba8 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -2049,7 +2049,7 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry) /* Initialize quotas before so that eventual writes go in * separate transaction */ - DQUOT_INIT(dentry->d_inode); + vfs_dq_init(dentry->d_inode); handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS(dir->i_sb)); if (IS_ERR(handle)) return PTR_ERR(handle); @@ -2108,7 +2108,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry) /* Initialize quotas before so that eventual writes go * in separate transaction */ - DQUOT_INIT(dentry->d_inode); + vfs_dq_init(dentry->d_inode); handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS(dir->i_sb)); if (IS_ERR(handle)) return PTR_ERR(handle); @@ -2272,7 +2272,7 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry, /* Initialize quotas before so that eventual writes go * in separate transaction */ if (new_dentry->d_inode) - DQUOT_INIT(new_dentry->d_inode); + vfs_dq_init(new_dentry->d_inode); handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS(old_dir->i_sb) + EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2); diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 41e6ae605e0..9e5b8e387e1 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -1436,7 +1436,7 @@ static void ext3_orphan_cleanup (struct super_block * sb, } list_add(&EXT3_I(inode)->i_orphan, &EXT3_SB(sb)->s_orphan); - DQUOT_INIT(inode); + vfs_dq_init(inode); if (inode->i_nlink) { printk(KERN_DEBUG "%s: truncating inode %lu to %Ld bytes\n", @@ -2700,7 +2700,7 @@ static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf) * Process 1 Process 2 * ext3_create() quota_sync() * journal_start() write_dquot() - * DQUOT_INIT() down(dqio_mutex) + * vfs_dq_init() down(dqio_mutex) * down(dqio_mutex) journal_start() * */ diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c index 175414ac221..83b7be849bd 100644 --- a/fs/ext3/xattr.c +++ b/fs/ext3/xattr.c @@ -498,7 +498,7 @@ ext3_xattr_release_block(handle_t *handle, struct inode *inode, error = ext3_journal_dirty_metadata(handle, bh); if (IS_SYNC(inode)) handle->h_sync = 1; - DQUOT_FREE_BLOCK(inode, 1); + vfs_dq_free_block(inode, 1); ea_bdebug(bh, "refcount now=%d; releasing", le32_to_cpu(BHDR(bh)->h_refcount)); if (ce) @@ -774,7 +774,7 @@ inserted: /* The old block is released after updating the inode. */ error = -EDQUOT; - if (DQUOT_ALLOC_BLOCK(inode, 1)) + if (vfs_dq_alloc_block(inode, 1)) goto cleanup; error = ext3_journal_get_write_access(handle, new_bh); @@ -848,7 +848,7 @@ cleanup: return error; cleanup_dquot: - DQUOT_FREE_BLOCK(inode, 1); + vfs_dq_free_block(inode, 1); goto cleanup; bad_block: -- GitLab From a269eb18294d35874c53311acc2cd0b5ef477ce5 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 26 Jan 2009 17:04:39 +0100 Subject: [PATCH 4571/4982] ext4: Use lowercase names of quota functions Use lowercase names of quota functions instead of old uppercase ones. Signed-off-by: Jan Kara Acked-by: Mingming Cao CC: linux-ext4@vger.kernel.org --- fs/ext4/balloc.c | 2 +- fs/ext4/ialloc.c | 12 ++++++------ fs/ext4/inode.c | 4 ++-- fs/ext4/mballoc.c | 4 ++-- fs/ext4/namei.c | 6 +++--- fs/ext4/super.c | 6 +++--- fs/ext4/xattr.c | 6 +++--- 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index de9459b4cb9..38f40d55899 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -536,7 +536,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, ext4_mb_free_blocks(handle, inode, block, count, metadata, &dquot_freed_blocks); if (dquot_freed_blocks) - DQUOT_FREE_BLOCK(inode, dquot_freed_blocks); + vfs_dq_free_block(inode, dquot_freed_blocks); return; } diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 2d2b3585ee9..fb51b40e3e8 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -220,10 +220,10 @@ void ext4_free_inode(handle_t *handle, struct inode *inode) * Note: we must free any quota before locking the superblock, * as writing the quota to disk may need the lock as well. */ - DQUOT_INIT(inode); + vfs_dq_init(inode); ext4_xattr_delete_inode(handle, inode); - DQUOT_FREE_INODE(inode); - DQUOT_DROP(inode); + vfs_dq_free_inode(inode); + vfs_dq_drop(inode); is_directory = S_ISDIR(inode->i_mode); @@ -915,7 +915,7 @@ got: ei->i_extra_isize = EXT4_SB(sb)->s_want_extra_isize; ret = inode; - if (DQUOT_ALLOC_INODE(inode)) { + if (vfs_dq_alloc_inode(inode)) { err = -EDQUOT; goto fail_drop; } @@ -956,10 +956,10 @@ really_out: return ret; fail_free_drop: - DQUOT_FREE_INODE(inode); + vfs_dq_free_inode(inode); fail_drop: - DQUOT_DROP(inode); + vfs_dq_drop(inode); inode->i_flags |= S_NOQUOTA; inode->i_nlink = 0; unlock_new_inode(inode); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 8290cfbd9fa..71d3ecd5db7 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4642,7 +4642,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) error = PTR_ERR(handle); goto err_out; } - error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0; + error = vfs_dq_transfer(inode, attr) ? -EDQUOT : 0; if (error) { ext4_journal_stop(handle); return error; @@ -5021,7 +5021,7 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode) * i_size has been changed by generic_commit_write() and we thus need * to include the updated inode in the current transaction. * - * Also, DQUOT_ALLOC_SPACE() will always dirty the inode when blocks + * Also, vfs_dq_alloc_block() will always dirty the inode when blocks * are allocated to the file. * * If the inode is marked synchronous, we don't honour that here - doing diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 4de42090c41..b038188bd03 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -4587,7 +4587,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, return 0; } reserv_blks = ar->len; - while (ar->len && DQUOT_ALLOC_BLOCK(ar->inode, ar->len)) { + while (ar->len && vfs_dq_alloc_block(ar->inode, ar->len)) { ar->flags |= EXT4_MB_HINT_NOPREALLOC; ar->len--; } @@ -4663,7 +4663,7 @@ out2: kmem_cache_free(ext4_ac_cachep, ac); out1: if (inquota && ar->len < inquota) - DQUOT_FREE_BLOCK(ar->inode, inquota - ar->len); + vfs_dq_free_block(ar->inode, inquota - ar->len); out3: if (!ar->len) { if (!EXT4_I(ar->inode)->i_delalloc_reserved_flag) diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index ba702bd7910..83410244d3e 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -2092,7 +2092,7 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry) /* Initialize quotas before so that eventual writes go in * separate transaction */ - DQUOT_INIT(dentry->d_inode); + vfs_dq_init(dentry->d_inode); handle = ext4_journal_start(dir, EXT4_DELETE_TRANS_BLOCKS(dir->i_sb)); if (IS_ERR(handle)) return PTR_ERR(handle); @@ -2151,7 +2151,7 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry) /* Initialize quotas before so that eventual writes go * in separate transaction */ - DQUOT_INIT(dentry->d_inode); + vfs_dq_init(dentry->d_inode); handle = ext4_journal_start(dir, EXT4_DELETE_TRANS_BLOCKS(dir->i_sb)); if (IS_ERR(handle)) return PTR_ERR(handle); @@ -2318,7 +2318,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, /* Initialize quotas before so that eventual writes go * in separate transaction */ if (new_dentry->d_inode) - DQUOT_INIT(new_dentry->d_inode); + vfs_dq_init(new_dentry->d_inode); handle = ext4_journal_start(old_dir, 2 * EXT4_DATA_TRANS_BLOCKS(old_dir->i_sb) + EXT4_INDEX_EXTRA_TRANS_BLOCKS + 2); diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 5a238e9c71c..f7371a6a923 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1804,7 +1804,7 @@ static void ext4_orphan_cleanup(struct super_block *sb, } list_add(&EXT4_I(inode)->i_orphan, &EXT4_SB(sb)->s_orphan); - DQUOT_INIT(inode); + vfs_dq_init(inode); if (inode->i_nlink) { printk(KERN_DEBUG "%s: truncating inode %lu to %lld bytes\n", @@ -3369,8 +3369,8 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) * is locked for write. Otherwise the are possible deadlocks: * Process 1 Process 2 * ext4_create() quota_sync() - * jbd2_journal_start() write_dquot() - * DQUOT_INIT() down(dqio_mutex) + * jbd2_journal_start() write_dquot() + * vfs_dq_init() down(dqio_mutex) * down(dqio_mutex) jbd2_journal_start() * */ diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 157ce6589c5..62b31c24699 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -490,7 +490,7 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode, error = ext4_handle_dirty_metadata(handle, inode, bh); if (IS_SYNC(inode)) ext4_handle_sync(handle); - DQUOT_FREE_BLOCK(inode, 1); + vfs_dq_free_block(inode, 1); ea_bdebug(bh, "refcount now=%d; releasing", le32_to_cpu(BHDR(bh)->h_refcount)); if (ce) @@ -784,7 +784,7 @@ inserted: /* The old block is released after updating the inode. */ error = -EDQUOT; - if (DQUOT_ALLOC_BLOCK(inode, 1)) + if (vfs_dq_alloc_block(inode, 1)) goto cleanup; error = ext4_journal_get_write_access(handle, new_bh); @@ -860,7 +860,7 @@ cleanup: return error; cleanup_dquot: - DQUOT_FREE_BLOCK(inode, 1); + vfs_dq_free_block(inode, 1); goto cleanup; bad_block: -- GitLab From 77db4f25bca22ce96be0cd3c5a3160599817ff45 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 26 Jan 2009 17:14:18 +0100 Subject: [PATCH 4572/4982] reiserfs: Use lowercase names of quota functions Use lowercase names of quota functions instead of old uppercase ones. Signed-off-by: Jan Kara CC: reiserfs-devel@vger.kernel.org --- fs/reiserfs/bitmap.c | 14 ++++++++------ fs/reiserfs/inode.c | 10 +++++----- fs/reiserfs/namei.c | 6 +++--- fs/reiserfs/stree.c | 14 +++++++------- fs/reiserfs/super.c | 2 +- 5 files changed, 24 insertions(+), 22 deletions(-) diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c index 4646caa6045..f32d1425cc9 100644 --- a/fs/reiserfs/bitmap.c +++ b/fs/reiserfs/bitmap.c @@ -430,7 +430,7 @@ static void _reiserfs_free_block(struct reiserfs_transaction_handle *th, journal_mark_dirty(th, s, sbh); if (for_unformatted) - DQUOT_FREE_BLOCK_NODIRTY(inode, 1); + vfs_dq_free_block_nodirty(inode, 1); } void reiserfs_free_block(struct reiserfs_transaction_handle *th, @@ -1055,7 +1055,7 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start amount_needed, hint->inode->i_uid); #endif quota_ret = - DQUOT_ALLOC_BLOCK_NODIRTY(hint->inode, amount_needed); + vfs_dq_alloc_block_nodirty(hint->inode, amount_needed); if (quota_ret) /* Quota exceeded? */ return QUOTA_EXCEEDED; if (hint->preallocate && hint->prealloc_size) { @@ -1064,8 +1064,7 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start "reiserquota: allocating (prealloc) %d blocks id=%u", hint->prealloc_size, hint->inode->i_uid); #endif - quota_ret = - DQUOT_PREALLOC_BLOCK_NODIRTY(hint->inode, + quota_ret = vfs_dq_prealloc_block_nodirty(hint->inode, hint->prealloc_size); if (quota_ret) hint->preallocate = hint->prealloc_size = 0; @@ -1098,7 +1097,10 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start nr_allocated, hint->inode->i_uid); #endif - DQUOT_FREE_BLOCK_NODIRTY(hint->inode, amount_needed + hint->prealloc_size - nr_allocated); /* Free not allocated blocks */ + /* Free not allocated blocks */ + vfs_dq_free_block_nodirty(hint->inode, + amount_needed + hint->prealloc_size - + nr_allocated); } while (nr_allocated--) reiserfs_free_block(hint->th, hint->inode, @@ -1129,7 +1131,7 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start REISERFS_I(hint->inode)->i_prealloc_count, hint->inode->i_uid); #endif - DQUOT_FREE_BLOCK_NODIRTY(hint->inode, amount_needed + + vfs_dq_free_block_nodirty(hint->inode, amount_needed + hint->prealloc_size - nr_allocated - REISERFS_I(hint->inode)-> i_prealloc_count); diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 55fce92cdf1..823227a7662 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -53,7 +53,7 @@ void reiserfs_delete_inode(struct inode *inode) * after delete_object so that quota updates go into the same transaction as * stat data deletion */ if (!err) - DQUOT_FREE_INODE(inode); + vfs_dq_free_inode(inode); if (journal_end(&th, inode->i_sb, jbegin_count)) goto out; @@ -1763,7 +1763,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, BUG_ON(!th->t_trans_id); - if (DQUOT_ALLOC_INODE(inode)) { + if (vfs_dq_alloc_inode(inode)) { err = -EDQUOT; goto out_end_trans; } @@ -1947,12 +1947,12 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, INODE_PKEY(inode)->k_objectid = 0; /* Quota change must be inside a transaction for journaling */ - DQUOT_FREE_INODE(inode); + vfs_dq_free_inode(inode); out_end_trans: journal_end(th, th->t_super, th->t_blocks_allocated); /* Drop can be outside and it needs more credits so it's better to have it outside */ - DQUOT_DROP(inode); + vfs_dq_drop(inode); inode->i_flags |= S_NOQUOTA; make_bad_inode(inode); @@ -3119,7 +3119,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) if (error) goto out; error = - DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0; + vfs_dq_transfer(inode, attr) ? -EDQUOT : 0; if (error) { journal_end(&th, inode->i_sb, jbegin_count); diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index 738967f6c8e..639d635d9d4 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c @@ -555,7 +555,7 @@ static int reiserfs_add_entry(struct reiserfs_transaction_handle *th, */ static int drop_new_inode(struct inode *inode) { - DQUOT_DROP(inode); + vfs_dq_drop(inode); make_bad_inode(inode); inode->i_flags |= S_NOQUOTA; iput(inode); @@ -563,7 +563,7 @@ static int drop_new_inode(struct inode *inode) } /* utility function that does setup for reiserfs_new_inode. -** DQUOT_INIT needs lots of credits so it's better to have it +** vfs_dq_init needs lots of credits so it's better to have it ** outside of a transaction, so we had to pull some bits of ** reiserfs_new_inode out into this func. */ @@ -586,7 +586,7 @@ static int new_inode_init(struct inode *inode, struct inode *dir, int mode) } else { inode->i_gid = current_fsgid(); } - DQUOT_INIT(inode); + vfs_dq_init(inode); return 0; } diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index abbc64dcc8d..73aaa33f673 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c @@ -1297,7 +1297,7 @@ int reiserfs_delete_item(struct reiserfs_transaction_handle *th, struct treepath "reiserquota delete_item(): freeing %u, id=%u type=%c", quota_cut_bytes, p_s_inode->i_uid, head2type(&s_ih)); #endif - DQUOT_FREE_SPACE_NODIRTY(p_s_inode, quota_cut_bytes); + vfs_dq_free_space_nodirty(p_s_inode, quota_cut_bytes); /* Return deleted body length */ return n_ret_value; @@ -1383,7 +1383,7 @@ void reiserfs_delete_solid_item(struct reiserfs_transaction_handle *th, quota_cut_bytes, inode->i_uid, key2type(key)); #endif - DQUOT_FREE_SPACE_NODIRTY(inode, + vfs_dq_free_space_nodirty(inode, quota_cut_bytes); } break; @@ -1734,7 +1734,7 @@ int reiserfs_cut_from_item(struct reiserfs_transaction_handle *th, "reiserquota cut_from_item(): freeing %u id=%u type=%c", quota_cut_bytes, p_s_inode->i_uid, '?'); #endif - DQUOT_FREE_SPACE_NODIRTY(p_s_inode, quota_cut_bytes); + vfs_dq_free_space_nodirty(p_s_inode, quota_cut_bytes); return n_ret_value; } @@ -1971,7 +1971,7 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree key2type(&(p_s_key->on_disk_key))); #endif - if (DQUOT_ALLOC_SPACE_NODIRTY(inode, n_pasted_size)) { + if (vfs_dq_alloc_space_nodirty(inode, n_pasted_size)) { pathrelse(p_s_search_path); return -EDQUOT; } @@ -2027,7 +2027,7 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree n_pasted_size, inode->i_uid, key2type(&(p_s_key->on_disk_key))); #endif - DQUOT_FREE_SPACE_NODIRTY(inode, n_pasted_size); + vfs_dq_free_space_nodirty(inode, n_pasted_size); return retval; } @@ -2060,7 +2060,7 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th, struct treepath #endif /* We can't dirty inode here. It would be immediately written but * appropriate stat item isn't inserted yet... */ - if (DQUOT_ALLOC_SPACE_NODIRTY(inode, quota_bytes)) { + if (vfs_dq_alloc_space_nodirty(inode, quota_bytes)) { pathrelse(p_s_path); return -EDQUOT; } @@ -2112,6 +2112,6 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th, struct treepath quota_bytes, inode->i_uid, head2type(p_s_ih)); #endif if (inode) - DQUOT_FREE_SPACE_NODIRTY(inode, quota_bytes); + vfs_dq_free_space_nodirty(inode, quota_bytes); return retval; } diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 317c0352163..5dbafb73940 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -250,7 +250,7 @@ static int finish_unfinished(struct super_block *s) retval = remove_save_link_only(s, &save_link_key, 0); continue; } - DQUOT_INIT(inode); + vfs_dq_init(inode); if (truncate && S_ISDIR(inode->i_mode)) { /* We got a truncate request for a dir which is impossible. -- GitLab From 5f5fa796c6b0158b50a2d5d2f80a926466ea87b3 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 26 Jan 2009 17:15:30 +0100 Subject: [PATCH 4573/4982] ufs: Use lowercase names of quota functions Use lowercase names of quota functions instead of old uppercase ones. Signed-off-by: Jan Kara CC: Evgeniy Dushistov --- fs/ufs/balloc.c | 12 ++++++------ fs/ufs/ialloc.c | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index 0d9ada17373..54c16ec95df 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c @@ -85,7 +85,7 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count) "bit already cleared for fragment %u", i); } - DQUOT_FREE_BLOCK (inode, count); + vfs_dq_free_block(inode, count); fs32_add(sb, &ucg->cg_cs.cs_nffree, count); @@ -195,7 +195,7 @@ do_more: ubh_setblock(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) ufs_clusteracct (sb, ucpi, blkno, 1); - DQUOT_FREE_BLOCK(inode, uspi->s_fpb); + vfs_dq_free_block(inode, uspi->s_fpb); fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1); uspi->cs_total.cs_nbfree++; @@ -556,7 +556,7 @@ static u64 ufs_add_fragments(struct inode *inode, u64 fragment, fs32_add(sb, &ucg->cg_frsum[fragsize - count], 1); for (i = oldcount; i < newcount; i++) ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i); - if(DQUOT_ALLOC_BLOCK(inode, count)) { + if (vfs_dq_alloc_block(inode, count)) { *err = -EDQUOT; return 0; } @@ -664,7 +664,7 @@ cg_found: for (i = count; i < uspi->s_fpb; i++) ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i); i = uspi->s_fpb - count; - DQUOT_FREE_BLOCK(inode, i); + vfs_dq_free_block(inode, i); fs32_add(sb, &ucg->cg_cs.cs_nffree, i); uspi->cs_total.cs_nffree += i; @@ -676,7 +676,7 @@ cg_found: result = ufs_bitmap_search (sb, ucpi, goal, allocsize); if (result == INVBLOCK) return 0; - if(DQUOT_ALLOC_BLOCK(inode, count)) { + if (vfs_dq_alloc_block(inode, count)) { *err = -EDQUOT; return 0; } @@ -747,7 +747,7 @@ gotit: ubh_clrblock (UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) ufs_clusteracct (sb, ucpi, blkno, -1); - if(DQUOT_ALLOC_BLOCK(inode, uspi->s_fpb)) { + if (vfs_dq_alloc_block(inode, uspi->s_fpb)) { *err = -EDQUOT; return INVBLOCK; } diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c index 6f5dcf00609..3527c00fef0 100644 --- a/fs/ufs/ialloc.c +++ b/fs/ufs/ialloc.c @@ -95,8 +95,8 @@ void ufs_free_inode (struct inode * inode) is_directory = S_ISDIR(inode->i_mode); - DQUOT_FREE_INODE(inode); - DQUOT_DROP(inode); + vfs_dq_free_inode(inode); + vfs_dq_drop(inode); clear_inode (inode); @@ -355,8 +355,8 @@ cg_found: unlock_super (sb); - if (DQUOT_ALLOC_INODE(inode)) { - DQUOT_DROP(inode); + if (vfs_dq_alloc_inode(inode)) { + vfs_dq_drop(inode); err = -EDQUOT; goto fail_without_unlock; } -- GitLab From bacfb7c2e5d10f40f7adb23aeeffc824b839eaa8 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 26 Jan 2009 17:20:46 +0100 Subject: [PATCH 4574/4982] udf: Use lowercase names of quota functions Use lowercase names of quota functions instead of old uppercase ones. Signed-off-by: Jan Kara --- fs/udf/balloc.c | 14 +++++++------- fs/udf/ialloc.c | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c index 1b809bd494b..2bb788a2acb 100644 --- a/fs/udf/balloc.c +++ b/fs/udf/balloc.c @@ -206,7 +206,7 @@ static void udf_bitmap_free_blocks(struct super_block *sb, ((char *)bh->b_data)[(bit + i) >> 3]); } else { if (inode) - DQUOT_FREE_BLOCK(inode, 1); + vfs_dq_free_block(inode, 1); udf_add_free_space(sbi, sbi->s_partition, 1); } } @@ -261,11 +261,11 @@ static int udf_bitmap_prealloc_blocks(struct super_block *sb, while (bit < (sb->s_blocksize << 3) && block_count > 0) { if (!udf_test_bit(bit, bh->b_data)) goto out; - else if (DQUOT_PREALLOC_BLOCK(inode, 1)) + else if (vfs_dq_prealloc_block(inode, 1)) goto out; else if (!udf_clear_bit(bit, bh->b_data)) { udf_debug("bit already cleared for block %d\n", bit); - DQUOT_FREE_BLOCK(inode, 1); + vfs_dq_free_block(inode, 1); goto out; } block_count--; @@ -393,7 +393,7 @@ got_block: /* * Check quota for allocation of this block. */ - if (inode && DQUOT_ALLOC_BLOCK(inode, 1)) { + if (inode && vfs_dq_alloc_block(inode, 1)) { mutex_unlock(&sbi->s_alloc_mutex); *err = -EDQUOT; return 0; @@ -452,7 +452,7 @@ static void udf_table_free_blocks(struct super_block *sb, /* We do this up front - There are some error conditions that could occure, but.. oh well */ if (inode) - DQUOT_FREE_BLOCK(inode, count); + vfs_dq_free_block(inode, count); if (udf_add_free_space(sbi, sbi->s_partition, count)) mark_buffer_dirty(sbi->s_lvid_bh); @@ -700,7 +700,7 @@ static int udf_table_prealloc_blocks(struct super_block *sb, epos.offset -= adsize; alloc_count = (elen >> sb->s_blocksize_bits); - if (inode && DQUOT_PREALLOC_BLOCK(inode, + if (inode && vfs_dq_prealloc_block(inode, alloc_count > block_count ? block_count : alloc_count)) alloc_count = 0; else if (alloc_count > block_count) { @@ -806,7 +806,7 @@ static int udf_table_new_block(struct super_block *sb, goal_eloc.logicalBlockNum++; goal_elen -= sb->s_blocksize; - if (inode && DQUOT_ALLOC_BLOCK(inode, 1)) { + if (inode && vfs_dq_alloc_block(inode, 1)) { brelse(goal_epos.bh); mutex_unlock(&sbi->s_alloc_mutex); *err = -EDQUOT; diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c index 31fc84297dd..47dbe5613f9 100644 --- a/fs/udf/ialloc.c +++ b/fs/udf/ialloc.c @@ -36,8 +36,8 @@ void udf_free_inode(struct inode *inode) * Note: we must free any quota before locking the superblock, * as writing the quota to disk may need the lock as well. */ - DQUOT_FREE_INODE(inode); - DQUOT_DROP(inode); + vfs_dq_free_inode(inode); + vfs_dq_drop(inode); clear_inode(inode); @@ -154,8 +154,8 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err) insert_inode_hash(inode); mark_inode_dirty(inode); - if (DQUOT_ALLOC_INODE(inode)) { - DQUOT_DROP(inode); + if (vfs_dq_alloc_inode(inode)) { + vfs_dq_drop(inode); inode->i_flags |= S_NOQUOTA; inode->i_nlink = 0; iput(inode); -- GitLab From c94d2a22f26bdb11d3dd817669b940a8c76a8cad Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 26 Jan 2009 17:22:32 +0100 Subject: [PATCH 4575/4982] jfs: Use lowercase names of quota functions Use lowercase names of quota functions instead of old uppercase ones. Signed-off-by: Jan Kara Acked-by: Dave Kleikamp --- fs/jfs/acl.c | 2 +- fs/jfs/inode.c | 6 +++--- fs/jfs/jfs_dtree.c | 18 +++++++++--------- fs/jfs/jfs_extent.c | 10 +++++----- fs/jfs/jfs_inode.c | 4 ++-- fs/jfs/jfs_xtree.c | 14 +++++++------- fs/jfs/namei.c | 6 +++--- fs/jfs/xattr.c | 12 ++++++------ 8 files changed, 36 insertions(+), 36 deletions(-) diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c index d3e5c33665d..a166c1669e8 100644 --- a/fs/jfs/acl.c +++ b/fs/jfs/acl.c @@ -233,7 +233,7 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr) if ((iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) || (iattr->ia_valid & ATTR_GID && iattr->ia_gid != inode->i_gid)) { - if (DQUOT_TRANSFER(inode, iattr)) + if (vfs_dq_transfer(inode, iattr)) return -EDQUOT; } diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c index b00ee9f05a0..b2ae190a77b 100644 --- a/fs/jfs/inode.c +++ b/fs/jfs/inode.c @@ -158,9 +158,9 @@ void jfs_delete_inode(struct inode *inode) /* * Free the inode from the quota allocation. */ - DQUOT_INIT(inode); - DQUOT_FREE_INODE(inode); - DQUOT_DROP(inode); + vfs_dq_init(inode); + vfs_dq_free_inode(inode); + vfs_dq_drop(inode); } clear_inode(inode); diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c index 4dcc0581999..925871e9887 100644 --- a/fs/jfs/jfs_dtree.c +++ b/fs/jfs/jfs_dtree.c @@ -381,10 +381,10 @@ static u32 add_index(tid_t tid, struct inode *ip, s64 bn, int slot) * It's time to move the inline table to an external * page and begin to build the xtree */ - if (DQUOT_ALLOC_BLOCK(ip, sbi->nbperpage)) + if (vfs_dq_alloc_block(ip, sbi->nbperpage)) goto clean_up; if (dbAlloc(ip, 0, sbi->nbperpage, &xaddr)) { - DQUOT_FREE_BLOCK(ip, sbi->nbperpage); + vfs_dq_free_block(ip, sbi->nbperpage); goto clean_up; } @@ -408,7 +408,7 @@ static u32 add_index(tid_t tid, struct inode *ip, s64 bn, int slot) memcpy(&jfs_ip->i_dirtable, temp_table, sizeof (temp_table)); dbFree(ip, xaddr, sbi->nbperpage); - DQUOT_FREE_BLOCK(ip, sbi->nbperpage); + vfs_dq_free_block(ip, sbi->nbperpage); goto clean_up; } ip->i_size = PSIZE; @@ -1027,7 +1027,7 @@ static int dtSplitUp(tid_t tid, n = xlen; /* Allocate blocks to quota. */ - if (DQUOT_ALLOC_BLOCK(ip, n)) { + if (vfs_dq_alloc_block(ip, n)) { rc = -EDQUOT; goto extendOut; } @@ -1308,7 +1308,7 @@ static int dtSplitUp(tid_t tid, /* Rollback quota allocation */ if (rc && quota_allocation) - DQUOT_FREE_BLOCK(ip, quota_allocation); + vfs_dq_free_block(ip, quota_allocation); dtSplitUp_Exit: @@ -1369,7 +1369,7 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split, return -EIO; /* Allocate blocks to quota. */ - if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) { + if (vfs_dq_alloc_block(ip, lengthPXD(pxd))) { release_metapage(rmp); return -EDQUOT; } @@ -1916,7 +1916,7 @@ static int dtSplitRoot(tid_t tid, rp = rmp->data; /* Allocate blocks to quota. */ - if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) { + if (vfs_dq_alloc_block(ip, lengthPXD(pxd))) { release_metapage(rmp); return -EDQUOT; } @@ -2287,7 +2287,7 @@ static int dtDeleteUp(tid_t tid, struct inode *ip, xlen = lengthPXD(&fp->header.self); /* Free quota allocation. */ - DQUOT_FREE_BLOCK(ip, xlen); + vfs_dq_free_block(ip, xlen); /* free/invalidate its buffer page */ discard_metapage(fmp); @@ -2363,7 +2363,7 @@ static int dtDeleteUp(tid_t tid, struct inode *ip, xlen = lengthPXD(&p->header.self); /* Free quota allocation */ - DQUOT_FREE_BLOCK(ip, xlen); + vfs_dq_free_block(ip, xlen); /* free/invalidate its buffer page */ discard_metapage(mp); diff --git a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c index 7ae1e3281de..169802ea07f 100644 --- a/fs/jfs/jfs_extent.c +++ b/fs/jfs/jfs_extent.c @@ -141,7 +141,7 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, bool abnr) } /* Allocate blocks to quota. */ - if (DQUOT_ALLOC_BLOCK(ip, nxlen)) { + if (vfs_dq_alloc_block(ip, nxlen)) { dbFree(ip, nxaddr, (s64) nxlen); mutex_unlock(&JFS_IP(ip)->commit_mutex); return -EDQUOT; @@ -164,7 +164,7 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, bool abnr) */ if (rc) { dbFree(ip, nxaddr, nxlen); - DQUOT_FREE_BLOCK(ip, nxlen); + vfs_dq_free_block(ip, nxlen); mutex_unlock(&JFS_IP(ip)->commit_mutex); return (rc); } @@ -256,7 +256,7 @@ int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, bool abnr) goto exit; /* Allocat blocks to quota. */ - if (DQUOT_ALLOC_BLOCK(ip, nxlen)) { + if (vfs_dq_alloc_block(ip, nxlen)) { dbFree(ip, nxaddr, (s64) nxlen); mutex_unlock(&JFS_IP(ip)->commit_mutex); return -EDQUOT; @@ -297,7 +297,7 @@ int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, bool abnr) /* extend the extent */ if ((rc = xtExtend(0, ip, xoff + xlen, (int) nextend, 0))) { dbFree(ip, xaddr + xlen, delta); - DQUOT_FREE_BLOCK(ip, nxlen); + vfs_dq_free_block(ip, nxlen); goto exit; } } else { @@ -308,7 +308,7 @@ int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, bool abnr) */ if ((rc = xtTailgate(0, ip, xoff, (int) ntail, nxaddr, 0))) { dbFree(ip, nxaddr, nxlen); - DQUOT_FREE_BLOCK(ip, nxlen); + vfs_dq_free_block(ip, nxlen); goto exit; } } diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c index d4d142c2edd..dc0e02159ac 100644 --- a/fs/jfs/jfs_inode.c +++ b/fs/jfs/jfs_inode.c @@ -116,7 +116,7 @@ struct inode *ialloc(struct inode *parent, umode_t mode) /* * Allocate inode to quota. */ - if (DQUOT_ALLOC_INODE(inode)) { + if (vfs_dq_alloc_inode(inode)) { rc = -EDQUOT; goto fail_drop; } @@ -162,7 +162,7 @@ struct inode *ialloc(struct inode *parent, umode_t mode) return inode; fail_drop: - DQUOT_DROP(inode); + vfs_dq_drop(inode); inode->i_flags |= S_NOQUOTA; fail_unlock: inode->i_nlink = 0; diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c index ae3acafb447..a27e26c9056 100644 --- a/fs/jfs/jfs_xtree.c +++ b/fs/jfs/jfs_xtree.c @@ -846,10 +846,10 @@ int xtInsert(tid_t tid, /* transaction id */ hint = addressXAD(xad) + lengthXAD(xad) - 1; } else hint = 0; - if ((rc = DQUOT_ALLOC_BLOCK(ip, xlen))) + if ((rc = vfs_dq_alloc_block(ip, xlen))) goto out; if ((rc = dbAlloc(ip, hint, (s64) xlen, &xaddr))) { - DQUOT_FREE_BLOCK(ip, xlen); + vfs_dq_free_block(ip, xlen); goto out; } } @@ -878,7 +878,7 @@ int xtInsert(tid_t tid, /* transaction id */ /* undo data extent allocation */ if (*xaddrp == 0) { dbFree(ip, xaddr, (s64) xlen); - DQUOT_FREE_BLOCK(ip, xlen); + vfs_dq_free_block(ip, xlen); } return rc; } @@ -1246,7 +1246,7 @@ xtSplitPage(tid_t tid, struct inode *ip, rbn = addressPXD(pxd); /* Allocate blocks to quota. */ - if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) { + if (vfs_dq_alloc_block(ip, lengthPXD(pxd))) { rc = -EDQUOT; goto clean_up; } @@ -1456,7 +1456,7 @@ xtSplitPage(tid_t tid, struct inode *ip, /* Rollback quota allocation. */ if (quota_allocation) - DQUOT_FREE_BLOCK(ip, quota_allocation); + vfs_dq_free_block(ip, quota_allocation); return (rc); } @@ -1513,7 +1513,7 @@ xtSplitRoot(tid_t tid, return -EIO; /* Allocate blocks to quota. */ - if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) { + if (vfs_dq_alloc_block(ip, lengthPXD(pxd))) { release_metapage(rmp); return -EDQUOT; } @@ -3941,7 +3941,7 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag) ip->i_size = newsize; /* update quota allocation to reflect freed blocks */ - DQUOT_FREE_BLOCK(ip, nfreed); + vfs_dq_free_block(ip, nfreed); /* * free tlock of invalidated pages diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index b4de56b851e..9feaa04555d 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -356,7 +356,7 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry) jfs_info("jfs_rmdir: dip:0x%p name:%s", dip, dentry->d_name.name); /* Init inode for quota operations. */ - DQUOT_INIT(ip); + vfs_dq_init(ip); /* directory must be empty to be removed */ if (!dtEmpty(ip)) { @@ -483,7 +483,7 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry) jfs_info("jfs_unlink: dip:0x%p name:%s", dip, dentry->d_name.name); /* Init inode for quota operations. */ - DQUOT_INIT(ip); + vfs_dq_init(ip); if ((rc = get_UCSname(&dname, dentry))) goto out; @@ -1136,7 +1136,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, } else if (new_ip) { IWRITE_LOCK(new_ip, RDWRLOCK_NORMAL); /* Init inode for quota operations. */ - DQUOT_INIT(new_ip); + vfs_dq_init(new_ip); } /* diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index 9b7f2cdaae0..61dfa8173eb 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c @@ -260,14 +260,14 @@ static int ea_write(struct inode *ip, struct jfs_ea_list *ealist, int size, nblocks = (size + (sb->s_blocksize - 1)) >> sb->s_blocksize_bits; /* Allocate new blocks to quota. */ - if (DQUOT_ALLOC_BLOCK(ip, nblocks)) { + if (vfs_dq_alloc_block(ip, nblocks)) { return -EDQUOT; } rc = dbAlloc(ip, INOHINT(ip), nblocks, &blkno); if (rc) { /*Rollback quota allocation. */ - DQUOT_FREE_BLOCK(ip, nblocks); + vfs_dq_free_block(ip, nblocks); return rc; } @@ -332,7 +332,7 @@ static int ea_write(struct inode *ip, struct jfs_ea_list *ealist, int size, failed: /* Rollback quota allocation. */ - DQUOT_FREE_BLOCK(ip, nblocks); + vfs_dq_free_block(ip, nblocks); dbFree(ip, blkno, nblocks); return rc; @@ -538,7 +538,7 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size) if (blocks_needed > current_blocks) { /* Allocate new blocks to quota. */ - if (DQUOT_ALLOC_BLOCK(inode, blocks_needed)) + if (vfs_dq_alloc_block(inode, blocks_needed)) return -EDQUOT; quota_allocation = blocks_needed; @@ -602,7 +602,7 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size) clean_up: /* Rollback quota allocation */ if (quota_allocation) - DQUOT_FREE_BLOCK(inode, quota_allocation); + vfs_dq_free_block(inode, quota_allocation); return (rc); } @@ -677,7 +677,7 @@ static int ea_put(tid_t tid, struct inode *inode, struct ea_buffer *ea_buf, /* If old blocks exist, they must be removed from quota allocation. */ if (old_blocks) - DQUOT_FREE_BLOCK(inode, old_blocks); + vfs_dq_free_block(inode, old_blocks); inode->i_ctime = CURRENT_TIME; -- GitLab From 90c0af05a5a486f7709195e20bb26ad8f67ba5af Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 9 Feb 2009 22:22:21 +0100 Subject: [PATCH 4576/4982] nfsd: Use lowercase names of quota functions Use lowercase names of quota functions instead of old uppercase ones. CC: bfields@fieldses.org CC: neilb@suse.de Signed-off-by: Jan Kara --- fs/nfsd/vfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 6e50aaa56ca..ad38fc9e581 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -356,7 +356,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, put_write_access(inode); goto out_nfserr; } - DQUOT_INIT(inode); + vfs_dq_init(inode); } /* sanitize the mode change */ @@ -723,7 +723,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, else flags = O_WRONLY|O_LARGEFILE; - DQUOT_INIT(inode); + vfs_dq_init(inode); } *filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_path.mnt), flags, cred); -- GitLab From bf84c82d000b9820b01f516d13d328f354f8a8ee Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 26 Jan 2009 17:37:01 +0100 Subject: [PATCH 4577/4982] quota: Remove uppercase aliases for quota functions. Since all users have been converted, remove uppercase names of quota functions. Signed-off-by: Jan Kara --- include/linux/quotaops.h | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index 69b502e5eba..36353d95c8d 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -454,35 +454,4 @@ static inline void vfs_dq_free_block(struct inode *inode, qsize_t nr) vfs_dq_free_space(inode, nr << inode->i_blkbits); } -/* - * Define uppercase equivalents for compatibility with old function names - * Can go away when we think all users have been converted (15/04/2008) - */ -#define DQUOT_INIT(inode) vfs_dq_init(inode) -#define DQUOT_DROP(inode) vfs_dq_drop(inode) -#define DQUOT_PREALLOC_SPACE_NODIRTY(inode, nr) \ - vfs_dq_prealloc_space_nodirty(inode, nr) -#define DQUOT_PREALLOC_SPACE(inode, nr) vfs_dq_prealloc_space(inode, nr) -#define DQUOT_ALLOC_SPACE_NODIRTY(inode, nr) \ - vfs_dq_alloc_space_nodirty(inode, nr) -#define DQUOT_ALLOC_SPACE(inode, nr) vfs_dq_alloc_space(inode, nr) -#define DQUOT_PREALLOC_BLOCK_NODIRTY(inode, nr) \ - vfs_dq_prealloc_block_nodirty(inode, nr) -#define DQUOT_PREALLOC_BLOCK(inode, nr) vfs_dq_prealloc_block(inode, nr) -#define DQUOT_ALLOC_BLOCK_NODIRTY(inode, nr) \ - vfs_dq_alloc_block_nodirty(inode, nr) -#define DQUOT_ALLOC_BLOCK(inode, nr) vfs_dq_alloc_block(inode, nr) -#define DQUOT_ALLOC_INODE(inode) vfs_dq_alloc_inode(inode) -#define DQUOT_FREE_SPACE_NODIRTY(inode, nr) \ - vfs_dq_free_space_nodirty(inode, nr) -#define DQUOT_FREE_SPACE(inode, nr) vfs_dq_free_space(inode, nr) -#define DQUOT_FREE_BLOCK_NODIRTY(inode, nr) \ - vfs_dq_free_block_nodirty(inode, nr) -#define DQUOT_FREE_BLOCK(inode, nr) vfs_dq_free_block(inode, nr) -#define DQUOT_FREE_INODE(inode) vfs_dq_free_inode(inode) -#define DQUOT_TRANSFER(inode, iattr) vfs_dq_transfer(inode, iattr) -#define DQUOT_SYNC(sb) vfs_dq_sync(sb) -#define DQUOT_OFF(sb, remount) vfs_dq_off(sb, remount) -#define DQUOT_ON_REMOUNT(sb) vfs_dq_quota_on_remount(sb) - #endif /* _LINUX_QUOTAOPS_ */ -- GitLab From 7a2435d874388271cfe5046d180751352a1d30a2 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 27 Jan 2009 01:47:11 +0100 Subject: [PATCH 4578/4982] quota: Remove superfluous inlines Remove inlines of large functions to decrease code size (saved 1543 bytes). Signed-off-by: Jan Kara --- fs/quota/dquot.c | 13 +++++++------ fs/quota/quota.c | 2 +- fs/quota/quota_tree.c | 6 +++--- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 4881db32e56..4a37b8e32b4 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -243,7 +243,8 @@ static inline void remove_dquot_hash(struct dquot *dquot) hlist_del_init(&dquot->dq_hash); } -static inline struct dquot *find_dquot(unsigned int hashent, struct super_block *sb, unsigned int id, int type) +static struct dquot *find_dquot(unsigned int hashent, struct super_block *sb, + unsigned int id, int type) { struct hlist_node *node; struct dquot *dquot; @@ -935,7 +936,7 @@ void dquot_free_reserved_space(struct dquot *dquot, qsize_t number) dquot->dq_dqb.dqb_rsvspace -= number; } -static inline void dquot_decr_inodes(struct dquot *dquot, qsize_t number) +static void dquot_decr_inodes(struct dquot *dquot, qsize_t number) { if (sb_dqopt(dquot->dq_sb)->flags & DQUOT_NEGATIVE_USAGE || dquot->dq_dqb.dqb_curinodes >= number) @@ -947,7 +948,7 @@ static inline void dquot_decr_inodes(struct dquot *dquot, qsize_t number) clear_bit(DQ_INODES_B, &dquot->dq_flags); } -static inline void dquot_decr_space(struct dquot *dquot, qsize_t number) +static void dquot_decr_space(struct dquot *dquot, qsize_t number) { if (sb_dqopt(dquot->dq_sb)->flags & DQUOT_NEGATIVE_USAGE || dquot->dq_dqb.dqb_curspace >= number) @@ -974,7 +975,7 @@ static int warning_issued(struct dquot *dquot, const int warntype) #ifdef CONFIG_PRINT_QUOTA_WARNING static int flag_print_warnings = 1; -static inline int need_print_warning(struct dquot *dquot) +static int need_print_warning(struct dquot *dquot) { if (!flag_print_warnings) return 0; @@ -1109,7 +1110,7 @@ err_out: * * Note that this function can sleep. */ -static inline void flush_warnings(struct dquot * const *dquots, char *warntype) +static void flush_warnings(struct dquot *const *dquots, char *warntype) { int i; @@ -1125,7 +1126,7 @@ static inline void flush_warnings(struct dquot * const *dquots, char *warntype) } } -static inline char ignore_hardlimit(struct dquot *dquot) +static int ignore_hardlimit(struct dquot *dquot) { struct mem_dqinfo *info = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_type]; diff --git a/fs/quota/quota.c b/fs/quota/quota.c index d76ada914f9..89541bcbe27 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c @@ -341,7 +341,7 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void * look up a superblock on which quota ops will be performed * - use the name of a block device to find the superblock thereon */ -static inline struct super_block *quotactl_block(const char __user *special) +static struct super_block *quotactl_block(const char __user *special) { #ifdef CONFIG_BLOCK struct block_device *bdev; diff --git a/fs/quota/quota_tree.c b/fs/quota/quota_tree.c index 3a5a90c0896..48e35a48f1c 100644 --- a/fs/quota/quota_tree.c +++ b/fs/quota/quota_tree.c @@ -33,7 +33,7 @@ static int get_index(struct qtree_mem_dqinfo *info, qid_t id, int depth) } /* Number of entries in one blocks */ -static inline int qtree_dqstr_in_blk(struct qtree_mem_dqinfo *info) +static int qtree_dqstr_in_blk(struct qtree_mem_dqinfo *info) { return (info->dqi_usable_bs - sizeof(struct qt_disk_dqdbheader)) / info->dqi_entry_size; @@ -47,7 +47,7 @@ static char *getdqbuf(size_t size) return buf; } -static inline ssize_t read_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf) +static ssize_t read_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf) { struct super_block *sb = info->dqi_sb; @@ -56,7 +56,7 @@ static inline ssize_t read_blk(struct qtree_mem_dqinfo *info, uint blk, char *bu info->dqi_usable_bs, blk << info->dqi_blocksize_bits); } -static inline ssize_t write_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf) +static ssize_t write_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf) { struct super_block *sb = info->dqi_sb; -- GitLab From 268157ba673e2a868c167211e39fcad4ada5fd1e Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 27 Jan 2009 15:47:22 +0100 Subject: [PATCH 4579/4982] quota: Coding style fixes Wrap long lines, remove assignments from conditions, rewrite two overcomplicated for loops. Signed-off-by: Jan Kara --- fs/quota/dquot.c | 181 ++++++++++++++++++++++++++---------------- fs/quota/quota.c | 35 +++++--- fs/quota/quota_tree.c | 42 ++++++---- fs/quota/quota_v1.c | 48 +++++++---- fs/quota/quota_v2.c | 3 +- 5 files changed, 198 insertions(+), 111 deletions(-) diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 4a37b8e32b4..a1bd5eabbe5 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -156,7 +156,9 @@ void unregister_quota_format(struct quota_format_type *fmt) struct quota_format_type **actqf; spin_lock(&dq_list_lock); - for (actqf = "a_formats; *actqf && *actqf != fmt; actqf = &(*actqf)->qf_next); + for (actqf = "a_formats; *actqf && *actqf != fmt; + actqf = &(*actqf)->qf_next) + ; if (*actqf) *actqf = (*actqf)->qf_next; spin_unlock(&dq_list_lock); @@ -168,18 +170,25 @@ static struct quota_format_type *find_quota_format(int id) struct quota_format_type *actqf; spin_lock(&dq_list_lock); - for (actqf = quota_formats; actqf && actqf->qf_fmt_id != id; actqf = actqf->qf_next); + for (actqf = quota_formats; actqf && actqf->qf_fmt_id != id; + actqf = actqf->qf_next) + ; if (!actqf || !try_module_get(actqf->qf_owner)) { int qm; spin_unlock(&dq_list_lock); - for (qm = 0; module_names[qm].qm_fmt_id && module_names[qm].qm_fmt_id != id; qm++); - if (!module_names[qm].qm_fmt_id || request_module(module_names[qm].qm_mod_name)) + for (qm = 0; module_names[qm].qm_fmt_id && + module_names[qm].qm_fmt_id != id; qm++) + ; + if (!module_names[qm].qm_fmt_id || + request_module(module_names[qm].qm_mod_name)) return NULL; spin_lock(&dq_list_lock); - for (actqf = quota_formats; actqf && actqf->qf_fmt_id != id; actqf = actqf->qf_next); + for (actqf = quota_formats; actqf && actqf->qf_fmt_id != id; + actqf = actqf->qf_next) + ; if (actqf && !try_module_get(actqf->qf_owner)) actqf = NULL; } @@ -234,7 +243,8 @@ hashfn(const struct super_block *sb, unsigned int id, int type) */ static inline void insert_dquot_hash(struct dquot *dquot) { - struct hlist_head *head = dquot_hash + hashfn(dquot->dq_sb, dquot->dq_id, dquot->dq_type); + struct hlist_head *head; + head = dquot_hash + hashfn(dquot->dq_sb, dquot->dq_id, dquot->dq_type); hlist_add_head(&dquot->dq_hash, head); } @@ -251,7 +261,8 @@ static struct dquot *find_dquot(unsigned int hashent, struct super_block *sb, hlist_for_each (node, dquot_hash+hashent) { dquot = hlist_entry(node, struct dquot, dq_hash); - if (dquot->dq_sb == sb && dquot->dq_id == id && dquot->dq_type == type) + if (dquot->dq_sb == sb && dquot->dq_id == id && + dquot->dq_type == type) return dquot; } return NULL; @@ -351,8 +362,10 @@ int dquot_acquire(struct dquot *dquot) if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && !dquot->dq_off) { ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot); /* Write the info if needed */ - if (info_dirty(&dqopt->info[dquot->dq_type])) - ret2 = dqopt->ops[dquot->dq_type]->write_file_info(dquot->dq_sb, dquot->dq_type); + if (info_dirty(&dqopt->info[dquot->dq_type])) { + ret2 = dqopt->ops[dquot->dq_type]->write_file_info( + dquot->dq_sb, dquot->dq_type); + } if (ret < 0) goto out_iolock; if (ret2 < 0) { @@ -387,8 +400,10 @@ int dquot_commit(struct dquot *dquot) * => we have better not writing it */ if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) { ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot); - if (info_dirty(&dqopt->info[dquot->dq_type])) - ret2 = dqopt->ops[dquot->dq_type]->write_file_info(dquot->dq_sb, dquot->dq_type); + if (info_dirty(&dqopt->info[dquot->dq_type])) { + ret2 = dqopt->ops[dquot->dq_type]->write_file_info( + dquot->dq_sb, dquot->dq_type); + } if (ret >= 0) ret = ret2; } @@ -414,8 +429,10 @@ int dquot_release(struct dquot *dquot) if (dqopt->ops[dquot->dq_type]->release_dqblk) { ret = dqopt->ops[dquot->dq_type]->release_dqblk(dquot); /* Write the info */ - if (info_dirty(&dqopt->info[dquot->dq_type])) - ret2 = dqopt->ops[dquot->dq_type]->write_file_info(dquot->dq_sb, dquot->dq_type); + if (info_dirty(&dqopt->info[dquot->dq_type])) { + ret2 = dqopt->ops[dquot->dq_type]->write_file_info( + dquot->dq_sb, dquot->dq_type); + } if (ret >= 0) ret = ret2; } @@ -543,7 +560,8 @@ int vfs_quota_sync(struct super_block *sb, int type) spin_lock(&dq_list_lock); dirty = &dqopt->info[cnt].dqi_dirty_list; while (!list_empty(dirty)) { - dquot = list_first_entry(dirty, struct dquot, dq_dirty); + dquot = list_first_entry(dirty, struct dquot, + dq_dirty); /* Dirty and inactive can be only bad dquot... */ if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) { clear_dquot_dirty(dquot); @@ -763,11 +781,12 @@ we_slept: dqstats.lookups++; spin_unlock(&dq_list_lock); } - /* Wait for dq_lock - after this we know that either dquot_release() is already - * finished or it will be canceled due to dq_count > 1 test */ + /* Wait for dq_lock - after this we know that either dquot_release() is + * already finished or it will be canceled due to dq_count > 1 test */ wait_on_dquot(dquot); - /* Read the dquot and instantiate it (everything done only if needed) */ - if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && sb->dq_op->acquire_dquot(dquot) < 0) { + /* Read the dquot / allocate space in quota file */ + if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && + sb->dq_op->acquire_dquot(dquot) < 0) { dqput(dquot); dquot = NULL; goto out; @@ -828,7 +847,10 @@ static void add_dquot_ref(struct super_block *sb, int type) iput(old_inode); } -/* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */ +/* + * Return 0 if dqput() won't block. + * (note that 1 doesn't necessarily mean blocking) + */ static inline int dqput_blocks(struct dquot *dquot) { if (atomic_read(&dquot->dq_count) <= 1) @@ -836,8 +858,11 @@ static inline int dqput_blocks(struct dquot *dquot) return 0; } -/* Remove references to dquots from inode - add dquot to list for freeing if needed */ -/* We can't race with anybody because we hold dqptr_sem for writing... */ +/* + * Remove references to dquots from inode and add dquot to list for freeing + * if we have the last referece to dquot + * We can't race with anybody because we hold dqptr_sem for writing... + */ static int remove_inode_dquot_ref(struct inode *inode, int type, struct list_head *tofree_head) { @@ -851,7 +876,9 @@ static int remove_inode_dquot_ref(struct inode *inode, int type, printk(KERN_WARNING "VFS: Adding dquot with dq_count %d to dispose list.\n", atomic_read(&dquot->dq_count)); #endif spin_lock(&dq_list_lock); - list_add(&dquot->dq_free, tofree_head); /* As dquot must have currently users it can't be on the free list... */ + /* As dquot must have currently users it can't be on + * the free list... */ + list_add(&dquot->dq_free, tofree_head); spin_unlock(&dq_list_lock); return 1; } @@ -861,19 +888,22 @@ static int remove_inode_dquot_ref(struct inode *inode, int type, return 0; } -/* Free list of dquots - called from inode.c */ -/* dquots are removed from inodes, no new references can be got so we are the only ones holding reference */ +/* + * Free list of dquots + * Dquots are removed from inodes and no new references can be got so we are + * the only ones holding reference + */ static void put_dquot_list(struct list_head *tofree_head) { struct list_head *act_head; struct dquot *dquot; act_head = tofree_head->next; - /* So now we have dquots on the list... Just free them */ while (act_head != tofree_head) { dquot = list_entry(act_head, struct dquot, dq_free); act_head = act_head->next; - list_del_init(&dquot->dq_free); /* Remove dquot from the list so we won't have problems... */ + /* Remove dquot from the list so we won't have problems... */ + list_del_init(&dquot->dq_free); dqput(dquot); } } @@ -1131,37 +1161,42 @@ static int ignore_hardlimit(struct dquot *dquot) struct mem_dqinfo *info = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_type]; return capable(CAP_SYS_RESOURCE) && - (info->dqi_format->qf_fmt_id != QFMT_VFS_OLD || !(info->dqi_flags & V1_DQF_RSQUASH)); + (info->dqi_format->qf_fmt_id != QFMT_VFS_OLD || + !(info->dqi_flags & V1_DQF_RSQUASH)); } /* needs dq_data_lock */ static int check_idq(struct dquot *dquot, qsize_t inodes, char *warntype) { + qsize_t newinodes = dquot->dq_dqb.dqb_curinodes + inodes; + *warntype = QUOTA_NL_NOWARN; if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type) || test_bit(DQ_FAKE_B, &dquot->dq_flags)) return QUOTA_OK; if (dquot->dq_dqb.dqb_ihardlimit && - (dquot->dq_dqb.dqb_curinodes + inodes) > dquot->dq_dqb.dqb_ihardlimit && + newinodes > dquot->dq_dqb.dqb_ihardlimit && !ignore_hardlimit(dquot)) { *warntype = QUOTA_NL_IHARDWARN; return NO_QUOTA; } if (dquot->dq_dqb.dqb_isoftlimit && - (dquot->dq_dqb.dqb_curinodes + inodes) > dquot->dq_dqb.dqb_isoftlimit && - dquot->dq_dqb.dqb_itime && get_seconds() >= dquot->dq_dqb.dqb_itime && + newinodes > dquot->dq_dqb.dqb_isoftlimit && + dquot->dq_dqb.dqb_itime && + get_seconds() >= dquot->dq_dqb.dqb_itime && !ignore_hardlimit(dquot)) { *warntype = QUOTA_NL_ISOFTLONGWARN; return NO_QUOTA; } if (dquot->dq_dqb.dqb_isoftlimit && - (dquot->dq_dqb.dqb_curinodes + inodes) > dquot->dq_dqb.dqb_isoftlimit && + newinodes > dquot->dq_dqb.dqb_isoftlimit && dquot->dq_dqb.dqb_itime == 0) { *warntype = QUOTA_NL_ISOFTWARN; - dquot->dq_dqb.dqb_itime = get_seconds() + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_igrace; + dquot->dq_dqb.dqb_itime = get_seconds() + + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_igrace; } return QUOTA_OK; @@ -1171,9 +1206,10 @@ static int check_idq(struct dquot *dquot, qsize_t inodes, char *warntype) static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *warntype) { qsize_t tspace; + struct super_block *sb = dquot->dq_sb; *warntype = QUOTA_NL_NOWARN; - if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type) || + if (!sb_has_quota_limits_enabled(sb, dquot->dq_type) || test_bit(DQ_FAKE_B, &dquot->dq_flags)) return QUOTA_OK; @@ -1190,7 +1226,8 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war if (dquot->dq_dqb.dqb_bsoftlimit && tspace > dquot->dq_dqb.dqb_bsoftlimit && - dquot->dq_dqb.dqb_btime && get_seconds() >= dquot->dq_dqb.dqb_btime && + dquot->dq_dqb.dqb_btime && + get_seconds() >= dquot->dq_dqb.dqb_btime && !ignore_hardlimit(dquot)) { if (!prealloc) *warntype = QUOTA_NL_BSOFTLONGWARN; @@ -1202,7 +1239,8 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war dquot->dq_dqb.dqb_btime == 0) { if (!prealloc) { *warntype = QUOTA_NL_BSOFTWARN; - dquot->dq_dqb.dqb_btime = get_seconds() + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_bgrace; + dquot->dq_dqb.dqb_btime = get_seconds() + + sb_dqopt(sb)->info[dquot->dq_type].dqi_bgrace; } else /* @@ -1217,15 +1255,18 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war static int info_idq_free(struct dquot *dquot, qsize_t inodes) { + qsize_t newinodes; + if (test_bit(DQ_FAKE_B, &dquot->dq_flags) || dquot->dq_dqb.dqb_curinodes <= dquot->dq_dqb.dqb_isoftlimit || !sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type)) return QUOTA_NL_NOWARN; - if (dquot->dq_dqb.dqb_curinodes - inodes <= dquot->dq_dqb.dqb_isoftlimit) + newinodes = dquot->dq_dqb.dqb_curinodes - inodes; + if (newinodes <= dquot->dq_dqb.dqb_isoftlimit) return QUOTA_NL_ISOFTBELOW; if (dquot->dq_dqb.dqb_curinodes >= dquot->dq_dqb.dqb_ihardlimit && - dquot->dq_dqb.dqb_curinodes - inodes < dquot->dq_dqb.dqb_ihardlimit) + newinodes < dquot->dq_dqb.dqb_ihardlimit) return QUOTA_NL_IHARDBELOW; return QUOTA_NL_NOWARN; } @@ -1466,7 +1507,8 @@ int dquot_alloc_inode(const struct inode *inode, qsize_t number) for (cnt = 0; cnt < MAXQUOTAS; cnt++) { if (!inode->i_dquot[cnt]) continue; - if (check_idq(inode->i_dquot[cnt], number, warntype+cnt) == NO_QUOTA) + if (check_idq(inode->i_dquot[cnt], number, warntype+cnt) + == NO_QUOTA) goto warn_put_all; } @@ -1673,19 +1715,13 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr) transfer_from[cnt] = NULL; transfer_to[cnt] = NULL; warntype_to[cnt] = QUOTA_NL_NOWARN; - switch (cnt) { - case USRQUOTA: - if (!chuid) - continue; - transfer_to[cnt] = dqget(inode->i_sb, iattr->ia_uid, cnt); - break; - case GRPQUOTA: - if (!chgid) - continue; - transfer_to[cnt] = dqget(inode->i_sb, iattr->ia_gid, cnt); - break; - } } + if (chuid) + transfer_to[USRQUOTA] = dqget(inode->i_sb, iattr->ia_uid, + USRQUOTA); + if (chgid) + transfer_to[GRPQUOTA] = dqget(inode->i_sb, iattr->ia_gid, + GRPQUOTA); down_write(&sb_dqopt(inode->i_sb)->dqptr_sem); /* Now recheck reliably when holding dqptr_sem */ @@ -1881,8 +1917,8 @@ int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags) drop_dquot_ref(sb, cnt); invalidate_dquots(sb, cnt); /* - * Now all dquots should be invalidated, all writes done so we should be only - * users of the info. No locks needed. + * Now all dquots should be invalidated, all writes done so we + * should be only users of the info. No locks needed. */ if (info_dirty(&dqopt->info[cnt])) sb->dq_op->write_info(sb, cnt); @@ -1920,10 +1956,12 @@ int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags) /* If quota was reenabled in the meantime, we have * nothing to do */ if (!sb_has_quota_loaded(sb, cnt)) { - mutex_lock_nested(&toputinode[cnt]->i_mutex, I_MUTEX_QUOTA); + mutex_lock_nested(&toputinode[cnt]->i_mutex, + I_MUTEX_QUOTA); toputinode[cnt]->i_flags &= ~(S_IMMUTABLE | S_NOATIME | S_NOQUOTA); - truncate_inode_pages(&toputinode[cnt]->i_data, 0); + truncate_inode_pages(&toputinode[cnt]->i_data, + 0); mutex_unlock(&toputinode[cnt]->i_mutex); mark_inode_dirty(toputinode[cnt]); } @@ -2013,7 +2051,8 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, * possible) Also nobody should write to the file - we use * special IO operations which ignore the immutable bit. */ down_write(&dqopt->dqptr_sem); - oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE | S_NOQUOTA); + oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE | + S_NOQUOTA); inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE; up_write(&dqopt->dqptr_sem); sb->dq_op->drop(inode); @@ -2032,7 +2071,8 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, dqopt->info[type].dqi_fmt_id = format_id; INIT_LIST_HEAD(&dqopt->info[type].dqi_dirty_list); mutex_lock(&dqopt->dqio_mutex); - if ((error = dqopt->ops[type]->read_file_info(sb, type)) < 0) { + error = dqopt->ops[type]->read_file_info(sb, type); + if (error < 0) { mutex_unlock(&dqopt->dqio_mutex); goto out_file_init; } @@ -2254,7 +2294,8 @@ static void do_get_dqblk(struct dquot *dquot, struct if_dqblk *di) spin_unlock(&dq_data_lock); } -int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di) +int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, + struct if_dqblk *di) { struct dquot *dquot; @@ -2318,22 +2359,25 @@ static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di) } if (check_blim) { - if (!dm->dqb_bsoftlimit || dm->dqb_curspace < dm->dqb_bsoftlimit) { + if (!dm->dqb_bsoftlimit || + dm->dqb_curspace < dm->dqb_bsoftlimit) { dm->dqb_btime = 0; clear_bit(DQ_BLKS_B, &dquot->dq_flags); - } - else if (!(di->dqb_valid & QIF_BTIME)) /* Set grace only if user hasn't provided his own... */ + } else if (!(di->dqb_valid & QIF_BTIME)) + /* Set grace only if user hasn't provided his own... */ dm->dqb_btime = get_seconds() + dqi->dqi_bgrace; } if (check_ilim) { - if (!dm->dqb_isoftlimit || dm->dqb_curinodes < dm->dqb_isoftlimit) { + if (!dm->dqb_isoftlimit || + dm->dqb_curinodes < dm->dqb_isoftlimit) { dm->dqb_itime = 0; clear_bit(DQ_INODES_B, &dquot->dq_flags); - } - else if (!(di->dqb_valid & QIF_ITIME)) /* Set grace only if user hasn't provided his own... */ + } else if (!(di->dqb_valid & QIF_ITIME)) + /* Set grace only if user hasn't provided his own... */ dm->dqb_itime = get_seconds() + dqi->dqi_igrace; } - if (dm->dqb_bhardlimit || dm->dqb_bsoftlimit || dm->dqb_ihardlimit || dm->dqb_isoftlimit) + if (dm->dqb_bhardlimit || dm->dqb_bsoftlimit || dm->dqb_ihardlimit || + dm->dqb_isoftlimit) clear_bit(DQ_FAKE_B, &dquot->dq_flags); else set_bit(DQ_FAKE_B, &dquot->dq_flags); @@ -2343,7 +2387,8 @@ static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di) return 0; } -int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di) +int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, + struct if_dqblk *di) { struct dquot *dquot; int rc; @@ -2400,7 +2445,8 @@ int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii) if (ii->dqi_valid & IIF_IGRACE) mi->dqi_igrace = ii->dqi_igrace; if (ii->dqi_valid & IIF_FLAGS) - mi->dqi_flags = (mi->dqi_flags & ~DQF_MASK) | (ii->dqi_flags & DQF_MASK); + mi->dqi_flags = (mi->dqi_flags & ~DQF_MASK) | + (ii->dqi_flags & DQF_MASK); spin_unlock(&dq_data_lock); mark_info_dirty(sb, type); /* Force write to disk */ @@ -2559,7 +2605,8 @@ static int __init dquot_init(void) #ifdef CONFIG_QUOTA_NETLINK_INTERFACE if (genl_register_family("a_genl_family) != 0) - printk(KERN_ERR "VFS: Failed to create quota netlink interface.\n"); + printk(KERN_ERR + "VFS: Failed to create quota netlink interface.\n"); #endif return 0; diff --git a/fs/quota/quota.c b/fs/quota/quota.c index 89541bcbe27..b7f5a468f07 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c @@ -20,7 +20,8 @@ #include /* Check validity of generic quotactl commands */ -static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id) +static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, + qid_t id) { if (type >= MAXQUOTAS) return -EINVAL; @@ -72,7 +73,8 @@ static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid case Q_SETINFO: case Q_SETQUOTA: case Q_GETQUOTA: - /* This is just informative test so we are satisfied without a lock */ + /* This is just an informative test so we are satisfied + * without the lock */ if (!sb_has_quota_active(sb, type)) return -ESRCH; } @@ -92,7 +94,8 @@ static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid } /* Check validity of XFS Quota Manager commands */ -static int xqm_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id) +static int xqm_quotactl_valid(struct super_block *sb, int type, int cmd, + qid_t id) { if (type >= XQM_MAXQUOTAS) return -EINVAL; @@ -142,7 +145,8 @@ static int xqm_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t i return 0; } -static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id) +static int check_quotactl_valid(struct super_block *sb, int type, int cmd, + qid_t id) { int error; @@ -180,7 +184,8 @@ static void quota_sync_sb(struct super_block *sb, int type) continue; if (!sb_has_quota_active(sb, cnt)) continue; - mutex_lock_nested(&sb_dqopt(sb)->files[cnt]->i_mutex, I_MUTEX_QUOTA); + mutex_lock_nested(&sb_dqopt(sb)->files[cnt]->i_mutex, + I_MUTEX_QUOTA); truncate_inode_pages(&sb_dqopt(sb)->files[cnt]->i_data, 0); mutex_unlock(&sb_dqopt(sb)->files[cnt]->i_mutex); } @@ -200,14 +205,15 @@ void sync_dquots(struct super_block *sb, int type) spin_lock(&sb_lock); restart: list_for_each_entry(sb, &super_blocks, s_list) { - /* This test just improves performance so it needn't be reliable... */ + /* This test just improves performance so it needn't be + * reliable... */ for (cnt = 0; cnt < MAXQUOTAS; cnt++) { if (type != -1 && type != cnt) continue; if (!sb_has_quota_active(sb, cnt)) continue; if (!info_dirty(&sb_dqopt(sb)->info[cnt]) && - list_empty(&sb_dqopt(sb)->info[cnt].dqi_dirty_list)) + list_empty(&sb_dqopt(sb)->info[cnt].dqi_dirty_list)) continue; break; } @@ -227,7 +233,8 @@ restart: } /* Copy parameters and call proper function */ -static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void __user *addr) +static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, + void __user *addr) { int ret; @@ -235,7 +242,8 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void case Q_QUOTAON: { char *pathname; - if (IS_ERR(pathname = getname(addr))) + pathname = getname(addr); + if (IS_ERR(pathname)) return PTR_ERR(pathname); ret = sb->s_qcop->quota_on(sb, type, id, pathname, 0); putname(pathname); @@ -261,7 +269,8 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void case Q_GETINFO: { struct if_dqinfo info; - if ((ret = sb->s_qcop->get_info(sb, type, &info))) + ret = sb->s_qcop->get_info(sb, type, &info); + if (ret) return ret; if (copy_to_user(addr, &info, sizeof(info))) return -EFAULT; @@ -277,7 +286,8 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void case Q_GETQUOTA: { struct if_dqblk idq; - if ((ret = sb->s_qcop->get_dqblk(sb, type, id, &idq))) + ret = sb->s_qcop->get_dqblk(sb, type, id, &idq); + if (ret) return ret; if (copy_to_user(addr, &idq, sizeof(idq))) return -EFAULT; @@ -322,7 +332,8 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void case Q_XGETQUOTA: { struct fs_disk_quota fdq; - if ((ret = sb->s_qcop->get_xquota(sb, type, id, &fdq))) + ret = sb->s_qcop->get_xquota(sb, type, id, &fdq); + if (ret) return ret; if (copy_to_user(addr, &fdq, sizeof(fdq))) return -EFAULT; diff --git a/fs/quota/quota_tree.c b/fs/quota/quota_tree.c index 48e35a48f1c..f81f4bcfb17 100644 --- a/fs/quota/quota_tree.c +++ b/fs/quota/quota_tree.c @@ -43,7 +43,8 @@ static char *getdqbuf(size_t size) { char *buf = kmalloc(size, GFP_NOFS); if (!buf) - printk(KERN_WARNING "VFS: Not enough memory for quota buffers.\n"); + printk(KERN_WARNING + "VFS: Not enough memory for quota buffers.\n"); return buf; } @@ -113,7 +114,8 @@ static int put_free_dqblk(struct qtree_mem_dqinfo *info, char *buf, uint blk) } /* Remove given block from the list of blocks with free entries */ -static int remove_free_dqentry(struct qtree_mem_dqinfo *info, char *buf, uint blk) +static int remove_free_dqentry(struct qtree_mem_dqinfo *info, char *buf, + uint blk) { char *tmpbuf = getdqbuf(info->dqi_usable_bs); struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf; @@ -150,7 +152,9 @@ static int remove_free_dqentry(struct qtree_mem_dqinfo *info, char *buf, uint bl dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0); /* No matter whether write succeeds block is out of list */ if (write_blk(info, blk, buf) < 0) - printk(KERN_ERR "VFS: Can't write block (%u) with free entries.\n", blk); + printk(KERN_ERR + "VFS: Can't write block (%u) with free entries.\n", + blk); return 0; out_buf: kfree(tmpbuf); @@ -158,7 +162,8 @@ out_buf: } /* Insert given block to the beginning of list with free entries */ -static int insert_free_dqentry(struct qtree_mem_dqinfo *info, char *buf, uint blk) +static int insert_free_dqentry(struct qtree_mem_dqinfo *info, char *buf, + uint blk) { char *tmpbuf = getdqbuf(info->dqi_usable_bs); struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf; @@ -230,7 +235,8 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info, return 0; } memset(buf, 0, info->dqi_usable_bs); - /* This is enough as block is already zeroed and entry list is empty... */ + /* This is enough as the block is already zeroed and the entry + * list is empty... */ info->dqi_free_entry = blk; mark_info_dirty(dquot->dq_sb, dquot->dq_type); } @@ -246,10 +252,12 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info, } le16_add_cpu(&dh->dqdh_entries, 1); /* Find free structure in block */ - for (i = 0, ddquot = buf + sizeof(struct qt_disk_dqdbheader); - i < qtree_dqstr_in_blk(info) && !qtree_entry_unused(info, ddquot); - i++, ddquot += info->dqi_entry_size) - ; + ddquot = buf + sizeof(struct qt_disk_dqdbheader); + for (i = 0; i < qtree_dqstr_in_blk(info); i++) { + if (qtree_entry_unused(info, ddquot)) + break; + ddquot += info->dqi_entry_size; + } #ifdef __QUOTA_QT_PARANOIA if (i == qtree_dqstr_in_blk(info)) { printk(KERN_ERR "VFS: find_free_dqentry(): Data block full " @@ -340,7 +348,8 @@ static inline int dq_insert_tree(struct qtree_mem_dqinfo *info, } /* - * We don't have to be afraid of deadlocks as we never have quotas on quota files... + * We don't have to be afraid of deadlocks as we never have quotas on quota + * files... */ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) { @@ -515,10 +524,12 @@ static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info, printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk); goto out_buf; } - for (i = 0, ddquot = buf + sizeof(struct qt_disk_dqdbheader); - i < qtree_dqstr_in_blk(info) && !info->dqi_ops->is_id(ddquot, dquot); - i++, ddquot += info->dqi_entry_size) - ; + ddquot = buf + sizeof(struct qt_disk_dqdbheader); + for (i = 0; i < qtree_dqstr_in_blk(info); i++) { + if (info->dqi_ops->is_id(ddquot, dquot)) + break; + ddquot += info->dqi_entry_size; + } if (i == qtree_dqstr_in_blk(info)) { printk(KERN_ERR "VFS: Quota for id %u referenced " "but not present.\n", dquot->dq_id); @@ -632,7 +643,8 @@ EXPORT_SYMBOL(qtree_read_dquot); * the only one operating on dquot (thanks to dq_lock) */ int qtree_release_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) { - if (test_bit(DQ_FAKE_B, &dquot->dq_flags) && !(dquot->dq_dqb.dqb_curinodes | dquot->dq_dqb.dqb_curspace)) + if (test_bit(DQ_FAKE_B, &dquot->dq_flags) && + !(dquot->dq_dqb.dqb_curinodes | dquot->dq_dqb.dqb_curspace)) return qtree_delete_dquot(info, dquot); return 0; } diff --git a/fs/quota/quota_v1.c b/fs/quota/quota_v1.c index b4af1c69ad1..0edcf42b177 100644 --- a/fs/quota/quota_v1.c +++ b/fs/quota/quota_v1.c @@ -62,11 +62,14 @@ static int v1_read_dqblk(struct dquot *dquot) /* Set structure to 0s in case read fails/is after end of file */ memset(&dqblk, 0, sizeof(struct v1_disk_dqblk)); - dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type, (char *)&dqblk, sizeof(struct v1_disk_dqblk), v1_dqoff(dquot->dq_id)); + dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type, (char *)&dqblk, + sizeof(struct v1_disk_dqblk), v1_dqoff(dquot->dq_id)); v1_disk2mem_dqblk(&dquot->dq_dqb, &dqblk); - if (dquot->dq_dqb.dqb_bhardlimit == 0 && dquot->dq_dqb.dqb_bsoftlimit == 0 && - dquot->dq_dqb.dqb_ihardlimit == 0 && dquot->dq_dqb.dqb_isoftlimit == 0) + if (dquot->dq_dqb.dqb_bhardlimit == 0 && + dquot->dq_dqb.dqb_bsoftlimit == 0 && + dquot->dq_dqb.dqb_ihardlimit == 0 && + dquot->dq_dqb.dqb_isoftlimit == 0) set_bit(DQ_FAKE_B, &dquot->dq_flags); dqstats.reads++; @@ -81,13 +84,16 @@ static int v1_commit_dqblk(struct dquot *dquot) v1_mem2disk_dqblk(&dqblk, &dquot->dq_dqb); if (dquot->dq_id == 0) { - dqblk.dqb_btime = sb_dqopt(dquot->dq_sb)->info[type].dqi_bgrace; - dqblk.dqb_itime = sb_dqopt(dquot->dq_sb)->info[type].dqi_igrace; + dqblk.dqb_btime = + sb_dqopt(dquot->dq_sb)->info[type].dqi_bgrace; + dqblk.dqb_itime = + sb_dqopt(dquot->dq_sb)->info[type].dqi_igrace; } ret = 0; if (sb_dqopt(dquot->dq_sb)->files[type]) - ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type, (char *)&dqblk, - sizeof(struct v1_disk_dqblk), v1_dqoff(dquot->dq_id)); + ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type, + (char *)&dqblk, sizeof(struct v1_disk_dqblk), + v1_dqoff(dquot->dq_id)); if (ret != sizeof(struct v1_disk_dqblk)) { printk(KERN_WARNING "VFS: dquota write failed on dev %s\n", dquot->dq_sb->s_id); @@ -130,15 +136,20 @@ static int v1_check_quota_file(struct super_block *sb, int type) return 0; blocks = isize >> BLOCK_SIZE_BITS; off = isize & (BLOCK_SIZE - 1); - if ((blocks % sizeof(struct v1_disk_dqblk) * BLOCK_SIZE + off) % sizeof(struct v1_disk_dqblk)) + if ((blocks % sizeof(struct v1_disk_dqblk) * BLOCK_SIZE + off) % + sizeof(struct v1_disk_dqblk)) return 0; - /* Doublecheck whether we didn't get file with new format - with old quotactl() this could happen */ - size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0); + /* Doublecheck whether we didn't get file with new format - with old + * quotactl() this could happen */ + size = sb->s_op->quota_read(sb, type, (char *)&dqhead, + sizeof(struct v2_disk_dqheader), 0); if (size != sizeof(struct v2_disk_dqheader)) return 1; /* Probably not new format */ if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type]) return 1; /* Definitely not new format */ - printk(KERN_INFO "VFS: %s: Refusing to turn on old quota format on given file. It probably contains newer quota format.\n", sb->s_id); + printk(KERN_INFO + "VFS: %s: Refusing to turn on old quota format on given file." + " It probably contains newer quota format.\n", sb->s_id); return 0; /* Seems like a new format file -> refuse it */ } @@ -148,7 +159,9 @@ static int v1_read_file_info(struct super_block *sb, int type) struct v1_disk_dqblk dqblk; int ret; - if ((ret = sb->s_op->quota_read(sb, type, (char *)&dqblk, sizeof(struct v1_disk_dqblk), v1_dqoff(0))) != sizeof(struct v1_disk_dqblk)) { + ret = sb->s_op->quota_read(sb, type, (char *)&dqblk, + sizeof(struct v1_disk_dqblk), v1_dqoff(0)); + if (ret != sizeof(struct v1_disk_dqblk)) { if (ret >= 0) ret = -EIO; goto out; @@ -157,8 +170,10 @@ static int v1_read_file_info(struct super_block *sb, int type) /* limits are stored as unsigned 32-bit data */ dqopt->info[type].dqi_maxblimit = 0xffffffff; dqopt->info[type].dqi_maxilimit = 0xffffffff; - dqopt->info[type].dqi_igrace = dqblk.dqb_itime ? dqblk.dqb_itime : MAX_IQ_TIME; - dqopt->info[type].dqi_bgrace = dqblk.dqb_btime ? dqblk.dqb_btime : MAX_DQ_TIME; + dqopt->info[type].dqi_igrace = + dqblk.dqb_itime ? dqblk.dqb_itime : MAX_IQ_TIME; + dqopt->info[type].dqi_bgrace = + dqblk.dqb_btime ? dqblk.dqb_btime : MAX_DQ_TIME; out: return ret; } @@ -170,8 +185,9 @@ static int v1_write_file_info(struct super_block *sb, int type) int ret; dqopt->info[type].dqi_flags &= ~DQF_INFO_DIRTY; - if ((ret = sb->s_op->quota_read(sb, type, (char *)&dqblk, - sizeof(struct v1_disk_dqblk), v1_dqoff(0))) != sizeof(struct v1_disk_dqblk)) { + ret = sb->s_op->quota_read(sb, type, (char *)&dqblk, + sizeof(struct v1_disk_dqblk), v1_dqoff(0)); + if (ret != sizeof(struct v1_disk_dqblk)) { if (ret >= 0) ret = -EIO; goto out; diff --git a/fs/quota/quota_v2.c b/fs/quota/quota_v2.c index b618b563635..a5475fb1ae4 100644 --- a/fs/quota/quota_v2.c +++ b/fs/quota/quota_v2.c @@ -54,7 +54,8 @@ static int v2_check_quota_file(struct super_block *sb, int type) static const uint quota_magics[] = V2_INITQMAGICS; static const uint quota_versions[] = V2_INITQVERSIONS; - size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0); + size = sb->s_op->quota_read(sb, type, (char *)&dqhead, + sizeof(struct v2_disk_dqheader), 0); if (size != sizeof(struct v2_disk_dqheader)) { printk("quota_v2: failed read expected=%zd got=%zd\n", sizeof(struct v2_disk_dqheader), size); -- GitLab From 620372a9ffc6f1239a4f379ff145de9e4b5d23ba Mon Sep 17 00:00:00 2001 From: Matt LaPlante Date: Tue, 10 Feb 2009 14:50:34 +0100 Subject: [PATCH 4580/4982] trivial: fix typos/grammar errors in fs/Kconfig Signed-off-by: Matt LaPlante Acked-by: Randy Dunlap Signed-off-by: Jiri Kosina Signed-off-by: Jan Kara --- fs/quota/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/quota/Kconfig b/fs/quota/Kconfig index d9750d86fde..8047e01ef46 100644 --- a/fs/quota/Kconfig +++ b/fs/quota/Kconfig @@ -33,7 +33,7 @@ config PRINT_QUOTA_WARNING Note that this behavior is currently deprecated and may go away in future. Please use notification via netlink socket instead. -# Generic support for tree structured quota files. Seleted when needed. +# Generic support for tree structured quota files. Selected when needed. config QUOTA_TREE tristate -- GitLab From c16831b4cc9b0805adf8ca3001752a7ec10a17bf Mon Sep 17 00:00:00 2001 From: Manish Katiyar Date: Thu, 12 Feb 2009 21:57:04 +0100 Subject: [PATCH 4581/4982] ext2: Zero our b_size in ext2_quota_read() ext2_quota_read() doesn't initialize tmp_bh.b_size before calling ext2_get_block() where we access it. Since it is a local variable it might contain some garbage. Make sure it is filled with reasonable value before passing. Signed-off-by: Manish Katiyar Signed-off-by: Jan Kara --- fs/ext2/super.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 7c6e3606f0e..f983225266d 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -1331,6 +1331,7 @@ static ssize_t ext2_quota_read(struct super_block *sb, int type, char *data, sb->s_blocksize - offset : toread; tmp_bh.b_state = 0; + tmp_bh.b_size = sb->s_blocksize; err = ext2_get_block(inode, blk, &tmp_bh, 0); if (err < 0) return err; -- GitLab From cda6d377ec6b2ee2e58d563d0bd7eb313e0165df Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 25 Mar 2009 21:01:47 -0700 Subject: [PATCH 4582/4982] bridge: bad error handling when adding invalid ether address This fixes an crash when empty bond device is added to a bridge. If an interface with invalid ethernet address (all zero) is added to a bridge, then bridge code detects it when setting up the forward databas entry. But the error unwind is broken, the bridge port object can get freed twice: once when ref count went to zeo, and once by kfree. Since object is never really accessible, just free it. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br_if.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 727c5c510a6..8a96672e2c5 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -426,7 +426,6 @@ err2: err1: kobject_del(&p->kobj); err0: - kobject_put(&p->kobj); dev_set_promiscuity(dev, -1); put_back: dev_put(dev); -- GitLab From 37e73df8c3f19f4733c60ec53c104ff6f79ba467 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 25 Mar 2009 21:58:45 +0000 Subject: [PATCH 4583/4982] e1000: fix tx hang detect logic and address dma mapping issues This patch changes the dma mapping to better support skb_dma_map/skb_dma_unmap and addresses and redefines the tx hang logic to be based off of time stamp instead of if the dma field is populated Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 55 ++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 1f390ceb486..e60faabe902 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2056,6 +2056,7 @@ static void e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter, dev_kfree_skb_any(buffer_info->skb); buffer_info->skb = NULL; } + buffer_info->time_stamp = 0; /* buffer_info must be completely set up in the transmit path */ } @@ -2903,24 +2904,24 @@ static int e1000_tx_map(struct e1000_adapter *adapter, unsigned int mss) { struct e1000_hw *hw = &adapter->hw; + struct e1000_buffer *buffer_info; unsigned int len = skb_headlen(skb); unsigned int offset, size, count = 0, i; unsigned int f; - dma_addr_t map; + dma_addr_t *map; i = tx_ring->next_to_use; if (skb_dma_map(&adapter->pdev->dev, skb, DMA_TO_DEVICE)) { dev_err(&adapter->pdev->dev, "TX DMA map failed\n"); - dev_kfree_skb(skb); - return -2; + return 0; } - map = skb_shinfo(skb)->dma_maps[0]; + map = skb_shinfo(skb)->dma_maps; offset = 0; while (len) { - struct e1000_buffer *buffer_info = &tx_ring->buffer_info[i]; + buffer_info = &tx_ring->buffer_info[i]; size = min(len, max_per_txd); /* Workaround for Controller erratum -- * descriptor for non-tso packet in a linear SKB that follows a @@ -2953,14 +2954,18 @@ static int e1000_tx_map(struct e1000_adapter *adapter, size -= 4; buffer_info->length = size; - buffer_info->dma = map + offset; + buffer_info->dma = map[0] + offset; buffer_info->time_stamp = jiffies; buffer_info->next_to_watch = i; len -= size; offset += size; count++; - if (unlikely(++i == tx_ring->count)) i = 0; + if (len) { + i++; + if (unlikely(i == tx_ring->count)) + i = 0; + } } for (f = 0; f < nr_frags; f++) { @@ -2968,11 +2973,13 @@ static int e1000_tx_map(struct e1000_adapter *adapter, frag = &skb_shinfo(skb)->frags[f]; len = frag->size; - map = skb_shinfo(skb)->dma_maps[f + 1]; offset = 0; while (len) { - struct e1000_buffer *buffer_info; + i++; + if (unlikely(i == tx_ring->count)) + i = 0; + buffer_info = &tx_ring->buffer_info[i]; size = min(len, max_per_txd); /* Workaround for premature desc write-backs @@ -2988,21 +2995,18 @@ static int e1000_tx_map(struct e1000_adapter *adapter, size -= 4; buffer_info->length = size; - buffer_info->dma = map + offset; + buffer_info->dma = map[f + 1] + offset; buffer_info->time_stamp = jiffies; buffer_info->next_to_watch = i; len -= size; offset += size; count++; - if (unlikely(++i == tx_ring->count)) i = 0; } } - i = (i == 0) ? tx_ring->count - 1 : i - 1; tx_ring->buffer_info[i].skb = skb; tx_ring->buffer_info[first].next_to_watch = i; - smp_wmb(); return count; } @@ -3318,14 +3322,20 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if (likely(skb->protocol == htons(ETH_P_IP))) tx_flags |= E1000_TX_FLAGS_IPV4; - e1000_tx_queue(adapter, tx_ring, tx_flags, - e1000_tx_map(adapter, tx_ring, skb, first, - max_per_txd, nr_frags, mss)); + count = e1000_tx_map(adapter, tx_ring, skb, first, max_per_txd, + nr_frags, mss); - netdev->trans_start = jiffies; + if (count) { + e1000_tx_queue(adapter, tx_ring, tx_flags, count); + netdev->trans_start = jiffies; + /* Make sure there is space in the ring for the next send. */ + e1000_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2); - /* Make sure there is space in the ring for the next send. */ - e1000_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2); + } else { + dev_kfree_skb_any(skb); + tx_ring->buffer_info[first].time_stamp = 0; + tx_ring->next_to_use = first; + } return NETDEV_TX_OK; } @@ -3842,12 +3852,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, /* Detect a transmit hang in hardware, this serializes the * check with the clearing of time_stamp and movement of i */ adapter->detect_tx_hung = false; - /* - * read barrier to make sure that the ->dma member and time - * stamp are updated fully - */ - smp_rmb(); - if (tx_ring->buffer_info[eop].dma && + if (tx_ring->buffer_info[eop].time_stamp && time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + (adapter->tx_timeout_factor * HZ)) && !(er32(STATUS) & E1000_STATUS_TXOFF)) { -- GitLab From ccfb342c5cd584f0f3e682280f7152310edf0e39 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 25 Mar 2009 21:59:04 +0000 Subject: [PATCH 4584/4982] e1000: cleanup clean_tx_irq routine so that it completely cleans ring The tx cleanup routine was stopping after 64 packets and this was causing issues resulting in the ring not being completely cleaned. This change updates the driver to clean the entire ring and if it doesn't it then will retry on the next pass. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index e60faabe902..5c61b921ca7 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3769,7 +3769,7 @@ static int e1000_clean(struct napi_struct *napi, int budget) adapter->clean_rx(adapter, &adapter->rx_ring[0], &work_done, budget); - if (tx_cleaned) + if (!tx_cleaned) work_done = budget; /* If budget not fully consumed, exit the polling mode */ @@ -3796,15 +3796,16 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, struct e1000_buffer *buffer_info; unsigned int i, eop; unsigned int count = 0; - bool cleaned = false; + bool cleaned; unsigned int total_tx_bytes=0, total_tx_packets=0; i = tx_ring->next_to_clean; eop = tx_ring->buffer_info[i].next_to_watch; eop_desc = E1000_TX_DESC(*tx_ring, eop); - while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) { - for (cleaned = false; !cleaned; ) { + while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) && + (count < tx_ring->count)) { + for (cleaned = false; !cleaned; count++) { tx_desc = E1000_TX_DESC(*tx_ring, i); buffer_info = &tx_ring->buffer_info[i]; cleaned = (i == eop); @@ -3827,10 +3828,6 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, eop = tx_ring->buffer_info[i].next_to_watch; eop_desc = E1000_TX_DESC(*tx_ring, eop); -#define E1000_TX_WEIGHT 64 - /* weight of a sort for tx, to avoid endless transmit cleanup */ - if (count++ == E1000_TX_WEIGHT) - break; } tx_ring->next_to_clean = i; @@ -3852,8 +3849,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, /* Detect a transmit hang in hardware, this serializes the * check with the clearing of time_stamp and movement of i */ adapter->detect_tx_hung = false; - if (tx_ring->buffer_info[eop].time_stamp && - time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + + if (tx_ring->buffer_info[i].time_stamp && + time_after(jiffies, tx_ring->buffer_info[i].time_stamp + (adapter->tx_timeout_factor * HZ)) && !(er32(STATUS) & E1000_STATUS_TXOFF)) { @@ -3875,7 +3872,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, readl(hw->hw_addr + tx_ring->tdt), tx_ring->next_to_use, tx_ring->next_to_clean, - tx_ring->buffer_info[eop].time_stamp, + tx_ring->buffer_info[i].time_stamp, eop, jiffies, eop_desc->upper.fields.status); @@ -3886,7 +3883,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, adapter->total_tx_packets += total_tx_packets; adapter->net_stats.tx_bytes += total_tx_bytes; adapter->net_stats.tx_packets += total_tx_packets; - return cleaned; + return (count < tx_ring->count); } /** -- GitLab From a6c42322722976ca81e6d02e4a702f33d659d8fc Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Wed, 25 Mar 2009 21:59:22 +0000 Subject: [PATCH 4585/4982] e1000: fix close race with interrupt this is in regards to http://bugzilla.kernel.org/show_bug.cgi?id=12876 where it appears that e1000 can leave its interrupt enabled after exiting the driver. Fix the bug by making the interrupt enable paths more aware of the driver exiting. Thanks to Alan Cox for the poke and initial investigation. CC: Alan Cox Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 5c61b921ca7..93b861d032b 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -577,12 +577,30 @@ out: void e1000_down(struct e1000_adapter *adapter) { + struct e1000_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; + u32 rctl, tctl; /* signal that we're down so the interrupt handler does not * reschedule our watchdog timer */ set_bit(__E1000_DOWN, &adapter->flags); + /* disable receives in the hardware */ + rctl = er32(RCTL); + ew32(RCTL, rctl & ~E1000_RCTL_EN); + /* flush and sleep below */ + + /* can be netif_tx_disable when NETIF_F_LLTX is removed */ + netif_stop_queue(netdev); + + /* disable transmits in the hardware */ + tctl = er32(TCTL); + tctl &= ~E1000_TCTL_EN; + ew32(TCTL, tctl); + /* flush both disables and wait for them to finish */ + E1000_WRITE_FLUSH(); + msleep(10); + napi_disable(&adapter->napi); e1000_irq_disable(adapter); @@ -595,7 +613,6 @@ void e1000_down(struct e1000_adapter *adapter) adapter->link_speed = 0; adapter->link_duplex = 0; netif_carrier_off(netdev); - netif_stop_queue(netdev); e1000_reset(adapter); e1000_clean_all_tx_rings(adapter); @@ -3744,10 +3761,12 @@ static irqreturn_t e1000_intr(int irq, void *data) adapter->total_rx_bytes = 0; adapter->total_rx_packets = 0; __napi_schedule(&adapter->napi); - } else + } else { /* this really should not happen! if it does it is basically a * bug, but not a hard error, so enable ints and continue */ - e1000_irq_enable(adapter); + if (!test_bit(__E1000_DOWN, &adapter->flags)) + e1000_irq_enable(adapter); + } return IRQ_HANDLED; } @@ -3777,7 +3796,8 @@ static int e1000_clean(struct napi_struct *napi, int budget) if (likely(adapter->itr_setting & 3)) e1000_set_itr(adapter); napi_complete(napi); - e1000_irq_enable(adapter); + if (!test_bit(__E1000_DOWN, &adapter->flags)) + e1000_irq_enable(adapter); } return work_done; -- GitLab From 704b3ea3b9b4ea0e115208946abd5c8a64080113 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Thu, 26 Mar 2009 01:03:23 -0700 Subject: [PATCH 4586/4982] netfilter: fix warning about invalid const usage This patch fixes the declaration of the logger structure in ebt_log and ebt_ulog: I forgot to remove the const option from their declaration in the commit ca735b3aaa945626ba65a3e51145bfe4ecd9e222 ("netfilter: use a linked list of loggers"). Pointed-out-by: Stephen Rothwell Signed-off-by: Eric Leblond Signed-off-by: David S. Miller --- net/bridge/netfilter/ebt_log.c | 2 +- net/bridge/netfilter/ebt_ulog.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index d44cbf8c374..a94f3cc377c 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c @@ -214,7 +214,7 @@ static struct xt_target ebt_log_tg_reg __read_mostly = { .me = THIS_MODULE, }; -static const struct nf_logger ebt_log_logger = { +static struct nf_logger ebt_log_logger __read_mostly = { .name = "ebt_log", .logfn = &ebt_log_packet, .me = THIS_MODULE, diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index 2c6d6823e70..80c78c5611b 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c @@ -279,7 +279,7 @@ static struct xt_target ebt_ulog_tg_reg __read_mostly = { .me = THIS_MODULE, }; -static const struct nf_logger ebt_ulog_logger = { +static struct nf_logger ebt_ulog_logger __read_mostly = { .name = "ulog", .logfn = &ebt_log_packet, .me = THIS_MODULE, -- GitLab From 3b334d427cb9c866216820bfad0d8318869cc154 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Thu, 26 Mar 2009 01:04:02 -0700 Subject: [PATCH 4587/4982] netfilter: fix warning in ebt_ulog init function. The ebt_ulog module does not follow the fixed convention about function return. Loading the module is triggering the following message: sys_init_module: 'ebt_ulog'->init suspiciously returned 1, it should follow 0/-E convention sys_init_module: loading module anyway... Pid: 2334, comm: modprobe Not tainted 2.6.29-rc5edenwall0-00883-g199e57b #146 Call Trace: [] ? printk+0xf/0x16 [] sys_init_module+0x107/0x186 [] syscall_call+0x7/0xb The following patch fixes the return treatment in ebt_ulog_init() function. Signed-off-by: Eric Leblond Signed-off-by: David S. Miller --- net/bridge/netfilter/ebt_ulog.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index 80c78c5611b..ac6fa43c8ec 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c @@ -287,13 +287,13 @@ static struct nf_logger ebt_ulog_logger __read_mostly = { static int __init ebt_ulog_init(void) { - bool ret = true; + int ret; int i; if (nlbufsiz >= 128*1024) { printk(KERN_NOTICE "ebt_ulog: Netlink buffer has to be <= 128kB," " please try a smaller nlbufsiz parameter.\n"); - return false; + return -EINVAL; } /* initialize ulog_buffers */ @@ -308,12 +308,12 @@ static int __init ebt_ulog_init(void) if (!ebtulognl) { printk(KERN_WARNING KBUILD_MODNAME ": out of memory trying to " "call netlink_kernel_create\n"); - ret = false; - } else if (xt_register_target(&ebt_ulog_tg_reg) != 0) { + ret = -ENOMEM; + } else if ((ret = xt_register_target(&ebt_ulog_tg_reg)) != 0) { netlink_kernel_release(ebtulognl); } - if (ret) + if (ret == 0) nf_log_register(NFPROTO_BRIDGE, &ebt_ulog_logger); return ret; -- GitLab From 7249dee5bdbe96302b5ff0d9a7701cf3dc8cffe8 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Thu, 26 Mar 2009 01:04:28 -0700 Subject: [PATCH 4588/4982] netfilter: fix nf_logger name in ebt_ulog. This patch renames the ebt_ulog nf_logger from "ulog" to "ebt_ulog" to be in sync with other modules naming. As this name was currently only used for informational purpose, the renaming should be harmless. Signed-off-by: Eric Leblond Signed-off-by: David S. Miller --- net/bridge/netfilter/ebt_ulog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index ac6fa43c8ec..133eeae45a4 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c @@ -280,7 +280,7 @@ static struct xt_target ebt_ulog_tg_reg __read_mostly = { }; static struct nf_logger ebt_ulog_logger __read_mostly = { - .name = "ulog", + .name = "ebt_ulog", .logfn = &ebt_log_packet, .me = THIS_MODULE, }; -- GitLab From 59d3a193f1ec1639db447aa1ceb39cd1811fb36e Mon Sep 17 00:00:00 2001 From: Paulius Zaleckas Date: Thu, 26 Mar 2009 10:06:08 +0200 Subject: [PATCH 4589/4982] ARM: Add Gemini architecture v3 Adds support for Cortina Systems Gemini family CPUs: http://www.cortina-systems.com/products/category/18 v3: - fixed __io(a) to be defined as __typesafe_io(a) v2: - #include -> - remove asm/system.h include - revorked mm.c to use named initializers - removed "empty" dma.h - updated copyrights Signed-off-by: Paulius Zaleckas --- arch/arm/Kconfig | 8 + arch/arm/Makefile | 1 + arch/arm/mach-gemini/Kconfig | 12 + arch/arm/mach-gemini/Makefile | 7 + arch/arm/mach-gemini/Makefile.boot | 9 + arch/arm/mach-gemini/common.h | 27 ++ arch/arm/mach-gemini/devices.c | 92 ++++++ .../mach-gemini/include/mach/debug-macro.S | 23 ++ .../mach-gemini/include/mach/entry-macro.S | 39 +++ .../arm/mach-gemini/include/mach/global_reg.h | 278 ++++++++++++++++++ arch/arm/mach-gemini/include/mach/hardware.h | 75 +++++ arch/arm/mach-gemini/include/mach/io.h | 18 ++ arch/arm/mach-gemini/include/mach/irqs.h | 50 ++++ arch/arm/mach-gemini/include/mach/memory.h | 19 ++ arch/arm/mach-gemini/include/mach/system.h | 37 +++ arch/arm/mach-gemini/include/mach/timex.h | 13 + .../arm/mach-gemini/include/mach/uncompress.h | 42 +++ arch/arm/mach-gemini/include/mach/vmalloc.h | 10 + arch/arm/mach-gemini/irq.c | 102 +++++++ arch/arm/mach-gemini/mm.c | 82 ++++++ arch/arm/mach-gemini/time.c | 89 ++++++ 21 files changed, 1033 insertions(+) create mode 100644 arch/arm/mach-gemini/Kconfig create mode 100644 arch/arm/mach-gemini/Makefile create mode 100644 arch/arm/mach-gemini/Makefile.boot create mode 100644 arch/arm/mach-gemini/common.h create mode 100644 arch/arm/mach-gemini/devices.c create mode 100644 arch/arm/mach-gemini/include/mach/debug-macro.S create mode 100644 arch/arm/mach-gemini/include/mach/entry-macro.S create mode 100644 arch/arm/mach-gemini/include/mach/global_reg.h create mode 100644 arch/arm/mach-gemini/include/mach/hardware.h create mode 100644 arch/arm/mach-gemini/include/mach/io.h create mode 100644 arch/arm/mach-gemini/include/mach/irqs.h create mode 100644 arch/arm/mach-gemini/include/mach/memory.h create mode 100644 arch/arm/mach-gemini/include/mach/system.h create mode 100644 arch/arm/mach-gemini/include/mach/timex.h create mode 100644 arch/arm/mach-gemini/include/mach/uncompress.h create mode 100644 arch/arm/mach-gemini/include/mach/vmalloc.h create mode 100644 arch/arm/mach-gemini/irq.c create mode 100644 arch/arm/mach-gemini/mm.c create mode 100644 arch/arm/mach-gemini/time.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index dbfdf87f993..5686f4074dd 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -275,6 +275,12 @@ config ARCH_EP93XX help This enables support for the Cirrus EP93xx series of CPUs. +config ARCH_GEMINI + bool "Cortina Systems Gemini" + select CPU_FA526 + help + Support for the Cortina Systems Gemini family SoCs + config ARCH_FOOTBRIDGE bool "FootBridge" select CPU_SA110 @@ -598,6 +604,8 @@ source "arch/arm/mach-ep93xx/Kconfig" source "arch/arm/mach-footbridge/Kconfig" +source "arch/arm/mach-gemini/Kconfig" + source "arch/arm/mach-integrator/Kconfig" source "arch/arm/mach-iop32x/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index d29f9260fb1..56e13bf2202 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -108,6 +108,7 @@ endif machine-$(CONFIG_ARCH_PXA) := pxa machine-$(CONFIG_ARCH_L7200) := l7200 machine-$(CONFIG_ARCH_INTEGRATOR) := integrator + machine-$(CONFIG_ARCH_GEMINI) := gemini textofs-$(CONFIG_ARCH_CLPS711X) := 0x00028000 machine-$(CONFIG_ARCH_CLPS711X) := clps711x machine-$(CONFIG_ARCH_IOP32X) := iop32x diff --git a/arch/arm/mach-gemini/Kconfig b/arch/arm/mach-gemini/Kconfig new file mode 100644 index 00000000000..3aff39abb18 --- /dev/null +++ b/arch/arm/mach-gemini/Kconfig @@ -0,0 +1,12 @@ +if ARCH_GEMINI + +menu "Cortina Systems Gemini Implementations" + +endmenu + +config GEMINI_MEM_SWAP + bool "Gemini memory is swapped" + help + Say Y here if Gemini memory is swapped by bootloader. + +endif diff --git a/arch/arm/mach-gemini/Makefile b/arch/arm/mach-gemini/Makefile new file mode 100644 index 00000000000..133e2050685 --- /dev/null +++ b/arch/arm/mach-gemini/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the linux kernel. +# + +# Object file lists. + +obj-y := irq.o mm.o time.o devices.o diff --git a/arch/arm/mach-gemini/Makefile.boot b/arch/arm/mach-gemini/Makefile.boot new file mode 100644 index 00000000000..22a52c228d9 --- /dev/null +++ b/arch/arm/mach-gemini/Makefile.boot @@ -0,0 +1,9 @@ +ifeq ($(CONFIG_GEMINI_MEM_SWAP),y) + zreladdr-y := 0x00008000 +params_phys-y := 0x00000100 +initrd_phys-y := 0x00800000 +else + zreladdr-y := 0x10008000 +params_phys-y := 0x10000100 +initrd_phys-y := 0x10800000 +endif diff --git a/arch/arm/mach-gemini/common.h b/arch/arm/mach-gemini/common.h new file mode 100644 index 00000000000..9c1afa1c580 --- /dev/null +++ b/arch/arm/mach-gemini/common.h @@ -0,0 +1,27 @@ +/* + * Common Gemini architecture functions + * + * Copyright (C) 2008-2009 Paulius Zaleckas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __GEMINI_COMMON_H__ +#define __GEMINI_COMMON_H__ + +struct mtd_partition; + +extern void gemini_map_io(void); +extern void gemini_init_irq(void); +extern void gemini_timer_init(void); + +/* Common platform devices registration functions */ +extern int platform_register_uart(void); +extern int platform_register_pflash(unsigned int size, + struct mtd_partition *parts, + unsigned int nr_parts); + +#endif /* __GEMINI_COMMON_H__ */ diff --git a/arch/arm/mach-gemini/devices.c b/arch/arm/mach-gemini/devices.c new file mode 100644 index 00000000000..6b525253d02 --- /dev/null +++ b/arch/arm/mach-gemini/devices.c @@ -0,0 +1,92 @@ +/* + * Common devices definition for Gemini + * + * Copyright (C) 2008-2009 Paulius Zaleckas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static struct plat_serial8250_port serial_platform_data[] = { + { + .membase = (void *)IO_ADDRESS(GEMINI_UART_BASE), + .mapbase = GEMINI_UART_BASE, + .irq = IRQ_UART, + .uartclk = UART_CLK, + .regshift = 2, + .iotype = UPIO_MEM, + .type = PORT_16550A, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_FIXED_TYPE, + }, + {}, +}; + +static struct platform_device serial_device = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM, + .dev = { + .platform_data = serial_platform_data, + }, +}; + +int platform_register_uart(void) +{ + return platform_device_register(&serial_device); +} + +static struct resource flash_resource = { + .start = GEMINI_FLASH_BASE, + .flags = IORESOURCE_MEM, +}; + +static struct physmap_flash_data pflash_platform_data = {}; + +static struct platform_device pflash_device = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &pflash_platform_data, + }, + .resource = &flash_resource, + .num_resources = 1, +}; + +int platform_register_pflash(unsigned int size, struct mtd_partition *parts, + unsigned int nr_parts) +{ + unsigned int reg; + + reg = __raw_readl(IO_ADDRESS(GEMINI_GLOBAL_BASE) + GLOBAL_STATUS); + + if ((reg & FLASH_TYPE_MASK) != FLASH_TYPE_PARALLEL) + return -ENXIO; + + if (reg & FLASH_WIDTH_16BIT) + pflash_platform_data.width = 2; + else + pflash_platform_data.width = 1; + + /* enable parallel flash pins and disable others */ + reg = __raw_readl(IO_ADDRESS(GEMINI_GLOBAL_BASE) + GLOBAL_MISC_CTRL); + reg &= ~PFLASH_PADS_DISABLE; + reg |= SFLASH_PADS_DISABLE | NAND_PADS_DISABLE; + __raw_writel(reg, IO_ADDRESS(GEMINI_GLOBAL_BASE) + GLOBAL_MISC_CTRL); + + flash_resource.end = flash_resource.start + size - 1; + + pflash_platform_data.parts = parts; + pflash_platform_data.nr_parts = nr_parts; + + return platform_device_register(&pflash_device); +} diff --git a/arch/arm/mach-gemini/include/mach/debug-macro.S b/arch/arm/mach-gemini/include/mach/debug-macro.S new file mode 100644 index 00000000000..d04a6eaeae1 --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/debug-macro.S @@ -0,0 +1,23 @@ +/* + * Debugging macro include header + * + * Copyright (C) 1994-1999 Russell King + * Copyright (C) 2001-2006 Storlink, Corp. + * Copyright (C) 2008-2009 Paulius Zaleckas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include + + .macro addruart,rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + ldreq \rx, =GEMINI_UART_BASE @ physical + ldrne \rx, =IO_ADDRESS(GEMINI_UART_BASE) @ virtual + .endm + +#define UART_SHIFT 2 +#define FLOW_CONTROL +#include diff --git a/arch/arm/mach-gemini/include/mach/entry-macro.S b/arch/arm/mach-gemini/include/mach/entry-macro.S new file mode 100644 index 00000000000..1624f91a2b8 --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/entry-macro.S @@ -0,0 +1,39 @@ +/* + * Low-level IRQ helper macros for Gemini platform. + * + * Copyright (C) 2001-2006 Storlink, Corp. + * Copyright (C) 2008-2009 Paulius Zaleckas + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ +#include + +#define IRQ_STATUS 0x14 + + .macro disable_fiq + .endm + + .macro get_irqnr_preamble, base, tmp + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \irqstat, =IO_ADDRESS(GEMINI_INTERRUPT_BASE + IRQ_STATUS) + ldr \irqnr, [\irqstat] + cmp \irqnr, #0 + beq 2313f + mov \tmp, \irqnr + mov \irqnr, #0 +2312: + tst \tmp, #1 + bne 2313f + add \irqnr, \irqnr, #1 + mov \tmp, \tmp, lsr #1 + cmp \irqnr, #31 + bcc 2312b +2313: + .endm diff --git a/arch/arm/mach-gemini/include/mach/global_reg.h b/arch/arm/mach-gemini/include/mach/global_reg.h new file mode 100644 index 00000000000..de7ff7e849f --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/global_reg.h @@ -0,0 +1,278 @@ +/* + * This file contains the hardware definitions for Gemini. + * + * Copyright (C) 2009 Paulius Zaleckas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#ifndef __MACH_GLOBAL_REG_H +#define __MACH_GLOBAL_REG_H + +/* Global Word ID Register*/ +#define GLOBAL_ID 0x00 + +#define CHIP_ID(reg) ((reg) >> 8) +#define CHIP_REVISION(reg) ((reg) & 0xFF) + +/* Global Status Register */ +#define GLOBAL_STATUS 0x04 + +#define CPU_BIG_ENDIAN (1 << 31) +#define PLL_OSC_30M (1 << 30) /* else 60MHz */ + +#define OPERATION_MODE_MASK (0xF << 26) +#define OPM_IDDQ (0xF << 26) +#define OPM_NAND (0xE << 26) +#define OPM_RING (0xD << 26) +#define OPM_DIRECT_BOOT (0xC << 26) +#define OPM_USB1_PHY_TEST (0xB << 26) +#define OPM_USB0_PHY_TEST (0xA << 26) +#define OPM_SATA1_PHY_TEST (0x9 << 26) +#define OPM_SATA0_PHY_TEST (0x8 << 26) +#define OPM_ICE_ARM (0x7 << 26) +#define OPM_ICE_FARADAY (0x6 << 26) +#define OPM_PLL_BYPASS (0x5 << 26) +#define OPM_DEBUG (0x4 << 26) +#define OPM_BURN_IN (0x3 << 26) +#define OPM_MBIST (0x2 << 26) +#define OPM_SCAN (0x1 << 26) +#define OPM_REAL (0x0 << 26) + +#define FLASH_TYPE_MASK (0x3 << 24) +#define FLASH_TYPE_NAND_2K (0x3 << 24) +#define FLASH_TYPE_NAND_512 (0x2 << 24) +#define FLASH_TYPE_PARALLEL (0x1 << 24) +#define FLASH_TYPE_SERIAL (0x0 << 24) +/* if parallel */ +#define FLASH_WIDTH_16BIT (1 << 23) /* else 8 bit */ +/* if serial */ +#define FLASH_ATMEL (1 << 23) /* else STM */ + +#define FLASH_SIZE_MASK (0x3 << 21) +#define NAND_256M (0x3 << 21) /* and more */ +#define NAND_128M (0x2 << 21) +#define NAND_64M (0x1 << 21) +#define NAND_32M (0x0 << 21) +#define ATMEL_16M (0x3 << 21) /* and more */ +#define ATMEL_8M (0x2 << 21) +#define ATMEL_4M_2M (0x1 << 21) +#define ATMEL_1M (0x0 << 21) /* and less */ +#define STM_32M (1 << 22) /* and more */ +#define STM_16M (0 << 22) /* and less */ + +#define FLASH_PARALLEL_HIGH_PIN_CNT (1 << 20) /* else low pin cnt */ + +#define CPU_AHB_RATIO_MASK (0x3 << 18) +#define CPU_AHB_1_1 (0x0 << 18) +#define CPU_AHB_3_2 (0x1 << 18) +#define CPU_AHB_24_13 (0x2 << 18) +#define CPU_AHB_2_1 (0x3 << 18) + +#define REG_TO_AHB_SPEED(reg) ((((reg) >> 15) & 0x7) * 10 + 130) +#define AHB_SPEED_TO_REG(x) ((((x - 130)) / 10) << 15) + +/* it is posible to override some settings, use >> OVERRIDE_xxxx_SHIFT */ +#define OVERRIDE_FLASH_TYPE_SHIFT 16 +#define OVERRIDE_FLASH_WIDTH_SHIFT 16 +#define OVERRIDE_FLASH_SIZE_SHIFT 16 +#define OVERRIDE_CPU_AHB_RATIO_SHIFT 15 +#define OVERRIDE_AHB_SPEED_SHIFT 15 + +/* Global PLL Control Register */ +#define GLOBAL_PLL_CTRL 0x08 + +#define PLL_BYPASS (1 << 31) +#define PLL_POWER_DOWN (1 << 8) +#define PLL_CONTROL_Q (0x1F << 0) + +/* Global Soft Reset Control Register */ +#define GLOBAL_RESET 0x0C + +#define RESET_GLOBAL (1 << 31) +#define RESET_CPU1 (1 << 30) +#define RESET_TVE (1 << 28) +#define RESET_SATA1 (1 << 27) +#define RESET_SATA0 (1 << 26) +#define RESET_CIR (1 << 25) +#define RESET_EXT_DEV (1 << 24) +#define RESET_WD (1 << 23) +#define RESET_GPIO2 (1 << 22) +#define RESET_GPIO1 (1 << 21) +#define RESET_GPIO0 (1 << 20) +#define RESET_SSP (1 << 19) +#define RESET_UART (1 << 18) +#define RESET_TIMER (1 << 17) +#define RESET_RTC (1 << 16) +#define RESET_INT1 (1 << 15) +#define RESET_INT0 (1 << 14) +#define RESET_LCD (1 << 13) +#define RESET_LPC (1 << 12) +#define RESET_APB (1 << 11) +#define RESET_DMA (1 << 10) +#define RESET_USB1 (1 << 9) +#define RESET_USB0 (1 << 8) +#define RESET_PCI (1 << 7) +#define RESET_GMAC1 (1 << 6) +#define RESET_GMAC0 (1 << 5) +#define RESET_SECURITY (1 << 4) +#define RESET_RAID (1 << 3) +#define RESET_IDE (1 << 2) +#define RESET_FLASH (1 << 1) +#define RESET_DRAM (1 << 0) + +/* Global IO Pad Driving Capability Control Register */ +#define GLOBAL_IO_DRIVING_CTRL 0x10 + +#define DRIVING_CURRENT_MASK 0x3 + +/* here 00-4mA, 01-8mA, 10-12mA, 11-16mA */ +#define GPIO1_PADS_31_28_SHIFT 28 +#define GPIO0_PADS_31_16_SHIFT 26 +#define GPIO0_PADS_15_0_SHIFT 24 +#define PCI_AND_EXT_RESET_PADS_SHIFT 22 +#define IDE_PADS_SHIFT 20 +#define GMAC1_PADS_SHIFT 18 +#define GMAC0_PADS_SHIFT 16 +/* DRAM is not in mA and poorly documented */ +#define DRAM_CLOCK_PADS_SHIFT 8 +#define DRAM_DATA_PADS_SHIFT 4 +#define DRAM_CONTROL_PADS_SHIFT 0 + +/* Global IO Pad Slew Rate Control Register */ +#define GLOBAL_IO_SLEW_RATE_CTRL 0x14 + +#define GPIO1_PADS_31_28_SLOW (1 << 10) +#define GPIO0_PADS_31_16_SLOW (1 << 9) +#define GPIO0_PADS_15_0_SLOW (1 << 8) +#define PCI_PADS_SLOW (1 << 7) +#define IDE_PADS_SLOW (1 << 6) +#define GMAC1_PADS_SLOW (1 << 5) +#define GMAC0_PADS_SLOW (1 << 4) +#define DRAM_CLOCK_PADS_SLOW (1 << 1) +#define DRAM_IO_PADS_SLOW (1 << 0) + +/* + * General skew control defines + * 16 steps, each step is around 0.2ns + */ +#define SKEW_MASK 0xF + +/* Global IDE PAD Skew Control Register */ +#define GLOBAL_IDE_SKEW_CTRL 0x18 + +#define IDE1_HOST_STROBE_DELAY_SHIFT 28 +#define IDE1_DEVICE_STROBE_DELAY_SHIFT 24 +#define IDE1_OUTPUT_IO_SKEW_SHIFT 20 +#define IDE1_INPUT_IO_SKEW_SHIFT 16 +#define IDE0_HOST_STROBE_DELAY_SHIFT 12 +#define IDE0_DEVICE_STROBE_DELAY_SHIFT 8 +#define IDE0_OUTPUT_IO_SKEW_SHIFT 4 +#define IDE0_INPUT_IO_SKEW_SHIFT 0 + +/* Global GMAC Control Pad Skew Control Register */ +#define GLOBAL_GMAC_CTRL_SKEW_CTRL 0x1C + +#define GMAC1_TXC_SKEW_SHIFT 28 +#define GMAC1_TXEN_SKEW_SHIFT 24 +#define GMAC1_RXC_SKEW_SHIFT 20 +#define GMAC1_RXDV_SKEW_SHIFT 16 +#define GMAC0_TXC_SKEW_SHIFT 12 +#define GMAC0_TXEN_SKEW_SHIFT 8 +#define GMAC0_RXC_SKEW_SHIFT 4 +#define GMAC0_RXDV_SKEW_SHIFT 0 + +/* Global GMAC0 Data PAD Skew Control Register */ +#define GLOBAL_GMAC0_DATA_SKEW_CTRL 0x20 +/* Global GMAC1 Data PAD Skew Control Register */ +#define GLOBAL_GMAC1_DATA_SKEW_CTRL 0x24 + +#define GMAC_TXD_SKEW_SHIFT(x) (((x) * 4) + 16) +#define GMAC_RXD_SKEW_SHIFT(x) ((x) * 4) + +/* CPU has two AHB busses. */ + +/* Global Arbitration0 Control Register */ +#define GLOBAL_ARBITRATION0_CTRL 0x28 + +#define BOOT_CONTROLLER_HIGH_PRIO (1 << 3) +#define DMA_BUS1_HIGH_PRIO (1 << 2) +#define CPU0_HIGH_PRIO (1 << 0) + +/* Global Arbitration1 Control Register */ +#define GLOBAL_ARBITRATION1_CTRL 0x2C + +#define TVE_HIGH_PRIO (1 << 9) +#define PCI_HIGH_PRIO (1 << 8) +#define USB1_HIGH_PRIO (1 << 7) +#define USB0_HIGH_PRIO (1 << 6) +#define GMAC1_HIGH_PRIO (1 << 5) +#define GMAC0_HIGH_PRIO (1 << 4) +#define SECURITY_HIGH_PRIO (1 << 3) +#define RAID_HIGH_PRIO (1 << 2) +#define IDE_HIGH_PRIO (1 << 1) +#define DMA_BUS2_HIGH_PRIO (1 << 0) + +/* Common bits for both arbitration registers */ +#define BURST_LENGTH_SHIFT 16 +#define BURST_LENGTH_MASK (0x3F << 16) + +/* Miscellaneous Control Register */ +#define GLOBAL_MISC_CTRL 0x30 + +#define MEMORY_SPACE_SWAP (1 << 31) +#define USB1_PLUG_MINIB (1 << 30) /* else plug is mini-A */ +#define USB0_PLUG_MINIB (1 << 29) +#define GMAC_GMII (1 << 28) +#define GMAC_1_ENABLE (1 << 27) +/* TODO: define ATA/SATA bits */ +#define USB1_VBUS_ON (1 << 23) +#define USB0_VBUS_ON (1 << 22) +#define APB_CLKOUT_ENABLE (1 << 21) +#define TVC_CLKOUT_ENABLE (1 << 20) +#define EXT_CLKIN_ENABLE (1 << 19) +#define PCI_66MHZ (1 << 18) /* else 33 MHz */ +#define PCI_CLKOUT_ENABLE (1 << 17) +#define LPC_CLKOUT_ENABLE (1 << 16) +#define USB1_WAKEUP_ON (1 << 15) +#define USB0_WAKEUP_ON (1 << 14) +/* TODO: define PCI idle detect bits */ +#define TVC_PADS_ENABLE (1 << 9) +#define SSP_PADS_ENABLE (1 << 8) +#define LCD_PADS_ENABLE (1 << 7) +#define LPC_PADS_ENABLE (1 << 6) +#define PCI_PADS_ENABLE (1 << 5) +#define IDE_PADS_ENABLE (1 << 4) +#define DRAM_PADS_POWER_DOWN (1 << 3) +#define NAND_PADS_DISABLE (1 << 2) +#define PFLASH_PADS_DISABLE (1 << 1) +#define SFLASH_PADS_DISABLE (1 << 0) + +/* Global Clock Control Register */ +#define GLOBAL_CLOCK_CTRL 0x34 + +#define POWER_STATE_G0 (1 << 31) +#define POWER_STATE_S1 (1 << 30) /* else it is S3/S4 state */ +#define SECURITY_APB_AHB (1 << 29) +/* else Security APB clk will be 0.75xAHB */ +/* TODO: TVC clock divider */ +#define PCI_CLKRUN_ENABLE (1 << 16) +#define BOOT_CLK_DISABLE (1 << 13) +#define TVC_CLK_DISABLE (1 << 12) +#define FLASH_CLK_DISABLE (1 << 11) +#define DDR_CLK_DISABLE (1 << 10) +#define PCI_CLK_DISABLE (1 << 9) +#define IDE_CLK_DISABLE (1 << 8) +#define USB1_CLK_DISABLE (1 << 7) +#define USB0_CLK_DISABLE (1 << 6) +#define SATA1_CLK_DISABLE (1 << 5) +#define SATA0_CLK_DISABLE (1 << 4) +#define GMAC1_CLK_DISABLE (1 << 3) +#define GMAC0_CLK_DISABLE (1 << 2) +#define SECURITY_CLK_DISABLE (1 << 1) + +/* TODO: other registers definitions if needed */ + +#endif /* __MACH_GLOBAL_REG_H */ diff --git a/arch/arm/mach-gemini/include/mach/hardware.h b/arch/arm/mach-gemini/include/mach/hardware.h new file mode 100644 index 00000000000..de6752674c0 --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/hardware.h @@ -0,0 +1,75 @@ +/* + * This file contains the hardware definitions for Gemini. + * + * Copyright (C) 2001-2006 Storlink, Corp. + * Copyright (C) 2008-2009 Paulius Zaleckas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#ifndef __MACH_HARDWARE_H +#define __MACH_HARDWARE_H + +/* + * Memory Map definitions + */ +/* FIXME: Does it really swap SRAM like this? */ +#ifdef CONFIG_GEMINI_MEM_SWAP +# define GEMINI_DRAM_BASE 0x00000000 +# define GEMINI_SRAM_BASE 0x20000000 +#else +# define GEMINI_SRAM_BASE 0x00000000 +# define GEMINI_DRAM_BASE 0x10000000 +#endif +#define GEMINI_FLASH_BASE 0x30000000 +#define GEMINI_GLOBAL_BASE 0x40000000 +#define GEMINI_WAQTCHDOG_BASE 0x41000000 +#define GEMINI_UART_BASE 0x42000000 +#define GEMINI_TIMER_BASE 0x43000000 +#define GEMINI_LCD_BASE 0x44000000 +#define GEMINI_RTC_BASE 0x45000000 +#define GEMINI_SATA_BASE 0x46000000 +#define GEMINI_LPC_HOST_BASE 0x47000000 +#define GEMINI_LPC_IO_BASE 0x47800000 +#define GEMINI_INTERRUPT_BASE 0x48000000 +/* TODO: Different interrupt controlers when SMP + * #define GEMINI_INTERRUPT0_BASE 0x48000000 + * #define GEMINI_INTERRUPT1_BASE 0x49000000 + */ +#define GEMINI_SSP_CTRL_BASE 0x4A000000 +#define GEMINI_POWER_CTRL_BASE 0x4B000000 +#define GEMINI_CIR_BASE 0x4C000000 +#define GEMINI_GPIO_BASE(x) (0x4D000000 + (x) * 0x1000000) +#define GEMINI_PCI_IO_BASE 0x50000000 +#define GEMINI_PCI_MEM_BASE 0x58000000 +#define GEMINI_TOE_BASE 0x60000000 +#define GEMINI_GMAC0_BASE 0x6000A000 +#define GEMINI_GMAC1_BASE 0x6000E000 +#define GEMINI_SECURITY_BASE 0x62000000 +#define GEMINI_IDE0_BASE 0x63000000 +#define GEMINI_IDE1_BASE 0x63400000 +#define GEMINI_RAID_BASE 0x64000000 +#define GEMINI_FLASH_CTRL_BASE 0x65000000 +#define GEMINI_DRAM_CTRL_BASE 0x66000000 +#define GEMINI_GENERAL_DMA_BASE 0x67000000 +#define GEMINI_USB0_BASE 0x68000000 +#define GEMINI_USB1_BASE 0x69000000 +#define GEMINI_BIG_ENDIAN_BASE 0x80000000 + +#define GEMINI_TIMER1_BASE GEMINI_TIMER_BASE +#define GEMINI_TIMER2_BASE (GEMINI_TIMER_BASE + 0x10) +#define GEMINI_TIMER3_BASE (GEMINI_TIMER_BASE + 0x20) + +/* + * UART Clock when System clk is 150MHz + */ +#define UART_CLK 48000000 + +/* + * macro to get at IO space when running virtually + */ +#define IO_ADDRESS(x) ((((x) & 0xFFF00000) >> 4) | ((x) & 0x000FFFFF) | 0xF0000000) + +#endif diff --git a/arch/arm/mach-gemini/include/mach/io.h b/arch/arm/mach-gemini/include/mach/io.h new file mode 100644 index 00000000000..c548056b98b --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/io.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2001-2006 Storlink, Corp. + * Copyright (C) 2008-2009 Paulius Zaleckas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#ifndef __MACH_IO_H +#define __MACH_IO_H + +#define IO_SPACE_LIMIT 0xffffffff + +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) + +#endif /* __MACH_IO_H */ diff --git a/arch/arm/mach-gemini/include/mach/irqs.h b/arch/arm/mach-gemini/include/mach/irqs.h new file mode 100644 index 00000000000..c7728ac458f --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/irqs.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2001-2006 Storlink, Corp. + * Copyright (C) 2008-2009 Paulius Zaleckas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __MACH_IRQS_H__ +#define __MACH_IRQS_H__ + +#define IRQ_SERIRQ1 31 +#define IRQ_SERIRQ0 30 +#define IRQ_PCID 29 +#define IRQ_PCIC 28 +#define IRQ_PCIB 27 +#define IRQ_PWR 26 +#define IRQ_CIR 25 +#define IRQ_GPIO(x) (22 + (x)) +#define IRQ_SSP 21 +#define IRQ_LPC 20 +#define IRQ_LCD 19 +#define IRQ_UART 18 +#define IRQ_RTC 17 +#define IRQ_TIMER3 16 +#define IRQ_TIMER2 15 +#define IRQ_TIMER1 14 +#define IRQ_FLASH 12 +#define IRQ_USB1 11 +#define IRQ_USB0 10 +#define IRQ_DMA 9 +#define IRQ_PCI 8 +#define IRQ_IPSEC 7 +#define IRQ_RAID 6 +#define IRQ_IDE1 5 +#define IRQ_IDE0 4 +#define IRQ_WATCHDOG 3 +#define IRQ_GMAC1 2 +#define IRQ_GMAC0 1 +#define IRQ_IPI 0 + +#define NORMAL_IRQ_NUM 32 + +#define ARCH_TIMER_IRQ IRQ_TIMER2 + +#define NR_IRQS NORMAL_IRQ_NUM + +#endif /* __MACH_IRQS_H__ */ diff --git a/arch/arm/mach-gemini/include/mach/memory.h b/arch/arm/mach-gemini/include/mach/memory.h new file mode 100644 index 00000000000..2d14d5bf1f9 --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/memory.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2001-2006 Storlink, Corp. + * Copyright (C) 2008-2009 Paulius Zaleckas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#ifndef __MACH_MEMORY_H +#define __MACH_MEMORY_H + +#ifdef CONFIG_GEMINI_MEM_SWAP +# define PHYS_OFFSET UL(0x00000000) +#else +# define PHYS_OFFSET UL(0x10000000) +#endif + +#endif /* __MACH_MEMORY_H */ diff --git a/arch/arm/mach-gemini/include/mach/system.h b/arch/arm/mach-gemini/include/mach/system.h new file mode 100644 index 00000000000..bbbd72767a0 --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/system.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2001-2006 Storlink, Corp. + * Copyright (C) 2008-2009 Paulius Zaleckas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#ifndef __MACH_SYSTEM_H +#define __MACH_SYSTEM_H + +#include +#include +#include + +static inline void arch_idle(void) +{ + /* + * Because of broken hardware we have to enable interrupts or the CPU + * will never wakeup... Acctualy it is not very good to enable + * interrupts here since scheduler can miss a tick, but there is + * no other way around this. Platforms that needs it for power saving + * should call enable_hlt() in init code, since by default it is + * disabled. + */ + local_irq_enable(); + cpu_do_idle(); +} + +static inline void arch_reset(char mode) +{ + __raw_writel(RESET_GLOBAL | RESET_CPU1, + IO_ADDRESS(GEMINI_GLOBAL_BASE) + GLOBAL_RESET); +} + +#endif /* __MACH_SYSTEM_H */ diff --git a/arch/arm/mach-gemini/include/mach/timex.h b/arch/arm/mach-gemini/include/mach/timex.h new file mode 100644 index 00000000000..dc5690ba975 --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/timex.h @@ -0,0 +1,13 @@ +/* + * Gemini timex specifications + * + * Copyright (C) 2008-2009 Paulius Zaleckas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +/* When AHB bus frequency is 150MHz */ +#define CLOCK_TICK_RATE 38000000 diff --git a/arch/arm/mach-gemini/include/mach/uncompress.h b/arch/arm/mach-gemini/include/mach/uncompress.h new file mode 100644 index 00000000000..59c5df7e716 --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/uncompress.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2008-2009 Paulius Zaleckas + * + * Based on mach-pxa/include/mach/uncompress.h: + * Copyright: (C) 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __MACH_UNCOMPRESS_H +#define __MACH_UNCOMPRESS_H + +#include +#include + +static volatile unsigned long *UART = (unsigned long *)GEMINI_UART_BASE; + +/* + * The following code assumes the serial port has already been + * initialized by the bootloader. If you didn't setup a port in + * your bootloader then nothing will appear (which might be desired). + */ +static inline void putc(char c) +{ + while (!(UART[UART_LSR] & UART_LSR_THRE)) + barrier(); + UART[UART_TX] = c; +} + +#define flush() do { } while (0) + +/* + * nothing to do + */ +#define arch_decomp_setup() + +#define arch_decomp_wdog() + +#endif /* __MACH_UNCOMPRESS_H */ diff --git a/arch/arm/mach-gemini/include/mach/vmalloc.h b/arch/arm/mach-gemini/include/mach/vmalloc.h new file mode 100644 index 00000000000..83e536d9436 --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/vmalloc.h @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2008-2009 Paulius Zaleckas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#define VMALLOC_END 0xF0000000 diff --git a/arch/arm/mach-gemini/irq.c b/arch/arm/mach-gemini/irq.c new file mode 100644 index 00000000000..9e613ca8120 --- /dev/null +++ b/arch/arm/mach-gemini/irq.c @@ -0,0 +1,102 @@ +/* + * Interrupt routines for Gemini + * + * Copyright (C) 2001-2006 Storlink, Corp. + * Copyright (C) 2008-2009 Paulius Zaleckas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IRQ_SOURCE(base_addr) (base_addr + 0x00) +#define IRQ_MASK(base_addr) (base_addr + 0x04) +#define IRQ_CLEAR(base_addr) (base_addr + 0x08) +#define IRQ_TMODE(base_addr) (base_addr + 0x0C) +#define IRQ_TLEVEL(base_addr) (base_addr + 0x10) +#define IRQ_STATUS(base_addr) (base_addr + 0x14) +#define FIQ_SOURCE(base_addr) (base_addr + 0x20) +#define FIQ_MASK(base_addr) (base_addr + 0x24) +#define FIQ_CLEAR(base_addr) (base_addr + 0x28) +#define FIQ_TMODE(base_addr) (base_addr + 0x2C) +#define FIQ_LEVEL(base_addr) (base_addr + 0x30) +#define FIQ_STATUS(base_addr) (base_addr + 0x34) + +static void gemini_ack_irq(unsigned int irq) +{ + __raw_writel(1 << irq, IRQ_CLEAR(IO_ADDRESS(GEMINI_INTERRUPT_BASE))); +} + +static void gemini_mask_irq(unsigned int irq) +{ + unsigned int mask; + + mask = __raw_readl(IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE))); + mask &= ~(1 << irq); + __raw_writel(mask, IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE))); +} + +static void gemini_unmask_irq(unsigned int irq) +{ + unsigned int mask; + + mask = __raw_readl(IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE))); + mask |= (1 << irq); + __raw_writel(mask, IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE))); +} + +static struct irq_chip gemini_irq_chip = { + .name = "INTC", + .ack = gemini_ack_irq, + .mask = gemini_mask_irq, + .unmask = gemini_unmask_irq, +}; + +static struct resource irq_resource = { + .name = "irq_handler", + .start = IO_ADDRESS(GEMINI_INTERRUPT_BASE), + .end = IO_ADDRESS(FIQ_STATUS(GEMINI_INTERRUPT_BASE)) + 4, +}; + +void __init gemini_init_irq(void) +{ + unsigned int i, mode = 0, level = 0; + + /* + * Disable arch_idle() by default since it is buggy + * For more info see arch/arm/mach-gemini/include/mach/system.h + */ + disable_hlt(); + + request_resource(&iomem_resource, &irq_resource); + + for (i = 0; i < NR_IRQS; i++) { + set_irq_chip(i, &gemini_irq_chip); + if((i >= IRQ_TIMER1 && i <= IRQ_TIMER3) || (i >= IRQ_SERIRQ0 && i <= IRQ_SERIRQ1)) { + set_irq_handler(i, handle_edge_irq); + mode |= 1 << i; + level |= 1 << i; + } else { + set_irq_handler(i, handle_level_irq); + } + set_irq_flags(i, IRQF_VALID | IRQF_PROBE); + } + + /* Disable all interrupts */ + __raw_writel(0, IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE))); + __raw_writel(0, FIQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE))); + + /* Set interrupt mode */ + __raw_writel(mode, IRQ_TMODE(IO_ADDRESS(GEMINI_INTERRUPT_BASE))); + __raw_writel(level, IRQ_TLEVEL(IO_ADDRESS(GEMINI_INTERRUPT_BASE))); +} diff --git a/arch/arm/mach-gemini/mm.c b/arch/arm/mach-gemini/mm.c new file mode 100644 index 00000000000..51948242ec0 --- /dev/null +++ b/arch/arm/mach-gemini/mm.c @@ -0,0 +1,82 @@ +/* + * Static mappings for Gemini + * + * Copyright (C) 2001-2006 Storlink, Corp. + * Copyright (C) 2008-2009 Paulius Zaleckas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#include +#include + +#include + +#include + +/* Page table mapping for I/O region */ +static struct map_desc gemini_io_desc[] __initdata = { + { + .virtual = IO_ADDRESS(GEMINI_GLOBAL_BASE), + .pfn =__phys_to_pfn(GEMINI_GLOBAL_BASE), + .length = SZ_512K, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(GEMINI_UART_BASE), + .pfn = __phys_to_pfn(GEMINI_UART_BASE), + .length = SZ_512K, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(GEMINI_TIMER_BASE), + .pfn = __phys_to_pfn(GEMINI_TIMER_BASE), + .length = SZ_512K, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(GEMINI_INTERRUPT_BASE), + .pfn = __phys_to_pfn(GEMINI_INTERRUPT_BASE), + .length = SZ_512K, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(GEMINI_POWER_CTRL_BASE), + .pfn = __phys_to_pfn(GEMINI_POWER_CTRL_BASE), + .length = SZ_512K, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(GEMINI_GPIO_BASE(0)), + .pfn = __phys_to_pfn(GEMINI_GPIO_BASE(0)), + .length = SZ_512K, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(GEMINI_GPIO_BASE(1)), + .pfn = __phys_to_pfn(GEMINI_GPIO_BASE(1)), + .length = SZ_512K, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(GEMINI_GPIO_BASE(2)), + .pfn = __phys_to_pfn(GEMINI_GPIO_BASE(2)), + .length = SZ_512K, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(GEMINI_FLASH_CTRL_BASE), + .pfn = __phys_to_pfn(GEMINI_FLASH_CTRL_BASE), + .length = SZ_512K, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(GEMINI_DRAM_CTRL_BASE), + .pfn = __phys_to_pfn(GEMINI_DRAM_CTRL_BASE), + .length = SZ_512K, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(GEMINI_GENERAL_DMA_BASE), + .pfn = __phys_to_pfn(GEMINI_GENERAL_DMA_BASE), + .length = SZ_512K, + .type = MT_DEVICE, + }, +}; + +void __init gemini_map_io(void) +{ + iotable_init(gemini_io_desc, ARRAY_SIZE(gemini_io_desc)); +} diff --git a/arch/arm/mach-gemini/time.c b/arch/arm/mach-gemini/time.c new file mode 100644 index 00000000000..21dc5a89d1c --- /dev/null +++ b/arch/arm/mach-gemini/time.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2001-2006 Storlink, Corp. + * Copyright (C) 2008-2009 Paulius Zaleckas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include + +/* + * Register definitions for the timers + */ +#define TIMER_COUNT(BASE_ADDR) (BASE_ADDR + 0x00) +#define TIMER_LOAD(BASE_ADDR) (BASE_ADDR + 0x04) +#define TIMER_MATCH1(BASE_ADDR) (BASE_ADDR + 0x08) +#define TIMER_MATCH2(BASE_ADDR) (BASE_ADDR + 0x0C) +#define TIMER_CR(BASE_ADDR) (BASE_ADDR + 0x30) + +#define TIMER_1_CR_ENABLE (1 << 0) +#define TIMER_1_CR_CLOCK (1 << 1) +#define TIMER_1_CR_INT (1 << 2) +#define TIMER_2_CR_ENABLE (1 << 3) +#define TIMER_2_CR_CLOCK (1 << 4) +#define TIMER_2_CR_INT (1 << 5) +#define TIMER_3_CR_ENABLE (1 << 6) +#define TIMER_3_CR_CLOCK (1 << 7) +#define TIMER_3_CR_INT (1 << 8) + +/* + * IRQ handler for the timer + */ +static irqreturn_t gemini_timer_interrupt(int irq, void *dev_id) +{ + timer_tick(); + + return IRQ_HANDLED; +} + +static struct irqaction gemini_timer_irq = { + .name = "Gemini Timer Tick", + .flags = IRQF_DISABLED | IRQF_TIMER, + .handler = gemini_timer_interrupt, +}; + +/* + * Set up timer interrupt, and return the current time in seconds. + */ +void __init gemini_timer_init(void) +{ + unsigned int tick_rate, reg_v; + + reg_v = __raw_readl(IO_ADDRESS(GEMINI_GLOBAL_BASE + GLOBAL_STATUS)); + tick_rate = REG_TO_AHB_SPEED(reg_v) * 1000000; + + printk(KERN_INFO "Bus: %dMHz", tick_rate / 1000000); + + tick_rate /= 6; /* APB bus run AHB*(1/6) */ + + switch(reg_v & CPU_AHB_RATIO_MASK) { + case CPU_AHB_1_1: + printk(KERN_CONT "(1/1)\n"); + break; + case CPU_AHB_3_2: + printk(KERN_CONT "(3/2)\n"); + break; + case CPU_AHB_24_13: + printk(KERN_CONT "(24/13)\n"); + break; + case CPU_AHB_2_1: + printk(KERN_CONT "(2/1)\n"); + break; + } + + /* + * Make irqs happen for the system timer + */ + setup_irq(IRQ_TIMER2, &gemini_timer_irq); + /* Start the timer */ + __raw_writel(tick_rate / HZ, TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER2_BASE))); + __raw_writel(tick_rate / HZ, TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER2_BASE))); + __raw_writel(TIMER_2_CR_ENABLE | TIMER_2_CR_INT, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE))); +} -- GitLab From 881a95f976e687307b41ba3c767561f533485c7e Mon Sep 17 00:00:00 2001 From: Paulius Zaleckas Date: Thu, 26 Mar 2009 10:06:27 +0200 Subject: [PATCH 4590/4982] MAINTAINERS: add myself as Gemini architecture maintainer Signed-off-by: Paulius Zaleckas --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index edca2ad0ebd..52e95780bd8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -502,6 +502,13 @@ P: Richard Purdie M: rpurdie@rpsys.net S: Maintained +ARM/CORTINA SYSTEMS GEMINI ARM ARCHITECTURE +P: Paulius Zaleckas +M: paulius.zaleckas@teltonika.lt +L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +T: git gitorious.org/linux-gemini/mainline.git +S: Maintained + ARM/EZX SMARTPHONES (A780, A910, A1200, E680, ROKR E2 and ROKR E6) P: Daniel Ribeiro M: drwyrm@gmail.com -- GitLab From 1df621ae2f3b03d557d962a7afec2b1d04558986 Mon Sep 17 00:00:00 2001 From: Paulius Zaleckas Date: Thu, 26 Mar 2009 10:06:27 +0200 Subject: [PATCH 4591/4982] Gemini: gpiolib based GPIO support v2 v2: - update copyrights Signed-off-by: Paulius Zaleckas --- arch/arm/Kconfig | 2 + arch/arm/mach-gemini/Makefile | 2 +- arch/arm/mach-gemini/common.h | 1 + arch/arm/mach-gemini/gpio.c | 232 +++++++++++++++++++++++ arch/arm/mach-gemini/include/mach/gpio.h | 25 +++ arch/arm/mach-gemini/include/mach/irqs.h | 5 +- 6 files changed, 265 insertions(+), 2 deletions(-) create mode 100644 arch/arm/mach-gemini/gpio.c create mode 100644 arch/arm/mach-gemini/include/mach/gpio.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 5686f4074dd..5b0204083e0 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -278,6 +278,8 @@ config ARCH_EP93XX config ARCH_GEMINI bool "Cortina Systems Gemini" select CPU_FA526 + select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB help Support for the Cortina Systems Gemini family SoCs diff --git a/arch/arm/mach-gemini/Makefile b/arch/arm/mach-gemini/Makefile index 133e2050685..e2835cdb0d2 100644 --- a/arch/arm/mach-gemini/Makefile +++ b/arch/arm/mach-gemini/Makefile @@ -4,4 +4,4 @@ # Object file lists. -obj-y := irq.o mm.o time.o devices.o +obj-y := irq.o mm.o time.o devices.o gpio.o diff --git a/arch/arm/mach-gemini/common.h b/arch/arm/mach-gemini/common.h index 9c1afa1c580..9392834a214 100644 --- a/arch/arm/mach-gemini/common.h +++ b/arch/arm/mach-gemini/common.h @@ -17,6 +17,7 @@ struct mtd_partition; extern void gemini_map_io(void); extern void gemini_init_irq(void); extern void gemini_timer_init(void); +extern void gemini_gpio_init(void); /* Common platform devices registration functions */ extern int platform_register_uart(void); diff --git a/arch/arm/mach-gemini/gpio.c b/arch/arm/mach-gemini/gpio.c new file mode 100644 index 00000000000..e7263854bc7 --- /dev/null +++ b/arch/arm/mach-gemini/gpio.c @@ -0,0 +1,232 @@ +/* + * Gemini gpiochip and interrupt routines + * + * Copyright (C) 2008-2009 Paulius Zaleckas + * + * Based on plat-mxc/gpio.c: + * MXC GPIO support. (c) 2008 Daniel Mack + * Copyright 2008 Juergen Beisert, kernel@pengutronix.de + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#define GPIO_BASE(x) IO_ADDRESS(GEMINI_GPIO_BASE(x)) + +/* GPIO registers definition */ +#define GPIO_DATA_OUT 0x0 +#define GPIO_DATA_IN 0x4 +#define GPIO_DIR 0x8 +#define GPIO_DATA_SET 0x10 +#define GPIO_DATA_CLR 0x14 +#define GPIO_PULL_EN 0x18 +#define GPIO_PULL_TYPE 0x1C +#define GPIO_INT_EN 0x20 +#define GPIO_INT_STAT 0x24 +#define GPIO_INT_MASK 0x2C +#define GPIO_INT_CLR 0x30 +#define GPIO_INT_TYPE 0x34 +#define GPIO_INT_BOTH_EDGE 0x38 +#define GPIO_INT_LEVEL 0x3C +#define GPIO_DEBOUNCE_EN 0x40 +#define GPIO_DEBOUNCE_PRESCALE 0x44 + +#define GPIO_PORT_NUM 3 + +static void _set_gpio_irqenable(unsigned int base, unsigned int index, + int enable) +{ + unsigned int reg; + + reg = __raw_readl(base + GPIO_INT_EN); + reg = (reg & (~(1 << index))) | (!!enable << index); + __raw_writel(reg, base + GPIO_INT_EN); +} + +static void gpio_ack_irq(unsigned int irq) +{ + unsigned int gpio = irq_to_gpio(irq); + unsigned int base = GPIO_BASE(gpio / 32); + + __raw_writel(1 << (gpio % 32), base + GPIO_INT_CLR); +} + +static void gpio_mask_irq(unsigned int irq) +{ + unsigned int gpio = irq_to_gpio(irq); + unsigned int base = GPIO_BASE(gpio / 32); + + _set_gpio_irqenable(base, gpio % 32, 0); +} + +static void gpio_unmask_irq(unsigned int irq) +{ + unsigned int gpio = irq_to_gpio(irq); + unsigned int base = GPIO_BASE(gpio / 32); + + _set_gpio_irqenable(base, gpio % 32, 1); +} + +static int gpio_set_irq_type(unsigned int irq, unsigned int type) +{ + unsigned int gpio = irq_to_gpio(irq); + unsigned int gpio_mask = 1 << (gpio % 32); + unsigned int base = GPIO_BASE(gpio / 32); + unsigned int reg_both, reg_level, reg_type; + + reg_type = __raw_readl(base + GPIO_INT_TYPE); + reg_level = __raw_readl(base + GPIO_INT_BOTH_EDGE); + reg_both = __raw_readl(base + GPIO_INT_BOTH_EDGE); + + switch (type) { + case IRQ_TYPE_EDGE_BOTH: + reg_type &= ~gpio_mask; + reg_both |= gpio_mask; + break; + case IRQ_TYPE_EDGE_RISING: + reg_type &= ~gpio_mask; + reg_both &= ~gpio_mask; + reg_level &= ~gpio_mask; + break; + case IRQ_TYPE_EDGE_FALLING: + reg_type &= ~gpio_mask; + reg_both &= ~gpio_mask; + reg_level |= gpio_mask; + break; + case IRQ_TYPE_LEVEL_HIGH: + reg_type |= gpio_mask; + reg_level &= ~gpio_mask; + break; + case IRQ_TYPE_LEVEL_LOW: + reg_type |= gpio_mask; + reg_level |= gpio_mask; + break; + default: + return -EINVAL; + } + + __raw_writel(reg_type, base + GPIO_INT_TYPE); + __raw_writel(reg_level, base + GPIO_INT_BOTH_EDGE); + __raw_writel(reg_both, base + GPIO_INT_BOTH_EDGE); + + gpio_ack_irq(irq); + + return 0; +} + +static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + unsigned int gpio_irq_no, irq_stat; + unsigned int port = (unsigned int)get_irq_data(irq); + + irq_stat = __raw_readl(GPIO_BASE(port) + GPIO_INT_STAT); + + gpio_irq_no = GPIO_IRQ_BASE + port * 32; + for (; irq_stat != 0; irq_stat >>= 1, gpio_irq_no++) { + + if ((irq_stat & 1) == 0) + continue; + + BUG_ON(!(irq_desc[gpio_irq_no].handle_irq)); + irq_desc[gpio_irq_no].handle_irq(gpio_irq_no, + &irq_desc[gpio_irq_no]); + } +} + +static struct irq_chip gpio_irq_chip = { + .name = "GPIO", + .ack = gpio_ack_irq, + .mask = gpio_mask_irq, + .unmask = gpio_unmask_irq, + .set_type = gpio_set_irq_type, +}; + +static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset, + int dir) +{ + unsigned int base = GPIO_BASE(offset / 32); + unsigned int reg; + + reg = __raw_readl(base + GPIO_DIR); + if (dir) + reg |= 1 << (offset % 32); + else + reg &= ~(1 << (offset % 32)); + __raw_writel(reg, base + GPIO_DIR); +} + +static void gemini_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + unsigned int base = GPIO_BASE(offset / 32); + + if (value) + __raw_writel(1 << (offset % 32), base + GPIO_DATA_SET); + else + __raw_writel(1 << (offset % 32), base + GPIO_DATA_CLR); +} + +static int gemini_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + unsigned int base = GPIO_BASE(offset / 32); + + return (__raw_readl(base + GPIO_DATA_IN) >> (offset % 32)) & 1; +} + +static int gemini_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + _set_gpio_direction(chip, offset, 0); + return 0; +} + +static int gemini_gpio_direction_output(struct gpio_chip *chip, unsigned offset, + int value) +{ + _set_gpio_direction(chip, offset, 1); + gemini_gpio_set(chip, offset, value); + return 0; +} + +static struct gpio_chip gemini_gpio_chip = { + .label = "Gemini", + .direction_input = gemini_gpio_direction_input, + .get = gemini_gpio_get, + .direction_output = gemini_gpio_direction_output, + .set = gemini_gpio_set, + .base = 0, + .ngpio = GPIO_PORT_NUM * 32, +}; + +void __init gemini_gpio_init(void) +{ + int i, j; + + for (i = 0; i < GPIO_PORT_NUM; i++) { + /* disable, unmask and clear all interrupts */ + __raw_writel(0x0, GPIO_BASE(i) + GPIO_INT_EN); + __raw_writel(0x0, GPIO_BASE(i) + GPIO_INT_MASK); + __raw_writel(~0x0, GPIO_BASE(i) + GPIO_INT_CLR); + + for (j = GPIO_IRQ_BASE + i * 32; + j < GPIO_IRQ_BASE + (i + 1) * 32; j++) { + set_irq_chip(j, &gpio_irq_chip); + set_irq_handler(j, handle_edge_irq); + set_irq_flags(j, IRQF_VALID); + } + + set_irq_chained_handler(IRQ_GPIO(i), gpio_irq_handler); + set_irq_data(IRQ_GPIO(i), (void *)i); + } + + BUG_ON(gpiochip_add(&gemini_gpio_chip)); +} diff --git a/arch/arm/mach-gemini/include/mach/gpio.h b/arch/arm/mach-gemini/include/mach/gpio.h new file mode 100644 index 00000000000..3bc2c70f298 --- /dev/null +++ b/arch/arm/mach-gemini/include/mach/gpio.h @@ -0,0 +1,25 @@ +/* + * Gemini gpiolib specific defines + * + * Copyright (C) 2008-2009 Paulius Zaleckas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __MACH_GPIO_H__ +#define __MACH_GPIO_H__ + +#include +#include + +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value +#define gpio_cansleep __gpio_cansleep + +#define gpio_to_irq(x) ((x) + GPIO_IRQ_BASE) +#define irq_to_gpio(x) ((x) - GPIO_IRQ_BASE) + +#endif /* __MACH_GPIO_H__ */ diff --git a/arch/arm/mach-gemini/include/mach/irqs.h b/arch/arm/mach-gemini/include/mach/irqs.h index c7728ac458f..06bc47e77e8 100644 --- a/arch/arm/mach-gemini/include/mach/irqs.h +++ b/arch/arm/mach-gemini/include/mach/irqs.h @@ -43,8 +43,11 @@ #define NORMAL_IRQ_NUM 32 +#define GPIO_IRQ_BASE NORMAL_IRQ_NUM +#define GPIO_IRQ_NUM (3 * 32) + #define ARCH_TIMER_IRQ IRQ_TIMER2 -#define NR_IRQS NORMAL_IRQ_NUM +#define NR_IRQS (NORMAL_IRQ_NUM + GPIO_IRQ_NUM) #endif /* __MACH_IRQS_H__ */ -- GitLab From 839e642f3dda44a35c6a91780bff41d84c288022 Mon Sep 17 00:00:00 2001 From: Paulius Zaleckas Date: Thu, 26 Mar 2009 10:06:27 +0200 Subject: [PATCH 4592/4982] Gemini: Add support for Teltonika RUT100 Signed-off-by: Paulius Zaleckas --- arch/arm/mach-gemini/Kconfig | 7 +++ arch/arm/mach-gemini/Makefile | 3 + arch/arm/mach-gemini/board-rut1xx.c | 95 +++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 arch/arm/mach-gemini/board-rut1xx.c diff --git a/arch/arm/mach-gemini/Kconfig b/arch/arm/mach-gemini/Kconfig index 3aff39abb18..515b75cf2e8 100644 --- a/arch/arm/mach-gemini/Kconfig +++ b/arch/arm/mach-gemini/Kconfig @@ -2,6 +2,13 @@ if ARCH_GEMINI menu "Cortina Systems Gemini Implementations" +config MACH_RUT100 + bool "Teltonika RUT100" + select GEMINI_MEM_SWAP + help + Say Y here if you intend to run this kernel on a + Teltonika 3G Router RUT100. + endmenu config GEMINI_MEM_SWAP diff --git a/arch/arm/mach-gemini/Makefile b/arch/arm/mach-gemini/Makefile index e2835cdb0d2..719505b8182 100644 --- a/arch/arm/mach-gemini/Makefile +++ b/arch/arm/mach-gemini/Makefile @@ -5,3 +5,6 @@ # Object file lists. obj-y := irq.o mm.o time.o devices.o gpio.o + +# Board-specific support +obj-$(CONFIG_MACH_RUT100) += board-rut1xx.o diff --git a/arch/arm/mach-gemini/board-rut1xx.c b/arch/arm/mach-gemini/board-rut1xx.c new file mode 100644 index 00000000000..e0de968e32a --- /dev/null +++ b/arch/arm/mach-gemini/board-rut1xx.c @@ -0,0 +1,95 @@ +/* + * Support for Teltonika RUT1xx + * + * Copyright (C) 2008-2009 Paulius Zaleckas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "common.h" + +static struct gpio_keys_button rut1xx_keys[] = { + { + .code = KEY_SETUP, + .gpio = 60, + .active_low = 1, + .desc = "Reset to defaults", + .type = EV_KEY, + }, +}; + +static struct gpio_keys_platform_data rut1xx_keys_data = { + .buttons = rut1xx_keys, + .nbuttons = ARRAY_SIZE(rut1xx_keys), +}; + +static struct platform_device rut1xx_keys_device = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &rut1xx_keys_data, + }, +}; + +static struct gpio_led rut100_leds[] = { + { + .name = "Power", + .default_trigger = "heartbeat", + .gpio = 17, + }, + { + .name = "GSM", + .default_trigger = "default-on", + .gpio = 7, + .active_low = 1, + }, +}; + +static struct gpio_led_platform_data rut100_leds_data = { + .num_leds = ARRAY_SIZE(rut100_leds), + .leds = rut100_leds, +}; + +static struct platform_device rut1xx_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &rut100_leds_data, + }, +}; + +static struct sys_timer rut1xx_timer = { + .init = gemini_timer_init, +}; + +static void __init rut1xx_init(void) +{ + gemini_gpio_init(); + platform_register_uart(); + platform_register_pflash(SZ_8M, NULL, 0); + platform_device_register(&rut1xx_leds); + platform_device_register(&rut1xx_keys_device); +} + +MACHINE_START(RUT100, "Teltonika RUT100") + .phys_io = 0x7fffc000, + .io_pg_offst = ((0xffffc000) >> 18) & 0xfffc, + .boot_params = 0x100, + .map_io = gemini_map_io, + .init_irq = gemini_init_irq, + .timer = &rut1xx_timer, + .init_machine = rut1xx_init, +MACHINE_END -- GitLab From 12d04a3c12b420f23398b4d650127642469a60a6 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 25 Mar 2009 22:05:03 +0000 Subject: [PATCH 4593/4982] e1000e: commonize tx cleanup routine to match e1000 & igb This change updates the e1000e tx cleanup routine to more closely match what already exists in igb and e1000. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/netdev.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 15424bad569..17974121912 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -621,15 +621,16 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) struct e1000_buffer *buffer_info; unsigned int i, eop; unsigned int count = 0; - bool cleaned = 0; + bool cleaned; unsigned int total_tx_bytes = 0, total_tx_packets = 0; i = tx_ring->next_to_clean; eop = tx_ring->buffer_info[i].next_to_watch; eop_desc = E1000_TX_DESC(*tx_ring, eop); - while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) { - for (cleaned = 0; !cleaned; ) { + while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) && + (count < tx_ring->count)) { + for (cleaned = 0; !cleaned; count++) { tx_desc = E1000_TX_DESC(*tx_ring, i); buffer_info = &tx_ring->buffer_info[i]; cleaned = (i == eop); @@ -655,10 +656,6 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) eop = tx_ring->buffer_info[i].next_to_watch; eop_desc = E1000_TX_DESC(*tx_ring, eop); -#define E1000_TX_WEIGHT 64 - /* weight of a sort for tx, to avoid endless transmit cleanup */ - if (count++ == E1000_TX_WEIGHT) - break; } tx_ring->next_to_clean = i; @@ -682,8 +679,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) /* Detect a transmit hang in hardware, this serializes the * check with the clearing of time_stamp and movement of i */ adapter->detect_tx_hung = 0; - if (tx_ring->buffer_info[eop].time_stamp && - time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + if (tx_ring->buffer_info[i].time_stamp && + time_after(jiffies, tx_ring->buffer_info[i].time_stamp + (adapter->tx_timeout_factor * HZ)) && !(er32(STATUS) & E1000_STATUS_TXOFF)) { e1000_print_tx_hang(adapter); @@ -694,7 +691,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) adapter->total_tx_packets += total_tx_packets; adapter->net_stats.tx_bytes += total_tx_bytes; adapter->net_stats.tx_packets += total_tx_packets; - return cleaned; + return (count < tx_ring->count); } /** @@ -2010,7 +2007,7 @@ static int e1000_clean(struct napi_struct *napi, int budget) clean_rx: adapter->clean_rx(adapter, &work_done, budget); - if (tx_cleaned) + if (!tx_cleaned) work_done = budget; /* If budget not fully consumed, exit the polling mode */ -- GitLab From a72d2b2cc63994cb8d592a004bf5331be6905814 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Wed, 25 Mar 2009 22:05:21 +0000 Subject: [PATCH 4594/4982] e1000e: fix loss of multicast packets e1000e (and e1000, igb, ixgbe, ixgb) all do a series of operations each time a multicast address is added. The flow goes something like 1) stack adds one multicast address 2) stack passes whole current list of unicast and multicast addresses to driver 3) driver clears entire list in hardware 4) driver programs each multicast address using iomem in a loop This was causing multicast packets to be lost during the reprogramming process. reference with test program: http://kerneltrap.org/mailarchive/linux-netdev/2009/3/14/5160514/thread Thanks to Dave Boutcher for his report and test program. This driver fix prepares an array all at once in memory and programs it in one shot to the hardware, not requiring an "erase" cycle. It would still be possible for packets to be dropped while the receiver is off during reprogramming. Signed-off-by: Jesse Brandeburg CC: Dave Boutcher Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/lib.c | 62 ++++++++++++---------------------------- 1 file changed, 18 insertions(+), 44 deletions(-) diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index ac2f34e1836..18a4f5902f3 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c @@ -158,41 +158,6 @@ void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index) E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((index << 1) + 1), rar_high); } -/** - * e1000_mta_set - Set multicast filter table address - * @hw: pointer to the HW structure - * @hash_value: determines the MTA register and bit to set - * - * The multicast table address is a register array of 32-bit registers. - * The hash_value is used to determine what register the bit is in, the - * current value is read, the new bit is OR'd in and the new value is - * written back into the register. - **/ -static void e1000_mta_set(struct e1000_hw *hw, u32 hash_value) -{ - u32 hash_bit, hash_reg, mta; - - /* - * The MTA is a register array of 32-bit registers. It is - * treated like an array of (32*mta_reg_count) bits. We want to - * set bit BitArray[hash_value]. So we figure out what register - * the bit is in, read it, OR in the new bit, then write - * back the new value. The (hw->mac.mta_reg_count - 1) serves as a - * mask to bits 31:5 of the hash value which gives us the - * register we're modifying. The hash bit within that register - * is determined by the lower 5 bits of the hash value. - */ - hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); - hash_bit = hash_value & 0x1F; - - mta = E1000_READ_REG_ARRAY(hw, E1000_MTA, hash_reg); - - mta |= (1 << hash_bit); - - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, hash_reg, mta); - e1e_flush(); -} - /** * e1000_hash_mc_addr - Generate a multicast hash value * @hw: pointer to the HW structure @@ -281,8 +246,13 @@ void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw, u8 *mc_addr_list, u32 mc_addr_count, u32 rar_used_count, u32 rar_count) { - u32 hash_value; u32 i; + u32 *mcarray = kzalloc(hw->mac.mta_reg_count * sizeof(u32), GFP_ATOMIC); + + if (!mcarray) { + printk(KERN_ERR "multicast array memory allocation failed\n"); + return; + } /* * Load the first set of multicast addresses into the exact @@ -302,20 +272,24 @@ void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw, } } - /* Clear the old settings from the MTA */ - hw_dbg(hw, "Clearing MTA\n"); - for (i = 0; i < hw->mac.mta_reg_count; i++) { - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); - e1e_flush(); - } - /* Load any remaining multicast addresses into the hash table. */ for (; mc_addr_count > 0; mc_addr_count--) { + u32 hash_value, hash_reg, hash_bit, mta; hash_value = e1000_hash_mc_addr(hw, mc_addr_list); hw_dbg(hw, "Hash value = 0x%03X\n", hash_value); - e1000_mta_set(hw, hash_value); + hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); + hash_bit = hash_value & 0x1F; + mta = (1 << hash_bit); + mcarray[hash_reg] |= mta; mc_addr_list += ETH_ALEN; } + + /* write the hash table completely */ + for (i = 0; i < hw->mac.mta_reg_count; i++) + E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, mcarray[i]); + + e1e_flush(); + kfree(mcarray); } /** -- GitLab From a3c69fef7a7775b0bcfbb8249845a25598cfe951 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Wed, 25 Mar 2009 22:05:41 +0000 Subject: [PATCH 4595/4982] e1000e: fix close interrupt race As noticed by Alan Cox, it is possible for e1000e to exit its interrupt handler or NAPI with interrupts enabled even when the driver is unloading or being configured administratively down. fix related to fix for: http://bugzilla.kernel.org/show_bug.cgi?id=12876 Signed-off-by: Jesse Brandeburg CC: Alan Cox Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/netdev.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 17974121912..b4ae0465121 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -1261,7 +1261,8 @@ static irqreturn_t e1000_msix_other(int irq, void *data) u32 icr = er32(ICR); if (!(icr & E1000_ICR_INT_ASSERTED)) { - ew32(IMS, E1000_IMS_OTHER); + if (!test_bit(__E1000_DOWN, &adapter->state)) + ew32(IMS, E1000_IMS_OTHER); return IRQ_NONE; } @@ -1278,7 +1279,8 @@ static irqreturn_t e1000_msix_other(int irq, void *data) } no_link_interrupt: - ew32(IMS, E1000_IMS_LSC | E1000_IMS_OTHER); + if (!test_bit(__E1000_DOWN, &adapter->state)) + ew32(IMS, E1000_IMS_LSC | E1000_IMS_OTHER); return IRQ_HANDLED; } @@ -2015,10 +2017,12 @@ clean_rx: if (adapter->itr_setting & 3) e1000_set_itr(adapter); napi_complete(napi); - if (adapter->msix_entries) - ew32(IMS, adapter->rx_ring->ims_val); - else - e1000_irq_enable(adapter); + if (!test_bit(__E1000_DOWN, &adapter->state)) { + if (adapter->msix_entries) + ew32(IMS, adapter->rx_ring->ims_val); + else + e1000_irq_enable(adapter); + } } return work_done; -- GitLab From 73afa537926d76dbd550614c3b75e375f1e39f83 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Wed, 25 Mar 2009 22:06:01 +0000 Subject: [PATCH 4596/4982] e1000e: update version number Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/netdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index b4ae0465121..bfb2d6c85c5 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -48,7 +48,7 @@ #include "e1000.h" -#define DRV_VERSION "0.3.3.4-k2" +#define DRV_VERSION "0.3.3.4-k4" char e1000e_driver_name[] = "e1000e"; const char e1000e_driver_version[] = DRV_VERSION; -- GitLab From ede5ad0e29b641c3d3a644272a9127bfd98dfcc8 Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Thu, 26 Mar 2009 01:11:48 -0700 Subject: [PATCH 4597/4982] net: core: remove unneeded include in net/core/utils.c. Signed-off-by: Rami Rosen Signed-off-by: David S. Miller --- net/core/utils.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/core/utils.c b/net/core/utils.c index 72e0ebe964a..83221aee708 100644 --- a/net/core/utils.c +++ b/net/core/utils.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include -- GitLab From bb3daa4a5960cd9d39bad88679fcf587b456c05d Mon Sep 17 00:00:00 2001 From: PJ Waskiewicz Date: Wed, 25 Mar 2009 22:10:42 +0000 Subject: [PATCH 4598/4982] ixgbe: Allow Priority Flow Control settings to survive a device reset When changing DCB parameters, ixgbe needs to have the MAC reset. The way the flow control code is setup today, PFC will be disabled on a reset. This patch adds a new flow control type for PFC, and then has the netlink layer take care of toggling which type of flow control to enable. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_common.c | 23 +++++++++++++++++++++-- drivers/net/ixgbe/ixgbe_dcb_82598.c | 1 - drivers/net/ixgbe/ixgbe_dcb_82599.c | 3 --- drivers/net/ixgbe/ixgbe_dcb_nl.c | 2 ++ drivers/net/ixgbe/ixgbe_type.h | 3 +++ 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index 245db0e712e..8cfd3fd309a 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -1654,9 +1654,10 @@ s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packetbuf_num) * 0: Flow control is completely disabled * 1: Rx flow control is enabled (we can receive pause frames, * but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames but - * we do not support receiving pause frames). + * 2: Tx flow control is enabled (we can send pause frames but + * we do not support receiving pause frames). * 3: Both Rx and Tx flow control (symmetric) are enabled. + * 4: Priority Flow Control is enabled. * other: Invalid. */ switch (hw->fc.current_mode) { @@ -1686,6 +1687,11 @@ s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packetbuf_num) mflcn_reg |= IXGBE_MFLCN_RFCE; fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X; break; +#ifdef CONFIG_DCB + case ixgbe_fc_pfc: + goto out; + break; +#endif default: hw_dbg(hw, "Flow control param set incorrectly\n"); ret_val = -IXGBE_ERR_CONFIG; @@ -1746,6 +1752,7 @@ s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw) * 2: Tx flow control is enabled (we can send pause frames but * we do not support receiving pause frames). * 3: Both Rx and Tx flow control (symmetric) are enabled. + * 4: Priority Flow Control is enabled. * other: Invalid. */ switch (hw->fc.current_mode) { @@ -1776,6 +1783,11 @@ s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw) /* Flow control (both Rx and Tx) is enabled by SW override. */ reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); break; +#ifdef CONFIG_DCB + case ixgbe_fc_pfc: + goto out; + break; +#endif default: hw_dbg(hw, "Flow control param set incorrectly\n"); ret_val = -IXGBE_ERR_CONFIG; @@ -1874,6 +1886,13 @@ s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw, s32 packetbuf_num) ixgbe_link_speed speed; bool link_up; +#ifdef CONFIG_DCB + if (hw->fc.requested_mode == ixgbe_fc_pfc) { + hw->fc.current_mode = hw->fc.requested_mode; + goto out; + } + +#endif /* Validate the packetbuf configuration */ if (packetbuf_num < 0 || packetbuf_num > 7) { hw_dbg(hw, "Invalid packet buffer number [%d], expected range " diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ixgbe/ixgbe_dcb_82598.c index df359554d49..62206273d88 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82598.c +++ b/drivers/net/ixgbe/ixgbe_dcb_82598.c @@ -298,7 +298,6 @@ s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, reg = IXGBE_READ_REG(hw, IXGBE_RMCS); reg &= ~IXGBE_RMCS_TFCE_802_3X; /* correct the reporting of our flow control status */ - hw->fc.current_mode = ixgbe_fc_none; reg |= IXGBE_RMCS_TFCE_PRIORITY; IXGBE_WRITE_REG(hw, IXGBE_RMCS, reg); diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ixgbe/ixgbe_dcb_82599.c index adcbac42263..470b676c1da 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82599.c +++ b/drivers/net/ixgbe/ixgbe_dcb_82599.c @@ -299,9 +299,6 @@ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, goto out; } - /* PFC is mutually exclusive with link flow control */ - hw->fc.current_mode = ixgbe_fc_none; - /* Configure PFC Tx thresholds per TC */ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { /* Config and remember Tx */ diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index 8a9939ee292..0a8731f1f23 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c @@ -130,6 +130,7 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) adapter->tx_ring = NULL; adapter->rx_ring = NULL; + adapter->hw.fc.requested_mode = ixgbe_fc_pfc; adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; adapter->flags |= IXGBE_FLAG_DCB_ENABLED; ixgbe_init_interrupt_scheme(adapter); @@ -138,6 +139,7 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) } else { /* Turn off DCB */ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { + adapter->hw.fc.requested_mode = ixgbe_fc_default; if (netif_running(netdev)) netdev->netdev_ops->ndo_stop(netdev); ixgbe_reset_interrupt_capability(adapter); diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 95fc36cff26..2b2ecba7b60 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -1939,6 +1939,9 @@ enum ixgbe_fc_mode { ixgbe_fc_rx_pause, ixgbe_fc_tx_pause, ixgbe_fc_full, +#ifdef CONFIG_DCB + ixgbe_fc_pfc, +#endif ixgbe_fc_default }; -- GitLab From 86ee79c3dbd48d7430fd81edc1da3516c9f6dabc Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 26 Mar 2009 01:54:46 -0700 Subject: [PATCH 4599/4982] sparc64: Flush TLB before releasing pages. tlb_flush_mmu() needs to flush pending TLB entries before processing the mmu_gather ->pages list. Noticed by Benjamin Herrenschmidt. Signed-off-by: David S. Miller --- arch/sparc/include/asm/tlb_64.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sparc/include/asm/tlb_64.h b/arch/sparc/include/asm/tlb_64.h index ec81cdedef2..ee38e731bfa 100644 --- a/arch/sparc/include/asm/tlb_64.h +++ b/arch/sparc/include/asm/tlb_64.h @@ -57,6 +57,8 @@ static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm, unsigned i static inline void tlb_flush_mmu(struct mmu_gather *mp) { + if (!mp->fullmm) + flush_tlb_pending(); if (mp->need_flush) { free_pages_and_swap_cache(mp->pages, mp->pages_nr); mp->pages_nr = 0; @@ -78,8 +80,6 @@ static inline void tlb_finish_mmu(struct mmu_gather *mp, unsigned long start, un if (mp->fullmm) mp->fullmm = 0; - else - flush_tlb_pending(); /* keep the page table cache within bounds */ check_pgt_cache(); -- GitLab From f028f3b2f987ebc61cef382ab7a5c449917b728e Mon Sep 17 00:00:00 2001 From: Nikanth Karthikesan Date: Tue, 24 Mar 2009 12:33:41 +0100 Subject: [PATCH 4600/4982] loop: fix circular locking in loop_clr_fd() With CONFIG_PROVE_LOCKING enabled $ losetup /dev/loop0 file $ losetup -o 32256 /dev/loop1 /dev/loop0 $ losetup -d /dev/loop1 $ losetup -d /dev/loop0 triggers a [ INFO: possible circular locking dependency detected ] I think this warning is a false positive. Open/close on a loop device acquires bd_mutex of the device before acquiring lo_ctl_mutex of the same device. For ioctl(LOOP_CLR_FD) after acquiring lo_ctl_mutex, fput on the backing_file might acquire the bd_mutex of a device, if backing file is a device and this is the last reference to the file being dropped . But it is guaranteed that it is impossible to have a circular list of backing devices.(say loop2->loop1->loop0->loop2 is not possible), which guarantees that this can never deadlock. So this warning should be suppressed. It is very difficult to annotate lockdep not to warn here in the correct way. A simple way to silence lockdep could be to mark the lo_ctl_mutex in ioctl to be a sub class, but this might mask some other real bugs. @@ -1164,7 +1164,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, struct loop_device *lo = bdev->bd_disk->private_data; int err; - mutex_lock(&lo->lo_ctl_mutex); + mutex_lock_nested(&lo->lo_ctl_mutex, 1); switch (cmd) { case LOOP_SET_FD: err = loop_set_fd(lo, mode, bdev, arg); Or actually marking the bd_mutex after lo_ctl_mutex as a sub class could be a better solution. Luckily it is easy to avoid calling fput on backing file with lo_ctl_mutex held, so no lockdep annotation is required. If you do not like the special handling of the lo_ctl_mutex just for the LOOP_CLR_FD ioctl in lo_ioctl(), the mutex handling could be moved inside each of the individual ioctl handlers and I could send you another patch. Signed-off-by: Jens Axboe --- drivers/block/loop.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 9721d100caf..2621ed2ce6d 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -969,11 +969,18 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) bd_set_size(bdev, 0); mapping_set_gfp_mask(filp->f_mapping, gfp); lo->lo_state = Lo_unbound; - fput(filp); /* This is safe: open() is still holding a reference. */ module_put(THIS_MODULE); if (max_part > 0) ioctl_by_bdev(bdev, BLKRRPART, 0); + mutex_unlock(&lo->lo_ctl_mutex); + /* + * Need not hold lo_ctl_mutex to fput backing file. + * Calling fput holding lo_ctl_mutex triggers a circular + * lock dependency possibility warning as fput can take + * bd_mutex which is usually taken before lo_ctl_mutex. + */ + fput(filp); return 0; } @@ -1191,7 +1198,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, struct loop_device *lo = bdev->bd_disk->private_data; int err; - mutex_lock(&lo->lo_ctl_mutex); + mutex_lock_nested(&lo->lo_ctl_mutex, 1); switch (cmd) { case LOOP_SET_FD: err = loop_set_fd(lo, mode, bdev, arg); @@ -1200,7 +1207,10 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, err = loop_change_fd(lo, bdev, arg); break; case LOOP_CLR_FD: + /* loop_clr_fd would have unlocked lo_ctl_mutex on success */ err = loop_clr_fd(lo, bdev); + if (!err) + goto out_unlocked; break; case LOOP_SET_STATUS: err = loop_set_status_old(lo, (struct loop_info __user *) arg); @@ -1218,6 +1228,8 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL; } mutex_unlock(&lo->lo_ctl_mutex); + +out_unlocked: return err; } -- GitLab From 1cd96c242a829d52f7a5ae98f554ca9775429685 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Tue, 24 Mar 2009 12:35:07 +0100 Subject: [PATCH 4601/4982] block: WARN in __blk_put_request() for potential bio leak Put a WARN_ON in __blk_put_request if it is about to leak bio(s). This is a serious bug that can happen in error handling code paths. For this to work I have fixed a couple of places in block/ where request->bio != NULL ownership was not honored. And a small cleanup at sg_io() while at it. Signed-off-by: Boaz Harrosh Signed-off-by: Jens Axboe --- block/blk-core.c | 3 +++ block/blk-merge.c | 2 ++ block/scsi_ioctl.c | 21 ++++----------------- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 7b63c9b6333..996ed906d8c 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1062,6 +1062,9 @@ void __blk_put_request(struct request_queue *q, struct request *req) elv_completed_request(q, req); + /* this is a bio leak */ + WARN_ON(req->bio != NULL); + /* * Request may not have originated from ll_rw_blk. if not, * it didn't come out of our reserved rq pools diff --git a/block/blk-merge.c b/block/blk-merge.c index 5a244f05360..e39cb24b767 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -403,6 +403,8 @@ static int attempt_merge(struct request_queue *q, struct request *req, if (blk_rq_cpu_valid(next)) req->cpu = next->cpu; + /* owner-ship of bio passed from next to req */ + next->bio = NULL; __blk_put_request(q, next); return 1; } diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index ee9c67d7e1b..626ee274c5c 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -214,21 +214,10 @@ static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq, return 0; } -/* - * unmap a request that was previously mapped to this sg_io_hdr. handles - * both sg and non-sg sg_io_hdr. - */ -static int blk_unmap_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr) -{ - blk_rq_unmap_user(rq->bio); - blk_put_request(rq); - return 0; -} - static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr, struct bio *bio) { - int r, ret = 0; + int ret = 0; /* * fill in all the output members @@ -253,12 +242,10 @@ static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr, ret = -EFAULT; } - rq->bio = bio; - r = blk_unmap_sghdr_rq(rq, hdr); - if (ret) - r = ret; + blk_rq_unmap_user(bio); + blk_put_request(rq); - return r; + return ret; } static int sg_io(struct request_queue *q, struct gendisk *bd_disk, -- GitLab From e7cbbf1bf17e3c706f874e867f7b744e1c86fed9 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Tue, 24 Mar 2009 12:37:50 +0100 Subject: [PATCH 4602/4982] bsg: Remove bogus check against request_queue->max_sectors bsg submits REQ_TYPE_BLOCK_PC so the right check is max_hw_sectors. But I've removed this check because right after, bsg proceeds with calling blk_rq_map_user() which does all the right checks. Signed-off-by: Boaz Harrosh Signed-off-by: Jens Axboe --- block/bsg.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/block/bsg.c b/block/bsg.c index 0f63b91d0af..206060e795d 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -218,9 +218,6 @@ bsg_validate_sgv4_hdr(struct request_queue *q, struct sg_io_v4 *hdr, int *rw) if (hdr->guard != 'Q') return -EINVAL; - if (hdr->dout_xfer_len > (q->max_sectors << 9) || - hdr->din_xfer_len > (q->max_sectors << 9)) - return -EIO; switch (hdr->protocol) { case BSG_PROTOCOL_SCSI: -- GitLab From 07e86f405addc6436eb969b8279bb14a6dcacce4 Mon Sep 17 00:00:00 2001 From: Avishay Traeger Date: Tue, 24 Mar 2009 12:40:18 +0100 Subject: [PATCH 4603/4982] block: Repeated lines in switching-sched.txt These lines appear in this file twice - removed one occurrence. Signed-off-by: Avishay Traeger Signed-off-by: Jens Axboe --- Documentation/block/switching-sched.txt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Documentation/block/switching-sched.txt b/Documentation/block/switching-sched.txt index 634c952e196..d5af3f63081 100644 --- a/Documentation/block/switching-sched.txt +++ b/Documentation/block/switching-sched.txt @@ -35,9 +35,3 @@ noop anticipatory deadline [cfq] # echo anticipatory > /sys/block/hda/queue/scheduler # cat /sys/block/hda/queue/scheduler noop [anticipatory] deadline cfq - -Each io queue has a set of io scheduler tunables associated with it. These -tunables control how the io scheduler works. You can find these entries -in: - -/sys/block//queue/iosched -- GitLab From 26160158d3d3df548f4ee046cc6147fe048cfa9c Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 17 Mar 2009 09:35:06 +0100 Subject: [PATCH 4604/4982] Move the default_backing_dev_info out of readahead.c and into backing-dev.c It really makes no sense to have it in readahead.c, so move it where it belongs. Signed-off-by: Jens Axboe --- mm/backing-dev.c | 26 +++++++++++++++++++++++++- mm/readahead.c | 25 ------------------------- 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 8e858744413..be68c956a66 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -2,11 +2,24 @@ #include #include #include +#include #include #include #include #include +void default_unplug_io_fn(struct backing_dev_info *bdi, struct page *page) +{ +} +EXPORT_SYMBOL(default_unplug_io_fn); + +struct backing_dev_info default_backing_dev_info = { + .ra_pages = VM_MAX_READAHEAD * 1024 / PAGE_CACHE_SIZE, + .state = 0, + .capabilities = BDI_CAP_MAP_COPY, + .unplug_io_fn = default_unplug_io_fn, +}; +EXPORT_SYMBOL_GPL(default_backing_dev_info); static struct class *bdi_class; @@ -166,9 +179,20 @@ static __init int bdi_class_init(void) bdi_debug_init(); return 0; } - postcore_initcall(bdi_class_init); +static int __init default_bdi_init(void) +{ + int err; + + err = bdi_init(&default_backing_dev_info); + if (!err) + bdi_register(&default_backing_dev_info, NULL, "default"); + + return err; +} +subsys_initcall(default_bdi_init); + int bdi_register(struct backing_dev_info *bdi, struct device *parent, const char *fmt, ...) { diff --git a/mm/readahead.c b/mm/readahead.c index bec83c15a78..9ce303d4b81 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -17,19 +17,6 @@ #include #include -void default_unplug_io_fn(struct backing_dev_info *bdi, struct page *page) -{ -} -EXPORT_SYMBOL(default_unplug_io_fn); - -struct backing_dev_info default_backing_dev_info = { - .ra_pages = VM_MAX_READAHEAD * 1024 / PAGE_CACHE_SIZE, - .state = 0, - .capabilities = BDI_CAP_MAP_COPY, - .unplug_io_fn = default_unplug_io_fn, -}; -EXPORT_SYMBOL_GPL(default_backing_dev_info); - /* * Initialise a struct file's readahead state. Assumes that the caller has * memset *ra to zero. @@ -233,18 +220,6 @@ unsigned long max_sane_readahead(unsigned long nr) + node_page_state(numa_node_id(), NR_FREE_PAGES)) / 2); } -static int __init readahead_init(void) -{ - int err; - - err = bdi_init(&default_backing_dev_info); - if (!err) - bdi_register(&default_backing_dev_info, NULL, "default"); - - return err; -} -subsys_initcall(readahead_init); - /* * Submit IO for the read-ahead request in file_ra_state. */ -- GitLab From 6933c02e9cc47c2df3c016621a013ec79fb4203f Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 17 Mar 2009 09:36:37 +0100 Subject: [PATCH 4605/4982] btrfs: get rid of current_is_pdflush() in btrfs_btree_balance_dirty Chris says it's safe to kill. Acked-by: Chris Mason Signed-off-by: Jens Axboe --- fs/btrfs/disk-io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 3e18175248e..6ec80c0fc86 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2385,7 +2385,7 @@ void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr) unsigned long thresh = 32 * 1024 * 1024; tree = &BTRFS_I(root->fs_info->btree_inode)->io_tree; - if (current_is_pdflush() || current->flags & PF_MEMALLOC) + if (current->flags & PF_MEMALLOC) return; num_dirty = count_range_bits(tree, &start, (u64)-1, -- GitLab From a2a9537ac0b37a5da6fbe7e1e9cb06c524d2a9c4 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 17 Mar 2009 09:38:40 +0100 Subject: [PATCH 4606/4982] Get rid of pdflush_operation() in emergency sync and remount Opencode a cheasy approach with kevent. The idea here is that we'll add some generic delayed work infrastructure, which probably wont be based on pdflush (or maybe it will, in which case we can just add it back). This is in preparation for getting rid of pdflush completely. Signed-off-by: Jens Axboe --- fs/super.c | 11 +++++++++-- fs/sync.c | 14 +++++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/fs/super.c b/fs/super.c index 6ce501447ad..dd4acb158b5 100644 --- a/fs/super.c +++ b/fs/super.c @@ -674,7 +674,7 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) return 0; } -static void do_emergency_remount(unsigned long foo) +static void do_emergency_remount(struct work_struct *work) { struct super_block *sb; @@ -697,12 +697,19 @@ static void do_emergency_remount(unsigned long foo) spin_lock(&sb_lock); } spin_unlock(&sb_lock); + kfree(work); printk("Emergency Remount complete\n"); } void emergency_remount(void) { - pdflush_operation(do_emergency_remount, 0); + struct work_struct *work; + + work = kmalloc(sizeof(*work), GFP_ATOMIC); + if (work) { + INIT_WORK(work, do_emergency_remount); + schedule_work(work); + } } /* diff --git a/fs/sync.c b/fs/sync.c index a16d53e5fe9..ec95a69d17a 100644 --- a/fs/sync.c +++ b/fs/sync.c @@ -42,9 +42,21 @@ SYSCALL_DEFINE0(sync) return 0; } +static void do_sync_work(struct work_struct *work) +{ + do_sync(0); + kfree(work); +} + void emergency_sync(void) { - pdflush_operation(do_sync, 0); + struct work_struct *work; + + work = kmalloc(sizeof(*work), GFP_ATOMIC); + if (work) { + INIT_WORK(work, do_sync_work); + schedule_work(work); + } } /* -- GitLab From d271e8bd8c60ce059ee36d836ba063cfc61c3e21 Mon Sep 17 00:00:00 2001 From: Holger Eitzenberger Date: Thu, 26 Mar 2009 13:37:14 +0100 Subject: [PATCH 4607/4982] ctnetlink: compute generic part of event more acurately On a box with most of the optional Netfilter switches turned off some of the NLAs are never send, e. g. secmark, mark or the conntrack byte/packet counters. As a worst case scenario this may possibly still lead to ctnetlink skbs being reallocated in netlink_trim() later, loosing all the nice effects from the previous patches. I try to solve that (at least partly) by correctly #ifdef'ing the NLAs in the computation. Signed-off-by: Holger Eitzenberger Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_netlink.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 03547c60f38..2fb833b130c 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -441,19 +441,28 @@ ctnetlink_alloc_skb(const struct nf_conntrack_tuple *tuple, gfp_t gfp) + 3 * NLA_TYPE_SIZE(u_int8_t) /* CTA_PROTO_NUM */ + NLA_TYPE_SIZE(u_int32_t) /* CTA_ID */ + NLA_TYPE_SIZE(u_int32_t) /* CTA_STATUS */ +#ifdef CONFIG_NF_CT_ACCT + 2 * nla_total_size(0) /* CTA_COUNTERS_ORIG|REPL */ + 2 * NLA_TYPE_SIZE(uint64_t) /* CTA_COUNTERS_PACKETS */ + 2 * NLA_TYPE_SIZE(uint64_t) /* CTA_COUNTERS_BYTES */ +#endif + NLA_TYPE_SIZE(u_int32_t) /* CTA_TIMEOUT */ + nla_total_size(0) /* CTA_PROTOINFO */ + nla_total_size(0) /* CTA_HELP */ + nla_total_size(NF_CT_HELPER_NAME_LEN) /* CTA_HELP_NAME */ +#ifdef CONFIG_NF_CONNTRACK_SECMARK + NLA_TYPE_SIZE(u_int32_t) /* CTA_SECMARK */ +#endif +#ifdef CONFIG_NF_NAT_NEEDED + 2 * nla_total_size(0) /* CTA_NAT_SEQ_ADJ_ORIG|REPL */ + 2 * NLA_TYPE_SIZE(u_int32_t) /* CTA_NAT_SEQ_CORRECTION_POS */ + 2 * NLA_TYPE_SIZE(u_int32_t) /* CTA_NAT_SEQ_CORRECTION_BEFORE */ + 2 * NLA_TYPE_SIZE(u_int32_t) /* CTA_NAT_SEQ_CORRECTION_AFTER */ - + NLA_TYPE_SIZE(u_int32_t); /* CTA_MARK */ +#endif +#ifdef CONFIG_NF_CONNTRACK_MARK + + NLA_TYPE_SIZE(u_int32_t) /* CTA_MARK */ +#endif + ; #undef NLA_TYPE_SIZE -- GitLab From 707b2c247c6c3e8976f94fcf9ab25c85502352d5 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Thu, 26 Mar 2009 21:04:10 +0800 Subject: [PATCH 4608/4982] [ARM] pxa: build arch/arm/plat-pxa/mfp.c only when PXA3xx or ARCH_MMP defined arch/arm/plat-pxa/mfp.c is not intended to be use by PXA25x/PXA27x, make it explicit here only for use by PXA3xx or ARCH_MMP. Reported-by: Guennadi Liakhovestski Reported-by: Robert Jarzmik Signed-off-by: Eric Miao --- arch/arm/plat-pxa/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile index 4be37235f57..8f2c4c7fbd4 100644 --- a/arch/arm/plat-pxa/Makefile +++ b/arch/arm/plat-pxa/Makefile @@ -2,6 +2,8 @@ # Makefile for code common across different PXA processor families # -obj-y := dma.o mfp.o +obj-y := dma.o obj-$(CONFIG_GENERIC_GPIO) += gpio.o +obj-$(CONFIG_PXA3xx) += mfp.o +obj-$(CONFIG_ARCH_MMP) += mfp.o -- GitLab From d7fd5f1e3b195a8232b3ed768ac2809ddce8ca46 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Thu, 26 Mar 2009 15:23:42 +0100 Subject: [PATCH 4609/4982] [S390] fix dump_stack vs. %p and (null) The s390 implemenation of dump_stack uses %p to display stack content. Since d97106ab53f812910a62d18afb9dbe882819c1ba (Make %p print '(null)' for NULL pointers) this causes a strange output for dump_stack: [...] Process basename (pid: 8822, task: 00000000b2ece038, ksp: 00000000b24d7b38) 04000000b5685c00 00000000b24d7760 0000000000000002 (null) 00000000b24d7800 00000000b24d7778 00000000b24d7778 00000000001052fe (null) 00000000b24d7b38 (null) 000000000000000a 000000000000000d (null) 00000000b24d7760 00000000b24d77d8 000000000051a7e8 00000000001052fe 00000000b24d7760 00000000b24d77b0 Call Trace: [...] This patch changes our dump_stack to use the appropriate %x format. Signed-off-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/traps.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 4584d81984c..c2e42cc65ce 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -61,9 +61,11 @@ extern pgm_check_handler_t do_asce_exception; #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; }) #ifndef CONFIG_64BIT +#define LONG "%08lx " #define FOURLONG "%08lx %08lx %08lx %08lx\n" static int kstack_depth_to_print = 12; #else /* CONFIG_64BIT */ +#define LONG "%016lx " #define FOURLONG "%016lx %016lx %016lx %016lx\n" static int kstack_depth_to_print = 20; #endif /* CONFIG_64BIT */ @@ -155,7 +157,7 @@ void show_stack(struct task_struct *task, unsigned long *sp) break; if (i && ((i * sizeof (long) % 32) == 0)) printk("\n "); - printk("%p ", (void *)*stack++); + printk(LONG, *stack++); } printk("\n"); show_trace(task, sp); -- GitLab From 099b765139929efdcf232f8870804accf8c4cdc5 Mon Sep 17 00:00:00 2001 From: Frank Munzert Date: Thu, 26 Mar 2009 15:23:43 +0100 Subject: [PATCH 4610/4982] [S390] Automatic IPL after dump Provide new shutdown action "dump_reipl" for automatic ipl after dump. Signed-off-by: Frank Munzert Signed-off-by: Martin Schwidefsky Signed-off-by: Heiko Carstens --- arch/s390/include/asm/lowcore.h | 24 ++++----- arch/s390/include/asm/system.h | 16 ++++++ arch/s390/kernel/ipl.c | 56 +++++++++++++++++++-- arch/s390/kernel/setup.c | 5 ++ arch/s390/kernel/smp.c | 9 ---- drivers/s390/char/zcore.c | 88 ++++++++++++++++++++++++++++++++- 6 files changed, 172 insertions(+), 26 deletions(-) diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index f3720defdd1..ee4b10ff938 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -111,7 +111,7 @@ #define __LC_PASTE 0xE40 -#define __LC_PANIC_MAGIC 0xE00 +#define __LC_DUMP_REIPL 0xE00 #ifndef __s390x__ #define __LC_PFAULT_INTPARM 0x080 #define __LC_CPU_TIMER_SAVE_AREA 0x0D8 @@ -286,12 +286,14 @@ struct _lowcore __u64 int_clock; /* 0xc98 */ __u8 pad11[0xe00-0xca0]; /* 0xca0 */ - /* 0xe00 is used as indicator for dump tools */ - /* whether the kernel died with panic() or not */ - __u32 panic_magic; /* 0xe00 */ + /* 0xe00 contains the address of the IPL Parameter */ + /* Information block. Dump tools need IPIB for IPL */ + /* after dump. */ + __u32 ipib; /* 0xe00 */ + __u32 ipib_checksum; /* 0xe04 */ /* Align to the top 1k of prefix area */ - __u8 pad12[0x1000-0xe04]; /* 0xe04 */ + __u8 pad12[0x1000-0xe08]; /* 0xe08 */ #else /* !__s390x__ */ /* prefix area: defined by architecture */ __u32 ccw1[2]; /* 0x000 */ @@ -379,12 +381,14 @@ struct _lowcore __u64 int_clock; /* 0xde8 */ __u8 pad12[0xe00-0xdf0]; /* 0xdf0 */ - /* 0xe00 is used as indicator for dump tools */ - /* whether the kernel died with panic() or not */ - __u32 panic_magic; /* 0xe00 */ + /* 0xe00 contains the address of the IPL Parameter */ + /* Information block. Dump tools need IPIB for IPL */ + /* after dump. */ + __u64 ipib; /* 0xe00 */ + __u32 ipib_checksum; /* 0xe08 */ /* Per cpu primary space access list */ - __u8 pad_0xe04[0xe38-0xe04]; /* 0xe04 */ + __u8 pad_0xe0c[0xe38-0xe0c]; /* 0xe0c */ __u64 vdso_per_cpu_data; /* 0xe38 */ __u32 paste[16]; /* 0xe40 */ @@ -433,8 +437,6 @@ static inline __u32 store_prefix(void) return address; } -#define __PANIC_MAGIC 0xDEADC0DE - #endif #endif diff --git a/arch/s390/include/asm/system.h b/arch/s390/include/asm/system.h index 3a8b26eb1f2..3f2ccb82b86 100644 --- a/arch/s390/include/asm/system.h +++ b/arch/s390/include/asm/system.h @@ -458,6 +458,22 @@ static inline unsigned short stap(void) return cpu_address; } +static inline u32 cksm(void *addr, unsigned long len) +{ + register unsigned long _addr asm("0") = (unsigned long) addr; + register unsigned long _len asm("1") = len; + unsigned long accu = 0; + + asm volatile( + "0:\n" + " cksm %0,%1\n" + " jnz 0b\n" + : "+d" (accu), "+d" (_addr), "+d" (_len) + : + : "cc", "memory"); + return accu; +} + extern void (*_machine_restart)(char *command); extern void (*_machine_halt)(void); extern void (*_machine_power_off)(void); diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 2dcf590faba..5663c1f8e46 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -56,13 +56,14 @@ struct shutdown_trigger { }; /* - * Five shutdown action types are supported: + * The following shutdown action types are supported: */ #define SHUTDOWN_ACTION_IPL_STR "ipl" #define SHUTDOWN_ACTION_REIPL_STR "reipl" #define SHUTDOWN_ACTION_DUMP_STR "dump" #define SHUTDOWN_ACTION_VMCMD_STR "vmcmd" #define SHUTDOWN_ACTION_STOP_STR "stop" +#define SHUTDOWN_ACTION_DUMP_REIPL_STR "dump_reipl" struct shutdown_action { char *name; @@ -146,6 +147,7 @@ static enum ipl_method reipl_method = REIPL_METHOD_DEFAULT; static struct ipl_parameter_block *reipl_block_fcp; static struct ipl_parameter_block *reipl_block_ccw; static struct ipl_parameter_block *reipl_block_nss; +static struct ipl_parameter_block *reipl_block_actual; static int dump_capabilities = DUMP_TYPE_NONE; static enum dump_type dump_type = DUMP_TYPE_NONE; @@ -835,6 +837,7 @@ static int reipl_set_type(enum ipl_type type) reipl_method = REIPL_METHOD_CCW_VM; else reipl_method = REIPL_METHOD_CCW_CIO; + reipl_block_actual = reipl_block_ccw; break; case IPL_TYPE_FCP: if (diag308_set_works) @@ -843,6 +846,7 @@ static int reipl_set_type(enum ipl_type type) reipl_method = REIPL_METHOD_FCP_RO_VM; else reipl_method = REIPL_METHOD_FCP_RO_DIAG; + reipl_block_actual = reipl_block_fcp; break; case IPL_TYPE_FCP_DUMP: reipl_method = REIPL_METHOD_FCP_DUMP; @@ -852,6 +856,7 @@ static int reipl_set_type(enum ipl_type type) reipl_method = REIPL_METHOD_NSS_DIAG; else reipl_method = REIPL_METHOD_NSS; + reipl_block_actual = reipl_block_nss; break; case IPL_TYPE_UNKNOWN: reipl_method = REIPL_METHOD_DEFAULT; @@ -1332,6 +1337,48 @@ static struct shutdown_action __refdata dump_action = { .init = dump_init, }; +static void dump_reipl_run(struct shutdown_trigger *trigger) +{ + preempt_disable(); + /* + * Bypass dynamic address translation (DAT) when storing IPL parameter + * information block address and checksum into the prefix area + * (corresponding to absolute addresses 0-8191). + * When enhanced DAT applies and the STE format control in one, + * the absolute address is formed without prefixing. In this case a + * normal store (stg/st) into the prefix area would no more match to + * absolute addresses 0-8191. + */ +#ifdef CONFIG_64BIT + asm volatile("sturg %0,%1" + :: "a" ((unsigned long) reipl_block_actual), + "a" (&lowcore_ptr[smp_processor_id()]->ipib)); +#else + asm volatile("stura %0,%1" + :: "a" ((unsigned long) reipl_block_actual), + "a" (&lowcore_ptr[smp_processor_id()]->ipib)); +#endif + asm volatile("stura %0,%1" + :: "a" (cksm(reipl_block_actual, reipl_block_actual->hdr.len)), + "a" (&lowcore_ptr[smp_processor_id()]->ipib_checksum)); + preempt_enable(); + dump_run(trigger); +} + +static int __init dump_reipl_init(void) +{ + if (!diag308_set_works) + return -EOPNOTSUPP; + else + return 0; +} + +static struct shutdown_action __refdata dump_reipl_action = { + .name = SHUTDOWN_ACTION_DUMP_REIPL_STR, + .fn = dump_reipl_run, + .init = dump_reipl_init, +}; + /* * vmcmd shutdown action: Trigger vm command on shutdown. */ @@ -1421,7 +1468,8 @@ static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR, /* action list */ static struct shutdown_action *shutdown_actions_list[] = { - &ipl_action, &reipl_action, &dump_action, &vmcmd_action, &stop_action}; + &ipl_action, &reipl_action, &dump_reipl_action, &dump_action, + &vmcmd_action, &stop_action}; #define SHUTDOWN_ACTIONS_COUNT (sizeof(shutdown_actions_list) / sizeof(void *)) /* @@ -1434,11 +1482,11 @@ static int set_trigger(const char *buf, struct shutdown_trigger *trigger, size_t len) { int i; + for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) { if (!shutdown_actions_list[i]) continue; - if (strncmp(buf, shutdown_actions_list[i]->name, - strlen(shutdown_actions_list[i]->name)) == 0) { + if (sysfs_streq(buf, shutdown_actions_list[i]->name)) { trigger->action = shutdown_actions_list[i]; return len; } diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index c5cfb6185ea..8fdf08379ce 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -86,6 +86,10 @@ volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */ int __initdata memory_end_set; unsigned long __initdata memory_end; +/* An array with a pointer to the lowcore of every CPU. */ +struct _lowcore *lowcore_ptr[NR_CPUS]; +EXPORT_SYMBOL(lowcore_ptr); + /* * This is set up by the setup-routine at boot-time * for S390 need to find out, what we have to setup @@ -434,6 +438,7 @@ setup_lowcore(void) lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0]; #endif set_prefix((u32)(unsigned long) lc); + lowcore_ptr[0] = lc; } static void __init diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 2d337cbb932..e279d0fbbbe 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -50,12 +50,6 @@ #include #include "entry.h" -/* - * An array with a pointer the lowcore of every CPU. - */ -struct _lowcore *lowcore_ptr[NR_CPUS]; -EXPORT_SYMBOL(lowcore_ptr); - static struct task_struct *current_set[NR_CPUS]; static u8 smp_cpu_type; @@ -82,9 +76,6 @@ void smp_send_stop(void) /* Disable all interrupts/machine checks */ __load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK); - /* write magic number to zero page (absolute 0) */ - lowcore_ptr[smp_processor_id()]->panic_magic = __PANIC_MAGIC; - /* stop all processors */ for_each_online_cpu(cpu) { if (cpu == smp_processor_id()) diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index eefc6611412..cfe782ee647 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c @@ -5,7 +5,7 @@ * * For more information please refer to Documentation/s390/zfcpdump.txt * - * Copyright IBM Corp. 2003,2007 + * Copyright IBM Corp. 2003,2008 * Author(s): Michael Holzheu */ @@ -48,12 +48,19 @@ struct sys_info { union save_area lc_mask; }; +struct ipib_info { + unsigned long ipib; + u32 checksum; +} __attribute__((packed)); + static struct sys_info sys_info; static struct debug_info *zcore_dbf; static int hsa_available; static struct dentry *zcore_dir; static struct dentry *zcore_file; static struct dentry *zcore_memmap_file; +static struct dentry *zcore_reipl_file; +static struct ipl_parameter_block *ipl_block; /* * Copy memory from HSA to kernel or user memory (not reentrant): @@ -527,6 +534,33 @@ static const struct file_operations zcore_memmap_fops = { .release = zcore_memmap_release, }; +static ssize_t zcore_reipl_write(struct file *filp, const char __user *buf, + size_t count, loff_t *ppos) +{ + if (ipl_block) { + diag308(DIAG308_SET, ipl_block); + diag308(DIAG308_IPL, NULL); + } + return count; +} + +static int zcore_reipl_open(struct inode *inode, struct file *filp) +{ + return 0; +} + +static int zcore_reipl_release(struct inode *inode, struct file *filp) +{ + return 0; +} + +static const struct file_operations zcore_reipl_fops = { + .owner = THIS_MODULE, + .write = zcore_reipl_write, + .open = zcore_reipl_open, + .release = zcore_reipl_release, +}; + static void __init set_s390_lc_mask(union save_area *map) { @@ -645,6 +679,39 @@ static int __init zcore_header_init(int arch, struct zcore_header *hdr) return 0; } +/* + * Provide IPL parameter information block from either HSA or memory + * for future reipl + */ +static int __init zcore_reipl_init(void) +{ + struct ipib_info ipib_info; + int rc; + + rc = memcpy_hsa_kernel(&ipib_info, __LC_DUMP_REIPL, sizeof(ipib_info)); + if (rc) + return rc; + if (ipib_info.ipib == 0) + return 0; + ipl_block = (void *) __get_free_page(GFP_KERNEL); + if (!ipl_block) + return -ENOMEM; + if (ipib_info.ipib < ZFCPDUMP_HSA_SIZE) + rc = memcpy_hsa_kernel(ipl_block, ipib_info.ipib, PAGE_SIZE); + else + rc = memcpy_real(ipl_block, ipib_info.ipib, PAGE_SIZE); + if (rc) { + free_page((unsigned long) ipl_block); + return rc; + } + if (cksm(ipl_block, ipl_block->hdr.len) != ipib_info.checksum) { + TRACE("Checksum does not match\n"); + free_page((unsigned long) ipl_block); + ipl_block = NULL; + } + return 0; +} + static int __init zcore_init(void) { unsigned char arch; @@ -690,6 +757,10 @@ static int __init zcore_init(void) if (rc) goto fail; + rc = zcore_reipl_init(); + if (rc) + goto fail; + zcore_dir = debugfs_create_dir("zcore" , NULL); if (!zcore_dir) { rc = -ENOMEM; @@ -707,9 +778,17 @@ static int __init zcore_init(void) rc = -ENOMEM; goto fail_file; } + zcore_reipl_file = debugfs_create_file("reipl", S_IRUSR, zcore_dir, + NULL, &zcore_reipl_fops); + if (!zcore_reipl_file) { + rc = -ENOMEM; + goto fail_memmap_file; + } hsa_available = 1; return 0; +fail_memmap_file: + debugfs_remove(zcore_memmap_file); fail_file: debugfs_remove(zcore_file); fail_dir: @@ -723,10 +802,15 @@ static void __exit zcore_exit(void) { debug_unregister(zcore_dbf); sclp_sdias_exit(); + free_page((unsigned long) ipl_block); + debugfs_remove(zcore_reipl_file); + debugfs_remove(zcore_memmap_file); + debugfs_remove(zcore_file); + debugfs_remove(zcore_dir); diag308(DIAG308_REL_HSA, NULL); } -MODULE_AUTHOR("Copyright IBM Corp. 2003,2007"); +MODULE_AUTHOR("Copyright IBM Corp. 2003,2008"); MODULE_DESCRIPTION("zcore module for zfcpdump support"); MODULE_LICENSE("GPL"); -- GitLab From 59fa4392dddae244a1148cbbcb090b5a5728f576 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 26 Mar 2009 15:23:44 +0100 Subject: [PATCH 4611/4982] [S390] page fault: invoke oom-killer s390 arch backend for 1c0fe6e3bda0464728c23c8d84aa47567e8b716c "mm: invoke oom-killer from page fault". Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/mm/fault.c | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 4d537205e83..833e8366c35 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -200,29 +200,6 @@ static void do_low_address(struct pt_regs *regs, unsigned long error_code) do_no_context(regs, error_code, 0); } -/* - * We ran out of memory, or some other thing happened to us that made - * us unable to handle the page fault gracefully. - */ -static int do_out_of_memory(struct pt_regs *regs, unsigned long error_code, - unsigned long address) -{ - struct task_struct *tsk = current; - struct mm_struct *mm = tsk->mm; - - up_read(&mm->mmap_sem); - if (is_global_init(tsk)) { - yield(); - down_read(&mm->mmap_sem); - return 1; - } - printk("VM: killing process %s\n", tsk->comm); - if (regs->psw.mask & PSW_MASK_PSTATE) - do_group_exit(SIGKILL); - do_no_context(regs, error_code, address); - return 0; -} - static void do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address) { @@ -367,7 +344,6 @@ good_area: goto bad_area; } -survive: if (is_vm_hugetlb_page(vma)) address &= HPAGE_MASK; /* @@ -378,8 +354,8 @@ survive: fault = handle_mm_fault(mm, vma, address, write); if (unlikely(fault & VM_FAULT_ERROR)) { if (fault & VM_FAULT_OOM) { - if (do_out_of_memory(regs, error_code, address)) - goto survive; + up_read(&mm->mmap_sem); + pagefault_out_of_memory(); return; } else if (fault & VM_FAULT_SIGBUS) { do_sigbus(regs, error_code, address); -- GitLab From 0000d031703c33b9ea909ad81f03762db66135e1 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 26 Mar 2009 15:23:45 +0100 Subject: [PATCH 4612/4982] [S390] dasd: enable compat ioctls All of the ioctls are compatible. Just enable them. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd.c | 3 ++- drivers/s390/block/dasd_ioctl.c | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 08c23a92101..93972ed7f2d 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -2101,7 +2101,8 @@ dasd_device_operations = { .owner = THIS_MODULE, .open = dasd_open, .release = dasd_release, - .locked_ioctl = dasd_ioctl, + .ioctl = dasd_ioctl, + .compat_ioctl = dasd_ioctl, .getgeo = dasd_getgeo, }; diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index b82d816d9ef..16e6ba462cb 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -365,9 +365,9 @@ static int dasd_ioctl_readall_cmb(struct dasd_block *block, unsigned int cmd, return ret; } -int -dasd_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) +static int +dasd_do_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) { struct dasd_block *block = bdev->bd_disk->private_data; void __user *argp = (void __user *)arg; @@ -420,3 +420,14 @@ dasd_ioctl(struct block_device *bdev, fmode_t mode, return -EINVAL; } } + +int dasd_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) +{ + int rc; + + lock_kernel(); + rc = dasd_do_ioctl(bdev, mode, cmd, arg); + unlock_kernel(); + return rc; +} -- GitLab From f9a28f7bc5225af476f8d4bb669038da8801b7c4 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Joret Date: Thu, 26 Mar 2009 15:23:46 +0100 Subject: [PATCH 4613/4982] [S390] dasd_eckd / Write format R0 is now allowed BB Permission is now granted to the subsystem to format write R0 with: * an ID = CCHHR, where CC = physical cylinder number, HH = physical head number, and R = 0 * a key length of zero * a data length of eight * a data field containing all zeros Signed-off-by: Jean-Baptiste Joret Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd_eckd.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index bdb87998f36..0eb5e5888c4 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -1265,6 +1265,8 @@ dasd_eckd_format_device(struct dasd_device * device, int rpt, cyl, head; int cplength, datasize; int i; + int intensity = 0; + int r0_perm; private = (struct dasd_eckd_private *) device->private; rpt = recs_per_track(&private->rdc_data, 0, fdata->blksize); @@ -1296,9 +1298,17 @@ dasd_eckd_format_device(struct dasd_device * device, * Bit 1: write home address, currently not supported * Bit 2: invalidate tracks * Bit 3: use OS/390 compatible disk layout (cdl) + * Bit 4: do not allow storage subsystem to modify record zero * Only some bit combinations do make sense. */ - switch (fdata->intensity) { + if (fdata->intensity & 0x10) { + r0_perm = 0; + intensity = fdata->intensity & ~0x10; + } else { + r0_perm = 1; + intensity = fdata->intensity; + } + switch (intensity) { case 0x00: /* Normal format */ case 0x08: /* Normal format, use cdl. */ cplength = 2 + rpt; @@ -1335,11 +1345,14 @@ dasd_eckd_format_device(struct dasd_device * device, data = fcp->data; ccw = fcp->cpaddr; - switch (fdata->intensity & ~0x08) { + switch (intensity & ~0x08) { case 0x00: /* Normal format. */ define_extent(ccw++, (struct DE_eckd_data *) data, fdata->start_unit, fdata->start_unit, DASD_ECKD_CCW_WRITE_CKD, device); + /* grant subsystem permission to format R0 */ + if (r0_perm) + ((struct DE_eckd_data *)data)->ga_extended |= 0x04; data += sizeof(struct DE_eckd_data); ccw[-1].flags |= CCW_FLAG_CC; locate_record(ccw++, (struct LO_eckd_data *) data, @@ -1373,7 +1386,7 @@ dasd_eckd_format_device(struct dasd_device * device, data += sizeof(struct LO_eckd_data); break; } - if (fdata->intensity & 0x01) { /* write record zero */ + if (intensity & 0x01) { /* write record zero */ ect = (struct eckd_count *) data; data += sizeof(struct eckd_count); ect->cyl = cyl; @@ -1388,7 +1401,7 @@ dasd_eckd_format_device(struct dasd_device * device, ccw->cda = (__u32)(addr_t) ect; ccw++; } - if ((fdata->intensity & ~0x08) & 0x04) { /* erase track */ + if ((intensity & ~0x08) & 0x04) { /* erase track */ ect = (struct eckd_count *) data; data += sizeof(struct eckd_count); ect->cyl = cyl; @@ -1411,14 +1424,14 @@ dasd_eckd_format_device(struct dasd_device * device, ect->kl = 0; ect->dl = fdata->blksize; /* Check for special tracks 0-1 when formatting CDL */ - if ((fdata->intensity & 0x08) && + if ((intensity & 0x08) && fdata->start_unit == 0) { if (i < 3) { ect->kl = 4; ect->dl = sizes_trk0[i] - 4; } } - if ((fdata->intensity & 0x08) && + if ((intensity & 0x08) && fdata->start_unit == 1) { ect->kl = 44; ect->dl = LABEL_SIZE - 44; -- GitLab From b44b0ab3bac16356f03e94b1b49ba9305710c445 Mon Sep 17 00:00:00 2001 From: Stefan Weinhuber Date: Thu, 26 Mar 2009 15:23:47 +0100 Subject: [PATCH 4614/4982] [S390] dasd: add large volume support The dasd device driver will now support ECKD devices with more then 65520 cylinders. In the traditional ECKD adressing scheme each track is addressed by a 16-bit cylinder and 16-bit head number. The new addressing scheme makes use of the fact that the actual number of heads is never larger then 15, so 12 bits of the head number can be redefined to be part of the cylinder address. Signed-off-by: Stefan Weinhuber Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/dasd.h | 10 +-- arch/s390/include/asm/vtoc.h | 16 +++- drivers/s390/block/dasd_eckd.c | 126 +++++++++++++++++--------------- drivers/s390/block/dasd_eckd.h | 9 ++- drivers/s390/block/dasd_int.h | 2 +- drivers/s390/block/dasd_ioctl.c | 4 +- drivers/s390/block/dasd_proc.c | 2 +- fs/partitions/ibm.c | 101 +++++++++++++++++-------- 8 files changed, 171 insertions(+), 99 deletions(-) diff --git a/arch/s390/include/asm/dasd.h b/arch/s390/include/asm/dasd.h index e2db6f16d9c..218bce81ec7 100644 --- a/arch/s390/include/asm/dasd.h +++ b/arch/s390/include/asm/dasd.h @@ -162,15 +162,15 @@ typedef struct dasd_profile_info_t { unsigned int dasd_io_nr_req[32]; /* histogram of # of requests in chanq */ } dasd_profile_info_t; -/* +/* * struct format_data_t * represents all data necessary to format a dasd */ typedef struct format_data_t { - int start_unit; /* from track */ - int stop_unit; /* to track */ - int blksize; /* sectorsize */ - int intensity; + unsigned int start_unit; /* from track */ + unsigned int stop_unit; /* to track */ + unsigned int blksize; /* sectorsize */ + unsigned int intensity; } format_data_t; /* diff --git a/arch/s390/include/asm/vtoc.h b/arch/s390/include/asm/vtoc.h index 3a5267d90d2..8406a2b3157 100644 --- a/arch/s390/include/asm/vtoc.h +++ b/arch/s390/include/asm/vtoc.h @@ -39,7 +39,7 @@ struct vtoc_labeldate __u16 day; } __attribute__ ((packed)); -struct vtoc_volume_label +struct vtoc_volume_label_cdl { char volkey[4]; /* volume key = volume label */ char vollbl[4]; /* volume label */ @@ -56,6 +56,14 @@ struct vtoc_volume_label char res3[29]; /* reserved */ } __attribute__ ((packed)); +struct vtoc_volume_label_ldl { + char vollbl[4]; /* volume label */ + char volid[6]; /* volume identifier */ + char res3[69]; /* reserved */ + char ldl_version; /* version number, valid for ldl format */ + __u64 formatted_blocks; /* valid when ldl_version >= f2 */ +} __attribute__ ((packed)); + struct vtoc_extent { __u8 typeind; /* extent type indicator */ @@ -140,7 +148,11 @@ struct vtoc_format4_label char res2[10]; /* reserved */ __u8 DS4EFLVL; /* extended free-space management level */ struct vtoc_cchhb DS4EFPTR; /* pointer to extended free-space info */ - char res3[9]; /* reserved */ + char res3; /* reserved */ + __u32 DS4DCYL; /* number of logical cyls */ + char res4[2]; /* reserved */ + __u8 DS4DEVF2; /* device flags */ + char res5; /* reserved */ } __attribute__ ((packed)); struct vtoc_ds5ext diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 0eb5e5888c4..69f93e626fd 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -159,6 +159,14 @@ recs_per_track(struct dasd_eckd_characteristics * rdc, return 0; } +static void set_ch_t(struct ch_t *geo, __u32 cyl, __u8 head) +{ + geo->cyl = (__u16) cyl; + geo->head = cyl >> 16; + geo->head <<= 4; + geo->head |= head; +} + static int check_XRC (struct ccw1 *de_ccw, struct DE_eckd_data *data, @@ -186,11 +194,12 @@ check_XRC (struct ccw1 *de_ccw, } static int -define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk, - int totrk, int cmd, struct dasd_device * device) +define_extent(struct ccw1 *ccw, struct DE_eckd_data *data, unsigned int trk, + unsigned int totrk, int cmd, struct dasd_device *device) { struct dasd_eckd_private *private; - struct ch_t geo, beg, end; + u32 begcyl, endcyl; + u16 heads, beghead, endhead; int rc = 0; private = (struct dasd_eckd_private *) device->private; @@ -248,27 +257,24 @@ define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk, && !(private->uses_cdl && trk < 2)) data->ga_extended |= 0x40; /* Regular Data Format Mode */ - geo.cyl = private->rdc_data.no_cyl; - geo.head = private->rdc_data.trk_per_cyl; - beg.cyl = trk / geo.head; - beg.head = trk % geo.head; - end.cyl = totrk / geo.head; - end.head = totrk % geo.head; + heads = private->rdc_data.trk_per_cyl; + begcyl = trk / heads; + beghead = trk % heads; + endcyl = totrk / heads; + endhead = totrk % heads; /* check for sequential prestage - enhance cylinder range */ if (data->attributes.operation == DASD_SEQ_PRESTAGE || data->attributes.operation == DASD_SEQ_ACCESS) { - if (end.cyl + private->attrib.nr_cyl < geo.cyl) - end.cyl += private->attrib.nr_cyl; + if (endcyl + private->attrib.nr_cyl < private->real_cyl) + endcyl += private->attrib.nr_cyl; else - end.cyl = (geo.cyl - 1); + endcyl = (private->real_cyl - 1); } - data->beg_ext.cyl = beg.cyl; - data->beg_ext.head = beg.head; - data->end_ext.cyl = end.cyl; - data->end_ext.head = end.head; + set_ch_t(&data->beg_ext, begcyl, beghead); + set_ch_t(&data->end_ext, endcyl, endhead); return rc; } @@ -294,13 +300,14 @@ static int check_XRC_on_prefix(struct PFX_eckd_data *pfxdata, return rc; } -static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, int trk, - int totrk, int cmd, struct dasd_device *basedev, - struct dasd_device *startdev) +static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, + unsigned int trk, unsigned int totrk, int cmd, + struct dasd_device *basedev, struct dasd_device *startdev) { struct dasd_eckd_private *basepriv, *startpriv; struct DE_eckd_data *data; - struct ch_t geo, beg, end; + u32 begcyl, endcyl; + u16 heads, beghead, endhead; int rc = 0; basepriv = (struct dasd_eckd_private *) basedev->private; @@ -374,33 +381,30 @@ static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, int trk, && !(basepriv->uses_cdl && trk < 2)) data->ga_extended |= 0x40; /* Regular Data Format Mode */ - geo.cyl = basepriv->rdc_data.no_cyl; - geo.head = basepriv->rdc_data.trk_per_cyl; - beg.cyl = trk / geo.head; - beg.head = trk % geo.head; - end.cyl = totrk / geo.head; - end.head = totrk % geo.head; + heads = basepriv->rdc_data.trk_per_cyl; + begcyl = trk / heads; + beghead = trk % heads; + endcyl = totrk / heads; + endhead = totrk % heads; /* check for sequential prestage - enhance cylinder range */ if (data->attributes.operation == DASD_SEQ_PRESTAGE || data->attributes.operation == DASD_SEQ_ACCESS) { - if (end.cyl + basepriv->attrib.nr_cyl < geo.cyl) - end.cyl += basepriv->attrib.nr_cyl; + if (endcyl + basepriv->attrib.nr_cyl < basepriv->real_cyl) + endcyl += basepriv->attrib.nr_cyl; else - end.cyl = (geo.cyl - 1); + endcyl = (basepriv->real_cyl - 1); } - data->beg_ext.cyl = beg.cyl; - data->beg_ext.head = beg.head; - data->end_ext.cyl = end.cyl; - data->end_ext.head = end.head; + set_ch_t(&data->beg_ext, begcyl, beghead); + set_ch_t(&data->end_ext, endcyl, endhead); return rc; } static void -locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, int trk, - int rec_on_trk, int no_rec, int cmd, +locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, unsigned int trk, + unsigned int rec_on_trk, int no_rec, int cmd, struct dasd_device * device, int reclen) { struct dasd_eckd_private *private; @@ -493,10 +497,11 @@ locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, int trk, default: DEV_MESSAGE(KERN_ERR, device, "unknown opcode 0x%x", cmd); } - data->seek_addr.cyl = data->search_arg.cyl = - trk / private->rdc_data.trk_per_cyl; - data->seek_addr.head = data->search_arg.head = - trk % private->rdc_data.trk_per_cyl; + set_ch_t(&data->seek_addr, + trk / private->rdc_data.trk_per_cyl, + trk % private->rdc_data.trk_per_cyl); + data->search_arg.cyl = data->seek_addr.cyl; + data->search_arg.head = data->seek_addr.head; data->search_arg.record = rec_on_trk; } @@ -1002,13 +1007,20 @@ dasd_eckd_check_characteristics(struct dasd_device *device) "rc=%d", rc); goto out_err3; } + /* find the vaild cylinder size */ + if (private->rdc_data.no_cyl == LV_COMPAT_CYL && + private->rdc_data.long_no_cyl) + private->real_cyl = private->rdc_data.long_no_cyl; + else + private->real_cyl = private->rdc_data.no_cyl; + DEV_MESSAGE(KERN_INFO, device, "%04X/%02X(CU:%04X/%02X) Cyl:%d Head:%d Sec:%d", private->rdc_data.dev_type, private->rdc_data.dev_model, private->rdc_data.cu_type, private->rdc_data.cu_model.model, - private->rdc_data.no_cyl, + private->real_cyl, private->rdc_data.trk_per_cyl, private->rdc_data.sec_per_trk); return 0; @@ -1157,8 +1169,6 @@ dasd_eckd_end_analysis(struct dasd_block *block) } private->uses_cdl = 1; - /* Calculate number of blocks/records per track. */ - blk_per_trk = recs_per_track(&private->rdc_data, 0, block->bp_block); /* Check Track 0 for Compatible Disk Layout */ count_area = NULL; for (i = 0; i < 3; i++) { @@ -1200,14 +1210,14 @@ dasd_eckd_end_analysis(struct dasd_block *block) block->s2b_shift++; blk_per_trk = recs_per_track(&private->rdc_data, 0, block->bp_block); - block->blocks = (private->rdc_data.no_cyl * + block->blocks = (private->real_cyl * private->rdc_data.trk_per_cyl * blk_per_trk); DEV_MESSAGE(KERN_INFO, device, "(%dkB blks): %dkB at %dkB/trk %s", (block->bp_block >> 10), - ((private->rdc_data.no_cyl * + ((private->real_cyl * private->rdc_data.trk_per_cyl * blk_per_trk * (block->bp_block >> 9)) >> 1), ((blk_per_trk * block->bp_block) >> 10), @@ -1262,7 +1272,8 @@ dasd_eckd_format_device(struct dasd_device * device, struct eckd_count *ect; struct ccw1 *ccw; void *data; - int rpt, cyl, head; + int rpt; + struct ch_t address; int cplength, datasize; int i; int intensity = 0; @@ -1270,24 +1281,25 @@ dasd_eckd_format_device(struct dasd_device * device, private = (struct dasd_eckd_private *) device->private; rpt = recs_per_track(&private->rdc_data, 0, fdata->blksize); - cyl = fdata->start_unit / private->rdc_data.trk_per_cyl; - head = fdata->start_unit % private->rdc_data.trk_per_cyl; + set_ch_t(&address, + fdata->start_unit / private->rdc_data.trk_per_cyl, + fdata->start_unit % private->rdc_data.trk_per_cyl); /* Sanity checks. */ if (fdata->start_unit >= - (private->rdc_data.no_cyl * private->rdc_data.trk_per_cyl)) { - DEV_MESSAGE(KERN_INFO, device, "Track no %d too big!", + (private->real_cyl * private->rdc_data.trk_per_cyl)) { + DEV_MESSAGE(KERN_INFO, device, "Track no %u too big!", fdata->start_unit); return ERR_PTR(-EINVAL); } if (fdata->start_unit > fdata->stop_unit) { - DEV_MESSAGE(KERN_INFO, device, "Track %d reached! ending.", + DEV_MESSAGE(KERN_INFO, device, "Track %u reached! ending.", fdata->start_unit); return ERR_PTR(-EINVAL); } if (dasd_check_blocksize(fdata->blksize) != 0) { DEV_MESSAGE(KERN_WARNING, device, - "Invalid blocksize %d...terminating!", + "Invalid blocksize %u...terminating!", fdata->blksize); return ERR_PTR(-EINVAL); } @@ -1389,8 +1401,8 @@ dasd_eckd_format_device(struct dasd_device * device, if (intensity & 0x01) { /* write record zero */ ect = (struct eckd_count *) data; data += sizeof(struct eckd_count); - ect->cyl = cyl; - ect->head = head; + ect->cyl = address.cyl; + ect->head = address.head; ect->record = 0; ect->kl = 0; ect->dl = 8; @@ -1404,8 +1416,8 @@ dasd_eckd_format_device(struct dasd_device * device, if ((intensity & ~0x08) & 0x04) { /* erase track */ ect = (struct eckd_count *) data; data += sizeof(struct eckd_count); - ect->cyl = cyl; - ect->head = head; + ect->cyl = address.cyl; + ect->head = address.head; ect->record = 1; ect->kl = 0; ect->dl = 0; @@ -1418,8 +1430,8 @@ dasd_eckd_format_device(struct dasd_device * device, for (i = 0; i < rpt; i++) { ect = (struct eckd_count *) data; data += sizeof(struct eckd_count); - ect->cyl = cyl; - ect->head = head; + ect->cyl = address.cyl; + ect->head = address.head; ect->record = i + 1; ect->kl = 0; ect->dl = fdata->blksize; diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index 2476f87d21d..eecfa776db1 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h @@ -48,6 +48,11 @@ #define PSF_ORDER_PRSSD 0x18 #define PSF_ORDER_SSC 0x1D +/* + * Size that is reportet for large volumes in the old 16-bit no_cyl field + */ +#define LV_COMPAT_CYL 0xFFFE + /***************************************************************************** * SECTION: Type Definitions ****************************************************************************/ @@ -228,7 +233,8 @@ struct dasd_eckd_characteristics { __u8 factor7; __u8 factor8; __u8 reserved2[3]; - __u8 reserved3[10]; + __u8 reserved3[6]; + __u32 long_no_cyl; } __attribute__ ((packed)); /* elements of the configuration data */ @@ -406,6 +412,7 @@ struct dasd_eckd_private { int uses_cdl; struct attrib_data_t attrib; /* e.g. cache operations */ struct dasd_rssd_features features; + u32 real_cyl; /* alias managemnet */ struct dasd_uid uid; diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 4a39084d9c9..29991a9fa07 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -378,7 +378,7 @@ struct dasd_block { struct block_device *bdev; atomic_t open_count; - unsigned long blocks; /* size of volume in blocks */ + unsigned long long blocks; /* size of volume in blocks */ unsigned int bp_block; /* bytes per block */ unsigned int s2b_shift; /* log2 (bp_block/512) */ diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index 16e6ba462cb..a3bbdb807ba 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -146,7 +146,7 @@ static int dasd_format(struct dasd_block *block, struct format_data_t *fdata) } DBF_DEV_EVENT(DBF_NOTICE, base, - "formatting units %d to %d (%d B blocks) flags %d", + "formatting units %u to %u (%u B blocks) flags %u", fdata->start_unit, fdata->stop_unit, fdata->blksize, fdata->intensity); @@ -170,7 +170,7 @@ static int dasd_format(struct dasd_block *block, struct format_data_t *fdata) if (rc) { if (rc != -ERESTARTSYS) DEV_MESSAGE(KERN_ERR, base, - " Formatting of unit %d failed " + " Formatting of unit %u failed " "with rc = %d", fdata->start_unit, rc); return rc; diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index bf6fd348f20..0aa569419d5 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c @@ -112,7 +112,7 @@ dasd_devices_show(struct seq_file *m, void *v) seq_printf(m, "n/f "); else seq_printf(m, - "at blocksize: %d, %ld blocks, %ld MB", + "at blocksize: %d, %lld blocks, %lld MB", block->bp_block, block->blocks, ((block->bp_block >> 9) * block->blocks) >> 11); diff --git a/fs/partitions/ibm.c b/fs/partitions/ibm.c index 1e064c4a4f8..46297683cd3 100644 --- a/fs/partitions/ibm.c +++ b/fs/partitions/ibm.c @@ -21,20 +21,38 @@ * compute the block number from a * cyl-cyl-head-head structure */ -static inline int +static sector_t cchh2blk (struct vtoc_cchh *ptr, struct hd_geometry *geo) { - return ptr->cc * geo->heads * geo->sectors + - ptr->hh * geo->sectors; + + sector_t cyl; + __u16 head; + + /*decode cylinder and heads for large volumes */ + cyl = ptr->hh & 0xFFF0; + cyl <<= 12; + cyl |= ptr->cc; + head = ptr->hh & 0x000F; + return cyl * geo->heads * geo->sectors + + head * geo->sectors; } /* * compute the block number from a * cyl-cyl-head-head-block structure */ -static inline int +static sector_t cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) { - return ptr->cc * geo->heads * geo->sectors + - ptr->hh * geo->sectors + + + sector_t cyl; + __u16 head; + + /*decode cylinder and heads for large volumes */ + cyl = ptr->hh & 0xFFF0; + cyl <<= 12; + cyl |= ptr->cc; + head = ptr->hh & 0x000F; + return cyl * geo->heads * geo->sectors + + head * geo->sectors + ptr->b; } @@ -43,14 +61,15 @@ cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) { int ibm_partition(struct parsed_partitions *state, struct block_device *bdev) { - int blocksize, offset, size,res; - loff_t i_size; + int blocksize, res; + loff_t i_size, offset, size, fmt_size; dasd_information2_t *info; struct hd_geometry *geo; char type[5] = {0,}; char name[7] = {0,}; union label_t { - struct vtoc_volume_label vol; + struct vtoc_volume_label_cdl vol; + struct vtoc_volume_label_ldl lnx; struct vtoc_cms_label cms; } *label; unsigned char *data; @@ -85,14 +104,16 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) if (data == NULL) goto out_readerr; - strncpy (type, data, 4); - if ((!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) - strncpy(name, data + 8, 6); - else - strncpy(name, data + 4, 6); memcpy(label, data, sizeof(union label_t)); put_dev_sector(sect); + if ((!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) { + strncpy(type, label->vol.vollbl, 4); + strncpy(name, label->vol.volid, 6); + } else { + strncpy(type, label->lnx.vollbl, 4); + strncpy(name, label->lnx.volid, 6); + } EBCASC(type, 4); EBCASC(name, 6); @@ -110,36 +131,54 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) /* * VM style CMS1 labeled disk */ + blocksize = label->cms.block_size; if (label->cms.disk_offset != 0) { printk("CMS1/%8s(MDSK):", name); /* disk is reserved minidisk */ - blocksize = label->cms.block_size; offset = label->cms.disk_offset; size = (label->cms.block_count - 1) * (blocksize >> 9); } else { printk("CMS1/%8s:", name); offset = (info->label_block + 1); - size = i_size >> 9; + size = label->cms.block_count + * (blocksize >> 9); } + put_partition(state, 1, offset*(blocksize >> 9), + size-offset*(blocksize >> 9)); } else { - /* - * Old style LNX1 or unlabeled disk - */ - if (strncmp(type, "LNX1", 4) == 0) - printk ("LNX1/%8s:", name); - else + if (strncmp(type, "LNX1", 4) == 0) { + printk("LNX1/%8s:", name); + if (label->lnx.ldl_version == 0xf2) { + fmt_size = label->lnx.formatted_blocks + * (blocksize >> 9); + } else if (!strcmp(info->type, "ECKD")) { + /* formated w/o large volume support */ + fmt_size = geo->cylinders * geo->heads + * geo->sectors * (blocksize >> 9); + } else { + /* old label and no usable disk geometry + * (e.g. DIAG) */ + fmt_size = i_size >> 9; + } + size = i_size >> 9; + if (fmt_size < size) + size = fmt_size; + offset = (info->label_block + 1); + } else { + /* unlabeled disk */ printk("(nonl)"); - offset = (info->label_block + 1); - size = i_size >> 9; - } - put_partition(state, 1, offset*(blocksize >> 9), + size = i_size >> 9; + offset = (info->label_block + 1); + } + put_partition(state, 1, offset*(blocksize >> 9), size-offset*(blocksize >> 9)); + } } else if (info->format == DASD_FORMAT_CDL) { /* * New style CDL formatted disk */ - unsigned int blk; + sector_t blk; int counter; /* @@ -166,7 +205,8 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) /* skip FMT4 / FMT5 / FMT7 labels */ if (f1.DS1FMTID == _ascebc['4'] || f1.DS1FMTID == _ascebc['5'] - || f1.DS1FMTID == _ascebc['7']) { + || f1.DS1FMTID == _ascebc['7'] + || f1.DS1FMTID == _ascebc['9']) { blk++; data = read_dev_sector(bdev, blk * (blocksize/512), @@ -174,8 +214,9 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) continue; } - /* only FMT1 valid at this point */ - if (f1.DS1FMTID != _ascebc['1']) + /* only FMT1 and 8 labels valid at this point */ + if (f1.DS1FMTID != _ascebc['1'] && + f1.DS1FMTID != _ascebc['8']) break; /* OK, we got valid partition data */ -- GitLab From f3eb5384cf0325c02e306b1d81e70f81a03d7432 Mon Sep 17 00:00:00 2001 From: Stefan Weinhuber Date: Thu, 26 Mar 2009 15:23:48 +0100 Subject: [PATCH 4615/4982] [S390] dasd: add High Performance FICON support To support High Performance FICON, the DASD device driver has to translate I/O requests into the new transport mode control words (TCW) instead of the traditional (command mode) CCW requests. Signed-off-by: Stefan Weinhuber Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/idals.h | 17 +- drivers/s390/block/dasd.c | 70 ++- drivers/s390/block/dasd_3990_erp.c | 141 +++-- drivers/s390/block/dasd_alias.c | 25 +- drivers/s390/block/dasd_devmap.c | 7 + drivers/s390/block/dasd_eckd.c | 972 ++++++++++++++++++++++++++--- drivers/s390/block/dasd_eckd.h | 40 +- drivers/s390/block/dasd_eer.c | 21 +- drivers/s390/block/dasd_int.h | 5 +- 9 files changed, 1123 insertions(+), 175 deletions(-) diff --git a/arch/s390/include/asm/idals.h b/arch/s390/include/asm/idals.h index e82c10efe65..aae276d0038 100644 --- a/arch/s390/include/asm/idals.h +++ b/arch/s390/include/asm/idals.h @@ -44,24 +44,18 @@ idal_is_needed(void *vaddr, unsigned int length) /* * Return the number of idal words needed for an address/length pair. */ -static inline unsigned int -idal_nr_words(void *vaddr, unsigned int length) +static inline unsigned int idal_nr_words(void *vaddr, unsigned int length) { -#ifdef __s390x__ - if (idal_is_needed(vaddr, length)) - return ((__pa(vaddr) & (IDA_BLOCK_SIZE-1)) + length + - (IDA_BLOCK_SIZE-1)) >> IDA_SIZE_LOG; -#endif - return 0; + return ((__pa(vaddr) & (IDA_BLOCK_SIZE-1)) + length + + (IDA_BLOCK_SIZE-1)) >> IDA_SIZE_LOG; } /* * Create the list of idal words for an address/length pair. */ -static inline unsigned long * -idal_create_words(unsigned long *idaws, void *vaddr, unsigned int length) +static inline unsigned long *idal_create_words(unsigned long *idaws, + void *vaddr, unsigned int length) { -#ifdef __s390x__ unsigned long paddr; unsigned int cidaw; @@ -74,7 +68,6 @@ idal_create_words(unsigned long *idaws, void *vaddr, unsigned int length) paddr += IDA_BLOCK_SIZE; *idaws++ = paddr; } -#endif return idaws; } diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 93972ed7f2d..00f7d24b337 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -22,6 +22,7 @@ #include #include #include +#include /* This is ugly... */ #define PRINTK_HEADER "dasd:" @@ -852,8 +853,13 @@ int dasd_start_IO(struct dasd_ccw_req *cqr) cqr->startclk = get_clock(); cqr->starttime = jiffies; cqr->retries--; - rc = ccw_device_start(device->cdev, cqr->cpaddr, (long) cqr, - cqr->lpm, 0); + if (cqr->cpmode == 1) { + rc = ccw_device_tm_start(device->cdev, cqr->cpaddr, + (long) cqr, cqr->lpm); + } else { + rc = ccw_device_start(device->cdev, cqr->cpaddr, + (long) cqr, cqr->lpm, 0); + } switch (rc) { case 0: cqr->status = DASD_CQR_IN_IO; @@ -881,9 +887,12 @@ int dasd_start_IO(struct dasd_ccw_req *cqr) " retry on all pathes"); break; case -ENODEV: + DBF_DEV_EVENT(DBF_DEBUG, device, "%s", + "start_IO: -ENODEV device gone, retry"); + break; case -EIO: DBF_DEV_EVENT(DBF_ERR, device, "%s", - "start_IO: device gone, retry"); + "start_IO: -EIO device gone, retry"); break; default: DEV_MESSAGE(KERN_ERR, device, @@ -1015,9 +1024,9 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, /* check for unsolicited interrupts */ cqr = (struct dasd_ccw_req *) intparm; - if (!cqr || ((irb->scsw.cmd.cc == 1) && - (irb->scsw.cmd.fctl & SCSW_FCTL_START_FUNC) && - (irb->scsw.cmd.stctl & SCSW_STCTL_STATUS_PEND))) { + if (!cqr || ((scsw_cc(&irb->scsw) == 1) && + (scsw_fctl(&irb->scsw) & SCSW_FCTL_START_FUNC) && + (scsw_stctl(&irb->scsw) & SCSW_STCTL_STATUS_PEND))) { if (cqr && cqr->status == DASD_CQR_IN_IO) cqr->status = DASD_CQR_QUEUED; device = dasd_device_from_cdev_locked(cdev); @@ -1040,7 +1049,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, /* Check for clear pending */ if (cqr->status == DASD_CQR_CLEAR_PENDING && - irb->scsw.cmd.fctl & SCSW_FCTL_CLEAR_FUNC) { + scsw_fctl(&irb->scsw) & SCSW_FCTL_CLEAR_FUNC) { cqr->status = DASD_CQR_CLEARED; dasd_device_clear_timer(device); wake_up(&dasd_flush_wq); @@ -1048,7 +1057,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, return; } - /* check status - the request might have been killed by dyn detach */ + /* check status - the request might have been killed by dyn detach */ if (cqr->status != DASD_CQR_IN_IO) { MESSAGE(KERN_DEBUG, "invalid status: bus_id %s, status %02x", @@ -1059,8 +1068,8 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, ((irb->scsw.cmd.cstat << 8) | irb->scsw.cmd.dstat), cqr); next = NULL; expires = 0; - if (irb->scsw.cmd.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END) && - irb->scsw.cmd.cstat == 0 && !irb->esw.esw0.erw.cons) { + if (scsw_dstat(&irb->scsw) == (DEV_STAT_CHN_END | DEV_STAT_DEV_END) && + scsw_cstat(&irb->scsw) == 0) { /* request was completed successfully */ cqr->status = DASD_CQR_SUCCESS; cqr->stopclk = now; @@ -1991,8 +2000,11 @@ static void dasd_setup_queue(struct dasd_block *block) blk_queue_max_sectors(block->request_queue, max); blk_queue_max_phys_segments(block->request_queue, -1L); blk_queue_max_hw_segments(block->request_queue, -1L); - blk_queue_max_segment_size(block->request_queue, -1L); - blk_queue_segment_boundary(block->request_queue, -1L); + /* with page sized segments we can translate each segement into + * one idaw/tidaw + */ + blk_queue_max_segment_size(block->request_queue, PAGE_SIZE); + blk_queue_segment_boundary(block->request_queue, PAGE_SIZE - 1); blk_queue_ordered(block->request_queue, QUEUE_ORDERED_DRAIN, NULL); } @@ -2432,6 +2444,40 @@ int dasd_generic_read_dev_chars(struct dasd_device *device, char *magic, } EXPORT_SYMBOL_GPL(dasd_generic_read_dev_chars); +/* + * In command mode and transport mode we need to look for sense + * data in different places. The sense data itself is allways + * an array of 32 bytes, so we can unify the sense data access + * for both modes. + */ +char *dasd_get_sense(struct irb *irb) +{ + struct tsb *tsb = NULL; + char *sense = NULL; + + if (scsw_is_tm(&irb->scsw) && (irb->scsw.tm.fcxs == 0x01)) { + if (irb->scsw.tm.tcw) + tsb = tcw_get_tsb((struct tcw *)(unsigned long) + irb->scsw.tm.tcw); + if (tsb && tsb->length == 64 && tsb->flags) + switch (tsb->flags & 0x07) { + case 1: /* tsa_iostat */ + sense = tsb->tsa.iostat.sense; + break; + case 2: /* tsa_ddpc */ + sense = tsb->tsa.ddpc.sense; + break; + default: + /* currently we don't use interrogate data */ + break; + } + } else if (irb->esw.esw0.erw.cons) { + sense = irb->ecw; + } + return sense; +} +EXPORT_SYMBOL_GPL(dasd_get_sense); + static int __init dasd_init(void) { int rc; diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index d82aad5224f..4cee4591614 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c @@ -1561,6 +1561,13 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) cqr = cqr->refers; } + if (scsw_is_tm(&cqr->irb.scsw)) { + DBF_DEV_EVENT(DBF_WARNING, device, "%s", + "32 bit sense, action 1B is not defined" + " in transport mode - just retry"); + return default_erp; + } + /* for imprecise ending just do default erp */ if (sense[1] & 0x01) { @@ -1599,7 +1606,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) oldccw = cqr->cpaddr; if (oldccw->cmd_code == DASD_ECKD_CCW_PFX) { PFX_data = cqr->data; - memcpy(DE_data, &PFX_data->define_extend, + memcpy(DE_data, &PFX_data->define_extent, sizeof(struct DE_eckd_data)); } else memcpy(DE_data, cqr->data, sizeof(struct DE_eckd_data)); @@ -1712,6 +1719,13 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense) cqr = cqr->refers; } + if (scsw_is_tm(&cqr->irb.scsw)) { + DBF_DEV_EVENT(DBF_WARNING, device, "%s", + "32 bit sense, action 1B, update," + " in transport mode - just retry"); + return previous_erp; + } + /* for imprecise ending just do default erp */ if (sense[1] & 0x01) { @@ -2171,7 +2185,7 @@ dasd_3990_erp_control_check(struct dasd_ccw_req *erp) { struct dasd_device *device = erp->startdev; - if (erp->refers->irb.scsw.cmd.cstat & (SCHN_STAT_INTF_CTRL_CHK + if (scsw_cstat(&erp->refers->irb.scsw) & (SCHN_STAT_INTF_CTRL_CHK | SCHN_STAT_CHN_CTRL_CHK)) { DEV_MESSAGE(KERN_DEBUG, device, "%s", "channel or interface control check"); @@ -2193,21 +2207,23 @@ dasd_3990_erp_control_check(struct dasd_ccw_req *erp) * erp_new contens was possibly modified */ static struct dasd_ccw_req * -dasd_3990_erp_inspect(struct dasd_ccw_req * erp) +dasd_3990_erp_inspect(struct dasd_ccw_req *erp) { struct dasd_ccw_req *erp_new = NULL; - /* sense data are located in the refers record of the */ - /* already set up new ERP ! */ - char *sense = erp->refers->irb.ecw; + char *sense; /* if this problem occured on an alias retry on base */ erp_new = dasd_3990_erp_inspect_alias(erp); if (erp_new) return erp_new; - /* check if no concurrent sens is available */ - if (!erp->refers->irb.esw.esw0.erw.cons) + /* sense data are located in the refers record of the + * already set up new ERP ! + * check if concurrent sens is available + */ + sense = dasd_get_sense(&erp->refers->irb); + if (!sense) erp_new = dasd_3990_erp_control_check(erp); /* distinguish between 24 and 32 byte sense data */ else if (sense[27] & DASD_SENSE_BIT_0) { @@ -2231,7 +2247,11 @@ dasd_3990_erp_inspect(struct dasd_ccw_req * erp) * DESCRIPTION * This funtion adds an additional request block (ERP) to the head of * the given cqr (or erp). - * This erp is initialized as an default erp (retry TIC) + * For a command mode cqr the erp is initialized as an default erp + * (retry TIC). + * For transport mode we make a copy of the original TCW (points to + * the original TCCB, TIDALs, etc.) but give it a fresh + * TSB so the original sense data will not be changed. * * PARAMETER * cqr head of the current ERP-chain (or single cqr if @@ -2239,17 +2259,27 @@ dasd_3990_erp_inspect(struct dasd_ccw_req * erp) * RETURN VALUES * erp pointer to new ERP-chain head */ -static struct dasd_ccw_req * -dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr) +static struct dasd_ccw_req *dasd_3990_erp_add_erp(struct dasd_ccw_req *cqr) { struct dasd_device *device = cqr->startdev; struct ccw1 *ccw; - - /* allocate additional request block */ struct dasd_ccw_req *erp; + int cplength, datasize; + struct tcw *tcw; + struct tsb *tsb; + + if (cqr->cpmode == 1) { + cplength = 0; + datasize = sizeof(struct tcw) + sizeof(struct tsb); + } else { + cplength = 2; + datasize = 0; + } - erp = dasd_alloc_erp_request((char *) &cqr->magic, 2, 0, device); + /* allocate additional request block */ + erp = dasd_alloc_erp_request((char *) &cqr->magic, + cplength, datasize, device); if (IS_ERR(erp)) { if (cqr->retries <= 0) { DEV_MESSAGE(KERN_ERR, device, "%s", @@ -2266,13 +2296,24 @@ dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr) return cqr; } - /* initialize request with default TIC to current ERP/CQR */ - ccw = erp->cpaddr; - ccw->cmd_code = CCW_CMD_NOOP; - ccw->flags = CCW_FLAG_CC; - ccw++; - ccw->cmd_code = CCW_CMD_TIC; - ccw->cda = (long)(cqr->cpaddr); + if (cqr->cpmode == 1) { + /* make a shallow copy of the original tcw but set new tsb */ + erp->cpmode = 1; + erp->cpaddr = erp->data; + tcw = erp->data; + tsb = (struct tsb *) &tcw[1]; + *tcw = *((struct tcw *)cqr->cpaddr); + tcw->tsb = (long)tsb; + } else { + /* initialize request with default TIC to current ERP/CQR */ + ccw = erp->cpaddr; + ccw->cmd_code = CCW_CMD_NOOP; + ccw->flags = CCW_FLAG_CC; + ccw++; + ccw->cmd_code = CCW_CMD_TIC; + ccw->cda = (long)(cqr->cpaddr); + } + erp->function = dasd_3990_erp_add_erp; erp->refers = cqr; erp->startdev = device; @@ -2282,7 +2323,6 @@ dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr) erp->expires = 0; erp->retries = 256; erp->buildclk = get_clock(); - erp->status = DASD_CQR_FILLED; return erp; @@ -2340,28 +2380,33 @@ dasd_3990_erp_additional_erp(struct dasd_ccw_req * cqr) * match 'boolean' for match found * returns 1 if match found, otherwise 0. */ -static int -dasd_3990_erp_error_match(struct dasd_ccw_req *cqr1, struct dasd_ccw_req *cqr2) +static int dasd_3990_erp_error_match(struct dasd_ccw_req *cqr1, + struct dasd_ccw_req *cqr2) { + char *sense1, *sense2; if (cqr1->startdev != cqr2->startdev) return 0; - if (cqr1->irb.esw.esw0.erw.cons != cqr2->irb.esw.esw0.erw.cons) - return 0; + sense1 = dasd_get_sense(&cqr1->irb); + sense2 = dasd_get_sense(&cqr2->irb); - if ((cqr1->irb.esw.esw0.erw.cons == 0) && - (cqr2->irb.esw.esw0.erw.cons == 0)) { - if ((cqr1->irb.scsw.cmd.cstat & (SCHN_STAT_INTF_CTRL_CHK | - SCHN_STAT_CHN_CTRL_CHK)) == - (cqr2->irb.scsw.cmd.cstat & (SCHN_STAT_INTF_CTRL_CHK | - SCHN_STAT_CHN_CTRL_CHK))) + /* one request has sense data, the other not -> no match, return 0 */ + if (!sense1 != !sense2) + return 0; + /* no sense data in both cases -> check cstat for IFCC */ + if (!sense1 && !sense2) { + if ((scsw_cstat(&cqr1->irb.scsw) & (SCHN_STAT_INTF_CTRL_CHK | + SCHN_STAT_CHN_CTRL_CHK)) == + (scsw_cstat(&cqr2->irb.scsw) & (SCHN_STAT_INTF_CTRL_CHK | + SCHN_STAT_CHN_CTRL_CHK))) return 1; /* match with ifcc*/ } /* check sense data; byte 0-2,25,27 */ - if (!((memcmp (cqr1->irb.ecw, cqr2->irb.ecw, 3) == 0) && - (cqr1->irb.ecw[27] == cqr2->irb.ecw[27]) && - (cqr1->irb.ecw[25] == cqr2->irb.ecw[25]))) { + if (!(sense1 && sense2 && + (memcmp(sense1, sense2, 3) == 0) && + (sense1[27] == sense2[27]) && + (sense1[25] == sense2[25]))) { return 0; /* sense doesn't match */ } @@ -2434,7 +2479,7 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp) { struct dasd_device *device = erp->startdev; - char *sense = erp->irb.ecw; + char *sense = dasd_get_sense(&erp->irb); /* check for 24 byte sense ERP */ if ((erp->function == dasd_3990_erp_bus_out) || @@ -2449,7 +2494,7 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp) /* prepare erp for retry on different channel path */ erp = dasd_3990_erp_action_1(erp); - if (!(sense[2] & DASD_SENSE_BIT_0)) { + if (sense && !(sense[2] & DASD_SENSE_BIT_0)) { /* issue a Diagnostic Control command with an * Inhibit Write subcommand */ @@ -2479,10 +2524,11 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp) } /* check for 32 byte sense ERP */ - } else if ((erp->function == dasd_3990_erp_compound_retry) || - (erp->function == dasd_3990_erp_compound_path) || - (erp->function == dasd_3990_erp_compound_code) || - (erp->function == dasd_3990_erp_compound_config)) { + } else if (sense && + ((erp->function == dasd_3990_erp_compound_retry) || + (erp->function == dasd_3990_erp_compound_path) || + (erp->function == dasd_3990_erp_compound_code) || + (erp->function == dasd_3990_erp_compound_config))) { erp = dasd_3990_erp_compound(erp, sense); @@ -2548,18 +2594,19 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head, if (erp->retries > 0) { - char *sense = erp->refers->irb.ecw; + char *sense = dasd_get_sense(&erp->refers->irb); /* check for special retries */ - if (erp->function == dasd_3990_erp_action_4) { + if (sense && erp->function == dasd_3990_erp_action_4) { erp = dasd_3990_erp_action_4(erp, sense); - } else if (erp->function == dasd_3990_erp_action_1B_32) { + } else if (sense && + erp->function == dasd_3990_erp_action_1B_32) { erp = dasd_3990_update_1B(erp, sense); - } else if (erp->function == dasd_3990_erp_int_req) { + } else if (sense && erp->function == dasd_3990_erp_int_req) { erp = dasd_3990_erp_int_req(erp); @@ -2622,8 +2669,8 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr) } /* double-check if current erp/cqr was successful */ - if ((cqr->irb.scsw.cmd.cstat == 0x00) && - (cqr->irb.scsw.cmd.dstat == + if ((scsw_cstat(&cqr->irb.scsw) == 0x00) && + (scsw_dstat(&cqr->irb.scsw) == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))) { DEV_MESSAGE(KERN_DEBUG, device, diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index 20676cdef4a..219bee7bd77 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c @@ -646,14 +646,16 @@ static int reset_summary_unit_check(struct alias_lcu *lcu, { struct dasd_ccw_req *cqr; int rc = 0; + struct ccw1 *ccw; cqr = lcu->rsu_cqr; strncpy((char *) &cqr->magic, "ECKD", 4); ASCEBC((char *) &cqr->magic, 4); - cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RSCK; - cqr->cpaddr->flags = 0 ; - cqr->cpaddr->count = 16; - cqr->cpaddr->cda = (__u32)(addr_t) cqr->data; + ccw = cqr->cpaddr; + ccw->cmd_code = DASD_ECKD_CCW_RSCK; + ccw->flags = 0 ; + ccw->count = 16; + ccw->cda = (__u32)(addr_t) cqr->data; ((char *)cqr->data)[0] = reason; clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); @@ -855,12 +857,21 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device, struct alias_lcu *lcu; char reason; struct dasd_eckd_private *private; + char *sense; private = (struct dasd_eckd_private *) device->private; - reason = irb->ecw[8]; - DEV_MESSAGE(KERN_WARNING, device, "%s %x", - "eckd handle summary unit check: reason", reason); + sense = dasd_get_sense(irb); + if (sense) { + reason = sense[8]; + DBF_DEV_EVENT(DBF_NOTICE, device, "%s %x", + "eckd handle summary unit check: reason", reason); + } else { + DBF_DEV_EVENT(DBF_WARNING, device, "%s", + "eckd handle summary unit check:" + " no reason code available"); + return; + } lcu = private->lcu; if (!lcu) { diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 34339902efb..da231a787ce 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -67,6 +67,8 @@ int dasd_probeonly = 0; /* is true, when probeonly mode is active */ int dasd_autodetect = 0; /* is true, when autodetection is active */ int dasd_nopav = 0; /* is true, when PAV is disabled */ EXPORT_SYMBOL_GPL(dasd_nopav); +int dasd_nofcx; /* disable High Performance Ficon */ +EXPORT_SYMBOL_GPL(dasd_nofcx); /* * char *dasd[] is intended to hold the ranges supplied by the dasd= statement @@ -272,6 +274,11 @@ dasd_parse_keyword( char *parsestring ) { } return residual_str; } + if (strncmp("nofcx", parsestring, length) == 0) { + dasd_nofcx = 1; + MESSAGE(KERN_INFO, "%s", "disable High Performance Ficon"); + return residual_str; + } if (strncmp("fixedbuffers", parsestring, length) == 0) { if (dasd_page_cache) return residual_str; diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 69f93e626fd..1e4c89b8b30 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -27,9 +27,12 @@ #include #include #include +#include #include "dasd_int.h" #include "dasd_eckd.h" +#include "../cio/chsc.h" + #ifdef PRINTK_HEADER #undef PRINTK_HEADER @@ -245,7 +248,8 @@ define_extent(struct ccw1 *ccw, struct DE_eckd_data *data, unsigned int trk, rc = check_XRC (ccw, data, device); break; default: - DEV_MESSAGE(KERN_ERR, device, "unknown opcode 0x%x", cmd); + DBF_DEV_EVENT(DBF_ERR, device, + "PFX LRE unknown opcode 0x%x", cmd); break; } @@ -289,30 +293,145 @@ static int check_XRC_on_prefix(struct PFX_eckd_data *pfxdata, return 0; /* switch on System Time Stamp - needed for XRC Support */ - pfxdata->define_extend.ga_extended |= 0x08; /* 'Time Stamp Valid' */ - pfxdata->define_extend.ga_extended |= 0x02; /* 'Extended Parameter' */ + pfxdata->define_extent.ga_extended |= 0x08; /* 'Time Stamp Valid' */ + pfxdata->define_extent.ga_extended |= 0x02; /* 'Extended Parameter' */ pfxdata->validity.time_stamp = 1; /* 'Time Stamp Valid' */ - rc = get_sync_clock(&pfxdata->define_extend.ep_sys_time); + rc = get_sync_clock(&pfxdata->define_extent.ep_sys_time); /* Ignore return code if sync clock is switched off. */ if (rc == -ENOSYS || rc == -EACCES) rc = 0; return rc; } -static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, - unsigned int trk, unsigned int totrk, int cmd, - struct dasd_device *basedev, struct dasd_device *startdev) +static void fill_LRE_data(struct LRE_eckd_data *data, unsigned int trk, + unsigned int rec_on_trk, int count, int cmd, + struct dasd_device *device, unsigned int reclen, + unsigned int tlf) +{ + struct dasd_eckd_private *private; + int sector; + int dn, d; + + private = (struct dasd_eckd_private *) device->private; + + memset(data, 0, sizeof(*data)); + sector = 0; + if (rec_on_trk) { + switch (private->rdc_data.dev_type) { + case 0x3390: + dn = ceil_quot(reclen + 6, 232); + d = 9 + ceil_quot(reclen + 6 * (dn + 1), 34); + sector = (49 + (rec_on_trk - 1) * (10 + d)) / 8; + break; + case 0x3380: + d = 7 + ceil_quot(reclen + 12, 32); + sector = (39 + (rec_on_trk - 1) * (8 + d)) / 7; + break; + } + } + data->sector = sector; + /* note: meaning of count depends on the operation + * for record based I/O it's the number of records, but for + * track based I/O it's the number of tracks + */ + data->count = count; + switch (cmd) { + case DASD_ECKD_CCW_WRITE_HOME_ADDRESS: + data->operation.orientation = 0x3; + data->operation.operation = 0x03; + break; + case DASD_ECKD_CCW_READ_HOME_ADDRESS: + data->operation.orientation = 0x3; + data->operation.operation = 0x16; + break; + case DASD_ECKD_CCW_WRITE_RECORD_ZERO: + data->operation.orientation = 0x1; + data->operation.operation = 0x03; + data->count++; + break; + case DASD_ECKD_CCW_READ_RECORD_ZERO: + data->operation.orientation = 0x3; + data->operation.operation = 0x16; + data->count++; + break; + case DASD_ECKD_CCW_WRITE: + case DASD_ECKD_CCW_WRITE_MT: + case DASD_ECKD_CCW_WRITE_KD: + case DASD_ECKD_CCW_WRITE_KD_MT: + data->auxiliary.length_valid = 0x1; + data->length = reclen; + data->operation.operation = 0x01; + break; + case DASD_ECKD_CCW_WRITE_CKD: + case DASD_ECKD_CCW_WRITE_CKD_MT: + data->auxiliary.length_valid = 0x1; + data->length = reclen; + data->operation.operation = 0x03; + break; + case DASD_ECKD_CCW_WRITE_TRACK_DATA: + data->auxiliary.length_valid = 0x1; + data->length = reclen; /* not tlf, as one might think */ + data->operation.operation = 0x3F; + data->extended_operation = 0x23; + break; + case DASD_ECKD_CCW_READ: + case DASD_ECKD_CCW_READ_MT: + case DASD_ECKD_CCW_READ_KD: + case DASD_ECKD_CCW_READ_KD_MT: + data->auxiliary.length_valid = 0x1; + data->length = reclen; + data->operation.operation = 0x06; + break; + case DASD_ECKD_CCW_READ_CKD: + case DASD_ECKD_CCW_READ_CKD_MT: + data->auxiliary.length_valid = 0x1; + data->length = reclen; + data->operation.operation = 0x16; + break; + case DASD_ECKD_CCW_READ_COUNT: + data->operation.operation = 0x06; + break; + case DASD_ECKD_CCW_READ_TRACK_DATA: + data->auxiliary.length_valid = 0x1; + data->length = tlf; + data->operation.operation = 0x0C; + break; + case DASD_ECKD_CCW_ERASE: + data->length = reclen; + data->auxiliary.length_valid = 0x1; + data->operation.operation = 0x0b; + break; + default: + DBF_DEV_EVENT(DBF_ERR, device, + "fill LRE unknown opcode 0x%x", cmd); + BUG(); + } + set_ch_t(&data->seek_addr, + trk / private->rdc_data.trk_per_cyl, + trk % private->rdc_data.trk_per_cyl); + data->search_arg.cyl = data->seek_addr.cyl; + data->search_arg.head = data->seek_addr.head; + data->search_arg.record = rec_on_trk; +} + +static int prefix_LRE(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, + unsigned int trk, unsigned int totrk, int cmd, + struct dasd_device *basedev, struct dasd_device *startdev, + unsigned char format, unsigned int rec_on_trk, int count, + unsigned int blksize, unsigned int tlf) { struct dasd_eckd_private *basepriv, *startpriv; - struct DE_eckd_data *data; + struct DE_eckd_data *dedata; + struct LRE_eckd_data *lredata; u32 begcyl, endcyl; u16 heads, beghead, endhead; int rc = 0; basepriv = (struct dasd_eckd_private *) basedev->private; startpriv = (struct dasd_eckd_private *) startdev->private; - data = &pfxdata->define_extend; + dedata = &pfxdata->define_extent; + lredata = &pfxdata->locate_record; ccw->cmd_code = DASD_ECKD_CCW_PFX; ccw->flags = 0; @@ -321,10 +440,16 @@ static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, memset(pfxdata, 0, sizeof(*pfxdata)); /* prefix data */ - pfxdata->format = 0; + if (format > 1) { + DBF_DEV_EVENT(DBF_ERR, basedev, + "PFX LRE unknown format 0x%x", format); + BUG(); + return -EINVAL; + } + pfxdata->format = format; pfxdata->base_address = basepriv->ned->unit_addr; pfxdata->base_lss = basepriv->ned->ID; - pfxdata->validity.define_extend = 1; + pfxdata->validity.define_extent = 1; /* private uid is kept up to date, conf_data may be outdated */ if (startpriv->uid.type != UA_BASE_DEVICE) { @@ -344,42 +469,55 @@ static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, case DASD_ECKD_CCW_READ_KD: case DASD_ECKD_CCW_READ_KD_MT: case DASD_ECKD_CCW_READ_COUNT: - data->mask.perm = 0x1; - data->attributes.operation = basepriv->attrib.operation; + dedata->mask.perm = 0x1; + dedata->attributes.operation = basepriv->attrib.operation; + break; + case DASD_ECKD_CCW_READ_TRACK_DATA: + dedata->mask.perm = 0x1; + dedata->attributes.operation = basepriv->attrib.operation; + dedata->blk_size = 0; break; case DASD_ECKD_CCW_WRITE: case DASD_ECKD_CCW_WRITE_MT: case DASD_ECKD_CCW_WRITE_KD: case DASD_ECKD_CCW_WRITE_KD_MT: - data->mask.perm = 0x02; - data->attributes.operation = basepriv->attrib.operation; + dedata->mask.perm = 0x02; + dedata->attributes.operation = basepriv->attrib.operation; rc = check_XRC_on_prefix(pfxdata, basedev); break; case DASD_ECKD_CCW_WRITE_CKD: case DASD_ECKD_CCW_WRITE_CKD_MT: - data->attributes.operation = DASD_BYPASS_CACHE; + dedata->attributes.operation = DASD_BYPASS_CACHE; rc = check_XRC_on_prefix(pfxdata, basedev); break; case DASD_ECKD_CCW_ERASE: case DASD_ECKD_CCW_WRITE_HOME_ADDRESS: case DASD_ECKD_CCW_WRITE_RECORD_ZERO: - data->mask.perm = 0x3; - data->mask.auth = 0x1; - data->attributes.operation = DASD_BYPASS_CACHE; + dedata->mask.perm = 0x3; + dedata->mask.auth = 0x1; + dedata->attributes.operation = DASD_BYPASS_CACHE; rc = check_XRC_on_prefix(pfxdata, basedev); break; - default: - DEV_MESSAGE(KERN_ERR, basedev, "unknown opcode 0x%x", cmd); + case DASD_ECKD_CCW_WRITE_TRACK_DATA: + dedata->mask.perm = 0x02; + dedata->attributes.operation = basepriv->attrib.operation; + dedata->blk_size = blksize; + rc = check_XRC_on_prefix(pfxdata, basedev); break; + default: + DBF_DEV_EVENT(DBF_ERR, basedev, + "PFX LRE unknown opcode 0x%x", cmd); + BUG(); + return -EINVAL; } - data->attributes.mode = 0x3; /* ECKD */ + dedata->attributes.mode = 0x3; /* ECKD */ if ((basepriv->rdc_data.cu_type == 0x2105 || basepriv->rdc_data.cu_type == 0x2107 || basepriv->rdc_data.cu_type == 0x1750) && !(basepriv->uses_cdl && trk < 2)) - data->ga_extended |= 0x40; /* Regular Data Format Mode */ + dedata->ga_extended |= 0x40; /* Regular Data Format Mode */ heads = basepriv->rdc_data.trk_per_cyl; begcyl = trk / heads; @@ -388,8 +526,8 @@ static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, endhead = totrk % heads; /* check for sequential prestage - enhance cylinder range */ - if (data->attributes.operation == DASD_SEQ_PRESTAGE || - data->attributes.operation == DASD_SEQ_ACCESS) { + if (dedata->attributes.operation == DASD_SEQ_PRESTAGE || + dedata->attributes.operation == DASD_SEQ_ACCESS) { if (endcyl + basepriv->attrib.nr_cyl < basepriv->real_cyl) endcyl += basepriv->attrib.nr_cyl; @@ -397,11 +535,25 @@ static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, endcyl = (basepriv->real_cyl - 1); } - set_ch_t(&data->beg_ext, begcyl, beghead); - set_ch_t(&data->end_ext, endcyl, endhead); + set_ch_t(&dedata->beg_ext, begcyl, beghead); + set_ch_t(&dedata->end_ext, endcyl, endhead); + + if (format == 1) { + fill_LRE_data(lredata, trk, rec_on_trk, count, cmd, + basedev, blksize, tlf); + } + return rc; } +static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, + unsigned int trk, unsigned int totrk, int cmd, + struct dasd_device *basedev, struct dasd_device *startdev) +{ + return prefix_LRE(ccw, pfxdata, trk, totrk, cmd, basedev, startdev, + 0, 0, 0, 0, 0); +} + static void locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, unsigned int trk, unsigned int rec_on_trk, int no_rec, int cmd, @@ -845,7 +997,8 @@ static int dasd_eckd_read_features(struct dasd_device *device) /* * Build CP for Perform Subsystem Function - SSC. */ -static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device) +static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device, + int enable_pav) { struct dasd_ccw_req *cqr; struct dasd_psf_ssc_data *psf_ssc_data; @@ -862,9 +1015,11 @@ static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device) } psf_ssc_data = (struct dasd_psf_ssc_data *)cqr->data; psf_ssc_data->order = PSF_ORDER_SSC; - psf_ssc_data->suborder = 0x88; - psf_ssc_data->reserved[0] = 0x88; - + psf_ssc_data->suborder = 0x40; + if (enable_pav) { + psf_ssc_data->suborder |= 0x88; + psf_ssc_data->reserved[0] = 0x88; + } ccw = cqr->cpaddr; ccw->cmd_code = DASD_ECKD_CCW_PSF; ccw->cda = (__u32)(addr_t)psf_ssc_data; @@ -885,12 +1040,12 @@ static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device) * call might change behaviour of DASD devices. */ static int -dasd_eckd_psf_ssc(struct dasd_device *device) +dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav) { struct dasd_ccw_req *cqr; int rc; - cqr = dasd_eckd_build_psf_ssc(device); + cqr = dasd_eckd_build_psf_ssc(device, enable_pav); if (IS_ERR(cqr)) return PTR_ERR(cqr); @@ -909,12 +1064,13 @@ static int dasd_eckd_validate_server(struct dasd_device *device) { int rc; struct dasd_eckd_private *private; + int enable_pav; - /* Currently PAV is the only reason to 'validate' server on LPAR */ if (dasd_nopav || MACHINE_IS_VM) - return 0; - - rc = dasd_eckd_psf_ssc(device); + enable_pav = 0; + else + enable_pav = 1; + rc = dasd_eckd_psf_ssc(device, enable_pav); /* may be requested feature is not available on server, * therefore just report error and go ahead */ private = (struct dasd_eckd_private *) device->private; @@ -1504,40 +1660,41 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device, struct irb *irb) { char mask; + char *sense = NULL; /* first of all check for state change pending interrupt */ mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP; - if ((irb->scsw.cmd.dstat & mask) == mask) { + if ((scsw_dstat(&irb->scsw) & mask) == mask) { dasd_generic_handle_state_change(device); return; } /* summary unit check */ - if ((irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) && + if ((scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK) && (irb->ecw[7] == 0x0D)) { dasd_alias_handle_summary_unit_check(device, irb); return; } - + sense = dasd_get_sense(irb); /* service information message SIM */ - if (irb->esw.esw0.erw.cons && !(irb->ecw[27] & DASD_SENSE_BIT_0) && - ((irb->ecw[6] & DASD_SIM_SENSE) == DASD_SIM_SENSE)) { - dasd_3990_erp_handle_sim(device, irb->ecw); + if (sense && !(sense[27] & DASD_SENSE_BIT_0) && + ((sense[6] & DASD_SIM_SENSE) == DASD_SIM_SENSE)) { + dasd_3990_erp_handle_sim(device, sense); dasd_schedule_device_bh(device); return; } - if ((irb->scsw.cmd.cc == 1) && - (irb->scsw.cmd.fctl & SCSW_FCTL_START_FUNC) && - (irb->scsw.cmd.actl & SCSW_ACTL_START_PEND) && - (irb->scsw.cmd.stctl & SCSW_STCTL_STATUS_PEND)) { + if ((scsw_cc(&irb->scsw) == 1) && + (scsw_fctl(&irb->scsw) & SCSW_FCTL_START_FUNC) && + (scsw_actl(&irb->scsw) & SCSW_ACTL_START_PEND) && + (scsw_stctl(&irb->scsw) & SCSW_STCTL_STATUS_PEND)) { /* fake irb do nothing, they are handled elsewhere */ dasd_schedule_device_bh(device); return; } - if (!(irb->esw.esw0.erw.cons)) { + if (!sense) { /* just report other unsolicited interrupts */ DEV_MESSAGE(KERN_ERR, device, "%s", "unsolicited interrupt received"); @@ -1552,9 +1709,19 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device, return; }; -static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev, + +static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single( + struct dasd_device *startdev, struct dasd_block *block, - struct request *req) + struct request *req, + sector_t first_rec, + sector_t last_rec, + sector_t first_trk, + sector_t last_trk, + unsigned int first_offs, + unsigned int last_offs, + unsigned int blk_per_trk, + unsigned int blksize) { struct dasd_eckd_private *private; unsigned long *idaws; @@ -1564,11 +1731,9 @@ static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev, struct req_iterator iter; struct bio_vec *bv; char *dst; - unsigned int blksize, blk_per_trk, off; + unsigned int off; int count, cidaw, cplength, datasize; - sector_t recid, first_rec, last_rec; - sector_t first_trk, last_trk; - unsigned int first_offs, last_offs; + sector_t recid; unsigned char cmd, rcmd; int use_prefix; struct dasd_device *basedev; @@ -1581,15 +1746,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev, cmd = DASD_ECKD_CCW_WRITE_MT; else return ERR_PTR(-EINVAL); - /* Calculate number of blocks/records per track. */ - blksize = block->bp_block; - blk_per_trk = recs_per_track(&private->rdc_data, 0, blksize); - /* Calculate record id of first and last block. */ - first_rec = first_trk = req->sector >> block->s2b_shift; - first_offs = sector_div(first_trk, blk_per_trk); - last_rec = last_trk = - (req->sector + req->nr_sectors - 1) >> block->s2b_shift; - last_offs = sector_div(last_trk, blk_per_trk); + /* Check struct bio and count the number of blocks for the request. */ count = 0; cidaw = 0; @@ -1739,6 +1896,497 @@ static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev, return cqr; } +static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track( + struct dasd_device *startdev, + struct dasd_block *block, + struct request *req, + sector_t first_rec, + sector_t last_rec, + sector_t first_trk, + sector_t last_trk, + unsigned int first_offs, + unsigned int last_offs, + unsigned int blk_per_trk, + unsigned int blksize) +{ + struct dasd_eckd_private *private; + unsigned long *idaws; + struct dasd_ccw_req *cqr; + struct ccw1 *ccw; + struct req_iterator iter; + struct bio_vec *bv; + char *dst, *idaw_dst; + unsigned int cidaw, cplength, datasize; + unsigned int tlf; + sector_t recid; + unsigned char cmd; + struct dasd_device *basedev; + unsigned int trkcount, count, count_to_trk_end; + unsigned int idaw_len, seg_len, part_len, len_to_track_end; + unsigned char new_track, end_idaw; + sector_t trkid; + unsigned int recoffs; + + basedev = block->base; + private = (struct dasd_eckd_private *) basedev->private; + if (rq_data_dir(req) == READ) + cmd = DASD_ECKD_CCW_READ_TRACK_DATA; + else if (rq_data_dir(req) == WRITE) + cmd = DASD_ECKD_CCW_WRITE_TRACK_DATA; + else + return ERR_PTR(-EINVAL); + + /* Track based I/O needs IDAWs for each page, and not just for + * 64 bit addresses. We need additional idals for pages + * that get filled from two tracks, so we use the number + * of records as upper limit. + */ + cidaw = last_rec - first_rec + 1; + trkcount = last_trk - first_trk + 1; + + /* 1x prefix + one read/write ccw per track */ + cplength = 1 + trkcount; + + /* on 31-bit we need space for two 32 bit addresses per page + * on 64-bit one 64 bit address + */ + datasize = sizeof(struct PFX_eckd_data) + + cidaw * sizeof(unsigned long long); + + /* Allocate the ccw request. */ + cqr = dasd_smalloc_request(dasd_eckd_discipline.name, + cplength, datasize, startdev); + if (IS_ERR(cqr)) + return cqr; + ccw = cqr->cpaddr; + /* transfer length factor: how many bytes to read from the last track */ + if (first_trk == last_trk) + tlf = last_offs - first_offs + 1; + else + tlf = last_offs + 1; + tlf *= blksize; + + if (prefix_LRE(ccw++, cqr->data, first_trk, + last_trk, cmd, basedev, startdev, + 1 /* format */, first_offs + 1, + trkcount, blksize, + tlf) == -EAGAIN) { + /* Clock not in sync and XRC is enabled. + * Try again later. + */ + dasd_sfree_request(cqr, startdev); + return ERR_PTR(-EAGAIN); + } + + /* + * The translation of request into ccw programs must meet the + * following conditions: + * - all idaws but the first and the last must address full pages + * (or 2K blocks on 31-bit) + * - the scope of a ccw and it's idal ends with the track boundaries + */ + idaws = (unsigned long *) (cqr->data + sizeof(struct PFX_eckd_data)); + recid = first_rec; + new_track = 1; + end_idaw = 0; + len_to_track_end = 0; + idaw_dst = 0; + idaw_len = 0; + rq_for_each_segment(bv, req, iter) { + dst = page_address(bv->bv_page) + bv->bv_offset; + seg_len = bv->bv_len; + while (seg_len) { + if (new_track) { + trkid = recid; + recoffs = sector_div(trkid, blk_per_trk); + count_to_trk_end = blk_per_trk - recoffs; + count = min((last_rec - recid + 1), + (sector_t)count_to_trk_end); + len_to_track_end = count * blksize; + ccw[-1].flags |= CCW_FLAG_CC; + ccw->cmd_code = cmd; + ccw->count = len_to_track_end; + ccw->cda = (__u32)(addr_t)idaws; + ccw->flags = CCW_FLAG_IDA; + ccw++; + recid += count; + new_track = 0; + } + /* If we start a new idaw, everything is fine and the + * start of the new idaw is the start of this segment. + * If we continue an idaw, we must make sure that the + * current segment begins where the so far accumulated + * idaw ends + */ + if (!idaw_dst) + idaw_dst = dst; + if ((idaw_dst + idaw_len) != dst) { + dasd_sfree_request(cqr, startdev); + return ERR_PTR(-ERANGE); + } + part_len = min(seg_len, len_to_track_end); + seg_len -= part_len; + dst += part_len; + idaw_len += part_len; + len_to_track_end -= part_len; + /* collected memory area ends on an IDA_BLOCK border, + * -> create an idaw + * idal_create_words will handle cases where idaw_len + * is larger then IDA_BLOCK_SIZE + */ + if (!(__pa(idaw_dst + idaw_len) & (IDA_BLOCK_SIZE-1))) + end_idaw = 1; + /* We also need to end the idaw at track end */ + if (!len_to_track_end) { + new_track = 1; + end_idaw = 1; + } + if (end_idaw) { + idaws = idal_create_words(idaws, idaw_dst, + idaw_len); + idaw_dst = 0; + idaw_len = 0; + end_idaw = 0; + } + } + } + + if (blk_noretry_request(req) || + block->base->features & DASD_FEATURE_FAILFAST) + set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); + cqr->startdev = startdev; + cqr->memdev = startdev; + cqr->block = block; + cqr->expires = 5 * 60 * HZ; /* 5 minutes */ + cqr->lpm = private->path_data.ppm; + cqr->retries = 256; + cqr->buildclk = get_clock(); + cqr->status = DASD_CQR_FILLED; + return cqr; +} + +static int prepare_itcw(struct itcw *itcw, + unsigned int trk, unsigned int totrk, int cmd, + struct dasd_device *basedev, + struct dasd_device *startdev, + unsigned int rec_on_trk, int count, + unsigned int blksize, + unsigned int total_data_size, + unsigned int tlf, + unsigned int blk_per_trk) +{ + struct PFX_eckd_data pfxdata; + struct dasd_eckd_private *basepriv, *startpriv; + struct DE_eckd_data *dedata; + struct LRE_eckd_data *lredata; + struct dcw *dcw; + + u32 begcyl, endcyl; + u16 heads, beghead, endhead; + u8 pfx_cmd; + + int rc = 0; + int sector = 0; + int dn, d; + + + /* setup prefix data */ + basepriv = (struct dasd_eckd_private *) basedev->private; + startpriv = (struct dasd_eckd_private *) startdev->private; + dedata = &pfxdata.define_extent; + lredata = &pfxdata.locate_record; + + memset(&pfxdata, 0, sizeof(pfxdata)); + pfxdata.format = 1; /* PFX with LRE */ + pfxdata.base_address = basepriv->ned->unit_addr; + pfxdata.base_lss = basepriv->ned->ID; + pfxdata.validity.define_extent = 1; + + /* private uid is kept up to date, conf_data may be outdated */ + if (startpriv->uid.type != UA_BASE_DEVICE) { + pfxdata.validity.verify_base = 1; + if (startpriv->uid.type == UA_HYPER_PAV_ALIAS) + pfxdata.validity.hyper_pav = 1; + } + + switch (cmd) { + case DASD_ECKD_CCW_READ_TRACK_DATA: + dedata->mask.perm = 0x1; + dedata->attributes.operation = basepriv->attrib.operation; + dedata->blk_size = blksize; + dedata->ga_extended |= 0x42; + lredata->operation.orientation = 0x0; + lredata->operation.operation = 0x0C; + lredata->auxiliary.check_bytes = 0x01; + pfx_cmd = DASD_ECKD_CCW_PFX_READ; + break; + case DASD_ECKD_CCW_WRITE_TRACK_DATA: + dedata->mask.perm = 0x02; + dedata->attributes.operation = basepriv->attrib.operation; + dedata->blk_size = blksize; + rc = check_XRC_on_prefix(&pfxdata, basedev); + dedata->ga_extended |= 0x42; + lredata->operation.orientation = 0x0; + lredata->operation.operation = 0x3F; + lredata->extended_operation = 0x23; + lredata->auxiliary.check_bytes = 0x2; + pfx_cmd = DASD_ECKD_CCW_PFX; + break; + default: + DBF_DEV_EVENT(DBF_ERR, basedev, + "prepare itcw, unknown opcode 0x%x", cmd); + BUG(); + break; + } + if (rc) + return rc; + + dedata->attributes.mode = 0x3; /* ECKD */ + + heads = basepriv->rdc_data.trk_per_cyl; + begcyl = trk / heads; + beghead = trk % heads; + endcyl = totrk / heads; + endhead = totrk % heads; + + /* check for sequential prestage - enhance cylinder range */ + if (dedata->attributes.operation == DASD_SEQ_PRESTAGE || + dedata->attributes.operation == DASD_SEQ_ACCESS) { + + if (endcyl + basepriv->attrib.nr_cyl < basepriv->real_cyl) + endcyl += basepriv->attrib.nr_cyl; + else + endcyl = (basepriv->real_cyl - 1); + } + + set_ch_t(&dedata->beg_ext, begcyl, beghead); + set_ch_t(&dedata->end_ext, endcyl, endhead); + + dedata->ep_format = 0x20; /* records per track is valid */ + dedata->ep_rec_per_track = blk_per_trk; + + if (rec_on_trk) { + switch (basepriv->rdc_data.dev_type) { + case 0x3390: + dn = ceil_quot(blksize + 6, 232); + d = 9 + ceil_quot(blksize + 6 * (dn + 1), 34); + sector = (49 + (rec_on_trk - 1) * (10 + d)) / 8; + break; + case 0x3380: + d = 7 + ceil_quot(blksize + 12, 32); + sector = (39 + (rec_on_trk - 1) * (8 + d)) / 7; + break; + } + } + + lredata->auxiliary.length_valid = 1; + lredata->auxiliary.length_scope = 1; + lredata->auxiliary.imbedded_ccw_valid = 1; + lredata->length = tlf; + lredata->imbedded_ccw = cmd; + lredata->count = count; + lredata->sector = sector; + set_ch_t(&lredata->seek_addr, begcyl, beghead); + lredata->search_arg.cyl = lredata->seek_addr.cyl; + lredata->search_arg.head = lredata->seek_addr.head; + lredata->search_arg.record = rec_on_trk; + + dcw = itcw_add_dcw(itcw, pfx_cmd, 0, + &pfxdata, sizeof(pfxdata), total_data_size); + + return rc; +} + +static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( + struct dasd_device *startdev, + struct dasd_block *block, + struct request *req, + sector_t first_rec, + sector_t last_rec, + sector_t first_trk, + sector_t last_trk, + unsigned int first_offs, + unsigned int last_offs, + unsigned int blk_per_trk, + unsigned int blksize) +{ + struct dasd_eckd_private *private; + struct dasd_ccw_req *cqr; + struct req_iterator iter; + struct bio_vec *bv; + char *dst; + unsigned int trkcount, ctidaw; + unsigned char cmd; + struct dasd_device *basedev; + unsigned int tlf; + struct itcw *itcw; + struct tidaw *last_tidaw = NULL; + int itcw_op; + size_t itcw_size; + + basedev = block->base; + private = (struct dasd_eckd_private *) basedev->private; + if (rq_data_dir(req) == READ) { + cmd = DASD_ECKD_CCW_READ_TRACK_DATA; + itcw_op = ITCW_OP_READ; + } else if (rq_data_dir(req) == WRITE) { + cmd = DASD_ECKD_CCW_WRITE_TRACK_DATA; + itcw_op = ITCW_OP_WRITE; + } else + return ERR_PTR(-EINVAL); + + /* trackbased I/O needs address all memory via TIDAWs, + * not just for 64 bit addresses. This allows us to map + * each segment directly to one tidaw. + */ + trkcount = last_trk - first_trk + 1; + ctidaw = 0; + rq_for_each_segment(bv, req, iter) { + ++ctidaw; + } + + /* Allocate the ccw request. */ + itcw_size = itcw_calc_size(0, ctidaw, 0); + cqr = dasd_smalloc_request(dasd_eckd_discipline.name, + 0, itcw_size, startdev); + if (IS_ERR(cqr)) + return cqr; + + cqr->cpmode = 1; + cqr->startdev = startdev; + cqr->memdev = startdev; + cqr->block = block; + cqr->expires = 100*HZ; + cqr->buildclk = get_clock(); + cqr->status = DASD_CQR_FILLED; + cqr->retries = 10; + + /* transfer length factor: how many bytes to read from the last track */ + if (first_trk == last_trk) + tlf = last_offs - first_offs + 1; + else + tlf = last_offs + 1; + tlf *= blksize; + + itcw = itcw_init(cqr->data, itcw_size, itcw_op, 0, ctidaw, 0); + cqr->cpaddr = itcw_get_tcw(itcw); + + if (prepare_itcw(itcw, first_trk, last_trk, + cmd, basedev, startdev, + first_offs + 1, + trkcount, blksize, + (last_rec - first_rec + 1) * blksize, + tlf, blk_per_trk) == -EAGAIN) { + /* Clock not in sync and XRC is enabled. + * Try again later. + */ + dasd_sfree_request(cqr, startdev); + return ERR_PTR(-EAGAIN); + } + + /* + * A tidaw can address 4k of memory, but must not cross page boundaries + * We can let the block layer handle this by setting + * blk_queue_segment_boundary to page boundaries and + * blk_max_segment_size to page size when setting up the request queue. + */ + rq_for_each_segment(bv, req, iter) { + dst = page_address(bv->bv_page) + bv->bv_offset; + last_tidaw = itcw_add_tidaw(itcw, 0x00, dst, bv->bv_len); + if (IS_ERR(last_tidaw)) + return (struct dasd_ccw_req *)last_tidaw; + } + + last_tidaw->flags |= 0x80; + itcw_finalize(itcw); + + if (blk_noretry_request(req) || + block->base->features & DASD_FEATURE_FAILFAST) + set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); + cqr->startdev = startdev; + cqr->memdev = startdev; + cqr->block = block; + cqr->expires = 5 * 60 * HZ; /* 5 minutes */ + cqr->lpm = private->path_data.ppm; + cqr->retries = 256; + cqr->buildclk = get_clock(); + cqr->status = DASD_CQR_FILLED; + return cqr; +} + +static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev, + struct dasd_block *block, + struct request *req) +{ + int tpm, cmdrtd, cmdwtd; + int use_prefix; + + struct dasd_eckd_private *private; + int fcx_in_css, fcx_in_gneq, fcx_in_features; + struct dasd_device *basedev; + sector_t first_rec, last_rec; + sector_t first_trk, last_trk; + unsigned int first_offs, last_offs; + unsigned int blk_per_trk, blksize; + int cdlspecial; + struct dasd_ccw_req *cqr; + + basedev = block->base; + private = (struct dasd_eckd_private *) basedev->private; + + /* Calculate number of blocks/records per track. */ + blksize = block->bp_block; + blk_per_trk = recs_per_track(&private->rdc_data, 0, blksize); + /* Calculate record id of first and last block. */ + first_rec = first_trk = req->sector >> block->s2b_shift; + first_offs = sector_div(first_trk, blk_per_trk); + last_rec = last_trk = + (req->sector + req->nr_sectors - 1) >> block->s2b_shift; + last_offs = sector_div(last_trk, blk_per_trk); + cdlspecial = (private->uses_cdl && first_rec < 2*blk_per_trk); + + /* is transport mode supported ? */ + fcx_in_css = css_general_characteristics.fcx; + fcx_in_gneq = private->gneq->reserved2[7] & 0x04; + fcx_in_features = private->features.feature[40] & 0x80; + tpm = fcx_in_css && fcx_in_gneq && fcx_in_features; + + /* is read track data and write track data in command mode supported? */ + cmdrtd = private->features.feature[9] & 0x20; + cmdwtd = private->features.feature[12] & 0x40; + use_prefix = private->features.feature[8] & 0x01; + + cqr = NULL; + if (cdlspecial || dasd_page_cache) { + /* do nothing, just fall through to the cmd mode single case */ + } else if (!dasd_nofcx && tpm && (first_trk == last_trk)) { + cqr = dasd_eckd_build_cp_tpm_track(startdev, block, req, + first_rec, last_rec, + first_trk, last_trk, + first_offs, last_offs, + blk_per_trk, blksize); + if (IS_ERR(cqr) && PTR_ERR(cqr) != -EAGAIN) + cqr = NULL; + } else if (use_prefix && + (((rq_data_dir(req) == READ) && cmdrtd) || + ((rq_data_dir(req) == WRITE) && cmdwtd))) { + cqr = dasd_eckd_build_cp_cmd_track(startdev, block, req, + first_rec, last_rec, + first_trk, last_trk, + first_offs, last_offs, + blk_per_trk, blksize); + if (IS_ERR(cqr) && PTR_ERR(cqr) != -EAGAIN) + cqr = NULL; + } + if (!cqr) + cqr = dasd_eckd_build_cp_cmd_single(startdev, block, req, + first_rec, last_rec, + first_trk, last_trk, + first_offs, last_offs, + blk_per_trk, blksize); + return cqr; +} + static int dasd_eckd_free_cp(struct dasd_ccw_req *cqr, struct request *req) { @@ -1792,7 +2440,7 @@ out: } /* - * Modify ccw chain in cqr so it can be started on a base device. + * Modify ccw/tcw in cqr so it can be started on a base device. * * Note that this is not enough to restart the cqr! * Either reset cqr->startdev as well (summary unit check handling) @@ -1802,13 +2450,24 @@ void dasd_eckd_reset_ccw_to_base_io(struct dasd_ccw_req *cqr) { struct ccw1 *ccw; struct PFX_eckd_data *pfxdata; - - ccw = cqr->cpaddr; - pfxdata = cqr->data; - - if (ccw->cmd_code == DASD_ECKD_CCW_PFX) { + struct tcw *tcw; + struct tccb *tccb; + struct dcw *dcw; + + if (cqr->cpmode == 1) { + tcw = cqr->cpaddr; + tccb = tcw_get_tccb(tcw); + dcw = (struct dcw *)&tccb->tca[0]; + pfxdata = (struct PFX_eckd_data *)&dcw->cd[0]; pfxdata->validity.verify_base = 0; pfxdata->validity.hyper_pav = 0; + } else { + ccw = cqr->cpaddr; + pfxdata = cqr->data; + if (ccw->cmd_code == DASD_ECKD_CCW_PFX) { + pfxdata->validity.verify_base = 0; + pfxdata->validity.hyper_pav = 0; + } } } @@ -1886,6 +2545,7 @@ dasd_eckd_release(struct dasd_device *device) { struct dasd_ccw_req *cqr; int rc; + struct ccw1 *ccw; if (!capable(CAP_SYS_ADMIN)) return -EACCES; @@ -1897,10 +2557,11 @@ dasd_eckd_release(struct dasd_device *device) "Could not allocate initialization request"); return PTR_ERR(cqr); } - cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RELEASE; - cqr->cpaddr->flags |= CCW_FLAG_SLI; - cqr->cpaddr->count = 32; - cqr->cpaddr->cda = (__u32)(addr_t) cqr->data; + ccw = cqr->cpaddr; + ccw->cmd_code = DASD_ECKD_CCW_RELEASE; + ccw->flags |= CCW_FLAG_SLI; + ccw->count = 32; + ccw->cda = (__u32)(addr_t) cqr->data; cqr->startdev = device; cqr->memdev = device; clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); @@ -1927,6 +2588,7 @@ dasd_eckd_reserve(struct dasd_device *device) { struct dasd_ccw_req *cqr; int rc; + struct ccw1 *ccw; if (!capable(CAP_SYS_ADMIN)) return -EACCES; @@ -1938,10 +2600,11 @@ dasd_eckd_reserve(struct dasd_device *device) "Could not allocate initialization request"); return PTR_ERR(cqr); } - cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RESERVE; - cqr->cpaddr->flags |= CCW_FLAG_SLI; - cqr->cpaddr->count = 32; - cqr->cpaddr->cda = (__u32)(addr_t) cqr->data; + ccw = cqr->cpaddr; + ccw->cmd_code = DASD_ECKD_CCW_RESERVE; + ccw->flags |= CCW_FLAG_SLI; + ccw->count = 32; + ccw->cda = (__u32)(addr_t) cqr->data; cqr->startdev = device; cqr->memdev = device; clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); @@ -1967,6 +2630,7 @@ dasd_eckd_steal_lock(struct dasd_device *device) { struct dasd_ccw_req *cqr; int rc; + struct ccw1 *ccw; if (!capable(CAP_SYS_ADMIN)) return -EACCES; @@ -1978,10 +2642,11 @@ dasd_eckd_steal_lock(struct dasd_device *device) "Could not allocate initialization request"); return PTR_ERR(cqr); } - cqr->cpaddr->cmd_code = DASD_ECKD_CCW_SLCK; - cqr->cpaddr->flags |= CCW_FLAG_SLI; - cqr->cpaddr->count = 32; - cqr->cpaddr->cda = (__u32)(addr_t) cqr->data; + ccw = cqr->cpaddr; + ccw->cmd_code = DASD_ECKD_CCW_SLCK; + ccw->flags |= CCW_FLAG_SLI; + ccw->count = 32; + ccw->cda = (__u32)(addr_t) cqr->data; cqr->startdev = device; cqr->memdev = device; clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); @@ -2271,7 +2936,7 @@ dasd_eckd_dump_ccw_range(struct ccw1 *from, struct ccw1 *to, char *page) * Print sense data and related channel program. * Parts are printed because printk buffer is only 1024 bytes. */ -static void dasd_eckd_dump_sense(struct dasd_device *device, +static void dasd_eckd_dump_sense_ccw(struct dasd_device *device, struct dasd_ccw_req *req, struct irb *irb) { char *page; @@ -2290,7 +2955,7 @@ static void dasd_eckd_dump_sense(struct dasd_device *device, dev_name(&device->cdev->dev)); len += sprintf(page + len, KERN_ERR PRINTK_HEADER " in req: %p CS: 0x%02X DS: 0x%02X\n", req, - irb->scsw.cmd.cstat, irb->scsw.cmd.dstat); + scsw_cstat(&irb->scsw), scsw_dstat(&irb->scsw)); len += sprintf(page + len, KERN_ERR PRINTK_HEADER " device %s: Failing CCW: %p\n", dev_name(&device->cdev->dev), @@ -2366,6 +3031,147 @@ static void dasd_eckd_dump_sense(struct dasd_device *device, free_page((unsigned long) page); } + +/* + * Print sense data from a tcw. + */ +static void dasd_eckd_dump_sense_tcw(struct dasd_device *device, + struct dasd_ccw_req *req, struct irb *irb) +{ + char *page; + int len, sl, sct, residual; + + struct tsb *tsb; + u8 *sense; + + + page = (char *) get_zeroed_page(GFP_ATOMIC); + if (page == NULL) { + DEV_MESSAGE(KERN_ERR, device, " %s", + "No memory to dump sense data"); + return; + } + /* dump the sense data */ + len = sprintf(page, KERN_ERR PRINTK_HEADER + " I/O status report for device %s:\n", + dev_name(&device->cdev->dev)); + len += sprintf(page + len, KERN_ERR PRINTK_HEADER + " in req: %p CS: 0x%02X DS: 0x%02X " + "fcxs: 0x%02X schxs: 0x%02X\n", req, + scsw_cstat(&irb->scsw), scsw_dstat(&irb->scsw), + irb->scsw.tm.fcxs, irb->scsw.tm.schxs); + len += sprintf(page + len, KERN_ERR PRINTK_HEADER + " device %s: Failing TCW: %p\n", + dev_name(&device->cdev->dev), + (void *) (addr_t) irb->scsw.tm.tcw); + + tsb = NULL; + sense = NULL; + if (irb->scsw.tm.tcw) + tsb = tcw_get_tsb( + (struct tcw *)(unsigned long)irb->scsw.tm.tcw); + + if (tsb && (irb->scsw.tm.fcxs == 0x01)) { + len += sprintf(page + len, KERN_ERR PRINTK_HEADER + " tsb->length %d\n", tsb->length); + len += sprintf(page + len, KERN_ERR PRINTK_HEADER + " tsb->flags %x\n", tsb->flags); + len += sprintf(page + len, KERN_ERR PRINTK_HEADER + " tsb->dcw_offset %d\n", tsb->dcw_offset); + len += sprintf(page + len, KERN_ERR PRINTK_HEADER + " tsb->count %d\n", tsb->count); + residual = tsb->count - 28; + len += sprintf(page + len, KERN_ERR PRINTK_HEADER + " residual %d\n", residual); + + switch (tsb->flags & 0x07) { + case 1: /* tsa_iostat */ + len += sprintf(page + len, KERN_ERR PRINTK_HEADER + " tsb->tsa.iostat.dev_time %d\n", + tsb->tsa.iostat.dev_time); + len += sprintf(page + len, KERN_ERR PRINTK_HEADER + " tsb->tsa.iostat.def_time %d\n", + tsb->tsa.iostat.def_time); + len += sprintf(page + len, KERN_ERR PRINTK_HEADER + " tsb->tsa.iostat.queue_time %d\n", + tsb->tsa.iostat.queue_time); + len += sprintf(page + len, KERN_ERR PRINTK_HEADER + " tsb->tsa.iostat.dev_busy_time %d\n", + tsb->tsa.iostat.dev_busy_time); + len += sprintf(page + len, KERN_ERR PRINTK_HEADER + " tsb->tsa.iostat.dev_act_time %d\n", + tsb->tsa.iostat.dev_act_time); + sense = tsb->tsa.iostat.sense; + break; + case 2: /* ts_ddpc */ + len += sprintf(page + len, KERN_ERR PRINTK_HEADER + " tsb->tsa.ddpc.rc %d\n", tsb->tsa.ddpc.rc); + len += sprintf(page + len, KERN_ERR PRINTK_HEADER + " tsb->tsa.ddpc.rcq: "); + for (sl = 0; sl < 16; sl++) { + for (sct = 0; sct < 8; sct++) { + len += sprintf(page + len, " %02x", + tsb->tsa.ddpc.rcq[sl]); + } + len += sprintf(page + len, "\n"); + } + sense = tsb->tsa.ddpc.sense; + break; + case 3: /* tsa_intrg */ + len += sprintf(page + len, KERN_ERR PRINTK_HEADER + " tsb->tsa.intrg.: not supportet yet \n"); + break; + } + + if (sense) { + for (sl = 0; sl < 4; sl++) { + len += sprintf(page + len, + KERN_ERR PRINTK_HEADER + " Sense(hex) %2d-%2d:", + (8 * sl), ((8 * sl) + 7)); + for (sct = 0; sct < 8; sct++) { + len += sprintf(page + len, " %02x", + sense[8 * sl + sct]); + } + len += sprintf(page + len, "\n"); + } + + if (sense[27] & DASD_SENSE_BIT_0) { + /* 24 Byte Sense Data */ + sprintf(page + len, KERN_ERR PRINTK_HEADER + " 24 Byte: %x MSG %x, " + "%s MSGb to SYSOP\n", + sense[7] >> 4, sense[7] & 0x0f, + sense[1] & 0x10 ? "" : "no"); + } else { + /* 32 Byte Sense Data */ + sprintf(page + len, KERN_ERR PRINTK_HEADER + " 32 Byte: Format: %x " + "Exception class %x\n", + sense[6] & 0x0f, sense[22] >> 4); + } + } else { + sprintf(page + len, KERN_ERR PRINTK_HEADER + " SORRY - NO VALID SENSE AVAILABLE\n"); + } + } else { + sprintf(page + len, KERN_ERR PRINTK_HEADER + " SORRY - NO TSB DATA AVAILABLE\n"); + } + printk("%s", page); + free_page((unsigned long) page); +} + +static void dasd_eckd_dump_sense(struct dasd_device *device, + struct dasd_ccw_req *req, struct irb *irb) +{ + if (req && scsw_is_tm(&req->irb.scsw)) + dasd_eckd_dump_sense_tcw(device, req, irb); + else + dasd_eckd_dump_sense_ccw(device, req, irb); +} + + /* * max_blocks is dependent on the amount of storage that is available * in the static io buffer for each device. Currently each device has diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index eecfa776db1..ad45bcac3ce 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h @@ -38,8 +38,11 @@ #define DASD_ECKD_CCW_RELEASE 0x94 #define DASD_ECKD_CCW_READ_CKD_MT 0x9e #define DASD_ECKD_CCW_WRITE_CKD_MT 0x9d +#define DASD_ECKD_CCW_WRITE_TRACK_DATA 0xA5 +#define DASD_ECKD_CCW_READ_TRACK_DATA 0xA6 #define DASD_ECKD_CCW_RESERVE 0xB4 #define DASD_ECKD_CCW_PFX 0xE7 +#define DASD_ECKD_CCW_PFX_READ 0xEA #define DASD_ECKD_CCW_RSCK 0xF9 /* @@ -123,7 +126,9 @@ struct DE_eckd_data { unsigned long long ep_sys_time; /* Ext Parameter - System Time Stamp */ __u8 ep_format; /* Extended Parameter format byte */ __u8 ep_prio; /* Extended Parameter priority I/O byte */ - __u8 ep_reserved[6]; /* Extended Parameter Reserved */ + __u8 ep_reserved1; /* Extended Parameter Reserved */ + __u8 ep_rec_per_track; /* Number of records on a track */ + __u8 ep_reserved[4]; /* Extended Parameter Reserved */ } __attribute__ ((packed)); struct LO_eckd_data { @@ -144,11 +149,37 @@ struct LO_eckd_data { __u16 length; } __attribute__ ((packed)); +struct LRE_eckd_data { + struct { + unsigned char orientation:2; + unsigned char operation:6; + } __attribute__ ((packed)) operation; + struct { + unsigned char length_valid:1; + unsigned char length_scope:1; + unsigned char imbedded_ccw_valid:1; + unsigned char check_bytes:2; + unsigned char imbedded_count_valid:1; + unsigned char reserved:1; + unsigned char read_count_suffix:1; + } __attribute__ ((packed)) auxiliary; + __u8 imbedded_ccw; + __u8 count; + struct ch_t seek_addr; + struct chr_t search_arg; + __u8 sector; + __u16 length; + __u8 imbedded_count; + __u8 extended_operation; + __u16 extended_parameter_length; + __u8 extended_parameter[0]; +} __attribute__ ((packed)); + /* Prefix data for format 0x00 and 0x01 */ struct PFX_eckd_data { unsigned char format; struct { - unsigned char define_extend:1; + unsigned char define_extent:1; unsigned char time_stamp:1; unsigned char verify_base:1; unsigned char hyper_pav:1; @@ -158,9 +189,8 @@ struct PFX_eckd_data { __u8 aux; __u8 base_lss; __u8 reserved[7]; - struct DE_eckd_data define_extend; - struct LO_eckd_data locate_record; - __u8 LO_extended_data[4]; + struct DE_eckd_data define_extent; + struct LRE_eckd_data locate_record; } __attribute__ ((packed)); struct dasd_eckd_characteristics { diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c index f8e05ce9862..9ce4209552a 100644 --- a/drivers/s390/block/dasd_eer.c +++ b/drivers/s390/block/dasd_eer.c @@ -297,11 +297,12 @@ static void dasd_eer_write_standard_trigger(struct dasd_device *device, struct dasd_eer_header header; unsigned long flags; struct eerbuffer *eerb; + char *sense; /* go through cqr chain and count the valid sense data sets */ data_size = 0; for (temp_cqr = cqr; temp_cqr; temp_cqr = temp_cqr->refers) - if (temp_cqr->irb.esw.esw0.erw.cons) + if (dasd_get_sense(&temp_cqr->irb)) data_size += 32; header.total_size = sizeof(header) + data_size + 4; /* "EOR" */ @@ -316,9 +317,11 @@ static void dasd_eer_write_standard_trigger(struct dasd_device *device, list_for_each_entry(eerb, &bufferlist, list) { dasd_eer_start_record(eerb, header.total_size); dasd_eer_write_buffer(eerb, (char *) &header, sizeof(header)); - for (temp_cqr = cqr; temp_cqr; temp_cqr = temp_cqr->refers) - if (temp_cqr->irb.esw.esw0.erw.cons) - dasd_eer_write_buffer(eerb, cqr->irb.ecw, 32); + for (temp_cqr = cqr; temp_cqr; temp_cqr = temp_cqr->refers) { + sense = dasd_get_sense(&temp_cqr->irb); + if (sense) + dasd_eer_write_buffer(eerb, sense, 32); + } dasd_eer_write_buffer(eerb, "EOR", 4); } spin_unlock_irqrestore(&bufferlock, flags); @@ -451,6 +454,7 @@ int dasd_eer_enable(struct dasd_device *device) { struct dasd_ccw_req *cqr; unsigned long flags; + struct ccw1 *ccw; if (device->eer_cqr) return 0; @@ -468,10 +472,11 @@ int dasd_eer_enable(struct dasd_device *device) cqr->expires = 10 * HZ; clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); - cqr->cpaddr->cmd_code = DASD_ECKD_CCW_SNSS; - cqr->cpaddr->count = SNSS_DATA_SIZE; - cqr->cpaddr->flags = 0; - cqr->cpaddr->cda = (__u32)(addr_t) cqr->data; + ccw = cqr->cpaddr; + ccw->cmd_code = DASD_ECKD_CCW_SNSS; + ccw->count = SNSS_DATA_SIZE; + ccw->flags = 0; + ccw->cda = (__u32)(addr_t) cqr->data; cqr->buildclk = get_clock(); cqr->status = DASD_CQR_FILLED; diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 29991a9fa07..7b314c1d471 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -157,7 +157,8 @@ struct dasd_ccw_req { struct dasd_block *block; /* the originating block device */ struct dasd_device *memdev; /* the device used to allocate this */ struct dasd_device *startdev; /* device the request is started on */ - struct ccw1 *cpaddr; /* address of channel program */ + void *cpaddr; /* address of ccw or tcw */ + unsigned char cpmode; /* 0 = cmd mode, 1 = itcw */ char status; /* status of this request */ short retries; /* A retry counter */ unsigned long flags; /* flags of this request */ @@ -573,12 +574,14 @@ int dasd_generic_notify(struct ccw_device *, int); void dasd_generic_handle_state_change(struct dasd_device *); int dasd_generic_read_dev_chars(struct dasd_device *, char *, void **, int); +char *dasd_get_sense(struct irb *); /* externals in dasd_devmap.c */ extern int dasd_max_devindex; extern int dasd_probeonly; extern int dasd_autodetect; extern int dasd_nopav; +extern int dasd_nofcx; int dasd_devmap_init(void); void dasd_devmap_exit(void); -- GitLab From fc19f381b3828aa4f8a3417dbefc3418ec6bbe10 Mon Sep 17 00:00:00 2001 From: Stefan Haberland Date: Thu, 26 Mar 2009 15:23:49 +0100 Subject: [PATCH 4616/4982] [S390] dasd: message cleanup Moved some Messages into s390 debug feature and changed remaining messages to use the dev_xxx and pr_xxx macros. Signed-off-by: Stefan Haberland Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd.c | 176 +++---- drivers/s390/block/dasd_3990_erp.c | 730 +++++++++++++++-------------- drivers/s390/block/dasd_alias.c | 10 +- drivers/s390/block/dasd_devmap.c | 38 +- drivers/s390/block/dasd_diag.c | 66 ++- drivers/s390/block/dasd_eckd.c | 196 +++++--- drivers/s390/block/dasd_eer.c | 6 +- drivers/s390/block/dasd_erp.c | 21 +- drivers/s390/block/dasd_fba.c | 77 +-- drivers/s390/block/dasd_genhd.c | 7 +- drivers/s390/block/dasd_int.h | 6 + drivers/s390/block/dasd_ioctl.c | 27 +- drivers/s390/block/dasd_proc.c | 20 +- 13 files changed, 743 insertions(+), 637 deletions(-) diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 00f7d24b337..2fd64e5a9ab 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -9,6 +9,9 @@ * */ +#define KMSG_COMPONENT "dasd" +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt + #include #include #include @@ -222,7 +225,7 @@ static int dasd_state_known_to_basic(struct dasd_device *device) return rc; } /* register 'device' debug area, used for all DBF_DEV_XXX calls */ - device->debug_area = debug_register(dev_name(&device->cdev->dev), 1, 1, + device->debug_area = debug_register(dev_name(&device->cdev->dev), 4, 1, 8 * sizeof(long)); debug_register_view(device->debug_area, &debug_sprintf_view); debug_set_level(device->debug_area, DBF_WARNING); @@ -763,7 +766,7 @@ static inline int dasd_check_cqr(struct dasd_ccw_req *cqr) return -EINVAL; device = cqr->startdev; if (strncmp((char *) &cqr->magic, device->discipline->ebcname, 4)) { - DEV_MESSAGE(KERN_WARNING, device, + DBF_DEV_EVENT(DBF_WARNING, device, " dasd_ccw_req 0x%08x magic doesn't match" " discipline 0x%08x", cqr->magic, @@ -783,6 +786,7 @@ int dasd_term_IO(struct dasd_ccw_req *cqr) { struct dasd_device *device; int retries, rc; + char errorstring[ERRORLENGTH]; /* Check the cqr */ rc = dasd_check_cqr(cqr); @@ -816,10 +820,10 @@ int dasd_term_IO(struct dasd_ccw_req *cqr) "device busy, retry later"); break; default: - DEV_MESSAGE(KERN_ERR, device, - "line %d unknown RC=%d, please " - "report to linux390@de.ibm.com", - __LINE__, rc); + /* internal error 10 - unknown rc*/ + snprintf(errorstring, ERRORLENGTH, "10 %d", rc); + dev_err(&device->cdev->dev, "An error occurred in the " + "DASD device driver, reason=%s\n", errorstring); BUG(); break; } @@ -837,6 +841,7 @@ int dasd_start_IO(struct dasd_ccw_req *cqr) { struct dasd_device *device; int rc; + char errorstring[ERRORLENGTH]; /* Check the cqr */ rc = dasd_check_cqr(cqr); @@ -844,9 +849,10 @@ int dasd_start_IO(struct dasd_ccw_req *cqr) return rc; device = (struct dasd_device *) cqr->startdev; if (cqr->retries < 0) { - DEV_MESSAGE(KERN_DEBUG, device, - "start_IO: request %p (%02x/%i) - no retry left.", - cqr, cqr->status, cqr->retries); + /* internal error 14 - start_IO run out of retries */ + sprintf(errorstring, "14 %p", cqr); + dev_err(&device->cdev->dev, "An error occurred in the DASD " + "device driver, reason=%s\n", errorstring); cqr->status = DASD_CQR_ERROR; return -EIO; } @@ -868,11 +874,11 @@ int dasd_start_IO(struct dasd_ccw_req *cqr) cqr); break; case -EBUSY: - DBF_DEV_EVENT(DBF_ERR, device, "%s", + DBF_DEV_EVENT(DBF_DEBUG, device, "%s", "start_IO: device busy, retry later"); break; case -ETIMEDOUT: - DBF_DEV_EVENT(DBF_ERR, device, "%s", + DBF_DEV_EVENT(DBF_DEBUG, device, "%s", "start_IO: request timeout, retry later"); break; case -EACCES: @@ -882,7 +888,7 @@ int dasd_start_IO(struct dasd_ccw_req *cqr) * Do a retry with all available pathes. */ cqr->lpm = LPM_ANYPATH; - DBF_DEV_EVENT(DBF_ERR, device, "%s", + DBF_DEV_EVENT(DBF_DEBUG, device, "%s", "start_IO: selected pathes gone," " retry on all pathes"); break; @@ -891,13 +897,15 @@ int dasd_start_IO(struct dasd_ccw_req *cqr) "start_IO: -ENODEV device gone, retry"); break; case -EIO: - DBF_DEV_EVENT(DBF_ERR, device, "%s", + DBF_DEV_EVENT(DBF_DEBUG, device, "%s", "start_IO: -EIO device gone, retry"); break; default: - DEV_MESSAGE(KERN_ERR, device, - "line %d unknown RC=%d, please report" - " to linux390@de.ibm.com", __LINE__, rc); + /* internal error 11 - unknown rc */ + snprintf(errorstring, ERRORLENGTH, "11 %d", rc); + dev_err(&device->cdev->dev, + "An error occurred in the DASD device driver, " + "reason=%s\n", errorstring); BUG(); break; } @@ -954,7 +962,7 @@ static void dasd_handle_killed_request(struct ccw_device *cdev, return; cqr = (struct dasd_ccw_req *) intparm; if (cqr->status != DASD_CQR_IN_IO) { - MESSAGE(KERN_DEBUG, + DBF_EVENT(DBF_DEBUG, "invalid status in handle_killed_request: " "bus_id %s, status %02x", dev_name(&cdev->dev), cqr->status); @@ -965,8 +973,8 @@ static void dasd_handle_killed_request(struct ccw_device *cdev, if (device == NULL || device != dasd_device_from_cdev_locked(cdev) || strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { - MESSAGE(KERN_DEBUG, "invalid device in request: bus_id %s", - dev_name(&cdev->dev)); + DBF_DEV_EVENT(DBF_DEBUG, device, "invalid device in request: " + "bus_id %s", dev_name(&cdev->dev)); return; } @@ -1005,11 +1013,11 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, case -EIO: break; case -ETIMEDOUT: - printk(KERN_WARNING"%s(%s): request timed out\n", + DBF_EVENT(DBF_WARNING, "%s(%s): request timed out\n", __func__, dev_name(&cdev->dev)); break; default: - printk(KERN_WARNING"%s(%s): unknown error %ld\n", + DBF_EVENT(DBF_WARNING, "%s(%s): unknown error %ld\n", __func__, dev_name(&cdev->dev), PTR_ERR(irb)); } dasd_handle_killed_request(cdev, intparm); @@ -1018,10 +1026,6 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, now = get_clock(); - DBF_EVENT(DBF_ERR, "Interrupt: bus_id %s CS/DS %04x ip %08x", - dev_name(&cdev->dev), ((irb->scsw.cmd.cstat << 8) | - irb->scsw.cmd.dstat), (unsigned int) intparm); - /* check for unsolicited interrupts */ cqr = (struct dasd_ccw_req *) intparm; if (!cqr || ((scsw_cc(&irb->scsw) == 1) && @@ -1042,8 +1046,8 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, device = (struct dasd_device *) cqr->startdev; if (!device || strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { - MESSAGE(KERN_DEBUG, "invalid device in request: bus_id %s", - dev_name(&cdev->dev)); + DBF_DEV_EVENT(DBF_DEBUG, device, "invalid device in request: " + "bus_id %s", dev_name(&cdev->dev)); return; } @@ -1059,13 +1063,11 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, /* check status - the request might have been killed by dyn detach */ if (cqr->status != DASD_CQR_IN_IO) { - MESSAGE(KERN_DEBUG, - "invalid status: bus_id %s, status %02x", - dev_name(&cdev->dev), cqr->status); + DBF_DEV_EVENT(DBF_DEBUG, device, "invalid status: bus_id %s, " + "status %02x", dev_name(&cdev->dev), cqr->status); return; } - DBF_DEV_EVENT(DBF_DEBUG, device, "Int: CS/DS 0x%04x for cqr %p", - ((irb->scsw.cmd.cstat << 8) | irb->scsw.cmd.dstat), cqr); + next = NULL; expires = 0; if (scsw_dstat(&irb->scsw) == (DEV_STAT_CHN_END | DEV_STAT_DEV_END) && @@ -1080,18 +1082,23 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, } } else { /* error */ memcpy(&cqr->irb, irb, sizeof(struct irb)); + /* log sense for every failed I/O to s390 debugfeature */ + dasd_log_sense_dbf(cqr, irb); if (device->features & DASD_FEATURE_ERPLOG) { dasd_log_sense(cqr, irb); } + /* * If we don't want complex ERP for this request, then just * reset this and retry it in the fastpath */ if (!test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags) && cqr->retries > 0) { - DEV_MESSAGE(KERN_DEBUG, device, - "default ERP in fastpath (%i retries left)", - cqr->retries); + if (cqr->lpm == LPM_ANYPATH) + DBF_DEV_EVENT(DBF_DEBUG, device, + "default ERP in fastpath " + "(%i retries left)", + cqr->retries); cqr->lpm = LPM_ANYPATH; cqr->status = DASD_CQR_QUEUED; next = cqr; @@ -1102,10 +1109,6 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, (!device->stopped)) { if (device->discipline->start_IO(next) == 0) expires = next->expires; - else - DEV_MESSAGE(KERN_DEBUG, device, "%s", - "Interrupt fastpath " - "failed!"); } if (expires != 0) dasd_device_set_timer(device, expires); @@ -1178,6 +1181,7 @@ static void __dasd_device_process_final_queue(struct dasd_device *device, struct dasd_block *block; void (*callback)(struct dasd_ccw_req *, void *data); void *callback_data; + char errorstring[ERRORLENGTH]; list_for_each_safe(l, n, final_queue) { cqr = list_entry(l, struct dasd_ccw_req, devlist); @@ -1198,10 +1202,11 @@ static void __dasd_device_process_final_queue(struct dasd_device *device, cqr->status = DASD_CQR_TERMINATED; break; default: - DEV_MESSAGE(KERN_ERR, device, - "wrong cqr status in __dasd_process_final_queue " - "for cqr %p, status %x", - cqr, cqr->status); + /* internal error 12 - wrong cqr status*/ + snprintf(errorstring, ERRORLENGTH, "12 %p %x02", cqr, cqr->status); + dev_err(&device->cdev->dev, + "An error occurred in the DASD device driver, " + "reason=%s\n", errorstring); BUG(); } if (cqr->callback != NULL) @@ -1226,18 +1231,17 @@ static void __dasd_device_check_expire(struct dasd_device *device) (time_after_eq(jiffies, cqr->expires + cqr->starttime))) { if (device->discipline->term_IO(cqr) != 0) { /* Hmpf, try again in 5 sec */ - DEV_MESSAGE(KERN_ERR, device, - "internal error - timeout (%is) expired " - "for cqr %p, termination failed, " - "retrying in 5s", - (cqr->expires/HZ), cqr); + dev_err(&device->cdev->dev, + "cqr %p timed out (%is) but cannot be " + "ended, retrying in 5 s\n", + cqr, (cqr->expires/HZ)); cqr->expires += 5*HZ; dasd_device_set_timer(device, 5*HZ); } else { - DEV_MESSAGE(KERN_ERR, device, - "internal error - timeout (%is) expired " - "for cqr %p (%i retries left)", - (cqr->expires/HZ), cqr, cqr->retries); + dev_err(&device->cdev->dev, + "cqr %p timed out (%is), %i retries " + "remaining\n", cqr, (cqr->expires/HZ), + cqr->retries); } } } @@ -1299,10 +1303,9 @@ int dasd_flush_device_queue(struct dasd_device *device) rc = device->discipline->term_IO(cqr); if (rc) { /* unable to terminate requeust */ - DEV_MESSAGE(KERN_ERR, device, - "dasd flush ccw_queue is unable " - " to terminate request %p", - cqr); + dev_err(&device->cdev->dev, + "Flushing the DASD request queue " + "failed for request %p\n", cqr); /* stop flush processing */ goto finished; } @@ -1546,10 +1549,9 @@ int dasd_cancel_req(struct dasd_ccw_req *cqr) /* request in IO - terminate IO and release again */ rc = device->discipline->term_IO(cqr); if (rc) { - DEV_MESSAGE(KERN_ERR, device, - "dasd_cancel_req is unable " - " to terminate request %p, rc = %d", - cqr, rc); + dev_err(&device->cdev->dev, + "Cancelling request %p failed with rc=%d\n", + cqr, rc); } else { cqr->stopclk = get_clock(); rc = 1; @@ -1626,7 +1628,7 @@ static inline void __dasd_block_process_erp(struct dasd_block *block, if (cqr->status == DASD_CQR_DONE) DBF_DEV_EVENT(DBF_NOTICE, device, "%s", "ERP successful"); else - DEV_MESSAGE(KERN_ERR, device, "%s", "ERP unsuccessful"); + dev_err(&device->cdev->dev, "ERP failed for the DASD\n"); erp_fn = device->discipline->erp_postaction(cqr); erp_fn(cqr); } @@ -2055,8 +2057,9 @@ static int dasd_open(struct block_device *bdev, fmode_t mode) } if (dasd_probeonly) { - DEV_MESSAGE(KERN_INFO, base, "%s", - "No access to device due to probeonly mode"); + dev_info(&base->cdev->dev, + "Accessing the DASD failed because it is in " + "probeonly mode\n"); rc = -EPERM; goto out; } @@ -2156,14 +2159,14 @@ int dasd_generic_probe(struct ccw_device *cdev, ret = ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP); if (ret) { - printk(KERN_WARNING + DBF_EVENT(DBF_WARNING, "dasd_generic_probe: could not set ccw-device options " "for %s\n", dev_name(&cdev->dev)); return ret; } ret = dasd_add_sysfs_files(cdev); if (ret) { - printk(KERN_WARNING + DBF_EVENT(DBF_WARNING, "dasd_generic_probe: could not add sysfs entries " "for %s\n", dev_name(&cdev->dev)); return ret; @@ -2179,9 +2182,7 @@ int dasd_generic_probe(struct ccw_device *cdev, (dasd_autodetect && dasd_busid_known(dev_name(&cdev->dev)) != 0)) ret = ccw_device_set_online(cdev); if (ret) - printk(KERN_WARNING - "dasd_generic_probe: could not initially " - "online ccw-device %s; return code: %d\n", + pr_warning("%s: Setting the DASD online failed with rc=%d\n", dev_name(&cdev->dev), ret); return 0; } @@ -2245,10 +2246,9 @@ int dasd_generic_set_online(struct ccw_device *cdev, discipline = base_discipline; if (device->features & DASD_FEATURE_USEDIAG) { if (!dasd_diag_discipline_pointer) { - printk (KERN_WARNING - "dasd_generic couldn't online device %s " - "- discipline DIAG not available\n", - dev_name(&cdev->dev)); + pr_warning("%s Setting the DASD online failed because " + "of missing DIAG discipline\n", + dev_name(&cdev->dev)); dasd_delete_device(device); return -ENODEV; } @@ -2269,10 +2269,9 @@ int dasd_generic_set_online(struct ccw_device *cdev, /* check_device will allocate block device if necessary */ rc = discipline->check_device(device); if (rc) { - printk (KERN_WARNING - "dasd_generic couldn't online device %s " - "with discipline %s rc=%i\n", - dev_name(&cdev->dev), discipline->name, rc); + pr_warning("%s Setting the DASD online with discipline %s " + "failed with rc=%i\n", + dev_name(&cdev->dev), discipline->name, rc); module_put(discipline->owner); module_put(base_discipline->owner); dasd_delete_device(device); @@ -2281,9 +2280,8 @@ int dasd_generic_set_online(struct ccw_device *cdev, dasd_set_target_state(device, DASD_STATE_ONLINE); if (device->state <= DASD_STATE_KNOWN) { - printk (KERN_WARNING - "dasd_generic discipline not found for %s\n", - dev_name(&cdev->dev)); + pr_warning("%s Setting the DASD online failed because of a " + "missing discipline\n", dev_name(&cdev->dev)); rc = -ENODEV; dasd_set_target_state(device, DASD_STATE_NEW); if (device->block) @@ -2327,13 +2325,13 @@ int dasd_generic_set_offline(struct ccw_device *cdev) open_count = atomic_read(&device->block->open_count); if (open_count > max_count) { if (open_count > 0) - printk(KERN_WARNING "Can't offline dasd " - "device with open count = %i.\n", - open_count); + pr_warning("%s: The DASD cannot be set offline " + "with open count %i\n", + dev_name(&cdev->dev), open_count); else - printk(KERN_WARNING "%s", - "Can't offline dasd device due " - "to internal use\n"); + pr_warning("%s: The DASD cannot be set offline " + "while it is in use\n", + dev_name(&cdev->dev)); clear_bit(DASD_FLAG_OFFLINE, &device->flags); dasd_put_device(device); return -EBUSY; @@ -2406,8 +2404,10 @@ static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device, cqr = dasd_smalloc_request(magic, 1 /* RDC */, rdc_buffer_size, device); if (IS_ERR(cqr)) { - DEV_MESSAGE(KERN_WARNING, device, "%s", - "Could not allocate RDC request"); + /* internal error 13 - Allocating the RDC request failed*/ + dev_err(&device->cdev->dev, + "An error occurred in the DASD device driver, " + "reason=%s\n", "13"); return cqr; } @@ -2519,7 +2519,7 @@ static int __init dasd_init(void) return 0; failed: - MESSAGE(KERN_INFO, "%s", "initialization not performed due to errors"); + pr_info("The DASD device driver could not be initialized\n"); dasd_exit(); return rc; } diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index 4cee4591614..27991b69205 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c @@ -7,6 +7,8 @@ * */ +#define KMSG_COMPONENT "dasd" + #include #include #include @@ -75,7 +77,7 @@ dasd_3990_erp_block_queue(struct dasd_ccw_req * erp, int expires) struct dasd_device *device = erp->startdev; unsigned long flags; - DEV_MESSAGE(KERN_INFO, device, + DBF_DEV_EVENT(DBF_INFO, device, "blocking request queue for %is", expires/HZ); spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); @@ -114,9 +116,9 @@ dasd_3990_erp_int_req(struct dasd_ccw_req * erp) } else { /* issue a message and wait for 'device ready' interrupt */ - DEV_MESSAGE(KERN_ERR, device, "%s", + dev_err(&device->cdev->dev, "is offline or not installed - " - "INTERVENTION REQUIRED!!"); + "INTERVENTION REQUIRED!!\n"); dasd_3990_erp_block_queue(erp, 60*HZ); } @@ -158,7 +160,7 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp) if ((erp->lpm & opm) != 0x00) { - DEV_MESSAGE(KERN_DEBUG, device, + DBF_DEV_EVENT(DBF_WARNING, device, "try alternate lpm=%x (lpum=%x / opm=%x)", erp->lpm, erp->irb.esw.esw0.sublog.lpum, opm); @@ -166,10 +168,9 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp) erp->status = DASD_CQR_FILLED; erp->retries = 10; } else { - DEV_MESSAGE(KERN_ERR, device, - "No alternate channel path left (lpum=%x / " - "opm=%x) -> permanent error", - erp->irb.esw.esw0.sublog.lpum, opm); + dev_err(&device->cdev->dev, + "The DASD cannot be reached on any path (lpum=%x" + "/opm=%x)\n", erp->irb.esw.esw0.sublog.lpum, opm); /* post request with permanent error */ erp->status = DASD_CQR_FAILED; @@ -204,8 +205,8 @@ dasd_3990_erp_DCTL(struct dasd_ccw_req * erp, char modifier) sizeof(struct DCTL_data), device); if (IS_ERR(dctl_cqr)) { - DEV_MESSAGE(KERN_ERR, device, "%s", - "Unable to allocate DCTL-CQR"); + dev_err(&device->cdev->dev, + "Unable to allocate DCTL-CQR\n"); erp->status = DASD_CQR_FAILED; return erp; } @@ -294,7 +295,7 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense) /* interrupt (this enables easier enqueing of the cqr) */ if (erp->function != dasd_3990_erp_action_4) { - DEV_MESSAGE(KERN_INFO, device, "%s", + DBF_DEV_EVENT(DBF_INFO, device, "%s", "dasd_3990_erp_action_4: first time retry"); erp->retries = 256; @@ -303,7 +304,7 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense) } else { if (sense && (sense[25] == 0x1D)) { /* state change pending */ - DEV_MESSAGE(KERN_INFO, device, + DBF_DEV_EVENT(DBF_INFO, device, "waiting for state change pending " "interrupt, %d retries left", erp->retries); @@ -311,15 +312,14 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense) dasd_3990_erp_block_queue(erp, 30*HZ); } else if (sense && (sense[25] == 0x1E)) { /* busy */ - DEV_MESSAGE(KERN_INFO, device, + DBF_DEV_EVENT(DBF_INFO, device, "busy - redriving request later, " "%d retries left", erp->retries); dasd_3990_erp_block_queue(erp, HZ); } else { - /* no state change pending - retry */ - DEV_MESSAGE (KERN_INFO, device, + DBF_DEV_EVENT(DBF_INFO, device, "redriving request immediately, " "%d retries left", erp->retries); @@ -384,6 +384,7 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense) struct dasd_device *device = erp->startdev; char msg_format = (sense[7] & 0xF0); char msg_no = (sense[7] & 0x0F); + char errorstring[ERRORLENGTH]; switch (msg_format) { case 0x00: /* Format 0 - Program or System Checks */ @@ -394,95 +395,97 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense) case 0x00: /* No Message */ break; case 0x01: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 0 - Invalid Command"); + dev_warn(&device->cdev->dev, + "FORMAT 0 - Invalid Command\n"); break; case 0x02: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 0 - Invalid Command " - "Sequence"); + "Sequence\n"); break; case 0x03: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 0 - CCW Count less than " - "required"); + "required\n"); break; case 0x04: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 0 - Invalid Parameter"); + dev_warn(&device->cdev->dev, + "FORMAT 0 - Invalid Parameter\n"); break; case 0x05: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 0 - Diagnostic of Sepecial" - " Command Violates File Mask"); + dev_warn(&device->cdev->dev, + "FORMAT 0 - Diagnostic of Special" + " Command Violates File Mask\n"); break; case 0x07: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 0 - Channel Returned with " - "Incorrect retry CCW"); + "Incorrect retry CCW\n"); break; case 0x08: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 0 - Reset Notification"); + dev_warn(&device->cdev->dev, + "FORMAT 0 - Reset Notification\n"); break; case 0x09: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 0 - Storage Path Restart"); + dev_warn(&device->cdev->dev, + "FORMAT 0 - Storage Path Restart\n"); break; case 0x0A: - DEV_MESSAGE(KERN_WARNING, device, + dev_warn(&device->cdev->dev, "FORMAT 0 - Channel requested " - "... %02x", sense[8]); + "... %02x\n", sense[8]); break; case 0x0B: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 0 - Invalid Defective/" - "Alternate Track Pointer"); + "Alternate Track Pointer\n"); break; case 0x0C: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 0 - DPS Installation " - "Check"); + "Check\n"); break; case 0x0E: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 0 - Command Invalid on " - "Secondary Address"); + "Secondary Address\n"); break; case 0x0F: - DEV_MESSAGE(KERN_WARNING, device, + dev_warn(&device->cdev->dev, "FORMAT 0 - Status Not As " - "Required: reason %02x", sense[8]); + "Required: reason %02x\n", + sense[8]); break; default: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 0 - Reseved"); + dev_warn(&device->cdev->dev, + "FORMAT 0 - Reserved\n"); } } else { switch (msg_no) { case 0x00: /* No Message */ break; case 0x01: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 0 - Device Error Source"); + dev_warn(&device->cdev->dev, + "FORMAT 0 - Device Error " + "Source\n"); break; case 0x02: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 0 - Reserved"); + dev_warn(&device->cdev->dev, + "FORMAT 0 - Reserved\n"); break; case 0x03: - DEV_MESSAGE(KERN_WARNING, device, + dev_warn(&device->cdev->dev, "FORMAT 0 - Device Fenced - " - "device = %02x", sense[4]); + "device = %02x\n", sense[4]); break; case 0x04: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 0 - Data Pinned for " - "Device"); + "Device\n"); break; default: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 0 - Reserved"); + dev_warn(&device->cdev->dev, + "FORMAT 0 - Reserved\n"); } } break; @@ -492,348 +495,352 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense) case 0x00: /* No Message */ break; case 0x01: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 1 - Device Status 1 not as " - "expected"); + "expected\n"); break; case 0x03: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 1 - Index missing"); + dev_warn(&device->cdev->dev, + "FORMAT 1 - Index missing\n"); break; case 0x04: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 1 - Interruption cannot be reset"); + dev_warn(&device->cdev->dev, + "FORMAT 1 - Interruption cannot be " + "reset\n"); break; case 0x05: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 1 - Device did not respond to " - "selection"); + "selection\n"); break; case 0x06: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 1 - Device check-2 error or Set " - "Sector is not complete"); + "Sector is not complete\n"); break; case 0x07: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 1 - Head address does not " - "compare"); + "compare\n"); break; case 0x08: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 1 - Device status 1 not valid"); + dev_warn(&device->cdev->dev, + "FORMAT 1 - Device status 1 not valid\n"); break; case 0x09: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 1 - Device not ready"); + dev_warn(&device->cdev->dev, + "FORMAT 1 - Device not ready\n"); break; case 0x0A: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 1 - Track physical address did " - "not compare"); + "not compare\n"); break; case 0x0B: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 1 - Missing device address bit"); + dev_warn(&device->cdev->dev, + "FORMAT 1 - Missing device address bit\n"); break; case 0x0C: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 1 - Drive motor switch is off"); + dev_warn(&device->cdev->dev, + "FORMAT 1 - Drive motor switch is off\n"); break; case 0x0D: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 1 - Seek incomplete"); + dev_warn(&device->cdev->dev, + "FORMAT 1 - Seek incomplete\n"); break; case 0x0E: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 1 - Cylinder address did not " - "compare"); + "compare\n"); break; case 0x0F: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 1 - Offset active cannot be " - "reset"); + "reset\n"); break; default: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 1 - Reserved"); + dev_warn(&device->cdev->dev, + "FORMAT 1 - Reserved\n"); } break; case 0x20: /* Format 2 - 3990 Equipment Checks */ switch (msg_no) { case 0x08: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 2 - 3990 check-2 error"); + dev_warn(&device->cdev->dev, + "FORMAT 2 - 3990 check-2 error\n"); break; case 0x0E: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 2 - Support facility errors"); + dev_warn(&device->cdev->dev, + "FORMAT 2 - Support facility errors\n"); break; case 0x0F: - DEV_MESSAGE(KERN_WARNING, device, - "FORMAT 2 - Microcode detected error %02x", - sense[8]); + dev_warn(&device->cdev->dev, + "FORMAT 2 - Microcode detected error " + "%02x\n", + sense[8]); break; default: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 2 - Reserved"); + dev_warn(&device->cdev->dev, + "FORMAT 2 - Reserved\n"); } break; case 0x30: /* Format 3 - 3990 Control Checks */ switch (msg_no) { case 0x0F: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 3 - Allegiance terminated"); + dev_warn(&device->cdev->dev, + "FORMAT 3 - Allegiance terminated\n"); break; default: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 3 - Reserved"); + dev_warn(&device->cdev->dev, + "FORMAT 3 - Reserved\n"); } break; case 0x40: /* Format 4 - Data Checks */ switch (msg_no) { case 0x00: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 4 - Home address area error"); + dev_warn(&device->cdev->dev, + "FORMAT 4 - Home address area error\n"); break; case 0x01: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 4 - Count area error"); + dev_warn(&device->cdev->dev, + "FORMAT 4 - Count area error\n"); break; case 0x02: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 4 - Key area error"); + dev_warn(&device->cdev->dev, + "FORMAT 4 - Key area error\n"); break; case 0x03: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 4 - Data area error"); + dev_warn(&device->cdev->dev, + "FORMAT 4 - Data area error\n"); break; case 0x04: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 4 - No sync byte in home address " - "area"); + "area\n"); break; case 0x05: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 4 - No sync byte in count address " - "area"); + "area\n"); break; case 0x06: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 4 - No sync byte in key area"); + dev_warn(&device->cdev->dev, + "FORMAT 4 - No sync byte in key area\n"); break; case 0x07: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 4 - No sync byte in data area"); + dev_warn(&device->cdev->dev, + "FORMAT 4 - No sync byte in data area\n"); break; case 0x08: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 4 - Home address area error; " - "offset active"); + "offset active\n"); break; case 0x09: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 4 - Count area error; offset " - "active"); + "active\n"); break; case 0x0A: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 4 - Key area error; offset " - "active"); + "active\n"); break; case 0x0B: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 4 - Data area error; " - "offset active"); + "offset active\n"); break; case 0x0C: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 4 - No sync byte in home " - "address area; offset active"); + "address area; offset active\n"); break; case 0x0D: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 4 - No syn byte in count " - "address area; offset active"); + "address area; offset active\n"); break; case 0x0E: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 4 - No sync byte in key area; " - "offset active"); + "offset active\n"); break; case 0x0F: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 4 - No syn byte in data area; " - "offset active"); + "offset active\n"); break; default: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 4 - Reserved"); + dev_warn(&device->cdev->dev, + "FORMAT 4 - Reserved\n"); } break; case 0x50: /* Format 5 - Data Check with displacement information */ switch (msg_no) { case 0x00: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 5 - Data Check in the " - "home address area"); + "home address area\n"); break; case 0x01: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 5 - Data Check in the count area"); + dev_warn(&device->cdev->dev, + "FORMAT 5 - Data Check in the count " + "area\n"); break; case 0x02: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 5 - Data Check in the key area"); + dev_warn(&device->cdev->dev, + "FORMAT 5 - Data Check in the key area\n"); break; case 0x03: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 5 - Data Check in the data area"); + dev_warn(&device->cdev->dev, + "FORMAT 5 - Data Check in the data " + "area\n"); break; case 0x08: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 5 - Data Check in the " - "home address area; offset active"); + "home address area; offset active\n"); break; case 0x09: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 5 - Data Check in the count area; " - "offset active"); + "offset active\n"); break; case 0x0A: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 5 - Data Check in the key area; " - "offset active"); + "offset active\n"); break; case 0x0B: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 5 - Data Check in the data area; " - "offset active"); + "offset active\n"); break; default: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 5 - Reserved"); + dev_warn(&device->cdev->dev, + "FORMAT 5 - Reserved\n"); } break; case 0x60: /* Format 6 - Usage Statistics/Overrun Errors */ switch (msg_no) { case 0x00: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 6 - Overrun on channel A"); + dev_warn(&device->cdev->dev, + "FORMAT 6 - Overrun on channel A\n"); break; case 0x01: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 6 - Overrun on channel B"); + dev_warn(&device->cdev->dev, + "FORMAT 6 - Overrun on channel B\n"); break; case 0x02: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 6 - Overrun on channel C"); + dev_warn(&device->cdev->dev, + "FORMAT 6 - Overrun on channel C\n"); break; case 0x03: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 6 - Overrun on channel D"); + dev_warn(&device->cdev->dev, + "FORMAT 6 - Overrun on channel D\n"); break; case 0x04: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 6 - Overrun on channel E"); + dev_warn(&device->cdev->dev, + "FORMAT 6 - Overrun on channel E\n"); break; case 0x05: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 6 - Overrun on channel F"); + dev_warn(&device->cdev->dev, + "FORMAT 6 - Overrun on channel F\n"); break; case 0x06: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 6 - Overrun on channel G"); + dev_warn(&device->cdev->dev, + "FORMAT 6 - Overrun on channel G\n"); break; case 0x07: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 6 - Overrun on channel H"); + dev_warn(&device->cdev->dev, + "FORMAT 6 - Overrun on channel H\n"); break; default: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 6 - Reserved"); + dev_warn(&device->cdev->dev, + "FORMAT 6 - Reserved\n"); } break; case 0x70: /* Format 7 - Device Connection Control Checks */ switch (msg_no) { case 0x00: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 7 - RCC initiated by a connection " - "check alert"); + "check alert\n"); break; case 0x01: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 7 - RCC 1 sequence not " - "successful"); + "successful\n"); break; case 0x02: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 7 - RCC 1 and RCC 2 sequences not " - "successful"); + "successful\n"); break; case 0x03: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 7 - Invalid tag-in during " - "selection sequence"); + "selection sequence\n"); break; case 0x04: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 7 - extra RCC required"); + dev_warn(&device->cdev->dev, + "FORMAT 7 - extra RCC required\n"); break; case 0x05: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 7 - Invalid DCC selection " - "response or timeout"); + "response or timeout\n"); break; case 0x06: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 7 - Missing end operation; device " - "transfer complete"); + "transfer complete\n"); break; case 0x07: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 7 - Missing end operation; device " - "transfer incomplete"); + "transfer incomplete\n"); break; case 0x08: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 7 - Invalid tag-in for an " - "immediate command sequence"); + "immediate command sequence\n"); break; case 0x09: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 7 - Invalid tag-in for an " - "extended command sequence"); + "extended command sequence\n"); break; case 0x0A: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 7 - 3990 microcode time out when " - "stopping selection"); + "stopping selection\n"); break; case 0x0B: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 7 - No response to selection " - "after a poll interruption"); + "after a poll interruption\n"); break; case 0x0C: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 7 - Permanent path error (DASD " - "controller not available)"); + "controller not available)\n"); break; case 0x0D: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 7 - DASD controller not available" - " on disconnected command chain"); + " on disconnected command chain\n"); break; default: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 7 - Reserved"); + dev_warn(&device->cdev->dev, + "FORMAT 7 - Reserved\n"); } break; @@ -841,52 +848,52 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense) switch (msg_no) { case 0x00: /* No Message */ case 0x01: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 8 - Error correction code " - "hardware fault"); + "hardware fault\n"); break; case 0x03: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 8 - Unexpected end operation " - "response code"); + "response code\n"); break; case 0x04: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 8 - End operation with transfer " - "count not zero"); + "count not zero\n"); break; case 0x05: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 8 - End operation with transfer " - "count zero"); + "count zero\n"); break; case 0x06: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 8 - DPS checks after a system " - "reset or selective reset"); + "reset or selective reset\n"); break; case 0x07: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 8 - DPS cannot be filled"); + dev_warn(&device->cdev->dev, + "FORMAT 8 - DPS cannot be filled\n"); break; case 0x08: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 8 - Short busy time-out during " - "device selection"); + "device selection\n"); break; case 0x09: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 8 - DASD controller failed to " - "set or reset the long busy latch"); + "set or reset the long busy latch\n"); break; case 0x0A: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 8 - No interruption from device " - "during a command chain"); + "during a command chain\n"); break; default: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 8 - Reserved"); + dev_warn(&device->cdev->dev, + "FORMAT 8 - Reserved\n"); } break; @@ -895,97 +902,100 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense) case 0x00: break; /* No Message */ case 0x06: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 9 - Device check-2 error"); + dev_warn(&device->cdev->dev, + "FORMAT 9 - Device check-2 error\n"); break; case 0x07: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 9 - Head address did not compare"); + dev_warn(&device->cdev->dev, + "FORMAT 9 - Head address did not " + "compare\n"); break; case 0x0A: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 9 - Track physical address did " - "not compare while oriented"); + "not compare while oriented\n"); break; case 0x0E: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT 9 - Cylinder address did not " - "compare"); + "compare\n"); break; default: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT 9 - Reserved"); + dev_warn(&device->cdev->dev, + "FORMAT 9 - Reserved\n"); } break; case 0xF0: /* Format F - Cache Storage Checks */ switch (msg_no) { case 0x00: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT F - Operation Terminated"); + dev_warn(&device->cdev->dev, + "FORMAT F - Operation Terminated\n"); break; case 0x01: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT F - Subsystem Processing Error"); + dev_warn(&device->cdev->dev, + "FORMAT F - Subsystem Processing Error\n"); break; case 0x02: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT F - Cache or nonvolatile storage " - "equipment failure"); + "equipment failure\n"); break; case 0x04: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT F - Caching terminated"); + dev_warn(&device->cdev->dev, + "FORMAT F - Caching terminated\n"); break; case 0x06: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT F - Cache fast write access not " - "authorized"); + "authorized\n"); break; case 0x07: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT F - Track format incorrect"); + dev_warn(&device->cdev->dev, + "FORMAT F - Track format incorrect\n"); break; case 0x09: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT F - Caching reinitiated"); + dev_warn(&device->cdev->dev, + "FORMAT F - Caching reinitiated\n"); break; case 0x0A: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT F - Nonvolatile storage " - "terminated"); + "terminated\n"); break; case 0x0B: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT F - Volume is suspended duplex"); + dev_warn(&device->cdev->dev, + "FORMAT F - Volume is suspended duplex\n"); /* call extended error reporting (EER) */ dasd_eer_write(device, erp->refers, DASD_EER_PPRCSUSPEND); break; case 0x0C: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT F - Subsystem status connot be " - "determined"); + dev_warn(&device->cdev->dev, + "FORMAT F - Subsystem status cannot be " + "determined\n"); break; case 0x0D: - DEV_MESSAGE(KERN_WARNING, device, "%s", + dev_warn(&device->cdev->dev, "FORMAT F - Caching status reset to " - "default"); + "default\n"); break; case 0x0E: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT F - DASD Fast Write inhibited"); + dev_warn(&device->cdev->dev, + "FORMAT F - DASD Fast Write inhibited\n"); break; default: - DEV_MESSAGE(KERN_WARNING, device, "%s", - "FORMAT D - Reserved"); + dev_warn(&device->cdev->dev, + "FORMAT D - Reserved\n"); } break; - default: /* unknown message format - should not happen */ - DEV_MESSAGE (KERN_WARNING, device, - "unknown message format %02x", - msg_format); + default: /* unknown message format - should not happen + internal error 03 - unknown message format */ + snprintf(errorstring, ERRORLENGTH, "03 %x02", msg_format); + dev_err(&device->cdev->dev, + "An error occurred in the DASD device driver, " + "reason=%s\n", errorstring); break; } /* end switch message format */ @@ -1015,7 +1025,7 @@ dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense) /* env data present (ACTION 10 - retry should work) */ if (sense[2] & SNS2_ENV_DATA_PRESENT) { - DEV_MESSAGE(KERN_DEBUG, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Command Reject - environmental data present"); dasd_3990_handle_env_data(erp, sense); @@ -1023,9 +1033,10 @@ dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense) erp->retries = 5; } else { - /* fatal error - set status to FAILED */ - DEV_MESSAGE(KERN_ERR, device, "%s", - "Command Reject - Fatal error"); + /* fatal error - set status to FAILED + internal error 09 - Command Reject */ + dev_err(&device->cdev->dev, "An error occurred in the DASD " + "device driver, reason=%s\n", "09"); erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); } @@ -1061,7 +1072,7 @@ dasd_3990_erp_bus_out(struct dasd_ccw_req * erp) } else { /* issue a message and wait for 'device ready' interrupt */ - DEV_MESSAGE(KERN_DEBUG, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "bus out parity error or BOPC requested by " "channel"); @@ -1093,21 +1104,19 @@ dasd_3990_erp_equip_check(struct dasd_ccw_req * erp, char *sense) erp->function = dasd_3990_erp_equip_check; if (sense[1] & SNS1_WRITE_INHIBITED) { + dev_info(&device->cdev->dev, + "Write inhibited path encountered\n"); - DEV_MESSAGE(KERN_DEBUG, device, "%s", - "Write inhibited path encountered"); - - /* vary path offline */ - DEV_MESSAGE(KERN_ERR, device, "%s", - "Path should be varied off-line. " - "This is not implemented yet \n - please report " - "to linux390@de.ibm.com"); + /* vary path offline + internal error 04 - Path should be varied off-line.*/ + dev_err(&device->cdev->dev, "An error occurred in the DASD " + "device driver, reason=%s\n", "04"); erp = dasd_3990_erp_action_1(erp); } else if (sense[2] & SNS2_ENV_DATA_PRESENT) { - DEV_MESSAGE(KERN_DEBUG, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Equipment Check - " "environmental data present"); dasd_3990_handle_env_data(erp, sense); @@ -1116,7 +1125,7 @@ dasd_3990_erp_equip_check(struct dasd_ccw_req * erp, char *sense) } else if (sense[1] & SNS1_PERM_ERR) { - DEV_MESSAGE(KERN_DEBUG, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Equipment Check - retry exhausted or " "undesirable"); @@ -1125,7 +1134,7 @@ dasd_3990_erp_equip_check(struct dasd_ccw_req * erp, char *sense) } else { /* all other equipment checks - Action 5 */ /* rest is done when retries == 0 */ - DEV_MESSAGE(KERN_DEBUG, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Equipment check or processing error"); erp = dasd_3990_erp_action_5(erp); @@ -1156,9 +1165,9 @@ dasd_3990_erp_data_check(struct dasd_ccw_req * erp, char *sense) if (sense[2] & SNS2_CORRECTABLE) { /* correctable data check */ /* issue message that the data has been corrected */ - DEV_MESSAGE(KERN_EMERG, device, "%s", + dev_emerg(&device->cdev->dev, "Data recovered during retry with PCI " - "fetch mode active"); + "fetch mode active\n"); /* not possible to handle this situation in Linux */ panic("No way to inform application about the possibly " @@ -1166,7 +1175,7 @@ dasd_3990_erp_data_check(struct dasd_ccw_req * erp, char *sense) } else if (sense[2] & SNS2_ENV_DATA_PRESENT) { - DEV_MESSAGE(KERN_DEBUG, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Uncorrectable data check recovered secondary " "addr of duplex pair"); @@ -1174,7 +1183,7 @@ dasd_3990_erp_data_check(struct dasd_ccw_req * erp, char *sense) } else if (sense[1] & SNS1_PERM_ERR) { - DEV_MESSAGE(KERN_DEBUG, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Uncorrectable data check with internal " "retry exhausted"); @@ -1182,7 +1191,7 @@ dasd_3990_erp_data_check(struct dasd_ccw_req * erp, char *sense) } else { /* all other data checks */ - DEV_MESSAGE(KERN_DEBUG, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Uncorrectable data check with retry count " "exhausted..."); @@ -1212,7 +1221,7 @@ dasd_3990_erp_overrun(struct dasd_ccw_req * erp, char *sense) erp->function = dasd_3990_erp_overrun; - DEV_MESSAGE(KERN_DEBUG, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Overrun - service overrun or overrun" " error requested by channel"); @@ -1243,7 +1252,7 @@ dasd_3990_erp_inv_format(struct dasd_ccw_req * erp, char *sense) if (sense[2] & SNS2_ENV_DATA_PRESENT) { - DEV_MESSAGE(KERN_DEBUG, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Track format error when destaging or " "staging data"); @@ -1252,8 +1261,10 @@ dasd_3990_erp_inv_format(struct dasd_ccw_req * erp, char *sense) erp = dasd_3990_erp_action_4(erp, sense); } else { - DEV_MESSAGE(KERN_ERR, device, "%s", - "Invalid Track Format - Fatal error"); + /* internal error 06 - The track format is not valid*/ + dev_err(&device->cdev->dev, + "An error occurred in the DASD device driver, " + "reason=%s\n", "06"); erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); } @@ -1279,8 +1290,8 @@ dasd_3990_erp_EOC(struct dasd_ccw_req * default_erp, char *sense) struct dasd_device *device = default_erp->startdev; - DEV_MESSAGE(KERN_ERR, device, "%s", - "End-of-Cylinder - must never happen"); + dev_err(&device->cdev->dev, + "The cylinder data for accessing the DASD is inconsistent\n"); /* implement action 7 - BUG */ return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED); @@ -1306,7 +1317,7 @@ dasd_3990_erp_env_data(struct dasd_ccw_req * erp, char *sense) erp->function = dasd_3990_erp_env_data; - DEV_MESSAGE(KERN_DEBUG, device, "%s", "Environmental data present"); + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Environmental data present"); dasd_3990_handle_env_data(erp, sense); @@ -1339,8 +1350,8 @@ dasd_3990_erp_no_rec(struct dasd_ccw_req * default_erp, char *sense) struct dasd_device *device = default_erp->startdev; - DEV_MESSAGE(KERN_ERR, device, "%s", - "No Record Found - Fatal error "); + dev_err(&device->cdev->dev, + "The specified record was not found\n"); return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED); @@ -1365,7 +1376,8 @@ dasd_3990_erp_file_prot(struct dasd_ccw_req * erp) struct dasd_device *device = erp->startdev; - DEV_MESSAGE(KERN_ERR, device, "%s", "File Protected"); + dev_err(&device->cdev->dev, "Accessing the DASD failed because of " + "a hardware error\n"); return dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); @@ -1394,7 +1406,7 @@ static struct dasd_ccw_req *dasd_3990_erp_inspect_alias( if (cqr->block && (cqr->block->base != cqr->startdev)) { if (cqr->startdev->features & DASD_FEATURE_ERPLOG) { - DEV_MESSAGE(KERN_ERR, cqr->startdev, + DBF_DEV_EVENT(DBF_ERR, cqr->startdev, "ERP on alias device for request %p," " recover on base device %s", cqr, dev_name(&cqr->block->base->cdev->dev)); @@ -1511,7 +1523,7 @@ dasd_3990_erp_action_10_32(struct dasd_ccw_req * erp, char *sense) erp->retries = 256; erp->function = dasd_3990_erp_action_10_32; - DEV_MESSAGE(KERN_DEBUG, device, "%s", "Perform logging requested"); + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Perform logging requested"); return erp; @@ -1549,7 +1561,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) char *LO_data; /* LO_eckd_data_t */ struct ccw1 *ccw, *oldccw; - DEV_MESSAGE(KERN_DEBUG, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Write not finished because of unexpected condition"); default_erp->function = dasd_3990_erp_action_1B_32; @@ -1570,8 +1582,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) /* for imprecise ending just do default erp */ if (sense[1] & 0x01) { - - DEV_MESSAGE(KERN_DEBUG, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Imprecise ending is set - just retry"); return default_erp; @@ -1582,8 +1593,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) cpa = default_erp->refers->irb.scsw.cmd.cpa; if (cpa == 0) { - - DEV_MESSAGE(KERN_DEBUG, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Unable to determine address of the CCW " "to be restarted"); @@ -1597,7 +1607,9 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) sizeof(struct LO_eckd_data), device); if (IS_ERR(erp)) { - DEV_MESSAGE(KERN_ERR, device, "%s", "Unable to allocate ERP"); + /* internal error 01 - Unable to allocate ERP */ + dev_err(&device->cdev->dev, "An error occurred in the DASD " + "device driver, reason=%s\n", "01"); return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED); } @@ -1615,10 +1627,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) LO_data = erp->data + sizeof(struct DE_eckd_data); if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) { - - DEV_MESSAGE(KERN_ERR, device, "%s", - "BUG - this should not happen"); - + /* should not */ return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED); } @@ -1708,7 +1717,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense) char *LO_data; /* struct LO_eckd_data */ struct ccw1 *ccw; - DEV_MESSAGE(KERN_DEBUG, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Write not finished because of unexpected condition" " - follow on"); @@ -1728,8 +1737,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense) /* for imprecise ending just do default erp */ if (sense[1] & 0x01) { - - DEV_MESSAGE(KERN_DEBUG, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Imprecise ending is set - just retry"); previous_erp->status = DASD_CQR_FILLED; @@ -1742,10 +1750,10 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense) cpa = previous_erp->irb.scsw.cmd.cpa; if (cpa == 0) { - - DEV_MESSAGE(KERN_DEBUG, device, "%s", - "Unable to determine address of the CCW " - "to be restarted"); + /* internal error 02 - + Unable to determine address of the CCW to be restarted */ + dev_err(&device->cdev->dev, "An error occurred in the DASD " + "device driver, reason=%s\n", "02"); previous_erp->status = DASD_CQR_FAILED; @@ -1758,10 +1766,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense) LO_data = erp->data + sizeof(struct DE_eckd_data); if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) { - - DEV_MESSAGE(KERN_ERR, device, "%s", - "BUG - this should not happen"); - + /* should not happen */ previous_erp->status = DASD_CQR_FAILED; return previous_erp; @@ -1949,14 +1954,13 @@ dasd_3990_erp_compound_config(struct dasd_ccw_req * erp, char *sense) if ((sense[25] & DASD_SENSE_BIT_1) && (sense[26] & DASD_SENSE_BIT_2)) { - /* set to suspended duplex state then restart */ + /* set to suspended duplex state then restart + internal error 05 - Set device to suspended duplex state + should be done */ struct dasd_device *device = erp->startdev; - - DEV_MESSAGE(KERN_ERR, device, "%s", - "Set device to suspended duplex state should be " - "done!\n" - "This is not implemented yet (for compound ERP)" - " - please report to linux390@de.ibm.com"); + dev_err(&device->cdev->dev, + "An error occurred in the DASD device driver, " + "reason=%s\n", "05"); } @@ -2026,15 +2030,14 @@ dasd_3990_erp_handle_sim(struct dasd_device *device, char *sense) { /* print message according to log or message to operator mode */ if ((sense[24] & DASD_SIM_MSG_TO_OP) || (sense[1] & 0x10)) { - /* print SIM SRC from RefCode */ - DEV_MESSAGE(KERN_ERR, device, "SIM - SRC: " - "%02x%02x%02x%02x", sense[22], + dev_err(&device->cdev->dev, "SIM - SRC: " + "%02x%02x%02x%02x\n", sense[22], sense[23], sense[11], sense[12]); } else if (sense[24] & DASD_SIM_LOG) { /* print SIM SRC Refcode */ - DEV_MESSAGE(KERN_WARNING, device, "SIM - SRC: " - "%02x%02x%02x%02x", sense[22], + dev_warn(&device->cdev->dev, "log SIM - SRC: " + "%02x%02x%02x%02x\n", sense[22], sense[23], sense[11], sense[12]); } } @@ -2077,14 +2080,14 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) switch (sense[25]) { case 0x00: /* success - use default ERP for retries */ - DEV_MESSAGE(KERN_DEBUG, device, "%s", + DBF_DEV_EVENT(DBF_DEBUG, device, "%s", "ERP called for successful request" " - just retry"); break; case 0x01: /* fatal error */ - DEV_MESSAGE(KERN_ERR, device, "%s", - "Retry not recommended - Fatal error"); + dev_err(&device->cdev->dev, + "ERP failed for the DASD\n"); erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); break; @@ -2094,13 +2097,10 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) erp = dasd_3990_erp_int_req(erp); break; - case 0x0F: /* length mismatch during update write command */ - DEV_MESSAGE(KERN_ERR, device, "%s", - "update write command error - should not " - "happen;\n" - "Please send this message together with " - "the above sense data to linux390@de." - "ibm.com"); + case 0x0F: /* length mismatch during update write command + internal error 08 - update write command error*/ + dev_err(&device->cdev->dev, "An error occurred in the " + "DASD device driver, reason=%s\n", "08"); erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); break; @@ -2109,13 +2109,12 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) erp = dasd_3990_erp_action_10_32(erp, sense); break; - case 0x15: /* next track outside defined extend */ - DEV_MESSAGE(KERN_ERR, device, "%s", - "next track outside defined extend - " - "should not happen;\n" - "Please send this message together with " - "the above sense data to linux390@de." - "ibm.com"); + case 0x15: /* next track outside defined extend + internal error 07 - The next track is not + within the defined storage extent */ + dev_err(&device->cdev->dev, + "An error occurred in the DASD device driver, " + "reason=%s\n", "07"); erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); break; @@ -2126,9 +2125,9 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) break; case 0x1C: /* invalid data */ - DEV_MESSAGE(KERN_EMERG, device, "%s", + dev_emerg(&device->cdev->dev, "Data recovered during retry with PCI " - "fetch mode active"); + "fetch mode active\n"); /* not possible to handle this situation in Linux */ panic @@ -2137,7 +2136,7 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) break; case 0x1D: /* state-change pending */ - DEV_MESSAGE(KERN_DEBUG, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "A State change pending condition exists " "for the subsystem or device"); @@ -2145,7 +2144,7 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) break; case 0x1E: /* busy */ - DEV_MESSAGE(KERN_DEBUG, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Busy condition exists " "for the subsystem or device"); erp = dasd_3990_erp_action_4(erp, sense); @@ -2187,7 +2186,7 @@ dasd_3990_erp_control_check(struct dasd_ccw_req *erp) if (scsw_cstat(&erp->refers->irb.scsw) & (SCHN_STAT_INTF_CTRL_CHK | SCHN_STAT_CHN_CTRL_CHK)) { - DEV_MESSAGE(KERN_DEBUG, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "channel or interface control check"); erp = dasd_3990_erp_action_4(erp, NULL); } @@ -2282,12 +2281,12 @@ static struct dasd_ccw_req *dasd_3990_erp_add_erp(struct dasd_ccw_req *cqr) cplength, datasize, device); if (IS_ERR(erp)) { if (cqr->retries <= 0) { - DEV_MESSAGE(KERN_ERR, device, "%s", + DBF_DEV_EVENT(DBF_ERR, device, "%s", "Unable to allocate ERP request"); cqr->status = DASD_CQR_FAILED; cqr->stopclk = get_clock (); } else { - DEV_MESSAGE (KERN_ERR, device, + DBF_DEV_EVENT(DBF_ERR, device, "Unable to allocate ERP request " "(%i retries left)", cqr->retries); @@ -2516,7 +2515,7 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp) break; } default: - DEV_MESSAGE(KERN_DEBUG, device, + DBF_DEV_EVENT(DBF_WARNING, device, "invalid subcommand modifier 0x%x " "for Diagnostic Control Command", sense[25]); @@ -2533,11 +2532,12 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp) erp = dasd_3990_erp_compound(erp, sense); } else { - /* No retry left and no additional special handling */ - /*necessary */ - DEV_MESSAGE(KERN_ERR, device, - "no retries left for erp %p - " - "set status to FAILED", erp); + /* + * No retry left and no additional special handling + * necessary + */ + dev_err(&device->cdev->dev, + "ERP %p has run out of retries and failed\n", erp); erp->status = DASD_CQR_FAILED; } @@ -2612,7 +2612,7 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head, } else { /* simple retry */ - DEV_MESSAGE(KERN_DEBUG, device, + DBF_DEV_EVENT(DBF_DEBUG, device, "%i retries left for erp %p", erp->retries, erp); @@ -2656,13 +2656,13 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr) if (device->features & DASD_FEATURE_ERPLOG) { /* print current erp_chain */ - DEV_MESSAGE(KERN_ERR, device, "%s", - "ERP chain at BEGINNING of ERP-ACTION"); + dev_err(&device->cdev->dev, + "ERP chain at BEGINNING of ERP-ACTION\n"); for (temp_erp = cqr; temp_erp != NULL; temp_erp = temp_erp->refers) { - DEV_MESSAGE(KERN_ERR, device, - " erp %p (%02x) refers to %p", + dev_err(&device->cdev->dev, + "ERP %p (%02x) refers to %p\n", temp_erp, temp_erp->status, temp_erp->refers); } @@ -2673,7 +2673,7 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr) (scsw_dstat(&cqr->irb.scsw) == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))) { - DEV_MESSAGE(KERN_DEBUG, device, + DBF_DEV_EVENT(DBF_DEBUG, device, "ERP called for successful request %p" " - NO ERP necessary", cqr); @@ -2695,13 +2695,13 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr) if (device->features & DASD_FEATURE_ERPLOG) { /* print current erp_chain */ - DEV_MESSAGE(KERN_ERR, device, "%s", - "ERP chain at END of ERP-ACTION"); + dev_err(&device->cdev->dev, + "ERP chain at END of ERP-ACTION\n"); for (temp_erp = erp; temp_erp != NULL; temp_erp = temp_erp->refers) { - DEV_MESSAGE(KERN_ERR, device, - " erp %p (%02x) refers to %p", + dev_err(&device->cdev->dev, + "ERP %p (%02x) refers to %p\n", temp_erp, temp_erp->status, temp_erp->refers); } @@ -2714,6 +2714,8 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr) list_add_tail(&erp->blocklist, &cqr->blocklist); } + + return erp; } /* end dasd_3990_erp_action */ diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index 219bee7bd77..5b7bbc87593 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c @@ -5,6 +5,8 @@ * Author(s): Stefan Weinhuber */ +#define KMSG_COMPONENT "dasd" + #include #include #include "dasd_int.h" @@ -503,7 +505,7 @@ static void lcu_update_work(struct work_struct *work) */ spin_lock_irqsave(&lcu->lock, flags); if (rc || (lcu->flags & NEED_UAC_UPDATE)) { - DEV_MESSAGE(KERN_WARNING, device, "could not update" + DBF_DEV_EVENT(DBF_WARNING, device, "could not update" " alias data in lcu (rc = %d), retry later", rc); schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ); } else { @@ -875,7 +877,7 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device, lcu = private->lcu; if (!lcu) { - DEV_MESSAGE(KERN_WARNING, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "device not ready to handle summary" " unit check (no lcu structure)"); return; @@ -888,7 +890,7 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device, * the next interrupt on a different device */ if (list_empty(&device->alias_list)) { - DEV_MESSAGE(KERN_WARNING, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "device is in offline processing," " don't do summary unit check handling"); spin_unlock(&lcu->lock); @@ -896,7 +898,7 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device, } if (lcu->suc_data.device) { /* already scheduled or running */ - DEV_MESSAGE(KERN_WARNING, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "previous instance of summary unit check worker" " still pending"); spin_unlock(&lcu->lock); diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index da231a787ce..e77666c8e6c 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -13,6 +13,8 @@ * */ +#define KMSG_COMPONENT "dasd" + #include #include #include @@ -127,6 +129,7 @@ __setup ("dasd=", dasd_call_setup); * Read a device busid/devno from a string. */ static int + dasd_busid(char **str, int *id0, int *id1, int *devno) { int val, old_style; @@ -134,8 +137,7 @@ dasd_busid(char **str, int *id0, int *id1, int *devno) /* Interpret ipldev busid */ if (strncmp(DASD_IPLDEV, *str, strlen(DASD_IPLDEV)) == 0) { if (ipl_info.type != IPL_TYPE_CCW) { - MESSAGE(KERN_ERR, "%s", "ipl device is not a ccw " - "device"); + pr_err("The IPL device is not a CCW device\n"); return -EINVAL; } *id0 = 0; @@ -211,9 +213,8 @@ dasd_feature_list(char *str, char **endp) else if (len == 8 && !strncmp(str, "failfast", 8)) features |= DASD_FEATURE_FAILFAST; else { - MESSAGE(KERN_WARNING, - "unsupported feature: %*s, " - "ignoring setting", len, str); + pr_warning("%*s is not a supported device option\n", + len, str); rc = -EINVAL; } str += len; @@ -222,8 +223,8 @@ dasd_feature_list(char *str, char **endp) str++; } if (*str != ')') { - MESSAGE(KERN_WARNING, "%s", - "missing ')' in dasd parameter string\n"); + pr_warning("A closing parenthesis ')' is missing in the " + "dasd= parameter\n"); rc = -EINVAL; } else str++; @@ -255,28 +256,27 @@ dasd_parse_keyword( char *parsestring ) { } if (strncmp("autodetect", parsestring, length) == 0) { dasd_autodetect = 1; - MESSAGE (KERN_INFO, "%s", - "turning to autodetection mode"); + pr_info("The autodetection mode has been activated\n"); return residual_str; } if (strncmp("probeonly", parsestring, length) == 0) { dasd_probeonly = 1; - MESSAGE(KERN_INFO, "%s", - "turning to probeonly mode"); + pr_info("The probeonly mode has been activated\n"); return residual_str; } if (strncmp("nopav", parsestring, length) == 0) { if (MACHINE_IS_VM) - MESSAGE(KERN_INFO, "%s", "'nopav' not supported on VM"); + pr_info("'nopav' is not supported on z/VM\n"); else { dasd_nopav = 1; - MESSAGE(KERN_INFO, "%s", "disable PAV mode"); + pr_info("PAV support has be deactivated\n"); } return residual_str; } if (strncmp("nofcx", parsestring, length) == 0) { dasd_nofcx = 1; - MESSAGE(KERN_INFO, "%s", "disable High Performance Ficon"); + pr_info("High Performance FICON support has been " + "deactivated\n"); return residual_str; } if (strncmp("fixedbuffers", parsestring, length) == 0) { @@ -287,10 +287,10 @@ dasd_parse_keyword( char *parsestring ) { PAGE_SIZE, SLAB_CACHE_DMA, NULL); if (!dasd_page_cache) - MESSAGE(KERN_WARNING, "%s", "Failed to create slab, " + DBF_EVENT(DBF_WARNING, "%s", "Failed to create slab, " "fixed buffer mode disabled."); else - MESSAGE (KERN_INFO, "%s", + DBF_EVENT(DBF_INFO, "%s", "turning on fixed buffer mode"); return residual_str; } @@ -328,7 +328,7 @@ dasd_parse_range( char *parsestring ) { (from_id0 != to_id0 || from_id1 != to_id1 || from > to)) rc = -EINVAL; if (rc) { - MESSAGE(KERN_ERR, "Invalid device range %s", parsestring); + pr_err("%s is not a valid device range\n", parsestring); return ERR_PTR(rc); } features = dasd_feature_list(str, &str); @@ -347,8 +347,8 @@ dasd_parse_range( char *parsestring ) { return str + 1; if (*str == '\0') return str; - MESSAGE(KERN_WARNING, - "junk at end of dasd parameter string: %s\n", str); + pr_warning("The dasd= parameter value %s has an invalid ending\n", + str); return ERR_PTR(-EINVAL); } diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index ef2a5695205..b9a7f773344 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -8,6 +8,8 @@ * */ +#define KMSG_COMPONENT "dasd" + #include #include #include @@ -144,8 +146,8 @@ dasd_diag_erp(struct dasd_device *device) mdsk_term_io(device); rc = mdsk_init_io(device, device->block->bp_block, 0, NULL); if (rc) - DEV_MESSAGE(KERN_WARNING, device, "DIAG ERP unsuccessful, " - "rc=%d", rc); + dev_warn(&device->cdev->dev, "DIAG ERP failed with " + "rc=%d\n", rc); } /* Start a given request at the device. Return zero on success, non-zero @@ -160,7 +162,7 @@ dasd_start_diag(struct dasd_ccw_req * cqr) device = cqr->startdev; if (cqr->retries < 0) { - DEV_MESSAGE(KERN_WARNING, device, "DIAG start_IO: request %p " + DBF_DEV_EVENT(DBF_ERR, device, "DIAG start_IO: request %p " "- no retry left)", cqr); cqr->status = DASD_CQR_ERROR; return -EIO; @@ -195,7 +197,7 @@ dasd_start_diag(struct dasd_ccw_req * cqr) break; default: /* Error condition */ cqr->status = DASD_CQR_QUEUED; - DEV_MESSAGE(KERN_WARNING, device, "dia250 returned rc=%d", rc); + DBF_DEV_EVENT(DBF_WARNING, device, "dia250 returned rc=%d", rc); dasd_diag_erp(device); rc = -EIO; break; @@ -243,13 +245,14 @@ dasd_ext_handler(__u16 code) return; } if (!ip) { /* no intparm: unsolicited interrupt */ - MESSAGE(KERN_DEBUG, "%s", "caught unsolicited interrupt"); + DBF_EVENT(DBF_NOTICE, "%s", "caught unsolicited " + "interrupt"); return; } cqr = (struct dasd_ccw_req *) ip; device = (struct dasd_device *) cqr->startdev; if (strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { - DEV_MESSAGE(KERN_WARNING, device, + DBF_DEV_EVENT(DBF_WARNING, device, " magic number of dasd_ccw_req 0x%08X doesn't" " match discipline 0x%08X", cqr->magic, *(int *) (&device->discipline->name)); @@ -281,15 +284,11 @@ dasd_ext_handler(__u16 code) rc = dasd_start_diag(next); if (rc == 0) expires = next->expires; - else if (rc != -EACCES) - DEV_MESSAGE(KERN_WARNING, device, "%s", - "Interrupt fastpath " - "failed!"); } } } else { cqr->status = DASD_CQR_QUEUED; - DEV_MESSAGE(KERN_WARNING, device, "interrupt status for " + DBF_DEV_EVENT(DBF_DEBUG, device, "interrupt status for " "request %p was %d (%d retries left)", cqr, status, cqr->retries); dasd_diag_erp(device); @@ -322,8 +321,9 @@ dasd_diag_check_device(struct dasd_device *device) if (private == NULL) { private = kzalloc(sizeof(struct dasd_diag_private),GFP_KERNEL); if (private == NULL) { - DEV_MESSAGE(KERN_WARNING, device, "%s", - "memory allocation failed for private data"); + DBF_DEV_EVENT(DBF_WARNING, device, "%s", + "Allocating memory for private DASD data " + "failed\n"); return -ENOMEM; } ccw_device_get_id(device->cdev, &private->dev_id); @@ -331,7 +331,7 @@ dasd_diag_check_device(struct dasd_device *device) } block = dasd_alloc_block(); if (IS_ERR(block)) { - DEV_MESSAGE(KERN_WARNING, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "could not allocate dasd block structure"); device->private = NULL; kfree(private); @@ -347,7 +347,7 @@ dasd_diag_check_device(struct dasd_device *device) rc = diag210((struct diag210 *) rdc_data); if (rc) { - DEV_MESSAGE(KERN_WARNING, device, "failed to retrieve device " + DBF_DEV_EVENT(DBF_WARNING, device, "failed to retrieve device " "information (rc=%d)", rc); rc = -EOPNOTSUPP; goto out; @@ -362,8 +362,8 @@ dasd_diag_check_device(struct dasd_device *device) private->pt_block = 2; break; default: - DEV_MESSAGE(KERN_WARNING, device, "unsupported device class " - "(class=%d)", private->rdc_data.vdev_class); + dev_warn(&device->cdev->dev, "Device type %d is not supported " + "in DIAG mode\n", private->rdc_data.vdev_class); rc = -EOPNOTSUPP; goto out; } @@ -380,7 +380,7 @@ dasd_diag_check_device(struct dasd_device *device) /* figure out blocksize of device */ label = (struct vtoc_cms_label *) get_zeroed_page(GFP_KERNEL); if (label == NULL) { - DEV_MESSAGE(KERN_WARNING, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "No memory to allocate initialization request"); rc = -ENOMEM; goto out; @@ -404,8 +404,8 @@ dasd_diag_check_device(struct dasd_device *device) private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT; rc = dia250(&private->iob, RW_BIO); if (rc == 3) { - DEV_MESSAGE(KERN_WARNING, device, "%s", - "DIAG call failed"); + dev_warn(&device->cdev->dev, + "A 64-bit DIAG call failed\n"); rc = -EOPNOTSUPP; goto out_label; } @@ -414,8 +414,8 @@ dasd_diag_check_device(struct dasd_device *device) break; } if (bsize > PAGE_SIZE) { - DEV_MESSAGE(KERN_WARNING, device, "device access failed " - "(rc=%d)", rc); + dev_warn(&device->cdev->dev, "Accessing the DASD failed because" + " of an incorrect format (rc=%d)\n", rc); rc = -EIO; goto out_label; } @@ -433,15 +433,15 @@ dasd_diag_check_device(struct dasd_device *device) block->s2b_shift++; rc = mdsk_init_io(device, block->bp_block, 0, NULL); if (rc) { - DEV_MESSAGE(KERN_WARNING, device, "DIAG initialization " - "failed (rc=%d)", rc); + dev_warn(&device->cdev->dev, "DIAG initialization " + "failed with rc=%d\n", rc); rc = -EIO; } else { - DEV_MESSAGE(KERN_INFO, device, - "(%ld B/blk): %ldkB", - (unsigned long) block->bp_block, - (unsigned long) (block->blocks << - block->s2b_shift) >> 1); + dev_info(&device->cdev->dev, + "New DASD with %ld byte/block, total size %ld KB\n", + (unsigned long) block->bp_block, + (unsigned long) (block->blocks << + block->s2b_shift) >> 1); } out_label: free_page((long) label); @@ -595,7 +595,7 @@ static void dasd_diag_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, struct irb *stat) { - DEV_MESSAGE(KERN_ERR, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "dump sense not available for DIAG data"); } @@ -621,10 +621,8 @@ static int __init dasd_diag_init(void) { if (!MACHINE_IS_VM) { - MESSAGE_LOG(KERN_INFO, - "Machine is not VM: %s " - "discipline not initializing", - dasd_diag_discipline.name); + pr_info("Discipline %s cannot be used without z/VM\n", + dasd_diag_discipline.name); return -ENODEV; } ASCEBC(dasd_diag_discipline.ebcname, 4); diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 1e4c89b8b30..21254793c60 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -11,6 +11,8 @@ * */ +#define KMSG_COMPONENT "dasd" + #include #include #include @@ -87,7 +89,7 @@ dasd_eckd_probe (struct ccw_device *cdev) /* set ECKD specific ccw-device options */ ret = ccw_device_set_options(cdev, CCWDEV_ALLOW_FORCE); if (ret) { - printk(KERN_WARNING + DBF_EVENT(DBF_WARNING, "dasd_eckd_probe: could not set ccw-device options " "for %s\n", dev_name(&cdev->dev)); return ret; @@ -248,8 +250,8 @@ define_extent(struct ccw1 *ccw, struct DE_eckd_data *data, unsigned int trk, rc = check_XRC (ccw, data, device); break; default: - DBF_DEV_EVENT(DBF_ERR, device, - "PFX LRE unknown opcode 0x%x", cmd); + dev_err(&device->cdev->dev, + "0x%x is not a known command\n", cmd); break; } @@ -647,7 +649,8 @@ locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, unsigned int trk, data->operation.operation = 0x0b; break; default: - DEV_MESSAGE(KERN_ERR, device, "unknown opcode 0x%x", cmd); + DBF_DEV_EVENT(DBF_ERR, device, "unknown locate record " + "opcode 0x%x", cmd); } set_ch_t(&data->seek_addr, trk / private->rdc_data.trk_per_cyl, @@ -742,8 +745,8 @@ static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device, cqr = dasd_smalloc_request("ECKD", 1 /* RCD */, ciw->count, device); if (IS_ERR(cqr)) { - DEV_MESSAGE(KERN_WARNING, device, "%s", - "Could not allocate RCD request"); + DBF_DEV_EVENT(DBF_WARNING, device, "%s", + "Could not allocate RCD request"); return cqr; } @@ -893,14 +896,16 @@ static int dasd_eckd_read_conf(struct dasd_device *device) rc = dasd_eckd_read_conf_lpm(device, &conf_data, &conf_len, lpm); if (rc && rc != -EOPNOTSUPP) { /* -EOPNOTSUPP is ok */ - MESSAGE(KERN_WARNING, - "Read configuration data returned " - "error %d", rc); + DBF_EVENT(DBF_WARNING, + "Read configuration data returned " + "error %d for device: %s", rc, + dev_name(&device->cdev->dev)); return rc; } if (conf_data == NULL) { - MESSAGE(KERN_WARNING, "%s", "No configuration " - "data retrieved"); + DBF_EVENT(DBF_WARNING, "No configuration " + "data retrieved for device: %s", + dev_name(&device->cdev->dev)); continue; /* no error */ } /* save first valid configuration data */ @@ -947,8 +952,9 @@ static int dasd_eckd_read_features(struct dasd_device *device) sizeof(struct dasd_rssd_features)), device); if (IS_ERR(cqr)) { - DEV_MESSAGE(KERN_WARNING, device, "%s", - "Could not allocate initialization request"); + DBF_EVENT(DBF_WARNING, "Could not allocate initialization " + "request for device: %s", + dev_name(&device->cdev->dev)); return PTR_ERR(cqr); } cqr->startdev = device; @@ -1009,7 +1015,7 @@ static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device, device); if (IS_ERR(cqr)) { - DEV_MESSAGE(KERN_WARNING, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Could not allocate PSF-SSC request"); return cqr; } @@ -1074,10 +1080,10 @@ static int dasd_eckd_validate_server(struct dasd_device *device) /* may be requested feature is not available on server, * therefore just report error and go ahead */ private = (struct dasd_eckd_private *) device->private; - DEV_MESSAGE(KERN_INFO, device, - "PSF-SSC on storage subsystem %s.%s.%04x returned rc=%d", - private->uid.vendor, private->uid.serial, - private->uid.ssid, rc); + DBF_EVENT(DBF_WARNING, "PSF-SSC on storage subsystem %s.%s.%04x " + "returned rc=%d for device: %s", + private->uid.vendor, private->uid.serial, + private->uid.ssid, rc, dev_name(&device->cdev->dev)); /* RE-Read Configuration Data */ return dasd_eckd_read_conf(device); } @@ -1099,9 +1105,9 @@ dasd_eckd_check_characteristics(struct dasd_device *device) private = kzalloc(sizeof(struct dasd_eckd_private), GFP_KERNEL | GFP_DMA); if (private == NULL) { - DEV_MESSAGE(KERN_WARNING, device, "%s", - "memory allocation failed for private " - "data"); + dev_warn(&device->cdev->dev, + "Allocating memory for private DASD data " + "failed\n"); return -ENOMEM; } device->private = (void *) private; @@ -1126,8 +1132,9 @@ dasd_eckd_check_characteristics(struct dasd_device *device) if (private->uid.type == UA_BASE_DEVICE) { block = dasd_alloc_block(); if (IS_ERR(block)) { - DEV_MESSAGE(KERN_WARNING, device, "%s", - "could not allocate dasd block structure"); + DBF_EVENT(DBF_WARNING, "could not allocate dasd " + "block structure for device: %s", + dev_name(&device->cdev->dev)); rc = PTR_ERR(block); goto out_err1; } @@ -1158,9 +1165,9 @@ dasd_eckd_check_characteristics(struct dasd_device *device) memset(rdc_data, 0, sizeof(rdc_data)); rc = dasd_generic_read_dev_chars(device, "ECKD", &rdc_data, 64); if (rc) { - DEV_MESSAGE(KERN_WARNING, device, - "Read device characteristics returned " - "rc=%d", rc); + DBF_EVENT(DBF_WARNING, + "Read device characteristics failed, rc=%d for " + "device: %s", rc, dev_name(&device->cdev->dev)); goto out_err3; } /* find the vaild cylinder size */ @@ -1170,15 +1177,15 @@ dasd_eckd_check_characteristics(struct dasd_device *device) else private->real_cyl = private->rdc_data.no_cyl; - DEV_MESSAGE(KERN_INFO, device, - "%04X/%02X(CU:%04X/%02X) Cyl:%d Head:%d Sec:%d", - private->rdc_data.dev_type, - private->rdc_data.dev_model, - private->rdc_data.cu_type, - private->rdc_data.cu_model.model, + dev_info(&device->cdev->dev, "New DASD %04X/%02X (CU %04X/%02X) " + "with %d cylinders, %d heads, %d sectors\n", + private->rdc_data.dev_type, + private->rdc_data.dev_model, + private->rdc_data.cu_type, + private->rdc_data.cu_model.model, private->real_cyl, - private->rdc_data.trk_per_cyl, - private->rdc_data.sec_per_trk); + private->rdc_data.trk_per_cyl, + private->rdc_data.sec_per_trk); return 0; out_err3: @@ -1319,8 +1326,8 @@ dasd_eckd_end_analysis(struct dasd_block *block) status = private->init_cqr_status; private->init_cqr_status = -1; if (status != DASD_CQR_DONE) { - DEV_MESSAGE(KERN_WARNING, device, "%s", - "volume analysis returned unformatted disk"); + dev_warn(&device->cdev->dev, + "The DASD is not formatted\n"); return -EMEDIUMTYPE; } @@ -1348,8 +1355,8 @@ dasd_eckd_end_analysis(struct dasd_block *block) count_area = &private->count_area[0]; } else { if (private->count_area[3].record == 1) - DEV_MESSAGE(KERN_WARNING, device, "%s", - "Trk 0: no records after VTOC!"); + dev_warn(&device->cdev->dev, + "Track 0 has no records following the VTOC\n"); } if (count_area != NULL && count_area->kl == 0) { /* we found notthing violating our disk layout */ @@ -1357,8 +1364,8 @@ dasd_eckd_end_analysis(struct dasd_block *block) block->bp_block = count_area->dl; } if (block->bp_block == 0) { - DEV_MESSAGE(KERN_WARNING, device, "%s", - "Volume has incompatible disk layout"); + dev_warn(&device->cdev->dev, + "The disk layout of the DASD is not supported\n"); return -EMEDIUMTYPE; } block->s2b_shift = 0; /* bits to shift 512 to get a block */ @@ -1370,15 +1377,15 @@ dasd_eckd_end_analysis(struct dasd_block *block) private->rdc_data.trk_per_cyl * blk_per_trk); - DEV_MESSAGE(KERN_INFO, device, - "(%dkB blks): %dkB at %dkB/trk %s", - (block->bp_block >> 10), - ((private->real_cyl * - private->rdc_data.trk_per_cyl * - blk_per_trk * (block->bp_block >> 9)) >> 1), - ((blk_per_trk * block->bp_block) >> 10), - private->uses_cdl ? - "compatible disk layout" : "linux disk layout"); + dev_info(&device->cdev->dev, + "DASD with %d KB/block, %d KB total size, %d KB/track, " + "%s\n", (block->bp_block >> 10), + ((private->real_cyl * + private->rdc_data.trk_per_cyl * + blk_per_trk * (block->bp_block >> 9)) >> 1), + ((blk_per_trk * block->bp_block) >> 10), + private->uses_cdl ? + "compatible disk layout" : "linux disk layout"); return 0; } @@ -1444,19 +1451,19 @@ dasd_eckd_format_device(struct dasd_device * device, /* Sanity checks. */ if (fdata->start_unit >= (private->real_cyl * private->rdc_data.trk_per_cyl)) { - DEV_MESSAGE(KERN_INFO, device, "Track no %u too big!", - fdata->start_unit); + dev_warn(&device->cdev->dev, "Start track number %d used in " + "formatting is too big\n", fdata->start_unit); return ERR_PTR(-EINVAL); } if (fdata->start_unit > fdata->stop_unit) { - DEV_MESSAGE(KERN_INFO, device, "Track %u reached! ending.", - fdata->start_unit); + dev_warn(&device->cdev->dev, "Start track %d used in " + "formatting exceeds end track\n", fdata->start_unit); return ERR_PTR(-EINVAL); } if (dasd_check_blocksize(fdata->blksize) != 0) { - DEV_MESSAGE(KERN_WARNING, device, - "Invalid blocksize %u...terminating!", - fdata->blksize); + dev_warn(&device->cdev->dev, + "The DASD cannot be formatted with block size %d\n", + fdata->blksize); return ERR_PTR(-EINVAL); } @@ -1500,8 +1507,8 @@ dasd_eckd_format_device(struct dasd_device * device, sizeof(struct eckd_count); break; default: - DEV_MESSAGE(KERN_WARNING, device, "Invalid flags 0x%x.", - fdata->intensity); + dev_warn(&device->cdev->dev, "An I/O control call used " + "incorrect flags 0x%x\n", fdata->intensity); return ERR_PTR(-EINVAL); } /* Allocate the format ccw request. */ @@ -1696,13 +1703,14 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device, if (!sense) { /* just report other unsolicited interrupts */ - DEV_MESSAGE(KERN_ERR, device, "%s", + DBF_DEV_EVENT(DBF_ERR, device, "%s", "unsolicited interrupt received"); } else { - DEV_MESSAGE(KERN_ERR, device, "%s", + DBF_DEV_EVENT(DBF_ERR, device, "%s", "unsolicited interrupt received " "(sense available)"); - device->discipline->dump_sense(device, NULL, irb); + device->discipline->dump_sense_dbf(device, NULL, irb, + "unsolicited"); } dasd_schedule_device_bh(device); @@ -2553,7 +2561,7 @@ dasd_eckd_release(struct dasd_device *device) cqr = dasd_smalloc_request(dasd_eckd_discipline.name, 1, 32, device); if (IS_ERR(cqr)) { - DEV_MESSAGE(KERN_WARNING, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Could not allocate initialization request"); return PTR_ERR(cqr); } @@ -2596,7 +2604,7 @@ dasd_eckd_reserve(struct dasd_device *device) cqr = dasd_smalloc_request(dasd_eckd_discipline.name, 1, 32, device); if (IS_ERR(cqr)) { - DEV_MESSAGE(KERN_WARNING, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Could not allocate initialization request"); return PTR_ERR(cqr); } @@ -2638,7 +2646,7 @@ dasd_eckd_steal_lock(struct dasd_device *device) cqr = dasd_smalloc_request(dasd_eckd_discipline.name, 1, 32, device); if (IS_ERR(cqr)) { - DEV_MESSAGE(KERN_WARNING, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Could not allocate initialization request"); return PTR_ERR(cqr); } @@ -2680,7 +2688,7 @@ dasd_eckd_performance(struct dasd_device *device, void __user *argp) sizeof(struct dasd_rssd_perf_stats_t)), device); if (IS_ERR(cqr)) { - DEV_MESSAGE(KERN_WARNING, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Could not allocate initialization request"); return PTR_ERR(cqr); } @@ -2770,9 +2778,9 @@ dasd_eckd_set_attrib(struct dasd_device *device, void __user *argp) return -EFAULT; private->attrib = attrib; - DEV_MESSAGE(KERN_INFO, device, - "cache operation mode set to %x (%i cylinder prestage)", - private->attrib.operation, private->attrib.nr_cyl); + dev_info(&device->cdev->dev, + "The DASD cache mode was set to %x (%i cylinder prestage)\n", + private->attrib.operation, private->attrib.nr_cyl); return 0; } @@ -2823,7 +2831,7 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp) /* setup CCWs for PSF + RSSD */ cqr = dasd_smalloc_request("ECKD", 2 , 0, device); if (IS_ERR(cqr)) { - DEV_MESSAGE(KERN_WARNING, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Could not allocate initialization request"); rc = PTR_ERR(cqr); goto out_free; @@ -2932,6 +2940,49 @@ dasd_eckd_dump_ccw_range(struct ccw1 *from, struct ccw1 *to, char *page) return len; } +static void +dasd_eckd_dump_sense_dbf(struct dasd_device *device, struct dasd_ccw_req *req, + struct irb *irb, char *reason) +{ + u64 *sense; + int sl; + struct tsb *tsb; + + sense = NULL; + tsb = NULL; + if (req && scsw_is_tm(&req->irb.scsw)) { + if (irb->scsw.tm.tcw) + tsb = tcw_get_tsb( + (struct tcw *)(unsigned long)irb->scsw.tm.tcw); + if (tsb && (irb->scsw.tm.fcxs == 0x01)) { + switch (tsb->flags & 0x07) { + case 1: /* tsa_iostat */ + sense = (u64 *)tsb->tsa.iostat.sense; + break; + case 2: /* ts_ddpc */ + sense = (u64 *)tsb->tsa.ddpc.sense; + break; + case 3: /* tsa_intrg */ + break; + } + } + } else { + if (irb->esw.esw0.erw.cons) + sense = (u64 *)irb->ecw; + } + if (sense) { + for (sl = 0; sl < 4; sl++) { + DBF_DEV_EVENT(DBF_EMERG, device, + "%s: %016llx %016llx %016llx %016llx", + reason, sense[0], sense[1], sense[2], + sense[3]); + } + } else { + DBF_DEV_EVENT(DBF_EMERG, device, "%s", + "SORRY - NO VALID SENSE AVAILABLE\n"); + } +} + /* * Print sense data and related channel program. * Parts are printed because printk buffer is only 1024 bytes. @@ -2945,8 +2996,8 @@ static void dasd_eckd_dump_sense_ccw(struct dasd_device *device, page = (char *) get_zeroed_page(GFP_ATOMIC); if (page == NULL) { - DEV_MESSAGE(KERN_ERR, device, " %s", - "No memory to dump sense data"); + DBF_DEV_EVENT(DBF_WARNING, device, "%s", + "No memory to dump sense data\n"); return; } /* dump the sense data */ @@ -3047,7 +3098,7 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device, page = (char *) get_zeroed_page(GFP_ATOMIC); if (page == NULL) { - DEV_MESSAGE(KERN_ERR, device, " %s", + DBF_DEV_EVENT(DBF_WARNING, device, " %s", "No memory to dump sense data"); return; } @@ -3206,6 +3257,7 @@ static struct dasd_discipline dasd_eckd_discipline = { .build_cp = dasd_eckd_build_alias_cp, .free_cp = dasd_eckd_free_alias_cp, .dump_sense = dasd_eckd_dump_sense, + .dump_sense_dbf = dasd_eckd_dump_sense_dbf, .fill_info = dasd_eckd_fill_info, .ioctl = dasd_eckd_ioctl, }; diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c index 9ce4209552a..c24c8c30380 100644 --- a/drivers/s390/block/dasd_eer.c +++ b/drivers/s390/block/dasd_eer.c @@ -6,6 +6,8 @@ * Author(s): Stefan Weinhuber */ +#define KMSG_COMPONENT "dasd" + #include #include #include @@ -539,7 +541,7 @@ static int dasd_eer_open(struct inode *inp, struct file *filp) if (eerb->buffer_page_count < 1 || eerb->buffer_page_count > INT_MAX / PAGE_SIZE) { kfree(eerb); - MESSAGE(KERN_WARNING, "can't open device since module " + DBF_EVENT(DBF_WARNING, "can't open device since module " "parameter eer_pages is smaller than 1 or" " bigger than %d", (int)(INT_MAX / PAGE_SIZE)); unlock_kernel(); @@ -692,7 +694,7 @@ int __init dasd_eer_init(void) if (rc) { kfree(dasd_eer_dev); dasd_eer_dev = NULL; - MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not " + DBF_EVENT(DBF_ERR, "%s", "dasd_eer_init could not " "register misc device"); return rc; } diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c index 8f10000851a..d970ce2814b 100644 --- a/drivers/s390/block/dasd_erp.c +++ b/drivers/s390/block/dasd_erp.c @@ -9,6 +9,8 @@ * */ +#define KMSG_COMPONENT "dasd" + #include #include @@ -91,14 +93,14 @@ dasd_default_erp_action(struct dasd_ccw_req *cqr) /* just retry - there is nothing to save ... I got no sense data.... */ if (cqr->retries > 0) { - DEV_MESSAGE (KERN_DEBUG, device, + DBF_DEV_EVENT(DBF_DEBUG, device, "default ERP called (%i retries left)", cqr->retries); cqr->lpm = LPM_ANYPATH; cqr->status = DASD_CQR_FILLED; } else { - DEV_MESSAGE (KERN_WARNING, device, "%s", - "default ERP called (NO retry left)"); + dev_err(&device->cdev->dev, + "default ERP has run out of retries and failed\n"); cqr->status = DASD_CQR_FAILED; cqr->stopclk = get_clock(); } @@ -162,8 +164,21 @@ dasd_log_sense(struct dasd_ccw_req *cqr, struct irb *irb) device->discipline->dump_sense(device, cqr, irb); } +void +dasd_log_sense_dbf(struct dasd_ccw_req *cqr, struct irb *irb) +{ + struct dasd_device *device; + + device = cqr->startdev; + /* dump sense data to s390 debugfeature*/ + if (device->discipline && device->discipline->dump_sense_dbf) + device->discipline->dump_sense_dbf(device, cqr, irb, "log"); +} +EXPORT_SYMBOL(dasd_log_sense_dbf); + EXPORT_SYMBOL(dasd_default_erp_action); EXPORT_SYMBOL(dasd_default_erp_postaction); EXPORT_SYMBOL(dasd_alloc_erp_request); EXPORT_SYMBOL(dasd_free_erp_request); EXPORT_SYMBOL(dasd_log_sense); + diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index f1d17602169..a3eb6fd1467 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c @@ -6,6 +6,8 @@ * */ +#define KMSG_COMPONENT "dasd" + #include #include #include @@ -128,17 +130,18 @@ dasd_fba_check_characteristics(struct dasd_device *device) private = kzalloc(sizeof(struct dasd_fba_private), GFP_KERNEL | GFP_DMA); if (private == NULL) { - DEV_MESSAGE(KERN_WARNING, device, "%s", - "memory allocation failed for private " - "data"); + dev_warn(&device->cdev->dev, + "Allocating memory for private DASD " + "data failed\n"); return -ENOMEM; } device->private = (void *) private; } block = dasd_alloc_block(); if (IS_ERR(block)) { - DEV_MESSAGE(KERN_WARNING, device, "%s", - "could not allocate dasd block structure"); + DBF_EVENT(DBF_WARNING, "could not allocate dasd block " + "structure for device: %s", + dev_name(&device->cdev->dev)); device->private = NULL; kfree(private); return PTR_ERR(block); @@ -150,9 +153,9 @@ dasd_fba_check_characteristics(struct dasd_device *device) rdc_data = (void *) &(private->rdc_data); rc = dasd_generic_read_dev_chars(device, "FBA ", &rdc_data, 32); if (rc) { - DEV_MESSAGE(KERN_WARNING, device, - "Read device characteristics returned error %d", - rc); + DBF_EVENT(DBF_WARNING, "Read device characteristics returned " + "error %d for device: %s", + rc, dev_name(&device->cdev->dev)); device->block = NULL; dasd_free_block(block); device->private = NULL; @@ -160,15 +163,16 @@ dasd_fba_check_characteristics(struct dasd_device *device) return rc; } - DEV_MESSAGE(KERN_INFO, device, - "%04X/%02X(CU:%04X/%02X) %dMB at(%d B/blk)", - cdev->id.dev_type, - cdev->id.dev_model, - cdev->id.cu_type, - cdev->id.cu_model, - ((private->rdc_data.blk_bdsa * - (private->rdc_data.blk_size >> 9)) >> 11), - private->rdc_data.blk_size); + dev_info(&device->cdev->dev, + "New FBA DASD %04X/%02X (CU %04X/%02X) with %d MB " + "and %d B/blk\n", + cdev->id.dev_type, + cdev->id.dev_model, + cdev->id.cu_type, + cdev->id.cu_model, + ((private->rdc_data.blk_bdsa * + (private->rdc_data.blk_size >> 9)) >> 11), + private->rdc_data.blk_size); return 0; } @@ -180,7 +184,7 @@ static int dasd_fba_do_analysis(struct dasd_block *block) private = (struct dasd_fba_private *) block->base->private; rc = dasd_check_blocksize(private->rdc_data.blk_size); if (rc) { - DEV_MESSAGE(KERN_INFO, block->base, "unknown blocksize %d", + DBF_DEV_EVENT(DBF_WARNING, block->base, "unknown blocksize %d", private->rdc_data.blk_size); return rc; } @@ -215,7 +219,7 @@ dasd_fba_erp_postaction(struct dasd_ccw_req * cqr) if (cqr->function == dasd_default_erp_action) return dasd_default_erp_postaction; - DEV_MESSAGE(KERN_WARNING, cqr->startdev, "unknown ERP action %p", + DBF_DEV_EVENT(DBF_WARNING, cqr->startdev, "unknown ERP action %p", cqr->function); return NULL; } @@ -233,9 +237,9 @@ static void dasd_fba_handle_unsolicited_interrupt(struct dasd_device *device, } /* check for unsolicited interrupts */ - DEV_MESSAGE(KERN_DEBUG, device, "%s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "unsolicited interrupt received"); - device->discipline->dump_sense(device, NULL, irb); + device->discipline->dump_sense_dbf(device, NULL, irb, "unsolicited"); dasd_schedule_device_bh(device); return; }; @@ -436,6 +440,25 @@ dasd_fba_fill_info(struct dasd_device * device, return 0; } +static void +dasd_fba_dump_sense_dbf(struct dasd_device *device, struct dasd_ccw_req *req, + struct irb *irb, char *reason) +{ + int sl; + if (irb->esw.esw0.erw.cons) { + for (sl = 0; sl < 4; sl++) { + DBF_DEV_EVENT(DBF_EMERG, device, + "%s: %08x %08x %08x %08x", + reason, irb->ecw[8 * 0], irb->ecw[8 * 1], + irb->ecw[8 * 2], irb->ecw[8 * 3]); + } + } else { + DBF_DEV_EVENT(DBF_EMERG, device, "%s", + "SORRY - NO VALID SENSE AVAILABLE\n"); + } +} + + static void dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, struct irb *irb) @@ -446,7 +469,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, page = (char *) get_zeroed_page(GFP_ATOMIC); if (page == NULL) { - DEV_MESSAGE(KERN_ERR, device, " %s", + DBF_DEV_EVENT(DBF_WARNING, device, "%s", "No memory to dump sense data"); return; } @@ -476,8 +499,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, len += sprintf(page + len, KERN_ERR PRINTK_HEADER " SORRY - NO VALID SENSE AVAILABLE\n"); } - MESSAGE_LOG(KERN_ERR, "%s", - page + sizeof(KERN_ERR PRINTK_HEADER)); + printk(KERN_ERR "%s", page); /* dump the Channel Program */ /* print first CCWs (maximum 8) */ @@ -498,8 +520,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, len += sprintf(page + len, "\n"); act++; } - MESSAGE_LOG(KERN_ERR, "%s", - page + sizeof(KERN_ERR PRINTK_HEADER)); + printk(KERN_ERR "%s", page); /* print failing CCW area */ @@ -540,8 +561,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, act++; } if (len > 0) - MESSAGE_LOG(KERN_ERR, "%s", - page + sizeof(KERN_ERR PRINTK_HEADER)); + printk(KERN_ERR "%s", page); free_page((unsigned long) page); } @@ -576,6 +596,7 @@ static struct dasd_discipline dasd_fba_discipline = { .build_cp = dasd_fba_build_cp, .free_cp = dasd_fba_free_cp, .dump_sense = dasd_fba_dump_sense, + .dump_sense_dbf = dasd_fba_dump_sense_dbf, .fill_info = dasd_fba_fill_info, }; diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c index e99d566b69c..d3198303b93 100644 --- a/drivers/s390/block/dasd_genhd.c +++ b/drivers/s390/block/dasd_genhd.c @@ -11,6 +11,8 @@ * */ +#define KMSG_COMPONENT "dasd" + #include #include #include @@ -163,9 +165,8 @@ int dasd_gendisk_init(void) /* Register to static dasd major 94 */ rc = register_blkdev(DASD_MAJOR, "dasd"); if (rc != 0) { - MESSAGE(KERN_WARNING, - "Couldn't register successfully to " - "major no %d", DASD_MAJOR); + pr_warning("Registering the device driver with major number " + "%d failed\n", DASD_MAJOR); return rc; } return 0; diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 7b314c1d471..c1e487f774c 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -112,6 +112,9 @@ do { \ d_data); \ } while(0) +/* limit size for an errorstring */ +#define ERRORLENGTH 30 + /* definition of dbf debug levels */ #define DBF_EMERG 0 /* system is unusable */ #define DBF_ALERT 1 /* action must be taken immediately */ @@ -281,6 +284,8 @@ struct dasd_discipline { dasd_erp_fn_t(*erp_postaction) (struct dasd_ccw_req *); void (*dump_sense) (struct dasd_device *, struct dasd_ccw_req *, struct irb *); + void (*dump_sense_dbf) (struct dasd_device *, struct dasd_ccw_req *, + struct irb *, char *); void (*handle_unsolicited_interrupt) (struct dasd_device *, struct irb *); @@ -626,6 +631,7 @@ struct dasd_ccw_req *dasd_alloc_erp_request(char *, int, int, struct dasd_device *); void dasd_free_erp_request(struct dasd_ccw_req *, struct dasd_device *); void dasd_log_sense(struct dasd_ccw_req *, struct irb *); +void dasd_log_sense_dbf(struct dasd_ccw_req *cqr, struct irb *irb); /* externals in dasd_3990_erp.c */ struct dasd_ccw_req *dasd_3990_erp_action(struct dasd_ccw_req *); diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index a3bbdb807ba..4ce3f72ee1c 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -9,6 +9,9 @@ * * i/o controls for the dasd driver. */ + +#define KMSG_COMPONENT "dasd" + #include #include #include @@ -94,7 +97,8 @@ static int dasd_ioctl_quiesce(struct dasd_block *block) if (!capable (CAP_SYS_ADMIN)) return -EACCES; - DEV_MESSAGE(KERN_DEBUG, base, "%s", "Quiesce IO on device"); + dev_info(&base->cdev->dev, "The DASD has been put in the quiesce " + "state\n"); spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags); base->stopped |= DASD_STOPPED_QUIESCE; spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags); @@ -103,7 +107,7 @@ static int dasd_ioctl_quiesce(struct dasd_block *block) /* - * Quiesce device. + * Resume device. */ static int dasd_ioctl_resume(struct dasd_block *block) { @@ -114,7 +118,8 @@ static int dasd_ioctl_resume(struct dasd_block *block) if (!capable (CAP_SYS_ADMIN)) return -EACCES; - DEV_MESSAGE(KERN_DEBUG, base, "%s", "resume IO on device"); + dev_info(&base->cdev->dev, "I/O operations have been resumed " + "on the DASD\n"); spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags); base->stopped &= ~DASD_STOPPED_QUIESCE; spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags); @@ -140,8 +145,8 @@ static int dasd_format(struct dasd_block *block, struct format_data_t *fdata) return -EPERM; if (base->state != DASD_STATE_BASIC) { - DEV_MESSAGE(KERN_WARNING, base, "%s", - "dasd_format: device is not disabled! "); + dev_warn(&base->cdev->dev, + "The DASD cannot be formatted while it is enabled\n"); return -EBUSY; } @@ -169,10 +174,9 @@ static int dasd_format(struct dasd_block *block, struct format_data_t *fdata) dasd_sfree_request(cqr, cqr->memdev); if (rc) { if (rc != -ERESTARTSYS) - DEV_MESSAGE(KERN_ERR, base, - " Formatting of unit %u failed " - "with rc = %d", - fdata->start_unit, rc); + dev_err(&base->cdev->dev, + "Formatting unit %d failed with " + "rc=%d\n", fdata->start_unit, rc); return rc; } fdata->start_unit++; @@ -199,8 +203,9 @@ dasd_ioctl_format(struct block_device *bdev, void __user *argp) if (copy_from_user(&fdata, argp, sizeof(struct format_data_t))) return -EFAULT; if (bdev != bdev->bd_contains) { - DEV_MESSAGE(KERN_WARNING, block->base, "%s", - "Cannot low-level format a partition"); + dev_warn(&block->base->cdev->dev, + "The specified DASD is a partition and cannot be " + "formatted\n"); return -EINVAL; } return dasd_format(block, &fdata); diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index 0aa569419d5..2080ba6a69b 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c @@ -11,6 +11,8 @@ * */ +#define KMSG_COMPONENT "dasd" + #include #include #include @@ -267,7 +269,7 @@ dasd_statistics_write(struct file *file, const char __user *user_buf, buffer = dasd_get_user_string(user_buf, user_len); if (IS_ERR(buffer)) return PTR_ERR(buffer); - MESSAGE_LOG(KERN_INFO, "/proc/dasd/statictics: '%s'", buffer); + DBF_EVENT(DBF_DEBUG, "/proc/dasd/statictics: '%s'\n", buffer); /* check for valid verbs */ for (str = buffer; isspace(*str); str++); @@ -277,33 +279,33 @@ dasd_statistics_write(struct file *file, const char __user *user_buf, if (strcmp(str, "on") == 0) { /* switch on statistics profiling */ dasd_profile_level = DASD_PROFILE_ON; - MESSAGE(KERN_INFO, "%s", "Statistics switched on"); + pr_info("The statistics feature has been switched " + "on\n"); } else if (strcmp(str, "off") == 0) { /* switch off and reset statistics profiling */ memset(&dasd_global_profile, 0, sizeof (struct dasd_profile_info_t)); dasd_profile_level = DASD_PROFILE_OFF; - MESSAGE(KERN_INFO, "%s", "Statistics switched off"); + pr_info("The statistics feature has been switched " + "off\n"); } else goto out_error; } else if (strncmp(str, "reset", 5) == 0) { /* reset the statistics */ memset(&dasd_global_profile, 0, sizeof (struct dasd_profile_info_t)); - MESSAGE(KERN_INFO, "%s", "Statistics reset"); + pr_info("The statistics have been reset\n"); } else goto out_error; kfree(buffer); return user_len; out_error: - MESSAGE(KERN_WARNING, "%s", - "/proc/dasd/statistics: only 'set on', 'set off' " - "and 'reset' are supported verbs"); + pr_warning("%s is not a supported value for /proc/dasd/statistics\n", + str); kfree(buffer); return -EINVAL; #else - MESSAGE(KERN_WARNING, "%s", - "/proc/dasd/statistics: is not activated in this kernel"); + pr_warning("/proc/dasd/statistics: is not activated in this kernel\n"); return user_len; #endif /* CONFIG_DASD_PROFILE */ } -- GitLab From 94f5b09d97ee1f803c76d0262e0b0d3791825d09 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 26 Mar 2009 15:23:50 +0100 Subject: [PATCH 4617/4982] [S390] move sysinfo.c from drivers/s390 to arch/s390/kernel All in sysinfo.c is core kernel code and not driver code. So move it to arch/s390/kernel. Also includes some small cleanups. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/Makefile | 4 +- {drivers/s390 => arch/s390/kernel}/sysinfo.c | 69 ++++---------------- drivers/s390/Makefile | 4 +- 3 files changed, 18 insertions(+), 59 deletions(-) rename {drivers/s390 => arch/s390/kernel}/sysinfo.c (88%) diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 3edc6c6f258..33e7aee7051 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -17,10 +17,12 @@ CFLAGS_smp.o := -Wno-nonnull # CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"' +CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w + obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o \ processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ s390_ext.o debug.o irq.o ipl.o dis.o diag.o mem_detect.o \ - vdso.o vtime.o + vdso.o vtime.o sysinfo.o obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) diff --git a/drivers/s390/sysinfo.c b/arch/s390/kernel/sysinfo.c similarity index 88% rename from drivers/s390/sysinfo.c rename to arch/s390/kernel/sysinfo.c index 0eea9078138..b5e75e1061c 100644 --- a/drivers/s390/sysinfo.c +++ b/arch/s390/kernel/sysinfo.c @@ -1,9 +1,7 @@ /* - * drivers/s390/sysinfo.c - * - * Copyright IBM Corp. 2001, 2008 - * Author(s): Ulrich Weigand (Ulrich.Weigand@de.ibm.com) - * Martin Schwidefsky + * Copyright IBM Corp. 2001, 2009 + * Author(s): Ulrich Weigand , + * Martin Schwidefsky , */ #include @@ -24,7 +22,7 @@ static inline int stsi_0(void) { - int rc = stsi (NULL, 0, 0, 0); + int rc = stsi(NULL, 0, 0, 0); return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28); } @@ -78,23 +76,6 @@ static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len) return len; } -#if 0 /* Currently unused */ -static int stsi_1_2_1(struct sysinfo_1_2_1 *info, char *page, int len) -{ - if (stsi(info, 1, 2, 1) == -ENOSYS) - return len; - - len += sprintf(page + len, "\n"); - EBCASC(info->sequence, sizeof(info->sequence)); - EBCASC(info->plant, sizeof(info->plant)); - len += sprintf(page + len, "Sequence Code of CPU: %-16.16s\n", - info->sequence); - len += sprintf(page + len, "Plant of CPU: %-16.16s\n", - info->plant); - return len; -} -#endif - static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len) { struct sysinfo_1_2_2_extension *ext; @@ -145,33 +126,15 @@ static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len) if (info->secondary_capability != 0) len += sprintf(page + len, "Secondary Capability: %d\n", info->secondary_capability); - return len; } -#if 0 /* Currently unused */ -static int stsi_2_2_1(struct sysinfo_2_2_1 *info, char *page, int len) -{ - if (stsi(info, 2, 2, 1) == -ENOSYS) - return len; - - len += sprintf(page + len, "\n"); - EBCASC (info->sequence, sizeof(info->sequence)); - EBCASC (info->plant, sizeof(info->plant)); - len += sprintf(page + len, "Sequence Code of logical CPU: %-16.16s\n", - info->sequence); - len += sprintf(page + len, "Plant of logical CPU: %-16.16s\n", - info->plant); - return len; -} -#endif - static int stsi_2_2_2(struct sysinfo_2_2_2 *info, char *page, int len) { if (stsi(info, 2, 2, 2) == -ENOSYS) return len; - EBCASC (info->name, sizeof(info->name)); + EBCASC(info->name, sizeof(info->name)); len += sprintf(page + len, "\n"); len += sprintf(page + len, "LPAR Number: %d\n", @@ -214,8 +177,8 @@ static int stsi_3_2_2(struct sysinfo_3_2_2 *info, char *page, int len) if (stsi(info, 3, 2, 2) == -ENOSYS) return len; for (i = 0; i < info->count; i++) { - EBCASC (info->vm[i].name, sizeof(info->vm[i].name)); - EBCASC (info->vm[i].cpi, sizeof(info->vm[i].cpi)); + EBCASC(info->vm[i].name, sizeof(info->vm[i].name)); + EBCASC(info->vm[i].cpi, sizeof(info->vm[i].cpi)); len += sprintf(page + len, "\n"); len += sprintf(page + len, "VM%02d Name: %-8.8s\n", i, info->vm[i].name); @@ -237,14 +200,13 @@ static int stsi_3_2_2(struct sysinfo_3_2_2 *info, char *page, int len) return len; } - static int proc_read_sysinfo(char *page, char **start, - off_t off, int count, - int *eof, void *data) + off_t off, int count, + int *eof, void *data) { - unsigned long info = get_zeroed_page (GFP_KERNEL); + unsigned long info = get_zeroed_page(GFP_KERNEL); int level, len; - + if (!info) return 0; @@ -262,8 +224,8 @@ static int proc_read_sysinfo(char *page, char **start, if (level >= 3) len = stsi_3_2_2((struct sysinfo_3_2_2 *) info, page, len); - free_page (info); - return len; + free_page(info); + return len; } static __init int create_proc_sysinfo(void) @@ -272,8 +234,7 @@ static __init int create_proc_sysinfo(void) proc_read_sysinfo, NULL); return 0; } - -__initcall(create_proc_sysinfo); +device_initcall(create_proc_sysinfo); /* * Service levels interface. @@ -387,13 +348,11 @@ static __init int create_proc_service_level(void) register_service_level(&service_level_vm); return 0; } - subsys_initcall(create_proc_service_level); /* * Bogomips calculation based on cpu capability. */ - int get_cpu_capability(unsigned int *capability) { struct sysinfo_1_2_2 *info; diff --git a/drivers/s390/Makefile b/drivers/s390/Makefile index d0eae59bc36..0828dc83935 100644 --- a/drivers/s390/Makefile +++ b/drivers/s390/Makefile @@ -2,9 +2,7 @@ # Makefile for the S/390 specific device drivers # -CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w - -obj-y += s390mach.o sysinfo.o +obj-y += s390mach.o obj-y += cio/ block/ char/ crypto/ net/ scsi/ kvm/ drivers-y += drivers/s390/built-in.o -- GitLab From 082fb301e048e84669234afb80fe27e6fa87efb4 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 26 Mar 2009 15:23:51 +0100 Subject: [PATCH 4618/4982] [S390] delete drivers/s390/ebcdic.c Dead file. Seems to be a leftover from the 2.4->2.5 conversion. The used and uptodate version of this file is in arch/s390/kernel. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/ebcdic.c | 246 ------------------------------------------ 1 file changed, 246 deletions(-) delete mode 100644 drivers/s390/ebcdic.c diff --git a/drivers/s390/ebcdic.c b/drivers/s390/ebcdic.c deleted file mode 100644 index 99c98da1547..00000000000 --- a/drivers/s390/ebcdic.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * arch/s390/kernel/ebcdic.c - * ECBDIC -> ASCII, ASCII -> ECBDIC conversion tables. - * - * S390 version - * Copyright (C) 1998 IBM Corporation - * Author(s): Martin Schwidefsky - */ - -#include - -/* - * ASCII -> EBCDIC - */ -__u8 _ascebc[256] = -{ - /*00 NL SH SX EX ET NQ AK BL */ - 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, - /*08 BS HT LF VT FF CR SO SI */ - 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - /*10 DL D1 D2 D3 D4 NK SN EB */ - 0x10, 0x11, 0x12, 0x13, 0x3C, 0x15, 0x32, 0x26, - /*18 CN EM SB EC FS GS RS US */ - 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F, - /*20 SP ! " # $ % & ' */ - 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, - /*28 ( ) * + , - . / */ - 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, - /*30 0 1 2 3 4 5 6 7 */ - 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, - /*38 8 9 : ; < = > ? */ - 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, - /*40 @ A B C D E F G */ - 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, - /*48 H I J K L M N O */ - 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, - /*50 P Q R S T U V W */ - 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, - /*58 X Y Z [ \ ] ^ _ */ - 0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D, - /*60 ` a b c d e f g */ - 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - /*68 h i j k l m n o */ - 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, - /*70 p q r s t u v w */ - 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, - /*78 x y z { | } ~ DL */ - 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, - 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, - 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, - 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, - 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, - 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, - 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, - 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, - 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, - 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, - 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, - 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, - 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, - 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, - 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, - 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, - 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0xFF -}; - -/* - * EBCDIC -> ASCII - */ -__u8 _ebcasc[256] = -{ - /* 0x00 NUL SOH STX ETX *SEL HT *RNL DEL */ - 0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F, - /* 0x08 -GE -SPS -RPT VT FF CR SO SI */ - 0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - /* 0x10 DLE DC1 DC2 DC3 -RES -NL BS -POC - -ENP ->LF */ - 0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07, - /* 0x18 CAN EM -UBS -CU1 -IFS -IGS -IRS -ITB - -IUS */ - 0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - /* 0x20 -DS -SOS FS -WUS -BYP LF ETB ESC - -INP */ - 0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B, - /* 0x28 -SA -SFE -SM -CSP -MFA ENQ ACK BEL - -SW */ - 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07, - /* 0x30 ---- ---- SYN -IR -PP -TRN -NBS EOT */ - 0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04, - /* 0x38 -SBS -IT -RFF -CU3 DC4 NAK ---- SUB */ - 0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A, - /* 0x40 SP RSP ä ---- */ - 0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86, - /* 0x48 . < ( + | */ - 0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, - /* 0x50 & ---- */ - 0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07, - /* 0x58 ß ! $ * ) ; */ - 0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA, - /* 0x60 - / ---- Ä ---- ---- ---- */ - 0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F, - /* 0x68 ---- , % _ > ? */ - 0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, - /* 0x70 ---- ---- ---- ---- ---- ---- ---- */ - 0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - /* 0x78 * ` : # @ ' = " */ - 0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, - /* 0x80 * a b c d e f g */ - 0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - /* 0x88 h i ---- ---- ---- */ - 0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1, - /* 0x90 ° j k l m n o p */ - 0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, - /* 0x98 q r ---- ---- */ - 0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07, - /* 0xA0 ~ s t u v w x */ - 0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - /* 0xA8 y z ---- ---- ---- ---- */ - 0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07, - /* 0xB0 ^ ---- § ---- */ - 0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC, - /* 0xB8 ---- [ ] ---- ---- ---- ---- */ - 0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07, - /* 0xC0 { A B C D E F G */ - 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - /* 0xC8 H I ---- ö ---- */ - 0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07, - /* 0xD0 } J K L M N O P */ - 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, - /* 0xD8 Q R ---- ü */ - 0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98, - /* 0xE0 \ S T U V W X */ - 0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, - /* 0xE8 Y Z ---- Ö ---- ---- ---- */ - 0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07, - /* 0xF0 0 1 2 3 4 5 6 7 */ - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - /* 0xF8 8 9 ---- ---- Ü ---- ---- ---- */ - 0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07 -}; - -/* - * EBCDIC (capitals) -> ASCII (small case) - */ -__u8 _ebcasc_reduce_case[256] = -{ - /* 0x00 NUL SOH STX ETX *SEL HT *RNL DEL */ - 0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F, - - /* 0x08 -GE -SPS -RPT VT FF CR SO SI */ - 0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - - /* 0x10 DLE DC1 DC2 DC3 -RES -NL BS -POC - -ENP ->LF */ - 0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07, - - /* 0x18 CAN EM -UBS -CU1 -IFS -IGS -IRS -ITB - -IUS */ - 0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - - /* 0x20 -DS -SOS FS -WUS -BYP LF ETB ESC - -INP */ - 0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B, - - /* 0x28 -SA -SFE -SM -CSP -MFA ENQ ACK BEL - -SW */ - 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07, - - /* 0x30 ---- ---- SYN -IR -PP -TRN -NBS EOT */ - 0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04, - - /* 0x38 -SBS -IT -RFF -CU3 DC4 NAK ---- SUB */ - 0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A, - - /* 0x40 SP RSP ä ---- */ - 0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86, - - /* 0x48 . < ( + | */ - 0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, - - /* 0x50 & ---- */ - 0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07, - - /* 0x58 ß ! $ * ) ; */ - 0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA, - - /* 0x60 - / ---- Ä ---- ---- ---- */ - 0x2D, 0x2F, 0x07, 0x84, 0x07, 0x07, 0x07, 0x8F, - - /* 0x68 ---- , % _ > ? */ - 0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, - - /* 0x70 ---- ---- ---- ---- ---- ---- ---- */ - 0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - - /* 0x78 * ` : # @ ' = " */ - 0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, - - /* 0x80 * a b c d e f g */ - 0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - - /* 0x88 h i ---- ---- ---- */ - 0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1, - - /* 0x90 ° j k l m n o p */ - 0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, - - /* 0x98 q r ---- ---- */ - 0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07, - - /* 0xA0 ~ s t u v w x */ - 0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - - /* 0xA8 y z ---- ---- ---- ---- */ - 0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07, - - /* 0xB0 ^ ---- § ---- */ - 0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC, - - /* 0xB8 ---- [ ] ---- ---- ---- ---- */ - 0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07, - - /* 0xC0 { A B C D E F G */ - 0x7B, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - - /* 0xC8 H I ---- ö ---- */ - 0x68, 0x69, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07, - - /* 0xD0 } J K L M N O P */ - 0x7D, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, - - /* 0xD8 Q R ---- ü */ - 0x71, 0x72, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98, - - /* 0xE0 \ S T U V W X */ - 0x5C, 0xF6, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - - /* 0xE8 Y Z ---- Ö ---- ---- ---- */ - 0x79, 0x7A, 0xFD, 0x07, 0x94, 0x07, 0x07, 0x07, - - /* 0xF0 0 1 2 3 4 5 6 7 */ - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - - /* 0xF8 8 9 ---- ---- Ü ---- ---- ---- */ - 0x38, 0x39, 0x07, 0x07, 0x81, 0x07, 0x07, 0x07 -}; -- GitLab From cbdc229245e8cf5c201e68221ebf2f33d2aaf029 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 26 Mar 2009 15:23:52 +0100 Subject: [PATCH 4619/4982] [S390] arch/s390/kernel/process.c: fix whitespace damage Fix all the whitespace damage in process.c, especially copy_thread(). Next patch will add code to copy_thread() which needs to 'fixed' first. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/process.c | 64 ++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 37 deletions(-) diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 5cd38a90e64..e0563baa1cf 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -1,18 +1,10 @@ /* - * arch/s390/kernel/process.c + * This file handles the architecture dependent parts of process handling. * - * S390 version - * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), - * Hartmut Penner (hp@de.ibm.com), - * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), - * - * Derived from "arch/i386/kernel/process.c" - * Copyright (C) 1995, Linus Torvalds - */ - -/* - * This file handles the architecture-dependent parts of process handling.. + * Copyright IBM Corp. 1999,2009 + * Author(s): Martin Schwidefsky , + * Hartmut Penner , + * Denis Joseph Barrow, */ #include @@ -168,34 +160,34 @@ void release_thread(struct task_struct *dead_task) } int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, - unsigned long unused, - struct task_struct * p, struct pt_regs * regs) + unsigned long unused, + struct task_struct *p, struct pt_regs *regs) { - struct fake_frame - { - struct stack_frame sf; - struct pt_regs childregs; - } *frame; - - frame = container_of(task_pt_regs(p), struct fake_frame, childregs); - p->thread.ksp = (unsigned long) frame; + struct fake_frame + { + struct stack_frame sf; + struct pt_regs childregs; + } *frame; + + frame = container_of(task_pt_regs(p), struct fake_frame, childregs); + p->thread.ksp = (unsigned long) frame; /* Store access registers to kernel stack of new process. */ - frame->childregs = *regs; + frame->childregs = *regs; frame->childregs.gprs[2] = 0; /* child returns 0 on fork. */ - frame->childregs.gprs[15] = new_stackp; - frame->sf.back_chain = 0; + frame->childregs.gprs[15] = new_stackp; + frame->sf.back_chain = 0; - /* new return point is ret_from_fork */ - frame->sf.gprs[8] = (unsigned long) ret_from_fork; + /* new return point is ret_from_fork */ + frame->sf.gprs[8] = (unsigned long) ret_from_fork; - /* fake return stack for resume(), don't go back to schedule */ - frame->sf.gprs[9] = (unsigned long) frame; + /* fake return stack for resume(), don't go back to schedule */ + frame->sf.gprs[9] = (unsigned long) frame; /* Save access registers to new thread structure. */ save_access_regs(&p->thread.acrs[0]); #ifndef CONFIG_64BIT - /* + /* * save fprs to current->thread.fp_regs to merge them with * the emulated registers and then copy the result to the child. */ @@ -220,10 +212,9 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, #endif /* CONFIG_64BIT */ /* start new process with ar4 pointing to the correct address space */ p->thread.mm_segment = get_fs(); - /* Don't copy debug registers */ - memset(&p->thread.per_info,0,sizeof(p->thread.per_info)); - - return 0; + /* Don't copy debug registers */ + memset(&p->thread.per_info, 0, sizeof(p->thread.per_info)); + return 0; } SYSCALL_DEFINE0(fork) @@ -311,7 +302,7 @@ out: int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs) { #ifndef CONFIG_64BIT - /* + /* * save fprs to current->thread.fp_regs to merge them with * the emulated registers and then copy the result to the dump. */ @@ -346,4 +337,3 @@ unsigned long get_wchan(struct task_struct *p) } return 0; } - -- GitLab From 5168ce2c647f02756803bef7b74906f485491a1c Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 26 Mar 2009 15:23:53 +0100 Subject: [PATCH 4620/4982] [S390] cputime: initialize per thread timer values on fork Initialize per thread timer values instead of just copying them from the parent. That way it is easily possible to tell how much time a thread spent in user/system context. Doesn't fix a bug, this is just for debugging purposes. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/process.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index e0563baa1cf..e6b480625cb 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -163,6 +163,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, unsigned long unused, struct task_struct *p, struct pt_regs *regs) { + struct thread_info *ti; struct fake_frame { struct stack_frame sf; @@ -214,6 +215,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, p->thread.mm_segment = get_fs(); /* Don't copy debug registers */ memset(&p->thread.per_info, 0, sizeof(p->thread.per_info)); + /* Initialize per thread user and system timer values */ + ti = task_thread_info(p); + ti->user_timer = 0; + ti->system_timer = 0; return 0; } -- GitLab From 82f3a79bc6b50ab82744ebc32efba31c78dbccf7 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Thu, 26 Mar 2009 15:23:54 +0100 Subject: [PATCH 4621/4982] [S390] hvc_iucv: Update and add missing kernel messages If the hvc_iucv= kernel parameter specifies a value that is not valid, display an error message. Minor changes to existing kernel messages. Signed-off-by: Hendrik Brueckner Signed-off-by: Martin Schwidefsky --- drivers/char/hvc_iucv.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/char/hvc_iucv.c b/drivers/char/hvc_iucv.c index a53496828b7..146be5a6094 100644 --- a/drivers/char/hvc_iucv.c +++ b/drivers/char/hvc_iucv.c @@ -885,7 +885,7 @@ static int __init hvc_iucv_init(void) unsigned int i; if (!MACHINE_IS_VM) { - pr_info("The z/VM IUCV HVC device driver cannot " + pr_notice("The z/VM IUCV HVC device driver cannot " "be used without z/VM\n"); return -ENODEV; } @@ -893,8 +893,11 @@ static int __init hvc_iucv_init(void) if (!hvc_iucv_devices) return -ENODEV; - if (hvc_iucv_devices > MAX_HVC_IUCV_LINES) + if (hvc_iucv_devices > MAX_HVC_IUCV_LINES) { + pr_err("%lu is not a valid value for the hvc_iucv= " + "kernel parameter\n", hvc_iucv_devices); return -EINVAL; + } hvc_iucv_buffer_cache = kmem_cache_create(KMSG_COMPONENT, sizeof(struct iucv_tty_buffer), -- GitLab From 431429ff788598a19c1a193b9fca3961b7f55916 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Thu, 26 Mar 2009 15:23:55 +0100 Subject: [PATCH 4622/4982] [S390] hvc_iucv: Provide IUCV z/VM user ID filtering This patch introduces the kernel parameter hvc_iucv_allow= that specifies a comma-separated list of z/VM user IDs. If specified, the z/VM IUCV hypervisor console device driver accepts IUCV connections from listed z/VM user IDs only. Signed-off-by: Hendrik Brueckner Signed-off-by: Martin Schwidefsky --- Documentation/kernel-parameters.txt | 3 + drivers/char/hvc_iucv.c | 254 +++++++++++++++++++++++++++- 2 files changed, 249 insertions(+), 8 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 54f21a5c262..9f932a76a94 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -829,6 +829,9 @@ and is between 256 and 4096 characters. It is defined in the file hvc_iucv= [S390] Number of z/VM IUCV hypervisor console (HVC) terminal devices. Valid values: 0..8 + hvc_iucv_allow= [S390] Comma-separated list of z/VM user IDs. + If specified, z/VM IUCV HVC accepts connections + from listed z/VM user IDs only. i8042.debug [HW] Toggle i8042 debug mode i8042.direct [HW] Put keyboard port into non-translated mode diff --git a/drivers/char/hvc_iucv.c b/drivers/char/hvc_iucv.c index 146be5a6094..54481a88776 100644 --- a/drivers/char/hvc_iucv.c +++ b/drivers/char/hvc_iucv.c @@ -13,10 +13,11 @@ #include #include +#include #include #include #include -#include +#include #include #include #include @@ -95,6 +96,12 @@ static unsigned long hvc_iucv_devices = 1; /* Array of allocated hvc iucv tty lines... */ static struct hvc_iucv_private *hvc_iucv_table[MAX_HVC_IUCV_LINES]; #define IUCV_HVC_CON_IDX (0) +/* List of z/VM user ID filter entries (struct iucv_vmid_filter) */ +#define MAX_VMID_FILTER (500) +static size_t hvc_iucv_filter_size; +static void *hvc_iucv_filter; +static const char *hvc_iucv_filter_string; +static DEFINE_RWLOCK(hvc_iucv_filter_lock); /* Kmem cache and mempool for iucv_tty_buffer elements */ static struct kmem_cache *hvc_iucv_buffer_cache; @@ -617,6 +624,27 @@ static void hvc_iucv_notifier_del(struct hvc_struct *hp, int id) } } +/** + * hvc_iucv_filter_connreq() - Filter connection request based on z/VM user ID + * @ipvmid: Originating z/VM user ID (right padded with blanks) + * + * Returns 0 if the z/VM user ID @ipvmid is allowed to connection, otherwise + * non-zero. + */ +static int hvc_iucv_filter_connreq(u8 ipvmid[8]) +{ + size_t i; + + /* Note: default policy is ACCEPT if no filter is set */ + if (!hvc_iucv_filter_size) + return 0; + + for (i = 0; i < hvc_iucv_filter_size; i++) + if (0 == memcmp(ipvmid, hvc_iucv_filter + (8 * i), 8)) + return 0; + return 1; +} + /** * hvc_iucv_path_pending() - IUCV handler to process a connection request. * @path: Pending path (struct iucv_path) @@ -641,6 +669,7 @@ static int hvc_iucv_path_pending(struct iucv_path *path, { struct hvc_iucv_private *priv; u8 nuser_data[16]; + u8 vm_user_id[9]; int i, rc; priv = NULL; @@ -653,6 +682,20 @@ static int hvc_iucv_path_pending(struct iucv_path *path, if (!priv) return -ENODEV; + /* Enforce that ipvmid is allowed to connect to us */ + read_lock(&hvc_iucv_filter_lock); + rc = hvc_iucv_filter_connreq(ipvmid); + read_unlock(&hvc_iucv_filter_lock); + if (rc) { + iucv_path_sever(path, ipuser); + iucv_path_free(path); + memcpy(vm_user_id, ipvmid, 8); + vm_user_id[8] = 0; + pr_info("A connection request from z/VM user ID %s " + "was refused\n", vm_user_id); + return 0; + } + spin_lock(&priv->lock); /* If the terminal is already connected or being severed, then sever @@ -876,6 +919,171 @@ static int __init hvc_iucv_alloc(int id, unsigned int is_console) return 0; } +/** + * hvc_iucv_parse_filter() - Parse filter for a single z/VM user ID + * @filter: String containing a comma-separated list of z/VM user IDs + */ +static const char *hvc_iucv_parse_filter(const char *filter, char *dest) +{ + const char *nextdelim, *residual; + size_t len; + + nextdelim = strchr(filter, ','); + if (nextdelim) { + len = nextdelim - filter; + residual = nextdelim + 1; + } else { + len = strlen(filter); + residual = filter + len; + } + + if (len == 0) + return ERR_PTR(-EINVAL); + + /* check for '\n' (if called from sysfs) */ + if (filter[len - 1] == '\n') + len--; + + if (len > 8) + return ERR_PTR(-EINVAL); + + /* pad with blanks and save upper case version of user ID */ + memset(dest, ' ', 8); + while (len--) + dest[len] = toupper(filter[len]); + return residual; +} + +/** + * hvc_iucv_setup_filter() - Set up z/VM user ID filter + * @filter: String consisting of a comma-separated list of z/VM user IDs + * + * The function parses the @filter string and creates an array containing + * the list of z/VM user ID filter entries. + * Return code 0 means success, -EINVAL if the filter is syntactically + * incorrect, -ENOMEM if there was not enough memory to allocate the + * filter list array, or -ENOSPC if too many z/VM user IDs have been specified. + */ +static int hvc_iucv_setup_filter(const char *val) +{ + const char *residual; + int err; + size_t size, count; + void *array, *old_filter; + + count = strlen(val); + if (count == 0 || (count == 1 && val[0] == '\n')) { + size = 0; + array = NULL; + goto out_replace_filter; /* clear filter */ + } + + /* count user IDs in order to allocate sufficient memory */ + size = 1; + residual = val; + while ((residual = strchr(residual, ',')) != NULL) { + residual++; + size++; + } + + /* check if the specified list exceeds the filter limit */ + if (size > MAX_VMID_FILTER) + return -ENOSPC; + + array = kzalloc(size * 8, GFP_KERNEL); + if (!array) + return -ENOMEM; + + count = size; + residual = val; + while (*residual && count) { + residual = hvc_iucv_parse_filter(residual, + array + ((size - count) * 8)); + if (IS_ERR(residual)) { + err = PTR_ERR(residual); + kfree(array); + goto out_err; + } + count--; + } + +out_replace_filter: + write_lock_bh(&hvc_iucv_filter_lock); + old_filter = hvc_iucv_filter; + hvc_iucv_filter_size = size; + hvc_iucv_filter = array; + write_unlock_bh(&hvc_iucv_filter_lock); + kfree(old_filter); + + err = 0; +out_err: + return err; +} + +/** + * param_set_vmidfilter() - Set z/VM user ID filter parameter + * @val: String consisting of a comma-separated list of z/VM user IDs + * @kp: Kernel parameter pointing to hvc_iucv_filter array + * + * The function sets up the z/VM user ID filter specified as comma-separated + * list of user IDs in @val. + * Note: If it is called early in the boot process, @val is stored and + * parsed later in hvc_iucv_init(). + */ +static int param_set_vmidfilter(const char *val, struct kernel_param *kp) +{ + int rc; + + if (!MACHINE_IS_VM || !hvc_iucv_devices) + return -ENODEV; + + if (!val) + return -EINVAL; + + rc = 0; + if (slab_is_available()) + rc = hvc_iucv_setup_filter(val); + else + hvc_iucv_filter_string = val; /* defer... */ + return rc; +} + +/** + * param_get_vmidfilter() - Get z/VM user ID filter + * @buffer: Buffer to store z/VM user ID filter, + * (buffer size assumption PAGE_SIZE) + * @kp: Kernel parameter pointing to the hvc_iucv_filter array + * + * The function stores the filter as a comma-separated list of z/VM user IDs + * in @buffer. Typically, sysfs routines call this function for attr show. + */ +static int param_get_vmidfilter(char *buffer, struct kernel_param *kp) +{ + int rc; + size_t index, len; + void *start, *end; + + if (!MACHINE_IS_VM || !hvc_iucv_devices) + return -ENODEV; + + rc = 0; + read_lock_bh(&hvc_iucv_filter_lock); + for (index = 0; index < hvc_iucv_filter_size; index++) { + start = hvc_iucv_filter + (8 * index); + end = memchr(start, ' ', 8); + len = (end) ? end - start : 8; + memcpy(buffer + rc, start, len); + rc += len; + buffer[rc++] = ','; + } + read_unlock_bh(&hvc_iucv_filter_lock); + if (rc) + buffer[--rc] = '\0'; /* replace last comma and update rc */ + return rc; +} + +#define param_check_vmidfilter(name, p) __param_check(name, p, void) + /** * hvc_iucv_init() - z/VM IUCV HVC device driver initialization */ @@ -884,19 +1092,44 @@ static int __init hvc_iucv_init(void) int rc; unsigned int i; + if (!hvc_iucv_devices) + return -ENODEV; + if (!MACHINE_IS_VM) { pr_notice("The z/VM IUCV HVC device driver cannot " "be used without z/VM\n"); - return -ENODEV; + rc = -ENODEV; + goto out_error; } - if (!hvc_iucv_devices) - return -ENODEV; - if (hvc_iucv_devices > MAX_HVC_IUCV_LINES) { pr_err("%lu is not a valid value for the hvc_iucv= " "kernel parameter\n", hvc_iucv_devices); - return -EINVAL; + rc = -EINVAL; + goto out_error; + } + + /* parse hvc_iucv_allow string and create z/VM user ID filter list */ + if (hvc_iucv_filter_string) { + rc = hvc_iucv_setup_filter(hvc_iucv_filter_string); + switch (rc) { + case 0: + break; + case -ENOMEM: + pr_err("Allocating memory failed with " + "reason code=%d\n", 3); + goto out_error; + case -EINVAL: + pr_err("hvc_iucv_allow= does not specify a valid " + "z/VM user ID list\n"); + goto out_error; + case -ENOSPC: + pr_err("hvc_iucv_allow= specifies too many " + "z/VM user IDs\n"); + goto out_error; + default: + goto out_error; + } } hvc_iucv_buffer_cache = kmem_cache_create(KMSG_COMPONENT, @@ -904,7 +1137,8 @@ static int __init hvc_iucv_init(void) 0, 0, NULL); if (!hvc_iucv_buffer_cache) { pr_err("Allocating memory failed with reason code=%d\n", 1); - return -ENOMEM; + rc = -ENOMEM; + goto out_error; } hvc_iucv_mempool = mempool_create_slab_pool(MEMPOOL_MIN_NR, @@ -912,7 +1146,8 @@ static int __init hvc_iucv_init(void) if (!hvc_iucv_mempool) { pr_err("Allocating memory failed with reason code=%d\n", 2); kmem_cache_destroy(hvc_iucv_buffer_cache); - return -ENOMEM; + rc = -ENOMEM; + goto out_error; } /* register the first terminal device as console @@ -956,6 +1191,8 @@ out_error_hvc: out_error_memory: mempool_destroy(hvc_iucv_mempool); kmem_cache_destroy(hvc_iucv_buffer_cache); +out_error: + hvc_iucv_devices = 0; /* ensure that we do not provide any device */ return rc; } @@ -971,3 +1208,4 @@ static int __init hvc_iucv_config(char *val) device_initcall(hvc_iucv_init); __setup("hvc_iucv=", hvc_iucv_config); +core_param(hvc_iucv_allow, hvc_iucv_filter, vmidfilter, 0640); -- GitLab From 3324e60aafa9aeb1009878d45079b67367a5e2b6 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Thu, 26 Mar 2009 15:23:56 +0100 Subject: [PATCH 4623/4982] [S390] lockdep: trace hardirq off in smp_send_stop With lockdep we got the following trace after a panic: Badness at /home/autobuild/BUILD/linux-2.6.28-20090204/kernel/lockdep.c:2878 [...] Call Trace: [<0000000000176334>] lock_acquire+0x54/0xbc [<000000000050b4fe>] __atomic_notifier_call_chain+0x6e/0xdc [<000000000050b59c>] atomic_notifier_call_chain+0x30/0x44 [<0000000000504274>] panic+0xd0/0x1e8 [...] INFO: lockdep is turned off. Last Breaking-Event-Address: [<0000000000170e62>] check_flags+0xae/0x15c possible reason: unannotated irqs-off. lockdep is right. We missed a trace_hardirq_off in our smp_send_stop function and smp_send_stop is called before the panic call chain. Reported-by: Mijo Signed-off-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/smp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index e279d0fbbbe..a8858634dd0 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -75,6 +76,7 @@ void smp_send_stop(void) /* Disable all interrupts/machine checks */ __load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK); + trace_hardirqs_off(); /* stop all processors */ for_each_online_cpu(cpu) { -- GitLab From 702d9e584feb028ed7e2a6d2b103b8ea57622ff2 Mon Sep 17 00:00:00 2001 From: Carsten Otte Date: Thu, 26 Mar 2009 15:23:57 +0100 Subject: [PATCH 4624/4982] [S390] check addressing mode in s390_enable_sie The sie instruction requires address spaces to be switched to run proper. This patch verifies that this is the case in s390_enable_sie, otherwise the kernel would crash badly as soon as the process runs into sie. Signed-off-by: Carsten Otte Signed-off-by: Martin Schwidefsky --- arch/s390/mm/pgtable.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 6b6ddc4ea02..9bf86125f6f 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -258,6 +258,10 @@ int s390_enable_sie(void) struct task_struct *tsk = current; struct mm_struct *mm, *old_mm; + /* Do we have switched amode? If no, we cannot do sie */ + if (!switch_amode) + return -EINVAL; + /* Do we have pgstes? if yes, we are done */ if (tsk->mm->context.has_pgste) return 0; -- GitLab From 92e6ecf392fac3082653ac9d84b1bdf53d0ea160 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Thu, 26 Mar 2009 15:23:58 +0100 Subject: [PATCH 4625/4982] [S390] Fix hypervisor detection for KVM Currently we use the cpuid (via STIDP instruction) to recognize LPAR, z/VM and KVM. The architecture states, that bit 0-7 of STIDP returns all zero, and if STIDP is executed in a virtual machine, the VM operating system will replace bits 0-7 with FF. KVM should not use FE to distinguish z/VM from KVM for interested guests. The proper way to detect the hypervisor is the STSI (Store System Information) instruction, which return information about the hypervisors via function code 3, selector1=2, selector2=2. This patch changes the detection routine of Linux to use STSI instead of STIDP. This detection is earlier than bootmem, we have to use a static buffer. Since STSI expects a 4kb block (4kb aligned) this patch also changes the init.data alignment for s390. As this section will be freed during boot, this should be no problem. Patch is tested with LPAR, z/VM, KVM on LPAR, and KVM under z/VM. Signed-off-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/sysinfo.h | 1 + arch/s390/kernel/early.c | 22 +++++++++++++--------- arch/s390/kernel/vmlinux.lds.S | 2 ++ arch/s390/kvm/kvm-s390.c | 2 +- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/arch/s390/include/asm/sysinfo.h b/arch/s390/include/asm/sysinfo.h index ad93212d9e1..9d70057d828 100644 --- a/arch/s390/include/asm/sysinfo.h +++ b/arch/s390/include/asm/sysinfo.h @@ -100,6 +100,7 @@ struct sysinfo_3_2_2 { char reserved_1[24]; } vm[8]; + char reserved_544[3552]; }; static inline int stsi(void *sysinfo, int fc, int sel1, int sel2) diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 2a2ca268b1d..d61eb3334ed 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -6,6 +6,7 @@ * Heiko Carstens */ +#include #include #include #include @@ -20,6 +21,7 @@ #include #include #include +#include #include #include #include "entry.h" @@ -173,19 +175,21 @@ static noinline __init void init_kernel_storage_key(void) page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY); } +static __initdata struct sysinfo_3_2_2 vmms __aligned(PAGE_SIZE); + static noinline __init void detect_machine_type(void) { - struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data; - - get_cpu_id(&S390_lowcore.cpu_data.cpu_id); - - /* Running under z/VM ? */ - if (cpuinfo->cpu_id.version == 0xff) - machine_flags |= MACHINE_FLAG_VM; + /* No VM information? Looks like LPAR */ + if (stsi(&vmms, 3, 2, 2) == -ENOSYS) + return; + if (!vmms.count) + return; - /* Running under KVM ? */ - if (cpuinfo->cpu_id.version == 0xfe) + /* Running under KVM? If not we assume z/VM */ + if (!memcmp(vmms.vm[0].cpi, "\xd2\xe5\xd4", 3)) machine_flags |= MACHINE_FLAG_KVM; + else + machine_flags |= MACHINE_FLAG_VM; } static __init void early_pgm_check_handler(void) diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index d796d05c9c0..7a2063eb88f 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S @@ -108,6 +108,8 @@ SECTIONS EXIT_TEXT } + /* early.c uses stsi, which requires page aligned data. */ + . = ALIGN(PAGE_SIZE); .init.data : { INIT_DATA } diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 0d33893e1e8..c55a4b9ffd8 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -286,7 +286,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) setup_timer(&vcpu->arch.ckc_timer, kvm_s390_idle_wakeup, (unsigned long) vcpu); get_cpu_id(&vcpu->arch.cpu_id); - vcpu->arch.cpu_id.version = 0xfe; + vcpu->arch.cpu_id.version = 0xff; return 0; } -- GitLab From cc54c1e66e4b90ab657464fec30e6970636ee23d Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 26 Mar 2009 15:23:59 +0100 Subject: [PATCH 4626/4982] [S390] ftrace: dont trace machine check handler The ftrace code is currently not reentrant, so we better don't trace our machine check handler. Machine checks are handled like NMIs on s390. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/s390mach.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c index 92b0417f8e1..8e437052e07 100644 --- a/drivers/s390/s390mach.c +++ b/drivers/s390/s390mach.c @@ -357,8 +357,7 @@ s390_revalidate_registers(struct mci *mci) /* * machine check handler. */ -void -s390_do_machine_check(struct pt_regs *regs) +void notrace s390_do_machine_check(struct pt_regs *regs) { static DEFINE_SPINLOCK(ipd_lock); static unsigned long long last_ipd; -- GitLab From 70193af9188113c9b4ff3dde1aed9f9c8f7c4f93 Mon Sep 17 00:00:00 2001 From: Sachin Sant Date: Thu, 26 Mar 2009 15:24:00 +0100 Subject: [PATCH 4627/4982] [S390] Fix appldata build break with !NET With CONFIG_NET not set appldata build breaks on s390. arch/s390/appldata/built-in.o: In function appldata_get_net_sum_data: appldata_net_sum.c:(.text+0x2684): undefined reference to dev_get_stats appldata_net_sum.c:(.text+0x2688): undefined reference to init_net appldata_net_sum.c:(.text+0x268c): undefined reference to init_net appldata_net_sum.c:(.text+0x2694): undefined reference to dev_base_lock The following patch fixes the issue for me. Signed-off-by: Sachin Sant Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 6b0a3538dc6..3f470604a89 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -521,7 +521,7 @@ config APPLDATA_OS config APPLDATA_NET_SUM tristate "Monitor overall network statistics" - depends on APPLDATA_BASE + depends on APPLDATA_BASE && NET help This provides network related data to the Linux - VM Monitor Stream, currently there is only a total sum of network I/O statistics, no -- GitLab From f5daba1d4116d964435ddd99f32b6c80448a496b Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 26 Mar 2009 15:24:01 +0100 Subject: [PATCH 4628/4982] [S390] split/move machine check handler code Split machine check handler code and move it to cio and kernel code where it belongs to. No functional change. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/crw.h | 68 +++++ arch/s390/include/asm/nmi.h | 66 +++++ arch/s390/kernel/Makefile | 2 +- .../s390/s390mach.c => arch/s390/kernel/nmi.c | 246 ++++-------------- arch/s390/kernel/process.c | 2 +- arch/s390/kvm/kvm-s390.c | 4 +- drivers/s390/Makefile | 1 - drivers/s390/cio/Makefile | 2 +- drivers/s390/cio/chp.c | 6 +- drivers/s390/cio/chsc.c | 6 +- drivers/s390/cio/cio.c | 3 +- drivers/s390/cio/crw.c | 145 +++++++++++ drivers/s390/cio/css.c | 6 +- drivers/s390/s390mach.h | 122 --------- 14 files changed, 340 insertions(+), 339 deletions(-) create mode 100644 arch/s390/include/asm/crw.h create mode 100644 arch/s390/include/asm/nmi.h rename drivers/s390/s390mach.c => arch/s390/kernel/nmi.c (67%) create mode 100644 drivers/s390/cio/crw.c delete mode 100644 drivers/s390/s390mach.h diff --git a/arch/s390/include/asm/crw.h b/arch/s390/include/asm/crw.h new file mode 100644 index 00000000000..2185a6d619d --- /dev/null +++ b/arch/s390/include/asm/crw.h @@ -0,0 +1,68 @@ +/* + * Data definitions for channel report processing + * Copyright IBM Corp. 2000,2009 + * Author(s): Ingo Adlung , + * Martin Schwidefsky , + * Cornelia Huck , + * Heiko Carstens , + */ + +#ifndef _ASM_S390_CRW_H +#define _ASM_S390_CRW_H + +#include + +/* + * Channel Report Word + */ +struct crw { + __u32 res1 : 1; /* reserved zero */ + __u32 slct : 1; /* solicited */ + __u32 oflw : 1; /* overflow */ + __u32 chn : 1; /* chained */ + __u32 rsc : 4; /* reporting source code */ + __u32 anc : 1; /* ancillary report */ + __u32 res2 : 1; /* reserved zero */ + __u32 erc : 6; /* error-recovery code */ + __u32 rsid : 16; /* reporting-source ID */ +} __attribute__ ((packed)); + +typedef void (*crw_handler_t)(struct crw *, struct crw *, int); + +extern int crw_register_handler(int rsc, crw_handler_t handler); +extern void crw_unregister_handler(int rsc); +extern void crw_handle_channel_report(void); + +#define NR_RSCS 16 + +#define CRW_RSC_MONITOR 0x2 /* monitoring facility */ +#define CRW_RSC_SCH 0x3 /* subchannel */ +#define CRW_RSC_CPATH 0x4 /* channel path */ +#define CRW_RSC_CONFIG 0x9 /* configuration-alert facility */ +#define CRW_RSC_CSS 0xB /* channel subsystem */ + +#define CRW_ERC_EVENT 0x00 /* event information pending */ +#define CRW_ERC_AVAIL 0x01 /* available */ +#define CRW_ERC_INIT 0x02 /* initialized */ +#define CRW_ERC_TERROR 0x03 /* temporary error */ +#define CRW_ERC_IPARM 0x04 /* installed parm initialized */ +#define CRW_ERC_TERM 0x05 /* terminal */ +#define CRW_ERC_PERRN 0x06 /* perm. error, fac. not init */ +#define CRW_ERC_PERRI 0x07 /* perm. error, facility init */ +#define CRW_ERC_PMOD 0x08 /* installed parameters modified */ + +static inline int stcrw(struct crw *pcrw) +{ + int ccode; + + asm volatile( + " stcrw 0(%2)\n" + " ipm %0\n" + " srl %0,28\n" + : "=d" (ccode), "=m" (*pcrw) + : "a" (pcrw) + : "cc" ); + return ccode; +} + +#endif /* _ASM_S390_CRW_H */ diff --git a/arch/s390/include/asm/nmi.h b/arch/s390/include/asm/nmi.h new file mode 100644 index 00000000000..f4b60441adc --- /dev/null +++ b/arch/s390/include/asm/nmi.h @@ -0,0 +1,66 @@ +/* + * Machine check handler definitions + * + * Copyright IBM Corp. 2000,2009 + * Author(s): Ingo Adlung , + * Martin Schwidefsky , + * Cornelia Huck , + * Heiko Carstens , + */ + +#ifndef _ASM_S390_NMI_H +#define _ASM_S390_NMI_H + +#include + +struct mci { + __u32 sd : 1; /* 00 system damage */ + __u32 pd : 1; /* 01 instruction-processing damage */ + __u32 sr : 1; /* 02 system recovery */ + __u32 : 1; /* 03 */ + __u32 cd : 1; /* 04 timing-facility damage */ + __u32 ed : 1; /* 05 external damage */ + __u32 : 1; /* 06 */ + __u32 dg : 1; /* 07 degradation */ + __u32 w : 1; /* 08 warning pending */ + __u32 cp : 1; /* 09 channel-report pending */ + __u32 sp : 1; /* 10 service-processor damage */ + __u32 ck : 1; /* 11 channel-subsystem damage */ + __u32 : 2; /* 12-13 */ + __u32 b : 1; /* 14 backed up */ + __u32 : 1; /* 15 */ + __u32 se : 1; /* 16 storage error uncorrected */ + __u32 sc : 1; /* 17 storage error corrected */ + __u32 ke : 1; /* 18 storage-key error uncorrected */ + __u32 ds : 1; /* 19 storage degradation */ + __u32 wp : 1; /* 20 psw mwp validity */ + __u32 ms : 1; /* 21 psw mask and key validity */ + __u32 pm : 1; /* 22 psw program mask and cc validity */ + __u32 ia : 1; /* 23 psw instruction address validity */ + __u32 fa : 1; /* 24 failing storage address validity */ + __u32 : 1; /* 25 */ + __u32 ec : 1; /* 26 external damage code validity */ + __u32 fp : 1; /* 27 floating point register validity */ + __u32 gr : 1; /* 28 general register validity */ + __u32 cr : 1; /* 29 control register validity */ + __u32 : 1; /* 30 */ + __u32 st : 1; /* 31 storage logical validity */ + __u32 ie : 1; /* 32 indirect storage error */ + __u32 ar : 1; /* 33 access register validity */ + __u32 da : 1; /* 34 delayed access exception */ + __u32 : 7; /* 35-41 */ + __u32 pr : 1; /* 42 tod programmable register validity */ + __u32 fc : 1; /* 43 fp control register validity */ + __u32 ap : 1; /* 44 ancillary report */ + __u32 : 1; /* 45 */ + __u32 ct : 1; /* 46 cpu timer validity */ + __u32 cc : 1; /* 47 clock comparator validity */ + __u32 : 16; /* 47-63 */ +}; + +struct pt_regs; + +extern void s390_handle_mcck(void); +extern void s390_do_machine_check(struct pt_regs *regs); + +#endif /* _ASM_S390_NMI_H */ diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 33e7aee7051..228e3105ded 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -22,7 +22,7 @@ CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o \ processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ s390_ext.o debug.o irq.o ipl.o dis.o diag.o mem_detect.o \ - vdso.o vtime.o sysinfo.o + vdso.o vtime.o sysinfo.o nmi.o obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) diff --git a/drivers/s390/s390mach.c b/arch/s390/kernel/nmi.c similarity index 67% rename from drivers/s390/s390mach.c rename to arch/s390/kernel/nmi.c index 8e437052e07..8d50eaf76a6 100644 --- a/drivers/s390/s390mach.c +++ b/arch/s390/kernel/nmi.c @@ -1,137 +1,23 @@ /* - * drivers/s390/s390mach.c - * S/390 machine check handler + * Machine check handler * - * Copyright IBM Corp. 2000,2008 - * Author(s): Ingo Adlung (adlung@de.ibm.com) - * Martin Schwidefsky (schwidefsky@de.ibm.com) - * Cornelia Huck + * Copyright IBM Corp. 2000,2009 + * Author(s): Ingo Adlung , + * Martin Schwidefsky , + * Cornelia Huck , + * Heiko Carstens , */ #include -#include #include -#include #include -#include -#include -#include +#include #include -#include +#include +#include #include -#include "s390mach.h" - -static struct semaphore m_sem; - -static NORET_TYPE void -s390_handle_damage(char *msg) -{ -#ifdef CONFIG_SMP - smp_send_stop(); -#endif - disabled_wait((unsigned long) __builtin_return_address(0)); - for(;;); -} - -static crw_handler_t crw_handlers[NR_RSCS]; - -/** - * s390_register_crw_handler() - register a channel report word handler - * @rsc: reporting source code to handle - * @handler: handler to be registered - * - * Returns %0 on success and a negative error value otherwise. - */ -int s390_register_crw_handler(int rsc, crw_handler_t handler) -{ - if ((rsc < 0) || (rsc >= NR_RSCS)) - return -EINVAL; - if (!cmpxchg(&crw_handlers[rsc], NULL, handler)) - return 0; - return -EBUSY; -} - -/** - * s390_unregister_crw_handler() - unregister a channel report word handler - * @rsc: reporting source code to handle - */ -void s390_unregister_crw_handler(int rsc) -{ - if ((rsc < 0) || (rsc >= NR_RSCS)) - return; - xchg(&crw_handlers[rsc], NULL); - synchronize_sched(); -} - -/* - * Retrieve CRWs and call function to handle event. - */ -static int s390_collect_crw_info(void *param) -{ - struct crw crw[2]; - int ccode; - struct semaphore *sem; - unsigned int chain; - int ignore; - - sem = (struct semaphore *)param; -repeat: - ignore = down_interruptible(sem); - chain = 0; - while (1) { - if (unlikely(chain > 1)) { - struct crw tmp_crw; - - printk(KERN_WARNING"%s: Code does not support more " - "than two chained crws; please report to " - "linux390@de.ibm.com!\n", __func__); - ccode = stcrw(&tmp_crw); - printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, " - "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", - __func__, tmp_crw.slct, tmp_crw.oflw, - tmp_crw.chn, tmp_crw.rsc, tmp_crw.anc, - tmp_crw.erc, tmp_crw.rsid); - printk(KERN_WARNING"%s: This was crw number %x in the " - "chain\n", __func__, chain); - if (ccode != 0) - break; - chain = tmp_crw.chn ? chain + 1 : 0; - continue; - } - ccode = stcrw(&crw[chain]); - if (ccode != 0) - break; - printk(KERN_DEBUG "crw_info : CRW reports slct=%d, oflw=%d, " - "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", - crw[chain].slct, crw[chain].oflw, crw[chain].chn, - crw[chain].rsc, crw[chain].anc, crw[chain].erc, - crw[chain].rsid); - /* Check for overflows. */ - if (crw[chain].oflw) { - int i; - - pr_debug("%s: crw overflow detected!\n", __func__); - for (i = 0; i < NR_RSCS; i++) { - if (crw_handlers[i]) - crw_handlers[i](NULL, NULL, 1); - } - chain = 0; - continue; - } - if (crw[0].chn && !chain) { - chain++; - continue; - } - if (crw_handlers[crw[chain].rsc]) - crw_handlers[crw[chain].rsc](&crw[0], - chain ? &crw[1] : NULL, - 0); - /* chain is always 0 or 1 here. */ - chain = crw[chain].chn ? chain + 1 : 0; - } - goto repeat; - return 0; -} +#include +#include struct mcck_struct { int kill_task; @@ -142,12 +28,18 @@ struct mcck_struct { static DEFINE_PER_CPU(struct mcck_struct, cpu_mcck); +static NORET_TYPE void s390_handle_damage(char *msg) +{ + smp_send_stop(); + disabled_wait((unsigned long) __builtin_return_address(0)); + while (1); +} + /* * Main machine check handler function. Will be called with interrupts enabled * or disabled and machine checks enabled or disabled. */ -void -s390_handle_mcck(void) +void s390_handle_mcck(void) { unsigned long flags; struct mcck_struct mcck; @@ -166,7 +58,7 @@ s390_handle_mcck(void) local_irq_restore(flags); if (mcck.channel_report) - up(&m_sem); + crw_handle_channel_report(); #ifdef CONFIG_MACHCHK_WARNING /* @@ -204,8 +96,7 @@ EXPORT_SYMBOL_GPL(s390_handle_mcck); * returns 0 if all registers could be validated * returns 1 otherwise */ -static int -s390_revalidate_registers(struct mci *mci) +static int notrace s390_revalidate_registers(struct mci *mci) { int kill_task; u64 tmpclock; @@ -214,22 +105,21 @@ s390_revalidate_registers(struct mci *mci) kill_task = 0; zero = 0; - /* General purpose registers */ - if (!mci->gr) + + if (!mci->gr) { /* * General purpose registers couldn't be restored and have * unknown contents. Process needs to be terminated. */ kill_task = 1; - - /* Revalidate floating point registers */ - if (!mci->fp) + } + if (!mci->fp) { /* * Floating point registers can't be restored and * therefore the process needs to be terminated. */ kill_task = 1; - + } #ifndef CONFIG_64BIT asm volatile( " ld 0,0(%0)\n" @@ -245,9 +135,8 @@ s390_revalidate_registers(struct mci *mci) fpt_creg_save_area = &S390_lowcore.fpt_creg_save_area; #else fpt_save_area = (void *) S390_lowcore.extended_save_area_addr; - fpt_creg_save_area = fpt_save_area+128; + fpt_creg_save_area = fpt_save_area + 128; #endif - /* Floating point control register */ if (!mci->fc) { /* * Floating point control register can't be restored. @@ -278,26 +167,25 @@ s390_revalidate_registers(struct mci *mci) " ld 15,120(%0)\n" : : "a" (fpt_save_area)); } - /* Revalidate access registers */ asm volatile( " lam 0,15,0(%0)" : : "a" (&S390_lowcore.access_regs_save_area)); - if (!mci->ar) + if (!mci->ar) { /* * Access registers have unknown contents. * Terminating task. */ kill_task = 1; - + } /* Revalidate control registers */ - if (!mci->cr) + if (!mci->cr) { /* * Control registers have unknown contents. * Can't recover and therefore stopping machine. */ s390_handle_damage("invalid control registers."); - else + } else { #ifdef CONFIG_64BIT asm volatile( " lctlg 0,15,0(%0)" @@ -307,12 +195,11 @@ s390_revalidate_registers(struct mci *mci) " lctl 0,15,0(%0)" : : "a" (&S390_lowcore.cregs_save_area)); #endif - + } /* * We don't even try to revalidate the TOD register, since we simply * can't write something sensible into that register. */ - #ifdef CONFIG_64BIT /* * See if we can revalidate the TOD programmable register with its @@ -330,7 +217,6 @@ s390_revalidate_registers(struct mci *mci) : : "a" (&S390_lowcore.tod_progreg_save_area) : "0", "cc"); #endif - /* Revalidate clock comparator register */ asm volatile( " stck 0(%1)\n" @@ -354,31 +240,35 @@ s390_revalidate_registers(struct mci *mci) #define MAX_IPD_COUNT 29 #define MAX_IPD_TIME (5 * 60 * USEC_PER_SEC) /* 5 minutes */ +#define ED_STP_ISLAND 6 /* External damage STP island check */ +#define ED_STP_SYNC 7 /* External damage STP sync check */ +#define ED_ETR_SYNC 12 /* External damage ETR sync check */ +#define ED_ETR_SWITCH 13 /* External damage ETR switch to local */ + /* * machine check handler. */ void notrace s390_do_machine_check(struct pt_regs *regs) { + static int ipd_count; static DEFINE_SPINLOCK(ipd_lock); static unsigned long long last_ipd; - static int ipd_count; + struct mcck_struct *mcck; unsigned long long tmp; struct mci *mci; - struct mcck_struct *mcck; int umode; lockdep_off(); - s390_idle_check(); mci = (struct mci *) &S390_lowcore.mcck_interruption_code; mcck = &__get_cpu_var(cpu_mcck); umode = user_mode(regs); - if (mci->sd) + if (mci->sd) { /* System damage -> stopping machine */ s390_handle_damage("received system damage machine check."); - + } if (mci->pd) { if (mci->b) { /* Processing backup -> verify if we can survive this */ @@ -408,24 +298,17 @@ void notrace s390_do_machine_check(struct pt_regs *regs) * Nullifying exigent condition, therefore we might * retry this instruction. */ - spin_lock(&ipd_lock); - tmp = get_clock(); - if (((tmp - last_ipd) >> 12) < MAX_IPD_TIME) ipd_count++; else ipd_count = 1; - last_ipd = tmp; - if (ipd_count == MAX_IPD_COUNT) s390_handle_damage("too many ipd retries."); - spin_unlock(&ipd_lock); - } - else { + } else { /* Processing damage -> stopping machine */ s390_handle_damage("received instruction processing " "damage machine check."); @@ -440,20 +323,18 @@ void notrace s390_do_machine_check(struct pt_regs *regs) mcck->kill_task = 1; mcck->mcck_code = *(unsigned long long *) mci; set_thread_flag(TIF_MCCK_PENDING); - } - else + } else { /* * Couldn't restore all register contents while in * kernel mode -> stopping machine. */ s390_handle_damage("unable to revalidate registers."); + } } - if (mci->cd) { /* Timing facility damage */ s390_handle_damage("TOD clock damaged"); } - if (mci->ed && mci->ec) { /* External damage */ if (S390_lowcore.external_damage_code & (1U << ED_ETR_SYNC)) @@ -465,28 +346,23 @@ void notrace s390_do_machine_check(struct pt_regs *regs) if (S390_lowcore.external_damage_code & (1U << ED_STP_ISLAND)) stp_island_check(); } - if (mci->se) /* Storage error uncorrected */ s390_handle_damage("received storage error uncorrected " "machine check."); - if (mci->ke) /* Storage key-error uncorrected */ s390_handle_damage("received storage key-error uncorrected " "machine check."); - if (mci->ds && mci->fa) /* Storage degradation */ s390_handle_damage("received storage degradation machine " "check."); - if (mci->cp) { /* Channel report word pending */ mcck->channel_report = 1; set_thread_flag(TIF_MCCK_PENDING); } - if (mci->w) { /* Warning pending */ mcck->warning = 1; @@ -495,43 +371,13 @@ void notrace s390_do_machine_check(struct pt_regs *regs) lockdep_on(); } -/* - * s390_init_machine_check - * - * initialize machine check handling - */ -static int -machine_check_init(void) +static int __init machine_check_init(void) { - init_MUTEX_LOCKED(&m_sem); ctl_set_bit(14, 25); /* enable external damage MCH */ - ctl_set_bit(14, 27); /* enable system recovery MCH */ + ctl_set_bit(14, 27); /* enable system recovery MCH */ #ifdef CONFIG_MACHCHK_WARNING ctl_set_bit(14, 24); /* enable warning MCH */ #endif return 0; } - -/* - * Initialize the machine check handler really early to be able to - * catch all machine checks that happen during boot - */ arch_initcall(machine_check_init); - -/* - * Machine checks for the channel subsystem must be enabled - * after the channel subsystem is initialized - */ -static int __init -machine_check_crw_init (void) -{ - struct task_struct *task; - - task = kthread_run(s390_collect_crw_info, &m_sem, "kmcheck"); - if (IS_ERR(task)) - return PTR_ERR(task); - ctl_set_bit(14, 28); /* enable channel report MCH */ - return 0; -} - -device_initcall (machine_check_crw_init); diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index e6b480625cb..bd616fb31e7 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -39,6 +39,7 @@ #include #include #include +#include #include "entry.h" asmlinkage void ret_from_fork(void) asm ("ret_from_fork"); @@ -68,7 +69,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk) return sf->gprs[8]; } -extern void s390_handle_mcck(void); /* * The idle loop on a S390... */ diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index c55a4b9ffd8..caa4d287701 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -23,7 +23,7 @@ #include #include #include - +#include #include "kvm-s390.h" #include "gaccess.h" @@ -440,8 +440,6 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, return -EINVAL; /* not implemented yet */ } -extern void s390_handle_mcck(void); - static void __vcpu_run(struct kvm_vcpu *vcpu) { memcpy(&vcpu->arch.sie_block->gg14, &vcpu->arch.guest_gprs[14], 16); diff --git a/drivers/s390/Makefile b/drivers/s390/Makefile index 0828dc83935..95bccfd3f16 100644 --- a/drivers/s390/Makefile +++ b/drivers/s390/Makefile @@ -2,7 +2,6 @@ # Makefile for the S/390 specific device drivers # -obj-y += s390mach.o obj-y += cio/ block/ char/ crypto/ net/ scsi/ kvm/ drivers-y += drivers/s390/built-in.o diff --git a/drivers/s390/cio/Makefile b/drivers/s390/cio/Makefile index bd79bd16539..adb3dd30152 100644 --- a/drivers/s390/cio/Makefile +++ b/drivers/s390/cio/Makefile @@ -3,7 +3,7 @@ # obj-y += airq.o blacklist.o chsc.o cio.o css.o chp.o idset.o isc.o scsw.o \ - fcx.o itcw.o + fcx.o itcw.o crw.o ccw_device-objs += device.o device_fsm.o device_ops.o ccw_device-objs += device_id.o device_pgid.o device_status.o obj-y += ccw_device.o cmf.o diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index 1246f61a533..3e5f304ad88 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c @@ -17,8 +17,8 @@ #include #include #include +#include -#include "../s390mach.h" #include "cio.h" #include "css.h" #include "ioasm.h" @@ -706,12 +706,12 @@ static int __init chp_init(void) struct chp_id chpid; int ret; - ret = s390_register_crw_handler(CRW_RSC_CPATH, chp_process_crw); + ret = crw_register_handler(CRW_RSC_CPATH, chp_process_crw); if (ret) return ret; chp_wq = create_singlethread_workqueue("cio_chp"); if (!chp_wq) { - s390_unregister_crw_handler(CRW_RSC_CPATH); + crw_unregister_handler(CRW_RSC_CPATH); return -ENOMEM; } INIT_WORK(&cfg_work, cfg_func); diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index ebab6ea4659..7399b07a1ae 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -19,8 +19,8 @@ #include #include #include +#include -#include "../s390mach.h" #include "css.h" #include "cio.h" #include "cio_debug.h" @@ -820,7 +820,7 @@ int __init chsc_alloc_sei_area(void) "chsc machine checks!\n"); return -ENOMEM; } - ret = s390_register_crw_handler(CRW_RSC_CSS, chsc_process_crw); + ret = crw_register_handler(CRW_RSC_CSS, chsc_process_crw); if (ret) kfree(sei_page); return ret; @@ -828,7 +828,7 @@ int __init chsc_alloc_sei_area(void) void __init chsc_free_sei_area(void) { - s390_unregister_crw_handler(CRW_RSC_CSS); + crw_unregister_handler(CRW_RSC_CSS); kfree(sei_page); } diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 659f8a79165..73135c5e9df 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include "cio.h" #include "css.h" #include "chsc.h" @@ -38,7 +40,6 @@ #include "blacklist.h" #include "cio_debug.h" #include "chp.h" -#include "../s390mach.h" debug_info_t *cio_debug_msg_id; debug_info_t *cio_debug_trace_id; diff --git a/drivers/s390/cio/crw.c b/drivers/s390/cio/crw.c new file mode 100644 index 00000000000..508f88f6420 --- /dev/null +++ b/drivers/s390/cio/crw.c @@ -0,0 +1,145 @@ +/* + * Channel report handling code + * + * Copyright IBM Corp. 2000,2009 + * Author(s): Ingo Adlung , + * Martin Schwidefsky , + * Cornelia Huck , + * Heiko Carstens , + */ + +#include +#include +#include +#include + +static struct semaphore crw_semaphore; +static crw_handler_t crw_handlers[NR_RSCS]; + +/** + * crw_register_handler() - register a channel report word handler + * @rsc: reporting source code to handle + * @handler: handler to be registered + * + * Returns %0 on success and a negative error value otherwise. + */ +int crw_register_handler(int rsc, crw_handler_t handler) +{ + if ((rsc < 0) || (rsc >= NR_RSCS)) + return -EINVAL; + if (!cmpxchg(&crw_handlers[rsc], NULL, handler)) + return 0; + return -EBUSY; +} + +/** + * crw_unregister_handler() - unregister a channel report word handler + * @rsc: reporting source code to handle + */ +void crw_unregister_handler(int rsc) +{ + if ((rsc < 0) || (rsc >= NR_RSCS)) + return; + xchg(&crw_handlers[rsc], NULL); + synchronize_sched(); +} + +/* + * Retrieve CRWs and call function to handle event. + */ +static int crw_collect_info(void *unused) +{ + struct crw crw[2]; + int ccode; + unsigned int chain; + int ignore; + +repeat: + ignore = down_interruptible(&crw_semaphore); + chain = 0; + while (1) { + if (unlikely(chain > 1)) { + struct crw tmp_crw; + + printk(KERN_WARNING"%s: Code does not support more " + "than two chained crws; please report to " + "linux390@de.ibm.com!\n", __func__); + ccode = stcrw(&tmp_crw); + printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, " + "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", + __func__, tmp_crw.slct, tmp_crw.oflw, + tmp_crw.chn, tmp_crw.rsc, tmp_crw.anc, + tmp_crw.erc, tmp_crw.rsid); + printk(KERN_WARNING"%s: This was crw number %x in the " + "chain\n", __func__, chain); + if (ccode != 0) + break; + chain = tmp_crw.chn ? chain + 1 : 0; + continue; + } + ccode = stcrw(&crw[chain]); + if (ccode != 0) + break; + printk(KERN_DEBUG "crw_info : CRW reports slct=%d, oflw=%d, " + "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", + crw[chain].slct, crw[chain].oflw, crw[chain].chn, + crw[chain].rsc, crw[chain].anc, crw[chain].erc, + crw[chain].rsid); + /* Check for overflows. */ + if (crw[chain].oflw) { + int i; + + pr_debug("%s: crw overflow detected!\n", __func__); + for (i = 0; i < NR_RSCS; i++) { + if (crw_handlers[i]) + crw_handlers[i](NULL, NULL, 1); + } + chain = 0; + continue; + } + if (crw[0].chn && !chain) { + chain++; + continue; + } + if (crw_handlers[crw[chain].rsc]) + crw_handlers[crw[chain].rsc](&crw[0], + chain ? &crw[1] : NULL, + 0); + /* chain is always 0 or 1 here. */ + chain = crw[chain].chn ? chain + 1 : 0; + } + goto repeat; + return 0; +} + +void crw_handle_channel_report(void) +{ + up(&crw_semaphore); +} + +/* + * Separate initcall needed for semaphore initialization since + * crw_handle_channel_report might be called before crw_machine_check_init. + */ +static int __init crw_init_semaphore(void) +{ + init_MUTEX_LOCKED(&crw_semaphore); + return 0; +} +pure_initcall(crw_init_semaphore); + +/* + * Machine checks for the channel subsystem must be enabled + * after the channel subsystem is initialized + */ +static int __init crw_machine_check_init(void) +{ + struct task_struct *task; + + task = kthread_run(crw_collect_info, NULL, "kmcheck"); + if (IS_ERR(task)) + return PTR_ERR(task); + ctl_set_bit(14, 28); /* enable channel report MCH */ + return 0; +} +device_initcall(crw_machine_check_init); diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 8019288bc6d..a5fc56371ba 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -18,8 +18,8 @@ #include #include #include +#include -#include "../s390mach.h" #include "css.h" #include "cio.h" #include "cio_debug.h" @@ -765,7 +765,7 @@ init_channel_subsystem (void) if (ret) goto out; - ret = s390_register_crw_handler(CRW_RSC_SCH, css_process_crw); + ret = crw_register_handler(CRW_RSC_SCH, css_process_crw); if (ret) goto out; @@ -845,7 +845,7 @@ out_unregister: out_bus: bus_unregister(&css_bus_type); out: - s390_unregister_crw_handler(CRW_RSC_CSS); + crw_unregister_handler(CRW_RSC_CSS); chsc_free_sei_area(); kfree(slow_subchannel_set); pr_alert("The CSS device driver initialization failed with " diff --git a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h deleted file mode 100644 index d39f8b697d2..00000000000 --- a/drivers/s390/s390mach.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * drivers/s390/s390mach.h - * S/390 data definitions for machine check processing - * - * S390 version - * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Ingo Adlung (adlung@de.ibm.com) - */ - -#ifndef __s390mach_h -#define __s390mach_h - -#include - -struct mci { - __u32 sd : 1; /* 00 system damage */ - __u32 pd : 1; /* 01 instruction-processing damage */ - __u32 sr : 1; /* 02 system recovery */ - __u32 to_be_defined_1 : 1; /* 03 */ - __u32 cd : 1; /* 04 timing-facility damage */ - __u32 ed : 1; /* 05 external damage */ - __u32 to_be_defined_2 : 1; /* 06 */ - __u32 dg : 1; /* 07 degradation */ - __u32 w : 1; /* 08 warning pending */ - __u32 cp : 1; /* 09 channel-report pending */ - __u32 sp : 1; /* 10 service-processor damage */ - __u32 ck : 1; /* 11 channel-subsystem damage */ - __u32 to_be_defined_3 : 2; /* 12-13 */ - __u32 b : 1; /* 14 backed up */ - __u32 to_be_defined_4 : 1; /* 15 */ - __u32 se : 1; /* 16 storage error uncorrected */ - __u32 sc : 1; /* 17 storage error corrected */ - __u32 ke : 1; /* 18 storage-key error uncorrected */ - __u32 ds : 1; /* 19 storage degradation */ - __u32 wp : 1; /* 20 psw mwp validity */ - __u32 ms : 1; /* 21 psw mask and key validity */ - __u32 pm : 1; /* 22 psw program mask and cc validity */ - __u32 ia : 1; /* 23 psw instruction address validity */ - __u32 fa : 1; /* 24 failing storage address validity */ - __u32 to_be_defined_5 : 1; /* 25 */ - __u32 ec : 1; /* 26 external damage code validity */ - __u32 fp : 1; /* 27 floating point register validity */ - __u32 gr : 1; /* 28 general register validity */ - __u32 cr : 1; /* 29 control register validity */ - __u32 to_be_defined_6 : 1; /* 30 */ - __u32 st : 1; /* 31 storage logical validity */ - __u32 ie : 1; /* 32 indirect storage error */ - __u32 ar : 1; /* 33 access register validity */ - __u32 da : 1; /* 34 delayed access exception */ - __u32 to_be_defined_7 : 7; /* 35-41 */ - __u32 pr : 1; /* 42 tod programmable register validity */ - __u32 fc : 1; /* 43 fp control register validity */ - __u32 ap : 1; /* 44 ancillary report */ - __u32 to_be_defined_8 : 1; /* 45 */ - __u32 ct : 1; /* 46 cpu timer validity */ - __u32 cc : 1; /* 47 clock comparator validity */ - __u32 to_be_defined_9 : 16; /* 47-63 */ -}; - -/* - * Channel Report Word - */ -struct crw { - __u32 res1 : 1; /* reserved zero */ - __u32 slct : 1; /* solicited */ - __u32 oflw : 1; /* overflow */ - __u32 chn : 1; /* chained */ - __u32 rsc : 4; /* reporting source code */ - __u32 anc : 1; /* ancillary report */ - __u32 res2 : 1; /* reserved zero */ - __u32 erc : 6; /* error-recovery code */ - __u32 rsid : 16; /* reporting-source ID */ -} __attribute__ ((packed)); - -typedef void (*crw_handler_t)(struct crw *, struct crw *, int); - -extern int s390_register_crw_handler(int rsc, crw_handler_t handler); -extern void s390_unregister_crw_handler(int rsc); - -#define NR_RSCS 16 - -#define CRW_RSC_MONITOR 0x2 /* monitoring facility */ -#define CRW_RSC_SCH 0x3 /* subchannel */ -#define CRW_RSC_CPATH 0x4 /* channel path */ -#define CRW_RSC_CONFIG 0x9 /* configuration-alert facility */ -#define CRW_RSC_CSS 0xB /* channel subsystem */ - -#define CRW_ERC_EVENT 0x00 /* event information pending */ -#define CRW_ERC_AVAIL 0x01 /* available */ -#define CRW_ERC_INIT 0x02 /* initialized */ -#define CRW_ERC_TERROR 0x03 /* temporary error */ -#define CRW_ERC_IPARM 0x04 /* installed parm initialized */ -#define CRW_ERC_TERM 0x05 /* terminal */ -#define CRW_ERC_PERRN 0x06 /* perm. error, fac. not init */ -#define CRW_ERC_PERRI 0x07 /* perm. error, facility init */ -#define CRW_ERC_PMOD 0x08 /* installed parameters modified */ - -static inline int stcrw(struct crw *pcrw ) -{ - int ccode; - - __asm__ __volatile__( - "stcrw 0(%2)\n\t" - "ipm %0\n\t" - "srl %0,28\n\t" - : "=d" (ccode), "=m" (*pcrw) - : "a" (pcrw) - : "cc" ); - return ccode; -} - -#define ED_ETR_SYNC 12 /* External damage ETR sync check */ -#define ED_ETR_SWITCH 13 /* External damage ETR switch to local */ - -#define ED_STP_SYNC 7 /* External damage STP sync check */ -#define ED_STP_ISLAND 6 /* External damage STP island check */ - -struct pt_regs; - -void s390_handle_mcck(void); -void s390_do_machine_check(struct pt_regs *regs); -#endif /* __s390mach */ -- GitLab From 7b886416dfd76df9dd7304868556b1d82cf38890 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 26 Mar 2009 15:24:02 +0100 Subject: [PATCH 4629/4982] [S390] Remove CONFIG_MACHCHK_WARNING. Everybody enables it so there is no point for an extra config option. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/Kconfig | 7 ------- arch/s390/kernel/nmi.c | 29 +++++++++++------------------ 2 files changed, 11 insertions(+), 25 deletions(-) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 3f470604a89..0a9463bea75 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -343,13 +343,6 @@ source "mm/Kconfig" comment "I/O subsystem configuration" -config MACHCHK_WARNING - bool "Process warning machine checks" - help - Select this option if you want the machine check handler on IBM S/390 or - zSeries to process warning machine checks (e.g. on power failures). - If unsure, say "Y". - config QDIO tristate "QDIO support" ---help--- diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c index 8d50eaf76a6..4bfdc421d7e 100644 --- a/arch/s390/kernel/nmi.c +++ b/arch/s390/kernel/nmi.c @@ -59,28 +59,23 @@ void s390_handle_mcck(void) if (mcck.channel_report) crw_handle_channel_report(); - -#ifdef CONFIG_MACHCHK_WARNING -/* - * The warning may remain for a prolonged period on the bare iron. - * (actually till the machine is powered off, or until the problem is gone) - * So we just stop listening for the WARNING MCH and prevent continuously - * being interrupted. One caveat is however, that we must do this per - * processor and cannot use the smp version of ctl_clear_bit(). - * On VM we only get one interrupt per virtally presented machinecheck. - * Though one suffices, we may get one interrupt per (virtual) processor. - */ + /* + * A warning may remain for a prolonged period on the bare iron. + * (actually until the machine is powered off, or the problem is gone) + * So we just stop listening for the WARNING MCH and avoid continuously + * being interrupted. One caveat is however, that we must do this per + * processor and cannot use the smp version of ctl_clear_bit(). + * On VM we only get one interrupt per virtally presented machinecheck. + * Though one suffices, we may get one interrupt per (virtual) cpu. + */ if (mcck.warning) { /* WARNING pending ? */ static int mchchk_wng_posted = 0; - /* - * Use single machine clear, as we cannot handle smp right now - */ + + /* Use single cpu clear, as we cannot handle smp here. */ __ctl_clear_bit(14, 24); /* Disable WARNING MCH */ if (xchg(&mchchk_wng_posted, 1) == 0) kill_cad_pid(SIGPWR, 1); } -#endif - if (mcck.kill_task) { local_irq_enable(); printk(KERN_EMERG "mcck: Terminating task because of machine " @@ -375,9 +370,7 @@ static int __init machine_check_init(void) { ctl_set_bit(14, 25); /* enable external damage MCH */ ctl_set_bit(14, 27); /* enable system recovery MCH */ -#ifdef CONFIG_MACHCHK_WARNING ctl_set_bit(14, 24); /* enable warning MCH */ -#endif return 0; } arch_initcall(machine_check_init); -- GitLab From e3dd9c2da674993edb5b52acb56a5d954415639b Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 26 Mar 2009 15:24:03 +0100 Subject: [PATCH 4630/4982] [S390] convert bitmap definitions to C Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/bitops.h | 2 +- arch/s390/kernel/bitmap.S | 56 ---------------------------------- arch/s390/kernel/bitmap.c | 49 +++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 57 deletions(-) delete mode 100644 arch/s390/kernel/bitmap.S create mode 100644 arch/s390/kernel/bitmap.c diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h index 8e9243ae0c1..334964a0fb1 100644 --- a/arch/s390/include/asm/bitops.h +++ b/arch/s390/include/asm/bitops.h @@ -57,7 +57,7 @@ * with operation of the form "set_bit(bitnr, flags)". */ -/* bitmap tables from arch/S390/kernel/bitmap.S */ +/* bitmap tables from arch/s390/kernel/bitmap.c */ extern const char _oi_bitmap[]; extern const char _ni_bitmap[]; extern const char _zb_findmap[]; diff --git a/arch/s390/kernel/bitmap.S b/arch/s390/kernel/bitmap.S deleted file mode 100644 index dfb41f946e2..00000000000 --- a/arch/s390/kernel/bitmap.S +++ /dev/null @@ -1,56 +0,0 @@ -/* - * arch/s390/kernel/bitmap.S - * Bitmaps for set_bit, clear_bit, test_and_set_bit, ... - * See include/asm-s390/{bitops.h|posix_types.h} for details - * - * S390 version - * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), - */ - - .globl _oi_bitmap -_oi_bitmap: - .byte 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 - - .globl _ni_bitmap -_ni_bitmap: - .byte 0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F - - .globl _zb_findmap -_zb_findmap: - .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 - .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5 - .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 - .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6 - .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 - .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5 - .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 - .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7 - .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 - .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5 - .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 - .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6 - .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 - .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5 - .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 - .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8 - - .globl _sb_findmap -_sb_findmap: - .byte 8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 - .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 - .byte 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 - .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 - .byte 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 - .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 - .byte 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 - .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 - .byte 7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 - .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 - .byte 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 - .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 - .byte 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 - .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 - .byte 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 - .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 - diff --git a/arch/s390/kernel/bitmap.c b/arch/s390/kernel/bitmap.c new file mode 100644 index 00000000000..54e362b4267 --- /dev/null +++ b/arch/s390/kernel/bitmap.c @@ -0,0 +1,49 @@ +/* + * Bitmaps for set_bit, clear_bit, test_and_set_bit, ... + * See include/asm/{bitops.h|posix_types.h} for details + * + * Copyright IBM Corp. 1999,2009 + * Author(s): Martin Schwidefsky , + */ + +#include + +const char _oi_bitmap[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; + +const char _ni_bitmap[] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f }; + +const char _zb_findmap[] = { + 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, + 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5, + 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, + 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6, + 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, + 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5, + 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, + 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7, + 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, + 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5, + 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, + 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6, + 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, + 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5, + 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, + 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8 }; + +const char _sb_findmap[] = { + 8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 }; -- GitLab From 1485c5c88483d200c9c4c71ed7e8eef1a1e317a1 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 26 Mar 2009 15:24:04 +0100 Subject: [PATCH 4631/4982] [S390] move EXPORT_SYMBOLs to definitions Move all EXPORT_SYMBOLs to their corresponding definitions. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/bitmap.c | 5 ++++ arch/s390/kernel/process.c | 2 ++ arch/s390/kernel/s390_ksyms.c | 44 ----------------------------------- arch/s390/kernel/setup.c | 8 +++++++ arch/s390/lib/delay.c | 2 ++ arch/s390/mm/init.c | 2 ++ 6 files changed, 19 insertions(+), 44 deletions(-) diff --git a/arch/s390/kernel/bitmap.c b/arch/s390/kernel/bitmap.c index 54e362b4267..3ae4757b006 100644 --- a/arch/s390/kernel/bitmap.c +++ b/arch/s390/kernel/bitmap.c @@ -7,10 +7,13 @@ */ #include +#include const char _oi_bitmap[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; +EXPORT_SYMBOL(_oi_bitmap); const char _ni_bitmap[] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f }; +EXPORT_SYMBOL(_ni_bitmap); const char _zb_findmap[] = { 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, @@ -29,6 +32,7 @@ const char _zb_findmap[] = { 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8 }; +EXPORT_SYMBOL(_zb_findmap); const char _sb_findmap[] = { 8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, @@ -47,3 +51,4 @@ const char _sb_findmap[] = { 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 }; +EXPORT_SYMBOL(_sb_findmap); diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index bd616fb31e7..b48e961a38f 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -141,6 +141,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); } +EXPORT_SYMBOL(kernel_thread); /* * Free current thread data structures etc.. @@ -318,6 +319,7 @@ int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs) #endif /* CONFIG_64BIT */ return 1; } +EXPORT_SYMBOL(dump_fpu); unsigned long get_wchan(struct task_struct *p) { diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c index 46b90cb0370..656fcbb9bd8 100644 --- a/arch/s390/kernel/s390_ksyms.c +++ b/arch/s390/kernel/s390_ksyms.c @@ -1,49 +1,5 @@ -/* - * arch/s390/kernel/s390_ksyms.c - * - * S390 version - */ -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#ifdef CONFIG_IP_MULTICAST -#include -#endif - -/* - * memory management - */ -EXPORT_SYMBOL(_oi_bitmap); -EXPORT_SYMBOL(_ni_bitmap); -EXPORT_SYMBOL(_zb_findmap); -EXPORT_SYMBOL(_sb_findmap); - -/* - * binfmt_elf loader - */ -extern int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs); -EXPORT_SYMBOL(dump_fpu); -EXPORT_SYMBOL(empty_zero_page); - -/* - * misc. - */ -EXPORT_SYMBOL(machine_flags); -EXPORT_SYMBOL(__udelay); -EXPORT_SYMBOL(kernel_thread); -EXPORT_SYMBOL(csum_fold); -EXPORT_SYMBOL(console_mode); -EXPORT_SYMBOL(console_devno); -EXPORT_SYMBOL(console_irq); #ifdef CONFIG_FUNCTION_TRACER EXPORT_SYMBOL(_mcount); diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 8fdf08379ce..0b8ad7b4f8f 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -74,9 +74,17 @@ EXPORT_SYMBOL(uaccess); * Machine setup.. */ unsigned int console_mode = 0; +EXPORT_SYMBOL(console_mode); + unsigned int console_devno = -1; +EXPORT_SYMBOL(console_devno); + unsigned int console_irq = -1; +EXPORT_SYMBOL(console_irq); + unsigned long machine_flags; +EXPORT_SYMBOL(machine_flags); + unsigned long elf_hwcap = 0; char elf_platform[ELF_PLATFORM_SIZE]; diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c index 6ccb9fab055..3f5f680726e 100644 --- a/arch/s390/lib/delay.c +++ b/arch/s390/lib/delay.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -92,6 +93,7 @@ out: local_irq_restore(flags); preempt_enable(); } +EXPORT_SYMBOL(__udelay); /* * Simple udelay variant. To be used on startup and reboot diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index f0258ca3b17..c634dfbe92e 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -40,7 +40,9 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE))); + char empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); +EXPORT_SYMBOL(empty_zero_page); /* * paging_init() sets up the page tables -- GitLab From eb32ae8d0e052d1a287f99f93130ea2ad9af317e Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 26 Mar 2009 15:24:05 +0100 Subject: [PATCH 4632/4982] [S390] cio: Use unbind/bind instead of unregister/register. The common I/O layer may encounter a situation where the device number of a ccw device has changed or a device driver doesn't want to keep a formerly disconnected device becoming operational again. Instead of using device_del()/ device_add() as now, we can just unbind the driver from the device and rebind it to get the desired effect (rebinding) with less overhead. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device.c | 27 +++++++-------------------- drivers/s390/cio/device.h | 2 +- drivers/s390/cio/device_fsm.c | 4 ++-- 3 files changed, 10 insertions(+), 23 deletions(-) diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 23d5752349b..71b3b73e8eb 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -681,35 +681,22 @@ get_orphaned_ccwdev_by_dev_id(struct channel_subsystem *css, return dev ? to_ccwdev(dev) : NULL; } -static void -ccw_device_add_changed(struct work_struct *work) -{ - struct ccw_device_private *priv; - struct ccw_device *cdev; - - priv = container_of(work, struct ccw_device_private, kick_work); - cdev = priv->cdev; - if (device_add(&cdev->dev)) { - put_device(&cdev->dev); - return; - } - set_bit(1, &cdev->private->registered); -} - -void ccw_device_do_unreg_rereg(struct work_struct *work) +void ccw_device_do_unbind_bind(struct work_struct *work) { struct ccw_device_private *priv; struct ccw_device *cdev; struct subchannel *sch; + int ret; priv = container_of(work, struct ccw_device_private, kick_work); cdev = priv->cdev; sch = to_subchannel(cdev->dev.parent); - ccw_device_unregister(cdev); - PREPARE_WORK(&cdev->private->kick_work, - ccw_device_add_changed); - queue_work(ccw_device_work, &cdev->private->kick_work); + if (test_bit(1, &cdev->private->registered)) { + device_release_driver(&cdev->dev); + ret = device_attach(&cdev->dev); + WARN_ON(ret == -ENODEV); + } } static void diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index 0f2e63ea48d..85e01846ca6 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h @@ -80,7 +80,7 @@ void io_subchannel_init_config(struct subchannel *sch); int ccw_device_cancel_halt_clear(struct ccw_device *); -void ccw_device_do_unreg_rereg(struct work_struct *); +void ccw_device_do_unbind_bind(struct work_struct *); void ccw_device_move_to_orphanage(struct work_struct *); int ccw_device_is_orphan(struct ccw_device *); diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 8df5eaafc5a..95f2f352cb9 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -194,7 +194,7 @@ ccw_device_handle_oper(struct ccw_device *cdev) cdev->id.dev_type != cdev->private->senseid.dev_type || cdev->id.dev_model != cdev->private->senseid.dev_model) { PREPARE_WORK(&cdev->private->kick_work, - ccw_device_do_unreg_rereg); + ccw_device_do_unbind_bind); queue_work(ccw_device_work, &cdev->private->kick_work); return 0; } @@ -366,7 +366,7 @@ static void ccw_device_oper_notify(struct ccw_device *cdev) } /* Driver doesn't want device back. */ ccw_device_set_notoper(cdev); - PREPARE_WORK(&cdev->private->kick_work, ccw_device_do_unreg_rereg); + PREPARE_WORK(&cdev->private->kick_work, ccw_device_do_unbind_bind); queue_work(ccw_device_work, &cdev->private->kick_work); } -- GitLab From ed04b892e28ae96662fbb3f4c961df5ff3385d28 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 26 Mar 2009 15:24:06 +0100 Subject: [PATCH 4633/4982] [S390] cio: Try harder to disable subchannel. Acting upon the assumption that cio_disable_subchannel() is only called when we really want to disable the subchannel (a) remove the check for activity (it is already done in ccw_device_offline(), which is the place where it matters) (b) collect pending status via tsch() and ignore it (it can't matter anymore since the subchannel will be disabled). Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/cio.c | 18 ++++++++++-------- drivers/s390/cio/device_fsm.c | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 73135c5e9df..2aebb982304 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -472,6 +472,7 @@ EXPORT_SYMBOL_GPL(cio_enable_subchannel); int cio_disable_subchannel(struct subchannel *sch) { char dbf_txt[15]; + int retry; int ret; CIO_TRACE_EVENT (2, "dissch"); @@ -482,16 +483,17 @@ int cio_disable_subchannel(struct subchannel *sch) if (cio_update_schib(sch)) return -ENODEV; - if (scsw_actl(&sch->schib.scsw) != 0) - /* - * the disable function must not be called while there are - * requests pending for completion ! - */ - return -EBUSY; - sch->config.ena = 0; - ret = cio_commit_config(sch); + for (retry = 0; retry < 3; retry++) { + ret = cio_commit_config(sch); + if (ret == -EBUSY) { + struct irb irb; + if (tsch(sch->schid, &irb) != 0) + break; + } else + break; + } sprintf (dbf_txt, "ret:%d", ret); CIO_TRACE_EVENT (2, dbf_txt); return ret; diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 95f2f352cb9..301d27bf944 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -1052,7 +1052,7 @@ ccw_device_offline_irq(struct ccw_device *cdev, enum dev_event dev_event) sch = to_subchannel(cdev->dev.parent); /* * An interrupt in state offline means a previous disable was not - * successful. Try again. + * successful - should not happen, but we try to disable again. */ cio_disable_subchannel(sch); } -- GitLab From c08f294a14cb4c2abbd1a9a619c2d8d07afd41e3 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 26 Mar 2009 15:24:07 +0100 Subject: [PATCH 4634/4982] [S390] cio: Use ccw_device_set_notoper(). Use ccw_device_set_notoper() (which also deletes the device timer and disables the subchannel) instead of simply setting the state to DEV_STATE_NOT_OPER in the generic not operational handling code. This prevents unexpected interrupts popping up for devices that are deemed not operational. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device_fsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 301d27bf944..87b4bfca080 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -728,7 +728,7 @@ static void ccw_device_generic_notoper(struct ccw_device *cdev, { struct subchannel *sch; - cdev->private->state = DEV_STATE_NOT_OPER; + ccw_device_set_notoper(cdev); sch = to_subchannel(cdev->dev.parent); css_schedule_eval(sch->schid); } -- GitLab From e74fe0cec92439115630b51195444b89b910800a Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Thu, 26 Mar 2009 15:24:08 +0100 Subject: [PATCH 4635/4982] [S390] cio: ccw device online store - report rc from ccw driver. In case the ccw driver refuses to set a device offline, we should transmit the return code to the caller. Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 71b3b73e8eb..9be6dd5a566 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -457,12 +457,13 @@ int ccw_device_set_online(struct ccw_device *cdev) return (ret == 0) ? -ENODEV : ret; } -static void online_store_handle_offline(struct ccw_device *cdev) +static int online_store_handle_offline(struct ccw_device *cdev) { if (cdev->private->state == DEV_STATE_DISCONNECTED) ccw_device_remove_disconnected(cdev); - else if (cdev->drv && cdev->drv->set_offline) - ccw_device_set_offline(cdev); + else if (cdev->online && cdev->drv && cdev->drv->set_offline) + return ccw_device_set_offline(cdev); + return 0; } static int online_store_recog_and_online(struct ccw_device *cdev) @@ -530,13 +531,10 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr, goto out; switch (i) { case 0: - online_store_handle_offline(cdev); - ret = count; + ret = online_store_handle_offline(cdev); break; case 1: ret = online_store_handle_online(cdev, force); - if (!ret) - ret = count; break; default: ret = -EINVAL; @@ -545,7 +543,7 @@ out: if (cdev->drv) module_put(cdev->drv->owner); atomic_set(&cdev->private->onoff, 0); - return ret; + return (ret < 0) ? ret : count; } static ssize_t -- GitLab From 98c1c6825247c71e3d8a9a5439ba21fce7563014 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 26 Mar 2009 15:24:09 +0100 Subject: [PATCH 4636/4982] [S390] cio/crw: add/fix locking The crw_unregister_handler uses xchg + synchronize_sched when unregistering a crw_handler. This doesn't protect crw_collect_info to potentially jump to NULL since it has unlocked code like this: if (crw_handlers[i]) crw_handlers[i](NULL, NULL, 1); So add a mutex which protects the crw handler array for changes. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/crw.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/drivers/s390/cio/crw.c b/drivers/s390/cio/crw.c index 508f88f6420..d157665d0e7 100644 --- a/drivers/s390/cio/crw.c +++ b/drivers/s390/cio/crw.c @@ -9,11 +9,13 @@ */ #include +#include #include #include #include static struct semaphore crw_semaphore; +static DEFINE_MUTEX(crw_handler_mutex); static crw_handler_t crw_handlers[NR_RSCS]; /** @@ -25,11 +27,17 @@ static crw_handler_t crw_handlers[NR_RSCS]; */ int crw_register_handler(int rsc, crw_handler_t handler) { + int rc = 0; + if ((rsc < 0) || (rsc >= NR_RSCS)) return -EINVAL; - if (!cmpxchg(&crw_handlers[rsc], NULL, handler)) - return 0; - return -EBUSY; + mutex_lock(&crw_handler_mutex); + if (crw_handlers[rsc]) + rc = -EBUSY; + else + crw_handlers[rsc] = handler; + mutex_unlock(&crw_handler_mutex); + return rc; } /** @@ -40,8 +48,9 @@ void crw_unregister_handler(int rsc) { if ((rsc < 0) || (rsc >= NR_RSCS)) return; - xchg(&crw_handlers[rsc], NULL); - synchronize_sched(); + mutex_lock(&crw_handler_mutex); + crw_handlers[rsc] = NULL; + mutex_unlock(&crw_handler_mutex); } /* @@ -58,6 +67,8 @@ repeat: ignore = down_interruptible(&crw_semaphore); chain = 0; while (1) { + crw_handler_t handler; + if (unlikely(chain > 1)) { struct crw tmp_crw; @@ -90,10 +101,12 @@ repeat: int i; pr_debug("%s: crw overflow detected!\n", __func__); + mutex_lock(&crw_handler_mutex); for (i = 0; i < NR_RSCS; i++) { if (crw_handlers[i]) crw_handlers[i](NULL, NULL, 1); } + mutex_unlock(&crw_handler_mutex); chain = 0; continue; } @@ -101,10 +114,11 @@ repeat: chain++; continue; } - if (crw_handlers[crw[chain].rsc]) - crw_handlers[crw[chain].rsc](&crw[0], - chain ? &crw[1] : NULL, - 0); + mutex_lock(&crw_handler_mutex); + handler = crw_handlers[crw[chain].rsc]; + if (handler) + handler(&crw[0], chain ? &crw[1] : NULL, 0); + mutex_unlock(&crw_handler_mutex); /* chain is always 0 or 1 here. */ chain = crw[chain].chn ? chain + 1 : 0; } -- GitLab From 87fa5af80cdd5053b27a546725948c2b74ec82b2 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 26 Mar 2009 15:24:10 +0100 Subject: [PATCH 4637/4982] [S390] cio: ensure single load of irq handler pointer Add barrier to prevent compiler from reloading pointer to irq handler. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/airq.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c index fe6cea15bba..d3850dc30e4 100644 --- a/drivers/s390/cio/airq.c +++ b/drivers/s390/cio/airq.c @@ -133,6 +133,8 @@ void do_adapter_IO(u8 isc) while (word) { if (word & INDICATOR_MASK) { airq = airqs[isc][i]; + /* Make sure gcc reads from airqs only once. */ + barrier(); if (likely(airq)) airq->handler(&indicators[isc].byte[i], airq->drv_data); -- GitLab From 90ac24a5aeb8d4bef001bd3589564a52846d0eee Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Thu, 26 Mar 2009 15:24:11 +0100 Subject: [PATCH 4638/4982] [S390] cio: device scan oom fallback. Since some callers rely on for_each_subchannel_staged to not fail, fall back to brute force scanning using get_subchannel_by_schid in case of a oom situation. Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/css.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index a5fc56371ba..1f2e424596a 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -83,6 +83,25 @@ static int call_fn_unknown_sch(struct subchannel_id schid, void *data) return rc; } +static int call_fn_all_sch(struct subchannel_id schid, void *data) +{ + struct cb_data *cb = data; + struct subchannel *sch; + int rc = 0; + + sch = get_subchannel_by_schid(schid); + if (sch) { + if (cb->fn_known_sch) + rc = cb->fn_known_sch(sch, cb->data); + put_device(&sch->dev); + } else { + if (cb->fn_unknown_sch) + rc = cb->fn_unknown_sch(schid, cb->data); + } + + return rc; +} + int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *), int (*fn_unknown)(struct subchannel_id, void *), void *data) @@ -90,13 +109,17 @@ int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *), struct cb_data cb; int rc; - cb.set = idset_sch_new(); - if (!cb.set) - return -ENOMEM; - idset_fill(cb.set); cb.data = data; cb.fn_known_sch = fn_known; cb.fn_unknown_sch = fn_unknown; + + cb.set = idset_sch_new(); + if (!cb.set) + /* fall back to brute force scanning in case of oom */ + return for_each_subchannel(call_fn_all_sch, &cb); + + idset_fill(cb.set); + /* Process registered subchannels. */ rc = bus_for_each_dev(&css_bus_type, NULL, &cb, call_fn_known_sch); if (rc) -- GitLab From a1f640734ab57d548a3fdadad6b869da534d4ecb Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Thu, 26 Mar 2009 15:24:12 +0100 Subject: [PATCH 4639/4982] [S390] cio: airq - fix array boundary MAX_ISC is a valid isc number, so arrays with an index of isc need to have a length of MAX_ISC+1 Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/airq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c index d3850dc30e4..65d2e769dfa 100644 --- a/drivers/s390/cio/airq.c +++ b/drivers/s390/cio/airq.c @@ -34,8 +34,8 @@ struct airq_t { void *drv_data; }; -static union indicator_t indicators[MAX_ISC]; -static struct airq_t *airqs[MAX_ISC][NR_AIRQS]; +static union indicator_t indicators[MAX_ISC+1]; +static struct airq_t *airqs[MAX_ISC+1][NR_AIRQS]; static int register_airq(struct airq_t *airq, u8 isc) { -- GitLab From 40c9f9992bc1caa1bb890bd8163361dbf2eefa86 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Thu, 26 Mar 2009 15:24:13 +0100 Subject: [PATCH 4640/4982] [S390] cio: ccw group online store - report rcs to the caller. In case the ccw group driver refuses to set a device [on|off]line, we should transmit the return code to the caller. Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/ccwgroup.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 918e6fce257..ec2742813bf 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -391,27 +391,28 @@ ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const unsigned long value; int ret; - gdev = to_ccwgroupdev(dev); if (!dev->driver) - return count; + return -ENODEV; + + gdev = to_ccwgroupdev(dev); + gdrv = to_ccwgroupdrv(dev->driver); - gdrv = to_ccwgroupdrv (gdev->dev.driver); if (!try_module_get(gdrv->owner)) return -EINVAL; ret = strict_strtoul(buf, 0, &value); if (ret) goto out; - ret = count; + if (value == 1) - ccwgroup_set_online(gdev); + ret = ccwgroup_set_online(gdev); else if (value == 0) - ccwgroup_set_offline(gdev); + ret = ccwgroup_set_offline(gdev); else ret = -EINVAL; out: module_put(gdrv->owner); - return ret; + return (ret == 0) ? count : ret; } static ssize_t -- GitLab From 50f1548399b7bd00ceb38c84a84463a89c82afe8 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Thu, 26 Mar 2009 15:24:14 +0100 Subject: [PATCH 4641/4982] [S390] cio: fix sanity checks in ccwgroup driver. Some sanity checks in the ccw group driver test the output of container_of macros to be !NULL. Test the input parameters instead. Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/ccwgroup.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index ec2742813bf..2becedbe888 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -454,13 +454,17 @@ ccwgroup_remove (struct device *dev) struct ccwgroup_device *gdev; struct ccwgroup_driver *gdrv; + device_remove_file(dev, &dev_attr_online); + + if (!dev->driver) + return 0; + gdev = to_ccwgroupdev(dev); gdrv = to_ccwgroupdrv(dev->driver); - device_remove_file(dev, &dev_attr_online); - - if (gdrv && gdrv->remove) + if (gdrv->remove) gdrv->remove(gdev); + return 0; } @@ -469,9 +473,13 @@ static void ccwgroup_shutdown(struct device *dev) struct ccwgroup_device *gdev; struct ccwgroup_driver *gdrv; + if (!dev->driver) + return; + gdev = to_ccwgroupdev(dev); gdrv = to_ccwgroupdrv(dev->driver); - if (gdrv && gdrv->shutdown) + + if (gdrv->shutdown) gdrv->shutdown(gdev); } -- GitLab From e909074bb91773680c0b2e49ea8af9f85c6f59bd Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Thu, 26 Mar 2009 15:24:15 +0100 Subject: [PATCH 4642/4982] [S390] cio: ccw group fix unbind behaviour. For a ccw group device unbinding it from its driver should do the same as a call to ungroup, since this virtual device can not exist without a driver. Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/ccwgroup.c | 42 +++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 2becedbe888..86b136cb09e 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -314,16 +314,32 @@ error: } EXPORT_SYMBOL(ccwgroup_create_from_string); -static int __init -init_ccwgroup (void) +static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action, + void *data); + +static struct notifier_block ccwgroup_nb = { + .notifier_call = ccwgroup_notifier +}; + +static int __init init_ccwgroup(void) { - return bus_register (&ccwgroup_bus_type); + int ret; + + ret = bus_register(&ccwgroup_bus_type); + if (ret) + return ret; + + ret = bus_register_notifier(&ccwgroup_bus_type, &ccwgroup_nb); + if (ret) + bus_unregister(&ccwgroup_bus_type); + + return ret; } -static void __exit -cleanup_ccwgroup (void) +static void __exit cleanup_ccwgroup(void) { - bus_unregister (&ccwgroup_bus_type); + bus_unregister_notifier(&ccwgroup_bus_type, &ccwgroup_nb); + bus_unregister(&ccwgroup_bus_type); } module_init(init_ccwgroup); @@ -455,6 +471,7 @@ ccwgroup_remove (struct device *dev) struct ccwgroup_driver *gdrv; device_remove_file(dev, &dev_attr_online); + device_remove_file(dev, &dev_attr_ungroup); if (!dev->driver) return 0; @@ -492,6 +509,19 @@ static struct bus_type ccwgroup_bus_type = { .shutdown = ccwgroup_shutdown, }; + +static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action, + void *data) +{ + struct device *dev = data; + + if (action == BUS_NOTIFY_UNBIND_DRIVER) + device_schedule_callback(dev, ccwgroup_ungroup_callback); + + return NOTIFY_OK; +} + + /** * ccwgroup_driver_register() - register a ccw group driver * @cdriver: driver to be registered -- GitLab From 94cbc203bee4ea87bd49ad56f6c5381bc10d8b6b Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Thu, 26 Mar 2009 15:24:16 +0100 Subject: [PATCH 4643/4982] [S390] cio: fix wrong buffer access in cio_ignore_write Writing only spaces to /proc/cio_ignore will cause a buffer overflow since the size_t value i will not become negative and so buf[-1UL] is accessed. Change the value of i to ssize_t. Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/blacklist.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index fe00be3675c..6565f027791 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c @@ -336,8 +336,7 @@ cio_ignore_write(struct file *file, const char __user *user_buf, size_t user_len, loff_t *offset) { char *buf; - size_t i; - ssize_t rc, ret; + ssize_t rc, ret, i; if (*offset) return -EINVAL; -- GitLab From 17e7d87d9f88480a75fc9c5978ab38131a074277 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Thu, 26 Mar 2009 15:24:17 +0100 Subject: [PATCH 4644/4982] [S390] cio: fix rc generation after chsc call In some situations a rc in __chsc_do_secm will be overwritten by another one. This shouldn't do harm since todays callers don't check for _specific_ errors but fix it for the sake of correctness. Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/chsc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 7399b07a1ae..883f16f96f2 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -589,6 +589,7 @@ __chsc_do_secm(struct channel_subsystem *css, int enable, void *page) case 0x0102: case 0x0103: ret = -EINVAL; + break; default: ret = chsc_error_from_response(secm_area->response.code); } -- GitLab From 7a968f0565dc5d0518c784465cc8ce32408102b7 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Thu, 26 Mar 2009 15:24:18 +0100 Subject: [PATCH 4645/4982] [S390] cio: incorrect status check in interrogate function Fix incorrect check for active I/O in interrogate function. Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device_ops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index eabcc42d63d..151754d5474 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -680,7 +680,7 @@ int ccw_device_tm_intrg(struct ccw_device *cdev) if (cdev->private->state != DEV_STATE_ONLINE) return -EIO; if (!scsw_is_tm(&sch->schib.scsw) || - !(scsw_actl(&sch->schib.scsw) | SCSW_ACTL_START_PEND)) + !(scsw_actl(&sch->schib.scsw) & SCSW_ACTL_START_PEND)) return -EINVAL; return cio_tm_intrg(sch); } -- GitLab From 0cc110651bed4612074eeb445a23418a5ee34cd0 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Thu, 26 Mar 2009 15:24:19 +0100 Subject: [PATCH 4646/4982] [S390] cio: remove unused local variable Remove unused subchannel pointer in io_subchannel_recog_done. Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 9be6dd5a566..a048a5afa12 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -1019,8 +1019,6 @@ static void ccw_device_call_sch_unregister(struct work_struct *work) void io_subchannel_recog_done(struct ccw_device *cdev) { - struct subchannel *sch; - if (css_init_done == 0) { cdev->private->flags.recog_done = 1; return; @@ -1031,7 +1029,6 @@ io_subchannel_recog_done(struct ccw_device *cdev) /* Remove device found not operational. */ if (!get_device(&cdev->dev)) break; - sch = to_subchannel(cdev->dev.parent); PREPARE_WORK(&cdev->private->kick_work, ccw_device_call_sch_unregister); queue_work(slow_path_wq, &cdev->private->kick_work); -- GitLab From 56e25e9777bf15365293e27a3256eb9214a11edf Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Thu, 26 Mar 2009 15:24:20 +0100 Subject: [PATCH 4647/4982] [S390] cio: prevent workqueue deadlock Subchannel reprobing can block the kslowcrw workqueue indefinitely while waiting for device recognition to finish which is also scheduled to run on kslowcrw. Prevent this deadlock by moving the waiting portion of subchannel reprobing to the cio workqueue. Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/css.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 1f2e424596a..8446d15e448 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -533,6 +533,17 @@ static int reprobe_subchannel(struct subchannel_id schid, void *data) return ret; } +static void reprobe_after_idle(struct work_struct *unused) +{ + /* Make sure initial subchannel scan is done. */ + wait_event(ccw_device_init_wq, + atomic_read(&ccw_device_init_count) == 0); + if (need_reprobe) + css_schedule_reprobe(); +} + +static DECLARE_WORK(reprobe_idle_work, reprobe_after_idle); + /* Work function used to reprobe all unregistered subchannels. */ static void reprobe_all(struct work_struct *unused) { @@ -540,10 +551,12 @@ static void reprobe_all(struct work_struct *unused) CIO_MSG_EVENT(4, "reprobe start\n"); - need_reprobe = 0; /* Make sure initial subchannel scan is done. */ - wait_event(ccw_device_init_wq, - atomic_read(&ccw_device_init_count) == 0); + if (atomic_read(&ccw_device_init_count) != 0) { + queue_work(ccw_device_work, &reprobe_idle_work); + return; + } + need_reprobe = 0; ret = for_each_subchannel_staged(NULL, reprobe_subchannel, NULL); CIO_MSG_EVENT(4, "reprobe done (rc=%d, need_reprobe=%d)\n", ret, -- GitLab From 8283cb43ab3e92a039d3486a0f6253df95a5fa55 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 26 Mar 2009 15:24:21 +0100 Subject: [PATCH 4648/4982] [S390] clock sync mode flags The clock sync mode flag CLOCK_SYNC_STP is not cleared when stp is set offline. In this case the get_sync_clock() function returns -EACCESS and the dasd driver will block all i/o until stp is enabled again. In addition get_sync_clock can return -EACCESS if the clock is not in sync instead of -EAGAIN. Rework the stp/etr online handling to fix these problems. Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/time.c | 71 +++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 27 deletions(-) diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index fc468cae446..f72d41068dc 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -331,6 +331,7 @@ static unsigned long long adjust_time(unsigned long long old, } static DEFINE_PER_CPU(atomic_t, clock_sync_word); +static DEFINE_MUTEX(clock_sync_mutex); static unsigned long clock_sync_flags; #define CLOCK_SYNC_HAS_ETR 0 @@ -394,6 +395,20 @@ static void enable_sync_clock(void) atomic_set_mask(0x80000000, sw_ptr); } +/* + * Function to check if the clock is in sync. + */ +static inline int check_sync_clock(void) +{ + atomic_t *sw_ptr; + int rc; + + sw_ptr = &get_cpu_var(clock_sync_word); + rc = (atomic_read(sw_ptr) & 0x80000000U) != 0; + put_cpu_var(clock_sync_sync); + return rc; +} + /* Single threaded workqueue used for etr and stp sync events */ static struct workqueue_struct *time_sync_wq; @@ -485,6 +500,8 @@ static void etr_reset(void) if (etr_setr(&etr_eacr) == 0) { etr_tolec = get_clock(); set_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags); + if (etr_port0_online && etr_port1_online) + set_bit(CLOCK_SYNC_ETR, &clock_sync_flags); } else if (etr_port0_online || etr_port1_online) { pr_warning("The real or virtual hardware system does " "not provide an ETR interface\n"); @@ -533,8 +550,7 @@ void etr_switch_to_local(void) { if (!etr_eacr.sl) return; - if (test_bit(CLOCK_SYNC_ETR, &clock_sync_flags)) - disable_sync_clock(NULL); + disable_sync_clock(NULL); set_bit(ETR_EVENT_SWITCH_LOCAL, &etr_events); queue_work(time_sync_wq, &etr_work); } @@ -549,8 +565,7 @@ void etr_sync_check(void) { if (!etr_eacr.es) return; - if (test_bit(CLOCK_SYNC_ETR, &clock_sync_flags)) - disable_sync_clock(NULL); + disable_sync_clock(NULL); set_bit(ETR_EVENT_SYNC_CHECK, &etr_events); queue_work(time_sync_wq, &etr_work); } @@ -914,7 +929,7 @@ static struct etr_eacr etr_handle_update(struct etr_aib *aib, * Do not try to get the alternate port aib if the clock * is not in sync yet. */ - if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags) && !eacr.es) + if (!check_sync_clock()) return eacr; /* @@ -997,7 +1012,6 @@ static void etr_work_fn(struct work_struct *work) on_each_cpu(disable_sync_clock, NULL, 1); del_timer_sync(&etr_timer); etr_update_eacr(eacr); - clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags); goto out_unlock; } @@ -1071,18 +1085,13 @@ static void etr_work_fn(struct work_struct *work) /* Both ports not usable. */ eacr.es = eacr.sl = 0; sync_port = -1; - clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags); } - if (!test_bit(CLOCK_SYNC_ETR, &clock_sync_flags)) - eacr.es = 0; - /* * If the clock is in sync just update the eacr and return. * If there is no valid sync port wait for a port update. */ - if (test_bit(CLOCK_SYNC_STP, &clock_sync_flags) || - eacr.es || sync_port < 0) { + if (check_sync_clock() || sync_port < 0) { etr_update_eacr(eacr); etr_set_tolec_timeout(now); goto out_unlock; @@ -1103,13 +1112,11 @@ static void etr_work_fn(struct work_struct *work) * and set up a timer to try again after 0.5 seconds */ etr_update_eacr(eacr); - set_bit(CLOCK_SYNC_ETR, &clock_sync_flags); if (now < etr_tolec + (1600000 << 12) || etr_sync_clock_stop(&aib, sync_port) != 0) { /* Sync failed. Try again in 1/2 second. */ eacr.es = 0; etr_update_eacr(eacr); - clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags); etr_set_sync_timeout(); } else etr_set_tolec_timeout(now); @@ -1191,19 +1198,30 @@ static ssize_t etr_online_store(struct sys_device *dev, return -EINVAL; if (!test_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags)) return -EOPNOTSUPP; + mutex_lock(&clock_sync_mutex); if (dev == &etr_port0_dev) { if (etr_port0_online == value) - return count; /* Nothing to do. */ + goto out; /* Nothing to do. */ etr_port0_online = value; + if (etr_port0_online && etr_port1_online) + set_bit(CLOCK_SYNC_ETR, &clock_sync_flags); + else + clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags); set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events); queue_work(time_sync_wq, &etr_work); } else { if (etr_port1_online == value) - return count; /* Nothing to do. */ + goto out; /* Nothing to do. */ etr_port1_online = value; + if (etr_port0_online && etr_port1_online) + set_bit(CLOCK_SYNC_ETR, &clock_sync_flags); + else + clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags); set_bit(ETR_EVENT_PORT1_CHANGE, &etr_events); queue_work(time_sync_wq, &etr_work); } +out: + mutex_unlock(&clock_sync_mutex); return count; } @@ -1471,8 +1489,6 @@ static void stp_timing_alert(struct stp_irq_parm *intparm) */ void stp_sync_check(void) { - if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags)) - return; disable_sync_clock(NULL); queue_work(time_sync_wq, &stp_work); } @@ -1485,8 +1501,6 @@ void stp_sync_check(void) */ void stp_island_check(void) { - if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags)) - return; disable_sync_clock(NULL); queue_work(time_sync_wq, &stp_work); } @@ -1513,10 +1527,6 @@ static int stp_sync_clock(void *data) enable_sync_clock(); - set_bit(CLOCK_SYNC_STP, &clock_sync_flags); - if (test_and_clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags)) - queue_work(time_sync_wq, &etr_work); - rc = 0; if (stp_info.todoff[0] || stp_info.todoff[1] || stp_info.todoff[2] || stp_info.todoff[3] || @@ -1535,9 +1545,6 @@ static int stp_sync_clock(void *data) if (rc) { disable_sync_clock(NULL); stp_sync->in_sync = -EAGAIN; - clear_bit(CLOCK_SYNC_STP, &clock_sync_flags); - if (etr_port0_online || etr_port1_online) - queue_work(time_sync_wq, &etr_work); } else stp_sync->in_sync = 1; xchg(&first, 0); @@ -1569,6 +1576,10 @@ static void stp_work_fn(struct work_struct *work) if (rc || stp_info.c == 0) goto out_unlock; + /* Skip synchronization if the clock is already in sync. */ + if (check_sync_clock()) + goto out_unlock; + memset(&stp_sync, 0, sizeof(stp_sync)); get_online_cpus(); atomic_set(&stp_sync.cpus, num_online_cpus() - 1); @@ -1684,8 +1695,14 @@ static ssize_t stp_online_store(struct sysdev_class *class, return -EINVAL; if (!test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags)) return -EOPNOTSUPP; + mutex_lock(&clock_sync_mutex); stp_online = value; + if (stp_online) + set_bit(CLOCK_SYNC_STP, &clock_sync_flags); + else + clear_bit(CLOCK_SYNC_STP, &clock_sync_flags); queue_work(time_sync_wq, &stp_work); + mutex_unlock(&clock_sync_mutex); return count; } -- GitLab From 4b2a8b6043979f1e6cc8aaa4116c95b31ae942ec Mon Sep 17 00:00:00 2001 From: Gerald Schaefer Date: Thu, 26 Mar 2009 15:24:22 +0100 Subject: [PATCH 4649/4982] [S390] kernel: Disable switch_amode by default Disable switch_amode by default because pagetable walk on pre z9 hardware has negative performance impact. Signed-off-by: Gerald Schaefer Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/setup.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 0b8ad7b4f8f..dd3c5173627 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -301,11 +301,7 @@ static int __init early_parse_mem(char *p) early_param("mem", early_parse_mem); #ifdef CONFIG_S390_SWITCH_AMODE -#ifdef CONFIG_PGSTE -unsigned int switch_amode = 1; -#else unsigned int switch_amode = 0; -#endif EXPORT_SYMBOL_GPL(switch_amode); static int set_amode_and_uaccess(unsigned long user_amode, -- GitLab From feed9b62da6e2997612143ae4b857ec7f33c810d Mon Sep 17 00:00:00 2001 From: Felix Beck Date: Thu, 26 Mar 2009 15:24:23 +0100 Subject: [PATCH 4650/4982] [S390] Add zcrypt section in MAINTAINERS Add zcrypt section in S390 part of MAINTAINERS file. Signed-off-by: Felix Beck Signed-off-by: Ralph Wuerthner Signed-off-by: Martin Schwidefsky --- MAINTAINERS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 5d460c9d1c2..fc1e8d6250e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3726,6 +3726,15 @@ L: linux-s390@vger.kernel.org W: http://www.ibm.com/developerworks/linux/linux390/ S: Supported +S390 ZCRYPT DRIVER +P: Felix Beck +M: felix.beck@de.ibm.com +P: Ralph Wuerthner +M: ralph.wuerthner@de.ibm.com +M: linux390@de.ibm.com +L: linux-s390@vger.kernel.org +S: Supported + S390 ZFCP DRIVER P: Christof Schmitt M: christof.schmitt@de.ibm.com -- GitLab From b454740246d14b0a9c00220696f9020eaa15ca12 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Thu, 26 Mar 2009 15:24:24 +0100 Subject: [PATCH 4651/4982] [S390] qdio: add missing tiq_list locking Add a mutex to protect the tiq_list. Although reading the list is done using RCU adding and removing elements from the list must still happen locked since multiple qdio devices may change the list in parallel otherwise. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/qdio_main.c | 1 + drivers/s390/cio/qdio_thinint.c | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 10cb0f8726e..5100996201d 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -1112,6 +1112,7 @@ int qdio_shutdown(struct ccw_device *cdev, int how) if (!irq_ptr) return -ENODEV; + BUG_ON(irqs_disabled()); DBF_EVENT("qshutdown:%4x", cdev->private->schid.sch_no); mutex_lock(&irq_ptr->setup_mutex); diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index 8e90e147b74..981044c8386 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c @@ -31,6 +31,7 @@ /* list of thin interrupt input queues */ static LIST_HEAD(tiq_list); +DEFINE_MUTEX(tiq_list_lock); /* adapter local summary indicator */ static unsigned char *tiqdio_alsi; @@ -95,10 +96,10 @@ void tiqdio_add_input_queues(struct qdio_irq *irq_ptr) if (!css_qdio_omit_svs && irq_ptr->siga_flag.sync) css_qdio_omit_svs = 1; - for_each_input_queue(irq_ptr, q, i) { + mutex_lock(&tiq_list_lock); + for_each_input_queue(irq_ptr, q, i) list_add_rcu(&q->entry, &tiq_list); - synchronize_rcu(); - } + mutex_unlock(&tiq_list_lock); xchg(irq_ptr->dsci, 1); tasklet_schedule(&tiqdio_tasklet); } @@ -118,7 +119,10 @@ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) /* if establish triggered an error */ if (!q || !q->entry.prev || !q->entry.next) continue; + + mutex_lock(&tiq_list_lock); list_del_rcu(&q->entry); + mutex_unlock(&tiq_list_lock); synchronize_rcu(); } } -- GitLab From e4c14e2085cd32f61e9ffc47d5b20d4f5f7639f3 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Thu, 26 Mar 2009 15:24:25 +0100 Subject: [PATCH 4652/4982] [S390] qdio: Dont call qdio_shutdown in case qdio_activate fails Remove the call to qdio_shutdown from qdio_activate since the upper-layer drivers are responsible to call qdio_shutdown when qdio_activate returns with an error. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/qdio_main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 5100996201d..fa902703996 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -1404,9 +1404,8 @@ int qdio_activate(struct ccw_device *cdev) switch (irq_ptr->state) { case QDIO_IRQ_STATE_STOPPED: case QDIO_IRQ_STATE_ERR: - mutex_unlock(&irq_ptr->setup_mutex); - qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR); - return -EIO; + rc = -EIO; + break; default: qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ACTIVE); rc = 0; -- GitLab From c38f96080955854e54df9cb392bc674e1ae330e1 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Thu, 26 Mar 2009 15:24:26 +0100 Subject: [PATCH 4653/4982] [S390] qdio: proper kill of qdio tasklets The queue tasklets were stopped with tasklet_disable. Although tasklet_disable prevents the tasklet from beeing executed it is still possible that a tasklet is scheduled on a CPU at that point. A following qdio_establish calls tasklet_init which clears the tasklet count and the tasklet state leading to the following Oops: <2>kernel BUG at kernel/softirq.c:392! <4>illegal operation: 0001 [#1] SMP <4>Modules linked in: iptable_filter ip_tables x_tables dm_round_robin dm_multipath scsi_dh sg sd_mod crc_t10dif nfs lockd nfs _acl sunrpc fuse loop dm_mod qeth_l3 ipv6 zfcp qeth scsi_transport_fc qdio scsi_tgt scsi_mod chsc_sch ccwgroup dasd_eckd_mod dasdm od ext3 mbcache jbd <4>Supported: Yes <4>CPU: 0 Not tainted 2.6.27.13-1.1.mz13-default #1 <4>Process blast.LzS_64 (pid: 16445, task: 000000006cc02538, ksp: 000000006cb67998) <4>Krnl PSW : 0704c00180000000 00000000001399f4 (tasklet_action+0xc8/0x1d4) <4> R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:3 CC:0 PM:0 EA:3 <4>Krnl GPRS: ffffffff00000030 0000000000000002 0000000000000002 fffffffffffffffe <4> 000000000013aabe 00000000003b6a18 fffffffffffffffd 0000000000000000 <4> 00000000006705a8 000000007d0914a8 000000007d0914b0 000000007fecfd30 <4> 0000000000000000 00000000003b63e8 000000007fecfd90 000000007fecfd30 <4>Krnl Code: 00000000001399e8: b9200021 cgr %r2,%r1 <4> 00000000001399ec: a7740004 brc 7,1399f4 <4> 00000000001399f0: a7f40001 brc 15,1399f2 <4> >00000000001399f4: c0100027e8ee larl %r1,636bd0 <4> 00000000001399fa: bf1f1008 icm %r1,15,8(%r1) <4> 00000000001399fe: a7840019 brc 8,139a30 <4> 0000000000139a02: c0300027e8ef larl %r3,636be0 <4> 0000000000139a08: e3c030000004 lg %r12,0(%r3) <4>Call Trace: <4>([<0000000000139c12>] tasklet_hi_action+0x112/0x1d4) <4> [<000000000013aabe>] __do_softirq+0xde/0x1c4 <4> [<000000000010fa2e>] do_softirq+0x96/0xb0 <4> [<000000000013a8d8>] irq_exit+0x70/0xcc <4> [<000000000010d1d8>] do_extint+0xf0/0x110 <4> [<0000000000113b10>] ext_no_vtime+0x16/0x1a <4> [<000003e0000a3662>] ext3_dirty_inode+0xe6/0xe8 [ext3] <4>([<00000000001f6cf2>] __mark_inode_dirty+0x52/0x1d4) <4> [<000003e0000a44f0>] ext3_ordered_write_end+0x138/0x190 [ext3] <4> [<000000000018d5ec>] generic_perform_write+0x174/0x230 <4> [<0000000000190144>] generic_file_buffered_write+0xb4/0x194 <4> [<0000000000190864>] __generic_file_aio_write_nolock+0x418/0x454 <4> [<0000000000190ee2>] generic_file_aio_write+0x76/0xe4 <4> [<000003e0000a05c2>] ext3_file_write+0x3e/0xc8 [ext3] <4> [<00000000001cc2fe>] do_sync_write+0xd6/0x120 <4> [<00000000001ccfc8>] vfs_write+0xac/0x184 <4> [<00000000001cd218>] SyS_write+0x68/0xe0 <4> [<0000000000113402>] sysc_noemu+0x10/0x16 <4> [<0000020000043188>] 0x20000043188 <4>Last Breaking-Event-Address: <4> [<00000000001399f0>] tasklet_action+0xc4/0x1d4 <6>qdio: 0.0.c61b ZFCP on SC f67 using AI:1 QEBSM:0 PCI:1 TDD:1 SIGA: W AOP <4> <0>Kernel panic - not syncing: Fatal exception in interrupt Use tasklet_kill instead of tasklet_disbale. Since tasklet_schedule must not be called after tasklet_kill use the QDIO_IRQ_STATE_STOPPED to inidicate that a queue is going down and prevent further tasklet schedules in that case. Remove superflous tasklet_schedule from input queue setup, at that time the queues are not ready so the schedule results in a NOP. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/qdio_main.c | 35 ++++++++++++++++++++++----------- drivers/s390/cio/qdio_thinint.c | 8 ++++---- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index fa902703996..1974ec7bf0e 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -778,21 +778,17 @@ static void __qdio_outbound_processing(struct qdio_q *q) spin_unlock_irqrestore(&q->lock, flags); - if (queue_type(q) == QDIO_ZFCP_QFMT) { + if (queue_type(q) == QDIO_ZFCP_QFMT) if (!pci_out_supported(q) && !qdio_outbound_q_done(q)) - tasklet_schedule(&q->tasklet); - return; - } + goto sched; /* bail out for HiperSockets unicast queues */ if (queue_type(q) == QDIO_IQDIO_QFMT && !multicast_outbound(q)) return; if ((queue_type(q) == QDIO_IQDIO_QFMT) && - (atomic_read(&q->nr_buf_used)) > QDIO_IQDIO_POLL_LVL) { - tasklet_schedule(&q->tasklet); - return; - } + (atomic_read(&q->nr_buf_used)) > QDIO_IQDIO_POLL_LVL) + goto sched; if (q->u.out.pci_out_enabled) return; @@ -810,6 +806,12 @@ static void __qdio_outbound_processing(struct qdio_q *q) qdio_perf_stat_inc(&perf_stats.debug_tl_out_timer); } } + return; + +sched: + if (unlikely(q->irq_ptr->state == QDIO_IRQ_STATE_STOPPED)) + return; + tasklet_schedule(&q->tasklet); } /* outbound tasklet */ @@ -822,6 +824,9 @@ void qdio_outbound_processing(unsigned long data) void qdio_outbound_timer(unsigned long data) { struct qdio_q *q = (struct qdio_q *)data; + + if (unlikely(q->irq_ptr->state == QDIO_IRQ_STATE_STOPPED)) + return; tasklet_schedule(&q->tasklet); } @@ -863,6 +868,9 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr) int i; struct qdio_q *q; + if (unlikely(irq_ptr->state == QDIO_IRQ_STATE_STOPPED)) + return; + qdio_perf_stat_inc(&perf_stats.pci_int); for_each_input_queue(irq_ptr, q, i) @@ -1090,11 +1098,11 @@ static void qdio_shutdown_queues(struct ccw_device *cdev) int i; for_each_input_queue(irq_ptr, q, i) - tasklet_disable(&q->tasklet); + tasklet_kill(&q->tasklet); for_each_output_queue(irq_ptr, q, i) { - tasklet_disable(&q->tasklet); del_timer(&q->u.out.timer); + tasklet_kill(&q->tasklet); } } @@ -1125,6 +1133,12 @@ int qdio_shutdown(struct ccw_device *cdev, int how) return 0; } + /* + * Indicate that the device is going down. Scheduling the queue + * tasklets is forbidden from here on. + */ + qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED); + tiqdio_remove_input_queues(irq_ptr); qdio_shutdown_queues(cdev); qdio_shutdown_debug_entries(irq_ptr, cdev); @@ -1556,7 +1570,6 @@ static void handle_outbound(struct qdio_q *q, unsigned int callflags, qdio_perf_stat_inc(&perf_stats.fast_requeue); } out: - /* Fixme: could wait forever if called from process context */ tasklet_schedule(&q->tasklet); } diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index 981044c8386..c7c5512a892 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c @@ -101,7 +101,6 @@ void tiqdio_add_input_queues(struct qdio_irq *irq_ptr) list_add_rcu(&q->entry, &tiq_list); mutex_unlock(&tiq_list_lock); xchg(irq_ptr->dsci, 1); - tasklet_schedule(&tiqdio_tasklet); } /* @@ -159,7 +158,6 @@ static void __tiqdio_inbound_processing(struct qdio_q *q) */ qdio_check_outbound_after_thinint(q); -again: if (!qdio_inbound_q_moved(q)) return; @@ -167,7 +165,8 @@ again: if (!tiqdio_inbound_q_done(q)) { qdio_perf_stat_inc(&perf_stats.thinint_inbound_loop); - goto again; + if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) + tasklet_schedule(&q->tasklet); } qdio_stop_polling(q); @@ -177,7 +176,8 @@ again: */ if (!tiqdio_inbound_q_done(q)) { qdio_perf_stat_inc(&perf_stats.thinint_inbound_loop2); - goto again; + if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) + tasklet_schedule(&q->tasklet); } } -- GitLab From 700e982f28f5e13cef8eea93ac8c6702f699d894 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Thu, 26 Mar 2009 15:24:27 +0100 Subject: [PATCH 4654/4982] [S390] qdio: call qdio_free also if qdio_shutdown fails qdio_cleanup is a wrapper function that should call qdio_shutdown and qdio_free. qdio_free was not called if an error occured in qdio_shutdown resulting in a missing free of allocated resources. Call qdio_free regardless of the return value of qdio_shutdown. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/qdio_main.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 1974ec7bf0e..8e6bc9cddfa 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -1073,8 +1073,9 @@ EXPORT_SYMBOL_GPL(qdio_get_ssqd_desc); * @cdev: associated ccw device * @how: use halt or clear to shutdown * - * This function calls qdio_shutdown() for @cdev with method @how - * and on success qdio_free() for @cdev. + * This function calls qdio_shutdown() for @cdev with method @how. + * and qdio_free(). The qdio_free() return value is ignored since + * !irq_ptr is already checked. */ int qdio_cleanup(struct ccw_device *cdev, int how) { @@ -1085,8 +1086,8 @@ int qdio_cleanup(struct ccw_device *cdev, int how) return -ENODEV; rc = qdio_shutdown(cdev, how); - if (rc == 0) - rc = qdio_free(cdev); + + qdio_free(cdev); return rc; } EXPORT_SYMBOL_GPL(qdio_cleanup); -- GitLab From 3fdf1e18cbc7c58f2d5604315ddae3596725bc6a Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Thu, 26 Mar 2009 15:24:28 +0100 Subject: [PATCH 4655/4982] [S390] qdio: move ACK to newest buffer for devices without QEBSM The ACKnowledgement state should be set on the newest SBAL so an adapter interrupt surpression check needs to scan fewer SBALs. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/qdio_main.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 8e6bc9cddfa..61ba765936a 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -440,12 +440,16 @@ static inline void inbound_primed(struct qdio_q *q, int count) /* reset the previous ACK but first set the new one */ set_buf_state(q, new, SLSB_P_INPUT_ACK); set_buf_state(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT); - } - else { + } else { q->u.in.polling = 1; - set_buf_state(q, q->first_to_check, SLSB_P_INPUT_ACK); + set_buf_state(q, new, SLSB_P_INPUT_ACK); } + /* + * last_move_ftc points to the ACK'ed buffer and not to the last turns + * first_to_check like for qebsm. Since it is only used to check if + * the queue front moved in qdio_inbound_q_done this is not a problem. + */ q->last_move_ftc = new; count--; if (!count) @@ -455,7 +459,7 @@ static inline void inbound_primed(struct qdio_q *q, int count) * Need to change all PRIMED buffers to NOT_INIT, otherwise * we're loosing initiative in the thinint code. */ - set_buf_states(q, next_buf(q->first_to_check), SLSB_P_INPUT_NOT_INIT, + set_buf_states(q, q->first_to_check, SLSB_P_INPUT_NOT_INIT, count); } @@ -1480,7 +1484,6 @@ static void handle_inbound(struct qdio_q *q, unsigned int callflags, if (q->u.in.ack_count <= 0) { q->u.in.polling = 0; q->u.in.ack_count = 0; - /* TODO: must we set last_move_ftc to something meaningful? */ goto set; } q->last_move_ftc = add_buf(q->last_move_ftc, diff); -- GitLab From e85dea0e415617b5c5627f38c71b33fbc7f94a85 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Thu, 26 Mar 2009 15:24:29 +0100 Subject: [PATCH 4656/4982] [S390] qdio: seperate last move index and polling index The index value that indicated that the input queue moved was also used to store the index of the first acknowledged buffer. For non-qebsm only the newest buffer is acknowledged which may be different from the last move index so two seperate values are needed to track the input queue. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/qdio.h | 5 ++++- drivers/s390/cio/qdio_debug.c | 3 ++- drivers/s390/cio/qdio_main.c | 38 ++++++++++++++++------------------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 42f2b09631b..57807f5ffe8 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -186,6 +186,9 @@ struct qdio_input_q { /* input buffer acknowledgement flag */ int polling; + /* first ACK'ed buffer */ + int ack_start; + /* how much sbals are acknowledged with qebsm */ int ack_count; @@ -234,7 +237,7 @@ struct qdio_q { int first_to_check; /* first_to_check of the last time */ - int last_move_ftc; + int last_move; /* beginning position for calling the program */ int first_to_kick; diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c index da7afb04e71..e3434b34f86 100644 --- a/drivers/s390/cio/qdio_debug.c +++ b/drivers/s390/cio/qdio_debug.c @@ -63,8 +63,9 @@ static int qstat_show(struct seq_file *m, void *v) seq_printf(m, "device state indicator: %d\n", *(u32 *)q->irq_ptr->dsci); seq_printf(m, "nr_used: %d\n", atomic_read(&q->nr_buf_used)); seq_printf(m, "ftc: %d\n", q->first_to_check); - seq_printf(m, "last_move_ftc: %d\n", q->last_move_ftc); + seq_printf(m, "last_move: %d\n", q->last_move); seq_printf(m, "polling: %d\n", q->u.in.polling); + seq_printf(m, "ack start: %d\n", q->u.in.ack_start); seq_printf(m, "ack count: %d\n", q->u.in.ack_count); seq_printf(m, "slsb buffer states:\n"); seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n"); diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 61ba765936a..31b9318149b 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -380,11 +380,11 @@ inline void qdio_stop_polling(struct qdio_q *q) /* show the card that we are not polling anymore */ if (is_qebsm(q)) { - set_buf_states(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT, + set_buf_states(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT, q->u.in.ack_count); q->u.in.ack_count = 0; } else - set_buf_state(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT); + set_buf_state(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT); } static void announce_buffer_error(struct qdio_q *q, int count) @@ -419,15 +419,15 @@ static inline void inbound_primed(struct qdio_q *q, int count) if (!q->u.in.polling) { q->u.in.polling = 1; q->u.in.ack_count = count; - q->last_move_ftc = q->first_to_check; + q->u.in.ack_start = q->first_to_check; return; } /* delete the previous ACK's */ - set_buf_states(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT, + set_buf_states(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT, q->u.in.ack_count); q->u.in.ack_count = count; - q->last_move_ftc = q->first_to_check; + q->u.in.ack_start = q->first_to_check; return; } @@ -439,18 +439,13 @@ static inline void inbound_primed(struct qdio_q *q, int count) if (q->u.in.polling) { /* reset the previous ACK but first set the new one */ set_buf_state(q, new, SLSB_P_INPUT_ACK); - set_buf_state(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT); + set_buf_state(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT); } else { q->u.in.polling = 1; set_buf_state(q, new, SLSB_P_INPUT_ACK); } - /* - * last_move_ftc points to the ACK'ed buffer and not to the last turns - * first_to_check like for qebsm. Since it is only used to check if - * the queue front moved in qdio_inbound_q_done this is not a problem. - */ - q->last_move_ftc = new; + q->u.in.ack_start = new; count--; if (!count) return; @@ -527,7 +522,8 @@ int qdio_inbound_q_moved(struct qdio_q *q) bufnr = get_inbound_buffer_frontier(q); - if ((bufnr != q->last_move_ftc) || q->qdio_error) { + if ((bufnr != q->last_move) || q->qdio_error) { + q->last_move = bufnr; if (!need_siga_sync(q) && !pci_out_supported(q)) q->u.in.timestamp = get_usecs(); @@ -702,8 +698,8 @@ static inline int qdio_outbound_q_moved(struct qdio_q *q) bufnr = get_outbound_buffer_frontier(q); - if ((bufnr != q->last_move_ftc) || q->qdio_error) { - q->last_move_ftc = bufnr; + if ((bufnr != q->last_move) || q->qdio_error) { + q->last_move = bufnr; DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out moved:%1d", q->nr); return 1; } else @@ -748,7 +744,7 @@ static void qdio_kick_outbound_handler(struct qdio_q *q) int start, end, count; start = q->first_to_kick; - end = q->last_move_ftc; + end = q->last_move; if (end >= start) count = end - start; else @@ -764,7 +760,7 @@ static void qdio_kick_outbound_handler(struct qdio_q *q) q->irq_ptr->int_parm); /* for the next time: */ - q->first_to_kick = q->last_move_ftc; + q->first_to_kick = q->last_move; q->qdio_error = 0; } @@ -1475,18 +1471,18 @@ static void handle_inbound(struct qdio_q *q, unsigned int callflags, q->u.in.polling = 0; q->u.in.ack_count = 0; goto set; - } else if (buf_in_between(q->last_move_ftc, bufnr, count)) { + } else if (buf_in_between(q->u.in.ack_start, bufnr, count)) { if (is_qebsm(q)) { - /* partial overwrite, just update last_move_ftc */ + /* partial overwrite, just update ack_start */ diff = add_buf(bufnr, count); - diff = sub_buf(diff, q->last_move_ftc); + diff = sub_buf(diff, q->u.in.ack_start); q->u.in.ack_count -= diff; if (q->u.in.ack_count <= 0) { q->u.in.polling = 0; q->u.in.ack_count = 0; goto set; } - q->last_move_ftc = add_buf(q->last_move_ftc, diff); + q->u.in.ack_start = add_buf(q->u.in.ack_start, diff); } else /* the only ACK will be deleted, so stop polling */ -- GitLab From 9e890ad880be1dd98483313b2ec0e23fbd4e3792 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Thu, 26 Mar 2009 15:24:30 +0100 Subject: [PATCH 4657/4982] [S390] qdio: tasklet termination in case of module unload If the qdio module is unloaded the tiqdio tasklet must be terminated by tasklet_kill. Move the tasklet_kill after the unregistration of the adapter interrupt so the tiqdio tasklet will not be scheduled anymore before calling tasklet_kill. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/qdio_thinint.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index c7c5512a892..96f0095f568 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c @@ -370,10 +370,11 @@ void qdio_shutdown_thinint(struct qdio_irq *irq_ptr) void __exit tiqdio_unregister_thinints(void) { - tasklet_disable(&tiqdio_tasklet); + WARN_ON(!list_empty(&tiq_list)); if (tiqdio_alsi) { s390_unregister_adapter_interrupt(tiqdio_alsi, QDIO_AIRQ_ISC); isc_unregister(QDIO_AIRQ_ISC); } + tasklet_kill(&tiqdio_tasklet); } -- GitLab From d303b6fd858370c22d5c70c313669e3521a5f758 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Thu, 26 Mar 2009 15:24:31 +0100 Subject: [PATCH 4658/4982] [S390] qdio: report SIGA errors directly Errors from SIGA instructions are stored in the per queue qdio_error and reported back when the queue handler is called. That opens a race when multiple error conditions occur simultanously. Report SIGA errors immediately in the return value of do_QDIO so the upper layer can react and SIGA errors no longer interfere with other errors. Move the SIGA error handling in qeth from the outbound handler to qeth_flush_buffers. Signed-off-by: Jan Glauber --- arch/s390/include/asm/qdio.h | 1 + drivers/s390/cio/qdio.h | 1 - drivers/s390/cio/qdio_main.c | 73 +++++++++++++------------------ drivers/s390/cio/qdio_setup.c | 1 - drivers/s390/net/qeth_core_main.c | 55 +++++++---------------- 5 files changed, 48 insertions(+), 83 deletions(-) diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h index 27fc1746de1..402d6dcf0d2 100644 --- a/arch/s390/include/asm/qdio.h +++ b/arch/s390/include/asm/qdio.h @@ -314,6 +314,7 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int, int, int, unsigned long); /* qdio errors reported to the upper-layer program */ +#define QDIO_ERROR_SIGA_TARGET 0x02 #define QDIO_ERROR_SIGA_ACCESS_EXCEPTION 0x10 #define QDIO_ERROR_SIGA_BUSY 0x20 #define QDIO_ERROR_ACTIVATE_CHECK_CONDITION 0x40 diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 57807f5ffe8..41171d741f3 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -247,7 +247,6 @@ struct qdio_q { struct qdio_irq *irq_ptr; struct tasklet_struct tasklet; - spinlock_t lock; /* error condition during a data transfer */ unsigned int qdio_error; diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 31b9318149b..e53ac67e1e4 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -706,13 +706,13 @@ static inline int qdio_outbound_q_moved(struct qdio_q *q) return 0; } -static void qdio_kick_outbound_q(struct qdio_q *q) +static int qdio_kick_outbound_q(struct qdio_q *q) { unsigned int busy_bit; int cc; if (!need_siga_out(q)) - return; + return 0; DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w:%1d", q->nr); qdio_perf_stat_inc(&perf_stats.siga_out); @@ -724,19 +724,16 @@ static void qdio_kick_outbound_q(struct qdio_q *q) case 2: if (busy_bit) { DBF_ERROR("%4x cc2 REP:%1d", SCH_NO(q), q->nr); - q->qdio_error = cc | QDIO_ERROR_SIGA_BUSY; - } else { - DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w cc2:%1d", - q->nr); - q->qdio_error = cc; - } + cc |= QDIO_ERROR_SIGA_BUSY; + } else + DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w cc2:%1d", q->nr); break; case 1: case 3: DBF_ERROR("%4x SIGA-W:%1d", SCH_NO(q), cc); - q->qdio_error = cc; break; } + return cc; } static void qdio_kick_outbound_handler(struct qdio_q *q) @@ -766,18 +763,12 @@ static void qdio_kick_outbound_handler(struct qdio_q *q) static void __qdio_outbound_processing(struct qdio_q *q) { - unsigned long flags; - qdio_perf_stat_inc(&perf_stats.tasklet_outbound); - spin_lock_irqsave(&q->lock, flags); - BUG_ON(atomic_read(&q->nr_buf_used) < 0); if (qdio_outbound_q_moved(q)) qdio_kick_outbound_handler(q); - spin_unlock_irqrestore(&q->lock, flags); - if (queue_type(q) == QDIO_ZFCP_QFMT) if (!pci_out_supported(q) && !qdio_outbound_q_done(q)) goto sched; @@ -1457,10 +1448,10 @@ static inline int buf_in_between(int bufnr, int start, int count) * @bufnr: first buffer to process * @count: how many buffers are emptied */ -static void handle_inbound(struct qdio_q *q, unsigned int callflags, - int bufnr, int count) +static int handle_inbound(struct qdio_q *q, unsigned int callflags, + int bufnr, int count) { - int used, cc, diff; + int used, diff; if (!q->u.in.polling) goto set; @@ -1497,13 +1488,11 @@ set: /* no need to signal as long as the adapter had free buffers */ if (used) - return; + return 0; - if (need_siga_in(q)) { - cc = qdio_siga_input(q); - if (cc) - q->qdio_error = cc; - } + if (need_siga_in(q)) + return qdio_siga_input(q); + return 0; } /** @@ -1513,11 +1502,11 @@ set: * @bufnr: first buffer to process * @count: how many buffers are filled */ -static void handle_outbound(struct qdio_q *q, unsigned int callflags, - int bufnr, int count) +static int handle_outbound(struct qdio_q *q, unsigned int callflags, + int bufnr, int count) { unsigned char state; - int used; + int used, rc = 0; qdio_perf_stat_inc(&perf_stats.outbound_handler); @@ -1532,27 +1521,26 @@ static void handle_outbound(struct qdio_q *q, unsigned int callflags, if (queue_type(q) == QDIO_IQDIO_QFMT) { if (multicast_outbound(q)) - qdio_kick_outbound_q(q); + rc = qdio_kick_outbound_q(q); else if ((q->irq_ptr->ssqd_desc.mmwc > 1) && (count > 1) && (count <= q->irq_ptr->ssqd_desc.mmwc)) { /* exploit enhanced SIGA */ q->u.out.use_enh_siga = 1; - qdio_kick_outbound_q(q); + rc = qdio_kick_outbound_q(q); } else { /* * One siga-w per buffer required for unicast * HiperSockets. */ q->u.out.use_enh_siga = 0; - while (count--) - qdio_kick_outbound_q(q); + while (count--) { + rc = qdio_kick_outbound_q(q); + if (rc) + goto out; + } } - - /* report CC=2 conditions synchronously */ - if (q->qdio_error) - __qdio_outbound_processing(q); goto out; } @@ -1564,13 +1552,14 @@ static void handle_outbound(struct qdio_q *q, unsigned int callflags, /* try to fast requeue buffers */ get_buf_state(q, prev_buf(bufnr), &state, 0); if (state != SLSB_CU_OUTPUT_PRIMED) - qdio_kick_outbound_q(q); + rc = qdio_kick_outbound_q(q); else { DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "fast-req"); qdio_perf_stat_inc(&perf_stats.fast_requeue); } out: tasklet_schedule(&q->tasklet); + return rc; } /** @@ -1609,14 +1598,12 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags, return -EBUSY; if (callflags & QDIO_FLAG_SYNC_INPUT) - handle_inbound(irq_ptr->input_qs[q_nr], callflags, bufnr, - count); + return handle_inbound(irq_ptr->input_qs[q_nr], + callflags, bufnr, count); else if (callflags & QDIO_FLAG_SYNC_OUTPUT) - handle_outbound(irq_ptr->output_qs[q_nr], callflags, bufnr, - count); - else - return -EINVAL; - return 0; + return handle_outbound(irq_ptr->output_qs[q_nr], + callflags, bufnr, count); + return -EINVAL; } EXPORT_SYMBOL_GPL(do_QDIO); diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index c08356b95bf..18d54fc21ce 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c @@ -117,7 +117,6 @@ static void setup_queues_misc(struct qdio_q *q, struct qdio_irq *irq_ptr, q->mask = 1 << (31 - i); q->nr = i; q->handler = handler; - spin_lock_init(&q->lock); } static void setup_storage_lists(struct qdio_q *q, struct qdio_irq *irq_ptr, diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index d1b5bebea7f..2489bcebf5e 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -2693,40 +2693,21 @@ static int qeth_handle_send_error(struct qeth_card *card, struct qeth_qdio_out_buffer *buffer, unsigned int qdio_err) { int sbalf15 = buffer->buffer->element[15].flags & 0xff; - int cc = qdio_err & 3; QETH_DBF_TEXT(TRACE, 6, "hdsnderr"); qeth_check_qdio_errors(buffer->buffer, qdio_err, "qouterr"); - switch (cc) { - case 0: - if (qdio_err) { - QETH_DBF_TEXT(TRACE, 1, "lnkfail"); - QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card)); - QETH_DBF_TEXT_(TRACE, 1, "%04x %02x", - (u16)qdio_err, (u8)sbalf15); - return QETH_SEND_ERROR_LINK_FAILURE; - } + + if (!qdio_err) return QETH_SEND_ERROR_NONE; - case 2: - if (qdio_err & QDIO_ERROR_SIGA_BUSY) { - QETH_DBF_TEXT(TRACE, 1, "SIGAcc2B"); - QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card)); - return QETH_SEND_ERROR_KICK_IT; - } - if ((sbalf15 >= 15) && (sbalf15 <= 31)) - return QETH_SEND_ERROR_RETRY; - return QETH_SEND_ERROR_LINK_FAILURE; - /* look at qdio_error and sbalf 15 */ - case 1: - QETH_DBF_TEXT(TRACE, 1, "SIGAcc1"); - QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card)); - return QETH_SEND_ERROR_LINK_FAILURE; - case 3: - default: - QETH_DBF_TEXT(TRACE, 1, "SIGAcc3"); - QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card)); - return QETH_SEND_ERROR_KICK_IT; - } + + if ((sbalf15 >= 15) && (sbalf15 <= 31)) + return QETH_SEND_ERROR_RETRY; + + QETH_DBF_TEXT(TRACE, 1, "lnkfail"); + QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card)); + QETH_DBF_TEXT_(TRACE, 1, "%04x %02x", + (u16)qdio_err, (u8)sbalf15); + return QETH_SEND_ERROR_LINK_FAILURE; } /* @@ -2862,10 +2843,14 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, qeth_get_micros() - queue->card->perf_stats.outbound_do_qdio_start_time; if (rc) { + queue->card->stats.tx_errors += count; + /* ignore temporary SIGA errors without busy condition */ + if (rc == QDIO_ERROR_SIGA_TARGET) + return; QETH_DBF_TEXT(TRACE, 2, "flushbuf"); QETH_DBF_TEXT_(TRACE, 2, " err%d", rc); QETH_DBF_TEXT_(TRACE, 2, "%s", CARD_DDEV_ID(queue->card)); - queue->card->stats.tx_errors += count; + /* this must not happen under normal circumstances. if it * happens something is really wrong -> recover */ qeth_schedule_recovery(queue->card); @@ -2940,13 +2925,7 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev, } for (i = first_element; i < (first_element + count); ++i) { buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; - /*we only handle the KICK_IT error by doing a recovery */ - if (qeth_handle_send_error(card, buffer, qdio_error) - == QETH_SEND_ERROR_KICK_IT){ - netif_stop_queue(card->dev); - qeth_schedule_recovery(card); - return; - } + qeth_handle_send_error(card, buffer, qdio_error); qeth_clear_output_buffer(queue, buffer); } atomic_sub(count, &queue->used_buffers); -- GitLab From 9c8a08d7a74b07ab2c47e259231d9d0f0047a3c1 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Thu, 26 Mar 2009 15:24:32 +0100 Subject: [PATCH 4659/4982] [S390] qdio: merge inbound and outbound handler functions The inbound and outbound handlers are nearly identical if the outbound handler uses first_to_check as end index instead of last_move. Since both values are identical at that point the handlers can be merged. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/qdio.h | 2 +- drivers/s390/cio/qdio_main.c | 62 ++++++++++----------------------- drivers/s390/cio/qdio_thinint.c | 2 +- 3 files changed, 21 insertions(+), 45 deletions(-) diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 41171d741f3..13bcb811438 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -356,7 +356,7 @@ int get_buf_state(struct qdio_q *q, unsigned int bufnr, unsigned char *state, int auto_ack); void qdio_check_outbound_after_thinint(struct qdio_q *q); int qdio_inbound_q_moved(struct qdio_q *q); -void qdio_kick_inbound_handler(struct qdio_q *q); +void qdio_kick_handler(struct qdio_q *q); void qdio_stop_polling(struct qdio_q *q); int qdio_siga_sync_q(struct qdio_q *q); diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index e53ac67e1e4..9e8a2914259 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -570,29 +570,30 @@ static int qdio_inbound_q_done(struct qdio_q *q) } } -void qdio_kick_inbound_handler(struct qdio_q *q) +void qdio_kick_handler(struct qdio_q *q) { - int count, start, end; - - qdio_perf_stat_inc(&perf_stats.inbound_handler); - - start = q->first_to_kick; - end = q->first_to_check; - if (end >= start) - count = end - start; - else - count = end + QDIO_MAX_BUFFERS_PER_Q - start; - - DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%3d c:%3d", start, count); + int start = q->first_to_kick; + int end = q->first_to_check; + int count; if (unlikely(q->irq_ptr->state != QDIO_IRQ_STATE_ACTIVE)) return; - q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, - start, count, q->irq_ptr->int_parm); + count = sub_buf(end, start); + + if (q->is_input_q) { + qdio_perf_stat_inc(&perf_stats.inbound_handler); + DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%3d c:%3d", start, count); + } else { + DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "koh: nr:%1d", q->nr); + DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "s:%3d c:%3d", start, count); + } + + q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, start, count, + q->irq_ptr->int_parm); /* for the next time */ - q->first_to_kick = q->first_to_check; + q->first_to_kick = end; q->qdio_error = 0; } @@ -603,7 +604,7 @@ again: if (!qdio_inbound_q_moved(q)) return; - qdio_kick_inbound_handler(q); + qdio_kick_handler(q); if (!qdio_inbound_q_done(q)) /* means poll time is not yet over */ @@ -736,38 +737,13 @@ static int qdio_kick_outbound_q(struct qdio_q *q) return cc; } -static void qdio_kick_outbound_handler(struct qdio_q *q) -{ - int start, end, count; - - start = q->first_to_kick; - end = q->last_move; - if (end >= start) - count = end - start; - else - count = end + QDIO_MAX_BUFFERS_PER_Q - start; - - DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kickouth: %1d", q->nr); - DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "s:%3d c:%3d", start, count); - - if (unlikely(q->irq_ptr->state != QDIO_IRQ_STATE_ACTIVE)) - return; - - q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, start, count, - q->irq_ptr->int_parm); - - /* for the next time: */ - q->first_to_kick = q->last_move; - q->qdio_error = 0; -} - static void __qdio_outbound_processing(struct qdio_q *q) { qdio_perf_stat_inc(&perf_stats.tasklet_outbound); BUG_ON(atomic_read(&q->nr_buf_used) < 0); if (qdio_outbound_q_moved(q)) - qdio_kick_outbound_handler(q); + qdio_kick_handler(q); if (queue_type(q) == QDIO_ZFCP_QFMT) if (!pci_out_supported(q) && !qdio_outbound_q_done(q)) diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index 96f0095f568..c655d011a78 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c @@ -161,7 +161,7 @@ static void __tiqdio_inbound_processing(struct qdio_q *q) if (!qdio_inbound_q_moved(q)) return; - qdio_kick_inbound_handler(q); + qdio_kick_handler(q); if (!tiqdio_inbound_q_done(q)) { qdio_perf_stat_inc(&perf_stats.thinint_inbound_loop); -- GitLab From 6faf250789dfd35146a71402f9be245be82bf01e Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 26 Mar 2009 15:24:33 +0100 Subject: [PATCH 4660/4982] [S390] allow usage of string functions in linux/string.h In introducing a trivial "strstarts()" function in linux/string.h, we hit the following error on s390: In file included from include/linux/bitmap.h:8, from include/linux/cpumask.h:142, from include/linux/smp.h:12, from /home/rusty/devel/kernel/patches/linux-2.6/arch/s390/include/asm/spinlock.h:14, from include/linux/spinlock.h:88, from include/linux/seqlock.h:29, from include/linux/time.h:8, from include/linux/stat.h:60, from include/linux/module.h:10, from arch/s390/lib/string.c:13: include/linux/string.h: In function 'strstarts': include/linux/string.h:124: error: implicit declaration of function 'strlen' include/linux/string.h:124: warning: incompatible implicit declaration of built-in function 'strlen' Because when including asm/string.h from arch/s390/lib/string.c we don't declare the string ops we are about to define, and linux/string.h barfs. The fix is to declare them in this IN_ARCH_STRING_C case, but in general I wonder if there's a neater fix. Reported-by: linux-next Signed-off-by: Rusty Russell Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/string.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/s390/include/asm/string.h b/arch/s390/include/asm/string.h index d074673a6d9..adf079170aa 100644 --- a/arch/s390/include/asm/string.h +++ b/arch/s390/include/asm/string.h @@ -135,7 +135,13 @@ static inline size_t strnlen(const char * s, size_t n) : "+a" (end), "+a" (tmp) : "d" (r0) : "cc"); return end - s; } - +#else /* IN_ARCH_STRING_C */ +void *memchr(const void * s, int c, size_t n); +void *memscan(void *s, int c, size_t n); +char *strcat(char *dst, const char *src); +char *strcpy(char *dst, const char *src); +size_t strlen(const char *s); +size_t strnlen(const char * s, size_t n); #endif /* !IN_ARCH_STRING_C */ #endif /* __KERNEL__ */ -- GitLab From ced2c8bcbc5082bc112d7c7410b3f5380c77e306 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Thu, 26 Mar 2009 15:24:34 +0100 Subject: [PATCH 4661/4982] [S390] remove duplicate nul-termination of string strlcpy() does already NUL-terminate the destination string. Signed-off-by: Hendrik Brueckner Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/early.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index d61eb3334ed..4d221c81c84 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -352,7 +352,6 @@ static void __init setup_boot_command_line(void) /* copy arch command line */ strlcpy(boot_command_line, COMMAND_LINE, ARCH_COMMAND_LINE_SIZE); - boot_command_line[ARCH_COMMAND_LINE_SIZE - 1] = 0; /* append IPL PARM data to the boot command line */ if (MACHINE_IS_VM) { -- GitLab From e13ed9b2704487e98d9241282765869fbd9a2dda Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 26 Mar 2009 15:24:35 +0100 Subject: [PATCH 4662/4982] [S390] bitops: remove likely annotations likely/unlikely profiling revealed that none of the branches in bitops is taken likely or unlikely. So remove the annotations. In addition the generated code is shorter. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/bitops.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h index 334964a0fb1..b30606f6d52 100644 --- a/arch/s390/include/asm/bitops.h +++ b/arch/s390/include/asm/bitops.h @@ -525,16 +525,16 @@ static inline unsigned long __ffs_word_loop(const unsigned long *addr, static inline unsigned long __ffz_word(unsigned long nr, unsigned long word) { #ifdef __s390x__ - if (likely((word & 0xffffffff) == 0xffffffff)) { + if ((word & 0xffffffff) == 0xffffffff) { word >>= 32; nr += 32; } #endif - if (likely((word & 0xffff) == 0xffff)) { + if ((word & 0xffff) == 0xffff) { word >>= 16; nr += 16; } - if (likely((word & 0xff) == 0xff)) { + if ((word & 0xff) == 0xff) { word >>= 8; nr += 8; } @@ -549,16 +549,16 @@ static inline unsigned long __ffz_word(unsigned long nr, unsigned long word) static inline unsigned long __ffs_word(unsigned long nr, unsigned long word) { #ifdef __s390x__ - if (likely((word & 0xffffffff) == 0)) { + if ((word & 0xffffffff) == 0) { word >>= 32; nr += 32; } #endif - if (likely((word & 0xffff) == 0)) { + if ((word & 0xffff) == 0) { word >>= 16; nr += 16; } - if (likely((word & 0xff) == 0)) { + if ((word & 0xff) == 0) { word >>= 8; nr += 8; } -- GitLab From 504665a91498f43d220b7d0942281067283a35f7 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 26 Mar 2009 15:24:36 +0100 Subject: [PATCH 4663/4982] [S390] module function call optimization Avoid the detour over the PLT if the branch target of a function call in a module is in the range of the bras (16-bit) or brasl (32-bit) instruction. The PLT is still generated but it is unused. Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/module.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c index 59b4e796680..eed4a00cb67 100644 --- a/arch/s390/kernel/module.c +++ b/arch/s390/kernel/module.c @@ -310,15 +310,20 @@ apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab, info->plt_initialized = 1; } if (r_type == R_390_PLTOFF16 || - r_type == R_390_PLTOFF32 - || r_type == R_390_PLTOFF64 - ) + r_type == R_390_PLTOFF32 || + r_type == R_390_PLTOFF64) val = me->arch.plt_offset - me->arch.got_offset + info->plt_offset + rela->r_addend; - else - val = (Elf_Addr) me->module_core + - me->arch.plt_offset + info->plt_offset + - rela->r_addend - loc; + else { + if (!((r_type == R_390_PLT16DBL && + val - loc + 0xffffUL < 0x1ffffeUL) || + (r_type == R_390_PLT32DBL && + val - loc + 0xffffffffULL < 0x1fffffffeULL))) + val = (Elf_Addr) me->module_core + + me->arch.plt_offset + + info->plt_offset; + val += rela->r_addend - loc; + } if (r_type == R_390_PLT16DBL) *(unsigned short *) loc = val >> 1; else if (r_type == R_390_PLTOFF16) -- GitLab From 1edad85b16fdda43c8ab809e2779e8bf64ab8bb2 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 26 Mar 2009 15:24:37 +0100 Subject: [PATCH 4664/4982] [S390] use compiler builtin versions of strlen/strcpy/strcat Use builtin variants if gcc 4 or newer is used to compile the kernel. Generates better code than the asm variants. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/string.h | 8 ++++++++ arch/s390/lib/string.c | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/arch/s390/include/asm/string.h b/arch/s390/include/asm/string.h index adf079170aa..cd0241db5a4 100644 --- a/arch/s390/include/asm/string.h +++ b/arch/s390/include/asm/string.h @@ -100,6 +100,7 @@ static inline char *strcat(char *dst, const char *src) static inline char *strcpy(char *dst, const char *src) { +#if __GNUC__ < 4 register int r0 asm("0") = 0; char *ret = dst; @@ -109,10 +110,14 @@ static inline char *strcpy(char *dst, const char *src) : "+&a" (dst), "+&a" (src) : "d" (r0) : "cc", "memory"); return ret; +#else + return __builtin_strcpy(dst, src); +#endif } static inline size_t strlen(const char *s) { +#if __GNUC__ < 4 register unsigned long r0 asm("0") = 0; const char *tmp = s; @@ -121,6 +126,9 @@ static inline size_t strlen(const char *s) " jo 0b" : "+d" (r0), "+a" (tmp) : : "cc"); return r0 - (unsigned long) s; +#else + return __builtin_strlen(s); +#endif } static inline size_t strnlen(const char * s, size_t n) diff --git a/arch/s390/lib/string.c b/arch/s390/lib/string.c index ae5cf5d03d4..4143b7c1909 100644 --- a/arch/s390/lib/string.c +++ b/arch/s390/lib/string.c @@ -44,7 +44,11 @@ static inline char *__strnend(const char *s, size_t n) */ size_t strlen(const char *s) { +#if __GNUC__ < 4 return __strend(s) - s; +#else + return __builtin_strlen(s); +#endif } EXPORT_SYMBOL(strlen); @@ -70,6 +74,7 @@ EXPORT_SYMBOL(strnlen); */ char *strcpy(char *dest, const char *src) { +#if __GNUC__ < 4 register int r0 asm("0") = 0; char *ret = dest; @@ -78,6 +83,9 @@ char *strcpy(char *dest, const char *src) : "+&a" (dest), "+&a" (src) : "d" (r0) : "cc", "memory" ); return ret; +#else + return __builtin_strcpy(dest, src); +#endif } EXPORT_SYMBOL(strcpy); -- GitLab From ab640db01013192f6867785a7def7c9d9ec8903d Mon Sep 17 00:00:00 2001 From: Carsten Otte Date: Thu, 26 Mar 2009 15:24:38 +0100 Subject: [PATCH 4665/4982] [S390] tape message cleanup This is a cleanup of all the messages this driver prints. It uses the dev_message macros now. Signed-off-by: Carsten Otte Signed-off-by: Martin Schwidefsky --- drivers/s390/char/tape.h | 2 - drivers/s390/char/tape_34xx.c | 161 +++++++-------- drivers/s390/char/tape_3590.c | 364 ++++++++++++++++----------------- drivers/s390/char/tape_block.c | 18 +- drivers/s390/char/tape_char.c | 7 - drivers/s390/char/tape_core.c | 62 +----- drivers/s390/char/tape_proc.c | 3 - drivers/s390/char/tape_std.c | 21 +- 8 files changed, 267 insertions(+), 371 deletions(-) diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h index d0d565a05df..c07809c8016 100644 --- a/drivers/s390/char/tape.h +++ b/drivers/s390/char/tape.h @@ -324,8 +324,6 @@ static inline void tape_proc_cleanup (void) {;} #endif /* a function for dumping device sense info */ -extern void tape_dump_sense(struct tape_device *, struct tape_request *, - struct irb *); extern void tape_dump_sense_dbf(struct tape_device *, struct tape_request *, struct irb *); diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c index 22ca34361ed..807ded5eb04 100644 --- a/drivers/s390/char/tape_34xx.c +++ b/drivers/s390/char/tape_34xx.c @@ -8,6 +8,8 @@ * Martin Schwidefsky */ +#define KMSG_COMPONENT "tape" + #include #include #include @@ -18,8 +20,6 @@ #include "tape.h" #include "tape_std.h" -#define PRINTK_HEADER "TAPE_34XX: " - /* * Pointer to debug area. */ @@ -203,8 +203,7 @@ tape_34xx_unsolicited_irq(struct tape_device *device, struct irb *irb) tape_34xx_schedule_work(device, TO_MSEN); } else { DBF_EVENT(3, "unsol.irq! dev end: %08x\n", device->cdev_id); - PRINT_WARN("Unsolicited IRQ (Device End) caught.\n"); - tape_dump_sense(device, NULL, irb); + tape_dump_sense_dbf(device, NULL, irb); } return TAPE_IO_SUCCESS; } @@ -226,9 +225,7 @@ tape_34xx_erp_read_opposite(struct tape_device *device, tape_std_read_backward(device, request); return tape_34xx_erp_retry(request); } - if (request->op != TO_RBA) - PRINT_ERR("read_opposite called with state:%s\n", - tape_op_verbose[request->op]); + /* * We tried to read forward and backward, but hat no * success -> failed. @@ -241,13 +238,9 @@ tape_34xx_erp_bug(struct tape_device *device, struct tape_request *request, struct irb *irb, int no) { if (request->op != TO_ASSIGN) { - PRINT_WARN("An unexpected condition #%d was caught in " - "tape error recovery.\n", no); - PRINT_WARN("Please report this incident.\n"); - if (request) - PRINT_WARN("Operation of tape:%s\n", - tape_op_verbose[request->op]); - tape_dump_sense(device, request, irb); + dev_err(&device->cdev->dev, "An unexpected condition %d " + "occurred in tape error recovery\n", no); + tape_dump_sense_dbf(device, request, irb); } return tape_34xx_erp_failed(request, -EIO); } @@ -261,9 +254,8 @@ tape_34xx_erp_overrun(struct tape_device *device, struct tape_request *request, struct irb *irb) { if (irb->ecw[3] == 0x40) { - PRINT_WARN ("Data overrun error between control-unit " - "and drive. Use a faster channel connection, " - "if possible! \n"); + dev_warn (&device->cdev->dev, "A data overrun occurred between" + " the control unit and tape unit\n"); return tape_34xx_erp_failed(request, -EIO); } return tape_34xx_erp_bug(device, request, irb, -1); @@ -280,7 +272,8 @@ tape_34xx_erp_sequence(struct tape_device *device, /* * cu detected incorrect block-id sequence on tape. */ - PRINT_WARN("Illegal block-id sequence found!\n"); + dev_warn (&device->cdev->dev, "The block ID sequence on the " + "tape is incorrect\n"); return tape_34xx_erp_failed(request, -EIO); } /* @@ -393,8 +386,6 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, /* Writing at physical end of volume */ return tape_34xx_erp_failed(request, -ENOSPC); default: - PRINT_ERR("Invalid op in %s:%i\n", - __func__, __LINE__); return tape_34xx_erp_failed(request, 0); } } @@ -420,7 +411,8 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, irb, -4); /* data check is permanent, CU recovery has failed */ - PRINT_WARN("Permanent read error\n"); + dev_warn (&device->cdev->dev, "A read error occurred " + "that cannot be recovered\n"); return tape_34xx_erp_failed(request, -EIO); case 0x25: // a write data check occurred @@ -433,22 +425,26 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, irb, -5); // data check is permanent, cu-recovery has failed - PRINT_WARN("Permanent write error\n"); + dev_warn (&device->cdev->dev, "A write error on the " + "tape cannot be recovered\n"); return tape_34xx_erp_failed(request, -EIO); case 0x26: /* Data Check (read opposite) occurred. */ return tape_34xx_erp_read_opposite(device, request); case 0x28: /* ID-Mark at tape start couldn't be written */ - PRINT_WARN("ID-Mark could not be written.\n"); + dev_warn (&device->cdev->dev, "Writing the ID-mark " + "failed\n"); return tape_34xx_erp_failed(request, -EIO); case 0x31: /* Tape void. Tried to read beyond end of device. */ - PRINT_WARN("Read beyond end of recorded area.\n"); + dev_warn (&device->cdev->dev, "Reading the tape beyond" + " the end of the recorded area failed\n"); return tape_34xx_erp_failed(request, -ENOSPC); case 0x41: /* Record sequence error. */ - PRINT_WARN("Invalid block-id sequence found.\n"); + dev_warn (&device->cdev->dev, "The tape contains an " + "incorrect block ID sequence\n"); return tape_34xx_erp_failed(request, -EIO); default: /* all data checks for 3480 should result in one of @@ -470,16 +466,12 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, switch (sense[3]) { case 0x00: /* Unit check with erpa code 0. Report and ignore. */ - PRINT_WARN("Non-error sense was found. " - "Unit-check will be ignored.\n"); return TAPE_IO_SUCCESS; case 0x21: /* * Data streaming not operational. CU will switch to * interlock mode. Reissue the command. */ - PRINT_WARN("Data streaming not operational. " - "Switching to interlock-mode.\n"); return tape_34xx_erp_retry(request); case 0x22: /* @@ -487,11 +479,8 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, * error on the lower interface, internal path not usable, * or error during cartridge load. */ - PRINT_WARN("A path equipment check occurred. One of the " - "following conditions occurred:\n"); - PRINT_WARN("drive adapter error, buffer error on the lower " - "interface, internal path not usable, error " - "during cartridge load.\n"); + dev_warn (&device->cdev->dev, "A path equipment check occurred" + " for the tape device\n"); return tape_34xx_erp_failed(request, -EIO); case 0x24: /* @@ -514,7 +503,6 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, * but the hardware isn't capable to do idrc, or a perform * subsystem func is issued and the CU is not on-line. */ - PRINT_WARN ("Function incompatible. Try to switch off idrc\n"); return tape_34xx_erp_failed(request, -EIO); case 0x2a: /* @@ -552,23 +540,26 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, * reading the format id mark or that that format specified * is not supported by the drive. */ - PRINT_WARN("Drive not capable processing the tape format!\n"); + dev_warn (&device->cdev->dev, "The tape unit cannot process " + "the tape format\n"); return tape_34xx_erp_failed(request, -EMEDIUMTYPE); case 0x30: /* The medium is write protected. */ - PRINT_WARN("Medium is write protected!\n"); + dev_warn (&device->cdev->dev, "The tape medium is write-" + "protected\n"); return tape_34xx_erp_failed(request, -EACCES); case 0x32: // Tension loss. We cannot recover this, it's an I/O error. - PRINT_WARN("The drive lost tape tension.\n"); + dev_warn (&device->cdev->dev, "The tape does not have the " + "required tape tension\n"); return tape_34xx_erp_failed(request, -EIO); case 0x33: /* * Load Failure. The cartridge was not inserted correctly or * the tape is not threaded correctly. */ - PRINT_WARN("Cartridge load failure. Reload the cartridge " - "and try again.\n"); + dev_warn (&device->cdev->dev, "The tape unit failed to load" + " the cartridge\n"); tape_34xx_delete_sbid_from(device, 0); return tape_34xx_erp_failed(request, -EIO); case 0x34: @@ -576,8 +567,8 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, * Unload failure. The drive cannot maintain tape tension * and control tape movement during an unload operation. */ - PRINT_WARN("Failure during cartridge unload. " - "Please try manually.\n"); + dev_warn (&device->cdev->dev, "Automatic unloading of the tape" + " cartridge failed\n"); if (request->op == TO_RUN) return tape_34xx_erp_failed(request, -EIO); return tape_34xx_erp_bug(device, request, irb, sense[3]); @@ -589,8 +580,8 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, * - the cartridge loader does not respond correctly * - a failure occurs during an index, load, or unload cycle */ - PRINT_WARN("Equipment check! Please check the drive and " - "the cartridge loader.\n"); + dev_warn (&device->cdev->dev, "An equipment check has occurred" + " on the tape unit\n"); return tape_34xx_erp_failed(request, -EIO); case 0x36: if (device->cdev->id.driver_info == tape_3490) @@ -603,7 +594,8 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, * Tape length error. The tape is shorter than reported in * the beginning-of-tape data. */ - PRINT_WARN("Tape length error.\n"); + dev_warn (&device->cdev->dev, "The tape information states an" + " incorrect length\n"); return tape_34xx_erp_failed(request, -EIO); case 0x38: /* @@ -620,12 +612,12 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, return tape_34xx_erp_failed(request, -EIO); case 0x3a: /* Drive switched to not ready. */ - PRINT_WARN("Drive not ready. Turn the ready/not ready switch " - "to ready position and try again.\n"); + dev_warn (&device->cdev->dev, "The tape unit is not ready\n"); return tape_34xx_erp_failed(request, -EIO); case 0x3b: /* Manual rewind or unload. This causes an I/O error. */ - PRINT_WARN("Medium was rewound or unloaded manually.\n"); + dev_warn (&device->cdev->dev, "The tape medium has been " + "rewound or unloaded manually\n"); tape_34xx_delete_sbid_from(device, 0); return tape_34xx_erp_failed(request, -EIO); case 0x42: @@ -633,7 +625,8 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, * Degraded mode. A condition that can cause degraded * performance is detected. */ - PRINT_WARN("Subsystem is running in degraded mode.\n"); + dev_warn (&device->cdev->dev, "The tape subsystem is running " + "in degraded mode\n"); return tape_34xx_erp_retry(request); case 0x43: /* Drive not ready. */ @@ -652,7 +645,6 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, break; } } - PRINT_WARN("The drive is not ready.\n"); return tape_34xx_erp_failed(request, -ENOMEDIUM); case 0x44: /* Locate Block unsuccessful. */ @@ -663,7 +655,8 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, return tape_34xx_erp_failed(request, -EIO); case 0x45: /* The drive is assigned to a different channel path. */ - PRINT_WARN("The drive is assigned elsewhere.\n"); + dev_warn (&device->cdev->dev, "The tape unit is already " + "assigned\n"); return tape_34xx_erp_failed(request, -EIO); case 0x46: /* @@ -671,11 +664,12 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, * the power supply may be switched off or * the drive address may not be set correctly. */ - PRINT_WARN("The drive is not on-line."); + dev_warn (&device->cdev->dev, "The tape unit is not online\n"); return tape_34xx_erp_failed(request, -EIO); case 0x47: /* Volume fenced. CU reports volume integrity is lost. */ - PRINT_WARN("Volume fenced. The volume integrity is lost.\n"); + dev_warn (&device->cdev->dev, "The control unit has fenced " + "access to the tape volume\n"); tape_34xx_delete_sbid_from(device, 0); return tape_34xx_erp_failed(request, -EIO); case 0x48: @@ -683,20 +677,21 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, return tape_34xx_erp_retry(request); case 0x49: /* Bus out check. A parity check error on the bus was found. */ - PRINT_WARN("Bus out check. A data transfer over the bus " - "has been corrupted.\n"); + dev_warn (&device->cdev->dev, "A parity error occurred on the " + "tape bus\n"); return tape_34xx_erp_failed(request, -EIO); case 0x4a: /* Control unit erp failed. */ - PRINT_WARN("The control unit I/O error recovery failed.\n"); + dev_warn (&device->cdev->dev, "I/O error recovery failed on " + "the tape control unit\n"); return tape_34xx_erp_failed(request, -EIO); case 0x4b: /* * CU and drive incompatible. The drive requests micro-program * patches, which are not available on the CU. */ - PRINT_WARN("The drive needs microprogram patches from the " - "control unit, which are not available.\n"); + dev_warn (&device->cdev->dev, "The tape unit requires a " + "firmware update\n"); return tape_34xx_erp_failed(request, -EIO); case 0x4c: /* @@ -721,8 +716,8 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, * the block to be written is larger than allowed for * buffered mode. */ - PRINT_WARN("Maximum block size for buffered " - "mode exceeded.\n"); + dev_warn (&device->cdev->dev, "The maximum block size" + " for buffered mode is exceeded\n"); return tape_34xx_erp_failed(request, -ENOBUFS); } /* This erpa is reserved for 3480. */ @@ -759,22 +754,20 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, return tape_34xx_erp_retry(request); case 0x55: /* Channel interface recovery (permanent). */ - PRINT_WARN("A permanent channel interface error occurred.\n"); + dev_warn (&device->cdev->dev, "A channel interface error cannot be" + " recovered\n"); return tape_34xx_erp_failed(request, -EIO); case 0x56: /* Channel protocol error. */ - PRINT_WARN("A channel protocol error occurred.\n"); + dev_warn (&device->cdev->dev, "A channel protocol error " + "occurred\n"); return tape_34xx_erp_failed(request, -EIO); case 0x57: if (device->cdev->id.driver_info == tape_3480) { /* Attention intercept. */ - PRINT_WARN("An attention intercept occurred, " - "which will be recovered.\n"); return tape_34xx_erp_retry(request); } else { /* Global status intercept. */ - PRINT_WARN("An global status intercept was received, " - "which will be recovered.\n"); return tape_34xx_erp_retry(request); } case 0x5a: @@ -782,42 +775,31 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, * Tape length incompatible. The tape inserted is too long, * which could cause damage to the tape or the drive. */ - PRINT_WARN("Tape Length Incompatible\n"); - PRINT_WARN("Tape length exceeds IBM enhanced capacity " - "cartdridge length or a medium\n"); - PRINT_WARN("with EC-CST identification mark has been mounted " - "in a device that writes\n"); - PRINT_WARN("3480 or 3480 XF format.\n"); + dev_warn (&device->cdev->dev, "The tape unit does not support " + "the tape length\n"); return tape_34xx_erp_failed(request, -EIO); case 0x5b: /* Format 3480 XF incompatible */ if (sense[1] & SENSE_BEGINNING_OF_TAPE) /* The tape will get overwritten. */ return tape_34xx_erp_retry(request); - PRINT_WARN("Format 3480 XF Incompatible\n"); - PRINT_WARN("Medium has been created in 3480 format. " - "To change the format writes\n"); - PRINT_WARN("must be issued at BOT.\n"); + dev_warn (&device->cdev->dev, "The tape unit does not support" + " format 3480 XF\n"); return tape_34xx_erp_failed(request, -EIO); case 0x5c: /* Format 3480-2 XF incompatible */ - PRINT_WARN("Format 3480-2 XF Incompatible\n"); - PRINT_WARN("Device can only read 3480 or 3480 XF format.\n"); + dev_warn (&device->cdev->dev, "The tape unit does not support tape " + "format 3480-2 XF\n"); return tape_34xx_erp_failed(request, -EIO); case 0x5d: /* Tape length violation. */ - PRINT_WARN("Tape Length Violation\n"); - PRINT_WARN("The mounted tape exceeds IBM Enhanced Capacity " - "Cartdridge System Tape length.\n"); - PRINT_WARN("This may cause damage to the drive or tape when " - "processing to the EOV\n"); + dev_warn (&device->cdev->dev, "The tape unit does not support" + " the current tape length\n"); return tape_34xx_erp_failed(request, -EMEDIUMTYPE); case 0x5e: /* Compaction algorithm incompatible. */ - PRINT_WARN("Compaction Algorithm Incompatible\n"); - PRINT_WARN("The volume is recorded using an incompatible " - "compaction algorithm,\n"); - PRINT_WARN("which is not supported by the device.\n"); + dev_warn (&device->cdev->dev, "The tape unit does not support" + " the compaction algorithm\n"); return tape_34xx_erp_failed(request, -EMEDIUMTYPE); /* The following erpas should have been covered earlier. */ @@ -848,7 +830,6 @@ tape_34xx_irq(struct tape_device *device, struct tape_request *request, (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) && (request->op == TO_WRI)) { /* Write at end of volume */ - PRINT_INFO("End of volume\n"); /* XXX */ return tape_34xx_erp_failed(request, -ENOSPC); } @@ -869,9 +850,7 @@ tape_34xx_irq(struct tape_device *device, struct tape_request *request, } DBF_EVENT(6, "xunknownirq\n"); - PRINT_ERR("Unexpected interrupt.\n"); - PRINT_ERR("Current op is: %s", tape_op_verbose[request->op]); - tape_dump_sense(device, request, irb); + tape_dump_sense_dbf(device, request, irb); return TAPE_IO_STOP; } diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index 71605a179d6..5a5bb97a081 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c @@ -8,12 +8,15 @@ * Martin Schwidefsky */ +#define KMSG_COMPONENT "tape" + #include #include #include #include #define TAPE_DBF_AREA tape_3590_dbf +#define BUFSIZE 512 /* size of buffers for dynamic generated messages */ #include "tape.h" #include "tape_std.h" @@ -36,7 +39,7 @@ EXPORT_SYMBOL(TAPE_DBF_AREA); * - Read Alternate: implemented *******************************************************************/ -#define PRINTK_HEADER "TAPE_3590: " +#define KMSG_COMPONENT "tape" static const char *tape_3590_msg[TAPE_3590_MAX_MSG] = { [0x00] = "", @@ -726,7 +729,7 @@ static void tape_3590_med_state_set(struct tape_device *device, } c_info->medium_status |= TAPE390_MEDIUM_LOADED_MASK; if (sense->flags & MSENSE_CRYPT_MASK) { - PRINT_INFO("Medium is encrypted (%04x)\n", sense->flags); + DBF_EVENT(6, "Medium is encrypted (%04x)\n", sense->flags); c_info->medium_status |= TAPE390_MEDIUM_ENCRYPTED_MASK; } else { DBF_EVENT(6, "Medium is not encrypted %04x\n", sense->flags); @@ -847,8 +850,7 @@ tape_3590_unsolicited_irq(struct tape_device *device, struct irb *irb) tape_3590_schedule_work(device, TO_READ_ATTMSG); } else { DBF_EVENT(3, "unsol.irq! dev end: %08x\n", device->cdev_id); - PRINT_WARN("Unsolicited IRQ (Device End) caught.\n"); - tape_dump_sense(device, NULL, irb); + tape_dump_sense_dbf(device, NULL, irb); } /* check medium state */ tape_3590_schedule_work(device, TO_MSEN); @@ -876,8 +878,6 @@ tape_3590_erp_basic(struct tape_device *device, struct tape_request *request, case SENSE_BRA_DRE: return tape_3590_erp_failed(device, request, irb, rc); default: - PRINT_ERR("Unknown BRA %x - This should not happen!\n", - sense->bra); BUG(); return TAPE_IO_STOP; } @@ -910,7 +910,8 @@ tape_3590_erp_swap(struct tape_device *device, struct tape_request *request, * should proceed with the new tape... this * should probably be done in user space! */ - PRINT_WARN("(%s): Swap Tape Device!\n", dev_name(&device->cdev->dev)); + dev_warn (&device->cdev->dev, "The tape medium must be loaded into a " + "different tape unit\n"); return tape_3590_erp_basic(device, request, irb, -EIO); } @@ -985,8 +986,6 @@ tape_3590_erp_read_opposite(struct tape_device *device, return tape_3590_erp_failed(device, request, irb, -EIO); break; default: - PRINT_WARN("read_opposite_recovery_called_with_op: %s\n", - tape_op_verbose[request->op]); return tape_3590_erp_failed(device, request, irb, -EIO); } } @@ -998,50 +997,61 @@ static void tape_3590_print_mim_msg_f0(struct tape_device *device, struct irb *irb) { struct tape_3590_sense *sense; + char *exception, *service; + + exception = kmalloc(BUFSIZE, GFP_ATOMIC); + service = kmalloc(BUFSIZE, GFP_ATOMIC); + + if (!exception || !service) + goto out_nomem; sense = (struct tape_3590_sense *) irb->ecw; /* Exception Message */ switch (sense->fmt.f70.emc) { case 0x02: - PRINT_WARN("(%s): Data degraded\n", - dev_name(&device->cdev->dev)); + snprintf(exception, BUFSIZE, "Data degraded"); break; case 0x03: - PRINT_WARN("(%s): Data degraded in partion %i\n", - dev_name(&device->cdev->dev), sense->fmt.f70.mp); + snprintf(exception, BUFSIZE, "Data degraded in partion %i", + sense->fmt.f70.mp); break; case 0x04: - PRINT_WARN("(%s): Medium degraded\n", - dev_name(&device->cdev->dev)); + snprintf(exception, BUFSIZE, "Medium degraded"); break; case 0x05: - PRINT_WARN("(%s): Medium degraded in partition %i\n", - dev_name(&device->cdev->dev), sense->fmt.f70.mp); + snprintf(exception, BUFSIZE, "Medium degraded in partition %i", + sense->fmt.f70.mp); break; case 0x06: - PRINT_WARN("(%s): Block 0 Error\n", - dev_name(&device->cdev->dev)); + snprintf(exception, BUFSIZE, "Block 0 Error"); break; case 0x07: - PRINT_WARN("(%s): Medium Exception 0x%02x\n", - dev_name(&device->cdev->dev), sense->fmt.f70.md); + snprintf(exception, BUFSIZE, "Medium Exception 0x%02x", + sense->fmt.f70.md); break; default: - PRINT_WARN("(%s): MIM ExMsg: 0x%02x\n", - dev_name(&device->cdev->dev), sense->fmt.f70.emc); + snprintf(exception, BUFSIZE, "0x%02x", + sense->fmt.f70.emc); break; } /* Service Message */ switch (sense->fmt.f70.smc) { case 0x02: - PRINT_WARN("(%s): Reference Media maintenance procedure %i\n", - dev_name(&device->cdev->dev), sense->fmt.f70.md); + snprintf(service, BUFSIZE, "Reference Media maintenance " + "procedure %i", sense->fmt.f70.md); break; default: - PRINT_WARN("(%s): MIM ServiceMsg: 0x%02x\n", - dev_name(&device->cdev->dev), sense->fmt.f70.smc); + snprintf(service, BUFSIZE, "0x%02x", + sense->fmt.f70.smc); break; } + + dev_warn (&device->cdev->dev, "Tape media information: exception %s, " + "service %s\n", exception, service); + +out_nomem: + kfree(exception); + kfree(service); } /* @@ -1051,108 +1061,108 @@ static void tape_3590_print_io_sim_msg_f1(struct tape_device *device, struct irb *irb) { struct tape_3590_sense *sense; + char *exception, *service; + + exception = kmalloc(BUFSIZE, GFP_ATOMIC); + service = kmalloc(BUFSIZE, GFP_ATOMIC); + + if (!exception || !service) + goto out_nomem; sense = (struct tape_3590_sense *) irb->ecw; /* Exception Message */ switch (sense->fmt.f71.emc) { case 0x01: - PRINT_WARN("(%s): Effect of failure is unknown\n", - dev_name(&device->cdev->dev)); + snprintf(exception, BUFSIZE, "Effect of failure is unknown"); break; case 0x02: - PRINT_WARN("(%s): CU Exception - no performance impact\n", - dev_name(&device->cdev->dev)); + snprintf(exception, BUFSIZE, "CU Exception - no performance " + "impact"); break; case 0x03: - PRINT_WARN("(%s): CU Exception on channel interface 0x%02x\n", - dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); + snprintf(exception, BUFSIZE, "CU Exception on channel " + "interface 0x%02x", sense->fmt.f71.md[0]); break; case 0x04: - PRINT_WARN("(%s): CU Exception on device path 0x%02x\n", - dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); + snprintf(exception, BUFSIZE, "CU Exception on device path " + "0x%02x", sense->fmt.f71.md[0]); break; case 0x05: - PRINT_WARN("(%s): CU Exception on library path 0x%02x\n", - dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); + snprintf(exception, BUFSIZE, "CU Exception on library path " + "0x%02x", sense->fmt.f71.md[0]); break; case 0x06: - PRINT_WARN("(%s): CU Exception on node 0x%02x\n", - dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); + snprintf(exception, BUFSIZE, "CU Exception on node 0x%02x", + sense->fmt.f71.md[0]); break; case 0x07: - PRINT_WARN("(%s): CU Exception on partition 0x%02x\n", - dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); + snprintf(exception, BUFSIZE, "CU Exception on partition " + "0x%02x", sense->fmt.f71.md[0]); break; default: - PRINT_WARN("(%s): SIM ExMsg: 0x%02x\n", - dev_name(&device->cdev->dev), sense->fmt.f71.emc); + snprintf(exception, BUFSIZE, "0x%02x", + sense->fmt.f71.emc); } /* Service Message */ switch (sense->fmt.f71.smc) { case 0x01: - PRINT_WARN("(%s): Repair impact is unknown\n", - dev_name(&device->cdev->dev)); + snprintf(service, BUFSIZE, "Repair impact is unknown"); break; case 0x02: - PRINT_WARN("(%s): Repair will not impact cu performance\n", - dev_name(&device->cdev->dev)); + snprintf(service, BUFSIZE, "Repair will not impact cu " + "performance"); break; case 0x03: if (sense->fmt.f71.mdf == 0) - PRINT_WARN("(%s): Repair will disable node " - "0x%x on CU\n", - dev_name(&device->cdev->dev), - sense->fmt.f71.md[1]); + snprintf(service, BUFSIZE, "Repair will disable node " + "0x%x on CU", sense->fmt.f71.md[1]); else - PRINT_WARN("(%s): Repair will disable nodes " - "(0x%x-0x%x) on CU\n", - dev_name(&device->cdev->dev), - sense->fmt.f71.md[1], sense->fmt.f71.md[2]); + snprintf(service, BUFSIZE, "Repair will disable " + "nodes (0x%x-0x%x) on CU", sense->fmt.f71.md[1], + sense->fmt.f71.md[2]); break; case 0x04: if (sense->fmt.f71.mdf == 0) - PRINT_WARN("(%s): Repair will disable cannel path " - "0x%x on CU\n", - dev_name(&device->cdev->dev), - sense->fmt.f71.md[1]); + snprintf(service, BUFSIZE, "Repair will disable " + "channel path 0x%x on CU", + sense->fmt.f71.md[1]); else - PRINT_WARN("(%s): Repair will disable cannel paths " - "(0x%x-0x%x) on CU\n", - dev_name(&device->cdev->dev), - sense->fmt.f71.md[1], sense->fmt.f71.md[2]); + snprintf(service, BUFSIZE, "Repair will disable cannel" + " paths (0x%x-0x%x) on CU", + sense->fmt.f71.md[1], sense->fmt.f71.md[2]); break; case 0x05: if (sense->fmt.f71.mdf == 0) - PRINT_WARN("(%s): Repair will disable device path " - "0x%x on CU\n", - dev_name(&device->cdev->dev), - sense->fmt.f71.md[1]); + snprintf(service, BUFSIZE, "Repair will disable device" + " path 0x%x on CU", sense->fmt.f71.md[1]); else - PRINT_WARN("(%s): Repair will disable device paths " - "(0x%x-0x%x) on CU\n", - dev_name(&device->cdev->dev), - sense->fmt.f71.md[1], sense->fmt.f71.md[2]); + snprintf(service, BUFSIZE, "Repair will disable device" + " paths (0x%x-0x%x) on CU", + sense->fmt.f71.md[1], sense->fmt.f71.md[2]); break; case 0x06: if (sense->fmt.f71.mdf == 0) - PRINT_WARN("(%s): Repair will disable library path " - "0x%x on CU\n", - dev_name(&device->cdev->dev), - sense->fmt.f71.md[1]); + snprintf(service, BUFSIZE, "Repair will disable " + "library path 0x%x on CU", + sense->fmt.f71.md[1]); else - PRINT_WARN("(%s): Repair will disable library paths " - "(0x%x-0x%x) on CU\n", - dev_name(&device->cdev->dev), - sense->fmt.f71.md[1], sense->fmt.f71.md[2]); + snprintf(service, BUFSIZE, "Repair will disable " + "library paths (0x%x-0x%x) on CU", + sense->fmt.f71.md[1], sense->fmt.f71.md[2]); break; case 0x07: - PRINT_WARN("(%s): Repair will disable access to CU\n", - dev_name(&device->cdev->dev)); + snprintf(service, BUFSIZE, "Repair will disable access to CU"); break; default: - PRINT_WARN("(%s): SIM ServiceMsg: 0x%02x\n", - dev_name(&device->cdev->dev), sense->fmt.f71.smc); + snprintf(service, BUFSIZE, "0x%02x", + sense->fmt.f71.smc); } + + dev_warn (&device->cdev->dev, "I/O subsystem information: exception" + " %s, service %s\n", exception, service); +out_nomem: + kfree(exception); + kfree(service); } /* @@ -1162,111 +1172,109 @@ static void tape_3590_print_dev_sim_msg_f2(struct tape_device *device, struct irb *irb) { struct tape_3590_sense *sense; + char *exception, *service; + + exception = kmalloc(BUFSIZE, GFP_ATOMIC); + service = kmalloc(BUFSIZE, GFP_ATOMIC); + + if (!exception || !service) + goto out_nomem; sense = (struct tape_3590_sense *) irb->ecw; /* Exception Message */ switch (sense->fmt.f71.emc) { case 0x01: - PRINT_WARN("(%s): Effect of failure is unknown\n", - dev_name(&device->cdev->dev)); + snprintf(exception, BUFSIZE, "Effect of failure is unknown"); break; case 0x02: - PRINT_WARN("(%s): DV Exception - no performance impact\n", - dev_name(&device->cdev->dev)); + snprintf(exception, BUFSIZE, "DV Exception - no performance" + " impact"); break; case 0x03: - PRINT_WARN("(%s): DV Exception on channel interface 0x%02x\n", - dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); + snprintf(exception, BUFSIZE, "DV Exception on channel " + "interface 0x%02x", sense->fmt.f71.md[0]); break; case 0x04: - PRINT_WARN("(%s): DV Exception on loader 0x%02x\n", - dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); + snprintf(exception, BUFSIZE, "DV Exception on loader 0x%02x", + sense->fmt.f71.md[0]); break; case 0x05: - PRINT_WARN("(%s): DV Exception on message display 0x%02x\n", - dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); + snprintf(exception, BUFSIZE, "DV Exception on message display" + " 0x%02x", sense->fmt.f71.md[0]); break; case 0x06: - PRINT_WARN("(%s): DV Exception in tape path\n", - dev_name(&device->cdev->dev)); + snprintf(exception, BUFSIZE, "DV Exception in tape path"); break; case 0x07: - PRINT_WARN("(%s): DV Exception in drive\n", - dev_name(&device->cdev->dev)); + snprintf(exception, BUFSIZE, "DV Exception in drive"); break; default: - PRINT_WARN("(%s): DSIM ExMsg: 0x%02x\n", - dev_name(&device->cdev->dev), sense->fmt.f71.emc); + snprintf(exception, BUFSIZE, "0x%02x", + sense->fmt.f71.emc); } /* Service Message */ switch (sense->fmt.f71.smc) { case 0x01: - PRINT_WARN("(%s): Repair impact is unknown\n", - dev_name(&device->cdev->dev)); + snprintf(service, BUFSIZE, "Repair impact is unknown"); break; case 0x02: - PRINT_WARN("(%s): Repair will not impact device performance\n", - dev_name(&device->cdev->dev)); + snprintf(service, BUFSIZE, "Repair will not impact device " + "performance"); break; case 0x03: if (sense->fmt.f71.mdf == 0) - PRINT_WARN("(%s): Repair will disable channel path " - "0x%x on DV\n", - dev_name(&device->cdev->dev), - sense->fmt.f71.md[1]); + snprintf(service, BUFSIZE, "Repair will disable " + "channel path 0x%x on DV", + sense->fmt.f71.md[1]); else - PRINT_WARN("(%s): Repair will disable channel path " - "(0x%x-0x%x) on DV\n", - dev_name(&device->cdev->dev), - sense->fmt.f71.md[1], sense->fmt.f71.md[2]); + snprintf(service, BUFSIZE, "Repair will disable " + "channel path (0x%x-0x%x) on DV", + sense->fmt.f71.md[1], sense->fmt.f71.md[2]); break; case 0x04: if (sense->fmt.f71.mdf == 0) - PRINT_WARN("(%s): Repair will disable interface 0x%x " - "on DV\n", - dev_name(&device->cdev->dev), - sense->fmt.f71.md[1]); + snprintf(service, BUFSIZE, "Repair will disable " + "interface 0x%x on DV", sense->fmt.f71.md[1]); else - PRINT_WARN("(%s): Repair will disable interfaces " - "(0x%x-0x%x) on DV\n", - dev_name(&device->cdev->dev), - sense->fmt.f71.md[1], sense->fmt.f71.md[2]); + snprintf(service, BUFSIZE, "Repair will disable " + "interfaces (0x%x-0x%x) on DV", + sense->fmt.f71.md[1], sense->fmt.f71.md[2]); break; case 0x05: if (sense->fmt.f71.mdf == 0) - PRINT_WARN("(%s): Repair will disable loader 0x%x " - "on DV\n", - dev_name(&device->cdev->dev), - sense->fmt.f71.md[1]); + snprintf(service, BUFSIZE, "Repair will disable loader" + " 0x%x on DV", sense->fmt.f71.md[1]); else - PRINT_WARN("(%s): Repair will disable loader " - "(0x%x-0x%x) on DV\n", - dev_name(&device->cdev->dev), - sense->fmt.f71.md[1], sense->fmt.f71.md[2]); + snprintf(service, BUFSIZE, "Repair will disable loader" + " (0x%x-0x%x) on DV", + sense->fmt.f71.md[1], sense->fmt.f71.md[2]); break; case 0x07: - PRINT_WARN("(%s): Repair will disable access to DV\n", - dev_name(&device->cdev->dev)); + snprintf(service, BUFSIZE, "Repair will disable access to DV"); break; case 0x08: if (sense->fmt.f71.mdf == 0) - PRINT_WARN("(%s): Repair will disable message " - "display 0x%x on DV\n", - dev_name(&device->cdev->dev), - sense->fmt.f71.md[1]); + snprintf(service, BUFSIZE, "Repair will disable " + "message display 0x%x on DV", + sense->fmt.f71.md[1]); else - PRINT_WARN("(%s): Repair will disable message " - "displays (0x%x-0x%x) on DV\n", - dev_name(&device->cdev->dev), - sense->fmt.f71.md[1], sense->fmt.f71.md[2]); + snprintf(service, BUFSIZE, "Repair will disable " + "message displays (0x%x-0x%x) on DV", + sense->fmt.f71.md[1], sense->fmt.f71.md[2]); break; case 0x09: - PRINT_WARN("(%s): Clean DV\n", dev_name(&device->cdev->dev)); + snprintf(service, BUFSIZE, "Clean DV"); break; default: - PRINT_WARN("(%s): DSIM ServiceMsg: 0x%02x\n", - dev_name(&device->cdev->dev), sense->fmt.f71.smc); + snprintf(service, BUFSIZE, "0x%02x", + sense->fmt.f71.smc); } + + dev_warn (&device->cdev->dev, "Device subsystem information: exception" + " %s, service %s\n", exception, service); +out_nomem: + kfree(exception); + kfree(service); } /* @@ -1282,46 +1290,44 @@ tape_3590_print_era_msg(struct tape_device *device, struct irb *irb) return; if ((sense->mc > 0) && (sense->mc < TAPE_3590_MAX_MSG)) { if (tape_3590_msg[sense->mc] != NULL) - PRINT_WARN("(%s): %s\n", dev_name(&device->cdev->dev), - tape_3590_msg[sense->mc]); - else { - PRINT_WARN("(%s): Message Code 0x%x\n", - dev_name(&device->cdev->dev), sense->mc); - } + dev_warn (&device->cdev->dev, "The tape unit has " + "issued sense message %s\n", + tape_3590_msg[sense->mc]); + else + dev_warn (&device->cdev->dev, "The tape unit has " + "issued an unknown sense message code 0x%x\n", + sense->mc); return; } if (sense->mc == 0xf0) { /* Standard Media Information Message */ - PRINT_WARN("(%s): MIM SEV=%i, MC=%02x, ES=%x/%x, " - "RC=%02x-%04x-%02x\n", dev_name(&device->cdev->dev), - sense->fmt.f70.sev, sense->mc, - sense->fmt.f70.emc, sense->fmt.f70.smc, - sense->fmt.f70.refcode, sense->fmt.f70.mid, - sense->fmt.f70.fid); + dev_warn (&device->cdev->dev, "MIM SEV=%i, MC=%02x, ES=%x/%x, " + "RC=%02x-%04x-%02x\n", sense->fmt.f70.sev, sense->mc, + sense->fmt.f70.emc, sense->fmt.f70.smc, + sense->fmt.f70.refcode, sense->fmt.f70.mid, + sense->fmt.f70.fid); tape_3590_print_mim_msg_f0(device, irb); return; } if (sense->mc == 0xf1) { /* Standard I/O Subsystem Service Information Message */ - PRINT_WARN("(%s): IOSIM SEV=%i, DEVTYPE=3590/%02x, " - "MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n", - dev_name(&device->cdev->dev), sense->fmt.f71.sev, - device->cdev->id.dev_model, - sense->mc, sense->fmt.f71.emc, - sense->fmt.f71.smc, sense->fmt.f71.refcode1, - sense->fmt.f71.refcode2, sense->fmt.f71.refcode3); + dev_warn (&device->cdev->dev, "IOSIM SEV=%i, DEVTYPE=3590/%02x," + " MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n", + sense->fmt.f71.sev, device->cdev->id.dev_model, + sense->mc, sense->fmt.f71.emc, sense->fmt.f71.smc, + sense->fmt.f71.refcode1, sense->fmt.f71.refcode2, + sense->fmt.f71.refcode3); tape_3590_print_io_sim_msg_f1(device, irb); return; } if (sense->mc == 0xf2) { /* Standard Device Service Information Message */ - PRINT_WARN("(%s): DEVSIM SEV=%i, DEVTYPE=3590/%02x, " - "MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n", - dev_name(&device->cdev->dev), sense->fmt.f71.sev, - device->cdev->id.dev_model, - sense->mc, sense->fmt.f71.emc, - sense->fmt.f71.smc, sense->fmt.f71.refcode1, - sense->fmt.f71.refcode2, sense->fmt.f71.refcode3); + dev_warn (&device->cdev->dev, "DEVSIM SEV=%i, DEVTYPE=3590/%02x" + ", MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n", + sense->fmt.f71.sev, device->cdev->id.dev_model, + sense->mc, sense->fmt.f71.emc, sense->fmt.f71.smc, + sense->fmt.f71.refcode1, sense->fmt.f71.refcode2, + sense->fmt.f71.refcode3); tape_3590_print_dev_sim_msg_f2(device, irb); return; } @@ -1329,8 +1335,8 @@ tape_3590_print_era_msg(struct tape_device *device, struct irb *irb) /* Standard Library Service Information Message */ return; } - PRINT_WARN("(%s): Device Message(%x)\n", - dev_name(&device->cdev->dev), sense->mc); + dev_warn (&device->cdev->dev, "The tape unit has issued an unknown " + "sense message code %x\n", sense->mc); } static int tape_3590_crypt_error(struct tape_device *device, @@ -1355,9 +1361,8 @@ static int tape_3590_crypt_error(struct tape_device *device, /* No connection to EKM */ return tape_3590_erp_basic(device, request, irb, -ENOTCONN); - PRINT_ERR("(%s): Unable to get encryption key from EKM\n", bus_id); - PRINT_ERR("(%s): CU=%02X DRIVE=%06X EKM=%02X:%04X\n", bus_id, cu_rc, - drv_rc, ekm_rc1, ekm_rc2); + dev_err (&device->cdev->dev, "The tape unit failed to obtain the " + "encryption key from EKM\n"); return tape_3590_erp_basic(device, request, irb, -ENOKEY); } @@ -1443,8 +1448,6 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request, * print additional msg since default msg * "device intervention" is not very meaningfull */ - PRINT_WARN("(%s): Tape operation when medium not loaded\n", - dev_name(&device->cdev->dev)); tape_med_state_set(device, MS_UNLOADED); tape_3590_schedule_work(device, TO_CRYPT_OFF); return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM); @@ -1490,19 +1493,13 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request, return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM); case 0x6020: - PRINT_WARN("(%s): Cartridge of wrong type ?\n", - dev_name(&device->cdev->dev)); return tape_3590_erp_basic(device, request, irb, -EMEDIUMTYPE); case 0x8011: - PRINT_WARN("(%s): Another host has reserved the tape device\n", - dev_name(&device->cdev->dev)); return tape_3590_erp_basic(device, request, irb, -EPERM); case 0x8013: - PRINT_WARN("(%s): Another host has privileged access to the " - "tape device\n", dev_name(&device->cdev->dev)); - PRINT_WARN("(%s): To solve the problem unload the current " - "cartridge!\n", dev_name(&device->cdev->dev)); + dev_warn (&device->cdev->dev, "A different host has privileged" + " access to the tape unit\n"); return tape_3590_erp_basic(device, request, irb, -EPERM); default: return tape_3590_erp_basic(device, request, irb, -EIO); @@ -1552,9 +1549,7 @@ tape_3590_irq(struct tape_device *device, struct tape_request *request, } DBF_EVENT(6, "xunknownirq\n"); - PRINT_ERR("Unexpected interrupt.\n"); - PRINT_ERR("Current op is: %s", tape_op_verbose[request->op]); - tape_dump_sense(device, request, irb); + tape_dump_sense_dbf(device, request, irb); return TAPE_IO_STOP; } @@ -1609,7 +1604,6 @@ tape_3590_setup_device(struct tape_device *device) if (rc) goto fail_rdc_data; if (rdc_data->data[31] == 0x13) { - PRINT_INFO("Device has crypto support\n"); data->crypt_info.capability |= TAPE390_CRYPT_SUPPORTED_MASK; tape_3592_disable_crypt(device); } else { diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index ae18baf59f0..f32e89e7c4f 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c @@ -10,6 +10,8 @@ * Stefan Bader */ +#define KMSG_COMPONENT "tape" + #include #include #include @@ -23,8 +25,6 @@ #include "tape.h" -#define PRINTK_HEADER "TAPE_BLOCK: " - #define TAPEBLOCK_MAX_SEC 100 #define TAPEBLOCK_MIN_REQUEUE 3 @@ -279,8 +279,6 @@ tapeblock_cleanup_device(struct tape_device *device) tape_put_device(device); if (!device->blk_data.disk) { - PRINT_ERR("(%s): No gendisk to clean up!\n", - dev_name(&device->cdev->dev)); goto cleanup_queue; } @@ -314,7 +312,8 @@ tapeblock_revalidate_disk(struct gendisk *disk) if (!device->blk_data.medium_changed) return 0; - PRINT_INFO("Detecting media size...\n"); + dev_info(&device->cdev->dev, "Determining the size of the recorded " + "area...\n"); rc = tape_mtop(device, MTFSFM, 1); if (rc) return rc; @@ -341,7 +340,8 @@ tapeblock_revalidate_disk(struct gendisk *disk) device->bof = rc; nr_of_blks -= rc; - PRINT_INFO("Found %i blocks on media\n", nr_of_blks); + dev_info(&device->cdev->dev, "The size of the recorded area is %i " + "blocks\n", nr_of_blks); set_capacity(device->blk_data.disk, nr_of_blks*(TAPEBLOCK_HSEC_SIZE/512)); @@ -376,8 +376,8 @@ tapeblock_open(struct block_device *bdev, fmode_t mode) if (device->required_tapemarks) { DBF_EVENT(2, "TBLOCK: missing tapemarks\n"); - PRINT_ERR("TBLOCK: Refusing to open tape with missing" - " end of file marks.\n"); + dev_warn(&device->cdev->dev, "Opening the tape failed because" + " of missing end-of-file marks\n"); rc = -EPERM; goto put_device; } @@ -452,7 +452,6 @@ tapeblock_ioctl( rc = -EINVAL; break; default: - PRINT_WARN("invalid ioctl 0x%x\n", command); rc = -EINVAL; } @@ -474,7 +473,6 @@ tapeblock_init(void) if (tapeblock_major == 0) tapeblock_major = rc; - PRINT_INFO("tape gets major %d for block device\n", tapeblock_major); return 0; } diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c index be0ce2215c8..31566c55adf 100644 --- a/drivers/s390/char/tape_char.c +++ b/drivers/s390/char/tape_char.c @@ -24,8 +24,6 @@ #include "tape_std.h" #include "tape_class.h" -#define PRINTK_HEADER "TAPE_CHAR: " - #define TAPECHAR_MAJOR 0 /* get dynamic major */ /* @@ -102,8 +100,6 @@ tapechar_check_idalbuffer(struct tape_device *device, size_t block_size) if (block_size > MAX_BLOCKSIZE) { DBF_EVENT(3, "Invalid blocksize (%zd > %d)\n", block_size, MAX_BLOCKSIZE); - PRINT_ERR("Invalid blocksize (%zd> %d)\n", - block_size, MAX_BLOCKSIZE); return -EINVAL; } @@ -485,7 +481,6 @@ tapechar_init (void) return -1; tapechar_major = MAJOR(dev); - PRINT_INFO("tape gets major %d for character devices\n", MAJOR(dev)); return 0; } @@ -496,7 +491,5 @@ tapechar_init (void) void tapechar_exit(void) { - PRINT_INFO("tape releases major %d for character devices\n", - tapechar_major); unregister_chrdev_region(MKDEV(tapechar_major, 0), 256); } diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index f9bb51fa7f5..1b6a2441246 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c @@ -11,6 +11,7 @@ * Stefan Bader */ +#define KMSG_COMPONENT "tape" #include #include // for kernel parameters #include // for requesting modules @@ -25,7 +26,6 @@ #include "tape.h" #include "tape_std.h" -#define PRINTK_HEADER "TAPE_CORE: " #define LONG_BUSY_TIMEOUT 180 /* seconds */ static void __tape_do_irq (struct ccw_device *, unsigned long, struct irb *); @@ -214,13 +214,13 @@ tape_med_state_set(struct tape_device *device, enum tape_medium_state newstate) switch(newstate){ case MS_UNLOADED: device->tape_generic_status |= GMT_DR_OPEN(~0); - PRINT_INFO("(%s): Tape is unloaded\n", - dev_name(&device->cdev->dev)); + dev_info(&device->cdev->dev, "The tape cartridge has been " + "successfully unloaded\n"); break; case MS_LOADED: device->tape_generic_status &= ~GMT_DR_OPEN(~0); - PRINT_INFO("(%s): Tape has been mounted\n", - dev_name(&device->cdev->dev)); + dev_info(&device->cdev->dev, "A tape cartridge has been " + "mounted\n"); break; default: // print nothing @@ -333,7 +333,6 @@ tape_generic_online(struct tape_device *device, /* Let the discipline have a go at the device. */ device->discipline = discipline; if (!try_module_get(discipline->owner)) { - PRINT_ERR("Cannot get module. Module gone.\n"); return -EINVAL; } @@ -391,7 +390,6 @@ int tape_generic_offline(struct tape_device *device) { if (!device) { - PRINT_ERR("tape_generic_offline: no such device\n"); return -ENODEV; } @@ -413,9 +411,6 @@ tape_generic_offline(struct tape_device *device) DBF_EVENT(3, "(%08x): Set offline failed " "- drive in use.\n", device->cdev_id); - PRINT_WARN("(%s): Set offline failed " - "- drive in use.\n", - dev_name(&device->cdev->dev)); spin_unlock_irq(get_ccwdev_lock(device->cdev)); return -EBUSY; } @@ -435,14 +430,11 @@ tape_alloc_device(void) device = kzalloc(sizeof(struct tape_device), GFP_KERNEL); if (device == NULL) { DBF_EXCEPTION(2, "ti:no mem\n"); - PRINT_INFO ("can't allocate memory for " - "tape info structure\n"); return ERR_PTR(-ENOMEM); } device->modeset_byte = kmalloc(1, GFP_KERNEL | GFP_DMA); if (device->modeset_byte == NULL) { DBF_EXCEPTION(2, "ti:no mem\n"); - PRINT_INFO("can't allocate memory for modeset byte\n"); kfree(device); return ERR_PTR(-ENOMEM); } @@ -490,7 +482,6 @@ tape_put_device(struct tape_device *device) } else { if (remain < 0) { DBF_EVENT(4, "put device without reference\n"); - PRINT_ERR("put device without reference\n"); } else { DBF_EVENT(4, "tape_free_device(%p)\n", device); kfree(device->modeset_byte); @@ -538,8 +529,6 @@ tape_generic_probe(struct ccw_device *cdev) ret = sysfs_create_group(&cdev->dev.kobj, &tape_attr_group); if (ret) { tape_put_device(device); - PRINT_ERR("probe failed for tape device %s\n", - dev_name(&cdev->dev)); return ret; } cdev->dev.driver_data = device; @@ -547,7 +536,6 @@ tape_generic_probe(struct ccw_device *cdev) device->cdev = cdev; ccw_device_get_id(cdev, &dev_id); device->cdev_id = devid_to_int(&dev_id); - PRINT_INFO("tape device %s found\n", dev_name(&cdev->dev)); return ret; } @@ -584,7 +572,6 @@ tape_generic_remove(struct ccw_device *cdev) device = cdev->dev.driver_data; if (!device) { - PRINT_ERR("No device pointer in tape_generic_remove!\n"); return; } DBF_LH(3, "(%08x): tape_generic_remove(%p)\n", device->cdev_id, cdev); @@ -615,10 +602,8 @@ tape_generic_remove(struct ccw_device *cdev) */ DBF_EVENT(3, "(%08x): Drive in use vanished!\n", device->cdev_id); - PRINT_WARN("(%s): Drive in use vanished - " - "expect trouble!\n", - dev_name(&device->cdev->dev)); - PRINT_WARN("State was %i\n", device->tape_state); + dev_warn(&device->cdev->dev, "A tape unit was detached" + " while in use\n"); tape_state_set(device, TS_NOT_OPER); __tape_discard_requests(device); spin_unlock_irq(get_ccwdev_lock(device->cdev)); @@ -829,30 +814,6 @@ __tape_end_request( __tape_start_next_request(device); } -/* - * Write sense data to console/dbf - */ -void -tape_dump_sense(struct tape_device* device, struct tape_request *request, - struct irb *irb) -{ - unsigned int *sptr; - - PRINT_INFO("-------------------------------------------------\n"); - PRINT_INFO("DSTAT : %02x CSTAT: %02x CPA: %04x\n", - irb->scsw.cmd.dstat, irb->scsw.cmd.cstat, irb->scsw.cmd.cpa); - PRINT_INFO("DEVICE: %s\n", dev_name(&device->cdev->dev)); - if (request != NULL) - PRINT_INFO("OP : %s\n", tape_op_verbose[request->op]); - - sptr = (unsigned int *) irb->ecw; - PRINT_INFO("Sense data: %08X %08X %08X %08X \n", - sptr[0], sptr[1], sptr[2], sptr[3]); - PRINT_INFO("Sense data: %08X %08X %08X %08X \n", - sptr[4], sptr[5], sptr[6], sptr[7]); - PRINT_INFO("--------------------------------------------------\n"); -} - /* * Write sense data to dbf */ @@ -1051,8 +1012,6 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) device = (struct tape_device *) cdev->dev.driver_data; if (device == NULL) { - PRINT_ERR("could not get device structure for %s " - "in interrupt\n", dev_name(&cdev->dev)); return; } request = (struct tape_request *) intparm; @@ -1064,13 +1023,13 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) /* FIXME: What to do with the request? */ switch (PTR_ERR(irb)) { case -ETIMEDOUT: - PRINT_WARN("(%s): Request timed out\n", + DBF_LH(1, "(%s): Request timed out\n", dev_name(&cdev->dev)); case -EIO: __tape_end_request(device, request, -EIO); break; default: - PRINT_ERR("(%s): Unexpected i/o error %li\n", + DBF_LH(1, "(%s): Unexpected i/o error %li\n", dev_name(&cdev->dev), PTR_ERR(irb)); } @@ -1182,8 +1141,6 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) default: if (rc > 0) { DBF_EVENT(6, "xunknownrc\n"); - PRINT_ERR("Invalid return code from discipline " - "interrupt function.\n"); __tape_end_request(device, request, -EIO); } else { __tape_end_request(device, request, rc); @@ -1323,7 +1280,6 @@ EXPORT_SYMBOL(tape_state_set); EXPORT_SYMBOL(tape_med_state_set); EXPORT_SYMBOL(tape_alloc_request); EXPORT_SYMBOL(tape_free_request); -EXPORT_SYMBOL(tape_dump_sense); EXPORT_SYMBOL(tape_dump_sense_dbf); EXPORT_SYMBOL(tape_do_io); EXPORT_SYMBOL(tape_do_io_async); diff --git a/drivers/s390/char/tape_proc.c b/drivers/s390/char/tape_proc.c index 8a376af926a..202f4213293 100644 --- a/drivers/s390/char/tape_proc.c +++ b/drivers/s390/char/tape_proc.c @@ -20,8 +20,6 @@ #include "tape.h" -#define PRINTK_HEADER "TAPE_PROC: " - static const char *tape_med_st_verbose[MS_SIZE] = { [MS_UNKNOWN] = "UNKNOWN ", @@ -128,7 +126,6 @@ tape_proc_init(void) proc_create("tapedevices", S_IFREG | S_IRUGO | S_IWUSR, NULL, &tape_proc_ops); if (tape_proc_devices == NULL) { - PRINT_WARN("tape: Cannot register procfs entry tapedevices\n"); return; } } diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c index 5bd573d144d..44dd0f80c84 100644 --- a/drivers/s390/char/tape_std.c +++ b/drivers/s390/char/tape_std.c @@ -26,8 +26,6 @@ #include "tape.h" #include "tape_std.h" -#define PRINTK_HEADER "TAPE_STD: " - /* * tape_std_assign */ @@ -46,9 +44,8 @@ tape_std_assign_timeout(unsigned long data) device->cdev_id); rc = tape_cancel_io(device, request); if(rc) - PRINT_ERR("(%s): Assign timeout: Cancel failed with rc = %i\n", + DBF_EVENT(3, "(%s): Assign timeout: Cancel failed with rc = %i\n", dev_name(&device->cdev->dev), rc); - } int @@ -82,8 +79,6 @@ tape_std_assign(struct tape_device *device) del_timer(&timeout); if (rc != 0) { - PRINT_WARN("%s: assign failed - device might be busy\n", - dev_name(&device->cdev->dev)); DBF_EVENT(3, "%08x: assign failed - device might be busy\n", device->cdev_id); } else { @@ -105,8 +100,6 @@ tape_std_unassign (struct tape_device *device) if (device->tape_state == TS_NOT_OPER) { DBF_EVENT(3, "(%08x): Can't unassign device\n", device->cdev_id); - PRINT_WARN("(%s): Can't unassign device - device gone\n", - dev_name(&device->cdev->dev)); return -EIO; } @@ -120,8 +113,6 @@ tape_std_unassign (struct tape_device *device) if ((rc = tape_do_io(device, request)) != 0) { DBF_EVENT(3, "%08x: Unassign failed\n", device->cdev_id); - PRINT_WARN("%s: Unassign failed\n", - dev_name(&device->cdev->dev)); } else { DBF_EVENT(3, "%08x: Tape unassigned\n", device->cdev_id); } @@ -242,8 +233,6 @@ tape_std_mtsetblk(struct tape_device *device, int count) if (count > MAX_BLOCKSIZE) { DBF_EVENT(3, "Invalid block size (%d > %d) given.\n", count, MAX_BLOCKSIZE); - PRINT_ERR("Invalid block size (%d > %d) given.\n", - count, MAX_BLOCKSIZE); return -EINVAL; } @@ -633,14 +622,6 @@ tape_std_mtcompression(struct tape_device *device, int mt_count) if (mt_count < 0 || mt_count > 1) { DBF_EXCEPTION(6, "xcom parm\n"); - if (*device->modeset_byte & 0x08) - PRINT_INFO("(%s) Compression is currently on\n", - dev_name(&device->cdev->dev)); - else - PRINT_INFO("(%s) Compression is currently off\n", - dev_name(&device->cdev->dev)); - PRINT_INFO("Use 1 to switch compression on, 0 to " - "switch it off\n"); return -EINVAL; } request = tape_alloc_request(2, 0); -- GitLab From 1fbc9f46a024535d95c3d5f136901decd86b109e Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Thu, 26 Mar 2009 15:24:39 +0100 Subject: [PATCH 4666/4982] [S390] list usage cleanup in s390 Trivial cleanup, list_del(); list_add{,_tail}() is equivalent to list_move{,_tail}(). Semantic patch for coccinelle can be found at www.cccmz.de/~snakebyte/list_move_tail.spatch Signed-off-by: Eric Sesterhenn Signed-off-by: Martin Schwidefsky --- drivers/s390/crypto/zcrypt_api.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index cb22b97944b..65b6a96afe6 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -128,8 +128,7 @@ static void __zcrypt_increase_preference(struct zcrypt_device *zdev) if (l == zdev->list.prev) return; /* Move zdev behind l */ - list_del(&zdev->list); - list_add(&zdev->list, l); + list_move(&zdev->list, l); } /** @@ -157,8 +156,7 @@ static void __zcrypt_decrease_preference(struct zcrypt_device *zdev) if (l == zdev->list.next) return; /* Move zdev before l */ - list_del(&zdev->list); - list_add_tail(&zdev->list, l); + list_move_tail(&zdev->list, l); } static void zcrypt_device_release(struct kref *kref) -- GitLab From eaf1b6fbca8d9be87bef2eafaa3f40bffe26ce04 Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Thu, 26 Mar 2009 15:24:40 +0100 Subject: [PATCH 4667/4982] [S390] Expose a constant for the number of words representing the CRs We need to use this value in the checkpoint/restart code and would like to have a constant instead of a magic '3'. Cc: linux-s390@vger.kernel.org Signed-off-by: Dan Smith Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/ptrace.h | 4 +++- arch/s390/kernel/compat_ptrace.h | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index 8920025c3c0..f1b051630c5 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h @@ -172,6 +172,8 @@ #define NUM_CRS 16 #define NUM_ACRS 16 +#define NUM_CR_WORDS 3 + #define FPR_SIZE 8 #define FPC_SIZE 4 #define FPC_PAD_SIZE 4 /* gcc insists on aligning the fpregs */ @@ -334,7 +336,7 @@ struct pt_regs */ typedef struct { - unsigned long cr[3]; + unsigned long cr[NUM_CR_WORDS]; } per_cr_words; #define PER_EM_MASK 0xE8000000UL diff --git a/arch/s390/kernel/compat_ptrace.h b/arch/s390/kernel/compat_ptrace.h index a2be3a978d5..123dd660d7f 100644 --- a/arch/s390/kernel/compat_ptrace.h +++ b/arch/s390/kernel/compat_ptrace.h @@ -1,10 +1,11 @@ #ifndef _PTRACE32_H #define _PTRACE32_H +#include /* needed for NUM_CR_WORDS */ #include "compat_linux.h" /* needed for psw_compat_t */ typedef struct { - __u32 cr[3]; + __u32 cr[NUM_CR_WORDS]; } per_cr_words32; typedef struct { -- GitLab From 2938af534d47891ddbced552e5d29f7b90bec609 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Thu, 26 Mar 2009 15:24:41 +0100 Subject: [PATCH 4668/4982] [S390] Fix comments in lowcore structure This patch fixes two addresses in the comments for the lowcore structure. Looks like an copy-paste bug. Signed-off-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/lowcore.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index ee4b10ff938..f94386ece0d 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -315,8 +315,8 @@ struct _lowcore __u8 op_access_id; /* 0x0a2 */ __u8 ar_access_id; /* 0x0a3 */ __u8 pad2[0xA8-0xA4]; /* 0x0a4 */ - addr_t trans_exc_code; /* 0x0A0 */ - addr_t monitor_code; /* 0x09c */ + addr_t trans_exc_code; /* 0x0a8 */ + addr_t monitor_code; /* 0x0b0 */ __u16 subchannel_id; /* 0x0b8 */ __u16 subchannel_nr; /* 0x0ba */ __u32 io_int_parm; /* 0x0bc */ -- GitLab From 7b4684880dfc6c45bc56039ca5eada771d7643ab Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 26 Mar 2009 15:24:42 +0100 Subject: [PATCH 4669/4982] [S390] eliminate cpuinfo_S390 structure Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/lowcore.h | 15 +++---- arch/s390/include/asm/processor.h | 16 +------ arch/s390/include/asm/smp.h | 7 +--- arch/s390/kernel/processor.c | 69 +++++++++++++++---------------- arch/s390/kernel/setup.c | 10 ++--- arch/s390/kernel/smp.c | 8 ++-- drivers/s390/cio/css.c | 2 +- 7 files changed, 52 insertions(+), 75 deletions(-) diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index f94386ece0d..ad543c11826 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -80,7 +80,6 @@ #define __LC_USER_ASCE 0xC50 #define __LC_PANIC_STACK 0xC54 #define __LC_CPUID 0xC60 -#define __LC_CPUADDR 0xC68 #define __LC_IPLDEV 0xC7C #define __LC_CURRENT 0xC90 #define __LC_INT_CLOCK 0xC98 @@ -102,7 +101,6 @@ #define __LC_USER_ASCE 0xD60 #define __LC_PANIC_STACK 0xD68 #define __LC_CPUID 0xD80 -#define __LC_CPUADDR 0xD88 #define __LC_IPLDEV 0xDB8 #define __LC_CURRENT 0xDD8 #define __LC_INT_CLOCK 0xDE8 @@ -273,8 +271,10 @@ struct _lowcore __u32 user_exec_asce; /* 0xc58 */ __u8 pad10[0xc60-0xc5c]; /* 0xc5c */ /* entry.S sensitive area start */ - struct cpuinfo_S390 cpu_data; /* 0xc60 */ - __u32 ipl_device; /* 0xc7c */ + cpuid_t cpu_id; /* 0xc60 */ + __u32 cpu_nr; /* 0xc68 */ + __u32 ipl_device; /* 0xc6c */ + __u8 pad_0xc70[0xc80-0xc70]; /* 0xc70 */ /* entry.S sensitive area end */ /* SMP info area: defined by DJB */ @@ -366,9 +366,10 @@ struct _lowcore __u64 user_exec_asce; /* 0xd70 */ __u8 pad10[0xd80-0xd78]; /* 0xd78 */ /* entry.S sensitive area start */ - struct cpuinfo_S390 cpu_data; /* 0xd80 */ - __u32 ipl_device; /* 0xdb8 */ - __u32 pad11; /* 0xdbc */ + cpuid_t cpu_id; /* 0xd80 */ + __u32 cpu_nr; /* 0xd88 */ + __u32 ipl_device; /* 0xd8c */ + __u8 pad_0xd90[0xdc0-0xd90]; /* 0xd90 */ /* entry.S sensitive area end */ /* SMP info area: defined by DJB */ diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index db4523fe38a..61862b3ac79 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h @@ -42,22 +42,8 @@ static inline void get_cpu_id(cpuid_t *ptr) asm volatile("stidp 0(%1)" : "=m" (*ptr) : "a" (ptr)); } -struct cpuinfo_S390 -{ - cpuid_t cpu_id; - __u16 cpu_addr; - __u16 cpu_nr; - unsigned long loops_per_jiffy; - unsigned long *pgd_quick; -#ifdef __s390x__ - unsigned long *pmd_quick; -#endif /* __s390x__ */ - unsigned long *pte_quick; - unsigned long pgtable_cache_sz; -}; - extern void s390_adjust_jiffies(void); -extern void print_cpu_info(struct cpuinfo_S390 *); +extern void print_cpu_info(void); extern int get_cpu_capability(unsigned int *); /* diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h index 024b91e0623..2009158a450 100644 --- a/arch/s390/include/asm/smp.h +++ b/arch/s390/include/asm/smp.h @@ -50,12 +50,7 @@ extern void machine_power_off_smp(void); #define PROC_CHANGE_PENALTY 20 /* Schedule penalty */ -#define raw_smp_processor_id() (S390_lowcore.cpu_data.cpu_nr) - -static inline __u16 hard_smp_processor_id(void) -{ - return stap(); -} +#define raw_smp_processor_id() (S390_lowcore.cpu_nr) /* * returns 1 if cpu is in stopped/check stopped state or not operational diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c index 82c1872cfe8..423da1bd42a 100644 --- a/arch/s390/kernel/processor.c +++ b/arch/s390/kernel/processor.c @@ -18,10 +18,11 @@ #include #include -void __cpuinit print_cpu_info(struct cpuinfo_S390 *cpuinfo) +void __cpuinit print_cpu_info(void) { pr_info("Processor %d started, address %d, identification %06X\n", - cpuinfo->cpu_nr, cpuinfo->cpu_addr, cpuinfo->cpu_id.ident); + S390_lowcore.cpu_nr, S390_lowcore.cpu_addr, + S390_lowcore.cpu_id.ident); } /* @@ -34,44 +35,42 @@ static int show_cpuinfo(struct seq_file *m, void *v) "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", "edat" }; - struct cpuinfo_S390 *cpuinfo; - unsigned long n = (unsigned long) v - 1; - int i; + struct _lowcore *lc; + unsigned long n = (unsigned long) v - 1; + int i; - s390_adjust_jiffies(); - preempt_disable(); - if (!n) { - seq_printf(m, "vendor_id : IBM/S390\n" - "# processors : %i\n" - "bogomips per cpu: %lu.%02lu\n", - num_online_cpus(), loops_per_jiffy/(500000/HZ), - (loops_per_jiffy/(5000/HZ))%100); - seq_puts(m, "features\t: "); - for (i = 0; i < 8; i++) - if (hwcap_str[i] && (elf_hwcap & (1UL << i))) - seq_printf(m, "%s ", hwcap_str[i]); - seq_puts(m, "\n"); - } + s390_adjust_jiffies(); + preempt_disable(); + if (!n) { + seq_printf(m, "vendor_id : IBM/S390\n" + "# processors : %i\n" + "bogomips per cpu: %lu.%02lu\n", + num_online_cpus(), loops_per_jiffy/(500000/HZ), + (loops_per_jiffy/(5000/HZ))%100); + seq_puts(m, "features\t: "); + for (i = 0; i < 8; i++) + if (hwcap_str[i] && (elf_hwcap & (1UL << i))) + seq_printf(m, "%s ", hwcap_str[i]); + seq_puts(m, "\n"); + } - if (cpu_online(n)) { + if (cpu_online(n)) { #ifdef CONFIG_SMP - if (smp_processor_id() == n) - cpuinfo = &S390_lowcore.cpu_data; - else - cpuinfo = &lowcore_ptr[n]->cpu_data; + lc = (smp_processor_id() == n) ? + &S390_lowcore : lowcore_ptr[n]; #else - cpuinfo = &S390_lowcore.cpu_data; + lc = &S390_lowcore; #endif - seq_printf(m, "processor %li: " - "version = %02X, " - "identification = %06X, " - "machine = %04X\n", - n, cpuinfo->cpu_id.version, - cpuinfo->cpu_id.ident, - cpuinfo->cpu_id.machine); - } - preempt_enable(); - return 0; + seq_printf(m, "processor %li: " + "version = %02X, " + "identification = %06X, " + "machine = %04X\n", + n, lc->cpu_id.version, + lc->cpu_id.ident, + lc->cpu_id.machine); + } + preempt_enable(); + return 0; } static void *c_start(struct seq_file *m, loff_t *pos) diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index dd3c5173627..9c8853f21bb 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -121,13 +121,10 @@ static struct resource data_resource = { */ void __cpuinit cpu_init(void) { - int addr = hard_smp_processor_id(); - /* * Store processor id in lowcore (used e.g. in timer_interrupt) */ - get_cpu_id(&S390_lowcore.cpu_data.cpu_id); - S390_lowcore.cpu_data.cpu_addr = addr; + get_cpu_id(&S390_lowcore.cpu_id); /* * Force FPU initialization: @@ -686,7 +683,6 @@ setup_memory(void) static void __init setup_hwcaps(void) { static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 }; - struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data; unsigned long long facility_list_extended; unsigned int facility_list; int i; @@ -732,7 +728,7 @@ static void __init setup_hwcaps(void) if (MACHINE_HAS_HPAGE) elf_hwcap |= 1UL << 7; - switch (cpuinfo->cpu_id.machine) { + switch (S390_lowcore.cpu_id.machine) { case 0x9672: #if !defined(CONFIG_64BIT) default: /* Use "g5" as default for 31 bit kernels. */ @@ -825,7 +821,7 @@ setup_arch(char **cmdline_p) setup_lowcore(); cpu_init(); - __cpu_logical_map[0] = S390_lowcore.cpu_data.cpu_addr; + __cpu_logical_map[0] = stap(); s390_init_cpu_topology(); /* diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index a8858634dd0..b167f74d94c 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -372,7 +372,7 @@ static void __init smp_detect_cpus(void) c_cpus = 1; s_cpus = 0; - boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr; + boot_cpu_addr = __cpu_logical_map[0]; info = kmalloc(sizeof(*info), GFP_KERNEL); if (!info) panic("smp_detect_cpus failed to allocate memory\n"); @@ -446,7 +446,7 @@ int __cpuinit start_secondary(void *cpuvoid) /* Switch on interrupts */ local_irq_enable(); /* Print info about this processor */ - print_cpu_info(&S390_lowcore.cpu_data); + print_cpu_info(); /* cpu_idle will call schedule for us */ cpu_idle(); return 0; @@ -564,7 +564,7 @@ int __cpuinit __cpu_up(unsigned int cpu) : : "a" (&cpu_lowcore->access_regs_save_area) : "memory"); cpu_lowcore->percpu_offset = __per_cpu_offset[cpu]; cpu_lowcore->current_task = (unsigned long) idle; - cpu_lowcore->cpu_data.cpu_nr = cpu; + cpu_lowcore->cpu_nr = cpu; cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce; cpu_lowcore->ipl_device = S390_lowcore.ipl_device; eieio(); @@ -656,7 +656,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) /* request the 0x1201 emergency signal external interrupt */ if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0) panic("Couldn't request external interrupt 0x1201"); - print_cpu_info(&S390_lowcore.cpu_data); + print_cpu_info(); /* Reallocate current lowcore, but keep its contents. */ lc_order = sizeof(long) == 8 ? 1 : 0; diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 8446d15e448..dcd0e48918d 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -655,7 +655,7 @@ css_generate_pgid(struct channel_subsystem *css, u32 tod_high) css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid; } else { #ifdef CONFIG_SMP - css->global_pgid.pgid_high.cpu_addr = hard_smp_processor_id(); + css->global_pgid.pgid_high.cpu_addr = stap(); #else css->global_pgid.pgid_high.cpu_addr = 0; #endif -- GitLab From da292bbe1f620221b08c4b589424f370168d642b Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 26 Mar 2009 15:24:43 +0100 Subject: [PATCH 4670/4982] [S390] eliminate ipl_device from lowcore Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/lowcore.h | 8 ++------ arch/s390/kernel/head31.S | 1 - arch/s390/kernel/head64.S | 1 - arch/s390/kernel/setup.c | 1 - arch/s390/kernel/smp.c | 1 - 5 files changed, 2 insertions(+), 10 deletions(-) diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index ad543c11826..5b18035c1dc 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -80,7 +80,6 @@ #define __LC_USER_ASCE 0xC50 #define __LC_PANIC_STACK 0xC54 #define __LC_CPUID 0xC60 -#define __LC_IPLDEV 0xC7C #define __LC_CURRENT 0xC90 #define __LC_INT_CLOCK 0xC98 #else /* __s390x__ */ @@ -101,7 +100,6 @@ #define __LC_USER_ASCE 0xD60 #define __LC_PANIC_STACK 0xD68 #define __LC_CPUID 0xD80 -#define __LC_IPLDEV 0xDB8 #define __LC_CURRENT 0xDD8 #define __LC_INT_CLOCK 0xDE8 #define __LC_VDSO_PER_CPU 0xE38 @@ -273,8 +271,7 @@ struct _lowcore /* entry.S sensitive area start */ cpuid_t cpu_id; /* 0xc60 */ __u32 cpu_nr; /* 0xc68 */ - __u32 ipl_device; /* 0xc6c */ - __u8 pad_0xc70[0xc80-0xc70]; /* 0xc70 */ + __u8 pad_0xc6c[0xc80-0xc6c]; /* 0xc6c */ /* entry.S sensitive area end */ /* SMP info area: defined by DJB */ @@ -368,8 +365,7 @@ struct _lowcore /* entry.S sensitive area start */ cpuid_t cpu_id; /* 0xd80 */ __u32 cpu_nr; /* 0xd88 */ - __u32 ipl_device; /* 0xd8c */ - __u8 pad_0xd90[0xdc0-0xd90]; /* 0xd90 */ + __u8 pad_0xd8c[0xdc0-0xd8c]; /* 0xd8c */ /* entry.S sensitive area end */ /* SMP info area: defined by DJB */ diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S index db476d114ca..2ced846065b 100644 --- a/arch/s390/kernel/head31.S +++ b/arch/s390/kernel/head31.S @@ -20,7 +20,6 @@ startup_continue: lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers l %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area # move IPL device to lowcore - mvc __LC_IPLDEV(4),IPL_DEVICE-PARMAREA(%r12) # # Setup stack # diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index f9f70aa1524..65667b2e65c 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -86,7 +86,6 @@ startup_continue: lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers lg %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area # move IPL device to lowcore - mvc __LC_IPLDEV(4),IPL_DEVICE+4-PARMAREA(%r12) lghi %r0,__LC_PASTE stg %r0,__LC_VDSO_PER_CPU # diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 9c8853f21bb..91551ef1d67 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -419,7 +419,6 @@ setup_lowcore(void) PSW_ADDR_AMODE | (unsigned long) mcck_int_handler; lc->io_new_psw.mask = psw_kernel_bits; lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler; - lc->ipl_device = S390_lowcore.ipl_device; lc->clock_comparator = -1ULL; lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE; lc->async_stack = (unsigned long) diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index b167f74d94c..775885772ff 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -566,7 +566,6 @@ int __cpuinit __cpu_up(unsigned int cpu) cpu_lowcore->current_task = (unsigned long) idle; cpu_lowcore->cpu_nr = cpu; cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce; - cpu_lowcore->ipl_device = S390_lowcore.ipl_device; eieio(); while (signal_processor(cpu, sigp_restart) == sigp_busy) -- GitLab From 866ba28418d30122d863c50182a202741f4dcf3e Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 26 Mar 2009 15:24:44 +0100 Subject: [PATCH 4671/4982] [S390] cleanup lowcore.h The lowcore.h header has quite a lot of whitespace damage and a rather wild collection of entries. Remove all that whitespace and tidy up the order of the lowcore fields. Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/lowcore.h | 652 ++++++++++++++++---------------- arch/s390/kernel/head.S | 2 + 2 files changed, 331 insertions(+), 323 deletions(-) diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index 5b18035c1dc..b349f1c7fdf 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -11,125 +11,118 @@ #ifndef _ASM_S390_LOWCORE_H #define _ASM_S390_LOWCORE_H -#ifndef __s390x__ -#define __LC_EXT_OLD_PSW 0x018 -#define __LC_SVC_OLD_PSW 0x020 -#define __LC_PGM_OLD_PSW 0x028 -#define __LC_MCK_OLD_PSW 0x030 -#define __LC_IO_OLD_PSW 0x038 -#define __LC_EXT_NEW_PSW 0x058 -#define __LC_SVC_NEW_PSW 0x060 -#define __LC_PGM_NEW_PSW 0x068 -#define __LC_MCK_NEW_PSW 0x070 -#define __LC_IO_NEW_PSW 0x078 -#else /* !__s390x__ */ -#define __LC_EXT_OLD_PSW 0x0130 -#define __LC_SVC_OLD_PSW 0x0140 -#define __LC_PGM_OLD_PSW 0x0150 -#define __LC_MCK_OLD_PSW 0x0160 -#define __LC_IO_OLD_PSW 0x0170 -#define __LC_EXT_NEW_PSW 0x01b0 -#define __LC_SVC_NEW_PSW 0x01c0 -#define __LC_PGM_NEW_PSW 0x01d0 -#define __LC_MCK_NEW_PSW 0x01e0 -#define __LC_IO_NEW_PSW 0x01f0 -#endif /* !__s390x__ */ - -#define __LC_IPL_PARMBLOCK_PTR 0x014 -#define __LC_EXT_PARAMS 0x080 -#define __LC_CPU_ADDRESS 0x084 -#define __LC_EXT_INT_CODE 0x086 - -#define __LC_SVC_ILC 0x088 -#define __LC_SVC_INT_CODE 0x08A -#define __LC_PGM_ILC 0x08C -#define __LC_PGM_INT_CODE 0x08E +#define __LC_IPL_PARMBLOCK_PTR 0x0014 +#define __LC_EXT_PARAMS 0x0080 +#define __LC_CPU_ADDRESS 0x0084 +#define __LC_EXT_INT_CODE 0x0086 -#define __LC_PER_ATMID 0x096 -#define __LC_PER_ADDRESS 0x098 -#define __LC_PER_ACCESS_ID 0x0A1 -#define __LC_AR_MODE_ID 0x0A3 +#define __LC_SVC_ILC 0x0088 +#define __LC_SVC_INT_CODE 0x008a +#define __LC_PGM_ILC 0x008c +#define __LC_PGM_INT_CODE 0x008e -#define __LC_SUBCHANNEL_ID 0x0B8 -#define __LC_SUBCHANNEL_NR 0x0BA -#define __LC_IO_INT_PARM 0x0BC -#define __LC_IO_INT_WORD 0x0C0 -#define __LC_MCCK_CODE 0x0E8 +#define __LC_PER_ATMID 0x0096 +#define __LC_PER_ADDRESS 0x0098 +#define __LC_PER_ACCESS_ID 0x00a1 +#define __LC_AR_MODE_ID 0x00a3 -#define __LC_LAST_BREAK 0x110 +#define __LC_SUBCHANNEL_ID 0x00b8 +#define __LC_SUBCHANNEL_NR 0x00ba +#define __LC_IO_INT_PARM 0x00bc +#define __LC_IO_INT_WORD 0x00c0 +#define __LC_MCCK_CODE 0x00e8 -#define __LC_RETURN_PSW 0x200 - -#define __LC_SAVE_AREA 0xC00 +#define __LC_DUMP_REIPL 0x0e00 #ifndef __s390x__ -#define __LC_IRB 0x208 -#define __LC_SYNC_ENTER_TIMER 0x248 -#define __LC_ASYNC_ENTER_TIMER 0x250 -#define __LC_EXIT_TIMER 0x258 -#define __LC_USER_TIMER 0x260 -#define __LC_SYSTEM_TIMER 0x268 -#define __LC_STEAL_TIMER 0x270 -#define __LC_LAST_UPDATE_TIMER 0x278 -#define __LC_LAST_UPDATE_CLOCK 0x280 -#define __LC_RETURN_MCCK_PSW 0x288 -#define __LC_KERNEL_STACK 0xC40 -#define __LC_THREAD_INFO 0xC44 -#define __LC_ASYNC_STACK 0xC48 -#define __LC_KERNEL_ASCE 0xC4C -#define __LC_USER_ASCE 0xC50 -#define __LC_PANIC_STACK 0xC54 -#define __LC_CPUID 0xC60 -#define __LC_CURRENT 0xC90 -#define __LC_INT_CLOCK 0xC98 +#define __LC_EXT_OLD_PSW 0x0018 +#define __LC_SVC_OLD_PSW 0x0020 +#define __LC_PGM_OLD_PSW 0x0028 +#define __LC_MCK_OLD_PSW 0x0030 +#define __LC_IO_OLD_PSW 0x0038 +#define __LC_EXT_NEW_PSW 0x0058 +#define __LC_SVC_NEW_PSW 0x0060 +#define __LC_PGM_NEW_PSW 0x0068 +#define __LC_MCK_NEW_PSW 0x0070 +#define __LC_IO_NEW_PSW 0x0078 +#define __LC_SAVE_AREA 0x0200 +#define __LC_RETURN_PSW 0x0240 +#define __LC_RETURN_MCCK_PSW 0x0248 +#define __LC_SYNC_ENTER_TIMER 0x0250 +#define __LC_ASYNC_ENTER_TIMER 0x0258 +#define __LC_EXIT_TIMER 0x0260 +#define __LC_USER_TIMER 0x0268 +#define __LC_SYSTEM_TIMER 0x0270 +#define __LC_STEAL_TIMER 0x0278 +#define __LC_LAST_UPDATE_TIMER 0x0280 +#define __LC_LAST_UPDATE_CLOCK 0x0288 +#define __LC_CURRENT 0x0290 +#define __LC_THREAD_INFO 0x0294 +#define __LC_KERNEL_STACK 0x0298 +#define __LC_ASYNC_STACK 0x029c +#define __LC_PANIC_STACK 0x02a0 +#define __LC_KERNEL_ASCE 0x02a4 +#define __LC_USER_ASCE 0x02a8 +#define __LC_USER_EXEC_ASCE 0x02ac +#define __LC_CPUID 0x02b0 +#define __LC_INT_CLOCK 0x02c8 +#define __LC_IRB 0x0300 +#define __LC_PFAULT_INTPARM 0x0080 +#define __LC_CPU_TIMER_SAVE_AREA 0x00d8 +#define __LC_CLOCK_COMP_SAVE_AREA 0x00e0 +#define __LC_PSW_SAVE_AREA 0x0100 +#define __LC_PREFIX_SAVE_AREA 0x0108 +#define __LC_AREGS_SAVE_AREA 0x0120 +#define __LC_FPREGS_SAVE_AREA 0x0160 +#define __LC_GPREGS_SAVE_AREA 0x0180 +#define __LC_CREGS_SAVE_AREA 0x01c0 #else /* __s390x__ */ -#define __LC_IRB 0x210 -#define __LC_SYNC_ENTER_TIMER 0x250 -#define __LC_ASYNC_ENTER_TIMER 0x258 -#define __LC_EXIT_TIMER 0x260 -#define __LC_USER_TIMER 0x268 -#define __LC_SYSTEM_TIMER 0x270 -#define __LC_STEAL_TIMER 0x278 -#define __LC_LAST_UPDATE_TIMER 0x280 -#define __LC_LAST_UPDATE_CLOCK 0x288 -#define __LC_RETURN_MCCK_PSW 0x290 -#define __LC_KERNEL_STACK 0xD40 -#define __LC_THREAD_INFO 0xD48 -#define __LC_ASYNC_STACK 0xD50 -#define __LC_KERNEL_ASCE 0xD58 -#define __LC_USER_ASCE 0xD60 -#define __LC_PANIC_STACK 0xD68 -#define __LC_CPUID 0xD80 -#define __LC_CURRENT 0xDD8 -#define __LC_INT_CLOCK 0xDE8 -#define __LC_VDSO_PER_CPU 0xE38 -#endif /* __s390x__ */ - -#define __LC_PASTE 0xE40 - -#define __LC_DUMP_REIPL 0xE00 -#ifndef __s390x__ -#define __LC_PFAULT_INTPARM 0x080 -#define __LC_CPU_TIMER_SAVE_AREA 0x0D8 -#define __LC_CLOCK_COMP_SAVE_AREA 0x0E0 -#define __LC_PSW_SAVE_AREA 0x100 -#define __LC_PREFIX_SAVE_AREA 0x108 -#define __LC_AREGS_SAVE_AREA 0x120 -#define __LC_FPREGS_SAVE_AREA 0x160 -#define __LC_GPREGS_SAVE_AREA 0x180 -#define __LC_CREGS_SAVE_AREA 0x1C0 -#else /* __s390x__ */ -#define __LC_PFAULT_INTPARM 0x11B8 +#define __LC_LAST_BREAK 0x0110 +#define __LC_EXT_OLD_PSW 0x0130 +#define __LC_SVC_OLD_PSW 0x0140 +#define __LC_PGM_OLD_PSW 0x0150 +#define __LC_MCK_OLD_PSW 0x0160 +#define __LC_IO_OLD_PSW 0x0170 +#define __LC_EXT_NEW_PSW 0x01b0 +#define __LC_SVC_NEW_PSW 0x01c0 +#define __LC_PGM_NEW_PSW 0x01d0 +#define __LC_MCK_NEW_PSW 0x01e0 +#define __LC_IO_NEW_PSW 0x01f0 +#define __LC_SAVE_AREA 0x0200 +#define __LC_RETURN_PSW 0x0280 +#define __LC_RETURN_MCCK_PSW 0x0290 +#define __LC_SYNC_ENTER_TIMER 0x02a0 +#define __LC_ASYNC_ENTER_TIMER 0x02a8 +#define __LC_EXIT_TIMER 0x02b0 +#define __LC_USER_TIMER 0x02b8 +#define __LC_SYSTEM_TIMER 0x02c0 +#define __LC_STEAL_TIMER 0x02c8 +#define __LC_LAST_UPDATE_TIMER 0x02d0 +#define __LC_LAST_UPDATE_CLOCK 0x02d8 +#define __LC_CURRENT 0x02e0 +#define __LC_THREAD_INFO 0x02e8 +#define __LC_KERNEL_STACK 0x02f0 +#define __LC_ASYNC_STACK 0x02f8 +#define __LC_PANIC_STACK 0x0300 +#define __LC_KERNEL_ASCE 0x0308 +#define __LC_USER_ASCE 0x0310 +#define __LC_USER_EXEC_ASCE 0x0318 +#define __LC_CPUID 0x0320 +#define __LC_INT_CLOCK 0x0340 +#define __LC_VDSO_PER_CPU 0x0350 +#define __LC_IRB 0x0380 +#define __LC_PASTE 0x03c0 +#define __LC_PFAULT_INTPARM 0x11b8 #define __LC_FPREGS_SAVE_AREA 0x1200 -#define __LC_GPREGS_SAVE_AREA 0x1280 +#define __LC_GPREGS_SAVE_AREA 0x1280 #define __LC_PSW_SAVE_AREA 0x1300 #define __LC_PREFIX_SAVE_AREA 0x1318 -#define __LC_FP_CREG_SAVE_AREA 0x131C +#define __LC_FP_CREG_SAVE_AREA 0x131c #define __LC_TODREG_SAVE_AREA 0x1324 -#define __LC_CPU_TIMER_SAVE_AREA 0x1328 +#define __LC_CPU_TIMER_SAVE_AREA 0x1328 #define __LC_CLOCK_COMP_SAVE_AREA 0x1331 -#define __LC_AREGS_SAVE_AREA 0x1340 -#define __LC_CREGS_SAVE_AREA 0x1380 +#define __LC_AREGS_SAVE_AREA 0x1340 +#define __LC_CREGS_SAVE_AREA 0x1380 #endif /* __s390x__ */ #ifndef __ASSEMBLY__ @@ -194,227 +187,240 @@ union save_area { struct _lowcore { #ifndef __s390x__ - /* prefix area: defined by architecture */ - psw_t restart_psw; /* 0x000 */ - __u32 ccw2[4]; /* 0x008 */ - psw_t external_old_psw; /* 0x018 */ - psw_t svc_old_psw; /* 0x020 */ - psw_t program_old_psw; /* 0x028 */ - psw_t mcck_old_psw; /* 0x030 */ - psw_t io_old_psw; /* 0x038 */ - __u8 pad1[0x58-0x40]; /* 0x040 */ - psw_t external_new_psw; /* 0x058 */ - psw_t svc_new_psw; /* 0x060 */ - psw_t program_new_psw; /* 0x068 */ - psw_t mcck_new_psw; /* 0x070 */ - psw_t io_new_psw; /* 0x078 */ - __u32 ext_params; /* 0x080 */ - __u16 cpu_addr; /* 0x084 */ - __u16 ext_int_code; /* 0x086 */ - __u16 svc_ilc; /* 0x088 */ - __u16 svc_code; /* 0x08a */ - __u16 pgm_ilc; /* 0x08c */ - __u16 pgm_code; /* 0x08e */ - __u32 trans_exc_code; /* 0x090 */ - __u16 mon_class_num; /* 0x094 */ - __u16 per_perc_atmid; /* 0x096 */ - __u32 per_address; /* 0x098 */ - __u32 monitor_code; /* 0x09c */ - __u8 exc_access_id; /* 0x0a0 */ - __u8 per_access_id; /* 0x0a1 */ - __u8 pad2[0xB8-0xA2]; /* 0x0a2 */ - __u16 subchannel_id; /* 0x0b8 */ - __u16 subchannel_nr; /* 0x0ba */ - __u32 io_int_parm; /* 0x0bc */ - __u32 io_int_word; /* 0x0c0 */ - __u8 pad3[0xc8-0xc4]; /* 0x0c4 */ - __u32 stfl_fac_list; /* 0x0c8 */ - __u8 pad4[0xd4-0xcc]; /* 0x0cc */ - __u32 extended_save_area_addr; /* 0x0d4 */ - __u32 cpu_timer_save_area[2]; /* 0x0d8 */ - __u32 clock_comp_save_area[2]; /* 0x0e0 */ - __u32 mcck_interruption_code[2]; /* 0x0e8 */ - __u8 pad5[0xf4-0xf0]; /* 0x0f0 */ - __u32 external_damage_code; /* 0x0f4 */ - __u32 failing_storage_address; /* 0x0f8 */ - __u8 pad6[0x100-0xfc]; /* 0x0fc */ - __u32 st_status_fixed_logout[4];/* 0x100 */ - __u8 pad7[0x120-0x110]; /* 0x110 */ - __u32 access_regs_save_area[16];/* 0x120 */ - __u32 floating_pt_save_area[8]; /* 0x160 */ - __u32 gpregs_save_area[16]; /* 0x180 */ - __u32 cregs_save_area[16]; /* 0x1c0 */ - - psw_t return_psw; /* 0x200 */ - __u8 irb[64]; /* 0x208 */ - __u64 sync_enter_timer; /* 0x248 */ - __u64 async_enter_timer; /* 0x250 */ - __u64 exit_timer; /* 0x258 */ - __u64 user_timer; /* 0x260 */ - __u64 system_timer; /* 0x268 */ - __u64 steal_timer; /* 0x270 */ - __u64 last_update_timer; /* 0x278 */ - __u64 last_update_clock; /* 0x280 */ - psw_t return_mcck_psw; /* 0x288 */ - __u8 pad8[0xc00-0x290]; /* 0x290 */ - - /* System info area */ - __u32 save_area[16]; /* 0xc00 */ - __u32 kernel_stack; /* 0xc40 */ - __u32 thread_info; /* 0xc44 */ - __u32 async_stack; /* 0xc48 */ - __u32 kernel_asce; /* 0xc4c */ - __u32 user_asce; /* 0xc50 */ - __u32 panic_stack; /* 0xc54 */ - __u32 user_exec_asce; /* 0xc58 */ - __u8 pad10[0xc60-0xc5c]; /* 0xc5c */ - /* entry.S sensitive area start */ - cpuid_t cpu_id; /* 0xc60 */ - __u32 cpu_nr; /* 0xc68 */ - __u8 pad_0xc6c[0xc80-0xc6c]; /* 0xc6c */ - /* entry.S sensitive area end */ - - /* SMP info area: defined by DJB */ - __u64 clock_comparator; /* 0xc80 */ - __u32 ext_call_fast; /* 0xc88 */ - __u32 percpu_offset; /* 0xc8c */ - __u32 current_task; /* 0xc90 */ - __u32 softirq_pending; /* 0xc94 */ - __u64 int_clock; /* 0xc98 */ - __u8 pad11[0xe00-0xca0]; /* 0xca0 */ - - /* 0xe00 contains the address of the IPL Parameter */ - /* Information block. Dump tools need IPIB for IPL */ - /* after dump. */ - __u32 ipib; /* 0xe00 */ - __u32 ipib_checksum; /* 0xe04 */ - - /* Align to the top 1k of prefix area */ - __u8 pad12[0x1000-0xe08]; /* 0xe08 */ + /* 0x0000 - 0x01ff: defined by architecture */ + psw_t restart_psw; /* 0x0000 */ + __u32 ccw2[4]; /* 0x0008 */ + psw_t external_old_psw; /* 0x0018 */ + psw_t svc_old_psw; /* 0x0020 */ + psw_t program_old_psw; /* 0x0028 */ + psw_t mcck_old_psw; /* 0x0030 */ + psw_t io_old_psw; /* 0x0038 */ + __u8 pad_0x0040[0x0058-0x0040]; /* 0x0040 */ + psw_t external_new_psw; /* 0x0058 */ + psw_t svc_new_psw; /* 0x0060 */ + psw_t program_new_psw; /* 0x0068 */ + psw_t mcck_new_psw; /* 0x0070 */ + psw_t io_new_psw; /* 0x0078 */ + __u32 ext_params; /* 0x0080 */ + __u16 cpu_addr; /* 0x0084 */ + __u16 ext_int_code; /* 0x0086 */ + __u16 svc_ilc; /* 0x0088 */ + __u16 svc_code; /* 0x008a */ + __u16 pgm_ilc; /* 0x008c */ + __u16 pgm_code; /* 0x008e */ + __u32 trans_exc_code; /* 0x0090 */ + __u16 mon_class_num; /* 0x0094 */ + __u16 per_perc_atmid; /* 0x0096 */ + __u32 per_address; /* 0x0098 */ + __u32 monitor_code; /* 0x009c */ + __u8 exc_access_id; /* 0x00a0 */ + __u8 per_access_id; /* 0x00a1 */ + __u8 pad_0x00a2[0x00b8-0x00a2]; /* 0x00a2 */ + __u16 subchannel_id; /* 0x00b8 */ + __u16 subchannel_nr; /* 0x00ba */ + __u32 io_int_parm; /* 0x00bc */ + __u32 io_int_word; /* 0x00c0 */ + __u8 pad_0x00c4[0x00c8-0x00c4]; /* 0x00c4 */ + __u32 stfl_fac_list; /* 0x00c8 */ + __u8 pad_0x00cc[0x00d4-0x00cc]; /* 0x00cc */ + __u32 extended_save_area_addr; /* 0x00d4 */ + __u32 cpu_timer_save_area[2]; /* 0x00d8 */ + __u32 clock_comp_save_area[2]; /* 0x00e0 */ + __u32 mcck_interruption_code[2]; /* 0x00e8 */ + __u8 pad_0x00f0[0x00f4-0x00f0]; /* 0x00f0 */ + __u32 external_damage_code; /* 0x00f4 */ + __u32 failing_storage_address; /* 0x00f8 */ + __u8 pad_0x00fc[0x0100-0x00fc]; /* 0x00fc */ + __u32 st_status_fixed_logout[4]; /* 0x0100 */ + __u8 pad_0x0110[0x0120-0x0110]; /* 0x0110 */ + + /* CPU register save area: defined by architecture */ + __u32 access_regs_save_area[16]; /* 0x0120 */ + __u32 floating_pt_save_area[8]; /* 0x0160 */ + __u32 gpregs_save_area[16]; /* 0x0180 */ + __u32 cregs_save_area[16]; /* 0x01c0 */ + + /* Return psws. */ + __u32 save_area[16]; /* 0x0200 */ + psw_t return_psw; /* 0x0240 */ + psw_t return_mcck_psw; /* 0x0248 */ + + /* CPU time accounting values */ + __u64 sync_enter_timer; /* 0x0250 */ + __u64 async_enter_timer; /* 0x0258 */ + __u64 exit_timer; /* 0x0260 */ + __u64 user_timer; /* 0x0268 */ + __u64 system_timer; /* 0x0270 */ + __u64 steal_timer; /* 0x0278 */ + __u64 last_update_timer; /* 0x0280 */ + __u64 last_update_clock; /* 0x0288 */ + + /* Current process. */ + __u32 current_task; /* 0x0290 */ + __u32 thread_info; /* 0x0294 */ + __u32 kernel_stack; /* 0x0298 */ + + /* Interrupt and panic stack. */ + __u32 async_stack; /* 0x029c */ + __u32 panic_stack; /* 0x02a0 */ + + /* Address space pointer. */ + __u32 kernel_asce; /* 0x02a4 */ + __u32 user_asce; /* 0x02a8 */ + __u32 user_exec_asce; /* 0x02ac */ + + /* SMP info area */ + cpuid_t cpu_id; /* 0x02b0 */ + __u32 cpu_nr; /* 0x02b8 */ + __u32 softirq_pending; /* 0x02bc */ + __u32 percpu_offset; /* 0x02c0 */ + __u32 ext_call_fast; /* 0x02c4 */ + __u64 int_clock; /* 0x02c8 */ + __u64 clock_comparator; /* 0x02d0 */ + __u8 pad_0x02d8[0x0300-0x02d8]; /* 0x02d8 */ + + /* Interrupt response block */ + __u8 irb[64]; /* 0x0300 */ + + __u8 pad_0x0400[0x0e00-0x0400]; /* 0x0400 */ + + /* + * 0xe00 contains the address of the IPL Parameter Information + * block. Dump tools need IPIB for IPL after dump. + * Note: do not change the position of any fields in 0x0e00-0x0f00 + */ + __u32 ipib; /* 0x0e00 */ + __u32 ipib_checksum; /* 0x0e04 */ + + /* Align to the top 1k of prefix area */ + __u8 pad_0x0e08[0x1000-0x0e08]; /* 0x0e08 */ #else /* !__s390x__ */ - /* prefix area: defined by architecture */ - __u32 ccw1[2]; /* 0x000 */ - __u32 ccw2[4]; /* 0x008 */ - __u8 pad1[0x80-0x18]; /* 0x018 */ - __u32 ext_params; /* 0x080 */ - __u16 cpu_addr; /* 0x084 */ - __u16 ext_int_code; /* 0x086 */ - __u16 svc_ilc; /* 0x088 */ - __u16 svc_code; /* 0x08a */ - __u16 pgm_ilc; /* 0x08c */ - __u16 pgm_code; /* 0x08e */ - __u32 data_exc_code; /* 0x090 */ - __u16 mon_class_num; /* 0x094 */ - __u16 per_perc_atmid; /* 0x096 */ - addr_t per_address; /* 0x098 */ - __u8 exc_access_id; /* 0x0a0 */ - __u8 per_access_id; /* 0x0a1 */ - __u8 op_access_id; /* 0x0a2 */ - __u8 ar_access_id; /* 0x0a3 */ - __u8 pad2[0xA8-0xA4]; /* 0x0a4 */ - addr_t trans_exc_code; /* 0x0a8 */ - addr_t monitor_code; /* 0x0b0 */ - __u16 subchannel_id; /* 0x0b8 */ - __u16 subchannel_nr; /* 0x0ba */ - __u32 io_int_parm; /* 0x0bc */ - __u32 io_int_word; /* 0x0c0 */ - __u8 pad3[0xc8-0xc4]; /* 0x0c4 */ - __u32 stfl_fac_list; /* 0x0c8 */ - __u8 pad4[0xe8-0xcc]; /* 0x0cc */ - __u32 mcck_interruption_code[2]; /* 0x0e8 */ - __u8 pad5[0xf4-0xf0]; /* 0x0f0 */ - __u32 external_damage_code; /* 0x0f4 */ - addr_t failing_storage_address; /* 0x0f8 */ - __u8 pad6[0x120-0x100]; /* 0x100 */ - psw_t restart_old_psw; /* 0x120 */ - psw_t external_old_psw; /* 0x130 */ - psw_t svc_old_psw; /* 0x140 */ - psw_t program_old_psw; /* 0x150 */ - psw_t mcck_old_psw; /* 0x160 */ - psw_t io_old_psw; /* 0x170 */ - __u8 pad7[0x1a0-0x180]; /* 0x180 */ - psw_t restart_psw; /* 0x1a0 */ - psw_t external_new_psw; /* 0x1b0 */ - psw_t svc_new_psw; /* 0x1c0 */ - psw_t program_new_psw; /* 0x1d0 */ - psw_t mcck_new_psw; /* 0x1e0 */ - psw_t io_new_psw; /* 0x1f0 */ - psw_t return_psw; /* 0x200 */ - __u8 irb[64]; /* 0x210 */ - __u64 sync_enter_timer; /* 0x250 */ - __u64 async_enter_timer; /* 0x258 */ - __u64 exit_timer; /* 0x260 */ - __u64 user_timer; /* 0x268 */ - __u64 system_timer; /* 0x270 */ - __u64 steal_timer; /* 0x278 */ - __u64 last_update_timer; /* 0x280 */ - __u64 last_update_clock; /* 0x288 */ - psw_t return_mcck_psw; /* 0x290 */ - __u8 pad8[0xc00-0x2a0]; /* 0x2a0 */ - /* System info area */ - __u64 save_area[16]; /* 0xc00 */ - __u8 pad9[0xd40-0xc80]; /* 0xc80 */ - __u64 kernel_stack; /* 0xd40 */ - __u64 thread_info; /* 0xd48 */ - __u64 async_stack; /* 0xd50 */ - __u64 kernel_asce; /* 0xd58 */ - __u64 user_asce; /* 0xd60 */ - __u64 panic_stack; /* 0xd68 */ - __u64 user_exec_asce; /* 0xd70 */ - __u8 pad10[0xd80-0xd78]; /* 0xd78 */ - /* entry.S sensitive area start */ - cpuid_t cpu_id; /* 0xd80 */ - __u32 cpu_nr; /* 0xd88 */ - __u8 pad_0xd8c[0xdc0-0xd8c]; /* 0xd8c */ - /* entry.S sensitive area end */ - - /* SMP info area: defined by DJB */ - __u64 clock_comparator; /* 0xdc0 */ - __u64 ext_call_fast; /* 0xdc8 */ - __u64 percpu_offset; /* 0xdd0 */ - __u64 current_task; /* 0xdd8 */ - __u32 softirq_pending; /* 0xde0 */ - __u32 pad_0x0de4; /* 0xde4 */ - __u64 int_clock; /* 0xde8 */ - __u8 pad12[0xe00-0xdf0]; /* 0xdf0 */ - - /* 0xe00 contains the address of the IPL Parameter */ - /* Information block. Dump tools need IPIB for IPL */ - /* after dump. */ - __u64 ipib; /* 0xe00 */ - __u32 ipib_checksum; /* 0xe08 */ + /* 0x0000 - 0x01ff: defined by architecture */ + __u32 ccw1[2]; /* 0x0000 */ + __u32 ccw2[4]; /* 0x0008 */ + __u8 pad_0x0018[0x0080-0x0018]; /* 0x0018 */ + __u32 ext_params; /* 0x0080 */ + __u16 cpu_addr; /* 0x0084 */ + __u16 ext_int_code; /* 0x0086 */ + __u16 svc_ilc; /* 0x0088 */ + __u16 svc_code; /* 0x008a */ + __u16 pgm_ilc; /* 0x008c */ + __u16 pgm_code; /* 0x008e */ + __u32 data_exc_code; /* 0x0090 */ + __u16 mon_class_num; /* 0x0094 */ + __u16 per_perc_atmid; /* 0x0096 */ + addr_t per_address; /* 0x0098 */ + __u8 exc_access_id; /* 0x00a0 */ + __u8 per_access_id; /* 0x00a1 */ + __u8 op_access_id; /* 0x00a2 */ + __u8 ar_access_id; /* 0x00a3 */ + __u8 pad_0x00a4[0x00a8-0x00a4]; /* 0x00a4 */ + addr_t trans_exc_code; /* 0x00a8 */ + addr_t monitor_code; /* 0x00b0 */ + __u16 subchannel_id; /* 0x00b8 */ + __u16 subchannel_nr; /* 0x00ba */ + __u32 io_int_parm; /* 0x00bc */ + __u32 io_int_word; /* 0x00c0 */ + __u8 pad_0x00c4[0x00c8-0x00c4]; /* 0x00c4 */ + __u32 stfl_fac_list; /* 0x00c8 */ + __u8 pad_0x00cc[0x00e8-0x00cc]; /* 0x00cc */ + __u32 mcck_interruption_code[2]; /* 0x00e8 */ + __u8 pad_0x00f0[0x00f4-0x00f0]; /* 0x00f0 */ + __u32 external_damage_code; /* 0x00f4 */ + addr_t failing_storage_address; /* 0x00f8 */ + __u8 pad_0x0100[0x0120-0x0100]; /* 0x0100 */ + psw_t restart_old_psw; /* 0x0120 */ + psw_t external_old_psw; /* 0x0130 */ + psw_t svc_old_psw; /* 0x0140 */ + psw_t program_old_psw; /* 0x0150 */ + psw_t mcck_old_psw; /* 0x0160 */ + psw_t io_old_psw; /* 0x0170 */ + __u8 pad_0x0180[0x01a0-0x0180]; /* 0x0180 */ + psw_t restart_psw; /* 0x01a0 */ + psw_t external_new_psw; /* 0x01b0 */ + psw_t svc_new_psw; /* 0x01c0 */ + psw_t program_new_psw; /* 0x01d0 */ + psw_t mcck_new_psw; /* 0x01e0 */ + psw_t io_new_psw; /* 0x01f0 */ + + /* Entry/exit save area & return psws. */ + __u64 save_area[16]; /* 0x0200 */ + psw_t return_psw; /* 0x0280 */ + psw_t return_mcck_psw; /* 0x0290 */ + + /* CPU accounting and timing values. */ + __u64 sync_enter_timer; /* 0x02a0 */ + __u64 async_enter_timer; /* 0x02a8 */ + __u64 exit_timer; /* 0x02b0 */ + __u64 user_timer; /* 0x02b8 */ + __u64 system_timer; /* 0x02c0 */ + __u64 steal_timer; /* 0x02c8 */ + __u64 last_update_timer; /* 0x02d0 */ + __u64 last_update_clock; /* 0x02d8 */ + + /* Current process. */ + __u64 current_task; /* 0x02e0 */ + __u64 thread_info; /* 0x02e8 */ + __u64 kernel_stack; /* 0x02f0 */ + + /* Interrupt and panic stack. */ + __u64 async_stack; /* 0x02f8 */ + __u64 panic_stack; /* 0x0300 */ + + /* Address space pointer. */ + __u64 kernel_asce; /* 0x0308 */ + __u64 user_asce; /* 0x0310 */ + __u64 user_exec_asce; /* 0x0318 */ + + /* SMP info area */ + cpuid_t cpu_id; /* 0x0320 */ + __u32 cpu_nr; /* 0x0328 */ + __u32 softirq_pending; /* 0x032c */ + __u64 percpu_offset; /* 0x0330 */ + __u64 ext_call_fast; /* 0x0338 */ + __u64 int_clock; /* 0x0340 */ + __u64 clock_comparator; /* 0x0348 */ + __u64 vdso_per_cpu_data; /* 0x0350 */ + __u8 pad_0x0358[0x0380-0x0358]; /* 0x0358 */ + + /* Interrupt response block. */ + __u8 irb[64]; /* 0x0380 */ /* Per cpu primary space access list */ - __u8 pad_0xe0c[0xe38-0xe0c]; /* 0xe0c */ - __u64 vdso_per_cpu_data; /* 0xe38 */ - __u32 paste[16]; /* 0xe40 */ - - __u8 pad13[0x11b8-0xe80]; /* 0xe80 */ - - /* 64 bit extparam used for pfault, diag 250 etc */ - __u64 ext_params2; /* 0x11B8 */ - - __u8 pad14[0x1200-0x11C0]; /* 0x11C0 */ - - /* System info area */ - - __u64 floating_pt_save_area[16]; /* 0x1200 */ - __u64 gpregs_save_area[16]; /* 0x1280 */ - __u32 st_status_fixed_logout[4]; /* 0x1300 */ - __u8 pad15[0x1318-0x1310]; /* 0x1310 */ - __u32 prefixreg_save_area; /* 0x1318 */ - __u32 fpt_creg_save_area; /* 0x131c */ - __u8 pad16[0x1324-0x1320]; /* 0x1320 */ - __u32 tod_progreg_save_area; /* 0x1324 */ - __u32 cpu_timer_save_area[2]; /* 0x1328 */ - __u32 clock_comp_save_area[2]; /* 0x1330 */ - __u8 pad17[0x1340-0x1338]; /* 0x1338 */ - __u32 access_regs_save_area[16]; /* 0x1340 */ - __u64 cregs_save_area[16]; /* 0x1380 */ + __u32 paste[16]; /* 0x03c0 */ + + __u8 pad_0x0400[0x0e00-0x0400]; /* 0x0400 */ + + /* + * 0xe00 contains the address of the IPL Parameter Information + * block. Dump tools need IPIB for IPL after dump. + * Note: do not change the position of any fields in 0x0e00-0x0f00 + */ + __u64 ipib; /* 0x0e00 */ + __u32 ipib_checksum; /* 0x0e08 */ + __u8 pad_0x0e0c[0x11b8-0x0e0c]; /* 0x0e0c */ + + /* 64 bit extparam used for pfault/diag 250: defined by architecture */ + __u64 ext_params2; /* 0x11B8 */ + __u8 pad_0x11c0[0x1200-0x11C0]; /* 0x11C0 */ + + /* CPU register save area: defined by architecture */ + __u64 floating_pt_save_area[16]; /* 0x1200 */ + __u64 gpregs_save_area[16]; /* 0x1280 */ + __u32 st_status_fixed_logout[4]; /* 0x1300 */ + __u8 pad_0x1310[0x1318-0x1310]; /* 0x1310 */ + __u32 prefixreg_save_area; /* 0x1318 */ + __u32 fpt_creg_save_area; /* 0x131c */ + __u8 pad_0x1320[0x1324-0x1320]; /* 0x1320 */ + __u32 tod_progreg_save_area; /* 0x1324 */ + __u32 cpu_timer_save_area[2]; /* 0x1328 */ + __u32 clock_comp_save_area[2]; /* 0x1330 */ + __u8 pad_0x1338[0x1340-0x1338]; /* 0x1338 */ + __u32 access_regs_save_area[16]; /* 0x1340 */ + __u64 cregs_save_area[16]; /* 0x1380 */ /* align to the top of the prefix area */ - - __u8 pad18[0x2000-0x1400]; /* 0x1400 */ + __u8 pad_0x1400[0x2000-0x1400]; /* 0x1400 */ #endif /* !__s390x__ */ } __attribute__((packed)); /* End structure*/ diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index ec7e35f6055..1046c2c9f8d 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S @@ -469,6 +469,8 @@ start: .org 0x10000 startup:basr %r13,0 # get base .LPG0: + xc 0x200(256),0x200 # partially clear lowcore + xc 0x300(256),0x300 #ifndef CONFIG_MARCH_G5 # check processor version against MARCH_{G5,Z900,Z990,Z9_109,Z10} -- GitLab From 159d1ff8f6c38086ed75f8e892790d0a4f3a6b71 Mon Sep 17 00:00:00 2001 From: Frank Munzert Date: Thu, 26 Mar 2009 15:24:45 +0100 Subject: [PATCH 4672/4982] [S390] Use csum_partial in checksum.h The cksm function in system.h is duplicate to csum_partial in checksum.h. Remove cksm and use csum_partial instead. Signed-off-by: Frank Munzert Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/system.h | 16 ---------------- arch/s390/kernel/ipl.c | 4 +++- drivers/s390/char/zcore.c | 4 +++- 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/arch/s390/include/asm/system.h b/arch/s390/include/asm/system.h index 3f2ccb82b86..3a8b26eb1f2 100644 --- a/arch/s390/include/asm/system.h +++ b/arch/s390/include/asm/system.h @@ -458,22 +458,6 @@ static inline unsigned short stap(void) return cpu_address; } -static inline u32 cksm(void *addr, unsigned long len) -{ - register unsigned long _addr asm("0") = (unsigned long) addr; - register unsigned long _len asm("1") = len; - unsigned long accu = 0; - - asm volatile( - "0:\n" - " cksm %0,%1\n" - " jnz 0b\n" - : "+d" (accu), "+d" (_addr), "+d" (_len) - : - : "cc", "memory"); - return accu; -} - extern void (*_machine_restart)(char *command); extern void (*_machine_halt)(void); extern void (*_machine_power_off)(void); diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 5663c1f8e46..505fec06e63 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -24,6 +24,7 @@ #include #include #include +#include #define IPL_PARM_BLOCK_VERSION 0 @@ -1359,7 +1360,8 @@ static void dump_reipl_run(struct shutdown_trigger *trigger) "a" (&lowcore_ptr[smp_processor_id()]->ipib)); #endif asm volatile("stura %0,%1" - :: "a" (cksm(reipl_block_actual, reipl_block_actual->hdr.len)), + :: "a" (csum_partial(reipl_block_actual, + reipl_block_actual->hdr.len, 0)), "a" (&lowcore_ptr[smp_processor_id()]->ipib_checksum)); preempt_enable(); dump_run(trigger); diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index cfe782ee647..1bbae433fbd 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "sclp.h" #define TRACE(x...) debug_sprintf_event(zcore_dbf, 1, x) @@ -704,7 +705,8 @@ static int __init zcore_reipl_init(void) free_page((unsigned long) ipl_block); return rc; } - if (cksm(ipl_block, ipl_block->hdr.len) != ipib_info.checksum) { + if (csum_partial(ipl_block, ipl_block->hdr.len, 0) != + ipib_info.checksum) { TRACE("Checksum does not match\n"); free_page((unsigned long) ipl_block); ipl_block = NULL; -- GitLab From 59f2e69d0f95bc00353628ef33fd534fbb8e3597 Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Thu, 26 Mar 2009 15:24:46 +0100 Subject: [PATCH 4673/4982] [S390] zfcpdump: Prevent zcore from beeing built as a kernel module. The zcore code switches to real addressing mode when creating a kernel dump. This is not possible, if it is built as a kernel module. With this patch zcore (zfcpdump) can't be built as a kernel module any more. Signed-off-by: Michael Holzheu Signed-off-by: Martin Schwidefsky --- arch/s390/Kconfig | 2 +- arch/s390/kernel/setup.c | 4 ++-- arch/s390/kernel/smp.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 0a9463bea75..2a8af5e1634 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -545,7 +545,7 @@ config KEXEC but is independent of hardware/microcode support. config ZFCPDUMP - tristate "zfcpdump support" + bool "zfcpdump support" select SMP default n help diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 91551ef1d67..46fc981e02b 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -226,7 +226,7 @@ static void __init conmode_default(void) } } -#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE) +#ifdef CONFIG_ZFCPDUMP static void __init setup_zfcpdump(unsigned int console_devno) { static char str[41]; @@ -515,7 +515,7 @@ static void __init setup_memory_end(void) unsigned long max_mem; int i; -#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE) +#ifdef CONFIG_ZFCPDUMP if (ipl_info.type == IPL_TYPE_FCP_DUMP) { memory_end = ZFCPDUMP_HSA_SIZE; memory_end_set = 1; diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 775885772ff..bb3d34aa7b8 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -226,7 +226,7 @@ EXPORT_SYMBOL(smp_ctl_clear_bit); */ #define CPU_INIT_NO 1 -#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE) +#ifdef CONFIG_ZFCPDUMP /* * zfcpdump_prefix_array holds prefix registers for the following scenario: @@ -267,7 +267,7 @@ EXPORT_SYMBOL_GPL(zfcpdump_save_areas); static inline void smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) { } -#endif /* CONFIG_ZFCPDUMP || CONFIG_ZFCPDUMP_MODULE */ +#endif /* CONFIG_ZFCPDUMP */ static int cpu_stopped(int cpu) { -- GitLab From 6aa0d3a922c4f58fc36cc1502c6ac72f999e26bb Mon Sep 17 00:00:00 2001 From: Stoyan Gaydarov Date: Thu, 26 Mar 2009 15:24:47 +0100 Subject: [PATCH 4674/4982] [S390] BUG to BUG_ON changes Signed-off-by: Stoyan Gaydarov Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/debug.c | 3 +-- arch/s390/kernel/setup.c | 3 +-- drivers/s390/char/tape_3590.c | 3 +-- drivers/s390/char/tape_core.c | 6 ++---- drivers/s390/char/tape_std.c | 4 ++-- 5 files changed, 7 insertions(+), 12 deletions(-) diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index ba03fc0a3a5..39137b9e162 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c @@ -698,8 +698,7 @@ debug_info_t *debug_register_mode(const char *name, int pages_per_area, if ((uid != 0) || (gid != 0)) pr_warning("Root becomes the owner of all s390dbf files " "in sysfs\n"); - if (!initialized) - BUG(); + BUG_ON(!initialized); mutex_lock(&debug_mutex); /* create new debug_info */ diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 46fc981e02b..580abb53ce8 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -134,8 +134,7 @@ void __cpuinit cpu_init(void) atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; - if (current->mm) - BUG(); + BUG_ON(current->mm); enter_lazy_tlb(&init_mm, current); } diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index 5a5bb97a081..fc1d9129414 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c @@ -664,8 +664,7 @@ tape_3590_bread(struct tape_device *device, struct request *req) ccw++; dst += TAPEBLOCK_HSEC_SIZE; } - if (off > bv->bv_len) - BUG(); + BUG_ON(off > bv->bv_len); } ccw = tape_ccw_end(ccw, NOP, 0, NULL); DBF_EVENT(6, "xBREDccwg\n"); diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index 1b6a2441246..08c09d3503c 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c @@ -624,8 +624,7 @@ tape_alloc_request(int cplength, int datasize) { struct tape_request *request; - if (datasize > PAGE_SIZE || (cplength*sizeof(struct ccw1)) > PAGE_SIZE) - BUG(); + BUG_ON(datasize > PAGE_SIZE || (cplength*sizeof(struct ccw1)) > PAGE_SIZE); DBF_LH(6, "tape_alloc_request(%d, %d)\n", cplength, datasize); @@ -782,8 +781,7 @@ static void tape_long_busy_timeout(unsigned long data) device = (struct tape_device *) data; spin_lock_irq(get_ccwdev_lock(device->cdev)); request = list_entry(device->req_queue.next, struct tape_request, list); - if (request->status != TAPE_REQUEST_LONG_BUSY) - BUG(); + BUG_ON(request->status != TAPE_REQUEST_LONG_BUSY); DBF_LH(6, "%08x: Long busy timeout.\n", device->cdev_id); __tape_start_next_request(device); device->lb_timeout.data = (unsigned long) tape_put_device(device); diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c index 44dd0f80c84..1a9420ba518 100644 --- a/drivers/s390/char/tape_std.c +++ b/drivers/s390/char/tape_std.c @@ -37,8 +37,8 @@ tape_std_assign_timeout(unsigned long data) int rc; request = (struct tape_request *) data; - if ((device = request->device) == NULL) - BUG(); + device = request->device; + BUG_ON(!device); DBF_EVENT(3, "%08x: Assignment timeout. Device busy.\n", device->cdev_id); -- GitLab From 3e75a902196c45d26d5e28014eb2d9821aa9794f Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Thu, 26 Mar 2009 15:24:48 +0100 Subject: [PATCH 4675/4982] [S390] use kzfree() Use kzfree() instead of memset() + kfree(). Signed-off-by: Johannes Weiner Reviewed-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/crypto/prng.c | 3 +-- drivers/s390/crypto/zcrypt_pcixcc.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/s390/crypto/prng.c b/arch/s390/crypto/prng.c index eca724d229e..b49c00ce65e 100644 --- a/arch/s390/crypto/prng.c +++ b/arch/s390/crypto/prng.c @@ -201,8 +201,7 @@ out_free: static void __exit prng_exit(void) { /* wipe me */ - memset(p->buf, 0, prng_chunk_size); - kfree(p->buf); + kzfree(p->buf); kfree(p); misc_deregister(&prng_dev); diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c index e7a1e22e77a..c20d4790258 100644 --- a/drivers/s390/crypto/zcrypt_pcixcc.c +++ b/drivers/s390/crypto/zcrypt_pcixcc.c @@ -781,8 +781,7 @@ static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev, /* Signal pending. */ ap_cancel_message(zdev->ap_dev, &ap_msg); out_free: - memset(ap_msg.message, 0x0, ap_msg.length); - kfree(ap_msg.message); + kzfree(ap_msg.message); return rc; } -- GitLab From a0fa8e3743c80643a06a770b95e73e751548ab17 Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Thu, 26 Mar 2009 15:24:49 +0100 Subject: [PATCH 4676/4982] [S390] s390dbf: Remove redundant initilizations. Signed-off-by: Michael Holzheu Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/debug.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index 39137b9e162..369de12b873 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c @@ -603,7 +603,7 @@ debug_input(struct file *file, const char __user *user_buf, size_t length, static int debug_open(struct inode *inode, struct file *file) { - int i = 0, rc = 0; + int i, rc = 0; file_private_info_t *p_info; debug_info_t *debug_info, *debug_info_snapshot; @@ -1155,7 +1155,6 @@ debug_unregister_view(debug_info_t * id, struct debug_view *view) else { debugfs_remove(id->debugfs_entries[i]); id->views[i] = NULL; - rc = 0; } spin_unlock_irqrestore(&id->lock, flags); out: -- GitLab From 58ace9f2a8f1caa0303aa64079d3929be28a937a Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Thu, 26 Mar 2009 15:24:50 +0100 Subject: [PATCH 4677/4982] [S390] s390dbf: Remove needless check for NULL pointer. The check for NULL pointer has already be done before. Therefore we can remove the second check. Signed-off-by: Michael Holzheu Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/debug.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index 369de12b873..be8bceaf37d 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c @@ -642,8 +642,7 @@ found: p_info = kmalloc(sizeof(file_private_info_t), GFP_KERNEL); if(!p_info){ - if(debug_info_snapshot) - debug_info_free(debug_info_snapshot); + debug_info_free(debug_info_snapshot); rc = -ENOMEM; goto out; } -- GitLab From 008d2d112cb8a743a87dfe41a67e11c0a4c73aa4 Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Thu, 26 Mar 2009 15:24:51 +0100 Subject: [PATCH 4678/4982] [S390] ipl: Improve checking logic and remove switch defaults. A code analysis tool reported two warnings: "The expression `ipl_info.type == IPL_TYPE_FCP' is true whenever evaluated." and "Default is not possible". This patch improves the corresponding if statement logic and removes the unnecessary switch defaults. Signed-off-by: Michael Holzheu Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/ipl.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 505fec06e63..2b901fb8193 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -966,7 +966,6 @@ static void reipl_run(struct shutdown_trigger *trigger) diag308(DIAG308_IPL, NULL); break; case REIPL_METHOD_FCP_DUMP: - default: break; } disabled_wait((unsigned long) __builtin_return_address(0)); @@ -1075,10 +1074,12 @@ static int __init reipl_fcp_init(void) { int rc; - if ((!diag308_set_works) && (ipl_info.type != IPL_TYPE_FCP)) - return 0; - if ((!diag308_set_works) && (ipl_info.type == IPL_TYPE_FCP)) - make_attrs_ro(reipl_fcp_attrs); + if (!diag308_set_works) { + if (ipl_info.type == IPL_TYPE_FCP) + make_attrs_ro(reipl_fcp_attrs); + else + return 0; + } reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL); if (!reipl_block_fcp) @@ -1259,7 +1260,6 @@ static void dump_run(struct shutdown_trigger *trigger) diag308(DIAG308_DUMP, NULL); break; case DUMP_METHOD_NONE: - default: return; } printk(KERN_EMERG "Dump failed!\n"); @@ -1746,7 +1746,6 @@ void __init setup_ipl(void) sizeof(ipl_info.data.nss.name)); break; case IPL_TYPE_UNKNOWN: - default: /* We have no info to copy */ break; } -- GitLab From 6d54c5a3fb13d32d66a8383cb0b5fb422a563051 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 26 Mar 2009 15:24:52 +0100 Subject: [PATCH 4679/4982] [S390] smp: fix memory leak on __cpu_up If sigp_set_prefix fails on __cpu_up we leak the lowcore structures and async+panic stacks for the failed cpu. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/smp.c | 6 +++--- arch/s390/kernel/vdso.c | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index bb3d34aa7b8..1f4711b60aa 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -508,7 +508,6 @@ out: return -ENOMEM; } -#ifdef CONFIG_HOTPLUG_CPU static void smp_free_lowcore(int cpu) { struct _lowcore *lowcore; @@ -527,7 +526,6 @@ static void smp_free_lowcore(int cpu) free_pages((unsigned long) lowcore, lc_order); lowcore_ptr[cpu] = NULL; } -#endif /* CONFIG_HOTPLUG_CPU */ /* Upping and downing of CPUs */ int __cpuinit __cpu_up(unsigned int cpu) @@ -544,8 +542,10 @@ int __cpuinit __cpu_up(unsigned int cpu) ccode = signal_processor_p((__u32)(unsigned long)(lowcore_ptr[cpu]), cpu, sigp_set_prefix); - if (ccode) + if (ccode) { + smp_free_lowcore(cpu); return -EIO; + } idle = current_set[cpu]; cpu_lowcore = lowcore_ptr[cpu]; diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c index 690e1781968..89b2e7f1b7a 100644 --- a/arch/s390/kernel/vdso.c +++ b/arch/s390/kernel/vdso.c @@ -144,7 +144,6 @@ out: return -ENOMEM; } -#ifdef CONFIG_HOTPLUG_CPU void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore) { unsigned long segment_table, page_table, page_frame; @@ -163,7 +162,6 @@ void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore) free_page(page_table); free_pages(segment_table, SEGMENT_ORDER); } -#endif /* CONFIG_HOTPLUG_CPU */ static void __vdso_init_cr5(void *dummy) { -- GitLab From d0d3cdf4c27fa4ce241616da08138954e02890f7 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 26 Mar 2009 15:24:53 +0100 Subject: [PATCH 4680/4982] [S390] smp: perform initial cpu reset before starting a cpu Performing an initial cpu reset makes sure all registers and tlbs of the targeted cpu are initialized and flushed. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/smp.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 1f4711b60aa..fe5f8dc1e6f 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -534,18 +534,23 @@ int __cpuinit __cpu_up(unsigned int cpu) struct _lowcore *cpu_lowcore; struct stack_frame *sf; sigp_ccode ccode; + u32 lowcore; if (smp_cpu_state[cpu] != CPU_STATE_CONFIGURED) return -EIO; if (smp_alloc_lowcore(cpu)) return -ENOMEM; - - ccode = signal_processor_p((__u32)(unsigned long)(lowcore_ptr[cpu]), - cpu, sigp_set_prefix); - if (ccode) { - smp_free_lowcore(cpu); - return -EIO; - } + do { + ccode = signal_processor(cpu, sigp_initial_cpu_reset); + if (ccode == sigp_busy) + udelay(10); + if (ccode == sigp_not_operational) + goto err_out; + } while (ccode == sigp_busy); + + lowcore = (u32)(unsigned long)lowcore_ptr[cpu]; + while (signal_processor_p(lowcore, cpu, sigp_set_prefix) == sigp_busy) + udelay(10); idle = current_set[cpu]; cpu_lowcore = lowcore_ptr[cpu]; @@ -574,6 +579,10 @@ int __cpuinit __cpu_up(unsigned int cpu) while (!cpu_online(cpu)) cpu_relax(); return 0; + +err_out: + smp_free_lowcore(cpu); + return -EIO; } static int __init setup_possible_cpus(char *s) -- GitLab From 2ac3307f275c2a91af0417e16d2cfb95ae478661 Mon Sep 17 00:00:00 2001 From: Christian Ehrhardt Date: Thu, 26 Mar 2009 15:24:54 +0100 Subject: [PATCH 4681/4982] [S390] fix dfp elf hwcap/facility bit detection The old dfp detection wanted to check bit 43 (dfp high performance), but due to a wrong calculation always used to check bit 42. Additionally the "userspace expectation" is, that the dfp capability bit is set is if facility bit 42 (decimal floating point facility available) and bit 44 (perform floating point operation facility avail). The patch fixes the bit calculation and extends the check to work like: elf hw cap dfp bit = facility bits 42 (dfp) & 44 (pfpo) available Signed-off-by: Christian Ehrhardt Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/setup.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 580abb53ce8..18222ac4078 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -713,13 +713,15 @@ static void __init setup_hwcaps(void) * How many facility words are stored depends on the number of * doublewords passed to the instruction. The additional facilites * are: - * Bit 43: decimal floating point facility is installed + * Bit 42: decimal floating point facility is installed + * Bit 44: perform floating point operation facility is installed * translated to: * HWCAP_S390_DFP bit 6. */ if ((elf_hwcap & (1UL << 2)) && __stfle(&facility_list_extended, 1) > 0) { - if (facility_list_extended & (1ULL << (64 - 43))) + if ((facility_list_extended & (1ULL << (63 - 42))) + && (facility_list_extended & (1ULL << (63 - 44)))) elf_hwcap |= 1UL << 6; } -- GitLab From 7e9b580e5f0644cd8952b6671fd5380fd430bca3 Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Thu, 26 Mar 2009 15:24:55 +0100 Subject: [PATCH 4682/4982] [S390] Ensure that ipl panic notifier is called late. The s390 ipl panic notifier will stop the system or trigger a system dump. This should be done as final action on the panic path. All other panic notifiers should be executed before. Currently we use priority 0 for the ipl notifier. In order to be called late, this patch changes the priority to INT_MIN which is the lowest possible priority. Signed-off-by: Michael Holzheu Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/ipl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 2b901fb8193..56d876904ec 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -1722,7 +1722,7 @@ static int on_panic_notify(struct notifier_block *self, static struct notifier_block on_panic_nb = { .notifier_call = on_panic_notify, - .priority = 0, + .priority = INT_MIN, }; void __init setup_ipl(void) -- GitLab From 488253ce49714f4e9d42413c1d60b7724059a338 Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Thu, 26 Mar 2009 15:24:56 +0100 Subject: [PATCH 4683/4982] [S390] Add hwcap flag for the etf3 enhancement facility The Extended Translation Facility 3 (ETF3) added instructions which allow conversions between different unicode character maps (UTF-8, UTF-32 ...). These instructions got enhanced with a later version of the ETF3 allowing malformed multibyte chars to be recognized and reported correctly. The attached patch reserves bit 8 in the elf hwcaps vector for the enhanced version of ETF3. The bit corresponds to the stfle bits 22 and 30 and will only be set if both of the stfle bits are set. Signed-off-by: Andreas Krebbel Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/processor.c | 6 +++--- arch/s390/kernel/setup.c | 13 ++++++++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c index 423da1bd42a..802c8ab247f 100644 --- a/arch/s390/kernel/processor.c +++ b/arch/s390/kernel/processor.c @@ -31,9 +31,9 @@ void __cpuinit print_cpu_info(void) static int show_cpuinfo(struct seq_file *m, void *v) { - static const char *hwcap_str[8] = { + static const char *hwcap_str[9] = { "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", - "edat" + "edat", "etf3eh" }; struct _lowcore *lc; unsigned long n = (unsigned long) v - 1; @@ -48,7 +48,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) num_online_cpus(), loops_per_jiffy/(500000/HZ), (loops_per_jiffy/(5000/HZ))%100); seq_puts(m, "features\t: "); - for (i = 0; i < 8; i++) + for (i = 0; i < 9; i++) if (hwcap_str[i] && (elf_hwcap & (1UL << i))) seq_printf(m, "%s ", hwcap_str[i]); seq_puts(m, "\n"); diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 18222ac4078..06201b93cbb 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -696,15 +696,22 @@ static void __init setup_hwcaps(void) * Bit 17: the message-security assist is installed * Bit 19: the long-displacement facility is installed * Bit 21: the extended-immediate facility is installed + * Bit 22: extended-translation facility 3 is installed + * Bit 30: extended-translation facility 3 enhancement facility * These get translated to: * HWCAP_S390_ESAN3 bit 0, HWCAP_S390_ZARCH bit 1, * HWCAP_S390_STFLE bit 2, HWCAP_S390_MSA bit 3, - * HWCAP_S390_LDISP bit 4, and HWCAP_S390_EIMM bit 5. + * HWCAP_S390_LDISP bit 4, HWCAP_S390_EIMM bit 5 and + * HWCAP_S390_ETF3EH bit 8 (22 && 30). */ for (i = 0; i < 6; i++) if (facility_list & (1UL << (31 - stfl_bits[i]))) elf_hwcap |= 1UL << i; + if ((facility_list & (1UL << (31 - 22))) + && (facility_list & (1UL << (31 - 30)))) + elf_hwcap |= 1UL << 8; + /* * Check for additional facilities with store-facility-list-extended. * stfle stores doublewords (8 byte) with bit 1ULL<<63 as bit 0 @@ -716,12 +723,12 @@ static void __init setup_hwcaps(void) * Bit 42: decimal floating point facility is installed * Bit 44: perform floating point operation facility is installed * translated to: - * HWCAP_S390_DFP bit 6. + * HWCAP_S390_DFP bit 6 (42 && 44). */ if ((elf_hwcap & (1UL << 2)) && __stfle(&facility_list_extended, 1) > 0) { if ((facility_list_extended & (1ULL << (63 - 42))) - && (facility_list_extended & (1ULL << (63 - 44)))) + && (facility_list_extended & (1ULL << (63 - 44)))) elf_hwcap |= 1UL << 6; } -- GitLab From c70d0fef1da286d7f96e774674aea2d20cf6222f Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 26 Mar 2009 15:24:57 +0100 Subject: [PATCH 4684/4982] [S390] fix clock comparator save area usage The lowcore clock comparator save area on 64 bit machines is defined to contain only the seven most significant bits of the register. That's also why it starts at an uneven address (0x1331). The current code however writes eight bytes to the address and therefore overwrites the first byte of the access register save area. Fix this and write only seven bytes to the save area. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/reipl64.S | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/arch/s390/kernel/reipl64.S b/arch/s390/kernel/reipl64.S index c41930499a5..774147824c3 100644 --- a/arch/s390/kernel/reipl64.S +++ b/arch/s390/kernel/reipl64.S @@ -1,10 +1,7 @@ /* - * arch/s390/kernel/reipl.S - * - * S390 version - * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com) - Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) + * Copyright IBM Corp 2000,2009 + * Author(s): Holger Smolinski , + * Denis Joseph Barrow, */ #include @@ -30,7 +27,7 @@ do_reipl_asm: basr %r13,0 mvc __LC_PREFIX_SAVE_AREA-0x1000(4,%r1),0(%r10) stfpc __LC_FP_CREG_SAVE_AREA-0x1000(%r1) stckc .Lclkcmp-.Lpg0(%r13) - mvc __LC_CLOCK_COMP_SAVE_AREA-0x1000(8,%r1),.Lclkcmp-.Lpg0(%r13) + mvc __LC_CLOCK_COMP_SAVE_AREA-0x1000(7,%r1),.Lclkcmp-.Lpg0(%r13) stpt __LC_CPU_TIMER_SAVE_AREA-0x1000(%r1) stg %r13, __LC_PSW_SAVE_AREA-0x1000+8(%r1) -- GitLab From 6f7a321d5feb0bc9aa7f7b14eceb1e6a63bff937 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 26 Mar 2009 15:24:58 +0100 Subject: [PATCH 4685/4982] [S390] cpumask: remove cpu_coregroup_map Impact: cleanup cpu_coregroup_mask is the New Hotness. As S/390 uses theirs internally, so we just make it static. Signed-off-by: Rusty Russell Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/topology.h | 1 - arch/s390/kernel/topology.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h index c979c3b56ab..5e0ad618dc4 100644 --- a/arch/s390/include/asm/topology.h +++ b/arch/s390/include/asm/topology.h @@ -5,7 +5,6 @@ #define mc_capable() (1) -cpumask_t cpu_coregroup_map(unsigned int cpu); const struct cpumask *cpu_coregroup_mask(unsigned int cpu); extern cpumask_t cpu_core_map[NR_CPUS]; diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index cc362c9ea8f..3c72c9cf22b 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c @@ -74,7 +74,7 @@ static DEFINE_SPINLOCK(topology_lock); cpumask_t cpu_core_map[NR_CPUS]; -cpumask_t cpu_coregroup_map(unsigned int cpu) +static cpumask_t cpu_coregroup_map(unsigned int cpu) { struct core_info *core = &core_info; unsigned long flags; -- GitLab From 93632d1bf7447d445c6fc274c8931152f9412b56 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 26 Mar 2009 15:24:59 +0100 Subject: [PATCH 4686/4982] [S390] cpumask: prepare for iterators to only go to nr_cpu_ids/nr_cpumask_bits. Impact: cleanup, futureproof In fact, all cpumask ops will only be valid (in general) for bit numbers < nr_cpu_ids. So use that instead of NR_CPUS in various places (I also updated the immediate sites to use the new cpumask_ operators). This is always safe: no cpu number can be >= nr_cpu_ids, and nr_cpu_ids is initialized to NR_CPUS at boot. Signed-off-by: Rusty Russell Signed-off-by: Mike Travis Acked-by: Ingo Molnar Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/smp.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index fe5f8dc1e6f..13052a4ed71 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -297,8 +297,8 @@ static int smp_rescan_cpus_sigp(cpumask_t avail) { int cpu_id, logical_cpu; - logical_cpu = first_cpu(avail); - if (logical_cpu == NR_CPUS) + logical_cpu = cpumask_first(&avail); + if (logical_cpu >= nr_cpu_ids) return 0; for (cpu_id = 0; cpu_id <= 65535; cpu_id++) { if (cpu_known(cpu_id)) @@ -309,8 +309,8 @@ static int smp_rescan_cpus_sigp(cpumask_t avail) continue; cpu_set(logical_cpu, cpu_present_map); smp_cpu_state[logical_cpu] = CPU_STATE_CONFIGURED; - logical_cpu = next_cpu(logical_cpu, avail); - if (logical_cpu == NR_CPUS) + logical_cpu = cpumask_next(logical_cpu, &avail); + if (logical_cpu >= nr_cpu_ids) break; } return 0; @@ -322,8 +322,8 @@ static int smp_rescan_cpus_sclp(cpumask_t avail) int cpu_id, logical_cpu, cpu; int rc; - logical_cpu = first_cpu(avail); - if (logical_cpu == NR_CPUS) + logical_cpu = cpumask_first(&avail); + if (logical_cpu >= nr_cpu_ids) return 0; info = kmalloc(sizeof(*info), GFP_KERNEL); if (!info) @@ -344,8 +344,8 @@ static int smp_rescan_cpus_sclp(cpumask_t avail) smp_cpu_state[logical_cpu] = CPU_STATE_STANDBY; else smp_cpu_state[logical_cpu] = CPU_STATE_CONFIGURED; - logical_cpu = next_cpu(logical_cpu, avail); - if (logical_cpu == NR_CPUS) + logical_cpu = cpumask_next(logical_cpu, &avail); + if (logical_cpu >= nr_cpu_ids) break; } out: @@ -591,7 +591,7 @@ static int __init setup_possible_cpus(char *s) pcpus = simple_strtoul(s, NULL, 0); cpu_possible_map = cpumask_of_cpu(0); - for (cpu = 1; cpu < pcpus && cpu < NR_CPUS; cpu++) + for (cpu = 1; cpu < pcpus && cpu < nr_cpu_ids; cpu++) cpu_set(cpu, cpu_possible_map); return 0; } -- GitLab From def6cfb70bab83c0094bc0cedd27c4eda563043e Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 26 Mar 2009 15:25:00 +0100 Subject: [PATCH 4687/4982] [S390] cpumask: Use accessors code. Impact: use new API Use the accessors rather than frobbing bits directly. Most of this is in arch code I haven't even compiled, but is straightforward. Signed-off-by: Rusty Russell Signed-off-by: Mike Travis Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/smp.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 13052a4ed71..006ed5016eb 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -590,9 +590,8 @@ static int __init setup_possible_cpus(char *s) int pcpus, cpu; pcpus = simple_strtoul(s, NULL, 0); - cpu_possible_map = cpumask_of_cpu(0); - for (cpu = 1; cpu < pcpus && cpu < nr_cpu_ids; cpu++) - cpu_set(cpu, cpu_possible_map); + for (cpu = 0; cpu < pcpus && cpu < nr_cpu_ids; cpu++) + set_cpu_possible(cpu, true); return 0; } early_param("possible_cpus", setup_possible_cpus); -- GitLab From 005f8eee6f3c8173e492d7bd4d51bda990eb468b Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 26 Mar 2009 15:25:01 +0100 Subject: [PATCH 4688/4982] [S390] cpumask: use mm_cpumask() wrapper Makes code futureproof against the impending change to mm->cpu_vm_mask. It's also a chance to use the new cpumask_ ops which take a pointer (the older ones are deprecated, but there's no hurry for arch code). Signed-off-by: Rusty Russell Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/mmu_context.h | 2 +- arch/s390/include/asm/tlbflush.h | 4 ++-- arch/s390/mm/pgtable.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h index 28ec870655a..fc7edd6f41b 100644 --- a/arch/s390/include/asm/mmu_context.h +++ b/arch/s390/include/asm/mmu_context.h @@ -74,7 +74,7 @@ static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk) static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk) { - cpu_set(smp_processor_id(), next->cpu_vm_mask); + cpumask_set_cpu(smp_processor_id(), mm_cpumask(next)); update_mm(next, tsk); } diff --git a/arch/s390/include/asm/tlbflush.h b/arch/s390/include/asm/tlbflush.h index d60394b9745..304cffa623e 100644 --- a/arch/s390/include/asm/tlbflush.h +++ b/arch/s390/include/asm/tlbflush.h @@ -51,7 +51,7 @@ static inline void __tlb_flush_full(struct mm_struct *mm) * If the process only ran on the local cpu, do a local flush. */ local_cpumask = cpumask_of_cpu(smp_processor_id()); - if (cpus_equal(mm->cpu_vm_mask, local_cpumask)) + if (cpumask_equal(mm_cpumask(mm), &local_cpumask)) __tlb_flush_local(); else __tlb_flush_global(); @@ -73,7 +73,7 @@ static inline void __tlb_flush_idte(unsigned long asce) static inline void __tlb_flush_mm(struct mm_struct * mm) { - if (unlikely(cpus_empty(mm->cpu_vm_mask))) + if (unlikely(cpumask_empty(mm_cpumask(mm)))) return; /* * If the machine has IDTE we prefer to do a per mm flush diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 9bf86125f6f..be6c1cf4ad5 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -296,7 +296,7 @@ int s390_enable_sie(void) tsk->mm = tsk->active_mm = mm; preempt_disable(); update_mm(mm, tsk); - cpu_set(smp_processor_id(), mm->cpu_vm_mask); + cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm)); preempt_enable(); task_unlock(tsk); mmput(old_mm); -- GitLab From ef3500b2b2955af4fa6b0564b51c0c604e38c571 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Thu, 26 Mar 2009 15:25:02 +0100 Subject: [PATCH 4689/4982] [S390] remove duplicated #includes Remove duplicated #include's in arch/s390/kernel/ipl.c. Signed-off-by: Huang Weiyi Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/ipl.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 56d876904ec..6f3711a0eaa 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #define IPL_PARM_BLOCK_VERSION 0 -- GitLab From fc2869f6a1993550c2765e934b117e993782db30 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 13 Mar 2009 16:37:48 +0100 Subject: [PATCH 4690/4982] x86: disable __do_IRQ support Impact: disable unused code x86 is fully converted to flow handlers. No need to keep the deprecated __do_IRQ() support active. Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index bc2fbadff9f..3a330a437c6 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -165,6 +165,9 @@ config GENERIC_HARDIRQS bool default y +config GENERIC_HARDIRQS_NO__DO_IRQ + def_bool y + config GENERIC_IRQ_PROBE bool default y -- GitLab From 9d50638bae05ab7f62d700c9e4a83a1845cf9ef4 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sun, 8 Feb 2009 11:00:25 +0530 Subject: [PATCH 4691/4982] unconditionally include asm/types.h from linux/types.h Reported-by: Sam Ravnborg Signed-off-by: Jaswinder Singh Rajput Signed-off-by: Ingo Molnar --- include/linux/types.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/types.h b/include/linux/types.h index c30973ace89..fca82ed55f4 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -1,6 +1,8 @@ #ifndef _LINUX_TYPES_H #define _LINUX_TYPES_H +#include + #ifndef __ASSEMBLY__ #ifdef __KERNEL__ @@ -10,7 +12,6 @@ #endif #include -#include #ifndef __KERNEL_STRICT_NAMES -- GitLab From 85efde6f4e0de9577256c5f0030088d3fd4347c1 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 26 Feb 2009 00:51:39 +0100 Subject: [PATCH 4692/4982] make exported headers use strict posix types A number of standard posix types are used in exported headers, which is not allowed if __STRICT_KERNEL_NAMES is defined. In order to get rid of the non-__STRICT_KERNEL_NAMES part and to make sane headers the default, we have to change them all to safe types. There are also still some leftovers in reiserfs_fs.h, elfcore.h and coda.h, but these files have not compiled in user space for a long time. This leaves out the various integer types ({u_,u,}int{8,16,32,64}_t), which we take care of separately. Signed-off-by: Arnd Bergmann Acked-by: Mauro Carvalho Chehab Cc: David Airlie Cc: Arnaldo Carvalho de Melo Cc: YOSHIFUJI Hideaki Cc: netdev@vger.kernel.org Cc: linux-ppp@vger.kernel.org Cc: Jaroslav Kysela Cc: Takashi Iwai Cc: David Woodhouse Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- include/asm-generic/fcntl.h | 12 ++++++------ include/asm-generic/siginfo.h | 14 +++++++------- include/linux/agpgart.h | 14 +++++++------- include/linux/cn_proc.h | 20 ++++++++++---------- include/linux/cyclades.h | 6 +++--- include/linux/dvb/video.h | 2 +- include/linux/if_pppol2tp.h | 2 +- include/linux/mroute6.h | 2 +- include/linux/netfilter_ipv4/ipt_owner.h | 8 ++++---- include/linux/netfilter_ipv6/ip6t_owner.h | 8 ++++---- include/linux/ppp_defs.h | 4 ++-- include/linux/suspend_ioctls.h | 11 ++++++----- include/linux/time.h | 8 ++++---- include/linux/times.h | 8 ++++---- include/linux/utime.h | 4 ++-- include/linux/xfrm.h | 2 +- include/mtd/mtd-abi.h | 4 ++-- include/sound/asound.h | 4 ++-- 18 files changed, 67 insertions(+), 66 deletions(-) diff --git a/include/asm-generic/fcntl.h b/include/asm-generic/fcntl.h index b8477414c5c..4d3e48373e7 100644 --- a/include/asm-generic/fcntl.h +++ b/include/asm-generic/fcntl.h @@ -117,9 +117,9 @@ struct flock { short l_type; short l_whence; - off_t l_start; - off_t l_len; - pid_t l_pid; + __kernel_off_t l_start; + __kernel_off_t l_len; + __kernel_pid_t l_pid; __ARCH_FLOCK_PAD }; #endif @@ -140,9 +140,9 @@ struct flock { struct flock64 { short l_type; short l_whence; - loff_t l_start; - loff_t l_len; - pid_t l_pid; + __kernel_loff_t l_start; + __kernel_loff_t l_len; + __kernel_pid_t l_pid; __ARCH_FLOCK64_PAD }; #endif diff --git a/include/asm-generic/siginfo.h b/include/asm-generic/siginfo.h index 969570167e9..35752dadd6d 100644 --- a/include/asm-generic/siginfo.h +++ b/include/asm-generic/siginfo.h @@ -23,7 +23,7 @@ typedef union sigval { #endif #ifndef __ARCH_SI_UID_T -#define __ARCH_SI_UID_T uid_t +#define __ARCH_SI_UID_T __kernel_uid32_t #endif /* @@ -47,13 +47,13 @@ typedef struct siginfo { /* kill() */ struct { - pid_t _pid; /* sender's pid */ + __kernel_pid_t _pid; /* sender's pid */ __ARCH_SI_UID_T _uid; /* sender's uid */ } _kill; /* POSIX.1b timers */ struct { - timer_t _tid; /* timer id */ + __kernel_timer_t _tid; /* timer id */ int _overrun; /* overrun count */ char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)]; sigval_t _sigval; /* same as below */ @@ -62,18 +62,18 @@ typedef struct siginfo { /* POSIX.1b signals */ struct { - pid_t _pid; /* sender's pid */ + __kernel_pid_t _pid; /* sender's pid */ __ARCH_SI_UID_T _uid; /* sender's uid */ sigval_t _sigval; } _rt; /* SIGCHLD */ struct { - pid_t _pid; /* which child */ + __kernel_pid_t _pid; /* which child */ __ARCH_SI_UID_T _uid; /* sender's uid */ int _status; /* exit code */ - clock_t _utime; - clock_t _stime; + __kernel_clock_t _utime; + __kernel_clock_t _stime; } _sigchld; /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ diff --git a/include/linux/agpgart.h b/include/linux/agpgart.h index 110c600c885..f6778eceb8f 100644 --- a/include/linux/agpgart.h +++ b/include/linux/agpgart.h @@ -77,20 +77,20 @@ typedef struct _agp_setup { * The "prot" down below needs still a "sleep" flag somehow ... */ typedef struct _agp_segment { - off_t pg_start; /* starting page to populate */ - size_t pg_count; /* number of pages */ - int prot; /* prot flags for mmap */ + __kernel_off_t pg_start; /* starting page to populate */ + __kernel_size_t pg_count; /* number of pages */ + int prot; /* prot flags for mmap */ } agp_segment; typedef struct _agp_region { - pid_t pid; /* pid of process */ - size_t seg_count; /* number of segments */ + __kernel_pid_t pid; /* pid of process */ + __kernel_size_t seg_count; /* number of segments */ struct _agp_segment *seg_list; } agp_region; typedef struct _agp_allocate { int key; /* tag of allocation */ - size_t pg_count; /* number of pages */ + __kernel_size_t pg_count;/* number of pages */ __u32 type; /* 0 == normal, other devspec */ __u32 physical; /* device specific (some devices * need a phys address of the @@ -100,7 +100,7 @@ typedef struct _agp_allocate { typedef struct _agp_bind { int key; /* tag of allocation */ - off_t pg_start; /* starting page to populate */ + __kernel_off_t pg_start;/* starting page to populate */ } agp_bind; typedef struct _agp_unbind { diff --git a/include/linux/cn_proc.h b/include/linux/cn_proc.h index 1c86d65bc4b..b8125b2eb66 100644 --- a/include/linux/cn_proc.h +++ b/include/linux/cn_proc.h @@ -65,20 +65,20 @@ struct proc_event { } ack; struct fork_proc_event { - pid_t parent_pid; - pid_t parent_tgid; - pid_t child_pid; - pid_t child_tgid; + __kernel_pid_t parent_pid; + __kernel_pid_t parent_tgid; + __kernel_pid_t child_pid; + __kernel_pid_t child_tgid; } fork; struct exec_proc_event { - pid_t process_pid; - pid_t process_tgid; + __kernel_pid_t process_pid; + __kernel_pid_t process_tgid; } exec; struct id_proc_event { - pid_t process_pid; - pid_t process_tgid; + __kernel_pid_t process_pid; + __kernel_pid_t process_tgid; union { __u32 ruid; /* task uid */ __u32 rgid; /* task gid */ @@ -90,8 +90,8 @@ struct proc_event { } id; struct exit_proc_event { - pid_t process_pid; - pid_t process_tgid; + __kernel_pid_t process_pid; + __kernel_pid_t process_tgid; __u32 exit_code, exit_signal; } exit; } event_data; diff --git a/include/linux/cyclades.h b/include/linux/cyclades.h index d06fbf28634..788850ba4e7 100644 --- a/include/linux/cyclades.h +++ b/include/linux/cyclades.h @@ -82,9 +82,9 @@ struct cyclades_monitor { * open) */ struct cyclades_idle_stats { - time_t in_use; /* Time device has been in use (secs) */ - time_t recv_idle; /* Time since last char received (secs) */ - time_t xmit_idle; /* Time since last char transmitted (secs) */ + __kernel_time_t in_use; /* Time device has been in use (secs) */ + __kernel_time_t recv_idle; /* Time since last char received (secs) */ + __kernel_time_t xmit_idle; /* Time since last char transmitted (secs) */ unsigned long recv_bytes; /* Bytes received */ unsigned long xmit_bytes; /* Bytes transmitted */ unsigned long overruns; /* Input overruns */ diff --git a/include/linux/dvb/video.h b/include/linux/dvb/video.h index bd49c3ebf91..ee5d2df2d78 100644 --- a/include/linux/dvb/video.h +++ b/include/linux/dvb/video.h @@ -137,7 +137,7 @@ struct video_event { #define VIDEO_EVENT_FRAME_RATE_CHANGED 2 #define VIDEO_EVENT_DECODER_STOPPED 3 #define VIDEO_EVENT_VSYNC 4 - time_t timestamp; + __kernel_time_t timestamp; union { video_size_t size; unsigned int frame_rate; /* in frames per 1000sec */ diff --git a/include/linux/if_pppol2tp.h b/include/linux/if_pppol2tp.h index c7a66882b6d..3a14b088c8e 100644 --- a/include/linux/if_pppol2tp.h +++ b/include/linux/if_pppol2tp.h @@ -26,7 +26,7 @@ */ struct pppol2tp_addr { - pid_t pid; /* pid that owns the fd. + __kernel_pid_t pid; /* pid that owns the fd. * 0 => current */ int fd; /* FD of UDP socket to use */ diff --git a/include/linux/mroute6.h b/include/linux/mroute6.h index 5375faca1f7..43dc97e3218 100644 --- a/include/linux/mroute6.h +++ b/include/linux/mroute6.h @@ -65,7 +65,7 @@ struct mif6ctl { mifi_t mif6c_mifi; /* Index of MIF */ unsigned char mif6c_flags; /* MIFF_ flags */ unsigned char vifc_threshold; /* ttl limit */ - u_short mif6c_pifi; /* the index of the physical IF */ + __u16 mif6c_pifi; /* the index of the physical IF */ unsigned int vifc_rate_limit; /* Rate limiter values (NI) */ }; diff --git a/include/linux/netfilter_ipv4/ipt_owner.h b/include/linux/netfilter_ipv4/ipt_owner.h index 92f4bdac54e..a78445be999 100644 --- a/include/linux/netfilter_ipv4/ipt_owner.h +++ b/include/linux/netfilter_ipv4/ipt_owner.h @@ -9,10 +9,10 @@ #define IPT_OWNER_COMM 0x10 struct ipt_owner_info { - uid_t uid; - gid_t gid; - pid_t pid; - pid_t sid; + __kernel_uid32_t uid; + __kernel_gid32_t gid; + __kernel_pid_t pid; + __kernel_pid_t sid; char comm[16]; u_int8_t match, invert; /* flags */ }; diff --git a/include/linux/netfilter_ipv6/ip6t_owner.h b/include/linux/netfilter_ipv6/ip6t_owner.h index 19937da3d10..ec5cc7a38c4 100644 --- a/include/linux/netfilter_ipv6/ip6t_owner.h +++ b/include/linux/netfilter_ipv6/ip6t_owner.h @@ -8,10 +8,10 @@ #define IP6T_OWNER_SID 0x08 struct ip6t_owner_info { - uid_t uid; - gid_t gid; - pid_t pid; - pid_t sid; + __kernel_uid32_t uid; + __kernel_gid32_t gid; + __kernel_pid_t pid; + __kernel_pid_t sid; u_int8_t match, invert; /* flags */ }; diff --git a/include/linux/ppp_defs.h b/include/linux/ppp_defs.h index 1c866bda201..0f93ed6b4a8 100644 --- a/include/linux/ppp_defs.h +++ b/include/linux/ppp_defs.h @@ -177,8 +177,8 @@ struct ppp_comp_stats { * the last NP packet was sent or received. */ struct ppp_idle { - time_t xmit_idle; /* time since last NP packet sent */ - time_t recv_idle; /* time since last NP packet received */ + __kernel_time_t xmit_idle; /* time since last NP packet sent */ + __kernel_time_t recv_idle; /* time since last NP packet received */ }; #endif /* _PPP_DEFS_H_ */ diff --git a/include/linux/suspend_ioctls.h b/include/linux/suspend_ioctls.h index 2c6faec96bd..0b30382984f 100644 --- a/include/linux/suspend_ioctls.h +++ b/include/linux/suspend_ioctls.h @@ -1,14 +1,15 @@ #ifndef _LINUX_SUSPEND_IOCTLS_H #define _LINUX_SUSPEND_IOCTLS_H +#include /* * This structure is used to pass the values needed for the identification * of the resume swap area from a user space to the kernel via the * SNAPSHOT_SET_SWAP_AREA ioctl */ struct resume_swap_area { - loff_t offset; - u_int32_t dev; + __kernel_loff_t offset; + __u32 dev; } __attribute__((packed)); #define SNAPSHOT_IOC_MAGIC '3' @@ -20,13 +21,13 @@ struct resume_swap_area { #define SNAPSHOT_S2RAM _IO(SNAPSHOT_IOC_MAGIC, 11) #define SNAPSHOT_SET_SWAP_AREA _IOW(SNAPSHOT_IOC_MAGIC, 13, \ struct resume_swap_area) -#define SNAPSHOT_GET_IMAGE_SIZE _IOR(SNAPSHOT_IOC_MAGIC, 14, loff_t) +#define SNAPSHOT_GET_IMAGE_SIZE _IOR(SNAPSHOT_IOC_MAGIC, 14, __kernel_loff_t) #define SNAPSHOT_PLATFORM_SUPPORT _IO(SNAPSHOT_IOC_MAGIC, 15) #define SNAPSHOT_POWER_OFF _IO(SNAPSHOT_IOC_MAGIC, 16) #define SNAPSHOT_CREATE_IMAGE _IOW(SNAPSHOT_IOC_MAGIC, 17, int) #define SNAPSHOT_PREF_IMAGE_SIZE _IO(SNAPSHOT_IOC_MAGIC, 18) -#define SNAPSHOT_AVAIL_SWAP_SIZE _IOR(SNAPSHOT_IOC_MAGIC, 19, loff_t) -#define SNAPSHOT_ALLOC_SWAP_PAGE _IOR(SNAPSHOT_IOC_MAGIC, 20, loff_t) +#define SNAPSHOT_AVAIL_SWAP_SIZE _IOR(SNAPSHOT_IOC_MAGIC, 19, __kernel_loff_t) +#define SNAPSHOT_ALLOC_SWAP_PAGE _IOR(SNAPSHOT_IOC_MAGIC, 20, __kernel_loff_t) #define SNAPSHOT_IOC_MAXNR 20 #endif /* _LINUX_SUSPEND_IOCTLS_H */ diff --git a/include/linux/time.h b/include/linux/time.h index fbbd2a1c92b..242f62499bb 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -12,14 +12,14 @@ #ifndef _STRUCT_TIMESPEC #define _STRUCT_TIMESPEC struct timespec { - time_t tv_sec; /* seconds */ - long tv_nsec; /* nanoseconds */ + __kernel_time_t tv_sec; /* seconds */ + long tv_nsec; /* nanoseconds */ }; #endif struct timeval { - time_t tv_sec; /* seconds */ - suseconds_t tv_usec; /* microseconds */ + __kernel_time_t tv_sec; /* seconds */ + __kernel_suseconds_t tv_usec; /* microseconds */ }; struct timezone { diff --git a/include/linux/times.h b/include/linux/times.h index e2d3020742a..87b62615ced 100644 --- a/include/linux/times.h +++ b/include/linux/times.h @@ -4,10 +4,10 @@ #include struct tms { - clock_t tms_utime; - clock_t tms_stime; - clock_t tms_cutime; - clock_t tms_cstime; + __kernel_clock_t tms_utime; + __kernel_clock_t tms_stime; + __kernel_clock_t tms_cutime; + __kernel_clock_t tms_cstime; }; #endif diff --git a/include/linux/utime.h b/include/linux/utime.h index 640be6a1959..5cdf673afbd 100644 --- a/include/linux/utime.h +++ b/include/linux/utime.h @@ -4,8 +4,8 @@ #include struct utimbuf { - time_t actime; - time_t modtime; + __kernel_time_t actime; + __kernel_time_t modtime; }; #endif diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index 52f3abd453a..2d4ec15abac 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h @@ -58,7 +58,7 @@ struct xfrm_selector __u8 prefixlen_s; __u8 proto; int ifindex; - uid_t user; + __kernel_uid32_t user; }; #define XFRM_INF (~(__u64)0) diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h index c6c61cd5a25..fb672013299 100644 --- a/include/mtd/mtd-abi.h +++ b/include/mtd/mtd-abi.h @@ -84,8 +84,8 @@ struct otp_info { #define MEMGETREGIONINFO _IOWR('M', 8, struct region_info_user) #define MEMSETOOBSEL _IOW('M', 9, struct nand_oobinfo) #define MEMGETOOBSEL _IOR('M', 10, struct nand_oobinfo) -#define MEMGETBADBLOCK _IOW('M', 11, loff_t) -#define MEMSETBADBLOCK _IOW('M', 12, loff_t) +#define MEMGETBADBLOCK _IOW('M', 11, __kernel_loff_t) +#define MEMSETBADBLOCK _IOW('M', 12, __kernel_loff_t) #define OTPSELECT _IOR('M', 13, int) #define OTPGETREGIONCOUNT _IOW('M', 14, int) #define OTPGETREGIONINFO _IOW('M', 15, struct otp_info) diff --git a/include/sound/asound.h b/include/sound/asound.h index 1c02ed1d7c4..16684c5a608 100644 --- a/include/sound/asound.h +++ b/include/sound/asound.h @@ -385,7 +385,7 @@ struct snd_pcm_sw_params { struct snd_pcm_channel_info { unsigned int channel; - off_t offset; /* mmap offset */ + __kernel_off_t offset; /* mmap offset */ unsigned int first; /* offset to first sample in bits */ unsigned int step; /* samples distance in bits */ }; @@ -789,7 +789,7 @@ struct snd_ctl_elem_info { snd_ctl_elem_type_t type; /* R: value type - SNDRV_CTL_ELEM_TYPE_* */ unsigned int access; /* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */ unsigned int count; /* count of values */ - pid_t owner; /* owner's PID of this control */ + __kernel_pid_t owner; /* owner's PID of this control */ union { struct { long min; /* R: minimum value */ -- GitLab From 9adfbfb611307060db54691bc7e6d53fdc12312b Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 26 Feb 2009 00:51:40 +0100 Subject: [PATCH 4693/4982] make most exported headers use strict integer types This takes care of all files that have only a small number of non-strict integer type uses. Signed-off-by: Arnd Bergmann Cc: Mauro Carvalho Chehab Cc: David Airlie Cc: Arnaldo Carvalho de Melo Cc: YOSHIFUJI Hideaki Cc: netdev@vger.kernel.org Cc: linux-ppp@vger.kernel.org Cc: Jaroslav Kysela Cc: Takashi Iwai Cc: David Woodhouse Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- include/linux/atmlec.h | 5 +- include/linux/atmmpc.h | 45 +++--- include/linux/cm4000_cs.h | 10 +- include/linux/dlm_netlink.h | 18 +-- include/linux/dm-ioctl.h | 42 +++--- include/linux/dvb/audio.h | 2 +- include/linux/dvb/video.h | 22 +-- include/linux/if_arcnet.h | 27 ++-- include/linux/ip_vs.h | 26 ++-- include/linux/ivtvfb.h | 2 +- include/linux/matroxfb.h | 2 +- include/linux/pfkeyv2.h | 242 ++++++++++++++++---------------- include/linux/selinux_netlink.h | 6 +- include/sound/asound.h | 5 +- include/sound/emu10k1.h | 12 +- 15 files changed, 240 insertions(+), 226 deletions(-) diff --git a/include/linux/atmlec.h b/include/linux/atmlec.h index 6f5a1bab8f5..39c917fd1b9 100644 --- a/include/linux/atmlec.h +++ b/include/linux/atmlec.h @@ -11,6 +11,7 @@ #include #include #include +#include /* ATM lec daemon control socket */ #define ATMLEC_CTRL _IO('a', ATMIOC_LANE) @@ -78,8 +79,8 @@ struct atmlec_msg { } normal; struct atmlec_config_msg config; struct { - uint16_t lec_id; /* requestor lec_id */ - uint32_t tran_id; /* transaction id */ + __u16 lec_id; /* requestor lec_id */ + __u32 tran_id; /* transaction id */ unsigned char mac_addr[ETH_ALEN]; /* dst mac addr */ unsigned char atm_addr[ATM_ESA_LEN]; /* reqestor ATM addr */ } proxy; /* diff --git a/include/linux/atmmpc.h b/include/linux/atmmpc.h index ea1650425a1..2aba5787fa6 100644 --- a/include/linux/atmmpc.h +++ b/include/linux/atmmpc.h @@ -4,6 +4,7 @@ #include #include #include +#include #define ATMMPC_CTRL _IO('a', ATMIOC_MPOA) #define ATMMPC_DATA _IO('a', ATMIOC_MPOA+1) @@ -18,39 +19,39 @@ struct atmmpc_ioc { }; typedef struct in_ctrl_info { - uint8_t Last_NHRP_CIE_code; - uint8_t Last_Q2931_cause_value; - uint8_t eg_MPC_ATM_addr[ATM_ESA_LEN]; + __u8 Last_NHRP_CIE_code; + __u8 Last_Q2931_cause_value; + __u8 eg_MPC_ATM_addr[ATM_ESA_LEN]; __be32 tag; __be32 in_dst_ip; /* IP address this ingress MPC sends packets to */ - uint16_t holding_time; - uint32_t request_id; + __u16 holding_time; + __u32 request_id; } in_ctrl_info; typedef struct eg_ctrl_info { - uint8_t DLL_header[256]; - uint8_t DH_length; + __u8 DLL_header[256]; + __u8 DH_length; __be32 cache_id; __be32 tag; __be32 mps_ip; __be32 eg_dst_ip; /* IP address to which ingress MPC sends packets */ - uint8_t in_MPC_data_ATM_addr[ATM_ESA_LEN]; - uint16_t holding_time; + __u8 in_MPC_data_ATM_addr[ATM_ESA_LEN]; + __u16 holding_time; } eg_ctrl_info; struct mpc_parameters { - uint16_t mpc_p1; /* Shortcut-Setup Frame Count */ - uint16_t mpc_p2; /* Shortcut-Setup Frame Time */ - uint8_t mpc_p3[8]; /* Flow-detection Protocols */ - uint16_t mpc_p4; /* MPC Initial Retry Time */ - uint16_t mpc_p5; /* MPC Retry Time Maximum */ - uint16_t mpc_p6; /* Hold Down Time */ + __u16 mpc_p1; /* Shortcut-Setup Frame Count */ + __u16 mpc_p2; /* Shortcut-Setup Frame Time */ + __u8 mpc_p3[8]; /* Flow-detection Protocols */ + __u16 mpc_p4; /* MPC Initial Retry Time */ + __u16 mpc_p5; /* MPC Retry Time Maximum */ + __u16 mpc_p6; /* Hold Down Time */ } ; struct k_message { - uint16_t type; + __u16 type; __be32 ip_mask; - uint8_t MPS_ctrl[ATM_ESA_LEN]; + __u8 MPS_ctrl[ATM_ESA_LEN]; union { in_ctrl_info in_info; eg_ctrl_info eg_info; @@ -61,11 +62,11 @@ struct k_message { struct llc_snap_hdr { /* RFC 1483 LLC/SNAP encapsulation for routed IP PDUs */ - uint8_t dsap; /* Destination Service Access Point (0xAA) */ - uint8_t ssap; /* Source Service Access Point (0xAA) */ - uint8_t ui; /* Unnumbered Information (0x03) */ - uint8_t org[3]; /* Organizational identification (0x000000) */ - uint8_t type[2]; /* Ether type (for IP) (0x0800) */ + __u8 dsap; /* Destination Service Access Point (0xAA) */ + __u8 ssap; /* Source Service Access Point (0xAA) */ + __u8 ui; /* Unnumbered Information (0x03) */ + __u8 org[3]; /* Organizational identification (0x000000) */ + __u8 type[2]; /* Ether type (for IP) (0x0800) */ }; /* TLVs this MPC recognizes */ diff --git a/include/linux/cm4000_cs.h b/include/linux/cm4000_cs.h index 605ebe24bb2..72bfefdbd76 100644 --- a/include/linux/cm4000_cs.h +++ b/include/linux/cm4000_cs.h @@ -1,6 +1,8 @@ #ifndef _CM4000_H_ #define _CM4000_H_ +#include + #define MAX_ATR 33 #define CM4000_MAX_DEV 4 @@ -10,9 +12,9 @@ * not to break compilation of userspace apps. -HW */ typedef struct atreq { - int32_t atr_len; + __s32 atr_len; unsigned char atr[64]; - int32_t power_act; + __s32 power_act; unsigned char bIFSD; unsigned char bIFSC; } atreq_t; @@ -22,13 +24,13 @@ typedef struct atreq { * member sizes. This leads to CONFIG_COMPAT breakage, since 32bit userspace * will lay out the structure members differently than the 64bit kernel. * - * I've changed "ptsreq.protocol" from "unsigned long" to "u_int32_t". + * I've changed "ptsreq.protocol" from "unsigned long" to "__u32". * On 32bit this will make no difference. With 64bit kernels, it will make * 32bit apps work, too. */ typedef struct ptsreq { - u_int32_t protocol; /*T=0: 2^0, T=1: 2^1*/ + __u32 protocol; /*T=0: 2^0, T=1: 2^1*/ unsigned char flags; unsigned char pts1; unsigned char pts2; diff --git a/include/linux/dlm_netlink.h b/include/linux/dlm_netlink.h index 19276332707..647c8ef2722 100644 --- a/include/linux/dlm_netlink.h +++ b/include/linux/dlm_netlink.h @@ -9,6 +9,8 @@ #ifndef _DLM_NETLINK_H #define _DLM_NETLINK_H +#include + enum { DLM_STATUS_WAITING = 1, DLM_STATUS_GRANTED = 2, @@ -18,16 +20,16 @@ enum { #define DLM_LOCK_DATA_VERSION 1 struct dlm_lock_data { - uint16_t version; - uint32_t lockspace_id; + __u16 version; + __u32 lockspace_id; int nodeid; int ownpid; - uint32_t id; - uint32_t remid; - uint64_t xid; - int8_t status; - int8_t grmode; - int8_t rqmode; + __u32 id; + __u32 remid; + __u64 xid; + __s8 status; + __s8 grmode; + __s8 rqmode; unsigned long timestamp; int resource_namelen; char resource_name[DLM_RESNAME_MAXLEN]; diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h index 28c2940eb30..48e44ee2b46 100644 --- a/include/linux/dm-ioctl.h +++ b/include/linux/dm-ioctl.h @@ -113,20 +113,20 @@ struct dm_ioctl { * return -ENOTTY) fill out this field, even if the * command failed. */ - uint32_t version[3]; /* in/out */ - uint32_t data_size; /* total size of data passed in + __u32 version[3]; /* in/out */ + __u32 data_size; /* total size of data passed in * including this struct */ - uint32_t data_start; /* offset to start of data + __u32 data_start; /* offset to start of data * relative to start of this struct */ - uint32_t target_count; /* in/out */ - int32_t open_count; /* out */ - uint32_t flags; /* in/out */ - uint32_t event_nr; /* in/out */ - uint32_t padding; + __u32 target_count; /* in/out */ + __s32 open_count; /* out */ + __u32 flags; /* in/out */ + __u32 event_nr; /* in/out */ + __u32 padding; - uint64_t dev; /* in/out */ + __u64 dev; /* in/out */ char name[DM_NAME_LEN]; /* device name */ char uuid[DM_UUID_LEN]; /* unique identifier for @@ -139,9 +139,9 @@ struct dm_ioctl { * dm_ioctl. */ struct dm_target_spec { - uint64_t sector_start; - uint64_t length; - int32_t status; /* used when reading from kernel only */ + __u64 sector_start; + __u64 length; + __s32 status; /* used when reading from kernel only */ /* * Location of the next dm_target_spec. @@ -153,7 +153,7 @@ struct dm_target_spec { * (that follows the dm_ioctl struct) to the start of the "next" * dm_target_spec. */ - uint32_t next; + __u32 next; char target_type[DM_MAX_TYPE_NAME]; @@ -168,17 +168,17 @@ struct dm_target_spec { * Used to retrieve the target dependencies. */ struct dm_target_deps { - uint32_t count; /* Array size */ - uint32_t padding; /* unused */ - uint64_t dev[0]; /* out */ + __u32 count; /* Array size */ + __u32 padding; /* unused */ + __u64 dev[0]; /* out */ }; /* * Used to get a list of all dm devices. */ struct dm_name_list { - uint64_t dev; - uint32_t next; /* offset to the next record from + __u64 dev; + __u32 next; /* offset to the next record from the _start_ of this */ char name[0]; }; @@ -187,8 +187,8 @@ struct dm_name_list { * Used to retrieve the target versions */ struct dm_target_versions { - uint32_t next; - uint32_t version[3]; + __u32 next; + __u32 version[3]; char name[0]; }; @@ -197,7 +197,7 @@ struct dm_target_versions { * Used to pass message to a target */ struct dm_target_msg { - uint64_t sector; /* Device sector */ + __u64 sector; /* Device sector */ char message[0]; }; diff --git a/include/linux/dvb/audio.h b/include/linux/dvb/audio.h index bb0df2aaebf..fec66bd24f2 100644 --- a/include/linux/dvb/audio.h +++ b/include/linux/dvb/audio.h @@ -76,7 +76,7 @@ struct audio_karaoke{ /* if Vocal1 or Vocal2 are non-zero, they get mixed */ } audio_karaoke_t; /* into left and right */ -typedef uint16_t audio_attributes_t; +typedef __u16 audio_attributes_t; /* bits: descr. */ /* 15-13 audio coding mode (0=ac3, 2=mpeg1, 3=mpeg2ext, 4=LPCM, 6=DTS, */ /* 12 multichannel extension */ diff --git a/include/linux/dvb/video.h b/include/linux/dvb/video.h index ee5d2df2d78..1d750c0fd86 100644 --- a/include/linux/dvb/video.h +++ b/include/linux/dvb/video.h @@ -132,7 +132,7 @@ struct video_command { #define VIDEO_VSYNC_FIELD_PROGRESSIVE (3) struct video_event { - int32_t type; + __s32 type; #define VIDEO_EVENT_SIZE_CHANGED 1 #define VIDEO_EVENT_FRAME_RATE_CHANGED 2 #define VIDEO_EVENT_DECODER_STOPPED 3 @@ -157,25 +157,25 @@ struct video_status { struct video_still_picture { char __user *iFrame; /* pointer to a single iframe in memory */ - int32_t size; + __s32 size; }; typedef struct video_highlight { int active; /* 1=show highlight, 0=hide highlight */ - uint8_t contrast1; /* 7- 4 Pattern pixel contrast */ + __u8 contrast1; /* 7- 4 Pattern pixel contrast */ /* 3- 0 Background pixel contrast */ - uint8_t contrast2; /* 7- 4 Emphasis pixel-2 contrast */ + __u8 contrast2; /* 7- 4 Emphasis pixel-2 contrast */ /* 3- 0 Emphasis pixel-1 contrast */ - uint8_t color1; /* 7- 4 Pattern pixel color */ + __u8 color1; /* 7- 4 Pattern pixel color */ /* 3- 0 Background pixel color */ - uint8_t color2; /* 7- 4 Emphasis pixel-2 color */ + __u8 color2; /* 7- 4 Emphasis pixel-2 color */ /* 3- 0 Emphasis pixel-1 color */ - uint32_t ypos; /* 23-22 auto action mode */ + __u32 ypos; /* 23-22 auto action mode */ /* 21-12 start y */ /* 9- 0 end y */ - uint32_t xpos; /* 23-22 button color number */ + __u32 xpos; /* 23-22 button color number */ /* 21-12 start x */ /* 9- 0 end x */ } video_highlight_t; @@ -189,17 +189,17 @@ typedef struct video_spu { typedef struct video_spu_palette { /* SPU Palette information */ int length; - uint8_t __user *palette; + __u8 __user *palette; } video_spu_palette_t; typedef struct video_navi_pack { int length; /* 0 ... 1024 */ - uint8_t data[1024]; + __u8 data[1024]; } video_navi_pack_t; -typedef uint16_t video_attributes_t; +typedef __u16 video_attributes_t; /* bits: descr. */ /* 15-14 Video compression mode (0=MPEG-1, 1=MPEG-2) */ /* 13-12 TV system (0=525/60, 1=625/50) */ diff --git a/include/linux/if_arcnet.h b/include/linux/if_arcnet.h index 27ea2ac445a..0835debab11 100644 --- a/include/linux/if_arcnet.h +++ b/include/linux/if_arcnet.h @@ -16,6 +16,7 @@ #ifndef _LINUX_IF_ARCNET_H #define _LINUX_IF_ARCNET_H +#include #include @@ -57,10 +58,10 @@ */ struct arc_rfc1201 { - uint8_t proto; /* protocol ID field - varies */ - uint8_t split_flag; /* for use with split packets */ + __u8 proto; /* protocol ID field - varies */ + __u8 split_flag; /* for use with split packets */ __be16 sequence; /* sequence number */ - uint8_t payload[0]; /* space remaining in packet (504 bytes)*/ + __u8 payload[0]; /* space remaining in packet (504 bytes)*/ }; #define RFC1201_HDR_SIZE 4 @@ -70,8 +71,8 @@ struct arc_rfc1201 */ struct arc_rfc1051 { - uint8_t proto; /* ARC_P_RFC1051_ARP/RFC1051_IP */ - uint8_t payload[0]; /* 507 bytes */ + __u8 proto; /* ARC_P_RFC1051_ARP/RFC1051_IP */ + __u8 payload[0]; /* 507 bytes */ }; #define RFC1051_HDR_SIZE 1 @@ -82,20 +83,20 @@ struct arc_rfc1051 */ struct arc_eth_encap { - uint8_t proto; /* Always ARC_P_ETHER */ + __u8 proto; /* Always ARC_P_ETHER */ struct ethhdr eth; /* standard ethernet header (yuck!) */ - uint8_t payload[0]; /* 493 bytes */ + __u8 payload[0]; /* 493 bytes */ }; #define ETH_ENCAP_HDR_SIZE 14 struct arc_cap { - uint8_t proto; - uint8_t cookie[sizeof(int)]; /* Actually NOT sent over the network */ + __u8 proto; + __u8 cookie[sizeof(int)]; /* Actually NOT sent over the network */ union { - uint8_t ack; - uint8_t raw[0]; /* 507 bytes */ + __u8 ack; + __u8 raw[0]; /* 507 bytes */ } mes; }; @@ -109,7 +110,7 @@ struct arc_cap */ struct arc_hardware { - uint8_t source, /* source ARCnet - filled in automagically */ + __u8 source, /* source ARCnet - filled in automagically */ dest, /* destination ARCnet - 0 for broadcast */ offset[2]; /* offset bytes (some weird semantics) */ }; @@ -130,7 +131,7 @@ struct archdr struct arc_rfc1051 rfc1051; struct arc_eth_encap eth_encap; struct arc_cap cap; - uint8_t raw[0]; /* 508 bytes */ + __u8 raw[0]; /* 508 bytes */ } soft; }; diff --git a/include/linux/ip_vs.h b/include/linux/ip_vs.h index 0f434a28fb5..148265e63e8 100644 --- a/include/linux/ip_vs.h +++ b/include/linux/ip_vs.h @@ -96,10 +96,10 @@ */ struct ip_vs_service_user { /* virtual service addresses */ - u_int16_t protocol; + __u16 protocol; __be32 addr; /* virtual ip address */ __be16 port; - u_int32_t fwmark; /* firwall mark of service */ + __u32 fwmark; /* firwall mark of service */ /* virtual service options */ char sched_name[IP_VS_SCHEDNAME_MAXLEN]; @@ -119,8 +119,8 @@ struct ip_vs_dest_user { int weight; /* destination weight */ /* thresholds for active connections */ - u_int32_t u_threshold; /* upper threshold */ - u_int32_t l_threshold; /* lower threshold */ + __u32 u_threshold; /* upper threshold */ + __u32 l_threshold; /* lower threshold */ }; @@ -159,10 +159,10 @@ struct ip_vs_getinfo { /* The argument to IP_VS_SO_GET_SERVICE */ struct ip_vs_service_entry { /* which service: user fills in these */ - u_int16_t protocol; + __u16 protocol; __be32 addr; /* virtual address */ __be16 port; - u_int32_t fwmark; /* firwall mark of service */ + __u32 fwmark; /* firwall mark of service */ /* service options */ char sched_name[IP_VS_SCHEDNAME_MAXLEN]; @@ -184,12 +184,12 @@ struct ip_vs_dest_entry { unsigned conn_flags; /* connection flags */ int weight; /* destination weight */ - u_int32_t u_threshold; /* upper threshold */ - u_int32_t l_threshold; /* lower threshold */ + __u32 u_threshold; /* upper threshold */ + __u32 l_threshold; /* lower threshold */ - u_int32_t activeconns; /* active connections */ - u_int32_t inactconns; /* inactive connections */ - u_int32_t persistconns; /* persistent connections */ + __u32 activeconns; /* active connections */ + __u32 inactconns; /* inactive connections */ + __u32 persistconns; /* persistent connections */ /* statistics */ struct ip_vs_stats_user stats; @@ -199,10 +199,10 @@ struct ip_vs_dest_entry { /* The argument to IP_VS_SO_GET_DESTS */ struct ip_vs_get_dests { /* which service: user fills in these */ - u_int16_t protocol; + __u16 protocol; __be32 addr; /* virtual address */ __be16 port; - u_int32_t fwmark; /* firwall mark of service */ + __u32 fwmark; /* firwall mark of service */ /* number of real servers */ unsigned int num_dests; diff --git a/include/linux/ivtvfb.h b/include/linux/ivtvfb.h index e20af47b59a..9d88b29ddf5 100644 --- a/include/linux/ivtvfb.h +++ b/include/linux/ivtvfb.h @@ -33,6 +33,6 @@ struct ivtvfb_dma_frame { }; #define IVTVFB_IOC_DMA_FRAME _IOW('V', BASE_VIDIOC_PRIVATE+0, struct ivtvfb_dma_frame) -#define FBIO_WAITFORVSYNC _IOW('F', 0x20, u_int32_t) +#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) #endif diff --git a/include/linux/matroxfb.h b/include/linux/matroxfb.h index 404f678e734..2203121a43e 100644 --- a/include/linux/matroxfb.h +++ b/include/linux/matroxfb.h @@ -37,7 +37,7 @@ enum matroxfb_ctrl_id { MATROXFB_CID_LAST }; -#define FBIO_WAITFORVSYNC _IOW('F', 0x20, u_int32_t) +#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) #endif diff --git a/include/linux/pfkeyv2.h b/include/linux/pfkeyv2.h index 01b262959f2..228b0b6306b 100644 --- a/include/linux/pfkeyv2.h +++ b/include/linux/pfkeyv2.h @@ -12,187 +12,187 @@ #define PFKEYV2_REVISION 199806L struct sadb_msg { - uint8_t sadb_msg_version; - uint8_t sadb_msg_type; - uint8_t sadb_msg_errno; - uint8_t sadb_msg_satype; - uint16_t sadb_msg_len; - uint16_t sadb_msg_reserved; - uint32_t sadb_msg_seq; - uint32_t sadb_msg_pid; + __u8 sadb_msg_version; + __u8 sadb_msg_type; + __u8 sadb_msg_errno; + __u8 sadb_msg_satype; + __u16 sadb_msg_len; + __u16 sadb_msg_reserved; + __u32 sadb_msg_seq; + __u32 sadb_msg_pid; } __attribute__((packed)); /* sizeof(struct sadb_msg) == 16 */ struct sadb_ext { - uint16_t sadb_ext_len; - uint16_t sadb_ext_type; + __u16 sadb_ext_len; + __u16 sadb_ext_type; } __attribute__((packed)); /* sizeof(struct sadb_ext) == 4 */ struct sadb_sa { - uint16_t sadb_sa_len; - uint16_t sadb_sa_exttype; + __u16 sadb_sa_len; + __u16 sadb_sa_exttype; __be32 sadb_sa_spi; - uint8_t sadb_sa_replay; - uint8_t sadb_sa_state; - uint8_t sadb_sa_auth; - uint8_t sadb_sa_encrypt; - uint32_t sadb_sa_flags; + __u8 sadb_sa_replay; + __u8 sadb_sa_state; + __u8 sadb_sa_auth; + __u8 sadb_sa_encrypt; + __u32 sadb_sa_flags; } __attribute__((packed)); /* sizeof(struct sadb_sa) == 16 */ struct sadb_lifetime { - uint16_t sadb_lifetime_len; - uint16_t sadb_lifetime_exttype; - uint32_t sadb_lifetime_allocations; - uint64_t sadb_lifetime_bytes; - uint64_t sadb_lifetime_addtime; - uint64_t sadb_lifetime_usetime; + __u16 sadb_lifetime_len; + __u16 sadb_lifetime_exttype; + __u32 sadb_lifetime_allocations; + __u64 sadb_lifetime_bytes; + __u64 sadb_lifetime_addtime; + __u64 sadb_lifetime_usetime; } __attribute__((packed)); /* sizeof(struct sadb_lifetime) == 32 */ struct sadb_address { - uint16_t sadb_address_len; - uint16_t sadb_address_exttype; - uint8_t sadb_address_proto; - uint8_t sadb_address_prefixlen; - uint16_t sadb_address_reserved; + __u16 sadb_address_len; + __u16 sadb_address_exttype; + __u8 sadb_address_proto; + __u8 sadb_address_prefixlen; + __u16 sadb_address_reserved; } __attribute__((packed)); /* sizeof(struct sadb_address) == 8 */ struct sadb_key { - uint16_t sadb_key_len; - uint16_t sadb_key_exttype; - uint16_t sadb_key_bits; - uint16_t sadb_key_reserved; + __u16 sadb_key_len; + __u16 sadb_key_exttype; + __u16 sadb_key_bits; + __u16 sadb_key_reserved; } __attribute__((packed)); /* sizeof(struct sadb_key) == 8 */ struct sadb_ident { - uint16_t sadb_ident_len; - uint16_t sadb_ident_exttype; - uint16_t sadb_ident_type; - uint16_t sadb_ident_reserved; - uint64_t sadb_ident_id; + __u16 sadb_ident_len; + __u16 sadb_ident_exttype; + __u16 sadb_ident_type; + __u16 sadb_ident_reserved; + __u64 sadb_ident_id; } __attribute__((packed)); /* sizeof(struct sadb_ident) == 16 */ struct sadb_sens { - uint16_t sadb_sens_len; - uint16_t sadb_sens_exttype; - uint32_t sadb_sens_dpd; - uint8_t sadb_sens_sens_level; - uint8_t sadb_sens_sens_len; - uint8_t sadb_sens_integ_level; - uint8_t sadb_sens_integ_len; - uint32_t sadb_sens_reserved; + __u16 sadb_sens_len; + __u16 sadb_sens_exttype; + __u32 sadb_sens_dpd; + __u8 sadb_sens_sens_level; + __u8 sadb_sens_sens_len; + __u8 sadb_sens_integ_level; + __u8 sadb_sens_integ_len; + __u32 sadb_sens_reserved; } __attribute__((packed)); /* sizeof(struct sadb_sens) == 16 */ /* followed by: - uint64_t sadb_sens_bitmap[sens_len]; - uint64_t sadb_integ_bitmap[integ_len]; */ + __u64 sadb_sens_bitmap[sens_len]; + __u64 sadb_integ_bitmap[integ_len]; */ struct sadb_prop { - uint16_t sadb_prop_len; - uint16_t sadb_prop_exttype; - uint8_t sadb_prop_replay; - uint8_t sadb_prop_reserved[3]; + __u16 sadb_prop_len; + __u16 sadb_prop_exttype; + __u8 sadb_prop_replay; + __u8 sadb_prop_reserved[3]; } __attribute__((packed)); /* sizeof(struct sadb_prop) == 8 */ /* followed by: struct sadb_comb sadb_combs[(sadb_prop_len + - sizeof(uint64_t) - sizeof(struct sadb_prop)) / + sizeof(__u64) - sizeof(struct sadb_prop)) / sizeof(struct sadb_comb)]; */ struct sadb_comb { - uint8_t sadb_comb_auth; - uint8_t sadb_comb_encrypt; - uint16_t sadb_comb_flags; - uint16_t sadb_comb_auth_minbits; - uint16_t sadb_comb_auth_maxbits; - uint16_t sadb_comb_encrypt_minbits; - uint16_t sadb_comb_encrypt_maxbits; - uint32_t sadb_comb_reserved; - uint32_t sadb_comb_soft_allocations; - uint32_t sadb_comb_hard_allocations; - uint64_t sadb_comb_soft_bytes; - uint64_t sadb_comb_hard_bytes; - uint64_t sadb_comb_soft_addtime; - uint64_t sadb_comb_hard_addtime; - uint64_t sadb_comb_soft_usetime; - uint64_t sadb_comb_hard_usetime; + __u8 sadb_comb_auth; + __u8 sadb_comb_encrypt; + __u16 sadb_comb_flags; + __u16 sadb_comb_auth_minbits; + __u16 sadb_comb_auth_maxbits; + __u16 sadb_comb_encrypt_minbits; + __u16 sadb_comb_encrypt_maxbits; + __u32 sadb_comb_reserved; + __u32 sadb_comb_soft_allocations; + __u32 sadb_comb_hard_allocations; + __u64 sadb_comb_soft_bytes; + __u64 sadb_comb_hard_bytes; + __u64 sadb_comb_soft_addtime; + __u64 sadb_comb_hard_addtime; + __u64 sadb_comb_soft_usetime; + __u64 sadb_comb_hard_usetime; } __attribute__((packed)); /* sizeof(struct sadb_comb) == 72 */ struct sadb_supported { - uint16_t sadb_supported_len; - uint16_t sadb_supported_exttype; - uint32_t sadb_supported_reserved; + __u16 sadb_supported_len; + __u16 sadb_supported_exttype; + __u32 sadb_supported_reserved; } __attribute__((packed)); /* sizeof(struct sadb_supported) == 8 */ /* followed by: struct sadb_alg sadb_algs[(sadb_supported_len + - sizeof(uint64_t) - sizeof(struct sadb_supported)) / + sizeof(__u64) - sizeof(struct sadb_supported)) / sizeof(struct sadb_alg)]; */ struct sadb_alg { - uint8_t sadb_alg_id; - uint8_t sadb_alg_ivlen; - uint16_t sadb_alg_minbits; - uint16_t sadb_alg_maxbits; - uint16_t sadb_alg_reserved; + __u8 sadb_alg_id; + __u8 sadb_alg_ivlen; + __u16 sadb_alg_minbits; + __u16 sadb_alg_maxbits; + __u16 sadb_alg_reserved; } __attribute__((packed)); /* sizeof(struct sadb_alg) == 8 */ struct sadb_spirange { - uint16_t sadb_spirange_len; - uint16_t sadb_spirange_exttype; - uint32_t sadb_spirange_min; - uint32_t sadb_spirange_max; - uint32_t sadb_spirange_reserved; + __u16 sadb_spirange_len; + __u16 sadb_spirange_exttype; + __u32 sadb_spirange_min; + __u32 sadb_spirange_max; + __u32 sadb_spirange_reserved; } __attribute__((packed)); /* sizeof(struct sadb_spirange) == 16 */ struct sadb_x_kmprivate { - uint16_t sadb_x_kmprivate_len; - uint16_t sadb_x_kmprivate_exttype; - uint32_t sadb_x_kmprivate_reserved; + __u16 sadb_x_kmprivate_len; + __u16 sadb_x_kmprivate_exttype; + __u32 sadb_x_kmprivate_reserved; } __attribute__((packed)); /* sizeof(struct sadb_x_kmprivate) == 8 */ struct sadb_x_sa2 { - uint16_t sadb_x_sa2_len; - uint16_t sadb_x_sa2_exttype; - uint8_t sadb_x_sa2_mode; - uint8_t sadb_x_sa2_reserved1; - uint16_t sadb_x_sa2_reserved2; - uint32_t sadb_x_sa2_sequence; - uint32_t sadb_x_sa2_reqid; + __u16 sadb_x_sa2_len; + __u16 sadb_x_sa2_exttype; + __u8 sadb_x_sa2_mode; + __u8 sadb_x_sa2_reserved1; + __u16 sadb_x_sa2_reserved2; + __u32 sadb_x_sa2_sequence; + __u32 sadb_x_sa2_reqid; } __attribute__((packed)); /* sizeof(struct sadb_x_sa2) == 16 */ struct sadb_x_policy { - uint16_t sadb_x_policy_len; - uint16_t sadb_x_policy_exttype; - uint16_t sadb_x_policy_type; - uint8_t sadb_x_policy_dir; - uint8_t sadb_x_policy_reserved; - uint32_t sadb_x_policy_id; - uint32_t sadb_x_policy_priority; + __u16 sadb_x_policy_len; + __u16 sadb_x_policy_exttype; + __u16 sadb_x_policy_type; + __u8 sadb_x_policy_dir; + __u8 sadb_x_policy_reserved; + __u32 sadb_x_policy_id; + __u32 sadb_x_policy_priority; } __attribute__((packed)); /* sizeof(struct sadb_x_policy) == 16 */ struct sadb_x_ipsecrequest { - uint16_t sadb_x_ipsecrequest_len; - uint16_t sadb_x_ipsecrequest_proto; - uint8_t sadb_x_ipsecrequest_mode; - uint8_t sadb_x_ipsecrequest_level; - uint16_t sadb_x_ipsecrequest_reserved1; - uint32_t sadb_x_ipsecrequest_reqid; - uint32_t sadb_x_ipsecrequest_reserved2; + __u16 sadb_x_ipsecrequest_len; + __u16 sadb_x_ipsecrequest_proto; + __u8 sadb_x_ipsecrequest_mode; + __u8 sadb_x_ipsecrequest_level; + __u16 sadb_x_ipsecrequest_reserved1; + __u32 sadb_x_ipsecrequest_reqid; + __u32 sadb_x_ipsecrequest_reserved2; } __attribute__((packed)); /* sizeof(struct sadb_x_ipsecrequest) == 16 */ @@ -200,38 +200,38 @@ struct sadb_x_ipsecrequest { * type of NAT-T is supported, draft-ietf-ipsec-udp-encaps-06 */ struct sadb_x_nat_t_type { - uint16_t sadb_x_nat_t_type_len; - uint16_t sadb_x_nat_t_type_exttype; - uint8_t sadb_x_nat_t_type_type; - uint8_t sadb_x_nat_t_type_reserved[3]; + __u16 sadb_x_nat_t_type_len; + __u16 sadb_x_nat_t_type_exttype; + __u8 sadb_x_nat_t_type_type; + __u8 sadb_x_nat_t_type_reserved[3]; } __attribute__((packed)); /* sizeof(struct sadb_x_nat_t_type) == 8 */ /* Pass a NAT Traversal port (Source or Dest port) */ struct sadb_x_nat_t_port { - uint16_t sadb_x_nat_t_port_len; - uint16_t sadb_x_nat_t_port_exttype; + __u16 sadb_x_nat_t_port_len; + __u16 sadb_x_nat_t_port_exttype; __be16 sadb_x_nat_t_port_port; - uint16_t sadb_x_nat_t_port_reserved; + __u16 sadb_x_nat_t_port_reserved; } __attribute__((packed)); /* sizeof(struct sadb_x_nat_t_port) == 8 */ /* Generic LSM security context */ struct sadb_x_sec_ctx { - uint16_t sadb_x_sec_len; - uint16_t sadb_x_sec_exttype; - uint8_t sadb_x_ctx_alg; /* LSMs: e.g., selinux == 1 */ - uint8_t sadb_x_ctx_doi; - uint16_t sadb_x_ctx_len; + __u16 sadb_x_sec_len; + __u16 sadb_x_sec_exttype; + __u8 sadb_x_ctx_alg; /* LSMs: e.g., selinux == 1 */ + __u8 sadb_x_ctx_doi; + __u16 sadb_x_ctx_len; } __attribute__((packed)); /* sizeof(struct sadb_sec_ctx) = 8 */ /* Used by MIGRATE to pass addresses IKE will use to perform * negotiation with the peer */ struct sadb_x_kmaddress { - uint16_t sadb_x_kmaddress_len; - uint16_t sadb_x_kmaddress_exttype; - uint32_t sadb_x_kmaddress_reserved; + __u16 sadb_x_kmaddress_len; + __u16 sadb_x_kmaddress_exttype; + __u32 sadb_x_kmaddress_reserved; } __attribute__((packed)); /* sizeof(struct sadb_x_kmaddress) == 8 */ diff --git a/include/linux/selinux_netlink.h b/include/linux/selinux_netlink.h index bbf489decd8..d239797785c 100644 --- a/include/linux/selinux_netlink.h +++ b/include/linux/selinux_netlink.h @@ -12,6 +12,8 @@ #ifndef _LINUX_SELINUX_NETLINK_H #define _LINUX_SELINUX_NETLINK_H +#include + /* Message types. */ #define SELNL_MSG_BASE 0x10 enum { @@ -38,11 +40,11 @@ enum selinux_nlgroups { /* Message structures */ struct selnl_msg_setenforce { - int32_t val; + __s32 val; }; struct selnl_msg_policyload { - u_int32_t seqno; + __u32 seqno; }; #endif /* _LINUX_SELINUX_NETLINK_H */ diff --git a/include/sound/asound.h b/include/sound/asound.h index 16684c5a608..d9beda5f74a 100644 --- a/include/sound/asound.h +++ b/include/sound/asound.h @@ -23,9 +23,10 @@ #ifndef __SOUND_ASOUND_H #define __SOUND_ASOUND_H +#include + #ifdef __KERNEL__ #include -#include #include #include @@ -342,7 +343,7 @@ struct snd_interval { #define SNDRV_MASK_MAX 256 struct snd_mask { - u_int32_t bits[(SNDRV_MASK_MAX+31)/32]; + __u32 bits[(SNDRV_MASK_MAX+31)/32]; }; struct snd_pcm_hw_params { diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h index 10ee28eac01..c380056ff26 100644 --- a/include/sound/emu10k1.h +++ b/include/sound/emu10k1.h @@ -1,6 +1,8 @@ #ifndef __SOUND_EMU10K1_H #define __SOUND_EMU10K1_H +#include + /* * Copyright (c) by Jaroslav Kysela , * Creative Labs, Inc. @@ -34,6 +36,8 @@ #include #include #include +#include + #include /* ------------------- DEFINES -------------------- */ @@ -2171,7 +2175,7 @@ struct snd_emu10k1_fx8010_code { char name[128]; DECLARE_BITMAP(gpr_valid, 0x200); /* bitmask of valid initializers */ - u_int32_t __user *gpr_map; /* initializers */ + __u32 __user *gpr_map; /* initializers */ unsigned int gpr_add_control_count; /* count of GPR controls to add/replace */ struct snd_emu10k1_fx8010_control_gpr __user *gpr_add_controls; /* GPR controls to add/replace */ @@ -2184,11 +2188,11 @@ struct snd_emu10k1_fx8010_code { struct snd_emu10k1_fx8010_control_gpr __user *gpr_list_controls; /* listed GPR controls */ DECLARE_BITMAP(tram_valid, 0x100); /* bitmask of valid initializers */ - u_int32_t __user *tram_data_map; /* data initializers */ - u_int32_t __user *tram_addr_map; /* map initializers */ + __u32 __user *tram_data_map; /* data initializers */ + __u32 __user *tram_addr_map; /* map initializers */ DECLARE_BITMAP(code_valid, 1024); /* bitmask of valid instructions */ - u_int32_t __user *code; /* one instruction - 64 bits */ + __u32 __user *code; /* one instruction - 64 bits */ }; struct snd_emu10k1_fx8010_tram { -- GitLab From ccef7ab534347e2e1e1ef398d2ec987d37e519f3 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 26 Feb 2009 00:51:41 +0100 Subject: [PATCH 4694/4982] make MTD headers use strict integer types The MTD headers traditionally use stdint types rather than the kernel integer types. This converts them to do the same as all the others. Cc: David Woodhouse Signed-off-by: Arnd Bergmann Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- include/linux/jffs2.h | 27 +++++++-------- include/mtd/inftl-user.h | 36 ++++++++++---------- include/mtd/jffs2-user.h | 5 +-- include/mtd/mtd-abi.h | 66 ++++++++++++++++++------------------ include/mtd/nftl-user.h | 32 +++++++++--------- include/mtd/ubi-user.h | 72 +++++++++++++++++++++------------------- 6 files changed, 123 insertions(+), 115 deletions(-) diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h index da720bc3eb1..2b32d638147 100644 --- a/include/linux/jffs2.h +++ b/include/linux/jffs2.h @@ -12,6 +12,7 @@ #ifndef __LINUX_JFFS2_H__ #define __LINUX_JFFS2_H__ +#include #include /* You must include something which defines the C99 uintXX_t types. @@ -91,15 +92,15 @@ byteswapping */ typedef struct { - uint32_t v32; + __u32 v32; } __attribute__((packed)) jint32_t; typedef struct { - uint32_t m; + __u32 m; } __attribute__((packed)) jmode_t; typedef struct { - uint16_t v16; + __u16 v16; } __attribute__((packed)) jint16_t; struct jffs2_unknown_node @@ -121,12 +122,12 @@ struct jffs2_raw_dirent jint32_t version; jint32_t ino; /* == zero for unlink */ jint32_t mctime; - uint8_t nsize; - uint8_t type; - uint8_t unused[2]; + __u8 nsize; + __u8 type; + __u8 unused[2]; jint32_t node_crc; jint32_t name_crc; - uint8_t name[0]; + __u8 name[0]; }; /* The JFFS2 raw inode structure: Used for storage on physical media. */ @@ -153,12 +154,12 @@ struct jffs2_raw_inode jint32_t offset; /* Where to begin to write. */ jint32_t csize; /* (Compressed) data size */ jint32_t dsize; /* Size of the node's data. (after decompression) */ - uint8_t compr; /* Compression algorithm used */ - uint8_t usercompr; /* Compression algorithm requested by the user */ + __u8 compr; /* Compression algorithm used */ + __u8 usercompr; /* Compression algorithm requested by the user */ jint16_t flags; /* See JFFS2_INO_FLAG_* */ jint32_t data_crc; /* CRC for the (compressed) data. */ jint32_t node_crc; /* CRC for the raw inode (excluding data) */ - uint8_t data[0]; + __u8 data[0]; }; struct jffs2_raw_xattr { @@ -168,12 +169,12 @@ struct jffs2_raw_xattr { jint32_t hdr_crc; jint32_t xid; /* XATTR identifier number */ jint32_t version; - uint8_t xprefix; - uint8_t name_len; + __u8 xprefix; + __u8 name_len; jint16_t value_len; jint32_t data_crc; jint32_t node_crc; - uint8_t data[0]; + __u8 data[0]; } __attribute__((packed)); struct jffs2_raw_xref diff --git a/include/mtd/inftl-user.h b/include/mtd/inftl-user.h index d409d489d90..8376bd1a9e0 100644 --- a/include/mtd/inftl-user.h +++ b/include/mtd/inftl-user.h @@ -16,33 +16,33 @@ /* Block Control Information */ struct inftl_bci { - uint8_t ECCsig[6]; - uint8_t Status; - uint8_t Status1; + __u8 ECCsig[6]; + __u8 Status; + __u8 Status1; } __attribute__((packed)); struct inftl_unithead1 { - uint16_t virtualUnitNo; - uint16_t prevUnitNo; - uint8_t ANAC; - uint8_t NACs; - uint8_t parityPerField; - uint8_t discarded; + __u16 virtualUnitNo; + __u16 prevUnitNo; + __u8 ANAC; + __u8 NACs; + __u8 parityPerField; + __u8 discarded; } __attribute__((packed)); struct inftl_unithead2 { - uint8_t parityPerField; - uint8_t ANAC; - uint16_t prevUnitNo; - uint16_t virtualUnitNo; - uint8_t NACs; - uint8_t discarded; + __u8 parityPerField; + __u8 ANAC; + __u16 prevUnitNo; + __u16 virtualUnitNo; + __u8 NACs; + __u8 discarded; } __attribute__((packed)); struct inftl_unittail { - uint8_t Reserved[4]; - uint16_t EraseMark; - uint16_t EraseMark1; + __u8 Reserved[4]; + __u16 EraseMark; + __u16 EraseMark1; } __attribute__((packed)); union inftl_uci { diff --git a/include/mtd/jffs2-user.h b/include/mtd/jffs2-user.h index 001685d7fa8..fa94b0eb67c 100644 --- a/include/mtd/jffs2-user.h +++ b/include/mtd/jffs2-user.h @@ -7,6 +7,7 @@ /* This file is blessed for inclusion by userspace */ #include +#include #include #include @@ -19,8 +20,8 @@ extern int target_endian; -#define t16(x) ({ uint16_t __b = (x); (target_endian==__BYTE_ORDER)?__b:bswap_16(__b); }) -#define t32(x) ({ uint32_t __b = (x); (target_endian==__BYTE_ORDER)?__b:bswap_32(__b); }) +#define t16(x) ({ __u16 __b = (x); (target_endian==__BYTE_ORDER)?__b:bswap_16(__b); }) +#define t32(x) ({ __u32 __b = (x); (target_endian==__BYTE_ORDER)?__b:bswap_32(__b); }) #define cpu_to_je16(x) ((jint16_t){t16(x)}) #define cpu_to_je32(x) ((jint32_t){t32(x)}) diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h index fb672013299..b6595b3c68b 100644 --- a/include/mtd/mtd-abi.h +++ b/include/mtd/mtd-abi.h @@ -5,14 +5,16 @@ #ifndef __MTD_ABI_H__ #define __MTD_ABI_H__ +#include + struct erase_info_user { - uint32_t start; - uint32_t length; + __u32 start; + __u32 length; }; struct mtd_oob_buf { - uint32_t start; - uint32_t length; + __u32 start; + __u32 length; unsigned char __user *ptr; }; @@ -48,30 +50,30 @@ struct mtd_oob_buf { #define MTD_OTP_USER 2 struct mtd_info_user { - uint8_t type; - uint32_t flags; - uint32_t size; // Total size of the MTD - uint32_t erasesize; - uint32_t writesize; - uint32_t oobsize; // Amount of OOB data per block (e.g. 16) + __u8 type; + __u32 flags; + __u32 size; // Total size of the MTD + __u32 erasesize; + __u32 writesize; + __u32 oobsize; // Amount of OOB data per block (e.g. 16) /* The below two fields are obsolete and broken, do not use them * (TODO: remove at some point) */ - uint32_t ecctype; - uint32_t eccsize; + __u32 ecctype; + __u32 eccsize; }; struct region_info_user { - uint32_t offset; /* At which this region starts, + __u32 offset; /* At which this region starts, * from the beginning of the MTD */ - uint32_t erasesize; /* For this region */ - uint32_t numblocks; /* Number of blocks in this region */ - uint32_t regionindex; + __u32 erasesize; /* For this region */ + __u32 numblocks; /* Number of blocks in this region */ + __u32 regionindex; }; struct otp_info { - uint32_t start; - uint32_t length; - uint32_t locked; + __u32 start; + __u32 length; + __u32 locked; }; #define MEMGETINFO _IOR('M', 1, struct mtd_info_user) @@ -99,15 +101,15 @@ struct otp_info { * interfaces */ struct nand_oobinfo { - uint32_t useecc; - uint32_t eccbytes; - uint32_t oobfree[8][2]; - uint32_t eccpos[32]; + __u32 useecc; + __u32 eccbytes; + __u32 oobfree[8][2]; + __u32 eccpos[32]; }; struct nand_oobfree { - uint32_t offset; - uint32_t length; + __u32 offset; + __u32 length; }; #define MTD_MAX_OOBFREE_ENTRIES 8 @@ -116,9 +118,9 @@ struct nand_oobfree { * diagnosis and to allow creation of raw images */ struct nand_ecclayout { - uint32_t eccbytes; - uint32_t eccpos[64]; - uint32_t oobavail; + __u32 eccbytes; + __u32 eccpos[64]; + __u32 oobavail; struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES]; }; @@ -131,10 +133,10 @@ struct nand_ecclayout { * @bbtblocks: number of blocks reserved for bad block tables */ struct mtd_ecc_stats { - uint32_t corrected; - uint32_t failed; - uint32_t badblocks; - uint32_t bbtblocks; + __u32 corrected; + __u32 failed; + __u32 badblocks; + __u32 bbtblocks; }; /* diff --git a/include/mtd/nftl-user.h b/include/mtd/nftl-user.h index 390d21c080a..98e9e57f22d 100644 --- a/include/mtd/nftl-user.h +++ b/include/mtd/nftl-user.h @@ -6,33 +6,35 @@ #ifndef __MTD_NFTL_USER_H__ #define __MTD_NFTL_USER_H__ +#include + /* Block Control Information */ struct nftl_bci { unsigned char ECCSig[6]; - uint8_t Status; - uint8_t Status1; + __u8 Status; + __u8 Status1; }__attribute__((packed)); /* Unit Control Information */ struct nftl_uci0 { - uint16_t VirtUnitNum; - uint16_t ReplUnitNum; - uint16_t SpareVirtUnitNum; - uint16_t SpareReplUnitNum; + __u16 VirtUnitNum; + __u16 ReplUnitNum; + __u16 SpareVirtUnitNum; + __u16 SpareReplUnitNum; } __attribute__((packed)); struct nftl_uci1 { - uint32_t WearInfo; - uint16_t EraseMark; - uint16_t EraseMark1; + __u32 WearInfo; + __u16 EraseMark; + __u16 EraseMark1; } __attribute__((packed)); struct nftl_uci2 { - uint16_t FoldMark; - uint16_t FoldMark1; - uint32_t unused; + __u16 FoldMark; + __u16 FoldMark1; + __u32 unused; } __attribute__((packed)); union nftl_uci { @@ -50,9 +52,9 @@ struct nftl_oob { struct NFTLMediaHeader { char DataOrgID[6]; - uint16_t NumEraseUnits; - uint16_t FirstPhysicalEUN; - uint32_t FormattedSize; + __u16 NumEraseUnits; + __u16 FirstPhysicalEUN; + __u32 FormattedSize; unsigned char UnitSizeFactor; } __attribute__((packed)); diff --git a/include/mtd/ubi-user.h b/include/mtd/ubi-user.h index 296efae3525..466a8320f1e 100644 --- a/include/mtd/ubi-user.h +++ b/include/mtd/ubi-user.h @@ -21,6 +21,8 @@ #ifndef __UBI_USER_H__ #define __UBI_USER_H__ +#include + /* * UBI device creation (the same as MTD device attachment) * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -152,7 +154,7 @@ /* Create an UBI volume */ #define UBI_IOCMKVOL _IOW(UBI_IOC_MAGIC, 0, struct ubi_mkvol_req) /* Remove an UBI volume */ -#define UBI_IOCRMVOL _IOW(UBI_IOC_MAGIC, 1, int32_t) +#define UBI_IOCRMVOL _IOW(UBI_IOC_MAGIC, 1, __s32) /* Re-size an UBI volume */ #define UBI_IOCRSVOL _IOW(UBI_IOC_MAGIC, 2, struct ubi_rsvol_req) /* Re-name volumes */ @@ -165,24 +167,24 @@ /* Attach an MTD device */ #define UBI_IOCATT _IOW(UBI_CTRL_IOC_MAGIC, 64, struct ubi_attach_req) /* Detach an MTD device */ -#define UBI_IOCDET _IOW(UBI_CTRL_IOC_MAGIC, 65, int32_t) +#define UBI_IOCDET _IOW(UBI_CTRL_IOC_MAGIC, 65, __s32) /* ioctl commands of UBI volume character devices */ #define UBI_VOL_IOC_MAGIC 'O' /* Start UBI volume update */ -#define UBI_IOCVOLUP _IOW(UBI_VOL_IOC_MAGIC, 0, int64_t) +#define UBI_IOCVOLUP _IOW(UBI_VOL_IOC_MAGIC, 0, __s64) /* LEB erasure command, used for debugging, disabled by default */ -#define UBI_IOCEBER _IOW(UBI_VOL_IOC_MAGIC, 1, int32_t) +#define UBI_IOCEBER _IOW(UBI_VOL_IOC_MAGIC, 1, __s32) /* Atomic LEB change command */ -#define UBI_IOCEBCH _IOW(UBI_VOL_IOC_MAGIC, 2, int32_t) +#define UBI_IOCEBCH _IOW(UBI_VOL_IOC_MAGIC, 2, __s32) /* Map LEB command */ #define UBI_IOCEBMAP _IOW(UBI_VOL_IOC_MAGIC, 3, struct ubi_map_req) /* Unmap LEB command */ -#define UBI_IOCEBUNMAP _IOW(UBI_VOL_IOC_MAGIC, 4, int32_t) +#define UBI_IOCEBUNMAP _IOW(UBI_VOL_IOC_MAGIC, 4, __s32) /* Check if LEB is mapped command */ -#define UBI_IOCEBISMAP _IOR(UBI_VOL_IOC_MAGIC, 5, int32_t) +#define UBI_IOCEBISMAP _IOR(UBI_VOL_IOC_MAGIC, 5, __s32) /* Set an UBI volume property */ #define UBI_IOCSETPROP _IOW(UBI_VOL_IOC_MAGIC, 6, struct ubi_set_prop_req) @@ -260,10 +262,10 @@ enum { * sub-page of the first page and add needed padding. */ struct ubi_attach_req { - int32_t ubi_num; - int32_t mtd_num; - int32_t vid_hdr_offset; - int8_t padding[12]; + __s32 ubi_num; + __s32 mtd_num; + __s32 vid_hdr_offset; + __s8 padding[12]; }; /** @@ -298,13 +300,13 @@ struct ubi_attach_req { * BLOBs, without caring about how to properly align them. */ struct ubi_mkvol_req { - int32_t vol_id; - int32_t alignment; - int64_t bytes; - int8_t vol_type; - int8_t padding1; - int16_t name_len; - int8_t padding2[4]; + __s32 vol_id; + __s32 alignment; + __s64 bytes; + __s8 vol_type; + __s8 padding1; + __s16 name_len; + __s8 padding2[4]; char name[UBI_MAX_VOLUME_NAME + 1]; } __attribute__ ((packed)); @@ -320,8 +322,8 @@ struct ubi_mkvol_req { * zero number of bytes). */ struct ubi_rsvol_req { - int64_t bytes; - int32_t vol_id; + __s64 bytes; + __s32 vol_id; } __attribute__ ((packed)); /** @@ -356,12 +358,12 @@ struct ubi_rsvol_req { * re-name request. */ struct ubi_rnvol_req { - int32_t count; - int8_t padding1[12]; + __s32 count; + __s8 padding1[12]; struct { - int32_t vol_id; - int16_t name_len; - int8_t padding2[2]; + __s32 vol_id; + __s16 name_len; + __s8 padding2[2]; char name[UBI_MAX_VOLUME_NAME + 1]; } ents[UBI_MAX_RNVOL]; } __attribute__ ((packed)); @@ -375,10 +377,10 @@ struct ubi_rnvol_req { * @padding: reserved for future, not used, has to be zeroed */ struct ubi_leb_change_req { - int32_t lnum; - int32_t bytes; - int8_t dtype; - int8_t padding[7]; + __s32 lnum; + __s32 bytes; + __s8 dtype; + __s8 padding[7]; } __attribute__ ((packed)); /** @@ -388,9 +390,9 @@ struct ubi_leb_change_req { * @padding: reserved for future, not used, has to be zeroed */ struct ubi_map_req { - int32_t lnum; - int8_t dtype; - int8_t padding[3]; + __s32 lnum; + __s8 dtype; + __s8 padding[3]; } __attribute__ ((packed)); @@ -402,9 +404,9 @@ struct ubi_map_req { * @value: value to set */ struct ubi_set_prop_req { - uint8_t property; - uint8_t padding[7]; - uint64_t value; + __u8 property; + __u8 padding[7]; + __u64 value; } __attribute__ ((packed)); #endif /* __UBI_USER_H__ */ -- GitLab From 1d7f83d5ad6c30b385ba549c1c3a287cc872b7ae Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 26 Feb 2009 00:51:42 +0100 Subject: [PATCH 4695/4982] make drm headers use strict integer types The drm headers are traditionally shared with BSD and could not use the strict linux integer types. This is over now, so we can use our own types now. Cc: David Airlie Signed-off-by: Arnd Bergmann Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- include/drm/drm.h | 21 +++--- include/drm/drm_mode.h | 153 +++++++++++++++++++-------------------- include/drm/i915_drm.h | 140 +++++++++++++++++------------------ include/drm/mga_drm.h | 18 +++-- include/drm/radeon_drm.h | 4 +- include/drm/via_drm.h | 42 ++++++----- 6 files changed, 190 insertions(+), 188 deletions(-) diff --git a/include/drm/drm.h b/include/drm/drm.h index 8e77357334a..7cb50bdde46 100644 --- a/include/drm/drm.h +++ b/include/drm/drm.h @@ -36,8 +36,7 @@ #ifndef _DRM_H_ #define _DRM_H_ -#if defined(__KERNEL__) -#endif +#include #include /* For _IO* macros */ #define DRM_IOCTL_NR(n) _IOC_NR(n) #define DRM_IOC_VOID _IOC_NONE @@ -497,8 +496,8 @@ union drm_wait_vblank { * \sa drmModesetCtl(). */ struct drm_modeset_ctl { - uint32_t crtc; - uint32_t cmd; + __u32 crtc; + __u32 cmd; }; /** @@ -574,29 +573,29 @@ struct drm_set_version { /** DRM_IOCTL_GEM_CLOSE ioctl argument type */ struct drm_gem_close { /** Handle of the object to be closed. */ - uint32_t handle; - uint32_t pad; + __u32 handle; + __u32 pad; }; /** DRM_IOCTL_GEM_FLINK ioctl argument type */ struct drm_gem_flink { /** Handle for the object being named */ - uint32_t handle; + __u32 handle; /** Returned global name */ - uint32_t name; + __u32 name; }; /** DRM_IOCTL_GEM_OPEN ioctl argument type */ struct drm_gem_open { /** Name of object being opened */ - uint32_t name; + __u32 name; /** Returned handle for the object */ - uint32_t handle; + __u32 handle; /** Returned size of the object */ - uint64_t size; + __u64 size; }; #include "drm_mode.h" diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h index 601d2bd839f..ae304cc73c9 100644 --- a/include/drm/drm_mode.h +++ b/include/drm/drm_mode.h @@ -27,11 +27,8 @@ #ifndef _DRM_MODE_H #define _DRM_MODE_H -#if !defined(__KERNEL__) && !defined(_KERNEL) -#include -#else #include -#endif +#include #define DRM_DISPLAY_INFO_LEN 32 #define DRM_CONNECTOR_NAME_LEN 32 @@ -81,41 +78,41 @@ #define DRM_MODE_DITHERING_ON 1 struct drm_mode_modeinfo { - uint32_t clock; - uint16_t hdisplay, hsync_start, hsync_end, htotal, hskew; - uint16_t vdisplay, vsync_start, vsync_end, vtotal, vscan; + __u32 clock; + __u16 hdisplay, hsync_start, hsync_end, htotal, hskew; + __u16 vdisplay, vsync_start, vsync_end, vtotal, vscan; - uint32_t vrefresh; /* vertical refresh * 1000 */ + __u32 vrefresh; /* vertical refresh * 1000 */ - uint32_t flags; - uint32_t type; + __u32 flags; + __u32 type; char name[DRM_DISPLAY_MODE_LEN]; }; struct drm_mode_card_res { - uint64_t fb_id_ptr; - uint64_t crtc_id_ptr; - uint64_t connector_id_ptr; - uint64_t encoder_id_ptr; - uint32_t count_fbs; - uint32_t count_crtcs; - uint32_t count_connectors; - uint32_t count_encoders; - uint32_t min_width, max_width; - uint32_t min_height, max_height; + __u64 fb_id_ptr; + __u64 crtc_id_ptr; + __u64 connector_id_ptr; + __u64 encoder_id_ptr; + __u32 count_fbs; + __u32 count_crtcs; + __u32 count_connectors; + __u32 count_encoders; + __u32 min_width, max_width; + __u32 min_height, max_height; }; struct drm_mode_crtc { - uint64_t set_connectors_ptr; - uint32_t count_connectors; + __u64 set_connectors_ptr; + __u32 count_connectors; - uint32_t crtc_id; /**< Id */ - uint32_t fb_id; /**< Id of framebuffer */ + __u32 crtc_id; /**< Id */ + __u32 fb_id; /**< Id of framebuffer */ - uint32_t x, y; /**< Position on the frameuffer */ + __u32 x, y; /**< Position on the frameuffer */ - uint32_t gamma_size; - uint32_t mode_valid; + __u32 gamma_size; + __u32 mode_valid; struct drm_mode_modeinfo mode; }; @@ -126,13 +123,13 @@ struct drm_mode_crtc { #define DRM_MODE_ENCODER_TVDAC 4 struct drm_mode_get_encoder { - uint32_t encoder_id; - uint32_t encoder_type; + __u32 encoder_id; + __u32 encoder_type; - uint32_t crtc_id; /**< Id of crtc */ + __u32 crtc_id; /**< Id of crtc */ - uint32_t possible_crtcs; - uint32_t possible_clones; + __u32 possible_crtcs; + __u32 possible_clones; }; /* This is for connectors with multiple signal types. */ @@ -161,23 +158,23 @@ struct drm_mode_get_encoder { struct drm_mode_get_connector { - uint64_t encoders_ptr; - uint64_t modes_ptr; - uint64_t props_ptr; - uint64_t prop_values_ptr; + __u64 encoders_ptr; + __u64 modes_ptr; + __u64 props_ptr; + __u64 prop_values_ptr; - uint32_t count_modes; - uint32_t count_props; - uint32_t count_encoders; + __u32 count_modes; + __u32 count_props; + __u32 count_encoders; - uint32_t encoder_id; /**< Current Encoder */ - uint32_t connector_id; /**< Id */ - uint32_t connector_type; - uint32_t connector_type_id; + __u32 encoder_id; /**< Current Encoder */ + __u32 connector_id; /**< Id */ + __u32 connector_type; + __u32 connector_type_id; - uint32_t connection; - uint32_t mm_width, mm_height; /**< HxW in millimeters */ - uint32_t subpixel; + __u32 connection; + __u32 mm_width, mm_height; /**< HxW in millimeters */ + __u32 subpixel; }; #define DRM_MODE_PROP_PENDING (1<<0) @@ -187,46 +184,46 @@ struct drm_mode_get_connector { #define DRM_MODE_PROP_BLOB (1<<4) struct drm_mode_property_enum { - uint64_t value; + __u64 value; char name[DRM_PROP_NAME_LEN]; }; struct drm_mode_get_property { - uint64_t values_ptr; /* values and blob lengths */ - uint64_t enum_blob_ptr; /* enum and blob id ptrs */ + __u64 values_ptr; /* values and blob lengths */ + __u64 enum_blob_ptr; /* enum and blob id ptrs */ - uint32_t prop_id; - uint32_t flags; + __u32 prop_id; + __u32 flags; char name[DRM_PROP_NAME_LEN]; - uint32_t count_values; - uint32_t count_enum_blobs; + __u32 count_values; + __u32 count_enum_blobs; }; struct drm_mode_connector_set_property { - uint64_t value; - uint32_t prop_id; - uint32_t connector_id; + __u64 value; + __u32 prop_id; + __u32 connector_id; }; struct drm_mode_get_blob { - uint32_t blob_id; - uint32_t length; - uint64_t data; + __u32 blob_id; + __u32 length; + __u64 data; }; struct drm_mode_fb_cmd { - uint32_t fb_id; - uint32_t width, height; - uint32_t pitch; - uint32_t bpp; - uint32_t depth; + __u32 fb_id; + __u32 width, height; + __u32 pitch; + __u32 bpp; + __u32 depth; /* driver specific handle */ - uint32_t handle; + __u32 handle; }; struct drm_mode_mode_cmd { - uint32_t connector_id; + __u32 connector_id; struct drm_mode_modeinfo mode; }; @@ -248,24 +245,24 @@ struct drm_mode_mode_cmd { * y */ struct drm_mode_cursor { - uint32_t flags; - uint32_t crtc_id; - int32_t x; - int32_t y; - uint32_t width; - uint32_t height; + __u32 flags; + __u32 crtc_id; + __s32 x; + __s32 y; + __u32 width; + __u32 height; /* driver specific handle */ - uint32_t handle; + __u32 handle; }; struct drm_mode_crtc_lut { - uint32_t crtc_id; - uint32_t gamma_size; + __u32 crtc_id; + __u32 gamma_size; /* pointers to arrays */ - uint64_t red; - uint64_t green; - uint64_t blue; + __u64 red; + __u64 green; + __u64 blue; }; #endif diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h index b3bcf72dc65..641b9b210d3 100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h @@ -30,7 +30,7 @@ /* Please note that modifications to all structs defined here are * subject to backwards-compatibility constraints. */ - +#include #include "drm.h" /* Each region is a minimum of 16k, and there are at most 255 of them. @@ -116,15 +116,15 @@ typedef struct _drm_i915_sarea { /* fill out some space for old userspace triple buffer */ drm_handle_t unused_handle; - uint32_t unused1, unused2, unused3; + __u32 unused1, unused2, unused3; /* buffer object handles for static buffers. May change * over the lifetime of the client. */ - uint32_t front_bo_handle; - uint32_t back_bo_handle; - uint32_t unused_bo_handle; - uint32_t depth_bo_handle; + __u32 front_bo_handle; + __u32 back_bo_handle; + __u32 unused_bo_handle; + __u32 depth_bo_handle; } drm_i915_sarea_t; @@ -325,7 +325,7 @@ typedef struct drm_i915_vblank_swap { } drm_i915_vblank_swap_t; typedef struct drm_i915_hws_addr { - uint64_t addr; + __u64 addr; } drm_i915_hws_addr_t; struct drm_i915_gem_init { @@ -333,12 +333,12 @@ struct drm_i915_gem_init { * Beginning offset in the GTT to be managed by the DRM memory * manager. */ - uint64_t gtt_start; + __u64 gtt_start; /** * Ending offset in the GTT to be managed by the DRM memory * manager. */ - uint64_t gtt_end; + __u64 gtt_end; }; struct drm_i915_gem_create { @@ -347,94 +347,94 @@ struct drm_i915_gem_create { * * The (page-aligned) allocated size for the object will be returned. */ - uint64_t size; + __u64 size; /** * Returned handle for the object. * * Object handles are nonzero. */ - uint32_t handle; - uint32_t pad; + __u32 handle; + __u32 pad; }; struct drm_i915_gem_pread { /** Handle for the object being read. */ - uint32_t handle; - uint32_t pad; + __u32 handle; + __u32 pad; /** Offset into the object to read from */ - uint64_t offset; + __u64 offset; /** Length of data to read */ - uint64_t size; + __u64 size; /** * Pointer to write the data into. * * This is a fixed-size type for 32/64 compatibility. */ - uint64_t data_ptr; + __u64 data_ptr; }; struct drm_i915_gem_pwrite { /** Handle for the object being written to. */ - uint32_t handle; - uint32_t pad; + __u32 handle; + __u32 pad; /** Offset into the object to write to */ - uint64_t offset; + __u64 offset; /** Length of data to write */ - uint64_t size; + __u64 size; /** * Pointer to read the data from. * * This is a fixed-size type for 32/64 compatibility. */ - uint64_t data_ptr; + __u64 data_ptr; }; struct drm_i915_gem_mmap { /** Handle for the object being mapped. */ - uint32_t handle; - uint32_t pad; + __u32 handle; + __u32 pad; /** Offset in the object to map. */ - uint64_t offset; + __u64 offset; /** * Length of data to map. * * The value will be page-aligned. */ - uint64_t size; + __u64 size; /** * Returned pointer the data was mapped at. * * This is a fixed-size type for 32/64 compatibility. */ - uint64_t addr_ptr; + __u64 addr_ptr; }; struct drm_i915_gem_mmap_gtt { /** Handle for the object being mapped. */ - uint32_t handle; - uint32_t pad; + __u32 handle; + __u32 pad; /** * Fake offset to use for subsequent mmap call * * This is a fixed-size type for 32/64 compatibility. */ - uint64_t offset; + __u64 offset; }; struct drm_i915_gem_set_domain { /** Handle for the object */ - uint32_t handle; + __u32 handle; /** New read domains */ - uint32_t read_domains; + __u32 read_domains; /** New write domain */ - uint32_t write_domain; + __u32 write_domain; }; struct drm_i915_gem_sw_finish { /** Handle for the object */ - uint32_t handle; + __u32 handle; }; struct drm_i915_gem_relocation_entry { @@ -446,16 +446,16 @@ struct drm_i915_gem_relocation_entry { * a relocation list for state buffers and not re-write it per * exec using the buffer. */ - uint32_t target_handle; + __u32 target_handle; /** * Value to be added to the offset of the target buffer to make up * the relocation entry. */ - uint32_t delta; + __u32 delta; /** Offset in the buffer the relocation entry will be written into */ - uint64_t offset; + __u64 offset; /** * Offset value of the target buffer that the relocation entry was last @@ -465,12 +465,12 @@ struct drm_i915_gem_relocation_entry { * and writing the relocation. This value is written back out by * the execbuffer ioctl when the relocation is written. */ - uint64_t presumed_offset; + __u64 presumed_offset; /** * Target memory domains read by this operation. */ - uint32_t read_domains; + __u32 read_domains; /** * Target memory domains written by this operation. @@ -479,7 +479,7 @@ struct drm_i915_gem_relocation_entry { * execbuffer operation, so that where there are conflicts, * the application will get -EINVAL back. */ - uint32_t write_domain; + __u32 write_domain; }; /** @{ @@ -510,24 +510,24 @@ struct drm_i915_gem_exec_object { * User's handle for a buffer to be bound into the GTT for this * operation. */ - uint32_t handle; + __u32 handle; /** Number of relocations to be performed on this buffer */ - uint32_t relocation_count; + __u32 relocation_count; /** * Pointer to array of struct drm_i915_gem_relocation_entry containing * the relocations to be performed in this buffer. */ - uint64_t relocs_ptr; + __u64 relocs_ptr; /** Required alignment in graphics aperture */ - uint64_t alignment; + __u64 alignment; /** * Returned value of the updated offset of the object, for future * presumed_offset writes. */ - uint64_t offset; + __u64 offset; }; struct drm_i915_gem_execbuffer { @@ -541,44 +541,44 @@ struct drm_i915_gem_execbuffer { * a buffer is performing refer to buffers that have already appeared * in the validate list. */ - uint64_t buffers_ptr; - uint32_t buffer_count; + __u64 buffers_ptr; + __u32 buffer_count; /** Offset in the batchbuffer to start execution from. */ - uint32_t batch_start_offset; + __u32 batch_start_offset; /** Bytes used in batchbuffer from batch_start_offset */ - uint32_t batch_len; - uint32_t DR1; - uint32_t DR4; - uint32_t num_cliprects; + __u32 batch_len; + __u32 DR1; + __u32 DR4; + __u32 num_cliprects; /** This is a struct drm_clip_rect *cliprects */ - uint64_t cliprects_ptr; + __u64 cliprects_ptr; }; struct drm_i915_gem_pin { /** Handle of the buffer to be pinned. */ - uint32_t handle; - uint32_t pad; + __u32 handle; + __u32 pad; /** alignment required within the aperture */ - uint64_t alignment; + __u64 alignment; /** Returned GTT offset of the buffer. */ - uint64_t offset; + __u64 offset; }; struct drm_i915_gem_unpin { /** Handle of the buffer to be unpinned. */ - uint32_t handle; - uint32_t pad; + __u32 handle; + __u32 pad; }; struct drm_i915_gem_busy { /** Handle of the buffer to check for busy */ - uint32_t handle; + __u32 handle; /** Return busy status (1 if busy, 0 if idle) */ - uint32_t busy; + __u32 busy; }; #define I915_TILING_NONE 0 @@ -595,7 +595,7 @@ struct drm_i915_gem_busy { struct drm_i915_gem_set_tiling { /** Handle of the buffer to have its tiling state updated */ - uint32_t handle; + __u32 handle; /** * Tiling mode for the object (I915_TILING_NONE, I915_TILING_X, @@ -609,47 +609,47 @@ struct drm_i915_gem_set_tiling { * * Buffer contents become undefined when changing tiling_mode. */ - uint32_t tiling_mode; + __u32 tiling_mode; /** * Stride in bytes for the object when in I915_TILING_X or * I915_TILING_Y. */ - uint32_t stride; + __u32 stride; /** * Returned address bit 6 swizzling required for CPU access through * mmap mapping. */ - uint32_t swizzle_mode; + __u32 swizzle_mode; }; struct drm_i915_gem_get_tiling { /** Handle of the buffer to get tiling state for. */ - uint32_t handle; + __u32 handle; /** * Current tiling mode for the object (I915_TILING_NONE, I915_TILING_X, * I915_TILING_Y). */ - uint32_t tiling_mode; + __u32 tiling_mode; /** * Returned address bit 6 swizzling required for CPU access through * mmap mapping. */ - uint32_t swizzle_mode; + __u32 swizzle_mode; }; struct drm_i915_gem_get_aperture { /** Total size of the aperture used by i915_gem_execbuffer, in bytes */ - uint64_t aper_size; + __u64 aper_size; /** * Available space in the aperture used by i915_gem_execbuffer, in * bytes */ - uint64_t aper_available_size; + __u64 aper_available_size; }; #endif /* _I915_DRM_H_ */ diff --git a/include/drm/mga_drm.h b/include/drm/mga_drm.h index 944b50a5ff2..325fd6fb4a4 100644 --- a/include/drm/mga_drm.h +++ b/include/drm/mga_drm.h @@ -35,6 +35,8 @@ #ifndef __MGA_DRM_H__ #define __MGA_DRM_H__ +#include + /* WARNING: If you change any of these defines, make sure to change the * defines in the Xserver file (mga_sarea.h) */ @@ -255,8 +257,8 @@ typedef struct _drm_mga_sarea { #define DRM_IOCTL_MGA_ILOAD DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_ILOAD, drm_mga_iload_t) #define DRM_IOCTL_MGA_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_BLIT, drm_mga_blit_t) #define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_GETPARAM, drm_mga_getparam_t) -#define DRM_IOCTL_MGA_SET_FENCE DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_SET_FENCE, uint32_t) -#define DRM_IOCTL_MGA_WAIT_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_WAIT_FENCE, uint32_t) +#define DRM_IOCTL_MGA_SET_FENCE DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_SET_FENCE, __u32) +#define DRM_IOCTL_MGA_WAIT_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_WAIT_FENCE, __u32) #define DRM_IOCTL_MGA_DMA_BOOTSTRAP DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_DMA_BOOTSTRAP, drm_mga_dma_bootstrap_t) typedef struct _drm_mga_warp_index { @@ -310,7 +312,7 @@ typedef struct drm_mga_dma_bootstrap { */ /*@{ */ unsigned long texture_handle; /**< Handle used to map AGP textures. */ - uint32_t texture_size; /**< Size of the AGP texture region. */ + __u32 texture_size; /**< Size of the AGP texture region. */ /*@} */ /** @@ -319,7 +321,7 @@ typedef struct drm_mga_dma_bootstrap { * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be * filled in with the actual AGP mode. If AGP was not available */ - uint32_t primary_size; + __u32 primary_size; /** * Requested number of secondary DMA buffers. @@ -329,7 +331,7 @@ typedef struct drm_mga_dma_bootstrap { * allocated. Particularly when PCI DMA is used, this may be * (subtantially) less than the number requested. */ - uint32_t secondary_bin_count; + __u32 secondary_bin_count; /** * Requested size of each secondary DMA buffer. @@ -338,7 +340,7 @@ typedef struct drm_mga_dma_bootstrap { * dma_mga_dma_bootstrap::secondary_bin_count, it is \b not allowed * to reduce dma_mga_dma_bootstrap::secondary_bin_size. */ - uint32_t secondary_bin_size; + __u32 secondary_bin_size; /** * Bit-wise mask of AGPSTAT2_* values. Currently only \c AGPSTAT2_1X, @@ -350,12 +352,12 @@ typedef struct drm_mga_dma_bootstrap { * filled in with the actual AGP mode. If AGP was not available * (i.e., PCI DMA was used), this value will be zero. */ - uint32_t agp_mode; + __u32 agp_mode; /** * Desired AGP GART size, measured in megabytes. */ - uint8_t agp_size; + __u8 agp_size; } drm_mga_dma_bootstrap_t; typedef struct drm_mga_clear { diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h index 73ff51f1231..72ecf67ad3e 100644 --- a/include/drm/radeon_drm.h +++ b/include/drm/radeon_drm.h @@ -33,6 +33,8 @@ #ifndef __RADEON_DRM_H__ #define __RADEON_DRM_H__ +#include + /* WARNING: If you change any of these defines, make sure to change the * defines in the X server file (radeon_sarea.h) */ @@ -722,7 +724,7 @@ typedef struct drm_radeon_irq_wait { typedef struct drm_radeon_setparam { unsigned int param; - int64_t value; + __s64 value; } drm_radeon_setparam_t; #define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */ diff --git a/include/drm/via_drm.h b/include/drm/via_drm.h index a3b5c102b06..170786e5c2f 100644 --- a/include/drm/via_drm.h +++ b/include/drm/via_drm.h @@ -24,6 +24,8 @@ #ifndef _VIA_DRM_H_ #define _VIA_DRM_H_ +#include + /* WARNING: These defines must be the same as what the Xserver uses. * if you change them, you must change the defines in the Xserver. */ @@ -114,19 +116,19 @@ #define VIA_MEM_UNKNOWN 4 typedef struct { - uint32_t offset; - uint32_t size; + __u32 offset; + __u32 size; } drm_via_agp_t; typedef struct { - uint32_t offset; - uint32_t size; + __u32 offset; + __u32 size; } drm_via_fb_t; typedef struct { - uint32_t context; - uint32_t type; - uint32_t size; + __u32 context; + __u32 type; + __u32 size; unsigned long index; unsigned long offset; } drm_via_mem_t; @@ -148,9 +150,9 @@ typedef struct _drm_via_futex { VIA_FUTEX_WAIT = 0x00, VIA_FUTEX_WAKE = 0X01 } func; - uint32_t ms; - uint32_t lock; - uint32_t val; + __u32 ms; + __u32 lock; + __u32 val; } drm_via_futex_t; typedef struct _drm_via_dma_init { @@ -211,7 +213,7 @@ typedef struct _drm_via_cmdbuf_size { VIA_CMDBUF_LAG = 0x02 } func; int wait; - uint32_t size; + __u32 size; } drm_via_cmdbuf_size_t; typedef enum { @@ -236,8 +238,8 @@ enum drm_via_irqs { struct drm_via_wait_irq_request { unsigned irq; via_irq_seq_type_t type; - uint32_t sequence; - uint32_t signal; + __u32 sequence; + __u32 signal; }; typedef union drm_via_irqwait { @@ -246,7 +248,7 @@ typedef union drm_via_irqwait { } drm_via_irqwait_t; typedef struct drm_via_blitsync { - uint32_t sync_handle; + __u32 sync_handle; unsigned engine; } drm_via_blitsync_t; @@ -257,16 +259,16 @@ typedef struct drm_via_blitsync { */ typedef struct drm_via_dmablit { - uint32_t num_lines; - uint32_t line_length; + __u32 num_lines; + __u32 line_length; - uint32_t fb_addr; - uint32_t fb_stride; + __u32 fb_addr; + __u32 fb_stride; unsigned char *mem_addr; - uint32_t mem_stride; + __u32 mem_stride; - uint32_t flags; + __u32 flags; int to_fb; drm_via_blitsync_t sync; -- GitLab From 60c195c729532815c5209c81442fa0eb26ace706 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 26 Feb 2009 00:51:43 +0100 Subject: [PATCH 4696/4982] make netfilter use strict integer types Netfilter traditionally uses BSD integer types in its interface headers. This changes it to use the Linux strict integer types, like everyone else. Cc: netfilter-devel@vger.kernel.org Signed-off-by: Arnd Bergmann Acked-by: David S. Miller Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- include/linux/netfilter/nf_conntrack_tcp.h | 6 ++-- include/linux/netfilter/nfnetlink.h | 4 +-- include/linux/netfilter/nfnetlink_compat.h | 7 +++-- include/linux/netfilter/nfnetlink_log.h | 32 +++++++++---------- include/linux/netfilter/nfnetlink_queue.h | 24 +++++++-------- include/linux/netfilter/x_tables.h | 30 +++++++++--------- include/linux/netfilter/xt_CLASSIFY.h | 4 ++- include/linux/netfilter/xt_CONNMARK.h | 8 +++-- include/linux/netfilter/xt_CONNSECMARK.h | 4 ++- include/linux/netfilter/xt_DSCP.h | 7 +++-- include/linux/netfilter/xt_MARK.h | 6 ++-- include/linux/netfilter/xt_NFLOG.h | 12 +++++--- include/linux/netfilter/xt_NFQUEUE.h | 4 ++- include/linux/netfilter/xt_RATEEST.h | 6 ++-- include/linux/netfilter/xt_SECMARK.h | 6 ++-- include/linux/netfilter/xt_TCPMSS.h | 4 ++- include/linux/netfilter/xt_connbytes.h | 6 ++-- include/linux/netfilter/xt_connmark.h | 8 +++-- include/linux/netfilter/xt_conntrack.h | 12 ++++---- include/linux/netfilter/xt_dccp.h | 14 +++++---- include/linux/netfilter/xt_dscp.h | 12 +++++--- include/linux/netfilter/xt_esp.h | 6 ++-- include/linux/netfilter/xt_hashlimit.h | 32 ++++++++++--------- include/linux/netfilter/xt_iprange.h | 4 ++- include/linux/netfilter/xt_length.h | 6 ++-- include/linux/netfilter/xt_limit.h | 10 +++--- include/linux/netfilter/xt_mark.h | 8 +++-- include/linux/netfilter/xt_multiport.h | 18 ++++++----- include/linux/netfilter/xt_owner.h | 8 +++-- include/linux/netfilter/xt_physdev.h | 6 ++-- include/linux/netfilter/xt_policy.h | 14 +++++---- include/linux/netfilter/xt_rateest.h | 14 +++++---- include/linux/netfilter/xt_realm.h | 8 +++-- include/linux/netfilter/xt_recent.h | 12 +++++--- include/linux/netfilter/xt_sctp.h | 36 ++++++++++++---------- include/linux/netfilter/xt_statistic.h | 14 +++++---- include/linux/netfilter/xt_string.h | 12 +++++--- include/linux/netfilter/xt_tcpmss.h | 6 ++-- include/linux/netfilter/xt_tcpudp.h | 20 ++++++------ 39 files changed, 260 insertions(+), 190 deletions(-) diff --git a/include/linux/netfilter/nf_conntrack_tcp.h b/include/linux/netfilter/nf_conntrack_tcp.h index a049df4f223..3066789b972 100644 --- a/include/linux/netfilter/nf_conntrack_tcp.h +++ b/include/linux/netfilter/nf_conntrack_tcp.h @@ -2,6 +2,8 @@ #define _NF_CONNTRACK_TCP_H /* TCP tracking. */ +#include + /* This is exposed to userspace (ctnetlink) */ enum tcp_conntrack { TCP_CONNTRACK_NONE, @@ -34,8 +36,8 @@ enum tcp_conntrack { #define IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED 0x10 struct nf_ct_tcp_flags { - u_int8_t flags; - u_int8_t mask; + __u8 flags; + __u8 mask; }; #ifdef __KERNEL__ diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h index 7d8e0455cca..e53546cfa35 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux/netfilter/nfnetlink.h @@ -25,8 +25,8 @@ enum nfnetlink_groups { /* General form of address family dependent message. */ struct nfgenmsg { - u_int8_t nfgen_family; /* AF_xxx */ - u_int8_t version; /* nfnetlink version */ + __u8 nfgen_family; /* AF_xxx */ + __u8 version; /* nfnetlink version */ __be16 res_id; /* resource id */ }; diff --git a/include/linux/netfilter/nfnetlink_compat.h b/include/linux/netfilter/nfnetlink_compat.h index e1451760c9c..eda55cabcee 100644 --- a/include/linux/netfilter/nfnetlink_compat.h +++ b/include/linux/netfilter/nfnetlink_compat.h @@ -1,5 +1,8 @@ #ifndef _NFNETLINK_COMPAT_H #define _NFNETLINK_COMPAT_H + +#include + #ifndef __KERNEL__ /* Old nfnetlink macros for userspace */ @@ -20,8 +23,8 @@ struct nfattr { - u_int16_t nfa_len; - u_int16_t nfa_type; /* we use 15 bits for the type, and the highest + __u16 nfa_len; + __u16 nfa_type; /* we use 15 bits for the type, and the highest * bit to indicate whether the payload is nested */ }; diff --git a/include/linux/netfilter/nfnetlink_log.h b/include/linux/netfilter/nfnetlink_log.h index f661731f3cb..d3bab7a2c9b 100644 --- a/include/linux/netfilter/nfnetlink_log.h +++ b/include/linux/netfilter/nfnetlink_log.h @@ -17,14 +17,14 @@ enum nfulnl_msg_types { struct nfulnl_msg_packet_hdr { __be16 hw_protocol; /* hw protocol (network order) */ - u_int8_t hook; /* netfilter hook */ - u_int8_t _pad; + __u8 hook; /* netfilter hook */ + __u8 _pad; }; struct nfulnl_msg_packet_hw { __be16 hw_addrlen; - u_int16_t _pad; - u_int8_t hw_addr[8]; + __u16 _pad; + __u8 hw_addr[8]; }; struct nfulnl_msg_packet_timestamp { @@ -35,12 +35,12 @@ struct nfulnl_msg_packet_timestamp { enum nfulnl_attr_type { NFULA_UNSPEC, NFULA_PACKET_HDR, - NFULA_MARK, /* u_int32_t nfmark */ + NFULA_MARK, /* __u32 nfmark */ NFULA_TIMESTAMP, /* nfulnl_msg_packet_timestamp */ - NFULA_IFINDEX_INDEV, /* u_int32_t ifindex */ - NFULA_IFINDEX_OUTDEV, /* u_int32_t ifindex */ - NFULA_IFINDEX_PHYSINDEV, /* u_int32_t ifindex */ - NFULA_IFINDEX_PHYSOUTDEV, /* u_int32_t ifindex */ + NFULA_IFINDEX_INDEV, /* __u32 ifindex */ + NFULA_IFINDEX_OUTDEV, /* __u32 ifindex */ + NFULA_IFINDEX_PHYSINDEV, /* __u32 ifindex */ + NFULA_IFINDEX_PHYSOUTDEV, /* __u32 ifindex */ NFULA_HWADDR, /* nfulnl_msg_packet_hw */ NFULA_PAYLOAD, /* opaque data payload */ NFULA_PREFIX, /* string prefix */ @@ -65,23 +65,23 @@ enum nfulnl_msg_config_cmds { }; struct nfulnl_msg_config_cmd { - u_int8_t command; /* nfulnl_msg_config_cmds */ + __u8 command; /* nfulnl_msg_config_cmds */ } __attribute__ ((packed)); struct nfulnl_msg_config_mode { __be32 copy_range; - u_int8_t copy_mode; - u_int8_t _pad; + __u8 copy_mode; + __u8 _pad; } __attribute__ ((packed)); enum nfulnl_attr_config { NFULA_CFG_UNSPEC, NFULA_CFG_CMD, /* nfulnl_msg_config_cmd */ NFULA_CFG_MODE, /* nfulnl_msg_config_mode */ - NFULA_CFG_NLBUFSIZ, /* u_int32_t buffer size */ - NFULA_CFG_TIMEOUT, /* u_int32_t in 1/100 s */ - NFULA_CFG_QTHRESH, /* u_int32_t */ - NFULA_CFG_FLAGS, /* u_int16_t */ + NFULA_CFG_NLBUFSIZ, /* __u32 buffer size */ + NFULA_CFG_TIMEOUT, /* __u32 in 1/100 s */ + NFULA_CFG_QTHRESH, /* __u32 */ + NFULA_CFG_FLAGS, /* __u16 */ __NFULA_CFG_MAX }; #define NFULA_CFG_MAX (__NFULA_CFG_MAX -1) diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h index 83e789633e3..2455fe5f4e0 100644 --- a/include/linux/netfilter/nfnetlink_queue.h +++ b/include/linux/netfilter/nfnetlink_queue.h @@ -15,13 +15,13 @@ enum nfqnl_msg_types { struct nfqnl_msg_packet_hdr { __be32 packet_id; /* unique ID of packet in queue */ __be16 hw_protocol; /* hw protocol (network order) */ - u_int8_t hook; /* netfilter hook */ + __u8 hook; /* netfilter hook */ } __attribute__ ((packed)); struct nfqnl_msg_packet_hw { __be16 hw_addrlen; - u_int16_t _pad; - u_int8_t hw_addr[8]; + __u16 _pad; + __u8 hw_addr[8]; }; struct nfqnl_msg_packet_timestamp { @@ -33,12 +33,12 @@ enum nfqnl_attr_type { NFQA_UNSPEC, NFQA_PACKET_HDR, NFQA_VERDICT_HDR, /* nfqnl_msg_verdict_hrd */ - NFQA_MARK, /* u_int32_t nfmark */ + NFQA_MARK, /* __u32 nfmark */ NFQA_TIMESTAMP, /* nfqnl_msg_packet_timestamp */ - NFQA_IFINDEX_INDEV, /* u_int32_t ifindex */ - NFQA_IFINDEX_OUTDEV, /* u_int32_t ifindex */ - NFQA_IFINDEX_PHYSINDEV, /* u_int32_t ifindex */ - NFQA_IFINDEX_PHYSOUTDEV, /* u_int32_t ifindex */ + NFQA_IFINDEX_INDEV, /* __u32 ifindex */ + NFQA_IFINDEX_OUTDEV, /* __u32 ifindex */ + NFQA_IFINDEX_PHYSINDEV, /* __u32 ifindex */ + NFQA_IFINDEX_PHYSOUTDEV, /* __u32 ifindex */ NFQA_HWADDR, /* nfqnl_msg_packet_hw */ NFQA_PAYLOAD, /* opaque data payload */ @@ -61,8 +61,8 @@ enum nfqnl_msg_config_cmds { }; struct nfqnl_msg_config_cmd { - u_int8_t command; /* nfqnl_msg_config_cmds */ - u_int8_t _pad; + __u8 command; /* nfqnl_msg_config_cmds */ + __u8 _pad; __be16 pf; /* AF_xxx for PF_[UN]BIND */ }; @@ -74,7 +74,7 @@ enum nfqnl_config_mode { struct nfqnl_msg_config_params { __be32 copy_range; - u_int8_t copy_mode; /* enum nfqnl_config_mode */ + __u8 copy_mode; /* enum nfqnl_config_mode */ } __attribute__ ((packed)); @@ -82,7 +82,7 @@ enum nfqnl_attr_config { NFQA_CFG_UNSPEC, NFQA_CFG_CMD, /* nfqnl_msg_config_cmd */ NFQA_CFG_PARAMS, /* nfqnl_msg_config_params */ - NFQA_CFG_QUEUE_MAXLEN, /* u_int32_t */ + NFQA_CFG_QUEUE_MAXLEN, /* __u32 */ __NFQA_CFG_MAX }; #define NFQA_CFG_MAX (__NFQA_CFG_MAX-1) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index c7ee8744d26..33fd9c949d8 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -1,6 +1,8 @@ #ifndef _X_TABLES_H #define _X_TABLES_H +#include + #define XT_FUNCTION_MAXNAMELEN 30 #define XT_TABLE_MAXNAMELEN 32 @@ -8,22 +10,22 @@ struct xt_entry_match { union { struct { - u_int16_t match_size; + __u16 match_size; /* Used by userspace */ char name[XT_FUNCTION_MAXNAMELEN-1]; - u_int8_t revision; + __u8 revision; } user; struct { - u_int16_t match_size; + __u16 match_size; /* Used inside the kernel */ struct xt_match *match; } kernel; /* Total length */ - u_int16_t match_size; + __u16 match_size; } u; unsigned char data[0]; @@ -33,22 +35,22 @@ struct xt_entry_target { union { struct { - u_int16_t target_size; + __u16 target_size; /* Used by userspace */ char name[XT_FUNCTION_MAXNAMELEN-1]; - u_int8_t revision; + __u8 revision; } user; struct { - u_int16_t target_size; + __u16 target_size; /* Used inside the kernel */ struct xt_target *target; } kernel; /* Total length */ - u_int16_t target_size; + __u16 target_size; } u; unsigned char data[0]; @@ -74,7 +76,7 @@ struct xt_get_revision { char name[XT_FUNCTION_MAXNAMELEN-1]; - u_int8_t revision; + __u8 revision; }; /* CONTINUE verdict for targets */ @@ -90,10 +92,10 @@ struct xt_get_revision */ struct _xt_align { - u_int8_t u8; - u_int16_t u16; - u_int32_t u32; - u_int64_t u64; + __u8 u8; + __u16 u16; + __u32 u32; + __u64 u64; }; #define XT_ALIGN(s) (((s) + (__alignof__(struct _xt_align)-1)) \ @@ -109,7 +111,7 @@ struct _xt_align struct xt_counters { - u_int64_t pcnt, bcnt; /* Packet and byte counters */ + __u64 pcnt, bcnt; /* Packet and byte counters */ }; /* The argument to IPT_SO_ADD_COUNTERS. */ diff --git a/include/linux/netfilter/xt_CLASSIFY.h b/include/linux/netfilter/xt_CLASSIFY.h index 58111355255..a813bf14dd6 100644 --- a/include/linux/netfilter/xt_CLASSIFY.h +++ b/include/linux/netfilter/xt_CLASSIFY.h @@ -1,8 +1,10 @@ #ifndef _XT_CLASSIFY_H #define _XT_CLASSIFY_H +#include + struct xt_classify_target_info { - u_int32_t priority; + __u32 priority; }; #endif /*_XT_CLASSIFY_H */ diff --git a/include/linux/netfilter/xt_CONNMARK.h b/include/linux/netfilter/xt_CONNMARK.h index 4e58ba43c28..7635c8ffdad 100644 --- a/include/linux/netfilter/xt_CONNMARK.h +++ b/include/linux/netfilter/xt_CONNMARK.h @@ -1,6 +1,8 @@ #ifndef _XT_CONNMARK_H_target #define _XT_CONNMARK_H_target +#include + /* Copyright (C) 2002,2004 MARA Systems AB * by Henrik Nordstrom * @@ -19,12 +21,12 @@ enum { struct xt_connmark_target_info { unsigned long mark; unsigned long mask; - u_int8_t mode; + __u8 mode; }; struct xt_connmark_tginfo1 { - u_int32_t ctmark, ctmask, nfmask; - u_int8_t mode; + __u32 ctmark, ctmask, nfmask; + __u8 mode; }; #endif /*_XT_CONNMARK_H_target*/ diff --git a/include/linux/netfilter/xt_CONNSECMARK.h b/include/linux/netfilter/xt_CONNSECMARK.h index c6bd75469ba..b973ff80fa1 100644 --- a/include/linux/netfilter/xt_CONNSECMARK.h +++ b/include/linux/netfilter/xt_CONNSECMARK.h @@ -1,13 +1,15 @@ #ifndef _XT_CONNSECMARK_H_target #define _XT_CONNSECMARK_H_target +#include + enum { CONNSECMARK_SAVE = 1, CONNSECMARK_RESTORE, }; struct xt_connsecmark_target_info { - u_int8_t mode; + __u8 mode; }; #endif /*_XT_CONNSECMARK_H_target */ diff --git a/include/linux/netfilter/xt_DSCP.h b/include/linux/netfilter/xt_DSCP.h index 14da1968e2c..648e0b3bed2 100644 --- a/include/linux/netfilter/xt_DSCP.h +++ b/include/linux/netfilter/xt_DSCP.h @@ -11,15 +11,16 @@ #ifndef _XT_DSCP_TARGET_H #define _XT_DSCP_TARGET_H #include +#include /* target info */ struct xt_DSCP_info { - u_int8_t dscp; + __u8 dscp; }; struct xt_tos_target_info { - u_int8_t tos_value; - u_int8_t tos_mask; + __u8 tos_value; + __u8 tos_mask; }; #endif /* _XT_DSCP_TARGET_H */ diff --git a/include/linux/netfilter/xt_MARK.h b/include/linux/netfilter/xt_MARK.h index 778b278fd9f..028304bcc0b 100644 --- a/include/linux/netfilter/xt_MARK.h +++ b/include/linux/netfilter/xt_MARK.h @@ -1,6 +1,8 @@ #ifndef _XT_MARK_H_target #define _XT_MARK_H_target +#include + /* Version 0 */ struct xt_mark_target_info { unsigned long mark; @@ -15,11 +17,11 @@ enum { struct xt_mark_target_info_v1 { unsigned long mark; - u_int8_t mode; + __u8 mode; }; struct xt_mark_tginfo2 { - u_int32_t mark, mask; + __u32 mark, mask; }; #endif /*_XT_MARK_H_target */ diff --git a/include/linux/netfilter/xt_NFLOG.h b/include/linux/netfilter/xt_NFLOG.h index cdcd0ed58f7..eaac7b5226e 100644 --- a/include/linux/netfilter/xt_NFLOG.h +++ b/include/linux/netfilter/xt_NFLOG.h @@ -1,17 +1,19 @@ #ifndef _XT_NFLOG_TARGET #define _XT_NFLOG_TARGET +#include + #define XT_NFLOG_DEFAULT_GROUP 0x1 #define XT_NFLOG_DEFAULT_THRESHOLD 1 #define XT_NFLOG_MASK 0x0 struct xt_nflog_info { - u_int32_t len; - u_int16_t group; - u_int16_t threshold; - u_int16_t flags; - u_int16_t pad; + __u32 len; + __u16 group; + __u16 threshold; + __u16 flags; + __u16 pad; char prefix[64]; }; diff --git a/include/linux/netfilter/xt_NFQUEUE.h b/include/linux/netfilter/xt_NFQUEUE.h index 9a9af79f74d..982a89f7827 100644 --- a/include/linux/netfilter/xt_NFQUEUE.h +++ b/include/linux/netfilter/xt_NFQUEUE.h @@ -8,9 +8,11 @@ #ifndef _XT_NFQ_TARGET_H #define _XT_NFQ_TARGET_H +#include + /* target info */ struct xt_NFQ_info { - u_int16_t queuenum; + __u16 queuenum; }; #endif /* _XT_NFQ_TARGET_H */ diff --git a/include/linux/netfilter/xt_RATEEST.h b/include/linux/netfilter/xt_RATEEST.h index f79e3133cbe..6605e20ad8c 100644 --- a/include/linux/netfilter/xt_RATEEST.h +++ b/include/linux/netfilter/xt_RATEEST.h @@ -1,10 +1,12 @@ #ifndef _XT_RATEEST_TARGET_H #define _XT_RATEEST_TARGET_H +#include + struct xt_rateest_target_info { char name[IFNAMSIZ]; - int8_t interval; - u_int8_t ewma_log; + __s8 interval; + __u8 ewma_log; /* Used internally by the kernel */ struct xt_rateest *est __attribute__((aligned(8))); diff --git a/include/linux/netfilter/xt_SECMARK.h b/include/linux/netfilter/xt_SECMARK.h index c53fbffa997..6fcd3448b18 100644 --- a/include/linux/netfilter/xt_SECMARK.h +++ b/include/linux/netfilter/xt_SECMARK.h @@ -1,6 +1,8 @@ #ifndef _XT_SECMARK_H_target #define _XT_SECMARK_H_target +#include + /* * This is intended for use by various security subsystems (but not * at the same time). @@ -12,12 +14,12 @@ #define SECMARK_SELCTX_MAX 256 struct xt_secmark_target_selinux_info { - u_int32_t selsid; + __u32 selsid; char selctx[SECMARK_SELCTX_MAX]; }; struct xt_secmark_target_info { - u_int8_t mode; + __u8 mode; union { struct xt_secmark_target_selinux_info sel; } u; diff --git a/include/linux/netfilter/xt_TCPMSS.h b/include/linux/netfilter/xt_TCPMSS.h index 53a292cd47f..9a6960afc13 100644 --- a/include/linux/netfilter/xt_TCPMSS.h +++ b/include/linux/netfilter/xt_TCPMSS.h @@ -1,8 +1,10 @@ #ifndef _XT_TCPMSS_H #define _XT_TCPMSS_H +#include + struct xt_tcpmss_info { - u_int16_t mss; + __u16 mss; }; #define XT_TCPMSS_CLAMP_PMTU 0xffff diff --git a/include/linux/netfilter/xt_connbytes.h b/include/linux/netfilter/xt_connbytes.h index c022c989754..52bd6153b99 100644 --- a/include/linux/netfilter/xt_connbytes.h +++ b/include/linux/netfilter/xt_connbytes.h @@ -1,6 +1,8 @@ #ifndef _XT_CONNBYTES_H #define _XT_CONNBYTES_H +#include + enum xt_connbytes_what { XT_CONNBYTES_PKTS, XT_CONNBYTES_BYTES, @@ -19,7 +21,7 @@ struct xt_connbytes_info aligned_u64 from; /* count to be matched */ aligned_u64 to; /* count to be matched */ } count; - u_int8_t what; /* ipt_connbytes_what */ - u_int8_t direction; /* ipt_connbytes_direction */ + __u8 what; /* ipt_connbytes_what */ + __u8 direction; /* ipt_connbytes_direction */ }; #endif diff --git a/include/linux/netfilter/xt_connmark.h b/include/linux/netfilter/xt_connmark.h index 359ef86918d..571e266d004 100644 --- a/include/linux/netfilter/xt_connmark.h +++ b/include/linux/netfilter/xt_connmark.h @@ -1,6 +1,8 @@ #ifndef _XT_CONNMARK_H #define _XT_CONNMARK_H +#include + /* Copyright (C) 2002,2004 MARA Systems AB * by Henrik Nordstrom * @@ -12,12 +14,12 @@ struct xt_connmark_info { unsigned long mark, mask; - u_int8_t invert; + __u8 invert; }; struct xt_connmark_mtinfo1 { - u_int32_t mark, mask; - u_int8_t invert; + __u32 mark, mask; + __u8 invert; }; #endif /*_XT_CONNMARK_H*/ diff --git a/include/linux/netfilter/xt_conntrack.h b/include/linux/netfilter/xt_conntrack.h index 8f534527539..3430c775194 100644 --- a/include/linux/netfilter/xt_conntrack.h +++ b/include/linux/netfilter/xt_conntrack.h @@ -63,9 +63,9 @@ struct xt_conntrack_info unsigned long expires_min, expires_max; /* Flags word */ - u_int8_t flags; + __u8 flags; /* Inverse flags */ - u_int8_t invflags; + __u8 invflags; }; struct xt_conntrack_mtinfo1 { @@ -73,12 +73,12 @@ struct xt_conntrack_mtinfo1 { union nf_inet_addr origdst_addr, origdst_mask; union nf_inet_addr replsrc_addr, replsrc_mask; union nf_inet_addr repldst_addr, repldst_mask; - u_int32_t expires_min, expires_max; - u_int16_t l4proto; + __u32 expires_min, expires_max; + __u16 l4proto; __be16 origsrc_port, origdst_port; __be16 replsrc_port, repldst_port; - u_int16_t match_flags, invert_flags; - u_int8_t state_mask, status_mask; + __u16 match_flags, invert_flags; + __u8 state_mask, status_mask; }; #endif /*_XT_CONNTRACK_H*/ diff --git a/include/linux/netfilter/xt_dccp.h b/include/linux/netfilter/xt_dccp.h index e0221b9d32c..a579e1b6f04 100644 --- a/include/linux/netfilter/xt_dccp.h +++ b/include/linux/netfilter/xt_dccp.h @@ -1,6 +1,8 @@ #ifndef _XT_DCCP_H_ #define _XT_DCCP_H_ +#include + #define XT_DCCP_SRC_PORTS 0x01 #define XT_DCCP_DEST_PORTS 0x02 #define XT_DCCP_TYPE 0x04 @@ -9,14 +11,14 @@ #define XT_DCCP_VALID_FLAGS 0x0f struct xt_dccp_info { - u_int16_t dpts[2]; /* Min, Max */ - u_int16_t spts[2]; /* Min, Max */ + __u16 dpts[2]; /* Min, Max */ + __u16 spts[2]; /* Min, Max */ - u_int16_t flags; - u_int16_t invflags; + __u16 flags; + __u16 invflags; - u_int16_t typemask; - u_int8_t option; + __u16 typemask; + __u8 option; }; #endif /* _XT_DCCP_H_ */ diff --git a/include/linux/netfilter/xt_dscp.h b/include/linux/netfilter/xt_dscp.h index f49bc1a648d..15f8932ad5c 100644 --- a/include/linux/netfilter/xt_dscp.h +++ b/include/linux/netfilter/xt_dscp.h @@ -10,20 +10,22 @@ #ifndef _XT_DSCP_H #define _XT_DSCP_H +#include + #define XT_DSCP_MASK 0xfc /* 11111100 */ #define XT_DSCP_SHIFT 2 #define XT_DSCP_MAX 0x3f /* 00111111 */ /* match info */ struct xt_dscp_info { - u_int8_t dscp; - u_int8_t invert; + __u8 dscp; + __u8 invert; }; struct xt_tos_match_info { - u_int8_t tos_mask; - u_int8_t tos_value; - u_int8_t invert; + __u8 tos_mask; + __u8 tos_value; + __u8 invert; }; #endif /* _XT_DSCP_H */ diff --git a/include/linux/netfilter/xt_esp.h b/include/linux/netfilter/xt_esp.h index 9380fb1c27d..ef6fa4747d0 100644 --- a/include/linux/netfilter/xt_esp.h +++ b/include/linux/netfilter/xt_esp.h @@ -1,10 +1,12 @@ #ifndef _XT_ESP_H #define _XT_ESP_H +#include + struct xt_esp { - u_int32_t spis[2]; /* Security Parameter Index */ - u_int8_t invflags; /* Inverse flags */ + __u32 spis[2]; /* Security Parameter Index */ + __u8 invflags; /* Inverse flags */ }; /* Values for "invflags" field in struct xt_esp. */ diff --git a/include/linux/netfilter/xt_hashlimit.h b/include/linux/netfilter/xt_hashlimit.h index 51b18d83b47..b1925b5925e 100644 --- a/include/linux/netfilter/xt_hashlimit.h +++ b/include/linux/netfilter/xt_hashlimit.h @@ -1,6 +1,8 @@ #ifndef _XT_HASHLIMIT_H #define _XT_HASHLIMIT_H +#include + /* timings are in milliseconds. */ #define XT_HASHLIMIT_SCALE 10000 /* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490 @@ -18,15 +20,15 @@ enum { }; struct hashlimit_cfg { - u_int32_t mode; /* bitmask of XT_HASHLIMIT_HASH_* */ - u_int32_t avg; /* Average secs between packets * scale */ - u_int32_t burst; /* Period multiplier for upper limit. */ + __u32 mode; /* bitmask of XT_HASHLIMIT_HASH_* */ + __u32 avg; /* Average secs between packets * scale */ + __u32 burst; /* Period multiplier for upper limit. */ /* user specified */ - u_int32_t size; /* how many buckets */ - u_int32_t max; /* max number of entries */ - u_int32_t gc_interval; /* gc interval */ - u_int32_t expire; /* when do entries expire? */ + __u32 size; /* how many buckets */ + __u32 max; /* max number of entries */ + __u32 gc_interval; /* gc interval */ + __u32 expire; /* when do entries expire? */ }; struct xt_hashlimit_info { @@ -42,17 +44,17 @@ struct xt_hashlimit_info { }; struct hashlimit_cfg1 { - u_int32_t mode; /* bitmask of XT_HASHLIMIT_HASH_* */ - u_int32_t avg; /* Average secs between packets * scale */ - u_int32_t burst; /* Period multiplier for upper limit. */ + __u32 mode; /* bitmask of XT_HASHLIMIT_HASH_* */ + __u32 avg; /* Average secs between packets * scale */ + __u32 burst; /* Period multiplier for upper limit. */ /* user specified */ - u_int32_t size; /* how many buckets */ - u_int32_t max; /* max number of entries */ - u_int32_t gc_interval; /* gc interval */ - u_int32_t expire; /* when do entries expire? */ + __u32 size; /* how many buckets */ + __u32 max; /* max number of entries */ + __u32 gc_interval; /* gc interval */ + __u32 expire; /* when do entries expire? */ - u_int8_t srcmask, dstmask; + __u8 srcmask, dstmask; }; struct xt_hashlimit_mtinfo1 { diff --git a/include/linux/netfilter/xt_iprange.h b/include/linux/netfilter/xt_iprange.h index a4299c7d368..c1f21a779a4 100644 --- a/include/linux/netfilter/xt_iprange.h +++ b/include/linux/netfilter/xt_iprange.h @@ -1,6 +1,8 @@ #ifndef _LINUX_NETFILTER_XT_IPRANGE_H #define _LINUX_NETFILTER_XT_IPRANGE_H 1 +#include + enum { IPRANGE_SRC = 1 << 0, /* match source IP address */ IPRANGE_DST = 1 << 1, /* match destination IP address */ @@ -11,7 +13,7 @@ enum { struct xt_iprange_mtinfo { union nf_inet_addr src_min, src_max; union nf_inet_addr dst_min, dst_max; - u_int8_t flags; + __u8 flags; }; #endif /* _LINUX_NETFILTER_XT_IPRANGE_H */ diff --git a/include/linux/netfilter/xt_length.h b/include/linux/netfilter/xt_length.h index 7c2b439f73f..b82ed7c4b1e 100644 --- a/include/linux/netfilter/xt_length.h +++ b/include/linux/netfilter/xt_length.h @@ -1,9 +1,11 @@ #ifndef _XT_LENGTH_H #define _XT_LENGTH_H +#include + struct xt_length_info { - u_int16_t min, max; - u_int8_t invert; + __u16 min, max; + __u8 invert; }; #endif /*_XT_LENGTH_H*/ diff --git a/include/linux/netfilter/xt_limit.h b/include/linux/netfilter/xt_limit.h index b3ce65375ec..190e98b1f7c 100644 --- a/include/linux/netfilter/xt_limit.h +++ b/include/linux/netfilter/xt_limit.h @@ -1,19 +1,21 @@ #ifndef _XT_RATE_H #define _XT_RATE_H +#include + /* timings are in milliseconds. */ #define XT_LIMIT_SCALE 10000 /* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490 seconds, or one every 59 hours. */ struct xt_rateinfo { - u_int32_t avg; /* Average secs between packets * scale */ - u_int32_t burst; /* Period multiplier for upper limit. */ + __u32 avg; /* Average secs between packets * scale */ + __u32 burst; /* Period multiplier for upper limit. */ /* Used internally by the kernel */ unsigned long prev; - u_int32_t credit; - u_int32_t credit_cap, cost; + __u32 credit; + __u32 credit_cap, cost; /* Ugly, ugly fucker. */ struct xt_rateinfo *master; diff --git a/include/linux/netfilter/xt_mark.h b/include/linux/netfilter/xt_mark.h index fae74bc3f34..6fa460a3cc2 100644 --- a/include/linux/netfilter/xt_mark.h +++ b/include/linux/netfilter/xt_mark.h @@ -1,14 +1,16 @@ #ifndef _XT_MARK_H #define _XT_MARK_H +#include + struct xt_mark_info { unsigned long mark, mask; - u_int8_t invert; + __u8 invert; }; struct xt_mark_mtinfo1 { - u_int32_t mark, mask; - u_int8_t invert; + __u32 mark, mask; + __u8 invert; }; #endif /*_XT_MARK_H*/ diff --git a/include/linux/netfilter/xt_multiport.h b/include/linux/netfilter/xt_multiport.h index d49ee418371..185db499fcb 100644 --- a/include/linux/netfilter/xt_multiport.h +++ b/include/linux/netfilter/xt_multiport.h @@ -1,6 +1,8 @@ #ifndef _XT_MULTIPORT_H #define _XT_MULTIPORT_H +#include + enum xt_multiport_flags { XT_MULTIPORT_SOURCE, @@ -13,18 +15,18 @@ enum xt_multiport_flags /* Must fit inside union xt_matchinfo: 16 bytes */ struct xt_multiport { - u_int8_t flags; /* Type of comparison */ - u_int8_t count; /* Number of ports */ - u_int16_t ports[XT_MULTI_PORTS]; /* Ports */ + __u8 flags; /* Type of comparison */ + __u8 count; /* Number of ports */ + __u16 ports[XT_MULTI_PORTS]; /* Ports */ }; struct xt_multiport_v1 { - u_int8_t flags; /* Type of comparison */ - u_int8_t count; /* Number of ports */ - u_int16_t ports[XT_MULTI_PORTS]; /* Ports */ - u_int8_t pflags[XT_MULTI_PORTS]; /* Port flags */ - u_int8_t invert; /* Invert flag */ + __u8 flags; /* Type of comparison */ + __u8 count; /* Number of ports */ + __u16 ports[XT_MULTI_PORTS]; /* Ports */ + __u8 pflags[XT_MULTI_PORTS]; /* Port flags */ + __u8 invert; /* Invert flag */ }; #endif /*_XT_MULTIPORT_H*/ diff --git a/include/linux/netfilter/xt_owner.h b/include/linux/netfilter/xt_owner.h index c84e52cfe41..2081761714b 100644 --- a/include/linux/netfilter/xt_owner.h +++ b/include/linux/netfilter/xt_owner.h @@ -1,6 +1,8 @@ #ifndef _XT_OWNER_MATCH_H #define _XT_OWNER_MATCH_H +#include + enum { XT_OWNER_UID = 1 << 0, XT_OWNER_GID = 1 << 1, @@ -8,9 +10,9 @@ enum { }; struct xt_owner_match_info { - u_int32_t uid_min, uid_max; - u_int32_t gid_min, gid_max; - u_int8_t match, invert; + __u32 uid_min, uid_max; + __u32 gid_min, gid_max; + __u8 match, invert; }; #endif /* _XT_OWNER_MATCH_H */ diff --git a/include/linux/netfilter/xt_physdev.h b/include/linux/netfilter/xt_physdev.h index 25a7a1815b5..8555e399886 100644 --- a/include/linux/netfilter/xt_physdev.h +++ b/include/linux/netfilter/xt_physdev.h @@ -1,6 +1,8 @@ #ifndef _XT_PHYSDEV_H #define _XT_PHYSDEV_H +#include + #ifdef __KERNEL__ #include #endif @@ -17,8 +19,8 @@ struct xt_physdev_info { char in_mask[IFNAMSIZ]; char physoutdev[IFNAMSIZ]; char out_mask[IFNAMSIZ]; - u_int8_t invert; - u_int8_t bitmask; + __u8 invert; + __u8 bitmask; }; #endif /*_XT_PHYSDEV_H*/ diff --git a/include/linux/netfilter/xt_policy.h b/include/linux/netfilter/xt_policy.h index 053d8cc6546..7bb64e7c853 100644 --- a/include/linux/netfilter/xt_policy.h +++ b/include/linux/netfilter/xt_policy.h @@ -1,6 +1,8 @@ #ifndef _XT_POLICY_H #define _XT_POLICY_H +#include + #define XT_POLICY_MAX_ELEM 4 enum xt_policy_flags @@ -19,7 +21,7 @@ enum xt_policy_modes struct xt_policy_spec { - u_int8_t saddr:1, + __u8 saddr:1, daddr:1, proto:1, mode:1, @@ -55,9 +57,9 @@ struct xt_policy_elem #endif }; __be32 spi; - u_int32_t reqid; - u_int8_t proto; - u_int8_t mode; + __u32 reqid; + __u8 proto; + __u8 mode; struct xt_policy_spec match; struct xt_policy_spec invert; @@ -66,8 +68,8 @@ struct xt_policy_elem struct xt_policy_info { struct xt_policy_elem pol[XT_POLICY_MAX_ELEM]; - u_int16_t flags; - u_int16_t len; + __u16 flags; + __u16 len; }; #endif /* _XT_POLICY_H */ diff --git a/include/linux/netfilter/xt_rateest.h b/include/linux/netfilter/xt_rateest.h index 2010cb74250..d40a6196842 100644 --- a/include/linux/netfilter/xt_rateest.h +++ b/include/linux/netfilter/xt_rateest.h @@ -1,6 +1,8 @@ #ifndef _XT_RATEEST_MATCH_H #define _XT_RATEEST_MATCH_H +#include + enum xt_rateest_match_flags { XT_RATEEST_MATCH_INVERT = 1<<0, XT_RATEEST_MATCH_ABS = 1<<1, @@ -20,12 +22,12 @@ enum xt_rateest_match_mode { struct xt_rateest_match_info { char name1[IFNAMSIZ]; char name2[IFNAMSIZ]; - u_int16_t flags; - u_int16_t mode; - u_int32_t bps1; - u_int32_t pps1; - u_int32_t bps2; - u_int32_t pps2; + __u16 flags; + __u16 mode; + __u32 bps1; + __u32 pps1; + __u32 bps2; + __u32 pps2; /* Used internally by the kernel */ struct xt_rateest *est1 __attribute__((aligned(8))); diff --git a/include/linux/netfilter/xt_realm.h b/include/linux/netfilter/xt_realm.h index 220e8724571..d4a82ee56a0 100644 --- a/include/linux/netfilter/xt_realm.h +++ b/include/linux/netfilter/xt_realm.h @@ -1,10 +1,12 @@ #ifndef _XT_REALM_H #define _XT_REALM_H +#include + struct xt_realm_info { - u_int32_t id; - u_int32_t mask; - u_int8_t invert; + __u32 id; + __u32 mask; + __u8 invert; }; #endif /* _XT_REALM_H */ diff --git a/include/linux/netfilter/xt_recent.h b/include/linux/netfilter/xt_recent.h index 5cfeb81c679..d2c27660992 100644 --- a/include/linux/netfilter/xt_recent.h +++ b/include/linux/netfilter/xt_recent.h @@ -1,6 +1,8 @@ #ifndef _LINUX_NETFILTER_XT_RECENT_H #define _LINUX_NETFILTER_XT_RECENT_H 1 +#include + enum { XT_RECENT_CHECK = 1 << 0, XT_RECENT_SET = 1 << 1, @@ -15,12 +17,12 @@ enum { }; struct xt_recent_mtinfo { - u_int32_t seconds; - u_int32_t hit_count; - u_int8_t check_set; - u_int8_t invert; + __u32 seconds; + __u32 hit_count; + __u8 check_set; + __u8 invert; char name[XT_RECENT_NAME_LEN]; - u_int8_t side; + __u8 side; }; #endif /* _LINUX_NETFILTER_XT_RECENT_H */ diff --git a/include/linux/netfilter/xt_sctp.h b/include/linux/netfilter/xt_sctp.h index 32000ba6ece..29287be696a 100644 --- a/include/linux/netfilter/xt_sctp.h +++ b/include/linux/netfilter/xt_sctp.h @@ -1,6 +1,8 @@ #ifndef _XT_SCTP_H_ #define _XT_SCTP_H_ +#include + #define XT_SCTP_SRC_PORTS 0x01 #define XT_SCTP_DEST_PORTS 0x02 #define XT_SCTP_CHUNK_TYPES 0x04 @@ -8,49 +10,49 @@ #define XT_SCTP_VALID_FLAGS 0x07 struct xt_sctp_flag_info { - u_int8_t chunktype; - u_int8_t flag; - u_int8_t flag_mask; + __u8 chunktype; + __u8 flag; + __u8 flag_mask; }; #define XT_NUM_SCTP_FLAGS 4 struct xt_sctp_info { - u_int16_t dpts[2]; /* Min, Max */ - u_int16_t spts[2]; /* Min, Max */ + __u16 dpts[2]; /* Min, Max */ + __u16 spts[2]; /* Min, Max */ - u_int32_t chunkmap[256 / sizeof (u_int32_t)]; /* Bit mask of chunks to be matched according to RFC 2960 */ + __u32 chunkmap[256 / sizeof (__u32)]; /* Bit mask of chunks to be matched according to RFC 2960 */ #define SCTP_CHUNK_MATCH_ANY 0x01 /* Match if any of the chunk types are present */ #define SCTP_CHUNK_MATCH_ALL 0x02 /* Match if all of the chunk types are present */ #define SCTP_CHUNK_MATCH_ONLY 0x04 /* Match if these are the only chunk types present */ - u_int32_t chunk_match_type; + __u32 chunk_match_type; struct xt_sctp_flag_info flag_info[XT_NUM_SCTP_FLAGS]; int flag_count; - u_int32_t flags; - u_int32_t invflags; + __u32 flags; + __u32 invflags; }; #define bytes(type) (sizeof(type) * 8) #define SCTP_CHUNKMAP_SET(chunkmap, type) \ do { \ - (chunkmap)[type / bytes(u_int32_t)] |= \ - 1 << (type % bytes(u_int32_t)); \ + (chunkmap)[type / bytes(__u32)] |= \ + 1 << (type % bytes(__u32)); \ } while (0) #define SCTP_CHUNKMAP_CLEAR(chunkmap, type) \ do { \ - (chunkmap)[type / bytes(u_int32_t)] &= \ - ~(1 << (type % bytes(u_int32_t))); \ + (chunkmap)[type / bytes(__u32)] &= \ + ~(1 << (type % bytes(__u32))); \ } while (0) #define SCTP_CHUNKMAP_IS_SET(chunkmap, type) \ ({ \ - ((chunkmap)[type / bytes (u_int32_t)] & \ - (1 << (type % bytes (u_int32_t)))) ? 1: 0; \ + ((chunkmap)[type / bytes (__u32)] & \ + (1 << (type % bytes (__u32)))) ? 1: 0; \ }) #define SCTP_CHUNKMAP_RESET(chunkmap) \ @@ -65,7 +67,7 @@ struct xt_sctp_info { #define SCTP_CHUNKMAP_IS_CLEAR(chunkmap) \ __sctp_chunkmap_is_clear((chunkmap), ARRAY_SIZE(chunkmap)) static inline bool -__sctp_chunkmap_is_clear(const u_int32_t *chunkmap, unsigned int n) +__sctp_chunkmap_is_clear(const __u32 *chunkmap, unsigned int n) { unsigned int i; for (i = 0; i < n; ++i) @@ -77,7 +79,7 @@ __sctp_chunkmap_is_clear(const u_int32_t *chunkmap, unsigned int n) #define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap) \ __sctp_chunkmap_is_all_set((chunkmap), ARRAY_SIZE(chunkmap)) static inline bool -__sctp_chunkmap_is_all_set(const u_int32_t *chunkmap, unsigned int n) +__sctp_chunkmap_is_all_set(const __u32 *chunkmap, unsigned int n) { unsigned int i; for (i = 0; i < n; ++i) diff --git a/include/linux/netfilter/xt_statistic.h b/include/linux/netfilter/xt_statistic.h index 3d38bc97504..095f3c66f45 100644 --- a/include/linux/netfilter/xt_statistic.h +++ b/include/linux/netfilter/xt_statistic.h @@ -1,6 +1,8 @@ #ifndef _XT_STATISTIC_H #define _XT_STATISTIC_H +#include + enum xt_statistic_mode { XT_STATISTIC_MODE_RANDOM, XT_STATISTIC_MODE_NTH, @@ -14,17 +16,17 @@ enum xt_statistic_flags { #define XT_STATISTIC_MASK 0x1 struct xt_statistic_info { - u_int16_t mode; - u_int16_t flags; + __u16 mode; + __u16 flags; union { struct { - u_int32_t probability; + __u32 probability; } random; struct { - u_int32_t every; - u_int32_t packet; + __u32 every; + __u32 packet; /* Used internally by the kernel */ - u_int32_t count; + __u32 count; } nth; } u; struct xt_statistic_info *master __attribute__((aligned(8))); diff --git a/include/linux/netfilter/xt_string.h b/include/linux/netfilter/xt_string.h index 8a6ba7bbef9..ecbb95fc89e 100644 --- a/include/linux/netfilter/xt_string.h +++ b/include/linux/netfilter/xt_string.h @@ -1,6 +1,8 @@ #ifndef _XT_STRING_H #define _XT_STRING_H +#include + #define XT_STRING_MAX_PATTERN_SIZE 128 #define XT_STRING_MAX_ALGO_NAME_SIZE 16 @@ -11,18 +13,18 @@ enum { struct xt_string_info { - u_int16_t from_offset; - u_int16_t to_offset; + __u16 from_offset; + __u16 to_offset; char algo[XT_STRING_MAX_ALGO_NAME_SIZE]; char pattern[XT_STRING_MAX_PATTERN_SIZE]; - u_int8_t patlen; + __u8 patlen; union { struct { - u_int8_t invert; + __u8 invert; } v0; struct { - u_int8_t flags; + __u8 flags; } v1; } u; diff --git a/include/linux/netfilter/xt_tcpmss.h b/include/linux/netfilter/xt_tcpmss.h index e03274c4c79..fbac56b9e66 100644 --- a/include/linux/netfilter/xt_tcpmss.h +++ b/include/linux/netfilter/xt_tcpmss.h @@ -1,9 +1,11 @@ #ifndef _XT_TCPMSS_MATCH_H #define _XT_TCPMSS_MATCH_H +#include + struct xt_tcpmss_match_info { - u_int16_t mss_min, mss_max; - u_int8_t invert; + __u16 mss_min, mss_max; + __u8 invert; }; #endif /*_XT_TCPMSS_MATCH_H*/ diff --git a/include/linux/netfilter/xt_tcpudp.h b/include/linux/netfilter/xt_tcpudp.h index 78bc65f11ad..a490a0bc1d2 100644 --- a/include/linux/netfilter/xt_tcpudp.h +++ b/include/linux/netfilter/xt_tcpudp.h @@ -1,15 +1,17 @@ #ifndef _XT_TCPUDP_H #define _XT_TCPUDP_H +#include + /* TCP matching stuff */ struct xt_tcp { - u_int16_t spts[2]; /* Source port range. */ - u_int16_t dpts[2]; /* Destination port range. */ - u_int8_t option; /* TCP Option iff non-zero*/ - u_int8_t flg_mask; /* TCP flags mask byte */ - u_int8_t flg_cmp; /* TCP flags compare byte */ - u_int8_t invflags; /* Inverse flags */ + __u16 spts[2]; /* Source port range. */ + __u16 dpts[2]; /* Destination port range. */ + __u8 option; /* TCP Option iff non-zero*/ + __u8 flg_mask; /* TCP flags mask byte */ + __u8 flg_cmp; /* TCP flags compare byte */ + __u8 invflags; /* Inverse flags */ }; /* Values for "inv" field in struct ipt_tcp. */ @@ -22,9 +24,9 @@ struct xt_tcp /* UDP matching stuff */ struct xt_udp { - u_int16_t spts[2]; /* Source port range. */ - u_int16_t dpts[2]; /* Destination port range. */ - u_int8_t invflags; /* Inverse flags */ + __u16 spts[2]; /* Source port range. */ + __u16 dpts[2]; /* Destination port range. */ + __u8 invflags; /* Inverse flags */ }; /* Values for "invflags" field in struct ipt_udp. */ -- GitLab From 3a471cbc081b6bf2b58a48db13d734ecd3b0d437 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 26 Feb 2009 00:51:45 +0100 Subject: [PATCH 4697/4982] remove __KERNEL_STRICT_NAMES With the last used of non-strict names gone from the exported header files, we can remove the old libc5 compatibility cruft from our headers and only export strict types. Signed-off-by: Arnd Bergmann Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- include/asm-generic/statfs.h | 5 +++-- include/linux/types.h | 13 ++----------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/include/asm-generic/statfs.h b/include/asm-generic/statfs.h index 6129d680214..3b4fb3e52f0 100644 --- a/include/asm-generic/statfs.h +++ b/include/asm-generic/statfs.h @@ -1,8 +1,9 @@ #ifndef _GENERIC_STATFS_H #define _GENERIC_STATFS_H -#ifndef __KERNEL_STRICT_NAMES -# include +#include + +#ifdef __KERNEL__ typedef __kernel_fsid_t fsid_t; #endif diff --git a/include/linux/types.h b/include/linux/types.h index fca82ed55f4..5abe354020f 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -13,7 +13,7 @@ #include -#ifndef __KERNEL_STRICT_NAMES +#ifdef __KERNEL__ typedef __u32 __kernel_dev_t; @@ -31,7 +31,6 @@ typedef __kernel_timer_t timer_t; typedef __kernel_clockid_t clockid_t; typedef __kernel_mqd_t mqd_t; -#ifdef __KERNEL__ typedef _Bool bool; typedef __kernel_uid32_t uid_t; @@ -47,14 +46,6 @@ typedef __kernel_old_uid_t old_uid_t; typedef __kernel_old_gid_t old_gid_t; #endif /* CONFIG_UID16 */ -/* libc5 includes this file to define uid_t, thus uid_t can never change - * when it is included by non-kernel code - */ -#else -typedef __kernel_uid_t uid_t; -typedef __kernel_gid_t gid_t; -#endif /* __KERNEL__ */ - #if defined(__GNUC__) typedef __kernel_loff_t loff_t; #endif @@ -156,7 +147,7 @@ typedef unsigned long blkcnt_t; #define pgoff_t unsigned long #endif -#endif /* __KERNEL_STRICT_NAMES */ +#endif /* __KERNEL__ */ /* * Below are truly Linux-specific types that should never collide with -- GitLab From 8cd2c29dd5f04d91dac6ea7f8b9df4ff1b4380ee Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 25 Feb 2009 15:22:19 -0800 Subject: [PATCH 4698/4982] compiler-gcc4: conditionalize #error on __KERNEL__ Impact: Fix for exported headers We only want to error out on specific gcc versions if we are actually building the kernel, so conditionalize the #if...#error on __KERNEL__. Based on a patchset by Arnd Bergmann . Cc: Arnd Bergmann Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- include/linux/compiler-gcc4.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h index 09992718f9e..450fa597c94 100644 --- a/include/linux/compiler-gcc4.h +++ b/include/linux/compiler-gcc4.h @@ -3,8 +3,10 @@ #endif /* GCC 4.1.[01] miscompiles __weak */ -#if __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ <= 1 -# error Your version of gcc miscompiles the __weak directive +#ifdef __KERNEL__ +# if __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ <= 1 +# error Your version of gcc miscompiles the __weak directive +# endif #endif #define __used __attribute__((__used__)) -- GitLab From f9f35677d81adb0feedcd6e0e661784805c8facd Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 26 Feb 2009 09:57:27 +0100 Subject: [PATCH 4699/4982] emu101k1.h: fix duplicate include of Impact: cleanup The earlier patch 'make most exported headers use strict integer types' accidentally includes both from the common and from the kernel-only parts. Signed-off-by: Arnd Bergmann Acked-by: Takashi Iwai Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- include/sound/emu10k1.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h index c380056ff26..6a664c3f7c1 100644 --- a/include/sound/emu10k1.h +++ b/include/sound/emu10k1.h @@ -36,7 +36,6 @@ #include #include #include -#include #include -- GitLab From 17d140402e6f0fd5dde2fdf8d045e3f95f865663 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Wed, 14 Jan 2009 23:37:50 +0300 Subject: [PATCH 4700/4982] x86: headers cleanup - setup.h Impact: cleanup 'make headers_check' warn us about leaking of kernel private (mostly compile time vars) data to userspace in headers. Fix it. Guard this one by __KERNEL__. Signed-off-by: Cyrill Gorcunov Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- arch/x86/include/asm/setup.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h index 5a3a1371575..c2308f5250f 100644 --- a/arch/x86/include/asm/setup.h +++ b/arch/x86/include/asm/setup.h @@ -1,6 +1,8 @@ #ifndef _ASM_X86_SETUP_H #define _ASM_X86_SETUP_H +#ifdef __KERNEL__ + #define COMMAND_LINE_SIZE 2048 #ifndef __ASSEMBLY__ @@ -33,8 +35,6 @@ struct x86_quirks { #endif /* __ASSEMBLY__ */ -#ifdef __KERNEL__ - #ifdef __i386__ #include -- GitLab From 11ff6f05f1e836a6a02369a4c4b64757e484adc1 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 26 Mar 2009 17:32:14 +0000 Subject: [PATCH 4701/4982] Allow relatime to update atime once a day Allow atime to be updated once per day even with relatime. This lets utilities like tmpreaper (which delete files based on last access time) continue working, making relatime a plausible default for distributions. Signed-off-by: Matthew Garrett Reviewed-by: Matthew Wilcox Acked-by: Valerie Aurora Henson Acked-by: Alan Cox Acked-by: Ingo Molnar Signed-off-by: Linus Torvalds --- fs/inode.c | 47 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/fs/inode.c b/fs/inode.c index 826fb0b9d1c..6ac0cef6c5f 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1290,6 +1290,40 @@ sector_t bmap(struct inode * inode, sector_t block) } EXPORT_SYMBOL(bmap); +/* + * With relative atime, only update atime if the previous atime is + * earlier than either the ctime or mtime or if at least a day has + * passed since the last atime update. + */ +static int relatime_need_update(struct vfsmount *mnt, struct inode *inode, + struct timespec now) +{ + + if (!(mnt->mnt_flags & MNT_RELATIME)) + return 1; + /* + * Is mtime younger than atime? If yes, update atime: + */ + if (timespec_compare(&inode->i_mtime, &inode->i_atime) >= 0) + return 1; + /* + * Is ctime younger than atime? If yes, update atime: + */ + if (timespec_compare(&inode->i_ctime, &inode->i_atime) >= 0) + return 1; + + /* + * Is the previous atime value older than a day? If yes, + * update atime: + */ + if ((long)(now.tv_sec - inode->i_atime.tv_sec) >= 24*60*60) + return 1; + /* + * Good, we can skip the atime update: + */ + return 0; +} + /** * touch_atime - update the access time * @mnt: mount the inode is accessed on @@ -1317,17 +1351,12 @@ void touch_atime(struct vfsmount *mnt, struct dentry *dentry) goto out; if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode)) goto out; - if (mnt->mnt_flags & MNT_RELATIME) { - /* - * With relative atime, only update atime if the previous - * atime is earlier than either the ctime or mtime. - */ - if (timespec_compare(&inode->i_mtime, &inode->i_atime) < 0 && - timespec_compare(&inode->i_ctime, &inode->i_atime) < 0) - goto out; - } now = current_fs_time(inode->i_sb); + + if (!relatime_need_update(mnt, inode, now)) + goto out; + if (timespec_equal(&inode->i_atime, &now)) goto out; -- GitLab From d0adde574b8487ef30f69e2d08bba769e4be513f Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 26 Mar 2009 17:49:56 +0000 Subject: [PATCH 4702/4982] Add a strictatime mount option Add support for explicitly requesting full atime updates. This makes it possible for kernels to default to relatime but still allow userspace to override it. Signed-off-by: Matthew Garrett Signed-off-by: Linus Torvalds --- fs/namespace.c | 6 +++++- include/linux/fs.h | 1 + include/linux/mount.h | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/namespace.c b/fs/namespace.c index 06f8e63f6cb..d0659ec291c 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -780,6 +780,7 @@ static void show_mnt_opts(struct seq_file *m, struct vfsmount *mnt) { MNT_NOATIME, ",noatime" }, { MNT_NODIRATIME, ",nodiratime" }, { MNT_RELATIME, ",relatime" }, + { MNT_STRICTATIME, ",strictatime" }, { 0, NULL } }; const struct proc_fs_info *fs_infop; @@ -1932,11 +1933,14 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, mnt_flags |= MNT_NODIRATIME; if (flags & MS_RELATIME) mnt_flags |= MNT_RELATIME; + if (flags & MS_STRICTATIME) + mnt_flags &= ~(MNT_RELATIME | MNT_NOATIME); if (flags & MS_RDONLY) mnt_flags |= MNT_READONLY; flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | - MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT); + MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT | + MS_STRICTATIME); /* ... and get the mountpoint */ retval = kern_path(dir_name, LOOKUP_FOLLOW, &path); diff --git a/include/linux/fs.h b/include/linux/fs.h index 92734c0012e..5bc81c4a98c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -141,6 +141,7 @@ struct inodes_stat_t { #define MS_RELATIME (1<<21) /* Update atime relative to mtime/ctime. */ #define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */ #define MS_I_VERSION (1<<23) /* Update inode I_version field */ +#define MS_STRICTATIME (1<<24) /* Always perform atime updates */ #define MS_ACTIVE (1<<30) #define MS_NOUSER (1<<31) diff --git a/include/linux/mount.h b/include/linux/mount.h index cab2a85e2ee..51f55f903af 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -27,6 +27,7 @@ struct mnt_namespace; #define MNT_NODIRATIME 0x10 #define MNT_RELATIME 0x20 #define MNT_READONLY 0x40 /* does the user want this to be r/o? */ +#define MNT_STRICTATIME 0x80 #define MNT_SHRINKABLE 0x100 #define MNT_IMBALANCED_WRITE_COUNT 0x200 /* just for debugging */ -- GitLab From 0a1c01c9477602ee8b44548a9405b2c1d587b5a2 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 26 Mar 2009 17:53:14 +0000 Subject: [PATCH 4703/4982] Make relatime default Change the default behaviour of the kernel to use relatime for all filesystems. This can be overridden with the "strictatime" mount option. Signed-off-by: Matthew Garrett Signed-off-by: Linus Torvalds --- fs/namespace.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index d0659ec291c..f0e75309735 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1920,6 +1920,9 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, if (data_page) ((char *)data_page)[PAGE_SIZE - 1] = 0; + /* Default to relatime */ + mnt_flags |= MNT_RELATIME; + /* Separate the per-mountpoint flags */ if (flags & MS_NOSUID) mnt_flags |= MNT_NOSUID; @@ -1931,8 +1934,6 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, mnt_flags |= MNT_NOATIME; if (flags & MS_NODIRATIME) mnt_flags |= MNT_NODIRATIME; - if (flags & MS_RELATIME) - mnt_flags |= MNT_RELATIME; if (flags & MS_STRICTATIME) mnt_flags &= ~(MNT_RELATIME | MNT_NOATIME); if (flags & MS_RDONLY) -- GitLab From 1b5e62b42b55c509eea04c3c0f25e42c8b35b564 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Mon, 23 Mar 2009 08:57:38 +0800 Subject: [PATCH 4704/4982] writeback: double the dirty thresholds Enlarge default dirty ratios from 5/10 to 10/20. This fixes [Bug #12809] iozone regression with 2.6.29-rc6. The iozone benchmarks are performed on a 1200M file, with 8GB ram. iozone -i 0 -i 1 -i 2 -i 3 -i 4 -r 4k -s 64k -s 512m -s 1200m -b tmp.xls iozone -B -r 4k -s 64k -s 512m -s 1200m -b tmp.xls The performance regression is triggered by commit 1cf6e7d83bf3(mm: task dirty accounting fix), which makes more correct/thorough dirty accounting. The default 5/10 dirty ratios were picked (a) with the old dirty logic and (b) largely at random and (c) designed to be aggressive. In particular, that (a) means that having fixed some of the dirty accounting, maybe the real bug is now that it was always too aggressive, just hidden by an accounting issue. The enlarged 10/20 dirty ratios are just about enough to fix the regression. [ We will have to look at how this affects the old fsync() latency issue, but that probably will need independent work. - Linus ] Cc: Nick Piggin Cc: Peter Zijlstra Reported-by: "Lin, Ming M" Tested-by: "Lin, Ming M" Signed-off-by: Wu Fengguang Signed-off-by: Linus Torvalds --- mm/page-writeback.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 74dc57c7434..40ca7cdb653 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -66,7 +66,7 @@ static inline long sync_writeback_pages(void) /* * Start background writeback (via pdflush) at this percentage */ -int dirty_background_ratio = 5; +int dirty_background_ratio = 10; /* * dirty_background_bytes starts at 0 (disabled) so that it is a function of @@ -83,7 +83,7 @@ int vm_highmem_is_dirtyable; /* * The generator of dirty data starts writeback at this percentage */ -int vm_dirty_ratio = 10; +int vm_dirty_ratio = 20; /* * vm_dirty_bytes starts at 0 (disabled) so that it is a function of -- GitLab From 612bfc9e630e3f7a4f3be1325eac28de8b8970af Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Thu, 30 Oct 2008 21:17:47 +0100 Subject: [PATCH 4705/4982] m68k: Add install target This patch enables the use of "make install" on m68k architecture to copy kernel to /boot. Signed-off-by: Laurent Vivier Signed-off-by: Geert Uytterhoeven --- arch/m68k/Makefile | 3 +++ arch/m68k/install.sh | 52 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 arch/m68k/install.sh diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile index 8133dbc4496..570d85c3f97 100644 --- a/arch/m68k/Makefile +++ b/arch/m68k/Makefile @@ -117,3 +117,6 @@ endif archclean: rm -f vmlinux.gz vmlinux.bz2 + +install: + sh $(srctree)/arch/m68k/install.sh $(KERNELRELEASE) vmlinux.gz System.map "$(INSTALL_PATH)" diff --git a/arch/m68k/install.sh b/arch/m68k/install.sh new file mode 100644 index 00000000000..9c6bae6112e --- /dev/null +++ b/arch/m68k/install.sh @@ -0,0 +1,52 @@ +#!/bin/sh +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 1995 by Linus Torvalds +# +# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin +# +# "make install" script for m68k architecture +# +# Arguments: +# $1 - kernel version +# $2 - kernel image file +# $3 - kernel map file +# $4 - default install path (blank if root directory) +# + +verify () { + if [ ! -f "$1" ]; then + echo "" 1>&2 + echo " *** Missing file: $1" 1>&2 + echo ' *** You need to run "make" before "make install".' 1>&2 + echo "" 1>&2 + exit 1 + fi +} + +# Make sure the files actually exist +verify "$2" +verify "$3" + +# User may have a custom install script + +if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi +if [ -x /sbin/${CROSS_COMPILE}installkernel ]; then exec /sbin/${CROSS_COMPILE}installkernel "$@"; fi + +# Default install - same as make zlilo + +if [ -f $4/vmlinuz ]; then + mv $4/vmlinuz $4/vmlinuz.old +fi + +if [ -f $4/System.map ]; then + mv $4/System.map $4/System.old +fi + +cat $2 > $4/vmlinuz +cp $3 $4/System.map + +sync -- GitLab From 7ad93b42bd135641ddc2c298f030132aca7aeca3 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Thu, 6 Nov 2008 20:57:41 +0100 Subject: [PATCH 4706/4982] m68k: mac - Add a new entry in mac_model to identify the floppy controller type. This patch adds a field "floppy_type" which can take the following values: MAC_FLOPPY_IWM for an IWM based mac MAC_FLOPPY_SWIM_ADDR1 for a SWIM based mac with controller at VIA1 + 0x1E000 MAC_FLOPPY_SWIM_ADDR2 for a SWIM based mac with controller at VIA1 + 0x16000 MAC_FLOPPY_IOP for an IOP based mac MAC_FLOPPY_AV for an AV based mac Signed-off-by: Laurent Vivier Signed-off-by: Geert Uytterhoeven --- arch/m68k/include/asm/macintosh.h | 7 ++ arch/m68k/mac/config.c | 163 ++++++++++++++++++++---------- 2 files changed, 116 insertions(+), 54 deletions(-) diff --git a/arch/m68k/include/asm/macintosh.h b/arch/m68k/include/asm/macintosh.h index 05309f7e3d0..50db3591ca1 100644 --- a/arch/m68k/include/asm/macintosh.h +++ b/arch/m68k/include/asm/macintosh.h @@ -34,6 +34,7 @@ struct mac_model char scc_type; char ether_type; char nubus_type; + char floppy_type; }; #define MAC_ADB_NONE 0 @@ -71,6 +72,12 @@ struct mac_model #define MAC_NO_NUBUS 0 #define MAC_NUBUS 1 +#define MAC_FLOPPY_IWM 0 +#define MAC_FLOPPY_SWIM_ADDR1 1 +#define MAC_FLOPPY_SWIM_ADDR2 2 +#define MAC_FLOPPY_SWIM_IOP 3 +#define MAC_FLOPPY_AV 4 + /* * Gestalt numbers */ diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c index 98b6bcfb37b..3a1c0b2862e 100644 --- a/arch/m68k/mac/config.c +++ b/arch/m68k/mac/config.c @@ -224,7 +224,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_II, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_IWM }, /* @@ -239,7 +240,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_II, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_IWM }, { .ident = MAC_MODEL_IIX, .name = "IIx", @@ -247,7 +249,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_II, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_IICX, .name = "IIcx", @@ -255,7 +258,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_II, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_SE30, .name = "SE/30", @@ -263,7 +267,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_II, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, /* @@ -280,7 +285,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IIci, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_IIFX, .name = "IIfx", @@ -288,7 +294,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IIci, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_IOP, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_IOP }, { .ident = MAC_MODEL_IISI, .name = "IIsi", @@ -296,7 +303,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IIci, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_IIVI, .name = "IIvi", @@ -304,7 +312,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IIci, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_IIVX, .name = "IIvx", @@ -312,7 +321,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IIci, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, /* @@ -326,7 +336,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IIci, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_CCL, .name = "Color Classic", @@ -334,7 +345,9 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IIci, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS}, + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 + }, /* * Some Mac LC machines. Basically the same as the IIci, ADB like IIsi @@ -347,7 +360,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IIci, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_LCII, .name = "LC II", @@ -355,7 +369,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IIci, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_LCIII, .name = "LC III", @@ -363,7 +378,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IIci, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, /* @@ -383,7 +399,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1 }, { .ident = MAC_MODEL_Q605_ACC, .name = "Quadra 605", @@ -391,7 +408,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1 }, { .ident = MAC_MODEL_Q610, .name = "Quadra 610", @@ -400,7 +418,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1 }, { .ident = MAC_MODEL_Q630, .name = "Quadra 630", @@ -410,7 +429,8 @@ static struct mac_model mac_data_table[] = { .ide_type = MAC_IDE_QUADRA, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1 }, { .ident = MAC_MODEL_Q650, .name = "Quadra 650", @@ -419,7 +439,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1 }, /* The Q700 does have a NS Sonic */ { @@ -430,7 +451,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA2, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1 }, { .ident = MAC_MODEL_Q800, .name = "Quadra 800", @@ -439,7 +461,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1 }, { .ident = MAC_MODEL_Q840, .name = "Quadra 840AV", @@ -448,7 +471,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA3, .scc_type = MAC_SCC_PSC, .ether_type = MAC_ETHER_MACE, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_AV }, { .ident = MAC_MODEL_Q900, .name = "Quadra 900", @@ -457,7 +481,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA2, .scc_type = MAC_SCC_IOP, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_IOP }, { .ident = MAC_MODEL_Q950, .name = "Quadra 950", @@ -466,7 +491,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA2, .scc_type = MAC_SCC_IOP, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_IOP }, /* @@ -480,7 +506,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IIci, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_P475, .name = "Performa 475", @@ -488,7 +515,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1 }, { .ident = MAC_MODEL_P475F, .name = "Performa 475", @@ -496,7 +524,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1 }, { .ident = MAC_MODEL_P520, .name = "Performa 520", @@ -504,7 +533,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IIci, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_P550, .name = "Performa 550", @@ -512,7 +542,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IIci, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, /* These have the comm slot, and therefore the possibility of SONIC ethernet */ { @@ -523,7 +554,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_II, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1 }, { .ident = MAC_MODEL_P588, .name = "Performa 588", @@ -533,7 +565,8 @@ static struct mac_model mac_data_table[] = { .ide_type = MAC_IDE_QUADRA, .scc_type = MAC_SCC_II, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1 }, { .ident = MAC_MODEL_TV, .name = "TV", @@ -541,7 +574,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_P600, .name = "Performa 600", @@ -549,7 +583,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IIci, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, /* @@ -565,7 +600,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1 }, { .ident = MAC_MODEL_C650, .name = "Centris 650", @@ -574,7 +610,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR1 }, { .ident = MAC_MODEL_C660, .name = "Centris 660AV", @@ -583,7 +620,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA3, .scc_type = MAC_SCC_PSC, .ether_type = MAC_ETHER_MACE, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_AV }, /* @@ -599,7 +637,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_PB145, .name = "PowerBook 145", @@ -607,7 +646,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_PB150, .name = "PowerBook 150", @@ -616,7 +656,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_OLD, .ide_type = MAC_IDE_PB, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_PB160, .name = "PowerBook 160", @@ -624,7 +665,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_PB165, .name = "PowerBook 165", @@ -632,7 +674,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_PB165C, .name = "PowerBook 165c", @@ -640,7 +683,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_PB170, .name = "PowerBook 170", @@ -648,7 +692,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_PB180, .name = "PowerBook 180", @@ -656,7 +701,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_PB180C, .name = "PowerBook 180c", @@ -664,7 +710,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_PB190, .name = "PowerBook 190", @@ -673,7 +720,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_OLD, .ide_type = MAC_IDE_BABOON, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_PB520, .name = "PowerBook 520", @@ -682,7 +730,8 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, /* @@ -702,7 +751,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IIci, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_PB230, .name = "PowerBook Duo 230", @@ -710,7 +760,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IIci, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_PB250, .name = "PowerBook Duo 250", @@ -718,7 +769,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IIci, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_PB270C, .name = "PowerBook Duo 270c", @@ -726,7 +778,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IIci, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_PB280, .name = "PowerBook Duo 280", @@ -734,7 +787,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IIci, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, { .ident = MAC_MODEL_PB280C, .name = "PowerBook Duo 280c", @@ -742,7 +796,8 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IIci, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS + .nubus_type = MAC_NUBUS, + .floppy_type = MAC_FLOPPY_SWIM_ADDR2 }, /* -- GitLab From 8852ecd97488249ca7fe2c0d3eb44cae95886881 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Sat, 15 Nov 2008 16:10:10 +0100 Subject: [PATCH 4707/4982] m68k: mac - Add SWIM floppy support It allows to read data from a floppy, but not to write to, and to eject the floppy (useful on our Mac without eject button). Signed-off-by: Laurent Vivier Signed-off-by: Geert Uytterhoeven --- arch/m68k/mac/config.c | 44 ++ arch/m68k/mac/via.c | 9 + drivers/block/Kconfig | 7 + drivers/block/Makefile | 3 + drivers/block/swim.c | 995 +++++++++++++++++++++++++++++++++++++++ drivers/block/swim_asm.S | 247 ++++++++++ 6 files changed, 1305 insertions(+) create mode 100644 drivers/block/swim.c create mode 100644 drivers/block/swim_asm.S diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c index 3a1c0b2862e..be017984a45 100644 --- a/arch/m68k/mac/config.c +++ b/arch/m68k/mac/config.c @@ -22,6 +22,7 @@ /* keyb */ #include #include +#include #define BOOTINFO_COMPAT_1_0 #include @@ -43,6 +44,10 @@ #include #include +/* platform device info */ + +#define SWIM_IO_SIZE 0x2000 /* SWIM IO resource size */ + /* Mac bootinfo struct */ struct mac_booter_data mac_bi_data; @@ -870,3 +875,42 @@ static void mac_get_model(char *str) strcpy(str, "Macintosh "); strcat(str, macintosh_config->name); } + +static struct resource swim_resources[1]; + +static struct platform_device swim_device = { + .name = "swim", + .id = -1, + .num_resources = ARRAY_SIZE(swim_resources), + .resource = swim_resources, +}; + +static struct platform_device *mac_platform_devices[] __initdata = { + &swim_device +}; + +int __init mac_platform_init(void) +{ + u8 *swim_base; + + switch (macintosh_config->floppy_type) { + case MAC_FLOPPY_SWIM_ADDR1: + swim_base = (u8 *)(VIA1_BASE + 0x1E000); + break; + case MAC_FLOPPY_SWIM_ADDR2: + swim_base = (u8 *)(VIA1_BASE + 0x16000); + break; + default: + return 0; + } + + swim_resources[0].name = "swim-regs"; + swim_resources[0].start = (resource_size_t)swim_base; + swim_resources[0].end = (resource_size_t)(swim_base + SWIM_IO_SIZE); + swim_resources[0].flags = IORESOURCE_MEM; + + return platform_add_devices(mac_platform_devices, + ARRAY_SIZE(mac_platform_devices)); +} + +arch_initcall(mac_platform_init); diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c index 7d97ba54536..11bce3cb648 100644 --- a/arch/m68k/mac/via.c +++ b/arch/m68k/mac/via.c @@ -645,3 +645,12 @@ int via_irq_pending(int irq) } return 0; } + +void via1_set_head(int head) +{ + if (head == 0) + via1[vBufA] &= ~VIA1A_vHeadSel; + else + via1[vBufA] |= VIA1A_vHeadSel; +} +EXPORT_SYMBOL(via1_set_head); diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 0344a8a8321..e7b8aa0cb47 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -45,6 +45,13 @@ config MAC_FLOPPY If you have a SWIM-3 (Super Woz Integrated Machine 3; from Apple) floppy controller, say Y here. Most commonly found in PowerMacs. +config BLK_DEV_SWIM + tristate "Support for SWIM Macintosh floppy" + depends on M68K && MAC + help + You should select this option if you want floppy support + and you don't have a II, IIfx, Q900, Q950 or AV series. + config AMIGA_Z2RAM tristate "Amiga Zorro II ramdisk support" depends on ZORRO diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 87e120e0a79..3145141cef7 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -6,6 +6,7 @@ # obj-$(CONFIG_MAC_FLOPPY) += swim3.o +obj-$(CONFIG_BLK_DEV_SWIM) += swim_mod.o obj-$(CONFIG_BLK_DEV_FD) += floppy.o obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o obj-$(CONFIG_PS3_DISK) += ps3disk.o @@ -33,3 +34,5 @@ obj-$(CONFIG_BLK_DEV_UB) += ub.o obj-$(CONFIG_BLK_DEV_HD) += hd.o obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o + +swim_mod-objs := swim.o swim_asm.o diff --git a/drivers/block/swim.c b/drivers/block/swim.c new file mode 100644 index 00000000000..d22cc385693 --- /dev/null +++ b/drivers/block/swim.c @@ -0,0 +1,995 @@ +/* + * Driver for SWIM (Sander Woz Integrated Machine) floppy controller + * + * Copyright (C) 2004,2008 Laurent Vivier + * + * based on Alastair Bridgewater SWIM analysis, 2001 + * based on SWIM3 driver (c) Paul Mackerras, 1996 + * based on netBSD IWM driver (c) 1997, 1998 Hauke Fath. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 2004-08-21 (lv) - Initial implementation + * 2008-10-30 (lv) - Port to 2.6 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define CARDNAME "swim" + +struct sector_header { + unsigned char side; + unsigned char track; + unsigned char sector; + unsigned char size; + unsigned char crc0; + unsigned char crc1; +} __attribute__((packed)); + +#define DRIVER_VERSION "Version 0.2 (2008-10-30)" + +#define REG(x) unsigned char x, x ## _pad[0x200 - 1]; + +struct swim { + REG(write_data) + REG(write_mark) + REG(write_CRC) + REG(write_parameter) + REG(write_phase) + REG(write_setup) + REG(write_mode0) + REG(write_mode1) + + REG(read_data) + REG(read_mark) + REG(read_error) + REG(read_parameter) + REG(read_phase) + REG(read_setup) + REG(read_status) + REG(read_handshake) +} __attribute__((packed)); + +#define swim_write(base, reg, v) out_8(&(base)->write_##reg, (v)) +#define swim_read(base, reg) in_8(&(base)->read_##reg) + +/* IWM registers */ + +struct iwm { + REG(ph0L) + REG(ph0H) + REG(ph1L) + REG(ph1H) + REG(ph2L) + REG(ph2H) + REG(ph3L) + REG(ph3H) + REG(mtrOff) + REG(mtrOn) + REG(intDrive) + REG(extDrive) + REG(q6L) + REG(q6H) + REG(q7L) + REG(q7H) +} __attribute__((packed)); + +#define iwm_write(base, reg, v) out_8(&(base)->reg, (v)) +#define iwm_read(base, reg) in_8(&(base)->reg) + +/* bits in phase register */ + +#define SEEK_POSITIVE 0x070 +#define SEEK_NEGATIVE 0x074 +#define STEP 0x071 +#define MOTOR_ON 0x072 +#define MOTOR_OFF 0x076 +#define INDEX 0x073 +#define EJECT 0x077 +#define SETMFM 0x171 +#define SETGCR 0x175 + +#define RELAX 0x033 +#define LSTRB 0x008 + +#define CA_MASK 0x077 + +/* Select values for swim_select and swim_readbit */ + +#define READ_DATA_0 0x074 +#define TWOMEG_DRIVE 0x075 +#define SINGLE_SIDED 0x076 +#define DRIVE_PRESENT 0x077 +#define DISK_IN 0x170 +#define WRITE_PROT 0x171 +#define TRACK_ZERO 0x172 +#define TACHO 0x173 +#define READ_DATA_1 0x174 +#define MFM_MODE 0x175 +#define SEEK_COMPLETE 0x176 +#define ONEMEG_MEDIA 0x177 + +/* Bits in handshake register */ + +#define MARK_BYTE 0x01 +#define CRC_ZERO 0x02 +#define RDDATA 0x04 +#define SENSE 0x08 +#define MOTEN 0x10 +#define ERROR 0x20 +#define DAT2BYTE 0x40 +#define DAT1BYTE 0x80 + +/* bits in setup register */ + +#define S_INV_WDATA 0x01 +#define S_3_5_SELECT 0x02 +#define S_GCR 0x04 +#define S_FCLK_DIV2 0x08 +#define S_ERROR_CORR 0x10 +#define S_IBM_DRIVE 0x20 +#define S_GCR_WRITE 0x40 +#define S_TIMEOUT 0x80 + +/* bits in mode register */ + +#define CLFIFO 0x01 +#define ENBL1 0x02 +#define ENBL2 0x04 +#define ACTION 0x08 +#define WRITE_MODE 0x10 +#define HEDSEL 0x20 +#define MOTON 0x80 + +/*----------------------------------------------------------------------------*/ + +enum drive_location { + INTERNAL_DRIVE = 0x02, + EXTERNAL_DRIVE = 0x04, +}; + +enum media_type { + DD_MEDIA, + HD_MEDIA, +}; + +struct floppy_state { + + /* physical properties */ + + enum drive_location location; /* internal or external drive */ + int head_number; /* single- or double-sided drive */ + + /* media */ + + int disk_in; + int ejected; + enum media_type type; + int write_protected; + + int total_secs; + int secpercyl; + int secpertrack; + + /* in-use information */ + + int track; + int ref_count; + + struct gendisk *disk; + + /* parent controller */ + + struct swim_priv *swd; +}; + +enum motor_action { + OFF, + ON, +}; + +enum head { + LOWER_HEAD = 0, + UPPER_HEAD = 1, +}; + +#define FD_MAX_UNIT 2 + +struct swim_priv { + struct swim __iomem *base; + spinlock_t lock; + struct request_queue *queue; + int floppy_count; + struct floppy_state unit[FD_MAX_UNIT]; +}; + +extern int swim_read_sector_header(struct swim __iomem *base, + struct sector_header *header); +extern int swim_read_sector_data(struct swim __iomem *base, + unsigned char *data); + +static inline void set_swim_mode(struct swim __iomem *base, int enable) +{ + struct iwm __iomem *iwm_base; + unsigned long flags; + + if (!enable) { + swim_write(base, mode0, 0xf8); + return; + } + + iwm_base = (struct iwm __iomem *)base; + local_irq_save(flags); + + iwm_read(iwm_base, q7L); + iwm_read(iwm_base, mtrOff); + iwm_read(iwm_base, q6H); + + iwm_write(iwm_base, q7H, 0x57); + iwm_write(iwm_base, q7H, 0x17); + iwm_write(iwm_base, q7H, 0x57); + iwm_write(iwm_base, q7H, 0x57); + + local_irq_restore(flags); +} + +static inline int get_swim_mode(struct swim __iomem *base) +{ + unsigned long flags; + + local_irq_save(flags); + + swim_write(base, phase, 0xf5); + if (swim_read(base, phase) != 0xf5) + goto is_iwm; + swim_write(base, phase, 0xf6); + if (swim_read(base, phase) != 0xf6) + goto is_iwm; + swim_write(base, phase, 0xf7); + if (swim_read(base, phase) != 0xf7) + goto is_iwm; + local_irq_restore(flags); + return 1; +is_iwm: + local_irq_restore(flags); + return 0; +} + +static inline void swim_select(struct swim __iomem *base, int sel) +{ + swim_write(base, phase, RELAX); + + via1_set_head(sel & 0x100); + + swim_write(base, phase, sel & CA_MASK); +} + +static inline void swim_action(struct swim __iomem *base, int action) +{ + unsigned long flags; + + local_irq_save(flags); + + swim_select(base, action); + udelay(1); + swim_write(base, phase, (LSTRB<<4) | LSTRB); + udelay(1); + swim_write(base, phase, (LSTRB<<4) | ((~LSTRB) & 0x0F)); + udelay(1); + + local_irq_restore(flags); +} + +static inline int swim_readbit(struct swim __iomem *base, int bit) +{ + int stat; + + swim_select(base, bit); + + udelay(10); + + stat = swim_read(base, handshake); + + return (stat & SENSE) == 0; +} + +static inline void swim_drive(struct swim __iomem *base, + enum drive_location location) +{ + if (location == INTERNAL_DRIVE) { + swim_write(base, mode0, EXTERNAL_DRIVE); /* clear drive 1 bit */ + swim_write(base, mode1, INTERNAL_DRIVE); /* set drive 0 bit */ + } else if (location == EXTERNAL_DRIVE) { + swim_write(base, mode0, INTERNAL_DRIVE); /* clear drive 0 bit */ + swim_write(base, mode1, EXTERNAL_DRIVE); /* set drive 1 bit */ + } +} + +static inline void swim_motor(struct swim __iomem *base, + enum motor_action action) +{ + if (action == ON) { + int i; + + swim_action(base, MOTOR_ON); + + for (i = 0; i < 2*HZ; i++) { + swim_select(base, RELAX); + if (swim_readbit(base, MOTOR_ON)) + break; + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + } + } else if (action == OFF) { + swim_action(base, MOTOR_OFF); + swim_select(base, RELAX); + } +} + +static inline void swim_eject(struct swim __iomem *base) +{ + int i; + + swim_action(base, EJECT); + + for (i = 0; i < 2*HZ; i++) { + swim_select(base, RELAX); + if (!swim_readbit(base, DISK_IN)) + break; + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + } + swim_select(base, RELAX); +} + +static inline void swim_head(struct swim __iomem *base, enum head head) +{ + /* wait drive is ready */ + + if (head == UPPER_HEAD) + swim_select(base, READ_DATA_1); + else if (head == LOWER_HEAD) + swim_select(base, READ_DATA_0); +} + +static inline int swim_step(struct swim __iomem *base) +{ + int wait; + + swim_action(base, STEP); + + for (wait = 0; wait < HZ; wait++) { + + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + + swim_select(base, RELAX); + if (!swim_readbit(base, STEP)) + return 0; + } + return -1; +} + +static inline int swim_track00(struct swim __iomem *base) +{ + int try; + + swim_action(base, SEEK_NEGATIVE); + + for (try = 0; try < 100; try++) { + + swim_select(base, RELAX); + if (swim_readbit(base, TRACK_ZERO)) + break; + + if (swim_step(base)) + return -1; + } + + if (swim_readbit(base, TRACK_ZERO)) + return 0; + + return -1; +} + +static inline int swim_seek(struct swim __iomem *base, int step) +{ + if (step == 0) + return 0; + + if (step < 0) { + swim_action(base, SEEK_NEGATIVE); + step = -step; + } else + swim_action(base, SEEK_POSITIVE); + + for ( ; step > 0; step--) { + if (swim_step(base)) + return -1; + } + + return 0; +} + +static inline int swim_track(struct floppy_state *fs, int track) +{ + struct swim __iomem *base = fs->swd->base; + int ret; + + ret = swim_seek(base, track - fs->track); + + if (ret == 0) + fs->track = track; + else { + swim_track00(base); + fs->track = 0; + } + + return ret; +} + +static int floppy_eject(struct floppy_state *fs) +{ + struct swim __iomem *base = fs->swd->base; + + swim_drive(base, fs->location); + swim_motor(base, OFF); + swim_eject(base); + + fs->disk_in = 0; + fs->ejected = 1; + + return 0; +} + +static inline int swim_read_sector(struct floppy_state *fs, + int side, int track, + int sector, unsigned char *buffer) +{ + struct swim __iomem *base = fs->swd->base; + unsigned long flags; + struct sector_header header; + int ret = -1; + short i; + + swim_track(fs, track); + + swim_write(base, mode1, MOTON); + swim_head(base, side); + swim_write(base, mode0, side); + + local_irq_save(flags); + for (i = 0; i < 36; i++) { + ret = swim_read_sector_header(base, &header); + if (!ret && (header.sector == sector)) { + /* found */ + + ret = swim_read_sector_data(base, buffer); + break; + } + } + local_irq_restore(flags); + + swim_write(base, mode0, MOTON); + + if ((header.side != side) || (header.track != track) || + (header.sector != sector)) + return 0; + + return ret; +} + +static int floppy_read_sectors(struct floppy_state *fs, + int req_sector, int sectors_nb, + unsigned char *buffer) +{ + struct swim __iomem *base = fs->swd->base; + int ret; + int side, track, sector; + int i, try; + + + swim_drive(base, fs->location); + for (i = req_sector; i < req_sector + sectors_nb; i++) { + int x; + track = i / fs->secpercyl; + x = i % fs->secpercyl; + side = x / fs->secpertrack; + sector = x % fs->secpertrack + 1; + + try = 5; + do { + ret = swim_read_sector(fs, side, track, sector, + buffer); + if (try-- == 0) + return -1; + } while (ret != 512); + + buffer += ret; + } + + return 0; +} + +static void redo_fd_request(struct request_queue *q) +{ + struct request *req; + struct floppy_state *fs; + + while ((req = elv_next_request(q))) { + + fs = req->rq_disk->private_data; + if (req->sector < 0 || req->sector >= fs->total_secs) { + end_request(req, 0); + continue; + } + if (req->current_nr_sectors == 0) { + end_request(req, 1); + continue; + } + if (!fs->disk_in) { + end_request(req, 0); + continue; + } + if (rq_data_dir(req) == WRITE) { + if (fs->write_protected) { + end_request(req, 0); + continue; + } + } + switch (rq_data_dir(req)) { + case WRITE: + /* NOT IMPLEMENTED */ + end_request(req, 0); + break; + case READ: + if (floppy_read_sectors(fs, req->sector, + req->current_nr_sectors, + req->buffer)) { + end_request(req, 0); + continue; + } + req->nr_sectors -= req->current_nr_sectors; + req->sector += req->current_nr_sectors; + req->buffer += req->current_nr_sectors * 512; + end_request(req, 1); + break; + } + } +} + +static void do_fd_request(struct request_queue *q) +{ + redo_fd_request(q); +} + +static struct floppy_struct floppy_type[4] = { + { 0, 0, 0, 0, 0, 0x00, 0x00, 0x00, 0x00, NULL }, /* no testing */ + { 720, 9, 1, 80, 0, 0x2A, 0x02, 0xDF, 0x50, NULL }, /* 360KB SS 3.5"*/ + { 1440, 9, 2, 80, 0, 0x2A, 0x02, 0xDF, 0x50, NULL }, /* 720KB 3.5" */ + { 2880, 18, 2, 80, 0, 0x1B, 0x00, 0xCF, 0x6C, NULL }, /* 1.44MB 3.5" */ +}; + +static int get_floppy_geometry(struct floppy_state *fs, int type, + struct floppy_struct **g) +{ + if (type >= ARRAY_SIZE(floppy_type)) + return -EINVAL; + + if (type) + *g = &floppy_type[type]; + else if (fs->type == HD_MEDIA) /* High-Density media */ + *g = &floppy_type[3]; + else if (fs->head_number == 2) /* double-sided */ + *g = &floppy_type[2]; + else + *g = &floppy_type[1]; + + return 0; +} + +static void setup_medium(struct floppy_state *fs) +{ + struct swim __iomem *base = fs->swd->base; + + if (swim_readbit(base, DISK_IN)) { + struct floppy_struct *g; + fs->disk_in = 1; + fs->write_protected = swim_readbit(base, WRITE_PROT); + fs->type = swim_readbit(base, ONEMEG_MEDIA); + + if (swim_track00(base)) + printk(KERN_ERR + "SWIM: cannot move floppy head to track 0\n"); + + swim_track00(base); + + get_floppy_geometry(fs, 0, &g); + fs->total_secs = g->size; + fs->secpercyl = g->head * g->sect; + fs->secpertrack = g->sect; + fs->track = 0; + } else { + fs->disk_in = 0; + } +} + +static int floppy_open(struct block_device *bdev, fmode_t mode) +{ + struct floppy_state *fs = bdev->bd_disk->private_data; + struct swim __iomem *base = fs->swd->base; + int err; + + if (fs->ref_count == -1 || (fs->ref_count && mode & FMODE_EXCL)) + return -EBUSY; + + if (mode & FMODE_EXCL) + fs->ref_count = -1; + else + fs->ref_count++; + + swim_write(base, setup, S_IBM_DRIVE | S_FCLK_DIV2); + udelay(10); + swim_drive(base, INTERNAL_DRIVE); + swim_motor(base, ON); + swim_action(base, SETMFM); + if (fs->ejected) + setup_medium(fs); + if (!fs->disk_in) { + err = -ENXIO; + goto out; + } + + if (mode & FMODE_NDELAY) + return 0; + + if (mode & (FMODE_READ|FMODE_WRITE)) { + check_disk_change(bdev); + if ((mode & FMODE_WRITE) && fs->write_protected) { + err = -EROFS; + goto out; + } + } + return 0; +out: + if (fs->ref_count < 0) + fs->ref_count = 0; + else if (fs->ref_count > 0) + --fs->ref_count; + + if (fs->ref_count == 0) + swim_motor(base, OFF); + return err; +} + +static int floppy_release(struct gendisk *disk, fmode_t mode) +{ + struct floppy_state *fs = disk->private_data; + struct swim __iomem *base = fs->swd->base; + + if (fs->ref_count < 0) + fs->ref_count = 0; + else if (fs->ref_count > 0) + --fs->ref_count; + + if (fs->ref_count == 0) + swim_motor(base, OFF); + + return 0; +} + +static int floppy_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long param) +{ + struct floppy_state *fs = bdev->bd_disk->private_data; + int err; + + if ((cmd & 0x80) && !capable(CAP_SYS_ADMIN)) + return -EPERM; + + switch (cmd) { + case FDEJECT: + if (fs->ref_count != 1) + return -EBUSY; + err = floppy_eject(fs); + return err; + + case FDGETPRM: + if (copy_to_user((void __user *) param, (void *) &floppy_type, + sizeof(struct floppy_struct))) + return -EFAULT; + break; + + default: + printk(KERN_DEBUG "SWIM floppy_ioctl: unknown cmd %d\n", + cmd); + return -ENOSYS; + } + return 0; +} + +static int floppy_getgeo(struct block_device *bdev, struct hd_geometry *geo) +{ + struct floppy_state *fs = bdev->bd_disk->private_data; + struct floppy_struct *g; + int ret; + + ret = get_floppy_geometry(fs, 0, &g); + if (ret) + return ret; + + geo->heads = g->head; + geo->sectors = g->sect; + geo->cylinders = g->track; + + return 0; +} + +static int floppy_check_change(struct gendisk *disk) +{ + struct floppy_state *fs = disk->private_data; + + return fs->ejected; +} + +static int floppy_revalidate(struct gendisk *disk) +{ + struct floppy_state *fs = disk->private_data; + struct swim __iomem *base = fs->swd->base; + + swim_drive(base, fs->location); + + if (fs->ejected) + setup_medium(fs); + + if (!fs->disk_in) + swim_motor(base, OFF); + else + fs->ejected = 0; + + return !fs->disk_in; +} + +static struct block_device_operations floppy_fops = { + .owner = THIS_MODULE, + .open = floppy_open, + .release = floppy_release, + .locked_ioctl = floppy_ioctl, + .getgeo = floppy_getgeo, + .media_changed = floppy_check_change, + .revalidate_disk = floppy_revalidate, +}; + +static struct kobject *floppy_find(dev_t dev, int *part, void *data) +{ + struct swim_priv *swd = data; + int drive = (*part & 3); + + if (drive > swd->floppy_count) + return NULL; + + *part = 0; + return get_disk(swd->unit[drive].disk); +} + +static int __devinit swim_add_floppy(struct swim_priv *swd, + enum drive_location location) +{ + struct floppy_state *fs = &swd->unit[swd->floppy_count]; + struct swim __iomem *base = swd->base; + + fs->location = location; + + swim_drive(base, location); + + swim_motor(base, OFF); + + if (swim_readbit(base, SINGLE_SIDED)) + fs->head_number = 1; + else + fs->head_number = 2; + fs->ref_count = 0; + fs->ejected = 1; + + swd->floppy_count++; + + return 0; +} + +static int __devinit swim_floppy_init(struct swim_priv *swd) +{ + int err; + int drive; + struct swim __iomem *base = swd->base; + + /* scan floppy drives */ + + swim_drive(base, INTERNAL_DRIVE); + if (swim_readbit(base, DRIVE_PRESENT)) + swim_add_floppy(swd, INTERNAL_DRIVE); + swim_drive(base, EXTERNAL_DRIVE); + if (swim_readbit(base, DRIVE_PRESENT)) + swim_add_floppy(swd, EXTERNAL_DRIVE); + + /* register floppy drives */ + + err = register_blkdev(FLOPPY_MAJOR, "fd"); + if (err) { + printk(KERN_ERR "Unable to get major %d for SWIM floppy\n", + FLOPPY_MAJOR); + return -EBUSY; + } + + for (drive = 0; drive < swd->floppy_count; drive++) { + swd->unit[drive].disk = alloc_disk(1); + if (swd->unit[drive].disk == NULL) { + err = -ENOMEM; + goto exit_put_disks; + } + swd->unit[drive].swd = swd; + } + + swd->queue = blk_init_queue(do_fd_request, &swd->lock); + if (!swd->queue) { + err = -ENOMEM; + goto exit_put_disks; + } + + for (drive = 0; drive < swd->floppy_count; drive++) { + swd->unit[drive].disk->flags = GENHD_FL_REMOVABLE; + swd->unit[drive].disk->major = FLOPPY_MAJOR; + swd->unit[drive].disk->first_minor = drive; + sprintf(swd->unit[drive].disk->disk_name, "fd%d", drive); + swd->unit[drive].disk->fops = &floppy_fops; + swd->unit[drive].disk->private_data = &swd->unit[drive]; + swd->unit[drive].disk->queue = swd->queue; + set_capacity(swd->unit[drive].disk, 2880); + add_disk(swd->unit[drive].disk); + } + + blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE, + floppy_find, NULL, swd); + + return 0; + +exit_put_disks: + unregister_blkdev(FLOPPY_MAJOR, "fd"); + while (drive--) + put_disk(swd->unit[drive].disk); + return err; +} + +static int __devinit swim_probe(struct platform_device *dev) +{ + struct resource *res; + struct swim __iomem *swim_base; + struct swim_priv *swd; + int ret; + + res = platform_get_resource_byname(dev, IORESOURCE_MEM, "swim-regs"); + if (!res) { + ret = -ENODEV; + goto out; + } + + if (!request_mem_region(res->start, resource_size(res), CARDNAME)) { + ret = -EBUSY; + goto out; + } + + swim_base = ioremap(res->start, resource_size(res)); + if (!swim_base) { + return -ENOMEM; + goto out_release_io; + } + + /* probe device */ + + set_swim_mode(swim_base, 1); + if (!get_swim_mode(swim_base)) { + printk(KERN_INFO "SWIM device not found !\n"); + ret = -ENODEV; + goto out_iounmap; + } + + /* set platform driver data */ + + swd = kzalloc(sizeof(struct swim_priv), GFP_KERNEL); + if (!swd) { + ret = -ENOMEM; + goto out_iounmap; + } + platform_set_drvdata(dev, swd); + + swd->base = swim_base; + + ret = swim_floppy_init(swd); + if (ret) + goto out_kfree; + + return 0; + +out_kfree: + platform_set_drvdata(dev, NULL); + kfree(swd); +out_iounmap: + iounmap(swim_base); +out_release_io: + release_mem_region(res->start, resource_size(res)); +out: + return ret; +} + +static int __devexit swim_remove(struct platform_device *dev) +{ + struct swim_priv *swd = platform_get_drvdata(dev); + int drive; + struct resource *res; + + blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); + + for (drive = 0; drive < swd->floppy_count; drive++) { + del_gendisk(swd->unit[drive].disk); + put_disk(swd->unit[drive].disk); + } + + unregister_blkdev(FLOPPY_MAJOR, "fd"); + + blk_cleanup_queue(swd->queue); + + /* eject floppies */ + + for (drive = 0; drive < swd->floppy_count; drive++) + floppy_eject(&swd->unit[drive]); + + iounmap(swd->base); + + res = platform_get_resource_byname(dev, IORESOURCE_MEM, "swim-regs"); + if (res) + release_mem_region(res->start, resource_size(res)); + + platform_set_drvdata(dev, NULL); + kfree(swd); + + return 0; +} + +static struct platform_driver swim_driver = { + .probe = swim_probe, + .remove = __devexit_p(swim_remove), + .driver = { + .name = CARDNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init swim_init(void) +{ + printk(KERN_INFO "SWIM floppy driver %s\n", DRIVER_VERSION); + + return platform_driver_register(&swim_driver); +} +module_init(swim_init); + +static void __exit swim_exit(void) +{ + platform_driver_unregister(&swim_driver); +} +module_exit(swim_exit); + +MODULE_DESCRIPTION("Driver for SWIM floppy controller"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Laurent Vivier "); +MODULE_ALIAS_BLOCKDEV_MAJOR(FLOPPY_MAJOR); diff --git a/drivers/block/swim_asm.S b/drivers/block/swim_asm.S new file mode 100644 index 00000000000..c9668206857 --- /dev/null +++ b/drivers/block/swim_asm.S @@ -0,0 +1,247 @@ +/* + * low-level functions for the SWIM floppy controller + * + * needs assembly language because is very timing dependent + * this controller exists only on macintosh 680x0 based + * + * Copyright (C) 2004,2008 Laurent Vivier + * + * based on Alastair Bridgewater SWIM analysis, 2001 + * based on netBSD IWM driver (c) 1997, 1998 Hauke Fath. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 2004-08-21 (lv) - Initial implementation + * 2008-11-05 (lv) - add get_swim_mode + */ + + .equ write_data, 0x0000 + .equ write_mark, 0x0200 + .equ write_CRC, 0x0400 + .equ write_parameter,0x0600 + .equ write_phase, 0x0800 + .equ write_setup, 0x0a00 + .equ write_mode0, 0x0c00 + .equ write_mode1, 0x0e00 + .equ read_data, 0x1000 + .equ read_mark, 0x1200 + .equ read_error, 0x1400 + .equ read_parameter, 0x1600 + .equ read_phase, 0x1800 + .equ read_setup, 0x1a00 + .equ read_status, 0x1c00 + .equ read_handshake, 0x1e00 + + .equ o_side, 0 + .equ o_track, 1 + .equ o_sector, 2 + .equ o_size, 3 + .equ o_crc0, 4 + .equ o_crc1, 5 + + .equ seek_time, 30000 + .equ max_retry, 40 + .equ sector_size, 512 + + .global swim_read_sector_header +swim_read_sector_header: + link %a6, #0 + moveml %d1-%d5/%a0-%a4,%sp@- + movel %a6@(0x0c), %a4 + bsr mfm_read_addrmark + moveml %sp@+, %d1-%d5/%a0-%a4 + unlk %a6 + rts + +sector_address_mark: + .byte 0xa1, 0xa1, 0xa1, 0xfe +sector_data_mark: + .byte 0xa1, 0xa1, 0xa1, 0xfb + +mfm_read_addrmark: + movel %a6@(0x08), %a3 + lea %a3@(read_handshake), %a2 + lea %a3@(read_mark), %a3 + moveq #-1, %d0 + movew #seek_time, %d2 + +wait_header_init: + tstb %a3@(read_error - read_mark) + moveb #0x18, %a3@(write_mode0 - read_mark) + moveb #0x01, %a3@(write_mode1 - read_mark) + moveb #0x01, %a3@(write_mode0 - read_mark) + tstb %a3@(read_error - read_mark) + moveb #0x08, %a3@(write_mode1 - read_mark) + + lea sector_address_mark, %a0 + moveq #3, %d1 + +wait_addr_mark_byte: + + tstb %a2@ + dbmi %d2, wait_addr_mark_byte + bpl header_exit + + moveb %a3@, %d3 + cmpb %a0@+, %d3 + dbne %d1, wait_addr_mark_byte + bne wait_header_init + + moveq #max_retry, %d2 + +amark0: tstb %a2@ + dbmi %d2, amark0 + bpl signal_nonyb + + moveb %a3@, %a4@(o_track) + + moveq #max_retry, %d2 + +amark1: tstb %a2@ + dbmi %d2, amark1 + bpl signal_nonyb + + moveb %a3@, %a4@(o_side) + + moveq #max_retry, %d2 + +amark2: tstb %a2@ + dbmi %d2, amark2 + bpl signal_nonyb + + moveb %a3@, %a4@(o_sector) + + moveq #max_retry, %d2 + +amark3: tstb %a2@ + dbmi %d2, amark3 + bpl signal_nonyb + + moveb %a3@, %a4@(o_size) + + moveq #max_retry, %d2 + +crc0: tstb %a2@ + dbmi %d2, crc0 + bpl signal_nonyb + + moveb %a3@, %a4@(o_crc0) + + moveq #max_retry, %d2 + +crc1: tstb %a2@ + dbmi %d2, crc1 + bpl signal_nonyb + + moveb %a3@, %a4@(o_crc1) + + tstb %a3@(read_error - read_mark) + +header_exit: + moveq #0, %d0 + moveb #0x18, %a3@(write_mode0 - read_mark) + rts +signal_nonyb: + moveq #-1, %d0 + moveb #0x18, %a3@(write_mode0 - read_mark) + rts + + .global swim_read_sector_data +swim_read_sector_data: + link %a6, #0 + moveml %d1-%d5/%a0-%a5,%sp@- + movel %a6@(0x0c), %a4 + bsr mfm_read_data + moveml %sp@+, %d1-%d5/%a0-%a5 + unlk %a6 + rts + +mfm_read_data: + movel %a6@(0x08), %a3 + lea %a3@(read_handshake), %a2 + lea %a3@(read_data), %a5 + lea %a3@(read_mark), %a3 + movew #seek_time, %d2 + +wait_data_init: + tstb %a3@(read_error - read_mark) + moveb #0x18, %a3@(write_mode0 - read_mark) + moveb #0x01, %a3@(write_mode1 - read_mark) + moveb #0x01, %a3@(write_mode0 - read_mark) + tstb %a3@(read_error - read_mark) + moveb #0x08, %a3@(write_mode1 - read_mark) + + lea sector_data_mark, %a0 + moveq #3, %d1 + + /* wait data address mark */ + +wait_data_mark_byte: + + tstb %a2@ + dbmi %d2, wait_data_mark_byte + bpl data_exit + + moveb %a3@, %d3 + cmpb %a0@+, %d3 + dbne %d1, wait_data_mark_byte + bne wait_data_init + + /* read data */ + + tstb %a3@(read_error - read_mark) + + movel #sector_size-1, %d4 /* sector size */ +read_new_data: + movew #max_retry, %d2 +read_data_loop: + moveb %a2@, %d5 + andb #0xc0, %d5 + dbne %d2, read_data_loop + beq data_exit + moveb %a5@, %a4@+ + andb #0x40, %d5 + dbne %d4, read_new_data + beq exit_loop + moveb %a5@, %a4@+ + dbra %d4, read_new_data +exit_loop: + + /* read CRC */ + + movew #max_retry, %d2 +data_crc0: + + tstb %a2@ + dbmi %d2, data_crc0 + bpl data_exit + + moveb %a3@, %d5 + + moveq #max_retry, %d2 + +data_crc1: + + tstb %a2@ + dbmi %d2, data_crc1 + bpl data_exit + + moveb %a3@, %d5 + + tstb %a3@(read_error - read_mark) + + moveb #0x18, %a3@(write_mode0 - read_mark) + + /* return number of bytes read */ + + movel #sector_size, %d0 + addw #1, %d4 + subl %d4, %d0 + rts +data_exit: + moveb #0x18, %a3@(write_mode0 - read_mark) + moveq #-1, %d0 + rts -- GitLab From 0e750aa47ab26236c15c1dc7a66ecf39148e67bc Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 24 Nov 2008 21:37:09 +0100 Subject: [PATCH 4708/4982] MAINTAINERS: Replace dead link to m68k CVS repository by link to new git repository CVS is dead, long live git! Signed-off-by: Geert Uytterhoeven --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 5d460c9d1c2..38ec1daaf79 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2832,7 +2832,7 @@ P: Roman Zippel M: zippel@linux-m68k.org L: linux-m68k@lists.linux-m68k.org W: http://www.linux-m68k.org/ -W: http://linux-m68k-cvs.ubb.ca/ +T: git git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k.git S: Maintained M68K ON APPLE MACINTOSH -- GitLab From d497e3ab91a726ecd76028698e5ce298f75ab681 Mon Sep 17 00:00:00 2001 From: Michael Schmitz Date: Sun, 18 Jan 2009 03:17:33 +0100 Subject: [PATCH 4709/4982] m68k: section mismatch fixes: DMAsound for Atari add __initdata to driver presets struct Signed-off-By: Michael Schmitz Signed-off-by: Geert Uytterhoeven --- sound/oss/dmasound/dmasound_atari.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/oss/dmasound/dmasound_atari.c b/sound/oss/dmasound/dmasound_atari.c index 38931f2f696..1f477412306 100644 --- a/sound/oss/dmasound/dmasound_atari.c +++ b/sound/oss/dmasound/dmasound_atari.c @@ -1524,7 +1524,7 @@ static SETTINGS def_soft = { .speed = 8000 } ; -static MACHINE machTT = { +static __initdata MACHINE machTT = { .name = "Atari", .name2 = "TT", .owner = THIS_MODULE, @@ -1553,7 +1553,7 @@ static MACHINE machTT = { .capabilities = DSP_CAP_BATCH /* As per SNDCTL_DSP_GETCAPS */ }; -static MACHINE machFalcon = { +static __initdata MACHINE machFalcon = { .name = "Atari", .name2 = "FALCON", .dma_alloc = AtaAlloc, -- GitLab From 95fde7a83989d595c06105629f42f3691bf62f91 Mon Sep 17 00:00:00 2001 From: Michael Schmitz Date: Sun, 18 Jan 2009 03:22:15 +0100 Subject: [PATCH 4710/4982] m68k: section mismatch fixes: Atari SCSI add __init annotations to probe routines Signed-off-by: Michael Schmitz Signed-off-by: Geert Uytterhoeven --- drivers/scsi/atari_NCR5380.c | 2 +- drivers/scsi/atari_scsi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 93b61f14865..0471f880048 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -844,7 +844,7 @@ static char *lprint_Scsi_Cmnd(Scsi_Cmnd *cmd, char *pos, char *buffer, int lengt * */ -static int NCR5380_init(struct Scsi_Host *instance, int flags) +static int __init NCR5380_init(struct Scsi_Host *instance, int flags) { int i; SETUP_HOSTDATA(instance); diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 21fe07f9df8..ad7a23aef0e 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -589,7 +589,7 @@ int atari_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) #endif -int atari_scsi_detect(struct scsi_host_template *host) +int __init atari_scsi_detect(struct scsi_host_template *host) { static int called = 0; struct Scsi_Host *instance; -- GitLab From 4b2873ba0bda7dc747cde8b6c7dc6c0b01ea6213 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 26 Mar 2009 09:48:45 +0100 Subject: [PATCH 4711/4982] m68k: irq_node.handler() should return irqreturn_t commit b5dc7840b3ebe9c7967dd8ba73db957767009ff9 ("m68k: introduce irq controller") reverted the return type of struct irq_node.handler() from irqreturn_t to int. Change it back to irqreturn_t, else it will give a compiler warning when irqreturn_t is turned into an enum in the near future: | arch/m68k/kernel/ints.c:231: warning: assignment from incompatible pointer type Signed-off-by: Geert Uytterhoeven --- arch/m68k/include/asm/irq_mm.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/m68k/include/asm/irq_mm.h b/arch/m68k/include/asm/irq_mm.h index 226bfc0f21b..0cab42cad79 100644 --- a/arch/m68k/include/asm/irq_mm.h +++ b/arch/m68k/include/asm/irq_mm.h @@ -3,6 +3,7 @@ #include #include +#include #include /* @@ -80,7 +81,7 @@ struct pt_regs; * interrupt source (if it supports chaining). */ typedef struct irq_node { - int (*handler)(int, void *); + irqreturn_t (*handler)(int, void *); void *dev_id; struct irq_node *next; unsigned long flags; -- GitLab From 9e80d407736161d9b8b0c5a0d44f786e44c322ea Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 26 Mar 2009 13:08:04 +0100 Subject: [PATCH 4712/4982] ext3: Avoid starting a transaction in writepage when not necessary We don't have to start a transaction in writepage() when all the blocks are a properly allocated. Even in ordered mode either the data has been written via write() and they are thus already added to transaction's list or the data was written via mmap and then it's random in which transaction they get written anyway. This should help VM to pageout dirty memory without blocking on transaction commits. Signed-off-by: Jan Kara Signed-off-by: Linus Torvalds --- fs/ext3/inode.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 5fa453b49a6..05e5c2e5c0d 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -1435,6 +1435,10 @@ static int journal_dirty_data_fn(handle_t *handle, struct buffer_head *bh) return 0; } +static int buffer_unmapped(handle_t *handle, struct buffer_head *bh) +{ + return !buffer_mapped(bh); +} /* * Note that we always start a transaction even if we're not journalling * data. This is to preserve ordering: any hole instantiation within @@ -1505,6 +1509,15 @@ static int ext3_ordered_writepage(struct page *page, if (ext3_journal_current_handle()) goto out_fail; + if (!page_has_buffers(page)) { + create_empty_buffers(page, inode->i_sb->s_blocksize, + (1 << BH_Dirty)|(1 << BH_Uptodate)); + } else if (!walk_page_buffers(NULL, page_buffers(page), 0, PAGE_CACHE_SIZE, NULL, buffer_unmapped)) { + /* Provide NULL instead of get_block so that we catch bugs if buffers weren't really mapped */ + return block_write_full_page(page, NULL, wbc); + } + page_bufs = page_buffers(page); + handle = ext3_journal_start(inode, ext3_writepage_trans_blocks(inode)); if (IS_ERR(handle)) { @@ -1512,11 +1525,6 @@ static int ext3_ordered_writepage(struct page *page, goto out_fail; } - if (!page_has_buffers(page)) { - create_empty_buffers(page, inode->i_sb->s_blocksize, - (1 << BH_Dirty)|(1 << BH_Uptodate)); - } - page_bufs = page_buffers(page); walk_page_buffers(handle, page_bufs, 0, PAGE_CACHE_SIZE, NULL, bget_one); -- GitLab From 7676b8fd701beb47cc1b4cc291acaa07287ea69a Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 26 Mar 2009 20:47:00 +0000 Subject: [PATCH 4713/4982] dontdiff: Fix asm exclude Now that the headers are in arch/foo/include/asm we don't want to exclude them when preparing diff files. Closes-bug: 12921 Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- Documentation/dontdiff | 1 - 1 file changed, 1 deletion(-) diff --git a/Documentation/dontdiff b/Documentation/dontdiff index 1e89a51ea49..88519daab6e 100644 --- a/Documentation/dontdiff +++ b/Documentation/dontdiff @@ -62,7 +62,6 @@ aic7*reg_print.c* aic7*seq.h* aicasm aicdb.h* -asm asm-offsets.h asm_offsets.h autoconf.h* -- GitLab From e2ab3dff9d515ef69ac7c245b5ad1e348f2106be Mon Sep 17 00:00:00 2001 From: David Miller Date: Thu, 26 Mar 2009 16:44:17 -0700 Subject: [PATCH 4714/4982] sparc64: Fix build of timer_interrupt(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit arch/sparc/kernel/time_64.c: In function ‘timer_interrupt’: arch/sparc/kernel/time_64.c:732: error: ‘struct kernel_stat’ has no member named ‘irqs’ make[1]: *** [arch/sparc/kernel/time_64.o] Error 1 Signed-off-by: David S. Miller Signed-off-by: Linus Torvalds --- arch/sparc/kernel/time_64.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index 642562d83ec..4ee2e48c4b3 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c @@ -724,12 +724,14 @@ void timer_interrupt(int irq, struct pt_regs *regs) unsigned long tick_mask = tick_ops->softint_mask; int cpu = smp_processor_id(); struct clock_event_device *evt = &per_cpu(sparc64_events, cpu); + struct irq_desc *desc; clear_softint(tick_mask); irq_enter(); - kstat_this_cpu.irqs[0]++; + desc = irq_to_desc(0); + kstat_incr_irqs_this_cpu(0, desc); if (unlikely(!evt->event_handler)) { printk(KERN_WARNING -- GitLab From 7c757eb9f804782fb39d0ae2c1a88ffb9309138e Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 26 Mar 2009 16:25:49 -0700 Subject: [PATCH 4715/4982] RDMA/nes: Fix mis-merge When net-next and infiniband were merged upstream, each branch deleted one of a pair of adjacent lines from nes_nic.c, but when Linus fixed the conflict up, he brought back both of the lines. Fix up to the intended final tree state. Signed-off-by: Roland Dreier Acked-by: David S. Miller Signed-off-by: Linus Torvalds --- drivers/infiniband/hw/nes/nes_nic.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index 8d3e4c6f237..ecb1f6fd627 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -1602,8 +1602,6 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, netif_napi_add(netdev, &nesvnic->napi, nes_netdev_poll, 128); nes_debug(NES_DBG_INIT, "Enabling VLAN Insert/Delete.\n"); netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - netdev->vlan_rx_register = nes_netdev_vlan_rx_register; - netdev->features |= NETIF_F_LLTX; /* Fill in the port structure */ nesvnic->netdev = netdev; -- GitLab From 8f1ead2d1a626ed0c85b3d2c2046a49081d5933f Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 26 Mar 2009 00:59:10 -0700 Subject: [PATCH 4716/4982] GRO: Disable GRO on legacy netif_rx path When I fixed the GRO crash in the legacy receive path I used napi_complete to replace __napi_complete. Unfortunately they're not the same when NETPOLL is enabled, which may result in us not calling __napi_complete at all. What's more, we really do need to keep the __napi_complete call within the IRQ-off section since in theory an IRQ can occur in between and fill up the backlog to the maximum, causing us to lock up. Since we can't seem to find a fix that works properly right now, this patch reverts all the GRO support from the netif_rx path. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/core/dev.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 052dd478d3e..63ec4bf89b2 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2627,18 +2627,15 @@ static int process_backlog(struct napi_struct *napi, int quota) local_irq_disable(); skb = __skb_dequeue(&queue->input_pkt_queue); if (!skb) { + __napi_complete(napi); local_irq_enable(); - napi_complete(napi); - goto out; + break; } local_irq_enable(); - napi_gro_receive(napi, skb); + netif_receive_skb(skb); } while (++work < quota && jiffies == start_time); - napi_gro_flush(napi); - -out: return work; } -- GitLab From a1702857724fb39cb68ce581490010df99168fd0 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 27 Mar 2009 00:12:24 -0700 Subject: [PATCH 4717/4982] net: Add support for the OpenCores 10/100 Mbps Ethernet MAC. This patch adds a platform device driver that supports the OpenCores 10/100 Mbps Ethernet MAC. The driver expects three resources: one IORESOURCE_MEM resource defines the memory region for the core's memory-mapped registers while a second IORESOURCE_MEM resource defines the network packet buffer space. The third resource, of type IORESOURCE_IRQ, associates an interrupt with the driver. Signed-off-by: Thierry Reding Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/Kconfig | 8 + drivers/net/Makefile | 1 + drivers/net/ethoc.c | 1112 ++++++++++++++++++++++++++++++++++++++++++ include/net/ethoc.h | 22 + 4 files changed, 1143 insertions(+) create mode 100644 drivers/net/ethoc.c create mode 100644 include/net/ethoc.h diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index e5ffc1c606c..f062b424704 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -972,6 +972,14 @@ config ENC28J60_WRITEVERIFY Enable the verify after the buffer write useful for debugging purpose. If unsure, say N. +config ETHOC + tristate "OpenCores 10/100 Mbps Ethernet MAC support" + depends on NET_ETHERNET + select MII + select PHYLIB + help + Say Y here if you want to use the OpenCores 10/100 Mbps Ethernet MAC. + config SMC911X tristate "SMSC LAN911[5678] support" select CRC32 diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 758ecdf4c82..98409c9dd44 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -230,6 +230,7 @@ obj-$(CONFIG_PASEMI_MAC) += pasemi_mac_driver.o pasemi_mac_driver-objs := pasemi_mac.o pasemi_mac_ethtool.o obj-$(CONFIG_MLX4_CORE) += mlx4/ obj-$(CONFIG_ENC28J60) += enc28j60.o +obj-$(CONFIG_ETHOC) += ethoc.o obj-$(CONFIG_XTENSA_XT2000_SONIC) += xtsonic.o diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c new file mode 100644 index 00000000000..91a9b1a3376 --- /dev/null +++ b/drivers/net/ethoc.c @@ -0,0 +1,1112 @@ +/* + * linux/drivers/net/ethoc.c + * + * Copyright (C) 2007-2008 Avionic Design Development GmbH + * Copyright (C) 2008-2009 Avionic Design GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Written by Thierry Reding + */ + +#include +#include +#include +#include +#include +#include +#include + +/* register offsets */ +#define MODER 0x00 +#define INT_SOURCE 0x04 +#define INT_MASK 0x08 +#define IPGT 0x0c +#define IPGR1 0x10 +#define IPGR2 0x14 +#define PACKETLEN 0x18 +#define COLLCONF 0x1c +#define TX_BD_NUM 0x20 +#define CTRLMODER 0x24 +#define MIIMODER 0x28 +#define MIICOMMAND 0x2c +#define MIIADDRESS 0x30 +#define MIITX_DATA 0x34 +#define MIIRX_DATA 0x38 +#define MIISTATUS 0x3c +#define MAC_ADDR0 0x40 +#define MAC_ADDR1 0x44 +#define ETH_HASH0 0x48 +#define ETH_HASH1 0x4c +#define ETH_TXCTRL 0x50 + +/* mode register */ +#define MODER_RXEN (1 << 0) /* receive enable */ +#define MODER_TXEN (1 << 1) /* transmit enable */ +#define MODER_NOPRE (1 << 2) /* no preamble */ +#define MODER_BRO (1 << 3) /* broadcast address */ +#define MODER_IAM (1 << 4) /* individual address mode */ +#define MODER_PRO (1 << 5) /* promiscuous mode */ +#define MODER_IFG (1 << 6) /* interframe gap for incoming frames */ +#define MODER_LOOP (1 << 7) /* loopback */ +#define MODER_NBO (1 << 8) /* no back-off */ +#define MODER_EDE (1 << 9) /* excess defer enable */ +#define MODER_FULLD (1 << 10) /* full duplex */ +#define MODER_RESET (1 << 11) /* FIXME: reset (undocumented) */ +#define MODER_DCRC (1 << 12) /* delayed CRC enable */ +#define MODER_CRC (1 << 13) /* CRC enable */ +#define MODER_HUGE (1 << 14) /* huge packets enable */ +#define MODER_PAD (1 << 15) /* padding enabled */ +#define MODER_RSM (1 << 16) /* receive small packets */ + +/* interrupt source and mask registers */ +#define INT_MASK_TXF (1 << 0) /* transmit frame */ +#define INT_MASK_TXE (1 << 1) /* transmit error */ +#define INT_MASK_RXF (1 << 2) /* receive frame */ +#define INT_MASK_RXE (1 << 3) /* receive error */ +#define INT_MASK_BUSY (1 << 4) +#define INT_MASK_TXC (1 << 5) /* transmit control frame */ +#define INT_MASK_RXC (1 << 6) /* receive control frame */ + +#define INT_MASK_TX (INT_MASK_TXF | INT_MASK_TXE) +#define INT_MASK_RX (INT_MASK_RXF | INT_MASK_RXE) + +#define INT_MASK_ALL ( \ + INT_MASK_TXF | INT_MASK_TXE | \ + INT_MASK_RXF | INT_MASK_RXE | \ + INT_MASK_TXC | INT_MASK_RXC | \ + INT_MASK_BUSY \ + ) + +/* packet length register */ +#define PACKETLEN_MIN(min) (((min) & 0xffff) << 16) +#define PACKETLEN_MAX(max) (((max) & 0xffff) << 0) +#define PACKETLEN_MIN_MAX(min, max) (PACKETLEN_MIN(min) | \ + PACKETLEN_MAX(max)) + +/* transmit buffer number register */ +#define TX_BD_NUM_VAL(x) (((x) <= 0x80) ? (x) : 0x80) + +/* control module mode register */ +#define CTRLMODER_PASSALL (1 << 0) /* pass all receive frames */ +#define CTRLMODER_RXFLOW (1 << 1) /* receive control flow */ +#define CTRLMODER_TXFLOW (1 << 2) /* transmit control flow */ + +/* MII mode register */ +#define MIIMODER_CLKDIV(x) ((x) & 0xfe) /* needs to be an even number */ +#define MIIMODER_NOPRE (1 << 8) /* no preamble */ + +/* MII command register */ +#define MIICOMMAND_SCAN (1 << 0) /* scan status */ +#define MIICOMMAND_READ (1 << 1) /* read status */ +#define MIICOMMAND_WRITE (1 << 2) /* write control data */ + +/* MII address register */ +#define MIIADDRESS_FIAD(x) (((x) & 0x1f) << 0) +#define MIIADDRESS_RGAD(x) (((x) & 0x1f) << 8) +#define MIIADDRESS_ADDR(phy, reg) (MIIADDRESS_FIAD(phy) | \ + MIIADDRESS_RGAD(reg)) + +/* MII transmit data register */ +#define MIITX_DATA_VAL(x) ((x) & 0xffff) + +/* MII receive data register */ +#define MIIRX_DATA_VAL(x) ((x) & 0xffff) + +/* MII status register */ +#define MIISTATUS_LINKFAIL (1 << 0) +#define MIISTATUS_BUSY (1 << 1) +#define MIISTATUS_INVALID (1 << 2) + +/* TX buffer descriptor */ +#define TX_BD_CS (1 << 0) /* carrier sense lost */ +#define TX_BD_DF (1 << 1) /* defer indication */ +#define TX_BD_LC (1 << 2) /* late collision */ +#define TX_BD_RL (1 << 3) /* retransmission limit */ +#define TX_BD_RETRY_MASK (0x00f0) +#define TX_BD_RETRY(x) (((x) & 0x00f0) >> 4) +#define TX_BD_UR (1 << 8) /* transmitter underrun */ +#define TX_BD_CRC (1 << 11) /* TX CRC enable */ +#define TX_BD_PAD (1 << 12) /* pad enable for short packets */ +#define TX_BD_WRAP (1 << 13) +#define TX_BD_IRQ (1 << 14) /* interrupt request enable */ +#define TX_BD_READY (1 << 15) /* TX buffer ready */ +#define TX_BD_LEN(x) (((x) & 0xffff) << 16) +#define TX_BD_LEN_MASK (0xffff << 16) + +#define TX_BD_STATS (TX_BD_CS | TX_BD_DF | TX_BD_LC | \ + TX_BD_RL | TX_BD_RETRY_MASK | TX_BD_UR) + +/* RX buffer descriptor */ +#define RX_BD_LC (1 << 0) /* late collision */ +#define RX_BD_CRC (1 << 1) /* RX CRC error */ +#define RX_BD_SF (1 << 2) /* short frame */ +#define RX_BD_TL (1 << 3) /* too long */ +#define RX_BD_DN (1 << 4) /* dribble nibble */ +#define RX_BD_IS (1 << 5) /* invalid symbol */ +#define RX_BD_OR (1 << 6) /* receiver overrun */ +#define RX_BD_MISS (1 << 7) +#define RX_BD_CF (1 << 8) /* control frame */ +#define RX_BD_WRAP (1 << 13) +#define RX_BD_IRQ (1 << 14) /* interrupt request enable */ +#define RX_BD_EMPTY (1 << 15) +#define RX_BD_LEN(x) (((x) & 0xffff) << 16) + +#define RX_BD_STATS (RX_BD_LC | RX_BD_CRC | RX_BD_SF | RX_BD_TL | \ + RX_BD_DN | RX_BD_IS | RX_BD_OR | RX_BD_MISS) + +#define ETHOC_BUFSIZ 1536 +#define ETHOC_ZLEN 64 +#define ETHOC_BD_BASE 0x400 +#define ETHOC_TIMEOUT (HZ / 2) +#define ETHOC_MII_TIMEOUT (1 + (HZ / 5)) + +/** + * struct ethoc - driver-private device structure + * @iobase: pointer to I/O memory region + * @membase: pointer to buffer memory region + * @num_tx: number of send buffers + * @cur_tx: last send buffer written + * @dty_tx: last buffer actually sent + * @num_rx: number of receive buffers + * @cur_rx: current receive buffer + * @netdev: pointer to network device structure + * @napi: NAPI structure + * @stats: network device statistics + * @msg_enable: device state flags + * @rx_lock: receive lock + * @lock: device lock + * @phy: attached PHY + * @mdio: MDIO bus for PHY access + * @phy_id: address of attached PHY + */ +struct ethoc { + void __iomem *iobase; + void __iomem *membase; + + unsigned int num_tx; + unsigned int cur_tx; + unsigned int dty_tx; + + unsigned int num_rx; + unsigned int cur_rx; + + struct net_device *netdev; + struct napi_struct napi; + struct net_device_stats stats; + u32 msg_enable; + + spinlock_t rx_lock; + spinlock_t lock; + + struct phy_device *phy; + struct mii_bus *mdio; + s8 phy_id; +}; + +/** + * struct ethoc_bd - buffer descriptor + * @stat: buffer statistics + * @addr: physical memory address + */ +struct ethoc_bd { + u32 stat; + u32 addr; +}; + +static u32 ethoc_read(struct ethoc *dev, loff_t offset) +{ + return ioread32(dev->iobase + offset); +} + +static void ethoc_write(struct ethoc *dev, loff_t offset, u32 data) +{ + iowrite32(data, dev->iobase + offset); +} + +static void ethoc_read_bd(struct ethoc *dev, int index, struct ethoc_bd *bd) +{ + loff_t offset = ETHOC_BD_BASE + (index * sizeof(struct ethoc_bd)); + bd->stat = ethoc_read(dev, offset + 0); + bd->addr = ethoc_read(dev, offset + 4); +} + +static void ethoc_write_bd(struct ethoc *dev, int index, + const struct ethoc_bd *bd) +{ + loff_t offset = ETHOC_BD_BASE + (index * sizeof(struct ethoc_bd)); + ethoc_write(dev, offset + 0, bd->stat); + ethoc_write(dev, offset + 4, bd->addr); +} + +static void ethoc_enable_irq(struct ethoc *dev, u32 mask) +{ + u32 imask = ethoc_read(dev, INT_MASK); + imask |= mask; + ethoc_write(dev, INT_MASK, imask); +} + +static void ethoc_disable_irq(struct ethoc *dev, u32 mask) +{ + u32 imask = ethoc_read(dev, INT_MASK); + imask &= ~mask; + ethoc_write(dev, INT_MASK, imask); +} + +static void ethoc_ack_irq(struct ethoc *dev, u32 mask) +{ + ethoc_write(dev, INT_SOURCE, mask); +} + +static void ethoc_enable_rx_and_tx(struct ethoc *dev) +{ + u32 mode = ethoc_read(dev, MODER); + mode |= MODER_RXEN | MODER_TXEN; + ethoc_write(dev, MODER, mode); +} + +static void ethoc_disable_rx_and_tx(struct ethoc *dev) +{ + u32 mode = ethoc_read(dev, MODER); + mode &= ~(MODER_RXEN | MODER_TXEN); + ethoc_write(dev, MODER, mode); +} + +static int ethoc_init_ring(struct ethoc *dev) +{ + struct ethoc_bd bd; + int i; + + dev->cur_tx = 0; + dev->dty_tx = 0; + dev->cur_rx = 0; + + /* setup transmission buffers */ + bd.addr = 0; + bd.stat = TX_BD_IRQ | TX_BD_CRC; + + for (i = 0; i < dev->num_tx; i++) { + if (i == dev->num_tx - 1) + bd.stat |= TX_BD_WRAP; + + ethoc_write_bd(dev, i, &bd); + bd.addr += ETHOC_BUFSIZ; + } + + bd.addr = dev->num_tx * ETHOC_BUFSIZ; + bd.stat = RX_BD_EMPTY | RX_BD_IRQ; + + for (i = 0; i < dev->num_rx; i++) { + if (i == dev->num_rx - 1) + bd.stat |= RX_BD_WRAP; + + ethoc_write_bd(dev, dev->num_tx + i, &bd); + bd.addr += ETHOC_BUFSIZ; + } + + return 0; +} + +static int ethoc_reset(struct ethoc *dev) +{ + u32 mode; + + /* TODO: reset controller? */ + + ethoc_disable_rx_and_tx(dev); + + /* TODO: setup registers */ + + /* enable FCS generation and automatic padding */ + mode = ethoc_read(dev, MODER); + mode |= MODER_CRC | MODER_PAD; + ethoc_write(dev, MODER, mode); + + /* set full-duplex mode */ + mode = ethoc_read(dev, MODER); + mode |= MODER_FULLD; + ethoc_write(dev, MODER, mode); + ethoc_write(dev, IPGT, 0x15); + + ethoc_ack_irq(dev, INT_MASK_ALL); + ethoc_enable_irq(dev, INT_MASK_ALL); + ethoc_enable_rx_and_tx(dev); + return 0; +} + +static unsigned int ethoc_update_rx_stats(struct ethoc *dev, + struct ethoc_bd *bd) +{ + struct net_device *netdev = dev->netdev; + unsigned int ret = 0; + + if (bd->stat & RX_BD_TL) { + dev_err(&netdev->dev, "RX: frame too long\n"); + dev->stats.rx_length_errors++; + ret++; + } + + if (bd->stat & RX_BD_SF) { + dev_err(&netdev->dev, "RX: frame too short\n"); + dev->stats.rx_length_errors++; + ret++; + } + + if (bd->stat & RX_BD_DN) { + dev_err(&netdev->dev, "RX: dribble nibble\n"); + dev->stats.rx_frame_errors++; + } + + if (bd->stat & RX_BD_CRC) { + dev_err(&netdev->dev, "RX: wrong CRC\n"); + dev->stats.rx_crc_errors++; + ret++; + } + + if (bd->stat & RX_BD_OR) { + dev_err(&netdev->dev, "RX: overrun\n"); + dev->stats.rx_over_errors++; + ret++; + } + + if (bd->stat & RX_BD_MISS) + dev->stats.rx_missed_errors++; + + if (bd->stat & RX_BD_LC) { + dev_err(&netdev->dev, "RX: late collision\n"); + dev->stats.collisions++; + ret++; + } + + return ret; +} + +static int ethoc_rx(struct net_device *dev, int limit) +{ + struct ethoc *priv = netdev_priv(dev); + int count; + + for (count = 0; count < limit; ++count) { + unsigned int entry; + struct ethoc_bd bd; + + entry = priv->num_tx + (priv->cur_rx % priv->num_rx); + ethoc_read_bd(priv, entry, &bd); + if (bd.stat & RX_BD_EMPTY) + break; + + if (ethoc_update_rx_stats(priv, &bd) == 0) { + int size = bd.stat >> 16; + struct sk_buff *skb = netdev_alloc_skb(dev, size); + if (likely(skb)) { + void *src = priv->membase + bd.addr; + memcpy_fromio(skb_put(skb, size), src, size); + skb->protocol = eth_type_trans(skb, dev); + dev->last_rx = jiffies; + priv->stats.rx_packets++; + priv->stats.rx_bytes += size; + netif_receive_skb(skb); + } else { + if (net_ratelimit()) + dev_warn(&dev->dev, "low on memory - " + "packet dropped\n"); + + priv->stats.rx_dropped++; + break; + } + } + + /* clear the buffer descriptor so it can be reused */ + bd.stat &= ~RX_BD_STATS; + bd.stat |= RX_BD_EMPTY; + ethoc_write_bd(priv, entry, &bd); + priv->cur_rx++; + } + + return count; +} + +static int ethoc_update_tx_stats(struct ethoc *dev, struct ethoc_bd *bd) +{ + struct net_device *netdev = dev->netdev; + + if (bd->stat & TX_BD_LC) { + dev_err(&netdev->dev, "TX: late collision\n"); + dev->stats.tx_window_errors++; + } + + if (bd->stat & TX_BD_RL) { + dev_err(&netdev->dev, "TX: retransmit limit\n"); + dev->stats.tx_aborted_errors++; + } + + if (bd->stat & TX_BD_UR) { + dev_err(&netdev->dev, "TX: underrun\n"); + dev->stats.tx_fifo_errors++; + } + + if (bd->stat & TX_BD_CS) { + dev_err(&netdev->dev, "TX: carrier sense lost\n"); + dev->stats.tx_carrier_errors++; + } + + if (bd->stat & TX_BD_STATS) + dev->stats.tx_errors++; + + dev->stats.collisions += (bd->stat >> 4) & 0xf; + dev->stats.tx_bytes += bd->stat >> 16; + dev->stats.tx_packets++; + return 0; +} + +static void ethoc_tx(struct net_device *dev) +{ + struct ethoc *priv = netdev_priv(dev); + + spin_lock(&priv->lock); + + while (priv->dty_tx != priv->cur_tx) { + unsigned int entry = priv->dty_tx % priv->num_tx; + struct ethoc_bd bd; + + ethoc_read_bd(priv, entry, &bd); + if (bd.stat & TX_BD_READY) + break; + + entry = (++priv->dty_tx) % priv->num_tx; + (void)ethoc_update_tx_stats(priv, &bd); + } + + if ((priv->cur_tx - priv->dty_tx) <= (priv->num_tx / 2)) + netif_wake_queue(dev); + + ethoc_ack_irq(priv, INT_MASK_TX); + spin_unlock(&priv->lock); +} + +static irqreturn_t ethoc_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = (struct net_device *)dev_id; + struct ethoc *priv = netdev_priv(dev); + u32 pending; + + ethoc_disable_irq(priv, INT_MASK_ALL); + pending = ethoc_read(priv, INT_SOURCE); + if (unlikely(pending == 0)) { + ethoc_enable_irq(priv, INT_MASK_ALL); + return IRQ_NONE; + } + + ethoc_ack_irq(priv, INT_MASK_ALL); + + if (pending & INT_MASK_BUSY) { + dev_err(&dev->dev, "packet dropped\n"); + priv->stats.rx_dropped++; + } + + if (pending & INT_MASK_RX) { + if (napi_schedule_prep(&priv->napi)) + __napi_schedule(&priv->napi); + } else { + ethoc_enable_irq(priv, INT_MASK_RX); + } + + if (pending & INT_MASK_TX) + ethoc_tx(dev); + + ethoc_enable_irq(priv, INT_MASK_ALL & ~INT_MASK_RX); + return IRQ_HANDLED; +} + +static int ethoc_get_mac_address(struct net_device *dev, void *addr) +{ + struct ethoc *priv = netdev_priv(dev); + u8 *mac = (u8 *)addr; + u32 reg; + + reg = ethoc_read(priv, MAC_ADDR0); + mac[2] = (reg >> 24) & 0xff; + mac[3] = (reg >> 16) & 0xff; + mac[4] = (reg >> 8) & 0xff; + mac[5] = (reg >> 0) & 0xff; + + reg = ethoc_read(priv, MAC_ADDR1); + mac[0] = (reg >> 8) & 0xff; + mac[1] = (reg >> 0) & 0xff; + + return 0; +} + +static int ethoc_poll(struct napi_struct *napi, int budget) +{ + struct ethoc *priv = container_of(napi, struct ethoc, napi); + int work_done = 0; + + work_done = ethoc_rx(priv->netdev, budget); + if (work_done < budget) { + ethoc_enable_irq(priv, INT_MASK_RX); + napi_complete(napi); + } + + return work_done; +} + +static int ethoc_mdio_read(struct mii_bus *bus, int phy, int reg) +{ + unsigned long timeout = jiffies + ETHOC_MII_TIMEOUT; + struct ethoc *priv = bus->priv; + + ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(phy, reg)); + ethoc_write(priv, MIICOMMAND, MIICOMMAND_READ); + + while (time_before(jiffies, timeout)) { + u32 status = ethoc_read(priv, MIISTATUS); + if (!(status & MIISTATUS_BUSY)) { + u32 data = ethoc_read(priv, MIIRX_DATA); + /* reset MII command register */ + ethoc_write(priv, MIICOMMAND, 0); + return data; + } + + schedule(); + } + + return -EBUSY; +} + +static int ethoc_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val) +{ + unsigned long timeout = jiffies + ETHOC_MII_TIMEOUT; + struct ethoc *priv = bus->priv; + + ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(phy, reg)); + ethoc_write(priv, MIITX_DATA, val); + ethoc_write(priv, MIICOMMAND, MIICOMMAND_WRITE); + + while (time_before(jiffies, timeout)) { + u32 stat = ethoc_read(priv, MIISTATUS); + if (!(stat & MIISTATUS_BUSY)) + return 0; + + schedule(); + } + + return -EBUSY; +} + +static int ethoc_mdio_reset(struct mii_bus *bus) +{ + return 0; +} + +static void ethoc_mdio_poll(struct net_device *dev) +{ +} + +static int ethoc_mdio_probe(struct net_device *dev) +{ + struct ethoc *priv = netdev_priv(dev); + struct phy_device *phy; + int i; + + for (i = 0; i < PHY_MAX_ADDR; i++) { + phy = priv->mdio->phy_map[i]; + if (phy) { + if (priv->phy_id != -1) { + /* attach to specified PHY */ + if (priv->phy_id == phy->addr) + break; + } else { + /* autoselect PHY if none was specified */ + if (phy->addr != 0) + break; + } + } + } + + if (!phy) { + dev_err(&dev->dev, "no PHY found\n"); + return -ENXIO; + } + + phy = phy_connect(dev, dev_name(&phy->dev), ðoc_mdio_poll, 0, + PHY_INTERFACE_MODE_GMII); + if (IS_ERR(phy)) { + dev_err(&dev->dev, "could not attach to PHY\n"); + return PTR_ERR(phy); + } + + priv->phy = phy; + return 0; +} + +static int ethoc_open(struct net_device *dev) +{ + struct ethoc *priv = netdev_priv(dev); + unsigned int min_tx = 2; + unsigned int num_bd; + int ret; + + ret = request_irq(dev->irq, ethoc_interrupt, IRQF_SHARED, + dev->name, dev); + if (ret) + return ret; + + /* calculate the number of TX/RX buffers */ + num_bd = (dev->mem_end - dev->mem_start + 1) / ETHOC_BUFSIZ; + priv->num_tx = min(min_tx, num_bd / 4); + priv->num_rx = num_bd - priv->num_tx; + ethoc_write(priv, TX_BD_NUM, priv->num_tx); + + ethoc_init_ring(priv); + ethoc_reset(priv); + + if (netif_queue_stopped(dev)) { + dev_dbg(&dev->dev, " resuming queue\n"); + netif_wake_queue(dev); + } else { + dev_dbg(&dev->dev, " starting queue\n"); + netif_start_queue(dev); + } + + phy_start(priv->phy); + napi_enable(&priv->napi); + + if (netif_msg_ifup(priv)) { + dev_info(&dev->dev, "I/O: %08lx Memory: %08lx-%08lx\n", + dev->base_addr, dev->mem_start, dev->mem_end); + } + + return 0; +} + +static int ethoc_stop(struct net_device *dev) +{ + struct ethoc *priv = netdev_priv(dev); + + napi_disable(&priv->napi); + + if (priv->phy) + phy_stop(priv->phy); + + ethoc_disable_rx_and_tx(priv); + free_irq(dev->irq, dev); + + if (!netif_queue_stopped(dev)) + netif_stop_queue(dev); + + return 0; +} + +static int ethoc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + struct ethoc *priv = netdev_priv(dev); + struct mii_ioctl_data *mdio = if_mii(ifr); + struct phy_device *phy = NULL; + + if (!netif_running(dev)) + return -EINVAL; + + if (cmd != SIOCGMIIPHY) { + if (mdio->phy_id >= PHY_MAX_ADDR) + return -ERANGE; + + phy = priv->mdio->phy_map[mdio->phy_id]; + if (!phy) + return -ENODEV; + } else { + phy = priv->phy; + } + + return phy_mii_ioctl(phy, mdio, cmd); +} + +static int ethoc_config(struct net_device *dev, struct ifmap *map) +{ + return -ENOSYS; +} + +static int ethoc_set_mac_address(struct net_device *dev, void *addr) +{ + struct ethoc *priv = netdev_priv(dev); + u8 *mac = (u8 *)addr; + + ethoc_write(priv, MAC_ADDR0, (mac[2] << 24) | (mac[3] << 16) | + (mac[4] << 8) | (mac[5] << 0)); + ethoc_write(priv, MAC_ADDR1, (mac[0] << 8) | (mac[1] << 0)); + + return 0; +} + +static void ethoc_set_multicast_list(struct net_device *dev) +{ + struct ethoc *priv = netdev_priv(dev); + u32 mode = ethoc_read(priv, MODER); + struct dev_mc_list *mc = NULL; + u32 hash[2] = { 0, 0 }; + + /* set loopback mode if requested */ + if (dev->flags & IFF_LOOPBACK) + mode |= MODER_LOOP; + else + mode &= ~MODER_LOOP; + + /* receive broadcast frames if requested */ + if (dev->flags & IFF_BROADCAST) + mode &= ~MODER_BRO; + else + mode |= MODER_BRO; + + /* enable promiscuous mode if requested */ + if (dev->flags & IFF_PROMISC) + mode |= MODER_PRO; + else + mode &= ~MODER_PRO; + + ethoc_write(priv, MODER, mode); + + /* receive multicast frames */ + if (dev->flags & IFF_ALLMULTI) { + hash[0] = 0xffffffff; + hash[1] = 0xffffffff; + } else { + for (mc = dev->mc_list; mc; mc = mc->next) { + u32 crc = ether_crc(mc->dmi_addrlen, mc->dmi_addr); + int bit = (crc >> 26) & 0x3f; + hash[bit >> 5] |= 1 << (bit & 0x1f); + } + } + + ethoc_write(priv, ETH_HASH0, hash[0]); + ethoc_write(priv, ETH_HASH1, hash[1]); +} + +static int ethoc_change_mtu(struct net_device *dev, int new_mtu) +{ + return -ENOSYS; +} + +static void ethoc_tx_timeout(struct net_device *dev) +{ + struct ethoc *priv = netdev_priv(dev); + u32 pending = ethoc_read(priv, INT_SOURCE); + if (likely(pending)) + ethoc_interrupt(dev->irq, dev); +} + +static struct net_device_stats *ethoc_stats(struct net_device *dev) +{ + struct ethoc *priv = netdev_priv(dev); + return &priv->stats; +} + +static int ethoc_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct ethoc *priv = netdev_priv(dev); + struct ethoc_bd bd; + unsigned int entry; + void *dest; + + if (unlikely(skb->len > ETHOC_BUFSIZ)) { + priv->stats.tx_errors++; + return -EMSGSIZE; + } + + entry = priv->cur_tx % priv->num_tx; + spin_lock_irq(&priv->lock); + priv->cur_tx++; + + ethoc_read_bd(priv, entry, &bd); + if (unlikely(skb->len < ETHOC_ZLEN)) + bd.stat |= TX_BD_PAD; + else + bd.stat &= ~TX_BD_PAD; + + dest = priv->membase + bd.addr; + memcpy_toio(dest, skb->data, skb->len); + + bd.stat &= ~(TX_BD_STATS | TX_BD_LEN_MASK); + bd.stat |= TX_BD_LEN(skb->len); + ethoc_write_bd(priv, entry, &bd); + + bd.stat |= TX_BD_READY; + ethoc_write_bd(priv, entry, &bd); + + if (priv->cur_tx == (priv->dty_tx + priv->num_tx)) { + dev_dbg(&dev->dev, "stopping queue\n"); + netif_stop_queue(dev); + } + + dev->trans_start = jiffies; + dev_kfree_skb(skb); + + spin_unlock_irq(&priv->lock); + return NETDEV_TX_OK; +} + +static const struct net_device_ops ethoc_netdev_ops = { + .ndo_open = ethoc_open, + .ndo_stop = ethoc_stop, + .ndo_do_ioctl = ethoc_ioctl, + .ndo_set_config = ethoc_config, + .ndo_set_mac_address = ethoc_set_mac_address, + .ndo_set_multicast_list = ethoc_set_multicast_list, + .ndo_change_mtu = ethoc_change_mtu, + .ndo_tx_timeout = ethoc_tx_timeout, + .ndo_get_stats = ethoc_stats, + .ndo_start_xmit = ethoc_start_xmit, +}; + +/** + * ethoc_probe() - initialize OpenCores ethernet MAC + * pdev: platform device + */ +static int ethoc_probe(struct platform_device *pdev) +{ + struct net_device *netdev = NULL; + struct resource *res = NULL; + struct resource *mmio = NULL; + struct resource *mem = NULL; + struct ethoc *priv = NULL; + unsigned int phy; + int ret = 0; + + /* allocate networking device */ + netdev = alloc_etherdev(sizeof(struct ethoc)); + if (!netdev) { + dev_err(&pdev->dev, "cannot allocate network device\n"); + ret = -ENOMEM; + goto out; + } + + SET_NETDEV_DEV(netdev, &pdev->dev); + platform_set_drvdata(pdev, netdev); + + /* obtain I/O memory space */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "cannot obtain I/O memory space\n"); + ret = -ENXIO; + goto free; + } + + mmio = devm_request_mem_region(&pdev->dev, res->start, + res->end - res->start + 1, res->name); + if (!res) { + dev_err(&pdev->dev, "cannot request I/O memory space\n"); + ret = -ENXIO; + goto free; + } + + netdev->base_addr = mmio->start; + + /* obtain buffer memory space */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res) { + dev_err(&pdev->dev, "cannot obtain memory space\n"); + ret = -ENXIO; + goto free; + } + + mem = devm_request_mem_region(&pdev->dev, res->start, + res->end - res->start + 1, res->name); + if (!mem) { + dev_err(&pdev->dev, "cannot request memory space\n"); + ret = -ENXIO; + goto free; + } + + netdev->mem_start = mem->start; + netdev->mem_end = mem->end; + + /* obtain device IRQ number */ + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(&pdev->dev, "cannot obtain IRQ\n"); + ret = -ENXIO; + goto free; + } + + netdev->irq = res->start; + + /* setup driver-private data */ + priv = netdev_priv(netdev); + priv->netdev = netdev; + + priv->iobase = devm_ioremap_nocache(&pdev->dev, netdev->base_addr, + mmio->end - mmio->start + 1); + if (!priv->iobase) { + dev_err(&pdev->dev, "cannot remap I/O memory space\n"); + ret = -ENXIO; + goto error; + } + + priv->membase = devm_ioremap_nocache(&pdev->dev, netdev->mem_start, + mem->end - mem->start + 1); + if (!priv->membase) { + dev_err(&pdev->dev, "cannot remap memory space\n"); + ret = -ENXIO; + goto error; + } + + /* Allow the platform setup code to pass in a MAC address. */ + if (pdev->dev.platform_data) { + struct ethoc_platform_data *pdata = + (struct ethoc_platform_data *)pdev->dev.platform_data; + memcpy(netdev->dev_addr, pdata->hwaddr, IFHWADDRLEN); + priv->phy_id = pdata->phy_id; + } + + /* Check that the given MAC address is valid. If it isn't, read the + * current MAC from the controller. */ + if (!is_valid_ether_addr(netdev->dev_addr)) + ethoc_get_mac_address(netdev, netdev->dev_addr); + + /* Check the MAC again for validity, if it still isn't choose and + * program a random one. */ + if (!is_valid_ether_addr(netdev->dev_addr)) + random_ether_addr(netdev->dev_addr); + + ethoc_set_mac_address(netdev, netdev->dev_addr); + + /* register MII bus */ + priv->mdio = mdiobus_alloc(); + if (!priv->mdio) { + ret = -ENOMEM; + goto free; + } + + priv->mdio->name = "ethoc-mdio"; + snprintf(priv->mdio->id, MII_BUS_ID_SIZE, "%s-%d", + priv->mdio->name, pdev->id); + priv->mdio->read = ethoc_mdio_read; + priv->mdio->write = ethoc_mdio_write; + priv->mdio->reset = ethoc_mdio_reset; + priv->mdio->priv = priv; + + priv->mdio->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); + if (!priv->mdio->irq) { + ret = -ENOMEM; + goto free_mdio; + } + + for (phy = 0; phy < PHY_MAX_ADDR; phy++) + priv->mdio->irq[phy] = PHY_POLL; + + ret = mdiobus_register(priv->mdio); + if (ret) { + dev_err(&netdev->dev, "failed to register MDIO bus\n"); + goto free_mdio; + } + + ret = ethoc_mdio_probe(netdev); + if (ret) { + dev_err(&netdev->dev, "failed to probe MDIO bus\n"); + goto error; + } + + ether_setup(netdev); + + /* setup the net_device structure */ + netdev->netdev_ops = ðoc_netdev_ops; + netdev->watchdog_timeo = ETHOC_TIMEOUT; + netdev->features |= 0; + + /* setup NAPI */ + memset(&priv->napi, 0, sizeof(priv->napi)); + netif_napi_add(netdev, &priv->napi, ethoc_poll, 64); + + spin_lock_init(&priv->rx_lock); + spin_lock_init(&priv->lock); + + ret = register_netdev(netdev); + if (ret < 0) { + dev_err(&netdev->dev, "failed to register interface\n"); + goto error; + } + + goto out; + +error: + mdiobus_unregister(priv->mdio); +free_mdio: + kfree(priv->mdio->irq); + mdiobus_free(priv->mdio); +free: + free_netdev(netdev); +out: + return ret; +} + +/** + * ethoc_remove() - shutdown OpenCores ethernet MAC + * @pdev: platform device + */ +static int ethoc_remove(struct platform_device *pdev) +{ + struct net_device *netdev = platform_get_drvdata(pdev); + struct ethoc *priv = netdev_priv(netdev); + + platform_set_drvdata(pdev, NULL); + + if (netdev) { + phy_disconnect(priv->phy); + priv->phy = NULL; + + if (priv->mdio) { + mdiobus_unregister(priv->mdio); + kfree(priv->mdio->irq); + mdiobus_free(priv->mdio); + } + + unregister_netdev(netdev); + free_netdev(netdev); + } + + return 0; +} + +#ifdef CONFIG_PM +static int ethoc_suspend(struct platform_device *pdev, pm_message_t state) +{ + return -ENOSYS; +} + +static int ethoc_resume(struct platform_device *pdev) +{ + return -ENOSYS; +} +#else +# define ethoc_suspend NULL +# define ethoc_resume NULL +#endif + +static struct platform_driver ethoc_driver = { + .probe = ethoc_probe, + .remove = ethoc_remove, + .suspend = ethoc_suspend, + .resume = ethoc_resume, + .driver = { + .name = "ethoc", + }, +}; + +static int __init ethoc_init(void) +{ + return platform_driver_register(ðoc_driver); +} + +static void __exit ethoc_exit(void) +{ + platform_driver_unregister(ðoc_driver); +} + +module_init(ethoc_init); +module_exit(ethoc_exit); + +MODULE_AUTHOR("Thierry Reding "); +MODULE_DESCRIPTION("OpenCores Ethernet MAC driver"); +MODULE_LICENSE("GPL v2"); + diff --git a/include/net/ethoc.h b/include/net/ethoc.h new file mode 100644 index 00000000000..96f3789b27b --- /dev/null +++ b/include/net/ethoc.h @@ -0,0 +1,22 @@ +/* + * linux/include/net/ethoc.h + * + * Copyright (C) 2008-2009 Avionic Design GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Written by Thierry Reding + */ + +#ifndef LINUX_NET_ETHOC_H +#define LINUX_NET_ETHOC_H 1 + +struct ethoc_platform_data { + u8 hwaddr[IFHWADDRLEN]; + s8 phy_id; +}; + +#endif /* !LINUX_NET_ETHOC_H */ + -- GitLab From 71f6f6dfdf7c7a67462386d9ea05c1095a89c555 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Fri, 27 Mar 2009 00:17:45 -0700 Subject: [PATCH 4718/4982] ipv6: Plug sk_buff leak in ipv6_rcv (net/ipv6/ip6_input.c) Commit 778d80be52699596bf70e0eb0761cf5e1e46088d (ipv6: Add disable_ipv6 sysctl to disable IPv6 operaion on specific interface) seems to have introduced a leak of sk_buff's for ipv6 traffic, at least in some configurations where idev is NULL, or when ipv6 is disabled via sysctl. The problem is that if the first condition of the if-statement returns non-NULL, it returns an skb with only one reference, and when the other conditions apply, execution jumps to the "out" label, which does not call kfree_skb for it. To plug this leak, change to use the "drop" label instead. (this relies on it being ok to call kfree_skb on NULL) This also allows us to avoid calling rcu_read_unlock here, and removes the only user of the "out" label. Signed-off-by: Jesper Nilsson Signed-off-by: David S. Miller --- net/ipv6/ip6_input.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index f171e8dbac9..8f04bd9da27 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -75,8 +75,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL || !idev || unlikely(idev->cnf.disable_ipv6)) { IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDISCARDS); - rcu_read_unlock(); - goto out; + goto drop; } memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm)); @@ -147,7 +146,6 @@ err: drop: rcu_read_unlock(); kfree_skb(skb); -out: return 0; } -- GitLab From 7d0b591c655ca0d72ebcbd242cf659a20a8995c5 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Fri, 27 Mar 2009 00:22:01 -0700 Subject: [PATCH 4719/4982] xfrm: spin_lock() should be spin_unlock() in xfrm_state.c spin_lock() should be spin_unlock() in xfrm_state_walk_done(). caused by: commit 12a169e7d8f4b1c95252d8b04ed0f1033ed7cfe2 "ipsec: Put dumpers on the dump list" Reported-by: Marc Milgram Signed-off-by: Chuck Ebbert Signed-off-by: David S. Miller --- net/xfrm/xfrm_state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 62a5425cc6a..82271720d97 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -1615,7 +1615,7 @@ void xfrm_state_walk_done(struct xfrm_state_walk *walk) spin_lock_bh(&xfrm_state_lock); list_del(&walk->all); - spin_lock_bh(&xfrm_state_lock); + spin_unlock_bh(&xfrm_state_lock); } EXPORT_SYMBOL(xfrm_state_walk_done); -- GitLab From 65f71b8bd2651e6d6ca9b09fe53a8db2da22b85c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 27 Mar 2009 00:25:24 -0700 Subject: [PATCH 4720/4982] benet: use do_div() for 64 bit divide The benet driver is doing a 64 bit divide, which is not supported in Linux kernel on 32 bit architectures. The correct way to do this is to use do_div(). Compile tested on i386 only. Signed-off-by: Stephen Hemminger Acked-by: Randy Dunlap Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index f901fee79a2..9b75aa63006 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -16,6 +16,7 @@ */ #include "be.h" +#include MODULE_VERSION(DRV_VER); MODULE_DEVICE_TABLE(pci, be_dev_ids); @@ -290,6 +291,17 @@ static struct net_device_stats *be_get_stats(struct net_device *dev) return &adapter->stats.net_stats; } +static u32 be_calc_rate(u64 bytes, unsigned long ticks) +{ + u64 rate = bytes; + + do_div(rate, ticks / HZ); + rate <<= 3; /* bytes/sec -> bits/sec */ + do_div(rate, 1000000ul); /* MB/Sec */ + + return rate; +} + static void be_tx_rate_update(struct be_adapter *adapter) { struct be_drvr_stats *stats = drvr_stats(adapter); @@ -303,11 +315,9 @@ static void be_tx_rate_update(struct be_adapter *adapter) /* Update tx rate once in two seconds */ if ((now - stats->be_tx_jiffies) > 2 * HZ) { - u32 r; - r = (stats->be_tx_bytes - stats->be_tx_bytes_prev) / - ((now - stats->be_tx_jiffies) / HZ); - r = r / 1000000; /* M bytes/s */ - stats->be_tx_rate = r * 8; /* M bits/s */ + stats->be_tx_rate = be_calc_rate(stats->be_tx_bytes + - stats->be_tx_bytes_prev, + now - stats->be_tx_jiffies); stats->be_tx_jiffies = now; stats->be_tx_bytes_prev = stats->be_tx_bytes; } @@ -599,7 +609,6 @@ static void be_rx_rate_update(struct be_adapter *adapter) { struct be_drvr_stats *stats = drvr_stats(adapter); ulong now = jiffies; - u32 rate; /* Wrapped around */ if (time_before(now, stats->be_rx_jiffies)) { @@ -611,10 +620,9 @@ static void be_rx_rate_update(struct be_adapter *adapter) if ((now - stats->be_rx_jiffies) < 2 * HZ) return; - rate = (stats->be_rx_bytes - stats->be_rx_bytes_prev) / - ((now - stats->be_rx_jiffies) / HZ); - rate = rate / 1000000; /* MB/Sec */ - stats->be_rx_rate = rate * 8; /* Mega Bits/Sec */ + stats->be_rx_rate = be_calc_rate(stats->be_rx_bytes + - stats->be_rx_bytes_prev, + now - stats->be_rx_jiffies); stats->be_rx_jiffies = now; stats->be_rx_bytes_prev = stats->be_rx_bytes; } -- GitLab From 03ba999117eb8688252f9068356b6e028c2c3a56 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 27 Mar 2009 00:27:18 -0700 Subject: [PATCH 4721/4982] appletalk: this warning can go I think Its past 2.2 ... Signed-off-by: Alan Cox Signed-off-by: David S. Miller --- net/appletalk/ddp.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 3e0671df3a3..d6a9243641a 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -1571,14 +1571,10 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr usat->sat_family != AF_APPLETALK) return -EINVAL; - /* netatalk doesn't implement this check */ + /* netatalk didn't implement this check */ if (usat->sat_addr.s_node == ATADDR_BCAST && !sock_flag(sk, SOCK_BROADCAST)) { - printk(KERN_INFO "SO_BROADCAST: Fix your netatalk as " - "it will break before 2.2\n"); -#if 0 return -EPERM; -#endif } } else { if (sk->sk_state != TCP_ESTABLISHED) -- GitLab From 83e0bbcbe2145f160fbaa109b0439dae7f4a38a9 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 27 Mar 2009 00:28:21 -0700 Subject: [PATCH 4722/4982] af_rose/x25: Sanity check the maximum user frame size Otherwise we can wrap the sizes and end up sending garbage. Closes #10423 Signed-off-by: Alan Cox Signed-off-by: David S. Miller --- net/netrom/af_netrom.c | 6 +++++- net/rose/af_rose.c | 4 ++++ net/x25/af_x25.c | 6 ++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 6d9c58ec56a..d1c16bbee93 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -1086,7 +1086,11 @@ static int nr_sendmsg(struct kiocb *iocb, struct socket *sock, SOCK_DEBUG(sk, "NET/ROM: sendto: Addresses built.\n"); - /* Build a packet */ + /* Build a packet - the conventional user limit is 236 bytes. We can + do ludicrously large NetROM frames but must not overflow */ + if (len > 65536) + return -EMSGSIZE; + SOCK_DEBUG(sk, "NET/ROM: sendto: building packet.\n"); size = len + NR_NETWORK_LEN + NR_TRANSPORT_LEN; diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 65013962658..0f36e8d59b2 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -1124,6 +1124,10 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock, /* Build a packet */ SOCK_DEBUG(sk, "ROSE: sendto: building packet.\n"); + /* Sanity check the packet size */ + if (len > 65535) + return -EMSGSIZE; + size = len + AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN; if ((skb = sock_alloc_send_skb(sk, size, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL) diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 9ca17b1ce52..ed80af8ca5f 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -1035,6 +1035,12 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock, sx25.sx25_addr = x25->dest_addr; } + /* Sanity check the packet size */ + if (len > 65535) { + rc = -EMSGSIZE; + goto out; + } + SOCK_DEBUG(sk, "x25_sendmsg: sendto: Addresses built.\n"); /* Build a packet */ -- GitLab From 54dc79fe0d895758bdaa1dcf8512d3d21263d105 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 27 Mar 2009 00:38:45 -0700 Subject: [PATCH 4723/4982] gianfar: fix headroom expansion code The code that was added to increase headroom was wrong. It doesn't handle the case where gfar_add_fcb() changes the skb. Better to do check at start of transmit (outside of lock), where error handling is better anyway. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 46 ++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 9d81e7a48db..a7a67376615 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -1239,19 +1239,9 @@ static int gfar_enet_open(struct net_device *dev) return err; } -static inline struct txfcb *gfar_add_fcb(struct sk_buff **skbp) +static inline struct txfcb *gfar_add_fcb(struct sk_buff *skb) { - struct txfcb *fcb; - struct sk_buff *skb = *skbp; - - if (unlikely(skb_headroom(skb) < GMAC_FCB_LEN)) { - struct sk_buff *old_skb = skb; - skb = skb_realloc_headroom(old_skb, GMAC_FCB_LEN); - if (!skb) - return NULL; - dev_kfree_skb_any(old_skb); - } - fcb = (struct txfcb *)skb_push(skb, GMAC_FCB_LEN); + struct txfcb *fcb = (struct txfcb *)skb_push(skb, GMAC_FCB_LEN); cacheable_memzero(fcb, GMAC_FCB_LEN); return fcb; @@ -1320,6 +1310,20 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) base = priv->tx_bd_base; + /* make space for additional header */ + if (skb_headroom(skb) < GMAC_FCB_LEN) { + struct sk_buff *skb_new; + + skb_new = skb_realloc_headroom(skb, GMAC_FCB_LEN); + if (!skb_new) { + dev->stats.tx_errors++; + kfree(skb); + return NETDEV_TX_OK; + } + kfree_skb(skb); + skb = skb_new; + } + /* total number of fragments in the SKB */ nr_frags = skb_shinfo(skb)->nr_frags; @@ -1372,20 +1376,18 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Set up checksumming */ if (CHECKSUM_PARTIAL == skb->ip_summed) { - fcb = gfar_add_fcb(&skb); - if (likely(fcb != NULL)) { - lstatus |= BD_LFLAG(TXBD_TOE); - gfar_tx_checksum(skb, fcb); - } + fcb = gfar_add_fcb(skb); + lstatus |= BD_LFLAG(TXBD_TOE); + gfar_tx_checksum(skb, fcb); } if (priv->vlgrp && vlan_tx_tag_present(skb)) { - if (unlikely(NULL == fcb)) - fcb = gfar_add_fcb(&skb); - if (likely(fcb != NULL)) { + if (unlikely(NULL == fcb)) { + fcb = gfar_add_fcb(skb); lstatus |= BD_LFLAG(TXBD_TOE); - gfar_tx_vlan(skb, fcb); } + + gfar_tx_vlan(skb, fcb); } /* setup the TxBD length and buffer pointer for the first BD */ @@ -1433,7 +1435,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Unlock priv */ spin_unlock_irqrestore(&priv->txlock, flags); - return 0; + return NETDEV_TX_OK; } /* Stops the kernel queue, and halts the controller */ -- GitLab From 58add9fc02e7a9dbab9d80d5fa64f13972e91eb5 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Thu, 26 Mar 2009 07:14:36 +0000 Subject: [PATCH 4724/4982] smsc911x: enforce read-after-write timing restriction on eeprom access The LAN911x datasheet specifies a minimum delay of 45ns between a write of E2P_DATA and any read. This patch adds a single dummy read of BYTE_TEST to enforce this timing constraint. Signed-off-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/smsc911x.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index ad3cbc91a8f..af8f60ca0f5 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1680,6 +1680,7 @@ static int smsc911x_eeprom_write_location(struct smsc911x_data *pdata, u8 address, u8 data) { u32 op = E2P_CMD_EPC_CMD_ERASE_ | address; + u32 temp; int ret; SMSC_TRACE(DRV, "address 0x%x, data 0x%x", address, data); @@ -1688,6 +1689,10 @@ static int smsc911x_eeprom_write_location(struct smsc911x_data *pdata, if (!ret) { op = E2P_CMD_EPC_CMD_WRITE_ | address; smsc911x_reg_write(pdata, E2P_DATA, (u32)data); + + /* Workaround for hardware read-after-write restriction */ + temp = smsc911x_reg_read(pdata, BYTE_TEST); + ret = smsc911x_eeprom_send_cmd(pdata, op); } -- GitLab From 1ace90fe0a36ae9da0b2e1211e6a30ec244e9bd0 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:15 +0000 Subject: [PATCH 4725/4982] 3c503, smc-ultra: netdev_ops bugs A couple of drivers have leftovers from netdev ops conversion. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/3c503.c | 3 --- drivers/net/smc-ultra.c | 3 --- 2 files changed, 6 deletions(-) diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c index 5b91a85fe10..4f08bd99583 100644 --- a/drivers/net/3c503.c +++ b/drivers/net/3c503.c @@ -353,9 +353,6 @@ el2_probe1(struct net_device *dev, int ioaddr) dev->netdev_ops = &el2_netdev_ops; dev->ethtool_ops = &netdev_ethtool_ops; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = eip_poll; -#endif retval = register_netdev(dev); if (retval) diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c index 2033fee3143..f56f5e4083b 100644 --- a/drivers/net/smc-ultra.c +++ b/drivers/net/smc-ultra.c @@ -142,9 +142,6 @@ static int __init do_ultra_probe(struct net_device *dev) int base_addr = dev->base_addr; int irq = dev->irq; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = &ultra_poll; -#endif if (base_addr > 0x1ff) /* Check a single specified location. */ return ultra_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ -- GitLab From cfa8707aa65f7ec8ed2130937810b4fb05b40cfa Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:16 +0000 Subject: [PATCH 4726/4982] uml: convert network device to internal network device stats Convert the UML network device to use internal network device stats. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- arch/um/drivers/net_kern.c | 19 ++++++------------- arch/um/include/shared/net_kern.h | 2 +- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index fde510b664d..6d2b1004d1e 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -86,7 +86,7 @@ static int uml_net_rx(struct net_device *dev) drop_skb->dev = dev; /* Read a packet into drop_skb and don't do anything with it. */ (*lp->read)(lp->fd, drop_skb, lp); - lp->stats.rx_dropped++; + dev->stats.rx_dropped++; return 0; } @@ -99,8 +99,8 @@ static int uml_net_rx(struct net_device *dev) skb_trim(skb, pkt_len); skb->protocol = (*lp->protocol)(skb); - lp->stats.rx_bytes += skb->len; - lp->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; + dev->stats.rx_packets++; netif_rx(skb); return pkt_len; } @@ -224,8 +224,8 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev) len = (*lp->write)(lp->fd, skb, lp); if (len == skb->len) { - lp->stats.tx_packets++; - lp->stats.tx_bytes += skb->len; + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; dev->trans_start = jiffies; netif_start_queue(dev); @@ -234,7 +234,7 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev) } else if (len == 0) { netif_start_queue(dev); - lp->stats.tx_dropped++; + dev->stats.tx_dropped++; } else { netif_start_queue(dev); @@ -248,12 +248,6 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } -static struct net_device_stats *uml_net_get_stats(struct net_device *dev) -{ - struct uml_net_private *lp = netdev_priv(dev); - return &lp->stats; -} - static void uml_net_set_multicast_list(struct net_device *dev) { return; @@ -476,7 +470,6 @@ static void eth_configure(int n, void *init, char *mac, dev->open = uml_net_open; dev->hard_start_xmit = uml_net_start_xmit; dev->stop = uml_net_close; - dev->get_stats = uml_net_get_stats; dev->set_multicast_list = uml_net_set_multicast_list; dev->tx_timeout = uml_net_tx_timeout; dev->set_mac_address = uml_net_set_mac; diff --git a/arch/um/include/shared/net_kern.h b/arch/um/include/shared/net_kern.h index d843c7924a7..5c367f22595 100644 --- a/arch/um/include/shared/net_kern.h +++ b/arch/um/include/shared/net_kern.h @@ -26,7 +26,7 @@ struct uml_net_private { spinlock_t lock; struct net_device *dev; struct timer_list tl; - struct net_device_stats stats; + struct work_struct work; int fd; unsigned char mac[ETH_ALEN]; -- GitLab From 8bb95b39a16ed55226810596f92216c53329d2fe Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:17 +0000 Subject: [PATCH 4727/4982] uml: convert network device to netdevice ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- arch/um/drivers/net_kern.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 6d2b1004d1e..434224e2229 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -371,6 +371,18 @@ static void net_device_release(struct device *dev) free_netdev(netdev); } +static const struct net_device_ops uml_netdev_ops = { + .ndo_open = uml_net_open, + .ndo_stop = uml_net_close, + .ndo_start_xmit = uml_net_start_xmit, + .ndo_set_multicast_list = uml_net_set_multicast_list, + .ndo_tx_timeout = uml_net_tx_timeout, + .ndo_set_mac_address = uml_net_set_mac, + .ndo_change_mtu = uml_net_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + /* * Ensures that platform_driver_register is called only once by * eth_configure. Will be set in an initcall. @@ -467,13 +479,7 @@ static void eth_configure(int n, void *init, char *mac, set_ether_mac(dev, device->mac); dev->mtu = transport->user->mtu; - dev->open = uml_net_open; - dev->hard_start_xmit = uml_net_start_xmit; - dev->stop = uml_net_close; - dev->set_multicast_list = uml_net_set_multicast_list; - dev->tx_timeout = uml_net_tx_timeout; - dev->set_mac_address = uml_net_set_mac; - dev->change_mtu = uml_net_change_mtu; + dev->netdev_ops = ¨_netdev_ops; dev->ethtool_ops = ¨_net_ethtool_ops; dev->watchdog_timeo = (HZ >> 1); dev->irq = UM_ETH_IRQ; -- GitLab From 8bbce3f61b63c7502b1d6228d9f59d3c6423a759 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:18 +0000 Subject: [PATCH 4728/4982] appletalk: convert cops to internal net_device_stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/appletalk/cops.c | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c index 54819a34ba0..89632c5855f 100644 --- a/drivers/net/appletalk/cops.c +++ b/drivers/net/appletalk/cops.c @@ -171,7 +171,6 @@ static unsigned int cops_debug = COPS_DEBUG; struct cops_local { - struct net_device_stats stats; int board; /* Holds what board type is. */ int nodeid; /* Set to 1 once have nodeid. */ unsigned char node_acquire; /* Node ID when acquired. */ @@ -197,7 +196,6 @@ static int cops_send_packet (struct sk_buff *skb, struct net_device *dev); static void set_multicast_list (struct net_device *dev); static int cops_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); static int cops_close (struct net_device *dev); -static struct net_device_stats *cops_get_stats (struct net_device *dev); static void cleanup_card(struct net_device *dev) { @@ -337,7 +335,6 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr) dev->tx_timeout = cops_timeout; dev->watchdog_timeo = HZ * 2; - dev->get_stats = cops_get_stats; dev->open = cops_open; dev->stop = cops_close; dev->do_ioctl = cops_ioctl; @@ -797,7 +794,7 @@ static void cops_rx(struct net_device *dev) { printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name); - lp->stats.rx_dropped++; + dev->stats.rx_dropped++; while(pkt_len--) /* Discard packet */ inb(ioaddr); spin_unlock_irqrestore(&lp->lock, flags); @@ -819,7 +816,7 @@ static void cops_rx(struct net_device *dev) { printk(KERN_WARNING "%s: Bad packet length of %d bytes.\n", dev->name, pkt_len); - lp->stats.tx_errors++; + dev->stats.tx_errors++; dev_kfree_skb_any(skb); return; } @@ -836,7 +833,7 @@ static void cops_rx(struct net_device *dev) if(rsp_type != LAP_RESPONSE) { printk(KERN_WARNING "%s: Bad packet type %d.\n", dev->name, rsp_type); - lp->stats.tx_errors++; + dev->stats.tx_errors++; dev_kfree_skb_any(skb); return; } @@ -846,8 +843,8 @@ static void cops_rx(struct net_device *dev) skb_reset_transport_header(skb); /* Point to data (Skip header). */ /* Update the counters. */ - lp->stats.rx_packets++; - lp->stats.rx_bytes += skb->len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; /* Send packet to a higher place. */ netif_rx(skb); @@ -858,7 +855,7 @@ static void cops_timeout(struct net_device *dev) struct cops_local *lp = netdev_priv(dev); int ioaddr = dev->base_addr; - lp->stats.tx_errors++; + dev->stats.tx_errors++; if(lp->board==TANGENT) { if((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0) @@ -916,8 +913,8 @@ static int cops_send_packet(struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&lp->lock, flags); /* Restore interrupts. */ /* Done sending packet, update counters and cleanup. */ - lp->stats.tx_packets++; - lp->stats.tx_bytes += skb->len; + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; dev->trans_start = jiffies; dev_kfree_skb (skb); return 0; @@ -986,15 +983,6 @@ static int cops_close(struct net_device *dev) return 0; } -/* - * Get the current statistics. - * This may be called with the card open or closed. - */ -static struct net_device_stats *cops_get_stats(struct net_device *dev) -{ - struct cops_local *lp = netdev_priv(dev); - return &lp->stats; -} #ifdef MODULE static struct net_device *cops_dev; -- GitLab From c2839d433de2fee2216b41ef8222708949bf989f Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:19 +0000 Subject: [PATCH 4729/4982] appltetalk: convert cops device to net_device ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/appletalk/cops.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c index 89632c5855f..7f832541980 100644 --- a/drivers/net/appletalk/cops.c +++ b/drivers/net/appletalk/cops.c @@ -258,6 +258,15 @@ out: return ERR_PTR(err); } +static const struct net_device_ops cops_netdev_ops = { + .ndo_open = cops_open, + .ndo_stop = cops_close, + .ndo_start_xmit = cops_send_packet, + .ndo_tx_timeout = cops_timeout, + .ndo_do_ioctl = cops_ioctl, + .ndo_set_multicast_list = set_multicast_list, +}; + /* * This is the real probe routine. Linux has a history of friendly device * probes on the ISA bus. A good device probes avoids doing writes, and @@ -331,15 +340,9 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr) /* Copy local board variable to lp struct. */ lp->board = board; - dev->hard_start_xmit = cops_send_packet; - dev->tx_timeout = cops_timeout; + dev->netdev_ops = &cops_netdev_ops; dev->watchdog_timeo = HZ * 2; - dev->open = cops_open; - dev->stop = cops_close; - dev->do_ioctl = cops_ioctl; - dev->set_multicast_list = set_multicast_list; - dev->mc_list = NULL; /* Tell the user where the card is and what mode we're in. */ if(board==DAYNA) -- GitLab From 4fafc12328a4e2d4afbc4541c46be014e22c5b66 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:20 +0000 Subject: [PATCH 4730/4982] appletalk: convert LTPC to use internal net_device_stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/appletalk/ltpc.c | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c index dc4d4960560..74d9787311e 100644 --- a/drivers/net/appletalk/ltpc.c +++ b/drivers/net/appletalk/ltpc.c @@ -261,7 +261,6 @@ static unsigned char *ltdmacbuf; struct ltpc_private { - struct net_device_stats stats; struct atalk_addr my_addr; }; @@ -699,7 +698,6 @@ static int do_read(struct net_device *dev, void *cbuf, int cbuflen, static struct timer_list ltpc_timer; static int ltpc_xmit(struct sk_buff *skb, struct net_device *dev); -static struct net_device_stats *ltpc_get_stats(struct net_device *dev); static int read_30 ( struct net_device *dev) { @@ -726,8 +724,6 @@ static int sendup_buffer (struct net_device *dev) int dnode, snode, llaptype, len; int sklen; struct sk_buff *skb; - struct ltpc_private *ltpc_priv = netdev_priv(dev); - struct net_device_stats *stats = <pc_priv->stats; struct lt_rcvlap *ltc = (struct lt_rcvlap *) ltdmacbuf; if (ltc->command != LT_RCVLAP) { @@ -779,8 +775,8 @@ static int sendup_buffer (struct net_device *dev) skb_reset_transport_header(skb); - stats->rx_packets++; - stats->rx_bytes+=skb->len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; /* toss it onwards */ netif_rx(skb); @@ -904,10 +900,6 @@ static int ltpc_xmit(struct sk_buff *skb, struct net_device *dev) /* in kernel 1.3.xx, on entry skb->data points to ddp header, * and skb->len is the length of the ddp data + ddp header */ - - struct ltpc_private *ltpc_priv = netdev_priv(dev); - struct net_device_stats *stats = <pc_priv->stats; - int i; struct lt_sendlap cbuf; unsigned char *hdr; @@ -936,20 +928,13 @@ static int ltpc_xmit(struct sk_buff *skb, struct net_device *dev) printk("\n"); } - stats->tx_packets++; - stats->tx_bytes+=skb->len; + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; dev_kfree_skb(skb); return 0; } -static struct net_device_stats *ltpc_get_stats(struct net_device *dev) -{ - struct ltpc_private *ltpc_priv = netdev_priv(dev); - struct net_device_stats *stats = <pc_priv->stats; - return stats; -} - /* initialization stuff */ static int __init ltpc_probe_dma(int base, int dma) @@ -1135,7 +1120,6 @@ struct net_device * __init ltpc_probe(void) /* Fill in the fields of the device structure with ethernet-generic values. */ dev->hard_start_xmit = ltpc_xmit; - dev->get_stats = ltpc_get_stats; /* add the ltpc-specific things */ dev->do_ioctl = <pc_ioctl; -- GitLab From 816b26f500e9d78ccd56e1c8ffac85f5d8765c00 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:21 +0000 Subject: [PATCH 4731/4982] appletalk: convert LTPC to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/appletalk/ltpc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c index 74d9787311e..78cc7146913 100644 --- a/drivers/net/appletalk/ltpc.c +++ b/drivers/net/appletalk/ltpc.c @@ -1012,6 +1012,12 @@ static int __init ltpc_probe_dma(int base, int dma) return (want & 2) ? 3 : 1; } +static const struct net_device_ops ltpc_netdev = { + .ndo_start_xmit = ltpc_xmit, + .ndo_do_ioctl = ltpc_ioctl, + .ndo_set_multicast_list = set_multicast_list, +}; + struct net_device * __init ltpc_probe(void) { struct net_device *dev; @@ -1118,13 +1124,7 @@ struct net_device * __init ltpc_probe(void) else printk(KERN_INFO "Apple/Farallon LocalTalk-PC card at %03x, DMA%d. Using polled mode.\n",io,dma); - /* Fill in the fields of the device structure with ethernet-generic values. */ - dev->hard_start_xmit = ltpc_xmit; - - /* add the ltpc-specific things */ - dev->do_ioctl = <pc_ioctl; - - dev->set_multicast_list = &set_multicast_list; + dev->netdev_ops = <pc_netdev; dev->mc_list = NULL; dev->base_addr = io; dev->irq = irq; -- GitLab From ddec2c89f89b9f2d15ddff07f01570123e95f544 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:22 +0000 Subject: [PATCH 4732/4982] IRDA: convert donauboe to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/irda/donauboe.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c index 6f3e7f71658..6b6548b9fda 100644 --- a/drivers/net/irda/donauboe.c +++ b/drivers/net/irda/donauboe.c @@ -1524,6 +1524,13 @@ toshoboe_close (struct pci_dev *pci_dev) free_netdev(self->netdev); } +static const struct net_device_ops toshoboe_netdev_ops = { + .ndo_open = toshoboe_net_open, + .ndo_stop = toshoboe_net_close, + .ndo_start_xmit = toshoboe_hard_xmit, + .ndo_do_ioctl = toshoboe_net_ioctl, +}; + static int toshoboe_open (struct pci_dev *pci_dev, const struct pci_device_id *pdid) { @@ -1657,10 +1664,7 @@ toshoboe_open (struct pci_dev *pci_dev, const struct pci_device_id *pdid) #endif SET_NETDEV_DEV(dev, &pci_dev->dev); - dev->hard_start_xmit = toshoboe_hard_xmit; - dev->open = toshoboe_net_open; - dev->stop = toshoboe_net_close; - dev->do_ioctl = toshoboe_net_ioctl; + dev->netdev_ops = &toshoboe_netdev_ops; err = register_netdev(dev); if (err) -- GitLab From 79f8ae3aa27f2f17a50ad1deee1e16ff02be01bb Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:23 +0000 Subject: [PATCH 4733/4982] tokenring: convert drivers to net_device_ops Convert madge and proteon drivers which are really just subclasses of tms380. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/tokenring/madgemc.c | 11 ++++++----- drivers/net/tokenring/proteon.c | 9 +++++++-- drivers/net/tokenring/skisa.c | 9 +++++++-- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c index 193308118f9..456f8bff40b 100644 --- a/drivers/net/tokenring/madgemc.c +++ b/drivers/net/tokenring/madgemc.c @@ -142,7 +142,7 @@ static void madgemc_sifwritew(struct net_device *dev, unsigned short val, unsign return; } - +static struct net_device_ops madgemc_netdev_ops __read_mostly; static int __devinit madgemc_probe(struct device *device) { @@ -168,7 +168,7 @@ static int __devinit madgemc_probe(struct device *device) goto getout; } - dev->dma = 0; + dev->netdev_ops = &madgemc_netdev_ops; card = kmalloc(sizeof(struct card_info), GFP_KERNEL); if (card==NULL) { @@ -348,9 +348,6 @@ static int __devinit madgemc_probe(struct device *device) memcpy(tp->ProductID, "Madge MCA 16/4 ", PROD_ID_SIZE + 1); - dev->open = madgemc_open; - dev->stop = madgemc_close; - tp->tmspriv = card; dev_set_drvdata(device, dev); @@ -758,6 +755,10 @@ static struct mca_driver madgemc_driver = { static int __init madgemc_init (void) { + madgemc_netdev_ops = tms380tr_netdev_ops; + madgemc_netdev_ops.ndo_open = madgemc_open; + madgemc_netdev_ops.ndo_stop = madgemc_close; + return mca_register_driver (&madgemc_driver); } diff --git a/drivers/net/tokenring/proteon.c b/drivers/net/tokenring/proteon.c index b8c955f6d31..16e8783ee9c 100644 --- a/drivers/net/tokenring/proteon.c +++ b/drivers/net/tokenring/proteon.c @@ -116,6 +116,8 @@ nodev: return -ENODEV; } +static struct net_device_ops proteon_netdev_ops __read_mostly; + static int __init setup_card(struct net_device *dev, struct device *pdev) { struct net_local *tp; @@ -167,8 +169,7 @@ static int __init setup_card(struct net_device *dev, struct device *pdev) tp->tmspriv = NULL; - dev->open = proteon_open; - dev->stop = tms380tr_close; + dev->netdev_ops = &proteon_netdev_ops; if (dev->irq == 0) { @@ -352,6 +353,10 @@ static int __init proteon_init(void) struct platform_device *pdev; int i, num = 0, err = 0; + proteon_netdev_ops = tms380tr_netdev_ops; + proteon_netdev_ops.ndo_open = proteon_open; + proteon_netdev_ops.ndo_stop = tms380tr_close; + err = platform_driver_register(&proteon_driver); if (err) return err; diff --git a/drivers/net/tokenring/skisa.c b/drivers/net/tokenring/skisa.c index c0f58f08782..46db5c5395b 100644 --- a/drivers/net/tokenring/skisa.c +++ b/drivers/net/tokenring/skisa.c @@ -133,6 +133,8 @@ static int __init sk_isa_probe1(struct net_device *dev, int ioaddr) return 0; } +static struct net_device_ops sk_isa_netdev_ops __read_mostly; + static int __init setup_card(struct net_device *dev, struct device *pdev) { struct net_local *tp; @@ -184,8 +186,7 @@ static int __init setup_card(struct net_device *dev, struct device *pdev) tp->tmspriv = NULL; - dev->open = sk_isa_open; - dev->stop = tms380tr_close; + dev->netdev_ops = &sk_isa_netdev_ops; if (dev->irq == 0) { @@ -362,6 +363,10 @@ static int __init sk_isa_init(void) struct platform_device *pdev; int i, num = 0, err = 0; + sk_isa_netdev_ops = tms380tr_netdev_ops; + sk_isa_netdev_ops.ndo_open = sk_isa_open; + sk_isa_netdev_ops.ndo_stop = tms380tr_close; + err = platform_driver_register(&sk_isa_driver); if (err) return err; -- GitLab From f70d59492ed8bc1d74b364ebe2b97ef6705910b1 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:24 +0000 Subject: [PATCH 4734/4982] tokenring: convert smctr to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/tokenring/smctr.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c index 9d7db2c8d66..a91d9c55d78 100644 --- a/drivers/net/tokenring/smctr.c +++ b/drivers/net/tokenring/smctr.c @@ -124,7 +124,6 @@ static unsigned int smctr_get_num_rx_bdbs(struct net_device *dev); static int smctr_get_physical_drop_number(struct net_device *dev); static __u8 *smctr_get_rx_pointer(struct net_device *dev, short queue); static int smctr_get_station_id(struct net_device *dev); -static struct net_device_stats *smctr_get_stats(struct net_device *dev); static FCBlock *smctr_get_tx_fcb(struct net_device *dev, __u16 queue, __u16 bytes_count); static int smctr_get_upstream_neighbor_addr(struct net_device *dev); @@ -3633,6 +3632,14 @@ out: return ERR_PTR(err); } +static const struct net_device_ops smctr_netdev_ops = { + .ndo_open = smctr_open, + .ndo_stop = smctr_close, + .ndo_start_xmit = smctr_send_packet, + .ndo_tx_timeout = smctr_timeout, + .ndo_get_stats = smctr_get_stats, + .ndo_set_multicast_list = smctr_set_multicast_list, +}; static int __init smctr_probe1(struct net_device *dev, int ioaddr) { @@ -3683,13 +3690,8 @@ static int __init smctr_probe1(struct net_device *dev, int ioaddr) (unsigned int)dev->base_addr, dev->irq, tp->rom_base, tp->ram_base); - dev->open = smctr_open; - dev->stop = smctr_close; - dev->hard_start_xmit = smctr_send_packet; - dev->tx_timeout = smctr_timeout; + dev->netdev_ops = &smctr_netdev_ops; dev->watchdog_timeo = HZ; - dev->get_stats = smctr_get_stats; - dev->set_multicast_list = &smctr_set_multicast_list; return (0); out: -- GitLab From ac99533fb716171db12798039671f19631cf3586 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:25 +0000 Subject: [PATCH 4735/4982] wan: convert sdla driver to net_device_ops Also use internal net_device_stats Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wan/sdla.c | 36 +++++++++++++++--------------------- include/linux/if_frad.h | 1 - 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c index 6a07ba9371d..1d637f407a0 100644 --- a/drivers/net/wan/sdla.c +++ b/drivers/net/wan/sdla.c @@ -714,19 +714,19 @@ static int sdla_transmit(struct sk_buff *skb, struct net_device *dev) switch (ret) { case SDLA_RET_OK: - flp->stats.tx_packets++; + dev->stats.tx_packets++; ret = DLCI_RET_OK; break; case SDLA_RET_CIR_OVERFLOW: case SDLA_RET_BUF_OVERSIZE: case SDLA_RET_NO_BUFS: - flp->stats.tx_dropped++; + dev->stats.tx_dropped++; ret = DLCI_RET_DROP; break; default: - flp->stats.tx_errors++; + dev->stats.tx_errors++; ret = DLCI_RET_ERR; break; } @@ -807,7 +807,7 @@ static void sdla_receive(struct net_device *dev) if (i == CONFIG_DLCI_MAX) { printk(KERN_NOTICE "%s: Received packet from invalid DLCI %i, ignoring.", dev->name, dlci); - flp->stats.rx_errors++; + dev->stats.rx_errors++; success = 0; } } @@ -819,7 +819,7 @@ static void sdla_receive(struct net_device *dev) if (skb == NULL) { printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); - flp->stats.rx_dropped++; + dev->stats.rx_dropped++; success = 0; } else @@ -859,7 +859,7 @@ static void sdla_receive(struct net_device *dev) if (success) { - flp->stats.rx_packets++; + dev->stats.rx_packets++; dlp = netdev_priv(master); (*dlp->receive)(skb, master); } @@ -1590,13 +1590,14 @@ fail: return err; } -static struct net_device_stats *sdla_stats(struct net_device *dev) -{ - struct frad_local *flp; - flp = netdev_priv(dev); - - return(&flp->stats); -} +static const struct net_device_ops sdla_netdev_ops = { + .ndo_open = sdla_open, + .ndo_stop = sdla_close, + .ndo_do_ioctl = sdla_ioctl, + .ndo_set_config = sdla_set_config, + .ndo_start_xmit = sdla_transmit, + .ndo_change_mtu = sdla_change_mtu, +}; static void setup_sdla(struct net_device *dev) { @@ -1604,20 +1605,13 @@ static void setup_sdla(struct net_device *dev) netdev_boot_setup_check(dev); + dev->netdev_ops = &sdla_netdev_ops; dev->flags = 0; dev->type = 0xFFFF; dev->hard_header_len = 0; dev->addr_len = 0; dev->mtu = SDLA_MAX_MTU; - dev->open = sdla_open; - dev->stop = sdla_close; - dev->do_ioctl = sdla_ioctl; - dev->set_config = sdla_set_config; - dev->get_stats = sdla_stats; - dev->hard_start_xmit = sdla_transmit; - dev->change_mtu = sdla_change_mtu; - flp->activate = sdla_activate; flp->deactivate = sdla_deactivate; flp->assoc = sdla_assoc; diff --git a/include/linux/if_frad.h b/include/linux/if_frad.h index 60e16a551dd..673f2209453 100644 --- a/include/linux/if_frad.h +++ b/include/linux/if_frad.h @@ -153,7 +153,6 @@ struct frhdr struct dlci_local { - struct net_device_stats stats; struct net_device *master; struct net_device *slave; struct dlci_conf config; -- GitLab From 8fdcf1aba33a61475d411d91ab47c2c9adb3e4c3 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:26 +0000 Subject: [PATCH 4736/4982] wireless: convert arlan to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/arlan-main.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/arlan-main.c b/drivers/net/wireless/arlan-main.c index bfca15da6f0..5b9f1e06ebf 100644 --- a/drivers/net/wireless/arlan-main.c +++ b/drivers/net/wireless/arlan-main.c @@ -1030,7 +1030,17 @@ static int arlan_mac_addr(struct net_device *dev, void *p) return 0; } - +static const struct net_device_ops arlan_netdev_ops = { + .ndo_open = arlan_open, + .ndo_stop = arlan_close, + .ndo_start_xmit = arlan_tx, + .ndo_get_stats = arlan_statistics, + .ndo_set_multicast_list = arlan_set_multicast, + .ndo_change_mtu = arlan_change_mtu, + .ndo_set_mac_address = arlan_mac_addr, + .ndo_tx_timeout = arlan_tx_timeout, + .ndo_validate_addr = eth_validate_addr, +}; static int __init arlan_setup_device(struct net_device *dev, int num) { @@ -1042,14 +1052,7 @@ static int __init arlan_setup_device(struct net_device *dev, int num) ap->conf = (struct arlan_shmem *)(ap+1); dev->tx_queue_len = tx_queue_len; - dev->open = arlan_open; - dev->stop = arlan_close; - dev->hard_start_xmit = arlan_tx; - dev->get_stats = arlan_statistics; - dev->set_multicast_list = arlan_set_multicast; - dev->change_mtu = arlan_change_mtu; - dev->set_mac_address = arlan_mac_addr; - dev->tx_timeout = arlan_tx_timeout; + dev->netdev_ops = &arlan_netdev_ops; dev->watchdog_timeo = 3*HZ; ap->irq_test_done = 0; -- GitLab From 0687478a9977db0698d40f0024d4b06fd42e01a0 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:27 +0000 Subject: [PATCH 4737/4982] wireless: convert wavelan to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/wireless/wavelan.c | 79 +++++++++++++++----------------- drivers/net/wireless/wavelan.p.h | 9 +--- 2 files changed, 37 insertions(+), 51 deletions(-) diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c index b728541f2fb..3ab3eb95718 100644 --- a/drivers/net/wireless/wavelan.c +++ b/drivers/net/wireless/wavelan.c @@ -735,9 +735,9 @@ if (lp->tx_n_in_use > 0) if (tx_status & AC_SFLD_OK) { int ncollisions; - lp->stats.tx_packets++; + dev->stats.tx_packets++; ncollisions = tx_status & AC_SFLD_MAXCOL; - lp->stats.collisions += ncollisions; + dev->stats.collisions += ncollisions; #ifdef DEBUG_TX_INFO if (ncollisions > 0) printk(KERN_DEBUG @@ -745,9 +745,9 @@ if (lp->tx_n_in_use > 0) dev->name, ncollisions); #endif } else { - lp->stats.tx_errors++; + dev->stats.tx_errors++; if (tx_status & AC_SFLD_S10) { - lp->stats.tx_carrier_errors++; + dev->stats.tx_carrier_errors++; #ifdef DEBUG_TX_FAIL printk(KERN_DEBUG "%s: wv_complete(): tx error: no CS.\n", @@ -755,7 +755,7 @@ if (lp->tx_n_in_use > 0) #endif } if (tx_status & AC_SFLD_S9) { - lp->stats.tx_carrier_errors++; + dev->stats.tx_carrier_errors++; #ifdef DEBUG_TX_FAIL printk(KERN_DEBUG "%s: wv_complete(): tx error: lost CTS.\n", @@ -763,7 +763,7 @@ if (lp->tx_n_in_use > 0) #endif } if (tx_status & AC_SFLD_S8) { - lp->stats.tx_fifo_errors++; + dev->stats.tx_fifo_errors++; #ifdef DEBUG_TX_FAIL printk(KERN_DEBUG "%s: wv_complete(): tx error: slow DMA.\n", @@ -771,7 +771,7 @@ if (lp->tx_n_in_use > 0) #endif } if (tx_status & AC_SFLD_S6) { - lp->stats.tx_heartbeat_errors++; + dev->stats.tx_heartbeat_errors++; #ifdef DEBUG_TX_FAIL printk(KERN_DEBUG "%s: wv_complete(): tx error: heart beat.\n", @@ -779,7 +779,7 @@ if (lp->tx_n_in_use > 0) #endif } if (tx_status & AC_SFLD_S5) { - lp->stats.tx_aborted_errors++; + dev->stats.tx_aborted_errors++; #ifdef DEBUG_TX_FAIL printk(KERN_DEBUG "%s: wv_complete(): tx error: too many collisions.\n", @@ -1346,20 +1346,6 @@ static void wv_init_info(struct net_device * dev) * or wireless extensions */ -/*------------------------------------------------------------------*/ -/* - * Get the current Ethernet statistics. This may be called with the - * card open or closed. - * Used when the user read /proc/net/dev - */ -static en_stats *wavelan_get_stats(struct net_device * dev) -{ -#ifdef DEBUG_IOCTL_TRACE - printk(KERN_DEBUG "%s: <>wavelan_get_stats()\n", dev->name); -#endif - - return &((net_local *)netdev_priv(dev))->stats; -} /*------------------------------------------------------------------*/ /* @@ -2466,7 +2452,7 @@ wv_packet_read(struct net_device * dev, u16 buf_off, int sksize) "%s: wv_packet_read(): could not alloc_skb(%d, GFP_ATOMIC).\n", dev->name, sksize); #endif - lp->stats.rx_dropped++; + dev->stats.rx_dropped++; return; } @@ -2526,8 +2512,8 @@ wv_packet_read(struct net_device * dev, u16 buf_off, int sksize) netif_rx(skb); /* Keep statistics up to date */ - lp->stats.rx_packets++; - lp->stats.rx_bytes += sksize; + dev->stats.rx_packets++; + dev->stats.rx_bytes += sksize; #ifdef DEBUG_RX_TRACE printk(KERN_DEBUG "%s: <-wv_packet_read()\n", dev->name); @@ -2608,7 +2594,7 @@ static void wv_receive(struct net_device * dev) #endif } else { /* If reception was no successful */ - lp->stats.rx_errors++; + dev->stats.rx_errors++; #ifdef DEBUG_RX_INFO printk(KERN_DEBUG @@ -2624,7 +2610,7 @@ static void wv_receive(struct net_device * dev) #endif if ((fd.fd_status & FD_STATUS_S7) != 0) { - lp->stats.rx_length_errors++; + dev->stats.rx_length_errors++; #ifdef DEBUG_RX_FAIL printk(KERN_DEBUG "%s: wv_receive(): frame too short.\n", @@ -2633,7 +2619,7 @@ static void wv_receive(struct net_device * dev) } if ((fd.fd_status & FD_STATUS_S8) != 0) { - lp->stats.rx_over_errors++; + dev->stats.rx_over_errors++; #ifdef DEBUG_RX_FAIL printk(KERN_DEBUG "%s: wv_receive(): rx DMA overrun.\n", @@ -2642,7 +2628,7 @@ static void wv_receive(struct net_device * dev) } if ((fd.fd_status & FD_STATUS_S9) != 0) { - lp->stats.rx_fifo_errors++; + dev->stats.rx_fifo_errors++; #ifdef DEBUG_RX_FAIL printk(KERN_DEBUG "%s: wv_receive(): ran out of resources.\n", @@ -2651,7 +2637,7 @@ static void wv_receive(struct net_device * dev) } if ((fd.fd_status & FD_STATUS_S10) != 0) { - lp->stats.rx_frame_errors++; + dev->stats.rx_frame_errors++; #ifdef DEBUG_RX_FAIL printk(KERN_DEBUG "%s: wv_receive(): alignment error.\n", @@ -2660,7 +2646,7 @@ static void wv_receive(struct net_device * dev) } if ((fd.fd_status & FD_STATUS_S11) != 0) { - lp->stats.rx_crc_errors++; + dev->stats.rx_crc_errors++; #ifdef DEBUG_RX_FAIL printk(KERN_DEBUG "%s: wv_receive(): CRC error.\n", @@ -2826,7 +2812,7 @@ static int wv_packet_write(struct net_device * dev, void *buf, short length) dev->trans_start = jiffies; /* Keep stats up to date. */ - lp->stats.tx_bytes += length; + dev->stats.tx_bytes += length; if (lp->tx_first_in_use == I82586NULL) lp->tx_first_in_use = txblock; @@ -4038,6 +4024,22 @@ static int wavelan_close(struct net_device * dev) return 0; } +static const struct net_device_ops wavelan_netdev_ops = { + .ndo_open = wavelan_open, + .ndo_stop = wavelan_close, + .ndo_start_xmit = wavelan_packet_xmit, + .ndo_set_multicast_list = wavelan_set_multicast_list, + .ndo_tx_timeout = wavelan_watchdog, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, +#ifdef SET_MAC_ADDRESS + .ndo_set_mac_address = wavelan_set_mac_address +#else + .ndo_set_mac_address = eth_mac_addr, +#endif +}; + + /*------------------------------------------------------------------*/ /* * Probe an I/O address, and if the WaveLAN is there configure the @@ -4130,17 +4132,8 @@ static int __init wavelan_config(struct net_device *dev, unsigned short ioaddr) /* Init spinlock */ spin_lock_init(&lp->spinlock); - dev->open = wavelan_open; - dev->stop = wavelan_close; - dev->hard_start_xmit = wavelan_packet_xmit; - dev->get_stats = wavelan_get_stats; - dev->set_multicast_list = &wavelan_set_multicast_list; - dev->tx_timeout = &wavelan_watchdog; - dev->watchdog_timeo = WATCHDOG_JIFFIES; -#ifdef SET_MAC_ADDRESS - dev->set_mac_address = &wavelan_set_mac_address; -#endif /* SET_MAC_ADDRESS */ - + dev->netdev_ops = &wavelan_netdev_ops; + dev->watchdog_timeo = WATCHDOG_JIFFIES; dev->wireless_handlers = &wavelan_handler_def; lp->wireless_data.spy_data = &lp->spy_data; dev->wireless_data = &lp->wireless_data; diff --git a/drivers/net/wireless/wavelan.p.h b/drivers/net/wireless/wavelan.p.h index 44d31bbf39e..2daa0210d78 100644 --- a/drivers/net/wireless/wavelan.p.h +++ b/drivers/net/wireless/wavelan.p.h @@ -459,11 +459,9 @@ static const char *version = "wavelan.c : v24 (SMP + wireless extensions) 11/12/ /****************************** TYPES ******************************/ /* Shortcuts */ -typedef struct net_device_stats en_stats; typedef struct iw_statistics iw_stats; typedef struct iw_quality iw_qual; -typedef struct iw_freq iw_freq; -typedef struct net_local net_local; +typedef struct iw_freq iw_freq;typedef struct net_local net_local; typedef struct timer_list timer_list; /* Basic types */ @@ -475,15 +473,12 @@ typedef u_char mac_addr[WAVELAN_ADDR_SIZE]; /* Hardware address */ * For each network interface, Linux keeps data in two structures: "device" * keeps the generic data (same format for everybody) and "net_local" keeps * additional specific data. - * Note that some of this specific data is in fact generic (en_stats, for - * example). */ struct net_local { net_local * next; /* linked list of the devices */ struct net_device * dev; /* reverse link */ spinlock_t spinlock; /* Serialize access to the hardware (SMP) */ - en_stats stats; /* Ethernet interface statistics */ int nresets; /* number of hardware resets */ u_char reconfig_82586; /* We need to reconfigure the controller. */ u_char promiscuous; /* promiscuous mode */ @@ -601,8 +596,6 @@ static void static inline void wv_init_info(struct net_device *); /* display startup info */ /* ------------------- IOCTL, STATS & RECONFIG ------------------- */ -static en_stats * - wavelan_get_stats(struct net_device *); /* Give stats /proc/net/dev */ static iw_stats * wavelan_get_wireless_stats(struct net_device *); static void -- GitLab From b20417db3149a9de87e4b4594bcf5f713031c507 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:28 +0000 Subject: [PATCH 4738/4982] netdev: seeq8005 convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/seeq8005.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c index 12a8ffffeb0..ebbbe09725f 100644 --- a/drivers/net/seeq8005.c +++ b/drivers/net/seeq8005.c @@ -143,6 +143,17 @@ out: return ERR_PTR(err); } +static const struct net_device_ops seeq8005_netdev_ops = { + .ndo_open = seeq8005_open, + .ndo_stop = seeq8005_close, + .ndo_start_xmit = seeq8005_send_packet, + .ndo_tx_timeout = seeq8005_timeout, + .ndo_set_multicast_list = set_multicast_list, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + /* This is the real probe routine. Linux has a history of friendly device probes on the ISA bus. A good device probes avoids doing writes, and verifies that the correct device exists and functions. */ @@ -332,12 +343,8 @@ static int __init seeq8005_probe1(struct net_device *dev, int ioaddr) } } #endif - dev->open = seeq8005_open; - dev->stop = seeq8005_close; - dev->hard_start_xmit = seeq8005_send_packet; - dev->tx_timeout = seeq8005_timeout; + dev->netdev_ops = &seeq8005_netdev_ops; dev->watchdog_timeo = HZ/20; - dev->set_multicast_list = set_multicast_list; dev->flags &= ~IFF_MULTICAST; return 0; -- GitLab From 32670c36d0222e2fdfa9673bb878e0f347411cd4 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:29 +0000 Subject: [PATCH 4739/4982] netdev: smc9194 convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/smc9194.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c index 18d653bbd4e..9a7973a5411 100644 --- a/drivers/net/smc9194.c +++ b/drivers/net/smc9194.c @@ -831,6 +831,17 @@ static int __init smc_findirq(int ioaddr) #endif } +static const struct net_device_ops smc_netdev_ops = { + .ndo_open = smc_open, + .ndo_stop = smc_close, + .ndo_start_xmit = smc_wait_to_send_packet, + .ndo_tx_timeout = smc_timeout, + .ndo_set_multicast_list = smc_set_multicast_list, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + /*---------------------------------------------------------------------- . Function: smc_probe( int ioaddr ) . @@ -1044,12 +1055,8 @@ static int __init smc_probe(struct net_device *dev, int ioaddr) goto err_out; } - dev->open = smc_open; - dev->stop = smc_close; - dev->hard_start_xmit = smc_wait_to_send_packet; - dev->tx_timeout = smc_timeout; + dev->netdev_ops = &smc_netdev_ops; dev->watchdog_timeo = HZ/20; - dev->set_multicast_list = smc_set_multicast_list; return 0; -- GitLab From 5f352f9a1c8d53270970f4efcf5496cb9b01c4a8 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:30 +0000 Subject: [PATCH 4740/4982] netdev: smc-ultra32 convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/smc-ultra32.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/net/smc-ultra32.c b/drivers/net/smc-ultra32.c index cb6c097a2e0..7a554adc70f 100644 --- a/drivers/net/smc-ultra32.c +++ b/drivers/net/smc-ultra32.c @@ -153,6 +153,22 @@ out: return ERR_PTR(err); } + +static const struct net_device_ops ultra32_netdev_ops = { + .ndo_open = ultra32_open, + .ndo_stop = ultra32_close, + .ndo_start_xmit = ei_start_xmit, + .ndo_tx_timeout = ei_tx_timeout, + .ndo_get_stats = ei_get_stats, + .ndo_set_multicast_list = ei_set_multicast_list, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, + .ndo_change_mtu = eth_change_mtu, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = ei_poll, +#endif +}; + static int __init ultra32_probe1(struct net_device *dev, int ioaddr) { int i, edge, media, retval; @@ -273,11 +289,8 @@ static int __init ultra32_probe1(struct net_device *dev, int ioaddr) ei_status.block_output = &ultra32_block_output; ei_status.get_8390_hdr = &ultra32_get_8390_hdr; ei_status.reset_8390 = &ultra32_reset_8390; - dev->open = &ultra32_open; - dev->stop = &ultra32_close; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = ei_poll; -#endif + + dev->netdev_ops = &ultra32_netdev_ops; NS8390_init(dev, 0); return 0; -- GitLab From 06e884031702f06b32ce20750ab3c46c596dc776 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:31 +0000 Subject: [PATCH 4741/4982] netdev: smc-ultra fix netpoll net_device_ops conversion left the wrong poll_controller hook. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/smc-ultra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c index f56f5e4083b..0291ea098a0 100644 --- a/drivers/net/smc-ultra.c +++ b/drivers/net/smc-ultra.c @@ -196,7 +196,7 @@ static const struct net_device_ops ultra_netdev_ops = { .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = ei_poll, + .ndo_poll_controller = ultra_poll, #endif }; -- GitLab From 462540bdb2f08d465a2416764fc628520f82939f Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:32 +0000 Subject: [PATCH 4742/4982] lance: convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/lance.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/net/lance.c b/drivers/net/lance.c index d83d4010656..633808d447b 100644 --- a/drivers/net/lance.c +++ b/drivers/net/lance.c @@ -454,6 +454,18 @@ out: } #endif +static const struct net_device_ops lance_netdev_ops = { + .ndo_open = lance_open, + .ndo_start_xmit = lance_start_xmit, + .ndo_stop = lance_close, + .ndo_get_stats = lance_get_stats, + .ndo_set_multicast_list = set_multicast_list, + .ndo_tx_timeout = lance_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int options) { struct lance_private *lp; @@ -714,12 +726,7 @@ static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int printk(version); /* The LANCE-specific entries in the device structure. */ - dev->open = lance_open; - dev->hard_start_xmit = lance_start_xmit; - dev->stop = lance_close; - dev->get_stats = lance_get_stats; - dev->set_multicast_list = set_multicast_list; - dev->tx_timeout = lance_tx_timeout; + dev->netdev_ops = &lance_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; err = register_netdev(dev); -- GitLab From d9c6d50d8dae755fe136e9cfdd137f856f60af4b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:33 +0000 Subject: [PATCH 4743/4982] netdev: ibmlana convert to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/ibmlana.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c index 5b5bf9f9861..c25bc0bc0b2 100644 --- a/drivers/net/ibmlana.c +++ b/drivers/net/ibmlana.c @@ -905,6 +905,17 @@ static char *ibmlana_adapter_names[] __devinitdata = { NULL }; + +static const struct net_device_ops ibmlana_netdev_ops = { + .ndo_open = ibmlana_open, + .ndo_stop = ibmlana_close, + .ndo_start_xmit = ibmlana_tx, + .ndo_set_multicast_list = ibmlana_set_multicast_list, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + static int __devinit ibmlana_init_one(struct device *kdev) { struct mca_device *mdev = to_mca_device(kdev); @@ -973,11 +984,7 @@ static int __devinit ibmlana_init_one(struct device *kdev) mca_device_set_claim(mdev, 1); /* set methods */ - - dev->open = ibmlana_open; - dev->stop = ibmlana_close; - dev->hard_start_xmit = ibmlana_tx; - dev->set_multicast_list = ibmlana_set_multicast_list; + dev->netdev_ops = &ibmlana_netdev_ops; dev->flags |= IFF_MULTICAST; /* copy out MAC address */ -- GitLab From 8a5f7dafbc92b6e87bd02b9d5b2b58da4f5bb4c3 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:34 +0000 Subject: [PATCH 4744/4982] netdev: convert eexpress to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/eexpress.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c index 9ff3f2f5e38..1686dca2874 100644 --- a/drivers/net/eexpress.c +++ b/drivers/net/eexpress.c @@ -1043,6 +1043,17 @@ static void eexp_hw_tx_pio(struct net_device *dev, unsigned short *buf, lp->last_tx = jiffies; } +static const struct net_device_ops eexp_netdev_ops = { + .ndo_open = eexp_open, + .ndo_stop = eexp_close, + .ndo_start_xmit = eexp_xmit, + .ndo_set_multicast_list = eexp_set_multicast, + .ndo_tx_timeout = eexp_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + /* * Sanity check the suspected EtherExpress card * Read hardware address, reset card, size memory and initialize buffer @@ -1163,11 +1174,7 @@ static int __init eexp_hw_probe(struct net_device *dev, unsigned short ioaddr) lp->rx_buf_start = TX_BUF_START + (lp->num_tx_bufs*TX_BUF_SIZE); lp->width = buswidth; - dev->open = eexp_open; - dev->stop = eexp_close; - dev->hard_start_xmit = eexp_xmit; - dev->set_multicast_list = &eexp_set_multicast; - dev->tx_timeout = eexp_timeout; + dev->netdev_ops = &eexp_netdev_ops; dev->watchdog_timeo = 2*HZ; return register_netdev(dev); -- GitLab From 8afb1cebf5e7fde4a1bddacb559bda8526e64144 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:35 +0000 Subject: [PATCH 4745/4982] netdev: convert eexpro to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/eepro.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c index e187c88ae14..cc2ab6412c7 100644 --- a/drivers/net/eepro.c +++ b/drivers/net/eepro.c @@ -739,6 +739,17 @@ static void __init eepro_print_info (struct net_device *dev) static const struct ethtool_ops eepro_ethtool_ops; +static const struct net_device_ops eepro_netdev_ops = { + .ndo_open = eepro_open, + .ndo_stop = eepro_close, + .ndo_start_xmit = eepro_send_packet, + .ndo_set_multicast_list = set_multicast_list, + .ndo_tx_timeout = eepro_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + /* This is the real probe routine. Linux has a history of friendly device probes on the ISA bus. A good device probe avoids doing writes, and verifies that the correct device exists and functions. */ @@ -851,11 +862,7 @@ static int __init eepro_probe1(struct net_device *dev, int autoprobe) } } - dev->open = eepro_open; - dev->stop = eepro_close; - dev->hard_start_xmit = eepro_send_packet; - dev->set_multicast_list = &set_multicast_list; - dev->tx_timeout = eepro_tx_timeout; + dev->netdev_ops = &eepro_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; dev->ethtool_ops = &eepro_ethtool_ops; -- GitLab From cb0c7005d2dd20499c0855bfcb05272a4d206d23 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:36 +0000 Subject: [PATCH 4746/4982] netdev: convert at1700 to net_device_ops Remove unneeded memset (alloc_etherdev does it already). Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/at1700.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c index ced70799b89..18b566ad4fd 100644 --- a/drivers/net/at1700.c +++ b/drivers/net/at1700.c @@ -249,6 +249,17 @@ out: return ERR_PTR(err); } +static const struct net_device_ops at1700_netdev_ops = { + .ndo_open = net_open, + .ndo_stop = net_close, + .ndo_start_xmit = net_send_packet, + .ndo_set_multicast_list = set_rx_mode, + .ndo_tx_timeout = net_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + /* The Fujitsu datasheet suggests that the NIC be probed for by checking its "signature", the default bit pattern after a reset. This *doesn't* work -- there is no way to reset the bus interface without a complete power-cycle! @@ -448,13 +459,7 @@ found: if (net_debug) printk(version); - memset(lp, 0, sizeof(struct net_local)); - - dev->open = net_open; - dev->stop = net_close; - dev->hard_start_xmit = net_send_packet; - dev->set_multicast_list = &set_rx_mode; - dev->tx_timeout = net_tx_timeout; + dev->netdev_ops = &at1700_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; spin_lock_init(&lp->lock); -- GitLab From 361bc03e180c4e27e8f21bc7ea3a8066886f78d5 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:37 +0000 Subject: [PATCH 4747/4982] netdev: convert depca to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/depca.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/net/depca.c b/drivers/net/depca.c index 55625dbbae5..357f565851e 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -566,6 +566,18 @@ MODULE_LICENSE("GPL"); outw(CSR0, DEPCA_ADDR);\ outw(STOP, DEPCA_DATA) +static const struct net_device_ops depca_netdev_ops = { + .ndo_open = depca_open, + .ndo_start_xmit = depca_start_xmit, + .ndo_stop = depca_close, + .ndo_set_multicast_list = set_multicast_list, + .ndo_do_ioctl = depca_ioctl, + .ndo_tx_timeout = depca_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + static int __init depca_hw_init (struct net_device *dev, struct device *device) { struct depca_private *lp; @@ -793,12 +805,7 @@ static int __init depca_hw_init (struct net_device *dev, struct device *device) } /* The DEPCA-specific entries in the device structure. */ - dev->open = &depca_open; - dev->hard_start_xmit = &depca_start_xmit; - dev->stop = &depca_close; - dev->set_multicast_list = &set_multicast_list; - dev->do_ioctl = &depca_ioctl; - dev->tx_timeout = depca_tx_timeout; + dev->netdev_ops = &depca_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; dev->mem_start = 0; -- GitLab From 968804d9705a014f231eedf82ba9e33810898b68 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:38 +0000 Subject: [PATCH 4748/4982] netdev: convert ewrk3 to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/ewrk3.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c index b852303c936..1a685a04d4b 100644 --- a/drivers/net/ewrk3.c +++ b/drivers/net/ewrk3.c @@ -388,6 +388,18 @@ static int __init ewrk3_probe1(struct net_device *dev, u_long iobase, int irq) return err; } +static const struct net_device_ops ewrk3_netdev_ops = { + .ndo_open = ewrk3_open, + .ndo_start_xmit = ewrk3_queue_pkt, + .ndo_stop = ewrk3_close, + .ndo_set_multicast_list = set_multicast_list, + .ndo_do_ioctl = ewrk3_ioctl, + .ndo_tx_timeout = ewrk3_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + static int __init ewrk3_hw_init(struct net_device *dev, u_long iobase) { @@ -603,16 +615,11 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase) printk(version); } /* The EWRK3-specific entries in the device structure. */ - dev->open = ewrk3_open; - dev->hard_start_xmit = ewrk3_queue_pkt; - dev->stop = ewrk3_close; - dev->set_multicast_list = set_multicast_list; - dev->do_ioctl = ewrk3_ioctl; + dev->netdev_ops = &ewrk3_netdev_ops; if (lp->adapter_name[4] == '3') SET_ETHTOOL_OPS(dev, ðtool_ops_203); else SET_ETHTOOL_OPS(dev, ðtool_ops); - dev->tx_timeout = ewrk3_timeout; dev->watchdog_timeo = QUEUE_PKT_TIMEOUT; dev->mem_start = 0; -- GitLab From 2c7669e3a9f748dd35743f06cbdaf4340263c3bf Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:39 +0000 Subject: [PATCH 4749/4982] netdev: convert ni52 to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/ni52.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c index a8bcc00c330..77d44a06170 100644 --- a/drivers/net/ni52.c +++ b/drivers/net/ni52.c @@ -441,6 +441,18 @@ out: return ERR_PTR(err); } +static const struct net_device_ops ni52_netdev_ops = { + .ndo_open = ni52_open, + .ndo_stop = ni52_close, + .ndo_get_stats = ni52_get_stats, + .ndo_tx_timeout = ni52_timeout, + .ndo_start_xmit = ni52_send_packet, + .ndo_set_multicast_list = set_multicast_list, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + static int __init ni52_probe1(struct net_device *dev, int ioaddr) { int i, size, retval; @@ -561,15 +573,8 @@ static int __init ni52_probe1(struct net_device *dev, int ioaddr) printk("IRQ %d (assigned and not checked!).\n", dev->irq); } - dev->open = ni52_open; - dev->stop = ni52_close; - dev->get_stats = ni52_get_stats; - dev->tx_timeout = ni52_timeout; + dev->netdev_ops = &ni52_netdev_ops; dev->watchdog_timeo = HZ/20; - dev->hard_start_xmit = ni52_send_packet; - dev->set_multicast_list = set_multicast_list; - - dev->if_port = 0; return 0; out: -- GitLab From c6bca821e66c5fec8ffc11ff24a82adf338bcf6b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:40 +0000 Subject: [PATCH 4750/4982] netdev: convert ni65 to net_device_ops Also, use internal net_device_stats. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/ni65.c | 75 ++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 43 deletions(-) diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c index df5f869e8d8..6474f02bf78 100644 --- a/drivers/net/ni65.c +++ b/drivers/net/ni65.c @@ -237,7 +237,7 @@ struct priv void *tmdbounce[TMDNUM]; int tmdbouncenum; int lock,xmit_queued; - struct net_device_stats stats; + void *self; int cmdr_addr; int cardno; @@ -257,7 +257,6 @@ static void ni65_timeout(struct net_device *dev); static int ni65_close(struct net_device *dev); static int ni65_alloc_buffer(struct net_device *dev); static void ni65_free_buffer(struct priv *p); -static struct net_device_stats *ni65_get_stats(struct net_device *); static void set_multicast_list(struct net_device *dev); static int irqtab[] __initdata = { 9,12,15,5 }; /* irq config-translate */ @@ -401,6 +400,17 @@ out: return ERR_PTR(err); } +static const struct net_device_ops ni65_netdev_ops = { + .ndo_open = ni65_open, + .ndo_stop = ni65_close, + .ndo_start_xmit = ni65_send_packet, + .ndo_tx_timeout = ni65_timeout, + .ndo_set_multicast_list = set_multicast_list, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + /* * this is the real card probe .. */ @@ -549,13 +559,9 @@ static int __init ni65_probe1(struct net_device *dev,int ioaddr) } dev->base_addr = ioaddr; - dev->open = ni65_open; - dev->stop = ni65_close; - dev->hard_start_xmit = ni65_send_packet; - dev->tx_timeout = ni65_timeout; + dev->netdev_ops = &ni65_netdev_ops; dev->watchdog_timeo = HZ/2; - dev->get_stats = ni65_get_stats; - dev->set_multicast_list = set_multicast_list; + return 0; /* everything is OK */ } @@ -901,13 +907,13 @@ static irqreturn_t ni65_interrupt(int irq, void * dev_id) if(debuglevel > 1) printk(KERN_ERR "%s: general error: %04x.\n",dev->name,csr0); if(csr0 & CSR0_BABL) - p->stats.tx_errors++; + dev->stats.tx_errors++; if(csr0 & CSR0_MISS) { int i; for(i=0;irmdhead[i].u.s.status); printk("\n"); - p->stats.rx_errors++; + dev->stats.rx_errors++; } if(csr0 & CSR0_MERR) { if(debuglevel > 1) @@ -997,12 +1003,12 @@ static void ni65_xmit_intr(struct net_device *dev,int csr0) #endif /* checking some errors */ if(tmdp->status2 & XMIT_RTRY) - p->stats.tx_aborted_errors++; + dev->stats.tx_aborted_errors++; if(tmdp->status2 & XMIT_LCAR) - p->stats.tx_carrier_errors++; + dev->stats.tx_carrier_errors++; if(tmdp->status2 & (XMIT_BUFF | XMIT_UFLO )) { /* this stops the xmitter */ - p->stats.tx_fifo_errors++; + dev->stats.tx_fifo_errors++; if(debuglevel > 0) printk(KERN_ERR "%s: Xmit FIFO/BUFF error\n",dev->name); if(p->features & INIT_RING_BEFORE_START) { @@ -1016,12 +1022,12 @@ static void ni65_xmit_intr(struct net_device *dev,int csr0) if(debuglevel > 2) printk(KERN_ERR "%s: xmit-error: %04x %02x-%04x\n",dev->name,csr0,(int) tmdstat,(int) tmdp->status2); if(!(csr0 & CSR0_BABL)) /* don't count errors twice */ - p->stats.tx_errors++; + dev->stats.tx_errors++; tmdp->status2 = 0; } else { - p->stats.tx_bytes -= (short)(tmdp->blen); - p->stats.tx_packets++; + dev->stats.tx_bytes -= (short)(tmdp->blen); + dev->stats.tx_packets++; } #ifdef XMT_VIA_SKB @@ -1057,7 +1063,7 @@ static void ni65_recv_intr(struct net_device *dev,int csr0) if(!(rmdstat & RCV_ERR)) { if(rmdstat & RCV_START) { - p->stats.rx_length_errors++; + dev->stats.rx_length_errors++; printk(KERN_ERR "%s: recv, packet too long: %d\n",dev->name,rmdp->mlen & 0x0fff); } } @@ -1066,16 +1072,16 @@ static void ni65_recv_intr(struct net_device *dev,int csr0) printk(KERN_ERR "%s: receive-error: %04x, lance-status: %04x/%04x\n", dev->name,(int) rmdstat,csr0,(int) inw(PORT+L_DATAREG) ); if(rmdstat & RCV_FRAM) - p->stats.rx_frame_errors++; + dev->stats.rx_frame_errors++; if(rmdstat & RCV_OFLO) - p->stats.rx_over_errors++; + dev->stats.rx_over_errors++; if(rmdstat & RCV_CRC) - p->stats.rx_crc_errors++; + dev->stats.rx_crc_errors++; if(rmdstat & RCV_BUF_ERR) - p->stats.rx_fifo_errors++; + dev->stats.rx_fifo_errors++; } if(!(csr0 & CSR0_MISS)) /* don't count errors twice */ - p->stats.rx_errors++; + dev->stats.rx_errors++; } else if( (len = (rmdp->mlen & 0x0fff) - 4) >= 60) { @@ -1106,20 +1112,20 @@ static void ni65_recv_intr(struct net_device *dev,int csr0) skb_put(skb,len); skb_copy_to_linear_data(skb, (unsigned char *) p->recvbounce[p->rmdnum],len); #endif - p->stats.rx_packets++; - p->stats.rx_bytes += len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += len; skb->protocol=eth_type_trans(skb,dev); netif_rx(skb); } else { printk(KERN_ERR "%s: can't alloc new sk_buff\n",dev->name); - p->stats.rx_dropped++; + dev->stats.rx_dropped++; } } else { printk(KERN_INFO "%s: received runt packet\n",dev->name); - p->stats.rx_errors++; + dev->stats.rx_errors++; } rmdp->blen = -(R_BUF_SIZE-8); rmdp->mlen = 0; @@ -1213,23 +1219,6 @@ static int ni65_send_packet(struct sk_buff *skb, struct net_device *dev) return 0; } -static struct net_device_stats *ni65_get_stats(struct net_device *dev) -{ - -#if 0 - int i; - struct priv *p = dev->ml_priv; - for(i=0;irmdhead + ((p->rmdnum + i) & (RMDNUM-1)); - printk("%02x ",rmdp->u.s.status); - } - printk("\n"); -#endif - - return &((struct priv *)dev->ml_priv)->stats; -} - static void set_multicast_list(struct net_device *dev) { if(!ni65_lance_reinit(dev)) -- GitLab From 1494f2f5601b3220d55f1fdd8a6f990d41446c59 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:41 +0000 Subject: [PATCH 4751/4982] netdev: convert ac3200 to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/ac3200.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c index 071a851a2ea..eac73382c08 100644 --- a/drivers/net/ac3200.c +++ b/drivers/net/ac3200.c @@ -143,6 +143,22 @@ out: } #endif +static const struct net_device_ops ac_netdev_ops = { + .ndo_open = ac_open, + .ndo_stop = ac_close_card, + + .ndo_start_xmit = ei_start_xmit, + .ndo_tx_timeout = ei_tx_timeout, + .ndo_get_stats = ei_get_stats, + .ndo_set_multicast_list = ei_set_multicast_list, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, + .ndo_change_mtu = eth_change_mtu, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = ei_poll, +#endif +}; + static int __init ac_probe1(int ioaddr, struct net_device *dev) { int i, retval; @@ -253,11 +269,7 @@ static int __init ac_probe1(int ioaddr, struct net_device *dev) ei_status.block_output = &ac_block_output; ei_status.get_8390_hdr = &ac_get_8390_hdr; - dev->open = &ac_open; - dev->stop = &ac_close_card; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = ei_poll; -#endif + dev->netdev_ops = &ac_netdev_ops; NS8390_init(dev, 0); retval = register_netdev(dev); -- GitLab From 635d8ba2ecb614b88ab16cb82c12cb344cab4427 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:42 +0000 Subject: [PATCH 4752/4982] netdev: convert lp486e to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/lp486e.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c index 4d1a059921c..d44bddbee37 100644 --- a/drivers/net/lp486e.c +++ b/drivers/net/lp486e.c @@ -952,6 +952,17 @@ static void print_eth(char *add) (unsigned char) add[12], (unsigned char) add[13]); } +static const struct net_device_ops i596_netdev_ops = { + .ndo_open = i596_open, + .ndo_stop = i596_close, + .ndo_start_xmit = i596_start_xmit, + .ndo_set_multicast_list = set_multicast_list, + .ndo_tx_timeout = i596_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + static int __init lp486e_probe(struct net_device *dev) { struct i596_private *lp; unsigned char eth_addr[6] = { 0, 0xaa, 0, 0, 0, 0 }; @@ -1014,12 +1025,8 @@ static int __init lp486e_probe(struct net_device *dev) { printk("\n"); /* The LP486E-specific entries in the device structure. */ - dev->open = &i596_open; - dev->stop = &i596_close; - dev->hard_start_xmit = &i596_start_xmit; - dev->set_multicast_list = &set_multicast_list; + dev->netdev_ops = &i596_netdev_ops; dev->watchdog_timeo = 5*HZ; - dev->tx_timeout = i596_tx_timeout; #if 0 /* selftest reports 0x320925ae - don't know what that means */ -- GitLab From 15d23e7a9e02c8ecbbf9a855e626707ba839135a Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:43 +0000 Subject: [PATCH 4753/4982] netdev: convert cs89x0 to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/cs89x0.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index ff6497658a4..7433b88eed7 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -501,6 +501,21 @@ static void net_poll_controller(struct net_device *dev) } #endif +static const struct net_device_ops net_ops = { + .ndo_open = net_open, + .ndo_stop = net_close, + .ndo_tx_timeout = net_timeout, + .ndo_start_xmit = net_send_packet, + .ndo_get_stats = net_get_stats, + .ndo_set_multicast_list = set_multicast_list, + .ndo_set_mac_address = set_mac_address, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = net_poll_controller, +#endif + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, +}; + /* This is the real probe routine. Linux has a history of friendly device probes on the ISA bus. A good device probes avoids doing writes, and verifies that the correct device exists and functions. @@ -843,17 +858,8 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) /* print the ethernet address. */ printk(", MAC %pM", dev->dev_addr); - dev->open = net_open; - dev->stop = net_close; - dev->tx_timeout = net_timeout; - dev->watchdog_timeo = HZ; - dev->hard_start_xmit = net_send_packet; - dev->get_stats = net_get_stats; - dev->set_multicast_list = set_multicast_list; - dev->set_mac_address = set_mac_address; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = net_poll_controller; -#endif + dev->netdev_ops = &net_ops; + dev->watchdog_timeo = HZ; printk("\n"); if (net_debug) -- GitLab From 6d1ec7812d6350409ecfe7f6dded3a6c801b89d3 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Mar 2009 15:11:44 +0000 Subject: [PATCH 4754/4982] netdev: convert eth16i to net_device_ops Also, get rid of unnecessary memset. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/eth16i.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c index 5c048f2fd74..0d8b6da046f 100644 --- a/drivers/net/eth16i.c +++ b/drivers/net/eth16i.c @@ -475,6 +475,17 @@ out: } #endif +static const struct net_device_ops eth16i_netdev_ops = { + .ndo_open = eth16i_open, + .ndo_stop = eth16i_close, + .ndo_start_xmit = eth16i_tx, + .ndo_set_multicast_list = eth16i_multicast, + .ndo_tx_timeout = eth16i_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + static int __init eth16i_probe1(struct net_device *dev, int ioaddr) { struct eth16i_local *lp = netdev_priv(dev); @@ -549,12 +560,7 @@ static int __init eth16i_probe1(struct net_device *dev, int ioaddr) BITCLR(ioaddr + CONFIG_REG_1, POWERUP); /* Initialize the device structure */ - memset(lp, 0, sizeof(struct eth16i_local)); - dev->open = eth16i_open; - dev->stop = eth16i_close; - dev->hard_start_xmit = eth16i_tx; - dev->set_multicast_list = eth16i_multicast; - dev->tx_timeout = eth16i_timeout; + dev->netdev_ops = ð16i_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; spin_lock_init(&lp->lock); -- GitLab From 3156378993b0fc0f9f12f5f297f0a9b4c4fe0fc8 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Thu, 26 Mar 2009 16:39:09 +0000 Subject: [PATCH 4755/4982] cxgb3: start qset timers when setup succeeded Start queue set reclaim timers after the queue sets have been allocated successfully. Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/adapter.h | 1 + drivers/net/cxgb3/cxgb3_main.c | 3 ++- drivers/net/cxgb3/sge.c | 24 +++++++++++++++++++++--- 3 files changed, 24 insertions(+), 4 deletions(-) mode change 100644 => 100755 drivers/net/cxgb3/cxgb3_main.c mode change 100644 => 100755 drivers/net/cxgb3/sge.c diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h index 71eaa431371..2cf6c9299f2 100644 --- a/drivers/net/cxgb3/adapter.h +++ b/drivers/net/cxgb3/adapter.h @@ -291,6 +291,7 @@ void t3_os_link_fault_handler(struct adapter *adapter, int port_id); void t3_sge_start(struct adapter *adap); void t3_sge_stop(struct adapter *adap); +void t3_start_sge_timers(struct adapter *adap); void t3_stop_sge_timers(struct adapter *adap); void t3_free_sge_resources(struct adapter *adap); void t3_sge_err_intr_handler(struct adapter *adapter); diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c old mode 100644 new mode 100755 index d8be89621bf..8ad5f3299ba --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -602,7 +602,6 @@ static int setup_sge_qsets(struct adapter *adap) &adap->params.sge.qset[qset_idx], ntxq, dev, netdev_get_tx_queue(dev, j)); if (err) { - t3_stop_sge_timers(adap); t3_free_sge_resources(adap); return err; } @@ -1046,6 +1045,8 @@ static int cxgb_up(struct adapter *adap) setup_rss(adap); if (!(adap->flags & NAPI_INIT)) init_napi(adap); + + t3_start_sge_timers(adap); adap->flags |= FULL_INIT_DONE; } diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c old mode 100644 new mode 100755 index a7555cb3fa4..fcd1a4f4f77 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -3044,9 +3044,6 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, t3_write_reg(adapter, A_SG_GTS, V_RSPQ(q->rspq.cntxt_id) | V_NEWTIMER(q->rspq.holdoff_tmr)); - mod_timer(&q->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD); - mod_timer(&q->rx_reclaim_timer, jiffies + RX_RECLAIM_PERIOD); - return 0; err_unlock: @@ -3056,6 +3053,27 @@ err: return ret; } +/** + * t3_start_sge_timers - start SGE timer call backs + * @adap: the adapter + * + * Starts each SGE queue set's timer call back + */ +void t3_start_sge_timers(struct adapter *adap) +{ + int i; + + for (i = 0; i < SGE_QSETS; ++i) { + struct sge_qset *q = &adap->sge.qs[i]; + + if (q->tx_reclaim_timer.function) + mod_timer(&q->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD); + + if (q->rx_reclaim_timer.function) + mod_timer(&q->rx_reclaim_timer, jiffies + RX_RECLAIM_PERIOD); + } +} + /** * t3_stop_sge_timers - stop SGE timer call backs * @adap: the adapter -- GitLab From 3fa58c883d44c50b48f2d57a0bc626a7812b0cae Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Thu, 26 Mar 2009 16:39:14 +0000 Subject: [PATCH 4756/4982] cxgb3: sge setup fixes Enable timestamps, update delayed ack threshold for iSCSI/iWARP traffic Remove the len flag in Tx requests. It might corrupt offload trace packets. Update SGE context setup to avoid potential H/W misprogrammation. Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/sge.c | 2 +- drivers/net/cxgb3/t3_hw.c | 45 +++++++++++++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 8 deletions(-) mode change 100644 => 100755 drivers/net/cxgb3/t3_hw.c diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index fcd1a4f4f77..54667f0dde9 100755 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -1089,7 +1089,7 @@ static void write_tx_pkt_wr(struct adapter *adap, struct sk_buff *skb, struct tx_desc *d = &q->desc[pidx]; struct cpl_tx_pkt *cpl = (struct cpl_tx_pkt *)d; - cpl->len = htonl(skb->len | 0x80000000); + cpl->len = htonl(skb->len); cntrl = V_TXPKT_INTF(pi->port_id); if (vlan_tx_tag_present(skb) && pi->vlan_grp) diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c old mode 100644 new mode 100755 index ff262a04ded..7d8fbae58dc --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c @@ -2128,16 +2128,40 @@ void t3_port_intr_clear(struct adapter *adapter, int idx) static int t3_sge_write_context(struct adapter *adapter, unsigned int id, unsigned int type) { - t3_write_reg(adapter, A_SG_CONTEXT_MASK0, 0xffffffff); - t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0xffffffff); - t3_write_reg(adapter, A_SG_CONTEXT_MASK2, 0xffffffff); - t3_write_reg(adapter, A_SG_CONTEXT_MASK3, 0xffffffff); + if (type == F_RESPONSEQ) { + /* + * Can't write the Response Queue Context bits for + * Interrupt Armed or the Reserve bits after the chip + * has been initialized out of reset. Writing to these + * bits can confuse the hardware. + */ + t3_write_reg(adapter, A_SG_CONTEXT_MASK0, 0xffffffff); + t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0xffffffff); + t3_write_reg(adapter, A_SG_CONTEXT_MASK2, 0x17ffffff); + t3_write_reg(adapter, A_SG_CONTEXT_MASK3, 0xffffffff); + } else { + t3_write_reg(adapter, A_SG_CONTEXT_MASK0, 0xffffffff); + t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0xffffffff); + t3_write_reg(adapter, A_SG_CONTEXT_MASK2, 0xffffffff); + t3_write_reg(adapter, A_SG_CONTEXT_MASK3, 0xffffffff); + } t3_write_reg(adapter, A_SG_CONTEXT_CMD, V_CONTEXT_CMD_OPCODE(1) | type | V_CONTEXT(id)); return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, 0, SG_CONTEXT_CMD_ATTEMPTS, 1); } +/** + * clear_sge_ctxt - completely clear an SGE context + * @adapter: the adapter + * @id: the context id + * @type: the context type + * + * Completely clear an SGE context. Used predominantly at post-reset + * initialization. Note in particular that we don't skip writing to any + * "sensitive bits" in the contexts the way that t3_sge_write_context() + * does ... + */ static int clear_sge_ctxt(struct adapter *adap, unsigned int id, unsigned int type) { @@ -2145,7 +2169,14 @@ static int clear_sge_ctxt(struct adapter *adap, unsigned int id, t3_write_reg(adap, A_SG_CONTEXT_DATA1, 0); t3_write_reg(adap, A_SG_CONTEXT_DATA2, 0); t3_write_reg(adap, A_SG_CONTEXT_DATA3, 0); - return t3_sge_write_context(adap, id, type); + t3_write_reg(adap, A_SG_CONTEXT_MASK0, 0xffffffff); + t3_write_reg(adap, A_SG_CONTEXT_MASK1, 0xffffffff); + t3_write_reg(adap, A_SG_CONTEXT_MASK2, 0xffffffff); + t3_write_reg(adap, A_SG_CONTEXT_MASK3, 0xffffffff); + t3_write_reg(adap, A_SG_CONTEXT_CMD, + V_CONTEXT_CMD_OPCODE(1) | type | V_CONTEXT(id)); + return t3_wait_op_done(adap, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, + 0, SG_CONTEXT_CMD_ATTEMPTS, 1); } /** @@ -2729,10 +2760,10 @@ static void tp_config(struct adapter *adap, const struct tp_params *p) F_TCPCHECKSUMOFFLOAD | V_IPTTL(64)); t3_write_reg(adap, A_TP_TCP_OPTIONS, V_MTUDEFAULT(576) | F_MTUENABLE | V_WINDOWSCALEMODE(1) | - V_TIMESTAMPSMODE(0) | V_SACKMODE(1) | V_SACKRX(1)); + V_TIMESTAMPSMODE(1) | V_SACKMODE(1) | V_SACKRX(1)); t3_write_reg(adap, A_TP_DACK_CONFIG, V_AUTOSTATE3(1) | V_AUTOSTATE2(1) | V_AUTOSTATE1(0) | - V_BYTETHRESHOLD(16384) | V_MSSTHRESHOLD(2) | + V_BYTETHRESHOLD(26880) | V_MSSTHRESHOLD(2) | F_AUTOCAREFUL | F_AUTOENABLE | V_DACK_MODE(1)); t3_set_reg_field(adap, A_TP_IN_CONFIG, F_RXFBARBPRIO | F_TXFBARBPRIO, F_IPV6ENABLE | F_NICMODE); -- GitLab From 68f40c10292a94762956896d4d320a2620945adc Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Thu, 26 Mar 2009 16:39:19 +0000 Subject: [PATCH 4757/4982] cxgb3: use resource_size_t for mmio declarations Use resource_size_t to declare mmio start and len variables. Print PEX error register after EEH resumed. Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/cxgb3_main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 8ad5f3299ba..e2b119312a0 100755 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -2871,6 +2871,9 @@ static void t3_io_resume(struct pci_dev *pdev) { struct adapter *adapter = pci_get_drvdata(pdev); + CH_ALERT(adapter, "adapter recovering, PEX ERR 0x%x\n", + t3_read_reg(adapter, A_PCIE_PEX_ERR)); + t3_resume_ports(adapter); } @@ -3003,7 +3006,7 @@ static int __devinit init_one(struct pci_dev *pdev, static int version_printed; int i, err, pci_using_dac = 0; - unsigned long mmio_start, mmio_len; + resource_size_t mmio_start, mmio_len; const struct adapter_info *ai; struct adapter *adapter = NULL; struct port_info *pi; -- GitLab From 952cdf333f9d1b0b71f1b9a3c5e421a2673ed7de Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Thu, 26 Mar 2009 16:39:24 +0000 Subject: [PATCH 4758/4982] cxgb3: differentiate portx and Tx channels Separate ports from H/W Tx channels. Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/common.h | 4 +++- drivers/net/cxgb3/cxgb3_main.c | 4 ++-- drivers/net/cxgb3/t3_hw.c | 35 ++++++++++++++++++---------------- 3 files changed, 24 insertions(+), 19 deletions(-) mode change 100755 => 100644 drivers/net/cxgb3/cxgb3_main.c mode change 100755 => 100644 drivers/net/cxgb3/t3_hw.c diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h index 9ee021e750c..e508dc32f3e 100644 --- a/drivers/net/cxgb3/common.h +++ b/drivers/net/cxgb3/common.h @@ -191,7 +191,8 @@ struct mdio_ops { }; struct adapter_info { - unsigned char nports; /* # of ports */ + unsigned char nports0; /* # of ports on channel 0 */ + unsigned char nports1; /* # of ports on channel 1 */ unsigned char phy_base_addr; /* MDIO PHY base address */ unsigned int gpio_out; /* GPIO output settings */ unsigned char gpio_intr[MAX_NPORTS]; /* GPIO PHY IRQ pins */ @@ -422,6 +423,7 @@ struct adapter_params { unsigned short b_wnd[NCCTRL_WIN]; unsigned int nports; /* # of ethernet ports */ + unsigned int chan_map; /* bitmap of in-use Tx channels */ unsigned int stats_update_period; /* MAC stats accumulation period */ unsigned int linkpoll_period; /* link poll period in 0.1s */ unsigned int rev; /* chip revision */ diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c old mode 100755 new mode 100644 index e2b119312a0..2c2aaa74145 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -3086,7 +3086,7 @@ static int __devinit init_one(struct pci_dev *pdev, INIT_WORK(&adapter->fatal_error_handler_task, fatal_error_task); INIT_DELAYED_WORK(&adapter->adap_check_task, t3_adap_check_task); - for (i = 0; i < ai->nports; ++i) { + for (i = 0; i < ai->nports0 + ai->nports1; ++i) { struct net_device *netdev; netdev = alloc_etherdev_mq(sizeof(struct port_info), SGE_QSETS); @@ -3176,7 +3176,7 @@ static int __devinit init_one(struct pci_dev *pdev, out_free_dev: iounmap(adapter->regs); - for (i = ai->nports - 1; i >= 0; --i) + for (i = ai->nports0 + ai->nports1 - 1; i >= 0; --i) if (adapter->port[i]) free_netdev(adapter->port[i]); diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c old mode 100755 new mode 100644 index 7d8fbae58dc..31ed31a3428 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c @@ -493,20 +493,20 @@ int t3_phy_lasi_intr_handler(struct cphy *phy) } static const struct adapter_info t3_adap_info[] = { - {2, 0, + {1, 1, 0, F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, { S_GPIO3, S_GPIO5 }, 0, &mi1_mdio_ops, "Chelsio PE9000"}, - {2, 0, + {1, 1, 0, F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, { S_GPIO3, S_GPIO5 }, 0, &mi1_mdio_ops, "Chelsio T302"}, - {1, 0, + {1, 0, 0, F_GPIO1_OEN | F_GPIO6_OEN | F_GPIO7_OEN | F_GPIO10_OEN | F_GPIO11_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, { 0 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI, &mi1_mdio_ext_ops, "Chelsio T310"}, - {2, 0, + {1, 1, 0, F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO5_OEN | F_GPIO6_OEN | F_GPIO7_OEN | F_GPIO10_OEN | F_GPIO11_OEN | F_GPIO1_OUT_VAL | F_GPIO5_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, @@ -514,7 +514,7 @@ static const struct adapter_info t3_adap_info[] = { &mi1_mdio_ext_ops, "Chelsio T320"}, {}, {}, - {1, 0, + {1, 0, 0, F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO6_OEN | F_GPIO7_OEN | F_GPIO10_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, { S_GPIO9 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI, @@ -3227,20 +3227,22 @@ int t3_mps_set_active_ports(struct adapter *adap, unsigned int port_mask) } /* - * Perform the bits of HW initialization that are dependent on the number - * of available ports. + * Perform the bits of HW initialization that are dependent on the Tx + * channels being used. */ -static void init_hw_for_avail_ports(struct adapter *adap, int nports) +static void chan_init_hw(struct adapter *adap, unsigned int chan_map) { int i; - if (nports == 1) { + if (chan_map != 3) { /* one channel */ t3_set_reg_field(adap, A_ULPRX_CTL, F_ROUND_ROBIN, 0); t3_set_reg_field(adap, A_ULPTX_CONFIG, F_CFG_RR_ARB, 0); - t3_write_reg(adap, A_MPS_CFG, F_TPRXPORTEN | F_TPTXPORT0EN | - F_PORT0ACTIVE | F_ENFORCEPKT); - t3_write_reg(adap, A_PM1_TX_CFG, 0xffffffff); - } else { + t3_write_reg(adap, A_MPS_CFG, F_TPRXPORTEN | F_ENFORCEPKT | + (chan_map == 1 ? F_TPTXPORT0EN | F_PORT0ACTIVE : + F_TPTXPORT1EN | F_PORT1ACTIVE)); + t3_write_reg(adap, A_PM1_TX_CFG, + chan_map == 1 ? 0xffffffff : 0); + } else { /* two channels */ t3_set_reg_field(adap, A_ULPRX_CTL, 0, F_ROUND_ROBIN); t3_set_reg_field(adap, A_ULPTX_CONFIG, 0, F_CFG_RR_ARB); t3_write_reg(adap, A_ULPTX_DMA_WEIGHT, @@ -3548,7 +3550,7 @@ int t3_init_hw(struct adapter *adapter, u32 fw_params) t3_write_reg(adapter, A_PM1_RX_CFG, 0xffffffff); t3_write_reg(adapter, A_PM1_RX_MODE, 0); t3_write_reg(adapter, A_PM1_TX_MODE, 0); - init_hw_for_avail_ports(adapter, adapter->params.nports); + chan_init_hw(adapter, adapter->params.chan_map); t3_sge_init(adapter, &adapter->params.sge); t3_write_reg(adapter, A_T3DBG_GPIO_ACT_LOW, calc_gpio_intr(adapter)); @@ -3785,7 +3787,8 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, get_pci_mode(adapter, &adapter->params.pci); adapter->params.info = ai; - adapter->params.nports = ai->nports; + adapter->params.nports = ai->nports0 + ai->nports1; + adapter->params.chan_map = !!ai->nports0 | (!!ai->nports1 << 1); adapter->params.rev = t3_read_reg(adapter, A_PL_REV); /* * We used to only run the "adapter check task" once a second if @@ -3816,7 +3819,7 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, mc7_prep(adapter, &adapter->pmtx, MC7_PMTX_BASE_ADDR, "PMTX"); mc7_prep(adapter, &adapter->cm, MC7_CM_BASE_ADDR, "CM"); - p->nchan = ai->nports; + p->nchan = adapter->params.chan_map == 3 ? 2 : 1; p->pmrx_size = t3_mc7_size(&adapter->pmrx); p->pmtx_size = t3_mc7_size(&adapter->pmtx); p->cm_size = t3_mc7_size(&adapter->cm); -- GitLab From 5e68b772e6efd189d6aca76f6872fb75d51ace60 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Thu, 26 Mar 2009 16:39:29 +0000 Subject: [PATCH 4759/4982] cxgb3: map entire Rx page, feed map+offset to Rx ring. DMA mapping can be expensive in the presence of iommus. Reduce the Rx iommu activity by mapping an entire page, and provide the H/W the mapped address + offset of the current page chunk. Reserve bits at the end of the page to track mapping references, so the page can be unmapped. Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/adapter.h | 3 + drivers/net/cxgb3/sge.c | 138 +++++++++++++++++++++++++++--------- 2 files changed, 106 insertions(+), 35 deletions(-) mode change 100755 => 100644 drivers/net/cxgb3/sge.c diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h index 2cf6c9299f2..714df2b675e 100644 --- a/drivers/net/cxgb3/adapter.h +++ b/drivers/net/cxgb3/adapter.h @@ -85,6 +85,8 @@ struct fl_pg_chunk { struct page *page; void *va; unsigned int offset; + u64 *p_cnt; + DECLARE_PCI_UNMAP_ADDR(mapping); }; struct rx_desc; @@ -101,6 +103,7 @@ struct sge_fl { /* SGE per free-buffer list state */ struct fl_pg_chunk pg_chunk;/* page chunk cache */ unsigned int use_pages; /* whether FL uses pages or sk_buffs */ unsigned int order; /* order of page allocations */ + unsigned int alloc_size; /* size of allocated buffer */ struct rx_desc *desc; /* address of HW Rx descriptor ring */ struct rx_sw_desc *sdesc; /* address of SW Rx descriptor ring */ dma_addr_t phys_addr; /* physical address of HW ring start */ diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c old mode 100755 new mode 100644 index 54667f0dde9..26d3587f339 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -50,6 +50,7 @@ #define SGE_RX_COPY_THRES 256 #define SGE_RX_PULL_LEN 128 +#define SGE_PG_RSVD SMP_CACHE_BYTES /* * Page chunk size for FL0 buffers if FL0 is to be populated with page chunks. * It must be a divisor of PAGE_SIZE. If set to 0 FL0 will use sk_buffs @@ -57,8 +58,10 @@ */ #define FL0_PG_CHUNK_SIZE 2048 #define FL0_PG_ORDER 0 +#define FL0_PG_ALLOC_SIZE (PAGE_SIZE << FL0_PG_ORDER) #define FL1_PG_CHUNK_SIZE (PAGE_SIZE > 8192 ? 16384 : 8192) #define FL1_PG_ORDER (PAGE_SIZE > 8192 ? 0 : 1) +#define FL1_PG_ALLOC_SIZE (PAGE_SIZE << FL1_PG_ORDER) #define SGE_RX_DROP_THRES 16 #define RX_RECLAIM_PERIOD (HZ/4) @@ -345,13 +348,21 @@ static inline int should_restart_tx(const struct sge_txq *q) return q->in_use - r < (q->size >> 1); } -static void clear_rx_desc(const struct sge_fl *q, struct rx_sw_desc *d) +static void clear_rx_desc(struct pci_dev *pdev, const struct sge_fl *q, + struct rx_sw_desc *d) { - if (q->use_pages) { - if (d->pg_chunk.page) - put_page(d->pg_chunk.page); + if (q->use_pages && d->pg_chunk.page) { + (*d->pg_chunk.p_cnt)--; + if (!*d->pg_chunk.p_cnt) + pci_unmap_page(pdev, + pci_unmap_addr(&d->pg_chunk, mapping), + q->alloc_size, PCI_DMA_FROMDEVICE); + + put_page(d->pg_chunk.page); d->pg_chunk.page = NULL; } else { + pci_unmap_single(pdev, pci_unmap_addr(d, dma_addr), + q->buf_size, PCI_DMA_FROMDEVICE); kfree_skb(d->skb); d->skb = NULL; } @@ -372,9 +383,8 @@ static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q) while (q->credits--) { struct rx_sw_desc *d = &q->sdesc[cidx]; - pci_unmap_single(pdev, pci_unmap_addr(d, dma_addr), - q->buf_size, PCI_DMA_FROMDEVICE); - clear_rx_desc(q, d); + + clear_rx_desc(pdev, q, d); if (++cidx == q->size) cidx = 0; } @@ -417,18 +427,39 @@ static inline int add_one_rx_buf(void *va, unsigned int len, return 0; } -static int alloc_pg_chunk(struct sge_fl *q, struct rx_sw_desc *sd, gfp_t gfp, +static inline int add_one_rx_chunk(dma_addr_t mapping, struct rx_desc *d, + unsigned int gen) +{ + d->addr_lo = cpu_to_be32(mapping); + d->addr_hi = cpu_to_be32((u64) mapping >> 32); + wmb(); + d->len_gen = cpu_to_be32(V_FLD_GEN1(gen)); + d->gen2 = cpu_to_be32(V_FLD_GEN2(gen)); + return 0; +} + +static int alloc_pg_chunk(struct adapter *adapter, struct sge_fl *q, + struct rx_sw_desc *sd, gfp_t gfp, unsigned int order) { if (!q->pg_chunk.page) { + dma_addr_t mapping; + q->pg_chunk.page = alloc_pages(gfp, order); if (unlikely(!q->pg_chunk.page)) return -ENOMEM; q->pg_chunk.va = page_address(q->pg_chunk.page); + q->pg_chunk.p_cnt = q->pg_chunk.va + (PAGE_SIZE << order) - + SGE_PG_RSVD; q->pg_chunk.offset = 0; + mapping = pci_map_page(adapter->pdev, q->pg_chunk.page, + 0, q->alloc_size, PCI_DMA_FROMDEVICE); + pci_unmap_addr_set(&q->pg_chunk, mapping, mapping); } sd->pg_chunk = q->pg_chunk; + prefetch(sd->pg_chunk.p_cnt); + q->pg_chunk.offset += q->buf_size; if (q->pg_chunk.offset == (PAGE_SIZE << order)) q->pg_chunk.page = NULL; @@ -436,6 +467,12 @@ static int alloc_pg_chunk(struct sge_fl *q, struct rx_sw_desc *sd, gfp_t gfp, q->pg_chunk.va += q->buf_size; get_page(q->pg_chunk.page); } + + if (sd->pg_chunk.offset == 0) + *sd->pg_chunk.p_cnt = 1; + else + *sd->pg_chunk.p_cnt += 1; + return 0; } @@ -460,35 +497,43 @@ static inline void ring_fl_db(struct adapter *adap, struct sge_fl *q) */ static int refill_fl(struct adapter *adap, struct sge_fl *q, int n, gfp_t gfp) { - void *buf_start; struct rx_sw_desc *sd = &q->sdesc[q->pidx]; struct rx_desc *d = &q->desc[q->pidx]; unsigned int count = 0; while (n--) { + dma_addr_t mapping; int err; if (q->use_pages) { - if (unlikely(alloc_pg_chunk(q, sd, gfp, q->order))) { + if (unlikely(alloc_pg_chunk(adap, q, sd, gfp, + q->order))) { nomem: q->alloc_failed++; break; } - buf_start = sd->pg_chunk.va; + mapping = pci_unmap_addr(&sd->pg_chunk, mapping) + + sd->pg_chunk.offset; + pci_unmap_addr_set(sd, dma_addr, mapping); + + add_one_rx_chunk(mapping, d, q->gen); + pci_dma_sync_single_for_device(adap->pdev, mapping, + q->buf_size - SGE_PG_RSVD, + PCI_DMA_FROMDEVICE); } else { - struct sk_buff *skb = alloc_skb(q->buf_size, gfp); + void *buf_start; + struct sk_buff *skb = alloc_skb(q->buf_size, gfp); if (!skb) goto nomem; sd->skb = skb; buf_start = skb->data; - } - - err = add_one_rx_buf(buf_start, q->buf_size, d, sd, q->gen, - adap->pdev); - if (unlikely(err)) { - clear_rx_desc(q, sd); - break; + err = add_one_rx_buf(buf_start, q->buf_size, d, sd, + q->gen, adap->pdev); + if (unlikely(err)) { + clear_rx_desc(adap->pdev, q, sd); + break; + } } d++; @@ -795,19 +840,19 @@ static struct sk_buff *get_packet_pg(struct adapter *adap, struct sge_fl *fl, struct sk_buff *newskb, *skb; struct rx_sw_desc *sd = &fl->sdesc[fl->cidx]; - newskb = skb = q->pg_skb; + dma_addr_t dma_addr = pci_unmap_addr(sd, dma_addr); + newskb = skb = q->pg_skb; if (!skb && (len <= SGE_RX_COPY_THRES)) { newskb = alloc_skb(len, GFP_ATOMIC); if (likely(newskb != NULL)) { __skb_put(newskb, len); - pci_dma_sync_single_for_cpu(adap->pdev, - pci_unmap_addr(sd, dma_addr), len, + pci_dma_sync_single_for_cpu(adap->pdev, dma_addr, len, PCI_DMA_FROMDEVICE); memcpy(newskb->data, sd->pg_chunk.va, len); - pci_dma_sync_single_for_device(adap->pdev, - pci_unmap_addr(sd, dma_addr), len, - PCI_DMA_FROMDEVICE); + pci_dma_sync_single_for_device(adap->pdev, dma_addr, + len, + PCI_DMA_FROMDEVICE); } else if (!drop_thres) return NULL; recycle: @@ -820,16 +865,25 @@ recycle: if (unlikely(q->rx_recycle_buf || (!skb && fl->credits <= drop_thres))) goto recycle; + prefetch(sd->pg_chunk.p_cnt); + if (!skb) newskb = alloc_skb(SGE_RX_PULL_LEN, GFP_ATOMIC); + if (unlikely(!newskb)) { if (!drop_thres) return NULL; goto recycle; } - pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr), - fl->buf_size, PCI_DMA_FROMDEVICE); + pci_dma_sync_single_for_cpu(adap->pdev, dma_addr, len, + PCI_DMA_FROMDEVICE); + (*sd->pg_chunk.p_cnt)--; + if (!*sd->pg_chunk.p_cnt) + pci_unmap_page(adap->pdev, + pci_unmap_addr(&sd->pg_chunk, mapping), + fl->alloc_size, + PCI_DMA_FROMDEVICE); if (!skb) { __skb_put(newskb, SGE_RX_PULL_LEN); memcpy(newskb->data, sd->pg_chunk.va, SGE_RX_PULL_LEN); @@ -1958,8 +2012,8 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq, skb_pull(skb, sizeof(*p) + pad); skb->protocol = eth_type_trans(skb, adap->port[p->iff]); pi = netdev_priv(skb->dev); - if ((pi->rx_offload & T3_RX_CSUM) && p->csum_valid && p->csum == htons(0xffff) && - !p->fragment) { + if ((pi->rx_offload & T3_RX_CSUM) && p->csum_valid && + p->csum == htons(0xffff) && !p->fragment) { qs->port_stats[SGE_PSTAT_RX_CSUM_GOOD]++; skb->ip_summed = CHECKSUM_UNNECESSARY; } else @@ -2034,10 +2088,19 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs, fl->credits--; len -= offset; - pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr), - fl->buf_size, PCI_DMA_FROMDEVICE); + pci_dma_sync_single_for_cpu(adap->pdev, + pci_unmap_addr(sd, dma_addr), + fl->buf_size - SGE_PG_RSVD, + PCI_DMA_FROMDEVICE); + + (*sd->pg_chunk.p_cnt)--; + if (!*sd->pg_chunk.p_cnt) + pci_unmap_page(adap->pdev, + pci_unmap_addr(&sd->pg_chunk, mapping), + fl->alloc_size, + PCI_DMA_FROMDEVICE); - prefetch(&qs->lro_frag_tbl); + prefetch(qs->lro_va); rx_frag += nr_frags; rx_frag->page = sd->pg_chunk.page; @@ -2047,6 +2110,7 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs, qs->lro_frag_tbl.nr_frags++; qs->lro_frag_tbl.len = frag_len; + if (!complete) return; @@ -2236,6 +2300,8 @@ no_mem: if (fl->use_pages) { void *addr = fl->sdesc[fl->cidx].pg_chunk.va; + prefetch(&qs->lro_frag_tbl); + prefetch(addr); #if L1_CACHE_BYTES < 128 prefetch(addr + L1_CACHE_BYTES); @@ -2972,21 +3038,23 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, q->fl[1].use_pages = FL1_PG_CHUNK_SIZE > 0; q->fl[0].order = FL0_PG_ORDER; q->fl[1].order = FL1_PG_ORDER; + q->fl[0].alloc_size = FL0_PG_ALLOC_SIZE; + q->fl[1].alloc_size = FL1_PG_ALLOC_SIZE; spin_lock_irq(&adapter->sge.reg_lock); /* FL threshold comparison uses < */ ret = t3_sge_init_rspcntxt(adapter, q->rspq.cntxt_id, irq_vec_idx, q->rspq.phys_addr, q->rspq.size, - q->fl[0].buf_size, 1, 0); + q->fl[0].buf_size - SGE_PG_RSVD, 1, 0); if (ret) goto err_unlock; for (i = 0; i < SGE_RXQ_PER_SET; ++i) { ret = t3_sge_init_flcntxt(adapter, q->fl[i].cntxt_id, 0, q->fl[i].phys_addr, q->fl[i].size, - q->fl[i].buf_size, p->cong_thres, 1, - 0); + q->fl[i].buf_size - SGE_PG_RSVD, + p->cong_thres, 1, 0); if (ret) goto err_unlock; } -- GitLab From f9384d41c02408dd404aa64d66d0ef38adcf6479 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 27 Mar 2009 01:09:17 -0700 Subject: [PATCH 4760/4982] sparc64: Fix MM refcount check in smp_flush_tlb_pending(). As explained by Benjamin Herrenschmidt: > CPU 0 is running the context, task->mm == task->active_mm == your > context. The CPU is in userspace happily churning things. > > CPU 1 used to run it, not anymore, it's now running fancyfsd which > is a kernel thread, but current->active_mm still points to that > same context. > > Because there's only one "real" user, mm_users is 1 (but mm_count is > elevated, it's just that the presence on CPU 1 as active_mm has no > effect on mm_count(). > > At this point, fancyfsd decides to invalidate a mapping currently mapped > by that context, for example because a networked file has changed > remotely or something like that, using unmap_mapping_ranges(). > > So CPU 1 goes into the zapping code, which eventually ends up calling > flush_tlb_pending(). Your test will succeed, as current->active_mm is > indeed the target mm for the flush, and mm_users is indeed 1. So you > will -not- send an IPI to the other CPU, and CPU 0 will continue happily > accessing the pages that should have been unmapped. To fix this problem, check ->mm instead of ->active_mm, and this means: > So if you test current->mm, you effectively account for mm_users == 1, > so the only way the mm can be active on another processor is as a lazy > mm for a kernel thread. So your test should work properly as long > as you don't have a HW that will do speculative TLB reloads into the > TLB on that other CPU (and even if you do, you flush-on-switch-in should > get rid of any crap here). And therefore we should be OK. Signed-off-by: David S. Miller --- arch/sparc/kernel/smp_64.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index 6cd1a5b6506..79457f682b5 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c @@ -1031,7 +1031,7 @@ void smp_fetch_global_regs(void) * If the address space is non-shared (ie. mm->count == 1) we avoid * cross calls when we want to flush the currently running process's * tlb state. This is done by clearing all cpu bits except the current - * processor's in current->active_mm->cpu_vm_mask and performing the + * processor's in current->mm->cpu_vm_mask and performing the * flush locally only. This will force any subsequent cpus which run * this task to flush the context from the local tlb if the process * migrates to another cpu (again). @@ -1074,7 +1074,7 @@ void smp_flush_tlb_pending(struct mm_struct *mm, unsigned long nr, unsigned long u32 ctx = CTX_HWBITS(mm->context); int cpu = get_cpu(); - if (mm == current->active_mm && atomic_read(&mm->mm_users) == 1) + if (mm == current->mm && atomic_read(&mm->mm_users) == 1) mm->cpu_vm_mask = cpumask_of_cpu(cpu); else smp_cross_call_masked(&xcall_flush_tlb_pending, -- GitLab From bd14ba842cd29edbbd40e566194bd33cf0c92f6c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 27 Mar 2009 01:10:58 -0700 Subject: [PATCH 4761/4982] gianfar: Fix kfree(skb) Noticed by Li Yang. Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index a7a67376615..44cbf2622b4 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -1317,7 +1317,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) skb_new = skb_realloc_headroom(skb, GMAC_FCB_LEN); if (!skb_new) { dev->stats.tx_errors++; - kfree(skb); + kfree_skb(skb); return NETDEV_TX_OK; } kfree_skb(skb); -- GitLab From 0412d6c9271811b84568fcea3237e2193e21866a Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 25 Mar 2009 19:46:48 +0100 Subject: [PATCH 4762/4982] i.MX1: remove fb support from mach-imx The lack of an include file currently breaks compilation of mx1ads_defconfig. As framebuffer support is not actively used for mach-imx and the whole architecture will be replaced by mach-mx1 soon, just remove fb support. Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/generic.c | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c index 887cb21f75b..05f1739ee12 100644 --- a/arch/arm/mach-imx/generic.c +++ b/arch/arm/mach-imx/generic.c @@ -29,7 +29,6 @@ #include #include -#include #include #include @@ -245,43 +244,8 @@ void __init imx_set_mmc_info(struct imxmmc_platform_data *info) imx_mmc_device.dev.platform_data = info; } -static struct imx_fb_platform_data imx_fb_info; - -void __init set_imx_fb_info(struct imx_fb_platform_data *hard_imx_fb_info) -{ - memcpy(&imx_fb_info,hard_imx_fb_info,sizeof(struct imx_fb_platform_data)); -} - -static struct resource imxfb_resources[] = { - [0] = { - .start = 0x00205000, - .end = 0x002050FF, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = LCDC_INT, - .end = LCDC_INT, - .flags = IORESOURCE_IRQ, - }, -}; - -static u64 fb_dma_mask = ~(u64)0; - -static struct platform_device imxfb_device = { - .name = "imx-fb", - .id = 0, - .dev = { - .platform_data = &imx_fb_info, - .dma_mask = &fb_dma_mask, - .coherent_dma_mask = 0xffffffff, - }, - .num_resources = ARRAY_SIZE(imxfb_resources), - .resource = imxfb_resources, -}; - static struct platform_device *devices[] __initdata = { &imx_mmc_device, - &imxfb_device, }; static struct map_desc imx_io_desc[] __initdata = { -- GitLab From 05fd8e73e1357feaea9c48938d937eae76b4aef4 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sat, 7 Mar 2009 12:55:49 +0100 Subject: [PATCH 4763/4982] clkdev: add possibility to get a clock based on the device name This adds clk_get_sys to get a clock without the associated struct device. Signed-off-by: Sascha Hauer --- arch/arm/common/clkdev.c | 11 +++++++++-- include/linux/clk.h | 17 +++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/arch/arm/common/clkdev.c b/arch/arm/common/clkdev.c index 1037bba1832..5589444ff43 100644 --- a/arch/arm/common/clkdev.c +++ b/arch/arm/common/clkdev.c @@ -62,9 +62,8 @@ static struct clk *clk_find(const char *dev_id, const char *con_id) return clk; } -struct clk *clk_get(struct device *dev, const char *con_id) +struct clk *clk_get_sys(const char *dev_id, const char *con_id) { - const char *dev_id = dev ? dev_name(dev) : NULL; struct clk *clk; mutex_lock(&clocks_mutex); @@ -75,6 +74,14 @@ struct clk *clk_get(struct device *dev, const char *con_id) return clk ? clk : ERR_PTR(-ENOENT); } +EXPORT_SYMBOL(clk_get_sys); + +struct clk *clk_get(struct device *dev, const char *con_id) +{ + const char *dev_id = dev ? dev_name(dev) : NULL; + + return clk_get_sys(dev_id, con_id); +} EXPORT_SYMBOL(clk_get); void clk_put(struct clk *clk) diff --git a/include/linux/clk.h b/include/linux/clk.h index 778777316ea..1db9bbf444a 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -125,4 +125,21 @@ int clk_set_parent(struct clk *clk, struct clk *parent); */ struct clk *clk_get_parent(struct clk *clk); +/** + * clk_get_sys - get a clock based upon the device name + * @dev_id: device name + * @con_id: connection ID + * + * Returns a struct clk corresponding to the clock producer, or + * valid IS_ERR() condition containing errno. The implementation + * uses @dev_id and @con_id to determine the clock consumer, and + * thereby the clock producer. In contrast to clk_get() this function + * takes the device name instead of the device itself for identification. + * + * Drivers must assume that the clock source is not enabled. + * + * clk_get_sys should not be called from within interrupt context. + */ +struct clk *clk_get_sys(const char *dev_id, const char *con_id); + #endif -- GitLab From 74bef9a4fa978669b234c4454daa596c0494c09a Mon Sep 17 00:00:00 2001 From: Ilya Yanok Date: Tue, 3 Mar 2009 02:49:23 +0300 Subject: [PATCH 4764/4982] mxc: add arch_reset() function This patch adds arch_reset() function for all mxc platforms. It also removes (unsused) arch/arm/mach-mx2/system.c file. This patch has been tested on i.MX1/27/31/35 Signed-off-by: Ilya Yanok Signed-off-by: Sascha Hauer --- arch/arm/mach-mx2/Makefile | 2 +- arch/arm/plat-mxc/Makefile | 2 +- arch/arm/plat-mxc/include/mach/system.h | 5 +-- arch/arm/{mach-mx2 => plat-mxc}/system.c | 50 +++++++++++++----------- 4 files changed, 30 insertions(+), 29 deletions(-) rename arch/arm/{mach-mx2 => plat-mxc}/system.c (62%) diff --git a/arch/arm/mach-mx2/Makefile b/arch/arm/mach-mx2/Makefile index 6e1a2bffc81..950649a9154 100644 --- a/arch/arm/mach-mx2/Makefile +++ b/arch/arm/mach-mx2/Makefile @@ -4,7 +4,7 @@ # Object file lists. -obj-y := system.o generic.o devices.o serial.o +obj-y := generic.o devices.o serial.o obj-$(CONFIG_MACH_MX21) += clock_imx21.o diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile index 564fd4ebf38..055406312b6 100644 --- a/arch/arm/plat-mxc/Makefile +++ b/arch/arm/plat-mxc/Makefile @@ -3,7 +3,7 @@ # # Common support -obj-y := irq.o clock.o gpio.o time.o devices.o cpu.o +obj-y := irq.o clock.o gpio.o time.o devices.o cpu.o system.o obj-$(CONFIG_ARCH_MX1) += iomux-mx1-mx2.o dma-mx1-mx2.o obj-$(CONFIG_ARCH_MX2) += iomux-mx1-mx2.o dma-mx1-mx2.o diff --git a/arch/arm/plat-mxc/include/mach/system.h b/arch/arm/plat-mxc/include/mach/system.h index cd03ebaa49b..e56241af870 100644 --- a/arch/arm/plat-mxc/include/mach/system.h +++ b/arch/arm/plat-mxc/include/mach/system.h @@ -26,9 +26,6 @@ static inline void arch_idle(void) cpu_do_idle(); } -static inline void arch_reset(char mode, const char *cmd) -{ - cpu_reset(0); -} +void arch_reset(char mode, const char *cmd); #endif /* __ASM_ARCH_MXC_SYSTEM_H__ */ diff --git a/arch/arm/mach-mx2/system.c b/arch/arm/plat-mxc/system.c similarity index 62% rename from arch/arm/mach-mx2/system.c rename to arch/arm/plat-mxc/system.c index 92c79d4bd16..79c37577c91 100644 --- a/arch/arm/mach-mx2/system.c +++ b/arch/arm/plat-mxc/system.c @@ -3,6 +3,7 @@ * Copyright (C) 2000 Deep Blue Solutions Ltd * Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved. * Copyright 2008 Juergen Beisert, kernel@pengutronix.de + * Copyright 2009 Ilya Yanok, Emcraft Systems Ltd, yanok@emcraft.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,42 +23,45 @@ #include #include #include +#include +#include #include #include #include -/* - * Put the CPU into idle mode. It is called by default_idle() - * in process.c file. - */ -void arch_idle(void) -{ - /* - * This should do all the clock switching - * and wait for interrupt tricks. - */ - cpu_do_idle(); -} - -#define WDOG_WCR_REG IO_ADDRESS(WDOG_BASE_ADDR) -#define WDOG_WCR_SRS (1 << 4) +#ifdef CONFIG_ARCH_MX1 +#define WDOG_WCR_REG IO_ADDRESS(WDT_BASE_ADDR) +#define WDOG_WCR_ENABLE (1 << 0) +#else +#define WDOG_WCR_REG IO_ADDRESS(WDOG_BASE_ADDR) +#define WDOG_WCR_ENABLE (1 << 2) +#endif /* * Reset the system. It is called by machine_restart(). */ void arch_reset(char mode, const char *cmd) { - struct clk *clk; + if (!cpu_is_mx1()) { + struct clk *clk; - clk = clk_get(NULL, "wdog_clk"); - if (!clk) { - printk(KERN_ERR"Cannot activate the watchdog. Giving up\n"); - return; + clk = clk_get_sys("imx-wdt.0", NULL); + if (!IS_ERR(clk)) + clk_enable(clk); } - clk_enable(clk); - /* Assert SRS signal */ - __raw_writew(__raw_readw(WDOG_WCR_REG) & ~WDOG_WCR_SRS, WDOG_WCR_REG); + __raw_writew(WDOG_WCR_ENABLE, WDOG_WCR_REG); + + /* wait for reset to assert... */ + mdelay(500); + + printk(KERN_ERR "Watchdog reset failed to assert reset\n"); + + /* delay to allow the serial port to show the message */ + mdelay(50); + + /* we'll take a jump through zero as a poor second */ + cpu_reset(0); } -- GitLab From f909ef6437a8388e3f1272c67ee29071f930bd6b Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 15 Jan 2009 15:21:00 +0100 Subject: [PATCH 4765/4982] imxfb: add clock support v2: Added change from Martin Fuzzey: pixclock should be in pico seconds instead of MHz. Signed-off-by: Sascha Hauer --- drivers/video/imxfb.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index bd1cb75cd14..8f7a2b2c78e 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -26,9 +26,11 @@ #include #include #include +#include #include #include #include +#include #include @@ -141,6 +143,7 @@ struct imxfb_rgb { struct imxfb_info { struct platform_device *pdev; void __iomem *regs; + struct clk *clk; u_int max_bpp; u_int max_xres; @@ -403,6 +406,8 @@ static void imxfb_enable_controller(struct imxfb_info *fbi) writel(RMCR_LCDC_EN, fbi->regs + LCDC_RMCR); + clk_enable(fbi->clk); + if (fbi->backlight_power) fbi->backlight_power(1); if (fbi->lcd_power) @@ -418,6 +423,8 @@ static void imxfb_disable_controller(struct imxfb_info *fbi) if (fbi->lcd_power) fbi->lcd_power(0); + clk_disable(fbi->clk); + writel(0, fbi->regs + LCDC_RMCR); } @@ -461,6 +468,9 @@ static struct fb_ops imxfb_ops = { static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info) { struct imxfb_info *fbi = info->par; + unsigned int pcr, lcd_clk; + unsigned long long tmp; + pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n", var->xres, var->hsync_len, var->left_margin, var->right_margin); @@ -507,7 +517,23 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf writel(SIZE_XMAX(var->xres) | SIZE_YMAX(var->yres), fbi->regs + LCDC_SIZE); - writel(fbi->pcr, fbi->regs + LCDC_PCR); + + lcd_clk = clk_get_rate(fbi->clk); + tmp = var->pixclock * (unsigned long long)lcd_clk; + do_div(tmp, 1000000); + if (do_div(tmp, 1000000) > 500000) + tmp++; + pcr = (unsigned int)tmp; + if (--pcr > 0x3F) { + pcr = 0x3F; + printk(KERN_WARNING "Must limit pixel clock to %uHz\n", + lcd_clk / pcr); + } + + /* add sync polarities */ + pcr |= fbi->pcr & ~0x3F; + + writel(pcr, fbi->regs + LCDC_PCR); writel(fbi->pwmr, fbi->regs + LCDC_PWMR); writel(fbi->lscr1, fbi->regs + LCDC_LSCR1); writel(fbi->dmacr, fbi->regs + LCDC_DMACR); @@ -649,6 +675,13 @@ static int __init imxfb_probe(struct platform_device *pdev) goto failed_req; } + fbi->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(fbi->clk)) { + ret = PTR_ERR(fbi->clk);; + dev_err(&pdev->dev, "unable to get clock: %d\n", ret); + goto failed_getclock; + } + fbi->regs = ioremap(res->start, resource_size(res)); if (fbi->regs == NULL) { printk(KERN_ERR"Cannot map frame buffer registers\n"); @@ -717,6 +750,8 @@ failed_platform_init: dma_free_writecombine(&pdev->dev,fbi->map_size,fbi->map_cpu, fbi->map_dma); failed_map: + clk_put(fbi->clk); +failed_getclock: iounmap(fbi->regs); failed_ioremap: release_mem_region(res->start, res->end - res->start); @@ -751,6 +786,9 @@ static int __devexit imxfb_remove(struct platform_device *pdev) iounmap(fbi->regs); release_mem_region(res->start, res->end - res->start + 1); + clk_disable(fbi->clk); + clk_put(fbi->clk); + platform_set_drvdata(pdev, NULL); return 0; -- GitLab From ec621699031b298eadd7e364f65281291b19ea37 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 26 Mar 2009 12:23:23 +0100 Subject: [PATCH 4766/4982] i.MX21/27: remove ifdef CONFIG_FB_IMX Compile in the framebuffer device unconditionally to fix pcm038 compilation without framebuffer support. Signed-off-by: Sascha Hauer --- arch/arm/mach-mx2/devices.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/mach-mx2/devices.c b/arch/arm/mach-mx2/devices.c index f81aa8a8fbb..a0f1b367432 100644 --- a/arch/arm/mach-mx2/devices.c +++ b/arch/arm/mach-mx2/devices.c @@ -229,7 +229,6 @@ struct platform_device mxc_nand_device = { .resource = mxc_nand_resources, }; -#ifdef CONFIG_FB_IMX /* * lcdc: * - i.MX1: the basic controller @@ -259,7 +258,6 @@ struct platform_device mxc_fb_device = { .coherent_dma_mask = 0xFFFFFFFF, }, }; -#endif #ifdef CONFIG_MACH_MX27 static struct resource mxc_fec_resources[] = { -- GitLab From 4d1e4e5a6387aad97590e2da9c6db1350f22f63a Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 26 Mar 2009 12:38:26 +0100 Subject: [PATCH 4767/4982] imxfb: Fix TFT mode We read from the PCR reg to determine whether to use TFT mode or not. This is not possible because it may not have been initialized with the correct value yet. Select it using fbi->pcr instead. Signed-off-by: Sascha Hauer --- drivers/video/imxfb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 8f7a2b2c78e..15a0ee6d8e2 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -327,7 +327,7 @@ static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) break; case 16: default: - if (readl(fbi->regs + LCDC_PCR) & PCR_TFT) + if (fbi->pcr & PCR_TFT) rgb = &def_rgb_16_tft; else rgb = &def_rgb_16_stn; -- GitLab From 66f3e6afa8e48486c4dd535d616fbfe04569fbd4 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Fri, 27 Mar 2009 16:55:41 +0100 Subject: [PATCH 4768/4982] [IA64] Fix kstat_this_cpu build breakage arch/ia64/kernel/irq_ia64.c: In function 'ia64_handle_irq': arch/ia64/kernel/irq_ia64.c:498: error: 'struct kernel_stat' has no member named 'irqs' arch/ia64/kernel/irq_ia64.c:500: error: 'struct kernel_stat' has no member named 'irqs' arch/ia64/kernel/irq_ia64.c: In function 'ia64_process_pending_intr': arch/ia64/kernel/irq_ia64.c:556: error: 'struct kernel_stat' has no member named 'irqs' arch/ia64/kernel/irq_ia64.c:558: error: 'struct kernel_stat' has no member named 'irqs' Fix build breakage due to recent kstat_this_cpu changes in: d7e51e66899f95dabc89b4d4c6674a6e50fa37fc sparseirq: make some func to be used with genirq Signed-off-by: Jes Sorensen Signed-off-by: Tony Luck --- arch/ia64/kernel/irq_ia64.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index 28d3d483db9..977a6ef1332 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -493,14 +493,16 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) saved_tpr = ia64_getreg(_IA64_REG_CR_TPR); ia64_srlz_d(); while (vector != IA64_SPURIOUS_INT_VECTOR) { + struct irq_desc *desc; + int irq = local_vector_to_irq(vector); + + desc = irq_desc + irq; if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) { smp_local_flush_tlb(); - kstat_this_cpu.irqs[vector]++; + kstat_incr_irqs_this_cpu(irq, desc); } else if (unlikely(IS_RESCHEDULE(vector))) - kstat_this_cpu.irqs[vector]++; + kstat_incr_irqs_this_cpu(irq, desc); else { - int irq = local_vector_to_irq(vector); - ia64_setreg(_IA64_REG_CR_TPR, vector); ia64_srlz_d(); @@ -543,22 +545,25 @@ void ia64_process_pending_intr(void) vector = ia64_get_ivr(); - irq_enter(); - saved_tpr = ia64_getreg(_IA64_REG_CR_TPR); - ia64_srlz_d(); + irq_enter(); + saved_tpr = ia64_getreg(_IA64_REG_CR_TPR); + ia64_srlz_d(); /* * Perform normal interrupt style processing */ while (vector != IA64_SPURIOUS_INT_VECTOR) { + struct irq_desc *desc; + int irq = local_vector_to_irq(vector); + desc = irq_desc + irq; + if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) { smp_local_flush_tlb(); - kstat_this_cpu.irqs[vector]++; + kstat_incr_irqs_this_cpu(irq, desc); } else if (unlikely(IS_RESCHEDULE(vector))) - kstat_this_cpu.irqs[vector]++; + kstat_incr_irqs_this_cpu(irq, desc); else { struct pt_regs *old_regs = set_irq_regs(NULL); - int irq = local_vector_to_irq(vector); ia64_setreg(_IA64_REG_CR_TPR, vector); ia64_srlz_d(); -- GitLab From ec1ab0abde0af586a59541ad71841f022dcac3e7 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 9 May 2008 12:35:29 +0200 Subject: [PATCH 4769/4982] affs: fix missing unlocks in affs_remove_link In two error cases affs_remove_link doesn't call affs_unlock_dir to release the i_hash_lock semaphore. Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/affs/amigaffs.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c index 805573005de..7d0f0a30f7a 100644 --- a/fs/affs/amigaffs.c +++ b/fs/affs/amigaffs.c @@ -179,14 +179,18 @@ affs_remove_link(struct dentry *dentry) affs_lock_dir(dir); affs_fix_dcache(dentry, link_ino); retval = affs_remove_hash(dir, link_bh); - if (retval) + if (retval) { + affs_unlock_dir(dir); goto done; + } mark_buffer_dirty_inode(link_bh, inode); memcpy(AFFS_TAIL(sb, bh)->name, AFFS_TAIL(sb, link_bh)->name, 32); retval = affs_insert_hash(dir, bh); - if (retval) + if (retval) { + affs_unlock_dir(dir); goto done; + } mark_buffer_dirty_inode(bh, inode); affs_unlock_dir(dir); -- GitLab From 2b1c6bd77d4e6a727ffac8630cd154b2144b751a Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 28 Nov 2008 10:09:09 +0100 Subject: [PATCH 4770/4982] generic compat_sys_ustat Due to a different size of ino_t ustat needs a compat handler, but currently only x86 and mips provide one. Add a generic compat_sys_ustat and switch all architectures over to it. Instead of doing various user copy hacks compat_sys_ustat just reimplements sys_ustat as it's trivial. This was suggested by Arnd Bergmann. Found by Eric Sandeen when running xfstests/017 on ppc64, which causes stack smashing warnings on RHEL/Fedora due to the too large amount of data writen by the syscall. Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro --- arch/ia64/ia32/ia32_entry.S | 2 +- arch/mips/kernel/linux32.c | 34 ------------------------------ arch/mips/kernel/scall64-n32.S | 2 +- arch/mips/kernel/scall64-o32.S | 2 +- arch/parisc/kernel/syscall_table.S | 2 +- arch/powerpc/include/asm/systbl.h | 2 +- arch/s390/kernel/compat_wrapper.S | 2 +- arch/x86/ia32/ia32entry.S | 2 +- arch/x86/ia32/sys_ia32.c | 22 ------------------- arch/x86/include/asm/ia32.h | 7 ------ arch/x86/include/asm/sys_ia32.h | 2 -- fs/compat.c | 28 ++++++++++++++++++++++++ include/linux/compat.h | 8 +++++++ 13 files changed, 43 insertions(+), 72 deletions(-) diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S index a46f8395e9a..af9405cd70e 100644 --- a/arch/ia64/ia32/ia32_entry.S +++ b/arch/ia64/ia32/ia32_entry.S @@ -240,7 +240,7 @@ ia32_syscall_table: data8 sys_ni_syscall data8 sys_umask /* 60 */ data8 sys_chroot - data8 sys_ustat + data8 compat_sys_ustat data8 sys_dup2 data8 sys_getppid data8 sys_getpgrp /* 65 */ diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index 1a86f84fa94..784859cedef 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c @@ -356,40 +356,6 @@ SYSCALL_DEFINE1(32_personality, unsigned long, personality) return ret; } -/* ustat compatibility */ -struct ustat32 { - compat_daddr_t f_tfree; - compat_ino_t f_tinode; - char f_fname[6]; - char f_fpack[6]; -}; - -extern asmlinkage long sys_ustat(dev_t dev, struct ustat __user * ubuf); - -SYSCALL_DEFINE2(32_ustat, dev_t, dev, struct ustat32 __user *, ubuf32) -{ - int err; - struct ustat tmp; - struct ustat32 tmp32; - mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); - err = sys_ustat(dev, (struct ustat __user *)&tmp); - set_fs(old_fs); - - if (err) - goto out; - - memset(&tmp32, 0, sizeof(struct ustat32)); - tmp32.f_tfree = tmp.f_tfree; - tmp32.f_tinode = tmp.f_tinode; - - err = copy_to_user(ubuf32, &tmp32, sizeof(struct ustat32)) ? -EFAULT : 0; - -out: - return err; -} - SYSCALL_DEFINE4(32_sendfile, long, out_fd, long, in_fd, compat_off_t __user *, offset, s32, count) { diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 7438e92f8a0..f61d6b0e573 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -253,7 +253,7 @@ EXPORT(sysn32_call_table) PTR compat_sys_utime /* 6130 */ PTR sys_mknod PTR sys_32_personality - PTR sys_32_ustat + PTR compat_sys_ustat PTR compat_sys_statfs PTR compat_sys_fstatfs /* 6135 */ PTR sys_sysfs diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index b0fef4ff982..60997f1f69d 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -265,7 +265,7 @@ sys_call_table: PTR sys_olduname PTR sys_umask /* 4060 */ PTR sys_chroot - PTR sys_32_ustat + PTR compat_sys_ustat PTR sys_dup2 PTR sys_getppid PTR sys_getpgrp /* 4065 */ diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index 303d2b647e4..03b9a01bc16 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S @@ -130,7 +130,7 @@ ENTRY_OURS(newuname) ENTRY_SAME(umask) /* 60 */ ENTRY_SAME(chroot) - ENTRY_SAME(ustat) + ENTRY_COMP(ustat) ENTRY_SAME(dup2) ENTRY_SAME(getppid) ENTRY_SAME(getpgrp) /* 65 */ diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h index 72353f6070a..fe166491e9d 100644 --- a/arch/powerpc/include/asm/systbl.h +++ b/arch/powerpc/include/asm/systbl.h @@ -65,7 +65,7 @@ SYSCALL(ni_syscall) SYSX(sys_ni_syscall,sys_olduname, sys_olduname) COMPAT_SYS_SPU(umask) SYSCALL_SPU(chroot) -SYSCALL(ustat) +COMPAT_SYS(ustat) SYSCALL_SPU(dup2) SYSCALL_SPU(getppid) SYSCALL_SPU(getpgrp) diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 62c706eb0de..87cf5a79a35 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -252,7 +252,7 @@ sys32_chroot_wrapper: sys32_ustat_wrapper: llgfr %r2,%r2 # dev_t llgtr %r3,%r3 # struct ustat * - jg sys_ustat + jg compat_sys_ustat .globl sys32_dup2_wrapper sys32_dup2_wrapper: diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index 5a0d76dc56a..8ef8876666b 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -557,7 +557,7 @@ ia32_sys_call_table: .quad sys32_olduname .quad sys_umask /* 60 */ .quad sys_chroot - .quad sys32_ustat + .quad compat_sys_ustat .quad sys_dup2 .quad sys_getppid .quad sys_getpgrp /* 65 */ diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c index 6c0d7f6231a..efac92fd1ef 100644 --- a/arch/x86/ia32/sys_ia32.c +++ b/arch/x86/ia32/sys_ia32.c @@ -638,28 +638,6 @@ long sys32_uname(struct old_utsname __user *name) return err ? -EFAULT : 0; } -long sys32_ustat(unsigned dev, struct ustat32 __user *u32p) -{ - struct ustat u; - mm_segment_t seg; - int ret; - - seg = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ustat(dev, (struct ustat __user *)&u); - set_fs(seg); - if (ret < 0) - return ret; - - if (!access_ok(VERIFY_WRITE, u32p, sizeof(struct ustat32)) || - __put_user((__u32) u.f_tfree, &u32p->f_tfree) || - __put_user((__u32) u.f_tinode, &u32p->f_tfree) || - __copy_to_user(&u32p->f_fname, u.f_fname, sizeof(u.f_fname)) || - __copy_to_user(&u32p->f_fpack, u.f_fpack, sizeof(u.f_fpack))) - ret = -EFAULT; - return ret; -} - asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv, compat_uptr_t __user *envp, struct pt_regs *regs) { diff --git a/arch/x86/include/asm/ia32.h b/arch/x86/include/asm/ia32.h index 50ca486fd88..1f7e6251728 100644 --- a/arch/x86/include/asm/ia32.h +++ b/arch/x86/include/asm/ia32.h @@ -129,13 +129,6 @@ typedef struct compat_siginfo { } _sifields; } compat_siginfo_t; -struct ustat32 { - __u32 f_tfree; - compat_ino_t f_tinode; - char f_fname[6]; - char f_fpack[6]; -}; - #define IA32_STACK_TOP IA32_PAGE_OFFSET #ifdef __KERNEL__ diff --git a/arch/x86/include/asm/sys_ia32.h b/arch/x86/include/asm/sys_ia32.h index ffb08be2a53..72a6dcd1299 100644 --- a/arch/x86/include/asm/sys_ia32.h +++ b/arch/x86/include/asm/sys_ia32.h @@ -70,8 +70,6 @@ struct old_utsname; asmlinkage long sys32_olduname(struct oldold_utsname __user *); long sys32_uname(struct old_utsname __user *); -long sys32_ustat(unsigned, struct ustat32 __user *); - asmlinkage long sys32_execve(char __user *, compat_uptr_t __user *, compat_uptr_t __user *, struct pt_regs *); asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *); diff --git a/fs/compat.c b/fs/compat.c index d0145ca2757..4e0db94b535 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -378,6 +378,34 @@ out: return error; } +/* + * This is a copy of sys_ustat, just dealing with a structure layout. + * Given how simple this syscall is that apporach is more maintainable + * than the various conversion hacks. + */ +asmlinkage long compat_sys_ustat(unsigned dev, struct compat_ustat __user *u) +{ + struct super_block *sb; + struct compat_ustat tmp; + struct kstatfs sbuf; + int err; + + sb = user_get_super(new_decode_dev(dev)); + if (!sb) + return -EINVAL; + err = vfs_statfs(sb->s_root, &sbuf); + drop_super(sb); + if (err) + return err; + + memset(&tmp, 0, sizeof(struct compat_ustat)); + tmp.f_tfree = sbuf.f_bfree; + tmp.f_tinode = sbuf.f_ffree; + if (copy_to_user(u, &tmp, sizeof(struct compat_ustat))) + return -EFAULT; + return 0; +} + static int get_compat_flock(struct flock *kfl, struct compat_flock __user *ufl) { if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) || diff --git a/include/linux/compat.h b/include/linux/compat.h index 3fd2194ff57..b880864672d 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -125,6 +125,13 @@ struct compat_dirent { char d_name[256]; }; +struct compat_ustat { + compat_daddr_t f_tfree; + compat_ino_t f_tinode; + char f_fname[6]; + char f_fpack[6]; +}; + typedef union compat_sigval { compat_int_t sival_int; compat_uptr_t sival_ptr; @@ -178,6 +185,7 @@ long compat_sys_semtimedop(int semid, struct sembuf __user *tsems, unsigned nsems, const struct compat_timespec __user *timeout); asmlinkage long compat_sys_keyctl(u32 option, u32 arg2, u32 arg3, u32 arg4, u32 arg5); +asmlinkage long compat_sys_ustat(unsigned dev, struct compat_ustat __user *u32); asmlinkage ssize_t compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, unsigned long vlen); -- GitLab From b6520c81934848cef126d93951f7ce242e0f656d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 5 Jan 2009 19:10:37 +0100 Subject: [PATCH 4771/4982] cleanup d_add_ci Make sure that comments describe what's going on and not how, and always use __d_instantiate instead of two separate branches, one with d_instantiate and one with __d_instantiate. Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/dcache.c | 48 ++++++++++++++++++------------------------------ 1 file changed, 18 insertions(+), 30 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index 07e2d4a44bd..90bbd7e1b11 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1247,15 +1247,18 @@ struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode, struct dentry *found; struct dentry *new; - /* Does a dentry matching the name exist already? */ + /* + * First check if a dentry matching the name already exists, + * if not go ahead and create it now. + */ found = d_hash_and_lookup(dentry->d_parent, name); - /* If not, create it now and return */ if (!found) { new = d_alloc(dentry->d_parent, name); if (!new) { error = -ENOMEM; goto err_out; } + found = d_splice_alias(inode, new); if (found) { dput(new); @@ -1263,61 +1266,46 @@ struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode, } return new; } - /* Matching dentry exists, check if it is negative. */ + + /* + * If a matching dentry exists, and it's not negative use it. + * + * Decrement the reference count to balance the iget() done + * earlier on. + */ if (found->d_inode) { if (unlikely(found->d_inode != inode)) { /* This can't happen because bad inodes are unhashed. */ BUG_ON(!is_bad_inode(inode)); BUG_ON(!is_bad_inode(found->d_inode)); } - /* - * Already have the inode and the dentry attached, decrement - * the reference count to balance the iget() done - * earlier on. We found the dentry using d_lookup() so it - * cannot be disconnected and thus we do not need to worry - * about any NFS/disconnectedness issues here. - */ iput(inode); return found; } + /* * Negative dentry: instantiate it unless the inode is a directory and - * has a 'disconnected' dentry (i.e. IS_ROOT and DCACHE_DISCONNECTED), - * in which case d_move() that in place of the found dentry. + * already has a dentry. */ - if (!S_ISDIR(inode->i_mode)) { - /* Not a directory; everything is easy. */ - d_instantiate(found, inode); - return found; - } spin_lock(&dcache_lock); - if (list_empty(&inode->i_dentry)) { - /* - * Directory without a 'disconnected' dentry; we need to do - * d_instantiate() by hand because it takes dcache_lock which - * we already hold. - */ + if (!S_ISDIR(inode->i_mode) || list_empty(&inode->i_dentry)) { __d_instantiate(found, inode); spin_unlock(&dcache_lock); security_d_instantiate(found, inode); return found; } + /* - * Directory with a 'disconnected' dentry; get a reference to the - * 'disconnected' dentry. + * In case a directory already has a (disconnected) entry grab a + * reference to it, move it in place and use it. */ new = list_entry(inode->i_dentry.next, struct dentry, d_alias); dget_locked(new); spin_unlock(&dcache_lock); - /* Do security vodoo. */ security_d_instantiate(found, inode); - /* Move new in place of found. */ d_move(new, found); - /* Balance the iget() we did above. */ iput(inode); - /* Throw away found. */ dput(found); - /* Use new as the actual dentry. */ return new; err_out: -- GitLab From c8fe8f30c7fe6ce6fc44a1db7d5bfa5144cd9211 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 5 Jan 2009 19:27:23 +0100 Subject: [PATCH 4772/4982] cleanup may_open Add a switch for the various i_mode fmt cases, and remove the comment about writeability of devices nodes - that part is handled in inode_permission and comment on (briefly) there. Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/namei.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index bbc15c23755..2a40409e3e0 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1486,24 +1486,22 @@ int may_open(struct path *path, int acc_mode, int flag) if (!inode) return -ENOENT; - if (S_ISLNK(inode->i_mode)) + switch (inode->i_mode & S_IFMT) { + case S_IFLNK: return -ELOOP; - - if (S_ISDIR(inode->i_mode) && (acc_mode & MAY_WRITE)) - return -EISDIR; - - /* - * FIFO's, sockets and device files are special: they don't - * actually live on the filesystem itself, and as such you - * can write to them even if the filesystem is read-only. - */ - if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { - flag &= ~O_TRUNC; - } else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { + case S_IFDIR: + if (acc_mode & MAY_WRITE) + return -EISDIR; + break; + case S_IFBLK: + case S_IFCHR: if (path->mnt->mnt_flags & MNT_NODEV) return -EACCES; - + /*FALLTHRU*/ + case S_IFIFO: + case S_IFSOCK: flag &= ~O_TRUNC; + break; } error = inode_permission(inode, acc_mode); -- GitLab From 9e6766cc8c125cf406960a5bfdf1455473f4835c Mon Sep 17 00:00:00 2001 From: Duane Griffin Date: Thu, 8 Jan 2009 22:43:48 +0000 Subject: [PATCH 4773/4982] ufs: validate maximum fast symlink size from superblock The maximum fast symlink size is set in the superblock of certain types of UFS filesystem. Before using it we need to check that it isn't longer than the available space we have in the inode. Signed-off-by: Duane Griffin Signed-off-by: Al Viro --- fs/ufs/super.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 261a1c2f22d..e1c1fc5ee23 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -636,6 +636,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) unsigned block_size, super_block_size; unsigned flags; unsigned super_block_offset; + unsigned maxsymlen; int ret = -EINVAL; uspi = NULL; @@ -1069,6 +1070,16 @@ magic_found: uspi->s_maxsymlinklen = fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_maxsymlinklen); + if (uspi->fs_magic == UFS2_MAGIC) + maxsymlen = 2 * 4 * (UFS_NDADDR + UFS_NINDIR); + else + maxsymlen = 4 * (UFS_NDADDR + UFS_NINDIR); + if (uspi->s_maxsymlinklen > maxsymlen) { + ufs_warning(sb, __func__, "ufs_read_super: excessive maximum " + "fast symlink size (%u)\n", uspi->s_maxsymlinklen); + uspi->s_maxsymlinklen = maxsymlen; + } + inode = ufs_iget(sb, UFS_ROOTINO); if (IS_ERR(inode)) { ret = PTR_ERR(inode); -- GitLab From f33219b7a90c4779a0b59e11fb35ebc4542db328 Mon Sep 17 00:00:00 2001 From: Duane Griffin Date: Thu, 8 Jan 2009 22:43:49 +0000 Subject: [PATCH 4774/4982] ufs: don't truncate longer ufs2 fast symlinks ufs2 fast symlinks can be twice as long as ufs ones, however the code was using the ufs size in various places. Fix that so ufs2 symlinks over 60 characters aren't truncated. Note that we copy the entire area instead of using the maxsymlinklen field from the superblock. This way we will be more robust against corruption (of the superblock). While we are at it, use memcpy instead of open-coding it with for loops. Signed-off-by: Duane Griffin Signed-off-by: Al Viro --- fs/ufs/inode.c | 37 ++++++++++++++++--------------------- fs/ufs/ufs.h | 2 +- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 39f87789856..ac8b324415d 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -622,7 +622,6 @@ static int ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode) struct ufs_inode_info *ufsi = UFS_I(inode); struct super_block *sb = inode->i_sb; mode_t mode; - unsigned i; /* * Copy data to the in-core inode. @@ -655,11 +654,11 @@ static int ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode) if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) { - for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) - ufsi->i_u1.i_data[i] = ufs_inode->ui_u2.ui_addr.ui_db[i]; + memcpy(ufsi->i_u1.i_data, &ufs_inode->ui_u2.ui_addr, + sizeof(ufs_inode->ui_u2.ui_addr)); } else { - for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) - ufsi->i_u1.i_symlink[i] = ufs_inode->ui_u2.ui_symlink[i]; + memcpy(ufsi->i_u1.i_symlink, ufs_inode->ui_u2.ui_symlink, + sizeof(ufs_inode->ui_u2.ui_symlink)); } return 0; } @@ -669,7 +668,6 @@ static int ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode) struct ufs_inode_info *ufsi = UFS_I(inode); struct super_block *sb = inode->i_sb; mode_t mode; - unsigned i; UFSD("Reading ufs2 inode, ino %lu\n", inode->i_ino); /* @@ -704,12 +702,11 @@ static int ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode) */ if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) { - for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) - ufsi->i_u1.u2_i_data[i] = - ufs2_inode->ui_u2.ui_addr.ui_db[i]; + memcpy(ufsi->i_u1.u2_i_data, &ufs2_inode->ui_u2.ui_addr, + sizeof(ufs2_inode->ui_u2.ui_addr)); } else { - for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) - ufsi->i_u1.i_symlink[i] = ufs2_inode->ui_u2.ui_symlink[i]; + memcpy(ufsi->i_u1.i_symlink, ufs2_inode->ui_u2.ui_symlink, + sizeof(ufs2_inode->ui_u2.ui_symlink)); } return 0; } @@ -781,7 +778,6 @@ static void ufs1_update_inode(struct inode *inode, struct ufs_inode *ufs_inode) { struct super_block *sb = inode->i_sb; struct ufs_inode_info *ufsi = UFS_I(inode); - unsigned i; ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode); ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink); @@ -809,12 +805,12 @@ static void ufs1_update_inode(struct inode *inode, struct ufs_inode *ufs_inode) /* ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, inode->i_rdev); */ ufs_inode->ui_u2.ui_addr.ui_db[0] = ufsi->i_u1.i_data[0]; } else if (inode->i_blocks) { - for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) - ufs_inode->ui_u2.ui_addr.ui_db[i] = ufsi->i_u1.i_data[i]; + memcpy(&ufs_inode->ui_u2.ui_addr, ufsi->i_u1.i_data, + sizeof(ufs_inode->ui_u2.ui_addr)); } else { - for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) - ufs_inode->ui_u2.ui_symlink[i] = ufsi->i_u1.i_symlink[i]; + memcpy(&ufs_inode->ui_u2.ui_symlink, ufsi->i_u1.i_symlink, + sizeof(ufs_inode->ui_u2.ui_symlink)); } if (!inode->i_nlink) @@ -825,7 +821,6 @@ static void ufs2_update_inode(struct inode *inode, struct ufs2_inode *ufs_inode) { struct super_block *sb = inode->i_sb; struct ufs_inode_info *ufsi = UFS_I(inode); - unsigned i; UFSD("ENTER\n"); ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode); @@ -850,11 +845,11 @@ static void ufs2_update_inode(struct inode *inode, struct ufs2_inode *ufs_inode) /* ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, inode->i_rdev); */ ufs_inode->ui_u2.ui_addr.ui_db[0] = ufsi->i_u1.u2_i_data[0]; } else if (inode->i_blocks) { - for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) - ufs_inode->ui_u2.ui_addr.ui_db[i] = ufsi->i_u1.u2_i_data[i]; + memcpy(&ufs_inode->ui_u2.ui_addr, ufsi->i_u1.u2_i_data, + sizeof(ufs_inode->ui_u2.ui_addr)); } else { - for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) - ufs_inode->ui_u2.ui_symlink[i] = ufsi->i_u1.i_symlink[i]; + memcpy(&ufs_inode->ui_u2.ui_symlink, ufsi->i_u1.i_symlink, + sizeof(ufs_inode->ui_u2.ui_symlink)); } if (!inode->i_nlink) diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h index 11c035168ea..69b3427d788 100644 --- a/fs/ufs/ufs.h +++ b/fs/ufs/ufs.h @@ -23,7 +23,7 @@ struct ufs_sb_info { struct ufs_inode_info { union { __fs32 i_data[15]; - __u8 i_symlink[4*15]; + __u8 i_symlink[2 * 4 * 15]; __fs64 u2_i_data[15]; } i_u1; __u32 i_flags; -- GitLab From b12903f1384cd176a3994a6bf6caf5a482169cc8 Mon Sep 17 00:00:00 2001 From: Duane Griffin Date: Thu, 8 Jan 2009 22:43:50 +0000 Subject: [PATCH 4775/4982] ufs: ensure fast symlinks are NUL-terminated Ensure fast symlink targets are NUL-terminated, even if corrupted on-disk. Signed-off-by: Duane Griffin Signed-off-by: Al Viro --- fs/ufs/inode.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index ac8b324415d..3d2512c21f0 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -658,7 +658,8 @@ static int ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode) sizeof(ufs_inode->ui_u2.ui_addr)); } else { memcpy(ufsi->i_u1.i_symlink, ufs_inode->ui_u2.ui_symlink, - sizeof(ufs_inode->ui_u2.ui_symlink)); + sizeof(ufs_inode->ui_u2.ui_symlink) - 1); + ufsi->i_u1.i_symlink[sizeof(ufs_inode->ui_u2.ui_symlink) - 1] = 0; } return 0; } @@ -706,7 +707,8 @@ static int ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode) sizeof(ufs2_inode->ui_u2.ui_addr)); } else { memcpy(ufsi->i_u1.i_symlink, ufs2_inode->ui_u2.ui_symlink, - sizeof(ufs2_inode->ui_u2.ui_symlink)); + sizeof(ufs2_inode->ui_u2.ui_symlink) - 1); + ufsi->i_u1.i_symlink[sizeof(ufs2_inode->ui_u2.ui_symlink) - 1] = 0; } return 0; } -- GitLab From 723be1f30046a46471b00106ebef9d8c832f12e9 Mon Sep 17 00:00:00 2001 From: Duane Griffin Date: Thu, 8 Jan 2009 22:43:51 +0000 Subject: [PATCH 4776/4982] ufs: copy symlink data into the correct union member Copy symlink data into the union member it is accessed through. Although this shouldn't make a difference to behaviour it makes the code easier to follow and grep through. It may also prevent problems if the struct/union definitions change in the future. Signed-off-by: Duane Griffin Signed-off-by: Al Viro --- fs/ufs/namei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c index e3a9b1fac75..23119fe7ad6 100644 --- a/fs/ufs/namei.c +++ b/fs/ufs/namei.c @@ -147,7 +147,7 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry, } else { /* fast symlink */ inode->i_op = &ufs_fast_symlink_inode_operations; - memcpy((char*)&UFS_I(inode)->i_u1.i_data,symname,l); + memcpy(UFS_I(inode)->i_u1.i_symlink, symname, l); inode->i_size = l-1; } mark_inode_dirty(inode); -- GitLab From 10f303ae1e5e77a9f7cb053e6329906afb132c67 Mon Sep 17 00:00:00 2001 From: Cheng Renquan Date: Wed, 14 Jan 2009 17:01:33 +0800 Subject: [PATCH 4777/4982] do_pipe cleanup: drop its last user in arch/alpha/ The last user of do_pipe is in arch/alpha/, after replacing it with do_pipe_flags, the do_pipe can be totally dropped. Signed-off-by: Cheng Renquan Acked-by: Richard Henderson Signed-off-by: Al Viro --- arch/alpha/kernel/entry.S | 3 ++- arch/alpha/kernel/osf_sys.c | 2 -- fs/pipe.c | 5 ----- include/linux/fs.h | 1 - 4 files changed, 2 insertions(+), 9 deletions(-) diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index e4a54b61589..b45d913a51c 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -903,8 +903,9 @@ sys_alpha_pipe: stq $26, 0($sp) .prologue 0 + mov $31, $17 lda $16, 8($sp) - jsr $26, do_pipe + jsr $26, do_pipe_flags ldq $26, 0($sp) bne $0, 1f diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index ae41f097864..42ee05981e7 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -46,8 +46,6 @@ #include #include -extern int do_pipe(int *); - /* * Brk needs to return an error. Still support Linux's brk(0) query idiom, * which OSF programs just shouldn't be doing. We're still not quite diff --git a/fs/pipe.c b/fs/pipe.c index 14f502b89cf..df3719562fc 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -1034,11 +1034,6 @@ int do_pipe_flags(int *fd, int flags) return error; } -int do_pipe(int *fd) -{ - return do_pipe_flags(fd, 0); -} - /* * sys_pipe() is the normal C calling standard for creating * a pipe. It's not the way Unix traditionally does this, though. diff --git a/include/linux/fs.h b/include/linux/fs.h index 92734c0012e..51de83bd8a8 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1881,7 +1881,6 @@ static inline void allow_write_access(struct file *file) if (file) atomic_inc(&file->f_path.dentry->d_inode->i_writecount); } -extern int do_pipe(int *); extern int do_pipe_flags(int *, int); extern struct file *create_read_pipe(struct file *f, int flags); extern struct file *create_write_pipe(int flags); -- GitLab From c2aca5e529a2499d454c41e01f59f1d5fe4a1364 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Tue, 20 Jan 2009 10:29:45 +0000 Subject: [PATCH 4778/4982] vfs: Update fs.h to use inline functions when no file locking set This avoids various issues which might give rise to compiler warnings about missing functions and/or unused variable with the previous macros. This also fixes a bug where one of the macros was returning 0, but it should have been void. Reported-by: Randy Dunlap Signed-off-by: Steven Whitehouse Tested-by: Randy Dunlap Signed-off-by: Al Viro --- include/linux/fs.h | 165 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 139 insertions(+), 26 deletions(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index 51de83bd8a8..d84020b7e67 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1063,34 +1063,147 @@ extern int lease_modify(struct file_lock **, int); extern int lock_may_read(struct inode *, loff_t start, unsigned long count); extern int lock_may_write(struct inode *, loff_t start, unsigned long count); #else /* !CONFIG_FILE_LOCKING */ -#define fcntl_getlk(a, b) ({ -EINVAL; }) -#define fcntl_setlk(a, b, c, d) ({ -EACCES; }) +static inline int fcntl_getlk(struct file *file, struct flock __user *user) +{ + return -EINVAL; +} + +static inline int fcntl_setlk(unsigned int fd, struct file *file, + unsigned int cmd, struct flock __user *user) +{ + return -EACCES; +} + #if BITS_PER_LONG == 32 -#define fcntl_getlk64(a, b) ({ -EINVAL; }) -#define fcntl_setlk64(a, b, c, d) ({ -EACCES; }) +static inline int fcntl_getlk64(struct file *file, struct flock64 __user *user) +{ + return -EINVAL; +} + +static inline int fcntl_setlk64(unsigned int fd, struct file *file, + unsigned int cmd, struct flock64 __user *user) +{ + return -EACCES; +} #endif -#define fcntl_setlease(a, b, c) ({ 0; }) -#define fcntl_getlease(a) ({ 0; }) -#define locks_init_lock(a) ({ }) -#define __locks_copy_lock(a, b) ({ }) -#define locks_copy_lock(a, b) ({ }) -#define locks_remove_posix(a, b) ({ }) -#define locks_remove_flock(a) ({ }) -#define posix_test_lock(a, b) ({ 0; }) -#define posix_lock_file(a, b, c) ({ -ENOLCK; }) -#define posix_lock_file_wait(a, b) ({ -ENOLCK; }) -#define posix_unblock_lock(a, b) (-ENOENT) -#define vfs_test_lock(a, b) ({ 0; }) -#define vfs_lock_file(a, b, c, d) (-ENOLCK) -#define vfs_cancel_lock(a, b) ({ 0; }) -#define flock_lock_file_wait(a, b) ({ -ENOLCK; }) -#define __break_lease(a, b) ({ 0; }) -#define lease_get_mtime(a, b) ({ }) -#define generic_setlease(a, b, c) ({ -EINVAL; }) -#define vfs_setlease(a, b, c) ({ -EINVAL; }) -#define lease_modify(a, b) ({ -EINVAL; }) -#define lock_may_read(a, b, c) ({ 1; }) -#define lock_may_write(a, b, c) ({ 1; }) +static inline int fcntl_setlease(unsigned int fd, struct file *filp, long arg) +{ + return 0; +} + +static inline int fcntl_getlease(struct file *filp) +{ + return 0; +} + +static inline void locks_init_lock(struct file_lock *fl) +{ + return; +} + +static inline void __locks_copy_lock(struct file_lock *new, struct file_lock *fl) +{ + return; +} + +static inline void locks_copy_lock(struct file_lock *new, struct file_lock *fl) +{ + return; +} + +static inline void locks_remove_posix(struct file *filp, fl_owner_t owner) +{ + return; +} + +static inline void locks_remove_flock(struct file *filp) +{ + return; +} + +static inline void posix_test_lock(struct file *filp, struct file_lock *fl) +{ + return; +} + +static inline int posix_lock_file(struct file *filp, struct file_lock *fl, + struct file_lock *conflock) +{ + return -ENOLCK; +} + +static inline int posix_lock_file_wait(struct file *filp, struct file_lock *fl) +{ + return -ENOLCK; +} + +static inline int posix_unblock_lock(struct file *filp, + struct file_lock *waiter) +{ + return -ENOENT; +} + +static inline int vfs_test_lock(struct file *filp, struct file_lock *fl) +{ + return 0; +} + +static inline int vfs_lock_file(struct file *filp, unsigned int cmd, + struct file_lock *fl, struct file_lock *conf) +{ + return -ENOLCK; +} + +static inline int vfs_cancel_lock(struct file *filp, struct file_lock *fl) +{ + return 0; +} + +static inline int flock_lock_file_wait(struct file *filp, + struct file_lock *request) +{ + return -ENOLCK; +} + +static inline int __break_lease(struct inode *inode, unsigned int mode) +{ + return 0; +} + +static inline void lease_get_mtime(struct inode *inode, struct timespec *time) +{ + return; +} + +static inline int generic_setlease(struct file *filp, long arg, + struct file_lock **flp) +{ + return -EINVAL; +} + +static inline int vfs_setlease(struct file *filp, long arg, + struct file_lock **lease) +{ + return -EINVAL; +} + +static inline int lease_modify(struct file_lock **before, int arg) +{ + return -EINVAL; +} + +static inline int lock_may_read(struct inode *inode, loff_t start, + unsigned long len) +{ + return 1; +} + +static inline int lock_may_write(struct inode *inode, loff_t start, + unsigned long len) +{ + return 1; +} + #endif /* !CONFIG_FILE_LOCKING */ -- GitLab From af5df56688acfb75c1b15b4e000ec5e82a9cdc29 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Tue, 20 Jan 2009 10:29:46 +0000 Subject: [PATCH 4779/4982] vfs: Further changes from macro to inline function in fs.h There is a second set of macros for when CONFIG_FILE_LOCKING is not set. This patch updates those to become inline functions as well. Signed-off-by: Steven Whitehouse Signed-off-by: Al Viro --- include/linux/fs.h | 45 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index d84020b7e67..5f74d616cd7 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1800,13 +1800,44 @@ static inline int break_lease(struct inode *inode, unsigned int mode) return 0; } #else /* !CONFIG_FILE_LOCKING */ -#define locks_mandatory_locked(a) ({ 0; }) -#define locks_mandatory_area(a, b, c, d, e) ({ 0; }) -#define __mandatory_lock(a) ({ 0; }) -#define mandatory_lock(a) ({ 0; }) -#define locks_verify_locked(a) ({ 0; }) -#define locks_verify_truncate(a, b, c) ({ 0; }) -#define break_lease(a, b) ({ 0; }) +static inline int locks_mandatory_locked(struct inode *inode) +{ + return 0; +} + +static inline int locks_mandatory_area(int rw, struct inode *inode, + struct file *filp, loff_t offset, + size_t count) +{ + return 0; +} + +static inline int __mandatory_lock(struct inode *inode) +{ + return 0; +} + +static inline int mandatory_lock(struct inode *inode) +{ + return 0; +} + +static inline int locks_verify_locked(struct inode *inode) +{ + return 0; +} + +static inline int locks_verify_truncate(struct inode *inode, struct file *filp, + size_t size) +{ + return 0; +} + +static inline int break_lease(struct inode *inode, unsigned int mode) +{ + return 0; +} + #endif /* CONFIG_FILE_LOCKING */ /* fs/open.c */ -- GitLab From a9f184f02aa49d46c4c35311d93cbcd1c61149df Mon Sep 17 00:00:00 2001 From: Sukadev Bhattiprolu Date: Wed, 28 Jan 2009 16:57:12 -0800 Subject: [PATCH 4780/4982] devpts: Must release s_umount on error We should drop the ->s_umount mutex if an error occurs after the sget()/grab_super() call. This was introduced when adding support for multiple instances of devpts and noticed during a code review/reorg. Signed-off-by: Sukadev Bhattiprolu Signed-off-by: Al Viro --- fs/devpts/inode.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index bff4052b05e..140b43144cd 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -385,6 +385,7 @@ static int new_pts_mount(struct file_system_type *fs_type, int flags, fail: dput(mnt->mnt_sb->s_root); + up_write(&mnt->mnt_sb->s_umount); deactivate_super(mnt->mnt_sb); return err; } @@ -473,6 +474,7 @@ static int init_pts_mount(struct file_system_type *fs_type, int flags, err = mknod_ptmx(mnt->mnt_sb); if (err) { dput(mnt->mnt_sb->s_root); + up_write(&mnt->mnt_sb->s_umount); deactivate_super(mnt->mnt_sb); } -- GitLab From e56980d451904b623573ef4966cbab768e433c79 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 11 Feb 2009 13:14:54 -0800 Subject: [PATCH 4781/4982] fs: make struct dentry->d_op const This change will allow for tagging many dentry_operations const in the source tree. Signed-off-by: Jan Engelhardt Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Al Viro --- include/linux/dcache.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/dcache.h b/include/linux/dcache.h index c66d22487bf..15156364d19 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -112,7 +112,7 @@ struct dentry { struct list_head d_subdirs; /* our children */ struct list_head d_alias; /* inode alias list */ unsigned long d_time; /* used by d_revalidate */ - struct dentry_operations *d_op; + const struct dentry_operations *d_op; struct super_block *d_sb; /* The root of the dentry tree */ void *d_fsdata; /* fs-specific data */ -- GitLab From f786aa90e026f2174bb0c26d49f338c5c46ede55 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 20 Feb 2009 05:51:22 +0000 Subject: [PATCH 4782/4982] constify dentry_operations: NFS Signed-off-by: Al Viro --- fs/nfs/dir.c | 4 ++-- fs/nfs/nfs4_fs.h | 2 +- include/linux/nfs_fs.h | 2 +- include/linux/nfs_xdr.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 672368f865c..78bf72fc1db 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -899,7 +899,7 @@ static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode) iput(inode); } -struct dentry_operations nfs_dentry_operations = { +const struct dentry_operations nfs_dentry_operations = { .d_revalidate = nfs_lookup_revalidate, .d_delete = nfs_dentry_delete, .d_iput = nfs_dentry_iput, @@ -967,7 +967,7 @@ out: #ifdef CONFIG_NFS_V4 static int nfs_open_revalidate(struct dentry *, struct nameidata *); -struct dentry_operations nfs4_dentry_operations = { +const struct dentry_operations nfs4_dentry_operations = { .d_revalidate = nfs_open_revalidate, .d_delete = nfs_dentry_delete, .d_iput = nfs_dentry_iput, diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 4e4d3320437..84345deab26 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -179,7 +179,7 @@ struct nfs4_state_recovery_ops { int (*recover_lock)(struct nfs4_state *, struct file_lock *); }; -extern struct dentry_operations nfs4_dentry_operations; +extern const struct dentry_operations nfs4_dentry_operations; extern const struct inode_operations nfs4_dir_inode_operations; /* inode.c */ diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index db867b04ac3..8cc8807f77d 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -415,7 +415,7 @@ extern const struct inode_operations nfs_dir_inode_operations; extern const struct inode_operations nfs3_dir_inode_operations; #endif /* CONFIG_NFS_V3 */ extern const struct file_operations nfs_dir_operations; -extern struct dentry_operations nfs_dentry_operations; +extern const struct dentry_operations nfs_dentry_operations; extern void nfs_force_lookup_revalidate(struct inode *dir); extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr); diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 2e5f00066af..43a713fce11 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -785,7 +785,7 @@ struct nfs_access_entry; */ struct nfs_rpc_ops { u32 version; /* Protocol version */ - struct dentry_operations *dentry_ops; + const struct dentry_operations *dentry_ops; const struct inode_operations *dir_inode_ops; const struct inode_operations *file_inode_ops; -- GitLab From e16404ed0f3f330dc3e99b95cef69bb60bcd27f7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 20 Feb 2009 05:55:13 +0000 Subject: [PATCH 4783/4982] constify dentry_operations: misc filesystems Signed-off-by: Al Viro --- fs/adfs/adfs.h | 2 +- fs/adfs/dir.c | 2 +- fs/affs/affs.h | 3 +-- fs/affs/namei.c | 4 ++-- fs/coda/dir.c | 2 +- fs/hfs/hfs_fs.h | 2 +- fs/hfs/sysdep.c | 2 +- fs/hfsplus/hfsplus_fs.h | 2 +- fs/hfsplus/inode.c | 2 +- fs/hostfs/hostfs_kern.c | 4 ++-- fs/hpfs/dentry.c | 2 +- fs/isofs/inode.c | 2 +- fs/ncpfs/dir.c | 4 ++-- fs/reiserfs/xattr.c | 2 +- fs/smbfs/dir.c | 4 ++-- fs/sysv/namei.c | 2 +- fs/sysv/sysv.h | 2 +- include/linux/ncp_fs.h | 2 +- 18 files changed, 22 insertions(+), 23 deletions(-) diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h index 831157502d5..e0a85dbeeb8 100644 --- a/fs/adfs/adfs.h +++ b/fs/adfs/adfs.h @@ -86,7 +86,7 @@ void __adfs_error(struct super_block *sb, const char *function, /* dir_*.c */ extern const struct inode_operations adfs_dir_inode_operations; extern const struct file_operations adfs_dir_operations; -extern struct dentry_operations adfs_dentry_operations; +extern const struct dentry_operations adfs_dentry_operations; extern struct adfs_dir_ops adfs_f_dir_ops; extern struct adfs_dir_ops adfs_fplus_dir_ops; diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c index 85a30e92980..e867ccf3724 100644 --- a/fs/adfs/dir.c +++ b/fs/adfs/dir.c @@ -263,7 +263,7 @@ adfs_compare(struct dentry *parent, struct qstr *entry, struct qstr *name) return 0; } -struct dentry_operations adfs_dentry_operations = { +const struct dentry_operations adfs_dentry_operations = { .d_hash = adfs_hash, .d_compare = adfs_compare, }; diff --git a/fs/affs/affs.h b/fs/affs/affs.h index e9ec915f755..1a2d5e3c7f4 100644 --- a/fs/affs/affs.h +++ b/fs/affs/affs.h @@ -199,8 +199,7 @@ extern const struct address_space_operations affs_symlink_aops; extern const struct address_space_operations affs_aops; extern const struct address_space_operations affs_aops_ofs; -extern struct dentry_operations affs_dentry_operations; -extern struct dentry_operations affs_dentry_operations_intl; +extern const struct dentry_operations affs_dentry_operations; static inline void affs_set_blocksize(struct super_block *sb, int size) diff --git a/fs/affs/namei.c b/fs/affs/namei.c index cfcf1b6cf82..960d336ec69 100644 --- a/fs/affs/namei.c +++ b/fs/affs/namei.c @@ -19,12 +19,12 @@ static int affs_intl_toupper(int ch); static int affs_intl_hash_dentry(struct dentry *, struct qstr *); static int affs_intl_compare_dentry(struct dentry *, struct qstr *, struct qstr *); -struct dentry_operations affs_dentry_operations = { +const struct dentry_operations affs_dentry_operations = { .d_hash = affs_hash_dentry, .d_compare = affs_compare_dentry, }; -static struct dentry_operations affs_intl_dentry_operations = { +static const struct dentry_operations affs_intl_dentry_operations = { .d_hash = affs_intl_hash_dentry, .d_compare = affs_intl_compare_dentry, }; diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 75b1fa90b2c..4bb9d0a5dec 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -59,7 +59,7 @@ static int coda_return_EIO(void) } #define CODA_EIO_ERROR ((void *) (coda_return_EIO)) -static struct dentry_operations coda_dentry_operations = +static const struct dentry_operations coda_dentry_operations = { .d_revalidate = coda_dentry_revalidate, .d_delete = coda_dentry_delete, diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h index 9955232fdf8..052387e1167 100644 --- a/fs/hfs/hfs_fs.h +++ b/fs/hfs/hfs_fs.h @@ -213,7 +213,7 @@ extern void hfs_mdb_put(struct super_block *); extern int hfs_part_find(struct super_block *, sector_t *, sector_t *); /* string.c */ -extern struct dentry_operations hfs_dentry_operations; +extern const struct dentry_operations hfs_dentry_operations; extern int hfs_hash_dentry(struct dentry *, struct qstr *); extern int hfs_strcmp(const unsigned char *, unsigned int, diff --git a/fs/hfs/sysdep.c b/fs/hfs/sysdep.c index 5bf89ec01cd..7478f5c219a 100644 --- a/fs/hfs/sysdep.c +++ b/fs/hfs/sysdep.c @@ -31,7 +31,7 @@ static int hfs_revalidate_dentry(struct dentry *dentry, struct nameidata *nd) return 1; } -struct dentry_operations hfs_dentry_operations = +const struct dentry_operations hfs_dentry_operations = { .d_revalidate = hfs_revalidate_dentry, .d_hash = hfs_hash_dentry, diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index f027a905225..5c10d803d9d 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -327,7 +327,7 @@ void hfsplus_file_truncate(struct inode *); /* inode.c */ extern const struct address_space_operations hfsplus_aops; extern const struct address_space_operations hfsplus_btree_aops; -extern struct dentry_operations hfsplus_dentry_operations; +extern const struct dentry_operations hfsplus_dentry_operations; void hfsplus_inode_read_fork(struct inode *, struct hfsplus_fork_raw *); void hfsplus_inode_write_fork(struct inode *, struct hfsplus_fork_raw *); diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index f105ee9e1cc..1bcf597c056 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -137,7 +137,7 @@ const struct address_space_operations hfsplus_aops = { .writepages = hfsplus_writepages, }; -struct dentry_operations hfsplus_dentry_operations = { +const struct dentry_operations hfsplus_dentry_operations = { .d_hash = hfsplus_hash_dentry, .d_compare = hfsplus_compare_dentry, }; diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 5c538e0ec14..fe02ad4740e 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -31,12 +31,12 @@ static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode) #define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_path.dentry->d_inode) -int hostfs_d_delete(struct dentry *dentry) +static int hostfs_d_delete(struct dentry *dentry) { return 1; } -struct dentry_operations hostfs_dentry_ops = { +static const struct dentry_operations hostfs_dentry_ops = { .d_delete = hostfs_d_delete, }; diff --git a/fs/hpfs/dentry.c b/fs/hpfs/dentry.c index 08319126b2a..940d6d150be 100644 --- a/fs/hpfs/dentry.c +++ b/fs/hpfs/dentry.c @@ -49,7 +49,7 @@ static int hpfs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qst return 0; } -static struct dentry_operations hpfs_dentry_operations = { +static const struct dentry_operations hpfs_dentry_operations = { .d_hash = hpfs_hash_dentry, .d_compare = hpfs_compare_dentry, }; diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 6147ec3643a..13d2eddd069 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -114,7 +114,7 @@ static const struct super_operations isofs_sops = { }; -static struct dentry_operations isofs_dentry_ops[] = { +static const struct dentry_operations isofs_dentry_ops[] = { { .d_hash = isofs_hash, .d_compare = isofs_dentry_cmp, diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index 07e9715b865..9c590722d87 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c @@ -79,7 +79,7 @@ static int ncp_hash_dentry(struct dentry *, struct qstr *); static int ncp_compare_dentry (struct dentry *, struct qstr *, struct qstr *); static int ncp_delete_dentry(struct dentry *); -static struct dentry_operations ncp_dentry_operations = +static const struct dentry_operations ncp_dentry_operations = { .d_revalidate = ncp_lookup_validate, .d_hash = ncp_hash_dentry, @@ -87,7 +87,7 @@ static struct dentry_operations ncp_dentry_operations = .d_delete = ncp_delete_dentry, }; -struct dentry_operations ncp_root_dentry_operations = +const struct dentry_operations ncp_root_dentry_operations = { .d_hash = ncp_hash_dentry, .d_compare = ncp_compare_dentry, diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index ad92461cbfc..ae881ccd2f0 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -1136,7 +1136,7 @@ xattr_lookup_poison(struct dentry *dentry, struct qstr *q1, struct qstr *name) return 1; } -static struct dentry_operations xattr_lookup_poison_ops = { +static const struct dentry_operations xattr_lookup_poison_ops = { .d_compare = xattr_lookup_poison, }; diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c index e7ddd0328dd..3e4803b4427 100644 --- a/fs/smbfs/dir.c +++ b/fs/smbfs/dir.c @@ -277,7 +277,7 @@ static int smb_hash_dentry(struct dentry *, struct qstr *); static int smb_compare_dentry(struct dentry *, struct qstr *, struct qstr *); static int smb_delete_dentry(struct dentry *); -static struct dentry_operations smbfs_dentry_operations = +static const struct dentry_operations smbfs_dentry_operations = { .d_revalidate = smb_lookup_validate, .d_hash = smb_hash_dentry, @@ -285,7 +285,7 @@ static struct dentry_operations smbfs_dentry_operations = .d_delete = smb_delete_dentry, }; -static struct dentry_operations smbfs_dentry_operations_case = +static const struct dentry_operations smbfs_dentry_operations_case = { .d_revalidate = smb_lookup_validate, .d_delete = smb_delete_dentry, diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c index a1f1ef33e81..33e047b59b8 100644 --- a/fs/sysv/namei.c +++ b/fs/sysv/namei.c @@ -38,7 +38,7 @@ static int sysv_hash(struct dentry *dentry, struct qstr *qstr) return 0; } -struct dentry_operations sysv_dentry_operations = { +const struct dentry_operations sysv_dentry_operations = { .d_hash = sysv_hash, }; diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h index 38ebe3f85b3..5784a318c88 100644 --- a/fs/sysv/sysv.h +++ b/fs/sysv/sysv.h @@ -170,7 +170,7 @@ extern const struct file_operations sysv_file_operations; extern const struct file_operations sysv_dir_operations; extern const struct address_space_operations sysv_aops; extern const struct super_operations sysv_sops; -extern struct dentry_operations sysv_dentry_operations; +extern const struct dentry_operations sysv_dentry_operations; enum { diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h index f69e66d151c..30b06c89394 100644 --- a/include/linux/ncp_fs.h +++ b/include/linux/ncp_fs.h @@ -204,7 +204,7 @@ void ncp_update_inode2(struct inode *, struct ncp_entry_info *); /* linux/fs/ncpfs/dir.c */ extern const struct inode_operations ncp_dir_inode_operations; extern const struct file_operations ncp_dir_operations; -extern struct dentry_operations ncp_root_dentry_operations; +extern const struct dentry_operations ncp_root_dentry_operations; int ncp_conn_logged_in(struct super_block *); int ncp_date_dos2unix(__le16 time, __le16 date); void ncp_date_unix2dos(int unix_date, __le16 * time, __le16 * date); -- GitLab From a488257ce5a55c53973671218791296463698d07 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 20 Feb 2009 05:55:46 +0000 Subject: [PATCH 4784/4982] constify dentry_operations: 9p Signed-off-by: Al Viro --- fs/9p/v9fs_vfs.h | 4 ++-- fs/9p/vfs_dentry.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index c295ba786ed..f0c7de78e20 100644 --- a/fs/9p/v9fs_vfs.h +++ b/fs/9p/v9fs_vfs.h @@ -41,8 +41,8 @@ extern struct file_system_type v9fs_fs_type; extern const struct address_space_operations v9fs_addr_operations; extern const struct file_operations v9fs_file_operations; extern const struct file_operations v9fs_dir_operations; -extern struct dentry_operations v9fs_dentry_operations; -extern struct dentry_operations v9fs_cached_dentry_operations; +extern const struct dentry_operations v9fs_dentry_operations; +extern const struct dentry_operations v9fs_cached_dentry_operations; struct inode *v9fs_get_inode(struct super_block *sb, int mode); ino_t v9fs_qid2ino(struct p9_qid *qid); diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c index 06dcc7c4f23..d74325295b1 100644 --- a/fs/9p/vfs_dentry.c +++ b/fs/9p/vfs_dentry.c @@ -104,12 +104,12 @@ void v9fs_dentry_release(struct dentry *dentry) } } -struct dentry_operations v9fs_cached_dentry_operations = { +const struct dentry_operations v9fs_cached_dentry_operations = { .d_delete = v9fs_cached_dentry_delete, .d_release = v9fs_dentry_release, }; -struct dentry_operations v9fs_dentry_operations = { +const struct dentry_operations v9fs_dentry_operations = { .d_delete = v9fs_dentry_delete, .d_release = v9fs_dentry_release, }; -- GitLab From 08f11513fa6f712506edb99327f7d051da9d860f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 20 Feb 2009 05:56:19 +0000 Subject: [PATCH 4785/4982] constify dentry_operations: autofs, autofs4 Signed-off-by: Al Viro --- fs/autofs/root.c | 2 +- fs/autofs4/inode.c | 2 +- fs/autofs4/root.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/autofs/root.c b/fs/autofs/root.c index 8aacade5695..4a1401cea0a 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c @@ -192,7 +192,7 @@ static int autofs_revalidate(struct dentry * dentry, struct nameidata *nd) return 1; } -static struct dentry_operations autofs_dentry_operations = { +static const struct dentry_operations autofs_dentry_operations = { .d_revalidate = autofs_revalidate, }; diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 716e12b627b..69c8142da83 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -310,7 +310,7 @@ static struct autofs_info *autofs4_mkroot(struct autofs_sb_info *sbi) return ino; } -static struct dentry_operations autofs4_sb_dentry_operations = { +static const struct dentry_operations autofs4_sb_dentry_operations = { .d_release = autofs4_dentry_release, }; diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 2a41c2a7fc5..74b1469a950 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -349,13 +349,13 @@ void autofs4_dentry_release(struct dentry *de) } /* For dentries of directories in the root dir */ -static struct dentry_operations autofs4_root_dentry_operations = { +static const struct dentry_operations autofs4_root_dentry_operations = { .d_revalidate = autofs4_revalidate, .d_release = autofs4_dentry_release, }; /* For other dentries */ -static struct dentry_operations autofs4_dentry_operations = { +static const struct dentry_operations autofs4_dentry_operations = { .d_revalidate = autofs4_revalidate, .d_release = autofs4_dentry_release, }; -- GitLab From 79be57cc7fd25563c73ab26b0c28ff6ad0d618fc Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 20 Feb 2009 05:56:47 +0000 Subject: [PATCH 4786/4982] constify dentry_operations: AFS Signed-off-by: Al Viro --- fs/afs/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 99cf390641f..9bd757774c9 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c @@ -62,7 +62,7 @@ const struct inode_operations afs_dir_inode_operations = { .setattr = afs_setattr, }; -static struct dentry_operations afs_fs_dentry_operations = { +static const struct dentry_operations afs_fs_dentry_operations = { .d_revalidate = afs_d_revalidate, .d_delete = afs_d_delete, .d_release = afs_d_release, -- GitLab From 4fd03e84d8f4e6304cef19698a24dee84039ef01 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 20 Feb 2009 05:57:07 +0000 Subject: [PATCH 4787/4982] constify dentry_operations: CIFS Signed-off-by: Al Viro --- fs/cifs/cifsfs.h | 4 ++-- fs/cifs/dir.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 2b1d28a9ee2..77e190dc288 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -78,8 +78,8 @@ extern int cifs_dir_open(struct inode *inode, struct file *file); extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); /* Functions related to dir entries */ -extern struct dentry_operations cifs_dentry_ops; -extern struct dentry_operations cifs_ci_dentry_ops; +extern const struct dentry_operations cifs_dentry_ops; +extern const struct dentry_operations cifs_ci_dentry_ops; /* Functions related to symlinks */ extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd); diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 89fb7283265..43cc0fd2f8a 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -699,7 +699,7 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) return rc; } */ -struct dentry_operations cifs_dentry_ops = { +const struct dentry_operations cifs_dentry_ops = { .d_revalidate = cifs_d_revalidate, /* d_delete: cifs_d_delete, */ /* not needed except for debugging */ }; @@ -737,7 +737,7 @@ static int cifs_ci_compare(struct dentry *dentry, struct qstr *a, return 1; } -struct dentry_operations cifs_ci_dentry_ops = { +const struct dentry_operations cifs_ci_dentry_ops = { .d_revalidate = cifs_d_revalidate, .d_hash = cifs_ci_hash, .d_compare = cifs_ci_compare, -- GitLab From 5a3fd05a9bb2f104020fbfc4551ad4aaed4660a4 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 20 Feb 2009 05:57:52 +0000 Subject: [PATCH 4788/4982] constify dentry_operations: ecryptfs Signed-off-by: Al Viro --- fs/ecryptfs/dentry.c | 2 +- fs/ecryptfs/ecryptfs_kernel.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c index 5e596583946..2dda5ade75b 100644 --- a/fs/ecryptfs/dentry.c +++ b/fs/ecryptfs/dentry.c @@ -89,7 +89,7 @@ static void ecryptfs_d_release(struct dentry *dentry) return; } -struct dentry_operations ecryptfs_dops = { +const struct dentry_operations ecryptfs_dops = { .d_revalidate = ecryptfs_d_revalidate, .d_release = ecryptfs_d_release, }; diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index ac749d4d644..064c5820e4e 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -580,7 +580,7 @@ extern const struct inode_operations ecryptfs_main_iops; extern const struct inode_operations ecryptfs_dir_iops; extern const struct inode_operations ecryptfs_symlink_iops; extern const struct super_operations ecryptfs_sops; -extern struct dentry_operations ecryptfs_dops; +extern const struct dentry_operations ecryptfs_dops; extern struct address_space_operations ecryptfs_aops; extern int ecryptfs_verbosity; extern unsigned int ecryptfs_message_buf_len; -- GitLab From d72f71eb0edd629c95715aa7305b0259d3581e34 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 20 Feb 2009 05:58:47 +0000 Subject: [PATCH 4789/4982] constify dentry_operations: procfs Signed-off-by: Al Viro --- fs/proc/base.c | 6 +++--- fs/proc/generic.c | 2 +- fs/proc/proc_sysctl.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index beaa0ce3b82..aef6d55b7de 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1545,7 +1545,7 @@ static int pid_delete_dentry(struct dentry * dentry) return !proc_pid(dentry->d_inode)->tasks[PIDTYPE_PID].first; } -static struct dentry_operations pid_dentry_operations = +static const struct dentry_operations pid_dentry_operations = { .d_revalidate = pid_revalidate, .d_delete = pid_delete_dentry, @@ -1717,7 +1717,7 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) return 0; } -static struct dentry_operations tid_fd_dentry_operations = +static const struct dentry_operations tid_fd_dentry_operations = { .d_revalidate = tid_fd_revalidate, .d_delete = pid_delete_dentry, @@ -2339,7 +2339,7 @@ static int proc_base_revalidate(struct dentry *dentry, struct nameidata *nd) return 0; } -static struct dentry_operations proc_base_dentry_operations = +static const struct dentry_operations proc_base_dentry_operations = { .d_revalidate = proc_base_revalidate, .d_delete = pid_delete_dentry, diff --git a/fs/proc/generic.c b/fs/proc/generic.c index db7fa5cab98..5d2989e9dcc 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -363,7 +363,7 @@ static int proc_delete_dentry(struct dentry * dentry) return 1; } -static struct dentry_operations proc_dentry_operations = +static const struct dentry_operations proc_dentry_operations = { .d_delete = proc_delete_dentry, }; diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index 94fcfff6863..9b1e4e9a16b 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -7,7 +7,7 @@ #include #include "internal.h" -static struct dentry_operations proc_sys_dentry_operations; +static const struct dentry_operations proc_sys_dentry_operations; static const struct file_operations proc_sys_file_operations; static const struct inode_operations proc_sys_inode_operations; static const struct file_operations proc_sys_dir_file_operations; @@ -396,7 +396,7 @@ static int proc_sys_compare(struct dentry *dir, struct qstr *qstr, return !sysctl_is_seen(PROC_I(dentry->d_inode)->sysctl); } -static struct dentry_operations proc_sys_dentry_operations = { +static const struct dentry_operations proc_sys_dentry_operations = { .d_revalidate = proc_sys_revalidate, .d_delete = proc_sys_delete, .d_compare = proc_sys_compare, -- GitLab From 4269590a72934bb901b33b686e20605bf66653c4 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 20 Feb 2009 05:59:13 +0000 Subject: [PATCH 4790/4982] constify dentry_operations: FUSE Signed-off-by: Al Viro --- fs/fuse/dir.c | 2 +- fs/fuse/fuse_i.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index fdff346e96f..06da05261e0 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -224,7 +224,7 @@ static int invalid_nodeid(u64 nodeid) return !nodeid || nodeid == FUSE_ROOT_ID; } -struct dentry_operations fuse_dentry_operations = { +const struct dentry_operations fuse_dentry_operations = { .d_revalidate = fuse_dentry_revalidate, }; diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 5e64b815a5a..6fc5aedaa0d 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -493,7 +493,7 @@ static inline u64 get_node_id(struct inode *inode) /** Device operations */ extern const struct file_operations fuse_dev_operations; -extern struct dentry_operations fuse_dentry_operations; +extern const struct dentry_operations fuse_dentry_operations; /** * Get a filled in inode -- GitLab From ce6cdc474aa5bf4c1a7dc698d83bb0622846a81d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 20 Feb 2009 05:59:46 +0000 Subject: [PATCH 4791/4982] constify dentry_operations: FAT Signed-off-by: Al Viro --- fs/fat/namei_msdos.c | 2 +- fs/fat/namei_vfat.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c index 7ba03a4acbe..da3f361a37d 100644 --- a/fs/fat/namei_msdos.c +++ b/fs/fat/namei_msdos.c @@ -188,7 +188,7 @@ old_compare: goto out; } -static struct dentry_operations msdos_dentry_operations = { +static const struct dentry_operations msdos_dentry_operations = { .d_hash = msdos_hash, .d_compare = msdos_cmp, }; diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index 8ae32e37673..a0e00e3a46e 100644 --- a/fs/fat/namei_vfat.c +++ b/fs/fat/namei_vfat.c @@ -166,13 +166,13 @@ static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b) return 1; } -static struct dentry_operations vfat_ci_dentry_ops = { +static const struct dentry_operations vfat_ci_dentry_ops = { .d_revalidate = vfat_revalidate_ci, .d_hash = vfat_hashi, .d_compare = vfat_cmpi, }; -static struct dentry_operations vfat_dentry_ops = { +static const struct dentry_operations vfat_dentry_ops = { .d_revalidate = vfat_revalidate, .d_hash = vfat_hash, .d_compare = vfat_cmp, -- GitLab From 92cecbbfa3785a944c733a284b77faee5b82b70c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 20 Feb 2009 06:00:05 +0000 Subject: [PATCH 4792/4982] constify dentry_operations: GFS2 Signed-off-by: Al Viro --- fs/gfs2/ops_dentry.c | 2 +- fs/gfs2/super.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/gfs2/ops_dentry.c b/fs/gfs2/ops_dentry.c index c2ad36330ca..aea4d50580d 100644 --- a/fs/gfs2/ops_dentry.c +++ b/fs/gfs2/ops_dentry.c @@ -108,7 +108,7 @@ static int gfs2_dhash(struct dentry *dentry, struct qstr *str) return 0; } -struct dentry_operations gfs2_dops = { +const struct dentry_operations gfs2_dops = { .d_revalidate = gfs2_drevalidate, .d_hash = gfs2_dhash, }; diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h index f6b8b00ad88..a931e44ab56 100644 --- a/fs/gfs2/super.h +++ b/fs/gfs2/super.h @@ -47,7 +47,7 @@ extern struct file_system_type gfs2_fs_type; extern struct file_system_type gfs2meta_fs_type; extern const struct export_operations gfs2_export_ops; extern const struct super_operations gfs2_super_ops; -extern struct dentry_operations gfs2_dops; +extern const struct dentry_operations gfs2_dops; #endif /* __SUPER_DOT_H__ */ -- GitLab From d8fba0ffe5e7442fc2560873ec901be6e56602a1 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 20 Feb 2009 06:00:26 +0000 Subject: [PATCH 4793/4982] constify dentry_operations: OCFS2 Signed-off-by: Al Viro --- fs/ocfs2/dcache.c | 2 +- fs/ocfs2/dcache.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index e9d7c2038c0..7d604480557 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c @@ -455,7 +455,7 @@ out_move: d_move(dentry, target); } -struct dentry_operations ocfs2_dentry_ops = { +const struct dentry_operations ocfs2_dentry_ops = { .d_revalidate = ocfs2_dentry_revalidate, .d_iput = ocfs2_dentry_iput, }; diff --git a/fs/ocfs2/dcache.h b/fs/ocfs2/dcache.h index d06e16c0664..faa12e75f98 100644 --- a/fs/ocfs2/dcache.h +++ b/fs/ocfs2/dcache.h @@ -26,7 +26,7 @@ #ifndef OCFS2_DCACHE_H #define OCFS2_DCACHE_H -extern struct dentry_operations ocfs2_dentry_ops; +extern const struct dentry_operations ocfs2_dentry_ops; struct ocfs2_dentry_lock { /* Use count of dentry lock */ -- GitLab From ad28b4ef1937b11432cd64fe1ebad714f8e253bd Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 20 Feb 2009 06:00:49 +0000 Subject: [PATCH 4794/4982] constify dentry_operations: JFS Signed-off-by: Al Viro --- fs/jfs/jfs_inode.h | 2 +- fs/jfs/namei.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h index adb2fafcc54..1eff7db34d6 100644 --- a/fs/jfs/jfs_inode.h +++ b/fs/jfs/jfs_inode.h @@ -47,5 +47,5 @@ extern const struct file_operations jfs_dir_operations; extern const struct inode_operations jfs_file_inode_operations; extern const struct file_operations jfs_file_operations; extern const struct inode_operations jfs_symlink_inode_operations; -extern struct dentry_operations jfs_ci_dentry_operations; +extern const struct dentry_operations jfs_ci_dentry_operations; #endif /* _H_JFS_INODE */ diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index b4de56b851e..5f80aef219d 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -35,7 +35,7 @@ /* * forward references */ -struct dentry_operations jfs_ci_dentry_operations; +const struct dentry_operations jfs_ci_dentry_operations; static s64 commitZeroLink(tid_t, struct inode *); @@ -1595,7 +1595,7 @@ out: return result; } -struct dentry_operations jfs_ci_dentry_operations = +const struct dentry_operations jfs_ci_dentry_operations = { .d_hash = jfs_ci_hash, .d_compare = jfs_ci_compare, -- GitLab From ee1ec32903fc3139af00ebc7ee483dabca3f4fa5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 20 Feb 2009 06:01:46 +0000 Subject: [PATCH 4795/4982] constify dentry_operations: sysfs Signed-off-by: Al Viro --- fs/sysfs/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 82d3b79d0e0..6b8fe71ba14 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -302,7 +302,7 @@ static void sysfs_d_iput(struct dentry * dentry, struct inode * inode) iput(inode); } -static struct dentry_operations sysfs_dentry_ops = { +static const struct dentry_operations sysfs_dentry_ops = { .d_iput = sysfs_d_iput, }; -- GitLab From 296c2d86635bd6ecd8f282dfff18bb68fb4fc512 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 20 Feb 2009 06:02:01 +0000 Subject: [PATCH 4796/4982] constify dentry_operations: configfs Signed-off-by: Al Viro --- fs/configfs/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 8e93341f3e8..05373db21a4 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -72,7 +72,7 @@ static int configfs_d_delete(struct dentry *dentry) return 1; } -static struct dentry_operations configfs_dentry_ops = { +static const struct dentry_operations configfs_dentry_ops = { .d_iput = configfs_d_iput, /* simple_delete_dentry() isn't exported */ .d_delete = configfs_d_delete, -- GitLab From 3ba13d179e8c24c68eac32b93593a6b10fcd1572 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 20 Feb 2009 06:02:22 +0000 Subject: [PATCH 4797/4982] constify dentry_operations: rest Signed-off-by: Al Viro --- arch/ia64/kernel/perfmon.c | 2 +- fs/anon_inodes.c | 2 +- fs/libfs.c | 2 +- fs/pipe.c | 2 +- kernel/cgroup.c | 2 +- net/socket.c | 2 +- net/sunrpc/rpc_pipe.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 0e499757309..5c0f408cfd7 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -2196,7 +2196,7 @@ pfmfs_delete_dentry(struct dentry *dentry) return 1; } -static struct dentry_operations pfmfs_dentry_operations = { +static const struct dentry_operations pfmfs_dentry_operations = { .d_delete = pfmfs_delete_dentry, }; diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c index 3bbdb9d0237..1dd96d4406c 100644 --- a/fs/anon_inodes.c +++ b/fs/anon_inodes.c @@ -48,7 +48,7 @@ static struct file_system_type anon_inode_fs_type = { .get_sb = anon_inodefs_get_sb, .kill_sb = kill_anon_super, }; -static struct dentry_operations anon_inodefs_dentry_operations = { +static const struct dentry_operations anon_inodefs_dentry_operations = { .d_delete = anon_inodefs_delete_dentry, }; diff --git a/fs/libfs.c b/fs/libfs.c index 49b44099dab..ec600bd33e7 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -44,7 +44,7 @@ static int simple_delete_dentry(struct dentry *dentry) */ struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { - static struct dentry_operations simple_dentry_operations = { + static const struct dentry_operations simple_dentry_operations = { .d_delete = simple_delete_dentry, }; diff --git a/fs/pipe.c b/fs/pipe.c index df3719562fc..6ddf05209a4 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -870,7 +870,7 @@ static char *pipefs_dname(struct dentry *dentry, char *buffer, int buflen) dentry->d_inode->i_ino); } -static struct dentry_operations pipefs_dentry_operations = { +static const struct dentry_operations pipefs_dentry_operations = { .d_delete = pipefs_delete_dentry, .d_dname = pipefs_dname, }; diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 9edb5c4b79b..b01100ebd07 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -1627,7 +1627,7 @@ static struct inode_operations cgroup_dir_inode_operations = { static int cgroup_create_file(struct dentry *dentry, int mode, struct super_block *sb) { - static struct dentry_operations cgroup_dops = { + static const struct dentry_operations cgroup_dops = { .d_iput = cgroup_diput, }; diff --git a/net/socket.c b/net/socket.c index 35dd7371752..2f895f60ca8 100644 --- a/net/socket.c +++ b/net/socket.c @@ -328,7 +328,7 @@ static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen) dentry->d_inode->i_ino); } -static struct dentry_operations sockfs_dentry_operations = { +static const struct dentry_operations sockfs_dentry_operations = { .d_delete = sockfs_delete_dentry, .d_dname = sockfs_dname, }; diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 577385a4a5d..9ced0628d69 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -480,7 +480,7 @@ static int rpc_delete_dentry(struct dentry *dentry) return 1; } -static struct dentry_operations rpc_dentry_operations = { +static const struct dentry_operations rpc_dentry_operations = { .d_delete = rpc_delete_dentry, }; -- GitLab From 585d3bc06f4ca57f975a5a1f698f65a45ea66225 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 25 Feb 2009 10:44:19 +0100 Subject: [PATCH 4798/4982] fs: move bdev code out of buffer.c Move some block device related code out from buffer.c and put it in block_dev.c. I'm trying to move non-buffer_head code out of buffer.c Signed-off-by: Al Viro --- fs/block_dev.c | 146 ++++++++++++++++++++++++++++++++++++ fs/buffer.c | 145 ----------------------------------- include/linux/buffer_head.h | 7 -- include/linux/fs.h | 7 ++ 4 files changed, 153 insertions(+), 152 deletions(-) diff --git a/fs/block_dev.c b/fs/block_dev.c index b3c1efff5e1..8c3c6899ccf 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -174,6 +175,151 @@ blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, iov, offset, nr_segs, blkdev_get_blocks, NULL); } +/* + * Write out and wait upon all the dirty data associated with a block + * device via its mapping. Does not take the superblock lock. + */ +int sync_blockdev(struct block_device *bdev) +{ + int ret = 0; + + if (bdev) + ret = filemap_write_and_wait(bdev->bd_inode->i_mapping); + return ret; +} +EXPORT_SYMBOL(sync_blockdev); + +/* + * Write out and wait upon all dirty data associated with this + * device. Filesystem data as well as the underlying block + * device. Takes the superblock lock. + */ +int fsync_bdev(struct block_device *bdev) +{ + struct super_block *sb = get_super(bdev); + if (sb) { + int res = fsync_super(sb); + drop_super(sb); + return res; + } + return sync_blockdev(bdev); +} + +/** + * freeze_bdev -- lock a filesystem and force it into a consistent state + * @bdev: blockdevice to lock + * + * This takes the block device bd_mount_sem to make sure no new mounts + * happen on bdev until thaw_bdev() is called. + * If a superblock is found on this device, we take the s_umount semaphore + * on it to make sure nobody unmounts until the snapshot creation is done. + * The reference counter (bd_fsfreeze_count) guarantees that only the last + * unfreeze process can unfreeze the frozen filesystem actually when multiple + * freeze requests arrive simultaneously. It counts up in freeze_bdev() and + * count down in thaw_bdev(). When it becomes 0, thaw_bdev() will unfreeze + * actually. + */ +struct super_block *freeze_bdev(struct block_device *bdev) +{ + struct super_block *sb; + int error = 0; + + mutex_lock(&bdev->bd_fsfreeze_mutex); + if (bdev->bd_fsfreeze_count > 0) { + bdev->bd_fsfreeze_count++; + sb = get_super(bdev); + mutex_unlock(&bdev->bd_fsfreeze_mutex); + return sb; + } + bdev->bd_fsfreeze_count++; + + down(&bdev->bd_mount_sem); + sb = get_super(bdev); + if (sb && !(sb->s_flags & MS_RDONLY)) { + sb->s_frozen = SB_FREEZE_WRITE; + smp_wmb(); + + __fsync_super(sb); + + sb->s_frozen = SB_FREEZE_TRANS; + smp_wmb(); + + sync_blockdev(sb->s_bdev); + + if (sb->s_op->freeze_fs) { + error = sb->s_op->freeze_fs(sb); + if (error) { + printk(KERN_ERR + "VFS:Filesystem freeze failed\n"); + sb->s_frozen = SB_UNFROZEN; + drop_super(sb); + up(&bdev->bd_mount_sem); + bdev->bd_fsfreeze_count--; + mutex_unlock(&bdev->bd_fsfreeze_mutex); + return ERR_PTR(error); + } + } + } + + sync_blockdev(bdev); + mutex_unlock(&bdev->bd_fsfreeze_mutex); + + return sb; /* thaw_bdev releases s->s_umount and bd_mount_sem */ +} +EXPORT_SYMBOL(freeze_bdev); + +/** + * thaw_bdev -- unlock filesystem + * @bdev: blockdevice to unlock + * @sb: associated superblock + * + * Unlocks the filesystem and marks it writeable again after freeze_bdev(). + */ +int thaw_bdev(struct block_device *bdev, struct super_block *sb) +{ + int error = 0; + + mutex_lock(&bdev->bd_fsfreeze_mutex); + if (!bdev->bd_fsfreeze_count) { + mutex_unlock(&bdev->bd_fsfreeze_mutex); + return -EINVAL; + } + + bdev->bd_fsfreeze_count--; + if (bdev->bd_fsfreeze_count > 0) { + if (sb) + drop_super(sb); + mutex_unlock(&bdev->bd_fsfreeze_mutex); + return 0; + } + + if (sb) { + BUG_ON(sb->s_bdev != bdev); + if (!(sb->s_flags & MS_RDONLY)) { + if (sb->s_op->unfreeze_fs) { + error = sb->s_op->unfreeze_fs(sb); + if (error) { + printk(KERN_ERR + "VFS:Filesystem thaw failed\n"); + sb->s_frozen = SB_FREEZE_TRANS; + bdev->bd_fsfreeze_count++; + mutex_unlock(&bdev->bd_fsfreeze_mutex); + return error; + } + } + sb->s_frozen = SB_UNFROZEN; + smp_wmb(); + wake_up(&sb->s_wait_unfrozen); + } + drop_super(sb); + } + + up(&bdev->bd_mount_sem); + mutex_unlock(&bdev->bd_fsfreeze_mutex); + return 0; +} +EXPORT_SYMBOL(thaw_bdev); + static int blkdev_writepage(struct page *page, struct writeback_control *wbc) { return block_write_full_page(page, blkdev_get_block, wbc); diff --git a/fs/buffer.c b/fs/buffer.c index 891e1c78e4f..a2fd743d97c 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -165,151 +165,6 @@ void end_buffer_write_sync(struct buffer_head *bh, int uptodate) put_bh(bh); } -/* - * Write out and wait upon all the dirty data associated with a block - * device via its mapping. Does not take the superblock lock. - */ -int sync_blockdev(struct block_device *bdev) -{ - int ret = 0; - - if (bdev) - ret = filemap_write_and_wait(bdev->bd_inode->i_mapping); - return ret; -} -EXPORT_SYMBOL(sync_blockdev); - -/* - * Write out and wait upon all dirty data associated with this - * device. Filesystem data as well as the underlying block - * device. Takes the superblock lock. - */ -int fsync_bdev(struct block_device *bdev) -{ - struct super_block *sb = get_super(bdev); - if (sb) { - int res = fsync_super(sb); - drop_super(sb); - return res; - } - return sync_blockdev(bdev); -} - -/** - * freeze_bdev -- lock a filesystem and force it into a consistent state - * @bdev: blockdevice to lock - * - * This takes the block device bd_mount_sem to make sure no new mounts - * happen on bdev until thaw_bdev() is called. - * If a superblock is found on this device, we take the s_umount semaphore - * on it to make sure nobody unmounts until the snapshot creation is done. - * The reference counter (bd_fsfreeze_count) guarantees that only the last - * unfreeze process can unfreeze the frozen filesystem actually when multiple - * freeze requests arrive simultaneously. It counts up in freeze_bdev() and - * count down in thaw_bdev(). When it becomes 0, thaw_bdev() will unfreeze - * actually. - */ -struct super_block *freeze_bdev(struct block_device *bdev) -{ - struct super_block *sb; - int error = 0; - - mutex_lock(&bdev->bd_fsfreeze_mutex); - if (bdev->bd_fsfreeze_count > 0) { - bdev->bd_fsfreeze_count++; - sb = get_super(bdev); - mutex_unlock(&bdev->bd_fsfreeze_mutex); - return sb; - } - bdev->bd_fsfreeze_count++; - - down(&bdev->bd_mount_sem); - sb = get_super(bdev); - if (sb && !(sb->s_flags & MS_RDONLY)) { - sb->s_frozen = SB_FREEZE_WRITE; - smp_wmb(); - - __fsync_super(sb); - - sb->s_frozen = SB_FREEZE_TRANS; - smp_wmb(); - - sync_blockdev(sb->s_bdev); - - if (sb->s_op->freeze_fs) { - error = sb->s_op->freeze_fs(sb); - if (error) { - printk(KERN_ERR - "VFS:Filesystem freeze failed\n"); - sb->s_frozen = SB_UNFROZEN; - drop_super(sb); - up(&bdev->bd_mount_sem); - bdev->bd_fsfreeze_count--; - mutex_unlock(&bdev->bd_fsfreeze_mutex); - return ERR_PTR(error); - } - } - } - - sync_blockdev(bdev); - mutex_unlock(&bdev->bd_fsfreeze_mutex); - - return sb; /* thaw_bdev releases s->s_umount and bd_mount_sem */ -} -EXPORT_SYMBOL(freeze_bdev); - -/** - * thaw_bdev -- unlock filesystem - * @bdev: blockdevice to unlock - * @sb: associated superblock - * - * Unlocks the filesystem and marks it writeable again after freeze_bdev(). - */ -int thaw_bdev(struct block_device *bdev, struct super_block *sb) -{ - int error = 0; - - mutex_lock(&bdev->bd_fsfreeze_mutex); - if (!bdev->bd_fsfreeze_count) { - mutex_unlock(&bdev->bd_fsfreeze_mutex); - return -EINVAL; - } - - bdev->bd_fsfreeze_count--; - if (bdev->bd_fsfreeze_count > 0) { - if (sb) - drop_super(sb); - mutex_unlock(&bdev->bd_fsfreeze_mutex); - return 0; - } - - if (sb) { - BUG_ON(sb->s_bdev != bdev); - if (!(sb->s_flags & MS_RDONLY)) { - if (sb->s_op->unfreeze_fs) { - error = sb->s_op->unfreeze_fs(sb); - if (error) { - printk(KERN_ERR - "VFS:Filesystem thaw failed\n"); - sb->s_frozen = SB_FREEZE_TRANS; - bdev->bd_fsfreeze_count++; - mutex_unlock(&bdev->bd_fsfreeze_mutex); - return error; - } - } - sb->s_frozen = SB_UNFROZEN; - smp_wmb(); - wake_up(&sb->s_wait_unfrozen); - } - drop_super(sb); - } - - up(&bdev->bd_mount_sem); - mutex_unlock(&bdev->bd_fsfreeze_mutex); - return 0; -} -EXPORT_SYMBOL(thaw_bdev); - /* * Various filesystems appear to want __find_get_block to be non-blocking. * But it's the page lock which protects the buffers. To get around this, diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index bd7ac793be1..f19fd9045ea 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -165,15 +165,8 @@ int sync_mapping_buffers(struct address_space *mapping); void unmap_underlying_metadata(struct block_device *bdev, sector_t block); void mark_buffer_async_write(struct buffer_head *bh); -void invalidate_bdev(struct block_device *); -int sync_blockdev(struct block_device *bdev); void __wait_on_buffer(struct buffer_head *); wait_queue_head_t *bh_waitq_head(struct buffer_head *bh); -int fsync_bdev(struct block_device *); -struct super_block *freeze_bdev(struct block_device *); -int thaw_bdev(struct block_device *, struct super_block *); -int fsync_super(struct super_block *); -int fsync_no_super(struct block_device *); struct buffer_head *__find_get_block(struct block_device *bdev, sector_t block, unsigned size); struct buffer_head *__getblk(struct block_device *bdev, sector_t block, diff --git a/include/linux/fs.h b/include/linux/fs.h index 5f74d616cd7..c2c4454a268 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1874,6 +1874,13 @@ extern void bd_set_size(struct block_device *, loff_t size); extern void bd_forget(struct inode *inode); extern void bdput(struct block_device *); extern struct block_device *open_by_devnum(dev_t, fmode_t); +extern void invalidate_bdev(struct block_device *); +extern int sync_blockdev(struct block_device *bdev); +extern struct super_block *freeze_bdev(struct block_device *); +extern int thaw_bdev(struct block_device *bdev, struct super_block *sb); +extern int fsync_bdev(struct block_device *); +extern int fsync_super(struct super_block *); +extern int fsync_no_super(struct block_device *); #else static inline void bd_forget(struct inode *inode) {} #endif -- GitLab From a3ec947c85ec339884b30ef6a08133e9311fdae1 Mon Sep 17 00:00:00 2001 From: Sukadev Bhattiprolu Date: Wed, 4 Mar 2009 12:06:34 -0800 Subject: [PATCH 4799/4982] vfs: simple_set_mnt() should return void simple_set_mnt() is defined as returning 'int' but always returns 0. Callers assume simple_set_mnt() never fails and don't properly cleanup if it were to _ever_ fail. For instance, get_sb_single() and get_sb_nodev() should: up_write(sb->s_unmount); deactivate_super(sb); if simple_set_mnt() fails. Since simple_set_mnt() never fails, would be cleaner if it did not return anything. [akpm@linux-foundation.org: fix build] Signed-off-by: Sukadev Bhattiprolu Acked-by: Serge Hallyn Cc: Al Viro Cc: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Al Viro --- drivers/mtd/mtdsuper.c | 7 +++++-- fs/9p/vfs_super.c | 5 +++-- fs/cifs/cifsfs.c | 3 ++- fs/devpts/inode.c | 3 ++- fs/libfs.c | 3 ++- fs/namespace.c | 3 +-- fs/proc/root.c | 3 ++- fs/super.c | 9 ++++++--- fs/ubifs/super.c | 3 ++- include/linux/fs.h | 2 +- kernel/cgroup.c | 3 ++- 11 files changed, 28 insertions(+), 16 deletions(-) diff --git a/drivers/mtd/mtdsuper.c b/drivers/mtd/mtdsuper.c index 00d46e137b2..92285d0089c 100644 --- a/drivers/mtd/mtdsuper.c +++ b/drivers/mtd/mtdsuper.c @@ -81,13 +81,16 @@ static int get_sb_mtd_aux(struct file_system_type *fs_type, int flags, /* go */ sb->s_flags |= MS_ACTIVE; - return simple_set_mnt(mnt, sb); + simple_set_mnt(mnt, sb); + + return 0; /* new mountpoint for an already mounted superblock */ already_mounted: DEBUG(1, "MTDSB: Device %d (\"%s\") is already mounted\n", mtd->index, mtd->name); - ret = simple_set_mnt(mnt, sb); + simple_set_mnt(mnt, sb); + ret = 0; goto out_put; out_error: diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 93212e40221..5f8ab8adb5f 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -168,8 +168,9 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, p9stat_free(st); kfree(st); -P9_DPRINTK(P9_DEBUG_VFS, " return simple set mount\n"); - return simple_set_mnt(mnt, sb); +P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n"); + simple_set_mnt(mnt, sb); + return 0; release_sb: if (sb) { diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 13ea53251dc..38491fd3871 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -606,7 +606,8 @@ cifs_get_sb(struct file_system_type *fs_type, return rc; } sb->s_flags |= MS_ACTIVE; - return simple_set_mnt(mnt, sb); + simple_set_mnt(mnt, sb); + return 0; } static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 140b43144cd..b0a76340a4c 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -454,7 +454,8 @@ static int get_init_pts_sb(struct file_system_type *fs_type, int flags, s->s_flags |= MS_ACTIVE; } do_remount_sb(s, flags, data, 0); - return simple_set_mnt(mnt, s); + simple_set_mnt(mnt, s); + return 0; } /* diff --git a/fs/libfs.c b/fs/libfs.c index ec600bd33e7..4910a36f516 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -242,7 +242,8 @@ int get_sb_pseudo(struct file_system_type *fs_type, char *name, d_instantiate(dentry, root); s->s_root = dentry; s->s_flags |= MS_ACTIVE; - return simple_set_mnt(mnt, s); + simple_set_mnt(mnt, s); + return 0; Enomem: up_write(&s->s_umount); diff --git a/fs/namespace.c b/fs/namespace.c index 06f8e63f6cb..2432ca6bb22 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -397,11 +397,10 @@ static void __mnt_unmake_readonly(struct vfsmount *mnt) spin_unlock(&vfsmount_lock); } -int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb) +void simple_set_mnt(struct vfsmount *mnt, struct super_block *sb) { mnt->mnt_sb = sb; mnt->mnt_root = dget(sb->s_root); - return 0; } EXPORT_SYMBOL(simple_set_mnt); diff --git a/fs/proc/root.c b/fs/proc/root.c index f6299a25594..1e15a2b176e 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -83,7 +83,8 @@ static int proc_get_sb(struct file_system_type *fs_type, ns->proc_mnt = mnt; } - return simple_set_mnt(mnt, sb); + simple_set_mnt(mnt, sb); + return 0; } static void proc_kill_sb(struct super_block *sb) diff --git a/fs/super.c b/fs/super.c index 6ce501447ad..e512fab64c9 100644 --- a/fs/super.c +++ b/fs/super.c @@ -831,7 +831,8 @@ int get_sb_bdev(struct file_system_type *fs_type, bdev->bd_super = s; } - return simple_set_mnt(mnt, s); + simple_set_mnt(mnt, s); + return 0; error_s: error = PTR_ERR(s); @@ -877,7 +878,8 @@ int get_sb_nodev(struct file_system_type *fs_type, return error; } s->s_flags |= MS_ACTIVE; - return simple_set_mnt(mnt, s); + simple_set_mnt(mnt, s); + return 0; } EXPORT_SYMBOL(get_sb_nodev); @@ -909,7 +911,8 @@ int get_sb_single(struct file_system_type *fs_type, s->s_flags |= MS_ACTIVE; } do_remount_sb(s, flags, data, 0); - return simple_set_mnt(mnt, s); + simple_set_mnt(mnt, s); + return 0; } EXPORT_SYMBOL(get_sb_single); diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 1182b66a549..c5c98355459 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -2034,7 +2034,8 @@ static int ubifs_get_sb(struct file_system_type *fs_type, int flags, /* 'fill_super()' opens ubi again so we must close it here */ ubi_close_volume(ubi); - return simple_set_mnt(mnt, sb); + simple_set_mnt(mnt, sb); + return 0; out_deact: up_write(&sb->s_umount); diff --git a/include/linux/fs.h b/include/linux/fs.h index c2c4454a268..a7d73914a9f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1719,7 +1719,7 @@ struct super_block *sget(struct file_system_type *type, extern int get_sb_pseudo(struct file_system_type *, char *, const struct super_operations *ops, unsigned long, struct vfsmount *mnt); -extern int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb); +extern void simple_set_mnt(struct vfsmount *mnt, struct super_block *sb); int __put_super_and_need_restart(struct super_block *sb); /* Alas, no aliases. Too much hassle with bringing module.h everywhere */ diff --git a/kernel/cgroup.c b/kernel/cgroup.c index b01100ebd07..c500ca7239b 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -1071,7 +1071,8 @@ static int cgroup_get_sb(struct file_system_type *fs_type, mutex_unlock(&cgroup_mutex); } - return simple_set_mnt(mnt, sb); + simple_set_mnt(mnt, sb); + return 0; free_cg_links: free_cg_links(&tmp_cg_links); -- GitLab From fdbf5348661ac9d519164d1489f30cc0384fda58 Mon Sep 17 00:00:00 2001 From: Sukadev Bhattiprolu Date: Sat, 7 Mar 2009 10:16:20 -0800 Subject: [PATCH 4800/4982] Unroll essentials of do_remount_sb() into devpts On remount, devpts fs only needs to parse the mount options. Users cannot directly create/dirty files in /dev/pts so the MS_RDONLY flag and shrinking the dcache does not really apply to devpts. So effectively on remount, devpts only parses the mount options and updates these options in its super block. As such, we could replace do_remount_sb() call with a direct parse_mount_options(). Doing so enables subsequent patches to avoid parsing the mount options twice and simplify the code. Signed-off-by: Sukadev Bhattiprolu Acked-by: Serge Hallyn Signed-off-by: Al Viro --- fs/devpts/inode.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index b0a76340a4c..fb4da9d8913 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -437,6 +437,8 @@ static int get_init_pts_sb(struct file_system_type *fs_type, int flags, void *data, struct vfsmount *mnt) { struct super_block *s; + struct pts_mount_opts *opts; + struct pts_fs_info *fsi; int error; s = sget(fs_type, compare_init_pts_sb, set_anon_super, NULL); @@ -453,7 +455,10 @@ static int get_init_pts_sb(struct file_system_type *fs_type, int flags, } s->s_flags |= MS_ACTIVE; } - do_remount_sb(s, flags, data, 0); + fsi = DEVPTS_SB(s); + opts = &fsi->mount_opts; + parse_mount_options(data, PARSE_REMOUNT, opts); + simple_set_mnt(mnt, s); return 0; } -- GitLab From 482984f06df54d886995a4383d2f5bb85e3de945 Mon Sep 17 00:00:00 2001 From: Sukadev Bhattiprolu Date: Sat, 7 Mar 2009 10:14:41 -0800 Subject: [PATCH 4801/4982] Parse mount options just once and copy them to super block Since all the mount option parsing is done in devpts, we could do it just once and pass it around in devpts functions and eventually store it in the super block. Signed-off-by: Sukadev Bhattiprolu Signed-off-by: Al Viro --- fs/devpts/inode.c | 100 ++++++++++------------------------------------ 1 file changed, 22 insertions(+), 78 deletions(-) diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index fb4da9d8913..70013dd8ec7 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -321,61 +321,22 @@ static int compare_init_pts_sb(struct super_block *s, void *p) return 0; } -/* - * Safely parse the mount options in @data and update @opts. - * - * devpts ends up parsing options two times during mount, due to the - * two modes of operation it supports. The first parse occurs in - * devpts_get_sb() when determining the mode (single-instance or - * multi-instance mode). The second parse happens in devpts_remount() - * or new_pts_mount() depending on the mode. - * - * Parsing of options modifies the @data making subsequent parsing - * incorrect. So make a local copy of @data and parse it. - * - * Return: 0 On success, -errno on error - */ -static int safe_parse_mount_options(void *data, struct pts_mount_opts *opts) -{ - int rc; - void *datacp; - - if (!data) - return 0; - - /* Use kstrdup() ? */ - datacp = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!datacp) - return -ENOMEM; - - memcpy(datacp, data, PAGE_SIZE); - rc = parse_mount_options((char *)datacp, PARSE_MOUNT, opts); - kfree(datacp); - - return rc; -} - /* * Mount a new (private) instance of devpts. PTYs created in this * instance are independent of the PTYs in other devpts instances. */ static int new_pts_mount(struct file_system_type *fs_type, int flags, - void *data, struct vfsmount *mnt) + void *data, struct pts_mount_opts *opts, struct vfsmount *mnt) { int err; struct pts_fs_info *fsi; - struct pts_mount_opts *opts; err = get_sb_nodev(fs_type, flags, data, devpts_fill_super, mnt); if (err) return err; fsi = DEVPTS_SB(mnt->mnt_sb); - opts = &fsi->mount_opts; - - err = parse_mount_options(data, PARSE_MOUNT, opts); - if (err) - goto fail; + memcpy(&fsi->mount_opts, opts, sizeof(opts)); err = mknod_ptmx(mnt->mnt_sb); if (err) @@ -390,28 +351,6 @@ fail: return err; } -/* - * Check if 'newinstance' mount option was specified in @data. - * - * Return: -errno on error (eg: invalid mount options specified) - * : 1 if 'newinstance' mount option was specified - * : 0 if 'newinstance' mount option was NOT specified - */ -static int is_new_instance_mount(void *data) -{ - int rc; - struct pts_mount_opts opts; - - if (!data) - return 0; - - rc = safe_parse_mount_options(data, &opts); - if (!rc) - rc = opts.newinstance; - - return rc; -} - /* * get_init_pts_sb() * @@ -434,10 +373,9 @@ static int is_new_instance_mount(void *data) * presence of the private namespace (i.e 'newinstance') super-blocks. */ static int get_init_pts_sb(struct file_system_type *fs_type, int flags, - void *data, struct vfsmount *mnt) + void *data, struct pts_mount_opts *opts, struct vfsmount *mnt) { struct super_block *s; - struct pts_mount_opts *opts; struct pts_fs_info *fsi; int error; @@ -455,11 +393,12 @@ static int get_init_pts_sb(struct file_system_type *fs_type, int flags, } s->s_flags |= MS_ACTIVE; } - fsi = DEVPTS_SB(s); - opts = &fsi->mount_opts; - parse_mount_options(data, PARSE_REMOUNT, opts); simple_set_mnt(mnt, s); + + fsi = DEVPTS_SB(mnt->mnt_sb); + memcpy(&fsi->mount_opts, opts, sizeof(opts)); + return 0; } @@ -469,11 +408,11 @@ static int get_init_pts_sb(struct file_system_type *fs_type, int flags, * kernel still allows multiple-instances. */ static int init_pts_mount(struct file_system_type *fs_type, int flags, - void *data, struct vfsmount *mnt) + void *data, struct pts_mount_opts *opts, struct vfsmount *mnt) { int err; - err = get_init_pts_sb(fs_type, flags, data, mnt); + err = get_init_pts_sb(fs_type, flags, data, opts, mnt); if (err) return err; @@ -490,17 +429,22 @@ static int init_pts_mount(struct file_system_type *fs_type, int flags, static int devpts_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - int new; - - new = is_new_instance_mount(data); - if (new < 0) - return new; + int error; + struct pts_mount_opts opts; - if (new) - return new_pts_mount(fs_type, flags, data, mnt); + memset(&opts, 0, sizeof(opts)); + if (data) { + error = parse_mount_options(data, PARSE_MOUNT, &opts); + if (error) + return error; + } - return init_pts_mount(fs_type, flags, data, mnt); + if (opts.newinstance) + return new_pts_mount(fs_type, flags, data, &opts, mnt); + else + return init_pts_mount(fs_type, flags, data, &opts, mnt); } + #else /* * This supports only the legacy single-instance semantics (no -- GitLab From 945cf2c79f6fbb1b74e3b0ca08f48b6af56ad412 Mon Sep 17 00:00:00 2001 From: Sukadev Bhattiprolu Date: Sat, 7 Mar 2009 10:11:41 -0800 Subject: [PATCH 4802/4982] Move common mknod_ptmx() calls into caller We create 'ptmx' node in both single-instance and multiple-instance mounts. So devpts_get_sb() can call mknod_ptmx() once rather than have both modes calling mknod_ptmx() separately. Signed-off-by: Sukadev Bhattiprolu Acked-by: Serge Hallyn Signed-off-by: Al Viro --- fs/devpts/inode.c | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 70013dd8ec7..58b719006af 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -338,17 +338,7 @@ static int new_pts_mount(struct file_system_type *fs_type, int flags, fsi = DEVPTS_SB(mnt->mnt_sb); memcpy(&fsi->mount_opts, opts, sizeof(opts)); - err = mknod_ptmx(mnt->mnt_sb); - if (err) - goto fail; - return 0; - -fail: - dput(mnt->mnt_sb->s_root); - up_write(&mnt->mnt_sb->s_umount); - deactivate_super(mnt->mnt_sb); - return err; } /* @@ -416,13 +406,6 @@ static int init_pts_mount(struct file_system_type *fs_type, int flags, if (err) return err; - err = mknod_ptmx(mnt->mnt_sb); - if (err) { - dput(mnt->mnt_sb->s_root); - up_write(&mnt->mnt_sb->s_umount); - deactivate_super(mnt->mnt_sb); - } - return err; } @@ -440,9 +423,24 @@ static int devpts_get_sb(struct file_system_type *fs_type, } if (opts.newinstance) - return new_pts_mount(fs_type, flags, data, &opts, mnt); + error = new_pts_mount(fs_type, flags, data, &opts, mnt); else - return init_pts_mount(fs_type, flags, data, &opts, mnt); + error = init_pts_mount(fs_type, flags, data, &opts, mnt); + + if (error) + return error; + + error = mknod_ptmx(mnt->mnt_sb); + if (error) + goto out_dput; + + return 0; + +out_dput: + dput(mnt->mnt_sb->s_root); + up_write(&mnt->mnt_sb->s_umount); + deactivate_super(mnt->mnt_sb); + return error; } #else -- GitLab From 289f00e225a6f60056644e0fd7e4081cb140c631 Mon Sep 17 00:00:00 2001 From: Sukadev Bhattiprolu Date: Sat, 7 Mar 2009 10:12:06 -0800 Subject: [PATCH 4803/4982] Remove get_init_pts_sb() With mknod_ptmx() moved to devpts_get_sb(), init_pts_mount() becomes a wrapper around get_init_pts_sb(). Remove get_init_pts_sb() and fold code into init_pts_mount(). Signed-off-by: Sukadev Bhattiprolu Acked-by: Serge Hallyn Signed-off-by: Al Viro --- fs/devpts/inode.c | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 58b719006af..9c775fa4130 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -342,7 +342,11 @@ static int new_pts_mount(struct file_system_type *fs_type, int flags, } /* - * get_init_pts_sb() + * init_pts_mount() + * + * Mount or remount the initial kernel mount of devpts. This type of + * mount maintains the legacy, single-instance semantics, while the + * kernel still allows multiple-instances. * * This interface is needed to support multiple namespace semantics in * devpts while preserving backward compatibility of the current 'single- @@ -362,7 +366,7 @@ static int new_pts_mount(struct file_system_type *fs_type, int flags, * consistently selects the 'single-namespace' superblock even in the * presence of the private namespace (i.e 'newinstance') super-blocks. */ -static int get_init_pts_sb(struct file_system_type *fs_type, int flags, +static int init_pts_mount(struct file_system_type *fs_type, int flags, void *data, struct pts_mount_opts *opts, struct vfsmount *mnt) { struct super_block *s; @@ -392,23 +396,6 @@ static int get_init_pts_sb(struct file_system_type *fs_type, int flags, return 0; } -/* - * Mount or remount the initial kernel mount of devpts. This type of - * mount maintains the legacy, single-instance semantics, while the - * kernel still allows multiple-instances. - */ -static int init_pts_mount(struct file_system_type *fs_type, int flags, - void *data, struct pts_mount_opts *opts, struct vfsmount *mnt) -{ - int err; - - err = get_init_pts_sb(fs_type, flags, data, opts, mnt); - if (err) - return err; - - return err; -} - static int devpts_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { -- GitLab From 1bd7903560f1f713e85188a5aaf4d2428b6c8b50 Mon Sep 17 00:00:00 2001 From: Sukadev Bhattiprolu Date: Sat, 7 Mar 2009 10:12:32 -0800 Subject: [PATCH 4804/4982] Merge code for single and multiple-instance mounts new_pts_mount() (including the get_sb_nodev()), shares a lot of code with init_pts_mount(). The only difference between them is the 'test-super' function passed into sget(). Move all common code into devpts_get_sb() and remove the new_pts_mount() and init_pts_mount() functions, Changelog[v3]: [Serge Hallyn]: Remove unnecessary printk()s Changelog[v2]: (Christoph Hellwig): Merge code in 'do_pts_mount()' into devpts_get_sb() Signed-off-by: Sukadev Bhattiprolu Acked-by: Serge Hallyn Tested-by: Serge Hallyn Signed-off-by: Al Viro --- fs/devpts/inode.c | 113 ++++++++++++++++------------------------------ 1 file changed, 40 insertions(+), 73 deletions(-) diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 9c775fa4130..63a4a59e414 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -322,85 +322,38 @@ static int compare_init_pts_sb(struct super_block *s, void *p) } /* - * Mount a new (private) instance of devpts. PTYs created in this - * instance are independent of the PTYs in other devpts instances. - */ -static int new_pts_mount(struct file_system_type *fs_type, int flags, - void *data, struct pts_mount_opts *opts, struct vfsmount *mnt) -{ - int err; - struct pts_fs_info *fsi; - - err = get_sb_nodev(fs_type, flags, data, devpts_fill_super, mnt); - if (err) - return err; - - fsi = DEVPTS_SB(mnt->mnt_sb); - memcpy(&fsi->mount_opts, opts, sizeof(opts)); - - return 0; -} - -/* - * init_pts_mount() + * devpts_get_sb() + * + * If the '-o newinstance' mount option was specified, mount a new + * (private) instance of devpts. PTYs created in this instance are + * independent of the PTYs in other devpts instances. + * + * If the '-o newinstance' option was not specified, mount/remount the + * initial kernel mount of devpts. This type of mount gives the + * legacy, single-instance semantics. * - * Mount or remount the initial kernel mount of devpts. This type of - * mount maintains the legacy, single-instance semantics, while the - * kernel still allows multiple-instances. + * The 'newinstance' option is needed to support multiple namespace + * semantics in devpts while preserving backward compatibility of the + * current 'single-namespace' semantics. i.e all mounts of devpts + * without the 'newinstance' mount option should bind to the initial + * kernel mount, like get_sb_single(). * - * This interface is needed to support multiple namespace semantics in - * devpts while preserving backward compatibility of the current 'single- - * namespace' semantics. i.e all mounts of devpts without the 'newinstance' - * mount option should bind to the initial kernel mount, like - * get_sb_single(). + * Mounts with 'newinstance' option create a new, private namespace. * - * Mounts with 'newinstance' option create a new private namespace. + * NOTE: * - * But for single-mount semantics, devpts cannot use get_sb_single(), + * For single-mount semantics, devpts cannot use get_sb_single(), * because get_sb_single()/sget() find and use the super-block from * the most recent mount of devpts. But that recent mount may be a * 'newinstance' mount and get_sb_single() would pick the newinstance * super-block instead of the initial super-block. - * - * This interface is identical to get_sb_single() except that it - * consistently selects the 'single-namespace' superblock even in the - * presence of the private namespace (i.e 'newinstance') super-blocks. */ -static int init_pts_mount(struct file_system_type *fs_type, int flags, - void *data, struct pts_mount_opts *opts, struct vfsmount *mnt) -{ - struct super_block *s; - struct pts_fs_info *fsi; - int error; - - s = sget(fs_type, compare_init_pts_sb, set_anon_super, NULL); - if (IS_ERR(s)) - return PTR_ERR(s); - - if (!s->s_root) { - s->s_flags = flags; - error = devpts_fill_super(s, data, flags & MS_SILENT ? 1 : 0); - if (error) { - up_write(&s->s_umount); - deactivate_super(s); - return error; - } - s->s_flags |= MS_ACTIVE; - } - - simple_set_mnt(mnt, s); - - fsi = DEVPTS_SB(mnt->mnt_sb); - memcpy(&fsi->mount_opts, opts, sizeof(opts)); - - return 0; -} - static int devpts_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { int error; struct pts_mount_opts opts; + struct super_block *s; memset(&opts, 0, sizeof(opts)); if (data) { @@ -410,23 +363,37 @@ static int devpts_get_sb(struct file_system_type *fs_type, } if (opts.newinstance) - error = new_pts_mount(fs_type, flags, data, &opts, mnt); + s = sget(fs_type, NULL, set_anon_super, NULL); else - error = init_pts_mount(fs_type, flags, data, &opts, mnt); + s = sget(fs_type, compare_init_pts_sb, set_anon_super, NULL); - if (error) - return error; + if (IS_ERR(s)) + return PTR_ERR(s); + + if (!s->s_root) { + s->s_flags = flags; + error = devpts_fill_super(s, data, flags & MS_SILENT ? 1 : 0); + if (error) + goto out_undo_sget; + s->s_flags |= MS_ACTIVE; + } + + simple_set_mnt(mnt, s); + + memcpy(&(DEVPTS_SB(s))->mount_opts, &opts, sizeof(opts)); - error = mknod_ptmx(mnt->mnt_sb); + error = mknod_ptmx(s); if (error) goto out_dput; return 0; out_dput: - dput(mnt->mnt_sb->s_root); - up_write(&mnt->mnt_sb->s_umount); - deactivate_super(mnt->mnt_sb); + dput(s->s_root); + +out_undo_sget: + up_write(&s->s_umount); + deactivate_super(s); return error; } -- GitLab From aabb8fdb41128705fd1627f56fdd571e45fdbcdb Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 11 Mar 2009 13:17:36 -0700 Subject: [PATCH 4805/4982] fs: avoid I_NEW inodes To be on the safe side, it should be less fragile to exclude I_NEW inodes from inode list scans by default (unless there is an important reason to have them). Normally they will get excluded (eg. by zero refcount or writecount etc), however it is a bit fragile for list walkers to know exactly what parts of the inode state is set up and valid to test when in I_NEW. So along these lines, move I_NEW checks upward as well (sometimes taking I_FREEING etc checks with them too -- this shouldn't be a problem should it?) Signed-off-by: Nick Piggin Acked-by: Jan Kara Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Al Viro --- fs/dquot.c | 10 ++++++++-- fs/drop_caches.c | 2 +- fs/inode.c | 2 ++ fs/notify/inotify/inotify.c | 16 ++++++++-------- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/fs/dquot.c b/fs/dquot.c index bca3cac4bee..cb1c3bc324d 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -789,12 +789,12 @@ static void add_dquot_ref(struct super_block *sb, int type) spin_lock(&inode_lock); list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { + if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) + continue; if (!atomic_read(&inode->i_writecount)) continue; if (!dqinit_needed(inode, type)) continue; - if (inode->i_state & (I_FREEING|I_WILL_FREE)) - continue; __iget(inode); spin_unlock(&inode_lock); @@ -870,6 +870,12 @@ static void remove_dquot_ref(struct super_block *sb, int type, spin_lock(&inode_lock); list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { + /* + * We have to scan also I_NEW inodes because they can already + * have quota pointer initialized. Luckily, we need to touch + * only quota pointers and these have separate locking + * (dqptr_sem). + */ if (!IS_NOQUOTA(inode)) remove_inode_dquot_ref(inode, type, tofree_head); } diff --git a/fs/drop_caches.c b/fs/drop_caches.c index 3e5637fc377..44d725f612c 100644 --- a/fs/drop_caches.c +++ b/fs/drop_caches.c @@ -18,7 +18,7 @@ static void drop_pagecache_sb(struct super_block *sb) spin_lock(&inode_lock); list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { - if (inode->i_state & (I_FREEING|I_WILL_FREE)) + if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) continue; if (inode->i_mapping->nrpages == 0) continue; diff --git a/fs/inode.c b/fs/inode.c index 826fb0b9d1c..06aa5a1fb61 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -356,6 +356,8 @@ static int invalidate_list(struct list_head *head, struct list_head *dispose) if (tmp == head) break; inode = list_entry(tmp, struct inode, i_sb_list); + if (inode->i_state & I_NEW) + continue; invalidate_inode_buffers(inode); if (!atomic_read(&inode->i_count)) { list_move(&inode->i_list, dispose); diff --git a/fs/notify/inotify/inotify.c b/fs/notify/inotify/inotify.c index 331f2e88e28..220c13f0d73 100644 --- a/fs/notify/inotify/inotify.c +++ b/fs/notify/inotify/inotify.c @@ -379,6 +379,14 @@ void inotify_unmount_inodes(struct list_head *list) struct inode *need_iput_tmp; struct list_head *watches; + /* + * We cannot __iget() an inode in state I_CLEAR, I_FREEING, + * I_WILL_FREE, or I_NEW which is fine because by that point + * the inode cannot have any associated watches. + */ + if (inode->i_state & (I_CLEAR|I_FREEING|I_WILL_FREE|I_NEW)) + continue; + /* * If i_count is zero, the inode cannot have any watches and * doing an __iget/iput with MS_ACTIVE clear would actually @@ -388,14 +396,6 @@ void inotify_unmount_inodes(struct list_head *list) if (!atomic_read(&inode->i_count)) continue; - /* - * We cannot __iget() an inode in state I_CLEAR, I_FREEING, or - * I_WILL_FREE which is fine because by that point the inode - * cannot have any associated watches. - */ - if (inode->i_state & (I_CLEAR | I_FREEING | I_WILL_FREE)) - continue; - need_iput_tmp = need_iput; need_iput = NULL; /* In case inotify_remove_watch_locked() drops a reference. */ -- GitLab From 32a0f488ce5e8a9a148491f15edc508ab5e8265b Mon Sep 17 00:00:00 2001 From: Beat Michel Liechti Date: Thu, 26 Mar 2009 22:36:52 +0100 Subject: [PATCH 4806/4982] DVB: firedtv: FireDTV S2 problems with tuning solved Signed-off-by: Beat Michel Liechti Tuning was broken on FireDTV S2 (and presumably FloppyDTV S2) because a wrong opcode was sent. The box only gave "not implemented" responses. Changing the opcode to _TUNE_QPSK2 fixes this for good. Cc: stable@kernel.org Signed-off-by: Stefan Richter --- drivers/media/dvb/firewire/firedtv-avc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c index 1a300f00e0f..32526f103b5 100644 --- a/drivers/media/dvb/firewire/firedtv-avc.c +++ b/drivers/media/dvb/firewire/firedtv-avc.c @@ -135,6 +135,7 @@ static const char *debug_fcp_opcode(unsigned int opcode, case SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL: return "RegisterRC"; case SFE_VENDOR_OPCODE_LNB_CONTROL: return "LNBControl"; case SFE_VENDOR_OPCODE_TUNE_QPSK: return "TuneQPSK"; + case SFE_VENDOR_OPCODE_TUNE_QPSK2: return "TuneQPSK2"; case SFE_VENDOR_OPCODE_HOST2CA: return "Host2CA"; case SFE_VENDOR_OPCODE_CA2HOST: return "CA2Host"; } @@ -266,7 +267,10 @@ static void avc_tuner_tuneqpsk(struct firedtv *fdtv, c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; - c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK; + if (fdtv->type == FIREDTV_DVB_S2) + c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK2; + else + c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK; c->operand[4] = (params->frequency >> 24) & 0xff; c->operand[5] = (params->frequency >> 16) & 0xff; -- GitLab From 568d9a8f6d4bf81e0672c74573dc02981d31e3ea Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 12 Mar 2009 16:27:11 -0700 Subject: [PATCH 4807/4982] drm/i915: Change DCC tiling detection case to cover only mobile parts. Later spec investigation has revealed that every 9xx mobile part has had this register in this format. Also, no non-mobile parts have been shown to have this register. So make all mobile use the same code, and all non-mobile use the hack 965 detection. Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem_tiling.c | 31 +++++++++++++------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 7fb4191ef93..4cce1aef438 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -96,16 +96,16 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) */ swizzle_x = I915_BIT_6_SWIZZLE_NONE; swizzle_y = I915_BIT_6_SWIZZLE_NONE; - } else if ((!IS_I965G(dev) && !IS_G33(dev)) || IS_I965GM(dev) || - IS_GM45(dev)) { + } else if (IS_MOBILE(dev)) { uint32_t dcc; - /* On 915-945 and GM965, channel interleave by the CPU is - * determined by DCC. The CPU will alternate based on bit 6 - * in interleaved mode, and the GPU will then also alternate - * on bit 6, 9, and 10 for X, but the CPU may also optionally - * alternate based on bit 17 (XOR not disabled and XOR - * bit == 17). + /* On mobile 9xx chipsets, channel interleave by the CPU is + * determined by DCC. For single-channel, neither the CPU + * nor the GPU do swizzling. For dual channel interleaved, + * the GPU's interleave is bit 9 and 10 for X tiled, and bit + * 9 for Y tiled. The CPU's interleave is independent, and + * can be based on either bit 11 (haven't seen this yet) or + * bit 17 (common). */ dcc = I915_READ(DCC); switch (dcc & DCC_ADDRESSING_MODE_MASK) { @@ -115,19 +115,18 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) swizzle_y = I915_BIT_6_SWIZZLE_NONE; break; case DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED: - if (IS_I915G(dev) || IS_I915GM(dev) || - dcc & DCC_CHANNEL_XOR_DISABLE) { + if (dcc & DCC_CHANNEL_XOR_DISABLE) { + /* This is the base swizzling by the GPU for + * tiled buffers. + */ swizzle_x = I915_BIT_6_SWIZZLE_9_10; swizzle_y = I915_BIT_6_SWIZZLE_9; - } else if ((IS_I965GM(dev) || IS_GM45(dev)) && - (dcc & DCC_CHANNEL_XOR_BIT_17) == 0) { - /* GM965/GM45 does either bit 11 or bit 17 - * swizzling. - */ + } else if ((dcc & DCC_CHANNEL_XOR_BIT_17) == 0) { + /* Bit 11 swizzling by the CPU in addition. */ swizzle_x = I915_BIT_6_SWIZZLE_9_10_11; swizzle_y = I915_BIT_6_SWIZZLE_9_11; } else { - /* Bit 17 or perhaps other swizzling */ + /* Bit 17 swizzling by the CPU in addition. */ swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN; swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN; } -- GitLab From 044c7c415a68077b7c444c753aa03a35149e881a Mon Sep 17 00:00:00 2001 From: Ma Ling Date: Wed, 18 Mar 2009 20:13:23 +0800 Subject: [PATCH 4808/4982] drm/i915: Use documented PLL timing limits for G4X platform The values come from the internal reference spreadsheet on PLL timing limits for the G4X chipsets. Part of fixing fd.o bug #17508 Signed-off-by: Ma Ling [anholt: Cleaned up some whitespace] Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 187 ++++++++++++++++++++++++++- 1 file changed, 186 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a2834276cb3..89f7af0bdb1 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -115,6 +115,89 @@ typedef struct { #define INTEL_LIMIT_I8XX_LVDS 1 #define INTEL_LIMIT_I9XX_SDVO_DAC 2 #define INTEL_LIMIT_I9XX_LVDS 3 +#define INTEL_LIMIT_G4X_SDVO 4 +#define INTEL_LIMIT_G4X_HDMI_DAC 5 +#define INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS 6 +#define INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS 7 + +/*The parameter is for SDVO on G4x platform*/ +#define G4X_DOT_SDVO_MIN 25000 +#define G4X_DOT_SDVO_MAX 270000 +#define G4X_VCO_MIN 1750000 +#define G4X_VCO_MAX 3500000 +#define G4X_N_SDVO_MIN 1 +#define G4X_N_SDVO_MAX 4 +#define G4X_M_SDVO_MIN 104 +#define G4X_M_SDVO_MAX 138 +#define G4X_M1_SDVO_MIN 17 +#define G4X_M1_SDVO_MAX 23 +#define G4X_M2_SDVO_MIN 5 +#define G4X_M2_SDVO_MAX 11 +#define G4X_P_SDVO_MIN 10 +#define G4X_P_SDVO_MAX 30 +#define G4X_P1_SDVO_MIN 1 +#define G4X_P1_SDVO_MAX 3 +#define G4X_P2_SDVO_SLOW 10 +#define G4X_P2_SDVO_FAST 10 +#define G4X_P2_SDVO_LIMIT 270000 + +/*The parameter is for HDMI_DAC on G4x platform*/ +#define G4X_DOT_HDMI_DAC_MIN 22000 +#define G4X_DOT_HDMI_DAC_MAX 400000 +#define G4X_N_HDMI_DAC_MIN 1 +#define G4X_N_HDMI_DAC_MAX 4 +#define G4X_M_HDMI_DAC_MIN 104 +#define G4X_M_HDMI_DAC_MAX 138 +#define G4X_M1_HDMI_DAC_MIN 16 +#define G4X_M1_HDMI_DAC_MAX 23 +#define G4X_M2_HDMI_DAC_MIN 5 +#define G4X_M2_HDMI_DAC_MAX 11 +#define G4X_P_HDMI_DAC_MIN 5 +#define G4X_P_HDMI_DAC_MAX 80 +#define G4X_P1_HDMI_DAC_MIN 1 +#define G4X_P1_HDMI_DAC_MAX 8 +#define G4X_P2_HDMI_DAC_SLOW 10 +#define G4X_P2_HDMI_DAC_FAST 5 +#define G4X_P2_HDMI_DAC_LIMIT 165000 + +/*The parameter is for SINGLE_CHANNEL_LVDS on G4x platform*/ +#define G4X_DOT_SINGLE_CHANNEL_LVDS_MIN 20000 +#define G4X_DOT_SINGLE_CHANNEL_LVDS_MAX 115000 +#define G4X_N_SINGLE_CHANNEL_LVDS_MIN 1 +#define G4X_N_SINGLE_CHANNEL_LVDS_MAX 3 +#define G4X_M_SINGLE_CHANNEL_LVDS_MIN 104 +#define G4X_M_SINGLE_CHANNEL_LVDS_MAX 138 +#define G4X_M1_SINGLE_CHANNEL_LVDS_MIN 17 +#define G4X_M1_SINGLE_CHANNEL_LVDS_MAX 23 +#define G4X_M2_SINGLE_CHANNEL_LVDS_MIN 5 +#define G4X_M2_SINGLE_CHANNEL_LVDS_MAX 11 +#define G4X_P_SINGLE_CHANNEL_LVDS_MIN 28 +#define G4X_P_SINGLE_CHANNEL_LVDS_MAX 112 +#define G4X_P1_SINGLE_CHANNEL_LVDS_MIN 2 +#define G4X_P1_SINGLE_CHANNEL_LVDS_MAX 8 +#define G4X_P2_SINGLE_CHANNEL_LVDS_SLOW 14 +#define G4X_P2_SINGLE_CHANNEL_LVDS_FAST 14 +#define G4X_P2_SINGLE_CHANNEL_LVDS_LIMIT 0 + +/*The parameter is for DUAL_CHANNEL_LVDS on G4x platform*/ +#define G4X_DOT_DUAL_CHANNEL_LVDS_MIN 80000 +#define G4X_DOT_DUAL_CHANNEL_LVDS_MAX 224000 +#define G4X_N_DUAL_CHANNEL_LVDS_MIN 1 +#define G4X_N_DUAL_CHANNEL_LVDS_MAX 3 +#define G4X_M_DUAL_CHANNEL_LVDS_MIN 104 +#define G4X_M_DUAL_CHANNEL_LVDS_MAX 138 +#define G4X_M1_DUAL_CHANNEL_LVDS_MIN 17 +#define G4X_M1_DUAL_CHANNEL_LVDS_MAX 23 +#define G4X_M2_DUAL_CHANNEL_LVDS_MIN 5 +#define G4X_M2_DUAL_CHANNEL_LVDS_MAX 11 +#define G4X_P_DUAL_CHANNEL_LVDS_MIN 14 +#define G4X_P_DUAL_CHANNEL_LVDS_MAX 42 +#define G4X_P1_DUAL_CHANNEL_LVDS_MIN 2 +#define G4X_P1_DUAL_CHANNEL_LVDS_MAX 6 +#define G4X_P2_DUAL_CHANNEL_LVDS_SLOW 7 +#define G4X_P2_DUAL_CHANNEL_LVDS_FAST 7 +#define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT 0 + static const intel_limit_t intel_limits[] = { { /* INTEL_LIMIT_I8XX_DVO_DAC */ @@ -168,14 +251,116 @@ static const intel_limit_t intel_limits[] = { .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, }, + /* below parameter and function is for G4X Chipset Family*/ + { /* INTEL_LIMIT_G4X_SDVO */ + .dot = { .min = G4X_DOT_SDVO_MIN, .max = G4X_DOT_SDVO_MAX }, + .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, + .n = { .min = G4X_N_SDVO_MIN, .max = G4X_N_SDVO_MAX }, + .m = { .min = G4X_M_SDVO_MIN, .max = G4X_M_SDVO_MAX }, + .m1 = { .min = G4X_M1_SDVO_MIN, .max = G4X_M1_SDVO_MAX }, + .m2 = { .min = G4X_M2_SDVO_MIN, .max = G4X_M2_SDVO_MAX }, + .p = { .min = G4X_P_SDVO_MIN, .max = G4X_P_SDVO_MAX }, + .p1 = { .min = G4X_P1_SDVO_MIN, .max = G4X_P1_SDVO_MAX}, + .p2 = { .dot_limit = G4X_P2_SDVO_LIMIT, + .p2_slow = G4X_P2_SDVO_SLOW, + .p2_fast = G4X_P2_SDVO_FAST + }, + }, + { /* INTEL_LIMIT_G4X_HDMI_DAC */ + .dot = { .min = G4X_DOT_HDMI_DAC_MIN, .max = G4X_DOT_HDMI_DAC_MAX }, + .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, + .n = { .min = G4X_N_HDMI_DAC_MIN, .max = G4X_N_HDMI_DAC_MAX }, + .m = { .min = G4X_M_HDMI_DAC_MIN, .max = G4X_M_HDMI_DAC_MAX }, + .m1 = { .min = G4X_M1_HDMI_DAC_MIN, .max = G4X_M1_HDMI_DAC_MAX }, + .m2 = { .min = G4X_M2_HDMI_DAC_MIN, .max = G4X_M2_HDMI_DAC_MAX }, + .p = { .min = G4X_P_HDMI_DAC_MIN, .max = G4X_P_HDMI_DAC_MAX }, + .p1 = { .min = G4X_P1_HDMI_DAC_MIN, .max = G4X_P1_HDMI_DAC_MAX}, + .p2 = { .dot_limit = G4X_P2_HDMI_DAC_LIMIT, + .p2_slow = G4X_P2_HDMI_DAC_SLOW, + .p2_fast = G4X_P2_HDMI_DAC_FAST + }, + }, + { /* INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS */ + .dot = { .min = G4X_DOT_SINGLE_CHANNEL_LVDS_MIN, + .max = G4X_DOT_SINGLE_CHANNEL_LVDS_MAX }, + .vco = { .min = G4X_VCO_MIN, + .max = G4X_VCO_MAX }, + .n = { .min = G4X_N_SINGLE_CHANNEL_LVDS_MIN, + .max = G4X_N_SINGLE_CHANNEL_LVDS_MAX }, + .m = { .min = G4X_M_SINGLE_CHANNEL_LVDS_MIN, + .max = G4X_M_SINGLE_CHANNEL_LVDS_MAX }, + .m1 = { .min = G4X_M1_SINGLE_CHANNEL_LVDS_MIN, + .max = G4X_M1_SINGLE_CHANNEL_LVDS_MAX }, + .m2 = { .min = G4X_M2_SINGLE_CHANNEL_LVDS_MIN, + .max = G4X_M2_SINGLE_CHANNEL_LVDS_MAX }, + .p = { .min = G4X_P_SINGLE_CHANNEL_LVDS_MIN, + .max = G4X_P_SINGLE_CHANNEL_LVDS_MAX }, + .p1 = { .min = G4X_P1_SINGLE_CHANNEL_LVDS_MIN, + .max = G4X_P1_SINGLE_CHANNEL_LVDS_MAX }, + .p2 = { .dot_limit = G4X_P2_SINGLE_CHANNEL_LVDS_LIMIT, + .p2_slow = G4X_P2_SINGLE_CHANNEL_LVDS_SLOW, + .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST + }, + }, + { /* INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS */ + .dot = { .min = G4X_DOT_DUAL_CHANNEL_LVDS_MIN, + .max = G4X_DOT_DUAL_CHANNEL_LVDS_MAX }, + .vco = { .min = G4X_VCO_MIN, + .max = G4X_VCO_MAX }, + .n = { .min = G4X_N_DUAL_CHANNEL_LVDS_MIN, + .max = G4X_N_DUAL_CHANNEL_LVDS_MAX }, + .m = { .min = G4X_M_DUAL_CHANNEL_LVDS_MIN, + .max = G4X_M_DUAL_CHANNEL_LVDS_MAX }, + .m1 = { .min = G4X_M1_DUAL_CHANNEL_LVDS_MIN, + .max = G4X_M1_DUAL_CHANNEL_LVDS_MAX }, + .m2 = { .min = G4X_M2_DUAL_CHANNEL_LVDS_MIN, + .max = G4X_M2_DUAL_CHANNEL_LVDS_MAX }, + .p = { .min = G4X_P_DUAL_CHANNEL_LVDS_MIN, + .max = G4X_P_DUAL_CHANNEL_LVDS_MAX }, + .p1 = { .min = G4X_P1_DUAL_CHANNEL_LVDS_MIN, + .max = G4X_P1_DUAL_CHANNEL_LVDS_MAX }, + .p2 = { .dot_limit = G4X_P2_DUAL_CHANNEL_LVDS_LIMIT, + .p2_slow = G4X_P2_DUAL_CHANNEL_LVDS_SLOW, + .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST + }, + }, }; +static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + const intel_limit_t *limit; + + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { + if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == + LVDS_CLKB_POWER_UP) + /* LVDS with dual channel */ + limit = &intel_limits + [INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS]; + else + /* LVDS with dual channel */ + limit = &intel_limits + [INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS]; + } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) || + intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) { + limit = &intel_limits[INTEL_LIMIT_G4X_HDMI_DAC]; + } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) { + limit = &intel_limits[INTEL_LIMIT_G4X_SDVO]; + } else /* The option is for other outputs */ + limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; + + return limit; +} + static const intel_limit_t *intel_limit(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; const intel_limit_t *limit; - if (IS_I9XX(dev)) { + if (IS_G4X(dev)) { + limit = intel_g4x_limit(crtc); + } else if (IS_I9XX(dev)) { if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS]; else -- GitLab From d490609321828c62e8dfa6220f0acd82e5cb3756 Mon Sep 17 00:00:00 2001 From: Ma Ling Date: Wed, 18 Mar 2009 20:13:27 +0800 Subject: [PATCH 4809/4982] drm/i915: Use a different PLL timing search function on G4X. This improves the PLL timings according to the suggestion of the hardware engineers. This results in some outputs being able to sync that weren't able to before. This is part of fixing fd.o bug #17508. Signed-off-by: Ma Ling [anholt: cleaned up a couple of redundant comments] Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 100 +++++++++++++++++++++++---- 1 file changed, 88 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 89f7af0bdb1..8e29545273b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -56,11 +56,13 @@ typedef struct { } intel_p2_t; #define INTEL_P2_NUM 2 - -typedef struct { +typedef struct intel_limit intel_limit_t; +struct intel_limit { intel_range_t dot, vco, n, m, m1, m2, p, p1; intel_p2_t p2; -} intel_limit_t; + bool (* find_pll)(const intel_limit_t *, struct drm_crtc *, + int, int, intel_clock_t *); +}; #define I8XX_DOT_MIN 25000 #define I8XX_DOT_MAX 350000 @@ -198,6 +200,12 @@ typedef struct { #define G4X_P2_DUAL_CHANNEL_LVDS_FAST 7 #define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT 0 +static bool +intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, + int target, int refclk, intel_clock_t *best_clock); +static bool +intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, + int target, int refclk, intel_clock_t *best_clock); static const intel_limit_t intel_limits[] = { { /* INTEL_LIMIT_I8XX_DVO_DAC */ @@ -211,6 +219,7 @@ static const intel_limit_t intel_limits[] = { .p1 = { .min = I8XX_P1_MIN, .max = I8XX_P1_MAX }, .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, + .find_pll = intel_find_best_PLL, }, { /* INTEL_LIMIT_I8XX_LVDS */ .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, @@ -223,6 +232,7 @@ static const intel_limit_t intel_limits[] = { .p1 = { .min = I8XX_P1_LVDS_MIN, .max = I8XX_P1_LVDS_MAX }, .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, + .find_pll = intel_find_best_PLL, }, { /* INTEL_LIMIT_I9XX_SDVO_DAC */ .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, @@ -235,6 +245,7 @@ static const intel_limit_t intel_limits[] = { .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX }, .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, + .find_pll = intel_find_best_PLL, }, { /* INTEL_LIMIT_I9XX_LVDS */ .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, @@ -250,6 +261,7 @@ static const intel_limit_t intel_limits[] = { */ .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, + .find_pll = intel_find_best_PLL, }, /* below parameter and function is for G4X Chipset Family*/ { /* INTEL_LIMIT_G4X_SDVO */ @@ -265,6 +277,7 @@ static const intel_limit_t intel_limits[] = { .p2_slow = G4X_P2_SDVO_SLOW, .p2_fast = G4X_P2_SDVO_FAST }, + .find_pll = intel_g4x_find_best_PLL, }, { /* INTEL_LIMIT_G4X_HDMI_DAC */ .dot = { .min = G4X_DOT_HDMI_DAC_MIN, .max = G4X_DOT_HDMI_DAC_MAX }, @@ -279,6 +292,7 @@ static const intel_limit_t intel_limits[] = { .p2_slow = G4X_P2_HDMI_DAC_SLOW, .p2_fast = G4X_P2_HDMI_DAC_FAST }, + .find_pll = intel_g4x_find_best_PLL, }, { /* INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS */ .dot = { .min = G4X_DOT_SINGLE_CHANNEL_LVDS_MIN, @@ -301,6 +315,7 @@ static const intel_limit_t intel_limits[] = { .p2_slow = G4X_P2_SINGLE_CHANNEL_LVDS_SLOW, .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST }, + .find_pll = intel_g4x_find_best_PLL, }, { /* INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS */ .dot = { .min = G4X_DOT_DUAL_CHANNEL_LVDS_MIN, @@ -323,6 +338,7 @@ static const intel_limit_t intel_limits[] = { .p2_slow = G4X_P2_DUAL_CHANNEL_LVDS_SLOW, .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST }, + .find_pll = intel_g4x_find_best_PLL, }, }; @@ -437,18 +453,14 @@ static bool intel_PLL_is_valid(struct drm_crtc *crtc, intel_clock_t *clock) return true; } -/** - * Returns a set of divisors for the desired target clock with the given - * refclk, or FALSE. The returned values represent the clock equation: - * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. - */ -static bool intel_find_best_PLL(struct drm_crtc *crtc, int target, - int refclk, intel_clock_t *best_clock) +static bool +intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, + int target, int refclk, intel_clock_t *best_clock) + { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; intel_clock_t clock; - const intel_limit_t *limit = intel_limit(crtc); int err = target; if (IS_I9XX(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && @@ -500,6 +512,63 @@ static bool intel_find_best_PLL(struct drm_crtc *crtc, int target, return (err != target); } +static bool +intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, + int target, int refclk, intel_clock_t *best_clock) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + intel_clock_t clock; + int max_n; + bool found; + /* approximately equals target * 0.00488 */ + int err_most = (target >> 8) + (target >> 10); + found = false; + + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { + if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == + LVDS_CLKB_POWER_UP) + clock.p2 = limit->p2.p2_fast; + else + clock.p2 = limit->p2.p2_slow; + } else { + if (target < limit->p2.dot_limit) + clock.p2 = limit->p2.p2_slow; + else + clock.p2 = limit->p2.p2_fast; + } + + memset(best_clock, 0, sizeof(*best_clock)); + max_n = limit->n.max; + /* based on hardware requriment prefer smaller n to precision */ + for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) { + /* based on hardware requirment prefere larger m1,m2, p1 */ + for (clock.m1 = limit->m1.max; + clock.m1 >= limit->m1.min; clock.m1--) { + for (clock.m2 = limit->m2.max; + clock.m2 >= limit->m2.min; clock.m2--) { + for (clock.p1 = limit->p1.max; + clock.p1 >= limit->p1.min; clock.p1--) { + int this_err; + + intel_clock(refclk, &clock); + if (!intel_PLL_is_valid(crtc, &clock)) + continue; + this_err = abs(clock.dot - target) ; + if (this_err < err_most) { + *best_clock = clock; + err_most = this_err; + max_n = clock.n; + found = true; + } + } + } + } + } + + return found; +} + void intel_wait_for_vblank(struct drm_device *dev) { @@ -918,6 +987,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, bool is_crt = false, is_lvds = false, is_tv = false; struct drm_mode_config *mode_config = &dev->mode_config; struct drm_connector *connector; + const intel_limit_t *limit; int ret; drm_vblank_pre_modeset(dev, pipe); @@ -961,7 +1031,13 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, refclk = 48000; } - ok = intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, &clock); + /* + * Returns a set of divisors for the desired target clock with the given + * refclk, or FALSE. The returned values represent the clock equation: + * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. + */ + limit = intel_limit(crtc); + ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock); if (!ok) { DRM_ERROR("Couldn't find PLL settings for mode!\n"); return -EINVAL; -- GitLab From 13520b051e8888dd3af9bda639d83e7df76613d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 13 Mar 2009 15:42:14 -0400 Subject: [PATCH 4810/4982] drm/i915: Read the right SDVO register when detecting SVDO/HDMI. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes incorrect detection of the second SDVO/HDMI output on G4X, and extra boot time on pre-G4X. Signed-off-by: Kristian Høgsberg Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8e29545273b..0d40b4b6979 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1735,13 +1735,21 @@ static void intel_setup_outputs(struct drm_device *dev) if (IS_I9XX(dev)) { int found; + u32 reg; if (I915_READ(SDVOB) & SDVO_DETECTED) { found = intel_sdvo_init(dev, SDVOB); if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) intel_hdmi_init(dev, SDVOB); } - if (!IS_G4X(dev) || (I915_READ(SDVOB) & SDVO_DETECTED)) { + + /* Before G4X SDVOC doesn't have its own detect register */ + if (IS_G4X(dev)) + reg = SDVOC; + else + reg = SDVOB; + + if (I915_READ(reg) & SDVO_DETECTED) { found = intel_sdvo_init(dev, SDVOC); if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) intel_hdmi_init(dev, SDVOC); -- GitLab From 3de09aa3b38910d366f4710ffdf430c9d387d1a3 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 9 Mar 2009 09:42:23 -0700 Subject: [PATCH 4811/4982] drm/i915: Fix lock order reversal in GTT pwrite path. Since the pagefault path determines that the lock order we use has to be mmap_sem -> struct_mutex, we can't allow page faults to occur while the struct_mutex is held. To fix this in pwrite, we first try optimistically to see if we can copy from user without faulting. If it fails, fall back to using get_user_pages to pin the user's memory, and map those pages atomically when copying it to the GPU. Signed-off-by: Eric Anholt Reviewed-by: Jesse Barnes --- drivers/gpu/drm/i915/i915_gem.c | 166 ++++++++++++++++++++++++++------ 1 file changed, 139 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 37427e4016c..35f8c7bd0d3 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -223,29 +223,34 @@ fast_user_write(struct io_mapping *mapping, */ static inline int -slow_user_write(struct io_mapping *mapping, - loff_t page_base, int page_offset, - char __user *user_data, - int length) +slow_kernel_write(struct io_mapping *mapping, + loff_t gtt_base, int gtt_offset, + struct page *user_page, int user_offset, + int length) { - char __iomem *vaddr; + char *src_vaddr, *dst_vaddr; unsigned long unwritten; - vaddr = io_mapping_map_wc(mapping, page_base); - if (vaddr == NULL) - return -EFAULT; - unwritten = __copy_from_user(vaddr + page_offset, - user_data, length); - io_mapping_unmap(vaddr); + dst_vaddr = io_mapping_map_atomic_wc(mapping, gtt_base); + src_vaddr = kmap_atomic(user_page, KM_USER1); + unwritten = __copy_from_user_inatomic_nocache(dst_vaddr + gtt_offset, + src_vaddr + user_offset, + length); + kunmap_atomic(src_vaddr, KM_USER1); + io_mapping_unmap_atomic(dst_vaddr); if (unwritten) return -EFAULT; return 0; } +/** + * This is the fast pwrite path, where we copy the data directly from the + * user into the GTT, uncached. + */ static int -i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj, - struct drm_i915_gem_pwrite *args, - struct drm_file *file_priv) +i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj, + struct drm_i915_gem_pwrite *args, + struct drm_file *file_priv) { struct drm_i915_gem_object *obj_priv = obj->driver_private; drm_i915_private_t *dev_priv = dev->dev_private; @@ -273,7 +278,6 @@ i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj, obj_priv = obj->driver_private; offset = obj_priv->gtt_offset + args->offset; - obj_priv->dirty = 1; while (remain > 0) { /* Operation in this page @@ -292,16 +296,11 @@ i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj, page_offset, user_data, page_length); /* If we get a fault while copying data, then (presumably) our - * source page isn't available. In this case, use the - * non-atomic function + * source page isn't available. Return the error and we'll + * retry in the slow path. */ - if (ret) { - ret = slow_user_write (dev_priv->mm.gtt_mapping, - page_base, page_offset, - user_data, page_length); - if (ret) - goto fail; - } + if (ret) + goto fail; remain -= page_length; user_data += page_length; @@ -315,6 +314,115 @@ fail: return ret; } +/** + * This is the fallback GTT pwrite path, which uses get_user_pages to pin + * the memory and maps it using kmap_atomic for copying. + * + * This code resulted in x11perf -rgb10text consuming about 10% more CPU + * than using i915_gem_gtt_pwrite_fast on a G45 (32-bit). + */ +static int +i915_gem_gtt_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj, + struct drm_i915_gem_pwrite *args, + struct drm_file *file_priv) +{ + struct drm_i915_gem_object *obj_priv = obj->driver_private; + drm_i915_private_t *dev_priv = dev->dev_private; + ssize_t remain; + loff_t gtt_page_base, offset; + loff_t first_data_page, last_data_page, num_pages; + loff_t pinned_pages, i; + struct page **user_pages; + struct mm_struct *mm = current->mm; + int gtt_page_offset, data_page_offset, data_page_index, page_length; + int ret; + uint64_t data_ptr = args->data_ptr; + + remain = args->size; + + /* Pin the user pages containing the data. We can't fault while + * holding the struct mutex, and all of the pwrite implementations + * want to hold it while dereferencing the user data. + */ + first_data_page = data_ptr / PAGE_SIZE; + last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE; + num_pages = last_data_page - first_data_page + 1; + + user_pages = kcalloc(num_pages, sizeof(struct page *), GFP_KERNEL); + if (user_pages == NULL) + return -ENOMEM; + + down_read(&mm->mmap_sem); + pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr, + num_pages, 0, 0, user_pages, NULL); + up_read(&mm->mmap_sem); + if (pinned_pages < num_pages) { + ret = -EFAULT; + goto out_unpin_pages; + } + + mutex_lock(&dev->struct_mutex); + ret = i915_gem_object_pin(obj, 0); + if (ret) + goto out_unlock; + + ret = i915_gem_object_set_to_gtt_domain(obj, 1); + if (ret) + goto out_unpin_object; + + obj_priv = obj->driver_private; + offset = obj_priv->gtt_offset + args->offset; + + while (remain > 0) { + /* Operation in this page + * + * gtt_page_base = page offset within aperture + * gtt_page_offset = offset within page in aperture + * data_page_index = page number in get_user_pages return + * data_page_offset = offset with data_page_index page. + * page_length = bytes to copy for this page + */ + gtt_page_base = offset & PAGE_MASK; + gtt_page_offset = offset & ~PAGE_MASK; + data_page_index = data_ptr / PAGE_SIZE - first_data_page; + data_page_offset = data_ptr & ~PAGE_MASK; + + page_length = remain; + if ((gtt_page_offset + page_length) > PAGE_SIZE) + page_length = PAGE_SIZE - gtt_page_offset; + if ((data_page_offset + page_length) > PAGE_SIZE) + page_length = PAGE_SIZE - data_page_offset; + + ret = slow_kernel_write(dev_priv->mm.gtt_mapping, + gtt_page_base, gtt_page_offset, + user_pages[data_page_index], + data_page_offset, + page_length); + + /* If we get a fault while copying data, then (presumably) our + * source page isn't available. Return the error and we'll + * retry in the slow path. + */ + if (ret) + goto out_unpin_object; + + remain -= page_length; + offset += page_length; + data_ptr += page_length; + } + +out_unpin_object: + i915_gem_object_unpin(obj); +out_unlock: + mutex_unlock(&dev->struct_mutex); +out_unpin_pages: + for (i = 0; i < pinned_pages; i++) + page_cache_release(user_pages[i]); + kfree(user_pages); + + return ret; +} + static int i915_gem_shmem_pwrite(struct drm_device *dev, struct drm_gem_object *obj, struct drm_i915_gem_pwrite *args, @@ -388,9 +496,13 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, if (obj_priv->phys_obj) ret = i915_gem_phys_pwrite(dev, obj, args, file_priv); else if (obj_priv->tiling_mode == I915_TILING_NONE && - dev->gtt_total != 0) - ret = i915_gem_gtt_pwrite(dev, obj, args, file_priv); - else + dev->gtt_total != 0) { + ret = i915_gem_gtt_pwrite_fast(dev, obj, args, file_priv); + if (ret == -EFAULT) { + ret = i915_gem_gtt_pwrite_slow(dev, obj, args, + file_priv); + } + } else ret = i915_gem_shmem_pwrite(dev, obj, args, file_priv); #if WATCH_PWRITE -- GitLab From 856fa1988ea483fc2dab84a16681dcfde821b740 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 19 Mar 2009 14:10:50 -0700 Subject: [PATCH 4812/4982] drm/i915: Make GEM object's page lists refcounted instead of get/free. We've wanted this for a few consumers that touch the pages directly (such as the following commit), which have been doing the refcounting outside of get/put pages. Signed-off-by: Eric Anholt Reviewed-by: Jesse Barnes --- drivers/gpu/drm/i915/i915_drv.h | 3 +- drivers/gpu/drm/i915/i915_gem.c | 70 +++++++++++++++++---------------- 2 files changed, 38 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d6cc9861e0a..75e33844146 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -404,7 +404,8 @@ struct drm_i915_gem_object { /** AGP memory structure for our GTT binding. */ DRM_AGP_MEM *agp_mem; - struct page **page_list; + struct page **pages; + int pages_refcount; /** * Current offset of the object in GTT space. diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 35f8c7bd0d3..b998d659fd9 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -43,8 +43,8 @@ static int i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, uint64_t offset, uint64_t size); static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj); -static int i915_gem_object_get_page_list(struct drm_gem_object *obj); -static void i915_gem_object_free_page_list(struct drm_gem_object *obj); +static int i915_gem_object_get_pages(struct drm_gem_object *obj); +static void i915_gem_object_put_pages(struct drm_gem_object *obj); static int i915_gem_object_wait_rendering(struct drm_gem_object *obj); static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment); @@ -928,29 +928,30 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, } static void -i915_gem_object_free_page_list(struct drm_gem_object *obj) +i915_gem_object_put_pages(struct drm_gem_object *obj) { struct drm_i915_gem_object *obj_priv = obj->driver_private; int page_count = obj->size / PAGE_SIZE; int i; - if (obj_priv->page_list == NULL) - return; + BUG_ON(obj_priv->pages_refcount == 0); + if (--obj_priv->pages_refcount != 0) + return; for (i = 0; i < page_count; i++) - if (obj_priv->page_list[i] != NULL) { + if (obj_priv->pages[i] != NULL) { if (obj_priv->dirty) - set_page_dirty(obj_priv->page_list[i]); - mark_page_accessed(obj_priv->page_list[i]); - page_cache_release(obj_priv->page_list[i]); + set_page_dirty(obj_priv->pages[i]); + mark_page_accessed(obj_priv->pages[i]); + page_cache_release(obj_priv->pages[i]); } obj_priv->dirty = 0; - drm_free(obj_priv->page_list, + drm_free(obj_priv->pages, page_count * sizeof(struct page *), DRM_MEM_DRIVER); - obj_priv->page_list = NULL; + obj_priv->pages = NULL; } static void @@ -1402,7 +1403,7 @@ i915_gem_object_unbind(struct drm_gem_object *obj) if (obj_priv->fence_reg != I915_FENCE_REG_NONE) i915_gem_clear_fence_reg(obj); - i915_gem_object_free_page_list(obj); + i915_gem_object_put_pages(obj); if (obj_priv->gtt_space) { atomic_dec(&dev->gtt_count); @@ -1521,7 +1522,7 @@ i915_gem_evict_everything(struct drm_device *dev) } static int -i915_gem_object_get_page_list(struct drm_gem_object *obj) +i915_gem_object_get_pages(struct drm_gem_object *obj) { struct drm_i915_gem_object *obj_priv = obj->driver_private; int page_count, i; @@ -1530,18 +1531,19 @@ i915_gem_object_get_page_list(struct drm_gem_object *obj) struct page *page; int ret; - if (obj_priv->page_list) + if (obj_priv->pages_refcount++ != 0) return 0; /* Get the list of pages out of our struct file. They'll be pinned * at this point until we release them. */ page_count = obj->size / PAGE_SIZE; - BUG_ON(obj_priv->page_list != NULL); - obj_priv->page_list = drm_calloc(page_count, sizeof(struct page *), - DRM_MEM_DRIVER); - if (obj_priv->page_list == NULL) { + BUG_ON(obj_priv->pages != NULL); + obj_priv->pages = drm_calloc(page_count, sizeof(struct page *), + DRM_MEM_DRIVER); + if (obj_priv->pages == NULL) { DRM_ERROR("Faled to allocate page list\n"); + obj_priv->pages_refcount--; return -ENOMEM; } @@ -1552,10 +1554,10 @@ i915_gem_object_get_page_list(struct drm_gem_object *obj) if (IS_ERR(page)) { ret = PTR_ERR(page); DRM_ERROR("read_mapping_page failed: %d\n", ret); - i915_gem_object_free_page_list(obj); + i915_gem_object_put_pages(obj); return ret; } - obj_priv->page_list[i] = page; + obj_priv->pages[i] = page; } return 0; } @@ -1878,7 +1880,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) DRM_INFO("Binding object of size %d at 0x%08x\n", obj->size, obj_priv->gtt_offset); #endif - ret = i915_gem_object_get_page_list(obj); + ret = i915_gem_object_get_pages(obj); if (ret) { drm_mm_put_block(obj_priv->gtt_space); obj_priv->gtt_space = NULL; @@ -1890,12 +1892,12 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) * into the GTT. */ obj_priv->agp_mem = drm_agp_bind_pages(dev, - obj_priv->page_list, + obj_priv->pages, page_count, obj_priv->gtt_offset, obj_priv->agp_type); if (obj_priv->agp_mem == NULL) { - i915_gem_object_free_page_list(obj); + i915_gem_object_put_pages(obj); drm_mm_put_block(obj_priv->gtt_space); obj_priv->gtt_space = NULL; return -ENOMEM; @@ -1922,10 +1924,10 @@ i915_gem_clflush_object(struct drm_gem_object *obj) * to GPU, and we can ignore the cache flush because it'll happen * again at bind time. */ - if (obj_priv->page_list == NULL) + if (obj_priv->pages == NULL) return; - drm_clflush_pages(obj_priv->page_list, obj->size / PAGE_SIZE); + drm_clflush_pages(obj_priv->pages, obj->size / PAGE_SIZE); } /** Flushes any GPU write domain for the object if it's dirty. */ @@ -2270,7 +2272,7 @@ i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj) for (i = 0; i <= (obj->size - 1) / PAGE_SIZE; i++) { if (obj_priv->page_cpu_valid[i]) continue; - drm_clflush_pages(obj_priv->page_list + i, 1); + drm_clflush_pages(obj_priv->pages + i, 1); } drm_agp_chipset_flush(dev); } @@ -2336,7 +2338,7 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, if (obj_priv->page_cpu_valid[i]) continue; - drm_clflush_pages(obj_priv->page_list + i, 1); + drm_clflush_pages(obj_priv->pages + i, 1); obj_priv->page_cpu_valid[i] = 1; } @@ -3304,7 +3306,7 @@ i915_gem_init_hws(struct drm_device *dev) dev_priv->status_gfx_addr = obj_priv->gtt_offset; - dev_priv->hw_status_page = kmap(obj_priv->page_list[0]); + dev_priv->hw_status_page = kmap(obj_priv->pages[0]); if (dev_priv->hw_status_page == NULL) { DRM_ERROR("Failed to map status page.\n"); memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); @@ -3334,7 +3336,7 @@ i915_gem_cleanup_hws(struct drm_device *dev) obj = dev_priv->hws_obj; obj_priv = obj->driver_private; - kunmap(obj_priv->page_list[0]); + kunmap(obj_priv->pages[0]); i915_gem_object_unpin(obj); drm_gem_object_unreference(obj); dev_priv->hws_obj = NULL; @@ -3637,20 +3639,20 @@ void i915_gem_detach_phys_object(struct drm_device *dev, if (!obj_priv->phys_obj) return; - ret = i915_gem_object_get_page_list(obj); + ret = i915_gem_object_get_pages(obj); if (ret) goto out; page_count = obj->size / PAGE_SIZE; for (i = 0; i < page_count; i++) { - char *dst = kmap_atomic(obj_priv->page_list[i], KM_USER0); + char *dst = kmap_atomic(obj_priv->pages[i], KM_USER0); char *src = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE); memcpy(dst, src, PAGE_SIZE); kunmap_atomic(dst, KM_USER0); } - drm_clflush_pages(obj_priv->page_list, page_count); + drm_clflush_pages(obj_priv->pages, page_count); drm_agp_chipset_flush(dev); out: obj_priv->phys_obj->cur_obj = NULL; @@ -3693,7 +3695,7 @@ i915_gem_attach_phys_object(struct drm_device *dev, obj_priv->phys_obj = dev_priv->mm.phys_objs[id - 1]; obj_priv->phys_obj->cur_obj = obj; - ret = i915_gem_object_get_page_list(obj); + ret = i915_gem_object_get_pages(obj); if (ret) { DRM_ERROR("failed to get page list\n"); goto out; @@ -3702,7 +3704,7 @@ i915_gem_attach_phys_object(struct drm_device *dev, page_count = obj->size / PAGE_SIZE; for (i = 0; i < page_count; i++) { - char *src = kmap_atomic(obj_priv->page_list[i], KM_USER0); + char *src = kmap_atomic(obj_priv->pages[i], KM_USER0); char *dst = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE); memcpy(dst, src, PAGE_SIZE); -- GitLab From 40123c1f8dd920dcff7a42cde5b351d7d0b0422e Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 9 Mar 2009 13:42:30 -0700 Subject: [PATCH 4813/4982] drm/i915: Fix lock order reversal in shmem pwrite path. Like the GTT pwrite path fix, this uses an optimistic path and a fallback to get_user_pages. Note that this means we have to stop using vfs_write and roll it ourselves. Signed-off-by: Eric Anholt Reviewed-by: Jesse Barnes --- drivers/gpu/drm/i915/i915_gem.c | 225 +++++++++++++++++++++++++++++--- 1 file changed, 205 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index b998d659fd9..bdc7326052d 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -136,6 +136,33 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data, return 0; } +static inline int +slow_shmem_copy(struct page *dst_page, + int dst_offset, + struct page *src_page, + int src_offset, + int length) +{ + char *dst_vaddr, *src_vaddr; + + dst_vaddr = kmap_atomic(dst_page, KM_USER0); + if (dst_vaddr == NULL) + return -ENOMEM; + + src_vaddr = kmap_atomic(src_page, KM_USER1); + if (src_vaddr == NULL) { + kunmap_atomic(dst_vaddr, KM_USER0); + return -ENOMEM; + } + + memcpy(dst_vaddr + dst_offset, src_vaddr + src_offset, length); + + kunmap_atomic(src_vaddr, KM_USER1); + kunmap_atomic(dst_vaddr, KM_USER0); + + return 0; +} + /** * Reads data from the object referenced by handle. * @@ -243,6 +270,23 @@ slow_kernel_write(struct io_mapping *mapping, return 0; } +static inline int +fast_shmem_write(struct page **pages, + loff_t page_base, int page_offset, + char __user *data, + int length) +{ + char __iomem *vaddr; + + vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0); + if (vaddr == NULL) + return -ENOMEM; + __copy_from_user_inatomic(vaddr + page_offset, data, length); + kunmap_atomic(vaddr, KM_USER0); + + return 0; +} + /** * This is the fast pwrite path, where we copy the data directly from the * user into the GTT, uncached. @@ -423,39 +467,175 @@ out_unpin_pages: return ret; } +/** + * This is the fast shmem pwrite path, which attempts to directly + * copy_from_user into the kmapped pages backing the object. + */ static int -i915_gem_shmem_pwrite(struct drm_device *dev, struct drm_gem_object *obj, - struct drm_i915_gem_pwrite *args, - struct drm_file *file_priv) +i915_gem_shmem_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj, + struct drm_i915_gem_pwrite *args, + struct drm_file *file_priv) { + struct drm_i915_gem_object *obj_priv = obj->driver_private; + ssize_t remain; + loff_t offset, page_base; + char __user *user_data; + int page_offset, page_length; int ret; - loff_t offset; - ssize_t written; + + user_data = (char __user *) (uintptr_t) args->data_ptr; + remain = args->size; mutex_lock(&dev->struct_mutex); + ret = i915_gem_object_get_pages(obj); + if (ret != 0) + goto fail_unlock; + ret = i915_gem_object_set_to_cpu_domain(obj, 1); - if (ret) { - mutex_unlock(&dev->struct_mutex); - return ret; + if (ret != 0) + goto fail_put_pages; + + obj_priv = obj->driver_private; + offset = args->offset; + obj_priv->dirty = 1; + + while (remain > 0) { + /* Operation in this page + * + * page_base = page offset within aperture + * page_offset = offset within page + * page_length = bytes to copy for this page + */ + page_base = (offset & ~(PAGE_SIZE-1)); + page_offset = offset & (PAGE_SIZE-1); + page_length = remain; + if ((page_offset + remain) > PAGE_SIZE) + page_length = PAGE_SIZE - page_offset; + + ret = fast_shmem_write(obj_priv->pages, + page_base, page_offset, + user_data, page_length); + if (ret) + goto fail_put_pages; + + remain -= page_length; + user_data += page_length; + offset += page_length; } +fail_put_pages: + i915_gem_object_put_pages(obj); +fail_unlock: + mutex_unlock(&dev->struct_mutex); + + return ret; +} + +/** + * This is the fallback shmem pwrite path, which uses get_user_pages to pin + * the memory and maps it using kmap_atomic for copying. + * + * This avoids taking mmap_sem for faulting on the user's address while the + * struct_mutex is held. + */ +static int +i915_gem_shmem_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj, + struct drm_i915_gem_pwrite *args, + struct drm_file *file_priv) +{ + struct drm_i915_gem_object *obj_priv = obj->driver_private; + struct mm_struct *mm = current->mm; + struct page **user_pages; + ssize_t remain; + loff_t offset, pinned_pages, i; + loff_t first_data_page, last_data_page, num_pages; + int shmem_page_index, shmem_page_offset; + int data_page_index, data_page_offset; + int page_length; + int ret; + uint64_t data_ptr = args->data_ptr; + + remain = args->size; + + /* Pin the user pages containing the data. We can't fault while + * holding the struct mutex, and all of the pwrite implementations + * want to hold it while dereferencing the user data. + */ + first_data_page = data_ptr / PAGE_SIZE; + last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE; + num_pages = last_data_page - first_data_page + 1; + + user_pages = kcalloc(num_pages, sizeof(struct page *), GFP_KERNEL); + if (user_pages == NULL) + return -ENOMEM; + + down_read(&mm->mmap_sem); + pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr, + num_pages, 0, 0, user_pages, NULL); + up_read(&mm->mmap_sem); + if (pinned_pages < num_pages) { + ret = -EFAULT; + goto fail_put_user_pages; + } + + mutex_lock(&dev->struct_mutex); + + ret = i915_gem_object_get_pages(obj); + if (ret != 0) + goto fail_unlock; + + ret = i915_gem_object_set_to_cpu_domain(obj, 1); + if (ret != 0) + goto fail_put_pages; + + obj_priv = obj->driver_private; offset = args->offset; + obj_priv->dirty = 1; - written = vfs_write(obj->filp, - (char __user *)(uintptr_t) args->data_ptr, - args->size, &offset); - if (written != args->size) { - mutex_unlock(&dev->struct_mutex); - if (written < 0) - return written; - else - return -EINVAL; + while (remain > 0) { + /* Operation in this page + * + * shmem_page_index = page number within shmem file + * shmem_page_offset = offset within page in shmem file + * data_page_index = page number in get_user_pages return + * data_page_offset = offset with data_page_index page. + * page_length = bytes to copy for this page + */ + shmem_page_index = offset / PAGE_SIZE; + shmem_page_offset = offset & ~PAGE_MASK; + data_page_index = data_ptr / PAGE_SIZE - first_data_page; + data_page_offset = data_ptr & ~PAGE_MASK; + + page_length = remain; + if ((shmem_page_offset + page_length) > PAGE_SIZE) + page_length = PAGE_SIZE - shmem_page_offset; + if ((data_page_offset + page_length) > PAGE_SIZE) + page_length = PAGE_SIZE - data_page_offset; + + ret = slow_shmem_copy(obj_priv->pages[shmem_page_index], + shmem_page_offset, + user_pages[data_page_index], + data_page_offset, + page_length); + if (ret) + goto fail_put_pages; + + remain -= page_length; + data_ptr += page_length; + offset += page_length; } +fail_put_pages: + i915_gem_object_put_pages(obj); +fail_unlock: mutex_unlock(&dev->struct_mutex); +fail_put_user_pages: + for (i = 0; i < pinned_pages; i++) + page_cache_release(user_pages[i]); + kfree(user_pages); - return 0; + return ret; } /** @@ -502,8 +682,13 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, ret = i915_gem_gtt_pwrite_slow(dev, obj, args, file_priv); } - } else - ret = i915_gem_shmem_pwrite(dev, obj, args, file_priv); + } else { + ret = i915_gem_shmem_pwrite_fast(dev, obj, args, file_priv); + if (ret == -EFAULT) { + ret = i915_gem_shmem_pwrite_slow(dev, obj, args, + file_priv); + } + } #if WATCH_PWRITE if (ret) -- GitLab From eb01459fbbccb4ca0b879cbfc97e33ac6eabf975 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 10 Mar 2009 11:44:52 -0700 Subject: [PATCH 4814/4982] drm/i915: Fix lock order reversal in shmem pread path. Signed-off-by: Eric Anholt Reviewed-by: Jesse Barnes --- drivers/gpu/drm/i915/i915_gem.c | 221 ++++++++++++++++++++++++++++---- 1 file changed, 195 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index bdc7326052d..010af908bdb 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -136,6 +136,24 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data, return 0; } +static inline int +fast_shmem_read(struct page **pages, + loff_t page_base, int page_offset, + char __user *data, + int length) +{ + char __iomem *vaddr; + int ret; + + vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0); + if (vaddr == NULL) + return -ENOMEM; + ret = __copy_to_user_inatomic(data, vaddr + page_offset, length); + kunmap_atomic(vaddr, KM_USER0); + + return ret; +} + static inline int slow_shmem_copy(struct page *dst_page, int dst_offset, @@ -163,6 +181,179 @@ slow_shmem_copy(struct page *dst_page, return 0; } +/** + * This is the fast shmem pread path, which attempts to copy_from_user directly + * from the backing pages of the object to the user's address space. On a + * fault, it fails so we can fall back to i915_gem_shmem_pwrite_slow(). + */ +static int +i915_gem_shmem_pread_fast(struct drm_device *dev, struct drm_gem_object *obj, + struct drm_i915_gem_pread *args, + struct drm_file *file_priv) +{ + struct drm_i915_gem_object *obj_priv = obj->driver_private; + ssize_t remain; + loff_t offset, page_base; + char __user *user_data; + int page_offset, page_length; + int ret; + + user_data = (char __user *) (uintptr_t) args->data_ptr; + remain = args->size; + + mutex_lock(&dev->struct_mutex); + + ret = i915_gem_object_get_pages(obj); + if (ret != 0) + goto fail_unlock; + + ret = i915_gem_object_set_cpu_read_domain_range(obj, args->offset, + args->size); + if (ret != 0) + goto fail_put_pages; + + obj_priv = obj->driver_private; + offset = args->offset; + + while (remain > 0) { + /* Operation in this page + * + * page_base = page offset within aperture + * page_offset = offset within page + * page_length = bytes to copy for this page + */ + page_base = (offset & ~(PAGE_SIZE-1)); + page_offset = offset & (PAGE_SIZE-1); + page_length = remain; + if ((page_offset + remain) > PAGE_SIZE) + page_length = PAGE_SIZE - page_offset; + + ret = fast_shmem_read(obj_priv->pages, + page_base, page_offset, + user_data, page_length); + if (ret) + goto fail_put_pages; + + remain -= page_length; + user_data += page_length; + offset += page_length; + } + +fail_put_pages: + i915_gem_object_put_pages(obj); +fail_unlock: + mutex_unlock(&dev->struct_mutex); + + return ret; +} + +/** + * This is the fallback shmem pread path, which allocates temporary storage + * in kernel space to copy_to_user into outside of the struct_mutex, so we + * can copy out of the object's backing pages while holding the struct mutex + * and not take page faults. + */ +static int +i915_gem_shmem_pread_slow(struct drm_device *dev, struct drm_gem_object *obj, + struct drm_i915_gem_pread *args, + struct drm_file *file_priv) +{ + struct drm_i915_gem_object *obj_priv = obj->driver_private; + struct mm_struct *mm = current->mm; + struct page **user_pages; + ssize_t remain; + loff_t offset, pinned_pages, i; + loff_t first_data_page, last_data_page, num_pages; + int shmem_page_index, shmem_page_offset; + int data_page_index, data_page_offset; + int page_length; + int ret; + uint64_t data_ptr = args->data_ptr; + + remain = args->size; + + /* Pin the user pages containing the data. We can't fault while + * holding the struct mutex, yet we want to hold it while + * dereferencing the user data. + */ + first_data_page = data_ptr / PAGE_SIZE; + last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE; + num_pages = last_data_page - first_data_page + 1; + + user_pages = kcalloc(num_pages, sizeof(struct page *), GFP_KERNEL); + if (user_pages == NULL) + return -ENOMEM; + + down_read(&mm->mmap_sem); + pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr, + num_pages, 0, 0, user_pages, NULL); + up_read(&mm->mmap_sem); + if (pinned_pages < num_pages) { + ret = -EFAULT; + goto fail_put_user_pages; + } + + mutex_lock(&dev->struct_mutex); + + ret = i915_gem_object_get_pages(obj); + if (ret != 0) + goto fail_unlock; + + ret = i915_gem_object_set_cpu_read_domain_range(obj, args->offset, + args->size); + if (ret != 0) + goto fail_put_pages; + + obj_priv = obj->driver_private; + offset = args->offset; + + while (remain > 0) { + /* Operation in this page + * + * shmem_page_index = page number within shmem file + * shmem_page_offset = offset within page in shmem file + * data_page_index = page number in get_user_pages return + * data_page_offset = offset with data_page_index page. + * page_length = bytes to copy for this page + */ + shmem_page_index = offset / PAGE_SIZE; + shmem_page_offset = offset & ~PAGE_MASK; + data_page_index = data_ptr / PAGE_SIZE - first_data_page; + data_page_offset = data_ptr & ~PAGE_MASK; + + page_length = remain; + if ((shmem_page_offset + page_length) > PAGE_SIZE) + page_length = PAGE_SIZE - shmem_page_offset; + if ((data_page_offset + page_length) > PAGE_SIZE) + page_length = PAGE_SIZE - data_page_offset; + + ret = slow_shmem_copy(user_pages[data_page_index], + data_page_offset, + obj_priv->pages[shmem_page_index], + shmem_page_offset, + page_length); + if (ret) + goto fail_put_pages; + + remain -= page_length; + data_ptr += page_length; + offset += page_length; + } + +fail_put_pages: + i915_gem_object_put_pages(obj); +fail_unlock: + mutex_unlock(&dev->struct_mutex); +fail_put_user_pages: + for (i = 0; i < pinned_pages; i++) { + SetPageDirty(user_pages[i]); + page_cache_release(user_pages[i]); + } + kfree(user_pages); + + return ret; +} + /** * Reads data from the object referenced by handle. * @@ -175,8 +366,6 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, struct drm_i915_gem_pread *args = data; struct drm_gem_object *obj; struct drm_i915_gem_object *obj_priv; - ssize_t read; - loff_t offset; int ret; obj = drm_gem_object_lookup(dev, file_priv, args->handle); @@ -194,33 +383,13 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, return -EINVAL; } - mutex_lock(&dev->struct_mutex); - - ret = i915_gem_object_set_cpu_read_domain_range(obj, args->offset, - args->size); - if (ret != 0) { - drm_gem_object_unreference(obj); - mutex_unlock(&dev->struct_mutex); - return ret; - } - - offset = args->offset; - - read = vfs_read(obj->filp, (char __user *)(uintptr_t)args->data_ptr, - args->size, &offset); - if (read != args->size) { - drm_gem_object_unreference(obj); - mutex_unlock(&dev->struct_mutex); - if (read < 0) - return read; - else - return -EINVAL; - } + ret = i915_gem_shmem_pread_fast(dev, obj, args, file_priv); + if (ret != 0) + ret = i915_gem_shmem_pread_slow(dev, obj, args, file_priv); drm_gem_object_unreference(obj); - mutex_unlock(&dev->struct_mutex); - return 0; + return ret; } /* This is the fast write path which cannot handle -- GitLab From 201361a54ed187d8595a283e3a4ddb213bc8323b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 11 Mar 2009 12:30:04 -0700 Subject: [PATCH 4815/4982] drm/i915: Fix lock order reversal with cliprects and cmdbuf in non-DRI2 paths. This introduces allocation in the batch submission path that wasn't there previously, but these are compatibility paths so we care about simplicity more than performance. kernel.org bug #12419. Signed-off-by: Eric Anholt Reviewed-by: Keith Packard Acked-by: Jesse Barnes --- drivers/gpu/drm/i915/i915_dma.c | 107 ++++++++++++++++++++++---------- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 27 ++++++-- 3 files changed, 97 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 6d21b9e48b8..ae83fe0ab37 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -356,7 +356,7 @@ static int validate_cmd(int cmd) return ret; } -static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwords) +static int i915_emit_cmds(struct drm_device * dev, int *buffer, int dwords) { drm_i915_private_t *dev_priv = dev->dev_private; int i; @@ -370,8 +370,7 @@ static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwor for (i = 0; i < dwords;) { int cmd, sz; - if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd))) - return -EINVAL; + cmd = buffer[i]; if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords) return -EINVAL; @@ -379,11 +378,7 @@ static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwor OUT_RING(cmd); while (++i, --sz) { - if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], - sizeof(cmd))) { - return -EINVAL; - } - OUT_RING(cmd); + OUT_RING(buffer[i]); } } @@ -397,17 +392,13 @@ static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwor int i915_emit_box(struct drm_device *dev, - struct drm_clip_rect __user *boxes, + struct drm_clip_rect *boxes, int i, int DR1, int DR4) { drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_clip_rect box; + struct drm_clip_rect box = boxes[i]; RING_LOCALS; - if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) { - return -EFAULT; - } - if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) { DRM_ERROR("Bad box %d,%d..%d,%d\n", box.x1, box.y1, box.x2, box.y2); @@ -460,7 +451,9 @@ static void i915_emit_breadcrumb(struct drm_device *dev) } static int i915_dispatch_cmdbuffer(struct drm_device * dev, - drm_i915_cmdbuffer_t * cmd) + drm_i915_cmdbuffer_t *cmd, + struct drm_clip_rect *cliprects, + void *cmdbuf) { int nbox = cmd->num_cliprects; int i = 0, count, ret; @@ -476,13 +469,13 @@ static int i915_dispatch_cmdbuffer(struct drm_device * dev, for (i = 0; i < count; i++) { if (i < nbox) { - ret = i915_emit_box(dev, cmd->cliprects, i, + ret = i915_emit_box(dev, cliprects, i, cmd->DR1, cmd->DR4); if (ret) return ret; } - ret = i915_emit_cmds(dev, (int __user *)cmd->buf, cmd->sz / 4); + ret = i915_emit_cmds(dev, cmdbuf, cmd->sz / 4); if (ret) return ret; } @@ -492,10 +485,10 @@ static int i915_dispatch_cmdbuffer(struct drm_device * dev, } static int i915_dispatch_batchbuffer(struct drm_device * dev, - drm_i915_batchbuffer_t * batch) + drm_i915_batchbuffer_t * batch, + struct drm_clip_rect *cliprects) { drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_clip_rect __user *boxes = batch->cliprects; int nbox = batch->num_cliprects; int i = 0, count; RING_LOCALS; @@ -511,7 +504,7 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev, for (i = 0; i < count; i++) { if (i < nbox) { - int ret = i915_emit_box(dev, boxes, i, + int ret = i915_emit_box(dev, cliprects, i, batch->DR1, batch->DR4); if (ret) return ret; @@ -626,6 +619,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, master_priv->sarea_priv; drm_i915_batchbuffer_t *batch = data; int ret; + struct drm_clip_rect *cliprects = NULL; if (!dev_priv->allow_batchbuffer) { DRM_ERROR("Batchbuffer ioctl disabled\n"); @@ -637,17 +631,35 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, RING_LOCK_TEST_WITH_RETURN(dev, file_priv); - if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects, - batch->num_cliprects * - sizeof(struct drm_clip_rect))) - return -EFAULT; + if (batch->num_cliprects < 0) + return -EINVAL; + + if (batch->num_cliprects) { + cliprects = drm_calloc(batch->num_cliprects, + sizeof(struct drm_clip_rect), + DRM_MEM_DRIVER); + if (cliprects == NULL) + return -ENOMEM; + + ret = copy_from_user(cliprects, batch->cliprects, + batch->num_cliprects * + sizeof(struct drm_clip_rect)); + if (ret != 0) + goto fail_free; + } mutex_lock(&dev->struct_mutex); - ret = i915_dispatch_batchbuffer(dev, batch); + ret = i915_dispatch_batchbuffer(dev, batch, cliprects); mutex_unlock(&dev->struct_mutex); if (sarea_priv) sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); + +fail_free: + drm_free(cliprects, + batch->num_cliprects * sizeof(struct drm_clip_rect), + DRM_MEM_DRIVER); + return ret; } @@ -659,6 +671,8 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) master_priv->sarea_priv; drm_i915_cmdbuffer_t *cmdbuf = data; + struct drm_clip_rect *cliprects = NULL; + void *batch_data; int ret; DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n", @@ -666,25 +680,50 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, RING_LOCK_TEST_WITH_RETURN(dev, file_priv); - if (cmdbuf->num_cliprects && - DRM_VERIFYAREA_READ(cmdbuf->cliprects, - cmdbuf->num_cliprects * - sizeof(struct drm_clip_rect))) { - DRM_ERROR("Fault accessing cliprects\n"); - return -EFAULT; + if (cmdbuf->num_cliprects < 0) + return -EINVAL; + + batch_data = drm_alloc(cmdbuf->sz, DRM_MEM_DRIVER); + if (batch_data == NULL) + return -ENOMEM; + + ret = copy_from_user(batch_data, cmdbuf->buf, cmdbuf->sz); + if (ret != 0) + goto fail_batch_free; + + if (cmdbuf->num_cliprects) { + cliprects = drm_calloc(cmdbuf->num_cliprects, + sizeof(struct drm_clip_rect), + DRM_MEM_DRIVER); + if (cliprects == NULL) + goto fail_batch_free; + + ret = copy_from_user(cliprects, cmdbuf->cliprects, + cmdbuf->num_cliprects * + sizeof(struct drm_clip_rect)); + if (ret != 0) + goto fail_clip_free; } mutex_lock(&dev->struct_mutex); - ret = i915_dispatch_cmdbuffer(dev, cmdbuf); + ret = i915_dispatch_cmdbuffer(dev, cmdbuf, cliprects, batch_data); mutex_unlock(&dev->struct_mutex); if (ret) { DRM_ERROR("i915_dispatch_cmdbuffer failed\n"); - return ret; + goto fail_batch_free; } if (sarea_priv) sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); - return 0; + +fail_batch_free: + drm_free(batch_data, cmdbuf->sz, DRM_MEM_DRIVER); +fail_clip_free: + drm_free(cliprects, + cmdbuf->num_cliprects * sizeof(struct drm_clip_rect), + DRM_MEM_DRIVER); + + return ret; } static int i915_flip_bufs(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 75e33844146..2c02ce6b2b9 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -520,7 +520,7 @@ extern int i915_driver_device_is_agp(struct drm_device * dev); extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); extern int i915_emit_box(struct drm_device *dev, - struct drm_clip_rect __user *boxes, + struct drm_clip_rect *boxes, int i, int DR1, int DR4); /* i915_irq.c */ diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 010af908bdb..2bda15197cc 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2891,11 +2891,10 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, static int i915_dispatch_gem_execbuffer(struct drm_device *dev, struct drm_i915_gem_execbuffer *exec, + struct drm_clip_rect *cliprects, uint64_t exec_offset) { drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_clip_rect __user *boxes = (struct drm_clip_rect __user *) - (uintptr_t) exec->cliprects_ptr; int nbox = exec->num_cliprects; int i = 0, count; uint32_t exec_start, exec_len; @@ -2916,7 +2915,7 @@ i915_dispatch_gem_execbuffer(struct drm_device *dev, for (i = 0; i < count; i++) { if (i < nbox) { - int ret = i915_emit_box(dev, boxes, i, + int ret = i915_emit_box(dev, cliprects, i, exec->DR1, exec->DR4); if (ret) return ret; @@ -2983,6 +2982,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, struct drm_gem_object **object_list = NULL; struct drm_gem_object *batch_obj; struct drm_i915_gem_object *obj_priv; + struct drm_clip_rect *cliprects = NULL; int ret, i, pinned = 0; uint64_t exec_offset; uint32_t seqno, flush_domains; @@ -3019,6 +3019,23 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, goto pre_mutex_err; } + if (args->num_cliprects != 0) { + cliprects = drm_calloc(args->num_cliprects, sizeof(*cliprects), + DRM_MEM_DRIVER); + if (cliprects == NULL) + goto pre_mutex_err; + + ret = copy_from_user(cliprects, + (struct drm_clip_rect __user *) + (uintptr_t) args->cliprects_ptr, + sizeof(*cliprects) * args->num_cliprects); + if (ret != 0) { + DRM_ERROR("copy %d cliprects failed: %d\n", + args->num_cliprects, ret); + goto pre_mutex_err; + } + } + mutex_lock(&dev->struct_mutex); i915_verify_inactive(dev, __FILE__, __LINE__); @@ -3155,7 +3172,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, #endif /* Exec the batchbuffer */ - ret = i915_dispatch_gem_execbuffer(dev, args, exec_offset); + ret = i915_dispatch_gem_execbuffer(dev, args, cliprects, exec_offset); if (ret) { DRM_ERROR("dispatch failed %d\n", ret); goto err; @@ -3224,6 +3241,8 @@ pre_mutex_err: DRM_MEM_DRIVER); drm_free(exec_list, sizeof(*exec_list) * args->buffer_count, DRM_MEM_DRIVER); + drm_free(cliprects, sizeof(*cliprects) * args->num_cliprects, + DRM_MEM_DRIVER); return ret; } -- GitLab From 40a5f0decdf050785ebd62b36ad48c869ee4b384 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 12 Mar 2009 11:23:52 -0700 Subject: [PATCH 4816/4982] drm/i915: Fix lock order reversal in GEM relocation entry copying. Signed-off-by: Eric Anholt Reviewed-by: Keith Packard --- drivers/gpu/drm/i915/i915_gem.c | 187 +++++++++++++++++++++++--------- 1 file changed, 133 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 2bda15197cc..f135c903305 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2713,12 +2713,11 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, static int i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, struct drm_file *file_priv, - struct drm_i915_gem_exec_object *entry) + struct drm_i915_gem_exec_object *entry, + struct drm_i915_gem_relocation_entry *relocs) { struct drm_device *dev = obj->dev; drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_relocation_entry reloc; - struct drm_i915_gem_relocation_entry __user *relocs; struct drm_i915_gem_object *obj_priv = obj->driver_private; int i, ret; void __iomem *reloc_page; @@ -2730,25 +2729,18 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, entry->offset = obj_priv->gtt_offset; - relocs = (struct drm_i915_gem_relocation_entry __user *) - (uintptr_t) entry->relocs_ptr; /* Apply the relocations, using the GTT aperture to avoid cache * flushing requirements. */ for (i = 0; i < entry->relocation_count; i++) { + struct drm_i915_gem_relocation_entry *reloc= &relocs[i]; struct drm_gem_object *target_obj; struct drm_i915_gem_object *target_obj_priv; uint32_t reloc_val, reloc_offset; uint32_t __iomem *reloc_entry; - ret = copy_from_user(&reloc, relocs + i, sizeof(reloc)); - if (ret != 0) { - i915_gem_object_unpin(obj); - return ret; - } - target_obj = drm_gem_object_lookup(obj->dev, file_priv, - reloc.target_handle); + reloc->target_handle); if (target_obj == NULL) { i915_gem_object_unpin(obj); return -EBADF; @@ -2760,53 +2752,53 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, */ if (target_obj_priv->gtt_space == NULL) { DRM_ERROR("No GTT space found for object %d\n", - reloc.target_handle); + reloc->target_handle); drm_gem_object_unreference(target_obj); i915_gem_object_unpin(obj); return -EINVAL; } - if (reloc.offset > obj->size - 4) { + if (reloc->offset > obj->size - 4) { DRM_ERROR("Relocation beyond object bounds: " "obj %p target %d offset %d size %d.\n", - obj, reloc.target_handle, - (int) reloc.offset, (int) obj->size); + obj, reloc->target_handle, + (int) reloc->offset, (int) obj->size); drm_gem_object_unreference(target_obj); i915_gem_object_unpin(obj); return -EINVAL; } - if (reloc.offset & 3) { + if (reloc->offset & 3) { DRM_ERROR("Relocation not 4-byte aligned: " "obj %p target %d offset %d.\n", - obj, reloc.target_handle, - (int) reloc.offset); + obj, reloc->target_handle, + (int) reloc->offset); drm_gem_object_unreference(target_obj); i915_gem_object_unpin(obj); return -EINVAL; } - if (reloc.write_domain & I915_GEM_DOMAIN_CPU || - reloc.read_domains & I915_GEM_DOMAIN_CPU) { + if (reloc->write_domain & I915_GEM_DOMAIN_CPU || + reloc->read_domains & I915_GEM_DOMAIN_CPU) { DRM_ERROR("reloc with read/write CPU domains: " "obj %p target %d offset %d " "read %08x write %08x", - obj, reloc.target_handle, - (int) reloc.offset, - reloc.read_domains, - reloc.write_domain); + obj, reloc->target_handle, + (int) reloc->offset, + reloc->read_domains, + reloc->write_domain); drm_gem_object_unreference(target_obj); i915_gem_object_unpin(obj); return -EINVAL; } - if (reloc.write_domain && target_obj->pending_write_domain && - reloc.write_domain != target_obj->pending_write_domain) { + if (reloc->write_domain && target_obj->pending_write_domain && + reloc->write_domain != target_obj->pending_write_domain) { DRM_ERROR("Write domain conflict: " "obj %p target %d offset %d " "new %08x old %08x\n", - obj, reloc.target_handle, - (int) reloc.offset, - reloc.write_domain, + obj, reloc->target_handle, + (int) reloc->offset, + reloc->write_domain, target_obj->pending_write_domain); drm_gem_object_unreference(target_obj); i915_gem_object_unpin(obj); @@ -2819,22 +2811,22 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, "presumed %08x delta %08x\n", __func__, obj, - (int) reloc.offset, - (int) reloc.target_handle, - (int) reloc.read_domains, - (int) reloc.write_domain, + (int) reloc->offset, + (int) reloc->target_handle, + (int) reloc->read_domains, + (int) reloc->write_domain, (int) target_obj_priv->gtt_offset, - (int) reloc.presumed_offset, - reloc.delta); + (int) reloc->presumed_offset, + reloc->delta); #endif - target_obj->pending_read_domains |= reloc.read_domains; - target_obj->pending_write_domain |= reloc.write_domain; + target_obj->pending_read_domains |= reloc->read_domains; + target_obj->pending_write_domain |= reloc->write_domain; /* If the relocation already has the right value in it, no * more work needs to be done. */ - if (target_obj_priv->gtt_offset == reloc.presumed_offset) { + if (target_obj_priv->gtt_offset == reloc->presumed_offset) { drm_gem_object_unreference(target_obj); continue; } @@ -2849,32 +2841,26 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, /* Map the page containing the relocation we're going to * perform. */ - reloc_offset = obj_priv->gtt_offset + reloc.offset; + reloc_offset = obj_priv->gtt_offset + reloc->offset; reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, (reloc_offset & ~(PAGE_SIZE - 1))); reloc_entry = (uint32_t __iomem *)(reloc_page + (reloc_offset & (PAGE_SIZE - 1))); - reloc_val = target_obj_priv->gtt_offset + reloc.delta; + reloc_val = target_obj_priv->gtt_offset + reloc->delta; #if WATCH_BUF DRM_INFO("Applied relocation: %p@0x%08x %08x -> %08x\n", - obj, (unsigned int) reloc.offset, + obj, (unsigned int) reloc->offset, readl(reloc_entry), reloc_val); #endif writel(reloc_val, reloc_entry); io_mapping_unmap_atomic(reloc_page); - /* Write the updated presumed offset for this entry back out - * to the user. + /* The updated presumed offset for this entry will be + * copied back out to the user. */ - reloc.presumed_offset = target_obj_priv->gtt_offset; - ret = copy_to_user(relocs + i, &reloc, sizeof(reloc)); - if (ret != 0) { - drm_gem_object_unreference(target_obj); - i915_gem_object_unpin(obj); - return ret; - } + reloc->presumed_offset = target_obj_priv->gtt_offset; drm_gem_object_unreference(target_obj); } @@ -2971,6 +2957,75 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file_priv) return ret; } +static int +i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list, + uint32_t buffer_count, + struct drm_i915_gem_relocation_entry **relocs) +{ + uint32_t reloc_count = 0, reloc_index = 0, i; + int ret; + + *relocs = NULL; + for (i = 0; i < buffer_count; i++) { + if (reloc_count + exec_list[i].relocation_count < reloc_count) + return -EINVAL; + reloc_count += exec_list[i].relocation_count; + } + + *relocs = drm_calloc(reloc_count, sizeof(**relocs), DRM_MEM_DRIVER); + if (*relocs == NULL) + return -ENOMEM; + + for (i = 0; i < buffer_count; i++) { + struct drm_i915_gem_relocation_entry __user *user_relocs; + + user_relocs = (void __user *)(uintptr_t)exec_list[i].relocs_ptr; + + ret = copy_from_user(&(*relocs)[reloc_index], + user_relocs, + exec_list[i].relocation_count * + sizeof(**relocs)); + if (ret != 0) { + drm_free(*relocs, reloc_count * sizeof(**relocs), + DRM_MEM_DRIVER); + *relocs = NULL; + return ret; + } + + reloc_index += exec_list[i].relocation_count; + } + + return ret; +} + +static int +i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object *exec_list, + uint32_t buffer_count, + struct drm_i915_gem_relocation_entry *relocs) +{ + uint32_t reloc_count = 0, i; + int ret; + + for (i = 0; i < buffer_count; i++) { + struct drm_i915_gem_relocation_entry __user *user_relocs; + + user_relocs = (void __user *)(uintptr_t)exec_list[i].relocs_ptr; + + if (ret == 0) { + ret = copy_to_user(user_relocs, + &relocs[reloc_count], + exec_list[i].relocation_count * + sizeof(*relocs)); + } + + reloc_count += exec_list[i].relocation_count; + } + + drm_free(relocs, reloc_count * sizeof(*relocs), DRM_MEM_DRIVER); + + return ret; +} + int i915_gem_execbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -2983,9 +3038,10 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, struct drm_gem_object *batch_obj; struct drm_i915_gem_object *obj_priv; struct drm_clip_rect *cliprects = NULL; - int ret, i, pinned = 0; + struct drm_i915_gem_relocation_entry *relocs; + int ret, ret2, i, pinned = 0; uint64_t exec_offset; - uint32_t seqno, flush_domains; + uint32_t seqno, flush_domains, reloc_index; int pin_tries; #if WATCH_EXEC @@ -3036,6 +3092,11 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, } } + ret = i915_gem_get_relocs_from_user(exec_list, args->buffer_count, + &relocs); + if (ret != 0) + goto pre_mutex_err; + mutex_lock(&dev->struct_mutex); i915_verify_inactive(dev, __FILE__, __LINE__); @@ -3078,15 +3139,19 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, /* Pin and relocate */ for (pin_tries = 0; ; pin_tries++) { ret = 0; + reloc_index = 0; + for (i = 0; i < args->buffer_count; i++) { object_list[i]->pending_read_domains = 0; object_list[i]->pending_write_domain = 0; ret = i915_gem_object_pin_and_relocate(object_list[i], file_priv, - &exec_list[i]); + &exec_list[i], + &relocs[reloc_index]); if (ret) break; pinned = i + 1; + reloc_index += exec_list[i].relocation_count; } /* success */ if (ret == 0) @@ -3236,6 +3301,20 @@ err: args->buffer_count, ret); } + /* Copy the updated relocations out regardless of current error + * state. Failure to update the relocs would mean that the next + * time userland calls execbuf, it would do so with presumed offset + * state that didn't match the actual object state. + */ + ret2 = i915_gem_put_relocs_to_user(exec_list, args->buffer_count, + relocs); + if (ret2 != 0) { + DRM_ERROR("Failed to copy relocations back out: %d\n", ret2); + + if (ret == 0) + ret = ret2; + } + pre_mutex_err: drm_free(object_list, sizeof(*object_list) * args->buffer_count, DRM_MEM_DRIVER); -- GitLab From 28a62277e06f93729d0340d9659153dcfbdbe16d Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Tue, 17 Feb 2009 20:08:49 -0500 Subject: [PATCH 4817/4982] drm: Convert proc files to seq_file and introduce debugfs The old mechanism to formatting proc files is extremely ugly. The seq_file API was designed specifically for cases like this and greatly simplifies the process. Also, most of the files in /proc really don't belong there. This patch introduces the infrastructure for putting these into debugfs and exposes all of the proc files in debugfs as well. Signed-off-by: Ben Gamari Signed-off-by: Eric Anholt --- drivers/gpu/drm/Makefile | 3 +- drivers/gpu/drm/drm_debugfs.c | 235 +++++++++++ drivers/gpu/drm/drm_drv.c | 12 +- drivers/gpu/drm/drm_info.c | 328 ++++++++++++++++ drivers/gpu/drm/drm_proc.c | 721 ++++++---------------------------- drivers/gpu/drm/drm_stub.c | 15 +- include/drm/drmP.h | 77 +++- 7 files changed, 776 insertions(+), 615 deletions(-) create mode 100644 drivers/gpu/drm/drm_debugfs.c create mode 100644 drivers/gpu/drm/drm_info.c diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 30022c4a5c1..4ec5061fa58 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -10,7 +10,8 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \ drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \ drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \ drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \ - drm_crtc.o drm_crtc_helper.o drm_modes.o drm_edid.o + drm_crtc.o drm_crtc_helper.o drm_modes.o drm_edid.o \ + drm_info.o drm_debugfs.o drm-$(CONFIG_COMPAT) += drm_ioc32.o diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c new file mode 100644 index 00000000000..c77c6c6d9d2 --- /dev/null +++ b/drivers/gpu/drm/drm_debugfs.c @@ -0,0 +1,235 @@ +/** + * \file drm_debugfs.c + * debugfs support for DRM + * + * \author Ben Gamari + */ + +/* + * Created: Sun Dec 21 13:08:50 2008 by bgamari@gmail.com + * + * Copyright 2008 Ben Gamari + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include "drmP.h" + +#if defined(CONFIG_DEBUG_FS) + +/*************************************************** + * Initialization, etc. + **************************************************/ + +static struct drm_info_list drm_debugfs_list[] = { + {"name", drm_name_info, 0}, + {"vm", drm_vm_info, 0}, + {"clients", drm_clients_info, 0}, + {"queues", drm_queues_info, 0}, + {"bufs", drm_bufs_info, 0}, + {"gem_names", drm_gem_name_info, DRIVER_GEM}, + {"gem_objects", drm_gem_object_info, DRIVER_GEM}, +#if DRM_DEBUG_CODE + {"vma", drm_vma_info, 0}, +#endif +}; +#define DRM_DEBUGFS_ENTRIES ARRAY_SIZE(drm_debugfs_list) + + +static int drm_debugfs_open(struct inode *inode, struct file *file) +{ + struct drm_info_node *node = inode->i_private; + + return single_open(file, node->info_ent->show, node); +} + + +static const struct file_operations drm_debugfs_fops = { + .owner = THIS_MODULE, + .open = drm_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + + +/** + * Initialize a given set of debugfs files for a device + * + * \param files The array of files to create + * \param count The number of files given + * \param root DRI debugfs dir entry. + * \param minor device minor number + * \return Zero on success, non-zero on failure + * + * Create a given set of debugfs files represented by an array of + * gdm_debugfs_lists in the given root directory. + */ +int drm_debugfs_create_files(struct drm_info_list *files, int count, + struct dentry *root, struct drm_minor *minor) +{ + struct drm_device *dev = minor->dev; + struct dentry *ent; + struct drm_info_node *tmp; + char name[64]; + int i, ret; + + for (i = 0; i < count; i++) { + u32 features = files[i].driver_features; + + if (features != 0 && + (dev->driver->driver_features & features) != features) + continue; + + tmp = drm_alloc(sizeof(struct drm_info_node), + _DRM_DRIVER); + ent = debugfs_create_file(files[i].name, S_IFREG | S_IRUGO, + root, tmp, &drm_debugfs_fops); + if (!ent) { + DRM_ERROR("Cannot create /debugfs/dri/%s/%s\n", + name, files[i].name); + drm_free(tmp, sizeof(struct drm_info_node), + _DRM_DRIVER); + ret = -1; + goto fail; + } + + tmp->minor = minor; + tmp->dent = ent; + tmp->info_ent = &files[i]; + list_add(&(tmp->list), &(minor->debugfs_nodes.list)); + } + return 0; + +fail: + drm_debugfs_remove_files(files, count, minor); + return ret; +} +EXPORT_SYMBOL(drm_debugfs_create_files); + +/** + * Initialize the DRI debugfs filesystem for a device + * + * \param dev DRM device + * \param minor device minor number + * \param root DRI debugfs dir entry. + * + * Create the DRI debugfs root entry "/debugfs/dri", the device debugfs root entry + * "/debugfs/dri/%minor%/", and each entry in debugfs_list as + * "/debugfs/dri/%minor%/%name%". + */ +int drm_debugfs_init(struct drm_minor *minor, int minor_id, + struct dentry *root) +{ + struct drm_device *dev = minor->dev; + char name[64]; + int ret; + + INIT_LIST_HEAD(&minor->debugfs_nodes.list); + sprintf(name, "%d", minor_id); + minor->debugfs_root = debugfs_create_dir(name, root); + if (!minor->debugfs_root) { + DRM_ERROR("Cannot create /debugfs/dri/%s\n", name); + return -1; + } + + ret = drm_debugfs_create_files(drm_debugfs_list, DRM_DEBUGFS_ENTRIES, + minor->debugfs_root, minor); + if (ret) { + debugfs_remove(minor->debugfs_root); + minor->debugfs_root = NULL; + DRM_ERROR("Failed to create core drm debugfs files\n"); + return ret; + } + + if (dev->driver->debugfs_init) { + ret = dev->driver->debugfs_init(minor); + if (ret) { + DRM_ERROR("DRM: Driver failed to initialize " + "/debugfs/dri.\n"); + return ret; + } + } + return 0; +} + + +/** + * Remove a list of debugfs files + * + * \param files The list of files + * \param count The number of files + * \param minor The minor of which we should remove the files + * \return always zero. + * + * Remove all debugfs entries created by debugfs_init(). + */ +int drm_debugfs_remove_files(struct drm_info_list *files, int count, + struct drm_minor *minor) +{ + struct list_head *pos, *q; + struct drm_info_node *tmp; + int i; + + for (i = 0; i < count; i++) { + list_for_each_safe(pos, q, &minor->debugfs_nodes.list) { + tmp = list_entry(pos, struct drm_info_node, list); + if (tmp->info_ent == &files[i]) { + debugfs_remove(tmp->dent); + list_del(pos); + drm_free(tmp, sizeof(struct drm_info_node), + _DRM_DRIVER); + } + } + } + return 0; +} +EXPORT_SYMBOL(drm_debugfs_remove_files); + +/** + * Cleanup the debugfs filesystem resources. + * + * \param minor device minor number. + * \return always zero. + * + * Remove all debugfs entries created by debugfs_init(). + */ +int drm_debugfs_cleanup(struct drm_minor *minor) +{ + struct drm_device *dev = minor->dev; + + if (!minor->debugfs_root) + return 0; + + if (dev->driver->debugfs_cleanup) + dev->driver->debugfs_cleanup(minor); + + drm_debugfs_remove_files(drm_debugfs_list, DRM_DEBUGFS_ENTRIES, minor); + + debugfs_remove(minor->debugfs_root); + minor->debugfs_root = NULL; + + return 0; +} + +#endif /* CONFIG_DEBUG_FS */ + diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 14c7a23dc15..ed32edb1716 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -46,9 +46,11 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include #include "drmP.h" #include "drm_core.h" + static int drm_version(struct drm_device *dev, void *data, struct drm_file *file_priv); @@ -178,7 +180,7 @@ int drm_lastclose(struct drm_device * dev) /* Clear AGP information */ if (drm_core_has_AGP(dev) && dev->agp && - !drm_core_check_feature(dev, DRIVER_MODESET)) { + !drm_core_check_feature(dev, DRIVER_MODESET)) { struct drm_agp_mem *entry, *tempe; /* Remove AGP resources, but leave dev->agp @@ -382,6 +384,13 @@ static int __init drm_core_init(void) goto err_p3; } + drm_debugfs_root = debugfs_create_dir("dri", NULL); + if (!drm_debugfs_root) { + DRM_ERROR("Cannot create /debugfs/dri\n"); + ret = -1; + goto err_p3; + } + drm_mem_init(); DRM_INFO("Initialized %s %d.%d.%d %s\n", @@ -400,6 +409,7 @@ err_p1: static void __exit drm_core_exit(void) { remove_proc_entry("dri", NULL); + debugfs_remove(drm_debugfs_root); drm_sysfs_destroy(); unregister_chrdev(DRM_MAJOR, "drm"); diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c new file mode 100644 index 00000000000..fc98952b903 --- /dev/null +++ b/drivers/gpu/drm/drm_info.c @@ -0,0 +1,328 @@ +/** + * \file drm_info.c + * DRM info file implementations + * + * \author Ben Gamari + */ + +/* + * Created: Sun Dec 21 13:09:50 2008 by bgamari@gmail.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * Copyright 2008 Ben Gamari + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "drmP.h" + +/** + * Called when "/proc/dri/.../name" is read. + * + * Prints the device name together with the bus id if available. + */ +int drm_name_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_minor *minor = node->minor; + struct drm_device *dev = minor->dev; + struct drm_master *master = minor->master; + + if (!master) + return 0; + + if (master->unique) { + seq_printf(m, "%s %s %s\n", + dev->driver->pci_driver.name, + pci_name(dev->pdev), master->unique); + } else { + seq_printf(m, "%s %s\n", dev->driver->pci_driver.name, + pci_name(dev->pdev)); + } + + return 0; +} + +/** + * Called when "/proc/dri/.../vm" is read. + * + * Prints information about all mappings in drm_device::maplist. + */ +int drm_vm_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct drm_map *map; + struct drm_map_list *r_list; + + /* Hardcoded from _DRM_FRAME_BUFFER, + _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and + _DRM_SCATTER_GATHER and _DRM_CONSISTENT */ + const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" }; + const char *type; + int i; + + mutex_lock(&dev->struct_mutex); + seq_printf(m, "slot offset size type flags address mtrr\n\n"); + i = 0; + list_for_each_entry(r_list, &dev->maplist, head) { + map = r_list->map; + if (!map) + continue; + if (map->type < 0 || map->type > 5) + type = "??"; + else + type = types[map->type]; + + seq_printf(m, "%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ", + i, + map->offset, + map->size, type, map->flags, + (unsigned long) r_list->user_token); + if (map->mtrr < 0) + seq_printf(m, "none\n"); + else + seq_printf(m, "%4d\n", map->mtrr); + i++; + } + mutex_unlock(&dev->struct_mutex); + return 0; +} + +/** + * Called when "/proc/dri/.../queues" is read. + */ +int drm_queues_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + int i; + struct drm_queue *q; + + mutex_lock(&dev->struct_mutex); + seq_printf(m, " ctx/flags use fin" + " blk/rw/rwf wait flushed queued" + " locks\n\n"); + for (i = 0; i < dev->queue_count; i++) { + q = dev->queuelist[i]; + atomic_inc(&q->use_count); + seq_printf(m, "%5d/0x%03x %5d %5d" + " %5d/%c%c/%c%c%c %5Zd\n", + i, + q->flags, + atomic_read(&q->use_count), + atomic_read(&q->finalization), + atomic_read(&q->block_count), + atomic_read(&q->block_read) ? 'r' : '-', + atomic_read(&q->block_write) ? 'w' : '-', + waitqueue_active(&q->read_queue) ? 'r' : '-', + waitqueue_active(&q->write_queue) ? 'w' : '-', + waitqueue_active(&q->flush_queue) ? 'f' : '-', + DRM_BUFCOUNT(&q->waitlist)); + atomic_dec(&q->use_count); + } + mutex_unlock(&dev->struct_mutex); + return 0; +} + +/** + * Called when "/proc/dri/.../bufs" is read. + */ +int drm_bufs_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct drm_device_dma *dma; + int i, seg_pages; + + mutex_lock(&dev->struct_mutex); + dma = dev->dma; + if (!dma) { + mutex_unlock(&dev->struct_mutex); + return 0; + } + + seq_printf(m, " o size count free segs pages kB\n\n"); + for (i = 0; i <= DRM_MAX_ORDER; i++) { + if (dma->bufs[i].buf_count) { + seg_pages = dma->bufs[i].seg_count * (1 << dma->bufs[i].page_order); + seq_printf(m, "%2d %8d %5d %5d %5d %5d %5ld\n", + i, + dma->bufs[i].buf_size, + dma->bufs[i].buf_count, + atomic_read(&dma->bufs[i].freelist.count), + dma->bufs[i].seg_count, + seg_pages, + seg_pages * PAGE_SIZE / 1024); + } + } + seq_printf(m, "\n"); + for (i = 0; i < dma->buf_count; i++) { + if (i && !(i % 32)) + seq_printf(m, "\n"); + seq_printf(m, " %d", dma->buflist[i]->list); + } + seq_printf(m, "\n"); + mutex_unlock(&dev->struct_mutex); + return 0; +} + +/** + * Called when "/proc/dri/.../vblank" is read. + */ +int drm_vblank_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + int crtc; + + mutex_lock(&dev->struct_mutex); + for (crtc = 0; crtc < dev->num_crtcs; crtc++) { + seq_printf(m, "CRTC %d enable: %d\n", + crtc, atomic_read(&dev->vblank_refcount[crtc])); + seq_printf(m, "CRTC %d counter: %d\n", + crtc, drm_vblank_count(dev, crtc)); + seq_printf(m, "CRTC %d last wait: %d\n", + crtc, dev->last_vblank_wait[crtc]); + seq_printf(m, "CRTC %d in modeset: %d\n", + crtc, dev->vblank_inmodeset[crtc]); + } + mutex_unlock(&dev->struct_mutex); + return 0; +} + +/** + * Called when "/proc/dri/.../clients" is read. + * + */ +int drm_clients_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct drm_file *priv; + + mutex_lock(&dev->struct_mutex); + seq_printf(m, "a dev pid uid magic ioctls\n\n"); + list_for_each_entry(priv, &dev->filelist, lhead) { + seq_printf(m, "%c %3d %5d %5d %10u %10lu\n", + priv->authenticated ? 'y' : 'n', + priv->minor->index, + priv->pid, + priv->uid, priv->magic, priv->ioctl_count); + } + mutex_unlock(&dev->struct_mutex); + return 0; +} + + +int drm_gem_one_name_info(int id, void *ptr, void *data) +{ + struct drm_gem_object *obj = ptr; + struct seq_file *m = data; + + seq_printf(m, "name %d size %zd\n", obj->name, obj->size); + + seq_printf(m, "%6d %8zd %7d %8d\n", + obj->name, obj->size, + atomic_read(&obj->handlecount.refcount), + atomic_read(&obj->refcount.refcount)); + return 0; +} + +int drm_gem_name_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + + seq_printf(m, " name size handles refcount\n"); + idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, m); + return 0; +} + +int drm_gem_object_info(struct seq_file *m, void* data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + + seq_printf(m, "%d objects\n", atomic_read(&dev->object_count)); + seq_printf(m, "%d object bytes\n", atomic_read(&dev->object_memory)); + seq_printf(m, "%d pinned\n", atomic_read(&dev->pin_count)); + seq_printf(m, "%d pin bytes\n", atomic_read(&dev->pin_memory)); + seq_printf(m, "%d gtt bytes\n", atomic_read(&dev->gtt_memory)); + seq_printf(m, "%d gtt total\n", dev->gtt_total); + return 0; +} + +#if DRM_DEBUG_CODE + +int drm_vma_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct drm_vma_entry *pt; + struct vm_area_struct *vma; +#if defined(__i386__) + unsigned int pgprot; +#endif + + mutex_lock(&dev->struct_mutex); + seq_printf(m, "vma use count: %d, high_memory = %p, 0x%08lx\n", + atomic_read(&dev->vma_count), + high_memory, virt_to_phys(high_memory)); + + list_for_each_entry(pt, &dev->vmalist, head) { + vma = pt->vma; + if (!vma) + continue; + seq_printf(m, + "\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000", + pt->pid, vma->vm_start, vma->vm_end, + vma->vm_flags & VM_READ ? 'r' : '-', + vma->vm_flags & VM_WRITE ? 'w' : '-', + vma->vm_flags & VM_EXEC ? 'x' : '-', + vma->vm_flags & VM_MAYSHARE ? 's' : 'p', + vma->vm_flags & VM_LOCKED ? 'l' : '-', + vma->vm_flags & VM_IO ? 'i' : '-', + vma->vm_pgoff); + +#if defined(__i386__) + pgprot = pgprot_val(vma->vm_page_prot); + seq_printf(m, " %c%c%c%c%c%c%c%c%c", + pgprot & _PAGE_PRESENT ? 'p' : '-', + pgprot & _PAGE_RW ? 'w' : 'r', + pgprot & _PAGE_USER ? 'u' : 's', + pgprot & _PAGE_PWT ? 't' : 'b', + pgprot & _PAGE_PCD ? 'u' : 'c', + pgprot & _PAGE_ACCESSED ? 'a' : '-', + pgprot & _PAGE_DIRTY ? 'd' : '-', + pgprot & _PAGE_PSE ? 'm' : 'k', + pgprot & _PAGE_GLOBAL ? 'g' : 'l'); +#endif + seq_printf(m, "\n"); + } + mutex_unlock(&dev->struct_mutex); + return 0; +} + +#endif + diff --git a/drivers/gpu/drm/drm_proc.c b/drivers/gpu/drm/drm_proc.c index 8df849f6683..9b3c5af61e9 100644 --- a/drivers/gpu/drm/drm_proc.c +++ b/drivers/gpu/drm/drm_proc.c @@ -37,697 +37,196 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include #include "drmP.h" -static int drm_name_info(char *buf, char **start, off_t offset, - int request, int *eof, void *data); -static int drm_vm_info(char *buf, char **start, off_t offset, - int request, int *eof, void *data); -static int drm_clients_info(char *buf, char **start, off_t offset, - int request, int *eof, void *data); -static int drm_queues_info(char *buf, char **start, off_t offset, - int request, int *eof, void *data); -static int drm_bufs_info(char *buf, char **start, off_t offset, - int request, int *eof, void *data); -static int drm_vblank_info(char *buf, char **start, off_t offset, - int request, int *eof, void *data); -static int drm_gem_name_info(char *buf, char **start, off_t offset, - int request, int *eof, void *data); -static int drm_gem_object_info(char *buf, char **start, off_t offset, - int request, int *eof, void *data); -#if DRM_DEBUG_CODE -static int drm_vma_info(char *buf, char **start, off_t offset, - int request, int *eof, void *data); -#endif + +/*************************************************** + * Initialization, etc. + **************************************************/ /** * Proc file list. */ -static struct drm_proc_list { - const char *name; /**< file name */ - int (*f) (char *, char **, off_t, int, int *, void *); /**< proc callback*/ - u32 driver_features; /**< Required driver features for this entry */ -} drm_proc_list[] = { +static struct drm_info_list drm_proc_list[] = { {"name", drm_name_info, 0}, - {"mem", drm_mem_info, 0}, {"vm", drm_vm_info, 0}, {"clients", drm_clients_info, 0}, {"queues", drm_queues_info, 0}, {"bufs", drm_bufs_info, 0}, - {"vblank", drm_vblank_info, 0}, {"gem_names", drm_gem_name_info, DRIVER_GEM}, {"gem_objects", drm_gem_object_info, DRIVER_GEM}, #if DRM_DEBUG_CODE - {"vma", drm_vma_info}, + {"vma", drm_vma_info, 0}, #endif }; - #define DRM_PROC_ENTRIES ARRAY_SIZE(drm_proc_list) +static int drm_proc_open(struct inode *inode, struct file *file) +{ + struct drm_info_node* node = PDE(inode)->data; + + return single_open(file, node->info_ent->show, node); +} + +static const struct file_operations drm_proc_fops = { + .owner = THIS_MODULE, + .open = drm_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + + /** - * Initialize the DRI proc filesystem for a device. + * Initialize a given set of proc files for a device * - * \param dev DRM device. - * \param minor device minor number. + * \param files The array of files to create + * \param count The number of files given * \param root DRI proc dir entry. - * \param dev_root resulting DRI device proc dir entry. - * \return root entry pointer on success, or NULL on failure. + * \param minor device minor number + * \return Zero on success, non-zero on failure * - * Create the DRI proc root entry "/proc/dri", the device proc root entry - * "/proc/dri/%minor%/", and each entry in proc_list as - * "/proc/dri/%minor%/%name%". + * Create a given set of proc files represented by an array of + * gdm_proc_lists in the given root directory. */ -int drm_proc_init(struct drm_minor *minor, int minor_id, - struct proc_dir_entry *root) +int drm_proc_create_files(struct drm_info_list *files, int count, + struct proc_dir_entry *root, struct drm_minor *minor) { struct drm_device *dev = minor->dev; struct proc_dir_entry *ent; - int i, j, ret; + struct drm_info_node *tmp; char name[64]; + int i, ret; - sprintf(name, "%d", minor_id); - minor->dev_root = proc_mkdir(name, root); - if (!minor->dev_root) { - DRM_ERROR("Cannot create /proc/dri/%s\n", name); - return -1; - } - - for (i = 0; i < DRM_PROC_ENTRIES; i++) { - u32 features = drm_proc_list[i].driver_features; + for (i = 0; i < count; i++) { + u32 features = files[i].driver_features; if (features != 0 && (dev->driver->driver_features & features) != features) continue; - ent = create_proc_entry(drm_proc_list[i].name, - S_IFREG | S_IRUGO, minor->dev_root); + tmp = drm_alloc(sizeof(struct drm_info_node), _DRM_DRIVER); + ent = create_proc_entry(files[i].name, S_IFREG | S_IRUGO, root); if (!ent) { DRM_ERROR("Cannot create /proc/dri/%s/%s\n", - name, drm_proc_list[i].name); + name, files[i].name); + drm_free(tmp, sizeof(struct drm_info_node), + _DRM_DRIVER); ret = -1; goto fail; } - ent->read_proc = drm_proc_list[i].f; - ent->data = minor; - } - if (dev->driver->proc_init) { - ret = dev->driver->proc_init(minor); - if (ret) { - DRM_ERROR("DRM: Driver failed to initialize " - "/proc/dri.\n"); - goto fail; - } + ent->proc_fops = &drm_proc_fops; + ent->data = tmp; + tmp->minor = minor; + tmp->info_ent = &files[i]; + list_add(&(tmp->list), &(minor->proc_nodes.list)); } - return 0; - fail: - for (j = 0; j < i; j++) - remove_proc_entry(drm_proc_list[i].name, - minor->dev_root); - remove_proc_entry(name, root); - minor->dev_root = NULL; +fail: + for (i = 0; i < count; i++) + remove_proc_entry(drm_proc_list[i].name, minor->proc_root); return ret; } /** - * Cleanup the proc filesystem resources. + * Initialize the DRI proc filesystem for a device * - * \param minor device minor number. + * \param dev DRM device + * \param minor device minor number * \param root DRI proc dir entry. - * \param dev_root DRI device proc dir entry. - * \return always zero. + * \param dev_root resulting DRI device proc dir entry. + * \return root entry pointer on success, or NULL on failure. * - * Remove all proc entries created by proc_init(). + * Create the DRI proc root entry "/proc/dri", the device proc root entry + * "/proc/dri/%minor%/", and each entry in proc_list as + * "/proc/dri/%minor%/%name%". */ -int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root) +int drm_proc_init(struct drm_minor *minor, int minor_id, + struct proc_dir_entry *root) { struct drm_device *dev = minor->dev; - int i; char name[64]; + int ret; - if (!root || !minor->dev_root) - return 0; - - if (dev->driver->proc_cleanup) - dev->driver->proc_cleanup(minor); - - for (i = 0; i < DRM_PROC_ENTRIES; i++) - remove_proc_entry(drm_proc_list[i].name, minor->dev_root); - sprintf(name, "%d", minor->index); - remove_proc_entry(name, root); - - return 0; -} - -/** - * Called when "/proc/dri/.../name" is read. - * - * \param buf output buffer. - * \param start start of output data. - * \param offset requested start offset. - * \param request requested number of bytes. - * \param eof whether there is no more data to return. - * \param data private data. - * \return number of written bytes. - * - * Prints the device name together with the bus id if available. - */ -static int drm_name_info(char *buf, char **start, off_t offset, int request, - int *eof, void *data) -{ - struct drm_minor *minor = (struct drm_minor *) data; - struct drm_master *master = minor->master; - struct drm_device *dev = minor->dev; - int len = 0; - - if (offset > DRM_PROC_LIMIT) { - *eof = 1; - return 0; + INIT_LIST_HEAD(&minor->proc_nodes.list); + sprintf(name, "%d", minor_id); + minor->proc_root = proc_mkdir(name, root); + if (!minor->proc_root) { + DRM_ERROR("Cannot create /proc/dri/%s\n", name); + return -1; } - if (!master) - return 0; - - *start = &buf[offset]; - *eof = 0; - - if (master->unique) { - DRM_PROC_PRINT("%s %s %s\n", - dev->driver->pci_driver.name, - pci_name(dev->pdev), master->unique); - } else { - DRM_PROC_PRINT("%s %s\n", dev->driver->pci_driver.name, - pci_name(dev->pdev)); + ret = drm_proc_create_files(drm_proc_list, DRM_PROC_ENTRIES, + minor->proc_root, minor); + if (ret) { + remove_proc_entry(name, root); + minor->proc_root = NULL; + DRM_ERROR("Failed to create core drm proc files\n"); + return ret; } - if (len > request + offset) - return request; - *eof = 1; - return len - offset; -} - -/** - * Called when "/proc/dri/.../vm" is read. - * - * \param buf output buffer. - * \param start start of output data. - * \param offset requested start offset. - * \param request requested number of bytes. - * \param eof whether there is no more data to return. - * \param data private data. - * \return number of written bytes. - * - * Prints information about all mappings in drm_device::maplist. - */ -static int drm__vm_info(char *buf, char **start, off_t offset, int request, - int *eof, void *data) -{ - struct drm_minor *minor = (struct drm_minor *) data; - struct drm_device *dev = minor->dev; - int len = 0; - struct drm_map *map; - struct drm_map_list *r_list; - - /* Hardcoded from _DRM_FRAME_BUFFER, - _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and - _DRM_SCATTER_GATHER and _DRM_CONSISTENT */ - const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" }; - const char *type; - int i; - - if (offset > DRM_PROC_LIMIT) { - *eof = 1; - return 0; - } - - *start = &buf[offset]; - *eof = 0; - - DRM_PROC_PRINT("slot offset size type flags " - "address mtrr\n\n"); - i = 0; - list_for_each_entry(r_list, &dev->maplist, head) { - map = r_list->map; - if (!map) - continue; - if (map->type < 0 || map->type > 5) - type = "??"; - else - type = types[map->type]; - DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ", - i, - map->offset, - map->size, type, map->flags, - (unsigned long) r_list->user_token); - if (map->mtrr < 0) { - DRM_PROC_PRINT("none\n"); - } else { - DRM_PROC_PRINT("%4d\n", map->mtrr); + if (dev->driver->proc_init) { + ret = dev->driver->proc_init(minor); + if (ret) { + DRM_ERROR("DRM: Driver failed to initialize " + "/proc/dri.\n"); + return ret; } - i++; - } - - if (len > request + offset) - return request; - *eof = 1; - return len - offset; -} - -/** - * Simply calls _vm_info() while holding the drm_device::struct_mutex lock. - */ -static int drm_vm_info(char *buf, char **start, off_t offset, int request, - int *eof, void *data) -{ - struct drm_minor *minor = (struct drm_minor *) data; - struct drm_device *dev = minor->dev; - int ret; - - mutex_lock(&dev->struct_mutex); - ret = drm__vm_info(buf, start, offset, request, eof, data); - mutex_unlock(&dev->struct_mutex); - return ret; -} - -/** - * Called when "/proc/dri/.../queues" is read. - * - * \param buf output buffer. - * \param start start of output data. - * \param offset requested start offset. - * \param request requested number of bytes. - * \param eof whether there is no more data to return. - * \param data private data. - * \return number of written bytes. - */ -static int drm__queues_info(char *buf, char **start, off_t offset, - int request, int *eof, void *data) -{ - struct drm_minor *minor = (struct drm_minor *) data; - struct drm_device *dev = minor->dev; - int len = 0; - int i; - struct drm_queue *q; - - if (offset > DRM_PROC_LIMIT) { - *eof = 1; - return 0; } - - *start = &buf[offset]; - *eof = 0; - - DRM_PROC_PRINT(" ctx/flags use fin" - " blk/rw/rwf wait flushed queued" - " locks\n\n"); - for (i = 0; i < dev->queue_count; i++) { - q = dev->queuelist[i]; - atomic_inc(&q->use_count); - DRM_PROC_PRINT_RET(atomic_dec(&q->use_count), - "%5d/0x%03x %5d %5d" - " %5d/%c%c/%c%c%c %5Zd\n", - i, - q->flags, - atomic_read(&q->use_count), - atomic_read(&q->finalization), - atomic_read(&q->block_count), - atomic_read(&q->block_read) ? 'r' : '-', - atomic_read(&q->block_write) ? 'w' : '-', - waitqueue_active(&q->read_queue) ? 'r' : '-', - waitqueue_active(&q-> - write_queue) ? 'w' : '-', - waitqueue_active(&q-> - flush_queue) ? 'f' : '-', - DRM_BUFCOUNT(&q->waitlist)); - atomic_dec(&q->use_count); - } - - if (len > request + offset) - return request; - *eof = 1; - return len - offset; -} - -/** - * Simply calls _queues_info() while holding the drm_device::struct_mutex lock. - */ -static int drm_queues_info(char *buf, char **start, off_t offset, int request, - int *eof, void *data) -{ - struct drm_minor *minor = (struct drm_minor *) data; - struct drm_device *dev = minor->dev; - int ret; - - mutex_lock(&dev->struct_mutex); - ret = drm__queues_info(buf, start, offset, request, eof, data); - mutex_unlock(&dev->struct_mutex); - return ret; + return 0; } -/** - * Called when "/proc/dri/.../bufs" is read. - * - * \param buf output buffer. - * \param start start of output data. - * \param offset requested start offset. - * \param request requested number of bytes. - * \param eof whether there is no more data to return. - * \param data private data. - * \return number of written bytes. - */ -static int drm__bufs_info(char *buf, char **start, off_t offset, int request, - int *eof, void *data) +int drm_proc_remove_files(struct drm_info_list *files, int count, + struct drm_minor *minor) { - struct drm_minor *minor = (struct drm_minor *) data; - struct drm_device *dev = minor->dev; - int len = 0; - struct drm_device_dma *dma = dev->dma; + struct list_head *pos, *q; + struct drm_info_node *tmp; int i; - if (!dma || offset > DRM_PROC_LIMIT) { - *eof = 1; - return 0; - } - - *start = &buf[offset]; - *eof = 0; - - DRM_PROC_PRINT(" o size count free segs pages kB\n\n"); - for (i = 0; i <= DRM_MAX_ORDER; i++) { - if (dma->bufs[i].buf_count) - DRM_PROC_PRINT("%2d %8d %5d %5d %5d %5d %5ld\n", - i, - dma->bufs[i].buf_size, - dma->bufs[i].buf_count, - atomic_read(&dma->bufs[i] - .freelist.count), - dma->bufs[i].seg_count, - dma->bufs[i].seg_count - * (1 << dma->bufs[i].page_order), - (dma->bufs[i].seg_count - * (1 << dma->bufs[i].page_order)) - * PAGE_SIZE / 1024); - } - DRM_PROC_PRINT("\n"); - for (i = 0; i < dma->buf_count; i++) { - if (i && !(i % 32)) - DRM_PROC_PRINT("\n"); - DRM_PROC_PRINT(" %d", dma->buflist[i]->list); + for (i = 0; i < count; i++) { + list_for_each_safe(pos, q, &minor->proc_nodes.list) { + tmp = list_entry(pos, struct drm_info_node, list); + if (tmp->info_ent == &files[i]) { + remove_proc_entry(files[i].name, + minor->proc_root); + list_del(pos); + drm_free(tmp, sizeof(struct drm_info_node), + _DRM_DRIVER); + } + } } - DRM_PROC_PRINT("\n"); - - if (len > request + offset) - return request; - *eof = 1; - return len - offset; -} - -/** - * Simply calls _bufs_info() while holding the drm_device::struct_mutex lock. - */ -static int drm_bufs_info(char *buf, char **start, off_t offset, int request, - int *eof, void *data) -{ - struct drm_minor *minor = (struct drm_minor *) data; - struct drm_device *dev = minor->dev; - int ret; - - mutex_lock(&dev->struct_mutex); - ret = drm__bufs_info(buf, start, offset, request, eof, data); - mutex_unlock(&dev->struct_mutex); - return ret; + return 0; } /** - * Called when "/proc/dri/.../vblank" is read. + * Cleanup the proc filesystem resources. * - * \param buf output buffer. - * \param start start of output data. - * \param offset requested start offset. - * \param request requested number of bytes. - * \param eof whether there is no more data to return. - * \param data private data. - * \return number of written bytes. - */ -static int drm__vblank_info(char *buf, char **start, off_t offset, int request, - int *eof, void *data) -{ - struct drm_minor *minor = (struct drm_minor *) data; - struct drm_device *dev = minor->dev; - int len = 0; - int crtc; - - if (offset > DRM_PROC_LIMIT) { - *eof = 1; - return 0; - } - - *start = &buf[offset]; - *eof = 0; - - for (crtc = 0; crtc < dev->num_crtcs; crtc++) { - DRM_PROC_PRINT("CRTC %d enable: %d\n", - crtc, atomic_read(&dev->vblank_refcount[crtc])); - DRM_PROC_PRINT("CRTC %d counter: %d\n", - crtc, drm_vblank_count(dev, crtc)); - DRM_PROC_PRINT("CRTC %d last wait: %d\n", - crtc, dev->last_vblank_wait[crtc]); - DRM_PROC_PRINT("CRTC %d in modeset: %d\n", - crtc, dev->vblank_inmodeset[crtc]); - } - - if (len > request + offset) - return request; - *eof = 1; - return len - offset; -} - -/** - * Simply calls _vblank_info() while holding the drm_device::struct_mutex lock. - */ -static int drm_vblank_info(char *buf, char **start, off_t offset, int request, - int *eof, void *data) -{ - struct drm_minor *minor = (struct drm_minor *) data; - struct drm_device *dev = minor->dev; - int ret; - - mutex_lock(&dev->struct_mutex); - ret = drm__vblank_info(buf, start, offset, request, eof, data); - mutex_unlock(&dev->struct_mutex); - return ret; -} - -/** - * Called when "/proc/dri/.../clients" is read. + * \param minor device minor number. + * \param root DRI proc dir entry. + * \param dev_root DRI device proc dir entry. + * \return always zero. * - * \param buf output buffer. - * \param start start of output data. - * \param offset requested start offset. - * \param request requested number of bytes. - * \param eof whether there is no more data to return. - * \param data private data. - * \return number of written bytes. + * Remove all proc entries created by proc_init(). */ -static int drm__clients_info(char *buf, char **start, off_t offset, - int request, int *eof, void *data) +int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root) { - struct drm_minor *minor = (struct drm_minor *) data; struct drm_device *dev = minor->dev; - int len = 0; - struct drm_file *priv; + char name[64]; - if (offset > DRM_PROC_LIMIT) { - *eof = 1; + if (!root || !minor->proc_root) return 0; - } - - *start = &buf[offset]; - *eof = 0; - - DRM_PROC_PRINT("a dev pid uid magic ioctls\n\n"); - list_for_each_entry(priv, &dev->filelist, lhead) { - DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n", - priv->authenticated ? 'y' : 'n', - priv->minor->index, - priv->pid, - priv->uid, priv->magic, priv->ioctl_count); - } - if (len > request + offset) - return request; - *eof = 1; - return len - offset; -} - -/** - * Simply calls _clients_info() while holding the drm_device::struct_mutex lock. - */ -static int drm_clients_info(char *buf, char **start, off_t offset, - int request, int *eof, void *data) -{ - struct drm_minor *minor = (struct drm_minor *) data; - struct drm_device *dev = minor->dev; - int ret; - - mutex_lock(&dev->struct_mutex); - ret = drm__clients_info(buf, start, offset, request, eof, data); - mutex_unlock(&dev->struct_mutex); - return ret; -} - -struct drm_gem_name_info_data { - int len; - char *buf; - int eof; -}; + if (dev->driver->proc_cleanup) + dev->driver->proc_cleanup(minor); -static int drm_gem_one_name_info(int id, void *ptr, void *data) -{ - struct drm_gem_object *obj = ptr; - struct drm_gem_name_info_data *nid = data; + drm_proc_remove_files(drm_proc_list, DRM_PROC_ENTRIES, minor); - DRM_INFO("name %d size %zd\n", obj->name, obj->size); - if (nid->eof) - return 0; + sprintf(name, "%d", minor->index); + remove_proc_entry(name, root); - nid->len += sprintf(&nid->buf[nid->len], - "%6d %8zd %7d %8d\n", - obj->name, obj->size, - atomic_read(&obj->handlecount.refcount), - atomic_read(&obj->refcount.refcount)); - if (nid->len > DRM_PROC_LIMIT) { - nid->eof = 1; - return 0; - } return 0; } -static int drm_gem_name_info(char *buf, char **start, off_t offset, - int request, int *eof, void *data) -{ - struct drm_minor *minor = (struct drm_minor *) data; - struct drm_device *dev = minor->dev; - struct drm_gem_name_info_data nid; - - if (offset > DRM_PROC_LIMIT) { - *eof = 1; - return 0; - } - - nid.len = sprintf(buf, " name size handles refcount\n"); - nid.buf = buf; - nid.eof = 0; - idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, &nid); - - *start = &buf[offset]; - *eof = 0; - if (nid.len > request + offset) - return request; - *eof = 1; - return nid.len - offset; -} - -static int drm_gem_object_info(char *buf, char **start, off_t offset, - int request, int *eof, void *data) -{ - struct drm_minor *minor = (struct drm_minor *) data; - struct drm_device *dev = minor->dev; - int len = 0; - - if (offset > DRM_PROC_LIMIT) { - *eof = 1; - return 0; - } - - *start = &buf[offset]; - *eof = 0; - DRM_PROC_PRINT("%d objects\n", atomic_read(&dev->object_count)); - DRM_PROC_PRINT("%d object bytes\n", atomic_read(&dev->object_memory)); - DRM_PROC_PRINT("%d pinned\n", atomic_read(&dev->pin_count)); - DRM_PROC_PRINT("%d pin bytes\n", atomic_read(&dev->pin_memory)); - DRM_PROC_PRINT("%d gtt bytes\n", atomic_read(&dev->gtt_memory)); - DRM_PROC_PRINT("%d gtt total\n", dev->gtt_total); - if (len > request + offset) - return request; - *eof = 1; - return len - offset; -} - -#if DRM_DEBUG_CODE - -static int drm__vma_info(char *buf, char **start, off_t offset, int request, - int *eof, void *data) -{ - struct drm_minor *minor = (struct drm_minor *) data; - struct drm_device *dev = minor->dev; - int len = 0; - struct drm_vma_entry *pt; - struct vm_area_struct *vma; -#if defined(__i386__) - unsigned int pgprot; -#endif - - if (offset > DRM_PROC_LIMIT) { - *eof = 1; - return 0; - } - - *start = &buf[offset]; - *eof = 0; - - DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n", - atomic_read(&dev->vma_count), - high_memory, virt_to_phys(high_memory)); - list_for_each_entry(pt, &dev->vmalist, head) { - if (!(vma = pt->vma)) - continue; - DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000", - pt->pid, - vma->vm_start, - vma->vm_end, - vma->vm_flags & VM_READ ? 'r' : '-', - vma->vm_flags & VM_WRITE ? 'w' : '-', - vma->vm_flags & VM_EXEC ? 'x' : '-', - vma->vm_flags & VM_MAYSHARE ? 's' : 'p', - vma->vm_flags & VM_LOCKED ? 'l' : '-', - vma->vm_flags & VM_IO ? 'i' : '-', - vma->vm_pgoff); - -#if defined(__i386__) - pgprot = pgprot_val(vma->vm_page_prot); - DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c", - pgprot & _PAGE_PRESENT ? 'p' : '-', - pgprot & _PAGE_RW ? 'w' : 'r', - pgprot & _PAGE_USER ? 'u' : 's', - pgprot & _PAGE_PWT ? 't' : 'b', - pgprot & _PAGE_PCD ? 'u' : 'c', - pgprot & _PAGE_ACCESSED ? 'a' : '-', - pgprot & _PAGE_DIRTY ? 'd' : '-', - pgprot & _PAGE_PSE ? 'm' : 'k', - pgprot & _PAGE_GLOBAL ? 'g' : 'l'); -#endif - DRM_PROC_PRINT("\n"); - } - - if (len > request + offset) - return request; - *eof = 1; - return len - offset; -} - -static int drm_vma_info(char *buf, char **start, off_t offset, int request, - int *eof, void *data) -{ - struct drm_minor *minor = (struct drm_minor *) data; - struct drm_device *dev = minor->dev; - int ret; - - mutex_lock(&dev->struct_mutex); - ret = drm__vma_info(buf, start, offset, request, eof, data); - mutex_unlock(&dev->struct_mutex); - return ret; -} -#endif diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 7c8b15b22bf..48f33be8fd0 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -50,6 +50,7 @@ struct idr drm_minors_idr; struct class *drm_class; struct proc_dir_entry *drm_proc_root; +struct dentry *drm_debugfs_root; static int drm_minor_get_id(struct drm_device *dev, int type) { @@ -313,7 +314,15 @@ static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int t goto err_mem; } } else - new_minor->dev_root = NULL; + new_minor->proc_root = NULL; + +#if defined(CONFIG_DEBUG_FS) + ret = drm_debugfs_init(new_minor, minor_id, drm_debugfs_root); + if (ret) { + DRM_ERROR("DRM: Failed to initialize /debugfs/dri.\n"); + goto err_g2; + } +#endif ret = drm_sysfs_device_add(new_minor); if (ret) { @@ -451,6 +460,10 @@ int drm_put_minor(struct drm_minor **minor_p) if (minor->type == DRM_MINOR_LEGACY) drm_proc_cleanup(minor, drm_proc_root); +#if defined(CONFIG_DEBUG_FS) + drm_debugfs_cleanup(minor); +#endif + drm_sysfs_device_remove(minor); idr_remove(&drm_minors_idr, minor->index); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index e5f4ae989ab..c19a93c3be8 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -758,6 +758,8 @@ struct drm_driver { int (*proc_init)(struct drm_minor *minor); void (*proc_cleanup)(struct drm_minor *minor); + int (*debugfs_init)(struct drm_minor *minor); + void (*debugfs_cleanup)(struct drm_minor *minor); /** * Driver-specific constructor for drm_gem_objects, to set up @@ -793,6 +795,48 @@ struct drm_driver { #define DRM_MINOR_CONTROL 2 #define DRM_MINOR_RENDER 3 + +/** + * debugfs node list. This structure represents a debugfs file to + * be created by the drm core + */ +struct drm_debugfs_list { + const char *name; /** file name */ + int (*show)(struct seq_file*, void*); /** show callback */ + u32 driver_features; /**< Required driver features for this entry */ +}; + +/** + * debugfs node structure. This structure represents a debugfs file. + */ +struct drm_debugfs_node { + struct list_head list; + struct drm_minor *minor; + struct drm_debugfs_list *debugfs_ent; + struct dentry *dent; +}; + +/** + * Info file list entry. This structure represents a debugfs or proc file to + * be created by the drm core + */ +struct drm_info_list { + const char *name; /** file name */ + int (*show)(struct seq_file*, void*); /** show callback */ + u32 driver_features; /**< Required driver features for this entry */ + void *data; +}; + +/** + * debugfs node structure. This structure represents a debugfs file. + */ +struct drm_info_node { + struct list_head list; + struct drm_minor *minor; + struct drm_info_list *info_ent; + struct dentry *dent; +}; + /** * DRM minor structure. This structure represents a drm minor number. */ @@ -802,7 +846,12 @@ struct drm_minor { dev_t device; /**< Device number for mknod */ struct device kdev; /**< Linux device */ struct drm_device *dev; - struct proc_dir_entry *dev_root; /**< proc directory entry */ + + struct proc_dir_entry *proc_root; /**< proc directory entry */ + struct drm_info_node proc_nodes; + struct dentry *debugfs_root; + struct drm_info_node debugfs_nodes; + struct drm_master *master; /* currently active master for this node */ struct list_head master_list; struct drm_mode_group mode_group; @@ -1258,6 +1307,7 @@ extern unsigned int drm_debug; extern struct class *drm_class; extern struct proc_dir_entry *drm_proc_root; +extern struct dentry *drm_debugfs_root; extern struct idr drm_minors_idr; @@ -1268,6 +1318,31 @@ extern int drm_proc_init(struct drm_minor *minor, int minor_id, struct proc_dir_entry *root); extern int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root); + /* Debugfs support */ +#if defined(CONFIG_DEBUG_FS) +extern int drm_debugfs_init(struct drm_minor *minor, int minor_id, + struct dentry *root); +extern int drm_debugfs_create_files(struct drm_info_list *files, int count, + struct dentry *root, struct drm_minor *minor); +extern int drm_debugfs_remove_files(struct drm_info_list *files, int count, + struct drm_minor *minor); +extern int drm_debugfs_cleanup(struct drm_minor *minor); +#endif + + /* Info file support */ +extern int drm_name_info(struct seq_file *m, void *data); +extern int drm_vm_info(struct seq_file *m, void *data); +extern int drm_queues_info(struct seq_file *m, void *data); +extern int drm_bufs_info(struct seq_file *m, void *data); +extern int drm_vblank_info(struct seq_file *m, void *data); +extern int drm_clients_info(struct seq_file *m, void* data); +extern int drm_gem_name_info(struct seq_file *m, void *data); +extern int drm_gem_object_info(struct seq_file *m, void* data); + +#if DRM_DEBUG_CODE +extern int drm_vma_info(struct seq_file *m, void *data); +#endif + /* Scatter Gather Support (drm_scatter.h) */ extern void drm_sg_cleanup(struct drm_sg_mem * entry); extern int drm_sg_alloc_ioctl(struct drm_device *dev, void *data, -- GitLab From 2017263e9e72974610179beaa85c4498b9c4b7a4 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Tue, 17 Feb 2009 20:08:50 -0500 Subject: [PATCH 4818/4982] drm/i915: Convert i915 proc files to seq_file and move to debugfs. Signed-off-by: Ben Gamari Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/Makefile | 2 +- drivers/gpu/drm/i915/i915_drv.c | 6 +- drivers/gpu/drm/i915/i915_drv.h | 6 +- drivers/gpu/drm/i915/i915_gem_debugfs.c | 230 ++++++++++++++++ drivers/gpu/drm/i915/i915_gem_proc.c | 334 ------------------------ 5 files changed, 239 insertions(+), 339 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_gem_debugfs.c delete mode 100644 drivers/gpu/drm/i915/i915_gem_proc.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 793cba39d83..51c5a050aa7 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -7,7 +7,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \ i915_suspend.o \ i915_gem.o \ i915_gem_debug.o \ - i915_gem_proc.o \ + i915_gem_debugfs.o \ i915_gem_tiling.o \ intel_display.o \ intel_crt.o \ diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index b293ef0bae7..dcb91f5df6e 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -150,8 +150,10 @@ static struct drm_driver driver = { .get_reg_ofs = drm_core_get_reg_ofs, .master_create = i915_master_create, .master_destroy = i915_master_destroy, - .proc_init = i915_gem_proc_init, - .proc_cleanup = i915_gem_proc_cleanup, +#if defined(CONFIG_DEBUG_FS) + .debugfs_init = i915_gem_debugfs_init, + .debugfs_cleanup = i915_gem_debugfs_cleanup, +#endif .gem_init_object = i915_gem_init_object, .gem_free_object = i915_gem_free_object, .gem_vm_ops = &i915_gem_vm_ops, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2c02ce6b2b9..1c03b3e81ff 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -605,8 +605,6 @@ int i915_gem_get_tiling(struct drm_device *dev, void *data, int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); void i915_gem_load(struct drm_device *dev); -int i915_gem_proc_init(struct drm_minor *minor); -void i915_gem_proc_cleanup(struct drm_minor *minor); int i915_gem_init_object(struct drm_gem_object *obj); void i915_gem_free_object(struct drm_gem_object *obj); int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment); @@ -650,6 +648,10 @@ void i915_gem_dump_object(struct drm_gem_object *obj, int len, const char *where, uint32_t mark); void i915_dump_lru(struct drm_device *dev, const char *where); +/* i915_debugfs.c */ +int i915_gem_debugfs_init(struct drm_minor *minor); +void i915_gem_debugfs_cleanup(struct drm_minor *minor); + /* i915_suspend.c */ extern int i915_save_state(struct drm_device *dev); extern int i915_restore_state(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_gem_debugfs.c b/drivers/gpu/drm/i915/i915_gem_debugfs.c new file mode 100644 index 00000000000..dd2b0edb996 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_gem_debugfs.c @@ -0,0 +1,230 @@ +/* + * Copyright © 2008 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * Keith Packard + * + */ + +#include +#include "drmP.h" +#include "drm.h" +#include "i915_drm.h" +#include "i915_drv.h" + +#define DRM_I915_RING_DEBUG 1 + + +#if defined(CONFIG_DEBUG_FS) + +static int i915_gem_active_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj_priv; + + seq_printf(m, "Active:\n"); + list_for_each_entry(obj_priv, &dev_priv->mm.active_list, + list) + { + struct drm_gem_object *obj = obj_priv->obj; + if (obj->name) { + seq_printf(m, " %p(%d): %08x %08x %d\n", + obj, obj->name, + obj->read_domains, obj->write_domain, + obj_priv->last_rendering_seqno); + } else { + seq_printf(m, " %p: %08x %08x %d\n", + obj, + obj->read_domains, obj->write_domain, + obj_priv->last_rendering_seqno); + } + } + return 0; +} + +static int i915_gem_flushing_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj_priv; + + seq_printf(m, "Flushing:\n"); + list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list, + list) + { + struct drm_gem_object *obj = obj_priv->obj; + if (obj->name) { + seq_printf(m, " %p(%d): %08x %08x %d\n", + obj, obj->name, + obj->read_domains, obj->write_domain, + obj_priv->last_rendering_seqno); + } else { + seq_printf(m, " %p: %08x %08x %d\n", obj, + obj->read_domains, obj->write_domain, + obj_priv->last_rendering_seqno); + } + } + return 0; +} + +static int i915_gem_inactive_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj_priv; + + seq_printf(m, "Inactive:\n"); + list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, + list) + { + struct drm_gem_object *obj = obj_priv->obj; + if (obj->name) { + seq_printf(m, " %p(%d): %08x %08x %d\n", + obj, obj->name, + obj->read_domains, obj->write_domain, + obj_priv->last_rendering_seqno); + } else { + seq_printf(m, " %p: %08x %08x %d\n", obj, + obj->read_domains, obj->write_domain, + obj_priv->last_rendering_seqno); + } + } + return 0; +} + +static int i915_gem_request_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_gem_request *gem_request; + + seq_printf(m, "Request:\n"); + list_for_each_entry(gem_request, &dev_priv->mm.request_list, list) { + seq_printf(m, " %d @ %d\n", + gem_request->seqno, + (int) (jiffies - gem_request->emitted_jiffies)); + } + return 0; +} + +static int i915_gem_seqno_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + + if (dev_priv->hw_status_page != NULL) { + seq_printf(m, "Current sequence: %d\n", + i915_get_gem_seqno(dev)); + } else { + seq_printf(m, "Current sequence: hws uninitialized\n"); + } + seq_printf(m, "Waiter sequence: %d\n", + dev_priv->mm.waiting_gem_seqno); + seq_printf(m, "IRQ sequence: %d\n", dev_priv->mm.irq_gem_seqno); + return 0; +} + + +static int i915_interrupt_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + + seq_printf(m, "Interrupt enable: %08x\n", + I915_READ(IER)); + seq_printf(m, "Interrupt identity: %08x\n", + I915_READ(IIR)); + seq_printf(m, "Interrupt mask: %08x\n", + I915_READ(IMR)); + seq_printf(m, "Pipe A stat: %08x\n", + I915_READ(PIPEASTAT)); + seq_printf(m, "Pipe B stat: %08x\n", + I915_READ(PIPEBSTAT)); + seq_printf(m, "Interrupts received: %d\n", + atomic_read(&dev_priv->irq_received)); + if (dev_priv->hw_status_page != NULL) { + seq_printf(m, "Current sequence: %d\n", + i915_get_gem_seqno(dev)); + } else { + seq_printf(m, "Current sequence: hws uninitialized\n"); + } + seq_printf(m, "Waiter sequence: %d\n", + dev_priv->mm.waiting_gem_seqno); + seq_printf(m, "IRQ sequence: %d\n", + dev_priv->mm.irq_gem_seqno); + return 0; +} + +static int i915_hws_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + int i; + volatile u32 *hws; + + hws = (volatile u32 *)dev_priv->hw_status_page; + if (hws == NULL) + return 0; + + for (i = 0; i < 4096 / sizeof(u32) / 4; i += 4) { + seq_printf(m, "0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n", + i * 4, + hws[i], hws[i + 1], hws[i + 2], hws[i + 3]); + } + return 0; +} + +static struct drm_info_list i915_gem_debugfs_list[] = { + {"i915_gem_active", i915_gem_active_info, 0}, + {"i915_gem_flushing", i915_gem_flushing_info, 0}, + {"i915_gem_inactive", i915_gem_inactive_info, 0}, + {"i915_gem_request", i915_gem_request_info, 0}, + {"i915_gem_seqno", i915_gem_seqno_info, 0}, + {"i915_gem_interrupt", i915_interrupt_info, 0}, + {"i915_gem_hws", i915_hws_info, 0}, +}; +#define I915_GEM_DEBUGFS_ENTRIES ARRAY_SIZE(i915_gem_debugfs_list) + +int i915_gem_debugfs_init(struct drm_minor *minor) +{ + return drm_debugfs_create_files(i915_gem_debugfs_list, + I915_GEM_DEBUGFS_ENTRIES, + minor->debugfs_root, minor); +} + +void i915_gem_debugfs_cleanup(struct drm_minor *minor) +{ + drm_debugfs_remove_files(i915_gem_debugfs_list, + I915_GEM_DEBUGFS_ENTRIES, minor); +} + +#endif /* CONFIG_DEBUG_FS */ + diff --git a/drivers/gpu/drm/i915/i915_gem_proc.c b/drivers/gpu/drm/i915/i915_gem_proc.c deleted file mode 100644 index 4d1b9de0cd8..00000000000 --- a/drivers/gpu/drm/i915/i915_gem_proc.c +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright © 2008 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - * Authors: - * Eric Anholt - * Keith Packard - * - */ - -#include "drmP.h" -#include "drm.h" -#include "i915_drm.h" -#include "i915_drv.h" - -static int i915_gem_active_info(char *buf, char **start, off_t offset, - int request, int *eof, void *data) -{ - struct drm_minor *minor = (struct drm_minor *) data; - struct drm_device *dev = minor->dev; - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv; - int len = 0; - - if (offset > DRM_PROC_LIMIT) { - *eof = 1; - return 0; - } - - *start = &buf[offset]; - *eof = 0; - DRM_PROC_PRINT("Active:\n"); - list_for_each_entry(obj_priv, &dev_priv->mm.active_list, - list) - { - struct drm_gem_object *obj = obj_priv->obj; - if (obj->name) { - DRM_PROC_PRINT(" %p(%d): %08x %08x %d\n", - obj, obj->name, - obj->read_domains, obj->write_domain, - obj_priv->last_rendering_seqno); - } else { - DRM_PROC_PRINT(" %p: %08x %08x %d\n", - obj, - obj->read_domains, obj->write_domain, - obj_priv->last_rendering_seqno); - } - } - if (len > request + offset) - return request; - *eof = 1; - return len - offset; -} - -static int i915_gem_flushing_info(char *buf, char **start, off_t offset, - int request, int *eof, void *data) -{ - struct drm_minor *minor = (struct drm_minor *) data; - struct drm_device *dev = minor->dev; - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv; - int len = 0; - - if (offset > DRM_PROC_LIMIT) { - *eof = 1; - return 0; - } - - *start = &buf[offset]; - *eof = 0; - DRM_PROC_PRINT("Flushing:\n"); - list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list, - list) - { - struct drm_gem_object *obj = obj_priv->obj; - if (obj->name) { - DRM_PROC_PRINT(" %p(%d): %08x %08x %d\n", - obj, obj->name, - obj->read_domains, obj->write_domain, - obj_priv->last_rendering_seqno); - } else { - DRM_PROC_PRINT(" %p: %08x %08x %d\n", obj, - obj->read_domains, obj->write_domain, - obj_priv->last_rendering_seqno); - } - } - if (len > request + offset) - return request; - *eof = 1; - return len - offset; -} - -static int i915_gem_inactive_info(char *buf, char **start, off_t offset, - int request, int *eof, void *data) -{ - struct drm_minor *minor = (struct drm_minor *) data; - struct drm_device *dev = minor->dev; - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv; - int len = 0; - - if (offset > DRM_PROC_LIMIT) { - *eof = 1; - return 0; - } - - *start = &buf[offset]; - *eof = 0; - DRM_PROC_PRINT("Inactive:\n"); - list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, - list) - { - struct drm_gem_object *obj = obj_priv->obj; - if (obj->name) { - DRM_PROC_PRINT(" %p(%d): %08x %08x %d\n", - obj, obj->name, - obj->read_domains, obj->write_domain, - obj_priv->last_rendering_seqno); - } else { - DRM_PROC_PRINT(" %p: %08x %08x %d\n", obj, - obj->read_domains, obj->write_domain, - obj_priv->last_rendering_seqno); - } - } - if (len > request + offset) - return request; - *eof = 1; - return len - offset; -} - -static int i915_gem_request_info(char *buf, char **start, off_t offset, - int request, int *eof, void *data) -{ - struct drm_minor *minor = (struct drm_minor *) data; - struct drm_device *dev = minor->dev; - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_request *gem_request; - int len = 0; - - if (offset > DRM_PROC_LIMIT) { - *eof = 1; - return 0; - } - - *start = &buf[offset]; - *eof = 0; - DRM_PROC_PRINT("Request:\n"); - list_for_each_entry(gem_request, &dev_priv->mm.request_list, - list) - { - DRM_PROC_PRINT(" %d @ %d\n", - gem_request->seqno, - (int) (jiffies - gem_request->emitted_jiffies)); - } - if (len > request + offset) - return request; - *eof = 1; - return len - offset; -} - -static int i915_gem_seqno_info(char *buf, char **start, off_t offset, - int request, int *eof, void *data) -{ - struct drm_minor *minor = (struct drm_minor *) data; - struct drm_device *dev = minor->dev; - drm_i915_private_t *dev_priv = dev->dev_private; - int len = 0; - - if (offset > DRM_PROC_LIMIT) { - *eof = 1; - return 0; - } - - *start = &buf[offset]; - *eof = 0; - if (dev_priv->hw_status_page != NULL) { - DRM_PROC_PRINT("Current sequence: %d\n", - i915_get_gem_seqno(dev)); - } else { - DRM_PROC_PRINT("Current sequence: hws uninitialized\n"); - } - DRM_PROC_PRINT("Waiter sequence: %d\n", - dev_priv->mm.waiting_gem_seqno); - DRM_PROC_PRINT("IRQ sequence: %d\n", dev_priv->mm.irq_gem_seqno); - if (len > request + offset) - return request; - *eof = 1; - return len - offset; -} - - -static int i915_interrupt_info(char *buf, char **start, off_t offset, - int request, int *eof, void *data) -{ - struct drm_minor *minor = (struct drm_minor *) data; - struct drm_device *dev = minor->dev; - drm_i915_private_t *dev_priv = dev->dev_private; - int len = 0; - - if (offset > DRM_PROC_LIMIT) { - *eof = 1; - return 0; - } - - *start = &buf[offset]; - *eof = 0; - DRM_PROC_PRINT("Interrupt enable: %08x\n", - I915_READ(IER)); - DRM_PROC_PRINT("Interrupt identity: %08x\n", - I915_READ(IIR)); - DRM_PROC_PRINT("Interrupt mask: %08x\n", - I915_READ(IMR)); - DRM_PROC_PRINT("Pipe A stat: %08x\n", - I915_READ(PIPEASTAT)); - DRM_PROC_PRINT("Pipe B stat: %08x\n", - I915_READ(PIPEBSTAT)); - DRM_PROC_PRINT("Interrupts received: %d\n", - atomic_read(&dev_priv->irq_received)); - if (dev_priv->hw_status_page != NULL) { - DRM_PROC_PRINT("Current sequence: %d\n", - i915_get_gem_seqno(dev)); - } else { - DRM_PROC_PRINT("Current sequence: hws uninitialized\n"); - } - DRM_PROC_PRINT("Waiter sequence: %d\n", - dev_priv->mm.waiting_gem_seqno); - DRM_PROC_PRINT("IRQ sequence: %d\n", - dev_priv->mm.irq_gem_seqno); - if (len > request + offset) - return request; - *eof = 1; - return len - offset; -} - -static int i915_hws_info(char *buf, char **start, off_t offset, - int request, int *eof, void *data) -{ - struct drm_minor *minor = (struct drm_minor *) data; - struct drm_device *dev = minor->dev; - drm_i915_private_t *dev_priv = dev->dev_private; - int len = 0, i; - volatile u32 *hws; - - if (offset > DRM_PROC_LIMIT) { - *eof = 1; - return 0; - } - - hws = (volatile u32 *)dev_priv->hw_status_page; - if (hws == NULL) { - *eof = 1; - return 0; - } - - *start = &buf[offset]; - *eof = 0; - for (i = 0; i < 4096 / sizeof(u32) / 4; i += 4) { - DRM_PROC_PRINT("0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n", - i * 4, - hws[i], hws[i + 1], hws[i + 2], hws[i + 3]); - } - if (len > request + offset) - return request; - *eof = 1; - return len - offset; -} - -static struct drm_proc_list { - /** file name */ - const char *name; - /** proc callback*/ - int (*f) (char *, char **, off_t, int, int *, void *); -} i915_gem_proc_list[] = { - {"i915_gem_active", i915_gem_active_info}, - {"i915_gem_flushing", i915_gem_flushing_info}, - {"i915_gem_inactive", i915_gem_inactive_info}, - {"i915_gem_request", i915_gem_request_info}, - {"i915_gem_seqno", i915_gem_seqno_info}, - {"i915_gem_interrupt", i915_interrupt_info}, - {"i915_gem_hws", i915_hws_info}, -}; - -#define I915_GEM_PROC_ENTRIES ARRAY_SIZE(i915_gem_proc_list) - -int i915_gem_proc_init(struct drm_minor *minor) -{ - struct proc_dir_entry *ent; - int i, j; - - for (i = 0; i < I915_GEM_PROC_ENTRIES; i++) { - ent = create_proc_entry(i915_gem_proc_list[i].name, - S_IFREG | S_IRUGO, minor->dev_root); - if (!ent) { - DRM_ERROR("Cannot create /proc/dri/.../%s\n", - i915_gem_proc_list[i].name); - for (j = 0; j < i; j++) - remove_proc_entry(i915_gem_proc_list[i].name, - minor->dev_root); - return -1; - } - ent->read_proc = i915_gem_proc_list[i].f; - ent->data = minor; - } - return 0; -} - -void i915_gem_proc_cleanup(struct drm_minor *minor) -{ - int i; - - if (!minor->dev_root) - return; - - for (i = 0; i < I915_GEM_PROC_ENTRIES; i++) - remove_proc_entry(i915_gem_proc_list[i].name, minor->dev_root); -} -- GitLab From 433e12f78b68a8069f54956edf766bb21394c197 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Tue, 17 Feb 2009 20:08:51 -0500 Subject: [PATCH 4819/4982] drm/i915: Consolidate gem object list dumping Here we eliminate a few functions in favor of using a single function to dump from all of the object lists. Signed-Off-By: Ben Gamari Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem_debugfs.c | 86 ++++++++----------------- 1 file changed, 28 insertions(+), 58 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_debugfs.c b/drivers/gpu/drm/i915/i915_gem_debugfs.c index dd2b0edb996..4fc845cee80 100644 --- a/drivers/gpu/drm/i915/i915_gem_debugfs.c +++ b/drivers/gpu/drm/i915/i915_gem_debugfs.c @@ -37,69 +37,38 @@ #if defined(CONFIG_DEBUG_FS) -static int i915_gem_active_info(struct seq_file *m, void *data) -{ - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_device *dev = node->minor->dev; - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv; - - seq_printf(m, "Active:\n"); - list_for_each_entry(obj_priv, &dev_priv->mm.active_list, - list) - { - struct drm_gem_object *obj = obj_priv->obj; - if (obj->name) { - seq_printf(m, " %p(%d): %08x %08x %d\n", - obj, obj->name, - obj->read_domains, obj->write_domain, - obj_priv->last_rendering_seqno); - } else { - seq_printf(m, " %p: %08x %08x %d\n", - obj, - obj->read_domains, obj->write_domain, - obj_priv->last_rendering_seqno); - } - } - return 0; -} +#define ACTIVE_LIST 1 +#define FLUSHING_LIST 2 +#define INACTIVE_LIST 3 -static int i915_gem_flushing_info(struct seq_file *m, void *data) +static int i915_gem_object_list_info(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; + uintptr_t list = (uintptr_t) node->info_ent->data; + struct list_head *head; struct drm_device *dev = node->minor->dev; drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj_priv; - seq_printf(m, "Flushing:\n"); - list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list, - list) - { - struct drm_gem_object *obj = obj_priv->obj; - if (obj->name) { - seq_printf(m, " %p(%d): %08x %08x %d\n", - obj, obj->name, - obj->read_domains, obj->write_domain, - obj_priv->last_rendering_seqno); - } else { - seq_printf(m, " %p: %08x %08x %d\n", obj, - obj->read_domains, obj->write_domain, - obj_priv->last_rendering_seqno); - } + switch (list) { + case ACTIVE_LIST: + seq_printf(m, "Active:\n"); + head = &dev_priv->mm.active_list; + break; + case INACTIVE_LIST: + seq_printf(m, "Inctive:\n"); + head = &dev_priv->mm.inactive_list; + break; + case FLUSHING_LIST: + seq_printf(m, "Flushing:\n"); + head = &dev_priv->mm.flushing_list; + break; + default: + DRM_INFO("Ooops, unexpected list\n"); + return 0; } - return 0; -} -static int i915_gem_inactive_info(struct seq_file *m, void *data) -{ - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_device *dev = node->minor->dev; - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv; - - seq_printf(m, "Inactive:\n"); - list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, - list) + list_for_each_entry(obj_priv, head, list) { struct drm_gem_object *obj = obj_priv->obj; if (obj->name) { @@ -108,7 +77,8 @@ static int i915_gem_inactive_info(struct seq_file *m, void *data) obj->read_domains, obj->write_domain, obj_priv->last_rendering_seqno); } else { - seq_printf(m, " %p: %08x %08x %d\n", obj, + seq_printf(m, " %p: %08x %08x %d\n", + obj, obj->read_domains, obj->write_domain, obj_priv->last_rendering_seqno); } @@ -203,9 +173,9 @@ static int i915_hws_info(struct seq_file *m, void *data) } static struct drm_info_list i915_gem_debugfs_list[] = { - {"i915_gem_active", i915_gem_active_info, 0}, - {"i915_gem_flushing", i915_gem_flushing_info, 0}, - {"i915_gem_inactive", i915_gem_inactive_info, 0}, + {"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST}, + {"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST}, + {"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST}, {"i915_gem_request", i915_gem_request_info, 0}, {"i915_gem_seqno", i915_gem_seqno_info, 0}, {"i915_gem_interrupt", i915_interrupt_info, 0}, -- GitLab From f4ceda89895b56e2c03dd327f13d0256838a20ab Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 17 Feb 2009 23:53:41 -0800 Subject: [PATCH 4820/4982] drm/i915: Add information on pinning and fencing to the i915 list debug. This was inspired by a patch by Chris Wilson, though none of it applied in any way due to the debugfs work and I decided to change the formatting of the new information anyway. Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem_debugfs.c | 31 ++++++++++++++++--------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_debugfs.c b/drivers/gpu/drm/i915/i915_gem_debugfs.c index 4fc845cee80..f7e7d3750f8 100644 --- a/drivers/gpu/drm/i915/i915_gem_debugfs.c +++ b/drivers/gpu/drm/i915/i915_gem_debugfs.c @@ -70,18 +70,27 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) list_for_each_entry(obj_priv, head, list) { + char *pin_description; struct drm_gem_object *obj = obj_priv->obj; - if (obj->name) { - seq_printf(m, " %p(%d): %08x %08x %d\n", - obj, obj->name, - obj->read_domains, obj->write_domain, - obj_priv->last_rendering_seqno); - } else { - seq_printf(m, " %p: %08x %08x %d\n", - obj, - obj->read_domains, obj->write_domain, - obj_priv->last_rendering_seqno); - } + + if (obj_priv->user_pin_count > 0) + pin_description = "P"; + else if (obj_priv->pin_count > 0) + pin_description = "p"; + else + pin_description = " "; + + seq_printf(m, " %p: %s %08x %08x %d", + obj, + pin_description, + obj->read_domains, obj->write_domain, + obj_priv->last_rendering_seqno); + + if (obj->name) + seq_printf(m, " (name: %d)", obj->name); + if (obj_priv->fence_reg != I915_FENCE_REG_NONE) + seq_printf(m, " (fence: %d\n", obj_priv->fence_reg); + seq_printf(m, "\n"); } return 0; } -- GitLab From a6172a80ecb7ac64151960de1f709f78b509c57c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 11 Feb 2009 14:26:38 +0000 Subject: [PATCH 4821/4982] drm/i915: Display fence register state in debugfs i915_gem_fence_regs node. Signed-off-by: Chris Wilson Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem_debugfs.c | 66 +++++++++++++++++++++---- 1 file changed, 57 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_debugfs.c b/drivers/gpu/drm/i915/i915_gem_debugfs.c index f7e7d3750f8..5a4cdb5d287 100644 --- a/drivers/gpu/drm/i915/i915_gem_debugfs.c +++ b/drivers/gpu/drm/i915/i915_gem_debugfs.c @@ -41,6 +41,26 @@ #define FLUSHING_LIST 2 #define INACTIVE_LIST 3 +static const char *get_pin_flag(struct drm_i915_gem_object *obj_priv) +{ + if (obj_priv->user_pin_count > 0) + return "P"; + else if (obj_priv->pin_count > 0) + return "p"; + else + return " "; +} + +static const char *get_tiling_flag(struct drm_i915_gem_object *obj_priv) +{ + switch (obj_priv->tiling_mode) { + default: + case I915_TILING_NONE: return " "; + case I915_TILING_X: return "X"; + case I915_TILING_Y: return "Y"; + } +} + static int i915_gem_object_list_info(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; @@ -70,19 +90,11 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) list_for_each_entry(obj_priv, head, list) { - char *pin_description; struct drm_gem_object *obj = obj_priv->obj; - if (obj_priv->user_pin_count > 0) - pin_description = "P"; - else if (obj_priv->pin_count > 0) - pin_description = "p"; - else - pin_description = " "; - seq_printf(m, " %p: %s %08x %08x %d", obj, - pin_description, + get_pin_flag(obj_priv), obj->read_domains, obj->write_domain, obj_priv->last_rendering_seqno); @@ -161,6 +173,41 @@ static int i915_interrupt_info(struct seq_file *m, void *data) return 0; } +static int i915_gem_fence_regs_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + int i; + + seq_printf(m, "Reserved fences = %d\n", dev_priv->fence_reg_start); + seq_printf(m, "Total fences = %d\n", dev_priv->num_fence_regs); + for (i = 0; i < dev_priv->num_fence_regs; i++) { + struct drm_gem_object *obj = dev_priv->fence_regs[i].obj; + + if (obj == NULL) { + seq_printf(m, "Fenced object[%2d] = unused\n", i); + } else { + struct drm_i915_gem_object *obj_priv; + + obj_priv = obj->driver_private; + seq_printf(m, "Fenced object[%2d] = %p: %s " + "%08x %08x %08x %s %08x %08x %d", + i, obj, get_pin_flag(obj_priv), + obj_priv->gtt_offset, + obj->size, obj_priv->stride, + get_tiling_flag(obj_priv), + obj->read_domains, obj->write_domain, + obj_priv->last_rendering_seqno); + if (obj->name) + seq_printf(m, " (name: %d)", obj->name); + seq_printf(m, "\n"); + } + } + + return 0; +} + static int i915_hws_info(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; @@ -187,6 +234,7 @@ static struct drm_info_list i915_gem_debugfs_list[] = { {"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST}, {"i915_gem_request", i915_gem_request_info, 0}, {"i915_gem_seqno", i915_gem_seqno_info, 0}, + {"i915_gem_fence_regs", i915_gem_fence_regs_info, 0}, {"i915_gem_interrupt", i915_interrupt_info, 0}, {"i915_gem_hws", i915_hws_info, 0}, }; -- GitLab From ad086c833d00ef3be56ec554b1061f19e87a6210 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Fri, 20 Feb 2009 08:30:19 +0000 Subject: [PATCH 4822/4982] i915/drm: Remove two redundant agp_chipset_flushes agp_chipset_flush() is for flushing the intel GMCH write cache via the IFP, these two uses are for when we're getting the object into the cpu READ domain, and thus should not be needed. This confused me when I was getting my head around the code. With thanks to airlied for helping me check my mental picture of how the flushes and clflushes are supposed to be used. Signed-off-by: Owain G. Ainsworth Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index f135c903305..b52cba0f16d 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2381,7 +2381,6 @@ i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) static int i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) { - struct drm_device *dev = obj->dev; int ret; i915_gem_object_flush_gpu_write_domain(obj); @@ -2400,7 +2399,6 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) /* Flush the CPU cache if it's still invalid. */ if ((obj->read_domains & I915_GEM_DOMAIN_CPU) == 0) { i915_gem_clflush_object(obj); - drm_agp_chipset_flush(dev); obj->read_domains |= I915_GEM_DOMAIN_CPU; } @@ -2612,7 +2610,6 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj) static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj) { - struct drm_device *dev = obj->dev; struct drm_i915_gem_object *obj_priv = obj->driver_private; if (!obj_priv->page_cpu_valid) @@ -2628,7 +2625,6 @@ i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj) continue; drm_clflush_pages(obj_priv->pages + i, 1); } - drm_agp_chipset_flush(dev); } /* Free the page_cpu_valid mappings which are now stale, whether -- GitLab From 2177832f2e20fceb32142bb4fd33ae68c8af8c5a Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Mon, 23 Feb 2009 15:19:16 +0800 Subject: [PATCH 4823/4982] agp/intel: Add support for new intel chipset. This is a G33-like desktop and mobile chipset. Signed-off-by: Shaohua Li Signed-off-by: Eric Anholt --- drivers/char/agp/intel-agp.c | 21 ++++- drivers/gpu/drm/i915/i915_drv.h | 10 ++- drivers/gpu/drm/i915/i915_reg.h | 4 + drivers/gpu/drm/i915/intel_display.c | 113 +++++++++++++++++++++++---- include/drm/drm_pciids.h | 2 + 5 files changed, 128 insertions(+), 22 deletions(-) diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 4373adb2119..9d9490e22e0 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -26,6 +26,10 @@ #define PCI_DEVICE_ID_INTEL_82965GME_IG 0x2A12 #define PCI_DEVICE_ID_INTEL_82945GME_HB 0x27AC #define PCI_DEVICE_ID_INTEL_82945GME_IG 0x27AE +#define PCI_DEVICE_ID_INTEL_IGDGM_HB 0xA010 +#define PCI_DEVICE_ID_INTEL_IGDGM_IG 0xA011 +#define PCI_DEVICE_ID_INTEL_IGDG_HB 0xA000 +#define PCI_DEVICE_ID_INTEL_IGDG_IG 0xA001 #define PCI_DEVICE_ID_INTEL_G33_HB 0x29C0 #define PCI_DEVICE_ID_INTEL_G33_IG 0x29C2 #define PCI_DEVICE_ID_INTEL_Q35_HB 0x29B0 @@ -60,7 +64,12 @@ #define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q33_HB) + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q33_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDGM_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDG_HB) + +#define IS_IGD (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDGM_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDG_HB) #define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGD_E_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \ @@ -510,7 +519,7 @@ static void intel_i830_init_gtt_entries(void) size = 512; } size += 4; /* add in BIOS popup space */ - } else if (IS_G33) { + } else if (IS_G33 && !IS_IGD) { /* G33's GTT size defined in gmch_ctrl */ switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) { case G33_PGETBL_SIZE_1M: @@ -526,7 +535,7 @@ static void intel_i830_init_gtt_entries(void) size = 512; } size += 4; - } else if (IS_G4X) { + } else if (IS_G4X || IS_IGD) { /* On 4 series hardware, GTT stolen is separate from graphics * stolen, ignore it in stolen gtt entries counting. However, * 4KB of the stolen memory doesn't get mapped to the GTT. @@ -2161,6 +2170,10 @@ static const struct intel_driver_description { NULL, &intel_g33_driver }, { PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, 0, "Q33", NULL, &intel_g33_driver }, + { PCI_DEVICE_ID_INTEL_IGDGM_HB, PCI_DEVICE_ID_INTEL_IGDGM_IG, 0, "IGD", + NULL, &intel_g33_driver }, + { PCI_DEVICE_ID_INTEL_IGDG_HB, PCI_DEVICE_ID_INTEL_IGDG_IG, 0, "IGD", + NULL, &intel_g33_driver }, { PCI_DEVICE_ID_INTEL_GM45_HB, PCI_DEVICE_ID_INTEL_GM45_IG, 0, "Mobile Intel® GM45 Express", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_IGD_E_HB, PCI_DEVICE_ID_INTEL_IGD_E_IG, 0, @@ -2355,6 +2368,8 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_82945G_HB), ID(PCI_DEVICE_ID_INTEL_82945GM_HB), ID(PCI_DEVICE_ID_INTEL_82945GME_HB), + ID(PCI_DEVICE_ID_INTEL_IGDGM_HB), + ID(PCI_DEVICE_ID_INTEL_IGDG_HB), ID(PCI_DEVICE_ID_INTEL_82946GZ_HB), ID(PCI_DEVICE_ID_INTEL_82G35_HB), ID(PCI_DEVICE_ID_INTEL_82965Q_HB), diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1c03b3e81ff..c1685d0c704 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -787,15 +787,21 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); (dev)->pci_device == 0x2E22 || \ IS_GM45(dev)) +#define IS_IGDG(dev) ((dev)->pci_device == 0xa001) +#define IS_IGDGM(dev) ((dev)->pci_device == 0xa011) +#define IS_IGD(dev) (IS_IGDG(dev) || IS_IGDGM(dev)) + #define IS_G33(dev) ((dev)->pci_device == 0x29C2 || \ (dev)->pci_device == 0x29B2 || \ - (dev)->pci_device == 0x29D2) + (dev)->pci_device == 0x29D2 || \ + (IS_IGD(dev))) #define IS_I9XX(dev) (IS_I915G(dev) || IS_I915GM(dev) || IS_I945G(dev) || \ IS_I945GM(dev) || IS_I965G(dev) || IS_G33(dev)) #define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \ - IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev)) + IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev) || \ + IS_IGD(dev)) #define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev)) /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 90600d89941..6d567772679 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -359,6 +359,7 @@ #define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */ #define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */ #define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ +#define DPLL_FPA01_P1_POST_DIV_MASK_IGD 0x00ff8000 /* IGD */ #define I915_FIFO_UNDERRUN_STATUS (1UL<<31) #define I915_CRC_ERROR_ENABLE (1UL<<29) @@ -435,6 +436,7 @@ */ #define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000 #define DPLL_FPA01_P1_POST_DIV_SHIFT 16 +#define DPLL_FPA01_P1_POST_DIV_SHIFT_IGD 15 /* i830, required in DVO non-gang */ #define PLL_P2_DIVIDE_BY_4 (1 << 23) #define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */ @@ -501,10 +503,12 @@ #define FPB0 0x06048 #define FPB1 0x0604c #define FP_N_DIV_MASK 0x003f0000 +#define FP_N_IGD_DIV_MASK 0x00ff0000 #define FP_N_DIV_SHIFT 16 #define FP_M1_DIV_MASK 0x00003f00 #define FP_M1_DIV_SHIFT 8 #define FP_M2_DIV_MASK 0x0000003f +#define FP_M2_IGD_DIV_MASK 0x000000ff #define FP_M2_DIV_SHIFT 0 #define DPLL_TEST 0x606c #define DPLLB_TEST_SDVO_DIV_1 (0 << 22) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0d40b4b6979..d9c50ff94d7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -92,18 +92,32 @@ struct intel_limit { #define I9XX_DOT_MAX 400000 #define I9XX_VCO_MIN 1400000 #define I9XX_VCO_MAX 2800000 +#define IGD_VCO_MIN 1700000 +#define IGD_VCO_MAX 3500000 #define I9XX_N_MIN 1 #define I9XX_N_MAX 6 +/* IGD's Ncounter is a ring counter */ +#define IGD_N_MIN 3 +#define IGD_N_MAX 6 #define I9XX_M_MIN 70 #define I9XX_M_MAX 120 +#define IGD_M_MIN 2 +#define IGD_M_MAX 256 #define I9XX_M1_MIN 10 #define I9XX_M1_MAX 22 #define I9XX_M2_MIN 5 #define I9XX_M2_MAX 9 +/* IGD M1 is reserved, and must be 0 */ +#define IGD_M1_MIN 0 +#define IGD_M1_MAX 0 +#define IGD_M2_MIN 0 +#define IGD_M2_MAX 254 #define I9XX_P_SDVO_DAC_MIN 5 #define I9XX_P_SDVO_DAC_MAX 80 #define I9XX_P_LVDS_MIN 7 #define I9XX_P_LVDS_MAX 98 +#define IGD_P_LVDS_MIN 7 +#define IGD_P_LVDS_MAX 112 #define I9XX_P1_MIN 1 #define I9XX_P1_MAX 8 #define I9XX_P2_SDVO_DAC_SLOW 10 @@ -121,6 +135,8 @@ struct intel_limit { #define INTEL_LIMIT_G4X_HDMI_DAC 5 #define INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS 6 #define INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS 7 +#define INTEL_LIMIT_IGD_SDVO_DAC 8 +#define INTEL_LIMIT_IGD_LVDS 9 /*The parameter is for SDVO on G4x platform*/ #define G4X_DOT_SDVO_MIN 25000 @@ -340,6 +356,32 @@ static const intel_limit_t intel_limits[] = { }, .find_pll = intel_g4x_find_best_PLL, }, + { /* INTEL_LIMIT_IGD_SDVO */ + .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, + .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, + .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, + .m = { .min = IGD_M_MIN, .max = IGD_M_MAX }, + .m1 = { .min = IGD_M1_MIN, .max = IGD_M1_MAX }, + .m2 = { .min = IGD_M2_MIN, .max = IGD_M2_MAX }, + .p = { .min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX }, + .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX }, + .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, + .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, + }, + { /* INTEL_LIMIT_IGD_LVDS */ + .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, + .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, + .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, + .m = { .min = IGD_M_MIN, .max = IGD_M_MAX }, + .m1 = { .min = IGD_M1_MIN, .max = IGD_M1_MAX }, + .m2 = { .min = IGD_M2_MIN, .max = IGD_M2_MAX }, + .p = { .min = IGD_P_LVDS_MIN, .max = IGD_P_LVDS_MAX }, + .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX }, + /* IGD only supports single-channel mode. */ + .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, + .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW }, + }, + }; static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc) @@ -376,11 +418,16 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc) if (IS_G4X(dev)) { limit = intel_g4x_limit(crtc); - } else if (IS_I9XX(dev)) { + } else if (IS_I9XX(dev) && !IS_IGD(dev)) { if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS]; else limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; + } else if (IS_IGD(dev)) { + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) + limit = &intel_limits[INTEL_LIMIT_IGD_LVDS]; + else + limit = &intel_limits[INTEL_LIMIT_IGD_SDVO_DAC]; } else { if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) limit = &intel_limits[INTEL_LIMIT_I8XX_LVDS]; @@ -390,8 +437,21 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc) return limit; } -static void intel_clock(int refclk, intel_clock_t *clock) +/* m1 is reserved as 0 in IGD, n is a ring counter */ +static void igd_clock(int refclk, intel_clock_t *clock) { + clock->m = clock->m2 + 2; + clock->p = clock->p1 * clock->p2; + clock->vco = refclk * clock->m / clock->n; + clock->dot = clock->vco / clock->p; +} + +static void intel_clock(struct drm_device *dev, int refclk, intel_clock_t *clock) +{ + if (IS_IGD(dev)) { + igd_clock(refclk, clock); + return; + } clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); clock->p = clock->p1 * clock->p2; clock->vco = refclk * clock->m / (clock->n + 2); @@ -427,6 +487,7 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type) static bool intel_PLL_is_valid(struct drm_crtc *crtc, intel_clock_t *clock) { const intel_limit_t *limit = intel_limit (crtc); + struct drm_device *dev = crtc->dev; if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1) INTELPllInvalid ("p1 out of range\n"); @@ -436,7 +497,7 @@ static bool intel_PLL_is_valid(struct drm_crtc *crtc, intel_clock_t *clock) INTELPllInvalid ("m2 out of range\n"); if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1) INTELPllInvalid ("m1 out of range\n"); - if (clock->m1 <= clock->m2) + if (clock->m1 <= clock->m2 && !IS_IGD(dev)) INTELPllInvalid ("m1 <= m2\n"); if (clock->m < limit->m.min || limit->m.max < clock->m) INTELPllInvalid ("m out of range\n"); @@ -486,15 +547,17 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, memset (best_clock, 0, sizeof (*best_clock)); for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) { - for (clock.m2 = limit->m2.min; clock.m2 < clock.m1 && - clock.m2 <= limit->m2.max; clock.m2++) { + for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; clock.m2++) { + /* m1 is always 0 in IGD */ + if (clock.m2 >= clock.m1 && !IS_IGD(dev)) + break; for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) { for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max; clock.p1++) { int this_err; - intel_clock(refclk, &clock); + intel_clock(dev, refclk, &clock); if (!intel_PLL_is_valid(crtc, &clock)) continue; @@ -551,7 +614,7 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, clock.p1 >= limit->p1.min; clock.p1--) { int this_err; - intel_clock(refclk, &clock); + intel_clock(dev, refclk, &clock); if (!intel_PLL_is_valid(crtc, &clock)) continue; this_err = abs(clock.dot - target) ; @@ -888,7 +951,7 @@ static int intel_get_core_clock_speed(struct drm_device *dev) return 400000; else if (IS_I915G(dev)) return 333000; - else if (IS_I945GM(dev) || IS_845G(dev)) + else if (IS_I945GM(dev) || IS_845G(dev) || IS_IGDGM(dev)) return 200000; else if (IS_I915GM(dev)) { u16 gcfgc = 0; @@ -1043,7 +1106,10 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, return -EINVAL; } - fp = clock.n << 16 | clock.m1 << 8 | clock.m2; + if (IS_IGD(dev)) + fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2; + else + fp = clock.n << 16 | clock.m1 << 8 | clock.m2; dpll = DPLL_VGA_MODE_DIS; if (IS_I9XX(dev)) { @@ -1060,7 +1126,10 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, } /* compute bitmask from p1 value */ - dpll |= (1 << (clock.p1 - 1)) << 16; + if (IS_IGD(dev)) + dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_IGD; + else + dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; switch (clock.p2) { case 5: dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; @@ -1540,10 +1609,20 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) fp = I915_READ((pipe == 0) ? FPA1 : FPB1); clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; - clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; - clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT; + if (IS_IGD(dev)) { + clock.n = ffs((fp & FP_N_IGD_DIV_MASK) >> FP_N_DIV_SHIFT) - 1; + clock.m2 = (fp & FP_M2_IGD_DIV_MASK) >> FP_M2_DIV_SHIFT; + } else { + clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT; + clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; + } + if (IS_I9XX(dev)) { - clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >> + if (IS_IGD(dev)) + clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_IGD) >> + DPLL_FPA01_P1_POST_DIV_SHIFT_IGD); + else + clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >> DPLL_FPA01_P1_POST_DIV_SHIFT); switch (dpll & DPLL_MODE_MASK) { @@ -1562,7 +1641,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) } /* XXX: Handle the 100Mhz refclk */ - intel_clock(96000, &clock); + intel_clock(dev, 96000, &clock); } else { bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN); @@ -1574,9 +1653,9 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN) { /* XXX: might not be 66MHz */ - intel_clock(66000, &clock); + intel_clock(dev, 66000, &clock); } else - intel_clock(48000, &clock); + intel_clock(dev, 48000, &clock); } else { if (dpll & PLL_P1_DIVIDE_BY_TWO) clock.p1 = 2; @@ -1589,7 +1668,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) else clock.p2 = 2; - intel_clock(48000, &clock); + intel_clock(dev, 48000, &clock); } } diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index 5165f240aa6..76c4c824303 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -418,4 +418,6 @@ {0x8086, 0x2e02, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ {0x8086, 0x2e12, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ {0x8086, 0x2e22, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0xa001, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0xa011, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ {0, 0, 0} -- GitLab From ba01079c71559304771f9d741c9bbe8b2eac22a2 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Wed, 4 Mar 2009 20:23:02 +0800 Subject: [PATCH 4824/4982] drm/i915: TV modes' parameters sync up with 2D driver This covers at least: TV: subcarrier fix for NTSC and PAL TV: fix timing parameters for PAL, 480p, 1080i Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_tv.c | 112 ++++++++++++++++---------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 56485d67369..0e606855c85 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -217,8 +217,8 @@ static const u32 filter_table[] = { */ static const struct color_conversion ntsc_m_csc_composite = { .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104, - .ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0f00, - .rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0f00, + .ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0200, + .rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0200, }; static const struct video_levels ntsc_m_levels_composite = { @@ -226,9 +226,9 @@ static const struct video_levels ntsc_m_levels_composite = { }; static const struct color_conversion ntsc_m_csc_svideo = { - .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0134, - .ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0f00, - .rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0f00, + .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0133, + .ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0200, + .rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0200, }; static const struct video_levels ntsc_m_levels_svideo = { @@ -237,8 +237,8 @@ static const struct video_levels ntsc_m_levels_svideo = { static const struct color_conversion ntsc_j_csc_composite = { .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0119, - .ru = 0x074c, .gu = 0x0546, .bu = 0x05ec, .au = 0x0f00, - .rv = 0x035a, .gv = 0x0322, .bv = 0x06e1, .av = 0x0f00, + .ru = 0x074c, .gu = 0x0546, .bu = 0x05ec, .au = 0x0200, + .rv = 0x035a, .gv = 0x0322, .bv = 0x06e1, .av = 0x0200, }; static const struct video_levels ntsc_j_levels_composite = { @@ -247,8 +247,8 @@ static const struct video_levels ntsc_j_levels_composite = { static const struct color_conversion ntsc_j_csc_svideo = { .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x014c, - .ru = 0x0788, .gu = 0x0581, .bu = 0x0322, .au = 0x0f00, - .rv = 0x0399, .gv = 0x0356, .bv = 0x070a, .av = 0x0f00, + .ru = 0x0788, .gu = 0x0581, .bu = 0x0322, .au = 0x0200, + .rv = 0x0399, .gv = 0x0356, .bv = 0x070a, .av = 0x0200, }; static const struct video_levels ntsc_j_levels_svideo = { @@ -257,8 +257,8 @@ static const struct video_levels ntsc_j_levels_svideo = { static const struct color_conversion pal_csc_composite = { .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0113, - .ru = 0x0745, .gu = 0x053f, .bu = 0x05e1, .au = 0x0f00, - .rv = 0x0353, .gv = 0x031c, .bv = 0x06dc, .av = 0x0f00, + .ru = 0x0745, .gu = 0x053f, .bu = 0x05e1, .au = 0x0200, + .rv = 0x0353, .gv = 0x031c, .bv = 0x06dc, .av = 0x0200, }; static const struct video_levels pal_levels_composite = { @@ -267,8 +267,8 @@ static const struct video_levels pal_levels_composite = { static const struct color_conversion pal_csc_svideo = { .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0145, - .ru = 0x0780, .gu = 0x0579, .bu = 0x031c, .au = 0x0f00, - .rv = 0x0390, .gv = 0x034f, .bv = 0x0705, .av = 0x0f00, + .ru = 0x0780, .gu = 0x0579, .bu = 0x031c, .au = 0x0200, + .rv = 0x0390, .gv = 0x034f, .bv = 0x0705, .av = 0x0200, }; static const struct video_levels pal_levels_svideo = { @@ -277,8 +277,8 @@ static const struct video_levels pal_levels_svideo = { static const struct color_conversion pal_m_csc_composite = { .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104, - .ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0f00, - .rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0f00, + .ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0200, + .rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0200, }; static const struct video_levels pal_m_levels_composite = { @@ -286,9 +286,9 @@ static const struct video_levels pal_m_levels_composite = { }; static const struct color_conversion pal_m_csc_svideo = { - .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0134, - .ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0f00, - .rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0f00, + .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0133, + .ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0200, + .rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0200, }; static const struct video_levels pal_m_levels_svideo = { @@ -297,8 +297,8 @@ static const struct video_levels pal_m_levels_svideo = { static const struct color_conversion pal_n_csc_composite = { .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104, - .ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0f00, - .rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0f00, + .ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0200, + .rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0200, }; static const struct video_levels pal_n_levels_composite = { @@ -306,9 +306,9 @@ static const struct video_levels pal_n_levels_composite = { }; static const struct color_conversion pal_n_csc_svideo = { - .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0134, - .ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0f00, - .rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0f00, + .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0133, + .ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0200, + .rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0200, }; static const struct video_levels pal_n_levels_svideo = { @@ -319,9 +319,9 @@ static const struct video_levels pal_n_levels_svideo = { * Component connections */ static const struct color_conversion sdtv_csc_yprpb = { - .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0146, - .ru = 0x0559, .gu = 0x0353, .bu = 0x0100, .au = 0x0f00, - .rv = 0x0100, .gv = 0x03ad, .bv = 0x074d, .av = 0x0f00, + .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0145, + .ru = 0x0559, .gu = 0x0353, .bu = 0x0100, .au = 0x0200, + .rv = 0x0100, .gv = 0x03ad, .bv = 0x074d, .av = 0x0200, }; static const struct color_conversion sdtv_csc_rgb = { @@ -331,9 +331,9 @@ static const struct color_conversion sdtv_csc_rgb = { }; static const struct color_conversion hdtv_csc_yprpb = { - .ry = 0x05b3, .gy = 0x016e, .by = 0x0728, .ay = 0x0146, - .ru = 0x07d5, .gu = 0x038b, .bu = 0x0100, .au = 0x0f00, - .rv = 0x0100, .gv = 0x03d1, .bv = 0x06bc, .av = 0x0f00, + .ry = 0x05b3, .gy = 0x016e, .by = 0x0728, .ay = 0x0145, + .ru = 0x07d5, .gu = 0x038b, .bu = 0x0100, .au = 0x0200, + .rv = 0x0100, .gv = 0x03d1, .bv = 0x06bc, .av = 0x0200, }; static const struct color_conversion hdtv_csc_rgb = { @@ -414,7 +414,7 @@ struct tv_mode { static const struct tv_mode tv_modes[] = { { .name = "NTSC-M", - .clock = 107520, + .clock = 108000, .refresh = 29970, .oversample = TV_OVERSAMPLE_8X, .component_only = 0, @@ -442,8 +442,8 @@ static const struct tv_mode tv_modes[] = { .vburst_start_f4 = 10, .vburst_end_f4 = 240, /* desired 3.5800000 actual 3.5800000 clock 107.52 */ - .dda1_inc = 136, - .dda2_inc = 7624, .dda2_size = 20013, + .dda1_inc = 135, + .dda2_inc = 20800, .dda2_size = 27456, .dda3_inc = 0, .dda3_size = 0, .sc_reset = TV_SC_RESET_EVERY_4, .pal_burst = false, @@ -457,7 +457,7 @@ static const struct tv_mode tv_modes[] = { }, { .name = "NTSC-443", - .clock = 107520, + .clock = 108000, .refresh = 29970, .oversample = TV_OVERSAMPLE_8X, .component_only = 0, @@ -485,10 +485,10 @@ static const struct tv_mode tv_modes[] = { /* desired 4.4336180 actual 4.4336180 clock 107.52 */ .dda1_inc = 168, - .dda2_inc = 18557, .dda2_size = 20625, - .dda3_inc = 0, .dda3_size = 0, - .sc_reset = TV_SC_RESET_EVERY_8, - .pal_burst = true, + .dda2_inc = 4093, .dda2_size = 27456, + .dda3_inc = 310, .dda3_size = 525, + .sc_reset = TV_SC_RESET_NEVER, + .pal_burst = false, .composite_levels = &ntsc_m_levels_composite, .composite_color = &ntsc_m_csc_composite, @@ -499,7 +499,7 @@ static const struct tv_mode tv_modes[] = { }, { .name = "NTSC-J", - .clock = 107520, + .clock = 108000, .refresh = 29970, .oversample = TV_OVERSAMPLE_8X, .component_only = 0, @@ -527,8 +527,8 @@ static const struct tv_mode tv_modes[] = { .vburst_start_f4 = 10, .vburst_end_f4 = 240, /* desired 3.5800000 actual 3.5800000 clock 107.52 */ - .dda1_inc = 136, - .dda2_inc = 7624, .dda2_size = 20013, + .dda1_inc = 135, + .dda2_inc = 20800, .dda2_size = 27456, .dda3_inc = 0, .dda3_size = 0, .sc_reset = TV_SC_RESET_EVERY_4, .pal_burst = false, @@ -542,7 +542,7 @@ static const struct tv_mode tv_modes[] = { }, { .name = "PAL-M", - .clock = 107520, + .clock = 108000, .refresh = 29970, .oversample = TV_OVERSAMPLE_8X, .component_only = 0, @@ -570,11 +570,11 @@ static const struct tv_mode tv_modes[] = { .vburst_start_f4 = 10, .vburst_end_f4 = 240, /* desired 3.5800000 actual 3.5800000 clock 107.52 */ - .dda1_inc = 136, - .dda2_inc = 7624, .dda2_size = 20013, + .dda1_inc = 135, + .dda2_inc = 16704, .dda2_size = 27456, .dda3_inc = 0, .dda3_size = 0, - .sc_reset = TV_SC_RESET_EVERY_4, - .pal_burst = false, + .sc_reset = TV_SC_RESET_EVERY_8, + .pal_burst = true, .composite_levels = &pal_m_levels_composite, .composite_color = &pal_m_csc_composite, @@ -586,7 +586,7 @@ static const struct tv_mode tv_modes[] = { { /* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */ .name = "PAL-N", - .clock = 107520, + .clock = 108000, .refresh = 25000, .oversample = TV_OVERSAMPLE_8X, .component_only = 0, @@ -615,9 +615,9 @@ static const struct tv_mode tv_modes[] = { /* desired 4.4336180 actual 4.4336180 clock 107.52 */ - .dda1_inc = 168, - .dda2_inc = 18557, .dda2_size = 20625, - .dda3_inc = 0, .dda3_size = 0, + .dda1_inc = 135, + .dda2_inc = 23578, .dda2_size = 27648, + .dda3_inc = 134, .dda3_size = 625, .sc_reset = TV_SC_RESET_EVERY_8, .pal_burst = true, @@ -631,12 +631,12 @@ static const struct tv_mode tv_modes[] = { { /* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */ .name = "PAL", - .clock = 107520, + .clock = 108000, .refresh = 25000, .oversample = TV_OVERSAMPLE_8X, .component_only = 0, - .hsync_end = 64, .hblank_end = 128, + .hsync_end = 64, .hblank_end = 142, .hblank_start = 844, .htotal = 863, .progressive = false, .trilevel_sync = false, @@ -659,8 +659,8 @@ static const struct tv_mode tv_modes[] = { /* desired 4.4336180 actual 4.4336180 clock 107.52 */ .dda1_inc = 168, - .dda2_inc = 18557, .dda2_size = 20625, - .dda3_inc = 0, .dda3_size = 0, + .dda2_inc = 4122, .dda2_size = 27648, + .dda3_inc = 67, .dda3_size = 625, .sc_reset = TV_SC_RESET_EVERY_8, .pal_burst = true, @@ -689,7 +689,7 @@ static const struct tv_mode tv_modes[] = { .veq_ena = false, .vi_end_f1 = 44, .vi_end_f2 = 44, - .nbr_end = 496, + .nbr_end = 479, .burst_ena = false, @@ -713,7 +713,7 @@ static const struct tv_mode tv_modes[] = { .veq_ena = false, .vi_end_f1 = 44, .vi_end_f2 = 44, - .nbr_end = 496, + .nbr_end = 479, .burst_ena = false, @@ -876,7 +876,7 @@ static const struct tv_mode tv_modes[] = { .component_only = 1, .hsync_end = 88, .hblank_end = 235, - .hblank_start = 2155, .htotal = 2200, + .hblank_start = 2155, .htotal = 2201, .progressive = false, .trilevel_sync = true, -- GitLab From 6bcdcd9e3c09d133e3278edabebc314a2451b74a Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Tue, 3 Mar 2009 18:06:42 +0800 Subject: [PATCH 4825/4982] drm/i915: Sync mode_valid/mode_set with intel video driver This covers: Limit CRT DAC speed better. and also clears the border color in case it's set to some garbage, which would fix ugly outlines in the blank regions of the CRT. Signed-off-by: Zhao Yakui [anholt: replaced *drm_dev with *dev] Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_crt.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index dcaed3466e8..e58defa247d 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -64,11 +64,21 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode) static int intel_crt_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { + struct drm_device *dev = connector->dev; + + int max_clock = 0; if (mode->flags & DRM_MODE_FLAG_DBLSCAN) return MODE_NO_DBLESCAN; - if (mode->clock > 400000 || mode->clock < 25000) - return MODE_CLOCK_RANGE; + if (mode->clock < 25000) + return MODE_CLOCK_LOW; + + if (!IS_I9XX(dev)) + max_clock = 350000; + else + max_clock = 400000; + if (mode->clock > max_clock) + return MODE_CLOCK_HIGH; return MODE_OK; } @@ -113,10 +123,13 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) adpa |= ADPA_VSYNC_ACTIVE_HIGH; - if (intel_crtc->pipe == 0) + if (intel_crtc->pipe == 0) { adpa |= ADPA_PIPE_A_SELECT; - else + I915_WRITE(BCLRPAT_A, 0); + } else { adpa |= ADPA_PIPE_B_SELECT; + I915_WRITE(BCLRPAT_B, 0); + } I915_WRITE(ADPA, adpa); } -- GitLab From 771cb081354161eea21534ba58e5cc1a2db94a25 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Tue, 3 Mar 2009 18:07:52 +0800 Subject: [PATCH 4826/4982] drm/i915: Sync crt hotplug detection with intel video driver This covers: Use long crt hotplug activation time on GM45. Signed-off-by: Zhao Yakui Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_reg.h | 16 ++++++++++++ drivers/gpu/drm/i915/intel_crt.c | 45 +++++++++++++++++++++++--------- 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 6d567772679..05b1894fa13 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -633,6 +633,22 @@ #define TV_HOTPLUG_INT_EN (1 << 18) #define CRT_HOTPLUG_INT_EN (1 << 9) #define CRT_HOTPLUG_FORCE_DETECT (1 << 3) +#define CRT_HOTPLUG_ACTIVATION_PERIOD_32 (0 << 8) +/* must use period 64 on GM45 according to docs */ +#define CRT_HOTPLUG_ACTIVATION_PERIOD_64 (1 << 8) +#define CRT_HOTPLUG_DAC_ON_TIME_2M (0 << 7) +#define CRT_HOTPLUG_DAC_ON_TIME_4M (1 << 7) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_40 (0 << 5) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_50 (1 << 5) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_60 (2 << 5) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_70 (3 << 5) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_MASK (3 << 5) +#define CRT_HOTPLUG_DETECT_DELAY_1G (0 << 4) +#define CRT_HOTPLUG_DETECT_DELAY_2G (1 << 4) +#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2) +#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) +#define CRT_HOTPLUG_MASK (0x3fc) /* Bits 9-2 */ + #define PORT_HOTPLUG_STAT 0x61114 #define HDMIB_HOTPLUG_INT_STATUS (1 << 29) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index e58defa247d..2b6d44381c3 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -146,20 +146,39 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) { struct drm_device *dev = connector->dev; struct drm_i915_private *dev_priv = dev->dev_private; - u32 temp; - - unsigned long timeout = jiffies + msecs_to_jiffies(1000); - - temp = I915_READ(PORT_HOTPLUG_EN); - - I915_WRITE(PORT_HOTPLUG_EN, - temp | CRT_HOTPLUG_FORCE_DETECT | (1 << 5)); + u32 hotplug_en; + int i, tries = 0; + /* + * On 4 series desktop, CRT detect sequence need to be done twice + * to get a reliable result. + */ - do { - if (!(I915_READ(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT)) - break; - msleep(1); - } while (time_after(timeout, jiffies)); + if (IS_G4X(dev) && !IS_GM45(dev)) + tries = 2; + else + tries = 1; + hotplug_en = I915_READ(PORT_HOTPLUG_EN); + hotplug_en &= ~(CRT_HOTPLUG_MASK); + hotplug_en |= CRT_HOTPLUG_FORCE_DETECT; + + if (IS_GM45(dev)) + hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; + + hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; + + for (i = 0; i < tries ; i++) { + unsigned long timeout; + /* turn on the FORCE_DETECT */ + I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); + timeout = jiffies + msecs_to_jiffies(1000); + /* wait for FORCE_DETECT to go off */ + do { + if (!(I915_READ(PORT_HOTPLUG_EN) & + CRT_HOTPLUG_FORCE_DETECT)) + break; + msleep(1); + } while (time_after(timeout, jiffies)); + } if ((I915_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) == CRT_HOTPLUG_MONITOR_COLOR) -- GitLab From 02c5dd985ddc5407aa9cc7e0f4456ca63b294f16 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Wed, 4 Mar 2009 19:36:01 +0800 Subject: [PATCH 4827/4982] drm/i915: Fix TV get_modes to return modes count The get_modes hook must return the number of modes added. This also fixes TV mode's clock calculation int overflow issue, and use 0.01 precision for mode refresh validation. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_tv.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 0e606855c85..08c4034c44c 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1082,7 +1082,7 @@ intel_tv_mode_valid(struct drm_connector *connector, struct drm_display_mode *mo const struct tv_mode *tv_mode = intel_tv_mode_find(intel_output); /* Ensure TV refresh is close to desired refresh */ - if (tv_mode && abs(tv_mode->refresh - drm_mode_vrefresh(mode)) < 1) + if (tv_mode && abs(tv_mode->refresh - drm_mode_vrefresh(mode)) < 10) return MODE_OK; return MODE_CLOCK_RANGE; } @@ -1495,7 +1495,8 @@ intel_tv_get_modes(struct drm_connector *connector) struct drm_display_mode *mode_ptr; struct intel_output *intel_output = to_intel_output(connector); const struct tv_mode *tv_mode = intel_tv_mode_find(intel_output); - int j; + int j, count = 0; + u64 tmp; for (j = 0; j < sizeof(input_res_table) / sizeof(input_res_table[0]); j++) { @@ -1510,8 +1511,9 @@ intel_tv_get_modes(struct drm_connector *connector) && !tv_mode->component_only)) continue; - mode_ptr = drm_calloc(1, sizeof(struct drm_display_mode), - DRM_MEM_DRIVER); + mode_ptr = drm_mode_create(connector->dev); + if (!mode_ptr) + continue; strncpy(mode_ptr->name, input->name, DRM_DISPLAY_MODE_LEN); mode_ptr->hdisplay = hactive_s; @@ -1528,15 +1530,17 @@ intel_tv_get_modes(struct drm_connector *connector) mode_ptr->vsync_end = mode_ptr->vsync_start + 1; mode_ptr->vtotal = vactive_s + 33; - mode_ptr->clock = (int) (tv_mode->refresh * - mode_ptr->vtotal * - mode_ptr->htotal / 1000) / 1000; + tmp = (u64) tv_mode->refresh * mode_ptr->vtotal; + tmp *= mode_ptr->htotal; + tmp = div_u64(tmp, 1000000); + mode_ptr->clock = (int) tmp; mode_ptr->type = DRM_MODE_TYPE_DRIVER; drm_mode_probed_add(connector, mode_ptr); + count++; } - return 0; + return count; } static void -- GitLab From d2d9f23240a7ec29a496ee072ffdf69c4f6cdc76 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Wed, 4 Mar 2009 19:36:02 +0800 Subject: [PATCH 4828/4982] drm/i915: TV mode_set sync up with 2D driver Fix TV control save register for untouched bits, and color knobs different definition for 945 and 965 chips. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_reg.h | 2 +- drivers/gpu/drm/i915/intel_tv.c | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 05b1894fa13..377cc588f5e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -876,7 +876,7 @@ */ # define TV_ENC_C0_FIX (1 << 10) /** Bits that must be preserved by software */ -# define TV_CTL_SAVE ((3 << 8) | (3 << 6)) +# define TV_CTL_SAVE ((1 << 11) | (3 << 9) | (7 << 6) | 0xf) # define TV_FUSE_STATE_MASK (3 << 4) /** Read-only state that reports all features enabled */ # define TV_FUSE_STATE_ENABLED (0 << 4) diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 08c4034c44c..7021798f98e 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1135,7 +1135,8 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, if (!tv_mode) return; /* can't happen (mode_prepare prevents this) */ - tv_ctl = 0; + tv_ctl = I915_READ(TV_CTL); + tv_ctl &= TV_CTL_SAVE; switch (tv_priv->type) { default: @@ -1215,7 +1216,6 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, /* dda1 implies valid video levels */ if (tv_mode->dda1_inc) { scctl1 |= TV_SC_DDA1_EN; - scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT; } if (tv_mode->dda2_inc) @@ -1225,6 +1225,7 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, scctl1 |= TV_SC_DDA3_EN; scctl1 |= tv_mode->sc_reset; + scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT; scctl1 |= tv_mode->dda1_inc << TV_SCDDA1_INC_SHIFT; scctl2 = tv_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT | @@ -1266,7 +1267,11 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, color_conversion->av); } - I915_WRITE(TV_CLR_KNOBS, 0x00606000); + if (IS_I965G(dev)) + I915_WRITE(TV_CLR_KNOBS, 0x00404000); + else + I915_WRITE(TV_CLR_KNOBS, 0x00606000); + if (video_levels) I915_WRITE(TV_CLR_LEVEL, ((video_levels->black << TV_BLACK_LEVEL_SHIFT) | -- GitLab From bf5a269a4cc966f783b9faaf3fffd8fa31b53383 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Wed, 4 Mar 2009 19:36:03 +0800 Subject: [PATCH 4829/4982] drm/i915: TV detection fix Check that the encoder has a real enabled crtc for TV detect, and fix missing TV type setting after detect. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_tv.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 7021798f98e..ceca9471a75 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1406,6 +1406,7 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_output *intel_output) tv_dac = I915_READ(TV_DAC); I915_WRITE(TV_DAC, save_tv_dac); I915_WRITE(TV_CTL, save_tv_ctl); + intel_wait_for_vblank(dev); } /* * A B C @@ -1456,7 +1457,7 @@ intel_tv_detect(struct drm_connector *connector) mode = reported_modes[0]; drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V); - if (encoder->crtc) { + if (encoder->crtc && encoder->crtc->enabled) { type = intel_tv_detect_type(encoder->crtc, intel_output); } else { crtc = intel_get_load_detect_pipe(intel_output, &mode, &dpms_mode); @@ -1467,6 +1468,8 @@ intel_tv_detect(struct drm_connector *connector) type = -1; } + tv_priv->type = type; + if (type < 0) return connector_status_disconnected; -- GitLab From 98787c057fdefdce6230ff46f2c1105835005a4c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 6 Mar 2009 23:27:52 +0000 Subject: [PATCH 4830/4982] drm/i915: Check for dev->primary->master before dereference. I've hit the occasional oops inside i915_wait_ring() with an indication of a NULL derefence of dev->primary->master. Adding a NULL check is consistent with the other potential users of dev->primary->master. Signed-off-by: Chris Wilson Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_dma.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index ae83fe0ab37..a818b377e1f 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -41,7 +41,6 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller) { drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; drm_i915_ring_buffer_t *ring = &(dev_priv->ring); u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD; u32 last_acthd = I915_READ(acthd_reg); @@ -58,8 +57,12 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller) if (ring->space >= n) return 0; - if (master_priv->sarea_priv) - master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; + if (dev->primary->master) { + struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; + if (master_priv->sarea_priv) + master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; + } + if (ring->head != last_head) i = 0; -- GitLab From 2b5cde2b272f56ec67b56a2af8c067d42eff7328 Mon Sep 17 00:00:00 2001 From: Li Peng Date: Fri, 13 Mar 2009 10:25:07 +0800 Subject: [PATCH 4831/4982] drm/i915: Fix LVDS dither setting Update bdb_lvds_options structure according to its defination in 2D driver. Then we can parse and set 'lvds_dither' bit correctly on non-965 chips. Signed-off-by: Li Peng Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_bios.h | 12 ++++++------ drivers/gpu/drm/i915/intel_lvds.c | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 5ea715ace3a..de621aad85b 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -162,13 +162,13 @@ struct bdb_lvds_options { u8 panel_type; u8 rsvd1; /* LVDS capabilities, stored in a dword */ - u8 rsvd2:1; - u8 lvds_edid:1; - u8 pixel_dither:1; - u8 pfit_ratio_auto:1; - u8 pfit_gfx_mode_enhanced:1; - u8 pfit_text_mode_enhanced:1; u8 pfit_mode:2; + u8 pfit_text_mode_enhanced:1; + u8 pfit_gfx_mode_enhanced:1; + u8 pfit_ratio_auto:1; + u8 pixel_dither:1; + u8 lvds_edid:1; + u8 rsvd2:1; u8 rsvd4; } __attribute__((packed)); diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 0d211af9885..6619f26e46a 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -265,7 +265,7 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, pfit_control = 0; if (!IS_I965G(dev)) { - if (dev_priv->panel_wants_dither) + if (dev_priv->panel_wants_dither || dev_priv->lvds_dither) pfit_control |= PANEL_8TO6_DITHER_ENABLE; } else -- GitLab From 5b28beaf88436fa44fc25ee27a2fadffb75f222e Mon Sep 17 00:00:00 2001 From: Li Yang Date: Fri, 27 Mar 2009 15:54:30 -0700 Subject: [PATCH 4832/4982] gianfar: only check headroom when FCB is needed Signed-off-by: Li Yang Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 44cbf2622b4..6a38800be3f 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -1310,8 +1310,10 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) base = priv->tx_bd_base; - /* make space for additional header */ - if (skb_headroom(skb) < GMAC_FCB_LEN) { + /* make space for additional header when fcb is needed */ + if (((skb->ip_summed == CHECKSUM_PARTIAL) || + (priv->vlgrp && vlan_tx_tag_present(skb))) && + (skb_headroom(skb) < GMAC_FCB_LEN)) { struct sk_buff *skb_new; skb_new = skb_realloc_headroom(skb, GMAC_FCB_LEN); -- GitLab From cc0be3227df9146968311308a9d19db1469ce1db Mon Sep 17 00:00:00 2001 From: Dmitri Vorobiev Date: Fri, 27 Mar 2009 15:55:36 -0700 Subject: [PATCH 4833/4982] net: Add missing include into include/linux/netdevice.h The inline function skb_gro_mac_header defined in include/linux/netdevice.h makes use of page_address(). Depending on configuration options, the latter is either defined as a macro or is declared as a function in another header file, namely include/linux/mm.h. However, include/linux/netdevice.h does not include include/linux/mm.h. On MIPS, this has produced the following build error: CC kernel/sysctl_check.o In file included from include/linux/icmpv6.h:173, from include/linux/ipv6.h:208, from include/net/ip_vs.h:26, from kernel/sysctl_check.c:6: include/linux/netdevice.h: In function 'skb_gro_mac_header': include/linux/netdevice.h:1132: error: implicit declaration of function 'page_address' include/linux/netdevice.h:1133: warning: pointer/integer type mismatch in conditional expression make[1]: *** [kernel/sysctl_check.o] Error 1 make: *** [kernel] Error 2 The patch adds the missing include and fixes the build error. Signed-off-by: Dmitri Vorobiev Signed-off-by: David S. Miller --- include/linux/netdevice.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index be3ebd7e8ce..1b55952a17f 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -32,6 +32,7 @@ #ifdef __KERNEL__ #include #include +#include #include #include #include -- GitLab From 79675900cbf2c4e67e95f94983ec4ee800b83739 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Fri, 27 Mar 2009 16:00:03 -0700 Subject: [PATCH 4834/4982] ucc_geth: Fix three oopses in PHY {de,}initialization code When there are no free snums, UCC ethernet should gracefully fail, but currently it oopses this way: # ifconfig eth0 up fill_init_enet_entries: Can not get SNUM. ucc_geth_startup: Can not fill p_init_enet_param_shadow. eth0: Cannot configure net device, aborting. Unable to handle kernel paging request for data at address 0x00000190 Faulting instruction address: 0xc0294c88 Oops: Kernel access of bad area, sig: 11 [#1] [...] NIP [c0294c88] mutex_lock+0x0/0x1c LR [c01b6be8] phy_stop+0x20/0x70 Call Trace: [efb25da0] [efb2eb60] 0xefb2eb60 (unreliable) [efb25db0] [c01b2058] ucc_geth_stop+0x2c/0x8c [efb25dd0] [c01b4194] ucc_geth_open+0x48/0x27c [efb25df0] [c020eec0] dev_open+0xc0/0x118 [...] This is because the ucc_geth_stop() routine assumes that ugeth->phydev is always initialized by the ucc_geth_open(), while it is not in case of errors. If we add a check to the ucc_geth_stop(), then another oops pops up: Unable to handle kernel paging request for data at address 0x00000004 Faulting instruction address: 0xc01b46a4 Oops: Kernel access of bad area, sig: 11 [#1] [...] NIP [c01b46a4] adjust_link+0x20/0x1b4 LR [c01b770c] phy_state_machine+0xdc/0x44c Call Trace: [ef83bf10] [c021b388] linkwatch_schedule_work+0x74/0xf8 (unreliable) [ef83bf40] [c01b770c] phy_state_machine+0xdc/0x44c [ef83bf60] [c004c13c] run_workqueue+0xb8/0x148 [ef83bf90] [c004c870] worker_thread+0x70/0xd0 [ef83bfd0] [c00505fc] kthread+0x48/0x84 [ef83bff0] [c000f464] kernel_thread+0x4c/0x68 [...] That one happens because ucc_geth_stop() does not call phy_disconnect() and so phylib state machine is running without any idea that a MAC has just died. Also, when device tree specifies fixed-link, and CONFIG_FIXED_PHY is disabled, we'll get this oops: 0:01 not found eth2: Could not attach to PHY eth2: Cannot initialize PHY, aborting. Unable to handle kernel paging request for data at address 0x00000190 Faulting instruction address: 0xc02967d0 Oops: Kernel access of bad area, sig: 11 [#1] [...] NIP [c02967d0] mutex_lock+0x0/0x1c LR [c01b6bcc] phy_stop+0x20/0x70 Call Trace: [ef82be50] [efb6bb60] 0xefb6bb60 (unreliable) [ef82be60] [c01b2058] ucc_geth_stop+0x2c/0x8c [ef82be80] [c01b4194] ucc_geth_open+0x48/0x27c [ef82bea0] [c0210a04] dev_open+0xc0/0x118 [ef82bec0] [c020f85c] dev_change_flags+0x84/0x1ac [ef82bee0] [c037b768] ic_open_devs+0x168/0x2bc [ef82bf20] [c037ca98] ip_auto_config+0x90/0x28c [ef82bf60] [c0001b9c] do_one_initcall+0x34/0x1a0 [ef82bfd0] [c035e240] do_initcalls+0x38/0x58 [ef82bfe0] [c035e2c4] kernel_init+0x30/0x90 [ef82bff0] [c000f464] kernel_thread+0x4c/0x68 [...] And again, ucc_geth_stop() assumes that ugeth->phydev is there, while it isn't. This patch fixes all three oopses simply by rearranging some code: - In ucc_geth_open(): move init_phy() call to the beginning, so that we only call ucc_geth_stop() with a PHY attached; - Move phy_disconnect() call from ucc_geth_close() to ucc_geth_stop(), so that we'll always disconnect the PHY. Signed-off-by: Anton Vorontsov Signed-off-by: David S. Miller --- drivers/net/ucc_geth.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index a110326dce6..86a479f61c0 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -2009,6 +2009,9 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth) /* Disable Rx and Tx */ clrbits32(&ug_regs->maccfg1, MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX); + phy_disconnect(ugeth->phydev); + ugeth->phydev = NULL; + ucc_geth_memclean(ugeth); } @@ -3345,6 +3348,14 @@ static int ucc_geth_open(struct net_device *dev) return -EINVAL; } + err = init_phy(dev); + if (err) { + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Cannot initialize PHY, aborting.", + dev->name); + return err; + } + err = ucc_struct_init(ugeth); if (err) { if (netif_msg_ifup(ugeth)) @@ -3381,13 +3392,6 @@ static int ucc_geth_open(struct net_device *dev) &ugeth->ug_regs->macstnaddr1, &ugeth->ug_regs->macstnaddr2); - err = init_phy(dev); - if (err) { - if (netif_msg_ifup(ugeth)) - ugeth_err("%s: Cannot initialize PHY, aborting.", dev->name); - goto out_err; - } - phy_start(ugeth->phydev); err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX); @@ -3430,9 +3434,6 @@ static int ucc_geth_close(struct net_device *dev) free_irq(ugeth->ug_info->uf_info.irq, ugeth->dev); - phy_disconnect(ugeth->phydev); - ugeth->phydev = NULL; - netif_stop_queue(dev); return 0; -- GitLab From 0b4d569de222452bcb55a4a536ade6cf4d8d1e30 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 27 Mar 2009 17:02:09 -0700 Subject: [PATCH 4835/4982] i915: fix wrong 'size_t' format string For the fifteen bazillionth time. See also commits f06da264cfb0f9444d41ca247213e419f90aa72a and aeb565dfc3ac4c8b47c5049085b4c7bfb2c7d5d7 ("i915: Fix more size_t format string warnings" and "Fix annoying DRM_ERROR() string warning"). Grr-target: Eric Anholt Grr-target: Chris Wilson Signed-off-by: Linus Torvalds --- drivers/gpu/drm/i915/i915_gem_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_debugfs.c b/drivers/gpu/drm/i915/i915_gem_debugfs.c index 5a4cdb5d287..455ec970b38 100644 --- a/drivers/gpu/drm/i915/i915_gem_debugfs.c +++ b/drivers/gpu/drm/i915/i915_gem_debugfs.c @@ -192,7 +192,7 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data) obj_priv = obj->driver_private; seq_printf(m, "Fenced object[%2d] = %p: %s " - "%08x %08x %08x %s %08x %08x %d", + "%08x %08zx %08x %s %08x %08x %d", i, obj, get_pin_flag(obj_priv), obj_priv->gtt_offset, obj->size, obj_priv->stride, -- GitLab From fa56dddd6720c8d4b9fa4c942377d2a019cf3708 Mon Sep 17 00:00:00 2001 From: Alina Friedrichsen Date: Tue, 10 Mar 2009 00:49:46 +0100 Subject: [PATCH 4836/4982] mac80211: ieee80211_ibss_commit() cleanup Don't call ieee80211_sta_find_ibss() directly, like it's done in STA mode, so that the commit() call is more harmless respectively has less site-effects. Signed-off-by: Alina Friedrichsen Signed-off-by: John W. Linville --- net/mac80211/ibss.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index f4becc12904..3201e1f9636 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -812,8 +812,9 @@ int ieee80211_ibss_commit(struct ieee80211_sub_if_data *sdata) ifibss->ibss_join_req = jiffies; ifibss->state = IEEE80211_IBSS_MLME_SEARCH; + set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request); - return ieee80211_sta_find_ibss(sdata); + return 0; } int ieee80211_ibss_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len) -- GitLab From 633e24ed95b6c87b42f201ecb65c12a75a5a7eef Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Thu, 12 Mar 2009 09:20:40 -0700 Subject: [PATCH 4837/4982] cfg80211/nl80211: remove usage of CONFIG_NL80211 The scan capability added to cfg80211/nl80211 introduced a dependency on nl80211 by cfg80211. We can thus no longer have just cfg80211 without nl80211. Specifically, cfg80211_scan_done() calls nl80211_send_scan_aborted() or nl80211_send_scan_done(). Now we remove the option for user to select nl80211. It will always be compiled if user selects cfg80211. Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- net/wireless/Kconfig | 13 ------------- net/wireless/Makefile | 3 +-- net/wireless/nl80211.h | 26 -------------------------- 3 files changed, 1 insertion(+), 41 deletions(-) diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 092ae6faccc..d1d18f34d27 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig @@ -10,19 +10,6 @@ config CFG80211_REG_DEBUG If unsure, say N. -config NL80211 - bool "nl80211 new netlink interface support" - depends on CFG80211 - default y - ---help--- - This option turns on the new netlink interface - (nl80211) support in cfg80211. - - If =n, drivers using mac80211 will be configured via - wireless extension support provided by that subsystem. - - If unsure, say Y. - config WIRELESS_OLD_REGULATORY bool "Old wireless static regulatory definitions" default y diff --git a/net/wireless/Makefile b/net/wireless/Makefile index dad43c24f69..c157b4d8014 100644 --- a/net/wireless/Makefile +++ b/net/wireless/Makefile @@ -5,8 +5,7 @@ obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib80211_crypt_wep.o obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o -cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o +cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o -cfg80211-$(CONFIG_NL80211) += nl80211.o ccflags-y += -D__CHECK_ENDIAN__ diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index e65a3c38c52..5b5fe1339de 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -3,7 +3,6 @@ #include "core.h" -#ifdef CONFIG_NL80211 extern int nl80211_init(void); extern void nl80211_exit(void); extern void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev); @@ -12,30 +11,5 @@ extern void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, extern void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, struct net_device *netdev); extern void nl80211_send_reg_change_event(struct regulatory_request *request); -#else -static inline int nl80211_init(void) -{ - return 0; -} -static inline void nl80211_exit(void) -{ -} -static inline void nl80211_notify_dev_rename( - struct cfg80211_registered_device *rdev) -{ -} -static inline void -nl80211_send_scan_done(struct cfg80211_registered_device *rdev, - struct net_device *netdev) -{} -static inline void nl80211_send_scan_aborted( - struct cfg80211_registered_device *rdev, - struct net_device *netdev) -{} -static inline void -nl80211_send_reg_change_event(struct regulatory_request *request) -{ -} -#endif /* CONFIG_NL80211 */ #endif /* __NET_WIRELESS_NL80211_H */ -- GitLab From 14587ce2a8898de959f32dfd505b4871f09930d5 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 12 Mar 2009 15:32:54 +0530 Subject: [PATCH 4838/4982] ath9k: Set IEEE80211_TX_CTL_RATE_CTRL_PROBE in rate control for probe rate Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/rc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 832735677a4..28d69da342c 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -864,6 +864,8 @@ static void ath_rc_ratefind(struct ath_softc *sc, rate_table, nrix, 1, 0); ath_rc_rate_set_series(rate_table, &rates[i++], txrc, try_per_rate, nrix, 0); + + tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; } else { try_per_rate = (ATH_11N_TXMAXTRY/4); /* Set the choosen rate. No RTS for first series entry. */ -- GitLab From 176be728ee7d32cfd33702d82c0733e51f66ab5b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 12 Mar 2009 23:49:28 +0100 Subject: [PATCH 4839/4982] mac80211: remove ieee80211_num_regular_queues This inline is useless and actually makes the code _longer_ rather than shorter. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 5 ----- net/mac80211/mlme.c | 2 +- net/mac80211/tx.c | 7 +++---- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 12a52efcd0d..3bfc6c6c8c4 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1017,11 +1017,6 @@ static inline void SET_IEEE80211_PERM_ADDR(struct ieee80211_hw *hw, u8 *addr) memcpy(hw->wiphy->perm_addr, addr, ETH_ALEN); } -static inline int ieee80211_num_regular_queues(struct ieee80211_hw *hw) -{ - return hw->queues; -} - static inline struct ieee80211_rate * ieee80211_get_tx_rate(const struct ieee80211_hw *hw, const struct ieee80211_tx_info *c) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 841b8450b3d..aaf7793583a 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1834,7 +1834,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) ifmgd->flags |= IEEE80211_STA_CREATE_IBSS | IEEE80211_STA_AUTO_BSSID_SEL | IEEE80211_STA_AUTO_CHANNEL_SEL; - if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4) + if (sdata->local->hw.queues >= 4) ifmgd->flags |= IEEE80211_STA_WMM_ENABLED; } diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 457238a2f3f..038460b0a48 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1666,8 +1666,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, } /* receiver and we are QoS enabled, use a QoS type frame */ - if (sta_flags & WLAN_STA_WME && - ieee80211_num_regular_queues(&local->hw) >= 4) { + if ((sta_flags & WLAN_STA_WME) && local->hw.queues >= 4) { fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA); hdrlen += 2; } @@ -1802,7 +1801,7 @@ void ieee80211_clear_tx_pending(struct ieee80211_local *local) int i, j; struct ieee80211_tx_stored_packet *store; - for (i = 0; i < ieee80211_num_regular_queues(&local->hw); i++) { + for (i = 0; i < local->hw.queues; i++) { if (!test_bit(i, local->queues_pending)) continue; store = &local->pending_packet[i]; @@ -1827,7 +1826,7 @@ void ieee80211_tx_pending(unsigned long data) int i, ret; netif_tx_lock_bh(dev); - for (i = 0; i < ieee80211_num_regular_queues(&local->hw); i++) { + for (i = 0; i < local->hw.queues; i++) { /* Check that this queue is ok */ if (__netif_subqueue_stopped(local->mdev, i) && !test_bit(i, local->queues_pending_run)) -- GitLab From 51b381479ff5bc9b8c49ce15fd8bc35c6b695ca4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 12 Mar 2009 11:16:48 +0100 Subject: [PATCH 4840/4982] mac80211: reduce max number of queues No hw/driver actually supports more than four queues right now, and we allocate a number of things per queue which means we waste a bit of memory. Reduce the maximum number to four to accurately reflect what we do (and need for QoS). Even if we had hardware supporting more queues we couldn't take advantage of that right now anyway. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 3bfc6c6c8c4..a38a82c785d 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -97,7 +97,7 @@ struct ieee80211_ht_bss_info { * for A-MPDU operation. */ enum ieee80211_max_queues { - IEEE80211_MAX_QUEUES = 16, + IEEE80211_MAX_QUEUES = 4, IEEE80211_MAX_AMPDU_QUEUES = 16, }; -- GitLab From 11432379fd2a3854a3408424d8dcd99afd811573 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Thu, 12 Mar 2009 14:04:34 +0100 Subject: [PATCH 4841/4982] mac80211: start pending scan after probe/auth/assoc timed out If a scan is queued in STA mode while the interface is in state direct probe, authenticate or associate the scan is delayed until the interface enters disabled or associated state. But in case of direct probe-, authentication- or association- timeout sta_work will not be scheduled anymore (without external trigger) and thus the pending scan is not executed and prevents a new scan from being triggered (-EBUSY). Fix this by queueing the sta work again after direct probe-, authentication- and association- timeout. Signed-off-by: Helmut Schaa Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index aaf7793583a..a55879663b3 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -682,6 +682,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct ieee80211_local *local = sdata->local; ifmgd->direct_probe_tries++; if (ifmgd->direct_probe_tries > IEEE80211_AUTH_MAX_TRIES) { @@ -697,6 +698,13 @@ static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata) ieee80211_rx_bss_remove(sdata, ifmgd->bssid, sdata->local->hw.conf.channel->center_freq, ifmgd->ssid, ifmgd->ssid_len); + + /* + * We might have a pending scan which had no chance to run yet + * due to state == IEEE80211_STA_MLME_DIRECT_PROBE. + * Hence, queue the STAs work again + */ + queue_work(local->hw.workqueue, &ifmgd->work); return; } @@ -721,6 +729,7 @@ static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata) static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct ieee80211_local *local = sdata->local; ifmgd->auth_tries++; if (ifmgd->auth_tries > IEEE80211_AUTH_MAX_TRIES) { @@ -732,6 +741,13 @@ static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata) ieee80211_rx_bss_remove(sdata, ifmgd->bssid, sdata->local->hw.conf.channel->center_freq, ifmgd->ssid, ifmgd->ssid_len); + + /* + * We might have a pending scan which had no chance to run yet + * due to state == IEEE80211_STA_MLME_AUTHENTICATE. + * Hence, queue the STAs work again + */ + queue_work(local->hw.workqueue, &ifmgd->work); return; } @@ -878,6 +894,7 @@ static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata) static void ieee80211_associate(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct ieee80211_local *local = sdata->local; ifmgd->assoc_tries++; if (ifmgd->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) { @@ -889,6 +906,12 @@ static void ieee80211_associate(struct ieee80211_sub_if_data *sdata) ieee80211_rx_bss_remove(sdata, ifmgd->bssid, sdata->local->hw.conf.channel->center_freq, ifmgd->ssid, ifmgd->ssid_len); + /* + * We might have a pending scan which had no chance to run yet + * due to state == IEEE80211_STA_MLME_ASSOCIATE. + * Hence, queue the STAs work again + */ + queue_work(local->hw.workqueue, &ifmgd->work); return; } -- GitLab From 4ed96f04f8a1869757f4dd4a9283a18ec63c442f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 12 Mar 2009 21:53:23 +0200 Subject: [PATCH 4842/4982] ath9k: Add support for multiple virtual AP interfaces This patch fixes the TSF offset calculation for staggered Beacon frames and sets ATH_BCBUF back to the earlier value 4 to enable multi-BSS configurations of up to four BSSes. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ath9k.h | 3 +- drivers/net/wireless/ath9k/beacon.c | 50 ++++++++++++++--------------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index b64be8e9a69..5afd244ea6a 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -390,6 +390,7 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid struct ath_vif { int av_bslot; + __le64 tsf_adjust; /* TSF adjustment for staggered beacons */ enum nl80211_iftype av_opmode; struct ath_buf *av_bcbuf; struct ath_tx_control av_btxctl; @@ -406,7 +407,7 @@ struct ath_vif { * number of beacon intervals, the game's up. */ #define BSTUCK_THRESH (9 * ATH_BCBUF) -#define ATH_BCBUF 1 +#define ATH_BCBUF 4 #define ATH_DEFAULT_BINTVAL 100 /* TU */ #define ATH_DEFAULT_BMISS_LIMIT 10 #define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c index 039c78136c5..3fd1b86a9b3 100644 --- a/drivers/net/wireless/ath9k/beacon.c +++ b/drivers/net/wireless/ath9k/beacon.c @@ -153,6 +153,8 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, bf->bf_mpdu = skb; if (skb == NULL) return NULL; + ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = + avp->tsf_adjust; info = IEEE80211_SKB_CB(skb); if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { @@ -253,7 +255,6 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) { struct ath_softc *sc = aphy->sc; struct ath_vif *avp; - struct ieee80211_hdr *hdr; struct ath_buf *bf; struct sk_buff *skb; __le64 tstamp; @@ -316,42 +317,33 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; sc->beacon.bc_tstamp = le64_to_cpu(tstamp); - - /* - * Calculate a TSF adjustment factor required for - * staggered beacons. Note that we assume the format - * of the beacon frame leaves the tstamp field immediately - * following the header. - */ + /* Calculate a TSF adjustment factor required for staggered beacons. */ if (avp->av_bslot > 0) { u64 tsfadjust; - __le64 val; int intval; intval = sc->hw->conf.beacon_int ? sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; /* - * The beacon interval is in TU's; the TSF in usecs. - * We figure out how many TU's to add to align the - * timestamp then convert to TSF units and handle - * byte swapping before writing it in the frame. - * The hardware will then add this each time a beacon - * frame is sent. Note that we align vif's 1..N - * and leave vif 0 untouched. This means vap 0 - * has a timestamp in one beacon interval while the - * others get a timestamp aligned to the next interval. + * Calculate the TSF offset for this beacon slot, i.e., the + * number of usecs that need to be added to the timestamp field + * in Beacon and Probe Response frames. Beacon slot 0 is + * processed at the correct offset, so it does not require TSF + * adjustment. Other slots are adjusted to get the timestamp + * close to the TBTT for the BSS. */ - tsfadjust = (intval * (ATH_BCBUF - avp->av_bslot)) / ATH_BCBUF; - val = cpu_to_le64(tsfadjust << 10); /* TU->TSF */ + tsfadjust = intval * avp->av_bslot / ATH_BCBUF; + avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); DPRINTF(sc, ATH_DBG_BEACON, "stagger beacons, bslot %d intval %u tsfadjust %llu\n", avp->av_bslot, intval, (unsigned long long)tsfadjust); - hdr = (struct ieee80211_hdr *)skb->data; - memcpy(&hdr[1], &val, sizeof(val)); - } + ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = + avp->tsf_adjust; + } else + avp->tsf_adjust = cpu_to_le64(0); bf->bf_mpdu = skb; bf->bf_buf_addr = bf->bf_dmacontext = @@ -447,8 +439,16 @@ void ath_beacon_tasklet(unsigned long data) tsf = ath9k_hw_gettsf64(ah); tsftu = TSF_TO_TU(tsf>>32, tsf); slot = ((tsftu % intval) * ATH_BCBUF) / intval; - vif = sc->beacon.bslot[(slot + 1) % ATH_BCBUF]; - aphy = sc->beacon.bslot_aphy[(slot + 1) % ATH_BCBUF]; + /* + * Reverse the slot order to get slot 0 on the TBTT offset that does + * not require TSF adjustment and other slots adding + * slot/ATH_BCBUF * beacon_int to timestamp. For example, with + * ATH_BCBUF = 4, we process beacon slots as follows: 3 2 1 0 3 2 1 .. + * and slot 0 is at correct offset to TBTT. + */ + slot = ATH_BCBUF - slot - 1; + vif = sc->beacon.bslot[slot]; + aphy = sc->beacon.bslot_aphy[slot]; DPRINTF(sc, ATH_DBG_BEACON, "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", -- GitLab From b572b24c578ab1be9d1fcb11d2d8244878757a66 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 12 Mar 2009 18:18:51 -0400 Subject: [PATCH 4843/4982] ath9k: remove dummy PCI "retry timeout" fix Remove the PCI retry timeout code as that was just taken from ipw2100 due to historical reasons but in reality its a no-op, additionally its simply incorrect as each PCI devices has its own custom PCI configuration space on PCI config space >= 0x40. Not to mention we were trying to write 0 to a place that already has 0 on it. Cc: Matthew Garrett Cc: Ben Cahill Cc: Inaky Perez-Gonzalez Tested-by: Adel Gadllah Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/pci.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/drivers/net/wireless/ath9k/pci.c b/drivers/net/wireless/ath9k/pci.c index 9a58baabb9c..53572d96cdb 100644 --- a/drivers/net/wireless/ath9k/pci.c +++ b/drivers/net/wireless/ath9k/pci.c @@ -87,7 +87,6 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) struct ath_softc *sc; struct ieee80211_hw *hw; u8 csz; - u32 val; int ret = 0; struct ath_hw *ah; @@ -134,14 +133,6 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_master(pdev); - /* - * Disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state. - */ - pci_read_config_dword(pdev, 0x40, &val); - if ((val & 0x0000ff00) != 0) - pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); - ret = pci_request_region(pdev, 0, "ath9k"); if (ret) { dev_err(&pdev->dev, "PCI memory region reserve error\n"); @@ -253,21 +244,12 @@ static int ath_pci_resume(struct pci_dev *pdev) struct ieee80211_hw *hw = pci_get_drvdata(pdev); struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; - u32 val; int err; err = pci_enable_device(pdev); if (err) return err; pci_restore_state(pdev); - /* - * Suspend/Resume resets the PCI configuration space, so we have to - * re-disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state - */ - pci_read_config_dword(pdev, 0x40, &val); - if ((val & 0x0000ff00) != 0) - pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); /* Enable LED */ ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN, -- GitLab From 7d01b221b338ef2a5b1ffa9c60645c0bdcce191e Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 13 Mar 2009 08:55:55 +0530 Subject: [PATCH 4844/4982] ath9k: Miscellaneous EEPROM handling cleanup Print the EEPROM version/revision on init. Choose appropriate debug masks on error conditions, and remove useless print messages. Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/eeprom.c | 75 +++++++++-------------------- drivers/net/wireless/ath9k/hw.c | 4 ++ 2 files changed, 28 insertions(+), 51 deletions(-) diff --git a/drivers/net/wireless/ath9k/eeprom.c b/drivers/net/wireless/ath9k/eeprom.c index 183c949bcca..6c9bc5fdb04 100644 --- a/drivers/net/wireless/ath9k/eeprom.c +++ b/drivers/net/wireless/ath9k/eeprom.c @@ -342,8 +342,7 @@ static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah) static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) { #define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) - struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; - u16 *eep_data; + u16 *eep_data = (u16 *)&ah->eeprom.map4k; int addr, eep_start_loc = 0; eep_start_loc = 64; @@ -353,8 +352,6 @@ static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) "Reading from EEPROM, not flash\n"); } - eep_data = (u16 *)eep; - for (addr = 0; addr < SIZE_EEPROM_4K; addr++) { if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) { DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, @@ -363,6 +360,7 @@ static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) } eep_data++; } + return true; #undef SIZE_EEPROM_4K } @@ -379,16 +377,15 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) if (!ath9k_hw_use_flash(ah)) { - if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Reading Magic # failed\n"); return false; } DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "Read Magic = 0x%04X\n", magic); + "Read Magic = 0x%04X\n", magic); if (magic != AR5416_EEPROM_MAGIC) { magic2 = swab16(magic); @@ -401,16 +398,9 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) temp = swab16(*eepdata); *eepdata = temp; eepdata++; - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "0x%04X ", *eepdata); - - if (((addr + 1) % 6) == 0) - DPRINTF(ah->ah_sc, - ATH_DBG_EEPROM, "\n"); } } else { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Invalid EEPROM Magic. " "endianness mismatch.\n"); return -EINVAL; @@ -441,7 +431,7 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) u16 word; DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "EEPROM Endianness is not native.. Changing \n"); + "EEPROM Endianness is not native.. Changing\n"); word = swab16(eep->baseEepHeader.length); eep->baseEepHeader.length = word; @@ -483,7 +473,7 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Bad EEPROM checksum 0x%x or revision 0x%04x\n", sum, ah->eep_ops->get_eeprom_ver(ah)); return -EINVAL; @@ -1295,9 +1285,6 @@ static bool ath9k_hw_4k_set_board_values(struct ath_hw *ah, db2[4] = ((pModal->db2_234 >> 8) & 0xf); } else if (pModal->version == 1) { - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "EEPROM Model version is set to 1 \n"); ob[0] = (pModal->ob_01 & 0xf); ob[1] = ob[2] = ob[3] = ob[4] = (pModal->ob_01 >> 4) & 0xf; db1[0] = (pModal->db1_01 & 0xf); @@ -1464,16 +1451,13 @@ static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah) static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah) { #define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16)) - struct ar5416_eeprom_def *eep = &ah->eeprom.def; - u16 *eep_data; + u16 *eep_data = (u16 *)&ah->eeprom.def; int addr, ar5416_eep_start_loc = 0x100; - eep_data = (u16 *)eep; - for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) { if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc, eep_data)) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Unable to read eeprom region\n"); return false; } @@ -1492,17 +1476,14 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) bool need_swap = false; int i, addr, size; - if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, - &magic)) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "Reading Magic # failed\n"); + if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Reading Magic # failed\n"); return false; } if (!ath9k_hw_use_flash(ah)) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "Read Magic = 0x%04X\n", magic); + "Read Magic = 0x%04X\n", magic); if (magic != AR5416_EEPROM_MAGIC) { magic2 = swab16(magic); @@ -1516,18 +1497,11 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) temp = swab16(*eepdata); *eepdata = temp; eepdata++; - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "0x%04X ", *eepdata); - - if (((addr + 1) % 6) == 0) - DPRINTF(ah->ah_sc, - ATH_DBG_EEPROM, "\n"); } } else { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Invalid EEPROM Magic. " - "endianness mismatch.\n"); + "Endianness mismatch.\n"); return -EINVAL; } } @@ -1556,7 +1530,7 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) u16 word; DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "EEPROM Endianness is not native.. Changing \n"); + "EEPROM Endianness is not native.. Changing.\n"); word = swab16(eep->baseEepHeader.length); eep->baseEepHeader.length = word; @@ -1602,7 +1576,7 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Bad EEPROM checksum 0x%x or revision 0x%04x\n", sum, ah->eep_ops->get_eeprom_ver(ah)); return -EINVAL; @@ -1855,8 +1829,6 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, AR_AN_TOP2_LOCALBIAS, AR_AN_TOP2_LOCALBIAS_S, pModal->local_bias); - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "ForceXPAon: %d\n", - pModal->force_xpaon); REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG, pModal->force_xpaon); } @@ -1882,6 +1854,7 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn); + if (AR_SREV_9280_10_OR_LATER(ah)) { REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, pModal->thresh62); @@ -1912,10 +1885,10 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, } if (AR_SREV_9280_20_OR_LATER(ah) && - AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19) + AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19) REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL, - AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK, - pModal->miscBits); + AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK, + pModal->miscBits); if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) { @@ -1926,14 +1899,14 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0); else REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, - eep->baseEepHeader.dacLpMode); + eep->baseEepHeader.dacLpMode); REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP, - pModal->miscBits >> 2); + pModal->miscBits >> 2); REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9, - AR_PHY_TX_DESIRED_SCALE_CCK, - eep->baseEepHeader.desiredScaleCCK); + AR_PHY_TX_DESIRED_SCALE_CCK, + eep->baseEepHeader.desiredScaleCCK); } return true; diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index d494e98ba97..3dd054b21f5 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -588,6 +588,10 @@ static int ath9k_hw_post_attach(struct ath_hw *ah) ecode = ath9k_hw_eeprom_attach(ah); if (ecode != 0) return ecode; + + DPRINTF(ah->ah_sc, ATH_DBG_CONFIG, "Eeprom VER: %d, REV: %d\n", + ah->eep_ops->get_eeprom_ver(ah), ah->eep_ops->get_eeprom_rev(ah)); + ecode = ath9k_hw_rfattach(ah); if (ecode != 0) return ecode; -- GitLab From 355363fcf7daded4a48308b54d6b86bea4f8bb6d Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 13 Mar 2009 08:56:02 +0530 Subject: [PATCH 4845/4982] ath9k: Move AR5416_VER_MASK to a common location Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/eeprom.c | 4 ---- drivers/net/wireless/ath9k/eeprom.h | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath9k/eeprom.c b/drivers/net/wireless/ath9k/eeprom.c index 6c9bc5fdb04..49dee238c68 100644 --- a/drivers/net/wireless/ath9k/eeprom.c +++ b/drivers/net/wireless/ath9k/eeprom.c @@ -1588,7 +1588,6 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, enum eeprom_param param) { -#define AR5416_VER_MASK (pBase->version & AR5416_EEP_VER_MINOR_MASK) struct ar5416_eeprom_def *eep = &ah->eeprom.def; struct modal_eep_header *pModal = eep->modalHeader; struct base_eep_header *pBase = &eep->baseEepHeader; @@ -1655,14 +1654,12 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, default: return 0; } -#undef AR5416_VER_MASK } /* XXX: Clean me up, make me more legible */ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, struct ath9k_channel *chan) { -#define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) struct modal_eep_header *pModal; struct ar5416_eeprom_def *eep = &ah->eeprom.def; int i, regChainOffset; @@ -1910,7 +1907,6 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, } return true; -#undef AR5416_VER_MASK } static void ath9k_hw_def_set_addac(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath9k/eeprom.h b/drivers/net/wireless/ath9k/eeprom.h index d6f6108f63c..0a4b22a554d 100644 --- a/drivers/net/wireless/ath9k/eeprom.h +++ b/drivers/net/wireless/ath9k/eeprom.h @@ -95,6 +95,7 @@ #define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5)) #define ath9k_hw_use_flash(_ah) (!(_ah->ah_flags & AH_USE_EEPROM)) +#define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) #define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \ ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) -- GitLab From a83615d74d9b952f24c904baad58610ed9d76838 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 13 Mar 2009 08:56:04 +0530 Subject: [PATCH 4846/4982] ath9k: Introduce a helper function for setting board gain values This improves readability. Handle both 4K/non-4K EEPROM in this patch. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/eeprom.c | 219 +++++++++++++--------------- 1 file changed, 99 insertions(+), 120 deletions(-) diff --git a/drivers/net/wireless/ath9k/eeprom.c b/drivers/net/wireless/ath9k/eeprom.c index 49dee238c68..c3bb1968bb5 100644 --- a/drivers/net/wireless/ath9k/eeprom.c +++ b/drivers/net/wireless/ath9k/eeprom.c @@ -1193,57 +1193,63 @@ static void ath9k_hw_4k_set_addac(struct ath_hw *ah, } } -static bool ath9k_hw_4k_set_board_values(struct ath_hw *ah, - struct ath9k_channel *chan) +static void ath9k_hw_4k_set_gain(struct ath_hw *ah, + struct modal_eep_4k_header *pModal, + struct ar5416_eeprom_4k *eep, + u8 txRxAttenLocal, int regChainOffset) { - struct modal_eep_4k_header *pModal; - struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; - int regChainOffset; - u8 txRxAttenLocal; - u8 ob[5], db1[5], db2[5]; - u8 ant_div_control1, ant_div_control2; - u32 regVal; - - - pModal = &eep->modalHeader; - - txRxAttenLocal = 23; - - REG_WRITE(ah, AR_PHY_SWITCH_COM, - ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); - - regChainOffset = 0; REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, pModal->antCtrlChain[0]); REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, - (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) & - ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | - AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | - SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | - SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); + (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) & + ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | + AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | + SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | + SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_3) { + AR5416_EEP_MINOR_VER_3) { txRxAttenLocal = pModal->txRxAttenCh[0]; + REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]); + AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]); REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]); + AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]); REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, - pModal->xatten2Margin[0]); + AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, + pModal->xatten2Margin[0]); REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]); + AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]); } REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, - AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); + AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, - AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); + AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); if (AR_SREV_9285_11(ah)) REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); +} + +static bool ath9k_hw_4k_set_board_values(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + struct modal_eep_4k_header *pModal; + struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; + u8 txRxAttenLocal; + u8 ob[5], db1[5], db2[5]; + u8 ant_div_control1, ant_div_control2; + u32 regVal; + + pModal = &eep->modalHeader; + txRxAttenLocal = 23; + + REG_WRITE(ah, AR_PHY_SWITCH_COM, + ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); + + /* Single chain for 4K EEPROM*/ + ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal, 0); /* Initialize Ant Diversity settings from EEPROM */ if (pModal->version == 3) { @@ -1656,7 +1662,62 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, } } -/* XXX: Clean me up, make me more legible */ +static void ath9k_hw_def_set_gain(struct ath_hw *ah, + struct modal_eep_header *pModal, + struct ar5416_eeprom_def *eep, + u8 txRxAttenLocal, int regChainOffset, int i) +{ + if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { + txRxAttenLocal = pModal->txRxAttenCh[i]; + + if (AR_SREV_9280_10_OR_LATER(ah)) { + REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, + pModal->bswMargin[i]); + REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN1_DB, + pModal->bswAtten[i]); + REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, + pModal->xatten2Margin[i]); + REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN2_DB, + pModal->xatten2Db[i]); + } else { + REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & + ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) + | SM(pModal-> bswMargin[i], + AR_PHY_GAIN_2GHZ_BSW_MARGIN)); + REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & + ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) + | SM(pModal->bswAtten[i], + AR_PHY_GAIN_2GHZ_BSW_ATTEN)); + } + } + + if (AR_SREV_9280_10_OR_LATER(ah)) { + REG_RMW_FIELD(ah, + AR_PHY_RXGAIN + regChainOffset, + AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); + REG_RMW_FIELD(ah, + AR_PHY_RXGAIN + regChainOffset, + AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]); + } else { + REG_WRITE(ah, + AR_PHY_RXGAIN + regChainOffset, + (REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) & + ~AR_PHY_RXGAIN_TXRX_ATTEN) + | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN)); + REG_WRITE(ah, + AR_PHY_GAIN_2GHZ + regChainOffset, + (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & + ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) | + SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN)); + } +} + static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, struct ath9k_channel *chan) { @@ -1666,7 +1727,6 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, u8 txRxAttenLocal; pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); - txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44; REG_WRITE(ah, AR_PHY_SWITCH_COM, @@ -1679,8 +1739,7 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, } if (AR_SREV_5416_20_OR_LATER(ah) && - (ah->rxchainmask == 5 || ah->txchainmask == 5) - && (i != 0)) + (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0)) regChainOffset = (i == 1) ? 0x2000 : 0x1000; else regChainOffset = i * 0x1000; @@ -1689,9 +1748,7 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, pModal->antCtrlChain[i]); REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, - (REG_READ(ah, - AR_PHY_TIMING_CTRL4(0) + - regChainOffset) & + (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) & ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | SM(pModal->iqCalICh[i], @@ -1699,87 +1756,9 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, SM(pModal->iqCalQCh[i], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); - if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { - txRxAttenLocal = pModal->txRxAttenCh[i]; - if (AR_SREV_9280_10_OR_LATER(ah)) { - REG_RMW_FIELD(ah, - AR_PHY_GAIN_2GHZ + - regChainOffset, - AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, - pModal-> - bswMargin[i]); - REG_RMW_FIELD(ah, - AR_PHY_GAIN_2GHZ + - regChainOffset, - AR_PHY_GAIN_2GHZ_XATTEN1_DB, - pModal-> - bswAtten[i]); - REG_RMW_FIELD(ah, - AR_PHY_GAIN_2GHZ + - regChainOffset, - AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, - pModal-> - xatten2Margin[i]); - REG_RMW_FIELD(ah, - AR_PHY_GAIN_2GHZ + - regChainOffset, - AR_PHY_GAIN_2GHZ_XATTEN2_DB, - pModal-> - xatten2Db[i]); - } else { - REG_WRITE(ah, - AR_PHY_GAIN_2GHZ + - regChainOffset, - (REG_READ(ah, - AR_PHY_GAIN_2GHZ + - regChainOffset) & - ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) - | SM(pModal-> - bswMargin[i], - AR_PHY_GAIN_2GHZ_BSW_MARGIN)); - REG_WRITE(ah, - AR_PHY_GAIN_2GHZ + - regChainOffset, - (REG_READ(ah, - AR_PHY_GAIN_2GHZ + - regChainOffset) & - ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) - | SM(pModal->bswAtten[i], - AR_PHY_GAIN_2GHZ_BSW_ATTEN)); - } - } - if (AR_SREV_9280_10_OR_LATER(ah)) { - REG_RMW_FIELD(ah, - AR_PHY_RXGAIN + - regChainOffset, - AR9280_PHY_RXGAIN_TXRX_ATTEN, - txRxAttenLocal); - REG_RMW_FIELD(ah, - AR_PHY_RXGAIN + - regChainOffset, - AR9280_PHY_RXGAIN_TXRX_MARGIN, - pModal->rxTxMarginCh[i]); - } else { - REG_WRITE(ah, - AR_PHY_RXGAIN + regChainOffset, - (REG_READ(ah, - AR_PHY_RXGAIN + - regChainOffset) & - ~AR_PHY_RXGAIN_TXRX_ATTEN) | - SM(txRxAttenLocal, - AR_PHY_RXGAIN_TXRX_ATTEN)); - REG_WRITE(ah, - AR_PHY_GAIN_2GHZ + - regChainOffset, - (REG_READ(ah, - AR_PHY_GAIN_2GHZ + - regChainOffset) & - ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) | - SM(pModal->rxTxMarginCh[i], - AR_PHY_GAIN_2GHZ_RXTX_MARGIN)); - } - } + if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) + ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal, + regChainOffset, i); } if (AR_SREV_9280_10_OR_LATER(ah)) { -- GitLab From d6509151bd3e952b7d157ea4dbae23279d427e95 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 13 Mar 2009 08:56:05 +0530 Subject: [PATCH 4847/4982] ath9k: Change return type for set_board_values() We always return true, checking for 'false' return value is bogus anyway, so fix this. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/eeprom.c | 8 ++------ drivers/net/wireless/ath9k/eeprom.h | 2 +- drivers/net/wireless/ath9k/hw.c | 6 +----- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/ath9k/eeprom.c b/drivers/net/wireless/ath9k/eeprom.c index c3bb1968bb5..973b576c0ad 100644 --- a/drivers/net/wireless/ath9k/eeprom.c +++ b/drivers/net/wireless/ath9k/eeprom.c @@ -1232,7 +1232,7 @@ static void ath9k_hw_4k_set_gain(struct ath_hw *ah, REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); } -static bool ath9k_hw_4k_set_board_values(struct ath_hw *ah, +static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, struct ath9k_channel *chan) { struct modal_eep_4k_header *pModal; @@ -1378,8 +1378,6 @@ static bool ath9k_hw_4k_set_board_values(struct ath_hw *ah, AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40); } - - return true; } static u16 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah, @@ -1718,7 +1716,7 @@ static void ath9k_hw_def_set_gain(struct ath_hw *ah, } } -static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, +static void ath9k_hw_def_set_board_values(struct ath_hw *ah, struct ath9k_channel *chan) { struct modal_eep_header *pModal; @@ -1884,8 +1882,6 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, AR_PHY_TX_DESIRED_SCALE_CCK, eep->baseEepHeader.desiredScaleCCK); } - - return true; } static void ath9k_hw_def_set_addac(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath9k/eeprom.h b/drivers/net/wireless/ath9k/eeprom.h index 0a4b22a554d..8e5b880d445 100644 --- a/drivers/net/wireless/ath9k/eeprom.h +++ b/drivers/net/wireless/ath9k/eeprom.h @@ -490,7 +490,7 @@ struct eeprom_ops { u8 (*get_num_ant_config)(struct ath_hw *hw, enum ieee80211_band band); u16 (*get_eeprom_antenna_cfg)(struct ath_hw *hw, struct ath9k_channel *chan); - bool (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan); + void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan); void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan); int (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan, u16 cfgCtl, u8 twiceAntennaReduction, diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 3dd054b21f5..78e5763f7c1 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -2277,11 +2277,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, else ath9k_hw_spur_mitigate(ah, chan); - if (!ah->eep_ops->set_board_values(ah, chan)) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "error setting board options\n"); - return -EIO; - } + ah->eep_ops->set_board_values(ah, chan); ath9k_hw_decrease_chain_power(ah, chan); -- GitLab From e71cef37f1f4cb7e9c919cbaabe23438f10a7080 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 13 Mar 2009 08:56:07 +0530 Subject: [PATCH 4848/4982] ath9k: Fix bug in 4K EEPROM size calculation We should be checking with the 4K header and not the non-4K header size. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/eeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath9k/eeprom.c b/drivers/net/wireless/ath9k/eeprom.c index 973b576c0ad..d7b9cf4e8eb 100644 --- a/drivers/net/wireless/ath9k/eeprom.c +++ b/drivers/net/wireless/ath9k/eeprom.c @@ -416,7 +416,7 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) else el = ah->eeprom.map4k.baseEepHeader.length; - if (el > sizeof(struct ar5416_eeprom_def)) + if (el > sizeof(struct ar5416_eeprom_4k)) el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16); else el = el / sizeof(u16); -- GitLab From 95e4acb7331722236b9f11492ae2e96473210ebc Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 13 Mar 2009 08:56:09 +0530 Subject: [PATCH 4849/4982] ath9k: Fill in ack signal in TX status This patch fills the ack_signal field in TX status with an appropriate value from the TX descriptor. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/xmit.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index e3f376611f8..0aae8f349ff 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -1852,13 +1852,17 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, return nbad; } -static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, int nbad) +static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, + int nbad, int txok) { struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); + if (txok) + tx_info->status.ack_signal = ds->ds_txstat.ts_rssi; + tx_info_priv->update_rc = false; if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; @@ -1996,7 +2000,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) nbad = ath_tx_num_badfrms(sc, bf, txok); } - ath_tx_rc_status(bf, ds, nbad); + ath_tx_rc_status(bf, ds, nbad, txok); if (bf_isampdu(bf)) ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok); -- GitLab From c2da50e5837f92c9f16a611efd1bb0754036691b Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 13 Mar 2009 08:56:11 +0530 Subject: [PATCH 4850/4982] ath9k: Fix bug in handling single stream stations AP mode currently sets up the dual stream capability for all stations. This patch fixes it by checking if the associated station supports dual stream MCS rates (8-15). We would disregard any MCS rates above 15, since Atheros HW supports only 0..15 rates currently, and can't receive at rates > 15 anyway. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/rc.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 28d69da342c..74bc4e64b03 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -1470,16 +1470,18 @@ static void ath_rc_init(struct ath_softc *sc, ath_rc_priv->ht_cap); } -static u8 ath_rc_build_ht_caps(struct ath_softc *sc, bool is_ht, bool is_cw40, - bool is_sgi40) +static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta, + bool is_cw40, bool is_sgi40) { u8 caps = 0; - if (is_ht) { + if (sta->ht_cap.ht_supported) { caps = WLAN_RC_HT_FLAG; if (sc->sc_ah->caps.tx_chainmask != 1 && - ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_DS, 0, NULL)) - caps |= WLAN_RC_DS_FLAG; + ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_DS, 0, NULL)) { + if (sta->ht_cap.mcs.rx_mask[1]) + caps |= WLAN_RC_DS_FLAG; + } if (is_cw40) caps |= WLAN_RC_40_FLAG; if (is_sgi40) @@ -1626,8 +1628,7 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, rate_table = sc->cur_rate_table; } - ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta->ht_cap.ht_supported, - is_cw40, is_sgi40); + ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi40); ath_rc_init(sc, priv_sta, sband, sta, rate_table); } @@ -1661,8 +1662,7 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, rate_table = ath_choose_rate_table(sc, sband->band, sta->ht_cap.ht_supported, oper_cw40); - ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, - sta->ht_cap.ht_supported, + ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, oper_cw40, oper_sgi40); ath_rc_init(sc, priv_sta, sband, sta, rate_table); -- GitLab From cee075a24eec64f1f5b2b3b14753b2d4b8ecce55 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 13 Mar 2009 09:07:23 +0530 Subject: [PATCH 4851/4982] ath9k: Update copyright in all the files How time flies. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ahb.c | 2 +- drivers/net/wireless/ath9k/ani.c | 2 +- drivers/net/wireless/ath9k/ani.h | 2 +- drivers/net/wireless/ath9k/ath9k.h | 2 +- drivers/net/wireless/ath9k/beacon.c | 2 +- drivers/net/wireless/ath9k/calib.c | 2 +- drivers/net/wireless/ath9k/calib.h | 2 +- drivers/net/wireless/ath9k/debug.c | 2 +- drivers/net/wireless/ath9k/debug.h | 2 +- drivers/net/wireless/ath9k/eeprom.c | 2 +- drivers/net/wireless/ath9k/eeprom.h | 2 +- drivers/net/wireless/ath9k/hw.c | 2 +- drivers/net/wireless/ath9k/hw.h | 2 +- drivers/net/wireless/ath9k/initvals.h | 2 +- drivers/net/wireless/ath9k/mac.c | 2 +- drivers/net/wireless/ath9k/mac.h | 2 +- drivers/net/wireless/ath9k/main.c | 2 +- drivers/net/wireless/ath9k/pci.c | 2 +- drivers/net/wireless/ath9k/phy.c | 2 +- drivers/net/wireless/ath9k/phy.h | 2 +- drivers/net/wireless/ath9k/rc.c | 2 +- drivers/net/wireless/ath9k/rc.h | 2 +- drivers/net/wireless/ath9k/recv.c | 2 +- drivers/net/wireless/ath9k/reg.h | 2 +- drivers/net/wireless/ath9k/regd.c | 2 +- drivers/net/wireless/ath9k/regd.h | 2 +- drivers/net/wireless/ath9k/regd_common.h | 2 +- drivers/net/wireless/ath9k/xmit.c | 2 +- 28 files changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/ath9k/ahb.c b/drivers/net/wireless/ath9k/ahb.c index 00cc7bb01f2..0e65c51ba17 100644 --- a/drivers/net/wireless/ath9k/ahb.c +++ b/drivers/net/wireless/ath9k/ahb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * Copyright (c) 2009 Gabor Juhos * Copyright (c) 2009 Imre Kaloz * diff --git a/drivers/net/wireless/ath9k/ani.c b/drivers/net/wireless/ath9k/ani.c index a39eb760cbb..6c5e887d50d 100644 --- a/drivers/net/wireless/ath9k/ani.c +++ b/drivers/net/wireless/ath9k/ani.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/ani.h b/drivers/net/wireless/ath9k/ani.h index 7315761f6d7..08b4e7ed5ff 100644 --- a/drivers/net/wireless/ath9k/ani.h +++ b/drivers/net/wireless/ath9k/ani.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index 5afd244ea6a..2b025645511 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c index 3fd1b86a9b3..e5b007196ca 100644 --- a/drivers/net/wireless/ath9k/beacon.c +++ b/drivers/net/wireless/ath9k/beacon.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c index c9446fb6b15..e2d62e97131 100644 --- a/drivers/net/wireless/ath9k/calib.c +++ b/drivers/net/wireless/ath9k/calib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/calib.h b/drivers/net/wireless/ath9k/calib.h index 32589e0c501..1c74bd50700 100644 --- a/drivers/net/wireless/ath9k/calib.h +++ b/drivers/net/wireless/ath9k/calib.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/debug.c b/drivers/net/wireless/ath9k/debug.c index 82573cadb1a..fdf9528fa49 100644 --- a/drivers/net/wireless/ath9k/debug.c +++ b/drivers/net/wireless/ath9k/debug.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/debug.h b/drivers/net/wireless/ath9k/debug.h index 065268b8568..7b0e5419d2b 100644 --- a/drivers/net/wireless/ath9k/debug.h +++ b/drivers/net/wireless/ath9k/debug.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/eeprom.c b/drivers/net/wireless/ath9k/eeprom.c index d7b9cf4e8eb..ffc36b0361c 100644 --- a/drivers/net/wireless/ath9k/eeprom.c +++ b/drivers/net/wireless/ath9k/eeprom.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/eeprom.h b/drivers/net/wireless/ath9k/eeprom.h index 8e5b880d445..25b68c881ff 100644 --- a/drivers/net/wireless/ath9k/eeprom.h +++ b/drivers/net/wireless/ath9k/eeprom.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 78e5763f7c1..15e4d422cad 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/hw.h b/drivers/net/wireless/ath9k/hw.h index dc681f011fd..0b594e0ee26 100644 --- a/drivers/net/wireless/ath9k/hw.h +++ b/drivers/net/wireless/ath9k/hw.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/initvals.h b/drivers/net/wireless/ath9k/initvals.h index 1d60c3706f1..e2f0a34b79a 100644 --- a/drivers/net/wireless/ath9k/initvals.h +++ b/drivers/net/wireless/ath9k/initvals.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/mac.c b/drivers/net/wireless/ath9k/mac.c index f757bc7eec6..e0a6dee4583 100644 --- a/drivers/net/wireless/ath9k/mac.c +++ b/drivers/net/wireless/ath9k/mac.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/mac.h b/drivers/net/wireless/ath9k/mac.h index a75f65dae1d..1176bce8b76 100644 --- a/drivers/net/wireless/ath9k/mac.h +++ b/drivers/net/wireless/ath9k/mac.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 8db75f6de53..7d27eed78af 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/pci.c b/drivers/net/wireless/ath9k/pci.c index 53572d96cdb..6dbc58580ab 100644 --- a/drivers/net/wireless/ath9k/pci.c +++ b/drivers/net/wireless/ath9k/pci.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/phy.c b/drivers/net/wireless/ath9k/phy.c index e1494bae0f9..8bcba906929 100644 --- a/drivers/net/wireless/ath9k/phy.c +++ b/drivers/net/wireless/ath9k/phy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/phy.h b/drivers/net/wireless/ath9k/phy.h index 1eac8c70734..0f7f8e0c9c9 100644 --- a/drivers/net/wireless/ath9k/phy.h +++ b/drivers/net/wireless/ath9k/phy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 74bc4e64b03..6c2fd395bc3 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2004 Video54 Technologies, Inc. - * Copyright (c) 2004-2008 Atheros Communications, Inc. + * Copyright (c) 2004-2009 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/rc.h b/drivers/net/wireless/ath9k/rc.h index db9b0b9a343..199a3ce57d6 100644 --- a/drivers/net/wireless/ath9k/rc.h +++ b/drivers/net/wireless/ath9k/rc.h @@ -1,7 +1,7 @@ /* * Copyright (c) 2004 Sam Leffler, Errno Consulting * Copyright (c) 2004 Video54 Technologies, Inc. - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c index 0bba17662a1..917bac7af6f 100644 --- a/drivers/net/wireless/ath9k/recv.c +++ b/drivers/net/wireless/ath9k/recv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/reg.h b/drivers/net/wireless/ath9k/reg.h index d86e90e3817..52605246679 100644 --- a/drivers/net/wireless/ath9k/reg.h +++ b/drivers/net/wireless/ath9k/reg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/regd.c b/drivers/net/wireless/ath9k/regd.c index b8f9b6d6bec..4ca62510229 100644 --- a/drivers/net/wireless/ath9k/regd.c +++ b/drivers/net/wireless/ath9k/regd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/regd.h b/drivers/net/wireless/ath9k/regd.h index 8f885f3bc8d..9f5fbd4eea7 100644 --- a/drivers/net/wireless/ath9k/regd.h +++ b/drivers/net/wireless/ath9k/regd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/regd_common.h b/drivers/net/wireless/ath9k/regd_common.h index b41d0002f3f..4d0e298cd1c 100644 --- a/drivers/net/wireless/ath9k/regd_common.h +++ b/drivers/net/wireless/ath9k/regd_common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 0aae8f349ff..8968abe7f48 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Atheros Communications Inc. + * Copyright (c) 2008-2009 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above -- GitLab From b5bde374f0f61f5d97114d400ade8fc96bf6f10d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 13 Mar 2009 11:19:45 +0100 Subject: [PATCH 4852/4982] mac80211: fix warnings in ieee80211_if_config The last warning can never trigger, and the explicit AP_VLAN check is pointless if we move the config_interface check down, in practice config_interface is required anyway. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/main.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index f38db4d37e5..dac68d476bf 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -161,12 +161,6 @@ int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) if (WARN_ON(!netif_running(sdata->dev))) return 0; - if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) - return -EINVAL; - - if (!local->ops->config_interface) - return 0; - memset(&conf, 0, sizeof(conf)); if (sdata->vif.type == NL80211_IFTYPE_STATION) @@ -183,6 +177,9 @@ int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) return -EINVAL; } + if (!local->ops->config_interface) + return 0; + switch (sdata->vif.type) { case NL80211_IFTYPE_AP: case NL80211_IFTYPE_ADHOC: @@ -224,9 +221,6 @@ int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) } } - if (WARN_ON(!conf.bssid && (changed & IEEE80211_IFCC_BSSID))) - return -EINVAL; - conf.changed = changed; return local->ops->config_interface(local_to_hw(local), -- GitLab From 25420604c8967ff24f087dd7b9cd4b278567d39a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 13 Mar 2009 11:43:36 +0100 Subject: [PATCH 4853/4982] mac80211: stop queues across suspend/resume Even though userland probably cannot submit packets, there might still be some coming, and that's no good when the driver doesn't expect them. Stop the queues across suspend/resume. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 1 + net/mac80211/pm.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index fbb91f1aebb..ad12c2a03a9 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -598,6 +598,7 @@ enum queue_stop_reason { IEEE80211_QUEUE_STOP_REASON_PS, IEEE80211_QUEUE_STOP_REASON_CSA, IEEE80211_QUEUE_STOP_REASON_AGGREGATION, + IEEE80211_QUEUE_STOP_REASON_SUSPEND, }; struct ieee80211_master_priv { diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 44525f51707..c923ceb089a 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -11,6 +11,9 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) struct ieee80211_if_init_conf conf; struct sta_info *sta; + ieee80211_stop_queues_by_reason(hw, + IEEE80211_QUEUE_STOP_REASON_SUSPEND); + flush_workqueue(local->hw.workqueue); /* disable keys */ @@ -113,5 +116,8 @@ int __ieee80211_resume(struct ieee80211_hw *hw) ieee80211_configure_filter(local); netif_addr_unlock_bh(local->mdev); + ieee80211_wake_queues_by_reason(hw, + IEEE80211_QUEUE_STOP_REASON_SUSPEND); + return 0; } -- GitLab From aae89831df03e5282a8f5c0ee46432cfb677fc5c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 13 Mar 2009 12:52:10 +0100 Subject: [PATCH 4854/4982] wireless: radiotap updates Radiotap was updated to include a "bad PLCP" flag and standardise the "bad FCS" flag in the "flags" rather than "RX flags" field, this patch updates Linux to that standard. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/radiotap.h | 10 ---------- drivers/net/wireless/libertas/rx.c | 12 ++---------- include/net/ieee80211_radiotap.h | 4 +++- net/mac80211/rx.c | 7 ++++--- 4 files changed, 9 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/libertas/radiotap.h b/drivers/net/wireless/libertas/radiotap.h index f8eb9097ff0..d16b26416e8 100644 --- a/drivers/net/wireless/libertas/radiotap.h +++ b/drivers/net/wireless/libertas/radiotap.h @@ -33,22 +33,12 @@ struct rx_radiotap_hdr { struct ieee80211_radiotap_header hdr; u8 flags; u8 rate; - u16 chan_freq; - u16 chan_flags; - u8 antenna; u8 antsignal; - u16 rx_flags; -#if 0 - u8 pad[IEEE80211_RADIOTAP_HDRLEN - 18]; -#endif } __attribute__ ((packed)); #define RX_RADIOTAP_PRESENT ( \ (1 << IEEE80211_RADIOTAP_FLAGS) | \ (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL) | \ - (1 << IEEE80211_RADIOTAP_ANTENNA) | \ (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) |\ - (1 << IEEE80211_RADIOTAP_RX_FLAGS) | \ 0) diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 4f60948dde9..63d7e19ce9b 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c @@ -351,19 +351,11 @@ static int process_rxed_802_11_packet(struct lbs_private *priv, radiotap_hdr.hdr.it_pad = 0; radiotap_hdr.hdr.it_len = cpu_to_le16 (sizeof(struct rx_radiotap_hdr)); radiotap_hdr.hdr.it_present = cpu_to_le32 (RX_RADIOTAP_PRESENT); - /* unknown values */ - radiotap_hdr.flags = 0; - radiotap_hdr.chan_freq = 0; - radiotap_hdr.chan_flags = 0; - radiotap_hdr.antenna = 0; - /* known values */ + if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) + radiotap_hdr.flags |= IEEE80211_RADIOTAP_F_BADFCS; radiotap_hdr.rate = convert_mv_rate_to_radiotap(prxpd->rx_rate); /* XXX must check no carryout */ radiotap_hdr.antsignal = prxpd->snr + prxpd->nf; - radiotap_hdr.rx_flags = 0; - if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) - radiotap_hdr.rx_flags |= IEEE80211_RADIOTAP_F_RX_BADFCS; - //memset(radiotap_hdr.pad, 0x11, IEEE80211_RADIOTAP_HDRLEN - 18); /* chop the rxpd */ skb_pull(skb, sizeof(struct rxpd)); diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h index 384698cb773..23c3f3d9777 100644 --- a/include/net/ieee80211_radiotap.h +++ b/include/net/ieee80211_radiotap.h @@ -230,8 +230,10 @@ enum ieee80211_radiotap_type { * 802.11 header and payload * (to 32-bit boundary) */ +#define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* bad FCS */ + /* For IEEE80211_RADIOTAP_RX_FLAGS */ -#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */ +#define IEEE80211_RADIOTAP_F_RX_BADPLCP 0x0002 /* frame has bad PLCP */ /* For IEEE80211_RADIOTAP_TX_FLAGS */ #define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 66f7ecf51b9..fcc0a599579 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -142,6 +142,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, /* IEEE80211_RADIOTAP_FLAGS */ if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) *pos |= IEEE80211_RADIOTAP_F_FCS; + if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) + *pos |= IEEE80211_RADIOTAP_F_BADFCS; if (status->flag & RX_FLAG_SHORTPRE) *pos |= IEEE80211_RADIOTAP_F_SHORTPRE; pos++; @@ -204,9 +206,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, /* ensure 2 byte alignment for the 2 byte field as required */ if ((pos - (unsigned char *)rthdr) & 1) pos++; - /* FIXME: when radiotap gets a 'bad PLCP' flag use it here */ - if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) - *(__le16 *)pos |= cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADFCS); + if (status->flag & RX_FLAG_FAILED_PLCP_CRC) + *(__le16 *)pos |= cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADPLCP); pos += 2; } -- GitLab From ec30415f7935f0ff92f93a4ac87233ca3007a78a Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Fri, 13 Mar 2009 20:26:52 +0530 Subject: [PATCH 4855/4982] mac80211: Populate HT limitation with TKIP/WEP to the handler for SIOCSIWENCODE too Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- net/mac80211/wext.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 935c63ed3df..e55d2834764 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -630,7 +630,7 @@ static int ieee80211_ioctl_siwencode(struct net_device *dev, struct ieee80211_sub_if_data *sdata; int idx, i, alg = ALG_WEP; u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - int remove = 0; + int remove = 0, ret; sdata = IEEE80211_DEV_TO_SUB_IF(dev); @@ -656,11 +656,20 @@ static int ieee80211_ioctl_siwencode(struct net_device *dev, return 0; } - return ieee80211_set_encryption( + ret = ieee80211_set_encryption( sdata, bcaddr, idx, alg, remove, !sdata->default_key, keybuf, erq->length); + + if (!ret) { + if (remove) + sdata->u.mgd.flags &= ~IEEE80211_STA_TKIP_WEP_USED; + else + sdata->u.mgd.flags |= IEEE80211_STA_TKIP_WEP_USED; + } + + return ret; } -- GitLab From 8fdc621dc743b87879ccf0177969864b09388d9a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 14 Mar 2009 09:34:01 +0100 Subject: [PATCH 4856/4982] nl80211: export supported commands This makes nl80211 export the supported commands (command groups) per wiphy so userspace has an idea what it can do -- this will be required reading for userspace when we introduce auth/assoc /or/ connect for older hardware that cannot separate auth and assoc. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/nl80211.h | 6 ++++++ net/wireless/nl80211.c | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index f33aa08dd9b..3700d927e24 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -349,6 +349,10 @@ enum nl80211_commands { * @NL80211_ATTR_REG_TYPE: indicates the type of the regulatory domain currently * set. This can be one of the nl80211_reg_type (%NL80211_REGDOM_TYPE_*) * + * @NL80211_ATTR_SUPPORTED_COMMANDS: wiphy attribute that specifies + * an array of command numbers (i.e. a mapping index to command number) + * that the driver for the given wiphy supports. + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -426,6 +430,8 @@ enum nl80211_attrs { NL80211_ATTR_REG_INITIATOR, NL80211_ATTR_REG_TYPE, + NL80211_ATTR_SUPPORTED_COMMANDS, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index ab9d8f14e15..58ee1b1aff8 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -131,6 +131,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, struct nlattr *nl_freqs, *nl_freq; struct nlattr *nl_rates, *nl_rate; struct nlattr *nl_modes; + struct nlattr *nl_cmds; enum ieee80211_band band; struct ieee80211_channel *chan; struct ieee80211_rate *rate; @@ -242,6 +243,32 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, } nla_nest_end(msg, nl_bands); + nl_cmds = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_COMMANDS); + if (!nl_cmds) + goto nla_put_failure; + + i = 0; +#define CMD(op, n) \ + do { \ + if (dev->ops->op) { \ + i++; \ + NLA_PUT_U32(msg, i, NL80211_CMD_ ## n); \ + } \ + } while (0) + + CMD(add_virtual_intf, NEW_INTERFACE); + CMD(change_virtual_intf, SET_INTERFACE); + CMD(add_key, NEW_KEY); + CMD(add_beacon, NEW_BEACON); + CMD(add_station, NEW_STATION); + CMD(add_mpath, NEW_MPATH); + CMD(set_mesh_params, SET_MESH_PARAMS); + CMD(change_bss, SET_BSS); + CMD(set_mgmt_extra_ie, SET_MGMT_EXTRA_IE); + +#undef CMD + nla_nest_end(msg, nl_cmds); + return genlmsg_end(msg, hdr); nla_put_failure: -- GitLab From 7f0216a49bea717b9606b81c60f2f0b6152123eb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 14 Mar 2009 09:42:49 +0100 Subject: [PATCH 4857/4982] mac80211: acquire sta_lock for station suspend/resume To avoid concurrent manipulations of the sta list (which shouldn't be possible at this point, but anyway) we need to hold the sta_lock around iterating the list. At the same time, we do not need to iterate the list at all if the driver doesn't want to be notified. Signed-off-by: Johannes Berg Acked-by: Bob Copeland Signed-off-by: John W. Linville --- net/mac80211/pm.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index c923ceb089a..ef7be1ce2c8 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -10,6 +10,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) struct ieee80211_sub_if_data *sdata; struct ieee80211_if_init_conf conf; struct sta_info *sta; + unsigned long flags; ieee80211_stop_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_SUSPEND); @@ -21,9 +22,9 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) ieee80211_disable_keys(sdata); /* remove STAs */ - list_for_each_entry(sta, &local->sta_list, list) { - - if (local->ops->sta_notify) { + if (local->ops->sta_notify) { + spin_lock_irqsave(&local->sta_lock, flags); + list_for_each_entry(sta, &local->sta_list, list) { if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, @@ -32,11 +33,11 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) local->ops->sta_notify(hw, &sdata->vif, STA_NOTIFY_REMOVE, &sta->sta); } + spin_unlock_irqrestore(&local->sta_lock, flags); } /* remove all interfaces */ list_for_each_entry(sdata, &local->interfaces, list) { - if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && sdata->vif.type != NL80211_IFTYPE_MONITOR && netif_running(sdata->dev)) { @@ -64,6 +65,7 @@ int __ieee80211_resume(struct ieee80211_hw *hw) struct ieee80211_sub_if_data *sdata; struct ieee80211_if_init_conf conf; struct sta_info *sta; + unsigned long flags; int res; /* restart hardware */ @@ -75,7 +77,6 @@ int __ieee80211_resume(struct ieee80211_hw *hw) /* add interfaces */ list_for_each_entry(sdata, &local->interfaces, list) { - if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && sdata->vif.type != NL80211_IFTYPE_MONITOR && netif_running(sdata->dev)) { @@ -87,9 +88,9 @@ int __ieee80211_resume(struct ieee80211_hw *hw) } /* add STAs back */ - list_for_each_entry(sta, &local->sta_list, list) { - - if (local->ops->sta_notify) { + if (local->ops->sta_notify) { + spin_lock_irqsave(&local->sta_lock, flags); + list_for_each_entry(sta, &local->sta_list, list) { if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, @@ -98,6 +99,7 @@ int __ieee80211_resume(struct ieee80211_hw *hw) local->ops->sta_notify(hw, &sdata->vif, STA_NOTIFY_ADD, &sta->sta); } + spin_unlock_irqrestore(&local->sta_lock, flags); } /* add back keys */ -- GitLab From 85067c06ba0329c37d5a357ced1f39a5583ccc98 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Sat, 14 Mar 2009 19:59:41 +0530 Subject: [PATCH 4858/4982] ath9k: Keep LED on in idle state after association Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 7d27eed78af..4c29cef66a6 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -940,18 +940,25 @@ static void ath_led_blink_work(struct work_struct *work) if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED)) return; - ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, - (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0); + + if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) || + (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) + ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0); + else + ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, + (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0); queue_delayed_work(sc->hw->workqueue, &sc->ath_led_blink_work, (sc->sc_flags & SC_OP_LED_ON) ? msecs_to_jiffies(sc->led_off_duration) : msecs_to_jiffies(sc->led_on_duration)); - sc->led_on_duration = - max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25); - sc->led_off_duration = - max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10); + sc->led_on_duration = sc->led_on_cnt ? + max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) : + ATH_LED_ON_DURATION_IDLE; + sc->led_off_duration = sc->led_off_cnt ? + max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10) : + ATH_LED_OFF_DURATION_IDLE; sc->led_on_cnt = sc->led_off_cnt = 0; if (sc->sc_flags & SC_OP_LED_ON) sc->sc_flags &= ~SC_OP_LED_ON; -- GitLab From 3f46b29cd8caa35fcbc46e254a5abeee4e0e9e2f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 14 Mar 2009 19:10:51 +0100 Subject: [PATCH 4859/4982] ieee80211: document DS bit usage I keep needing this because I'm too stupid to remember it. Everybody else can probably remember, but who knows :) Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index b1bb817d142..382387e75b8 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -18,6 +18,22 @@ #include #include +/* + * DS bit usage + * + * TA = transmitter address + * RA = receiver address + * DA = destination address + * SA = source address + * + * ToDS FromDS A1(RA) A2(TA) A3 A4 Use + * ----------------------------------------------------------------- + * 0 0 DA SA BSSID - IBSS/DLS + * 0 1 DA BSSID SA - AP -> STA + * 1 0 BSSID SA DA - AP <- STA + * 1 1 RA TA DA SA unspecified (WDS) + */ + #define FCS_LEN 4 #define IEEE80211_FCTL_VERS 0x0003 -- GitLab From 504f365554a7f543fcd706878ff9edf785be7614 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Sun, 15 Mar 2009 22:13:39 +0200 Subject: [PATCH 4860/4982] ath5k: Choose the right initvals for RF2425 * Fix a typo in initvals.c so that we use the RF2425 array for RF2425 and not RF2413 Note: This also fixes incorect pd gain overlap since RF2425 has different pd gain overlap from RF2413 Signed-off-by: Nick Kossifidis Acked-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/initvals.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath5k/initvals.c b/drivers/net/wireless/ath5k/initvals.c index 44886434187..61fb621ed20 100644 --- a/drivers/net/wireless/ath5k/initvals.c +++ b/drivers/net/wireless/ath5k/initvals.c @@ -1510,8 +1510,8 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) rf2425_ini_mode_end, mode); ath5k_hw_ini_registers(ah, - ARRAY_SIZE(rf2413_ini_common_end), - rf2413_ini_common_end, change_channel); + ARRAY_SIZE(rf2425_ini_common_end), + rf2425_ini_common_end, change_channel); ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5112_ini_bbgain), -- GitLab From 8e218fb24faef0bfe95bc91b3c05261e20439527 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Sun, 15 Mar 2009 22:17:04 +0200 Subject: [PATCH 4861/4982] ath5k: Convert chip specific calibration data to a generic format * Convert chip specific calibration data to a generic format common for all chips Note: We scale up power to be in 0.25dB units for all chips for compatibility with RF5112 v2: Address Bob's and Jiri's comments Signed-off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/eeprom.c | 774 +++++++++++++++++++--------- drivers/net/wireless/ath5k/eeprom.h | 128 +++-- 2 files changed, 629 insertions(+), 273 deletions(-) diff --git a/drivers/net/wireless/ath5k/eeprom.c b/drivers/net/wireless/ath5k/eeprom.c index ac45ca47ca8..c0fb3b09ba4 100644 --- a/drivers/net/wireless/ath5k/eeprom.c +++ b/drivers/net/wireless/ath5k/eeprom.c @@ -1,7 +1,7 @@ /* * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * Copyright (c) 2008 Felix Fietkau + * Copyright (c) 2006-2009 Nick Kossifidis + * Copyright (c) 2008-2009 Felix Fietkau * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -98,11 +98,6 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) int ret; u16 val; - /* Initial TX thermal adjustment values */ - ee->ee_tx_clip = 4; - ee->ee_pwd_84 = ee->ee_pwd_90 = 1; - ee->ee_gain_select = 1; - /* * Read values from EEPROM and store them in the capability structure */ @@ -241,22 +236,22 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff); switch(mode) { case AR5K_EEPROM_MODE_11A: - ee->ee_ob[mode][3] = (val >> 5) & 0x7; - ee->ee_db[mode][3] = (val >> 2) & 0x7; - ee->ee_ob[mode][2] = (val << 1) & 0x7; + ee->ee_ob[mode][3] = (val >> 5) & 0x7; + ee->ee_db[mode][3] = (val >> 2) & 0x7; + ee->ee_ob[mode][2] = (val << 1) & 0x7; AR5K_EEPROM_READ(o++, val); - ee->ee_ob[mode][2] |= (val >> 15) & 0x1; - ee->ee_db[mode][2] = (val >> 12) & 0x7; - ee->ee_ob[mode][1] = (val >> 9) & 0x7; - ee->ee_db[mode][1] = (val >> 6) & 0x7; - ee->ee_ob[mode][0] = (val >> 3) & 0x7; - ee->ee_db[mode][0] = val & 0x7; + ee->ee_ob[mode][2] |= (val >> 15) & 0x1; + ee->ee_db[mode][2] = (val >> 12) & 0x7; + ee->ee_ob[mode][1] = (val >> 9) & 0x7; + ee->ee_db[mode][1] = (val >> 6) & 0x7; + ee->ee_ob[mode][0] = (val >> 3) & 0x7; + ee->ee_db[mode][0] = val & 0x7; break; case AR5K_EEPROM_MODE_11G: case AR5K_EEPROM_MODE_11B: - ee->ee_ob[mode][1] = (val >> 4) & 0x7; - ee->ee_db[mode][1] = val & 0x7; + ee->ee_ob[mode][1] = (val >> 4) & 0x7; + ee->ee_db[mode][1] = val & 0x7; break; } @@ -504,35 +499,6 @@ ath5k_eeprom_init_modes(struct ath5k_hw *ah) return 0; } -/* Used to match PCDAC steps with power values on RF5111 chips - * (eeprom versions < 4). For RF5111 we have 10 pre-defined PCDAC - * steps that match with the power values we read from eeprom. On - * older eeprom versions (< 3.2) these steps are equaly spaced at - * 10% of the pcdac curve -until the curve reaches it's maximum- - * (10 steps from 0 to 100%) but on newer eeprom versions (>= 3.2) - * these 10 steps are spaced in a different way. This function returns - * the pcdac steps based on eeprom version and curve min/max so that we - * can have pcdac/pwr points. - */ -static inline void -ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp) -{ - static const u16 intercepts3[] = - { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 }; - static const u16 intercepts3_2[] = - { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }; - const u16 *ip; - int i; - - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_2) - ip = intercepts3_2; - else - ip = intercepts3; - - for (i = 0; i < ARRAY_SIZE(intercepts3); i++) - *vp++ = (ip[i] * max + (100 - ip[i]) * min) / 100; -} - /* Read the frequency piers for each mode (mostly used on newer eeproms with 0xff * frequency mask) */ static inline int @@ -546,26 +512,25 @@ ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max, int ret; u16 val; + ee->ee_n_piers[mode] = 0; while(i < max) { AR5K_EEPROM_READ(o++, val); - freq1 = (val >> 8) & 0xff; - freq2 = val & 0xff; - - if (freq1) { - pc[i++].freq = ath5k_eeprom_bin2freq(ee, - freq1, mode); - ee->ee_n_piers[mode]++; - } + freq1 = val & 0xff; + if (!freq1) + break; - if (freq2) { - pc[i++].freq = ath5k_eeprom_bin2freq(ee, - freq2, mode); - ee->ee_n_piers[mode]++; - } + pc[i++].freq = ath5k_eeprom_bin2freq(ee, + freq1, mode); + ee->ee_n_piers[mode]++; - if (!freq1 || !freq2) + freq2 = (val >> 8) & 0xff; + if (!freq2) break; + + pc[i++].freq = ath5k_eeprom_bin2freq(ee, + freq2, mode); + ee->ee_n_piers[mode]++; } /* return new offset */ @@ -652,13 +617,122 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset) return 0; } -/* Read power calibration for RF5111 chips +/* + * Read power calibration for RF5111 chips + * * For RF5111 we have an XPD -eXternal Power Detector- curve - * for each calibrated channel. Each curve has PCDAC steps on - * x axis and power on y axis and looks like a logarithmic - * function. To recreate the curve and pass the power values - * on the pcdac table, we read 10 points here and interpolate later. + * for each calibrated channel. Each curve has 0,5dB Power steps + * on x axis and PCDAC steps (offsets) on y axis and looks like an + * exponential function. To recreate the curve we read 11 points + * here and interpolate later. */ + +/* Used to match PCDAC steps with power values on RF5111 chips + * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC + * steps that match with the power values we read from eeprom. On + * older eeprom versions (< 3.2) these steps are equaly spaced at + * 10% of the pcdac curve -until the curve reaches it's maximum- + * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2) + * these 11 steps are spaced in a different way. This function returns + * the pcdac steps based on eeprom version and curve min/max so that we + * can have pcdac/pwr points. + */ +static inline void +ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp) +{ + const static u16 intercepts3[] = + { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 }; + const static u16 intercepts3_2[] = + { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }; + const u16 *ip; + int i; + + if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_2) + ip = intercepts3_2; + else + ip = intercepts3; + + for (i = 0; i < ARRAY_SIZE(intercepts3); i++) + vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100; +} + +/* Convert RF5111 specific data to generic raw data + * used by interpolation code */ +static int +ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode, + struct ath5k_chan_pcal_info *chinfo) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + struct ath5k_chan_pcal_info_rf5111 *pcinfo; + struct ath5k_pdgain_info *pd; + u8 pier, point, idx; + u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; + + /* Fill raw data for each calibration pier */ + for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { + + pcinfo = &chinfo[pier].rf5111_info; + + /* Allocate pd_curves for this cal pier */ + chinfo[pier].pd_curves = + kcalloc(AR5K_EEPROM_N_PD_CURVES, + sizeof(struct ath5k_pdgain_info), + GFP_KERNEL); + + if (!chinfo[pier].pd_curves) + return -ENOMEM; + + /* Only one curve for RF5111 + * find out which one and place + * in in pd_curves. + * Note: ee_x_gain is reversed here */ + for (idx = 0; idx < AR5K_EEPROM_N_PD_CURVES; idx++) { + + if (!((ee->ee_x_gain[mode] >> idx) & 0x1)) { + pdgain_idx[0] = idx; + break; + } + } + + ee->ee_pd_gains[mode] = 1; + + pd = &chinfo[pier].pd_curves[idx]; + + pd->pd_points = AR5K_EEPROM_N_PWR_POINTS_5111; + + /* Allocate pd points for this curve */ + pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, + sizeof(u8), GFP_KERNEL); + if (!pd->pd_step) + return -ENOMEM; + + pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, + sizeof(s16), GFP_KERNEL); + if (!pd->pd_pwr) + return -ENOMEM; + + /* Fill raw dataset + * (convert power to 0.25dB units + * for RF5112 combatibility) */ + for (point = 0; point < pd->pd_points; point++) { + + /* Absolute values */ + pd->pd_pwr[point] = 2 * pcinfo->pwr[point]; + + /* Already sorted */ + pd->pd_step[point] = pcinfo->pcdac[point]; + } + + /* Set min/max pwr */ + chinfo[pier].min_pwr = pd->pd_pwr[0]; + chinfo[pier].max_pwr = pd->pd_pwr[10]; + + } + + return 0; +} + +/* Parse EEPROM data */ static int ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode) { @@ -747,30 +821,165 @@ ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode) cdata->pcdac_max, cdata->pcdac); } - return 0; + return ath5k_eeprom_convert_pcal_info_5111(ah, mode, pcal); } -/* Read power calibration for RF5112 chips + +/* + * Read power calibration for RF5112 chips + * * For RF5112 we have 4 XPD -eXternal Power Detector- curves * for each calibrated channel on 0, -6, -12 and -18dbm but we only - * use the higher (3) and the lower (0) curves. Each curve has PCDAC - * steps on x axis and power on y axis and looks like a linear - * function. To recreate the curve and pass the power values - * on the pcdac table, we read 4 points for xpd 0 and 3 points - * for xpd 3 here and interpolate later. + * use the higher (3) and the lower (0) curves. Each curve has 0.5dB + * power steps on x axis and PCDAC steps on y axis and looks like a + * linear function. To recreate the curve and pass the power values + * on hw, we read 4 points for xpd 0 (lower gain -> max power) + * and 3 points for xpd 3 (higher gain -> lower power) here and + * interpolate later. * * Note: Many vendors just use xpd 0 so xpd 3 is zeroed. */ + +/* Convert RF5112 specific data to generic raw data + * used by interpolation code */ +static int +ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode, + struct ath5k_chan_pcal_info *chinfo) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + struct ath5k_chan_pcal_info_rf5112 *pcinfo; + u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; + unsigned int pier, pdg, point; + + /* Fill raw data for each calibration pier */ + for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { + + pcinfo = &chinfo[pier].rf5112_info; + + /* Allocate pd_curves for this cal pier */ + chinfo[pier].pd_curves = + kcalloc(AR5K_EEPROM_N_PD_CURVES, + sizeof(struct ath5k_pdgain_info), + GFP_KERNEL); + + if (!chinfo[pier].pd_curves) + return -ENOMEM; + + /* Fill pd_curves */ + for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { + + u8 idx = pdgain_idx[pdg]; + struct ath5k_pdgain_info *pd = + &chinfo[pier].pd_curves[idx]; + + /* Lowest gain curve (max power) */ + if (pdg == 0) { + /* One more point for better accuracy */ + pd->pd_points = AR5K_EEPROM_N_XPD0_POINTS; + + /* Allocate pd points for this curve */ + pd->pd_step = kcalloc(pd->pd_points, + sizeof(u8), GFP_KERNEL); + + if (!pd->pd_step) + return -ENOMEM; + + pd->pd_pwr = kcalloc(pd->pd_points, + sizeof(s16), GFP_KERNEL); + + if (!pd->pd_pwr) + return -ENOMEM; + + + /* Fill raw dataset + * (all power levels are in 0.25dB units) */ + pd->pd_step[0] = pcinfo->pcdac_x0[0]; + pd->pd_pwr[0] = pcinfo->pwr_x0[0]; + + for (point = 1; point < pd->pd_points; + point++) { + /* Absolute values */ + pd->pd_pwr[point] = + pcinfo->pwr_x0[point]; + + /* Deltas */ + pd->pd_step[point] = + pd->pd_step[point - 1] + + pcinfo->pcdac_x0[point]; + } + + /* Set min power for this frequency */ + chinfo[pier].min_pwr = pd->pd_pwr[0]; + + /* Highest gain curve (min power) */ + } else if (pdg == 1) { + + pd->pd_points = AR5K_EEPROM_N_XPD3_POINTS; + + /* Allocate pd points for this curve */ + pd->pd_step = kcalloc(pd->pd_points, + sizeof(u8), GFP_KERNEL); + + if (!pd->pd_step) + return -ENOMEM; + + pd->pd_pwr = kcalloc(pd->pd_points, + sizeof(s16), GFP_KERNEL); + + if (!pd->pd_pwr) + return -ENOMEM; + + /* Fill raw dataset + * (all power levels are in 0.25dB units) */ + for (point = 0; point < pd->pd_points; + point++) { + /* Absolute values */ + pd->pd_pwr[point] = + pcinfo->pwr_x3[point]; + + /* Fixed points */ + pd->pd_step[point] = + pcinfo->pcdac_x3[point]; + } + + /* Since we have a higher gain curve + * override min power */ + chinfo[pier].min_pwr = pd->pd_pwr[0]; + } + } + } + + return 0; +} + +/* Parse EEPROM data */ static int ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) { struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; struct ath5k_chan_pcal_info_rf5112 *chan_pcal_info; struct ath5k_chan_pcal_info *gen_chan_info; + u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; u32 offset; - unsigned int i, c; + u8 i, c; u16 val; int ret; + u8 pd_gains = 0; + + /* Count how many curves we have and + * identify them (which one of the 4 + * available curves we have on each count). + * Curves are stored from lower (x0) to + * higher (x3) gain */ + for (i = 0; i < AR5K_EEPROM_N_PD_CURVES; i++) { + /* ee_x_gain[mode] is x gain mask */ + if ((ee->ee_x_gain[mode] >> i) & 0x1) + pdgain_idx[pd_gains++] = i; + } + ee->ee_pd_gains[mode] = pd_gains; + + if (pd_gains == 0 || pd_gains > 2) + return -EINVAL; switch (mode) { case AR5K_EEPROM_MODE_11A: @@ -808,13 +1017,13 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) for (i = 0; i < ee->ee_n_piers[mode]; i++) { chan_pcal_info = &gen_chan_info[i].rf5112_info; - /* Power values in dBm * 4 + /* Power values in quarter dB * for the lower xpd gain curve * (0 dBm -> higher output power) */ for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) { AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pwr_x0[c] = (val & 0xff); - chan_pcal_info->pwr_x0[++c] = ((val >> 8) & 0xff); + chan_pcal_info->pwr_x0[c] = (s8) (val & 0xff); + chan_pcal_info->pwr_x0[++c] = (s8) ((val >> 8) & 0xff); } /* PCDAC steps @@ -825,12 +1034,12 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) chan_pcal_info->pcdac_x0[2] = ((val >> 5) & 0x1f); chan_pcal_info->pcdac_x0[3] = ((val >> 10) & 0x1f); - /* Power values in dBm * 4 + /* Power values in quarter dB * for the higher xpd gain curve * (18 dBm -> lower output power) */ AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pwr_x3[0] = (val & 0xff); - chan_pcal_info->pwr_x3[1] = ((val >> 8) & 0xff); + chan_pcal_info->pwr_x3[0] = (s8) (val & 0xff); + chan_pcal_info->pwr_x3[1] = (s8) ((val >> 8) & 0xff); AR5K_EEPROM_READ(offset++, val); chan_pcal_info->pwr_x3[2] = (val & 0xff); @@ -843,24 +1052,36 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) chan_pcal_info->pcdac_x3[2] = 63; if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3) { - chan_pcal_info->pcdac_x0[0] = ((val >> 8) & 0xff); + chan_pcal_info->pcdac_x0[0] = ((val >> 8) & 0x3f); /* Last xpd0 power level is also channel maximum */ gen_chan_info[i].max_pwr = chan_pcal_info->pwr_x0[3]; } else { chan_pcal_info->pcdac_x0[0] = 1; - gen_chan_info[i].max_pwr = ((val >> 8) & 0xff); + gen_chan_info[i].max_pwr = (s8) ((val >> 8) & 0xff); } - /* Recreate pcdac_x0 table for this channel using pcdac steps */ - chan_pcal_info->pcdac_x0[1] += chan_pcal_info->pcdac_x0[0]; - chan_pcal_info->pcdac_x0[2] += chan_pcal_info->pcdac_x0[1]; - chan_pcal_info->pcdac_x0[3] += chan_pcal_info->pcdac_x0[2]; } - return 0; + return ath5k_eeprom_convert_pcal_info_5112(ah, mode, gen_chan_info); } + +/* + * Read power calibration for RF2413 chips + * + * For RF2413 we have a Power to PDDAC table (Power Detector) + * instead of a PCDAC and 4 pd gain curves for each calibrated channel. + * Each curve has power on x axis in 0.5 db steps and PDDADC steps on y + * axis and looks like an exponential function like the RF5111 curve. + * + * To recreate the curves we read here the points and interpolate + * later. Note that in most cases only 2 (higher and lower) curves are + * used (like RF5112) but vendors have the oportunity to include all + * 4 curves on eeprom. The final curve (higher power) has an extra + * point for better accuracy like RF5112. + */ + /* For RF2413 power calibration data doesn't start on a fixed location and * if a mode is not supported, it's section is missing -not zeroed-. * So we need to calculate the starting offset for each section by using @@ -890,13 +1111,15 @@ ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode) switch(mode) { case AR5K_EEPROM_MODE_11G: if (AR5K_EEPROM_HDR_11B(ee->ee_header)) - offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11B) + - AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2; + offset += ath5k_pdgains_size_2413(ee, + AR5K_EEPROM_MODE_11B) + + AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2; /* fall through */ case AR5K_EEPROM_MODE_11B: if (AR5K_EEPROM_HDR_11A(ee->ee_header)) - offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11A) + - AR5K_EEPROM_N_5GHZ_CHAN / 2; + offset += ath5k_pdgains_size_2413(ee, + AR5K_EEPROM_MODE_11A) + + AR5K_EEPROM_N_5GHZ_CHAN / 2; /* fall through */ case AR5K_EEPROM_MODE_11A: break; @@ -907,37 +1130,118 @@ ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode) return offset; } -/* Read power calibration for RF2413 chips - * For RF2413 we have a PDDAC table (Power Detector) instead - * of a PCDAC and 4 pd gain curves for each calibrated channel. - * Each curve has PDDAC steps on x axis and power on y axis and - * looks like an exponential function. To recreate the curves - * we read here the points and interpolate later. Note that - * in most cases only higher and lower curves are used (like - * RF5112) but vendors have the oportunity to include all 4 - * curves on eeprom. The final curve (higher power) has an extra - * point for better accuracy like RF5112. - */ +/* Convert RF2413 specific data to generic raw data + * used by interpolation code */ +static int +ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode, + struct ath5k_chan_pcal_info *chinfo) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + struct ath5k_chan_pcal_info_rf2413 *pcinfo; + u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; + unsigned int pier, pdg, point; + + /* Fill raw data for each calibration pier */ + for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { + + pcinfo = &chinfo[pier].rf2413_info; + + /* Allocate pd_curves for this cal pier */ + chinfo[pier].pd_curves = + kcalloc(AR5K_EEPROM_N_PD_CURVES, + sizeof(struct ath5k_pdgain_info), + GFP_KERNEL); + + if (!chinfo[pier].pd_curves) + return -ENOMEM; + + /* Fill pd_curves */ + for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { + + u8 idx = pdgain_idx[pdg]; + struct ath5k_pdgain_info *pd = + &chinfo[pier].pd_curves[idx]; + + /* One more point for the highest power + * curve (lowest gain) */ + if (pdg == ee->ee_pd_gains[mode] - 1) + pd->pd_points = AR5K_EEPROM_N_PD_POINTS; + else + pd->pd_points = AR5K_EEPROM_N_PD_POINTS - 1; + + /* Allocate pd points for this curve */ + pd->pd_step = kcalloc(pd->pd_points, + sizeof(u8), GFP_KERNEL); + + if (!pd->pd_step) + return -ENOMEM; + + pd->pd_pwr = kcalloc(pd->pd_points, + sizeof(s16), GFP_KERNEL); + + if (!pd->pd_pwr) + return -ENOMEM; + + /* Fill raw dataset + * convert all pwr levels to + * quarter dB for RF5112 combatibility */ + pd->pd_step[0] = pcinfo->pddac_i[pdg]; + pd->pd_pwr[0] = 4 * pcinfo->pwr_i[pdg]; + + for (point = 1; point < pd->pd_points; point++) { + + pd->pd_pwr[point] = pd->pd_pwr[point - 1] + + 2 * pcinfo->pwr[pdg][point - 1]; + + pd->pd_step[point] = pd->pd_step[point - 1] + + pcinfo->pddac[pdg][point - 1]; + + } + + /* Highest gain curve -> min power */ + if (pdg == 0) + chinfo[pier].min_pwr = pd->pd_pwr[0]; + + /* Lowest gain curve -> max power */ + if (pdg == ee->ee_pd_gains[mode] - 1) + chinfo[pier].max_pwr = + pd->pd_pwr[pd->pd_points - 1]; + } + } + + return 0; +} + +/* Parse EEPROM data */ static int ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) { struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_chan_pcal_info_rf2413 *chan_pcal_info; - struct ath5k_chan_pcal_info *gen_chan_info; - unsigned int i, c; + struct ath5k_chan_pcal_info_rf2413 *pcinfo; + struct ath5k_chan_pcal_info *chinfo; + u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; u32 offset; - int ret; + int idx, i, ret; u16 val; u8 pd_gains = 0; - if (ee->ee_x_gain[mode] & 0x1) pd_gains++; - if ((ee->ee_x_gain[mode] >> 1) & 0x1) pd_gains++; - if ((ee->ee_x_gain[mode] >> 2) & 0x1) pd_gains++; - if ((ee->ee_x_gain[mode] >> 3) & 0x1) pd_gains++; + /* Count how many curves we have and + * identify them (which one of the 4 + * available curves we have on each count). + * Curves are stored from higher to + * lower gain so we go backwards */ + for (idx = AR5K_EEPROM_N_PD_CURVES - 1; idx >= 0; idx--) { + /* ee_x_gain[mode] is x gain mask */ + if ((ee->ee_x_gain[mode] >> idx) & 0x1) + pdgain_idx[pd_gains++] = idx; + + } ee->ee_pd_gains[mode] = pd_gains; + if (pd_gains == 0) + return -EINVAL; + offset = ath5k_cal_data_offset_2413(ee, mode); - ee->ee_n_piers[mode] = 0; switch (mode) { case AR5K_EEPROM_MODE_11A: if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) @@ -945,7 +1249,7 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) ath5k_eeprom_init_11a_pcal_freq(ah, offset); offset += AR5K_EEPROM_N_5GHZ_CHAN / 2; - gen_chan_info = ee->ee_pwr_cal_a; + chinfo = ee->ee_pwr_cal_a; break; case AR5K_EEPROM_MODE_11B: if (!AR5K_EEPROM_HDR_11B(ee->ee_header)) @@ -953,7 +1257,7 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) ath5k_eeprom_init_11bg_2413(ah, mode, offset); offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2; - gen_chan_info = ee->ee_pwr_cal_b; + chinfo = ee->ee_pwr_cal_b; break; case AR5K_EEPROM_MODE_11G: if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) @@ -961,41 +1265,35 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) ath5k_eeprom_init_11bg_2413(ah, mode, offset); offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2; - gen_chan_info = ee->ee_pwr_cal_g; + chinfo = ee->ee_pwr_cal_g; break; default: return -EINVAL; } - if (pd_gains == 0) - return 0; - for (i = 0; i < ee->ee_n_piers[mode]; i++) { - chan_pcal_info = &gen_chan_info[i].rf2413_info; + pcinfo = &chinfo[i].rf2413_info; /* * Read pwr_i, pddac_i and the first * 2 pd points (pwr, pddac) */ AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pwr_i[0] = val & 0x1f; - chan_pcal_info->pddac_i[0] = (val >> 5) & 0x7f; - chan_pcal_info->pwr[0][0] = - (val >> 12) & 0xf; + pcinfo->pwr_i[0] = val & 0x1f; + pcinfo->pddac_i[0] = (val >> 5) & 0x7f; + pcinfo->pwr[0][0] = (val >> 12) & 0xf; AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pddac[0][0] = val & 0x3f; - chan_pcal_info->pwr[0][1] = (val >> 6) & 0xf; - chan_pcal_info->pddac[0][1] = - (val >> 10) & 0x3f; + pcinfo->pddac[0][0] = val & 0x3f; + pcinfo->pwr[0][1] = (val >> 6) & 0xf; + pcinfo->pddac[0][1] = (val >> 10) & 0x3f; AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pwr[0][2] = val & 0xf; - chan_pcal_info->pddac[0][2] = - (val >> 4) & 0x3f; + pcinfo->pwr[0][2] = val & 0xf; + pcinfo->pddac[0][2] = (val >> 4) & 0x3f; - chan_pcal_info->pwr[0][3] = 0; - chan_pcal_info->pddac[0][3] = 0; + pcinfo->pwr[0][3] = 0; + pcinfo->pddac[0][3] = 0; if (pd_gains > 1) { /* @@ -1003,44 +1301,36 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) * so it only has 2 pd points. * Continue wih pd gain 1. */ - chan_pcal_info->pwr_i[1] = (val >> 10) & 0x1f; + pcinfo->pwr_i[1] = (val >> 10) & 0x1f; - chan_pcal_info->pddac_i[1] = (val >> 15) & 0x1; + pcinfo->pddac_i[1] = (val >> 15) & 0x1; AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pddac_i[1] |= (val & 0x3F) << 1; + pcinfo->pddac_i[1] |= (val & 0x3F) << 1; - chan_pcal_info->pwr[1][0] = (val >> 6) & 0xf; - chan_pcal_info->pddac[1][0] = - (val >> 10) & 0x3f; + pcinfo->pwr[1][0] = (val >> 6) & 0xf; + pcinfo->pddac[1][0] = (val >> 10) & 0x3f; AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pwr[1][1] = val & 0xf; - chan_pcal_info->pddac[1][1] = - (val >> 4) & 0x3f; - chan_pcal_info->pwr[1][2] = - (val >> 10) & 0xf; - - chan_pcal_info->pddac[1][2] = - (val >> 14) & 0x3; + pcinfo->pwr[1][1] = val & 0xf; + pcinfo->pddac[1][1] = (val >> 4) & 0x3f; + pcinfo->pwr[1][2] = (val >> 10) & 0xf; + + pcinfo->pddac[1][2] = (val >> 14) & 0x3; AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pddac[1][2] |= - (val & 0xF) << 2; + pcinfo->pddac[1][2] |= (val & 0xF) << 2; - chan_pcal_info->pwr[1][3] = 0; - chan_pcal_info->pddac[1][3] = 0; + pcinfo->pwr[1][3] = 0; + pcinfo->pddac[1][3] = 0; } else if (pd_gains == 1) { /* * Pd gain 0 is the last one so * read the extra point. */ - chan_pcal_info->pwr[0][3] = - (val >> 10) & 0xf; + pcinfo->pwr[0][3] = (val >> 10) & 0xf; - chan_pcal_info->pddac[0][3] = - (val >> 14) & 0x3; + pcinfo->pddac[0][3] = (val >> 14) & 0x3; AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pddac[0][3] |= - (val & 0xF) << 2; + pcinfo->pddac[0][3] |= (val & 0xF) << 2; } /* @@ -1048,105 +1338,65 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) * as above. */ if (pd_gains > 2) { - chan_pcal_info->pwr_i[2] = (val >> 4) & 0x1f; - chan_pcal_info->pddac_i[2] = (val >> 9) & 0x7f; + pcinfo->pwr_i[2] = (val >> 4) & 0x1f; + pcinfo->pddac_i[2] = (val >> 9) & 0x7f; AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pwr[2][0] = - (val >> 0) & 0xf; - chan_pcal_info->pddac[2][0] = - (val >> 4) & 0x3f; - chan_pcal_info->pwr[2][1] = - (val >> 10) & 0xf; - - chan_pcal_info->pddac[2][1] = - (val >> 14) & 0x3; + pcinfo->pwr[2][0] = (val >> 0) & 0xf; + pcinfo->pddac[2][0] = (val >> 4) & 0x3f; + pcinfo->pwr[2][1] = (val >> 10) & 0xf; + + pcinfo->pddac[2][1] = (val >> 14) & 0x3; AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pddac[2][1] |= - (val & 0xF) << 2; + pcinfo->pddac[2][1] |= (val & 0xF) << 2; - chan_pcal_info->pwr[2][2] = - (val >> 4) & 0xf; - chan_pcal_info->pddac[2][2] = - (val >> 8) & 0x3f; + pcinfo->pwr[2][2] = (val >> 4) & 0xf; + pcinfo->pddac[2][2] = (val >> 8) & 0x3f; - chan_pcal_info->pwr[2][3] = 0; - chan_pcal_info->pddac[2][3] = 0; + pcinfo->pwr[2][3] = 0; + pcinfo->pddac[2][3] = 0; } else if (pd_gains == 2) { - chan_pcal_info->pwr[1][3] = - (val >> 4) & 0xf; - chan_pcal_info->pddac[1][3] = - (val >> 8) & 0x3f; + pcinfo->pwr[1][3] = (val >> 4) & 0xf; + pcinfo->pddac[1][3] = (val >> 8) & 0x3f; } if (pd_gains > 3) { - chan_pcal_info->pwr_i[3] = (val >> 14) & 0x3; + pcinfo->pwr_i[3] = (val >> 14) & 0x3; AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pwr_i[3] |= ((val >> 0) & 0x7) << 2; + pcinfo->pwr_i[3] |= ((val >> 0) & 0x7) << 2; - chan_pcal_info->pddac_i[3] = (val >> 3) & 0x7f; - chan_pcal_info->pwr[3][0] = - (val >> 10) & 0xf; - chan_pcal_info->pddac[3][0] = - (val >> 14) & 0x3; + pcinfo->pddac_i[3] = (val >> 3) & 0x7f; + pcinfo->pwr[3][0] = (val >> 10) & 0xf; + pcinfo->pddac[3][0] = (val >> 14) & 0x3; AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pddac[3][0] |= - (val & 0xF) << 2; - chan_pcal_info->pwr[3][1] = - (val >> 4) & 0xf; - chan_pcal_info->pddac[3][1] = - (val >> 8) & 0x3f; - - chan_pcal_info->pwr[3][2] = - (val >> 14) & 0x3; + pcinfo->pddac[3][0] |= (val & 0xF) << 2; + pcinfo->pwr[3][1] = (val >> 4) & 0xf; + pcinfo->pddac[3][1] = (val >> 8) & 0x3f; + + pcinfo->pwr[3][2] = (val >> 14) & 0x3; AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pwr[3][2] |= - ((val >> 0) & 0x3) << 2; + pcinfo->pwr[3][2] |= ((val >> 0) & 0x3) << 2; - chan_pcal_info->pddac[3][2] = - (val >> 2) & 0x3f; - chan_pcal_info->pwr[3][3] = - (val >> 8) & 0xf; + pcinfo->pddac[3][2] = (val >> 2) & 0x3f; + pcinfo->pwr[3][3] = (val >> 8) & 0xf; - chan_pcal_info->pddac[3][3] = - (val >> 12) & 0xF; + pcinfo->pddac[3][3] = (val >> 12) & 0xF; AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pddac[3][3] |= - ((val >> 0) & 0x3) << 4; + pcinfo->pddac[3][3] |= ((val >> 0) & 0x3) << 4; } else if (pd_gains == 3) { - chan_pcal_info->pwr[2][3] = - (val >> 14) & 0x3; + pcinfo->pwr[2][3] = (val >> 14) & 0x3; AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pwr[2][3] |= - ((val >> 0) & 0x3) << 2; - - chan_pcal_info->pddac[2][3] = - (val >> 2) & 0x3f; - } + pcinfo->pwr[2][3] |= ((val >> 0) & 0x3) << 2; - for (c = 0; c < pd_gains; c++) { - /* Recreate pwr table for this channel using pwr steps */ - chan_pcal_info->pwr[c][0] += chan_pcal_info->pwr_i[c] * 2; - chan_pcal_info->pwr[c][1] += chan_pcal_info->pwr[c][0]; - chan_pcal_info->pwr[c][2] += chan_pcal_info->pwr[c][1]; - chan_pcal_info->pwr[c][3] += chan_pcal_info->pwr[c][2]; - if (chan_pcal_info->pwr[c][3] == chan_pcal_info->pwr[c][2]) - chan_pcal_info->pwr[c][3] = 0; - - /* Recreate pddac table for this channel using pddac steps */ - chan_pcal_info->pddac[c][0] += chan_pcal_info->pddac_i[c]; - chan_pcal_info->pddac[c][1] += chan_pcal_info->pddac[c][0]; - chan_pcal_info->pddac[c][2] += chan_pcal_info->pddac[c][1]; - chan_pcal_info->pddac[c][3] += chan_pcal_info->pddac[c][2]; - if (chan_pcal_info->pddac[c][3] == chan_pcal_info->pddac[c][2]) - chan_pcal_info->pddac[c][3] = 0; + pcinfo->pddac[2][3] = (val >> 2) & 0x3f; } } - return 0; + return ath5k_eeprom_convert_pcal_info_2413(ah, mode, chinfo); } + /* * Read per rate target power (this is the maximum tx power * supported by the card). This info is used when setting @@ -1154,11 +1404,12 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) * * This also works for v5 EEPROMs. */ -static int ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode) +static int +ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode) { struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; struct ath5k_rate_pcal_info *rate_pcal_info; - u16 *rate_target_pwr_num; + u8 *rate_target_pwr_num; u32 offset; u16 val; int ret, i; @@ -1264,7 +1515,9 @@ ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah) else read_pcal = ath5k_eeprom_read_pcal_info_5111; - for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) { + + for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; + mode++) { err = read_pcal(ah, mode); if (err) return err; @@ -1277,6 +1530,62 @@ ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah) return 0; } +static int +ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + struct ath5k_chan_pcal_info *chinfo; + u8 pier, pdg; + + switch (mode) { + case AR5K_EEPROM_MODE_11A: + if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) + return 0; + chinfo = ee->ee_pwr_cal_a; + break; + case AR5K_EEPROM_MODE_11B: + if (!AR5K_EEPROM_HDR_11B(ee->ee_header)) + return 0; + chinfo = ee->ee_pwr_cal_b; + break; + case AR5K_EEPROM_MODE_11G: + if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) + return 0; + chinfo = ee->ee_pwr_cal_g; + break; + default: + return -EINVAL; + } + + for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { + if (!chinfo[pier].pd_curves) + continue; + + for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { + struct ath5k_pdgain_info *pd = + &chinfo[pier].pd_curves[pdg]; + + if (pd != NULL) { + kfree(pd->pd_step); + kfree(pd->pd_pwr); + } + } + + kfree(chinfo[pier].pd_curves); + } + + return 0; +} + +void +ath5k_eeprom_detach(struct ath5k_hw *ah) +{ + u8 mode; + + for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) + ath5k_eeprom_free_pcal_info(ah, mode); +} + /* Read conformance test limits used for regulatory control */ static int ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) @@ -1457,3 +1766,4 @@ bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah) else return false; } + diff --git a/drivers/net/wireless/ath5k/eeprom.h b/drivers/net/wireless/ath5k/eeprom.h index 1deebc0257d..b0c0606dea0 100644 --- a/drivers/net/wireless/ath5k/eeprom.h +++ b/drivers/net/wireless/ath5k/eeprom.h @@ -173,6 +173,7 @@ #define AR5K_EEPROM_N_5GHZ_CHAN 10 #define AR5K_EEPROM_N_2GHZ_CHAN 3 #define AR5K_EEPROM_N_2GHZ_CHAN_2413 4 +#define AR5K_EEPROM_N_2GHZ_CHAN_MAX 4 #define AR5K_EEPROM_MAX_CHAN 10 #define AR5K_EEPROM_N_PWR_POINTS_5111 11 #define AR5K_EEPROM_N_PCDAC 11 @@ -193,7 +194,7 @@ #define AR5K_EEPROM_SCALE_OC_DELTA(_x) (((_x) * 2) / 10) #define AR5K_EEPROM_N_CTLS(_v) AR5K_EEPROM_OFF(_v, 16, 32) #define AR5K_EEPROM_MAX_CTLS 32 -#define AR5K_EEPROM_N_XPD_PER_CHANNEL 4 +#define AR5K_EEPROM_N_PD_CURVES 4 #define AR5K_EEPROM_N_XPD0_POINTS 4 #define AR5K_EEPROM_N_XPD3_POINTS 3 #define AR5K_EEPROM_N_PD_GAINS 4 @@ -232,7 +233,7 @@ enum ath5k_ctl_mode { AR5K_CTL_11B = 1, AR5K_CTL_11G = 2, AR5K_CTL_TURBO = 3, - AR5K_CTL_108G = 4, + AR5K_CTL_TURBOG = 4, AR5K_CTL_2GHT20 = 5, AR5K_CTL_5GHT20 = 6, AR5K_CTL_2GHT40 = 7, @@ -240,65 +241,114 @@ enum ath5k_ctl_mode { AR5K_CTL_MODE_M = 15, }; +/* Default CTL ids for the 3 main reg domains. + * Atheros only uses these by default but vendors + * can have up to 32 different CTLs for different + * scenarios. Note that theese values are ORed with + * the mode id (above) so we can have up to 24 CTL + * datasets out of these 3 main regdomains. That leaves + * 8 ids that can be used by vendors and since 0x20 is + * missing from HAL sources i guess this is the set of + * custom CTLs vendors can use. */ +#define AR5K_CTL_FCC 0x10 +#define AR5K_CTL_CUSTOM 0x20 +#define AR5K_CTL_ETSI 0x30 +#define AR5K_CTL_MKK 0x40 + +/* Indicates a CTL with only mode set and + * no reg domain mapping, such CTLs are used + * for world roaming domains or simply when + * a reg domain is not set */ +#define AR5K_CTL_NO_REGDOMAIN 0xf0 + +/* Indicates an empty (invalid) CTL */ +#define AR5K_CTL_NO_CTL 0xff + /* Per channel calibration data, used for power table setup */ struct ath5k_chan_pcal_info_rf5111 { /* Power levels in half dbm units * for one power curve. */ - u8 pwr[AR5K_EEPROM_N_PWR_POINTS_5111]; + u8 pwr[AR5K_EEPROM_N_PWR_POINTS_5111]; /* PCDAC table steps * for the above values */ - u8 pcdac[AR5K_EEPROM_N_PWR_POINTS_5111]; + u8 pcdac[AR5K_EEPROM_N_PWR_POINTS_5111]; /* Starting PCDAC step */ - u8 pcdac_min; + u8 pcdac_min; /* Final PCDAC step */ - u8 pcdac_max; + u8 pcdac_max; }; struct ath5k_chan_pcal_info_rf5112 { /* Power levels in quarter dBm units * for lower (0) and higher (3) - * level curves */ - s8 pwr_x0[AR5K_EEPROM_N_XPD0_POINTS]; - s8 pwr_x3[AR5K_EEPROM_N_XPD3_POINTS]; + * level curves in 0.25dB units */ + s8 pwr_x0[AR5K_EEPROM_N_XPD0_POINTS]; + s8 pwr_x3[AR5K_EEPROM_N_XPD3_POINTS]; /* PCDAC table steps * for the above values */ - u8 pcdac_x0[AR5K_EEPROM_N_XPD0_POINTS]; - u8 pcdac_x3[AR5K_EEPROM_N_XPD3_POINTS]; + u8 pcdac_x0[AR5K_EEPROM_N_XPD0_POINTS]; + u8 pcdac_x3[AR5K_EEPROM_N_XPD3_POINTS]; }; struct ath5k_chan_pcal_info_rf2413 { /* Starting pwr/pddac values */ - s8 pwr_i[AR5K_EEPROM_N_PD_GAINS]; - u8 pddac_i[AR5K_EEPROM_N_PD_GAINS]; - /* (pwr,pddac) points */ - s8 pwr[AR5K_EEPROM_N_PD_GAINS] - [AR5K_EEPROM_N_PD_POINTS]; - u8 pddac[AR5K_EEPROM_N_PD_GAINS] - [AR5K_EEPROM_N_PD_POINTS]; + s8 pwr_i[AR5K_EEPROM_N_PD_GAINS]; + u8 pddac_i[AR5K_EEPROM_N_PD_GAINS]; + /* (pwr,pddac) points + * power levels in 0.5dB units */ + s8 pwr[AR5K_EEPROM_N_PD_GAINS] + [AR5K_EEPROM_N_PD_POINTS]; + u8 pddac[AR5K_EEPROM_N_PD_GAINS] + [AR5K_EEPROM_N_PD_POINTS]; +}; + +enum ath5k_powertable_type { + AR5K_PWRTABLE_PWR_TO_PCDAC = 0, + AR5K_PWRTABLE_LINEAR_PCDAC = 1, + AR5K_PWRTABLE_PWR_TO_PDADC = 2, +}; + +struct ath5k_pdgain_info { + u8 pd_points; + u8 *pd_step; + /* Power values are in + * 0.25dB units */ + s16 *pd_pwr; }; struct ath5k_chan_pcal_info { /* Frequency */ u16 freq; - /* Max available power */ - s8 max_pwr; + /* Tx power boundaries */ + s16 max_pwr; + s16 min_pwr; union { struct ath5k_chan_pcal_info_rf5111 rf5111_info; struct ath5k_chan_pcal_info_rf5112 rf5112_info; struct ath5k_chan_pcal_info_rf2413 rf2413_info; }; + /* Raw values used by phy code + * Curves are stored in order from lower + * gain to higher gain (max txpower -> min txpower) */ + struct ath5k_pdgain_info *pd_curves; }; -/* Per rate calibration data for each mode, used for power table setup */ +/* Per rate calibration data for each mode, + * used for rate power table setup. + * Note: Values in 0.5dB units */ struct ath5k_rate_pcal_info { u16 freq; /* Frequency */ - /* Power level for 6-24Mbit/s rates */ + /* Power level for 6-24Mbit/s rates or + * 1Mb rate */ u16 target_power_6to24; - /* Power level for 36Mbit rate */ + /* Power level for 36Mbit rate or + * 2Mb rate */ u16 target_power_36; - /* Power level for 48Mbit rate */ + /* Power level for 48Mbit rate or + * 5.5Mbit rate */ u16 target_power_48; - /* Power level for 54Mbit rate */ + /* Power level for 54Mbit rate or + * 11Mbit rate */ u16 target_power_54; }; @@ -330,12 +380,6 @@ struct ath5k_eeprom_info { u16 ee_cck_ofdm_power_delta; u16 ee_scaled_cck_delta; - /* Used for tx thermal adjustment (eeprom_init, rfregs) */ - u16 ee_tx_clip; - u16 ee_pwd_84; - u16 ee_pwd_90; - u16 ee_gain_select; - /* RF Calibration settings (reset, rfregs) */ u16 ee_i_cal[AR5K_EEPROM_N_MODES]; u16 ee_q_cal[AR5K_EEPROM_N_MODES]; @@ -363,23 +407,25 @@ struct ath5k_eeprom_info { /* Power calibration data */ u16 ee_false_detect[AR5K_EEPROM_N_MODES]; - /* Number of pd gain curves per mode (RF2413) */ - u8 ee_pd_gains[AR5K_EEPROM_N_MODES]; + /* Number of pd gain curves per mode */ + u8 ee_pd_gains[AR5K_EEPROM_N_MODES]; + /* Back mapping pdcurve number -> pdcurve index in pd->pd_curves */ + u8 ee_pdc_to_idx[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PD_GAINS]; - u8 ee_n_piers[AR5K_EEPROM_N_MODES]; + u8 ee_n_piers[AR5K_EEPROM_N_MODES]; struct ath5k_chan_pcal_info ee_pwr_cal_a[AR5K_EEPROM_N_5GHZ_CHAN]; - struct ath5k_chan_pcal_info ee_pwr_cal_b[AR5K_EEPROM_N_2GHZ_CHAN]; - struct ath5k_chan_pcal_info ee_pwr_cal_g[AR5K_EEPROM_N_2GHZ_CHAN]; + struct ath5k_chan_pcal_info ee_pwr_cal_b[AR5K_EEPROM_N_2GHZ_CHAN_MAX]; + struct ath5k_chan_pcal_info ee_pwr_cal_g[AR5K_EEPROM_N_2GHZ_CHAN_MAX]; /* Per rate target power levels */ - u16 ee_rate_target_pwr_num[AR5K_EEPROM_N_MODES]; + u8 ee_rate_target_pwr_num[AR5K_EEPROM_N_MODES]; struct ath5k_rate_pcal_info ee_rate_tpwr_a[AR5K_EEPROM_N_5GHZ_CHAN]; - struct ath5k_rate_pcal_info ee_rate_tpwr_b[AR5K_EEPROM_N_2GHZ_CHAN]; - struct ath5k_rate_pcal_info ee_rate_tpwr_g[AR5K_EEPROM_N_2GHZ_CHAN]; + struct ath5k_rate_pcal_info ee_rate_tpwr_b[AR5K_EEPROM_N_2GHZ_CHAN_MAX]; + struct ath5k_rate_pcal_info ee_rate_tpwr_g[AR5K_EEPROM_N_2GHZ_CHAN_MAX]; /* Conformance test limits (Unused) */ - u16 ee_ctls; - u16 ee_ctl[AR5K_EEPROM_MAX_CTLS]; + u8 ee_ctls; + u8 ee_ctl[AR5K_EEPROM_MAX_CTLS]; struct ath5k_edge_power ee_ctl_pwr[AR5K_EEPROM_N_EDGES * AR5K_EEPROM_MAX_CTLS]; /* Noise Floor Calibration settings */ -- GitLab From 9ca9fb8aa8422595956af9681518cdb8b167055e Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 16 Mar 2009 22:34:02 -0400 Subject: [PATCH 4862/4982] ath5k: disable MIB interrupts The MIB interrupt fires whenever counters overflow; however without support for automatic noise immunity, we can sometimes get an interrupt storm. The get_stats() callback reads the counters anyway so we can disable the interrupt for now until ANI is implemented. This fixes the issue reported in http://bugzilla.kernel.org/show_bug.cgi?id=12647. Changes-licensed-under: 3-Clause-BSD Cc: stable@kernel.org Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index cad3ccf61b0..8eec155ed0c 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -2305,7 +2305,7 @@ ath5k_init(struct ath5k_softc *sc) sc->curband = &sc->sbands[sc->curchan->band]; sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | - AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB; + AR5K_INT_FATAL | AR5K_INT_GLOBAL; ret = ath5k_reset(sc, false, false); if (ret) goto done; -- GitLab From e23a9014fd4d502a419255a83e2479ab804c6f16 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 16 Mar 2009 22:34:03 -0400 Subject: [PATCH 4863/4982] ath5k: remove dummy PCI "retry timeout" fix Remove the PCI retry timeout code, for all the same reasons that Luis Rodriguez removed it for ath9k. Changes-licensed-under: 3-Clause-BSD Cc: Luis Rodriguez Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 8eec155ed0c..ef9825fa4ec 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -685,13 +685,6 @@ ath5k_pci_resume(struct pci_dev *pdev) if (err) return err; - /* - * Suspend/Resume resets the PCI configuration space, so we have to - * re-disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state - */ - pci_write_config_byte(pdev, 0x41, 0); - err = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); if (err) { ATH5K_ERR(sc, "request_irq failed\n"); -- GitLab From 722f069a6dc95d7c6c2cdfbe3413899a3b768f9c Mon Sep 17 00:00:00 2001 From: Sujith Date: Tue, 17 Mar 2009 08:50:06 +0530 Subject: [PATCH 4864/4982] mac80211: Tear down aggregation sessions for suspend/resume When the driver has been notified with a STA_REMOVE, it tears down the internal ADDBA state. On resume, trying to initiate aggregation would fail because mac80211 has not cleared the operational state for that . This can be fixed by tearing down the existing sessions on a suspend. Also, the driver can initiate a new BA session when suspend is in progress. This is fixed by marking the station as being in suspend state and denying ADDBA requests for such STAs. Signed-off-by: Sujith Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/agg-rx.c | 8 ++++++++ net/mac80211/agg-tx.c | 9 +++++++++ net/mac80211/pm.c | 25 +++++++++++++++++++++++++ net/mac80211/sta_info.h | 3 +++ 4 files changed, 45 insertions(+) diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index a95affc9462..07656d830bc 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -197,6 +197,14 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, status = WLAN_STATUS_REQUEST_DECLINED; + if (test_sta_flags(sta, WLAN_STA_SUSPEND)) { +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "Suspend in progress. " + "Denying ADDBA request\n"); +#endif + goto end_no_lock; + } + /* sanity check for incoming parameters: * check if configuration can support the BA policy * and if buffer size does not exceeds max value */ diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 1df116d4d6e..e5776ef1717 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -257,6 +257,15 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) goto unlock; } + if (test_sta_flags(sta, WLAN_STA_SUSPEND)) { +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "Suspend in progress. " + "Denying BA session request\n"); +#endif + ret = -EINVAL; + goto unlock; + } + spin_lock_bh(&sta->lock); sdata = sta->sdata; diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index ef7be1ce2c8..1e6152ac677 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -21,6 +21,19 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) list_for_each_entry(sdata, &local->interfaces, list) ieee80211_disable_keys(sdata); + /* Tear down aggregation sessions */ + + rcu_read_lock(); + + if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { + list_for_each_entry_rcu(sta, &local->sta_list, list) { + set_sta_flags(sta, WLAN_STA_SUSPEND); + ieee80211_sta_tear_down_BA_sessions(sta); + } + } + + rcu_read_unlock(); + /* remove STAs */ if (local->ops->sta_notify) { spin_lock_irqsave(&local->sta_lock, flags); @@ -102,6 +115,18 @@ int __ieee80211_resume(struct ieee80211_hw *hw) spin_unlock_irqrestore(&local->sta_lock, flags); } + /* Clear Suspend state so that ADDBA requests can be processed */ + + rcu_read_lock(); + + if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { + list_for_each_entry_rcu(sta, &local->sta_list, list) { + clear_sta_flags(sta, WLAN_STA_SUSPEND); + } + } + + rcu_read_unlock(); + /* add back keys */ list_for_each_entry(sdata, &local->interfaces, list) if (netif_running(sdata->dev)) diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 1f45573c580..5b223b216e5 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -35,6 +35,8 @@ * IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next * frame to this station is transmitted. * @WLAN_STA_MFP: Management frame protection is used with this STA. + * @WLAN_STA_SUSPEND: Set/cleared during a suspend/resume cycle. + * Used to deny ADDBA requests (both TX and RX). */ enum ieee80211_sta_info_flags { WLAN_STA_AUTH = 1<<0, @@ -48,6 +50,7 @@ enum ieee80211_sta_info_flags { WLAN_STA_PSPOLL = 1<<8, WLAN_STA_CLEAR_PS_FILT = 1<<9, WLAN_STA_MFP = 1<<10, + WLAN_STA_SUSPEND = 1<<11 }; #define STA_TID_NUM 16 -- GitLab From 6d5eaafa558783a669bb46c3dba902370e8f0ffc Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Tue, 17 Mar 2009 11:29:19 +0100 Subject: [PATCH 4865/4982] rt2x00: Update MAINTAINERS entry: new mailinglist The rt2400-devel mailinglist will be replaced by the new mailinglist rt2x00-users. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index fa7be04b0cf..bdadcb3c3f4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3602,7 +3602,7 @@ S: Maintained RALINK RT2X00 WIRELESS LAN DRIVER P: rt2x00 project L: linux-wireless@vger.kernel.org -L: rt2400-devel@lists.sourceforge.net +L: users@rt2x00.serialmonkey.com W: http://rt2x00.serialmonkey.com/ S: Maintained T: git kernel.org:/pub/scm/linux/kernel/git/ivd/rt2x00.git -- GitLab From 8f655dde240293f3b82313cae91c64ffd7b64c50 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Sun, 15 Mar 2009 22:20:35 +0200 Subject: [PATCH 4866/4982] ath5k: Add tx power calibration support * Add tx power calibration support * Add a few tx power limits * Hardcode default power to 12.5dB * Disable TPC for now v2: Address Jiri's comments Signed-off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/ath5k.h | 35 +- drivers/net/wireless/ath5k/attach.c | 2 + drivers/net/wireless/ath5k/base.c | 12 +- drivers/net/wireless/ath5k/desc.c | 4 + drivers/net/wireless/ath5k/phy.c | 1170 +++++++++++++++++++++++++-- drivers/net/wireless/ath5k/reg.h | 19 + drivers/net/wireless/ath5k/reset.c | 35 +- 7 files changed, 1180 insertions(+), 97 deletions(-) diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index 0dc2c7321c8..0b616e72fe0 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h @@ -204,9 +204,9 @@ #define AR5K_TUNE_CWMAX_11B 1023 #define AR5K_TUNE_CWMAX_XR 7 #define AR5K_TUNE_NOISE_FLOOR -72 -#define AR5K_TUNE_MAX_TXPOWER 60 -#define AR5K_TUNE_DEFAULT_TXPOWER 30 -#define AR5K_TUNE_TPC_TXPOWER true +#define AR5K_TUNE_MAX_TXPOWER 63 +#define AR5K_TUNE_DEFAULT_TXPOWER 25 +#define AR5K_TUNE_TPC_TXPOWER false #define AR5K_TUNE_ANT_DIVERSITY true #define AR5K_TUNE_HWTXTRIES 4 @@ -551,11 +551,11 @@ enum ath5k_pkt_type { */ #define AR5K_TXPOWER_OFDM(_r, _v) ( \ ((0 & 1) << ((_v) + 6)) | \ - (((ah->ah_txpower.txp_rates[(_r)]) & 0x3f) << (_v)) \ + (((ah->ah_txpower.txp_rates_power_table[(_r)]) & 0x3f) << (_v)) \ ) #define AR5K_TXPOWER_CCK(_r, _v) ( \ - (ah->ah_txpower.txp_rates[(_r)] & 0x3f) << (_v) \ + (ah->ah_txpower.txp_rates_power_table[(_r)] & 0x3f) << (_v) \ ) /* @@ -1085,13 +1085,25 @@ struct ath5k_hw { struct ath5k_gain ah_gain; u8 ah_offset[AR5K_MAX_RF_BANKS]; + struct { - u16 txp_pcdac[AR5K_EEPROM_POWER_TABLE_SIZE]; - u16 txp_rates[AR5K_MAX_RATES]; - s16 txp_min; - s16 txp_max; + /* Temporary tables used for interpolation */ + u8 tmpL[AR5K_EEPROM_N_PD_GAINS] + [AR5K_EEPROM_POWER_TABLE_SIZE]; + u8 tmpR[AR5K_EEPROM_N_PD_GAINS] + [AR5K_EEPROM_POWER_TABLE_SIZE]; + u8 txp_pd_table[AR5K_EEPROM_POWER_TABLE_SIZE * 2]; + u16 txp_rates_power_table[AR5K_MAX_RATES]; + u8 txp_min_idx; bool txp_tpc; + /* Values in 0.25dB units */ + s16 txp_min_pwr; + s16 txp_max_pwr; + s16 txp_offset; s16 txp_ofdm; + /* Values in dB units */ + s16 txp_cck_ofdm_pwr_delta; + s16 txp_cck_ofdm_gainf_delta; } ah_txpower; struct { @@ -1161,6 +1173,7 @@ extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_l /* EEPROM access functions */ extern int ath5k_eeprom_init(struct ath5k_hw *ah); +extern void ath5k_eeprom_detach(struct ath5k_hw *ah); extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah); @@ -1256,8 +1269,8 @@ extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant); extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah); extern int ath5k_hw_phy_disable(struct ath5k_hw *ah); /* TX power setup */ -extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, unsigned int txpower); -extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, unsigned int power); +extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 ee_mode, u8 txpower); +extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 ee_mode, u8 txpower); /* * Functions used internaly diff --git a/drivers/net/wireless/ath5k/attach.c b/drivers/net/wireless/ath5k/attach.c index 656cb9dc833..70d376c63aa 100644 --- a/drivers/net/wireless/ath5k/attach.c +++ b/drivers/net/wireless/ath5k/attach.c @@ -341,6 +341,8 @@ void ath5k_hw_detach(struct ath5k_hw *ah) if (ah->ah_rf_banks != NULL) kfree(ah->ah_rf_banks); + ath5k_eeprom_detach(ah); + /* assume interrupts are down */ kfree(ah); } diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index ef9825fa4ec..f28b86c5d34 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -1209,6 +1209,9 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) pktlen = skb->len; + /* FIXME: If we are in g mode and rate is a CCK rate + * subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta + * from tx power (value is in dB units already) */ if (info->control.hw_key) { keyidx = info->control.hw_key->hw_key_idx; pktlen += info->control.hw_key->icv_len; @@ -2037,6 +2040,9 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) antenna = sc->bsent & 4 ? 2 : 1; } + /* FIXME: If we are in g mode and rate is a CCK rate + * subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta + * from tx power (value is in dB units already) */ ds->ds_data = bf->skbaddr; ret = ah->ah_setup_tx_desc(ah, ds, skb->len, ieee80211_get_hdrlen_from_skb(skb), @@ -2601,12 +2607,6 @@ ath5k_reset(struct ath5k_softc *sc, bool stop, bool change_channel) goto err; } - /* - * This is needed only to setup initial state - * but it's best done after a reset. - */ - ath5k_hw_set_txpower_limit(sc->ah, 0); - ret = ath5k_rx_start(sc); if (ret) { ATH5K_ERR(sc, "can't start recv logic\n"); diff --git a/drivers/net/wireless/ath5k/desc.c b/drivers/net/wireless/ath5k/desc.c index b40a9287a39..dc30a2b70a6 100644 --- a/drivers/net/wireless/ath5k/desc.c +++ b/drivers/net/wireless/ath5k/desc.c @@ -194,6 +194,10 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, return -EINVAL; } + tx_power += ah->ah_txpower.txp_offset; + if (tx_power > AR5K_TUNE_MAX_TXPOWER) + tx_power = AR5K_TUNE_MAX_TXPOWER; + /* Clear descriptor */ memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc)); diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c index 81f5bebc48b..9e2faae5ae9 100644 --- a/drivers/net/wireless/ath5k/phy.c +++ b/drivers/net/wireless/ath5k/phy.c @@ -4,6 +4,7 @@ * Copyright (c) 2004-2007 Reyk Floeter * Copyright (c) 2006-2009 Nick Kossifidis * Copyright (c) 2007-2008 Jiri Slaby + * Copyright (c) 2008-2009 Felix Fietkau * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -183,7 +184,9 @@ static void ath5k_hw_request_rfgain_probe(struct ath5k_hw *ah) if (ah->ah_gain.g_state != AR5K_RFGAIN_ACTIVE) return; - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_max, + /* Send the packet with 2dB below max power as + * patent doc suggest */ + ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_max_pwr - 4, AR5K_PHY_PAPD_PROBE_TXPOWER) | AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE); @@ -1433,93 +1436,1120 @@ unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah) return false; /*XXX: What do we return for 5210 ?*/ } + +/****************\ +* TX power setup * +\****************/ + +/* + * Helper functions + */ + +/* + * Do linear interpolation between two given (x, y) points + */ +static s16 +ath5k_get_interpolated_value(s16 target, s16 x_left, s16 x_right, + s16 y_left, s16 y_right) +{ + s16 ratio, result; + + /* Avoid divide by zero and skip interpolation + * if we have the same point */ + if ((x_left == x_right) || (y_left == y_right)) + return y_left; + + /* + * Since we use ints and not fps, we need to scale up in + * order to get a sane ratio value (or else we 'll eg. get + * always 1 instead of 1.25, 1.75 etc). We scale up by 100 + * to have some accuracy both for 0.5 and 0.25 steps. + */ + ratio = ((100 * y_right - 100 * y_left)/(x_right - x_left)); + + /* Now scale down to be in range */ + result = y_left + (ratio * (target - x_left) / 100); + + return result; +} + +/* + * Find vertical boundary (min pwr) for the linear PCDAC curve. + * + * Since we have the top of the curve and we draw the line below + * until we reach 1 (1 pcdac step) we need to know which point + * (x value) that is so that we don't go below y axis and have negative + * pcdac values when creating the curve, or fill the table with zeroes. + */ +static s16 +ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR, + const s16 *pwrL, const s16 *pwrR) +{ + s8 tmp; + s16 min_pwrL, min_pwrR; + s16 pwr_i = pwrL[0]; + + do { + pwr_i--; + tmp = (s8) ath5k_get_interpolated_value(pwr_i, + pwrL[0], pwrL[1], + stepL[0], stepL[1]); + + } while (tmp > 1); + + min_pwrL = pwr_i; + + pwr_i = pwrR[0]; + do { + pwr_i--; + tmp = (s8) ath5k_get_interpolated_value(pwr_i, + pwrR[0], pwrR[1], + stepR[0], stepR[1]); + + } while (tmp > 1); + + min_pwrR = pwr_i; + + /* Keep the right boundary so that it works for both curves */ + return max(min_pwrL, min_pwrR); +} + +/* + * Interpolate (pwr,vpd) points to create a Power to PDADC or a + * Power to PCDAC curve. + * + * Each curve has power on x axis (in 0.5dB units) and PCDAC/PDADC + * steps (offsets) on y axis. Power can go up to 31.5dB and max + * PCDAC/PDADC step for each curve is 64 but we can write more than + * one curves on hw so we can go up to 128 (which is the max step we + * can write on the final table). + * + * We write y values (PCDAC/PDADC steps) on hw. + */ +static void +ath5k_create_power_curve(s16 pmin, s16 pmax, + const s16 *pwr, const u8 *vpd, + u8 num_points, + u8 *vpd_table, u8 type) +{ + u8 idx[2] = { 0, 1 }; + s16 pwr_i = 2*pmin; + int i; + + if (num_points < 2) + return; + + /* We want the whole line, so adjust boundaries + * to cover the entire power range. Note that + * power values are already 0.25dB so no need + * to multiply pwr_i by 2 */ + if (type == AR5K_PWRTABLE_LINEAR_PCDAC) { + pwr_i = pmin; + pmin = 0; + pmax = 63; + } + + /* Find surrounding turning points (TPs) + * and interpolate between them */ + for (i = 0; (i <= (u16) (pmax - pmin)) && + (i < AR5K_EEPROM_POWER_TABLE_SIZE); i++) { + + /* We passed the right TP, move to the next set of TPs + * if we pass the last TP, extrapolate above using the last + * two TPs for ratio */ + if ((pwr_i > pwr[idx[1]]) && (idx[1] < num_points - 1)) { + idx[0]++; + idx[1]++; + } + + vpd_table[i] = (u8) ath5k_get_interpolated_value(pwr_i, + pwr[idx[0]], pwr[idx[1]], + vpd[idx[0]], vpd[idx[1]]); + + /* Increase by 0.5dB + * (0.25 dB units) */ + pwr_i += 2; + } +} + +/* + * Get the surrounding per-channel power calibration piers + * for a given frequency so that we can interpolate between + * them and come up with an apropriate dataset for our current + * channel. + */ +static void +ath5k_get_chan_pcal_surrounding_piers(struct ath5k_hw *ah, + struct ieee80211_channel *channel, + struct ath5k_chan_pcal_info **pcinfo_l, + struct ath5k_chan_pcal_info **pcinfo_r) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + struct ath5k_chan_pcal_info *pcinfo; + u8 idx_l, idx_r; + u8 mode, max, i; + u32 target = channel->center_freq; + + idx_l = 0; + idx_r = 0; + + if (!(channel->hw_value & CHANNEL_OFDM)) { + pcinfo = ee->ee_pwr_cal_b; + mode = AR5K_EEPROM_MODE_11B; + } else if (channel->hw_value & CHANNEL_2GHZ) { + pcinfo = ee->ee_pwr_cal_g; + mode = AR5K_EEPROM_MODE_11G; + } else { + pcinfo = ee->ee_pwr_cal_a; + mode = AR5K_EEPROM_MODE_11A; + } + max = ee->ee_n_piers[mode] - 1; + + /* Frequency is below our calibrated + * range. Use the lowest power curve + * we have */ + if (target < pcinfo[0].freq) { + idx_l = idx_r = 0; + goto done; + } + + /* Frequency is above our calibrated + * range. Use the highest power curve + * we have */ + if (target > pcinfo[max].freq) { + idx_l = idx_r = max; + goto done; + } + + /* Frequency is inside our calibrated + * channel range. Pick the surrounding + * calibration piers so that we can + * interpolate */ + for (i = 0; i <= max; i++) { + + /* Frequency matches one of our calibration + * piers, no need to interpolate, just use + * that calibration pier */ + if (pcinfo[i].freq == target) { + idx_l = idx_r = i; + goto done; + } + + /* We found a calibration pier that's above + * frequency, use this pier and the previous + * one to interpolate */ + if (target < pcinfo[i].freq) { + idx_r = i; + idx_l = idx_r - 1; + goto done; + } + } + +done: + *pcinfo_l = &pcinfo[idx_l]; + *pcinfo_r = &pcinfo[idx_r]; + + return; +} + +/* + * Get the surrounding per-rate power calibration data + * for a given frequency and interpolate between power + * values to set max target power supported by hw for + * each rate. + */ +static void +ath5k_get_rate_pcal_data(struct ath5k_hw *ah, + struct ieee80211_channel *channel, + struct ath5k_rate_pcal_info *rates) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + struct ath5k_rate_pcal_info *rpinfo; + u8 idx_l, idx_r; + u8 mode, max, i; + u32 target = channel->center_freq; + + idx_l = 0; + idx_r = 0; + + if (!(channel->hw_value & CHANNEL_OFDM)) { + rpinfo = ee->ee_rate_tpwr_b; + mode = AR5K_EEPROM_MODE_11B; + } else if (channel->hw_value & CHANNEL_2GHZ) { + rpinfo = ee->ee_rate_tpwr_g; + mode = AR5K_EEPROM_MODE_11G; + } else { + rpinfo = ee->ee_rate_tpwr_a; + mode = AR5K_EEPROM_MODE_11A; + } + max = ee->ee_rate_target_pwr_num[mode] - 1; + + /* Get the surrounding calibration + * piers - same as above */ + if (target < rpinfo[0].freq) { + idx_l = idx_r = 0; + goto done; + } + + if (target > rpinfo[max].freq) { + idx_l = idx_r = max; + goto done; + } + + for (i = 0; i <= max; i++) { + + if (rpinfo[i].freq == target) { + idx_l = idx_r = i; + goto done; + } + + if (target < rpinfo[i].freq) { + idx_r = i; + idx_l = idx_r - 1; + goto done; + } + } + +done: + /* Now interpolate power value, based on the frequency */ + rates->freq = target; + + rates->target_power_6to24 = + ath5k_get_interpolated_value(target, rpinfo[idx_l].freq, + rpinfo[idx_r].freq, + rpinfo[idx_l].target_power_6to24, + rpinfo[idx_r].target_power_6to24); + + rates->target_power_36 = + ath5k_get_interpolated_value(target, rpinfo[idx_l].freq, + rpinfo[idx_r].freq, + rpinfo[idx_l].target_power_36, + rpinfo[idx_r].target_power_36); + + rates->target_power_48 = + ath5k_get_interpolated_value(target, rpinfo[idx_l].freq, + rpinfo[idx_r].freq, + rpinfo[idx_l].target_power_48, + rpinfo[idx_r].target_power_48); + + rates->target_power_54 = + ath5k_get_interpolated_value(target, rpinfo[idx_l].freq, + rpinfo[idx_r].freq, + rpinfo[idx_l].target_power_54, + rpinfo[idx_r].target_power_54); +} + +/* + * Get the max edge power for this channel if + * we have such data from EEPROM's Conformance Test + * Limits (CTL), and limit max power if needed. + * + * FIXME: Only works for world regulatory domains + */ +static void +ath5k_get_max_ctl_power(struct ath5k_hw *ah, + struct ieee80211_channel *channel) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + struct ath5k_edge_power *rep = ee->ee_ctl_pwr; + u8 *ctl_val = ee->ee_ctl; + s16 max_chan_pwr = ah->ah_txpower.txp_max_pwr / 4; + s16 edge_pwr = 0; + u8 rep_idx; + u8 i, ctl_mode; + u8 ctl_idx = 0xFF; + u32 target = channel->center_freq; + + /* Find out a CTL for our mode that's not mapped + * on a specific reg domain. + * + * TODO: Map our current reg domain to one of the 3 available + * reg domain ids so that we can support more CTLs. */ + switch (channel->hw_value & CHANNEL_MODES) { + case CHANNEL_A: + ctl_mode = AR5K_CTL_11A | AR5K_CTL_NO_REGDOMAIN; + break; + case CHANNEL_G: + ctl_mode = AR5K_CTL_11G | AR5K_CTL_NO_REGDOMAIN; + break; + case CHANNEL_B: + ctl_mode = AR5K_CTL_11B | AR5K_CTL_NO_REGDOMAIN; + break; + case CHANNEL_T: + ctl_mode = AR5K_CTL_TURBO | AR5K_CTL_NO_REGDOMAIN; + break; + case CHANNEL_TG: + ctl_mode = AR5K_CTL_TURBOG | AR5K_CTL_NO_REGDOMAIN; + break; + case CHANNEL_XR: + /* Fall through */ + default: + return; + } + + for (i = 0; i < ee->ee_ctls; i++) { + if (ctl_val[i] == ctl_mode) { + ctl_idx = i; + break; + } + } + + /* If we have a CTL dataset available grab it and find the + * edge power for our frequency */ + if (ctl_idx == 0xFF) + return; + + /* Edge powers are sorted by frequency from lower + * to higher. Each CTL corresponds to 8 edge power + * measurements. */ + rep_idx = ctl_idx * AR5K_EEPROM_N_EDGES; + + /* Don't do boundaries check because we + * might have more that one bands defined + * for this mode */ + + /* Get the edge power that's closer to our + * frequency */ + for (i = 0; i < AR5K_EEPROM_N_EDGES; i++) { + rep_idx += i; + if (target <= rep[rep_idx].freq) + edge_pwr = (s16) rep[rep_idx].edge; + } + + if (edge_pwr) + ah->ah_txpower.txp_max_pwr = 4*min(edge_pwr, max_chan_pwr); +} + + +/* + * Power to PCDAC table functions + */ + /* - * TX power setup + * Fill Power to PCDAC table on RF5111 + * + * No further processing is needed for RF5111, the only thing we have to + * do is fill the values below and above calibration range since eeprom data + * may not cover the entire PCDAC table. */ +static void +ath5k_fill_pwr_to_pcdac_table(struct ath5k_hw *ah, s16* table_min, + s16 *table_max) +{ + u8 *pcdac_out = ah->ah_txpower.txp_pd_table; + u8 *pcdac_tmp = ah->ah_txpower.tmpL[0]; + u8 pcdac_0, pcdac_n, pcdac_i, pwr_idx, i; + s16 min_pwr, max_pwr; + + /* Get table boundaries */ + min_pwr = table_min[0]; + pcdac_0 = pcdac_tmp[0]; + + max_pwr = table_max[0]; + pcdac_n = pcdac_tmp[table_max[0] - table_min[0]]; + + /* Extrapolate below minimum using pcdac_0 */ + pcdac_i = 0; + for (i = 0; i < min_pwr; i++) + pcdac_out[pcdac_i++] = pcdac_0; + + /* Copy values from pcdac_tmp */ + pwr_idx = min_pwr; + for (i = 0 ; pwr_idx <= max_pwr && + pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE; i++) { + pcdac_out[pcdac_i++] = pcdac_tmp[i]; + pwr_idx++; + } + + /* Extrapolate above maximum */ + while (pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE) + pcdac_out[pcdac_i++] = pcdac_n; + +} /* - * Initialize the tx power table (not fully implemented) + * Combine available XPD Curves and fill Linear Power to PCDAC table + * on RF5112 + * + * RFX112 can have up to 2 curves (one for low txpower range and one for + * higher txpower range). We need to put them both on pcdac_out and place + * them in the correct location. In case we only have one curve available + * just fit it on pcdac_out (it's supposed to cover the entire range of + * available pwr levels since it's always the higher power curve). Extrapolate + * below and above final table if needed. */ -static void ath5k_txpower_table(struct ath5k_hw *ah, - struct ieee80211_channel *channel, s16 max_power) +static void +ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min, + s16 *table_max, u8 pdcurves) { - unsigned int i, min, max, n; - u16 txpower, *rates; - - rates = ah->ah_txpower.txp_rates; - - txpower = AR5K_TUNE_DEFAULT_TXPOWER * 2; - if (max_power > txpower) - txpower = max_power > AR5K_TUNE_MAX_TXPOWER ? - AR5K_TUNE_MAX_TXPOWER : max_power; - - for (i = 0; i < AR5K_MAX_RATES; i++) - rates[i] = txpower; - - /* XXX setup target powers by rate */ - - ah->ah_txpower.txp_min = rates[7]; - ah->ah_txpower.txp_max = rates[0]; - ah->ah_txpower.txp_ofdm = rates[0]; - - /* Calculate the power table */ - n = ARRAY_SIZE(ah->ah_txpower.txp_pcdac); - min = AR5K_EEPROM_PCDAC_START; - max = AR5K_EEPROM_PCDAC_STOP; - for (i = 0; i < n; i += AR5K_EEPROM_PCDAC_STEP) - ah->ah_txpower.txp_pcdac[i] = -#ifdef notyet - min + ((i * (max - min)) / n); -#else - min; + u8 *pcdac_out = ah->ah_txpower.txp_pd_table; + u8 *pcdac_low_pwr; + u8 *pcdac_high_pwr; + u8 *pcdac_tmp; + u8 pwr; + s16 max_pwr_idx; + s16 min_pwr_idx; + s16 mid_pwr_idx = 0; + /* Edge flag turs on the 7nth bit on the PCDAC + * to delcare the higher power curve (force values + * to be greater than 64). If we only have one curve + * we don't need to set this, if we have 2 curves and + * fill the table backwards this can also be used to + * switch from higher power curve to lower power curve */ + u8 edge_flag; + int i; + + /* When we have only one curve available + * that's the higher power curve. If we have + * two curves the first is the high power curve + * and the next is the low power curve. */ + if (pdcurves > 1) { + pcdac_low_pwr = ah->ah_txpower.tmpL[1]; + pcdac_high_pwr = ah->ah_txpower.tmpL[0]; + mid_pwr_idx = table_max[1] - table_min[1] - 1; + max_pwr_idx = (table_max[0] - table_min[0]) / 2; + + /* If table size goes beyond 31.5dB, keep the + * upper 31.5dB range when setting tx power. + * Note: 126 = 31.5 dB in quarter dB steps */ + if (table_max[0] - table_min[1] > 126) + min_pwr_idx = table_max[0] - 126; + else + min_pwr_idx = table_min[1]; + + /* Since we fill table backwards + * start from high power curve */ + pcdac_tmp = pcdac_high_pwr; + + edge_flag = 0x40; +#if 0 + /* If both min and max power limits are in lower + * power curve's range, only use the low power curve. + * TODO: min/max levels are related to target + * power values requested from driver/user + * XXX: Is this really needed ? */ + if (min_pwr < table_max[1] && + max_pwr < table_max[1]) { + edge_flag = 0; + pcdac_tmp = pcdac_low_pwr; + max_pwr_idx = (table_max[1] - table_min[1])/2; + } #endif + } else { + pcdac_low_pwr = ah->ah_txpower.tmpL[1]; /* Zeroed */ + pcdac_high_pwr = ah->ah_txpower.tmpL[0]; + min_pwr_idx = table_min[0]; + max_pwr_idx = (table_max[0] - table_min[0]) / 2; + pcdac_tmp = pcdac_high_pwr; + edge_flag = 0; + } + + /* This is used when setting tx power*/ + ah->ah_txpower.txp_min_idx = min_pwr_idx/2; + + /* Fill Power to PCDAC table backwards */ + pwr = max_pwr_idx; + for (i = 63; i >= 0; i--) { + /* Entering lower power range, reset + * edge flag and set pcdac_tmp to lower + * power curve.*/ + if (edge_flag == 0x40 && + (2*pwr <= (table_max[1] - table_min[0]) || pwr == 0)) { + edge_flag = 0x00; + pcdac_tmp = pcdac_low_pwr; + pwr = mid_pwr_idx/2; + } + + /* Don't go below 1, extrapolate below if we have + * already swithced to the lower power curve -or + * we only have one curve and edge_flag is zero + * anyway */ + if (pcdac_tmp[pwr] < 1 && (edge_flag == 0x00)) { + while (i >= 0) { + pcdac_out[i] = pcdac_out[i + 1]; + i--; + } + break; + } + + pcdac_out[i] = pcdac_tmp[pwr] | edge_flag; + + /* Extrapolate above if pcdac is greater than + * 126 -this can happen because we OR pcdac_out + * value with edge_flag on high power curve */ + if (pcdac_out[i] > 126) + pcdac_out[i] = 126; + + /* Decrease by a 0.5dB step */ + pwr--; + } } +/* Write PCDAC values on hw */ +static void +ath5k_setup_pcdac_table(struct ath5k_hw *ah) +{ + u8 *pcdac_out = ah->ah_txpower.txp_pd_table; + int i; + + /* + * Write TX power values + */ + for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) { + ath5k_hw_reg_write(ah, + (((pcdac_out[2*i + 0] << 8 | 0xff) & 0xffff) << 0) | + (((pcdac_out[2*i + 1] << 8 | 0xff) & 0xffff) << 16), + AR5K_PHY_PCDAC_TXPOWER(i)); + } +} + + /* - * Set transmition power + * Power to PDADC table functions */ -int /*O.K. - txpower_table is unimplemented so this doesn't work*/ -ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, - unsigned int txpower) + +/* + * Set the gain boundaries and create final Power to PDADC table + * + * We can have up to 4 pd curves, we need to do a simmilar process + * as we do for RF5112. This time we don't have an edge_flag but we + * set the gain boundaries on a separate register. + */ +static void +ath5k_combine_pwr_to_pdadc_curves(struct ath5k_hw *ah, + s16 *pwr_min, s16 *pwr_max, u8 pdcurves) { - bool tpc = ah->ah_txpower.txp_tpc; - unsigned int i; + u8 gain_boundaries[AR5K_EEPROM_N_PD_GAINS]; + u8 *pdadc_out = ah->ah_txpower.txp_pd_table; + u8 *pdadc_tmp; + s16 pdadc_0; + u8 pdadc_i, pdadc_n, pwr_step, pdg, max_idx, table_size; + u8 pd_gain_overlap; + + /* Note: Register value is initialized on initvals + * there is no feedback from hw. + * XXX: What about pd_gain_overlap from EEPROM ? */ + pd_gain_overlap = (u8) ath5k_hw_reg_read(ah, AR5K_PHY_TPC_RG5) & + AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP; + + /* Create final PDADC table */ + for (pdg = 0, pdadc_i = 0; pdg < pdcurves; pdg++) { + pdadc_tmp = ah->ah_txpower.tmpL[pdg]; + + if (pdg == pdcurves - 1) + /* 2 dB boundary stretch for last + * (higher power) curve */ + gain_boundaries[pdg] = pwr_max[pdg] + 4; + else + /* Set gain boundary in the middle + * between this curve and the next one */ + gain_boundaries[pdg] = + (pwr_max[pdg] + pwr_min[pdg + 1]) / 2; + + /* Sanity check in case our 2 db stretch got out of + * range. */ + if (gain_boundaries[pdg] > AR5K_TUNE_MAX_TXPOWER) + gain_boundaries[pdg] = AR5K_TUNE_MAX_TXPOWER; + + /* For the first curve (lower power) + * start from 0 dB */ + if (pdg == 0) + pdadc_0 = 0; + else + /* For the other curves use the gain overlap */ + pdadc_0 = (gain_boundaries[pdg - 1] - pwr_min[pdg]) - + pd_gain_overlap; - ATH5K_TRACE(ah->ah_sc); - if (txpower > AR5K_TUNE_MAX_TXPOWER) { - ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower); - return -EINVAL; + /* Force each power step to be at least 0.5 dB */ + if ((pdadc_tmp[1] - pdadc_tmp[0]) > 1) + pwr_step = pdadc_tmp[1] - pdadc_tmp[0]; + else + pwr_step = 1; + + /* If pdadc_0 is negative, we need to extrapolate + * below this pdgain by a number of pwr_steps */ + while ((pdadc_0 < 0) && (pdadc_i < 128)) { + s16 tmp = pdadc_tmp[0] + pdadc_0 * pwr_step; + pdadc_out[pdadc_i++] = (tmp < 0) ? 0 : (u8) tmp; + pdadc_0++; + } + + /* Set last pwr level, using gain boundaries */ + pdadc_n = gain_boundaries[pdg] + pd_gain_overlap - pwr_min[pdg]; + /* Limit it to be inside pwr range */ + table_size = pwr_max[pdg] - pwr_min[pdg]; + max_idx = (pdadc_n < table_size) ? pdadc_n : table_size; + + /* Fill pdadc_out table */ + while (pdadc_0 < max_idx) + pdadc_out[pdadc_i++] = pdadc_tmp[pdadc_0++]; + + /* Need to extrapolate above this pdgain? */ + if (pdadc_n <= max_idx) + continue; + + /* Force each power step to be at least 0.5 dB */ + if ((pdadc_tmp[table_size - 1] - pdadc_tmp[table_size - 2]) > 1) + pwr_step = pdadc_tmp[table_size - 1] - + pdadc_tmp[table_size - 2]; + else + pwr_step = 1; + + /* Extrapolate above */ + while ((pdadc_0 < (s16) pdadc_n) && + (pdadc_i < AR5K_EEPROM_POWER_TABLE_SIZE * 2)) { + s16 tmp = pdadc_tmp[table_size - 1] + + (pdadc_0 - max_idx) * pwr_step; + pdadc_out[pdadc_i++] = (tmp > 127) ? 127 : (u8) tmp; + pdadc_0++; + } } + while (pdg < AR5K_EEPROM_N_PD_GAINS) { + gain_boundaries[pdg] = gain_boundaries[pdg - 1]; + pdg++; + } + + while (pdadc_i < AR5K_EEPROM_POWER_TABLE_SIZE * 2) { + pdadc_out[pdadc_i] = pdadc_out[pdadc_i - 1]; + pdadc_i++; + } + + /* Set gain boundaries */ + ath5k_hw_reg_write(ah, + AR5K_REG_SM(pd_gain_overlap, + AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP) | + AR5K_REG_SM(gain_boundaries[0], + AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1) | + AR5K_REG_SM(gain_boundaries[1], + AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2) | + AR5K_REG_SM(gain_boundaries[2], + AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3) | + AR5K_REG_SM(gain_boundaries[3], + AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4), + AR5K_PHY_TPC_RG5); + + /* Used for setting rate power table */ + ah->ah_txpower.txp_min_idx = pwr_min[0]; + +} + +/* Write PDADC values on hw */ +static void +ath5k_setup_pwr_to_pdadc_table(struct ath5k_hw *ah, + u8 pdcurves, u8 *pdg_to_idx) +{ + u8 *pdadc_out = ah->ah_txpower.txp_pd_table; + u32 reg; + u8 i; + + /* Select the right pdgain curves */ + + /* Clear current settings */ + reg = ath5k_hw_reg_read(ah, AR5K_PHY_TPC_RG1); + reg &= ~(AR5K_PHY_TPC_RG1_PDGAIN_1 | + AR5K_PHY_TPC_RG1_PDGAIN_2 | + AR5K_PHY_TPC_RG1_PDGAIN_3 | + AR5K_PHY_TPC_RG1_NUM_PD_GAIN); + /* - * RF2413 for some reason can't - * transmit anything if we call - * this funtion, so we skip it - * until we fix txpower. + * Use pd_gains curve from eeprom * - * XXX: Assume same for RF2425 - * to be safe. + * This overrides the default setting from initvals + * in case some vendors (e.g. Zcomax) don't use the default + * curves. If we don't honor their settings we 'll get a + * 5dB (1 * gain overlap ?) drop. */ - if ((ah->ah_radio == AR5K_RF2413) || (ah->ah_radio == AR5K_RF2425)) - return 0; + reg |= AR5K_REG_SM(pdcurves, AR5K_PHY_TPC_RG1_NUM_PD_GAIN); - /* Reset TX power values */ - memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); - ah->ah_txpower.txp_tpc = tpc; - - /* Initialize TX power table */ - ath5k_txpower_table(ah, channel, txpower); + switch (pdcurves) { + case 3: + reg |= AR5K_REG_SM(pdg_to_idx[2], AR5K_PHY_TPC_RG1_PDGAIN_3); + /* Fall through */ + case 2: + reg |= AR5K_REG_SM(pdg_to_idx[1], AR5K_PHY_TPC_RG1_PDGAIN_2); + /* Fall through */ + case 1: + reg |= AR5K_REG_SM(pdg_to_idx[0], AR5K_PHY_TPC_RG1_PDGAIN_1); + break; + } + ath5k_hw_reg_write(ah, reg, AR5K_PHY_TPC_RG1); /* * Write TX power values */ for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) { ath5k_hw_reg_write(ah, - ((((ah->ah_txpower.txp_pcdac[(i << 1) + 1] << 8) | 0xff) & 0xffff) << 16) | - (((ah->ah_txpower.txp_pcdac[(i << 1) ] << 8) | 0xff) & 0xffff), - AR5K_PHY_PCDAC_TXPOWER(i)); + ((pdadc_out[4*i + 0] & 0xff) << 0) | + ((pdadc_out[4*i + 1] & 0xff) << 8) | + ((pdadc_out[4*i + 2] & 0xff) << 16) | + ((pdadc_out[4*i + 3] & 0xff) << 24), + AR5K_PHY_PDADC_TXPOWER(i)); + } +} + + +/* + * Common code for PCDAC/PDADC tables + */ + +/* + * This is the main function that uses all of the above + * to set PCDAC/PDADC table on hw for the current channel. + * This table is used for tx power calibration on the basband, + * without it we get weird tx power levels and in some cases + * distorted spectral mask + */ +static int +ath5k_setup_channel_powertable(struct ath5k_hw *ah, + struct ieee80211_channel *channel, + u8 ee_mode, u8 type) +{ + struct ath5k_pdgain_info *pdg_L, *pdg_R; + struct ath5k_chan_pcal_info *pcinfo_L; + struct ath5k_chan_pcal_info *pcinfo_R; + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + u8 *pdg_curve_to_idx = ee->ee_pdc_to_idx[ee_mode]; + s16 table_min[AR5K_EEPROM_N_PD_GAINS]; + s16 table_max[AR5K_EEPROM_N_PD_GAINS]; + u8 *tmpL; + u8 *tmpR; + u32 target = channel->center_freq; + int pdg, i; + + /* Get surounding freq piers for this channel */ + ath5k_get_chan_pcal_surrounding_piers(ah, channel, + &pcinfo_L, + &pcinfo_R); + + /* Loop over pd gain curves on + * surounding freq piers by index */ + for (pdg = 0; pdg < ee->ee_pd_gains[ee_mode]; pdg++) { + + /* Fill curves in reverse order + * from lower power (max gain) + * to higher power. Use curve -> idx + * backmaping we did on eeprom init */ + u8 idx = pdg_curve_to_idx[pdg]; + + /* Grab the needed curves by index */ + pdg_L = &pcinfo_L->pd_curves[idx]; + pdg_R = &pcinfo_R->pd_curves[idx]; + + /* Initialize the temp tables */ + tmpL = ah->ah_txpower.tmpL[pdg]; + tmpR = ah->ah_txpower.tmpR[pdg]; + + /* Set curve's x boundaries and create + * curves so that they cover the same + * range (if we don't do that one table + * will have values on some range and the + * other one won't have any so interpolation + * will fail) */ + table_min[pdg] = min(pdg_L->pd_pwr[0], + pdg_R->pd_pwr[0]) / 2; + + table_max[pdg] = max(pdg_L->pd_pwr[pdg_L->pd_points - 1], + pdg_R->pd_pwr[pdg_R->pd_points - 1]) / 2; + + /* Now create the curves on surrounding channels + * and interpolate if needed to get the final + * curve for this gain on this channel */ + switch (type) { + case AR5K_PWRTABLE_LINEAR_PCDAC: + /* Override min/max so that we don't loose + * accuracy (don't divide by 2) */ + table_min[pdg] = min(pdg_L->pd_pwr[0], + pdg_R->pd_pwr[0]); + + table_max[pdg] = + max(pdg_L->pd_pwr[pdg_L->pd_points - 1], + pdg_R->pd_pwr[pdg_R->pd_points - 1]); + + /* Override minimum so that we don't get + * out of bounds while extrapolating + * below. Don't do this when we have 2 + * curves and we are on the high power curve + * because table_min is ok in this case */ + if (!(ee->ee_pd_gains[ee_mode] > 1 && pdg == 0)) { + + table_min[pdg] = + ath5k_get_linear_pcdac_min(pdg_L->pd_step, + pdg_R->pd_step, + pdg_L->pd_pwr, + pdg_R->pd_pwr); + + /* Don't go too low because we will + * miss the upper part of the curve. + * Note: 126 = 31.5dB (max power supported) + * in 0.25dB units */ + if (table_max[pdg] - table_min[pdg] > 126) + table_min[pdg] = table_max[pdg] - 126; + } + + /* Fall through */ + case AR5K_PWRTABLE_PWR_TO_PCDAC: + case AR5K_PWRTABLE_PWR_TO_PDADC: + + ath5k_create_power_curve(table_min[pdg], + table_max[pdg], + pdg_L->pd_pwr, + pdg_L->pd_step, + pdg_L->pd_points, tmpL, type); + + /* We are in a calibration + * pier, no need to interpolate + * between freq piers */ + if (pcinfo_L == pcinfo_R) + continue; + + ath5k_create_power_curve(table_min[pdg], + table_max[pdg], + pdg_R->pd_pwr, + pdg_R->pd_step, + pdg_R->pd_points, tmpR, type); + break; + default: + return -EINVAL; + } + + /* Interpolate between curves + * of surounding freq piers to + * get the final curve for this + * pd gain. Re-use tmpL for interpolation + * output */ + for (i = 0; (i < (u16) (table_max[pdg] - table_min[pdg])) && + (i < AR5K_EEPROM_POWER_TABLE_SIZE); i++) { + tmpL[i] = (u8) ath5k_get_interpolated_value(target, + (s16) pcinfo_L->freq, + (s16) pcinfo_R->freq, + (s16) tmpL[i], + (s16) tmpR[i]); + } } + /* Now we have a set of curves for this + * channel on tmpL (x range is table_max - table_min + * and y values are tmpL[pdg][]) sorted in the same + * order as EEPROM (because we've used the backmaping). + * So for RF5112 it's from higher power to lower power + * and for RF2413 it's from lower power to higher power. + * For RF5111 we only have one curve. */ + + /* Fill min and max power levels for this + * channel by interpolating the values on + * surounding channels to complete the dataset */ + ah->ah_txpower.txp_min_pwr = ath5k_get_interpolated_value(target, + (s16) pcinfo_L->freq, + (s16) pcinfo_R->freq, + pcinfo_L->min_pwr, pcinfo_R->min_pwr); + + ah->ah_txpower.txp_max_pwr = ath5k_get_interpolated_value(target, + (s16) pcinfo_L->freq, + (s16) pcinfo_R->freq, + pcinfo_L->max_pwr, pcinfo_R->max_pwr); + + /* We are ready to go, fill PCDAC/PDADC + * table and write settings on hardware */ + switch (type) { + case AR5K_PWRTABLE_LINEAR_PCDAC: + /* For RF5112 we can have one or two curves + * and each curve covers a certain power lvl + * range so we need to do some more processing */ + ath5k_combine_linear_pcdac_curves(ah, table_min, table_max, + ee->ee_pd_gains[ee_mode]); + + /* Set txp.offset so that we can + * match max power value with max + * table index */ + ah->ah_txpower.txp_offset = 64 - (table_max[0] / 2); + + /* Write settings on hw */ + ath5k_setup_pcdac_table(ah); + break; + case AR5K_PWRTABLE_PWR_TO_PCDAC: + /* We are done for RF5111 since it has only + * one curve, just fit the curve on the table */ + ath5k_fill_pwr_to_pcdac_table(ah, table_min, table_max); + + /* No rate powertable adjustment for RF5111 */ + ah->ah_txpower.txp_min_idx = 0; + ah->ah_txpower.txp_offset = 0; + + /* Write settings on hw */ + ath5k_setup_pcdac_table(ah); + break; + case AR5K_PWRTABLE_PWR_TO_PDADC: + /* Set PDADC boundaries and fill + * final PDADC table */ + ath5k_combine_pwr_to_pdadc_curves(ah, table_min, table_max, + ee->ee_pd_gains[ee_mode]); + + /* Write settings on hw */ + ath5k_setup_pwr_to_pdadc_table(ah, pdg, pdg_curve_to_idx); + + /* Set txp.offset, note that table_min + * can be negative */ + ah->ah_txpower.txp_offset = table_min[0]; + break; + default: + return -EINVAL; + } + + return 0; +} + + +/* + * Per-rate tx power setting + * + * This is the code that sets the desired tx power (below + * maximum) on hw for each rate (we also have TPC that sets + * power per packet). We do that by providing an index on the + * PCDAC/PDADC table we set up. + */ + +/* + * Set rate power table + * + * For now we only limit txpower based on maximum tx power + * supported by hw (what's inside rate_info). We need to limit + * this even more, based on regulatory domain etc. + * + * Rate power table contains indices to PCDAC/PDADC table (0.5dB steps) + * and is indexed as follows: + * rates[0] - rates[7] -> OFDM rates + * rates[8] - rates[14] -> CCK rates + * rates[15] -> XR rates (they all have the same power) + */ +static void +ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, + struct ath5k_rate_pcal_info *rate_info, + u8 ee_mode) +{ + unsigned int i; + u16 *rates; + + /* max_pwr is power level we got from driver/user in 0.5dB + * units, switch to 0.25dB units so we can compare */ + max_pwr *= 2; + max_pwr = min(max_pwr, (u16) ah->ah_txpower.txp_max_pwr) / 2; + + /* apply rate limits */ + rates = ah->ah_txpower.txp_rates_power_table; + + /* OFDM rates 6 to 24Mb/s */ + for (i = 0; i < 5; i++) + rates[i] = min(max_pwr, rate_info->target_power_6to24); + + /* Rest OFDM rates */ + rates[5] = min(rates[0], rate_info->target_power_36); + rates[6] = min(rates[0], rate_info->target_power_48); + rates[7] = min(rates[0], rate_info->target_power_54); + + /* CCK rates */ + /* 1L */ + rates[8] = min(rates[0], rate_info->target_power_6to24); + /* 2L */ + rates[9] = min(rates[0], rate_info->target_power_36); + /* 2S */ + rates[10] = min(rates[0], rate_info->target_power_36); + /* 5L */ + rates[11] = min(rates[0], rate_info->target_power_48); + /* 5S */ + rates[12] = min(rates[0], rate_info->target_power_48); + /* 11L */ + rates[13] = min(rates[0], rate_info->target_power_54); + /* 11S */ + rates[14] = min(rates[0], rate_info->target_power_54); + + /* XR rates */ + rates[15] = min(rates[0], rate_info->target_power_6to24); + + /* CCK rates have different peak to average ratio + * so we have to tweak their power so that gainf + * correction works ok. For this we use OFDM to + * CCK delta from eeprom */ + if ((ee_mode == AR5K_EEPROM_MODE_11G) && + (ah->ah_phy_revision < AR5K_SREV_PHY_5212A)) + for (i = 8; i <= 15; i++) + rates[i] -= ah->ah_txpower.txp_cck_ofdm_gainf_delta; + + ah->ah_txpower.txp_min_pwr = rates[7]; + ah->ah_txpower.txp_max_pwr = rates[0]; + ah->ah_txpower.txp_ofdm = rates[7]; +} + + +/* + * Set transmition power + */ +int +ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, + u8 ee_mode, u8 txpower) +{ + struct ath5k_rate_pcal_info rate_info; + u8 type; + int ret; + + ATH5K_TRACE(ah->ah_sc); + if (txpower > AR5K_TUNE_MAX_TXPOWER) { + ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower); + return -EINVAL; + } + if (txpower == 0) + txpower = AR5K_TUNE_DEFAULT_TXPOWER; + + /* Reset TX power values */ + memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); + ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; + ah->ah_txpower.txp_min_pwr = 0; + ah->ah_txpower.txp_max_pwr = AR5K_TUNE_MAX_TXPOWER; + + /* Initialize TX power table */ + switch (ah->ah_radio) { + case AR5K_RF5111: + type = AR5K_PWRTABLE_PWR_TO_PCDAC; + break; + case AR5K_RF5112: + type = AR5K_PWRTABLE_LINEAR_PCDAC; + break; + case AR5K_RF2413: + case AR5K_RF5413: + case AR5K_RF2316: + case AR5K_RF2317: + case AR5K_RF2425: + type = AR5K_PWRTABLE_PWR_TO_PDADC; + break; + default: + return -EINVAL; + } + + /* FIXME: Only on channel/mode change */ + ret = ath5k_setup_channel_powertable(ah, channel, ee_mode, type); + if (ret) + return ret; + + /* Limit max power if we have a CTL available */ + ath5k_get_max_ctl_power(ah, channel); + + /* FIXME: Tx power limit for this regdomain + * XXX: Mac80211/CRDA will do that anyway ? */ + + /* FIXME: Antenna reduction stuff */ + + /* FIXME: Limit power on turbo modes */ + + /* FIXME: TPC scale reduction */ + + /* Get surounding channels for per-rate power table + * calibration */ + ath5k_get_rate_pcal_data(ah, channel, &rate_info); + + /* Setup rate power table */ + ath5k_setup_rate_powertable(ah, txpower, &rate_info, ee_mode); + + /* Write rate power table on hw */ ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(3, 24) | AR5K_TXPOWER_OFDM(2, 16) | AR5K_TXPOWER_OFDM(1, 8) | AR5K_TXPOWER_OFDM(0, 0), AR5K_PHY_TXPOWER_RATE1); @@ -1536,26 +2566,34 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, AR5K_TXPOWER_CCK(13, 16) | AR5K_TXPOWER_CCK(12, 8) | AR5K_TXPOWER_CCK(11, 0), AR5K_PHY_TXPOWER_RATE4); - if (ah->ah_txpower.txp_tpc) + /* FIXME: TPC support */ + if (ah->ah_txpower.txp_tpc) { ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE | AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX); - else + + ath5k_hw_reg_write(ah, + AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_ACK) | + AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_CTS) | + AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_CHIRP), + AR5K_TPC); + } else { ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX | AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX); + } return 0; } -int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, unsigned int power) +int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 mode, u8 txpower) { /*Just a try M.F.*/ struct ieee80211_channel *channel = &ah->ah_current_channel; ATH5K_TRACE(ah->ah_sc); ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER, - "changing txpower to %d\n", power); + "changing txpower to %d\n", txpower); - return ath5k_hw_txpower(ah, channel, power); + return ath5k_hw_txpower(ah, channel, mode, txpower); } #undef _ATH5K_PHY diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h index 2dc008e1022..7070d1543cd 100644 --- a/drivers/net/wireless/ath5k/reg.h +++ b/drivers/net/wireless/ath5k/reg.h @@ -1553,6 +1553,19 @@ /*===5212 Specific PCU registers===*/ +/* + * Transmit power control register + */ +#define AR5K_TPC 0x80e8 +#define AR5K_TPC_ACK 0x0000003f /* ack frames */ +#define AR5K_TPC_ACK_S 0 +#define AR5K_TPC_CTS 0x00003f00 /* cts frames */ +#define AR5K_TPC_CTS_S 8 +#define AR5K_TPC_CHIRP 0x003f0000 /* chirp frames */ +#define AR5K_TPC_CHIRP_S 16 +#define AR5K_TPC_DOPPLER 0x0f000000 /* doppler chirp span */ +#define AR5K_TPC_DOPPLER_S 24 + /* * XR (eXtended Range) mode register */ @@ -2550,6 +2563,12 @@ #define AR5K_PHY_TPC_RG1 0xa258 #define AR5K_PHY_TPC_RG1_NUM_PD_GAIN 0x0000c000 #define AR5K_PHY_TPC_RG1_NUM_PD_GAIN_S 14 +#define AR5K_PHY_TPC_RG1_PDGAIN_1 0x00030000 +#define AR5K_PHY_TPC_RG1_PDGAIN_1_S 16 +#define AR5K_PHY_TPC_RG1_PDGAIN_2 0x000c0000 +#define AR5K_PHY_TPC_RG1_PDGAIN_2_S 18 +#define AR5K_PHY_TPC_RG1_PDGAIN_3 0x00300000 +#define AR5K_PHY_TPC_RG1_PDGAIN_3_S 20 #define AR5K_PHY_TPC_RG5 0xa26C #define AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP 0x0000000F diff --git a/drivers/net/wireless/ath5k/reset.c b/drivers/net/wireless/ath5k/reset.c index 685dc213eda..7a17d31b2fd 100644 --- a/drivers/net/wireless/ath5k/reset.c +++ b/drivers/net/wireless/ath5k/reset.c @@ -664,29 +664,35 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 *ant, u8 ee_mode) { struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + s16 cck_ofdm_pwr_delta; - /* Set CCK to OFDM power delta */ - if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) { - int16_t cck_ofdm_pwr_delta; - - /* Adjust power delta for channel 14 */ - if (channel->center_freq == 2484) - cck_ofdm_pwr_delta = - ((ee->ee_cck_ofdm_power_delta - - ee->ee_scaled_cck_delta) * 2) / 10; - else - cck_ofdm_pwr_delta = - (ee->ee_cck_ofdm_power_delta * 2) / 10; + /* Adjust power delta for channel 14 */ + if (channel->center_freq == 2484) + cck_ofdm_pwr_delta = + ((ee->ee_cck_ofdm_power_delta - + ee->ee_scaled_cck_delta) * 2) / 10; + else + cck_ofdm_pwr_delta = + (ee->ee_cck_ofdm_power_delta * 2) / 10; + /* Set CCK to OFDM power delta on tx power + * adjustment register */ + if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) { if (channel->hw_value == CHANNEL_G) ath5k_hw_reg_write(ah, - AR5K_REG_SM((ee->ee_cck_ofdm_power_delta * -1), + AR5K_REG_SM((ee->ee_cck_ofdm_gain_delta * -1), AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA) | AR5K_REG_SM((cck_ofdm_pwr_delta * -1), AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX), AR5K_PHY_TX_PWR_ADJ); else ath5k_hw_reg_write(ah, 0, AR5K_PHY_TX_PWR_ADJ); + } else { + /* For older revs we scale power on sw during tx power + * setup */ + ah->ah_txpower.txp_cck_ofdm_pwr_delta = cck_ofdm_pwr_delta; + ah->ah_txpower.txp_cck_ofdm_gainf_delta = + ee->ee_cck_ofdm_gain_delta; } /* Set antenna idle switch table */ @@ -994,7 +1000,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, /* * Set TX power (FIXME) */ - ret = ath5k_hw_txpower(ah, channel, AR5K_TUNE_DEFAULT_TXPOWER); + ret = ath5k_hw_txpower(ah, channel, ee_mode, + AR5K_TUNE_DEFAULT_TXPOWER); if (ret) return ret; -- GitLab From 3b85875a252dbbd95c2e04d73639719a0a79634e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 12 Mar 2009 09:55:09 +0100 Subject: [PATCH 4867/4982] nl80211: rework locking When I added scanning to cfg80211, we got a lock dependency like this: rtnl --> cfg80211_mtx nl80211, on the other hand, has the reverse lock dependency: cfg80211_mtx --> rtnl which clearly is a bad idea. This patch reworks nl80211 to take these two locks in the other order to fix the possible, and easily triggerable, deadlock. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 271 +++++++++++++++++++++++++---------------- 1 file changed, 166 insertions(+), 105 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 58ee1b1aff8..a3ecf8d7389 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -602,9 +602,12 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) memset(¶ms, 0, sizeof(params)); + rtnl_lock(); + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) - return err; + goto unlock_rtnl; + ifindex = dev->ifindex; type = dev->ieee80211_ptr->iftype; dev_put(dev); @@ -641,17 +644,17 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) if (!err) flags = &_flags; } - rtnl_lock(); + err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, type, flags, ¶ms); dev = __dev_get_by_index(&init_net, ifindex); WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type)); - rtnl_unlock(); - unlock: cfg80211_put_dev(drv); + unlock_rtnl: + rtnl_unlock(); return err; } @@ -674,9 +677,13 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) return -EINVAL; } + rtnl_lock(); + drv = cfg80211_get_dev_from_info(info); - if (IS_ERR(drv)) - return PTR_ERR(drv); + if (IS_ERR(drv)) { + err = PTR_ERR(drv); + goto unlock_rtnl; + } if (!drv->ops->add_virtual_intf || !(drv->wiphy.interface_modes & (1 << type))) { @@ -690,18 +697,17 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); } - rtnl_lock(); err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, &flags); err = drv->ops->add_virtual_intf(&drv->wiphy, nla_data(info->attrs[NL80211_ATTR_IFNAME]), type, err ? NULL : &flags, ¶ms); - rtnl_unlock(); - unlock: cfg80211_put_dev(drv); + unlock_rtnl: + rtnl_unlock(); return err; } @@ -711,9 +717,11 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) int ifindex, err; struct net_device *dev; + rtnl_lock(); + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) - return err; + goto unlock_rtnl; ifindex = dev->ifindex; dev_put(dev); @@ -722,12 +730,12 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) goto out; } - rtnl_lock(); err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex); - rtnl_unlock(); out: cfg80211_put_dev(drv); + unlock_rtnl: + rtnl_unlock(); return err; } @@ -779,9 +787,11 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NL80211_ATTR_MAC]) mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); + rtnl_lock(); + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) - return err; + goto unlock_rtnl; if (!drv->ops->get_key) { err = -EOPNOTSUPP; @@ -809,10 +819,8 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) if (mac_addr) NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); - rtnl_lock(); err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr, &cookie, get_key_callback); - rtnl_unlock(); if (err) goto out; @@ -830,6 +838,9 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) out: cfg80211_put_dev(drv); dev_put(dev); + unlock_rtnl: + rtnl_unlock(); + return err; } @@ -858,9 +869,11 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) !info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]) return -EINVAL; + rtnl_lock(); + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) - return err; + goto unlock_rtnl; if (info->attrs[NL80211_ATTR_KEY_DEFAULT]) func = drv->ops->set_default_key; @@ -872,13 +885,15 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) goto out; } - rtnl_lock(); err = func(&drv->wiphy, dev, key_idx); - rtnl_unlock(); out: cfg80211_put_dev(drv); dev_put(dev); + + unlock_rtnl: + rtnl_unlock(); + return err; } @@ -948,22 +963,25 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) return -EINVAL; } + rtnl_lock(); + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) - return err; + goto unlock_rtnl; if (!drv->ops->add_key) { err = -EOPNOTSUPP; goto out; } - rtnl_lock(); err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, ¶ms); - rtnl_unlock(); out: cfg80211_put_dev(drv); dev_put(dev); + unlock_rtnl: + rtnl_unlock(); + return err; } @@ -984,22 +1002,26 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NL80211_ATTR_MAC]) mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); + rtnl_lock(); + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) - return err; + goto unlock_rtnl; if (!drv->ops->del_key) { err = -EOPNOTSUPP; goto out; } - rtnl_lock(); err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr); - rtnl_unlock(); out: cfg80211_put_dev(drv); dev_put(dev); + + unlock_rtnl: + rtnl_unlock(); + return err; } @@ -1013,9 +1035,11 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) struct beacon_parameters params; int haveinfo = 0; + rtnl_lock(); + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) - return err; + goto unlock_rtnl; switch (info->genlhdr->cmd) { case NL80211_CMD_NEW_BEACON: @@ -1076,13 +1100,14 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) goto out; } - rtnl_lock(); err = call(&drv->wiphy, dev, ¶ms); - rtnl_unlock(); out: cfg80211_put_dev(drv); dev_put(dev); + unlock_rtnl: + rtnl_unlock(); + return err; } @@ -1092,22 +1117,25 @@ static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) int err; struct net_device *dev; + rtnl_lock(); + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) - return err; + goto unlock_rtnl; if (!drv->ops->del_beacon) { err = -EOPNOTSUPP; goto out; } - rtnl_lock(); err = drv->ops->del_beacon(&drv->wiphy, dev); - rtnl_unlock(); out: cfg80211_put_dev(drv); dev_put(dev); + unlock_rtnl: + rtnl_unlock(); + return err; } @@ -1273,14 +1301,18 @@ static int nl80211_dump_station(struct sk_buff *skb, return -EINVAL; } - netdev = dev_get_by_index(&init_net, ifidx); - if (!netdev) - return -ENODEV; + rtnl_lock(); + + netdev = __dev_get_by_index(&init_net, ifidx); + if (!netdev) { + err = -ENODEV; + goto out_rtnl; + } dev = cfg80211_get_dev_from_ifindex(ifidx); if (IS_ERR(dev)) { err = PTR_ERR(dev); - goto out_put_netdev; + goto out_rtnl; } if (!dev->ops->dump_station) { @@ -1288,15 +1320,13 @@ static int nl80211_dump_station(struct sk_buff *skb, goto out_err; } - rtnl_lock(); - while (1) { err = dev->ops->dump_station(&dev->wiphy, netdev, sta_idx, mac_addr, &sinfo); if (err == -ENOENT) break; if (err) - goto out_err_rtnl; + goto out_err; if (nl80211_send_station(skb, NETLINK_CB(cb->skb).pid, @@ -1312,12 +1342,10 @@ static int nl80211_dump_station(struct sk_buff *skb, out: cb->args[1] = sta_idx; err = skb->len; - out_err_rtnl: - rtnl_unlock(); out_err: cfg80211_put_dev(dev); - out_put_netdev: - dev_put(netdev); + out_rtnl: + rtnl_unlock(); return err; } @@ -1338,19 +1366,18 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); + rtnl_lock(); + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) - return err; + goto out_rtnl; if (!drv->ops->get_station) { err = -EOPNOTSUPP; goto out; } - rtnl_lock(); err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &sinfo); - rtnl_unlock(); - if (err) goto out; @@ -1367,10 +1394,12 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) out_free: nlmsg_free(msg); - out: cfg80211_put_dev(drv); dev_put(dev); + out_rtnl: + rtnl_unlock(); + return err; } @@ -1438,9 +1467,11 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) params.plink_action = nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); + rtnl_lock(); + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) - return err; + goto out_rtnl; err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); if (err) @@ -1451,15 +1482,16 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) goto out; } - rtnl_lock(); err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, ¶ms); - rtnl_unlock(); out: if (params.vlan) dev_put(params.vlan); cfg80211_put_dev(drv); dev_put(dev); + out_rtnl: + rtnl_unlock(); + return err; } @@ -1501,9 +1533,11 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) ¶ms.station_flags)) return -EINVAL; + rtnl_lock(); + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) - return err; + goto out_rtnl; err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); if (err) @@ -1514,15 +1548,16 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) goto out; } - rtnl_lock(); err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, ¶ms); - rtnl_unlock(); out: if (params.vlan) dev_put(params.vlan); cfg80211_put_dev(drv); dev_put(dev); + out_rtnl: + rtnl_unlock(); + return err; } @@ -1536,22 +1571,25 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NL80211_ATTR_MAC]) mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); + rtnl_lock(); + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) - return err; + goto out_rtnl; if (!drv->ops->del_station) { err = -EOPNOTSUPP; goto out; } - rtnl_lock(); err = drv->ops->del_station(&drv->wiphy, dev, mac_addr); - rtnl_unlock(); out: cfg80211_put_dev(drv); dev_put(dev); + out_rtnl: + rtnl_unlock(); + return err; } @@ -1632,14 +1670,18 @@ static int nl80211_dump_mpath(struct sk_buff *skb, return -EINVAL; } - netdev = dev_get_by_index(&init_net, ifidx); - if (!netdev) - return -ENODEV; + rtnl_lock(); + + netdev = __dev_get_by_index(&init_net, ifidx); + if (!netdev) { + err = -ENODEV; + goto out_rtnl; + } dev = cfg80211_get_dev_from_ifindex(ifidx); if (IS_ERR(dev)) { err = PTR_ERR(dev); - goto out_put_netdev; + goto out_rtnl; } if (!dev->ops->dump_mpath) { @@ -1647,15 +1689,13 @@ static int nl80211_dump_mpath(struct sk_buff *skb, goto out_err; } - rtnl_lock(); - while (1) { err = dev->ops->dump_mpath(&dev->wiphy, netdev, path_idx, dst, next_hop, &pinfo); if (err == -ENOENT) break; if (err) - goto out_err_rtnl; + goto out_err; if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, NLM_F_MULTI, @@ -1670,12 +1710,10 @@ static int nl80211_dump_mpath(struct sk_buff *skb, out: cb->args[1] = path_idx; err = skb->len; - out_err_rtnl: - rtnl_unlock(); out_err: cfg80211_put_dev(dev); - out_put_netdev: - dev_put(netdev); + out_rtnl: + rtnl_unlock(); return err; } @@ -1697,19 +1735,18 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info) dst = nla_data(info->attrs[NL80211_ATTR_MAC]); + rtnl_lock(); + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) - return err; + goto out_rtnl; if (!drv->ops->get_mpath) { err = -EOPNOTSUPP; goto out; } - rtnl_lock(); err = drv->ops->get_mpath(&drv->wiphy, dev, dst, next_hop, &pinfo); - rtnl_unlock(); - if (err) goto out; @@ -1726,10 +1763,12 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info) out_free: nlmsg_free(msg); - out: cfg80211_put_dev(drv); dev_put(dev); + out_rtnl: + rtnl_unlock(); + return err; } @@ -1750,22 +1789,25 @@ static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info) dst = nla_data(info->attrs[NL80211_ATTR_MAC]); next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); + rtnl_lock(); + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) - return err; + goto out_rtnl; if (!drv->ops->change_mpath) { err = -EOPNOTSUPP; goto out; } - rtnl_lock(); err = drv->ops->change_mpath(&drv->wiphy, dev, dst, next_hop); - rtnl_unlock(); out: cfg80211_put_dev(drv); dev_put(dev); + out_rtnl: + rtnl_unlock(); + return err; } static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info) @@ -1785,22 +1827,25 @@ static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info) dst = nla_data(info->attrs[NL80211_ATTR_MAC]); next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); + rtnl_lock(); + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) - return err; + goto out_rtnl; if (!drv->ops->add_mpath) { err = -EOPNOTSUPP; goto out; } - rtnl_lock(); err = drv->ops->add_mpath(&drv->wiphy, dev, dst, next_hop); - rtnl_unlock(); out: cfg80211_put_dev(drv); dev_put(dev); + out_rtnl: + rtnl_unlock(); + return err; } @@ -1814,22 +1859,25 @@ static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NL80211_ATTR_MAC]) dst = nla_data(info->attrs[NL80211_ATTR_MAC]); + rtnl_lock(); + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) - return err; + goto out_rtnl; if (!drv->ops->del_mpath) { err = -EOPNOTSUPP; goto out; } - rtnl_lock(); err = drv->ops->del_mpath(&drv->wiphy, dev, dst); - rtnl_unlock(); out: cfg80211_put_dev(drv); dev_put(dev); + out_rtnl: + rtnl_unlock(); + return err; } @@ -1862,22 +1910,25 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); } + rtnl_lock(); + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) - return err; + goto out_rtnl; if (!drv->ops->change_bss) { err = -EOPNOTSUPP; goto out; } - rtnl_lock(); err = drv->ops->change_bss(&drv->wiphy, dev, ¶ms); - rtnl_unlock(); out: cfg80211_put_dev(drv); dev_put(dev); + out_rtnl: + rtnl_unlock(); + return err; } @@ -1972,10 +2023,12 @@ static int nl80211_get_mesh_params(struct sk_buff *skb, struct nlattr *pinfoattr; struct sk_buff *msg; + rtnl_lock(); + /* Look up our device */ err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) - return err; + goto out_rtnl; if (!drv->ops->get_mesh_params) { err = -EOPNOTSUPP; @@ -1983,9 +2036,7 @@ static int nl80211_get_mesh_params(struct sk_buff *skb, } /* Get the mesh params */ - rtnl_lock(); err = drv->ops->get_mesh_params(&drv->wiphy, dev, &cur_params); - rtnl_unlock(); if (err) goto out; @@ -2034,13 +2085,16 @@ static int nl80211_get_mesh_params(struct sk_buff *skb, err = genlmsg_unicast(msg, info->snd_pid); goto out; -nla_put_failure: + nla_put_failure: genlmsg_cancel(msg, hdr); err = -EMSGSIZE; -out: + out: /* Cleanup */ cfg80211_put_dev(drv); dev_put(dev); + out_rtnl: + rtnl_unlock(); + return err; } @@ -2087,9 +2141,11 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info) parent_attr, nl80211_meshconf_params_policy)) return -EINVAL; + rtnl_lock(); + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) - return err; + goto out_rtnl; if (!drv->ops->set_mesh_params) { err = -EOPNOTSUPP; @@ -2136,14 +2192,15 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info) nla_get_u16); /* Apply changes */ - rtnl_lock(); err = drv->ops->set_mesh_params(&drv->wiphy, dev, &cfg, mask); - rtnl_unlock(); out: /* cleanup */ cfg80211_put_dev(drv); dev_put(dev); + out_rtnl: + rtnl_unlock(); + return err; } @@ -2310,19 +2367,22 @@ static int nl80211_set_mgmt_extra_ie(struct sk_buff *skb, params.ies_len = nla_len(info->attrs[NL80211_ATTR_IE]); } + rtnl_lock(); + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) - return err; + goto out_rtnl; - if (drv->ops->set_mgmt_extra_ie) { - rtnl_lock(); + if (drv->ops->set_mgmt_extra_ie) err = drv->ops->set_mgmt_extra_ie(&drv->wiphy, dev, ¶ms); - rtnl_unlock(); - } else + else err = -EOPNOTSUPP; cfg80211_put_dev(drv); dev_put(dev); + out_rtnl: + rtnl_unlock(); + return err; } @@ -2339,9 +2399,11 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) enum ieee80211_band band; size_t ie_len; + rtnl_lock(); + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) - return err; + goto out_rtnl; wiphy = &drv->wiphy; @@ -2350,11 +2412,9 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) goto out; } - rtnl_lock(); - if (drv->scan_req) { err = -EBUSY; - goto out_unlock; + goto out; } if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { @@ -2362,7 +2422,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) n_channels++; if (!n_channels) { err = -EINVAL; - goto out_unlock; + goto out; } } else { for (band = 0; band < IEEE80211_NUM_BANDS; band++) @@ -2376,7 +2436,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) if (n_ssids > wiphy->max_scan_ssids) { err = -EINVAL; - goto out_unlock; + goto out; } if (info->attrs[NL80211_ATTR_IE]) @@ -2390,7 +2450,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) + ie_len, GFP_KERNEL); if (!request) { err = -ENOMEM; - goto out_unlock; + goto out; } request->channels = (void *)((char *)request + sizeof(*request)); @@ -2461,11 +2521,12 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) drv->scan_req = NULL; kfree(request); } - out_unlock: - rtnl_unlock(); out: cfg80211_put_dev(drv); dev_put(dev); + out_rtnl: + rtnl_unlock(); + return err; } -- GitLab From 019fb97d47896c0ead4a77f55e5350c2750f675f Mon Sep 17 00:00:00 2001 From: Mohamed Abbas Date: Tue, 17 Mar 2009 21:59:18 -0700 Subject: [PATCH 4868/4982] iwlagn: use changed in mac_config In function iwl_mac_config use changed flag to call only the affected functions. This patch also allow user to cache channel, txpower and power value when the interface is not ready and apply the changes once the interface ready. Signed-off-by: Mohamed Abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 161 ++++++++++++------------ drivers/net/wireless/iwlwifi/iwl-core.c | 4 + 2 files changed, 85 insertions(+), 80 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 0db3bc011ac..4d2ed52af16 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1567,9 +1567,8 @@ static void iwl_alive_start(struct iwl_priv *priv) if (iwl_is_associated(priv)) { struct iwl_rxon_cmd *active_rxon = (struct iwl_rxon_cmd *)&priv->active_rxon; - - memcpy(&priv->staging_rxon, &priv->active_rxon, - sizeof(priv->staging_rxon)); + /* apply any changes in staging */ + priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; } else { /* Initialize our rx_config data */ @@ -2184,110 +2183,112 @@ static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) struct iwl_priv *priv = hw->priv; const struct iwl_channel_info *ch_info; struct ieee80211_conf *conf = &hw->conf; - unsigned long flags; + unsigned long flags = 0; int ret = 0; - u16 channel; + u16 ch; + int scan_active = 0; mutex_lock(&priv->mutex); - IWL_DEBUG_MAC80211(priv, "enter to channel %d\n", conf->channel->hw_value); - - priv->current_ht_config.is_ht = conf_is_ht(conf); + IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n", + conf->channel->hw_value, changed); - if (conf->radio_enabled && iwl_radio_kill_sw_enable_radio(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF-KILL - waiting for uCode\n"); - goto out; + if (unlikely(!priv->cfg->mod_params->disable_hw_scan && + test_bit(STATUS_SCANNING, &priv->status))) { + scan_active = 1; + IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); } - if (!conf->radio_enabled) - iwl_radio_kill_sw_disable_radio(priv); - if (!iwl_is_ready(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); - ret = -EIO; - goto out; - } + /* during scanning mac80211 will delay channel setting until + * scan finish with changed = 0 + */ + if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) { + if (scan_active) + goto set_ch_out; + + ch = ieee80211_frequency_to_channel(conf->channel->center_freq); + ch_info = iwl_get_channel_info(priv, conf->channel->band, ch); + if (!is_channel_valid(ch_info)) { + IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); + ret = -EINVAL; + goto set_ch_out; + } - if (unlikely(!priv->cfg->mod_params->disable_hw_scan && - test_bit(STATUS_SCANNING, &priv->status))) { - IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); - mutex_unlock(&priv->mutex); - return 0; - } + if (priv->iw_mode == NL80211_IFTYPE_ADHOC && + !is_channel_ibss(ch_info)) { + IWL_ERR(priv, "channel %d in band %d not " + "IBSS channel\n", + conf->channel->hw_value, conf->channel->band); + ret = -EINVAL; + goto set_ch_out; + } - channel = ieee80211_frequency_to_channel(conf->channel->center_freq); - ch_info = iwl_get_channel_info(priv, conf->channel->band, channel); - if (!is_channel_valid(ch_info)) { - IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); - ret = -EINVAL; - goto out; - } + priv->current_ht_config.is_ht = conf_is_ht(conf); - if (priv->iw_mode == NL80211_IFTYPE_ADHOC && - !is_channel_ibss(ch_info)) { - IWL_ERR(priv, "channel %d in band %d not IBSS channel\n", - conf->channel->hw_value, conf->channel->band); - ret = -EINVAL; - goto out; - } + spin_lock_irqsave(&priv->lock, flags); - spin_lock_irqsave(&priv->lock, flags); + /* if we are switching from ht to 2.4 clear flags + * from any ht related info since 2.4 does not + * support ht */ + if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) + priv->staging_rxon.flags = 0; - /* if we are switching from ht to 2.4 clear flags - * from any ht related info since 2.4 does not - * support ht */ - if ((le16_to_cpu(priv->staging_rxon.channel) != channel) -#ifdef IEEE80211_CONF_CHANNEL_SWITCH - && !(conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) -#endif - ) - priv->staging_rxon.flags = 0; + iwl_set_rxon_channel(priv, conf->channel); + + iwl_set_flags_for_band(priv, conf->channel->band); + spin_unlock_irqrestore(&priv->lock, flags); + set_ch_out: + /* The list of supported rates and rate mask can be different + * for each band; since the band may have changed, reset + * the rate mask to what mac80211 lists */ + iwl_set_rate(priv); + } - iwl_set_rxon_channel(priv, conf->channel); + if (changed & IEEE80211_CONF_CHANGE_PS) { + if (conf->flags & IEEE80211_CONF_PS) + ret = iwl_power_set_user_mode(priv, IWL_POWER_INDEX_3); + else + ret = iwl_power_set_user_mode(priv, IWL_POWER_MODE_CAM); + if (ret) + IWL_DEBUG_MAC80211(priv, "Error setting power level\n"); - iwl_set_flags_for_band(priv, conf->channel->band); + } - /* The list of supported rates and rate mask can be different - * for each band; since the band may have changed, reset - * the rate mask to what mac80211 lists */ - iwl_set_rate(priv); + if (changed & IEEE80211_CONF_CHANGE_POWER) { + IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n", + priv->tx_power_user_lmt, conf->power_level); - spin_unlock_irqrestore(&priv->lock, flags); + iwl_set_tx_power(priv, conf->power_level, false); + } -#ifdef IEEE80211_CONF_CHANNEL_SWITCH - if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) { - iwl_hw_channel_switch(priv, conf->channel); - goto out; + /* call to ensure that 4965 rx_chain is set properly in monitor mode */ + iwl_set_rxon_chain(priv); + + if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) { + if (conf->radio_enabled && + iwl_radio_kill_sw_enable_radio(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - RF-KILL - " + "waiting for uCode\n"); + goto out; + } + + if (!conf->radio_enabled) + iwl_radio_kill_sw_disable_radio(priv); } -#endif if (!conf->radio_enabled) { IWL_DEBUG_MAC80211(priv, "leave - radio disabled\n"); goto out; } - if (iwl_is_rfkill(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF kill\n"); - ret = -EIO; + if (!iwl_is_ready(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); goto out; } - if (conf->flags & IEEE80211_CONF_PS) - ret = iwl_power_set_user_mode(priv, IWL_POWER_INDEX_3); - else - ret = iwl_power_set_user_mode(priv, IWL_POWER_MODE_CAM); - if (ret) - IWL_DEBUG_MAC80211(priv, "Error setting power level\n"); - - IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n", - priv->tx_power_user_lmt, conf->power_level); - - iwl_set_tx_power(priv, conf->power_level, false); - - iwl_set_rate(priv); - - /* call to ensure that 4965 rx_chain is set properly in monitor mode */ - iwl_set_rxon_chain(priv); + if (scan_active) + goto out; if (memcmp(&priv->active_rxon, &priv->staging_rxon, sizeof(priv->staging_rxon))) @@ -2295,9 +2296,9 @@ static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) else IWL_DEBUG_INFO(priv, "No re-sending same RXON configuration.\n"); - IWL_DEBUG_MAC80211(priv, "leave\n"); out: + IWL_DEBUG_MAC80211(priv, "leave\n"); mutex_unlock(&priv->mutex); return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 085e9cf1cac..bcdecb11080 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1437,6 +1437,10 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) priv->tx_power_user_lmt = tx_power; + /* if nic is not up don't send command */ + if (!iwl_is_ready_rf(priv)) + return ret; + if (force && priv->cfg->ops->lib->send_tx_power) ret = priv->cfg->ops->lib->send_tx_power(priv); -- GitLab From 37fec3846a5a8b098e35c44ee858407bab0df43f Mon Sep 17 00:00:00 2001 From: Mohamed Abbas Date: Tue, 17 Mar 2009 21:51:42 -0700 Subject: [PATCH 4869/4982] iwl3945: use changed in iwl3945_mac_config In function iwl3945_mac_config use changed flag to call only the affected functions. Signed-off-by: Mohamed Abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 4465320f273..16ecf03a155 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3773,15 +3773,19 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed) } #endif - if (conf->radio_enabled && iwl_radio_kill_sw_enable_radio(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF-KILL - waiting for uCode\n"); - goto out; - } + if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) { + if (conf->radio_enabled && + iwl_radio_kill_sw_enable_radio(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - RF-KILL - " + "waiting for uCode\n"); + goto out; + } - if (!conf->radio_enabled) { - iwl_radio_kill_sw_disable_radio(priv); - IWL_DEBUG_MAC80211(priv, "leave - radio disabled\n"); - goto out; + if (!conf->radio_enabled) { + iwl_radio_kill_sw_disable_radio(priv); + IWL_DEBUG_MAC80211(priv, "leave - radio disabled\n"); + goto out; + } } if (iwl_is_rfkill(priv)) { -- GitLab From 5c2207c64209be2fe0d6b43ada2e41b28a948015 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 17 Mar 2009 21:51:43 -0700 Subject: [PATCH 4870/4982] iwlwifi: return 0 for AMPDU_TX/RX_STOP request if NIC is going down When receive IEEE80211_AMPDU_RX_STOP or IEEE80211_AMPDU_TX_STOP request in iwl_mac_ampdu_action() from mac80211; check STATUS_EXIT_PENDING bit, if NIC is on the way out, then return 0 back to mac80211, this can prevent mac80211 report HW error incorrectly. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 4d2ed52af16..c1482852ea4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2683,6 +2683,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u16 tid, u16 *ssn) { struct iwl_priv *priv = hw->priv; + int ret; IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", sta->addr, tid); @@ -2696,13 +2697,21 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, return iwl_sta_rx_agg_start(priv, sta->addr, tid, *ssn); case IEEE80211_AMPDU_RX_STOP: IWL_DEBUG_HT(priv, "stop Rx\n"); - return iwl_sta_rx_agg_stop(priv, sta->addr, tid); + ret = iwl_sta_rx_agg_stop(priv, sta->addr, tid); + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return 0; + else + return ret; case IEEE80211_AMPDU_TX_START: IWL_DEBUG_HT(priv, "start Tx\n"); return iwl_tx_agg_start(priv, sta->addr, tid, ssn); case IEEE80211_AMPDU_TX_STOP: IWL_DEBUG_HT(priv, "stop Tx\n"); - return iwl_tx_agg_stop(priv, sta->addr, tid); + ret = iwl_tx_agg_stop(priv, sta->addr, tid); + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return 0; + else + return ret; default: IWL_DEBUG_HT(priv, "unknown\n"); return -EINVAL; -- GitLab From 4f01ac01539d83709d6ae314fc172da7b7e70456 Mon Sep 17 00:00:00 2001 From: Mohamed Abbas Date: Tue, 17 Mar 2009 21:51:44 -0700 Subject: [PATCH 4871/4982] iwlagn: allow power level setting all the times allow user to set power level at all times Signed-off-by: Mohamed Abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 5 ----- drivers/net/wireless/iwlwifi/iwl3945-base.c | 5 ----- 2 files changed, 10 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c1482852ea4..663dc83be50 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3093,11 +3093,6 @@ static ssize_t store_power_level(struct device *d, mutex_lock(&priv->mutex); - if (!iwl_is_ready(priv)) { - ret = -EAGAIN; - goto out; - } - ret = strict_strtoul(buf, 10, &mode); if (ret) goto out; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 16ecf03a155..bd59ed4dae2 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4550,11 +4550,6 @@ static ssize_t store_power_level(struct device *d, mutex_lock(&priv->mutex); - if (!iwl_is_ready(priv)) { - ret = -EAGAIN; - goto out; - } - ret = strict_strtoul(buf, 10, &mode); if (ret) goto out; -- GitLab From 28c608750f5f72e3c4139f7a51358eccd58c80a9 Mon Sep 17 00:00:00 2001 From: Mohamed Abbas Date: Tue, 17 Mar 2009 21:51:45 -0700 Subject: [PATCH 4872/4982] iwlcore: dont commit power command if interface is not up If user set new power level, accept the new power level and only send command to host if the interface is up and radio on. Signed-off-by: Mohamed Abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-power.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 18b7e4195ea..47c894530eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -273,7 +273,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) if (priv->iw_mode != NL80211_IFTYPE_STATION) final_mode = IWL_POWER_MODE_CAM; - if (!iwl_is_rfkill(priv) && !setting->power_disabled && + if (iwl_is_ready_rf(priv) && !setting->power_disabled && ((setting->power_mode != final_mode) || force)) { struct iwl_powertable_cmd cmd; -- GitLab From b1c6019bc0fe829309258d888f47d9ae54353039 Mon Sep 17 00:00:00 2001 From: Mohamed Abbas Date: Tue, 17 Mar 2009 21:51:47 -0700 Subject: [PATCH 4873/4982] iwlwifi: support 11h Set IEEE80211_HW_SPECTRUM_MGMT bit in hw->flags, this tell mac80211 we support spectrum mgmt. Signed-off-by: Mohamed Abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 1 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index bcdecb11080..4b1298c2b0d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1298,6 +1298,7 @@ int iwl_setup_mac(struct iwl_priv *priv) hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM | IEEE80211_HW_AMPDU_AGGREGATION | + IEEE80211_HW_SPECTRUM_MGMT | IEEE80211_HW_SUPPORTS_PS; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index bd59ed4dae2..ec446451d9e 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4904,7 +4904,8 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) /* Tell mac80211 our characteristics */ hw->flags = IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM; + IEEE80211_HW_NOISE_DBM | + IEEE80211_HW_SPECTRUM_MGMT; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | -- GitLab From 21c02a1ab2d4b4a439461140e1ac355db32c3f2b Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Tue, 17 Mar 2009 21:51:48 -0700 Subject: [PATCH 4874/4982] iwl3945: set TFD_QUEUE_MAX to correct value Total number of queues is 8 but only 7 of them are TX queues. 4 AC(Data) queue ,1 CMD and 2 HCCA. The HCCA queues are not used. max_txq_num is set to maximum usable TX queues. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 205603d082a..73f93a0ff2d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -233,7 +233,7 @@ struct iwl3945_eeprom { #define PCI_CFG_REV_ID_BIT_RTP (0x80) /* bit 7 */ #define TFD_QUEUE_MIN 0 -#define TFD_QUEUE_MAX 6 +#define TFD_QUEUE_MAX 5 /* 4 DATA + 1 CMD */ #define IWL_NUM_SCAN_RATES (2) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index ba7e720e73c..99bb48e0336 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1046,7 +1046,7 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv) goto error; /* Tx queue(s) */ - for (txq_id = 0; txq_id < TFD_QUEUE_MAX; txq_id++) { + for (txq_id = 0; txq_id <= priv->hw_params.max_txq_num; txq_id++) { slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; rc = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, @@ -1239,7 +1239,7 @@ void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv) int txq_id; /* Tx queues */ - for (txq_id = 0; txq_id < TFD_QUEUE_MAX; txq_id++) + for (txq_id = 0; txq_id <= priv->hw_params.max_txq_num; txq_id++) iwl_tx_queue_free(priv, txq_id); } @@ -1259,7 +1259,7 @@ void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) iwl_write_prph(priv, ALM_SCD_MODE_REG, 0); /* reset TFD queues */ - for (txq_id = 0; txq_id < TFD_QUEUE_MAX; txq_id++) { + for (txq_id = 0; txq_id <= priv->hw_params.max_txq_num; txq_id++) { iwl_write_direct32(priv, FH39_TCSR_CONFIG(txq_id), 0x0); iwl_poll_direct_bit(priv, FH39_TSSR_TX_STATUS, FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id), @@ -2488,6 +2488,9 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) return -ENOMEM; } + /* Assign number of Usable TX queues */ + priv->hw_params.max_txq_num = TFD_QUEUE_MAX; + priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd); priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_3K; priv->hw_params.max_pkt_size = 2342; -- GitLab From 3e5d238fa75783e1080e7413c7e36dd5203950eb Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Tue, 17 Mar 2009 21:51:49 -0700 Subject: [PATCH 4875/4982] iwl3945: use iwl_cmd_queue_free iwl_cmd_queue_free needs to be used to free up the cmd_queue, as TFD slots for cmd_queue and tx_queue are different. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 11 +++++------ drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl-tx.c | 6 ++++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 99bb48e0336..50c61ed2352 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -747,11 +747,6 @@ void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) int i; int counter; - /* classify bd */ - if (txq->q.id == IWL_CMD_QUEUE_NUM) - /* nothing to cleanup after for host commands */ - return; - /* sanity check */ counter = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags)); if (counter > NUM_TFD_CHUNKS) { @@ -1240,7 +1235,11 @@ void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv) /* Tx queues */ for (txq_id = 0; txq_id <= priv->hw_params.max_txq_num; txq_id++) - iwl_tx_queue_free(priv, txq_id); + if (txq_id == IWL_CMD_QUEUE_NUM) + iwl_cmd_queue_free(priv); + else + iwl_tx_queue_free(priv, txq_id); + } void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 27310fec2e4..a8eac8c3c1f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -264,6 +264,7 @@ void iwl_rx_reply_error(struct iwl_priv *priv, * RX ******************************************************/ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq); +void iwl_cmd_queue_free(struct iwl_priv *priv); int iwl_rx_queue_alloc(struct iwl_priv *priv); void iwl_rx_handle(struct iwl_priv *priv); int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index dff60fb7021..9e83ee24ea8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -174,7 +174,7 @@ EXPORT_SYMBOL(iwl_tx_queue_free); * Free all buffers. * 0-fill, but do not free "txq" descriptor structure. */ -static void iwl_cmd_queue_free(struct iwl_priv *priv) +void iwl_cmd_queue_free(struct iwl_priv *priv) { struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; struct iwl_queue *q = &txq->q; @@ -193,12 +193,14 @@ static void iwl_cmd_queue_free(struct iwl_priv *priv) /* De-alloc circular buffer of TFDs */ if (txq->q.n_bd) - pci_free_consistent(dev, sizeof(struct iwl_tfd) * + pci_free_consistent(dev, priv->hw_params.tfd_size * txq->q.n_bd, txq->tfds, txq->q.dma_addr); /* 0-fill queue descriptor structure */ memset(txq, 0, sizeof(*txq)); } +EXPORT_SYMBOL(iwl_cmd_queue_free); + /*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** * DMA services * -- GitLab From 1e680233e7edfd081ebf9ec54e118547d5de7a8c Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Tue, 17 Mar 2009 21:51:50 -0700 Subject: [PATCH 4876/4982] iwl3945: fix checkpatch.pl errors Patch fixes two checkpatch.pl errors. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 50c61ed2352..d03f5534afe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1179,7 +1179,7 @@ int iwl3945_hw_nic_init(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id); rc = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); - if(rc) + if (rc) return rc; priv->cfg->ops->lib->apm_ops.config(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index ec446451d9e..d61f9a0701e 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -560,7 +560,7 @@ static int iwl3945_set_dynamic_key(struct iwl_priv *priv, ret = iwl3945_set_wep_dynamic_key_info(priv, keyconf, sta_id); break; default: - IWL_ERR(priv,"Unknown alg: %s alg = %d\n", __func__, keyconf->alg); + IWL_ERR(priv, "Unknown alg: %s alg = %d\n", __func__, keyconf->alg); ret = -EINVAL; } -- GitLab From 82127493a656f6293ffb1566410b5753f29991ef Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Tue, 17 Mar 2009 21:51:51 -0700 Subject: [PATCH 4877/4982] iwl3945: control rate decrease Control the rate decrease. Do not decrease the rate fast. Use success_ratio for rate scaling :) Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index f65c308a671..af6b9d44477 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -124,7 +124,7 @@ static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = { #define IWL39_RATE_HIGH_TH 11520 #define IWL_SUCCESS_UP_TH 8960 #define IWL_SUCCESS_DOWN_TH 10880 -#define IWL_RATE_MIN_FAILURE_TH 8 +#define IWL_RATE_MIN_FAILURE_TH 6 #define IWL_RATE_MIN_SUCCESS_TH 8 #define IWL_RATE_DECREASE_TH 1920 #define IWL_RATE_RETRY_TH 15 @@ -488,7 +488,7 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband IWL_DEBUG_RATE(priv, "enter\n"); - retries = info->status.rates[0].count - 1; + retries = info->status.rates[0].count; /* Sanity Check for retries */ if (retries > IWL_RATE_RETRY_TH) retries = IWL_RATE_RETRY_TH; @@ -791,16 +791,15 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) { IWL_DEBUG_RATE(priv, "decrease rate because of low success_ratio\n"); scale_action = -1; - /* No throughput measured yet for adjacent rates, * try increase */ } else if ((low_tpt == IWL_INVALID_VALUE) && (high_tpt == IWL_INVALID_VALUE)) { - if (high != IWL_RATE_INVALID && window->success_counter >= IWL_RATE_INCREASE_TH) + if (high != IWL_RATE_INVALID && window->success_ratio >= IWL_RATE_INCREASE_TH) scale_action = 1; else if (low != IWL_RATE_INVALID) - scale_action = -1; + scale_action = 0; /* Both adjacent throughputs are measured, but neither one has * better throughput; we're using the best rate, don't change @@ -826,14 +825,14 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, else { IWL_DEBUG_RATE(priv, "decrease rate because of high tpt\n"); - scale_action = -1; + scale_action = 0; } } else if (low_tpt != IWL_INVALID_VALUE) { if (low_tpt > current_tpt) { IWL_DEBUG_RATE(priv, "decrease rate because of low tpt\n"); scale_action = -1; - } else if (window->success_counter >= IWL_RATE_INCREASE_TH) { + } else if (window->success_ratio >= IWL_RATE_INCREASE_TH) { /* Lower rate has better * throughput,decrease rate */ scale_action = 1; -- GitLab From a2f1cbebdccc866d6c7da9eb655d35b5c60d33a0 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 17 Mar 2009 21:51:52 -0700 Subject: [PATCH 4878/4982] iwlwifi: report error when detect failure during stop agg queue This fix related to bug 1921 at http://www.intellinuxwireless.org/bugzilla/show_bug.cgi?id=1921 when detect error during stopping tx aggregation queue, report the error to help identify the problem. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-5000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 4 +++- drivers/net/wireless/iwlwifi/iwl-tx.c | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 08c19bea71e..a3d9a95a9b3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1077,7 +1077,7 @@ static int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || (IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) { - IWL_WARN(priv, + IWL_ERR(priv, "queue number out of range: %d, must be %d to %d\n", txq_id, IWL50_FIRST_AMPDU_QUEUE, IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES - 1); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 1684490d93c..5798fe49c77 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -1138,8 +1138,10 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid) int sta_id; sta_id = iwl_find_station(priv, addr); - if (sta_id == IWL_INVALID_STATION) + if (sta_id == IWL_INVALID_STATION) { + IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); return -ENXIO; + } spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].sta.station_flags_msk = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 9e83ee24ea8..b13862a598e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -1223,8 +1223,10 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) sta_id = iwl_find_station(priv, ra); - if (sta_id == IWL_INVALID_STATION) + if (sta_id == IWL_INVALID_STATION) { + IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); return -ENXIO; + } if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON) IWL_WARN(priv, "Stopping AGG while state not IWL_AGG_ON\n"); -- GitLab From 43da9192326a4499b5faf737c3636f25b56b53e0 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Tue, 17 Mar 2009 21:51:53 -0700 Subject: [PATCH 4879/4982] iwl3945: replace stations with stations_39 A *leftover* stations is replaced with stations_39. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index d61f9a0701e..ede29b6c4dc 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -485,14 +485,14 @@ static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv, memcpy(priv->stations_39[sta_id].sta.key.key, keyconf->key, keyconf->keylen); - if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) + if ((priv->stations_39[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) == STA_KEY_FLG_NO_ENC) - priv->stations[sta_id].sta.key.key_offset = + priv->stations_39[sta_id].sta.key.key_offset = iwl_get_free_ucode_key_index(priv); /* else, we are overriding an existing key => no need to allocated room * in uCode. */ - WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, + WARN(priv->stations_39[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, "no space for a new key"); priv->stations_39[sta_id].sta.key.key_flags = key_flags; -- GitLab From a9a6ffffd05f97e6acbdeafc595e269855829751 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 18 Mar 2009 14:06:44 +0200 Subject: [PATCH 4880/4982] mac80211: don't drop nullfunc frames during software scan ieee80211_tx_h_check_assoc() was dropping everything else than probe requests during software scan. So the nullfunc frame with the power save bit was dropped and AP never received it. This meant that AP never buffered any frames for the station during software scan. Fix this by allowing to transmit both probe request and nullfunc frames during software scan. Tested with stlc45xx. Signed-off-by: Kalle Valo Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/scan.c | 13 +++++++++++++ net/mac80211/tx.c | 14 +++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 5030a3c8750..46f35dc6acc 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -409,6 +409,19 @@ int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, return 0; } + /* + * Hardware/driver doesn't support hw_scan, so use software + * scanning instead. First send a nullfunc frame with power save + * bit on so that AP will buffer the frames for us while we are not + * listening, then send probe requests to each channel and wait for + * the responses. After all channels are scanned, tune back to the + * original channel and send a nullfunc frame with power save bit + * off to trigger the AP to send us all the buffered frames. + * + * Note that while local->sw_scanning is true everything else but + * nullfunc frames and probe requests will be dropped in + * ieee80211_tx_h_check_assoc(). + */ local->sw_scanning = true; if (local->ops->sw_scan_start) local->ops->sw_scan_start(local_to_hw(local)); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 038460b0a48..f3f240c6901 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -193,7 +193,19 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) return TX_CONTINUE; if (unlikely(tx->local->sw_scanning) && - !ieee80211_is_probe_req(hdr->frame_control)) + !ieee80211_is_probe_req(hdr->frame_control) && + !ieee80211_is_nullfunc(hdr->frame_control)) + /* + * When software scanning only nullfunc frames (to notify + * the sleep state to the AP) and probe requests (for the + * active scan) are allowed, all other frames should not be + * sent and we should not get here, but if we do + * nonetheless, drop them to avoid sending them + * off-channel. See the link below and + * ieee80211_start_scan() for more. + * + * http://article.gmane.org/gmane.linux.kernel.wireless.general/30089 + */ return TX_DROP; if (tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT) -- GitLab From b3a902850a8f5bc11a660051faae707f928d4bd6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 18 Mar 2009 14:29:38 +0100 Subject: [PATCH 4881/4982] mac80211: kill IEEE80211_CONF_SHORT_SLOT_TIME No drivers use it any more, so it can now be removed safely. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index a38a82c785d..daa539a4287 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -520,12 +520,6 @@ enum ieee80211_conf_flags { IEEE80211_CONF_PS = (1<<1), }; -/* XXX: remove all this once drivers stop trying to use it */ -static inline int __deprecated __IEEE80211_CONF_SHORT_SLOT_TIME(void) -{ - return 0; -} -#define IEEE80211_CONF_SHORT_SLOT_TIME (__IEEE80211_CONF_SHORT_SLOT_TIME()) /** * enum ieee80211_conf_changed - denotes which configuration changed -- GitLab From 0934af2340caf3c9f247ae650bf0c6faa4203dba Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Wed, 18 Mar 2009 20:22:00 +0530 Subject: [PATCH 4882/4982] ath9k: Fix rate control update for aggregated frames We will miss rate control update if first A-MPDU of an aggregation is not Block Acked as we always tell if the rate control needs to updated through update_rc of first A-MPDU. This patch does rate control update for the first A-MPDU which notifies it's tx status (which is not necessarily the first A-MPDU of an aggregation) to mac80211. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/xmit.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 8968abe7f48..f2877193e95 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -64,6 +64,10 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, struct list_head *head); static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf); +static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, + int txok); +static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, + int nbad, int txok); /*********************/ /* Aggregation logic */ @@ -274,9 +278,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; struct ath_desc *ds = bf_last->bf_desc; struct list_head bf_head, bf_pending; - u16 seq_st = 0; + u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0; u32 ba[WME_BA_BMP_SIZE >> 5]; - int isaggr, txfail, txpending, sendbar = 0, needreset = 0; + int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; + bool rc_update = true; skb = (struct sk_buff *)bf->bf_mpdu; hdr = (struct ieee80211_hdr *)skb->data; @@ -316,6 +321,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, INIT_LIST_HEAD(&bf_pending); INIT_LIST_HEAD(&bf_head); + nbad = ath_tx_num_badfrms(sc, bf, txok); while (bf) { txfail = txpending = 0; bf_next = bf->bf_next; @@ -323,8 +329,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) { /* transmit completion, subframe is * acked by block ack */ + acked_cnt++; } else if (!isaggr && txok) { /* transmit completion */ + acked_cnt++; } else { if (!(tid->state & AGGR_CLEANUP) && ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) { @@ -335,6 +343,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, bf->bf_state.bf_type |= BUF_XRETRY; txfail = 1; sendbar = 1; + txfail_cnt++; } } else { /* @@ -361,6 +370,11 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, ath_tx_update_baw(sc, tid, bf->bf_seqno); spin_unlock_bh(&txq->axq_lock); + if (rc_update) + if (acked_cnt == 1 || txfail_cnt == 1) { + ath_tx_rc_status(bf, ds, nbad, txok); + rc_update = false; + } ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar); } else { /* retry the un-acked ones */ @@ -1901,7 +1915,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) struct ath_buf *bf, *lastbf, *bf_held = NULL; struct list_head bf_head; struct ath_desc *ds; - int txok, nbad = 0; + int txok; int status; DPRINTF(sc, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n", @@ -1995,13 +2009,9 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) bf->bf_retries = ds->ds_txstat.ts_longretry; if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) bf->bf_state.bf_type |= BUF_XRETRY; - nbad = 0; - } else { - nbad = ath_tx_num_badfrms(sc, bf, txok); + ath_tx_rc_status(bf, ds, 0, txok); } - ath_tx_rc_status(bf, ds, nbad, txok); - if (bf_isampdu(bf)) ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok); else -- GitLab From 4b4698c443c9db62b220c41a1793872d6ebe82e1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 19 Mar 2009 13:39:19 +0200 Subject: [PATCH 4883/4982] mac80211: Fix a typo in assoc vs. reassoc check Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a55879663b3..4c753bb43ba 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -103,7 +103,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) u32 rates = 0; size_t e_ies_len; - if (ifmgd->flags & IEEE80211_IBSS_PREV_BSSID_SET) { + if (ifmgd->flags & IEEE80211_STA_PREV_BSSID_SET) { e_ies = sdata->u.mgd.ie_reassocreq; e_ies_len = sdata->u.mgd.ie_reassocreq_len; } else { -- GitLab From a299542e97ec1939fdca7db6d3d82c0aa9bf8b9a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 19 Mar 2009 13:39:20 +0200 Subject: [PATCH 4884/4982] mac80211: Fix reassociation by not clearing previous BSSID We must not clear the previous BSSID when roaming to another AP within the same ESS for reassociation to be used properly. It is fine to clear this when the SSID changes, so let's move the code into ieee80211_sta_set_ssid(). Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 4c753bb43ba..1f49b63d8dd 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1888,8 +1888,6 @@ int ieee80211_sta_commit(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - ifmgd->flags &= ~IEEE80211_STA_PREV_BSSID_SET; - if (ifmgd->ssid_len) ifmgd->flags |= IEEE80211_STA_SSID_SET; else @@ -1908,6 +1906,10 @@ int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size ifmgd = &sdata->u.mgd; if (ifmgd->ssid_len != len || memcmp(ifmgd->ssid, ssid, len) != 0) { + /* + * Do not use reassociation if SSID is changed (different ESS). + */ + ifmgd->flags &= ~IEEE80211_STA_PREV_BSSID_SET; memset(ifmgd->ssid, 0, sizeof(ifmgd->ssid)); memcpy(ifmgd->ssid, ssid, len); ifmgd->ssid_len = len; -- GitLab From 6039f6d23fe792d615da5449e9fa1c6b43caacf6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 19 Mar 2009 13:39:21 +0200 Subject: [PATCH 4885/4982] nl80211: Event notifications for MLME events Add new nl80211 event notifications (and a new multicast group, "mlme") for informing user space about received and processed Authentication, (Re)Association Response, Deauthentication, and Disassociation frames in station and IBSS modes (i.e., MLME SAP interface primitives MLME-AUTHENTICATE.confirm, MLME-ASSOCIATE.confirm, MLME-REASSOCIATE.confirm, MLME-DEAUTHENTICATE.indicate, and MLME-DISASSOCIATE.indication). The event data is encapsulated as the 802.11 management frame since we already have the frame in that format and it includes all the needed information. This is the initial step in providing MLME SAP interface for authentication and association with nl80211. In other words, kernel code will act as the MLME and a user space application can control it as the SME. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- include/linux/nl80211.h | 36 ++++++++++++++++++++- include/net/cfg80211.h | 46 ++++++++++++++++++++++++++ net/mac80211/mlme.c | 9 ++++-- net/wireless/Makefile | 2 +- net/wireless/mlme.c | 46 ++++++++++++++++++++++++++ net/wireless/nl80211.c | 72 +++++++++++++++++++++++++++++++++++++++++ net/wireless/nl80211.h | 12 +++++++ 7 files changed, 219 insertions(+), 4 deletions(-) create mode 100644 net/wireless/mlme.c diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 3700d927e24..5ce68ae8314 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -161,6 +161,25 @@ * %NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on * to (%NL80211_ATTR_REG_ALPHA2). * + * @NL80211_CMD_AUTHENTICATE: authentication notification (on the "mlme" + * multicast group). This event reports reception of an Authentication + * frame in station and IBSS modes when the local MLME processed the + * frame, i.e., it was for the local STA and was received in correct + * state. This is similar to MLME-AUTHENTICATE.confirm primitive in the + * MLME SAP interface (kernel providing MLME, userspace SME). The + * included NL80211_ATTR_FRAME attribute contains the management frame + * (including both the header and frame body, but not FCS). + * @NL80211_CMD_ASSOCIATE: association notification; like + * NL80211_CMD_AUTHENTICATE but for Association Response and Reassociation + * Response frames (similar to MLME-ASSOCIATE.confirm or + * MLME-REASSOCIATE.confirm primitives). + * @NL80211_CMD_DEAUTHENTICATE: deauthentication notification; like + * NL80211_CMD_AUTHENTICATE but for Deauthentication frames (similar to + * MLME-DEAUTHENTICATE.indication primitive). + * @NL80211_CMD_DISASSOCIATE: disassociation notification; like + * NL80211_CMD_AUTHENTICATE but for Disassociation frames (similar to + * MLME-DISASSOCIATE.indication primitive). + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -217,6 +236,11 @@ enum nl80211_commands { NL80211_CMD_REG_CHANGE, + NL80211_CMD_AUTHENTICATE, + NL80211_CMD_ASSOCIATE, + NL80211_CMD_DEAUTHENTICATE, + NL80211_CMD_DISASSOCIATE, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -230,8 +254,11 @@ enum nl80211_commands { */ #define NL80211_CMD_SET_BSS NL80211_CMD_SET_BSS #define NL80211_CMD_SET_MGMT_EXTRA_IE NL80211_CMD_SET_MGMT_EXTRA_IE - #define NL80211_CMD_REG_CHANGE NL80211_CMD_REG_CHANGE +#define NL80211_CMD_AUTHENTICATE NL80211_CMD_AUTHENTICATE +#define NL80211_CMD_ASSOCIATE NL80211_CMD_ASSOCIATE +#define NL80211_CMD_DEAUTHENTICATE NL80211_CMD_DEAUTHENTICATE +#define NL80211_CMD_DISASSOCIATE NL80211_CMD_DISASSOCIATE /** * enum nl80211_attrs - nl80211 netlink attributes @@ -353,6 +380,10 @@ enum nl80211_commands { * an array of command numbers (i.e. a mapping index to command number) * that the driver for the given wiphy supports. * + * @NL80211_ATTR_FRAME: frame data (binary attribute), including frame header + * and body, but not FCS; used, e.g., with NL80211_CMD_AUTHENTICATE and + * NL80211_CMD_ASSOCIATE events + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -432,6 +463,8 @@ enum nl80211_attrs { NL80211_ATTR_SUPPORTED_COMMANDS, + NL80211_ATTR_FRAME, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -451,6 +484,7 @@ enum nl80211_attrs { #define NL80211_ATTR_IE NL80211_ATTR_IE #define NL80211_ATTR_REG_INITIATOR NL80211_ATTR_REG_INITIATOR #define NL80211_ATTR_REG_TYPE NL80211_ATTR_REG_TYPE +#define NL80211_ATTR_FRAME NL80211_ATTR_FRAME #define NL80211_MAX_SUPP_RATES 32 #define NL80211_MAX_SUPP_REG_RULES 32 diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 50f3fd9ff52..ad44016021b 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -807,4 +807,50 @@ void cfg80211_put_bss(struct cfg80211_bss *bss); */ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *bss); +/** + * cfg80211_send_rx_auth - notification of processed authentication + * @dev: network device + * @buf: authentication frame (header + body) + * @len: length of the frame data + * + * This function is called whenever an authentication has been processed in + * station mode. + */ +void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len); + +/** + * cfg80211_send_rx_assoc - notification of processed association + * @dev: network device + * @buf: (re)association response frame (header + body) + * @len: length of the frame data + * + * This function is called whenever a (re)association response has been + * processed in station mode. + */ +void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len); + +/** + * cfg80211_send_rx_deauth - notification of processed deauthentication + * @dev: network device + * @buf: deauthentication frame (header + body) + * @len: length of the frame data + * + * This function is called whenever deauthentication has been processed in + * station mode. + */ +void cfg80211_send_rx_deauth(struct net_device *dev, const u8 *buf, + size_t len); + +/** + * cfg80211_send_rx_disassoc - notification of processed disassociation + * @dev: network device + * @buf: disassociation response frame (header + body) + * @len: length of the frame data + * + * This function is called whenever disassociation has been processed in + * station mode. + */ +void cfg80211_send_rx_disassoc(struct net_device *dev, const u8 *buf, + size_t len); + #endif /* __NET_CFG80211_H */ diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 1f49b63d8dd..6dc7a61bc18 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1085,11 +1085,13 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, case WLAN_AUTH_OPEN: case WLAN_AUTH_LEAP: ieee80211_auth_completed(sdata); + cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len); break; case WLAN_AUTH_SHARED_KEY: - if (ifmgd->auth_transaction == 4) + if (ifmgd->auth_transaction == 4) { ieee80211_auth_completed(sdata); - else + cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len); + } else ieee80211_auth_challenge(sdata, mgmt, len); break; } @@ -1125,6 +1127,7 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, ieee80211_set_disassoc(sdata, true, false, 0); ifmgd->flags &= ~IEEE80211_STA_AUTHENTICATED; + cfg80211_send_rx_deauth(sdata->dev, (u8 *) mgmt, len); } @@ -1154,6 +1157,7 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, } ieee80211_set_disassoc(sdata, false, false, reason_code); + cfg80211_send_rx_disassoc(sdata->dev, (u8 *) mgmt, len); } @@ -1370,6 +1374,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, ieee80211_set_associated(sdata, changed); ieee80211_associated(sdata); + cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, len); } diff --git a/net/wireless/Makefile b/net/wireless/Makefile index c157b4d8014..6d1e7b27b75 100644 --- a/net/wireless/Makefile +++ b/net/wireless/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib80211_crypt_wep.o obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o -cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o +cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o mlme.o cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o ccflags-y += -D__CHECK_ENDIAN__ diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c new file mode 100644 index 00000000000..bec5721b6f9 --- /dev/null +++ b/net/wireless/mlme.c @@ -0,0 +1,46 @@ +/* + * cfg80211 MLME SAP interface + * + * Copyright (c) 2009, Jouni Malinen + */ + +#include +#include +#include +#include +#include +#include "core.h" +#include "nl80211.h" + +void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len) +{ + struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + nl80211_send_rx_auth(rdev, dev, buf, len); +} +EXPORT_SYMBOL(cfg80211_send_rx_auth); + +void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) +{ + struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + nl80211_send_rx_assoc(rdev, dev, buf, len); +} +EXPORT_SYMBOL(cfg80211_send_rx_assoc); + +void cfg80211_send_rx_deauth(struct net_device *dev, const u8 *buf, size_t len) +{ + struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + nl80211_send_rx_deauth(rdev, dev, buf, len); +} +EXPORT_SYMBOL(cfg80211_send_rx_deauth); + +void cfg80211_send_rx_disassoc(struct net_device *dev, const u8 *buf, + size_t len) +{ + struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + nl80211_send_rx_disassoc(rdev, dev, buf, len); +} +EXPORT_SYMBOL(cfg80211_send_rx_disassoc); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index a3ecf8d7389..c034c2418cb 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2830,6 +2830,9 @@ static struct genl_ops nl80211_ops[] = { .dumpit = nl80211_dump_scan, }, }; +static struct genl_multicast_group nl80211_mlme_mcgrp = { + .name = "mlme", +}; /* multicast groups */ static struct genl_multicast_group nl80211_config_mcgrp = { @@ -2975,6 +2978,71 @@ nla_put_failure: nlmsg_free(msg); } +static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + const u8 *buf, size_t len, + enum nl80211_commands cmd) +{ + struct sk_buff *msg; + void *hdr; + + msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!msg) + return; + + hdr = nl80211hdr_put(msg, 0, 0, 0, cmd); + if (!hdr) { + nlmsg_free(msg); + return; + } + + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); + NLA_PUT(msg, NL80211_ATTR_FRAME, len, buf); + + if (genlmsg_end(msg, hdr) < 0) { + nlmsg_free(msg); + return; + } + + genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_KERNEL); + return; + + nla_put_failure: + genlmsg_cancel(msg, hdr); + nlmsg_free(msg); +} + +void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *buf, size_t len) +{ + nl80211_send_mlme_event(rdev, netdev, buf, len, + NL80211_CMD_AUTHENTICATE); +} + +void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *buf, + size_t len) +{ + nl80211_send_mlme_event(rdev, netdev, buf, len, NL80211_CMD_ASSOCIATE); +} + +void nl80211_send_rx_deauth(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *buf, + size_t len) +{ + nl80211_send_mlme_event(rdev, netdev, buf, len, + NL80211_CMD_DEAUTHENTICATE); +} + +void nl80211_send_rx_disassoc(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *buf, + size_t len) +{ + nl80211_send_mlme_event(rdev, netdev, buf, len, + NL80211_CMD_DISASSOCIATE); +} + /* initialisation/exit functions */ int nl80211_init(void) @@ -3003,6 +3071,10 @@ int nl80211_init(void) if (err) goto err_out; + err = genl_register_mc_group(&nl80211_fam, &nl80211_mlme_mcgrp); + if (err) + goto err_out; + return 0; err_out: genl_unregister_family(&nl80211_fam); diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 5b5fe1339de..b77af4ab80b 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -11,5 +11,17 @@ extern void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, extern void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, struct net_device *netdev); extern void nl80211_send_reg_change_event(struct regulatory_request *request); +extern void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + const u8 *buf, size_t len); +extern void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + const u8 *buf, size_t len); +extern void nl80211_send_rx_deauth(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + const u8 *buf, size_t len); +extern void nl80211_send_rx_disassoc(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + const u8 *buf, size_t len); #endif /* __NET_WIRELESS_NL80211_H */ -- GitLab From 636a5d3625993c5ca59abc81794b9ded93cdb740 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 19 Mar 2009 13:39:22 +0200 Subject: [PATCH 4886/4982] nl80211: Add MLME primitives to support external SME This patch adds new nl80211 commands to allow user space to request authentication and association (and also deauthentication and disassociation). The commands are structured to allow separate authentication and association steps, i.e., the interface between kernel and user space is similar to the MLME SAP interface in IEEE 802.11 standard and an user space application takes the role of the SME. The patch introduces MLME-AUTHENTICATE.request, MLME-{,RE}ASSOCIATE.request, MLME-DEAUTHENTICATE.request, and MLME-DISASSOCIATE.request primitives. The authentication and association commands request the actual operations in two steps (assuming the driver supports this; if not, separate authentication step is skipped; this could end up being a separate "connect" command). The initial implementation for mac80211 uses the current net/mac80211/mlme.c for actual sending and processing of management frames and the new nl80211 commands will just stop the current state machine from moving automatically from authentication to association. Future cleanup may move more of the MLME operations into cfg80211. The goal of this design is to provide more control of authentication and association process to user space without having to move the full MLME implementation. This should be enough to allow IEEE 802.11r FT protocol and 802.11s SAE authentication to be implemented. Obviously, this will also bring the extra benefit of not having to use WEXT for association requests with mac80211. An example implementation of a user space SME using the new nl80211 commands is available for wpa_supplicant. This patch is enough to get IEEE 802.11r FT protocol working with over-the-air mechanism (over-the-DS will need additional MLME primitives for handling the FT Action frames). Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 1 + include/linux/nl80211.h | 58 +++++++-- include/net/cfg80211.h | 113 ++++++++++++++++ net/mac80211/cfg.c | 140 ++++++++++++++++++++ net/mac80211/ieee80211_i.h | 7 +- net/mac80211/mlme.c | 45 +++++-- net/mac80211/wext.c | 3 + net/wireless/nl80211.c | 255 +++++++++++++++++++++++++++++++++++++ 8 files changed, 601 insertions(+), 21 deletions(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 382387e75b8..4b501b48ce8 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -867,6 +867,7 @@ struct ieee80211_ht_info { /* Authentication algorithms */ #define WLAN_AUTH_OPEN 0 #define WLAN_AUTH_SHARED_KEY 1 +#define WLAN_AUTH_FT 2 #define WLAN_AUTH_LEAP 128 #define WLAN_AUTH_CHALLENGE_LEN 128 diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 5ce68ae8314..9685eaab40a 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -161,24 +161,37 @@ * %NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on * to (%NL80211_ATTR_REG_ALPHA2). * - * @NL80211_CMD_AUTHENTICATE: authentication notification (on the "mlme" - * multicast group). This event reports reception of an Authentication + * @NL80211_CMD_AUTHENTICATE: authentication request and notification. + * This command is used both as a command (request to authenticate) and + * as an event on the "mlme" multicast group indicating completion of the + * authentication process. + * When used as a command, %NL80211_ATTR_IFINDEX is used to identify the + * interface. %NL80211_ATTR_MAC is used to specify PeerSTAAddress (and + * BSSID in case of station mode). %NL80211_ATTR_SSID is used to specify + * the SSID (mainly for association, but is included in authentication + * request, too, to help BSS selection. %NL80211_ATTR_WIPHY_FREQ is used + * to specify the frequence of the channel in MHz. %NL80211_ATTR_AUTH_TYPE + * is used to specify the authentication type. %NL80211_ATTR_IE is used to + * define IEs (VendorSpecificInfo, but also including RSN IE and FT IEs) + * to be added to the frame. + * When used as an event, this reports reception of an Authentication * frame in station and IBSS modes when the local MLME processed the * frame, i.e., it was for the local STA and was received in correct * state. This is similar to MLME-AUTHENTICATE.confirm primitive in the * MLME SAP interface (kernel providing MLME, userspace SME). The * included NL80211_ATTR_FRAME attribute contains the management frame * (including both the header and frame body, but not FCS). - * @NL80211_CMD_ASSOCIATE: association notification; like - * NL80211_CMD_AUTHENTICATE but for Association Response and Reassociation - * Response frames (similar to MLME-ASSOCIATE.confirm or - * MLME-REASSOCIATE.confirm primitives). - * @NL80211_CMD_DEAUTHENTICATE: deauthentication notification; like + * @NL80211_CMD_ASSOCIATE: association request and notification; like + * NL80211_CMD_AUTHENTICATE but for Association and Reassociation + * (similar to MLME-ASSOCIATE.request, MLME-REASSOCIATE.request, + * MLME-ASSOCIATE.confirm or MLME-REASSOCIATE.confirm primitives). + * @NL80211_CMD_DEAUTHENTICATE: deauthentication request and notification; like * NL80211_CMD_AUTHENTICATE but for Deauthentication frames (similar to - * MLME-DEAUTHENTICATE.indication primitive). - * @NL80211_CMD_DISASSOCIATE: disassociation notification; like + * MLME-DEAUTHENTICATION.request and MLME-DEAUTHENTICATE.indication + * primitives). + * @NL80211_CMD_DISASSOCIATE: disassociation request and notification; like * NL80211_CMD_AUTHENTICATE but for Disassociation frames (similar to - * MLME-DISASSOCIATE.indication primitive). + * MLME-DISASSOCIATE.request and MLME-DISASSOCIATE.indication primitives). * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use @@ -383,6 +396,11 @@ enum nl80211_commands { * @NL80211_ATTR_FRAME: frame data (binary attribute), including frame header * and body, but not FCS; used, e.g., with NL80211_CMD_AUTHENTICATE and * NL80211_CMD_ASSOCIATE events + * @NL80211_ATTR_SSID: SSID (binary attribute, 0..32 octets) + * @NL80211_ATTR_AUTH_TYPE: AuthenticationType, see &enum nl80211_auth_type, + * represented as a u32 + * @NL80211_ATTR_REASON_CODE: ReasonCode for %NL80211_CMD_DEAUTHENTICATE and + * %NL80211_CMD_DISASSOCIATE, u16 * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -464,6 +482,9 @@ enum nl80211_attrs { NL80211_ATTR_SUPPORTED_COMMANDS, NL80211_ATTR_FRAME, + NL80211_ATTR_SSID, + NL80211_ATTR_AUTH_TYPE, + NL80211_ATTR_REASON_CODE, /* add attributes here, update the policy in nl80211.c */ @@ -485,6 +506,9 @@ enum nl80211_attrs { #define NL80211_ATTR_REG_INITIATOR NL80211_ATTR_REG_INITIATOR #define NL80211_ATTR_REG_TYPE NL80211_ATTR_REG_TYPE #define NL80211_ATTR_FRAME NL80211_ATTR_FRAME +#define NL80211_ATTR_SSID NL80211_ATTR_SSID +#define NL80211_ATTR_AUTH_TYPE NL80211_ATTR_AUTH_TYPE +#define NL80211_ATTR_REASON_CODE NL80211_ATTR_REASON_CODE #define NL80211_MAX_SUPP_RATES 32 #define NL80211_MAX_SUPP_REG_RULES 32 @@ -1018,4 +1042,18 @@ enum nl80211_bss { NL80211_BSS_MAX = __NL80211_BSS_AFTER_LAST - 1 }; +/** + * enum nl80211_auth_type - AuthenticationType + * + * @NL80211_AUTHTYPE_OPEN_SYSTEM: Open System authentication + * @NL80211_AUTHTYPE_SHARED_KEY: Shared Key authentication (WEP only) + * @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r) + * @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP) + */ +enum nl80211_auth_type { + NL80211_AUTHTYPE_OPEN_SYSTEM, + NL80211_AUTHTYPE_SHARED_KEY, + NL80211_AUTHTYPE_FT, + NL80211_AUTHTYPE_NETWORK_EAP, +}; #endif /* __LINUX_NL80211_H */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index ad44016021b..0da9a55881a 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -578,6 +578,105 @@ struct cfg80211_bss { u8 priv[0] __attribute__((__aligned__(sizeof(void *)))); }; +/** + * struct cfg80211_auth_request - Authentication request data + * + * This structure provides information needed to complete IEEE 802.11 + * authentication. + * NOTE: This structure will likely change when more code from mac80211 is + * moved into cfg80211 so that non-mac80211 drivers can benefit from it, too. + * Before using this in a driver that does not use mac80211, it would be better + * to check the status of that work and better yet, volunteer to work on it. + * + * @chan: The channel to use or %NULL if not specified (auto-select based on + * scan results) + * @peer_addr: The address of the peer STA (AP BSSID in infrastructure case); + * this field is required to be present; if the driver wants to help with + * BSS selection, it should use (yet to be added) MLME event to allow user + * space SME to be notified of roaming candidate, so that the SME can then + * use the authentication request with the recommended BSSID and whatever + * other data may be needed for authentication/association + * @ssid: SSID or %NULL if not yet available + * @ssid_len: Length of ssid in octets + * @auth_type: Authentication type (algorithm) + * @ie: Extra IEs to add to Authentication frame or %NULL + * @ie_len: Length of ie buffer in octets + */ +struct cfg80211_auth_request { + struct ieee80211_channel *chan; + u8 *peer_addr; + const u8 *ssid; + size_t ssid_len; + enum nl80211_auth_type auth_type; + const u8 *ie; + size_t ie_len; +}; + +/** + * struct cfg80211_assoc_request - (Re)Association request data + * + * This structure provides information needed to complete IEEE 802.11 + * (re)association. + * NOTE: This structure will likely change when more code from mac80211 is + * moved into cfg80211 so that non-mac80211 drivers can benefit from it, too. + * Before using this in a driver that does not use mac80211, it would be better + * to check the status of that work and better yet, volunteer to work on it. + * + * @chan: The channel to use or %NULL if not specified (auto-select based on + * scan results) + * @peer_addr: The address of the peer STA (AP BSSID); this field is required + * to be present and the STA must be in State 2 (authenticated) with the + * peer STA + * @ssid: SSID + * @ssid_len: Length of ssid in octets + * @ie: Extra IEs to add to (Re)Association Request frame or %NULL + * @ie_len: Length of ie buffer in octets + */ +struct cfg80211_assoc_request { + struct ieee80211_channel *chan; + u8 *peer_addr; + const u8 *ssid; + size_t ssid_len; + const u8 *ie; + size_t ie_len; +}; + +/** + * struct cfg80211_deauth_request - Deauthentication request data + * + * This structure provides information needed to complete IEEE 802.11 + * deauthentication. + * + * @peer_addr: The address of the peer STA (AP BSSID); this field is required + * to be present and the STA must be authenticated with the peer STA + * @ie: Extra IEs to add to Deauthentication frame or %NULL + * @ie_len: Length of ie buffer in octets + */ +struct cfg80211_deauth_request { + u8 *peer_addr; + u16 reason_code; + const u8 *ie; + size_t ie_len; +}; + +/** + * struct cfg80211_disassoc_request - Disassociation request data + * + * This structure provides information needed to complete IEEE 802.11 + * disassocation. + * + * @peer_addr: The address of the peer STA (AP BSSID); this field is required + * to be present and the STA must be associated with the peer STA + * @ie: Extra IEs to add to Disassociation frame or %NULL + * @ie_len: Length of ie buffer in octets + */ +struct cfg80211_disassoc_request { + u8 *peer_addr; + u16 reason_code; + const u8 *ie; + size_t ie_len; +}; + /** * struct cfg80211_ops - backend description for wireless configuration * @@ -650,6 +749,11 @@ struct cfg80211_bss { * the driver, and will be valid until passed to cfg80211_scan_done(). * For scan results, call cfg80211_inform_bss(); you can call this outside * the scan/scan_done bracket too. + * + * @auth: Request to authenticate with the specified peer + * @assoc: Request to (re)associate with the specified peer + * @deauth: Request to deauthenticate from the specified peer + * @disassoc: Request to disassociate from the specified peer */ struct cfg80211_ops { int (*suspend)(struct wiphy *wiphy); @@ -730,6 +834,15 @@ struct cfg80211_ops { int (*scan)(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_scan_request *request); + + int (*auth)(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_auth_request *req); + int (*assoc)(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_assoc_request *req); + int (*deauth)(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_deauth_request *req); + int (*disassoc)(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_disassoc_request *req); }; /* temporary wext handlers */ diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 58693e52d45..223e536e842 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1300,6 +1300,142 @@ static int ieee80211_scan(struct wiphy *wiphy, return ieee80211_request_scan(sdata, req); } +static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_auth_request *req) +{ + struct ieee80211_sub_if_data *sdata; + + if (!netif_running(dev)) + return -ENETDOWN; + + sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + if (sdata->vif.type != NL80211_IFTYPE_STATION) + return -EOPNOTSUPP; + + switch (req->auth_type) { + case NL80211_AUTHTYPE_OPEN_SYSTEM: + sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_OPEN; + break; + case NL80211_AUTHTYPE_SHARED_KEY: + sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_SHARED_KEY; + break; + case NL80211_AUTHTYPE_FT: + sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_FT; + break; + case NL80211_AUTHTYPE_NETWORK_EAP: + sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_LEAP; + break; + default: + return -EOPNOTSUPP; + } + + memcpy(sdata->u.mgd.bssid, req->peer_addr, ETH_ALEN); + sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; + sdata->u.mgd.flags |= IEEE80211_STA_BSSID_SET; + + /* TODO: req->chan */ + sdata->u.mgd.flags |= IEEE80211_STA_AUTO_CHANNEL_SEL; + + if (req->ssid) { + sdata->u.mgd.flags |= IEEE80211_STA_SSID_SET; + memcpy(sdata->u.mgd.ssid, req->ssid, req->ssid_len); + sdata->u.mgd.ssid_len = req->ssid_len; + sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL; + } + + kfree(sdata->u.mgd.sme_auth_ie); + sdata->u.mgd.sme_auth_ie = NULL; + sdata->u.mgd.sme_auth_ie_len = 0; + if (req->ie) { + sdata->u.mgd.sme_auth_ie = kmalloc(req->ie_len, GFP_KERNEL); + if (sdata->u.mgd.sme_auth_ie == NULL) + return -ENOMEM; + memcpy(sdata->u.mgd.sme_auth_ie, req->ie, req->ie_len); + sdata->u.mgd.sme_auth_ie_len = req->ie_len; + } + + sdata->u.mgd.flags |= IEEE80211_STA_EXT_SME; + sdata->u.mgd.state = IEEE80211_STA_MLME_DIRECT_PROBE; + ieee80211_sta_req_auth(sdata); + return 0; +} + +static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_assoc_request *req) +{ + struct ieee80211_sub_if_data *sdata; + int ret; + + if (!netif_running(dev)) + return -ENETDOWN; + + sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + if (sdata->vif.type != NL80211_IFTYPE_STATION) + return -EOPNOTSUPP; + + if (memcmp(sdata->u.mgd.bssid, req->peer_addr, ETH_ALEN) != 0 || + !(sdata->u.mgd.flags & IEEE80211_STA_AUTHENTICATED)) + return -ENOLINK; /* not authenticated */ + + sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; + sdata->u.mgd.flags |= IEEE80211_STA_BSSID_SET; + + /* TODO: req->chan */ + sdata->u.mgd.flags |= IEEE80211_STA_AUTO_CHANNEL_SEL; + + if (req->ssid) { + sdata->u.mgd.flags |= IEEE80211_STA_SSID_SET; + memcpy(sdata->u.mgd.ssid, req->ssid, req->ssid_len); + sdata->u.mgd.ssid_len = req->ssid_len; + sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL; + } else + sdata->u.mgd.flags |= IEEE80211_STA_AUTO_SSID_SEL; + + ret = ieee80211_sta_set_extra_ie(sdata, req->ie, req->ie_len); + if (ret) + return ret; + + sdata->u.mgd.flags |= IEEE80211_STA_EXT_SME; + sdata->u.mgd.state = IEEE80211_STA_MLME_ASSOCIATE; + ieee80211_sta_req_auth(sdata); + return 0; +} + +static int ieee80211_deauth(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_deauth_request *req) +{ + struct ieee80211_sub_if_data *sdata; + + if (!netif_running(dev)) + return -ENETDOWN; + + sdata = IEEE80211_DEV_TO_SUB_IF(dev); + if (sdata->vif.type != NL80211_IFTYPE_STATION) + return -EOPNOTSUPP; + + /* TODO: req->ie */ + return ieee80211_sta_deauthenticate(sdata, req->reason_code); +} + +static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_disassoc_request *req) +{ + struct ieee80211_sub_if_data *sdata; + + if (!netif_running(dev)) + return -ENETDOWN; + + sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + if (sdata->vif.type != NL80211_IFTYPE_STATION) + return -EOPNOTSUPP; + + /* TODO: req->ie */ + return ieee80211_sta_disassociate(sdata, req->reason_code); +} + struct cfg80211_ops mac80211_config_ops = { .add_virtual_intf = ieee80211_add_iface, .del_virtual_intf = ieee80211_del_iface, @@ -1333,4 +1469,8 @@ struct cfg80211_ops mac80211_config_ops = { .suspend = ieee80211_suspend, .resume = ieee80211_resume, .scan = ieee80211_scan, + .auth = ieee80211_auth, + .assoc = ieee80211_assoc, + .deauth = ieee80211_deauth, + .disassoc = ieee80211_disassoc, }; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ad12c2a03a9..7b96d95f48b 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -256,6 +256,7 @@ struct mesh_preq_queue { #define IEEE80211_STA_TKIP_WEP_USED BIT(14) #define IEEE80211_STA_CSA_RECEIVED BIT(15) #define IEEE80211_STA_MFP_ENABLED BIT(16) +#define IEEE80211_STA_EXT_SME BIT(17) /* flags for MLME request */ #define IEEE80211_STA_REQ_SCAN 0 #define IEEE80211_STA_REQ_DIRECT_PROBE 1 @@ -266,6 +267,7 @@ struct mesh_preq_queue { #define IEEE80211_AUTH_ALG_OPEN BIT(0) #define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1) #define IEEE80211_AUTH_ALG_LEAP BIT(2) +#define IEEE80211_AUTH_ALG_FT BIT(3) struct ieee80211_if_managed { struct timer_list timer; @@ -335,6 +337,9 @@ struct ieee80211_if_managed { size_t ie_deauth_len; u8 *ie_disassoc; size_t ie_disassoc_len; + + u8 *sme_auth_ie; + size_t sme_auth_ie_len; }; enum ieee80211_ibss_flags { @@ -970,7 +975,7 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, struct ieee80211_rx_status *rx_status); int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, - char *ie, size_t len); + const char *ie, size_t len); void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); void ieee80211_scan_failed(struct ieee80211_local *local); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 6dc7a61bc18..d1bcc843877 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -730,6 +730,8 @@ static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_local *local = sdata->local; + u8 *ies; + size_t ies_len; ifmgd->auth_tries++; if (ifmgd->auth_tries > IEEE80211_AUTH_MAX_TRIES) { @@ -755,7 +757,14 @@ static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata) printk(KERN_DEBUG "%s: authenticate with AP %pM\n", sdata->dev->name, ifmgd->bssid); - ieee80211_send_auth(sdata, 1, ifmgd->auth_alg, NULL, 0, + if (ifmgd->flags & IEEE80211_STA_EXT_SME) { + ies = ifmgd->sme_auth_ie; + ies_len = ifmgd->sme_auth_ie_len; + } else { + ies = NULL; + ies_len = 0; + } + ieee80211_send_auth(sdata, 1, ifmgd->auth_alg, ies, ies_len, ifmgd->bssid, 0); ifmgd->auth_transaction = 2; @@ -870,7 +879,8 @@ static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata) int wep_privacy; int privacy_invoked; - if (!ifmgd || (ifmgd->flags & IEEE80211_STA_MIXED_CELL)) + if (!ifmgd || (ifmgd->flags & (IEEE80211_STA_MIXED_CELL | + IEEE80211_STA_EXT_SME))) return 0; bss = ieee80211_rx_bss_get(local, ifmgd->bssid, @@ -998,7 +1008,11 @@ static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata) printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name); ifmgd->flags |= IEEE80211_STA_AUTHENTICATED; - ieee80211_associate(sdata); + if (ifmgd->flags & IEEE80211_STA_EXT_SME) { + /* Wait for SME to request association */ + ifmgd->state = IEEE80211_STA_MLME_DISABLED; + } else + ieee80211_associate(sdata); } @@ -1084,6 +1098,7 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, switch (ifmgd->auth_alg) { case WLAN_AUTH_OPEN: case WLAN_AUTH_LEAP: + case WLAN_AUTH_FT: ieee80211_auth_completed(sdata); cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len); break; @@ -1117,9 +1132,10 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, printk(KERN_DEBUG "%s: deauthenticated (Reason: %u)\n", sdata->dev->name, reason_code); - if (ifmgd->state == IEEE80211_STA_MLME_AUTHENTICATE || - ifmgd->state == IEEE80211_STA_MLME_ASSOCIATE || - ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED) { + if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) && + (ifmgd->state == IEEE80211_STA_MLME_AUTHENTICATE || + ifmgd->state == IEEE80211_STA_MLME_ASSOCIATE || + ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED)) { ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE; mod_timer(&ifmgd->timer, jiffies + IEEE80211_RETRY_AUTH_INTERVAL); @@ -1150,7 +1166,8 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n", sdata->dev->name, reason_code); - if (ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED) { + if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) && + ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED) { ifmgd->state = IEEE80211_STA_MLME_ASSOCIATE; mod_timer(&ifmgd->timer, jiffies + IEEE80211_RETRY_AUTH_INTERVAL); @@ -1664,6 +1681,8 @@ static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata) ifmgd->auth_alg = WLAN_AUTH_SHARED_KEY; else if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_LEAP) ifmgd->auth_alg = WLAN_AUTH_LEAP; + else if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_FT) + ifmgd->auth_alg = WLAN_AUTH_FT; else ifmgd->auth_alg = WLAN_AUTH_OPEN; ifmgd->auth_transaction = -1; @@ -1687,7 +1706,8 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata) u16 capa_val = WLAN_CAPABILITY_ESS; struct ieee80211_channel *chan = local->oper_channel; - if (ifmgd->flags & (IEEE80211_STA_AUTO_SSID_SEL | + if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) && + ifmgd->flags & (IEEE80211_STA_AUTO_SSID_SEL | IEEE80211_STA_AUTO_BSSID_SEL | IEEE80211_STA_AUTO_CHANNEL_SEL)) { capa_mask |= WLAN_CAPABILITY_PRIVACY; @@ -1884,7 +1904,11 @@ void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata) ieee80211_set_disassoc(sdata, true, true, WLAN_REASON_DEAUTH_LEAVING); - set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request); + if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) || + ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE) + set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request); + else if (ifmgd->flags & IEEE80211_STA_EXT_SME) + set_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request); queue_work(local->hw.workqueue, &ifmgd->work); } } @@ -1953,7 +1977,8 @@ int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid) return ieee80211_sta_commit(sdata); } -int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len) +int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, + const char *ie, size_t len) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index e55d2834764..ce21d66b102 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -137,6 +137,7 @@ static int ieee80211_ioctl_siwgenie(struct net_device *dev, if (ret) return ret; sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; + sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; ieee80211_sta_req_auth(sdata); return 0; } @@ -224,6 +225,7 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev, if (ret) return ret; + sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; ieee80211_sta_req_auth(sdata); return 0; } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) @@ -287,6 +289,7 @@ static int ieee80211_ioctl_siwap(struct net_device *dev, ret = ieee80211_sta_set_bssid(sdata, (u8 *) &ap_addr->sa_data); if (ret) return ret; + sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; ieee80211_sta_req_auth(sdata); return 0; } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index c034c2418cb..9e1318d1d4b 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -111,6 +111,11 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { .len = IEEE80211_MAX_DATA_LEN }, [NL80211_ATTR_SCAN_FREQUENCIES] = { .type = NLA_NESTED }, [NL80211_ATTR_SCAN_SSIDS] = { .type = NLA_NESTED }, + + [NL80211_ATTR_SSID] = { .type = NLA_BINARY, + .len = IEEE80211_MAX_SSID_LEN }, + [NL80211_ATTR_AUTH_TYPE] = { .type = NLA_U32 }, + [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 }, }; /* message building helper */ @@ -265,6 +270,10 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, CMD(set_mesh_params, SET_MESH_PARAMS); CMD(change_bss, SET_BSS); CMD(set_mgmt_extra_ie, SET_MGMT_EXTRA_IE); + CMD(auth, AUTHENTICATE); + CMD(assoc, ASSOCIATE); + CMD(deauth, DEAUTHENTICATE); + CMD(disassoc, DISASSOCIATE); #undef CMD nla_nest_end(msg, nl_cmds); @@ -2646,6 +2655,228 @@ static int nl80211_dump_scan(struct sk_buff *skb, return err; } +static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *drv; + struct net_device *dev; + struct cfg80211_auth_request req; + struct wiphy *wiphy; + int err; + + rtnl_lock(); + + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); + if (err) + goto unlock_rtnl; + + if (!drv->ops->auth) { + err = -EOPNOTSUPP; + goto out; + } + + if (!info->attrs[NL80211_ATTR_MAC]) { + err = -EINVAL; + goto out; + } + + wiphy = &drv->wiphy; + memset(&req, 0, sizeof(req)); + + req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); + + if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { + req.chan = ieee80211_get_channel( + wiphy, + nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); + if (!req.chan) { + err = -EINVAL; + goto out; + } + } + + if (info->attrs[NL80211_ATTR_SSID]) { + req.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); + req.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); + } + + if (info->attrs[NL80211_ATTR_IE]) { + req.ie = nla_data(info->attrs[NL80211_ATTR_IE]); + req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); + } + + if (info->attrs[NL80211_ATTR_AUTH_TYPE]) { + req.auth_type = + nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]); + } + + err = drv->ops->auth(&drv->wiphy, dev, &req); + +out: + cfg80211_put_dev(drv); + dev_put(dev); +unlock_rtnl: + rtnl_unlock(); + return err; +} + +static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *drv; + struct net_device *dev; + struct cfg80211_assoc_request req; + struct wiphy *wiphy; + int err; + + rtnl_lock(); + + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); + if (err) + goto unlock_rtnl; + + if (!drv->ops->assoc) { + err = -EOPNOTSUPP; + goto out; + } + + if (!info->attrs[NL80211_ATTR_MAC] || + !info->attrs[NL80211_ATTR_SSID]) { + err = -EINVAL; + goto out; + } + + wiphy = &drv->wiphy; + memset(&req, 0, sizeof(req)); + + req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); + + if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { + req.chan = ieee80211_get_channel( + wiphy, + nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); + if (!req.chan) { + err = -EINVAL; + goto out; + } + } + + if (nla_len(info->attrs[NL80211_ATTR_SSID]) > IEEE80211_MAX_SSID_LEN) { + err = -EINVAL; + goto out; + } + req.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); + req.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); + + if (info->attrs[NL80211_ATTR_IE]) { + req.ie = nla_data(info->attrs[NL80211_ATTR_IE]); + req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); + } + + err = drv->ops->assoc(&drv->wiphy, dev, &req); + +out: + cfg80211_put_dev(drv); + dev_put(dev); +unlock_rtnl: + rtnl_unlock(); + return err; +} + +static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *drv; + struct net_device *dev; + struct cfg80211_deauth_request req; + struct wiphy *wiphy; + int err; + + rtnl_lock(); + + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); + if (err) + goto unlock_rtnl; + + if (!drv->ops->deauth) { + err = -EOPNOTSUPP; + goto out; + } + + if (!info->attrs[NL80211_ATTR_MAC]) { + err = -EINVAL; + goto out; + } + + wiphy = &drv->wiphy; + memset(&req, 0, sizeof(req)); + + req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); + + if (info->attrs[NL80211_ATTR_REASON_CODE]) + req.reason_code = + nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); + + if (info->attrs[NL80211_ATTR_IE]) { + req.ie = nla_data(info->attrs[NL80211_ATTR_IE]); + req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); + } + + err = drv->ops->deauth(&drv->wiphy, dev, &req); + +out: + cfg80211_put_dev(drv); + dev_put(dev); +unlock_rtnl: + rtnl_unlock(); + return err; +} + +static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *drv; + struct net_device *dev; + struct cfg80211_disassoc_request req; + struct wiphy *wiphy; + int err; + + rtnl_lock(); + + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); + if (err) + goto unlock_rtnl; + + if (!drv->ops->disassoc) { + err = -EOPNOTSUPP; + goto out; + } + + if (!info->attrs[NL80211_ATTR_MAC]) { + err = -EINVAL; + goto out; + } + + wiphy = &drv->wiphy; + memset(&req, 0, sizeof(req)); + + req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); + + if (info->attrs[NL80211_ATTR_REASON_CODE]) + req.reason_code = + nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); + + if (info->attrs[NL80211_ATTR_IE]) { + req.ie = nla_data(info->attrs[NL80211_ATTR_IE]); + req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); + } + + err = drv->ops->disassoc(&drv->wiphy, dev, &req); + +out: + cfg80211_put_dev(drv); + dev_put(dev); +unlock_rtnl: + rtnl_unlock(); + return err; +} + static struct genl_ops nl80211_ops[] = { { .cmd = NL80211_CMD_GET_WIPHY, @@ -2829,6 +3060,30 @@ static struct genl_ops nl80211_ops[] = { .policy = nl80211_policy, .dumpit = nl80211_dump_scan, }, + { + .cmd = NL80211_CMD_AUTHENTICATE, + .doit = nl80211_authenticate, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, + { + .cmd = NL80211_CMD_ASSOCIATE, + .doit = nl80211_associate, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, + { + .cmd = NL80211_CMD_DEAUTHENTICATE, + .doit = nl80211_deauthenticate, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, + { + .cmd = NL80211_CMD_DISASSOCIATE, + .doit = nl80211_disassociate, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, }; static struct genl_multicast_group nl80211_mlme_mcgrp = { .name = "mlme", -- GitLab From 1bf68e5cda40eaa26b186f043340fd283a4fb718 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 19 Mar 2009 13:33:52 +0100 Subject: [PATCH 4887/4982] wireless/p54: P54_SPI should depend on GENERIC_HARDIRQS m68k allmodconfig: | drivers/net/wireless/p54/p54spi.c: In function 'p54spi_probe': | drivers/net/wireless/p54/p54spi.c:675: error: implicit declaration of function | 'set_irq_type' | make[4]: *** [drivers/net/wireless/p54/p54spi.o] Error 1 Signed-off-by: Geert Uytterhoeven Signed-off-by: John W. Linville --- drivers/net/wireless/p54/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/p54/Kconfig b/drivers/net/wireless/p54/Kconfig index cfc5f41aa13..0e344ac10d2 100644 --- a/drivers/net/wireless/p54/Kconfig +++ b/drivers/net/wireless/p54/Kconfig @@ -64,7 +64,7 @@ config P54_PCI config P54_SPI tristate "Prism54 SPI (stlc45xx) support" - depends on P54_COMMON && SPI_MASTER + depends on P54_COMMON && SPI_MASTER && GENERIC_HARDIRQS ---help--- This driver is for stlc4550 or stlc4560 based wireless chips. This driver is experimental, untested and will probably only work on -- GitLab From 3e3ccb3d9b8d5a1b65b34e1be2decf213ba3bebb Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Thu, 19 Mar 2009 19:27:21 +0100 Subject: [PATCH 4888/4982] b43: Mask PHY TX error interrupt, if not debugging This masks the PHY TX error interrupt, if debugging is disabled. Currently we have a bug somewhere which triggers this interrupt once in a while. (Depends on the network noise/quality). While this is nonfatal, it scares the hell out of users and we frequently receive bugreports that incorrectly identify this error message as the reason. There's another problem with this. The PHY TX error interrupt is protected with a watchdog that will restart the device if it keeps triggering very often. This is used to fix interrupt storms from completely broken devices. However, this watchdog might trigger in completely normal operation. If the TX capacity of the card is saturated, the likeliness of the watchdog triggering increases, as more TX errors occur. The current threshold for the watchdog is 1000 errors in 15 seconds. This patch adds a workaround for the issue by just enabling the interrupt if debugging is disabled (by Kconfig or by modparam). This has the downside that real fatal PHY TX errors are not caught anymore. But this is nonfatal due to the following reasons: * If the card is not able to transmit anymore, MLME will notice anyway. * I did _never_ see a real fatal PHY TX error in a mainline b43 driver. * It does _not_ result in interrupt storms or something like that. It will simply result in a stalled card. It can be debugged by enabling the debugging module parameter. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index b72ef3fd315..4896e083111 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3993,6 +3993,8 @@ static void setup_struct_wldev_for_init(struct b43_wldev *dev) dev->irq_reason = 0; memset(dev->dma_reason, 0, sizeof(dev->dma_reason)); dev->irq_savedstate = B43_IRQ_MASKTEMPLATE; + if (b43_modparam_verbose < B43_VERBOSITY_DEBUG) + dev->irq_savedstate &= ~B43_IRQ_PHY_TXERR; dev->mac_suspended = 1; -- GitLab From 827b1fb44b7e41377a5498b9d070a11dfae2c283 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 13 Mar 2009 11:44:18 +0100 Subject: [PATCH 4889/4982] mac80211: resume properly, add suspend/resume test When mac80211 resumes, it currently doesn't reconfigure the interfaces entirely and also doesn't reconfigure BSS information -- fix this. Also, to be able to test this, add a debugfs file that just calls the suspend/resume code to see what happens when we go through that, without needing the time-consuming suspend/resume cycle. (Original version broke the build for CONFIG_PM=n. Define alternative functions for that situation. -- JWL) Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/debugfs.c | 24 ++++++++++++++++++++++++ net/mac80211/ieee80211_i.h | 12 ++++++++++++ net/mac80211/pm.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index e37f557de3f..210b9b6fecd 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -40,6 +40,10 @@ static const struct file_operations name## _ops = { \ local->debugfs.name = debugfs_create_file(#name, 0400, phyd, \ local, &name## _ops); +#define DEBUGFS_ADD_MODE(name, mode) \ + local->debugfs.name = debugfs_create_file(#name, mode, phyd, \ + local, &name## _ops); + #define DEBUGFS_DEL(name) \ debugfs_remove(local->debugfs.name); \ local->debugfs.name = NULL; @@ -113,6 +117,24 @@ static const struct file_operations tsf_ops = { .open = mac80211_open_file_generic }; +static ssize_t reset_write(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_local *local = file->private_data; + + rtnl_lock(); + __ieee80211_suspend(&local->hw); + __ieee80211_resume(&local->hw); + rtnl_unlock(); + + return count; +} + +static const struct file_operations reset_ops = { + .write = reset_write, + .open = mac80211_open_file_generic, +}; + /* statistics stuff */ #define DEBUGFS_STATS_FILE(name, buflen, fmt, value...) \ @@ -254,6 +276,7 @@ void debugfs_hw_add(struct ieee80211_local *local) DEBUGFS_ADD(total_ps_buffered); DEBUGFS_ADD(wep_iv); DEBUGFS_ADD(tsf); + DEBUGFS_ADD_MODE(reset, 0200); statsd = debugfs_create_dir("statistics", phyd); local->debugfs.statistics = statsd; @@ -308,6 +331,7 @@ void debugfs_hw_del(struct ieee80211_local *local) DEBUGFS_DEL(total_ps_buffered); DEBUGFS_DEL(wep_iv); DEBUGFS_DEL(tsf); + DEBUGFS_DEL(reset); DEBUGFS_STATS_DEL(transmitted_fragment_count); DEBUGFS_STATS_DEL(multicast_transmitted_frame_count); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 7b96d95f48b..547cfac218e 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -780,6 +780,7 @@ struct ieee80211_local { struct dentry *total_ps_buffered; struct dentry *wep_iv; struct dentry *tsf; + struct dentry *reset; struct dentry *statistics; struct local_debugfsdentries_statsdentries { struct dentry *transmitted_fragment_count; @@ -1059,8 +1060,19 @@ void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, u8 pwr_constr_elem_len); /* Suspend/resume */ +#ifdef CONFIG_PM int __ieee80211_suspend(struct ieee80211_hw *hw); int __ieee80211_resume(struct ieee80211_hw *hw); +#else +static inline int __ieee80211_suspend(struct ieee80211_hw *hw) +{ + return 0; +} +static inline int __ieee80211_resume(struct ieee80211_hw *hw) +{ + return 0; +} +#endif /* utility functions/constants */ extern void *mac80211_wiphy_privid; /* for wiphy privid */ diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 1e6152ac677..02730232649 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -143,6 +143,35 @@ int __ieee80211_resume(struct ieee80211_hw *hw) ieee80211_configure_filter(local); netif_addr_unlock_bh(local->mdev); + /* Finally also reconfigure all the BSS information */ + list_for_each_entry(sdata, &local->interfaces, list) { + u32 changed = ~0; + if (!netif_running(sdata->dev)) + continue; + switch (sdata->vif.type) { + case NL80211_IFTYPE_STATION: + /* disable beacon change bits */ + changed &= ~IEEE80211_IFCC_BEACON; + /* fall through */ + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: + WARN_ON(ieee80211_if_config(sdata, changed)); + ieee80211_bss_info_change_notify(sdata, ~0); + break; + case NL80211_IFTYPE_WDS: + break; + case NL80211_IFTYPE_AP_VLAN: + case NL80211_IFTYPE_MONITOR: + /* ignore virtual */ + break; + case NL80211_IFTYPE_UNSPECIFIED: + case __NL80211_IFTYPE_AFTER_LAST: + WARN_ON(1); + break; + } + } + ieee80211_wake_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_SUSPEND); -- GitLab From 8a92e2ee02dee127d309c73969aeb2a56567c9a0 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Fri, 20 Mar 2009 15:27:49 +0530 Subject: [PATCH 4890/4982] ath9k: Fix bug in reporting status of tx rate This patch updates count of every hw tried rate with appropriate tries before reporting tx status of a frame. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/xmit.c | 35 +++++++++++++++++++------------ 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index f2877193e95..21e90bca350 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -67,7 +67,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf); static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, int txok); static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, - int nbad, int txok); + int nbad, int txok, bool update_rc); /*********************/ /* Aggregation logic */ @@ -370,11 +370,13 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, ath_tx_update_baw(sc, tid, bf->bf_seqno); spin_unlock_bh(&txq->axq_lock); - if (rc_update) - if (acked_cnt == 1 || txfail_cnt == 1) { - ath_tx_rc_status(bf, ds, nbad, txok); - rc_update = false; - } + if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { + ath_tx_rc_status(bf, ds, nbad, txok, true); + rc_update = false; + } else { + ath_tx_rc_status(bf, ds, nbad, txok, false); + } + ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar); } else { /* retry the un-acked ones */ @@ -1779,8 +1781,6 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, tx_info->flags |= IEEE80211_TX_STAT_ACK; } - tx_info->status.rates[0].count = tx_status->retries + 1; - hdrlen = ieee80211_get_hdrlen_from_skb(skb); padsize = hdrlen & 3; if (padsize && hdrlen >= 24) { @@ -1867,30 +1867,39 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, } static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, - int nbad, int txok) + int nbad, int txok, bool update_rc) { struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); + struct ieee80211_hw *hw = tx_info_priv->aphy->hw; + u8 i, tx_rateindex; if (txok) tx_info->status.ack_signal = ds->ds_txstat.ts_rssi; - tx_info_priv->update_rc = false; + tx_rateindex = ds->ds_txstat.ts_rateindex; + WARN_ON(tx_rateindex >= hw->max_rates); + + tx_info_priv->update_rc = update_rc; if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && - (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) { + (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { if (ieee80211_is_data(hdr->frame_control)) { memcpy(&tx_info_priv->tx, &ds->ds_txstat, sizeof(tx_info_priv->tx)); tx_info_priv->n_frames = bf->bf_nframes; tx_info_priv->n_bad_frames = nbad; - tx_info_priv->update_rc = true; } } + + for (i = tx_rateindex + 1; i < hw->max_rates; i++) + tx_info->status.rates[i].count = 0; + + tx_info->status.rates[tx_rateindex].count = bf->bf_retries + 1; } static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) @@ -2009,7 +2018,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) bf->bf_retries = ds->ds_txstat.ts_longretry; if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) bf->bf_state.bf_type |= BUF_XRETRY; - ath_tx_rc_status(bf, ds, 0, txok); + ath_tx_rc_status(bf, ds, 0, txok, true); } if (bf_isampdu(bf)) -- GitLab From 6b2c40326f9569283444d483448bcaadeca903e9 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Fri, 20 Mar 2009 15:27:50 +0530 Subject: [PATCH 4891/4982] ath9k: Nuke struct ath_xmit_status Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ath9k.h | 4 ---- drivers/net/wireless/ath9k/xmit.c | 25 ++++++++----------------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index 2b025645511..2689a08a284 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -295,13 +295,9 @@ struct ath_tx_control { enum ath9k_internal_frame_type frame_type; }; -struct ath_xmit_status { - int retries; - int flags; #define ATH_TX_ERROR 0x01 #define ATH_TX_XRETRY 0x02 #define ATH_TX_BAR 0x04 -}; /* All RSSI values are noise floor adjusted */ struct ath_tx_stat { diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 21e90bca350..689bdbf7880 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -1750,7 +1750,7 @@ exit: /*****************/ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, - struct ath_xmit_status *tx_status) + int tx_flags) { struct ieee80211_hw *hw = sc->hw; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); @@ -1771,12 +1771,10 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, tx_info->rate_driver_data[0] = NULL; } - if (tx_status->flags & ATH_TX_BAR) { + if (tx_flags & ATH_TX_BAR) tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; - tx_status->flags &= ~ATH_TX_BAR; - } - if (!(tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) { + if (!(tx_flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) { /* Frame was ACKed */ tx_info->flags |= IEEE80211_TX_STAT_ACK; } @@ -1803,29 +1801,22 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, int txok, int sendbar) { struct sk_buff *skb = bf->bf_mpdu; - struct ath_xmit_status tx_status; unsigned long flags; + int tx_flags = 0; - /* - * Set retry information. - * NB: Don't use the information in the descriptor, because the frame - * could be software retried. - */ - tx_status.retries = bf->bf_retries; - tx_status.flags = 0; if (sendbar) - tx_status.flags = ATH_TX_BAR; + tx_flags = ATH_TX_BAR; if (!txok) { - tx_status.flags |= ATH_TX_ERROR; + tx_flags |= ATH_TX_ERROR; if (bf_isxretried(bf)) - tx_status.flags |= ATH_TX_XRETRY; + tx_flags |= ATH_TX_XRETRY; } dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); - ath_tx_complete(sc, skb, &tx_status); + ath_tx_complete(sc, skb, tx_flags); /* * Return the list of ath_buf of this mpdu to free queue -- GitLab From d7873cb9abb5d8b4b9f7f5749af06e4e03798733 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 20 Mar 2009 15:53:16 +0200 Subject: [PATCH 4892/4982] mac80211: Fix memleak in nl80211 authentication on deinit This file was forgotten from the quilt patch that added MLME primitives, so the kfree on interface removal is missing. Fix this potential memleak by freeing the temporary Authentication frame IEs from SME when the interface is being removed. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/mac80211/iface.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index f9f27b9cadb..6b56dc2208e 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -660,6 +660,7 @@ static void ieee80211_teardown_sdata(struct net_device *dev) kfree(sdata->u.mgd.ie_reassocreq); kfree(sdata->u.mgd.ie_deauth); kfree(sdata->u.mgd.ie_disassoc); + kfree(sdata->u.mgd.sme_auth_ie); break; case NL80211_IFTYPE_WDS: case NL80211_IFTYPE_AP_VLAN: -- GitLab From feeb44454996cf5b375fad21697bf6202fe30dd2 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 20 Mar 2009 16:43:20 +0100 Subject: [PATCH 4893/4982] ssb: remove EXPERIMENTAL dependencies. ssb is not experimental anymore. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/ssb/Kconfig | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig index b1b947edcf0..540a2948596 100644 --- a/drivers/ssb/Kconfig +++ b/drivers/ssb/Kconfig @@ -53,11 +53,11 @@ config SSB_B43_PCI_BRIDGE config SSB_PCMCIAHOST_POSSIBLE bool - depends on SSB && (PCMCIA = y || PCMCIA = SSB) && EXPERIMENTAL + depends on SSB && (PCMCIA = y || PCMCIA = SSB) default y config SSB_PCMCIAHOST - bool "Support for SSB on PCMCIA-bus host (EXPERIMENTAL)" + bool "Support for SSB on PCMCIA-bus host" depends on SSB_PCMCIAHOST_POSSIBLE select SSB_SPROM help @@ -107,14 +107,14 @@ config SSB_DRIVER_PCICORE If unsure, say Y config SSB_PCICORE_HOSTMODE - bool "Hostmode support for SSB PCI core (EXPERIMENTAL)" - depends on SSB_DRIVER_PCICORE && SSB_DRIVER_MIPS && EXPERIMENTAL + bool "Hostmode support for SSB PCI core" + depends on SSB_DRIVER_PCICORE && SSB_DRIVER_MIPS help PCIcore hostmode operation (external PCI bus). config SSB_DRIVER_MIPS - bool "SSB Broadcom MIPS core driver (EXPERIMENTAL)" - depends on SSB && MIPS && EXPERIMENTAL + bool "SSB Broadcom MIPS core driver" + depends on SSB && MIPS select SSB_SERIAL help Driver for the Sonics Silicon Backplane attached @@ -129,8 +129,8 @@ config SSB_EMBEDDED default y config SSB_DRIVER_EXTIF - bool "SSB Broadcom EXTIF core driver (EXPERIMENTAL)" - depends on SSB_DRIVER_MIPS && EXPERIMENTAL + bool "SSB Broadcom EXTIF core driver" + depends on SSB_DRIVER_MIPS help Driver for the Sonics Silicon Backplane attached Broadcom EXTIF core. -- GitLab From 65fc73ac4a310945dfeceac961726c2765ad2ec0 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 20 Mar 2009 21:21:16 +0200 Subject: [PATCH 4894/4982] nl80211: Remove NL80211_CMD_SET_MGMT_EXTRA_IE The functionality that NL80211_CMD_SET_MGMT_EXTRA_IE provided can now be achieved with cleaner design by adding IE(s) into NL80211_CMD_TRIGGER_SCAN, NL80211_CMD_AUTHENTICATE, NL80211_CMD_ASSOCIATE, NL80211_CMD_DEAUTHENTICATE, and NL80211_CMD_DISASSOCIATE. Since this is a very recently added command and there are no known (or known planned) applications using NL80211_CMD_SET_MGMT_EXTRA_IE and taken into account how much extra complexity it adds to the IE processing we have now (and need to add in the future to fix IE order in couple of frames), it looks like the best option is to just remove the implementation of this command for now. The enum values themselves are left to avoid changing the nl80211 command or attribute numbers. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- include/linux/nl80211.h | 8 +++- include/net/cfg80211.h | 26 ------------ net/mac80211/cfg.c | 86 -------------------------------------- net/mac80211/ieee80211_i.h | 15 ------- net/mac80211/iface.c | 7 ---- net/mac80211/mlme.c | 36 ++-------------- net/mac80211/util.c | 29 ++----------- net/wireless/nl80211.c | 47 --------------------- 8 files changed, 14 insertions(+), 240 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 9685eaab40a..cbe8ce3bf48 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -142,6 +142,12 @@ * %NL80211_ATTR_IE. If the command succeeds, the requested data will be * added to all specified management frames generated by * kernel/firmware/driver. + * Note: This command has been removed and it is only reserved at this + * point to avoid re-using existing command number. The functionality this + * command was planned for has been provided with cleaner design with the + * option to specify additional IEs in NL80211_CMD_TRIGGER_SCAN, + * NL80211_CMD_AUTHENTICATE, NL80211_CMD_ASSOCIATE, + * NL80211_CMD_DEAUTHENTICATE, and NL80211_CMD_DISASSOCIATE. * * @NL80211_CMD_GET_SCAN: get scan results * @NL80211_CMD_TRIGGER_SCAN: trigger a new scan with the given parameters @@ -238,7 +244,7 @@ enum nl80211_commands { NL80211_CMD_GET_MESH_PARAMS, NL80211_CMD_SET_MESH_PARAMS, - NL80211_CMD_SET_MGMT_EXTRA_IE, + NL80211_CMD_SET_MGMT_EXTRA_IE /* reserved; not used */, NL80211_CMD_GET_REG, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 0da9a55881a..dca4a6b0461 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -471,26 +471,6 @@ struct ieee80211_txq_params { u8 aifs; }; -/** - * struct mgmt_extra_ie_params - Extra management frame IE parameters - * - * Used to add extra IE(s) into management frames. If the driver cannot add the - * requested data into all management frames of the specified subtype that are - * generated in kernel or firmware/hardware, it must reject the configuration - * call. The IE data buffer is added to the end of the specified management - * frame body after all other IEs. This addition is not applied to frames that - * are injected through a monitor interface. - * - * @subtype: Management frame subtype - * @ies: IE data buffer or %NULL to remove previous data - * @ies_len: Length of @ies in octets - */ -struct mgmt_extra_ie_params { - u8 subtype; - u8 *ies; - int ies_len; -}; - /* from net/wireless.h */ struct wiphy; @@ -743,8 +723,6 @@ struct cfg80211_disassoc_request { * * @set_channel: Set channel * - * @set_mgmt_extra_ie: Set extra IE data for management frames - * * @scan: Request to do a scan. If returning zero, the scan request is given * the driver, and will be valid until passed to cfg80211_scan_done(). * For scan results, call cfg80211_inform_bss(); you can call this outside @@ -828,10 +806,6 @@ struct cfg80211_ops { struct ieee80211_channel *chan, enum nl80211_channel_type channel_type); - int (*set_mgmt_extra_ie)(struct wiphy *wiphy, - struct net_device *dev, - struct mgmt_extra_ie_params *params); - int (*scan)(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_scan_request *request); diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 223e536e842..f5c15c9a00c 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1181,91 +1181,6 @@ static int ieee80211_set_channel(struct wiphy *wiphy, return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); } -static int set_mgmt_extra_ie_sta(struct ieee80211_sub_if_data *sdata, - u8 subtype, u8 *ies, size_t ies_len) -{ - struct ieee80211_local *local = sdata->local; - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - - switch (subtype) { - case IEEE80211_STYPE_PROBE_REQ >> 4: - if (local->ops->hw_scan) - break; - kfree(ifmgd->ie_probereq); - ifmgd->ie_probereq = ies; - ifmgd->ie_probereq_len = ies_len; - return 0; - case IEEE80211_STYPE_PROBE_RESP >> 4: - kfree(ifmgd->ie_proberesp); - ifmgd->ie_proberesp = ies; - ifmgd->ie_proberesp_len = ies_len; - return 0; - case IEEE80211_STYPE_AUTH >> 4: - kfree(ifmgd->ie_auth); - ifmgd->ie_auth = ies; - ifmgd->ie_auth_len = ies_len; - return 0; - case IEEE80211_STYPE_ASSOC_REQ >> 4: - kfree(ifmgd->ie_assocreq); - ifmgd->ie_assocreq = ies; - ifmgd->ie_assocreq_len = ies_len; - return 0; - case IEEE80211_STYPE_REASSOC_REQ >> 4: - kfree(ifmgd->ie_reassocreq); - ifmgd->ie_reassocreq = ies; - ifmgd->ie_reassocreq_len = ies_len; - return 0; - case IEEE80211_STYPE_DEAUTH >> 4: - kfree(ifmgd->ie_deauth); - ifmgd->ie_deauth = ies; - ifmgd->ie_deauth_len = ies_len; - return 0; - case IEEE80211_STYPE_DISASSOC >> 4: - kfree(ifmgd->ie_disassoc); - ifmgd->ie_disassoc = ies; - ifmgd->ie_disassoc_len = ies_len; - return 0; - } - - return -EOPNOTSUPP; -} - -static int ieee80211_set_mgmt_extra_ie(struct wiphy *wiphy, - struct net_device *dev, - struct mgmt_extra_ie_params *params) -{ - struct ieee80211_sub_if_data *sdata; - u8 *ies; - size_t ies_len; - int ret = -EOPNOTSUPP; - - if (params->ies) { - ies = kmemdup(params->ies, params->ies_len, GFP_KERNEL); - if (ies == NULL) - return -ENOMEM; - ies_len = params->ies_len; - } else { - ies = NULL; - ies_len = 0; - } - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - switch (sdata->vif.type) { - case NL80211_IFTYPE_STATION: - ret = set_mgmt_extra_ie_sta(sdata, params->subtype, - ies, ies_len); - break; - default: - ret = -EOPNOTSUPP; - break; - } - - if (ret) - kfree(ies); - return ret; -} - #ifdef CONFIG_PM static int ieee80211_suspend(struct wiphy *wiphy) { @@ -1465,7 +1380,6 @@ struct cfg80211_ops mac80211_config_ops = { .change_bss = ieee80211_change_bss, .set_txq_params = ieee80211_set_txq_params, .set_channel = ieee80211_set_channel, - .set_mgmt_extra_ie = ieee80211_set_mgmt_extra_ie, .suspend = ieee80211_suspend, .resume = ieee80211_resume, .scan = ieee80211_scan, diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 547cfac218e..f69e84ab961 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -323,21 +323,6 @@ struct ieee80211_if_managed { int wmm_last_param_set; /* Extra IE data for management frames */ - u8 *ie_probereq; - size_t ie_probereq_len; - u8 *ie_proberesp; - size_t ie_proberesp_len; - u8 *ie_auth; - size_t ie_auth_len; - u8 *ie_assocreq; - size_t ie_assocreq_len; - u8 *ie_reassocreq; - size_t ie_reassocreq_len; - u8 *ie_deauth; - size_t ie_deauth_len; - u8 *ie_disassoc; - size_t ie_disassoc_len; - u8 *sme_auth_ie; size_t sme_auth_ie_len; }; diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 6b56dc2208e..34f4798a98f 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -653,13 +653,6 @@ static void ieee80211_teardown_sdata(struct net_device *dev) kfree(sdata->u.mgd.extra_ie); kfree(sdata->u.mgd.assocreq_ies); kfree(sdata->u.mgd.assocresp_ies); - kfree(sdata->u.mgd.ie_probereq); - kfree(sdata->u.mgd.ie_proberesp); - kfree(sdata->u.mgd.ie_auth); - kfree(sdata->u.mgd.ie_assocreq); - kfree(sdata->u.mgd.ie_reassocreq); - kfree(sdata->u.mgd.ie_deauth); - kfree(sdata->u.mgd.ie_disassoc); kfree(sdata->u.mgd.sme_auth_ie); break; case NL80211_IFTYPE_WDS: diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index d1bcc843877..b0808efcedf 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -82,38 +82,23 @@ static int ieee80211_compatible_rates(struct ieee80211_bss *bss, /* frame sending functions */ -static void add_extra_ies(struct sk_buff *skb, u8 *ies, size_t ies_len) -{ - if (ies) - memcpy(skb_put(skb, ies_len), ies, ies_len); -} - static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; - u8 *pos, *ies, *ht_ie, *e_ies; + u8 *pos, *ies, *ht_ie; int i, len, count, rates_len, supp_rates_len; u16 capab; struct ieee80211_bss *bss; int wmm = 0; struct ieee80211_supported_band *sband; u32 rates = 0; - size_t e_ies_len; - - if (ifmgd->flags & IEEE80211_STA_PREV_BSSID_SET) { - e_ies = sdata->u.mgd.ie_reassocreq; - e_ies_len = sdata->u.mgd.ie_reassocreq_len; - } else { - e_ies = sdata->u.mgd.ie_assocreq; - e_ies_len = sdata->u.mgd.ie_assocreq_len; - } skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 + ifmgd->extra_ie_len + - ifmgd->ssid_len + e_ies_len); + ifmgd->ssid_len); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " "frame\n", sdata->dev->name); @@ -304,8 +289,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); } - add_extra_ies(skb, e_ies, e_ies_len); - kfree(ifmgd->assocreq_ies); ifmgd->assocreq_ies_len = (skb->data + skb->len) - ies; ifmgd->assocreq_ies = kmalloc(ifmgd->assocreq_ies_len, GFP_KERNEL); @@ -323,19 +306,8 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; - u8 *ies; - size_t ies_len; - if (stype == IEEE80211_STYPE_DEAUTH) { - ies = sdata->u.mgd.ie_deauth; - ies_len = sdata->u.mgd.ie_deauth_len; - } else { - ies = sdata->u.mgd.ie_disassoc; - ies_len = sdata->u.mgd.ie_disassoc_len; - } - - skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + - ies_len); + skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for " "deauth/disassoc frame\n", sdata->dev->name); @@ -353,8 +325,6 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, /* u.deauth.reason_code == u.disassoc.reason_code */ mgmt->u.deauth.reason_code = cpu_to_le16(reason); - add_extra_ies(skb, ies, ies_len); - ieee80211_tx_skb(sdata, skb, ifmgd->flags & IEEE80211_STA_MFP_ENABLED); } diff --git a/net/mac80211/util.c b/net/mac80211/util.c index e0431a1d218..444bb14c95e 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -846,16 +846,9 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; - const u8 *ie_auth = NULL; - int ie_auth_len = 0; - - if (sdata->vif.type == NL80211_IFTYPE_STATION) { - ie_auth_len = sdata->u.mgd.ie_auth_len; - ie_auth = sdata->u.mgd.ie_auth; - } skb = dev_alloc_skb(local->hw.extra_tx_headroom + - sizeof(*mgmt) + 6 + extra_len + ie_auth_len); + sizeof(*mgmt) + 6 + extra_len); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for auth " "frame\n", sdata->dev->name); @@ -877,8 +870,6 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, mgmt->u.auth.status_code = cpu_to_le16(0); if (extra) memcpy(skb_put(skb, extra_len), extra, extra_len); - if (ie_auth) - memcpy(skb_put(skb, ie_auth_len), ie_auth, ie_auth_len); ieee80211_tx_skb(sdata, skb, encrypt); } @@ -891,20 +882,11 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, struct ieee80211_supported_band *sband; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; - u8 *pos, *supp_rates, *esupp_rates = NULL, *extra_preq_ie = NULL; - int i, extra_preq_ie_len = 0; - - switch (sdata->vif.type) { - case NL80211_IFTYPE_STATION: - extra_preq_ie_len = sdata->u.mgd.ie_probereq_len; - extra_preq_ie = sdata->u.mgd.ie_probereq; - break; - default: - break; - } + u8 *pos, *supp_rates, *esupp_rates = NULL; + int i; skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 + - ie_len + extra_preq_ie_len); + ie_len); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for probe " "request\n", sdata->dev->name); @@ -953,9 +935,6 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, if (ie) memcpy(skb_put(skb, ie_len), ie, ie_len); - if (extra_preq_ie) - memcpy(skb_put(skb, extra_preq_ie_len), extra_preq_ie, - extra_preq_ie_len); ieee80211_tx_skb(sdata, skb, 0); } diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 9e1318d1d4b..44c79972be5 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -269,7 +269,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, CMD(add_mpath, NEW_MPATH); CMD(set_mesh_params, SET_MESH_PARAMS); CMD(change_bss, SET_BSS); - CMD(set_mgmt_extra_ie, SET_MGMT_EXTRA_IE); CMD(auth, AUTHENTICATE); CMD(assoc, ASSOCIATE); CMD(deauth, DEAUTHENTICATE); @@ -2355,46 +2354,6 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) return -EINVAL; } -static int nl80211_set_mgmt_extra_ie(struct sk_buff *skb, - struct genl_info *info) -{ - struct cfg80211_registered_device *drv; - int err; - struct net_device *dev; - struct mgmt_extra_ie_params params; - - memset(¶ms, 0, sizeof(params)); - - if (!info->attrs[NL80211_ATTR_MGMT_SUBTYPE]) - return -EINVAL; - params.subtype = nla_get_u8(info->attrs[NL80211_ATTR_MGMT_SUBTYPE]); - if (params.subtype > 15) - return -EINVAL; /* FC Subtype field is 4 bits (0..15) */ - - if (info->attrs[NL80211_ATTR_IE]) { - params.ies = nla_data(info->attrs[NL80211_ATTR_IE]); - params.ies_len = nla_len(info->attrs[NL80211_ATTR_IE]); - } - - rtnl_lock(); - - err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); - if (err) - goto out_rtnl; - - if (drv->ops->set_mgmt_extra_ie) - err = drv->ops->set_mgmt_extra_ie(&drv->wiphy, dev, ¶ms); - else - err = -EOPNOTSUPP; - - cfg80211_put_dev(drv); - dev_put(dev); - out_rtnl: - rtnl_unlock(); - - return err; -} - static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *drv; @@ -3043,12 +3002,6 @@ static struct genl_ops nl80211_ops[] = { .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, }, - { - .cmd = NL80211_CMD_SET_MGMT_EXTRA_IE, - .doit = nl80211_set_mgmt_extra_ie, - .policy = nl80211_policy, - .flags = GENL_ADMIN_PERM, - }, { .cmd = NL80211_CMD_TRIGGER_SCAN, .doit = nl80211_trigger_scan, -- GitLab From 255e737eab645ec6037baeca04a5e0a7c3b1f459 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 20 Mar 2009 21:21:17 +0200 Subject: [PATCH 4895/4982] nl80211: Add more through validation of MLME command parameters Check that the used authentication type and reason code are valid here so that drivers/mac80211 do not need to care about this. In addition, remove the unnecessary validation of SSID attribute length which is taken care of by netlink policy. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 44c79972be5..6f38ee7a3c9 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2614,6 +2614,14 @@ static int nl80211_dump_scan(struct sk_buff *skb, return err; } +static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type) +{ + return auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM || + auth_type == NL80211_AUTHTYPE_SHARED_KEY || + auth_type == NL80211_AUTHTYPE_FT || + auth_type == NL80211_AUTHTYPE_NETWORK_EAP; +} + static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *drv; @@ -2666,6 +2674,10 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NL80211_ATTR_AUTH_TYPE]) { req.auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]); + if (!nl80211_valid_auth_type(req.auth_type)) { + err = -EINVAL; + goto out; + } } err = drv->ops->auth(&drv->wiphy, dev, &req); @@ -2718,10 +2730,6 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) } } - if (nla_len(info->attrs[NL80211_ATTR_SSID]) > IEEE80211_MAX_SSID_LEN) { - err = -EINVAL; - goto out; - } req.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); req.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); @@ -2769,9 +2777,15 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); - if (info->attrs[NL80211_ATTR_REASON_CODE]) + if (info->attrs[NL80211_ATTR_REASON_CODE]) { req.reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); + if (req.reason_code == 0) { + /* Reason Code 0 is reserved */ + err = -EINVAL; + goto out; + } + } if (info->attrs[NL80211_ATTR_IE]) { req.ie = nla_data(info->attrs[NL80211_ATTR_IE]); @@ -2817,9 +2831,15 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); - if (info->attrs[NL80211_ATTR_REASON_CODE]) + if (info->attrs[NL80211_ATTR_REASON_CODE]) { req.reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); + if (req.reason_code == 0) { + /* Reason Code 0 is reserved */ + err = -EINVAL; + goto out; + } + } if (info->attrs[NL80211_ATTR_IE]) { req.ie = nla_data(info->attrs[NL80211_ATTR_IE]); -- GitLab From 35a8efe1a67ba5d7bb7492f67f52ed2aa4925892 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 20 Mar 2009 21:21:18 +0200 Subject: [PATCH 4896/4982] nl80211: Check that netif_runnin is true in cfg80211 code We do not want to require all the drivers using cfg80211 to need to do this or to be prepared to handle these commands when the interface is down. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 25 ------------------------- net/wireless/nl80211.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 25 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index f5c15c9a00c..b5810b4c79a 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -728,10 +728,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, int err; int layer2_update; - /* Prevent a race with changing the rate control algorithm */ - if (!netif_running(dev)) - return -ENETDOWN; - if (params->vlan) { sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); @@ -860,9 +856,6 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, struct sta_info *sta; int err; - if (!netif_running(dev)) - return -ENETDOWN; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) @@ -913,9 +906,6 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, struct mesh_path *mpath; struct sta_info *sta; - if (!netif_running(dev)) - return -ENETDOWN; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) @@ -1202,9 +1192,6 @@ static int ieee80211_scan(struct wiphy *wiphy, { struct ieee80211_sub_if_data *sdata; - if (!netif_running(dev)) - return -ENETDOWN; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_STATION && @@ -1220,9 +1207,6 @@ static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev, { struct ieee80211_sub_if_data *sdata; - if (!netif_running(dev)) - return -ENETDOWN; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_STATION) @@ -1282,9 +1266,6 @@ static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_sub_if_data *sdata; int ret; - if (!netif_running(dev)) - return -ENETDOWN; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_STATION) @@ -1323,9 +1304,6 @@ static int ieee80211_deauth(struct wiphy *wiphy, struct net_device *dev, { struct ieee80211_sub_if_data *sdata; - if (!netif_running(dev)) - return -ENETDOWN; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_STATION) return -EOPNOTSUPP; @@ -1339,9 +1317,6 @@ static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev, { struct ieee80211_sub_if_data *sdata; - if (!netif_running(dev)) - return -ENETDOWN; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_STATION) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 6f38ee7a3c9..6bb73a3a339 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1556,6 +1556,11 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) goto out; } + if (!netif_running(dev)) { + err = -ENETDOWN; + goto out; + } + err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, ¶ms); out: @@ -1808,6 +1813,11 @@ static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info) goto out; } + if (!netif_running(dev)) { + err = -ENETDOWN; + goto out; + } + err = drv->ops->change_mpath(&drv->wiphy, dev, dst, next_hop); out: @@ -1846,6 +1856,11 @@ static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info) goto out; } + if (!netif_running(dev)) { + err = -ENETDOWN; + goto out; + } + err = drv->ops->add_mpath(&drv->wiphy, dev, dst, next_hop); out: @@ -2380,6 +2395,11 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) goto out; } + if (!netif_running(dev)) { + err = -ENETDOWN; + goto out; + } + if (drv->scan_req) { err = -EBUSY; goto out; @@ -2641,6 +2661,11 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) goto out; } + if (!netif_running(dev)) { + err = -ENETDOWN; + goto out; + } + if (!info->attrs[NL80211_ATTR_MAC]) { err = -EINVAL; goto out; @@ -2709,6 +2734,11 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) goto out; } + if (!netif_running(dev)) { + err = -ENETDOWN; + goto out; + } + if (!info->attrs[NL80211_ATTR_MAC] || !info->attrs[NL80211_ATTR_SSID]) { err = -EINVAL; @@ -2767,6 +2797,11 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) goto out; } + if (!netif_running(dev)) { + err = -ENETDOWN; + goto out; + } + if (!info->attrs[NL80211_ATTR_MAC]) { err = -EINVAL; goto out; @@ -2821,6 +2856,11 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) goto out; } + if (!netif_running(dev)) { + err = -ENETDOWN; + goto out; + } + if (!info->attrs[NL80211_ATTR_MAC]) { err = -EINVAL; goto out; -- GitLab From eec60b037a875513d9715dcdb90b13ed81fc5f26 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 20 Mar 2009 21:21:19 +0200 Subject: [PATCH 4897/4982] nl80211: Check iftype in cfg80211 code We do not want to require all the drivers using cfg80211 to need to do this. In addition, make the error values consistent by using EOPNOTSUPP instead of semi-random assortment of errno values. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 40 ----------------------------- net/wireless/nl80211.c | 58 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 42 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index b5810b4c79a..e677b751d46 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -540,9 +540,6 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != NL80211_IFTYPE_AP) - return -EINVAL; - old = sdata->u.ap.beacon; if (old) @@ -559,9 +556,6 @@ static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != NL80211_IFTYPE_AP) - return -EINVAL; - old = sdata->u.ap.beacon; if (!old) @@ -577,9 +571,6 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != NL80211_IFTYPE_AP) - return -EINVAL; - old = sdata->u.ap.beacon; if (!old) @@ -858,9 +849,6 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) - return -ENOTSUPP; - rcu_read_lock(); sta = sta_info_get(local, next_hop); if (!sta) { @@ -908,9 +896,6 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) - return -ENOTSUPP; - rcu_read_lock(); sta = sta_info_get(local, next_hop); @@ -979,9 +964,6 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) - return -ENOTSUPP; - rcu_read_lock(); mpath = mesh_path_lookup(dst, sdata); if (!mpath) { @@ -1003,9 +985,6 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) - return -ENOTSUPP; - rcu_read_lock(); mpath = mesh_path_lookup_by_idx(idx, sdata); if (!mpath) { @@ -1025,8 +1004,6 @@ static int ieee80211_get_mesh_params(struct wiphy *wiphy, struct ieee80211_sub_if_data *sdata; sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) - return -ENOTSUPP; memcpy(conf, &(sdata->u.mesh.mshcfg), sizeof(struct mesh_config)); return 0; } @@ -1044,9 +1021,6 @@ static int ieee80211_set_mesh_params(struct wiphy *wiphy, struct ieee80211_sub_if_data *sdata; sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) - return -ENOTSUPP; - /* Set the config options which we are interested in setting */ conf = &(sdata->u.mesh.mshcfg); if (_chg_mesh_attr(NL80211_MESHCONF_RETRY_TIMEOUT, mask)) @@ -1094,9 +1068,6 @@ static int ieee80211_change_bss(struct wiphy *wiphy, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != NL80211_IFTYPE_AP) - return -EINVAL; - if (params->use_cts_prot >= 0) { sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot; changed |= BSS_CHANGED_ERP_CTS_PROT; @@ -1209,9 +1180,6 @@ static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != NL80211_IFTYPE_STATION) - return -EOPNOTSUPP; - switch (req->auth_type) { case NL80211_AUTHTYPE_OPEN_SYSTEM: sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_OPEN; @@ -1268,9 +1236,6 @@ static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != NL80211_IFTYPE_STATION) - return -EOPNOTSUPP; - if (memcmp(sdata->u.mgd.bssid, req->peer_addr, ETH_ALEN) != 0 || !(sdata->u.mgd.flags & IEEE80211_STA_AUTHENTICATED)) return -ENOLINK; /* not authenticated */ @@ -1305,8 +1270,6 @@ static int ieee80211_deauth(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_sub_if_data *sdata; sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != NL80211_IFTYPE_STATION) - return -EOPNOTSUPP; /* TODO: req->ie */ return ieee80211_sta_deauthenticate(sdata, req->reason_code); @@ -1319,9 +1282,6 @@ static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != NL80211_IFTYPE_STATION) - return -EOPNOTSUPP; - /* TODO: req->ie */ return ieee80211_sta_disassociate(sdata, req->reason_code); } diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 6bb73a3a339..a7d0b94f6b5 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1049,6 +1049,11 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) if (err) goto unlock_rtnl; + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) { + err = -EOPNOTSUPP; + goto out; + } + switch (info->genlhdr->cmd) { case NL80211_CMD_NEW_BEACON: /* these are required for NEW_BEACON */ @@ -1136,6 +1141,10 @@ static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) goto out; } + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) { + err = -EOPNOTSUPP; + goto out; + } err = drv->ops->del_beacon(&drv->wiphy, dev); out: @@ -1324,7 +1333,7 @@ static int nl80211_dump_station(struct sk_buff *skb, } if (!dev->ops->dump_station) { - err = -ENOSYS; + err = -EOPNOTSUPP; goto out_err; } @@ -1698,10 +1707,15 @@ static int nl80211_dump_mpath(struct sk_buff *skb, } if (!dev->ops->dump_mpath) { - err = -ENOSYS; + err = -EOPNOTSUPP; goto out_err; } + if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) { + err = -EOPNOTSUPP; + goto out; + } + while (1) { err = dev->ops->dump_mpath(&dev->wiphy, netdev, path_idx, dst, next_hop, &pinfo); @@ -1759,6 +1773,11 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info) goto out; } + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) { + err = -EOPNOTSUPP; + goto out; + } + err = drv->ops->get_mpath(&drv->wiphy, dev, dst, next_hop, &pinfo); if (err) goto out; @@ -1813,6 +1832,11 @@ static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info) goto out; } + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) { + err = -EOPNOTSUPP; + goto out; + } + if (!netif_running(dev)) { err = -ENETDOWN; goto out; @@ -1856,6 +1880,11 @@ static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info) goto out; } + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) { + err = -EOPNOTSUPP; + goto out; + } + if (!netif_running(dev)) { err = -ENETDOWN; goto out; @@ -1944,6 +1973,11 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) goto out; } + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) { + err = -EOPNOTSUPP; + goto out; + } + err = drv->ops->change_bss(&drv->wiphy, dev, ¶ms); out: @@ -2661,6 +2695,11 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) goto out; } + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { + err = -EOPNOTSUPP; + goto out; + } + if (!netif_running(dev)) { err = -ENETDOWN; goto out; @@ -2734,6 +2773,11 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) goto out; } + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { + err = -EOPNOTSUPP; + goto out; + } + if (!netif_running(dev)) { err = -ENETDOWN; goto out; @@ -2797,6 +2841,11 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) goto out; } + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { + err = -EOPNOTSUPP; + goto out; + } + if (!netif_running(dev)) { err = -ENETDOWN; goto out; @@ -2856,6 +2905,11 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) goto out; } + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { + err = -EOPNOTSUPP; + goto out; + } + if (!netif_running(dev)) { err = -ENETDOWN; goto out; -- GitLab From d8cd7effc20027c313d4086b123046ff9f9a5814 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Mon, 23 Mar 2009 15:37:45 +0100 Subject: [PATCH 4898/4982] p54: fix SoftLED compile dependencies This patch fixes a compile problem when the MAC80211_LEDS triggers are enabled but not LED class itself. (which is sort of pointless, but anyway...) Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/Kconfig | 5 +++++ drivers/net/wireless/p54/p54common.c | 16 ++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/p54/Kconfig b/drivers/net/wireless/p54/Kconfig index 0e344ac10d2..7d6e9d10820 100644 --- a/drivers/net/wireless/p54/Kconfig +++ b/drivers/net/wireless/p54/Kconfig @@ -71,3 +71,8 @@ config P54_SPI Nokia's N800/N810 Portable Internet Tablet. If you choose to build a module, it'll be called p54spi. + +config P54_LEDS + bool + depends on P54_COMMON && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = P54_COMMON) + default y diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 0a989834b70..0c1b0577d4e 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -21,9 +21,9 @@ #include #include -#ifdef CONFIG_MAC80211_LEDS +#ifdef CONFIG_P54_LEDS #include -#endif /* CONFIG_MAC80211_LEDS */ +#endif /* CONFIG_P54_LEDS */ #include "p54.h" #include "p54common.h" @@ -2420,7 +2420,7 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, return 0; } -#ifdef CONFIG_MAC80211_LEDS +#ifdef CONFIG_P54_LEDS static void p54_led_brightness_set(struct led_classdev *led_dev, enum led_brightness brightness) { @@ -2508,7 +2508,7 @@ static void p54_unregister_leds(struct ieee80211_hw *dev) if (priv->assoc_led.registered) led_classdev_unregister(&priv->assoc_led.led_dev); } -#endif /* CONFIG_MAC80211_LEDS */ +#endif /* CONFIG_P54_LEDS */ static const struct ieee80211_ops p54_ops = { .tx = p54_tx, @@ -2592,11 +2592,11 @@ int p54_register_common(struct ieee80211_hw *dev, struct device *pdev) return err; } - #ifdef CONFIG_MAC80211_LEDS +#ifdef CONFIG_P54_LEDS err = p54_init_leds(dev); if (err) return err; - #endif /* CONFIG_MAC80211_LEDS */ +#endif /* CONFIG_P54_LEDS */ dev_info(pdev, "is registered as '%s'\n", wiphy_name(dev->wiphy)); return 0; @@ -2610,9 +2610,9 @@ void p54_free_common(struct ieee80211_hw *dev) kfree(priv->output_limit); kfree(priv->curve_data); - #ifdef CONFIG_MAC80211_LEDS +#ifdef CONFIG_P54_LEDS p54_unregister_leds(dev); - #endif /* CONFIG_MAC80211_LEDS */ +#endif /* CONFIG_P54_LEDS */ } EXPORT_SYMBOL_GPL(p54_free_common); -- GitLab From 9cb5412b0760981d43ac3e612992c90cea690e72 Mon Sep 17 00:00:00 2001 From: Pat Erley Date: Fri, 20 Mar 2009 22:59:59 -0400 Subject: [PATCH 4899/4982] Add mesh point functionality to ath9k This patch enables mesh point operation for ath9k. Tested with b43, ath9k, rt2500usb, and ath5k as peers. Signed-off-by: Pat Erley Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/beacon.c | 4 +++- drivers/net/wireless/ath9k/hw.c | 2 ++ drivers/net/wireless/ath9k/main.c | 24 ++++++++++++------------ drivers/net/wireless/ath9k/rc.c | 1 + 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c index e5b007196ca..ec995730632 100644 --- a/drivers/net/wireless/ath9k/beacon.c +++ b/drivers/net/wireless/ath9k/beacon.c @@ -70,7 +70,8 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, ds = bf->bf_desc; flags = ATH9K_TXDESC_NOACK; - if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC && + if (((sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || + (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) && (ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) { ds->ds_link = bf->bf_daddr; /* self-linked */ flags |= ATH9K_TXDESC_VEOL; @@ -728,6 +729,7 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) ath_beacon_config_ap(sc, &conf, avp); break; case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: ath_beacon_config_adhoc(sc, &conf, avp, vif); break; case NL80211_IFTYPE_STATION: diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 15e4d422cad..b15eaf8417f 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -1448,6 +1448,7 @@ static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode) REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); break; case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC | AR_STA_ID1_KSRCH_MODE); REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); @@ -3149,6 +3150,7 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) flags |= AR_TBTT_TIMER_EN; break; case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: REG_SET_BIT(ah, AR_TXCFG, AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY); REG_WRITE(ah, AR_NEXT_NDP_TIMER, diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 4c29cef66a6..c13e4e53634 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1599,7 +1599,8 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC); + BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_MESH_POINT); hw->wiphy->reg_notifier = ath9k_reg_notifier; hw->wiphy->strict_regulatory = true; @@ -2207,18 +2208,13 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, ic_opmode = NL80211_IFTYPE_STATION; break; case NL80211_IFTYPE_ADHOC: - if (sc->nbcnvifs >= ATH_BCBUF) { - ret = -ENOBUFS; - goto out; - } - ic_opmode = NL80211_IFTYPE_ADHOC; - break; case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: if (sc->nbcnvifs >= ATH_BCBUF) { ret = -ENOBUFS; goto out; } - ic_opmode = NL80211_IFTYPE_AP; + ic_opmode = conf->type; break; default: DPRINTF(sc, ATH_DBG_FATAL, @@ -2254,7 +2250,8 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, * Note we only do this (at the moment) for station mode. */ if ((conf->type == NL80211_IFTYPE_STATION) || - (conf->type == NL80211_IFTYPE_ADHOC)) { + (conf->type == NL80211_IFTYPE_ADHOC) || + (conf->type == NL80211_IFTYPE_MESH_POINT)) { if (ath9k_hw_phycounters(sc->sc_ah)) sc->imask |= ATH9K_INT_MIB; sc->imask |= ATH9K_INT_TSFOOR; @@ -2301,8 +2298,9 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, del_timer_sync(&sc->ani.timer); /* Reclaim beacon resources */ - if (sc->sc_ah->opmode == NL80211_IFTYPE_AP || - sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) { + if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || + (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || + (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) { ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); ath_beacon_return(sc, avp); } @@ -2435,6 +2433,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, switch (vif->type) { case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: /* Set BSSID */ memcpy(sc->curbssid, conf->bssid, ETH_ALEN); memcpy(avp->bssid, conf->bssid, ETH_ALEN); @@ -2458,7 +2457,8 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, } if ((vif->type == NL80211_IFTYPE_ADHOC) || - (vif->type == NL80211_IFTYPE_AP)) { + (vif->type == NL80211_IFTYPE_AP) || + (vif->type == NL80211_IFTYPE_MESH_POINT)) { if ((conf->changed & IEEE80211_IFCC_BEACON) || (conf->changed & IEEE80211_IFCC_BEACON_ENABLED && conf->enable_beacon)) { diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 6c2fd395bc3..824ccbb8b7b 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -1619,6 +1619,7 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, /* Choose rate table first */ if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) || + (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) || (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) { rate_table = ath_choose_rate_table(sc, sband->band, sta->ht_cap.ht_supported, -- GitLab From 98dfaa577855a551e798e3a99b934386698d2026 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Fri, 20 Mar 2009 23:46:11 -0400 Subject: [PATCH 4900/4982] mac80211_hwsim: let the reg workqueue breathe when regtest is set Without this the regulatory domain isn't seen and we end up intersecting for each request (each radio). Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 2368b7f825a..55116102475 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -1041,6 +1041,9 @@ static int __init init_mac80211_hwsim(void) break; } + /* give the regulatory workqueue a chance to run */ + if (regtest) + schedule_timeout_interruptible(1); err = ieee80211_register_hw(hw); if (err < 0) { printk(KERN_DEBUG "mac80211_hwsim: " -- GitLab From 2e097dc65673ed421bbc2e49f52c125aa43a8ee6 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Fri, 20 Mar 2009 23:53:04 -0400 Subject: [PATCH 4901/4982] cfg80211: force last_request to be set for OLD_REG if regdom is EU Although EU is a bogus alpha2 we need to process the send request as our code depends on last_request being set. Cc: stable@kernel.org Reported-by: Quentin Armitage Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index eb8b8ed1615..ead9dccb547 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -2135,11 +2135,14 @@ int regulatory_init(void) /* * The old code still requests for a new regdomain and if * you have CRDA you get it updated, otherwise you get - * stuck with the static values. We ignore "EU" code as - * that is not a valid ISO / IEC 3166 alpha2 + * stuck with the static values. Since "EU" is not a valid + * ISO / IEC 3166 alpha2 code we can't expect userpace to + * give us a regulatory domain for it. We need last_request + * iniitalized though so lets just send a request which we + * know will be ignored... this crap will be removed once + * OLD_REG dies. */ - if (ieee80211_regdom[0] != 'E' || ieee80211_regdom[1] != 'U') - err = regulatory_hint_core(ieee80211_regdom); + err = regulatory_hint_core(ieee80211_regdom); #else cfg80211_regdomain = cfg80211_world_regdom; -- GitLab From cc0b6fe88e99096868bdbacbf486c97299533b5a Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Fri, 20 Mar 2009 23:53:05 -0400 Subject: [PATCH 4902/4982] cfg80211: fix incorrect assumption on last_request for 11d The incorrect assumption is the last regulatory request (last_request) is always a country IE when processing country IEs. Although this is true 99% of the time the first time this happens this could not be true. This fixes an oops in the branch check for the last_request when accessing drv_last_ie. The access was done under the assumption the struct won't be null. Note to stable: to port to 29 replace as follows, only 29 has country IE code: s|NL80211_REGDOM_SET_BY_COUNTRY_IE|REGDOM_SET_BY_COUNTRY_IE Cc: stable@kernel.org Reported-by: Quentin Armitage Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index ead9dccb547..9afc9168748 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1601,6 +1601,10 @@ static bool reg_same_country_ie_hint(struct wiphy *wiphy, assert_cfg80211_lock(); + if (unlikely(last_request->initiator != + NL80211_REGDOM_SET_BY_COUNTRY_IE)) + return false; + request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); if (!request_wiphy) @@ -1663,7 +1667,9 @@ void regulatory_hint_11d(struct wiphy *wiphy, * we optimize an early check to exit out early if we don't have to * do anything */ - if (likely(wiphy_idx_valid(last_request->wiphy_idx))) { + if (likely(last_request->initiator == + NL80211_REGDOM_SET_BY_COUNTRY_IE && + wiphy_idx_valid(last_request->wiphy_idx))) { struct cfg80211_registered_device *drv_last_ie; drv_last_ie = -- GitLab From 6ee7d33056f6e6fc7437d980dcc741816deedd0f Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Fri, 20 Mar 2009 23:53:06 -0400 Subject: [PATCH 4903/4982] cfg80211: make regdom module parameter available oustide of OLD_REG It seems a few users are using this module parameter although its not recommended. People are finding it useful despite there being utilities for setting this in userspace. I'm not aware of any distribution using this though. Until userspace and distributions catch up with a default userspace automatic replacement (GeoClue integration would be nirvana) we copy the ieee80211_regdom module parameter from OLD_REG to the new reg code to help these users migrate. Users who are using the non-valid ISO / IEC 3166 alpha "EU" in their ieee80211_regdom module parameter and migrate to non-OLD_REG enabled system will world roam. This also schedules removal of this same ieee80211_regdom module parameter circa March 2010. Hope is by then nirvana is reached and users will abandoned the module parameter completely. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- Documentation/feature-removal-schedule.txt | 30 +++++++++++++++++++--- net/wireless/reg.c | 7 ++++- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index e47c0ff8ba7..8365f52a354 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -6,7 +6,31 @@ be removed from this file. --------------------------- -What: old static regulatory information and ieee80211_regdom module parameter +What: The ieee80211_regdom module parameter +When: March 2010 + +Why: This was inherited by the CONFIG_WIRELESS_OLD_REGULATORY code, + and currently serves as an option for users to define an + ISO / IEC 3166 alpha2 code for the country they are currently + present in. Although there are userspace API replacements for this + through nl80211 distributions haven't yet caught up with implementing + decent alternatives through standard GUIs. Although available as an + option through iw or wpa_supplicant its just a matter of time before + distributions pick up good GUI options for this. The ideal solution + would actually consist of intelligent designs which would do this for + the user automatically even when travelling through different countries. + Until then we leave this module parameter as a compromise. + + When userspace improves with reasonable widely-available alternatives for + this we will no longer need this module parameter. This entry hopes that + by the super-futuristically looking date of "March 2010" we will have + such replacements widely available. + +Who: Luis R. Rodriguez + +--------------------------- + +What: old static regulatory information When: 2.6.29 Why: The old regulatory infrastructure has been replaced with a new one which does not require statically defined regulatory domains. We do @@ -17,9 +41,7 @@ Why: The old regulatory infrastructure has been replaced with a new one * JP * EU and used by default the US when CONFIG_WIRELESS_OLD_REGULATORY was - set. We also kept around the ieee80211_regdom module parameter in case - some applications were relying on it. Changing regulatory domains - can now be done instead by using nl80211, as is done with iw. + set. Who: Luis R. Rodriguez --------------------------- diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 9afc9168748..ac048a158d8 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -122,9 +122,14 @@ static const struct ieee80211_regdomain *cfg80211_world_regdom = #ifdef CONFIG_WIRELESS_OLD_REGULATORY static char *ieee80211_regdom = "US"; +#else +static char *ieee80211_regdom = "00"; +#endif + module_param(ieee80211_regdom, charp, 0444); MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); +#ifdef CONFIG_WIRELESS_OLD_REGULATORY /* * We assume 40 MHz bandwidth for the old regulatory work. * We make emphasis we are using the exact same frequencies @@ -2152,7 +2157,7 @@ int regulatory_init(void) #else cfg80211_regdomain = cfg80211_world_regdom; - err = regulatory_hint_core("00"); + err = regulatory_hint_core(ieee80211_regdom); #endif if (err) { if (err == -ENOMEM) -- GitLab From 86f04680df4a136a4a90501572dc2f31f8426581 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Fri, 20 Mar 2009 23:53:07 -0400 Subject: [PATCH 4904/4982] cfg80211: remove code about country IE support with OLD_REG We had left in code to allow interested developers to add support for parsing country IEs when OLD_REG was enabled. This never happened and since we're going to remove OLD_REG lets just remove these comments and code for it. This code path was never being entered so this has no functional change. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index ac048a158d8..6327e1617ac 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1420,16 +1420,6 @@ new_request: return r; } - /* - * Note: When CONFIG_WIRELESS_OLD_REGULATORY is enabled - * AND if CRDA is NOT present nothing will happen, if someone - * wants to bother with 11d with OLD_REG you can add a timer. - * If after x amount of time nothing happens you can call: - * - * return set_regdom(country_ie_regdomain); - * - * to intersect with the static rd - */ return call_crda(last_request->alpha2); } @@ -2033,28 +2023,21 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) */ BUG_ON(!country_ie_regdomain); + BUG_ON(rd == country_ie_regdomain); - if (rd != country_ie_regdomain) { - /* - * Intersect what CRDA returned and our what we - * had built from the Country IE received - */ + /* + * Intersect what CRDA returned and our what we + * had built from the Country IE received + */ - intersected_rd = regdom_intersect(rd, country_ie_regdomain); + intersected_rd = regdom_intersect(rd, country_ie_regdomain); - reg_country_ie_process_debug(rd, country_ie_regdomain, - intersected_rd); + reg_country_ie_process_debug(rd, + country_ie_regdomain, + intersected_rd); - kfree(country_ie_regdomain); - country_ie_regdomain = NULL; - } else { - /* - * This would happen when CRDA was not present and - * OLD_REGULATORY was enabled. We intersect our Country - * IE rd and what was set on cfg80211 originally - */ - intersected_rd = regdom_intersect(rd, cfg80211_regdomain); - } + kfree(country_ie_regdomain); + country_ie_regdomain = NULL; if (!intersected_rd) return -EINVAL; -- GitLab From ac7f9cfa2c3b810e0adfb889ad407a8c79a84dbe Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 21 Mar 2009 17:07:59 +0100 Subject: [PATCH 4905/4982] cfg80211: accept no-op interface mode changes When somebody tries to set the interface mode to the existing mode, don't ask the driver but silently accept the setting. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 28 +++++++++++++++++++++------- net/wireless/wext-compat.c | 11 +++++++++-- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index a7d0b94f6b5..8808431bd58 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -607,6 +607,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) enum nl80211_iftype type; struct net_device *dev; u32 _flags, *flags = NULL; + bool change = false; memset(¶ms, 0, sizeof(params)); @@ -620,11 +621,17 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) type = dev->ieee80211_ptr->iftype; dev_put(dev); - err = -EINVAL; if (info->attrs[NL80211_ATTR_IFTYPE]) { - type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); - if (type > NL80211_IFTYPE_MAX) + enum nl80211_iftype ntype; + + ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); + if (type != ntype) + change = true; + type = ntype; + if (type > NL80211_IFTYPE_MAX) { + err = -EINVAL; goto unlock; + } } if (!drv->ops->change_virtual_intf || @@ -640,6 +647,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) } params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); + change = true; } if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) { @@ -649,12 +657,18 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) } err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS], &_flags); - if (!err) - flags = &_flags; + if (err) + goto unlock; + + flags = &_flags; + change = true; } - err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, - type, flags, ¶ms); + if (change) + err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, + type, flags, ¶ms); + else + err = 0; dev = __dev_get_by_index(&init_net, ifindex); WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type)); diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index b84a9b4fe96..0fd1db6e95b 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -66,6 +66,7 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, struct cfg80211_registered_device *rdev; struct vif_params vifparams; enum nl80211_iftype type; + int ret; if (!wdev) return -EOPNOTSUPP; @@ -96,10 +97,16 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, return -EINVAL; } + if (type == wdev->iftype) + return 0; + memset(&vifparams, 0, sizeof(vifparams)); - return rdev->ops->change_virtual_intf(wdev->wiphy, dev->ifindex, type, - NULL, &vifparams); + ret = rdev->ops->change_virtual_intf(wdev->wiphy, dev->ifindex, type, + NULL, &vifparams); + WARN_ON(!ret && wdev->iftype != type); + + return ret; } EXPORT_SYMBOL(cfg80211_wext_siwmode); -- GitLab From 7986cf9581767d250ca0e5a554541bb276e08d21 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 21 Mar 2009 17:08:43 +0100 Subject: [PATCH 4906/4982] mac80211: remove mixed-cell and userspace MLME code Neither can currently be set from userspace, so there's no regression potential, and neither will be supported from userspace since the new userspace APIs allow the SME, which is in userspace, to control all we need. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 9 ++++----- net/mac80211/iface.c | 3 +-- net/mac80211/mlme.c | 3 +-- net/mac80211/rx.c | 13 ++++--------- net/mac80211/wext.c | 17 +---------------- 5 files changed, 11 insertions(+), 34 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index f69e84ab961..564167fbb9a 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -247,8 +247,9 @@ struct mesh_preq_queue { #define IEEE80211_STA_ASSOCIATED BIT(4) #define IEEE80211_STA_PROBEREQ_POLL BIT(5) #define IEEE80211_STA_CREATE_IBSS BIT(6) -#define IEEE80211_STA_MIXED_CELL BIT(7) +/* hole at 7, please re-use */ #define IEEE80211_STA_WMM_ENABLED BIT(8) +/* hole at 9, please re-use */ #define IEEE80211_STA_AUTO_SSID_SEL BIT(10) #define IEEE80211_STA_AUTO_BSSID_SEL BIT(11) #define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12) @@ -411,7 +412,6 @@ struct ieee80211_if_mesh { * * @IEEE80211_SDATA_ALLMULTI: interface wants all multicast packets * @IEEE80211_SDATA_PROMISC: interface is promisc - * @IEEE80211_SDATA_USERSPACE_MLME: userspace MLME is active * @IEEE80211_SDATA_OPERATING_GMODE: operating in G-only mode * @IEEE80211_SDATA_DONT_BRIDGE_PACKETS: bridge packets between * associated stations and deliver multicast frames both @@ -420,9 +420,8 @@ struct ieee80211_if_mesh { enum ieee80211_sub_if_data_flags { IEEE80211_SDATA_ALLMULTI = BIT(0), IEEE80211_SDATA_PROMISC = BIT(1), - IEEE80211_SDATA_USERSPACE_MLME = BIT(2), - IEEE80211_SDATA_OPERATING_GMODE = BIT(3), - IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(4), + IEEE80211_SDATA_OPERATING_GMODE = BIT(2), + IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(3), }; struct ieee80211_sub_if_data { diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 34f4798a98f..dd2a276fa8c 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -261,8 +261,7 @@ static int ieee80211_open(struct net_device *dev) ieee80211_bss_info_change_notify(sdata, changed); ieee80211_enable_keys(sdata); - if (sdata->vif.type == NL80211_IFTYPE_STATION && - !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)) + if (sdata->vif.type == NL80211_IFTYPE_STATION) netif_carrier_off(dev); else netif_carrier_on(dev); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index b0808efcedf..c05be09b9c6 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -849,8 +849,7 @@ static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata) int wep_privacy; int privacy_invoked; - if (!ifmgd || (ifmgd->flags & (IEEE80211_STA_MIXED_CELL | - IEEE80211_STA_EXT_SME))) + if (!ifmgd || (ifmgd->flags & IEEE80211_STA_EXT_SME)) return 0; bss = ieee80211_rx_bss_get(local, ifmgd->bssid, diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index fcc0a599579..47d395a5192 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1877,18 +1877,13 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) if (ieee80211_vif_is_mesh(&sdata->vif)) return ieee80211_mesh_rx_mgmt(sdata, rx->skb, rx->status); - if (sdata->vif.type != NL80211_IFTYPE_STATION && - sdata->vif.type != NL80211_IFTYPE_ADHOC) - return RX_DROP_MONITOR; - + if (sdata->vif.type != NL80211_IFTYPE_ADHOC) + return ieee80211_ibss_rx_mgmt(sdata, rx->skb, rx->status); - if (sdata->vif.type == NL80211_IFTYPE_STATION) { - if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) - return RX_DROP_MONITOR; + if (sdata->vif.type == NL80211_IFTYPE_STATION) return ieee80211_sta_rx_mgmt(sdata, rx->skb, rx->status); - } - return ieee80211_ibss_rx_mgmt(sdata, rx->skb, rx->status); + return RX_DROP_MONITOR; } static void ieee80211_rx_michael_mic_report(struct net_device *dev, diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index ce21d66b102..deb4ecec122 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -129,9 +129,6 @@ static int ieee80211_ioctl_siwgenie(struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) - return -EOPNOTSUPP; - if (sdata->vif.type == NL80211_IFTYPE_STATION) { int ret = ieee80211_sta_set_extra_ie(sdata, extra, data->length); if (ret) @@ -208,14 +205,6 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type == NL80211_IFTYPE_STATION) { - if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) { - if (len > IEEE80211_MAX_SSID_LEN) - return -EINVAL; - memcpy(sdata->u.mgd.ssid, ssid, len); - sdata->u.mgd.ssid_len = len; - return 0; - } - if (data->flags) sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL; else @@ -274,11 +263,7 @@ static int ieee80211_ioctl_siwap(struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type == NL80211_IFTYPE_STATION) { int ret; - if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) { - memcpy(sdata->u.mgd.bssid, (u8 *) &ap_addr->sa_data, - ETH_ALEN); - return 0; - } + if (is_zero_ether_addr((u8 *) &ap_addr->sa_data)) sdata->u.mgd.flags |= IEEE80211_STA_AUTO_BSSID_SEL | IEEE80211_STA_AUTO_CHANNEL_SEL; -- GitLab From 23b53f4f55d833ecc5a11b5fba646c78d3876927 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 21 Mar 2009 23:04:48 +0100 Subject: [PATCH 4907/4982] ar9170: hardware and eeprom header files hardware / firmware interface definitions for Atheros' AR9170 based devices. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ar9170/eeprom.h | 179 ++++++++++++ drivers/net/wireless/ar9170/hw.h | 406 +++++++++++++++++++++++++++ 2 files changed, 585 insertions(+) create mode 100644 drivers/net/wireless/ar9170/eeprom.h create mode 100644 drivers/net/wireless/ar9170/hw.h diff --git a/drivers/net/wireless/ar9170/eeprom.h b/drivers/net/wireless/ar9170/eeprom.h new file mode 100644 index 00000000000..d2c8cc83f1d --- /dev/null +++ b/drivers/net/wireless/ar9170/eeprom.h @@ -0,0 +1,179 @@ +/* + * Atheros AR9170 driver + * + * EEPROM layout + * + * Copyright 2008, Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, see + * http://www.gnu.org/licenses/. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * Copyright (c) 2007-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef __AR9170_EEPROM_H +#define __AR9170_EEPROM_H + +#define AR5416_MAX_CHAINS 2 +#define AR5416_MODAL_SPURS 5 + +struct ar9170_eeprom_modal { + __le32 antCtrlChain[AR5416_MAX_CHAINS]; + __le32 antCtrlCommon; + s8 antennaGainCh[AR5416_MAX_CHAINS]; + u8 switchSettling; + u8 txRxAttenCh[AR5416_MAX_CHAINS]; + u8 rxTxMarginCh[AR5416_MAX_CHAINS]; + s8 adcDesiredSize; + s8 pgaDesiredSize; + u8 xlnaGainCh[AR5416_MAX_CHAINS]; + u8 txEndToXpaOff; + u8 txEndToRxOn; + u8 txFrameToXpaOn; + u8 thresh62; + s8 noiseFloorThreshCh[AR5416_MAX_CHAINS]; + u8 xpdGain; + u8 xpd; + s8 iqCalICh[AR5416_MAX_CHAINS]; + s8 iqCalQCh[AR5416_MAX_CHAINS]; + u8 pdGainOverlap; + u8 ob; + u8 db; + u8 xpaBiasLvl; + u8 pwrDecreaseFor2Chain; + u8 pwrDecreaseFor3Chain; + u8 txFrameToDataStart; + u8 txFrameToPaOn; + u8 ht40PowerIncForPdadc; + u8 bswAtten[AR5416_MAX_CHAINS]; + u8 bswMargin[AR5416_MAX_CHAINS]; + u8 swSettleHt40; + u8 reserved[22]; + struct spur_channel { + __le16 spurChan; + u8 spurRangeLow; + u8 spurRangeHigh; + } __packed spur_channels[AR5416_MODAL_SPURS]; +} __packed; + +#define AR5416_NUM_PD_GAINS 4 +#define AR5416_PD_GAIN_ICEPTS 5 + +struct ar9170_calibration_data_per_freq { + u8 pwr_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; + u8 vpd_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; +} __packed; + +#define AR5416_NUM_5G_CAL_PIERS 8 +#define AR5416_NUM_2G_CAL_PIERS 4 + +#define AR5416_NUM_5G_TARGET_PWRS 8 +#define AR5416_NUM_2G_CCK_TARGET_PWRS 3 +#define AR5416_NUM_2G_OFDM_TARGET_PWRS 4 +#define AR5416_MAX_NUM_TGT_PWRS 8 + +struct ar9170_calibration_target_power_legacy { + u8 freq; + u8 power[4]; +} __packed; + +struct ar9170_calibration_target_power_ht { + u8 freq; + u8 power[8]; +} __packed; + +#define AR5416_NUM_CTLS 24 + +struct ar9170_calctl_edges { + u8 channel; +#define AR9170_CALCTL_EDGE_FLAGS 0xC0 + u8 power_flags; +} __packed; + +#define AR5416_NUM_BAND_EDGES 8 + +struct ar9170_calctl_data { + struct ar9170_calctl_edges + control_edges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES]; +} __packed; + + +struct ar9170_eeprom { + __le16 length; + __le16 checksum; + __le16 version; + u8 operating_flags; +#define AR9170_OPFLAG_5GHZ 1 +#define AR9170_OPFLAG_2GHZ 2 + u8 misc; + __le16 reg_domain[2]; + u8 mac_address[6]; + u8 rx_mask; + u8 tx_mask; + __le16 rf_silent; + __le16 bluetooth_options; + __le16 device_capabilities; + __le32 build_number; + u8 deviceType; + u8 reserved[33]; + + u8 customer_data[64]; + + struct ar9170_eeprom_modal + modal_header[2]; + + u8 cal_freq_pier_5G[AR5416_NUM_5G_CAL_PIERS]; + u8 cal_freq_pier_2G[AR5416_NUM_2G_CAL_PIERS]; + + struct ar9170_calibration_data_per_freq + cal_pier_data_5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS], + cal_pier_data_2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS]; + + /* power calibration data */ + struct ar9170_calibration_target_power_legacy + cal_tgt_pwr_5G[AR5416_NUM_5G_TARGET_PWRS]; + struct ar9170_calibration_target_power_ht + cal_tgt_pwr_5G_ht20[AR5416_NUM_5G_TARGET_PWRS], + cal_tgt_pwr_5G_ht40[AR5416_NUM_5G_TARGET_PWRS]; + + struct ar9170_calibration_target_power_legacy + cal_tgt_pwr_2G_cck[AR5416_NUM_2G_CCK_TARGET_PWRS], + cal_tgt_pwr_2G_ofdm[AR5416_NUM_2G_OFDM_TARGET_PWRS]; + struct ar9170_calibration_target_power_ht + cal_tgt_pwr_2G_ht20[AR5416_NUM_2G_OFDM_TARGET_PWRS], + cal_tgt_pwr_2G_ht40[AR5416_NUM_2G_OFDM_TARGET_PWRS]; + + /* conformance testing limits */ + u8 ctl_index[AR5416_NUM_CTLS]; + struct ar9170_calctl_data + ctl_data[AR5416_NUM_CTLS]; + + u8 pad; + __le16 subsystem_id; +} __packed; + +#endif /* __AR9170_EEPROM_H */ diff --git a/drivers/net/wireless/ar9170/hw.h b/drivers/net/wireless/ar9170/hw.h new file mode 100644 index 00000000000..ad205f82f60 --- /dev/null +++ b/drivers/net/wireless/ar9170/hw.h @@ -0,0 +1,406 @@ +/* + * Atheros AR9170 driver + * + * Hardware-specific definitions + * + * Copyright 2008, Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, see + * http://www.gnu.org/licenses/. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * Copyright (c) 2007-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef __AR9170_HW_H +#define __AR9170_HW_H + +#define AR9170_MAX_CMD_LEN 64 + +enum ar9170_cmd { + AR9170_CMD_RREG = 0x00, + AR9170_CMD_WREG = 0x01, + AR9170_CMD_RMEM = 0x02, + AR9170_CMD_WMEM = 0x03, + AR9170_CMD_BITAND = 0x04, + AR9170_CMD_BITOR = 0x05, + AR9170_CMD_EKEY = 0x28, + AR9170_CMD_DKEY = 0x29, + AR9170_CMD_FREQUENCY = 0x30, + AR9170_CMD_RF_INIT = 0x31, + AR9170_CMD_SYNTH = 0x32, + AR9170_CMD_FREQ_START = 0x33, + AR9170_CMD_ECHO = 0x80, + AR9170_CMD_TALLY = 0x81, + AR9170_CMD_TALLY_APD = 0x82, + AR9170_CMD_CONFIG = 0x83, + AR9170_CMD_RESET = 0x90, + AR9170_CMD_DKRESET = 0x91, + AR9170_CMD_DKTX_STATUS = 0x92, + AR9170_CMD_FDC = 0xA0, + AR9170_CMD_WREEPROM = 0xB0, + AR9170_CMD_WFLASH = 0xB0, + AR9170_CMD_FLASH_ERASE = 0xB1, + AR9170_CMD_FLASH_PROG = 0xB2, + AR9170_CMD_FLASH_CHKSUM = 0xB3, + AR9170_CMD_FLASH_READ = 0xB4, + AR9170_CMD_FW_DL_INIT = 0xB5, + AR9170_CMD_MEM_WREEPROM = 0xBB, +}; + +/* endpoints */ +#define AR9170_EP_TX 1 +#define AR9170_EP_RX 2 +#define AR9170_EP_IRQ 3 +#define AR9170_EP_CMD 4 + +#define AR9170_EEPROM_START 0x1600 + +#define AR9170_GPIO_REG_BASE 0x1d0100 +#define AR9170_GPIO_REG_PORT_TYPE AR9170_GPIO_REG_BASE +#define AR9170_GPIO_REG_DATA (AR9170_GPIO_REG_BASE + 4) +#define AR9170_NUM_LEDS 2 + + +#define AR9170_USB_REG_BASE 0x1e1000 +#define AR9170_USB_REG_DMA_CTL (AR9170_USB_REG_BASE + 0x108) +#define AR9170_DMA_CTL_ENABLE_TO_DEVICE 0x1 +#define AR9170_DMA_CTL_ENABLE_FROM_DEVICE 0x2 +#define AR9170_DMA_CTL_HIGH_SPEED 0x4 +#define AR9170_DMA_CTL_PACKET_MODE 0x8 + +#define AR9170_USB_REG_MAX_AGG_UPLOAD (AR9170_USB_REG_BASE + 0x110) +#define AR9170_USB_REG_UPLOAD_TIME_CTL (AR9170_USB_REG_BASE + 0x114) + + + +#define AR9170_MAC_REG_BASE 0x1c3000 + +#define AR9170_MAC_REG_TSF_L (AR9170_MAC_REG_BASE + 0x514) +#define AR9170_MAC_REG_TSF_H (AR9170_MAC_REG_BASE + 0x518) + +#define AR9170_MAC_REG_ATIM_WINDOW (AR9170_MAC_REG_BASE + 0x51C) +#define AR9170_MAC_REG_BCN_PERIOD (AR9170_MAC_REG_BASE + 0x520) +#define AR9170_MAC_REG_PRETBTT (AR9170_MAC_REG_BASE + 0x524) + +#define AR9170_MAC_REG_MAC_ADDR_L (AR9170_MAC_REG_BASE + 0x610) +#define AR9170_MAC_REG_MAC_ADDR_H (AR9170_MAC_REG_BASE + 0x614) +#define AR9170_MAC_REG_BSSID_L (AR9170_MAC_REG_BASE + 0x618) +#define AR9170_MAC_REG_BSSID_H (AR9170_MAC_REG_BASE + 0x61c) + +#define AR9170_MAC_REG_GROUP_HASH_TBL_L (AR9170_MAC_REG_BASE + 0x624) +#define AR9170_MAC_REG_GROUP_HASH_TBL_H (AR9170_MAC_REG_BASE + 0x628) + +#define AR9170_MAC_REG_RX_TIMEOUT (AR9170_MAC_REG_BASE + 0x62C) + +#define AR9170_MAC_REG_BASIC_RATE (AR9170_MAC_REG_BASE + 0x630) +#define AR9170_MAC_REG_MANDATORY_RATE (AR9170_MAC_REG_BASE + 0x634) +#define AR9170_MAC_REG_RTS_CTS_RATE (AR9170_MAC_REG_BASE + 0x638) +#define AR9170_MAC_REG_BACKOFF_PROTECT (AR9170_MAC_REG_BASE + 0x63c) +#define AR9170_MAC_REG_RX_THRESHOLD (AR9170_MAC_REG_BASE + 0x640) +#define AR9170_MAC_REG_RX_PE_DELAY (AR9170_MAC_REG_BASE + 0x64C) + +#define AR9170_MAC_REG_DYNAMIC_SIFS_ACK (AR9170_MAC_REG_BASE + 0x658) +#define AR9170_MAC_REG_SNIFFER (AR9170_MAC_REG_BASE + 0x674) +#define AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC BIT(0) +#define AR9170_MAC_REG_SNIFFER_DEFAULTS 0x02000000 +#define AR9170_MAC_REG_ENCRYPTION (AR9170_MAC_REG_BASE + 0x678) +#define AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE BIT(3) +#define AR9170_MAC_REG_ENCRYPTION_DEFAULTS 0x70 + +#define AR9170_MAC_REG_MISC_680 (AR9170_MAC_REG_BASE + 0x680) +#define AR9170_MAC_REG_TX_UNDERRUN (AR9170_MAC_REG_BASE + 0x688) + +#define AR9170_MAC_REG_FRAMETYPE_FILTER (AR9170_MAC_REG_BASE + 0x68c) +#define AR9170_MAC_REG_FTF_ASSOC_REQ BIT(0) +#define AR9170_MAC_REG_FTF_ASSOC_RESP BIT(1) +#define AR9170_MAC_REG_FTF_REASSOC_REQ BIT(2) +#define AR9170_MAC_REG_FTF_REASSOC_RESP BIT(3) +#define AR9170_MAC_REG_FTF_PRB_REQ BIT(4) +#define AR9170_MAC_REG_FTF_PRB_RESP BIT(5) +#define AR9170_MAC_REG_FTF_BIT6 BIT(6) +#define AR9170_MAC_REG_FTF_BIT7 BIT(7) +#define AR9170_MAC_REG_FTF_BEACON BIT(8) +#define AR9170_MAC_REG_FTF_ATIM BIT(9) +#define AR9170_MAC_REG_FTF_DEASSOC BIT(10) +#define AR9170_MAC_REG_FTF_AUTH BIT(11) +#define AR9170_MAC_REG_FTF_DEAUTH BIT(12) +#define AR9170_MAC_REG_FTF_BIT13 BIT(13) +#define AR9170_MAC_REG_FTF_BIT14 BIT(14) +#define AR9170_MAC_REG_FTF_BIT15 BIT(15) +#define AR9170_MAC_REG_FTF_BAR BIT(24) +#define AR9170_MAC_REG_FTF_BIT25 BIT(25) +#define AR9170_MAC_REG_FTF_PSPOLL BIT(26) +#define AR9170_MAC_REG_FTF_RTS BIT(27) +#define AR9170_MAC_REG_FTF_CTS BIT(28) +#define AR9170_MAC_REG_FTF_ACK BIT(29) +#define AR9170_MAC_REG_FTF_CFE BIT(30) +#define AR9170_MAC_REG_FTF_CFE_ACK BIT(31) +#define AR9170_MAC_REG_FTF_DEFAULTS 0x0500ffff +#define AR9170_MAC_REG_FTF_MONITOR 0xfd00ffff + +#define AR9170_MAC_REG_RX_TOTAL (AR9170_MAC_REG_BASE + 0x6A0) +#define AR9170_MAC_REG_RX_CRC32 (AR9170_MAC_REG_BASE + 0x6A4) +#define AR9170_MAC_REG_RX_CRC16 (AR9170_MAC_REG_BASE + 0x6A8) +#define AR9170_MAC_REG_RX_ERR_DECRYPTION_UNI (AR9170_MAC_REG_BASE + 0x6AC) +#define AR9170_MAC_REG_RX_OVERRUN (AR9170_MAC_REG_BASE + 0x6B0) +#define AR9170_MAC_REG_RX_ERR_DECRYPTION_MUL (AR9170_MAC_REG_BASE + 0x6BC) +#define AR9170_MAC_REG_TX_RETRY (AR9170_MAC_REG_BASE + 0x6CC) +#define AR9170_MAC_REG_TX_TOTAL (AR9170_MAC_REG_BASE + 0x6F4) + + +#define AR9170_MAC_REG_ACK_EXTENSION (AR9170_MAC_REG_BASE + 0x690) +#define AR9170_MAC_REG_EIFS_AND_SIFS (AR9170_MAC_REG_BASE + 0x698) + +#define AR9170_MAC_REG_SLOT_TIME (AR9170_MAC_REG_BASE + 0x6F0) + +#define AR9170_MAC_REG_POWERMANAGEMENT (AR9170_MAC_REG_BASE + 0x700) +#define AR9170_MAC_REG_POWERMGT_IBSS 0xe0 +#define AR9170_MAC_REG_POWERMGT_AP 0xa1 +#define AR9170_MAC_REG_POWERMGT_STA 0x2 +#define AR9170_MAC_REG_POWERMGT_AP_WDS 0x3 +#define AR9170_MAC_REG_POWERMGT_DEFAULTS (0xf << 24) + +#define AR9170_MAC_REG_ROLL_CALL_TBL_L (AR9170_MAC_REG_BASE + 0x704) +#define AR9170_MAC_REG_ROLL_CALL_TBL_H (AR9170_MAC_REG_BASE + 0x708) + +#define AR9170_MAC_REG_AC0_CW (AR9170_MAC_REG_BASE + 0xB00) +#define AR9170_MAC_REG_AC1_CW (AR9170_MAC_REG_BASE + 0xB04) +#define AR9170_MAC_REG_AC2_CW (AR9170_MAC_REG_BASE + 0xB08) +#define AR9170_MAC_REG_AC3_CW (AR9170_MAC_REG_BASE + 0xB0C) +#define AR9170_MAC_REG_AC4_CW (AR9170_MAC_REG_BASE + 0xB10) +#define AR9170_MAC_REG_AC1_AC0_AIFS (AR9170_MAC_REG_BASE + 0xB14) +#define AR9170_MAC_REG_AC3_AC2_AIFS (AR9170_MAC_REG_BASE + 0xB18) + +#define AR9170_MAC_REG_RETRY_MAX (AR9170_MAC_REG_BASE + 0xB28) + +#define AR9170_MAC_REG_FCS_SELECT (AR9170_MAC_REG_BASE + 0xBB0) +#define AR9170_MAC_FCS_SWFCS 0x1 +#define AR9170_MAC_FCS_FIFO_PROT 0x4 + + +#define AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND (AR9170_MAC_REG_BASE + 0xB30) + +#define AR9170_MAC_REG_AC1_AC0_TXOP (AR9170_MAC_REG_BASE + 0xB44) +#define AR9170_MAC_REG_AC3_AC2_TXOP (AR9170_MAC_REG_BASE + 0xB48) + +#define AR9170_MAC_REG_ACK_TABLE (AR9170_MAC_REG_BASE + 0xC00) +#define AR9170_MAC_REG_AMPDU_RX_THRESH (AR9170_MAC_REG_BASE + 0xC50) + +#define AR9170_MAC_REG_TXRX_MPI (AR9170_MAC_REG_BASE + 0xD7C) +#define AR9170_MAC_TXRX_MPI_TX_MPI_MASK 0x0000000f +#define AR9170_MAC_TXRX_MPI_TX_TO_MASK 0x0000fff0 +#define AR9170_MAC_TXRX_MPI_RX_MPI_MASK 0x000f0000 +#define AR9170_MAC_TXRX_MPI_RX_TO_MASK 0xfff00000 + +#define AR9170_MAC_REG_BCN_ADDR (AR9170_MAC_REG_BASE + 0xD84) +#define AR9170_MAC_REG_BCN_LENGTH (AR9170_MAC_REG_BASE + 0xD88) +#define AR9170_MAC_REG_BCN_PLCP (AR9170_MAC_REG_BASE + 0xD90) +#define AR9170_MAC_REG_BCN_CTRL (AR9170_MAC_REG_BASE + 0xD94) +#define AR9170_MAC_REG_BCN_HT1 (AR9170_MAC_REG_BASE + 0xDA0) +#define AR9170_MAC_REG_BCN_HT2 (AR9170_MAC_REG_BASE + 0xDA4) + + +#define AR9170_PWR_REG_BASE 0x1D4000 + +#define AR9170_PWR_REG_CLOCK_SEL (AR9170_PWR_REG_BASE + 0x008) +#define AR9170_PWR_CLK_AHB_40MHZ 0 +#define AR9170_PWR_CLK_AHB_20_22MHZ 1 +#define AR9170_PWR_CLK_AHB_40_44MHZ 2 +#define AR9170_PWR_CLK_AHB_80_88MHZ 3 +#define AR9170_PWR_CLK_DAC_160_INV_DLY 0x70 + + +/* put beacon here in memory */ +#define AR9170_BEACON_BUFFER_ADDRESS 0x117900 + + +struct ar9170_tx_control { + __le16 length; + __le16 mac_control; + __le32 phy_control; + u8 frame_data[0]; +} __packed; + +/* these are either-or */ +#define AR9170_TX_MAC_PROT_RTS 0x0001 +#define AR9170_TX_MAC_PROT_CTS 0x0002 + +#define AR9170_TX_MAC_NO_ACK 0x0004 +/* if unset, MAC will only do SIFS space before frame */ +#define AR9170_TX_MAC_BACKOFF 0x0008 +#define AR9170_TX_MAC_BURST 0x0010 +#define AR9170_TX_MAC_AGGR 0x0020 + +/* encryption is a two-bit field */ +#define AR9170_TX_MAC_ENCR_NONE 0x0000 +#define AR9170_TX_MAC_ENCR_RC4 0x0040 +#define AR9170_TX_MAC_ENCR_CENC 0x0080 +#define AR9170_TX_MAC_ENCR_AES 0x00c0 + +#define AR9170_TX_MAC_MMIC 0x0100 +#define AR9170_TX_MAC_HW_DURATION 0x0200 +#define AR9170_TX_MAC_QOS_SHIFT 10 +#define AR9170_TX_MAC_QOS_MASK (3 << AR9170_TX_MAC_QOS_SHIFT) +#define AR9170_TX_MAC_AGGR_QOS_BIT1 0x0400 +#define AR9170_TX_MAC_AGGR_QOS_BIT2 0x0800 +#define AR9170_TX_MAC_DISABLE_TXOP 0x1000 +#define AR9170_TX_MAC_TXOP_RIFS 0x2000 +#define AR9170_TX_MAC_IMM_AMPDU 0x4000 +#define AR9170_TX_MAC_RATE_PROBE 0x8000 + +/* either-or */ +#define AR9170_TX_PHY_MOD_CCK 0x00000000 +#define AR9170_TX_PHY_MOD_OFDM 0x00000001 +#define AR9170_TX_PHY_MOD_HT 0x00000002 + +/* depends on modulation */ +#define AR9170_TX_PHY_SHORT_PREAMBLE 0x00000004 +#define AR9170_TX_PHY_GREENFIELD 0x00000004 + +#define AR9170_TX_PHY_BW_SHIFT 3 +#define AR9170_TX_PHY_BW_MASK (3 << AR9170_TX_PHY_BW_SHIFT) +#define AR9170_TX_PHY_BW_20MHZ 0 +#define AR9170_TX_PHY_BW_40MHZ 2 +#define AR9170_TX_PHY_BW_40MHZ_DUP 3 + +#define AR9170_TX_PHY_TX_HEAVY_CLIP_SHIFT 6 +#define AR9170_TX_PHY_TX_HEAVY_CLIP_MASK (7 << AR9170_TX_PHY_TX_HEAVY_CLIP_SHIFT) + +#define AR9170_TX_PHY_TX_PWR_SHIFT 9 +#define AR9170_TX_PHY_TX_PWR_MASK (0x3f << AR9170_TX_PHY_TX_PWR_SHIFT) + +/* not part of the hw-spec */ +#define AR9170_TX_PHY_QOS_SHIFT 25 +#define AR9170_TX_PHY_QOS_MASK (3 << AR9170_TX_PHY_QOS_SHIFT) + +#define AR9170_TX_PHY_TXCHAIN_SHIFT 15 +#define AR9170_TX_PHY_TXCHAIN_MASK (7 << AR9170_TX_PHY_TXCHAIN_SHIFT) +#define AR9170_TX_PHY_TXCHAIN_1 1 +/* use for cck, ofdm 6/9/12/18/24 and HT if capable */ +#define AR9170_TX_PHY_TXCHAIN_2 5 + +#define AR9170_TX_PHY_MCS_SHIFT 18 +#define AR9170_TX_PHY_MCS_MASK (0x7f << AR9170_TX_PHY_MCS_SHIFT) + +#define AR9170_TX_PHY_SHORT_GI 0x80000000 + +struct ar9170_rx_head { + u8 plcp[12]; +}; + +struct ar9170_rx_tail { + union { + struct { + u8 rssi_ant0, rssi_ant1, rssi_ant2, + rssi_ant0x, rssi_ant1x, rssi_ant2x, + rssi_combined; + }; + u8 rssi[7]; + }; + + u8 evm_stream0[6], evm_stream1[6]; + u8 phy_err; + u8 SAidx, DAidx; + u8 error; + u8 status; +}; + +#define AR9170_ENC_ALG_NONE 0x0 +#define AR9170_ENC_ALG_WEP64 0x1 +#define AR9170_ENC_ALG_TKIP 0x2 +#define AR9170_ENC_ALG_AESCCMP 0x4 +#define AR9170_ENC_ALG_WEP128 0x5 +#define AR9170_ENC_ALG_WEP256 0x6 +#define AR9170_ENC_ALG_CENC 0x7 + +#define AR9170_RX_ENC_SOFTWARE 0x8 + +static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_tail *t) +{ + return (t->SAidx & 0xc0) >> 4 | + (t->DAidx & 0xc0) >> 6; +} + +#define AR9170_RX_STATUS_MODULATION_MASK 0x03 +#define AR9170_RX_STATUS_MODULATION_CCK 0x00 +#define AR9170_RX_STATUS_MODULATION_OFDM 0x01 +#define AR9170_RX_STATUS_MODULATION_HT 0x02 +#define AR9170_RX_STATUS_MODULATION_DUPOFDM 0x03 + +/* depends on modulation */ +#define AR9170_RX_STATUS_SHORT_PREAMBLE 0x08 +#define AR9170_RX_STATUS_GREENFIELD 0x08 + +#define AR9170_RX_STATUS_MPDU_MASK 0x30 +#define AR9170_RX_STATUS_MPDU_SINGLE 0x00 +#define AR9170_RX_STATUS_MPDU_FIRST 0x10 +#define AR9170_RX_STATUS_MPDU_MIDDLE 0x20 +#define AR9170_RX_STATUS_MPDU_LAST 0x30 + + +#define AR9170_RX_ERROR_RXTO 0x01 +#define AR9170_RX_ERROR_OVERRUN 0x02 +#define AR9170_RX_ERROR_DECRYPT 0x04 +#define AR9170_RX_ERROR_FCS 0x08 +#define AR9170_RX_ERROR_WRONG_RA 0x10 +#define AR9170_RX_ERROR_PLCP 0x20 +#define AR9170_RX_ERROR_MMIC 0x40 + +struct ar9170_cmd_tx_status { + __le16 unkn; + u8 dst[ETH_ALEN]; + __le32 rate; + __le16 status; +} __packed; + +#define AR9170_TX_STATUS_COMPLETE 0x00 +#define AR9170_TX_STATUS_RETRY 0x01 +#define AR9170_TX_STATUS_FAILED 0x02 + +struct ar9170_cmd_ba_failed_count { + __le16 failed; + __le16 rate; +} __packed; + +struct ar9170_cmd_response { + u8 flag; + u8 type; + + union { + struct ar9170_cmd_tx_status tx_status; + struct ar9170_cmd_ba_failed_count ba_fail_cnt; + u8 data[0]; + }; +} __packed; + +/* mac80211 queue to HW/FW map */ +static const u8 ar9170_qos_hwmap[4] = { 3, 2, 0, 1 }; + +/* HW/FW queue to mac80211 map */ +static const u8 ar9170_qos_mac80211map[4] = { 2, 3, 1, 0 }; + +#endif /* __AR9170_HW_H */ -- GitLab From e9348cdd280eb6a1d6d38fef513b578dc9ead363 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 21 Mar 2009 23:05:13 +0100 Subject: [PATCH 4908/4982] ar9170: ar9170: mac80211 interaction code This patch contains almost all mac80211 interaction code of AR9170. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ar9170/ar9170.h | 209 +++ drivers/net/wireless/ar9170/cmd.c | 130 ++ drivers/net/wireless/ar9170/cmd.h | 91 ++ drivers/net/wireless/ar9170/led.c | 171 +++ drivers/net/wireless/ar9170/main.c | 1776 ++++++++++++++++++++++++++ 5 files changed, 2377 insertions(+) create mode 100644 drivers/net/wireless/ar9170/ar9170.h create mode 100644 drivers/net/wireless/ar9170/cmd.c create mode 100644 drivers/net/wireless/ar9170/cmd.h create mode 100644 drivers/net/wireless/ar9170/led.c create mode 100644 drivers/net/wireless/ar9170/main.c diff --git a/drivers/net/wireless/ar9170/ar9170.h b/drivers/net/wireless/ar9170/ar9170.h new file mode 100644 index 00000000000..c49d7138d57 --- /dev/null +++ b/drivers/net/wireless/ar9170/ar9170.h @@ -0,0 +1,209 @@ +/* + * Atheros AR9170 driver + * + * Driver specific definitions + * + * Copyright 2008, Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, see + * http://www.gnu.org/licenses/. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * Copyright (c) 2007-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef __AR9170_H +#define __AR9170_H + +#include +#include +#include +#include +#ifdef CONFIG_AR9170_LEDS +#include +#endif /* CONFIG_AR9170_LEDS */ +#include "eeprom.h" +#include "hw.h" + +#define PAYLOAD_MAX (AR9170_MAX_CMD_LEN/4 - 1) + +enum ar9170_bw { + AR9170_BW_20, + AR9170_BW_40_BELOW, + AR9170_BW_40_ABOVE, + + __AR9170_NUM_BW, +}; + +enum ar9170_rf_init_mode { + AR9170_RFI_NONE, + AR9170_RFI_WARM, + AR9170_RFI_COLD, +}; + +#define AR9170_MAX_RX_BUFFER_SIZE 8192 + +#ifdef CONFIG_AR9170_LEDS +struct ar9170; + +struct ar9170_led { + struct ar9170 *ar; + struct led_classdev l; + char name[32]; + unsigned int toggled; + bool registered; +}; + +#endif /* CONFIG_AR9170_LEDS */ + +enum ar9170_device_state { + AR9170_UNKNOWN_STATE, + AR9170_STOPPED, + AR9170_IDLE, + AR9170_STARTED, + AR9170_ASSOCIATED, +}; + +struct ar9170 { + struct ieee80211_hw *hw; + struct mutex mutex; + enum ar9170_device_state state; + + int (*open)(struct ar9170 *); + void (*stop)(struct ar9170 *); + int (*tx)(struct ar9170 *, struct sk_buff *, bool, unsigned int); + int (*exec_cmd)(struct ar9170 *, enum ar9170_cmd, u32 , + void *, u32 , void *); + void (*callback_cmd)(struct ar9170 *, u32 , void *); + + /* interface mode settings */ + struct ieee80211_vif *vif; + u8 mac_addr[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + + /* beaconing */ + struct sk_buff *beacon; + struct work_struct beacon_work; + + /* cryptographic engine */ + u64 usedkeys; + bool rx_software_decryption; + bool disable_offload; + + /* filter settings */ + struct work_struct filter_config_work; + u64 cur_mc_hash, want_mc_hash; + u32 cur_filter, want_filter; + unsigned int filter_changed; + bool sniffer_enabled; + + /* PHY */ + struct ieee80211_channel *channel; + int noise[4]; + + /* power calibration data */ + u8 power_5G_leg[4]; + u8 power_2G_cck[4]; + u8 power_2G_ofdm[4]; + u8 power_5G_ht20[8]; + u8 power_5G_ht40[8]; + u8 power_2G_ht20[8]; + u8 power_2G_ht40[8]; + +#ifdef CONFIG_AR9170_LEDS + struct delayed_work led_work; + struct ar9170_led leds[AR9170_NUM_LEDS]; +#endif /* CONFIG_AR9170_LEDS */ + + /* qos queue settings */ + spinlock_t tx_stats_lock; + struct ieee80211_tx_queue_stats tx_stats[5]; + struct ieee80211_tx_queue_params edcf[5]; + + spinlock_t cmdlock; + __le32 cmdbuf[PAYLOAD_MAX + 1]; + + /* MAC statistics */ + struct ieee80211_low_level_stats stats; + + /* EEPROM */ + struct ar9170_eeprom eeprom; + + /* global tx status for unregistered Stations. */ + struct sk_buff_head global_tx_status; + struct sk_buff_head global_tx_status_waste; + struct delayed_work tx_status_janitor; +}; + +struct ar9170_sta_info { + struct sk_buff_head tx_status; +}; + +#define IS_STARTED(a) (a->state >= AR9170_STARTED) +#define IS_ACCEPTING_CMD(a) (a->state >= AR9170_IDLE) + +#define AR9170_FILTER_CHANGED_PROMISC BIT(0) +#define AR9170_FILTER_CHANGED_MULTICAST BIT(1) +#define AR9170_FILTER_CHANGED_FRAMEFILTER BIT(2) + +/* exported interface */ +void *ar9170_alloc(size_t priv_size); +int ar9170_register(struct ar9170 *ar, struct device *pdev); +void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb); +void ar9170_unregister(struct ar9170 *ar); +void ar9170_handle_tx_status(struct ar9170 *ar, struct sk_buff *skb, + bool update_statistics, u16 tx_status); + +/* MAC */ +int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb); +int ar9170_init_mac(struct ar9170 *ar); +int ar9170_set_qos(struct ar9170 *ar); +int ar9170_update_multicast(struct ar9170 *ar); +int ar9170_update_frame_filter(struct ar9170 *ar); +int ar9170_set_operating_mode(struct ar9170 *ar); +int ar9170_set_beacon_timers(struct ar9170 *ar); +int ar9170_set_hwretry_limit(struct ar9170 *ar, u32 max_retry); +int ar9170_update_beacon(struct ar9170 *ar); +void ar9170_new_beacon(struct work_struct *work); +int ar9170_upload_key(struct ar9170 *ar, u8 id, const u8 *mac, u8 ktype, + u8 keyidx, u8 *keydata, int keylen); +int ar9170_disable_key(struct ar9170 *ar, u8 id); + +/* LEDs */ +#ifdef CONFIG_AR9170_LEDS +int ar9170_register_leds(struct ar9170 *ar); +void ar9170_unregister_leds(struct ar9170 *ar); +#endif /* CONFIG_AR9170_LEDS */ +int ar9170_init_leds(struct ar9170 *ar); +int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state); + +/* PHY / RF */ +int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band); +int ar9170_init_rf(struct ar9170 *ar); +int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, + enum ar9170_rf_init_mode rfi, enum ar9170_bw bw); + +#endif /* __AR9170_H */ diff --git a/drivers/net/wireless/ar9170/cmd.c b/drivers/net/wireless/ar9170/cmd.c new file mode 100644 index 00000000000..fd5625c4e9d --- /dev/null +++ b/drivers/net/wireless/ar9170/cmd.c @@ -0,0 +1,130 @@ +/* + * Atheros AR9170 driver + * + * Basic HW register/memory/command access functions + * + * Copyright 2008, Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, see + * http://www.gnu.org/licenses/. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * Copyright (c) 2007-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ar9170.h" +#include "cmd.h" + +int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len) +{ + int err; + + if (unlikely(!IS_ACCEPTING_CMD(ar))) + return 0; + + err = ar->exec_cmd(ar, AR9170_CMD_WMEM, len, (u8 *) data, 0, NULL); + if (err) + printk(KERN_DEBUG "%s: writing memory failed\n", + wiphy_name(ar->hw->wiphy)); + return err; +} + +int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val) +{ + __le32 buf[2] = { + cpu_to_le32(reg), + cpu_to_le32(val), + }; + int err; + + if (unlikely(!IS_ACCEPTING_CMD(ar))) + return 0; + + err = ar->exec_cmd(ar, AR9170_CMD_WREG, sizeof(buf), + (u8 *) buf, 0, NULL); + if (err) + printk(KERN_DEBUG "%s: writing reg %#x (val %#x) failed\n", + wiphy_name(ar->hw->wiphy), reg, val); + return err; +} + +static int ar9170_read_mreg(struct ar9170 *ar, int nregs, + const u32 *regs, u32 *out) +{ + int i, err; + __le32 *offs, *res; + + if (unlikely(!IS_ACCEPTING_CMD(ar))) + return 0; + + /* abuse "out" for the register offsets, must be same length */ + offs = (__le32 *)out; + for (i = 0; i < nregs; i++) + offs[i] = cpu_to_le32(regs[i]); + + /* also use the same buffer for the input */ + res = (__le32 *)out; + + err = ar->exec_cmd(ar, AR9170_CMD_RREG, + 4 * nregs, (u8 *)offs, + 4 * nregs, (u8 *)res); + if (err) + return err; + + /* convert result to cpu endian */ + for (i = 0; i < nregs; i++) + out[i] = le32_to_cpu(res[i]); + + return 0; +} + +int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val) +{ + return ar9170_read_mreg(ar, 1, ®, val); +} + +int ar9170_echo_test(struct ar9170 *ar, u32 v) +{ + __le32 echobuf = cpu_to_le32(v); + __le32 echores; + int err; + + if (unlikely(!IS_ACCEPTING_CMD(ar))) + return -ENODEV; + + err = ar->exec_cmd(ar, AR9170_CMD_ECHO, + 4, (u8 *)&echobuf, + 4, (u8 *)&echores); + if (err) + return err; + + if (echobuf != echores) + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL_GPL(ar9170_echo_test); diff --git a/drivers/net/wireless/ar9170/cmd.h b/drivers/net/wireless/ar9170/cmd.h new file mode 100644 index 00000000000..a4f0e50e52b --- /dev/null +++ b/drivers/net/wireless/ar9170/cmd.h @@ -0,0 +1,91 @@ +/* + * Atheros AR9170 driver + * + * Basic HW register/memory/command access functions + * + * Copyright 2008, Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, see + * http://www.gnu.org/licenses/. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * Copyright (c) 2007-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef __CMD_H +#define __CMD_H + +#include "ar9170.h" + +/* basic HW access */ +int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len); +int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val); +int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val); +int ar9170_echo_test(struct ar9170 *ar, u32 v); + +/* + * Macros to facilitate writing multiple registers in a single + * write-combining USB command. Note that when the first group + * fails the whole thing will fail without any others attempted, + * but you won't know which write in the group failed. + */ +#define ar9170_regwrite_begin(ar) \ +do { \ + int __nreg = 0, __err = 0; \ + struct ar9170 *__ar = ar; + +#define ar9170_regwrite(r, v) do { \ + __ar->cmdbuf[2 * __nreg + 1] = cpu_to_le32(r); \ + __ar->cmdbuf[2 * __nreg + 2] = cpu_to_le32(v); \ + __nreg++; \ + if ((__nreg >= PAYLOAD_MAX/2)) { \ + if (IS_ACCEPTING_CMD(__ar)) \ + __err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \ + 8 * __nreg, \ + (u8 *) &__ar->cmdbuf[1], \ + 0, NULL); \ + __nreg = 0; \ + if (__err) \ + goto __regwrite_out; \ + } \ +} while (0) + +#define ar9170_regwrite_finish() \ +__regwrite_out : \ + if (__nreg) { \ + if (IS_ACCEPTING_CMD(__ar)) \ + __err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \ + 8 * __nreg, \ + (u8 *) &__ar->cmdbuf[1], \ + 0, NULL); \ + __nreg = 0; \ + } + +#define ar9170_regwrite_result() \ + __err; \ +} while (0); + +#endif /* __CMD_H */ diff --git a/drivers/net/wireless/ar9170/led.c b/drivers/net/wireless/ar9170/led.c new file mode 100644 index 00000000000..341cead7f60 --- /dev/null +++ b/drivers/net/wireless/ar9170/led.c @@ -0,0 +1,171 @@ +/* + * Atheros AR9170 driver + * + * LED handling + * + * Copyright 2008, Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, see + * http://www.gnu.org/licenses/. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * Copyright (c) 2007-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ar9170.h" +#include "cmd.h" + +int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state) +{ + return ar9170_write_reg(ar, AR9170_GPIO_REG_DATA, led_state); +} + +int ar9170_init_leds(struct ar9170 *ar) +{ + int err; + + /* disable LEDs */ + /* GPIO [0/1 mode: output, 2/3: input] */ + err = ar9170_write_reg(ar, AR9170_GPIO_REG_PORT_TYPE, 3); + if (err) + goto out; + + /* GPIO 0/1 value: off */ + err = ar9170_set_leds_state(ar, 0); + +out: + return err; +} + +#ifdef CONFIG_AR9170_LEDS +static void ar9170_update_leds(struct work_struct *work) +{ + struct ar9170 *ar = container_of(work, struct ar9170, led_work.work); + int i, tmp, blink_delay = 1000; + u32 led_val = 0; + bool rerun = false; + + if (unlikely(!IS_ACCEPTING_CMD(ar))) + return ; + + mutex_lock(&ar->mutex); + for (i = 0; i < AR9170_NUM_LEDS; i++) + if (ar->leds[i].toggled) { + led_val |= 1 << i; + + tmp = 70 + 200 / (ar->leds[i].toggled); + if (tmp < blink_delay) + blink_delay = tmp; + + if (ar->leds[i].toggled > 1) + ar->leds[i].toggled = 0; + + rerun = true; + } + + ar9170_set_leds_state(ar, led_val); + mutex_unlock(&ar->mutex); + + if (rerun) + queue_delayed_work(ar->hw->workqueue, &ar->led_work, + msecs_to_jiffies(blink_delay)); +} + +static void ar9170_led_brightness_set(struct led_classdev *led, + enum led_brightness brightness) +{ + struct ar9170_led *arl = container_of(led, struct ar9170_led, l); + struct ar9170 *ar = arl->ar; + + arl->toggled++; + + if (likely(IS_ACCEPTING_CMD(ar) && brightness)) + queue_delayed_work(ar->hw->workqueue, &ar->led_work, HZ/10); +} + +static int ar9170_register_led(struct ar9170 *ar, int i, char *name, + char *trigger) +{ + int err; + + snprintf(ar->leds[i].name, sizeof(ar->leds[i].name), + "ar9170-%s::%s", wiphy_name(ar->hw->wiphy), name); + + ar->leds[i].ar = ar; + ar->leds[i].l.name = ar->leds[i].name; + ar->leds[i].l.brightness_set = ar9170_led_brightness_set; + ar->leds[i].l.brightness = 0; + ar->leds[i].l.default_trigger = trigger; + + err = led_classdev_register(wiphy_dev(ar->hw->wiphy), + &ar->leds[i].l); + if (err) + printk(KERN_ERR "%s: failed to register %s LED (%d).\n", + wiphy_name(ar->hw->wiphy), ar->leds[i].name, err); + else + ar->leds[i].registered = true; + + return err; +} + +void ar9170_unregister_leds(struct ar9170 *ar) +{ + int i; + + cancel_delayed_work_sync(&ar->led_work); + + for (i = 0; i < AR9170_NUM_LEDS; i++) + if (ar->leds[i].registered) { + led_classdev_unregister(&ar->leds[i].l); + ar->leds[i].registered = false; + } +} + +int ar9170_register_leds(struct ar9170 *ar) +{ + int err; + + INIT_DELAYED_WORK(&ar->led_work, ar9170_update_leds); + + err = ar9170_register_led(ar, 0, "tx", + ieee80211_get_tx_led_name(ar->hw)); + if (err) + goto fail; + + err = ar9170_register_led(ar, 1, "assoc", + ieee80211_get_assoc_led_name(ar->hw)); + if (err) + goto fail; + + return 0; + +fail: + ar9170_unregister_leds(ar); + return err; +} + +#endif /* CONFIG_AR9170_LEDS */ diff --git a/drivers/net/wireless/ar9170/main.c b/drivers/net/wireless/ar9170/main.c new file mode 100644 index 00000000000..a3b5323743c --- /dev/null +++ b/drivers/net/wireless/ar9170/main.c @@ -0,0 +1,1776 @@ +/* + * Atheros AR9170 driver + * + * mac80211 interaction code + * + * Copyright 2008, Johannes Berg + * Copyright 2009, Christian Lamparter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, see + * http://www.gnu.org/licenses/. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * Copyright (c) 2007-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * BIG FAT TODO: + * + * By the looks of things: these devices share a lot of things like + * EEPROM layout/design and PHY code with other Atheros WIFI products. + * So this driver/library will eventually become ath9k code... or vice versa ;-) + */ + +#include +#include +#include +#include +#include "ar9170.h" +#include "hw.h" +#include "cmd.h" + +static int modparam_nohwcrypt; +module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); +MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); +MODULE_AUTHOR("Johannes Berg "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Atheros shared code for AR9170 wireless devices"); + +#define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \ + .bitrate = (_bitrate), \ + .flags = (_flags), \ + .hw_value = (_hw_rate) | (_txpidx) << 4, \ +} + +static struct ieee80211_rate __ar9170_ratetable[] = { + RATE(10, 0, 0, 0), + RATE(20, 1, 1, IEEE80211_RATE_SHORT_PREAMBLE), + RATE(55, 2, 2, IEEE80211_RATE_SHORT_PREAMBLE), + RATE(110, 3, 3, IEEE80211_RATE_SHORT_PREAMBLE), + RATE(60, 0xb, 0, 0), + RATE(90, 0xf, 0, 0), + RATE(120, 0xa, 0, 0), + RATE(180, 0xe, 0, 0), + RATE(240, 0x9, 0, 0), + RATE(360, 0xd, 1, 0), + RATE(480, 0x8, 2, 0), + RATE(540, 0xc, 3, 0), +}; +#undef RATE + +#define ar9170_g_ratetable (__ar9170_ratetable + 0) +#define ar9170_g_ratetable_size 12 +#define ar9170_a_ratetable (__ar9170_ratetable + 4) +#define ar9170_a_ratetable_size 8 + +/* + * NB: The hw_value is used as an index into the ar9170_phy_freq_params + * array in phy.c so that we don't have to do frequency lookups! + */ +#define CHAN(_freq, _idx) { \ + .center_freq = (_freq), \ + .hw_value = (_idx), \ + .max_power = 18, /* XXX */ \ +} + +static struct ieee80211_channel ar9170_2ghz_chantable[] = { + CHAN(2412, 0), + CHAN(2417, 1), + CHAN(2422, 2), + CHAN(2427, 3), + CHAN(2432, 4), + CHAN(2437, 5), + CHAN(2442, 6), + CHAN(2447, 7), + CHAN(2452, 8), + CHAN(2457, 9), + CHAN(2462, 10), + CHAN(2467, 11), + CHAN(2472, 12), + CHAN(2484, 13), +}; + +static struct ieee80211_channel ar9170_5ghz_chantable[] = { + CHAN(4920, 14), + CHAN(4940, 15), + CHAN(4960, 16), + CHAN(4980, 17), + CHAN(5040, 18), + CHAN(5060, 19), + CHAN(5080, 20), + CHAN(5180, 21), + CHAN(5200, 22), + CHAN(5220, 23), + CHAN(5240, 24), + CHAN(5260, 25), + CHAN(5280, 26), + CHAN(5300, 27), + CHAN(5320, 28), + CHAN(5500, 29), + CHAN(5520, 30), + CHAN(5540, 31), + CHAN(5560, 32), + CHAN(5580, 33), + CHAN(5600, 34), + CHAN(5620, 35), + CHAN(5640, 36), + CHAN(5660, 37), + CHAN(5680, 38), + CHAN(5700, 39), + CHAN(5745, 40), + CHAN(5765, 41), + CHAN(5785, 42), + CHAN(5805, 43), + CHAN(5825, 44), + CHAN(5170, 45), + CHAN(5190, 46), + CHAN(5210, 47), + CHAN(5230, 48), +}; +#undef CHAN + +static struct ieee80211_supported_band ar9170_band_2GHz = { + .channels = ar9170_2ghz_chantable, + .n_channels = ARRAY_SIZE(ar9170_2ghz_chantable), + .bitrates = ar9170_g_ratetable, + .n_bitrates = ar9170_g_ratetable_size, +}; + +#ifdef AR9170_QUEUE_DEBUG +/* + * In case some wants works with AR9170's crazy tx_status queueing techniques. + * He might need this rather useful probing function. + * + * NOTE: caller must hold the queue's spinlock! + */ + +static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) +{ + struct ar9170_tx_control *txc = (void *) skb->data; + struct ieee80211_hdr *hdr = (void *)txc->frame_data; + + printk(KERN_DEBUG "%s: => FRAME [skb:%p, queue:%d, DA:[%pM] " + "mac_control:%04x, phy_control:%08x]\n", + wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb), + ieee80211_get_DA(hdr), le16_to_cpu(txc->mac_control), + le32_to_cpu(txc->phy_control)); +} + +static void ar9170_dump_station_tx_status_queue(struct ar9170 *ar, + struct sk_buff_head *queue) +{ + struct sk_buff *skb; + int i = 0; + + printk(KERN_DEBUG "---[ cut here ]---\n"); + printk(KERN_DEBUG "%s: %d entries in tx_status queue.\n", + wiphy_name(ar->hw->wiphy), skb_queue_len(queue)); + + skb_queue_walk(queue, skb) { + struct ar9170_tx_control *txc = (void *) skb->data; + struct ieee80211_hdr *hdr = (void *)txc->frame_data; + + printk(KERN_DEBUG "index:%d => \n", i); + ar9170_print_txheader(ar, skb); + } + printk(KERN_DEBUG "---[ end ]---\n"); +} +#endif /* AR9170_QUEUE_DEBUG */ + +static struct ieee80211_supported_band ar9170_band_5GHz = { + .channels = ar9170_5ghz_chantable, + .n_channels = ARRAY_SIZE(ar9170_5ghz_chantable), + .bitrates = ar9170_a_ratetable, + .n_bitrates = ar9170_a_ratetable_size, +}; + +void ar9170_handle_tx_status(struct ar9170 *ar, struct sk_buff *skb, + bool valid_status, u16 tx_status) +{ + struct ieee80211_tx_info *txinfo; + unsigned int retries = 0, queue = skb_get_queue_mapping(skb); + unsigned long flags; + + spin_lock_irqsave(&ar->tx_stats_lock, flags); + ar->tx_stats[queue].len--; + if (ieee80211_queue_stopped(ar->hw, queue)) + ieee80211_wake_queue(ar->hw, queue); + spin_unlock_irqrestore(&ar->tx_stats_lock, flags); + + txinfo = IEEE80211_SKB_CB(skb); + ieee80211_tx_info_clear_status(txinfo); + + switch (tx_status) { + case AR9170_TX_STATUS_RETRY: + retries = 2; + case AR9170_TX_STATUS_COMPLETE: + txinfo->flags |= IEEE80211_TX_STAT_ACK; + break; + + case AR9170_TX_STATUS_FAILED: + retries = ar->hw->conf.long_frame_max_tx_count; + break; + + default: + printk(KERN_ERR "%s: invalid tx_status response (%x).\n", + wiphy_name(ar->hw->wiphy), tx_status); + break; + } + + if (valid_status) + txinfo->status.rates[0].count = retries + 1; + + skb_pull(skb, sizeof(struct ar9170_tx_control)); + ieee80211_tx_status_irqsafe(ar->hw, skb); +} +EXPORT_SYMBOL_GPL(ar9170_handle_tx_status); + +static struct sk_buff *ar9170_find_skb_in_queue(struct ar9170 *ar, + const u8 *mac, + const u32 queue, + struct sk_buff_head *q) +{ + unsigned long flags; + struct sk_buff *skb; + + spin_lock_irqsave(&q->lock, flags); + skb_queue_walk(q, skb) { + struct ar9170_tx_control *txc = (void *) skb->data; + struct ieee80211_hdr *hdr = (void *) txc->frame_data; + u32 txc_queue = (le32_to_cpu(txc->phy_control) & + AR9170_TX_PHY_QOS_MASK) >> + AR9170_TX_PHY_QOS_SHIFT; + + if ((queue != txc_queue) || + (compare_ether_addr(ieee80211_get_DA(hdr), mac))) + continue; + + __skb_unlink(skb, q); + spin_unlock_irqrestore(&q->lock, flags); + return skb; + } + spin_unlock_irqrestore(&q->lock, flags); + return NULL; +} + +static struct sk_buff *ar9170_find_skb_in_queue_by_mac(struct ar9170 *ar, + const u8 *mac, + struct sk_buff_head *q) +{ + unsigned long flags; + struct sk_buff *skb; + + spin_lock_irqsave(&q->lock, flags); + skb_queue_walk(q, skb) { + struct ar9170_tx_control *txc = (void *) skb->data; + struct ieee80211_hdr *hdr = (void *) txc->frame_data; + + if (compare_ether_addr(ieee80211_get_DA(hdr), mac)) + continue; + + __skb_unlink(skb, q); + spin_unlock_irqrestore(&q->lock, flags); + return skb; + } + spin_unlock_irqrestore(&q->lock, flags); + return NULL; +} + +static struct sk_buff *ar9170_find_skb_in_queue_by_txcq(struct ar9170 *ar, + const u32 queue, + struct sk_buff_head *q) +{ + unsigned long flags; + struct sk_buff *skb; + + spin_lock_irqsave(&q->lock, flags); + skb_queue_walk(q, skb) { + struct ar9170_tx_control *txc = (void *) skb->data; + u32 txc_queue = (le32_to_cpu(txc->phy_control) & + AR9170_TX_PHY_QOS_MASK) >> + AR9170_TX_PHY_QOS_SHIFT; + + if (queue != txc_queue) + continue; + + __skb_unlink(skb, q); + spin_unlock_irqrestore(&q->lock, flags); + return skb; + } + spin_unlock_irqrestore(&q->lock, flags); + return NULL; +} + +static struct sk_buff *ar9170_find_queued_skb(struct ar9170 *ar, const u8 *mac, + const u32 queue) +{ + struct ieee80211_sta *sta; + struct sk_buff *skb; + + /* + * Unfortunately, the firmware does not tell to which (queued) frame + * this transmission status report belongs to. + * + * So we have to make risky guesses - with the scarce information + * the firmware provided (-> destination MAC, and phy_control) - + * and hope that we picked the right one... + */ + rcu_read_lock(); + sta = ieee80211_find_sta(ar->hw, mac); + + if (likely(sta)) { + struct ar9170_sta_info *sta_priv = (void *) sta->drv_priv; + skb = ar9170_find_skb_in_queue_by_txcq(ar, queue, + &sta_priv->tx_status); + } else { + /* STA is not in database (yet/anymore). */ + + /* scan the waste bin for likely candidates */ + skb = ar9170_find_skb_in_queue(ar, mac, queue, + &ar->global_tx_status_waste); + if (!skb) { + /* so it still _must_ be in the global list. */ + skb = ar9170_find_skb_in_queue(ar, mac, queue, + &ar->global_tx_status); + } + } + rcu_read_unlock(); + +#ifdef AR9170_QUEUE_DEBUG + if (unlikely((!skb) && net_ratelimit())) { + printk(KERN_ERR "%s: ESS:[%pM] does not have any " + "outstanding frames in this queue (%d).\n", + wiphy_name(ar->hw->wiphy), mac, queue); + } +#endif /* AR9170_QUEUE_DEBUG */ + + return skb; +} + +/* + * This worker tries to keep the global tx_status queue empty. + * So we can guarantee that incoming tx_status reports for + * unregistered stations are always synced with the actual + * frame - which we think - belongs to. + */ + +static void ar9170_tx_status_janitor(struct work_struct *work) +{ + struct ar9170 *ar = container_of(work, struct ar9170, + filter_config_work); + struct sk_buff *skb; + + /* recycle the garbage back to mac80211... one by one. */ + while ((skb = skb_dequeue(&ar->global_tx_status_waste))) { +#ifdef AR9170_QUEUE_DEBUG + printk(KERN_DEBUG "%s: dispose queued frame =>\n", + wiphy_name(ar->hw->wiphy)); + ar9170_print_txheader(ar, skb); +#endif /* AR9170_QUEUE_DEBUG */ + ar9170_handle_tx_status(ar, skb, false, + AR9170_TX_STATUS_FAILED); + } + + + + while ((skb = skb_dequeue(&ar->global_tx_status))) { +#ifdef AR9170_QUEUE_DEBUG + printk(KERN_DEBUG "%s: moving frame into waste queue =>\n", + wiphy_name(ar->hw->wiphy)); + + ar9170_print_txheader(ar, skb); +#endif /* AR9170_QUEUE_DEBUG */ + skb_queue_tail(&ar->global_tx_status_waste, skb); + } + + /* recall the janitor in 100ms - if there's garbage in the can. */ + if (skb_queue_len(&ar->global_tx_status_waste) > 0) + queue_delayed_work(ar->hw->workqueue, &ar->tx_status_janitor, + msecs_to_jiffies(100)); +} + +static void ar9170_handle_command_response(struct ar9170 *ar, + void *buf, u32 len) +{ + struct ar9170_cmd_response *cmd = (void *) buf; + + if ((cmd->type & 0xc0) != 0xc0) { + ar->callback_cmd(ar, len, buf); + return; + } + + /* hardware event handlers */ + switch (cmd->type) { + case 0xc1: { + /* + * TX status notification: + * bytes: 0c c1 XX YY M1 M2 M3 M4 M5 M6 R4 R3 R2 R1 S2 S1 + * + * XX always 81 + * YY always 00 + * M1-M6 is the MAC address + * R1-R4 is the transmit rate + * S1-S2 is the transmit status + */ + + struct sk_buff *skb; + u32 queue = (le32_to_cpu(cmd->tx_status.rate) & + AR9170_TX_PHY_QOS_MASK) >> AR9170_TX_PHY_QOS_SHIFT; + + skb = ar9170_find_queued_skb(ar, cmd->tx_status.dst, queue); + if (unlikely(!skb)) + return ; + + ar9170_handle_tx_status(ar, skb, true, + le16_to_cpu(cmd->tx_status.status)); + break; + } + + case 0xc0: + /* + * pre-TBTT event + */ + if (ar->vif && ar->vif->type == NL80211_IFTYPE_AP) + queue_work(ar->hw->workqueue, &ar->beacon_work); + break; + + case 0xc2: + /* + * (IBSS) beacon send notification + * bytes: 04 c2 XX YY B4 B3 B2 B1 + * + * XX always 80 + * YY always 00 + * B1-B4 "should" be the number of send out beacons. + */ + break; + + case 0xc3: + /* End of Atim Window */ + break; + + case 0xc4: + case 0xc5: + /* BlockACK events */ + break; + + case 0xc6: + /* Watchdog Interrupt */ + break; + + case 0xc9: + /* retransmission issue / SIFS/EIFS collision ?! */ + break; + + default: + printk(KERN_INFO "received unhandled event %x\n", cmd->type); + print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, buf, len); + break; + } +} + +/* + * If the frame alignment is right (or the kernel has + * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there + * is only a single MPDU in the USB frame, then we can + * submit to mac80211 the SKB directly. However, since + * there may be multiple packets in one SKB in stream + * mode, and we need to observe the proper ordering, + * this is non-trivial. + */ +static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) +{ + struct sk_buff *skb; + struct ar9170_rx_head *head = (void *)buf; + struct ar9170_rx_tail *tail; + struct ieee80211_rx_status status; + int mpdu_len, i; + u8 error, antennas = 0, decrypt; + __le16 fc; + int reserved; + + if (unlikely(!IS_STARTED(ar))) + return ; + + /* Received MPDU */ + mpdu_len = len; + mpdu_len -= sizeof(struct ar9170_rx_head); + mpdu_len -= sizeof(struct ar9170_rx_tail); + BUILD_BUG_ON(sizeof(struct ar9170_rx_head) != 12); + BUILD_BUG_ON(sizeof(struct ar9170_rx_tail) != 24); + + if (mpdu_len <= FCS_LEN) + return; + + tail = (void *)(buf + sizeof(struct ar9170_rx_head) + mpdu_len); + + for (i = 0; i < 3; i++) + if (tail->rssi[i] != 0x80) + antennas |= BIT(i); + + /* post-process RSSI */ + for (i = 0; i < 7; i++) + if (tail->rssi[i] & 0x80) + tail->rssi[i] = ((tail->rssi[i] & 0x7f) + 1) & 0x7f; + + memset(&status, 0, sizeof(status)); + + status.band = ar->channel->band; + status.freq = ar->channel->center_freq; + status.signal = ar->noise[0] + tail->rssi_combined; + status.noise = ar->noise[0]; + status.antenna = antennas; + + switch (tail->status & AR9170_RX_STATUS_MODULATION_MASK) { + case AR9170_RX_STATUS_MODULATION_CCK: + if (tail->status & AR9170_RX_STATUS_SHORT_PREAMBLE) + status.flag |= RX_FLAG_SHORTPRE; + switch (head->plcp[0]) { + case 0x0a: + status.rate_idx = 0; + break; + case 0x14: + status.rate_idx = 1; + break; + case 0x37: + status.rate_idx = 2; + break; + case 0x6e: + status.rate_idx = 3; + break; + default: + if ((!ar->sniffer_enabled) && (net_ratelimit())) + printk(KERN_ERR "%s: invalid plcp cck rate " + "(%x).\n", wiphy_name(ar->hw->wiphy), + head->plcp[0]); + return; + } + break; + case AR9170_RX_STATUS_MODULATION_OFDM: + switch (head->plcp[0] & 0xF) { + case 0xB: + status.rate_idx = 0; + break; + case 0xF: + status.rate_idx = 1; + break; + case 0xA: + status.rate_idx = 2; + break; + case 0xE: + status.rate_idx = 3; + break; + case 0x9: + status.rate_idx = 4; + break; + case 0xD: + status.rate_idx = 5; + break; + case 0x8: + status.rate_idx = 6; + break; + case 0xC: + status.rate_idx = 7; + break; + default: + if ((!ar->sniffer_enabled) && (net_ratelimit())) + printk(KERN_ERR "%s: invalid plcp ofdm rate " + "(%x).\n", wiphy_name(ar->hw->wiphy), + head->plcp[0]); + return; + } + if (status.band == IEEE80211_BAND_2GHZ) + status.rate_idx += 4; + break; + case AR9170_RX_STATUS_MODULATION_HT: + case AR9170_RX_STATUS_MODULATION_DUPOFDM: + /* XXX */ + + if (net_ratelimit()) + printk(KERN_ERR "%s: invalid modulation\n", + wiphy_name(ar->hw->wiphy)); + return; + } + + error = tail->error; + + if (error & AR9170_RX_ERROR_MMIC) { + status.flag |= RX_FLAG_MMIC_ERROR; + error &= ~AR9170_RX_ERROR_MMIC; + } + + if (error & AR9170_RX_ERROR_PLCP) { + status.flag |= RX_FLAG_FAILED_PLCP_CRC; + error &= ~AR9170_RX_ERROR_PLCP; + } + + if (error & AR9170_RX_ERROR_FCS) { + status.flag |= RX_FLAG_FAILED_FCS_CRC; + error &= ~AR9170_RX_ERROR_FCS; + } + + decrypt = ar9170_get_decrypt_type(tail); + if (!(decrypt & AR9170_RX_ENC_SOFTWARE) && + decrypt != AR9170_ENC_ALG_NONE) + status.flag |= RX_FLAG_DECRYPTED; + + /* ignore wrong RA errors */ + error &= ~AR9170_RX_ERROR_WRONG_RA; + + if (error & AR9170_RX_ERROR_DECRYPT) { + error &= ~AR9170_RX_ERROR_DECRYPT; + + /* + * Rx decryption is done in place, + * the original data is lost anyway. + */ + return ; + } + + /* drop any other error frames */ + if ((error) && (net_ratelimit())) { + printk(KERN_DEBUG "%s: errors: %#x\n", + wiphy_name(ar->hw->wiphy), error); + return; + } + + buf += sizeof(struct ar9170_rx_head); + fc = *(__le16 *)buf; + + if (ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc)) + reserved = 32 + 2; + else + reserved = 32; + + skb = dev_alloc_skb(mpdu_len + reserved); + if (!skb) + return; + + skb_reserve(skb, reserved); + memcpy(skb_put(skb, mpdu_len), buf, mpdu_len); + ieee80211_rx_irqsafe(ar->hw, skb, &status); +} + +/* + * TODO: + * It looks like AR9170 supports more than just the USB transport interface. + * Unfortunately, there is no available information what parts of the + * precendent and following code fragments is device specific and what not. + * For now, everything stays here, until some SPI chips pop up. + */ +void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb) +{ + unsigned int i, tlen, resplen; + u8 *tbuf, *respbuf; + + tbuf = skb->data; + tlen = skb->len; + + while (tlen >= 4) { + int clen = tbuf[1] << 8 | tbuf[0]; + int wlen = (clen + 3) & ~3; + + /* + * parse stream (if any) + */ + if (tbuf[2] != 0 || tbuf[3] != 0x4e) { + printk(KERN_ERR "%s: missing tag!\n", + wiphy_name(ar->hw->wiphy)); + return ; + } + if (wlen > tlen - 4) { + printk(KERN_ERR "%s: invalid RX (%d, %d, %d)\n", + wiphy_name(ar->hw->wiphy), clen, wlen, tlen); + print_hex_dump(KERN_DEBUG, "data: ", + DUMP_PREFIX_OFFSET, + 16, 1, tbuf, tlen, true); + return ; + } + resplen = clen; + respbuf = tbuf + 4; + tbuf += wlen + 4; + tlen -= wlen + 4; + + i = 0; + + /* weird thing, but this is the same in the original driver */ + while (resplen > 2 && i < 12 && + respbuf[0] == 0xff && respbuf[1] == 0xff) { + i += 2; + resplen -= 2; + respbuf += 2; + } + + if (resplen < 4) + continue; + + /* found the 6 * 0xffff marker? */ + if (i == 12) + ar9170_handle_command_response(ar, respbuf, resplen); + else + ar9170_handle_mpdu(ar, respbuf, resplen); + } + + if (tlen) + printk(KERN_ERR "%s: buffer remains!\n", + wiphy_name(ar->hw->wiphy)); +} +EXPORT_SYMBOL_GPL(ar9170_rx); + +#define AR9170_FILL_QUEUE(queue, ai_fs, cwmin, cwmax, _txop) \ +do { \ + queue.aifs = ai_fs; \ + queue.cw_min = cwmin; \ + queue.cw_max = cwmax; \ + queue.txop = _txop; \ +} while (0) + +static int ar9170_op_start(struct ieee80211_hw *hw) +{ + struct ar9170 *ar = hw->priv; + int err, i; + + mutex_lock(&ar->mutex); + + /* reinitialize queues statistics */ + memset(&ar->tx_stats, 0, sizeof(ar->tx_stats)); + for (i = 0; i < ARRAY_SIZE(ar->tx_stats); i++) + ar->tx_stats[i].limit = 8; + + /* reset QoS defaults */ + AR9170_FILL_QUEUE(ar->edcf[0], 3, 15, 1023, 0); /* BEST EFFORT*/ + AR9170_FILL_QUEUE(ar->edcf[1], 7, 15, 1023, 0); /* BACKGROUND */ + AR9170_FILL_QUEUE(ar->edcf[2], 2, 7, 15, 94); /* VIDEO */ + AR9170_FILL_QUEUE(ar->edcf[3], 2, 3, 7, 47); /* VOICE */ + AR9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */ + + err = ar->open(ar); + if (err) + goto out; + + err = ar9170_init_mac(ar); + if (err) + goto out; + + err = ar9170_set_qos(ar); + if (err) + goto out; + + err = ar9170_init_phy(ar, IEEE80211_BAND_2GHZ); + if (err) + goto out; + + err = ar9170_init_rf(ar); + if (err) + goto out; + + /* start DMA */ + err = ar9170_write_reg(ar, 0x1c3d30, 0x100); + if (err) + goto out; + + ar->state = AR9170_STARTED; + +out: + mutex_unlock(&ar->mutex); + return err; +} + +static void ar9170_op_stop(struct ieee80211_hw *hw) +{ + struct ar9170 *ar = hw->priv; + + if (IS_STARTED(ar)) + ar->state = AR9170_IDLE; + + mutex_lock(&ar->mutex); + + cancel_delayed_work_sync(&ar->tx_status_janitor); + cancel_work_sync(&ar->filter_config_work); + cancel_work_sync(&ar->beacon_work); + skb_queue_purge(&ar->global_tx_status_waste); + skb_queue_purge(&ar->global_tx_status); + + if (IS_ACCEPTING_CMD(ar)) { + ar9170_set_leds_state(ar, 0); + + /* stop DMA */ + ar9170_write_reg(ar, 0x1c3d30, 0); + ar->stop(ar); + } + + mutex_unlock(&ar->mutex); +} + +int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct ar9170 *ar = hw->priv; + struct ieee80211_hdr *hdr; + struct ar9170_tx_control *txc; + struct ieee80211_tx_info *info; + struct ieee80211_rate *rate = NULL; + struct ieee80211_tx_rate *txrate; + unsigned int queue = skb_get_queue_mapping(skb); + unsigned long flags = 0; + struct ar9170_sta_info *sta_info = NULL; + u32 power, chains; + u16 keytype = 0; + u16 len, icv = 0; + int err; + bool tx_status; + + if (unlikely(!IS_STARTED(ar))) + goto err_free; + + hdr = (void *)skb->data; + info = IEEE80211_SKB_CB(skb); + len = skb->len; + + spin_lock_irqsave(&ar->tx_stats_lock, flags); + if (ar->tx_stats[queue].limit < ar->tx_stats[queue].len) { + spin_unlock_irqrestore(&ar->tx_stats_lock, flags); + return NETDEV_TX_OK; + } + + ar->tx_stats[queue].len++; + ar->tx_stats[queue].count++; + if (ar->tx_stats[queue].limit == ar->tx_stats[queue].len) + ieee80211_stop_queue(hw, queue); + + spin_unlock_irqrestore(&ar->tx_stats_lock, flags); + + txc = (void *)skb_push(skb, sizeof(*txc)); + + tx_status = (((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) != 0) || + ((info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) != 0)); + + if (info->control.hw_key) { + icv = info->control.hw_key->icv_len; + + switch (info->control.hw_key->alg) { + case ALG_WEP: + keytype = AR9170_TX_MAC_ENCR_RC4; + break; + case ALG_TKIP: + keytype = AR9170_TX_MAC_ENCR_RC4; + break; + case ALG_CCMP: + keytype = AR9170_TX_MAC_ENCR_AES; + break; + default: + WARN_ON(1); + goto err_dequeue; + } + } + + /* Length */ + txc->length = cpu_to_le16(len + icv + 4); + + txc->mac_control = cpu_to_le16(AR9170_TX_MAC_HW_DURATION | + AR9170_TX_MAC_BACKOFF); + txc->mac_control |= cpu_to_le16(ar9170_qos_hwmap[queue] << + AR9170_TX_MAC_QOS_SHIFT); + txc->mac_control |= cpu_to_le16(keytype); + txc->phy_control = cpu_to_le32(0); + + if (info->flags & IEEE80211_TX_CTL_NO_ACK) + txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_NO_ACK); + + if (info->flags & IEEE80211_TX_CTL_AMPDU) + txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); + + txrate = &info->control.rates[0]; + + if (txrate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) + txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); + else if (txrate->flags & IEEE80211_TX_RC_USE_RTS_CTS) + txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); + + if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD) + txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD); + + if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) + txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_PREAMBLE); + + if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) + txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ); + /* this works because 40 MHz is 2 and dup is 3 */ + if (txrate->flags & IEEE80211_TX_RC_DUP_DATA) + txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ_DUP); + + if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) + txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_GI); + + if (txrate->flags & IEEE80211_TX_RC_MCS) { + u32 r = txrate->idx; + u8 *txpower; + + r <<= AR9170_TX_PHY_MCS_SHIFT; + if (WARN_ON(r & ~AR9170_TX_PHY_MCS_MASK)) + goto err_dequeue; + txc->phy_control |= cpu_to_le32(r & AR9170_TX_PHY_MCS_MASK); + txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_MOD_HT); + + if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) { + if (info->band == IEEE80211_BAND_5GHZ) + txpower = ar->power_5G_ht40; + else + txpower = ar->power_2G_ht40; + } else { + if (info->band == IEEE80211_BAND_5GHZ) + txpower = ar->power_5G_ht20; + else + txpower = ar->power_2G_ht20; + } + + power = txpower[(txrate->idx) & 7]; + } else { + u8 *txpower; + u32 mod; + u32 phyrate; + u8 idx = txrate->idx; + + if (info->band != IEEE80211_BAND_2GHZ) { + idx += 4; + txpower = ar->power_5G_leg; + mod = AR9170_TX_PHY_MOD_OFDM; + } else { + if (idx < 4) { + txpower = ar->power_2G_cck; + mod = AR9170_TX_PHY_MOD_CCK; + } else { + mod = AR9170_TX_PHY_MOD_OFDM; + txpower = ar->power_2G_ofdm; + } + } + + rate = &__ar9170_ratetable[idx]; + + phyrate = rate->hw_value & 0xF; + power = txpower[(rate->hw_value & 0x30) >> 4]; + phyrate <<= AR9170_TX_PHY_MCS_SHIFT; + + txc->phy_control |= cpu_to_le32(mod); + txc->phy_control |= cpu_to_le32(phyrate); + } + + power <<= AR9170_TX_PHY_TX_PWR_SHIFT; + power &= AR9170_TX_PHY_TX_PWR_MASK; + txc->phy_control |= cpu_to_le32(power); + + /* set TX chains */ + if (ar->eeprom.tx_mask == 1) { + chains = AR9170_TX_PHY_TXCHAIN_1; + } else { + chains = AR9170_TX_PHY_TXCHAIN_2; + + /* >= 36M legacy OFDM - use only one chain */ + if (rate && rate->bitrate >= 360) + chains = AR9170_TX_PHY_TXCHAIN_1; + } + txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT); + + if (tx_status) { + txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); + /* + * WARNING: + * Putting the QoS queue bits into an unexplored territory is + * certainly not elegant. + * + * In my defense: This idea provides a reasonable way to + * smuggle valuable information to the tx_status callback. + * Also, the idea behind this bit-abuse came straight from + * the original driver code. + */ + + txc->phy_control |= + cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT); + + if (info->control.sta) { + sta_info = (void *) info->control.sta->drv_priv; + skb_queue_tail(&sta_info->tx_status, skb); + } else { + skb_queue_tail(&ar->global_tx_status, skb); + + queue_delayed_work(ar->hw->workqueue, + &ar->tx_status_janitor, + msecs_to_jiffies(100)); + } + } + + err = ar->tx(ar, skb, tx_status, 0); + if (unlikely(tx_status && err)) { + if (info->control.sta) + skb_unlink(skb, &sta_info->tx_status); + else + skb_unlink(skb, &ar->global_tx_status); + } + + return NETDEV_TX_OK; + +err_dequeue: + spin_lock_irqsave(&ar->tx_stats_lock, flags); + ar->tx_stats[queue].len--; + ar->tx_stats[queue].count--; + spin_unlock_irqrestore(&ar->tx_stats_lock, flags); + +err_free: + dev_kfree_skb(skb); + return NETDEV_TX_OK; +} + +static int ar9170_op_add_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf) +{ + struct ar9170 *ar = hw->priv; + int err = 0; + + mutex_lock(&ar->mutex); + + if (ar->vif) { + err = -EBUSY; + goto unlock; + } + + ar->vif = conf->vif; + memcpy(ar->mac_addr, conf->mac_addr, ETH_ALEN); + + if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) { + ar->rx_software_decryption = true; + ar->disable_offload = true; + } + + ar->cur_filter = 0; + ar->want_filter = AR9170_MAC_REG_FTF_DEFAULTS; + err = ar9170_update_frame_filter(ar); + if (err) + goto unlock; + + err = ar9170_set_operating_mode(ar); + +unlock: + mutex_unlock(&ar->mutex); + return err; +} + +static void ar9170_op_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf) +{ + struct ar9170 *ar = hw->priv; + + mutex_lock(&ar->mutex); + ar->vif = NULL; + ar->want_filter = 0; + ar9170_update_frame_filter(ar); + ar9170_set_beacon_timers(ar); + dev_kfree_skb(ar->beacon); + ar->beacon = NULL; + ar->sniffer_enabled = false; + ar->rx_software_decryption = false; + ar9170_set_operating_mode(ar); + mutex_unlock(&ar->mutex); +} + +static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed) +{ + struct ar9170 *ar = hw->priv; + int err = 0; + + mutex_lock(&ar->mutex); + + if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) { + /* TODO */ + err = 0; + } + + if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { + /* TODO */ + err = 0; + } + + if (changed & IEEE80211_CONF_CHANGE_PS) { + /* TODO */ + err = 0; + } + + if (changed & IEEE80211_CONF_CHANGE_POWER) { + /* TODO */ + err = 0; + } + + if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { + /* + * is it long_frame_max_tx_count or short_frame_max_tx_count? + */ + + err = ar9170_set_hwretry_limit(ar, + ar->hw->conf.long_frame_max_tx_count); + if (err) + goto out; + } + + if (changed & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) { + err = ar9170_set_beacon_timers(ar); + if (err) + goto out; + } + + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + err = ar9170_set_channel(ar, hw->conf.channel, + AR9170_RFI_NONE, AR9170_BW_20); + if (err) + goto out; + /* adjust slot time for 5 GHz */ + if (hw->conf.channel->band == IEEE80211_BAND_5GHZ) + err = ar9170_write_reg(ar, AR9170_MAC_REG_SLOT_TIME, + 9 << 10); + } + +out: + mutex_unlock(&ar->mutex); + return err; +} + +static int ar9170_op_config_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_if_conf *conf) +{ + struct ar9170 *ar = hw->priv; + int err = 0; + + mutex_lock(&ar->mutex); + + if (conf->changed & IEEE80211_IFCC_BSSID) { + memcpy(ar->bssid, conf->bssid, ETH_ALEN); + err = ar9170_set_operating_mode(ar); + } + + if (conf->changed & IEEE80211_IFCC_BEACON) { + err = ar9170_update_beacon(ar); + + if (err) + goto out; + err = ar9170_set_beacon_timers(ar); + } + +out: + mutex_unlock(&ar->mutex); + return err; +} + +static void ar9170_set_filters(struct work_struct *work) +{ + struct ar9170 *ar = container_of(work, struct ar9170, + filter_config_work); + int err; + + mutex_lock(&ar->mutex); + if (unlikely(!IS_STARTED(ar))) + goto unlock; + + if (ar->filter_changed & AR9170_FILTER_CHANGED_PROMISC) { + err = ar9170_set_operating_mode(ar); + if (err) + goto unlock; + } + + if (ar->filter_changed & AR9170_FILTER_CHANGED_MULTICAST) { + err = ar9170_update_multicast(ar); + if (err) + goto unlock; + } + + if (ar->filter_changed & AR9170_FILTER_CHANGED_FRAMEFILTER) + err = ar9170_update_frame_filter(ar); + +unlock: + mutex_unlock(&ar->mutex); +} + +static void ar9170_op_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *new_flags, + int mc_count, struct dev_mc_list *mclist) +{ + struct ar9170 *ar = hw->priv; + + /* mask supported flags */ + *new_flags &= FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC | + FIF_PROMISC_IN_BSS; + + /* + * We can support more by setting the sniffer bit and + * then checking the error flags, later. + */ + + if (changed_flags & FIF_ALLMULTI) { + if (*new_flags & FIF_ALLMULTI) { + ar->want_mc_hash = ~0ULL; + } else { + u64 mchash; + int i; + + /* always get broadcast frames */ + mchash = 1ULL << (0xff>>2); + + for (i = 0; i < mc_count; i++) { + if (WARN_ON(!mclist)) + break; + mchash |= 1ULL << (mclist->dmi_addr[5] >> 2); + mclist = mclist->next; + } + ar->want_mc_hash = mchash; + } + ar->filter_changed |= AR9170_FILTER_CHANGED_MULTICAST; + } + + if (changed_flags & FIF_CONTROL) { + u32 filter = AR9170_MAC_REG_FTF_PSPOLL | + AR9170_MAC_REG_FTF_RTS | + AR9170_MAC_REG_FTF_CTS | + AR9170_MAC_REG_FTF_ACK | + AR9170_MAC_REG_FTF_CFE | + AR9170_MAC_REG_FTF_CFE_ACK; + + if (*new_flags & FIF_CONTROL) + ar->want_filter = ar->cur_filter | filter; + else + ar->want_filter = ar->cur_filter & ~filter; + + ar->filter_changed |= AR9170_FILTER_CHANGED_FRAMEFILTER; + } + + if (changed_flags & FIF_PROMISC_IN_BSS) { + ar->sniffer_enabled = ((*new_flags) & FIF_PROMISC_IN_BSS) != 0; + ar->filter_changed |= AR9170_FILTER_CHANGED_PROMISC; + } + + if (likely(IS_STARTED(ar))) + queue_work(ar->hw->workqueue, &ar->filter_config_work); +} + +static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changed) +{ + struct ar9170 *ar = hw->priv; + int err = 0; + + mutex_lock(&ar->mutex); + + ar9170_regwrite_begin(ar); + + if (changed & BSS_CHANGED_ASSOC) { + ar->state = bss_conf->assoc ? AR9170_ASSOCIATED : ar->state; + +#ifndef CONFIG_AR9170_LEDS + /* enable assoc LED. */ + err = ar9170_set_leds_state(ar, bss_conf->assoc ? 2 : 0); +#endif /* CONFIG_AR9170_LEDS */ + } + + if (changed & BSS_CHANGED_HT) { + /* TODO */ + err = 0; + } + + if (changed & BSS_CHANGED_ERP_SLOT) { + u32 slottime = 20; + + if (bss_conf->use_short_slot) + slottime = 9; + + ar9170_regwrite(AR9170_MAC_REG_SLOT_TIME, slottime << 10); + } + + if (changed & BSS_CHANGED_BASIC_RATES) { + u32 cck, ofdm; + + if (hw->conf.channel->band == IEEE80211_BAND_5GHZ) { + ofdm = bss_conf->basic_rates; + cck = 0; + } else { + /* four cck rates */ + cck = bss_conf->basic_rates & 0xf; + ofdm = bss_conf->basic_rates >> 4; + } + ar9170_regwrite(AR9170_MAC_REG_BASIC_RATE, + ofdm << 8 | cck); + } + + ar9170_regwrite_finish(); + err = ar9170_regwrite_result(); + mutex_unlock(&ar->mutex); +} + +static u64 ar9170_op_get_tsf(struct ieee80211_hw *hw) +{ + struct ar9170 *ar = hw->priv; + int err; + u32 tsf_low; + u32 tsf_high; + u64 tsf; + + mutex_lock(&ar->mutex); + err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_L, &tsf_low); + if (!err) + err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_H, &tsf_high); + mutex_unlock(&ar->mutex); + + if (WARN_ON(err)) + return 0; + + tsf = tsf_high; + tsf = (tsf << 32) | tsf_low; + return tsf; +} + +static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct ar9170 *ar = hw->priv; + int err = 0, i; + u8 ktype; + + if ((!ar->vif) || (ar->disable_offload)) + return -EOPNOTSUPP; + + switch (key->alg) { + case ALG_WEP: + if (key->keylen == LEN_WEP40) + ktype = AR9170_ENC_ALG_WEP64; + else + ktype = AR9170_ENC_ALG_WEP128; + break; + case ALG_TKIP: + ktype = AR9170_ENC_ALG_TKIP; + break; + case ALG_CCMP: + ktype = AR9170_ENC_ALG_AESCCMP; + break; + default: + return -EOPNOTSUPP; + } + + mutex_lock(&ar->mutex); + if (cmd == SET_KEY) { + if (unlikely(!IS_STARTED(ar))) { + err = -EOPNOTSUPP; + goto out; + } + + /* group keys need all-zeroes address */ + if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) + sta = NULL; + + if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { + for (i = 0; i < 64; i++) + if (!(ar->usedkeys & BIT(i))) + break; + if (i == 64) { + ar->rx_software_decryption = true; + ar9170_set_operating_mode(ar); + err = -ENOSPC; + goto out; + } + } else { + i = 64 + key->keyidx; + } + + key->hw_key_idx = i; + + err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, ktype, 0, + key->key, min_t(u8, 16, key->keylen)); + if (err) + goto out; + + if (key->alg == ALG_TKIP) { + err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, + ktype, 1, key->key + 16, 16); + if (err) + goto out; + + /* + * hardware is not capable generating the MMIC + * for fragmented frames! + */ + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + } + + if (i < 64) + ar->usedkeys |= BIT(i); + + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + } else { + if (unlikely(!IS_STARTED(ar))) { + /* The device is gone... together with the key ;-) */ + err = 0; + goto out; + } + + err = ar9170_disable_key(ar, key->hw_key_idx); + if (err) + goto out; + + if (key->hw_key_idx < 64) { + ar->usedkeys &= ~BIT(key->hw_key_idx); + } else { + err = ar9170_upload_key(ar, key->hw_key_idx, NULL, + AR9170_ENC_ALG_NONE, 0, + NULL, 0); + if (err) + goto out; + + if (key->alg == ALG_TKIP) { + err = ar9170_upload_key(ar, key->hw_key_idx, + NULL, + AR9170_ENC_ALG_NONE, 1, + NULL, 0); + if (err) + goto out; + } + + } + } + + ar9170_regwrite_begin(ar); + ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_L, ar->usedkeys); + ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_H, ar->usedkeys >> 32); + ar9170_regwrite_finish(); + err = ar9170_regwrite_result(); + +out: + mutex_unlock(&ar->mutex); + + return err; +} + +static void ar9170_sta_notify(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum sta_notify_cmd cmd, + struct ieee80211_sta *sta) +{ + struct ar9170 *ar = hw->priv; + struct ar9170_sta_info *info = (void *) sta->drv_priv; + struct sk_buff *skb; + + switch (cmd) { + case STA_NOTIFY_ADD: + skb_queue_head_init(&info->tx_status); + + /* + * do we already have a frame that needs tx_status + * from this station in our queue? + * If so then transfer them to the new station queue. + */ + + /* preserve the correct order - check the waste bin first */ + while ((skb = ar9170_find_skb_in_queue_by_mac(ar, sta->addr, + &ar->global_tx_status_waste))) + skb_queue_tail(&info->tx_status, skb); + + /* now the still pending frames */ + while ((skb = ar9170_find_skb_in_queue_by_mac(ar, sta->addr, + &ar->global_tx_status))) + skb_queue_tail(&info->tx_status, skb); + +#ifdef AR9170_QUEUE_DEBUG + printk(KERN_DEBUG "%s: STA[%pM] has %d queued frames =>\n", + wiphy_name(ar->hw->wiphy), sta->addr, + skb_queue_len(&info->tx_status)); + + ar9170_dump_station_tx_status_queue(ar, &info->tx_status); +#endif /* AR9170_QUEUE_DEBUG */ + + + break; + + case STA_NOTIFY_REMOVE: + + /* + * transfer all outstanding frames that need a tx_status + * reports to the fallback queue + */ + + while ((skb = skb_dequeue(&ar->global_tx_status))) { +#ifdef AR9170_QUEUE_DEBUG + printk(KERN_DEBUG "%s: queueing frame in global " + "tx_status queue =>\n", + wiphy_name(ar->hw->wiphy)); + + ar9170_print_txheader(ar, skb); +#endif /* AR9170_QUEUE_DEBUG */ + skb_queue_tail(&ar->global_tx_status_waste, skb); + } + break; + + default: + break; + } +} + +static int ar9170_get_stats(struct ieee80211_hw *hw, + struct ieee80211_low_level_stats *stats) +{ + struct ar9170 *ar = hw->priv; + u32 val; + int err; + + mutex_lock(&ar->mutex); + err = ar9170_read_reg(ar, AR9170_MAC_REG_TX_RETRY, &val); + ar->stats.dot11ACKFailureCount += val; + + memcpy(stats, &ar->stats, sizeof(*stats)); + mutex_unlock(&ar->mutex); + + return 0; +} + +static int ar9170_get_tx_stats(struct ieee80211_hw *hw, + struct ieee80211_tx_queue_stats *tx_stats) +{ + struct ar9170 *ar = hw->priv; + + spin_lock_bh(&ar->tx_stats_lock); + memcpy(tx_stats, ar->tx_stats, sizeof(tx_stats[0]) * hw->queues); + spin_unlock_bh(&ar->tx_stats_lock); + + return 0; +} + +static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, + const struct ieee80211_tx_queue_params *param) +{ + struct ar9170 *ar = hw->priv; + int ret; + + mutex_lock(&ar->mutex); + if ((param) && !(queue > 4)) { + memcpy(&ar->edcf[ar9170_qos_hwmap[queue]], + param, sizeof(*param)); + + ret = ar9170_set_qos(ar); + } else + ret = -EINVAL; + + mutex_unlock(&ar->mutex); + return ret; +} + +static const struct ieee80211_ops ar9170_ops = { + .start = ar9170_op_start, + .stop = ar9170_op_stop, + .tx = ar9170_op_tx, + .add_interface = ar9170_op_add_interface, + .remove_interface = ar9170_op_remove_interface, + .config = ar9170_op_config, + .config_interface = ar9170_op_config_interface, + .configure_filter = ar9170_op_configure_filter, + .conf_tx = ar9170_conf_tx, + .bss_info_changed = ar9170_op_bss_info_changed, + .get_tsf = ar9170_op_get_tsf, + .set_key = ar9170_set_key, + .sta_notify = ar9170_sta_notify, + .get_stats = ar9170_get_stats, + .get_tx_stats = ar9170_get_tx_stats, +}; + +void *ar9170_alloc(size_t priv_size) +{ + struct ieee80211_hw *hw; + struct ar9170 *ar; + int i; + + hw = ieee80211_alloc_hw(priv_size, &ar9170_ops); + if (!hw) + return ERR_PTR(-ENOMEM); + + ar = hw->priv; + ar->hw = hw; + + mutex_init(&ar->mutex); + spin_lock_init(&ar->cmdlock); + spin_lock_init(&ar->tx_stats_lock); + skb_queue_head_init(&ar->global_tx_status); + skb_queue_head_init(&ar->global_tx_status_waste); + INIT_WORK(&ar->filter_config_work, ar9170_set_filters); + INIT_WORK(&ar->beacon_work, ar9170_new_beacon); + INIT_DELAYED_WORK(&ar->tx_status_janitor, ar9170_tx_status_janitor); + + /* all hw supports 2.4 GHz, so set channel to 1 by default */ + ar->channel = &ar9170_2ghz_chantable[0]; + + /* first part of wiphy init */ + ar->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_WDS) | + BIT(NL80211_IFTYPE_ADHOC); + ar->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS | + IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | + IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_NOISE_DBM; + + ar->hw->queues = 4; + ar->hw->extra_tx_headroom = 8; + ar->hw->sta_data_size = sizeof(struct ar9170_sta_info); + + ar->hw->max_rates = 1; + ar->hw->max_rate_tries = 3; + + for (i = 0; i < ARRAY_SIZE(ar->noise); i++) + ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */ + + return ar; +} +EXPORT_SYMBOL_GPL(ar9170_alloc); + +static int ar9170_read_eeprom(struct ar9170 *ar) +{ +#define RW 8 /* number of words to read at once */ +#define RB (sizeof(u32) * RW) + DECLARE_MAC_BUF(mbuf); + u8 *eeprom = (void *)&ar->eeprom; + u8 *addr = ar->eeprom.mac_address; + __le32 offsets[RW]; + int i, j, err, bands = 0; + + BUILD_BUG_ON(sizeof(ar->eeprom) & 3); + + BUILD_BUG_ON(RB > AR9170_MAX_CMD_LEN - 4); +#ifndef __CHECKER__ + /* don't want to handle trailing remains */ + BUILD_BUG_ON(sizeof(ar->eeprom) % RB); +#endif + + for (i = 0; i < sizeof(ar->eeprom)/RB; i++) { + for (j = 0; j < RW; j++) + offsets[j] = cpu_to_le32(AR9170_EEPROM_START + + RB * i + 4 * j); + + err = ar->exec_cmd(ar, AR9170_CMD_RREG, + RB, (u8 *) &offsets, + RB, eeprom + RB * i); + if (err) + return err; + } + +#undef RW +#undef RB + + if (ar->eeprom.length == cpu_to_le16(0xFFFF)) + return -ENODATA; + + if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) { + ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &ar9170_band_2GHz; + bands++; + } + if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) { + ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar9170_band_5GHz; + bands++; + } + /* + * I measured this, a bandswitch takes roughly + * 135 ms and a frequency switch about 80. + * + * FIXME: measure these values again once EEPROM settings + * are used, that will influence them! + */ + if (bands == 2) + ar->hw->channel_change_time = 135 * 1000; + else + ar->hw->channel_change_time = 80 * 1000; + + /* second part of wiphy init */ + SET_IEEE80211_PERM_ADDR(ar->hw, addr); + + return bands ? 0 : -EINVAL; +} + +int ar9170_register(struct ar9170 *ar, struct device *pdev) +{ + int err; + + /* try to read EEPROM, init MAC addr */ + err = ar9170_read_eeprom(ar); + if (err) + goto err_out; + + err = ieee80211_register_hw(ar->hw); + if (err) + goto err_out; + + err = ar9170_init_leds(ar); + if (err) + goto err_unreg; + +#ifdef CONFIG_AR9170_LEDS + err = ar9170_register_leds(ar); + if (err) + goto err_unreg; +#endif /* CONFIG_AR9170_LEDS */ + + dev_info(pdev, "Atheros AR9170 is registered as '%s'\n", + wiphy_name(ar->hw->wiphy)); + + return err; + +err_unreg: + ieee80211_unregister_hw(ar->hw); + +err_out: + return err; +} +EXPORT_SYMBOL_GPL(ar9170_register); + +void ar9170_unregister(struct ar9170 *ar) +{ +#ifdef CONFIG_AR9170_LEDS + ar9170_unregister_leds(ar); +#endif /* CONFIG_AR9170_LEDS */ + + ieee80211_unregister_hw(ar->hw); + mutex_destroy(&ar->mutex); +} +EXPORT_SYMBOL_GPL(ar9170_unregister); + +static int __init ar9170_init(void) +{ + if (modparam_nohwcrypt) + printk(KERN_INFO "ar9170: cryptographic acceleration " + "disabled.\n"); + + return 0; +} + +static void __exit ar9170_exit(void) +{ + +} + +module_init(ar9170_init); +module_exit(ar9170_exit); -- GitLab From 6cb19353535f9f02fc2a753e3261a255406ba8fa Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 22 Mar 2009 02:36:06 +0100 Subject: [PATCH 4909/4982] ar9170: mac/bbp and phy code MAC/BBP and PHY programming code Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ar9170/mac.c | 452 +++++++++++ drivers/net/wireless/ar9170/phy.c | 1240 +++++++++++++++++++++++++++++ 2 files changed, 1692 insertions(+) create mode 100644 drivers/net/wireless/ar9170/mac.c create mode 100644 drivers/net/wireless/ar9170/phy.c diff --git a/drivers/net/wireless/ar9170/mac.c b/drivers/net/wireless/ar9170/mac.c new file mode 100644 index 00000000000..c8fa3073169 --- /dev/null +++ b/drivers/net/wireless/ar9170/mac.c @@ -0,0 +1,452 @@ +/* + * Atheros AR9170 driver + * + * MAC programming + * + * Copyright 2008, Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, see + * http://www.gnu.org/licenses/. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * Copyright (c) 2007-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "ar9170.h" +#include "cmd.h" + +int ar9170_set_qos(struct ar9170 *ar) +{ + ar9170_regwrite_begin(ar); + + ar9170_regwrite(AR9170_MAC_REG_AC0_CW, ar->edcf[0].cw_min | + (ar->edcf[0].cw_max << 16)); + ar9170_regwrite(AR9170_MAC_REG_AC1_CW, ar->edcf[1].cw_min | + (ar->edcf[1].cw_max << 16)); + ar9170_regwrite(AR9170_MAC_REG_AC2_CW, ar->edcf[2].cw_min | + (ar->edcf[2].cw_max << 16)); + ar9170_regwrite(AR9170_MAC_REG_AC3_CW, ar->edcf[3].cw_min | + (ar->edcf[3].cw_max << 16)); + ar9170_regwrite(AR9170_MAC_REG_AC4_CW, ar->edcf[4].cw_min | + (ar->edcf[4].cw_max << 16)); + + ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_AIFS, + ((ar->edcf[0].aifs * 9 + 10)) | + ((ar->edcf[1].aifs * 9 + 10) << 12) | + ((ar->edcf[2].aifs * 9 + 10) << 24)); + ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_AIFS, + ((ar->edcf[2].aifs * 9 + 10) >> 8) | + ((ar->edcf[3].aifs * 9 + 10) << 4) | + ((ar->edcf[4].aifs * 9 + 10) << 16)); + + ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_TXOP, + ar->edcf[0].txop | ar->edcf[1].txop << 16); + ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_TXOP, + ar->edcf[1].txop | ar->edcf[3].txop << 16); + + ar9170_regwrite_finish(); + + return ar9170_regwrite_result(); +} + +int ar9170_init_mac(struct ar9170 *ar) +{ + ar9170_regwrite_begin(ar); + + ar9170_regwrite(AR9170_MAC_REG_ACK_EXTENSION, 0x40); + + ar9170_regwrite(AR9170_MAC_REG_RETRY_MAX, 0); + + /* enable MMIC */ + ar9170_regwrite(AR9170_MAC_REG_SNIFFER, + AR9170_MAC_REG_SNIFFER_DEFAULTS); + + ar9170_regwrite(AR9170_MAC_REG_RX_THRESHOLD, 0xc1f80); + + ar9170_regwrite(AR9170_MAC_REG_RX_PE_DELAY, 0x70); + ar9170_regwrite(AR9170_MAC_REG_EIFS_AND_SIFS, 0xa144000); + ar9170_regwrite(AR9170_MAC_REG_SLOT_TIME, 9 << 10); + + /* CF-END mode */ + ar9170_regwrite(0x1c3b2c, 0x19000000); + + /* NAV protects ACK only (in TXOP) */ + ar9170_regwrite(0x1c3b38, 0x201); + + /* Set Beacon PHY CTRL's TPC to 0x7, TA1=1 */ + /* OTUS set AM to 0x1 */ + ar9170_regwrite(AR9170_MAC_REG_BCN_HT1, 0x8000170); + + ar9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105); + + /* AGG test code*/ + /* Aggregation MAX number and timeout */ + ar9170_regwrite(0x1c3b9c, 0x10000a); + + ar9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER, + AR9170_MAC_REG_FTF_DEFAULTS); + + /* Enable deaggregator, response in sniffer mode */ + ar9170_regwrite(0x1c3c40, 0x1 | 1<<30); + + /* rate sets */ + ar9170_regwrite(AR9170_MAC_REG_BASIC_RATE, 0x150f); + ar9170_regwrite(AR9170_MAC_REG_MANDATORY_RATE, 0x150f); + ar9170_regwrite(AR9170_MAC_REG_RTS_CTS_RATE, 0x10b01bb); + + /* MIMO response control */ + ar9170_regwrite(0x1c3694, 0x4003C1E);/* bit 26~28 otus-AM */ + + /* switch MAC to OTUS interface */ + ar9170_regwrite(0x1c3600, 0x3); + + ar9170_regwrite(AR9170_MAC_REG_AMPDU_RX_THRESH, 0xffff); + + /* set PHY register read timeout (??) */ + ar9170_regwrite(AR9170_MAC_REG_MISC_680, 0xf00008); + + /* Disable Rx TimeOut, workaround for BB. */ + ar9170_regwrite(AR9170_MAC_REG_RX_TIMEOUT, 0x0); + + /* Set CPU clock frequency to 88/80MHz */ + ar9170_regwrite(AR9170_PWR_REG_CLOCK_SEL, + AR9170_PWR_CLK_AHB_80_88MHZ | + AR9170_PWR_CLK_DAC_160_INV_DLY); + + /* Set WLAN DMA interrupt mode: generate int per packet */ + ar9170_regwrite(AR9170_MAC_REG_TXRX_MPI, 0x110011); + + ar9170_regwrite(AR9170_MAC_REG_FCS_SELECT, + AR9170_MAC_FCS_FIFO_PROT); + + /* Disables the CF_END frame, undocumented register */ + ar9170_regwrite(AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND, + 0x141E0F48); + + ar9170_regwrite_finish(); + + return ar9170_regwrite_result(); +} + +static int ar9170_set_mac_reg(struct ar9170 *ar, const u32 reg, const u8 *mac) +{ + static const u8 zero[ETH_ALEN] = { 0 }; + + if (!mac) + mac = zero; + + ar9170_regwrite_begin(ar); + + ar9170_regwrite(reg, + (mac[3] << 24) | (mac[2] << 16) | + (mac[1] << 8) | mac[0]); + + ar9170_regwrite(reg + 4, (mac[5] << 8) | mac[4]); + + ar9170_regwrite_finish(); + + return ar9170_regwrite_result(); +} + +int ar9170_update_multicast(struct ar9170 *ar) +{ + int err; + + ar9170_regwrite_begin(ar); + ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, + ar->want_mc_hash >> 32); + ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, + ar->want_mc_hash); + + ar9170_regwrite_finish(); + err = ar9170_regwrite_result(); + + if (err) + return err; + + ar->cur_mc_hash = ar->want_mc_hash; + + return 0; +} + +int ar9170_update_frame_filter(struct ar9170 *ar) +{ + int err; + + err = ar9170_write_reg(ar, AR9170_MAC_REG_FRAMETYPE_FILTER, + ar->want_filter); + + if (err) + return err; + + ar->cur_filter = ar->want_filter; + + return 0; +} + +static int ar9170_set_promiscouous(struct ar9170 *ar) +{ + u32 encr_mode, sniffer; + int err; + + err = ar9170_read_reg(ar, AR9170_MAC_REG_SNIFFER, &sniffer); + if (err) + return err; + + err = ar9170_read_reg(ar, AR9170_MAC_REG_ENCRYPTION, &encr_mode); + if (err) + return err; + + if (ar->sniffer_enabled) { + sniffer |= AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC; + + /* + * Rx decryption works in place. + * + * If we don't disable it, the hardware will render all + * encrypted frames which are encrypted with an unknown + * key useless. + */ + + encr_mode |= AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; + ar->sniffer_enabled = true; + } else { + sniffer &= ~AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC; + + if (ar->rx_software_decryption) + encr_mode |= AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; + else + encr_mode &= ~AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; + } + + ar9170_regwrite_begin(ar); + ar9170_regwrite(AR9170_MAC_REG_ENCRYPTION, encr_mode); + ar9170_regwrite(AR9170_MAC_REG_SNIFFER, sniffer); + ar9170_regwrite_finish(); + + return ar9170_regwrite_result(); +} + +int ar9170_set_operating_mode(struct ar9170 *ar) +{ + u32 pm_mode = AR9170_MAC_REG_POWERMGT_DEFAULTS; + u8 *mac_addr, *bssid; + int err; + + if (ar->vif) { + mac_addr = ar->mac_addr; + bssid = ar->bssid; + + switch (ar->vif->type) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_ADHOC: + pm_mode |= AR9170_MAC_REG_POWERMGT_IBSS; + break; +/* case NL80211_IFTYPE_AP: + pm_mode |= AR9170_MAC_REG_POWERMGT_AP; + break;*/ + case NL80211_IFTYPE_WDS: + pm_mode |= AR9170_MAC_REG_POWERMGT_AP_WDS; + break; + case NL80211_IFTYPE_MONITOR: + ar->sniffer_enabled = true; + ar->rx_software_decryption = true; + break; + default: + pm_mode |= AR9170_MAC_REG_POWERMGT_STA; + break; + } + } else { + mac_addr = NULL; + bssid = NULL; + } + + err = ar9170_set_mac_reg(ar, AR9170_MAC_REG_MAC_ADDR_L, mac_addr); + if (err) + return err; + + err = ar9170_set_mac_reg(ar, AR9170_MAC_REG_BSSID_L, bssid); + if (err) + return err; + + err = ar9170_set_promiscouous(ar); + if (err) + return err; + + ar9170_regwrite_begin(ar); + + ar9170_regwrite(AR9170_MAC_REG_POWERMANAGEMENT, pm_mode); + ar9170_regwrite_finish(); + + return ar9170_regwrite_result(); +} + +int ar9170_set_hwretry_limit(struct ar9170 *ar, unsigned int max_retry) +{ + u32 tmp = min_t(u32, 0x33333, max_retry * 0x11111); + + return ar9170_write_reg(ar, AR9170_MAC_REG_RETRY_MAX, tmp); +} + +int ar9170_set_beacon_timers(struct ar9170 *ar) +{ + u32 v = 0; + u32 pretbtt = 0; + + v |= ar->hw->conf.beacon_int; + + if (ar->vif) { + switch (ar->vif->type) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_ADHOC: + v |= BIT(25); + break; + case NL80211_IFTYPE_AP: + v |= BIT(24); + pretbtt = (ar->hw->conf.beacon_int - 6) << 16; + break; + default: + break; + } + + v |= ar->vif->bss_conf.dtim_period << 16; + } + + ar9170_regwrite_begin(ar); + + ar9170_regwrite(AR9170_MAC_REG_PRETBTT, pretbtt); + ar9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, v); + ar9170_regwrite_finish(); + return ar9170_regwrite_result(); +} + +int ar9170_update_beacon(struct ar9170 *ar) +{ + struct sk_buff *skb; + __le32 *data, *old = NULL; + u32 word; + int i; + + skb = ieee80211_beacon_get(ar->hw, ar->vif); + if (!skb) + return -ENOMEM; + + data = (__le32 *)skb->data; + if (ar->beacon) + old = (__le32 *)ar->beacon->data; + + ar9170_regwrite_begin(ar); + for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) { + /* + * XXX: This accesses beyond skb data for up + * to the last 3 bytes!! + */ + + if (old && (data[i] == old[i])) + continue; + + word = le32_to_cpu(data[i]); + ar9170_regwrite(AR9170_BEACON_BUFFER_ADDRESS + 4 * i, word); + } + + /* XXX: use skb->cb info */ + if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) + ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP, + ((skb->len + 4) << (3+16)) + 0x0400); + else + ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP, + ((skb->len + 4) << (3+16)) + 0x0400); + + ar9170_regwrite(AR9170_MAC_REG_BCN_LENGTH, skb->len + 4); + ar9170_regwrite(AR9170_MAC_REG_BCN_ADDR, AR9170_BEACON_BUFFER_ADDRESS); + ar9170_regwrite(AR9170_MAC_REG_BCN_CTRL, 1); + + ar9170_regwrite_finish(); + + dev_kfree_skb(ar->beacon); + ar->beacon = skb; + + return ar9170_regwrite_result(); +} + +void ar9170_new_beacon(struct work_struct *work) +{ + struct ar9170 *ar = container_of(work, struct ar9170, + beacon_work); + struct sk_buff *skb; + + if (unlikely(!IS_STARTED(ar))) + return ; + + mutex_lock(&ar->mutex); + + if (!ar->vif) + goto out; + + ar9170_update_beacon(ar); + + rcu_read_lock(); + while ((skb = ieee80211_get_buffered_bc(ar->hw, ar->vif))) + ar9170_op_tx(ar->hw, skb); + + rcu_read_unlock(); + + out: + mutex_unlock(&ar->mutex); +} + +int ar9170_upload_key(struct ar9170 *ar, u8 id, const u8 *mac, u8 ktype, + u8 keyidx, u8 *keydata, int keylen) +{ + __le32 vals[7]; + static const u8 bcast[ETH_ALEN] = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + u8 dummy; + + mac = mac ? : bcast; + + vals[0] = cpu_to_le32((keyidx << 16) + id); + vals[1] = cpu_to_le32(mac[1] << 24 | mac[0] << 16 | ktype); + vals[2] = cpu_to_le32(mac[5] << 24 | mac[4] << 16 | + mac[3] << 8 | mac[2]); + memset(&vals[3], 0, 16); + if (keydata) + memcpy(&vals[3], keydata, keylen); + + return ar->exec_cmd(ar, AR9170_CMD_EKEY, + sizeof(vals), (u8 *)vals, + 1, &dummy); +} + +int ar9170_disable_key(struct ar9170 *ar, u8 id) +{ + __le32 val = cpu_to_le32(id); + u8 dummy; + + return ar->exec_cmd(ar, AR9170_CMD_EKEY, + sizeof(val), (u8 *)&val, + 1, &dummy); +} diff --git a/drivers/net/wireless/ar9170/phy.c b/drivers/net/wireless/ar9170/phy.c new file mode 100644 index 00000000000..6ce20754b8e --- /dev/null +++ b/drivers/net/wireless/ar9170/phy.c @@ -0,0 +1,1240 @@ +/* + * Atheros AR9170 driver + * + * PHY and RF code + * + * Copyright 2008, Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, see + * http://www.gnu.org/licenses/. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * Copyright (c) 2007-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include "ar9170.h" +#include "cmd.h" + +static int ar9170_init_power_cal(struct ar9170 *ar) +{ + ar9170_regwrite_begin(ar); + + ar9170_regwrite(0x1bc000 + 0x993c, 0x7f); + ar9170_regwrite(0x1bc000 + 0x9934, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0x9938, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0xa234, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0xa238, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0xa38c, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0xa390, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0xa3cc, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0xa3d0, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0xa3d4, 0x3f3f3f3f); + + ar9170_regwrite_finish(); + return ar9170_regwrite_result(); +} + +struct ar9170_phy_init { + u32 reg, _5ghz_20, _5ghz_40, _2ghz_40, _2ghz_20; +}; + +static struct ar9170_phy_init ar5416_phy_init[] = { + { 0x1c5800, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, + { 0x1c5804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, }, + { 0x1c5808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c580c, 0xad848e19, 0xad848e19, 0xad848e19, 0xad848e19, }, + { 0x1c5810, 0x7d14e000, 0x7d14e000, 0x7d14e000, 0x7d14e000, }, + { 0x1c5814, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, }, + { 0x1c5818, 0x00000090, 0x00000090, 0x00000090, 0x00000090, }, + { 0x1c581c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, }, + { 0x1c5824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, }, + { 0x1c5828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, }, + { 0x1c582c, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, }, + { 0x1c5830, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, }, + { 0x1c5838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, + { 0x1c583c, 0x00200400, 0x00200400, 0x00200400, 0x00200400, }, + { 0x1c5840, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e, }, + { 0x1c5844, 0x1372161e, 0x13721c1e, 0x13721c24, 0x137216a4, }, + { 0x1c5848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, }, + { 0x1c584c, 0x1284233c, 0x1284233c, 0x1284233c, 0x1284233c, }, + { 0x1c5850, 0x6c48b4e4, 0x6c48b4e4, 0x6c48b0e4, 0x6c48b0e4, }, + { 0x1c5854, 0x00000859, 0x00000859, 0x00000859, 0x00000859, }, + { 0x1c5858, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, }, + { 0x1c585c, 0x31395c5e, 0x31395c5e, 0x31395c5e, 0x31395c5e, }, + { 0x1c5860, 0x0004dd10, 0x0004dd10, 0x0004dd20, 0x0004dd20, }, + { 0x1c5868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, }, + { 0x1c586c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, }, + { 0x1c5900, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5904, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5908, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c590c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, }, + { 0x1c5918, 0x00000118, 0x00000230, 0x00000268, 0x00000134, }, + { 0x1c591c, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff, }, + { 0x1c5920, 0x0510081c, 0x0510081c, 0x0510001c, 0x0510001c, }, + { 0x1c5924, 0xd0058a15, 0xd0058a15, 0xd0058a15, 0xd0058a15, }, + { 0x1c5928, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, + { 0x1c592c, 0x00000004, 0x00000004, 0x00000004, 0x00000004, }, + { 0x1c5934, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c5938, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c593c, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, }, + { 0x1c5944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, }, + { 0x1c5948, 0x9280b212, 0x9280b212, 0x9280b212, 0x9280b212, }, + { 0x1c594c, 0x00020028, 0x00020028, 0x00020028, 0x00020028, }, + { 0x1c5954, 0x5d50e188, 0x5d50e188, 0x5d50e188, 0x5d50e188, }, + { 0x1c5958, 0x00081fff, 0x00081fff, 0x00081fff, 0x00081fff, }, + { 0x1c5960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, + { 0x1c5964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, }, + { 0x1c5970, 0x190fb515, 0x190fb515, 0x190fb515, 0x190fb515, }, + { 0x1c5974, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5978, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, + { 0x1c597c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5980, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5984, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5988, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c598c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5990, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5994, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5998, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c599c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c59a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c59a4, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, + { 0x1c59a8, 0x001fff00, 0x001fff00, 0x001fff00, 0x001fff00, }, + { 0x1c59ac, 0x006f00c4, 0x006f00c4, 0x006f00c4, 0x006f00c4, }, + { 0x1c59b0, 0x03051000, 0x03051000, 0x03051000, 0x03051000, }, + { 0x1c59b4, 0x00000820, 0x00000820, 0x00000820, 0x00000820, }, + { 0x1c59c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, }, + { 0x1c59c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, }, + { 0x1c59c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, }, + { 0x1c59cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, }, + { 0x1c59d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, }, + { 0x1c59d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c59d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c59dc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c59e0, 0x00000200, 0x00000200, 0x00000200, 0x00000200, }, + { 0x1c59e4, 0x64646464, 0x64646464, 0x64646464, 0x64646464, }, + { 0x1c59e8, 0x3c787878, 0x3c787878, 0x3c787878, 0x3c787878, }, + { 0x1c59ec, 0x000000aa, 0x000000aa, 0x000000aa, 0x000000aa, }, + { 0x1c59f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c59fc, 0x00001042, 0x00001042, 0x00001042, 0x00001042, }, + { 0x1c5a00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5a04, 0x00000040, 0x00000040, 0x00000040, 0x00000040, }, + { 0x1c5a08, 0x00000080, 0x00000080, 0x00000080, 0x00000080, }, + { 0x1c5a0c, 0x000001a1, 0x000001a1, 0x00000141, 0x00000141, }, + { 0x1c5a10, 0x000001e1, 0x000001e1, 0x00000181, 0x00000181, }, + { 0x1c5a14, 0x00000021, 0x00000021, 0x000001c1, 0x000001c1, }, + { 0x1c5a18, 0x00000061, 0x00000061, 0x00000001, 0x00000001, }, + { 0x1c5a1c, 0x00000168, 0x00000168, 0x00000041, 0x00000041, }, + { 0x1c5a20, 0x000001a8, 0x000001a8, 0x000001a8, 0x000001a8, }, + { 0x1c5a24, 0x000001e8, 0x000001e8, 0x000001e8, 0x000001e8, }, + { 0x1c5a28, 0x00000028, 0x00000028, 0x00000028, 0x00000028, }, + { 0x1c5a2c, 0x00000068, 0x00000068, 0x00000068, 0x00000068, }, + { 0x1c5a30, 0x00000189, 0x00000189, 0x000000a8, 0x000000a8, }, + { 0x1c5a34, 0x000001c9, 0x000001c9, 0x00000169, 0x00000169, }, + { 0x1c5a38, 0x00000009, 0x00000009, 0x000001a9, 0x000001a9, }, + { 0x1c5a3c, 0x00000049, 0x00000049, 0x000001e9, 0x000001e9, }, + { 0x1c5a40, 0x00000089, 0x00000089, 0x00000029, 0x00000029, }, + { 0x1c5a44, 0x00000170, 0x00000170, 0x00000069, 0x00000069, }, + { 0x1c5a48, 0x000001b0, 0x000001b0, 0x00000190, 0x00000190, }, + { 0x1c5a4c, 0x000001f0, 0x000001f0, 0x000001d0, 0x000001d0, }, + { 0x1c5a50, 0x00000030, 0x00000030, 0x00000010, 0x00000010, }, + { 0x1c5a54, 0x00000070, 0x00000070, 0x00000050, 0x00000050, }, + { 0x1c5a58, 0x00000191, 0x00000191, 0x00000090, 0x00000090, }, + { 0x1c5a5c, 0x000001d1, 0x000001d1, 0x00000151, 0x00000151, }, + { 0x1c5a60, 0x00000011, 0x00000011, 0x00000191, 0x00000191, }, + { 0x1c5a64, 0x00000051, 0x00000051, 0x000001d1, 0x000001d1, }, + { 0x1c5a68, 0x00000091, 0x00000091, 0x00000011, 0x00000011, }, + { 0x1c5a6c, 0x000001b8, 0x000001b8, 0x00000051, 0x00000051, }, + { 0x1c5a70, 0x000001f8, 0x000001f8, 0x00000198, 0x00000198, }, + { 0x1c5a74, 0x00000038, 0x00000038, 0x000001d8, 0x000001d8, }, + { 0x1c5a78, 0x00000078, 0x00000078, 0x00000018, 0x00000018, }, + { 0x1c5a7c, 0x00000199, 0x00000199, 0x00000058, 0x00000058, }, + { 0x1c5a80, 0x000001d9, 0x000001d9, 0x00000098, 0x00000098, }, + { 0x1c5a84, 0x00000019, 0x00000019, 0x00000159, 0x00000159, }, + { 0x1c5a88, 0x00000059, 0x00000059, 0x00000199, 0x00000199, }, + { 0x1c5a8c, 0x00000099, 0x00000099, 0x000001d9, 0x000001d9, }, + { 0x1c5a90, 0x000000d9, 0x000000d9, 0x00000019, 0x00000019, }, + { 0x1c5a94, 0x000000f9, 0x000000f9, 0x00000059, 0x00000059, }, + { 0x1c5a98, 0x000000f9, 0x000000f9, 0x00000099, 0x00000099, }, + { 0x1c5a9c, 0x000000f9, 0x000000f9, 0x000000d9, 0x000000d9, }, + { 0x1c5aa0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5aa4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5aa8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5aac, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ab0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ab4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ab8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5abc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ac0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ac4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ac8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5acc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ad0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ad4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ad8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5adc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ae0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ae4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ae8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5aec, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5af0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5af4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5af8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5afc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5b00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5b04, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, + { 0x1c5b08, 0x00000002, 0x00000002, 0x00000002, 0x00000002, }, + { 0x1c5b0c, 0x00000003, 0x00000003, 0x00000003, 0x00000003, }, + { 0x1c5b10, 0x00000004, 0x00000004, 0x00000004, 0x00000004, }, + { 0x1c5b14, 0x00000005, 0x00000005, 0x00000005, 0x00000005, }, + { 0x1c5b18, 0x00000008, 0x00000008, 0x00000008, 0x00000008, }, + { 0x1c5b1c, 0x00000009, 0x00000009, 0x00000009, 0x00000009, }, + { 0x1c5b20, 0x0000000a, 0x0000000a, 0x0000000a, 0x0000000a, }, + { 0x1c5b24, 0x0000000b, 0x0000000b, 0x0000000b, 0x0000000b, }, + { 0x1c5b28, 0x0000000c, 0x0000000c, 0x0000000c, 0x0000000c, }, + { 0x1c5b2c, 0x0000000d, 0x0000000d, 0x0000000d, 0x0000000d, }, + { 0x1c5b30, 0x00000010, 0x00000010, 0x00000010, 0x00000010, }, + { 0x1c5b34, 0x00000011, 0x00000011, 0x00000011, 0x00000011, }, + { 0x1c5b38, 0x00000012, 0x00000012, 0x00000012, 0x00000012, }, + { 0x1c5b3c, 0x00000013, 0x00000013, 0x00000013, 0x00000013, }, + { 0x1c5b40, 0x00000014, 0x00000014, 0x00000014, 0x00000014, }, + { 0x1c5b44, 0x00000015, 0x00000015, 0x00000015, 0x00000015, }, + { 0x1c5b48, 0x00000018, 0x00000018, 0x00000018, 0x00000018, }, + { 0x1c5b4c, 0x00000019, 0x00000019, 0x00000019, 0x00000019, }, + { 0x1c5b50, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, }, + { 0x1c5b54, 0x0000001b, 0x0000001b, 0x0000001b, 0x0000001b, }, + { 0x1c5b58, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, }, + { 0x1c5b5c, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, }, + { 0x1c5b60, 0x00000020, 0x00000020, 0x00000020, 0x00000020, }, + { 0x1c5b64, 0x00000021, 0x00000021, 0x00000021, 0x00000021, }, + { 0x1c5b68, 0x00000022, 0x00000022, 0x00000022, 0x00000022, }, + { 0x1c5b6c, 0x00000023, 0x00000023, 0x00000023, 0x00000023, }, + { 0x1c5b70, 0x00000024, 0x00000024, 0x00000024, 0x00000024, }, + { 0x1c5b74, 0x00000025, 0x00000025, 0x00000025, 0x00000025, }, + { 0x1c5b78, 0x00000028, 0x00000028, 0x00000028, 0x00000028, }, + { 0x1c5b7c, 0x00000029, 0x00000029, 0x00000029, 0x00000029, }, + { 0x1c5b80, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a, }, + { 0x1c5b84, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, }, + { 0x1c5b88, 0x0000002c, 0x0000002c, 0x0000002c, 0x0000002c, }, + { 0x1c5b8c, 0x0000002d, 0x0000002d, 0x0000002d, 0x0000002d, }, + { 0x1c5b90, 0x00000030, 0x00000030, 0x00000030, 0x00000030, }, + { 0x1c5b94, 0x00000031, 0x00000031, 0x00000031, 0x00000031, }, + { 0x1c5b98, 0x00000032, 0x00000032, 0x00000032, 0x00000032, }, + { 0x1c5b9c, 0x00000033, 0x00000033, 0x00000033, 0x00000033, }, + { 0x1c5ba0, 0x00000034, 0x00000034, 0x00000034, 0x00000034, }, + { 0x1c5ba4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5ba8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bac, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bb0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bb4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bb8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bbc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bc0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bc4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bc8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bcc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bd0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bd4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bd8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bdc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5be0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5be4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5be8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bec, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bf0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bf4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bf8, 0x00000010, 0x00000010, 0x00000010, 0x00000010, }, + { 0x1c5bfc, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, }, + { 0x1c5c00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c0c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c10, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c14, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c18, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c1c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c24, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c28, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c2c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c30, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c34, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c38, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c3c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5cf0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5cf4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5cf8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5cfc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6200, 0x00000008, 0x00000008, 0x0000000e, 0x0000000e, }, + { 0x1c6204, 0x00000440, 0x00000440, 0x00000440, 0x00000440, }, + { 0x1c6208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, }, + { 0x1c620c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, + { 0x1c6210, 0x40806333, 0x40806333, 0x40806333, 0x40806333, }, + { 0x1c6214, 0x00106c10, 0x00106c10, 0x00106c10, 0x00106c10, }, + { 0x1c6218, 0x009c4060, 0x009c4060, 0x009c4060, 0x009c4060, }, + { 0x1c621c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, }, + { 0x1c6220, 0x018830c6, 0x018830c6, 0x018830c6, 0x018830c6, }, + { 0x1c6224, 0x00000400, 0x00000400, 0x00000400, 0x00000400, }, + { 0x1c6228, 0x000009b5, 0x000009b5, 0x000009b5, 0x000009b5, }, + { 0x1c622c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6230, 0x00000108, 0x00000210, 0x00000210, 0x00000108, }, + { 0x1c6234, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c6238, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c623c, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, }, + { 0x1c6240, 0x38490a20, 0x38490a20, 0x38490a20, 0x38490a20, }, + { 0x1c6244, 0x00007bb6, 0x00007bb6, 0x00007bb6, 0x00007bb6, }, + { 0x1c6248, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, }, + { 0x1c624c, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, + { 0x1c6250, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, }, + { 0x1c6254, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6258, 0x0cc75380, 0x0cc75380, 0x0cc75380, 0x0cc75380, }, + { 0x1c625c, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, }, + { 0x1c6260, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, }, + { 0x1c6264, 0x00418a11, 0x00418a11, 0x00418a11, 0x00418a11, }, + { 0x1c6268, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c626c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, + { 0x1c6274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, }, + { 0x1c6278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, + { 0x1c627c, 0x051701ce, 0x051701ce, 0x051701ce, 0x051701ce, }, + { 0x1c6300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, }, + { 0x1c6304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, }, + { 0x1c6308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, }, + { 0x1c630c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, }, + { 0x1c6310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, }, + { 0x1c6314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, }, + { 0x1c6318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, }, + { 0x1c631c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, }, + { 0x1c6320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, }, + { 0x1c6324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, }, + { 0x1c6328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, }, + { 0x1c632c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6338, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c633c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6340, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6344, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6348, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, + { 0x1c634c, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, + { 0x1c6350, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, + { 0x1c6354, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, }, + { 0x1c6358, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, }, + { 0x1c6388, 0x08000000, 0x08000000, 0x08000000, 0x08000000, }, + { 0x1c638c, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c6390, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c6394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, + { 0x1c6398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, }, + { 0x1c639c, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, + { 0x1c63a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63a4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63a8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63ac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63b0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63b4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63b8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63bc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63c0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63c4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63c8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63cc, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c63d0, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c63d4, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c63d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, + { 0x1c63e0, 0x000000c0, 0x000000c0, 0x000000c0, 0x000000c0, }, + { 0x1c6848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, }, + { 0x1c6920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, }, + { 0x1c6960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, + { 0x1c720c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, + { 0x1c726c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, + { 0x1c7848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, }, + { 0x1c7920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, }, + { 0x1c7960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, + { 0x1c820c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, + { 0x1c826c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, +/* { 0x1c8864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, }, */ + { 0x1c8864, 0x0001c600, 0x0001c600, 0x0001c600, 0x0001c600, }, + { 0x1c895c, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, }, + { 0x1c8968, 0x000003ce, 0x000003ce, 0x000003ce, 0x000003ce, }, + { 0x1c89bc, 0x00181400, 0x00181400, 0x00181400, 0x00181400, }, + { 0x1c9270, 0x00820820, 0x00820820, 0x00820820, 0x00820820, }, + { 0x1c935c, 0x066c420f, 0x066c420f, 0x066c420f, 0x066c420f, }, + { 0x1c9360, 0x0f282207, 0x0f282207, 0x0f282207, 0x0f282207, }, + { 0x1c9364, 0x17601685, 0x17601685, 0x17601685, 0x17601685, }, + { 0x1c9368, 0x1f801104, 0x1f801104, 0x1f801104, 0x1f801104, }, + { 0x1c936c, 0x37a00c03, 0x37a00c03, 0x37a00c03, 0x37a00c03, }, + { 0x1c9370, 0x3fc40883, 0x3fc40883, 0x3fc40883, 0x3fc40883, }, + { 0x1c9374, 0x57c00803, 0x57c00803, 0x57c00803, 0x57c00803, }, + { 0x1c9378, 0x5fd80682, 0x5fd80682, 0x5fd80682, 0x5fd80682, }, + { 0x1c937c, 0x7fe00482, 0x7fe00482, 0x7fe00482, 0x7fe00482, }, + { 0x1c9380, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, }, + { 0x1c9384, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, } +}; + +int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band) +{ + int i, err; + u32 val; + bool is_2ghz = band == IEEE80211_BAND_2GHZ; + bool is_40mhz = false; /* XXX: for now */ + + ar9170_regwrite_begin(ar); + + for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) { + if (is_40mhz) { + if (is_2ghz) + val = ar5416_phy_init[i]._2ghz_40; + else + val = ar5416_phy_init[i]._5ghz_40; + } else { + if (is_2ghz) + val = ar5416_phy_init[i]._2ghz_20; + else + val = ar5416_phy_init[i]._5ghz_20; + } + + ar9170_regwrite(ar5416_phy_init[i].reg, val); + } + + ar9170_regwrite_finish(); + err = ar9170_regwrite_result(); + if (err) + return err; + + /* XXX: use EEPROM data here! */ + + err = ar9170_init_power_cal(ar); + if (err) + return err; + + /* XXX: remove magic! */ + if (is_2ghz) + err = ar9170_write_reg(ar, 0x1d4014, 0x5163); + else + err = ar9170_write_reg(ar, 0x1d4014, 0x5143); + + return err; +} + +struct ar9170_rf_init { + u32 reg, _5ghz, _2ghz; +}; + +static struct ar9170_rf_init ar9170_rf_init[] = { + /* bank 0 */ + { 0x1c58b0, 0x1e5795e5, 0x1e5795e5}, + { 0x1c58e0, 0x02008020, 0x02008020}, + /* bank 1 */ + { 0x1c58b0, 0x02108421, 0x02108421}, + { 0x1c58ec, 0x00000008, 0x00000008}, + /* bank 2 */ + { 0x1c58b0, 0x0e73ff17, 0x0e73ff17}, + { 0x1c58e0, 0x00000420, 0x00000420}, + /* bank 3 */ + { 0x1c58f0, 0x01400018, 0x01c00018}, + /* bank 4 */ + { 0x1c58b0, 0x000001a1, 0x000001a1}, + { 0x1c58e8, 0x00000001, 0x00000001}, + /* bank 5 */ + { 0x1c58b0, 0x00000013, 0x00000013}, + { 0x1c58e4, 0x00000002, 0x00000002}, + /* bank 6 */ + { 0x1c58b0, 0x00000000, 0x00000000}, + { 0x1c58b0, 0x00000000, 0x00000000}, + { 0x1c58b0, 0x00000000, 0x00000000}, + { 0x1c58b0, 0x00000000, 0x00000000}, + { 0x1c58b0, 0x00000000, 0x00000000}, + { 0x1c58b0, 0x00004000, 0x00004000}, + { 0x1c58b0, 0x00006c00, 0x00006c00}, + { 0x1c58b0, 0x00002c00, 0x00002c00}, + { 0x1c58b0, 0x00004800, 0x00004800}, + { 0x1c58b0, 0x00004000, 0x00004000}, + { 0x1c58b0, 0x00006000, 0x00006000}, + { 0x1c58b0, 0x00001000, 0x00001000}, + { 0x1c58b0, 0x00004000, 0x00004000}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00087c00, 0x00087c00}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00005400, 0x00005400}, + { 0x1c58b0, 0x00000c00, 0x00000c00}, + { 0x1c58b0, 0x00001800, 0x00001800}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00006c00, 0x00006c00}, + { 0x1c58b0, 0x00006c00, 0x00006c00}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00002c00, 0x00002c00}, + { 0x1c58b0, 0x00003c00, 0x00003c00}, + { 0x1c58b0, 0x00003800, 0x00003800}, + { 0x1c58b0, 0x00001c00, 0x00001c00}, + { 0x1c58b0, 0x00000800, 0x00000800}, + { 0x1c58b0, 0x00000408, 0x00000408}, + { 0x1c58b0, 0x00004c15, 0x00004c15}, + { 0x1c58b0, 0x00004188, 0x00004188}, + { 0x1c58b0, 0x0000201e, 0x0000201e}, + { 0x1c58b0, 0x00010408, 0x00010408}, + { 0x1c58b0, 0x00000801, 0x00000801}, + { 0x1c58b0, 0x00000c08, 0x00000c08}, + { 0x1c58b0, 0x0000181e, 0x0000181e}, + { 0x1c58b0, 0x00001016, 0x00001016}, + { 0x1c58b0, 0x00002800, 0x00002800}, + { 0x1c58b0, 0x00004010, 0x00004010}, + { 0x1c58b0, 0x0000081c, 0x0000081c}, + { 0x1c58b0, 0x00000115, 0x00000115}, + { 0x1c58b0, 0x00000015, 0x00000015}, + { 0x1c58b0, 0x00000066, 0x00000066}, + { 0x1c58b0, 0x0000001c, 0x0000001c}, + { 0x1c58b0, 0x00000000, 0x00000000}, + { 0x1c58b0, 0x00000004, 0x00000004}, + { 0x1c58b0, 0x00000015, 0x00000015}, + { 0x1c58b0, 0x0000001f, 0x0000001f}, + { 0x1c58e0, 0x00000000, 0x00000400}, + /* bank 7 */ + { 0x1c58b0, 0x000000a0, 0x000000a0}, + { 0x1c58b0, 0x00000000, 0x00000000}, + { 0x1c58b0, 0x00000040, 0x00000040}, + { 0x1c58f0, 0x0000001c, 0x0000001c}, +}; + +static int ar9170_init_rf_banks_0_7(struct ar9170 *ar, bool band5ghz) +{ + int err, i; + + ar9170_regwrite_begin(ar); + + for (i = 0; i < ARRAY_SIZE(ar9170_rf_init); i++) + ar9170_regwrite(ar9170_rf_init[i].reg, + band5ghz ? ar9170_rf_init[i]._5ghz + : ar9170_rf_init[i]._2ghz); + + ar9170_regwrite_finish(); + err = ar9170_regwrite_result(); + if (err) + printk(KERN_ERR "%s: rf init failed\n", + wiphy_name(ar->hw->wiphy)); + return err; +} + +static int ar9170_init_rf_bank4_pwr(struct ar9170 *ar, bool band5ghz, + u32 freq, enum ar9170_bw bw) +{ + int err; + u32 d0, d1, td0, td1, fd0, fd1; + u8 chansel; + u8 refsel0 = 1, refsel1 = 0; + u8 lf_synth = 0; + + switch (bw) { + case AR9170_BW_40_ABOVE: + freq += 10; + break; + case AR9170_BW_40_BELOW: + freq -= 10; + break; + case AR9170_BW_20: + break; + case __AR9170_NUM_BW: + BUG(); + } + + if (band5ghz) { + if (freq % 10) { + chansel = (freq - 4800) / 5; + } else { + chansel = ((freq - 4800) / 10) * 2; + refsel0 = 0; + refsel1 = 1; + } + chansel = byte_rev_table[chansel]; + } else { + if (freq == 2484) { + chansel = 10 + (freq - 2274) / 5; + lf_synth = 1; + } else + chansel = 16 + (freq - 2272) / 5; + chansel *= 4; + chansel = byte_rev_table[chansel]; + } + + d1 = chansel; + d0 = 0x21 | + refsel0 << 3 | + refsel1 << 2 | + lf_synth << 1; + td0 = d0 & 0x1f; + td1 = d1 & 0x1f; + fd0 = td1 << 5 | td0; + + td0 = (d0 >> 5) & 0x7; + td1 = (d1 >> 5) & 0x7; + fd1 = td1 << 5 | td0; + + ar9170_regwrite_begin(ar); + + ar9170_regwrite(0x1c58b0, fd0); + ar9170_regwrite(0x1c58e8, fd1); + + ar9170_regwrite_finish(); + err = ar9170_regwrite_result(); + if (err) + return err; + + msleep(10); + + return 0; +} + +struct ar9170_phy_freq_params { + u8 coeff_exp; + u16 coeff_man; + u8 coeff_exp_shgi; + u16 coeff_man_shgi; +}; + +struct ar9170_phy_freq_entry { + u16 freq; + struct ar9170_phy_freq_params params[__AR9170_NUM_BW]; +}; + +/* NB: must be in sync with channel tables in main! */ +static const struct ar9170_phy_freq_entry ar9170_phy_freq_params[] = { +/* + * freq, + * 20MHz, + * 40MHz (below), + * 40Mhz (above), + */ + { 2412, { + { 3, 21737, 3, 19563, }, + { 3, 21827, 3, 19644, }, + { 3, 21647, 3, 19482, }, + } }, + { 2417, { + { 3, 21692, 3, 19523, }, + { 3, 21782, 3, 19604, }, + { 3, 21602, 3, 19442, }, + } }, + { 2422, { + { 3, 21647, 3, 19482, }, + { 3, 21737, 3, 19563, }, + { 3, 21558, 3, 19402, }, + } }, + { 2427, { + { 3, 21602, 3, 19442, }, + { 3, 21692, 3, 19523, }, + { 3, 21514, 3, 19362, }, + } }, + { 2432, { + { 3, 21558, 3, 19402, }, + { 3, 21647, 3, 19482, }, + { 3, 21470, 3, 19323, }, + } }, + { 2437, { + { 3, 21514, 3, 19362, }, + { 3, 21602, 3, 19442, }, + { 3, 21426, 3, 19283, }, + } }, + { 2442, { + { 3, 21470, 3, 19323, }, + { 3, 21558, 3, 19402, }, + { 3, 21382, 3, 19244, }, + } }, + { 2447, { + { 3, 21426, 3, 19283, }, + { 3, 21514, 3, 19362, }, + { 3, 21339, 3, 19205, }, + } }, + { 2452, { + { 3, 21382, 3, 19244, }, + { 3, 21470, 3, 19323, }, + { 3, 21295, 3, 19166, }, + } }, + { 2457, { + { 3, 21339, 3, 19205, }, + { 3, 21426, 3, 19283, }, + { 3, 21252, 3, 19127, }, + } }, + { 2462, { + { 3, 21295, 3, 19166, }, + { 3, 21382, 3, 19244, }, + { 3, 21209, 3, 19088, }, + } }, + { 2467, { + { 3, 21252, 3, 19127, }, + { 3, 21339, 3, 19205, }, + { 3, 21166, 3, 19050, }, + } }, + { 2472, { + { 3, 21209, 3, 19088, }, + { 3, 21295, 3, 19166, }, + { 3, 21124, 3, 19011, }, + } }, + { 2484, { + { 3, 21107, 3, 18996, }, + { 3, 21192, 3, 19073, }, + { 3, 21022, 3, 18920, }, + } }, + { 4920, { + { 4, 21313, 4, 19181, }, + { 4, 21356, 4, 19220, }, + { 4, 21269, 4, 19142, }, + } }, + { 4940, { + { 4, 21226, 4, 19104, }, + { 4, 21269, 4, 19142, }, + { 4, 21183, 4, 19065, }, + } }, + { 4960, { + { 4, 21141, 4, 19027, }, + { 4, 21183, 4, 19065, }, + { 4, 21098, 4, 18988, }, + } }, + { 4980, { + { 4, 21056, 4, 18950, }, + { 4, 21098, 4, 18988, }, + { 4, 21014, 4, 18912, }, + } }, + { 5040, { + { 4, 20805, 4, 18725, }, + { 4, 20846, 4, 18762, }, + { 4, 20764, 4, 18687, }, + } }, + { 5060, { + { 4, 20723, 4, 18651, }, + { 4, 20764, 4, 18687, }, + { 4, 20682, 4, 18614, }, + } }, + { 5080, { + { 4, 20641, 4, 18577, }, + { 4, 20682, 4, 18614, }, + { 4, 20601, 4, 18541, }, + } }, + { 5180, { + { 4, 20243, 4, 18219, }, + { 4, 20282, 4, 18254, }, + { 4, 20204, 4, 18183, }, + } }, + { 5200, { + { 4, 20165, 4, 18148, }, + { 4, 20204, 4, 18183, }, + { 4, 20126, 4, 18114, }, + } }, + { 5220, { + { 4, 20088, 4, 18079, }, + { 4, 20126, 4, 18114, }, + { 4, 20049, 4, 18044, }, + } }, + { 5240, { + { 4, 20011, 4, 18010, }, + { 4, 20049, 4, 18044, }, + { 4, 19973, 4, 17976, }, + } }, + { 5260, { + { 4, 19935, 4, 17941, }, + { 4, 19973, 4, 17976, }, + { 4, 19897, 4, 17907, }, + } }, + { 5280, { + { 4, 19859, 4, 17873, }, + { 4, 19897, 4, 17907, }, + { 4, 19822, 4, 17840, }, + } }, + { 5300, { + { 4, 19784, 4, 17806, }, + { 4, 19822, 4, 17840, }, + { 4, 19747, 4, 17772, }, + } }, + { 5320, { + { 4, 19710, 4, 17739, }, + { 4, 19747, 4, 17772, }, + { 4, 19673, 4, 17706, }, + } }, + { 5500, { + { 4, 19065, 4, 17159, }, + { 4, 19100, 4, 17190, }, + { 4, 19030, 4, 17127, }, + } }, + { 5520, { + { 4, 18996, 4, 17096, }, + { 4, 19030, 4, 17127, }, + { 4, 18962, 4, 17065, }, + } }, + { 5540, { + { 4, 18927, 4, 17035, }, + { 4, 18962, 4, 17065, }, + { 4, 18893, 4, 17004, }, + } }, + { 5560, { + { 4, 18859, 4, 16973, }, + { 4, 18893, 4, 17004, }, + { 4, 18825, 4, 16943, }, + } }, + { 5580, { + { 4, 18792, 4, 16913, }, + { 4, 18825, 4, 16943, }, + { 4, 18758, 4, 16882, }, + } }, + { 5600, { + { 4, 18725, 4, 16852, }, + { 4, 18758, 4, 16882, }, + { 4, 18691, 4, 16822, }, + } }, + { 5620, { + { 4, 18658, 4, 16792, }, + { 4, 18691, 4, 16822, }, + { 4, 18625, 4, 16762, }, + } }, + { 5640, { + { 4, 18592, 4, 16733, }, + { 4, 18625, 4, 16762, }, + { 4, 18559, 4, 16703, }, + } }, + { 5660, { + { 4, 18526, 4, 16673, }, + { 4, 18559, 4, 16703, }, + { 4, 18493, 4, 16644, }, + } }, + { 5680, { + { 4, 18461, 4, 16615, }, + { 4, 18493, 4, 16644, }, + { 4, 18428, 4, 16586, }, + } }, + { 5700, { + { 4, 18396, 4, 16556, }, + { 4, 18428, 4, 16586, }, + { 4, 18364, 4, 16527, }, + } }, + { 5745, { + { 4, 18252, 4, 16427, }, + { 4, 18284, 4, 16455, }, + { 4, 18220, 4, 16398, }, + } }, + { 5765, { + { 4, 18189, 5, 32740, }, + { 4, 18220, 4, 16398, }, + { 4, 18157, 5, 32683, }, + } }, + { 5785, { + { 4, 18126, 5, 32626, }, + { 4, 18157, 5, 32683, }, + { 4, 18094, 5, 32570, }, + } }, + { 5805, { + { 4, 18063, 5, 32514, }, + { 4, 18094, 5, 32570, }, + { 4, 18032, 5, 32458, }, + } }, + { 5825, { + { 4, 18001, 5, 32402, }, + { 4, 18032, 5, 32458, }, + { 4, 17970, 5, 32347, }, + } }, + { 5170, { + { 4, 20282, 4, 18254, }, + { 4, 20321, 4, 18289, }, + { 4, 20243, 4, 18219, }, + } }, + { 5190, { + { 4, 20204, 4, 18183, }, + { 4, 20243, 4, 18219, }, + { 4, 20165, 4, 18148, }, + } }, + { 5210, { + { 4, 20126, 4, 18114, }, + { 4, 20165, 4, 18148, }, + { 4, 20088, 4, 18079, }, + } }, + { 5230, { + { 4, 20049, 4, 18044, }, + { 4, 20088, 4, 18079, }, + { 4, 20011, 4, 18010, }, + } }, +}; + +static const struct ar9170_phy_freq_params * +ar9170_get_hw_dyn_params(struct ieee80211_channel *channel, + enum ar9170_bw bw) +{ + unsigned int chanidx = 0; + u16 freq = 2412; + + if (channel) { + chanidx = channel->hw_value; + freq = channel->center_freq; + } + + BUG_ON(chanidx >= ARRAY_SIZE(ar9170_phy_freq_params)); + + BUILD_BUG_ON(__AR9170_NUM_BW != 3); + + WARN_ON(ar9170_phy_freq_params[chanidx].freq != freq); + + return &ar9170_phy_freq_params[chanidx].params[bw]; +} + + +int ar9170_init_rf(struct ar9170 *ar) +{ + const struct ar9170_phy_freq_params *freqpar; + __le32 cmd[7]; + int err; + + err = ar9170_init_rf_banks_0_7(ar, false); + if (err) + return err; + + err = ar9170_init_rf_bank4_pwr(ar, false, 2412, AR9170_BW_20); + if (err) + return err; + + freqpar = ar9170_get_hw_dyn_params(NULL, AR9170_BW_20); + + cmd[0] = cpu_to_le32(2412 * 1000); + cmd[1] = cpu_to_le32(0); + cmd[2] = cpu_to_le32(1); + cmd[3] = cpu_to_le32(freqpar->coeff_exp); + cmd[4] = cpu_to_le32(freqpar->coeff_man); + cmd[5] = cpu_to_le32(freqpar->coeff_exp_shgi); + cmd[6] = cpu_to_le32(freqpar->coeff_man_shgi); + + /* RF_INIT echoes the command back to us */ + err = ar->exec_cmd(ar, AR9170_CMD_RF_INIT, + sizeof(cmd), (u8 *)cmd, + sizeof(cmd), (u8 *)cmd); + if (err) + return err; + + msleep(1000); + + return ar9170_echo_test(ar, 0xaabbccdd); +} + +static int ar9170_find_freq_idx(int nfreqs, u8 *freqs, u8 f) +{ + int idx = nfreqs - 2; + + while (idx >= 0) { + if (f >= freqs[idx]) + return idx; + idx--; + } + + return 0; +} + +static s32 ar9170_interpolate_s32(s32 x, s32 x1, s32 y1, s32 x2, s32 y2) +{ + /* nothing to interpolate, it's horizontal */ + if (y2 == y1) + return y1; + + /* check if we hit one of the edges */ + if (x == x1) + return y1; + if (x == x2) + return y2; + + /* x1 == x2 is bad, hopefully == x */ + if (x2 == x1) + return y1; + + return y1 + (((y2 - y1) * (x - x1)) / (x2 - x1)); +} + +static u8 ar9170_interpolate_u8(u8 x, u8 x1, u8 y1, u8 x2, u8 y2) +{ +#define SHIFT 8 + s32 y; + + y = ar9170_interpolate_s32(x << SHIFT, + x1 << SHIFT, y1 << SHIFT, + x2 << SHIFT, y2 << SHIFT); + + /* + * XXX: unwrap this expression + * Isn't it just DIV_ROUND_UP(y, 1<> SHIFT) + ((y & (1<<(SHIFT-1))) >> (SHIFT - 1)); +#undef SHIFT +} + +static int ar9170_set_power_cal(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) +{ + struct ar9170_calibration_target_power_legacy *ctpl; + struct ar9170_calibration_target_power_ht *ctph; + u8 *ctpres; + int ntargets; + int idx, i, n; + u8 ackpower, ackchains, f; + u8 pwr_freqs[AR5416_MAX_NUM_TGT_PWRS]; + + if (freq < 3000) + f = freq - 2300; + else + f = (freq - 4800)/5; + + /* + * cycle through the various modes + * + * legacy modes first: 5G, 2G CCK, 2G OFDM + */ + for (i = 0; i < 3; i++) { + switch (i) { + case 0: /* 5 GHz legacy */ + ctpl = &ar->eeprom.cal_tgt_pwr_5G[0]; + ntargets = AR5416_NUM_5G_TARGET_PWRS; + ctpres = ar->power_5G_leg; + break; + case 1: /* 2.4 GHz CCK */ + ctpl = &ar->eeprom.cal_tgt_pwr_2G_cck[0]; + ntargets = AR5416_NUM_2G_CCK_TARGET_PWRS; + ctpres = ar->power_2G_cck; + break; + case 2: /* 2.4 GHz OFDM */ + ctpl = &ar->eeprom.cal_tgt_pwr_2G_ofdm[0]; + ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; + ctpres = ar->power_2G_ofdm; + break; + default: + BUG(); + } + + for (n = 0; n < ntargets; n++) { + if (ctpl[n].freq == 0xff) + break; + pwr_freqs[n] = ctpl[n].freq; + } + ntargets = n; + idx = ar9170_find_freq_idx(ntargets, pwr_freqs, f); + for (n = 0; n < 4; n++) + ctpres[n] = ar9170_interpolate_u8( + f, + ctpl[idx + 0].freq, + ctpl[idx + 0].power[n], + ctpl[idx + 1].freq, + ctpl[idx + 1].power[n]); + } + + /* + * HT modes now: 5G HT20, 5G HT40, 2G CCK, 2G OFDM, 2G HT20, 2G HT40 + */ + for (i = 0; i < 4; i++) { + switch (i) { + case 0: /* 5 GHz HT 20 */ + ctph = &ar->eeprom.cal_tgt_pwr_5G_ht20[0]; + ntargets = AR5416_NUM_5G_TARGET_PWRS; + ctpres = ar->power_5G_ht20; + break; + case 1: /* 5 GHz HT 40 */ + ctph = &ar->eeprom.cal_tgt_pwr_5G_ht40[0]; + ntargets = AR5416_NUM_5G_TARGET_PWRS; + ctpres = ar->power_5G_ht40; + break; + case 2: /* 2.4 GHz HT 20 */ + ctph = &ar->eeprom.cal_tgt_pwr_2G_ht20[0]; + ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; + ctpres = ar->power_2G_ht20; + break; + case 3: /* 2.4 GHz HT 40 */ + ctph = &ar->eeprom.cal_tgt_pwr_2G_ht40[0]; + ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; + ctpres = ar->power_2G_ht40; + break; + default: + BUG(); + } + + for (n = 0; n < ntargets; n++) { + if (ctph[n].freq == 0xff) + break; + pwr_freqs[n] = ctph[n].freq; + } + ntargets = n; + idx = ar9170_find_freq_idx(ntargets, pwr_freqs, f); + for (n = 0; n < 8; n++) + ctpres[n] = ar9170_interpolate_u8( + f, + ctph[idx + 0].freq, + ctph[idx + 0].power[n], + ctph[idx + 1].freq, + ctph[idx + 1].power[n]); + } + + /* set ACK/CTS TX power */ + ar9170_regwrite_begin(ar); + + if (ar->eeprom.tx_mask != 1) + ackchains = AR9170_TX_PHY_TXCHAIN_2; + else + ackchains = AR9170_TX_PHY_TXCHAIN_1; + + if (freq < 3000) + ackpower = ar->power_2G_ofdm[0] & 0x3f; + else + ackpower = ar->power_5G_leg[0] & 0x3f; + + ar9170_regwrite(0x1c3694, ackpower << 20 | ackchains << 26); + ar9170_regwrite(0x1c3bb4, ackpower << 5 | ackchains << 11 | + ackpower << 21 | ackchains << 27); + + ar9170_regwrite_finish(); + return ar9170_regwrite_result(); +} + +static int ar9170_calc_noise_dbm(u32 raw_noise) +{ + if (raw_noise & 0x100) + return ~((raw_noise & 0x0ff) >> 1); + else + return (raw_noise & 0xff) >> 1; +} + +int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, + enum ar9170_rf_init_mode rfi, enum ar9170_bw bw) +{ + const struct ar9170_phy_freq_params *freqpar; + u32 cmd, tmp, offs; + __le32 vals[8]; + int i, err; + bool bandswitch; + + /* clear BB heavy clip enable */ + err = ar9170_write_reg(ar, 0x1c59e0, 0x200); + if (err) + return err; + + /* may be NULL at first setup */ + if (ar->channel) + bandswitch = ar->channel->band != channel->band; + else + bandswitch = true; + + /* HW workaround */ + if (!ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] && + channel->center_freq <= 2417) + bandswitch = true; + + err = ar->exec_cmd(ar, AR9170_CMD_FREQ_START, 0, NULL, 0, NULL); + if (err) + return err; + + if (rfi != AR9170_RFI_NONE || bandswitch) { + u32 val = 0x400; + + if (rfi == AR9170_RFI_COLD) + val = 0x800; + + /* warm/cold reset BB/ADDA */ + err = ar9170_write_reg(ar, 0x1d4004, val); + if (err) + return err; + + err = ar9170_write_reg(ar, 0x1d4004, 0x0); + if (err) + return err; + + err = ar9170_init_phy(ar, channel->band); + if (err) + return err; + + err = ar9170_init_rf_banks_0_7(ar, + channel->band == IEEE80211_BAND_5GHZ); + if (err) + return err; + + cmd = AR9170_CMD_RF_INIT; + } else { + cmd = AR9170_CMD_FREQUENCY; + } + + err = ar9170_init_rf_bank4_pwr(ar, + channel->band == IEEE80211_BAND_5GHZ, + channel->center_freq, bw); + if (err) + return err; + + switch (bw) { + case AR9170_BW_20: + tmp = 0x240; + offs = 0; + break; + case AR9170_BW_40_BELOW: + tmp = 0x2c4; + offs = 3; + break; + case AR9170_BW_40_ABOVE: + tmp = 0x2d4; + offs = 1; + break; + default: + BUG(); + return -ENOSYS; + } + + if (0 /* 2 streams capable */) + tmp |= 0x100; + + err = ar9170_write_reg(ar, 0x1c5804, tmp); + if (err) + return err; + + err = ar9170_set_power_cal(ar, channel->center_freq, bw); + if (err) + return err; + + freqpar = ar9170_get_hw_dyn_params(channel, bw); + + vals[0] = cpu_to_le32(channel->center_freq * 1000); + vals[1] = cpu_to_le32(bw == AR9170_BW_20 ? 0 : 1); + vals[2] = cpu_to_le32(offs << 2 | 1); + vals[3] = cpu_to_le32(freqpar->coeff_exp); + vals[4] = cpu_to_le32(freqpar->coeff_man); + vals[5] = cpu_to_le32(freqpar->coeff_exp_shgi); + vals[6] = cpu_to_le32(freqpar->coeff_man_shgi); + vals[7] = cpu_to_le32(1000); + + err = ar->exec_cmd(ar, cmd, sizeof(vals), (u8 *)vals, + sizeof(vals), (u8 *)vals); + if (err) + return err; + + for (i = 0; i < 2; i++) { + ar->noise[i] = ar9170_calc_noise_dbm( + (le32_to_cpu(vals[2 + i]) >> 19) & 0x1ff); + + ar->noise[i + 2] = ar9170_calc_noise_dbm( + (le32_to_cpu(vals[5 + i]) >> 23) & 0x1ff); + } + + ar->channel = channel; + return 0; +} -- GitLab From b63a2cb30405777033d58045c562a3b04d87d702 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 21 Mar 2009 23:05:48 +0100 Subject: [PATCH 4910/4982] ar9170: ar9170: USB frontend driver USB frontend driver code for Atheros' AR9170 modules. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ar9170/usb.c | 747 ++++++++++++++++++++++++++++++ drivers/net/wireless/ar9170/usb.h | 74 +++ 2 files changed, 821 insertions(+) create mode 100644 drivers/net/wireless/ar9170/usb.c create mode 100644 drivers/net/wireless/ar9170/usb.h diff --git a/drivers/net/wireless/ar9170/usb.c b/drivers/net/wireless/ar9170/usb.c new file mode 100644 index 00000000000..ede511e4047 --- /dev/null +++ b/drivers/net/wireless/ar9170/usb.c @@ -0,0 +1,747 @@ +/* + * Atheros AR9170 driver + * + * USB - frontend + * + * Copyright 2008, Johannes Berg + * Copyright 2009, Christian Lamparter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, see + * http://www.gnu.org/licenses/. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * Copyright (c) 2007-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include "ar9170.h" +#include "cmd.h" +#include "hw.h" +#include "usb.h" + +MODULE_AUTHOR("Christian Lamparter "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("USB Driver for Atheros AR9170 based devices"); +MODULE_FIRMWARE("ar9170-1.fw"); +MODULE_FIRMWARE("ar9170-2.fw"); + +static struct usb_device_id ar9170_usb_ids[] = { + /* Atheros 9170 */ + { USB_DEVICE(0x0cf3, 0x9170) }, + /* Atheros TG121N */ + { USB_DEVICE(0x0cf3, 0x1001) }, + /* D-Link DWA 160A */ + { USB_DEVICE(0x07d1, 0x3c10) }, + /* Netgear WNDA3100 */ + { USB_DEVICE(0x0846, 0x9010) }, + /* Netgear WN111 v2 */ + { USB_DEVICE(0x0846, 0x9001) }, + /* Zydas ZD1221 */ + { USB_DEVICE(0x0ace, 0x1221) }, + /* Z-Com UB81 BG */ + { USB_DEVICE(0x0cde, 0x0023) }, + /* Z-Com UB82 ABG */ + { USB_DEVICE(0x0cde, 0x0026) }, + /* Arcadyan WN7512 */ + { USB_DEVICE(0x083a, 0xf522) }, + /* Planex GWUS300 */ + { USB_DEVICE(0x2019, 0x5304) }, + /* IO-Data WNGDNUS2 */ + { USB_DEVICE(0x04bb, 0x093f) }, + + /* terminate */ + {} +}; +MODULE_DEVICE_TABLE(usb, ar9170_usb_ids); + +static void ar9170_usb_tx_urb_complete_free(struct urb *urb) +{ + struct sk_buff *skb = urb->context; + struct ar9170_usb *aru = (struct ar9170_usb *) + usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); + + if (!aru) { + dev_kfree_skb_irq(skb); + return ; + } + + ar9170_handle_tx_status(&aru->common, skb, false, + AR9170_TX_STATUS_COMPLETE); +} + +static void ar9170_usb_tx_urb_complete(struct urb *urb) +{ +} + +static void ar9170_usb_irq_completed(struct urb *urb) +{ + struct ar9170_usb *aru = urb->context; + + switch (urb->status) { + /* everything is fine */ + case 0: + break; + + /* disconnect */ + case -ENOENT: + case -ECONNRESET: + case -ENODEV: + case -ESHUTDOWN: + goto free; + + default: + goto resubmit; + } + + print_hex_dump_bytes("ar9170 irq: ", DUMP_PREFIX_OFFSET, + urb->transfer_buffer, urb->actual_length); + +resubmit: + usb_anchor_urb(urb, &aru->rx_submitted); + if (usb_submit_urb(urb, GFP_ATOMIC)) { + usb_unanchor_urb(urb); + goto free; + } + + return; + +free: + usb_buffer_free(aru->udev, 64, urb->transfer_buffer, urb->transfer_dma); +} + +static void ar9170_usb_rx_completed(struct urb *urb) +{ + struct sk_buff *skb = urb->context; + struct ar9170_usb *aru = (struct ar9170_usb *) + usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); + int err; + + if (!aru) + goto free; + + switch (urb->status) { + /* everything is fine */ + case 0: + break; + + /* disconnect */ + case -ENOENT: + case -ECONNRESET: + case -ENODEV: + case -ESHUTDOWN: + goto free; + + default: + goto resubmit; + } + + skb_put(skb, urb->actual_length); + ar9170_rx(&aru->common, skb); + +resubmit: + skb_reset_tail_pointer(skb); + skb_trim(skb, 0); + + usb_anchor_urb(urb, &aru->rx_submitted); + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err) { + usb_unanchor_urb(urb); + dev_kfree_skb_irq(skb); + } + + return ; + +free: + dev_kfree_skb_irq(skb); + return; +} + +static int ar9170_usb_prep_rx_urb(struct ar9170_usb *aru, + struct urb *urb, gfp_t gfp) +{ + struct sk_buff *skb; + + skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE + 32, gfp); + if (!skb) + return -ENOMEM; + + /* reserve some space for mac80211's radiotap */ + skb_reserve(skb, 32); + + usb_fill_bulk_urb(urb, aru->udev, + usb_rcvbulkpipe(aru->udev, AR9170_EP_RX), + skb->data, min(skb_tailroom(skb), + AR9170_MAX_RX_BUFFER_SIZE), + ar9170_usb_rx_completed, skb); + + return 0; +} + +static int ar9170_usb_alloc_rx_irq_urb(struct ar9170_usb *aru) +{ + struct urb *urb = NULL; + void *ibuf; + int err = -ENOMEM; + + /* initialize interrupt endpoint */ + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + goto out; + + ibuf = usb_buffer_alloc(aru->udev, 64, GFP_KERNEL, &urb->transfer_dma); + if (!ibuf) + goto out; + + usb_fill_int_urb(urb, aru->udev, + usb_rcvintpipe(aru->udev, AR9170_EP_IRQ), ibuf, + 64, ar9170_usb_irq_completed, aru, 1); + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + usb_anchor_urb(urb, &aru->rx_submitted); + err = usb_submit_urb(urb, GFP_KERNEL); + if (err) { + usb_unanchor_urb(urb); + usb_buffer_free(aru->udev, 64, urb->transfer_buffer, + urb->transfer_dma); + } + +out: + usb_free_urb(urb); + return err; +} + +static int ar9170_usb_alloc_rx_bulk_urbs(struct ar9170_usb *aru) +{ + struct urb *urb; + int i; + int err = -EINVAL; + + for (i = 0; i < AR9170_NUM_RX_URBS; i++) { + err = -ENOMEM; + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + goto err_out; + + err = ar9170_usb_prep_rx_urb(aru, urb, GFP_KERNEL); + if (err) { + usb_free_urb(urb); + goto err_out; + } + + usb_anchor_urb(urb, &aru->rx_submitted); + err = usb_submit_urb(urb, GFP_KERNEL); + if (err) { + usb_unanchor_urb(urb); + dev_kfree_skb_any((void *) urb->transfer_buffer); + usb_free_urb(urb); + goto err_out; + } + usb_free_urb(urb); + } + + /* the device now waiting for a firmware. */ + aru->common.state = AR9170_IDLE; + return 0; + +err_out: + + usb_kill_anchored_urbs(&aru->rx_submitted); + return err; +} + +static void ar9170_usb_cancel_urbs(struct ar9170_usb *aru) +{ + int ret; + + aru->common.state = AR9170_UNKNOWN_STATE; + + usb_unlink_anchored_urbs(&aru->tx_submitted); + + /* give the LED OFF command and the deauth frame a chance to air. */ + ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted, + msecs_to_jiffies(100)); + if (ret == 0) + dev_err(&aru->udev->dev, "kill pending tx urbs.\n"); + usb_poison_anchored_urbs(&aru->tx_submitted); + + usb_poison_anchored_urbs(&aru->rx_submitted); +} + +static int ar9170_usb_exec_cmd(struct ar9170 *ar, enum ar9170_cmd cmd, + unsigned int plen, void *payload, + unsigned int outlen, void *out) +{ + struct ar9170_usb *aru = (void *) ar; + struct urb *urb = NULL; + unsigned long flags; + int err = -ENOMEM; + + if (unlikely(!IS_ACCEPTING_CMD(ar))) + return -EPERM; + + if (WARN_ON(plen > AR9170_MAX_CMD_LEN - 4)) + return -EINVAL; + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (unlikely(!urb)) + goto err_free; + + ar->cmdbuf[0] = cpu_to_le32(plen); + ar->cmdbuf[0] |= cpu_to_le32(cmd << 8); + /* writing multiple regs fills this buffer already */ + if (plen && payload != (u8 *)(&ar->cmdbuf[1])) + memcpy(&ar->cmdbuf[1], payload, plen); + + spin_lock_irqsave(&aru->common.cmdlock, flags); + aru->readbuf = (u8 *)out; + aru->readlen = outlen; + spin_unlock_irqrestore(&aru->common.cmdlock, flags); + + usb_fill_int_urb(urb, aru->udev, + usb_sndbulkpipe(aru->udev, AR9170_EP_CMD), + aru->common.cmdbuf, plen + 4, + ar9170_usb_tx_urb_complete, NULL, 1); + + usb_anchor_urb(urb, &aru->tx_submitted); + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err) { + usb_unanchor_urb(urb); + usb_free_urb(urb); + goto err_unbuf; + } + usb_free_urb(urb); + + err = wait_for_completion_timeout(&aru->cmd_wait, HZ); + if (err == 0) { + err = -ETIMEDOUT; + goto err_unbuf; + } + + if (outlen >= 0 && aru->readlen != outlen) { + err = -EMSGSIZE; + goto err_unbuf; + } + + return 0; + +err_unbuf: + /* Maybe the device was removed in the second we were waiting? */ + if (IS_STARTED(ar)) { + dev_err(&aru->udev->dev, "no command feedback " + "received (%d).\n", err); + + /* provide some maybe useful debug information */ + print_hex_dump_bytes("ar9170 cmd: ", DUMP_PREFIX_NONE, + aru->common.cmdbuf, plen + 4); + dump_stack(); + } + + /* invalidate to avoid completing the next prematurely */ + spin_lock_irqsave(&aru->common.cmdlock, flags); + aru->readbuf = NULL; + aru->readlen = 0; + spin_unlock_irqrestore(&aru->common.cmdlock, flags); + +err_free: + + return err; +} + +static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb, + bool txstatus_needed, unsigned int extra_len) +{ + struct ar9170_usb *aru = (struct ar9170_usb *) ar; + struct urb *urb; + int err; + + if (unlikely(!IS_STARTED(ar))) { + /* Seriously, what were you drink... err... thinking!? */ + return -EPERM; + } + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (unlikely(!urb)) + return -ENOMEM; + + usb_fill_bulk_urb(urb, aru->udev, + usb_sndbulkpipe(aru->udev, AR9170_EP_TX), + skb->data, skb->len + extra_len, (txstatus_needed ? + ar9170_usb_tx_urb_complete : + ar9170_usb_tx_urb_complete_free), skb); + urb->transfer_flags |= URB_ZERO_PACKET; + + usb_anchor_urb(urb, &aru->tx_submitted); + err = usb_submit_urb(urb, GFP_ATOMIC); + if (unlikely(err)) + usb_unanchor_urb(urb); + + usb_free_urb(urb); + return err; +} + +static void ar9170_usb_callback_cmd(struct ar9170 *ar, u32 len , void *buffer) +{ + struct ar9170_usb *aru = (void *) ar; + unsigned long flags; + u32 in, out; + + if (!buffer) + return ; + + in = le32_to_cpup((__le32 *)buffer); + out = le32_to_cpu(ar->cmdbuf[0]); + + /* mask off length byte */ + out &= ~0xFF; + + if (aru->readlen >= 0) { + /* add expected length */ + out |= aru->readlen; + } else { + /* add obtained length */ + out |= in & 0xFF; + } + + /* + * Some commands (e.g: AR9170_CMD_FREQUENCY) have a variable response + * length and we cannot predict the correct length in advance. + * So we only check if we provided enough space for the data. + */ + if (unlikely(out < in)) { + dev_warn(&aru->udev->dev, "received invalid command response " + "got %d bytes, instead of %d bytes " + "and the resp length is %d bytes\n", + in, out, len); + print_hex_dump_bytes("ar9170 invalid resp: ", + DUMP_PREFIX_OFFSET, buffer, len); + /* + * Do not complete, then the command times out, + * and we get a stack trace from there. + */ + return ; + } + + spin_lock_irqsave(&aru->common.cmdlock, flags); + if (aru->readbuf && len > 0) { + memcpy(aru->readbuf, buffer + 4, len - 4); + aru->readbuf = NULL; + } + complete(&aru->cmd_wait); + spin_unlock_irqrestore(&aru->common.cmdlock, flags); +} + +static int ar9170_usb_upload(struct ar9170_usb *aru, const void *data, + size_t len, u32 addr, bool complete) +{ + int transfer, err; + u8 *buf = kmalloc(4096, GFP_KERNEL); + + if (!buf) + return -ENOMEM; + + while (len) { + transfer = min_t(int, len, 4096); + memcpy(buf, data, transfer); + + err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0), + 0x30 /* FW DL */, 0x40 | USB_DIR_OUT, + addr >> 8, 0, buf, transfer, 1000); + + if (err < 0) { + kfree(buf); + return err; + } + + len -= transfer; + data += transfer; + addr += transfer; + } + kfree(buf); + + if (complete) { + err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0), + 0x31 /* FW DL COMPLETE */, + 0x40 | USB_DIR_OUT, 0, 0, NULL, 0, 5000); + } + + return 0; +} + +static int ar9170_usb_request_firmware(struct ar9170_usb *aru) +{ + int err = 0; + + err = request_firmware(&aru->init_values, "ar9170-1.fw", + &aru->udev->dev); + if (err) { + dev_err(&aru->udev->dev, "file with init values not found.\n"); + return err; + } + + err = request_firmware(&aru->firmware, "ar9170-2.fw", &aru->udev->dev); + if (err) { + release_firmware(aru->init_values); + dev_err(&aru->udev->dev, "firmware file not found.\n"); + return err; + } + + return err; +} + +static int ar9170_usb_reset(struct ar9170_usb *aru) +{ + int ret, lock = (aru->intf->condition != USB_INTERFACE_BINDING); + + if (lock) { + ret = usb_lock_device_for_reset(aru->udev, aru->intf); + if (ret < 0) { + dev_err(&aru->udev->dev, "unable to lock device " + "for reset (%d).\n", ret); + return ret; + } + } + + ret = usb_reset_device(aru->udev); + if (lock) + usb_unlock_device(aru->udev); + + /* let it rest - for a second - */ + msleep(1000); + + return ret; +} + +static int ar9170_usb_upload_firmware(struct ar9170_usb *aru) +{ + int err; + + /* First, upload initial values to device RAM */ + err = ar9170_usb_upload(aru, aru->init_values->data, + aru->init_values->size, 0x102800, false); + if (err) { + dev_err(&aru->udev->dev, "firmware part 1 " + "upload failed (%d).\n", err); + return err; + } + + /* Then, upload the firmware itself and start it */ + return ar9170_usb_upload(aru, aru->firmware->data, aru->firmware->size, + 0x200000, true); +} + +static int ar9170_usb_init_transport(struct ar9170_usb *aru) +{ + struct ar9170 *ar = (void *) &aru->common; + int err; + + ar9170_regwrite_begin(ar); + + /* Set USB Rx stream mode MAX packet number to 2 */ + ar9170_regwrite(AR9170_USB_REG_MAX_AGG_UPLOAD, 0x4); + + /* Set USB Rx stream mode timeout to 10us */ + ar9170_regwrite(AR9170_USB_REG_UPLOAD_TIME_CTL, 0x80); + + ar9170_regwrite_finish(); + + err = ar9170_regwrite_result(); + if (err) + dev_err(&aru->udev->dev, "USB setup failed (%d).\n", err); + + return err; +} + +static void ar9170_usb_stop(struct ar9170 *ar) +{ + struct ar9170_usb *aru = (void *) ar; + int ret; + + if (IS_ACCEPTING_CMD(ar)) + aru->common.state = AR9170_STOPPED; + + /* lets wait a while until the tx - queues are dried out */ + ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted, + msecs_to_jiffies(1000)); + if (ret == 0) + dev_err(&aru->udev->dev, "kill pending tx urbs.\n"); + + usb_poison_anchored_urbs(&aru->tx_submitted); + + /* + * Note: + * So far we freed all tx urbs, but we won't dare to touch any rx urbs. + * Else we would end up with a unresponsive device... + */ +} + +static int ar9170_usb_open(struct ar9170 *ar) +{ + struct ar9170_usb *aru = (void *) ar; + int err; + + usb_unpoison_anchored_urbs(&aru->tx_submitted); + err = ar9170_usb_init_transport(aru); + if (err) { + usb_poison_anchored_urbs(&aru->tx_submitted); + return err; + } + + aru->common.state = AR9170_IDLE; + return 0; +} + +static int ar9170_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct ar9170_usb *aru; + struct ar9170 *ar; + struct usb_device *udev; + int err; + + aru = ar9170_alloc(sizeof(*aru)); + if (IS_ERR(aru)) { + err = PTR_ERR(aru); + goto out; + } + + udev = interface_to_usbdev(intf); + usb_get_dev(udev); + aru->udev = udev; + aru->intf = intf; + ar = &aru->common; + + usb_set_intfdata(intf, aru); + SET_IEEE80211_DEV(ar->hw, &udev->dev); + + init_usb_anchor(&aru->rx_submitted); + init_usb_anchor(&aru->tx_submitted); + init_completion(&aru->cmd_wait); + + aru->common.stop = ar9170_usb_stop; + aru->common.open = ar9170_usb_open; + aru->common.tx = ar9170_usb_tx; + aru->common.exec_cmd = ar9170_usb_exec_cmd; + aru->common.callback_cmd = ar9170_usb_callback_cmd; + + err = ar9170_usb_reset(aru); + if (err) + goto err_unlock; + + err = ar9170_usb_request_firmware(aru); + if (err) + goto err_unlock; + + err = ar9170_usb_alloc_rx_irq_urb(aru); + if (err) + goto err_freefw; + + err = ar9170_usb_alloc_rx_bulk_urbs(aru); + if (err) + goto err_unrx; + + err = ar9170_usb_upload_firmware(aru); + if (err) { + err = ar9170_echo_test(&aru->common, 0x60d43110); + if (err) { + /* force user invention, by disabling the device */ + err = usb_driver_set_configuration(aru->udev, -1); + dev_err(&aru->udev->dev, "device is in a bad state. " + "please reconnect it!\n"); + goto err_unrx; + } + } + + err = ar9170_usb_open(ar); + if (err) + goto err_unrx; + + err = ar9170_register(ar, &udev->dev); + + ar9170_usb_stop(ar); + if (err) + goto err_unrx; + + return 0; + +err_unrx: + ar9170_usb_cancel_urbs(aru); + +err_freefw: + release_firmware(aru->init_values); + release_firmware(aru->firmware); + +err_unlock: + usb_set_intfdata(intf, NULL); + usb_put_dev(udev); + ieee80211_free_hw(ar->hw); +out: + return err; +} + +static void ar9170_usb_disconnect(struct usb_interface *intf) +{ + struct ar9170_usb *aru = usb_get_intfdata(intf); + + if (!aru) + return; + + aru->common.state = AR9170_IDLE; + ar9170_unregister(&aru->common); + ar9170_usb_cancel_urbs(aru); + + release_firmware(aru->init_values); + release_firmware(aru->firmware); + + usb_put_dev(aru->udev); + usb_set_intfdata(intf, NULL); + ieee80211_free_hw(aru->common.hw); +} + +static struct usb_driver ar9170_driver = { + .name = "ar9170usb", + .probe = ar9170_usb_probe, + .disconnect = ar9170_usb_disconnect, + .id_table = ar9170_usb_ids, + .soft_unbind = 1, +}; + +static int __init ar9170_init(void) +{ + return usb_register(&ar9170_driver); +} + +static void __exit ar9170_exit(void) +{ + usb_deregister(&ar9170_driver); +} + +module_init(ar9170_init); +module_exit(ar9170_exit); diff --git a/drivers/net/wireless/ar9170/usb.h b/drivers/net/wireless/ar9170/usb.h new file mode 100644 index 00000000000..f5852924cd6 --- /dev/null +++ b/drivers/net/wireless/ar9170/usb.h @@ -0,0 +1,74 @@ +/* + * Atheros AR9170 USB driver + * + * Driver specific definitions + * + * Copyright 2008, Johannes Berg + * Copyright 2009, Christian Lamparter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, see + * http://www.gnu.org/licenses/. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * Copyright (c) 2007-2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef __USB_H +#define __USB_H + +#include +#include +#include +#include +#include +#include +#include +#include "eeprom.h" +#include "hw.h" +#include "ar9170.h" + +#define AR9170_NUM_RX_URBS 16 + +struct firmware; + +struct ar9170_usb { + struct ar9170 common; + struct usb_device *udev; + struct usb_interface *intf; + + struct usb_anchor rx_submitted; + struct usb_anchor tx_submitted; + + spinlock_t cmdlock; + struct completion cmd_wait; + int readlen; + u8 *readbuf; + + const struct firmware *init_values; + const struct firmware *firmware; +}; + +#endif /* __USB_H */ -- GitLab From 75ca88c9701bf8f65fc1f009f10dd64b0378b977 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 21 Mar 2009 23:11:49 +0100 Subject: [PATCH 4911/4982] ar9170: update Makefile, Kconfig and MAINTAINERS This patch update all necessary Makefile and Kconfig files. Now you can then enable ar9170 in the kernel configuration under: Device Drivers ---> [*] Network device support ---> Wireless LAN ---> [*] Wireless LAN (IEEE 802.11) Atheros AR9170 support Atheros AR9170 USB support Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- MAINTAINERS | 8 ++++++++ drivers/net/wireless/Kconfig | 1 + drivers/net/wireless/Makefile | 1 + drivers/net/wireless/ar9170/Kconfig | 28 ++++++++++++++++++++++++++++ drivers/net/wireless/ar9170/Makefile | 5 +++++ 5 files changed, 43 insertions(+) create mode 100644 drivers/net/wireless/ar9170/Kconfig create mode 100644 drivers/net/wireless/ar9170/Makefile diff --git a/MAINTAINERS b/MAINTAINERS index bdadcb3c3f4..64c89c215b0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -765,6 +765,14 @@ L: linux-wireless@vger.kernel.org L: ath9k-devel@lists.ath9k.org S: Supported +ATHEROS AR9170 WIRELESS DRIVER +P: Christian Lamparter +M: chunkeey@web.de +L: linux-wireless@vger.kernel.org +W: http://wireless.kernel.org/en/users/Drivers/ar9170 +S: Maintained +F: drivers/net/wireless/ar9170/ + ATI_REMOTE2 DRIVER P: Ville Syrjala M: syrjala@sci.fi diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 612fffe100a..8a0823588c5 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -485,6 +485,7 @@ config MWL8K source "drivers/net/wireless/p54/Kconfig" source "drivers/net/wireless/ath5k/Kconfig" source "drivers/net/wireless/ath9k/Kconfig" +source "drivers/net/wireless/ar9170/Kconfig" source "drivers/net/wireless/ipw2x00/Kconfig" source "drivers/net/wireless/iwlwifi/Kconfig" source "drivers/net/wireless/hostap/Kconfig" diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index d780487c420..5e7c9acb6be 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -57,5 +57,6 @@ obj-$(CONFIG_P54_COMMON) += p54/ obj-$(CONFIG_ATH5K) += ath5k/ obj-$(CONFIG_ATH9K) += ath9k/ +obj-$(CONFIG_AR9170_COMMON) += ar9170/ obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o diff --git a/drivers/net/wireless/ar9170/Kconfig b/drivers/net/wireless/ar9170/Kconfig new file mode 100644 index 00000000000..f6611876e28 --- /dev/null +++ b/drivers/net/wireless/ar9170/Kconfig @@ -0,0 +1,28 @@ +config AR9170_COMMON + tristate "Atheros AR9170 support" + depends on WLAN_80211 && MAC80211 && EXPERIMENTAL + help + This is common code for AR9170 based devices. + This module does nothing by itself - the USB/(SPI) frontends + also need to be enabled in order to support any devices. + + Say Y if you have the hardware, or M to build a module called + ar9170common. + +config AR9170_USB + tristate "Atheros AR9170 USB support" + depends on AR9170_COMMON && USB + select FW_LOADER + help + This is a driver for the Atheros "otus" 802.11n USB devices. + + These devices require additional firmware (2 files). + For now, these files can be downloaded from here: + http://wireless.kernel.org/en/users/Drivers/ar9170 + + If you choose to build a module, it'll be called ar9170usb. + +config AR9170_LEDS + bool + depends on AR9170_COMMON && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = AR9170_COMMON) + default y diff --git a/drivers/net/wireless/ar9170/Makefile b/drivers/net/wireless/ar9170/Makefile new file mode 100644 index 00000000000..59b174dd466 --- /dev/null +++ b/drivers/net/wireless/ar9170/Makefile @@ -0,0 +1,5 @@ +ar9170common-objs += main.o cmd.o mac.o phy.o led.o +ar9170usb-objs += usb.o + +obj-$(CONFIG_AR9170_COMMON) += ar9170common.o +obj-$(CONFIG_AR9170_USB) += ar9170usb.o -- GitLab From af83debf5bb44257082d4489ac86123a0cadf6d3 Mon Sep 17 00:00:00 2001 From: Tulio Magno Quites Machado Filho Date: Sun, 22 Mar 2009 01:41:13 +0100 Subject: [PATCH 4912/4982] ath5k: Support LED's on Acer Extensa 5620z Add vendor ID for Quanta Microsystems and update the led table with the reported device. Reported-by: Scott Barnes Signed-off-by: Tulio Magno Quites Machado Filho Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/led.c | 2 ++ include/linux/pci_ids.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/net/wireless/ath5k/led.c b/drivers/net/wireless/ath5k/led.c index 0686e12738b..19555fb79c9 100644 --- a/drivers/net/wireless/ath5k/led.c +++ b/drivers/net/wireless/ath5k/led.c @@ -65,6 +65,8 @@ static const struct pci_device_id ath5k_led_devices[] = { { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0422), ATH_LED(1, 1) }, /* E-machines E510 (tuliom@gmail.com) */ { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0428), ATH_LED(3, 0) }, + /* Acer Extensa 5620z (nekoreeve@gmail.com) */ + { ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0105), ATH_LED(3, 0) }, { } }; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 097f410edef..05dfa7c4fb6 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2271,6 +2271,8 @@ #define PCI_DEVICE_ID_KORENIX_JETCARDF0 0x1600 #define PCI_DEVICE_ID_KORENIX_JETCARDF1 0x16ff +#define PCI_VENDOR_ID_QMI 0x1a32 + #define PCI_VENDOR_ID_TEKRAM 0x1de1 #define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29 -- GitLab From 3cf335d527ba6af80f4143f3c9e5136afdb143af Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 22 Mar 2009 21:57:06 +0200 Subject: [PATCH 4913/4982] mac80211: decrease execution of the associated timer Currently the timer is triggering every two seconds (IEEE80211_MONITORING_INTERVAL). Decrease the timer to only trigger during data idle periods to avoid waking up CPU unnecessary. The timer will still trigger during idle periods, that needs to be fixed later. There's also a functional change that probe requests are sent only when the data path is idle, earlier they were sent also while there was activity on the data path. This is also preparation for the beacon filtering support. Thanks to Johannes Berg for the idea. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 2 ++ net/mac80211/mlme.c | 15 +++++++++++++++ net/mac80211/rx.c | 3 +++ 3 files changed, 20 insertions(+) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 564167fbb9a..055bb776408 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1083,6 +1083,8 @@ void ieee80211_dynamic_ps_timer(unsigned long data); void ieee80211_send_nullfunc(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, int powersave); +void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, + struct ieee80211_hdr *hdr); void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, enum queue_stop_reason reason); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index c05be09b9c6..209abb073df 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -909,6 +909,21 @@ static void ieee80211_associate(struct ieee80211_sub_if_data *sdata) mod_timer(&ifmgd->timer, jiffies + IEEE80211_ASSOC_TIMEOUT); } +void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, + struct ieee80211_hdr *hdr) +{ + /* + * We can postpone the mgd.timer whenever receiving unicast frames + * from AP because we know that the connection is working both ways + * at that time. But multicast frames (and hence also beacons) must + * be ignored here, because we need to trigger the timer during + * data idle periods for sending the periodical probe request to + * the AP. + */ + if (!is_multicast_ether_addr(hdr->addr1)) + mod_timer(&sdata->u.mgd.timer, + jiffies + IEEE80211_MONITORING_INTERVAL); +} static void ieee80211_associated(struct ieee80211_sub_if_data *sdata) { diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 47d395a5192..dbfb2846535 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -856,6 +856,9 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) if (!(rx->flags & IEEE80211_RX_RA_MATCH)) return RX_CONTINUE; + if (rx->sdata->vif.type == NL80211_IFTYPE_STATION) + ieee80211_sta_rx_notify(rx->sdata, hdr); + sta->rx_fragments++; sta->rx_bytes += rx->skb->len; sta->last_signal = rx->status->signal; -- GitLab From 15b7b0629c8213905926394dc73d600e0ca250ce Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 22 Mar 2009 21:57:14 +0200 Subject: [PATCH 4914/4982] mac80211: track beacons separately from the rx path activity Separate beacon and rx path tracking in preparation for the beacon filtering support. At the same time change ieee80211_associated() to look a bit simpler. Probe requests are now sent only after IEEE80211_PROBE_IDLE_TIME, which is now set to 60 seconds. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 1 + net/mac80211/mlme.c | 77 +++++++++++++++++++++++--------------- net/mac80211/rx.c | 6 ++- 3 files changed, 52 insertions(+), 32 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 055bb776408..8a617a7fc09 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -308,6 +308,7 @@ struct ieee80211_if_managed { unsigned long request; unsigned long last_probe; + unsigned long last_beacon; unsigned int flags; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 209abb073df..8f30f4d19da 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -30,7 +30,7 @@ #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) #define IEEE80211_ASSOC_MAX_TRIES 3 #define IEEE80211_MONITORING_INTERVAL (2 * HZ) -#define IEEE80211_PROBE_INTERVAL (60 * HZ) +#define IEEE80211_PROBE_IDLE_TIME (60 * HZ) #define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ) /* utils */ @@ -930,7 +930,7 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata) struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_local *local = sdata->local; struct sta_info *sta; - int disassoc; + bool disassoc = false; /* TODO: start monitoring current AP signal quality and number of * missed beacons. Scan other channels every now and then and search @@ -945,36 +945,39 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata) if (!sta) { printk(KERN_DEBUG "%s: No STA entry for own AP %pM\n", sdata->dev->name, ifmgd->bssid); - disassoc = 1; - } else { - disassoc = 0; - if (time_after(jiffies, - sta->last_rx + IEEE80211_MONITORING_INTERVAL)) { - if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) { - printk(KERN_DEBUG "%s: No ProbeResp from " - "current AP %pM - assume out of " - "range\n", - sdata->dev->name, ifmgd->bssid); - disassoc = 1; - } else - ieee80211_send_probe_req(sdata, ifmgd->bssid, - ifmgd->ssid, - ifmgd->ssid_len, - NULL, 0); - ifmgd->flags ^= IEEE80211_STA_PROBEREQ_POLL; - } else { - ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL; - if (time_after(jiffies, ifmgd->last_probe + - IEEE80211_PROBE_INTERVAL)) { - ifmgd->last_probe = jiffies; - ieee80211_send_probe_req(sdata, ifmgd->bssid, - ifmgd->ssid, - ifmgd->ssid_len, - NULL, 0); - } - } + disassoc = true; + goto unlock; + } + + if ((ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) && + time_after(jiffies, sta->last_rx + IEEE80211_MONITORING_INTERVAL)) { + printk(KERN_DEBUG "%s: no probe response from AP %pM " + "- disassociating\n", + sdata->dev->name, ifmgd->bssid); + disassoc = true; + ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL; + goto unlock; + } + + if (time_after(jiffies, + ifmgd->last_beacon + IEEE80211_MONITORING_INTERVAL)) { + printk(KERN_DEBUG "%s: beacon loss from AP %pM " + "- sending probe request\n", + sdata->dev->name, ifmgd->bssid); + ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL; + ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid, + ifmgd->ssid_len, NULL, 0); + goto unlock; + + } + + if (time_after(jiffies, sta->last_rx + IEEE80211_PROBE_IDLE_TIME)) { + ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL; + ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid, + ifmgd->ssid_len, NULL, 0); } + unlock: rcu_read_unlock(); if (disassoc) @@ -1374,6 +1377,12 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, bss_conf->assoc_capability = capab_info; ieee80211_set_associated(sdata, changed); + /* + * initialise the time of last beacon to be the association time, + * otherwise beacon loss check will trigger immediately + */ + ifmgd->last_beacon = jiffies; + ieee80211_associated(sdata); cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, len); } @@ -1422,9 +1431,12 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, size_t len, struct ieee80211_rx_status *rx_status) { + struct ieee80211_if_managed *ifmgd; size_t baselen; struct ieee802_11_elems elems; + ifmgd = &sdata->u.mgd; + if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) return; /* ignore ProbeResp to foreign address */ @@ -1439,11 +1451,14 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, /* direct probe may be part of the association flow */ if (test_and_clear_bit(IEEE80211_STA_REQ_DIRECT_PROBE, - &sdata->u.mgd.request)) { + &ifmgd->request)) { printk(KERN_DEBUG "%s direct probe responded\n", sdata->dev->name); ieee80211_authenticate(sdata); } + + if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) + ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL; } static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index dbfb2846535..eff59f36e8e 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -850,7 +850,11 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) * Mesh beacons will update last_rx when if they are found to * match the current local configuration when processed. */ - sta->last_rx = jiffies; + if (rx->sdata->vif.type == NL80211_IFTYPE_STATION && + ieee80211_is_beacon(hdr->frame_control)) { + rx->sdata->u.mgd.last_beacon = jiffies; + } else + sta->last_rx = jiffies; } if (!(rx->flags & IEEE80211_RX_RA_MATCH)) -- GitLab From 9050bdd8589c373e01e41ddbd9a192de2ff01ef0 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 22 Mar 2009 21:57:21 +0200 Subject: [PATCH 4915/4982] mac80211: disable power save when scanning When software scanning we need to disable power save so that all possible probe responses and beacons are received. For hardware scanning assume that hardware will take care of that and document that assumption. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- include/net/mac80211.h | 12 ++++---- net/mac80211/scan.c | 64 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 69 insertions(+), 7 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index daa539a4287..174dc1d7526 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1307,11 +1307,13 @@ enum ieee80211_ampdu_mlme_action { * * @hw_scan: Ask the hardware to service the scan request, no need to start * the scan state machine in stack. The scan must honour the channel - * configuration done by the regulatory agent in the wiphy's registered - * bands. When the scan finishes, ieee80211_scan_completed() must be - * called; note that it also must be called when the scan cannot finish - * because the hardware is turned off! Anything else is a bug! - * Returns a negative error code which will be seen in userspace. + * configuration done by the regulatory agent in the wiphy's + * registered bands. The hardware (or the driver) needs to make sure + * that power save is disabled. When the scan finishes, + * ieee80211_scan_completed() must be called; note that it also must + * be called when the scan cannot finish because the hardware is + * turned off! Anything else is a bug! Returns a negative error code + * which will be seen in userspace. * * @sw_scan_start: Notifier function that is called just before a software scan * is started. Can be NULL, if the driver doesn't need this notification. diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 46f35dc6acc..3bf9839f591 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -214,6 +214,66 @@ void ieee80211_scan_failed(struct ieee80211_local *local) local->scan_req = NULL; } +/* + * inform AP that we will go to sleep so that it will buffer the frames + * while we scan + */ +static void ieee80211_scan_ps_enable(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + bool ps = false; + + /* FIXME: what to do when local->pspolling is true? */ + + del_timer_sync(&local->dynamic_ps_timer); + cancel_work_sync(&local->dynamic_ps_enable_work); + + if (local->hw.conf.flags & IEEE80211_CONF_PS) { + ps = true; + local->hw.conf.flags &= ~IEEE80211_CONF_PS; + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + } + + if (!ps || !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) + /* + * If power save was enabled, no need to send a nullfunc + * frame because AP knows that we are sleeping. But if the + * hardware is creating the nullfunc frame for power save + * status (ie. IEEE80211_HW_PS_NULLFUNC_STACK is not + * enabled) and power save was enabled, the firmware just + * sent a null frame with power save disabled. So we need + * to send a new nullfunc frame to inform the AP that we + * are again sleeping. + */ + ieee80211_send_nullfunc(local, sdata, 1); +} + +/* inform AP that we are awake again, unless power save is enabled */ +static void ieee80211_scan_ps_disable(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + + if (!local->powersave) + ieee80211_send_nullfunc(local, sdata, 0); + else { + /* + * In !IEEE80211_HW_PS_NULLFUNC_STACK case the hardware + * will send a nullfunc frame with the powersave bit set + * even though the AP already knows that we are sleeping. + * This could be avoided by sending a null frame with power + * save bit disabled before enabling the power save, but + * this doesn't gain anything. + * + * When IEEE80211_HW_PS_NULLFUNC_STACK is enabled, no need + * to send a nullfunc frame because AP already knows that + * we are sleeping, let's just enable power save mode in + * hardware. + */ + local->hw.conf.flags |= IEEE80211_CONF_PS; + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + } +} + void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) { struct ieee80211_local *local = hw_to_local(hw); @@ -268,7 +328,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) /* Tell AP we're back */ if (sdata->vif.type == NL80211_IFTYPE_STATION) { if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED) { - ieee80211_send_nullfunc(local, sdata, 0); + ieee80211_scan_ps_disable(sdata); netif_tx_wake_all_queues(sdata->dev); } } else @@ -441,7 +501,7 @@ int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, if (sdata->vif.type == NL80211_IFTYPE_STATION) { if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED) { netif_tx_stop_all_queues(sdata->dev); - ieee80211_send_nullfunc(local, sdata, 1); + ieee80211_scan_ps_enable(sdata); } } else netif_tx_stop_all_queues(sdata->dev); -- GitLab From a08c1c1ac0c26229ca1ca45d554b209a56edc8be Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 22 Mar 2009 21:57:28 +0200 Subject: [PATCH 4916/4982] cfg80211: add feature to hold bss In beacon filtering there needs to be a way to not expire the BSS even when no beacons are received. Add an interface to cfg80211 to hold BSS and make sure that it's not expired. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- include/net/cfg80211.h | 18 ++++++++++++++++++ net/wireless/core.h | 2 ++ net/wireless/scan.c | 27 ++++++++++++++++++++++++++- 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index dca4a6b0461..5389afdc129 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -539,6 +539,7 @@ enum cfg80211_signal_type { * is no guarantee that these are well-formed!) * @len_information_elements: total length of the information elements * @signal: signal strength value (type depends on the wiphy's signal_type) + * @hold: BSS should not expire * @free_priv: function pointer to free private data * @priv: private area for driver use, has at least wiphy->bss_priv_size bytes */ @@ -940,4 +941,21 @@ void cfg80211_send_rx_deauth(struct net_device *dev, const u8 *buf, void cfg80211_send_rx_disassoc(struct net_device *dev, const u8 *buf, size_t len); +/** + * cfg80211_hold_bss - exclude bss from expiration + * @bss: bss which should not expire + * + * In a case when the BSS is not updated but it shouldn't expire this + * function can be used to mark the BSS to be excluded from expiration. + */ +void cfg80211_hold_bss(struct cfg80211_bss *bss); + +/** + * cfg80211_unhold_bss - remove expiration exception from the BSS + * @bss: bss which can expire again + * + * This function marks the BSS to be expirable again. + */ +void cfg80211_unhold_bss(struct cfg80211_bss *bss); + #endif /* __NET_CFG80211_H */ diff --git a/net/wireless/core.h b/net/wireless/core.h index 6acd483a61f..97a6fd8b2b0 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -90,6 +90,8 @@ struct cfg80211_internal_bss { struct rb_node rbn; unsigned long ts; struct kref ref; + bool hold; + /* must be last because of priv member */ struct cfg80211_bss pub; }; diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 280dbcd02c1..2a00e362f5f 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -80,7 +80,8 @@ void cfg80211_bss_expire(struct cfg80211_registered_device *dev) bool expired = false; list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) { - if (!time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE)) + if (bss->hold || + !time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE)) continue; list_del(&bss->list); rb_erase(&bss->rbn, &dev->bss_tree); @@ -471,6 +472,30 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub) } EXPORT_SYMBOL(cfg80211_unlink_bss); +void cfg80211_hold_bss(struct cfg80211_bss *pub) +{ + struct cfg80211_internal_bss *bss; + + if (!pub) + return; + + bss = container_of(pub, struct cfg80211_internal_bss, pub); + bss->hold = true; +} +EXPORT_SYMBOL(cfg80211_hold_bss); + +void cfg80211_unhold_bss(struct cfg80211_bss *pub) +{ + struct cfg80211_internal_bss *bss; + + if (!pub) + return; + + bss = container_of(pub, struct cfg80211_internal_bss, pub); + bss->hold = false; +} +EXPORT_SYMBOL(cfg80211_unhold_bss); + #ifdef CONFIG_WIRELESS_EXT int cfg80211_wext_siwscan(struct net_device *dev, struct iw_request_info *info, -- GitLab From 04de83815993714a7ba2618f637fa1092a5f664b Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 22 Mar 2009 21:57:35 +0200 Subject: [PATCH 4917/4982] mac80211: add beacon filtering support Add IEEE80211_HW_BEACON_FILTERING flag so that driver inform that it supports beacon filtering. Drivers need to call the new function ieee80211_beacon_loss() to notify about beacon loss. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- Documentation/DocBook/mac80211.tmpl | 6 ++++ include/net/mac80211.h | 33 +++++++++++++++++++ net/mac80211/ieee80211_i.h | 2 ++ net/mac80211/iface.c | 3 ++ net/mac80211/mlme.c | 49 ++++++++++++++++++++++++++++- 5 files changed, 92 insertions(+), 1 deletion(-) diff --git a/Documentation/DocBook/mac80211.tmpl b/Documentation/DocBook/mac80211.tmpl index 8af6d962687..fbeaffc1dcc 100644 --- a/Documentation/DocBook/mac80211.tmpl +++ b/Documentation/DocBook/mac80211.tmpl @@ -227,6 +227,12 @@ usage should require reading the full document. !Pinclude/net/mac80211.h Powersave support + + Beacon filter support +!Pinclude/net/mac80211.h Beacon filter support +!Finclude/net/mac80211.h ieee80211_beacon_loss + + Multiple queues and QoS support TBD diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 174dc1d7526..d881ed8ad2c 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -882,6 +882,10 @@ enum ieee80211_tkip_key_type { * * @IEEE80211_HW_MFP_CAPABLE: * Hardware supports management frame protection (MFP, IEEE 802.11w). + * + * @IEEE80211_HW_BEACON_FILTER: + * Hardware supports dropping of irrelevant beacon frames to + * avoid waking up cpu. */ enum ieee80211_hw_flags { IEEE80211_HW_RX_INCLUDES_FCS = 1<<1, @@ -897,6 +901,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_PS_NULLFUNC_STACK = 1<<11, IEEE80211_HW_SUPPORTS_DYNAMIC_PS = 1<<12, IEEE80211_HW_MFP_CAPABLE = 1<<13, + IEEE80211_HW_BEACON_FILTER = 1<<14, }; /** @@ -1120,6 +1125,24 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, * value, or by the stack if all nullfunc handling is in the stack. */ +/** + * DOC: Beacon filter support + * + * Some hardware have beacon filter support to reduce host cpu wakeups + * which will reduce system power consumption. It usuallly works so that + * the firmware creates a checksum of the beacon but omits all constantly + * changing elements (TSF, TIM etc). Whenever the checksum changes the + * beacon is forwarded to the host, otherwise it will be just dropped. That + * way the host will only receive beacons where some relevant information + * (for example ERP protection or WMM settings) have changed. + * + * Beacon filter support is informed with %IEEE80211_HW_BEACON_FILTER flag. + * The driver needs to enable beacon filter support whenever power save is + * enabled, that is %IEEE80211_CONF_PS is set. When power save is enabled, + * the stack will not check for beacon miss at all and the driver needs to + * notify about complete loss of beacons with ieee80211_beacon_loss(). + */ + /** * DOC: Frame filtering * @@ -1970,6 +1993,16 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, const u8 *addr); +/** + * ieee80211_beacon_loss - inform hardware does not receive beacons + * + * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. + * + * When beacon filtering is enabled with IEEE80211_HW_BEACON_FILTERING and + * IEEE80211_CONF_PS is set, the driver needs to inform whenever the + * hardware is not receiving beacons with this function. + */ +void ieee80211_beacon_loss(struct ieee80211_vif *vif); /* Rate control API */ diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 8a617a7fc09..acba78e1a5c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -275,6 +275,7 @@ struct ieee80211_if_managed { struct timer_list chswitch_timer; struct work_struct work; struct work_struct chswitch_work; + struct work_struct beacon_loss_work; u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; @@ -1086,6 +1087,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, int powersave); void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, struct ieee80211_hdr *hdr); +void ieee80211_beacon_loss_work(struct work_struct *work); void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, enum queue_stop_reason reason); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index dd2a276fa8c..91e8e1bacaa 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -477,6 +477,9 @@ static int ieee80211_stop(struct net_device *dev) */ cancel_work_sync(&sdata->u.mgd.work); cancel_work_sync(&sdata->u.mgd.chswitch_work); + + cancel_work_sync(&sdata->u.mgd.beacon_loss_work); + /* * When we get here, the interface is marked down. * Call synchronize_rcu() to wait for the RX path diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 8f30f4d19da..7ecda9d59d8 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -610,6 +610,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, bss_info_changed |= ieee80211_handle_bss_capability(sdata, bss->cbss.capability, bss->has_erp_value, bss->erp_value); + cfg80211_hold_bss(&bss->cbss); + ieee80211_rx_bss_put(local, bss); } @@ -751,6 +753,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_local *local = sdata->local; + struct ieee80211_conf *conf = &local_to_hw(local)->conf; + struct ieee80211_bss *bss; struct sta_info *sta; u32 changed = 0, config_changed = 0; @@ -774,6 +778,15 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, ieee80211_sta_tear_down_BA_sessions(sta); + bss = ieee80211_rx_bss_get(local, ifmgd->bssid, + conf->channel->center_freq, + ifmgd->ssid, ifmgd->ssid_len); + + if (bss) { + cfg80211_unhold_bss(&bss->cbss); + ieee80211_rx_bss_put(local, bss); + } + if (self_disconnected) { if (deauth) ieee80211_send_deauth_disassoc(sdata, @@ -925,6 +938,33 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, jiffies + IEEE80211_MONITORING_INTERVAL); } +void ieee80211_beacon_loss_work(struct work_struct *work) +{ + struct ieee80211_sub_if_data *sdata = + container_of(work, struct ieee80211_sub_if_data, + u.mgd.beacon_loss_work); + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + + printk(KERN_DEBUG "%s: driver reports beacon loss from AP %pM " + "- sending probe request\n", sdata->dev->name, + sdata->u.mgd.bssid); + + ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL; + ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid, + ifmgd->ssid_len, NULL, 0); + + mod_timer(&ifmgd->timer, jiffies + IEEE80211_MONITORING_INTERVAL); +} + +void ieee80211_beacon_loss(struct ieee80211_vif *vif) +{ + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + + queue_work(sdata->local->hw.workqueue, + &sdata->u.mgd.beacon_loss_work); +} +EXPORT_SYMBOL(ieee80211_beacon_loss); + static void ieee80211_associated(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; @@ -959,7 +999,13 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata) goto unlock; } - if (time_after(jiffies, + /* + * Beacon filtering is only enabled with power save and then the + * stack should not check for beacon loss. + */ + if (!((local->hw.flags & IEEE80211_HW_BEACON_FILTER) && + (local->hw.conf.flags & IEEE80211_CONF_PS)) && + time_after(jiffies, ifmgd->last_beacon + IEEE80211_MONITORING_INTERVAL)) { printk(KERN_DEBUG "%s: beacon loss from AP %pM " "- sending probe request\n", @@ -1869,6 +1915,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) ifmgd = &sdata->u.mgd; INIT_WORK(&ifmgd->work, ieee80211_sta_work); INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); + INIT_WORK(&ifmgd->beacon_loss_work, ieee80211_beacon_loss_work); setup_timer(&ifmgd->timer, ieee80211_sta_timer, (unsigned long) sdata); setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer, -- GitLab From 4a48e2a484e5cf99da4795cf2d6916e057d533ad Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Mon, 23 Mar 2009 12:15:43 +0100 Subject: [PATCH 4918/4982] ar9170: simplify & deBUG tx_status queueing and reporting This patch simplifies the tx_status report code by using four tx_queues per station instead of only one. (the skb lookup should be in O(1) now :-p ). Also, it fixes a really obvious copy&paste bug in the janitor work code and adds back a few spilled bits to the hardware definition header about QoS. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ar9170/ar9170.h | 2 +- drivers/net/wireless/ar9170/hw.h | 11 +++ drivers/net/wireless/ar9170/main.c | 139 +++++++-------------------- 3 files changed, 49 insertions(+), 103 deletions(-) diff --git a/drivers/net/wireless/ar9170/ar9170.h b/drivers/net/wireless/ar9170/ar9170.h index c49d7138d57..f4fb2e94aea 100644 --- a/drivers/net/wireless/ar9170/ar9170.h +++ b/drivers/net/wireless/ar9170/ar9170.h @@ -159,7 +159,7 @@ struct ar9170 { }; struct ar9170_sta_info { - struct sk_buff_head tx_status; + struct sk_buff_head tx_status[__AR9170_NUM_TXQ]; }; #define IS_STARTED(a) (a->state >= AR9170_STARTED) diff --git a/drivers/net/wireless/ar9170/hw.h b/drivers/net/wireless/ar9170/hw.h index ad205f82f60..13091bd9d81 100644 --- a/drivers/net/wireless/ar9170/hw.h +++ b/drivers/net/wireless/ar9170/hw.h @@ -397,10 +397,21 @@ struct ar9170_cmd_response { }; } __packed; +/* QoS */ + /* mac80211 queue to HW/FW map */ static const u8 ar9170_qos_hwmap[4] = { 3, 2, 0, 1 }; /* HW/FW queue to mac80211 map */ static const u8 ar9170_qos_mac80211map[4] = { 2, 3, 1, 0 }; +enum ar9170_txq { + AR9170_TXQ_BE, + AR9170_TXQ_BK, + AR9170_TXQ_VI, + AR9170_TXQ_VO, + + __AR9170_NUM_TXQ, +}; + #endif /* __AR9170_HW_H */ diff --git a/drivers/net/wireless/ar9170/main.c b/drivers/net/wireless/ar9170/main.c index a3b5323743c..f8c2357a173 100644 --- a/drivers/net/wireless/ar9170/main.c +++ b/drivers/net/wireless/ar9170/main.c @@ -277,54 +277,6 @@ static struct sk_buff *ar9170_find_skb_in_queue(struct ar9170 *ar, return NULL; } -static struct sk_buff *ar9170_find_skb_in_queue_by_mac(struct ar9170 *ar, - const u8 *mac, - struct sk_buff_head *q) -{ - unsigned long flags; - struct sk_buff *skb; - - spin_lock_irqsave(&q->lock, flags); - skb_queue_walk(q, skb) { - struct ar9170_tx_control *txc = (void *) skb->data; - struct ieee80211_hdr *hdr = (void *) txc->frame_data; - - if (compare_ether_addr(ieee80211_get_DA(hdr), mac)) - continue; - - __skb_unlink(skb, q); - spin_unlock_irqrestore(&q->lock, flags); - return skb; - } - spin_unlock_irqrestore(&q->lock, flags); - return NULL; -} - -static struct sk_buff *ar9170_find_skb_in_queue_by_txcq(struct ar9170 *ar, - const u32 queue, - struct sk_buff_head *q) -{ - unsigned long flags; - struct sk_buff *skb; - - spin_lock_irqsave(&q->lock, flags); - skb_queue_walk(q, skb) { - struct ar9170_tx_control *txc = (void *) skb->data; - u32 txc_queue = (le32_to_cpu(txc->phy_control) & - AR9170_TX_PHY_QOS_MASK) >> - AR9170_TX_PHY_QOS_SHIFT; - - if (queue != txc_queue) - continue; - - __skb_unlink(skb, q); - spin_unlock_irqrestore(&q->lock, flags); - return skb; - } - spin_unlock_irqrestore(&q->lock, flags); - return NULL; -} - static struct sk_buff *ar9170_find_queued_skb(struct ar9170 *ar, const u8 *mac, const u32 queue) { @@ -344,21 +296,21 @@ static struct sk_buff *ar9170_find_queued_skb(struct ar9170 *ar, const u8 *mac, if (likely(sta)) { struct ar9170_sta_info *sta_priv = (void *) sta->drv_priv; - skb = ar9170_find_skb_in_queue_by_txcq(ar, queue, - &sta_priv->tx_status); - } else { - /* STA is not in database (yet/anymore). */ + skb = skb_dequeue(&sta_priv->tx_status[queue]); + rcu_read_unlock(); + if (likely(skb)) + return skb; + } else + rcu_read_unlock(); - /* scan the waste bin for likely candidates */ + /* scan the waste queue for candidates */ + skb = ar9170_find_skb_in_queue(ar, mac, queue, + &ar->global_tx_status_waste); + if (!skb) { + /* so it still _must_ be in the global list. */ skb = ar9170_find_skb_in_queue(ar, mac, queue, - &ar->global_tx_status_waste); - if (!skb) { - /* so it still _must_ be in the global list. */ - skb = ar9170_find_skb_in_queue(ar, mac, queue, - &ar->global_tx_status); - } + &ar->global_tx_status); } - rcu_read_unlock(); #ifdef AR9170_QUEUE_DEBUG if (unlikely((!skb) && net_ratelimit())) { @@ -367,7 +319,6 @@ static struct sk_buff *ar9170_find_queued_skb(struct ar9170 *ar, const u8 *mac, wiphy_name(ar->hw->wiphy), mac, queue); } #endif /* AR9170_QUEUE_DEBUG */ - return skb; } @@ -381,9 +332,13 @@ static struct sk_buff *ar9170_find_queued_skb(struct ar9170 *ar, const u8 *mac, static void ar9170_tx_status_janitor(struct work_struct *work) { struct ar9170 *ar = container_of(work, struct ar9170, - filter_config_work); + tx_status_janitor.work); struct sk_buff *skb; + if (unlikely(!IS_STARTED(ar))) + return ; + + mutex_lock(&ar->mutex); /* recycle the garbage back to mac80211... one by one. */ while ((skb = skb_dequeue(&ar->global_tx_status_waste))) { #ifdef AR9170_QUEUE_DEBUG @@ -395,8 +350,6 @@ static void ar9170_tx_status_janitor(struct work_struct *work) AR9170_TX_STATUS_FAILED); } - - while ((skb = skb_dequeue(&ar->global_tx_status))) { #ifdef AR9170_QUEUE_DEBUG printk(KERN_DEBUG "%s: moving frame into waste queue =>\n", @@ -411,6 +364,8 @@ static void ar9170_tx_status_janitor(struct work_struct *work) if (skb_queue_len(&ar->global_tx_status_waste) > 0) queue_delayed_work(ar->hw->workqueue, &ar->tx_status_janitor, msecs_to_jiffies(100)); + + mutex_unlock(&ar->mutex); } static void ar9170_handle_command_response(struct ar9170 *ar, @@ -1012,7 +967,7 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) if (info->control.sta) { sta_info = (void *) info->control.sta->drv_priv; - skb_queue_tail(&sta_info->tx_status, skb); + skb_queue_tail(&sta_info->tx_status[queue], skb); } else { skb_queue_tail(&ar->global_tx_status, skb); @@ -1025,7 +980,7 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) err = ar->tx(ar, skb, tx_status, 0); if (unlikely(tx_status && err)) { if (info->control.sta) - skb_unlink(skb, &sta_info->tx_status); + skb_unlink(skb, &sta_info->tx_status[queue]); else skb_unlink(skb, &ar->global_tx_status); } @@ -1479,55 +1434,35 @@ static void ar9170_sta_notify(struct ieee80211_hw *hw, struct ar9170 *ar = hw->priv; struct ar9170_sta_info *info = (void *) sta->drv_priv; struct sk_buff *skb; + unsigned int i; switch (cmd) { case STA_NOTIFY_ADD: - skb_queue_head_init(&info->tx_status); - - /* - * do we already have a frame that needs tx_status - * from this station in our queue? - * If so then transfer them to the new station queue. - */ - - /* preserve the correct order - check the waste bin first */ - while ((skb = ar9170_find_skb_in_queue_by_mac(ar, sta->addr, - &ar->global_tx_status_waste))) - skb_queue_tail(&info->tx_status, skb); - - /* now the still pending frames */ - while ((skb = ar9170_find_skb_in_queue_by_mac(ar, sta->addr, - &ar->global_tx_status))) - skb_queue_tail(&info->tx_status, skb); - -#ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: STA[%pM] has %d queued frames =>\n", - wiphy_name(ar->hw->wiphy), sta->addr, - skb_queue_len(&info->tx_status)); - - ar9170_dump_station_tx_status_queue(ar, &info->tx_status); -#endif /* AR9170_QUEUE_DEBUG */ - - + for (i = 0; i < ar->hw->queues; i++) + skb_queue_head_init(&info->tx_status[i]); break; case STA_NOTIFY_REMOVE: /* * transfer all outstanding frames that need a tx_status - * reports to the fallback queue + * reports to the global tx_status queue */ - while ((skb = skb_dequeue(&ar->global_tx_status))) { + for (i = 0; i < ar->hw->queues; i++) { + while ((skb = skb_dequeue(&info->tx_status[i]))) { #ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: queueing frame in global " - "tx_status queue =>\n", - wiphy_name(ar->hw->wiphy)); + printk(KERN_DEBUG "%s: queueing frame in " + "global tx_status queue =>\n", + wiphy_name(ar->hw->wiphy)); - ar9170_print_txheader(ar, skb); + ar9170_print_txheader(ar, skb); #endif /* AR9170_QUEUE_DEBUG */ - skb_queue_tail(&ar->global_tx_status_waste, skb); + skb_queue_tail(&ar->global_tx_status, skb); + } } + queue_delayed_work(ar->hw->workqueue, &ar->tx_status_janitor, + msecs_to_jiffies(100)); break; default: @@ -1571,7 +1506,7 @@ static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, int ret; mutex_lock(&ar->mutex); - if ((param) && !(queue > 4)) { + if ((param) && !(queue > ar->hw->queues)) { memcpy(&ar->edcf[ar9170_qos_hwmap[queue]], param, sizeof(*param)); @@ -1635,7 +1570,7 @@ void *ar9170_alloc(size_t priv_size) IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; - ar->hw->queues = 4; + ar->hw->queues = __AR9170_NUM_TXQ; ar->hw->extra_tx_headroom = 8; ar->hw->sta_data_size = sizeof(struct ar9170_sta_info); -- GitLab From 2b874e83c970b45c328ab12239b066a43505454c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Mar 2009 14:10:22 +0100 Subject: [PATCH 4919/4982] mac80211: rate control status only for controlled packets This patch changes mac80211 to not notify the rate control algorithm's tx_status() method when reporting status for a packet that didn't go through the rate control algorithm's get_rate() method. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 4 ++++ net/mac80211/rate.c | 6 ++++-- net/mac80211/rate.h | 4 +++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index d881ed8ad2c..6f3bc4cc53e 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -245,6 +245,9 @@ struct ieee80211_bss_conf { * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be * set by rate control algorithms to indicate probe rate, will * be cleared for fragmented frames (except on the last fragment) + * @IEEE80211_TX_INTFL_RCALGO: mac80211 internal flag, do not test or + * set this flag in the driver; indicates that the rate control + * algorithm was used and should be notified of TX status */ enum mac80211_tx_control_flags { IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), @@ -260,6 +263,7 @@ enum mac80211_tx_control_flags { IEEE80211_TX_STAT_AMPDU = BIT(10), IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11), IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), + IEEE80211_TX_INTFL_RCALGO = BIT(13), }; /** diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 3fa7ab28506..4641f00a1e5 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -219,10 +219,12 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, info->control.rates[i].count = 1; } - if (sta && sdata->force_unicast_rateidx > -1) + if (sta && sdata->force_unicast_rateidx > -1) { info->control.rates[0].idx = sdata->force_unicast_rateidx; - else + } else { ref->ops->get_rate(ref->priv, ista, priv_sta, txrc); + info->flags |= IEEE80211_TX_INTFL_RCALGO; + } /* * try to enforce the maximum rate the user wanted diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index b9164c9a956..2ab5ad9e71c 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h @@ -44,8 +44,10 @@ static inline void rate_control_tx_status(struct ieee80211_local *local, struct rate_control_ref *ref = local->rate_ctrl; struct ieee80211_sta *ista = &sta->sta; void *priv_sta = sta->rate_ctrl_priv; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); + if (likely(info->flags & IEEE80211_TX_INTFL_RCALGO)) + ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); } -- GitLab From a1bfa0eb98e2fedd05a64a4a8943ea8f6f7c5469 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Mon, 23 Mar 2009 15:49:33 +0100 Subject: [PATCH 4920/4982] p54: Kconfig maintenance This patch updates p54's Kconfig entry and removes the out-dated device list. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/Kconfig | 32 ++++---------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/p54/Kconfig b/drivers/net/wireless/p54/Kconfig index 7d6e9d10820..b45d6a4ed1e 100644 --- a/drivers/net/wireless/p54/Kconfig +++ b/drivers/net/wireless/p54/Kconfig @@ -1,9 +1,10 @@ config P54_COMMON tristate "Softmac Prism54 support" - depends on MAC80211 && WLAN_80211 && FW_LOADER && EXPERIMENTAL + depends on MAC80211 && WLAN_80211 && EXPERIMENTAL + select FW_LOADER ---help--- - This is common code for isl38xx based cards. - This module does nothing by itself - the USB/PCI frontends + This is common code for isl38xx/stlc45xx based modules. + This module does nothing by itself - the USB/PCI/SPI front-ends also need to be enabled in order to support any devices. These devices require softmac firmware which can be found at @@ -17,31 +18,6 @@ config P54_USB select CRC32 ---help--- This driver is for USB isl38xx based wireless cards. - These are USB based adapters found in devices such as: - - 3COM 3CRWE254G72 - SMC 2862W-G - Accton 802.11g WN4501 USB - Siemens Gigaset USB - Netgear WG121 - Netgear WG111 - Medion 40900, Roper Europe - Shuttle PN15, Airvast WM168g, IOGear GWU513 - Linksys WUSB54G - Linksys WUSB54G Portable - DLink DWL-G120 Spinnaker - DLink DWL-G122 - Belkin F5D7050 ver 1000 - Cohiba Proto board - SMC 2862W-G version 2 - U.S. Robotics U5 802.11g Adapter - FUJITSU E-5400 USB D1700 - Sagem XG703A - DLink DWL-G120 Cohiba - Spinnaker Proto board - Linksys WUSB54AG - Inventel UR054G - Spinnaker DUT These devices require softmac firmware which can be found at http://prism54.org/ -- GitLab From a3c0b87c4f21911fb7185902dd13f0e3cd7f33f7 Mon Sep 17 00:00:00 2001 From: Lorenzo Nava Date: Sun, 22 Mar 2009 19:15:41 +0100 Subject: [PATCH 4921/4982] b43: fix b43_plcp_get_bitrate_idx_ofdm return type This patch fixes the return type of b43_plcp_get_bitrate_idx_ofdm. If the plcp contains an error, the function return value is 255 instead of -1, and the packet was not dropped. This causes a warning in __ieee80211_rx function because rate idx is out of range. Cc: stable@kernel.org Signed-off-by: Lorenzo Nava Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/xmit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 0f53c7e5e01..a63d88841df 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -50,7 +50,7 @@ static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp) } /* Extract the bitrate index out of an OFDM PLCP header. */ -static u8 b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy) +static int b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy) { int base = aphy ? 0 : 4; -- GitLab From b726604706ad88d8b28bc487e45e710f58cc19ee Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 2 Mar 2009 21:55:18 -0500 Subject: [PATCH 4922/4982] ath5k: warn and correct rate for unknown hw rate indexes ath5k sets up a mapping table from the hardware rate index to the rate index used by mac80211; however, we have seen some received frames with incorrect rate indexes. Such frames normally get dropped with a warning in __ieee80211_rx(), but it doesn't include enough information to track down the error. This patch adds a warning to hw_to_driver_rix for any lookups that result in a rate index of -1, then returns a valid rate so the frame can be processed. Changes-licensed-under: 3-Clause-BSD Signed-off-by: Bob Copeland Cc: stable@kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 15 ++++++++++++--- drivers/net/wireless/ath5k/base.h | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index f28b86c5d34..6580df2f744 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -1088,9 +1088,18 @@ ath5k_mode_setup(struct ath5k_softc *sc) static inline int ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix) { - WARN(hw_rix < 0 || hw_rix >= AR5K_MAX_RATES, - "hw_rix out of bounds: %x\n", hw_rix); - return sc->rate_idx[sc->curband->band][hw_rix]; + int rix; + + /* return base rate on errors */ + if (WARN(hw_rix < 0 || hw_rix >= AR5K_MAX_RATES, + "hw_rix out of bounds: %x\n", hw_rix)) + return 0; + + rix = sc->rate_idx[sc->curband->band][hw_rix]; + if (WARN(rix < 0, "invalid hw_rix: %x\n", hw_rix)) + rix = 0; + + return rix; } /***************\ diff --git a/drivers/net/wireless/ath5k/base.h b/drivers/net/wireless/ath5k/base.h index 20e0d14b41e..822956114cd 100644 --- a/drivers/net/wireless/ath5k/base.h +++ b/drivers/net/wireless/ath5k/base.h @@ -112,7 +112,7 @@ struct ath5k_softc { struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; struct ieee80211_channel channels[ATH_CHAN_MAX]; struct ieee80211_rate rates[IEEE80211_NUM_BANDS][AR5K_MAX_RATES]; - u8 rate_idx[IEEE80211_NUM_BANDS][AR5K_MAX_RATES]; + s8 rate_idx[IEEE80211_NUM_BANDS][AR5K_MAX_RATES]; enum nl80211_iftype opmode; struct ath5k_hw *ah; /* Atheros HW */ -- GitLab From 14344b81ec264efbe59de0183f5ba38650a479a6 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 21 Mar 2009 00:00:57 +0100 Subject: [PATCH 4923/4982] rt2x00: New USB ID for rt73usb Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt73usb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 24fdfdfee3d..420fff42c0d 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2425,6 +2425,8 @@ static struct usb_device_id rt73usb_device_table[] = { { USB_DEVICE(0x0df6, 0x9712), USB_DEVICE_DATA(&rt73usb_ops) }, /* Surecom */ { USB_DEVICE(0x0769, 0x31f3), USB_DEVICE_DATA(&rt73usb_ops) }, + /* Tilgin */ + { USB_DEVICE(0x6933, 0x5001), USB_DEVICE_DATA(&rt73usb_ops) }, /* Philips */ { USB_DEVICE(0x0471, 0x200a), USB_DEVICE_DATA(&rt73usb_ops) }, /* Planex */ -- GitLab From 051b919188650fe4c93ca8701183ae88439388f6 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 23 Mar 2009 18:25:01 -0400 Subject: [PATCH 4924/4982] ath9k: fix dma mapping leak of rx buffer upon rmmod We were claiming DMA buffers on the RX tasklet but never upon a simple module removal. Cc: stable@kernel.org Signed-off-by: FUJITA Tomonori Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/recv.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c index 917bac7af6f..71cb18d6757 100644 --- a/drivers/net/wireless/ath9k/recv.c +++ b/drivers/net/wireless/ath9k/recv.c @@ -344,8 +344,13 @@ void ath_rx_cleanup(struct ath_softc *sc) list_for_each_entry(bf, &sc->rx.rxbuf, list) { skb = bf->bf_mpdu; - if (skb) + if (skb) { + dma_unmap_single(sc->dev, + bf->bf_buf_addr, + sc->rx.bufsize, + DMA_FROM_DEVICE); dev_kfree_skb(skb); + } } if (sc->rx.rxdma.dd_desc_len != 0) -- GitLab From de00c04ecbb482507ace2197782123446a1cfdca Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 24 Mar 2009 16:21:55 +0100 Subject: [PATCH 4925/4982] ar9170: single module build This patch restores all-in-one module build procedure for ar9170. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/Makefile | 2 +- drivers/net/wireless/ar9170/Kconfig | 17 +++--------- drivers/net/wireless/ar9170/Makefile | 4 +-- drivers/net/wireless/ar9170/cmd.c | 1 - drivers/net/wireless/ar9170/main.c | 40 ---------------------------- drivers/net/wireless/ar9170/usb.c | 3 ++- 6 files changed, 7 insertions(+), 60 deletions(-) diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 5e7c9acb6be..50e7fba7f0e 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -57,6 +57,6 @@ obj-$(CONFIG_P54_COMMON) += p54/ obj-$(CONFIG_ATH5K) += ath5k/ obj-$(CONFIG_ATH9K) += ath9k/ -obj-$(CONFIG_AR9170_COMMON) += ar9170/ +obj-$(CONFIG_AR9170_USB) += ar9170/ obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o diff --git a/drivers/net/wireless/ar9170/Kconfig b/drivers/net/wireless/ar9170/Kconfig index f6611876e28..de4281fda12 100644 --- a/drivers/net/wireless/ar9170/Kconfig +++ b/drivers/net/wireless/ar9170/Kconfig @@ -1,17 +1,6 @@ -config AR9170_COMMON - tristate "Atheros AR9170 support" - depends on WLAN_80211 && MAC80211 && EXPERIMENTAL - help - This is common code for AR9170 based devices. - This module does nothing by itself - the USB/(SPI) frontends - also need to be enabled in order to support any devices. - - Say Y if you have the hardware, or M to build a module called - ar9170common. - config AR9170_USB - tristate "Atheros AR9170 USB support" - depends on AR9170_COMMON && USB + tristate "Atheros AR9170 802.11n USB support" + depends on USB && MAC80211 && WLAN_80211 && EXPERIMENTAL select FW_LOADER help This is a driver for the Atheros "otus" 802.11n USB devices. @@ -24,5 +13,5 @@ config AR9170_USB config AR9170_LEDS bool - depends on AR9170_COMMON && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = AR9170_COMMON) + depends on AR9170_USB && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = AR9170_USB) default y diff --git a/drivers/net/wireless/ar9170/Makefile b/drivers/net/wireless/ar9170/Makefile index 59b174dd466..8d91c7ee321 100644 --- a/drivers/net/wireless/ar9170/Makefile +++ b/drivers/net/wireless/ar9170/Makefile @@ -1,5 +1,3 @@ -ar9170common-objs += main.o cmd.o mac.o phy.o led.o -ar9170usb-objs += usb.o +ar9170usb-objs := usb.o main.o cmd.o mac.o phy.o led.o -obj-$(CONFIG_AR9170_COMMON) += ar9170common.o obj-$(CONFIG_AR9170_USB) += ar9170usb.o diff --git a/drivers/net/wireless/ar9170/cmd.c b/drivers/net/wireless/ar9170/cmd.c index fd5625c4e9d..f57a6200167 100644 --- a/drivers/net/wireless/ar9170/cmd.c +++ b/drivers/net/wireless/ar9170/cmd.c @@ -127,4 +127,3 @@ int ar9170_echo_test(struct ar9170 *ar, u32 v) return 0; } -EXPORT_SYMBOL_GPL(ar9170_echo_test); diff --git a/drivers/net/wireless/ar9170/main.c b/drivers/net/wireless/ar9170/main.c index f8c2357a173..5996ff9f7f4 100644 --- a/drivers/net/wireless/ar9170/main.c +++ b/drivers/net/wireless/ar9170/main.c @@ -37,14 +37,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* - * BIG FAT TODO: - * - * By the looks of things: these devices share a lot of things like - * EEPROM layout/design and PHY code with other Atheros WIFI products. - * So this driver/library will eventually become ath9k code... or vice versa ;-) - */ - #include #include #include @@ -56,9 +48,6 @@ static int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); -MODULE_AUTHOR("Johannes Berg "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Atheros shared code for AR9170 wireless devices"); #define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \ .bitrate = (_bitrate), \ @@ -247,7 +236,6 @@ void ar9170_handle_tx_status(struct ar9170 *ar, struct sk_buff *skb, skb_pull(skb, sizeof(struct ar9170_tx_control)); ieee80211_tx_status_irqsafe(ar->hw, skb); } -EXPORT_SYMBOL_GPL(ar9170_handle_tx_status); static struct sk_buff *ar9170_find_skb_in_queue(struct ar9170 *ar, const u8 *mac, @@ -630,13 +618,6 @@ static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) ieee80211_rx_irqsafe(ar->hw, skb, &status); } -/* - * TODO: - * It looks like AR9170 supports more than just the USB transport interface. - * Unfortunately, there is no available information what parts of the - * precendent and following code fragments is device specific and what not. - * For now, everything stays here, until some SPI chips pop up. - */ void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb) { unsigned int i, tlen, resplen; @@ -694,7 +675,6 @@ void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb) printk(KERN_ERR "%s: buffer remains!\n", wiphy_name(ar->hw->wiphy)); } -EXPORT_SYMBOL_GPL(ar9170_rx); #define AR9170_FILL_QUEUE(queue, ai_fs, cwmin, cwmax, _txop) \ do { \ @@ -1582,7 +1562,6 @@ void *ar9170_alloc(size_t priv_size) return ar; } -EXPORT_SYMBOL_GPL(ar9170_alloc); static int ar9170_read_eeprom(struct ar9170 *ar) { @@ -1680,7 +1659,6 @@ err_unreg: err_out: return err; } -EXPORT_SYMBOL_GPL(ar9170_register); void ar9170_unregister(struct ar9170 *ar) { @@ -1691,21 +1669,3 @@ void ar9170_unregister(struct ar9170 *ar) ieee80211_unregister_hw(ar->hw); mutex_destroy(&ar->mutex); } -EXPORT_SYMBOL_GPL(ar9170_unregister); - -static int __init ar9170_init(void) -{ - if (modparam_nohwcrypt) - printk(KERN_INFO "ar9170: cryptographic acceleration " - "disabled.\n"); - - return 0; -} - -static void __exit ar9170_exit(void) -{ - -} - -module_init(ar9170_init); -module_exit(ar9170_exit); diff --git a/drivers/net/wireless/ar9170/usb.c b/drivers/net/wireless/ar9170/usb.c index ede511e4047..ad296840893 100644 --- a/drivers/net/wireless/ar9170/usb.c +++ b/drivers/net/wireless/ar9170/usb.c @@ -47,9 +47,10 @@ #include "hw.h" #include "usb.h" +MODULE_AUTHOR("Johannes Berg "); MODULE_AUTHOR("Christian Lamparter "); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("USB Driver for Atheros AR9170 based devices"); +MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless"); MODULE_FIRMWARE("ar9170-1.fw"); MODULE_FIRMWARE("ar9170-2.fw"); -- GitLab From 5a0fe8ac70f81b5b91156736066e6445d0dcc61f Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 23 Mar 2009 23:35:37 -0400 Subject: [PATCH 4926/4982] ath5k: properly drop packets from ops->tx We shouldn't return NETDEV_TX_BUSY from the TX callback, especially after we've mucked with the sk_buffs. Drop the packets and return NETDEV_TX_OK. Changes-licensed-under: 3-Clause-BSD Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 6580df2f744..5d57d774e46 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -2562,7 +2562,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) if (skb_headroom(skb) < padsize) { ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough" " headroom to pad %d\n", hdrlen, padsize); - return NETDEV_TX_BUSY; + goto drop_packet; } skb_push(skb, padsize); memmove(skb->data, skb->data+padsize, hdrlen); @@ -2573,7 +2573,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) ATH5K_ERR(sc, "no further txbuf available, dropping packet\n"); spin_unlock_irqrestore(&sc->txbuflock, flags); ieee80211_stop_queue(hw, skb_get_queue_mapping(skb)); - return NETDEV_TX_BUSY; + goto drop_packet; } bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list); list_del(&bf->list); @@ -2590,10 +2590,12 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) list_add_tail(&bf->list, &sc->txbuf); sc->txbuf_len++; spin_unlock_irqrestore(&sc->txbuflock, flags); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; + goto drop_packet; } + return NETDEV_TX_OK; +drop_packet: + dev_kfree_skb_any(skb); return NETDEV_TX_OK; } -- GitLab From 3832c287f11ba001bbe48e9be8c59cb9f71f6b43 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 24 Mar 2009 08:46:57 +0100 Subject: [PATCH 4927/4982] mac80211: fix RX path My previous patch ("mac80211: remove mixed-cell and userspace MLME code") was too obvious to me, so obvious that a stupid bug crept in. The IBSS RX function must be invoked for IBSS, of course, not anything != IBSS. Reported-by: Larry Finger Signed-off-by: Johannes Berg Tested-by: Larry Finger Signed-off-by: John W. Linville --- net/mac80211/rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index eff59f36e8e..64ebe664eff 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1884,7 +1884,7 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) if (ieee80211_vif_is_mesh(&sdata->vif)) return ieee80211_mesh_rx_mgmt(sdata, rx->skb, rx->status); - if (sdata->vif.type != NL80211_IFTYPE_ADHOC) + if (sdata->vif.type == NL80211_IFTYPE_ADHOC) return ieee80211_ibss_rx_mgmt(sdata, rx->skb, rx->status); if (sdata->vif.type == NL80211_IFTYPE_STATION) -- GitLab From 4bbf4d56583dd52c429d88f43cb614bdbe5deea6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 24 Mar 2009 09:35:46 +0100 Subject: [PATCH 4928/4982] cfg80211: fix locking in nl80211_set_wiphy Luis reports that there's a circular locking dependency; this is because cfg80211_dev_rename() will acquire the cfg80211_mutex while the device mutex is held, while this normally is done the other way around. The solution is to open-code the device-getting in nl80211_set_wiphy and require holding the mutex around cfg80211_dev_rename rather than acquiring it within. Also fix a bug -- rtnl locking is expected by drivers so we need to provide it. Reported-by: Luis R. Rodriguez Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/core.c | 30 ++++++++++-------------------- net/wireless/core.h | 3 +++ net/wireless/nl80211.c | 28 ++++++++++++++++++++-------- 3 files changed, 33 insertions(+), 28 deletions(-) diff --git a/net/wireless/core.c b/net/wireless/core.c index 17fe3904974..d1f556535f6 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -87,7 +87,7 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx) } /* requires cfg80211_mutex to be held! */ -static struct cfg80211_registered_device * +struct cfg80211_registered_device * __cfg80211_drv_from_info(struct genl_info *info) { int ifindex; @@ -176,13 +176,14 @@ void cfg80211_put_dev(struct cfg80211_registered_device *drv) mutex_unlock(&drv->mtx); } +/* requires cfg80211_mutex to be held */ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, char *newname) { struct cfg80211_registered_device *drv; int wiphy_idx, taken = -1, result, digits; - mutex_lock(&cfg80211_mutex); + assert_cfg80211_lock(); /* prohibit calling the thing phy%d when %d is not its number */ sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken); @@ -195,30 +196,23 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, * deny the name if it is phy where is printed * without leading zeroes. taken == strlen(newname) here */ - result = -EINVAL; if (taken == strlen(PHY_NAME) + digits) - goto out_unlock; + return -EINVAL; } /* Ignore nop renames */ - result = 0; if (strcmp(newname, dev_name(&rdev->wiphy.dev)) == 0) - goto out_unlock; + return 0; /* Ensure another device does not already have this name. */ - list_for_each_entry(drv, &cfg80211_drv_list, list) { - result = -EINVAL; + list_for_each_entry(drv, &cfg80211_drv_list, list) if (strcmp(newname, dev_name(&drv->wiphy.dev)) == 0) - goto out_unlock; - } + return -EINVAL; - /* this will only check for collisions in sysfs - * which is not even always compiled in. - */ result = device_rename(&rdev->wiphy.dev, newname); if (result) - goto out_unlock; + return result; if (rdev->wiphy.debugfsdir && !debugfs_rename(rdev->wiphy.debugfsdir->d_parent, @@ -228,13 +222,9 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, printk(KERN_ERR "cfg80211: failed to rename debugfs dir to %s!\n", newname); - result = 0; -out_unlock: - mutex_unlock(&cfg80211_mutex); - if (result == 0) - nl80211_notify_dev_rename(rdev); + nl80211_notify_dev_rename(rdev); - return result; + return 0; } /* exported functions */ diff --git a/net/wireless/core.h b/net/wireless/core.h index 97a6fd8b2b0..d43daa236ef 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -99,6 +99,9 @@ struct cfg80211_internal_bss { struct cfg80211_registered_device *cfg80211_drv_by_wiphy_idx(int wiphy_idx); int get_wiphy_idx(struct wiphy *wiphy); +struct cfg80211_registered_device * +__cfg80211_drv_from_info(struct genl_info *info); + /* * This function returns a pointer to the driver * that the genl_info item that is passed refers to. diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 8808431bd58..353e1a4ece8 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -366,16 +366,26 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) int result = 0, rem_txq_params = 0; struct nlattr *nl_txq_params; - rdev = cfg80211_get_dev_from_info(info); - if (IS_ERR(rdev)) - return PTR_ERR(rdev); + rtnl_lock(); + + mutex_lock(&cfg80211_mutex); + + rdev = __cfg80211_drv_from_info(info); + if (IS_ERR(rdev)) { + result = PTR_ERR(rdev); + goto unlock; + } - if (info->attrs[NL80211_ATTR_WIPHY_NAME]) { + mutex_lock(&rdev->mtx); + + if (info->attrs[NL80211_ATTR_WIPHY_NAME]) result = cfg80211_dev_rename( rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); - if (result) - goto bad_res; - } + + mutex_unlock(&cfg80211_mutex); + + if (result) + goto bad_res; if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) { struct ieee80211_txq_params txq_params; @@ -471,7 +481,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) bad_res: - cfg80211_put_dev(rdev); + mutex_unlock(&rdev->mtx); + unlock: + rtnl_unlock(); return result; } -- GitLab From dd970e43d86c253ff159d9668499aaf42d175722 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 24 Mar 2009 10:36:48 +0100 Subject: [PATCH 4929/4982] b43: Add BCM4307 PCI-ID 00:09.0 Network controller [0280]: Broadcom Corporation BCM4307 Ethernet Controller [14e4:4306] (rev 03) Subsystem: Broadcom Corporation BCM4307 Ethernet Controller [14e4:4306] Flags: bus master, fast devsel, latency 32, IRQ 10 Memory at d7000000 (32-bit, non-prefetchable) [size=8K] Kernel driver in use: b43-pci-bridge Kernel modules: ssb Reported-by: yoann Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/ssb/b43_pci_bridge.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ssb/b43_pci_bridge.c b/drivers/ssb/b43_pci_bridge.c index 27a677584a4..ef9c6a04ad8 100644 --- a/drivers/ssb/b43_pci_bridge.c +++ b/drivers/ssb/b43_pci_bridge.c @@ -18,6 +18,7 @@ static const struct pci_device_id b43_pci_bridge_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4301) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4306) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4307) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4311) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4312) }, -- GitLab From 08df05aa9b25f3079585855506022bb33a011183 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 24 Mar 2009 10:02:54 -0700 Subject: [PATCH 4930/4982] iwlwifi: show current driver status in user readable format change the display of current driver status bit to user readable format for better and easier debugging Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 54 +++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 36cfeccfafb..64eb585f157 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -425,6 +425,56 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, return ret; } +static ssize_t iwl_dbgfs_status_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) { + + struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + char buf[512]; + int pos = 0; + const size_t bufsz = sizeof(buf); + + pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n", + test_bit(STATUS_HCMD_ACTIVE, &priv->status)); + pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_SYNC_ACTIVE: %d\n", + test_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)); + pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n", + test_bit(STATUS_INT_ENABLED, &priv->status)); + pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", + test_bit(STATUS_RF_KILL_HW, &priv->status)); + pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_SW:\t %d\n", + test_bit(STATUS_RF_KILL_SW, &priv->status)); + pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n", + test_bit(STATUS_INIT, &priv->status)); + pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n", + test_bit(STATUS_ALIVE, &priv->status)); + pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n", + test_bit(STATUS_READY, &priv->status)); + pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n", + test_bit(STATUS_TEMPERATURE, &priv->status)); + pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n", + test_bit(STATUS_GEO_CONFIGURED, &priv->status)); + pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", + test_bit(STATUS_EXIT_PENDING, &priv->status)); + pos += scnprintf(buf + pos, bufsz - pos, "STATUS_IN_SUSPEND:\t %d\n", + test_bit(STATUS_IN_SUSPEND, &priv->status)); + pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", + test_bit(STATUS_STATISTICS, &priv->status)); + pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n", + test_bit(STATUS_SCANNING, &priv->status)); + pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n", + test_bit(STATUS_SCAN_ABORTING, &priv->status)); + pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n", + test_bit(STATUS_SCAN_HW, &priv->status)); + pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n", + test_bit(STATUS_POWER_PMI, &priv->status)); + pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n", + test_bit(STATUS_FW_ERROR, &priv->status)); + pos += scnprintf(buf + pos, bufsz - pos, "STATUS_MODE_PENDING:\t %d\n", + test_bit(STATUS_MODE_PENDING, &priv->status)); + return simple_read_from_buffer(user_buf, count, ppos, buf, pos); +} + DEBUGFS_READ_WRITE_FILE_OPS(sram); DEBUGFS_WRITE_FILE_OPS(log_event); DEBUGFS_READ_FILE_OPS(eeprom); @@ -432,6 +482,7 @@ DEBUGFS_READ_FILE_OPS(stations); DEBUGFS_READ_FILE_OPS(rx_statistics); DEBUGFS_READ_FILE_OPS(tx_statistics); DEBUGFS_READ_FILE_OPS(channels); +DEBUGFS_READ_FILE_OPS(status); /* * Create the debugfs files and directories @@ -466,7 +517,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(rx_statistics, data); DEBUGFS_ADD_FILE(tx_statistics, data); DEBUGFS_ADD_FILE(channels, data); - DEBUGFS_ADD_X32(status, data, (u32 *)&priv->status); + DEBUGFS_ADD_FILE(status, data); DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); DEBUGFS_ADD_BOOL(disable_chain_noise, rf, &priv->disable_chain_noise_cal); @@ -496,6 +547,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels); + DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status); DEBUGFS_REMOVE(priv->dbgfs->dir_data); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise); -- GitLab From 2de8e0d999b8790861cd3749bec2236ccc1c8110 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Mar 2009 17:28:35 +0100 Subject: [PATCH 4931/4982] mac80211: rewrite fragmentation Fragmentation currently uses an allocated array to store the fragment skbs, and then keeps track of which have been sent and which are still pending etc. This is rather complicated; make it simpler by just chaining the fragments into skb->next and removing from that list when sent. Also simplifies all code that needs to touch fragments, since it now only needs to walk the skb->next list. This is a prerequisite for fixing the stored packet code, which I need to do for proper aggregation packet storing. Signed-off-by: Johannes Berg Reviewed-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 7 - net/mac80211/tx.c | 322 +++++++++++++++++-------------------- net/mac80211/util.c | 19 +-- net/mac80211/wep.c | 21 +-- net/mac80211/wpa.c | 28 +--- 5 files changed, 173 insertions(+), 224 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index acba78e1a5c..785f6363a6f 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -149,11 +149,6 @@ struct ieee80211_tx_data { struct ieee80211_channel *channel; - /* Extra fragments (in addition to the first fragment - * in skb) */ - struct sk_buff **extra_frag; - int num_extra_frag; - u16 ethertype; unsigned int flags; }; @@ -191,8 +186,6 @@ struct ieee80211_rx_data { struct ieee80211_tx_stored_packet { struct sk_buff *skb; - struct sk_buff **extra_frag; - int num_extra_frag; }; struct beacon_data { diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index f3f240c6901..51bf49cc75b 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -34,8 +34,7 @@ #define IEEE80211_TX_OK 0 #define IEEE80211_TX_AGAIN 1 -#define IEEE80211_TX_FRAG_AGAIN 2 -#define IEEE80211_TX_PENDING 3 +#define IEEE80211_TX_PENDING 2 /* misc utils */ @@ -702,17 +701,62 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) return TX_CONTINUE; } +static int ieee80211_fragment(struct ieee80211_local *local, + struct sk_buff *skb, int hdrlen, + int frag_threshold) +{ + struct sk_buff *tail = skb, *tmp; + int per_fragm = frag_threshold - hdrlen - FCS_LEN; + int pos = hdrlen + per_fragm; + int rem = skb->len - hdrlen - per_fragm; + + if (WARN_ON(rem < 0)) + return -EINVAL; + + while (rem) { + int fraglen = per_fragm; + + if (fraglen > rem) + fraglen = rem; + rem -= fraglen; + tmp = dev_alloc_skb(local->tx_headroom + + frag_threshold + + IEEE80211_ENCRYPT_HEADROOM + + IEEE80211_ENCRYPT_TAILROOM); + if (!tmp) + return -ENOMEM; + tail->next = tmp; + tail = tmp; + skb_reserve(tmp, local->tx_headroom + + IEEE80211_ENCRYPT_HEADROOM); + /* copy control information */ + memcpy(tmp->cb, skb->cb, sizeof(tmp->cb)); + skb_copy_queue_mapping(tmp, skb); + tmp->priority = skb->priority; + tmp->do_not_encrypt = skb->do_not_encrypt; + tmp->dev = skb->dev; + tmp->iif = skb->iif; + + /* copy header and data */ + memcpy(skb_put(tmp, hdrlen), skb->data, hdrlen); + memcpy(skb_put(tmp, fraglen), skb->data + pos, fraglen); + + pos += fraglen; + } + + skb->len = hdrlen + per_fragm; + return 0; +} + static ieee80211_tx_result debug_noinline ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; - size_t hdrlen, per_fragm, num_fragm, payload_len, left; - struct sk_buff **frags, *first, *frag; - int i; - u16 seq; - u8 *pos; + struct sk_buff *skb = tx->skb; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr = (void *)skb->data; int frag_threshold = tx->local->fragmentation_threshold; + int hdrlen; + int fragnum; if (!(tx->flags & IEEE80211_TX_FRAGMENTED)) return TX_CONTINUE; @@ -725,58 +769,35 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU)) return TX_DROP; - first = tx->skb; - hdrlen = ieee80211_hdrlen(hdr->frame_control); - payload_len = first->len - hdrlen; - per_fragm = frag_threshold - hdrlen - FCS_LEN; - num_fragm = DIV_ROUND_UP(payload_len, per_fragm); - - frags = kzalloc(num_fragm * sizeof(struct sk_buff *), GFP_ATOMIC); - if (!frags) - goto fail; - - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS); - seq = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ; - pos = first->data + hdrlen + per_fragm; - left = payload_len - per_fragm; - for (i = 0; i < num_fragm - 1; i++) { - struct ieee80211_hdr *fhdr; - size_t copylen; - - if (left <= 0) - goto fail; - /* reserve enough extra head and tail room for possible - * encryption */ - frag = frags[i] = - dev_alloc_skb(tx->local->tx_headroom + - frag_threshold + - IEEE80211_ENCRYPT_HEADROOM + - IEEE80211_ENCRYPT_TAILROOM); - if (!frag) - goto fail; - - /* Make sure that all fragments use the same priority so - * that they end up using the same TX queue */ - frag->priority = first->priority; + /* internal error, why is TX_FRAGMENTED set? */ + if (WARN_ON(skb->len <= frag_threshold)) + return TX_DROP; - skb_reserve(frag, tx->local->tx_headroom + - IEEE80211_ENCRYPT_HEADROOM); + /* + * Now fragment the frame. This will allocate all the fragments and + * chain them (using skb as the first fragment) to skb->next. + * During transmission, we will remove the successfully transmitted + * fragments from this list. When the low-level driver rejects one + * of the fragments then we will simply pretend to accept the skb + * but store it away as pending. + */ + if (ieee80211_fragment(tx->local, skb, hdrlen, frag_threshold)) + return TX_DROP; - /* copy TX information */ - info = IEEE80211_SKB_CB(frag); - memcpy(info, first->cb, sizeof(frag->cb)); + /* update duration/seq/flags of fragments */ + fragnum = 0; + do { + int next_len; + const __le16 morefrags = cpu_to_le16(IEEE80211_FCTL_MOREFRAGS); - /* copy/fill in 802.11 header */ - fhdr = (struct ieee80211_hdr *) skb_put(frag, hdrlen); - memcpy(fhdr, first->data, hdrlen); - fhdr->seq_ctrl = cpu_to_le16(seq | ((i + 1) & IEEE80211_SCTL_FRAG)); + hdr = (void *)skb->data; + info = IEEE80211_SKB_CB(skb); - if (i == num_fragm - 2) { - /* clear MOREFRAGS bit for the last fragment */ - fhdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREFRAGS); - } else { + if (skb->next) { + hdr->frame_control |= morefrags; + next_len = skb->next->len; /* * No multi-rate retries for fragmented frames, that * would completely throw off the NAV at other STAs. @@ -787,37 +808,16 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) info->control.rates[4].idx = -1; BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 5); info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; + } else { + hdr->frame_control &= ~morefrags; + next_len = 0; } - - /* copy data */ - copylen = left > per_fragm ? per_fragm : left; - memcpy(skb_put(frag, copylen), pos, copylen); - - skb_copy_queue_mapping(frag, first); - - frag->do_not_encrypt = first->do_not_encrypt; - frag->dev = first->dev; - frag->iif = first->iif; - - pos += copylen; - left -= copylen; - } - skb_trim(first, hdrlen + per_fragm); - - tx->num_extra_frag = num_fragm - 1; - tx->extra_frag = frags; + hdr->duration_id = ieee80211_duration(tx, 0, next_len); + hdr->seq_ctrl |= cpu_to_le16(fragnum & IEEE80211_SCTL_FRAG); + fragnum++; + } while ((skb = skb->next)); return TX_CONTINUE; - - fail: - if (frags) { - for (i = 0; i < num_fragm - 1; i++) - if (frags[i]) - dev_kfree_skb(frags[i]); - kfree(frags); - } - I802_DEBUG_INC(tx->local->tx_handlers_drop_fragment); - return TX_DROP; } static ieee80211_tx_result debug_noinline @@ -845,27 +845,19 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) static ieee80211_tx_result debug_noinline ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; - int next_len, i; - int group_addr = is_multicast_ether_addr(hdr->addr1); - - if (!(tx->flags & IEEE80211_TX_FRAGMENTED)) { - hdr->duration_id = ieee80211_duration(tx, group_addr, 0); - return TX_CONTINUE; - } - - hdr->duration_id = ieee80211_duration(tx, group_addr, - tx->extra_frag[0]->len); + struct sk_buff *skb = tx->skb; + struct ieee80211_hdr *hdr; + int next_len; + bool group_addr; - for (i = 0; i < tx->num_extra_frag; i++) { - if (i + 1 < tx->num_extra_frag) - next_len = tx->extra_frag[i + 1]->len; - else - next_len = 0; + do { + hdr = (void *) skb->data; + next_len = skb->next ? skb->next->len : 0; + group_addr = is_multicast_ether_addr(hdr->addr1); - hdr = (struct ieee80211_hdr *)tx->extra_frag[i]->data; - hdr->duration_id = ieee80211_duration(tx, 0, next_len); - } + hdr->duration_id = + ieee80211_duration(tx, group_addr, next_len); + } while ((skb = skb->next)); return TX_CONTINUE; } @@ -873,19 +865,16 @@ ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx) static ieee80211_tx_result debug_noinline ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) { - int i; + struct sk_buff *skb = tx->skb; if (!tx->sta) return TX_CONTINUE; tx->sta->tx_packets++; - tx->sta->tx_fragments++; - tx->sta->tx_bytes += tx->skb->len; - if (tx->extra_frag) { - tx->sta->tx_fragments += tx->num_extra_frag; - for (i = 0; i < tx->num_extra_frag; i++) - tx->sta->tx_bytes += tx->extra_frag[i]->len; - } + do { + tx->sta->tx_fragments++; + tx->sta->tx_bytes += skb->len; + } while ((skb = skb->next)); return TX_CONTINUE; } @@ -1099,45 +1088,36 @@ static int ieee80211_tx_prepare(struct ieee80211_local *local, return 0; } -static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, +static int __ieee80211_tx(struct ieee80211_local *local, struct ieee80211_tx_data *tx) { + struct sk_buff *skb = tx->skb, *next; struct ieee80211_tx_info *info; - int ret, i; + int ret; + bool fragm = false; - if (skb) { + local->mdev->trans_start = jiffies; + + while (skb) { if (ieee80211_queue_stopped(&local->hw, skb_get_queue_mapping(skb))) return IEEE80211_TX_PENDING; - ret = local->ops->tx(local_to_hw(local), skb); - if (ret) - return IEEE80211_TX_AGAIN; - local->mdev->trans_start = jiffies; - ieee80211_led_tx(local, 1); - } - if (tx->extra_frag) { - for (i = 0; i < tx->num_extra_frag; i++) { - if (!tx->extra_frag[i]) - continue; - info = IEEE80211_SKB_CB(tx->extra_frag[i]); + if (fragm) { + info = IEEE80211_SKB_CB(skb); info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT | IEEE80211_TX_CTL_FIRST_FRAGMENT); - if (ieee80211_queue_stopped(&local->hw, - skb_get_queue_mapping(tx->extra_frag[i]))) - return IEEE80211_TX_FRAG_AGAIN; - - ret = local->ops->tx(local_to_hw(local), - tx->extra_frag[i]); - if (ret) - return IEEE80211_TX_FRAG_AGAIN; - local->mdev->trans_start = jiffies; - ieee80211_led_tx(local, 1); - tx->extra_frag[i] = NULL; } - kfree(tx->extra_frag); - tx->extra_frag = NULL; + + next = skb->next; + ret = local->ops->tx(local_to_hw(local), skb); + if (ret != NETDEV_TX_OK) + return IEEE80211_TX_AGAIN; + tx->skb = skb = next; + ieee80211_led_tx(local, 1); + fragm = true; } + return IEEE80211_TX_OK; } @@ -1149,7 +1129,6 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) { struct sk_buff *skb = tx->skb; ieee80211_tx_result res = TX_DROP; - int i; #define CALL_TXH(txh) \ res = txh(tx); \ @@ -1173,11 +1152,13 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) txh_done: if (unlikely(res == TX_DROP)) { I802_DEBUG_INC(tx->local->tx_handlers_drop); - dev_kfree_skb(skb); - for (i = 0; i < tx->num_extra_frag; i++) - if (tx->extra_frag[i]) - dev_kfree_skb(tx->extra_frag[i]); - kfree(tx->extra_frag); + while (skb) { + struct sk_buff *next; + + next = skb->next; + dev_kfree_skb(skb); + skb = next; + } return -1; } else if (unlikely(res == TX_QUEUED)) { I802_DEBUG_INC(tx->local->tx_handlers_queued); @@ -1194,7 +1175,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) struct ieee80211_tx_data tx; ieee80211_tx_result res_prepare; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - int ret, i; + int ret; u16 queue; queue = skb_get_queue_mapping(skb); @@ -1225,7 +1206,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) goto out; retry: - ret = __ieee80211_tx(local, skb, &tx); + ret = __ieee80211_tx(local, &tx); if (ret) { struct ieee80211_tx_stored_packet *store; @@ -1240,9 +1221,6 @@ retry: store = &local->pending_packet[queue]; - if (ret == IEEE80211_TX_FRAG_AGAIN) - skb = NULL; - set_bit(queue, local->queues_pending); smp_mb(); /* @@ -1260,22 +1238,23 @@ retry: clear_bit(queue, local->queues_pending); goto retry; } - store->skb = skb; - store->extra_frag = tx.extra_frag; - store->num_extra_frag = tx.num_extra_frag; + store->skb = tx.skb; } out: rcu_read_unlock(); return 0; drop: - if (skb) - dev_kfree_skb(skb); - for (i = 0; i < tx.num_extra_frag; i++) - if (tx.extra_frag[i]) - dev_kfree_skb(tx.extra_frag[i]); - kfree(tx.extra_frag); rcu_read_unlock(); + + skb = tx.skb; + while (skb) { + struct sk_buff *next; + + next = skb->next; + dev_kfree_skb(skb); + skb = next; + } return 0; } @@ -1810,17 +1789,21 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, */ void ieee80211_clear_tx_pending(struct ieee80211_local *local) { - int i, j; - struct ieee80211_tx_stored_packet *store; + struct sk_buff *skb; + int i; for (i = 0; i < local->hw.queues; i++) { if (!test_bit(i, local->queues_pending)) continue; - store = &local->pending_packet[i]; - kfree_skb(store->skb); - for (j = 0; j < store->num_extra_frag; j++) - kfree_skb(store->extra_frag[j]); - kfree(store->extra_frag); + + skb = local->pending_packet[i].skb; + while (skb) { + struct sk_buff *next; + + next = skb->next; + dev_kfree_skb(skb); + skb = next; + } clear_bit(i, local->queues_pending); } } @@ -1854,14 +1837,11 @@ void ieee80211_tx_pending(unsigned long data) netif_start_subqueue(local->mdev, i); store = &local->pending_packet[i]; - tx.extra_frag = store->extra_frag; - tx.num_extra_frag = store->num_extra_frag; tx.flags = 0; - ret = __ieee80211_tx(local, store->skb, &tx); - if (ret) { - if (ret == IEEE80211_TX_FRAG_AGAIN) - store->skb = NULL; - } else { + tx.skb = store->skb; + ret = __ieee80211_tx(local, &tx); + store->skb = tx.skb; + if (!ret) { clear_bit(i, local->queues_pending); ieee80211_wake_queue(&local->hw, i); } diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 444bb14c95e..021166c8cce 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -166,18 +166,13 @@ int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; - - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); - if (tx->extra_frag) { - struct ieee80211_hdr *fhdr; - int i; - for (i = 0; i < tx->num_extra_frag; i++) { - fhdr = (struct ieee80211_hdr *) - tx->extra_frag[i]->data; - fhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); - } - } + struct sk_buff *skb = tx->skb; + struct ieee80211_hdr *hdr; + + do { + hdr = (struct ieee80211_hdr *) skb->data; + hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); + } while ((skb = skb->next)); } int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 7043ddc7549..ef73105b306 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c @@ -329,24 +329,17 @@ static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) ieee80211_tx_result ieee80211_crypto_wep_encrypt(struct ieee80211_tx_data *tx) { - int i; + struct sk_buff *skb; ieee80211_tx_set_protected(tx); - if (wep_encrypt_skb(tx, tx->skb) < 0) { - I802_DEBUG_INC(tx->local->tx_handlers_drop_wep); - return TX_DROP; - } - - if (tx->extra_frag) { - for (i = 0; i < tx->num_extra_frag; i++) { - if (wep_encrypt_skb(tx, tx->extra_frag[i])) { - I802_DEBUG_INC(tx->local-> - tx_handlers_drop_wep); - return TX_DROP; - } + skb = tx->skb; + do { + if (wep_encrypt_skb(tx, skb) < 0) { + I802_DEBUG_INC(tx->local->tx_handlers_drop_wep); + return TX_DROP; } - } + } while ((skb = skb->next)); return TX_CONTINUE; } diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 9101b48ec2a..4f8bfea278f 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -196,19 +196,13 @@ ieee80211_tx_result ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx) { struct sk_buff *skb = tx->skb; - int i; ieee80211_tx_set_protected(tx); - if (tkip_encrypt_skb(tx, skb) < 0) - return TX_DROP; - - if (tx->extra_frag) { - for (i = 0; i < tx->num_extra_frag; i++) { - if (tkip_encrypt_skb(tx, tx->extra_frag[i])) - return TX_DROP; - } - } + do { + if (tkip_encrypt_skb(tx, skb) < 0) + return TX_DROP; + } while ((skb = skb->next)); return TX_CONTINUE; } @@ -428,19 +422,13 @@ ieee80211_tx_result ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx) { struct sk_buff *skb = tx->skb; - int i; ieee80211_tx_set_protected(tx); - if (ccmp_encrypt_skb(tx, skb) < 0) - return TX_DROP; - - if (tx->extra_frag) { - for (i = 0; i < tx->num_extra_frag; i++) { - if (ccmp_encrypt_skb(tx, tx->extra_frag[i])) - return TX_DROP; - } - } + do { + if (ccmp_encrypt_skb(tx, skb) < 0) + return TX_DROP; + } while ((skb = skb->next)); return TX_CONTINUE; } -- GitLab From f0e72851f7ad108fed20426b46a18ab5fcd5729f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Mar 2009 17:28:36 +0100 Subject: [PATCH 4932/4982] mac80211: fix A-MPDU queue assignment Internally, mac80211 requires the skb's queue mapping to be set to the AC queue, not the virtual A-MPDU queue. This is not done correctly currently, this patch moves the code down to directly before the driver is invoked and adds a comment that it will be moved into the driver later. Since this requires __ieee80211_tx() to have the sta pointer, make sure to provide it in ieee80211_tx_pending(). Signed-off-by: Johannes Berg Reviewed-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/mac80211/tx.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 51bf49cc75b..0d97cad84b1 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1024,13 +1024,8 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, spin_lock_irqsave(&tx->sta->lock, flags); state = &tx->sta->ampdu_mlme.tid_state_tx[tid]; - if (*state == HT_AGG_STATE_OPERATIONAL) { + if (*state == HT_AGG_STATE_OPERATIONAL) info->flags |= IEEE80211_TX_CTL_AMPDU; - if (local->hw.ampdu_queues) - skb_set_queue_mapping( - skb, tx->local->hw.queues + - tx->sta->tid_to_tx_q[tid]); - } spin_unlock_irqrestore(&tx->sta->lock, flags); } @@ -1103,10 +1098,29 @@ static int __ieee80211_tx(struct ieee80211_local *local, skb_get_queue_mapping(skb))) return IEEE80211_TX_PENDING; - if (fragm) { - info = IEEE80211_SKB_CB(skb); + info = IEEE80211_SKB_CB(skb); + + if (fragm) info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT | IEEE80211_TX_CTL_FIRST_FRAGMENT); + + /* + * Internally, we need to have the queue mapping point to + * the real AC queue, not the virtual A-MPDU queue. This + * now finally sets the queue to what the driver wants. + * We will later move this down into the only driver that + * needs it, iwlwifi. + */ + if (tx->sta && local->hw.ampdu_queues && + info->flags & IEEE80211_TX_CTL_AMPDU) { + unsigned long flags; + u8 *qc = ieee80211_get_qos_ctl((void *) skb->data); + int tid = *qc & IEEE80211_QOS_CTL_TID_MASK; + + spin_lock_irqsave(&tx->sta->lock, flags); + skb_set_queue_mapping(skb, local->hw.queues + + tx->sta->tid_to_tx_q[tid]); + spin_unlock_irqrestore(&tx->sta->lock, flags); } next = skb->next; @@ -1817,9 +1831,11 @@ void ieee80211_tx_pending(unsigned long data) struct ieee80211_local *local = (struct ieee80211_local *)data; struct net_device *dev = local->mdev; struct ieee80211_tx_stored_packet *store; + struct ieee80211_hdr *hdr; struct ieee80211_tx_data tx; int i, ret; + rcu_read_lock(); netif_tx_lock_bh(dev); for (i = 0; i < local->hw.queues; i++) { /* Check that this queue is ok */ @@ -1839,6 +1855,8 @@ void ieee80211_tx_pending(unsigned long data) store = &local->pending_packet[i]; tx.flags = 0; tx.skb = store->skb; + hdr = (struct ieee80211_hdr *)tx.skb->data; + tx.sta = sta_info_get(local, hdr->addr1); ret = __ieee80211_tx(local, &tx); store->skb = tx.skb; if (!ret) { @@ -1847,6 +1865,7 @@ void ieee80211_tx_pending(unsigned long data) } } netif_tx_unlock_bh(dev); + rcu_read_unlock(); } /* functions for drivers to get certain frames */ -- GitLab From 2a577d98712a284a612dd51d69db5cb989810dc2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Mar 2009 17:28:37 +0100 Subject: [PATCH 4933/4982] mac80211: rework the pending packets code The pending packets code is quite incomprehensible, uses memory barriers nobody really understands, etc. This patch reworks it entirely, using the queue spinlock, proper stop bits and the skb queues themselves to indicate whether packets are pending or not (rather than a separate variable like before). Signed-off-by: Johannes Berg Reviewed-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 9 +-- net/mac80211/main.c | 2 + net/mac80211/tx.c | 144 ++++++++++++++++++++----------------- net/mac80211/util.c | 22 +++--- 4 files changed, 98 insertions(+), 79 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 785f6363a6f..6ce62e553dc 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -184,10 +184,6 @@ struct ieee80211_rx_data { u16 tkip_iv16; }; -struct ieee80211_tx_stored_packet { - struct sk_buff *skb; -}; - struct beacon_data { u8 *head, *tail; int head_len, tail_len; @@ -583,6 +579,7 @@ enum queue_stop_reason { IEEE80211_QUEUE_STOP_REASON_CSA, IEEE80211_QUEUE_STOP_REASON_AGGREGATION, IEEE80211_QUEUE_STOP_REASON_SUSPEND, + IEEE80211_QUEUE_STOP_REASON_PENDING, }; struct ieee80211_master_priv { @@ -639,9 +636,7 @@ struct ieee80211_local { struct sta_info *sta_hash[STA_HASH_SIZE]; struct timer_list sta_cleanup; - unsigned long queues_pending[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)]; - unsigned long queues_pending_run[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)]; - struct ieee80211_tx_stored_packet pending_packet[IEEE80211_MAX_QUEUES]; + struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; struct tasklet_struct tx_pending_tasklet; /* number of interfaces with corresponding IFF_ flags */ diff --git a/net/mac80211/main.c b/net/mac80211/main.c index dac68d476bf..a7430e98c53 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -781,6 +781,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, sta_info_init(local); + for (i = 0; i < IEEE80211_MAX_QUEUES; i++) + skb_queue_head_init(&local->pending[i]); tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending, (unsigned long)local); tasklet_disable(&local->tx_pending_tasklet); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 0d97cad84b1..ee1b77f8a80 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1189,12 +1189,14 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) struct ieee80211_tx_data tx; ieee80211_tx_result res_prepare; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - int ret; + struct sk_buff *next; + unsigned long flags; + int ret, retries; u16 queue; queue = skb_get_queue_mapping(skb); - WARN_ON(test_bit(queue, local->queues_pending)); + WARN_ON(!skb_queue_empty(&local->pending[queue])); if (unlikely(skb->len < 10)) { dev_kfree_skb(skb); @@ -1219,40 +1221,52 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) if (invoke_tx_handlers(&tx)) goto out; -retry: + retries = 0; + retry: ret = __ieee80211_tx(local, &tx); - if (ret) { - struct ieee80211_tx_stored_packet *store; - + switch (ret) { + case IEEE80211_TX_OK: + break; + case IEEE80211_TX_AGAIN: /* * Since there are no fragmented frames on A-MPDU * queues, there's no reason for a driver to reject * a frame there, warn and drop it. */ - if (ret != IEEE80211_TX_PENDING) - if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU)) - goto drop; + if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU)) + goto drop; + /* fall through */ + case IEEE80211_TX_PENDING: + skb = tx.skb; - store = &local->pending_packet[queue]; + spin_lock_irqsave(&local->queue_stop_reason_lock, flags); - set_bit(queue, local->queues_pending); - smp_mb(); - /* - * When the driver gets out of buffers during sending of - * fragments and calls ieee80211_stop_queue, the netif - * subqueue is stopped. There is, however, a small window - * in which the PENDING bit is not yet set. If a buffer - * gets available in that window (i.e. driver calls - * ieee80211_wake_queue), we would end up with ieee80211_tx - * called with the PENDING bit still set. Prevent this by - * continuing transmitting here when that situation is - * possible to have happened. - */ - if (!__netif_subqueue_stopped(local->mdev, queue)) { - clear_bit(queue, local->queues_pending); + if (__netif_subqueue_stopped(local->mdev, queue)) { + do { + next = skb->next; + skb->next = NULL; + skb_queue_tail(&local->pending[queue], skb); + } while ((skb = next)); + + /* + * Make sure nobody will enable the queue on us + * (without going through the tasklet) nor disable the + * netdev queue underneath the pending handling code. + */ + __set_bit(IEEE80211_QUEUE_STOP_REASON_PENDING, + &local->queue_stop_reasons[queue]); + + spin_unlock_irqrestore(&local->queue_stop_reason_lock, + flags); + } else { + spin_unlock_irqrestore(&local->queue_stop_reason_lock, + flags); + + retries++; + if (WARN(retries > 10, "tx refused but queue active")) + goto drop; goto retry; } - store->skb = tx.skb; } out: rcu_read_unlock(); @@ -1263,8 +1277,6 @@ retry: skb = tx.skb; while (skb) { - struct sk_buff *next; - next = skb->next; dev_kfree_skb(skb); skb = next; @@ -1803,23 +1815,10 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, */ void ieee80211_clear_tx_pending(struct ieee80211_local *local) { - struct sk_buff *skb; int i; - for (i = 0; i < local->hw.queues; i++) { - if (!test_bit(i, local->queues_pending)) - continue; - - skb = local->pending_packet[i].skb; - while (skb) { - struct sk_buff *next; - - next = skb->next; - dev_kfree_skb(skb); - skb = next; - } - clear_bit(i, local->queues_pending); - } + for (i = 0; i < local->hw.queues; i++) + skb_queue_purge(&local->pending[i]); } /* @@ -1830,40 +1829,57 @@ void ieee80211_tx_pending(unsigned long data) { struct ieee80211_local *local = (struct ieee80211_local *)data; struct net_device *dev = local->mdev; - struct ieee80211_tx_stored_packet *store; struct ieee80211_hdr *hdr; + unsigned long flags; struct ieee80211_tx_data tx; int i, ret; + bool next; rcu_read_lock(); netif_tx_lock_bh(dev); - for (i = 0; i < local->hw.queues; i++) { - /* Check that this queue is ok */ - if (__netif_subqueue_stopped(local->mdev, i) && - !test_bit(i, local->queues_pending_run)) - continue; - if (!test_bit(i, local->queues_pending)) { - clear_bit(i, local->queues_pending_run); - ieee80211_wake_queue(&local->hw, i); + for (i = 0; i < local->hw.queues; i++) { + /* + * If queue is stopped by something other than due to pending + * frames, or we have no pending frames, proceed to next queue. + */ + spin_lock_irqsave(&local->queue_stop_reason_lock, flags); + next = false; + if (local->queue_stop_reasons[i] != + BIT(IEEE80211_QUEUE_STOP_REASON_PENDING) || + skb_queue_empty(&local->pending[i])) + next = true; + spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); + + if (next) continue; - } - clear_bit(i, local->queues_pending_run); + /* + * start the queue now to allow processing our packets, + * we're under the tx lock here anyway so nothing will + * happen as a result of this + */ netif_start_subqueue(local->mdev, i); - store = &local->pending_packet[i]; - tx.flags = 0; - tx.skb = store->skb; - hdr = (struct ieee80211_hdr *)tx.skb->data; - tx.sta = sta_info_get(local, hdr->addr1); - ret = __ieee80211_tx(local, &tx); - store->skb = tx.skb; - if (!ret) { - clear_bit(i, local->queues_pending); - ieee80211_wake_queue(&local->hw, i); + while (!skb_queue_empty(&local->pending[i])) { + tx.flags = 0; + tx.skb = skb_dequeue(&local->pending[i]); + hdr = (struct ieee80211_hdr *)tx.skb->data; + tx.sta = sta_info_get(local, hdr->addr1); + + ret = __ieee80211_tx(local, &tx); + if (ret != IEEE80211_TX_OK) { + skb_queue_head(&local->pending[i], tx.skb); + break; + } } + + /* Start regular packet processing again. */ + if (skb_queue_empty(&local->pending[i])) + ieee80211_wake_queue_by_reason(&local->hw, i, + IEEE80211_QUEUE_STOP_REASON_PENDING); } + netif_tx_unlock_bh(dev); rcu_read_unlock(); } diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 021166c8cce..0247d8022f5 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -365,16 +365,16 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, __clear_bit(reason, &local->queue_stop_reasons[queue]); + if (!skb_queue_empty(&local->pending[queue]) && + local->queue_stop_reasons[queue] == + BIT(IEEE80211_QUEUE_STOP_REASON_PENDING)) + tasklet_schedule(&local->tx_pending_tasklet); + if (local->queue_stop_reasons[queue] != 0) /* someone still has this queue stopped */ return; - if (test_bit(queue, local->queues_pending)) { - set_bit(queue, local->queues_pending_run); - tasklet_schedule(&local->tx_pending_tasklet); - } else { - netif_wake_subqueue(local->mdev, queue); - } + netif_wake_subqueue(local->mdev, queue); } void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, @@ -420,9 +420,15 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, reason = IEEE80211_QUEUE_STOP_REASON_AGGREGATION; } - __set_bit(reason, &local->queue_stop_reasons[queue]); + /* + * Only stop if it was previously running, this is necessary + * for correct pending packets handling because there we may + * start (but not wake) the queue and rely on that. + */ + if (!local->queue_stop_reasons[queue]) + netif_stop_subqueue(local->mdev, queue); - netif_stop_subqueue(local->mdev, queue); + __set_bit(reason, &local->queue_stop_reasons[queue]); } void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, -- GitLab From 1870cd71e87da1a1afb904f2c84086f487a07135 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Mar 2009 17:28:38 +0100 Subject: [PATCH 4934/4982] mac80211: clean up __ieee80211_tx args __ieee80211_tx takes a struct ieee80211_tx_data argument, but only uses a few of its members, namely 'skb' and 'sta'. Make that explicit, so that less internal knowledge is required in ieee80211_tx_pending and the possibility of introducing errors here is removed. Signed-off-by: Johannes Berg Reviewed-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/mac80211/tx.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index ee1b77f8a80..b909e4090e9 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1084,9 +1084,10 @@ static int ieee80211_tx_prepare(struct ieee80211_local *local, } static int __ieee80211_tx(struct ieee80211_local *local, - struct ieee80211_tx_data *tx) + struct sk_buff **skbp, + struct sta_info *sta) { - struct sk_buff *skb = tx->skb, *next; + struct sk_buff *skb = *skbp, *next; struct ieee80211_tx_info *info; int ret; bool fragm = false; @@ -1111,23 +1112,23 @@ static int __ieee80211_tx(struct ieee80211_local *local, * We will later move this down into the only driver that * needs it, iwlwifi. */ - if (tx->sta && local->hw.ampdu_queues && + if (sta && local->hw.ampdu_queues && info->flags & IEEE80211_TX_CTL_AMPDU) { unsigned long flags; u8 *qc = ieee80211_get_qos_ctl((void *) skb->data); int tid = *qc & IEEE80211_QOS_CTL_TID_MASK; - spin_lock_irqsave(&tx->sta->lock, flags); + spin_lock_irqsave(&sta->lock, flags); skb_set_queue_mapping(skb, local->hw.queues + - tx->sta->tid_to_tx_q[tid]); - spin_unlock_irqrestore(&tx->sta->lock, flags); + sta->tid_to_tx_q[tid]); + spin_unlock_irqrestore(&sta->lock, flags); } next = skb->next; ret = local->ops->tx(local_to_hw(local), skb); if (ret != NETDEV_TX_OK) return IEEE80211_TX_AGAIN; - tx->skb = skb = next; + *skbp = skb = next; ieee80211_led_tx(local, 1); fragm = true; } @@ -1223,7 +1224,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) retries = 0; retry: - ret = __ieee80211_tx(local, &tx); + ret = __ieee80211_tx(local, &tx.skb, tx.sta); switch (ret) { case IEEE80211_TX_OK: break; @@ -1831,7 +1832,6 @@ void ieee80211_tx_pending(unsigned long data) struct net_device *dev = local->mdev; struct ieee80211_hdr *hdr; unsigned long flags; - struct ieee80211_tx_data tx; int i, ret; bool next; @@ -1862,14 +1862,15 @@ void ieee80211_tx_pending(unsigned long data) netif_start_subqueue(local->mdev, i); while (!skb_queue_empty(&local->pending[i])) { - tx.flags = 0; - tx.skb = skb_dequeue(&local->pending[i]); - hdr = (struct ieee80211_hdr *)tx.skb->data; - tx.sta = sta_info_get(local, hdr->addr1); + struct sk_buff *skb = skb_dequeue(&local->pending[i]); + struct sta_info *sta; + + hdr = (struct ieee80211_hdr *)skb->data; + sta = sta_info_get(local, hdr->addr1); - ret = __ieee80211_tx(local, &tx); + ret = __ieee80211_tx(local, &skb, sta); if (ret != IEEE80211_TX_OK) { - skb_queue_head(&local->pending[i], tx.skb); + skb_queue_head(&local->pending[i], skb); break; } } -- GitLab From b1720231ca07dee3382980f3b25e6581bd2e54e9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Mar 2009 17:28:39 +0100 Subject: [PATCH 4935/4982] mac80211: unify and fix TX aggregation start When TX aggregation becomes operational, we do a number of steps: 1) print a debug message 2) wake the virtual queue 3) notify the driver Unfortunately, 1) and 3) are only done if the driver is first to reply to the aggregation request, it is, however, possible that the remote station replies before the driver! Thus, unify the code for this and call the new function ieee80211_agg_tx_operational in both places where TX aggregation can become operational. Additionally, rename the driver notification from IEEE80211_AMPDU_TX_RESUME to IEEE80211_AMPDU_TX_OPERATIONAL. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 2 +- include/net/mac80211.h | 4 +- net/mac80211/agg-tx.c | 63 +++++++++++++------------------ 3 files changed, 30 insertions(+), 39 deletions(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index c13e4e53634..13d4e6756c9 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -2730,7 +2730,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid); break; - case IEEE80211_AMPDU_TX_RESUME: + case IEEE80211_AMPDU_TX_OPERATIONAL: ath_tx_aggr_resume(sc, sta, tid); break; default: diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 6f3bc4cc53e..07fe9875506 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1236,14 +1236,14 @@ enum ieee80211_filter_flags { * @IEEE80211_AMPDU_RX_STOP: stop Rx aggregation * @IEEE80211_AMPDU_TX_START: start Tx aggregation * @IEEE80211_AMPDU_TX_STOP: stop Tx aggregation - * @IEEE80211_AMPDU_TX_RESUME: resume TX aggregation + * @IEEE80211_AMPDU_TX_OPERATIONAL: TX aggregation has become operational */ enum ieee80211_ampdu_mlme_action { IEEE80211_AMPDU_RX_START, IEEE80211_AMPDU_RX_STOP, IEEE80211_AMPDU_TX_START, IEEE80211_AMPDU_TX_STOP, - IEEE80211_AMPDU_TX_RESUME, + IEEE80211_AMPDU_TX_OPERATIONAL, }; /** diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index e5776ef1717..fd718e2b29f 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -404,6 +404,27 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) } EXPORT_SYMBOL(ieee80211_start_tx_ba_session); +static void ieee80211_agg_tx_operational(struct ieee80211_local *local, + struct sta_info *sta, u16 tid) +{ +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); +#endif + + if (local->hw.ampdu_queues) { + /* + * Wake up the A-MPDU queue, we stopped it earlier, + * this will in turn wake the entire AC. + */ + ieee80211_wake_queue_by_reason(&local->hw, + local->hw.queues + sta->tid_to_tx_q[tid], + IEEE80211_QUEUE_STOP_REASON_AGGREGATION); + } + + local->ops->ampdu_action(&local->hw, IEEE80211_AMPDU_TX_OPERATIONAL, + &sta->sta, tid, NULL); +} + void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) { struct ieee80211_local *local = hw_to_local(hw); @@ -446,20 +467,8 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) *state |= HT_ADDBA_DRV_READY_MSK; - if (*state == HT_AGG_STATE_OPERATIONAL) { -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); -#endif - if (hw->ampdu_queues) { - /* - * Wake up this queue, we stopped it earlier, - * this will in turn wake the entire AC. - */ - ieee80211_wake_queue_by_reason(hw, - hw->queues + sta->tid_to_tx_q[tid], - IEEE80211_QUEUE_STOP_REASON_AGGREGATION); - } - } + if (*state == HT_AGG_STATE_OPERATIONAL) + ieee80211_agg_tx_operational(local, sta, tid); out: spin_unlock_bh(&sta->lock); @@ -646,9 +655,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, struct ieee80211_mgmt *mgmt, size_t len) { - struct ieee80211_hw *hw = &local->hw; - u16 capab; - u16 tid, start_seq_num; + u16 capab, tid; u8 *state; capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); @@ -682,26 +689,10 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, *state |= HT_ADDBA_RECEIVED_MSK; - if (hw->ampdu_queues && *state != curstate && - *state == HT_AGG_STATE_OPERATIONAL) { - /* - * Wake up this queue, we stopped it earlier, - * this will in turn wake the entire AC. - */ - ieee80211_wake_queue_by_reason(hw, - hw->queues + sta->tid_to_tx_q[tid], - IEEE80211_QUEUE_STOP_REASON_AGGREGATION); - } - sta->ampdu_mlme.addba_req_num[tid] = 0; + if (*state != curstate && *state == HT_AGG_STATE_OPERATIONAL) + ieee80211_agg_tx_operational(local, sta, tid); - if (local->ops->ampdu_action) { - (void)local->ops->ampdu_action(hw, - IEEE80211_AMPDU_TX_RESUME, - &sta->sta, tid, &start_seq_num); - } -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "Resuming TX aggregation for tid %d\n", tid); -#endif /* CONFIG_MAC80211_HT_DEBUG */ + sta->ampdu_mlme.addba_req_num[tid] = 0; } else { sta->ampdu_mlme.addba_req_num[tid]++; ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR); -- GitLab From a220858d30604902f650074bfac5a7598bc97ea4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Mar 2009 17:28:40 +0100 Subject: [PATCH 4936/4982] mac80211: add skb length sanity checking We just found a bug in zd1211rw where it would reject packets in the ->tx() method but leave them modified, which would cause retransmit attempts with completely bogus skbs, eventually leading to a panic due to not having enough headroom in those. This patch adds a sanity check to mac80211 to catch such driver mistakes; in this case we warn and drop the skb. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/tx.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index b909e4090e9..a0e00c6339c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1089,7 +1089,7 @@ static int __ieee80211_tx(struct ieee80211_local *local, { struct sk_buff *skb = *skbp, *next; struct ieee80211_tx_info *info; - int ret; + int ret, len; bool fragm = false; local->mdev->trans_start = jiffies; @@ -1125,7 +1125,12 @@ static int __ieee80211_tx(struct ieee80211_local *local, } next = skb->next; + len = skb->len; ret = local->ops->tx(local_to_hw(local), skb); + if (WARN_ON(ret != NETDEV_TX_OK && skb->len != len)) { + dev_kfree_skb(skb); + ret = NETDEV_TX_OK; + } if (ret != NETDEV_TX_OK) return IEEE80211_TX_AGAIN; *skbp = skb = next; -- GitLab From cd8ffc800ce18e558335c4946b2217864fc16045 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Mar 2009 17:28:41 +0100 Subject: [PATCH 4937/4982] mac80211: fix aggregation to not require queue stop Instead of stopping the entire AC queue when enabling aggregation (which was only done for hardware with aggregation queues) buffer the packets for each station, and release them to the pending skb queue once aggregation is turned on successfully. We get a little more code, but it becomes conceptually simpler and we can remove the entire virtual queue mechanism from mac80211 in a follow-up patch. This changes how mac80211 behaves towards drivers that support aggregation but have no hardware queues -- those drivers will now not be handed packets while the aggregation session is being established, but only after it has been fully established. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 4 ++ net/mac80211/agg-tx.c | 136 +++++++++++++++++++++-------------- net/mac80211/ieee80211_i.h | 8 +++ net/mac80211/main.c | 2 + net/mac80211/sta_info.c | 5 ++ net/mac80211/sta_info.h | 2 + net/mac80211/tx.c | 142 ++++++++++++++++++++++++++++++------- 7 files changed, 221 insertions(+), 78 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 07fe9875506..841f7f804bb 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -248,6 +248,9 @@ struct ieee80211_bss_conf { * @IEEE80211_TX_INTFL_RCALGO: mac80211 internal flag, do not test or * set this flag in the driver; indicates that the rate control * algorithm was used and should be notified of TX status + * @IEEE80211_TX_INTFL_NEED_TXPROCESSING: completely internal to mac80211, + * used to indicate that a pending frame requires TX processing before + * it can be sent out. */ enum mac80211_tx_control_flags { IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), @@ -264,6 +267,7 @@ enum mac80211_tx_control_flags { IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11), IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), IEEE80211_TX_INTFL_RCALGO = BIT(13), + IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14), }; /** diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index fd718e2b29f..64b839bfbf1 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -132,16 +132,6 @@ static int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, state = &sta->ampdu_mlme.tid_state_tx[tid]; if (local->hw.ampdu_queues) { - if (initiator) { - /* - * Stop the AC queue to avoid issues where we send - * unaggregated frames already before the delba. - */ - ieee80211_stop_queue_by_reason(&local->hw, - local->hw.queues + sta->tid_to_tx_q[tid], - IEEE80211_QUEUE_STOP_REASON_AGGREGATION); - } - /* * Pretend the driver woke the queue, just in case * it disabled it before the session was stopped. @@ -158,6 +148,10 @@ static int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, /* HW shall not deny going back to legacy */ if (WARN_ON(ret)) { *state = HT_AGG_STATE_OPERATIONAL; + /* + * We may have pending packets get stuck in this case... + * Not bothering with a workaround for now. + */ } return ret; @@ -226,13 +220,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) ra, tid); #endif /* CONFIG_MAC80211_HT_DEBUG */ - if (hw->ampdu_queues && ieee80211_ac_from_tid(tid) == 0) { -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "rejecting on voice AC\n"); -#endif - return -EINVAL; - } - rcu_read_lock(); sta = sta_info_get(local, ra); @@ -267,6 +254,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) } spin_lock_bh(&sta->lock); + spin_lock(&local->ampdu_lock); sdata = sta->sdata; @@ -308,21 +296,19 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) ret = -ENOSPC; goto err_unlock_sta; } - - /* - * If we successfully allocate the session, we can't have - * anything going on on the queue this TID maps into, so - * stop it for now. This is a "virtual" stop using the same - * mechanism that drivers will use. - * - * XXX: queue up frames for this session in the sta_info - * struct instead to avoid hitting all other STAs. - */ - ieee80211_stop_queue_by_reason( - &local->hw, hw->queues + qn, - IEEE80211_QUEUE_STOP_REASON_AGGREGATION); } + /* + * While we're asking the driver about the aggregation, + * stop the AC queue so that we don't have to worry + * about frames that came in while we were doing that, + * which would require us to put them to the AC pending + * afterwards which just makes the code more complex. + */ + ieee80211_stop_queue_by_reason( + &local->hw, ieee80211_ac_from_tid(tid), + IEEE80211_QUEUE_STOP_REASON_AGGREGATION); + /* prepare A-MPDU MLME for Tx aggregation */ sta->ampdu_mlme.tid_tx[tid] = kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC); @@ -336,6 +322,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) goto err_return_queue; } + skb_queue_head_init(&sta->ampdu_mlme.tid_tx[tid]->pending); + /* Tx timer */ sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function = sta_addba_resp_timer_expired; @@ -362,6 +350,12 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) } sta->tid_to_tx_q[tid] = qn; + /* Driver vetoed or OKed, but we can take packets again now */ + ieee80211_wake_queue_by_reason( + &local->hw, ieee80211_ac_from_tid(tid), + IEEE80211_QUEUE_STOP_REASON_AGGREGATION); + + spin_unlock(&local->ampdu_lock); spin_unlock_bh(&sta->lock); /* send an addBA request */ @@ -388,15 +382,16 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) sta->ampdu_mlme.tid_tx[tid] = NULL; err_return_queue: if (qn >= 0) { - /* We failed, so start queue again right away. */ - ieee80211_wake_queue_by_reason(hw, hw->queues + qn, - IEEE80211_QUEUE_STOP_REASON_AGGREGATION); /* give queue back to pool */ spin_lock(&local->queue_stop_reason_lock); local->ampdu_ac_queue[qn] = -1; spin_unlock(&local->queue_stop_reason_lock); } + ieee80211_wake_queue_by_reason( + &local->hw, ieee80211_ac_from_tid(tid), + IEEE80211_QUEUE_STOP_REASON_AGGREGATION); err_unlock_sta: + spin_unlock(&local->ampdu_lock); spin_unlock_bh(&sta->lock); unlock: rcu_read_unlock(); @@ -404,6 +399,45 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) } EXPORT_SYMBOL(ieee80211_start_tx_ba_session); +/* + * splice packets from the STA's pending to the local pending, + * requires a call to ieee80211_agg_splice_finish and holding + * local->ampdu_lock across both calls. + */ +static void ieee80211_agg_splice_packets(struct ieee80211_local *local, + struct sta_info *sta, u16 tid) +{ + unsigned long flags; + u16 queue = ieee80211_ac_from_tid(tid); + + ieee80211_stop_queue_by_reason( + &local->hw, queue, + IEEE80211_QUEUE_STOP_REASON_AGGREGATION); + + if (!skb_queue_empty(&sta->ampdu_mlme.tid_tx[tid]->pending)) { + spin_lock_irqsave(&local->queue_stop_reason_lock, flags); + /* mark queue as pending, it is stopped already */ + __set_bit(IEEE80211_QUEUE_STOP_REASON_PENDING, + &local->queue_stop_reasons[queue]); + /* copy over remaining packets */ + skb_queue_splice_tail_init( + &sta->ampdu_mlme.tid_tx[tid]->pending, + &local->pending[queue]); + spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); + } +} + +static void ieee80211_agg_splice_finish(struct ieee80211_local *local, + struct sta_info *sta, u16 tid) +{ + u16 queue = ieee80211_ac_from_tid(tid); + + ieee80211_wake_queue_by_reason( + &local->hw, queue, + IEEE80211_QUEUE_STOP_REASON_AGGREGATION); +} + +/* caller must hold sta->lock */ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, struct sta_info *sta, u16 tid) { @@ -411,15 +445,16 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); #endif - if (local->hw.ampdu_queues) { - /* - * Wake up the A-MPDU queue, we stopped it earlier, - * this will in turn wake the entire AC. - */ - ieee80211_wake_queue_by_reason(&local->hw, - local->hw.queues + sta->tid_to_tx_q[tid], - IEEE80211_QUEUE_STOP_REASON_AGGREGATION); - } + spin_lock(&local->ampdu_lock); + ieee80211_agg_splice_packets(local, sta, tid); + /* + * NB: we rely on sta->lock being taken in the TX + * processing here when adding to the pending queue, + * otherwise we could only change the state of the + * session to OPERATIONAL _here_. + */ + ieee80211_agg_splice_finish(local, sta, tid); + spin_unlock(&local->ampdu_lock); local->ops->ampdu_action(&local->hw, IEEE80211_AMPDU_TX_OPERATIONAL, &sta->sta, tid, NULL); @@ -602,22 +637,19 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); spin_lock_bh(&sta->lock); + spin_lock(&local->ampdu_lock); - if (*state & HT_AGG_STATE_INITIATOR_MSK && - hw->ampdu_queues) { - /* - * Wake up this queue, we stopped it earlier, - * this will in turn wake the entire AC. - */ - ieee80211_wake_queue_by_reason(hw, - hw->queues + sta->tid_to_tx_q[tid], - IEEE80211_QUEUE_STOP_REASON_AGGREGATION); - } + ieee80211_agg_splice_packets(local, sta, tid); *state = HT_AGG_STATE_IDLE; + /* from now on packets are no longer put onto sta->pending */ sta->ampdu_mlme.addba_req_num[tid] = 0; kfree(sta->ampdu_mlme.tid_tx[tid]); sta->ampdu_mlme.tid_tx[tid] = NULL; + + ieee80211_agg_splice_finish(local, sta, tid); + + spin_unlock(&local->ampdu_lock); spin_unlock_bh(&sta->lock); rcu_read_unlock(); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 6ce62e553dc..32345b479ad 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -639,6 +639,14 @@ struct ieee80211_local { struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; struct tasklet_struct tx_pending_tasklet; + /* + * This lock is used to prevent concurrent A-MPDU + * session start/stop processing, this thus also + * synchronises the ->ampdu_action() callback to + * drivers and limits it to one at a time. + */ + spinlock_t ampdu_lock; + /* number of interfaces with corresponding IFF_ flags */ atomic_t iff_allmultis, iff_promiscs; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index a7430e98c53..756284e0bbd 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -795,6 +795,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, skb_queue_head_init(&local->skb_queue); skb_queue_head_init(&local->skb_queue_unreliable); + spin_lock_init(&local->ampdu_lock); + return local_to_hw(local); } EXPORT_SYMBOL(ieee80211_alloc_hw); diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 4ba3c540fcf..dd3593c1fd2 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -239,6 +239,11 @@ void sta_info_destroy(struct sta_info *sta) tid_tx = sta->ampdu_mlme.tid_tx[i]; if (tid_tx) { del_timer_sync(&tid_tx->addba_resp_timer); + /* + * STA removed while aggregation session being + * started? Bit odd, but purge frames anyway. + */ + skb_queue_purge(&tid_tx->pending); kfree(tid_tx); } } diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 5b223b216e5..18fd5d1a442 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -73,11 +73,13 @@ enum ieee80211_sta_info_flags { * struct tid_ampdu_tx - TID aggregation information (Tx). * * @addba_resp_timer: timer for peer's response to addba request + * @pending: pending frames queue -- use sta's spinlock to protect * @ssn: Starting Sequence Number expected to be aggregated. * @dialog_token: dialog token for aggregation session */ struct tid_ampdu_tx { struct timer_list addba_resp_timer; + struct sk_buff_head pending; u16 ssn; u8 dialog_token; }; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index a0e00c6339c..906ab785db4 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -984,9 +984,9 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, struct ieee80211_hdr *hdr; struct ieee80211_sub_if_data *sdata; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - int hdrlen, tid; u8 *qc, *state; + bool queued = false; memset(tx, 0, sizeof(*tx)); tx->skb = skb; @@ -1013,20 +1013,53 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, */ } + /* + * If this flag is set to true anywhere, and we get here, + * we are doing the needed processing, so remove the flag + * now. + */ + info->flags &= ~IEEE80211_TX_INTFL_NEED_TXPROCESSING; + hdr = (struct ieee80211_hdr *) skb->data; tx->sta = sta_info_get(local, hdr->addr1); - if (tx->sta && ieee80211_is_data_qos(hdr->frame_control)) { + if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && + (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) { unsigned long flags; + struct tid_ampdu_tx *tid_tx; + qc = ieee80211_get_qos_ctl(hdr); tid = *qc & IEEE80211_QOS_CTL_TID_MASK; spin_lock_irqsave(&tx->sta->lock, flags); + /* + * XXX: This spinlock could be fairly expensive, but see the + * comment in agg-tx.c:ieee80211_agg_tx_operational(). + * One way to solve this would be to do something RCU-like + * for managing the tid_tx struct and using atomic bitops + * for the actual state -- by introducing an actual + * 'operational' bit that would be possible. It would + * require changing ieee80211_agg_tx_operational() to + * set that bit, and changing the way tid_tx is managed + * everywhere, including races between that bit and + * tid_tx going away (tid_tx being added can be easily + * committed to memory before the 'operational' bit). + */ + tid_tx = tx->sta->ampdu_mlme.tid_tx[tid]; state = &tx->sta->ampdu_mlme.tid_state_tx[tid]; - if (*state == HT_AGG_STATE_OPERATIONAL) + if (*state == HT_AGG_STATE_OPERATIONAL) { info->flags |= IEEE80211_TX_CTL_AMPDU; + } else if (*state != HT_AGG_STATE_IDLE) { + /* in progress */ + queued = true; + info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; + __skb_queue_tail(&tid_tx->pending, skb); + } spin_unlock_irqrestore(&tx->sta->lock, flags); + + if (unlikely(queued)) + return TX_QUEUED; } if (is_multicast_ether_addr(hdr->addr1)) { @@ -1077,7 +1110,14 @@ static int ieee80211_tx_prepare(struct ieee80211_local *local, } if (unlikely(!dev)) return -ENODEV; - /* initialises tx with control */ + /* + * initialises tx with control + * + * return value is safe to ignore here because this function + * can only be invoked for multicast frames + * + * XXX: clean up + */ __ieee80211_tx_prepare(tx, skb, dev); dev_put(dev); return 0; @@ -1188,7 +1228,8 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) return 0; } -static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) +static void ieee80211_tx(struct net_device *dev, struct sk_buff *skb, + bool txpending) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct sta_info *sta; @@ -1202,11 +1243,11 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) queue = skb_get_queue_mapping(skb); - WARN_ON(!skb_queue_empty(&local->pending[queue])); + WARN_ON(!txpending && !skb_queue_empty(&local->pending[queue])); if (unlikely(skb->len < 10)) { dev_kfree_skb(skb); - return 0; + return; } rcu_read_lock(); @@ -1214,10 +1255,13 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) /* initialises tx */ res_prepare = __ieee80211_tx_prepare(&tx, skb, dev); - if (res_prepare == TX_DROP) { + if (unlikely(res_prepare == TX_DROP)) { dev_kfree_skb(skb); rcu_read_unlock(); - return 0; + return; + } else if (unlikely(res_prepare == TX_QUEUED)) { + rcu_read_unlock(); + return; } sta = tx.sta; @@ -1251,7 +1295,12 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) do { next = skb->next; skb->next = NULL; - skb_queue_tail(&local->pending[queue], skb); + if (unlikely(txpending)) + skb_queue_head(&local->pending[queue], + skb); + else + skb_queue_tail(&local->pending[queue], + skb); } while ((skb = next)); /* @@ -1276,7 +1325,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) } out: rcu_read_unlock(); - return 0; + return; drop: rcu_read_unlock(); @@ -1287,7 +1336,6 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) dev_kfree_skb(skb); skb = next; } - return 0; } /* device xmit handlers */ @@ -1346,7 +1394,6 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) FOUND_SDATA, UNKNOWN_ADDRESS, } monitor_iface = NOT_MONITOR; - int ret; if (skb->iif) odev = dev_get_by_index(&init_net, skb->iif); @@ -1360,7 +1407,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) "originating device\n", dev->name); #endif dev_kfree_skb(skb); - return 0; + return NETDEV_TX_OK; } if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && @@ -1389,7 +1436,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) else if (mesh_nexthop_lookup(skb, osdata)) { dev_put(odev); - return 0; + return NETDEV_TX_OK; } if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh, @@ -1451,7 +1498,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) if (ieee80211_skb_resize(osdata->local, skb, headroom, may_encrypt)) { dev_kfree_skb(skb); dev_put(odev); - return 0; + return NETDEV_TX_OK; } if (osdata->vif.type == NL80211_IFTYPE_AP_VLAN) @@ -1460,10 +1507,11 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) u.ap); if (likely(monitor_iface != UNKNOWN_ADDRESS)) info->control.vif = &osdata->vif; - ret = ieee80211_tx(odev, skb); + + ieee80211_tx(odev, skb, false); dev_put(odev); - return ret; + return NETDEV_TX_OK; } int ieee80211_monitor_start_xmit(struct sk_buff *skb, @@ -1827,6 +1875,54 @@ void ieee80211_clear_tx_pending(struct ieee80211_local *local) skb_queue_purge(&local->pending[i]); } +static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, + struct sk_buff *skb) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_sub_if_data *sdata; + struct sta_info *sta; + struct ieee80211_hdr *hdr; + struct net_device *dev; + int ret; + bool result = true; + + /* does interface still exist? */ + dev = dev_get_by_index(&init_net, skb->iif); + if (!dev) { + dev_kfree_skb(skb); + return true; + } + + /* validate info->control.vif against skb->iif */ + sdata = IEEE80211_DEV_TO_SUB_IF(dev); + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + sdata = container_of(sdata->bss, + struct ieee80211_sub_if_data, + u.ap); + + if (unlikely(info->control.vif && info->control.vif != &sdata->vif)) { + dev_kfree_skb(skb); + result = true; + goto out; + } + + if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) { + ieee80211_tx(dev, skb, true); + } else { + hdr = (struct ieee80211_hdr *)skb->data; + sta = sta_info_get(local, hdr->addr1); + + ret = __ieee80211_tx(local, &skb, sta); + if (ret != IEEE80211_TX_OK) + result = false; + } + + out: + dev_put(dev); + + return result; +} + /* * Transmit all pending packets. Called from tasklet, locks master device * TX lock so that no new packets can come in. @@ -1835,9 +1931,8 @@ void ieee80211_tx_pending(unsigned long data) { struct ieee80211_local *local = (struct ieee80211_local *)data; struct net_device *dev = local->mdev; - struct ieee80211_hdr *hdr; unsigned long flags; - int i, ret; + int i; bool next; rcu_read_lock(); @@ -1868,13 +1963,8 @@ void ieee80211_tx_pending(unsigned long data) while (!skb_queue_empty(&local->pending[i])) { struct sk_buff *skb = skb_dequeue(&local->pending[i]); - struct sta_info *sta; - - hdr = (struct ieee80211_hdr *)skb->data; - sta = sta_info_get(local, hdr->addr1); - ret = __ieee80211_tx(local, &skb, sta); - if (ret != IEEE80211_TX_OK) { + if (!ieee80211_tx_pending_skb(local, skb)) { skb_queue_head(&local->pending[i], skb); break; } -- GitLab From e4e72fb4de93e3d4047a4ee3f08778422e17ed0d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Mar 2009 17:28:42 +0100 Subject: [PATCH 4938/4982] mac80211/iwlwifi: move virtual A-MDPU queue bookkeeping to iwlwifi This patch removes all the virtual A-MPDU-queue bookkeeping from mac80211. Curiously, iwlwifi already does its own bookkeeping, so it doesn't require much changes except where it needs to handle starting and stopping the queues in mac80211. To handle the queue stop/wake properly, we rewrite the software queue number for aggregation frames and internally to iwlwifi keep track of the queues that map into the same AC queue, and only talk to mac80211 about the AC queue. The implementation requires calling two new functions, iwl_stop_queue and iwl_wake_queue instead of the mac80211 counterparts. Signed-off-by: Johannes Berg Cc: Reinette Chattre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 7 ++- drivers/net/wireless/iwlwifi/iwl-5000.c | 7 ++- drivers/net/wireless/iwlwifi/iwl-core.c | 3 -- drivers/net/wireless/iwlwifi/iwl-dev.h | 6 +++ drivers/net/wireless/iwlwifi/iwl-helpers.h | 52 ++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-tx.c | 8 +-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- drivers/net/wireless/mac80211_hwsim.c | 1 - include/net/mac80211.h | 14 +---- net/mac80211/agg-tx.c | 44 ++-------------- net/mac80211/ieee80211_i.h | 7 +-- net/mac80211/main.c | 9 ---- net/mac80211/sta_info.c | 12 ----- net/mac80211/sta_info.h | 2 - net/mac80211/tx.c | 19 ------- net/mac80211/util.c | 58 +++------------------ 17 files changed, 84 insertions(+), 169 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index d03f5534afe..2399328e8de 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -293,7 +293,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv, if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) && (txq_id != IWL_CMD_QUEUE_NUM) && priv->mac80211_registered) - ieee80211_wake_queue(priv->hw, txq_id); + iwl_wake_queue(priv, txq_id); } /** diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index bd0140be774..847a6220c5e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2178,10 +2178,9 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, (iwl_queue_space(&txq->q) > txq->q.low_mark) && (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) { if (agg->state == IWL_AGG_OFF) - ieee80211_wake_queue(priv->hw, txq_id); + iwl_wake_queue(priv, txq_id); else - ieee80211_wake_queue(priv->hw, - txq->swq_id); + iwl_wake_queue(priv, txq->swq_id); } } } else { @@ -2205,7 +2204,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, if (priv->mac80211_registered && (iwl_queue_space(&txq->q) > txq->q.low_mark)) - ieee80211_wake_queue(priv->hw, txq_id); + iwl_wake_queue(priv, txq_id); } if (qc && likely(sta_id != IWL_INVALID_STATION)) diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index a3d9a95a9b3..e5ca2511a81 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1295,10 +1295,9 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, (iwl_queue_space(&txq->q) > txq->q.low_mark) && (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) { if (agg->state == IWL_AGG_OFF) - ieee80211_wake_queue(priv->hw, txq_id); + iwl_wake_queue(priv, txq_id); else - ieee80211_wake_queue(priv->hw, - txq->swq_id); + iwl_wake_queue(priv, txq->swq_id); } } } else { @@ -1324,7 +1323,7 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, if (priv->mac80211_registered && (iwl_queue_space(&txq->q) > txq->q.low_mark)) - ieee80211_wake_queue(priv->hw, txq_id); + iwl_wake_queue(priv, txq_id); } if (ieee80211_is_data_qos(tx_resp->frame_ctrl)) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 4b1298c2b0d..c54fb93e9d7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1309,9 +1309,6 @@ int iwl_setup_mac(struct iwl_priv *priv) /* Default value; 4 EDCA QOS priorities */ hw->queues = 4; - /* queues to support 11n aggregation */ - if (priv->cfg->sku & IWL_SKU_N) - hw->ampdu_queues = priv->cfg->mod_params->num_of_ampdu_queues; hw->conf.beacon_int = 100; hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 0baae802282..ec9a13846ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -996,6 +996,12 @@ struct iwl_priv { u8 key_mapping_key; unsigned long ucode_key_table; + /* queue refcounts */ +#define IWL_MAX_HW_QUEUES 32 + unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)]; + /* for each AC */ + atomic_t queue_stop_count[4]; + /* Indication if ieee80211_ops->open has been called */ u8 is_open; diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index fb64d297dd4..a1328c3c81a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -93,4 +93,56 @@ static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev, return (desc->v_addr != NULL) ? 0 : -ENOMEM; } +/* + * we have 8 bits used like this: + * + * 7 6 5 4 3 2 1 0 + * | | | | | | | | + * | | | | | | +-+-------- AC queue (0-3) + * | | | | | | + * | +-+-+-+-+------------ HW A-MPDU queue + * | + * +---------------------- indicates agg queue + */ +static inline u8 iwl_virtual_agg_queue_num(u8 ac, u8 hwq) +{ + BUG_ON(ac > 3); /* only have 2 bits */ + BUG_ON(hwq > 31); /* only have 5 bits */ + + return 0x80 | (hwq << 2) | ac; +} + +static inline void iwl_wake_queue(struct iwl_priv *priv, u8 queue) +{ + u8 ac = queue; + u8 hwq = queue; + + if (queue & 0x80) { + ac = queue & 3; + hwq = (queue >> 2) & 0x1f; + } + + if (test_and_clear_bit(hwq, priv->queue_stopped)) + if (atomic_dec_return(&priv->queue_stop_count[ac]) <= 0) + ieee80211_wake_queue(priv->hw, ac); +} + +static inline void iwl_stop_queue(struct iwl_priv *priv, u8 queue) +{ + u8 ac = queue; + u8 hwq = queue; + + if (queue & 0x80) { + ac = queue & 3; + hwq = (queue >> 2) & 0x1f; + } + + if (!test_and_set_bit(hwq, priv->queue_stopped)) + if (atomic_inc_return(&priv->queue_stop_count[ac]) > 0) + ieee80211_stop_queue(priv->hw, ac); +} + +#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue +#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue + #endif /* __iwl_helpers_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index b13862a598e..1f117a49c56 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -763,8 +763,10 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) hdr->seq_ctrl |= cpu_to_le16(seq_number); seq_number += 0x10; /* aggregation is on for this */ - if (info->flags & IEEE80211_TX_CTL_AMPDU) + if (info->flags & IEEE80211_TX_CTL_AMPDU) { txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; + swq_id = iwl_virtual_agg_queue_num(swq_id, txq_id); + } priv->stations[sta_id].tid[tid].tfds_in_queue++; } @@ -895,7 +897,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) iwl_txq_update_write_ptr(priv, txq); spin_unlock_irqrestore(&priv->lock, flags); } else { - ieee80211_stop_queue(priv->hw, txq->swq_id); + iwl_stop_queue(priv, txq->swq_id); } } @@ -1433,7 +1435,7 @@ void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, if ((iwl_queue_space(&txq->q) > txq->q.low_mark) && priv->mac80211_registered && (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) - ieee80211_wake_queue(priv->hw, txq->swq_id); + iwl_wake_queue(priv, txq->swq_id); iwl_txq_check_empty(priv, sta_id, tid, scd_flow); } diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index ede29b6c4dc..a71b08ca7c7 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1168,7 +1168,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) spin_unlock_irqrestore(&priv->lock, flags); } - ieee80211_stop_queue(priv->hw, skb_get_queue_mapping(skb)); + iwl_stop_queue(priv, skb_get_queue_mapping(skb)); } return 0; diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 55116102475..d4fdc8b7d7d 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -933,7 +933,6 @@ static int __init init_mac80211_hwsim(void) BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MESH_POINT); - hw->ampdu_queues = 1; hw->flags = IEEE80211_HW_MFP_CAPABLE; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 841f7f804bb..3b83a80e3fe 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -93,12 +93,9 @@ struct ieee80211_ht_bss_info { * enum ieee80211_max_queues - maximum number of queues * * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues. - * @IEEE80211_MAX_AMPDU_QUEUES: Maximum number of queues usable - * for A-MPDU operation. */ enum ieee80211_max_queues { IEEE80211_MAX_QUEUES = 4, - IEEE80211_MAX_AMPDU_QUEUES = 16, }; /** @@ -952,12 +949,6 @@ enum ieee80211_hw_flags { * data packets. WMM/QoS requires at least four, these * queues need to have configurable access parameters. * - * @ampdu_queues: number of available hardware transmit queues - * for A-MPDU packets, these have no access parameters - * because they're used only for A-MPDU frames. Note that - * mac80211 will not currently use any of the regular queues - * for aggregation. - * * @rate_control_algorithm: rate control algorithm for this hardware. * If unset (NULL), the default algorithm will be used. Must be * set before calling ieee80211_register_hw(). @@ -982,7 +973,6 @@ struct ieee80211_hw { int vif_data_size; int sta_data_size; u16 queues; - u16 ampdu_queues; u16 max_listen_interval; s8 max_signal; u8 max_rates; @@ -1372,8 +1362,8 @@ enum ieee80211_ampdu_mlme_action { * @get_tx_stats: Get statistics of the current TX queue status. This is used * to get number of currently queued packets (queue length), maximum queue * size (limit), and total number of packets sent using each TX queue - * (count). The 'stats' pointer points to an array that has hw->queues + - * hw->ampdu_queues items. + * (count). The 'stats' pointer points to an array that has hw->queues + * items. * * @get_tsf: Get the current TSF timer value from firmware/hardware. Currently, * this is only used for IBSS mode BSSID merging and debugging. Is not a diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 64b839bfbf1..947aaaad35d 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -131,14 +131,6 @@ static int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, state = &sta->ampdu_mlme.tid_state_tx[tid]; - if (local->hw.ampdu_queues) { - /* - * Pretend the driver woke the queue, just in case - * it disabled it before the session was stopped. - */ - ieee80211_wake_queue( - &local->hw, local->hw.queues + sta->tid_to_tx_q[tid]); - } *state = HT_AGG_STATE_REQ_STOP_BA_MSK | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); @@ -206,7 +198,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) struct sta_info *sta; struct ieee80211_sub_if_data *sdata; u8 *state; - int i, qn = -1, ret = 0; + int ret = 0; u16 start_seq_num; if (WARN_ON(!local->ops->ampdu_action)) @@ -275,29 +267,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) goto err_unlock_sta; } - if (hw->ampdu_queues) { - spin_lock(&local->queue_stop_reason_lock); - /* reserve a new queue for this session */ - for (i = 0; i < local->hw.ampdu_queues; i++) { - if (local->ampdu_ac_queue[i] < 0) { - qn = i; - local->ampdu_ac_queue[qn] = - ieee80211_ac_from_tid(tid); - break; - } - } - spin_unlock(&local->queue_stop_reason_lock); - - if (qn < 0) { -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "BA request denied - " - "queue unavailable for tid %d\n", tid); -#endif /* CONFIG_MAC80211_HT_DEBUG */ - ret = -ENOSPC; - goto err_unlock_sta; - } - } - /* * While we're asking the driver about the aggregation, * stop the AC queue so that we don't have to worry @@ -319,7 +288,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) tid); #endif ret = -ENOMEM; - goto err_return_queue; + goto err_wake_queue; } skb_queue_head_init(&sta->ampdu_mlme.tid_tx[tid]->pending); @@ -348,7 +317,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) *state = HT_AGG_STATE_IDLE; goto err_free; } - sta->tid_to_tx_q[tid] = qn; /* Driver vetoed or OKed, but we can take packets again now */ ieee80211_wake_queue_by_reason( @@ -380,13 +348,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) err_free: kfree(sta->ampdu_mlme.tid_tx[tid]); sta->ampdu_mlme.tid_tx[tid] = NULL; - err_return_queue: - if (qn >= 0) { - /* give queue back to pool */ - spin_lock(&local->queue_stop_reason_lock); - local->ampdu_ac_queue[qn] = -1; - spin_unlock(&local->queue_stop_reason_lock); - } + err_wake_queue: ieee80211_wake_queue_by_reason( &local->hw, ieee80211_ac_from_tid(tid), IEEE80211_QUEUE_STOP_REASON_AGGREGATION); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 32345b479ad..e6ed78cb16b 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -594,12 +594,7 @@ struct ieee80211_local { const struct ieee80211_ops *ops; - /* AC queue corresponding to each AMPDU queue */ - s8 ampdu_ac_queue[IEEE80211_MAX_AMPDU_QUEUES]; - unsigned int amdpu_ac_stop_refcnt[IEEE80211_MAX_AMPDU_QUEUES]; - - unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES + - IEEE80211_MAX_AMPDU_QUEUES]; + unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES]; /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ spinlock_t queue_stop_reason_lock; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 756284e0bbd..a6f1d8a869b 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -774,11 +774,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, setup_timer(&local->dynamic_ps_timer, ieee80211_dynamic_ps_timer, (unsigned long) local); - for (i = 0; i < IEEE80211_MAX_AMPDU_QUEUES; i++) - local->ampdu_ac_queue[i] = -1; - /* using an s8 won't work with more than that */ - BUILD_BUG_ON(IEEE80211_MAX_AMPDU_QUEUES > 127); - sta_info_init(local); for (i = 0; i < IEEE80211_MAX_QUEUES; i++) @@ -874,10 +869,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) */ if (hw->queues > IEEE80211_MAX_QUEUES) hw->queues = IEEE80211_MAX_QUEUES; - if (hw->ampdu_queues > IEEE80211_MAX_AMPDU_QUEUES) - hw->ampdu_queues = IEEE80211_MAX_AMPDU_QUEUES; - if (hw->queues < 4) - hw->ampdu_queues = 0; mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv), "wmaster%d", ieee80211_master_setup, diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index dd3593c1fd2..c5f14e6bbde 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -203,17 +203,6 @@ void sta_info_destroy(struct sta_info *sta) if (tid_rx) tid_rx->shutdown = true; - /* - * The stop callback cannot find this station any more, but - * it didn't complete its work -- start the queue if necessary - */ - if (sta->ampdu_mlme.tid_state_tx[i] & HT_AGG_STATE_INITIATOR_MSK && - sta->ampdu_mlme.tid_state_tx[i] & HT_AGG_STATE_REQ_STOP_BA_MSK && - local->hw.ampdu_queues) - ieee80211_wake_queue_by_reason(&local->hw, - local->hw.queues + sta->tid_to_tx_q[i], - IEEE80211_QUEUE_STOP_REASON_AGGREGATION); - spin_unlock_bh(&sta->lock); /* @@ -292,7 +281,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, * enable session_timer's data differentiation. refer to * sta_rx_agg_session_timer_expired for useage */ sta->timer_to_tid[i] = i; - sta->tid_to_tx_q[i] = -1; /* rx */ sta->ampdu_mlme.tid_state_rx[i] = HT_AGG_STATE_IDLE; sta->ampdu_mlme.tid_rx[i] = NULL; diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 18fd5d1a442..5534d489f50 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -206,7 +206,6 @@ struct sta_ampdu_mlme { * @tid_seq: per-TID sequence numbers for sending to this STA * @ampdu_mlme: A-MPDU state machine state * @timer_to_tid: identity mapping to ID timers - * @tid_to_tx_q: map tid to tx queue (invalid == negative values) * @llid: Local link ID * @plid: Peer link ID * @reason: Cancel reason on PLINK_HOLDING state @@ -281,7 +280,6 @@ struct sta_info { */ struct sta_ampdu_mlme ampdu_mlme; u8 timer_to_tid[STA_TID_NUM]; - s8 tid_to_tx_q[STA_TID_NUM]; #ifdef CONFIG_MAC80211_MESH /* diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 906ab785db4..3fb04a86444 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1145,25 +1145,6 @@ static int __ieee80211_tx(struct ieee80211_local *local, info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT | IEEE80211_TX_CTL_FIRST_FRAGMENT); - /* - * Internally, we need to have the queue mapping point to - * the real AC queue, not the virtual A-MPDU queue. This - * now finally sets the queue to what the driver wants. - * We will later move this down into the only driver that - * needs it, iwlwifi. - */ - if (sta && local->hw.ampdu_queues && - info->flags & IEEE80211_TX_CTL_AMPDU) { - unsigned long flags; - u8 *qc = ieee80211_get_qos_ctl((void *) skb->data); - int tid = *qc & IEEE80211_QOS_CTL_TID_MASK; - - spin_lock_irqsave(&sta->lock, flags); - skb_set_queue_mapping(skb, local->hw.queues + - sta->tid_to_tx_q[tid]); - spin_unlock_irqrestore(&sta->lock, flags); - } - next = skb->next; len = skb->len; ret = local->ops->tx(local_to_hw(local), skb); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 0247d8022f5..fdf432f1455 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -339,29 +339,8 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, { struct ieee80211_local *local = hw_to_local(hw); - if (queue >= hw->queues) { - if (local->ampdu_ac_queue[queue - hw->queues] < 0) - return; - - /* - * for virtual aggregation queues, we need to refcount the - * internal mac80211 disable (multiple times!), keep track of - * driver disable _and_ make sure the regular queue is - * actually enabled. - */ - if (reason == IEEE80211_QUEUE_STOP_REASON_AGGREGATION) - local->amdpu_ac_stop_refcnt[queue - hw->queues]--; - else - __clear_bit(reason, &local->queue_stop_reasons[queue]); - - if (local->queue_stop_reasons[queue] || - local->amdpu_ac_stop_refcnt[queue - hw->queues]) - return; - - /* now go on to treat the corresponding regular queue */ - queue = local->ampdu_ac_queue[queue - hw->queues]; - reason = IEEE80211_QUEUE_STOP_REASON_AGGREGATION; - } + if (WARN_ON(queue >= hw->queues)) + return; __clear_bit(reason, &local->queue_stop_reasons[queue]); @@ -400,25 +379,8 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, { struct ieee80211_local *local = hw_to_local(hw); - if (queue >= hw->queues) { - if (local->ampdu_ac_queue[queue - hw->queues] < 0) - return; - - /* - * for virtual aggregation queues, we need to refcount the - * internal mac80211 disable (multiple times!), keep track of - * driver disable _and_ make sure the regular queue is - * actually enabled. - */ - if (reason == IEEE80211_QUEUE_STOP_REASON_AGGREGATION) - local->amdpu_ac_stop_refcnt[queue - hw->queues]++; - else - __set_bit(reason, &local->queue_stop_reasons[queue]); - - /* now go on to treat the corresponding regular queue */ - queue = local->ampdu_ac_queue[queue - hw->queues]; - reason = IEEE80211_QUEUE_STOP_REASON_AGGREGATION; - } + if (WARN_ON(queue >= hw->queues)) + return; /* * Only stop if it was previously running, this is necessary @@ -474,15 +436,9 @@ EXPORT_SYMBOL(ieee80211_stop_queues); int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue) { struct ieee80211_local *local = hw_to_local(hw); - unsigned long flags; - if (queue >= hw->queues) { - spin_lock_irqsave(&local->queue_stop_reason_lock, flags); - queue = local->ampdu_ac_queue[queue - hw->queues]; - spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); - if (queue < 0) - return true; - } + if (WARN_ON(queue >= hw->queues)) + return true; return __netif_subqueue_stopped(local->mdev, queue); } @@ -497,7 +453,7 @@ void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, spin_lock_irqsave(&local->queue_stop_reason_lock, flags); - for (i = 0; i < hw->queues + hw->ampdu_queues; i++) + for (i = 0; i < hw->queues; i++) __ieee80211_wake_queue(hw, i, reason); spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); -- GitLab From 8a5117d80fe93de5df5b56480054f7df1fd20755 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 24 Mar 2009 21:21:07 -0400 Subject: [PATCH 4939/4982] cfg80211: default CONFIG_WIRELESS_OLD_REGULATORY to n And update description and feature-removal schedule according to the new plan. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- Documentation/feature-removal-schedule.txt | 13 +++++--- net/wireless/Kconfig | 37 ++++++---------------- 2 files changed, 18 insertions(+), 32 deletions(-) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 8365f52a354..02ea3773535 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -7,7 +7,7 @@ be removed from this file. --------------------------- What: The ieee80211_regdom module parameter -When: March 2010 +When: March 2010 / desktop catchup Why: This was inherited by the CONFIG_WIRELESS_OLD_REGULATORY code, and currently serves as an option for users to define an @@ -30,18 +30,23 @@ Who: Luis R. Rodriguez --------------------------- -What: old static regulatory information -When: 2.6.29 +What: CONFIG_WIRELESS_OLD_REGULATORY - old static regulatory information +When: March 2010 / desktop catchup + Why: The old regulatory infrastructure has been replaced with a new one which does not require statically defined regulatory domains. We do not want to keep static regulatory domains in the kernel due to the the dynamic nature of regulatory law and localization. We kept around the old static definitions for the regulatory domains of: + * US * JP * EU + and used by default the US when CONFIG_WIRELESS_OLD_REGULATORY was - set. + set. We will remove this option once the standard Linux desktop catches + up with the new userspace APIs we have implemented. + Who: Luis R. Rodriguez --------------------------- diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index d1d18f34d27..3c3bc9e579e 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig @@ -12,36 +12,17 @@ config CFG80211_REG_DEBUG config WIRELESS_OLD_REGULATORY bool "Old wireless static regulatory definitions" - default y + default n ---help--- This option enables the old static regulatory information - and uses it within the new framework. This is available - temporarily as an option to help prevent immediate issues - due to the switch to the new regulatory framework which - does require a new userspace application which has the - database of regulatory information (CRDA) and another for - setting regulatory domains (iw). - - For more information see: - - http://wireless.kernel.org/en/developers/Regulatory/CRDA - http://wireless.kernel.org/en/users/Documentation/iw - - It is important to note though that if you *do* have CRDA present - and if this option is enabled CRDA *will* be called to update the - regulatory domain (for US and JP only). Support for letting the user - set the regulatory domain through iw is also supported. This option - mainly exists to leave around for a kernel release some old static - regulatory domains that were defined and to keep around the old - ieee80211_regdom module parameter. This is being phased out and you - should stop using them ASAP. - - Note: You will need CRDA if you want 802.11d support - - Say Y unless you have installed a new userspace application. - Also say Y if have one currently depending on the ieee80211_regdom - module parameter and cannot port it to use the new userspace - interfaces. + and uses it within the new framework. This option is available + for historical reasons and it is advised to leave it off. + + For details see: + + http://wireless.kernel.org/en/developers/Regulatory + + Say N and if you say Y, please tell us why. The default is N. config WIRELESS_EXT bool "Wireless extensions" -- GitLab From 80e20f6f360078b4852eac6825883e5aa25564bb Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 27 Mar 2009 17:22:55 -0700 Subject: [PATCH 4940/4982] Revert "netrom: zero length frame filtering in NetRom" This reverts commit a3ac80a130300573de351083cf4a5b46d233e8bf. Alan Cox says that zero length writes do have special meaning and are useful in this protocol. Signed-off-by: David S. Miller --- net/netrom/af_netrom.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index d1c16bbee93..4e705f87969 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -1037,10 +1037,6 @@ static int nr_sendmsg(struct kiocb *iocb, struct socket *sock, unsigned char *asmptr; int size; - /* Netrom empty data frame has no meaning : don't send */ - if (len == 0) - return 0; - if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_CMSG_COMPAT)) return -EINVAL; @@ -1175,11 +1171,6 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock, skb_reset_transport_header(skb); copied = skb->len; - /* NetRom empty data frame has no meaning : ignore it */ - if (copied == 0) { - goto out; - } - if (copied > size) { copied = size; msg->msg_flags |= MSG_TRUNC; @@ -1195,7 +1186,7 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock, msg->msg_namelen = sizeof(*sax); -out: skb_free_datagram(sk, skb); + skb_free_datagram(sk, skb); release_sock(sk); return copied; -- GitLab From c44a4366649aca4f5b4a51ff71d4c9cde3b7c9da Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 27 Mar 2009 17:23:42 -0700 Subject: [PATCH 4941/4982] Revert "ax25: zero length frame filtering in AX25" This reverts commit f99bcff7a290768e035f3d4726e103c6ebe858bf. Like netrom, Alan Cox says that zero lengths have real meaning and are useful in this protocol. Signed-off-by: David S. Miller --- net/ax25/af_ax25.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 7da5ebb84e9..fd9d06f291d 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1435,11 +1435,6 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock, size_t size; int lv, err, addr_len = msg->msg_namelen; - /* AX.25 empty data frame has no meaning : don't send */ - if (len == 0) { - return (0); - } - if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_CMSG_COMPAT)) return -EINVAL; @@ -1639,13 +1634,6 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock, skb_reset_transport_header(skb); copied = skb->len; - /* AX.25 empty data frame has no meaning : ignore it */ - if (copied == 0) { - err = copied; - skb_free_datagram(sk, skb); - goto out; - } - if (copied > size) { copied = size; msg->msg_flags |= MSG_TRUNC; -- GitLab From 6e8a4fa651975ff808dba130eae442f4cea1671c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 27 Mar 2009 18:15:02 -0700 Subject: [PATCH 4942/4982] sparc64: We need to use compat_sys_ustat() as well. Sparc was missed in commit 2b1c6bd77d4e6a727ffac8630cd154b2144b751a ("generic compat_sys_ustat"). We definitely need it, since our __kernel_ino_t is "unsigned long". Signed-off-by: David S. Miller --- arch/sparc/kernel/systbls_64.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S index f93c42a2b52..a8000b1cda7 100644 --- a/arch/sparc/kernel/systbls_64.S +++ b/arch/sparc/kernel/systbls_64.S @@ -51,7 +51,7 @@ sys_call_table32: /*150*/ .word sys_nis_syscall, sys_inotify_init, sys_inotify_add_watch, sys_poll, sys_getdents64 .word compat_sys_fcntl64, sys_inotify_rm_watch, compat_sys_statfs, compat_sys_fstatfs, sys_oldumount /*160*/ .word compat_sys_sched_setaffinity, compat_sys_sched_getaffinity, sys32_getdomainname, sys32_setdomainname, sys_nis_syscall - .word sys_quotactl, sys_set_tid_address, compat_sys_mount, sys_ustat, sys32_setxattr + .word sys_quotactl, sys_set_tid_address, compat_sys_mount, compat_sys_ustat, sys32_setxattr /*170*/ .word sys32_lsetxattr, sys32_fsetxattr, sys_getxattr, sys_lgetxattr, compat_sys_getdents .word sys_setsid, sys_fchdir, sys32_fgetxattr, sys_listxattr, sys_llistxattr /*180*/ .word sys32_flistxattr, sys_removexattr, sys_lremovexattr, compat_sys_sigpending, sys_ni_syscall -- GitLab From 085780d5bb53edbc008156c310ac512aabd23610 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sat, 28 Mar 2009 17:43:01 +0800 Subject: [PATCH 4943/4982] Blackfin arch: include linux headers that this one uses definitions from fro sport drivers Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/bfin_sport.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/blackfin/include/asm/bfin_sport.h b/arch/blackfin/include/asm/bfin_sport.h index 65a651db5b0..d4169590e75 100644 --- a/arch/blackfin/include/asm/bfin_sport.h +++ b/arch/blackfin/include/asm/bfin_sport.h @@ -9,6 +9,13 @@ #ifndef __BFIN_SPORT_H__ #define __BFIN_SPORT_H__ +#ifdef __KERNEL__ +#include +#include +#include +#include +#endif + #define SPORT_MAJOR 237 #define SPORT_NR_DEVS 2 -- GitLab From c9b78189f50dcba6e69080268873a62c67e4bc15 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 27 Mar 2009 22:00:09 +0100 Subject: [PATCH 4944/4982] [ARM] pxa: fix Colibri PXA300 and PXA320 LCD backlight pins Reported-by: Matthias Meier Signed-off-by: Daniel Mack Signed-off-by: Eric Miao --- arch/arm/mach-pxa/colibri-pxa300.c | 2 +- arch/arm/mach-pxa/colibri-pxa320.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-pxa/colibri-pxa300.c b/arch/arm/mach-pxa/colibri-pxa300.c index 169ab552c21..10c2eaf9323 100644 --- a/arch/arm/mach-pxa/colibri-pxa300.c +++ b/arch/arm/mach-pxa/colibri-pxa300.c @@ -172,7 +172,7 @@ void __init colibri_pxa300_init(void) colibri_pxa300_init_eth(); colibri_pxa300_init_ohci(); colibri_pxa300_init_lcd(); - colibri_pxa3xx_init_lcd(mfp_to_gpio(GPIO49_GPIO)); + colibri_pxa3xx_init_lcd(mfp_to_gpio(GPIO39_GPIO)); colibri_pxa310_init_ac97(); colibri_pxa3xx_init_mmc(ARRAY_AND_SIZE(colibri_pxa300_mmc_pin_config), mfp_to_gpio(MFP_PIN_GPIO13)); diff --git a/arch/arm/mach-pxa/colibri-pxa320.c b/arch/arm/mach-pxa/colibri-pxa320.c index 573a9a1dd52..55b74a7a615 100644 --- a/arch/arm/mach-pxa/colibri-pxa320.c +++ b/arch/arm/mach-pxa/colibri-pxa320.c @@ -169,7 +169,7 @@ void __init colibri_pxa320_init(void) colibri_pxa320_init_eth(); colibri_pxa320_init_ohci(); colibri_pxa320_init_lcd(); - colibri_pxa3xx_init_lcd(mfp_to_gpio(GPIO39_GPIO)); + colibri_pxa3xx_init_lcd(mfp_to_gpio(GPIO49_GPIO)); colibri_pxa320_init_ac97(); colibri_pxa3xx_init_mmc(ARRAY_AND_SIZE(colibri_pxa320_mmc_pin_config), mfp_to_gpio(MFP_PIN_GPIO28)); -- GitLab From d66ea8d4c2aa7199cf4e5c977eb25764e5fc5da9 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 28 Mar 2009 17:56:28 +0800 Subject: [PATCH 4945/4982] [ARM] pxa: fix the bad assumption that PCMCIA sockets always start with 0 Signed-off-by: Marek Vasut Signed-off-by: Eric Miao --- drivers/pcmcia/pxa2xx_base.c | 4 ++-- drivers/pcmcia/pxa2xx_palmld.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c index 16f84aab6ab..c49a7269f6d 100644 --- a/drivers/pcmcia/pxa2xx_base.c +++ b/drivers/pcmcia/pxa2xx_base.c @@ -214,7 +214,7 @@ static void pxa2xx_configure_sockets(struct device *dev) MECR |= MECR_CIT; /* Set MECR:NOS (Number Of Sockets) */ - if (ops->nr > 1 || machine_is_viper()) + if ((ops->first + ops->nr) > 1 || machine_is_viper()) MECR |= MECR_NOS; else MECR &= ~MECR_NOS; @@ -250,7 +250,7 @@ int __pxa2xx_drv_pcmcia_probe(struct device *dev) for (i = 0; i < ops->nr; i++) { skt = &sinfo->skt[i]; - skt->nr = i; + skt->nr = ops->first + i; skt->irq = NO_IRQ; skt->res_skt.start = _PCMCIA(skt->nr); diff --git a/drivers/pcmcia/pxa2xx_palmld.c b/drivers/pcmcia/pxa2xx_palmld.c index 1736c67e547..5ba9b3664a0 100644 --- a/drivers/pcmcia/pxa2xx_palmld.c +++ b/drivers/pcmcia/pxa2xx_palmld.c @@ -98,8 +98,8 @@ static void palmld_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) static struct pcmcia_low_level palmld_pcmcia_ops = { .owner = THIS_MODULE, - .first = 0, - .nr = 2, + .first = 1, + .nr = 1, .hw_init = palmld_pcmcia_hw_init, .hw_shutdown = palmld_pcmcia_hw_shutdown, -- GitLab From a66648756f97ea5150875b85a0177c33e41afc1d Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Sat, 28 Mar 2009 23:46:17 +0800 Subject: [PATCH 4946/4982] Blackfin arch: update default kernel configuration Signed-off-by: Sonic Zhang Signed-off-by: Bryan Wu --- arch/blackfin/configs/BF518F-EZBRD_defconfig | 42 ++++- arch/blackfin/configs/BF526-EZBRD_defconfig | 140 +++++++++------- arch/blackfin/configs/BF527-EZKIT_defconfig | 150 +++++++++-------- arch/blackfin/configs/BF533-EZKIT_defconfig | 54 +++--- arch/blackfin/configs/BF533-STAMP_defconfig | 100 ++++-------- arch/blackfin/configs/BF537-STAMP_defconfig | 97 ++++------- arch/blackfin/configs/BF538-EZKIT_defconfig | 101 ++++-------- arch/blackfin/configs/BF548-EZKIT_defconfig | 163 ++++++++++--------- arch/blackfin/configs/BF561-EZKIT_defconfig | 54 +++--- arch/blackfin/configs/BlackStamp_defconfig | 4 +- arch/blackfin/configs/CM-BF527_defconfig | 6 +- arch/blackfin/configs/CM-BF533_defconfig | 4 +- arch/blackfin/configs/CM-BF537E_defconfig | 4 +- arch/blackfin/configs/CM-BF537U_defconfig | 4 +- arch/blackfin/configs/CM-BF548_defconfig | 4 +- arch/blackfin/configs/CM-BF561_defconfig | 4 +- arch/blackfin/configs/H8606_defconfig | 4 +- arch/blackfin/configs/IP0X_defconfig | 4 +- arch/blackfin/configs/PNAV-10_defconfig | 39 ++++- arch/blackfin/configs/SRV1_defconfig | 4 +- arch/blackfin/configs/TCM-BF537_defconfig | 6 +- 21 files changed, 501 insertions(+), 487 deletions(-) diff --git a/arch/blackfin/configs/BF518F-EZBRD_defconfig b/arch/blackfin/configs/BF518F-EZBRD_defconfig index 281f4b60e60..c121d6e6e2b 100644 --- a/arch/blackfin/configs/BF518F-EZBRD_defconfig +++ b/arch/blackfin/configs/BF518F-EZBRD_defconfig @@ -1,7 +1,6 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.28 -# Fri Feb 20 10:01:44 2009 +# Linux kernel version: 2.6.28.7 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -43,7 +42,7 @@ CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y +# CONFIG_SYSCTL is not set CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y @@ -56,13 +55,13 @@ CONFIG_BUG=y # CONFIG_ELF_CORE is not set CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y -CONFIG_FUTEX=y +# CONFIG_FUTEX is not set CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y CONFIG_TIMERFD=y CONFIG_EVENTFD=y -CONFIG_AIO=y +# CONFIG_AIO is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -314,7 +313,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_VIRT_TO_BUS=y -CONFIG_BFIN_GPTIMERS=y +CONFIG_BFIN_GPTIMERS=m # CONFIG_DMA_UNCACHED_4M is not set # CONFIG_DMA_UNCACHED_2M is not set CONFIG_DMA_UNCACHED_1M=y @@ -375,7 +374,6 @@ CONFIG_BINFMT_ZFLAT=y # # CONFIG_PM is not set CONFIG_ARCH_SUSPEND_POSSIBLE=y -# CONFIG_PM_WAKEUP_BY_GPIO is not set # # CPU Frequency scaling @@ -634,6 +632,7 @@ CONFIG_BFIN_RX_DESC_NUM=20 # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set @@ -793,6 +792,7 @@ CONFIG_SPI_MASTER=y # CONFIG_SPI_BFIN=y # CONFIG_SPI_BFIN_LOCK is not set +# CONFIG_SPI_BFIN_SPORT is not set # CONFIG_SPI_BITBANG is not set # @@ -816,6 +816,12 @@ CONFIG_WATCHDOG=y # # CONFIG_SOFT_WATCHDOG is not set CONFIG_BFIN_WDT=y +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set # # Multifunction device drivers @@ -865,7 +871,26 @@ CONFIG_DUMMY_CONSOLE=y # CONFIG_SOUND is not set # CONFIG_HID_SUPPORT is not set # CONFIG_USB_SUPPORT is not set -# CONFIG_MMC is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +CONFIG_SDH_BFIN=m +CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND=y +CONFIG_SDH_BFIN_ENABLE_SDIO_IRQ=y +# CONFIG_MMC_SPI is not set # CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set # CONFIG_ACCESSIBILITY is not set @@ -1121,7 +1146,6 @@ CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set # CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_KGDB_TESTCASE is not set CONFIG_DEBUG_VERBOSE=y CONFIG_DEBUG_MMRS=y # CONFIG_DEBUG_HWERR is not set diff --git a/arch/blackfin/configs/BF526-EZBRD_defconfig b/arch/blackfin/configs/BF526-EZBRD_defconfig index 8e2b855b8db..3e562b2775d 100644 --- a/arch/blackfin/configs/BF526-EZBRD_defconfig +++ b/arch/blackfin/configs/BF526-EZBRD_defconfig @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.28-rc2 +# Linux kernel version: 2.6.28.7 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -42,7 +42,7 @@ CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y +# CONFIG_SYSCTL is not set CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y @@ -55,13 +55,13 @@ CONFIG_BUG=y # CONFIG_ELF_CORE is not set CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y -CONFIG_FUTEX=y +# CONFIG_FUTEX is not set CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y CONFIG_TIMERFD=y CONFIG_EVENTFD=y -CONFIG_AIO=y +# CONFIG_AIO is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -132,15 +132,20 @@ CONFIG_BF526=y # CONFIG_BF538 is not set # CONFIG_BF539 is not set # CONFIG_BF542 is not set +# CONFIG_BF542M is not set # CONFIG_BF544 is not set +# CONFIG_BF544M is not set # CONFIG_BF547 is not set +# CONFIG_BF547M is not set # CONFIG_BF548 is not set +# CONFIG_BF548M is not set # CONFIG_BF549 is not set +# CONFIG_BF549M is not set # CONFIG_BF561 is not set CONFIG_BF_REV_MIN=0 CONFIG_BF_REV_MAX=2 -CONFIG_BF_REV_0_0=y -# CONFIG_BF_REV_0_1 is not set +# CONFIG_BF_REV_0_0 is not set +CONFIG_BF_REV_0_1=y # CONFIG_BF_REV_0_2 is not set # CONFIG_BF_REV_0_3 is not set # CONFIG_BF_REV_0_4 is not set @@ -313,7 +318,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_VIRT_TO_BUS=y -CONFIG_BFIN_GPTIMERS=y +CONFIG_BFIN_GPTIMERS=m # CONFIG_DMA_UNCACHED_4M is not set # CONFIG_DMA_UNCACHED_2M is not set CONFIG_DMA_UNCACHED_1M=y @@ -374,7 +379,6 @@ CONFIG_BINFMT_ZFLAT=y # # CONFIG_PM is not set CONFIG_ARCH_SUSPEND_POSSIBLE=y -# CONFIG_PM_WAKEUP_BY_GPIO is not set # # CPU Frequency scaling @@ -583,7 +587,9 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set +# CONFIG_ICS932S401 is not set # CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -637,6 +643,7 @@ CONFIG_BFIN_MAC_RMII=y # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set CONFIG_NETDEV_1000=y # CONFIG_AX88180 is not set CONFIG_NETDEV_10000=y @@ -815,6 +822,7 @@ CONFIG_SPI_MASTER=y # CONFIG_SPI_BFIN=y # CONFIG_SPI_BFIN_LOCK is not set +# CONFIG_SPI_BFIN_SPORT is not set # CONFIG_SPI_BITBANG is not set # @@ -838,6 +846,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_ADM1029 is not set # CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7462 is not set # CONFIG_SENSORS_ADT7470 is not set # CONFIG_SENSORS_ADT7473 is not set # CONFIG_SENSORS_ATXP1 is not set @@ -896,6 +905,12 @@ CONFIG_BFIN_WDT=y # USB-based Watchdog Cards # # CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set # # Multifunction device drivers @@ -904,8 +919,10 @@ CONFIG_BFIN_WDT=y # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_MFD_TMIO is not set +# CONFIG_PMIC_DA903X is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_REGULATOR is not set # # Multimedia devices @@ -940,55 +957,7 @@ CONFIG_BFIN_WDT=y # Console display driver support # CONFIG_DUMMY_CONSOLE=y -CONFIG_SOUND=m -CONFIG_SOUND_OSS_CORE=y -CONFIG_SND=m -CONFIG_SND_TIMER=m -CONFIG_SND_PCM=m -# CONFIG_SND_SEQUENCER is not set -CONFIG_SND_OSSEMUL=y -CONFIG_SND_MIXER_OSS=m -CONFIG_SND_PCM_OSS=m -CONFIG_SND_PCM_OSS_PLUGINS=y -# CONFIG_SND_DYNAMIC_MINORS is not set -CONFIG_SND_SUPPORT_OLD_API=y -CONFIG_SND_VERBOSE_PROCFS=y -# CONFIG_SND_VERBOSE_PRINTK is not set -# CONFIG_SND_DEBUG is not set -CONFIG_SND_DRIVERS=y -# CONFIG_SND_DUMMY is not set -# CONFIG_SND_MTPAV is not set -# CONFIG_SND_SERIAL_U16550 is not set -# CONFIG_SND_MPU401 is not set -CONFIG_SND_SPI=y - -# -# ALSA Blackfin devices -# -# CONFIG_SND_BLACKFIN_AD1836 is not set -# CONFIG_SND_BFIN_AD73322 is not set -CONFIG_SND_USB=y -# CONFIG_SND_USB_AUDIO is not set -# CONFIG_SND_USB_CAIAQ is not set -CONFIG_SND_SOC=m -CONFIG_SND_SOC_AC97_BUS=y -CONFIG_SND_BF5XX_I2S=m -CONFIG_SND_BF5XX_SOC_SSM2602=m -# CONFIG_SND_BF5XX_SOC_AD73311 is not set -CONFIG_SND_BF5XX_AC97=m -CONFIG_SND_BF5XX_MMAP_SUPPORT=y -# CONFIG_SND_BF5XX_MULTICHAN_SUPPORT is not set -CONFIG_SND_BF5XX_SOC_SPORT=m -CONFIG_SND_BF5XX_SOC_I2S=m -CONFIG_SND_BF5XX_SOC_AC97=m -CONFIG_SND_BF5XX_SOC_AD1980=m -CONFIG_SND_BF5XX_SPORT_NUM=0 -# CONFIG_SND_BF5XX_HAVE_COLD_RESET is not set -# CONFIG_SND_SOC_ALL_CODECS is not set -CONFIG_SND_SOC_AD1980=m -CONFIG_SND_SOC_SSM2602=m -# CONFIG_SOUND_PRIME is not set -CONFIG_AC97_BUS=m +# CONFIG_SOUND is not set CONFIG_HID_SUPPORT=y CONFIG_HID=y # CONFIG_HID_DEBUG is not set @@ -1063,13 +1032,15 @@ CONFIG_USB_MUSB_HDRC=y CONFIG_USB_MUSB_SOC=y # -# Blackfin high speed USB support +# Blackfin high speed USB Support # CONFIG_USB_MUSB_HOST=y # CONFIG_USB_MUSB_PERIPHERAL is not set # CONFIG_USB_MUSB_OTG is not set +# CONFIG_USB_GADGET_MUSB_HDRC is not set CONFIG_USB_MUSB_HDRC_HCD=y CONFIG_MUSB_PIO_ONLY=y +CONFIG_MUSB_DMA_POLL=y # CONFIG_USB_MUSB_DEBUG is not set # @@ -1081,18 +1052,33 @@ CONFIG_MUSB_PIO_ONLY=y # CONFIG_USB_TMC is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; # # -# may also be needed; see USB_STORAGE Help for more information +# see USB_STORAGE Help for more information # +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set # CONFIG_USB_LIBUSUAL is not set # # USB Imaging devices # # CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set # # USB port drivers @@ -1124,6 +1110,30 @@ CONFIG_MUSB_PIO_ONLY=y # CONFIG_USB_ISIGHTFW is not set # CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set +# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_PXA27X is not set +# CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_FSL_QE is not set +# CONFIG_USB_GADGET_NET2272 is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_ZERO is not set +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set # CONFIG_MMC is not set # CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set @@ -1158,12 +1168,14 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_M41T80 is not set # CONFIG_RTC_DRV_S35390A is not set # CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set # # SPI RTC drivers # # CONFIG_RTC_DRV_M41T94 is not set # CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set # CONFIG_RTC_DRV_MAX6902 is not set # CONFIG_RTC_DRV_R9701 is not set # CONFIG_RTC_DRV_RS5C348 is not set @@ -1384,6 +1396,13 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_FAULT_INJECTION is not set CONFIG_SYSCTL_SYSCALL_CHECK=y + +# +# Tracers +# +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set # CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y @@ -1423,6 +1442,7 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_FIPS is not set # CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_CRYPTD is not set diff --git a/arch/blackfin/configs/BF527-EZKIT_defconfig b/arch/blackfin/configs/BF527-EZKIT_defconfig index a50050f1770..911b5dba1db 100644 --- a/arch/blackfin/configs/BF527-EZKIT_defconfig +++ b/arch/blackfin/configs/BF527-EZKIT_defconfig @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.28-rc2 +# Linux kernel version: 2.6.28.7 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -36,14 +36,13 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set # CONFIG_GROUP_SCHED is not set -# CONFIG_SYSFS_DEPRECATED is not set # CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y +# CONFIG_SYSCTL is not set CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y @@ -56,13 +55,13 @@ CONFIG_BUG=y # CONFIG_ELF_CORE is not set CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y -CONFIG_FUTEX=y +# CONFIG_FUTEX is not set CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y CONFIG_TIMERFD=y CONFIG_EVENTFD=y -CONFIG_AIO=y +# CONFIG_AIO is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -133,15 +132,20 @@ CONFIG_BF527=y # CONFIG_BF538 is not set # CONFIG_BF539 is not set # CONFIG_BF542 is not set +# CONFIG_BF542M is not set # CONFIG_BF544 is not set +# CONFIG_BF544M is not set # CONFIG_BF547 is not set +# CONFIG_BF547M is not set # CONFIG_BF548 is not set +# CONFIG_BF548M is not set # CONFIG_BF549 is not set +# CONFIG_BF549M is not set # CONFIG_BF561 is not set CONFIG_BF_REV_MIN=0 CONFIG_BF_REV_MAX=2 -CONFIG_BF_REV_0_0=y -# CONFIG_BF_REV_0_1 is not set +# CONFIG_BF_REV_0_0 is not set +CONFIG_BF_REV_0_1=y # CONFIG_BF_REV_0_2 is not set # CONFIG_BF_REV_0_3 is not set # CONFIG_BF_REV_0_4 is not set @@ -314,7 +318,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_VIRT_TO_BUS=y -CONFIG_BFIN_GPTIMERS=y +CONFIG_BFIN_GPTIMERS=m # CONFIG_DMA_UNCACHED_4M is not set # CONFIG_DMA_UNCACHED_2M is not set CONFIG_DMA_UNCACHED_1M=y @@ -375,7 +379,6 @@ CONFIG_BINFMT_ZFLAT=y # # CONFIG_PM is not set CONFIG_ARCH_SUSPEND_POSSIBLE=y -# CONFIG_PM_WAKEUP_BY_GPIO is not set # # CPU Frequency scaling @@ -626,7 +629,9 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set +# CONFIG_ICS932S401 is not set # CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -681,6 +686,7 @@ CONFIG_BFIN_MAC_RMII=y # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set CONFIG_NETDEV_1000=y # CONFIG_AX88180 is not set CONFIG_NETDEV_10000=y @@ -755,8 +761,8 @@ CONFIG_INPUT_MISC=y # CONFIG_SPI_ADC_BF533 is not set # CONFIG_BF5xx_PPIFCD is not set # CONFIG_BFIN_SIMPLE_TIMER is not set -# CONFIG_BF5xx_PPI is not set -# CONFIG_BFIN_SPORT is not set +CONFIG_BF5xx_PPI=m +CONFIG_BFIN_SPORT=m # CONFIG_BFIN_TIMER_LATENCY is not set # CONFIG_TWI_LCD is not set CONFIG_BFIN_DMA_INTERFACE=m @@ -859,6 +865,7 @@ CONFIG_SPI_MASTER=y # CONFIG_SPI_BFIN=y # CONFIG_SPI_BFIN_LOCK is not set +# CONFIG_SPI_BFIN_SPORT is not set # CONFIG_SPI_BITBANG is not set # @@ -871,60 +878,7 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y # CONFIG_GPIOLIB is not set # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set -CONFIG_HWMON=y -# CONFIG_HWMON_VID is not set -# CONFIG_SENSORS_AD7414 is not set -# CONFIG_SENSORS_AD7418 is not set -# CONFIG_SENSORS_ADCXX is not set -# CONFIG_SENSORS_ADM1021 is not set -# CONFIG_SENSORS_ADM1025 is not set -# CONFIG_SENSORS_ADM1026 is not set -# CONFIG_SENSORS_ADM1029 is not set -# CONFIG_SENSORS_ADM1031 is not set -# CONFIG_SENSORS_ADM9240 is not set -# CONFIG_SENSORS_ADT7470 is not set -# CONFIG_SENSORS_ADT7473 is not set -# CONFIG_SENSORS_ATXP1 is not set -# CONFIG_SENSORS_DS1621 is not set -# CONFIG_SENSORS_F71805F is not set -# CONFIG_SENSORS_F71882FG is not set -# CONFIG_SENSORS_F75375S is not set -# CONFIG_SENSORS_GL518SM is not set -# CONFIG_SENSORS_GL520SM is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_LM63 is not set -# CONFIG_SENSORS_LM70 is not set -# CONFIG_SENSORS_LM75 is not set -# CONFIG_SENSORS_LM77 is not set -# CONFIG_SENSORS_LM78 is not set -# CONFIG_SENSORS_LM80 is not set -# CONFIG_SENSORS_LM83 is not set -# CONFIG_SENSORS_LM85 is not set -# CONFIG_SENSORS_LM87 is not set -# CONFIG_SENSORS_LM90 is not set -# CONFIG_SENSORS_LM92 is not set -# CONFIG_SENSORS_LM93 is not set -# CONFIG_SENSORS_MAX1111 is not set -# CONFIG_SENSORS_MAX1619 is not set -# CONFIG_SENSORS_MAX6650 is not set -# CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_PC87427 is not set -# CONFIG_SENSORS_DME1737 is not set -# CONFIG_SENSORS_SMSC47M1 is not set -# CONFIG_SENSORS_SMSC47M192 is not set -# CONFIG_SENSORS_SMSC47B397 is not set -# CONFIG_SENSORS_ADS7828 is not set -# CONFIG_SENSORS_THMC50 is not set -# CONFIG_SENSORS_VT1211 is not set -# CONFIG_SENSORS_W83781D is not set -# CONFIG_SENSORS_W83791D is not set -# CONFIG_SENSORS_W83792D is not set -# CONFIG_SENSORS_W83793 is not set -# CONFIG_SENSORS_W83L785TS is not set -# CONFIG_SENSORS_W83L786NG is not set -# CONFIG_SENSORS_W83627HF is not set -# CONFIG_SENSORS_W83627EHF is not set -# CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_HWMON is not set # CONFIG_THERMAL is not set # CONFIG_THERMAL_HWMON is not set CONFIG_WATCHDOG=y @@ -940,6 +894,12 @@ CONFIG_BFIN_WDT=y # USB-based Watchdog Cards # # CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set # # Multifunction device drivers @@ -948,8 +908,10 @@ CONFIG_BFIN_WDT=y # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_MFD_TMIO is not set +# CONFIG_PMIC_DA903X is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_REGULATOR is not set # # Multimedia devices @@ -1000,6 +962,7 @@ CONFIG_FB_BFIN_T350MCQB=y # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_LCD_CLASS_DEVICE=m CONFIG_LCD_LTV350QV=m @@ -1152,13 +1115,15 @@ CONFIG_USB_MUSB_HDRC=y CONFIG_USB_MUSB_SOC=y # -# Blackfin high speed USB support +# Blackfin high speed USB Support # CONFIG_USB_MUSB_HOST=y # CONFIG_USB_MUSB_PERIPHERAL is not set # CONFIG_USB_MUSB_OTG is not set +# CONFIG_USB_GADGET_MUSB_HDRC is not set CONFIG_USB_MUSB_HDRC_HCD=y CONFIG_MUSB_PIO_ONLY=y +CONFIG_MUSB_DMA_POLL=y # CONFIG_USB_MUSB_DEBUG is not set # @@ -1170,18 +1135,33 @@ CONFIG_MUSB_PIO_ONLY=y # CONFIG_USB_TMC is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; # # -# may also be needed; see USB_STORAGE Help for more information +# see USB_STORAGE Help for more information # +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set # CONFIG_USB_LIBUSUAL is not set # # USB Imaging devices # # CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set # # USB port drivers @@ -1213,6 +1193,30 @@ CONFIG_MUSB_PIO_ONLY=y # CONFIG_USB_ISIGHTFW is not set # CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set +# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_PXA27X is not set +# CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_FSL_QE is not set +# CONFIG_USB_GADGET_NET2272 is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_ZERO is not set +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set # CONFIG_MMC is not set # CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set @@ -1247,12 +1251,14 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_M41T80 is not set # CONFIG_RTC_DRV_S35390A is not set # CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set # # SPI RTC drivers # # CONFIG_RTC_DRV_M41T94 is not set # CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set # CONFIG_RTC_DRV_MAX6902 is not set # CONFIG_RTC_DRV_R9701 is not set # CONFIG_RTC_DRV_RS5C348 is not set @@ -1473,6 +1479,13 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set + +# +# Tracers +# +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set # CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y @@ -1512,6 +1525,7 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_FIPS is not set # CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_CRYPTD is not set diff --git a/arch/blackfin/configs/BF533-EZKIT_defconfig b/arch/blackfin/configs/BF533-EZKIT_defconfig index 0a2a00d6388..4c41e03efe0 100644 --- a/arch/blackfin/configs/BF533-EZKIT_defconfig +++ b/arch/blackfin/configs/BF533-EZKIT_defconfig @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.28-rc2 +# Linux kernel version: 2.6.28.7 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -36,14 +36,13 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set # CONFIG_GROUP_SCHED is not set -# CONFIG_SYSFS_DEPRECATED is not set # CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y +# CONFIG_SYSCTL is not set CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y @@ -56,13 +55,13 @@ CONFIG_BUG=y # CONFIG_ELF_CORE is not set CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y -CONFIG_FUTEX=y +# CONFIG_FUTEX is not set CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y CONFIG_TIMERFD=y CONFIG_EVENTFD=y -CONFIG_AIO=y +# CONFIG_AIO is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -133,10 +132,15 @@ CONFIG_BF533=y # CONFIG_BF538 is not set # CONFIG_BF539 is not set # CONFIG_BF542 is not set +# CONFIG_BF542M is not set # CONFIG_BF544 is not set +# CONFIG_BF544M is not set # CONFIG_BF547 is not set +# CONFIG_BF547M is not set # CONFIG_BF548 is not set +# CONFIG_BF548M is not set # CONFIG_BF549 is not set +# CONFIG_BF549M is not set # CONFIG_BF561 is not set CONFIG_BF_REV_MIN=3 CONFIG_BF_REV_MAX=6 @@ -157,7 +161,6 @@ CONFIG_BFIN533_EZKIT=y # CONFIG_BFIN533_BLUETECHNIX_CM is not set # CONFIG_H8606_HVSISTEMAS is not set # CONFIG_BFIN532_IP0X is not set -# CONFIG_GENERIC_BF533_BOARD is not set # # BF533/2/1 Specific Configuration @@ -277,7 +280,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_VIRT_TO_BUS=y -# CONFIG_BFIN_GPTIMERS is not set +CONFIG_BFIN_GPTIMERS=m # CONFIG_DMA_UNCACHED_4M is not set # CONFIG_DMA_UNCACHED_2M is not set CONFIG_DMA_UNCACHED_1M=y @@ -575,6 +578,7 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set # CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -608,6 +612,7 @@ CONFIG_SMC91X=y # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set CONFIG_NETDEV_1000=y # CONFIG_AX88180 is not set CONFIG_NETDEV_10000=y @@ -714,6 +719,7 @@ CONFIG_SPI_MASTER=y # CONFIG_SPI_BFIN=y # CONFIG_SPI_BFIN_LOCK is not set +# CONFIG_SPI_BFIN_SPORT is not set # CONFIG_SPI_BITBANG is not set # @@ -726,22 +732,7 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y # CONFIG_GPIOLIB is not set # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set -CONFIG_HWMON=y -# CONFIG_HWMON_VID is not set -# CONFIG_SENSORS_ADCXX is not set -# CONFIG_SENSORS_F71805F is not set -# CONFIG_SENSORS_F71882FG is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_LM70 is not set -# CONFIG_SENSORS_MAX1111 is not set -# CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_PC87427 is not set -# CONFIG_SENSORS_SMSC47M1 is not set -# CONFIG_SENSORS_SMSC47B397 is not set -# CONFIG_SENSORS_VT1211 is not set -# CONFIG_SENSORS_W83627HF is not set -# CONFIG_SENSORS_W83627EHF is not set -# CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_HWMON is not set # CONFIG_THERMAL is not set # CONFIG_THERMAL_HWMON is not set CONFIG_WATCHDOG=y @@ -752,6 +743,12 @@ CONFIG_WATCHDOG=y # # CONFIG_SOFT_WATCHDOG is not set CONFIG_BFIN_WDT=y +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set # # Multifunction device drivers @@ -760,7 +757,7 @@ CONFIG_BFIN_WDT=y # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_MFD_TMIO is not set -# CONFIG_MFD_WM8400 is not set +# CONFIG_REGULATOR is not set # # Multimedia devices @@ -826,6 +823,7 @@ CONFIG_RTC_INTF_DEV=y # # CONFIG_RTC_DRV_M41T94 is not set # CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set # CONFIG_RTC_DRV_MAX6902 is not set # CONFIG_RTC_DRV_R9701 is not set # CONFIG_RTC_DRV_RS5C348 is not set @@ -1046,6 +1044,13 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set + +# +# Tracers +# +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set # CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y @@ -1084,6 +1089,7 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_FIPS is not set # CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_CRYPTD is not set diff --git a/arch/blackfin/configs/BF533-STAMP_defconfig b/arch/blackfin/configs/BF533-STAMP_defconfig index eb027587a35..9c482cd1b34 100644 --- a/arch/blackfin/configs/BF533-STAMP_defconfig +++ b/arch/blackfin/configs/BF533-STAMP_defconfig @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.28-rc2 +# Linux kernel version: 2.6.28.7 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -36,14 +36,13 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set # CONFIG_GROUP_SCHED is not set -# CONFIG_SYSFS_DEPRECATED is not set # CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y +# CONFIG_SYSCTL is not set CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y @@ -56,13 +55,13 @@ CONFIG_BUG=y # CONFIG_ELF_CORE is not set CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y -CONFIG_FUTEX=y +# CONFIG_FUTEX is not set CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y CONFIG_TIMERFD=y CONFIG_EVENTFD=y -CONFIG_AIO=y +# CONFIG_AIO is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -133,10 +132,15 @@ CONFIG_BF533=y # CONFIG_BF538 is not set # CONFIG_BF539 is not set # CONFIG_BF542 is not set +# CONFIG_BF542M is not set # CONFIG_BF544 is not set +# CONFIG_BF544M is not set # CONFIG_BF547 is not set +# CONFIG_BF547M is not set # CONFIG_BF548 is not set +# CONFIG_BF548M is not set # CONFIG_BF549 is not set +# CONFIG_BF549M is not set # CONFIG_BF561 is not set CONFIG_BF_REV_MIN=3 CONFIG_BF_REV_MAX=6 @@ -157,7 +161,6 @@ CONFIG_BFIN533_STAMP=y # CONFIG_BFIN533_BLUETECHNIX_CM is not set # CONFIG_H8606_HVSISTEMAS is not set # CONFIG_BFIN532_IP0X is not set -# CONFIG_GENERIC_BF533_BOARD is not set # # BF533/2/1 Specific Configuration @@ -277,7 +280,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_VIRT_TO_BUS=y -# CONFIG_BFIN_GPTIMERS is not set +CONFIG_BFIN_GPTIMERS=m # CONFIG_DMA_UNCACHED_4M is not set # CONFIG_DMA_UNCACHED_2M is not set CONFIG_DMA_UNCACHED_1M=y @@ -578,7 +581,9 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set +# CONFIG_ICS932S401 is not set # CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -612,6 +617,7 @@ CONFIG_SMC91X=y # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set CONFIG_NETDEV_1000=y # CONFIG_AX88180 is not set CONFIG_NETDEV_10000=y @@ -671,10 +677,10 @@ CONFIG_CONFIG_INPUT_PCF8574=m # CONFIG_SPI_ADC_BF533 is not set # CONFIG_BF5xx_PPIFCD is not set # CONFIG_BFIN_SIMPLE_TIMER is not set -# CONFIG_BF5xx_PPI is not set -CONFIG_BFIN_SPORT=y +CONFIG_BF5xx_PPI=m +CONFIG_BFIN_SPORT=m # CONFIG_BFIN_TIMER_LATENCY is not set -CONFIG_TWI_LCD=m +# CONFIG_TWI_LCD is not set CONFIG_BFIN_DMA_INTERFACE=m CONFIG_SIMPLE_GPIO=m # CONFIG_VT is not set @@ -765,6 +771,7 @@ CONFIG_SPI_MASTER=y # CONFIG_SPI_BFIN=y # CONFIG_SPI_BFIN_LOCK is not set +# CONFIG_SPI_BFIN_SPORT is not set # CONFIG_SPI_BITBANG is not set # @@ -777,60 +784,7 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y # CONFIG_GPIOLIB is not set # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set -CONFIG_HWMON=y -# CONFIG_HWMON_VID is not set -# CONFIG_SENSORS_AD7414 is not set -# CONFIG_SENSORS_AD7418 is not set -# CONFIG_SENSORS_ADCXX is not set -# CONFIG_SENSORS_ADM1021 is not set -# CONFIG_SENSORS_ADM1025 is not set -# CONFIG_SENSORS_ADM1026 is not set -# CONFIG_SENSORS_ADM1029 is not set -# CONFIG_SENSORS_ADM1031 is not set -# CONFIG_SENSORS_ADM9240 is not set -# CONFIG_SENSORS_ADT7470 is not set -# CONFIG_SENSORS_ADT7473 is not set -# CONFIG_SENSORS_ATXP1 is not set -# CONFIG_SENSORS_DS1621 is not set -# CONFIG_SENSORS_F71805F is not set -# CONFIG_SENSORS_F71882FG is not set -# CONFIG_SENSORS_F75375S is not set -# CONFIG_SENSORS_GL518SM is not set -# CONFIG_SENSORS_GL520SM is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_LM63 is not set -# CONFIG_SENSORS_LM70 is not set -# CONFIG_SENSORS_LM75 is not set -# CONFIG_SENSORS_LM77 is not set -# CONFIG_SENSORS_LM78 is not set -# CONFIG_SENSORS_LM80 is not set -# CONFIG_SENSORS_LM83 is not set -# CONFIG_SENSORS_LM85 is not set -# CONFIG_SENSORS_LM87 is not set -# CONFIG_SENSORS_LM90 is not set -# CONFIG_SENSORS_LM92 is not set -# CONFIG_SENSORS_LM93 is not set -# CONFIG_SENSORS_MAX1111 is not set -# CONFIG_SENSORS_MAX1619 is not set -# CONFIG_SENSORS_MAX6650 is not set -# CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_PC87427 is not set -# CONFIG_SENSORS_DME1737 is not set -# CONFIG_SENSORS_SMSC47M1 is not set -# CONFIG_SENSORS_SMSC47M192 is not set -# CONFIG_SENSORS_SMSC47B397 is not set -# CONFIG_SENSORS_ADS7828 is not set -# CONFIG_SENSORS_THMC50 is not set -# CONFIG_SENSORS_VT1211 is not set -# CONFIG_SENSORS_W83781D is not set -# CONFIG_SENSORS_W83791D is not set -# CONFIG_SENSORS_W83792D is not set -# CONFIG_SENSORS_W83793 is not set -# CONFIG_SENSORS_W83L785TS is not set -# CONFIG_SENSORS_W83L786NG is not set -# CONFIG_SENSORS_W83627HF is not set -# CONFIG_SENSORS_W83627EHF is not set -# CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_HWMON is not set # CONFIG_THERMAL is not set # CONFIG_THERMAL_HWMON is not set CONFIG_WATCHDOG=y @@ -841,6 +795,12 @@ CONFIG_WATCHDOG=y # # CONFIG_SOFT_WATCHDOG is not set CONFIG_BFIN_WDT=y +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set # # Multifunction device drivers @@ -851,6 +811,7 @@ CONFIG_BFIN_WDT=y # CONFIG_MFD_TMIO is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_REGULATOR is not set # # Multimedia devices @@ -909,6 +870,7 @@ CONFIG_ADV7393_1XMEM=y # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set # CONFIG_BACKLIGHT_LCD_SUPPORT is not set # @@ -1018,12 +980,14 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_M41T80 is not set # CONFIG_RTC_DRV_S35390A is not set # CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set # # SPI RTC drivers # # CONFIG_RTC_DRV_M41T94 is not set # CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set # CONFIG_RTC_DRV_MAX6902 is not set # CONFIG_RTC_DRV_R9701 is not set # CONFIG_RTC_DRV_RS5C348 is not set @@ -1244,6 +1208,13 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set + +# +# Tracers +# +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set # CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y @@ -1282,6 +1253,7 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_FIPS is not set # CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_CRYPTD is not set diff --git a/arch/blackfin/configs/BF537-STAMP_defconfig b/arch/blackfin/configs/BF537-STAMP_defconfig index 9e62b9f40eb..591f6edda4f 100644 --- a/arch/blackfin/configs/BF537-STAMP_defconfig +++ b/arch/blackfin/configs/BF537-STAMP_defconfig @@ -1,7 +1,6 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.28-rc2 -# Tue Dec 30 17:24:37 2008 +# Linux kernel version: 2.6.28.7 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -37,14 +36,13 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set # CONFIG_GROUP_SCHED is not set -# CONFIG_SYSFS_DEPRECATED is not set # CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y +# CONFIG_SYSCTL is not set CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y @@ -57,13 +55,13 @@ CONFIG_BUG=y # CONFIG_ELF_CORE is not set CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y -CONFIG_FUTEX=y +# CONFIG_FUTEX is not set CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y CONFIG_TIMERFD=y CONFIG_EVENTFD=y -CONFIG_AIO=y +# CONFIG_AIO is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -134,10 +132,15 @@ CONFIG_BF537=y # CONFIG_BF538 is not set # CONFIG_BF539 is not set # CONFIG_BF542 is not set +# CONFIG_BF542M is not set # CONFIG_BF544 is not set +# CONFIG_BF544M is not set # CONFIG_BF547 is not set +# CONFIG_BF547M is not set # CONFIG_BF548 is not set +# CONFIG_BF548M is not set # CONFIG_BF549 is not set +# CONFIG_BF549M is not set # CONFIG_BF561 is not set CONFIG_BF_REV_MIN=2 CONFIG_BF_REV_MAX=3 @@ -184,7 +187,6 @@ CONFIG_BFIN537_STAMP=y # CONFIG_BFIN537_BLUETECHNIX_TCM is not set # CONFIG_PNAV10 is not set # CONFIG_CAMSIG_MINOTAUR is not set -# CONFIG_GENERIC_BF537_BOARD is not set # # BF537 Specific Configuration @@ -589,7 +591,9 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set +# CONFIG_ICS932S401 is not set # CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -644,6 +648,7 @@ CONFIG_BFIN_RX_DESC_NUM=20 # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set CONFIG_NETDEV_1000=y # CONFIG_AX88180 is not set CONFIG_NETDEV_10000=y @@ -706,10 +711,10 @@ CONFIG_SERIO_LIBPS2=y # CONFIG_SPI_ADC_BF533 is not set # CONFIG_BF5xx_PPIFCD is not set # CONFIG_BFIN_SIMPLE_TIMER is not set -# CONFIG_BF5xx_PPI is not set +CONFIG_BF5xx_PPI=m CONFIG_BFIN_SPORT=m # CONFIG_BFIN_TIMER_LATENCY is not set -CONFIG_TWI_LCD=m +# CONFIG_TWI_LCD is not set CONFIG_BFIN_DMA_INTERFACE=m CONFIG_SIMPLE_GPIO=m # CONFIG_VT is not set @@ -808,6 +813,7 @@ CONFIG_SPI_MASTER=y # CONFIG_SPI_BFIN=y # CONFIG_SPI_BFIN_LOCK is not set +# CONFIG_SPI_BFIN_SPORT is not set # CONFIG_SPI_BITBANG is not set # @@ -820,60 +826,7 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y # CONFIG_GPIOLIB is not set # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set -CONFIG_HWMON=y -# CONFIG_HWMON_VID is not set -# CONFIG_SENSORS_AD7414 is not set -# CONFIG_SENSORS_AD7418 is not set -# CONFIG_SENSORS_ADCXX is not set -# CONFIG_SENSORS_ADM1021 is not set -# CONFIG_SENSORS_ADM1025 is not set -# CONFIG_SENSORS_ADM1026 is not set -# CONFIG_SENSORS_ADM1029 is not set -# CONFIG_SENSORS_ADM1031 is not set -# CONFIG_SENSORS_ADM9240 is not set -# CONFIG_SENSORS_ADT7470 is not set -# CONFIG_SENSORS_ADT7473 is not set -# CONFIG_SENSORS_ATXP1 is not set -# CONFIG_SENSORS_DS1621 is not set -# CONFIG_SENSORS_F71805F is not set -# CONFIG_SENSORS_F71882FG is not set -# CONFIG_SENSORS_F75375S is not set -# CONFIG_SENSORS_GL518SM is not set -# CONFIG_SENSORS_GL520SM is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_LM63 is not set -# CONFIG_SENSORS_LM70 is not set -# CONFIG_SENSORS_LM75 is not set -# CONFIG_SENSORS_LM77 is not set -# CONFIG_SENSORS_LM78 is not set -# CONFIG_SENSORS_LM80 is not set -# CONFIG_SENSORS_LM83 is not set -# CONFIG_SENSORS_LM85 is not set -# CONFIG_SENSORS_LM87 is not set -# CONFIG_SENSORS_LM90 is not set -# CONFIG_SENSORS_LM92 is not set -# CONFIG_SENSORS_LM93 is not set -# CONFIG_SENSORS_MAX1111 is not set -# CONFIG_SENSORS_MAX1619 is not set -# CONFIG_SENSORS_MAX6650 is not set -# CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_PC87427 is not set -# CONFIG_SENSORS_DME1737 is not set -# CONFIG_SENSORS_SMSC47M1 is not set -# CONFIG_SENSORS_SMSC47M192 is not set -# CONFIG_SENSORS_SMSC47B397 is not set -# CONFIG_SENSORS_ADS7828 is not set -# CONFIG_SENSORS_THMC50 is not set -# CONFIG_SENSORS_VT1211 is not set -# CONFIG_SENSORS_W83781D is not set -# CONFIG_SENSORS_W83791D is not set -# CONFIG_SENSORS_W83792D is not set -# CONFIG_SENSORS_W83793 is not set -# CONFIG_SENSORS_W83L785TS is not set -# CONFIG_SENSORS_W83L786NG is not set -# CONFIG_SENSORS_W83627HF is not set -# CONFIG_SENSORS_W83627EHF is not set -# CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_HWMON is not set # CONFIG_THERMAL is not set # CONFIG_THERMAL_HWMON is not set CONFIG_WATCHDOG=y @@ -884,6 +837,12 @@ CONFIG_WATCHDOG=y # # CONFIG_SOFT_WATCHDOG is not set CONFIG_BFIN_WDT=y +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set # # Multifunction device drivers @@ -894,6 +853,7 @@ CONFIG_BFIN_WDT=y # CONFIG_MFD_TMIO is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_REGULATOR is not set # # Multimedia devices @@ -957,6 +917,7 @@ CONFIG_ADV7393_1XMEM=y # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_LCD_CLASS_DEVICE=m # CONFIG_LCD_LTV350QV is not set @@ -1074,12 +1035,14 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_M41T80 is not set # CONFIG_RTC_DRV_S35390A is not set # CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set # # SPI RTC drivers # # CONFIG_RTC_DRV_M41T94 is not set # CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set # CONFIG_RTC_DRV_MAX6902 is not set # CONFIG_RTC_DRV_R9701 is not set # CONFIG_RTC_DRV_RS5C348 is not set @@ -1300,6 +1263,13 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set + +# +# Tracers +# +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set # CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y @@ -1338,6 +1308,7 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_FIPS is not set # CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_CRYPTD is not set diff --git a/arch/blackfin/configs/BF538-EZKIT_defconfig b/arch/blackfin/configs/BF538-EZKIT_defconfig index dd6ad6be1c8..1a8e8c3adf9 100644 --- a/arch/blackfin/configs/BF538-EZKIT_defconfig +++ b/arch/blackfin/configs/BF538-EZKIT_defconfig @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.28-rc2 +# Linux kernel version: 2.6.28.7 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -42,7 +42,7 @@ CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y +# CONFIG_SYSCTL is not set CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y @@ -55,13 +55,13 @@ CONFIG_BUG=y # CONFIG_ELF_CORE is not set CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y -CONFIG_FUTEX=y +# CONFIG_FUTEX is not set CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y CONFIG_TIMERFD=y CONFIG_EVENTFD=y -CONFIG_AIO=y +# CONFIG_AIO is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -132,10 +132,15 @@ CONFIG_PREEMPT_VOLUNTARY=y CONFIG_BF538=y # CONFIG_BF539 is not set # CONFIG_BF542 is not set +# CONFIG_BF542M is not set # CONFIG_BF544 is not set +# CONFIG_BF544M is not set # CONFIG_BF547 is not set +# CONFIG_BF547M is not set # CONFIG_BF548 is not set +# CONFIG_BF548M is not set # CONFIG_BF549 is not set +# CONFIG_BF549M is not set # CONFIG_BF561 is not set CONFIG_BF_REV_MIN=4 CONFIG_BF_REV_MAX=5 @@ -293,7 +298,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_VIRT_TO_BUS=y -CONFIG_BFIN_GPTIMERS=y +CONFIG_BFIN_GPTIMERS=m # CONFIG_DMA_UNCACHED_4M is not set # CONFIG_DMA_UNCACHED_2M is not set CONFIG_DMA_UNCACHED_1M=y @@ -354,7 +359,6 @@ CONFIG_BINFMT_ZFLAT=y # # CONFIG_PM is not set CONFIG_ARCH_SUSPEND_POSSIBLE=y -# CONFIG_PM_WAKEUP_BY_GPIO is not set # # CPU Frequency scaling @@ -645,6 +649,7 @@ CONFIG_SMC91X=y # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set @@ -690,7 +695,7 @@ CONFIG_INPUT_TOUCHSCREEN=y # CONFIG_TOUCHSCREEN_AD7877 is not set # CONFIG_TOUCHSCREEN_AD7879_I2C is not set CONFIG_TOUCHSCREEN_AD7879_SPI=y -CONFIG_TOUCHSCREEN_AD7879=m +CONFIG_TOUCHSCREEN_AD7879=y # CONFIG_TOUCHSCREEN_FUJITSU is not set # CONFIG_TOUCHSCREEN_GUNZE is not set # CONFIG_TOUCHSCREEN_ELO is not set @@ -718,8 +723,8 @@ CONFIG_INPUT_MISC=y # CONFIG_SPI_ADC_BF533 is not set # CONFIG_BF5xx_PPIFCD is not set # CONFIG_BFIN_SIMPLE_TIMER is not set -# CONFIG_BF5xx_PPI is not set -CONFIG_BFIN_SPORT=y +CONFIG_BF5xx_PPI=m +CONFIG_BFIN_SPORT=m # CONFIG_BFIN_TIMER_LATENCY is not set # CONFIG_TWI_LCD is not set CONFIG_BFIN_DMA_INTERFACE=m @@ -762,7 +767,7 @@ CONFIG_UNIX98_PTYS=y # CONFIG_R3964 is not set # CONFIG_RAW_DRIVER is not set # CONFIG_TCG_TPM is not set -CONFIG_I2C=y +CONFIG_I2C=m CONFIG_I2C_BOARDINFO=y # CONFIG_I2C_CHARDEV is not set CONFIG_I2C_HELPER_AUTO=y @@ -774,7 +779,7 @@ CONFIG_I2C_HELPER_AUTO=y # # I2C system bus drivers (mostly embedded / system-on-chip) # -CONFIG_I2C_BLACKFIN_TWI=y +CONFIG_I2C_BLACKFIN_TWI=m CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100 # CONFIG_I2C_GPIO is not set # CONFIG_I2C_OCORES is not set @@ -818,6 +823,7 @@ CONFIG_SPI_MASTER=y # CONFIG_SPI_BFIN=y # CONFIG_SPI_BFIN_LOCK is not set +# CONFIG_SPI_BFIN_SPORT is not set # CONFIG_SPI_BITBANG is not set # @@ -830,60 +836,7 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y # CONFIG_GPIOLIB is not set # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set -CONFIG_HWMON=y -# CONFIG_HWMON_VID is not set -# CONFIG_SENSORS_AD7414 is not set -# CONFIG_SENSORS_AD7418 is not set -# CONFIG_SENSORS_ADCXX is not set -# CONFIG_SENSORS_ADM1021 is not set -# CONFIG_SENSORS_ADM1025 is not set -# CONFIG_SENSORS_ADM1026 is not set -# CONFIG_SENSORS_ADM1029 is not set -# CONFIG_SENSORS_ADM1031 is not set -# CONFIG_SENSORS_ADM9240 is not set -# CONFIG_SENSORS_ADT7470 is not set -# CONFIG_SENSORS_ADT7473 is not set -# CONFIG_SENSORS_ATXP1 is not set -# CONFIG_SENSORS_DS1621 is not set -# CONFIG_SENSORS_F71805F is not set -# CONFIG_SENSORS_F71882FG is not set -# CONFIG_SENSORS_F75375S is not set -# CONFIG_SENSORS_GL518SM is not set -# CONFIG_SENSORS_GL520SM is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_LM63 is not set -# CONFIG_SENSORS_LM70 is not set -# CONFIG_SENSORS_LM75 is not set -# CONFIG_SENSORS_LM77 is not set -# CONFIG_SENSORS_LM78 is not set -# CONFIG_SENSORS_LM80 is not set -# CONFIG_SENSORS_LM83 is not set -# CONFIG_SENSORS_LM85 is not set -# CONFIG_SENSORS_LM87 is not set -# CONFIG_SENSORS_LM90 is not set -# CONFIG_SENSORS_LM92 is not set -# CONFIG_SENSORS_LM93 is not set -# CONFIG_SENSORS_MAX1111 is not set -# CONFIG_SENSORS_MAX1619 is not set -# CONFIG_SENSORS_MAX6650 is not set -# CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_PC87427 is not set -# CONFIG_SENSORS_DME1737 is not set -# CONFIG_SENSORS_SMSC47M1 is not set -# CONFIG_SENSORS_SMSC47M192 is not set -# CONFIG_SENSORS_SMSC47B397 is not set -# CONFIG_SENSORS_ADS7828 is not set -# CONFIG_SENSORS_THMC50 is not set -# CONFIG_SENSORS_VT1211 is not set -# CONFIG_SENSORS_W83781D is not set -# CONFIG_SENSORS_W83791D is not set -# CONFIG_SENSORS_W83792D is not set -# CONFIG_SENSORS_W83793 is not set -# CONFIG_SENSORS_W83L785TS is not set -# CONFIG_SENSORS_W83L786NG is not set -# CONFIG_SENSORS_W83627HF is not set -# CONFIG_SENSORS_W83627EHF is not set -# CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_HWMON is not set # CONFIG_THERMAL is not set # CONFIG_THERMAL_HWMON is not set CONFIG_WATCHDOG=y @@ -894,6 +847,12 @@ CONFIG_WATCHDOG=y # # CONFIG_SOFT_WATCHDOG is not set CONFIG_BFIN_WDT=y +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set # # Multifunction device drivers @@ -904,6 +863,7 @@ CONFIG_BFIN_WDT=y # CONFIG_MFD_TMIO is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_REGULATOR is not set # # Multimedia devices @@ -954,6 +914,7 @@ CONFIG_FB_BFIN_LQ035Q1=m # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set # CONFIG_BACKLIGHT_LCD_SUPPORT is not set # @@ -1007,12 +968,14 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_M41T80 is not set # CONFIG_RTC_DRV_S35390A is not set # CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set # # SPI RTC drivers # # CONFIG_RTC_DRV_M41T94 is not set # CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set # CONFIG_RTC_DRV_MAX6902 is not set # CONFIG_RTC_DRV_R9701 is not set # CONFIG_RTC_DRV_RS5C348 is not set @@ -1233,6 +1196,13 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_FAULT_INJECTION is not set CONFIG_SYSCTL_SYSCALL_CHECK=y + +# +# Tracers +# +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set # CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y @@ -1271,6 +1241,7 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_FIPS is not set # CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_CRYPTD is not set diff --git a/arch/blackfin/configs/BF548-EZKIT_defconfig b/arch/blackfin/configs/BF548-EZKIT_defconfig index 6bc2fb1b2a7..2cd1c2b218d 100644 --- a/arch/blackfin/configs/BF548-EZKIT_defconfig +++ b/arch/blackfin/configs/BF548-EZKIT_defconfig @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.28-rc2 +# Linux kernel version: 2.6.28.7 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -36,14 +36,13 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set # CONFIG_GROUP_SCHED is not set -# CONFIG_SYSFS_DEPRECATED is not set # CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y +# CONFIG_SYSCTL is not set CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y @@ -56,13 +55,13 @@ CONFIG_BUG=y # CONFIG_ELF_CORE is not set CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y -CONFIG_FUTEX=y +# CONFIG_FUTEX is not set CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y CONFIG_TIMERFD=y CONFIG_EVENTFD=y -CONFIG_AIO=y +# CONFIG_AIO is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -133,16 +132,21 @@ CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_BF538 is not set # CONFIG_BF539 is not set # CONFIG_BF542 is not set +# CONFIG_BF542M is not set # CONFIG_BF544 is not set +# CONFIG_BF544M is not set # CONFIG_BF547 is not set +# CONFIG_BF547M is not set CONFIG_BF548=y +# CONFIG_BF548M is not set # CONFIG_BF549 is not set +# CONFIG_BF549M is not set # CONFIG_BF561 is not set CONFIG_BF_REV_MIN=0 CONFIG_BF_REV_MAX=2 -CONFIG_BF_REV_0_0=y +# CONFIG_BF_REV_0_0 is not set # CONFIG_BF_REV_0_1 is not set -# CONFIG_BF_REV_0_2 is not set +CONFIG_BF_REV_0_2=y # CONFIG_BF_REV_0_3 is not set # CONFIG_BF_REV_0_4 is not set # CONFIG_BF_REV_0_5 is not set @@ -348,7 +352,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_VIRT_TO_BUS=y -# CONFIG_BFIN_GPTIMERS is not set +CONFIG_BFIN_GPTIMERS=m # CONFIG_DMA_UNCACHED_4M is not set CONFIG_DMA_UNCACHED_2M=y # CONFIG_DMA_UNCACHED_1M is not set @@ -413,7 +417,6 @@ CONFIG_BINFMT_ZFLAT=y # # CONFIG_PM is not set CONFIG_ARCH_SUSPEND_POSSIBLE=y -# CONFIG_PM_WAKEUP_BY_GPIO is not set # # CPU Frequency scaling @@ -512,9 +515,9 @@ CONFIG_IRCOMM=m # CONFIG_IRTTY_SIR=m CONFIG_BFIN_SIR=m -CONFIG_BFIN_SIR3=y # CONFIG_BFIN_SIR0 is not set # CONFIG_BFIN_SIR2 is not set +CONFIG_BFIN_SIR3=y CONFIG_SIR_BFIN_DMA=y # CONFIG_SIR_BFIN_PIO is not set @@ -538,7 +541,8 @@ CONFIG_SIR_BFIN_DMA=y CONFIG_WIRELESS=y # CONFIG_CFG80211 is not set CONFIG_WIRELESS_OLD_REGULATORY=y -# CONFIG_WIRELESS_EXT is not set +CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y # CONFIG_MAC80211 is not set # CONFIG_IEEE80211 is not set # CONFIG_RFKILL is not set @@ -554,7 +558,9 @@ CONFIG_WIRELESS_OLD_REGULATORY=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set +CONFIG_FW_LOADER=m +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set @@ -668,7 +674,9 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set +# CONFIG_ICS932S401 is not set # CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -743,6 +751,7 @@ CONFIG_SMSC911X=y # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set CONFIG_NETDEV_1000=y # CONFIG_AX88180 is not set CONFIG_NETDEV_10000=y @@ -751,8 +760,16 @@ CONFIG_NETDEV_10000=y # Wireless LAN # # CONFIG_WLAN_PRE80211 is not set -# CONFIG_WLAN_80211 is not set +CONFIG_WLAN_80211=y +CONFIG_LIBERTAS=m +# CONFIG_LIBERTAS_USB is not set +CONFIG_LIBERTAS_SDIO=m +CONFIG_POWEROF2_BLOCKSIZE_ONLY=y +# CONFIG_LIBERTAS_DEBUG is not set +# CONFIG_USB_ZD1201 is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set # CONFIG_IWLWIFI_LEDS is not set +# CONFIG_HOSTAP is not set # # USB Network Adapters @@ -844,8 +861,8 @@ CONFIG_INPUT_MISC=y # CONFIG_SPI_ADC_BF533 is not set # CONFIG_BF5xx_PPIFCD is not set # CONFIG_BFIN_SIMPLE_TIMER is not set -# CONFIG_BF5xx_PPI is not set -# CONFIG_BFIN_SPORT is not set +CONFIG_BF5xx_PPI=m +CONFIG_BFIN_SPORT=m # CONFIG_BFIN_TIMER_LATENCY is not set # CONFIG_TWI_LCD is not set CONFIG_BFIN_DMA_INTERFACE=m @@ -950,6 +967,7 @@ CONFIG_SPI_MASTER=y # CONFIG_SPI_BFIN=y # CONFIG_SPI_BFIN_LOCK is not set +# CONFIG_SPI_BFIN_SPORT is not set # CONFIG_SPI_BITBANG is not set # @@ -962,60 +980,7 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y # CONFIG_GPIOLIB is not set # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set -CONFIG_HWMON=y -# CONFIG_HWMON_VID is not set -# CONFIG_SENSORS_AD7414 is not set -# CONFIG_SENSORS_AD7418 is not set -# CONFIG_SENSORS_ADCXX is not set -# CONFIG_SENSORS_ADM1021 is not set -# CONFIG_SENSORS_ADM1025 is not set -# CONFIG_SENSORS_ADM1026 is not set -# CONFIG_SENSORS_ADM1029 is not set -# CONFIG_SENSORS_ADM1031 is not set -# CONFIG_SENSORS_ADM9240 is not set -# CONFIG_SENSORS_ADT7470 is not set -# CONFIG_SENSORS_ADT7473 is not set -# CONFIG_SENSORS_ATXP1 is not set -# CONFIG_SENSORS_DS1621 is not set -# CONFIG_SENSORS_F71805F is not set -# CONFIG_SENSORS_F71882FG is not set -# CONFIG_SENSORS_F75375S is not set -# CONFIG_SENSORS_GL518SM is not set -# CONFIG_SENSORS_GL520SM is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_LM63 is not set -# CONFIG_SENSORS_LM70 is not set -# CONFIG_SENSORS_LM75 is not set -# CONFIG_SENSORS_LM77 is not set -# CONFIG_SENSORS_LM78 is not set -# CONFIG_SENSORS_LM80 is not set -# CONFIG_SENSORS_LM83 is not set -# CONFIG_SENSORS_LM85 is not set -# CONFIG_SENSORS_LM87 is not set -# CONFIG_SENSORS_LM90 is not set -# CONFIG_SENSORS_LM92 is not set -# CONFIG_SENSORS_LM93 is not set -# CONFIG_SENSORS_MAX1111 is not set -# CONFIG_SENSORS_MAX1619 is not set -# CONFIG_SENSORS_MAX6650 is not set -# CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_PC87427 is not set -# CONFIG_SENSORS_DME1737 is not set -# CONFIG_SENSORS_SMSC47M1 is not set -# CONFIG_SENSORS_SMSC47M192 is not set -# CONFIG_SENSORS_SMSC47B397 is not set -# CONFIG_SENSORS_ADS7828 is not set -# CONFIG_SENSORS_THMC50 is not set -# CONFIG_SENSORS_VT1211 is not set -# CONFIG_SENSORS_W83781D is not set -# CONFIG_SENSORS_W83791D is not set -# CONFIG_SENSORS_W83792D is not set -# CONFIG_SENSORS_W83793 is not set -# CONFIG_SENSORS_W83L785TS is not set -# CONFIG_SENSORS_W83L786NG is not set -# CONFIG_SENSORS_W83627HF is not set -# CONFIG_SENSORS_W83627EHF is not set -# CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_HWMON is not set # CONFIG_THERMAL is not set # CONFIG_THERMAL_HWMON is not set CONFIG_WATCHDOG=y @@ -1031,6 +996,12 @@ CONFIG_BFIN_WDT=y # USB-based Watchdog Cards # # CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set # # Multifunction device drivers @@ -1039,8 +1010,10 @@ CONFIG_BFIN_WDT=y # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_MFD_TMIO is not set +# CONFIG_PMIC_DA903X is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_REGULATOR is not set # # Multimedia devices @@ -1092,6 +1065,7 @@ CONFIG_FB_BF54X_LQ043=y # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set # CONFIG_BACKLIGHT_LCD_SUPPORT is not set # @@ -1243,15 +1217,15 @@ CONFIG_USB_MUSB_HDRC=y CONFIG_USB_MUSB_SOC=y # -# Blackfin high speed USB support +# Blackfin high speed USB Support # CONFIG_USB_MUSB_HOST=y # CONFIG_USB_MUSB_PERIPHERAL is not set # CONFIG_USB_MUSB_OTG is not set +# CONFIG_USB_GADGET_MUSB_HDRC is not set CONFIG_USB_MUSB_HDRC_HCD=y -# CONFIG_MUSB_PIO_ONLY is not set -CONFIG_USB_INVENTRA_DMA=y -# CONFIG_USB_TI_CPPI_DMA is not set +CONFIG_MUSB_PIO_ONLY=y +CONFIG_MUSB_DMA_POLL=y # CONFIG_USB_MUSB_DEBUG is not set # @@ -1263,11 +1237,11 @@ CONFIG_USB_INVENTRA_DMA=y # CONFIG_USB_TMC is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; # # -# may also be needed; see USB_STORAGE Help for more information +# see USB_STORAGE Help for more information # CONFIG_USB_STORAGE=m # CONFIG_USB_STORAGE_DEBUG is not set @@ -1321,7 +1295,31 @@ CONFIG_USB_STORAGE=m # CONFIG_USB_ISIGHTFW is not set # CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set -CONFIG_MMC=m +# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_PXA27X is not set +# CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_FSL_QE is not set +# CONFIG_USB_GADGET_NET2272 is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_ZERO is not set +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_UNSAFE_RESUME is not set @@ -1337,8 +1335,9 @@ CONFIG_MMC_BLOCK_BOUNCE=y # MMC/SD/SDIO Host Controller Drivers # # CONFIG_MMC_SDHCI is not set -CONFIG_SDH_BFIN=m +CONFIG_SDH_BFIN=y # CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND is not set +# CONFIG_SDH_BFIN_ENABLE_SDIO_IRQ is not set # CONFIG_MMC_SPI is not set # CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set @@ -1373,12 +1372,14 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_M41T80 is not set # CONFIG_RTC_DRV_S35390A is not set # CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set # # SPI RTC drivers # # CONFIG_RTC_DRV_M41T94 is not set # CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set # CONFIG_RTC_DRV_MAX6902 is not set # CONFIG_RTC_DRV_R9701 is not set # CONFIG_RTC_DRV_RS5C348 is not set @@ -1641,6 +1642,13 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set + +# +# Tracers +# +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set # CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y @@ -1680,6 +1688,7 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_FIPS is not set # CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_CRYPTD is not set diff --git a/arch/blackfin/configs/BF561-EZKIT_defconfig b/arch/blackfin/configs/BF561-EZKIT_defconfig index 69714fb3e60..4a6ea8e31df 100644 --- a/arch/blackfin/configs/BF561-EZKIT_defconfig +++ b/arch/blackfin/configs/BF561-EZKIT_defconfig @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.28-rc2 +# Linux kernel version: 2.6.28.7 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -36,14 +36,13 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set # CONFIG_GROUP_SCHED is not set -# CONFIG_SYSFS_DEPRECATED is not set # CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y +# CONFIG_SYSCTL is not set CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y @@ -56,13 +55,13 @@ CONFIG_BUG=y # CONFIG_ELF_CORE is not set CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y -CONFIG_FUTEX=y +# CONFIG_FUTEX is not set CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y CONFIG_TIMERFD=y CONFIG_EVENTFD=y -CONFIG_AIO=y +# CONFIG_AIO is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -133,10 +132,15 @@ CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_BF538 is not set # CONFIG_BF539 is not set # CONFIG_BF542 is not set +# CONFIG_BF542M is not set # CONFIG_BF544 is not set +# CONFIG_BF544M is not set # CONFIG_BF547 is not set +# CONFIG_BF547M is not set # CONFIG_BF548 is not set +# CONFIG_BF548M is not set # CONFIG_BF549 is not set +# CONFIG_BF549M is not set CONFIG_BF561=y # CONFIG_SMP is not set CONFIG_BF_REV_MIN=3 @@ -166,7 +170,6 @@ CONFIG_IRQ_SPI_ERROR=7 CONFIG_BFIN561_EZKIT=y # CONFIG_BFIN561_TEPLA is not set # CONFIG_BFIN561_BLUETECHNIX_CM is not set -# CONFIG_GENERIC_BF561_BOARD is not set # # BF561 Specific Configuration @@ -316,7 +319,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_VIRT_TO_BUS=y -# CONFIG_BFIN_GPTIMERS is not set +CONFIG_BFIN_GPTIMERS=m # CONFIG_DMA_UNCACHED_4M is not set # CONFIG_DMA_UNCACHED_2M is not set CONFIG_DMA_UNCACHED_1M=y @@ -382,7 +385,6 @@ CONFIG_BINFMT_ZFLAT=y # # CONFIG_PM is not set CONFIG_ARCH_SUSPEND_POSSIBLE=y -# CONFIG_PM_WAKEUP_BY_GPIO is not set # # CPU Frequency scaling @@ -612,6 +614,7 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set # CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -645,6 +648,7 @@ CONFIG_SMC91X=y # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set CONFIG_NETDEV_1000=y # CONFIG_AX88180 is not set CONFIG_NETDEV_10000=y @@ -751,6 +755,7 @@ CONFIG_SPI_MASTER=y # CONFIG_SPI_BFIN=y # CONFIG_SPI_BFIN_LOCK is not set +# CONFIG_SPI_BFIN_SPORT is not set # CONFIG_SPI_BITBANG is not set # @@ -763,22 +768,7 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y # CONFIG_GPIOLIB is not set # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set -CONFIG_HWMON=y -# CONFIG_HWMON_VID is not set -# CONFIG_SENSORS_ADCXX is not set -# CONFIG_SENSORS_F71805F is not set -# CONFIG_SENSORS_F71882FG is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_LM70 is not set -# CONFIG_SENSORS_MAX1111 is not set -# CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_PC87427 is not set -# CONFIG_SENSORS_SMSC47M1 is not set -# CONFIG_SENSORS_SMSC47B397 is not set -# CONFIG_SENSORS_VT1211 is not set -# CONFIG_SENSORS_W83627HF is not set -# CONFIG_SENSORS_W83627EHF is not set -# CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_HWMON is not set # CONFIG_THERMAL is not set # CONFIG_THERMAL_HWMON is not set CONFIG_WATCHDOG=y @@ -789,6 +779,12 @@ CONFIG_WATCHDOG=y # # CONFIG_SOFT_WATCHDOG is not set CONFIG_BFIN_WDT=y +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set # # Multifunction device drivers @@ -797,7 +793,7 @@ CONFIG_BFIN_WDT=y # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_MFD_TMIO is not set -# CONFIG_MFD_WM8400 is not set +# CONFIG_REGULATOR is not set # # Multimedia devices @@ -1041,6 +1037,13 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set + +# +# Tracers +# +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set # CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y @@ -1079,6 +1082,7 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_FIPS is not set # CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_CRYPTD is not set diff --git a/arch/blackfin/configs/BlackStamp_defconfig b/arch/blackfin/configs/BlackStamp_defconfig index 017c6ea071b..ef1a2c84ace 100644 --- a/arch/blackfin/configs/BlackStamp_defconfig +++ b/arch/blackfin/configs/BlackStamp_defconfig @@ -43,7 +43,7 @@ CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y +# CONFIG_SYSCTL is not set CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y @@ -56,7 +56,7 @@ CONFIG_BUG=y # CONFIG_ELF_CORE is not set CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y -CONFIG_FUTEX=y +# CONFIG_FUTEX is not set CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y diff --git a/arch/blackfin/configs/CM-BF527_defconfig b/arch/blackfin/configs/CM-BF527_defconfig index d880ef78677..e2fc588e433 100644 --- a/arch/blackfin/configs/CM-BF527_defconfig +++ b/arch/blackfin/configs/CM-BF527_defconfig @@ -43,7 +43,7 @@ CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y +# CONFIG_SYSCTL is not set CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y @@ -56,13 +56,13 @@ CONFIG_BUG=y # CONFIG_ELF_CORE is not set CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y -CONFIG_FUTEX=y +# CONFIG_FUTEX is not set CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y CONFIG_TIMERFD=y CONFIG_EVENTFD=y -CONFIG_AIO=y +# CONFIG_AIO is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y # CONFIG_SLUB is not set diff --git a/arch/blackfin/configs/CM-BF533_defconfig b/arch/blackfin/configs/CM-BF533_defconfig index 085211b9e4e..65a8bbb8d64 100644 --- a/arch/blackfin/configs/CM-BF533_defconfig +++ b/arch/blackfin/configs/CM-BF533_defconfig @@ -46,7 +46,7 @@ CONFIG_LOG_BUF_SHIFT=14 # CONFIG_RELAY is not set # CONFIG_BLK_DEV_INITRD is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y +# CONFIG_SYSCTL is not set CONFIG_EMBEDDED=y # CONFIG_UID16 is not set CONFIG_SYSCTL_SYSCALL=y @@ -57,7 +57,7 @@ CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_ELF_CORE is not set CONFIG_BASE_FULL=y -CONFIG_FUTEX=y +# CONFIG_FUTEX is not set CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y diff --git a/arch/blackfin/configs/CM-BF537E_defconfig b/arch/blackfin/configs/CM-BF537E_defconfig index 750203e27a4..9b7e9d78114 100644 --- a/arch/blackfin/configs/CM-BF537E_defconfig +++ b/arch/blackfin/configs/CM-BF537E_defconfig @@ -46,7 +46,7 @@ CONFIG_LOG_BUF_SHIFT=14 # CONFIG_RELAY is not set # CONFIG_BLK_DEV_INITRD is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y +# CONFIG_SYSCTL is not set CONFIG_EMBEDDED=y # CONFIG_UID16 is not set CONFIG_SYSCTL_SYSCALL=y @@ -57,7 +57,7 @@ CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_ELF_CORE is not set CONFIG_BASE_FULL=y -CONFIG_FUTEX=y +# CONFIG_FUTEX is not set CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y diff --git a/arch/blackfin/configs/CM-BF537U_defconfig b/arch/blackfin/configs/CM-BF537U_defconfig index dec8a7d5cc0..569523c1c03 100644 --- a/arch/blackfin/configs/CM-BF537U_defconfig +++ b/arch/blackfin/configs/CM-BF537U_defconfig @@ -46,7 +46,7 @@ CONFIG_LOG_BUF_SHIFT=14 # CONFIG_RELAY is not set # CONFIG_BLK_DEV_INITRD is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y +# CONFIG_SYSCTL is not set CONFIG_EMBEDDED=y # CONFIG_UID16 is not set CONFIG_SYSCTL_SYSCALL=y @@ -57,7 +57,7 @@ CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_ELF_CORE is not set CONFIG_BASE_FULL=y -CONFIG_FUTEX=y +# CONFIG_FUTEX is not set CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y diff --git a/arch/blackfin/configs/CM-BF548_defconfig b/arch/blackfin/configs/CM-BF548_defconfig index f410430b4e3..035b635e599 100644 --- a/arch/blackfin/configs/CM-BF548_defconfig +++ b/arch/blackfin/configs/CM-BF548_defconfig @@ -46,7 +46,7 @@ CONFIG_FAIR_USER_SCHED=y CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y +# CONFIG_SYSCTL is not set CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y @@ -57,7 +57,7 @@ CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_ELF_CORE is not set CONFIG_BASE_FULL=y -CONFIG_FUTEX=y +# CONFIG_FUTEX is not set CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y diff --git a/arch/blackfin/configs/CM-BF561_defconfig b/arch/blackfin/configs/CM-BF561_defconfig index 346bc7af8f4..7015e42ccce 100644 --- a/arch/blackfin/configs/CM-BF561_defconfig +++ b/arch/blackfin/configs/CM-BF561_defconfig @@ -46,7 +46,7 @@ CONFIG_FAIR_USER_SCHED=y # CONFIG_RELAY is not set # CONFIG_BLK_DEV_INITRD is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y +# CONFIG_SYSCTL is not set CONFIG_EMBEDDED=y # CONFIG_UID16 is not set CONFIG_SYSCTL_SYSCALL=y @@ -57,7 +57,7 @@ CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_ELF_CORE is not set CONFIG_BASE_FULL=y -CONFIG_FUTEX=y +# CONFIG_FUTEX is not set CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y diff --git a/arch/blackfin/configs/H8606_defconfig b/arch/blackfin/configs/H8606_defconfig index bd553da15db..dfc8e1ddd77 100644 --- a/arch/blackfin/configs/H8606_defconfig +++ b/arch/blackfin/configs/H8606_defconfig @@ -45,7 +45,7 @@ CONFIG_SYSFS_DEPRECATED=y # CONFIG_RELAY is not set # CONFIG_BLK_DEV_INITRD is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y +# CONFIG_SYSCTL is not set CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y @@ -56,7 +56,7 @@ CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_ELF_CORE is not set CONFIG_BASE_FULL=y -CONFIG_FUTEX=y +# CONFIG_FUTEX is not set CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y diff --git a/arch/blackfin/configs/IP0X_defconfig b/arch/blackfin/configs/IP0X_defconfig index 7db93874c98..95a5f91aeba 100644 --- a/arch/blackfin/configs/IP0X_defconfig +++ b/arch/blackfin/configs/IP0X_defconfig @@ -46,7 +46,7 @@ CONFIG_SYSFS_DEPRECATED=y CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y +# CONFIG_SYSCTL is not set CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y @@ -57,7 +57,7 @@ CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_ELF_CORE is not set CONFIG_BASE_FULL=y -CONFIG_FUTEX=y +# CONFIG_FUTEX is not set CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y diff --git a/arch/blackfin/configs/PNAV-10_defconfig b/arch/blackfin/configs/PNAV-10_defconfig index ad096702ac1..78e24080e7f 100644 --- a/arch/blackfin/configs/PNAV-10_defconfig +++ b/arch/blackfin/configs/PNAV-10_defconfig @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.28-rc2 +# Linux kernel version: 2.6.28.7 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -35,13 +35,12 @@ CONFIG_SYSVIPC_SYSCTL=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set # CONFIG_GROUP_SCHED is not set -# CONFIG_SYSFS_DEPRECATED is not set # CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set # CONFIG_BLK_DEV_INITRD is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y +# CONFIG_SYSCTL is not set CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y @@ -53,13 +52,13 @@ CONFIG_BUG=y # CONFIG_ELF_CORE is not set CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y -CONFIG_FUTEX=y +# CONFIG_FUTEX is not set CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y CONFIG_TIMERFD=y CONFIG_EVENTFD=y -CONFIG_AIO=y +# CONFIG_AIO is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -130,10 +129,15 @@ CONFIG_BF537=y # CONFIG_BF538 is not set # CONFIG_BF539 is not set # CONFIG_BF542 is not set +# CONFIG_BF542M is not set # CONFIG_BF544 is not set +# CONFIG_BF544M is not set # CONFIG_BF547 is not set +# CONFIG_BF547M is not set # CONFIG_BF548 is not set +# CONFIG_BF548M is not set # CONFIG_BF549 is not set +# CONFIG_BF549M is not set # CONFIG_BF561 is not set CONFIG_BF_REV_MIN=2 CONFIG_BF_REV_MAX=3 @@ -180,7 +184,6 @@ CONFIG_IRQ_SPI=10 # CONFIG_BFIN537_BLUETECHNIX_TCM is not set CONFIG_PNAV10=y # CONFIG_CAMSIG_MINOTAUR is not set -# CONFIG_GENERIC_BF537_BOARD is not set # # BF537 Specific Configuration @@ -341,7 +344,6 @@ CONFIG_BINFMT_ZFLAT=y # # CONFIG_PM is not set CONFIG_ARCH_SUSPEND_POSSIBLE=y -# CONFIG_PM_WAKEUP_BY_GPIO is not set # # CPU Frequency scaling @@ -538,7 +540,9 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set +# CONFIG_ICS932S401 is not set # CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -593,6 +597,7 @@ CONFIG_BFIN_MAC_RMII=y # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set CONFIG_NETDEV_1000=y # CONFIG_AX88180 is not set CONFIG_NETDEV_10000=y @@ -776,6 +781,7 @@ CONFIG_SPI_MASTER=y # CONFIG_SPI_BFIN=y # CONFIG_SPI_BFIN_LOCK is not set +# CONFIG_SPI_BFIN_SPORT is not set # CONFIG_SPI_BITBANG is not set # @@ -799,6 +805,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_ADM1029 is not set # CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7462 is not set # CONFIG_SENSORS_ADT7470 is not set # CONFIG_SENSORS_ADT7473 is not set # CONFIG_SENSORS_ATXP1 is not set @@ -845,6 +852,12 @@ CONFIG_HWMON=y # CONFIG_THERMAL is not set # CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set # # Multifunction device drivers @@ -853,8 +866,10 @@ CONFIG_HWMON=y # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_MFD_TMIO is not set +# CONFIG_PMIC_DA903X is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_REGULATOR is not set # # Multimedia devices @@ -910,6 +925,7 @@ CONFIG_FB_BFIN_LANDSCAPE=y # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_LCD_CLASS_DEVICE=y # CONFIG_LCD_LTV350QV is not set @@ -966,7 +982,7 @@ CONFIG_USB_ARCH_HAS_HCD=y # # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; # # CONFIG_USB_GADGET is not set # CONFIG_MMC is not set @@ -1003,12 +1019,14 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_M41T80 is not set # CONFIG_RTC_DRV_S35390A is not set # CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set # # SPI RTC drivers # # CONFIG_RTC_DRV_M41T94 is not set # CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set # CONFIG_RTC_DRV_MAX6902 is not set # CONFIG_RTC_DRV_R9701 is not set # CONFIG_RTC_DRV_RS5C348 is not set @@ -1196,6 +1214,10 @@ CONFIG_FRAME_WARN=1024 # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set + +# +# Tracers +# # CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y @@ -1230,6 +1252,7 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_FIPS is not set # CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_CRYPTD is not set diff --git a/arch/blackfin/configs/SRV1_defconfig b/arch/blackfin/configs/SRV1_defconfig index a46529c6ade..2bc0779d22e 100644 --- a/arch/blackfin/configs/SRV1_defconfig +++ b/arch/blackfin/configs/SRV1_defconfig @@ -49,7 +49,7 @@ CONFIG_SYSFS_DEPRECATED=y CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y +# CONFIG_SYSCTL is not set CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y @@ -61,7 +61,7 @@ CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_ELF_CORE is not set CONFIG_BASE_FULL=y -CONFIG_FUTEX=y +# CONFIG_FUTEX is not set CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y diff --git a/arch/blackfin/configs/TCM-BF537_defconfig b/arch/blackfin/configs/TCM-BF537_defconfig index 97a1f1d20dc..e65b3a49214 100644 --- a/arch/blackfin/configs/TCM-BF537_defconfig +++ b/arch/blackfin/configs/TCM-BF537_defconfig @@ -39,7 +39,7 @@ CONFIG_LOG_BUF_SHIFT=14 # CONFIG_NAMESPACES is not set # CONFIG_BLK_DEV_INITRD is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y +# CONFIG_SYSCTL is not set CONFIG_EMBEDDED=y # CONFIG_UID16 is not set CONFIG_SYSCTL_SYSCALL=y @@ -51,13 +51,13 @@ CONFIG_BUG=y # CONFIG_ELF_CORE is not set CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y -CONFIG_FUTEX=y +# CONFIG_FUTEX is not set CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y CONFIG_TIMERFD=y CONFIG_EVENTFD=y -CONFIG_AIO=y +# CONFIG_AIO is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y # CONFIG_SLUB is not set -- GitLab From e1312bfcc25f9301f997bf1ce84355a0f1167847 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Sat, 28 Mar 2009 21:18:45 +0800 Subject: [PATCH 4947/4982] Blackfin arch: add a check to make sure only Blackfin GPIOs may generate IRQs Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/gpio.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/blackfin/include/asm/gpio.h b/arch/blackfin/include/asm/gpio.h index d4a082ef75b..3c99ddc8df1 100644 --- a/arch/blackfin/include/asm/gpio.h +++ b/arch/blackfin/include/asm/gpio.h @@ -303,7 +303,10 @@ static inline void gpio_set_value(unsigned gpio, int value) static inline int gpio_to_irq(unsigned gpio) { - return (gpio + GPIO_IRQ_BASE); + if (likely(gpio < MAX_BLACKFIN_GPIOS)) + return gpio + GPIO_IRQ_BASE; + + return -EINVAL; } static inline int irq_to_gpio(unsigned irq) -- GitLab From ffc89627ae14b46f41836ddabdc9dc77c597eca5 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sat, 28 Mar 2009 20:31:33 +0800 Subject: [PATCH 4948/4982] Blackfin arch: bf51x processors also have 8 timers Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/gptimers.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/blackfin/include/asm/gptimers.h b/arch/blackfin/include/asm/gptimers.h index 0520d2aac8f..a29f649e172 100644 --- a/arch/blackfin/include/asm/gptimers.h +++ b/arch/blackfin/include/asm/gptimers.h @@ -15,9 +15,9 @@ #include /* - * BF537/BF527: 8 timers: + * BF51x/BF52x/BF537: 8 timers: */ -#if defined(BF527_FAMILY) || defined(BF537_FAMILY) +#if defined(CONFIG_BF51x) || defined(BF527_FAMILY) || defined(BF537_FAMILY) # define MAX_BLACKFIN_GPTIMERS 8 # define TIMER0_GROUP_REG TIMER_ENABLE #endif -- GitLab From 269647dc8f3b557d0f9ec59533a5e651cc109efb Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sat, 28 Mar 2009 20:32:57 +0800 Subject: [PATCH 4949/4982] Blackfin arch: convert BF5{18,27,48}_FAMILY to CONFIG_BF{51,52,54}x convert BF5{18,27,48}_FAMILY to CONFIG_BF{51,52,54}x as the defines are redundant in these cases Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/gpio.h | 2 +- arch/blackfin/include/asm/gptimers.h | 4 +- arch/blackfin/kernel/bfin_gpio.c | 54 +++++++++---------- .../mach-bf518/include/mach/blackfin.h | 2 - .../mach-bf527/include/mach/blackfin.h | 2 - .../mach-bf548/include/mach/blackfin.h | 2 - 6 files changed, 30 insertions(+), 36 deletions(-) diff --git a/arch/blackfin/include/asm/gpio.h b/arch/blackfin/include/asm/gpio.h index 3c99ddc8df1..fe139619351 100644 --- a/arch/blackfin/include/asm/gpio.h +++ b/arch/blackfin/include/asm/gpio.h @@ -110,7 +110,7 @@ * MODIFICATION HISTORY : **************************************************************/ -#ifndef BF548_FAMILY +#ifndef CONFIG_BF54x void set_gpio_dir(unsigned, unsigned short); void set_gpio_inen(unsigned, unsigned short); void set_gpio_polar(unsigned, unsigned short); diff --git a/arch/blackfin/include/asm/gptimers.h b/arch/blackfin/include/asm/gptimers.h index a29f649e172..b0f847ae4bf 100644 --- a/arch/blackfin/include/asm/gptimers.h +++ b/arch/blackfin/include/asm/gptimers.h @@ -17,14 +17,14 @@ /* * BF51x/BF52x/BF537: 8 timers: */ -#if defined(CONFIG_BF51x) || defined(BF527_FAMILY) || defined(BF537_FAMILY) +#if defined(CONFIG_BF51x) || defined(CONFIG_BF52x) || defined(BF537_FAMILY) # define MAX_BLACKFIN_GPTIMERS 8 # define TIMER0_GROUP_REG TIMER_ENABLE #endif /* * BF54x: 11 timers (BF542: 8 timers): */ -#if defined(BF548_FAMILY) +#if defined(CONFIG_BF54x) # ifdef CONFIG_BF542 # define MAX_BLACKFIN_GPTIMERS 8 # else diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index 51dac55c524..031ea3e2140 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -69,7 +69,7 @@ enum { static struct gpio_port_t * const gpio_array[] = { #if defined(BF533_FAMILY) || defined(BF538_FAMILY) (struct gpio_port_t *) FIO_FLAG_D, -#elif defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY) +#elif defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) (struct gpio_port_t *) PORTFIO, (struct gpio_port_t *) PORTGIO, (struct gpio_port_t *) PORTHIO, @@ -77,7 +77,7 @@ static struct gpio_port_t * const gpio_array[] = { (struct gpio_port_t *) FIO0_FLAG_D, (struct gpio_port_t *) FIO1_FLAG_D, (struct gpio_port_t *) FIO2_FLAG_D, -#elif defined(BF548_FAMILY) +#elif defined(CONFIG_BF54x) (struct gpio_port_t *)PORTA_FER, (struct gpio_port_t *)PORTB_FER, (struct gpio_port_t *)PORTC_FER, @@ -93,7 +93,7 @@ static struct gpio_port_t * const gpio_array[] = { #endif }; -#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY) +#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) static unsigned short * const port_fer[] = { (unsigned short *) PORTF_FER, (unsigned short *) PORTG_FER, @@ -109,11 +109,11 @@ static unsigned short * const port_mux[] = { static const u8 pmux_offset[][16] = { -# if defined(BF527_FAMILY) +# if defined(CONFIG_BF52x) { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */ { 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */ { 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */ -# elif defined(BF518_FAMILY) +# elif defined(CONFIG_BF51x) { 0, 2, 2, 2, 2, 2, 2, 4, 6, 6, 6, 8, 8, 8, 8, 10 }, /* PORTF */ { 0, 0, 0, 2, 4, 6, 6, 6, 8, 10, 10, 12, 14, 14, 14, 14 }, /* PORTG */ { 0, 0, 0, 0, 2, 2, 4, 6, 10, 10, 10, 10, 10, 10, 10, 10 }, /* PORTH */ @@ -139,7 +139,7 @@ static struct gpio_port_s gpio_bank_saved[GPIO_BANK_NUM]; inline int check_gpio(unsigned gpio) { -#if defined(BF548_FAMILY) +#if defined(CONFIG_BF54x) if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15 || gpio == GPIO_PH14 || gpio == GPIO_PH15 || gpio == GPIO_PJ14 || gpio == GPIO_PJ15) @@ -187,13 +187,13 @@ static void port_setup(unsigned gpio, unsigned short usage) if (check_gpio(gpio)) return; -#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY) +#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) if (usage == GPIO_USAGE) *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio); else *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); SSYNC(); -#elif defined(BF548_FAMILY) +#elif defined(CONFIG_BF54x) if (usage == GPIO_USAGE) gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio); else @@ -273,7 +273,7 @@ static void portmux_setup(unsigned short per) } } } -#elif defined(BF548_FAMILY) +#elif defined(CONFIG_BF54x) inline void portmux_setup(unsigned short per) { u32 pmux; @@ -297,7 +297,7 @@ inline u16 get_portmux(unsigned short per) return (pmux >> (2 * gpio_sub_n(ident)) & 0x3); } -#elif defined(BF527_FAMILY) || defined(BF518_FAMILY) +#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x) inline void portmux_setup(unsigned short per) { u16 pmux, ident = P_IDENT(per), function = P_FUNCT2MUX(per); @@ -322,7 +322,7 @@ static int __init bfin_gpio_init(void) arch_initcall(bfin_gpio_init); -#ifndef BF548_FAMILY +#ifndef CONFIG_BF54x /*********************************************************** * * FUNCTIONS: Blackfin General Purpose Ports Access Functions @@ -489,7 +489,7 @@ static const unsigned int sic_iwr_irqs[] = { IRQ_PROG_INTB, IRQ_PORTG_INTB, IRQ_MAC_TX #elif defined(BF538_FAMILY) IRQ_PORTF_INTB -#elif defined(BF527_FAMILY) || defined(BF518_FAMILY) +#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x) IRQ_PORTF_INTB, IRQ_PORTG_INTB, IRQ_PORTH_INTB #elif defined(BF561_FAMILY) IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB @@ -586,7 +586,7 @@ u32 bfin_pm_standby_setup(void) gpio_array[bank]->maskb = 0; if (mask) { -#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY) +#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) gpio_bank_saved[bank].fer = *port_fer[bank]; #endif gpio_bank_saved[bank].inen = gpio_array[bank]->inen; @@ -631,7 +631,7 @@ void bfin_pm_standby_restore(void) bank = gpio_bank(i); if (mask) { -#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY) +#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) *port_fer[bank] = gpio_bank_saved[bank].fer; #endif gpio_array[bank]->inen = gpio_bank_saved[bank].inen; @@ -657,9 +657,9 @@ void bfin_gpio_pm_hibernate_suspend(void) for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { bank = gpio_bank(i); -#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY) +#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) gpio_bank_saved[bank].fer = *port_fer[bank]; -#if defined(BF527_FAMILY) || defined(BF518_FAMILY) +#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x) gpio_bank_saved[bank].mux = *port_mux[bank]; #else if (bank == 0) @@ -685,8 +685,8 @@ void bfin_gpio_pm_hibernate_restore(void) for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { bank = gpio_bank(i); -#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY) -#if defined(BF527_FAMILY) || defined(BF518_FAMILY) +#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) +#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x) *port_mux[bank] = gpio_bank_saved[bank].mux; #else if (bank == 0) @@ -710,7 +710,7 @@ void bfin_gpio_pm_hibernate_restore(void) #endif -#else /* BF548_FAMILY */ +#else /* CONFIG_BF54x */ #ifdef CONFIG_PM u32 bfin_pm_standby_setup(void) @@ -762,7 +762,7 @@ unsigned short get_gpio_dir(unsigned gpio) } EXPORT_SYMBOL(get_gpio_dir); -#endif /* BF548_FAMILY */ +#endif /* CONFIG_BF54x */ /*********************************************************** * @@ -817,7 +817,7 @@ int peripheral_request(unsigned short per, const char *label) * be requested and used by several drivers */ -#ifdef BF548_FAMILY +#ifdef CONFIG_BF54x if (!((per & P_MAYSHARE) && get_portmux(per) == P_FUNCT2MUX(per))) { #else if (!(per & P_MAYSHARE)) { @@ -964,7 +964,7 @@ int bfin_gpio_request(unsigned gpio, const char *label) printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved as gpio-irq!" " (Documentation/blackfin/bfin-gpio-notes.txt)\n", gpio); } -#ifndef BF548_FAMILY +#ifndef CONFIG_BF54x else { /* Reset POLAR setting when acquiring a gpio for the first time */ set_gpio_polar(gpio, 0); } @@ -1072,7 +1072,7 @@ void bfin_gpio_irq_free(unsigned gpio) static inline void __bfin_gpio_direction_input(unsigned gpio) { -#ifdef BF548_FAMILY +#ifdef CONFIG_BF54x gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio); #else gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio); @@ -1100,13 +1100,13 @@ EXPORT_SYMBOL(bfin_gpio_direction_input); void bfin_gpio_irq_prepare(unsigned gpio) { -#ifdef BF548_FAMILY +#ifdef CONFIG_BF54x unsigned long flags; #endif port_setup(gpio, GPIO_USAGE); -#ifdef BF548_FAMILY +#ifdef CONFIG_BF54x local_irq_save_hw(flags); __bfin_gpio_direction_input(gpio); local_irq_restore_hw(flags); @@ -1135,7 +1135,7 @@ int bfin_gpio_direction_output(unsigned gpio, int value) gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); gpio_set_value(gpio, value); -#ifdef BF548_FAMILY +#ifdef CONFIG_BF54x gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio); #else gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio); @@ -1150,7 +1150,7 @@ EXPORT_SYMBOL(bfin_gpio_direction_output); int bfin_gpio_get_value(unsigned gpio) { -#ifdef BF548_FAMILY +#ifdef CONFIG_BF54x return (1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio))); #else unsigned long flags; diff --git a/arch/blackfin/mach-bf518/include/mach/blackfin.h b/arch/blackfin/mach-bf518/include/mach/blackfin.h index d1a2b9ca622..267bb7c8bfb 100644 --- a/arch/blackfin/mach-bf518/include/mach/blackfin.h +++ b/arch/blackfin/mach-bf518/include/mach/blackfin.h @@ -32,8 +32,6 @@ #ifndef _MACH_BLACKFIN_H_ #define _MACH_BLACKFIN_H_ -#define BF518_FAMILY - #include "bf518.h" #include "mem_map.h" #include "defBF512.h" diff --git a/arch/blackfin/mach-bf527/include/mach/blackfin.h b/arch/blackfin/mach-bf527/include/mach/blackfin.h index 297821e2d79..417abcd61f4 100644 --- a/arch/blackfin/mach-bf527/include/mach/blackfin.h +++ b/arch/blackfin/mach-bf527/include/mach/blackfin.h @@ -32,8 +32,6 @@ #ifndef _MACH_BLACKFIN_H_ #define _MACH_BLACKFIN_H_ -#define BF527_FAMILY - #include "bf527.h" #include "mem_map.h" #include "defBF522.h" diff --git a/arch/blackfin/mach-bf548/include/mach/blackfin.h b/arch/blackfin/mach-bf548/include/mach/blackfin.h index 0c0e3e2c3c2..cf6c1500222 100644 --- a/arch/blackfin/mach-bf548/include/mach/blackfin.h +++ b/arch/blackfin/mach-bf548/include/mach/blackfin.h @@ -32,8 +32,6 @@ #ifndef _MACH_BLACKFIN_H_ #define _MACH_BLACKFIN_H_ -#define BF548_FAMILY - #include "bf548.h" #include "mem_map.h" #include "anomaly.h" -- GitLab From 714e76d71d99f00734217e642ba64204df3bdf35 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sat, 28 Mar 2009 20:38:17 +0800 Subject: [PATCH 4950/4982] Blackfin arch: clean up sports header file Remove redundancy of the name err_irq Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/bfin_sport.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/blackfin/include/asm/bfin_sport.h b/arch/blackfin/include/asm/bfin_sport.h index d4169590e75..b558908e1c7 100644 --- a/arch/blackfin/include/asm/bfin_sport.h +++ b/arch/blackfin/include/asm/bfin_sport.h @@ -126,7 +126,7 @@ struct sport_dev { int tx_len; int tx_sent; - int sport_err_irq; + int err_irq; struct mutex mutex; /* mutual exclusion semaphore */ struct task_struct *task; -- GitLab From 2c8beb2cbef632a3683950aab8bcd9735a0a0270 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Sat, 28 Mar 2009 22:13:43 +0800 Subject: [PATCH 4951/4982] Blackfin arch: enable the platfrom PATA driver with CF Cards Provide option to use the platfrom PATA driver with CF Cards on the CF-IDE-NAND Add-On-Card in Common Memory Mode Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf537/boards/stamp.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index cd04c5e4487..0afe9bd6dbc 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -1120,8 +1120,11 @@ static struct platform_device bfin_sport1_uart_device = { #endif #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE) -#define PATA_INT IRQ_PF5 +#define CF_IDE_NAND_CARD_USE_HDD_INTERFACE +/* #define CF_IDE_NAND_CARD_USE_CF_IN_COMMON_MEMORY_MODE */ +#ifdef CF_IDE_NAND_CARD_USE_HDD_INTERFACE +#define PATA_INT IRQ_PF5 static struct pata_platform_info bfin_pata_platform_data = { .ioport_shift = 1, .irq_flags = IRQF_TRIGGER_HIGH | IRQF_DISABLED, @@ -1144,6 +1147,24 @@ static struct resource bfin_pata_resources[] = { .flags = IORESOURCE_IRQ, }, }; +#elif defined(CF_IDE_NAND_CARD_USE_CF_IN_COMMON_MEMORY_MODE) +static struct pata_platform_info bfin_pata_platform_data = { + .ioport_shift = 0, +}; + +static struct resource bfin_pata_resources[] = { + { + .start = 0x20211820, + .end = 0x2021183F, + .flags = IORESOURCE_MEM, + }, + { + .start = 0x2021181C, + .end = 0x2021181F, + .flags = IORESOURCE_MEM, + }, +}; +#endif static struct platform_device bfin_pata_device = { .name = "pata_platform", -- GitLab From 3ea57218fde5fe6c2ff449d4c30fc69ac6976096 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Sat, 28 Mar 2009 22:15:07 +0800 Subject: [PATCH 4952/4982] Blackfin arch: Privide BF537-STAMP platform data of ADP5520 Multifunction driver ADP5520 Multifunction LCD Backlight and Keypad Input Device Driver Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf537/boards/stamp.c | 142 ++++++++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index 0afe9bd6dbc..f32b7477dcb 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -1073,6 +1073,141 @@ static struct adp5588_kpad_platform_data adp5588_kpad_data = { }; #endif +#if defined(CONFIG_PMIC_ADP5520) || defined(CONFIG_PMIC_ADP5520_MODULE) +#include + + /* + * ADP5520/5501 Backlight Data + */ + +static struct adp5520_backlight_platfrom_data adp5520_backlight_data = { + .fade_in = FADE_T_1200ms, + .fade_out = FADE_T_1200ms, + .fade_led_law = BL_LAW_LINEAR, + .en_ambl_sens = 1, + .abml_filt = BL_AMBL_FILT_640ms, + .l1_daylight_max = BL_CUR_mA(15), + .l1_daylight_dim = BL_CUR_mA(0), + .l2_office_max = BL_CUR_mA(7), + .l2_office_dim = BL_CUR_mA(0), + .l3_dark_max = BL_CUR_mA(3), + .l3_dark_dim = BL_CUR_mA(0), + .l2_trip = L2_COMP_CURR_uA(700), + .l2_hyst = L2_COMP_CURR_uA(50), + .l3_trip = L3_COMP_CURR_uA(80), + .l3_hyst = L3_COMP_CURR_uA(20), +}; + + /* + * ADP5520/5501 LEDs Data + */ + +#include + +static struct led_info adp5520_leds[] = { + { + .name = "adp5520-led1", + .default_trigger = "none", + .flags = FLAG_ID_ADP5520_LED1_ADP5501_LED0 | LED_OFFT_600ms, + }, +#ifdef ADP5520_EN_ALL_LEDS + { + .name = "adp5520-led2", + .default_trigger = "none", + .flags = FLAG_ID_ADP5520_LED2_ADP5501_LED1, + }, + { + .name = "adp5520-led3", + .default_trigger = "none", + .flags = FLAG_ID_ADP5520_LED3_ADP5501_LED2, + }, +#endif +}; + +static struct adp5520_leds_platfrom_data adp5520_leds_data = { + .num_leds = ARRAY_SIZE(adp5520_leds), + .leds = adp5520_leds, + .fade_in = FADE_T_600ms, + .fade_out = FADE_T_600ms, + .led_on_time = LED_ONT_600ms, +}; + + /* + * ADP5520 GPIO Data + */ + +static struct adp5520_gpio_platfrom_data adp5520_gpio_data = { + .gpio_start = 50, + .gpio_en_mask = GPIO_C1 | GPIO_C2 | GPIO_R2, + .gpio_pullup_mask = GPIO_C1 | GPIO_C2 | GPIO_R2, +}; + + /* + * ADP5520 Keypad Data + */ + +#include +static const unsigned short adp5520_keymap[ADP5520_KEYMAPSIZE] = { + [KEY(0, 0)] = KEY_GRAVE, + [KEY(0, 1)] = KEY_1, + [KEY(0, 2)] = KEY_2, + [KEY(0, 3)] = KEY_3, + [KEY(1, 0)] = KEY_4, + [KEY(1, 1)] = KEY_5, + [KEY(1, 2)] = KEY_6, + [KEY(1, 3)] = KEY_7, + [KEY(2, 0)] = KEY_8, + [KEY(2, 1)] = KEY_9, + [KEY(2, 2)] = KEY_0, + [KEY(2, 3)] = KEY_MINUS, + [KEY(3, 0)] = KEY_EQUAL, + [KEY(3, 1)] = KEY_BACKSLASH, + [KEY(3, 2)] = KEY_BACKSPACE, + [KEY(3, 3)] = KEY_ENTER, +}; + +static struct adp5520_keys_platfrom_data adp5520_keys_data = { + .rows_en_mask = ROW_R3 | ROW_R2 | ROW_R1 | ROW_R0, + .cols_en_mask = COL_C3 | COL_C2 | COL_C1 | COL_C0, + .keymap = adp5520_keymap, + .keymapsize = ARRAY_SIZE(adp5520_keymap), + .repeat = 0, +}; + + /* + * ADP5520/5501 Multifuction Device Init Data + */ + +static struct adp5520_subdev_info adp5520_subdevs[] = { + { + .name = "adp5520-backlight", + .id = ID_ADP5520, + .platform_data = &adp5520_backlight_data, + }, + { + .name = "adp5520-led", + .id = ID_ADP5520, + .platform_data = &adp5520_leds_data, + }, + { + .name = "adp5520-gpio", + .id = ID_ADP5520, + .platform_data = &adp5520_gpio_data, + }, + { + .name = "adp5520-keys", + .id = ID_ADP5520, + .platform_data = &adp5520_keys_data, + }, +}; + +static struct adp5520_platform_data adp5520_pdev_data = { + .num_subdevs = ARRAY_SIZE(adp5520_subdevs), + .subdevs = adp5520_subdevs, +}; + +#endif + static struct i2c_board_info __initdata bfin_i2c_board_info[] = { #if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE) { @@ -1105,6 +1240,13 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = { .platform_data = (void *)&adp5588_kpad_data, }, #endif +#if defined(CONFIG_PMIC_ADP5520) || defined(CONFIG_PMIC_ADP5520_MODULE) + { + I2C_BOARD_INFO("pmic-adp5520", 0x32), + .irq = IRQ_PF7, + .platform_data = (void *)&adp5520_pdev_data, + }, +#endif }; #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE) -- GitLab From b89df5042300bc08492a567f409c6899863ed8a3 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Sat, 28 Mar 2009 23:14:41 +0800 Subject: [PATCH 4953/4982] Blackfin arch: Blacklist Hibernate (PM_SUSPEND_MEM) on BF561 as well Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c index f48a6aebb49..bce5a84be49 100644 --- a/arch/blackfin/mach-common/pm.c +++ b/arch/blackfin/mach-common/pm.c @@ -287,7 +287,7 @@ int bfin_pm_suspend_mem_enter(void) static int bfin_pm_valid(suspend_state_t state) { return (state == PM_SUSPEND_STANDBY -#ifndef BF533_FAMILY +#if !(defined(BF533_FAMILY) || defined(CONFIG_BF561)) /* * On BF533/2/1: * If we enter Hibernate the SCKE Pin is driven Low, -- GitLab From 1e9aa95526c3dfc50e55665c7129469a12593beb Mon Sep 17 00:00:00 2001 From: Cliff Cai Date: Sat, 28 Mar 2009 23:28:51 +0800 Subject: [PATCH 4954/4982] Blackfin arch: add sport-spi related resource stuff to board file Signed-off-by: Cliff Cai Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf537/boards/stamp.c | 70 +++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index f32b7477dcb..0572926da23 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -843,6 +843,71 @@ static struct platform_device bfin_spi0_device = { }; #endif /* spi master and devices */ +#if defined(CONFIG_SPI_BFIN_SPORT) || defined(CONFIG_SPI_BFIN_SPORT_MODULE) + +/* SPORT SPI controller data */ +static struct bfin5xx_spi_master bfin_sport_spi0_info = { + .num_chipselect = 1, /* master only supports one device */ + .enable_dma = 0, /* master don't support DMA */ + .pin_req = {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_DRPRI, + P_SPORT0_RSCLK, P_SPORT0_TFS, P_SPORT0_RFS, 0}, +}; + +static struct resource bfin_sport_spi0_resource[] = { + [0] = { + .start = SPORT0_TCR1, + .end = SPORT0_TCR1 + 0xFF, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_SPORT0_ERROR, + .end = IRQ_SPORT0_ERROR, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device bfin_sport_spi0_device = { + .name = "bfin-sport-spi", + .id = 1, /* Bus number */ + .num_resources = ARRAY_SIZE(bfin_sport_spi0_resource), + .resource = bfin_sport_spi0_resource, + .dev = { + .platform_data = &bfin_sport_spi0_info, /* Passed to driver */ + }, +}; + +static struct bfin5xx_spi_master bfin_sport_spi1_info = { + .num_chipselect = 1, /* master only supports one device */ + .enable_dma = 0, /* master don't support DMA */ + .pin_req = {P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_DRPRI, + P_SPORT1_RSCLK, P_SPORT1_TFS, P_SPORT1_RFS, 0}, +}; + +static struct resource bfin_sport_spi1_resource[] = { + [0] = { + .start = SPORT1_TCR1, + .end = SPORT1_TCR1 + 0xFF, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_SPORT1_ERROR, + .end = IRQ_SPORT1_ERROR, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device bfin_sport_spi1_device = { + .name = "bfin-sport-spi", + .id = 2, /* Bus number */ + .num_resources = ARRAY_SIZE(bfin_sport_spi1_resource), + .resource = bfin_sport_spi1_resource, + .dev = { + .platform_data = &bfin_sport_spi1_info, /* Passed to driver */ + }, +}; + +#endif /* sport spi master and devices */ + #if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE) static struct platform_device bfin_fb_device = { .name = "bf537-lq035", @@ -1395,6 +1460,11 @@ static struct platform_device *stamp_devices[] __initdata = { &bfin_spi0_device, #endif +#if defined(CONFIG_SPI_BFIN_SPORT) || defined(CONFIG_SPI_BFIN_SPORT_MODULE) + &bfin_sport_spi0_device, + &bfin_sport_spi1_device, +#endif + #if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE) &bfin_fb_device, #endif -- GitLab From 1eb19e30adeb05957b45204f0c04d94fc4662ffd Mon Sep 17 00:00:00 2001 From: Cliff Cai Date: Sat, 28 Mar 2009 23:31:43 +0800 Subject: [PATCH 4955/4982] Blackfin arch: sport spi needs 6 gpio pins Signed-off-by: Cliff Cai Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/bfin5xx_spi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/blackfin/include/asm/bfin5xx_spi.h b/arch/blackfin/include/asm/bfin5xx_spi.h index 1306e6b2294..0292d58f936 100644 --- a/arch/blackfin/include/asm/bfin5xx_spi.h +++ b/arch/blackfin/include/asm/bfin5xx_spi.h @@ -110,7 +110,7 @@ struct bfin5xx_spi_master { u16 num_chipselect; u8 enable_dma; - u16 pin_req[4]; + u16 pin_req[7]; }; /* spi_board_info.controller_data for SPI slave devices, -- GitLab From 4636b3019a76aacc5b01e14bd14cb468fb00940f Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 29 Mar 2009 00:47:31 +0800 Subject: [PATCH 4956/4982] Blackfin arch: add link-time asserts to make sure on-chip regions dont overflow Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/vmlinux.lds.S | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S index 4b4341da058..27952ae047d 100644 --- a/arch/blackfin/kernel/vmlinux.lds.S +++ b/arch/blackfin/kernel/vmlinux.lds.S @@ -183,6 +183,7 @@ SECTIONS . = ALIGN(4); __etext_l1 = .; } + ASSERT (SIZEOF(.text_l1) <= L1_CODE_LENGTH, "L1 text overflow!") .data_l1 L1_DATA_A_START : AT(LOADADDR(.text_l1) + SIZEOF(.text_l1)) { @@ -200,6 +201,7 @@ SECTIONS . = ALIGN(4); __ebss_l1 = .; } + ASSERT (SIZEOF(.data_a_l1) <= L1_DATA_A_LENGTH, "L1 data A overflow!") .data_b_l1 L1_DATA_B_START : AT(LOADADDR(.data_l1) + SIZEOF(.data_l1)) { @@ -214,6 +216,7 @@ SECTIONS . = ALIGN(4); __ebss_b_l1 = .; } + ASSERT (SIZEOF(.data_b_l1) <= L1_DATA_B_LENGTH, "L1 data B overflow!") __l2_lma_start = LOADADDR(.data_b_l1) + SIZEOF(.data_b_l1); @@ -239,6 +242,7 @@ SECTIONS . = ALIGN(4); __ebss_l2 = .; } + ASSERT (SIZEOF(.text_data_l1) <= L2_LENGTH, "L2 overflow!") /* Force trailing alignment of our init section so that when we * free our init memory, we don't leave behind a partial page. -- GitLab From abd750a0fa731f9fd568526adb96d11322734167 Mon Sep 17 00:00:00 2001 From: Cliff Cai Date: Sun, 29 Mar 2009 01:03:20 +0800 Subject: [PATCH 4957/4982] Blackfin arch: add RSI's definitions to bf514 and bf516 Signed-off-by: Cliff Cai Signed-off-by: Bryan Wu --- .../mach-bf518/include/mach/cdefBF514.h | 67 +++++++++ .../mach-bf518/include/mach/cdefBF516.h | 67 +++++++++ .../mach-bf518/include/mach/defBF514.h | 135 ++++++++++++++++++ .../mach-bf518/include/mach/defBF516.h | 135 ++++++++++++++++++ 4 files changed, 404 insertions(+) diff --git a/arch/blackfin/mach-bf518/include/mach/cdefBF514.h b/arch/blackfin/mach-bf518/include/mach/cdefBF514.h index 9521e178fb2..dfe492dfe54 100644 --- a/arch/blackfin/mach-bf518/include/mach/cdefBF514.h +++ b/arch/blackfin/mach-bf518/include/mach/cdefBF514.h @@ -45,4 +45,71 @@ /* The following are the #defines needed by ADSP-BF514 that are not in the common header */ +/* Removable Storage Interface Registers */ + +#define bfin_read_RSI_PWR_CTL() bfin_read16(RSI_PWR_CONTROL) +#define bfin_write_RSI_PWR_CTL(val) bfin_write16(RSI_PWR_CONTROL, val) +#define bfin_read_RSI_CLK_CTL() bfin_read16(RSI_CLK_CONTROL) +#define bfin_write_RSI_CLK_CTL(val) bfin_write16(RSI_CLK_CONTROL, val) +#define bfin_read_RSI_ARGUMENT() bfin_read32(RSI_ARGUMENT) +#define bfin_write_RSI_ARGUMENT(val) bfin_write32(RSI_ARGUMENT, val) +#define bfin_read_RSI_COMMAND() bfin_read16(RSI_COMMAND) +#define bfin_write_RSI_COMMAND(val) bfin_write16(RSI_COMMAND, val) +#define bfin_read_RSI_RESP_CMD() bfin_read16(RSI_RESP_CMD) +#define bfin_write_RSI_RESP_CMD(val) bfin_write16(RSI_RESP_CMD, val) +#define bfin_read_RSI_RESPONSE0() bfin_read32(RSI_RESPONSE0) +#define bfin_write_RSI_RESPONSE0(val) bfin_write32(RSI_RESPONSE0, val) +#define bfin_read_RSI_RESPONSE1() bfin_read32(RSI_RESPONSE1) +#define bfin_write_RSI_RESPONSE1(val) bfin_write32(RSI_RESPONSE1, val) +#define bfin_read_RSI_RESPONSE2() bfin_read32(RSI_RESPONSE2) +#define bfin_write_RSI_RESPONSE2(val) bfin_write32(RSI_RESPONSE2, val) +#define bfin_read_RSI_RESPONSE3() bfin_read32(RSI_RESPONSE3) +#define bfin_write_RSI_RESPONSE3(val) bfin_write32(RSI_RESPONSE3, val) +#define bfin_read_RSI_DATA_TIMER() bfin_read32(RSI_DATA_TIMER) +#define bfin_write_RSI_DATA_TIMER(val) bfin_write32(RSI_DATA_TIMER, val) +#define bfin_read_RSI_DATA_LGTH() bfin_read16(RSI_DATA_LGTH) +#define bfin_write_RSI_DATA_LGTH(val) bfin_write16(RSI_DATA_LGTH, val) +#define bfin_read_RSI_DATA_CTL() bfin_read16(RSI_DATA_CONTROL) +#define bfin_write_RSI_DATA_CTL(val) bfin_write16(RSI_DATA_CONTROL, val) +#define bfin_read_RSI_DATA_CNT() bfin_read16(RSI_DATA_CNT) +#define bfin_write_RSI_DATA_CNT(val) bfin_write16(RSI_DATA_CNT, val) +#define bfin_read_RSI_STATUS() bfin_read32(RSI_STATUS) +#define bfin_write_RSI_STATUS(val) bfin_write32(RSI_STATUS, val) +#define bfin_read_RSI_STATUS_CLR() bfin_read16(RSI_STATUSCL) +#define bfin_write_RSI_STATUS_CLR(val) bfin_write16(RSI_STATUSCL, val) +#define bfin_read_RSI_MASK0() bfin_read32(RSI_MASK0) +#define bfin_write_RSI_MASK0(val) bfin_write32(RSI_MASK0, val) +#define bfin_read_RSI_MASK1() bfin_read32(RSI_MASK1) +#define bfin_write_RSI_MASK1(val) bfin_write32(RSI_MASK1, val) +#define bfin_read_RSI_FIFO_CNT() bfin_read16(RSI_FIFO_CNT) +#define bfin_write_RSI_FIFO_CNT(val) bfin_write16(RSI_FIFO_CNT, val) +#define bfin_read_RSI_CEATA_CTL() bfin_read16(RSI_CEATA_CONTROL) +#define bfin_write_RSI_CEATA_CTL(val) bfin_write16(RSI_CEATA_CONTROL, val) +#define bfin_read_RSI_FIFO() bfin_read32(RSI_FIFO) +#define bfin_write_RSI_FIFO(val) bfin_write32(RSI_FIFO, val) +#define bfin_read_RSI_E_STATUS() bfin_read16(RSI_ESTAT) +#define bfin_write_RSI_E_STATUS(val) bfin_write16(RSI_ESTAT, val) +#define bfin_read_RSI_E_MASK() bfin_read16(RSI_EMASK) +#define bfin_write_RSI_E_MASK(val) bfin_write16(RSI_EMASK, val) +#define bfin_read_RSI_CFG() bfin_read16(RSI_CONFIG) +#define bfin_write_RSI_CFG(val) bfin_write16(RSI_CONFIG, val) +#define bfin_read_RSI_RD_WAIT_EN() bfin_read16(RSI_RD_WAIT_EN) +#define bfin_write_RSI_RD_WAIT_EN(val) bfin_write16(RSI_RD_WAIT_EN, val) +#define bfin_read_RSI_PID0() bfin_read16(RSI_PID0) +#define bfin_write_RSI_PID0(val) bfin_write16(RSI_PID0, val) +#define bfin_read_RSI_PID1() bfin_read16(RSI_PID1) +#define bfin_write_RSI_PID1(val) bfin_write16(RSI_PID1, val) +#define bfin_read_RSI_PID2() bfin_read16(RSI_PID2) +#define bfin_write_RSI_PID2(val) bfin_write16(RSI_PID2, val) +#define bfin_read_RSI_PID3() bfin_read16(RSI_PID3) +#define bfin_write_RSI_PID3(val) bfin_write16(RSI_PID3, val) +#define bfin_read_RSI_PID4() bfin_read16(RSI_PID4) +#define bfin_write_RSI_PID4(val) bfin_write16(RSI_PID4, val) +#define bfin_read_RSI_PID5() bfin_read16(RSI_PID5) +#define bfin_write_RSI_PID5(val) bfin_write16(RSI_PID5, val) +#define bfin_read_RSI_PID6() bfin_read16(RSI_PID6) +#define bfin_write_RSI_PID6(val) bfin_write16(RSI_PID6, val) +#define bfin_read_RSI_PID7() bfin_read16(RSI_PID7) +#define bfin_write_RSI_PID7(val) bfin_write16(RSI_PID7, val) + #endif /* _CDEF_BF514_H */ diff --git a/arch/blackfin/mach-bf518/include/mach/cdefBF516.h b/arch/blackfin/mach-bf518/include/mach/cdefBF516.h index 4e26ccfcef9..14df43d4677 100644 --- a/arch/blackfin/mach-bf518/include/mach/cdefBF516.h +++ b/arch/blackfin/mach-bf518/include/mach/cdefBF516.h @@ -210,4 +210,71 @@ #define bfin_read_EMAC_TXC_ABORT() bfin_read32(EMAC_TXC_ABORT) #define bfin_write_EMAC_TXC_ABORT(val) bfin_write32(EMAC_TXC_ABORT, val) +/* Removable Storage Interface Registers */ + +#define bfin_read_RSI_PWR_CTL() bfin_read16(RSI_PWR_CONTROL) +#define bfin_write_RSI_PWR_CTL(val) bfin_write16(RSI_PWR_CONTROL, val) +#define bfin_read_RSI_CLK_CTL() bfin_read16(RSI_CLK_CONTROL) +#define bfin_write_RSI_CLK_CTL(val) bfin_write16(RSI_CLK_CONTROL, val) +#define bfin_read_RSI_ARGUMENT() bfin_read32(RSI_ARGUMENT) +#define bfin_write_RSI_ARGUMENT(val) bfin_write32(RSI_ARGUMENT, val) +#define bfin_read_RSI_COMMAND() bfin_read16(RSI_COMMAND) +#define bfin_write_RSI_COMMAND(val) bfin_write16(RSI_COMMAND, val) +#define bfin_read_RSI_RESP_CMD() bfin_read16(RSI_RESP_CMD) +#define bfin_write_RSI_RESP_CMD(val) bfin_write16(RSI_RESP_CMD, val) +#define bfin_read_RSI_RESPONSE0() bfin_read32(RSI_RESPONSE0) +#define bfin_write_RSI_RESPONSE0(val) bfin_write32(RSI_RESPONSE0, val) +#define bfin_read_RSI_RESPONSE1() bfin_read32(RSI_RESPONSE1) +#define bfin_write_RSI_RESPONSE1(val) bfin_write32(RSI_RESPONSE1, val) +#define bfin_read_RSI_RESPONSE2() bfin_read32(RSI_RESPONSE2) +#define bfin_write_RSI_RESPONSE2(val) bfin_write32(RSI_RESPONSE2, val) +#define bfin_read_RSI_RESPONSE3() bfin_read32(RSI_RESPONSE3) +#define bfin_write_RSI_RESPONSE3(val) bfin_write32(RSI_RESPONSE3, val) +#define bfin_read_RSI_DATA_TIMER() bfin_read32(RSI_DATA_TIMER) +#define bfin_write_RSI_DATA_TIMER(val) bfin_write32(RSI_DATA_TIMER, val) +#define bfin_read_RSI_DATA_LGTH() bfin_read16(RSI_DATA_LGTH) +#define bfin_write_RSI_DATA_LGTH(val) bfin_write16(RSI_DATA_LGTH, val) +#define bfin_read_RSI_DATA_CTL() bfin_read16(RSI_DATA_CONTROL) +#define bfin_write_RSI_DATA_CTL(val) bfin_write16(RSI_DATA_CONTROL, val) +#define bfin_read_RSI_DATA_CNT() bfin_read16(RSI_DATA_CNT) +#define bfin_write_RSI_DATA_CNT(val) bfin_write16(RSI_DATA_CNT, val) +#define bfin_read_RSI_STATUS() bfin_read32(RSI_STATUS) +#define bfin_write_RSI_STATUS(val) bfin_write32(RSI_STATUS, val) +#define bfin_read_RSI_STATUS_CLR() bfin_read16(RSI_STATUSCL) +#define bfin_write_RSI_STATUS_CLR(val) bfin_write16(RSI_STATUSCL, val) +#define bfin_read_RSI_MASK0() bfin_read32(RSI_MASK0) +#define bfin_write_RSI_MASK0(val) bfin_write32(RSI_MASK0, val) +#define bfin_read_RSI_MASK1() bfin_read32(RSI_MASK1) +#define bfin_write_RSI_MASK1(val) bfin_write32(RSI_MASK1, val) +#define bfin_read_RSI_FIFO_CNT() bfin_read16(RSI_FIFO_CNT) +#define bfin_write_RSI_FIFO_CNT(val) bfin_write16(RSI_FIFO_CNT, val) +#define bfin_read_RSI_CEATA_CTL() bfin_read16(RSI_CEATA_CONTROL) +#define bfin_write_RSI_CEATA_CTL(val) bfin_write16(RSI_CEATA_CONTROL, val) +#define bfin_read_RSI_FIFO() bfin_read32(RSI_FIFO) +#define bfin_write_RSI_FIFO(val) bfin_write32(RSI_FIFO, val) +#define bfin_read_RSI_E_STATUS() bfin_read16(RSI_ESTAT) +#define bfin_write_RSI_E_STATUS(val) bfin_write16(RSI_ESTAT, val) +#define bfin_read_RSI_E_MASK() bfin_read16(RSI_EMASK) +#define bfin_write_RSI_E_MASK(val) bfin_write16(RSI_EMASK, val) +#define bfin_read_RSI_CFG() bfin_read16(RSI_CONFIG) +#define bfin_write_RSI_CFG(val) bfin_write16(RSI_CONFIG, val) +#define bfin_read_RSI_RD_WAIT_EN() bfin_read16(RSI_RD_WAIT_EN) +#define bfin_write_RSI_RD_WAIT_EN(val) bfin_write16(RSI_RD_WAIT_EN, val) +#define bfin_read_RSI_PID0() bfin_read16(RSI_PID0) +#define bfin_write_RSI_PID0(val) bfin_write16(RSI_PID0, val) +#define bfin_read_RSI_PID1() bfin_read16(RSI_PID1) +#define bfin_write_RSI_PID1(val) bfin_write16(RSI_PID1, val) +#define bfin_read_RSI_PID2() bfin_read16(RSI_PID2) +#define bfin_write_RSI_PID2(val) bfin_write16(RSI_PID2, val) +#define bfin_read_RSI_PID3() bfin_read16(RSI_PID3) +#define bfin_write_RSI_PID3(val) bfin_write16(RSI_PID3, val) +#define bfin_read_RSI_PID4() bfin_read16(RSI_PID4) +#define bfin_write_RSI_PID4(val) bfin_write16(RSI_PID4, val) +#define bfin_read_RSI_PID5() bfin_read16(RSI_PID5) +#define bfin_write_RSI_PID5(val) bfin_write16(RSI_PID5, val) +#define bfin_read_RSI_PID6() bfin_read16(RSI_PID6) +#define bfin_write_RSI_PID6(val) bfin_write16(RSI_PID6, val) +#define bfin_read_RSI_PID7() bfin_read16(RSI_PID7) +#define bfin_write_RSI_PID7(val) bfin_write16(RSI_PID7, val) + #endif /* _CDEF_BF516_H */ diff --git a/arch/blackfin/mach-bf518/include/mach/defBF514.h b/arch/blackfin/mach-bf518/include/mach/defBF514.h index 543f2913b3f..56ee5a7c200 100644 --- a/arch/blackfin/mach-bf518/include/mach/defBF514.h +++ b/arch/blackfin/mach-bf518/include/mach/defBF514.h @@ -110,4 +110,139 @@ #define RSI_PID6 0xFFC03FF8 /* RSI Peripheral ID Register 6 */ #define RSI_PID7 0xFFC03FFC /* RSI Peripheral ID Register 7 */ +/* ********************************************************** */ +/* SINGLE BIT MACRO PAIRS (bit mask and negated one) */ +/* and MULTI BIT READ MACROS */ +/* ********************************************************** */ + +/* Bit masks for SDH_COMMAND */ + +#define CMD_IDX 0x3f /* Command Index */ +#define CMD_RSP 0x40 /* Response */ +#define CMD_L_RSP 0x80 /* Long Response */ +#define CMD_INT_E 0x100 /* Command Interrupt */ +#define CMD_PEND_E 0x200 /* Command Pending */ +#define CMD_E 0x400 /* Command Enable */ + +/* Bit masks for SDH_PWR_CTL */ + +#define PWR_ON 0x3 /* Power On */ +#if 0 +#define TBD 0x3c /* TBD */ +#endif +#define SD_CMD_OD 0x40 /* Open Drain Output */ +#define ROD_CTL 0x80 /* Rod Control */ + +/* Bit masks for SDH_CLK_CTL */ + +#define CLKDIV 0xff /* MC_CLK Divisor */ +#define CLK_E 0x100 /* MC_CLK Bus Clock Enable */ +#define PWR_SV_E 0x200 /* Power Save Enable */ +#define CLKDIV_BYPASS 0x400 /* Bypass Divisor */ +#define WIDE_BUS 0x800 /* Wide Bus Mode Enable */ + +/* Bit masks for SDH_RESP_CMD */ + +#define RESP_CMD 0x3f /* Response Command */ + +/* Bit masks for SDH_DATA_CTL */ + +#define DTX_E 0x1 /* Data Transfer Enable */ +#define DTX_DIR 0x2 /* Data Transfer Direction */ +#define DTX_MODE 0x4 /* Data Transfer Mode */ +#define DTX_DMA_E 0x8 /* Data Transfer DMA Enable */ +#define DTX_BLK_LGTH 0xf0 /* Data Transfer Block Length */ + +/* Bit masks for SDH_STATUS */ + +#define CMD_CRC_FAIL 0x1 /* CMD CRC Fail */ +#define DAT_CRC_FAIL 0x2 /* Data CRC Fail */ +#define CMD_TIME_OUT 0x4 /* CMD Time Out */ +#define DAT_TIME_OUT 0x8 /* Data Time Out */ +#define TX_UNDERRUN 0x10 /* Transmit Underrun */ +#define RX_OVERRUN 0x20 /* Receive Overrun */ +#define CMD_RESP_END 0x40 /* CMD Response End */ +#define CMD_SENT 0x80 /* CMD Sent */ +#define DAT_END 0x100 /* Data End */ +#define START_BIT_ERR 0x200 /* Start Bit Error */ +#define DAT_BLK_END 0x400 /* Data Block End */ +#define CMD_ACT 0x800 /* CMD Active */ +#define TX_ACT 0x1000 /* Transmit Active */ +#define RX_ACT 0x2000 /* Receive Active */ +#define TX_FIFO_STAT 0x4000 /* Transmit FIFO Status */ +#define RX_FIFO_STAT 0x8000 /* Receive FIFO Status */ +#define TX_FIFO_FULL 0x10000 /* Transmit FIFO Full */ +#define RX_FIFO_FULL 0x20000 /* Receive FIFO Full */ +#define TX_FIFO_ZERO 0x40000 /* Transmit FIFO Empty */ +#define RX_DAT_ZERO 0x80000 /* Receive FIFO Empty */ +#define TX_DAT_RDY 0x100000 /* Transmit Data Available */ +#define RX_FIFO_RDY 0x200000 /* Receive Data Available */ + +/* Bit masks for SDH_STATUS_CLR */ + +#define CMD_CRC_FAIL_STAT 0x1 /* CMD CRC Fail Status */ +#define DAT_CRC_FAIL_STAT 0x2 /* Data CRC Fail Status */ +#define CMD_TIMEOUT_STAT 0x4 /* CMD Time Out Status */ +#define DAT_TIMEOUT_STAT 0x8 /* Data Time Out status */ +#define TX_UNDERRUN_STAT 0x10 /* Transmit Underrun Status */ +#define RX_OVERRUN_STAT 0x20 /* Receive Overrun Status */ +#define CMD_RESP_END_STAT 0x40 /* CMD Response End Status */ +#define CMD_SENT_STAT 0x80 /* CMD Sent Status */ +#define DAT_END_STAT 0x100 /* Data End Status */ +#define START_BIT_ERR_STAT 0x200 /* Start Bit Error Status */ +#define DAT_BLK_END_STAT 0x400 /* Data Block End Status */ + +/* Bit masks for SDH_MASK0 */ + +#define CMD_CRC_FAIL_MASK 0x1 /* CMD CRC Fail Mask */ +#define DAT_CRC_FAIL_MASK 0x2 /* Data CRC Fail Mask */ +#define CMD_TIMEOUT_MASK 0x4 /* CMD Time Out Mask */ +#define DAT_TIMEOUT_MASK 0x8 /* Data Time Out Mask */ +#define TX_UNDERRUN_MASK 0x10 /* Transmit Underrun Mask */ +#define RX_OVERRUN_MASK 0x20 /* Receive Overrun Mask */ +#define CMD_RESP_END_MASK 0x40 /* CMD Response End Mask */ +#define CMD_SENT_MASK 0x80 /* CMD Sent Mask */ +#define DAT_END_MASK 0x100 /* Data End Mask */ +#define START_BIT_ERR_MASK 0x200 /* Start Bit Error Mask */ +#define DAT_BLK_END_MASK 0x400 /* Data Block End Mask */ +#define CMD_ACT_MASK 0x800 /* CMD Active Mask */ +#define TX_ACT_MASK 0x1000 /* Transmit Active Mask */ +#define RX_ACT_MASK 0x2000 /* Receive Active Mask */ +#define TX_FIFO_STAT_MASK 0x4000 /* Transmit FIFO Status Mask */ +#define RX_FIFO_STAT_MASK 0x8000 /* Receive FIFO Status Mask */ +#define TX_FIFO_FULL_MASK 0x10000 /* Transmit FIFO Full Mask */ +#define RX_FIFO_FULL_MASK 0x20000 /* Receive FIFO Full Mask */ +#define TX_FIFO_ZERO_MASK 0x40000 /* Transmit FIFO Empty Mask */ +#define RX_DAT_ZERO_MASK 0x80000 /* Receive FIFO Empty Mask */ +#define TX_DAT_RDY_MASK 0x100000 /* Transmit Data Available Mask */ +#define RX_FIFO_RDY_MASK 0x200000 /* Receive Data Available Mask */ + +/* Bit masks for SDH_FIFO_CNT */ + +#define FIFO_COUNT 0x7fff /* FIFO Count */ + +/* Bit masks for SDH_E_STATUS */ + +#define SDIO_INT_DET 0x2 /* SDIO Int Detected */ +#define SD_CARD_DET 0x10 /* SD Card Detect */ + +/* Bit masks for SDH_E_MASK */ + +#define SDIO_MSK 0x2 /* Mask SDIO Int Detected */ +#define SCD_MSK 0x40 /* Mask Card Detect */ + +/* Bit masks for SDH_CFG */ + +#define CLKS_EN 0x1 /* Clocks Enable */ +#define SD4E 0x4 /* SDIO 4-Bit Enable */ +#define MWE 0x8 /* Moving Window Enable */ +#define SD_RST 0x10 /* SDMMC Reset */ +#define PUP_SDDAT 0x20 /* Pull-up SD_DAT */ +#define PUP_SDDAT3 0x40 /* Pull-up SD_DAT3 */ +#define PD_SDDAT3 0x80 /* Pull-down SD_DAT3 */ + +/* Bit masks for SDH_RD_WAIT_EN */ + +#define RWR 0x1 /* Read Wait Request */ + #endif /* _DEF_BF514_H */ diff --git a/arch/blackfin/mach-bf518/include/mach/defBF516.h b/arch/blackfin/mach-bf518/include/mach/defBF516.h index 149a269306c..dfc93843517 100644 --- a/arch/blackfin/mach-bf518/include/mach/defBF516.h +++ b/arch/blackfin/mach-bf518/include/mach/defBF516.h @@ -487,4 +487,139 @@ #define RSI_PID6 0xFFC03FF8 /* RSI Peripheral ID Register 6 */ #define RSI_PID7 0xFFC03FFC /* RSI Peripheral ID Register 7 */ +/* ********************************************************** */ +/* SINGLE BIT MACRO PAIRS (bit mask and negated one) */ +/* and MULTI BIT READ MACROS */ +/* ********************************************************** */ + +/* Bit masks for SDH_COMMAND */ + +#define CMD_IDX 0x3f /* Command Index */ +#define CMD_RSP 0x40 /* Response */ +#define CMD_L_RSP 0x80 /* Long Response */ +#define CMD_INT_E 0x100 /* Command Interrupt */ +#define CMD_PEND_E 0x200 /* Command Pending */ +#define CMD_E 0x400 /* Command Enable */ + +/* Bit masks for SDH_PWR_CTL */ + +#define PWR_ON 0x3 /* Power On */ +#if 0 +#define TBD 0x3c /* TBD */ +#endif +#define SD_CMD_OD 0x40 /* Open Drain Output */ +#define ROD_CTL 0x80 /* Rod Control */ + +/* Bit masks for SDH_CLK_CTL */ + +#define CLKDIV 0xff /* MC_CLK Divisor */ +#define CLK_E 0x100 /* MC_CLK Bus Clock Enable */ +#define PWR_SV_E 0x200 /* Power Save Enable */ +#define CLKDIV_BYPASS 0x400 /* Bypass Divisor */ +#define WIDE_BUS 0x800 /* Wide Bus Mode Enable */ + +/* Bit masks for SDH_RESP_CMD */ + +#define RESP_CMD 0x3f /* Response Command */ + +/* Bit masks for SDH_DATA_CTL */ + +#define DTX_E 0x1 /* Data Transfer Enable */ +#define DTX_DIR 0x2 /* Data Transfer Direction */ +#define DTX_MODE 0x4 /* Data Transfer Mode */ +#define DTX_DMA_E 0x8 /* Data Transfer DMA Enable */ +#define DTX_BLK_LGTH 0xf0 /* Data Transfer Block Length */ + +/* Bit masks for SDH_STATUS */ + +#define CMD_CRC_FAIL 0x1 /* CMD CRC Fail */ +#define DAT_CRC_FAIL 0x2 /* Data CRC Fail */ +#define CMD_TIME_OUT 0x4 /* CMD Time Out */ +#define DAT_TIME_OUT 0x8 /* Data Time Out */ +#define TX_UNDERRUN 0x10 /* Transmit Underrun */ +#define RX_OVERRUN 0x20 /* Receive Overrun */ +#define CMD_RESP_END 0x40 /* CMD Response End */ +#define CMD_SENT 0x80 /* CMD Sent */ +#define DAT_END 0x100 /* Data End */ +#define START_BIT_ERR 0x200 /* Start Bit Error */ +#define DAT_BLK_END 0x400 /* Data Block End */ +#define CMD_ACT 0x800 /* CMD Active */ +#define TX_ACT 0x1000 /* Transmit Active */ +#define RX_ACT 0x2000 /* Receive Active */ +#define TX_FIFO_STAT 0x4000 /* Transmit FIFO Status */ +#define RX_FIFO_STAT 0x8000 /* Receive FIFO Status */ +#define TX_FIFO_FULL 0x10000 /* Transmit FIFO Full */ +#define RX_FIFO_FULL 0x20000 /* Receive FIFO Full */ +#define TX_FIFO_ZERO 0x40000 /* Transmit FIFO Empty */ +#define RX_DAT_ZERO 0x80000 /* Receive FIFO Empty */ +#define TX_DAT_RDY 0x100000 /* Transmit Data Available */ +#define RX_FIFO_RDY 0x200000 /* Receive Data Available */ + +/* Bit masks for SDH_STATUS_CLR */ + +#define CMD_CRC_FAIL_STAT 0x1 /* CMD CRC Fail Status */ +#define DAT_CRC_FAIL_STAT 0x2 /* Data CRC Fail Status */ +#define CMD_TIMEOUT_STAT 0x4 /* CMD Time Out Status */ +#define DAT_TIMEOUT_STAT 0x8 /* Data Time Out status */ +#define TX_UNDERRUN_STAT 0x10 /* Transmit Underrun Status */ +#define RX_OVERRUN_STAT 0x20 /* Receive Overrun Status */ +#define CMD_RESP_END_STAT 0x40 /* CMD Response End Status */ +#define CMD_SENT_STAT 0x80 /* CMD Sent Status */ +#define DAT_END_STAT 0x100 /* Data End Status */ +#define START_BIT_ERR_STAT 0x200 /* Start Bit Error Status */ +#define DAT_BLK_END_STAT 0x400 /* Data Block End Status */ + +/* Bit masks for SDH_MASK0 */ + +#define CMD_CRC_FAIL_MASK 0x1 /* CMD CRC Fail Mask */ +#define DAT_CRC_FAIL_MASK 0x2 /* Data CRC Fail Mask */ +#define CMD_TIMEOUT_MASK 0x4 /* CMD Time Out Mask */ +#define DAT_TIMEOUT_MASK 0x8 /* Data Time Out Mask */ +#define TX_UNDERRUN_MASK 0x10 /* Transmit Underrun Mask */ +#define RX_OVERRUN_MASK 0x20 /* Receive Overrun Mask */ +#define CMD_RESP_END_MASK 0x40 /* CMD Response End Mask */ +#define CMD_SENT_MASK 0x80 /* CMD Sent Mask */ +#define DAT_END_MASK 0x100 /* Data End Mask */ +#define START_BIT_ERR_MASK 0x200 /* Start Bit Error Mask */ +#define DAT_BLK_END_MASK 0x400 /* Data Block End Mask */ +#define CMD_ACT_MASK 0x800 /* CMD Active Mask */ +#define TX_ACT_MASK 0x1000 /* Transmit Active Mask */ +#define RX_ACT_MASK 0x2000 /* Receive Active Mask */ +#define TX_FIFO_STAT_MASK 0x4000 /* Transmit FIFO Status Mask */ +#define RX_FIFO_STAT_MASK 0x8000 /* Receive FIFO Status Mask */ +#define TX_FIFO_FULL_MASK 0x10000 /* Transmit FIFO Full Mask */ +#define RX_FIFO_FULL_MASK 0x20000 /* Receive FIFO Full Mask */ +#define TX_FIFO_ZERO_MASK 0x40000 /* Transmit FIFO Empty Mask */ +#define RX_DAT_ZERO_MASK 0x80000 /* Receive FIFO Empty Mask */ +#define TX_DAT_RDY_MASK 0x100000 /* Transmit Data Available Mask */ +#define RX_FIFO_RDY_MASK 0x200000 /* Receive Data Available Mask */ + +/* Bit masks for SDH_FIFO_CNT */ + +#define FIFO_COUNT 0x7fff /* FIFO Count */ + +/* Bit masks for SDH_E_STATUS */ + +#define SDIO_INT_DET 0x2 /* SDIO Int Detected */ +#define SD_CARD_DET 0x10 /* SD Card Detect */ + +/* Bit masks for SDH_E_MASK */ + +#define SDIO_MSK 0x2 /* Mask SDIO Int Detected */ +#define SCD_MSK 0x40 /* Mask Card Detect */ + +/* Bit masks for SDH_CFG */ + +#define CLKS_EN 0x1 /* Clocks Enable */ +#define SD4E 0x4 /* SDIO 4-Bit Enable */ +#define MWE 0x8 /* Moving Window Enable */ +#define SD_RST 0x10 /* SDMMC Reset */ +#define PUP_SDDAT 0x20 /* Pull-up SD_DAT */ +#define PUP_SDDAT3 0x40 /* Pull-up SD_DAT3 */ +#define PD_SDDAT3 0x80 /* Pull-down SD_DAT3 */ + +/* Bit masks for SDH_RD_WAIT_EN */ + +#define RWR 0x1 /* Read Wait Request */ + #endif /* _DEF_BF516_H */ -- GitLab From d6879c585b7f8c2f3eb2f7e7beac806af4e9755c Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sun, 29 Mar 2009 01:10:30 +0800 Subject: [PATCH 4958/4982] Blackfin arch: be less noisy when gets a gpio conflict after kernel has booted Once the kernel has booted - be less noisy when someone does a modprobe (and gets a gpio conflict). Signed-off-by: Robin Getz Signed-off-by: Bryan Wu --- arch/blackfin/kernel/bfin_gpio.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index 031ea3e2140..a0678da4053 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -802,7 +802,8 @@ int peripheral_request(unsigned short per, const char *label) */ if (unlikely(!check_gpio(ident) && reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) { - dump_stack(); + if (system_state == SYSTEM_BOOTING) + dump_stack(); printk(KERN_ERR "%s: Peripheral %d is already reserved as GPIO by %s !\n", __func__, ident, get_label(ident)); @@ -830,7 +831,8 @@ int peripheral_request(unsigned short per, const char *label) if (cmp_label(ident, label) == 0) goto anyway; - dump_stack(); + if (system_state == SYSTEM_BOOTING) + dump_stack(); printk(KERN_ERR "%s: Peripheral %d function %d is already reserved by %s !\n", __func__, ident, P_FUNCT2MUX(per), get_label(ident)); @@ -946,14 +948,16 @@ int bfin_gpio_request(unsigned gpio, const char *label) } if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { - dump_stack(); + if (system_state == SYSTEM_BOOTING) + dump_stack(); printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n", gpio, get_label(gpio)); local_irq_restore_hw(flags); return -EBUSY; } if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) { - dump_stack(); + if (system_state == SYSTEM_BOOTING) + dump_stack(); printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", gpio, get_label(gpio)); @@ -993,7 +997,8 @@ void bfin_gpio_free(unsigned gpio) local_irq_save_hw(flags); if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) { - dump_stack(); + if (system_state == SYSTEM_BOOTING) + dump_stack(); gpio_error(gpio); local_irq_restore_hw(flags); return; @@ -1017,7 +1022,8 @@ int bfin_gpio_irq_request(unsigned gpio, const char *label) local_irq_save_hw(flags); if (unlikely(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio))) { - dump_stack(); + if (system_state == SYSTEM_BOOTING) + dump_stack(); printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved as gpio-irq !\n", gpio); @@ -1025,7 +1031,8 @@ int bfin_gpio_irq_request(unsigned gpio, const char *label) return -EBUSY; } if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) { - dump_stack(); + if (system_state == SYSTEM_BOOTING) + dump_stack(); printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", gpio, get_label(gpio)); @@ -1057,7 +1064,8 @@ void bfin_gpio_irq_free(unsigned gpio) local_irq_save_hw(flags); if (unlikely(!(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio)))) { - dump_stack(); + if (system_state == SYSTEM_BOOTING) + dump_stack(); gpio_error(gpio); local_irq_restore_hw(flags); return; -- GitLab From 9e495834e59ca9b29f1a1f63b9f5533bb022ac49 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Sat, 28 Mar 2009 18:53:31 +0100 Subject: [PATCH 4959/4982] [ARM] 5434/1: ARM: OMAP: Fix mailbox compile for 24xx OMAP34XX_MAILBOX_BASE must be defined both for 24xx and 34xx. Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/plat-omap/include/mach/omap34xx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/plat-omap/include/mach/omap34xx.h b/arch/arm/plat-omap/include/mach/omap34xx.h index 1b1c35d2169..ab640151d3e 100644 --- a/arch/arm/plat-omap/include/mach/omap34xx.h +++ b/arch/arm/plat-omap/include/mach/omap34xx.h @@ -81,6 +81,7 @@ #define OMAP34XX_HSUSB_HOST_BASE (L4_34XX_BASE + 0x64000) #define OMAP34XX_USBTLL_BASE (L4_34XX_BASE + 0x62000) +#define OMAP34XX_MAILBOX_BASE (L4_34XX_BASE + 0x94000) #if defined(CONFIG_ARCH_OMAP3430) @@ -88,7 +89,6 @@ #define OMAP2_CM_BASE OMAP3430_CM_BASE #define OMAP2_PRM_BASE OMAP3430_PRM_BASE #define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP34XX_IC_BASE) -#define OMAP34XX_MAILBOX_BASE (L4_34XX_BASE + 0x94000) #endif -- GitLab From 9710794383ee5008d67f1a6613a4717bf6de47bc Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sun, 15 Mar 2009 11:11:44 -0700 Subject: [PATCH 4960/4982] async: remove the temporary (2.6.29) "async is off by default" code Now that everyone has been able to test the async code (and it's being used in the Moblin betas by default), we can enable it by default. The various fixes needed have gone into 2.6.29 already. [With an important bugfix from Stefan Richter] Signed-off-by: Arjan van de Ven --- kernel/async.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/kernel/async.c b/kernel/async.c index f565891f2c9..968ef9457d4 100644 --- a/kernel/async.c +++ b/kernel/async.c @@ -49,6 +49,7 @@ asynchronous and synchronous parts of the kernel. */ #include +#include #include #include #include @@ -387,20 +388,11 @@ static int async_manager_thread(void *unused) static int __init async_init(void) { - if (async_enabled) - if (IS_ERR(kthread_run(async_manager_thread, NULL, - "async/mgr"))) - async_enabled = 0; - return 0; -} + async_enabled = + !IS_ERR(kthread_run(async_manager_thread, NULL, "async/mgr")); -static int __init setup_async(char *str) -{ - async_enabled = 1; - return 1; + WARN_ON(!async_enabled); + return 0; } -__setup("fastboot", setup_async); - - core_initcall(async_init); -- GitLab From 0c406263f0a22b9fad65404cf2b14eced0739485 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Mon, 26 Jan 2009 18:58:11 -0800 Subject: [PATCH 4961/4982] ide/net: flip the order of SATA and network init this patch flips the order in which sata and network drivers are initialized. SATA probing takes quite a bit of time, and with the asynchronous infrastructure other drivers that run after it can execute in parallel. Network drivers do tend to take some real time talking to the hardware, so running these later is a good thing (the sata probe then runs concurrent) This saves about 15% of my kernels boot time. Both Dave and Jeff acked this patch and suggested it should go via the async tree. Signed-off-by: Arjan van de Ven Acked-by: David S. Miller Acked-by: Jeff Garzik --- drivers/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/Makefile b/drivers/Makefile index c1bf4173793..2618a6169a1 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -36,13 +36,14 @@ obj-$(CONFIG_FB_INTEL) += video/intelfb/ obj-y += serial/ obj-$(CONFIG_PARPORT) += parport/ -obj-y += base/ block/ misc/ mfd/ net/ media/ +obj-y += base/ block/ misc/ mfd/ media/ obj-$(CONFIG_NUBUS) += nubus/ -obj-$(CONFIG_ATM) += atm/ obj-y += macintosh/ obj-$(CONFIG_IDE) += ide/ obj-$(CONFIG_SCSI) += scsi/ obj-$(CONFIG_ATA) += ata/ +obj-y += net/ +obj-$(CONFIG_ATM) += atm/ obj-$(CONFIG_FUSION) += message/ obj-$(CONFIG_FIREWIRE) += firewire/ obj-y += ieee1394/ -- GitLab From df52092f3c97788592ef72501a43fb7ac6a3cfe0 Mon Sep 17 00:00:00 2001 From: "Li, Shaohua" Date: Wed, 13 Aug 2008 17:26:01 +0800 Subject: [PATCH 4962/4982] fastboot: remove duplicate unpack_to_rootfs() we check if initrd is initramfs first and then do the real unpack. The check isn't required, we can directly do unpack. If the initrd isn't an initramfs, we can remove the garbage. In my laptop, this saves 0.1s boot time. This patch penalizes non-initramfs initrd case, but nowadays, initramfs is the most widely used method for initrds. Signed-off-by: Shaohua Li Acked-by: Arjan van de Ven Signed-off-by: Ingo Molnar --- init/initramfs.c | 71 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/init/initramfs.c b/init/initramfs.c index d9c941c0c3c..d3c56fcb30b 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -166,8 +167,6 @@ static __initdata char *victim; static __initdata unsigned count; static __initdata loff_t this_header, next_header; -static __initdata int dry_run; - static inline void __init eat(unsigned n) { victim += n; @@ -229,10 +228,6 @@ static int __init do_header(void) parse_header(collected); next_header = this_header + N_ALIGN(name_len) + body_len; next_header = (next_header + 3) & ~3; - if (dry_run) { - read_into(name_buf, N_ALIGN(name_len), GotName); - return 0; - } state = SkipIt; if (name_len <= 0 || name_len > PATH_MAX) return 0; @@ -303,8 +298,6 @@ static int __init do_name(void) free_hash(); return 0; } - if (dry_run) - return 0; clean_path(collected, mode); if (S_ISREG(mode)) { int ml = maybe_link(); @@ -476,10 +469,9 @@ static void __init flush_window(void) outcnt = 0; } -static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) +static char * __init unpack_to_rootfs(char *buf, unsigned len) { int written; - dry_run = check_only; header_buf = kmalloc(110, GFP_KERNEL); symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL); name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL); @@ -574,10 +566,57 @@ skip: initrd_end = 0; } +#define BUF_SIZE 1024 +static void __init clean_rootfs(void) +{ + int fd; + void *buf; + struct linux_dirent64 *dirp; + int count; + + fd = sys_open("/", O_RDONLY, 0); + WARN_ON(fd < 0); + if (fd < 0) + return; + buf = kzalloc(BUF_SIZE, GFP_KERNEL); + WARN_ON(!buf); + if (!buf) { + sys_close(fd); + return; + } + + dirp = buf; + count = sys_getdents64(fd, dirp, BUF_SIZE); + while (count > 0) { + while (count > 0) { + struct stat st; + int ret; + + ret = sys_newlstat(dirp->d_name, &st); + WARN_ON_ONCE(ret); + if (!ret) { + if (S_ISDIR(st.st_mode)) + sys_rmdir(dirp->d_name); + else + sys_unlink(dirp->d_name); + } + + count -= dirp->d_reclen; + dirp = (void *)dirp + dirp->d_reclen; + } + dirp = buf; + memset(buf, 0, BUF_SIZE); + count = sys_getdents64(fd, dirp, BUF_SIZE); + } + + sys_close(fd); + kfree(buf); +} + static int __init populate_rootfs(void) { char *err = unpack_to_rootfs(__initramfs_start, - __initramfs_end - __initramfs_start, 0); + __initramfs_end - __initramfs_start); if (err) panic(err); if (initrd_start) { @@ -585,13 +624,15 @@ static int __init populate_rootfs(void) int fd; printk(KERN_INFO "checking if image is initramfs..."); err = unpack_to_rootfs((char *)initrd_start, - initrd_end - initrd_start, 1); + initrd_end - initrd_start); if (!err) { printk(" it is\n"); - unpack_to_rootfs((char *)initrd_start, - initrd_end - initrd_start, 0); free_initrd(); return 0; + } else { + clean_rootfs(); + unpack_to_rootfs(__initramfs_start, + __initramfs_end - __initramfs_start); } printk("it isn't (%s); looks like an initrd\n", err); fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 0700); @@ -604,7 +645,7 @@ static int __init populate_rootfs(void) #else printk(KERN_INFO "Unpacking initramfs..."); err = unpack_to_rootfs((char *)initrd_start, - initrd_end - initrd_start, 0); + initrd_end - initrd_start); if (err) panic(err); printk(" done\n"); -- GitLab From f0bba9f934517533acbda7329be93f55d5a01c03 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Sat, 28 Mar 2009 19:18:05 +0100 Subject: [PATCH 4963/4982] [ARM] 5435/1: fix compile warning in sanity_check_meminfo() Compiling recent 2.6.29-rc kernels for ARM gives me the following warning: arch/arm/mm/mmu.c: In function 'sanity_check_meminfo': arch/arm/mm/mmu.c:697: warning: comparison between pointer and integer This is because commit 3fd9825c42c784a59b3b90bdf073f49d4bb42a8d "[ARM] 5402/1: fix a case of wrap-around in sanity_check_meminfo()" in 2.6.29-rc5-git4 added a comparison of a pointer with PAGE_OFFSET, which is an integer. Fixed by casting PAGE_OFFSET to void *. Signed-off-by: Mikael Pettersson Acked-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/mm/mmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index d4d082c5c2d..5a89e57e342 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -694,7 +694,7 @@ static void __init sanity_check_meminfo(void) * the vmalloc area. */ if (__va(bank->start) >= VMALLOC_MIN || - __va(bank->start) < PAGE_OFFSET) { + __va(bank->start) < (void *)PAGE_OFFSET) { printk(KERN_NOTICE "Ignoring RAM at %.8lx-%.8lx " "(vmalloc region overlap).\n", bank->start, bank->start + bank->size - 1); -- GitLab From 764c16918fb2347b3cbc8f6030b2b6561911bc32 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 28 Mar 2009 21:34:40 +0100 Subject: [PATCH 4964/4982] i2c: Document the different ways to instantiate i2c devices On popular demand, here comes some documentation about how to instantiate i2c devices in the new (standard) i2c device driver binding model. I have also clarified how the class bitfield lets driver authors control which buses are probed in the auto-detect case, and warned more loudly against the abuse of this method. Signed-off-by: Jean Delvare Acked-by: Michael Lawnick Acked-by: Hans Verkuil --- Documentation/i2c/instantiating-devices | 167 ++++++++++++++++++++++++ Documentation/i2c/writing-clients | 19 ++- 2 files changed, 182 insertions(+), 4 deletions(-) create mode 100644 Documentation/i2c/instantiating-devices diff --git a/Documentation/i2c/instantiating-devices b/Documentation/i2c/instantiating-devices new file mode 100644 index 00000000000..b55ce57a84d --- /dev/null +++ b/Documentation/i2c/instantiating-devices @@ -0,0 +1,167 @@ +How to instantiate I2C devices +============================== + +Unlike PCI or USB devices, I2C devices are not enumerated at the hardware +level. Instead, the software must know which devices are connected on each +I2C bus segment, and what address these devices are using. For this +reason, the kernel code must instantiate I2C devices explicitly. There are +several ways to achieve this, depending on the context and requirements. + + +Method 1: Declare the I2C devices by bus number +----------------------------------------------- + +This method is appropriate when the I2C bus is a system bus as is the case +for many embedded systems. On such systems, each I2C bus has a number +which is known in advance. It is thus possible to pre-declare the I2C +devices which live on this bus. This is done with an array of struct +i2c_board_info which is registered by calling i2c_register_board_info(). + +Example (from omap2 h4): + +static struct i2c_board_info __initdata h4_i2c_board_info[] = { + { + I2C_BOARD_INFO("isp1301_omap", 0x2d), + .irq = OMAP_GPIO_IRQ(125), + }, + { /* EEPROM on mainboard */ + I2C_BOARD_INFO("24c01", 0x52), + .platform_data = &m24c01, + }, + { /* EEPROM on cpu card */ + I2C_BOARD_INFO("24c01", 0x57), + .platform_data = &m24c01, + }, +}; + +static void __init omap_h4_init(void) +{ + (...) + i2c_register_board_info(1, h4_i2c_board_info, + ARRAY_SIZE(h4_i2c_board_info)); + (...) +} + +The above code declares 3 devices on I2C bus 1, including their respective +addresses and custom data needed by their drivers. When the I2C bus in +question is registered, the I2C devices will be instantiated automatically +by i2c-core. + +The devices will be automatically unbound and destroyed when the I2C bus +they sit on goes away (if ever.) + + +Method 2: Instantiate the devices explicitly +-------------------------------------------- + +This method is appropriate when a larger device uses an I2C bus for +internal communication. A typical case is TV adapters. These can have a +tuner, a video decoder, an audio decoder, etc. usually connected to the +main chip by the means of an I2C bus. You won't know the number of the I2C +bus in advance, so the method 1 described above can't be used. Instead, +you can instantiate your I2C devices explicitly. This is done by filling +a struct i2c_board_info and calling i2c_new_device(). + +Example (from the sfe4001 network driver): + +static struct i2c_board_info sfe4001_hwmon_info = { + I2C_BOARD_INFO("max6647", 0x4e), +}; + +int sfe4001_init(struct efx_nic *efx) +{ + (...) + efx->board_info.hwmon_client = + i2c_new_device(&efx->i2c_adap, &sfe4001_hwmon_info); + + (...) +} + +The above code instantiates 1 I2C device on the I2C bus which is on the +network adapter in question. + +A variant of this is when you don't know for sure if an I2C device is +present or not (for example for an optional feature which is not present +on cheap variants of a board but you have no way to tell them apart), or +it may have different addresses from one board to the next (manufacturer +changing its design without notice). In this case, you can call +i2c_new_probed_device() instead of i2c_new_device(). + +Example (from the pnx4008 OHCI driver): + +static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; + +static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev) +{ + (...) + struct i2c_adapter *i2c_adap; + struct i2c_board_info i2c_info; + + (...) + i2c_adap = i2c_get_adapter(2); + memset(&i2c_info, 0, sizeof(struct i2c_board_info)); + strlcpy(i2c_info.name, "isp1301_pnx", I2C_NAME_SIZE); + isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info, + normal_i2c); + i2c_put_adapter(i2c_adap); + (...) +} + +The above code instantiates up to 1 I2C device on the I2C bus which is on +the OHCI adapter in question. It first tries at address 0x2c, if nothing +is found there it tries address 0x2d, and if still nothing is found, it +simply gives up. + +The driver which instantiated the I2C device is responsible for destroying +it on cleanup. This is done by calling i2c_unregister_device() on the +pointer that was earlier returned by i2c_new_device() or +i2c_new_probed_device(). + + +Method 3: Probe an I2C bus for certain devices +---------------------------------------------- + +Sometimes you do not have enough information about an I2C device, not even +to call i2c_new_probed_device(). The typical case is hardware monitoring +chips on PC mainboards. There are several dozen models, which can live +at 25 different addresses. Given the huge number of mainboards out there, +it is next to impossible to build an exhaustive list of the hardware +monitoring chips being used. Fortunately, most of these chips have +manufacturer and device ID registers, so they can be identified by +probing. + +In that case, I2C devices are neither declared nor instantiated +explicitly. Instead, i2c-core will probe for such devices as soon as their +drivers are loaded, and if any is found, an I2C device will be +instantiated automatically. In order to prevent any misbehavior of this +mechanism, the following restrictions apply: +* The I2C device driver must implement the detect() method, which + identifies a supported device by reading from arbitrary registers. +* Only buses which are likely to have a supported device and agree to be + probed, will be probed. For example this avoids probing for hardware + monitoring chips on a TV adapter. + +Example: +See lm90_driver and lm90_detect() in drivers/hwmon/lm90.c + +I2C devices instantiated as a result of such a successful probe will be +destroyed automatically when the driver which detected them is removed, +or when the underlying I2C bus is itself destroyed, whichever happens +first. + +Those of you familiar with the i2c subsystem of 2.4 kernels and early 2.6 +kernels will find out that this method 3 is essentially similar to what +was done there. Two significant differences are: +* Probing is only one way to instantiate I2C devices now, while it was the + only way back then. Where possible, methods 1 and 2 should be preferred. + Method 3 should only be used when there is no other way, as it can have + undesirable side effects. +* I2C buses must now explicitly say which I2C driver classes can probe + them (by the means of the class bitfield), while all I2C buses were + probed by default back then. The default is an empty class which means + that no probing happens. The purpose of the class bitfield is to limit + the aforementioned undesirable side effects. + +Once again, method 3 should be avoided wherever possible. Explicit device +instantiation (methods 1 and 2) is much preferred for it is safer and +faster. diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients index 6b9af7d479c..c1a06f989cf 100644 --- a/Documentation/i2c/writing-clients +++ b/Documentation/i2c/writing-clients @@ -207,15 +207,26 @@ You simply have to define a detect callback which will attempt to identify supported devices (returning 0 for supported ones and -ENODEV for unsupported ones), a list of addresses to probe, and a device type (or class) so that only I2C buses which may have that type of device -connected (and not otherwise enumerated) will be probed. The i2c -core will then call you back as needed and will instantiate a device -for you for every successful detection. +connected (and not otherwise enumerated) will be probed. For example, +a driver for a hardware monitoring chip for which auto-detection is +needed would set its class to I2C_CLASS_HWMON, and only I2C adapters +with a class including I2C_CLASS_HWMON would be probed by this driver. +Note that the absence of matching classes does not prevent the use of +a device of that type on the given I2C adapter. All it prevents is +auto-detection; explicit instantiation of devices is still possible. Note that this mechanism is purely optional and not suitable for all devices. You need some reliable way to identify the supported devices (typically using device-specific, dedicated identification registers), otherwise misdetections are likely to occur and things can get wrong -quickly. +quickly. Keep in mind that the I2C protocol doesn't include any +standard way to detect the presence of a chip at a given address, let +alone a standard way to identify devices. Even worse is the lack of +semantics associated to bus transfers, which means that the same +transfer can be seen as a read operation by a chip and as a write +operation by another chip. For these reasons, explicit device +instantiation should always be preferred to auto-detection where +possible. Device Deletion -- GitLab From f02e3d74e9f89e3d49284e7c99217993b657f5b7 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 28 Mar 2009 21:34:40 +0100 Subject: [PATCH 4965/4982] i2c: Let checkpatch shout on users of the legacy model As suggested by Mauro Carvalho Chehab. Signed-off-by: Jean Delvare Cc: Mauro Carvalho Chehab --- Documentation/feature-removal-schedule.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 02ea3773535..7907586c6e0 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -340,7 +340,8 @@ Who: Krzysztof Piotr Oledzki --------------------------- What: i2c_attach_client(), i2c_detach_client(), i2c_driver->detach_client() -When: 2.6.29 (ideally) or 2.6.30 (more likely) +When: 2.6.30 +Check: i2c_attach_client i2c_detach_client Why: Deprecated by the new (standard) device driver binding model. Use i2c_driver->probe() and ->remove() instead. Who: Jean Delvare -- GitLab From acec211ca605d79083058e6037bbf131c3f993fc Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 28 Mar 2009 21:34:40 +0100 Subject: [PATCH 4966/4982] i2c: Clarify which clients are auto-removed The automatic removal of i2c clients only affects the clients which were created automatically in the first place. Add a comment saying that to avoid any confusion. Signed-off-by: Jean Delvare --- drivers/i2c/i2c-core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index fbb9030b68a..456caa80bfd 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -581,7 +581,8 @@ static int i2c_do_del_adapter(struct device_driver *d, void *data) struct i2c_client *client, *_n; int res; - /* Remove the devices we created ourselves */ + /* Remove the devices we created ourselves as the result of hardware + * probing (using a driver's detect method) */ list_for_each_entry_safe(client, _n, &driver->clients, detected) { if (client->adapter == adapter) { dev_dbg(&adapter->dev, "Removing %s at 0x%x\n", @@ -749,6 +750,8 @@ static int __detach_adapter(struct device *dev, void *data) struct i2c_driver *driver = data; struct i2c_client *client, *_n; + /* Remove the devices we created ourselves as the result of hardware + * probing (using a driver's detect method) */ list_for_each_entry_safe(client, _n, &driver->clients, detected) { dev_dbg(&adapter->dev, "Removing %s at 0x%x\n", client->name, client->addr); -- GitLab From d2dd14ac1847082d4bb955619e86ed315c0ecd20 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 28 Mar 2009 21:34:41 +0100 Subject: [PATCH 4967/4982] i2c-nforce2: Add support for MCP67, MCP73, MCP78S and MCP79 The MCP78S and MCP79 appear to be compatible with the previous nForce chips as far as the SMBus controller is concerned. The MCP67 and MCP73 were not tested yet but I'd be very surprised if they weren't compatible too. Signed-off-by: Jean Delvare Cc: Oleg Ryjkov Cc: Malcolm Lalkaka Cc: Zbigniew Luszpinski --- Documentation/i2c/busses/i2c-nforce2 | 12 ++++++++---- drivers/i2c/busses/i2c-nforce2.c | 12 ++++++++++-- include/linux/pci_ids.h | 4 ++++ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/Documentation/i2c/busses/i2c-nforce2 b/Documentation/i2c/busses/i2c-nforce2 index fae3495bcba..9698c396b83 100644 --- a/Documentation/i2c/busses/i2c-nforce2 +++ b/Documentation/i2c/busses/i2c-nforce2 @@ -7,10 +7,14 @@ Supported adapters: * nForce3 250Gb MCP 10de:00E4 * nForce4 MCP 10de:0052 * nForce4 MCP-04 10de:0034 - * nForce4 MCP51 10de:0264 - * nForce4 MCP55 10de:0368 - * nForce4 MCP61 10de:03EB - * nForce4 MCP65 10de:0446 + * nForce MCP51 10de:0264 + * nForce MCP55 10de:0368 + * nForce MCP61 10de:03EB + * nForce MCP65 10de:0446 + * nForce MCP67 10de:0542 + * nForce MCP73 10de:07D8 + * nForce MCP78S 10de:0752 + * nForce MCP79 10de:0AA2 Datasheet: not publicly available, but seems to be similar to the AMD-8111 SMBus 2.0 adapter. diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c index 05af6cd7f27..2ff4683703a 100644 --- a/drivers/i2c/busses/i2c-nforce2.c +++ b/drivers/i2c/busses/i2c-nforce2.c @@ -31,10 +31,14 @@ nForce3 250Gb MCP 00E4 nForce4 MCP 0052 nForce4 MCP-04 0034 - nForce4 MCP51 0264 - nForce4 MCP55 0368 + nForce MCP51 0264 + nForce MCP55 0368 nForce MCP61 03EB nForce MCP65 0446 + nForce MCP67 0542 + nForce MCP73 07D8 + nForce MCP78S 0752 + nForce MCP79 0AA2 This driver supports the 2 SMBuses that are included in the MCP of the nForce2/3/4/5xx chipsets. @@ -315,6 +319,10 @@ static struct pci_device_id nforce2_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP78S_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP79_SMBUS) }, { 0 } }; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 05dfa7c4fb6..5109fecde28 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1237,6 +1237,7 @@ #define PCI_DEVICE_ID_NVIDIA_NVENET_21 0x0451 #define PCI_DEVICE_ID_NVIDIA_NVENET_22 0x0452 #define PCI_DEVICE_ID_NVIDIA_NVENET_23 0x0453 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_SMBUS 0x0542 #define PCI_DEVICE_ID_NVIDIA_NVENET_24 0x054C #define PCI_DEVICE_ID_NVIDIA_NVENET_25 0x054D #define PCI_DEVICE_ID_NVIDIA_NVENET_26 0x054E @@ -1247,11 +1248,14 @@ #define PCI_DEVICE_ID_NVIDIA_NVENET_31 0x07DF #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE 0x0560 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE 0x056C +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP78S_SMBUS 0x0752 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE 0x0759 #define PCI_DEVICE_ID_NVIDIA_NVENET_32 0x0760 #define PCI_DEVICE_ID_NVIDIA_NVENET_33 0x0761 #define PCI_DEVICE_ID_NVIDIA_NVENET_34 0x0762 #define PCI_DEVICE_ID_NVIDIA_NVENET_35 0x0763 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_SMBUS 0x07D8 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP79_SMBUS 0x0AA2 #define PCI_DEVICE_ID_NVIDIA_NVENET_36 0x0AB0 #define PCI_DEVICE_ID_NVIDIA_NVENET_37 0x0AB1 #define PCI_DEVICE_ID_NVIDIA_NVENET_38 0x0AB2 -- GitLab From 781b8a2a31b7009a0baa8d700feafa6afc3fb861 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 28 Mar 2009 21:34:41 +0100 Subject: [PATCH 4968/4982] eeprom/at24: Remove EXPERIMENTAL This driver has been widely used since inclusion and no problems have been reported. Signed-off-by: Wolfram Sang Cc: David Brownell Signed-off-by: Jean Delvare --- drivers/misc/eeprom/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig index c76df8cda5e..89fec052f3b 100644 --- a/drivers/misc/eeprom/Kconfig +++ b/drivers/misc/eeprom/Kconfig @@ -2,7 +2,7 @@ menu "EEPROM support" config EEPROM_AT24 tristate "I2C EEPROMs from most vendors" - depends on I2C && SYSFS && EXPERIMENTAL + depends on I2C && SYSFS help Enable this driver to get read/write support to most I2C EEPROMs, after you configure the driver to know about each EEPROM on -- GitLab From 0c168ceb9e1898a7f2895e80ce9915835b083bd3 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Sat, 28 Mar 2009 21:34:42 +0100 Subject: [PATCH 4969/4982] i2c-algo-pcf: Style cleanups cleanup whitespace, fix comments and remove the unused STUB_I2C. Signed-off-by: Roel Kluin Signed-off-by: Jean Delvare Acked-by: Eric Brower --- drivers/i2c/algos/i2c-algo-pcf.c | 250 ++++++++++++++----------------- 1 file changed, 115 insertions(+), 135 deletions(-) diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c index 3e01992230b..5906986d013 100644 --- a/drivers/i2c/algos/i2c-algo-pcf.c +++ b/drivers/i2c/algos/i2c-algo-pcf.c @@ -1,31 +1,30 @@ -/* ------------------------------------------------------------------------- */ -/* i2c-algo-pcf.c i2c driver algorithms for PCF8584 adapters */ -/* ------------------------------------------------------------------------- */ -/* Copyright (C) 1995-1997 Simon G. Vogl - 1998-2000 Hans Berglund - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* ------------------------------------------------------------------------- */ - -/* With some changes from Kyösti Mälkki and - Frodo Looijaard ,and also from Martin Bailey - */ - -/* Partially rewriten by Oleg I. Vdovikin to handle multiple - messages, proper stop/repstart signaling during receive, - added detect code */ +/* + * i2c-algo-pcf.c i2c driver algorithms for PCF8584 adapters + * + * Copyright (C) 1995-1997 Simon G. Vogl + * 1998-2000 Hans Berglund + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * With some changes from Kyösti Mälkki and + * Frodo Looijaard , and also from Martin Bailey + * + * + * Partially rewriten by Oleg I. Vdovikin to handle multiple + * messages, proper stop/repstart signaling during receive, added detect code + */ #include #include @@ -38,17 +37,18 @@ #include "i2c-algo-pcf.h" -#define DEB2(x) if (i2c_debug>=2) x -#define DEB3(x) if (i2c_debug>=3) x /* print several statistical values*/ -#define DEBPROTO(x) if (i2c_debug>=9) x; - /* debug the protocol by showing transferred bits */ +#define DEB2(x) if (i2c_debug >= 2) x +#define DEB3(x) if (i2c_debug >= 3) x /* print several statistical values */ +#define DEBPROTO(x) if (i2c_debug >= 9) x; + /* debug the protocol by showing transferred bits */ #define DEF_TIMEOUT 16 -/* module parameters: +/* + * module parameters: */ static int i2c_debug; -/* --- setting states on the bus with the right timing: --------------- */ +/* setting states on the bus with the right timing: */ #define set_pcf(adap, ctl, val) adap->setpcf(adap->data, ctl, val) #define get_pcf(adap, ctl) adap->getpcf(adap->data, ctl) @@ -57,22 +57,21 @@ static int i2c_debug; #define i2c_outb(adap, val) adap->setpcf(adap->data, 0, val) #define i2c_inb(adap) adap->getpcf(adap->data, 0) -/* --- other auxiliary functions -------------------------------------- */ +/* other auxiliary functions */ -static void i2c_start(struct i2c_algo_pcf_data *adap) +static void i2c_start(struct i2c_algo_pcf_data *adap) { DEBPROTO(printk("S ")); set_pcf(adap, 1, I2C_PCF_START); } -static void i2c_repstart(struct i2c_algo_pcf_data *adap) +static void i2c_repstart(struct i2c_algo_pcf_data *adap) { DEBPROTO(printk(" Sr ")); set_pcf(adap, 1, I2C_PCF_REPSTART); } - -static void i2c_stop(struct i2c_algo_pcf_data *adap) +static void i2c_stop(struct i2c_algo_pcf_data *adap) { DEBPROTO(printk("P\n")); set_pcf(adap, 1, I2C_PCF_STOP); @@ -82,17 +81,17 @@ static void handle_lab(struct i2c_algo_pcf_data *adap, const int *status) { DEB2(printk(KERN_INFO "i2c-algo-pcf.o: lost arbitration (CSR 0x%02x)\n", - *status)); - - /* Cleanup from LAB -- reset and enable ESO. + *status)); + /* + * Cleanup from LAB -- reset and enable ESO. * This resets the PCF8584; since we've lost the bus, no * further attempts should be made by callers to clean up * (no i2c_stop() etc.) */ set_pcf(adap, 1, I2C_PCF_PIN); set_pcf(adap, 1, I2C_PCF_ESO); - - /* We pause for a time period sufficient for any running + /* + * We pause for a time period sufficient for any running * I2C transaction to complete -- the arbitration logic won't * work properly until the next START is seen. * It is assumed the bus driver or client has set a proper value. @@ -108,48 +107,48 @@ static void handle_lab(struct i2c_algo_pcf_data *adap, const int *status) get_pcf(adap, 1))); } -static int wait_for_bb(struct i2c_algo_pcf_data *adap) { +static int wait_for_bb(struct i2c_algo_pcf_data *adap) +{ int timeout = DEF_TIMEOUT; int status; status = get_pcf(adap, 1); -#ifndef STUB_I2C + while (timeout-- && !(status & I2C_PCF_BB)) { udelay(100); /* wait for 100 us */ status = get_pcf(adap, 1); } -#endif - if (timeout <= 0) { + + if (timeout <= 0) printk(KERN_ERR "Timeout waiting for Bus Busy\n"); - } - - return (timeout<=0); -} + return timeout <= 0; +} -static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) { +static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) +{ int timeout = DEF_TIMEOUT; *status = get_pcf(adap, 1); -#ifndef STUB_I2C + while (timeout-- && (*status & I2C_PCF_PIN)) { adap->waitforpin(adap->data); *status = get_pcf(adap, 1); } if (*status & I2C_PCF_LAB) { handle_lab(adap, status); - return(-EINTR); + return -EINTR; } -#endif + if (timeout <= 0) - return(-1); + return -1; else - return(0); + return 0; } -/* +/* * This should perform the 'PCF8584 initialization sequence' as described * in the Philips IC12 data book (1995, Aug 29). * There should be a 30 clock cycle wait after reset, I assume this @@ -164,18 +163,21 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap) { unsigned char temp; - DEB3(printk(KERN_DEBUG "i2c-algo-pcf.o: PCF state 0x%02x\n", get_pcf(adap, 1))); + DEB3(printk(KERN_DEBUG "i2c-algo-pcf.o: PCF state 0x%02x\n", + get_pcf(adap, 1))); /* S1=0x80: S0 selected, serial interface off */ set_pcf(adap, 1, I2C_PCF_PIN); - /* check to see S1 now used as R/W ctrl - - PCF8584 does that when ESO is zero */ + /* + * check to see S1 now used as R/W ctrl - + * PCF8584 does that when ESO is zero + */ if (((temp = get_pcf(adap, 1)) & 0x7f) != (0)) { DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S0 (0x%02x).\n", temp)); return -ENXIO; /* definetly not PCF8584 */ } - /* load own address in S0, effective address is (own << 1) */ + /* load own address in S0, effective address is (own << 1) */ i2c_outb(adap, get_own(adap)); /* check it's really written */ if ((temp = i2c_inb(adap)) != get_own(adap)) { @@ -183,7 +185,7 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap) return -ENXIO; } - /* S1=0xA0, next byte in S2 */ + /* S1=0xA0, next byte in S2 */ set_pcf(adap, 1, I2C_PCF_PIN | I2C_PCF_ES1); /* check to see S2 now selected */ if (((temp = get_pcf(adap, 1)) & 0x7f) != I2C_PCF_ES1) { @@ -191,7 +193,7 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap) return -ENXIO; } - /* load clock register S2 */ + /* load clock register S2 */ i2c_outb(adap, get_clock(adap)); /* check it's really written, the only 5 lowest bits does matter */ if (((temp = i2c_inb(adap)) & 0x1f) != get_clock(adap)) { @@ -199,7 +201,7 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap) return -ENXIO; } - /* Enable serial interface, idle, S0 selected */ + /* Enable serial interface, idle, S0 selected */ set_pcf(adap, 1, I2C_PCF_IDLE); /* check to see PCF is really idled and we can access status register */ @@ -207,57 +209,47 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap) DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S1` (0x%02x).\n", temp)); return -ENXIO; } - + printk(KERN_DEBUG "i2c-algo-pcf.o: detected and initialized PCF8584.\n"); return 0; } - -/* ----- Utility functions - */ - static int pcf_sendbytes(struct i2c_adapter *i2c_adap, const char *buf, - int count, int last) + int count, int last) { struct i2c_algo_pcf_data *adap = i2c_adap->algo_data; int wrcount, status, timeout; - + for (wrcount=0; wrcountdev, "i2c_write: writing %2.2X\n", - buf[wrcount]&0xff)); + buf[wrcount] & 0xff)); i2c_outb(adap, buf[wrcount]); timeout = wait_for_pin(adap, &status); if (timeout) { - if (timeout == -EINTR) { - /* arbitration lost */ - return -EINTR; - } + if (timeout == -EINTR) + return -EINTR; /* arbitration lost */ + i2c_stop(adap); dev_err(&i2c_adap->dev, "i2c_write: error - timeout.\n"); return -EREMOTEIO; /* got a better one ?? */ } -#ifndef STUB_I2C if (status & I2C_PCF_LRB) { i2c_stop(adap); dev_err(&i2c_adap->dev, "i2c_write: error - no ack.\n"); return -EREMOTEIO; /* got a better one ?? */ } -#endif } - if (last) { + if (last) i2c_stop(adap); - } - else { + else i2c_repstart(adap); - } - return (wrcount); + return wrcount; } - static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf, - int count, int last) + int count, int last) { int i, status; struct i2c_algo_pcf_data *adap = i2c_adap->algo_data; @@ -267,42 +259,36 @@ static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf, for (i = 0; i <= count; i++) { if ((wfp = wait_for_pin(adap, &status))) { - if (wfp == -EINTR) { - /* arbitration lost */ - return -EINTR; - } + if (wfp == -EINTR) + return -EINTR; /* arbitration lost */ + i2c_stop(adap); dev_err(&i2c_adap->dev, "pcf_readbytes timed out.\n"); - return (-1); + return -1; } -#ifndef STUB_I2C if ((status & I2C_PCF_LRB) && (i != count)) { i2c_stop(adap); dev_err(&i2c_adap->dev, "i2c_read: i2c_inb, No ack.\n"); - return (-1); + return -1; } -#endif - + if (i == count - 1) { set_pcf(adap, 1, I2C_PCF_ESO); - } else - if (i == count) { - if (last) { + } else if (i == count) { + if (last) i2c_stop(adap); - } else { + else i2c_repstart(adap); - } - }; + } - if (i) { + if (i) buf[i - 1] = i2c_inb(adap); - } else { + else i2c_inb(adap); /* dummy read */ - } } - return (i - 1); + return i - 1; } @@ -323,14 +309,14 @@ static int pcf_doAddress(struct i2c_algo_pcf_data *adap, } static int pcf_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg *msgs, + struct i2c_msg *msgs, int num) { struct i2c_algo_pcf_data *adap = i2c_adap->algo_data; struct i2c_msg *pmsg; int i; int ret=0, timeout, status; - + if (adap->xfer_begin) adap->xfer_begin(adap->data); @@ -338,25 +324,24 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap, timeout = wait_for_bb(adap); if (timeout) { DEB2(printk(KERN_ERR "i2c-algo-pcf.o: " - "Timeout waiting for BB in pcf_xfer\n");) + "Timeout waiting for BB in pcf_xfer\n");) i = -EIO; goto out; } - + for (i = 0;ret >= 0 && i < num; i++) { pmsg = &msgs[i]; DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: Doing %s %d bytes to 0x%02x - %d of %d messages\n", pmsg->flags & I2C_M_RD ? "read" : "write", - pmsg->len, pmsg->addr, i + 1, num);) - + pmsg->len, pmsg->addr, i + 1, num);) + ret = pcf_doAddress(adap, pmsg); /* Send START */ - if (i == 0) { - i2c_start(adap); - } - + if (i == 0) + i2c_start(adap); + /* Wait for PIN (pending interrupt NOT) */ timeout = wait_for_pin(adap, &status); if (timeout) { @@ -371,8 +356,7 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap, i = -EREMOTEIO; goto out; } - -#ifndef STUB_I2C + /* Check LRB (last rcvd bit - slave ack) */ if (status & I2C_PCF_LRB) { i2c_stop(adap); @@ -380,27 +364,24 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap, i = -EREMOTEIO; goto out; } -#endif - + DEB3(printk(KERN_DEBUG "i2c-algo-pcf.o: Msg %d, addr=0x%x, flags=0x%x, len=%d\n", i, msgs[i].addr, msgs[i].flags, msgs[i].len);) - - /* Read */ + if (pmsg->flags & I2C_M_RD) { - /* read bytes into buffer*/ ret = pcf_readbytes(i2c_adap, pmsg->buf, pmsg->len, - (i + 1 == num)); - + (i + 1 == num)); + if (ret != pmsg->len) { DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: fail: " "only read %d bytes.\n",ret)); } else { DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: read %d bytes.\n",ret)); } - } else { /* Write */ + } else { ret = pcf_sendbytes(i2c_adap, pmsg->buf, pmsg->len, - (i + 1 == num)); - + (i + 1 == num)); + if (ret != pmsg->len) { DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: fail: " "only wrote %d bytes.\n",ret)); @@ -413,24 +394,23 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap, out: if (adap->xfer_end) adap->xfer_end(adap->data); - return (i); + return i; } static u32 pcf_func(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING; } -/* -----exported algorithm data: ------------------------------------- */ - +/* exported algorithm data: */ static const struct i2c_algorithm pcf_algo = { .master_xfer = pcf_xfer, .functionality = pcf_func, }; -/* - * registering functions to load algorithms at runtime +/* + * registering functions to load algorithms at runtime */ int i2c_pcf_add_bus(struct i2c_adapter *adap) { @@ -458,4 +438,4 @@ MODULE_LICENSE("GPL"); module_param(i2c_debug, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(i2c_debug, - "debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol"); + "debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol"); -- GitLab From 94d78e180c0323422854bc1718e657ac2d0cac1b Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Sat, 28 Mar 2009 21:34:42 +0100 Subject: [PATCH 4970/4982] i2c-algo-pcf: Handle timeout correctly With a postfix decrement these timeouts reach -1 rather than 0, but after the loop it is tested whether they have become 0. As pointed out by Jean Delvare, the msg_num should be tested before the timeout. With the current order, you could exit with a timeout error while all the messages were successfully transferred. Signed-off-by: Roel Kluin Signed-off-by: Jean Delvare Acked-by: Eric Brower --- drivers/i2c/algos/i2c-algo-pcf.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c index 5906986d013..65a769f3ae7 100644 --- a/drivers/i2c/algos/i2c-algo-pcf.c +++ b/drivers/i2c/algos/i2c-algo-pcf.c @@ -115,15 +115,17 @@ static int wait_for_bb(struct i2c_algo_pcf_data *adap) status = get_pcf(adap, 1); - while (timeout-- && !(status & I2C_PCF_BB)) { + while (!(status & I2C_PCF_BB) && --timeout) { udelay(100); /* wait for 100 us */ status = get_pcf(adap, 1); } - if (timeout <= 0) + if (timeout == 0) { printk(KERN_ERR "Timeout waiting for Bus Busy\n"); + return -ETIMEDOUT; + } - return timeout <= 0; + return 0; } static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) @@ -133,7 +135,7 @@ static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) *status = get_pcf(adap, 1); - while (timeout-- && (*status & I2C_PCF_PIN)) { + while ((*status & I2C_PCF_PIN) && --timeout) { adap->waitforpin(adap->data); *status = get_pcf(adap, 1); } @@ -142,10 +144,10 @@ static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) return -EINTR; } - if (timeout <= 0) - return -1; - else - return 0; + if (timeout == 0) + return -ETIMEDOUT; + + return 0; } /* -- GitLab From 154d22b04ae1741c5fcfd5d747b813a9a279abff Mon Sep 17 00:00:00 2001 From: Frank Seidel Date: Sat, 28 Mar 2009 21:34:42 +0100 Subject: [PATCH 4971/4982] i2c: Add missing KERN_* constants to printks According to kerneljanitors todo list all printk calls (beginning a new line) should have an according KERN_* constant. Those are the missing pieces here for the i2c subsystem. Signed-off-by: Frank Seidel Signed-off-by: Jean Delvare --- drivers/i2c/algos/i2c-algo-pcf.c | 2 +- drivers/i2c/busses/i2c-pca-isa.c | 5 +++-- drivers/i2c/busses/i2c-powermac.c | 3 ++- drivers/i2c/busses/i2c-pxa.c | 9 +++++---- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c index 65a769f3ae7..d31147e1077 100644 --- a/drivers/i2c/algos/i2c-algo-pcf.c +++ b/drivers/i2c/algos/i2c-algo-pcf.c @@ -61,7 +61,7 @@ static int i2c_debug; static void i2c_start(struct i2c_algo_pcf_data *adap) { - DEBPROTO(printk("S ")); + DEBPROTO(printk(KERN_DEBUG "S ")); set_pcf(adap, 1, I2C_PCF_START); } diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c index 4aa8138cb0a..c420a7c0f3e 100644 --- a/drivers/i2c/busses/i2c-pca-isa.c +++ b/drivers/i2c/busses/i2c-pca-isa.c @@ -49,7 +49,8 @@ static void pca_isa_writebyte(void *pd, int reg, int val) { #ifdef DEBUG_IO static char *names[] = { "T/O", "DAT", "ADR", "CON" }; - printk("*** write %s at %#lx <= %#04x\n", names[reg], base+reg, val); + printk(KERN_DEBUG "*** write %s at %#lx <= %#04x\n", names[reg], + base+reg, val); #endif outb(val, base+reg); } @@ -60,7 +61,7 @@ static int pca_isa_readbyte(void *pd, int reg) #ifdef DEBUG_IO { static char *names[] = { "STA", "DAT", "ADR", "CON" }; - printk("*** read %s => %#04x\n", names[reg], res); + printk(KERN_DEBUG "*** read %s => %#04x\n", names[reg], res); } #endif return res; diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c index 60ca91745e5..3c9d71f6018 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c @@ -191,7 +191,8 @@ static int __devexit i2c_powermac_remove(struct platform_device *dev) i2c_set_adapdata(adapter, NULL); /* We aren't that prepared to deal with this... */ if (rc) - printk("i2c-powermac.c: Failed to remove bus %s !\n", + printk(KERN_WARNING + "i2c-powermac.c: Failed to remove bus %s !\n", adapter->name); platform_set_drvdata(dev, NULL); kfree(adapter); diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index bdb1f7510e9..c1405c8f6ba 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -210,11 +210,12 @@ static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id); static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why) { unsigned int i; - printk("i2c: error: %s\n", why); - printk("i2c: msg_num: %d msg_idx: %d msg_ptr: %d\n", + printk(KERN_ERR "i2c: error: %s\n", why); + printk(KERN_ERR "i2c: msg_num: %d msg_idx: %d msg_ptr: %d\n", i2c->msg_num, i2c->msg_idx, i2c->msg_ptr); - printk("i2c: ICR: %08x ISR: %08x\n" - "i2c: log: ", readl(_ICR(i2c)), readl(_ISR(i2c))); + printk(KERN_ERR "i2c: ICR: %08x ISR: %08x\n", + readl(_ICR(i2c)), readl(_ISR(i2c))); + printk(KERN_DEBUG "i2c: log: "); for (i = 0; i < i2c->irqlogidx; i++) printk("[%08x:%08x] ", i2c->isrlog[i], i2c->icrlog[i]); printk("\n"); -- GitLab From 8fcfef6e65c5b58e6482eae0b793319c8d9efd44 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 28 Mar 2009 21:34:43 +0100 Subject: [PATCH 4972/4982] i2c: Set a default timeout value for all adapters Setting a default timeout value on a per-algo basis doesn't make any sense. Move the default value setting to i2c-core. Individual adapter drivers can specify a different (non-zero) value if they wish. Also express the timeout value in a way which results in the same duration regarless of the value of HZ. Signed-off-by: Jean Delvare Acked-by: Wolfram Sang --- drivers/i2c/algos/i2c-algo-bit.c | 4 +--- drivers/i2c/algos/i2c-algo-pcf.c | 1 - drivers/i2c/i2c-core.c | 5 +++++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index eb8f72ca02f..d420cc5f563 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c @@ -604,9 +604,7 @@ static int i2c_bit_prepare_bus(struct i2c_adapter *adap) /* register new adapter to i2c module... */ adap->algo = &i2c_bit_algo; - - adap->timeout = 100; /* default values, should */ - adap->retries = 3; /* be replaced by defines */ + adap->retries = 3; return 0; } diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c index d31147e1077..7ce75775ec7 100644 --- a/drivers/i2c/algos/i2c-algo-pcf.c +++ b/drivers/i2c/algos/i2c-algo-pcf.c @@ -423,7 +423,6 @@ int i2c_pcf_add_bus(struct i2c_adapter *adap) /* register new adapter to i2c module... */ adap->algo = &pcf_algo; - adap->timeout = 100; if ((rval = pcf_init_8584(pcf_adap))) return rval; diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 456caa80bfd..e361033815d 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -459,6 +459,11 @@ static int i2c_register_adapter(struct i2c_adapter *adap) pr_debug("I2C adapter driver [%s] forgot to specify " "physical device\n", adap->name); } + + /* Set default timeout to 1 second if not already set */ + if (adap->timeout == 0) + adap->timeout = HZ; + dev_set_name(&adap->dev, "i2c-%d", adap->nr); adap->dev.release = &i2c_adapter_dev_release; adap->dev.class = &i2c_adapter_class; -- GitLab From 8a52c6b4d55b2960d93a90a7cf6afd252357fa54 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 28 Mar 2009 21:34:43 +0100 Subject: [PATCH 4973/4982] i2c: Adapter timeout is in jiffies i2c_adapter.timeout is in jiffies. Fix all drivers which thought otherwise. It didn't really matter as long as the value was only used inside the driver, but soon i2c-core will use it too so it must have the proper unit. Note: for the i2c-mpc driver, this fixes a bug in polling mode. Timeout would trigger after 1 jiffy, which is most probably not what the author wanted. Signed-off-by: Jean Delvare Cc: Clifford Wolf Acked-by: Sean MacLennan Cc: Stefan Roese Acked-by: Lennert Buytenhek Cc: Dan Williams Cc: Grant Likely Acked-by: Mark A. Greer --- drivers/i2c/busses/i2c-ibm_iic.c | 6 +++--- drivers/i2c/busses/i2c-iop3xx.c | 2 +- drivers/i2c/busses/i2c-mpc.c | 4 ++-- drivers/i2c/busses/i2c-mv64xxx.c | 7 +++---- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index 88f0db73b36..8b92a4666e0 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -415,7 +415,7 @@ static int iic_wait_for_tc(struct ibm_iic_private* dev){ if (dev->irq >= 0){ /* Interrupt mode */ ret = wait_event_interruptible_timeout(dev->wq, - !(in_8(&iic->sts) & STS_PT), dev->adap.timeout * HZ); + !(in_8(&iic->sts) & STS_PT), dev->adap.timeout); if (unlikely(ret < 0)) DBG("%d: wait interrupted\n", dev->idx); @@ -426,7 +426,7 @@ static int iic_wait_for_tc(struct ibm_iic_private* dev){ } else { /* Polling mode */ - unsigned long x = jiffies + dev->adap.timeout * HZ; + unsigned long x = jiffies + dev->adap.timeout; while (in_8(&iic->sts) & STS_PT){ if (unlikely(time_after(jiffies, x))){ @@ -748,7 +748,7 @@ static int __devinit iic_probe(struct of_device *ofdev, i2c_set_adapdata(adap, dev); adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; adap->algo = &iic_algo; - adap->timeout = 1; + adap->timeout = HZ; ret = i2c_add_adapter(adap); if (ret < 0) { diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c index 3190690c26c..a75c75e77b9 100644 --- a/drivers/i2c/busses/i2c-iop3xx.c +++ b/drivers/i2c/busses/i2c-iop3xx.c @@ -488,7 +488,7 @@ iop3xx_i2c_probe(struct platform_device *pdev) /* * Default values...should these come in from board code? */ - new_adapter->timeout = 100; + new_adapter->timeout = HZ; new_adapter->algo = &iop3xx_i2c_algo; init_waitqueue_head(&adapter_data->waitq); diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index aedbbe6618d..2b847d87594 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -116,7 +116,7 @@ static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing) } else { /* Interrupt mode */ result = wait_event_interruptible_timeout(i2c->queue, - (i2c->interrupt & CSR_MIF), timeout * HZ); + (i2c->interrupt & CSR_MIF), timeout); if (unlikely(result < 0)) { pr_debug("I2C: wait interrupted\n"); @@ -311,7 +311,7 @@ static struct i2c_adapter mpc_ops = { .owner = THIS_MODULE, .name = "MPC adapter", .algo = &mpc_algo, - .timeout = 1, + .timeout = HZ, }; static int __devinit fsl_i2c_probe(struct of_device *op, const struct of_device_id *match) diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 7f186bbcb99..5a4945d1dba 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -358,7 +358,7 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data) char abort = 0; time_left = wait_event_interruptible_timeout(drv_data->waitq, - !drv_data->block, msecs_to_jiffies(drv_data->adapter.timeout)); + !drv_data->block, drv_data->adapter.timeout); spin_lock_irqsave(&drv_data->lock, flags); if (!time_left) { /* Timed out */ @@ -374,8 +374,7 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data) spin_unlock_irqrestore(&drv_data->lock, flags); time_left = wait_event_timeout(drv_data->waitq, - !drv_data->block, - msecs_to_jiffies(drv_data->adapter.timeout)); + !drv_data->block, drv_data->adapter.timeout); if ((time_left <= 0) && drv_data->block) { drv_data->state = MV64XXX_I2C_STATE_IDLE; @@ -530,7 +529,7 @@ mv64xxx_i2c_probe(struct platform_device *pd) drv_data->adapter.algo = &mv64xxx_i2c_algo; drv_data->adapter.owner = THIS_MODULE; drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - drv_data->adapter.timeout = pdata->timeout; + drv_data->adapter.timeout = msecs_to_jiffies(pdata->timeout); drv_data->adapter.nr = pd->id; platform_set_drvdata(pd, drv_data); i2c_set_adapdata(&drv_data->adapter, drv_data); -- GitLab From 98a679cad56c0ba4677821836179abbe0aff8769 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 28 Mar 2009 21:34:43 +0100 Subject: [PATCH 4974/4982] i2c-davinci: Fix timeout handling Properly set the adapter timeout value in jiffies, and then use that value in the driver, rather than a hard-coded constant. Signed-off-by: Jean Delvare Tested-by: Troy Kisky Cc: Kevin Hilman --- drivers/i2c/busses/i2c-davinci.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 5d7789834b9..3fae3a91ce5 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -216,7 +216,7 @@ static int i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev, { unsigned long timeout; - timeout = jiffies + DAVINCI_I2C_TIMEOUT; + timeout = jiffies + dev->adapter.timeout; while (davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG) & DAVINCI_I2C_STR_BB) { if (time_after(jiffies, timeout)) { @@ -289,7 +289,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, - DAVINCI_I2C_TIMEOUT); + dev->adapter.timeout); if (r == 0) { dev_err(dev->dev, "controller timed out\n"); i2c_davinci_init(dev); @@ -546,9 +546,7 @@ static int davinci_i2c_probe(struct platform_device *pdev) strlcpy(adap->name, "DaVinci I2C adapter", sizeof(adap->name)); adap->algo = &i2c_davinci_algo; adap->dev.parent = &pdev->dev; - - /* FIXME */ - adap->timeout = 1; + adap->timeout = DAVINCI_I2C_TIMEOUT; adap->nr = pdev->id; r = i2c_add_numbered_adapter(adap); -- GitLab From bac3e7c2aa2575a1c71f6fa643499676ca7c12c3 Mon Sep 17 00:00:00 2001 From: Frank Seidel Date: Sat, 28 Mar 2009 21:34:44 +0100 Subject: [PATCH 4975/4982] i2c: Adapt debug macros for KERN_* constants According to kerneljanitors todo list all printk calls (beginning a new line) should have an according KERN_* constant. Those are the changes to the debug macros in the i2c subsystem to meet this requirement. Also changing no-debug statements to raw printks again. Signed-off-by: Frank Seidel Signed-off-by: Jean Delvare Tested-by: Wolfram Sang --- drivers/i2c/algos/i2c-algo-pca.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c index d50b329a3c9..943d70ee5d5 100644 --- a/drivers/i2c/algos/i2c-algo-pca.c +++ b/drivers/i2c/algos/i2c-algo-pca.c @@ -27,9 +27,12 @@ #include #include -#define DEB1(fmt, args...) do { if (i2c_debug>=1) printk(fmt, ## args); } while(0) -#define DEB2(fmt, args...) do { if (i2c_debug>=2) printk(fmt, ## args); } while(0) -#define DEB3(fmt, args...) do { if (i2c_debug>=3) printk(fmt, ## args); } while(0) +#define DEB1(fmt, args...) do { if (i2c_debug >= 1) \ + printk(KERN_DEBUG fmt, ## args); } while (0) +#define DEB2(fmt, args...) do { if (i2c_debug >= 2) \ + printk(KERN_DEBUG fmt, ## args); } while (0) +#define DEB3(fmt, args...) do { if (i2c_debug >= 3) \ + printk(KERN_DEBUG fmt, ## args); } while (0) static int i2c_debug; @@ -313,7 +316,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, ret = curmsg; out: - DEB1(KERN_CRIT "}}} transfered %d/%d messages. " + DEB1("}}} transfered %d/%d messages. " "status is %#04x. control is %#04x\n", curmsg, num, pca_status(adap), pca_get_con(adap)); @@ -347,7 +350,8 @@ static int pca_init(struct i2c_adapter *adap) pca_reset(pca_data); clock = pca_clock(pca_data); - DEB1(KERN_INFO "%s: Clock frequency is %dkHz\n", adap->name, freqs[clock]); + printk(KERN_INFO "%s: Clock frequency is %dkHz\n", adap->name, + freqs[clock]); pca_set_con(pca_data, I2C_PCA_CON_ENSIO | clock); udelay(500); /* 500 us for oscilator to stabilise */ -- GitLab From eff9ec95efaaf6b12d230f0ea7d3c295d3bc9d57 Mon Sep 17 00:00:00 2001 From: Marco Aurelio da Costa Date: Sat, 28 Mar 2009 21:34:44 +0100 Subject: [PATCH 4976/4982] i2c-algo-pca: Add PCA9665 support Add support for the PCA9665 I2C controller. Signed-off-by: Wolfram Sang Signed-off-by: Jean Delvare --- drivers/i2c/algos/i2c-algo-pca.c | 180 ++++++++++++++++++++++++-- drivers/i2c/busses/Kconfig | 8 +- drivers/i2c/busses/i2c-pca-isa.c | 14 +- drivers/i2c/busses/i2c-pca-platform.c | 9 +- include/linux/i2c-algo-pca.h | 33 ++++- 5 files changed, 216 insertions(+), 28 deletions(-) diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c index 943d70ee5d5..a8e51bd1a4f 100644 --- a/drivers/i2c/algos/i2c-algo-pca.c +++ b/drivers/i2c/algos/i2c-algo-pca.c @@ -46,6 +46,14 @@ static int i2c_debug; #define pca_wait(adap) adap->wait_for_completion(adap->data) #define pca_reset(adap) adap->reset_chip(adap->data) +static void pca9665_reset(void *pd) +{ + struct i2c_algo_pca_data *adap = pd; + pca_outw(adap, I2C_PCA_INDPTR, I2C_PCA_IPRESET); + pca_outw(adap, I2C_PCA_IND, 0xA5); + pca_outw(adap, I2C_PCA_IND, 0x5A); +} + /* * Generate a start condition on the i2c bus. * @@ -333,27 +341,171 @@ static const struct i2c_algorithm pca_algo = { .functionality = pca_func, }; -static int pca_init(struct i2c_adapter *adap) +static unsigned int pca_probe_chip(struct i2c_adapter *adap) { - static int freqs[] = {330,288,217,146,88,59,44,36}; - int clock; struct i2c_algo_pca_data *pca_data = adap->algo_data; - - if (pca_data->i2c_clock > 7) { - printk(KERN_WARNING "%s: Invalid I2C clock speed selected. Trying default.\n", - adap->name); - pca_data->i2c_clock = I2C_PCA_CON_59kHz; + /* The trick here is to check if there is an indirect register + * available. If there is one, we will read the value we first + * wrote on I2C_PCA_IADR. Otherwise, we will read the last value + * we wrote on I2C_PCA_ADR + */ + pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_IADR); + pca_outw(pca_data, I2C_PCA_IND, 0xAA); + pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_ITO); + pca_outw(pca_data, I2C_PCA_IND, 0x00); + pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_IADR); + if (pca_inw(pca_data, I2C_PCA_IND) == 0xAA) { + printk(KERN_INFO "%s: PCA9665 detected.\n", adap->name); + return I2C_PCA_CHIP_9665; + } else { + printk(KERN_INFO "%s: PCA9564 detected.\n", adap->name); + return I2C_PCA_CHIP_9564; } +} + +static int pca_init(struct i2c_adapter *adap) +{ + struct i2c_algo_pca_data *pca_data = adap->algo_data; adap->algo = &pca_algo; - pca_reset(pca_data); + if (pca_probe_chip(adap) == I2C_PCA_CHIP_9564) { + static int freqs[] = {330, 288, 217, 146, 88, 59, 44, 36}; + int clock; + + if (pca_data->i2c_clock > 7) { + switch (pca_data->i2c_clock) { + case 330000: + pca_data->i2c_clock = I2C_PCA_CON_330kHz; + break; + case 288000: + pca_data->i2c_clock = I2C_PCA_CON_288kHz; + break; + case 217000: + pca_data->i2c_clock = I2C_PCA_CON_217kHz; + break; + case 146000: + pca_data->i2c_clock = I2C_PCA_CON_146kHz; + break; + case 88000: + pca_data->i2c_clock = I2C_PCA_CON_88kHz; + break; + case 59000: + pca_data->i2c_clock = I2C_PCA_CON_59kHz; + break; + case 44000: + pca_data->i2c_clock = I2C_PCA_CON_44kHz; + break; + case 36000: + pca_data->i2c_clock = I2C_PCA_CON_36kHz; + break; + default: + printk(KERN_WARNING + "%s: Invalid I2C clock speed selected." + " Using default 59kHz.\n", adap->name); + pca_data->i2c_clock = I2C_PCA_CON_59kHz; + } + } else { + printk(KERN_WARNING "%s: " + "Choosing the clock frequency based on " + "index is deprecated." + " Use the nominal frequency.\n", adap->name); + } + + pca_reset(pca_data); + + clock = pca_clock(pca_data); + printk(KERN_INFO "%s: Clock frequency is %dkHz\n", + adap->name, freqs[clock]); + + pca_set_con(pca_data, I2C_PCA_CON_ENSIO | clock); + } else { + int clock; + int mode; + int tlow, thi; + /* Values can be found on PCA9665 datasheet section 7.3.2.6 */ + int min_tlow, min_thi; + /* These values are the maximum raise and fall values allowed + * by the I2C operation mode (Standard, Fast or Fast+) + * They are used (added) below to calculate the clock dividers + * of PCA9665. Note that they are slightly different of the + * real maximum, to allow the change on mode exactly on the + * maximum clock rate for each mode + */ + int raise_fall_time; + + struct i2c_algo_pca_data *pca_data = adap->algo_data; + + /* Ignore the reset function from the module, + * we can use the parallel bus reset + */ + pca_data->reset_chip = pca9665_reset; + + if (pca_data->i2c_clock > 1265800) { + printk(KERN_WARNING "%s: I2C clock speed too high." + " Using 1265.8kHz.\n", adap->name); + pca_data->i2c_clock = 1265800; + } + + if (pca_data->i2c_clock < 60300) { + printk(KERN_WARNING "%s: I2C clock speed too low." + " Using 60.3kHz.\n", adap->name); + pca_data->i2c_clock = 60300; + } + + /* To avoid integer overflow, use clock/100 for calculations */ + clock = pca_clock(pca_data) / 100; + + if (pca_data->i2c_clock > 10000) { + mode = I2C_PCA_MODE_TURBO; + min_tlow = 14; + min_thi = 5; + raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */ + } else if (pca_data->i2c_clock > 4000) { + mode = I2C_PCA_MODE_FASTP; + min_tlow = 17; + min_thi = 9; + raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */ + } else if (pca_data->i2c_clock > 1000) { + mode = I2C_PCA_MODE_FAST; + min_tlow = 44; + min_thi = 20; + raise_fall_time = 58; /* Raise 29e-8s, Fall 29e-8s */ + } else { + mode = I2C_PCA_MODE_STD; + min_tlow = 157; + min_thi = 134; + raise_fall_time = 127; /* Raise 29e-8s, Fall 98e-8s */ + } + + /* The minimum clock that respects the thi/tlow = 134/157 is + * 64800 Hz. Below that, we have to fix the tlow to 255 and + * calculate the thi factor. + */ + if (clock < 648) { + tlow = 255; + thi = 1000000 - clock * raise_fall_time; + thi /= (I2C_PCA_OSC_PER * clock) - tlow; + } else { + tlow = (1000000 - clock * raise_fall_time) * min_tlow; + tlow /= I2C_PCA_OSC_PER * clock * (min_thi + min_tlow); + thi = tlow * min_thi / min_tlow; + } + + pca_reset(pca_data); - clock = pca_clock(pca_data); - printk(KERN_INFO "%s: Clock frequency is %dkHz\n", adap->name, - freqs[clock]); + printk(KERN_INFO + "%s: Clock frequency is %dHz\n", adap->name, clock * 100); - pca_set_con(pca_data, I2C_PCA_CON_ENSIO | clock); + pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_IMODE); + pca_outw(pca_data, I2C_PCA_IND, mode); + pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_ISCLL); + pca_outw(pca_data, I2C_PCA_IND, tlow); + pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_ISCLH); + pca_outw(pca_data, I2C_PCA_IND, thi); + + pca_set_con(pca_data, I2C_PCA_CON_ENSIO); + } udelay(500); /* 500 us for oscilator to stabilise */ return 0; @@ -388,7 +540,7 @@ EXPORT_SYMBOL(i2c_pca_add_numbered_bus); MODULE_AUTHOR("Ian Campbell , " "Wolfram Sang "); -MODULE_DESCRIPTION("I2C-Bus PCA9564 algorithm"); +MODULE_DESCRIPTION("I2C-Bus PCA9564/PCA9665 algorithm"); MODULE_LICENSE("GPL"); module_param(i2c_debug, int, 0); diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 7f95905bbb9..68650643d11 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -617,12 +617,12 @@ config I2C_ELEKTOR will be called i2c-elektor. config I2C_PCA_ISA - tristate "PCA9564 on an ISA bus" + tristate "PCA9564/PCA9665 on an ISA bus" depends on ISA select I2C_ALGOPCA default n help - This driver supports ISA boards using the Philips PCA9564 + This driver supports ISA boards using the Philips PCA9564/PCA9665 parallel bus to I2C bus controller. This driver can also be built as a module. If so, the module @@ -634,11 +634,11 @@ config I2C_PCA_ISA time). If unsure, say N. config I2C_PCA_PLATFORM - tristate "PCA9564 as platform device" + tristate "PCA9564/PCA9665 as platform device" select I2C_ALGOPCA default n help - This driver supports a memory mapped Philips PCA9564 + This driver supports a memory mapped Philips PCA9564/PCA9665 parallel bus to I2C bus controller. This driver can also be built as a module. If so, the module diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c index c420a7c0f3e..0cc8017b3f6 100644 --- a/drivers/i2c/busses/i2c-pca-isa.c +++ b/drivers/i2c/busses/i2c-pca-isa.c @@ -41,7 +41,7 @@ static int irq = -1; /* Data sheet recommends 59kHz for 100kHz operation due to variation * in the actual clock rate */ -static int clock = I2C_PCA_CON_59kHz; +static int clock = 59000; static wait_queue_head_t pca_wait; @@ -103,7 +103,7 @@ static struct i2c_algo_pca_data pca_isa_data = { static struct i2c_adapter pca_isa_ops = { .owner = THIS_MODULE, .algo_data = &pca_isa_data, - .name = "PCA9564 ISA Adapter", + .name = "PCA9564/PCA9665 ISA Adapter", .timeout = 100, }; @@ -196,7 +196,7 @@ static void __exit pca_isa_exit(void) } MODULE_AUTHOR("Ian Campbell "); -MODULE_DESCRIPTION("ISA base PCA9564 driver"); +MODULE_DESCRIPTION("ISA base PCA9564/PCA9665 driver"); MODULE_LICENSE("GPL"); module_param(base, ulong, 0); @@ -205,7 +205,13 @@ MODULE_PARM_DESC(base, "I/O base address"); module_param(irq, int, 0); MODULE_PARM_DESC(irq, "IRQ"); module_param(clock, int, 0); -MODULE_PARM_DESC(clock, "Clock rate as described in table 1 of PCA9564 datasheet"); +MODULE_PARM_DESC(clock, "Clock rate in hertz.\n\t\t" + "For PCA9564: 330000,288000,217000,146000," + "88000,59000,44000,36000\n" + "\t\tFor PCA9665:\tStandard: 60300 - 100099\n" + "\t\t\t\tFast: 100100 - 400099\n" + "\t\t\t\tFast+: 400100 - 10000099\n" + "\t\t\t\tTurbo: Up to 1265800"); module_init(pca_isa_init); module_exit(pca_isa_exit); diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index 6bb15ad0a6b..51d179bbddf 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -172,8 +172,9 @@ static int __devinit i2c_pca_pf_probe(struct platform_device *pdev) i2c->adap.nr = pdev->id >= 0 ? pdev->id : 0; i2c->adap.owner = THIS_MODULE; - snprintf(i2c->adap.name, sizeof(i2c->adap.name), "PCA9564 at 0x%08lx", - (unsigned long) res->start); + snprintf(i2c->adap.name, sizeof(i2c->adap.name), + "PCA9564/PCA9665 at 0x%08lx", + (unsigned long) res->start); i2c->adap.algo_data = &i2c->algo_data; i2c->adap.dev.parent = &pdev->dev; i2c->adap.timeout = platform_data->timeout; @@ -246,7 +247,7 @@ e_remap: e_alloc: release_mem_region(res->start, res_len(res)); e_print: - printk(KERN_ERR "Registering PCA9564 FAILED! (%d)\n", ret); + printk(KERN_ERR "Registering PCA9564/PCA9665 FAILED! (%d)\n", ret); return ret; } @@ -290,7 +291,7 @@ static void __exit i2c_pca_pf_exit(void) } MODULE_AUTHOR("Wolfram Sang "); -MODULE_DESCRIPTION("I2C-PCA9564 platform driver"); +MODULE_DESCRIPTION("I2C-PCA9564/PCA9665 platform driver"); MODULE_LICENSE("GPL"); module_init(i2c_pca_pf_init); diff --git a/include/linux/i2c-algo-pca.h b/include/linux/i2c-algo-pca.h index adcb3dc7ac2..1364d62e2fb 100644 --- a/include/linux/i2c-algo-pca.h +++ b/include/linux/i2c-algo-pca.h @@ -1,7 +1,14 @@ #ifndef _LINUX_I2C_ALGO_PCA_H #define _LINUX_I2C_ALGO_PCA_H -/* Clock speeds for the bus */ +/* Chips known to the pca algo */ +#define I2C_PCA_CHIP_9564 0x00 +#define I2C_PCA_CHIP_9665 0x01 + +/* Internal period for PCA9665 oscilator */ +#define I2C_PCA_OSC_PER 3 /* e10-8s */ + +/* Clock speeds for the bus for PCA9564*/ #define I2C_PCA_CON_330kHz 0x00 #define I2C_PCA_CON_288kHz 0x01 #define I2C_PCA_CON_217kHz 0x02 @@ -18,6 +25,26 @@ #define I2C_PCA_ADR 0x02 /* OWN ADR Read/Write */ #define I2C_PCA_CON 0x03 /* CONTROL Read/Write */ +/* PCA9665 registers */ +#define I2C_PCA_INDPTR 0x00 /* INDIRECT Pointer Write Only */ +#define I2C_PCA_IND 0x02 /* INDIRECT Read/Write */ + +/* PCA9665 indirect registers */ +#define I2C_PCA_ICOUNT 0x00 /* Byte Count for buffered mode */ +#define I2C_PCA_IADR 0x01 /* OWN ADR */ +#define I2C_PCA_ISCLL 0x02 /* SCL LOW period */ +#define I2C_PCA_ISCLH 0x03 /* SCL HIGH period */ +#define I2C_PCA_ITO 0x04 /* TIMEOUT */ +#define I2C_PCA_IPRESET 0x05 /* Parallel bus reset */ +#define I2C_PCA_IMODE 0x06 /* I2C Bus mode */ + +/* PCA9665 I2C bus mode */ +#define I2C_PCA_MODE_STD 0x00 /* Standard mode */ +#define I2C_PCA_MODE_FAST 0x01 /* Fast mode */ +#define I2C_PCA_MODE_FASTP 0x02 /* Fast Plus mode */ +#define I2C_PCA_MODE_TURBO 0x03 /* Turbo mode */ + + #define I2C_PCA_CON_AA 0x80 /* Assert Acknowledge */ #define I2C_PCA_CON_ENSIO 0x40 /* Enable */ #define I2C_PCA_CON_STA 0x20 /* Start */ @@ -31,7 +58,9 @@ struct i2c_algo_pca_data { int (*read_byte) (void *data, int reg); int (*wait_for_completion) (void *data); void (*reset_chip) (void *data); - /* i2c_clock values are defined in linux/i2c-algo-pca.h */ + /* For PCA9564, use one of the predefined frequencies: + * 330000, 288000, 217000, 146000, 88000, 59000, 44000, 36000 + * For PCA9665, use the frequency you want here. */ unsigned int i2c_clock; }; -- GitLab From 8e99ada8deaa9033600cd2c7d0a9366b0e99ab68 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 28 Mar 2009 21:34:45 +0100 Subject: [PATCH 4977/4982] i2c-algo-pca: Rework waiting for a free bus Waiting for a free bus now accepts the timeout value in jiffies and does proper checking using time_before. Signed-off-by: Wolfram Sang Signed-off-by: Jean Delvare --- arch/sh/boards/board-sh7785lcr.c | 2 +- drivers/i2c/algos/i2c-algo-pca.c | 17 ++++++++++------- drivers/i2c/busses/i2c-pca-isa.c | 2 +- include/linux/i2c-pca-platform.h | 2 +- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/arch/sh/boards/board-sh7785lcr.c b/arch/sh/boards/board-sh7785lcr.c index 94c0296bc35..6f94f17adc4 100644 --- a/arch/sh/boards/board-sh7785lcr.c +++ b/arch/sh/boards/board-sh7785lcr.c @@ -229,7 +229,7 @@ static struct resource i2c_resources[] = { static struct i2c_pca9564_pf_platform_data i2c_platform_data = { .gpio = 0, .i2c_clock_speed = I2C_PCA_CON_330kHz, - .timeout = 100, + .timeout = HZ, }; static struct platform_device i2c_device = { diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c index a8e51bd1a4f..9e134fad7bd 100644 --- a/drivers/i2c/algos/i2c-algo-pca.c +++ b/drivers/i2c/algos/i2c-algo-pca.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -186,14 +187,16 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, int numbytes = 0; int state; int ret; - int timeout = i2c_adap->timeout; + unsigned long timeout = jiffies + i2c_adap->timeout; - while ((state = pca_status(adap)) != 0xf8 && timeout--) { - msleep(10); - } - if (state != 0xf8) { - dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state); - return -EAGAIN; + while (pca_status(adap) != 0xf8) { + if (time_before(jiffies, timeout)) { + msleep(10); + } else { + dev_dbg(&i2c_adap->dev, "bus is not idle. status is " + "%#04x\n", state); + return -EAGAIN; + } } DEB1("{{{ XFER %d messages\n", num); diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c index 0cc8017b3f6..b9403fdfb6d 100644 --- a/drivers/i2c/busses/i2c-pca-isa.c +++ b/drivers/i2c/busses/i2c-pca-isa.c @@ -104,7 +104,7 @@ static struct i2c_adapter pca_isa_ops = { .owner = THIS_MODULE, .algo_data = &pca_isa_data, .name = "PCA9564/PCA9665 ISA Adapter", - .timeout = 100, + .timeout = HZ, }; static int __devinit pca_isa_match(struct device *dev, unsigned int id) diff --git a/include/linux/i2c-pca-platform.h b/include/linux/i2c-pca-platform.h index 3d191873f2d..aba33759dec 100644 --- a/include/linux/i2c-pca-platform.h +++ b/include/linux/i2c-pca-platform.h @@ -6,7 +6,7 @@ struct i2c_pca9564_pf_platform_data { * not supplied (negative value), but it * cannot exit some error conditions then */ int i2c_clock_speed; /* values are defined in linux/i2c-algo-pca.h */ - int timeout; /* timeout = this value * 10us */ + int timeout; /* timeout in jiffies */ }; #endif /* I2C_PCA9564_PLATFORM_H */ -- GitLab From 2378bc09b91b0702fac7823828a614fd8016a29f Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 28 Mar 2009 21:34:45 +0100 Subject: [PATCH 4978/4982] i2c-algo-pca: Use timeout for checking the state machine We now timeout also if the state machine does not change within the given time. For that, the driver-specific completion-functions are extended to return true or false depending on the timeout. This then gets checked in the algorithm. Signed-off-by: Wolfram Sang Signed-off-by: Jean Delvare --- drivers/i2c/algos/i2c-algo-pca.c | 41 +++++++++++++++------------ drivers/i2c/busses/i2c-pca-isa.c | 18 ++++++++---- drivers/i2c/busses/i2c-pca-platform.c | 20 ++++++------- 3 files changed, 46 insertions(+), 33 deletions(-) diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c index 9e134fad7bd..f68e5f8e23e 100644 --- a/drivers/i2c/algos/i2c-algo-pca.c +++ b/drivers/i2c/algos/i2c-algo-pca.c @@ -60,14 +60,14 @@ static void pca9665_reset(void *pd) * * returns after the start condition has occurred */ -static void pca_start(struct i2c_algo_pca_data *adap) +static int pca_start(struct i2c_algo_pca_data *adap) { int sta = pca_get_con(adap); DEB2("=== START\n"); sta |= I2C_PCA_CON_STA; sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_SI); pca_set_con(adap, sta); - pca_wait(adap); + return pca_wait(adap); } /* @@ -75,14 +75,14 @@ static void pca_start(struct i2c_algo_pca_data *adap) * * return after the repeated start condition has occurred */ -static void pca_repeated_start(struct i2c_algo_pca_data *adap) +static int pca_repeated_start(struct i2c_algo_pca_data *adap) { int sta = pca_get_con(adap); DEB2("=== REPEATED START\n"); sta |= I2C_PCA_CON_STA; sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_SI); pca_set_con(adap, sta); - pca_wait(adap); + return pca_wait(adap); } /* @@ -108,7 +108,7 @@ static void pca_stop(struct i2c_algo_pca_data *adap) * * returns after the address has been sent */ -static void pca_address(struct i2c_algo_pca_data *adap, +static int pca_address(struct i2c_algo_pca_data *adap, struct i2c_msg *msg) { int sta = pca_get_con(adap); @@ -125,7 +125,7 @@ static void pca_address(struct i2c_algo_pca_data *adap, sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI); pca_set_con(adap, sta); - pca_wait(adap); + return pca_wait(adap); } /* @@ -133,7 +133,7 @@ static void pca_address(struct i2c_algo_pca_data *adap, * * Returns after the byte has been transmitted */ -static void pca_tx_byte(struct i2c_algo_pca_data *adap, +static int pca_tx_byte(struct i2c_algo_pca_data *adap, __u8 b) { int sta = pca_get_con(adap); @@ -143,7 +143,7 @@ static void pca_tx_byte(struct i2c_algo_pca_data *adap, sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI); pca_set_con(adap, sta); - pca_wait(adap); + return pca_wait(adap); } /* @@ -163,7 +163,7 @@ static void pca_rx_byte(struct i2c_algo_pca_data *adap, * * Returns after next byte has arrived. */ -static void pca_rx_ack(struct i2c_algo_pca_data *adap, +static int pca_rx_ack(struct i2c_algo_pca_data *adap, int ack) { int sta = pca_get_con(adap); @@ -174,7 +174,7 @@ static void pca_rx_ack(struct i2c_algo_pca_data *adap, sta |= I2C_PCA_CON_AA; pca_set_con(adap, sta); - pca_wait(adap); + return pca_wait(adap); } static int pca_xfer(struct i2c_adapter *i2c_adap, @@ -187,6 +187,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, int numbytes = 0; int state; int ret; + int completed = 1; unsigned long timeout = jiffies + i2c_adap->timeout; while (pca_status(adap) != 0xf8) { @@ -232,18 +233,19 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, switch (state) { case 0xf8: /* On reset or stop the bus is idle */ - pca_start(adap); + completed = pca_start(adap); break; case 0x08: /* A START condition has been transmitted */ case 0x10: /* A repeated start condition has been transmitted */ - pca_address(adap, msg); + completed = pca_address(adap, msg); break; case 0x18: /* SLA+W has been transmitted; ACK has been received */ case 0x28: /* Data byte in I2CDAT has been transmitted; ACK has been received */ if (numbytes < msg->len) { - pca_tx_byte(adap, msg->buf[numbytes]); + completed = pca_tx_byte(adap, + msg->buf[numbytes]); numbytes++; break; } @@ -251,7 +253,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, if (curmsg == num) pca_stop(adap); else - pca_repeated_start(adap); + completed = pca_repeated_start(adap); break; case 0x20: /* SLA+W has been transmitted; NOT ACK has been received */ @@ -260,21 +262,22 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, goto out; case 0x40: /* SLA+R has been transmitted; ACK has been received */ - pca_rx_ack(adap, msg->len > 1); + completed = pca_rx_ack(adap, msg->len > 1); break; case 0x50: /* Data bytes has been received; ACK has been returned */ if (numbytes < msg->len) { pca_rx_byte(adap, &msg->buf[numbytes], 1); numbytes++; - pca_rx_ack(adap, numbytes < msg->len - 1); + completed = pca_rx_ack(adap, + numbytes < msg->len - 1); break; } curmsg++; numbytes = 0; if (curmsg == num) pca_stop(adap); else - pca_repeated_start(adap); + completed = pca_repeated_start(adap); break; case 0x48: /* SLA+R has been transmitted; NOT ACK has been received */ @@ -297,7 +300,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, if (curmsg == num) pca_stop(adap); else - pca_repeated_start(adap); + completed = pca_repeated_start(adap); } else { DEB2("NOT ACK sent after data byte received. " "Not final byte. numbytes %d. len %d\n", @@ -323,6 +326,8 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, break; } + if (!completed) + goto out; } ret = curmsg; diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c index b9403fdfb6d..0ed68e2ccd2 100644 --- a/drivers/i2c/busses/i2c-pca-isa.c +++ b/drivers/i2c/busses/i2c-pca-isa.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,7 @@ static int irq = -1; * in the actual clock rate */ static int clock = 59000; +static struct i2c_adapter pca_isa_ops; static wait_queue_head_t pca_wait; static void pca_isa_writebyte(void *pd, int reg, int val) @@ -69,16 +71,22 @@ static int pca_isa_readbyte(void *pd, int reg) static int pca_isa_waitforcompletion(void *pd) { - int ret = 0; + long ret = ~0; + unsigned long timeout; if (irq > -1) { - ret = wait_event_interruptible(pca_wait, - pca_isa_readbyte(pd, I2C_PCA_CON) & I2C_PCA_CON_SI); + ret = wait_event_interruptible_timeout(pca_wait, + pca_isa_readbyte(pd, I2C_PCA_CON) + & I2C_PCA_CON_SI, pca_isa_ops.timeout); } else { - while ((pca_isa_readbyte(pd, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0) + /* Do polling */ + timeout = jiffies + pca_isa_ops.timeout; + while (((pca_isa_readbyte(pd, I2C_PCA_CON) + & I2C_PCA_CON_SI) == 0) + && (ret = time_before(jiffies, timeout))) udelay(100); } - return ret; + return ret > 0; } static void pca_isa_resetchip(void *pd) diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index 51d179bbddf..df5e593a1d7 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -81,24 +82,23 @@ static void i2c_pca_pf_writebyte32(void *pd, int reg, int val) static int i2c_pca_pf_waitforcompletion(void *pd) { struct i2c_pca_pf_data *i2c = pd; - int ret = 0; + long ret = ~0; + unsigned long timeout; if (i2c->irq) { - ret = wait_event_interruptible(i2c->wait, + ret = wait_event_interruptible_timeout(i2c->wait, i2c->algo_data.read_byte(i2c, I2C_PCA_CON) - & I2C_PCA_CON_SI); + & I2C_PCA_CON_SI, i2c->adap.timeout); } else { - /* - * Do polling... - * XXX: Could get stuck in extreme cases! - * Maybe add timeout, but using irqs is preferred anyhow. - */ - while ((i2c->algo_data.read_byte(i2c, I2C_PCA_CON) + /* Do polling */ + timeout = jiffies + i2c->adap.timeout; + while (((i2c->algo_data.read_byte(i2c, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0) + && (ret = time_before(jiffies, timeout))) udelay(100); } - return ret; + return ret > 0; } static void i2c_pca_pf_dummyreset(void *pd) -- GitLab From 6b110d13aacc9c4ef5f01af12a5e2b7f1d23f106 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 28 Mar 2009 21:34:45 +0100 Subject: [PATCH 4979/4982] i2c-pca-platform: Use defaults if no platform_data given Signed-off-by: Wolfram Sang Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-pca-platform.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index df5e593a1d7..7b23891b7d5 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -177,10 +177,20 @@ static int __devinit i2c_pca_pf_probe(struct platform_device *pdev) (unsigned long) res->start); i2c->adap.algo_data = &i2c->algo_data; i2c->adap.dev.parent = &pdev->dev; - i2c->adap.timeout = platform_data->timeout; - i2c->algo_data.i2c_clock = platform_data->i2c_clock_speed; + if (platform_data) { + i2c->adap.timeout = platform_data->timeout; + i2c->algo_data.i2c_clock = platform_data->i2c_clock_speed; + i2c->gpio = platform_data->gpio; + } else { + i2c->adap.timeout = HZ; + i2c->algo_data.i2c_clock = 59000; + i2c->gpio = -1; + } + i2c->algo_data.data = i2c; + i2c->algo_data.wait_for_completion = i2c_pca_pf_waitforcompletion; + i2c->algo_data.reset_chip = i2c_pca_pf_dummyreset; switch (res->flags & IORESOURCE_MEM_TYPE_MASK) { case IORESOURCE_MEM_32BIT: @@ -198,11 +208,6 @@ static int __devinit i2c_pca_pf_probe(struct platform_device *pdev) break; } - i2c->algo_data.wait_for_completion = i2c_pca_pf_waitforcompletion; - - i2c->gpio = platform_data->gpio; - i2c->algo_data.reset_chip = i2c_pca_pf_dummyreset; - /* Use gpio_is_valid() when in mainline */ if (i2c->gpio > -1) { ret = gpio_request(i2c->gpio, i2c->adap.name); -- GitLab From 87e1960e93fe792c4f4344a6f3a970f9573c76aa Mon Sep 17 00:00:00 2001 From: Shane Huang Date: Sat, 28 Mar 2009 21:34:46 +0100 Subject: [PATCH 4980/4982] i2c-piix4: Add support to SB800 SMBus changes Add support for the AMD SB800 Family series of products. Major changes include the changes to addressing the SMBus registers at different location from the locations in the previous compatible parts from AMD such as SB400/SB600/SB700. For SB800, the main features and register definitions of SMBus and other interfaces are still compatible with the previous products with the only change being in how to access the internal registers for these blocks. Signed-off-by: Shane Huang Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-piix4.c | 73 +++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 761f9dd5362..63d5e597804 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -226,6 +226,70 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev, return 0; } +static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev, + const struct pci_device_id *id) +{ + unsigned short smba_idx = 0xcd6; + u8 smba_en_lo, smba_en_hi, i2ccfg, i2ccfg_offset = 0x10, smb_en = 0x2c; + + /* SB800 SMBus does not support forcing address */ + if (force || force_addr) { + dev_err(&PIIX4_dev->dev, "SB800 SMBus does not support " + "forcing address!\n"); + return -EINVAL; + } + + /* Determine the address of the SMBus areas */ + if (!request_region(smba_idx, 2, "smba_idx")) { + dev_err(&PIIX4_dev->dev, "SMBus base address index region " + "0x%x already in use!\n", smba_idx); + return -EBUSY; + } + outb_p(smb_en, smba_idx); + smba_en_lo = inb_p(smba_idx + 1); + outb_p(smb_en + 1, smba_idx); + smba_en_hi = inb_p(smba_idx + 1); + release_region(smba_idx, 2); + + if ((smba_en_lo & 1) == 0) { + dev_err(&PIIX4_dev->dev, + "Host SMBus controller not enabled!\n"); + return -ENODEV; + } + + piix4_smba = ((smba_en_hi << 8) | smba_en_lo) & 0xffe0; + if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) + return -EBUSY; + + if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) { + dev_err(&PIIX4_dev->dev, "SMBus region 0x%x already in use!\n", + piix4_smba); + return -EBUSY; + } + + /* Request the SMBus I2C bus config region */ + if (!request_region(piix4_smba + i2ccfg_offset, 1, "i2ccfg")) { + dev_err(&PIIX4_dev->dev, "SMBus I2C bus config region " + "0x%x already in use!\n", piix4_smba + i2ccfg_offset); + release_region(piix4_smba, SMBIOSIZE); + piix4_smba = 0; + return -EBUSY; + } + i2ccfg = inb_p(piix4_smba + i2ccfg_offset); + release_region(piix4_smba + i2ccfg_offset, 1); + + if (i2ccfg & 1) + dev_dbg(&PIIX4_dev->dev, "Using IRQ for SMBus.\n"); + else + dev_dbg(&PIIX4_dev->dev, "Using SMI# for SMBus.\n"); + + dev_info(&PIIX4_dev->dev, + "SMBus Host Controller at 0x%x, revision %d\n", + piix4_smba, i2ccfg >> 4); + + return 0; +} + static int piix4_transaction(void) { int temp; @@ -433,7 +497,14 @@ static int __devinit piix4_probe(struct pci_dev *dev, { int retval; - retval = piix4_setup(dev, id); + if ((dev->vendor == PCI_VENDOR_ID_ATI) && + (dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS) && + (dev->revision >= 0x40)) + /* base address location etc changed in SB800 */ + retval = piix4_setup_sb800(dev, id); + else + retval = piix4_setup(dev, id); + if (retval) return retval; -- GitLab From 506a8b6c27cb08998dc13069fbdf6eb7ec748b99 Mon Sep 17 00:00:00 2001 From: Flavio Leitner Date: Sat, 28 Mar 2009 21:34:46 +0100 Subject: [PATCH 4981/4982] i2c-piix4: Add support for the Broadcom HT1100 chipset Add support for the Broadcom HT1100 LD chipset (SMBus function.) Signed-off-by: Flavio Leitner Signed-off-by: Jean Delvare --- Documentation/i2c/busses/i2c-piix4 | 2 +- drivers/i2c/busses/Kconfig | 1 + drivers/i2c/busses/i2c-piix4.c | 4 +++- include/linux/pci_ids.h | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Documentation/i2c/busses/i2c-piix4 b/Documentation/i2c/busses/i2c-piix4 index ef1efa79b1d..f889481762b 100644 --- a/Documentation/i2c/busses/i2c-piix4 +++ b/Documentation/i2c/busses/i2c-piix4 @@ -4,7 +4,7 @@ Supported adapters: * Intel 82371AB PIIX4 and PIIX4E * Intel 82443MX (440MX) Datasheet: Publicly available at the Intel website - * ServerWorks OSB4, CSB5, CSB6 and HT-1000 southbridges + * ServerWorks OSB4, CSB5, CSB6, HT-1000 and HT-1100 southbridges Datasheet: Only available via NDA from ServerWorks * ATI IXP200, IXP300, IXP400, SB600, SB700 and SB800 southbridges Datasheet: Not publicly available diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 68650643d11..da809ad0996 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -132,6 +132,7 @@ config I2C_PIIX4 Serverworks CSB5 Serverworks CSB6 Serverworks HT-1000 + Serverworks HT-1100 SMSC Victory66 This driver can also be built as a module. If so, the module diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 63d5e597804..0249a7d762b 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -20,7 +20,7 @@ /* Supports: Intel PIIX4, 440MX - Serverworks OSB4, CSB5, CSB6, HT-1000 + Serverworks OSB4, CSB5, CSB6, HT-1000, HT-1100 ATI IXP200, IXP300, IXP400, SB600, SB700, SB800 SMSC Victory66 @@ -487,6 +487,8 @@ static struct pci_device_id piix4_ids[] = { PCI_DEVICE_ID_SERVERWORKS_CSB6) }, { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000SB) }, + { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, + PCI_DEVICE_ID_SERVERWORKS_HT1100LD) }, { 0, } }; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 5109fecde28..2c9e8080da5 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1479,6 +1479,7 @@ #define PCI_DEVICE_ID_SERVERWORKS_HT1000IDE 0x0214 #define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2 0x0217 #define PCI_DEVICE_ID_SERVERWORKS_CSB6LPC 0x0227 +#define PCI_DEVICE_ID_SERVERWORKS_HT1100LD 0x0408 #define PCI_VENDOR_ID_SBE 0x1176 #define PCI_DEVICE_ID_SBE_WANXL100 0x0301 -- GitLab From 09b8ce0a691d8e76f14a16ac6cbfde899f6c68e3 Mon Sep 17 00:00:00 2001 From: Zhenwen Xu Date: Sat, 28 Mar 2009 21:34:46 +0100 Subject: [PATCH 4982/4982] i2c-core: Some style cleanups Some lines over 80. The printk(KERN_ERR ... ) should be dev_err. And some blankspace should be deleted. Signed-off-by: Zhenwen Xu Signed-off-by: Jean Delvare --- drivers/i2c/i2c-core.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index e361033815d..b6f3a0de6ca 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -152,7 +152,7 @@ static void i2c_device_shutdown(struct device *dev) driver->shutdown(to_i2c_client(dev)); } -static int i2c_device_suspend(struct device * dev, pm_message_t mesg) +static int i2c_device_suspend(struct device *dev, pm_message_t mesg) { struct i2c_driver *driver; @@ -164,7 +164,7 @@ static int i2c_device_suspend(struct device * dev, pm_message_t mesg) return driver->suspend(to_i2c_client(dev), mesg); } -static int i2c_device_resume(struct device * dev) +static int i2c_device_resume(struct device *dev) { struct i2c_driver *driver; @@ -187,13 +187,15 @@ static void i2c_client_dev_release(struct device *dev) kfree(to_i2c_client(dev)); } -static ssize_t show_client_name(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t +show_client_name(struct device *dev, struct device_attribute *attr, char *buf) { struct i2c_client *client = to_i2c_client(dev); return sprintf(buf, "%s\n", client->name); } -static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t +show_modalias(struct device *dev, struct device_attribute *attr, char *buf) { struct i2c_client *client = to_i2c_client(dev); return sprintf(buf, "%s%s\n", I2C_MODULE_PREFIX, client->name); @@ -365,8 +367,7 @@ static struct i2c_driver dummy_driver = { * This returns the new i2c client, which should be saved for later use with * i2c_unregister_device(); or NULL to indicate an error. */ -struct i2c_client * -i2c_new_dummy(struct i2c_adapter *adapter, u16 address) +struct i2c_client *i2c_new_dummy(struct i2c_adapter *adapter, u16 address) { struct i2c_board_info info = { I2C_BOARD_INFO("dummy", address), @@ -413,8 +414,8 @@ static void i2c_scan_static_board_info(struct i2c_adapter *adapter) if (devinfo->busnum == adapter->nr && !i2c_new_device(adapter, &devinfo->board_info)) - printk(KERN_ERR "i2c-core: can't create i2c%d-%04x\n", - i2c_adapter_id(adapter), + dev_err(&adapter->dev, + "Can't create device at 0x%02x\n", devinfo->board_info.addr); } mutex_unlock(&__i2c_board_lock); @@ -1020,7 +1021,7 @@ module_exit(i2c_exit); * Note that there is no requirement that each message be sent to * the same slave address, although that is the most common model. */ -int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num) +int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { int ret; @@ -1527,8 +1528,7 @@ EXPORT_SYMBOL(i2c_put_adapter); /* The SMBus parts */ #define POLY (0x1070U << 3) -static u8 -crc8(u16 data) +static u8 crc8(u16 data) { int i; @@ -1992,9 +1992,9 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, * This executes an SMBus protocol operation, and returns a negative * errno code else zero on success. */ -s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags, +s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, char read_write, u8 command, int protocol, - union i2c_smbus_data * data) + union i2c_smbus_data *data) { s32 res; -- GitLab